From 47b09705ad16cffb6dc16bdb9e078b68844bdbb2 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Fri, 5 Oct 2007 16:34:34 +0000 Subject: [PATCH] retag kfw-3.2.2-beta1 git-svn-id: svn://anonsvn.mit.edu/krb5/tags/kfw-3_2_2-beta1@20105 dc483132-0cff-0310-8789-dd5450dbe970 --- krb5-1-6/README | 928 ++ krb5-1-6/doc/.cvsignore | 20 + krb5-1-6/doc/Makefile | 183 + krb5-1-6/doc/admin.texinfo | 5414 +++++++ krb5-1-6/doc/api/.cvsignore | 10 + krb5-1-6/doc/api/Makefile | 40 + krb5-1-6/doc/api/ccache.tex | 239 + krb5-1-6/doc/api/errors.tex | 310 + krb5-1-6/doc/api/fancyheadings.sty | 233 + krb5-1-6/doc/api/fixunder.sty | 48 + krb5-1-6/doc/api/free.tex | 266 + krb5-1-6/doc/api/functions.sty | 70 + krb5-1-6/doc/api/intro.tex | 299 + krb5-1-6/doc/api/keytab.tex | 221 + krb5-1-6/doc/api/krb5.ist | 26 + krb5-1-6/doc/api/krb5.tex | 1827 +++ krb5-1-6/doc/api/krb5idx.sty | 10 + krb5-1-6/doc/api/libdes.tex | 38 + krb5-1-6/doc/api/libos.tex | 486 + krb5-1-6/doc/api/library.tex | 114 + krb5-1-6/doc/api/rcache.tex | 207 + krb5-1-6/doc/api/tables.tex | 79 + krb5-1-6/doc/bug-report.texinfo | 10 + krb5-1-6/doc/build.texinfo | 1052 ++ krb5-1-6/doc/coding-style | 566 + krb5-1-6/doc/copyright.texinfo | 525 + krb5-1-6/doc/definitions.texinfo | 193 + krb5-1-6/doc/dnssrv.texinfo | 97 + krb5-1-6/doc/dnstxt.texinfo | 38 + krb5-1-6/doc/document-list.texinfo | 24 + krb5-1-6/doc/glossary.texinfo | 64 + krb5-1-6/doc/implement/.cvsignore | 7 + krb5-1-6/doc/implement/Makefile | 38 + krb5-1-6/doc/implement/ccache-i.tex | 224 + krb5-1-6/doc/implement/cksum-i.tex | 31 + krb5-1-6/doc/implement/crc-32-i.tex | 20 + krb5-1-6/doc/implement/encrypt-i.tex | 164 + krb5-1-6/doc/implement/fancyheadings.sty | 233 + krb5-1-6/doc/implement/fixunder.sty | 48 + krb5-1-6/doc/implement/functions.sty | 70 + krb5-1-6/doc/implement/implement.tex | 94 + krb5-1-6/doc/implement/kdb-i.tex | 242 + krb5-1-6/doc/implement/keytab-i.tex | 204 + krb5-1-6/doc/implement/libos-i.tex | 34 + krb5-1-6/doc/implement/rcache-i.tex | 142 + krb5-1-6/doc/implementor.texinfo | 1192 ++ krb5-1-6/doc/install-old.texi | 2239 +++ krb5-1-6/doc/install.texinfo | 1456 ++ krb5-1-6/doc/kadm5/adb-unit-test.tex | 134 + krb5-1-6/doc/kadm5/api-funcspec.tex | 2015 +++ krb5-1-6/doc/kadm5/api-server-design.tex | 1042 ++ krb5-1-6/doc/kadm5/api-unit-test.tex | 2679 ++++ krb5-1-6/doc/kadm5/fullpage.sty | 9 + krb5-1-6/doc/kadm5/rcsid.sty | 5 + krb5-1-6/doc/kadm5acl.texinfo | 113 + krb5-1-6/doc/kadmin/README | 46 + .../draft-ietf-cat-kerb-chg-password-02.txt | 311 + krb5-1-6/doc/kadmin/kadmin.protocol | 382 + krb5-1-6/doc/kadmin/kpasswd.protocol | 303 + krb5-1-6/doc/kdcconf.texinfo | 24 + krb5-1-6/doc/krb4-xrealm.txt | 143 + krb5-1-6/doc/krb425.texinfo | 322 + .../draft-jaganathan-rc4-hmac-03.txt | 1013 ++ krb5-1-6/doc/krb5-protocol/krb5.constants | 156 + krb5-1-6/doc/krb5-protocol/rfc3961.txt | 2803 ++++ krb5-1-6/doc/krb5-protocol/rfc3962.txt | 899 ++ krb5-1-6/doc/krb5-protocol/rfc4120.txt | 7731 ++++++++++ krb5-1-6/doc/krb5-protocol/rfc4121.txt | 1123 ++ krb5-1-6/doc/krb5conf.texinfo | 83 + krb5-1-6/doc/man2html | 608 + krb5-1-6/doc/man2html.M | 761 + krb5-1-6/doc/man2ps | 60 + krb5-1-6/doc/man2ps.M | 50 + krb5-1-6/doc/old-V4-docs/README | 4 + krb5-1-6/doc/old-V4-docs/installation.PS | 2338 +++ krb5-1-6/doc/old-V4-docs/installation.mss | 681 + krb5-1-6/doc/old-V4-docs/operation.PS | 2669 ++++ krb5-1-6/doc/old-V4-docs/operation.mss | 799 + krb5-1-6/doc/procedures.txt | 159 + krb5-1-6/doc/rpc/design.tex | 1037 ++ krb5-1-6/doc/salts.texinfo | 19 + krb5-1-6/doc/send-pr.texinfo | 144 + krb5-1-6/doc/support-enc.texinfo | 33 + krb5-1-6/doc/texinfo-suppl.tex | 7 + krb5-1-6/doc/texinfo.tex | 7226 +++++++++ krb5-1-6/doc/thread-safe.txt | 257 + krb5-1-6/doc/threads.txt | 101 + krb5-1-6/doc/user-guide.texinfo | 1705 +++ krb5-1-6/src/BADSYMS | 282 + krb5-1-6/src/Makefile.in | 600 + krb5-1-6/src/aclocal.m4 | 1825 +++ krb5-1-6/src/appl/Makefile.in | 7 + krb5-1-6/src/appl/bsd/Makefile.in | 182 + krb5-1-6/src/appl/bsd/compat_recv.c | 581 + krb5-1-6/src/appl/bsd/configure.in | 195 + krb5-1-6/src/appl/bsd/defines.h | 100 + krb5-1-6/src/appl/bsd/forward.c | 77 + krb5-1-6/src/appl/bsd/getdtablesize.c | 19 + krb5-1-6/src/appl/bsd/kcmd.c | 1369 ++ krb5-1-6/src/appl/bsd/klogind.M | 194 + krb5-1-6/src/appl/bsd/krcp.c | 1455 ++ krb5-1-6/src/appl/bsd/krlogin.c | 1857 +++ krb5-1-6/src/appl/bsd/krlogind.c | 1575 ++ krb5-1-6/src/appl/bsd/krsh.c | 635 + krb5-1-6/src/appl/bsd/krshd.c | 2084 +++ krb5-1-6/src/appl/bsd/kshd.M | 211 + krb5-1-6/src/appl/bsd/login.M | 97 + krb5-1-6/src/appl/bsd/login.c | 2505 ++++ krb5-1-6/src/appl/bsd/loginpaths.h | 113 + krb5-1-6/src/appl/bsd/rcp.M | 160 + krb5-1-6/src/appl/bsd/rlogin.M | 160 + krb5-1-6/src/appl/bsd/rpaths.h | 31 + krb5-1-6/src/appl/bsd/rsh.M | 173 + krb5-1-6/src/appl/bsd/setenv.c | 166 + krb5-1-6/src/appl/bsd/v4rcp.M | 52 + krb5-1-6/src/appl/bsd/v4rcp.c | 1114 ++ krb5-1-6/src/appl/configure.in | 21 + krb5-1-6/src/appl/gss-sample/Makefile.in | 65 + krb5-1-6/src/appl/gss-sample/README | 163 + krb5-1-6/src/appl/gss-sample/gss-client.c | 808 + krb5-1-6/src/appl/gss-sample/gss-misc.c | 425 + krb5-1-6/src/appl/gss-sample/gss-misc.h | 60 + krb5-1-6/src/appl/gss-sample/gss-server.c | 793 + krb5-1-6/src/appl/gssftp/Makefile.in | 6 + krb5-1-6/src/appl/gssftp/README.gssftp | 45 + krb5-1-6/src/appl/gssftp/arpa/ftp.h | 128 + krb5-1-6/src/appl/gssftp/arpa/telnet.h | 310 + krb5-1-6/src/appl/gssftp/configure.in | 68 + krb5-1-6/src/appl/gssftp/ftp/Makefile.in | 104 + krb5-1-6/src/appl/gssftp/ftp/cmds.c | 2529 ++++ krb5-1-6/src/appl/gssftp/ftp/cmdtab.c | 209 + krb5-1-6/src/appl/gssftp/ftp/domacro.c | 162 + krb5-1-6/src/appl/gssftp/ftp/ftp.M | 1131 ++ krb5-1-6/src/appl/gssftp/ftp/ftp.c | 2368 +++ krb5-1-6/src/appl/gssftp/ftp/ftp_var.h | 284 + krb5-1-6/src/appl/gssftp/ftp/getpass.c | 154 + krb5-1-6/src/appl/gssftp/ftp/glob.c | 784 + krb5-1-6/src/appl/gssftp/ftp/main.c | 633 + krb5-1-6/src/appl/gssftp/ftp/pathnames.h | 37 + krb5-1-6/src/appl/gssftp/ftp/pclose.c | 128 + krb5-1-6/src/appl/gssftp/ftp/radix.c | 166 + krb5-1-6/src/appl/gssftp/ftp/ruserpass.c | 296 + krb5-1-6/src/appl/gssftp/ftp/secure.c | 481 + krb5-1-6/src/appl/gssftp/ftp/secure.h | 15 + krb5-1-6/src/appl/gssftp/ftpd/CHANGES | 31 + krb5-1-6/src/appl/gssftp/ftpd/Makefile.in | 113 + krb5-1-6/src/appl/gssftp/ftpd/ftpcmd.y | 1557 ++ krb5-1-6/src/appl/gssftp/ftpd/ftpd.M | 513 + krb5-1-6/src/appl/gssftp/ftpd/ftpd.c | 3007 ++++ krb5-1-6/src/appl/gssftp/ftpd/ftpd_var.h | 97 + krb5-1-6/src/appl/gssftp/ftpd/logwtmp.c | 90 + krb5-1-6/src/appl/gssftp/ftpd/pathnames.h | 36 + krb5-1-6/src/appl/gssftp/ftpd/popen.c | 194 + krb5-1-6/src/appl/gssftp/ftpd/secure.h | 19 + krb5-1-6/src/appl/gssftp/ftpd/vers.c | 38 + krb5-1-6/src/appl/libpty/Makefile.in | 157 + krb5-1-6/src/appl/libpty/README | 108 + krb5-1-6/src/appl/libpty/cleanup.c | 112 + krb5-1-6/src/appl/libpty/configure.in | 263 + krb5-1-6/src/appl/libpty/dump-utmp.c | 281 + krb5-1-6/src/appl/libpty/getpty.c | 150 + krb5-1-6/src/appl/libpty/init.c | 33 + krb5-1-6/src/appl/libpty/init_slave.c | 100 + krb5-1-6/src/appl/libpty/libpty.h | 54 + krb5-1-6/src/appl/libpty/logwtmp.c | 112 + krb5-1-6/src/appl/libpty/open_ctty.c | 67 + krb5-1-6/src/appl/libpty/open_slave.c | 101 + krb5-1-6/src/appl/libpty/pty-int.h | 138 + krb5-1-6/src/appl/libpty/pty_err.et | 50 + krb5-1-6/src/appl/libpty/pty_paranoia.c | 650 + krb5-1-6/src/appl/libpty/sane_hostname.c | 116 + krb5-1-6/src/appl/libpty/update_utmp.c | 723 + krb5-1-6/src/appl/libpty/update_wtmp.c | 127 + krb5-1-6/src/appl/libpty/vhangup.c | 50 + krb5-1-6/src/appl/libpty/void_assoc.c | 49 + krb5-1-6/src/appl/sample/Makefile.in | 5 + krb5-1-6/src/appl/sample/sample.h | 36 + krb5-1-6/src/appl/sample/sclient/Makefile.in | 19 + krb5-1-6/src/appl/sample/sclient/sclient.M | 38 + krb5-1-6/src/appl/sample/sclient/sclient.c | 255 + krb5-1-6/src/appl/sample/sserver/Makefile.in | 19 + krb5-1-6/src/appl/sample/sserver/sserver.M | 130 + krb5-1-6/src/appl/sample/sserver/sserver.c | 242 + krb5-1-6/src/appl/simple/Makefile.in | 5 + krb5-1-6/src/appl/simple/client/Makefile.in | 19 + krb5-1-6/src/appl/simple/client/sim_client.c | 332 + krb5-1-6/src/appl/simple/server/Makefile.in | 20 + krb5-1-6/src/appl/simple/server/sim_server.c | 279 + krb5-1-6/src/appl/simple/simple.h | 32 + krb5-1-6/src/appl/telnet/Config.generic | 830 ++ krb5-1-6/src/appl/telnet/Makefile.in | 5 + krb5-1-6/src/appl/telnet/README | 679 + krb5-1-6/src/appl/telnet/arpa/telnet.h | 327 + krb5-1-6/src/appl/telnet/configure.in | 176 + krb5-1-6/src/appl/telnet/kern.diff | 308 + .../src/appl/telnet/libtelnet/Makefile.in | 141 + .../src/appl/telnet/libtelnet/auth-proto.h | 107 + krb5-1-6/src/appl/telnet/libtelnet/auth.c | 669 + krb5-1-6/src/appl/telnet/libtelnet/auth.h | 85 + .../src/appl/telnet/libtelnet/enc-proto.h | 144 + krb5-1-6/src/appl/telnet/libtelnet/enc_des.c | 780 + krb5-1-6/src/appl/telnet/libtelnet/encrypt.c | 1014 ++ krb5-1-6/src/appl/telnet/libtelnet/encrypt.h | 103 + krb5-1-6/src/appl/telnet/libtelnet/forward.c | 78 + krb5-1-6/src/appl/telnet/libtelnet/genget.c | 102 + krb5-1-6/src/appl/telnet/libtelnet/getent.c | 71 + krb5-1-6/src/appl/telnet/libtelnet/getopt.c | 126 + krb5-1-6/src/appl/telnet/libtelnet/gettytab.c | 307 + krb5-1-6/src/appl/telnet/libtelnet/gettytab.h | 120 + krb5-1-6/src/appl/telnet/libtelnet/herror.c | 68 + krb5-1-6/src/appl/telnet/libtelnet/kerberos.c | 744 + .../src/appl/telnet/libtelnet/kerberos5.c | 903 ++ .../src/appl/telnet/libtelnet/key-proto.h | 66 + krb5-1-6/src/appl/telnet/libtelnet/krb5forw.h | 4 + krb5-1-6/src/appl/telnet/libtelnet/mem.c | 190 + .../src/appl/telnet/libtelnet/misc-proto.h | 88 + krb5-1-6/src/appl/telnet/libtelnet/misc.c | 96 + krb5-1-6/src/appl/telnet/libtelnet/misc.h | 46 + krb5-1-6/src/appl/telnet/libtelnet/parsetos.c | 42 + krb5-1-6/src/appl/telnet/libtelnet/setenv.c | 172 + krb5-1-6/src/appl/telnet/libtelnet/setsid.c | 49 + krb5-1-6/src/appl/telnet/libtelnet/spx.c | 594 + .../src/appl/telnet/libtelnet/strcasecmp.c | 121 + krb5-1-6/src/appl/telnet/libtelnet/strchr.c | 47 + krb5-1-6/src/appl/telnet/libtelnet/strdup.c | 62 + krb5-1-6/src/appl/telnet/libtelnet/strerror.c | 69 + krb5-1-6/src/appl/telnet/libtelnet/strftime.c | 307 + krb5-1-6/src/appl/telnet/libtelnet/strrchr.c | 47 + krb5-1-6/src/appl/telnet/stty.diff | 72 + krb5-1-6/src/appl/telnet/telnet.state | 80 + krb5-1-6/src/appl/telnet/telnet/Makefile.in | 112 + krb5-1-6/src/appl/telnet/telnet/authenc.c | 115 + krb5-1-6/src/appl/telnet/telnet/commands.c | 3191 ++++ krb5-1-6/src/appl/telnet/telnet/defines.h | 61 + krb5-1-6/src/appl/telnet/telnet/externs.h | 530 + krb5-1-6/src/appl/telnet/telnet/fdset.h | 49 + krb5-1-6/src/appl/telnet/telnet/general.h | 45 + krb5-1-6/src/appl/telnet/telnet/main.c | 350 + krb5-1-6/src/appl/telnet/telnet/network.c | 179 + krb5-1-6/src/appl/telnet/telnet/ring.c | 367 + krb5-1-6/src/appl/telnet/telnet/ring.h | 98 + krb5-1-6/src/appl/telnet/telnet/sys_bsd.c | 1208 ++ krb5-1-6/src/appl/telnet/telnet/telnet.0.ps | 1008 ++ krb5-1-6/src/appl/telnet/telnet/telnet.0.txt | 718 + krb5-1-6/src/appl/telnet/telnet/telnet.1 | 1339 ++ krb5-1-6/src/appl/telnet/telnet/telnet.c | 2758 ++++ krb5-1-6/src/appl/telnet/telnet/terminal.c | 241 + krb5-1-6/src/appl/telnet/telnet/tmac.doc | 4102 +++++ krb5-1-6/src/appl/telnet/telnet/tn3270.c | 410 + krb5-1-6/src/appl/telnet/telnet/types.h | 52 + krb5-1-6/src/appl/telnet/telnet/utilities.c | 949 ++ krb5-1-6/src/appl/telnet/telnetd/ISSUES | 7 + krb5-1-6/src/appl/telnet/telnetd/Makefile.in | 148 + krb5-1-6/src/appl/telnet/telnetd/authenc.c | 86 + krb5-1-6/src/appl/telnet/telnetd/defs.h | 322 + krb5-1-6/src/appl/telnet/telnetd/ext.h | 228 + krb5-1-6/src/appl/telnet/telnetd/global.c | 46 + krb5-1-6/src/appl/telnet/telnetd/pathnames.h | 55 + krb5-1-6/src/appl/telnet/telnetd/slc.c | 491 + krb5-1-6/src/appl/telnet/telnetd/state.c | 1676 +++ krb5-1-6/src/appl/telnet/telnetd/sys_term.c | 1498 ++ .../src/appl/telnet/telnetd/telnetd-ktd.c | 1462 ++ krb5-1-6/src/appl/telnet/telnetd/telnetd.0.ps | 555 + .../src/appl/telnet/telnetd/telnetd.0.txt | 322 + krb5-1-6/src/appl/telnet/telnetd/telnetd.8 | 631 + krb5-1-6/src/appl/telnet/telnetd/telnetd.c | 1712 +++ krb5-1-6/src/appl/telnet/telnetd/telnetd.h | 48 + krb5-1-6/src/appl/telnet/telnetd/termio-tn.c | 33 + krb5-1-6/src/appl/telnet/telnetd/termios-tn.c | 35 + krb5-1-6/src/appl/telnet/telnetd/termstat.c | 652 + krb5-1-6/src/appl/telnet/telnetd/utility.c | 1300 ++ krb5-1-6/src/appl/user_user/Makefile.in | 25 + krb5-1-6/src/appl/user_user/client.c | 278 + krb5-1-6/src/appl/user_user/server.c | 231 + krb5-1-6/src/clients/Makefile.in | 55 + krb5-1-6/src/clients/kcpytkt/Makefile.in | 39 + krb5-1-6/src/clients/kcpytkt/kcpytkt.M | 37 + krb5-1-6/src/clients/kcpytkt/kcpytkt.c | 182 + krb5-1-6/src/clients/kdeltkt/Makefile.in | 39 + krb5-1-6/src/clients/kdeltkt/kdeltkt.M | 37 + krb5-1-6/src/clients/kdeltkt/kdeltkt.c | 174 + krb5-1-6/src/clients/kdestroy/Makefile.in | 51 + krb5-1-6/src/clients/kdestroy/kdestroy.M | 104 + krb5-1-6/src/clients/kdestroy/kdestroy.c | 228 + krb5-1-6/src/clients/kinit/Makefile.in | 54 + krb5-1-6/src/clients/kinit/kinit.M | 225 + krb5-1-6/src/clients/kinit/kinit.c | 1213 ++ krb5-1-6/src/clients/klist/Makefile.in | 54 + krb5-1-6/src/clients/klist/klist.M | 154 + krb5-1-6/src/clients/klist/klist.c | 837 ++ krb5-1-6/src/clients/kpasswd/Makefile.in | 54 + krb5-1-6/src/clients/kpasswd/kpasswd.M | 75 + krb5-1-6/src/clients/kpasswd/kpasswd.c | 159 + krb5-1-6/src/clients/kpasswd/ksetpwd.c | 316 + krb5-1-6/src/clients/ksu/Makefile.in | 110 + krb5-1-6/src/clients/ksu/authorization.c | 730 + krb5-1-6/src/clients/ksu/ccache.c | 819 + krb5-1-6/src/clients/ksu/heuristic.c | 769 + krb5-1-6/src/clients/ksu/krb_auth_su.c | 584 + krb5-1-6/src/clients/ksu/ksu.M | 481 + krb5-1-6/src/clients/ksu/ksu.h | 254 + krb5-1-6/src/clients/ksu/main.c | 1001 ++ krb5-1-6/src/clients/ksu/setenv.c | 172 + krb5-1-6/src/clients/ksu/xmalloc.c | 68 + krb5-1-6/src/clients/kvno/Makefile.in | 52 + krb5-1-6/src/clients/kvno/kvno.M | 85 + krb5-1-6/src/clients/kvno/kvno.c | 326 + krb5-1-6/src/config-files/Makefile.in | 12 + .../src/config-files/convert-config-files | 84 + krb5-1-6/src/config-files/kdc.conf | 13 + krb5-1-6/src/config-files/kdc.conf.M | 245 + krb5-1-6/src/config-files/krb5.conf | 33 + krb5-1-6/src/config-files/krb5.conf.M | 654 + krb5-1-6/src/config-files/services.append | 32 + krb5-1-6/src/config/ac-archive/README | 51 + krb5-1-6/src/config/ac-archive/acx_pthread.m4 | 239 + krb5-1-6/src/config/config.guess | 1500 ++ krb5-1-6/src/config/config.sub | 1608 ++ krb5-1-6/src/config/install-sh | 295 + krb5-1-6/src/config/lib.in | 170 + krb5-1-6/src/config/libnover.in | 112 + krb5-1-6/src/config/libobj.in | 39 + krb5-1-6/src/config/mkinstalldirs | 40 + krb5-1-6/src/config/move-if-changed | 17 + krb5-1-6/src/config/post.in | 192 + krb5-1-6/src/config/pre.in | 564 + krb5-1-6/src/config/ren2long | 9 + krb5-1-6/src/config/ren2long.awk | 75 + krb5-1-6/src/config/rm.bat | 32 + krb5-1-6/src/config/shlib.conf | 478 + krb5-1-6/src/config/wconfig.pl | 77 + krb5-1-6/src/config/win-post.in | 111 + krb5-1-6/src/config/win-pre.in | 258 + krb5-1-6/src/config/winexclude.sed | 20 + krb5-1-6/src/configure.in | 979 ++ krb5-1-6/src/gen-manpages/Makefile.in | 9 + krb5-1-6/src/gen-manpages/header.doc | 1 + krb5-1-6/src/gen-manpages/k5login.M | 55 + krb5-1-6/src/gen-manpages/kerberos.M | 143 + krb5-1-6/src/include/Makefile.in | 134 + krb5-1-6/src/include/adm.h | 220 + krb5-1-6/src/include/adm_defs.h | 209 + krb5-1-6/src/include/adm_proto.h | 132 + krb5-1-6/src/include/cm.h | 83 + krb5-1-6/src/include/copyright.h | 40 + krb5-1-6/src/include/fake-addrinfo.h | 233 + krb5-1-6/src/include/foreachaddr.h | 64 + krb5-1-6/src/include/gssapi.h | 5 + krb5-1-6/src/include/gssrpc/auth.h | 219 + krb5-1-6/src/include/gssrpc/auth_gss.h | 149 + krb5-1-6/src/include/gssrpc/auth_gssapi.h | 153 + krb5-1-6/src/include/gssrpc/auth_unix.h | 80 + krb5-1-6/src/include/gssrpc/clnt.h | 344 + krb5-1-6/src/include/gssrpc/netdb.h | 51 + krb5-1-6/src/include/gssrpc/pmap_clnt.h | 81 + krb5-1-6/src/include/gssrpc/pmap_prot.h | 101 + krb5-1-6/src/include/gssrpc/pmap_rmt.h | 63 + krb5-1-6/src/include/gssrpc/rename.h | 307 + krb5-1-6/src/include/gssrpc/rpc.h | 99 + krb5-1-6/src/include/gssrpc/rpc_msg.h | 205 + krb5-1-6/src/include/gssrpc/svc.h | 337 + krb5-1-6/src/include/gssrpc/svc_auth.h | 117 + krb5-1-6/src/include/gssrpc/types.hin | 175 + krb5-1-6/src/include/gssrpc/xdr.h | 334 + krb5-1-6/src/include/k5-err.h | 69 + krb5-1-6/src/include/k5-int-pkinit.h | 270 + krb5-1-6/src/include/k5-int.h | 2241 +++ krb5-1-6/src/include/k5-platform.h | 715 + krb5-1-6/src/include/k5-plugin.h | 104 + krb5-1-6/src/include/k5-thread.h | 797 + krb5-1-6/src/include/k5-util.h | 87 + krb5-1-6/src/include/kdb.h | 500 + krb5-1-6/src/include/kdb_dbc.h | 86 + krb5-1-6/src/include/kdb_kt.h | 42 + krb5-1-6/src/include/kerberosIV/Makefile.in | 22 + krb5-1-6/src/include/kerberosIV/addr_comp.h | 52 + .../src/include/kerberosIV/admin_server.h | 58 + krb5-1-6/src/include/kerberosIV/des.h | 237 + krb5-1-6/src/include/kerberosIV/kadm.h | 194 + krb5-1-6/src/include/kerberosIV/kdc.h | 55 + krb5-1-6/src/include/kerberosIV/klog.h | 57 + krb5-1-6/src/include/kerberosIV/kparse.h | 106 + krb5-1-6/src/include/kerberosIV/krb.h | 924 ++ krb5-1-6/src/include/kerberosIV/krb_db.h | 119 + krb5-1-6/src/include/kerberosIV/krbports.h | 27 + .../src/include/kerberosIV/lsb_addr_cmp.h | 47 + .../src/include/kerberosIV/mit-copyright.h | 23 + krb5-1-6/src/include/kerberosIV/prot.h | 277 + krb5-1-6/src/include/krb5.h | 7 + krb5-1-6/src/include/krb5/krb5.hin | 2692 ++++ krb5-1-6/src/include/krb5/locate_plugin.h | 60 + krb5-1-6/src/include/krb5/preauth_plugin.h | 507 + krb5-1-6/src/include/krb54proto.h | 18 + krb5-1-6/src/include/port-sockets.h | 187 + krb5-1-6/src/include/socket-utils.h | 108 + krb5-1-6/src/include/spnego-asn1.h | 89 + krb5-1-6/src/include/stock/osconf.h | 139 + krb5-1-6/src/include/syslog.h | 102 + krb5-1-6/src/include/win-mac.h | 224 + krb5-1-6/src/kadmin/Makefile.in | 8 + krb5-1-6/src/kadmin/cli/Makefile.in | 81 + krb5-1-6/src/kadmin/cli/getdate.y | 1027 ++ krb5-1-6/src/kadmin/cli/k5srvutil.M | 58 + krb5-1-6/src/kadmin/cli/k5srvutil.sh | 117 + krb5-1-6/src/kadmin/cli/kadmin.M | 869 ++ krb5-1-6/src/kadmin/cli/kadmin.c | 1760 +++ krb5-1-6/src/kadmin/cli/kadmin.h | 75 + krb5-1-6/src/kadmin/cli/kadmin.local.M | 1 + krb5-1-6/src/kadmin/cli/kadmin_ct.ct | 85 + krb5-1-6/src/kadmin/cli/keytab.c | 467 + krb5-1-6/src/kadmin/cli/ss_wrapper.c | 64 + krb5-1-6/src/kadmin/cli/strftime.c | 464 + krb5-1-6/src/kadmin/dbutil/Makefile.in | 165 + krb5-1-6/src/kadmin/dbutil/dump.c | 2433 +++ krb5-1-6/src/kadmin/dbutil/dumpv4.c | 462 + krb5-1-6/src/kadmin/dbutil/import_err.et | 26 + krb5-1-6/src/kadmin/dbutil/kadm5_create.c | 311 + krb5-1-6/src/kadmin/dbutil/kdb5_create.c | 437 + krb5-1-6/src/kadmin/dbutil/kdb5_destroy.c | 112 + krb5-1-6/src/kadmin/dbutil/kdb5_edit.M | 182 + krb5-1-6/src/kadmin/dbutil/kdb5_stash.c | 183 + krb5-1-6/src/kadmin/dbutil/kdb5_util.M | 272 + krb5-1-6/src/kadmin/dbutil/kdb5_util.c | 613 + krb5-1-6/src/kadmin/dbutil/kdb5_util.h | 88 + krb5-1-6/src/kadmin/dbutil/loadv4.c | 981 ++ krb5-1-6/src/kadmin/dbutil/nstrtok.h | 3 + krb5-1-6/src/kadmin/dbutil/ovload.c | 213 + krb5-1-6/src/kadmin/dbutil/string_table.c | 84 + krb5-1-6/src/kadmin/dbutil/string_table.h | 39 + krb5-1-6/src/kadmin/dbutil/strtok.c | 105 + krb5-1-6/src/kadmin/dbutil/tcl_wrapper.c | 241 + krb5-1-6/src/kadmin/dbutil/util.c | 158 + krb5-1-6/src/kadmin/kdbkeys/Makefile.in | 18 + krb5-1-6/src/kadmin/kdbkeys/do-test.pl | 56 + krb5-1-6/src/kadmin/ktutil/Makefile.in | 67 + krb5-1-6/src/kadmin/ktutil/ktutil.M | 67 + krb5-1-6/src/kadmin/ktutil/ktutil.c | 295 + krb5-1-6/src/kadmin/ktutil/ktutil.h | 75 + krb5-1-6/src/kadmin/ktutil/ktutil_ct.ct | 59 + krb5-1-6/src/kadmin/ktutil/ktutil_funcs.c | 556 + krb5-1-6/src/kadmin/passwd/Kpasswd | 46 + krb5-1-6/src/kadmin/passwd/Makefile.in | 57 + krb5-1-6/src/kadmin/passwd/kpasswd.M | 70 + krb5-1-6/src/kadmin/passwd/kpasswd.c | 281 + krb5-1-6/src/kadmin/passwd/kpasswd.h | 46 + krb5-1-6/src/kadmin/passwd/kpasswd_strings.et | 76 + krb5-1-6/src/kadmin/passwd/tty_kpasswd.c | 81 + .../src/kadmin/passwd/unit-test/Makefile.in | 27 + .../kadmin/passwd/unit-test/config/unix.exp | 74 + .../passwd/unit-test/kpasswd.0/changing.exp | 105 + .../passwd/unit-test/kpasswd.0/connecting.exp | 29 + .../passwd/unit-test/kpasswd.0/principal.exp | 60 + .../passwd/unit-test/kpasswd.0/usage.exp | 26 + .../kadmin/passwd/unit-test/lib/helpers.exp | 217 + krb5-1-6/src/kadmin/passwd/xm_kpasswd.c | 452 + krb5-1-6/src/kadmin/scripts/inst-hdrs.sh | 14 + krb5-1-6/src/kadmin/server/Makefile.in | 134 + krb5-1-6/src/kadmin/server/acls.l | 190 + krb5-1-6/src/kadmin/server/kadm_rpc_svc.c | 340 + krb5-1-6/src/kadmin/server/kadmind.M | 277 + krb5-1-6/src/kadmin/server/misc.c | 182 + krb5-1-6/src/kadmin/server/misc.h | 49 + krb5-1-6/src/kadmin/server/ovsec_kadmd.c | 1235 ++ krb5-1-6/src/kadmin/server/schpw.c | 411 + krb5-1-6/src/kadmin/server/server_glue_v1.c | 32 + krb5-1-6/src/kadmin/server/server_stubs.c | 1663 +++ krb5-1-6/src/kadmin/testing/Makefile.in | 10 + .../src/kadmin/testing/proto/kdc.conf.proto | 16 + .../src/kadmin/testing/proto/krb5.conf.proto | 29 + .../src/kadmin/testing/proto/ovsec_adm.dict | 3 + .../src/kadmin/testing/scripts/Makefile.in | 37 + .../kadmin/testing/scripts/compare_dump.plin | 242 + .../src/kadmin/testing/scripts/env-setup.shin | 118 + .../src/kadmin/testing/scripts/find-make.sh | 18 + .../testing/scripts/fixup-conf-files.plin | 344 + krb5-1-6/src/kadmin/testing/scripts/init_db | 227 + .../testing/scripts/make-host-keytab.plin | 144 + .../src/kadmin/testing/scripts/qualname.plin | 20 + .../src/kadmin/testing/scripts/save_files.sh | 62 + .../kadmin/testing/scripts/simple_dump.plin | 88 + .../src/kadmin/testing/scripts/start_servers | 72 + .../testing/scripts/start_servers_local | 218 + .../src/kadmin/testing/scripts/stop_servers | 62 + .../kadmin/testing/scripts/stop_servers_local | 53 + .../scripts/verify_xrunner_report.plin | 38 + krb5-1-6/src/kadmin/testing/tcl/util.t | 60 + krb5-1-6/src/kadmin/testing/util/Makefile.in | 75 + krb5-1-6/src/kadmin/testing/util/bsddb_dump.c | 64 + krb5-1-6/src/kadmin/testing/util/tcl_kadm5.c | 2549 ++++ krb5-1-6/src/kadmin/testing/util/tcl_kadm5.h | 4 + .../src/kadmin/testing/util/tcl_krb5_hash.c | 167 + .../src/kadmin/testing/util/tcl_ovsec_kadm.c | 2030 +++ .../kadmin/testing/util/tcl_ovsec_kadm_syntax | 57 + krb5-1-6/src/kadmin/testing/util/test.c | 38 + krb5-1-6/src/kdc/.saberinit | 35 + krb5-1-6/src/kdc/Makefile.in | 213 + krb5-1-6/src/kdc/dispatch.c | 115 + krb5-1-6/src/kdc/do_as_req.c | 554 + krb5-1-6/src/kdc/do_tgs_req.c | 847 ++ krb5-1-6/src/kdc/extern.c | 42 + krb5-1-6/src/kdc/extern.h | 99 + krb5-1-6/src/kdc/fakeka.M | 111 + krb5-1-6/src/kdc/fakeka.c | 1395 ++ krb5-1-6/src/kdc/kdc5_err.et | 35 + krb5-1-6/src/kdc/kdc_preauth.c | 2352 +++ krb5-1-6/src/kdc/kdc_util.c | 1591 ++ krb5-1-6/src/kdc/kdc_util.h | 206 + krb5-1-6/src/kdc/kerberos_v4.c | 1198 ++ krb5-1-6/src/kdc/krb5kdc.M | 188 + krb5-1-6/src/kdc/main.c | 764 + krb5-1-6/src/kdc/migration.doc | 59 + krb5-1-6/src/kdc/network.c | 1132 ++ krb5-1-6/src/kdc/policy.c | 75 + krb5-1-6/src/kdc/policy.h | 39 + krb5-1-6/src/kdc/replay.c | 175 + krb5-1-6/src/kdc/rtest.c | 116 + krb5-1-6/src/kdc/rtest.good | 26 + krb5-1-6/src/kdc/rtscript | 54 + krb5-1-6/src/krb5-config.M | 74 + krb5-1-6/src/krb5-config.in | 226 + krb5-1-6/src/krb524/Makefile.in | 176 + krb5-1-6/src/krb524/README | 154 + krb5-1-6/src/krb524/cnv_tkt_skey.c | 208 + krb5-1-6/src/krb524/conv_princ.c | 40 + krb5-1-6/src/krb524/k524init.M | 47 + krb5-1-6/src/krb524/k524init.c | 183 + krb5-1-6/src/krb524/krb524.c | 47 + krb5-1-6/src/krb524/krb524.def | 13 + krb5-1-6/src/krb524/krb524_prot | 11 + krb5-1-6/src/krb524/krb524d.M | 74 + krb5-1-6/src/krb524/krb524d.c | 636 + krb5-1-6/src/krb524/krb524d.h | 48 + krb5-1-6/src/krb524/libinit.c | 27 + krb5-1-6/src/krb524/test.c | 353 + krb5-1-6/src/lib/Makefile.in | 195 + krb5-1-6/src/lib/apputils/Makefile.in | 52 + krb5-1-6/src/lib/apputils/configure.in | 6 + krb5-1-6/src/lib/apputils/daemon.c | 95 + krb5-1-6/src/lib/apputils/dummy.c | 1 + krb5-1-6/src/lib/comerr32.def | 12 + krb5-1-6/src/lib/crypto/ISSUES | 16 + krb5-1-6/src/lib/crypto/Makefile.in | 772 + krb5-1-6/src/lib/crypto/aes/Makefile.in | 93 + krb5-1-6/src/lib/crypto/aes/aes-gen.c | 326 + krb5-1-6/src/lib/crypto/aes/aes-test.c | 138 + krb5-1-6/src/lib/crypto/aes/aes.h | 97 + krb5-1-6/src/lib/crypto/aes/aes.txt | 70 + krb5-1-6/src/lib/crypto/aes/aes_s2k.c | 93 + krb5-1-6/src/lib/crypto/aes/aes_s2k.h | 4 + krb5-1-6/src/lib/crypto/aes/aescpp.h | 55 + krb5-1-6/src/lib/crypto/aes/aescrypp.c | 487 + krb5-1-6/src/lib/crypto/aes/aescrypt.asm | 402 + krb5-1-6/src/lib/crypto/aes/aescrypt.c | 421 + krb5-1-6/src/lib/crypto/aes/aeskey.c | 363 + krb5-1-6/src/lib/crypto/aes/aeskeypp.c | 399 + krb5-1-6/src/lib/crypto/aes/aesopt.h | 851 ++ krb5-1-6/src/lib/crypto/aes/aessrc.url | 1 + krb5-1-6/src/lib/crypto/aes/aestab.c | 494 + krb5-1-6/src/lib/crypto/aes/expect-vk.txt | 1548 ++ krb5-1-6/src/lib/crypto/aes/expect-vt.txt | 1036 ++ krb5-1-6/src/lib/crypto/aes/test/Readme.txt | 22 + krb5-1-6/src/lib/crypto/aes/test/cbc_d_m.txt | 7224 +++++++++ krb5-1-6/src/lib/crypto/aes/test/cbc_e_m.txt | 7224 +++++++++ krb5-1-6/src/lib/crypto/aes/test/ecb_d_m.txt | 6024 ++++++++ krb5-1-6/src/lib/crypto/aes/test/ecb_e_m.txt | 6024 ++++++++ .../src/lib/crypto/aes/test/ecb_iv.readme | 19 + krb5-1-6/src/lib/crypto/aes/test/ecb_iv.txt | 123 + krb5-1-6/src/lib/crypto/aes/test/ecb_tbl.txt | 1955 +++ krb5-1-6/src/lib/crypto/aes/test/ecb_vk.txt | 2334 +++ krb5-1-6/src/lib/crypto/aes/test/ecb_vt.txt | 1566 ++ krb5-1-6/src/lib/crypto/aes/test/katmct.pdf | Bin 0 -> 100812 bytes krb5-1-6/src/lib/crypto/aes/uitypes.h | 83 + krb5-1-6/src/lib/crypto/aes/vb.txt | 87 + krb5-1-6/src/lib/crypto/arcfour/Makefile.in | 64 + krb5-1-6/src/lib/crypto/arcfour/arcfour-int.h | 31 + krb5-1-6/src/lib/crypto/arcfour/arcfour.c | 318 + krb5-1-6/src/lib/crypto/arcfour/arcfour.h | 36 + krb5-1-6/src/lib/crypto/arcfour/arcfour_s2k.c | 70 + krb5-1-6/src/lib/crypto/block_size.c | 47 + krb5-1-6/src/lib/crypto/checksum_length.c | 53 + krb5-1-6/src/lib/crypto/cksumtype_to_string.c | 46 + krb5-1-6/src/lib/crypto/cksumtypes.c | 98 + krb5-1-6/src/lib/crypto/cksumtypes.h | 30 + krb5-1-6/src/lib/crypto/coll_proof_cksum.c | 50 + krb5-1-6/src/lib/crypto/combine_keys.c | 349 + krb5-1-6/src/lib/crypto/crc32/CRC.pm | 156 + krb5-1-6/src/lib/crypto/crc32/Makefile.in | 55 + krb5-1-6/src/lib/crypto/crc32/Poly.pm | 182 + krb5-1-6/src/lib/crypto/crc32/crc-32.h | 71 + krb5-1-6/src/lib/crypto/crc32/crc.pl | 111 + krb5-1-6/src/lib/crypto/crc32/crc32.c | 192 + krb5-1-6/src/lib/crypto/crc32/t_crc.c | 213 + krb5-1-6/src/lib/crypto/crypto_libinit.c | 33 + krb5-1-6/src/lib/crypto/decrypt.c | 52 + krb5-1-6/src/lib/crypto/default_state.c | 63 + krb5-1-6/src/lib/crypto/des/ISSUES | 13 + krb5-1-6/src/lib/crypto/des/Makefile.in | 209 + krb5-1-6/src/lib/crypto/des/afsstring2key.c | 570 + krb5-1-6/src/lib/crypto/des/d3_cbc.c | 226 + krb5-1-6/src/lib/crypto/des/d3_kysched.c | 50 + krb5-1-6/src/lib/crypto/des/des_int.h | 305 + krb5-1-6/src/lib/crypto/des/destest.c | 247 + krb5-1-6/src/lib/crypto/des/doc/libdes.doc | 208 + krb5-1-6/src/lib/crypto/des/f_cbc.c | 255 + krb5-1-6/src/lib/crypto/des/f_cksum.c | 120 + krb5-1-6/src/lib/crypto/des/f_parity.c | 56 + krb5-1-6/src/lib/crypto/des/f_sched.c | 344 + krb5-1-6/src/lib/crypto/des/f_tables.c | 351 + krb5-1-6/src/lib/crypto/des/f_tables.h | 260 + krb5-1-6/src/lib/crypto/des/key_sched.c | 61 + krb5-1-6/src/lib/crypto/des/keytest.data | 171 + krb5-1-6/src/lib/crypto/des/string2key.c | 261 + krb5-1-6/src/lib/crypto/des/t_afss2k.c | 136 + krb5-1-6/src/lib/crypto/des/t_verify.c | 418 + krb5-1-6/src/lib/crypto/des/weak_key.c | 85 + krb5-1-6/src/lib/crypto/dk/Makefile.in | 112 + krb5-1-6/src/lib/crypto/dk/checksum.c | 103 + krb5-1-6/src/lib/crypto/dk/derive.c | 217 + krb5-1-6/src/lib/crypto/dk/dk.h | 90 + krb5-1-6/src/lib/crypto/dk/dk_decrypt.c | 203 + krb5-1-6/src/lib/crypto/dk/dk_encrypt.c | 362 + krb5-1-6/src/lib/crypto/dk/dk_prf.c | 64 + krb5-1-6/src/lib/crypto/dk/stringtokey.c | 96 + .../src/lib/crypto/enc_provider/Makefile.in | 87 + krb5-1-6/src/lib/crypto/enc_provider/aes.c | 208 + krb5-1-6/src/lib/crypto/enc_provider/des.c | 117 + krb5-1-6/src/lib/crypto/enc_provider/des3.c | 140 + .../lib/crypto/enc_provider/enc_provider.h | 33 + krb5-1-6/src/lib/crypto/enc_provider/rc4.c | 216 + krb5-1-6/src/lib/crypto/encrypt.c | 52 + krb5-1-6/src/lib/crypto/encrypt_length.c | 49 + krb5-1-6/src/lib/crypto/enctype_compare.c | 55 + krb5-1-6/src/lib/crypto/enctype_to_string.c | 46 + krb5-1-6/src/lib/crypto/etypes.c | 214 + krb5-1-6/src/lib/crypto/etypes.h | 30 + .../src/lib/crypto/hash_provider/Makefile.in | 82 + .../src/lib/crypto/hash_provider/hash_crc32.c | 59 + .../src/lib/crypto/hash_provider/hash_md4.c | 55 + .../src/lib/crypto/hash_provider/hash_md5.c | 55 + .../lib/crypto/hash_provider/hash_provider.h | 32 + .../src/lib/crypto/hash_provider/hash_sha1.c | 60 + krb5-1-6/src/lib/crypto/hmac.c | 127 + krb5-1-6/src/lib/crypto/keyblocks.c | 79 + .../src/lib/crypto/keyed_checksum_types.c | 89 + krb5-1-6/src/lib/crypto/keyed_cksum.c | 55 + .../lib/crypto/keyhash_provider/Makefile.in | 104 + .../src/lib/crypto/keyhash_provider/descbc.c | 70 + .../lib/crypto/keyhash_provider/hmac_md5.c | 96 + .../lib/crypto/keyhash_provider/k5_md4des.c | 190 + .../lib/crypto/keyhash_provider/k5_md5des.c | 187 + .../keyhash_provider/keyhash_provider.h | 32 + .../src/lib/crypto/keyhash_provider/t_cksum.c | 139 + krb5-1-6/src/lib/crypto/keylengths.c | 61 + krb5-1-6/src/lib/crypto/libk5crypto.exports | 158 + krb5-1-6/src/lib/crypto/make_checksum.c | 114 + krb5-1-6/src/lib/crypto/make_random_key.c | 83 + krb5-1-6/src/lib/crypto/mandatory_sumtype.c | 41 + krb5-1-6/src/lib/crypto/md4/ISSUES | 3 + krb5-1-6/src/lib/crypto/md4/Makefile.in | 72 + krb5-1-6/src/lib/crypto/md4/md4.c | 257 + krb5-1-6/src/lib/crypto/md4/rsa-md4.h | 94 + krb5-1-6/src/lib/crypto/md5/ISSUES | 3 + krb5-1-6/src/lib/crypto/md5/Makefile.in | 62 + krb5-1-6/src/lib/crypto/md5/md5.c | 355 + krb5-1-6/src/lib/crypto/md5/rsa-md5.h | 60 + krb5-1-6/src/lib/crypto/md5/t_cksum.c | 206 + krb5-1-6/src/lib/crypto/md5/t_mddriver.c | 323 + krb5-1-6/src/lib/crypto/nfold.c | 130 + krb5-1-6/src/lib/crypto/old/Makefile.in | 68 + krb5-1-6/src/lib/crypto/old/des_stringtokey.c | 58 + krb5-1-6/src/lib/crypto/old/old.h | 52 + krb5-1-6/src/lib/crypto/old/old_decrypt.c | 143 + krb5-1-6/src/lib/crypto/old/old_encrypt.c | 110 + krb5-1-6/src/lib/crypto/old_api_glue.c | 326 + krb5-1-6/src/lib/crypto/pbkdf2.c | 268 + krb5-1-6/src/lib/crypto/prf.c | 87 + krb5-1-6/src/lib/crypto/prng.c | 217 + krb5-1-6/src/lib/crypto/random_to_key.c | 73 + krb5-1-6/src/lib/crypto/raw/Makefile.in | 56 + krb5-1-6/src/lib/crypto/raw/raw.h | 46 + krb5-1-6/src/lib/crypto/raw/raw_decrypt.c | 38 + krb5-1-6/src/lib/crypto/raw/raw_encrypt.c | 50 + krb5-1-6/src/lib/crypto/sha1/ISSUES | 7 + krb5-1-6/src/lib/crypto/sha1/Makefile.in | 67 + krb5-1-6/src/lib/crypto/sha1/shs.c | 386 + krb5-1-6/src/lib/crypto/sha1/shs.h | 45 + krb5-1-6/src/lib/crypto/sha1/t_shs.c | 135 + krb5-1-6/src/lib/crypto/sha1/t_shs3.c | 592 + krb5-1-6/src/lib/crypto/state.c | 72 + krb5-1-6/src/lib/crypto/string_to_cksumtype.c | 43 + krb5-1-6/src/lib/crypto/string_to_enctype.c | 43 + krb5-1-6/src/lib/crypto/string_to_key.c | 99 + krb5-1-6/src/lib/crypto/t_cts.c | 177 + krb5-1-6/src/lib/crypto/t_encrypt.c | 153 + krb5-1-6/src/lib/crypto/t_hmac.c | 271 + krb5-1-6/src/lib/crypto/t_nfold.c | 165 + krb5-1-6/src/lib/crypto/t_pkcs5.c | 105 + krb5-1-6/src/lib/crypto/t_prf.c | 88 + krb5-1-6/src/lib/crypto/t_prng.c | 87 + krb5-1-6/src/lib/crypto/t_prng.comments | 14 + krb5-1-6/src/lib/crypto/t_prng.expected | 4 + krb5-1-6/src/lib/crypto/t_prng.reseedtest | 31 + .../src/lib/crypto/t_prng.reseedtest-comments | 21 + .../src/lib/crypto/t_prng.reseedtest-expected | 1 + krb5-1-6/src/lib/crypto/t_prng.seed | 25 + krb5-1-6/src/lib/crypto/valid_cksumtype.c | 47 + krb5-1-6/src/lib/crypto/valid_enctype.c | 47 + krb5-1-6/src/lib/crypto/vectors.c | 457 + krb5-1-6/src/lib/crypto/verify_checksum.c | 80 + krb5-1-6/src/lib/crypto/yarrow/ASSUMPTIONS | 101 + krb5-1-6/src/lib/crypto/yarrow/LICENSE | 21 + krb5-1-6/src/lib/crypto/yarrow/Makefile.in | 64 + krb5-1-6/src/lib/crypto/yarrow/README | 94 + krb5-1-6/src/lib/crypto/yarrow/TODO | 9 + krb5-1-6/src/lib/crypto/yarrow/yarrow.c | 955 ++ krb5-1-6/src/lib/crypto/yarrow/yarrow.h | 186 + krb5-1-6/src/lib/crypto/yarrow/yarrow.man | 315 + krb5-1-6/src/lib/crypto/yarrow/yarrow.pod | 112 + krb5-1-6/src/lib/crypto/yarrow/ycipher.c | 96 + krb5-1-6/src/lib/crypto/yarrow/ycipher.h | 42 + krb5-1-6/src/lib/crypto/yarrow/yexcep.h | 107 + krb5-1-6/src/lib/crypto/yarrow/yhash.h | 33 + krb5-1-6/src/lib/crypto/yarrow/ylock.h | 24 + krb5-1-6/src/lib/crypto/yarrow/ystate.h | 28 + krb5-1-6/src/lib/crypto/yarrow/ytest.c | 385 + krb5-1-6/src/lib/crypto/yarrow/ytypes.h | 27 + krb5-1-6/src/lib/des425/ISSUES | 28 + krb5-1-6/src/lib/des425/Makefile.in | 259 + krb5-1-6/src/lib/des425/cksum.c | 68 + krb5-1-6/src/lib/des425/des.c | 44 + krb5-1-6/src/lib/des425/enc_dec.c | 47 + krb5-1-6/src/lib/des425/key_parity.c | 52 + krb5-1-6/src/lib/des425/key_sched.c | 40 + krb5-1-6/src/lib/des425/libdes425.exports | 18 + krb5-1-6/src/lib/des425/mac_des_glue.c | 104 + krb5-1-6/src/lib/des425/new_rnd_key.c | 96 + krb5-1-6/src/lib/des425/pcbc_encrypt.c | 218 + krb5-1-6/src/lib/des425/quad_cksum.c | 200 + krb5-1-6/src/lib/des425/random_key.c | 74 + krb5-1-6/src/lib/des425/read_passwd.c | 129 + krb5-1-6/src/lib/des425/str_to_key.c | 168 + krb5-1-6/src/lib/des425/string2key.c | 174 + krb5-1-6/src/lib/des425/t_pcbc.c | 123 + krb5-1-6/src/lib/des425/t_quad.c | 101 + krb5-1-6/src/lib/des425/unix_time.c | 46 + krb5-1-6/src/lib/des425/util.c | 33 + krb5-1-6/src/lib/des425/verify.c | 317 + krb5-1-6/src/lib/des425/weak_key.c | 41 + krb5-1-6/src/lib/glue4.c | 19 + krb5-1-6/src/lib/gssapi/LICENSE | 91 + krb5-1-6/src/lib/gssapi/Makefile.in | 159 + krb5-1-6/src/lib/gssapi/README_SAMPLE_APP | 4 + krb5-1-6/src/lib/gssapi/generic/Makefile.in | 205 + .../lib/gssapi/generic/disp_com_err_status.c | 66 + .../lib/gssapi/generic/disp_major_status.c | 312 + krb5-1-6/src/lib/gssapi/generic/gssapi.hin | 790 + .../src/lib/gssapi/generic/gssapiP_generic.h | 258 + .../lib/gssapi/generic/gssapi_err_generic.et | 49 + .../src/lib/gssapi/generic/gssapi_generic.c | 148 + .../src/lib/gssapi/generic/gssapi_generic.h | 55 + krb5-1-6/src/lib/gssapi/generic/rel_buffer.c | 57 + krb5-1-6/src/lib/gssapi/generic/rel_oid_set.c | 61 + krb5-1-6/src/lib/gssapi/generic/util_buffer.c | 48 + .../src/lib/gssapi/generic/util_canonhost.c | 71 + .../src/lib/gssapi/generic/util_localhost.c | 50 + .../src/lib/gssapi/generic/util_ordering.c | 251 + krb5-1-6/src/lib/gssapi/generic/util_set.c | 105 + krb5-1-6/src/lib/gssapi/generic/util_token.c | 232 + .../src/lib/gssapi/generic/util_validate.c | 321 + .../lib/gssapi/generic/utl_nohash_validate.c | 121 + krb5-1-6/src/lib/gssapi/gss_libinit.c | 79 + krb5-1-6/src/lib/gssapi/gss_libinit.h | 9 + krb5-1-6/src/lib/gssapi/krb5/3des.txt | 395 + krb5-1-6/src/lib/gssapi/krb5/Makefile.in | 774 + .../src/lib/gssapi/krb5/accept_sec_context.c | 998 ++ krb5-1-6/src/lib/gssapi/krb5/acquire_cred.c | 670 + krb5-1-6/src/lib/gssapi/krb5/add_cred.c | 369 + krb5-1-6/src/lib/gssapi/krb5/canon_name.c | 45 + krb5-1-6/src/lib/gssapi/krb5/compare_name.c | 60 + krb5-1-6/src/lib/gssapi/krb5/context_time.c | 67 + krb5-1-6/src/lib/gssapi/krb5/copy_ccache.c | 59 + .../src/lib/gssapi/krb5/delete_sec_context.c | 119 + krb5-1-6/src/lib/gssapi/krb5/disp_name.c | 74 + krb5-1-6/src/lib/gssapi/krb5/disp_status.c | 68 + krb5-1-6/src/lib/gssapi/krb5/duplicate_name.c | 79 + krb5-1-6/src/lib/gssapi/krb5/export_name.c | 96 + .../src/lib/gssapi/krb5/export_sec_context.c | 102 + krb5-1-6/src/lib/gssapi/krb5/get_tkt_flags.c | 55 + krb5-1-6/src/lib/gssapi/krb5/gssapiP_krb5.h | 685 + .../src/lib/gssapi/krb5/gssapi_err_krb5.et | 40 + krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.c | 270 + krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.hin | 272 + krb5-1-6/src/lib/gssapi/krb5/import_name.c | 237 + .../src/lib/gssapi/krb5/import_sec_context.c | 126 + krb5-1-6/src/lib/gssapi/krb5/indicate_mechs.c | 44 + .../src/lib/gssapi/krb5/init_sec_context.c | 1021 ++ krb5-1-6/src/lib/gssapi/krb5/inq_context.c | 132 + krb5-1-6/src/lib/gssapi/krb5/inq_cred.c | 267 + krb5-1-6/src/lib/gssapi/krb5/inq_names.c | 99 + krb5-1-6/src/lib/gssapi/krb5/k5seal.c | 399 + krb5-1-6/src/lib/gssapi/krb5/k5sealv3.c | 511 + krb5-1-6/src/lib/gssapi/krb5/k5unseal.c | 550 + krb5-1-6/src/lib/gssapi/krb5/krb5_gss_glue.c | 1105 ++ krb5-1-6/src/lib/gssapi/krb5/lucid_context.c | 309 + .../lib/gssapi/krb5/process_context_token.c | 64 + krb5-1-6/src/lib/gssapi/krb5/rel_cred.c | 91 + krb5-1-6/src/lib/gssapi/krb5/rel_name.c | 54 + krb5-1-6/src/lib/gssapi/krb5/rel_oid.c | 86 + krb5-1-6/src/lib/gssapi/krb5/seal.c | 63 + krb5-1-6/src/lib/gssapi/krb5/ser_sctx.c | 676 + .../lib/gssapi/krb5/set_allowable_enctypes.c | 133 + krb5-1-6/src/lib/gssapi/krb5/set_ccache.c | 92 + krb5-1-6/src/lib/gssapi/krb5/sign.c | 57 + krb5-1-6/src/lib/gssapi/krb5/unseal.c | 66 + krb5-1-6/src/lib/gssapi/krb5/util_cksum.c | 108 + krb5-1-6/src/lib/gssapi/krb5/util_crypt.c | 240 + krb5-1-6/src/lib/gssapi/krb5/util_seed.c | 54 + krb5-1-6/src/lib/gssapi/krb5/util_seqnum.c | 105 + krb5-1-6/src/lib/gssapi/krb5/val_cred.c | 98 + krb5-1-6/src/lib/gssapi/krb5/verify.c | 64 + .../src/lib/gssapi/krb5/wrap_size_limit.c | 163 + .../src/lib/gssapi/libgssapi_krb5.exports | 73 + krb5-1-6/src/lib/gssapi/mechglue/Makefile.in | 334 + .../gssapi/mechglue/g_accept_sec_context.c | 364 + .../src/lib/gssapi/mechglue/g_acquire_cred.c | 516 + .../src/lib/gssapi/mechglue/g_canon_name.c | 182 + .../src/lib/gssapi/mechglue/g_compare_name.c | 197 + .../src/lib/gssapi/mechglue/g_context_time.c | 78 + .../gssapi/mechglue/g_delete_sec_context.c | 113 + krb5-1-6/src/lib/gssapi/mechglue/g_dsp_name.c | 136 + .../src/lib/gssapi/mechglue/g_dsp_status.c | 327 + krb5-1-6/src/lib/gssapi/mechglue/g_dup_name.c | 140 + .../lib/gssapi/mechglue/g_exp_sec_context.c | 135 + .../src/lib/gssapi/mechglue/g_export_name.c | 58 + krb5-1-6/src/lib/gssapi/mechglue/g_glue.c | 585 + krb5-1-6/src/lib/gssapi/mechglue/g_imp_name.c | 356 + .../lib/gssapi/mechglue/g_imp_sec_context.c | 163 + .../lib/gssapi/mechglue/g_init_sec_context.c | 252 + .../src/lib/gssapi/mechglue/g_initialize.c | 597 + .../src/lib/gssapi/mechglue/g_inq_context.c | 173 + krb5-1-6/src/lib/gssapi/mechglue/g_inq_cred.c | 270 + .../src/lib/gssapi/mechglue/g_inq_names.c | 190 + krb5-1-6/src/lib/gssapi/mechglue/g_mechname.c | 112 + krb5-1-6/src/lib/gssapi/mechglue/g_oid_ops.c | 88 + .../lib/gssapi/mechglue/g_process_context.c | 81 + .../src/lib/gssapi/mechglue/g_rel_buffer.c | 58 + krb5-1-6/src/lib/gssapi/mechglue/g_rel_cred.c | 100 + krb5-1-6/src/lib/gssapi/mechglue/g_rel_name.c | 83 + .../src/lib/gssapi/mechglue/g_rel_oid_set.c | 63 + krb5-1-6/src/lib/gssapi/mechglue/g_seal.c | 196 + krb5-1-6/src/lib/gssapi/mechglue/g_sign.c | 134 + .../src/lib/gssapi/mechglue/g_store_cred.c | 171 + krb5-1-6/src/lib/gssapi/mechglue/g_unseal.c | 122 + krb5-1-6/src/lib/gssapi/mechglue/g_verify.c | 104 + krb5-1-6/src/lib/gssapi/mechglue/mech.conf | 7 + krb5-1-6/src/lib/gssapi/mechglue/mechglue.h | 38 + krb5-1-6/src/lib/gssapi/mechglue/mglueP.h | 492 + krb5-1-6/src/lib/gssapi/mechglue/oid_ops.c | 514 + krb5-1-6/src/lib/gssapi/spnego/Makefile.in | 43 + .../src/lib/gssapi/spnego/gssapiP_spnego.h | 345 + krb5-1-6/src/lib/gssapi/spnego/spnego_mech.c | 2854 ++++ krb5-1-6/src/lib/gssapi32.def | 99 + krb5-1-6/src/lib/kadm5/Makefile.in | 206 + krb5-1-6/src/lib/kadm5/adb.h | 149 + krb5-1-6/src/lib/kadm5/admin.h | 747 + krb5-1-6/src/lib/kadm5/admin_internal.h | 80 + krb5-1-6/src/lib/kadm5/admin_xdr.h | 64 + krb5-1-6/src/lib/kadm5/alt_prof.c | 1041 ++ krb5-1-6/src/lib/kadm5/chpass_util.c | 255 + krb5-1-6/src/lib/kadm5/chpass_util_strings.et | 58 + krb5-1-6/src/lib/kadm5/clnt/Makefile.in | 165 + krb5-1-6/src/lib/kadm5/clnt/client_handle.c | 9 + krb5-1-6/src/lib/kadm5/clnt/client_init.c | 752 + krb5-1-6/src/lib/kadm5/clnt/client_internal.h | 97 + .../src/lib/kadm5/clnt/client_principal.c | 546 + krb5-1-6/src/lib/kadm5/clnt/client_rpc.c | 325 + .../src/lib/kadm5/clnt/clnt_chpass_util.c | 16 + krb5-1-6/src/lib/kadm5/clnt/clnt_policy.c | 152 + krb5-1-6/src/lib/kadm5/clnt/clnt_privs.c | 30 + .../src/lib/kadm5/clnt/libkadm5clnt.exports | 131 + krb5-1-6/src/lib/kadm5/kadm_err.et | 63 + krb5-1-6/src/lib/kadm5/kadm_rpc.h | 305 + krb5-1-6/src/lib/kadm5/kadm_rpc_xdr.c | 1044 ++ krb5-1-6/src/lib/kadm5/logger.c | 972 ++ krb5-1-6/src/lib/kadm5/misc_free.c | 115 + krb5-1-6/src/lib/kadm5/ovsec_glue.c | 194 + krb5-1-6/src/lib/kadm5/server_internal.h | 142 + krb5-1-6/src/lib/kadm5/srv/Makefile.in | 255 + krb5-1-6/src/lib/kadm5/srv/adb_xdr.c | 110 + .../src/lib/kadm5/srv/libkadm5srv.exports | 162 + krb5-1-6/src/lib/kadm5/srv/server_acl.c | 807 + krb5-1-6/src/lib/kadm5/srv/server_acl.h | 103 + krb5-1-6/src/lib/kadm5/srv/server_dict.c | 203 + krb5-1-6/src/lib/kadm5/srv/server_handle.c | 9 + krb5-1-6/src/lib/kadm5/srv/server_init.c | 434 + krb5-1-6/src/lib/kadm5/srv/server_kdb.c | 410 + krb5-1-6/src/lib/kadm5/srv/server_misc.c | 183 + krb5-1-6/src/lib/kadm5/srv/svr_chpass_util.c | 16 + krb5-1-6/src/lib/kadm5/srv/svr_iters.c | 271 + krb5-1-6/src/lib/kadm5/srv/svr_misc_free.c | 37 + krb5-1-6/src/lib/kadm5/srv/svr_policy.c | 317 + krb5-1-6/src/lib/kadm5/srv/svr_principal.c | 2109 +++ krb5-1-6/src/lib/kadm5/str_conv.c | 417 + krb5-1-6/src/lib/kadm5/unit-test/Makefile.in | 232 + .../src/lib/kadm5/unit-test/README.new-tests | 12 + .../unit-test/api.0/chpass-principal.exp | 176 + .../lib/kadm5/unit-test/api.0/crte-policy.exp | 991 ++ .../kadm5/unit-test/api.0/crte-principal.exp | 1336 ++ .../src/lib/kadm5/unit-test/api.0/destroy.exp | 203 + .../lib/kadm5/unit-test/api.0/dlte-policy.exp | 207 + .../kadm5/unit-test/api.0/dlte-principal.exp | 329 + .../lib/kadm5/unit-test/api.0/get-policy.exp | 199 + .../kadm5/unit-test/api.0/get-principal.exp | 346 + .../src/lib/kadm5/unit-test/api.0/init.exp | 728 + .../lib/kadm5/unit-test/api.0/mod-policy.exp | 703 + .../kadm5/unit-test/api.0/mod-principal.exp | 1942 +++ .../unit-test/api.0/randkey-principal.exp | 319 + .../unit-test/api.0/rename-principal.exp | 509 + .../src/lib/kadm5/unit-test/api.1/lock.exp | 287 + .../unit-test/api.2/chpass-principal-v2.exp | 68 + .../unit-test/api.2/chpass-principal.exp | 176 + .../lib/kadm5/unit-test/api.2/crte-policy.exp | 991 ++ .../kadm5/unit-test/api.2/crte-principal.exp | 1335 ++ .../src/lib/kadm5/unit-test/api.2/destroy.exp | 203 + .../lib/kadm5/unit-test/api.2/dlte-policy.exp | 207 + .../kadm5/unit-test/api.2/dlte-principal.exp | 329 + .../lib/kadm5/unit-test/api.2/get-policy.exp | 199 + .../unit-test/api.2/get-principal-v2.exp | 250 + .../kadm5/unit-test/api.2/get-principal.exp | 346 + .../src/lib/kadm5/unit-test/api.2/init-v2.exp | 619 + .../src/lib/kadm5/unit-test/api.2/init.exp | 732 + .../lib/kadm5/unit-test/api.2/mod-policy.exp | 703 + .../unit-test/api.2/mod-principal-v2.exp | 114 + .../kadm5/unit-test/api.2/mod-principal.exp | 1942 +++ .../unit-test/api.2/randkey-principal-v2.exp | 62 + .../unit-test/api.2/randkey-principal.exp | 319 + .../src/lib/kadm5/unit-test/config/unix.exp | 179 + .../src/lib/kadm5/unit-test/destroy-test.c | 42 + .../lib/kadm5/unit-test/diff-files/destroy-1 | 2 + .../lib/kadm5/unit-test/diff-files/no-diffs | 2 + .../src/lib/kadm5/unit-test/handle-test.c | 130 + krb5-1-6/src/lib/kadm5/unit-test/init-test.c | 30 + krb5-1-6/src/lib/kadm5/unit-test/iter-test.c | 48 + krb5-1-6/src/lib/kadm5/unit-test/lib/lib.t | 305 + krb5-1-6/src/lib/kadm5/unit-test/lock-test.c | 111 + .../src/lib/kadm5/unit-test/randkey-test.c | 45 + .../src/lib/kadm5/unit-test/setkey-test.c | 233 + krb5-1-6/src/lib/kadm5/unit-test/site.exp | 2 + krb5-1-6/src/lib/kdb/Makefile.in | 119 + krb5-1-6/src/lib/kdb/adb_err.et | 16 + krb5-1-6/src/lib/kdb/decrypt_key.c | 139 + krb5-1-6/src/lib/kdb/encrypt_key.c | 136 + krb5-1-6/src/lib/kdb/kdb5.c | 1958 +++ krb5-1-6/src/lib/kdb/kdb5.h | 197 + krb5-1-6/src/lib/kdb/kdb_cpw.c | 649 + krb5-1-6/src/lib/kdb/kdb_default.c | 340 + krb5-1-6/src/lib/kdb/keytab.c | 236 + krb5-1-6/src/lib/kdb/libkdb5.exports | 51 + krb5-1-6/src/lib/krb4/CCache-glue.c | 741 + krb5-1-6/src/lib/krb4/FSp-glue.c | 112 + krb5-1-6/src/lib/krb4/Makefile.in | 662 + krb5-1-6/src/lib/krb4/Password.c | 436 + krb5-1-6/src/lib/krb4/RealmsConfig-glue.c | 697 + krb5-1-6/src/lib/krb4/ad_print.c | 85 + krb5-1-6/src/lib/krb4/change_password.c | 127 + krb5-1-6/src/lib/krb4/cr_auth_repl.c | 136 + krb5-1-6/src/lib/krb4/cr_ciph.c | 136 + krb5-1-6/src/lib/krb4/cr_death_pkt.c | 78 + krb5-1-6/src/lib/krb4/cr_err_repl.c | 110 + krb5-1-6/src/lib/krb4/cr_tkt.c | 254 + krb5-1-6/src/lib/krb4/debug.c | 15 + krb5-1-6/src/lib/krb4/decomp_tkt.c | 295 + krb5-1-6/src/lib/krb4/dest_tkt.c | 160 + krb5-1-6/src/lib/krb4/err_txt.c | 87 + krb5-1-6/src/lib/krb4/et_errtxt.awk | 71 + krb5-1-6/src/lib/krb4/fgetst.c | 38 + krb5-1-6/src/lib/krb4/g_ad_tkt.c | 383 + krb5-1-6/src/lib/krb4/g_cnffile.c | 123 + krb5-1-6/src/lib/krb4/g_cred.c | 58 + krb5-1-6/src/lib/krb4/g_in_tkt.c | 555 + krb5-1-6/src/lib/krb4/g_phost.c | 92 + krb5-1-6/src/lib/krb4/g_pw_in_tkt.c | 383 + krb5-1-6/src/lib/krb4/g_pw_tkt.c | 68 + krb5-1-6/src/lib/krb4/g_svc_in_tkt.c | 152 + krb5-1-6/src/lib/krb4/g_tf_fname.c | 67 + krb5-1-6/src/lib/krb4/g_tf_realm.c | 44 + krb5-1-6/src/lib/krb4/g_tkt_svc.c | 174 + krb5-1-6/src/lib/krb4/gethostname.c | 36 + krb5-1-6/src/lib/krb4/getst.c | 40 + krb5-1-6/src/lib/krb4/in_tkt.c | 200 + krb5-1-6/src/lib/krb4/kadm_err.et | 58 + krb5-1-6/src/lib/krb4/kadm_net.c | 392 + krb5-1-6/src/lib/krb4/kadm_stream.c | 325 + krb5-1-6/src/lib/krb4/klog.c | 124 + krb5-1-6/src/lib/krb4/kname_parse.c | 411 + krb5-1-6/src/lib/krb4/kntoln.c | 62 + krb5-1-6/src/lib/krb4/kparse.c | 784 + krb5-1-6/src/lib/krb4/krb4int.h | 125 + krb5-1-6/src/lib/krb4/krb_err.et | 776 + krb5-1-6/src/lib/krb4/kuserok.c | 260 + krb5-1-6/src/lib/krb4/libkrb4.exports | 165 + krb5-1-6/src/lib/krb4/lifetime.c | 62 + krb5-1-6/src/lib/krb4/log.c | 148 + krb5-1-6/src/lib/krb4/mac_glue.c | 48 + krb5-1-6/src/lib/krb4/mac_store.c | 731 + krb5-1-6/src/lib/krb4/mac_store.h | 56 + krb5-1-6/src/lib/krb4/mac_stubs.c | 525 + krb5-1-6/src/lib/krb4/mac_time.c | 152 + krb5-1-6/src/lib/krb4/memcache.c | 891 ++ krb5-1-6/src/lib/krb4/memcache.h | 36 + krb5-1-6/src/lib/krb4/mk_auth.c | 249 + krb5-1-6/src/lib/krb4/mk_err.c | 83 + krb5-1-6/src/lib/krb4/mk_preauth.c | 78 + krb5-1-6/src/lib/krb4/mk_priv.c | 301 + krb5-1-6/src/lib/krb4/mk_req.c | 285 + krb5-1-6/src/lib/krb4/mk_safe.c | 167 + krb5-1-6/src/lib/krb4/month_sname.c | 28 + krb5-1-6/src/lib/krb4/netread.c | 69 + krb5-1-6/src/lib/krb4/netwrite.c | 65 + krb5-1-6/src/lib/krb4/password_to_key.c | 152 + krb5-1-6/src/lib/krb4/pkt_cipher.c | 35 + krb5-1-6/src/lib/krb4/pkt_clen.c | 47 + krb5-1-6/src/lib/krb4/prot_client.c | 370 + krb5-1-6/src/lib/krb4/prot_common.c | 136 + krb5-1-6/src/lib/krb4/prot_kdc.c | 461 + krb5-1-6/src/lib/krb4/put_svc_key.c | 94 + krb5-1-6/src/lib/krb4/rd_err.c | 78 + krb5-1-6/src/lib/krb4/rd_preauth.c | 62 + krb5-1-6/src/lib/krb4/rd_priv.c | 233 + krb5-1-6/src/lib/krb4/rd_req.c | 543 + krb5-1-6/src/lib/krb4/rd_safe.c | 208 + krb5-1-6/src/lib/krb4/rd_svc_key.c | 344 + krb5-1-6/src/lib/krb4/recvauth.c | 308 + krb5-1-6/src/lib/krb4/ren-cyg.sh | 11 + krb5-1-6/src/lib/krb4/ren-pc.bat | 29 + krb5-1-6/src/lib/krb4/ren-pc.sh | 7 + krb5-1-6/src/lib/krb4/ren-pl10.sh | 7 + krb5-1-6/src/lib/krb4/ren.msg | 117 + krb5-1-6/src/lib/krb4/ren2dos.sh | 7 + krb5-1-6/src/lib/krb4/ren2long.sh | 7 + krb5-1-6/src/lib/krb4/save_creds.c | 87 + krb5-1-6/src/lib/krb4/sed-cyg.sh | 13 + krb5-1-6/src/lib/krb4/sed-pc.sh | 11 + krb5-1-6/src/lib/krb4/sed-pl10.sh | 10 + krb5-1-6/src/lib/krb4/send_to_kdc.c | 206 + krb5-1-6/src/lib/krb4/sendauth.c | 282 + krb5-1-6/src/lib/krb4/setenv.c | 164 + krb5-1-6/src/lib/krb4/stime.c | 57 + krb5-1-6/src/lib/krb4/strcasecmp.c | 83 + krb5-1-6/src/lib/krb4/strnlen.c | 50 + krb5-1-6/src/lib/krb4/swab.c | 18 + krb5-1-6/src/lib/krb4/tf_shm.c | 171 + krb5-1-6/src/lib/krb4/tf_util.c | 1097 ++ krb5-1-6/src/lib/krb4/tkt_string.c | 100 + krb5-1-6/src/lib/krb4/unix_glue.c | 40 + krb5-1-6/src/lib/krb4/unix_time.c | 26 + krb5-1-6/src/lib/krb4/vmslink.com | 79 + krb5-1-6/src/lib/krb4/vmsswab.c | 34 + krb5-1-6/src/lib/krb4/win_glue.c | 51 + krb5-1-6/src/lib/krb4/win_store.c | 150 + krb5-1-6/src/lib/krb4/win_time.c | 121 + krb5-1-6/src/lib/krb4_32.def | 86 + krb5-1-6/src/lib/krb5.rc | 44 + krb5-1-6/src/lib/krb5/Makefile.in | 148 + krb5-1-6/src/lib/krb5/asn.1/.saberinit | 4 + krb5-1-6/src/lib/krb5/asn.1/KRB5-asn.py | 436 + krb5-1-6/src/lib/krb5/asn.1/Makefile.in | 174 + krb5-1-6/src/lib/krb5/asn.1/asn1_decode.c | 261 + krb5-1-6/src/lib/krb5/asn.1/asn1_decode.h | 92 + krb5-1-6/src/lib/krb5/asn.1/asn1_encode.c | 297 + krb5-1-6/src/lib/krb5/asn.1/asn1_encode.h | 159 + krb5-1-6/src/lib/krb5/asn.1/asn1_get.c | 118 + krb5-1-6/src/lib/krb5/asn.1/asn1_get.h | 77 + krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.c | 1566 ++ krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.h | 235 + krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.c | 1395 ++ krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.h | 339 + krb5-1-6/src/lib/krb5/asn.1/asn1_make.c | 160 + krb5-1-6/src/lib/krb5/asn.1/asn1_make.h | 134 + krb5-1-6/src/lib/krb5/asn.1/asn1_misc.c | 37 + krb5-1-6/src/lib/krb5/asn.1/asn1_misc.h | 39 + krb5-1-6/src/lib/krb5/asn.1/asn1buf.c | 384 + krb5-1-6/src/lib/krb5/asn.1/asn1buf.h | 231 + krb5-1-6/src/lib/krb5/asn.1/asn1glue.h | 46 + krb5-1-6/src/lib/krb5/asn.1/krb5_decode.c | 1083 ++ krb5-1-6/src/lib/krb5/asn.1/krb5_encode.c | 1014 ++ krb5-1-6/src/lib/krb5/asn.1/krbasn1.h | 81 + krb5-1-6/src/lib/krb5/asn.1/ldap_key_seq.c | 479 + krb5-1-6/src/lib/krb5/ccache/Makefile.in | 213 + krb5-1-6/src/lib/krb5/ccache/cc-int.h | 49 + krb5-1-6/src/lib/krb5/ccache/cc_file.c | 2446 +++ krb5-1-6/src/lib/krb5/ccache/cc_keyring.c | 2075 +++ krb5-1-6/src/lib/krb5/ccache/cc_memory.c | 781 + krb5-1-6/src/lib/krb5/ccache/cc_mslsa.c | 2762 ++++ krb5-1-6/src/lib/krb5/ccache/cc_retr.c | 388 + .../src/lib/krb5/ccache/ccapi/Makefile.in | 26 + krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.c | 1613 ++ krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.h | 155 + .../src/lib/krb5/ccache/ccapi/stdcc_util.c | 1066 ++ .../src/lib/krb5/ccache/ccapi/stdcc_util.h | 47 + krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.c | 100 + krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.h | 203 + krb5-1-6/src/lib/krb5/ccache/ccbase.c | 346 + krb5-1-6/src/lib/krb5/ccache/cccopy.c | 62 + krb5-1-6/src/lib/krb5/ccache/cccursor.c | 330 + krb5-1-6/src/lib/krb5/ccache/ccdefault.c | 114 + krb5-1-6/src/lib/krb5/ccache/ccdefops.c | 50 + krb5-1-6/src/lib/krb5/ccache/ccfns.c | 168 + krb5-1-6/src/lib/krb5/ccache/fcc.h | 36 + krb5-1-6/src/lib/krb5/ccache/scc.h | 101 + krb5-1-6/src/lib/krb5/ccache/ser_cc.c | 202 + krb5-1-6/src/lib/krb5/ccache/t_cc.c | 338 + krb5-1-6/src/lib/krb5/ccache/t_cccursor.c | 265 + krb5-1-6/src/lib/krb5/ccache/t_memory.c | 140 + krb5-1-6/src/lib/krb5/ccache/t_stdio.c | 169 + .../src/lib/krb5/error_tables/Makefile.in | 82 + .../src/lib/krb5/error_tables/asn1_err.et | 15 + krb5-1-6/src/lib/krb5/error_tables/init_ets.c | 50 + .../src/lib/krb5/error_tables/kdb5_err.et | 80 + .../src/lib/krb5/error_tables/krb524_err.et | 34 + .../src/lib/krb5/error_tables/krb5_err.et | 348 + .../src/lib/krb5/error_tables/kv5m_err.et | 90 + krb5-1-6/src/lib/krb5/keytab/Makefile.in | 145 + krb5-1-6/src/lib/krb5/keytab/kt-int.h | 39 + krb5-1-6/src/lib/krb5/keytab/kt_file.c | 1712 +++ krb5-1-6/src/lib/krb5/keytab/kt_srvtab.c | 482 + krb5-1-6/src/lib/krb5/keytab/ktadd.c | 39 + krb5-1-6/src/lib/krb5/keytab/ktbase.c | 244 + krb5-1-6/src/lib/krb5/keytab/ktdefault.c | 45 + krb5-1-6/src/lib/krb5/keytab/ktfns.c | 96 + krb5-1-6/src/lib/krb5/keytab/ktfr_entry.c | 50 + krb5-1-6/src/lib/krb5/keytab/ktremove.c | 39 + krb5-1-6/src/lib/krb5/keytab/read_servi.c | 81 + krb5-1-6/src/lib/krb5/krb/Makefile.in | 1193 ++ krb5-1-6/src/lib/krb5/krb/addr_comp.c | 48 + krb5-1-6/src/lib/krb5/krb/addr_order.c | 63 + krb5-1-6/src/lib/krb5/krb/addr_srch.c | 46 + krb5-1-6/src/lib/krb5/krb/appdefault.c | 166 + krb5-1-6/src/lib/krb5/krb/auth_con.c | 559 + krb5-1-6/src/lib/krb5/krb/auth_con.h | 36 + krb5-1-6/src/lib/krb5/krb/bld_pr_ext.c | 102 + krb5-1-6/src/lib/krb5/krb/bld_princ.c | 110 + krb5-1-6/src/lib/krb5/krb/brand.c | 72 + krb5-1-6/src/lib/krb5/krb/chk_trans.c | 441 + krb5-1-6/src/lib/krb5/krb/chpw.c | 542 + krb5-1-6/src/lib/krb5/krb/cleanup.h | 29 + krb5-1-6/src/lib/krb5/krb/conv_creds.c | 294 + krb5-1-6/src/lib/krb5/krb/conv_princ.c | 354 + krb5-1-6/src/lib/krb5/krb/copy_addrs.c | 139 + krb5-1-6/src/lib/krb5/krb/copy_athctr.c | 81 + krb5-1-6/src/lib/krb5/krb/copy_auth.c | 82 + krb5-1-6/src/lib/krb5/krb/copy_cksum.c | 51 + krb5-1-6/src/lib/krb5/krb/copy_creds.c | 94 + krb5-1-6/src/lib/krb5/krb/copy_data.c | 80 + krb5-1-6/src/lib/krb5/krb/copy_key.c | 51 + krb5-1-6/src/lib/krb5/krb/copy_princ.c | 89 + krb5-1-6/src/lib/krb5/krb/copy_tick.c | 126 + krb5-1-6/src/lib/krb5/krb/cp_key_cnt.c | 47 + krb5-1-6/src/lib/krb5/krb/decode_kdc.c | 77 + krb5-1-6/src/lib/krb5/krb/decrypt_tk.c | 73 + krb5-1-6/src/lib/krb5/krb/deltat.c | 1455 ++ krb5-1-6/src/lib/krb5/krb/enc_helper.c | 50 + krb5-1-6/src/lib/krb5/krb/encode_kdc.c | 128 + krb5-1-6/src/lib/krb5/krb/encrypt_tk.c | 67 + krb5-1-6/src/lib/krb5/krb/free_rtree.c | 41 + krb5-1-6/src/lib/krb5/krb/fwd_tgt.c | 197 + krb5-1-6/src/lib/krb5/krb/gc_frm_kdc.c | 1205 ++ krb5-1-6/src/lib/krb5/krb/gc_via_tkt.c | 344 + krb5-1-6/src/lib/krb5/krb/gen_seqnum.c | 67 + krb5-1-6/src/lib/krb5/krb/gen_subkey.c | 52 + krb5-1-6/src/lib/krb5/krb/get_creds.c | 329 + krb5-1-6/src/lib/krb5/krb/get_in_tkt.c | 1308 ++ krb5-1-6/src/lib/krb5/krb/gic_keytab.c | 219 + krb5-1-6/src/lib/krb5/krb/gic_opt.c | 447 + krb5-1-6/src/lib/krb5/krb/gic_pwd.c | 532 + krb5-1-6/src/lib/krb5/krb/in_tkt_sky.c | 112 + krb5-1-6/src/lib/krb5/krb/init_ctx.c | 579 + krb5-1-6/src/lib/krb5/krb/init_keyblock.c | 41 + krb5-1-6/src/lib/krb5/krb/int-proto.h | 58 + krb5-1-6/src/lib/krb5/krb/kdc_rep_dc.c | 80 + krb5-1-6/src/lib/krb5/krb/kerrs.c | 112 + krb5-1-6/src/lib/krb5/krb/kfree.c | 715 + krb5-1-6/src/lib/krb5/krb/mk_cred.c | 307 + krb5-1-6/src/lib/krb5/krb/mk_error.c | 51 + krb5-1-6/src/lib/krb5/krb/mk_priv.c | 233 + krb5-1-6/src/lib/krb5/krb/mk_rep.c | 96 + krb5-1-6/src/lib/krb5/krb/mk_req.c | 91 + krb5-1-6/src/lib/krb5/krb/mk_req_ext.c | 277 + krb5-1-6/src/lib/krb5/krb/mk_safe.c | 259 + krb5-1-6/src/lib/krb5/krb/parse.c | 285 + krb5-1-6/src/lib/krb5/krb/pr_to_salt.c | 86 + krb5-1-6/src/lib/krb5/krb/preauth.c | 581 + krb5-1-6/src/lib/krb5/krb/preauth2.c | 1656 +++ krb5-1-6/src/lib/krb5/krb/princ_comp.c | 87 + krb5-1-6/src/lib/krb5/krb/rd_cred.c | 247 + krb5-1-6/src/lib/krb5/krb/rd_error.c | 49 + krb5-1-6/src/lib/krb5/krb/rd_priv.c | 272 + krb5-1-6/src/lib/krb5/krb/rd_rep.c | 115 + krb5-1-6/src/lib/krb5/krb/rd_req.c | 117 + krb5-1-6/src/lib/krb5/krb/rd_req_dec.c | 453 + krb5-1-6/src/lib/krb5/krb/rd_safe.c | 275 + krb5-1-6/src/lib/krb5/krb/recvauth.c | 266 + krb5-1-6/src/lib/krb5/krb/send_tgs.c | 309 + krb5-1-6/src/lib/krb5/krb/sendauth.c | 233 + krb5-1-6/src/lib/krb5/krb/ser_actx.c | 563 + krb5-1-6/src/lib/krb5/krb/ser_adata.c | 199 + krb5-1-6/src/lib/krb5/krb/ser_addr.c | 203 + krb5-1-6/src/lib/krb5/krb/ser_auth.c | 350 + krb5-1-6/src/lib/krb5/krb/ser_cksum.c | 202 + krb5-1-6/src/lib/krb5/krb/ser_ctx.c | 637 + krb5-1-6/src/lib/krb5/krb/ser_eblk.c | 258 + krb5-1-6/src/lib/krb5/krb/ser_key.c | 200 + krb5-1-6/src/lib/krb5/krb/ser_princ.c | 181 + krb5-1-6/src/lib/krb5/krb/serialize.c | 278 + krb5-1-6/src/lib/krb5/krb/set_realm.c | 52 + krb5-1-6/src/lib/krb5/krb/srv_dec_tkt.c | 94 + krb5-1-6/src/lib/krb5/krb/srv_rcache.c | 134 + krb5-1-6/src/lib/krb5/krb/str_conv.c | 377 + krb5-1-6/src/lib/krb5/krb/strftime.c | 415 + krb5-1-6/src/lib/krb5/krb/strptime.c | 386 + krb5-1-6/src/lib/krb5/krb/t_deltat.c | 158 + krb5-1-6/src/lib/krb5/krb/t_expand.c | 2 + krb5-1-6/src/lib/krb5/krb/t_kerb.c | 232 + krb5-1-6/src/lib/krb5/krb/t_krb5.conf | 52 + krb5-1-6/src/lib/krb5/krb/t_ref_kerb.out | 19 + krb5-1-6/src/lib/krb5/krb/t_ser.c | 729 + krb5-1-6/src/lib/krb5/krb/t_walk_rtree.c | 58 + krb5-1-6/src/lib/krb5/krb/tgtname.c | 42 + krb5-1-6/src/lib/krb5/krb/transit-tests | 54 + krb5-1-6/src/lib/krb5/krb/unparse.c | 200 + krb5-1-6/src/lib/krb5/krb/v4lifetime.c | 149 + krb5-1-6/src/lib/krb5/krb/valid_times.c | 64 + krb5-1-6/src/lib/krb5/krb/vfy_increds.c | 224 + krb5-1-6/src/lib/krb5/krb/vic_opt.c | 14 + krb5-1-6/src/lib/krb5/krb/walk_rtree.c | 417 + krb5-1-6/src/lib/krb5/krb/x-deltat.y | 229 + krb5-1-6/src/lib/krb5/krb5_libinit.c | 112 + krb5-1-6/src/lib/krb5/krb5_libinit.h | 9 + krb5-1-6/src/lib/krb5/libkrb5.exports | 746 + krb5-1-6/src/lib/krb5/os/Makefile.in | 672 + krb5-1-6/src/lib/krb5/os/accessor.c | 119 + krb5-1-6/src/lib/krb5/os/an_to_ln.c | 831 ++ krb5-1-6/src/lib/krb5/os/c_ustime.c | 117 + krb5-1-6/src/lib/krb5/os/ccdefname.c | 327 + krb5-1-6/src/lib/krb5/os/changepw.c | 400 + krb5-1-6/src/lib/krb5/os/def_realm.c | 193 + krb5-1-6/src/lib/krb5/os/dnsglue.c | 335 + krb5-1-6/src/lib/krb5/os/dnsglue.h | 157 + krb5-1-6/src/lib/krb5/os/dnssrv.c | 185 + krb5-1-6/src/lib/krb5/os/free_hstrl.c | 42 + krb5-1-6/src/lib/krb5/os/free_krbhs.c | 45 + krb5-1-6/src/lib/krb5/os/full_ipadr.c | 86 + krb5-1-6/src/lib/krb5/os/gen_port.c | 49 + krb5-1-6/src/lib/krb5/os/gen_rname.c | 50 + krb5-1-6/src/lib/krb5/os/genaddrs.c | 130 + krb5-1-6/src/lib/krb5/os/get_krbhst.c | 128 + krb5-1-6/src/lib/krb5/os/hostaddr.c | 137 + krb5-1-6/src/lib/krb5/os/hst_realm.c | 493 + krb5-1-6/src/lib/krb5/os/init_os_ctx.c | 507 + krb5-1-6/src/lib/krb5/os/krbfileio.c | 103 + krb5-1-6/src/lib/krb5/os/ktdefname.c | 83 + krb5-1-6/src/lib/krb5/os/kuserok.c | 171 + krb5-1-6/src/lib/krb5/os/localaddr.c | 1565 ++ krb5-1-6/src/lib/krb5/os/locate_kdc.c | 842 ++ krb5-1-6/src/lib/krb5/os/lock_file.c | 139 + krb5-1-6/src/lib/krb5/os/mk_faddr.c | 88 + krb5-1-6/src/lib/krb5/os/net_read.c | 65 + krb5-1-6/src/lib/krb5/os/net_write.c | 61 + krb5-1-6/src/lib/krb5/os/os-proto.h | 74 + krb5-1-6/src/lib/krb5/os/osconfig.c | 46 + krb5-1-6/src/lib/krb5/os/port2ip.c | 84 + krb5-1-6/src/lib/krb5/os/prompter.c | 327 + krb5-1-6/src/lib/krb5/os/promptusr.c | 160 + krb5-1-6/src/lib/krb5/os/read_msg.c | 63 + krb5-1-6/src/lib/krb5/os/read_pwd.c | 297 + krb5-1-6/src/lib/krb5/os/realm_dom.c | 67 + krb5-1-6/src/lib/krb5/os/realm_iter.c | 60 + krb5-1-6/src/lib/krb5/os/ref_std_conf.out | 13 + krb5-1-6/src/lib/krb5/os/send524.c | 107 + krb5-1-6/src/lib/krb5/os/sendto_kdc.c | 1322 ++ krb5-1-6/src/lib/krb5/os/sn2princ.c | 214 + krb5-1-6/src/lib/krb5/os/t_an_to_ln.c | 41 + krb5-1-6/src/lib/krb5/os/t_gifconf.c | 134 + krb5-1-6/src/lib/krb5/os/t_locate_kdc.c | 131 + krb5-1-6/src/lib/krb5/os/t_realm_iter.c | 44 + krb5-1-6/src/lib/krb5/os/t_std_conf.c | 247 + krb5-1-6/src/lib/krb5/os/td_krb5.conf | 19 + krb5-1-6/src/lib/krb5/os/thread_safe.c | 40 + krb5-1-6/src/lib/krb5/os/timeofday.c | 52 + krb5-1-6/src/lib/krb5/os/toffset.c | 115 + krb5-1-6/src/lib/krb5/os/unlck_file.c | 37 + krb5-1-6/src/lib/krb5/os/ustime.c | 66 + krb5-1-6/src/lib/krb5/os/write_msg.c | 47 + krb5-1-6/src/lib/krb5/posix/Makefile.in | 18 + krb5-1-6/src/lib/krb5/posix/syslog.c | 10 + krb5-1-6/src/lib/krb5/rcache/Makefile.in | 124 + krb5-1-6/src/lib/krb5/rcache/README | 82 + krb5-1-6/src/lib/krb5/rcache/RELEASE | 17 + krb5-1-6/src/lib/krb5/rcache/rc-int.h | 77 + krb5-1-6/src/lib/krb5/rcache/rc_base.c | 171 + krb5-1-6/src/lib/krb5/rcache/rc_base.h | 15 + krb5-1-6/src/lib/krb5/rcache/rc_conv.c | 38 + krb5-1-6/src/lib/krb5/rcache/rc_dfl.c | 711 + krb5-1-6/src/lib/krb5/rcache/rc_dfl.h | 56 + krb5-1-6/src/lib/krb5/rcache/rc_io.c | 499 + krb5-1-6/src/lib/krb5/rcache/rc_io.h | 70 + krb5-1-6/src/lib/krb5/rcache/rc_none.c | 88 + krb5-1-6/src/lib/krb5/rcache/rcdef.c | 49 + krb5-1-6/src/lib/krb5/rcache/rcfns.c | 95 + krb5-1-6/src/lib/krb5/rcache/ser_rc.c | 208 + krb5-1-6/src/lib/krb5_32.def | 302 + krb5-1-6/src/lib/rpc/Makefile.in | 549 + krb5-1-6/src/lib/rpc/auth_gss.c | 632 + krb5-1-6/src/lib/rpc/auth_gssapi.c | 812 + krb5-1-6/src/lib/rpc/auth_gssapi_misc.c | 328 + krb5-1-6/src/lib/rpc/auth_none.c | 145 + krb5-1-6/src/lib/rpc/auth_unix.c | 328 + krb5-1-6/src/lib/rpc/authgss_prot.c | 366 + krb5-1-6/src/lib/rpc/authunix_prot.c | 64 + krb5-1-6/src/lib/rpc/bindresvport.c | 83 + krb5-1-6/src/lib/rpc/clnt_generic.c | 115 + krb5-1-6/src/lib/rpc/clnt_perror.c | 345 + krb5-1-6/src/lib/rpc/clnt_raw.c | 268 + krb5-1-6/src/lib/rpc/clnt_simple.c | 129 + krb5-1-6/src/lib/rpc/clnt_tcp.c | 496 + krb5-1-6/src/lib/rpc/clnt_udp.c | 484 + krb5-1-6/src/lib/rpc/dyn.c | 555 + krb5-1-6/src/lib/rpc/dyn.h | 79 + krb5-1-6/src/lib/rpc/dynP.h | 50 + krb5-1-6/src/lib/rpc/dyntest.c | 216 + krb5-1-6/src/lib/rpc/get_myaddress.c | 116 + krb5-1-6/src/lib/rpc/getrpcent.c | 236 + krb5-1-6/src/lib/rpc/getrpcport.c | 66 + krb5-1-6/src/lib/rpc/libgssrpc.exports | 141 + krb5-1-6/src/lib/rpc/pmap_clnt.c | 115 + krb5-1-6/src/lib/rpc/pmap_getmaps.c | 87 + krb5-1-6/src/lib/rpc/pmap_getport.c | 92 + krb5-1-6/src/lib/rpc/pmap_prot.c | 55 + krb5-1-6/src/lib/rpc/pmap_prot2.c | 114 + krb5-1-6/src/lib/rpc/pmap_rmt.c | 417 + krb5-1-6/src/lib/rpc/rpc_callmsg.c | 194 + krb5-1-6/src/lib/rpc/rpc_commondata.c | 47 + krb5-1-6/src/lib/rpc/rpc_dtablesize.c | 62 + krb5-1-6/src/lib/rpc/rpc_prot.c | 293 + krb5-1-6/src/lib/rpc/svc.c | 532 + krb5-1-6/src/lib/rpc/svc_auth.c | 109 + krb5-1-6/src/lib/rpc/svc_auth_gss.c | 732 + krb5-1-6/src/lib/rpc/svc_auth_gssapi.c | 1096 ++ krb5-1-6/src/lib/rpc/svc_auth_none.c | 75 + krb5-1-6/src/lib/rpc/svc_auth_unix.c | 141 + krb5-1-6/src/lib/rpc/svc_raw.c | 160 + krb5-1-6/src/lib/rpc/svc_run.c | 74 + krb5-1-6/src/lib/rpc/svc_simple.c | 149 + krb5-1-6/src/lib/rpc/svc_tcp.c | 504 + krb5-1-6/src/lib/rpc/svc_udp.c | 531 + krb5-1-6/src/lib/rpc/unit-test/Makefile.in | 108 + krb5-1-6/src/lib/rpc/unit-test/client.c | 276 + .../src/lib/rpc/unit-test/config/unix.exp | 125 + .../src/lib/rpc/unit-test/lib/helpers.exp | 236 + .../lib/rpc/unit-test/rpc_test.0/expire.exp | 46 + .../lib/rpc/unit-test/rpc_test.0/fullrun.exp | 95 + .../lib/rpc/unit-test/rpc_test.0/gsserr.exp | 27 + krb5-1-6/src/lib/rpc/unit-test/rpc_test.h | 13 + krb5-1-6/src/lib/rpc/unit-test/rpc_test.x | 30 + .../src/lib/rpc/unit-test/rpc_test_clnt.c | 22 + .../src/lib/rpc/unit-test/rpc_test_setup.sh | 59 + krb5-1-6/src/lib/rpc/unit-test/rpc_test_svc.c | 74 + krb5-1-6/src/lib/rpc/unit-test/server.c | 261 + krb5-1-6/src/lib/rpc/xdr.c | 637 + krb5-1-6/src/lib/rpc/xdr_alloc.c | 151 + krb5-1-6/src/lib/rpc/xdr_array.c | 158 + krb5-1-6/src/lib/rpc/xdr_float.c | 289 + krb5-1-6/src/lib/rpc/xdr_mem.c | 182 + krb5-1-6/src/lib/rpc/xdr_rec.c | 570 + krb5-1-6/src/lib/rpc/xdr_reference.c | 137 + krb5-1-6/src/lib/rpc/xdr_stdio.c | 170 + krb5-1-6/src/lib/win_glue.c | 489 + krb5-1-6/src/lib/xpprof32.def | 28 + krb5-1-6/src/patchlevel.h | 58 + krb5-1-6/src/plugins/kdb/db2/Makefile.in | 159 + krb5-1-6/src/plugins/kdb/db2/adb_openclose.c | 412 + krb5-1-6/src/plugins/kdb/db2/adb_policy.c | 389 + krb5-1-6/src/plugins/kdb/db2/configure.in | 27 + krb5-1-6/src/plugins/kdb/db2/db2.exports | 1 + krb5-1-6/src/plugins/kdb/db2/db2_exp.c | 256 + krb5-1-6/src/plugins/kdb/db2/kdb_compat.h | 81 + krb5-1-6/src/plugins/kdb/db2/kdb_db2.c | 1761 +++ krb5-1-6/src/plugins/kdb/db2/kdb_db2.h | 211 + krb5-1-6/src/plugins/kdb/db2/kdb_xdr.c | 493 + krb5-1-6/src/plugins/kdb/db2/kdb_xdr.h | 34 + .../src/plugins/kdb/db2/libdb2/CHANGELOG.db2 | 123 + .../src/plugins/kdb/db2/libdb2/Makefile.in | 43 + .../src/plugins/kdb/db2/libdb2/Makefile.inc | 10 + krb5-1-6/src/plugins/kdb/db2/libdb2/README | 17 + .../kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB | 2 + .../src/plugins/kdb/db2/libdb2/README.db2 | 41 + .../plugins/kdb/db2/libdb2/btree/Makefile.in | 14 + .../plugins/kdb/db2/libdb2/btree/Makefile.inc | 7 + .../plugins/kdb/db2/libdb2/btree/bt_close.c | 183 + .../plugins/kdb/db2/libdb2/btree/bt_conv.c | 221 + .../plugins/kdb/db2/libdb2/btree/bt_debug.c | 377 + .../plugins/kdb/db2/libdb2/btree/bt_delete.c | 657 + .../src/plugins/kdb/db2/libdb2/btree/bt_get.c | 105 + .../plugins/kdb/db2/libdb2/btree/bt_open.c | 476 + .../kdb/db2/libdb2/btree/bt_overflow.c | 228 + .../plugins/kdb/db2/libdb2/btree/bt_page.c | 100 + .../src/plugins/kdb/db2/libdb2/btree/bt_put.c | 328 + .../plugins/kdb/db2/libdb2/btree/bt_search.c | 297 + .../src/plugins/kdb/db2/libdb2/btree/bt_seq.c | 901 ++ .../plugins/kdb/db2/libdb2/btree/bt_split.c | 828 ++ .../plugins/kdb/db2/libdb2/btree/bt_utils.c | 260 + .../src/plugins/kdb/db2/libdb2/btree/btree.h | 383 + .../src/plugins/kdb/db2/libdb2/btree/extern.h | 110 + .../plugins/kdb/db2/libdb2/clib/Makefile.in | 11 + .../src/plugins/kdb/db2/libdb2/clib/memmove.c | 142 + .../src/plugins/kdb/db2/libdb2/clib/mkstemp.c | 126 + .../plugins/kdb/db2/libdb2/clib/strerror.c | 71 + .../src/plugins/kdb/db2/libdb2/configure.in | 95 + .../src/plugins/kdb/db2/libdb2/db/Makefile.in | 11 + .../plugins/kdb/db2/libdb2/db/Makefile.inc | 5 + krb5-1-6/src/plugins/kdb/db2/libdb2/db/db.c | 99 + .../plugins/kdb/db2/libdb2/docs/btree.3.ps | 366 + .../plugins/kdb/db2/libdb2/docs/dbopen.3.ps | 508 + .../src/plugins/kdb/db2/libdb2/docs/hash.3.ps | 292 + .../kdb/db2/libdb2/docs/hash.usenix.ps | 12209 +++++++++++++++ .../kdb/db2/libdb2/docs/libtp.usenix.ps | 12340 ++++++++++++++++ .../plugins/kdb/db2/libdb2/docs/mpool.3.ps | 320 + .../plugins/kdb/db2/libdb2/docs/recno.3.ps | 341 + .../plugins/kdb/db2/libdb2/hash/Makefile.in | 13 + .../plugins/kdb/db2/libdb2/hash/Makefile.inc | 6 + .../src/plugins/kdb/db2/libdb2/hash/dbm.c | 359 + .../src/plugins/kdb/db2/libdb2/hash/extern.h | 109 + .../src/plugins/kdb/db2/libdb2/hash/hash.c | 1068 ++ .../plugins/kdb/db2/libdb2/hash/hash.c.patch | 109 + .../src/plugins/kdb/db2/libdb2/hash/hash.h | 196 + .../plugins/kdb/db2/libdb2/hash/hash_bigkey.c | 483 + .../plugins/kdb/db2/libdb2/hash/hash_debug.c | 105 + .../plugins/kdb/db2/libdb2/hash/hash_func.c | 201 + .../plugins/kdb/db2/libdb2/hash/hash_log2.c | 55 + .../plugins/kdb/db2/libdb2/hash/hash_page.c | 1387 ++ .../src/plugins/kdb/db2/libdb2/hash/hsearch.c | 107 + .../src/plugins/kdb/db2/libdb2/hash/page.h | 178 + .../plugins/kdb/db2/libdb2/hash/page.h.patch | 42 + .../src/plugins/kdb/db2/libdb2/hash/search.h | 55 + .../kdb/db2/libdb2/include/db-config.h.in | 16 + .../plugins/kdb/db2/libdb2/include/db-dbm.h | 23 + .../plugins/kdb/db2/libdb2/include/db-int.h | 283 + .../plugins/kdb/db2/libdb2/include/db-ndbm.h | 91 + .../plugins/kdb/db2/libdb2/include/db-queue.h | 245 + .../src/plugins/kdb/db2/libdb2/include/db.h | 175 + .../src/plugins/kdb/db2/libdb2/libdb.exports | 99 + .../plugins/kdb/db2/libdb2/man/Makefile.inc | 7 + .../src/plugins/kdb/db2/libdb2/man/db.man.ps | 2295 +++ .../src/plugins/kdb/db2/libdb2/man/db_btree.3 | 246 + .../src/plugins/kdb/db2/libdb2/man/db_hash.3 | 138 + .../src/plugins/kdb/db2/libdb2/man/db_lock.3 | 462 + .../src/plugins/kdb/db2/libdb2/man/db_log.3 | 290 + .../src/plugins/kdb/db2/libdb2/man/db_mpool.3 | 403 + .../src/plugins/kdb/db2/libdb2/man/db_open.3 | 574 + .../src/plugins/kdb/db2/libdb2/man/db_recno.3 | 268 + .../src/plugins/kdb/db2/libdb2/man/db_txn.3 | 373 + .../src/plugins/kdb/db2/libdb2/man/spell.ok | 170 + .../plugins/kdb/db2/libdb2/mpool/Makefile.in | 11 + .../plugins/kdb/db2/libdb2/mpool/Makefile.inc | 5 + .../src/plugins/kdb/db2/libdb2/mpool/README | 7 + .../src/plugins/kdb/db2/libdb2/mpool/mpool.c | 513 + .../src/plugins/kdb/db2/libdb2/mpool/mpool.h | 117 + .../plugins/kdb/db2/libdb2/recno/Makefile.in | 13 + .../plugins/kdb/db2/libdb2/recno/Makefile.inc | 6 + .../src/plugins/kdb/db2/libdb2/recno/extern.h | 72 + .../plugins/kdb/db2/libdb2/recno/rec_close.c | 187 + .../plugins/kdb/db2/libdb2/recno/rec_delete.c | 197 + .../plugins/kdb/db2/libdb2/recno/rec_get.c | 311 + .../plugins/kdb/db2/libdb2/recno/rec_open.c | 243 + .../plugins/kdb/db2/libdb2/recno/rec_put.c | 280 + .../plugins/kdb/db2/libdb2/recno/rec_search.c | 126 + .../plugins/kdb/db2/libdb2/recno/rec_seq.c | 131 + .../plugins/kdb/db2/libdb2/recno/rec_utils.c | 122 + .../src/plugins/kdb/db2/libdb2/recno/recno.h | 39 + .../plugins/kdb/db2/libdb2/test/Makefile.in | 36 + .../src/plugins/kdb/db2/libdb2/test/README | 74 + .../plugins/kdb/db2/libdb2/test/SEQ_TEST/data | 8 + .../plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox | 399 + .../plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c | 85 + .../kdb/db2/libdb2/test/btree.tests/main.c | 832 ++ .../src/plugins/kdb/db2/libdb2/test/dbtest.c | 768 + .../plugins/kdb/db2/libdb2/test/dictionary | 308 + .../kdb/db2/libdb2/test/hash1.tests/Makefile | 43 + .../kdb/db2/libdb2/test/hash1.tests/driver2.c | 114 + .../kdb/db2/libdb2/test/hash1.tests/makedb.sh | 13 + .../kdb/db2/libdb2/test/hash1.tests/tcreat3.c | 105 + .../kdb/db2/libdb2/test/hash1.tests/tdel.c | 122 + .../kdb/db2/libdb2/test/hash1.tests/testit | 154 + .../kdb/db2/libdb2/test/hash1.tests/thash4.c | 131 + .../kdb/db2/libdb2/test/hash1.tests/tread2.c | 105 + .../kdb/db2/libdb2/test/hash1.tests/tseq.c | 88 + .../kdb/db2/libdb2/test/hash1.tests/tverify.c | 107 + .../kdb/db2/libdb2/test/hash2.tests/README | 72 + .../kdb/db2/libdb2/test/hash2.tests/bigtest.c | 76 + .../db2/libdb2/test/hash2.tests/passtest.c | 184 + .../libdb2/test/hash2.tests/passwd/genpass.c | 23 + .../src/plugins/kdb/db2/libdb2/test/run.test | 746 + krb5-1-6/src/plugins/kdb/db2/pol_xdr.c | 89 + krb5-1-6/src/plugins/kdb/db2/policy_db.h | 101 + krb5-1-6/src/plugins/kdb/ldap/Makefile.in | 65 + krb5-1-6/src/plugins/kdb/ldap/kldap.exports | 1 + krb5-1-6/src/plugins/kdb/ldap/ldap_exp.c | 88 + .../src/plugins/kdb/ldap/ldap_util/ChangeLog | 12 + .../plugins/kdb/ldap/ldap_util/Makefile.in | 29 + .../kdb/ldap/ldap_util/kdb5_ldap_list.c | 287 + .../kdb/ldap/ldap_util/kdb5_ldap_list.h | 47 + .../kdb/ldap/ldap_util/kdb5_ldap_policy.c | 881 ++ .../kdb/ldap/ldap_util/kdb5_ldap_policy.h | 37 + .../kdb/ldap/ldap_util/kdb5_ldap_realm.c | 2525 ++++ .../kdb/ldap/ldap_util/kdb5_ldap_realm.h | 61 + .../kdb/ldap/ldap_util/kdb5_ldap_services.c | 2161 +++ .../kdb/ldap/ldap_util/kdb5_ldap_services.h | 71 + .../kdb/ldap/ldap_util/kdb5_ldap_util.M | 934 ++ .../kdb/ldap/ldap_util/kdb5_ldap_util.c | 631 + .../kdb/ldap/ldap_util/kdb5_ldap_util.h | 78 + .../plugins/kdb/ldap/libkdb_ldap/ChangeLog | 37 + .../plugins/kdb/ldap/libkdb_ldap/Makefile.in | 308 + .../plugins/kdb/ldap/libkdb_ldap/configure.in | 36 + .../plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c | 502 + .../plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h | 322 + .../kdb/ldap/libkdb_ldap/kdb_ldap_conn.c | 352 + .../plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c | 228 + .../plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h | 34 + .../kdb/ldap/libkdb_ldap/kerberos.ldif | 763 + .../kdb/ldap/libkdb_ldap/kerberos.schema | 618 + .../kdb/ldap/libkdb_ldap/ldap_create.c | 402 + .../plugins/kdb/ldap/libkdb_ldap/ldap_err.c | 193 + .../plugins/kdb/ldap/libkdb_ldap/ldap_err.h | 12 + .../kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c | 100 + .../kdb/ldap/libkdb_ldap/ldap_handle.c | 274 + .../kdb/ldap/libkdb_ldap/ldap_handle.h | 46 + .../kdb/ldap/libkdb_ldap/ldap_krbcontainer.c | 203 + .../kdb/ldap/libkdb_ldap/ldap_krbcontainer.h | 60 + .../plugins/kdb/ldap/libkdb_ldap/ldap_main.h | 38 + .../plugins/kdb/ldap/libkdb_ldap/ldap_misc.c | 2255 +++ .../plugins/kdb/ldap/libkdb_ldap/ldap_misc.h | 153 + .../kdb/ldap/libkdb_ldap/ldap_principal.c | 517 + .../kdb/ldap/libkdb_ldap/ldap_principal.h | 122 + .../kdb/ldap/libkdb_ldap/ldap_principal2.c | 1288 ++ .../kdb/ldap/libkdb_ldap/ldap_pwd_policy.c | 456 + .../kdb/ldap/libkdb_ldap/ldap_pwd_policy.h | 54 + .../plugins/kdb/ldap/libkdb_ldap/ldap_realm.c | 1490 ++ .../plugins/kdb/ldap/libkdb_ldap/ldap_realm.h | 99 + .../ldap/libkdb_ldap/ldap_service_rights.c | 839 ++ .../kdb/ldap/libkdb_ldap/ldap_service_stash.c | 280 + .../kdb/ldap/libkdb_ldap/ldap_service_stash.h | 55 + .../kdb/ldap/libkdb_ldap/ldap_services.c | 597 + .../kdb/ldap/libkdb_ldap/ldap_services.h | 97 + .../kdb/ldap/libkdb_ldap/ldap_tkt_policy.c | 501 + .../kdb/ldap/libkdb_ldap/ldap_tkt_policy.h | 75 + .../kdb/ldap/libkdb_ldap/libkdb_ldap.exports | 50 + .../plugins/kdb/ldap/libkdb_ldap/princ_xdr.c | 232 + .../plugins/kdb/ldap/libkdb_ldap/princ_xdr.h | 61 + .../src/plugins/locate/python/Makefile.in | 43 + .../src/plugins/locate/python/configure.in | 10 + .../plugins/locate/python/locate-service.py | 77 + .../src/plugins/locate/python/py-locate.c | 313 + .../src/plugins/locate/python/python.exports | 1 + .../plugins/preauth/cksum_body/Makefile.in | 42 + .../preauth/cksum_body/cksum_body.exports | 2 + .../preauth/cksum_body/cksum_body_main.c | 668 + .../plugins/preauth/cksum_body/configure.in | 14 + .../src/plugins/preauth/pkinit/Makefile.in | 109 + .../src/plugins/preauth/pkinit/configure.in | 19 + krb5-1-6/src/plugins/preauth/pkinit/pkcs11.h | 1357 ++ .../src/plugins/preauth/pkinit/pkinit.exports | 2 + krb5-1-6/src/plugins/preauth/pkinit/pkinit.h | 354 + .../plugins/preauth/pkinit/pkinit_accessor.c | 118 + .../plugins/preauth/pkinit/pkinit_accessor.h | 83 + .../src/plugins/preauth/pkinit/pkinit_clnt.c | 1492 ++ .../plugins/preauth/pkinit/pkinit_crypto.h | 623 + .../preauth/pkinit/pkinit_crypto_openssl.c | 5612 +++++++ .../preauth/pkinit/pkinit_crypto_openssl.h | 265 + .../plugins/preauth/pkinit/pkinit_identity.c | 668 + .../src/plugins/preauth/pkinit/pkinit_lib.c | 477 + .../plugins/preauth/pkinit/pkinit_matching.c | 830 ++ .../plugins/preauth/pkinit/pkinit_profile.c | 376 + .../src/plugins/preauth/pkinit/pkinit_srv.c | 1399 ++ krb5-1-6/src/plugins/preauth/wpse/Makefile.in | 42 + .../src/plugins/preauth/wpse/configure.in | 14 + .../src/plugins/preauth/wpse/wpse.exports | 2 + krb5-1-6/src/plugins/preauth/wpse/wpse_main.c | 471 + krb5-1-6/src/prototype/getopt.c | 29 + krb5-1-6/src/prototype/prototype.c | 30 + krb5-1-6/src/prototype/prototype.h | 33 + krb5-1-6/src/slave/Makefile.in | 62 + krb5-1-6/src/slave/kprop.M | 67 + krb5-1-6/src/slave/kprop.c | 756 + krb5-1-6/src/slave/kprop.h | 38 + krb5-1-6/src/slave/kpropd.M | 138 + krb5-1-6/src/slave/kpropd.c | 992 ++ krb5-1-6/src/slave/kslave_update | 30 + krb5-1-6/src/t_krbconf | 38 + krb5-1-6/src/tests/Makefile.in | 68 + krb5-1-6/src/tests/asn.1/Makefile.in | 106 + krb5-1-6/src/tests/asn.1/README | 28 + krb5-1-6/src/tests/asn.1/debug.h | 20 + krb5-1-6/src/tests/asn.1/krb5_decode_test.c | 904 ++ krb5-1-6/src/tests/asn.1/krb5_encode_test.c | 681 + krb5-1-6/src/tests/asn.1/ktest.c | 1291 ++ krb5-1-6/src/tests/asn.1/ktest.h | 204 + krb5-1-6/src/tests/asn.1/ktest_equal.c | 669 + krb5-1-6/src/tests/asn.1/ktest_equal.h | 93 + krb5-1-6/src/tests/asn.1/reference_encode.out | 53 + krb5-1-6/src/tests/asn.1/trval.c | 840 ++ krb5-1-6/src/tests/asn.1/trval_reference.out | 1198 ++ krb5-1-6/src/tests/asn.1/utility.c | 125 + krb5-1-6/src/tests/asn.1/utility.h | 31 + krb5-1-6/src/tests/configure.in | 30 + krb5-1-6/src/tests/create/Makefile.in | 35 + krb5-1-6/src/tests/create/kdb5_mkdums.M | 141 + krb5-1-6/src/tests/create/kdb5_mkdums.c | 434 + krb5-1-6/src/tests/dejagnu/Makefile.in | 54 + krb5-1-6/src/tests/dejagnu/config/default.exp | 2721 ++++ .../src/tests/dejagnu/krb-root/rlogin.exp | 320 + .../src/tests/dejagnu/krb-root/telnet.exp | 449 + .../tests/dejagnu/krb-standalone/gssapi.exp | 328 + .../tests/dejagnu/krb-standalone/gssftp.exp | 457 + .../tests/dejagnu/krb-standalone/kadmin.exp | 1075 ++ .../tests/dejagnu/krb-standalone/pwhist.exp | 215 + .../src/tests/dejagnu/krb-standalone/rcp.exp | 232 + .../src/tests/dejagnu/krb-standalone/rsh.exp | 294 + .../tests/dejagnu/krb-standalone/sample.exp | 210 + .../dejagnu/krb-standalone/standalone.exp | 277 + .../tests/dejagnu/krb-standalone/v4gssftp.exp | 505 + .../dejagnu/krb-standalone/v4krb524d.exp | 168 + .../dejagnu/krb-standalone/v4standalone.exp | 95 + krb5-1-6/src/tests/dejagnu/t_inetd.c | 139 + krb5-1-6/src/tests/dump.c | 43 + krb5-1-6/src/tests/gss-threads/Makefile.in | 54 + krb5-1-6/src/tests/gss-threads/README | 165 + krb5-1-6/src/tests/gss-threads/gss-client.c | 883 ++ krb5-1-6/src/tests/gss-threads/gss-misc.c | 425 + krb5-1-6/src/tests/gss-threads/gss-misc.h | 60 + krb5-1-6/src/tests/gss-threads/gss-server.c | 850 ++ krb5-1-6/src/tests/gssapi/Makefile.in | 27 + krb5-1-6/src/tests/gssapi/t_imp_name.c | 150 + krb5-1-6/src/tests/hammer/Makefile.in | 33 + krb5-1-6/src/tests/hammer/kdc5_hammer.c | 530 + krb5-1-6/src/tests/hammer/pp.c | 28 + krb5-1-6/src/tests/misc/Makefile.in | 35 + krb5-1-6/src/tests/misc/test_getpw.c | 25 + krb5-1-6/src/tests/misc/test_getsockname.c | 91 + krb5-1-6/src/tests/misc/test_nfold.c | 65 + krb5-1-6/src/tests/resolve/Makefile.in | 44 + krb5-1-6/src/tests/resolve/addrinfo-test.c | 303 + .../src/tests/resolve/fake-addrinfo-test.c | 2 + krb5-1-6/src/tests/resolve/resolve.c | 170 + krb5-1-6/src/tests/shlib/Makefile.in | 37 + krb5-1-6/src/tests/shlib/t_loader.c | 372 + krb5-1-6/src/tests/test1.c | 195 + krb5-1-6/src/tests/threads/Makefile.in | 44 + krb5-1-6/src/tests/threads/prof1.c | 79 + krb5-1-6/src/tests/threads/t_rcache.c | 174 + krb5-1-6/src/tests/verify/Makefile.in | 34 + krb5-1-6/src/tests/verify/kdb5_verify.c | 471 + krb5-1-6/src/tests/verify/pkey.c | 24 + krb5-1-6/src/util/Makefile.in | 61 + krb5-1-6/src/util/ac_check_krb5.m4 | 58 + krb5-1-6/src/util/check-ac-syms | 33 + krb5-1-6/src/util/def-check.pl | 259 + krb5-1-6/src/util/depfix.pl | 228 + krb5-1-6/src/util/et/ISSUES | 60 + krb5-1-6/src/util/et/Makefile.in | 264 + krb5-1-6/src/util/et/com_err.3 | 96 + krb5-1-6/src/util/et/com_err.c | 175 + krb5-1-6/src/util/et/com_err.h | 72 + krb5-1-6/src/util/et/com_err.texinfo | 555 + krb5-1-6/src/util/et/compile_et.1 | 79 + krb5-1-6/src/util/et/compile_et.c | 348 + krb5-1-6/src/util/et/compile_et.sh | 24 + krb5-1-6/src/util/et/compiler.h | 14 + krb5-1-6/src/util/et/config_script | 22 + krb5-1-6/src/util/et/error_message.c | 365 + krb5-1-6/src/util/et/error_table.h | 39 + krb5-1-6/src/util/et/error_table.y | 231 + krb5-1-6/src/util/et/et.exp | 8 + krb5-1-6/src/util/et/et.pbexp | 10 + krb5-1-6/src/util/et/et1.et | 11 + krb5-1-6/src/util/et/et2.et | 11 + krb5-1-6/src/util/et/et_c.awk | 213 + krb5-1-6/src/util/et/et_c.pl | 289 + krb5-1-6/src/util/et/et_h.awk | 168 + krb5-1-6/src/util/et/et_h.pl | 234 + krb5-1-6/src/util/et/et_lex.lex.l | 23 + krb5-1-6/src/util/et/et_name.c | 56 + krb5-1-6/src/util/et/init_et.c | 108 + krb5-1-6/src/util/et/internal.h | 15 + krb5-1-6/src/util/et/libcom_err.exports | 9 + krb5-1-6/src/util/et/mit-sipb-copyright.h | 22 + krb5-1-6/src/util/et/t_com_err.c | 143 + krb5-1-6/src/util/et/test1.et | 69 + krb5-1-6/src/util/et/test2.et | 9 + krb5-1-6/src/util/et/test_et.c | 76 + krb5-1-6/src/util/et/texinfo.tex | 2077 +++ krb5-1-6/src/util/et/vfprintf.c | 50 + krb5-1-6/src/util/exitsleep.c | 47 + krb5-1-6/src/util/export-check.pl | 79 + krb5-1-6/src/util/getsyms | 63 + krb5-1-6/src/util/getsyms.sed | 42 + krb5-1-6/src/util/kbuild | 168 + krb5-1-6/src/util/kfrags/athena.conf | 1 + krb5-1-6/src/util/kfrags/base.conf | 16 + krb5-1-6/src/util/kfrags/cns.conf | 1 + krb5-1-6/src/util/kfrags/gcc.conf | 2 + krb5-1-6/src/util/kfrags/ranlib.conf | 1 + krb5-1-6/src/util/kfrags/shared.conf | 4 + krb5-1-6/src/util/kfrags/sunpro.conf | 1 + krb5-1-6/src/util/kfrags/svr4.conf | 1 + krb5-1-6/src/util/kfrags/ucb.conf | 2 + krb5-1-6/src/util/lndir | 103 + krb5-1-6/src/util/makedepend/cpp.ed | 75 + krb5-1-6/src/util/makedepend/cppsetup.c | 242 + krb5-1-6/src/util/makedepend/def.h | 135 + krb5-1-6/src/util/makedepend/ifparser.c | 451 + krb5-1-6/src/util/makedepend/ifparser.h | 76 + krb5-1-6/src/util/makedepend/include.c | 295 + krb5-1-6/src/util/makedepend/main.c | 688 + krb5-1-6/src/util/makedepend/mkdepend.man | 370 + krb5-1-6/src/util/makedepend/parse.c | 567 + krb5-1-6/src/util/makedepend/pr.c | 127 + krb5-1-6/src/util/mkrel | 224 + krb5-1-6/src/util/profile/Makefile.in | 197 + krb5-1-6/src/util/profile/argv_parse.c | 168 + krb5-1-6/src/util/profile/argv_parse.h | 43 + krb5-1-6/src/util/profile/dosshell.ini | 537 + krb5-1-6/src/util/profile/krb5.conf | 57 + krb5-1-6/src/util/profile/libprofile.exports | 55 + krb5-1-6/src/util/profile/prof_FSp_glue.c | 91 + krb5-1-6/src/util/profile/prof_err.et | 66 + krb5-1-6/src/util/profile/prof_file.c | 607 + krb5-1-6/src/util/profile/prof_get.c | 462 + krb5-1-6/src/util/profile/prof_init.c | 402 + krb5-1-6/src/util/profile/prof_int.h | 244 + krb5-1-6/src/util/profile/prof_parse.c | 494 + krb5-1-6/src/util/profile/prof_set.c | 286 + krb5-1-6/src/util/profile/prof_test1 | 154 + krb5-1-6/src/util/profile/prof_tree.c | 714 + krb5-1-6/src/util/profile/profile.5 | 71 + krb5-1-6/src/util/profile/profile.exp | 35 + krb5-1-6/src/util/profile/profile.hin | 125 + krb5-1-6/src/util/profile/profile.pbexp | 33 + krb5-1-6/src/util/profile/profile.swg | 258 + krb5-1-6/src/util/profile/profile_tcl.c | 2159 +++ krb5-1-6/src/util/profile/prtest.in | 36 + krb5-1-6/src/util/profile/prtest.script | 11 + krb5-1-6/src/util/profile/test.ini | 47 + krb5-1-6/src/util/profile/test_parse.c | 54 + krb5-1-6/src/util/profile/test_profile.c | 169 + krb5-1-6/src/util/reconf | 106 + krb5-1-6/src/util/send-pr/COPYING | 339 + krb5-1-6/src/util/send-pr/INSTALL | 83 + krb5-1-6/src/util/send-pr/MANIFEST | 20 + krb5-1-6/src/util/send-pr/Makefile.in | 48 + krb5-1-6/src/util/send-pr/README | 43 + krb5-1-6/src/util/send-pr/categories | 11 + krb5-1-6/src/util/send-pr/install-sid.sh | 86 + krb5-1-6/src/util/send-pr/send-pr.1 | 289 + krb5-1-6/src/util/send-pr/send-pr.sh | 542 + krb5-1-6/src/util/ss/Makefile.in | 227 + krb5-1-6/src/util/ss/cmd_tbl.lex.l | 81 + krb5-1-6/src/util/ss/config_script | 28 + krb5-1-6/src/util/ss/configure.in | 17 + krb5-1-6/src/util/ss/copyright.h | 22 + krb5-1-6/src/util/ss/ct.y | 81 + krb5-1-6/src/util/ss/ct_c_awk.in | 77 + krb5-1-6/src/util/ss/ct_c_sed.in | 161 + krb5-1-6/src/util/ss/data.c | 16 + krb5-1-6/src/util/ss/error.c | 69 + krb5-1-6/src/util/ss/execute_cmd.c | 220 + krb5-1-6/src/util/ss/help.c | 154 + krb5-1-6/src/util/ss/invocation.c | 78 + krb5-1-6/src/util/ss/list_rqs.c | 120 + krb5-1-6/src/util/ss/listen.c | 169 + krb5-1-6/src/util/ss/mit-sipb-copyright.h | 22 + krb5-1-6/src/util/ss/mk_cmds.c | 102 + krb5-1-6/src/util/ss/mk_cmds.sh | 29 + krb5-1-6/src/util/ss/options.c | 32 + krb5-1-6/src/util/ss/pager.c | 108 + krb5-1-6/src/util/ss/parse.c | 135 + krb5-1-6/src/util/ss/prompt.c | 28 + krb5-1-6/src/util/ss/request_tbl.c | 65 + krb5-1-6/src/util/ss/requests.c | 47 + krb5-1-6/src/util/ss/ss.h | 67 + krb5-1-6/src/util/ss/ss_err.et | 39 + krb5-1-6/src/util/ss/ss_internal.h | 122 + krb5-1-6/src/util/ss/std_rqs.ct | 46 + krb5-1-6/src/util/ss/test_ss.c | 99 + krb5-1-6/src/util/ss/utils.c | 136 + krb5-1-6/src/util/support/Makefile.in | 106 + krb5-1-6/src/util/support/cache-addrinfo.h | 128 + krb5-1-6/src/util/support/errors.c | 166 + krb5-1-6/src/util/support/fake-addrinfo.c | 1358 ++ krb5-1-6/src/util/support/gmt_mktime.c | 127 + krb5-1-6/src/util/support/init-addrinfo.c | 70 + .../src/util/support/libkrb5support.exports | 34 + krb5-1-6/src/util/support/plugins.c | 646 + krb5-1-6/src/util/support/supp-int.h | 36 + krb5-1-6/src/util/support/threads.c | 652 + krb5-1-6/src/util/valgrind-suppressions | 16 + krb5-1-6/src/util/windows/Makefile.in | 16 + krb5-1-6/src/util/windows/getopt.c | 152 + krb5-1-6/src/util/windows/getopt.h | 33 + krb5-1-6/src/util/windows/getopt_long.c | 236 + krb5-1-6/src/util/windows/libecho.c | 76 + krb5-1-6/src/wconfig.c | 219 + krb5-1-6/src/windows/Makefile.in | 63 + krb5-1-6/src/windows/README | 305 + krb5-1-6/src/windows/build/BKWconfig.xml | 172 + krb5-1-6/src/windows/build/Logger.pm | 87 + .../src/windows/build/bkw-automation.html | 356 + krb5-1-6/src/windows/build/bkw.pl | 690 + krb5-1-6/src/windows/build/bootstrap.xml | 19 + .../src/windows/build/commandandcontrol.pl | 170 + krb5-1-6/src/windows/build/copyfiles.pl | 137 + krb5-1-6/src/windows/build/copyfiles.xml | 221 + .../src/windows/build/corebinaryfiles.xml | 85 + .../src/windows/build/css/main-action(1).css | 54 + .../src/windows/build/css/main-action.css | 1032 ++ krb5-1-6/src/windows/build/makeZip.pl | 84 + krb5-1-6/src/windows/build/pruneFiles.pl | 36 + krb5-1-6/src/windows/build/repository1.pl | 90 + krb5-1-6/src/windows/build/sdkfiles.xml | 23 + krb5-1-6/src/windows/build/signFiles.pl | 27 + krb5-1-6/src/windows/build/site-local.sed | 2 + krb5-1-6/src/windows/build/tee.pl | 79 + krb5-1-6/src/windows/build/which.pl | 69 + krb5-1-6/src/windows/build/zipXML.pl | 21 + krb5-1-6/src/windows/cns/Makefile.in | 76 + krb5-1-6/src/windows/cns/clock00.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock05.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock10.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock15.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock20.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock25.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock30.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock35.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock40.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock45.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock50.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock55.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clock60.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clockexp.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/clocktkt.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/cns-help.doc | Bin 0 -> 22528 bytes krb5-1-6/src/windows/cns/cns-help.hlp | Bin 0 -> 11944 bytes krb5-1-6/src/windows/cns/cns-help.hpj | 133 + krb5-1-6/src/windows/cns/cns.c | 2208 +++ krb5-1-6/src/windows/cns/cns.h | 249 + krb5-1-6/src/windows/cns/cns.ico | Bin 0 -> 1086 bytes krb5-1-6/src/windows/cns/cns_reg.c | 230 + krb5-1-6/src/windows/cns/cns_reg.h | 33 + krb5-1-6/src/windows/cns/cnsres4.rc | 108 + krb5-1-6/src/windows/cns/cnsres5.rc | 215 + krb5-1-6/src/windows/cns/debug.c | 91 + krb5-1-6/src/windows/cns/heap.c | 33 + krb5-1-6/src/windows/cns/kerbnet.doc | Bin 0 -> 22528 bytes krb5-1-6/src/windows/cns/kerbnet.hlp | Bin 0 -> 16334 bytes krb5-1-6/src/windows/cns/kerbnet.hpj | 133 + krb5-1-6/src/windows/cns/kpasswd.c | 90 + krb5-1-6/src/windows/cns/krb5.def | 9 + krb5-1-6/src/windows/cns/krbini.h | 37 + krb5-1-6/src/windows/cns/options.c | 232 + krb5-1-6/src/windows/cns/password.c | 323 + krb5-1-6/src/windows/cns/tktlist.c | 442 + krb5-1-6/src/windows/cns/tktlist.h | 27 + krb5-1-6/src/windows/gina/Makefile.in | 36 + krb5-1-6/src/windows/gina/gina.def | 21 + krb5-1-6/src/windows/gina/ginastub.c | 365 + krb5-1-6/src/windows/gina/ginastub.h | 39 + krb5-1-6/src/windows/gss/Makefile.in | 52 + krb5-1-6/src/windows/gss/gss-client.c | 615 + krb5-1-6/src/windows/gss/gss-misc.c | 429 + krb5-1-6/src/windows/gss/gss-misc.h | 60 + krb5-1-6/src/windows/gss/gss.c | 722 + krb5-1-6/src/windows/gss/gss.def | 15 + krb5-1-6/src/windows/gss/gss.h | 43 + krb5-1-6/src/windows/gss/gss.ico | Bin 0 -> 766 bytes krb5-1-6/src/windows/gss/gss.rc | 148 + krb5-1-6/src/windows/gss/resource.h | 50 + krb5-1-6/src/windows/gss/ver_serv.txt | 11 + krb5-1-6/src/windows/identity/Makefile | 214 + krb5-1-6/src/windows/identity/apiversion.txt | 367 + krb5-1-6/src/windows/identity/config/Makefile | 147 + .../src/windows/identity/config/Makefile.w2k | 306 + .../src/windows/identity/config/Makefile.w32 | 344 + krb5-1-6/src/windows/identity/config/ccsv.pl | 134 + .../src/windows/identity/config/csvschema.cfg | 67 + .../identity/config/netidmgr_intver.h.in | 47 + .../identity/config/netidmgr_version.h.in | 63 + krb5-1-6/src/windows/identity/doc/Makefile | 71 + .../windows/identity/doc/cred_aquisition.h | 325 + .../windows/identity/doc/cred_data_types.h | 264 + krb5-1-6/src/windows/identity/doc/cred_main.h | 36 + krb5-1-6/src/windows/identity/doc/cred_msgs.h | 123 + .../windows/identity/doc/cred_prop_pages.h | 180 + .../src/windows/identity/doc/doxyfile.cfg | 1259 ++ krb5-1-6/src/windows/identity/doc/footer.html | 21 + krb5-1-6/src/windows/identity/doc/header.html | 6 + .../doc/images/credview-select-outline.jpg | Bin 0 -> 16084 bytes .../identity/doc/images/khimaira_logo.png | Bin 0 -> 3970 bytes .../doc/images/khimaira_logo_small.png | Bin 0 -> 3970 bytes .../doc/images/modules_plugins_krb5.png | Bin 0 -> 22193 bytes krb5-1-6/src/windows/identity/doc/main_page.h | 174 + .../src/windows/identity/doc/netidmgr.doc | Bin 0 -> 2042368 bytes .../src/windows/identity/doc/netidmgr.pdf | Bin 0 -> 1565851 bytes .../windows/identity/doc/plugin_framework.h | 241 + .../src/windows/identity/doc/plugin_locale.h | 109 + .../src/windows/identity/doc/plugin_main.h | 115 + .../windows/identity/doc/plugin_structure.h | 55 + .../src/windows/identity/doc/stylesheet.css | 387 + .../src/windows/identity/doc/ui_actions.h | 30 + .../src/windows/identity/doc/ui_context.h | 188 + krb5-1-6/src/windows/identity/doc/ui_main.h | 36 + krb5-1-6/src/windows/identity/doc/ui_menus.h | 30 + krb5-1-6/src/windows/identity/help/Index.hhk | 9 + krb5-1-6/src/windows/identity/help/Makefile | 41 + .../identity/help/html/about_netidmgr.htm | 57 + .../windows/identity/help/html/act_chpw.htm | 35 + .../identity/help/html/act_destroy_creds.htm | 36 + .../identity/help/html/act_import_creds.htm | 31 + .../identity/help/html/act_new_creds.htm | 118 + .../identity/help/html/act_renew_creds.htm | 40 + .../identity/help/html/act_set_default.htm | 30 + .../src/windows/identity/help/html/bugs.htm | 33 + .../identity/help/html/cmdline_netidmgr.htm | 50 + .../identity/help/html/concept_cred_pro.htm | 38 + .../identity/help/html/concept_credential.htm | 31 + .../identity/help/html/concept_ident_pro.htm | 32 + .../identity/help/html/concept_identity.htm | 35 + .../windows/identity/help/html/concepts.htm | 48 + .../windows/identity/help/html/copyright.htm | 48 + .../src/windows/identity/help/html/howdoi.htm | 45 + .../help/html/images/appicon_empty.png | Bin 0 -> 878 bytes .../help/html/images/appicon_expired.png | Bin 0 -> 1071 bytes .../help/html/images/appicon_good.png | Bin 0 -> 1065 bytes .../help/html/images/appicon_warnexp.png | Bin 0 -> 1036 bytes .../help/html/images/appicon_warning.png | Bin 0 -> 1064 bytes .../help/html/images/flag-critical.bmp | Bin 0 -> 822 bytes .../help/html/images/flag-warning.bmp | Bin 0 -> 822 bytes .../help/html/images/flag_expired.bmp | Bin 0 -> 774 bytes .../help/html/images/flag_renewable.bmp | Bin 0 -> 1334 bytes .../identity/help/html/images/id-sm.bmp | Bin 0 -> 822 bytes .../identity/help/html/images/logo.jpg | Bin 0 -> 2014 bytes .../identity/help/html/images/logo_shade.jpg | Bin 0 -> 1641 bytes .../html/images/notification_icon_menu.png | Bin 0 -> 8069 bytes .../help/html/images/screen_app_icon.png | Bin 0 -> 10789 bytes .../help/html/images/screen_chng_pwd.png | Bin 0 -> 10508 bytes .../html/images/screen_config_appearance.png | Bin 0 -> 20195 bytes .../images/screen_config_cred_provider.png | Bin 0 -> 26005 bytes .../html/images/screen_config_general.png | Bin 0 -> 30809 bytes .../html/images/screen_config_global_krb4.png | Bin 0 -> 20681 bytes .../html/images/screen_config_global_krb5.png | Bin 0 -> 21934 bytes .../help/html/images/screen_config_ident.png | Bin 0 -> 26360 bytes .../html/images/screen_config_ident_krb4.png | Bin 0 -> 18158 bytes .../html/images/screen_config_ident_krb5.png | Bin 0 -> 22456 bytes .../images/screen_config_ident_provider.png | Bin 0 -> 28809 bytes .../help/html/images/screen_config_idents.png | Bin 0 -> 23875 bytes .../images/screen_config_notifications.png | Bin 0 -> 17223 bytes .../images/screen_config_plug_in_krb4.png | Bin 0 -> 19313 bytes .../images/screen_config_plug_in_krb5.png | Bin 0 -> 21145 bytes .../screen_config_plug_in_krb5_ccache.png | Bin 0 -> 18848 bytes .../screen_config_plug_in_krb5_realm.png | Bin 0 -> 25097 bytes .../html/images/screen_config_plug_ins.png | Bin 0 -> 23714 bytes .../help/html/images/screen_main_wnd.png | Bin 0 -> 49149 bytes .../html/images/screen_main_wnd_basic.png | Bin 0 -> 24630 bytes .../help/html/images/screen_menu_bar.png | Bin 0 -> 871 bytes .../html/images/screen_menu_credential.png | Bin 0 -> 9870 bytes .../help/html/images/screen_menu_file.png | Bin 0 -> 2952 bytes .../help/html/images/screen_menu_help.png | Bin 0 -> 5812 bytes .../help/html/images/screen_menu_options.png | Bin 0 -> 4877 bytes .../help/html/images/screen_menu_view.png | Bin 0 -> 6386 bytes .../html/images/screen_menu_view_cols.png | Bin 0 -> 14875 bytes .../help/html/images/screen_new_creds.png | Bin 0 -> 11571 bytes .../html/images/screen_new_creds_err01.png | Bin 0 -> 11757 bytes .../help/html/images/screen_new_creds_exp.png | Bin 0 -> 23631 bytes .../help/html/images/screen_tb_standard.png | Bin 0 -> 10327 bytes .../help/html/images/screen_tray_icon.png | Bin 0 -> 5846 bytes .../help/html/images/wdg_collapsed_hi.bmp | Bin 0 -> 774 bytes .../help/html/images/wdg_expanded_hi.bmp | Bin 0 -> 774 bytes .../help/html/images/wdg_stick_hi.bmp | Bin 0 -> 774 bytes .../help/html/images/wdg_stuck_hi.bmp | Bin 0 -> 774 bytes .../windows/identity/help/html/menu_all.htm | 41 + .../identity/help/html/menu_credential.htm | 81 + .../windows/identity/help/html/menu_file.htm | 45 + .../windows/identity/help/html/menu_help.htm | 54 + .../identity/help/html/menu_options.htm | 65 + .../windows/identity/help/html/menu_view.htm | 99 + .../src/windows/identity/help/html/nidmgr.css | 122 + .../identity/help/html/tb_standard.htm | 80 + .../windows/identity/help/html/template.htm | 11 + .../windows/identity/help/html/use_config.htm | 306 + .../windows/identity/help/html/use_icon.htm | 74 + .../windows/identity/help/html/use_layout.htm | 91 + .../windows/identity/help/html/use_start.htm | 70 + .../src/windows/identity/help/html/using.htm | 58 + .../windows/identity/help/html/welcome.htm | 130 + .../windows/identity/help/html/wnd_main.htm | 114 + krb5-1-6/src/windows/identity/help/khhelp.h | 33 + .../src/windows/identity/help/netidmgr.hhp | 35 + krb5-1-6/src/windows/identity/help/popups.txt | 1 + .../windows/identity/help/popups_newcreds.txt | 30 + .../windows/identity/help/popups_password.txt | 19 + krb5-1-6/src/windows/identity/help/toc.hhc | 144 + .../src/windows/identity/include/Makefile | 38 + .../src/windows/identity/include/khdefs.h | 243 + .../src/windows/identity/include/kherror.h | 185 + .../src/windows/identity/include/khlist.h | 214 + .../src/windows/identity/include/khmsgtypes.h | 817 + .../src/windows/identity/include/netidmgr.h | 43 + .../src/windows/identity/kconfig/Makefile | 51 + krb5-1-6/src/windows/identity/kconfig/api.c | 2661 ++++ .../src/windows/identity/kconfig/kconfig.h | 960 ++ .../identity/kconfig/kconfiginternal.h | 131 + .../windows/identity/kconfig/kconfigmain.c | 37 + .../src/windows/identity/kconfig/registry.c | 28 + .../windows/identity/kconfig/test/utiltest.c | 207 + .../src/windows/identity/kcreddb/Makefile | 53 + .../src/windows/identity/kcreddb/attrib.c | 878 ++ .../src/windows/identity/kcreddb/attrib.h | 55 + krb5-1-6/src/windows/identity/kcreddb/buf.c | 391 + krb5-1-6/src/windows/identity/kcreddb/buf.h | 78 + .../src/windows/identity/kcreddb/credential.c | 1092 ++ .../src/windows/identity/kcreddb/credential.h | 71 + .../src/windows/identity/kcreddb/credset.c | 1166 ++ .../src/windows/identity/kcreddb/credset.h | 75 + .../src/windows/identity/kcreddb/credtype.c | 408 + .../src/windows/identity/kcreddb/credtype.h | 55 + .../src/windows/identity/kcreddb/identity.c | 1599 ++ .../src/windows/identity/kcreddb/identity.h | 60 + krb5-1-6/src/windows/identity/kcreddb/init.c | 91 + .../windows/identity/kcreddb/kcdbconfig.csv | 15 + .../src/windows/identity/kcreddb/kcreddb.h | 3329 +++++ .../identity/kcreddb/kcreddbinternal.h | 63 + .../windows/identity/kcreddb/kcreddbmain.c | 40 + .../identity/kcreddb/lang/en_us/kcredres.rc | 130 + .../src/windows/identity/kcreddb/langres.h | 48 + .../src/windows/identity/kcreddb/resource.h | 27 + krb5-1-6/src/windows/identity/kcreddb/type.c | 1386 ++ krb5-1-6/src/windows/identity/kcreddb/type.h | 216 + krb5-1-6/src/windows/identity/kherr/Makefile | 44 + krb5-1-6/src/windows/identity/kherr/kherr.c | 1580 ++ krb5-1-6/src/windows/identity/kherr/kherr.h | 1126 ++ .../windows/identity/kherr/kherrinternal.h | 74 + .../src/windows/identity/kherr/kherrmain.c | 52 + krb5-1-6/src/windows/identity/kmm/Makefile | 55 + krb5-1-6/src/windows/identity/kmm/kmm.c | 192 + krb5-1-6/src/windows/identity/kmm/kmm.h | 1068 ++ .../src/windows/identity/kmm/kmm_module.c | 676 + .../src/windows/identity/kmm/kmm_plugin.c | 414 + krb5-1-6/src/windows/identity/kmm/kmm_reg.c | 336 + .../src/windows/identity/kmm/kmm_registrar.c | 1034 ++ .../src/windows/identity/kmm/kmmconfig.csv | 47 + .../src/windows/identity/kmm/kmminternal.h | 261 + krb5-1-6/src/windows/identity/kmm/kmmmain.c | 161 + krb5-1-6/src/windows/identity/kmm/kplugin.h | 146 + .../src/windows/identity/kmm/lang/kmm_msgs.mc | 259 + krb5-1-6/src/windows/identity/kmq/Makefile | 49 + krb5-1-6/src/windows/identity/kmq/consumer.c | 572 + krb5-1-6/src/windows/identity/kmq/init.c | 310 + krb5-1-6/src/windows/identity/kmq/kmq.h | 713 + .../src/windows/identity/kmq/kmqconfig.csv | 5 + .../src/windows/identity/kmq/kmqinternal.h | 241 + krb5-1-6/src/windows/identity/kmq/kmqmain.c | 47 + krb5-1-6/src/windows/identity/kmq/msgtype.c | 394 + krb5-1-6/src/windows/identity/kmq/publisher.c | 567 + .../src/windows/identity/nidmgrdll/Makefile | 126 + .../windows/identity/nidmgrdll/Makefile.w2k | 120 + .../src/windows/identity/nidmgrdll/dllmain.c | 114 + .../windows/identity/nidmgrdll/nidmgrdll.rc | 74 + .../windows/identity/plugins/common/Makefile | 44 + .../identity/plugins/common/dynimport.c | 479 + .../identity/plugins/common/dynimport.h | 365 + .../identity/plugins/common/krb5common.c | 451 + .../identity/plugins/common/krb5common.h | 56 + .../windows/identity/plugins/krb4/Makefile | 106 + .../identity/plugins/krb4/errorfuncs.c | 226 + .../identity/plugins/krb4/errorfuncs.h | 65 + .../identity/plugins/krb4/images/plugin.ico | Bin 0 -> 7278 bytes .../identity/plugins/krb4/krb4configdlg.c | 555 + .../windows/identity/plugins/krb4/krb4funcs.c | 897 ++ .../windows/identity/plugins/krb4/krb4funcs.h | 132 + .../windows/identity/plugins/krb4/krb4main.c | 157 + .../identity/plugins/krb4/krb4newcreds.c | 884 ++ .../identity/plugins/krb4/krb4plugin.c | 297 + .../identity/plugins/krb4/krbconfig.csv | 17 + .../windows/identity/plugins/krb4/krbcred.h | 134 + .../plugins/krb4/lang/en_us/langres.rc | 205 + .../identity/plugins/krb4/lang/krb4_msgs.mc | 57 + .../windows/identity/plugins/krb4/langres.h | 49 + .../windows/identity/plugins/krb4/version.rc | 89 + .../windows/identity/plugins/krb5/Makefile | 114 + .../windows/identity/plugins/krb5/datarep.c | 407 + .../windows/identity/plugins/krb5/datarep.h | 76 + .../identity/plugins/krb5/errorfuncs.c | 297 + .../identity/plugins/krb5/errorfuncs.h | 75 + .../identity/plugins/krb5/images/deleted.ico | Bin 0 -> 1406 bytes .../plugins/krb5/images/krb5plugin.ico | Bin 0 -> 7278 bytes .../identity/plugins/krb5/images/modified.ico | Bin 0 -> 1406 bytes .../identity/plugins/krb5/images/new.ico | Bin 0 -> 1406 bytes .../identity/plugins/krb5/images/normal.ico | Bin 0 -> 1406 bytes .../identity/plugins/krb5/krb5configcc.c | 582 + .../identity/plugins/krb5/krb5configdlg.c | 2896 ++++ .../identity/plugins/krb5/krb5configid.c | 366 + .../identity/plugins/krb5/krb5configids.c | 284 + .../windows/identity/plugins/krb5/krb5funcs.c | 3622 +++++ .../windows/identity/plugins/krb5/krb5funcs.h | 223 + .../identity/plugins/krb5/krb5identpro.c | 1861 +++ .../windows/identity/plugins/krb5/krb5main.c | 497 + .../identity/plugins/krb5/krb5newcreds.c | 2886 ++++ .../identity/plugins/krb5/krb5plugin.c | 265 + .../windows/identity/plugins/krb5/krb5props.c | 176 + .../identity/plugins/krb5/krbconfig.csv | 45 + .../windows/identity/plugins/krb5/krbcred.h | 242 + .../plugins/krb5/lang/en_us/langres.rc | 507 + .../identity/plugins/krb5/lang/krb5_msgs.mc | 199 + .../windows/identity/plugins/krb5/langres.h | 216 + .../windows/identity/plugins/krb5/version.rc | 88 + .../sample/templates/credprov/Makefile | 278 + .../identity/sample/templates/credprov/README | 250 + .../sample/templates/credprov/config_id.c | 121 + .../sample/templates/credprov/config_ids.c | 99 + .../sample/templates/credprov/config_main.c | 103 + .../sample/templates/credprov/credacq.c | 408 + .../sample/templates/credprov/credprov.h | 176 + .../sample/templates/credprov/credtype.c | 52 + .../templates/credprov/images/plugin.ico | Bin 0 -> 9110 bytes .../templates/credprov/lang/en_us/langres.rc | 204 + .../sample/templates/credprov/langres.h | 34 + .../identity/sample/templates/credprov/main.c | 171 + .../sample/templates/credprov/plugin.c | 382 + .../sample/templates/credprov/proppage.c | 59 + .../sample/templates/credprov/version.rc | 94 + krb5-1-6/src/windows/identity/ui/Makefile | 109 + krb5-1-6/src/windows/identity/ui/Makefile.w2k | 91 + krb5-1-6/src/windows/identity/ui/aboutwnd.c | 154 + krb5-1-6/src/windows/identity/ui/aboutwnd.h | 33 + krb5-1-6/src/windows/identity/ui/addrchange.c | 93 + krb5-1-6/src/windows/identity/ui/addrchange.h | 36 + krb5-1-6/src/windows/identity/ui/appglobal.h | 163 + krb5-1-6/src/windows/identity/ui/appver.rc | 40 + .../src/windows/identity/ui/cfg_appear_wnd.c | 440 + .../src/windows/identity/ui/cfg_general_wnd.c | 424 + .../windows/identity/ui/cfg_identities_wnd.c | 1573 ++ .../src/windows/identity/ui/cfg_notif_wnd.c | 350 + .../src/windows/identity/ui/cfg_plugins_wnd.c | 654 + krb5-1-6/src/windows/identity/ui/configwnd.c | 1243 ++ krb5-1-6/src/windows/identity/ui/configwnd.h | 88 + krb5-1-6/src/windows/identity/ui/credfuncs.c | 1415 ++ krb5-1-6/src/windows/identity/ui/credfuncs.h | 95 + krb5-1-6/src/windows/identity/ui/credwnd.c | 5956 ++++++++ krb5-1-6/src/windows/identity/ui/credwnd.h | 306 + krb5-1-6/src/windows/identity/ui/debugfuncs.c | 256 + krb5-1-6/src/windows/identity/ui/debugfuncs.h | 37 + krb5-1-6/src/windows/identity/ui/htwnd.c | 1311 ++ krb5-1-6/src/windows/identity/ui/htwnd.h | 57 + .../identity/ui/images/app_notify_error.ico | Bin 0 -> 2862 bytes .../identity/ui/images/app_notify_info.ico | Bin 0 -> 2862 bytes .../identity/ui/images/app_notify_none.ico | Bin 0 -> 2862 bytes .../identity/ui/images/app_notify_warn.ico | Bin 0 -> 2862 bytes .../identity/ui/images/app_state_exp.ico | Bin 0 -> 2862 bytes .../identity/ui/images/app_state_ok.ico | Bin 0 -> 2862 bytes .../identity/ui/images/app_state_warn.ico | Bin 0 -> 2862 bytes .../identity/ui/images/cfg_applied.ico | Bin 0 -> 1406 bytes .../identity/ui/images/cfg_default.ico | Bin 0 -> 1406 bytes .../identity/ui/images/cfg_deleted.ico | Bin 0 -> 1406 bytes .../windows/identity/ui/images/cfg_mod.ico | Bin 0 -> 1406 bytes .../windows/identity/ui/images/cfg_plugin.ico | Bin 0 -> 9110 bytes .../identity/ui/images/cfg_plugin_dis.ico | Bin 0 -> 8854 bytes .../identity/ui/images/cfg_plugin_err.ico | Bin 0 -> 8854 bytes .../identity/ui/images/chpw-dis-sm.bmp | Bin 0 -> 822 bytes .../windows/identity/ui/images/chpw-dis.bmp | Bin 0 -> 2430 bytes .../windows/identity/ui/images/chpw-sm.bmp | Bin 0 -> 822 bytes .../src/windows/identity/ui/images/chpw.bmp | Bin 0 -> 2430 bytes .../windows/identity/ui/images/disabled.ico | Bin 0 -> 2166 bytes .../windows/identity/ui/images/enabled.ico | Bin 0 -> 2166 bytes .../identity/ui/images/flag-critical.bmp | Bin 0 -> 822 bytes .../identity/ui/images/flag-warning.bmp | Bin 0 -> 822 bytes .../identity/ui/images/flag_expired.bmp | Bin 0 -> 774 bytes .../identity/ui/images/flag_renewable.bmp | Bin 0 -> 1334 bytes .../windows/identity/ui/images/help-sm.bmp | Bin 0 -> 822 bytes .../src/windows/identity/ui/images/help.bmp | Bin 0 -> 2430 bytes .../identity/ui/images/id-delete-dis-sm.bmp | Bin 0 -> 1014 bytes .../identity/ui/images/id-delete-dis.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/id-delete-sm.bmp | Bin 0 -> 1014 bytes .../windows/identity/ui/images/id-delete.bmp | Bin 0 -> 3186 bytes .../windows/identity/ui/images/id-dis-sm.bmp | Bin 0 -> 822 bytes .../src/windows/identity/ui/images/id-dis.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/id-new-dis-sm.bmp | Bin 0 -> 1014 bytes .../windows/identity/ui/images/id-new-dis.bmp | Bin 0 -> 3186 bytes .../windows/identity/ui/images/id-new-sm.bmp | Bin 0 -> 1014 bytes .../src/windows/identity/ui/images/id-new.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/id-refresh-dis.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/id-refresh-sm-dis.bmp | Bin 0 -> 1014 bytes .../identity/ui/images/id-refresh-sm.bmp | Bin 0 -> 1014 bytes .../windows/identity/ui/images/id-refresh.bmp | Bin 0 -> 3186 bytes .../src/windows/identity/ui/images/id-sm.bmp | Bin 0 -> 822 bytes .../src/windows/identity/ui/images/id.bmp | Bin 0 -> 3186 bytes .../src/windows/identity/ui/images/id.ico | Bin 0 -> 2862 bytes .../src/windows/identity/ui/images/ident.png | Bin 0 -> 423 bytes .../windows/identity/ui/images/import-dis.bmp | Bin 0 -> 2430 bytes .../identity/ui/images/import-sm-dis.bmp | Bin 0 -> 774 bytes .../windows/identity/ui/images/import-sm.bmp | Bin 0 -> 822 bytes .../src/windows/identity/ui/images/import.bmp | Bin 0 -> 2430 bytes .../identity/ui/images/khimaira-cfg.bmp | Bin 0 -> 30056 bytes .../windows/identity/ui/images/logo_shade.bmp | Bin 0 -> 30056 bytes .../windows/identity/ui/images/main_app.ico | Bin 0 -> 25214 bytes .../identity/ui/images/tb-blank-small.bmp | Bin 0 -> 774 bytes .../windows/identity/ui/images/tb-blank.bmp | Bin 0 -> 2430 bytes .../windows/identity/ui/images/tb-space.bmp | Bin 0 -> 2430 bytes .../identity/ui/images/tk-delete-dis-sm.bmp | Bin 0 -> 1014 bytes .../identity/ui/images/tk-delete-dis.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/tk-delete-sm.bmp | Bin 0 -> 822 bytes .../windows/identity/ui/images/tk-delete.bmp | Bin 0 -> 2430 bytes .../windows/identity/ui/images/tk-dis-sm.bmp | Bin 0 -> 1014 bytes .../src/windows/identity/ui/images/tk-dis.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/tk-new-dis-sm.bmp | Bin 0 -> 1014 bytes .../windows/identity/ui/images/tk-new-dis.bmp | Bin 0 -> 3186 bytes .../windows/identity/ui/images/tk-new-sm.bmp | Bin 0 -> 822 bytes .../src/windows/identity/ui/images/tk-new.bmp | Bin 0 -> 2430 bytes .../identity/ui/images/tk-refresh-dis-sm.bmp | Bin 0 -> 1014 bytes .../identity/ui/images/tk-refresh-dis.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/tk-refresh-sm.bmp | Bin 0 -> 822 bytes .../windows/identity/ui/images/tk-refresh.bmp | Bin 0 -> 2430 bytes .../src/windows/identity/ui/images/tk-sm.bmp | Bin 0 -> 822 bytes .../src/windows/identity/ui/images/tk.bmp | Bin 0 -> 3186 bytes .../identity/ui/images/vw-refresh-sm.bmp | Bin 0 -> 822 bytes .../windows/identity/ui/images/vw-refresh.bmp | Bin 0 -> 2430 bytes .../identity/ui/images/wdg_collapsed.bmp | Bin 0 -> 774 bytes .../identity/ui/images/wdg_collapsed_hi.bmp | Bin 0 -> 774 bytes .../identity/ui/images/wdg_credtype.bmp | Bin 0 -> 1014 bytes .../identity/ui/images/wdg_expanded.bmp | Bin 0 -> 774 bytes .../identity/ui/images/wdg_expanded_hi.bmp | Bin 0 -> 774 bytes .../windows/identity/ui/images/wdg_flag.bmp | Bin 0 -> 1014 bytes .../windows/identity/ui/images/wdg_stick.bmp | Bin 0 -> 774 bytes .../identity/ui/images/wdg_stick_hi.bmp | Bin 0 -> 774 bytes .../windows/identity/ui/images/wdg_stuck.bmp | Bin 0 -> 774 bytes .../identity/ui/images/wdg_stuck_hi.bmp | Bin 0 -> 774 bytes krb5-1-6/src/windows/identity/ui/khmapp.h | 70 + .../identity/ui/lang/en_us/cmdline.rtf | Bin 0 -> 1252 bytes .../windows/identity/ui/lang/en_us/khapp.rc | 869 ++ krb5-1-6/src/windows/identity/ui/main.c | 1075 ++ krb5-1-6/src/windows/identity/ui/mainmenu.c | 1233 ++ krb5-1-6/src/windows/identity/ui/mainmenu.h | 68 + krb5-1-6/src/windows/identity/ui/mainwnd.c | 1369 ++ krb5-1-6/src/windows/identity/ui/mainwnd.h | 82 + .../src/windows/identity/ui/makeacceldef.pl | 29 + .../src/windows/identity/ui/makeactiondef.pl | 29 + .../identity/ui/netidmgr.exe.manifest.i386 | 22 + .../identity/ui/netidmgr.manifest.amd64.vc7 | 22 + .../ui/netidmgr.manifest.amd64.vc7.debug | 22 + .../identity/ui/netidmgr.manifest.amd64.vc8 | 31 + .../ui/netidmgr.manifest.amd64.vc8.debug | 31 + .../identity/ui/netidmgr.manifest.i386.vc7 | 22 + .../ui/netidmgr.manifest.i386.vc7.debug | 22 + .../identity/ui/netidmgr.manifest.i386.vc8 | 31 + .../ui/netidmgr.manifest.i386.vc8.debug | 31 + krb5-1-6/src/windows/identity/ui/newcredwnd.c | 3034 ++++ krb5-1-6/src/windows/identity/ui/newcredwnd.h | 193 + krb5-1-6/src/windows/identity/ui/notifier.c | 3174 ++++ krb5-1-6/src/windows/identity/ui/notifier.h | 69 + krb5-1-6/src/windows/identity/ui/passwnd.c | 133 + krb5-1-6/src/windows/identity/ui/passwnd.h | 39 + .../src/windows/identity/ui/propertywnd.c | 254 + .../src/windows/identity/ui/propertywnd.h | 36 + krb5-1-6/src/windows/identity/ui/reqdaemon.c | 453 + krb5-1-6/src/windows/identity/ui/reqdaemon.h | 42 + krb5-1-6/src/windows/identity/ui/resource.h | 421 + krb5-1-6/src/windows/identity/ui/statusbar.c | 208 + krb5-1-6/src/windows/identity/ui/statusbar.h | 55 + krb5-1-6/src/windows/identity/ui/taskbar.c | 87 + krb5-1-6/src/windows/identity/ui/taskbar.h | 38 + krb5-1-6/src/windows/identity/ui/timer.c | 1015 ++ krb5-1-6/src/windows/identity/ui/timer.h | 100 + krb5-1-6/src/windows/identity/ui/toolbar.c | 471 + krb5-1-6/src/windows/identity/ui/toolbar.h | 52 + krb5-1-6/src/windows/identity/ui/uiconfig.csv | 273 + krb5-1-6/src/windows/identity/uilib/Makefile | 68 + krb5-1-6/src/windows/identity/uilib/accel.csv | 26 + .../src/windows/identity/uilib/acceldef.cfg | 51 + krb5-1-6/src/windows/identity/uilib/action.c | 1672 +++ .../src/windows/identity/uilib/actiondef.cfg | 67 + .../src/windows/identity/uilib/actions.csv | 55 + krb5-1-6/src/windows/identity/uilib/alert.c | 440 + .../src/windows/identity/uilib/configui.c | 1088 ++ .../src/windows/identity/uilib/configui.h | 74 + krb5-1-6/src/windows/identity/uilib/creddlg.c | 719 + .../src/windows/identity/uilib/intaction.h | 112 + .../src/windows/identity/uilib/intalert.h | 136 + .../src/windows/identity/uilib/khaction.h | 1005 ++ .../src/windows/identity/uilib/khactiondef.h | 170 + .../src/windows/identity/uilib/khalerts.h | 403 + .../src/windows/identity/uilib/khconfigui.h | 627 + .../src/windows/identity/uilib/khhtlink.h | 77 + .../src/windows/identity/uilib/khnewcred.h | 1132 ++ krb5-1-6/src/windows/identity/uilib/khprops.h | 209 + .../src/windows/identity/uilib/khremote.h | 84 + .../src/windows/identity/uilib/khrescache.h | 100 + .../src/windows/identity/uilib/khtracker.h | 114 + .../src/windows/identity/uilib/khuidefs.h | 146 + .../src/windows/identity/uilib/propsheet.c | 232 + krb5-1-6/src/windows/identity/uilib/propwnd.c | 39 + .../src/windows/identity/uilib/rescache.c | 304 + .../src/windows/identity/uilib/trackerwnd.c | 477 + krb5-1-6/src/windows/identity/uilib/uibind.c | 62 + .../src/windows/identity/uilib/uilibmain.c | 46 + krb5-1-6/src/windows/identity/uilib/version.c | 85 + krb5-1-6/src/windows/identity/util/Makefile | 49 + .../src/windows/identity/util/hashtable.c | 173 + .../src/windows/identity/util/hashtable.h | 231 + krb5-1-6/src/windows/identity/util/mstring.c | 512 + krb5-1-6/src/windows/identity/util/mstring.h | 361 + krb5-1-6/src/windows/identity/util/perfstat.c | 459 + krb5-1-6/src/windows/identity/util/perfstat.h | 74 + krb5-1-6/src/windows/identity/util/sync.c | 132 + krb5-1-6/src/windows/identity/util/sync.h | 128 + krb5-1-6/src/windows/identity/util/utils.h | 37 + .../windows/installer/nsis/KfWConfigPage.ini | 59 + .../windows/installer/nsis/KfWConfigPage2.ini | 20 + .../src/windows/installer/nsis/kfw-fixed.nsi | 1907 +++ krb5-1-6/src/windows/installer/nsis/kfw.ico | Bin 0 -> 25214 bytes krb5-1-6/src/windows/installer/nsis/kfw.nsi | 16 + .../src/windows/installer/nsis/killer.cpp | 380 + .../src/windows/installer/nsis/licenses.rtf | 98 + .../installer/nsis/nsi-includes-tagged.nsi | 8 + .../installer/nsis/site-local-tagged.nsi | 13 + krb5-1-6/src/windows/installer/nsis/utils.nsi | 825 ++ .../windows/installer/wix/Binary/bannrbmp.bmp | Bin 0 -> 94554 bytes .../windows/installer/wix/Binary/completi.ico | Bin 0 -> 2998 bytes .../windows/installer/wix/Binary/custicon.ico | Bin 0 -> 2998 bytes .../windows/installer/wix/Binary/dlgbmp.bmp | Bin 0 -> 474822 bytes .../windows/installer/wix/Binary/exclamic.ico | Bin 0 -> 766 bytes .../src/windows/installer/wix/Binary/info.bmp | Bin 0 -> 1078 bytes .../windows/installer/wix/Binary/insticon.ico | Bin 0 -> 2998 bytes .../src/windows/installer/wix/Binary/new.bmp | Bin 0 -> 318 bytes .../windows/installer/wix/Binary/removico.ico | Bin 0 -> 2998 bytes .../windows/installer/wix/Binary/repairic.ico | Bin 0 -> 2998 bytes .../src/windows/installer/wix/Binary/up.bmp | Bin 0 -> 318 bytes krb5-1-6/src/windows/installer/wix/Makefile | 59 + krb5-1-6/src/windows/installer/wix/config.wxi | 182 + .../windows/installer/wix/custom/custom.cpp | 746 + .../src/windows/installer/wix/custom/custom.h | 81 + .../src/windows/installer/wix/features.wxi | 232 + krb5-1-6/src/windows/installer/wix/files.wxi | 1103 ++ krb5-1-6/src/windows/installer/wix/kfw.wxs | 240 + .../installer/wix/lang/config_1033.wxi | 68 + .../windows/installer/wix/lang/license.rtf | 102 + .../installer/wix/lang/strings_1033.wxl | 64 + .../windows/installer/wix/lang/ui_1033.wxi | 1239 ++ .../installer/wix/msi-deployment-guide.txt | 946 ++ .../src/windows/installer/wix/platform.wxi | 191 + .../src/windows/installer/wix/property.wxi | 95 + .../src/windows/installer/wix/runtime.wxi | 90 + .../windows/installer/wix/runtime_debug.wxi | 14 + .../installer/wix/site-local-tagged.wxi | 105 + krb5-1-6/src/windows/kfwlogon/Makefile.in | 47 + krb5-1-6/src/windows/kfwlogon/kfwcommon.c | 1352 ++ krb5-1-6/src/windows/kfwlogon/kfwcpcc.c | 39 + krb5-1-6/src/windows/kfwlogon/kfwlogon.c | 634 + krb5-1-6/src/windows/kfwlogon/kfwlogon.def | 14 + krb5-1-6/src/windows/kfwlogon/kfwlogon.h | 215 + krb5-1-6/src/windows/lib/Makefile.in | 17 + krb5-1-6/src/windows/lib/cacheapi.h | 458 + krb5-1-6/src/windows/lib/gic.c | 157 + krb5-1-6/src/windows/lib/gic.h | 28 + krb5-1-6/src/windows/lib/registry.c | 231 + krb5-1-6/src/windows/lib/registry.h | 40 + krb5-1-6/src/windows/lib/vardlg.c | 453 + krb5-1-6/src/windows/lib/vardlg.h | 32 + krb5-1-6/src/windows/ms2mit/Makefile.in | 41 + krb5-1-6/src/windows/ms2mit/mit2ms.c | 149 + krb5-1-6/src/windows/ms2mit/ms2mit.c | 171 + krb5-1-6/src/windows/version.rc | 329 + krb5-1-6/src/windows/winlevel.h | 33 + krb5-1-6/src/windows/wintel/Makefile.in | 46 + krb5-1-6/src/windows/wintel/auth.c | 867 ++ krb5-1-6/src/windows/wintel/auth.h | 28 + krb5-1-6/src/windows/wintel/dialog.h | 42 + krb5-1-6/src/windows/wintel/edit.c | 444 + krb5-1-6/src/windows/wintel/emul.c | 766 + krb5-1-6/src/windows/wintel/enc_des.c | 725 + krb5-1-6/src/windows/wintel/enc_des.h | 120 + krb5-1-6/src/windows/wintel/encrypt.c | 999 ++ krb5-1-6/src/windows/wintel/encrypt.h | 178 + krb5-1-6/src/windows/wintel/font.c | 100 + krb5-1-6/src/windows/wintel/genget.c | 101 + krb5-1-6/src/windows/wintel/ini.h | 16 + krb5-1-6/src/windows/wintel/intern.c | 815 + krb5-1-6/src/windows/wintel/k5stream.c | 119 + krb5-1-6/src/windows/wintel/k5stream.h | 57 + krb5-1-6/src/windows/wintel/ktelnet.doc | Bin 0 -> 16384 bytes krb5-1-6/src/windows/wintel/ktelnet.hlp | Bin 0 -> 9204 bytes krb5-1-6/src/windows/wintel/ktelnet.hpj | 92 + krb5-1-6/src/windows/wintel/ncsa.ico | Bin 0 -> 766 bytes krb5-1-6/src/windows/wintel/negotiat.c | 865 ++ krb5-1-6/src/windows/wintel/resource.h | 17 + krb5-1-6/src/windows/wintel/screen.c | 1147 ++ krb5-1-6/src/windows/wintel/screen.h | 325 + krb5-1-6/src/windows/wintel/struct.h | 29 + krb5-1-6/src/windows/wintel/telnet.c | 904 ++ krb5-1-6/src/windows/wintel/telnet.def | 39 + krb5-1-6/src/windows/wintel/telnet.h | 41 + krb5-1-6/src/windows/wintel/telnet.rc | 247 + krb5-1-6/src/windows/wintel/telnet_arpa.h | 327 + krb5-1-6/src/windows/wintel/telopts.h | 164 + krb5-1-6/src/windows/wintel/terminal.ico | Bin 0 -> 766 bytes krb5-1-6/src/windows/wintel/wt-proto.h | 63 + 2412 files changed, 720104 insertions(+) create mode 100644 krb5-1-6/README create mode 100644 krb5-1-6/doc/.cvsignore create mode 100644 krb5-1-6/doc/Makefile create mode 100644 krb5-1-6/doc/admin.texinfo create mode 100644 krb5-1-6/doc/api/.cvsignore create mode 100644 krb5-1-6/doc/api/Makefile create mode 100644 krb5-1-6/doc/api/ccache.tex create mode 100644 krb5-1-6/doc/api/errors.tex create mode 100644 krb5-1-6/doc/api/fancyheadings.sty create mode 100644 krb5-1-6/doc/api/fixunder.sty create mode 100644 krb5-1-6/doc/api/free.tex create mode 100644 krb5-1-6/doc/api/functions.sty create mode 100644 krb5-1-6/doc/api/intro.tex create mode 100644 krb5-1-6/doc/api/keytab.tex create mode 100644 krb5-1-6/doc/api/krb5.ist create mode 100644 krb5-1-6/doc/api/krb5.tex create mode 100644 krb5-1-6/doc/api/krb5idx.sty create mode 100644 krb5-1-6/doc/api/libdes.tex create mode 100644 krb5-1-6/doc/api/libos.tex create mode 100644 krb5-1-6/doc/api/library.tex create mode 100644 krb5-1-6/doc/api/rcache.tex create mode 100644 krb5-1-6/doc/api/tables.tex create mode 100644 krb5-1-6/doc/bug-report.texinfo create mode 100644 krb5-1-6/doc/build.texinfo create mode 100644 krb5-1-6/doc/coding-style create mode 100644 krb5-1-6/doc/copyright.texinfo create mode 100644 krb5-1-6/doc/definitions.texinfo create mode 100644 krb5-1-6/doc/dnssrv.texinfo create mode 100644 krb5-1-6/doc/dnstxt.texinfo create mode 100644 krb5-1-6/doc/document-list.texinfo create mode 100644 krb5-1-6/doc/glossary.texinfo create mode 100644 krb5-1-6/doc/implement/.cvsignore create mode 100644 krb5-1-6/doc/implement/Makefile create mode 100644 krb5-1-6/doc/implement/ccache-i.tex create mode 100644 krb5-1-6/doc/implement/cksum-i.tex create mode 100644 krb5-1-6/doc/implement/crc-32-i.tex create mode 100644 krb5-1-6/doc/implement/encrypt-i.tex create mode 100644 krb5-1-6/doc/implement/fancyheadings.sty create mode 100644 krb5-1-6/doc/implement/fixunder.sty create mode 100644 krb5-1-6/doc/implement/functions.sty create mode 100644 krb5-1-6/doc/implement/implement.tex create mode 100644 krb5-1-6/doc/implement/kdb-i.tex create mode 100644 krb5-1-6/doc/implement/keytab-i.tex create mode 100644 krb5-1-6/doc/implement/libos-i.tex create mode 100644 krb5-1-6/doc/implement/rcache-i.tex create mode 100644 krb5-1-6/doc/implementor.texinfo create mode 100644 krb5-1-6/doc/install-old.texi create mode 100644 krb5-1-6/doc/install.texinfo create mode 100644 krb5-1-6/doc/kadm5/adb-unit-test.tex create mode 100644 krb5-1-6/doc/kadm5/api-funcspec.tex create mode 100644 krb5-1-6/doc/kadm5/api-server-design.tex create mode 100644 krb5-1-6/doc/kadm5/api-unit-test.tex create mode 100644 krb5-1-6/doc/kadm5/fullpage.sty create mode 100644 krb5-1-6/doc/kadm5/rcsid.sty create mode 100644 krb5-1-6/doc/kadm5acl.texinfo create mode 100644 krb5-1-6/doc/kadmin/README create mode 100644 krb5-1-6/doc/kadmin/draft-ietf-cat-kerb-chg-password-02.txt create mode 100644 krb5-1-6/doc/kadmin/kadmin.protocol create mode 100644 krb5-1-6/doc/kadmin/kpasswd.protocol create mode 100644 krb5-1-6/doc/kdcconf.texinfo create mode 100644 krb5-1-6/doc/krb4-xrealm.txt create mode 100644 krb5-1-6/doc/krb425.texinfo create mode 100755 krb5-1-6/doc/krb5-protocol/draft-jaganathan-rc4-hmac-03.txt create mode 100644 krb5-1-6/doc/krb5-protocol/krb5.constants create mode 100644 krb5-1-6/doc/krb5-protocol/rfc3961.txt create mode 100644 krb5-1-6/doc/krb5-protocol/rfc3962.txt create mode 100644 krb5-1-6/doc/krb5-protocol/rfc4120.txt create mode 100644 krb5-1-6/doc/krb5-protocol/rfc4121.txt create mode 100644 krb5-1-6/doc/krb5conf.texinfo create mode 100755 krb5-1-6/doc/man2html create mode 100644 krb5-1-6/doc/man2html.M create mode 100755 krb5-1-6/doc/man2ps create mode 100644 krb5-1-6/doc/man2ps.M create mode 100644 krb5-1-6/doc/old-V4-docs/README create mode 100644 krb5-1-6/doc/old-V4-docs/installation.PS create mode 100644 krb5-1-6/doc/old-V4-docs/installation.mss create mode 100644 krb5-1-6/doc/old-V4-docs/operation.PS create mode 100644 krb5-1-6/doc/old-V4-docs/operation.mss create mode 100644 krb5-1-6/doc/procedures.txt create mode 100644 krb5-1-6/doc/rpc/design.tex create mode 100644 krb5-1-6/doc/salts.texinfo create mode 100644 krb5-1-6/doc/send-pr.texinfo create mode 100644 krb5-1-6/doc/support-enc.texinfo create mode 100644 krb5-1-6/doc/texinfo-suppl.tex create mode 100644 krb5-1-6/doc/texinfo.tex create mode 100644 krb5-1-6/doc/thread-safe.txt create mode 100644 krb5-1-6/doc/threads.txt create mode 100644 krb5-1-6/doc/user-guide.texinfo create mode 100644 krb5-1-6/src/BADSYMS create mode 100644 krb5-1-6/src/Makefile.in create mode 100644 krb5-1-6/src/aclocal.m4 create mode 100644 krb5-1-6/src/appl/Makefile.in create mode 100644 krb5-1-6/src/appl/bsd/Makefile.in create mode 100644 krb5-1-6/src/appl/bsd/compat_recv.c create mode 100644 krb5-1-6/src/appl/bsd/configure.in create mode 100644 krb5-1-6/src/appl/bsd/defines.h create mode 100644 krb5-1-6/src/appl/bsd/forward.c create mode 100644 krb5-1-6/src/appl/bsd/getdtablesize.c create mode 100644 krb5-1-6/src/appl/bsd/kcmd.c create mode 100644 krb5-1-6/src/appl/bsd/klogind.M create mode 100644 krb5-1-6/src/appl/bsd/krcp.c create mode 100644 krb5-1-6/src/appl/bsd/krlogin.c create mode 100644 krb5-1-6/src/appl/bsd/krlogind.c create mode 100644 krb5-1-6/src/appl/bsd/krsh.c create mode 100644 krb5-1-6/src/appl/bsd/krshd.c create mode 100644 krb5-1-6/src/appl/bsd/kshd.M create mode 100644 krb5-1-6/src/appl/bsd/login.M create mode 100644 krb5-1-6/src/appl/bsd/login.c create mode 100644 krb5-1-6/src/appl/bsd/loginpaths.h create mode 100644 krb5-1-6/src/appl/bsd/rcp.M create mode 100644 krb5-1-6/src/appl/bsd/rlogin.M create mode 100644 krb5-1-6/src/appl/bsd/rpaths.h create mode 100644 krb5-1-6/src/appl/bsd/rsh.M create mode 100644 krb5-1-6/src/appl/bsd/setenv.c create mode 100644 krb5-1-6/src/appl/bsd/v4rcp.M create mode 100644 krb5-1-6/src/appl/bsd/v4rcp.c create mode 100644 krb5-1-6/src/appl/configure.in create mode 100644 krb5-1-6/src/appl/gss-sample/Makefile.in create mode 100644 krb5-1-6/src/appl/gss-sample/README create mode 100644 krb5-1-6/src/appl/gss-sample/gss-client.c create mode 100644 krb5-1-6/src/appl/gss-sample/gss-misc.c create mode 100644 krb5-1-6/src/appl/gss-sample/gss-misc.h create mode 100644 krb5-1-6/src/appl/gss-sample/gss-server.c create mode 100644 krb5-1-6/src/appl/gssftp/Makefile.in create mode 100644 krb5-1-6/src/appl/gssftp/README.gssftp create mode 100644 krb5-1-6/src/appl/gssftp/arpa/ftp.h create mode 100644 krb5-1-6/src/appl/gssftp/arpa/telnet.h create mode 100644 krb5-1-6/src/appl/gssftp/configure.in create mode 100644 krb5-1-6/src/appl/gssftp/ftp/Makefile.in create mode 100644 krb5-1-6/src/appl/gssftp/ftp/cmds.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/cmdtab.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/domacro.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/ftp.M create mode 100644 krb5-1-6/src/appl/gssftp/ftp/ftp.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/ftp_var.h create mode 100644 krb5-1-6/src/appl/gssftp/ftp/getpass.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/glob.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/main.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/pathnames.h create mode 100644 krb5-1-6/src/appl/gssftp/ftp/pclose.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/radix.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/ruserpass.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/secure.c create mode 100644 krb5-1-6/src/appl/gssftp/ftp/secure.h create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/CHANGES create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/Makefile.in create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/ftpcmd.y create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/ftpd.M create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/ftpd.c create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/ftpd_var.h create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/logwtmp.c create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/pathnames.h create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/popen.c create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/secure.h create mode 100644 krb5-1-6/src/appl/gssftp/ftpd/vers.c create mode 100644 krb5-1-6/src/appl/libpty/Makefile.in create mode 100644 krb5-1-6/src/appl/libpty/README create mode 100644 krb5-1-6/src/appl/libpty/cleanup.c create mode 100644 krb5-1-6/src/appl/libpty/configure.in create mode 100644 krb5-1-6/src/appl/libpty/dump-utmp.c create mode 100644 krb5-1-6/src/appl/libpty/getpty.c create mode 100644 krb5-1-6/src/appl/libpty/init.c create mode 100644 krb5-1-6/src/appl/libpty/init_slave.c create mode 100644 krb5-1-6/src/appl/libpty/libpty.h create mode 100644 krb5-1-6/src/appl/libpty/logwtmp.c create mode 100644 krb5-1-6/src/appl/libpty/open_ctty.c create mode 100644 krb5-1-6/src/appl/libpty/open_slave.c create mode 100644 krb5-1-6/src/appl/libpty/pty-int.h create mode 100644 krb5-1-6/src/appl/libpty/pty_err.et create mode 100644 krb5-1-6/src/appl/libpty/pty_paranoia.c create mode 100644 krb5-1-6/src/appl/libpty/sane_hostname.c create mode 100644 krb5-1-6/src/appl/libpty/update_utmp.c create mode 100644 krb5-1-6/src/appl/libpty/update_wtmp.c create mode 100644 krb5-1-6/src/appl/libpty/vhangup.c create mode 100644 krb5-1-6/src/appl/libpty/void_assoc.c create mode 100644 krb5-1-6/src/appl/sample/Makefile.in create mode 100644 krb5-1-6/src/appl/sample/sample.h create mode 100644 krb5-1-6/src/appl/sample/sclient/Makefile.in create mode 100644 krb5-1-6/src/appl/sample/sclient/sclient.M create mode 100644 krb5-1-6/src/appl/sample/sclient/sclient.c create mode 100644 krb5-1-6/src/appl/sample/sserver/Makefile.in create mode 100644 krb5-1-6/src/appl/sample/sserver/sserver.M create mode 100644 krb5-1-6/src/appl/sample/sserver/sserver.c create mode 100644 krb5-1-6/src/appl/simple/Makefile.in create mode 100644 krb5-1-6/src/appl/simple/client/Makefile.in create mode 100644 krb5-1-6/src/appl/simple/client/sim_client.c create mode 100644 krb5-1-6/src/appl/simple/server/Makefile.in create mode 100644 krb5-1-6/src/appl/simple/server/sim_server.c create mode 100644 krb5-1-6/src/appl/simple/simple.h create mode 100644 krb5-1-6/src/appl/telnet/Config.generic create mode 100644 krb5-1-6/src/appl/telnet/Makefile.in create mode 100644 krb5-1-6/src/appl/telnet/README create mode 100644 krb5-1-6/src/appl/telnet/arpa/telnet.h create mode 100644 krb5-1-6/src/appl/telnet/configure.in create mode 100644 krb5-1-6/src/appl/telnet/kern.diff create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/Makefile.in create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/auth-proto.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/auth.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/auth.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/enc-proto.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/enc_des.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/encrypt.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/encrypt.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/forward.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/genget.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/getent.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/getopt.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/gettytab.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/gettytab.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/herror.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/kerberos.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/kerberos5.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/key-proto.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/krb5forw.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/mem.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/misc-proto.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/misc.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/misc.h create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/parsetos.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/setenv.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/setsid.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/spx.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/strcasecmp.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/strchr.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/strdup.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/strerror.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/strftime.c create mode 100644 krb5-1-6/src/appl/telnet/libtelnet/strrchr.c create mode 100644 krb5-1-6/src/appl/telnet/stty.diff create mode 100644 krb5-1-6/src/appl/telnet/telnet.state create mode 100644 krb5-1-6/src/appl/telnet/telnet/Makefile.in create mode 100644 krb5-1-6/src/appl/telnet/telnet/authenc.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/commands.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/defines.h create mode 100644 krb5-1-6/src/appl/telnet/telnet/externs.h create mode 100644 krb5-1-6/src/appl/telnet/telnet/fdset.h create mode 100644 krb5-1-6/src/appl/telnet/telnet/general.h create mode 100644 krb5-1-6/src/appl/telnet/telnet/main.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/network.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/ring.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/ring.h create mode 100644 krb5-1-6/src/appl/telnet/telnet/sys_bsd.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/telnet.0.ps create mode 100644 krb5-1-6/src/appl/telnet/telnet/telnet.0.txt create mode 100644 krb5-1-6/src/appl/telnet/telnet/telnet.1 create mode 100644 krb5-1-6/src/appl/telnet/telnet/telnet.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/terminal.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/tmac.doc create mode 100644 krb5-1-6/src/appl/telnet/telnet/tn3270.c create mode 100644 krb5-1-6/src/appl/telnet/telnet/types.h create mode 100644 krb5-1-6/src/appl/telnet/telnet/utilities.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/ISSUES create mode 100644 krb5-1-6/src/appl/telnet/telnetd/Makefile.in create mode 100644 krb5-1-6/src/appl/telnet/telnetd/authenc.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/defs.h create mode 100644 krb5-1-6/src/appl/telnet/telnetd/ext.h create mode 100644 krb5-1-6/src/appl/telnet/telnetd/global.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/pathnames.h create mode 100644 krb5-1-6/src/appl/telnet/telnetd/slc.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/state.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/sys_term.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/telnetd-ktd.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/telnetd.0.ps create mode 100644 krb5-1-6/src/appl/telnet/telnetd/telnetd.0.txt create mode 100644 krb5-1-6/src/appl/telnet/telnetd/telnetd.8 create mode 100644 krb5-1-6/src/appl/telnet/telnetd/telnetd.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/telnetd.h create mode 100644 krb5-1-6/src/appl/telnet/telnetd/termio-tn.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/termios-tn.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/termstat.c create mode 100644 krb5-1-6/src/appl/telnet/telnetd/utility.c create mode 100644 krb5-1-6/src/appl/user_user/Makefile.in create mode 100644 krb5-1-6/src/appl/user_user/client.c create mode 100644 krb5-1-6/src/appl/user_user/server.c create mode 100644 krb5-1-6/src/clients/Makefile.in create mode 100644 krb5-1-6/src/clients/kcpytkt/Makefile.in create mode 100644 krb5-1-6/src/clients/kcpytkt/kcpytkt.M create mode 100644 krb5-1-6/src/clients/kcpytkt/kcpytkt.c create mode 100644 krb5-1-6/src/clients/kdeltkt/Makefile.in create mode 100644 krb5-1-6/src/clients/kdeltkt/kdeltkt.M create mode 100644 krb5-1-6/src/clients/kdeltkt/kdeltkt.c create mode 100644 krb5-1-6/src/clients/kdestroy/Makefile.in create mode 100644 krb5-1-6/src/clients/kdestroy/kdestroy.M create mode 100644 krb5-1-6/src/clients/kdestroy/kdestroy.c create mode 100644 krb5-1-6/src/clients/kinit/Makefile.in create mode 100644 krb5-1-6/src/clients/kinit/kinit.M create mode 100644 krb5-1-6/src/clients/kinit/kinit.c create mode 100644 krb5-1-6/src/clients/klist/Makefile.in create mode 100644 krb5-1-6/src/clients/klist/klist.M create mode 100644 krb5-1-6/src/clients/klist/klist.c create mode 100644 krb5-1-6/src/clients/kpasswd/Makefile.in create mode 100644 krb5-1-6/src/clients/kpasswd/kpasswd.M create mode 100644 krb5-1-6/src/clients/kpasswd/kpasswd.c create mode 100644 krb5-1-6/src/clients/kpasswd/ksetpwd.c create mode 100644 krb5-1-6/src/clients/ksu/Makefile.in create mode 100644 krb5-1-6/src/clients/ksu/authorization.c create mode 100644 krb5-1-6/src/clients/ksu/ccache.c create mode 100644 krb5-1-6/src/clients/ksu/heuristic.c create mode 100644 krb5-1-6/src/clients/ksu/krb_auth_su.c create mode 100644 krb5-1-6/src/clients/ksu/ksu.M create mode 100644 krb5-1-6/src/clients/ksu/ksu.h create mode 100644 krb5-1-6/src/clients/ksu/main.c create mode 100644 krb5-1-6/src/clients/ksu/setenv.c create mode 100644 krb5-1-6/src/clients/ksu/xmalloc.c create mode 100644 krb5-1-6/src/clients/kvno/Makefile.in create mode 100644 krb5-1-6/src/clients/kvno/kvno.M create mode 100644 krb5-1-6/src/clients/kvno/kvno.c create mode 100644 krb5-1-6/src/config-files/Makefile.in create mode 100644 krb5-1-6/src/config-files/convert-config-files create mode 100644 krb5-1-6/src/config-files/kdc.conf create mode 100644 krb5-1-6/src/config-files/kdc.conf.M create mode 100644 krb5-1-6/src/config-files/krb5.conf create mode 100644 krb5-1-6/src/config-files/krb5.conf.M create mode 100644 krb5-1-6/src/config-files/services.append create mode 100644 krb5-1-6/src/config/ac-archive/README create mode 100644 krb5-1-6/src/config/ac-archive/acx_pthread.m4 create mode 100755 krb5-1-6/src/config/config.guess create mode 100755 krb5-1-6/src/config/config.sub create mode 100755 krb5-1-6/src/config/install-sh create mode 100644 krb5-1-6/src/config/lib.in create mode 100644 krb5-1-6/src/config/libnover.in create mode 100644 krb5-1-6/src/config/libobj.in create mode 100755 krb5-1-6/src/config/mkinstalldirs create mode 100755 krb5-1-6/src/config/move-if-changed create mode 100644 krb5-1-6/src/config/post.in create mode 100644 krb5-1-6/src/config/pre.in create mode 100755 krb5-1-6/src/config/ren2long create mode 100644 krb5-1-6/src/config/ren2long.awk create mode 100644 krb5-1-6/src/config/rm.bat create mode 100644 krb5-1-6/src/config/shlib.conf create mode 100755 krb5-1-6/src/config/wconfig.pl create mode 100644 krb5-1-6/src/config/win-post.in create mode 100644 krb5-1-6/src/config/win-pre.in create mode 100644 krb5-1-6/src/config/winexclude.sed create mode 100644 krb5-1-6/src/configure.in create mode 100644 krb5-1-6/src/gen-manpages/Makefile.in create mode 100644 krb5-1-6/src/gen-manpages/header.doc create mode 100644 krb5-1-6/src/gen-manpages/k5login.M create mode 100644 krb5-1-6/src/gen-manpages/kerberos.M create mode 100644 krb5-1-6/src/include/Makefile.in create mode 100644 krb5-1-6/src/include/adm.h create mode 100644 krb5-1-6/src/include/adm_defs.h create mode 100644 krb5-1-6/src/include/adm_proto.h create mode 100644 krb5-1-6/src/include/cm.h create mode 100644 krb5-1-6/src/include/copyright.h create mode 100644 krb5-1-6/src/include/fake-addrinfo.h create mode 100644 krb5-1-6/src/include/foreachaddr.h create mode 100644 krb5-1-6/src/include/gssapi.h create mode 100644 krb5-1-6/src/include/gssrpc/auth.h create mode 100644 krb5-1-6/src/include/gssrpc/auth_gss.h create mode 100644 krb5-1-6/src/include/gssrpc/auth_gssapi.h create mode 100644 krb5-1-6/src/include/gssrpc/auth_unix.h create mode 100644 krb5-1-6/src/include/gssrpc/clnt.h create mode 100644 krb5-1-6/src/include/gssrpc/netdb.h create mode 100644 krb5-1-6/src/include/gssrpc/pmap_clnt.h create mode 100644 krb5-1-6/src/include/gssrpc/pmap_prot.h create mode 100644 krb5-1-6/src/include/gssrpc/pmap_rmt.h create mode 100644 krb5-1-6/src/include/gssrpc/rename.h create mode 100644 krb5-1-6/src/include/gssrpc/rpc.h create mode 100644 krb5-1-6/src/include/gssrpc/rpc_msg.h create mode 100644 krb5-1-6/src/include/gssrpc/svc.h create mode 100644 krb5-1-6/src/include/gssrpc/svc_auth.h create mode 100644 krb5-1-6/src/include/gssrpc/types.hin create mode 100644 krb5-1-6/src/include/gssrpc/xdr.h create mode 100644 krb5-1-6/src/include/k5-err.h create mode 100644 krb5-1-6/src/include/k5-int-pkinit.h create mode 100644 krb5-1-6/src/include/k5-int.h create mode 100644 krb5-1-6/src/include/k5-platform.h create mode 100644 krb5-1-6/src/include/k5-plugin.h create mode 100644 krb5-1-6/src/include/k5-thread.h create mode 100644 krb5-1-6/src/include/k5-util.h create mode 100644 krb5-1-6/src/include/kdb.h create mode 100644 krb5-1-6/src/include/kdb_dbc.h create mode 100644 krb5-1-6/src/include/kdb_kt.h create mode 100644 krb5-1-6/src/include/kerberosIV/Makefile.in create mode 100644 krb5-1-6/src/include/kerberosIV/addr_comp.h create mode 100644 krb5-1-6/src/include/kerberosIV/admin_server.h create mode 100644 krb5-1-6/src/include/kerberosIV/des.h create mode 100644 krb5-1-6/src/include/kerberosIV/kadm.h create mode 100644 krb5-1-6/src/include/kerberosIV/kdc.h create mode 100644 krb5-1-6/src/include/kerberosIV/klog.h create mode 100644 krb5-1-6/src/include/kerberosIV/kparse.h create mode 100644 krb5-1-6/src/include/kerberosIV/krb.h create mode 100644 krb5-1-6/src/include/kerberosIV/krb_db.h create mode 100644 krb5-1-6/src/include/kerberosIV/krbports.h create mode 100644 krb5-1-6/src/include/kerberosIV/lsb_addr_cmp.h create mode 100644 krb5-1-6/src/include/kerberosIV/mit-copyright.h create mode 100644 krb5-1-6/src/include/kerberosIV/prot.h create mode 100644 krb5-1-6/src/include/krb5.h create mode 100644 krb5-1-6/src/include/krb5/krb5.hin create mode 100644 krb5-1-6/src/include/krb5/locate_plugin.h create mode 100644 krb5-1-6/src/include/krb5/preauth_plugin.h create mode 100644 krb5-1-6/src/include/krb54proto.h create mode 100644 krb5-1-6/src/include/port-sockets.h create mode 100644 krb5-1-6/src/include/socket-utils.h create mode 100644 krb5-1-6/src/include/spnego-asn1.h create mode 100644 krb5-1-6/src/include/stock/osconf.h create mode 100644 krb5-1-6/src/include/syslog.h create mode 100644 krb5-1-6/src/include/win-mac.h create mode 100644 krb5-1-6/src/kadmin/Makefile.in create mode 100644 krb5-1-6/src/kadmin/cli/Makefile.in create mode 100644 krb5-1-6/src/kadmin/cli/getdate.y create mode 100644 krb5-1-6/src/kadmin/cli/k5srvutil.M create mode 100755 krb5-1-6/src/kadmin/cli/k5srvutil.sh create mode 100644 krb5-1-6/src/kadmin/cli/kadmin.M create mode 100644 krb5-1-6/src/kadmin/cli/kadmin.c create mode 100644 krb5-1-6/src/kadmin/cli/kadmin.h create mode 100644 krb5-1-6/src/kadmin/cli/kadmin.local.M create mode 100644 krb5-1-6/src/kadmin/cli/kadmin_ct.ct create mode 100644 krb5-1-6/src/kadmin/cli/keytab.c create mode 100644 krb5-1-6/src/kadmin/cli/ss_wrapper.c create mode 100644 krb5-1-6/src/kadmin/cli/strftime.c create mode 100644 krb5-1-6/src/kadmin/dbutil/Makefile.in create mode 100644 krb5-1-6/src/kadmin/dbutil/dump.c create mode 100644 krb5-1-6/src/kadmin/dbutil/dumpv4.c create mode 100644 krb5-1-6/src/kadmin/dbutil/import_err.et create mode 100644 krb5-1-6/src/kadmin/dbutil/kadm5_create.c create mode 100644 krb5-1-6/src/kadmin/dbutil/kdb5_create.c create mode 100644 krb5-1-6/src/kadmin/dbutil/kdb5_destroy.c create mode 100644 krb5-1-6/src/kadmin/dbutil/kdb5_edit.M create mode 100644 krb5-1-6/src/kadmin/dbutil/kdb5_stash.c create mode 100644 krb5-1-6/src/kadmin/dbutil/kdb5_util.M create mode 100644 krb5-1-6/src/kadmin/dbutil/kdb5_util.c create mode 100644 krb5-1-6/src/kadmin/dbutil/kdb5_util.h create mode 100644 krb5-1-6/src/kadmin/dbutil/loadv4.c create mode 100644 krb5-1-6/src/kadmin/dbutil/nstrtok.h create mode 100644 krb5-1-6/src/kadmin/dbutil/ovload.c create mode 100644 krb5-1-6/src/kadmin/dbutil/string_table.c create mode 100644 krb5-1-6/src/kadmin/dbutil/string_table.h create mode 100644 krb5-1-6/src/kadmin/dbutil/strtok.c create mode 100644 krb5-1-6/src/kadmin/dbutil/tcl_wrapper.c create mode 100644 krb5-1-6/src/kadmin/dbutil/util.c create mode 100644 krb5-1-6/src/kadmin/kdbkeys/Makefile.in create mode 100755 krb5-1-6/src/kadmin/kdbkeys/do-test.pl create mode 100644 krb5-1-6/src/kadmin/ktutil/Makefile.in create mode 100644 krb5-1-6/src/kadmin/ktutil/ktutil.M create mode 100644 krb5-1-6/src/kadmin/ktutil/ktutil.c create mode 100644 krb5-1-6/src/kadmin/ktutil/ktutil.h create mode 100644 krb5-1-6/src/kadmin/ktutil/ktutil_ct.ct create mode 100644 krb5-1-6/src/kadmin/ktutil/ktutil_funcs.c create mode 100644 krb5-1-6/src/kadmin/passwd/Kpasswd create mode 100644 krb5-1-6/src/kadmin/passwd/Makefile.in create mode 100644 krb5-1-6/src/kadmin/passwd/kpasswd.M create mode 100644 krb5-1-6/src/kadmin/passwd/kpasswd.c create mode 100644 krb5-1-6/src/kadmin/passwd/kpasswd.h create mode 100644 krb5-1-6/src/kadmin/passwd/kpasswd_strings.et create mode 100644 krb5-1-6/src/kadmin/passwd/tty_kpasswd.c create mode 100644 krb5-1-6/src/kadmin/passwd/unit-test/Makefile.in create mode 100644 krb5-1-6/src/kadmin/passwd/unit-test/config/unix.exp create mode 100644 krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp create mode 100644 krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/connecting.exp create mode 100644 krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp create mode 100644 krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/usage.exp create mode 100644 krb5-1-6/src/kadmin/passwd/unit-test/lib/helpers.exp create mode 100644 krb5-1-6/src/kadmin/passwd/xm_kpasswd.c create mode 100755 krb5-1-6/src/kadmin/scripts/inst-hdrs.sh create mode 100644 krb5-1-6/src/kadmin/server/Makefile.in create mode 100644 krb5-1-6/src/kadmin/server/acls.l create mode 100644 krb5-1-6/src/kadmin/server/kadm_rpc_svc.c create mode 100644 krb5-1-6/src/kadmin/server/kadmind.M create mode 100644 krb5-1-6/src/kadmin/server/misc.c create mode 100644 krb5-1-6/src/kadmin/server/misc.h create mode 100644 krb5-1-6/src/kadmin/server/ovsec_kadmd.c create mode 100644 krb5-1-6/src/kadmin/server/schpw.c create mode 100644 krb5-1-6/src/kadmin/server/server_glue_v1.c create mode 100644 krb5-1-6/src/kadmin/server/server_stubs.c create mode 100644 krb5-1-6/src/kadmin/testing/Makefile.in create mode 100644 krb5-1-6/src/kadmin/testing/proto/kdc.conf.proto create mode 100644 krb5-1-6/src/kadmin/testing/proto/krb5.conf.proto create mode 100644 krb5-1-6/src/kadmin/testing/proto/ovsec_adm.dict create mode 100644 krb5-1-6/src/kadmin/testing/scripts/Makefile.in create mode 100755 krb5-1-6/src/kadmin/testing/scripts/compare_dump.plin create mode 100755 krb5-1-6/src/kadmin/testing/scripts/env-setup.shin create mode 100755 krb5-1-6/src/kadmin/testing/scripts/find-make.sh create mode 100755 krb5-1-6/src/kadmin/testing/scripts/fixup-conf-files.plin create mode 100755 krb5-1-6/src/kadmin/testing/scripts/init_db create mode 100755 krb5-1-6/src/kadmin/testing/scripts/make-host-keytab.plin create mode 100755 krb5-1-6/src/kadmin/testing/scripts/qualname.plin create mode 100755 krb5-1-6/src/kadmin/testing/scripts/save_files.sh create mode 100755 krb5-1-6/src/kadmin/testing/scripts/simple_dump.plin create mode 100755 krb5-1-6/src/kadmin/testing/scripts/start_servers create mode 100755 krb5-1-6/src/kadmin/testing/scripts/start_servers_local create mode 100755 krb5-1-6/src/kadmin/testing/scripts/stop_servers create mode 100755 krb5-1-6/src/kadmin/testing/scripts/stop_servers_local create mode 100755 krb5-1-6/src/kadmin/testing/scripts/verify_xrunner_report.plin create mode 100644 krb5-1-6/src/kadmin/testing/tcl/util.t create mode 100644 krb5-1-6/src/kadmin/testing/util/Makefile.in create mode 100644 krb5-1-6/src/kadmin/testing/util/bsddb_dump.c create mode 100644 krb5-1-6/src/kadmin/testing/util/tcl_kadm5.c create mode 100644 krb5-1-6/src/kadmin/testing/util/tcl_kadm5.h create mode 100644 krb5-1-6/src/kadmin/testing/util/tcl_krb5_hash.c create mode 100644 krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm.c create mode 100644 krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm_syntax create mode 100644 krb5-1-6/src/kadmin/testing/util/test.c create mode 100644 krb5-1-6/src/kdc/.saberinit create mode 100644 krb5-1-6/src/kdc/Makefile.in create mode 100644 krb5-1-6/src/kdc/dispatch.c create mode 100644 krb5-1-6/src/kdc/do_as_req.c create mode 100644 krb5-1-6/src/kdc/do_tgs_req.c create mode 100644 krb5-1-6/src/kdc/extern.c create mode 100644 krb5-1-6/src/kdc/extern.h create mode 100644 krb5-1-6/src/kdc/fakeka.M create mode 100644 krb5-1-6/src/kdc/fakeka.c create mode 100644 krb5-1-6/src/kdc/kdc5_err.et create mode 100644 krb5-1-6/src/kdc/kdc_preauth.c create mode 100644 krb5-1-6/src/kdc/kdc_util.c create mode 100644 krb5-1-6/src/kdc/kdc_util.h create mode 100644 krb5-1-6/src/kdc/kerberos_v4.c create mode 100644 krb5-1-6/src/kdc/krb5kdc.M create mode 100644 krb5-1-6/src/kdc/main.c create mode 100644 krb5-1-6/src/kdc/migration.doc create mode 100644 krb5-1-6/src/kdc/network.c create mode 100644 krb5-1-6/src/kdc/policy.c create mode 100644 krb5-1-6/src/kdc/policy.h create mode 100644 krb5-1-6/src/kdc/replay.c create mode 100644 krb5-1-6/src/kdc/rtest.c create mode 100644 krb5-1-6/src/kdc/rtest.good create mode 100755 krb5-1-6/src/kdc/rtscript create mode 100644 krb5-1-6/src/krb5-config.M create mode 100755 krb5-1-6/src/krb5-config.in create mode 100644 krb5-1-6/src/krb524/Makefile.in create mode 100644 krb5-1-6/src/krb524/README create mode 100644 krb5-1-6/src/krb524/cnv_tkt_skey.c create mode 100644 krb5-1-6/src/krb524/conv_princ.c create mode 100644 krb5-1-6/src/krb524/k524init.M create mode 100644 krb5-1-6/src/krb524/k524init.c create mode 100644 krb5-1-6/src/krb524/krb524.c create mode 100644 krb5-1-6/src/krb524/krb524.def create mode 100644 krb5-1-6/src/krb524/krb524_prot create mode 100644 krb5-1-6/src/krb524/krb524d.M create mode 100644 krb5-1-6/src/krb524/krb524d.c create mode 100644 krb5-1-6/src/krb524/krb524d.h create mode 100644 krb5-1-6/src/krb524/libinit.c create mode 100644 krb5-1-6/src/krb524/test.c create mode 100644 krb5-1-6/src/lib/Makefile.in create mode 100644 krb5-1-6/src/lib/apputils/Makefile.in create mode 100644 krb5-1-6/src/lib/apputils/configure.in create mode 100644 krb5-1-6/src/lib/apputils/daemon.c create mode 100644 krb5-1-6/src/lib/apputils/dummy.c create mode 100644 krb5-1-6/src/lib/comerr32.def create mode 100644 krb5-1-6/src/lib/crypto/ISSUES create mode 100644 krb5-1-6/src/lib/crypto/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/aes/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/aes/aes-gen.c create mode 100644 krb5-1-6/src/lib/crypto/aes/aes-test.c create mode 100644 krb5-1-6/src/lib/crypto/aes/aes.h create mode 100644 krb5-1-6/src/lib/crypto/aes/aes.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/aes_s2k.c create mode 100644 krb5-1-6/src/lib/crypto/aes/aes_s2k.h create mode 100644 krb5-1-6/src/lib/crypto/aes/aescpp.h create mode 100644 krb5-1-6/src/lib/crypto/aes/aescrypp.c create mode 100644 krb5-1-6/src/lib/crypto/aes/aescrypt.asm create mode 100644 krb5-1-6/src/lib/crypto/aes/aescrypt.c create mode 100644 krb5-1-6/src/lib/crypto/aes/aeskey.c create mode 100644 krb5-1-6/src/lib/crypto/aes/aeskeypp.c create mode 100644 krb5-1-6/src/lib/crypto/aes/aesopt.h create mode 100644 krb5-1-6/src/lib/crypto/aes/aessrc.url create mode 100644 krb5-1-6/src/lib/crypto/aes/aestab.c create mode 100644 krb5-1-6/src/lib/crypto/aes/expect-vk.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/expect-vt.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/Readme.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/cbc_d_m.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/cbc_e_m.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/ecb_d_m.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/ecb_e_m.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/ecb_iv.readme create mode 100644 krb5-1-6/src/lib/crypto/aes/test/ecb_iv.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/ecb_tbl.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/ecb_vk.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/ecb_vt.txt create mode 100644 krb5-1-6/src/lib/crypto/aes/test/katmct.pdf create mode 100644 krb5-1-6/src/lib/crypto/aes/uitypes.h create mode 100644 krb5-1-6/src/lib/crypto/aes/vb.txt create mode 100644 krb5-1-6/src/lib/crypto/arcfour/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/arcfour/arcfour-int.h create mode 100644 krb5-1-6/src/lib/crypto/arcfour/arcfour.c create mode 100644 krb5-1-6/src/lib/crypto/arcfour/arcfour.h create mode 100644 krb5-1-6/src/lib/crypto/arcfour/arcfour_s2k.c create mode 100644 krb5-1-6/src/lib/crypto/block_size.c create mode 100644 krb5-1-6/src/lib/crypto/checksum_length.c create mode 100644 krb5-1-6/src/lib/crypto/cksumtype_to_string.c create mode 100644 krb5-1-6/src/lib/crypto/cksumtypes.c create mode 100644 krb5-1-6/src/lib/crypto/cksumtypes.h create mode 100644 krb5-1-6/src/lib/crypto/coll_proof_cksum.c create mode 100644 krb5-1-6/src/lib/crypto/combine_keys.c create mode 100644 krb5-1-6/src/lib/crypto/crc32/CRC.pm create mode 100644 krb5-1-6/src/lib/crypto/crc32/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/crc32/Poly.pm create mode 100644 krb5-1-6/src/lib/crypto/crc32/crc-32.h create mode 100644 krb5-1-6/src/lib/crypto/crc32/crc.pl create mode 100644 krb5-1-6/src/lib/crypto/crc32/crc32.c create mode 100644 krb5-1-6/src/lib/crypto/crc32/t_crc.c create mode 100644 krb5-1-6/src/lib/crypto/crypto_libinit.c create mode 100644 krb5-1-6/src/lib/crypto/decrypt.c create mode 100644 krb5-1-6/src/lib/crypto/default_state.c create mode 100644 krb5-1-6/src/lib/crypto/des/ISSUES create mode 100644 krb5-1-6/src/lib/crypto/des/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/des/afsstring2key.c create mode 100644 krb5-1-6/src/lib/crypto/des/d3_cbc.c create mode 100644 krb5-1-6/src/lib/crypto/des/d3_kysched.c create mode 100644 krb5-1-6/src/lib/crypto/des/des_int.h create mode 100644 krb5-1-6/src/lib/crypto/des/destest.c create mode 100644 krb5-1-6/src/lib/crypto/des/doc/libdes.doc create mode 100644 krb5-1-6/src/lib/crypto/des/f_cbc.c create mode 100644 krb5-1-6/src/lib/crypto/des/f_cksum.c create mode 100644 krb5-1-6/src/lib/crypto/des/f_parity.c create mode 100644 krb5-1-6/src/lib/crypto/des/f_sched.c create mode 100644 krb5-1-6/src/lib/crypto/des/f_tables.c create mode 100644 krb5-1-6/src/lib/crypto/des/f_tables.h create mode 100644 krb5-1-6/src/lib/crypto/des/key_sched.c create mode 100644 krb5-1-6/src/lib/crypto/des/keytest.data create mode 100644 krb5-1-6/src/lib/crypto/des/string2key.c create mode 100644 krb5-1-6/src/lib/crypto/des/t_afss2k.c create mode 100644 krb5-1-6/src/lib/crypto/des/t_verify.c create mode 100644 krb5-1-6/src/lib/crypto/des/weak_key.c create mode 100644 krb5-1-6/src/lib/crypto/dk/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/dk/checksum.c create mode 100644 krb5-1-6/src/lib/crypto/dk/derive.c create mode 100644 krb5-1-6/src/lib/crypto/dk/dk.h create mode 100644 krb5-1-6/src/lib/crypto/dk/dk_decrypt.c create mode 100644 krb5-1-6/src/lib/crypto/dk/dk_encrypt.c create mode 100644 krb5-1-6/src/lib/crypto/dk/dk_prf.c create mode 100644 krb5-1-6/src/lib/crypto/dk/stringtokey.c create mode 100644 krb5-1-6/src/lib/crypto/enc_provider/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/enc_provider/aes.c create mode 100644 krb5-1-6/src/lib/crypto/enc_provider/des.c create mode 100644 krb5-1-6/src/lib/crypto/enc_provider/des3.c create mode 100644 krb5-1-6/src/lib/crypto/enc_provider/enc_provider.h create mode 100644 krb5-1-6/src/lib/crypto/enc_provider/rc4.c create mode 100644 krb5-1-6/src/lib/crypto/encrypt.c create mode 100644 krb5-1-6/src/lib/crypto/encrypt_length.c create mode 100644 krb5-1-6/src/lib/crypto/enctype_compare.c create mode 100644 krb5-1-6/src/lib/crypto/enctype_to_string.c create mode 100644 krb5-1-6/src/lib/crypto/etypes.c create mode 100644 krb5-1-6/src/lib/crypto/etypes.h create mode 100644 krb5-1-6/src/lib/crypto/hash_provider/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/hash_provider/hash_crc32.c create mode 100644 krb5-1-6/src/lib/crypto/hash_provider/hash_md4.c create mode 100644 krb5-1-6/src/lib/crypto/hash_provider/hash_md5.c create mode 100644 krb5-1-6/src/lib/crypto/hash_provider/hash_provider.h create mode 100644 krb5-1-6/src/lib/crypto/hash_provider/hash_sha1.c create mode 100644 krb5-1-6/src/lib/crypto/hmac.c create mode 100644 krb5-1-6/src/lib/crypto/keyblocks.c create mode 100644 krb5-1-6/src/lib/crypto/keyed_checksum_types.c create mode 100644 krb5-1-6/src/lib/crypto/keyed_cksum.c create mode 100644 krb5-1-6/src/lib/crypto/keyhash_provider/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/keyhash_provider/descbc.c create mode 100644 krb5-1-6/src/lib/crypto/keyhash_provider/hmac_md5.c create mode 100644 krb5-1-6/src/lib/crypto/keyhash_provider/k5_md4des.c create mode 100644 krb5-1-6/src/lib/crypto/keyhash_provider/k5_md5des.c create mode 100644 krb5-1-6/src/lib/crypto/keyhash_provider/keyhash_provider.h create mode 100644 krb5-1-6/src/lib/crypto/keyhash_provider/t_cksum.c create mode 100644 krb5-1-6/src/lib/crypto/keylengths.c create mode 100644 krb5-1-6/src/lib/crypto/libk5crypto.exports create mode 100644 krb5-1-6/src/lib/crypto/make_checksum.c create mode 100644 krb5-1-6/src/lib/crypto/make_random_key.c create mode 100644 krb5-1-6/src/lib/crypto/mandatory_sumtype.c create mode 100644 krb5-1-6/src/lib/crypto/md4/ISSUES create mode 100644 krb5-1-6/src/lib/crypto/md4/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/md4/md4.c create mode 100644 krb5-1-6/src/lib/crypto/md4/rsa-md4.h create mode 100644 krb5-1-6/src/lib/crypto/md5/ISSUES create mode 100644 krb5-1-6/src/lib/crypto/md5/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/md5/md5.c create mode 100644 krb5-1-6/src/lib/crypto/md5/rsa-md5.h create mode 100644 krb5-1-6/src/lib/crypto/md5/t_cksum.c create mode 100644 krb5-1-6/src/lib/crypto/md5/t_mddriver.c create mode 100644 krb5-1-6/src/lib/crypto/nfold.c create mode 100644 krb5-1-6/src/lib/crypto/old/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/old/des_stringtokey.c create mode 100644 krb5-1-6/src/lib/crypto/old/old.h create mode 100644 krb5-1-6/src/lib/crypto/old/old_decrypt.c create mode 100644 krb5-1-6/src/lib/crypto/old/old_encrypt.c create mode 100644 krb5-1-6/src/lib/crypto/old_api_glue.c create mode 100644 krb5-1-6/src/lib/crypto/pbkdf2.c create mode 100644 krb5-1-6/src/lib/crypto/prf.c create mode 100644 krb5-1-6/src/lib/crypto/prng.c create mode 100644 krb5-1-6/src/lib/crypto/random_to_key.c create mode 100644 krb5-1-6/src/lib/crypto/raw/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/raw/raw.h create mode 100644 krb5-1-6/src/lib/crypto/raw/raw_decrypt.c create mode 100644 krb5-1-6/src/lib/crypto/raw/raw_encrypt.c create mode 100644 krb5-1-6/src/lib/crypto/sha1/ISSUES create mode 100644 krb5-1-6/src/lib/crypto/sha1/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/sha1/shs.c create mode 100644 krb5-1-6/src/lib/crypto/sha1/shs.h create mode 100644 krb5-1-6/src/lib/crypto/sha1/t_shs.c create mode 100644 krb5-1-6/src/lib/crypto/sha1/t_shs3.c create mode 100644 krb5-1-6/src/lib/crypto/state.c create mode 100644 krb5-1-6/src/lib/crypto/string_to_cksumtype.c create mode 100644 krb5-1-6/src/lib/crypto/string_to_enctype.c create mode 100644 krb5-1-6/src/lib/crypto/string_to_key.c create mode 100644 krb5-1-6/src/lib/crypto/t_cts.c create mode 100644 krb5-1-6/src/lib/crypto/t_encrypt.c create mode 100644 krb5-1-6/src/lib/crypto/t_hmac.c create mode 100644 krb5-1-6/src/lib/crypto/t_nfold.c create mode 100644 krb5-1-6/src/lib/crypto/t_pkcs5.c create mode 100644 krb5-1-6/src/lib/crypto/t_prf.c create mode 100644 krb5-1-6/src/lib/crypto/t_prng.c create mode 100644 krb5-1-6/src/lib/crypto/t_prng.comments create mode 100644 krb5-1-6/src/lib/crypto/t_prng.expected create mode 100644 krb5-1-6/src/lib/crypto/t_prng.reseedtest create mode 100644 krb5-1-6/src/lib/crypto/t_prng.reseedtest-comments create mode 100644 krb5-1-6/src/lib/crypto/t_prng.reseedtest-expected create mode 100644 krb5-1-6/src/lib/crypto/t_prng.seed create mode 100644 krb5-1-6/src/lib/crypto/valid_cksumtype.c create mode 100644 krb5-1-6/src/lib/crypto/valid_enctype.c create mode 100644 krb5-1-6/src/lib/crypto/vectors.c create mode 100644 krb5-1-6/src/lib/crypto/verify_checksum.c create mode 100644 krb5-1-6/src/lib/crypto/yarrow/ASSUMPTIONS create mode 100644 krb5-1-6/src/lib/crypto/yarrow/LICENSE create mode 100644 krb5-1-6/src/lib/crypto/yarrow/Makefile.in create mode 100644 krb5-1-6/src/lib/crypto/yarrow/README create mode 100644 krb5-1-6/src/lib/crypto/yarrow/TODO create mode 100644 krb5-1-6/src/lib/crypto/yarrow/yarrow.c create mode 100644 krb5-1-6/src/lib/crypto/yarrow/yarrow.h create mode 100644 krb5-1-6/src/lib/crypto/yarrow/yarrow.man create mode 100644 krb5-1-6/src/lib/crypto/yarrow/yarrow.pod create mode 100644 krb5-1-6/src/lib/crypto/yarrow/ycipher.c create mode 100644 krb5-1-6/src/lib/crypto/yarrow/ycipher.h create mode 100644 krb5-1-6/src/lib/crypto/yarrow/yexcep.h create mode 100644 krb5-1-6/src/lib/crypto/yarrow/yhash.h create mode 100644 krb5-1-6/src/lib/crypto/yarrow/ylock.h create mode 100644 krb5-1-6/src/lib/crypto/yarrow/ystate.h create mode 100644 krb5-1-6/src/lib/crypto/yarrow/ytest.c create mode 100644 krb5-1-6/src/lib/crypto/yarrow/ytypes.h create mode 100644 krb5-1-6/src/lib/des425/ISSUES create mode 100644 krb5-1-6/src/lib/des425/Makefile.in create mode 100644 krb5-1-6/src/lib/des425/cksum.c create mode 100644 krb5-1-6/src/lib/des425/des.c create mode 100644 krb5-1-6/src/lib/des425/enc_dec.c create mode 100644 krb5-1-6/src/lib/des425/key_parity.c create mode 100644 krb5-1-6/src/lib/des425/key_sched.c create mode 100644 krb5-1-6/src/lib/des425/libdes425.exports create mode 100644 krb5-1-6/src/lib/des425/mac_des_glue.c create mode 100644 krb5-1-6/src/lib/des425/new_rnd_key.c create mode 100644 krb5-1-6/src/lib/des425/pcbc_encrypt.c create mode 100644 krb5-1-6/src/lib/des425/quad_cksum.c create mode 100644 krb5-1-6/src/lib/des425/random_key.c create mode 100644 krb5-1-6/src/lib/des425/read_passwd.c create mode 100644 krb5-1-6/src/lib/des425/str_to_key.c create mode 100644 krb5-1-6/src/lib/des425/string2key.c create mode 100644 krb5-1-6/src/lib/des425/t_pcbc.c create mode 100644 krb5-1-6/src/lib/des425/t_quad.c create mode 100644 krb5-1-6/src/lib/des425/unix_time.c create mode 100644 krb5-1-6/src/lib/des425/util.c create mode 100644 krb5-1-6/src/lib/des425/verify.c create mode 100644 krb5-1-6/src/lib/des425/weak_key.c create mode 100644 krb5-1-6/src/lib/glue4.c create mode 100644 krb5-1-6/src/lib/gssapi/LICENSE create mode 100644 krb5-1-6/src/lib/gssapi/Makefile.in create mode 100644 krb5-1-6/src/lib/gssapi/README_SAMPLE_APP create mode 100644 krb5-1-6/src/lib/gssapi/generic/Makefile.in create mode 100644 krb5-1-6/src/lib/gssapi/generic/disp_com_err_status.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/disp_major_status.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/gssapi.hin create mode 100644 krb5-1-6/src/lib/gssapi/generic/gssapiP_generic.h create mode 100644 krb5-1-6/src/lib/gssapi/generic/gssapi_err_generic.et create mode 100644 krb5-1-6/src/lib/gssapi/generic/gssapi_generic.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/gssapi_generic.h create mode 100644 krb5-1-6/src/lib/gssapi/generic/rel_buffer.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/rel_oid_set.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/util_buffer.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/util_canonhost.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/util_localhost.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/util_ordering.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/util_set.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/util_token.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/util_validate.c create mode 100644 krb5-1-6/src/lib/gssapi/generic/utl_nohash_validate.c create mode 100644 krb5-1-6/src/lib/gssapi/gss_libinit.c create mode 100644 krb5-1-6/src/lib/gssapi/gss_libinit.h create mode 100644 krb5-1-6/src/lib/gssapi/krb5/3des.txt create mode 100644 krb5-1-6/src/lib/gssapi/krb5/Makefile.in create mode 100644 krb5-1-6/src/lib/gssapi/krb5/accept_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/acquire_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/add_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/canon_name.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/compare_name.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/context_time.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/copy_ccache.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/delete_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/disp_name.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/disp_status.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/duplicate_name.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/export_name.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/export_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/get_tkt_flags.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/gssapiP_krb5.h create mode 100644 krb5-1-6/src/lib/gssapi/krb5/gssapi_err_krb5.et create mode 100644 krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.hin create mode 100644 krb5-1-6/src/lib/gssapi/krb5/import_name.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/import_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/indicate_mechs.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/init_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/inq_context.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/inq_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/inq_names.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/k5seal.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/k5sealv3.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/k5unseal.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/krb5_gss_glue.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/lucid_context.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/process_context_token.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/rel_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/rel_name.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/rel_oid.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/seal.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/ser_sctx.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/set_allowable_enctypes.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/set_ccache.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/sign.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/unseal.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/util_cksum.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/util_crypt.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/util_seed.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/util_seqnum.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/val_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/verify.c create mode 100644 krb5-1-6/src/lib/gssapi/krb5/wrap_size_limit.c create mode 100644 krb5-1-6/src/lib/gssapi/libgssapi_krb5.exports create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/Makefile.in create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_accept_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_acquire_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_canon_name.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_compare_name.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_context_time.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_delete_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_dsp_name.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_dsp_status.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_dup_name.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_exp_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_export_name.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_glue.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_imp_name.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_imp_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_init_sec_context.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_initialize.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_inq_context.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_inq_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_inq_names.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_mechname.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_oid_ops.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_process_context.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_rel_buffer.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_rel_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_rel_name.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_rel_oid_set.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_seal.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_sign.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_store_cred.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_unseal.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/g_verify.c create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/mech.conf create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/mechglue.h create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/mglueP.h create mode 100644 krb5-1-6/src/lib/gssapi/mechglue/oid_ops.c create mode 100644 krb5-1-6/src/lib/gssapi/spnego/Makefile.in create mode 100644 krb5-1-6/src/lib/gssapi/spnego/gssapiP_spnego.h create mode 100644 krb5-1-6/src/lib/gssapi/spnego/spnego_mech.c create mode 100644 krb5-1-6/src/lib/gssapi32.def create mode 100644 krb5-1-6/src/lib/kadm5/Makefile.in create mode 100644 krb5-1-6/src/lib/kadm5/adb.h create mode 100644 krb5-1-6/src/lib/kadm5/admin.h create mode 100644 krb5-1-6/src/lib/kadm5/admin_internal.h create mode 100644 krb5-1-6/src/lib/kadm5/admin_xdr.h create mode 100644 krb5-1-6/src/lib/kadm5/alt_prof.c create mode 100644 krb5-1-6/src/lib/kadm5/chpass_util.c create mode 100644 krb5-1-6/src/lib/kadm5/chpass_util_strings.et create mode 100644 krb5-1-6/src/lib/kadm5/clnt/Makefile.in create mode 100644 krb5-1-6/src/lib/kadm5/clnt/client_handle.c create mode 100644 krb5-1-6/src/lib/kadm5/clnt/client_init.c create mode 100644 krb5-1-6/src/lib/kadm5/clnt/client_internal.h create mode 100644 krb5-1-6/src/lib/kadm5/clnt/client_principal.c create mode 100644 krb5-1-6/src/lib/kadm5/clnt/client_rpc.c create mode 100644 krb5-1-6/src/lib/kadm5/clnt/clnt_chpass_util.c create mode 100644 krb5-1-6/src/lib/kadm5/clnt/clnt_policy.c create mode 100644 krb5-1-6/src/lib/kadm5/clnt/clnt_privs.c create mode 100644 krb5-1-6/src/lib/kadm5/clnt/libkadm5clnt.exports create mode 100644 krb5-1-6/src/lib/kadm5/kadm_err.et create mode 100644 krb5-1-6/src/lib/kadm5/kadm_rpc.h create mode 100644 krb5-1-6/src/lib/kadm5/kadm_rpc_xdr.c create mode 100644 krb5-1-6/src/lib/kadm5/logger.c create mode 100644 krb5-1-6/src/lib/kadm5/misc_free.c create mode 100644 krb5-1-6/src/lib/kadm5/ovsec_glue.c create mode 100644 krb5-1-6/src/lib/kadm5/server_internal.h create mode 100644 krb5-1-6/src/lib/kadm5/srv/Makefile.in create mode 100644 krb5-1-6/src/lib/kadm5/srv/adb_xdr.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/libkadm5srv.exports create mode 100644 krb5-1-6/src/lib/kadm5/srv/server_acl.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/server_acl.h create mode 100644 krb5-1-6/src/lib/kadm5/srv/server_dict.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/server_handle.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/server_init.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/server_kdb.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/server_misc.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/svr_chpass_util.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/svr_iters.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/svr_misc_free.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/svr_policy.c create mode 100644 krb5-1-6/src/lib/kadm5/srv/svr_principal.c create mode 100644 krb5-1-6/src/lib/kadm5/str_conv.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/Makefile.in create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/README.new-tests create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/chpass-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/destroy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/get-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/get-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/init.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/randkey-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.0/rename-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.1/lock.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/destroy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/get-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/init-v2.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/init.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-policy.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/config/unix.exp create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/destroy-test.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/diff-files/destroy-1 create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/diff-files/no-diffs create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/handle-test.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/init-test.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/iter-test.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/lib/lib.t create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/lock-test.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/randkey-test.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/setkey-test.c create mode 100644 krb5-1-6/src/lib/kadm5/unit-test/site.exp create mode 100644 krb5-1-6/src/lib/kdb/Makefile.in create mode 100644 krb5-1-6/src/lib/kdb/adb_err.et create mode 100644 krb5-1-6/src/lib/kdb/decrypt_key.c create mode 100644 krb5-1-6/src/lib/kdb/encrypt_key.c create mode 100644 krb5-1-6/src/lib/kdb/kdb5.c create mode 100644 krb5-1-6/src/lib/kdb/kdb5.h create mode 100644 krb5-1-6/src/lib/kdb/kdb_cpw.c create mode 100644 krb5-1-6/src/lib/kdb/kdb_default.c create mode 100644 krb5-1-6/src/lib/kdb/keytab.c create mode 100644 krb5-1-6/src/lib/kdb/libkdb5.exports create mode 100644 krb5-1-6/src/lib/krb4/CCache-glue.c create mode 100644 krb5-1-6/src/lib/krb4/FSp-glue.c create mode 100644 krb5-1-6/src/lib/krb4/Makefile.in create mode 100644 krb5-1-6/src/lib/krb4/Password.c create mode 100644 krb5-1-6/src/lib/krb4/RealmsConfig-glue.c create mode 100644 krb5-1-6/src/lib/krb4/ad_print.c create mode 100644 krb5-1-6/src/lib/krb4/change_password.c create mode 100644 krb5-1-6/src/lib/krb4/cr_auth_repl.c create mode 100644 krb5-1-6/src/lib/krb4/cr_ciph.c create mode 100644 krb5-1-6/src/lib/krb4/cr_death_pkt.c create mode 100644 krb5-1-6/src/lib/krb4/cr_err_repl.c create mode 100644 krb5-1-6/src/lib/krb4/cr_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/debug.c create mode 100644 krb5-1-6/src/lib/krb4/decomp_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/dest_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/err_txt.c create mode 100755 krb5-1-6/src/lib/krb4/et_errtxt.awk create mode 100644 krb5-1-6/src/lib/krb4/fgetst.c create mode 100644 krb5-1-6/src/lib/krb4/g_ad_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/g_cnffile.c create mode 100644 krb5-1-6/src/lib/krb4/g_cred.c create mode 100644 krb5-1-6/src/lib/krb4/g_in_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/g_phost.c create mode 100644 krb5-1-6/src/lib/krb4/g_pw_in_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/g_pw_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/g_svc_in_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/g_tf_fname.c create mode 100644 krb5-1-6/src/lib/krb4/g_tf_realm.c create mode 100644 krb5-1-6/src/lib/krb4/g_tkt_svc.c create mode 100644 krb5-1-6/src/lib/krb4/gethostname.c create mode 100644 krb5-1-6/src/lib/krb4/getst.c create mode 100644 krb5-1-6/src/lib/krb4/in_tkt.c create mode 100644 krb5-1-6/src/lib/krb4/kadm_err.et create mode 100644 krb5-1-6/src/lib/krb4/kadm_net.c create mode 100644 krb5-1-6/src/lib/krb4/kadm_stream.c create mode 100644 krb5-1-6/src/lib/krb4/klog.c create mode 100644 krb5-1-6/src/lib/krb4/kname_parse.c create mode 100644 krb5-1-6/src/lib/krb4/kntoln.c create mode 100644 krb5-1-6/src/lib/krb4/kparse.c create mode 100644 krb5-1-6/src/lib/krb4/krb4int.h create mode 100644 krb5-1-6/src/lib/krb4/krb_err.et create mode 100644 krb5-1-6/src/lib/krb4/kuserok.c create mode 100644 krb5-1-6/src/lib/krb4/libkrb4.exports create mode 100644 krb5-1-6/src/lib/krb4/lifetime.c create mode 100644 krb5-1-6/src/lib/krb4/log.c create mode 100644 krb5-1-6/src/lib/krb4/mac_glue.c create mode 100644 krb5-1-6/src/lib/krb4/mac_store.c create mode 100644 krb5-1-6/src/lib/krb4/mac_store.h create mode 100644 krb5-1-6/src/lib/krb4/mac_stubs.c create mode 100644 krb5-1-6/src/lib/krb4/mac_time.c create mode 100644 krb5-1-6/src/lib/krb4/memcache.c create mode 100644 krb5-1-6/src/lib/krb4/memcache.h create mode 100644 krb5-1-6/src/lib/krb4/mk_auth.c create mode 100644 krb5-1-6/src/lib/krb4/mk_err.c create mode 100644 krb5-1-6/src/lib/krb4/mk_preauth.c create mode 100644 krb5-1-6/src/lib/krb4/mk_priv.c create mode 100644 krb5-1-6/src/lib/krb4/mk_req.c create mode 100644 krb5-1-6/src/lib/krb4/mk_safe.c create mode 100644 krb5-1-6/src/lib/krb4/month_sname.c create mode 100644 krb5-1-6/src/lib/krb4/netread.c create mode 100644 krb5-1-6/src/lib/krb4/netwrite.c create mode 100644 krb5-1-6/src/lib/krb4/password_to_key.c create mode 100644 krb5-1-6/src/lib/krb4/pkt_cipher.c create mode 100644 krb5-1-6/src/lib/krb4/pkt_clen.c create mode 100644 krb5-1-6/src/lib/krb4/prot_client.c create mode 100644 krb5-1-6/src/lib/krb4/prot_common.c create mode 100644 krb5-1-6/src/lib/krb4/prot_kdc.c create mode 100644 krb5-1-6/src/lib/krb4/put_svc_key.c create mode 100644 krb5-1-6/src/lib/krb4/rd_err.c create mode 100644 krb5-1-6/src/lib/krb4/rd_preauth.c create mode 100644 krb5-1-6/src/lib/krb4/rd_priv.c create mode 100644 krb5-1-6/src/lib/krb4/rd_req.c create mode 100644 krb5-1-6/src/lib/krb4/rd_safe.c create mode 100644 krb5-1-6/src/lib/krb4/rd_svc_key.c create mode 100644 krb5-1-6/src/lib/krb4/recvauth.c create mode 100755 krb5-1-6/src/lib/krb4/ren-cyg.sh create mode 100644 krb5-1-6/src/lib/krb4/ren-pc.bat create mode 100644 krb5-1-6/src/lib/krb4/ren-pc.sh create mode 100644 krb5-1-6/src/lib/krb4/ren-pl10.sh create mode 100644 krb5-1-6/src/lib/krb4/ren.msg create mode 100644 krb5-1-6/src/lib/krb4/ren2dos.sh create mode 100644 krb5-1-6/src/lib/krb4/ren2long.sh create mode 100644 krb5-1-6/src/lib/krb4/save_creds.c create mode 100755 krb5-1-6/src/lib/krb4/sed-cyg.sh create mode 100755 krb5-1-6/src/lib/krb4/sed-pc.sh create mode 100755 krb5-1-6/src/lib/krb4/sed-pl10.sh create mode 100644 krb5-1-6/src/lib/krb4/send_to_kdc.c create mode 100644 krb5-1-6/src/lib/krb4/sendauth.c create mode 100644 krb5-1-6/src/lib/krb4/setenv.c create mode 100644 krb5-1-6/src/lib/krb4/stime.c create mode 100644 krb5-1-6/src/lib/krb4/strcasecmp.c create mode 100644 krb5-1-6/src/lib/krb4/strnlen.c create mode 100644 krb5-1-6/src/lib/krb4/swab.c create mode 100644 krb5-1-6/src/lib/krb4/tf_shm.c create mode 100644 krb5-1-6/src/lib/krb4/tf_util.c create mode 100644 krb5-1-6/src/lib/krb4/tkt_string.c create mode 100644 krb5-1-6/src/lib/krb4/unix_glue.c create mode 100644 krb5-1-6/src/lib/krb4/unix_time.c create mode 100644 krb5-1-6/src/lib/krb4/vmslink.com create mode 100644 krb5-1-6/src/lib/krb4/vmsswab.c create mode 100644 krb5-1-6/src/lib/krb4/win_glue.c create mode 100644 krb5-1-6/src/lib/krb4/win_store.c create mode 100644 krb5-1-6/src/lib/krb4/win_time.c create mode 100644 krb5-1-6/src/lib/krb4_32.def create mode 100644 krb5-1-6/src/lib/krb5.rc create mode 100644 krb5-1-6/src/lib/krb5/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/asn.1/.saberinit create mode 100644 krb5-1-6/src/lib/krb5/asn.1/KRB5-asn.py create mode 100644 krb5-1-6/src/lib/krb5/asn.1/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_decode.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_decode.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_encode.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_encode.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_get.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_get.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_make.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_make.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_misc.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1_misc.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1buf.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1buf.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/asn1glue.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/krb5_decode.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/krb5_encode.c create mode 100644 krb5-1-6/src/lib/krb5/asn.1/krbasn1.h create mode 100644 krb5-1-6/src/lib/krb5/asn.1/ldap_key_seq.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/ccache/cc-int.h create mode 100644 krb5-1-6/src/lib/krb5/ccache/cc_file.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/cc_keyring.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/cc_memory.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/cc_mslsa.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/cc_retr.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccapi/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.h create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.h create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.h create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccbase.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/cccopy.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/cccursor.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccdefault.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccdefops.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/ccfns.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/fcc.h create mode 100644 krb5-1-6/src/lib/krb5/ccache/scc.h create mode 100644 krb5-1-6/src/lib/krb5/ccache/ser_cc.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/t_cc.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/t_cccursor.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/t_memory.c create mode 100644 krb5-1-6/src/lib/krb5/ccache/t_stdio.c create mode 100644 krb5-1-6/src/lib/krb5/error_tables/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/error_tables/asn1_err.et create mode 100644 krb5-1-6/src/lib/krb5/error_tables/init_ets.c create mode 100644 krb5-1-6/src/lib/krb5/error_tables/kdb5_err.et create mode 100644 krb5-1-6/src/lib/krb5/error_tables/krb524_err.et create mode 100644 krb5-1-6/src/lib/krb5/error_tables/krb5_err.et create mode 100644 krb5-1-6/src/lib/krb5/error_tables/kv5m_err.et create mode 100644 krb5-1-6/src/lib/krb5/keytab/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/keytab/kt-int.h create mode 100644 krb5-1-6/src/lib/krb5/keytab/kt_file.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/kt_srvtab.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/ktadd.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/ktbase.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/ktdefault.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/ktfns.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/ktfr_entry.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/ktremove.c create mode 100644 krb5-1-6/src/lib/krb5/keytab/read_servi.c create mode 100644 krb5-1-6/src/lib/krb5/krb/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/krb/addr_comp.c create mode 100644 krb5-1-6/src/lib/krb5/krb/addr_order.c create mode 100644 krb5-1-6/src/lib/krb5/krb/addr_srch.c create mode 100644 krb5-1-6/src/lib/krb5/krb/appdefault.c create mode 100644 krb5-1-6/src/lib/krb5/krb/auth_con.c create mode 100644 krb5-1-6/src/lib/krb5/krb/auth_con.h create mode 100644 krb5-1-6/src/lib/krb5/krb/bld_pr_ext.c create mode 100644 krb5-1-6/src/lib/krb5/krb/bld_princ.c create mode 100644 krb5-1-6/src/lib/krb5/krb/brand.c create mode 100644 krb5-1-6/src/lib/krb5/krb/chk_trans.c create mode 100644 krb5-1-6/src/lib/krb5/krb/chpw.c create mode 100644 krb5-1-6/src/lib/krb5/krb/cleanup.h create mode 100644 krb5-1-6/src/lib/krb5/krb/conv_creds.c create mode 100644 krb5-1-6/src/lib/krb5/krb/conv_princ.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_addrs.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_athctr.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_auth.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_cksum.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_creds.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_data.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_key.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_princ.c create mode 100644 krb5-1-6/src/lib/krb5/krb/copy_tick.c create mode 100644 krb5-1-6/src/lib/krb5/krb/cp_key_cnt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/decode_kdc.c create mode 100644 krb5-1-6/src/lib/krb5/krb/decrypt_tk.c create mode 100644 krb5-1-6/src/lib/krb5/krb/deltat.c create mode 100644 krb5-1-6/src/lib/krb5/krb/enc_helper.c create mode 100644 krb5-1-6/src/lib/krb5/krb/encode_kdc.c create mode 100644 krb5-1-6/src/lib/krb5/krb/encrypt_tk.c create mode 100644 krb5-1-6/src/lib/krb5/krb/free_rtree.c create mode 100644 krb5-1-6/src/lib/krb5/krb/fwd_tgt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/gc_frm_kdc.c create mode 100644 krb5-1-6/src/lib/krb5/krb/gc_via_tkt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/gen_seqnum.c create mode 100644 krb5-1-6/src/lib/krb5/krb/gen_subkey.c create mode 100644 krb5-1-6/src/lib/krb5/krb/get_creds.c create mode 100644 krb5-1-6/src/lib/krb5/krb/get_in_tkt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/gic_keytab.c create mode 100644 krb5-1-6/src/lib/krb5/krb/gic_opt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/gic_pwd.c create mode 100644 krb5-1-6/src/lib/krb5/krb/in_tkt_sky.c create mode 100644 krb5-1-6/src/lib/krb5/krb/init_ctx.c create mode 100644 krb5-1-6/src/lib/krb5/krb/init_keyblock.c create mode 100644 krb5-1-6/src/lib/krb5/krb/int-proto.h create mode 100644 krb5-1-6/src/lib/krb5/krb/kdc_rep_dc.c create mode 100644 krb5-1-6/src/lib/krb5/krb/kerrs.c create mode 100644 krb5-1-6/src/lib/krb5/krb/kfree.c create mode 100644 krb5-1-6/src/lib/krb5/krb/mk_cred.c create mode 100644 krb5-1-6/src/lib/krb5/krb/mk_error.c create mode 100644 krb5-1-6/src/lib/krb5/krb/mk_priv.c create mode 100644 krb5-1-6/src/lib/krb5/krb/mk_rep.c create mode 100644 krb5-1-6/src/lib/krb5/krb/mk_req.c create mode 100644 krb5-1-6/src/lib/krb5/krb/mk_req_ext.c create mode 100644 krb5-1-6/src/lib/krb5/krb/mk_safe.c create mode 100644 krb5-1-6/src/lib/krb5/krb/parse.c create mode 100644 krb5-1-6/src/lib/krb5/krb/pr_to_salt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/preauth.c create mode 100644 krb5-1-6/src/lib/krb5/krb/preauth2.c create mode 100644 krb5-1-6/src/lib/krb5/krb/princ_comp.c create mode 100644 krb5-1-6/src/lib/krb5/krb/rd_cred.c create mode 100644 krb5-1-6/src/lib/krb5/krb/rd_error.c create mode 100644 krb5-1-6/src/lib/krb5/krb/rd_priv.c create mode 100644 krb5-1-6/src/lib/krb5/krb/rd_rep.c create mode 100644 krb5-1-6/src/lib/krb5/krb/rd_req.c create mode 100644 krb5-1-6/src/lib/krb5/krb/rd_req_dec.c create mode 100644 krb5-1-6/src/lib/krb5/krb/rd_safe.c create mode 100644 krb5-1-6/src/lib/krb5/krb/recvauth.c create mode 100644 krb5-1-6/src/lib/krb5/krb/send_tgs.c create mode 100644 krb5-1-6/src/lib/krb5/krb/sendauth.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_actx.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_adata.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_addr.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_auth.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_cksum.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_ctx.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_eblk.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_key.c create mode 100644 krb5-1-6/src/lib/krb5/krb/ser_princ.c create mode 100644 krb5-1-6/src/lib/krb5/krb/serialize.c create mode 100644 krb5-1-6/src/lib/krb5/krb/set_realm.c create mode 100644 krb5-1-6/src/lib/krb5/krb/srv_dec_tkt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/srv_rcache.c create mode 100644 krb5-1-6/src/lib/krb5/krb/str_conv.c create mode 100644 krb5-1-6/src/lib/krb5/krb/strftime.c create mode 100644 krb5-1-6/src/lib/krb5/krb/strptime.c create mode 100644 krb5-1-6/src/lib/krb5/krb/t_deltat.c create mode 100644 krb5-1-6/src/lib/krb5/krb/t_expand.c create mode 100644 krb5-1-6/src/lib/krb5/krb/t_kerb.c create mode 100644 krb5-1-6/src/lib/krb5/krb/t_krb5.conf create mode 100644 krb5-1-6/src/lib/krb5/krb/t_ref_kerb.out create mode 100644 krb5-1-6/src/lib/krb5/krb/t_ser.c create mode 100644 krb5-1-6/src/lib/krb5/krb/t_walk_rtree.c create mode 100644 krb5-1-6/src/lib/krb5/krb/tgtname.c create mode 100755 krb5-1-6/src/lib/krb5/krb/transit-tests create mode 100644 krb5-1-6/src/lib/krb5/krb/unparse.c create mode 100644 krb5-1-6/src/lib/krb5/krb/v4lifetime.c create mode 100644 krb5-1-6/src/lib/krb5/krb/valid_times.c create mode 100644 krb5-1-6/src/lib/krb5/krb/vfy_increds.c create mode 100644 krb5-1-6/src/lib/krb5/krb/vic_opt.c create mode 100644 krb5-1-6/src/lib/krb5/krb/walk_rtree.c create mode 100644 krb5-1-6/src/lib/krb5/krb/x-deltat.y create mode 100644 krb5-1-6/src/lib/krb5/krb5_libinit.c create mode 100644 krb5-1-6/src/lib/krb5/krb5_libinit.h create mode 100644 krb5-1-6/src/lib/krb5/libkrb5.exports create mode 100644 krb5-1-6/src/lib/krb5/os/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/os/accessor.c create mode 100644 krb5-1-6/src/lib/krb5/os/an_to_ln.c create mode 100644 krb5-1-6/src/lib/krb5/os/c_ustime.c create mode 100644 krb5-1-6/src/lib/krb5/os/ccdefname.c create mode 100644 krb5-1-6/src/lib/krb5/os/changepw.c create mode 100644 krb5-1-6/src/lib/krb5/os/def_realm.c create mode 100644 krb5-1-6/src/lib/krb5/os/dnsglue.c create mode 100644 krb5-1-6/src/lib/krb5/os/dnsglue.h create mode 100644 krb5-1-6/src/lib/krb5/os/dnssrv.c create mode 100644 krb5-1-6/src/lib/krb5/os/free_hstrl.c create mode 100644 krb5-1-6/src/lib/krb5/os/free_krbhs.c create mode 100644 krb5-1-6/src/lib/krb5/os/full_ipadr.c create mode 100644 krb5-1-6/src/lib/krb5/os/gen_port.c create mode 100644 krb5-1-6/src/lib/krb5/os/gen_rname.c create mode 100644 krb5-1-6/src/lib/krb5/os/genaddrs.c create mode 100644 krb5-1-6/src/lib/krb5/os/get_krbhst.c create mode 100644 krb5-1-6/src/lib/krb5/os/hostaddr.c create mode 100644 krb5-1-6/src/lib/krb5/os/hst_realm.c create mode 100644 krb5-1-6/src/lib/krb5/os/init_os_ctx.c create mode 100644 krb5-1-6/src/lib/krb5/os/krbfileio.c create mode 100644 krb5-1-6/src/lib/krb5/os/ktdefname.c create mode 100644 krb5-1-6/src/lib/krb5/os/kuserok.c create mode 100644 krb5-1-6/src/lib/krb5/os/localaddr.c create mode 100644 krb5-1-6/src/lib/krb5/os/locate_kdc.c create mode 100644 krb5-1-6/src/lib/krb5/os/lock_file.c create mode 100644 krb5-1-6/src/lib/krb5/os/mk_faddr.c create mode 100644 krb5-1-6/src/lib/krb5/os/net_read.c create mode 100644 krb5-1-6/src/lib/krb5/os/net_write.c create mode 100644 krb5-1-6/src/lib/krb5/os/os-proto.h create mode 100644 krb5-1-6/src/lib/krb5/os/osconfig.c create mode 100644 krb5-1-6/src/lib/krb5/os/port2ip.c create mode 100644 krb5-1-6/src/lib/krb5/os/prompter.c create mode 100644 krb5-1-6/src/lib/krb5/os/promptusr.c create mode 100644 krb5-1-6/src/lib/krb5/os/read_msg.c create mode 100644 krb5-1-6/src/lib/krb5/os/read_pwd.c create mode 100644 krb5-1-6/src/lib/krb5/os/realm_dom.c create mode 100644 krb5-1-6/src/lib/krb5/os/realm_iter.c create mode 100644 krb5-1-6/src/lib/krb5/os/ref_std_conf.out create mode 100644 krb5-1-6/src/lib/krb5/os/send524.c create mode 100644 krb5-1-6/src/lib/krb5/os/sendto_kdc.c create mode 100644 krb5-1-6/src/lib/krb5/os/sn2princ.c create mode 100644 krb5-1-6/src/lib/krb5/os/t_an_to_ln.c create mode 100644 krb5-1-6/src/lib/krb5/os/t_gifconf.c create mode 100644 krb5-1-6/src/lib/krb5/os/t_locate_kdc.c create mode 100644 krb5-1-6/src/lib/krb5/os/t_realm_iter.c create mode 100644 krb5-1-6/src/lib/krb5/os/t_std_conf.c create mode 100644 krb5-1-6/src/lib/krb5/os/td_krb5.conf create mode 100644 krb5-1-6/src/lib/krb5/os/thread_safe.c create mode 100644 krb5-1-6/src/lib/krb5/os/timeofday.c create mode 100644 krb5-1-6/src/lib/krb5/os/toffset.c create mode 100644 krb5-1-6/src/lib/krb5/os/unlck_file.c create mode 100644 krb5-1-6/src/lib/krb5/os/ustime.c create mode 100644 krb5-1-6/src/lib/krb5/os/write_msg.c create mode 100644 krb5-1-6/src/lib/krb5/posix/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/posix/syslog.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/Makefile.in create mode 100644 krb5-1-6/src/lib/krb5/rcache/README create mode 100644 krb5-1-6/src/lib/krb5/rcache/RELEASE create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc-int.h create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_base.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_base.h create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_conv.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_dfl.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_dfl.h create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_io.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_io.h create mode 100644 krb5-1-6/src/lib/krb5/rcache/rc_none.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/rcdef.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/rcfns.c create mode 100644 krb5-1-6/src/lib/krb5/rcache/ser_rc.c create mode 100644 krb5-1-6/src/lib/krb5_32.def create mode 100644 krb5-1-6/src/lib/rpc/Makefile.in create mode 100644 krb5-1-6/src/lib/rpc/auth_gss.c create mode 100644 krb5-1-6/src/lib/rpc/auth_gssapi.c create mode 100644 krb5-1-6/src/lib/rpc/auth_gssapi_misc.c create mode 100644 krb5-1-6/src/lib/rpc/auth_none.c create mode 100644 krb5-1-6/src/lib/rpc/auth_unix.c create mode 100644 krb5-1-6/src/lib/rpc/authgss_prot.c create mode 100644 krb5-1-6/src/lib/rpc/authunix_prot.c create mode 100644 krb5-1-6/src/lib/rpc/bindresvport.c create mode 100644 krb5-1-6/src/lib/rpc/clnt_generic.c create mode 100644 krb5-1-6/src/lib/rpc/clnt_perror.c create mode 100644 krb5-1-6/src/lib/rpc/clnt_raw.c create mode 100644 krb5-1-6/src/lib/rpc/clnt_simple.c create mode 100644 krb5-1-6/src/lib/rpc/clnt_tcp.c create mode 100644 krb5-1-6/src/lib/rpc/clnt_udp.c create mode 100644 krb5-1-6/src/lib/rpc/dyn.c create mode 100644 krb5-1-6/src/lib/rpc/dyn.h create mode 100644 krb5-1-6/src/lib/rpc/dynP.h create mode 100644 krb5-1-6/src/lib/rpc/dyntest.c create mode 100644 krb5-1-6/src/lib/rpc/get_myaddress.c create mode 100644 krb5-1-6/src/lib/rpc/getrpcent.c create mode 100644 krb5-1-6/src/lib/rpc/getrpcport.c create mode 100644 krb5-1-6/src/lib/rpc/libgssrpc.exports create mode 100644 krb5-1-6/src/lib/rpc/pmap_clnt.c create mode 100644 krb5-1-6/src/lib/rpc/pmap_getmaps.c create mode 100644 krb5-1-6/src/lib/rpc/pmap_getport.c create mode 100644 krb5-1-6/src/lib/rpc/pmap_prot.c create mode 100644 krb5-1-6/src/lib/rpc/pmap_prot2.c create mode 100644 krb5-1-6/src/lib/rpc/pmap_rmt.c create mode 100644 krb5-1-6/src/lib/rpc/rpc_callmsg.c create mode 100644 krb5-1-6/src/lib/rpc/rpc_commondata.c create mode 100644 krb5-1-6/src/lib/rpc/rpc_dtablesize.c create mode 100644 krb5-1-6/src/lib/rpc/rpc_prot.c create mode 100644 krb5-1-6/src/lib/rpc/svc.c create mode 100644 krb5-1-6/src/lib/rpc/svc_auth.c create mode 100644 krb5-1-6/src/lib/rpc/svc_auth_gss.c create mode 100644 krb5-1-6/src/lib/rpc/svc_auth_gssapi.c create mode 100644 krb5-1-6/src/lib/rpc/svc_auth_none.c create mode 100644 krb5-1-6/src/lib/rpc/svc_auth_unix.c create mode 100644 krb5-1-6/src/lib/rpc/svc_raw.c create mode 100644 krb5-1-6/src/lib/rpc/svc_run.c create mode 100644 krb5-1-6/src/lib/rpc/svc_simple.c create mode 100644 krb5-1-6/src/lib/rpc/svc_tcp.c create mode 100644 krb5-1-6/src/lib/rpc/svc_udp.c create mode 100644 krb5-1-6/src/lib/rpc/unit-test/Makefile.in create mode 100644 krb5-1-6/src/lib/rpc/unit-test/client.c create mode 100644 krb5-1-6/src/lib/rpc/unit-test/config/unix.exp create mode 100644 krb5-1-6/src/lib/rpc/unit-test/lib/helpers.exp create mode 100644 krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/expire.exp create mode 100644 krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp create mode 100644 krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp create mode 100644 krb5-1-6/src/lib/rpc/unit-test/rpc_test.h create mode 100644 krb5-1-6/src/lib/rpc/unit-test/rpc_test.x create mode 100644 krb5-1-6/src/lib/rpc/unit-test/rpc_test_clnt.c create mode 100755 krb5-1-6/src/lib/rpc/unit-test/rpc_test_setup.sh create mode 100644 krb5-1-6/src/lib/rpc/unit-test/rpc_test_svc.c create mode 100644 krb5-1-6/src/lib/rpc/unit-test/server.c create mode 100644 krb5-1-6/src/lib/rpc/xdr.c create mode 100644 krb5-1-6/src/lib/rpc/xdr_alloc.c create mode 100644 krb5-1-6/src/lib/rpc/xdr_array.c create mode 100644 krb5-1-6/src/lib/rpc/xdr_float.c create mode 100644 krb5-1-6/src/lib/rpc/xdr_mem.c create mode 100644 krb5-1-6/src/lib/rpc/xdr_rec.c create mode 100644 krb5-1-6/src/lib/rpc/xdr_reference.c create mode 100644 krb5-1-6/src/lib/rpc/xdr_stdio.c create mode 100644 krb5-1-6/src/lib/win_glue.c create mode 100644 krb5-1-6/src/lib/xpprof32.def create mode 100644 krb5-1-6/src/patchlevel.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/adb_openclose.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/adb_policy.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/configure.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/db2.exports create mode 100644 krb5-1-6/src/plugins/kdb/db2/db2_exp.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/kdb_compat.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/kdb_db2.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/kdb_db2.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/kdb_xdr.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/kdb_xdr.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/CHANGELOG.db2 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.inc create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/README create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/README.db2 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.inc create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_close.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_conv.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_debug.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_delete.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_get.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_open.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_overflow.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_page.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_put.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_search.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_seq.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_split.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_utils.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/btree.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/btree/extern.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/clib/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/clib/memmove.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/clib/mkstemp.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/clib/strerror.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/configure.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.inc create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/db/db.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/docs/btree.3.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/docs/dbopen.3.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.3.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.usenix.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/docs/libtp.usenix.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/docs/recno.3.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.inc create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/dbm.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/extern.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c.patch create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_debug.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_func.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_log2.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_page.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hsearch.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h.patch create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/hash/search.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-config.h.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-dbm.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-int.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-ndbm.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-queue.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/include/db.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/libdb.exports create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/Makefile.inc create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db.man.ps create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_btree.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_hash.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_lock.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_log.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_mpool.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_open.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_recno.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_txn.3 create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/man/spell.ok create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/README create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.inc create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/extern.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_close.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_delete.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_get.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_open.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_put.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_search.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_seq.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_utils.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/recno/recno.h create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/README create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/dbtest.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/dictionary create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/README create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/libdb2/test/run.test create mode 100644 krb5-1-6/src/plugins/kdb/db2/pol_xdr.c create mode 100644 krb5-1-6/src/plugins/kdb/db2/policy_db.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/ldap/kldap.exports create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_exp.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/ChangeLog create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ChangeLog create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/configure.in create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c create mode 100644 krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h create mode 100644 krb5-1-6/src/plugins/locate/python/Makefile.in create mode 100644 krb5-1-6/src/plugins/locate/python/configure.in create mode 100644 krb5-1-6/src/plugins/locate/python/locate-service.py create mode 100644 krb5-1-6/src/plugins/locate/python/py-locate.c create mode 100644 krb5-1-6/src/plugins/locate/python/python.exports create mode 100644 krb5-1-6/src/plugins/preauth/cksum_body/Makefile.in create mode 100644 krb5-1-6/src/plugins/preauth/cksum_body/cksum_body.exports create mode 100644 krb5-1-6/src/plugins/preauth/cksum_body/cksum_body_main.c create mode 100644 krb5-1-6/src/plugins/preauth/cksum_body/configure.in create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/Makefile.in create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/configure.in create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkcs11.h create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit.exports create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit.h create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.c create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.h create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_clnt.c create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto.h create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_identity.c create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_lib.c create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_matching.c create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_profile.c create mode 100644 krb5-1-6/src/plugins/preauth/pkinit/pkinit_srv.c create mode 100644 krb5-1-6/src/plugins/preauth/wpse/Makefile.in create mode 100644 krb5-1-6/src/plugins/preauth/wpse/configure.in create mode 100644 krb5-1-6/src/plugins/preauth/wpse/wpse.exports create mode 100644 krb5-1-6/src/plugins/preauth/wpse/wpse_main.c create mode 100644 krb5-1-6/src/prototype/getopt.c create mode 100644 krb5-1-6/src/prototype/prototype.c create mode 100644 krb5-1-6/src/prototype/prototype.h create mode 100644 krb5-1-6/src/slave/Makefile.in create mode 100644 krb5-1-6/src/slave/kprop.M create mode 100644 krb5-1-6/src/slave/kprop.c create mode 100644 krb5-1-6/src/slave/kprop.h create mode 100644 krb5-1-6/src/slave/kpropd.M create mode 100644 krb5-1-6/src/slave/kpropd.c create mode 100644 krb5-1-6/src/slave/kslave_update create mode 100644 krb5-1-6/src/t_krbconf create mode 100644 krb5-1-6/src/tests/Makefile.in create mode 100644 krb5-1-6/src/tests/asn.1/Makefile.in create mode 100644 krb5-1-6/src/tests/asn.1/README create mode 100644 krb5-1-6/src/tests/asn.1/debug.h create mode 100644 krb5-1-6/src/tests/asn.1/krb5_decode_test.c create mode 100644 krb5-1-6/src/tests/asn.1/krb5_encode_test.c create mode 100644 krb5-1-6/src/tests/asn.1/ktest.c create mode 100644 krb5-1-6/src/tests/asn.1/ktest.h create mode 100644 krb5-1-6/src/tests/asn.1/ktest_equal.c create mode 100644 krb5-1-6/src/tests/asn.1/ktest_equal.h create mode 100644 krb5-1-6/src/tests/asn.1/reference_encode.out create mode 100644 krb5-1-6/src/tests/asn.1/trval.c create mode 100644 krb5-1-6/src/tests/asn.1/trval_reference.out create mode 100644 krb5-1-6/src/tests/asn.1/utility.c create mode 100644 krb5-1-6/src/tests/asn.1/utility.h create mode 100644 krb5-1-6/src/tests/configure.in create mode 100644 krb5-1-6/src/tests/create/Makefile.in create mode 100644 krb5-1-6/src/tests/create/kdb5_mkdums.M create mode 100644 krb5-1-6/src/tests/create/kdb5_mkdums.c create mode 100644 krb5-1-6/src/tests/dejagnu/Makefile.in create mode 100644 krb5-1-6/src/tests/dejagnu/config/default.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-root/rlogin.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-root/telnet.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/gssapi.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/gssftp.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/kadmin.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/pwhist.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/rcp.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/rsh.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/sample.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/standalone.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/v4gssftp.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/v4krb524d.exp create mode 100644 krb5-1-6/src/tests/dejagnu/krb-standalone/v4standalone.exp create mode 100644 krb5-1-6/src/tests/dejagnu/t_inetd.c create mode 100644 krb5-1-6/src/tests/dump.c create mode 100644 krb5-1-6/src/tests/gss-threads/Makefile.in create mode 100644 krb5-1-6/src/tests/gss-threads/README create mode 100644 krb5-1-6/src/tests/gss-threads/gss-client.c create mode 100644 krb5-1-6/src/tests/gss-threads/gss-misc.c create mode 100644 krb5-1-6/src/tests/gss-threads/gss-misc.h create mode 100644 krb5-1-6/src/tests/gss-threads/gss-server.c create mode 100644 krb5-1-6/src/tests/gssapi/Makefile.in create mode 100644 krb5-1-6/src/tests/gssapi/t_imp_name.c create mode 100644 krb5-1-6/src/tests/hammer/Makefile.in create mode 100644 krb5-1-6/src/tests/hammer/kdc5_hammer.c create mode 100644 krb5-1-6/src/tests/hammer/pp.c create mode 100644 krb5-1-6/src/tests/misc/Makefile.in create mode 100644 krb5-1-6/src/tests/misc/test_getpw.c create mode 100644 krb5-1-6/src/tests/misc/test_getsockname.c create mode 100644 krb5-1-6/src/tests/misc/test_nfold.c create mode 100644 krb5-1-6/src/tests/resolve/Makefile.in create mode 100644 krb5-1-6/src/tests/resolve/addrinfo-test.c create mode 100644 krb5-1-6/src/tests/resolve/fake-addrinfo-test.c create mode 100644 krb5-1-6/src/tests/resolve/resolve.c create mode 100644 krb5-1-6/src/tests/shlib/Makefile.in create mode 100644 krb5-1-6/src/tests/shlib/t_loader.c create mode 100644 krb5-1-6/src/tests/test1.c create mode 100644 krb5-1-6/src/tests/threads/Makefile.in create mode 100644 krb5-1-6/src/tests/threads/prof1.c create mode 100644 krb5-1-6/src/tests/threads/t_rcache.c create mode 100644 krb5-1-6/src/tests/verify/Makefile.in create mode 100644 krb5-1-6/src/tests/verify/kdb5_verify.c create mode 100644 krb5-1-6/src/tests/verify/pkey.c create mode 100644 krb5-1-6/src/util/Makefile.in create mode 100644 krb5-1-6/src/util/ac_check_krb5.m4 create mode 100755 krb5-1-6/src/util/check-ac-syms create mode 100644 krb5-1-6/src/util/def-check.pl create mode 100644 krb5-1-6/src/util/depfix.pl create mode 100644 krb5-1-6/src/util/et/ISSUES create mode 100644 krb5-1-6/src/util/et/Makefile.in create mode 100644 krb5-1-6/src/util/et/com_err.3 create mode 100644 krb5-1-6/src/util/et/com_err.c create mode 100644 krb5-1-6/src/util/et/com_err.h create mode 100644 krb5-1-6/src/util/et/com_err.texinfo create mode 100644 krb5-1-6/src/util/et/compile_et.1 create mode 100644 krb5-1-6/src/util/et/compile_et.c create mode 100755 krb5-1-6/src/util/et/compile_et.sh create mode 100644 krb5-1-6/src/util/et/compiler.h create mode 100755 krb5-1-6/src/util/et/config_script create mode 100644 krb5-1-6/src/util/et/error_message.c create mode 100644 krb5-1-6/src/util/et/error_table.h create mode 100644 krb5-1-6/src/util/et/error_table.y create mode 100644 krb5-1-6/src/util/et/et.exp create mode 100644 krb5-1-6/src/util/et/et.pbexp create mode 100644 krb5-1-6/src/util/et/et1.et create mode 100644 krb5-1-6/src/util/et/et2.et create mode 100644 krb5-1-6/src/util/et/et_c.awk create mode 100644 krb5-1-6/src/util/et/et_c.pl create mode 100644 krb5-1-6/src/util/et/et_h.awk create mode 100644 krb5-1-6/src/util/et/et_h.pl create mode 100644 krb5-1-6/src/util/et/et_lex.lex.l create mode 100644 krb5-1-6/src/util/et/et_name.c create mode 100644 krb5-1-6/src/util/et/init_et.c create mode 100644 krb5-1-6/src/util/et/internal.h create mode 100644 krb5-1-6/src/util/et/libcom_err.exports create mode 100644 krb5-1-6/src/util/et/mit-sipb-copyright.h create mode 100644 krb5-1-6/src/util/et/t_com_err.c create mode 100644 krb5-1-6/src/util/et/test1.et create mode 100644 krb5-1-6/src/util/et/test2.et create mode 100644 krb5-1-6/src/util/et/test_et.c create mode 100644 krb5-1-6/src/util/et/texinfo.tex create mode 100644 krb5-1-6/src/util/et/vfprintf.c create mode 100644 krb5-1-6/src/util/exitsleep.c create mode 100755 krb5-1-6/src/util/export-check.pl create mode 100755 krb5-1-6/src/util/getsyms create mode 100644 krb5-1-6/src/util/getsyms.sed create mode 100755 krb5-1-6/src/util/kbuild create mode 100644 krb5-1-6/src/util/kfrags/athena.conf create mode 100644 krb5-1-6/src/util/kfrags/base.conf create mode 100644 krb5-1-6/src/util/kfrags/cns.conf create mode 100644 krb5-1-6/src/util/kfrags/gcc.conf create mode 100644 krb5-1-6/src/util/kfrags/ranlib.conf create mode 100644 krb5-1-6/src/util/kfrags/shared.conf create mode 100644 krb5-1-6/src/util/kfrags/sunpro.conf create mode 100644 krb5-1-6/src/util/kfrags/svr4.conf create mode 100644 krb5-1-6/src/util/kfrags/ucb.conf create mode 100755 krb5-1-6/src/util/lndir create mode 100644 krb5-1-6/src/util/makedepend/cpp.ed create mode 100644 krb5-1-6/src/util/makedepend/cppsetup.c create mode 100644 krb5-1-6/src/util/makedepend/def.h create mode 100644 krb5-1-6/src/util/makedepend/ifparser.c create mode 100644 krb5-1-6/src/util/makedepend/ifparser.h create mode 100644 krb5-1-6/src/util/makedepend/include.c create mode 100644 krb5-1-6/src/util/makedepend/main.c create mode 100644 krb5-1-6/src/util/makedepend/mkdepend.man create mode 100644 krb5-1-6/src/util/makedepend/parse.c create mode 100644 krb5-1-6/src/util/makedepend/pr.c create mode 100755 krb5-1-6/src/util/mkrel create mode 100644 krb5-1-6/src/util/profile/Makefile.in create mode 100644 krb5-1-6/src/util/profile/argv_parse.c create mode 100644 krb5-1-6/src/util/profile/argv_parse.h create mode 100644 krb5-1-6/src/util/profile/dosshell.ini create mode 100644 krb5-1-6/src/util/profile/krb5.conf create mode 100644 krb5-1-6/src/util/profile/libprofile.exports create mode 100644 krb5-1-6/src/util/profile/prof_FSp_glue.c create mode 100644 krb5-1-6/src/util/profile/prof_err.et create mode 100644 krb5-1-6/src/util/profile/prof_file.c create mode 100644 krb5-1-6/src/util/profile/prof_get.c create mode 100644 krb5-1-6/src/util/profile/prof_init.c create mode 100644 krb5-1-6/src/util/profile/prof_int.h create mode 100644 krb5-1-6/src/util/profile/prof_parse.c create mode 100644 krb5-1-6/src/util/profile/prof_set.c create mode 100644 krb5-1-6/src/util/profile/prof_test1 create mode 100644 krb5-1-6/src/util/profile/prof_tree.c create mode 100644 krb5-1-6/src/util/profile/profile.5 create mode 100644 krb5-1-6/src/util/profile/profile.exp create mode 100644 krb5-1-6/src/util/profile/profile.hin create mode 100644 krb5-1-6/src/util/profile/profile.pbexp create mode 100644 krb5-1-6/src/util/profile/profile.swg create mode 100644 krb5-1-6/src/util/profile/profile_tcl.c create mode 100644 krb5-1-6/src/util/profile/prtest.in create mode 100644 krb5-1-6/src/util/profile/prtest.script create mode 100644 krb5-1-6/src/util/profile/test.ini create mode 100644 krb5-1-6/src/util/profile/test_parse.c create mode 100644 krb5-1-6/src/util/profile/test_profile.c create mode 100755 krb5-1-6/src/util/reconf create mode 100644 krb5-1-6/src/util/send-pr/COPYING create mode 100644 krb5-1-6/src/util/send-pr/INSTALL create mode 100644 krb5-1-6/src/util/send-pr/MANIFEST create mode 100644 krb5-1-6/src/util/send-pr/Makefile.in create mode 100644 krb5-1-6/src/util/send-pr/README create mode 100644 krb5-1-6/src/util/send-pr/categories create mode 100644 krb5-1-6/src/util/send-pr/install-sid.sh create mode 100644 krb5-1-6/src/util/send-pr/send-pr.1 create mode 100644 krb5-1-6/src/util/send-pr/send-pr.sh create mode 100644 krb5-1-6/src/util/ss/Makefile.in create mode 100644 krb5-1-6/src/util/ss/cmd_tbl.lex.l create mode 100755 krb5-1-6/src/util/ss/config_script create mode 100644 krb5-1-6/src/util/ss/configure.in create mode 100644 krb5-1-6/src/util/ss/copyright.h create mode 100644 krb5-1-6/src/util/ss/ct.y create mode 100644 krb5-1-6/src/util/ss/ct_c_awk.in create mode 100644 krb5-1-6/src/util/ss/ct_c_sed.in create mode 100644 krb5-1-6/src/util/ss/data.c create mode 100644 krb5-1-6/src/util/ss/error.c create mode 100644 krb5-1-6/src/util/ss/execute_cmd.c create mode 100644 krb5-1-6/src/util/ss/help.c create mode 100644 krb5-1-6/src/util/ss/invocation.c create mode 100644 krb5-1-6/src/util/ss/list_rqs.c create mode 100644 krb5-1-6/src/util/ss/listen.c create mode 100644 krb5-1-6/src/util/ss/mit-sipb-copyright.h create mode 100644 krb5-1-6/src/util/ss/mk_cmds.c create mode 100755 krb5-1-6/src/util/ss/mk_cmds.sh create mode 100644 krb5-1-6/src/util/ss/options.c create mode 100644 krb5-1-6/src/util/ss/pager.c create mode 100644 krb5-1-6/src/util/ss/parse.c create mode 100644 krb5-1-6/src/util/ss/prompt.c create mode 100644 krb5-1-6/src/util/ss/request_tbl.c create mode 100644 krb5-1-6/src/util/ss/requests.c create mode 100644 krb5-1-6/src/util/ss/ss.h create mode 100644 krb5-1-6/src/util/ss/ss_err.et create mode 100644 krb5-1-6/src/util/ss/ss_internal.h create mode 100644 krb5-1-6/src/util/ss/std_rqs.ct create mode 100644 krb5-1-6/src/util/ss/test_ss.c create mode 100644 krb5-1-6/src/util/ss/utils.c create mode 100644 krb5-1-6/src/util/support/Makefile.in create mode 100644 krb5-1-6/src/util/support/cache-addrinfo.h create mode 100644 krb5-1-6/src/util/support/errors.c create mode 100644 krb5-1-6/src/util/support/fake-addrinfo.c create mode 100644 krb5-1-6/src/util/support/gmt_mktime.c create mode 100644 krb5-1-6/src/util/support/init-addrinfo.c create mode 100644 krb5-1-6/src/util/support/libkrb5support.exports create mode 100644 krb5-1-6/src/util/support/plugins.c create mode 100644 krb5-1-6/src/util/support/supp-int.h create mode 100644 krb5-1-6/src/util/support/threads.c create mode 100644 krb5-1-6/src/util/valgrind-suppressions create mode 100644 krb5-1-6/src/util/windows/Makefile.in create mode 100644 krb5-1-6/src/util/windows/getopt.c create mode 100644 krb5-1-6/src/util/windows/getopt.h create mode 100644 krb5-1-6/src/util/windows/getopt_long.c create mode 100644 krb5-1-6/src/util/windows/libecho.c create mode 100644 krb5-1-6/src/wconfig.c create mode 100644 krb5-1-6/src/windows/Makefile.in create mode 100644 krb5-1-6/src/windows/README create mode 100644 krb5-1-6/src/windows/build/BKWconfig.xml create mode 100644 krb5-1-6/src/windows/build/Logger.pm create mode 100644 krb5-1-6/src/windows/build/bkw-automation.html create mode 100644 krb5-1-6/src/windows/build/bkw.pl create mode 100644 krb5-1-6/src/windows/build/bootstrap.xml create mode 100644 krb5-1-6/src/windows/build/commandandcontrol.pl create mode 100644 krb5-1-6/src/windows/build/copyfiles.pl create mode 100644 krb5-1-6/src/windows/build/copyfiles.xml create mode 100644 krb5-1-6/src/windows/build/corebinaryfiles.xml create mode 100644 krb5-1-6/src/windows/build/css/main-action(1).css create mode 100644 krb5-1-6/src/windows/build/css/main-action.css create mode 100644 krb5-1-6/src/windows/build/makeZip.pl create mode 100644 krb5-1-6/src/windows/build/pruneFiles.pl create mode 100644 krb5-1-6/src/windows/build/repository1.pl create mode 100644 krb5-1-6/src/windows/build/sdkfiles.xml create mode 100644 krb5-1-6/src/windows/build/signFiles.pl create mode 100644 krb5-1-6/src/windows/build/site-local.sed create mode 100644 krb5-1-6/src/windows/build/tee.pl create mode 100644 krb5-1-6/src/windows/build/which.pl create mode 100644 krb5-1-6/src/windows/build/zipXML.pl create mode 100644 krb5-1-6/src/windows/cns/Makefile.in create mode 100644 krb5-1-6/src/windows/cns/clock00.ico create mode 100644 krb5-1-6/src/windows/cns/clock05.ico create mode 100644 krb5-1-6/src/windows/cns/clock10.ico create mode 100644 krb5-1-6/src/windows/cns/clock15.ico create mode 100644 krb5-1-6/src/windows/cns/clock20.ico create mode 100644 krb5-1-6/src/windows/cns/clock25.ico create mode 100644 krb5-1-6/src/windows/cns/clock30.ico create mode 100644 krb5-1-6/src/windows/cns/clock35.ico create mode 100644 krb5-1-6/src/windows/cns/clock40.ico create mode 100644 krb5-1-6/src/windows/cns/clock45.ico create mode 100644 krb5-1-6/src/windows/cns/clock50.ico create mode 100644 krb5-1-6/src/windows/cns/clock55.ico create mode 100644 krb5-1-6/src/windows/cns/clock60.ico create mode 100644 krb5-1-6/src/windows/cns/clockexp.ico create mode 100644 krb5-1-6/src/windows/cns/clocktkt.ico create mode 100644 krb5-1-6/src/windows/cns/cns-help.doc create mode 100644 krb5-1-6/src/windows/cns/cns-help.hlp create mode 100644 krb5-1-6/src/windows/cns/cns-help.hpj create mode 100644 krb5-1-6/src/windows/cns/cns.c create mode 100644 krb5-1-6/src/windows/cns/cns.h create mode 100644 krb5-1-6/src/windows/cns/cns.ico create mode 100644 krb5-1-6/src/windows/cns/cns_reg.c create mode 100644 krb5-1-6/src/windows/cns/cns_reg.h create mode 100644 krb5-1-6/src/windows/cns/cnsres4.rc create mode 100644 krb5-1-6/src/windows/cns/cnsres5.rc create mode 100644 krb5-1-6/src/windows/cns/debug.c create mode 100644 krb5-1-6/src/windows/cns/heap.c create mode 100644 krb5-1-6/src/windows/cns/kerbnet.doc create mode 100644 krb5-1-6/src/windows/cns/kerbnet.hlp create mode 100644 krb5-1-6/src/windows/cns/kerbnet.hpj create mode 100644 krb5-1-6/src/windows/cns/kpasswd.c create mode 100644 krb5-1-6/src/windows/cns/krb5.def create mode 100644 krb5-1-6/src/windows/cns/krbini.h create mode 100644 krb5-1-6/src/windows/cns/options.c create mode 100644 krb5-1-6/src/windows/cns/password.c create mode 100644 krb5-1-6/src/windows/cns/tktlist.c create mode 100644 krb5-1-6/src/windows/cns/tktlist.h create mode 100644 krb5-1-6/src/windows/gina/Makefile.in create mode 100644 krb5-1-6/src/windows/gina/gina.def create mode 100644 krb5-1-6/src/windows/gina/ginastub.c create mode 100644 krb5-1-6/src/windows/gina/ginastub.h create mode 100644 krb5-1-6/src/windows/gss/Makefile.in create mode 100644 krb5-1-6/src/windows/gss/gss-client.c create mode 100644 krb5-1-6/src/windows/gss/gss-misc.c create mode 100644 krb5-1-6/src/windows/gss/gss-misc.h create mode 100644 krb5-1-6/src/windows/gss/gss.c create mode 100644 krb5-1-6/src/windows/gss/gss.def create mode 100644 krb5-1-6/src/windows/gss/gss.h create mode 100644 krb5-1-6/src/windows/gss/gss.ico create mode 100644 krb5-1-6/src/windows/gss/gss.rc create mode 100644 krb5-1-6/src/windows/gss/resource.h create mode 100644 krb5-1-6/src/windows/gss/ver_serv.txt create mode 100644 krb5-1-6/src/windows/identity/Makefile create mode 100644 krb5-1-6/src/windows/identity/apiversion.txt create mode 100644 krb5-1-6/src/windows/identity/config/Makefile create mode 100644 krb5-1-6/src/windows/identity/config/Makefile.w2k create mode 100644 krb5-1-6/src/windows/identity/config/Makefile.w32 create mode 100644 krb5-1-6/src/windows/identity/config/ccsv.pl create mode 100644 krb5-1-6/src/windows/identity/config/csvschema.cfg create mode 100644 krb5-1-6/src/windows/identity/config/netidmgr_intver.h.in create mode 100644 krb5-1-6/src/windows/identity/config/netidmgr_version.h.in create mode 100644 krb5-1-6/src/windows/identity/doc/Makefile create mode 100644 krb5-1-6/src/windows/identity/doc/cred_aquisition.h create mode 100644 krb5-1-6/src/windows/identity/doc/cred_data_types.h create mode 100644 krb5-1-6/src/windows/identity/doc/cred_main.h create mode 100644 krb5-1-6/src/windows/identity/doc/cred_msgs.h create mode 100644 krb5-1-6/src/windows/identity/doc/cred_prop_pages.h create mode 100644 krb5-1-6/src/windows/identity/doc/doxyfile.cfg create mode 100644 krb5-1-6/src/windows/identity/doc/footer.html create mode 100644 krb5-1-6/src/windows/identity/doc/header.html create mode 100644 krb5-1-6/src/windows/identity/doc/images/credview-select-outline.jpg create mode 100644 krb5-1-6/src/windows/identity/doc/images/khimaira_logo.png create mode 100644 krb5-1-6/src/windows/identity/doc/images/khimaira_logo_small.png create mode 100644 krb5-1-6/src/windows/identity/doc/images/modules_plugins_krb5.png create mode 100644 krb5-1-6/src/windows/identity/doc/main_page.h create mode 100755 krb5-1-6/src/windows/identity/doc/netidmgr.doc create mode 100755 krb5-1-6/src/windows/identity/doc/netidmgr.pdf create mode 100644 krb5-1-6/src/windows/identity/doc/plugin_framework.h create mode 100644 krb5-1-6/src/windows/identity/doc/plugin_locale.h create mode 100644 krb5-1-6/src/windows/identity/doc/plugin_main.h create mode 100644 krb5-1-6/src/windows/identity/doc/plugin_structure.h create mode 100644 krb5-1-6/src/windows/identity/doc/stylesheet.css create mode 100644 krb5-1-6/src/windows/identity/doc/ui_actions.h create mode 100644 krb5-1-6/src/windows/identity/doc/ui_context.h create mode 100644 krb5-1-6/src/windows/identity/doc/ui_main.h create mode 100644 krb5-1-6/src/windows/identity/doc/ui_menus.h create mode 100644 krb5-1-6/src/windows/identity/help/Index.hhk create mode 100644 krb5-1-6/src/windows/identity/help/Makefile create mode 100644 krb5-1-6/src/windows/identity/help/html/about_netidmgr.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/act_chpw.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/act_destroy_creds.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/act_import_creds.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/act_new_creds.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/act_renew_creds.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/act_set_default.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/bugs.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/cmdline_netidmgr.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/concept_cred_pro.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/concept_credential.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/concept_ident_pro.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/concept_identity.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/concepts.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/copyright.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/howdoi.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/images/appicon_empty.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/appicon_expired.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/appicon_good.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/appicon_warnexp.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/appicon_warning.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/flag-critical.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/flag-warning.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/flag_expired.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/flag_renewable.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/id-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/logo.jpg create mode 100644 krb5-1-6/src/windows/identity/help/html/images/logo_shade.jpg create mode 100644 krb5-1-6/src/windows/identity/help/html/images/notification_icon_menu.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_app_icon.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_chng_pwd.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_appearance.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_cred_provider.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_general.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_global_krb4.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_global_krb5.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_ident.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_krb4.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_krb5.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_provider.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_idents.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_notifications.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb4.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_ins.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_main_wnd.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_main_wnd_basic.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_menu_bar.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_menu_credential.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_menu_file.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_menu_help.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_menu_options.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_menu_view.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_menu_view_cols.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_new_creds.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_new_creds_err01.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_new_creds_exp.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_tb_standard.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/screen_tray_icon.png create mode 100644 krb5-1-6/src/windows/identity/help/html/images/wdg_collapsed_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/wdg_expanded_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/wdg_stick_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/images/wdg_stuck_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/help/html/menu_all.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/menu_credential.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/menu_file.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/menu_help.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/menu_options.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/menu_view.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/nidmgr.css create mode 100644 krb5-1-6/src/windows/identity/help/html/tb_standard.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/template.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/use_config.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/use_icon.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/use_layout.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/use_start.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/using.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/welcome.htm create mode 100644 krb5-1-6/src/windows/identity/help/html/wnd_main.htm create mode 100644 krb5-1-6/src/windows/identity/help/khhelp.h create mode 100644 krb5-1-6/src/windows/identity/help/netidmgr.hhp create mode 100644 krb5-1-6/src/windows/identity/help/popups.txt create mode 100644 krb5-1-6/src/windows/identity/help/popups_newcreds.txt create mode 100644 krb5-1-6/src/windows/identity/help/popups_password.txt create mode 100644 krb5-1-6/src/windows/identity/help/toc.hhc create mode 100644 krb5-1-6/src/windows/identity/include/Makefile create mode 100644 krb5-1-6/src/windows/identity/include/khdefs.h create mode 100644 krb5-1-6/src/windows/identity/include/kherror.h create mode 100644 krb5-1-6/src/windows/identity/include/khlist.h create mode 100644 krb5-1-6/src/windows/identity/include/khmsgtypes.h create mode 100644 krb5-1-6/src/windows/identity/include/netidmgr.h create mode 100644 krb5-1-6/src/windows/identity/kconfig/Makefile create mode 100644 krb5-1-6/src/windows/identity/kconfig/api.c create mode 100644 krb5-1-6/src/windows/identity/kconfig/kconfig.h create mode 100644 krb5-1-6/src/windows/identity/kconfig/kconfiginternal.h create mode 100644 krb5-1-6/src/windows/identity/kconfig/kconfigmain.c create mode 100644 krb5-1-6/src/windows/identity/kconfig/registry.c create mode 100644 krb5-1-6/src/windows/identity/kconfig/test/utiltest.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/Makefile create mode 100644 krb5-1-6/src/windows/identity/kcreddb/attrib.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/attrib.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/buf.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/buf.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/credential.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/credential.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/credset.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/credset.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/credtype.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/credtype.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/identity.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/identity.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/init.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/kcdbconfig.csv create mode 100644 krb5-1-6/src/windows/identity/kcreddb/kcreddb.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/kcreddbinternal.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/kcreddbmain.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/lang/en_us/kcredres.rc create mode 100644 krb5-1-6/src/windows/identity/kcreddb/langres.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/resource.h create mode 100644 krb5-1-6/src/windows/identity/kcreddb/type.c create mode 100644 krb5-1-6/src/windows/identity/kcreddb/type.h create mode 100644 krb5-1-6/src/windows/identity/kherr/Makefile create mode 100644 krb5-1-6/src/windows/identity/kherr/kherr.c create mode 100644 krb5-1-6/src/windows/identity/kherr/kherr.h create mode 100644 krb5-1-6/src/windows/identity/kherr/kherrinternal.h create mode 100644 krb5-1-6/src/windows/identity/kherr/kherrmain.c create mode 100644 krb5-1-6/src/windows/identity/kmm/Makefile create mode 100644 krb5-1-6/src/windows/identity/kmm/kmm.c create mode 100644 krb5-1-6/src/windows/identity/kmm/kmm.h create mode 100644 krb5-1-6/src/windows/identity/kmm/kmm_module.c create mode 100644 krb5-1-6/src/windows/identity/kmm/kmm_plugin.c create mode 100644 krb5-1-6/src/windows/identity/kmm/kmm_reg.c create mode 100644 krb5-1-6/src/windows/identity/kmm/kmm_registrar.c create mode 100644 krb5-1-6/src/windows/identity/kmm/kmmconfig.csv create mode 100644 krb5-1-6/src/windows/identity/kmm/kmminternal.h create mode 100644 krb5-1-6/src/windows/identity/kmm/kmmmain.c create mode 100644 krb5-1-6/src/windows/identity/kmm/kplugin.h create mode 100644 krb5-1-6/src/windows/identity/kmm/lang/kmm_msgs.mc create mode 100644 krb5-1-6/src/windows/identity/kmq/Makefile create mode 100644 krb5-1-6/src/windows/identity/kmq/consumer.c create mode 100644 krb5-1-6/src/windows/identity/kmq/init.c create mode 100644 krb5-1-6/src/windows/identity/kmq/kmq.h create mode 100644 krb5-1-6/src/windows/identity/kmq/kmqconfig.csv create mode 100644 krb5-1-6/src/windows/identity/kmq/kmqinternal.h create mode 100644 krb5-1-6/src/windows/identity/kmq/kmqmain.c create mode 100644 krb5-1-6/src/windows/identity/kmq/msgtype.c create mode 100644 krb5-1-6/src/windows/identity/kmq/publisher.c create mode 100644 krb5-1-6/src/windows/identity/nidmgrdll/Makefile create mode 100644 krb5-1-6/src/windows/identity/nidmgrdll/Makefile.w2k create mode 100644 krb5-1-6/src/windows/identity/nidmgrdll/dllmain.c create mode 100644 krb5-1-6/src/windows/identity/nidmgrdll/nidmgrdll.rc create mode 100644 krb5-1-6/src/windows/identity/plugins/common/Makefile create mode 100644 krb5-1-6/src/windows/identity/plugins/common/dynimport.c create mode 100644 krb5-1-6/src/windows/identity/plugins/common/dynimport.h create mode 100644 krb5-1-6/src/windows/identity/plugins/common/krb5common.c create mode 100644 krb5-1-6/src/windows/identity/plugins/common/krb5common.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/Makefile create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/images/plugin.ico create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krb4configdlg.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krb4main.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krb4newcreds.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krb4plugin.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krbconfig.csv create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/krbcred.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/lang/en_us/langres.rc create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/langres.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb4/version.rc create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/Makefile create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/datarep.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/datarep.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/images/deleted.ico create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/images/krb5plugin.ico create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/images/modified.ico create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/images/new.ico create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/images/normal.ico create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5configcc.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5configdlg.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5configid.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5configids.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5identpro.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5main.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5newcreds.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5plugin.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krb5props.c create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krbconfig.csv create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/krbcred.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/lang/en_us/langres.rc create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/langres.h create mode 100644 krb5-1-6/src/windows/identity/plugins/krb5/version.rc create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/Makefile create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/README create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/config_id.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/config_ids.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/config_main.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/credacq.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/credprov.h create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/credtype.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/images/plugin.ico create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/lang/en_us/langres.rc create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/langres.h create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/main.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/plugin.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/proppage.c create mode 100644 krb5-1-6/src/windows/identity/sample/templates/credprov/version.rc create mode 100644 krb5-1-6/src/windows/identity/ui/Makefile create mode 100644 krb5-1-6/src/windows/identity/ui/Makefile.w2k create mode 100644 krb5-1-6/src/windows/identity/ui/aboutwnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/aboutwnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/addrchange.c create mode 100644 krb5-1-6/src/windows/identity/ui/addrchange.h create mode 100644 krb5-1-6/src/windows/identity/ui/appglobal.h create mode 100644 krb5-1-6/src/windows/identity/ui/appver.rc create mode 100644 krb5-1-6/src/windows/identity/ui/cfg_appear_wnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/cfg_general_wnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/cfg_identities_wnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/cfg_notif_wnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/cfg_plugins_wnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/configwnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/configwnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/credfuncs.c create mode 100644 krb5-1-6/src/windows/identity/ui/credfuncs.h create mode 100644 krb5-1-6/src/windows/identity/ui/credwnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/credwnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/debugfuncs.c create mode 100644 krb5-1-6/src/windows/identity/ui/debugfuncs.h create mode 100644 krb5-1-6/src/windows/identity/ui/htwnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/htwnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/images/app_notify_error.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/app_notify_info.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/app_notify_none.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/app_notify_warn.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/app_state_exp.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/app_state_ok.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/app_state_warn.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/cfg_applied.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/cfg_default.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/cfg_deleted.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/cfg_mod.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/cfg_plugin.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/cfg_plugin_dis.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/cfg_plugin_err.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/chpw-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/chpw-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/chpw-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/chpw.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/disabled.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/enabled.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/flag-critical.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/flag-warning.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/flag_expired.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/flag_renewable.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/help-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/help.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-delete-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-delete-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-delete-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-delete.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-new-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-new-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-new-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-new.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-refresh-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-refresh-sm-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-refresh-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-refresh.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/id.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/ident.png create mode 100644 krb5-1-6/src/windows/identity/ui/images/import-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/import-sm-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/import-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/import.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/khimaira-cfg.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/logo_shade.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/main_app.ico create mode 100644 krb5-1-6/src/windows/identity/ui/images/tb-blank-small.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tb-blank.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tb-space.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-delete-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-delete-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-delete-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-delete.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-new-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-new-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-new-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-new.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-refresh-dis-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-refresh-dis.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-refresh-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-refresh.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/tk.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/vw-refresh-sm.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/vw-refresh.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_collapsed.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_collapsed_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_credtype.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_expanded.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_expanded_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_flag.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_stick.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_stick_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_stuck.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/images/wdg_stuck_hi.bmp create mode 100644 krb5-1-6/src/windows/identity/ui/khmapp.h create mode 100644 krb5-1-6/src/windows/identity/ui/lang/en_us/cmdline.rtf create mode 100644 krb5-1-6/src/windows/identity/ui/lang/en_us/khapp.rc create mode 100644 krb5-1-6/src/windows/identity/ui/main.c create mode 100644 krb5-1-6/src/windows/identity/ui/mainmenu.c create mode 100644 krb5-1-6/src/windows/identity/ui/mainmenu.h create mode 100644 krb5-1-6/src/windows/identity/ui/mainwnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/mainwnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/makeacceldef.pl create mode 100644 krb5-1-6/src/windows/identity/ui/makeactiondef.pl create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.exe.manifest.i386 create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7 create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8 create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7 create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7.debug create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8 create mode 100644 krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8.debug create mode 100644 krb5-1-6/src/windows/identity/ui/newcredwnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/newcredwnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/notifier.c create mode 100644 krb5-1-6/src/windows/identity/ui/notifier.h create mode 100644 krb5-1-6/src/windows/identity/ui/passwnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/passwnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/propertywnd.c create mode 100644 krb5-1-6/src/windows/identity/ui/propertywnd.h create mode 100644 krb5-1-6/src/windows/identity/ui/reqdaemon.c create mode 100644 krb5-1-6/src/windows/identity/ui/reqdaemon.h create mode 100644 krb5-1-6/src/windows/identity/ui/resource.h create mode 100644 krb5-1-6/src/windows/identity/ui/statusbar.c create mode 100644 krb5-1-6/src/windows/identity/ui/statusbar.h create mode 100644 krb5-1-6/src/windows/identity/ui/taskbar.c create mode 100644 krb5-1-6/src/windows/identity/ui/taskbar.h create mode 100644 krb5-1-6/src/windows/identity/ui/timer.c create mode 100644 krb5-1-6/src/windows/identity/ui/timer.h create mode 100644 krb5-1-6/src/windows/identity/ui/toolbar.c create mode 100644 krb5-1-6/src/windows/identity/ui/toolbar.h create mode 100644 krb5-1-6/src/windows/identity/ui/uiconfig.csv create mode 100644 krb5-1-6/src/windows/identity/uilib/Makefile create mode 100644 krb5-1-6/src/windows/identity/uilib/accel.csv create mode 100644 krb5-1-6/src/windows/identity/uilib/acceldef.cfg create mode 100644 krb5-1-6/src/windows/identity/uilib/action.c create mode 100644 krb5-1-6/src/windows/identity/uilib/actiondef.cfg create mode 100644 krb5-1-6/src/windows/identity/uilib/actions.csv create mode 100644 krb5-1-6/src/windows/identity/uilib/alert.c create mode 100644 krb5-1-6/src/windows/identity/uilib/configui.c create mode 100644 krb5-1-6/src/windows/identity/uilib/configui.h create mode 100644 krb5-1-6/src/windows/identity/uilib/creddlg.c create mode 100644 krb5-1-6/src/windows/identity/uilib/intaction.h create mode 100644 krb5-1-6/src/windows/identity/uilib/intalert.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khaction.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khactiondef.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khalerts.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khconfigui.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khhtlink.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khnewcred.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khprops.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khremote.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khrescache.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khtracker.h create mode 100644 krb5-1-6/src/windows/identity/uilib/khuidefs.h create mode 100644 krb5-1-6/src/windows/identity/uilib/propsheet.c create mode 100644 krb5-1-6/src/windows/identity/uilib/propwnd.c create mode 100644 krb5-1-6/src/windows/identity/uilib/rescache.c create mode 100644 krb5-1-6/src/windows/identity/uilib/trackerwnd.c create mode 100644 krb5-1-6/src/windows/identity/uilib/uibind.c create mode 100644 krb5-1-6/src/windows/identity/uilib/uilibmain.c create mode 100644 krb5-1-6/src/windows/identity/uilib/version.c create mode 100644 krb5-1-6/src/windows/identity/util/Makefile create mode 100644 krb5-1-6/src/windows/identity/util/hashtable.c create mode 100644 krb5-1-6/src/windows/identity/util/hashtable.h create mode 100644 krb5-1-6/src/windows/identity/util/mstring.c create mode 100644 krb5-1-6/src/windows/identity/util/mstring.h create mode 100644 krb5-1-6/src/windows/identity/util/perfstat.c create mode 100644 krb5-1-6/src/windows/identity/util/perfstat.h create mode 100644 krb5-1-6/src/windows/identity/util/sync.c create mode 100644 krb5-1-6/src/windows/identity/util/sync.h create mode 100644 krb5-1-6/src/windows/identity/util/utils.h create mode 100644 krb5-1-6/src/windows/installer/nsis/KfWConfigPage.ini create mode 100644 krb5-1-6/src/windows/installer/nsis/KfWConfigPage2.ini create mode 100644 krb5-1-6/src/windows/installer/nsis/kfw-fixed.nsi create mode 100644 krb5-1-6/src/windows/installer/nsis/kfw.ico create mode 100644 krb5-1-6/src/windows/installer/nsis/kfw.nsi create mode 100644 krb5-1-6/src/windows/installer/nsis/killer.cpp create mode 100644 krb5-1-6/src/windows/installer/nsis/licenses.rtf create mode 100644 krb5-1-6/src/windows/installer/nsis/nsi-includes-tagged.nsi create mode 100644 krb5-1-6/src/windows/installer/nsis/site-local-tagged.nsi create mode 100644 krb5-1-6/src/windows/installer/nsis/utils.nsi create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/bannrbmp.bmp create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/completi.ico create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/custicon.ico create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/dlgbmp.bmp create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/exclamic.ico create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/info.bmp create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/insticon.ico create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/new.bmp create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/removico.ico create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/repairic.ico create mode 100644 krb5-1-6/src/windows/installer/wix/Binary/up.bmp create mode 100644 krb5-1-6/src/windows/installer/wix/Makefile create mode 100644 krb5-1-6/src/windows/installer/wix/config.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/custom/custom.cpp create mode 100644 krb5-1-6/src/windows/installer/wix/custom/custom.h create mode 100644 krb5-1-6/src/windows/installer/wix/features.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/files.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/kfw.wxs create mode 100644 krb5-1-6/src/windows/installer/wix/lang/config_1033.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/lang/license.rtf create mode 100644 krb5-1-6/src/windows/installer/wix/lang/strings_1033.wxl create mode 100644 krb5-1-6/src/windows/installer/wix/lang/ui_1033.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/msi-deployment-guide.txt create mode 100644 krb5-1-6/src/windows/installer/wix/platform.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/property.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/runtime.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/runtime_debug.wxi create mode 100644 krb5-1-6/src/windows/installer/wix/site-local-tagged.wxi create mode 100644 krb5-1-6/src/windows/kfwlogon/Makefile.in create mode 100644 krb5-1-6/src/windows/kfwlogon/kfwcommon.c create mode 100644 krb5-1-6/src/windows/kfwlogon/kfwcpcc.c create mode 100644 krb5-1-6/src/windows/kfwlogon/kfwlogon.c create mode 100644 krb5-1-6/src/windows/kfwlogon/kfwlogon.def create mode 100644 krb5-1-6/src/windows/kfwlogon/kfwlogon.h create mode 100644 krb5-1-6/src/windows/lib/Makefile.in create mode 100644 krb5-1-6/src/windows/lib/cacheapi.h create mode 100644 krb5-1-6/src/windows/lib/gic.c create mode 100644 krb5-1-6/src/windows/lib/gic.h create mode 100644 krb5-1-6/src/windows/lib/registry.c create mode 100644 krb5-1-6/src/windows/lib/registry.h create mode 100644 krb5-1-6/src/windows/lib/vardlg.c create mode 100644 krb5-1-6/src/windows/lib/vardlg.h create mode 100644 krb5-1-6/src/windows/ms2mit/Makefile.in create mode 100644 krb5-1-6/src/windows/ms2mit/mit2ms.c create mode 100644 krb5-1-6/src/windows/ms2mit/ms2mit.c create mode 100644 krb5-1-6/src/windows/version.rc create mode 100644 krb5-1-6/src/windows/winlevel.h create mode 100644 krb5-1-6/src/windows/wintel/Makefile.in create mode 100644 krb5-1-6/src/windows/wintel/auth.c create mode 100644 krb5-1-6/src/windows/wintel/auth.h create mode 100644 krb5-1-6/src/windows/wintel/dialog.h create mode 100644 krb5-1-6/src/windows/wintel/edit.c create mode 100644 krb5-1-6/src/windows/wintel/emul.c create mode 100644 krb5-1-6/src/windows/wintel/enc_des.c create mode 100644 krb5-1-6/src/windows/wintel/enc_des.h create mode 100644 krb5-1-6/src/windows/wintel/encrypt.c create mode 100644 krb5-1-6/src/windows/wintel/encrypt.h create mode 100644 krb5-1-6/src/windows/wintel/font.c create mode 100644 krb5-1-6/src/windows/wintel/genget.c create mode 100644 krb5-1-6/src/windows/wintel/ini.h create mode 100644 krb5-1-6/src/windows/wintel/intern.c create mode 100644 krb5-1-6/src/windows/wintel/k5stream.c create mode 100644 krb5-1-6/src/windows/wintel/k5stream.h create mode 100644 krb5-1-6/src/windows/wintel/ktelnet.doc create mode 100644 krb5-1-6/src/windows/wintel/ktelnet.hlp create mode 100644 krb5-1-6/src/windows/wintel/ktelnet.hpj create mode 100644 krb5-1-6/src/windows/wintel/ncsa.ico create mode 100644 krb5-1-6/src/windows/wintel/negotiat.c create mode 100644 krb5-1-6/src/windows/wintel/resource.h create mode 100644 krb5-1-6/src/windows/wintel/screen.c create mode 100644 krb5-1-6/src/windows/wintel/screen.h create mode 100644 krb5-1-6/src/windows/wintel/struct.h create mode 100644 krb5-1-6/src/windows/wintel/telnet.c create mode 100644 krb5-1-6/src/windows/wintel/telnet.def create mode 100644 krb5-1-6/src/windows/wintel/telnet.h create mode 100644 krb5-1-6/src/windows/wintel/telnet.rc create mode 100644 krb5-1-6/src/windows/wintel/telnet_arpa.h create mode 100644 krb5-1-6/src/windows/wintel/telopts.h create mode 100644 krb5-1-6/src/windows/wintel/terminal.ico create mode 100644 krb5-1-6/src/windows/wintel/wt-proto.h diff --git a/krb5-1-6/README b/krb5-1-6/README new file mode 100644 index 000000000..e618af181 --- /dev/null +++ b/krb5-1-6/README @@ -0,0 +1,928 @@ + Kerberos Version 5, Release 1.6.3 + + Release Notes + The MIT Kerberos Team + +Unpacking the Source Distribution +--------------------------------- + +The source distribution of Kerberos 5 comes in a gzipped tarfile, +krb5-1.6.3.tar.gz. Instructions on how to extract the entire +distribution follow. + +If you have the GNU tar program and gzip installed, you can simply do: + + gtar zxpf krb5-1.6.3.tar.gz + +If you don't have GNU tar, you will need to get the FSF gzip +distribution and use gzcat: + + gzcat krb5-1.6.3.tar.gz | tar xpf - + +Both of these methods will extract the sources into krb5-1.6.3/src and +the documentation into krb5-1.6.3/doc. + +Building and Installing Kerberos 5 +---------------------------------- + +The first file you should look at is doc/install-guide.ps; it contains +the notes for building and installing Kerberos 5. The info file +krb5-install.info has the same information in info file format. You +can view this using the GNU emacs info-mode, or by using the +standalone info file viewer from the Free Software Foundation. This +is also available as an HTML file, install.html. + +Other good files to look at are admin-guide.ps and user-guide.ps, +which contain the system administrator's guide, and the user's guide, +respectively. They are also available as info files +kerberos-admin.info and krb5-user.info, respectively. These files are +also available as HTML files. + +If you are attempting to build under Windows, please see the +src/windows/README file. + +Reporting Bugs +-------------- + +Please report any problems/bugs/comments using the krb5-send-pr +program. The krb5-send-pr program will be installed in the sbin +directory once you have successfully compiled and installed Kerberos +V5 (or if you have installed one of our binary distributions). + +If you are not able to use krb5-send-pr because you haven't been able +compile and install Kerberos V5 on any platform, you may send mail to +krb5-bugs@mit.edu. + +You may view bug reports by visiting + +http://krbdev.mit.edu/rt/ + +and logging in as "guest" with password "guest". + +Major changes in krb5-1.6.3 +--------------------------- + +[5706] fix CVE-2007-3999, CVE-2007-4743 svc_auth_gss.c buffer overflow +[5707] fix CVE-2007-4000 modify_policy vulnerability + + The above are two kadmind vulnerabilities described in + MITKRB5-SA-2007-006. CVE-2007-3999 is actually a vulnerability in + the RPC library. + +[5617] Add PKINIT support + + At this point, PKINIT support should be considered to be ALPHA + code. APIs and configuration details may change in the future. + We would greatly appreciate testing and feedback of PKINIT + support. + +krb5-1.6.3 changes by ticket ID +------------------------------- + +3334 libkrb5 treats all KDC errors as terminal +4136 kadmin_unlock() calls kadm5_lock() instead of kadm5_unlock() +4950 gc_frm_kdc doesn't adjust use_conf_ktypes in referrals case +5471 krb5_ktfile_get_entry() can invalidate keytab file handle +5542 Optimize file/directory pruning in KfW build script +5548 Look for unix find command in multiple places in KfW build script +5577 MSI Deployment Guide +5581 Build fails in lib/gssapi/spnego +5584 NIM Changes Post KFW 3.2 +5604 NIM credential display doesn't update when credential deleted +5607 NIM GUI: Default identity display should not have a background color +5609 NIM watermark does not track tray icon +5613 NIM GUI: views jump around on the screen +5617 Add PKINIT support +5623 NIM: apply does not update saved values of general identities cfg page +5624 krb5_fcc_generate_new() doesn't work with mkstemp() +5625 KRB5_CALLCONV must be specified inside parens +5629 gss_init_sec_context does not release output token buffer when + used with spnego mech +5636 remove unused src/windows/identity/uilib/Makefile.w2k +5645 export krb5_get_profile +5653 compilation failure with IRIX native compiler +5666 read_entropy_from_device on partial read will not fill buffer +5673 NIM: resource leak in khui_action_trigger() +5674 NIM: Identity Configuration Panel Fixes +5675 NIM: New command-line options --hide and --show / new + command-line help dialog +5676 NIM: APP: Redesigned Color Schemas +5677 NIM: BUG: APP: Identity right click selection failure and + context menu keyboard events were ignored +5678 NIM: BUG: APP: WM_TIMER messages if received after timer event + is canceled results in invalid data access +5679 NIM: BUG: APP: Filler columns should not be resizeable +5680 NIM: BUG: APP: WM_PAINT messages received without update + regions results in incorrect window repainting behavior +5681 NIM: BUG: APP: Fix Cursor Position and Selection Usability Issues +5682 NIM: remove unused code from ui/credwnd.c +5683 NIM: support include files in schemas +5684 NIM: Keep API release documentation up to date +5685 NIM: FEATURE: API: Add Identity Provider Pre-Process Message + to trigger immediate identity selection +5686 NIM: BUG: LIB: khcint_remove_space() frees memory too soon + resulting in potential invalid memory access +5687 NIM: BUG: KRB5: External changes to default identity ccache + are improperly reflected by krb5 provider +5688 NIM: Reposition New Credentials Dialog if necessary +5689 NIM: BUG: APP: Revert ticket 5604 +5690 NIM: version update +5696 NIM: FEATURE: ALL: 64-bit Windows Support and Removal of + Compile Time Warnings +5697 make ccache handle referrals better +5698 Windows: Add support for 64-bit CCAPI DLL name: krbcc64s.exe +5700 -S sname option for kvno +5701 NIM: APP: remove unused preprocessor symbols from resource files +5702 NIM: LIB: a small source code readability change +5703 NIM: BUG: KRB5: FILE ccache support did not make use of + OPENCLOSE flags +5704 new warnings in pkinit code (patch needs review) +5705 GSS-API Win64 support: Access Leash API via leashw64.dll +5706 fix CVE-2007-3999, CVE-2007-4743 svc_auth_gss.c buffer overflow +5707 fix CVE-2007-4000 modify_policy vulnerability +5708 krb5_fcc_generate_new is non-functional +5710 Build 64-bit Windows gss.exe (gui version of gss-client.exe) + now that 64-bit CCAPI is available +5711 KFW: Add MSI installer for 64-bit AMD64 +5713 64-bit Windows krb5int_cc_default calls to Leash API must use + leashw64.dll +5719 NIM: FEATURE: APP: Add View->All Identities +5724 NIM: FEATURE: APP: Add Notification Icon Default Identity Context Menu +5751 KFW: permit administrative installs using MSI installation package +5753 NIM: BUG: APP: Do not report errors for modules that are not installed +5756 NIM: BUG: SRC: Windows\Identity Makefile "clean" more +5759 NIM: APP: BUG: restore HideWatermark functionality +5763 NIM: BUG: khm_krb5_initialize() failed to return error code +5764 NIM: BUG: Restore Copyright removed in revision 19855 +5766 MSLSA krb5_cc module fails to check success of UNICODE string + conversions +5768 set svn:eol-style property on a bunch of files +5772 NIM: BUG: SRC: Increase size of max ccache name buffers and + remove extraneous trailing path component separators +5773 NIM: BUG: KMM: Ensure proper buffer length for registry + multi-string reads; avoid error reports for modules without config + data; avoid race when sending thread quit message +5779 NIM: BUG: LIB: optimize khui_find_action() +5780 NIM: FEATURE: APP: Notification Icon Tooltip now includes + default identity name +5782 NIM: APP: BUG: Initial cursor position does not track selected identity +5783 NIM: APP: BUG: Identities without identity credentials are + listed as having credentials +5787 NIM: BUG: APP: Spell Check +5788 NIM: BUG: APP: Provide keyboard accelerator for switching + between advanced and basic obtain new credentials dialog modes +5789 NIM: documentation updates for KFW 3.2.2 +5790 NIM: SRC: disable potential uninitialized variable warning +5791 Add static ordinals to DLL exports +5792 NIM: BUG: LIB: deadlock in kmq +5793 NIM: BUG: APP: leaking prompts in obtain new credentials dialog +5794 NIM: BUG: APP: Change View->Choose Columns to View->Select + Columns to match standard windows style +5795 NIM: BUG: APP: store credential type in the correct field of + the khui_credwnd_identity structure +5796 NIM: BUG: APP: change notification icon state to track default + identity only +5797 NIM: BUG: APP: notification icon tooltip wrong string +5798 NIM: BUG: APP: command-line options window doesn't process + WM_CLOSE messages +5800 krb5_get_init_creds_opt_alloc needs to initialize the opt structure +5801 remove error tables by pointer +5802 libgssapi mechglue doesn't always store delegated credentials +5803 fix pkinit module deps for krb5-1.6.x + +Major changes in krb5-1.6.2 +--------------------------- + +[5585] fix MITKRB5-SA-2007-004: kadmind affected by multiple RPC + library vulnerabilities [CVE-2007-2442/VU#356961, + CVE-2007-2443/VU#365313] +[5586] fix MITKRB5-SA-2007-005: kadmind vulnerable to buffer overflow + [CVE-2007-2798/VU#554257] + +krb5-1.6.2 changes by ticket ID +------------------------------- + +5541 remove debugging code accidentally left in ftp/cmds.c +5546 race condition in referrals fallback +5547 profile stores empty string values without double quotes +5551 rd_req_decoded needs to deal with referral realms +5552 minor incompatability krb5-1.6.1 and OpenSSH_4.6p1, OpenSSL 0.9.8e +5554 Modify WIX installer to better support upgrading betas +5573 Kfw 3.2.0.msi is missing a file krb5/krb5.h +5579 krb5_walk_realm_tree leaks in capaths case +5585 fix MITKRB5-SA-2007-004 [CVE-2007-2442/VU#356961, + CVE-2007-2443/VU#365313] +5586 fix MITKRB5-SA-2007-005 [CVE-2007-2798/VU#554257] + +Major changes in krb5-1.6.1 +--------------------------- + +[5508] Fix MITKRB5-SA-2007-001: telnetd allows login as arbitrary user + [CVE-2007-0956, VU#220816] + +[5507] Fix MITKRB5-SA-2007-002: buffer overflow in krb5_klog_syslog + [CVE-2007-0957, VU#704024] + +[5445] Fix MITKRB5-SA-2007-003: double-free in kadmind - the RPC + library could perform a double-free due to a GSS-API library + bug [CVE-2007-1216, VU#419344] + +[5293] fix crash creating db2 database in non-existent directory + +krb5-1.6.1 changes by ticket ID +------------------------------- + +Listed below are the RT tickets of bugs fixed in krb5-1.6.1. Please see + +http://krbdev.mit.edu/rt/NoAuth/krb5-1.6/fixed-1.6.1.html + +for a current listing with links to the complete tickets. + +2724 kdc.conf man page typo in v4_mode section +5233 Change in behaviour in gss_release_buffer() by mechtypes + introduces memory leak +5238 fix leak in gss_krb5int_unseal_token_v3 +5246 Memory leak in tests/gssapi/t_imp_name.c +5257 error on gethostbyname is tested on errno instead of h_errno +5293 crash creating db2 database in non-existent directory +5294 create KDC database directory +5343 updated Windows README +5344 Update to KFW NSIS installer +5349 Proposed implementation of krb5_server_decrypt_ticket_keyblock + and krb5_server_decrypt_ticket_keytab +5353 kfw wix installer - memory overwrite error +5393 krb5-1.6: tcp kpasswd service required if only admin_server is + specified in krb5.conf +5394 krb5-1.6: segfault on password change +5396 Master ticket for NetIdMgr 1.2 commits +5397 NIM string tables +5398 NIM Kerberos v4 configuration dialog +5399 NIM Correct Visual Identity Expiration Status +5400 NIM Kerberos 5 Provider corrections +5403 Add KDC timesyncing support to the CCAPI ccache backend +5408 NIM - Context sensitive system tray menu and more +5409 KFW MSI installer corrections +5410 kt_file.c memory leak on error in krb5_kt_resolve / + krb5_kt_wresolve +5414 NIM Bug Fixes +5418 KFW: 32-bit builds use the pismere krbv4w32.dll library +5419 Microsoft Windows Visual Studio does not define ssize_t +5420 get_init_creds_opt extensibility +5437 hack to permit GetEnvironmentVariable usage without requiring + getenv() conversion +5445 gsstest doesn't like krb5-1.6 GSSAPI library + [also MITKRB5-SA-2007-003] +5446 KfW 3.1: stderr of kinit/klist/kdestroy cannot be re-directed + to file +5447 tail portability bug in k5srvutil +5452 NIM Improved Alert Management +5453 Windows - some apps define ssize_t as a preprocessor symbol +5454 krb5_get_cred_from_kdc fails to null terminate the tgt list +5455 valgrind detects uninitialized (but really unused) bytes in + 'queue' +5457 More existence tests; path update +5458 osf1: get proper library dependencies installed +5461 reverting commit to windows WIX installer (revision 19207) +5469 KFW: Vista Integrated Logon +5476 Zero sockaddrs in fai_add_entry() so we can compare them with + memcmp() +5477 Enable Vista support for MSLSA +5478 NIM: New Default View and miscellaneous fixes +5480 krb5 library uses kdc.conf when it shouldn't +5490 KfW build automation +5491 WIX installer stores WinLogon event handler under wrong + registry value +5492 remove unwanted files from kfw build script +5493 KFW: problems with non-interactive logons +5495 NIM commits for KFW 3.2 Beta 1 +5496 more bug fixes for NIM 1.2 (KFW 3.2) +5503 msi deployment guide updates for KFW 3.2 +5504 Network Identity Manager 1.2 User Manual +5505 More commits for NIM 1.2 Beta 1 +5507 MITKRB5-SA-2007-002: buffer overflow in krb5_klog_syslog +5508 MITKRB5-SA-2007-001: telnetd allows login as arbitrary user +5509 service location plugin returning no addresses handled + incorrectly +5510 krb5int_open_plugin_dirs errors out if directory does not + exist +5514 wix installer - modify file list +5515 KFW NSIS installer - copyright updates and aklog removal +5516 NIM 1.2.0.1 corrections +5518 EAI_NODATA deprecated, not always defined +5521 KfW build system (post kfw-3.2-beta1) +5522 NIM 3.2 documentation update +5523 KFW 3.2 Beta 2 commits +5524 NIM doxyfile.cfg - update to Doxygen 1.5.2 +5525 NIM 1.2 HtmlHelp User Documentation +5526 NIM - Fix taskbar button visibility on Vista +5527 kfw build - include netidmgr_userdoc.pdf in zip file +5528 Add vertical scrollbars to realm fields in dialogs +5529 Missing version resource info on krb5 files +5530 KFW 3.2.0.7002 about dialogue will not respond to alt-f4 +5532 KFW Network Provider Improvements +5533 updates for NIM developer documentation +5534 kfwlogon corrections for XP +5535 More NIM Developer documentation updates +5537 only check current dir for a.tmp +5539 add option to export instead of checkout, etc. + +Major changes in krb5-1.6 +------------------------- + +* Partial client implementation to handle server name referrals. + +* Pre-authentication plug-in framework, donated by Red Hat. + +* LDAP KDB plug-in, donated by Novell. + +* Fix for MITKRB5-SA-2006-002: the RPC library could call an + uninitialized function pointer, which created a security + vulnerability for kadmind. + +* Fix for MITKRB5-SA-2006-003: the GSS-API mechglue layer could fail + to initialize some output pointers, causing callers to attempt to + free uninitialized pointers. This caused a security vulnerability + in kadmind. + +Note that the implementation of referral handling involves a change to +the behavior of krb5_sname_to_principal() to return a zero-length +realm name if it is unable to find the realm corresponding to the +hostname. This special realm name signals the ticket-acquisition code +to request KDC canonicalization of service principal names. Other +library code has changed to accommodate this new behavior. This +particular method of implementing service principal name referral +handling may change in the future; we invite discussion on this +subject. + +Major known bugs in krb5-1.6 +---------------------------- + +5293 crash creating db2 database in non-existent directory + + Attempting to create a KDB in a non-existent directory using the + Berkeley DB back end may cause a crash resulting from a null pointer + dereference. If a core dump occurs, this may cause a local exposure + of sensitive information such a master key password. This will be + fixed in an upcoming patch release. + +krb5-1.6 changes by ticket ID +----------------------------- + +Listed below are the RT tickets of bugs fixed in krb5-1.6. Please see + +http://krbdev.mit.edu/rt/NoAuth/krb5-1.6/fixed-1.6.html + +for a current listing with links to the complete tickets. + +1204 Unable to get a TGT cross-realm referral +2087 undocumented options for kpropd +2240 krb5-config --cflags gssapi when used by OpenSSH-snap-20040212 +2579 kdc: add_to_transited may reference off end of array... +2652 Add support for referrals +2876 Tree does not compile with GCC 4.0 +2935 KDB/LDAP backend +3089 krb5_verify_init_creds() is not thread safe +3091 add krb5_cc_new_unique() +3218 kdb5_util load requires that the dumpfile be writable. +3276 local array of structures not declared static +3288 NetIdMgr cannot obtain Kerberos 5 tickets containing addresses +3322 get_cred_via_tkt() checks too strict on server principal +3522 Error code definitions are outside macros to prevent multiple + inclusion in public headers +3642 changes for embedding manifest into dlls and exes +3735 Add TCP change/set password support +3947 allow multiple calls to krb5_get_error_message to retrieve message +3955 check calling conventions specified for Windows +3961 fix stdcc.c to build without USE_CCAPI_V3 +4021 use GSS_C_NO_CHANNEL_BINDINGS not NULL in lib/rpc/auth_gss.c +4023 Turn off KLL automatic prompting support in kadmin +4024 gss_acquire_cred auto prompt support shouldn't break + gss_krb5_ccache_name() +4025 need to look harder for tclConfig.sh +4055 remove unused Metrowerks support from yarrow +4056 g_canon_name.c if-statement warning cleanup +4057 GSSAPI opaque types should be pointers to opaque structs, not void* +4256 Make process error +4292 LDAP error prevents KfM 6.0 from building on Tiger +4294 Bad loop logic in krb5_mcc_generate_new +4304 audit referrals merge (R18598) +4327 doc/krb5-protocol out of date +4389 cursor for iterating over ccaches +4412 Don't segfault if a preauth plugin module fails to load +4453 krb5-1.6-pre: fix warnings/ improve 64bit compatibility in the + ldap plugin +4454 krb5-1.6-pre: kdb5_ldap_util stashsrvpw does not work +4455 IRIX build fails w/ GCC 4.0 (really GNU ld) +4482 enabling LDAP mix-in support for kdb5_util load +4488 osf1 -oldstyle_liblookup typo +4495 Avoid segfault in krb5_do_preauth_tryagain +4496 fix invalid access found by valgrind +4501 fix krb5_ldap_iterate to handle NULL match_expr and + open_db_and_mkey to use KRB5_KDB_SRV_TYPE_ADMIN +4534 don't confuse profile iterator in 425 princ conversion +4561 UC Berkeley BSD license change +4562 latest Novell ldap patches and kdb5_util dump support for ldap +4566 leaks in preauth plugin support +4567 KDC can crash for certain client requests when preauth plugins + are used +4587 Change preauth plugin context scope and lifetimes +4624 remove t_prf and t_prf.o on make clean +4625 Make clean in lib/kdb leaves error table files +4657 krb5.h not C++-safe due to "struct krb5_cccol_cursor" +4683 Remove obsolete/conflicting prototype for krb524_convert_princs +4688 Add public function to get keylength associated with an enctype +4689 Update minor version numbers for 1.6 +4690 Add "get_data" function to the client preauth plugin interface +4692 Document changing the krbtgt key +4693 Delay kadmind random number initialization until after fork +4735 more Novell ldap patches from Nov 6 and Fix for wrong password + policy reference count +4737 correct client preauth plugin request_context +4738 allow server preauth plugin verify_padata function to return e-data +4739 cccursor backend for CCAPI +4755 update copyrights and acknowledgments +4770 Add macros for __attribute__((deprecated)) for krb4 and des APIs +4771 LDAP patch from Novell, 2006-10-13 +4772 fix some warnings in ldap code +4773 fix warning in preauth_plugin.h header +4774 avoid double frees in ccache manipulation around gen_new +4775 include realm in "can't resolve KDC" error message +4784 krb5_stdccv3_generate_new returns NULL ccache +4788 ccache double free in krb5_fcc_read_addrs(). +4799 krb5_c_keylength -> krb5_c_keylengths; add krb5_c_random_to_key +4805 replace existing calls of cc_gen_new() +4841 free error message when freeing context +4846 clean up preauth2 salt debug code +4860 fix LDAP plugin Makefile.in lib frag substitutions +4928 krb5int_copy_data_contents shouldn't free memory it didn't allocate +4941 referrals changes to telnet have unconditional debugging printfs +4942 skip all modules in plugin if init function fails +4955 Referrals code breaks krb5_set_password_using_ccache to Active + Directory +4967 referrals support assumes all rewrites produce TGS principals +4972 return edata from non-PA_REQUIRED preauth types +4973 send a new request with the new padata returned by + krb5_do_preauth_tryagain() +4980 Remove unused prototype for krb5_find_config_files +4981 Make clean in lib/krb5/os does not clean test objs +4991 fix for kdb5_util load bug with dumps from a LDAP KDB +4994 minor update to kdb5_util man page for LDAP plugin +5003 krb5_cc_remove should work for the CCAPI +5005 Reading maxlife, maxrenewlife and ticket flags from conf file + in LDAP plugin +5009 kadmin.local with LDAP backend fails to start when master key + enctype is not default enctype +5022 build the trunk on Windows (again) +5027 admin guide changes for the LDAP backend +5032 Don't leak padata when looping for krb5_do_preauth_tryagain() +5090 krb5_get_init_creds_opt_set_change_password_prompt +5115 krb5_rc_io_open_internal on error will call close(-1) +5116 minor ldap specific changes in man page +5121 keytab code can't match principals with realms not yet determined +5123 don't pass null pointer to krb5_do_preauth_tryagain() +5124 use KRB5KRB_ERR_GENERIC, not KRB_ERR_GENERIC in preauth2.c +5125 Add -clearpolicy to kadmin addprinc usage +5152 misc cleanups in admin guide ldap sections +5159 don't split HTML output from makeinfo +5223 Fix typo in user-guide.texinfo +5245 Repair broken links in NetIdMgr Help +5260 Deletion of principal fails +5265 update ldap/Makefile.in for newer autoconf substitution requirements +5271 Document KDC behavior without stash file +5279 Document what the kadmind ACL is for +5301 MITKRB5-SA-2006-002: svctcp_destroy() can call uninitialized function pointer +5302 MITKRB5-SA-2006-003: mechglue argument handling too lax + +Copyright and Other Legal Notices +--------------------------------- + +Copyright (C) 1985-2007 by the Massachusetts Institute of Technology. + +All rights reserved. + +Export of this software from the United States of America may require +a specific license from the United States Government. It is the +responsibility of any person or organization contemplating export to +obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of M.I.T. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. Furthermore if you modify this software you must label +your software as modified software and not distribute it in such a +fashion that it might be confused with the original MIT software. +M.I.T. makes no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied +warranty. + +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. + +Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +"Commercial use" means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + + -------------------- + +Portions of src/lib/crypto have the following copyright: + + 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. + + + -------------------- + +The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in kadmin/create, +kadmin/dbutil, kadmin/passwd, kadmin/server, lib/kadm5, and portions +of lib/rpc: + + Copyright, OpenVision Technologies, Inc., 1996, All Rights Reserved + + WARNING: Retrieving the OpenVision Kerberos Administration system + source code, as described below, indicates your acceptance of the + following terms. If you do not agree to the following terms, do not + retrieve the OpenVision Kerberos administration system. + + You may freely use and distribute the Source Code and Object Code + compiled from it, with or without modification, but this Source + Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, + INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR + FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER + EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY + FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, + WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE + CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY + OTHER REASON. + + OpenVision retains all copyrights in the donated Source Code. OpenVision + also retains copyright to derivative works of the Source Code, whether + created by OpenVision or by a third party. The OpenVision copyright + notice must be preserved if derivative works are made based on the + donated Source Code. + + OpenVision Technologies, Inc. has donated this Kerberos + Administration system to MIT for inclusion in the standard + Kerberos 5 distribution. This donation underscores our + commitment to continuing Kerberos technology development + and our gratitude for the valuable work which has been + performed by MIT and the Kerberos community. + + -------------------- + + Portions contributed by Matt Crawford were + work performed at Fermi National Accelerator Laboratory, which is + operated by Universities Research Association, Inc., under + contract DE-AC02-76CHO3000 with the U.S. Department of Energy. + + -------------------- + +The implementation of the Yarrow pseudo-random number generator in +src/lib/crypto/yarrow has the following copyright: + + Copyright 2000 by Zero-Knowledge Systems, Inc. + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without fee, + 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 Zero-Knowledge Systems, + Inc. not be used in advertising or publicity pertaining to + distribution of the software without specific, written prior + permission. Zero-Knowledge Systems, Inc. makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + ZERO-KNOWLEDGE SYSTEMS, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL ZERO-KNOWLEDGE SYSTEMS, INC. BE LIABLE FOR + ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT + OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + -------------------- + +The implementation of the AES encryption algorithm in +src/lib/crypto/aes has the following copyright: + + Copyright (c) 2001, Dr Brian Gladman , Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + + -------------------- + +Portions contributed by Red Hat, including the pre-authentication +plug-ins framework, contain the following copyright: + + Copyright (c) 2006 Red Hat, Inc. + Portions copyright (c) 2006 Massachusetts Institute of Technology + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Red Hat, Inc., nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + -------------------- + +The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in +src/lib/gssapi, including the following files: + + lib/gssapi/generic/gssapi_err_generic.et + lib/gssapi/mechglue/g_accept_sec_context.c + lib/gssapi/mechglue/g_acquire_cred.c + lib/gssapi/mechglue/g_canon_name.c + lib/gssapi/mechglue/g_compare_name.c + lib/gssapi/mechglue/g_context_time.c + lib/gssapi/mechglue/g_delete_sec_context.c + lib/gssapi/mechglue/g_dsp_name.c + lib/gssapi/mechglue/g_dsp_status.c + lib/gssapi/mechglue/g_dup_name.c + lib/gssapi/mechglue/g_exp_sec_context.c + lib/gssapi/mechglue/g_export_name.c + lib/gssapi/mechglue/g_glue.c + lib/gssapi/mechglue/g_imp_name.c + lib/gssapi/mechglue/g_imp_sec_context.c + lib/gssapi/mechglue/g_init_sec_context.c + lib/gssapi/mechglue/g_initialize.c + lib/gssapi/mechglue/g_inquire_context.c + lib/gssapi/mechglue/g_inquire_cred.c + lib/gssapi/mechglue/g_inquire_names.c + lib/gssapi/mechglue/g_process_context.c + lib/gssapi/mechglue/g_rel_buffer.c + lib/gssapi/mechglue/g_rel_cred.c + lib/gssapi/mechglue/g_rel_name.c + lib/gssapi/mechglue/g_rel_oid_set.c + lib/gssapi/mechglue/g_seal.c + lib/gssapi/mechglue/g_sign.c + lib/gssapi/mechglue/g_store_cred.c + lib/gssapi/mechglue/g_unseal.c + lib/gssapi/mechglue/g_userok.c + lib/gssapi/mechglue/g_utils.c + lib/gssapi/mechglue/g_verify.c + lib/gssapi/mechglue/gssd_pname_to_uid.c + lib/gssapi/mechglue/mglueP.h + lib/gssapi/mechglue/oid_ops.c + lib/gssapi/spnego/gssapiP_spnego.h + lib/gssapi/spnego/spnego_mech.c + +are subject to the following license: + + Copyright (c) 2004 Sun Microsystems, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------- + +MIT Kerberos includes documentation and software developed at the +University of California at Berkeley, which includes this copyright +notice: + + Copyright (C) 1983 Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + -------------------- + +Portions contributed by Novell, Inc., including the LDAP database +backend, are subject to the following license: + + Copyright (c) 2004-2005, Novell, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The copyright holder's name is not used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + -------------------- + +Portions funded by Sandia National Laboratory and developed by the +University of Michigan's Center for Information Technology +Integration, including the PKINIT implementation, are subject to the +following license: + + COPYRIGHT (C) 2006-2007 + THE REGENTS OF THE UNIVERSITY OF MICHIGAN + ALL RIGHTS RESERVED + + Permission is granted to use, copy, create derivative works + and redistribute this software and such derivative works + for any purpose, so long as the name of The University of + Michigan is not used in any advertising or publicity + pertaining to the use of distribution of this software + without specific, written prior authorization. If the + above copyright notice or any other identification of the + University of Michigan is included in any copy of any + portion of this software, then the disclaimer below must + also be included. + + THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. + + -------------------- + +The pkcs11.h file included in the PKINIT code has the following +license: + + Copyright 2006 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. + +Acknowledgments +--------------- + +Thanks to Red Hat for donating the pre-authentication plug-in +framework. + +Thanks to Novell for donating the KDB abstraction layer and the LDAP +database plug-in. + +Thanks to Sun Microsystems for donating their implementations of +mechglue and SPNEGO. + +Thanks to iDefense for notifying us about the vulnerability in +MITKRB5-SA-2007-002. + +Thanks to the CITI group at the University of Michigan for +contributing the implementation of PKINIT. + +Thanks to Tenable Network Security and 3Com's Zero Day Initiative for +discovering CVE-2007-3999. Thanks to Kevin Coffman (UMich), Will +Fiveash (Sun), and Nico Williams (Sun) for help with developing the +revised patch. + +Thanks to Garrett Wollman of MIT CSAIL for discovering CVE-2007-4000. + +Thanks to the members of the Kerberos V5 development team at MIT, both +past and present: Danilo Almeida, Jeffrey Altman, Justin Anderson, +Richard Basch, Jay Berkenbilt, Mitch Berger, Andrew Boardman, Joe +Calzaretta, John Carr, Don Davis, Alexandra Ellwood, Nancy Gilman, +Matt Hancher, Sam Hartman, Paul Hill, Marc Horowitz, Eva Jacobus, +Miroslav Jurisic, Barry Jaspan, Geoffrey King, Kevin Koch, John Kohl, +Peter Litwack, Scott McGuire, Kevin Mitchell, Cliff Neuman, Paul Park, +Ezra Peisach, Chris Provenzano, Ken Raeburn, Jon Rochlis, Jeff +Schiller, Jen Selby, Brad Thompson, Harry Tsai, Ted Ts'o, Marshall +Vale, Tom Yu. diff --git a/krb5-1-6/doc/.cvsignore b/krb5-1-6/doc/.cvsignore new file mode 100644 index 000000000..c865798db --- /dev/null +++ b/krb5-1-6/doc/.cvsignore @@ -0,0 +1,20 @@ +*.html +*.info +*.info-* +*.log +*.dvi +*.aux +*.toc +*.cp +*.fn +*.vf +*.tp +*.ky +*.pg +*.vr +*.ps +*.fns +*.tps +*.vrs +*.pdf +krb5-install diff --git a/krb5-1-6/doc/Makefile b/krb5-1-6/doc/Makefile new file mode 100644 index 000000000..1bfaaa59c --- /dev/null +++ b/krb5-1-6/doc/Makefile @@ -0,0 +1,183 @@ +SRCDIR=../src +DVI=texi2dvi4a2ps # texi2dvi +DVIPS=dvips -o "$@" +PSPDF=ps2pdf +INFO=makeinfo +HTML=makeinfo --html --no-split +RM=rm -f +TAR=tar -chvf +GZIP=gzip -9 +MANPS=./man2ps +MANTXT=nroff -man +MANHTML=./man2html + +ADMIN_INCLUDES=definitions.texinfo copyright.texinfo document-list.texinfo \ + glossary.texinfo support-enc.texinfo salts.texinfo krb5conf.texinfo \ + kdcconf.texinfo dnstxt.texinfo dnssrv.texinfo send-pr.texinfo +ADMIN_DEPS=admin.texinfo $(ADMIN_INCLUDES) + +INSTALL_INCLUDES=definitions.texinfo copyright.texinfo document-list.texinfo \ + dnstxt.texinfo dnssrv.texinfo build.texinfo bug-report.texinfo \ + krb5conf.texinfo kdcconf.texinfo send-pr.texinfo +INSTALL_DEPS=install.texinfo $(INSTALL_INCLUDES) + +MANPAGES=$(SRCDIR)/appl/gssftp/ftp/ftp.M $(SRCDIR)/clients/kdestroy/kdestroy.M $(SRCDIR)/clients/kinit/kinit.M $(SRCDIR)/clients/klist/klist.M $(SRCDIR)/clients/ksu/ksu.M $(SRCDIR)/appl/bsd/rcp.M $(SRCDIR)/appl/bsd/rlogin.M $(SRCDIR)/appl/bsd/rsh.M $(SRCDIR)/appl/telnet/telnet/telnet.1 $(SRCDIR)/kadmin/passwd/kpasswd.M + +USER_GUIDE_INCLUDES=definitions.texinfo copyright.texinfo glossary.texinfo +USER_GUIDE_DEPS=user-guide.texinfo $(USER_GUIDE_INCLUDES) + +KRB425_INCLUDES=definitions.texinfo copyright.texinfo +KRB425_DEPS=krb425.texinfo $(KRB425_INCLUDES) + +.PHONY: all +all:: admin-guide-full install-guide-full user-guide-full krb425-guide-full clean-temp-ps clean-tex + +.PHONY: admin-guide-full +admin-guide-full:: admin-guide admin-guide-info admin-guide-html + +.PHONY: admin-guide +admin-guide:: admin-guide.ps + +admin-guide.ps: $(ADMIN_DEPS) + $(DVI) admin.texinfo + $(DVIPS) admin + +admin-guide.pdf: admin-guide.ps + $(PSPDF) admin-guide.ps admin-guide.pdf + +.PHONY: admin-guide-html +admin-guide-html:: admin.html + +admin.html: $(ADMIN_DEPS) + $(HTML) admin.texinfo + +.PHONY: admin-guide-info +admin-guide-info:: krb5-admin.info + +krb5-admin.info: $(ADMIN_DEPS) + $(INFO) admin.texinfo + +.PHONY: install-guide-full +install-guide-full:: install-guide install-guide-info install-guide-html + +.PHONY: install-guide +install-guide:: install-guide.ps + +install-guide.ps: $(INSTALL_DEPS) + $(DVI) install.texinfo + $(DVIPS) install + +install-guide.pdf: install-guide.ps + $(PSPDF) install-guide.ps install-guide.pdf + +.PHONY: install-guide-html +install-guide-html:: install.html + +install.html:: $(INSTALL_DEPS) + $(HTML) install.texinfo + +.PHONY: install-guide-info +install-guide-info:: krb5-install.info + +krb5-install.info: $(INSTALL_DEPS) + $(INFO) install.texinfo + +.PHONY: user-guide-full +user-guide-full:: user-guide user-guide-info user-guide-html + +.PHONY: user-guide +user-guide:: user-guide.ps + +user-guide.ps: $(USER_GUIDE_DEPS) + $(DVI) user-guide.texinfo + $(MANPS) $(MANPAGES) + $(DVIPS) user-guide + +user-guide.pdf: user-guide.ps + $(PSPDF) user-guide.ps user-guide.pdf + +.PHONY: user-guide-info +user-guide-info:: krb5-user.info + +krb5-user.info: $(USER_GUIDE_DEPS) + $(INFO) user-guide.texinfo + +.PHONY: user-guide-html +user-guide-html:: user-guide.html + +user-guide.html: $(USER_GUIDE_DEPS) + $(MANTXT) $(SRCDIR)/appl/gssftp/ftp/ftp.M | $(MANHTML) > ftp.html + $(MANTXT) $(SRCDIR)/clients/kdestroy/kdestroy.M | $(MANHTML) > kdestroy.html + $(MANTXT) $(SRCDIR)/clients/kinit/kinit.M | $(MANHTML) > kinit.html + $(MANTXT) $(SRCDIR)/clients/klist/klist.M | $(MANHTML) > klist.html + $(MANTXT) $(SRCDIR)/clients/ksu/ksu.M | $(MANHTML) > ksu.html + $(MANTXT) $(SRCDIR)/appl/bsd/rcp.M | $(MANHTML) > rcp.html + $(MANTXT) $(SRCDIR)/appl/bsd/rlogin.M | $(MANHTML) > rlogin.html + $(MANTXT) $(SRCDIR)/appl/bsd/rsh.M | $(MANHTML) > rsh.html + $(MANTXT) $(SRCDIR)/appl/telnet/telnet/telnet.1 | $(MANHTML) > telnet.html + $(MANTXT) $(SRCDIR)/kadmin/passwd/kpasswd.M | $(MANHTML) > kpasswd.html + $(HTML) user-guide.texinfo + +.PHONY: krb425-guide-full +krb425-guide-full:: krb425-guide krb425-guide-info krb425-guide-html + +.PHONY: krb425-guide +krb425-guide:: krb425-guide.ps + +krb425-guide.ps: $(KRB425_DEPS) + $(DVI) krb425.texinfo + $(DVIPS) krb425 + +.PHONY: krb425-guide-html +krb425-guide-html:: krb425.html + +krb425.html:: $(KRB425_DEPS) + $(HTML) krb425.texinfo + +.PHONY: krb425-guide-info +krb425-guide-info:: krb425.info + +krb425.info: $(KRB425_DEPS) + $(INFO) krb425.texinfo + +.PHONY: implementor.ps implementor.pdf implementor.info +implementor.pdf: implementor.ps + $(PSPDF) implementor.ps +implementor.ps: implementor.texinfo + $(DVI) implementor.texinfo + $(DVIPS) implementor +implementor.info: implementor.texinfo + $(INFO) implementor.texinfo + +.PHONY: clean +clean:: clean-all + +.PHONY: clean-all +clean-all:: clean-tex clean-backup clean-final clean-tarfiles + +.PHONY: clean-final +clean-final:: + $(RM) *.ps *.info *.info-? *.html *.pdf + +.PHONY: clean-tex +clean-tex:: + $(RM) *.aux *.cp *.dvi *.fn *.ky *.log *.pg *.toc *.tp *.vr *.fns *.vrs *.tps + +.PHONY: clean-backup +clean-backup:: + $(RM) *~ #* + +.PHONY: clean-tarfiles +clean-tarfiles:: + $(RM) *.tar *.tar.gz *.tgz + +.PHONY: clean-temp-ps +clean-temp-ps:: + $(RM) ftp?.ps kinit?.ps klist?.ps kdestroy?.ps ksu?.ps rlogin?.ps \ + rcp?.ps rsh?.ps telnet?.ps kpasswd?.ps + +.PHONY: tgz +tgz:: + $(TAR) krb5-docs.tar admin.texinfo build.texinfo copyright.texinfo definitions.texinfo document-list.texinfo glossary.texinfo install.texinfo texinfo.tex user-guide.texinfo *-guide.ps *.info *.info-? *.html + $(GZIP) krb5-docs.tar + $(MV) krb5-docs.tar.gz krb5-docs.tgz diff --git a/krb5-1-6/doc/admin.texinfo b/krb5-1-6/doc/admin.texinfo new file mode 100644 index 000000000..79608f372 --- /dev/null +++ b/krb5-1-6/doc/admin.texinfo @@ -0,0 +1,5414 @@ +\input texinfo-suppl.tex % contains @doubleleftarrow{} definition + % this line must come *before* \input texinfo +\input texinfo @c -*-texinfo-*- +@c %**start of header +@c guide +@setfilename krb5-admin.info +@settitle Kerberos V5 System Administrator's Guide +@setchapternewpage odd @c chapter begins on next odd page +@c @setchapternewpage on @c chapter begins on next page +@c @smallbook @c Format for 7" X 9.25" paper +@c %**end of header +@paragraphindent 0 +@iftex +@parskip 6pt plus 6pt +@end iftex + +@dircategory Kerberos +@direntry +* krb5-admin: (krb5-admin). Kerberos V5 Administrator's Guide +@end direntry + +@include definitions.texinfo +@set EDITION 1.0 +@set UPDATED June 14, 2007 + +@finalout @c don't print black warning boxes + +@titlepage +@title @value{PRODUCT} System Administrator's Guide +@subtitle Release: @value{RELEASE} +@subtitle Document Edition: @value{EDITION} +@subtitle Last updated: @value{UPDATED} +@author @value{COMPANY} + +@page +@vskip 0pt plus 1filll + +@end titlepage + +@comment node-name, next, previous, up +@node Top, Copyright, (dir), (dir) + +@ifinfo +This document describes how to administrate a @value{PRODUCT} +installation. +@end ifinfo + +@c The master menu is updated using emacs19's M-x texinfo-all-menus-update +@c function. Don't forget to run M-x texinfo-every-node-update after +@c you add a new section or subsection, or after you've rearranged the +@c order of sections or subsections. Also, don't forget to add an @node +@c comand before each @section or @subsection! All you need to enter +@c is: +@c +@c @node New Section Name +@c @section New Section Name +@c +@c M-x texinfo-every-node-update will take care of calculating the +@c node's forward and back pointers. +@c +@c --------------------------------------------------------------------- + +@menu +* Copyright:: +* Introduction:: +* How Kerberos Works:: +* Configuration Files:: +* Using DNS:: +* Administrating the Kerberos Database:: +* Configuring Kerberos with OpenLDAP back-end:: +* Application Servers:: +* Backups of Secure Hosts:: +* Bug Reporting:: +* Appendix:: +@end menu + +@node Copyright, Introduction, Top, Top +@unnumbered Copyright +@include copyright.texinfo + + +@node Introduction, How Kerberos Works, Copyright, Top +@chapter Introduction + +@menu +* Why Should I use Kerberos?:: +* Documentation for Kerberos V5:: +* Overview of This Guide:: +@end menu + +@node Why Should I use Kerberos?, Documentation for Kerberos V5, Introduction, Introduction +@section Why Should I use Kerberos? + +Since Kerberos negotiates authenticated, and optionally encrypted, +communications between two points anywhere on the internet, it provides +a layer of security that is not dependent on which side of a firewall +either client is on. Since studies have shown that half of the computer +security breaches in industry happen from @i{inside} firewalls, +@value{PRODUCT} from @value{COMPANY} will play a vital role in the +security of your network. + +@node Documentation for Kerberos V5, Overview of This Guide, Why Should I use Kerberos?, Introduction +@section Documentation for @value{PRODUCT} + +@include document-list.texinfo + +@node Overview of This Guide, , Documentation for Kerberos V5, Introduction +@section Overview of This Guide + +The next chapter describes how Kerberos works. + +Chapter three describes administration of the principals in the Kerberos +database. + +Chapter four describes how you can use DNS in configuring your Kerberos realm. + +Chapter five describes administrative programs for manipulating the +Kerberos database as a whole. + +Chapter six describes OpenLDAP Configuration steps. + +Chapter seven describes issues to consider when adding an application +server to the database. + +Chapter eight describes our problem reporting system. + +The appendices include the list of Kerberos error messages, and a +complete list of the time zones understood by @code{kadmin}. + +@node How Kerberos Works, Configuration Files, Introduction, Top +@chapter How Kerberos Works + +This section provides a simplified description of a general user's +interaction with the Kerberos system. This interaction happens +transparently---users don't need to know and probably don't care about +what's going on---but Kerberos administrators might find a schematic +description of the process useful. This description glosses over a lot +of details; for more information, see @i{Kerberos: An Authentication +Service for Open Network Systems}, a paper presented at Winter USENIX +1988, in Dallas, Texas. This paper can be retreived by FTP from +@code{athena-dist.mit.edu}, in the location: +@code{/pub/ATHENA/kerberos/doc/usenix.PS}. + +@menu +* Network Services and Their Client Programs:: +* Kerberos Tickets:: +* The Kerberos Database:: +* Kerberos Realms:: +* The Ticket-Granting Ticket:: +* Network Services and the Master Database:: +* The User/Kerberos Interaction:: +* Definitions:: +@end menu + +@node Network Services and Their Client Programs, Kerberos Tickets, How Kerberos Works, How Kerberos Works +@section Network Services and Their Client Programs + +In an environment that provides network services, you use @dfn{client} +programs to request @dfn{services} from @dfn{server} programs that are +somewhere on the network. Suppose you have logged in to a workstation +and you want to @samp{rlogin} to a typical UNIX host. You use the local +@samp{rlogin} client program to contact the remote machine's +@samp{rlogind} daemon. + +@node Kerberos Tickets, The Kerberos Database, Network Services and Their Client Programs, How Kerberos Works +@section Kerberos Tickets + +Under Kerberos, the @samp{klogind} daemon allows you to login to a +remote machine if you can provide @samp{klogind} a Kerberos ticket +which proves your identity. In addition to the ticket, you must also +have possession of the corresponding ticket session key. The +combination of a ticket and the ticket's session key is known as a credential. + +Typically, a client program automatically obtains credentials +identifying the person using the client program. The credentials are +obtained from a Kerberos server that resides somewhere on the network. +A Kerberos server maintains a database of user, server, and password +information. + +@node The Kerberos Database, Kerberos Realms, Kerberos Tickets, How Kerberos Works +@section The Kerberos Database + +Kerberos will give you credentials only if you have an entry in the +Kerberos server's @dfn{Kerberos database}. Your database entry includes +your Kerberos @dfn{principal} (an identifying string, which is often +just your username), and your Kerberos password. Every Kerberos user +must have an entry in this database. + +@node Kerberos Realms, The Ticket-Granting Ticket, The Kerberos Database, How Kerberos Works +@section Kerberos Realms + +Each administrative domain will have its own Kerberos database, which +contains information about the users and services for that particular +site or administrative domain. This administrative domain is the +@dfn{Kerberos realm}. + +Each Kerberos realm will have at least one Kerberos server, where the +master Kerberos database for that site or administrative domain is +stored. A Kerberos realm may also have one or more @dfn{slave servers}, +which have read-only copies of the Kerberos database that are +periodically propagated from the master server. For more details on how +this is done, see the ``Set Up the Slave KDCs for Database Propagation'' +and ``Propagate the Database to Each Slave KDC'' sections of the +@value{PRODUCT} Installation Guide. + +@node The Ticket-Granting Ticket, Network Services and the Master Database, Kerberos Realms, How Kerberos Works +@section The Ticket-Granting Ticket + +The @samp{kinit} command prompts for your password. If you enter it +successfully, you will obtain a @dfn{ticket-granting ticket} and a +@dfn{ticket session key} which gives you the right to use the ticket. +This combination of the ticket and its associated key is known as your +@dfn{credentials}. As illustrated below, client programs use your +ticket-granting ticket credentials in order to obtain client-specific +credentials as needed. + +Your credentials are stored in a @dfn{credentials cache}, which is often +just a file in @code{/tmp}. The credentials cache is also called the +@dfn{ticket file}, especially in Kerberos V4 documentation. Note, +however, that a credentials cache does not have to be stored in a file. + +@node Network Services and the Master Database, The User/Kerberos Interaction, The Ticket-Granting Ticket, How Kerberos Works +@section Network Services and the Master Database + +The master database also contains entries for all network services that +require Kerberos authentication. Suppose that your site has a machine, +@samp{laughter.@value{PRIMARYDOMAIN}}, that requires Kerberos +authentication from anyone who wants to @samp{rlogin} to it. The host's +Kerberos realm is @samp{@value{PRIMARYREALM}}. + +This service must be registered in the Kerberos database, using the +proper service name, which in this case is the @dfn{principal}: + +@smallexample +host/laughter.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} +@end smallexample + +@noindent +The @samp{/} character separates the Kerberos @dfn{primary} (in this +case, @samp{host}) from the @dfn{instance} (in this case, +@samp{laughter.@value{PRIMARYDOMAIN}}); the @samp{@@} character separates +the realm name (in this case, @samp{@value{PRIMARYREALM}}) from the rest +of the principal. The primary, @samp{host}, denotes the name or type of +the service that is being offered: generic host-level access to the +machine. The instance, @samp{laughter.@value{PRIMARYDOMAIN}}, names the +specific machine that is offering this service. There will generally be +many different machines, each offering one particular type of service, +and the instance serves to give each one of these servers a different +Kerberos principal. + +@menu +* The Keytab File:: +@end menu + +@node The Keytab File, , Network Services and the Master Database, Network Services and the Master Database +@subsection The Keytab File + +For each service, there must also be a @dfn{service key} known only by +Kerberos and the service. On the Kerberos server, the service key is +stored in the Kerberos database. + +On the server host, these service keys are stored in @dfn{key tables}, +which are files known as @dfn{keytabs}.@footnote{Keytabs were called +@dfn{srvtabs} in Kerberos V4.} For example, the service keys used by +services that run as root are usually stored in the keytab file +@code{/etc/krb5.keytab}. @b{N.B.:} This service key is the equivalent +of the service's password, and must be kept secure. Data which is meant +to be read only by the service is encrypted using this key. + +@node The User/Kerberos Interaction, Definitions, Network Services and the Master Database, How Kerberos Works +@section The User/Kerberos Interaction + +Suppose that you walk up to a host intending to login to it, and then +@samp{rlogin} to the machine @samp{laughter}. Here's what happens: + +@enumerate +@item +You login to the workstation and use the @samp{kinit} command to get a +ticket-granting ticket. This command prompts you for your Kerberos +password. (On systems running the @value{PRODUCT} @samp{login} program, +this may be done as part of the login process, not requiring the user to +run a separate program.) + +@enumerate A +@item +The @samp{kinit} command sends your request to the Kerberos master +server machine. The server software looks for your principal name's +entry in the Kerberos database. + +@item +If this entry exists, the Kerberos server creates and returns a +ticket-granting ticket and the key which allows you to use it, encrypted +by your password. If @samp{kinit} can decrypt the Kerberos reply using +the password you provide, it stores this ticket in a credentials cache +on your local machine for later use. The name of the credentials cache +can be specified in the @samp{KRB5CCNAME} environment variable. If this +variable is not set, the name of the file will be +@file{/tmp/krb5cc_}, where is your UNIX user-id, represented +in decimal format. +@end enumerate + +@need 1500 +@item +Now you use the @samp{rlogin} client to access the machine +@samp{laughter}. + +@example +host% @b{rlogin laughter} +@end example + +@enumerate A +@item +The @samp{rlogin} client checks your ticket file to see if you have a +ticket for the @samp{host} service for @samp{laughter}. You don't, so +@samp{rlogin} uses the credential cache's ticket-granting ticket to make +a request to the master server's ticket-granting service. + +@item +This ticket-granting service receives the request for a ticket for +@samp{host/laughter.@value{PRIMARYDOMAIN}}, and looks in the master +database for an entry for @samp{host/laughter.@value{PRIMARYDOMAIN}}. +If the entry exists, the ticket-granting service issues you a ticket for +that service. That ticket is also cached in your credentials cache. + +@item +The @samp{rlogin} client now sends that ticket to the @samp{laughter} +@samp{klogind} service program. The service program checks the ticket +by using its own service key. If the ticket is valid, it now knows your +identity. If you are allowed to login to @samp{laughter} (because your +username matches one in /etc/passwd, or your Kerberos principal is in +the appropriate @file{.k5login} file), @code{klogind} will let you +login. +@end enumerate +@end enumerate + +@node Definitions, , The User/Kerberos Interaction, How Kerberos Works +@section Definitions + +Following are definitions of some of the Kerberos terminology. + +@include glossary.texinfo + +@node Configuration Files, Using DNS, How Kerberos Works, Top +@chapter Configuration Files + +@menu +* Supported Encryption Types:: +* Salts:: +* krb5.conf:: +* kdc.conf:: +@end menu + +@node Supported Encryption Types, Salts, Configuration Files, Configuration Files +@section Supported Encryption Types + +Any tag in the configuration files which requires a list of encryption +types can be set to some combination of the following strings. + +@include support-enc.texinfo + +While aes128-cts and aes256-cts are supported for all Kerberos +operations, they are not supported by older versions of our GSSAPI +implementation (krb5-1.3.1 and earlier). + +By default, AES is enabled in this release. Sites wishing to use AES +encryption types on their KDCs need to be careful not to give GSSAPI +services AES keys if the servers have not been updated. If older +GSSAPI services are given AES keys, then services may fail when +clients supporting AES for GSSAPI are used. Sites may wish to use AES +for user keys and for the ticket granting ticket key, although doing +so requires specifying what encryption types are used as each +principal is created. + +If all GSSAPI-based services have been updated before or with the KDC, +this is not an issue. + +@node Salts, krb5.conf, Supported Encryption Types, Configuration Files +@section Salts + +Your Kerberos key is derived from your password. To ensure that people +who happen to pick the same password do not have the same key, Kerberos +5 incorporates more information into the key using something called a +salt. The supported values for salts are as follows. + +@include salts.texinfo + +@node krb5.conf, kdc.conf, Salts, Configuration Files +@section krb5.conf + +@include krb5conf.texinfo + +@menu +* libdefaults:: +* appdefaults:: +* login:: +* realms (krb5.conf):: +* domain_realm:: +* logging:: +* capaths:: +* dbdefaults:: +* dbmodules:: +* pkinit client options:: +* Sample krb5.conf File:: +@end menu + +@node libdefaults, appdefaults, krb5.conf, krb5.conf +@subsection [libdefaults] + +The @code{libdefaults} section may contain any of the following +relations: + +@table @b +@itemx default_keytab_name +This relation specifies the default keytab name to be used by +application servers such as telnetd and rlogind. The default is +@value{DefaultDefaultKeytabName}. + +@itemx default_realm +Identifies the default Kerberos realm for the client. Set its value to +your Kerberos realm. If this is not specified and the TXT record +lookup is enabled (see @ref{Using DNS}), then that information will be +used to determine the default realm. If this tag is not set in this +configuration file and there is no DNS information found, then an error +will be returned. + +@itemx default_tgs_enctypes +Identifies the supported list of session key encryption types that +should be returned by the KDC. The list may be delimited with commas +or whitespace. Kerberos supports many different encryption types, and +support for more is planned in the future. (see @ref{Supported Encryption +Types} for a list of the accepted values for this tag). The default +value is @value{DefaultDefaultTgsEnctypes}. + +@itemx default_tkt_enctypes +Identifies the supported list of session key encryption types that +should be requested by the client. The format is the same as for +@emph{default_tgs_enctypes}. The default value for this tag is +@value{DefaultDefaultTktEnctypes}. + +@itemx permitted_enctypes +Identifies all encryption types that are permitted for use in session +key encryption. The default value for this tag is +@value{DefaultPermittedEnctypes}. + +@itemx clockskew +Sets the maximum allowable amount of clockskew in seconds that the +library will tolerate before assuming that a Kerberos message is +invalid. The default value is @value{DefaultClockskew}. + +@itemx kdc_timesync +If this is set to 1 (for true), then client machines will compute the +difference between their time and the time returned by the KDC in the +timestamps in the tickets and use this value to correct for an +inaccurate system clock. This corrective factor is only used by the +Kerberos library. The default is @value{DefaultKDCTimesync}. + +@itemx kdc_req_checksum_type + +@itemx ap_req_checksum_type + +@itemx safe_checksum_type +An integer which specifies the type of checksum to use. Used for +compatability with DCE security servers which do not support the +default @value{DefaultChecksumType} used by this version of Kerberos. +The possible values and their meanings are as follows. + +@comment taken from krb5/src/include/krb5.h[in] +@table @b +@item 1 +CRC32 +@item 2 +RSA MD4 +@item 3 +RSA MD4 DES +@item 4 +DES CBC +@item 7 +RSA MD5 +@item 8 +RSA MD5 DES +@item 9 +NIST SHA +@item 12 +HMAC SHA1 DES3 +@item -138 +Microsoft MD5 HMAC checksum type +@end table + +@comment see lib/krb5/ccache/fcc.h +@itemx ccache_type +Use this parameter on systems which are DCE clients, to specify the +type of cache to be created by kinit, or when forwarded tickets are +received. DCE and Kerberos can share the cache, but some versions of +DCE do not support the default cache as created by this version of +Kerberos. Use a value of 1 on DCE 1.0.3a systems, and a value of 2 on +DCE 1.1 systems. The default value is @value{DefaultCcacheType}. + +@ignore +@itemx tkt_lifetime +The default lifetime of a ticket. The default is +@value{DefaultTktLifetime}. This is currently not supported by the +code. +@end ignore + +@itemx krb4_srvtab +Specifies the location of the Kerberos V4 srvtab file. Default is +@value{DefaultKrb4Srvtab}. + +@itemx krb4_config +Specifies the location of hte Kerberos V4 configuration file. Default +is @value{DefaultKrb4Config}. + +@itemx krb4_realms +Specifies the location of the Kerberos V4 domain/realm translation +file. Default is @value{DefaultKrb4Realms}. + +@itemx dns_lookup_kdc +Indicate whether DNS SRV records should be used to locate the KDCs and +other servers for a realm, if they are not listed in the information for +the realm. (Note that the @samp{admin_server} entry must be in the +file, because the DNS implementation for it is incomplete.) + +Enabling this option does open up a type of denial-of-service attack, if +someone spoofs the DNS records and redirects you to another server. +However, it's no worse than a denial of service, because that fake KDC +will be unable to decode anything you send it (besides the initial +ticket request, which has no encrypted data), and anything the fake KDC +sends will not be trusted without verification using some secret that it +won't know. + +If this option is not specified but @samp{dns_fallback} is, that value +will be used instead. If neither option is specified, the behavior +depends on configure-time options; if none were given, the default is to +enable this option. If the DNS support is not compiled in, this entry +has no effect. + +@itemx dns_lookup_realm +Indicate whether DNS TXT records should be used to determine the +Kerberos realm of a host. + +Enabling this option may permit a redirection attack, where spoofed DNS +replies persuade a client to authenticate to the wrong realm, when +talking to the wrong host (either by spoofing yet more DNS records or by +intercepting the net traffic). Depending on how the client software +manages hostnames, however, it could already be vulnerable to such +attacks. We are looking at possible ways to minimize or eliminate this +exposure. For now, we encourage more adventurous sites to try using +Secure DNS. + +If this option is not specified but @samp{dns_fallback} is, that value +will be used instead. If neither option is specified, the behavior +depends on configure-time options; if none were given, the default is to +disable this option. If the DNS support is not compiled in, this entry +has no effect. + +@itemx dns_fallback +General flag controlling the use of DNS for Kerberos information. If +both of the preceding options are specified, this option has no effect. + +@itemx extra_addresses +This allows a computer to use multiple local addresses, in order to +allow Kerberos to work in a network that uses NATs. The addresses +should be in a comma-separated list. + +@itemx udp_preference_limit +When sending a message to the KDC, the library will try using TCP before +UDP if the size of the message is above @code{udp_preference_list}. +If the message is smaller than @code{udp_preference_list}, then UDP +will be tried before TCP. Regardless of the size, both protocols will +be tried if the first attempt fails. + +@itemx verify_ap_req_nofail +If this flag is set, then an attempt to get initial credentials will +fail if the client machine does not have a keytab. The default for the +flag is @value{DefaultVerifyApReqNofail}. + +@itemx renew_lifetime +The value of this tag is the default renewable lifetime for +initial tickets. The default value for the tag is +@value{DefaultRenewLifetime}. + +@itemx noaddresses +Setting this flag causes the initial Kerberos ticket to be addressless. +The default for the flag is @value{DefaultNoaddresses}. + +@itemx forwardable +If this flag is set, initial tickets by default will be forwardable. +The default value for this flag is @value{DefaultForwardable}. + +@itemx proxiable +If this flag is set, initial tickets by default will be proxiable. +The default value for this flag is @value{DefaultProxiable}. + +@end table + + + +@node appdefaults, login, libdefaults, krb5.conf +@subsection [appdefaults] + +Each tag in the [appdefaults] section names a Kerberos V5 application +or an option that is used by some Kerberos V5 application[s]. The +value of the tag defines the default behaviors for that application. + +For example: + +@smallexample +@group +[appdefaults] + telnet = @{ + @value{PRIMARYREALM} = @{ + option1 = false + @} + @} + telnet = @{ + option1 = true + option2 = true + @} + @value{PRIMARYREALM} = @{ + option2 = false + @} + option2 = true + +@end group +@end smallexample + +The above four ways of specifying the value of an option are shown +in order of decreasing precedence. In this example, if telnet is +running in the realm @value{SECONDREALM}, it should, by default, have +option1 and option2 set to true. However, a telnet program in the realm +@value{PRIMARYREALM} should have option1 set to false and option2 set +to true. Any other programs in @value{PRIMARYREALM} should have option2 +set to false by default. Any programs running in other realms should +have option2 set to true. + +The list of specifiable options for each application may be found in +that application's man pages. The application defaults specified here +are overridden by those specified in the [realms] section. + +A special application name (afs_krb5) is used by the krb524 service to +know whether new format AFS tokens based on Kerberos 5 can be used +rather than the older format which used a converted Kerberos 4 ticket. +The new format allows for cross-realm authentication without +introducing a security hole. It is used by default. Older AFS +servers (before OpenAFS 1.2.8) will not support the new format. If +servers in your cell do not support the new format, you will need to +add an @code{afs_krb5} relation to the @code{appdefaults} section. +The following config file shows how to disable new format AFS tickets +for the @code{afs.example.com} cell in the @code{EXAMPLE.COM} realm. + +@smallexample +@group +[appdefaults] + afs_krb5 = @{ + EXAMPLE.COM = @{ + afs/afs.example.com = false + @} + @} + +@end group +@end smallexample + + + + + +@node login, realms (krb5.conf), appdefaults, krb5.conf +@subsection [login] + +Each tag in the [login] section of the file is an option for +login.krb5. This section may contain any of the following relations: + +@table @b +@itemx krb5_get_tickets +Indicate whether or not to use a user's password to get V5 tickets. +The default value is @value{DefaultKrb5GetTickets}. + +@itemx krb4_get_tickets +Indicate whether or not to user a user's password to get V4 tickets. +The default value is @value{DefaultKrb4GetTickets}. + +@itemx krb4_convert +Indicate whether or not to use the Kerberos conversion daemon to get V4 +tickets. The default value is @value{DefaultKrb4Convert}. If this is +set to false and krb4_get_tickets is true, then login will get the V5 +tickets directly using the Kerberos V4 protocol directly. This does +not currently work with non-MIT-V4 salt types (such as the AFS3 salt +type). Note that if this is set to true and krb524d is not running, +login will hang for approximately a minute under Solaris, due to a +Solaris socket emulation bug. + +@itemx krb_run_aklog +Indicate whether or not to run aklog. The default value is +@value{DefaultKrbRunAklog}. + +@itemx aklog_path +Indicate where to find aklog. The default value is +@value{DefaultAklogPath}. + +@itemx accept_passwd +A true value will cause login not to accept plaintext passwords. The +default value is @value{DefaultAcceptPasswd}. This is not yet +implemented. +@end table + +@node realms (krb5.conf), domain_realm, login, krb5.conf +@subsection [realms] + +Each tag in the [realms] section of the file is the name of a Kerberos +realm. The value of the tag is a subsection with relations that define +the properties of that particular realm. For each realm, the following +tags may be specified in the realm's subsection: + +@table @b +@itemx kdc +The name of a host running a KDC for that realm. An optional port +number (separated from the hostname by a colon) may be included. For +your computer to be able to communicate with the KDC for each realm, +this tag must be given a value in each realm subsection in the +configuration file, or there must be DNS SRV records specifying the +KDCs (see @ref{Using DNS}). + +@itemx master_kdc +Identifies the master KDC(s). Currently, this tag is used in only one +case: If an attempt to get credentials fails because of an invalid +password, the client software will attempt to contact the master KDC, +in case the user's password has just been changed, and the updated +database has not been propagated to the slave servers yet. (We don't +currently check whether the KDC from which the initial response came +is on the master KDC list. That may be fixed in the future.) + +@itemx database_module + +This relation indicates the name of the configuration section under [dbmodules] for database specific parameters used by the loadable database library. + + +@itemx admin_server +Identifies the host where the administration server is running. +Typically, this is the master Kerberos server. This tag must be given +a value in order to communicate with the kadmin server for the realm. + +@ignore +this doesn't seem to be used in the code +@itemx application defaults +Application defaults that are specific to a particular realm may be +specified within that realm's tag. Realm-specific application defaults +override the global defaults specified in the [appdefaults] section. +@end ignore + +@itemx default_domain +This tag is used for Kerberos 4 compatibility. Kerberos 4 does not +require the entire hostname of a server to be in its principal like +Kerberos 5 does. This tag provides the domain name needed to produce a +full hostname when translating V4 principal names into V5 principal +names. All servers in this realm are assumed to be in the domain given +as the value of this tag + +@itemx v4_instance_convert +This subsection allows the administrator to configure exceptions to the +default_domain mapping rule. It contains V4 instances (the tag name) +which should be translated to some specific hostname (the tag value) as +the second component in a Kerberos V5 principal name. + +@itemx v4_realm +This relation is used by the krb524 library routines when converting a +V5 principal name to a V4 principal name. It is used when the V4 realm +name and the V5 realm name are not the same, but still share the same +principal names and passwords. The tag value is the Kerberos V4 realm +name. + +@itemx auth_to_local_names +This subsection allows you to set explicit mappings from principal +names to local user names. The tag is the mapping name, and the value +is the corresponding local user name. + +@itemx auth_to_local +This tag allows you to set a general rule for mapping principal names +to local user names. It will be used if there is not an explicit +mapping for the principal name that is being translated. The possible +values are: + +@table @b + +@item DB:@i{filename} +The principal will be looked up in the database @i{filename}. Support +for this is not currently compiled in by default. + +@item RULE:@i{exp} +The local name will be formulated from @i{exp}. + +The format for @i{exp} is +@code{[@i{n}:$@i{d}..@i{string}](@i{regexp})s/@i{pattern}/@i{replacement}/g}. +The integer @i{n} indicates how many components the target principal +should have. If this matches, then a string will be formed by putting +together the components of the principal in the order indicated by each +integer @i{d}, and the arbitrary string @i{string} (i.e. if the +principal was @value{RANDOMUSER}/admin then [2:$2$1foo] would result in +the string "admin@value{RANDOMUSER}foo". If this string matches +@i{regexp}, then the @code{s//[g]} substitution command will be run over the +string. The optional g will cause the substitution to be global over +the string, instead of replacing only the first match in the string. + +@item DEFAULT +The principal name will be used as the local user name. If the +principal has more than one component or is not in the default realm, +this rule is not applicable and the conversion will fail. + +@end table + +For example: + +@smallexample +@group +[realms] + @value{PRIMARYREALM} = @{ + auth_to_local = @{ + RULE:[2:$1](@value{RANDOMUSER})s/^.*$/guest/ + RULE:[2:$1;$2](^.*;admin$)s/;admin$// + RULE:[2:$2](^.*;root)s/^.*$/root/ + DEFAULT + @} + @} +@end group +@end smallexample + +would result in any principal without @code{root} or @code{admin} as +the second component to be translated with the default rule. A +principal with a second component of @code{admin} will become its first +component. @code{root} will be used as the local name for any +principal with a second component of @code{root}. The exception to +these two rules are any principals @value{RANDOMUSER}/*, which will +always get the local name @code{guest}. + +@end table + +@node domain_realm, logging, realms (krb5.conf), krb5.conf +@subsection [domain_realm] + +The [domain_realm] section provides a translation from a domain name or +hostname to a Kerberos realm name. The tag name can be a host name, or +a domain name, where domain names are indicated by a prefix of a period +(@samp{.}). The value of the relation is the Kerberos realm name for +that particular host or domain. Host names and domain names should be +in lower case. + +If no translation entry applies, the host's realm is considered to be +the hostname's domain portion converted to upper case. For example, the +following [domain_realm] section: + +@smallexample +@group +[domain_realm] +@ifset MIT + .mit.edu = ATHENA.MIT.EDU +@end ifset + @value{PRIMARYDOMAIN} = @value{PRIMARYREALM} + crash.@value{PRIMARYDOMAIN} = TEST.@value{PRIMARYREALM} + @value{SECONDDOMAIN} = @value{SECONDREALM} +@end group +@end smallexample + +@noindent +maps crash.@value{PRIMARYDOMAIN} into the TEST.@value{PRIMARYREALM} +realm. All other hosts in the @value{PRIMARYDOMAIN} domain will map by +default to the @value{PRIMARYREALM} realm, and all hosts in the +@value{SECONDDOMAIN} domain will map by default into the +@value{SECONDREALM} realm. Note the entries for the hosts +@value{PRIMARYDOMAIN} and @value{SECONDDOMAIN}. Without these entries, +@ifset CYGNUS +these hosts would be mapped into the Kerberos realms @samp{COM} and +@end ifset +@ifclear CYGNUS +these hosts would be mapped into the Kerberos realms @samp{EDU} and +@end ifclear +@samp{ORG}, respectively. + +@node logging, capaths, domain_realm, krb5.conf +@subsection [logging] +The [logging] section indicates how a particular entity is to perform +its logging. The relations in this section assign one or more values to +the entity name. Currently, the following entities are used: + +@table @b + +@itemx kdc +These entries specify how the KDC is to perform its logging. + +@itemx admin_server +These entries specify how the administrative server +is to perform its logging. + +@itemx default +These entries specify how to perform logging in the +absence of explicit specifications otherwise. +@end table + +Values are of the following forms: + +@table @b +@itemx FILE= + +@itemx FILE: +This value causes the entity's logging messages to go to the specified +file. If the @samp{=} form is used, the file is overwritten. If the +@samp{:} form is used, the file is appended to. + +@itemx STDERR +This value causes the entity's logging messages to go to its standard +error stream. + +@itemx CONSOLE +This value causes the entity's logging messages to go to the console, if +the system supports it. + +@itemx DEVICE= +This causes the entity's logging messages to go to the specified device. + +@itemx SYSLOG[:[:]] +This causes the entity's logging messages to go to the system log. + +The @dfn{severity} argument specifies the default severity of system log +messages. This may be any of the following severities supported by the +@code{syslog(3)} call, minus the LOG_ prefix: LOG_EMERG, LOG_ALERT, +LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, and LOG_DEBUG. +For example, a value of @samp{CRIT} would specify LOG_CRIT severity. + +The facility argument specifies the facility under which the messages +are logged. This may be any of the following facilities supported by +the syslog(3) call minus the LOG_ prefix: LOG_KERN, LOG_USER, LOG_MAIL, +LOG_DAEMON, LOG_AUTH, LOG_LPR, LOG_NEWS, LOG_UUCP, LOG_CRON, and +LOG_LOCAL0 through LOG_LOCAL7. + +If no severity is specified, the default is ERR. If no facility is +specified, the default is AUTH. +@end table + +In the following example, the logging messages from the KDC will go to +the console and to the system log under the facility LOG_DAEMON with +default severity of LOG_INFO; and the logging messages from the +administrative server will be appended to the file /var/adm/kadmin.log +and sent to the device /dev/tty04. + +@smallexample +@group +[logging] + kdc = CONSOLE + kdc = SYSLOG:INFO:DAEMON + admin_server = FILE:/var/adm/kadmin.log + admin_server = DEVICE=/dev/tty04 +@end group +@end smallexample + +@node capaths, dbdefaults, logging, krb5.conf +@subsection [capaths] + +In order to perform direct (non-hierarchical) cross-realm +authentication, a database is needed to construct the authentication +paths between the realms. This section defines that database. + +A client will use this section to find the authentication path between +its realm and the realm of the server. The server will use this section +to verify the authentication path used by the client, by checking the +transited field of the received ticket. + +There is a tag for each participating realm, and each tag has subtags +for each of the realms. The value of the subtags is an intermediate +realm which may participate in the cross-realm authentication. The +subtags may be repeated if there is more then one intermediate realm. A +value of "." means that the two realms share keys directly, and no +intermediate realms should be allowed to participate. + +There are n**2 possible entries in this table, but only those entries +which will be needed on the client or the server need to be present. +The client needs a tag for its local realm, with subtags for all the +realms of servers it will need to authenticate with. A server needs a +tag for each realm of the clients it will serve. + +For example, ANL.GOV, PNL.GOV, and NERSC.GOV all wish to use the ES.NET +realm as an intermediate realm. ANL has a sub realm of TEST.ANL.GOV +which will authenticate with NERSC.GOV but not PNL.GOV. The [capaths] +section for ANL.GOV systems would look like this: + +@smallexample +@group +[capaths] + ANL.GOV = @{ + TEST.ANL.GOV = . + PNL.GOV = ES.NET + NERSC.GOV = ES.NET + ES.NET = . + @} + TEST.ANL.GOV = @{ + ANL.GOV = . + @} + PNL.GOV = @{ + ANL.GOV = ES.NET + @} + NERSC.GOV = @{ + ANL.GOV = ES.NET + @} + ES.NET = @{ + ANL.GOV = . + @} +@end group +@end smallexample + +The [capaths] section of the configuration file used on NERSC.GOV systems +would look like this: + +@smallexample +@group +[capaths] + NERSC.GOV = @{ + ANL.GOV = ES.NET + TEST.ANL.GOV = ES.NET + TEST.ANL.GOV = ANL.GOV + PNL.GOV = ES.NET + ES.NET = . + @} + ANL.GOV = @{ + NERSC.GOV = ES.NET + @} + PNL.GOV = @{ + NERSC.GOV = ES.NET + @} + ES.NET = @{ + NERSC.GOV = . + @} + TEST.ANL.GOV = @{ + NERSC.GOV = ANL.GOV + NERSC.GOV = ES.NET + @} +@end group +@end smallexample + +In the above examples, the ordering is not important, except when the +same subtag name is used more then once. The client will use this to +determine the path. (It is not important to the server, since the +transited field is not sorted.) + +This feature is not currently supported by DCE. DCE security servers +can be used with Kerberized clients and servers, but versions prior to +DCE 1.1 did not fill in the transited field, and should be used with +caution. + +@node dbdefaults, dbmodules, capaths, krb5.conf +@subsection [dbdefaults] + +The [dbdefaults] section provides default values for the database specific parameters. It can also specify the configuration section under [dbmodules] section for database specific parameters used by the database library.(@pxref{dbmodules}). + +The following tags are used in this section: + +@table @b +@itemx database_module +This relation indicates the name of the configuration section under the [dbmodules] for database specific parameters used by the loadable database library. + +@itemx ldap_kerberos_container_dn +This LDAP specific tag indicates the DN of the container object where the realm objects will be located. This value is used if the container object is not mentioned in the configuration section under [dbmodules]. + +@itemx ldap_kdc_dn +This LDAP specific tag indicates the default bind DN for the KDC server. The KDC server does a login to the directory as this object. This object should have the rights to read the Kerberos data in the LDAP database. This value is used if the bind DN for the KDC is not mentioned in the configuration section under [dbmodules]. + +@itemx ldap_kadmind_dn +This LDAP specific tag indicates the default bind DN for the Administration server. The administration server does a login to the directory as this object. This object should have the rights to read and write the Kerberos data in the LDAP database. This value is used if the bind DN for the Administration server is not mentioned in the configuration section under [dbmodules]. + +@itemx ldap_service_password_file + +This LDAP specific tag indicates the file containing the stashed passwords for the objects used by the Kerberos servers to bind to the LDAP server. This file must be kept secure. This value is used if no service password file is mentioned in the configuration section under [dbmodules]. + +@itemx ldap_server + +This LDAP specific tag indicates the list of LDAP servers that the Kerberos servers can connect to. The list of LDAP servers is whitespace-separated. The LDAP server is specified by a LDAP URI. This value is used if no LDAP servers are mentioned in the configuration section under [dbmodules]. It is recommended to use the ldapi:// or ldaps:// interface and not to use ldap:// interface. + +@itemx ldap_conns_per_server +This LDAP specific tag indicates the number of connections to be maintained per LDAP server. This value is used if the number of connections per LDAP server are not mentioned in the configuration section under [dbmodules]. The default value is 5. +@end table + +@node dbmodules, pkinit client options, dbdefaults, krb5.conf +@subsection [dbmodules] + +Contains database specific parameters used by the database library. Each tag in the [dbmodules] section of the file names a configuration section for database specific parameters that can be referred to by a realm. The value of the tag is a subsection where the relations in that subsection define the database specific parameters. + +For each section, the following tags may be specified in the subsection: + +@table @b +@itemx db_library +This tag indicates the name of the loadable database library. The value should be @samp{db2} for DB2 database and @samp{kldap} for LDAP database. + +@itemx ldap_kerberos_container_dn +This LDAP specific tag indicates the DN of the container object where the realm objects will be located. + +@itemx ldap_kdc_dn +This LDAP specific tag indicates the default bind DN for the KDC server. The KDC server does a login to the directory as this object. This object should have the rights to read the Kerberos data in the LDAP database. + +@itemx ldap_kadmind_dn +This LDAP specific tag indicates the default bind DN for the Administration server. The administration server does a login to the directory as this object. This object should have the rights to read and write the Kerberos data in the LDAP database. + +@itemx ldap_service_password_file +This LDAP specific tag indicates the file containing the stashed passwords for the objects used by the Kerberos servers to bind to the LDAP server. This file must be kept secure. + +@itemx ldap_server +This LDAP specific tag indicates the list of LDAP servers that the Kerberos servers can connect to. The list of LDAP servers is whitespace-separated. The LDAP server is specified by a LDAP URI. It is recommended to use ldapi:// or ldaps:// interface to connect to the LDAP server. + +@itemx ldap_conns_per_server +This LDAP specific tags indicates the number of connections to be maintained per LDAP server. + +@end table + +@node pkinit client options, Sample krb5.conf File, dbmodules, krb5.conf +@subsection pkinit options + +@menu +* pkinit identity syntax:: +* pkinit krb5.conf options:: +@end menu + +The following are @b{pkinit-specific} options. +Note that these values may be specified in @code{[libdefaults]} +as global defaults, +or within a realm-specific subsection of @code{[libdefaults]}, +or may be specified as realm-specific values in the +@code{[realms]} section. +Also note that a realm-specific value over-rides, does not add to, +a generic @code{[libdefaults]} specification. +The search order is: +@enumerate +@item realm-specific subsection of @code{[libdefaults]} +@smallexample +@group +[libdefaults] + EXAMPLE.COM = @{ + pkinit_anchors = FILE:/usr/local/example.com.crt + @} +@end group +@end smallexample + +@item realm-specific value in the @code{[realms]} section, +@smallexample +@group +[realms] + OTHERREALM.ORG = @{ + pkinit_anchors = FILE:/usr/local/otherrealm.org.crt + @} +@end group +@end smallexample + +@item generic value in the @code{[libdefaults]} section. +@smallexample +@group +[libdefaults] + pkinit_anchors = DIR:/usr/local/generic_trusted_cas/ + +@end group +@end smallexample +@end enumerate + +@node pkinit identity syntax, pkinit krb5.conf options, pkinit client options, pkinit client options +@subsubsection Specifying pkinit identity information + +The syntax for specifying Public Key identity, trust, and revocation +information for pkinit is as follows: +@table @b + +@item FILE:@i{file-name}[,@i{key-file-name}] +This option has context-specific behavior. +@table @b +@item pkinit_identity +@itemx pkinit_identities +@i{file-name} specifies the name of a PEM-format file +containing the user's certificate. If @i{key-file-name} is +not specified, the user's private key is expected to be +in @i{file-name} as well. Otherwise, @i{key-file-name} +is the name of the file containing the private key. +@item pkinit_anchors +@itemx pkinit_pool +@i{file-name} is assumed to be the name of an OpenSSL-style +ca-bundle file. +@end table + +@item DIR:@i{directory-name} +This option has context-specific behavior. +@table @b +@item pkinit_identity +@itemx pkinit_identities +@i{directory-name} specifies a directory with files named +@code{*.crt} and @code{*.key}, where the first part of the +file name is the same for matching pairs of certificate and +private key files. When a file with a name ending with @code{.crt} +is found, a matching file ending with @code{.key} is assumed +to contain the private key. If no such file is found, then +the certificate in the @code{.crt} is not used. +@item pkinit_anchors +@itemx pkinit_pool +@i{directory-name} is assumed to be an OpenSSL-style hashed CA directory +where each CA cert is stored in a file named @i{hash-of-ca-cert}.@i{#}. +This infrastructure is encouraged, but all files in the directory +will be examined and if they contain certificates (in PEM format), +they will be used. +@item pkinit_revoke +@i{directory-name} is assumed to be an OpenSSL-style hashed CA directory +where each revocation list is stored in a file named @i{hash-of-ca-cert}.@b{r}@i{#}. +This infrastructure is encouraged, but all files in the directory +will be examined and if they contain a revocation list (in PEM format), +they will be used. +@end table + +@item PKCS12:@i{pkcs12-file-name} +@i{pkcs12-file-name} is the name of a @code{PKCS #12} format file, containing +the user's certificate and private key. + +@item PKCS11:[@b{module_name=}]@i{module-name}[@b{:slotid=}@i{slot-id}][@b{:token=}@i{token-label}][@b{:certid=}@i{cert-id}][@b{:certlabel=}@i{cert-label}] +All keyword/values are optional. +@i{module-name} specifies the location of a library implementing +@code{PKCS #11}. If a value is encountered with not keyword, it +is assumed to be the @i{module-name}. If no @i{module-name} is +specified, the default is @code{opensc-pkcs11.so}. +@b{slotid=} and/or @b{token=} may be specified to force the use of a +particular smard card reader or token if there is more than one +available. +@b{certid=} and/or @b{certlabel=} may be specified to force the selection +of a particular certificate on the device. See the @code{pkinit_cert_match} +configuration option for more ways to select a particular certificate to +use for pkinit. + +@item ENV:@i{environment-variable-name} +@i{environment-variable-name} specifies the name of an environment +variable which has been set to a value conforming to one of the +previous values. For example, @code{ENV:X509_PROXY}, where environment +variable @code{X509_PROXY} has been set to @code{FILE:/tmp/my_proxy.pem}. +@end table + +@node pkinit krb5.conf options, , pkinit identity syntax, pkinit client options +@subsubsection pkinit krb5.conf options +@table @b + +@item pkinit_identities +Specifies the location(s) to be used to find the user's X.509 identity +information. This option may be specified multiple times. +Each value is attempted in order until identity information is found +and authentication is attempted. Note that these values are @b{not} +used if the user specifies @b{X509_user_identity} on the command line. + +@item pkinit_anchors +Specifies the location of trusted anchor (root) certificates which +the client trusts to sign KDC certificates. This option may be +specified multiple times. These values from the config file are +@b{not} used if the user specifies @b{X509_anchors} on the command line. + +@item pkinit_pool +Specifies the location of intermediate certificates which may be +used by the client to complete the trust chain between a KDC +certificate and a trusted anchor. This option may be specified +multiple times. + +@item pkinit_revoke +Specifies the location of Certificate Revocation List (CRL) information +to be used by the client when verifying the validity of the KDC +certificate presented. This option may be specified multiple times. + +@item pkinit_require_crl_checking +The default certificate verification process will always check +the available revocation information to see if a certificate has +been revoked. If a match is found for the certificate in a CRL, +verification fails. If the certificate being verified is not listed +in a CRL, or there is no CRL present for its issuing CA, +and @code{pkinit_require_crl_checking} is @code{false}, +then verification succeeds. + +However, if @code{pkinit_require_crl_checking} is @code{true} and +there is no CRL information available for the issuing CA, +then verification fails. + +@code{pkinit_require_crl_checking} should be set to @code{true} +if the policy is such that up-to-date CRLs @b{must} be present for +every CA. + +@item pkinit_dh_min_bits +Specifies the size of the Diffie-Hellman key the client will +attempt to use. The acceptable values are currently 1024, 2048, +and 4096. The default is 2048. + +@item pkinit_win2k +This flag specifies whether the target realm is assumed +to support only the @i{old}, pre-RFC version of the protocol. +The default is false. + +@item pkinit_win2k_require_binding +If this flag is set to true, it expects that the target +KDC is patched to return a reply with a checksum rather than a +nonce. The default is false. + +@item pkinit_eku_checking +This option specifies what Extended Key Usage value the KDC certificate +presented to the client must contain. +(@b{Note} that if the KDC certificate has the pkinit +SubjectAlternativeName encoded as the Kerberos TGS name, EKU checking +is not necessary since the issuing CA has certified this as a KDC +certificate.) +The values recognized in the @code{krb5.conf} file are: +@table @b +@item kpKDC +This is the default value and specifies that the KDC must have the +id-pkinit-KPKdc EKU as defined in RFC4556. +@item kpServerAuth +If @code{kpServerAuth} is specified, a KDC certificate with the +id-kp-serverAuth EKU as used by Microsoft will be accepted. +@item none +If @code{none} is specified, then the KDC certificate will not be +checked to verify it has an acceptable EKU. The use of this option +is @b{not recommended}. +@end table + +@item pkinit_kdc_hostname +The presense of this option indicates that the client is willing to +accept a KDC certificate with a dNSName SAN (Subject Alternative Name) +rather than requiring the id-pkinit-san as defined in RFC4556. This +option may be specified multiple times. Its value should contain +the acceptable hostname for the KDC (as contained in its certificate). + +@item pkinit_cert_match +Specifies matching rules that the client certificate must match before +it is used to attempt pkinit authentication. If a user has multiple +certificates available (on a smart card, or via other media), there +must be exactly one certificate chosen before attempting pkinit +authentication. This option may be specified multiple times. All the +available certificates are checked against each rule in order until +there is a match of exactly one certificate. + +The Subject and Issuer comparison strings are the RFC2253 string +representations from the certificate Subject DN and Issuer DN values. + +The syntax of the matching rules is: +@example +[@i{relation-operator}]@i{component-rule} @code{...} +@end example +where +@table @i +@item relation-operator +can be either @code{&&}, meaning all component rules must match, +or @code{||}, meaning only one component rule must match. +The default is @code{&&} if not specified. + +@item component-rule +can be one of the following. Note that there is no punctuation +or whitespace between component rules. +@table @b +@item @code{}@i{regular-expression} +@item @code{}@i{regular-expression} +@item @code{}@i{regular-expression} +@item @code{}@i{extended-key-usage-list} +where @i{extended-key-usage-list} is a comma-separated list of +required Extended Key Usage values. All values in the list must +be present in the certificate. +@smallexample +@group +@code{pkinit} +@code{msScLogin} +@code{clientAuth} +@code{emailProtection} +@end group +@end smallexample +@item @code{}@i{key-usage-list} +where @i{key-usage-list} is a comma-separated list of required +Key Usage values. All values in the list must be present in +the certificate. +@smallexample +@group +@code{digitalSignature} +@code{keyEncipherment} +@end group +@end smallexample +@end table +@end table +Examples: +@example +pkinit_cert_match = ||.*DoE.*.*@@EXAMPLE.COM +pkinit_cert_match = &&msScLogin,clientAuth.*DoE.* +pkinit_cert_match = msScLogin,clientAuthdigitalSignature +@end example +@end table + +@node Sample krb5.conf File, , pkinit client options, krb5.conf +@subsection Sample krb5.conf File + +Here is an example of a generic @code{krb5.conf} file: + +@smallexample +@group +[libdefaults] + default_realm = @value{PRIMARYREALM} + default_tkt_enctypes = des3-hmac-sha1 des-cbc-crc + default_tgs_enctypes = des3-hmac-sha1 des-cbc-crc + dns_lookup_kdc = true + dns_lookup_realm = false + +[realms] + @value{PRIMARYREALM} = @{ + kdc = @value{KDCSERVER}.@value{PRIMARYDOMAIN} + kdc = @value{KDCSLAVE1}.@value{PRIMARYDOMAIN} + kdc = @value{KDCSLAVE2}.@value{PRIMARYDOMAIN}:750 + admin_server = @value{KDCSERVER}.@value{PRIMARYDOMAIN} + master_kdc = @value{KDCSERVER}.@value{PRIMARYDOMAIN} + default_domain = @value{PRIMARYDOMAIN} + @} + @value{SECONDREALM} = @{ + kdc = @value{KDCSERVER}.@value{SECONDDOMAIN} + kdc = @value{KDCSLAVE1}.@value{SECONDDOMAIN} + admin_server = @value{KDCSERVER}.@value{SECONDDOMAIN} + @} + OPENLDAP.MIT.EDU = @{ + kdc = @value{KDCSERVER}.@value{PRIMARYDOMAIN} + admin_server = @value{KDCSERVER}.@value{PRIMARYDOMAIN} + database_module = openldap_ldapconf + @} + +[domain_realm] +@ifset MIT + .mit.edu = ATHENA.MIT.EDU +@end ifset + @value{PRIMARYDOMAIN} = @value{PRIMARYREALM} + +[capaths] + @value{PRIMARYREALM} = @{ + @value{SECONDREALM} = . + @} + @value{SECONDREALM} = @{ + @value{PRIMARYREALM} = . + @} + +[logging] + kdc = SYSLOG:INFO + admin_server = FILE=/var/kadm5.log +[dbdefaults] + ldap_kerberos_container_dn = cn=krbcontainer,o=mit +[dbmodules] + openldap_ldapconf = @{ + db_library = kldap + ldap_kerberos_container_dn = cn=krbcontainer,o=mit + ldap_kdc_dn = "cn=krbadmin,o=mit" + # this object needs to have read rights on + # the realm container, principal container and realm sub-trees + ldap_kadmind_dn = "cn=krbadmin,o=mit" + # this object needs to have read and write rights on + # the realm container, principal container and realm sub-trees + ldap_service_password_file = /etc/kerberos/service.keyfile + ldap_servers = ldaps://kerberos.mit.edu + ldap_conns_per_server = 5 +@} + + + +@end group +@end smallexample + +@iftex +@vfill +@end iftex + +@node kdc.conf, , krb5.conf, Configuration Files +@section kdc.conf + +@include kdcconf.texinfo + +@menu +* kdcdefaults:: +* realms (kdc.conf):: +* pkinit kdc options:: +* Sample kdc.conf File:: +@end menu + +@node kdcdefaults, realms (kdc.conf), kdc.conf, kdc.conf +@subsection [kdcdefaults] + +The following relation is defined in the [kdcdefaults] section: + +@table @b +@itemx kdc_ports +This relation lists the ports on which the Kerberos server should +listen for UDP requests by default. This list is a comma separated +list of integers. +If this relation is not specified, the compiled-in default is +@value{DefaultKdcPorts}, the first being the assigned Kerberos port +and the second which was used by Kerberos V4. + +@itemx kdc_tcp_ports +This relation lists the ports on which the Kerberos server should +listen for TCP connections by default. This list is a comma separated +list of integers. +If this relation is not specified, the compiled-in default is not to +listen for TCP connections at all. + +If you wish to change this (which we do not recommend, because the +current implementation has little protection against denial-of-service +attacks), the standard port number assigned for Kerberos TCP traffic +is port 88. + +@itemx v4_mode +This string specifies how the KDC should respond to Kerberos 4 +packets. The possible values are none, disable, full, and nopreauth. +The default value is @value{DefaultV4Mode}. +@comment these values found in krb5/src/kdc/kerberos_v4.c in v4mode_table +@end table + +@node realms (kdc.conf), pkinit kdc options, kdcdefaults, kdc.conf +@subsection [realms] + +Each tag in the [realms] section of the file names a Kerberos realm. +The value of the tag is a subsection where the relations in that +subsection define KDC parameters for that particular realm. + +For each realm, the following tags may be specified in the [realms] +subsection: + +@table @b +@itemx acl_file +(String.) Location of the access control list (acl) file that kadmin +uses to determine which principals are allowed which permissions on the +database. The default is @code{@value{DefaultAclFile}}. + +@itemx admin_keytab +(String.) Location of the keytab file that the legacy administration +daemons @code{kadmind4} and @code{v5passwdd} use to authenticate to +the database. The default is @code{@value{DefaultAdminKeytab}}. + +@itemx database_name +(String.) Location of the Kerberos database for this realm. The +default is @* @code{@value{DefaultDatabaseName}}. + +@itemx default_principal_expiration +(Absolute time string.) Specifies the default expiration date of +principals created in this realm. The default value for this tag is +@value{DefaultDefaultPrincipalExpiration}. + +@itemx default_principal_flags +(Flag string.) Specifies the default attributes of principals created +in this realm. The format for this string is a comma-separated list of +flags, with '+' before each flag that should be enabled and '-' before +each flag that should be disabled. The default is +@value{DefaultDefaultPrincipalFlags}. + +There are a number of possible flags: + +@table @b +@itemx postdateable +Enabling this flag allows the principal to obtain postdateable tickets. + +@itemx forwardable +Enabling this flag allows the principal to obtain forwardable tickets. + +@itemx tgt-based +Enabling this flag allows a principal to obtain tickets based on a +ticket-granting-ticket, rather than repeating the authentication +process that was used to obtain the TGT. + +@itemx renewable +Enabling this flag allows the principal to obtain renewable tickets. + +@itemx proxiable +Enabling this flag allows the principal to obtain proxy tickets. + +@itemx dup-skey +Enabling this flag allows the principal to obtain a session key for +another user, permitting user-to-user authentication for this principal. + +@itemx allow-tickets +Enabling this flag means that the KDC will issue tickets for this +principal. Disabling this flag essentially deactivates the principal +within this realm. + +@itemx preauth +If this flag is enabled on a client principal, then that principal is +required to preauthenticate to the KDC before receiving any tickets. +On a service principal, enabling this flag means that service tickets +for this principal will only be issued to clients with a TGT that has +the preauthenticated ticket set. + +@itemx hwauth +If this flag is enabled, then the principal is required to +preauthenticate using a hardware device before receiving any tickets. + +@itemx pwchange +Enabling this flag forces a password change for this principal. + +@itemx service +Enabling this flag allows the the KDC to issue service tickets for this +principal. + +@itemx pwservice +If this flag is enabled, it marks this principal as a password change +service. This should only be used in special cases, for example, if a +user's password has expired, then the user has to get tickets for that +principal without going through the normal password authentication in +order to be able to change the password. + +@end table + +@itemx dict_file +(String.) Location of the dictionary file containing strings that are +not allowed as passwords. If none is specified or if there is no +policy assigned to the principal, no dictionary checks of passwords +will be performed. + +@itemx kadmind_port +(Port number.) Specifies the port on which the kadmind daemon is to +listen for this realm. The assigned port for kadmind is +@value{DefaultKadmindPort}. + +@itemx kpasswd_port +(Port number.) Specifies the port on which the kpasswd daemon is to +listen for this realm. The default is @value{DefaultKpasswdPort}. + +@itemx key_stash_file +(String.) Specifies the location where the master key has been stored +(via @code{kdb5_util stash}). The default is +@code{@value{DefaultKeyStashFileStub}@i{REALM}}, where @i{REALM} is the +Kerberos realm. + +@itemx kdc_ports +(String.) Specifies the list of ports that the KDC is to listen to +for UDP requests for this realm. By default, the value of kdc_ports +as specified in the [kdcdefaults] section is used. + +@itemx kdc_tcp_ports +(String.) Specifies the list of ports that the KDC is to listen to +for TCP requests for this realm. By default, the value of +kdc_tcp_ports as specified in the [kdcdefaults] section is used. + +@itemx master_key_name +(String.) Specifies the name of the principal associated with the +master key. The default is @value{DefaultMasterKeyName}. + +@itemx master_key_type +(Key type string.) Specifies the master key's key type. The default +value for this is @value{DefaultMasterKeyType}. For a list of all +possible values, see @ref{Supported Encryption Types}. + +@itemx max_life +(Delta time string.) Specifes the maximum time period for which a +ticket may be valid in this realm. The default value is +@value{DefaultMaxLife}. + +@itemx max_renewable_life +(Delta time string.) Specifies the maximum time period during which a +valid ticket may be renewed in this realm. The default value is +@value{DefaultMaxRenewableLife}. + +@itemx supported_enctypes +List of key:salt strings. Specifies the default key/salt combinations of +principals for this realm. Any principals created through @code{kadmin} +will have keys of these types. The default value for this tag is +@value{DefaultSupportedEnctypes}. For lists of possible values, see +@ref{Supported Encryption Types} and @ref{Salts}. + +@itemx reject_bad_transit +A boolean value (@code{true}, @code{false}). If set to @code{true}, the +KDC will check the list of transited realms for cross-realm tickets +against the transit path computed from the realm names and the +@code{capaths} section of its @code{krb5.conf} file; if the path in the +ticket to be issued contains any realms not in the computed path, the +ticket will not be issued, and an error will be returned to the client +instead. If this value is set to @code{false}, such tickets will be +issued anyways, and it will be left up to the application server to +validate the realm transit path. + +If the @code{disable-transited-check} flag is set in the incoming +request, this check is not performed at all. Having the +@code{reject_bad_transit} option will cause such ticket requests to be +rejected always. + +This transit path checking and config file option currently apply only +to TGS requests. + +Earlier versions of the MIT release (before 1.2.3) had bugs in the +application server support such that the server-side checks may not be +performed correctly. We recommend turning this option on, unless you +know that all application servers in this realm have been updated to +fixed versions of the software, and for whatever reason, you don't want +the KDC to do the validation. + +This is a per-realm option so that multiple-realm KDCs may control it +separately for each realm, in case (for example) one realm has had the +software on its application servers updated but another has not. + +This option defaults to @code{true}. + +@end table + +@node pkinit kdc options, Sample kdc.conf File, realms (kdc.conf), kdc.conf +@subsection pkinit options + +@menu +* pkinit kdc.conf options:: +@end menu + +The following are @b{pkinit-specific} options. +Note that these values may be specified in @code{[kdcdefaults]} +as global defaults, +or within a realm-specific subsection of @code{[realms]}. +Also note that a realm-specific value over-rides, does not add to, +a generic @code{[kdcdefaults]} specification. +The search order is: +@enumerate +@item realm-specific subsection of @code{[realms]} +@smallexample +@group +[realms] + EXAMPLE.COM = @{ + pkinit_anchors = FILE:/usr/local/example.com.crt + @} +@end group +@end smallexample + +@item generic value in the @code{[kdcdefaults]} section. +@smallexample +@group +[kdcdefaults] + pkinit_anchors = DIR:/usr/local/generic_trusted_cas/ +@end group +@end smallexample +@end enumerate + +@node pkinit kdc.conf options, , pkinit kdc options, pkinit kdc options +@subsubsection pkinit kdc.conf options + +For information about the syntax of some of these options, +see @xref{pkinit identity syntax}. + +@table @b +@item pkinit_identity +Specifies the location of the KDC's X.509 identity information. +This option is @b{required} if pkinit is to be supported by the +KDC. + +@item pkinit_anchors +Specifies the location of trusted anchor (root) certificates +which the KDC trusts to sign client certificates. +This option is @b{required} if pkinit is to be supported by the +KDC. +This option may be specified multiple times. + +@item pkinit_pool +Specifies the location of intermediate certificates which may be +used by the KDC to complete the trust chain between a client's +certificate and a trusted anchor. +This option may be specified multiple times. + +@item pkinit_revoke +Specifies the location of Certificate Revocation List (CRL) +information to be used by the KDC when verifying the validity +of client certificates. +This option may be specified multiple times. + +@item pkinit_require_crl_checking +The default certificate verification process will always check +the available revocation information to see if a certificate has +been revoked. If a match is found for the certificate in a CRL, +verification fails. If the certificate being verified is not listed +in a CRL, or there is no CRL present for its issuing CA, +and @code{pkinit_require_crl_checking} is @code{false}, +then verification succeeds. + +However, if @code{pkinit_require_crl_checking} is @code{true} and +there is no CRL information available for the issuing CA, +then verification fails. + +@code{pkinit_require_crl_checking} should be set to @code{true} +if the policy is such that up-to-date CRLs @b{must} be present for +every CA. + +@item pkinit_dh_min_bits +Specifies the minimum number of bits the KDC is willing to accept +for a client's Diffie-Hellman key. The default is 2048. + +@item pkinit_allow_upn +Specifies that the KDC is willing to accept client certificates with +the Microsoft UserPrincipalName (UPN) Subject Alternative Name +(SAN). This means the KDC accepts the binding of the UPN in the +certificate to the Kerberos principal name. + +The default is false. + +Without this option, the KDC will only +accept certificates with the id-pkinit-san as defined in RFC4556. +There is currently no option to disable SAN checking in the KDC. + +@item pkinit_eku_checking +This option specifies what Extended Key Usage (EKU) values the +KDC is willing to accept in client certificates. +The values recognized in the @code{kdc.conf} file are: +@table @b +@item kpClientAuth +This is the default value and specifies that client certificates must +have the id-pkinit-KPClientAuth EKU as defined in RFC4556. +@item scLogin +If @code{scLogin} is specified, client certificates with the +Microsoft Smart Card Login EKU (id-ms-kp-sc-logon) will be accepted. +@item none +If @code{none} is specified, then client certificates will not be +checked to verify they have an acceptable EKU. +The use of this option is @b{not recommended}. +@end table +@end table + +@node Sample kdc.conf File, , pkinit kdc options, kdc.conf +@subsection Sample kdc.conf File + +Here's an example of a @code{kdc.conf} file: + +@smallexample +@group +[kdcdefaults] + kdc_ports = 88 + +[realms] + @value{PRIMARYREALM} = @{ + kadmind_port = 749 + max_life = 12h 0m 0s + max_renewable_life = 7d 0h 0m 0s + master_key_type = des3-hmac-sha1 + supported_enctypes = des3-hmac-sha1:normal des-cbc-crc:normal des-cbc-crc:v4 + @} + +[logging] + kdc = FILE:@value{ROOTDIR}/var/krb5kdc/kdc.log + admin_server = FILE:@value{ROOTDIR}/var/krb5kdc/kadmin.log + +@end group +@end smallexample + +@node Using DNS, Administrating the Kerberos Database, Configuration Files, Top +@chapter Using DNS + +@menu +* Mapping Hostnames onto Kerberos Realms:: +* Hostnames for KDCs:: +@end menu + +@node Mapping Hostnames onto Kerberos Realms, Hostnames for KDCs, Using DNS, Using DNS +@section Mapping Hostnames onto Kerberos Realms + +@include dnstxt.texinfo + +@node Hostnames for KDCs, , Mapping Hostnames onto Kerberos Realms, Using DNS +@section Hostnames for KDCs + +@include dnssrv.texinfo + +@node Administrating the Kerberos Database, Configuring Kerberos with OpenLDAP back-end, Using DNS, Top +@chapter Administrating the Kerberos Database + +Your Kerberos database contains all of your realm's Kerberos principals, +their passwords, and other administrative information about each +principal. For the most part, you will use the @code{kdb5_util} program +to manipulate the Kerberos database as a whole, and the @code{kadmin} +program to make changes to the entries in the database. (One notable +exception is that users will use the @code{kpasswd} program to change +their own passwords.) The @code{kadmin} program has its own +command-line interface, to which you type the database administrating +commands. + +@code{Kdb5_util} provides a means to create, delete, load, or dump a +Kerberos database. It also includes a command to stash a copy of the +master database key in a file on a KDC, so that the KDC can authenticate +itself to the @code{kadmind} and @code{krb5kdc} daemons at boot time. + +@code{Kadmin} provides for the maintenance of Kerberos principals, KADM5 +policies, and service key tables (keytabs). It exists as both a +Kerberos client, @code{kadmin}, using Kerberos authentication and an +RPC, to operate securely from anywhere on the network, and as a local +client, @code{kadmin.local}, intended to run directly on the KDC without +Kerberos authentication. @code{kadmin.local} need not run on the kdc if +the database is LDAP. Other than the fact that the remote client uses +Kerberos to authenticate the person using it, the functionalities of the two +versions are identical. The local version is necessary to enable you to set up +enough of the database to be able to use the remote version. +It replaces the now obsolete @code{kdb5_edit} (except for +database dump and load, which are provided by @code{kdb5_util}). + +The remote version authenticates to the KADM5 server using the service +principal @code{kadmin/admin}. If the credentials cache contains a +ticket for the @code{kadmin/admin} principal, and the @samp{-c ccache} +option is specified, that ticket is used to authenticate to KADM5. +Otherwise, the @samp{-p} and @samp{-k} options are used to specify the +client Kerberos principal name used to authenticate. Once kadmin has +determined the principal name, it requests a @code{kadmin/admin} +Kerberos service ticket from the KDC, and uses that service ticket to +authenticate to KADM5. + +@menu +* Kadmin Options:: +* Date Format:: +* Principals:: +* Policies:: +* Global Operations on the Kerberos Database:: +* Global Operations on the Kerberos LDAP Database:: +* Cross-realm Authentication:: +* Changing the krbtgt Key:: +@end menu + +@node Kadmin Options, Date Format, Administrating the Kerberos Database, Administrating the Kerberos Database +@section Kadmin Options + +You can invoke @code{kadmin} or @code{kadmin.local} with any of the +following options: + +@table @b +@item @b{-r} @i{REALM} +Use @i{REALM} as the default Kerberos realm for the database. + +@item @b{-p} @i{principal} +Use the Kerberos principal @i{principal} to authenticate to Kerberos. +If this option is not given, @code{kadmin} will append @code{admin} to +either the primary principal name, the environment variable USER, or to +the username obtained from @code{getpwuid}, in order of preference. + +@item @b{-q} @i{query} +Pass @i{query} directly to @code{kadmin}. This is useful for writing +scripts that pass specific queries to @code{kadmin}. + +@noindent +You can invoke @code{kadmin} with any of the following options: + +@item @b{-k} [@b{-t} @i{keytab}] +Use the keytab @i{keytab} to decrypt the KDC response instead of +prompting for a password on the TTY. In this case, the principal will +be @samp{host/@i{hostname}}. If @b{-t} is not used to specify a keytab, +then the default keytab will be used. + +@item @b{-c} @i{credentials cache} +Use @i{credentials_cache} as the credentials cache. The credentials +cache should contain a service ticket for the @code{kadmin/admin} +service, which can be acquired with the @code{kinit} program. If this +option is not specified, @code{kadmin} requests a new service ticket +from the KDC, and stores it in its own temporary ccache. + +@item @b{-w} @i{password} +Use @i{password} as the password instead of prompting for one on the +TTY. Note: placing the password for a Kerberos principal with +administration access into a shell script can be dangerous if +unauthorized users gain read access to the script. + +@item @b{-x} @i{db_args} +Specifies the database specific arguments. + +@item @b{-x} @i{host=} +Specifies the LDAP server to connect to by a LDAP URI. It is recommend to use +ldapi:// or ldaps:// interface to connect to the LDAP server. + +@item @b{-x} @i{binddn=} +Specifies the Distinguished Name (DN) of the object used by the administration server to bind to the LDAP server. This object should have the read and write rights on the realm container, principal container and realm subtree. + +@item @b{-x} @i{bindpwd=} +Specifies the password for the above mentioned binddn. It is recommended not to +use this option. Instead, the password can be stashed using the +stashsrvpw command of kdb5_ldap_util. + +Note: This database specific argument is applicable only to kadmin.local +and the KADM5 server. + +@item @b{-s} @i{admin_server[:port]} +Specifies the admin server that kadmin should contact. + +@noindent +You can invoke @code{kadmin.local} with an of the follwing options: + +@item @b{-d_ @i{dbname}} +Specifies the name of the Kerberos database. + +@item @b{-e} @i{"enctypes ..."} +Sets the list of cryptosystem and salt types to be used for any new +keys created. See @ref{Supported Encryption Types} and @ref{Salts} for +available types. + +@item @b{-m} +Do not authenticate using a keytab. This option will cause kadmin to +prompt for the master database password. + +@end table + +@node Date Format, Principals, Kadmin Options, Administrating the Kerberos Database +@section Date Format + +Many of the @code{kadmin} commands take a duration or time as an +argument. The date can appear in a wide variety of formats, such as: + +@smallexample +@group +"15 minutes" +"7 days" +"1 month" +"2 hours" +"400000 seconds" +"next year" +"this Monday" +"next Monday" +yesterday +tomorrow +now +"second Monday" +fortnight +"3/31/1992 10:00:07 PST" +"January 23, 2007 10:05pm" +"22:00 GMT" +@end group +@end smallexample + +Note that if the date specification contains spaces, you must enclose it +in double quotes. Note also that you cannot use a number without a +unit. (I.e., ``"60 seconds"'' is correct, but ``60'' is incorrect.) +All keywords are case-insensitive. The following is a list of all of +the allowable keywords. + +@table @b +@item Months +january, jan, february, feb, march, mar, april, apr, may, june, jun, +july, jul, august, aug, september, sep, sept, october, oct, november, +nov, december, dec + +@item Days +sunday, sun, monday, mon, tuesday, tues, tue, wednesday, wednes, wed, +thursday, thurs, thur, thu, friday, fri, saturday, sat + +@item Units +year, month, fortnight, week, day, hour, minute, min, second, sec + +@item Relative +tomorrow, yesterday, today, now, last, this, next, first, second, +third, fourth, fifth, sixth, seventh, eighth, ninth, tenth, eleventh, +twelfth, ago + +@item Time Zones +@code{kadmin} recognizes abbreviations for most of the world's time +zones. A complete listing appears in @ref{kadmin Time Zones}. + +@item 12-hour Time Delimiters +am, pm +@end table + +@node Principals, Policies, Date Format, Administrating the Kerberos Database +@section Principals + +Each entry in the Kerberos database contains a Kerberos principal +(@pxref{Definitions}) and the attributes and policies associated with +that principal. + +@menu +* Retrieving Information About a Principal:: +* Privileges:: +* Adding or Modifying Principals:: +* Deleting Principals:: +* Changing Passwords:: +@end menu + +@node Retrieving Information About a Principal, Privileges, Principals, Principals +@subsection Retrieving Information About a Principal + +@menu +* Attributes:: +* Retrieving a List of Principals:: +@end menu + +@node Attributes, Retrieving a List of Principals, Retrieving Information About a Principal, Retrieving Information About a Principal +@subsubsection Attributes + +To retrieve a listing of the attributes and/or policies associated with +a principal, use the @code{kadmin} @code{get_principal} command, which +requires the ``inquire'' administrative privilege. The syntax is: + +@smallexample +@b{get_principal} @i{principal} +@end smallexample + +@noindent +The @code{get_principal} command has the alias @code{getprinc}. + +For example, suppose you wanted to view the attributes of the +principal @* @code{@value{RANDOMUSER1}/root@@@value{PRIMARYREALM}}. + You would type: + +@smallexample +@group +@b{shell%} kadmin +@b{kadmin:} getprinc @value{RANDOMUSER1}/root +@b{Principal: @value{RANDOMUSER1}/root@@@value{PRIMARYREALM} +Expiration date: [never] +Last password change: Mon Jan 31 02:06:40 EDT 2002 +Password Expiration date: [none] +Maximum ticket life: 0 days 10:00:00 +Maximum renewable life: 7 days 00:00:00 +Last modified: Wed Jul 24 14:46:25 EDT 2002 (@value{ADMINUSER}/admin@@@value{PRIMARYREALM}) +Last successful authentication: Mon Jul 29 18:20:17 EDT 2002 +Last failed authentication: Mon Jul 29 18:18:54 EDT 2002 +Failed password attempts: 3 +Number of keys: 2 +Key: vno 2, Triple DES cbc mode with HMAC/sha1, no salt +Key: vno 2, DES cbc mode with CRC-32, no salt +Attributes: DISALLOW_FORWARDABLE, DISALLOW_PROXIABLE +Policy: [none] +kadmin:} +@end group +@end smallexample + +The @code{get_principal} command has a @code{-terse} option, which lists +the fields as a quoted, tab-separated string. For example: + +@smallexample +@group +@b{kadmin:} getprinc -terse @value{RANDOMUSER1}/root +@b{@value{RANDOMUSER1}/root@@@value{PRIMARYREALM} 0 1027458564 +0 36000 (@value{ADMINUSER}/admin@@@value{PRIMARYREALM} +1027536385 18 2 0 [none] 604800 1027980137 +1027980054 3 2 1 2 16 0 1 +2 1 0 +kadmin:} +@end group +@end smallexample + +@node Retrieving a List of Principals, , Attributes, Retrieving Information About a Principal +@subsubsection Retrieving a List of Principals + +To generate a listing of principals, use the @code{kadmin} +@code{list_principals} command, which requires the ``list'' privilege. +The syntax is: + +@smallexample +@b{list_principals} [@i{expression}] +@end smallexample + +@noindent where @i{expression} is a shell-style glob expression that +can contain the characters @samp{*}, @samp{?}, @samp{[}, and @samp{]}. +All policy names matching the expression are displayed. The +@code{list_principals} command has the aliases @code{listprincs}, +@code{get_principals}, and @code{getprincs}. For example: + +@smallexample +@group +@b{kadmin:} listprincs test* +@b{test3@@@value{PRIMARYREALM} +test2@@@value{PRIMARYREALM} +test1@@@value{PRIMARYREALM} +testuser@@@value{PRIMARYREALM} +kadmin:} +@end group +@end smallexample + +@noindent +If no expression is provided, all principals are printed. + +@node Privileges, Adding or Modifying Principals, Retrieving Information About a Principal, Principals +@subsection Privileges + +Administrative privileges for the Kerberos database are stored in the +file @code{kadm5.acl}. + +@include kadm5acl.texinfo + +@node Adding or Modifying Principals, Deleting Principals, Privileges, Principals +@subsection Adding or Modifying Principals + +To add a principal to the database, use the kadmin @code{add_principal} +command, which requires the ``add'' administrative privilege. This +function creates the new principal, prompting twice for a password, and, +if neither the -policy nor -clearpolicy options are specified and the +policy ``default'' exists, assigns it that policy. The syntax is: + +@smallexample +@b{kadmin:} add_principal [@i{options}] @i{principal} +@end smallexample + +To modify attributes of a principal, use the kadmin +@code{modify_principal} command, which requires the ``modify'' +administrative privilege. The syntax is: + +@smallexample +@b{kadmin:} modify_principal [@i{options}] @i{principal} +@end smallexample + +@noindent +@code{add_principal} has the aliases @code{addprinc} and +@code{ank}@footnote{@code{ank} was the short form of the equivalent +command using the deprecated @code{kadmin5} database administrative tool. +It has been kept}. @code{modify_principal} has the alias @code{modprinc}. + +The @code{add_principal} and @code{modify_principal} commands take the +following switches: + +@table @b +@item @b{-x} @i{db_princ_args} +Denotes the database specific options. +@noindent +The options for LDAP database are: +@table @b +@item @b{-x} @i{dn=} +Specifies the LDAP object that will contain the Kerberos principal being created. + +@item @b{-x} @i{linkdn=} +Specifies the LDAP object to which the newly created Kerberos principal object will point to. + +@item @b{-x} @i{containerdn=} +Specifies the container object under which the Kerberos principal is to be created. + +@item @b{-x} @i{tktpolicy=} +Associates a ticket policy to the Kerberos principal. Specifying an empty string +value clears the ticket policy associated with the principal. +@noindent +Note: +@noindent +* dn and containerdn options are not valid while modifying the principal. +@noindent +* containerdn and linkdn options cannot be specified with dn option. +@noindent +* If dn or containerdn options are not specified while adding the principal, the principals are created + under the prinicipal container configured in the realm or the realm container. +* dn and containerdn should be within the subtrees or principal container configured in the realm. +@end table + +@item -expire @i{date} +Sets the expiration date of the principal to @i{date}. + +@item -pwexpire @i{date} +Sets the expiration date of the password to @i{date}. + +@item -maxlife @i{maxlife} +Sets the maximum ticket life of the principal to @i{maxlife}. + +@item -maxrenewlife @i{maxrenewlife} +Sets the maximum renewable life of tickets for the principal to +@i{maxrenewlife}. + +@item -kvno @i{number} +Explicity sets the key version number to @i{number}. @value{COMPANY} +does not recommend doing this unless there is a specific reason. + +@item -policy @i{policy} +Sets the policy used by this principal. (@xref{Policies}.) With +@code{modify_principal}, the current policy assigned to the principal is +set or changed. With @code{add_principal}, if this option is not +supplied, the -clearpolicy is not specified, and the policy ``default'' +exists, that policy is assigned. If a principal is created with no +policy, @code{kadmin} will print a warning message. + +@item -clearpolicy +For @code{modify_principal}, removes the current policy from a +principal. For @code{add_principal}, suppresses the automatic +assignment of the policy ``default''. + +@item @{-|+@}allow_postdated +The ``-allow_postdated'' option prohibits this principal from obtaining +postdated tickets. ``+allow_postdated'' clears this flag. In effect, +``-allow_postdated'' sets the KRB5_KDB_DISALLOW_POSTDATED flag on the +principal in the database. + +@item @{-|+@}allow_forwardable +The ``-allow_forwardable'' option prohibits this principal from +obtaining forwardable tickets. ``+allow_forwardable'' clears this flag. +In effect, ``-allow_forwardable'' sets the KRB5_KDB_DISALLOW_FORWARDABLE +flag on the principal in the database. + +@item @{-|+@}allow_renewable +The ``-allow_renewable'' option prohibits this principal from obtaining +renewable tickets. ``+allow_renewable'' clears this flag. In effect, +``-allow_renewable'' sets the KRB5_KDB_DISALLOW_RENEWABLE flag on the +principal in the database. + +@item @{-|+@}allow_proxiable +The ``-allow_proxiable'' option prohibits this principal from obtaining +proxiable tickets. ``+allow_proxiable'' clears this flag. In effect, +``-allow_proxiable'' sets the @* KRB5_KDB_DISALLOW_PROXIABLE flag. on +the principal in the database. + +@item @{-|+@}allow_dup_skey +The ``-allow_dup_skey'' option disables user-to-user authentication for +this principal by prohibiting this principal from obtaining a session +key for another user. ``+allow_dup_skey'' clears this flag. In effect, +``-allow_dup_skey'' sets the @* KRB5_KDB_DISALLOW_DUP_SKEY flag on the +principal in the database. + +@item @{-|+@}requires_preauth +The ``+requires_preauth'' option requires this principal to +preauthenticate before being allowed to kinit. -requires_preauth clears +this flag. In effect, +requires_preauth sets the +KRB5_KDB_REQUIRES_PRE_AUTH flag on the principal in the database. + +@item @{-|+@}requires_hwauth +The ``+requires_hwauth'' flag requires the principal to preauthenticate +using a hardware device before being allowed to kinit. +``-requires_hwauth'' clears this flag. In effect, ``+requires_hwauth'' +sets the KRB5_KDB_REQUIRES_HW_AUTH flag on the principal in the +database. + +@item @{-|+@}allow_svr +The ``-allow_svr'' flag prohibits the issuance of service tickets for +this principal. ``+allow_svr'' clears this flag. In effect, +``-allow_svr'' sets the @* KRB5_KDB_DISALLOW_SVR flag on the principal +in the database. + +@item @{-|+@}allow_tgs_req +The ``-allow_tgs_req'' option specifies that a Ticket-Granting Service +(TGS) request for a service ticket for this principal is not permitted. +You will probably never need to use this option. ``+allow_tgs_req'' +clears this flag. The default is ``+allow_tgs_req''. In effect, +``-allow_tgs_req'' sets the KRB5_KDB_DISALLOW_TGT_BASED flag on the +principal in the database. + +@item @{-|+@}allow_tix +The ``-allow_tix'' option forbids the issuance of any tickets for this +principal. ``+allow_tix'' clears this flag. The default is +``+allow_tix''. In effect, ``-allow_tix'' sets the @* +KRB5_KDB_DISALLOW_ALL_TIX flag on the principal in the database. + +@item @{-|+@}needchange +The ``+needchange'' option sets a flag in attributes field to force a +password change; ``-needchange'' clears it. The default is +``-needchange''. In effect, ``+needchange'' sets the +KRB5_KDB_REQUIRES_PWCHANGE flag on the principal in the database. + +@item @{-|+@}password_changing_service +The ``+password_changing_service'' option sets a flag in the attributes +field marking this principal as a password change service. (Again, you +will probably never need to use this option.) +``-password_changing_service'' clears the flag. The default is +``-password_changing_service''. In effect, the +``+password_changing_service'' option sets the KRB5_KDB_PWCHANGE_SERVICE +flag on the principal in the database. + +@item -randkey +Sets the key for the principal to a random value (@code{add_principal} +only). @value{COMPANY} recommends using this option for host keys. + +@item -pw @i{password} +Sets the key of the principal to the specified string and does not +prompt for a password (@code{add_principal} only). @value{COMPANY} does +not recommend using this option. + +@item -e @i{enc:salt...} +Uses the specified list of enctype-salttype pairs for setting the key +of the principal. The quotes are necessary if there are multiple +enctype-salttype pairs. This will not function against kadmin daemons +earlier than krb5-1.2. See @ref{Supported Encryption Types} and +@ref{Salts} for available types. +@end table + +If you want to just use the default values, all you need to do is: + +@smallexample +@group +@b{kadmin:} addprinc @value{RANDOMUSER1} +@b{WARNING: no policy specified for "@value{RANDOMUSER1}@@@value{PRIMARYREALM}"; +defaulting to no policy.} +@iftex +@b{Enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<=Type it again.} +@end ifinfo +@ifhtml +@b{Enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<=Type it again.} +@end ifhtml +@b{Principal "@value{RANDOMUSER1}@@@value{PRIMARYREALM}" created. +kadmin:} +@end group +@end smallexample + +If you want to create a principal which is contained by a LDAP object, all you need to do is: + +@smallexample +@group +@b{kadmin:} addprinc -x dn=cn=@value{RANDOMUSER1},o=mit @value{RANDOMUSER1} +@b{WARNING: no policy specified for "@value{RANDOMUSER1}@@@value{PRIMARYREALM}"; +defaulting to no policy.} +@iftex +@b{Enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<=Type it again.} +@end ifinfo +@ifhtml +@b{Enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<=Type it again.} +@end ifhtml +@b{Principal "@value{RANDOMUSER1}@@@value{PRIMARYREALM}" created. +kadmin:} +@end group +@end smallexample + +If you want to create a principal under a specific LDAP container and link to an existing LDAP object, all you need to do is: + +@smallexample +@group +@b{kadmin:} addprinc -x containerdn=o=mit -x linkdn=cn=@value{RANDOMUSER2},o=mit @value{RANDOMUSER2} +@b{WARNING: no policy specified for "@value{RANDOMUSER2}@@@value{PRIMARYREALM}"; +defaulting to no policy.} +@iftex +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<=Type it again.} +@end ifinfo +@ifhtml +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<=Type it again.} +@end ifhtml +@b{Principal "@value{RANDOMUSER2}@@@value{PRIMARYREALM}" created. +kadmin:} +@end group +@end smallexample + +If you want to associate a ticket policy to a principal, all you need to do is: + +@smallexample +@group +@b{kadmin:} modprinc -x tktpolicy=userpolicy @value{RANDOMUSER2} +@b{Principal "@value{RANDOMUSER2}@@@value{PRIMARYREALM}" modified. +kadmin:} +@end group +@end smallexample + +If, on the other hand, you want to set up an account that expires on +January 1, 2000, that uses a policy called ``stduser'', with a temporary +password (which you want the user to change immediately), you would type +the following. (Note: each line beginning with @result{} is a +continuation of the previous line.) + +@smallexample +@group + +@b{kadmin:} addprinc @value{RANDOMUSER2} -expire "1/1/2000 12:01am EST" -policy stduser +@result{} +needchange +@iftex +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type the password.} +@b{Re-enter password for principal +@value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal +@value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type it again.} +@end ifinfo +@ifhtml +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type the password.} +@b{Re-enter password for principal +@value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type it again.} +@end ifhtml +@b{Principal "@value{RANDOMUSER2}@@@value{PRIMARYREALM}" created. +kadmin:} + +@end group +@end smallexample + +If you will need cross-realm authentication, you need to add principals +for the other realm's TGT to each realm. For example, if you need to +do cross-realm authentication between the realms @value{PRIMARYREALM} +and @value{SECONDREALM}, you would need to add the principals @* +@samp{krbtgt/@value{SECONDREALM}@@@value{PRIMARYREALM}} and +@samp{krbtgt/@value{PRIMARYREALM}@@@value{SECONDREALM}} to both +databases. You need to be sure the passwords and the key version +numbers (kvno) are the same in both databases. This may require +explicitly setting the kvno with the @samp{-kvno} option. See +@ref{Cross-realm Authentication} for more details. + +@node Deleting Principals, Changing Passwords, Adding or Modifying Principals, Principals +@subsection Deleting Principals + +To delete a principal, use the kadmin @code{delete_principal} command, +which requires the ``delete'' administrative privilege. The syntax is: + +@smallexample +@b{delete_principal} [@b{-force}] @i{principal} +@end smallexample + +@noindent @code{delete_principal} has the alias @code{delprinc}. The +@code{-force} option causes @code{delete_principal} not to ask if you're +sure. For example: + +@smallexample +@group +@b{kadmin:} delprinc @value{RANDOMUSER1} +@b{Are you sure you want to delete the principal +"@value{RANDOMUSER1}@@@value{PRIMARYREALM}"? (yes/no):} yes +@b{Principal "@value{RANDOMUSER1}@@@value{PRIMARYREALM}" deleted. +Make sure that you have removed this principal from +all ACLs before reusing. +kadmin:} +@end group +@end smallexample + +@node Changing Passwords, , Deleting Principals, Principals +@subsection Changing Passwords + +To change a principal's password use the kadmin @code{change_password} +command, which requires the ``modify'' administrative privilege (unless +the principal is changing his/her own password). The syntax is: + +@smallexample +@b{change_password} [@i{options}] @i{principal} +@end smallexample + +@noindent The @code{change_password} option has the alias @code{cpw}. +@code{change_password} takes the following options: + +@table @b +@item -randkey +Sets the key of the principal to a random value. + +@item @b{-pw} @i{password} +Sets the password to the string @i{password}. @value{COMPANY} does not +recommend using this option. + +@item @b{-e} @i{"enc:salt..."} +Uses the specified list of enctype-salttype pairs for setting the key +of the principal. The quotes are necessary if there are multiple +enctype-salttype pairs. This will not function against kadmin daemons +earlier than krb5-1.2. See @ref{Supported Encryption Types} and +@ref{Salts} for possible values. + +@item @b{-keepold} +Keeps the previous kvno's keys around. There is no easy way to delete +the old keys, and this flag is usually not necessary except perhaps for +TGS keys. Don't use this flag unless you know what you're doing. This +option is not supported for the LDAP database + + + +@end table + +For example: + +@smallexample +@group +@b{kadmin:} cpw @value{RANDOMUSER2} +@iftex +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type the new password.} +@b{Re-enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type the new password.} +@b{Re-enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type it again.} +@end ifinfo +@ifhtml +@b{Enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type the new password.} +@b{Re-enter password for principal @value{RANDOMUSER2}@@@value{PRIMARYREALM}:} @i{<= Type it again.} +@end ifhtml +@b{Password for @value{RANDOMUSER2}@@@value{PRIMARYREALM} changed. +kadmin:} +@end group +@end smallexample + +Note that @code{change_password} will not let you change the password to +one that is in the principal's password history. + +@node Policies, Global Operations on the Kerberos Database, Principals, Administrating the Kerberos Database +@section Policies + +A policy is a set of rules governing passwords. Policies can dictate +minimum and maximum password lifetimes, minimum number of characters and +character classes a password must contain, and the number of old +passwords kept in the database. + +@menu +* Retrieving Policies:: +* Retrieving the List of Policies:: +* Adding or Modifying Policies:: +* Deleting Policies:: +@end menu + +@node Retrieving Policies, Retrieving the List of Policies, Policies, Policies +@subsection Retrieving Policies + +To retrieve a policy, use the kadmin @code{get_policy} command, which +requires the ``inquire'' administrative privilege. The syntax is: + +@smallexample +@b{get_policy} [@b{-terse}] @i{policy} +@end smallexample + +The @code{get_policy} command has the alias @code{getpol}. For example: + +@smallexample +@group +@b{kadmin:} get_policy admin +@b{Policy: admin +Maximum password life: 180 days 00:00:00 +Minimum password life: 00:00:00 +Minimum password length: 6 +Minimum number of password character classes: 2 +Number of old keys kept: 5 +Reference count: 17 +kadmin:} +@end group +@end smallexample + +@noindent The @dfn{reference count} is the number of principals using +that policy. + +The @code{get_policy} command has a @code{-terse} option, which lists +each field as a quoted, tab-separated string. For example: + +@smallexample +@group +@b{kadmin:} get_policy -terse admin +@b{admin 15552000 0 6 2 5 17 +kadmin:} +@end group +@end smallexample + +@node Retrieving the List of Policies, Adding or Modifying Policies, Retrieving Policies, Policies +@subsection Retrieving the List of Policies + +You can retrieve the list of policies with the kadmin +@code{list_policies} command, which requires the ``list'' privilege. The +syntax is: + +@smallexample +@b{list_policies} [@i{expression}] +@end smallexample + +@noindent where @i{expression} is a shell-style glob expression that can +contain the characters *, ?, and []. All policy names matching the +expression are displayed. The @code{list_policies} command has the aliases +@code{listpols}, @code{get_policies}, and @code{getpols}. For example: + +@smallexample +@group +@b{kadmin:} listpols +@b{test-pol +dict-only +once-a-min +test-pol-nopw} + +@b{kadmin:} listpols t* +@b{test-pol +test-pol-nopw +kadmin:} +@end group +@end smallexample + + +@node Adding or Modifying Policies, Deleting Policies, Retrieving the List of Policies, Policies +@subsection Adding or Modifying Policies + +To add a new policy, use the kadmin @code{add_policy} command, which +requires the ``add'' administrative privilege. The syntax is: + +@smallexample +@b{add_policy} [@i{options}] @i{policy_name} +@end smallexample + +To modify attributes of a principal, use the kadmin @code{modify_policy} +command, which requires the ``modify'' administrative privilege. The +syntax is: + +@smallexample +@b{modify_policy} [@i{options}] @i{policy_name} +@end smallexample + +@noindent @code{add_policy} has the alias @code{addpol}. +@code{modify_poilcy} has the alias @code{modpol}. + +The @code{add_policy} and @code{modify_policy} commands take the +following switches: + +@table @b +@item -maxlife @i{time} +Sets the maximum lifetime of a password to @i{time}. + +@item -minlife @i{time} +Sets the minimum lifetime of a password to @i{time}. + +@item -minlength @i{length} +Sets the minimum length of a password to @i{length} characters. + +@item -minclasses @i{number} +Requires at least @i{number} of character classes in a password. + +@item -history @i{number} +Sets the number of past keys kept for a principal to @i{number}. This option is not supported for LDAP database. +@end table +@c **** An example here would be nice. **** + +@noindent +Note: The policies are created under realm container in the LDAP database. + +@node Deleting Policies, , Adding or Modifying Policies, Policies +@subsection Deleting Policies + +To delete a policy, use the @code{kadmin} @code{delete_policy} command, +which requires the ``delete'' administrative privilege. The syntax is: + +@smallexample +@b{delete_policy [-force]} @i{policy_name} +@end smallexample + +@noindent The @code{delete_policy} command has the alias @code{delpol}. +It prompts for confirmation before deletion. +For example: + +@smallexample +@group +@b{kadmin:} delete_policy guests +@b{Are you sure you want to delete the policy "guests"? +(yes/no):} yes +@b{kadmin:} +@end group +@end smallexample + +Note that you must cancel the policy from all principals before deleting +it. The @code{delete_policy} command will fail if it is in use by any +principals. + +@node Global Operations on the Kerberos Database, Global Operations on the Kerberos LDAP Database, Policies, Administrating the Kerberos Database +@section Global Operations on the Kerberos Database + +@menu +* Dumping a Kerberos Database to a File:: +* Restoring a Kerberos Database from a Dump File:: +* Creating a Stash File:: +* Creating and Destroying a Kerberos Database:: +@end menu + +The @code{kdb5_util} command is the primary tool for administrating the +Kerberos database. The syntax is: + +@smallexample +@b{kdb5_util} @i{command} [@i{kdb5_util_options}] [@i{command_options}] +@end smallexample + +The @code{kdb5_util} command takes the following options, which override +the defaults specified in the configuration files: + +@table @b +@itemx -r @i{realm} +specifies the the Kerberos realm of the database. + +@itemx -d @i{database_name} +specifies the name under which the principal database is stored. + +@itemx -k @i{master_key_type} +specifies the key type of the master key in the database. + +@itemx -M @i{master_key_name} +specifies the principal name of the master key in the database. + +@itemx -m +indicates that the master database password should be read from the TTY +rather than fetched from a file on disk. + +@itemx -sf @i{stash_file} +specifies the stash file of the master database password + +@itemx -P @i{password} +specifies the master database password. @value{COMPANY} does not +recommend using this option. + +@end table + +@node Dumping a Kerberos Database to a File, Restoring a Kerberos Database from a Dump File, Global Operations on the Kerberos Database, Global Operations on the Kerberos Database +@subsection Dumping a Kerberos Database to a File + +To dump a Kerberos database into a file, use the @code{kdb5_util} +@code{dump} command on one of the KDCs. The syntax is: + +@smallexample +@b{kdb5_util dump} [@b{-old}] [@b{-b6}] [@b{-b7}] [@b{-ov}] +[@b{-verbose}] [-mkey_convert] [-new_mkey_file] [@i{filename} +[@i{principals...}]] +@end smallexample + +The @code{kdb5_util dump} command takes the following options: + +@table @b +@itemx -old +causes the dump to be in the Kerberos 5 Beta 5 and earlier dump format +(``kdb5_edit load_dump version 2.0''). +@itemx -b6 +causes the dump to be in the Kerberos 5 Beta 6 format (``kdb5_edit +load_dump version 3.0''). +@itemx -b7 +causes the dump to be in the Kerberos 5 Beta 7 format (``kdbt_edit +load_dump version 4''). +@itemx -ov +causes the dump to be in ovsec_adm_export format. Currently, the only +way to preserve per-principal policy information is to use this in +conjunction with a normal dump. +@itemx -verbose +causes the name of each principal and policy to be printed as it is +dumped. +@itemx -mkey_convert +prompts for a new master password, and then dumps the database with +all keys reencrypted in this new master key +@itemx -new_mkey_file +reads a new key from the default keytab and then dumps the database +with all keys reencrypted in this new master key +@end table + +For example: + +@smallexample +@group +@b{shell%} kdb5_util dump dumpfile +@b{shell%} +@end group +@end smallexample + +@smallexample +@group +@b{shell%} kbd5_util dump -verbose dumpfile +@b{kadmin/admin@@@value{PRIMARYREALM} +krbtgt/@value{PRIMARYREALM}@@@value{PRIMARYREALM} +kadmin/history@@@value{PRIMARYREALM} +K/M@@@value{PRIMARYREALM} +kadmin/changepw@@@value{PRIMARYREALM} +shell%} +@end group +@end smallexample + +@noindent +If you specify which principals to dump, you must use the full +principal, as in the following example. (The line beginning with +@result{} is a continuation of the previous line.): + +@smallexample +@group +@b{shell%} kdb5_util dump -verbose dumpfile K/M@@@value{PRIMARYREALM} +@result{} kadmin/admin@@@value{PRIMARYREALM} +@b{kadmin/admin@@@value{PRIMARYREALM} +K/M@@@value{PRIMARYREALM} +shell%} +@end group +@end smallexample + +@noindent +Otherwise, the principals will not match those in the database and will +not be dumped: + +@smallexample +@group +@b{shell%} kdb5_util dump -verbose dumpfile K/M kadmin/admin +@b{shell%} +@end group +@end smallexample + +@noindent +If you do not specify a dump file, @code{kdb5_util} will dump the +database to the standard output. + +There is currently a bug where the default dump format omits the +per-principal policy information. In order to dump all the data +contained in the Kerberos database, you must perform a normal dump (with +no option flags) and an additional dump using the ``-ov'' flag to a +different file. + +@node Restoring a Kerberos Database from a Dump File, Creating a Stash File, Dumping a Kerberos Database to a File, Global Operations on the Kerberos Database +@subsection Restoring a Kerberos Database from a Dump File + +To restore a Kerberos database dump from a file, use the +@code{kdb5_util} @code{load} command on one of the KDCs. The syntax +is: + +@smallexample +@b{kdb5_util load} [@b{-old}] [@b{-b6}] [@b{-b7}] [@b{-ov}] [@b{-verbose}] +[@b{-update}] [@b{-hash}] @i{dumpfilename} @i{dbname} [@i{admin_dbname}] +@end smallexample + +The @code{kdb5_util load} command takes the following options: + +@table @b +@itemx -old +requires the dump to be in the Kerberos 5 Beta 5 and earlier dump format +(``kdb5_edit load_dump version 2.0''). +@itemx -b6 +requires the dump to be in the Kerberos 5 Beta 6 format (``kdb5_edit +load_dump version 3.0''). +@itemx -b7 +requires the dump to be in the Kerberos 5 Beta 7 format (``kdb5_edit +load_dump version 4''). +@itemx -ov +requires the dump to be in ovsec_adm_export format. +@itemx -verbose +causes the name of each principal and policy to be printed as it is +loaded. +@itemx -update +causes records from the dump file to be updated in or added to the +existing database. This is useful in conjunction with an +ovsec_adm_export format dump if you want to preserve per-principal +policy information, since the current default format does not contain +this data. +@itemx -hash +causes the database to be stored as a hash rather than a binary tree. +@end table + +For example: + +@smallexample +@group +@b{shell%} kdb5_util load dumpfile principal +@b{shell%} +@end group +@end smallexample + +@smallexample +@group +@b{shell%} kdb5_util load -update dumpfile principal +@b{shell%} +@end group +@end smallexample + +@noindent +If the database file exists, and the @b{-update} flag was not given, +@code{kdb5_util} will overwrite the existing database. + +@node Creating a Stash File, Creating and Destroying a Kerberos Database, Restoring a Kerberos Database from a Dump File, Global Operations on the Kerberos Database +@subsection Creating a Stash File + +A stash file allows a KDC to authenticate itself to the database +utilities, such as @code{kadmin}, @code{kadmind}, @code{krb5kdc}, and +@code{kdb5_util}. + +To create a stash file, use the @code{kdb5_util} @code{stash} command. +The syntax is: + +@smallexample +@b{kdb5_util stash} [@b{-f} @i{keyfile}] +@end smallexample + +For example: + +@smallexample +@group +@b{shell%} kdb5_util stash +@b{kdb5_util: Cannot find/read stored master key while reading master key +kdb5_util: Warning: proceeding without master key} +@iftex +@b{Enter KDC database master key:} @i{@doubleleftarrow{} Type the KDC database master password.} +@end iftex +@ifinfo +@b{Enter KDC database master key:} @i{<= Type the KDC database master password.} +@end ifinfo +@ifhtml +@b{Enter KDC database master key:} @i{<= Type the KDC database master password.} +@end ifhtml +@b{shell%} +@end group +@end smallexample + +@noindent +If you do not specify a stash file, @code{kdb5_util} will stash the key +in the file specified in your @code{kdc.conf} file. + +@node Creating and Destroying a Kerberos Database, , Creating a Stash File, Global Operations on the Kerberos Database +@subsection Creating and Destroying a Kerberos Database + +If you need to create a new Kerberos database, use the @code{kdb5_util} +@code{create} command. The syntax is: + +@smallexample +@b{kdb5_util create} [@b{-s}] +@end smallexample + +If you specify the @samp{-s} option, @code{kdb5_util} will stash a copy +of the master key in a stash file. (@xref{Creating a Stash File}.) For +example: + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/kdb5_util -r @value{PRIMARYREALM} create -s +@b{kdb5_util: No such file or directory while setting active database to +@result{} '@value{ROOTDIR}/var/krb5kdc/principal' +Initializing database '@value{ROOTDIR}/var/krb5kdc/principal' for +@result{} realm '@value{PRIMARYREALM}', +master key name 'K/M@@@value{PRIMARYREALM}' +You will be prompted for the database Master Password. +It is important that you NOT FORGET this password.} +@iftex +@b{Enter KDC database master key:} @i{@doubleleftarrow{} Type the master password.} +@b{Re-enter KDC database master key to verify:} @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter KDC database master key:} @i{<= Type the master password.} +@b{Re-enter KDC database master key to verify:} @i{<= Type it again.} +@end ifinfo +@ifhtml +@b{Enter KDC database master key:} @i{<= Type the master password.} +@b{Re-enter KDC database master key to verify:} @i{<= Type it again.} +@end ifhtml +@b{shell%} +@end group +@end smallexample + +If you need to destroy the current Kerberos database, use the +@code{kdb5_util} @code{destroy} command. The syntax is: + +@smallexample +@b{kdb5_util destroy} [@b{-f}] +@end smallexample + +The @code{destroy} command destroys the database, first overwriting the +disk sectors and then unlinking the files. If you specify the +@samp{-f} option, @code{kdb5_util} will not prompt you for a +confirmation before destroying the database. + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/kdb5_util -r @value{PRIMARYREALM} destroy +@iftex +@b{kdb5_util: Deleting KDC database stored in @value{DefaultDatabaseName}, are you sure +(type yes to confirm)?} @i{@doubleleftarrow{}yes} +@end iftex +@ifinfo +@b{kdb5_util: Deleting KDC database stored in @value{DefaultDatabaseName}, are you sure +(type yes to confirm)?} @i{<== yes} +@end ifinfo +@ifhtml +@b{kdb5_util: Deleting KDC database stored in @value{DefaultDatabaseName}, are you sure +(type yes to confirm)?} @i{<== yes} +@end ifhtml +@b{OK, deleting database '@value{DefaultDatabaseName}'...} + +@b{shell%} +@end group +@end smallexample + +@node Global Operations on the Kerberos LDAP Database, Cross-realm Authentication, Global Operations on the Kerberos Database, Administrating the Kerberos Database +@section Global Operations on the Kerberos LDAP Database + + +The @code{kdb5_ldap_util} is the primary tool for administrating the Kerberos LDAP database. It allows an administrator to manage realms, Kerberos services ( KDC and Admin Server) and ticket policies. +@noindent +The syntax is: +@smallexample +@b{kdb5_ldap_util} [@b{-D user_dn} [@i{-w passwd]}] [@b{-H} @i{ldap_uri}] command @i{[command_options]} +@end smallexample + +@table @b +@itemx -D @i{user_dn} +Specifies the Distinguished Name (DN) of the user who has sufficient rights to perform the operation on the LDAP server. +@itemx @b{-w} @i{passwd} +Specifies the password of user_dn. This option is not recommended. +@itemx @b{-H} @i{ldap_uri} +Specifies the URI of the LDAP server. It is recommended to use ldapi:// or ldaps:// to connect to the LDAP server. +@end table +@menu +* Creating a Kerberos Realm:: +* Modifying a Kerberos Realm:: +* Retrieving Information about a Kerberos Realm:: +* Destroying a Kerberos Realm:: +* Listing available Kerberos Realms:: +* Stashing Service Object's Password:: +* Creating and Modifying a Ticket Policy:: +* Retrieving Information About a Ticket Policy:: +* Destroying a Ticket Policy:: +* Listing available Ticket Policies:: +* Creating a Service Object (eDirectory):: +* Modifying a Service Object (eDirectory):: +* Retrieving Service Object Information (eDirectory):: +* Destroying a Service Object (eDirectory):: +* Listing Available Service Objects (eDirectory):: +* Passwords for Service Objects (eDirectory):: +@end menu + +@node Creating a Kerberos Realm, Modifying a Kerberos Realm, Global Operations on the Kerberos LDAP Database, Global Operations on the Kerberos LDAP Database +@subsection Creating a Kerberos Realm + +If you need to create a new realm, use the command as follows: +@smallexample + +@b{create} [@b{-r} @i{realm}] [@b{-subtrees} @i{subtree_dn_list}] [@b{-sscope} @i{search_scope}] [@b{-containerref} @i{container_reference_dn}] +[@b{-k} @i{ mkeytype}] [@b{-m}|@b{-P} @i{password}][@b{-sf} @i{stashlename}] [@b{-s}] [@b{-maxtktlife} @i{max_ticket_life}] +[@b{-maxrenewlife} @i{ max_renewable_ticket_life}] [@b{ticket_flags}] + +@end smallexample + +@noindent +Options to create realm in directory are as follows: + +@table @b + +@itemx @b{-r} @i{realm} +Specifies the Kerberos realm of the database; by default the realm returned by @samp{krb5_default_local_realm} (3) is used. + +@itemx @b{-subtrees} @i{subtree_dn_list} +Specifies the list of subtrees containing principals of a realm. The list contains the DN of the subtree objects separated by colon(:). + +@itemx @b{-sscope} @i{search_scope} +Specifies the scope for searching the principals under the subtree. The possible values are 1 or one (one level), 2 or sub (subtree). + +@itemx @b{-containerref} @i{container_reference_dn} +Specfies the DN of the container object in which the principals of a realm will be created. If the container reference is not configured for a realm, the principals will be created in the realm container. + +@itemx @b{-k} @i{mkeytype} +Specifies the key type of the master key in the database; the default +is that given in @file{kdc.conf}. + +@itemx @b{-m} @i{} +Specifies that the master database password should be read from the TTY rather than fetched from a file on disk. + +@itemx @b{-p} @i{password} +Specifies the master database password. This option is not recommended. + +@itemx @b{-sf} @i{stashfilename} +Specifies the stash file of the master database password. + +@itemx @b{-s} @i{} +Specifies that the stash file is to be created. + +@itemx @b{-maxtktlife} @i{max_ticket_life} +Specifies maximum ticket life for principals in this realm. This value is used, if it is not set on the principal. + +@itemx @b{-maxrenewlife} @i{max_renewable_ticket_life} +Specifies maximum renewable life of tickets for principals in this realm. This value is used, if it is not set on the principal. + +@itemx @b{ticket_flags} @i{} +Specifies the ticket flags. If this option is not specified, by default, none of the flags are set. This means all the ticket options will be allowed and no restriction will be set. This value is used, if it is not set on the principal. +@noindent + +The various flags are: +@table @b + +@itemx @{-|+@}allow_postdated +@code{-allow_postdated} prohibits principals from obtaining postdated tickets. (Sets the @samp{KRB5_KDB_DISALLOW_POSTDATED} flag.).@code{+allow_postdated} clears this flag. + +@itemx @{-|+@}allow_forwardable +@code{-allow_forwardable} prohibits principals from obtaining forwardable tickets. (Sets the +@samp{KRB5_KDB_DISALLOW_FORWARDABLE} flag.) @code{+allow_forwardable} clears this flag. + +@itemx @{-|+@}allow_renewable +@code{-allow_renewable} prohibits principals from obtaining renewable tickets. (Sets the @samp{KRB5_KDB_DISALLOW_RENEWABLE} flag.) @code{+allow_renewable} clears this flag. + +@itemx @{-|+@}allow_proxiable +@code{-allow_proxiable} prohibits principals from obtaining proxiable tickets. (Sets the @samp{KRB5_KDB_DISALLOW_PROXABLE} flag.) @code{+allow_proxiable} clears this flag. + +@itemx @{-|+@}allow_dup_skey +@code{-allow_dup_skey} disables user-to-user authentication for +principals by prohibiting principals from obtaining a sessions key for +another user. (Sets the @samp{KRB5_KDB_DISALLOW_DUP_SKEY} flag.) +@code{+allow_dup_skey} clears this flag. + +@itemx @{-|+@}requires_preauth +@code{+requires_preauth} requires principals to preauthenticate before being allowed to kinit. (Sets the @samp{KRB5_KDB_REQURES_PRE_AUTH} flag.) @code{-requires_preauth} clears this flag. + +@itemx @{-|+@}requires_hwauth +@code{+requires_hwauth} requires principals to preauthenticate using a +hardware device before being allowed to kinit. (Sets the +@samp{KRB5_KDB_REQURES_HW_AUTH} flag.) @code{-requires_hwauth} clears +this flag. + +@itemx @{-|+@}allow_svr +@code{-allow_svr} prohibits the issuance of service tickets for principals. (Sets the @samp{KRB5_KDB_DISALLOW_SVR} flag.) @code{+allow_svr} clears this flag. + +@itemx @{-|+@}allow_tgs_req +@code{-allow_tgs_req} specifies that a @dfn{Ticket-Granting Service +(TGS)} request for a service ticket for principals is not +permitted. This option is useless for most +things.@code{+allow_tgs_req} clears this flag. The default is +@code{+allow_tgs_req}. In effect, @code{-allow_tgs_req} sets the +@samp{KRB5_KDB_DISALLOW_TGT_BASED} flag on principals in the +database. + +@itemx @{-|+@}allow_tix +@code{-allow_tix} forbids the issuance of any tickets for +principals. @code{+allow_tix} clears this flag. The default is +@code{+allow_tix}. In effect, @code{-allow_tix} sets the +@samp{KRB5_KDB_DISALLOW_ALL_TIX} flag on principals in the database. + +@itemx @{-|+@}needchange +@code{+needchange} sets a flag in attributes field to force a password change; +@code{-needchange} clears it. The default is @code{-needchange}. In effect, +@code{+needchange} sets the @samp{KRB5_KDB_REQURES_PWCHANGE} flag on +principals in the database. + +@itemx @{-|+@}password_changing_service +@code{+password_changing_service} sets a flag in the attributes field +marking principal as a password change service principal (useless for +most things). @code{-password_changing_service} clears the flag. This +flag intentionally has a long name. The default is +@code{-password_changing_service}. In effect, +@code{+password_changing_service} sets the +@samp{KRB5_KDB_PWCHANGE_SERVICE} flag on principals in the database. + +@end table + +@end table + +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu create -sscope +-subtree ou=users,o=org -r ATHENA.MIT.EDU +@b{Password for "cn=admin,o=org":} +@b{Initializing database for realm 'ATHENA.MIT.EDU'} +@b{You will be prompted for the database Master Password.} +@b{It is important that you NOT FORGET this password.} +@b{Enter KDC database master key:} +@b{Re-enter KDC database master key to verify:} +shell% +@end group +@end smallexample +@menu +* eDirectory Options (Creating a Kerberos Realm):: +@end menu +@node eDirectory Options (Creating a Kerberos Realm), , Creating a Kerberos Realm, Creating a Kerberos Realm + +@subsubsection eDirectory Options + +@table @b +@itemx @b{-kdcdn} @i{kdc_servce_list} +Specifies the list of KDC service objects serving the realm. The list contains the DNs of the KDC service objects separated by colon(:). + +@itemx @b{-admindn} @i{admin_service_list} +Specifies the list of Administration service objects serving the realm. The list contains the DNs of the Administration service objects separated by colon(:). +@end table + +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu create -sscope +-subtree ou=users,o=org -kdcdn cn=krbkdc,o=org -admindn cn=krbadmin,o=org -r ATHENA.MIT.EDU +@b{Password for "cn=admin,o=org":} +@b{Initializing database for realm 'ATHENA.MIT.EDU'} +@b{You will be prompted for the database Master Password.} +@b{It is important that you NOT FORGET this password.} +@b{Enter KDC database master key:} +@b{Re-enter KDC database master key to verify:} +shell% +@end group +@end smallexample + +@node Modifying a Kerberos Realm, Retrieving Information about a Kerberos Realm, Creating a Kerberos Realm, Global Operations on the Kerberos LDAP Database +@subsection Modifying a Kerberos Realm + +If you need to modify a realm, use the command as follows: + +@smallexample + +@b{modify} [@b{-r} @i{realm}] [@b{-subtrees} @i{subtree_dn}] [@b{-sscope} @i{search_scope}][@b{-containerref} @i{container_reference_dn}] +[@b{-maxtktlife}@i{max_ticket_life}][@b{-maxrenewlife} @i{max_renewable_ticket_life}] [@b{-ticket_flags}] + +@end smallexample +Options to modify realm in directory are as follows: + +@table @b + +@itemx @b{-r} @i{realm} +Specifies the Kerberos realm of the database; by default the realm returned by krb5_default_local_realm (3) is used. + +@itemx @b{-subtrees} @i{subtree_dn_list} +Specifies the list of subtrees containing principal objects in the realm.The list contains the DN of the subtree objects separated by colon(:). This list replaces the existing list. + +@itemx @b{-sscope} @i{search_scope} +Specifies the scope for searching the principals under the subtrees. The possible values are 1 or one (one level), 2 or sub (subtrees). + +@itemx @b{-containerref} @i{container_reference_dn} +Specifies the Distinguished Name (DN) of the container object in which the principals of a realm will be created. + +@itemx @b{-maxtktlife} @i{max_ticket_life} +Specifies maximum ticket life for principals in this realm. This value is used, if it is not set on the principal. + +@itemx @b{-maxrenewlife} @i{max_renewable_ticket_life} +Specifies maximum renewable life of tickets for principals in this realm. This value is used, if it is not set on the principal. + +@itemx @b{-ticket_flags} @i{} +Specifies the ticket flags. If this option is not specified, by default, none of the flags are set. This means all the ticket options will be allowed and no restriction will be set. This value is used, if it is not set on the principal. +@noindent + +The various flags are: +@table @b + +@itemx @{-|+@}allow_postdated +@code{-allow_postdated} prohibits principals from obtaining postdated tickets. (Sets the @samp{KRB5_KDB_DISALLOW_POSTDATED} flag.).@code{+allow_postdated} clears this flag. +@itemx @{-|+@}allow_forwardable +@code{-allow_forwardable} prohibits principals from obtaining forwardable tickets. +(Sets the @samp{KRB5_KDB_DISALLOW_FORWARDABLE} flag.) @code{+allow_forwardable} clears this flag. +@itemx @{-|+@}allow_renewable +@code{-allow_renewable} prohibits principals from obtaining renewable tickets. (Sets the @samp{KRB5_KDB_DISALLOW_RENEWABLE} flag.) @code{+allow_renewable} clears this flag. +@itemx @{-|+@}allow_proxiable +@code{-allow_proxiable} prohibits principals from obtaining proxiable tickets. (Sets the @samp{KRB5_KDB_DISALLOW_PROXABLE} flag.) @code{+allow_proxiable} clears this flag. +@itemx @{-|+@}allow_dup_skey +@code{-allow_dup_skey} Disables user-to-user authentication for principals by prohibiting principals from obtaining a sessions key for another user. (Sets the @samp{KRB5_KDB_DISALLOW_DUP_SKEY} flag.). @code{+allow_dup_skey} clears This flag. +@itemx @{-|+@}requires_preauth +@code{+requires_preauth} requires principals to preauthenticate before being allowed to kinit. Sets the +@samp{KRB5_KDB_REQURES_PRE_AUTH} flag.@code{-requires_preauth} clears this flag. +@itemx @{-|+@}requires_hwauth +@code{+requires_hwauth} requires principals to preauthenticate using a hardware device before being allowed to kinit. (Sets the +@samp{KRB5_KDB_REQURES_HW_AUTH} flag.)@code{-requires_hwauth} clears this flag. +@itemx @{-|+@}allow_svr +@code{-allow_svr} prohibits the issuance of service tickets for principals. (Sets the @samp{KRB5_KDB_DISALLOW_SVR} flag.) @code{+allow_svr} clears This flag. +@itemx @{-|+@}allow_tgs_req +@code{-allow_tgs_req} specifies that a @dfn{Ticket-Granting Service (TGS)} request for a service ticket for principals is not permitted. This option is useless for most things.@code{+allow_tgs_req} clears this flag. +The default is. @code{+allow_tgs_req}. In effect, +@code{-allow_tgs_req} sets the @samp{KRB5_KDB_DISALLOW_TGT_BASED} flag +on principals in the database. +@itemx @{-|+@}allow_tix +@code{-allow_tix} forbids the issuance of any tickets for +principals. @code{+allow_tix} clears this flag. The default is +@code{+allow_tix}. In effect, @code{-allow_tix} sets the +@samp{KRB5_KDB_DISALLOW_ALL_TIX} flag on principals in the database. +@itemx @{-|+@}needchange +@code{+needchange} sets a flag in attributes field to force a password change; @code{-needchange} clears it. +The default is @code{-needchange}. In effect,@code{+needchange} sets +the @samp{KRB5_KDB_REQURES_PWCHANGE} flag on principals in the +database. +@itemx @{-|+@}password_changing_service +@code{+password_changing_service} sets a flag in the attributes field marking principal as a password change service principal (useless for most things).@code{-password_changing_service} clears the flag. This flag intentionally has a long name. The default is @code{-password_changing_service} +In effect, @code{+password_changing_service} sets the @samp{KRB5_KDB_PWCHANGE_SERVICE} flag on principals in the database. + +@end table + +@noindent +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu +modify -r ATHENA.MIT.EDU +requires_preauth +@b{Password for "cn=admin,o=org":} +shell% +@end group +@end smallexample + +@menu +* eDirectory Options (Modifying a Kerberos Realm):: +@end menu + +@end table + +@node eDirectory Options (Modifying a Kerberos Realm), , Modifying a Kerberos Realm, Modifying a Kerberos Realm +@subsubsection eDirectory Options + +@table @b +@itemx @b{-kdcdn} @i{kdc_service_list} +Specifies the list of KDC service objects serving the realm. The list contains the DNs of the KDC service objects separated by a colon (:). This list replaces the existing list. + +@itemx @b{-clearkdcdn} @i{kdc_service_list} +Specifies the list of KDC service objects that need to be removed from the existing list. The list contains the DNs of the KDC service objects separated by a colon (:). + +@itemx @b{-addkdcdn} @i{kdc_service_list} +Specifies the list of KDC service objects that need to be added to the existing list. The list contains the DNs of the KDC service objects separated by a colon (:). + +@itemx @b{-admindn} @i{admin_service_list} +Specifies the list of Administration service objects serving the realm. The list contains the DNs of the Administration service objects separated by a colon (:). This list replaces the existing list. + +@itemx @b{-clearadmindn} @i{admin_service_list} +Specifies the list of Administration service objects that need to be removed from the existing list. The list contains the DNs of the Administration service objects separated by a colon (:). + +@itemx @b{-addadmindn} @i{admin_service_list} +Specifies the list of Administration service objects that need to be added to the existing list. The list contains the DNs of the Administration service objects separated by a colon (:). + +@end table + +@node Retrieving Information about a Kerberos Realm, Destroying a Kerberos Realm, Modifying a Kerberos Realm, Global Operations on the Kerberos LDAP Database +@subsection Retrieving Information about a Kerberos Realm + +@table @b +@itemx @b{view} [@b{-r} @i{realm}] +Displays the attributes of a realm. Option is as follows: +@itemx @b{-r} @i{realm} +specifies the Kerberos realm of the database; by default the realm returned by krb5_default_local_realm (3)is used. +@end table +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu view -r ATHENA.MIT.EDU +@b{Password for "cn=admin,o=org":} +@b{Realm Name: ATHENA.MIT.EDU} +@b{Subtree: ou=users,o=org} +@b{Subtree: ou=servers,o=org} +@b{SearchScope: ONE} +@b{Maximum ticket life: 0 days 01:00:00} +@b{Maximum renewable life: 0 days 10:00:00} +@b{Ticket flags: DISALLOW_FORWARDABLE} +shell% +@end group +@end smallexample + + +@node Destroying a Kerberos Realm, Listing available Kerberos Realms, Retrieving Information about a Kerberos Realm, Global Operations on the Kerberos LDAP Database +@subsection Destroying a Kerberos Realm + +@table @b +@itemx destroy @b{[-f]} [@i{-r} @b{realm}] +Destroys an existing realm. Options are as follows: +@table @b +@itemx @i{-f} +If specified, will not prompt the user for confirmation. +@itemx @b{-r} @i{realm} +specifies the Kerberos realm of the database; by default the realm returned by +@samp{krb5_default_local_realm} (3)is used. + +@end table +@end table +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldap-server1.mit.edu destroy -r ATHENA.MIT.EDU +@b{Password for "cn=admin,o=org":} +@b{Deleting KDC database of 'ATHENA.MIT.EDU', are you sure?} +@b{type 'yes' to confirm)? Yes} +@b{OK, deleting database of 'ATHENA.MIT.EDU'...} +shell% +@end group +@end smallexample + +@node Listing available Kerberos Realms, Stashing Service Object's Password, Destroying a Kerberos Realm, Global Operations on the Kerberos LDAP Database +@subsection Listing available Kerberos Realms + +@table @b +@itemx @i{list} +This option lists the name of the realms. +@end table +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu list +@b{Password for "cn=admin,o=org":} +@b{ATHENA.MIT.EDU} +@b{OPENLDAP.MIT.EDU} +@b{MEDIA-LAB.MIT.EDU} +shell% +@end group +@end smallexample + +@node Stashing Service Object's Password, Creating and Modifying a Ticket Policy, Listing available Kerberos Realms, Global Operations on the Kerberos LDAP Database +@subsection Stashing Service Object's Password + +@b{stashsrvpw} [@b{-f} @i{filename}] @b{servicedn} + +This command allows an administrator to store the password of service object in a file. The KDC and Administration server uses this password to authenticate to the LDAP server. +@noindent +Options are as follows: + +@table @b +@itemx @b{-f} @i{filename} +Specifies the complete path of the service password file. By default, @code{/usr/local/var/service_passwd} is used. +@itemx servicedn +Specifies the Distinguished Name (DN) of the service object whose password is to be stored in file. +@end table +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util stashsrvpw -f /home/andrew/conf_keyle cn=service-kdc,o=org +@b{Password for "cn=service-kdc,o=org"}: +@b{Re-enter password for "cn=service-kdc,o=org"}: +shell% +@end group +@end smallexample + +@node Creating and Modifying a Ticket Policy, Retrieving Information About a Ticket Policy, Stashing Service Object's Password, Global Operations on the Kerberos LDAP Database +@subsection Creating and Modifying a Ticket Policy + +This command creates a ticket policy in directory. + +@smallexample +@b{create_policy} [@b{-r} @i{realm}] [@b{-maxrenewlife} @i{max_renewable_ticket_life}] [@b{ticket_flags}] @b{policy_name} +@end smallexample +Ticket policy objects are created under the realm container. + +This command modifies a ticket policy in directory. +@smallexample +@b{modify_policy} [@b{-r} @i{realm}] [@b{-maxrenewlife} @i{max_renewable_ticket_life}] [@b{ticket_flags}] @b{policy_name} +@end smallexample +@noindent +Options are as follows: + +@table @b + +@itemx @b{-r} @i{realm} +Specifies the Kerberos realm of the database; by default the realm returned by krb5_default_local_realm(3) is used. +@itemx @b{-maxtktlife} @i{max_ticket_life} +specifies maximum ticket life for principals. +@itemx @b{-maxrenewlife} @i{max_renewable_ticket_life} +specifies maximum renewable life of tickets for principals. + +@itemx @b{ticket_flags} +Specifies the ticket flags. If this option is not specified, by default, none of the flags are set. This means all the ticket options will be allowed and no restriction will be set. + +@noindent +The various flags are: +@table @b +@itemx @{-|+@}allow_postdated +@code{-allow_postdated} prohibits principals from obtaining postdated tickets. (Sets the @samp{KRB5_KDB_DISALLOW_POSTDATED} flag.).@code{+allow_postdated} clears this flag. + +@itemx @{-|+@}allow_forwardable + +@code{-allow_forwardable} prohibits principals from obtaining forwardable tickets. (Sets the +@samp{KRB5_KDB_DISALLOW_FORWARDABLE} flag.) @code{+allow_forwardable} clears this flag. + +@itemx @{-|+@}allow_renewable +@code{-allow_renewable} prohibits principals from obtaining renewable tickets. (Sets the @samp{KRB5_KDB_DISALLOW_RENEWABLE} flag.) @code{+allow_renewable} clears this flag. +@itemx @{-|+@}allow_proxiable +@code{-allow_proxiable} prohibits principals from obtaining proxiable tickets. (Sets the @samp{KRB5_KDB_DISALLOW_PROXABLE} flag.) @code{+allow_proxiable} clears this flag. +@itemx @{-|+@}allow_dup_skey +@code{-allow_dup_skey} Disables user-to-user authentication for principals by prohibiting principals from obtaining a sessions key for another user. (Sets the @samp{KRB5_KDB_DISALLOW_DUP_SKEY} flag.). @code{+allow_dup_skey} clears This flag. +@itemx @{-|+@}requires_preauth +@code{+requires_preauth} requires principals to preauthenticate before being allowed to kinit. (Sets the @samp{KRB5_KDB_REQURES_PRE_AUTH} flag.) +@code{-requires_preauth} clears this flag. + +@itemx @{-|+@}requires_hwauth +@code{+requires_hwauth} requires principals to preauthenticate using a +hardware device before being allowed to kinit. (Sets the +@samp{KRB5_KDB_REQURES_HW_AUTH} flag.) @code{-requires_hwauth} clears +this flag. + +@itemx @{-|+@}allow_svr +@code{-allow_svr} prohibits the issuance of service tickets for principals. (Sets the @samp{KRB5_KDB_DISALLOW_SVR} flag.) @code{+allow_svr} clears This flag. +@itemx @{-|+@}allow_tgs_req +@code{-allow_tgs_req} specifies that a @dfn{Ticket-Granting Service (TGS)} request for a service ticket for principals is not permitted. This option is useless for most things.@code{+allow_tgs_req} clears this flag. +The default is @code{+allow_tgs_req}. In effect, +@code{-allow_tgs_req} sets the @samp{KRB5_KDB_DISALLOW_TGT_BASED} flag +on principals in the database. + +@itemx @{-|+@}allow_tix +@code{-allow_tix} forbids the issuance of any tickets for +principals. @code{+allow_tix} clears this flag. The default is +@code{+allow_tix}. In effect, @code{-allow_tix} sets the +@samp{KRB5_KDB_DISALLOW_ALL_TIX} flag on principals in the database. + +@itemx @{-|+@}needchange +@code{+needchange} sets a flag in attributes field to force a password change; +@code{-needchange} clears it. The default is @code{-needchange}. In +effect, @code{+needchange} sets the @samp{KRB5_KDB_REQURES_PWCHANGE} +flag on principals in the database. + +@itemx @{-|+@}password_changing_service +@code{+password_changing_service} sets a flag in the attributes field +marking principal as a password change service principal (useless for +most things). @code{-password_changing_service} clears the flag. +This flag intentionally has a long name. The default is +@code{-password_changing_service}. In effect, +@code{+password_changing_service} sets the +@samp{KRB5_KDB_PWCHANGE_SERVICE} flag on principals in the database. +@end table + +@itemx policy_name +Specifies the name of the ticket policy. + +@end table +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu create_policy +-r ATHENA.MIT.EDU -maxtktlife "1 day" -maxrenewlife "1 week" -allow_forwardable usertktpolicy +@b{Password for "cn=admin,o=org":} +shell% +@end group +@end smallexample + +@node Retrieving Information About a Ticket Policy, Destroying a Ticket Policy, Creating and Modifying a Ticket Policy, Global Operations on the Kerberos LDAP Database +@subsection Retrieving Information About a Ticket Policy + +@table @b +@b{view_policy} [@b{-r} @i{realm}] @b{policy_name} + +@itemx view_policy +This option displays the attributes of a ticket policy. Option is as follows: + +@itemx @b{-r} @i{realm} +Specifies the Kerberos realm of the database; by default the realm returned by krb5_default_local_realm(3) is used. +@itemx policy_name +Specifies the name of the ticket policy. +@end table + +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu view_policy +-r ATHENA.MIT.EDU usertktpolicy +@b{Password for "cn=admin,o=org":} +@b{Ticket policy: usertktpolicy} +@b{Maxmum ticket life: 0 days 01:00:00} +@b{Maxmum renewable life: 0 days 10:00:00} +@b{Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE} +shell% +@end group +@end smallexample + + +@node Destroying a Ticket Policy, Listing available Ticket Policies, Retrieving Information About a Ticket Policy, Global Operations on the Kerberos LDAP Database +@subsection Destroying a Ticket Policy + +@table @b +@itemx @b{destroy_policy} @b{[-force]} @b{[-r} @i{realm}@b{]} @b{policy_name} +Destroys an existing ticket policy. Options are as follows: + +@table @b + +@itemx -force +Forces the deletion of the policy object. If not specified, will be prompted for confirmation while deleting the policy. Enter yes to confirm the deletion. + +@itemx -r realm +Specifies the Kerberos realm of the database; by default the realm returned by krb5_default_local_realm(3) is used. + +@itemx policy_name +Specifies the name of the ticket policy. +@end table +@end table +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu +destroy_policy -r ATHENA.MIT.EDU usertktpolicy +@b{Password for "cn=admin,o=org":} +@b{This will delete the policy object 'usertktpolicy', are you sure?} +@b{(type 'yes' to confirm)? Yes} +@b{** policy object 'usertktpolicy' deleted.} +shell% +@end group +@end smallexample + +@node Listing available Ticket Policies, Creating a Service Object (eDirectory), Destroying a Ticket Policy, Global Operations on the Kerberos LDAP Database +@subsection Listing available Ticket Policies + + +@table @b +@itemx @b{list_policy} [@b{-r} @i{realm}] +Lists the name of ticket policies in a realm. + +Option are as follows: + +@itemx -r realm +Specifies the Kerberos realm of the database; by default the realm returned by krb5_default_local_realm(3) is used. + +@end table + +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu list_policy -r ATHENA.MIT.EDU +@b{Password for "cn=admin,o=org":} +@b{usertktpolicy} +@b{tempusertktpolicy} +@b{krbtktpolicy} +shell% +@end group +@end smallexample + +@node Creating a Service Object (eDirectory), Modifying a Service Object (eDirectory), Listing available Ticket Policies, Global Operations on the Kerberos LDAP Database +@subsection Creating a Service Object (eDirectory) +@smallexample +@b{create_service} @i{-kdc|-admin|-pwd} [@b{-servicehost} @i{service_host_list}] [@b{-realm} @i{realm_list}] [@b{-randpw}| +@i{-fileonly}] [@i{-filename}] @b{service_dn} +@end smallexample +@noindent +Creates a service object in directory and assigns appropriate rights on the container holding kerberos data. + +Options are as follows: + +@table @b +@itemx -kdc +Specifies the KDC service +@itemx -admin +Specifies the Administration service +@itemx -pwd +Specifies the Password service + +@itemx @b{-servicehost} @i{service_host_list} +Specifies the list of entries separated by a colon (:). Each entry consists of the hostname or IP address of the server hosting the service, transport protocol and the port number of the service separated by a pound sign (#). +@noindent +For example, +@smallexample +server1#tcp#88:server2#udp#89. +@end smallexample +@itemx @b{-realm} @i{realm_list} +Specifies the list of realms that are to be associated with this service. The list contains the name of the realms separated by a colon (:). +@itemx -randpw +Generates and sets a random password. This option is used to set the random password for the service object in directory and also to store it in the file. @code{-fileonly} option cannot be used with @code{-randpw} option. + +@itemx -fileonly +Stores the password only in a file and not in directory. The @code{-randpw} option can not be used when @code{-fileonly} option is specified. +@itemx @i{-f} @b{filename} +Specifies the complete path of the file where the service object password is stashed. If this option is not specified, the default file will be /usr/local/var/service_passwd +@itemx service_dn +Specifies the Distinguished Name (DN) of the Kerberos service to be created. + +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu +create_service -kdc -randpw -f /home/andrew/service_passwd cn=service-kdc,o=org +@b{Password for "cn=admin,o=org":} +@b{File does not exist. Creating the file /home/andrew/service_passwd...} +shell% +@end group +@end smallexample +@end table + +@node Modifying a Service Object (eDirectory), Retrieving Service Object Information (eDirectory), Creating a Service Object (eDirectory), Global Operations on the Kerberos LDAP Database +@subsection Modifying a Service Object (eDirectory) +@smallexample +@b{modify_service} [@b{-servicehost} @i{service_host_list} |[@b{-clearservicehost} @i{service_host_list}] [@b{-addservicehost} @i{service_host_list}]] [@b{-realm} @i{realm_list} | [@b{-clearrealm} @i{realm_list}] [@b{-addrealm} @i{realm_list}]] service_dn +@end smallexample + +Modifies the attributes of a service and assigns appropriate rights, if realm associations are changed. + +Options are as follows: + +@table @b +@itemx @b{-servicehost} @i{service_host_list} +List of entries separated by a colon (:) where each entry consists of host name or IP address of the server hosting the service, transport protocol, and port number of the service separated by a pound sign (#). This list replaces the existing list. +For example, +@smallexample +server1#tcp#88:server2#udp#89 +@end smallexample +@itemx @b{-clearservicehost} @i{service_host_list} +Specifies the list of servicehost entries to be removed from the existing list. This is a colon separated list. +@itemx @b{-addservicehost} @i{service_host_list} +Specifies the list of servicehost entries to be added to the existing list. This is a colon separated list. +@itemx @b{-realm} @i{realm_list} +Specifies the list of realms that are to be associated with this service. The list contains the name of the realms separated by a colon (:). This list replaces the existing list. +@itemx @b{-clearrealm} @i{realm_list} +Specifies the list of realms to be removed from the existing list. The list contains the name of the realms separated by a colon (:). +@itemx @b{-addrealm} @i{realm_list} +Specifies the list of realms to be added to the existing list. The list contains the name of the realms separated by a colon (:). +@itemx service_dn +Specifies the Distinguished Name (DN) of the Kerberos service to be modified. + +@end table + +@noindent +For example: + +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu +modify_service -realm ATHENA.MIT.EDU cn=service-kdc,o=org +@b{Password for "cn=admin,o=org":} +@b{Changing rights for the service object. Please wait ... done} +shell% +@end group +@end smallexample +@node Retrieving Service Object Information (eDirectory), Destroying a Service Object (eDirectory), Modifying a Service Object (eDirectory), Global Operations on the Kerberos LDAP Database +@subsection Retrieving Service Object Information (eDirectory) + +@table @b +@itemx view_service service_dn +Displays the attributes of a service. Options are as follows: + +@itemx service_dn +Specifies the Distinguished name (DN) of the Kerberos service to be viewed. +@end table + +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu +view_service cn=service-kdc,o=org +@b{Password for "cn=admin,o=org":} +@b{Service dn: cn=service-kdc,o=org} +@b{Service type: kdc} +@b{Service host list:} +@b{Realm DN list: cn=ATHENA.MIT.EDU,cn=Kerberos,o=org} +shell% +@end group +@end smallexample + +@node Destroying a Service Object (eDirectory), Listing Available Service Objects (eDirectory), Retrieving Service Object Information (eDirectory), Global Operations on the Kerberos LDAP Database +@subsection Destroying a Service Object (eDirectory) +@smallexample +@b{destroy_service} [@b{-force}] [@b{-f} @i{stashfilename}] service_dn +@end smallexample +@noindent +Destroys an existing service. Options are as follows : + +@table @b +@itemx -force +If specified, will not prompt for user's confirmation, instead will force destruction of service. +@itemx @b{-f} @i{stashfilename} +Complete path of the service password file from where the entry corresponding to the service_dn needs to be removed. +@itemx service_dn +Distinguished Name (DN) of the Kerberos service to be destroyed. +@end table +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu +destroy_service cn=service-kdc,o=org +@b{Password for "cn=admin,o=org":} +@b{This will delete the service object 'cn=service-kdc,o=org', are you sure?} +@b{(type 'yes' to confirm)? Yes} +@b{** service object 'cn=service-kdc,o=org' deleted.} +shell% +@end group +@end smallexample + +@node Listing Available Service Objects (eDirectory), Passwords for Service Objects (eDirectory), Destroying a Service Object (eDirectory), Global Operations on the Kerberos LDAP Database +@subsection Listing Available Service Objects (eDirectory) + +@table @b +@itemx list_service [-basedn base_dn] +Lists the name of services under a given base in directory. Options is as follows: + +@itemx @b{-basedn} @i{base_dn} +Specifies the base DN for searching the policies, limiting the search to a particular subtree. If this option is not provided, LDAP Server specific search base will be used. For e.g., in the case of OpenLDAP, value of @code{defaultsearchbase} from @file{slapd.conf} file will be used, where as in the case of eDirectory, the default value for the base DN is Root. +@end table + +@noindent +For example: +@smallexample +@group +shell% kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu list_service +@b{Password for "cn=admin,o=org":} +@b{cn=service-kdc,o=org} +@b{cn=service-adm,o=org} +@b{cn=service-pwd,o=org} +shell% +@end group +@end smallexample + +@node Passwords for Service Objects (eDirectory), , Listing Available Service Objects (eDirectory), Global Operations on the Kerberos LDAP Database +@subsection Passwords for Service Objects (eDirectory) + +@b{setsrvpw} @b{[-randpw|-fileonly]}@b{[-f} @i{ filename}@b{]} @b{service_dn} + +Allows an administrator to set password for service objects such as KDC and Administration server in eDirectory and store them in a file. The +@code{-fileonly} command stores the password in a file and not in the eDirectory object. +Options are as follows: +@table @b +@itemx @b{-randpw} +Generates and sets a random password on the directory object and stores it in the file. The @code{-fileonly} option can not be used if @code{-randpw} option is already specified. +@itemx @b{-fileonly} +Stores the password only in a file and not in eDirectory. The @code{-randpw} option can not be used when @code{-fileonly} option is specified. +@itemx @b{-f} @i{filename} +Specifies the complete path of the file where the service object password is stashed. If this option is not specified, the default file will be /usr/local/var/service_passwd. +@itemx service_dn +Specifies the Distinguished Name (DN) of the service object whose password is to be set. + +@end table + + +@noindent +For example: + +@smallexample +@group +shell% kdb5_ldap_util setsrvpw -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu +setsrvpw -f /home/andrew/conf_keyfile cn=service-kdc,o=org +@b{Password for "cn=admin,o=org":} +@b{Password for "cn=service-kdc,o=org":} +@b{Re-enter password for "cn=service-kdc,o=org":} +shell% +@end group +@end smallexample + +@ignore +@c @node The KDC Logs, , GLobal operations on the Kerberos LDAP Database, Administrating the Kerberos Database +@c @section The KDC Logs + +This will have to wait until the next release. *sigh* +@end ignore + +@node Cross-realm Authentication, Changing the krbtgt Key, Global Operations on the Kerberos LDAP Database, Administrating the Kerberos Database +@section Cross-realm Authentication + +In order for a KDC in one realm to authenticate Kerberos users in a +different realm, it must share a key with the KDC in the other realm. +In both databases, there must be krbtgt service principals for realms. +These principals should all have the same passwords, key version +numbers, and encryption types. For example, if the administrators of +@value{PRIMARYREALM} and @value{SECONDREALM} wanted to authenticate +across the realms, they would run the following commands on the KDCs in +@i{both} realms: + +@smallexample +@group +@b{shell%:} kadmin.local -e "des3-hmac-sha1:normal des-cbc-crc:v4" +@b{kadmin:} add_princ -requires_preauth krbtgt/@value{PRIMARYREALM}@@@value{SECONDREALM} +@b{Enter password for principal krbtgt/@value{PRIMARYREALM}@@@value{SECONDREALM}:} +@b{Re-enter password for principal krbtgt/@value{PRIMARYREALM}@@@value{SECONDREALM}:} +@b{kadmin:} add_princ -requires_preauth krbtgt/@value{SECONDREALM}@@@value{PRIMARYREALM} +@b{Enter password for principal krbtgt/@value{SECONDREALM}@@@value{PRIMARYREALM}:} +@b{Enter password for principal krbtgt/@value{SECONDREALM}@@@value{PRIMARYREALM}:} +@b{kadmin:} +@end group +@end smallexample + +Even if most principals in a realm are generally created with the +requires_preauth flag enabled, this flag is not desirable on +cross-realm authentication keys because doing so makes it impossible to +disable preauthentication on a service-by-service basis. Disabling it +as in the example above is recommended. + +It is also very important that these principals have good passwords. +@value{COMPANY} recommends that TGT principal passwords be at least 26 +characters of random ASCII text. + +@node Changing the krbtgt Key, , Cross-realm Authentication, Administrating the Kerberos Database +@section Changing the krbtgt Key + +A Kerberos Ticket Granting Ticket (TGT) is a service ticket for the +principal krbtgt/@i{REALM}. The key for this principal is created when +the Kerberos database is initialized and need not be changed. However, +it will only have the encryption types supported by the KDC at the time +of the initial database creation. To allow use of newer encryption +types for the TGT, this key has to be changed. + +Changing this key using the normal @code{kadmin change_password} command +would invalidate any previously issued TGTs. Therefore, when changing +this key, normally one should use the @b{-keepold} flag to +@code{change_password} to retain the previous key in the database as +well as the new key. For example: + +@smallexample +@group +@b{kadmin:} change_password -randkey -keepold krbtgt/@value{PRIMARYREALM}@@@value{PRIMARYREALM} +@end group +@end smallexample + +There is currently no way to remove the old key without running +@code{change_password} without the @b{-keepold} flag (and thereby +invalidating all existing TGTs). After issuing this command, the old +key is still valid and is still vulnerable to (for instance) brute force +attacks. To completely retire an old key or encryption type, it's +therefore currently necessary to declare a flag day, run +@code{change_password} without the @b{-keepold} flag, and force all +users to acquire new tickets. + +@node Configuring Kerberos with OpenLDAP back-end, Application Servers, Administrating the Kerberos Database, Top +@chapter Configuring Kerberos with OpenLDAP back-end + +@enumerate +@item +Set up SSL on the OpenLDAP server and client to ensure secure +communication when the KDC service and LDAP server are on different +machines. @code{ldapi://} can be used if the LDAP server and KDC +service are running on the same machine. + +@enumerate A +@item +Setting up SSL on the OpenLDAP server: + +@enumerate a +@item +Get a CA certificate using OpenSSL tools + +@item +Configure OpenLDAP server for using SSL/TLS + +@noindent + For the latter, you need to specify the location of CA certificate location in slapd.conf file. + +@noindent + Refer to the following link for more information: + +@noindent +@uref{http://www.openldap.org/doc/admin23/tls.html} +@end enumerate + +@item +Setting up SSL on OpenLDAP Client: + +@enumerate a +@item +For the KDC and Admin Server, you need to do the client-side configuration in ldap.conf. + +@noindent +For example, +@smallexample +TLS_CACERT @code{/etc/openldap/certs/cacert.pem} +@end smallexample +@end enumerate +@end enumerate + +@item +Include the Kerberos schema file (kerberos.schema) in the +configuration file (slapd.conf) on the LDAP Server, by providing the +location where it is stored. + +@smallexample +include @code{/etc/openldap/schema/kerberos.schema} +@end smallexample + +@item +Configure the LDAP server ACLs to enable the KDC and Admin server to +read and write the Kerberos data. + +@subheading +Sample access control information + +@smallexample +access to dn.base="" + by * read + +access to dn.base="cn=Subschema" + by * read + +access to attrs=userPassword,userPKCS12 + by self write + by * auth + +access to attrs=shadowLastChange + by self write + by * read + +# Providing access to realm subtree +access to @code{dn.subtree}= @i{"o=mit"} + by @code{dn.exact}=@i{"cn=kdc-service,o=mit"} read + by @code{dn.exact}=@i{"cn=adm-service,o=mit"} write + by * none + +# Providing access to realm container +access to @code{dn.subtree}= @i{"cn=MIT.EDU,cn=Kerberos,o=mit"} + by @code{dn.exact}=@i{"cn=kdc-service,o=mit"} read + by @code{dn.exact}=@i{"cn=adm-service,o=mit"} write + by * none + +access to * + by * read +@end smallexample + +@noindent +The above list provides the access control information for the KDC and +Admin service object for the realm container and the realm +subtree. Thus if the realm subtree or the service objects for a realm +are changed then this information should be updated. + +@item +Start the LDAP server as follows: +@smallexample +slapd -h "ldapi:/// ldaps:///" +@end smallexample + +@item +Modify the krb5.conf file to include LDAP specific items listed below: +@smallexample +@samp{realms} +@noindent @samp{database_module} +@noindent +@samp{dbmodules} +@noindent @samp{db_library} +@noindent @samp{db_module_dir} +@noindent @samp{ldap_kdc_dn} +@noindent @samp{ldap_kadmind_dn} +@noindent @samp{ldap_service_password_file} +@noindent @samp{ldap_servers} +@noindent @samp{ldap_conns_per_server} +@end smallexample + +@noindent +For the sample @file{krb5.conf} file, refer to @ref{Sample krb5.conf File}. +@noindent +For more details, refer to the section @file{krb5.conf} + +@item +Create the realm using @samp{kdb5_ldap_util}. + +@smallexample +@b{kdb5_ldap_util} @b{-D} @i{ cn=admin,o=mit} create @b{-subtrees} @i{ o=mit} @b{-r} @i{MIT.EDU} @b{-s} +@end smallexample + +@noindent +Before executing the command, make sure that the subtree mentioned above @samp{(o=mit)} exists. + +For more information, refer to the section @dfn{Global Operations on the Kerberos LDAP Database}. + +@noindent +The realm object is created under the ldap_kerberos_container_dn specified in the configuration file. This operation will also create the Kerberos container, if not present already. This will be used to store information related to all realms. + +@item +Stash the password of the service object used by the KDC and +Administration service to bind to the LDAP server using the stashsrvpw +command of kdb5_ldap_util. The object DN should be the same as +ldap_kdc_dn and ldap_kadmind_dn values specified in the krb5.conf +file. + +@smallexample +@b{kdb5_ldap_util} @b{-D} @i{ cn=admin,o=mit} @i{stashsrvpw} @b{-f} @code{/etc/kerberos/service.keyfile} @i{cn=krbadmin,o=mit} +@end smallexample + +@item +Add krb5principalname to the indexes in slapd.conf to speed up the access. +@end enumerate + +@node Application Servers, Backups of Secure Hosts, Configuring Kerberos with OpenLDAP back-end, Top +@chapter Application Servers + +If you need to install the @value{PRODUCT} programs on an application +server, please refer to the @value{PRODUCT} Installation Guide. Once +you have installed the software, you need to add that host to the +Kerberos database (@pxref{Adding or Modifying Principals}), and generate +a @dfn{keytab} for that host, that contains the host's key. You also +need to make sure the host's clock is within your maximum clock skew of +the KDCs. + +@menu +* Keytabs:: +* Clock Skew:: +* Getting DNS Information Correct:: +* Configuring Your Firewall to Work With Kerberos V5:: +@end menu + +@node Keytabs, Clock Skew, Application Servers, Application Servers +@section Keytabs + +A @dfn{keytab} is a host's copy of its own keylist, which is analogous +to a user's password. An application server that needs to authenticate +itself to the KDC has to have a keytab that contains its own principal +and key. Just as it is important for users to protect their passwords, +it is equally important for hosts to protect their keytabs. You should +always store keytab files on local disk, and make them readable only by +root, and you should never send a keytab file over a network in the +clear. Ideally, you should run the @code{kadmin} command to extract a +keytab on the host on which the keytab is to reside. + +@menu +* Adding Principals to Keytabs:: +* Removing Principals from Keytabs:: +@end menu + +@node Adding Principals to Keytabs, Removing Principals from Keytabs, Keytabs, Keytabs +@subsection Adding Principals to Keytabs + +To generate a keytab, or to add a principal to an existing keytab, use +the @code{ktadd} command from @code{kadmin}, which requires the +``inquire'' administrative privilege. (If you use the @b{-glob} +@i{princ_exp} option, it also requires the ``list'' administrative +privilege.) The syntax is: + +@smallexample +@b{ktadd} [@b{-k[eytab]} @i{keytab}] [@b{-q}] [@b{-e} +@i{key:salt_list}] [@i{principal} | @b{-glob} @i{princ_exp}] +[@i{@dots{}}] +@end smallexample + +The @code{ktadd} command takes the following switches: + +@table @b +@item -k[eytab] @i{keytab} +use @i{keytab} as the keytab file. Otherwise, @code{ktadd} will use the +default keytab file (@code{@value{DefaultDefaultKeytabName}}). + +@item @b{-e} @i{"enc:salt..."} +Uses the specified list of enctype-salttype pairs for setting the key +of the principal. The quotes are necessary if there are multiple +enctype-salttype pairs. This will not function against kadmin daemons +earlier than krb5-1.2. See @ref{Supported Encryption Types} and +@ref{Salts} for all possible values. + +@item -q +run in quiet mode. This causes @code{ktadd} to display less verbose +information. + +@item @i{principal} | -glob @i{principal expression} +add @i{principal}, or all principals matching @i{principal expression} +to the keytab. The rules for @i{principal expression} are the same as +for the kadmin @code{list_principals} (@pxref{Retrieving a List of +Principals}) command. +@end table + +Here is a sample session, using configuration files that enable only +@samp{des-cbc-crc} encryption. (The line beginning with @result{} is a +continuation of the previous line.) + +@smallexample +@group +@b{kadmin:} ktadd host/@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} +@b{kadmin: Entry for principal host/@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} with + kvno 2, encryption type DES-CBC-CRC added to keytab + WRFILE:/etc/krb5.keytab. +kadmin:} +@end group +@end smallexample + +@smallexample +@group +@b{kadmin:} ktadd -k @value{ROOTDIR}/var/krb5kdc/kadmind.keytab +@result{} kadmin/admin kadmin/changepw +@b{kadmin: Entry for principal kadmin/admin@@@value{PRIMARYREALM} with + kvno 3, encryption type DES-CBC-CRC added to keytab + WRFILE:@value{ROOTDIR}/var/krb5kdc/kadmind.keytab. +kadmin:} +@end group +@end smallexample + +@node Removing Principals from Keytabs, , Adding Principals to Keytabs, Keytabs +@subsection Removing Principals from Keytabs + +To remove a principal from an existing keytab, use the kadmin +@code{ktremove} command. The syntax is: + +@smallexample +@b{ktremove} [@b{-k[eytab]} @i{keytab}] [@b{-q}] @i{principal} [@i{kvno} | @b{all} | @b{old}] +@end smallexample + +The @code{ktremove} command takes the following switches: + +@table @b +@item -k[eytab] @i{keytab} +use @i{keytab} as the keytab file. Otherwise, @code{ktremove} will use +the default keytab file (@code{/etc/krb5.keytab}). + +@item -q +run in quiet mode. This causes @code{ktremove} to display less verbose +information. + +@item @i{principal} +the principal to remove from the keytab. (Required.) + +@item @i{kvno} +remove all entries for the specified principal whose Key Version Numbers +match @i{kvno}. + +@item all +remove all entries for the specified principal + +@item old +remove all entries for the specified principal except those with the +highest kvno. +@end table + +For example: + +@smallexample +@group +@b{kadmin:} ktremove -k @value{ROOTDIR}/var/krb5kdc/kadmind.keytab kadmin/admin +@b{kadmin: Entry for principal kadmin/admin with kvno 3 removed + from keytab WRFILE:@value{ROOTDIR}/var/krb5kdc/kadmind.keytab. +kadmin:} +@end group +@end smallexample + +@node Clock Skew, Getting DNS Information Correct, Keytabs, Application Servers +@section Clock Skew + +In order to prevent intruders from resetting their system clocks in +order to continue to use expired tickets, @value{PRODUCT} is set up to +reject ticket requests from any host whose clock is not within the +specified maximum clock skew of the KDC (as specified in the +@code{kdc.conf} file). Similarly, hosts are configured to reject +responses from any KDC whose clock is not within the specified maximum +clock skew of the host (as specified in the @code{krb5.conf} file). The +default value for maximum clock skew is @value{DefaultClockskew}. + +@value{COMPANY} suggests that you add a line to client machines' +@code{/etc/rc} files to synchronize the machine's clock to your KDC at +boot time. On UNIX hosts, assuming you had a kdc called +@code{@value{KDCSERVER}} in your realm, this would be: + +@smallexample +gettime -s @value{KDCSERVER} +@end smallexample + +If the host is not likely to be rebooted frequently, you may also want +to set up a cron job that adjusts the time on a regular basis. + +@node Getting DNS Information Correct, Configuring Your Firewall to Work With Kerberos V5, Clock Skew, Application Servers +@section Getting DNS Information Correct + +Several aspects of Kerberos rely on name service. In order for Kerberos +to provide its high level of security, it is less forgiving of name +service problems than some other parts of your network. It is important +that your Domain Name System (DNS) entries and your hosts have the +correct information. + +Each host's canonical name must be the fully-qualified host name +(including the domain), and each host's IP address must reverse-resolve +to the canonical name. + +Other than the @code{localhost} entry, make all entries in each +machine's @code{/etc/hosts} file in the following form: + +@smallexample +IP address fully-qualified hostname aliases +@end smallexample + +Here is a sample @code{/etc/hosts} file: + +@smallexample +@group +# this is a comment +127.0.0.1 localhost localhost@@@value{PRIMARYDOMAIN} +@value{RANDOMHOST1IP} @value{RANDOMHOST1}.@value{PRIMARYDOMAIN} trillium wake-robin +@end group +@end smallexample + +Additionally, on Solaris machines, you need to be sure the ``hosts'' +entry in the file @* @code{/etc/nsswitch.conf} includes the source +``dns'' as well as ``file''. + +Finally, each host's keytab file must include a host/key pair for the +host's canonical name. You can list the keys in a keytab file by +issuing the command @code{klist -k}. For example: + +@smallexample +@group +viola# klist -k +Keytab name: /etc/krb5.keytab +KVNO Principal +---- ------------------------------------------------------------ + 1 host/@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} +@end group +@end smallexample + +If you telnet to the host with a fresh credentials cache (ticket file), +and then @code{klist}, the host's service principal should be +@i{host/fully-qualified-hostname@@REALM_NAME}. + +@node Configuring Your Firewall to Work With Kerberos V5, , Getting DNS Information Correct, Application Servers +@section Configuring Your Firewall to Work With @value{PRODUCT} + +If you need off-site users to be able to get Kerberos tickets in your +realm, they must be able to get to your KDC. This requires either that +you have a slave KDC outside your firewall, or you configure your +firewall to allow UDP requests into at least one of your KDCs, on +whichever port the KDC is running. (The default is port +@value{DefaultPort}; other ports may be specified in the KDC's kdc.conf +file.) Similarly, if you need off-site users to be able to change +their passwords in your realm, they must be able to get to your +Kerberos admin server. The default port for the admin server is +@value{DefaultKadmindPort}. + +If your on-site users inside your firewall will need to get to KDCs in +other realms, you will also need to configure your firewall to allow +outgoing TCP and UDP requests to port @value{DefaultPort}. +Additionally, if they will need to get to any Kerberos V4 KDCs, you may +also need to allow TCP and UDP requests to port +@value{DefaultSecondPort}. If your on-site users inside your firewall +will need to get to Kerberos admin servers in other realms, you will +also need to allow outgoing TCP and UDP requests to port +@value{DefaultKadmindPort}. + +If any of your KDCs are outside your firewall, you will need to allow +@code{kprop} requests to get through to the remote KDC. @code{Kprop} +uses the krb5_prop service on port @value{DefaultKrbPropPort} (tcp). + +If you need your off-site users to have access to machines inside your +firewall, you need to allow TCP connections from their off-site hosts on +the appropriate ports for the programs they will be using. The +following lines from @code{/etc/services} show the default port numbers +for the @value{PRODUCT} programs: + +@smallexample +@group +ftp @value{DefaultFTPPort}/tcp # Kerberos ftp and telnet use the +telnet @value{DefaultTelnetPort}/tcp # default ports +kerberos @value{DefaultPort}/udp kdc # Kerberos V5 KDC +kerberos @value{DefaultPort}/tcp kdc # Kerberos V5 KDC +klogin @value{DefaultKloginPort}/tcp # Kerberos authenticated rlogin +kshell @value{DefaultKshellPort}/tcp cmd # and remote shell +kerberos-adm @value{DefaultKadmindPort}/tcp # Kerberos 5 admin/changepw +kerberos-adm @value{DefaultKadmindPort}/udp # Kerberos 5 admin/changepw +krb5_prop @value{DefaultKrbPropPort}/tcp # Kerberos slave propagation +@c kpop 1109/tcp # Pop with Kerberos +eklogin @value{DefaultEkloginPort}/tcp # Kerberos auth. & encrypted rlogin +krb524 @value{DefaultKrb524Port}/tcp # Kerberos 5 to 4 ticket translator +@end group +@end smallexample + +By default, @value{PRODUCT} @code{telnet} and @code{ftp} use the same +ports as the standard @code{telnet} and @code{ftp} programs, so if you +already allow telnet and ftp connections through your firewall, the +@value{PRODUCT} versions will get through as well. If you do not +already allow telnet and ftp connections through your firewall, but need +your users to be able to use @value{PRODUCT} telnet and ftp, you can +either allow ftp and telnet connections on the standard ports, or switch +these programs to non-default port numbers and allow ftp and telnet +connections on those ports to get through. + +@value{PRODUCT} @code{rlogin} uses the @code{klogin} service, which by +default uses port @value{DefaultKloginPort}. Encrypted @value{PRODUCT} +rlogin uses the @code{eklogin} service, which by default uses port +@value{DefaultEkloginPort}. + +@value{PRODUCT} @code{rsh} uses the @code{kshell} service, which by +default uses port @value{DefaultKshellPort}. However, the server must +be able to make a TCP connection from the kshell port to an arbitrary +port on the client, so if your users are to be able to use @code{rsh} +from outside your firewall, the server they connect to must be able to +send outgoing packets to arbitrary port numbers. Similarly, if your +users need to run @code{rsh} from inside your firewall to hosts outside +your firewall, the outside server needs to be able to connect to an +arbitrary port on the machine inside your firewall. Because +@value{PRODUCT} @code{rcp} uses @code{rsh}, the same issues apply. If +you need to use @code{rsh} (or @code{rcp}) through your firewall and +are concerned with the security implications of allowing connections to +arbitrary ports, @value{COMPANY} suggests that you have rules that +specifically name these applications and, if possible, list the allowed +hosts. + +The book @cite{UNIX System Security}, by David Curry, is a good +starting point for learning to configure firewalls. + +@ignore +@c @node Enabling Users to Connect from Off-Site, , Configuring Your Firewall to Work With @value{PRODUCT}, Application Servers +@c @section Enabling Users to Connect from Off-Site + +This will have to wait until the next release. *sigh* +@end ignore + +@node Backups of Secure Hosts, Bug Reporting, Application Servers, Top +@chapter Backups of Secure Hosts + +When you back up a secure host, you should exclude the host's keytab +file from the backup. If someone obtained a copy of the keytab from a +backup, that person could make any host masquerade as the host whose +keytab was compromised. This could be particularly dangerous if the +compromised keytab was from one of your KDCs. If the machine has a disk +crash and the keytab file is lost, it is easy to generate another keytab +file. (@xref{Adding Principals to Keytabs}.) If you are unable to +exclude particular files from backups, you should ensure that the +backups are kept as secure as the host's root password. + +@menu +* Backing Up the Kerberos Database:: +@end menu + +@node Backing Up the Kerberos Database, , Backups of Secure Hosts, Backups of Secure Hosts +@section Backing Up the Kerberos Database + +As with any file, it is possible that your Kerberos database could +become corrupted. If this happens on one of the slave KDCs, you might +never notice, since the next automatic propagation of the database would +install a fresh copy. However, if it happens to the master KDC, the +corrupted database would be propagated to all of the slaves during the +next propagation. For this reason, @value{COMPANY} recommends that you +back up your Kerberos database regularly. Because the master KDC is +continuously dumping the database to a file in order to propagate it to +the slave KDCs, it is a simple matter to have a cron job periodically +copy the dump file to a secure machine elsewhere on your network. (Of +course, it is important to make the host where these backups are stored +as secure as your KDCs, and to encrypt its transmission across your +network.) Then if your database becomes corrupted, you can load the +most recent dump onto the master KDC. (@xref{Restoring a Kerberos +Database from a Dump File}.) + +@node Bug Reporting, Appendix, Backups of Secure Hosts, Top +@chapter Bug Reporting + +@include send-pr.texinfo + +@node Appendix, , Bug Reporting, Top +@appendix Appendix + +@menu +* Errors:: +* kadmin Time Zones:: +@end menu + +@node Errors, kadmin Time Zones, Appendix, Appendix +@appendixsec Kerberos Error Messages + +@menu +* Kerberos V5 Library Error Codes:: +* Kerberos V5 Database Library Error Codes:: +* Kerberos V5 Magic Numbers Error Codes:: +* ASN.1 Error Codes:: +* GSSAPI Error Codes:: +@end menu + +@node Kerberos V5 Library Error Codes, Kerberos V5 Database Library Error Codes, Errors, Errors +@appendixsubsec Kerberos V5 Library Error Codes + +This is the Kerberos v5 library error code table. Protocol error codes +are @* ERROR_TABLE_BASE_krb5 + the protocol error code number; other +error codes start at ERROR_TABLE_BASE_krb5 + 128. + +@c error table numbering starts at 0 +@enumerate 0 +@item +KRB5KDC_ERR_NONE: No error +@item +KRB5KDC_ERR_NAME_EXP: Client's entry in database has expired +@item +KRB5KDC_ERR_SERVICE_EXP: Server's entry in database has expired +@item +KRB5KDC_ERR_BAD_PVNO: Requested protocol version not supported +@item +KRB5KDC_ERR_C_OLD_MAST_KVNO: Client's key is encrypted in an old master +key +@item +KRB5KDC_ERR_S_OLD_MAST_KVNO: Server's key is encrypted in an old master +key +@item +KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: Client not found in Kerberos database +@item +KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: Server not found in Kerberos database +@item +KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE: Principal has multiple entries in +Kerberos database +@item +KRB5KDC_ERR_NULL_KEY: Client or server has a null key +@item +KRB5KDC_ERR_CANNOT_POSTDATE: Ticket is ineligible for postdating +@item +KRB5KDC_ERR_NEVER_VALID: Requested effective lifetime is negative or +too short +@item +KRB5KDC_ERR_POLICY: KDC policy rejects request +@item +KRB5KDC_ERR_BADOPTION: KDC can't fulfill requested option +@item +KRB5KDC_ERR_ETYPE_NOSUPP: KDC has no support for encryption type +@item +KRB5KDC_ERR_SUMTYPE_NOSUPP: KDC has no support for checksum type +@item +KRB5KDC_ERR_PADATA_TYPE_NOSUPP: KDC has no support for padata type +@item +KRB5KDC_ERR_TRTYPE_NOSUPP: KDC has no support for transited type +@item +KRB5KDC_ERR_CLIENT_REVOKED: Clients credentials have been revoked +@item +KRB5KDC_ERR_SERVICE_REVOKED: Credentials for server have been revoked +@item +KRB5KDC_ERR_TGT_REVOKED: TGT has been revoked +@item +KRB5KDC_ERR_CLIENT_NOTYET: Client not yet valid - try again later +@item +KRB5KDC_ERR_SERVICE_NOTYET: Server not yet valid - try again later +@item +KRB5KDC_ERR_KEY_EXP: Password has expired +@item +KRB5KDC_ERR_PREAUTH_FAILED: Preauthentication failed +@item +KRB5KDC_ERR_PREAUTH_REQUIRED: Additional pre-auth@-en@-ti@-ca@-tion required +@item +KRB5KDC_ERR_SERVER_NOMATCH: Requested server and ticket don't match +@item +KRB5PLACEHOLD_27: KRB5 error code 27 +@item +KRB5PLACEHOLD_28: KRB5 error code 28 +@item +KRB5PLACEHOLD_29: KRB5 error code 29 +@item +KRB5PLACEHOLD_30: KRB5 error code 30 +@item +KRB5KRB_AP_ERR_BAD_INTEGRITY: Decrypt integrity check failed +@item +KRB5KRB_AP_ERR_TKT_EXPIRED: Ticket expired +@item +KRB5KRB_AP_ERR_TKT_NYV: Ticket not yet valid +@item +KRB5KRB_AP_ERR_REPEAT: Request is a replay +@item +KRB5KRB_AP_ERR_NOT_US: The ticket isn't for us +@item +KRB5KRB_AP_ERR_BADMATCH: Ticket/authenticator don't match +@item +KRB5KRB_AP_ERR_SKEW: Clock skew too great +@item +KRB5KRB_AP_ERR_BADADDR: Incorrect net address +@item +KRB5KRB_AP_ERR_BADVERSION: Protocol version mismatch +@item +KRB5KRB_AP_ERR_MSG_TYPE: Invalid message type +@item +KRB5KRB_AP_ERR_MODIFIED: Message stream modified +@item +KRB5KRB_AP_ERR_BADORDER: Message out of order +@item +KRB5KRB_AP_ERR_ILL_CR_TKT: Illegal cross-realm ticket +@item +KRB5KRB_AP_ERR_BADKEYVER: Key version is not available +@item +KRB5KRB_AP_ERR_NOKEY: Service key not available +@item +KRB5KRB_AP_ERR_MUT_FAIL: Mutual authentication failed +@item +KRB5KRB_AP_ERR_BADDIRECTION: Incorrect message direction +@item +KRB5KRB_AP_ERR_METHOD: Alternative authentication method required +@item +KRB5KRB_AP_ERR_BADSEQ: Incorrect sequence number in message +@item +KRB5KRB_AP_ERR_INAPP_CKSUM: Inappropriate type of checksum in message +@item +KRB5KRB_AP_PATH_NOT_ACCEPTED: Policy rejects transited path +@item +KRB5KRB_ERR_RESPONSE_TOO_BIG: Response too big for UDP, retry with TCP +@item +KRB5PLACEHOLD_53: KRB5 error code 53 +@item +KRB5PLACEHOLD_54: KRB5 error code 54 +@item +KRB5PLACEHOLD_55: KRB5 error code 55 +@item +KRB5PLACEHOLD_56: KRB5 error code 56 +@item +KRB5PLACEHOLD_57: KRB5 error code 57 +@item +KRB5PLACEHOLD_58: KRB5 error code 58 +@item +KRB5PLACEHOLD_59: KRB5 error code 59 +@item +KRB5KRB_ERR_GENERIC: Generic error (see e-text) +@item +KRB5KRB_ERR_FIELD_TOOLONG: Field is too long for this implementation +@item +KRB5PLACEHOLD_62: KRB5 error code 62 +@item +KRB5PLACEHOLD_63: KRB5 error code 63 +@item +KRB5PLACEHOLD_64: KRB5 error code 64 +@item +KRB5PLACEHOLD_65: KRB5 error code 65 +@item +KRB5PLACEHOLD_66: KRB5 error code 66 +@item +KRB5PLACEHOLD_67: KRB5 error code 67 +@item +KRB5PLACEHOLD_68: KRB5 error code 68 +@item +KRB5PLACEHOLD_69: KRB5 error code 69 +@item +KRB5PLACEHOLD_70: KRB5 error code 70 +@item +KRB5PLACEHOLD_71: KRB5 error code 71 +@item +KRB5PLACEHOLD_72: KRB5 error code 72 +@item +KRB5PLACEHOLD_73: KRB5 error code 73 +@item +KRB5PLACEHOLD_74: KRB5 error code 74 +@item +KRB5PLACEHOLD_75: KRB5 error code 75 +@item +KRB5PLACEHOLD_76: KRB5 error code 76 +@item +KRB5PLACEHOLD_77: KRB5 error code 77 +@item +KRB5PLACEHOLD_78: KRB5 error code 78 +@item +KRB5PLACEHOLD_79: KRB5 error code 79 +@item +KRB5PLACEHOLD_80: KRB5 error code 80 +@item +KRB5PLACEHOLD_81: KRB5 error code 81 +@item +KRB5PLACEHOLD_82: KRB5 error code 82 +@item +KRB5PLACEHOLD_83: KRB5 error code 83 +@item +KRB5PLACEHOLD_84: KRB5 error code 84 +@item +KRB5PLACEHOLD_85: KRB5 error code 85 +@item +KRB5PLACEHOLD_86: KRB5 error code 86 +@item +KRB5PLACEHOLD_87: KRB5 error code 87 +@item +KRB5PLACEHOLD_88: KRB5 error code 88 +@item +KRB5PLACEHOLD_89: KRB5 error code 89 +@item +KRB5PLACEHOLD_90: KRB5 error code 90 +@item +KRB5PLACEHOLD_91: KRB5 error code 91 +@item +KRB5PLACEHOLD_92: KRB5 error code 92 +@item +KRB5PLACEHOLD_93: KRB5 error code 93 +@item +KRB5PLACEHOLD_94: KRB5 error code 94 +@item +KRB5PLACEHOLD_95: KRB5 error code 95 +@item +KRB5PLACEHOLD_96: KRB5 error code 96 +@item +KRB5PLACEHOLD_97: KRB5 error code 97 +@item +KRB5PLACEHOLD_98: KRB5 error code 98 +@item +KRB5PLACEHOLD_99: KRB5 error code 99 +@item +KRB5PLACEHOLD_100: KRB5 error code 100 +@item +KRB5PLACEHOLD_101: KRB5 error code 101 +@item +KRB5PLACEHOLD_102: KRB5 error code 102 +@item +KRB5PLACEHOLD_103: KRB5 error code 103 +@item +KRB5PLACEHOLD_104: KRB5 error code 104 +@item +KRB5PLACEHOLD_105: KRB5 error code 105 +@item +KRB5PLACEHOLD_106: KRB5 error code 106 +@item +KRB5PLACEHOLD_107: KRB5 error code 107 +@item +KRB5PLACEHOLD_108: KRB5 error code 108 +@item +KRB5PLACEHOLD_109: KRB5 error code 109 +@item +KRB5PLACEHOLD_110: KRB5 error code 110 +@item +KRB5PLACEHOLD_111: KRB5 error code 111 +@item +KRB5PLACEHOLD_112: KRB5 error code 112 +@item +KRB5PLACEHOLD_113: KRB5 error code 113 +@item +KRB5PLACEHOLD_114: KRB5 error code 114 +@item +KRB5PLACEHOLD_115: KRB5 error code 115 +@item +KRB5PLACEHOLD_116: KRB5 error code 116 +@item +KRB5PLACEHOLD_117: KRB5 error code 117 +@item +KRB5PLACEHOLD_118: KRB5 error code 118 +@item +KRB5PLACEHOLD_119: KRB5 error code 119 +@item +KRB5PLACEHOLD_120: KRB5 error code 120 +@item +KRB5PLACEHOLD_121: KRB5 error code 121 +@item +KRB5PLACEHOLD_122: KRB5 error code 122 +@item +KRB5PLACEHOLD_123: KRB5 error code 123 +@item +KRB5PLACEHOLD_124: KRB5 error code 124 +@item +KRB5PLACEHOLD_125: KRB5 error code 125 +@item +KRB5PLACEHOLD_126: KRB5 error code 126 +@item +KRB5PLACEHOLD_127: KRB5 error code 127 +@item +KRB5_ERR_RCSID: (RCS Id string for the krb5 error table) +@item +KRB5_LIBOS_BADLOCKFLAG: Invalid flag for file lock mode +@item +KRB5_LIBOS_CANTREADPWD: Cannot read password +@item +KRB5_LIBOS_BADPWDMATCH: Password mismatch +@item +KRB5_LIBOS_PWDINTR: Password read interrupted +@item +KRB5_PARSE_ILLCHAR: Illegal character in component name +@item +KRB5_PARSE_MALFORMED: Malformed representation of principal +@item +KRB5_CONFIG_CANTOPEN: Can't open/find Kerberos configuration file +@item +KRB5_CONFIG_BADFORMAT: Improper format of Kerberos configuration file +@item +KRB5_CONFIG_NOTENUFSPACE: Insufficient space to return complete +information +@item +KRB5_BADMSGTYPE: Invalid message type specified for encoding +@item +KRB5_CC_BADNAME: Credential cache name malformed +@item +KRB5_CC_UNKNOWN_TYPE: Unknown credential cache type +@item +KRB5_CC_NOTFOUND: Matching credential not found +@item +KRB5_CC_END: End of credential cache reached +@item +KRB5_NO_TKT_SUPPLIED: Request did not supply a ticket +@item +KRB5KRB_AP_WRONG_PRINC: Wrong principal in request +@item +KRB5KRB_AP_ERR_TKT_INVALID: Ticket has invalid flag set +@item +KRB5_PRINC_NOMATCH: Requested principal and ticket don't match +@item +KRB5_KDCREP_MODIFIED: KDC reply did not match expectations +@item +KRB5_KDCREP_SKEW: Clock skew too great in KDC reply +@item +KRB5_IN_TKT_REALM_MISMATCH: Client/server realm mismatch in initial +ticket request +@item +KRB5_PROG_ETYPE_NOSUPP: Program lacks support for encryption type +@item +KRB5_PROG_KEYTYPE_NOSUPP: Program lacks support for key type +@item +KRB5_WRONG_ETYPE: Requested encryption type not used in message +@item +KRB5_PROG_SUMTYPE_NOSUPP: Program lacks support for checksum type +@item +KRB5_REALM_UNKNOWN: Cannot find KDC for requested realm +@item +KRB5_SERVICE_UNKNOWN: Kerberos service unknown +@item +KRB5_KDC_UNREACH: Cannot contact any KDC for requested realm +@item +KRB5_NO_LOCALNAME: No local name found for principal name +@item +KRB5_MUTUAL_FAILED: Mutual authentication failed +@item +KRB5_RC_TYPE_EXISTS: Replay cache type is already registered +@item +KRB5_RC_MALLOC: No more memory to allocate (in replay cache code) +@item +KRB5_RC_TYPE_NOTFOUND: Replay cache type is unknown +@item +KRB5_RC_UNKNOWN: Generic unknown RC error +@item +KRB5_RC_REPLAY: Message is a replay +@item +KRB5_RC_IO: Replay I/O operation failed XXX +@item +KRB5_RC_NOIO: Replay cache type does not support non-volatile storage +@item +KRB5_RC_PARSE: Replay cache name parse/format error +@item +KRB5_RC_IO_EOF: End-of-file on replay cache I/O +@item +KRB5_RC_IO_MALLOC: No more memory to allocate (in replay cache I/O +code) +@item +KRB5_RC_IO_PERM: Permission denied in replay cache code +@item +KRB5_RC_IO_IO: I/O error in replay cache i/o code +@item +KRB5_RC_IO_UNKNOWN: Generic unknown RC/IO error +@item +KRB5_RC_IO_SPACE: Insufficient system space to store replay information +@item +KRB5_TRANS_CANTOPEN: Can't open/find realm translation file +@item +KRB5_TRANS_BADFORMAT: Improper format of realm translation file +@item +KRB5_LNAME_CANTOPEN: Can't open/find lname translation database +@item +KRB5_LNAME_NOTRANS: No translation available for requested principal +@item +KRB5_LNAME_BADFORMAT: Improper format of translation database entry +@item +KRB5_CRYPTO_INTERNAL: Cryptosystem internal error +@item +KRB5_KT_BADNAME: Key table name malformed +@item +KRB5_KT_UNKNOWN_TYPE: Unknown Key table type +@item +KRB5_KT_NOTFOUND: Key table entry not found +@item +KRB5_KT_END: End of key table reached +@item +KRB5_KT_NOWRITE: Cannot write to specified key table +@item +KRB5_KT_IOERR: Error writing to key table +@item +KRB5_NO_TKT_IN_RLM: Cannot find ticket for requested realm +@item +KRB5DES_BAD_KEYPAR: DES key has bad parity +@item +KRB5DES_WEAK_KEY: DES key is a weak key +@item +KRB5_BAD_ENCTYPE: Bad encryption type +@item +KRB5_BAD_KEYSIZE: Key size is incompatible with encryption type +@item +KRB5_BAD_MSIZE: Message size is incompatible with encryption type +@item +KRB5_CC_TYPE_EXISTS: Credentials cache type is already registered. +@item +KRB5_KT_TYPE_EXISTS: Key table type is already registered. +@item +KRB5_CC_IO: Credentials cache I/O operation failed XXX +@item +KRB5_FCC_PERM: Credentials cache file permissions incorrect +@item +KRB5_FCC_NOFILE: No credentials cache found +@item +KRB5_FCC_INTERNAL: Internal credentials cache error +@item +KRB5_CC_WRITE: Error writing to credentials cache +@item +KRB5_CC_NOMEM: No more memory to allocate (in credentials cache code) +@item +KRB5_CC_FORMAT: Bad format in credentials cache +@item +KRB5_INVALID_FLAGS: Invalid KDC option combination (library internal +error) [for dual tgt library calls] +@item +KRB5_NO_2ND_TKT: Request missing second ticket [for dual tgt library +calls] +@item +KRB5_NOCREDS_SUPPLIED: No credentials supplied to library routine +@item +KRB5_SENDAUTH_BADAUTHVERS: Bad sendauth version was sent +@item +KRB5_SENDAUTH_BADAPPLVERS: Bad application version was sent (via +sendauth) +@item +KRB5_SENDAUTH_BADRESPONSE: Bad response (during sendauth exchange) +@item +KRB5_SENDAUTH_REJECTED: Server rejected authentication (during sendauth +exchange) +@item +KRB5_PREAUTH_BAD_TYPE: Unsupported preauthentication type +@item +KRB5_PREAUTH_NO_KEY: Required preauthentication key not supplied +@item +KRB5_PREAUTH_FAILED: Generic preauthentication failure +@item +KRB5_RCACHE_BADVNO: Unsupported replay cache format version number +@item +KRB5_CCACHE_BADVNO: Unsupported credentials cache format version number +@item +KRB5_KEYTAB_BADVNO: Unsupported key table format version number +@item +KRB5_PROG_ATYPE_NOSUPP: Program lacks support for address type +@item +KRB5_RC_REQUIRED: Message replay detection requires rcache parameter +@item +KRB5_ERR_BAD_HOSTNAME: Hostname cannot be canonicalized +@item +KRB5_ERR_HOST_REALM_UNKNOWN: Cannot determine realm for host +@item +KRB5_SNAME_UNSUPP_NAMETYPE: Conversion to service principal undefined +for name type +@item +KRB5KRB_AP_ERR_V4_REPLY: Initial Ticket response appears to be Version +4 error +@item +KRB5_REALM_CANT_RESOLVE: Cannot resolve KDC for requested realm +@item +KRB5_TKT_NOT_FORWARDABLE: Requesting ticket can't get forwardable +tickets +@item +KRB5_FWD_BAD_PRINCIPAL: Bad principal name while trying to forward +credentials +@item +KRB5_GET_IN_TKT_LOOP: Looping detected inside krb5_get_in_tkt +@item +KRB5_CONFIG_NODEFREALM: Configuration file does not specify default realm +@item +KRB5_SAM_UNSUPPORTED: Bad SAM flags in obtain_sam_padata +@item +KRB5_KT_NAME_TOOLONG: Keytab name too long +@item +KRB5_KT_KVNONOTFOUND: Key version number for principal in key table is incorrect +@item +KRB5_APPL_EXPIRED: This application has expired +@item +KRB5_LIB_EXPIRED: This Krb5 library has expired +@item +KRB5_CHPW_PWDNULL: New password cannot be zero length +@item +KRB5_CHPW_FAIL: Password change failed +@item +KRB5_KT_FORMAT: Bad format in keytab +@item +KRB5_NOPERM_ETYPE: Encryption type not permitted +@item +KRB5_CONFIG_ETYPE_NOSUPP: No supported encryption types (config file error?) +@item +KRB5_OBSOLETE_FN: Program called an obsolete, deleted function +@item +KRB5_EAI_FAIL: unknown getaddrinfo failure +@item +KRB5_EAI_NODATA: no data available for host/domain name +@item +KRB5_EAI_NONAME: host/domain name not found +@item +KRB5_EAI_SERVICE: service name unknown +@item +KRB5_ERR_NUMERIC_REALM: Cannot determine realm for numeric host address +@end enumerate + +@node Kerberos V5 Database Library Error Codes, Kerberos V5 Magic Numbers Error Codes, Kerberos V5 Library Error Codes, Errors +@appendixsubsec Kerberos V5 Database Library Error Codes + +This is the Kerberos v5 database library error code table. + +@c error table numbering starts at 0 +@enumerate 0 +@item +KRB5_KDB_RCSID: (RCS Id string for the kdb error table) +@item +KRB5_KDB_INUSE: Entry already exists in database +@item +KRB5_KDB_UK_SERROR: Database store error +@item +KRB5_KDB_UK_RERROR: Database read error +@item +KRB5_KDB_UNAUTH: Insufficient access to perform requested operation +@item +KRB5_KDB_NOENTRY: No such entry in the database +@item +KRB5_KDB_ILL_WILDCARD: Illegal use of wildcard +@item +KRB5_KDB_DB_INUSE: Database is locked or in use--try again later +@item +KRB5_KDB_DB_CHANGED: Database was modified during read +@item +KRB5_KDB_TRUNCATED_RECORD: Database record is incomplete or corrupted +@item +KRB5_KDB_RECURSIVELOCK: Attempt to lock database twice +@item +KRB5_KDB_NOTLOCKED: Attempt to unlock database when not locked +@item +KRB5_KDB_BADLOCKMODE: Invalid kdb lock mode +@item +KRB5_KDB_DBNOTINITED: Database has not been initialized +@item +KRB5_KDB_DBINITED: Database has already been initialized +@item +KRB5_KDB_ILLDIRECTION: Bad direction for converting keys +@item +KRB5_KDB_NOMASTERKEY: Cannot find master key record in database +@item +KRB5_KDB_BADMASTERKEY: Master key does not match database +@item +KRB5_KDB_INVALIDKEYSIZE: Key size in database is invalid +@item +KRB5_KDB_CANTREAD_STORED: Cannot find/read stored master key +@item +KRB5_KDB_BADSTORED_MKEY: Stored master key is corrupted +@item +KRB5_KDB_CANTLOCK_DB: Insufficient access to lock database +@item +KRB5_KDB_DB_CORRUPT: Database format error +@item +KRB5_KDB_BAD_VERSION: Unsupported version in database entry +@item +KRB5_KDB_BAD_SALTTYPE: Unsupported salt type +@item +KRB5_KDB_BAD_ENCTYPE: Unsupported encryption type +@item +KRB5_KDB_BAD_CREATEFLAGS: Bad database creation flags +@item +KRB5_KDB_NO_PERMITTED_KEY: No matching key in entry having a permitted enc type +@item +KRB5_KDB_NO_MATCHING_KEY: No matching key in entry +@item +KRB5_KDB_SERVER_INTERNAL_ERR: Server error +@item +KRB5_KDB_ACCESS_ERROR: Unable to access Kerberos database +@item +KRB5_KDB_INTERNAL_ERROR:Kerberos database internal error +@item +KRB5_KDB_CONSTRAINT_VIOLATION:Kerberos database constraints violated +@end enumerate + +@node Kerberos V5 Magic Numbers Error Codes, ASN.1 Error Codes, Kerberos V5 Database Library Error Codes, Errors +@appendixsubsec Kerberos V5 Magic Numbers Error Codes + +This is the Kerberos v5 magic numbers error code table. + +@c error table numbering starts at 0 +@enumerate 0 +@item +KV5M_NONE: Kerberos V5 magic number table +@item +KV5M_PRINCIPAL: Bad magic number for krb5_principal structure +@item +KV5M_DATA: Bad magic number for krb5_data structure +@item +KV5M_KEYBLOCK: Bad magic number for krb5_keyblock structure +@item +KV5M_CHECKSUM: Bad magic number for krb5_checksum structure +@item +KV5M_ENCRYPT_BLOCK: Bad magic number for krb5_encrypt_block structure +@item +KV5M_ENC_DATA: Bad magic number for krb5_enc_data structure +@item +KV5M_CRYPTOSYSTEM_ENTRY: Bad magic number for krb5_cryp@-to@-sys@-tem_entry +structure +@item +KV5M_CS_TABLE_ENTRY: Bad magic number for krb5_cs_table_entry structure +@item +KV5M_CHECKSUM_ENTRY: Bad magic number for krb5_check@-sum_en@-try structure +@item +KV5M_AUTHDATA: Bad magic number for krb5_authdata structure +@item +KV5M_TRANSITED: Bad magic number for krb5_transited structure +@item +KV5M_ENC_TKT_PART: Bad magic number for krb5_enc_tkt_part structure +@item +KV5M_TICKET: Bad magic number for krb5_ticket structure +@item +KV5M_AUTHENTICATOR: Bad magic number for krb5_authenticator structure +@item +KV5M_TKT_AUTHENT: Bad magic number for krb5_tkt_authent structure +@item +KV5M_CREDS: Bad magic number for krb5_creds structure +@item +KV5M_LAST_REQ_ENTRY: Bad magic number for krb5_last_req_entry structure +@item +KV5M_PA_DATA: Bad magic number for krb5_pa_data structure +@item +KV5M_KDC_REQ: Bad magic number for krb5_kdc_req structure +@item +KV5M_ENC_KDC_REP_PART: Bad magic number for @* +krb5_enc_kdc_rep_part structure +@item +KV5M_KDC_REP: Bad magic number for krb5_kdc_rep structure +@item +KV5M_ERROR: Bad magic number for krb5_error structure +@item +KV5M_AP_REQ: Bad magic number for krb5_ap_req structure +@item +KV5M_AP_REP: Bad magic number for krb5_ap_rep structure +@item +KV5M_AP_REP_ENC_PART: Bad magic number for @* +krb5_ap_rep_enc_part structure +@item +KV5M_RESPONSE: Bad magic number for krb5_response structure +@item +KV5M_SAFE: Bad magic number for krb5_safe structure +@item +KV5M_PRIV: Bad magic number for krb5_priv structure +@item +KV5M_PRIV_ENC_PART: Bad magic number for krb5_priv_enc_part structure +@item +KV5M_CRED: Bad magic number for krb5_cred structure +@item +KV5M_CRED_INFO: Bad magic number for krb5_cred_info structure +@item +KV5M_CRED_ENC_PART: Bad magic number for krb5_cred_enc_part structure +@item +KV5M_PWD_DATA: Bad magic number for krb5_pwd_data structure +@item +KV5M_ADDRESS: Bad magic number for krb5_address structure +@item +KV5M_KEYTAB_ENTRY: Bad magic number for krb5_keytab_entry structure +@item +KV5M_CONTEXT: Bad magic number for krb5_context structure +@item +KV5M_OS_CONTEXT: Bad magic number for krb5_os_context structure +@item +KV5M_ALT_METHOD: Bad magic number for krb5_alt_method structure +@item +KV5M_ETYPE_INFO_ENTRY: Bad magic number for @* +krb5_etype_info_entry structure +@item +KV5M_DB_CONTEXT: Bad magic number for krb5_db_context structure +@item +KV5M_AUTH_CONTEXT: Bad magic number for krb5_auth_context structure +@item +KV5M_KEYTAB: Bad magic number for krb5_keytab structure +@item +KV5M_RCACHE: Bad magic number for krb5_rcache structure +@item +KV5M_CCACHE: Bad magic number for krb5_ccache structure +@item +KV5M_PREAUTH_OPS: Bad magic number for krb5_preauth_ops +@item +KV5M_SAM_CHALLENGE: Bad magic number for krb5_sam_challenge +@item +KV5M_SAM_KEY: Bad magic number for krb5_sam_key +@item +KV5M_ENC_SAM_RESPONSE_ENC: Bad magic number for @* +krb5_enc_sam_response_enc +@item +KV5M_SAM_RESPONSE: Bad magic number for krb5_sam_response +@item +KV5M_PREDICTED_SAM_RESPONSE: Bad magic number for +krb5_predicted_sam_response +@item +KV5M_PASSWD_PHRASE_ELEMENT: Bad magic number for passwd_phrase_element +@item +KV5M_GSS_OID: Bad magic number for GSSAPI OID +@item +KV5M_GSS_QUEUE: Bad magic number for GSSAPI QUEUE +@end enumerate + +@node ASN.1 Error Codes, GSSAPI Error Codes, Kerberos V5 Magic Numbers Error Codes, Errors +@appendixsubsec ASN.1 Error Codes + +@c error table numbering starts at 0 +@enumerate 0 +@item +ASN1_BAD_TIMEFORMAT: ASN.1 failed call to system time library +@item +ASN1_MISSING_FIELD: ASN.1 structure is missing a required field +@item +ASN1_MISPLACED_FIELD: ASN.1 unexpected field number +@item +ASN1_TYPE_MISMATCH: ASN.1 type numbers are inconsistent +@item +ASN1_OVERFLOW: ASN.1 value too large +@item +ASN1_OVERRUN: ASN.1 encoding ended unexpectedly +@item +ASN1_BAD_ID: ASN.1 identifier doesn't match expected value +@item +ASN1_BAD_LENGTH: ASN.1 length doesn't match expected value +@item +ASN1_BAD_FORMAT: ASN.1 badly-formatted encoding +@item +ASN1_PARSE_ERROR: ASN.1 parse error +@item +ASN1_BAD_GMTIME: ASN.1 bad return from gmtime +@item +ASN1_MISMATCH_INDEF: ASN.1 non-constructed indefinite encoding +@item +ASN1_MISSING_EOC: ASN.1 missing expected EOC +@end enumerate + +@node GSSAPI Error Codes, , ASN.1 Error Codes, Errors +@appendixsubsec GSSAPI Error Codes + +Generic GSSAPI Errors: + +@c error table numbering starts at 0 +@enumerate 0 +@item +G_BAD_SERVICE_NAME: No @ in SERVICE-NAME name string +@item +G_BAD_STRING_UID: STRING-UID-NAME contains nondigits +@item +G_NOUSER: UID does not resolve to username +@item +G_VALIDATE_FAILED: Validation error +@item +G_BUFFER_ALLOC: Couldn't allocate gss_buffer_t data +@item +G_BAD_MSG_CTX: Message context invalid +@item +G_WRONG_SIZE: Buffer is the wrong size +@item +G_BAD_USAGE: Credential usage type is unknown +@item +G_UNKNOWN_QOP: Unknown quality of protection specified +@item +G_BAD_HOSTNAME: Hostname in SERVICE-NAME string could not be +canonicalized +@item +G_WRONG_MECH: Mechanism is incorrect +@item +G_BAD_TOK_HEADER: Token header is malformed or corrupt +@item +G_BAD_DIRECTION: Packet was replayed in wrong direction +@item +G_TOK_TRUNC: Token is missing data +@item +G_REFLECT: Token was reflected +@item +G_WRONG_TOKID: Received token ID does not match expected token ID +@end enumerate + +Kerberos 5 GSSAPI Errors: + +@c error table numbering starts at 0 +@enumerate 0 +@item +KG_CCACHE_NOMATCH: Principal in credential cache does not match desired +name +@item +KG_KEYTAB_NOMATCH: No principal in keytab matches desired name +@item +KG_TGT_MISSING: Credential cache has no TGT +@item +KG_NO_SUBKEY: Authenticator has no subkey +@item +KG_CONTEXT_ESTABLISHED: Context is already fully established +@item +KG_BAD_SIGN_TYPE: Unknown signature type in token +@item +KG_BAD_LENGTH: Invalid field length in token +@item +KG_CTX_INCOMPLETE: Attempt to use incomplete security context +@item +KG_CONTEXT: Bad magic number for krb5_gss_ctx_id_t +@item +KG_CRED: Bad magic number for krb5_gss_cred_id_t +@item +KG_ENC_DESC: Bad magic number for krb5_gss_enc_desc +@item +KG_BAD_SEQ: Sequence number in token is corrupt +@item +KG_EMPTY_CCACHE: Credential cache is empty +@item +KG_NO_CTYPES: Acceptor and Initiator share no checksum types +@end enumerate + +@node kadmin Time Zones, , Errors, Appendix +@appendixsec kadmin Time Zones + +This is a complete listing of the time zones recognized by the +@code{kadmin} command. + +@table @b +@itemx gmt +Greenwich Mean Time +@itemx ut, utc +Universal Time (Coordinated). +@itemx wet +Western European Time. (Same as GMT.) +@itemx bst +British Summer Time. (1 hour ahead of GMT.) +@itemx wat +West Africa Time. (1 hour behind GMT.) +@itemx at +Azores Time. (2 hours behind GMT.) +@itemx bst +Brazil Standard Time. (3 hours behind GMT.) Note that the abbreviation +BST also stands for British Summer Time. +@itemx gst +Greenland Standard Time. (3 hours behind GMT.) Note that the +abbreviation GST also stands for Guam Standard Time. +@itemx nft +Newfoundland Time. (3.5 hours behind GMT.) +@itemx nst +Newfoundland Standard Time. (3.5 hours behind GMT.) +@itemx ndt +Newfoundland Daylight Time. (2.5 hours behind GMT.) +@itemx ast +Atlantic Standard Time. (4 hours behind GMT.) +@itemx adt +Atlantic Daylight Time. (3 hours behind GMT.) +@itemx est +Eastern Standard Time. (5 hours behind GMT.) +@itemx edt +Eastern Daylight Time. (4 hours behind GMT.) +@itemx cst +Central Standard Time. (6 hours behind GMT.) +@itemx cdt +Central Daylight Time. (5 hours behind GMT.) +@itemx mst +Mountain Standard Time. (7 hours behind GMT.) +@itemx mdt +Mountain Daylight Time. (6 hours behind GMT.) +@itemx pst +Pacific Standard Time. (8 hours behind GMT.) +@itemx pdt +Pacific Daylight Time. (7 hours behind GMT.) +@itemx yst +Yukon Standard Time. (9 hours behind GMT.) +@itemx ydt +Yukon Daylight Time. (8 hours behind GMT.) +@itemx hst +Hawaii Standard Time. (10 hours behind GMT.) +@itemx hdt +Hawaii Daylight Time. (9 hours behind GMT.) +@itemx cat +Central Alaska Time. (10 hours behind GMT.) +@itemx ahst +Alaska-Hawaii Standard Time. (10 hours behind GMT.) +@itemx nt +Nome Time. (11 hours behind GMT.) +@itemx idlw +International Date Line West Time. (12 hours behind GMT.) +@itemx cet +Central European Time. (1 hour ahead of GMT.) +@itemx met +Middle European Time. (1 hour ahead of GMT.) +@itemx mewt +Middle European Winter Time. (1 hour ahead of GMT.) +@itemx mest +Middle European Summer Time. (2 hours ahead of GMT.) +@itemx swt +Swedish Winter Time. (1 hour ahead of GMT.) +@itemx sst +Swedish Summer Time. (1 hours ahead of GMT.) +@itemx fwt +French Winter Time. (1 hour ahead of GMT.) +@itemx fst +French Summer Time. (2 hours ahead of GMT.) +@itemx eet +Eastern Europe Time; Russia Zone 1. (2 hours ahead of GMT.) +@itemx bt +Baghdad Time; Russia Zone 2. (3 hours ahead of GMT.) +@itemx it +Iran Time. (3.5 hours ahead of GMT.) +@itemx zp4 +Russia Zone 3. (4 hours ahead of GMT.) +@itemx zp5 +Russia Zone 4. (5 hours ahead of GMT.) +@itemx ist +Indian Standard Time. (5.5 hours ahead of GMT.) +@itemx zp6 +Russia Zone 5. (6 hours ahead of GMT.) +@itemx nst +North Sumatra Time. (6.5 hours ahead of GMT.) Note that the +abbreviation NST is also used for Newfoundland Stanard Time. +@itemx sst +South Sumatra Time; Russia Zone 6. (7 hours ahead of GMT.) Note that +SST is also Swedish Summer Time. +@itemx wast +West Australian Standard Time. (7 hours ahead of GMT.) +@itemx wadt +West Australian Daylight Time. (8 hours ahead of GMT.) +@itemx jt +Java Time. (7.5 hours ahead of GMT.) +@itemx cct +China Coast Time; Russia Zone 7. (8 hours ahead of GMT.) +@itemx jst +Japan Standard time; Russia Zone 8. (9 hours ahead of GMT.) +@itemx kst +Korean Standard Time. (9 hours ahead of GMT.) +@itemx cast +Central Australian Standard Time. (9.5 hours ahead of GMT.) +@itemx cadt +Central Australian Daylight Time. (10.5 hours ahead of GMT.) +@itemx east +Eastern Australian Standard Time. (10 hours ahead of GMT.) +@itemx eadt +Eastern Australian Daylight Time. (11 hours ahead of GMT.) +@itemx gst +Guam Standard Time; Russia Zone 9. (10 hours ahead of GMT.) +@itemx kdt +Korean Daylight Time. (10 hours ahead of GMT.) +@itemx nzt +New Zealand Time. (12 hours ahead of GMT.) +@itemx nzst +New Zealand Standard Time. (12 hours ahead of GMT.) +@itemx nzdt +New Zealand Daylight Time. (13 hours ahead of GMT.) +@itemx idle +International Date Line East. (12 hours ahead of GMT.) +@end table + +@contents +@bye + diff --git a/krb5-1-6/doc/api/.cvsignore b/krb5-1-6/doc/api/.cvsignore new file mode 100644 index 000000000..8625a6f31 --- /dev/null +++ b/krb5-1-6/doc/api/.cvsignore @@ -0,0 +1,10 @@ +library.ps +library.ind +library.log +library.idx +library.aux +library.toc +lib1.stamp +library.dvi +libdes.dvi +libdes.ps diff --git a/krb5-1-6/doc/api/Makefile b/krb5-1-6/doc/api/Makefile new file mode 100644 index 000000000..2d5d6b784 --- /dev/null +++ b/krb5-1-6/doc/api/Makefile @@ -0,0 +1,40 @@ +.SUFFIXES: .tex .dvi .ps + +SHELL=/bin/sh + +STYLES= fixunder.sty functions.sty krb5idx.sty +LIBTEX= library.tex intro.tex tables.tex errors.tex krb5.tex ccache.tex \ + rcache.tex keytab.tex libos.tex free.tex + +DESTEX= libdes.tex + +all: library.ps libdes.ps + + +libdes.dvi: $(DESTEX) $(STYLES) + +library.ps: library.dvi + +clean: + rm -f *.toc *.log *.idx *.ind *.aux *.ilg lib1.stamp + +really-clean: clean + rm -f *.dvi *.ps + + +library.dvi: lib1.stamp $(LIBTEX) $(STYLES) + latex library + +lib1.stamp: $(LIBTEX) $(STYLES) + touch library.ind + latex library + makeindex -s krb5.ist library.idx + date > lib1.stamp + +.tex.dvi: + latex $* + + +.dvi.ps: + dvips $*.dvi -o + diff --git a/krb5-1-6/doc/api/ccache.tex b/krb5-1-6/doc/api/ccache.tex new file mode 100644 index 000000000..d6e24e834 --- /dev/null +++ b/krb5-1-6/doc/api/ccache.tex @@ -0,0 +1,239 @@ +The credentials cache functions (some of which are macros which call to +specific types of credentials caches) deal with storing credentials +(tickets, session keys, and other identifying information) in a +semi-permanent store for later use by different programs. + +\begin{funcdecl}{krb5_cc_resolve}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{char *}{string_name} +\funcout +\funcarg{krb5_ccache *}{id} +\end{funcdecl} + +Fills in \funcparam{id} with a ccache identifier which corresponds to +the name in \funcparam{string_name}. + +Requires that \funcparam{string_name} be of the form ``type:residual'' and +``type'' is a type known to the library. + +\begin{funcdecl}{krb5_cc_gen_new}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_cc_ops *}{ops} +\funcout +\funcarg{krb5_ccache *}{id} +\end{funcdecl} + + +Fills in \funcparam{id} with a unique ccache identifier of a type defined by +\funcparam{ops}. The cache is left unopened. + +\begin{funcdecl}{krb5_cc_register}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_cc_ops *}{ops} +\funcarg{krb5_boolean}{override} +\end{funcdecl} + +Adds a new cache type identified and implemented by \funcparam{ops} to +the set recognized by \funcname{krb5_cc_resolve}. +If \funcparam{override} is FALSE, a ticket cache type named +\funcparam{ops{\ptsto}prefix} must not be known. + +\begin{funcdecl}{krb5_cc_get_name}{char *}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_ccache}{id} +\end{funcdecl} + +Returns the name of the ccache denoted by \funcparam{id}. + +\begin{funcdecl}{krb5_cc_default_name}{char *}{\funcinout} +\funcarg{krb5_context}{context} +\end{funcdecl} + +Returns the name of the default credentials cache; this may be equivalent to +\funcnamenoparens{getenv}({\tt "KRB5CCACHE"}) with an appropriate fallback. + +\begin{funcdecl}{krb5_cc_default}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_ccache *}{ccache} +\end{funcdecl} + +Equivalent to +\funcnamenoparens{krb5_cc_resolve}(\funcparam{context}, +\funcname{krb5_cc_default_name}, +\funcparam{ccache}). + +\begin{funcdecl}{krb5_cc_initialize}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ccache}{id} +\funcin +\funcarg{krb5_principal}{primary_principal} +\end{funcdecl} + +Creates/refreshes a credentials cache identified by \funcparam{id} with +primary principal set to \funcparam{primary_principal}. +If the credentials cache already exists, its contents are destroyed. + +Errors: permission errors, system errors. + +Modifies: cache identified by \funcparam{id}. + +\begin{funcdecl}{krb5_cc_destroy}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ccache}{id} +\end{funcdecl} + +Destroys the credentials cache identified by \funcparam{id}, invalidates +\funcparam{id}, and releases any other resources acquired during use of +the credentials cache. Requires that \funcparam{id} identifies a valid +credentials cache. After return, \funcparam{id} must not be used unless +it is first reinitialized using \funcname{krb5_cc_resolve} or +\funcname{krb5_cc_gen_new}. + +Errors: permission errors. + +\begin{funcdecl}{krb5_cc_close}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ccache}{id} +\end{funcdecl} + +Closes the credentials cache \funcparam{id}, invalidates +\funcparam{id}, and releases \funcparam{id} and any other resources +acquired during use of the credentials cache. Requires that +\funcparam{id} identifies a valid credentials cache. After return, +\funcparam{id} must not be used unless it is first reinitialized using +\funcname{krb5_cc_resolve} or \funcname{krb5_cc_gen_new}. + + +\begin{funcdecl}{krb5_cc_store_cred}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_ccache}{id} +\funcarg{krb5_creds *}{creds} +\end{funcdecl} + +Stores \funcparam{creds} in the cache \funcparam{id}, tagged with +\funcparam{creds{\ptsto}client}. +Requires that \funcparam{id} identifies a valid credentials cache. + +Errors: permission errors, storage failure errors. + +\begin{funcdecl}{krb5_cc_retrieve_cred}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_ccache}{id} +\funcarg{krb5_flags}{whichfields} +\funcarg{krb5_creds *}{mcreds} +\funcout +\funcarg{krb5_creds *}{creds} +\end{funcdecl} + +Searches the cache \funcparam{id} for credentials matching +\funcparam{mcreds}. The fields which are to be matched are specified by +set bits in \funcparam{whichfields}, and always include the principal +name \funcparam{mcreds{\ptsto}server}. +Requires that \funcparam{id} identifies a valid credentials cache. + +If at least one match is found, one of the matching credentials is +returned in \funcparam{*creds}. The credentials should be freed using +\funcname{krb5_free_credentials}. + +Errors: error code if no matches found. + +\begin{funcdecl}{krb5_cc_get_principal}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_ccache}{id} +\funcarg{krb5_principal *}{principal} +\end{funcdecl} + +Retrieves the primary principal of the credentials cache (as +set by the \funcname{krb5_cc_initialize} request) +The primary principal is filled into \funcparam{*principal}; the caller +should release this memory by calling \funcname{krb5_free_principal} on +\funcparam{*principal} when finished. + +Requires that \funcparam{id} identifies a valid credentials cache. + +\begin{funcdecl}{krb5_cc_start_seq_get}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ccache}{id} +\funcout +\funcarg{krb5_cc_cursor *}{cursor} +\end{funcdecl} + +Prepares to sequentially read every set of cached credentials. +\funcparam{cursor} is filled in with a cursor to be used in calls to +\funcname{krb5_cc_next_cred}. + +\begin{funcdecl}{krb5_cc_next_cred}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ccache}{id} +\funcout +\funcarg{krb5_creds *}{creds} +\funcinout +\funcarg{krb5_cc_cursor *}{cursor} +\end{funcdecl} + +Fetches the next entry from \funcparam{id}, returning its values in +\funcparam{*creds}, and updates \funcparam{*cursor} for the next request. +Requires that \funcparam{id} identifies a valid credentials cache and +\funcparam{*cursor} be a cursor returned by +\funcname{krb5_cc_start_seq_get} or a subsequent call to +\funcname{krb5_cc_next_cred}. + +Errors: error code if no more cache entries. + +\begin{funcdecl}{krb5_cc_end_seq_get}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ccache}{id} +\funcarg{krb5_cc_cursor *}{cursor} +\end{funcdecl} + +Finishes sequential processing mode and invalidates \funcparam{*cursor}. +\funcparam{*cursor} must never be re-used after this call. + +Requires that \funcparam{id} identifies a valid credentials cache and +\funcparam{*cursor} be a cursor returned by +\funcname{krb5_cc_start_seq_get} or a subsequent call to +\funcname{krb5_cc_next_cred}. + +Errors: may return error code if \funcparam{*cursor} is invalid. + + +\begin{funcdecl}{krb5_cc_remove_cred}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_ccache}{id} +\funcarg{krb5_flags}{which} +\funcarg{krb5_creds *}{cred} +\end{funcdecl} + +Removes any credentials from \funcparam{id} which match the principal +name {cred{\ptsto}server} and the fields in \funcparam{cred} masked by +\funcparam{which}. +Requires that \funcparam{id} identifies a valid credentials cache. + +Errors: returns error code if nothing matches; returns error code if +couldn't delete. + +\begin{funcdecl}{krb5_cc_set_flags}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ccache}{id} +\funcin +\funcarg{krb5_flags}{flags} +\end{funcdecl} + +Sets the flags on the cache \funcparam{id} to \funcparam{flags}. Useful +flags are defined in {\tt }. + +\begin{funcdecl}{krb5_get_notification_message}{unsigned int}{\funcvoid} +\end{funcdecl} + +Intended for use by Windows. Will register a unique message type using +\funcname{RegisterWindowMessage} which will be notified whenever the +cache changes. This will allow all processes to recheck their caches. diff --git a/krb5-1-6/doc/api/errors.tex b/krb5-1-6/doc/api/errors.tex new file mode 100644 index 000000000..ad90cac53 --- /dev/null +++ b/krb5-1-6/doc/api/errors.tex @@ -0,0 +1,310 @@ +\subsection{error_table krb5} + +% $Source$ +% $Author$ + +The Kerberos v5 library error code table follows. +Protocol error codes are ERROR_TABLE_BASE_krb5 + the protocol error +code number. Other error codes start at ERROR_TABLE_BASE_krb5 + 128. + +\begin{small} +\begin{tabular}{ll} +{\sc krb5kdc_err_none }& No error \\ +{\sc krb5kdc_err_name_exp }& Client's entry in database has expired \\ +{\sc krb5kdc_err_service_exp }& Server's entry in database has expired \\ +{\sc krb5kdc_err_bad_pvno }& Requested protocol version not supported \\ +{\sc krb5kdc_err_c_old_mast_kvno }& \parbox[t]{2in}{Client's key is encrypted in an old master key} \\ +{\sc krb5kdc_err_s_old_mast_kvno }& \parbox[t]{2in}{Server's key is encrypted in an old master key} \\ +{\sc krb5kdc_err_c_principal_unknown }& Client not found in Kerberos database \\ +{\sc krb5kdc_err_s_principal_unknown }& Server not found in Kerberos database \\ +{\sc krb5kdc_err_principal_not_unique }&\parbox[t]{2in}{\raggedright{Principal has multiple entries in Kerberos database}} \\ +{\sc krb5kdc_err_null_key }& Client or server has a null key \\ +{\sc krb5kdc_err_cannot_postdate }& Ticket is ineligible for postdating \\ +{\sc krb5kdc_err_never_valid }& \parbox[t]{2in}{Requested effective lifetime is negative or too short} \\ +{\sc krb5kdc_err_policy }& KDC policy rejects request \\ +{\sc krb5kdc_err_badoption }& KDC can't fulfill requested option \\ +{\sc krb5kdc_err_etype_nosupp }& KDC has no support for encryption type \\ +{\sc krb5kdc_err_sumtype_nosupp }& KDC has no support for checksum type \\ +{\sc krb5kdc_err_padata_type_nosupp }& KDC has no support for padata type \\ +{\sc krb5kdc_err_trtype_nosupp }& KDC has no support for transited type \\ +{\sc krb5kdc_err_client_revoked }& Clients credentials have been revoked \\ +{\sc krb5kdc_err_service_revoked }& Credentials for server have been revoked \\ +{\sc krb5kdc_err_tgt_revoked }& TGT has been revoked \\ +{\sc krb5kdc_err_client_notyet }& Client not yet valid - try again later \\ +{\sc krb5kdc_err_service_notyet }& Server not yet valid - try again later \\ +{\sc krb5kdc_err_key_exp }& Password has expired \\ +{\sc krb5kdc_preauth_failed }& Preauthentication failed \\ +{\sc krb5kdc_err_preauth_require }& Additional pre-authentication required \\ +{\sc krb5kdc_err_server_nomatch }& Requested server and ticket don't match \\ +\multicolumn{2}{c}{error codes 27-30 are currently placeholders}\\ + +\end{tabular} + +\begin{tabular}{ll} +{\sc krb5krb_ap_err_bad_integrity }& Decrypt integrity check failed \\ +{\sc krb5krb_ap_err_tkt_expired }& Ticket expired \\ +{\sc krb5krb_ap_err_tkt_nyv }& Ticket not yet valid \\ +{\sc krb5krb_ap_err_repeat }& Request is a replay \\ +{\sc krb5krb_ap_err_not_us }& The ticket isn't for us \\ +{\sc krb5krb_ap_err_badmatch }& Ticket/authenticator don't match \\ +{\sc krb5krb_ap_err_skew }& Clock skew too great \\ +{\sc krb5krb_ap_err_badaddr }& Incorrect net address \\ +{\sc krb5krb_ap_err_badversion }& Protocol version mismatch \\ +{\sc krb5krb_ap_err_msg_type }& Invalid message type \\ +{\sc krb5krb_ap_err_modified }& Message stream modified \\ +{\sc krb5krb_ap_err_badorder }& Message out of order \\ +{\sc krb5placehold_43 }& KRB5 error code 43 \\ +{\sc krb5krb_ap_err_badkeyver }& Key version is not available \\ +{\sc krb5krb_ap_err_nokey }& Service key not available \\ +{\sc krb5krb_ap_err_mut_fail }& Mutual authentication failed \\ +{\sc krb5krb_ap_err_baddirection }& Incorrect message direction \\ +{\sc krb5krb_ap_err_method }& Alternative authentication method required \\ +{\sc krb5krb_ap_err_badseq }& Incorrect sequence number in message \\ +{\sc krb5krb_ap_err_inapp_cksum }& Inappropriate type of checksum in message \\ +\multicolumn{2}{c}{error codes 51-59 are currently placeholders} \\ + +{\sc krb5krb_err_generic }& Generic error (see e-text) \\ +{\sc krb5krb_err_field_toolong }& Field is too long for this implementation \\ +\multicolumn{2}{c}{error codes 62-127 are currently placeholders} \\ +\end{tabular} + +\begin{tabular}{ll} +{\sc krb5_libos_badlockflag }& Invalid flag for file lock mode \\ +{\sc krb5_libos_cantreadpwd }& Cannot read password \\ +{\sc krb5_libos_badpwdmatch }& Password mismatch \\ +{\sc krb5_libos_pwdintr }& Password read interrupted \\ +{\sc krb5_parse_illchar }& Illegal character in component name \\ +{\sc krb5_parse_malformed }& Malformed representation of principal \\ +{\sc krb5_config_cantopen }& Can't open/find configuration file \\ +{\sc krb5_config_badformat }& Improper format of configuration file \\ +{\sc krb5_config_notenufspace }& Insufficient space to return complete information \\ +{\sc krb5_badmsgtype }& Invalid message type specified for encoding \\ +{\sc krb5_cc_badname }& Credential cache name malformed \\ +{\sc krb5_cc_unknown_type }& Unknown credential cache type \\ +{\sc krb5_cc_notfound }& Matching credential not found \\ +{\sc krb5_cc_end }& End of credential cache reached \\ +{\sc krb5_no_tkt_supplied }& Request did not supply a ticket \\ +{\sc krb5krb_ap_wrong_princ }& Wrong principal in request \\ +{\sc krb5krb_ap_err_tkt_invalid }& Ticket has invalid flag set \\ +{\sc krb5_princ_nomatch }& Requested principal and ticket don't match \\ +{\sc krb5_kdcrep_modified }& KDC reply did not match expectations \\ +{\sc krb5_kdcrep_skew }& Clock skew too great in KDC reply \\ +{\sc krb5_in_tkt_realm_mismatch }&\parbox[t]{2.5 in}{Client/server realm +mismatch in initial ticket requst}\\ + +{\sc krb5_prog_etype_nosupp }& Program lacks support for encryption type \\ +{\sc krb5_prog_keytype_nosupp }& Program lacks support for key type \\ +{\sc krb5_wrong_etype }& Requested encryption type not used in message \\ +{\sc krb5_prog_sumtype_nosupp }& Program lacks support for checksum type \\ +{\sc krb5_realm_unknown }& Cannot find KDC for requested realm \\ +{\sc krb5_service_unknown }& Kerberos service unknown \\ +{\sc krb5_kdc_unreach }& Cannot contact any KDC for requested realm \\ +{\sc krb5_no_localname }& No local name found for principal name \\ + +%\multicolumn{1}{c}{some of these should be combined/supplanted by system codes} \\ +\end{tabular} + +\begin{tabular}{ll} +{\sc krb5_rc_type_exists }& Replay cache type is already registered \\ +{\sc krb5_rc_malloc }& No more memory to allocate (in replay cache code) \\ +{\sc krb5_rc_type_notfound }& Replay cache type is unknown \\ +{\sc krb5_rc_unknown }& Generic unknown RC error \\ +{\sc krb5_rc_replay }& Message is a replay \\ +{\sc krb5_rc_io }& Replay I/O operation failed XXX \\ +{\sc krb5_rc_noio }& \parbox[t]{3in}{Replay cache type does not support non-volatile storage} \\ +{\sc krb5_rc_parse }& Replay cache name parse/format error \\ +{\sc krb5_rc_io_eof }& End-of-file on replay cache I/O \\ +{\sc krb5_rc_io_malloc }& \parbox[t]{3in}{No more memory to allocate (in replay cache I/O code)}\\ +{\sc krb5_rc_io_perm }& Permission denied in replay cache code \\ +{\sc krb5_rc_io_io }& I/O error in replay cache i/o code \\ +{\sc krb5_rc_io_unknown }& Generic unknown RC/IO error \\ +{\sc krb5_rc_io_space }& Insufficient system space to store replay information \\ +{\sc krb5_trans_cantopen }& Can't open/find realm translation file \\ +{\sc krb5_trans_badformat }& Improper format of realm translation file \\ +{\sc krb5_lname_cantopen }& Can't open/find lname translation database \\ +{\sc krb5_lname_notrans }& No translation available for requested principal \\ +{\sc krb5_lname_badformat }& Improper format of translation database entry \\ +{\sc krb5_crypto_internal }& Cryptosystem internal error \\ +{\sc krb5_kt_badname }& Key table name malformed \\ +{\sc krb5_kt_unknown_type }& Unknown Key table type \\ +{\sc krb5_kt_notfound }& Key table entry not found \\ +{\sc krb5_kt_end }& End of key table reached \\ +{\sc krb5_kt_nowrite }& Cannot write to specified key table \\ +{\sc krb5_kt_ioerr }& Error writing to key table \\ +{\sc krb5_no_tkt_in_rlm }& Cannot find ticket for requested realm \\ +{\sc krb5des_bad_keypar }& DES key has bad parity \\ +{\sc krb5des_weak_key }& DES key is a weak key \\ +{\sc krb5_bad_keytype }& Keytype is incompatible with encryption type \\ +{\sc krb5_bad_keysize }& Key size is incompatible with encryption type \\ +{\sc krb5_bad_msize }& Message size is incompatible with encryption type \\ +{\sc krb5_cc_type_exists }& Credentials cache type is already registered. \\ +{\sc krb5_kt_type_exists }& Key table type is already registered. \\ +{\sc krb5_cc_io }& Credentials cache I/O operation failed XXX \\ +{\sc krb5_fcc_perm }& Credentials cache file permissions incorrect \\ +{\sc krb5_fcc_nofile }& No credentials cache file found \\ +{\sc krb5_fcc_internal }& Internal file credentials cache error \\ +{\sc krb5_cc_nomem }& \parbox[t]{3in}{No more memory to allocate (in credentials cache code)}\\ +\end{tabular} + +\begin{tabular}{ll} +\multicolumn{2}{c}{errors for dual TGT library calls} \\ + +{\sc krb5_invalid_flags }& Invalid KDC option combination (library internal error) \\ +{\sc krb5_no_2nd_tkt }& Request missing second ticket \\ +{\sc krb5_nocreds_supplied }& No credentials supplied to library routine \\ + +\end{tabular} + +\begin{tabular}{ll} +\multicolumn{2}{c}{errors for sendauth and recvauth} \\ + +{\sc krb5_sendauth_badauthvers }& Bad sendauth version was sent \\ +{\sc krb5_sendauth_badapplvers }& Bad application version was sent (via sendauth) \\ +{\sc krb5_sendauth_badresponse }& Bad response (during sendauth exchange) \\ +{\sc krb5_sendauth_rejected }& Server rejected authentication\\ +& \ (during sendauth exchange) \\ +{\sc krb5_sendauth_mutual_failed }& Mutual authentication failed\\&\ (during sendauth exchange) \\ + +\end{tabular} + +\begin{tabular}{ll} +\multicolumn{2}{c}{errors for preauthentication} \\ + +{\sc krb5_preauth_bad_type }& Unsupported preauthentication type \\ +{\sc krb5_preauth_no_key }& Required preauthentication key not supplied \\ +{\sc krb5_preauth_failed }& Generic preauthentication failure \\ + +\end{tabular} + +\begin{tabular}{ll} +\multicolumn{2}{c}{version number errors} \\ + +{\sc krb5_rcache_badvno }& Unsupported replay cache format version number \\ +{\sc krb5_ccache_badvno }& Unsupported credentials cache format version number \\ +{\sc krb5_keytab_badvno }& Unsupported key table format version number \\ + +\end{tabular} + +\begin{tabular}{ll} +\multicolumn{2}{c}{other errors} \\ + +{\sc krb5_prog_atype_nosupp }& Program lacks support for address type \\ +{\sc krb5_rc_required }& Message replay detection requires\\&\ rcache parameter \\ +{\sc krb5_err_bad_hostname }& Hostname cannot be canonicalized \\ +{\sc krb5_err_host_realm_unknown }& Cannot determine realm for host \\ +{\sc krb5_sname_unsupp_nametype }& Conversion to service principal undefined\\&\ for name type \\ +{\sc krb5krb_ap_err_v4_reply }& Initial Ticket Response appears to be\\ +&\ Version 4 error \\ +{\sc krb5_realm_cant_resolve }& Cannot resolve KDC for requested realm \\ +{\sc krb5_tkt_not_forwardable }& Requesting ticket can't get forwardable tickets \\ +\end{tabular} +\end{small} + +\subsection{error_table kdb5} + +% $Source$ +% $Author$ + +The Kerberos v5 database library error code table + +\begin{small} +\begin{tabular}{ll} +\multicolumn{2}{c}{From the server side routines} \\ +{\sc krb5_kdb_inuse }& Entry already exists in database\\ +{\sc krb5_kdb_uk_serror }& Database store error\\ +{\sc krb5_kdb_uk_rerror }& Database read error\\ +{\sc krb5_kdb_unauth }& Insufficient access to perform requested operation\\ +{\sc krb5_kdb_noentry }& No such entry in the database\\ +{\sc krb5_kdb_ill_wildcard }& Illegal use of wildcard\\ +{\sc krb5_kdb_db_inuse }& Database is locked or in use--try again later\\ +{\sc krb5_kdb_db_changed }& Database was modified during read\\ +{\sc krb5_kdb_truncated_record }& Database record is incomplete or corrupted\\ +{\sc krb5_kdb_recursivelock }& Attempt to lock database twice\\ +{\sc krb5_kdb_notlocked }& Attempt to unlock database when not locked\\ +{\sc krb5_kdb_badlockmode }& Invalid kdb lock mode\\ +{\sc krb5_kdb_dbnotinited }& Database has not been initialized\\ +{\sc krb5_kdb_dbinited }& Database has already been initialized\\ +{\sc krb5_kdb_illdirection }& Bad direction for converting keys\\ +{\sc krb5_kdb_nomasterkey }& Cannot find master key record in database\\ +{\sc krb5_kdb_badmasterkey }& Master key does not match database\\ +{\sc krb5_kdb_invalidkeysize }& Key size in database is invalid\\ +{\sc krb5_kdb_cantread_stored }& Cannot find/read stored master key\\ +{\sc krb5_kdb_badstored_mkey }& Stored master key is corrupted\\ +{\sc krb5_kdb_cantlock_db }& Insufficient access to lock database \\ +{\sc krb5_kdb_db_corrupt }& Database format error\\ +{\sc krb5_kdb_bad_version }& Unsupported version in database entry \\ +\end{tabular} +\end{small} + +% $Source$ +% $Author$ + +\subsection{error_table kv5m} + +The Kerberos v5 magic numbers errorcode table follows. These are used +for the magic numbers found in data structures. + +\begin{small} +\begin{tabular}{ll} +{\sc kv5m_none }& Kerberos V5 magic number table \\ +{\sc kv5m_principal }& Bad magic number for krb5_principal structure \\ +{\sc kv5m_data }& Bad magic number for krb5_data structure \\ +{\sc kv5m_keyblock }& Bad magic number for krb5_keyblock structure \\ +{\sc kv5m_checksum }& Bad magic number for krb5_checksum structure \\ +{\sc kv5m_encrypt_block }& Bad magic number for krb5_encrypt_block structure \\ +{\sc kv5m_enc_data }& Bad magic number for krb5_enc_data structure \\ +{\sc kv5m_cryptosystem_entry }& Bad magic number for krb5_cryptosystem_entry\\&\ structure \\ +{\sc kv5m_cs_table_entry }& Bad magic number for krb5_cs_table_entry structure \\ +{\sc kv5m_checksum_entry }& Bad magic number for krb5_checksum_entry structure \\ + +{\sc kv5m_authdata }& Bad magic number for krb5_authdata structure \\ +{\sc kv5m_transited }& Bad magic number for krb5_transited structure \\ +{\sc kv5m_enc_tkt_parT }& Bad magic number for krb5_enc_tkt_part structure \\ +{\sc kv5m_ticket }& Bad magic number for krb5_ticket structure \\ +{\sc kv5m_authenticator }& Bad magic number for krb5_authenticator structure \\ +{\sc kv5m_tkt_authent }& Bad magic number for krb5_tkt_authent structure \\ +{\sc kv5m_creds }& Bad magic number for krb5_creds structure \\ +{\sc kv5m_last_req_entry }& Bad magic number for krb5_last_req_entry structure \\ +{\sc kv5m_pa_data }& Bad magic number for krb5_pa_data structure \\ +{\sc kv5m_kdc_req }& Bad magic number for krb5_kdc_req structure \\ +{\sc kv5m_enc_kdc_rep_part }& Bad magic number for krb5_enc_kdc_rep_part structure \\ +{\sc kv5m_kdc_rep }& Bad magic number for krb5_kdc_rep structure \\ +{\sc kv5m_error }& Bad magic number for krb5_error structure \\ +{\sc kv5m_ap_req }& Bad magic number for krb5_ap_req structure \\ +{\sc kv5m_ap_rep }& Bad magic number for krb5_ap_rep structure \\ +{\sc kv5m_ap_rep_enc_part }& Bad magic number for krb5_ap_rep_enc_part structure \\ +{\sc kv5m_response }& Bad magic number for krb5_response structure \\ +{\sc kv5m_safe }& Bad magic number for krb5_safe structure \\ +{\sc kv5m_priv }& Bad magic number for krb5_priv structure \\ +{\sc kv5m_priv_enc_part }& Bad magic number for krb5_priv_enc_part structure \\ +{\sc kv5m_cred }& Bad magic number for krb5_cred structure \\ +{\sc kv5m_cred_info }& Bad magic number for krb5_cred_info structure \\ +{\sc kv5m_cred_enc_part }& Bad magic number for krb5_cred_enc_part structure \\ +{\sc kv5m_pwd_data }& Bad magic number for krb5_pwd_data structure \\ +{\sc kv5m_address }& Bad magic number for krb5_address structure \\ +{\sc kv5m_keytab_entry }& Bad magic number for krb5_keytab_entry structure \\ +{\sc kv5m_context }& Bad magic number for krb5_context structure \\ +{\sc kv5m_os_context }& Bad magic number for krb5_os_context structure \\ + +\end{tabular} +\end{small} + +\subsection{error_table asn1} + +The Kerberos v5/ASN.1 error table mappings + +\begin{small} +\begin{tabular}{ll} +{\sc asn1_bad_timeformat }& ASN.1 failed call to system time library \\ +{\sc asn1_missing_field }& ASN.1 structure is missing a required field \\ +{\sc asn1_misplaced_field }& ASN.1 unexpected field number \\ +{\sc asn1_type_mismatch }& ASN.1 type numbers are inconsistent \\ +{\sc asn1_overflow }& ASN.1 value too large \\ +{\sc asn1_overrun }& ASN.1 encoding ended unexpectedly \\ +{\sc asn1_bad_id }& ASN.1 identifier doesn't match expected value \\ +{\sc asn1_bad_length }& ASN.1 length doesn't match expected value \\ +{\sc asn1_bad_format }& ASN.1 badly-formatted encoding \\ +{\sc asn1_parse_error }& ASN.1 parse error \\ +\end{tabular} +\end{small} + diff --git a/krb5-1-6/doc/api/fancyheadings.sty b/krb5-1-6/doc/api/fancyheadings.sty new file mode 100644 index 000000000..a71de0fb5 --- /dev/null +++ b/krb5-1-6/doc/api/fancyheadings.sty @@ -0,0 +1,233 @@ +% fancyheadings.sty version 1.0 +% Fancy headers and footers. +% Piet van Oostrum, Dept of Computer Science, University of Utrecht +% Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands +% Telephone: +31-30-531806. piet@cs.ruu.nl (mcvax!hp4nl!ruuinf!piet) +% March, 1989. + +% Here is a documentstylestyle option that allows you to customize your +% page headers and footers in an easy way. It combines features that were +% separately available in other pagestyles, without introducing much +% complexity. You can define: +% - three-part headers and footers +% - rules in header and footer +% - headers and footers wider than \textwidth +% - multiline headers and footers +% - separate headers and footers for even and odd pages +% - separate headers and footers for chapter pages +% +% To use this pagestyle, you must include the ``fancyheadings'' style +% option in your \documentstyle, and issue the \pagestyle{fancy} command. +% The \pagestyle{fancy} command should be issued after any changes made to +% \textwidth. +% +% The page layout will be as follows: +% +% LHEAD CHEAD RHEAD +% ----------------------------------- (rule) +% +% page body +% +% +% ----------------------------------- (rule) +% LFOOT CFOOT RFOOT +% +% The L-fields will be leftadjusted, the C-fields centered and the +% R-fields rightadjusted. +% Each of the six fields and the two rules can be defined separately. +% +% Simple use: +% +% The header and footer fields can be defined by commands \lhead{LHEAD} +% and so on for the other fields. If the field depends on something in the +% document (e.g. section titles) you must in general use the \markboth and +% \markright commands, otherwise a title may end on the wrong page. You +% can do this e.g. by redefining the commands \chaptermark, \sectionmark +% and so on (see example below). The defaults for these marks are as in +% the standard pagestyles. The marks can be put into a header or footer +% field by referencing \leftmark and \rightmark. +% +% Rules in header and footer +% +% The thickness of the rules below the header and above the footer can be +% changed by redefining the length parameters \headrulewidth (default +% 0.4pt) and \footrulewidth (default 0). These may be redefined by the +% \setlength command. A thickness of 0pt makes the rule invisible. +% If you want to make more complicated changes, you have to redefine the +% commands \headrule and/or \footrule. +% +% Headers and footers wider than \textwidth +% +% The headers and footers are set in a box of width \headwidth. The +% default for this is the value of \textwidth. You can make it wider (or +% smaller) by redefining \headwidth with the \setlength or \addtolength +% command. The headers and footers will stick out the page on the same +% side as the marginal notes. For example to include the marginal notes, +% add both \marginparsep and \marginparwidth to \headwidth (see also the +% example below). +% +% Multiline headers and footers +% +% Each of the six fields is set in an appropriate parbox, so you can put a +% multiline part in it with the \\ command. It is also possible to put +% extra space in it with the \vspace command. Note that if you do this you +% will probably have to increase the \headheight or \footskip lengths. +% +% Separate headers and footers for even and odd pages +% +% If you want the headers and footers to be different on even- and +% odd-numbered pages in the ``twoside'' style, the field-defining macros +% can be given an optional argument, to be used on the even-numbered +% pages, like \lhead[EVEN-LHEAD]{ODD-RHEAD}. +% +% Separate headers and footers for chapter pages +% +% LaTeX gives a \thispagestyle{plain} command for the first page of the +% document, the first page of each chapter and a couple of other pages. It +% might be incompatible with your pagestyle. In this case you can use a +% slightly different version of the pagestyle, called \pagestyle{fancyplain}. +% This pagestyle redefines the pagestyle ``plain'' to also use pagestyle +% ``fancy'' with the following modifications: +% - the thicknesses of the rules is defined by \plainheadrulewidth and +% \plainfootrulewidth (both default 0). +% - the 6 fields may be defined separately for the plain pages by +% giving them the value \fancyplain{PLAIN-VALUE}{NORMAL-VALUE}. This +% construct may be used in both the optional argument and the normal +% argument. Thus \lhead[\fancyplain{F1}{F2}]{\fancyplain{F3}{F4}} +% specifies the LHEAD value in a two-sided document: +% F1 on an even-numbered ``plain'' page +% F2 on an even-numbered normal page +% F3 on an odd-numbered ``plain'' page +% F4 on an odd-numbered normal page. +% +% Defaults: +% +% \headrulewidth 0.4pt +% \footrulewidth 0pt +% \plainheadrulewidth 0pt +% \plainfootrulewidth 0pt +% +% \lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}} +% % i.e. empty on ``plain'' pages \rightmark on even, \leftmark on odd pages +% \chead{} +% \rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}} +% % i.e. empty on ``plain'' pages \leftmark on even, \rightmark on odd pages +% \lfoot{} +% \cfoot{\rm\thepage} % page number +% \rfoot{} +% +% Examples: +% +% To put two lines containing the section title and the subsection title +% in the righthandside corner, use: +% +% \documentstyle[fancyheadings]{article} +% \pagestyle{fancy} +% \renewcommand{\sectionmark}[1]{\markboth{#1}{}} +% \renewcommand{\subsectionmark}[1]{\markright{#1}} +% \rfoot{\leftmark\\\rightmark} +% +% The following definitions give an approximation of the style used in the +% LaTeX book: +% +% \documentstyle[fancyheadings]{book} +% \pagestyle{fancyplain} +% \addtolength{\headwidth}{\marginparsep} +% \addtolength{\headwidth}{\marginparwidth} +% \renewcommand{\chaptermark}[1]{\markboth{#1}{#1}} % remember chapter title +% \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} +% % section number and title +% \lhead[\fancyplain{}{\bf\thepage}]{\fancyplain{}{\bf\rightmark}} +% \rhead[\fancyplain{}{\bf\leftmark}]{\fancyplain{}{\bf\thepage}} +% \cfoot{} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}} +\def\@xlhead[#1]#2{\gdef\@elhead{#1}\gdef\@olhead{#2}} +\def\@ylhead#1{\gdef\@elhead{#1}\gdef\@olhead{#1}} + +\def\chead{\@ifnextchar[{\@xchead}{\@ychead}} +\def\@xchead[#1]#2{\gdef\@echead{#1}\gdef\@ochead{#2}} +\def\@ychead#1{\gdef\@echead{#1}\gdef\@ochead{#1}} + +\def\rhead{\@ifnextchar[{\@xrhead}{\@yrhead}} +\def\@xrhead[#1]#2{\gdef\@erhead{#1}\gdef\@orhead{#2}} +\def\@yrhead#1{\gdef\@erhead{#1}\gdef\@orhead{#1}} + +\def\lfoot{\@ifnextchar[{\@xlfoot}{\@ylfoot}} +\def\@xlfoot[#1]#2{\gdef\@elfoot{#1}\gdef\@olfoot{#2}} +\def\@ylfoot#1{\gdef\@elfoot{#1}\gdef\@olfoot{#1}} + +\def\cfoot{\@ifnextchar[{\@xcfoot}{\@ycfoot}} +\def\@xcfoot[#1]#2{\gdef\@ecfoot{#1}\gdef\@ocfoot{#2}} +\def\@ycfoot#1{\gdef\@ecfoot{#1}\gdef\@ocfoot{#1}} + +\def\rfoot{\@ifnextchar[{\@xrfoot}{\@yrfoot}} +\def\@xrfoot[#1]#2{\gdef\@erfoot{#1}\gdef\@orfoot{#2}} +\def\@yrfoot#1{\gdef\@erfoot{#1}\gdef\@orfoot{#1}} + +\newdimen\headrulewidth +\newdimen\footrulewidth +\newdimen\plainheadrulewidth +\newdimen\plainfootrulewidth +\newdimen\headwidth +\newif\if@fancyplain \@fancyplainfalse +\def\fancyplain#1#2{\if@fancyplain#1\else#2\fi} + +% Initialization of the head and foot text. + +\headrulewidth 0.4pt +\footrulewidth\z@ +\plainheadrulewidth\z@ +\plainfootrulewidth\z@ + +\lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}} +% i.e. empty on ``plain'' pages \rightmark on even, \leftmark on odd pages +\chead{} +\rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}} +% i.e. empty on ``plain'' pages \leftmark on even, \rightmark on odd pages +\lfoot{} +\cfoot{\rm\thepage} % page number +\rfoot{} + +% Put together a header or footer given the left, center and +% right text, fillers at left and right and a rule. +% The \lap commands put the text into an hbox of zero size, +% so overlapping text does not generate an errormessage. + +\def\@fancyhead#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\hbox +{\rlap{\parbox[b]{\headwidth}{\raggedright#2\strut}}\hfill +\parbox[b]{\headwidth}{\centering#3\strut}\hfill +\llap{\parbox[b]{\headwidth}{\raggedleft#4\strut}}}\headrule}}#5} + + +\def\@fancyfoot#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\footrule +\hbox{\rlap{\parbox[t]{\headwidth}{\raggedright#2\strut}}\hfill +\parbox[t]{\headwidth}{\centering#3\strut}\hfill +\llap{\parbox[t]{\headwidth}{\raggedleft#4\strut}}}}}#5} + +\def\headrule{{\if@fancyplain\headrulewidth\plainheadrulewidth\fi +\hrule\@height\headrulewidth\@width\headwidth \vskip-\headrulewidth}} + +\def\footrule{{\if@fancyplain\footrulewidth\plainfootrulewidth\fi +\vskip-0.3\normalbaselineskip\vskip-\footrulewidth +\hrule\@width\headwidth\@height\footrulewidth\vskip0.3\normalbaselineskip}} + +\def\ps@fancy{ +\let\@mkboth\markboth +\@ifundefined{chapter}{\def\sectionmark##1{\markboth +{\uppercase{\ifnum \c@secnumdepth>\z@ + \thesection\hskip 1em\relax \fi ##1}}{}} +\def\subsectionmark##1{\markright {\ifnum \c@secnumdepth >\@ne + \thesubsection\hskip 1em\relax \fi ##1}}} +{\def\chaptermark##1{\markboth {\uppercase{\ifnum \c@secnumdepth>\m@ne + \@chapapp\ \thechapter. \ \fi ##1}}{}} +\def\sectionmark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\z@ + \thesection. \ \fi ##1}}}} +\def\@oddhead{\@fancyhead\relax\@olhead\@ochead\@orhead\hss} +\def\@oddfoot{\@fancyfoot\relax\@olfoot\@ocfoot\@orfoot\hss} +\def\@evenhead{\@fancyhead\hss\@elhead\@echead\@erhead\relax} +\def\@evenfoot{\@fancyfoot\hss\@elfoot\@ecfoot\@erfoot\relax} +\headwidth\textwidth} +\def\ps@fancyplain{\ps@fancy \let\ps@plain\ps@plain@fancy} +\def\ps@plain@fancy{\@fancyplaintrue\ps@fancy} diff --git a/krb5-1-6/doc/api/fixunder.sty b/krb5-1-6/doc/api/fixunder.sty new file mode 100644 index 000000000..b7ae58dbf --- /dev/null +++ b/krb5-1-6/doc/api/fixunder.sty @@ -0,0 +1,48 @@ +% fixunder.sty, 31 May 1990, John T. Kohl +% +% The contents of this file are in the public domain. +% +% +% play games with _ to make it active and to provide a reasonable _ +% character (from \tt in most cases), and a discretionary word-break point. + +% +% Some \makeunder... macros for convenience in setting catcodes. +% +\def\makeunderactive{\catcode`\_=\active\relax} +\def\makeunderother{\catcode`\_=12\relax} +\def\makeunderletter{\catcode`\_=11\relax} +\def\makeundernormal{\catcode`\_=8\relax} +\makeunderother +\def\cctwlunder{_} + +% +% The hair here is to allow things like \index to work reasonably with +% the new definition of underscore when the argument to index is part of +% a macro replacement and as such gets tokenized before \index is +% evaluated. +% [in the normal case at top-level, \index{foo_bar} works since \index +% does some hair to make _ into a reasonable character code, and \index +% does NOT use a macro expansion. If you have something like +% \def\foo#1#2{\index{#1} bar #2} +% then \foo{baz_quux}{frobnitz} will result in baz_quux getting +% tokenized BEFORE \foo is expanded, so that the catcode hair in \index +% is to no avail.] +% +% \underrealfalse declares that you want to replace with the \tt _; +% \underrealtrue declares that you want to replace with \char95 (ASCII _). +% +% for things like \index which write things out to files, set +% \underrealfalse before evaluating the \index macro, and what actually +% gets written to the file is an _, rather than something like +% {\leavemode \kern... } (the typical definition of \_). +% +% the above example would then be +% \def\foo#1#2{\underrealfalse\index{#1}\underrealtrue bar #2} +% + +\newif\ifunderreal +\underrealfalse +\makeunderactive +\def_{\ifunderreal\cctwlunder\else\leavevmode {\tt \cctwlunder}\discretionary{}{}{}\fi} +\let\_=_ diff --git a/krb5-1-6/doc/api/free.tex b/krb5-1-6/doc/api/free.tex new file mode 100644 index 000000000..02733b702 --- /dev/null +++ b/krb5-1-6/doc/api/free.tex @@ -0,0 +1,266 @@ +The free functions deal with deallocation of memory that has been +allocated by various routines. It is recommended that the developer use +these routines as they will know about the contents of the structures. + +\begin{funcdecl}{krb5_xfree}{void}{\funcinout} +\funcarg{void *}{ptr} +\end{funcdecl} + +Frees the pointer \funcarg{ptr}. This is a wrapper macro to +\funcname{free} that is designed to keep lint ``happy.'' + +\begin{funcdecl}{krb5_free_data}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_data *}{val} +\end{funcdecl} + +Frees the data structure \funcparam{val}, including the pointer +\funcparam{val} which has been allocate by any of numerous routines. + + +\begin{funcdecl}{krb5_free_princial}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_principal}{val} +\end{funcdecl} + +Frees the pwd_data \funcparam{val} that has been allocated from +\funcname{krb5_copy_principal}. + +\begin{funcdecl}{krb5_free_authenticator}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_authenticator *}{val} +\end{funcdecl} + +Frees the authenticator \funcparam{val}, including the pointer +\funcparam{val}. + +\begin{funcdecl}{krb5_free_authenticator_contents}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_authenticator *}{val} +\end{funcdecl} + +Frees the authenticator contents of \funcparam{val}. The pointer +\funcparam{val} is not freed. + + +\begin{funcdecl}{krb5_free_addresses}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_address **}{val} +\end{funcdecl} + +Frees the series of addresses \funcparam{*val} that have been allocated from +\funcname{krb5_copy_addresses}. + +\begin{funcdecl}{krb5_free_address}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_address *}{val} +\end{funcdecl} + +Frees the address \funcparam{val}. + +\begin{funcdecl}{krb5_free_authdata}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_authdata **}{val} +\end{funcdecl} + +Frees the authdata structure pointed to by \funcparam{val} that has been +allocated from +\funcname{krb5_copy_authdata}. + +\begin{funcdecl}{krb5_free_enc_tkt_part}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_enc_tkt_part *}{val} +\end{funcdecl} + +Frees \funcparam{val} that has been allocated from +\funcname{krb5_enc_tkt_part} and \funcname{krb5_decrypt_tkt_part}. + +\begin{funcdecl}{krb5_free_ticket}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ticket *}{val} +\end{funcdecl} + +Frees the ticket \funcparam{val} that has been allocated from +\funcname{krb5_copy_ticket} and other routines. + +\begin{funcdecl}{krb5_free_tickets}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ticket **}{val} +\end{funcdecl} + +Frees the tickets pointed to by \funcparam{val}. + +\begin{funcdecl}{krb5_free_kdc_req}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_kdc_req *}{val} +\end{funcdecl} + +Frees the kdc_req \funcparam{val} and all substructures. The pointer +\funcparam{val} is freed as well. + +\begin{funcdecl}{krb5_free_kdc_rep}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_kdc_rep *}{val} +\end{funcdecl} + +Frees the kdc_rep \funcparam{val} that has been allocated from +\funcname{krb5_get_in_tkt}. + +\begin{funcdecl}{krb5_free_kdc_rep_part}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_enc_kdc_rep_part *}{val} +\end{funcdecl} + +Frees the kdc_rep_part \funcparam{val}. + +\begin{funcdecl}{krb5_free_error}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_error *}{val} +\end{funcdecl} + +Frees the error \funcparam{val} that has been allocated from +\funcname{krb5_read_error} or \funcname{krb5_sendauth}. + +\begin{funcdecl}{krb5_free_ap_req}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ap_req *}{val} +\end{funcdecl} + +Frees the ap_req \funcparam{val}. + +\begin{funcdecl}{krb5_free_ap_rep}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ap_rep *}{val} +\end{funcdecl} + +Frees the ap_rep \funcparam{val}. + +\begin{funcdecl}{krb5_free_safe}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_safe *}{val} +\end{funcdecl} + +Frees the safe application data \funcparam{val} that is allocated with +\funcparam{decode_krb5_safe}. + + +\begin{funcdecl}{krb5_free_priv}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_priv *}{val} +\end{funcdecl} + +Frees the private data \funcparam{val} that has been allocated from +\funcname{decode_krb5_priv}. + +\begin{funcdecl}{krb5_free_priv_enc_part}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_priv_enc_part *}{val} +\end{funcdecl} + +Frees the private encoded part \funcparam{val} that has been allocated from +\funcname{decode_krb5_enc_priv_part}. + +\begin{funcdecl}{krb5_free_cred}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_cred *}{val} +\end{funcdecl} + +Frees the credential \funcparam{val}. + +\begin{funcdecl}{krb5_free_creds}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_creds *}{val} +\end{funcdecl} + +Calls \funcname{krb5_free_cred_contents} with \funcparam{val} as the +argument. \funcparam{val} is freed as well. + +\begin{funcdecl}{krb5_free_cred_contents}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_creds *}{val} +\end{funcdecl} + +The function zeros out the session key stored in the credential and then +frees the credentials structures. The argument \funcparam{val} is +{\bf not} freed. + + +\begin{funcdecl}{krb5_free_cred_enc_part}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_cred_enc_part *}{val} +\end{funcdecl} + +Frees the addresses and ticket_info elements of +\funcparam{val}. \funcparam{val} is {\bf not} freed by this routine. + +\begin{funcdecl}{krb5_free_checksum}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_checksum *}{val} +\end{funcdecl} + +The checksum and the pointer \funcparam{val} are both freed. + +\begin{funcdecl}{krb5_free_keyblock}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keyblock *}{val} +\end{funcdecl} + +The keyblock contents of \funcparam{val} are zeroed and the memory +freed. The pointer \funcparam{val} is freed as well. + +\begin{funcdecl}{krb5_free_pa_data}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_pa_data **}{val} +\end{funcdecl} + +Frees the contents of \funcparam{*val}. \funcparam{val} is freed as +well. + +\begin{funcdecl}{krb5_free_ap_rep_enc_part}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_ap_rep_enc_part *}{val} +\end{funcdecl} + +Frees the subkey keyblock (if set) as well as \funcparam{val} that has +been allocated from \funcname{krb5_rd_rep} or \funcname{krb5_send_auth}. + +\begin{funcdecl}{krb5_free_tkt_authent}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_tkt_authent *}{val} +\end{funcdecl} + +Frees the ticket and authenticator portions of \funcparam{val}. The +pointer \funcparam{val} is freed as well. + +\begin{funcdecl}{krb5_free_pwd_data}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{passwd_pwd_data *}{val} +\end{funcdecl} + +Frees the pwd_data \funcparam{val} that has been allocated from +\funcname{decode_krb5_pwd_data}. + +\begin{funcdecl}{krb5_free_pwd_sequences}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{passwd_phrase_element **}{val} +\end{funcdecl} + +Frees the passwd_phrase_element \funcparam{val}. This is usually called +from \funcname{krb5_free_pwd_data}. + +\begin{funcdecl}{krb5_free_realm_tree}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_principal *}{realms} +\end{funcdecl} + +Frees the realms tree \funcparam{realms} returned by +\funcname{krb5_walk_realm_tree}. + +\begin{funcdecl}{krb5_free_tgt_creds}{void}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_creds **}{tgts} +\end{funcdecl} + +Frees the TGT credentials \funcparam{tgts} returned by +\funcname{krb5_get_cred_from_kdc}. + diff --git a/krb5-1-6/doc/api/functions.sty b/krb5-1-6/doc/api/functions.sty new file mode 100644 index 000000000..a3165f811 --- /dev/null +++ b/krb5-1-6/doc/api/functions.sty @@ -0,0 +1,70 @@ +% +% definitions related to function declarations/displays +% +\ifx\undefined\@psfonts +\def\argfont{\tt} +\else +\font\argfont = pcrb +\hyphenchar\argfont = -1 +\fi +\let\funcfont=\bf +\newcount\argc@ount +%\setlength{\marginparsep}{0.05in} +%\setlength{\marginparwidth}{1.45in} +% +% This function fixes up the function name to be displayed in the +% margin so that the krb5_, if any, is stripped. +% +% Note: this is a hack; what's really happening is that name beginning with +% krb5 will have its first five characters stripped from it. +% This means that 'Krb5abc' will get rewritten to be 'bc'. +% Unfortunately, we can't do better because of the underscore +% hacks that are going on elsewhere. +% +% WARNING: This is ugly; don't look at it too soon after lunch! +% [tytso:19900920.2231EDT] +\newif\if@krbfunc +\def\endkrb{} +\def\fix@parname#1{\expandafter\parse@krb#1\endkrb% +\endkrb\endkrb\endkrb\endkrb}% In case the argument is less +% than five letters, we don't want to +% lose on the argument parsing. +\def\parse@krb#1#2#3#4#5#6\endkrb{\@krbfuncfalse% +\if#1k\if#2r\if#3b\if#45\@krbfunctrue\fi\fi\fi\fi% +\if@krbfunc#6\else#1#2#3#4#5#6\fi} +% +% funcdecl is used as \begin{funcdecl}{funcname}{return type}{firstline} +% +% see fixunder.sty for comments on why the \underrealtrue & \underrealfalse +% stuff is here. +\newenvironment{funcdecl}[3]{\underrealtrue\index{#1}\underrealfalse% +\medbreak +\gdef\funcn@me{#1} +\argc@ount=0\noindent% +%the \mbox{} is to prevent the line/paragraph breaking from eating the +%fill space. +\marginpar[{{\sloppy \hfil\fix@parname{\funcn@me}\hfill\mbox{}}}]% +{{\sloppy \hfill\fix@parname{\funcn@me}\hfil\mbox{}}}% +\vbox\bgroup\begin{minipage}[t]{\textwidth}\begin{tabbing} +#2 \\ +{\bf #1}(\= \+ #3% +}{) +\end{tabbing}\vfil\end{minipage}\egroup\par\nopagebreak +} +\newcommand{\docomm@}{\ifnum\argc@ount >0, \\\fi} +\newcommand{\funcvoid}{\argc@ount=0} +\newcommand{\funcin}{\docomm@\argc@ount=0{\sl /* IN */}\\} +\newcommand{\funcinout}{\docomm@\argc@ount=0{\sl /* IN/OUT */}\\} +\newcommand{\funcout}{\docomm@\argc@ount=0{\sl /* OUT */}\\} +\newcommand{\funcarg}[2]{\docomm@#1 {\argfont #2}\advance\argc@ount by1} +\newcommand{\funcparam}[1]{{\argfont #1}} +\newcommand{\funcfuncarg}[2]{\docomm@#1 {\argfont #2}(\= \+ \argc@ount=0} +\newcommand{\funcendfuncarg}{), \- \\ \argc@ount=0} +\newcommand{\libname}[1]{{\argfont #1}} +\newcommand{\globalname}[1]{{\argfont #1}} +\newcommand{\ptsto}{->\discretionary{}{}{}} +\newcommand{\datatype}[1]{{\bf #1}} +\newcommand{\filename}[1]{{\sl #1\/}} + +\newcommand{\funcname}[1]{\underrealtrue\index{#1}\underrealfalse{\funcfont #1}()} +\newcommand{\funcnamenoparens}[1]{\underrealtrue\index{#1}\underrealfalse{\funcfont #1}} diff --git a/krb5-1-6/doc/api/intro.tex b/krb5-1-6/doc/api/intro.tex new file mode 100644 index 000000000..370775b02 --- /dev/null +++ b/krb5-1-6/doc/api/intro.tex @@ -0,0 +1,299 @@ + This document describes the routines that make up the Kerberos +V5 application programming interface. It is geared towards +programmers who already have a basic familiarity with Kerberos and are +in the process of including Kerberos authentication as part of +applications being developed. + + The function descriptions included are up to date, even if the +description of the functions may be hard to understand for the novice +Kerberos programmer. + +\subsection{Acknowledgments} + + +The Kerberos model is based in part on Needham and Schroeder's trusted +third-party authentication protocol and on modifications suggested by +Denning and Sacco. The original design and implementation of Kerberos +Versions 1 through 4 was the work of Steve Miller of Digital Equipment +Corporation and Clifford Neuman (now at the Information Sciences +Institute of the University of Southern California), along with Jerome +Saltzer, Technical Director of Project Athena, and Jeffrey Schiller, +MIT Campus Network Manager. Many other members of Project Athena have +also contributed to the work on Kerberos. Version 4 is publicly +available, and has seen wide use across the Internet. + +Version 5 (described in this document) has evolved from Version 4 based +on new requirements and desires for features not available in Version 4. + +%nlg- a bunch more probably needs to be added here to credit all +%those that have contributed to V5 -nlg + +\subsection{Kerberos Basics} + +Kerberos performs authentication as a trusted third-party +authentication service by using conventional (shared secret +key\footnote{ {\em Secret} and {\em private} are often used +interchangeably in the literature. In our usage, it takes two (or +more) to share a secret, thus a shared DES key is a {\em secret} key. +Something is only private when no one but its owner knows it. Thus, +in public key cryptosystems, one has a public and a {\em private} key. +}) cryptography. Kerberos provides a means of verifying the +identities of principals, without relying on authentication by the +host operating system, without basing trust on host addresses, without +requiring physical security of all the hosts on the network, and under +the assumption that packets traveling along the network can be read, +modified, and inserted at will. + +When integrating Kerberos into an application it is important to +review how and when Kerberos functions are used to ensure that the +application's design does not compromise the authentication. For +instance, an application which uses Kerberos' functions only upon the +{\em initiation} of a stream-based network connection, and assumes the +absence of any active attackers who might be able to ``hijack'' the +stream connection. + +%{\Huge nlg- It would be nice to include more examples here of common +%mistakes one can make in designing kerberized systems -nlg} + +The Kerberos protocol code libraries, whose API is described in this +document, can be used to provide encryption to any application. In +order to add authentication to its transactions, a typical network +application adds one or two calls to the Kerberos library, which +results in the transmission of the necessary messages to achieve +authentication. + +The two methods for obtaining credentials, the initial ticket exchange +and the ticket granting ticket exchange, use slightly different +protocols and require different API routines. The basic difference an +API programmer will see is that the initial request does not require a +ticket granting ticket (TGT) but does require the client's secret key +because the reply is sent back encrypted in the client's secret key. +Usually this request is for a TGT and TGT based exchanges are used +from then on. In a TGT exchange the TGT is sent as part of the +request for tickets and the reply is encrypted in the session key from +the TGT. For example, once a user's password is used to obtain a TGT, +it is not required for subsequent TGT exchanges. + +The reply consists of a ticket and a session key, encrypted either in +the user's secret key (i.e., password), or the TGT session key. The +combination of a ticket and a session key is known as a set of {\em +credentials}.\footnote{In Kerberos V4, the ``ticket file'' was a bit of +a misnomer, since it contained both tickets and their associated session +keys. In Kerberos V5, the ``ticket file'' has been renamed to be the +{\em credentials cache}.} An application client can use these +credentials to authenticate to the application server by sending the +ticket and an {\em authenticator} to the server. The authenticator is +encrypted in the session key of the ticket, and contains the name of the +client, the name of the server, the time the authenticator was created. + +In order to verify the authentication, the application server decrypts +the ticket using its service key, which is only known by the application +server and the Kerberos server. Inside the ticket, the Kerberos server +had placed the name of the client, the name of the server, a DES key +associated with this ticket, and some additional information. The +application server then uses the ticket session key to decrypt the +authenticator, and verifies that the information in the authenticator +matches the information in the ticket, and that the timestamp in the +authenticator is recent (to prevent reply attacks). Since the session +key was generated randomly by the Kerberos server, and delivered only +encrypted in the service key, and in a key known only by the user, the +application server can be confident that user is really who he or she +claims to be, by virtue of the fact that the user was able to encrypt +the authenticator in the correct key. + +To provide detection of both replay +attacks and message stream modification attacks, the integrity of all +the messages exchanged between principals can also be +guar\-an\-teed\footnote{Using +\funcname{krb5_mk_safe} and \funcname{krb5_rd_safe} to create and +verify KRB5_SAFE messages} by generating and transmitting a +collision-proof checksum\footnote{aka cryptographic checksum, +elsewhere this is called a hash or digest function} of the client's +message, keyed with the session key. Privacy and integrity of the +messages exchanged between principals can be secured\footnote{Using +\funcname{krb5_mk_priv} and \funcname{krb5_rd_priv} to create and +verify KRB5_PRIV messages} by encrypting the data to be passed using +the session key. + +\subsubsection{The purpose of Realms} + +The Kerberos protocol is designed to operate across organizational +boundaries. Each organization wishing to run a Kerberos +server establishes its own {\em realm}. The name of the realm in which a +client is registered is part of the client's name, and can be used by the +end-service to decide whether to honor a request. + +By establishing {\em inter-realm} keys, the administrators of two +realms can allow a client authenticated in the local realm to use its +credentials remotely. The exchange of inter-realm keys (a separate +key may be used for each direction) registers the ticket-granting +service of each realm as a principal in the other realm. A client is +then able to obtain a ticket-granting ticket for the remote realm's +ticket-granting service from its local realm. When that +ticket-granting ticket is used, the remote ticket-granting service +uses the inter-realm key (which usually differs from its own normal +TGS key) to decrypt the ticket-granting ticket, and is thus certain +that it was issued by the client's own TGS. Tickets issued by the +remote ticket-granting service will indicate to the end-service that +the client was authenticated from another realm. + + +This method can be repeated to authenticate throughout an organization +across multiple realms. To build a valid authentication +path\footnote{An {\em authentication path} is the sequence of +intermediate realms that are transited in communicating from one realm +to another.} to a distant realm, the local realm must share an +inter-realm key with an intermediate realm which +communicates\footnote{A realm is said to {\em communicate} with +another realm if the two realms share an inter-realm key} with either +the distant remote realm or yet another intermediate realm. + +Realms are typically organized hierarchically. Each realm shares a +key with its parent and a different key with each child. If an +inter-realm key is not directly shared by two realms, the hierarchical +organization allows an authentication path to be easily constructed. +If a hierarchical organization is not used, it may be necessary to +consult some database in order to construct an authentication path +between realms. + +Although realms are typically hierarchical, intermediate realms may be +bypassed to achieve cross-realm authentication through alternate +authentication paths\footnote{These might be established to make communication +between two realms more efficient}. It is important for the +end-service to know which realms were transited when deciding how much +faith to place in the authentication process. To facilitate this +decision, a field in each ticket contains the names of the realms that +were involved in authenticating the client. + +\subsubsection{Fundamental assumptions about the environment} + +Kerberos has certain limitations that should be kept in mind when +designing security measures: + +\begin{itemize} +\item +Kerberos does not address ``Denial of service'' attacks. There are +places in these protocols where an intruder can prevent an application +from participating in the proper authentication steps. Detection and +solution of such attacks (some of which can appear to be not-uncommon +``normal'' failure modes for the system) is usually best left to +the human administrators and users. + +\item +Principals must keep their secret keys secret. If an intruder somehow +steals a principal's key, it will be able to masquerade as that +principal or impersonate any server to the legitimate principal. + +\item +``Password guessing'' attacks are not solved by Kerberos. If a user +chooses a poor password, it is possible for an attacker to +successfully mount an offline dictionary attack by repeatedly +attempting to decrypt, with successive entries from a dictionary, +messages obtained which are encrypted under a key derived from the +user's password. + +\end{itemize} + +\subsection{Glossary of terms} + +Below is a list of terms used throughout this document. + +\begin{description} +\item [Authentication] +Verifying the claimed identity of a principal. + +\item [Authentication header] +A record containing a Ticket and an Authenticator to be presented to a +server as part of the authentication process. + +\item [Authentication path] +A sequence of intermediate realms transited in the authentication +process when communicating from one realm to another. + +\item [Authenticator] +A record containing information that can be shown to +have been recently generated using the session key known only by the +client and server. + +\item [Authorization] +The process of determining whether a client may use a +service, which objects the client is allowed to access, and the +type of access allowed for each. + +\item [Ciphertext] +The output of an encryption function. Encryption transforms plaintext +into ciphertext. + +\item [Client] +A process that makes use of a network service on behalf of a +user. Note that in some cases a {\em Server} may itself be a client of +some other server (e.g. a print server may be a client of a file server). + +\item [Credentials] +A ticket plus the secret session key necessary to +successfully use that ticket in an authentication exchange. + +\item [KDC] +Key Distribution Center, a network service that supplies +tickets and temporary session keys; or an +instance of that service or the host on which it runs. +The KDC services both initial ticket and ticket-granting ticket +requests. +The initial ticket portion is sometimes referred to as the +Authentication Server (or service). +The ticket-granting ticket portion is sometimes referred to as the +ticket-granting server (or service). + +\item [Kerberos] +Aside from the 3-headed dog guarding Hades, the name given +to Project Athena's authentication service, the protocol used by that +service, or the code used to implement the authentication service. + +\item [Plaintext] +The input to an encryption function or the output of a decryption +function. Decryption transforms ciphertext into plaintext. + +\item [Principal] +A uniquely named client or server instance that participates in +a network communication. + +\item [Principal identifier] +The name used to uniquely identify each different +principal. + +\item [Seal] +To encipher a record containing several fields in such a way +that the fields cannot be individually replaced without either +knowledge of the encryption key or leaving evidence of tampering. + +\item [Secret key] +An encryption key shared by a principal and the KDC, +distributed outside the bounds of the system, with a long lifetime. +In the case of a human user's principal, the secret key is derived from a +password. + +\item [Server] +A particular Principal which provides a resource to network clients. + +\item [Service] +A resource provided to network clients; often provided by more than one +server (for example, remote file service). + +\item [Session key] +A temporary encryption key used between two principals, +with a lifetime limited to the duration of a single login +{\em session}. + +\item [Sub-session key] +A temporary encryption key used between two +principals, selected and exchanged by the principals using the session +key, and with a lifetime limited to the duration of a single +association. + +\item [Ticket] +A record that helps a client authenticate itself to a server; it contains +the client's identity, a session key, a timestamp, and other +information, all sealed using the server's secret key. It only serves to +authenticate a client when presented along with a fresh Authenticator. + +\end{description} diff --git a/krb5-1-6/doc/api/keytab.tex b/krb5-1-6/doc/api/keytab.tex new file mode 100644 index 000000000..63e27e538 --- /dev/null +++ b/krb5-1-6/doc/api/keytab.tex @@ -0,0 +1,221 @@ +The key table functions deal with storing and retrieving service keys +for use by unattended services which participate in authentication exchanges. + +Keytab routines are all be atomic. Every routine that acquires +a non-sharable resource releases it before it returns. + +All keytab types support multiple concurrent sequential scans. + +The order of values returned from \funcname{krb5_kt_next_entry} is +unspecified. + +Although the ``right thing'' should happen if the program aborts +abnormally, a close routine, \funcname{krb5_kt_free_entry}, is provided +for freeing resources, etc. People should use the close routine when +they are finished. + +\begin{funcdecl}{krb5_kt_register}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_kt_ops *}{ops} +\end{funcdecl} + + +Adds a new ticket cache type to the set recognized by +\funcname{krb5_kt_resolve}. +Requires that a keytab type named \funcparam{ops{\ptsto}prefix} is not +yet known. + +An error is returned if \funcparam{ops{\ptsto}prefix} is already known. + +\begin{funcdecl}{krb5_kt_resolve}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const char *}{string_name} +\funcout +\funcarg{krb5_keytab *}{id} +\end{funcdecl} + +Fills in \funcparam{*id} with a handle identifying the keytab with name +``string_name''. The keytab is not opened. +Requires that \funcparam{string_name} be of the form ``type:residual'' and +``type'' is a type known to the library. + +Errors: badly formatted name. + +\begin{funcdecl}{krb5_kt_default_name}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{char *}{name} +\funcarg{int}{namesize} +\end{funcdecl} + +\funcparam{name} is filled in with the first \funcparam{namesize} bytes of +the name of the default keytab. +If the name is shorter than \funcparam{namesize}, then the remainder of +\funcparam{name} will be zeroed. + + +\begin{funcdecl}{krb5_kt_default}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_keytab *}{id} +\end{funcdecl} + +Fills in \funcparam{id} with a handle identifying the default keytab. + +\begin{funcdecl}{krb5_kt_read_service_key}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_pointer}{keyprocarg} +\funcarg{krb5_principal}{principal} +\funcarg{krb5_kvno}{vno} +\funcarg{krb5_keytype}{keytype} +\funcout +\funcarg{krb5_keyblock **}{key} +\end{funcdecl} + +If \funcname{keyprocarg} is not NULL, it is taken to be a +\datatype{char *} denoting the name of a keytab. Otherwise, the default +keytab will be used. +The keytab is opened and searched for the entry identified by +\funcparam{principal}, \funcparam{keytype}, and \funcparam{vno}, +returning the resulting key +in \funcparam{*key} or returning an error code if it is not found. + +\funcname{krb5_free_keyblock} should be called on \funcparam{*key} when +the caller is finished with the key. + +Returns an error code if the entry is not found. + +\begin{funcdecl}{krb5_kt_add_entry}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_keytab}{id} +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +Calls the keytab-specific add routine \funcname{krb5_kt_add_internal} +with the same function arguments. If this routine is not available, +then KRB5_KT_NOWRITE is returned. + +\begin{funcdecl}{krb5_kt_remove_entry}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_keytab}{id} +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +Calls the keytab-specific remove routine +\funcname{krb5_kt_remove_internal} with the same function arguments. +If this routine is not available, then KRB5_KT_NOWRITE is returned. + +\begin{funcdecl}{krb5_kt_get_name}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keytab}{id} +\funcout +\funcarg{char *}{name} +\funcin +\funcarg{unsigned int}{namesize} +\end{funcdecl} + +\funcarg{name} is filled in with the first \funcparam{namesize} bytes of +the name of the keytab identified by \funcname{id}. +If the name is shorter than \funcparam{namesize}, then \funcarg{name} +will be null-terminated. + +\begin{funcdecl}{krb5_kt_close}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keytab}{id} +\end{funcdecl} + +Closes the keytab identified by \funcparam{id} and invalidates +\funcparam{id}, and releases any other resources acquired during use of +the key table. + +Requires that \funcparam{id} identifies a keytab. + +\begin{funcdecl}{krb5_kt_get_entry}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keytab}{id} +\funcin +\funcarg{krb5_principal}{principal} +\funcarg{krb5_kvno}{vno} +\funcarg{krb5_keytype}{keytype} +\funcout +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +\begin{sloppypar} +Searches the keytab identified by \funcparam{id} for an entry whose +principal matches \funcparam{principal}, whose keytype matches +\funcparam{keytype}, and +whose key version number matches \funcparam{vno}. If \funcparam{vno} is +zero, the first entry whose principal matches is returned. +\end{sloppypar} + +Returns an error code if no suitable entry is found. If an entry is +found, the entry is returned in \funcparam{*entry}; its contents should +be deallocated by calling \funcname{krb5_kt_free_entry} when no longer +needed. + +\begin{funcdecl}{krb5_kt_free_entry}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +Releases all storage allocated for \funcparam{entry}, which must point +to a structure previously filled in by \funcname{krb5_kt_get_entry} or +\funcname{krb5_kt_next_entry}. + +\begin{funcdecl}{krb5_kt_start_seq_get}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keytab}{id} +\funcout +\funcarg{krb5_kt_cursor *}{cursor} +\end{funcdecl} + +Prepares to read sequentially every key in the keytab identified by +\funcparam{id}. +\funcparam{cursor} is filled in with a cursor to be used in calls to +\funcname{krb5_kt_next_entry}. + +\begin{funcdecl}{krb5_kt_next_entry}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keytab}{id} +\funcout +\funcarg{krb5_keytab_entry *}{entry} +\funcinout +\funcarg{krb5_kt_cursor *}{cursor} +\end{funcdecl} + +Fetches the ``next'' entry in the keytab, returning it in +\funcparam{*entry}, and updates \funcparam{*cursor} for the next +request. If the keytab changes during the sequential get, an error is +guaranteed. \funcparam{*entry} should be freed after use by calling +\funcname{krb5_kt_free_entry}. + +Requires that \funcparam{id} identifies a valid keytab. and +\funcparam{*cursor} be a cursor returned by +\funcname{krb5_kt_start_seq_get} or a subsequent call to +\funcname{krb5_kt_next_entry}. + +Errors: error code if no more cache entries or if the keytab changes. + +\begin{funcdecl}{krb5_kt_end_seq_get}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_keytab}{id} +\funcarg{krb5_kt_cursor *}{cursor} +\end{funcdecl} + +Finishes sequential processing mode and invalidates \funcparam{cursor}, +which must never be re-used after this call. + +Requires that \funcparam{id} identifies a valid keytab and +\funcparam{*cursor} be a cursor returned by +\funcname{krb5_kt_start_seq_get} or a subsequent call to +\funcname{krb5_kt_next_entry}. + +May return error code if \funcparam{cursor} is invalid. + + diff --git a/krb5-1-6/doc/api/krb5.ist b/krb5-1-6/doc/api/krb5.ist new file mode 100644 index 000000000..36e9adb2b --- /dev/null +++ b/krb5-1-6/doc/api/krb5.ist @@ -0,0 +1,26 @@ +%% +%% This is based on the gind.ist +%% +actual '=' +quote '!' +level '>' +preamble +"\n \\begin{theindex} \n" +postamble +"\n\n \\end{theindex}\n" +item_x1 "\\efill \n \\subitem " +item_x2 "\\efill \n \\subsubitem " +delim_0 "\\pfill " +delim_1 "\\pfill " +delim_2 "\\pfill " +% The next lines will produce some warnings when +% running Makeindex as they try to cover two different +% versions of the program: +lethead_prefix "{\\bfseries\\hfil " +lethead_suffix "\\hfil}\\nopagebreak\n" +lethead_flag 1 +heading_prefix "{\\bfseries\\hfil " +heading_suffix "\\hfil}\\nopagebreak\n" +headings_flag 1 +%% +%% diff --git a/krb5-1-6/doc/api/krb5.tex b/krb5-1-6/doc/api/krb5.tex new file mode 100644 index 000000000..d70910ec0 --- /dev/null +++ b/krb5-1-6/doc/api/krb5.tex @@ -0,0 +1,1827 @@ +The main functions deal with the nitty-gritty details: verifying +tickets, creating authenticators, and the like. + +\subsubsection{The krb5_context} +The \datatype{krb5_context} is designed to represent the per process +state. When the library is made thread-safe, the context will represent +the per-thread state. Global parameters which are ``context'' specific +are stored in this structure, including default realm, default +encryption type, default configuration files and the like. Functions +exist to provide full access to the data structures stored in the +context and should not be accessed directly by developers. + +\begin{funcdecl}{krb5_init_context}{krb5_error_code}{\funcout} +\funcarg{krb5_context *}{context} +\end{funcdecl} + +Initializes the context \funcparam{*context} for the +application. Currently the context contains the encryption types, a +pointer to operating specific data and the default realm. In the future, +the context may be also contain thread specific data. The data in the +context should be freed with \funcname{krb5_free_context}. + +Returns system errors. + +\begin{funcdecl}{krb5_free_context}{void}{\funcinout} +\funcarg{krb5_context}{context} +\end{funcdecl} + +Frees the context returned by \funcname{krb5_init_context}. Internally +calls \funcname{krb5_os_free_context}. + +\begin{funcdecl}{krb5_set_default_in_tkt_etypes}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_enctype *}{etypes} +\end{funcdecl} + +Sets the desired default encryption type \funcparam{etypes} for the context +if valid. + +Returns {\sc enomem}, {\sc krb5_prog_etype_nosupp}. + +\begin{funcdecl}{krb5_get_default_in_tkt_etypes}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_enctype **}{etypes} +\end{funcdecl} + +Retrieves the default encryption types from the context and stores them +in \funcarg{etypes} which should be freed by the caller. + +Returns {\sc enomem}. + +\subsubsection{The krb5_auth_context} + +While the \datatype{krb5_context} represents a per-process or per-thread +context, the \datatype{krb5_auth_context} represents a per-connection +context are are used by the various functions involved directly in +client/server authentication. Some of the data stored in this context +include keyblocks, addresses, sequence numbers, authenticators, checksum +type, and replay cache pointer. + +\begin{funcdecl}{krb5_auth_con_init}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_auth_context *}{auth_context} +\end{funcdecl} + +The auth_context may be described as a per connection context. This +context contains all data pertinent to the the various authentication +routines. This function initializes the auth_context. + +The default flags for the context are set to enable the use of the replay cache +(KRB5_AUTH_CONTEXT_DO_TIME) but no sequence numbers. The function +\funcname{krb5_auth_con_setflags} allows the flags to be changed. + +The default checksum type is set to CKSUMTYPE_RSA_MD4_DES. This may be +changed with \funcname{krb5_auth_con_setcksumtype}. + +The auth_context structure should be freed with +\funcname{krb5_auth_con_free}. + +\begin{funcdecl}{krb5_auth_con_free}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\end{funcdecl} + +Frees the auth_context \funcparam{auth_context} returned by +\funcname{krb5_auth_con_init}. + +% perhaps some comment about which substructures are freed and which are not? + +\begin{funcdecl}{krb5_auth_con_setflags}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_int32}{flags} +\end{funcdecl} + +Sets the flags of \funcparam{auth_context} to funcparam{flags}. Valid +flags are: + +\begin{tabular}{ll} +\multicolumn{1}{c}{Symbol} & Meaning \\ +KRB5_AUTH_CONTEXT_DO_TIME & Use timestamps \\ +KRB5_AUTH_CONTEXT_RET_TIME & Save timestamps\\ &\ to output structure\\ +KRB5_AUTH_CONTEXT_DO_SEQUENCE & Use sequence numbers \\ +KRB5_AUTH_CONTEXT_RET_SEQUENCE & Copy sequence numbers \\ &\ to output structure\\ +\end{tabular} + + +\begin{funcdecl}{krb5_auth_con_getflags}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_int32 *}{flags} +\end{funcdecl} + +Retrievs the flags of \funcparam{auth_context}. + +\begin{funcdecl}{krb5_auth_con_setaddrs}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_address *}{local_addr} +\funcarg{krb5_address *}{remote_addr} +\end{funcdecl} + +Copies the \funcparam{local_addr} and \funcparam{remote_addr} into the +\funcparam{auth_context}. If either address is NULL, the previous +address remains in place. + +\begin{funcdecl}{krb5_auth_con_getaddrs}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_address **}{local_addr} +\funcarg{krb5_address **}{remote_addr} +\end{funcdecl} + +Retrieves \funcparam{local_addr} and \funcparam{remote_addr} from the +\funcparam{auth_context}. If \funcparam{local_addr} or +\funcparam{remote_addr} is not NULL, the memory is first freed with +\funcname{krb5_free_address} and then newly allocated. It is the callers +responsibility to free the returned addresses in this way. + + +\begin{funcdecl}{krb5_auth_con_setports}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_address *}{local_port} +\funcarg{krb5_address *}{remote_port} +\end{funcdecl} + +Copies the \funcparam{local_port} and \funcparam{remote_port} addresses +into the \funcparam{auth_context}. If either address is NULL, the previous +address remains in place. These addresses are set by +\funcname{krb5_auth_con_genaddrs}. + +\begin{funcdecl}{krb5_auth_con_setuserkey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_keyblock *}{keyblock} +\end{funcdecl} + +This function overloads the keyblock field. It is only useful prior to a +\funcname{krb5_rd_req_decode} call for user to user authentication where +the server has the key and needs to use it to decrypt the incoming +request. Once decrypted this key is no longer necessary and is then +overwritten with the session key sent by the client. + +\begin{funcdecl}{krb5_auth_con_getkey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_keyblock **}{keyblock} +\end{funcdecl} + +Retrieves the keyblock stored in \funcparam{auth_context}. The memory +allocated in this function should be freed with a call to +\funcname{krb5_free_keyblock}. + +\begin{funcdecl}{krb5_auth_con_getrecvsubkey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_keyblock **}{keyblock} +\end{funcdecl} + +Retrieves the recv\_subkey keyblock stored in +\funcparam{auth_context}. The memory allocated in this function should +be freed with a call to \funcname{krb5_free_keyblock}. + +\begin{funcdecl}{krb5_auth_con_getsendsubkey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_keyblock **}{keyblock} +\end{funcdecl} + +Retrieves the send\_subkey keyblock stored in +\funcparam{auth_context}. The memory allocated in this function should +be freed with a call to \funcname{krb5_free_keyblock}. + +\begin{funcdecl}{krb5_auth_con_setrecvsubkey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_keyblock *}{keyblock} +\end{funcdecl} + +Sets the recv\_subkey keyblock stored in \funcparam{auth_context}. + +\begin{funcdecl}{krb5_auth_con_setsendsubkey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_keyblock *}{keyblock} +\end{funcdecl} + +Sets the send\_subkey keyblock stored in \funcparam{auth_context}. + +\begin{funcdecl}{krb5_auth_setcksumtype}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_cksumtype}{cksumtype} +\end{funcdecl} + +Sets the checksum type used by the other functions in the library. + +\begin{funcdecl}{krb5_auth_getlocalseqnumber}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_int32 *}{seqnumber} +\end{funcdecl} + +Retrieves the local sequence number that was used during authentication +and stores it in \funcparam{seqnumber}. + +\begin{funcdecl}{krb5_auth_getremoteseqnumber}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_int32 *}{seqnumber} +\end{funcdecl} + +Retrieves the remote sequence number that was used during authentication +and stores it in \funcparam{seqnumber}. + +\begin{funcdecl}{krb5_auth_getauthenticator}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_authenticator **}{authenticator} +\end{funcdecl} + +Retrieves the authenticator that was used during mutual +authentication. It is the callers responsibility to free the memory +allocated to \funcparam{authenticator} by calling +\funcname{krb5_free_authenticator}. + +\begin{funcdecl}{krb5_auth_con_initivector}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\end{funcdecl} + +Allocates memory for and zeros the initial vector in the +\funcparam{auth_context} keyblock. + +\begin{funcdecl}{krb5_auth_con_setivector}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context *}{auth_context} +\funcin +\funcarg{krb5_pointer}{ivector} +\end{funcdecl} + +Sets the i_vector portion of \funcparam{auth_context} to +\funcparam{ivector}. + +\begin{funcdecl}{krb5_auth_con_setrcache}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{krb5_rcache}{rcache} +\end{funcdecl} + +Sets the replay cache that is used by the authentication routines to \funcparam{rcache}. + +%% +%% The following prototypes exist, but there is no code at this time +%% krb5_auth_con_getcksumtype, krb5_auth_con_getivector, +%% krb5_auth_con_getrcache. -- Ezra + +\subsubsection{Principal access functions} + +Principals define a uniquely named client or server instance that +participates in a network communication. The following functions allow +one to create, modify and access portions of the +\datatype{krb5_principal}. + +Other functions found in orther portions of the manual include +\funcname{krb5_sname_to_principal}, \funcname{krb5_free_principal}, + +While it is possible to directly access the data structure in the +structure, it is recommended that the functions be used. + +\begin{funcdecl}{krb5_parse_name}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const char *}{name} +\funcout +\funcarg{krb5_principal *}{principal} +\end{funcdecl} + +Converts a single-string representation \funcparam{name} of the +principal name to the multi-part principal format used in the protocols. + +A single-string representation of a Kerberos name consists of one or +more principal name components, separated by slashes, optionally +followed by the ``@'' character and a realm name. If the realm name +is not specified, the local realm is used. + +The slash and ``@'' characters may be quoted (i.e., included as part +of a component rather than as a component separator or realm prefix) +by preceding them with a backslash (``$\backslash$'') character. +Similarly, newline, tab, backspace, and null characters may be +included in a component by using $\backslash{}n$, $\backslash{}t$, +$\backslash{}b$ or $\backslash{}0$, respectively. + +The realm in a Kerberos name may not contain the slash, colon or null +characters. + +\funcparam{*principal} will point to allocated storage which should be freed by +the caller (using \funcname{krb5_free_principal}) after use. + +\funcname{krb5_parse_name} returns KRB5_PARSE_MALFORMED if the string is + badly formatted, or ENOMEM if space for the return value can't be +allocated. + +\begin{funcdecl}{krb5_unparse_name}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_const_principal}{principal} +\funcout +\funcarg{char **}{name} +\end{funcdecl} + +Converts the multi-part principal name \funcparam{principal} from the +format used in the protocols to a single-string representation of the +name. The resulting single-string representation will use the format +and quoting conventions described for \funcname{krb5_parse_name} +above. + +\funcparam{*name} points to allocated storage and should be freed by the caller +when finished. + +\funcname{krb5_unparse_name} returns {\sc KRB_PARSE_MALFORMED} if the principal +does not contain at least 2 components, and system errors ({\sc ENOMEM} if +unable to allocate memory). + +\begin{funcdecl}{krb5_unparse_name_ext}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_const_principal}{principal} +\funcinout +\funcarg{char **}{name} +\funcarg{unsigned int *}{size} +\end{funcdecl} + +\funcname{krb5_unparse_name_ext} is designed for applications which +must unparse a large number of principals, and are concerned about the +speed impact of needing to do a lot of memory allocations and +deallocations. It functions similarly to \funcname{krb5_unparse_name} +except if \funcparam{*name} is non-null, in which case, it is assumed +to contain an allocated buffer of size \funcparam{*size} and this +buffer will be resized with \funcname{realloc} to hold the unparsed +name. Note that in this case, +\funcparam{size} must not be null. + +If \funcparam{size} is non-null (whether or not \funcparam{*name} is +null when the function is called), it will be filled in with the size +of the unparsed name upon successful return. + +\begin{funcdecl}{krb5_princ_realm}{krb5_data *}{\funcinout} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\end{funcdecl} + +A macro which returns the realm of \funcparam{principal}. + +\begin{funcdecl}{krb5_princ_set_realm}{void}{\funcinout} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\funcparam{krb5_data *}{realm} +\end{funcdecl} + +A macro which returns sets the realm of \funcparam{principal} to +\funcparam{realm}. + +\begin{funcdecl}{krb5_princ_set_realm_data}{void}{\funcinout} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\funcparam{char *}{data} +\end{funcdecl} + +\internalfunc + +A macro which returns sets the data portion of the realm of +\funcparam{principal} to \funcparam{data}. + +\begin{funcdecl}{krb5_princ_set_realm_length}{void}{\funcinout} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\funcparam{int}{length} +\end{funcdecl} + +\internalfunc + +A macro which returns sets the length \funcparam{principal} to +\funcparam{length}. + +\begin{funcdecl}{krb5_princ_size}{void}{\funcinout} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\end{funcdecl} + +\internalfunc + +A macro which gives the number of elements in the principal. +May also be used on the left size of an assignment. + +\begin{funcdecl}{krb5_princ_type}{void}{\funcinout} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\end{funcdecl} + +\internalfunc + +A macro which gives the type of the principal. +May also be used on the left size of an assignment. + +\begin{funcdecl}{krb5_princ_data}{} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\end{funcdecl} + +\internalfunc + +A macro which gives the pointer to data portion of the principal. +May also be used on the left size of an assignment. + + +\begin{funcdecl}{krb5_princ_component}{} +\funcparam{krb5_context}{context} +\funcparam{krb5_principal}{principal} +\funcparam{int}{i} +\end{funcdecl} + +\internalfunc + +A macro which gives the pointer to ith element of the principal. +May also be used on the left size of an assignment. + +\begin{funcdecl}{krb5_build_principal}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_principal *}{princ} +\funcin +\funcarg{unsigned int}{rlen} +\funcarg{const char *}{realm} +\funcarg{char}{*s1, *s2, ..., 0} +\end{funcdecl} +\begin{funcdecl}{krb5_build_principal_va}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_principal *}{princ} +\funcin +\funcarg{unsigned int}{rlen} +\funcarg{const char *}{realm} +\funcarg{va_list}{ap} +\end{funcdecl} + +\begin{sloppypar} +\funcname{krb5_build_principal} and +\funcname{krb5_build_principal_va} +perform the same function; the former takes variadic arguments, while +the latter takes a pre-computed varargs pointer. +\end{sloppypar} + +Both functions take a realm name \funcparam{realm}, realm name length +\funcparam{rlen}, and a list of null-terminated strings, and fill in a +pointer to a principal structure \funcparam{princ}, making it point to a +structure representing the named principal. +The last string must be followed in the argument list by a null pointer. + + +\begin{funcdecl}{krb5_build_principal_ext}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_principal *}{princ} +\funcin +\funcarg{unsigned int}{rlen} +\funcarg{const char *}{realm} +\funcarg{}{int len1, char *s1, int len2, char *s2, ..., 0} +\end{funcdecl} + +\funcname{krb5_build_principal_ext} is similar to +\funcname{krb5_build_principal} but it takes its components as a list of +(length, contents) pairs rather than a list of null-terminated strings. +A length of zero indicates the end of the list. + +\begin{funcdecl}{krb5_copy_principal}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_const_principal}{inprinc} +\funcout +\funcarg{krb5_principal *}{outprinc} +\end{funcdecl} + +Copy a principal structure, filling in \funcparam{*outprinc} to point to +the newly allocated copy, which should be freed with +\funcname{krb5_free_principal}. + +\begin{funcdecl}{krb5_principal_compare}{krb5_boolean}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_const_principal}{princ1} +\funcarg{krb5_const_principal}{princ2} +\end{funcdecl} + +If the two principals are the same, return TRUE, else return FALSE. + +\begin{funcdecl}{krb5_realm_compare}{krb5_boolean}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_const_principal}{princ1} +\funcarg{krb5_const_principal}{princ2} +\end{funcdecl} + +If the realms of the two principals are the same, return TRUE, else +return FALSE. + + +\begin{funcdecl}{krb5_425_conv_principal}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const char *}{name} +\funcarg{const char *}{instance} +\funcarg{const char *}{realm} +\funcout +\funcarg{krb5_principal *}{princ} +\end{funcdecl} + +Build a principal \funcparam{princ} from a V4 specification made up of +\funcparam{name}.\funcparam{instance}@\funcparam{realm}. The routine is +site-customized to convert the V4 naming scheme to a V5 one. For +instance, the V4 ``rcmd'' is changed to ``host''. + +The returned principal should be freed with +\funcname{krb5_free_principal}. + +\subsubsection{The application functions} + +\begin{funcdecl}{krb5_encode_kdc_rep}{krb5_error_code}{\funcin} +\funcarg{const krb5_msgtype}{type} +\funcarg{const krb5_enc_kdc_rep_part *}{encpart} +\funcarg{krb5_encrypt_block *}{eblock} +\funcarg{const krb5_keyblock *}{client_key} +\funcinout +\funcarg{krb5_kdc_rep *}{dec_rep} +\funcout +\funcarg{krb5_data **}{enc_rep} +\end{funcdecl} + +\internalfunc + +Takes KDC rep parts in \funcparam{*rep} and \funcparam{*encpart}, and +formats it into \funcparam{*enc_rep}, using message type +\funcparam{type} and encryption key \funcparam{client_key} and +encryption block \funcparam{eblock}. + +\funcparam{enc_rep{\ptsto}data} will point to allocated storage upon +non-error return; the caller should free it when finished. + +Returns system errors. + +\begin{funcdecl}{krb5_decode_kdc_rep}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_data *}{enc_rep} +\funcarg{const krb5_keyblock *}{key} +\funcarg{const krb5_enctype}{etype} +\funcout +\funcarg{krb5_kdc_rep **}{dec_rep} +\end{funcdecl} + +\internalfunc + +Takes a KDC_REP message and decrypts encrypted part using +\funcparam{etype} and \funcparam{*key}, putting result in \funcparam{*dec_rep}. +The pointers in \funcparam{dec_rep} +are all set to allocated storage which should be freed by the caller +when finished with the response (by using \funcname{krb5_free_kdc_rep}). + + +If the response isn't a KDC_REP (tgs or as), it returns an error from +the decoding routines. + +Returns errors from encryption routines, system errors. + +\begin{funcdecl}{krb5_kdc_rep_decrypt_proc}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_keyblock *}{key} +\funcarg{krb5_const_pointer}{decryptarg} +\funcinout +\funcarg{krb5_kdc_rep *}{dec_rep} +\end{funcdecl} + +Decrypt the encrypted portion of \funcparam{dec_rep}, using the +encryption key \funcparam{key}. The parameter \funcparam{decryptarg} is +ignored. + +The result is in allocated storage pointed to by +\funcparam{dec_rep{\ptsto}enc_part2}, unless some error occurs. + +This function is suitable for use as the \funcparam{decrypt_proc} +argument to \funcname{krb5_get_in_tkt}. + +\begin{funcdecl}{krb5_encrypt_tkt_part}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_keyblock *}{srv_key} +\funcinout +\funcarg{krb5_ticket *}{dec_ticket} +\end{funcdecl} + +\internalfunc + +\begin{sloppypar} +Encrypts the unecrypted part of the ticket found in +\funcparam{dec_ticket{\ptsto}enc_part2} using +\funcparam{srv_key}, and places result in +\funcparam{dec_ticket{\ptsto}enc_part}. +The \funcparam{dec_ticket{\ptsto}enc_part} will be allocated by this +function. +\end{sloppypar} + +Returns errors from encryption routines, system errors + +\funcparam{enc_part{\ptsto}data} is allocated and filled in with +encrypted stuff. + +\begin{funcdecl}{krb5_decrypt_tkt_part}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_keyblock *}{srv_key} +\funcinout +\funcarg{krb5_ticket *}{dec_ticket} +\end{funcdecl} + +\internalfunc + +Takes encrypted \funcparam{dec_ticket{\ptsto}enc_part}, decrypts with +\funcparam{dec_ticket{\ptsto}etype} +using \funcparam{srv_key}, and places result in +\funcparam{dec_ticket{\ptsto}enc_part2}. The storage of +\funcparam{dec_ticket{\ptsto}enc_part2} will be allocated before return. + +Returns errors from encryption routines, system errors + +\begin{funcdecl}{krb5_send_tgs}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_flags}{kdcoptions} +\funcarg{const krb5_ticket_times *}{timestruct} +\funcarg{const krb5_enctype *}{etypes} +\funcarg{const krb5_cksumtype}{sumtype} +\funcarg{krb5_const_principal}{sname} +\funcarg{krb5_address * const *}{addrs} +\funcarg{krb5_authdata * const *}{authorization_data} +\funcarg{krb5_pa_data * const *}{padata} +\funcarg{const krb5_data *}{second_ticket} +\funcinout +\funcarg{krb5_creds *}{in_cred} +\funcout +\funcarg{krb5_response *}{rep} +\end{funcdecl} + +\internalfunc + +Sends a request to the TGS and waits for a response. +\funcparam{kdcoptions} is used for the options in the KRB_TGS_REQ. +\funcparam{timestruct} values are used for from, till, and rtime in the +KRB_TGS_REQ. +\funcparam{etypes} is a list of etypes used in the KRB_TGS_REQ. +\funcparam{sumtype} is used for the checksum in the AP_REQ in the KRB_TGS_REQ. +\funcparam{sname} is used for sname in the KRB_TGS_REQ. +\funcparam{addrs}, if non-NULL, is used for addresses in the KRB_TGS_REQ. +\funcparam{authorization_data}, if non-NULL, is used for +\funcparam{authorization_data} in the KRB_TGS_REQ. +\funcparam{padata}, if non-NULL, is combined with any other supplied +pre-authentication data for the KRB_TGS_REQ. +\funcparam{second_ticket}, if required by options, is used for the 2nd +ticket in the KRB_TGS_REQ. +\funcparam{in_cred} is used for the ticket and session key in the KRB_AP_REQ header in the KRB_TGS_REQ. + +The KDC realm is extracted from \funcparam{in_cred{\ptsto}server}'s realm. + +The response is placed into \funcparam{*rep}. +\funcparam{rep{\ptsto}response.data} is set to point at allocated storage +which should be freed by the caller when finished. + +Returns system errors. + +\begin{funcdecl}{krb5_get_cred_from_kdc}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_ccache}{ccache} +\funcarg{krb5_creds *}{in_cred} +\funcout +\funcarg{krb5_cred **}{out_cred} +\funcarg{krb5_creds ***}{tgts} +\end{funcdecl} + + +Retrieve credentials for principal \funcparam{in_cred{\ptsto}client}, +server \funcparam{creds{\ptsto}server}, possibly +\funcparam{creds{\ptsto}second_ticket} if needed by the ticket flags. + +\funcparam{ccache} is used to fetch initial TGT's to start the authentication +path to the server. + +Credentials are requested from the KDC for the server's realm. Any +TGT credentials obtained in the process of contacting the KDC are +returned in an array of credentials; \funcparam{tgts} is filled in to +point to an array of pointers to credential structures (if no TGT's were +used, the pointer is zeroed). TGT's may be returned even if no useful +end ticket was obtained. + +The returned credentials are NOT cached. + +If credentials are obtained, \funcparam{creds} is filled in with the results; +\funcparam{creds{\ptsto}ticket} and +\funcparam{creds{\ptsto}keyblock{\ptsto}key} are set to allocated storage, +which should be freed by the caller when finished. + +Returns errors, system errors. + +\begin{funcdecl}{krb5_get_cred_via_tkt}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_creds *}{tkt} +\funcarg{const krb5_flags}{kdcoptions} +\funcarg{krb5_address *const *}{address} +\funcarg{krb5_creds *}{in_cred} +\funcout +\funcarg{krb5_creds **}{out_cred} +\end{funcdecl} + +Takes a ticket \funcparam{tkt} and a target credential +\funcparam{in_cred}, attempts to fetch a TGS from the KDC. Upon +success the resulting is stored in \funcparam{out_cred}. The memory +allocated in \funcparam{out_cred} should be freed by the called when +finished by using \funcname{krb5_free_creds}. + +\funcparam{kdcoptions} refers to the options as listed in Table +\ref{KDCOptions}. The optional \funcparam{address} is used for addressed +in the KRB_TGS_REQ (see \funcname{krb5_send_tgs}). + +Returns errors, system errors. + + +\begin{funcdecl}{krb5_get_credentials}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_flags}{options} +\funcarg{krb5_ccache}{ccache} +\funcarg{krb5_creds *}{in_creds} +\funcout +\funcarg{krb5_creds *}{out_creds} +\end{funcdecl} + +This routine attempts to use the credentials cache \funcparam{ccache} or a TGS +exchange to get an additional ticket for the client identified by +\funcparam{in_creds{\ptsto}client}, with following information: +\begin{itemize} +\item {\bf The server} identified by \funcparam{in_creds{\ptsto}server} +\item {\bf The options} in \funcparam{options}. +Valid choices are KRB5_GC_USER_USER and KRB5_GC_GC_CACHED +\item {\bf The expiration date} specified in +\funcparam{in_creds{\ptsto}times.endtime} +\item {\bf The session key type} specified in +\funcparam{in_creds{\ptsto}keyblock.keytype} if it is non-zero. +\end{itemize} + +If \funcparam{options} specifies KRB5_GC_CACHED, +then \funcname{krb5_get_credentials} will only search the credentials cache +for a ticket. + +If \funcparam{options} specifies KRB5_GC_USER_USER, then +\funcname{krb5_get_credentials} will get credentials for a user to user +authentication. In a user to user authentication, the secret key for +the server +is the session key from the server's ticket-granting-ticket +(TGT). The TGT is passed from the server to the client over the +network --- this is safe since the TGT is encrypted in a key +known only by the Kerberos server --- and the client must pass +this TGT to \funcname{krb5_get_credentials} in +\funcparam{in_creds{\ptsto}second_ticket}. The Kerberos server will use +this TGT to construct a user to user ticket which can be verified by +the server by using the session key from its TGT. + +The effective {\bf expiration date} is the minimum of the following: +\begin{itemize} +\item The expiration date as specified in +\funcparam{in_creds{\ptsto}times.endtime} +\item The requested start time plus the maximum lifetime of the +server as specified by the server's entry in the +Kerberos database. +\item The requested start time plus the maximum lifetime of tickets +allowed in the local site, as specified by the KDC. +This is currently a compile-time option, +KRB5_KDB_MAX_LIFE in config.h, and is by default 1 day. +\end{itemize} + +If any special authorization data needs to be included in the ticket, +--- for example, restrictions on how the ticket can be used --- +they should be specified in \funcparam{in_creds{\ptsto}authdata}. If there +is no special authorization data to be passed, +\funcparam{in_creds{\ptsto}authdata} should be NULL. + +Any returned ticket and intermediate ticket-granting tickets are +stored in \funcparam{ccache}. + +Returns errors from encryption routines, system errors. + +\begin{funcdecl}{krb5_get_in_tkt}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_flags}{options} +\funcarg{krb5_address * const *}{addrs} +\funcarg{const krb5_enctype *}{etypes} +\funcarg{const krb5_preauthtype *}{ptypes} +\funcfuncarg{krb5_error_code}{(*key_proc)} + \funcarg{krb5_context}{context} + \funcarg{const krb5_keytype}{type} + \funcarg{krb5_data *}{salt} + \funcarg{krb5_const_pointer}{keyseed} + \funcarg{krb5_keyblock **}{key} +\funcendfuncarg +\funcarg{krb5_const_pointer}{keyseed} +\funcfuncarg{krb5_error_code}{(*decrypt_proc)} + \funcarg{krb5_context}{context} + \funcarg{const krb5_keyblock *}{key} + \funcarg{krb5_const_pointer}{decryptarg} + \funcarg{krb5_kdc_rep *}{dec_rep} +\funcendfuncarg +\funcarg{krb5_const_pointer}{decryptarg} +\funcinout +\funcarg{krb5_creds *}{creds} +\funcarg{krb5_ccache}{ccache} +\funcarg{krb5_kdc_rep **}{ret_as_reply} +\end{funcdecl} + +This all-purpose initial ticket routine, usually called via +\funcname{krb5_get_in_tkt_with_skey} or +\funcname{krb5_get_in_tkt_with_password} or +\funcname{krb5_get_in_tkt_with_keytab}. + + +Attempts to get an initial ticket for \funcparam{creds{\ptsto}client} +to use server \funcparam{creds{\ptsto}server}, using the following: +the realm from \funcparam{creds{\ptsto}client}; the options in +\funcparam{options} (listed in Table \ref{KDCOptions}); +and \funcparam{ptypes}, the preauthentication +method (valid preauthentication methods are listed in Table +\ref{padata-types}). +\funcname{krb5_get_in_tkt} requests encryption type +\funcparam{etypes} (valid encryption types are ETYPE_DES_CBC_CRC and +ETYPE_RAW_DES_CBC), +using \funcparam{creds{\ptsto}times.starttime}, +\funcparam{creds{\ptsto}times.endtime}, +\funcparam{creds{\ptsto}times.renew_till} +as from, till, and rtime. \funcparam{creds{\ptsto}times.renew_till} is +ignored unless the RENEWABLE option is requested. + +\funcparam{key_proc} is called, with \funcparam{context}, \funcparam{keytype}, +\funcparam{keyseed} and\funcparam{padata} as arguments, to fill in \funcparam{key} to be used for +decryption. The valid key types for \funcparam{keytype} are +KEYTYPE_NULL,\footnote{See RFC section 6.3.1} and +KEYTYPE_DES.\footnote{See RFC section 6.3.4} However, KEYTYPE_DES is +the only key type supported by MIT kerberos. +The content of \funcparam{keyseed} +depends on the \funcparam{key_proc} being used. %nlg - need a ref here +The \funcparam{padata} passed +to \funcparam{key_proc} is the preauthentication data returned by the +KDC as part of the reply to the initial ticket request. It may +contain an element of type KRB5_PADATA_PW_SALT, which +\funcparam{key_proc} should use to determine what salt to use when +generating the key. \funcparam{key_proc} should fill in +\funcparam{key} with a key for the client, or return an error code. + +\funcparam{decrypt_proc} is called to perform the decryption of the +response (the encrypted part is in +\funcparam{dec_rep{\ptsto}enc_part}; the decrypted part should be +allocated and filled into +\funcparam{dec_rep{\ptsto}enc_part2}. +\funcparam{decryptarg} is passed on to \funcparam{decrypt_proc}, and +its content depends on the \funcparam{decrypt_proc} being used. + +If \funcparam{addrs} is non-NULL, it is used for the addresses +requested. If it is null, the system standard addresses are used. + +If \funcparam{ret_as_reply} is non-NULL, it is filled in with a +pointer to a structure containing the reply packet from the KDC. Some +programs may find it useful to have direct access to this information. +For example, it can be used to obtain the pre-authentication data +passed back from the KDC. The caller is responsible for freeing this +structure by using \funcname{krb5_free_kdc_rep}. + +If \funcparam{etypes} is non-NULL, the it is used as for the list of +valid encyrption types. Otherwise, the context default is used (as +returned by \funcname{krb5_get_default_in_tkt_etypes}. + +A succesful call will place the ticket in the credentials cache +\funcparam{ccache} and fill in \funcparam{creds} with the ticket +information used/returned. + +Returns system errors, preauthentication errors, encryption errors. + +% XXX Right now, uses creds->addresses before it's copied into from +% the reply -- it's passed to krb5_obtain_padata. I think that's +% wrong, and it should be using either addrs or the result of +% krb5_os_localaddr instead. If I'm wrong, then this spec has to be +% updated to document that creds->addresses is used. On the other +% hand, if I'm right, then the bug in get_in_tkt needs to be fixed. +% See ov-cambridge PR 1525. + +\begin{funcdecl}{krb5_get_in_tkt_with_password}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_flags}{options} +\funcarg{krb5_address * const *}{addrs} +\funcarg{const krb5_enctype *}{etypes} +\funcarg{const krb5_preauthtype *}{pre_auth_types} +\funcarg{const char *}{password} +\funcarg{krb5_ccache}{ccache} +\funcinout +\funcarg{krb5_creds *}{creds} +\funcarg{krb5_kdc_rep **}{ret_as_reply} +\end{funcdecl} + +Attempts to get an initial ticket using the null-terminated string +\funcparam{password}. If \funcparam{password} is NULL, the password +is read from the terminal using as a prompt the globalname +\globalname{krb5_default_pwd_prompt1}. + +The password is converted into a key using the appropriate +string-to-key conversion function for the specified +\funcparam{keytype}, and using any salt data returned by the KDC in +response to the authentication request. + +See \funcname{krb5_get_in_tkt} for documentation of the +\funcparam{options}, \funcparam{addrs}, \funcparam{pre_auth_type}, +\funcparam{etype}, \funcparam{keytype}, \funcparam{ccache}, +\funcparam{creds} and \funcparam{ret_as_reply} arguments. + +Returns system errors, preauthentication errors, encryption errors. + +\begin{funcdecl}{krb5_get_in_tkt_with_keytab}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_flags}{options} +\funcarg{krb5_address * const *}{addrs} +\funcarg{const krb5_enctype *}{etypes} +\funcarg{const krb5_preauthtype *}{pre_auth_types} +\funcarg{const krb5_keytab *}{keytab} +\funcarg{krb5_ccache}{ccache} +\funcinout +\funcarg{krb5_creds *}{creds} +\funcarg{krb5_kdc_rep **}{ret_as_reply} +\end{funcdecl} + +Attempts to get an initial ticket using \funcparam{keytab}. If +\funcparam{keytab} is NULL, the default keytab is used +(e.g., \filename{/etc/v5srvtab}). + +See \funcname{krb5_get_in_tkt} for documentation of the +\funcparam{options}, \funcparam{addrs}, \funcparam{pre_auth_type}, +\funcparam{etype}, \funcparam{ccache}, \funcparam{creds} and +\funcparam{ret_as_reply} arguments. + +Returns system errors, preauthentication errors, encryption errors. + +\begin{funcdecl}{krb5_get_in_tkt_with_skey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_flags}{options} +\funcarg{krb5_address * const *}{addrs} +\funcarg{const krb5_enctype *}{etypes} +\funcarg{const krb5_preauthtype *}{pre_auth_types} +\funcarg{const krb5_keyblock *}{key} +\funcarg{krb5_ccache}{ccache} +\funcinout +\funcarg{krb5_creds *}{creds} +\funcarg{krb5_kdc_rep **}{ret_as_reply} +\end{funcdecl} + +Attempts to get an initial ticket using \funcparam{key}. If +\funcparam{key} is NULL, an appropriate key is retrieved from the +system key store (e.g., \filename{/etc/v5srvtab}). + +See \funcname{krb5_get_in_tkt} for documentation of the +\funcparam{options}, \funcparam{addrs}, \funcparam{pre_auth_type}, +\funcparam{etype}, \funcparam{ccache}, \funcparam{creds} and +\funcparam{ret_as_reply} arguments. + +Returns system errors, preauthentication errors, encryption errors. + +\begin{funcdecl}{krb5_mk_req}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context *}{auth_context} +\funcin +\funcarg{const krb5_flags}{ap_req_options} +\funcarg{char *}{service} +\funcarg{char *}{hostname} +\funcarg{krb5_data *}{in_data} +\funcinout +\funcarg{krb5_ccache}{ccache} +\funcout +\funcarg{krb5_data *}{outbuf} +\end{funcdecl} + +Formats a KRB_AP_REQ message into \funcparam{outbuf}. + +The server to receive the message is specified by +\funcparam{hostname}. The principal of the server to receive the message +is specified by \funcparam{hostname} and \funcparam{service}. +If credentials are not present in the credentials cache +\funcparam{ccache} for this server, the TGS request with default +parameters is used in an attempt to obtain such credentials, and they +are stored in \funcparam{ccache}. + +\funcparam{ap_req_options} specifies the KRB_AP_REQ options desired. +Valid options are: + +\begin{tabular}{ll} +AP_OPTS_USE_SESSION_KEY&\\ +AP_OPTS_MUTUAL_REQUIRED&\\ +\end{tabular} +\label{ap-req-options} + +The checksum method to be used is as specified in \funcparam{auth_context}. + +% XXX Not sure if it's legal in the protocol for no checksum to be +% included, or if so, how the server reacts to a request with no +% checksum. + +\funcparam{outbuf} should point to an existing \datatype{krb5_data} +structure. \funcparam{outbuf{\ptsto}length} and +\funcparam{outbuf{\ptsto}data} will be filled in on success, and the latter +should be freed by the caller when it is no longer needed; if an error +is returned, however, no storage is allocated and {\tt +outbuf{\ptsto}data} does not need to be freed. + +Returns system errors, error getting credentials for +\funcparam{server}. + +\begin{funcdecl}{krb5_mk_req_extended}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context *}{auth_context} +\funcin +\funcarg{const krb5_flags}{ap_req_options} +\funcarg{krb5_data *}{in_data} +\funcarg{krb5_creds *}{in_creds} +\funcout +\funcarg{krb5_data *}{outbuf} +\end{funcdecl} + +Formats a KRB_AP_REQ message into \funcparam{outbuf}, with more complete +options than \funcname{krb5_mk_req}. + +\funcparam{outbuf}, \funcparam{ap_req_options}, \funcparam{auth_context}, +and \funcparam{ccache} are used in the same fashion as for +\funcname{krb5_mk_req}. + +\funcparam{in_creds} is used to supply the credentials (ticket and session +key) needed to form the request. + +If \funcparam{in_creds{\ptsto}ticket} has no data (length == 0), then an +error is returned. + +During this call, the structure elements in \funcparam{in_creds} may be +freed and reallocated. Hence all of the structure elements which are +pointers should point to allocated memory, and there should be no other +pointers aliased to the same memory, since it may be deallocated during +this procedure call. + + +If \funcparam{ap_req_options} specifies AP_OPTS_USE_SUBKEY, then a +subkey will be generated if need be by \funcname{krb5_generate_subkey}. + +A copy of the authenticator will be stored in the +\funcparam{auth_context}, with the principal and checksum fields nulled +out, unless an error is returned. (This is to prevent pointer sharing +problems; the caller shouldn't need these fields anyway, since the +caller supplied them.) + +Returns system errors, errors contacting the KDC, KDC errors getting +a new ticket for the authenticator. + +\begin{funcdecl}{krb5_generate_subkey}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_keyblock *}{key} +\funcout +\funcarg{krb5_keyblock **}{subkey} +\end{funcdecl} + +Generates a pseudo-random sub-session key using the encryption system's +random key functions, based on the input \funcparam{key}. + +\funcparam{subkey} is filled in to point to the generated subkey, unless +an error is returned. The returned key (i.e., \funcparam{*subkey}) is +allocated and should be freed by the caller with +\funcname{krb5_free_keyblock} when it is no longer needed. + +\begin{funcdecl}{krb5_rd_req}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context *}{auth_context} +\funcin +\funcarg{const krb5_data *}{inbuf} +\funcarg{krb5_const_principal}{server} +\funcarg{krb5_keytab}{keytab} +\funcinout +\funcarg{krb5_flags *}{ap_req_options} +\funcout +\funcarg{krb5_ticket **}{ticket} +\end{funcdecl} + +Parses a KRB_AP_REQ message, returning its contents. Upon successful +return, if \funcparam{ticket} is non-NULL, \funcparam{*ticket} will be +modified to point to allocated storage containing the ticket +information. The caller is responsible for deallocating this space by +using \funcname{krb5_free_ticket}. + +\funcparam{inbuf} should contain the KRB_AP_REQ message to be parsed. + +If \funcparam{auth_context} is NULL, one will be generated and freed +internally by the function. + +\funcparam{server} specifies the expected server's name for the ticket. +If \funcparam{server} is NULL, then any server name will be accepted if +the appropriate key can be found, and the caller should verify that the +server principal matches some trust criterion. + +If \funcparam{server} is not NULL, and a replay detaction cache has not been +established with the \funcparam{auth_context}, one will be generated. + +\funcparam{keytab} specifies a keytab containing generate a decryption key. If +NULL, \funcparam{krb5_kt_default} will be used to find the default +keytab and the key taken from there\footnote{i.e., srvtab file in +Kerberos V4 parlance}. + + +If a keyblock is present in the \funcparam{auth_context}, it will be +used to decrypt the ticket request and the keyblock freed with +\funcname{krb5_free_keyblock}. This is useful for user to user +authentication. If no keyblock is specified, the \funcparam{keytab} is +consulted for an entry matching the requested keytype, server and +version number and used instead. + +The authentcator in the request is decrypted and stored in the +\funcparam{auth_context}. The client specified in the decrypted +authenticator is compared to the client specified in the decoded ticket +to ensure that the compare. + +If the remote_addr portion of the \funcparam{auth_context} is set, +then this routine checks if the request came from the right client. + +\funcparam{sender_addr} specifies the address(es) expected to be present +in the ticket. + +The replay cache is checked to see if the ticket and authenticator have +been seen and if so, returns an error. If not, the ticket and +authenticator are entered into the cache. + +Various other checks are made of the decoded data, including, +cross-realm policy, clockskew and ticket validation times. + +The keyblock, subkey, and sequence number of the request are all stored +in the \funcparam{auth_context} for future use. + +If the request has the AP_OPTS_MUTUAL_REQUIRED bit set, the local +sequence number, which is stored in the auth_context, is XORed with the +remote sequence number in the request. + +If \funcparam{ap_req_options} is non-NULL, it will be set to contain the +application request flags. + +Returns system errors, encryption errors, replay errors. + +\begin{funcdecl}{krb5_rd_req_decoded}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context *}{auth_context} +\funcin +\funcarg{const krb5_ap_req *}{req} +\funcarg{krb5_const_principal}{server} +\funcinout +\funcarg{krb5_keytab}{keytab} +\funcout +\funcarg{krb5_ticket **}{ticket} +\end{funcdecl} + +Essentially the same as \funcname{krb5_rd_req}, but uses a decoded AP_REQ +as the input rather than an encoded input. + +\begin{funcdecl}{krb5_mk_rep}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcout +\funcarg{krb5_data *}{outbuf} +\end{funcdecl} + +Formats and encrypts an AP_REP message, including in it the data in the +authentp portion of \funcparam{auth_context}, encrypted using the +keyblock portion of \funcparam{auth_context}. + +When successful, \funcparam{outbuf{\ptsto}length} and +\funcparam{outbuf{\ptsto}data} are filled in with the length of the +AP_REQ message and allocated data holding it. +\funcparam{outbuf{\ptsto}data} should be freed by the +caller when it is no longer needed. + +If the flags in \funcparam{auth_context} indicate that a sequence number +should be used (either {\sc KRB5_AUTH_CONTEXT_DO_SEQUENCE} or +{\sc KRB5_AUTH_CONTEXT_RET_SEQUENCE}) and the local sequqnce number in the +\funcparam{auth_context} is 0, a new number will be generated with +\funcname{krb5_generate_seq_number}. + +Returns system errors. + +\begin{funcdecl}{krb5_rd_rep}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{const krb5_data *}{inbuf} +\funcout +\funcarg{krb5_ap_rep_enc_part **}{repl} +\end{funcdecl} + +Parses and decrypts an AP_REP message from \funcparam{*inbuf}, filling in +\funcparam{*repl} with a pointer to allocated storage containing the +values from the message. The caller is responsible for freeing this +structure with \funcname{krb5_free_ap_rep_enc_part}. + +The keyblock stored in \funcparam{auth_context} is used to decrypt the +message after establishing any key pre-processing with +\funcname{krb5_process_key}. + +Returns system errors, encryption errors, replay errors. + +\begin{funcdecl}{krb5_mk_error}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_error *}{dec_err} +\funcout +\funcarg{krb5_data *}{enc_err} +\end{funcdecl} + +Formats the error structure \funcparam{*dec_err} into an error buffer +\funcparam{*enc_err}. + +The error buffer storage (\funcparam{enc_err{\ptsto}data}) is +allocated, and should be freed by the caller when finished. + +Returns system errors. + +\begin{funcdecl}{krb5_rd_error}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_data *}{enc_errbuf} +\funcout +\funcarg{krb5_error **}{dec_error} +\end{funcdecl} + +Parses an error protocol message from \funcparam{enc_errbuf} and fills in +\funcparam{*dec_error} with a pointer to allocated storage containing +the error message. The caller is reponsible for freeing this structure by +using \funcname{krb5_free_error}. + +Returns system errors. + +\begin{funcdecl}{krb5_generate_seq_number}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_keyblock *}{key} +\funcout +\funcarg{krb5_int32 *}{seqno} +\end{funcdecl} + +Generates a pseudo-random sequence number suitable for use as an initial +sequence number for the KRB_SAFE and KRB_PRIV message processing +routines. + +\funcparam{key} parameterizes the choice of the random sequence number, +which is filled into \funcparam{*seqno} upon return. + +\begin{funcdecl}{krb5_sendauth}{krb5_error_code} +\funcinout +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context *}{auth_context} +\funcin +\funcarg{krb5_pointer}{fd} +\funcarg{char *}{appl_version} +\funcarg{krb5_principal}{client} +\funcarg{krb5_principal}{server} +\funcarg{krb5_flags}{ap_req_options} +\funcarg{krb5_data *}{in_data} +\funcarg{krb5_creds *}{in_creds} +\funcinout +\funcarg{krb5_ccache}{ccache} +\funcout +\funcarg{krb5_error **}{error} +\funcarg{krb5_ap_rep_enc_part **}{rep_result} +\funcarg{krb5_creds **}{out_creds} +\end{funcdecl} + +\funcname{krb5_sendauth} provides a convenient means for client and +server programs to send authenticated messages to one another through +network connections. \funcname{krb5_sendauth} sends an authenticated +ticket from the client program to the server program using the network +connection specified by \funcparam{fd}. In the MIT Unix implementation, +\funcparam{fd} should be a pointer to a file descriptor describing the +network socket. This can be changed in other implementations, however, +if the routines \funcname{krb5_read_message}, +\funcname{krb5_write_message}, \funcname{krb5_net_read}, and +\funcname{krb5_net_write} are changed. + +The paramter \funcparam{appl_version} is a string describing the +application protocol version which the client is expecting to use for +this exchange. If the server is using a different application protocol, +an error will be returned. + +The parameters \funcparam{client} and \funcparam{server} specify the +kerberos principals for the client and the server. They are +ignored if \funcparam{in_creds} is non-null. Otherwise, +\funcparam{server} must be non-null, but \funcparam{client} may be +null, in which case the client principal used is the one in the +credential cache's default principal. + +The \funcparam{ap_req_options} parameters specifies the options which +should be passed to \funcname{krb5_mk_req}. Valid options are listed +in Table \ref{ap-req-options}. If \funcparam{ap_req_options} +specifies MUTUAL_REQUIRED, then \funcname{krb5_sendauth} will perform +a mutual authentication exchange, and if \funcparam{rep_result} is +non-null, it will be filled in with the result of the mutual +authentication exchange; the caller should free +\funcparam{*rep_result} with +\funcname{krb5_free_ap_rep_enc_part} when done with it. + +If \funcparam{in_creds} is non-null, then +\funcparam{in_creds{\ptsto}client} and +\funcparam{in_creds{\ptsto}server} must be filled in, and either +the other structure fields should be filled in with valid credentials, +or \funcparam{in_creds{\ptsto}ticket.length} should be zero. If +\funcparam{in_creds{\ptsto}ticket.length} is non-zero, then +\funcparam{in_creds} will be used as-is as the credentials to send to +the server, and \funcparam{ccache} is ignored; otherwise, +\funcparam{ccache} is used as described below, and \funcparam{out_creds} +, if not NULL, is filled in with the retrieved credentials. + +\funcname{ccache} specifies the credential cache to use when one is +needed (i.e., when \funcname{in_creds} is null or +\funcparam{in_creds{\ptsto}ticket.length} is zero). When a credential +cache is not needed, \funcname{ccache} is ignored. When a credential +cache is needed and \funcname{ccache} is null, the default credential +cache is used. Note that if the credential cache is needed and does +not contain the needed credentials, they will be retrieved from the +KDC and stored in the credential cache. + +If mutual authentication is used and \funcparam{rep_result} is non-null, +the sequence number for the server is available to the caller in +\funcparam{*rep_result->seq_number}. (If mutual authentication is not +used, there is no way to negotiate a sequence number for the server.) + +If an error occurs during the authenticated ticket exchange and +\funcparam{error} is non-null, the error packet (if any) that was sent +from the server will be placed in it. This error should be freed with +\funcname{krb5_free_error}. + +\begin{funcdecl}{krb5_recvauth}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context *}{auth_context} +\funcin +\funcarg{krb5_pointer}{fd} +\funcarg{char *}{appl_version} +\funcarg{krb5_principal}{server} +\funcarg{char *}{rc_type} +\funcarg{krb5_int32}{flags} +\funcarg{krb5_keytab}{keytab} +\funcout +\funcarg{krb5_ticket **}{ticket} +\end{funcdecl} + +\funcname{krb5_recvauth} provides a convenient means for client and +server programs to send authenticated messages to one another through +network connections. \funcname{krb5_sendauth} is the matching routine +to \funcname{krb5_recvauth} for the server. \funcname{krb5_recvauth} +will engage in an authentication dialogue with the +client program running \funcname{krb5_sendauth} to authenticate the +client to the server. In addition, if requested by the client, +\funcname{krb5_recvauth} will provide mutual authentication to +prove to the client that the server represented by +\funcname{krb5_recvauth} is legitimate. + +\funcparam{fd} is a pointer to the network connection. As in +\funcname{krb5_sendauth}, in the MIT Unix implementation +\funcparam{fd} is a pointer to a file descriptor. + +The parameter \funcparam{appl_version} is a string describing the +application protocol version which the server is expecting to use for +this exchange. If the client is using a different application protocol, +an error will be returned and the authentication exchange will be +aborted. + +If \funcparam{server} is non-null, then \funcname{krb5_recvauth} +verifies that the server principal requested by the client matches +\funcparam{server}. If not, an error will be returned and the +authentication exchange will be aborted. + +The parameters \funcparam{server}, \funcparam{auth_context}, +and \funcparam{keytab} are used by \funcname{krb5_rd_req} to obtain the +server's private key. + +If \funcparam{server} is non-null, the princicpal component of it is +ysed to determine the replay cache to use. Otherwise, +\funcname{krb5_recvauth} will use a default replay cache. + +The \funcparam{flags} argument allows the caller to modify the behavior of +\funcname{krb5_recvauth}. For non-library callers, \funcparam{flags} +should be 0. + +% XXX Note that if the bug I submitted entitled ``"flags" argument +% should not have been added to krb5_recvauth'' (OpenVision Cambridge +% bug number 1585) causes code changes, this will have to be updated. + +\funcparam{ticket} is optional and is only filled in if non-null. It is +filled with the data from the ticket sent by the client, and should be +freed with +\funcname{krb5_free_ticket} when it is no longer needed. + +\begin{funcdecl}{krb5_mk_safe}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{const krb5_data *}{userdata} +\funcout +\funcarg{krb5_data *}{outbuf} +\funcinout +\funcarg{krb5_replay_data *}{outdata} +\end{funcdecl} + +Formats a KRB_SAFE message into \funcparam{outbuf}. + +\funcparam{userdata} is formatted as the user data in the message. +Portions of \funcparam{auth_context} specify the checksum type; the +keyblockm which might be used to seed the checksum; +full addresses (host and port) for the sender and receiver. +The \funcparam{local_addr} portion of \funcparam{*auth_context} +is used to form the addresses usedin the KRB_SAFE message. The \funcparam{remote_addr} is optional; if the +receiver's address is not known, it may be replaced by NULL. +\funcparam{local_addr}, however, is mandatory. + +The \funcparam{auth_context} flags select whether sequence numbers or +timestamps should be used to identify the message. Valid flags are +listed below. + +\begin{tabular}{ll} +\multicolumn{1}{c}{Symbol} & Meaning \\ +KRB5_AUTH_CONTEXT_DO_TIME & Use timestamps\\ + &\ and replay cache\\ +KRB5_AUTH_CONTEXT_RET_TIME & Copy timestamp \\ + &\ to \funcparam{*outdata} \\ +KRB5_AUTH_CONTEXT_DO_SEQUENCE & Use sequence numbers \\ +KRB5_AUTH_CONTEXT_RET_SEQUENCE & Copy sequence numbers\\ + &\ to \funcparam{*outdata} \\ +\end{tabular} + +If timestamps are to be used (i.e., if KRB5_AUTH_CONTEXT_DO_TIME is +set), an entry describing the message will be entered in the replay +cache so that the caller may detect if this message is sent +back to him by an attacker. If KRB5_AUTH_CONTEXT_DO_TIME is not set, +the \funcparam{auth_context} replay cache is not used. + +If sequence numbers are to be used (i.e., if either +KRB5_AUTH_CONTEXT_DO_SEQUENCE or KRB5_AUTH_CONTEXT_RET_SEQUENEC is +set), then \funcparam{auth_context} local sequence number will be +placed in the protected message as its sequence number. + +The \funcparam{outbuf} buffer storage (i.e., +\funcparam{outbuf{\ptsto}data}) is allocated, and should be freed by +the caller when finished. + +Returns system errors, encryption errors. + +\begin{funcdecl}{krb5_rd_safe}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{const krb5_data *}{inbuf} +\funcout +\funcarg{krb5_data *}{outbuf} +\funcinout +\funcarg{krb5_replay_data *}{outdata} +\end{funcdecl} + +Parses a KRB_SAFE message from \funcparam{inbuf}, placing the +data in \funcparam{*outbuf} after verifying its integrity. + +The keyblock used for verifying the integrity of the message is taken +from the \funcparam{auth_context} recv\_subkey or keyblock. The +keyblock is chosen in the above order by the first one which is not +NULL. + +The remote_addr and localaddr portions of the \funcparam{*auth_context} +specify the full addresses (host and port) of the sender and receiver, +and must be of type \datatype{ADDRTYPE_ADDRPORT}. + + +The \funcparam{remote_addr} parameter is mandatory; it +specifies the address of the sender. If the address of the sender in +the message does not match \funcparam{remote_addr}, the error +KRB5KRB_AP_ERR_BADADDR will be returned. + +If \funcparam{local_addr} is non-NULL, then the address of the receiver +in the message much match it. If it is null, the receiver address in +the message will be checked against the list of local addresses as +returned by \funcname{krb5_os_localaddr}. If the check fails, +KRB5KRB_AP_ERR_BADARRD is returned. + +The \funcparam{outbuf} buffer storage (i.e., +\funcparam{outbuf{\ptsto}data} is allocated storage which the caller +should free when it is no longer needed. + +If auth_context_flags portion of \funcparam{auth_context} indicates +that sequence numbers are to be used (i.e., if KRB5_AUTH_CONTEXT_DOSEQUENCE is +set in it), The \funcparam{remote_seq_number} portion of +\funcparam{auth_context} is compared to the sequence number for the +message, and KRB5_KRB_AP_ERR_BADORDER is returned if it does not match. +Otherwise, the sequence number is not used. + + +If timestamps are to be used (i.e., if KRB5_AUTH_CONTEXT_DO_TIME is set +in the \funcparam{auth_context}), then two additional checks are performed: +\begin{itemize} +\item The timestamp in the message must be within the permitted clock + skew (which is usually five minutes), or KRB5KRB_AP_ERR_SKEW + is returned. +\item The message must not be a replayed message, according to + \funcparam{rcache}. +\end{itemize} + +Returns system errors, integrity errors. + +\begin{funcdecl}{krb5_mk_priv}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{const krb5_data *}{userdata} +\funcout +\funcarg{krb5_data *}{outbuf} +\funcarg{krb5_replay_data *}{outdata} +\end{funcdecl} + +Formats a KRB_PRIV message into \funcparam{outbuf}. Behaves similarly +to \funcname{krb5_mk_safe}, but the message is encrypted and +integrity-protected rather than just integrity-protected. + +\funcparam{inbuf}, \funcparam{auth_context}, +\funcparam{outdata} and +\funcparam{outbuf} function as in \funcname{krb5_mk_safe}. + +As in \funcname{krb5_mk_safe}, the remote_addr and remote_port part of +the \funcparam{auth_context} is optional; if the receiver's address is +not known, it may be replaced by NULL. The local_addr, however, is +mandatory. + +The encryption type is taken from the \funcparam{auth_context} keyblock +portion. If i_vector portion of the \funcparam{auth_context} +is non-null, it is used as an initialization vector for the encryption +(if the chosen encryption type supports initialization vectors) +and its contents are replaced with the last block of encrypted data +upon return. + +The flags from the \funcparam{auth_context} selects whether sequence numbers or timestamps +should be used to identify the message. Valid flags are listed below. + +\begin{tabular}{ll} +\multicolumn{1}{c}{Symbol} & Meaning \\ +KRB5_AUTH_CONTEXT_DO_TIME& Use timestamps in replay cache\\ +KRB5_AUTH_CONTEXT_RET_TIME& Use timestamps in output data\\ +KRB5_AUTH_CONTEXT_DO_SEQUENCE& Use sequence numbers\\ + &\ in replay cache\\ +KRB5_AUTH_CONTEXT_RET_SEQUENCE& Use sequence numbers\\ + &\ in replay cache and output data \\ +\end{tabular} + +Returns system errors, encryption errors. + +\begin{funcdecl}{krb5_rd_priv}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_auth_context}{auth_context} +\funcin +\funcarg{const krb5_data *}{inbuf} +\funcout +\funcarg{krb5_data *}{outbuf} +\funcarg{krb5_data *}{outdata} +\end{funcdecl} + +Parses a KRB_PRIV message from \funcparam{inbuf}, placing the data in +\funcparam{*outbuf} after decrypting it. Behaves similarly to +\funcname{krb5_rd_safe}, but the message is decrypted rather than +integrity-checked. + +\funcparam{inbuf}, \funcparam{auth_context}, +\funcparam{outdata} and \funcparam{outbuf} +function as in \funcname{krb5_rd_safe}. + + +The remote_addr part of the \funcparam{auth_context} as set by +\funcname{krb5_auth_con_setaddrs} is mandatory; it +specifies the address of the sender. If the address of the sender in +the message does not match the remote_addr, the error +KRB5KRB_AP_ERR_BADADDR will be returned. + +If local_addr portion of the auth_context is non-NULL, then the address +of the receiver in the message much match it. If it is null, the +receiver address in the message will be checked against the list of +local addresses as returned by \funcname{krb5_os_localaddr}. + +The \funcparam{keyblock} portion of \funcparam{auth_context} specifies +the key to be used for decryption of the message. If the +\funcparam{i_vector} element, is non-null, it is used as an +initialization vector for the decryption (if the encryption type of the +message supports initialization vectors) and its contents are replaced +with the last block of encrypted data in the message. + +The \funcparam{auth_context} flags specify whether timestamps +(KRB5_AUTH_CONTEXT_DO_TIME) and sequence numbers +(KRB5_AUTH_CONTEXT_DO_SEQUENCE) are to be used. + +Returns system errors, integrity errors. + +\subsubsection{Miscellaneous main functions} + +\begin{funcdecl}{krb5_address_search}{krb5_boolean}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_address *}{addr} +\funcarg{krb5_address * const *}{addrlist} +\end{funcdecl} + +If \funcparam{addr} is listed in \funcparam{addrlist}, or +\funcparam{addrlist} is null, return TRUE. If not listed, return FALSE. + +\begin{funcdecl}{krb5_address_compare}{krb5_boolean}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_address *}{addr1} +\funcarg{const krb5_address *}{addr2} +\end{funcdecl} + +If the two addresses are the same, return TRUE, else return FALSE. + +\begin{funcdecl}{krb5_fulladdr_order}{int}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_fulladdr *}{addr1} +\funcarg{const krb5_fulladdr *}{addr2} +\end{funcdecl} + +Return an ordering on the two full addresses: 0 if the same, +$< 0$ if first is less than 2nd, $> 0$ if first is greater than 2nd. + +\begin{funcdecl}{krb5_address_order}{int}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_address *}{addr1} +\funcarg{const krb5_address *}{addr2} +\end{funcdecl} + +Return an ordering on the two addresses: 0 if the same, +$< 0$ if first is less than 2nd, $> 0$ if first is greater than 2nd. + +\begin{funcdecl}{krb5_copy_addresses}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_address * const *}{inaddr} +\funcout +\funcarg{krb5_address ***}{outaddr} +\end{funcdecl} + +Copy addresses in \funcparam{inaddr} to \funcparam{*outaddr} which is +allocated memory and should be freed with \funcname{krb5_free_addresses}. + +\begin{funcdecl}{krb5_copy_authdata}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_authdata * const *}{inauthdat} +\funcout +\funcarg{krb5_authdata ***}{outauthdat} +\end{funcdecl} + +Copy an authdata structure, filling in \funcparam{*outauthdat} to point to the +newly allocated copy, which should be freed with +\funcname{krb5_free_authdata}. + +\begin{funcdecl}{krb5_copy_authenticator}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_authenticator *}{authfrom} +\funcout +\funcarg{krb5_authenticator **}{authto} +\end{funcdecl} + +Copy an authenticator structure, filling in \funcparam{*outauthdat} to +point to the newly allocated copy, which should be freed with +\funcname{krb5_free_authenticator}. + +\begin{funcdecl}{krb5_copy_keyblock}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_keyblock *}{from} +\funcout +\funcarg{krb5_keyblock **}{to} +\end{funcdecl} + +Copy a keyblock, filling in \funcparam{*to} to point to the newly +allocated copy, which should be freed with +\funcname{krb5_free_keyblock}. + +\begin{funcdecl}{krb5_copy_keyblock_contents}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_keyblock *}{from} +\funcout +\funcarg{krb5_keyblock *}{to} +\end{funcdecl} + +Copy keyblock contents from \funcparam{from} to \funcparam{to}, including +allocated storage. The allocated storage in \funcparam{to} should be +freed by using {\bf free}(\funcparam{to->contents}). + +\begin{funcdecl}{krb5_copy_checksum}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_checksum *}{ckfrom} +\funcout +\funcarg{krb5_checksum **}{ckto} +\end{funcdecl} + +Copy a checksum structure, filling in \funcparam{*ckto} to point to +the newly allocated copy, which should be freed with +\funcname{krb5_free_checksum}. + +\begin{funcdecl}{krb5_copy_creds}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_creds *}{incred} +\funcout +\funcarg{krb5_creds **}{outcred} +\end{funcdecl} + +Copy a credentials structure, filling in \funcparam{*outcred} to point +to the newly allocated copy, which should be freed with +\funcname{krb5_free_creds}. + +\begin{funcdecl}{krb5_copy_data}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_data *}{indata} +\funcout +\funcarg{krb5_data **}{outdata} +\end{funcdecl} + +Copy a data structure, filling in \funcparam{*outdata} to point to the +newly allocated copy, which should be freed with \funcname{krb5_free_data}. + +\begin{funcdecl}{krb5_copy_ticket}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_ticket *}{from} +\funcout +\funcarg{krb5_ticket **}{pto} +\end{funcdecl} + +Copy a ticket structure, filling in \funcparam{*pto} to point to +the newly allocated copy, which should be freed with +\funcname{krb5_free_ticket}. + + +\begin{funcdecl}{krb5_get_server_rcache}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const krb5_data *}{piece} +\funcout +\funcarg{krb5_rcache *}{ret_rcache} +\end{funcdecl} + +Generate a replay cache name, allocate space for its handle, and open +it. \funcparam{piece} is used to distinguish this replay cache from +others currently in use on the system. Typically, \funcparam{piece} +is the first component of the principal name for the client or server +which is calling \funcname{krb5_get_server_rcache}. + +Upon successful return, \funcparam{ret_rcache} is filled in to contain a +handle to an open rcache, which should be closed with +\funcname{krb5_rc_close}. + + diff --git a/krb5-1-6/doc/api/krb5idx.sty b/krb5-1-6/doc/api/krb5idx.sty new file mode 100644 index 000000000..729ed9779 --- /dev/null +++ b/krb5-1-6/doc/api/krb5idx.sty @@ -0,0 +1,10 @@ +\usepackage{makeidx} + +% The following defintions are for our indexing scheme. Stolen from +% doc.sty. +\def\dotfill{\leaders\hbox to.6em{\hss .\hss}\hskip\z@ plus 1fill}% +\def\dotfil{\leaders\hbox to.6em{\hss .\hss}\hfil}% +\def\efill{\hfill\nopagebreak}% +\def\pfill{\unskip~\dotfill\penalty500\strut\nobreak + \dotfil~\ignorespaces}% +%% diff --git a/krb5-1-6/doc/api/libdes.tex b/krb5-1-6/doc/api/libdes.tex new file mode 100644 index 000000000..71e75c59b --- /dev/null +++ b/krb5-1-6/doc/api/libdes.tex @@ -0,0 +1,38 @@ +\documentstyle[fixunder,functions,twoside]{article} +\setlength{\oddsidemargin}{0.25in} +\setlength{\evensidemargin}{-0.25in} +\setlength{\topmargin}{-.5in} +\setlength{\textheight}{9in} +\setlength{\parskip}{.1in} +\setlength{\parindent}{2em} +\setlength{\textwidth}{6.25in} + +\pagestyle{headings} +\begin{document} +\begin{center} +{\Huge Kerberos V5 Data Encryption Standard library} \\ +{\Large DRAFT} +\end{center} +\section{DES functions} +The DES functions conform to the encryption interface required by the +Kerberos version 5 library, and provide an encryption mechanism based on +the DES Cipher-block chaining mode (CBC), with the addition of a +cyclical redundancy check (CRC-32) for integrity checking upon +decryption. + +The functions have the same signatures as those described by the main +library document; the names are: +{\obeylines +\funcname{mit_des_encrypt_func} +\funcname{mit_des_decrypt_func} +\funcname{mit_des_process_key} +\funcname{mit_des_finish_key} +\funcname{mit_des_string_to_key} +\funcname{mit_des_init_random_key} +\funcname{mit_des_finish_random_key} +\funcname{mit_des_random_key} +} +The \datatype{krb5_cryptosystem_entry} for this cryptosystem is +\globalname{mit_des_cryptosystem_entry}. + +\end{document} diff --git a/krb5-1-6/doc/api/libos.tex b/krb5-1-6/doc/api/libos.tex new file mode 100644 index 000000000..447044fec --- /dev/null +++ b/krb5-1-6/doc/api/libos.tex @@ -0,0 +1,486 @@ +The operating-system specific functions provide an interface between the +other parts of the \libname{libkrb5.a} libraries and the operating system. + +Beware! Any of the functions below are allowed to be implemented as +macros. Prototypes for functions can be found in {\tt +}; other definitions (including macros, if used) are +in {\tt }. + +The following global symbols are provided in \libname{libos.a}. If you +wish to substitute for any of them, you must substitute for all of them +(they are all declared and initialized in the same object file): +\begin{description} +% These come from src/lib/osconfig.c +\item[extern char *\globalname{krb5_defkeyname}:] default name of key +table file +\item[extern char *\globalname{krb5_lname_file}:] name of aname/lname +translation database +\item[extern int \globalname{krb5_max_dgram_size}:] maximum allowable +datagram size +\item[extern int \globalname{krb5_max_skdc_timeout}:] maximum +per-message KDC reply timeout +\item[extern int \globalname{krb5_skdc_timeout_shift}:] shift factor +(bits) to exponentially back-off the KDC timeouts +\item[extern int \globalname{krb5_skdc_timeout_1}:] initial KDC timeout +\item[extern char *\globalname{krb5_kdc_udp_portname}:] name of KDC UDP port +\item[extern char *\globalname{krb5_default_pwd_prompt1}:] first prompt +for password reading. +\item[extern char *\globalname{krb5_default_pwd_prompt2}:] second prompt + +\end{description} + +\subsubsection{Operating specific context} +The \datatype{krb5_context} has space for operating system specific +data. These functions are called from \funcname{krb5_init_context} and +\funcname{krb5_free_context}, but are included here for completeness. + +\begin{funcdecl}{krb5_os_init_context}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\end{funcdecl} + +\internalfunc + +Initializes \funcparam{context{\ptsto}os_context} and establishes the +location of the initial configuration files. + +\begin{funcdecl}{krb5_os_free_context}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\end{funcdecl} + +\internalfunc + +Frees the operating system specific portion of \funcparam{context}. + +\subsubsection{Configuration based functions} +These functions allow access to configuration specific information. In +some cases, the configuration may be overriden by program control. + + +\begin{funcdecl}{krb5_set_config_files}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const char **}{filenames} +\end{funcdecl} + +Sets the list of configuration files to be examined in determining +machine defaults. \funcparam{filenames} is an array of files to check in +order. The array must have a NULL entry as the last element. + +Returns system errors. + +\begin{funcdecl}{krb5_get_krbhst}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const krb5_data *}{realm} +\funcout +\funcarg{char ***}{hostlist} +\end{funcdecl} + +Figures out the Kerberos server names for the given \funcparam{realm}, +filling in \funcparam{hostlist} with a null terminated array of +pointers to hostnames. + +If \funcparam{realm} is unknown, the filled-in pointer is set to NULL. + +The pointer array and strings pointed to are all in allocated storage, +and should be freed by the caller when finished. + +Returns system errors. + +\begin{funcdecl}{krb5_free_krbhst}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{char * const *}{hostlist} +\end{funcdecl} + +Frees the storage taken by a host list returned by \funcname{krb5_get_krbhst}. + +\begin{funcdecl}{krb5_get_default_realm}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcout +\funcarg{char **}{lrealm} +\end{funcdecl} + +Retrieves the default realm to be used if no user-specified realm is +available (e.g. to interpret a user-typed principal name with the +realm omitted for convenience), filling in \funcparam{lrealm} with a +pointer to the default realm in allocated storage. + +It is the caller's responsibility for freeing the allocated storage +pointed to be \funcparam{lream} when it is finished with it. + +Returns system errors. + +\begin{funcdecl}{krb5_set_default_realm}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{char *}{realm} +\end{funcdecl} + +Sets the default realm to be used if no user-specified realm is +available (e.g. to interpret a user-typed principal name with the +realm omitted for convenience). (c.f. krb5_get_default_realm) + +If \funcparam{realm} is NULL, then the operating system default value +will used. + +Returns system errors. + +\begin{funcdecl}{krb5_get_host_realm}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const char *}{host} +\funcout +\funcarg{char ***}{realmlist} +\end{funcdecl} + +Figures out the Kerberos realm names for \funcparam{host}, filling in +\funcparam{realmlist} with a +pointer to an argv[] style list of names, terminated with a null pointer. + +If \funcparam{host} is NULL, the local host's realms are determined. + +If there are no known realms for the host, the filled-in pointer is set +to NULL. + +The pointer array and strings pointed to are all in allocated storage, +and should be freed by the caller when finished. + +Returns system errors. + +\begin{funcdecl}{krb5_free_host_realm}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{char * const *}{realmlist} +\end{funcdecl} + +Frees the storage taken by a \funcparam{realmlist} returned by +\funcname{krb5_get_local_realm}. + +\begin{funcdecl}{krb5_get_realm_domain}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{const char *}{realm} +\funcout +\funcarg{char **}{domain} +\end{funcdecl} + +Determines the proper name of a realm. This is mainly so that a krb4 +principal can be converted properly into a krb5 one. If +\funcparam{realm} is null, the function will assume the default realm of +the host. The returned \funcparam{*domain} is allocated and must be +freed by the caller. + +\subsubsection{Disk based functions} +These functions all relate to disk based I/O. + +\begin{funcdecl}{krb5_lock_file}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{in}{fd} +\funcarg{int}{mode} +\end{funcdecl} + +Attempts to lock the file in the given \funcparam{mode}; returns 0 for a +successful lock, or an error code otherwise. + +The caller should arrange for the file referred by \funcparam{fd} to be +opened in such a way as to allow the required lock. + +Modes are given in {\tt } + +\begin{funcdecl}{krb5_unlock_file}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{int}{fd} +\end{funcdecl} + +Attempts to (completely) unlock the file. Returns 0 if successful, +or an error code otherwise. + + +\begin{funcdecl}{krb5_create_secure_file}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const char *}{pathname} +\end{funcdecl} + +Creates a file named pathname which can only be read by the current +user. + +\begin{funcdecl}{krb5_sync_disk_file}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{FILE *}{fp} +\end{funcdecl} + +Assures that the changes made to the file pointed to by the file +handle +fp are forced out to disk. + +\subsubsection{Network based routines} + +These routines send and receive network data the specifics +of addresses and families on a given operating system. + +\begin{funcdecl}{krb5_os_localaddr}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_address ***}{addr} +\end{funcdecl} + +Return all the protocol addresses of this host. + +Compile-time configuration flags will indicate which protocol family +addresses might be returned. +\funcparam{*addr} is filled in to point to an array of address pointers, +terminated by a null pointer. All the storage pointed to is allocated +and should be freed by the caller with \funcname{krb5_free_address} +when no longer needed. + +\begin{funcdecl}{krb5_gen_portaddr}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const krb5_address *}{adr} +\funcarg{krb5_const_pointer}{ptr} +\funcout +\funcarg{krb5_address **}{outaddr} +\end{funcdecl} + +Given an address \funcparam{adr} and an additional address-type specific +portion pointed to by +\funcparam{port} this routine +combines them into a freshly-allocated +\datatype{krb5_address} with type \datatype{ADDRTYPE_ADDRPORT} and fills in +\funcparam{*outaddr} to point to this address. For IP addresses, +\funcparam{ptr} should point to a network-byte-order TCP or UDP port +number. Upon success, \funcparam{*outaddr} will point to an allocated +address which should be freed with \funcname{krb5_free_address}. + + +\begin{funcdecl}{krb5_sendto_kdc}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const krb5_data *}{send} +\funcarg{const krb5_data *}{realm} +\funcout +\funcarg{krb5_data *}{receive} +\end{funcdecl} + +Send the message \funcparam{send} to a KDC for realm \funcparam{realm} and +return the response (if any) in \funcparam{receive}. + +If the message is sent and a response is received, 0 is returned, +otherwise an error code is returned. + +The storage for \funcparam{receive} is allocated and should be freed by +the caller when finished. + + +\begin{funcdecl}{krb5_net_read}{int}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{int}{fd} +\funcout +\funcarg{char *}{buf} +\funcin +\funcarg{int}{len} +\end{funcdecl} + +Like read(2), but guarantees that it reads as much as was requested +or returns -1 and sets errno. + +(make sure your sender will send all the stuff you are looking for!) +Only useful on stream sockets and pipes. + +\begin{funcdecl}{krb5_net_write}{int}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{int}{fd} +\funcarg{const char *}{buf} +\funcarg{int}{len} +\end{funcdecl} + +Like write(2), but guarantees that it writes as much as was requested +or returns -1 and sets errno. + +Only useful on stream sockets and pipes. + +\begin{funcdecl}{krb5_write_message}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_pointer}{fd} +\funcarg{krb5_data *}{data} +\end{funcdecl} + + +\funcname{krb5_write_message} writes data to the network as a message, +using the network connection pointed to by \funcparam{fd}. + +\begin{funcdecl}{krb5_read_message}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_pointer}{fd} +\funcout +\funcarg{krb5_data *}{data} +\end{funcdecl} + +Reads data from the network as a message, using the network connection +pointed to by fd. + +\subsubsection{Operating specific access functions} +These functions are involved with access control decisions and policies. + +\begin{funcdecl}{krb5_aname_to_localname}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_const_principal}{aname} +\funcarg{int}{lnsize} +\funcout +\funcarg{char *}{lname} +\end{funcdecl} + +Converts a principal name \funcparam{aname} to a local name suitable for use by +programs wishing a translation to an environment-specific name (e.g. +user account name). + +\funcparam{lnsize} specifies the maximum length name that is to be filled into +\funcparam{lname}. +The translation will be null terminated in all non-error returns. + +Returns system errors. + +\begin{funcdecl}{krb5_kuserok}{krb5_boolean}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_principal}{principal} +\funcarg{const char *}{luser} +\end{funcdecl} + +Given a Kerberos principal \funcparam{principal}, and a local username +\funcparam{luser}, +determine whether user is authorized to login to the account \funcparam{luser}. +Returns TRUE if authorized, FALSE if not authorized. + +\begin{funcdecl}{krb5_sname_to_principal}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const char *}{hostname} +\funcarg{const char *}{sname} +\funcarg{krb5_int32}{type} +\funcout +\funcarg{krb5_principal *}{ret_princ} +\end{funcdecl} + +Given a hostname \funcparam{hostname} and a generic service name +\funcparam{sname}, this function generates a full principal name to be +used when authenticating with the named service on the host. The full +prinicpal name is returned in \funcparam{ret_princ}. + +The realm of the +principal is determined internally by calling \funcname{krb5_get_host_realm}. + +The \funcparam{type} argument controls how +\funcname{krb5_sname_to_principal} generates the principal name, +\funcparam{ret_princ}, for the named service, \funcparam{sname}. +Currently, two values are supported: KRB5_NT_SRV_HOST, and +KRB5_NT_UNKNOWN. + +If \funcparam{type} is set to +KRB5_NT_SRV_HOST, the hostname will be +canonicalized, i.e. a fully qualified lowercase hostname using +the primary name and the domain name, before \funcparam{ret_princ} is +generated in the form +"sname/hostname@LOCAL.REALM." Most applications should use +KRB5_NT_SRV_HOST. + +However, if \funcparam{type} is set to KRB5_NT_UNKNOWN, +while the generated principal name will have the form +"sname/hostname@LOCAL.REALM" the hostname will not be canonicalized +first. It will appear exactly as it was passed in \funcparam{hostname}. + +The caller should release \funcparam{ret_princ}'s storage by calling +\funcname{krb5_free_principal} when it is finished with the principal. + + + +\subsubsection{Miscellaneous operating specific functions} +These functions handle the other operating specific functions that do +not fall into any other major class. + +\begin{funcdecl}{krb5_timeofday}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_context}{context} +\funcarg{krb5_int32 *}{timeret} +\end{funcdecl} + +Retrieves the system time of day, in seconds since the local system's +epoch. +[The ASN.1 encoding routines must convert this to the standard ASN.1 +encoding as needed] + +\begin{funcdecl}{krb5_us_timeofday}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcout +\funcarg{krb5_int32 *}{seconds} +\funcarg{krb5_int32 *}{microseconds} +\end{funcdecl} + +Retrieves the system time of day, in seconds since the local system's +epoch. +[The ASN.1 encoding routines must convert this to the standard ASN.1 +encoding as needed] + +{\raggedright The seconds portion is returned in \funcparam{*seconds}, the +microseconds portion in \funcparam{*microseconds}.} + +\begin{funcdecl}{krb5_read_password}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const char *}{prompt} +\funcarg{const char *}{prompt2} +\funcout +\funcarg{char *}{return_pwd} +\funcinout +\funcarg{unsigned int *}{size_return} +\end{funcdecl} + +Read a password from the keyboard. The first \funcparam{*size_return} +bytes of the password entered are returned in \funcparam{return_pwd}. +If fewer than \funcparam{*size_return} bytes are typed as a password, +the remainder of \funcparam{return_pwd} is zeroed. Upon success, the +total number of bytes filled in is stored in \funcparam{*size_return}. + +\funcparam{prompt} is used as the prompt for the first reading of a password. +It is printed to the terminal, and then a password is read from the +keyboard. No newline or spaces are emitted between the prompt and the +cursor, unless the newline/space is included in the prompt. + +If \funcparam{prompt2} is a null pointer, then the password is read +once. If \funcparam{prompt2} is set, then it is used as a prompt to +read another password in the same manner as described for +\funcparam{prompt}. After the second password is read, the two +passwords are compared, and an error is returned if they are not +identical. + +Echoing is turned off when the password is read. + +If there is an error in reading or verifying the password, an error code +is returned; else zero is returned. + + +\begin{funcdecl}{krb5_random_confounder}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{int}{size} +\funcout +\funcarg{krb5_pointer}{fillin} +\end{funcdecl} + +Given a length and a pointer, fills in the area pointed to by +\funcparam{fillin} with \funcparam{size} random octets suitable for use +in a confounder. + +\begin{funcdecl}{krb5_gen_replay_name}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{const krb5_address *}{inaddr} +\funcarg{const char *}{uniq} +\funcout +\funcarg{char **}{string} +\end{funcdecl} + +Given a \datatype{krb5_address} with type \datatype{ADDRTYPE_ADDRPORT} +in \funcparam{inaddr}, this function unpacks its component address and +additional type, and uses them along with \funcparam{uniq} to allocate a +fresh string to represent the address and additional information. The +string is suitable for use as a replay cache tag. This string is +allocated and should be freed with \funcname{free} when the caller has +finished using it. When using IP addresses, the components in +\funcparam{inaddr{\ptsto}contents} must be of type +\datatype{ADDRTYPE_INET} and \datatype{ADDRTYPE_PORT}. + +% XXX Note that if the bug I sent in entitled ``krb5_gen_replay_name +% outputs char * when krb5_get_server_rcache expects krb5_data'' +% (OpenVision Cambridge bug number 1582) causes the code of this +% function to change, the documentation above will have to be updated. diff --git a/krb5-1-6/doc/api/library.tex b/krb5-1-6/doc/api/library.tex new file mode 100644 index 000000000..713ce482f --- /dev/null +++ b/krb5-1-6/doc/api/library.tex @@ -0,0 +1,114 @@ +\documentclass[twoside]{article} +\usepackage{fixunder,functions,fancyheadings} +\usepackage{krb5idx} +%\usepackage{hyperref} + +%\hypersetup{letterpaper, +% bookmarks=true, +%pdfpagemode=UseOutlines, +%} + +% +%\setlength{\oddsidemargin}{1in} +%\setlength{\evensidemargin}{1.00in} +%\setlength{\textwidth}{6.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{1.50in} +\setlength{\textwidth}{5.25in} +\setlength{\marginparsep}{0.0in} +\setlength{\marginparwidth}{1.95 in} +\setlength{\topmargin}{-.5in} +\setlength{\textheight}{9in} +\setlength{\parskip}{.1in} +\setlength{\parindent}{2em} +\setlength{\footrulewidth}{0.4pt} +\setlength{\plainfootrulewidth}{0.4pt} +\setlength{\plainheadrulewidth}{0.4pt} +\makeindex +\newif\ifdraft +\draftfalse +% +% Far, far too inconvenient... it's still very draft-like anyway.... +% [tytso:19900921.0018EDT] +% +%\typein{Draft flag? (type \noexpand\draftfalse if not draft...)} +\ifdraft +\pagestyle{fancyplain} +\addtolength{\headwidth}{\marginparsep} +\addtolength{\headwidth}{\marginparwidth} +\makeatletter +\renewcommand{\sectionmark}[1]{\markboth {\uppercase{\ifnum \c@secnumdepth >\z@ + \thesection\hskip 1em\relax \fi #1}}{}}% +\renewcommand{\subsectionmark}[1]{\markright {\ifnum \c@secnumdepth >\@ne + \thesubsection\hskip 1em\relax \fi #1}} +\makeatother +\lhead[\thepage]{\fancyplain{}{\sl\rightmark}} +\rhead[\fancyplain{}{\sl\rightmark}]{\thepage} +\lfoot[]{{\bf DRAFT---DO NOT REDISTRIBUTE}} +\rfoot[{\bf DRAFT---DO NOT REDISTRIBUTE}]{} +\cfoot{\thepage} +\else\pagestyle{headings}\fi + +\def\internalfunc{NOTE: This is an internal function, which is not +necessarily intended for use by application programs. Its interface may +change at any time.\par} + +%nlg- time to make this a real document + +\title{\Huge Kerberos V5 application programming library} +\date{\ifdraft \\ {\Large DRAFT---}\fi\today} +\author{MIT Information Systems} + +\begin{document} +\maketitle +\tableofcontents + +%\thispagestyle{empty} +%\begin{center} +%{\Huge Kerberos V5 application programming library} +%\ifdraft \\ {\Large DRAFT---\today}\fi +%\end{center} + +\section{Introduction} +\input{intro.tex} + +\section{Useful KDC parameters to know about} +\input{tables.tex} + +\section{Error tables} +\input{errors.tex} + +%\addtolength{\oddsidemargin}{-1in} +%\addtolength{\evensidemargin}{1.00in} +%\addtolength{\textwidth}{-1.75in} +\newpage + +\section{libkrb5.a functions} +This section describes the functions provided in the \libname{libkrb5.a} +library. The library is built from several pieces, mostly for convenience in +programming, maintenance, and porting. + +\ifdraft\sloppy\fi + +\subsection{Main functions} +\input{krb5.tex} + +\subsection{Credentials cache functions} +\input{ccache.tex} + +\subsection{Replay cache functions} +\input{rcache.tex} + +\subsection{Key table functions} +\input{keytab.tex} + +\subsection{Free functions} +\input{free.tex} + +\subsection{Operating-system specific functions} +\input{libos.tex} + +\appendix +\cleardoublepage +\printindex +\end{document} diff --git a/krb5-1-6/doc/api/rcache.tex b/krb5-1-6/doc/api/rcache.tex new file mode 100644 index 000000000..28bad36ab --- /dev/null +++ b/krb5-1-6/doc/api/rcache.tex @@ -0,0 +1,207 @@ +The replay cache functions deal with verifying that AP_REQ's do not +contain duplicate authenticators; the storage must be non-volatile for +the site-determined validity period of authenticators. + +Each replay cache has a string ``name'' associated with it. The use of +this name is dependent on the underlying caching strategy (for +file-based things, it would be a cache file name). The +caching strategy uses non-volatile storage so that replay +integrity can be maintained across system failures. + +\begin{funcdecl}{krb5_auth_to_rep}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcin +\funcarg{krb5_tkt_authent *}{auth} +\funcout +\funcarg{krb5_donot_replay *}{rep} +\end{funcdecl} +Extract the relevant parts of \funcparam{auth} and fill them into the +structure pointed to by \funcparam{rep}. \funcparam{rep{\ptsto}client} +and \funcparam{rep{\ptsto}server} are set to allocated storage and +should be freed when \funcparam{*rep} is no longer needed. + +\begin{funcdecl}{krb5_rc_resolve_full}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache *}{id} +\funcin +\funcarg{char *}{string_name} +\end{funcdecl} + +\begin{sloppypar} +\funcparam{id} is filled in to identify a replay cache which +corresponds to the name in \funcparam{string_name}. The cache is not opened. +Requires that \funcparam{string_name} be of the form ``type:residual'' +and that ``type'' is a type known to the library. +\end{sloppypar} + +Before the cache can be used \funcname{krb5_rc_initialize} or +\funcname{krb5_rc_recover} must be called. + +Errors: error if cannot resolve name. + + +\begin{funcdecl}{krb5_rc_resolve_type}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache *}{id} +\funcin +\funcarg{char *}{type} +\end{funcdecl} + +\internalfunc + +Looks up \funcparam{type} in the list of knows cache types and if found +attaches the operations to \funcparam{*id} which must be previously +allocated. + +If \funcparam{type} is not found, {\sc krb5_rc_type_notfound} is returned. + +\begin{funcdecl}{krb5_rc_register_type}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rc_ops *}{ops} +\end{funcdecl} +Adds a new replay cache type implemented and identified by +\funcparam{ops} to the set recognized by +\funcname{krb5_rc_resolve}. This function requires that a ticket +cache of the type named in +\funcparam{ops{\ptsto}prefix} has not been previously registered. + + +\begin{funcdecl}{krb5_rc_default_name}{char *}{\funcin} +\funcarg{krb5_context}{context} +\end{funcdecl} + +\begin{sloppypar} +Returns the name of the default replay cache; this may be equivalent to +\funcnamenoparens{getenv}({\tt "KRB5RCACHE"}) with an appropriate fallback. +\end{sloppypar} + +\begin{funcdecl}{krb5_rc_default_type}{char *}{\funcin} +\funcarg{krb5_context}{context} +\end{funcdecl} + +Returns the type of the default replay cache. + +\begin{funcdecl}{krb5_rc_default}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache *}{id} +\end{funcdecl} + +This function returns an unopened replay cache of the default type and +default name (as would be returned by \funcname{krb5_rc_default_type} +and \funcname{krb5_rc_default_name}). Before the cache can be used +\funcname{krb5_rc_initialize} or \funcname{krb5_rc_recover} must be +called. + + +\begin{funcdecl}{krb5_rc_initialize}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\funcarg{krb5_deltat}{auth_lifespan} +\end{funcdecl} + +Creates/refreshes the replay cache identified by \funcparam{id} and sets its +authenticator lifespan to \funcparam{auth_lifespan}. If the +replay cache already exists, its contents are destroyed. + +Errors: permission errors, system errors + +\begin{funcdecl}{krb5_rc_recover}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\end{funcdecl} +Attempts to recover the replay cache \funcparam{id}, (presumably after a +system crash or server restart). + +Errors: error indicating that no cache was found to recover + +\begin{funcdecl}{krb5_rc_destroy}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\end{funcdecl} + +Destroys the replay cache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + +Errors: permission errors. + +\begin{funcdecl}{krb5_rc_close}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\end{funcdecl} + +Closes the replay cache \funcparam{id}, invalidates \funcparam{id}, +and releases any other resources acquired during use of the replay cache. +Requires that \funcparam{id} identifies a valid replay cache. + +Errors: permission errors + +\begin{funcdecl}{krb5_rc_store}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\funcarg{krb5_donot_replay *}{rep} +\end{funcdecl} +Stores \funcparam{rep} in the replay cache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + +Returns KRB5KRB_AP_ERR_REPEAT if \funcparam{rep} is already in the +cache. May also return permission errors, storage failure errors. + +\begin{funcdecl}{krb5_rc_expunge}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\end{funcdecl} +Removes all expired replay information (i.e. those entries which are +older than then authenticator lifespan of the cache) from the cache +\funcparam{id}. Requires that \funcparam{id} identifies a valid replay +cache. + +Errors: permission errors. + +\begin{funcdecl}{krb5_rc_get_lifespan}{krb5_error_code}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\funcout +\funcarg{krb5_deltat *}{auth_lifespan} +\end{funcdecl} +Fills in \funcparam{auth_lifespan} with the lifespan of +the cache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + +\begin{funcdecl}{krb5_rc_resolve}{krb5_error_code}{\funcinout} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\funcin +\funcarg{char *}{name} +\end{funcdecl} + +Initializes private data attached to \funcparam{id}. This function MUST +be called before the other per-replay cache functions. + +Requires that \funcparam{id} points to allocated space, with an +initialized \funcparam{id{\ptsto}ops} field. + +Since \funcname{krb5_rc_resolve} allocates memory, +\funcname{krb5_rc_close} must be called to free the allocated memory, +even if neither \funcname{krb5_rc_initialize} or +\funcname{krb5_rc_recover} were successfully called by the application. + +Returns: allocation errors. + + +\begin{funcdecl}{krb5_rc_get_name}{char *}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\end{funcdecl} + +Returns the name (excluding the type) of the rcache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + +\begin{funcdecl}{krb5_rc_get_type}{char *}{\funcin} +\funcarg{krb5_context}{context} +\funcarg{krb5_rcache}{id} +\end{funcdecl} + +Returns the type (excluding the name) of the rcache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + + diff --git a/krb5-1-6/doc/api/tables.tex b/krb5-1-6/doc/api/tables.tex new file mode 100644 index 000000000..b272a07b9 --- /dev/null +++ b/krb5-1-6/doc/api/tables.tex @@ -0,0 +1,79 @@ +The following is a list of options which can be passed to the Kerberos +server (also known as the Key Distribution Center or KDC). These +options affect what sort of tickets the KDC will return to the +application program. The KDC options can be passed to +\funcname{krb5_get_in_tkt}, \funcname{krb5_get_in_tkt_with_password}, +\funcname{krb5_get_in_tkt_with_skey}, and \funcname{krb5_send_tgs}. + + +\begin{center} +\begin{tabular}{llc} +\multicolumn{1}{c}{Symbol}&\multicolumn{1}{c}{RFC}& Valid for \\ +&\multicolumn{1}{c}{section}&get_in_tkt? \\ \hline +KDC_OPT_FORWARDABLE & 2.6 & yes \\ +KDC_OPT_FORWARDED & 2.6 & \\ +KDC_OPT_PROXIABLE & 2.5 & yes \\ +KDC_OPT_PROXY & 2.5 & \\ +KDC_OPT_ALLOW_POSTDATE & 2.4 & yes \\ +KDC_OPT_POSTDATED & 2.4 & yes \\ +KDC_OPT_RENEWABLE & 2.3 & yes \\ +KDC_OPT_RENEWABLE_OK & 2.7 & yes \\ +KDC_OPT_ENC_TKT_IN_SKEY & 2.7 & \\ +KDC_OPT_RENEW & 2.3 & \\ +KDC_OPT_VALIDATE & 2.2 & \\ +\end{tabular} +\end{center} +\label{KDCOptions} + +The following is a list of preauthentication methods which are supported +by Kerberos. Most preauthentication methods are used by +\funcname{krb5_get_in_tkt}, \funcname{krb5_get_in_tkt_with_password}, and +\funcname{krb5_get_in_tkt_with_skey}; at some sites, the Kerberos server can be +configured so that during the initial ticket transation, it will only +return encrypted tickets after the user has proven his or her identity +using a supported preauthentication mechanism. This is done to make +certain password guessing attacks more difficult to carry out. + + + +\begin{center} +\begin{tabular}{lcc} +\multicolumn{1}{c}{Symbol}&In & Valid for \\ +&RFC?&get_in_tkt? \\ \hline +KRB5_PADATA_NONE & yes & yes \\ +KRB5_PADATA_AP_REQ & yes & \\ +KRB5_PADATA_TGS_REQ & yes & \\ +KRB5_PADATA_PW_SALT & yes & \\ +KRB5_PADATA_ENC_TIMESTAMP & yes & yes \\ +KRB5_PADATA_ENC_SECURID & & yes \\ +\end{tabular} +\end{center} +\label{padata-types} + +KRB5_PADATA_TGS_REQ is rarely used by a programmer; it is used to pass +the ticket granting ticket to the Ticket Granting Service (TGS) during a +TGS transaction (as opposed to an initial ticket transaction). + +KRB5_PW_SALT is not really a preauthentication method at all. It is +passed back from the Kerberos server to application program, and it +contains a hint to the proper password salting algorithm which should be +used during the initial ticket exchange. + +%The encription type can also be specified in +%\funcname{krb5_get_in_tkt}, however normally only one keytype is used +%in any one database. +% +%\begin{center} +%\begin{tabular}{llc} +%\multicolumn{1}{c}{Symbol}&\multicolumn{1}{c}{RFC}& Supported? \\ +%& \multicolumn{1}{c}{section} & \\ \hline +%ETYPE_NULL & 6.3.1 & \\ +%ETYPE_DES_CBC_CRC & 6.3.2 & yes \\ +%ETYPE_DES_CBC_MD4 & 6.3.3 & \\ +%ETYPE_DES_CBC_MD5 & 6.3.4 & \\ +%ETYPE_RAW_DES_CBC & & yes \\ +%\end{tabular} +%\end{center} +%\label{etypes} + + diff --git a/krb5-1-6/doc/bug-report.texinfo b/krb5-1-6/doc/bug-report.texinfo new file mode 100644 index 000000000..9a1767d56 --- /dev/null +++ b/krb5-1-6/doc/bug-report.texinfo @@ -0,0 +1,10 @@ +In any complex software, there will be bugs. Please send bug reports or +other problems you may uncover using the @code{krb5-send-pr} program +installed with the distribution. In case @code{krb5-send-pr} fails to +work, send bug reports to @samp{krb5-bugs@@mit.edu}. Please mention +which version of the Kerberos V5 distribution you are using, and whether +you have made any private changes. Bug reports that include proposed +fixes are especially welcome. If you do include fixes, please send them +using either context diffs or unified diffs (using @samp{diff -c} or +@samp{diff -u}, respectively). + diff --git a/krb5-1-6/doc/build.texinfo b/krb5-1-6/doc/build.texinfo new file mode 100644 index 000000000..f92a4d249 --- /dev/null +++ b/krb5-1-6/doc/build.texinfo @@ -0,0 +1,1052 @@ +@value{PRODUCT} uses a configuration system built using the Free +Software Foundation's @samp{autoconf} program. This system makes +Kerberos V5 much simpler to build and reduces the amount of effort +required in porting Kerberos V5 to a new platform. + +@menu +* Organization of the Source Directory:: Description of the source tree. +* Build Requirements:: How much disk space, etc. you need to + build Kerberos. +* Unpacking the Sources:: Preparing the source tree. +* Doing the Build:: Compiling Kerberos. +* Installing the Binaries:: Installing the compiled binaries. +* Testing the Build:: Making sure Kerberos built correctly. +* Options to Configure:: Command-line options to Configure +* osconf.h:: Header file-specific configurations +* Shared Library Support:: Building Shared Libraries for Kerberos V5 +* OS Incompatibilities:: Special cases to watch for. +* Using Autoconf:: Modifying Kerberos V5's + configuration scripts. +@end menu + +@node Organization of the Source Directory, Build Requirements, Building Kerberos V5, Building Kerberos V5 +@section Organization of the Source Directory + +Below is a brief overview of the organization of the complete source +directory. More detailed descriptions follow. + +@table @b +@itemx appl +applications with @value{PRODUCT} extensions +@itemx clients +@value{PRODUCT} user programs +@itemx gen-manpages +manpages for @value{PRODUCT} and the @value{PRODUCT} login program +@itemx include +include files +@itemx kadmin +administrative interface to the Kerberos master database +@itemx kdc +the @value{PRODUCT} Authentication Service and Key Distribution Center +@itemx krb524 +utilities for converting between Kerberos 4 and Kerberos 5 +@itemx lib +libraries for use with/by @value{PRODUCT} +@itemx mac +source code for building @value{PRODUCT} on MacOS +@itemx prototype +templates for source code files +@itemx slave +utilities for propagating the database to slave KDCs +@itemx tests +test suite +@itemx util +various utilities for building/configuring the code, sending bug reports, etc. +@itemx windows +source code for building @value{PRODUCT} on Windows (see windows/README) +@end table + +@menu +* The appl Directory:: +* The clients Directory:: +* The gen-manpages Directory:: +* The include Directory:: +* The kadmin Directory:: +* The kdc Directory:: +* The krb524 Directory:: +* The lib Directory:: +* The prototype Directory:: +* The slave Directory:: +* The util Directory:: +@end menu + +@node The appl Directory, The clients Directory, Organization of the Source Directory, Organization of the Source Directory +@subsection The appl Directory + +The Kerberos release provides certain UNIX utilities, modified to use +Kerberos authentication. In the @i{appl/bsd} directory are the +Berkeley utilities @i{login}, @i{rlogin}, @i{rsh}, and @i{rcp}, as well as +the associated daemons @i{kshd} and @i{klogind}. The @i{login} program +obtains ticket-granting tickets for users upon login; the other utilities +provide authenticated Unix network services. + +The @i{appl} directory also contains Kerberized telnet and ftp programs, +as well as sample Kerberos application client and server programs. + +@node The clients Directory, The gen-manpages Directory, The appl Directory, Organization of the Source Directory +@subsection The clients Directory + +This directory contains the code for several user-oriented programs. + +@table @b +@itemx kdestroy +This program destroys the user's active Kerberos authorization tickets. +@value{COMPANY} recommends that users @code{kdestroy} before logging out. + +@itemx kinit +This program prompts users for their Kerberos principal name and password, +and attempts to get an initial ticket-granting-ticket for that principal. + +@itemx klist +This program lists the Kerberos principal and Kerberos tickets held in +a credentials cache, or the keys held in a keytab file. + +@itemx kpasswd +This program changes a user's Kerberos password. + +@itemx ksu +This program is a Kerberized version of the @code{su} program that is +meant to securely change the real and effective user ID to that of the +target user and to create a new security context. + +@itemx kvno +This program acquires a service ticket for the specified Kerberos +principals and prints out the key version numbers of each. +@end table + +@node The gen-manpages Directory, The include Directory, The clients Directory, Organization of the Source Directory +@subsection The gen-manpages Directory + +There are two manual pages in this directory. One is an introduction +to the Kerberos system. The other describes the @code{.k5login} file +which allows users to give access with their UID to other users +authenticated by the Kerberos system. + +@node The include Directory, The kadmin Directory, The gen-manpages Directory, Organization of the Source Directory +@subsection The include Directory + +This directory contains the @i{include} files needed to build the +Kerberos system. + +@node The kadmin Directory, The kdc Directory, The include Directory, Organization of the Source Directory +@subsection The kadmin Directory + +In this directory is the code for the utilities @code{kadmin}, +@code{kadmin.local}, @code{kdb5_util}, and @code{ktutil}. +@code{ktutil} is the Kerberos keytab file maintenance utility from +which a Kerberos administrator can read, write, or edit entries in a +Kerberos V5 keytab or Kerberos V4 srvtab. @code{kadmin} and +@code{kadmin.local} are command-line interfaces to the Kerberos V5 KADM5 +administration system. @code{kadmin.local} runs on the master KDC and +does not use Kerberos to authenticate to the database, while +@code{kadmin} uses Kerberos authentication and an encrypted RPC. The +two provide identical functionalities, which allow administrators to +modify the database of Kerberos principals. @code{kdb5_util} allows +administrators to perform low-level maintenance procedures on Kerberos +and the KADM5 database. With this utility, databases can be created, +destroyed, or dumped to and loaded from ASCII files. It can also be +used to create master key stash files. + +@node The kdc Directory, The krb524 Directory, The kadmin Directory, Organization of the Source Directory +@subsection The kdc Directory + +This directory contains the code for the @code{krb5kdc} daemon, the +Kerberos Authentication Service and Key Distribution Center. + +@node The krb524 Directory, The lib Directory, The kdc Directory, Organization of the Source Directory +@subsection The krb524 Directory + +This directory contains the code for @code{krb524}, a service that +converts Kerberos V5 credentials into Kerberos V4 credentials suitable +for use with applications that for whatever reason do not use V5 +directly. + +@node The lib Directory, The prototype Directory, The krb524 Directory, Organization of the Source Directory +@subsection The lib Directory + +The @i{lib} directory contain 10 subdirectories as well as some +definition and glue files. The @i{crypto} subdirectory contains the +Kerberos V5 encryption library. The @i{des425} subdirectory exports +the Kerberos V4 encryption API, and translates these functions into +calls to the Kerberos V5 encryption API. The @i{gssapi} library +contains the Generic Security Services API, which is a library of +commands to be used in secure client-server communication. The +@i{kadm5} directory contains the libraries for the KADM5 administration +utilities. The Kerberos 5 database libraries are contained in +@i{kdb}. The directories @i{krb4} and @i{krb5} contain the Kerberos 4 +and Kerberos 5 APIs, respectively. The @i{rpc} directory contains the +API for the Kerberos Remote Procedure Call protocol. + +@node The prototype Directory, The slave Directory, The lib Directory, Organization of the Source Directory +@subsection The prototype Directory + +This directory contains several template files. The @code{prototype.h} +and @code{prototype.c} files contain the MIT copyright message and a +placeholder for the title and description of the file. +@code{prototype.h} also has a short template for writing @code{ifdef} +and @code{ifndef} preprocessor statements. The @code{getopt.c} file +provides a template for writing code that will parse the options with +which a program was called. + +@node The slave Directory, The util Directory, The prototype Directory, Organization of the Source Directory +@subsection The slave Directory + +This directory contains code which allows for the propagation of the +Kerberos principal database from the master KDC to slave KDCs over an +encrypted, secure channel. @code{kprop} is the program which actually +propagates the database dump file. @code{kpropd} is the Kerberos V5 +slave KDC update server which accepts connections from the @code{kprop} +program. @code{kslave_update} is a script that takes the name of a +slave server, and propagates the database to that server if the +database has been modified since the last dump or if the database has +been dumped since the last propagation. + +@node The util Directory, , The slave Directory, Organization of the Source Directory +@subsection The util Directory + +This directory contains several utility programs and libraries. The +programs used to configure and build the code, such as @code{autoconf}, +@code{lndir}, @code{kbuild}, @code{reconf}, and @code{makedepend}, +are in this directory. The @i{profile} directory contains most of the +functions which parse the Kerberos configuration files (@code{krb5.conf} +and @code{kdc.conf}). Also in this directory are the Kerberos error table +library and utilities (@i{et}), the Sub-system library and utilities +(@i{ss}), database utilities (@i{db2}), pseudo-terminal utilities +(@i{pty}), bug-reporting program @code{send-pr}, and a generic +support library @code{support} used by several of our other libraries. + +@node Build Requirements, Unpacking the Sources, Organization of the Source Directory, Building Kerberos V5 +@section Build Requirements + +In order to build Kerberos V5, you will need approximately 60-70 +megabytes of disk space. The exact amount will vary depending on the +platform and whether the distribution is compiled with debugging symbol +tables or not. + +Your C compiler must conform to ANSI C (ISO/IEC 9899:1990, ``c89''). +Some operating systems do not have an ANSI C compiler, or their +default compiler requires extra command-line options to enable ANSI C +conformance. + +If you wish to keep a separate @dfn{build tree}, which contains the compiled +@file{*.o} file and executables, separate from your source tree, you +will need a @samp{make} program which supports @samp{VPATH}, or +you will need to use a tool such as @samp{lndir} to produce a symbolic +link tree for your build tree. + +@c Library support... + +@node Unpacking the Sources, Doing the Build, Build Requirements, Building Kerberos V5 +@section Unpacking the Sources + +The first step in each of these build procedures is to unpack the +source distribution. The Kerberos V5 distribution comes in a tar file, +generally named @file{krb5-@value{RELEASE}.tar}, which contains a +compressed tar file consisting of the sources for all of Kerberos +(generally @file{krb5-@value{RELEASE}.tar.gz}) and a PGP signature for +this source tree (generally @file{krb5-@value{RELEASE}.tar.gz.asc}). +@value{COMPANY} highly recommends that you verify the integrity of the +source code using this signature. + +Unpack the compressed tar file in some directory, such as +@file{/u1/krb5-@value{RELEASE}}. (In the rest of this document, we +will assume that you have chosen to unpack the Kerberos V5 source +distribution in this directory. Note that the tarfiles will by default +all unpack into the @file{./krb5-@value{RELEASE}} directory, so that if +your current directory is @file{/u1} when you unpack the tarfiles, you +will get @file{/u1/krb5-@value{RELEASE}/src}, etc.) + + +@node Doing the Build, Installing the Binaries, Unpacking the Sources, Building Kerberos V5 +@section Doing the Build + +You have a number of different options in how to build Kerberos. If you +only need to build Kerberos for one platform, using a single directory +tree which contains both the source files and the object files is the +simplest. However, if you need to maintain Kerberos for a large number +of platforms, you will probably want to use separate build trees for +each platform. We recommend that you look at @ref{OS +Incompatibilities}, for notes that we have on particular operating +systems. + +@menu +* Building Within a Single Tree:: +* Building with Separate Build Directories:: +* Building using lndir:: +@end menu + +@node Building Within a Single Tree, Building with Separate Build Directories, Doing the Build, Doing the Build +@subsection Building Within a Single Tree + +If you don't want separate build trees for each architecture, then +use the following abbreviated procedure. + +@enumerate +@item + @code{cd /u1/krb5-@value{RELEASE}/src} +@item + @code{./configure} +@item + @code{make} +@end enumerate + +That's it! + +@node Building with Separate Build Directories, Building using lndir, Building Within a Single Tree, Doing the Build +@subsection Building with Separate Build Directories + +If you wish to keep separate build directories for each platform, you +can do so using the following procedure. (Note, this requires that your +@samp{make} program support @samp{VPATH}. GNU's make will provide this +functionality, for example.) If your @samp{make} program does not +support this, see the next section. + +For example, if you wish to create a build directory for @code{pmax} binaries +you might use the following procedure: + +@enumerate +@item +@code{mkdir /u1/krb5-@value{RELEASE}/pmax} +@item + @code{cd /u1/krb5-@value{RELEASE}/pmax} +@item + @code{../src/configure} +@item + @code{make} +@end enumerate + +@node Building using lndir, , Building with Separate Build Directories, Doing the Build +@subsection Building Using @samp{lndir} + +If you wish to keep separate build directories for each platform, and +you do not have access to a @samp{make} program which supports @samp{VPATH}, +all is not lost. You can use the @samp{lndir} program to create +symbolic link trees in your build directory. + +For example, if you wish to create a build directory for solaris binaries +you might use the following procedure: + +@enumerate +@item + @code{mkdir /u1/krb5-@value{RELEASE}/solaris} +@item + @code{cd /u1/krb5-@value{RELEASE}/solaris} +@item + @code{/u1/krb5-@value{RELEASE}/src/util/lndir `pwd`/../src} +@item + @code{./configure} +@item + @code{make} +@end enumerate + +You must give an absolute pathname to @samp{lndir} because it has a bug that +makes it fail for relative pathnames. Note that this version differs +from the latest version as distributed and installed by the XConsortium +with X11R6. Either version should be acceptable. + +@node Installing the Binaries, Testing the Build, Doing the Build, Building Kerberos V5 +@section Installing the Binaries + +Once you have built Kerberos, you should install the binaries. You +can do this by running: + +@example +% make install +@end example + +If you want to install the binaries into a destination directory that +is not their final destination, which may be convenient if you want to +build a binary distribution to be deployed on multiple hosts, you may +use: + +@example +% make install DESTDIR=/path/to/destdir +@end example + +This will install the binaries under @code{DESTDIR/PREFIX}, e.g., the +user programs will install into @code{DESTDIR/PREFIX/bin}, the +libraries into @code{DESTDIR/PREFIX/lib}, etc. + +Note that if you want to test the build (see @ref{Testing the Build}), +you usually do not need to do a @code{make install} first. + +Some implementations of @samp{make} allow multiple commands to be run in +parallel, for faster builds. We test our Makefiles in parallel builds with +GNU @samp{make} only; they may not be compatible with other parallel build +implementations. + +@node Testing the Build, Options to Configure, Installing the Binaries, Building Kerberos V5 +@section Testing the Build + +The Kerberos V5 distribution comes with built-in regression tests. To +run them, simply type the following command while in the top-level build +directory (i.e., the directory where you sent typed @samp{make} to start +building Kerberos; see @ref{Doing the Build}.): + +@example +% make check +@end example + +However, there are several prerequisites that must be satisfied first: + +@itemize @bullet +@item +Configure and build Kerberos with Tcl support. Tcl is used to drive the +test suite. This often means passing @code{--with-tcl} to configure to +tell it the location of the Tcl configuration script. (See +@xref{Options to Configure}.) + +@item +You have to run @samp{make install} before running @samp{make check}, or +the test suite will often pick up the installed version of Kerberos +rather than the newly built one. You can install into a prefix that +isn't in the system library search path, though. This theoretically +could be fixed with the appropriate environment variable magic in the +test suite, but hasn't been yet. + +@item +In order to test the RPC layer, the local system has to be running the +@command{portmap} daemon and it has to be listening to the regular +network interface (not just localhost). +@end itemize + +@menu +* The DejaGnu Tests:: +* The KADM5 Tests:: +@end menu + +@node The DejaGnu Tests, The KADM5 Tests, Testing the Build, Testing the Build +@subsection The DejaGnu Tests + +Some of the built-in regression tests are setup to use the DejaGnu +framework for running tests. These tests tend to be more comprehensive +than the normal built-in tests as they setup test servers and test +client/server activities. + +DejaGnu may be found wherever GNU software is archived. + +Most of the tests are setup to run as a non-privileged user. For some +of the krb-root tests to work properly, either (a) the user running the +tests must not have a .k5login file in the home directory or (b) the +.k5login file must contain an entry for @code{@@KRBTEST.COM}. +There are two series of tests (@samp{rlogind} and @samp{telnetd}) which +require the ability to @samp{rlogin} as root to the local +machine. Admittedly, this does require the use of a @file{.rhosts} file +or some authenticated means. @footnote{If you are fortunate enough to +have a previous version of Kerberos V5 or V4 installed, and the Kerberos +rlogin is first in your path, you can setup @file{.k5login} or +@file{.klogin} respectively to allow you access.} + +If you cannot obtain root access to your machine, all the other tests +will still run. Note however, with DejaGnu 1.2, the "untested testcases" +will cause the testsuite to exit with a non-zero exit status which +@samp{make} will consider a failure of the testing process. Do not worry +about this, as these tests are the last run when @samp{make check} is +executed from the top level of the build tree. This problem does not +exist with DejaGnu 1.3. + +@node The KADM5 Tests, , The DejaGnu Tests, Testing the Build +@subsection The KADM5 Tests + +Regression tests for the KADM5 system, including the GSS-RPC, KADM5 +client and server libraries, and kpasswd, are also included in this +release. Each set of KADM5 tests is contained in a sub-directory called +@code{unit-test} directly below the system being tested. For example, +lib/rpc/unit-test contains the tests for GSS-RPC. The tests are all +based on DejaGnu (but they are not actually called part of "The DejaGnu +tests," whose naming predates the inclusion of the KADM5 system). In +addition, they require the Tool Command Language (TCL) header files and +libraries to be available during compilation and some of the tests also +require Perl in order to operate. If all of these resources are not +available during configuration, the KADM5 tests will not run. The TCL +installation directory can be specified with the @code{--with-tcl} +configure option. (See @xref{Options to Configure}.) The runtest and +perl programs must be in the current execution path. + +If you install DejaGnu, TCL, or Perl after configuring and building +Kerberos and then want to run the KADM5 tests, you will need to +re-configure the tree and run @code{make} at the top level again to make +sure all the proper programs are built. To save time, you actually only +need to reconfigure and build in the directories src/kadmin/testing, +src/lib/rpc, src/lib/kadm5. + +@node Options to Configure, osconf.h, Testing the Build, Building Kerberos V5 +@section Options to Configure + +There are a number of options to @samp{configure} which you can use to +control how the Kerberos distribution is built. The following table +lists the most commonly used options to Kerberos V5's @samp{configure} +program. + +@table @code + +@item --help + +Provides help to configure. This will list the set of commonly used +options for building Kerberos. + +@item --prefix=PREFIX + +By default, Kerberos will install the package's files rooted at +`/usr/local' as in `/usr/local/bin', `/usr/local/sbin', etc. If you +desire a different location, use this option. + +@item --exec-prefix=EXECPREFIX + +This option allows one to separate the architecture independent programs +from the configuration files and manual pages. + +@item --localstatedir=LOCALSTATEDIR + +This option sets the directory for locally modifiable single-machine +data. In Kerberos, this mostly is useful for setting a location for the +KDC data files, as they will be installed in +@code{LOCALSTATEDIR/krb5kdc}, which is by default +@code{PREFIX/var/krb5kdc}. + +@item CC=COMPILER + +Use @code{COMPILER} as the C compiler. + +@item CFLAGS=FLAGS + +Use @code{FLAGS} as the default set of C compiler flags. + +Note that if you use the native Ultrix compiler on a +DECstation you are likely to lose if you pass no flags to cc; md4.c +takes an estimated 3,469 billion years to compile if you provide neither +the @samp{-g} flag nor the @samp{-O} flag to @samp{cc}. + +@item CPPFLAGS=CPPOPTS + +Use @code{CPPOPTS} as the default set of C preprocessor flags. The most +common use of this option is to select certain @code{#define}'s for use +with the operating system's include files. + +@item LD=LINKER + +Use @code{LINKER} as the default loader if it should be different from C +compiler as specified above. + +@item LDFLAGS=LDOPTS + +This option allows one to specify optional arguments to be passed to the +linker. This might be used to specify optional library paths. + +@item --with-krb4 + +This option enables Kerberos V4 backwards compatibility using the +builtin Kerberos V4 library. + +@item --with-krb4=KRB4DIR + +This option enables Kerberos V4 backwards compatibility using a +pre-existing Kerberos V4 installation. The directory specified by +@code{KRB4DIR} specifies where the V4 header files should be found +(@file{KRB4DIR/include}) as well as where the V4 Kerberos library should +be found (@file{KRB4DIR/lib}). + +@item --without-krb4 + +Disables Kerberos V4 backwards compatibility. This prevents Kerberos V4 +clients from using the V5 services including the KDC. This would be +useful if you know you will never install or need to interact with V4 +clients. + +@item --with-netlib[=libs] + +Allows for suppression of or replacement of network libraries. By +default, Kerberos V5 configuration will look for @code{-lnsl} and +@code{-lsocket}. If your operating system has a broken resolver library +(see @ref{Solaris versions 2.0 through 2.3}) or fails to pass the tests in +@file{src/tests/resolv} you will need to use this option. + +@item --with-tcl=TCLPATH + +Some of the unit-tests in the build tree rely upon using a program in +Tcl. The directory specified by @code{TCLPATH} specifies where the Tcl +header file (@file{TCLPATH/include/tcl.h} as well as where the Tcl +library should be found (@file{TCLPATH/lib}). + +@item --enable-shared + +This option will turn on the building and use of shared library objects +in the Kerberos build. This option is only supported on certain +platforms. + +@item --enable-dns +@item --enable-dns-for-kdc +@item --enable-dns-for-realm + +Enable the use of DNS to look up a host's Kerberos realm, or a realm's +KDCs, if the information is not provided in krb5.conf. See @ref{Hostnames +for the Master and Slave KDCs} for information about using DNS to +locate the KDCs, and @ref{Mapping Hostnames onto Kerberos Realms} for +information about using DNS to determine the default realm. By default, +DNS lookups are enabled for the former but not for the latter. + +@item --enable-kdc-replay-cache + +Enable a cache in the KDC to detect retransmitted messages, and resend +the previous responses to them. This protects against certain types of +attempts to extract information from the KDC through some of the +hardware preauthentication systems. + +@item --with-system-et + +Use an installed version of the error-table support software, the +@samp{compile_et} program, the @file{com_err.h} header file and the +@file{com_err} library. If these are not in the default locations, +you may wish to specify @code{CPPFLAGS=-I/some/dir} and +@code{LDFLAGS=-L/some/other/dir} options at configuration time as +well. + +If this option is not given, a version supplied with the Kerberos +sources will be built and installed along with the rest of the +Kerberos tree, for Kerberos applications to link against. + +@item --with-system-ss + +Use an installed version of the subsystem command-line interface +software, the @samp{mk_cmds} program, the @file{ss/ss.h} header file +and the @file{ss} library. If these are not in the default locations, +you may wish to specify @code{CPPFLAGS=-I/some/dir} and +@code{LDFLAGS=-L/some/other/dir} options at configuration time as +well. See also the @samp{SS_LIB} option. + +If this option is not given, the @file{ss} library supplied with the +Kerberos sources will be compiled and linked into those programs that +need it; it will not be installed separately. + +@item SS_LIB=libs... + +If @samp{-lss} is not the correct way to link in your installed +@file{ss} library, for example if additional support libraries are +needed, specify the correct link options here. Some variants of this +library are around which allow for Emacs-like line editing, but +different versions require different support libraries to be +explicitly specified. + +This option is ignored if @samp{--with-system-ss} is not specified. + +@item --with-system-db + +Use an installed version of the Berkeley DB package, which must +provide an API compatible with version 1.85. This option is +@emph{unsupported} and untested. In particular, we do not know if the +database-rename code used in the dumpfile load operation will behave +properly. + +If this option is not given, a version supplied with the Kerberos +sources will be built and installed. (We are not updating this +version at this time because of licensing issues with newer versions +that we haven't investigated sufficiently yet.) + +@item DB_HEADER=headername.h + +If @samp{db.h} is not the correct header file to include to compile +against the Berkeley DB 1.85 API, specify the correct header file name +with this option. For example, @samp{DB_HEADER=db3/db_185.h}. + +@item DB_LIB=libs... + +If @samp{-ldb} is not the correct library specification for the +Berkeley DB library version to be used, override it with this option. +For example, @samp{DB_LIB=-ldb-3.3}. + +@end table + +For example, in order to configure Kerberos on a Solaris machine using +the @samp{suncc} compiler with the optimizer turned on, run the configure +script with the following options: + +@example +% ./configure CC=suncc CFLAGS=-O +@end example + +For a slightly more complicated example, consider a system where +several packages to be used by Kerberos are installed in +@samp{/usr/foobar}, including Berkeley DB 3.3, and an @samp{ss} +library that needs to link against the @samp{curses} library. The +configuration of Kerberos might be done thus: + +@example +% ./configure CPPFLAGS=-I/usr/foobar/include LDFLAGS=-L/usr/foobar/lib \ + --with-system-et --with-system-ss --with-system-db \ + SS_LIB='-lss -lcurses' \ + DB_HEADER=db3/db_185.h DB_LIB=-ldb-3.3 +@end example + +In previous releases, @code{--with-} options were used to specify the +compiler and linker and their options. + +@node osconf.h, Shared Library Support, Options to Configure, Building Kerberos V5 +@section @file{osconf.h} + +There is one configuration file which you may wish to edit to control +various compile-time parameters in the Kerberos distribution: +@file{include/stock/osconf.h}. The list that follows is by no means +complete, just some of the more interesting variables. + +Please note: The former configuration file @file{config.h} no longer +exists as its functionality has been merged into the auto-configuration +process. @xref{Options to Configure}. + + +@table @code + +@item DEFAULT_PROFILE_PATH + +The pathname to the file which contains the profiles for the known realms, +their KDCs, etc. The default value is @value{DefaultDefaultProfilePath}. + +The profile file format is no longer the same format as Kerberos V4's +@file{krb.conf} file. + +@item DEFAULT_KEYTAB_NAME + +The type and pathname to the default server keytab file (the +equivalent of Kerberos V4's @file{/etc/srvtab}). The default is +@value{DefaultDefaultKeytabName}. + +@item DEFAULT_KDC_ENCTYPE + +The default encryption type for the KDC. The default value is +@value{DefaultMasterKeyType}. + +@item KDCRCACHE + +The name of the replay cache used by the KDC. The default value is +@value{DefaultKDCRCache}. + +@item RCTMPDIR + +The directory which stores replay caches. The default is to try +@value{DefaultRCTmpDirs}. + +@item DEFAULT_KDB_FILE + +The location of the default database. The default value is +@value{DefaultDatabaseName}. + +@end table + +@node Shared Library Support, OS Incompatibilities, osconf.h, Building Kerberos V5 +@section Shared Library Support + +Shared library support is provided for a few operating systems. There +are restrictions as to which compiler to use when using shared +libraries. In all cases, executables linked with the shared libraries in +this build process will have built in the location of the libraries, +therefore obliterating the need for special LD_LIBRARY_PATH, et al environment +variables when using the programs. Except where noted, multiple versions +of the libraries may be installed on the same system and continue to +work. + +Currently the supported platforms are Solaris 2.6-2.9 (aka SunOS +5.6-5.9), Irix 6.5, Redhat Linux, MacOS 8-10, and Microsoft Windows +(using DLLs). + +Shared library support has been tested on the following platforms but +not exhaustively (they have been built but not necessarily tested in an +installed state): Tru64 (aka Alpha OSF/1 or Digital Unix) 4.0, and +HP/UX 10.20. + +Platforms for which there is shared library support but not significant +testing include FreeBSD, OpenBSD, AIX (4.3.3), Linux, NetBSD 1.4.x +(i386), and SunOS 4.x. + +To enable shared libraries on the above platforms, run the configure +script with the option @samp{--enable-shared}. + +@ifset notdef + +XXX What does this mean? + +One special note is that if the Kerberos V4 compatibility is compiled +in, you @b{must not} specify an alternate Kerberos V4 library from the +one in the tree or you will be missing references. + +@end ifset + +@node OS Incompatibilities, Using Autoconf, Shared Library Support, Building Kerberos V5 +@section Operating System Incompatibilities + +This section details operating system incompatibilities with Kerberos V5 +which have been reported to the developers at MIT. If you find +additional incompatibilities, and/or discover workarounds to such +problems, please send a report via the @code{krb5-send-pr} program. +Thanks! + +@menu +* AIX:: +* Alpha OSF/1 V1.3:: +* Alpha OSF/1 V2.0:: +* Alpha OSF/1 V4.0:: +* BSDI:: +* HPUX:: +* Solaris versions 2.0 through 2.3:: +* Solaris 2.X:: +* Solaris 9:: +* SGI Irix 5.X:: +* Ultrix 4.2/3:: +@end menu + +@node AIX, Alpha OSF/1 V1.3, OS Incompatibilities, OS Incompatibilities +@subsection AIX + +The AIX 3.2.5 linker dumps core trying to build a shared +@samp{libkrb5.a} produced with the GNU C compiler. The native AIX +compiler works fine. This problem is fixed using the AIX 4.1 linker. + +@node Alpha OSF/1 V1.3, Alpha OSF/1 V2.0, AIX, OS Incompatibilities +@subsection Alpha OSF/1 V1.3 + +Using the native compiler, compiling with the @samp{-O} compiler flag +causes the @code{asn.1} library to be compiled incorrectly. + +Using GCC version 2.6.3 or later instead of the native compiler will also work +fine, both with or without optimization. + +@node Alpha OSF/1 V2.0, Alpha OSF/1 V4.0, Alpha OSF/1 V1.3, OS Incompatibilities +@subsection Alpha OSF/1 V2.0 + +There used to be a bug when using the native compiler in compiling +@file{md4.c} when compiled without either the @samp{-O} or @samp{-g} +compiler options. We have changed the code and there is no problem +under V2.1, but we do not have access to V2.0 to test and see if the +problem would exist there. (We welcome feedback on this issue). There +was never a problem in using GCC version 2.6.3. + +In version 3.2 and beyond of the operating system, we have not seen +this sort of problem with the native compiler. + +@node Alpha OSF/1 V4.0, BSDI, Alpha OSF/1 V2.0, OS Incompatibilities +@subsection Alpha OSF/1 (Digital UNIX) V4.0 + +The C compiler provided with Alpha OSF/1 V4.0 (a.k.a. Digital UNIX) +defaults to an extended K&R C mode, not ANSI C. You need to provide +the @samp{-std} argument to the compiler (i.e., @samp{./configure +CC='cc -std'}) to enable extended ANSI C mode. More recent versions +of the operating system, such as 5.0, seem to have C compilers which +default to @samp{-std}. + +@c @node Alpha Tru64 UNIX 5.0 +@c @subsection Alpha Tru64 UNIX 5.0 +@c ... login.krb5 problems + +@node BSDI, HPUX, Alpha OSF/1 V4.0, OS Incompatibilities +@subsection BSDI + +BSDI versions 1.0 and 1.1 reportedly has a bad @samp{sed} which causes +it to go into an infinite loop during the build. The work around is +to use a @samp{sed} from somewhere else, such as GNU. (This may be +true for some versions of other systems derived from BSD 4.4, such as +NetBSD and FreeBSD.) + +@node HPUX, Solaris versions 2.0 through 2.3, BSDI, OS Incompatibilities +@subsection HPUX + +The native (bundled) compiler for HPUX currently will not work, +because it is not a full ANSI C compiler. The optional ANSI C +compiler should work as long as you give it the @samp{-Ae} flag +(i.e. @samp{./configure CC='cc -Ae'}). This is equivalent to +@samp{./configure CC='c89 -D_HPUX_SOURCE'}, which was the previous +recommendation. This has only been tested recently for HPUX 10.20. + +You will need to configure with @samp{--disable-shared +--enable-static}, because as of 1.4 we don't have support for HPUX +shared library finalization routines, nor the option (yet) to ignore +that lack of support (which means repeated +@code{dlopen}/@code{dlclose} cycles on the Kerberos libraries may not +be safe) and build the shared libraries anyways. + +You will also need to configure the build tree with +@samp{--disable-thread-support} if you are on HPUX 10 and do not have +the DCE development package installed, because that's where the +@code{pthread.h} header file is found. (We don't know if our code +will work with such a package installed, because according to some HP +documentation, their @code{pthread.h} has to be included before any +other header files, and our code doesn't do that.) + +If you use GCC, it may work, but some versions of GCC have omitted +certain important preprocessor defines, like @code{__STDC_EXT__} and +@code{__hpux}. + +@node Solaris versions 2.0 through 2.3, Solaris 2.X, HPUX, OS Incompatibilities +@subsection Solaris versions 2.0 through 2.3 + +The @code{gethostbyname()} routine is broken; it does not return a fully +qualified domain name, even if you are using the Domain Name Service +routines. Since Kerberos V5 uses the fully qualified domain name as the +second component of a service principal (i.e, +@samp{host/tsx-11.mit.edu@@ATHENA.MIT.EDU}), this causes problems for servers +who try to figure out their own fully qualified domain name. + +Workarounds: + +@enumerate + +@item + Supply your own resolver library. (such as bind-4.9.3pl1 available +from ftp.vix.com) + +@item + Upgrade to Solaris 2.4 + +@item + Make sure your /etc/nsswitch.conf has `files' before `dns' like: + +@example +hosts: files dns +@end example + +and then in /etc/hosts, make sure there is a line with your +workstation's IP address and hostname, with the fully qualified domain +name first. Example: + +@example +18.172.1.4 dcl.mit.edu dcl +@end example + +Note that making this change may cause other programs in your +environment to break or behave differently. + +@end enumerate + +@node Solaris 2.X, Solaris 9, Solaris versions 2.0 through 2.3, OS Incompatibilities +@subsection Solaris 2.X + +You @b{must} compile Kerberos V5 without the UCB compatibility +libraries. This means that @file{/usr/ucblib} must not be in the +LD_LIBRARY_PATH environment variable when you compile it. Alternatively +you can use the @code{-i} option to @samp{cc}, by using the specifying +@code{CFLAGS=-i} option to @samp{configure}. + +If you are compiling for a 64-bit execution environment, you may need +to configure with the option @code{CFLAGS="-D_XOPEN_SOURCE=500 +-D__EXTENSIONS__"}. This is not well tested; at MIT we work primarily +with the 32-bit execution environment. + +@node Solaris 9, SGI Irix 5.X, Solaris 2.X, OS Incompatibilities +@subsection Solaris 9 + +Solaris 9 has a kernel race condition which causes the final output +written to the slave side of a pty to be lost upon the final close() +of the slave device. This causes the dejagnu-based tests to fail +intermittently. A workaround exists, but requires some help from the +scheduler, and the ``make check'' must be executed from a shell with +elevated priority limits. + +Run something like + +@code{priocntl -s -c FX -m 30 -p 30 -i pid nnnn} + +as root, where @code{nnnn} is the pid of the shell whose priority +limit you wish to raise. + +Sun has released kernel patches for this race condition. Apply patch +117171-11 for sparc, or patch 117172-11 for x86. Later revisions of +the patches should also work. It is not necessary to run ``make +check'' from a shell with elevated priority limits once the patch has +been applied. + +@node SGI Irix 5.X, Ultrix 4.2/3, Solaris 9, OS Incompatibilities +@subsection SGI Irix 5.X + +If you are building in a tree separate from the source tree, the vendors +version of make does not work properly with regards to +@samp{VPATH}. It also has problems with standard inference rules in 5.2 +(not tested yet in 5.3) so one needs to use GNU's make. + +Under 5.2, there is a bug in the optional System V @code{-lsocket} +library in which the routine @code{gethostbyname()} is broken. The +system supplied version in @code{-lc} appears to work though so one may +simply specify @code{--with-netlib} option to @samp{configure}. + +In 5.3, @code{gethostbyname()} is no longer present in @code{-lsocket} and +is no longer an issue. + +@node Ultrix 4.2/3, , SGI Irix 5.X, OS Incompatibilities +@subsection Ultrix 4.2/3 + +The DEC MIPS platform currently will not support the native compiler, +since the Ultrix compiler is not a full ANSI C compiler. You should use +GCC instead. + +@ifset notdef + +On the DEC MIPS platform, using the native compiler, @file{md4.c} and +@file{md5.c} can not be compiled with the optimizer set at level 1. +That is, you must specify either @samp{CFLAGS=-O} and +@samp{CFLAGS=-g} to configure. If you don't specify either, the +compile will never complete. + +The optimizer isn't hung; it just takes an exponentially long time. +Compiling 6 out of the 48 algorithmic steps takes 3 seconds; compiling 7 +steps takes 9 seconds; compiling 8 steps takes 27 seconds, and so on. +Calculations estimate it will finish in approximately 3,469 billion +years.... + +Using GCC instead of the native compiler will also work fine, both with +or without optimization. + +@end ifset + +@node Using Autoconf, , OS Incompatibilities, Building Kerberos V5 +@section Using @samp{Autoconf} + +(If you are not a developer, you can skip this section.) + +In most of the Kerberos V5 source directories, there is a +@file{configure} script which automatically determines the compilation +environment and creates the proper Makefiles for a particular +platform. These @file{configure} files are generated using +@samp{autoconf}, which can be found in the @file{src/util/autoconf} +directory in the distribution. + +Normal users will not need to worry about running @samp{autoconf}; the +distribution comes with the @file{configure} files already prebuilt. +Developers who wish to modify the @file{configure.in} files should see +@ref{Top, , Overview, autoconf, The Autoconf Manual}. + +Note that in order to run @samp{autoconf}, you must have GNU @samp{m4} +in your path. Before you use the @samp{autoconf} in the Kerberos V5 +source tree, you may also need to run @samp{configure}, and then run +@samp{make} in the @file{src/util/autoconf} directory in order to +properly set up @samp{autoconf}. + +One tool which is provided for the convenience of developers can be +found in @file{src/util/reconf}. This program should be run while the +current directory is the top source directory. It will automatically +rebuild any @file{configure} files which need rebuilding. If you know +that you have made a change that will require that all the +@file{configure} files need to be rebuilt from scratch, specify the +@code{--force} option: + +@example +% cd /u1/krb5-@value{RELEASE}/src +% ./util/reconf --force +@end example + +The developmental sources are a raw source tree (before it's been packaged +for public release), without the pre-built @file{configure} files. +In order to build from such a source tree, you must do: + +@example +% cd krb5/util/autoconf +% ./configure +% make +% cd ../.. +% util/reconf +@end example + +Then follow the instructions for building packaged source trees (above). +To install the binaries into a binary tree, do: + +@example +% cd /u1/krb5-@value{RELEASE}/src +% make all +% make install DESTDIR=somewhere-else +@end example + diff --git a/krb5-1-6/doc/coding-style b/krb5-1-6/doc/coding-style new file mode 100644 index 000000000..e4c99967a --- /dev/null +++ b/krb5-1-6/doc/coding-style @@ -0,0 +1,566 @@ +WRITING C CODE +============== + +The code in the krb5 source tree largely follows BSD KNF +(/usr/share/misc/style on NetBSD) except that it uses a four column +basic offset. The style described here is a synthesis of BSD KNF and +the GNU coding standards for the C language. The formatting described +in the "Formatting Your Source Code" section of the GNU coding +standards is mostly what we want, except we use BSD brace style and +BSD-ish conventions for the spacing around operators. + +Formatting style for C code +--------------------------- + +In general, use a four column basic offset, tab stops at eight +columns. Indents should be tabified, i.e. continuous tabs followed by +spaces if necessary if the indent isn't a multiple of eight columns. +The "bsd" style in emacs cc-mode mostly does the right thing. You can +use "M-x c-set-style" "bsd" to get this. Alternatively, you can use +the "krb5" style that is included here. + +Labels, including case labels, are outdented by four columns. +Continuations of statements are indented by an additional four +columns. When continuing expressions this way, split the expression +so that the newline goes before a binary operator rather than after +it. + +Continuations of argument lists or parenthesized expressions should +line up with the column after the opening parenthesis. Note that this +may create width problems if you call a fuction deep in a bunch of +nested control flow statements. Regardless, any expression split +between lines should stil be split so that the newline goes before a +binary operator rather than after it. + +The maximum width should be 79 columns. If you need more than this, +consider rewriting the code so that it fits in 79 columns, since +control flow that is nested deeply enough to require excessive width +is also likely to be difficult to understand if not broken up. +Exceptions may be made for long strings, though ANSI C string +concatenation should work around that as well. + +Function names for definitions should start on column zero, on the +line following their return type name, e.g. + + char * + foo(int a) + { + /* ... */ + } + +[just pretend that's really at column zero] + +The opening brace of a function definition should also be on column +zero. + +Braces that open substatements, such as those following "if", "else", +"while", "for", "do", and "switch", should be on the same line as the +begining of the statement. This is sometimes called "hanging" braces. +The corresponding closing brace should be at the same indentation +level as the beginning of the statement. + +The "while" keyword in a do-while construct should sit on the same +line as the closing brace of the substatement following "do": + + do { + foo(); + } while (0); + +If there is an "if" statement immediately following an "else" keyword, +it should go on the same line immediately after the "else": + + if (x) { + foo(); + } else if (y) { + bar(); + } + +Comments to the right of code start in column 32. Comments not to the +right of code are indented at the prevailing indent for the +surrounding code. Make the comments complete sentences. If you need +more than one line, make them into block comments, like this: + + /* + * This is a block comment. It should consist of complete + * sentences. + * + * Paragraphs should be separated by blank lines so that emacs + * fill commands will work properly. + */ + +Really important single-line comments should also be done in block +form: + + /* + * This is a really important one-line comment. + */ + +In order to get the start and end delimiters for block comments to +stay when you use emacs to fill paragraphs in the comments, set both +the c-hanging-comment-starter-p and the c-hanging-comment-ender-p +variables to nil. This will be done by the tentative "krb5" style for +the emacs cc-mode. + +Since we are mostly aiming for C '89 compatibility, don't use "//" +comments. + +Spaces go after keywords, but not after function names. Do not, +however, put a space after sizeof. Don't put a space after a cast +operator, either. Spaces also do not go before parentheses that are +argument lists for function calls even if the function call is through +a pointer. Spaces go after commas in argument lists, as well as +commas that are comma operators. Spaces also go between parts in a +for loop, except for "forever" type loops. Use for statements rather +than while statements to create forever loops. + + if (x) { + p = calloc(1024, sizeof(int)); + } + cp = (*elem->fp)(1024); + for (i = 0; i < 10; i++); + for (;;) { + /* ... */ + } + +Binary operators get spaces, unary ones do not. Prefix and postfix +operators also do not get spaces. The structure member operators "." +and "->" count as postfix operators syntactically, not as binary +operators. + + x = --a + b / c - d++; + y = p->z.v[x]; + +Put spaces around the "?" and ":" in a conditional expression. + + x = y ? f() : g(); + +In general, do not parenthesize the argument of "return". + +Coding practices for C +---------------------- + +Assume, for most purposes, working ANSI/ISO C ('89, not '99) support, +both for internal use and for applications compiling against Kerberos +header files and libraries. Some exceptions are noted below. + +Do not use assignments as truth values. Rather than this: + + /* bad style */ + if ((retval = krb5_foo())) + /* ... */; + +do this: + + /* better style */ + retval = krb5_foo(); + if (retval) + /* ... */; + +This makes the code easier to read, and also makes it easier to use +debuggers. It may be excusable to put assignments into the +conditional espression of a "while" statement, though, like: + + while ((ch = getopt(argc, argv, "abn")) != -1) + /* ... */; + +Using assignments as truth values in conditional expressions may make +code particularly impenetrable. + +There are at least three types of "zero" known to C. These are the +integer zero (0), the null pointer constant (NULL), and the character +constant zero ('\0'). Yes, these are usually all technically the +integer zero. Use them in their correct contexts. (Purists will +point out that 0 is a valid null pointer constant; still, do not use 0 +to specify a null pointer constant. For further unconfusion, read the +section on null pointer constants in the C FAQ.) Do not use a lone +variable as a truth value unless it's of integer type. Thus: + + int i; + char *cp; + /* ... */ + if (i) + /* ... */; + if (cp != NULL) { + while (*cp != '\0') + /* ... */; + } + +Do not cast uses of NULL unless you're calling a function with a +variable number of arguments, in which case you should cast it to to +the appropriate pointer type. Likewise, do not cast the return value +from malloc() and friends; the prototype should declare them properly +as returning a void * and thus shouldn't require an explicit cast. + +Do not assume that realloc(NULL, size) will do the right thing, or +that free(NULL) will do the right thing. ANSI guarantees that it +will, but some old libraries (hopefully becoming obsolete) don't. +Also, don't assume that malloc(0) will return a non-NULL pointer. +Typically, though, the output of malloc(0) will be safe to pass to +realloc() and free(). + +In any case, reading the section in the C FAQ on null pointers is +highly recommended to remove confusion regarding null pointers in C, +since this is a subject of much confusion to even experienced +programmers. In particular, if you do not understand why using +calloc() to allocate a struct that contains pointer members or why +calling memset() to initialize such a struct to all-bytes-zero is +wrong, reread that section again. (Note that there are *lots* of +examples of code in the krb5 source tree that erroneously calls +memset() to zero a struct, and we should fix these somehow +eventually.) + +Control flow statements that have a single statement as their body +should nevertheless have braces around their bodies if the body is +more than one line long, especially in the case of stacked multiple +if-else clauses; use: + + if (x) { + if (y) + foo(); + else + bar(); + } + +instead of: + + /* bad style */ + if (x) + if (y) + foo(); + else + bar(); + +which, while legible to the compiler, may confuse human readers and +make the code less maintainable, especially if new branches get added +to any of the clauses. + +Also, you should almost never intersperse conditional compilation +directives with control flow statements, as some combination of +#define'd symbols may result in statements getting eaten by dangling +bits of control flow statements. When it is not possible to avoid +this questionable practice (you really should rewrite the relevant +code section), make use of redundant braces to ensure that a compiler +error will result in preference to incorrect runtime behavior (such as +inadvertantly providing someone with a root shell). + +Do not intersperse conditional compilation directives with control +flow statements in such a way that confuses emacs cc-mode. Not only +does emacs get confused, but the code becomes more difficult to read +and maintain. Therefore, avoid code like this: + + /* bad style */ + if (x) { + f(); + } + #ifdef FOO + else if (y) { + #else + else { + #endif + g(); + } + +Put comments after conditional compilation directives such as "#else" +and "#endif". Make them correspond to the sense of the value that +controls the compilation of the section they are closing, i.e. + + #ifdef FOO + /* ... */ + #else /* !FOO */ + /* ... */ + #endif /* !FOO */ + +Also, in the case of more complex conditional compilation directives, +write the comments like this: + + #if defined(FOO) || defined(BAR) + /* ... */ + #else /* !(defined(FOO) || defined(BAR)) */ + /* ... */ + #endif /* !(defined(FOO) || defined(BAR)) */ + +If you are writing a do-while loop that has only one statement in its +body, put braces around it anyway, since the while clause may be +mistaken for a while loop with an empty body. Don't do this: + + /* bad style */ + do + foo(); + while (x); + +Instead, write this: + + /* better style */ + do { + foo(); + } while (x); + +While it is syntactically correct to call through a function pointer +without applying a dereference operator to it, do not write code that +does this. It is easier to see that the function call is actually +taking place through a function pointer if you write an explicit +dereference. However, do not explicitly take the address of a +function in order to assign it to a function pointer, since a function +name degrades into a pointer. Thus: + + int (*fp)(void); + int foofunc(void); + fp = foofunc; + x = (*fp)(); + +In general, do not take the address of an array. It does not return a +pointer to the first element; it returns a pointer to the array +itself. These are often identical when cast to an integral type, but +they are inherently of different types themselves. Functions that +take array types or pointers to array types as arguments can be +particularly trouble-prone. + +If a function is declared to return a value, do not call "return" +without an argument or allow the flow of control to fall off the end +of the function. + +Always declare the return type of a function, even if it returns int. +Yes, this means declaring main() to return int, since main() is +required to return int by the standard. If a function is not supposed +to return a value, declare it as returning void rather than omitting +the return type, which will default the return type to int. + +Try to use ANSI C prototype-style function definitions in preference +to K&R style definitions. When using K&R style function definitions, +declare all the argument types, even those that are int, but beware of +any narrow types in the argument list. + +Do not declare variables in an inner scope, e.g. inside the compound +substatement of an if statement, unless the complexity of the code +really demands that the variables be declared that way. In such +situations, the function could probably stand to be broken up into +smaller chunks anyway. Do not declare variables in an inner scope +that shadow ones in an outer scope, since this leads to confusion. +Also, some debugging environments, such as gdb under Solaris, can't +see variables declared in an inner scope, so declaring such variables +will make maintenance more difficult as well. + +Parenthesize expressions that may be confusing, particularly where C's +precedences are broken. For example, the shift operators have lower +precedence than the +, -, *, /, and % operators. Perhaps the most +familiar C precedence quirk is that equality and relational operators +are of higher precedence than assignment operators. Less well known +is that the bitwise operators are of a lower precedence than equality +and relational operators. + +The sizeof operator takes either a unary expression or a parenthesized +type name. It is not necessary to parenthesize the operand of sizeof +if it is applied to a unary expression, but still, always parenthesize +the operand of the sizeof operator. The sizeof operator does not +evaluate its operand if it is a unary expression, so usages such as + + s = sizeof(++foo); + +should be avoided for the sake of sanity and readability. + +Don't pass around structures except by address. We may relax this +restriction for non-API function, though. + +For new functions, input parameters should go before output parameters +in the call signature. There are exceptions, such as a context-like +parameter. + +Every function should have block comment preceding it describing +briefly in complete sentences what it does, what inputs and outputs it +has, and what error codes it can return. It should also describe any +unsual aspects of the function. At some point we will want to put +some of this information into a machine-parsable form. + +Macros should have all-uppercase names. If it is necessary to use +multiple statements, use braces, and wrap the whole thing in a +do-while(0) construct, such as + + #define FOOMACRO(x, y) do { \ + foo = (x) + (y); \ + f(y); \ + } while (0) + +Leave off the semicolon at the end of a function-like macro, so that +it can be mostly used like a call to a function without a return +value. Line up the backslashes to make it more readable. Use M-x +c-backslash-region in emacs to do neat lined-up backslashes. +Parenthesize uses of arguments in the replacement text of a macro in +order to prevent weird interactions. + +Strive to make your code capable of compiling using "gcc -Wall +-Wmissing-prototypes -Wtraditional -Wcast-qual -Wcast-align +-Wconversion -Waggregate-return -pedantic" [XXX need to rethink this +somewhat] without generating any errors or warnings. Do not, however, +compile using the "-ansi" flag to gcc, since that can result in odd +behavior with header files on some systems, causing some necessary +symbols to not be defined. + +Namespaces +---------- + +The C standard reserves a bunch of namespaces for the implementation. +Don't stomp on them. For practical purposes, any identifier with a +leading underscore should not be used. (Technically, ^_[a-z].* are +reserved only for file scope, so should be safe for things smaller +than file scope, but it's better to be paranoid in this case.) + +POSIX reserves typedef names ending with _t as well. + +Recall that errno is a reserved identifier, and is permitted to be a +macro. Therefore, do not use errno as the name of a structure member, +etc. + +Reserved namespaces are somewhat more restricted than this; read the +appropriate section of the C standard if you have questions. + +If you're writing new library code, pick a short prefix and stick with +it for any identifier with external linkage. If for some reason a +library needs to have external symbols that should not be visible to +the application, pick another (related) prefix to use for the internal +globals. This applies to typedef names, tag names, and preprocessor +identifiers as well. + +For the krb5 library, the prefix for public global symbols is "krb5_". +Use "krb5int_" as a prefix for library internal globals. Avoid using +"__" in symbol names, as it may confuse C++ implementations. There +are admittedly a number of places where we leak thing into the +namespace; we should try to fix these. + +Header files should also not leak symbols. Usually using the upcased +version of the prefix you've picked will suffice, e.g. "KRB5_" as a +CPP symbol prefix corresponding to "krb5_". In general, do not define +macros that are lowercase, in order to avoid confusion and to prevent +namespace collisions. + +The C standard only guarantees six case-insensitive characters to be +significant in external identifiers; this is largely regarded as +obsolescent even in 1989 and we will ignore it. It does, however, +only guarantee 31 case-sensitive characters to be signficant in +internal identifiers, so do not use identifiers that differ beyond the +31st character. This is unlikely to be a problem, though. + +Aspects of C style in GNU coding std but not here +------------------------------------------------- + +* redundant parens to force extra indent of operators of different + precedences + +* redundant parens to force general extra indent of expressions that + are broken between lines + +* use of ^L characters to break up source files into pages + +* nitpicking about capitalization in comments of variable names when + their values are meant + +* commenting usages of static variables + +* casts to void + +* separation of word in names with underscores vs case change + +* enum vs #define'd integer constants + +* 14 char filename limits, MS-DOS filename limits + +* portability + +* system library function quirks + +* internationalization + +* mmap() + +Aspects of C style in BSD KNF but not here +------------------------------------------ + +* sorting of header files + +* sorting of struct members + +* separating struct tag decl and struct typedef + +* sorting of var decl + +* lining up var names in decls + +* newline after decls + +* usage of __P + +* usage of getopt + +* not initializing vars in decls + +* stdarg/varargs handling + +Emacs cc-mode style +------------------- + +Putting the following code in your .emacs file will result in mostly +the right thing happening with respect to formatting style. Note that +you may want to turn on auto-newline feature of cc-mode, though that +seems to have some bugs with brace-elseif-brace handling at least in +the version of cc-mode that comes with emacs 20.3. + + (defconst krb5-c-style + '("bsd" + (c-cleanup-list + brace-elseif-brace brace-else-brace defun-close-semi) + (c-comment-continuation-stars . "* ") + (c-electric-pound-behavior alignleft) + (c-hanging-braces-alist + (brace-list-open) + (class-open after) + (substatement-open after) + (block-close . c-snug-do-while) + (extern-lang-open after)) + (c-hanging-colons-alist + (case-label after) + (label after)) + (c-hanging-comment-starter-p) + (c-hanging-comment-ender-p) + (c-indent-comments-syntactically-p . t) + (c-label-minimum-indentation . 0) + (c-special-indent-hook))) + (defun krb5-c-hook () + (c-add-style "krb5" krb5-c-style t)) + (add-hook 'c-mode-common-hook 'krb5-c-hook) + +indent.pro settings +------------------- + +The following settings for the indent program should produce a +reasonable approximation to the C coding style described here, though +some manual cleanup may be necessary. Note that the gindent installed +in the gnu locker does not currently handle -psl correctly though. + +-bap +-br +-ce +-ci4 +-cli0 +-d0 +-di8 +-i4 +-ip4 +-l79 +-nbc +-ncdb +-ndj +-nfc1 +-lp +-npcs +-psl +-sc +-sob + +MAKEFILES +========= + +[XXX needs to be written] + +TEST SUITES +=========== + +[XXX needs to be written] diff --git a/krb5-1-6/doc/copyright.texinfo b/krb5-1-6/doc/copyright.texinfo new file mode 100644 index 000000000..5d239b561 --- /dev/null +++ b/krb5-1-6/doc/copyright.texinfo @@ -0,0 +1,525 @@ +Copyright @copyright{} 1985-2007 by the Massachusetts Institute of Technology. + +@quotation +Export of software employing encryption 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. +@end quotation + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute +this software and its documentation for any purpose and without fee is +hereby granted, provided that the above copyright notice appear in all +copies and that both that copyright notice and this permission notice +appear in supporting documentation, and that the name of M.I.T. not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. Furthermore if you +modify this software you must label your software as modified software +and not distribute it in such a fashion that it might be confused with +the original MIT software. M.I.T. makes no representations about the +suitability of this software for any purpose. It is provided ``as is'' +without express or implied warranty. + +Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +``Commercial use'' means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in +@code{kadmin/create}, @code{kadmin/dbutil}, @code{kadmin/passwd}, +@code{kadmin/server}, @code{lib/kadm5}, and portions of +@code{lib/rpc}: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright, OpenVision Technologies, Inc., 1996, All Rights Reserved + +WARNING: Retrieving the OpenVision Kerberos Administration system source +code, as described below, indicates your acceptance of the following +terms. If you do not agree to the following terms, do not retrieve the +OpenVision Kerberos administration system. + +You may freely use and distribute the Source Code and Object Code +compiled from it, with or without modification, but this Source Code is +provided to you ``AS IS'' EXCLUSIVE OF ANY WARRANTY, INCLUDING, WITHOUT +LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A +PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER EXPRESS OR IMPLIED. +IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY FOR ANY LOST PROFITS, +LOSS OF DATA OR COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR +FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS +AGREEMENT, INCLUDING, WITHOUT LIMITATION, THOSE RESULTING FROM THE USE +OF THE SOURCE CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR +ANY OTHER REASON. + +OpenVision retains all copyrights in the donated Source Code. OpenVision +also retains copyright to derivative works of the Source Code, whether +created by OpenVision or by a third party. The OpenVision copyright +notice must be preserved if derivative works are made based on the +donated Source Code. + +OpenVision Technologies, Inc. has donated this Kerberos Administration +system to MIT for inclusion in the standard Kerberos 5 distribution. +This donation underscores our commitment to continuing Kerberos +technology development and our gratitude for the valuable work which has +been performed by MIT and the Kerberos community. +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +@quotation +Portions contributed by Matt Crawford @code{} were work +performed at Fermi National Accelerator Laboratory, which is operated +by Universities Research Association, Inc., under contract +DE-AC02-76CHO3000 with the U.S. Department of Energy. +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +Portions of @code{src/lib/crypto} have the following copyright: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright @copyright{} 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. + +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +The implementation of the Yarrow pseudo-random number generator +in @code{src/lib/crypto/yarrow} has the following copyright: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright 2000 by Zero-Knowledge Systems, Inc. + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +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 Zero-Knowledge Systems, +Inc. not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. Zero-Knowledge Systems, Inc. makes no representations +about the suitability of this software for any purpose. It is +provided ``as is'' without express or implied warranty. + +ZERO-KNOWLEDGE SYSTEMS, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL ZERO-KNOWLEDGE SYSTEMS, INC. BE LIABLE FOR +ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +The implementation of the AES encryption algorithm in +@code{src/lib/crypto/aes} has the following copyright: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright @copyright{} 2001, Dr Brian Gladman @code{}, +Worcester, UK.@* +All rights reserved. + +LICENSE TERMS + +The free distribution and use of this software in both source and binary +form is allowed (with or without changes) provided that: + +@enumerate +@item +distributions of this source code include the above copyright +notice, this list of conditions and the following disclaimer; +@item +distributions in binary form include the above copyright +notice, this list of conditions and the following disclaimer +in the documentation and/or other associated materials; +@item +the copyright holder's name is not used to endorse products +built using this software without specific written permission. +@end enumerate + +DISCLAIMER + +This software is provided 'as is' with no explcit or implied warranties +in respect of any properties, including, but not limited to, correctness +and fitness for purpose. +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +Portions contributed by Red Hat, including the pre-authentication +plug-in framework, contain the following copyright: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright @copyright{} 2006 Red Hat, Inc.@* +Portions copyright @copyright{} 2006 Massachusetts Institute of Technology@* +All Rights Reserved.@* + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +@itemize + +@item +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +@item +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +@item +Neither the name of Red Hat, Inc., nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. +@end itemize + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in +@code{src/lib/gssapi}, including the following files: + +@smallexample +lib/gssapi/generic/gssapi_err_generic.et +lib/gssapi/mechglue/g_accept_sec_context.c +lib/gssapi/mechglue/g_acquire_cred.c +lib/gssapi/mechglue/g_canon_name.c +lib/gssapi/mechglue/g_compare_name.c +lib/gssapi/mechglue/g_context_time.c +lib/gssapi/mechglue/g_delete_sec_context.c +lib/gssapi/mechglue/g_dsp_name.c +lib/gssapi/mechglue/g_dsp_status.c +lib/gssapi/mechglue/g_dup_name.c +lib/gssapi/mechglue/g_exp_sec_context.c +lib/gssapi/mechglue/g_export_name.c +lib/gssapi/mechglue/g_glue.c +lib/gssapi/mechglue/g_imp_name.c +lib/gssapi/mechglue/g_imp_sec_context.c +lib/gssapi/mechglue/g_init_sec_context.c +lib/gssapi/mechglue/g_initialize.c +lib/gssapi/mechglue/g_inquire_context.c +lib/gssapi/mechglue/g_inquire_cred.c +lib/gssapi/mechglue/g_inquire_names.c +lib/gssapi/mechglue/g_process_context.c +lib/gssapi/mechglue/g_rel_buffer.c +lib/gssapi/mechglue/g_rel_cred.c +lib/gssapi/mechglue/g_rel_name.c +lib/gssapi/mechglue/g_rel_oid_set.c +lib/gssapi/mechglue/g_seal.c +lib/gssapi/mechglue/g_sign.c +lib/gssapi/mechglue/g_store_cred.c +lib/gssapi/mechglue/g_unseal.c +lib/gssapi/mechglue/g_userok.c +lib/gssapi/mechglue/g_utils.c +lib/gssapi/mechglue/g_verify.c +lib/gssapi/mechglue/gssd_pname_to_uid.c +lib/gssapi/mechglue/mglueP.h +lib/gssapi/mechglue/oid_ops.c +lib/gssapi/spnego/gssapiP_spnego.h +lib/gssapi/spnego/spnego_mech.c +@end smallexample + +are subject to the following license: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright @copyright{} 2004 Sun Microsystems, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +@value{PRODUCT} includes documentation and software developed at the +University of California at Berkeley, which includes this copyright +notice: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright @copyright{} 1983 Regents of the University of California.@* +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +@enumerate +@item +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +@item +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +@item +Neither the name of the University nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. +@end enumerate + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +Portions contributed by Novell, Inc., including the LDAP database +backend, are subject to the following license: + +@quotation +@iftex +@smallfonts @rm +@end iftex +Copyright (c) 2004-2005, Novell, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +@itemize +@item +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +@item +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +@item +The copyright holder's name is not used to endorse or promote products +derived from this software without specific prior written permission. +@end itemize + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +@end quotation + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex + +Portions funded by Sandia National Laboratory +and developed by the University of Michigan's +Center for Information Technology Integration, +including the PKINIT implementation, are subject +to the following license: + +@quotation +@iftex +@smallfonts @rm +@end iftex + +COPYRIGHT @copyright{} 2006-2007@* +THE REGENTS OF THE UNIVERSITY OF MICHIGAN@* +ALL RIGHTS RESERVED + +Permission is granted to use, copy, create derivative works +and redistribute this software and such derivative works +for any purpose, so long as the name of The University of +Michigan is not used in any advertising or publicity +pertaining to the use of distribution of this software +without specific, written prior authorization. If the +above copyright notice or any other identification of the +University of Michigan is included in any copy of any +portion of this software, then the disclaimer below must +also be included. + +THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION +FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY +PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF +MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING +WITHOUT LIMITATION THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE +REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE +FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR +CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING +OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN +IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. +@end quotation + +The pkcs11.h file included in the PKINIT code has the +following license: + +@quotation +@iftex +@smallfonts @rm +@end iftex + +Copyright 2006 g10 Code GmbH +Copyright 2006 Andreas Jellinghaus + +This file is free software; as a special exception the author gives +unlimited permission to copy and/or distribute it, with or without +modifications, as long as this notice is preserved. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. + +@iftex +@vskip 12pt +@hrule +@vskip 12pt +@end iftex +@end quotation + +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notices and this permission notice are +preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries a copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). +@end ignore + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@iftex +@pagealignmacro +@end iftex diff --git a/krb5-1-6/doc/definitions.texinfo b/krb5-1-6/doc/definitions.texinfo new file mode 100644 index 000000000..529445f48 --- /dev/null +++ b/krb5-1-6/doc/definitions.texinfo @@ -0,0 +1,193 @@ +@c Set the "MIT" flag for the MIT edition; set the "CYGNUS" flag for +@c the Cygnus edition. +@clear CYGNUS +@set MIT +@set ADMINUSER joeadmin +@set COMPANY MIT +@set KDCSERVER kerberos +@set KDCSLAVE1 @value{KDCSERVER}-1 +@set KDCSLAVE2 @value{KDCSERVER}-2 +@set PRIMARYDOMAIN mit.edu +@set PRIMARYREALM ATHENA.MIT.EDU +@set PRODUCT Kerberos V5 +@set CPRODUCT Kerberos +@set LCPRODUCT krb5 +@set RANDOMHOST1 daffodil +@set RANDOMHOST1IP 10.0.0.6 +@set RANDOMHOST2 trillium +@set RANDOMHOST2IP 10.1.2.3 +@set RANDOMUSER johndoe +@set RANDOMUSER1 jennifer +@set RANDOMUSER2 david +@set RELEASE 1.6 +@set PREVRELEASE 1.5 +@set INSTALLDIR /usr/@value{LCPRODUCT} +@set PREVINSTALLDIR @value{INSTALLDIR} +@set ROOTDIR /usr/local +@set BINDIR /usr/local/bin +@set LOCALSTATEDIR @value{ROOTDIR}/var +@set SECONDDOMAIN example.com +@set SECONDREALM EXAMPLE.COM +@set UPDATED @today + +@ignore +The rest of the variables in this file are defaults for tags in the +configuration files. Each group of defaults come from the same file in +the code, which is specified in the ignore comment above the group. +After each variable, there should be a comment specifying the variable +in the code that holds the default variable, or the line in which the +default was set. +@end ignore + +@ignore +the following should be consistent with the variables set in +krb5/src/lib/krb5/krb/init_ctx.c +@end ignore +@set DefaultETypeList aes256-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 des-cbc-crc des-cbc-md5 des-cbc-md4 +@comment DEFAULT_ETYPE_LIST +@set DefaultDefaultTgsEnctypes @value{DefaultETypeList} +@set DefaultDefaultTktEnctypes @value{DefaultETypeList} +@set DefaultPermittedEnctypes @value{DefaultETypeList} +@set DefaultClockskew 300 seconds, or five minutes +@comment libdefaults, clockskew +@set DefaultChecksumType RSA MD5 +@comment libdefaults, kdc_req_checksum_type, ap_req_checksum_type, safe_checksum_type +@set DefaultCcacheType 4 +@comment DEFAULT_CCACHE_TYPE +@set DefaultTktLifetime 1 day +@comment libdefaults, tkt_lifetime +@comment -- actually, that's not implemented; see +@comment lib/krb5/krb/get_in_tkt.c, and clients/kinit/kinit.c for krb4 +@comment fallback +@set DefaultKDCTimesync 1 +@comment DEFAULT_KDC_TIMESYNC +@set DefaultKDCDefaultOptions KDC_OPT_RENEWABLE_OK +@comment line 194 + +@ignore +the following defaults should be consistent with default variables set +in krb5/src/include/stock/osconf.h +@end ignore +@set DefaultMasterKeyType des3-cbc-sha1 +@comment DEFAULT_KDC_ENCTYPE +@set DefaultKadmindPort 749 +@comment DEFAULT_KADM5_PORT +@set DefaultAclFile @value{LOCALSTATEDIR}/krb5kdc/kadm5.acl +@comment DEFAULT_KADM5_ACL_FILE +@set DefaultAdminKeytab @value{LOCALSTATEDIR}/krb5kdc/kadm5.keytab +@comment DEFAULT_KADM5_KEYTAB +@set DefaultDatabaseName @value{LOCALSTATEDIR}/krb5kdc/principal +@comment DEFAULT_KDB_FILE +@set DefaultKdcPorts 88,750 +@comment DEFAULT_KDC_PORTLIST +@set DefaultKpasswdPort 464 +@comment DEFAULT_KPASSWD_PORT +@set DefaultSecondPort 750 +@comment KRB5_DEFAULT_SEC_PORT +@set DefaultPort 88 +@comment KRB5_DEFAULT_PORT +@set DefaultKeyStashFileStub @value{LOCALSTATEDIR}/krb5kdc/.k5. +@comment DEFAULT_KEYFILE_STUB +@set DefaultDefaultKeytabName /etc/krb5.keytab +@comment DEFAULT_KEYTAB_NAME +@set DefaultKpasswdPort 464 +@comment DEFAULT_KPASSWD_PORT +@set DefaultDefaultProfilePath /etc/krb5.conf +@comment DEFAULT_PROFILE_PATH +@set DefaultKDCRCache krb5kdc_rcache +@comment KDCRCACHE +@set DefaultRCTmpDirs /var/tmp, /usr/tmp, /var/usr/tmp, and /tmp + +@ignore +the following defaults should be consistent with the numbers set in +krb5/src/lib/kadm5/alt_prof.c +@end ignore +@set DefaultMaxLife 10 hours +@comment line 608 +@set DefaultMaxRenewableLife 0 +@comment line 622 +@set DefaultDefaultPrincipalExpiration 0 +@comment line 639 +@set DefaultSupportedEnctypes des3-hmac-sha1:normal des-cbc-crc:normal +@comment line 705 + +@ignore +the following defaults should be consistent with the values set in +krb5/src/include/kdb.h +@end ignore +@set DefaultDefaultPrincipalFlags postdateable, forwardable, tgt-based, renewable, proxiable, dup-skey, allow-tickets, and service enabled. +@comment KRB_KDC_DEFAULT_FLAGS set to 0 + +@ignore +the following defaults should be consistent with the values set in +include/kdb.h +@end ignore +@set DefaultMasterKeyName K/M +@comment KRB5_KDB_M_NAME + +@ignore +the following defaults should be consistent with the values set in +krb5/src/appl/bsd/login.c +@end ignore +@set DefaultKrb5GetTickets true +@comment login_krb5_get_tickets +@set DefaultKrb4GetTickets false +@comment login_krb4_get_tickets +@set DefaultKrb4Convert false +@comment login_krb4_convert +@set DefaultKrbRunAklog false +@comment login_krb_run_aklog +@set DefaultAklogPath $(prefix)/bin/aklog +@comment lines 955-956 +@set DefaultAcceptPasswd false +@comment login_accept_password + +@ignore +the following defaults should be consistent with the values set in +krb5/src/kdc/kerberos_v4 +@end ignore +@set DefaultV4Mode none +@comment KDC_V4_DEFAULT_MODE + +@ignore +these defaults are based on code in krb5/src/aclocal.m4 +@end ignore +@set DefaultDNSLookupKDC true +@set DefaultDNSLookupRealm false +@comment lines 1259-1300 + +@ignore +the following are based on variables in krb5/src/include/kerberosIV/krbports.h +@end ignore +@set DefaultKrbPropPort 754 +@comment KRB_PROP_PORT +@set DefaultKloginPort 543 +@comment KLOGIN_PORT +@set DefaultEkloginPort 2105 +@comment EKLOGIN_PORT +@set DefaultKshellPort 544 +@comment KRB_SHELL_PORT + +@ignore +/etc/services +@end ignore +@set DefaultTelnetPort 23 +@set DefaultFTPPort 21 +@set DefaultKrb524Port 4444 + +@comment src/include/kerberosIV/krb.h +@set DefaultKrb4Srvtab /etc/srvtab +@comment line 131 +@set DefaultKrb4Config /etc/krb.conf +@comment KRB_CONF +@set DefaultKrb4Realms /etc/krb.realms +@comment KRB_RLM_TRANS + +@comment krb5/src/lib/krb5/krb/get_in_tkt.c +@set DefaultRenewLifetime 0 +@set DefaultNoaddresses set +@set DefaultForwardable not set +@set DefaultProxiable not set + +@comment lib/krb5/krb/vfy_increds.c +@set DefaultVerifyApReqNofail not set diff --git a/krb5-1-6/doc/dnssrv.texinfo b/krb5-1-6/doc/dnssrv.texinfo new file mode 100644 index 000000000..c969fb269 --- /dev/null +++ b/krb5-1-6/doc/dnssrv.texinfo @@ -0,0 +1,97 @@ +@value{COMPANY} recommends that your KDCs have a predefined set of +CNAME records (DNS hostname aliases), such as @code{@value{KDCSERVER}} +for the master KDC and +@code{@value{KDCSLAVE1}}, @code{@value{KDCSLAVE2}}, @dots{} for the +slave KDCs. This way, if you need to swap a machine, you only need to +change a DNS entry, rather than having to change hostnames. + +A new mechanism for locating KDCs of a realm through DNS has been added +to the @value{COMPANY} @value{PRODUCT} distribution. A relatively new +record type called @code{SRV} has been added to DNS. Looked up by a +service name and a domain name, these records indicate the hostname and +port number to contact for that service, optionally with weighting and +prioritization. (See RFC 2782 if you want more information. You can +follow the example below for straightforward cases.) + +The use with Kerberos is fairly straightforward. The domain name used +in the SRV record name is the domain-style Kerberos realm name. (It is +possible to have Kerberos realm names that are not DNS-style names, but +we don't recommend it for Internet use, and our code does not support it +well.) Several different Kerberos-related service names are used: + +@table @code +@item _kerberos._udp +This is for contacting any KDC by UDP. This entry will be used the most +often. Normally you should list port 88 on each of your KDCs. +@c Don't encourage continued use of port 750 for krb5. +@c It should be only for backwards compatibility with krb4. +@c Do the Mac/Windows krb4 libraries use this DNS entry? +@c The UNIX code does not. + +@item _kerberos._tcp +This is for contacting any KDC by TCP. The MIT KDC by default will not +listen on any TCP ports, so unless you've changed the configuration or +you're running another KDC implementation, you should leave this +unspecified. If you do enable TCP support, normally you should use +port 88. + +@item _kerberos-master._udp +This entry should refer to those KDCs, if any, that will immediately see +password changes to the Kerberos database. This entry is used only in +one case, when the user is logging in and the password appears to be +incorrect; the master KDC is then contacted, and the same password used +to try to decrypt the response, in case the user's password had recently +been changed and the first KDC contacted hadn't been updated. Only if +that fails is an ``incorrect password'' error given. + +If you have only one KDC, or for whatever reason there is no accessible +KDC that would get database changes faster than the others, you do not +need to define this entry. + +@item _kerberos-adm._tcp +This should list port @value{DefaultKadmindPort} on your master KDC. +Support for it is not complete at this time, but it will eventually be +used by the @code{kadmin} program and related utilities. For now, you +will also need the @code{admin_server} entry in @code{krb5.conf}. +(@xref{krb5.conf}.) + +@item _kpasswd._udp +This should list port @value{DefaultKpasswdPort} on your master KDC. +It is used when a user changes her password. + +@item _kerberos-iv._udp +This should refer to your KDCs that serve Kerberos version 4 requests, +if you have Kerberos v4 enabled. + +@end table + +Be aware, however, that the DNS SRV specification requires that the +hostnames listed be the canonical names, not aliases. So, for example, +you might include the following records in your (BIND-style) zone file: + +@smallexample +$ORIGIN foobar.com. +_kerberos TXT "FOOBAR.COM" +kerberos CNAME daisy +kerberos-1 CNAME use-the-force-luke +kerberos-2 CNAME bunny-rabbit +_kerberos._udp SRV 0 0 88 daisy + SRV 0 0 88 use-the-force-luke + SRV 0 0 88 bunny-rabbit +_kerberos-master._udp SRV 0 0 88 daisy +_kerberos-adm._tcp SRV 0 0 749 daisy +_kpasswd._udp SRV 0 0 464 daisy +@end smallexample + +As with the DNS-based mechanism for determining the Kerberos realm of a +host, we recommend distributing the information this way for use by +other sites that may want to interact with yours using Kerberos, even if +you don't immediately make use of it within your own site. If you +anticipate installing a very large number of machines on which it will +be hard to update the Kerberos configuration files, you may wish to do +all of your Kerberos service lookups via DNS and not put the information +(except for @code{admin_server} as noted above) in future versions of +your @code{krb5.conf} files at all. Eventually, we hope to phase out +the listing of server hostnames in the client-side configuration files; +making preparations now will make the transition easier in the future. + diff --git a/krb5-1-6/doc/dnstxt.texinfo b/krb5-1-6/doc/dnstxt.texinfo new file mode 100644 index 000000000..e06d220cf --- /dev/null +++ b/krb5-1-6/doc/dnstxt.texinfo @@ -0,0 +1,38 @@ +Mapping hostnames onto Kerberos realms is done in one of two ways. + +The first mechanism, which has been in use for years in MIT-based +Kerberos distributions, works through a set of rules in +the @code{krb5.conf} configuration file. (@xref{krb5.conf}.) You can +specify mappings for an entire domain or subdomain, and/or on a +hostname-by-hostname basis. Since greater specificity takes precedence, +you would do this by specifying the mappings for a given domain or +subdomain and listing the exceptions. + +The second mechanism works by looking up the information in special +@code{TXT} records in the Domain Name Service. This is currently not +used by default because security holes could result if the DNS TXT +records were spoofed. If this mechanism is enabled on the client, +it will try to look up a @code{TXT} record for the DNS name formed by +putting the prefix @code{_kerberos} in front of the hostname in question. +If that record is not found, it will try using @code{_kerberos} and the +host's domain name, then its parent domain, and so forth. So for the +hostname BOSTON.ENGINEERING.FOOBAR.COM, the names looked up would be: + +@smallexample +_kerberos.boston.engineering.foobar.com +_kerberos.engineering.foobar.com +_kerberos.foobar.com +_kerberos.com +@end smallexample + +The value of the first TXT record found is taken as the realm name. +(Obviously, this doesn't work all that well if a host and a subdomain +have the same name, and different realms. For example, if all the hosts +in the ENGINEERING.FOOBAR.COM domain are in the ENGINEERING.FOOBAR.COM +realm, but a host named ENGINEERING.FOOBAR.COM is for some reason in +another realm. In that case, you would set up TXT records for all +hosts, rather than relying on the fallback to the domain name.) + +Even if you do not choose to use this mechanism within your site, you +may wish to set it up anyway, for use when interacting with other sites. + diff --git a/krb5-1-6/doc/document-list.texinfo b/krb5-1-6/doc/document-list.texinfo new file mode 100644 index 000000000..65058b96d --- /dev/null +++ b/krb5-1-6/doc/document-list.texinfo @@ -0,0 +1,24 @@ +This document is one piece of the document set for @value{PRODUCT}. The +documents, and their intended audiences, are: + +@itemize @bullet +@item +@b{@value{PRODUCT} Installation Guide}: a concise guide for installing +@value{PRODUCT}. Kerberos administrators (particularly whoever will be +making site-wide decisions about the installation) and the system +administrators who will be installing the software should read this +guide. + +@item +@b{@value{PRODUCT} System Administrator's Guide}: a sysadmin's guide to +administering a Kerberos installation. The System Administrator's Guide +describes the administration software and suggests policies and +procedures for administering a Kerberos installation. Anyone who will +have administrative access to your Kerberos database should read this +guide. + +@item +@b{@value{PRODUCT} UNIX User's Guide}: a guide to using the Kerberos +UNIX client programs. All users on UNIX systems should read this guide, +particularly the ``Tutorial'' section. +@end itemize diff --git a/krb5-1-6/doc/glossary.texinfo b/krb5-1-6/doc/glossary.texinfo new file mode 100644 index 000000000..d49a56a7f --- /dev/null +++ b/krb5-1-6/doc/glossary.texinfo @@ -0,0 +1,64 @@ +@table @b +@item client +an entity that can obtain a ticket. This entity is usually either a +user or a host. + +@item host +a computer that can be accessed over a network. + +@item Kerberos +in Greek mythology, the three-headed dog that guards the entrance to the +underworld. In the computing world, Kerberos is a network security +package that was developed at MIT. + +@item KDC +Key Distribution Center. A machine that issues Kerberos tickets. + +@item keytab +a @b{key tab}le file containing one or more keys. A host or service +uses a @dfn{keytab} file in much the same way as a user uses his/her +password. + +@item principal +a string that names a specific entity to which a set of credentials may +be assigned. It can have an arbitrary number of components, but +generally has three: + +@table @b +@item primary +the first part of a Kerberos @i{principal}. In the case of a user, it +is the username. In the case of a service, it is the name of the +service. + +@item instance +the second part of a Kerberos @i{principal}. It gives information that +qualifies the primary. The instance may be null. In the case of a +user, the instance is often used to describe the intended use of the +corresponding credentials. In the case of a host, the instance is the +fully qualified hostname. + +@item realm +the logical network served by a single Kerberos database and a set of +Key Distribution Centers. By convention, realm names are generally all +uppercase letters, to differentiate the realm from the internet domain. +@end table + +@noindent +The typical format of a typical Kerberos principal is +primary/instance@@REALM. + +@item service +any program or computer you access over a network. Examples of services +include ``host'' (a host, @i{e.g.}, when you use @code{telnet} and +@code{rsh}), ``ftp'' (FTP), ``krbtgt'' (authentication; +cf. @i{ticket-granting ticket}), and ``pop'' (email). + +@item ticket +a temporary set of electronic credentials that verify the identity of a +client for a particular service. + +@item TGT +Ticket-Granting Ticket. A special Kerberos ticket that permits the +client to obtain additional Kerberos tickets within the same Kerberos +realm. +@end table diff --git a/krb5-1-6/doc/implement/.cvsignore b/krb5-1-6/doc/implement/.cvsignore new file mode 100644 index 000000000..67a81b831 --- /dev/null +++ b/krb5-1-6/doc/implement/.cvsignore @@ -0,0 +1,7 @@ +implement.ind +implement.log +implement.idx +implement.aux +implement.toc +implement.dvi +implement.ps diff --git a/krb5-1-6/doc/implement/Makefile b/krb5-1-6/doc/implement/Makefile new file mode 100644 index 000000000..4c5116132 --- /dev/null +++ b/krb5-1-6/doc/implement/Makefile @@ -0,0 +1,38 @@ +.SUFFIXES: .tex .dvi .ps + +STYLES= fixunder.sty functions.sty +LIBTEX= implement.tex ccache-i.tex rcache-i.tex keytab-i.tex libos-i.tex \ + kdb-i.tex encrypt-i.tex cksum-i.tex crc-32-i.tex implement.ind + + +all: implement.ps + + +implement.ps: implement.dvi + +# hard to capture two-pass semantics in Makefiles... +# implement.ind: implement.dvi +implement.ind: implement.idx + makeindex implement.idx + +implement.idx: + touch implement.ind + latex implement.tex + rm implement.ind + +clean: + rm -f *.toc *.log *.idx *.ind *.aux *.ilg + +really-clean: clean + rm -f *.dvi *.ps + + +implement.dvi: $(LIBTEX) $(STYLES) + +.tex.dvi: + latex $* + + +.dvi.ps: + dvips $*.dvi -o + diff --git a/krb5-1-6/doc/implement/ccache-i.tex b/krb5-1-6/doc/implement/ccache-i.tex new file mode 100644 index 000000000..66d7b61bf --- /dev/null +++ b/krb5-1-6/doc/implement/ccache-i.tex @@ -0,0 +1,224 @@ +The credentials cache functions (some of which are macros which call to +specific types of credentials caches) deal with storing credentials +(tickets, session keys, and other identifying information) in a +semi-permanent store for later use by different programs. + +\subsubsection{The krb5_cc_ops structure} +In order to implement a new credentials cache type, the programmer should +declare a {\bf krb5_cc_ops} structure, and fill in the elements of the +structure appropriately, by implementing each of the credential cache +functions for the new credentials cache type. + +The prefix element specifies the prefix name of the the new credential +cache type. For example, if the prefix name is ``FILE'', then if the +program calls \funcname{krb5_cc_resolve} with a credential cache name +such as ``FILE:/tmp/krb5_cc_15806'', then \funcname{krb5_cc_resolve} +will call the resolve function (as defined by the {\bf krb5_cc_ops} +structure where the prefix element is ``FILE'') and pass it the +argument ``/tmp/krb5_cc_15806''. + +Before a new credentials cache type can be recognized by +\funcname{krb5_cc_resolve}, it must be registered with the Kerberos +library by calling \funcname{krb5_cc_register}. + +\begin{verbatim} +typedef struct _krb5_cc_ops { + char *prefix; + char *(*get_name)((krb5_ccache)); + krb5_error_code (*resolve)((krb5_ccache *, char *)); + krb5_error_code (*gen_new)((krb5_ccache *)); + krb5_error_code (*init)((krb5_ccache, krb5_principal)); + krb5_error_code (*destroy)((krb5_ccache)); + krb5_error_code (*close)((krb5_ccache)); + krb5_error_code (*store)((krb5_ccache, krb5_creds *)); + krb5_error_code (*retrieve)((krb5_ccache, krb5_flags, + krb5_creds *, krb5_creds *)); + krb5_error_code (*get_princ)((krb5_ccache, + krb5_principal *)); + krb5_error_code (*get_first)((krb5_ccache, + krb5_cc_cursor *)); + krb5_error_code (*get_next)((krb5_ccache, krb5_cc_cursor *, + krb5_creds *)); + krb5_error_code (*end_get)((krb5_ccache, krb5_cc_cursor *)); + krb5_error_code (*remove_cred)((krb5_ccache, krb5_flags, + krb5_creds *)); + krb5_error_code (*set_flags)((krb5_ccache, krb5_flags)); +} krb5_cc_ops; +\end{verbatim} + + +\subsubsection{Per-type functions} +The following entry points must be implemented for each type of +credentials cache. However, \funcname{resolve} and +\funcname{gen_new} are only called by the credentials cache glue code. +They are not called directly by the application. + + +\begin{funcdecl}{resolve}{krb5_error_code}{\funcout} +\funcarg{krb5_ccache *}{id} +\funcin +\funcarg{char *}{residual} +\end{funcdecl} + +Creates a credentials cache named by \funcparam{residual} (which may be +interpreted differently by each type of ccache). The cache is not +opened, but the cache name is held in reserve. + +\begin{funcdecl}{gen_new}{krb5_error_code}{\funcout} +\funcarg{krb5_ccache *}{id} +\end{funcdecl} + +Creates a new credentials cache whose name is guaranteed to be +unique. The cache is not opened. \funcparam{*id} is +filled in with a \datatype{krb5_ccache} which may be used in subsequent +calls to ccache functions. + +\begin{funcdecl}{init}{krb5_error_code}{\funcinout} +\funcarg{krb5_ccache}{id} +\funcin +\funcarg{krb5_principal}{primary_principal} +\end{funcdecl} + +Creates/refreshes a credentials cache identified by \funcparam{id} with +primary principal set to \funcparam{primary_principal}. +If the credentials cache already exists, its contents are destroyed. + +%Errors: permission errors, system errors. + +Modifies: cache identified by \funcparam{id}. + +\begin{funcdecl}{destroy}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\end{funcdecl} + +Destroys the credentials cache identified by \funcparam{id}, invalidates +\funcparam{id}, and releases any other resources acquired during use of +the credentials cache. Requires that \funcparam{id} identifies a valid +credentials cache. After return, \funcparam{id} must not be used unless +it is first reinitialized. + +%Errors: permission errors. + +\begin{funcdecl}{close}{krb5_error_code}{\funcinout} +\funcarg{krb5_ccache}{id} +\end{funcdecl} + +Closes the credentials cache \funcparam{id}, invalidates +\funcparam{id}, and releases \funcparam{id} and any other resources +acquired during use of the credentials cache. Requires that +\funcparam{id} identifies a valid credentials cache. After return, +\funcparam{id} must not be used unless it is first reinitialized. + + +\begin{funcdecl}{store}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcarg{krb5_creds *}{creds} +\end{funcdecl} + +Stores \funcparam{creds} in the cache \funcparam{id}, tagged with +\funcparam{creds{\ptsto}client}. +Requires that \funcparam{id} identifies a valid credentials cache. + +%Errors: permission errors, storage failure errors. + +\begin{funcdecl}{retrieve}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcarg{krb5_flags}{whichfields} +\funcarg{krb5_creds *}{mcreds} +\funcout +\funcarg{krb5_creds *}{creds} +\end{funcdecl} + +Searches the cache \funcparam{id} for credentials matching +\funcparam{mcreds}. The fields which are to be matched are specified by +set bits in \funcparam{whichfields}, and always include the principal +name \funcparam{mcreds{\ptsto}server}. +Requires that \funcparam{id} identifies a valid credentials cache. + +If at least one match is found, one of the matching credentials is +returned in \funcparam{*creds}. The credentials should be freed using +\funcname{krb5_free_credentials}. + +%Errors: error code if no matches found. + +\begin{funcdecl}{get_princ}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcarg{krb5_principal *}{principal} +\end{funcdecl} + +Retrieves the primary principal of the credentials cache (as +set by the \funcname{init} request) +The primary principal is filled into \funcparam{*principal}; the caller +should release this memory by calling \funcname{krb5_free_principal} on +\funcparam{*principal} when finished. + +Requires that \funcparam{id} identifies a valid credentials cache. + +\begin{funcdecl}{get_first}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcout +\funcarg{krb5_cc_cursor *}{cursor} +\end{funcdecl} + +Prepares to sequentially read every set of cached credentials. +Requires that \funcparam{id} identifies a valid credentials cache opened by +\funcname{krb5_cc_open}. +\funcparam{cursor} is filled in with a cursor to be used in calls to +\funcname{get_next}. + +\begin{funcdecl}{get_next}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcout +\funcarg{krb5_creds *}{creds} +\funcinout +\funcarg{krb5_cc_cursor *}{cursor} +\end{funcdecl} + +Fetches the next entry from \funcparam{id}, returning its values in +\funcparam{*creds}, and updates \funcparam{*cursor} for the next request. +Requires that \funcparam{id} identifies a valid credentials cache and +\funcparam{*cursor} be a cursor returned by +\funcname{get_first} or a subsequent call to +\funcname{get_next}. + +%Errors: error code if no more cache entries. + +\begin{funcdecl}{end_get}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcarg{krb5_cc_cursor *}{cursor} +\end{funcdecl} + +Finishes sequential processing mode and invalidates \funcparam{*cursor}. +\funcparam{*cursor} must never be re-used after this call. + +Requires that \funcparam{id} identifies a valid credentials cache and +\funcparam{*cursor} be a cursor returned by +\funcname{get_first} or a subsequent call to +\funcname{get_next}. + +%Errors: may return error code if \funcparam{*cursor} is invalid. + + +\begin{funcdecl}{remove_cred}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcarg{krb5_flags}{which} +\funcarg{krb5_creds *}{cred} +\end{funcdecl} + +Removes any credentials from \funcparam{id} which match the principal +name {cred{\ptsto}server} and the fields in \funcparam{cred} masked by +\funcparam{which}. +Requires that \funcparam{id} identifies a valid credentials cache. + +%Errors: returns error code if nothing matches; returns error code if +%couldn't delete. + +\begin{funcdecl}{set_flags}{krb5_error_code}{\funcin} +\funcarg{krb5_ccache}{id} +\funcarg{krb5_flags}{flags} +\end{funcdecl} + +Sets the flags on the cache \funcparam{id} to \funcparam{flags}. Useful +flags are defined in {\tt }. + + diff --git a/krb5-1-6/doc/implement/cksum-i.tex b/krb5-1-6/doc/implement/cksum-i.tex new file mode 100644 index 000000000..c7f763738 --- /dev/null +++ b/krb5-1-6/doc/implement/cksum-i.tex @@ -0,0 +1,31 @@ +Kerberos v5 has the ability to use multiple checksum algorithms. Any +checksum implementation which desires to link with and be usable from the MIT +Kerberos v5 implementation must implement this interface: + +\subsection{Functional interface} + +\begin{funcdecl}{sum_func}{krb5_error_code}{\funcin} +\funcarg{krb5_pointer}{in} +\funcarg{size_t}{in_length} +\funcarg{krb5_pointer}{seed} +\funcarg{size_t}{seed_length} +\funcout +\funcarg{krb5_checksum *}{outcksum} +\end{funcdecl} + +This routine computes the desired checksum over \funcparam{in_length} bytes +at \funcparam{in}. \funcparam{seed_length} bytes of a seed (usually an +encryption key) are pointed to by \funcparam{seed}. Some checksum +algorithms may choose to ignore \funcparam{seed}. If +\funcparam{seed_length} is zero, then there is no seed available. +The routine places the resulting value into \funcparam{outcksum{\ptsto}contents}. + +\funcparam{outcksum{\ptsto}contents} must be set by the caller to point +to enough storage to contain the checksum; the size necessary is an +element of the \datatype{krb5_checksum_entry} structure. + +\subsection{Other data elements} +In addition to the above listed function entry point, each checksum algorithm +should have an entry in \globalname{krb5_cksumarray} and a +\datatype{krb5_checksum_entry} structure describing the entry points +and checksum size for the algorithm. diff --git a/krb5-1-6/doc/implement/crc-32-i.tex b/krb5-1-6/doc/implement/crc-32-i.tex new file mode 100644 index 000000000..c5d07a33d --- /dev/null +++ b/krb5-1-6/doc/implement/crc-32-i.tex @@ -0,0 +1,20 @@ +The \libname{libcrc32.a} library provides an implementation of the +CRC-32 checksum algorithm which conforms to the interface required by +the Kerberos library. + +\begin{funcdecl}{crc32_sum_func}{static krb5_error_code}{\funcin} +\funcarg{krb5_pointer}{in} +\funcarg{size_t}{in_length} +\funcarg{krb5_pointer}{seed} +\funcarg{size_t}{seed_length} +\funcout +\funcarg{krb5_checksum *}{outcksum} +\end{funcdecl} + +This routine computes a CRC-32 checksum over \funcparam{in_length} bytes +at \funcparam{in}, and places the resulting value into +\funcparam{outcksum{\ptsto}contents}. \funcparam{seed} is ignored. + +\funcparam{outcksum{\ptsto}contents} must be set by the caller to point +to at least 4 bytes of storage. + diff --git a/krb5-1-6/doc/implement/encrypt-i.tex b/krb5-1-6/doc/implement/encrypt-i.tex new file mode 100644 index 000000000..57e8c833a --- /dev/null +++ b/krb5-1-6/doc/implement/encrypt-i.tex @@ -0,0 +1,164 @@ +Kerberos v5 has the ability to use multiple encryption systems. Any +encryption system which desires to link with and be usable from the MIT +Kerberos v5 implementation must implement at least this interface: + +\subsection{Functional interface} + +\begin{funcdecl}{encrypt_func}{krb5_error_code}{\funcvoid} +\funcarg{krb5_const_pointer}{in} +\funcarg{krb5_pointer}{out} +\funcarg{const size_t}{size} +\funcarg{krb5_encrypt_block *}{eblock} +\funcarg{krb5_pointer}{ivec} +\end{funcdecl} +Encrypts \funcparam{size} bytes at \funcparam{in}, storing result in +\funcparam{out}. \funcparam{eblock} points to an encrypt block which +has been initialized by \funcname{process_key}. + +\funcparam{in} must include sufficient space beyond the \funcparam{size} +bytes of input data to hold pad and redundancy check bytes; the macro +\funcname{krb5_encrypt_size} can be used to compute this size. + +\funcparam{out} must be preallocated by the caller to contain sufficient +storage to hold the output; the macro \funcname{krb5_encrypt_size} can +be used to compute this size. + +\funcparam{ivec} points to an initial vector/seed to be used in the encryption. +If null, the cryptosystem may choose an appropriate initialization vector. + +%Errors: Returns errors. + +\begin{funcdecl}{decrypt_func}{krb5_error_code}{\funcvoid} +\funcarg{krb5_const_pointer}{in} +\funcarg{krb5_pointer}{out} +\funcarg{const size_t}{size} +\funcarg{krb5_encrypt_block *}{eblock} +\funcarg{krb5_pointer}{ivec} +\end{funcdecl} +Decrypts \funcparam{size} bytes at \funcparam{in}, storing result in +\funcparam{out}. +\funcparam{eblock} points to an encrypt block which has been initialized +by \funcname{process_key}. + +\funcparam{size} must be a multiple of the encryption block size. + +\funcparam{out} must be preallocated by the caller to contain sufficient +storage to hold the output; this is guaranteed to be no more than +the input size. + +\funcparam{ivec} points to an initial vector/seed to be used in the decryption. +If null, the cryptosystem may choose an appropriate ivec. + +%Errors: Returns errors. + +\begin{funcdecl}{process_key}{krb5_error_code}{\funcvoid} +\funcarg{krb5_encrypt_block *}{eblock} +\funcarg{const krb5_keyblock *}{keyblock} +\end{funcdecl} +Does any necessary key preprocessing (such as computing key +schedules for DES). +\funcparam{eblock{\ptsto}crypto_entry} must be set by the caller; the +other elements of \funcparam{eblock} are to be assigned by this function. +[In particular, \funcparam{eblock{\ptsto}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 \funcparam{keyblock} before calling +\funcname{finish_key} on \funcparam{eblock}. + +%Errors: Returns errors. + +\begin{funcdecl}{finish_key}{krb5_error_code}{\funcvoid} +\funcarg{krb5_encrypt_block *}{eblock} +\end{funcdecl} +Does any necessary clean-up on \funcparam{eblock} (such as releasing +resources held by \funcparam{eblock{\ptsto}priv}. + +%Errors: Returns errors. + +\begin{funcdecl}{string_to_key}{krb5_error_code}{\funcvoid} +\funcarg{const krb5_keytype}{keytype} +\funcarg{krb5_keyblock *}{keyblock} +\funcarg{const krb5_data *}{data} +\funcarg{const krb5_data}{salt} +\end{funcdecl} +Converts the string pointed to by \funcparam{data} into an encryption key +of type \funcparam{keytype}. \funcparam{*keyblock} is filled in with +the key info; in particular, \funcparam{keyblock{\ptsto}contents} is to +be set to allocated storage. It is the responsibility of the caller to +release this storage when the generated key no longer needed. + +The routine may use \funcparam{salt} to seed or alter the conversion +algorithm. + +If the particular function called does not know how to make a +key of type \funcparam{keytype}, an error may be returned. + +%Errors: Returns errors. + +\begin{funcdecl}{init_random_key}{krb5_error_code}{\funcvoid} +\funcarg{const krb5_keyblock *}{seedblock} +\funcarg{krb5_pointer *}{seed} +\end{funcdecl} + +Initialize the random key generator using the encryption key +\funcparam{seedblock} and allocating private sequence information, filling +in \funcparam{*seed} with the address of such information. +\funcparam{*seed} is to be passed to \funcname{random_key} to provide +sequence information. + +\begin{funcdecl}{finish_random_key}{krb5_error_code}{\funcvoid} +\funcarg{krb5_pointer *}{seed} +\end{funcdecl} + +Free any resources held by \funcparam{seed} and assigned by +\funcname{init_random_key}. + +\begin{funcdecl}{random_key}{krb5_error_code}{\funcvoid} +\funcarg{krb5_pointer *}{seed} +\funcarg{krb5_keyblock **}{keyblock} +\end{funcdecl} + +Generate a random encryption key, allocating storage for it and +filling in the keyblock address in \funcparam{*keyblock}. +When the caller has finished using the keyblock, he should call +\funcname{krb5_free_keyblock} to release its storage. + +%\begin{funcdecl}{combine_keys}{krb5_error_code}{\funcin} +%\funcarg{const krb5_keyblock *}{key1} +%\funcarg{const krb5_keyblock *}{key2} +%\funcout +%\funcarg{krb5_keyblock **}{outkey} +%\end{funcdecl} +%Combine the two encryption keys \funcparam{key1} and \funcparam{key2} to +%generate a new output key \funcparam{outkey}. \funcparam{outkey} is +%filled in to point to the freshly-allocated key. When the caller is +%finished using the \funcparam{*outkey}, it should be freed with +%\funcname{krb5_free_keyblock}. + +\subsection{Other data elements} +In addition to the above listed function entry points, each encryption +system should have an entry in \globalname{krb5_csarray} and a +\datatype{krb5_cryptosystem_entry} structure describing the entry points +and key and padding sizes for the encryption system. + +\subsection{DES functions} +The DES functions conform to the encryption interface required by the +Kerberos version 5 library, and provide an encryption mechanism based on +the DES Cipher-block chaining mode (CBC), with the addition of a +cyclical redundancy check (CRC-32) for integrity checking upon +decryption. + +The functions have the same signatures as those described by the main +library document; the names are: +{\obeylines +\funcname{mit_des_encrypt_func} +\funcname{mit_des_decrypt_func} +\funcname{mit_des_process_key} +\funcname{mit_des_finish_key} +\funcname{mit_des_string_to_key} +\funcname{mit_des_init_random_key} +\funcname{mit_des_finish_random_key} +\funcname{mit_des_random_key} +} +The \datatype{krb5_cryptosystem_entry} for this cryptosystem is +\globalname{mit_des_cryptosystem_entry}. diff --git a/krb5-1-6/doc/implement/fancyheadings.sty b/krb5-1-6/doc/implement/fancyheadings.sty new file mode 100644 index 000000000..a71de0fb5 --- /dev/null +++ b/krb5-1-6/doc/implement/fancyheadings.sty @@ -0,0 +1,233 @@ +% fancyheadings.sty version 1.0 +% Fancy headers and footers. +% Piet van Oostrum, Dept of Computer Science, University of Utrecht +% Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands +% Telephone: +31-30-531806. piet@cs.ruu.nl (mcvax!hp4nl!ruuinf!piet) +% March, 1989. + +% Here is a documentstylestyle option that allows you to customize your +% page headers and footers in an easy way. It combines features that were +% separately available in other pagestyles, without introducing much +% complexity. You can define: +% - three-part headers and footers +% - rules in header and footer +% - headers and footers wider than \textwidth +% - multiline headers and footers +% - separate headers and footers for even and odd pages +% - separate headers and footers for chapter pages +% +% To use this pagestyle, you must include the ``fancyheadings'' style +% option in your \documentstyle, and issue the \pagestyle{fancy} command. +% The \pagestyle{fancy} command should be issued after any changes made to +% \textwidth. +% +% The page layout will be as follows: +% +% LHEAD CHEAD RHEAD +% ----------------------------------- (rule) +% +% page body +% +% +% ----------------------------------- (rule) +% LFOOT CFOOT RFOOT +% +% The L-fields will be leftadjusted, the C-fields centered and the +% R-fields rightadjusted. +% Each of the six fields and the two rules can be defined separately. +% +% Simple use: +% +% The header and footer fields can be defined by commands \lhead{LHEAD} +% and so on for the other fields. If the field depends on something in the +% document (e.g. section titles) you must in general use the \markboth and +% \markright commands, otherwise a title may end on the wrong page. You +% can do this e.g. by redefining the commands \chaptermark, \sectionmark +% and so on (see example below). The defaults for these marks are as in +% the standard pagestyles. The marks can be put into a header or footer +% field by referencing \leftmark and \rightmark. +% +% Rules in header and footer +% +% The thickness of the rules below the header and above the footer can be +% changed by redefining the length parameters \headrulewidth (default +% 0.4pt) and \footrulewidth (default 0). These may be redefined by the +% \setlength command. A thickness of 0pt makes the rule invisible. +% If you want to make more complicated changes, you have to redefine the +% commands \headrule and/or \footrule. +% +% Headers and footers wider than \textwidth +% +% The headers and footers are set in a box of width \headwidth. The +% default for this is the value of \textwidth. You can make it wider (or +% smaller) by redefining \headwidth with the \setlength or \addtolength +% command. The headers and footers will stick out the page on the same +% side as the marginal notes. For example to include the marginal notes, +% add both \marginparsep and \marginparwidth to \headwidth (see also the +% example below). +% +% Multiline headers and footers +% +% Each of the six fields is set in an appropriate parbox, so you can put a +% multiline part in it with the \\ command. It is also possible to put +% extra space in it with the \vspace command. Note that if you do this you +% will probably have to increase the \headheight or \footskip lengths. +% +% Separate headers and footers for even and odd pages +% +% If you want the headers and footers to be different on even- and +% odd-numbered pages in the ``twoside'' style, the field-defining macros +% can be given an optional argument, to be used on the even-numbered +% pages, like \lhead[EVEN-LHEAD]{ODD-RHEAD}. +% +% Separate headers and footers for chapter pages +% +% LaTeX gives a \thispagestyle{plain} command for the first page of the +% document, the first page of each chapter and a couple of other pages. It +% might be incompatible with your pagestyle. In this case you can use a +% slightly different version of the pagestyle, called \pagestyle{fancyplain}. +% This pagestyle redefines the pagestyle ``plain'' to also use pagestyle +% ``fancy'' with the following modifications: +% - the thicknesses of the rules is defined by \plainheadrulewidth and +% \plainfootrulewidth (both default 0). +% - the 6 fields may be defined separately for the plain pages by +% giving them the value \fancyplain{PLAIN-VALUE}{NORMAL-VALUE}. This +% construct may be used in both the optional argument and the normal +% argument. Thus \lhead[\fancyplain{F1}{F2}]{\fancyplain{F3}{F4}} +% specifies the LHEAD value in a two-sided document: +% F1 on an even-numbered ``plain'' page +% F2 on an even-numbered normal page +% F3 on an odd-numbered ``plain'' page +% F4 on an odd-numbered normal page. +% +% Defaults: +% +% \headrulewidth 0.4pt +% \footrulewidth 0pt +% \plainheadrulewidth 0pt +% \plainfootrulewidth 0pt +% +% \lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}} +% % i.e. empty on ``plain'' pages \rightmark on even, \leftmark on odd pages +% \chead{} +% \rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}} +% % i.e. empty on ``plain'' pages \leftmark on even, \rightmark on odd pages +% \lfoot{} +% \cfoot{\rm\thepage} % page number +% \rfoot{} +% +% Examples: +% +% To put two lines containing the section title and the subsection title +% in the righthandside corner, use: +% +% \documentstyle[fancyheadings]{article} +% \pagestyle{fancy} +% \renewcommand{\sectionmark}[1]{\markboth{#1}{}} +% \renewcommand{\subsectionmark}[1]{\markright{#1}} +% \rfoot{\leftmark\\\rightmark} +% +% The following definitions give an approximation of the style used in the +% LaTeX book: +% +% \documentstyle[fancyheadings]{book} +% \pagestyle{fancyplain} +% \addtolength{\headwidth}{\marginparsep} +% \addtolength{\headwidth}{\marginparwidth} +% \renewcommand{\chaptermark}[1]{\markboth{#1}{#1}} % remember chapter title +% \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} +% % section number and title +% \lhead[\fancyplain{}{\bf\thepage}]{\fancyplain{}{\bf\rightmark}} +% \rhead[\fancyplain{}{\bf\leftmark}]{\fancyplain{}{\bf\thepage}} +% \cfoot{} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}} +\def\@xlhead[#1]#2{\gdef\@elhead{#1}\gdef\@olhead{#2}} +\def\@ylhead#1{\gdef\@elhead{#1}\gdef\@olhead{#1}} + +\def\chead{\@ifnextchar[{\@xchead}{\@ychead}} +\def\@xchead[#1]#2{\gdef\@echead{#1}\gdef\@ochead{#2}} +\def\@ychead#1{\gdef\@echead{#1}\gdef\@ochead{#1}} + +\def\rhead{\@ifnextchar[{\@xrhead}{\@yrhead}} +\def\@xrhead[#1]#2{\gdef\@erhead{#1}\gdef\@orhead{#2}} +\def\@yrhead#1{\gdef\@erhead{#1}\gdef\@orhead{#1}} + +\def\lfoot{\@ifnextchar[{\@xlfoot}{\@ylfoot}} +\def\@xlfoot[#1]#2{\gdef\@elfoot{#1}\gdef\@olfoot{#2}} +\def\@ylfoot#1{\gdef\@elfoot{#1}\gdef\@olfoot{#1}} + +\def\cfoot{\@ifnextchar[{\@xcfoot}{\@ycfoot}} +\def\@xcfoot[#1]#2{\gdef\@ecfoot{#1}\gdef\@ocfoot{#2}} +\def\@ycfoot#1{\gdef\@ecfoot{#1}\gdef\@ocfoot{#1}} + +\def\rfoot{\@ifnextchar[{\@xrfoot}{\@yrfoot}} +\def\@xrfoot[#1]#2{\gdef\@erfoot{#1}\gdef\@orfoot{#2}} +\def\@yrfoot#1{\gdef\@erfoot{#1}\gdef\@orfoot{#1}} + +\newdimen\headrulewidth +\newdimen\footrulewidth +\newdimen\plainheadrulewidth +\newdimen\plainfootrulewidth +\newdimen\headwidth +\newif\if@fancyplain \@fancyplainfalse +\def\fancyplain#1#2{\if@fancyplain#1\else#2\fi} + +% Initialization of the head and foot text. + +\headrulewidth 0.4pt +\footrulewidth\z@ +\plainheadrulewidth\z@ +\plainfootrulewidth\z@ + +\lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}} +% i.e. empty on ``plain'' pages \rightmark on even, \leftmark on odd pages +\chead{} +\rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}} +% i.e. empty on ``plain'' pages \leftmark on even, \rightmark on odd pages +\lfoot{} +\cfoot{\rm\thepage} % page number +\rfoot{} + +% Put together a header or footer given the left, center and +% right text, fillers at left and right and a rule. +% The \lap commands put the text into an hbox of zero size, +% so overlapping text does not generate an errormessage. + +\def\@fancyhead#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\hbox +{\rlap{\parbox[b]{\headwidth}{\raggedright#2\strut}}\hfill +\parbox[b]{\headwidth}{\centering#3\strut}\hfill +\llap{\parbox[b]{\headwidth}{\raggedleft#4\strut}}}\headrule}}#5} + + +\def\@fancyfoot#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\footrule +\hbox{\rlap{\parbox[t]{\headwidth}{\raggedright#2\strut}}\hfill +\parbox[t]{\headwidth}{\centering#3\strut}\hfill +\llap{\parbox[t]{\headwidth}{\raggedleft#4\strut}}}}}#5} + +\def\headrule{{\if@fancyplain\headrulewidth\plainheadrulewidth\fi +\hrule\@height\headrulewidth\@width\headwidth \vskip-\headrulewidth}} + +\def\footrule{{\if@fancyplain\footrulewidth\plainfootrulewidth\fi +\vskip-0.3\normalbaselineskip\vskip-\footrulewidth +\hrule\@width\headwidth\@height\footrulewidth\vskip0.3\normalbaselineskip}} + +\def\ps@fancy{ +\let\@mkboth\markboth +\@ifundefined{chapter}{\def\sectionmark##1{\markboth +{\uppercase{\ifnum \c@secnumdepth>\z@ + \thesection\hskip 1em\relax \fi ##1}}{}} +\def\subsectionmark##1{\markright {\ifnum \c@secnumdepth >\@ne + \thesubsection\hskip 1em\relax \fi ##1}}} +{\def\chaptermark##1{\markboth {\uppercase{\ifnum \c@secnumdepth>\m@ne + \@chapapp\ \thechapter. \ \fi ##1}}{}} +\def\sectionmark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\z@ + \thesection. \ \fi ##1}}}} +\def\@oddhead{\@fancyhead\relax\@olhead\@ochead\@orhead\hss} +\def\@oddfoot{\@fancyfoot\relax\@olfoot\@ocfoot\@orfoot\hss} +\def\@evenhead{\@fancyhead\hss\@elhead\@echead\@erhead\relax} +\def\@evenfoot{\@fancyfoot\hss\@elfoot\@ecfoot\@erfoot\relax} +\headwidth\textwidth} +\def\ps@fancyplain{\ps@fancy \let\ps@plain\ps@plain@fancy} +\def\ps@plain@fancy{\@fancyplaintrue\ps@fancy} diff --git a/krb5-1-6/doc/implement/fixunder.sty b/krb5-1-6/doc/implement/fixunder.sty new file mode 100644 index 000000000..b7ae58dbf --- /dev/null +++ b/krb5-1-6/doc/implement/fixunder.sty @@ -0,0 +1,48 @@ +% fixunder.sty, 31 May 1990, John T. Kohl +% +% The contents of this file are in the public domain. +% +% +% play games with _ to make it active and to provide a reasonable _ +% character (from \tt in most cases), and a discretionary word-break point. + +% +% Some \makeunder... macros for convenience in setting catcodes. +% +\def\makeunderactive{\catcode`\_=\active\relax} +\def\makeunderother{\catcode`\_=12\relax} +\def\makeunderletter{\catcode`\_=11\relax} +\def\makeundernormal{\catcode`\_=8\relax} +\makeunderother +\def\cctwlunder{_} + +% +% The hair here is to allow things like \index to work reasonably with +% the new definition of underscore when the argument to index is part of +% a macro replacement and as such gets tokenized before \index is +% evaluated. +% [in the normal case at top-level, \index{foo_bar} works since \index +% does some hair to make _ into a reasonable character code, and \index +% does NOT use a macro expansion. If you have something like +% \def\foo#1#2{\index{#1} bar #2} +% then \foo{baz_quux}{frobnitz} will result in baz_quux getting +% tokenized BEFORE \foo is expanded, so that the catcode hair in \index +% is to no avail.] +% +% \underrealfalse declares that you want to replace with the \tt _; +% \underrealtrue declares that you want to replace with \char95 (ASCII _). +% +% for things like \index which write things out to files, set +% \underrealfalse before evaluating the \index macro, and what actually +% gets written to the file is an _, rather than something like +% {\leavemode \kern... } (the typical definition of \_). +% +% the above example would then be +% \def\foo#1#2{\underrealfalse\index{#1}\underrealtrue bar #2} +% + +\newif\ifunderreal +\underrealfalse +\makeunderactive +\def_{\ifunderreal\cctwlunder\else\leavevmode {\tt \cctwlunder}\discretionary{}{}{}\fi} +\let\_=_ diff --git a/krb5-1-6/doc/implement/functions.sty b/krb5-1-6/doc/implement/functions.sty new file mode 100644 index 000000000..a3165f811 --- /dev/null +++ b/krb5-1-6/doc/implement/functions.sty @@ -0,0 +1,70 @@ +% +% definitions related to function declarations/displays +% +\ifx\undefined\@psfonts +\def\argfont{\tt} +\else +\font\argfont = pcrb +\hyphenchar\argfont = -1 +\fi +\let\funcfont=\bf +\newcount\argc@ount +%\setlength{\marginparsep}{0.05in} +%\setlength{\marginparwidth}{1.45in} +% +% This function fixes up the function name to be displayed in the +% margin so that the krb5_, if any, is stripped. +% +% Note: this is a hack; what's really happening is that name beginning with +% krb5 will have its first five characters stripped from it. +% This means that 'Krb5abc' will get rewritten to be 'bc'. +% Unfortunately, we can't do better because of the underscore +% hacks that are going on elsewhere. +% +% WARNING: This is ugly; don't look at it too soon after lunch! +% [tytso:19900920.2231EDT] +\newif\if@krbfunc +\def\endkrb{} +\def\fix@parname#1{\expandafter\parse@krb#1\endkrb% +\endkrb\endkrb\endkrb\endkrb}% In case the argument is less +% than five letters, we don't want to +% lose on the argument parsing. +\def\parse@krb#1#2#3#4#5#6\endkrb{\@krbfuncfalse% +\if#1k\if#2r\if#3b\if#45\@krbfunctrue\fi\fi\fi\fi% +\if@krbfunc#6\else#1#2#3#4#5#6\fi} +% +% funcdecl is used as \begin{funcdecl}{funcname}{return type}{firstline} +% +% see fixunder.sty for comments on why the \underrealtrue & \underrealfalse +% stuff is here. +\newenvironment{funcdecl}[3]{\underrealtrue\index{#1}\underrealfalse% +\medbreak +\gdef\funcn@me{#1} +\argc@ount=0\noindent% +%the \mbox{} is to prevent the line/paragraph breaking from eating the +%fill space. +\marginpar[{{\sloppy \hfil\fix@parname{\funcn@me}\hfill\mbox{}}}]% +{{\sloppy \hfill\fix@parname{\funcn@me}\hfil\mbox{}}}% +\vbox\bgroup\begin{minipage}[t]{\textwidth}\begin{tabbing} +#2 \\ +{\bf #1}(\= \+ #3% +}{) +\end{tabbing}\vfil\end{minipage}\egroup\par\nopagebreak +} +\newcommand{\docomm@}{\ifnum\argc@ount >0, \\\fi} +\newcommand{\funcvoid}{\argc@ount=0} +\newcommand{\funcin}{\docomm@\argc@ount=0{\sl /* IN */}\\} +\newcommand{\funcinout}{\docomm@\argc@ount=0{\sl /* IN/OUT */}\\} +\newcommand{\funcout}{\docomm@\argc@ount=0{\sl /* OUT */}\\} +\newcommand{\funcarg}[2]{\docomm@#1 {\argfont #2}\advance\argc@ount by1} +\newcommand{\funcparam}[1]{{\argfont #1}} +\newcommand{\funcfuncarg}[2]{\docomm@#1 {\argfont #2}(\= \+ \argc@ount=0} +\newcommand{\funcendfuncarg}{), \- \\ \argc@ount=0} +\newcommand{\libname}[1]{{\argfont #1}} +\newcommand{\globalname}[1]{{\argfont #1}} +\newcommand{\ptsto}{->\discretionary{}{}{}} +\newcommand{\datatype}[1]{{\bf #1}} +\newcommand{\filename}[1]{{\sl #1\/}} + +\newcommand{\funcname}[1]{\underrealtrue\index{#1}\underrealfalse{\funcfont #1}()} +\newcommand{\funcnamenoparens}[1]{\underrealtrue\index{#1}\underrealfalse{\funcfont #1}} diff --git a/krb5-1-6/doc/implement/implement.tex b/krb5-1-6/doc/implement/implement.tex new file mode 100644 index 000000000..7b709f56f --- /dev/null +++ b/krb5-1-6/doc/implement/implement.tex @@ -0,0 +1,94 @@ +\documentstyle[fixunder,functions,twoside,fancyheadings]{article} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{2.00in} +\setlength{\marginparsep}{0.05in} +\setlength{\marginparwidth}{1.95 in} +\setlength{\textwidth}{4.75in} +\setlength{\topmargin}{-.5in} +\setlength{\textheight}{9in} +\setlength{\parskip}{.1in} +\setlength{\parindent}{2em} +\setlength{\footrulewidth}{0.4pt} +\setlength{\plainfootrulewidth}{0.4pt} +\setlength{\plainheadrulewidth}{0.4pt} +\makeindex +\newif\ifdraft +\draftfalse +% +% Far, far too inconvenient... it's still very draft-like anyway.... +% [tytso:19900921.0018EDT] +% +%\typein{Draft flag? (type \noexpand\draftfalse if not draft...)} +\ifdraft +\pagestyle{fancyplain} +\addtolength{\headwidth}{\marginparsep} +\addtolength{\headwidth}{\marginparwidth} +\makeatletter +\renewcommand{\sectionmark}[1]{\markboth {\uppercase{\ifnum \c@secnumdepth >\z@ + \thesection\hskip 1em\relax \fi #1}}{}}% +\renewcommand{\subsectionmark}[1]{\markright {\ifnum \c@secnumdepth >\@ne + \thesubsection\hskip 1em\relax \fi #1}} +\makeatother +\lhead[\thepage]{\fancyplain{}{\sl\rightmark}} +\rhead[\fancyplain{}{\sl\rightmark}]{\thepage} +\lfoot[]{{\bf DRAFT---DO NOT REDISTRIBUTE}} +\rfoot[{\bf DRAFT---DO NOT REDISTRIBUTE}]{} +\cfoot{\thepage} +\else\pagestyle{headings}\fi + +%nlg- time to make this a real document + +\title{\Huge Kerberos V5 Implementer's Guide} +\date{\ifdraft \\ {\Large DRAFT---}\fi\today} +\author{MIT Information Systems} + +\begin{document} +\maketitle +\tableofcontents + +\section{Introduction} + + This document is designed to aide the programmer who plans to +change MIT's implementation of Kerberos significantly. It is geared towards +programmers who are already familiar with Kerberos and how MIT's +implementation is structured. + + Some of the more basic information needed can be found in the +API document, although many functions have been repeated where +additional information has been included for the implementer. The +function descriptions included are up to date, even if the description +of the functions may not be very verbose. + +\ifdraft\sloppy\fi + +\section{Cache and Key table functions} + +\subsection{Credentials cache functions} +\input{ccache-i.tex} + +\subsection{Replay cache functions} +\input{rcache-i.tex} + +\subsection{Key table functions} +\input{keytab-i.tex} + +\section{Operating-system specific functions} +\input{libos-i.tex} + +\section{Principal database functions} + +\input{kdb-i.tex} + +\section{Encryption system interface} +\input{encrypt-i.tex} + +\section{Checksum interface} +\input{cksum-i.tex} + +\section{CRC-32 checksum functions} +\input{crc-32-i.tex} + +\appendix +\cleardoublepage +\input{\jobname.ind} +\end{document} diff --git a/krb5-1-6/doc/implement/kdb-i.tex b/krb5-1-6/doc/implement/kdb-i.tex new file mode 100644 index 000000000..dc81971bb --- /dev/null +++ b/krb5-1-6/doc/implement/kdb-i.tex @@ -0,0 +1,242 @@ +The \libname{libkdb.a} library provides a principal database interface +to be used by the Key Distribution center and other database +manipulation tools. + + +\begin{funcdecl}{krb5_db_set_name}{krb5_error_code}{\funcin} +\funcarg{char *}{name} +\end{funcdecl} + +Set the name of the database to \funcparam{name}. +%Errors: If it doesn't exist, an error code is returned. + +Must be called before \funcname{krb5_db_init} or after +\funcname{krb5_db_fini}; must not be called while db functions are active. + +\begin{funcdecl}{krb5_db_set_nonblocking}{krb5_error_code}{\funcin} +\funcarg{krb5_boolean}{newmode} +\funcout +\funcarg{krb5_boolean *}{oldmode} +\end{funcdecl} + +Changes the locking mode of the database functions, returning the previous +mode in \funcparam{*oldmode}. + +If \funcparam{newmode} is TRUE, then the database is put into +non-blocking mode, which may result in ``database busy'' error codes from +the get, put, and iterate routines. + +If \funcparam{newmode} is FALSE, then the database is put into blocking mode, +which may result in delays from the get, put and iterate routines. + +The default database mode is blocking mode. + +\begin{funcdecl}{krb5_db_init}{krb5_error_code}{\funcvoid} +\end{funcdecl} + +Called before using \funcname{krb5_db_get_principal}, +\funcname{krb5_db_put_principal}, \funcname{krb5_db_iterate}, and +\funcname{krb5_db_set_nonblocking}. + +Does any required initialization. + +%Errors: init errors, system errors. + +\begin{funcdecl}{krb5_db_fini}{krb5_error_code}{\funcvoid} +\end{funcdecl} + +Called after all database operations are complete, to perform any required +clean-up. + +%Errors: sysytem errors. + + +\begin{funcdecl}{krb5_db_get_age}{krb5_error_code}{\funcin} +\funcarg{char *}{db_name} +\funcout +\funcarg{time_t *}{age} +\end{funcdecl} + +Retrieves the age of the database \funcname{db_name} (or the current +default database if \funcname{db_name} is NULL). + +\funcparam{*age} is filled in in local system time units, and represents +the last modification time of the database. + +%Errors: system errors. + + +\begin{funcdecl}{krb5_db_create}{krb5_error_code}{\funcin} +\funcarg{char *}{db_name} +\end{funcdecl} + +Creates a new database named \funcname{db_name}. Will not create a +database by that name if it already exists. The database must be +populated by the caller by using \funcname{krb5_db_put_principal}. + +%Errors: db exists, system errors. + +\begin{funcdecl}{krb5_db_rename}{krb5_error_code}{\funcin} +\funcarg{char *}{source} +\funcarg{char *}{dest} +\end{funcdecl} +Renames the database \funcarg{source} to \funcarg{dest} + +Any database named \funcarg{dest} is destroyed. + +%Errors: system errors. + +\begin{funcdecl}{krb5_db_get_principal}{krb5_error_code}{\funcin} +\funcarg{krb5_principal}{searchfor} +\funcout +\funcarg{krb5_db_entry *}{entries} +\funcinout +\funcarg{int *}{nentries} +\funcout +\funcarg{krb5_boolean *}{more} +\end{funcdecl} + +Retrieves the principal records named by \funcparam{searchfor}. + +\funcparam{entries} must point to an array of \funcparam{*nentries} +krb5_db_entry structures. +At most \funcparam{*nentries} structures are filled in, and +\funcparam{*nentries} is modified to reflect the number actually returned. + +\funcparam{*nentries} must be at least one (1) when this function is called. + +\funcparam{*more} is set to TRUE if there are more records that wouldn't fit +in the available space, and FALSE otherwise. + +The principal structures filled in have pointers to allocated storage; +\funcname{krb5_db_free_principal} should be called with +\funcparam{entries} and \funcparam{*nentries} +in order to free this storage when no longer needed. + + +\begin{funcdecl}{krb5_db_free_principal}{void}{\funcin} +\funcarg{krb5_db_entry *}{entries} +\funcarg{int}{nentries} +\end{funcdecl} + +Frees allocated storage held by \funcparam{entries} as filled in by +\funcname{krb5_db_get_principal}. + + +\begin{funcdecl}{krb5_db_put_principal}{krb5_error_code}{\funcin} +\funcarg{krb5_db_entry *}{entries} +\funcarg{int *}{nentries} +\end{funcdecl} + +Stores the \funcparam{*nentries} principal structures pointed to by +\funcparam{entries} in the database. + +\funcparam{*nentries} is updated upon return to reflect the number of records +acutally stored; the first \funcparam{*nentries} records will have been +stored in the database. + +%Errors: Returns error code if not all entries were stored. + +\begin{funcdecl}{krb5_db_iterate}{krb5_error_code}{\funcin} +\funcfuncarg{krb5_error_code}{(*func)} +\funcarg{krb5_pointer}{} +\funcarg{krb5_db_entry *}{} +\funcendfuncarg +\funcarg{krb5_pointer}{iterate_arg} +\end{funcdecl} + +Iterates over the database, fetching every entry in an unspecified order +and calling \funcparam{(*func)}(\funcparam{iterate_arg}, +\funcparam{principal}) where \funcparam{principal} points to a record from the +database. + +If \funcparam{(*func)}() ever returns an error code, the iteration +should be +aborted and that error code is returned by this function. + +\begin{funcdecl}{krb5_db_store_mkey}{krb5_error_code}{\funcin} +\funcarg{char *}{keyfile} +\funcarg{krb5_principal}{mname} +\funcarg{krb5_keyblock *}{key} +\end{funcdecl} + +Put the KDC database master key into the file \funcparam{keyfile}. If +\funcparam{keyfile} is NULL, then a default file name derived from the +principal name \funcparam{mname} is used. + +\begin{funcdecl}{krb5_db_fetch_mkey}{krb5_error_code}{\funcin} +\funcarg{krb5_principal}{mname} +\funcarg{krb5_encrypt_block *}{eblock} +\funcarg{krb5_boolean}{fromkeyboard} +\funcarg{krb5_boolean}{twice} +\funcarg{krb5_data }{salt} +\funcinout +\funcarg{krb5_keyblock *}{key} +\end{funcdecl} + +Get the KDC database master key from somewhere, filling it into +\funcparam{*key}. +\funcparam{key{\ptsto}keytype} should be set to the desired key type. + +If \funcparam{fromkeyboard} is TRUE, then the master key is read as a password +from the user's terminal. In this case: +\funcparam{eblock} should point to a block with an appropriate +\funcname{string_to_key} function; if \funcparam{twice} is TRUE, the +password is read twice for verification; and if \funcparam{salt} is +non-NULL, it is used as the salt when converting the typed +password to the master key. + + +If \funcparam{fromkeyboard} is false, then the key is read from +a file whose name is derived from the principal name \funcparam{mname}. +Therefore, \funcparam{eblock}, \funcparam{twice} and \funcparam{salt} +are ignored. + + +\funcparam{mname} is the name of the key sought; this is often used by +\funcname{string_to_key} to aid in conversion of the password to a key. + +\begin{funcdecl}{krb5_kdb_encrypt_key}{krb5_error_code}{\funcin} +\funcarg{krb5_encrypt_block *}{eblock} +\funcarg{const krb5_keyblock *}{in} +\funcinout +\funcarg{krb5_encrypted_keyblock *}{out} +\end{funcdecl} + +Encrypt a key for storage in the database. \funcparam{eblock} is used +to encrypt the key in \funcparam{in} into \funcparam{out}; the storage +pointed to by \funcparam{*out} is allocated before use and should be +freed when the caller is finished with it. + +\begin{funcdecl}{krb5_kdb_decrypt_key}{krb5_error_code}{\funcin} +\funcarg{krb5_encrypt_block *}{eblock} +\funcarg{const krb5_encrypted_keyblock *}{in} +\funcinout +\funcarg{krb5_keyblock *}{out} +\end{funcdecl} + +Decrypt a key from storage in the database. \funcparam{eblock} is used +to decrypt the key in \funcparam{in} into \funcparam{out}; the storage +pointed to by \funcparam{*out} is allocated before use and should be +freed when the caller is finished with it. + +\begin{funcdecl}{krb5_db_setup_mkey_name}{krb5_error_code}{\funcin} +\funcarg{const}{char *keyname} +\funcarg{const}{char *realm} +\funcout +\funcarg{char **}{fullname} +\funcarg{krb5_principal *}{principal} +\end{funcdecl} + +Given a key name \funcparam{keyname} and a realm name \funcparam{realm}, +construct a principal which can be used to fetch the master key from the +database. This principal is filled into \funcparam{*principal}; +\funcparam{*principal} should be freed by \funcname{krb5_free_principal} +when the caller is finished. + +If \funcparam{keyname} is NULL, the default key name will be used. + +If \funcparam{fullname} is not NULL, it is set to point to a string +representation of the complete principal name; its storage may be freed +by calling \funcname{free} on \funcparam{*fullname}. + diff --git a/krb5-1-6/doc/implement/keytab-i.tex b/krb5-1-6/doc/implement/keytab-i.tex new file mode 100644 index 000000000..697728721 --- /dev/null +++ b/krb5-1-6/doc/implement/keytab-i.tex @@ -0,0 +1,204 @@ +The key table functions deal with storing and retrieving service keys +for use by unattended services which participate in authentication exchanges. + +Keytab routines should all be atomic. Before a routine returns it +must make sure that all non-sharable resources it acquires are +released and in a consistent state. For example, an implementation is not +allowed to leave a file open for writing or to have a lock on a file. + +Note that all keytab implementations must support multiple concurrent +sequential scans. Another detail to note is that +the order of values returned from \funcname{get_next} is +unspecified and may be sorted to the implementor's convenience. + +\subsubsection{The krb5_kt_ops structure} +In order to implement a new key table type, the programmer should +declare a {\bf krb5_kt_ops} structure, and fill in the elements of the +structure appropriately, by implementing each of the key table +functions for the new key table type. + +In order to reduce the size of binary programs when static linking is +used, it is common to provide two \datatype{krb5_kt_ops} structures for +each key table type, one for reading only in which the pointers to the +add and delete functions are zero, and one for reading and writing. + +\begin{verbatim} +typedef struct _krb5_kt_ops { + char *prefix; + /* routines always present */ + krb5_error_code (*resolve)((char *, + krb5_keytab *)); + krb5_error_code (*get_name)((krb5_keytab, + char *, + int)); + krb5_error_code (*close)((krb5_keytab)); + krb5_error_code (*get)((krb5_keytab, + krb5_principal, + krb5_kvno, + krb5_keytab_entry *)); + krb5_error_code (*start_seq_get)((krb5_keytab, + krb5_kt_cursor *)); + krb5_error_code (*get_next)((krb5_keytab, + krb5_keytab_entry *, + krb5_kt_cursor *)); + krb5_error_code (*end_get)((krb5_keytab, + krb5_kt_cursor *)); + /* routines to be included on extended version (write routines) */ + krb5_error_code (*add)((krb5_keytab, + krb5_keytab_entry *)); + krb5_error_code (*remove)((krb5_keytab, + krb5_keytab_entry *)); +} krb5_kt_ops; +\end{verbatim} + +\subsubsection{Per-type functions that are always present} +The following entry points must be implemented for each type of +key table. However, \funcname{resolve}, \funcname{remove} and +\funcname{add} are only called by the key table glue code. +They are not called directly by the application. + + however, application programs are not expected to call +\funcname{resolve}, \funcname{remove}, +or \funcname{add} directly. + +\begin{funcdecl}{resolve}{krb5_error_code}{\funcin} +\funcarg{char *}{residual} +\funcout +\funcarg{krb5_keytab *}{id} +\end{funcdecl} + +Fills in \funcparam{*id} with a handle identifying the keytab with name +``residual''. The interpretation of ``residual'' is dependent on the +type of keytab. + +\begin{funcdecl}{get_name}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\funcout +\funcarg{char *}{name} +\funcin +\funcarg{int}{namesize} +\end{funcdecl} + +\funcarg{name} is filled in with the first \funcparam{namesize} bytes of +the name of the keytab identified by \funcname{id}. +If the name is shorter than \funcparam{namesize}, then \funcarg{name} +will be null-terminated. + +\begin{funcdecl}{close}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\end{funcdecl} + +Closes the keytab identified by \funcparam{id} and invalidates +\funcparam{id}, and releases any other resources acquired during use of +the key table. + +Requires that \funcparam{id} identifies a valid credentials cache. + +\begin{funcdecl}{get}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\funcarg{krb5_principal}{principal} +\funcarg{krb5_kvno}{vno} +\funcout +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +Searches the keytab identified by \funcparam{id} for an entry whose +principal matches \funcparam{principal} and +whose key version number matches \funcparam{vno}. If \funcparam{vno} is +zero, the first entry whose principal matches is returned. + +%Errors: +This routine should return an error code if no suitable entry is +found. If an entry is found, the entry is returned in +\funcparam{*entry}; its contents should be deallocated by calling +\funcname{close} when no longer needed. + +\begin{funcdecl}{close}{krb5_error_code}{\funcinout} +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +Releases all storage allocated for \funcparam{entry}, which must point +to a structure previously filled in by \funcname{get} or +\funcname{get_next}. + +\begin{funcdecl}{start_seq_get}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\funcout +\funcarg{krb5_kt_cursor *}{cursor} +\end{funcdecl} + +Prepares to read sequentially every key in the keytab identified by +\funcparam{id}. +\funcparam{cursor} is filled in with a cursor to be used in calls to +\funcname{get_next}. + +\begin{funcdecl}{get_next}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\funcout +\funcarg{krb5_keytab_entry *}{entry} +\funcinout +\funcarg{krb5_kt_cursor}{cursor} +\end{funcdecl} + +Fetches the ``next'' entry in the keytab, returning it in +\funcparam{*entry}, and updates \funcparam{*cursor} for the next +request. If the keytab changes during the sequential get, an error +must be +%Errors: +guaranteed. \funcparam{*entry} should be freed after use by +calling +\funcname{close}. + +Requires that \funcparam{id} identifies a valid credentials cache. and +\funcparam{*cursor} be a cursor returned by +\funcname{start_seq_get} or a subsequent call to +\funcname{get_next}. + +%Errors: error code if no more cache entries or if the keytab changes. + +\begin{funcdecl}{end_get}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\funcarg{krb5_kt_cursor *}{cursor} +\end{funcdecl} + +Finishes sequential processing mode and invalidates \funcparam{cursor}, +which must never be re-used after this call. + +Requires that \funcparam{id} identifies a valid credentials cache. and +\funcparam{*cursor} be a cursor returned by +\funcname{start_seq_get} or a subsequent call to +\funcname{get_next}. + +%Errors: May return error code if \funcparam{cursor} is invalid. + +\subsubsection{Per-type functions to be included for write routines} + +\begin{funcdecl}{add}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +Stores \funcparam{entry} in the keytab \funcparam{id}. +Fails if the entry already exists. + +This operation must, within the constraints of the operating system, not +return until it can verify that the write has completed succesfully. +For example, in a UNIX file-based implementation, this routine (or the part +of the underlying implementation that it calls) would be responsible for +doing an \funcname{fsync} on the file before returning. + +%Errors: +This routine should return an error code if \funcparam{entry} is +already present in the keytab or if the key could not be stored (quota +problem, etc). + +\begin{funcdecl}{remove}{krb5_error_code}{\funcin} +\funcarg{krb5_keytab}{id} +\funcarg{krb5_keytab_entry *}{entry} +\end{funcdecl} + +Searches the keytab \funcparam{id} for an entry that exactly matches +\funcparam{entry}. If one is found, it is removed from the keytab. + +%Errors: Returns an error code if not found. + diff --git a/krb5-1-6/doc/implement/libos-i.tex b/krb5-1-6/doc/implement/libos-i.tex new file mode 100644 index 000000000..cdd4861ff --- /dev/null +++ b/krb5-1-6/doc/implement/libos-i.tex @@ -0,0 +1,34 @@ +The operating-system specific functions provide an interface between the +other parts of the \libname{libkrb5.a} libraries and the operating system. + +Beware! Any of the functions below are allowed to be implemented as +macros. Prototypes for functions can be found in {\tt +}; other definitions (including macros, if used) are +in {\tt }. + +The following global symbols are provided in \libname{libos.a}. If you +wish to substitute for any of them, you must substitute for all of them +(they are all declared and initialized in the same object file): +\begin{description} +% These come from src/lib/osconfig.c +\item[extern char *\globalname{krb5_config_file}:] name of configuration file +\item[extern char *\globalname{krb5_trans_file}:] name of hostname/realm +name translation file +\item[extern char *\globalname{krb5_defkeyname}:] default name of key +table file +\item[extern char *\globalname{krb5_lname_file}:] name of aname/lname +translation database +\item[extern int \globalname{krb5_max_dgram_size}:] maximum allowable +datagram size +\item[extern int \globalname{krb5_max_skdc_timeout}:] maximum +per-message KDC reply timeout +\item[extern int \globalname{krb5_skdc_timeout_shift}:] shift factor +(bits) to exponentially back-off the KDC timeouts +\item[extern int \globalname{krb5_skdc_timeout_1}:] initial KDC timeout +\item[extern char *\globalname{krb5_kdc_udp_portname}:] name of KDC UDP port +\item[extern char *\globalname{krb5_default_pwd_prompt1}:] first prompt +for password reading. +\item[extern char *\globalname{krb5_default_pwd_prompt2}:] second prompt + +\end{description} + diff --git a/krb5-1-6/doc/implement/rcache-i.tex b/krb5-1-6/doc/implement/rcache-i.tex new file mode 100644 index 000000000..e00a639da --- /dev/null +++ b/krb5-1-6/doc/implement/rcache-i.tex @@ -0,0 +1,142 @@ +The replay cache functions deal with verifying that AP_REQ's do not +contain duplicate authenticators; the storage must be non-volatile for +the site-determined validity period of authenticators. + +Each replay cache has a string {\bf name} associated with it. The use of +this name is dependent on the underlying caching strategy (for +file-based things, it would be a cache file name). The +caching strategy should use non-volatile storage so that replay +integrity can be maintained across system failures. + +\subsubsection{The krb5_rc_ops structure} +In order to implement a new replay cache type, the programmer should +declare a {\bf krb5_rc_ops} structure, and fill in the elements of the +structure appropriately, by implementing each of the replay cache +functions for the new replay cache type. + +The prefix element specifies the prefix {bf name} of the the new replay +cache type. For example, if the prefix {\bf name} is ``dfl'', then if the +program calls \funcname{krb5_rc_resolve} with a credential cache name +such as ``dfl:host'', then \funcname{krb5_rc_resolve} +will call the resolve function (as defined by the {\bf krb5_rc_ops} +structure where the prefix element is ``dfl'') and pass it the +argument ``host''. + +Before a new replay cache type can be recognized by +\funcname{krb5_rc_resolve}, it must be registered with the Kerberos +library by calling \funcname{krb5_rc_register}. + +\begin{verbatim} +typedef struct _krb5_rc_ops { + char *type; + krb5_error_code (*init)((krb5_rcache,krb5_deltat)); + krb5_error_code (*recover)((krb5_rcache)); + krb5_error_code (*destroy)((krb5_rcache)); + krb5_error_code (*close)((krb5_rcache)); + krb5_error_code (*store)((krb5_rcache,krb5_donot_replay *)); + krb5_error_code (*expunge)((krb5_rcache)); + krb5_error_code (*get_span)((krb5_rcache,krb5_deltat *)); + char *(*get_name)((krb5_rcache)); + krb5_error_code (*resolve)((krb5_rcache, char *)); +} krb5_rc_ops; +\end{verbatim} + + +\subsubsection{Per-type functions} +The following entry points must be implemented for each type of +replay cache. + +\begin{funcdecl}{init}{krb5_error_code}{\funcin} +\funcarg{krb5_rcache}{id} +\funcarg{krb5_deltat}{auth_lifespan} +\end{funcdecl} + +Creates/refreshes the replay cache identified by \funcparam{id} and sets its +authenticator lifespan to \funcparam{auth_lifespan}. If the +replay cache already exists, its contents are destroyed. + +%Errors: permission errors, system errors + +\begin{funcdecl}{recover}{krb5_error_code}{\funcin} +\funcarg{krb5_rcache}{id} +\end{funcdecl} +Attempts to recover the replay cache \funcparam{id}, (presumably after a +system crash or server restart). + +%Errors: error indicating that no cache was found to recover + +\begin{funcdecl}{destroy}{krb5_error_code}{\funcin} +\funcarg{krb5_rcache}{id} +\end{funcdecl} + +Destroys the replay cache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + +%Errors: permission errors. + +\begin{funcdecl}{close}{krb5_error_code}{\funcin} +\funcarg{krb5_rcache}{id} +\end{funcdecl} + +Closes the replay cache \funcparam{id}, invalidates \funcparam{id}, +and releases any other resources acquired during use of the replay cache. +Requires that \funcparam{id} identifies a valid replay cache. + +%Errors: permission errors + +\begin{funcdecl}{store}{krb5_error_code}{\funcin} +\funcarg{krb5_rcache}{id} +\funcarg{krb5_donot_replay *}{rep} +\end{funcdecl} +Stores \funcparam{rep} in the replay cache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + +Returns KRB5KRB_AP_ERR_REPEAT if \funcparam{rep} is already in the +cache. May also return permission errors, storage failure errors. + +\begin{funcdecl}{expunge}{krb5_error_code}{\funcin} +\funcarg{krb5_rcache}{id} +\end{funcdecl} +Removes all expired replay information (i.e. those entries which are +older than then authenticator lifespan of the cache) from the cache +\funcparam{id}. Requires that \funcparam{id} identifies a valid replay +cache. + +%Errors: permission errors. + +\begin{funcdecl}{get_span}{krb5_error_code}{\funcin} +\funcarg{krb5_rcache}{id} +\funcout +\funcarg{krb5_deltat *}{auth_lifespan} +\end{funcdecl} +Fills in \funcparam{auth_lifespan} with the lifespan of +the cache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + +\begin{funcdecl}{resolve}{krb5_error_code}{\funcinout} +\funcarg{krb5_rcache}{id} +\funcin +\funcarg{char *}{name} +\end{funcdecl} + +Initializes private data attached to \funcparam{id}. This function MUST +be called before the other per-replay cache functions. + +Requires that \funcparam{id} points to allocated space, with an +initialized \funcparam{id{\ptsto}ops} field. + +Since \funcname{resolve} allocates memory, +\funcname{close} must be called to free the allocated memory, +even if neither \funcname{init} or +\funcname{recover} were successfully called by the application. + +%Returns: allocation errors. + + +\begin{funcdecl}{krb5_rc_get_name}{char *}{\funcin} +\funcarg{krb5_rcache}{id} +\end{funcdecl} + +Returns the name (excluding the type) of the rcache \funcparam{id}. +Requires that \funcparam{id} identifies a valid replay cache. + diff --git a/krb5-1-6/doc/implementor.texinfo b/krb5-1-6/doc/implementor.texinfo new file mode 100644 index 000000000..169dee8c0 --- /dev/null +++ b/krb5-1-6/doc/implementor.texinfo @@ -0,0 +1,1192 @@ +\input texinfo @c -*-texinfo-*- +@c +@c Note: the above texinfo file must include the "doubleleftarrow" +@c definitions added by jcb. +@c %**start of header +@c guide +@setfilename krb5-implement.info +@settitle Kerberos V5 Installation Guide +@setchapternewpage odd @c chapter begins on next odd page +@c @setchapternewpage on @c chapter begins on next page +@c @smallbook @c Format for 7" X 9.25" paper +@c %**end of header + +@paragraphindent 0 +@iftex +@parskip 6pt plus 6pt +@end iftex + +@include definitions.texinfo +@c @set EDITION b7-1 +@set EDITION [working copy] + +@finalout @c don't print black warning boxes + +@titlepage +@title @value{PRODUCT} Implementor's Guide +@subtitle Release: @value{RELEASE} +@subtitle Document Edition: @value{EDITION} +@subtitle Last updated: @value{UPDATED} +@author @value{COMPANY} + +@page +@vskip 0pt plus 1filll + +@iftex +@include copyright.texinfo +@end iftex +@end titlepage + +@node Top, Introduction, (dir), (dir) +@comment node-name, next, previous, up + +@ifinfo +This file contains internal implementor's information for the +@value{RELEASE} release of @value{PRODUCT}. + +@include copyright.texinfo + +@end ifinfo + +@c The master menu is updated using emacs19's M-x texinfo-all-menus-update +@c function. Don't forget to run M-x texinfo-every-node-update after +@c you add a new section or subsection, or after you've rearranged the +@c order of sections or subsections. Also, don't forget to add an @node +@c comand before each @section or @subsection! All you need to enter +@c is: +@c +@c @node New Section Name +@c @section New Section Name +@c +@c M-x texinfo-every-node-update will take care of calculating the +@c node's forward and back pointers. +@c +@c --------------------------------------------------------------------- + +@menu +* Introduction:: +* Compiler and OS Requirements:: +* Networking:: +* Thread Safety:: +* Shared Libraries:: +* Porting Issues:: +@end menu + +@node Introduction, Compiler and OS Requirements, Top, Top +@chapter Introduction + +This file contains internal implementor's information for +@value{PRODUCT}. It is currently contains information that was removed +from install.texi; eventually it will have more detailed information on +the internals of the @value{PRODUCT}. + +@node Compiler and OS Requirements, Networking, Introduction, Top +@chapter Compiler and OS Requirements + +The basic Kerberos libraries are entirely written in C. +However, we do assume full ANSI C (1989) support, typical 32- or +64-bit twos-complement architectures (@code{char} is 8 bits, +@code{short} is 16 bits, @code{int} is 32 bits, byte order is 1234 or +4321), and a few aspects of ISO C 1999: + +@itemize @bullet +@item +support for inline functions, even if the keyword isn't @code{inline} +@item +64-bit arithmetic types (needed for sequence numbers in GSSAPI) +@end itemize + +These are handled through the internal header file +@file{k5-platform.h}. + +We also conditionally tailor code for the GNU C compiler in a few +places where it helps performance or debugging, but the code should +still work fine with other C compilers. + +On UNIX platforms, ... @i{(should outline what POSIX stuff we +require)}. + +See also @ref{Advanced Shared Library Requirements}, for UNIX and +Windows systems. + +Our makefiles are intended to support building from the top level with +a POSIX-compliant version of @code{make}, and parallel builds using +GNU @code{make}. The latter sometimes comes at the cost of efficiency with +non-GNU versions; for example, some targets in some directories will +always be rebuilt with certain versions of @code{make}, even though +the real dependencies are not out of date, because some versions of +@code{make} don't understand how we're using phony intermediate +targets to manage building in subdirectories in parallel builds. +(Actually, this is more my view of how we've been doing things than +official policy. ---Ken) + +@node Networking, Thread Safety, Compiler and OS Requirements, Top +@chapter Networking + +@menu +* Socket API:: +* IPv6 Support:: +* Local Addresses:: +* Host Address Lookup:: +@end menu + +@node Socket API, IPv6 Support, Networking, Networking +@section Socket API + +Someone should describe the API subset we're allowed to use with +sockets, how and when to use @code{SOCKET_ERRNO}, @i{etc}. + +Note that all new code doing hostname and address translation should +use @code{getaddrinfo} and friends. (@xref{Host Address Lookup}.) + +@node IPv6 Support, Local Addresses, Socket API, Networking +@section IPv6 Support + +Most of the IPv6 support is keyed on the macro @code{KRB5_USE_INET6}. +If this macro is not defined, there should be no references to +@code{AF_INET6}, @code{struct sockaddr_in6}, @i{etc}. + +The @code{configure} scripts will check for the existence of various +functions, macros and structure types to decide whether to enable the +IPv6 support. You can also use the @samp{--enable-ipv6} or +@samp{--disable-ipv6} options to override this decision. + +Regardless of the setting of @code{KRB5_USE_INET6}, some aspects of +the new APIs devised for IPv6 are used throughout the code, because it +would be too difficult maintain code for the IPv6 APIs and for the old +APIs at the same time. But for backwards compatibility, we try to +fake them if the system libraries don't provide them, at least for +now. This means we sometimes use slightly modified versions of the +APIs, but we try to keep the modifications as non-intrusive as +possible. Macros are used to rename struct tags and function names, +so don't @code{#undef} any of these names. + +@table @code + +@item getaddrinfo +@itemx getnameinfo +@itemx freeaddrinfo +@itemx gai_strerror +@itemx struct addrinfo +Always include the header file @file{fake-addrinfo.h} before using +these. If the native system doesn't provide them, the header file +will, using support functions that will call @code{gethostbyname} and +the like in the native libraries. (This is similar to how the Winsock +2 headers work, depending on some of the predefined macros indicating +the target OS version, though they define the support functions +directly in the header, as our code used to do.) + +We also provide ``wrapper'' versions on some systems where a native +implementation exists but the data it returns is broken in some way. + +So these may not always be thread-safe, and they may not always +provide IPv6 support, but the API will be consistent. + +@item struct sockaddr_storage +@itemx socklen_t +These are provided by @file{socket-utils.h}, if the native headers +don't provide them. @code{sockaddr_storage} contains a +@code{sockaddr_in}, so by definition it's big enough to hold one; it +also has some extra padding which will probably make it big enough to +hold a @code{sockaddr_in6} if the resulting binary should get run on a +kernel with IPv6 support. + +Question: Should these simply be moved into @file{port-sockets.h}? + +@end table + +IRIX 6.5.7 has no IPv6 support. Of the systems most actively in the +MIT's Athena environment (used by MIT's Kerberos UNIX developers), +this is the only one without built-in IPv6 support. In another year +or so we probably won't be using those systems any more, and we may +consider dropping support for systems without IPv6 support. + +Somewhere between IRIX 6.5.14 and 6.5.16, partial IPv6 support was +introduced to the extent that the configuration system detects the +IPv6 support and attempts to use it. Code compiles, but then upon +linking, one discovers that ``in6addr_any'' is not defined in any +system library. The header file @file{fake-addrinfo.h} provides a +static copy as a workaround. This run time IPv6 code has still not +been tested. + +Some utility functions or macros are also provided to give a +convenient shorthand for some operations, and to retain compile-time +type checking when possible (generally using inline functions but only +when compiling with GCC). + +@table @code + +@item socklen(struct sockaddr *) +Returns the length of the @code{sockaddr} structure, by looking at the +@code{sa_len} field if it exists, or by returning the known sizes of +@code{AF_INET} and @code{AF_INET6} address structures. + +@item sa2sin(struct sockaddr *) +@itemx sa2sin6(struct sockaddr *) +@itemx ss2sa(struct sockaddr_storage *) +@itemx ss2sin(struct sockaddr_storage *) +@itemx ss2sin6(struct sockaddr_storage *) +Pointer type conversions. Use these instead of plain casts, to get +type checking under GCC. + +@end table + +@node Local Addresses, Host Address Lookup, IPv6 Support, Networking +@section Local Addresses + +(Last update: 2005-04-21, but most of the information dates back to +early 2002.) + +Different systems have different ways of finding the local network +addresses. + +On Windows, @code{gethostbyname} is called on the local host name to get a +set of addresses. If that fails, a UDP socket is ``connected'' to a +particular IPv4 address, and the local socket name is retrieved, its +address being treated as the one local network address. Future +versions of the Windows code should be able to actually examine local +interfaces. + +On (most?) UNIX systems, there is an @code{ioctl} called +@code{SIOCGIFCONF} which gets interface configuration information. +The behavior of this @code{ioctl} varies across UNIX systems though. +It takes as input a buffer to fill with data structures, but if the +buffer isn't big enough, the behavior isn't well defined. Sometimes +you get an error, sometimes you get incomplete data. Sometimes you +get a clear indication that more space was needed, sometimes not. A +couple of systems have additional @code{ioctl}s that can be used to +determine or at least estimate the correct size for the buffer. In +Solaris, Sun has introduced @code{SIOCGLIFCONF} for querying IPv6 +addresses, and restricts @code{SIOCGIFCONF} to IPv4 only. (** We +should actually check if that's true.) They also added +@code{SIOCGIFNUM} and @code{SIOCGLIFNUM} for querying the number of +interfaces. HP-UX 11 also has @code{SIOCGLIFCONF}, but it requires a +different data structure, and we haven't finished that support yet. + +We (Ken Raeburn in particular) ran some tests on various systems to +see what would happen with buffers of various sizes from much smaller +to much larger than needed for the actual data. The buffers were +filled with specific byte values, and then checked to see how much of +the buffer was actually written to. The ``largest gap'' values listed +below are the largest number of bytes we've seen left unused at the +end of the supplied buffer when there were more entries to return. +These values may of coures be dependent on the configurations of the +particular systems we wre testing with. (See +@file{lib/krb5/os/t_gifconf.c} for the test program.) + +NetBSD 1.5-alpha: The returned @code{ifc_len} is the desired amount of +space, always. The returned list may be truncated if there isn't +enough room; no overrun. Largest gap: 43. However, NetBSD has +@code{getifaddrs}, which hides all the ugliness within the C library. + +BSD/OS 4.0.1 (courtesy djm): The returned @code{ifc_len} is equal to +or less than the supplied @code{ifc_len}. Sometimes the entire buffer +is used; sometimes N-1 bytes; occasionally, the buffer must have quite +a bit of extra room before the next structure will be added. Largest +gap: 39. + +Solaris 7,8,9: Return @code{EINVAL} if the buffer space is too small +for all the data to be returned, including when @code{ifc_len} is 0. +Solaris is the only system I've found so far that actually returns an +error. No gap. However, @code{SIOCGIFNUM} may be used to query the +number of interfaces. + +Linux 2.2.12 (Red Hat 6.1 distribution, x86), 2.4.9 (RH 7.1, x86): The +buffer is filled in with as many entries as will fit, and the size +used is returned in @code{ifc_len}. The list is truncated if needed, +with no indication. Largest gap: 31. @emph{However}, this interface +does not return any IPv6 addresses. They must be read from a file +under @file{/proc}. (This appears to be what the @samp{ifconfig} +program does.) + +IRIX 6.5.7: The buffer is filled in with as many entries as will fit +in N-1 bytes, and the size used is returned in @code{ifc_len}. +Providing exactly the desired number of bytes is inadequate; the +buffer must be @emph{bigger} than needed. (E.g., 32->0, 33->32.) The +returned @code{ifc_len} is always less than the supplied one. Largest +gap: 32. + +AIX 4.3.3: Sometimes the returned @code{ifc_len} is bigger than the +supplied one, but it may not be big enough for @emph{all} the +interfaces. Sometimes it's smaller than the supplied value, even if +the returned list is truncated. The list is filled in with as many +entries as will fit; no overrun. Largest gap: 143. + +Older AIX: We're told by W. David Shambroom in RT ticket 919 that +older versions of AIX have a bug in the @code{SIOCGIFCONF} +@code{ioctl} which can cause them to overrun the supplied buffer. +However, we don't yet have details as to which version, whether the +overrun amount was bounded (e.g., one @code{ifreq}'s worth) or not, +whether it's a real buffer overrun or someone assuming it was because +@code{ifc_len} was increased, @i{etc}. Once we've got details, we can +try to work around the problem. + +Digital UNIX 4.0F: If input @code{ifc_len} is zero, return an +@code{ifc_len} that's big enough to include all entries. (Actually, +on our system, it appears to be larger than that by 32.) If input +@code{ifc_len} is nonzero, fill in as many entries as will fit, and +set @code{ifc_len} accordingly. (Tested only with buffer previously +filled with zeros.) + +Tru64 UNIX 5.1A: Like Digital UNIX 4.0F, except the ``extra'' space +indicated when the input @code{ifc_len} is zero is larger. (We got +400 out when 320 appeared to be needed.) + +So... if the returned @code{ifc_len} is bigger than the supplied one, +we'll need at least that much space -- but possibly more -- to hold +all the results. If the returned value is a little smaller or the +same, we may still need more space. + +The heuristic we're using on most systems now is to keep growing the +buffer until the unused space is larger than an @code{ifreq} structure +by some safe margin. + +@node Host Address Lookup, , Local Addresses, Networking +@section Host Address Lookup + +The traditional @code{gethostbyname} function is not thread-safe, and +does not support looking up IPv6 addresses, both of which are becoming +more important. New standards have been in development that should +address both of these problems. The most promising is +@code{getaddrinfo} and friends, which is part of the Austin Group and +UNIX 98(?) specifications. Code in the MIT tree has mostly been +converted to use this interface. + +@quotation +(Question: What about @code{inet_ntop} and @code{inet_pton}? We're +not using them at the moment, but some bits of code would be +simplified if we were to do so, when plain addresses and not socket +addresses are already presented to us.) +@end quotation + +The @code{getaddrinfo} function takes a host name and service name and +returns a linked list of structures indicating the address family, +length, and actual data in ``sockaddr'' form. (That is, it includes a +pointer to a @code{sockaddr_in} or @code{sockaddr_in6} structure.) +Depending on options set via the @code{hints} input argument, the results +can be limited to a single address family (@i{e.g.}, for IPv4 +applications), and the canonical name of the indicated host can be +returned. Either the host or service can be a null pointer, in which +case only the other is looked up; they can also be expressed in +numeric form. This interface is extensible to additional address +families in the future. The returned linked list can be freed with +the @code{freeaddrinfo} function. + +The @code{getnameinfo} function does the reverse -- given an address +in ``sockaddr'' form, it converts the address and port values into +printable forms. + +Errors returned by either of these functions -- as return values, not +global variables -- can be translated into printable form with the +@code{gai_strerror} function. + +Some vendors are starting to implement @code{getaddrinfo} and friends, +however, some of the implementations are deficient in one way or +another. + +@table @asis + +@item AIX +As of AIX 4.3.3, @code{getaddrinfo} returns sockaddr structures +without the family and length fields filled in. + +@item GNU libc +The GNU C library, used on GNU/Linux systems, has had a few problems +in this area. One version would drop some IPv4 addresses for some +hosts that had multiple IPv4 and IPv6 addresses. + +In GNU libc 2.2.4, when the DNS is used, the name referred to by PTR +records for each of the addresses is looked up and stored in the +@code{ai_canonname} field, or the printed numeric form of the address +is, both of which are wrong. + +@item IRIX +No known bugs here, but as of IRIX 6.5.7, the version we're using at +MIT, these functions had not been implemented. + +@item Mac OS X +Two problems have been found with @code{getaddrinfo} on Mac OS X, at +least under version 10.3. First, while @code{gethostbyname} data is +cached to make multiple lookups of the same name (@i{e.g.}, by +different parts of the code that need to know about the same server +host), @code{getaddrinfo} results are not cached, so multiple queries +mean multiple DNS requests, which means more delays if the DNS servers +are not close by and fast to respond. We've implemented a cache of +our own to work around this, though it only applies to multiple +lookups in a short period of time within the same application process, +and it's only implemented for the Mac at the moment. + +Second, the Mac libraries will generate a DNS SRV RR query; as far as +I [Ken] can tell this is a bug, but Apple seems to consider it a +feature. (Call @code{getaddrinfo("example.com", "telnet", ...)} and +you get a SRV record query, but the spec on SRV records says you must +not use them unless the specification for the service in question says +to.) Yet more network traffic for each name to look up. + +@item NetBSD +As of NetBSD 1.5, this function is not thread-safe. In 1.5X +(intermediate code snapshot between 1.5 and 1.6 releases), the +@code{ai_canonname} field can be empty, even if the +@code{AI_CANONNAME} flag was passed. In particular, this can happen +if a numeric host address string is provided. Also, numeric service +names appear not to work unless the stream type is given; specifying +the TCP protocol is not enough. + +@item Tru64 UNIX +In Tru64 UNIX 5.0, @code{getaddrinfo} is available, but requires that +@code{} be included before its use; that header file defines +@code{getaddrinfo} as a macro expanding to either @code{ogetaddrinfo} +or @code{ngetaddrinfo}, and apparently the symbol @code{getaddrinfo} +is not present in the system library, causing the @code{configure} +test for it to fail. Technically speaking, I [Ken] think Compaq has +it wrong here, I think the symbol is supposed to be available even if +the application uses @code{#undef}, but I have not confirmed it in the +spec. + +@item Windows +According to Windows documentation, the returned @code{ai_canonname} +field can be null even if the @code{AI_CANONNAME} flag is given. + +@end table + +For most systems where @code{getaddrinfo} returns incorrect data, +we've provided wrapper versions that call the system version and then +try to fix up the returned data. + +For systems that don't provide these functions at all, we've provided +replacement versions that neither are thread-safe nor support IPv6, +but will allow us to convert the rest of our code to assume the +availability of @code{getaddrinfo}, rather than having to use two +branches everywhere, one for @code{getaddrinfo} and one for +@code{gethostbyname}. These replacement functions do use +@code{gethostbyname} and the like; for some systems it would be +possible to use @code{gethostbyname2} or @code{gethostbyname_r} or +other such functions, to provide thread safety or IPv6 support, but +this has not been a priority for us, since most modern systems have +these functions anyways. And if they don't, they probably don't have +real IPv6 support either. + +Including @file{fake-addrinfo.h} will enable the wrapper or +replacement versions when needed. The functions are actually defined +in the support library in @file{src/util/support}, added in the 1.4 +release. + +Do not assume that @code{ai_canonname} will be set when the +@code{AI_CANONNAME} flag is set. Check for a null pointer before +using it. + +@node Thread Safety, Shared Libraries, Networking, Top +@chapter Thread Safety + +Work is still needed as this section is being written. However, we've +made a lot of progress. + +@menu +* Kerberos API Thread Safety:: +* Thread System Requirements:: +* Internal Thread API:: +* Thread Shim Layer Implementation:: +@end menu + +@node Kerberos API Thread Safety, Thread System Requirements, Thread Safety, Thread Safety +@section Kerberos API Thread Safety + +We assume that a @code{krb5_context} or a @code{krb5_auth_context} +will be used in only one thread at a time, and any non-opaque object +clearly being modified by the application code (@i{e.g.}, a +@code{krb5_principal} having a field replaced) is not being used in +another thread at the same time. + +A credentials cache, key table, or replay cache object, once the C +object is created, may be used in multiple threads simultaneously; +internal locking is done by the implementations of those objects. (We +assume that object destructors are invoked only when all other threads +are finished with the object.) @i{(Iterators? Probably okay now, but +needs review.)} However, this doesn't mean that we've fixed any +problems there may be regarding simultaneous access to on-disk files +from multiple processes, and in fact if a process opens a disk file +multiple times, the same problems may come up. + +Any file locking issues may become worse, actually. UNIX file locking +with @code{flock} is done on a per-process basis, and closing a file +descriptor that was opened on a file releases any locks the process +may have on that file, even if they were obtained using other, +still-open file descriptors. UNIX file locks are used for credentials +caches and keytab files; the replay cache implementation is already +known to be unsafe in not using file locking. + +We MAY implement --- but haven't yet --- a ``fix'' whereby open files +are tracked by name (and per object type), and a new attempt to open +one gets a handle that uses the same open file descriptor, even if it +appears as two objects to the application. This won't address the +problem of getting the same file via two names that look different, +but it may be ``good enough.'' + +GSSAPI .... + +Strictly speaking, the GSSAPI specification says nothing about thread +safety, so for best portability, a GSSAPI application probably should +not assume that a GSSAPI implementation is thread-safe in any way. On +the other hand, the GSSAPI specification doesn't explicitly say that +it's safe to use in a program that uses the Berkeley sockets API, +either; at some point, you have to start making some assumptions. + +A GSSAPI security context, like a @code{krb5_context}, may be used +only in one thread at a time. The GSSAPI specification gives precise +definitions of C data structures for buffers, object identifiers, OID +sets, and channel bindings, that do not allow for the addition of a +mutex. Thus, these objects must not be modified by one thread while +in use by another. (All of the GSSAPI functions that modify these +types of objects should be obvious; they're listed as ``modify'' +parameters in the specification. In fact, aside from the case of +@code{gss_add_oid_set_member}, they're generally output arguments, +with the previous value ignored.) + +The function @code{gss_add_cred} can modify the +@code{input_cred_handle} object, if a null @code{output_cred_handle} +argument is supplied. Thus, all @code{gss_cred_id_t} objects must +have mutexes, and all accesses (except in the functions creating or +destroying them) must acquire the mutex first. + +Note that the use of @code{const} in the GSSAPI C bindings is not a +useful guide to when an object might or might not be modified. In +most cases, @code{const} is applied to handle arguments, which are +defined as arithmetic or pointer types. It applies to the argument +itself, not the data pointed to @i{if} the type is a pointer; this +would mean that the GSSAPI function in question cannot modify the +value of its handle parameter, and puts no constraints on +modifications to the object indicated by the handle. And according to +the C type compatibility rules, the function definition can omit those +@code{const} qualifiers anyways.@footnote{If you're thinking that this +means the use of @code{const} in the GSSAPI C bindings is confusing +and/or useless, you're right.} + + + + +@node Thread System Requirements, Internal Thread API, Kerberos API Thread Safety, Thread Safety +@section Thread System Requirements + +We support a few types of environments with regard to thread support: + +@itemize @bullet + +@item +Windows native threads. The objects used by the Windows thread +support functions generally need run-time initialization; this is done +through the library initialization function. (@xref{Advanced Shared +Library Requirements}.) + +@item +POSIX threads, with weak reference support so we can tell whether the +thread code was actually linked into the current executable. If the +functions aren't available, we assume the process is single-threaded +and ignore locks. (We do assume that the thread support functions +won't show up half-way through execution of the program.) In order to +support single-threaded programs wanting to load Kerberos or GSSAPI +modules through a plug-in mechanism, we don't list the pthread library +in the dependencies of our shared libraries. + +@item +POSIX threads, with the library functions always available, even if +they're stub versions that behave normally but don't permit the +creation of new threads. + +On AIX 4.3.3, we do not get weak references or useful stub functions, +and calling @code{dlopen} apparently causes the pthread library to get +loaded, so we've decided to link against the pthread library always. + +On Tru64 UNIX 5.1, we again do not get weak references or useful stub +functions. Rather than look for yet another approach for this one +platform, we decided to always link against the pthread library on +this platform as well. This may break single-threaded applications +that load the Kerberos libraries after startup. A clean solution, +even if platform-dependent, would be welcome. + +@item +Single-threaded. No locking is performed, any ``thread-local'' +storage is in fact global, @i{etc}. + +@end itemize + +If @code{pthread_once} is not provided in functional form in the +default libraries, and weak references are not supported, we always +link against the pthread libraries. (Tru64, AIX.) + +System routines: @code{getaddrinfo} (not always implemented +thread-safe), @code{gethostbyname_r}, @code{gmtime_r}, +@code{getpwnam_r} (but interfaces vary, see @file{k5-platform.h}), +@code{res_nsearch} (but watch for resource leaks). + +Unsafe system routines: @code{setenv}, @code{setlocale}. + +@node Internal Thread API, Thread Shim Layer Implementation, Thread System Requirements, Thread Safety +@section Internal Thread API + +Some ideas were discussed on the @samp{krbdev} mailing list, and while +the current implementation does largely resemble the scheme Ken +Raeburn proposed, some details have changed. + +The following macros in @file{k5-thread.h} implement a locking scheme +similar to POSIX threads, with fewer features. + +@deftp {Data type} k5_mutex_t +This is the type of a mutex to be used by the Kerberos libraries. Any +object of this type needs initialization. If the object is +dynamically allocated, @code{k5_mutex_init} must be used; if the +object is allocated statically, it should be initialized at compile +time with @code{K5_MUTEX_PARTIAL_INITIALIZER} and then +@code{k5_mutex_finish_init} should be called at run time. (In +general, one of these will do the work, and the other will do nothing +interesting, depending on the platform. When the debugging code is +turned on, it will check that both were done. However, as far as I +know, it should work to use just @code{k5_mutex_init} on a mutex in +static storage.) + +The mutex may be used only within the current process. It should not +be created in memory shared between processes. (Will it work in a +child process after @code{fork()}? I think so.) + +The @code{k5_mutex_t} object contains more than an operating-system +mutex; it may also contain debugging information such as the file and +line number in the Kerberos code where the last mutex operation was +performed, information for gathering statistics on mutex usage, +@i{etc}., depending on compile-time options. + +This type @emph{is not} a simple typedef for the native OS mutex +object, to prevent programmers from accidentally assuming that +arbitrary features of the native thread system will always be +available. (If someone wishes to make use of native thread system +features in random library code, they'll have to go further out of +their way to do it, and such changes probably won't be accepted in the +main Kerberos code base at MIT.) + +If thread support is disabled, a simple flag will be stored in place +of the operating-system mutex. This flag indicates the ``locked'' +state, and is checked in the @code{k5_mutex_lock} and +@code{k5_mutex_unlock} macros so that we can detect some cases of +improperly written code even if thread support is not built in. The +other debugging fields will still be present as well. + +If POSIX thread support and weak references are available, both the +POSIX mutex and a flag will be included; which one is used is +determined at run time depending on whether the thread support +routines are available. +@end deftp + +@defvr Macro K5_MUTEX_PARTIAL_INITIALIZER +Value to be used for compile-time initialization of a mutex in static +storage. +@end defvr + +@deftypefn Macro int k5_mutex_finish_init (k5_mutex_t *@var{m}) +Finishes run-time initialization, if such is needed, of a mutex that +was initialized with @code{K5_MUTEX_PARTIAL_INITIALIZER}. This macro +must be called before the mutex can be locked; usually this is done +from library initialization functions. +@end deftypefn + +@deftypefn Macro int k5_mutex_init (k5_mutex_t *@var{m}) +Initializes a mutex. +@end deftypefn + +@deftypefn Macro int k5_mutex_destroy (k5_mutex_t *@var{m}) +Destroys a mutex, whether allocated in static or heap storage. All +mutexes should be destroyed before the containing storage is freed, in +case additional system resources have been allocated to manage them. +@end deftypefn + +@deftypefn Macro int k5_mutex_lock (k5_mutex_t *@var{m}) +@deftypefnx Macro int k5_mutex_unlock (k5_mutex_t *@var{m}) +Lock or unlock a mutex, returning a system error code if an error +happened, or zero for success. (Typically, the return code from +@code{k5_mutex_unlock} is ignored.) +@end deftypefn + +@deftypefn Macro void k5_mutex_assert_locked (k5_mutex_t *@var{m}) +@deftypefnx Macro void k5_mutex_assert_unlocked (k5_mutex_t *@var{m}) +These macros may be used in functions that require that a certain +mutex be locked by the current thread, or not, at certain points +(typically on entry to the function). They may generate error +messages or debugger traps, or abort the program, if the mutex is not +in the expected state. Or, they may simply do nothing. + +It is not required that the OS mutex interface let the application +code determine the state of a mutex; hence these are not specified as +a single macro returning the current state, to be checked with +@code{assert}. +@end deftypefn + +Mutexes should be assumed not to be recursive; if a thread has the +mutex locked already, attempting to lock it again is an error and may +have unpredictable results (error return, abort, data corruption). +There is also no support assumed for ``trylock'' or ``lock with +timeout'' operations. + +Kerberos library code should use the macros above, and ports to new +thread systems should be done through the @code{k5_os_} layer. +(@xref{Thread Shim Layer Implementation}.) + +Thread-local storage is managed through another interface layer: + +@deftp {Enumerator} k5_key_t +This is an enumeration type which indicates which of the per-thread +data objects is to be referenced. +@end deftp + +@deftypefn Macro int k5_key_register (k5_key_t @var{key}, void (*@var{destructor})(void*)) +Registers a thread-local storage key and a function to destroy a +stored object if the thread exits. This function must be called +before @code{k5_setspecific} can be used. Currently @var{destructor} +must not be a null pointer; note, however, that the standard library +function @code{free} is of the correct type to be used here if the +allocated data doesn't require any special cleanup besides releasing +one block of storage. +@end deftypefn + +@deftypefn Macro void *k5_getspecific (k5_key_t @var{key}) +@deftypefnx Macro int k5_setspecific (k5_key_t @var{key}, void *@var{value}) +As with the POSIX interface, retrieve or store the value for the +current thread. Storing a value may return an error indication. If +an error occurs retrieving a value, @code{NULL} is returned. +@end deftypefn + +@deftypefn Macro int k5_key_delete (k5_key_t @var{key}) +Called to indicate that the key value will no longer be used, for +example if the library is in the process of being unloaded. The +destructor function should be called on objects of this type currently +allocated in any thread. (XXX Not implemented yet.) +@end deftypefn + +If support functions are needed to implement any of these macros, +they'll be in the Kerberos support library, and any exported symbols +will use the @code{krb5int_} prefix. The shorter @code{k5_} prefix is +just for convenience, and should not be visible to any application +code. + +@node Thread Shim Layer Implementation, , Internal Thread API, Thread Safety +@section Thread Shim Layer Implementation + +Each of the @code{k5_mutex_} macros has a corresponding +@code{k5_os_mutex_} macro which incorporates the operating system's +mutex object, a flag for non-threaded systems, or both if the use of +the OS pthread support is left until run time. The @code{k5_mutex_} +wrappers add debugging information like the file and line number of +the last lock or unlock call, where the mutex was created, @i{etc}. +There may also be statistical information gathered, such as how long a +thread waits for a mutex or how long the mutex is held. This is all +defined in @file{k5-thread.h}. + +The thread-specific storage support is defined as macros expanding to +similar function names with the @code{krb5int_} prefix, which +functions are defined in @file{util/support/threads.c}. POSIX, +Windows, and non-threaded versions are defined so far. + +The code for collecting and reporting statistics is also mainly in +that file. Macros defined in @file{k5-thread.h} will expand to +include calls to these functions, if @code{DEBUG_THREADS_STATS} is +defined, or do nothing. + +@node Shared Libraries, Porting Issues, Thread Safety, Top +@chapter Shared Libraries + +(These sections are old -- they should get updated.) + +@menu +* Shared Library Theory:: +* Advanced Shared Library Requirements:: +* Operating System Notes for Shared Libraries:: +@end menu + +@node Shared Library Theory, Advanced Shared Library Requirements, Shared Libraries, Shared Libraries +@section Theory of How Shared Libraries are Used + +An explanation of how shared libraries are implemented on a given +platform is too broad a topic for this manual. Instead this will touch +on some of the issues that the Kerberos V5 tree uses to support version +numbering and alternate install locations. + +Normally when one builds a shared library and then links with it, the +name of the shared library is stored in the object +(i.e. libfoo.so). Most operating systems allows one to change name that +is referenced and we have done so, placing the version number into the +shared library (i.e. libfoo.so.0.1). At link time, one would reference +libfoo.so, but when one executes the program, the shared library loader +would then look for the shared library with the alternate name. Hence +multiple versions of shared libraries may be supported relatively +easily. @footnote{Under AIX for the RISC/6000, multiple versions of +shared libraries are supported by combining two or more versions of the +shared library into one file. The Kerberos build procedure produces +shared libraries with version numbers in the internal module names, so +that the shared libraries are compatible with this scheme. +Unfortunately, combining two shared libraries requires internal +knowledge of the AIX shared library system beyond the scope of this +document. Practically speaking, only one version of AIX shared libraries +can be supported on a system, unless the multi-version library is +constructed by a programmer familiar with the AIX internals.} + +All operating systems (that we have seen) provide a means for programs +to specify the location of shared libraries. On different operating +systems, this is either specified when creating the shared library, and +link time, or both.@footnote{Both are necessary sometimes as the shared +libraries are dependent on other shared libraries.} The build process +will hardwire a path to the installed destination. + +@node Advanced Shared Library Requirements, Operating System Notes for Shared Libraries, Shared Library Theory, Shared Libraries +@section Advanced Shared Library Requirements + +In order to better support some multithreading models, and permit the +libraries to clean up internally maintained caches of information, +we've imposed new requirements on the OS shared library support. + +Specifically, we want the ability to run certain bits of code in a +thread-safe manner at library load time, on multithreading platforms +not supporting @code{pthread_once}, and we want the ability to run +cleanup code when the library is unloaded. + +In general, where platforms have initialization functions, we don't +always get an opportunity to return an error from them. However, the +system functions we call can return errors. So a framework has been +built that attempts to combine the @code{pthread_once} and load-time +initialization approaches, and add the ability to store an error code +indicating success or failure of the initialization routine. + +The main implementation of this framework is in @file{k5-platform.h}. +Some additional information, specifically the names of the +initialization and finalization functions, are stored in the makefiles +used to generate each of the UNIX libraries, in @file{win_glue.c}, and +somewhere in the Mac OS X support (XXX not added yet?). How the +information is used depends on the platform: + +@itemize @bullet + +@item +On platforms without any thread support, a simple flag is used, on the +assumption that the library code will have sole control over the +process execution until the initialization function returns. (It's +generally a bad idea to call any ``interesting'' function like +@code{longjmp} or Kerberos functions from signal handlers; now it's a +slightly worse idea.) + +@item +On platforms supporting @code{pthread_once}, library initialization is +generally delayed until the point where the library code needs to +verify that the initialization succeeded. If @code{pthread_once} may +not have been linked into the executable and we can tell (for example, +with weak symbol references), this is combined with the simple-flag +approach above. + +@item +On Windows, the library initialization function is run from +@file{win_glue.c} at load time; it should complete before the +library's symbol table is made accessible to the calling process. + +Windows note: There are limitations on what @code{DllMain} should do +in the initialization and finalization cases, and unfortunately we've +found that we do some of these things (specifically, calling +@code{WSAStartup} and @code{WSACleanup}, and loading other libraries +which do so also). Until we can rectify this problem, there is a +chance that explicitly unloading an MIT Kerberos library from an +application (more specifically, from within the @code{DllMain} of +another library) may cause a deadlock. +@end itemize + +Library finalization is similarly dependent on the platform and +configuration: + +@itemize @bullet + +@item +In static-library builds, since the library will be unloaded only when +the entire process calls @code{exit} or @code{exec} or otherwise +ceases to exist in its current form, freeing up memory resources in +the process, finalization can be skipped. + +@item +On UNIX platforms with library finalization support in shared +libraries, the (OS-level) finalization function is specified to run +the library's (shim-level) finalization function. If @code{gcc}'s +``destructor'' attribute appears to work, we use that. + +@item +On UNIX platforms without library finalization function support, +the finalization functions won't get called if the library is +unloaded. Resources (probably just memory) will be leaked. + +@item +On Windows, the finalization code is run out of @code{DllMain} in +@file{win_glue.c} at unload time. See the warnings above. + +@end itemize + +If there are other limitations on what operations can be performed in +shared library initialization and finalization routines on some +systems, the MIT Kerberos team would appreciate specific information +on these limitations. + +The internal interface currently used within the code of the Kerberos +libraries consists of four macros: + +@defmac MAKE_INIT_FUNCTION (@var{fname}) +Used at the top level of the file (@i{i.e.}, not within a function), +with a semicolon after it, declares @var{fname}, a function taking no +arguments and returning @code{int}, to be an initialization function. +This macro must be used before the function is declared, and it must +be defined in the current file as: +@example +int @var{fname} (void) @{ ... @} +@end example +This macro may define additional data and function objects, +and will declare @var{fname}, though it may or may not declare +@var{fname} as @code{static}. (Under C rules, the declaration above +is compatible with a declaration of the function as @code{static}, and +@code{static} linkage does apply, as long as the @code{static} declaration +comes first.) + +When the function is invoked, the return value --- zero or an error +code --- will be saved away, and returned any time +@code{CALL_INIT_FUNCTION} is used. + +There can be multiple initialization functions defined this way in a +library. +@end defmac + +@defmac MAKE_FINI_FUNCTION (@var{fname}) +This is similar to @code{MAKE_INIT_FUNCTION} except that @var{fname} +is to be a library finalization function, called when the library is +no longer in use and is being unloaded from the address space. +@example +void @var{fname} (void) @{ ... @} +@end example + +There may be multiple finalization functions defined for a library. +@end defmac + +@deftypefn Macro int CALL_INIT_FUNCTION (@var{fname}) +This macro ensures that the initialization function @var{fname} is +called at this point, if it has not been called already. The macro +returns an error code that indicates success (zero), an error in the +OS support (@i{e.g.}, if @code{pthread_once} returns an error), or an +error returned by the initialization function. + +Currently, all uses of @code{CALL_INIT_FUNCTION} must be in the same +file as the use of @code{MAKE_INIT_FUNCTION}, and must come after it. +@end deftypefn + +@deftypefn Macro int INITIALIZER_RAN (@var{fname}) +This macro returns non-zero iff the initialization function designated +by @var{fname} (and previously declared in the current file with +@code{MAKE_INIT_FUNCTION}) has been run, and returned no error +indication. + +Since the finalization function might always be invoked through linker +support and initialization functions only sometimes invoked via +@code{pthread_once} in other functions that may not ever be called, +finalization functions should check whether the objects to be +destroyed have actually been created. This macro provides one way of +doing that. +@end deftypefn + +The @file{Makefile.in} for the library must define two variables, +@code{LIBINITFUNC} and @code{LIBFINIFUNC}, containing a (possibly +empty) list of the names of the initialization and finalization +functions for the library as built under UNIX, ordered from +lowest-level (initialized first, finalized last) to highest-level. +(Windows and Mac OS X builds work differently.) + +Note that all of this assumes shared libraries. If static linking is +done, our options are a bit more limited. We assume +@code{pthread_once} is available if there is any thread support +(@i{i.e.}, we don't support static linking on Windows), and we assume +that finalization code would be called only when the process is +exiting, at which point all resources should be freed up anyways, so +it doesn't really matter whether our cleanup code gets called. In +fact, it should be more efficient if it does not. + +While one of our goals is to be able to repeatedly load, use, and +unload the MIT Kerberos libraries under a plugin architecture without +memory or other resource leaks, the main goal was to provide hooks +through which the library threading support could be properly +initialized on various platforms. The hooks we've added should be +sufficient for each library to free up any internal caches of +information at unload time, and we have added some of that support, +but it is not complete at this time. + + +We have also started limiting the list of exported symbols from shared +libraries on some UNIX platforms, and intend to start doing symbol +versioning on platforms that support it. The symbol lists we use for +UNIX at the moment are fairly all-inclusive, because we need more +symbols exported than are in the lists used for Windows and Mac +platforms, and we have not yet narrowed them down. The current lists +should not be taken as an indication of what we intend to export and +support in the future; see @file{krb5.h} for that. + +The export lists are stored in the directories in which each UNIX +library is built, and the commands set up at configuration time by +@file{shlib.conf} can specify any processing to be done on those files +(@i{e.g.}, insertion of leading underscores or linker command-line +arguments). + +For some systems with somewhat non-trivial commands that need to be +run to convert the export list into the proper form, file targets can be +defined in @file{config/lib.in}. + +@node Operating System Notes for Shared Libraries, , Advanced Shared Library Requirements, Shared Libraries +@section Operating System Notes for Shared Libraries + +From time to time users or developers suggest using GNU @code{Libtool} +or some other mechanism to generate shared libraries. Experience +with other packages suggests that Libtool tends to be difficult to +debug and when it works incorrectly, patches are required to generated +scripts to work around problems. So far, the Kerberos shared library +build mechanism, which sets a variety of makefile variables based on +operating system type and then uses those variables in the build +process has proven to be easier to debug and adequate to the task of +building shared libraries for Kerberos. + +@menu +* AIX Shared Library Support:: +* Alpha OSF/1 Shared Library Support:: +@end menu + +@node AIX Shared Library Support, Alpha OSF/1 Shared Library Support, Operating System Notes for Shared Libraries, Operating System Notes for Shared Libraries +@subsection AIX Shared Library Support + + AIX specifies shared library versions by combining multiple +versions into a single file. Because of the complexity of this process, +no automatic procedure for building multi-versioned shared libraries is +provided. Therefore, supporting multiple versions of the Kerberos shared +libraries under AIX will require significant work on the part of a +programmer famiiliar with AIX internals. + + AIX allows a single library to be used both as a static library +and as a shared library. For this reason, the @samp{--enable-shared} +switch to configure builds only shared libraries. On other operating +systems, both shared and static libraries are built when this switch is +specified. As with all other operating systems, only non-shared static +libraries are built when @samp{--enable-shared} is not specified. + + The AIX 3.2.5 linker dumps core trying to build a shared +@samp{libkrb5.a} produced with the GNU C compiler. The native AIX +compiler works fine. In addition, the AIX 4.1 linker is able to build a +shared @samp{libkrb5.a} when GNU C is used. + + +@node Alpha OSF/1 Shared Library Support, , AIX Shared Library Support, Operating System Notes for Shared Libraries +@subsection Alpha OSF/1 Shared Library Support + +Shared library support has been tested with V2.1 and higher of the +operating system. Shared libraries may be compiled both with GCC and the +native compiler. + +One of the nice features on this platform is that the paths to the +shared libraries is specified in the library itself without requiring +that one specify the same at link time. + +We are using the @samp{-rpath} option to @samp{ld} to place the library +load path into the executables. The one disadvantage of this is during +testing where we want to make sure that we are using the build tree +instead of a possibly installed library. The loader uses the contents of +@samp{-rpath} before LD_LIBRARY_PATH so we must specify a dummy _RLD_ROOT +and complete LD_LIBRARY_PATH in our tests. + +The one disadvantage with the method we are using.... + +@node Porting Issues, , Shared Libraries, Top +@chapter Porting Issues + +[Snipped from email from Ken Raeburn in reply to email asking about +porting MIT Kerberos to pSOS; maybe it'll be of use to someone else.] + +> - Any Porting issues to be considered? + +Yes. Our build procedure currently assumes that the machine used for +building is either a UNIX (or similar) system, or running Windows; it +also assumes that it's a native compilation, not a cross compilation. +I'm not familiar with pSOS, but assuming that you do cross compilation +on another OS, how you deal with that depends on the host system. + +UNIX host: The configure script attempts to learn a bunch of +attributes about the host system (program names, availability of +header files and functions and libraries) and uses them to decide how +to build the krb5 libraries and programs. Many attributes are tested +by running the compiler with various options and test source files, so +if you tell the configure script to run a cross compiler, it may come +up with most of the right answers, if you can arrange for success and +failure indications to be given at compile/link time. (This probably +wouldn't work well for VxWorks, for example, where symbol resolution +is done when the object code is loaded into the OS.) + +The configure script generates include/autoconf.h to influence +whether certain calls are made or certain headers are included, and +Makefile in each directory to indicate compilation options. Each +source directory has a Makefile.in, and config/pre.in and +config/post.in are incorporated into each generate Makefile. Various +@@FOO@@ sequences are substituted based on the system attributes or +configure options. (Aside from always using the config/ fragments, +this is typical of GNU Autoconf based software configuration.) + +Windows host: The ``wconfig'' program generates the Makefiles in +subdirectories, with config/win-pre.in and config/win-post.in used in +combination with each Makefile.in, and lines starting @code{##WIN32##} +are uncommented, but @code{@@FOO@@} substitutions are not done. +Instead of generating @file{autoconf.h}, it's copied from +@file{include/win-mac.h}, where we've hardcoded some of the parameters +we care about, and just left a bunch of others out. If you work with +a Windows host, you may want to provide your own makefile fragments, +and a replacement for @file{win-mac.h} or some additional data to go +into it conditionalized on some preprocessor symbol for pSOS. + +There are also places where we assume that certain header files or +functions are available, because both (most) UNIX and Windows +platforms (that we care about currently) provide them. And probably a +handful of places where we check for @code{_WIN32} to decide between ``the +Windows way'' and ``everything else'' (i.e., UNIX); you might need to add +a third branch for pSOS. And some places where we've got hooks for +Kerberos for Mac support, which you can probably ignore. + +Our build environment assumes that Perl is available, but it's only +needed in the build process, not for run time. If Tcl is available, +on UNIX, a few more programs may be built that are used for testing +some interfaces, but a cross compiler should notice that it can't link +against the native Tcl libraries, and configure should choose not to +build those programs. + +In the current 1.4 beta code, our library wants to find routines for +making DNS queries (SRV and TXT RR queries specifically) that are +outside the scope of getaddrinfo and friends. We also look for +@file{/dev/random} as a strong random number source, and text files +for configuration information. Our code assumes that allocating and +reallocating lots of little (or not so little) bits of memory isn't +too horribly expensive, and we don't take any special pains to keep +our stack size small. Depending how pSOS works, you may need to add +to the thread support code. (The MIT code doesn't create threads, but +will do locking and such to allow multiple threads to share global +data. The code in @file{include/k5-thread.h} is, uh, kind of +involved, and some pains have been taken to use macros whenever +possible to allow @code{assert()} calls during debugging to report +useful line numbers.) There are probably other minor issues to deal +with, I'm just making some guesses. + +> - what type of Data formats exchanged between Client and Server? + +If you're aiming for a server implementation only, it'll depend on the +exact protocol you wish to use, but typically the Kerberos application +server needs to accept the AP-REQ message and generate the AP-REP +message. Protection for the data to be transferred depends on on the +application protocol. For example, Kerberos provides some message +types for encapsulating application data with or without encryption; +the Kerberos mechanism for GSSAPI uses the Kerberos session key to +protect application data in a different message format. + +The server implementation would also need some secure means of getting +the service principal's key stored away. + +If you want client code support as well under pSOS, then you may have +to deal with DNS queries to find the KDC, +AS-REQ/AS-REP/TGS-REQ/TGS-REP message exchanges, and generating AP-REQ +and accepting AP-REP messages, etc. + +@contents +@bye diff --git a/krb5-1-6/doc/install-old.texi b/krb5-1-6/doc/install-old.texi new file mode 100644 index 000000000..af84a023e --- /dev/null +++ b/krb5-1-6/doc/install-old.texi @@ -0,0 +1,2239 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename install.info +@settitle Kerberos V5 +@c For double-sided printing, uncomment: +@setchapternewpage odd +@c %**end of header + +@set EDITION BETA 6 +@set VERSION BETA 6 +@set UPDATED Mar 20, 1996 + +@ignore +@iftex +@finalout +@end iftex +@end ignore + +@ifinfo +This file documents how to build and install the Kerberos V5 +distribution. + +Copyright (C) 1995, 1996 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 any necessary licenses 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. + +Athena(r), Hesiod(r), Moira(r), and Discuss(r) are registered trademarks of +the Massachusetts Institute of Technology (MIT). Project Athena, Athena +Dashboard, Athena MUSE, Kerberos, X Window System, and Zephyr are trademarks +of MIT. No commercial use of these trademarks may be made without prior +written permission of MIT. + +All other product names are trademarks of their respective companies. + +@end ifinfo + +@titlepage +@title Kerberos V5 +@subtitle Notes on Building and Installing Kerberos +@subtitle Edition @value{EDITION}, for Kerberos version @value{VERSION} +@subtitle @value{UPDATED} +@author by Theodore Ts'o + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1995, 1996 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 any necessary licenses 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. + +Athena(r), Hesiod(r), Moira(r), and Discuss(r) are registered trademarks of +the Massachusetts Institute of Technology (MIT). Project Athena, Athena +Dashboard, Athena MUSE, Kerberos, X Window System, and Zephyr are trademarks +of MIT. No commercial use of these trademarks may be made without prior +written permission of MIT. + +All other product names are trademarks of their respective companies. + +@end titlepage + +@node Top, Introduction, (dir), (dir) +@comment node-name, next, previous, up + +@ifinfo +This file documents how to build and install the Kerberos V5 +distribution. + +This is edition @value{EDITION}, for Kerberos V5 version @value{VERSION}. + +@end ifinfo + +@c The master menu is updated using emacs19's M-x texinfo-all-menus-update +@c function. Don't forget to run M-x texinfo-every-node-update after +@c you add a new section or subsection, or after you've rearranged the +@c order of sections or subsections. Also, don't forget to add an @node +@c command before each @section or @subsection! All you need to enter +@c is: +@c +@c @node New Section Name + +@c @section New Section Name +@c +@c M-x texinfo-every-node-update will take care of calculating the +@c node's forward and back pointers. +@c + +@menu +* Introduction:: +* How Kerberos Works:: +* Building Kerberos:: +* Installation:: +* Troubleshooting:: + + --- The Detailed Node Listing --- + +How Kerberos Works: A Schematic Description + +* Network Services:: +* Kerberos Tickets:: +* The Kerberos Database:: +* Kerberos Realms:: +* The Ticket-Granting Ticket:: +* Network Services and the Master Database:: +* The User-Kerberos Interaction:: + +Network Services and the Master Database + +* The Keytab File:: + +Building Kerberos + +* Build Requirements:: How much disk space, etc. you need to + build Kerberos. +* Unpacking the Sources:: Preparing the source tree. +* Doing the Build:: Compiling Kerberos. +* Testing the Build:: Making sure Kerberos built correctly. +* Options to Configure:: +* osconf.h:: +* Shared Library Support:: +* OS Incompatibilities:: Special cases to watch for. +* Using Autoconf:: Modifying Kerberos V5's + configuration scripts. + +Doing the Build + +* Building Within a Single Tree:: +* Building with Separate Build Directories:: +* Building using lndir:: + +Testing the Build + +* The DejaGnu Tests:: + +Shared Library Support + +* Shared Library Theory:: +* NetBSD Shared Library Support:: +* AIX Shared Library Support:: +* Solaris 5.3 Shared Library Support:: +* Alpha OSF/1 Shared Library Support:: + +Operating System Incompatibilities + +* Ultrix 4.2/3:: +* Alpha OSF/1 V1.3:: +* Alpha OSF/1 V2.0++:: +* BSDI:: +* Solaris versions 2.0 through 2.3:: +* Solaris 2.X:: +* SGI Irix 5.X:: + +Installation + +* Background:: +* Installation on any Machine:: +* Installing the KDC:: +* Migrating from V4 to V5 Kerberos:: +* A Sample Application:: +* Installing Kerberos Applications:: +* Common Kerberos Service Names:: + +Installation on any Machine + +* Picking a Realm Name:: +* Configuration files:: +* Recommended Programs:: + +Configuration files + +* krb5.conf:: +* Converting V4 configuration files:: +* /etc/services:: + +Installing the KDC + +* kdc.conf:: +* Initializing the KDB:: +* Storing the Master Password:: +* Adding Users to the Database:: +* Starting the Kerberos Server:: +* Setting up Slave Kerberos Servers:: +* Inter-realm Kerberos Operation:: +* The Administration Server:: +* Testing the Kerberos Server:: + +Setting up Slave Kerberos Servers + +* Kerberos Slave Database Propagation:: +* Installing a Slave Server:: + +A Sample Application + +* Installing the Sample Application:: +* Testing the Sample Server:: + +Installing Kerberos Applications + +* Levels of Security:: +* Preparing a Workstation for Kerberos Application Servers:: +* BSD Utilities:: +* Telnet and FTP:: + +BSD Utilities + +* Checksums:: Checksum facility for dealing with active attacks. +* BSD Utility Configuration Example:: Sample @file{inetd.conf} entries for BSD utilities. +@end menu + +@node Introduction, How Kerberos Works, Top, Top +@chapter Introduction + +This document describes the procedures necessary to compile Kerberos V5 +from the source distribution, and then to install it at a particular +site. The reader is assumed to be familiar with C/UNIX development +tools. + +In any complex software, there will be bugs. Please send bug reports +or other problems you may uncover to the e-mail address +@b{krb5-bugs@@mit.edu}. Please mention which version of the Kerberos +V5 distribution you are using, and whether you have made any private +changes. Bug reports that include proposed fixes are especially +welcome. If you do include fixes, please send them using either +context diffs or unified diffs (using @samp{diff -c} or @samp{diff +-u}, respectively). + +Please note that there are still a number of aspects of Kerberos V5 +which will likely change before the 1.0 release. +As these changes occur, we will update the documentation accordingly. + +@c As of this release, all the databases, including the aname to localname +@c ones now use version 1.85 of the Berkeley DB code. This may imply +@c database conversions for those running earlier releases of Kerberos +@c V5. We recommend that you dump your database with the old kdb5_edit and +@c restore with the new one. + + +@node How Kerberos Works, Building Kerberos, Introduction, Top +@chapter How Kerberos Works: A Schematic Description + +This section provides a simplified description of a general user's +interaction with the Kerberos system. This interaction happens +transparently--users don't need to know and probably don't care about +what's going on--but Kerberos administrators might find a schematic +description of the process useful. This description glosses over a lot +of details; for more information, see @i{Kerberos: An Authentication +Service for Open Network Systems}, a paper presented at Winter USENIX +1988, in Dallas, Texas. + +@menu +* Network Services:: +* Kerberos Tickets:: +* The Kerberos Database:: +* Kerberos Realms:: +* The Ticket-Granting Ticket:: +* Network Services and the Master Database:: +* The User-Kerberos Interaction:: +@end menu + +@node Network Services, Kerberos Tickets, How Kerberos Works, How Kerberos Works +@section Network Services and Their Client Programs + +In an environment that provides network services, you use @dfn{client} +programs to request service from @dfn{server} programs that are +somewhere on the network. Suppose you have logged in to a workstation +and you want to @samp{rlogin} to another machine. You use the local +@samp{rlogin} client program to contact the remote machine's +@samp{rlogind} daemon. + +@node Kerberos Tickets, The Kerberos Database, Network Services, How Kerberos Works +@section Kerberos Tickets + +Under Kerberos, the @samp{rlogind} daemon allows you to login to a +remote machine if you can provide @samp{rlogind} a Kerberos ticket +which proves your identity. In addition to the ticket, you must also +have possession of the corresponding ticket session key. The +combination of a ticket and the ticket's session key is known as a credential. + +Typically, a client program automatically obtains credentials +identifying the person using the client program. The credentials are +obtained from a Kerberos server that resides somewhere on the network. +A Kerberos server maintains a database of user, server, and password +information. + +@node The Kerberos Database, Kerberos Realms, Kerberos Tickets, How Kerberos Works +@section The Kerberos Database + +Kerberos will give you credentials only if you have an entry in the Kerberos +server's @dfn{Kerberos database}. Your database entry includes your +Kerberos @dfn{principal} (which is often just your username), and +your Kerberos password. Every Kerberos user must have an entry in this +database. + +@node Kerberos Realms, The Ticket-Granting Ticket, The Kerberos Database, How Kerberos Works +@section Kerberos Realms + +Each site (or administrative domain within a site) will have their own +Kerberos database, which contains information about the users and +services for that particular site or administrative domain. +A @dfn{Kerberos Realm} is used to distinguish the users and services in +one particular area of administrative control from another area of +administrative control. + +Each Kerberos realm will have at least one Kerberos server, where the +master Kerberos database for that site or administrative domain is +stored. A Kerberos realm may also have one or more @dfn{slave servers}, +which have read-only copies of the Kerberos database which are +periodically propagated from the master server. For more details on how +this is done, see @ref{Setting up Slave Kerberos Servers}. + +@node The Ticket-Granting Ticket, Network Services and the Master Database, Kerberos Realms, How Kerberos Works +@section The Ticket-Granting Ticket + +The @samp{kinit} command prompts for your password, and if you enter +it successfully, you will obtain a @dfn{ticket-granting ticket} and a +@dfn{ticket session key} which gives you the right to use the ticket. +This combination of the ticket and its associated key is also known as +your @dfn{credentials}. As illustrated below, client programs use +your ticket-granting ticket credentials in order to obtain +client-specific credentials as needed. + +Your credentials are stored in a @dfn{credentials cache}, which is often +simply just a file in @file{/tmp}. The credentials cache is also +referred to as the @dfn{ticket file}, especially in Kerberos V4 +documentation. It should be noted, however, that a credentials cache +does not have to be stored in a file. + +@node Network Services and the Master Database, The User-Kerberos Interaction, The Ticket-Granting Ticket, How Kerberos Works +@section Network Services and the Master Database + +The master database also contains entries for all network services that +require Kerberos authentication. Suppose that your site +has a machine, @samp{laughter.mit.edu}, that requires Kerberos +authentication from anyone who wants to @samp{rlogin} to it. The host's +Kerberos realm is @samp{ATHENA.MIT.EDU}. + +This service must be registered in the Kerberos database, using the +proper service name, which in this case is +@samp{host/laughter.mit.edu@@ATHENA.MIT.EDU}. The @kbd{/} character +separates the various @dfn{components} of the Kerberos principal; the +@kbd{@@} character separates the realm name from the rest of the +principal name. The first component, @samp{host}, denotes the name or +type of the service that is being offered: generic host-level access to +the machine. The second component, @samp{laughter.mit.edu}, names the +specific machine which is offering this service. There will generally +be many different machines, each offering one particular type of +service, and the second component serves to give each one of these +servers a different Kerberos name. + +@menu +* The Keytab File:: +@end menu + +@node The Keytab File, , Network Services and the Master Database, Network Services and the Master Database +@subsection The Keytab File + +For each service, there must also be a @dfn{service key} known only by +Kerberos and the service. On the Kerberos server, the service key is +stored in the Kerberos database. + +On the server host, these service keys are stored in the @dfn{Key +tables}, or @dfn{keytab files}. (Keytab files were previously +referred to as @dfn{srvtab files} in the V4 literature.) The service +keys that are used by services which run as root are often stored in +the file @file{/etc/v5srvtab}. + +@b{WARNING:} This service key is the equivalent of the service's +password, and must be kept secure. Data which is meant to be read only +by the service is encrypted using this key. + +@node The User-Kerberos Interaction, , Network Services and the Master Database, How Kerberos Works +@section The User--Kerberos Interaction + +Suppose that you (in the guise of a general user) walk up to a workstation +intending to login to it, and then @samp{rlogin} to the machine @samp{laughter}. +Here's what happens: + +@enumerate + +@item +You login to the workstation and use the @samp{kinit} command +to get a ticket-granting ticket. +This command prompts you for your Kerberos password. (On some systems +which have a modified @samp{/bin/login} program, this may be done as +part of the login process, not requiring the user to run a separate +program.) + +@enumerate A + +@item +The @samp{kinit} command sends your request to the Kerberos master +server machine. The server software looks for your principal name's +entry in the Kerberos database. + +@item +If this entry exists, the Kerberos server creates and returns a +ticket-granting ticket and the key which allows you to use it, encrypted +by your password. If @samp{kinit} can decrypt the Kerberos reply using +the password you provide, it stores this ticket in a credentials cache +on your local machine for later use. The name of the credentials cache +can be specified in the @samp{KRB5_CCNAME} environment variable. If +this variable is not set, the name of the file will be +@file{/tmp/krb5cc_}, where is your UNIX user-id, represented +in decimal format. +@end enumerate + +@item +Now you use the @samp{rlogin} client to access the machine +@samp{laughter}. + +@example +host% @b{rlogin laughter} +@end example + +@enumerate A + +@item +The @samp{rlogin} client checks your ticket file to see if you +have a ticket for the @samp{host} service for @samp{laughter}. +You don't, so @samp{rlogin} uses the credential cache's ticket-granting +ticket to make a request to the master server's ticket-granting service. + +@item +This ticket-granting service receives the +@samp{host/laughter.mit.edu} request and looks in the master database +for an @samp{host/laughter.mit.edu} entry. If the entry exists, the +ticket-granting service issues you a ticket for that service. That +ticket is also cached in your credentials cache. + +@item +The @samp{rlogin} client now sends that ticket to +the @samp{laughter} @samp{rlogind} service program. The service program +checks the ticket by using its own service key. If the ticket is valid, +it now knows your identity. If the ticket is valid and you are allowed +to login to @samp{laughter} (because the your name matches one in +/etc/passwd, or you are in the @file{.k5login} file), you will find +yourself logged into the machine. + +@end enumerate +@end enumerate + +@node Building Kerberos, Installation, How Kerberos Works, Top +@chapter Building Kerberos + +Starting with the Beta 4 distribution, we are using a new configuration +system, which was built using the Free Software Foundation's +@samp{autoconf} program. This system will hopefully make Kerberos V5 +much simpler to build and reduce the amount of effort required in +porting Kerberos V5 to a new platform. + +@menu +* Build Requirements:: How much disk space, etc. you need to + build Kerberos. +* Unpacking the Sources:: Preparing the source tree. +* Doing the Build:: Compiling Kerberos. +* Testing the Build:: Making sure Kerberos built correctly. +* Options to Configure:: +* osconf.h:: +* Shared Library Support:: +* OS Incompatibilities:: Special cases to watch for. +* Using Autoconf:: Modifying Kerberos V5's + configuration scripts. +@end menu + +@node Build Requirements, Unpacking the Sources, Building Kerberos, Building Kerberos +@section Build Requirements + +In order to build Kerberos V5, you will need approximately 60-70 +megabytes of disk space. The exact amount will vary depending on the +platform and whether the distribution is compiled with debugging symbol +tables or not. + +If you wish to keep a separate @dfn{build tree}, which contains the compiled +@file{*.o} file and executables, separate from your source tree, you +will need a @samp{make} program which supports @samp{VPATH}, or +you will need to use a tool such as @samp{lndir} to produce a symbolic +link tree for your build tree. + +@node Unpacking the Sources, Doing the Build, Build Requirements, Building Kerberos +@section Unpacking the Sources + +The first step in each of these build procedures is to unpack the source +distribution. The Kerberos V5 distribution comes in two compressed tar +files. The first file, which is generally named @file{krb5.src.tar.gz}, +contains the sources for all of Kerberos except for the crypto library, +which is found in the file @file{krb5.crypto.tar.gz}. + +Both files should be unpacked in the same directory, such as +@file{/u1/krb5}. (In the rest of this document, we will assume that you +have chosen to unpack the Kerberos V5 source distribution in this +directory.) + + +@node Doing the Build, Testing the Build, Unpacking the Sources, Building Kerberos +@section Doing the Build + +You have a number of different options in how to build Kerberos. If you +only need to build Kerberos for one platform, using a single directory +tree which contains both the source files and the object files is the +simplest. However, if you need to maintain Kerberos for a large number +of platforms, you will probably want to use separate build trees for +each platform. We recommend that you look at see @ref{OS +Incompatibilities} for notes that we have on particular operating +systems. + +@menu +* Building Within a Single Tree:: +* Building with Separate Build Directories:: +* Building using lndir:: +@end menu + +@node Building Within a Single Tree, Building with Separate Build Directories, Doing the Build, Doing the Build +@subsection Building Within a Single Tree + +If you don't want separate build trees for each architecture, then +use the following abbreviated procedure. + +@enumerate +@item + @code{cd /u1/krb5/src} +@item + @code{./configure} +@item + @code{make} +@end enumerate + +That's it! + +@node Building with Separate Build Directories, Building using lndir, Building Within a Single Tree, Doing the Build +@subsection Building with Separate Build Directories + +If you wish to keep separate build directories for each platform, you +can do so using the following procedure. (Note, this requires that your +@samp{make} program support @samp{VPATH}. GNU's make will provide this +functionality, for example.) If your @samp{make} program does not +support this, see the next section. + +For example, if you wish to create a build directory for @code{pmax} binaries +you might use the following procedure: + +@enumerate +@item +@code{mkdir /u1/krb5/pmax} +@item + @code{cd /u1/krb5/pmax} +@item + @code{../src/configure} +@item + @code{make} +@end enumerate + +@node Building using lndir, , Building with Separate Build Directories, Doing the Build +@subsection Building Using @samp{lndir} + +If you wish to keep separate build directories for each platform, and +you do not have access to a @samp{make} program which supports @samp{VPATH}, +all is not lost. You can use the @samp{lndir} program to create +symbolic link trees in your build directory. + +For example, if you wish to create a build directory for solaris binaries +you might use the following procedure: + +@enumerate +@item + @code{mkdir /u1/krb5/solaris} +@item + @code{cd /u1/krb5/solaris} +@item + @code{/u1/krb5/src/util/lndir `pwd`/../src} +@item + @code{./configure} +@item + @code{make} +@end enumerate + +You must give an absolute pathname to @samp{lndir} because it has a bug that +makes it fail for relative pathnames. Note that this version differs +from the latest version as distributed and installed by the XConsortium +with X11R6. Either version should be acceptable. + +@node Testing the Build, Options to Configure, Doing the Build, Building Kerberos +@section Testing the Build + +The Kerberos V5 distribution comes with built-in regression tests. To +run them, simply type the following command while in the top-level build +directory (i.e., the directory where you sent typed @samp{make} to start +building Kerberos; see @ref{Doing the Build}.): + +@example +% make check +@end example + +@menu +* The DejaGnu Tests:: +@end menu + +@node The DejaGnu Tests, , Testing the Build, Testing the Build +@subsection The DejaGnu Tests + +Some of the built-in regression tests are setup to use the DejaGnu +framework for running tests. These tests tend to be more comprehensive +than the normal built-in tests as they setup test servers and test +client/server activities. + +DejaGnu may be found wherever GNU software is archived. + +Most of the tests are setup to run as a non-privledged user. There are +two series of tests (@samp{rlogind} and @samp{telnetd}) which require +the ability to @samp{rlogin} as root to the local machine. Admittedly, +this does require the use of a @file{.rhosts} file or some other +authenticated means. @footnote{If you are fortunate enough to have a +previous version of Kerberos V5 or V4 installed, and the Kerberos rlogin +is first in your path, you can setup @file{.k5login} or @file{.klogin} +respectively to allow you access.} + +If you cannot obtain root access to your machine, all the other tests +will still run. Note however, with DejaGnu 1.2, the "untested testcases" +will cause the testsuite to exit with a non-zero exit status which +@samp{make} will consider a failure of the testing process. Do not worry +about this, as these tests are the last run when @samp{make check} is +executed from the top level of the build tree. + + +@node Options to Configure, osconf.h, Testing the Build, Building Kerberos +@section Options to Configure + +There are a number of options to @samp{configure} which you can use to +control how the Kerberos distribution is built. The following table +lists the most commonly used options to Kerberos V5's @samp{configure} +program. + +@table @code + +@item --help + +Provides help to configure. This will list the set of commonly used +options for building Kerberos. + +@item --prefix=DIR + +By default, Kerberos will install the package's files rooted at +`/usr/local' as in `/usr/local/bin', `/usr/local/sbin', etc. If you +desire a different location use this option. + +@item --exec-prefix=DIR + +This option allows one to separate the architecture independent programs +from the configuration files and manual pages. + +@item --with-cc=COMPILER + +Use @code{COMPILER} as the C compiler. + +@item --with-ccopts=FLAGS + +Use @code{FLAGS} as the default set of C compiler flags. + +Note that if you use the native Ultrix compiler on a +DECstation you are likely to lose if you pass no flags to cc; md4.c +takes an estimated 3,469 billion years to compile if you provide neither +the @samp{-g} flag nor the @samp{-O} flag to @samp{cc}. + +@item --with-cppopts=CPPOPTS + +Use @code{CPPOPTS} as the default set of C preprocessor flags. The most +common use of this option is to select certain @code{#define}'s for use +with the operating system's include files. + +@item --with-linker=LINKER + +Use @code{LINKER} as the default loader if it should be different from C +compiler as specified above. + +@item --with-ldopts=LDOPTS + +This option allows one to specify optional arguments to be passed to the +linker. This might be used to specify optional library paths. + +@item --with-krb4 + +This option enables Kerberos V4 backwards compatibility using the +builtin Kerberos V4 library. + +@item --with-krb4=KRB4DIR + +This option enables Kerberos V4 backwards compatibility. The directory +specified by @code{KRB4DIR} specifies where the V4 header files should +be found (@file{/KRB4DIR/include}) as well as where the V4 Kerberos +library should be found (@file{/KRB4DIR/lib}). + +@item --without-krb4 + +Disables Kerberos V4 backwards compatibility. This prevents Kerberos V4 +clients from using the V5 services including the KDC. This would be +useful if you know you will never install or need to interact with V4 +clients. + +@item --with-netlib[=libs] + +Allows for suppression of or replacement of network libraries. By +default, Kerberos V5 configuration will look for @code{-lnsl} and +@code{-lsocket}. If your operating system has a broken resolver library +(see @ref{Solaris versions 2.0 through 2.3}) or fails to pass the tests in +@file{src/tests/resolv} you will need to use this option. + +@item --enable-shared + +This option will turn on the building and use of shared library objects +in the Kerberos build. This option is only supported on certain +platforms. + +@item --with-vague-errors + +If enabled, gives vague and unhelpful error messages to the client... er, +attacker. (Needed to meet silly government regulations; most other +sites will want to keep this undefined.) + +@item --with-kdc-kdb-update + +Set this option if you want to allow the KDC to modify the Kerberos +database; this allows the last request information to be updated, as +well as the failure count information. Note that this doesn't work if +you're using slave servers!!! It also causes the database to be +modified (and thus needing to be locked) frequently. Please note that +the implementors do not regularly test this feature. + +@item --with-kdb-db=database + +The configuration process will try to determine a working set of +libraries required to implement the Kerberos database. Configure will +look for interfaces that use or emulate a @samp{ndbm} or @samp{dbm} +library. Failing that, a build in copy of the Berkeley DB code will be +used. You may decide to compile a different interface than the default +by specifying one of "ndbm", "dbm", or "db". + +An important note on platforms where the @samp{ndbm} implementation is +based on @sc{GDBM} (such as the Linux Slackware distribution). @sc{GDBM} +has its own built in file locking which prevents simultaneous access to +the database from two separate processes in which one wants to modify +the database while the otherone only wants to read. (i.e. the KDC and +administrative servers). In this case, you will need to specify the use +of the Berkeley DB. + +@end table + +For example, in order to configure Kerberos on a Solaris machine using +the @samp{suncc} with the optimizer turned on, run the configure +script with the following options: + +@example +% ./configure --with-cc=suncc --with-ccopts=-O +@end example + +@node osconf.h, Shared Library Support, Options to Configure, Building Kerberos +@section @file{osconf.h} + +There is one configuration file which you may wish to edit to control +various compile-time parameters in the Kerberos distribution: +@file{include/stock/osconf.h}. The list that follows is by no means +complete, just some of the more interesting variables. + +Please note: The former configuration file @file{config.h} no longer +exists as its functionality has been merged into the auto-configuration +process. @xref{Options to Configure}. + + +@table @code + +@item DEFAULT_PROFILE_PATH + +The pathname to the file which contains the profiles for the known +realms, their KDCs, etc. + +The profile file format is no longer the same format as Kerberos V4's +@file{krb.conf} file. + +@item DEFAULT_LNAME_FILENAME + +The pathname to the database that maps authentication names to local +account names. See kdb5_anadd(8). + +@item DEFAULT_KEYTAB_NAME + +The type and pathname to the default server keytab file (the equivalent +of Kerberos V4's @file{/etc/srvtab}). + +@item DEFAULT_KDC_ENCTYPE + +The default encryption type for the KDC. + +@item KDCRCACHE + +The name of the replay cache used by the KDC. + +@item RCTMPDIR + +The directory which stores replay caches. + +@item DEFAULT_KDB_FILE + +The location of the default database + +@end table + +@node Shared Library Support, OS Incompatibilities, osconf.h, Building Kerberos +@section Shared Library Support + +Shared library support is provided for a few operating systems. There +are restrictions as to which compiler to use when using shared +libraries. In all cases, executables linked with the shared libraries in +this build process will have built in the location of the libraries, +therefore obliterating the need for special LD_LIBRARY_PATH, et al environment +variables when using the programs. Except where noted, multiple versions +of the libraries may be installed on the same system and continue to +work. + +Currently the supported platforms are: NetBSD 1.0A, AIX 3.2.5, AIX 4.1, +Solaris 5.3, Alpha OSF/1 >= 2.1, HP-UX >= 9.X. + +To enable shared libraries on the above platforms, run the configure +script with the option @samp{--enable-shared}. + +One special note is that if the Kerberos V4 compatibility is compiled +in, you @b{must not} specify an alternate Kerberos V4 library from the +one in the tree or you will be missing references. + +@menu +* Shared Library Theory:: +* NetBSD Shared Library Support:: +* AIX Shared Library Support:: +* Solaris 5.3 Shared Library Support:: +* Alpha OSF/1 Shared Library Support:: +@end menu + +@node Shared Library Theory, NetBSD Shared Library Support, Shared Library Support, Shared Library Support +@subsection Theory of How Shared Libraries are Used + +An explanation of how shared libraries are implemented on a given +platform is too broad a topic for this manual. Instead this will touch +on some of the issues that the Kerberos V5 tree uses to support version +numbering and alternate install locations. + +Normally when one builds a shared library and then links with it, the +name of the shared library is stored in the object +(i.e. libfoo.so). Most operating systems allows one to change name that +is referenced and we have done so, placing the version number into the +shared library (i.e. libfoo.so.0.1). At link time, one would reference +libfoo.so, but when one executes the program, the shared library loader +would then look for the shared library with the alternate name. Hence +multiple versions of shared libraries may be supported relatively +easily. @footnote{Under AIX for the RISC/6000, multiple versions of +shared libraries are supported by combining two or more versions of the +shared library into one file. The Kerberos build procedure produces +shared libraries with version numbers in the internal module names, so +that the shared libraries are compatible with this scheme. +Unfortunately, combining two shared libraries requires internal +knowledge of the AIX shared library system beyond the scope of this +document. Practicallyspeaking, only one version of AIX shared libraries +can be supported on a system, unless the multi-version library is +constructed by a programmer familiar with the AIX internals.} + +All operating systems (that we have seen) provide a means for programs +to specify the location of shared libraries. On different operating +systems, this is either specified when creating the shared library, and +link time, or both.@footnote{Both are necessary sometimes as the shared +libraries are dependent on other shared libraries} The build process +will hardwire a path to the installed destination. + + +@node NetBSD Shared Library Support, AIX Shared Library Support, Shared Library Theory, Shared Library Support +@subsection NetBSD Shared Library Support + +Shared library support has been tested under NetBSD 1.0A using +GCC 2.4.5. Due to the vagaries of the loader in the operating system, +the library load path needs to be specified in building libraries and in +linking with them. Unless the library is placed in a standard location +to search for libraries, this may make it difficult for developers to +work with the shared libraries. + +@node AIX Shared Library Support, Solaris 5.3 Shared Library Support, NetBSD Shared Library Support, Shared Library Support +@subsection AIX Shared Library Support + + AIX specifies shared library versions by combining multiple +versions into a single file. Because of the complexity of this process, +no automatic procedure for building multi-versioned shared libraries is +provided. Therefore, supporting multiple versions of the Kerberos shared +libraries under AIX will require significant work on the part of a +programmer famiiliar with AIX internals. + + AIX allows a single library to be used both as a static library +and as a shared library. For this reason, the @samp{--enable-shared} +switch to configure builds only shared libraries. On other operating +systems, both shared and static libraries are built when this switch is +specified. As with all other operating systems, only non-shared static +libraries are built when @samp{--enable-shared} is not specified. + + The AIX 3.2.5 linker dumps core trying to build a shared +@samp{libkrb5.a} produced with the GNU C compiler. The native AIX +compiler works fine. In addition, the AIX 4.1 linker is able to build a +shared @samp{libkrb5.a} when GNU C is used. + + +@node Solaris 5.3 Shared Library Support, Alpha OSF/1 Shared Library Support, AIX Shared Library Support, Shared Library Support +@subsection Solaris 5.3 Shared Library Support + +Shared library support only works when using the Sunsoft C compiler. We +are currently using version 3.0.1. + +The path to the shared library must be specified at link time as well as +when creating libraries. + +@node Alpha OSF/1 Shared Library Support, , Solaris 5.3 Shared Library Support, Shared Library Support +@subsection Alpha OSF/1 Shared Library Support + +Shared library support has been tested with V2.1 and higher of the +operating system. Shared libraries may be compiled both with GCC and the +native compiler. + +One of the nice features on this platform is that the paths to the +shared libraries is specified in the library itself without requiring +that one specify the same at link time. + +We are using the @samp{-rpath} option to @samp{ld} to place the library +load path into the executables. The one disadvantage of this is during +testing where we want to make sure that we are using the build tree +instead of a possibly installed library. The loader uses the contents of +@samp{-rpath} before LD_LIBRARY_PATH so we must specify a dummy _RLD_ROOT +and complete LD_LIBRARY_PATH in our tests. + +The one disadvantage with the +method we are using + +@node OS Incompatibilities, Using Autoconf, Shared Library Support, Building Kerberos +@section Operating System Incompatibilities + +This section details operating system incompatibilities with Kerberos V5 +which have been reported to the developers at MIT. If you find additional +incompatibilities, and/or discover work arounds to such problems, please +send a report to @b{krb5-bugs@@mit.edu}. Thanks! + +@menu +* Ultrix 4.2/3:: +* Alpha OSF/1 V1.3:: +* Alpha OSF/1 V2.0++:: +* BSDI:: +* Solaris versions 2.0 through 2.3:: +* Solaris 2.X:: +* SGI Irix 5.X:: +@end menu + +@node Ultrix 4.2/3, Alpha OSF/1 V1.3, OS Incompatibilities, OS Incompatibilities +@subsection Ultrix 4.2/3 + +On the DEC MIPS platform, using the native compiler, @file{md4.c} and +@file{md5.c} can not be compiled with the optimizer set at level 1. +That is, you must specify either @samp{--with-ccopts=-O} and +@samp{--with-ccopts=-g} to configure. If you don't specify either, the +compile will never complete. + +The optimizer isn't hung; it just takes an exponentially long time. +Compiling 6 out of the 48 algorithmic steps takes 3 seconds; compiling 7 +steps takes 9 seconds; compiling 8 steps takes 27 seconds, and so on. +Calculations estimate it will finish in approximately 3,469 billion +years.... + +Using GCC instead of the native compiler will also work fine, both with +or without optimization. + +@node Alpha OSF/1 V1.3, Alpha OSF/1 V2.0++, Ultrix 4.2/3, OS Incompatibilities +@subsection Alpha OSF/1 V1.3 + +Using the native compiler, compiling with the @samp{-O} compiler flag +causes the @code{asn.1} library to be compiled incorrectly. + +Using GCC version 2.6.3 or later instead of the native compiler will also work +fine, both with or without optimization. + +@node Alpha OSF/1 V2.0++, BSDI, Alpha OSF/1 V1.3, OS Incompatibilities +@subsection Alpha OSF/1 V2.0++ + +There used to be a bug when using the native compiler in compiling +@file{md4.c} when compiled without either the @samp{-O} or @samp{-g} +compiler options. We have changed the code and there is no problem +under V2.1, but we do not have access to V2.0 to test and see if the +problem would exist there. (We welcome feedback on this issue). There +was never a problem in using GCC version 2.6.3. + +In version 3.2 and beyond of the operating system, we have not seen any +problems with the native compiler. + +@node BSDI, Solaris versions 2.0 through 2.3, Alpha OSF/1 V2.0++, OS Incompatibilities +@subsection BSDI + +BSDI versions 1.0 and 1.1 reportedly has a bad @samp{sed} which causes +it to go into an infinite loop during the build. The work around is +to use a @samp{sed} from somewhere else, such as GNU. (This may be +true for some versions of other systems derived from BSD 4.4, such as +NetBSD and FreeBSD.) + +@node Solaris versions 2.0 through 2.3, Solaris 2.X, BSDI, OS Incompatibilities +@subsection Solaris versions 2.0 through 2.3 + +The @code{gethostbyname()} routine is broken; it does not return a fully +qualified domain name, even if you are using the Domain Name Service +routines. Since Kerberos V5 uses the fully qualified domain name as the +second component of a service principal (i.e, +@samp{host/tsx-11.mit.edu@@ATHENA.MIT.EDU}), this causes problems for servers +who try to figure out their own fully qualified domain name. + +Workarounds: + +@enumerate + +@item + Supply your own resolver library. (such as bind-4.9.3pl1 availavle +from ftp.vix.com) + +@item + Upgrade to Solaris 2.4 + +@item + Make sure your /etc/nsswitch.conf has `files' before `dns' like: + +@example +hosts: files dns +@end example + +and then in /etc/hosts, make sure there is a line with your +workstation's IP address and hostname, with the fully qualified domain +name first. Example: + +@example +18.172.1.4 dcl.mit.edu dcl +@end example + +Note that making this change may cause other programs in your +environment to break or behave differently. + +@end enumerate + +@node Solaris 2.X, SGI Irix 5.X, Solaris versions 2.0 through 2.3, OS Incompatibilities +@subsection Solaris 2.X + +You @b{must} compile Kerberos V5 without the UCB compatibility +libraries. This means that @file{/usr/ucblib} must not be in the +LD_LIBRARY_PATH environment variable when you compile it. Alternatively +you can use the @code{-i} option to @samp{cc}, by using the specifying +@code{--with-ccopts=-i} option to @samp{configure}. + +@node SGI Irix 5.X, , Solaris 2.X, OS Incompatibilities +@subsection SGI Irix 5.X + +If you are building in a tree separate from the source tree, the vendors +version of make does not work properly with regards to +@samp{VPATH}. It also has problems with standard inference rules in 5.2 +(not tested yet in 5.3) so one needs to use GNU's make. + +Under 5.2, there is a bug in the optional System V @code{-lsocket} +library in which the routine @code{gethostbyname()} is broken. The +system supplied version in @code{-lc} appears to work though so one may +simply specify @code{--with-netlib} option to @samp{configure}. + +In 5.3, @code{gethostbyname()} is no longer present in @code{-lsocket} and +is no longer an issue. + +@node Using Autoconf, , OS Incompatibilities, Building Kerberos +@section Using @samp{Autoconf} + +(If you are not a developer, you can skip this section.) + +In most of the Kerberos V5 source directories, there is a +@file{configure} script which automatically determines the compilation +environment and creates the proper Makefiles for a particular platform. +These @file{configure} files are generated using @samp{autoconf} version +2.4, which can be found in the @file{src/util/autoconf} directory in the +distribution. + +Normal users will not need to worry about running @samp{autoconf}; the +distribution comes with the @file{configure} files already prebuilt. +Developers who wish to modify the @file{configure.in} files should see +@ref{Top, , Overview, autoconf, The Autoconf Manual}. + +Note that in order to run @samp{autoconf}, you must have GNU @samp{m4} +in your path. Before you use the @samp{autoconf} in the Kerberos V5 +source tree, you may also need to run @samp{configure}, and then run +@samp{make} in the @file{src/util/autoconf} directory in order to +properly set up @samp{autoconf}. + +One tool which is provided for the convenience of developers can be +found in @file{src/util/reconf}. This program should be run while the +current directory is the top source directory. It will automatically +rebuild any @file{configure} files which need rebuilding. If you know +that you have made a change that will require that all the +@file{configure} files need to be rebuilt from scratch, specify the +@code{--force} option: + +@example +% cd /u1/krb5/src +% ./util/reconf --force +@end example + +The developmental sources are a raw source tree (before it's been packaged +for public release), without the pre-built @file{configure} files. +In order to build from such a source tree, you must do: + +@example +% cd krb5/util/autoconf +% ./configure +% make +% cd ../.. +% util/reconf +@end example + +Then follow the instructions for building packaged source trees (above). +To install the binaries into a binary tree, do: + +@example +% cd /u1/krb5/src +% make all +% make install DESTDIR=somewhere-else +@end example + +@node Installation, Troubleshooting, Building Kerberos, Top +@chapter Installation + +When you are installing Kerberos for the first time at a site, you must +first decide on the realm name you will use for your site, and select a +machine to host the @dfn{Kerberos server}, which is also known as the +@dfn{KDC} (@dfn{Key Distribution Center}). The KDC must be located on a +secure machine, since its database contains the keys for the entire +realm. It is extremely important that the database be kept secure, if +the realm's Kerberos service is to remain secure. + +Once a KDC is installed and configured, you may then set up one or more +client machines, and one or more application machines. + +@menu +* Background:: +* Installation on any Machine:: +* Installing the KDC:: +* Migrating from V4 to V5 Kerberos:: +* A Sample Application:: +* Installing Kerberos Applications:: +* Common Kerberos Service Names:: +@end menu + +@node Background, Installation on any Machine, Installation, Installation +@section Background Information + +Your system's security is only as good as the security of your +@samp{root} password. You should take other precautions to protect your +system security in addition to installing Kerberos. Kerberos cannot +protect you from someone who is able to steal @samp{root} privileges. +Kerberos also does not protect you from break-ins caused by bugs in your +daemons (e.g., @samp{fingerd} or @samp{sendmail}). On almost all UNIX +systems, if intruders can break in as an ordinary users, they can obtain +superuser privileges by exploiting bugs or imperfect configuration files. + + +@node Installation on any Machine, Installing the KDC, Background, Installation +@section Installation on any Machine + +The following steps must be performed no matter what type of +machine (KDC, Client, or Application server) you are installing. All +machines functioning within the same administrative domain must use the +same Kerberos realm name; and all machines which are using Kerberos must +have the Kerberos configuration files properly installed. + +If you are installing Kerberos on a machine that will act only as a +Kerberos client, this section describes all that you need to do. If you +are installing a KDC, or an Kerberos Application server, you will also +need to complete the procedures detailed in @ref{Installing the KDC}, or +@ref{A Sample Application}, after you finish with the procedures found +in this section. + +@menu +* Picking a Realm Name:: +* Configuration files:: +* Recommended Programs:: +@end menu + +@node Picking a Realm Name, Configuration files, Installation on any Machine, Installation on any Machine +@subsection Picking a Realm Name + +Before you install Kerberos V5 at your site, you have to choose a +@dfn{realm name}, the name that specifies the system's administrative +domain. By convention, we suggest that you use your internet domain +name, in capital letters. (Kerberos realm names are case-sensitive, so +it's important that your realm name be in all upper case.) For example, +if your internet domain is @code{cygnus.com} (so that you have hostnames +such as @code{ftp.cygnus.com} and @code{tweedledum.cygnus.com}), then +your Kerberos realm should be @code{CYGNUS.COM}. Please note that +changing realm names is hard. Get it right the first time. + +@node Configuration files, Recommended Programs, Picking a Realm Name, Installation on any Machine +@comment node-name, next, previous, up@section +@subsection Configuration files + + +@menu +* krb5.conf:: +* Converting V4 configuration files:: +* /etc/services:: +@end menu + +@node krb5.conf, Converting V4 configuration files, Configuration files, Configuration files +@subsubsection The @file{krb5.conf} File + +The @file{krb5.conf} file contains information needed by the Kerberos V5 +library including a system's default Kerberos +realm, and the locations of the Kerberos servers. + +The @file{krb5.conf} uses an INI-style format. Sections are delimited by +square braces; within each section, there are relations where tags can +be assigned to have specific values. Tags can also contain a +subsection, which contains further relations or subsections. A tag can +be assigned to multiple values. + +Create a @file{/etc/krb5.conf} file using the following format: + +@example +[libdefaults] + default_realm = + +[realms] + = @{ + kdc = + admin_server = + default_domain = + @} + +[domain_realm] + <.domain.name> = +@end example + +Where @samp{realm_name} specifies the default realm to be used by that +particular system, and @samp{master_server_name} specifies the machine +name on which you will run the master server. The keywords @samp{kdc} +and @samp{admin_server} lists the location of the realms KDC and +administration servers. + +For example, if your realm name is @samp{ATHENA.MIT.EDU} and your master +server's name is @samp{kerberos.mit.edu}, the file should have these +contents: + +@example +[libdefaults] + default_realm = ATHENA.MIT.EDU + +[realms] + ATHENA.MIT.EDU = @{ + kdc = KERBEROS.MIT.EDU + admin_server = KERBEROS.MIT.EDU + default_domain = MIT.EDU + @} + +[domain_realm] + .mit.edu = ATHENA.MIT.EDU + mit.edu = ATHENA.MIT.EDU +@end example + + +In many situations, the default realm in which a host operates will be +identical to its Internet domain name, with the first component removed +and all letters capitalized. For example, @code{ftp.cygnus.com} is +traditionally in the realm @code{CYGNUS.COM}. +If this is not the case, you will need to establish a translation from +host name or domain name to realm name. This is accomplished with the +@samp{[domain_realm]} stanza. + +Each line of the translation file specifies either a host name or domain +name, and its associated realm: + +@example +[domain_realm] + <.domain.name> = KERBEROS.REALM1 + = KERBEROS.REALM2 +@end example + +For example, to map all hosts in the domain LSC.MIT.EDU to LSC.MIT.EDU +but the host FILMS.LSC.MIT.EDU to MIT.EDU your file would read: +@example +[domain_realm] + .LSC.MIT.EDU = LSC.MIT.EDU + FILMS.LSC.MIT.EDU = MIT.EDU +@end example + +If a particular host name matches both a domain name and a host name in +@samp{[domain_realm]}, the entry containing the host name takes precedence. + +See the @file{[SOURCE_DIR]/config-files/krb5.conf} file for an example +@file{krb5.conf} file. That file has examples of how to provide backup +servers for a given realm (additional lines with the same leading realm +name) and how to designate servers for remote realms. + +@node Converting V4 configuration files, /etc/services, krb5.conf, Configuration files +@subsubsection Conversion of V4 configuration files + +Kerberos V4's @file{krb.conf} and @file{krb.realms} files formats are no +longer used by the V5 library. A @sc{PERL} script has been provided to allow +for "easy" generation of an initial @file{krb5.conf}. It is located in +@file{[SOURCE_DIR]/config-files/convert-config-files}. The produced file +should be checked for errors. + +Note that if you are planning on using certain applications with +Kerberos V4 compatibility compiled in, the V4 library still needs the +files @file{krb.conf} and @file{krb.realms}. + + +@node /etc/services, , Converting V4 configuration files, Configuration files +@subsubsection /etc/services + +All hosts which will use Kerberos will need to have certain ports +defined in the system's @file{/etc/services} file. The file +@file{[SOURCEDIR]/config-files/services.append} contains the entries +which should be appended to the @file{/etc/services} file. Please note +that not all of the entries are required as several of the programs have +defaults built into the programs. This will be documented sometime in +the future. + +If you are using the Network Information Services (NIS) or Yellow +Pages (YP), you will need to add the services in the +@file{services.append} file to the services exported in the NIS or YP +server. + +@node Recommended Programs, , Configuration files, Installation on any Machine +@subsection Recommended Programs + +The following files should be installed on all machines which are +running Kerberos, either as a client, a KDC, or an application server: + +If you used the default @samp{make install} without using the +@samp{--prefix} argument to @file{configure}, then [K_USER] refers to +@file{/usr/local/bin}. + +@itemize @bullet +@item @file{/etc/krb5.conf} --- This files contains information required +by Kerberos V5 giving system defaults as well as locations of Kerberos +servers. +@item @file{[K_USER]/kinit} --- This program allows you to obtain +Kerberos credentials. +@item @file{[K_USER]/kdestroy} --- This program allows you to destroy +Kerberos credentials which are no longer needed. +@item @file{[K_USER]/klist} ---- This program allows you to list the +credentials found in your credentials cache. +@end itemize + +@node Installing the KDC, Migrating from V4 to V5 Kerberos, Installation on any Machine, Installation +@section Installing the KDC + +@menu +* kdc.conf:: +* Initializing the KDB:: +* Storing the Master Password:: +* Adding Users to the Database:: +* Starting the Kerberos Server:: +* Setting up Slave Kerberos Servers:: +* Inter-realm Kerberos Operation:: +* The Administration Server:: +* Testing the Kerberos Server:: +@end menu + +@node kdc.conf, Initializing the KDB, Installing the KDC, Installing the KDC +@subsection The optional @file{kdc.conf} profile + +There is an optional configuration file @file{kdc.conf} that allows one +to specify per-realm configuration data to be used by the Kerberos V5 +Authentication Service and Key Distribution Center. This information +includes database locations, key and per-realm defaults, port numbers, +ticket life times, etc. The location of the configuration file is +@file{/usr/local/lib/krb5kdc/kdc.conf}. + +See the man page or @file{[SOURCEDIR]/config-files/kdc.conf.M} for more +details. + +This document assumes that you do not have the @file{kdc.conf} +configuration file installed. + +Note also that @code{[logging]} subsection to @file{/etc/krb5.conf} can +be used to specify where to syslog messages regarding server activity. + +@node Initializing the KDB, Storing the Master Password, kdc.conf, Installing the KDC +@subsection Initializing the Kerberos Database + +Login to the Kerberos KDC, and use the @samp{su} command to become root. +If you installed the Kerberos administration tools +with the @samp{make install} command and the default pathnames, +they should be in the @file{/usr/local/admin} directory. +If you installed the tools in a different directory, +hopefully you know what it is. +From now on, we will refer to this directory as [ADMIN_DIR]. + +The default database will be located in the directory +@file{/usr/local/lib/krb5kdc} unless changed in the configuration +process. From now on, we will call this [DB_DIR]. + +The @samp{kdb5_create} command creates and initializes the master database. +It asks you to the database's master password. +Do not forget this password. +If you do, the database becomes useless. +(Your realm name should be substituted for [REALMNAME] below.) +@xref{Storing the Master Password} for an alternative way of dealing +with this master password. + +Because the install process does not create [DB_DIR] you need to do so +yourself. + +Use @samp{kdb5_create} as follows: + +@example +# @b{mkdir [DB_DIR]} +# @b{[ADMIN_DIR]/kdb5_create} +Initializing database '[DB_DIR]/principal' for realm '[REALMNAME]', +master key name 'K/M@@[REALMNAME]' +You will be prompted for the database Master Password. +It is important that you NOT FORGET this password. +Enter KDC database master key: @b{<-- [Enter the master password.]} +Re-enter KDC database master key to verify: @b{<-- [Re-enter it.]} +@end example + + +@node Storing the Master Password, Adding Users to the Database, Initializing the KDB, Installing the KDC +@subsection Storing the Master Password + +The @samp{kdb5_stash} command "stashes" the master password in the file +@file{[DB_DIR]/.k5.[REALM.NAME]} so that the Kerberos server can be started +automatically during an unattended reboot of the master server. Other +administrative programs use this hidden password so that they can access +the master database without someone having to manually provide the +master password. This command is an optional one; if you'd rather enter +the master password each time you start the Kerberos server, don't use +@samp{kdb5_stash}. + +On the one hand, if you use @samp{kdb5_stash}, a copy of the master key +will reside on a disk, which may not be acceptable; on the other hand, +if you don't use @samp{kdb5_stash}, the server cannot be started unless +someone is around to type the password manually. + +The command merely prompts for the master password: + +@example +# @b{[ADMIN_DIR]/kdb5_stash} +Enter KDC database master key: @b{<-- [Enter the master password.]} +@end example + +WARNING: If your Kerberos database master key is compromised and the +database is obtained, the security of your entire authentication system +is compromised. (If this happens to you, all of your user's passwords must +be set to new values manually --- i.e., not using Kerberos.) The master +key must be a carefully kept secret. If you keep backups, you must +guard all the master keys you use, in case someone has stolen an old +backup and wants to attack users' whose passwords haven't changed since +the backup was stolen. This is why we provide the option not to store +it on disk. + +@node Adding Users to the Database, Starting the Kerberos Server, Storing the Master Password, Installing the KDC +@subsection Adding Users to the Database + +The @samp{kdb5_edit} program may be used to add new users and services to +the master database, and to modify existing database +information. @xref{The Administration Server} for an alternative method +once the Kerberos environment is up and running. + +For example, to add yourself to the newly created database: (replace +@samp{[USERNAME]} with your username with. + +@example +# @b{[ADMIN_DIR]/kdb5_edit} +kdb5_edit: @b{ank [USERNAME]} +Enter password: @b{<-- [Enter your password.]} +Re-enter password for verification: @b{<-- [Re-enter it.]} +kdb5_edit: @b{quit} +@end example + +The @samp{ank} command is short for "add_new_key"; this command adds a +new user to the database. To see what other commands which @samp{kdb5_edit} +supports, type @kbd{? @key{RET}} at the @samp{kdb5_edit} prompt. + +@node Starting the Kerberos Server, Setting up Slave Kerberos Servers, Adding Users to the Database, Installing the KDC +@subsection Starting the Kerberos Server + +Assuming that you didn't use the @samp{--prefix} argument to +@file{configure}, then [K_SERVER] refers to @file{/usr/local/sbin}. + +In order to start the Kerberos server, simply run it. It will fork and +disassociate from the terminal unless the @samp{-n} argument is used. + +@example +# @b{[K_SERVER]/krb5kdc} +@end example + +If you have used the @samp{kdb5_stash} command to store the master database password, +the server will start automatically. +If you did not use @samp{kdb5_stash}, +use the following command: + +@example +# @b{[K_SERVER]/krb5kdc -m} +@end example + +The server will prompt you to enter the master password before actually +starting itself. + +@node Setting up Slave Kerberos Servers, Inter-realm Kerberos Operation, Starting the Kerberos Server, Installing the KDC +@subsection Setting up Slave Kerberos Servers + +Slave Kerberos servers allow clients to be able to get Kerberos tickets +even when the Master server is not available. Users will not be able to +change their passwords --- changes can only be made to database on the +Master server; however, users will be able to authenticate to +application servers, which is critically important in a distributed +client-server environment. The current implementation of the client code +does not provide load sharing in that the order of servers contacted is +the same as those listed in the @file{krb5.conf} file. + +@menu +* Kerberos Slave Database Propagation:: +* Installing a Slave Server:: +@end menu + +@node Kerberos Slave Database Propagation, Installing a Slave Server, Setting up Slave Kerberos Servers, Setting up Slave Kerberos Servers +@subsubsection Kerberos Slave Database Propagation + +In order to propagate the Kerberos database from the Master server to +the slaves, the @samp{kprop} and @samp{kpropd} client/server programs +are used. Periodically, the Master server will dump the Kerberos +database out into an ASCII format, using the @samp{kdb5_edit} program. +The master server will then run @samp{kprop} to propagate the dumped +database file to each slave server. + +On the slave server, the @samp{kpropd} program is invoked out of +@samp{inetd} server. After @samp{kprop} and @samp{kpropd} have +mutually authenticated with one another, and @samp{kpropd} is satisfied +with the identity of the Master server, then the dumped ASCII database +is transferred to the slave server in an encrypted fashion. After the +database is transfered, @samp{kpropd} will then run @samp{kdb5_edit} +with the appropriate arguments in order to undump the database into a +usable form by the KDC on the slave server. + +@node Installing a Slave Server, , Kerberos Slave Database Propagation, Setting up Slave Kerberos Servers +@subsubsection Installing a Slave Server + +@b{To be written.} + + +@node Inter-realm Kerberos Operation, The Administration Server, Setting up Slave Kerberos Servers, Installing the KDC +@subsection Inter-realm Kerberos Operation + +@b{To be written.} + +@node The Administration Server, Testing the Kerberos Server, Inter-realm Kerberos Operation, Installing the KDC +@subsection The Administration Server + +There is currently an administration server in the Kerberos source tree. +It is, however, very rough, and it will likely be significantly changed +or replaced before the 1.0 release. Hence, this manual does not +document the current administration server. Changes to the database can +be made by logging in to the KDC directly, and using the +@samp{kdb5_edit} program; see @ref{Adding Users to the Database}. + +@node Testing the Kerberos Server, , The Administration Server, Installing the KDC +@subsection Testing the Kerberos Server + +Use the @samp{kinit} command to obtain Kerberos credentials. This command +creates your credentials cache and stores your credentials in it. + +If you used the default @samp{make install} command and directories to +install the Kerberos user utilities, @samp{kinit} will be in the +@file{/usr/local/bin} directory. From now on, we'll refer to the Kerberos user +commands directory as [K_USER]. + +Use @samp{kinit} as follows: + +@example +% @b{[K_USER]/kinit [USERNAME]} +Password for [USERNAME]@@[REALMNAME]: @b{<-- enter your password} +@end example + + +Use the @samp{klist} program to list the contents of your ticket file. + +@example +% @b{[K_USER]/klist} +Ticket cache: /tmp/krb5cc_15806 +Default principal: [USERNAME]@@[REALMNAME] + + Valid starting Expires Service principal +31-Jan-95 21:58:32 1-Feb-95 05:57:39 krbtgt/[REALMMNAME]@@[REALMNAME] + +@end example + +@ignore +@c not yet... +If you have any problems, you can examine the log file +@file{/krb5/kerberos.log} on the Kerberos server machine to see if +there was some sort of error. +@end ignore + +@node Migrating from V4 to V5 Kerberos, A Sample Application, Installing the KDC, Installation +@section Migrating from V4 to V5 Kerberos + +@b{To be written.} A rough idea of the procedure that one may follow is +in @file{[SOURCE_DIR]/kdc/migration.doc}. + +@node A Sample Application, Installing Kerberos Applications, Migrating from V4 to V5 Kerberos, Installation +@section A Sample Application + +This release of Kerberos comes with a sample application server and a +corresponding client program. You will find this software +@file{[K_SERVER]/sserver} and @file{[K_USER]/sclient}, which is the +server's executable, and the client program's executable, respectively. + +The programs are rudimentary. +When they have been installed (the installation procedure is described +in detail later), they work as follows: + +@enumerate + +@item + The user starts @samp{sclient} and provides as arguments +to the command the name of the server machine and an optional port on +which to contact the server. + +@item + @samp{sclient} contacts the server machine and +authenticates the user to @samp{sserver}. + +@item + @samp{sserver} authenticates itself to @samp{sclient} (thus +performing mutual authentication), and +then returns a message to the client program. +This message contains the name of the Kerberos principal that was used +to authenticate to @samp{sserver}. + +@item + @samp{sclient} displays the server's message on the user's +terminal screen. + +@end enumerate + +@menu +* Installing the Sample Application:: +* Testing the Sample Server:: +@end menu + +@node Installing the Sample Application, Testing the Sample Server, A Sample Application, A Sample Application +@subsection Installing the Sample Application + +In general, +you use the following procedure to install a Kerberos-authenticated +server-client system. + +@enumerate + +@item + Add the appropriate entry to the Kerberos database using @samp{kdb_edit} + +@item + Create a @file{/etc/v5srvtab} file for the server machine. + +@item + Install the service program and the @file{/etc/v5srvtab} +file on the server machine. + +@item + Install the client program on the client machine. + +@item + Update the @file{/etc/services} file on the client and server machines. +@end enumerate + +We will use the sample application as an example, although programs +which do not take requests via the @samp{inetd} program may have +slightly different installation procedures. @samp{Inetd} starts +@samp{sserver} each time a client process contacts the server machine. +@samp{sserver} processes the request, terminates, then is restarted +when @samp{inetd} receives another @samp{sserver} request. When you +install the program on the server, you must add a @samp{sample} entry to +the server machine's @file{/etc/inetd.conf} file. + +The following description assumes that you are installing +@samp{sserver} on the machine @samp{jimi.mit.edu}. +Here's the process, step by step: + +@enumerate + +@item + Login as root or @samp{su} to root on the Kerberos server machine. +Use the @samp{kdb5_edit} program to create an entry for +@code{sample} in the Kerberos database: + +@example +# @b{[ADMIN_DIR]/kdb5_edit} +kdb5_edit: @b{add_random_key sample/jimi.mit.edu} +kdb5_edit: @b{quit} +@end example + +(Note: @samp{add_random_key} may be abbreviated as @samp{ark}.) + +@item + Use @samp{kdb5_edit} to create a @file{srvtab} file +for @samp{sserver}'s host machine: + +@example +# @b{[ADMIN_DIR]/kdb5_edit} +kdb5_edit: @b{extract_srvtab jimi.mit.edu sample} +'sample/jimi.mit.edu@@ATHENA.MIT.EDU' added to keytab 'WRFILE:jimi.mit.edu-new-srvtab' +kdb5_edit: @b{quit} +@end example + +(Note: @samp{extract_srvtab} may be abbreviated as @samp{xst}.) + +Transfer the @file{jimi.mit.edu-new-srvtab} file to @samp{jimi.mit.edu} +and install it as @file{/etc/v5srvtab}. + +@b{WARNING}: Note that this file is equivalent to the service's password and +should be treated with care. For example, it could be transferred by +removable media, but should not be sent over an open network in the +clear. This file should installed such that only the root user can read +it. + +@item + Add the following line to the @file{/etc/services} file on +@samp{jimi.mit.edu}, and on all machines that will run the +@samp{sample_client} program: + +@example +sample 906/tcp # Kerberos sample app server +@end example + +@item + Add a line similar to the following line to the @file{/etc/inetd.conf} +file on @samp{sample_server}'s machine: + +@example +sample stream tcp nowait switched root + [K_SERVER]/sserver sample_server +@end example + +where [K_SERVER] should be substituted with +the path to the @samp{sserver} program. +(This @file{inetd.conf} information should be placed on one line.) +You should examine existing lines in @file{/etc/inetd.conf} and use the +same format used by other entries (e.g. for telnet). Most systems do +not have a column for the `switched' keyword, and some do not have a +column for the username (usually `root', as above). + +@item + Restart @samp{inetd} by sending the current @samp{inetd} process +a hangup signal: + +@example +# @b{kill -HUP} @i{process_id_number} +@end example + +@item + The @samp{sserver} is now ready to take @samp{sclient} requests. + +@end enumerate + +@node Testing the Sample Server, , Installing the Sample Application, A Sample Application +@subsection Testing the Sample Server + +Assume that you have installed @samp{sserver} on @samp{jimi.mit.edu}. + +Login to your workstation and use the @samp{kinit} command to +obtain a Kerberos ticket-granting ticket: + +@example +% @b{[K_USER]/kinit [USERNAME]} +Password for [USERNAME]@@[REALMNAME]: @b{<--- Enter your password} +@end example + +Now use the @samp{sclient} program as follows: + +@example +% @b{[K_USER]/sclient jimi} +@end example + +The command should display something like the following: + +@example +sendauth succeeded, reply is: +reply len 29, contents: +You are [USERNAME]@@[REALMNAME] +@end example + +@node Installing Kerberos Applications, Common Kerberos Service Names, A Sample Application, Installation +@section Installing Kerberos Applications + + In addition to the sample application, Kerberos comes with +several servers that can be installed on workstations to provide secure +network services such as FTP, Telnet, and Rlogin. This section +describes these services and how to install them. First, a general +procedure is outlined for configuring a workstation to run Kerberos +application servers. Then, details of the particular configuration +options required by each server are presented. + + +@menu +* Levels of Security:: +* Preparing a Workstation for Kerberos Application Servers:: +* BSD Utilities:: +* Telnet and FTP:: +@end menu + +@node Levels of Security, Preparing a Workstation for Kerberos Application Servers, Installing Kerberos Applications, Installing Kerberos Applications +@subsection Levels of Security + + Before installing Kerberized servers, it is a good idea to +decide on a security policy for your environment. While developing a +comprehensive security policy is beyond the scope of these instructions, +there are several interactions between Kerberos servers and non-Kerberos +servers, as well as different modes in which Kerberos servers can run +that should be considered. In general, there are three levels of +connections: + +@enumerate + +@item +Encrypted Kerberos connections are the most secure services provided by +the Kerberos environment. Only encrypted services provide +confidentiality---encryption is required to make sure a passive +eavesdropper does not collect sensitive data, such as passwords, sent +over connections. Besides providing confidentiality, encryption +provides protection against active attacks. Without encryption or some +other form of integrity, an attacker may be able to insert commands or +change data in an authenticated session. + + +@item +The next level of security is Kerberos-authenticated services without +encryption. Without encryption, there is no confidentiality, and some +active attacks are possible. However, unencrypted services are faster +and are available commercially outside the United States. In addition, +the window of exposure to attack is generally limited to the lifetime of +a session---it is difficult for an attacker who does not have tickets to +start a new session if a Kerberos authentication exchange must take +place at the beginning of every session. + +@item +Passworded services provide the next lower level of security. +Unfortunately, it is all-to-easy for a passive attacker to use software +such as a packet sniffer to find passwords traveling over a network. +Additionally, once an attacker knows a password, they can start +additional sessions at future times until the password is changed from a +secure location. Despite the disadvantages of password-based network +services, there are some common reasons for enabling them. First, most +clients only support password-based services; not everyone has Kerberos +or other cryptographically-secure network services. Second, in some +environments, where the network is secure, passwords may be a reasonable +solution. Also, particularly on public-access systems, it is common to +enable password-based services for normal users, while using more-secure +services such as Kerberos for root logins by administrators. + +@item +The least secure common category of services are trust or host-based +services. These services use an IP address or client-supplied assertion +to provide authentication. Examples of host-based services include +@samp{rlogin}, @samp{rsh}, and the @samp{on} or @samp{rexd} service. It +is generally sufficient to know that a user exists on a target system, +and to know that a host-based or trust-based service is enabled in order +to exploit the service. Whenever possible, these services should be +disabled; there are few situations in which an a security policy is both +compatible with Kerberos and host-based services. +@end enumerate + + Next, decide whether Kerberos V4 compatibility is necessary. +Unencrypted Kerberos V4 services suffer from all the problems of +unencrypted Kerberos V5 services: lack of confidentiality and +susceptibility to active attack. In addition, the lack of a replay cache +in Kerberos V4 makes these active attacks much easier. Also, design bugs +in the Kerberos V4 BSD utilities such as @samp{rlogin}, @samp{rsh} and +@samp{rcp} cause the availability of an unencrypted service to +significantly decrease the security of a system, even if only the +encrypted service is ever used. For example, a system that runs both +encrypted and unencrypted Kerberos V4 @samp{rlogin} servers is less secure +than a system only running the encrypted service, even if users only +ever connect to the encrypted service. + + Therefore, if Kerberos V4 interoperability is desired or required, +try to avoid running unencrypted Kerberos V4 services wherever possible. +In particular, only enable encrypted @samp{rlogin} if at all possible. +Naturally, some environments will require additional Kerberos V4 +functionality, like @samp{rsh}. The Kerberos V5 versions of these services, +with Kerberos V4 interoperability enabled, are not any weaker than their +Kerberos V4 counterparts. So, if the existing Kerberos V4 security policy +allows these services, then enabling them under the Kerberos V5 security +policy should not be a problem. + + In addition, the issue of compatibility with older Kerberos V5 +clients must be considered. For the most part, this compatibility is +automatic, and has few security implications. The major exception to +this is the BSD utilities. Until Kerberos V5 Beta6, these utilities +inherited a few design defects from the Kerberos V4 BSD utilities. In +particular, the presence of an unencrypted service that was never used +adversely effected the security of an encrypted service. The solution +that was adopted preserves compatibility with Kerberos V5 Beta5 clients. +Unfortunately, older clients are incompatible with this scheme. If +interoperability with older clients is necessary, then the new scheme +for checksums can be disabled on the server. If these checksums are +disabled, there is a short window between when a connection is opened +and when the replay cache is updated where an active attack is possible. +Alternatively, sites wishing to enable all security features may wish to +disable compatibility with Kerberos V5 Beta5 BSD utilities. +@xref{Checksums}, for full details. + + In conclusion, as you prepare to install Kerberos application +servers, you should have answers to the following questions: + +@enumerate + +@item +What levels of services are appropriate for your security policy: +encrypted services, authenticated but not encrypted services, +password-based services, or host-based services? + +@item +Do you wish to enable Kerberos V4 compatibility? If so, do you need to +enable unencrypted services? + +@item +Do you need compatibility with Kerberos V5 clients before Beta5 +(released in May, 1995)? Do you wish to disable compatibility with +Beta5 clients for slightly enhanced security? +@end enumerate + + + +@node Preparing a Workstation for Kerberos Application Servers, BSD Utilities, Levels of Security, Installing Kerberos Applications +@subsection Preparing a Workstation for Kerberos Application Servers + + + The following procedure is very similar to the installation +procedure for the sample Kerberos server. @xref{Installing +the Sample Application}. However, instead of using the sample service, +this configuration is designed to set up host-based services. + +The following description assumes that you are installing @samp{sserver} +on the machine @samp{jimi.mit.edu}. Repeat these steps for each +workstation that will be running host-based servers. Note that it is +not necessary to run these procedures on client machines--machines used +only to connect to secure network services, but that do not run any +servers of their own. Here's the process, step by step: + +@enumerate + +@item + Login as root or @samp{su} to root on the Kerberos server machine. +Use the @samp{kdb5_edit} program to create a service entry for +@code{host} in the Kerberos database: + +@example +# @b{[ADMIN_DIR]/kdb5_edit} +kdb5_edit: @b{add_random_key host/jimi.mit.edu} +kdb5_edit: @b{quit} +@end example + +(Note: @samp{add_random_key} may be abbreviated as @samp{ark}.) + +@item + Use @samp{kdb5_edit} to create a @file{srvtab} file +for @samp{sserver}'s host machine: + +@example +# @b{[ADMIN_DIR]/kdb5_edit} +kdb5_edit: @b{extract_srvtab jimi.mit.edu host} +'host/jimi.mit.edu@@ATHENA.MIT.EDU' added to keytab 'WRFILE:jimi.mit.edu-new-srvtab' +kdb5_edit: @b{quit} +@end example + +(Note: @samp{extract_srvtab} may be abbreviated as @samp{xst}. Also, +additional services can be listed after @samp{host} on the +@samp{extract_srvtab} line; for example if the host jimi also runs the +sample server, the @samp{sample} service might have been listed after +host.) + +Transfer the @file{jimi.mit.edu-new-srvtab} file to @samp{jimi.mit.edu} +and install it as @file{/etc/v5srvtab}. + +@b{WARNING}: Note that this file is equivalent to the service's password and +should be treated with care. For example, it could be transferred by +removable media, but should not be sent over an open network in the +clear. This file should be installed such that only the root user can read +it. + +@item +Make sure that the @samp{/etc/services} file has been updated to include +Kerberos services. In particular, look for @samp{klogin}, +@samp{eklogin}, and @samp{kshell}. + +@item +For each server you plan to run, add a line to @file{/etc/inetd.conf}. +The following sections will give details on what this line should look +like for each Kerberos application service. + +@item +Consider removing non-Kerberized services like @samp{rlogin}, +@samp{rsh}, @samp{rexd}, and others, in accordance with the security policy you decided on in the last section. + +@item + Restart @samp{inetd}. On most systems, this is done by sending the current @samp{inetd} process +a hangup signal: + +@example +# @b{kill -HUP} @i{process_id_number} +@end example + +@item +Try using the Kerberos applications to connect to the host. + +@end enumerate + +@node BSD Utilities, Telnet and FTP, Preparing a Workstation for Kerberos Application Servers, Installing Kerberos Applications +@subsection BSD Utilities + + This section describes installing servers for the BSD utilities: +@samp{kshd} and @samp{klogind}. The @samp{klogind} server implements the +protocol used by the Kerberized @samp{rlogin} client. The @samp{kshd} +server implements the protocol used by the @samp{rsh} and @samp{rcp} +clients. + + These daemons take a common set of options to enable support for +different versions of Kerberos. The @samp{-5} option enables Kerberos +V5 support, and the @samp{-4} option enables Kerberos V4 support. At +least one of these options must be supplied or the server will refuse +all connections. Both options can be supplied if compatibility with +both versions of Kerberos is desired. + + Both the @samp{klogind} and @samp{kshd} take an @samp{-e} option +to control encryption; because of the design of the servers, it works +slightly differently. The Kerberos login service listens on two +different ports, one for encrypted connections, and one for unencrypted +connections. Because @samp{klogind} is started by @samp{inetd}, it +needs to know whether it is servicing an encrypted or unencrypted +connection. Thus, the @samp{-e} option tells @samp{klogind} that it is +listening to the encrypted port. Typically, systems that allow both +encrypted and unencrypted logins have two lines in @file{inetd.conf}, +one for the @samp{klogin} service and one for the @samp{eklogin} +service. The line for the @samp{eklogin} service uses the @samp{-e} +option, while the line for the @samp{klogin} service does not. Systems +only supporting encrypted logins simply have the @samp{eklogin} line. + + On the other hand, @samp{kshd} listens to encrypted and +unencrypted requests on the same port; information from the client +identifies the connection's encryption status. So, @samp{kshd} +interprets the @samp{-e} option to mean that encryption is required. If +this option is specified, unencrypted connections are dropped. Thus, +specifying @samp{-e} to @samp{kshd} is like only having a line for +@samp{eklogin}. + +@menu +* Checksums:: Checksum facility for dealing with active attacks. +* BSD Utility Configuration Example:: Sample @file{inetd.conf} entries for BSD utilities. +@end menu + +@node Checksums, BSD Utility Configuration Example, BSD Utilities, BSD Utilities +@subsubsection Checksums + + Under previous versions of Kerberos, it was possible for an active +attacker to change certain information in the initial authentication +exchange without this change being detected. Starting with Kerberos V5, +Beta6, this information is protected by a checksum passed in the +Kerberos authenticator. Ideally, the server could detect the presence +of this checksum and use it if it were present. This way, +administrators could be sure to use new clients that produced the +checksum, while users who were not as concerned about security could use +a wider range of clients. + + This is how the checksum feature works by default. +Unfortunately, clients previous to Kerberos V5, Beta5 used the checksum +field to incorporate semi-random data into the Kerberos authentication +exchange. It is impossible to distinguish these bogus checksums from +checksums that have been produced by modern clients, but modified by an +active attacker. Thus, the checksum feature is incompatible with +previous releases of Kerberos V5. Three modes of operation are provided +to meet the configuration needs of different sites: + +@enumerate + +@item +The @samp{-c} option to both @samp{kshd} and @samp{klogind} requires +that checksums be present and valid. This only works with clients more +recent than Kerberos V5, Beta6. An error will be given when an older +client tries to connect. This option is incompatible with Kerberos V4; +Kerberos V4 clients do not include a checksum. If this option is used +in conjunction with the @samp{-4} option for Kerberos V4 compatibility, +a warning about the configuration error will be logged on each +connection. + +@item +If no checksum-related option is specified, then checksums will be +validated if they are present, but not required. This is compatible with +Kerberos V4 and Kerberos V5 clients as early as Kerberos V5, Beta5. + +@item +If the @samp{-i} option is provided, then checksums are ignored, even if +present. This option is required to maintain compatibility with clients +older than Kerberos V5 Beta5. Site should upgrade to newer clients so +this option is not required. + +@end enumerate + +@node BSD Utility Configuration Example, , Checksums, BSD Utilities +@subsubsection BSD Utility Configuration Example + + This section includes sample entries for @file{/etc/inetd.conf}. +Sample configuration are presented for three systems. Note that while +the examples stretch over multiple lines, an entry for a single service +should be placed on only one line in @file{inetd.conf}. Also, not all +systems have all of the columns shown in the example. @xref{Installing +the Sample Application}, for details on adding services to +@file{inetd.conf}. + + The first system enables all security features. Only Kerberos +V5 encrypted connections are enabled, and checksums are required. +@example +eklogin stream tcp nowait root + [K_SERVER]/klogind klogind -5 -e -c +kshell stream tcp nowait root + [K_SERVER]/kshd kshd -5 -e -c +@end example + + + The second system enables encrypted services for both Kerberos +V5 and Kerberos V4. Checksums are not required, but since no V5 clients +earlier than Beta5 are used, they are not ignored. + +@example +eklogin stream tcp nowait root + [K_SERVER]/klogind klogind -5 -4 -e +kshell stream tcp nowait root + [K_SERVER]/kshd kshd -5 -4 -e +@end example + + + The final example has both encrypted and unencrypted services +enabled for both Kerberos V5 and Kerberos V4. Checksums are disabled to +preserve compatability with older V5 clients. + +@example +eklogin stream tcp nowait root + [K_SERVER]/klogind klogind -5 -4 -i -e +klogin stream tcp nowait root + [K_SERVER]/klogind klogind -5 -4 -i +kshell stream tcp nowait root + [K_SERVER]/kshd kshd -5 -4 -i +@end example + +@node Telnet and FTP, , BSD Utilities, Installing Kerberos Applications +@subsection Telnet and FTP + + The following are example entries for @file{inetd.conf} for the +@samp{telnetd} and @samp{ftpd} servers. @xref{Installing the Sample +Application}, for details on adding services to @file{inetd.conf}. Note +that unlike other @file{inetd.conf} examples in this document, these +line should replace existing lines for password-based services of the +same name. + + The first example only allows encrypted or authenticated connections. + +@example +telnet stream tcp nowait root + [K_SERVER]/telnetd telnetd -a user +ftp stream tcp nowait root + [K_server]/ftpd ftpd -a +@end example + + The second example also allows password-based connections to be +made. + +@example +telnet stream tcp nowait root + [K_SERVER]/telnetd telnetd +ftp stream tcp nowait root + [K_server]/ftpd ftpd +@end example + +@node Common Kerberos Service Names, , Installing Kerberos Applications, Installation +@section Common Kerberos Service Names + +The following service names are used by Kerberos client/server +applications. + +@table @code + +@item host +Used by @samp{telnet}, @samp{rlogin}, @samp{rsh}, @samp{rcp}, @samp{ftp} +and other services which generally give login access to the host. + +@item pop +Used by the Post Office Protocol. + +@item sample +Used by the Kerberos sample applications. + +@end table + +These service names are used as the first component of the server's +principal name, with the second component being the server's fully +qualified domain name, in lower case. + +@node Troubleshooting, , Installation, Top +@chapter Troubleshooting + +@b{To be written.} + +@contents +@bye diff --git a/krb5-1-6/doc/install.texinfo b/krb5-1-6/doc/install.texinfo new file mode 100644 index 000000000..64cdac70e --- /dev/null +++ b/krb5-1-6/doc/install.texinfo @@ -0,0 +1,1456 @@ +\input texinfo-suppl.tex % contains @doubleleftarrow{} definition + % this line must come *before* \input texinfo +\input texinfo @c -*-texinfo-*- +@c %**start of header +@c guide +@setfilename krb5-install.info +@settitle Kerberos V5 Installation Guide +@setchapternewpage odd @c chapter begins on next odd page +@c @setchapternewpage on @c chapter begins on next page +@c @smallbook @c Format for 7" X 9.25" paper +@c %**end of header + +@paragraphindent 0 +@iftex +@parskip 6pt plus 6pt +@end iftex + +@dircategory Kerberos +@direntry +* krb5-install: (krb5-install). Kerberos V5 Installation Guide +@end direntry + +@include definitions.texinfo +@set EDITION 1.1 + +@finalout @c don't print black warning boxes + +@titlepage +@title @value{PRODUCT} Installation Guide +@subtitle Release: @value{RELEASE} +@subtitle Document Edition: @value{EDITION} +@subtitle Last updated: @value{UPDATED} +@author @value{COMPANY} + +@page +@vskip 0pt plus 1filll + +@end titlepage + +@node Top, Copyright, (dir), (dir) +@comment node-name, next, previous, up + +@ifinfo +This file documents how to install the @value{RELEASE} release of +@value{PRODUCT}. + +@end ifinfo + +@c The master menu is updated using emacs19's M-x texinfo-all-menus-update +@c function. Don't forget to run M-x texinfo-every-node-update after +@c you add a new section or subsection, or after you've rearranged the +@c order of sections or subsections. Also, don't forget to add an @node +@c comand before each @section or @subsection! All you need to enter +@c is: +@c +@c @node New Section Name + +@c @section New Section Name +@c +@c M-x texinfo-every-node-update will take care of calculating the +@c node's forward and back pointers. +@c +@c --------------------------------------------------------------------- + +@menu +* Copyright:: +* Introduction:: +* Realm Configuration Decisions:: +* Building Kerberos V5:: +* Installing Kerberos V5:: +* Upgrading Existing Kerberos V5 Installations:: +* Bug Reports for Kerberos V5:: +@end menu + +@node Copyright, Introduction, Top, Top +@unnumbered Copyright +@include copyright.texinfo + +@node Introduction, Realm Configuration Decisions, Copyright, Top +@chapter Introduction + +@menu +* What is Kerberos and How Does it Work?:: +* Why Should I use Kerberos?:: +* Please Read the Documentation:: +* Overview of This Guide:: +@end menu + +@node What is Kerberos and How Does it Work?, Why Should I use Kerberos?, Introduction, Introduction +@section What is Kerberos and How Does it Work? + +@value{PRODUCT} is based on the Kerberos authentication system developed +at MIT. Under Kerberos, a client (generally either a user or a service) +sends a request for a ticket to the Key Distribution Center (KDC). The +KDC creates a @dfn{ticket-granting ticket} (TGT) for the client, +encrypts it using the client's password as the key, and sends the +encrypted TGT back to the client. The client then attempts to decrypt +the TGT, using its password. If the client successfully decrypts the +TGT (@i{i.e.}, if the client gave the correct password), it keeps the +decrypted TGT, which indicates proof of the client's identity. + +The TGT, which expires at a specified time, permits the client to obtain +additional tickets, which give permission for specific services. The +requesting and granting of these additional tickets is user-transparent. + +@node Why Should I use Kerberos?, Please Read the Documentation, What is Kerberos and How Does it Work?, Introduction +@section Why Should I use Kerberos? + +Since Kerberos negotiates authenticated, and optionally encrypted, +communications between two points anywhere on the Internet, it provides +a layer of security that is not dependent on which side of a firewall +either client is on. Since studies have shown that half of the computer +security breaches in industry happen from @i{inside} firewalls, +@value{PRODUCT} from @value{COMPANY} will play a vital role in the +security of your network. + +@node Please Read the Documentation, Overview of This Guide, Why Should I use Kerberos?, Introduction +@section Please Read the Documentation + +As with any software package that uses a centrallized database, the +installation procedure is somewhat involved, and requires forethought +and planning. @value{COMPANY} has attempted to make this +@value{PRODUCT} Installation Guide as concise as possible, rather than +making it an exhaustive description of the details of Kerberos. +@ifset CYGNUS +Consequently, everything in this guide appears because @value{COMPANY} +believes that it is important. Please read and follow these +instructions carefully, and if there is anything you do not understand +or are not sure of, please don't hesitate to call us. +@end ifset +@ifset MIT +Consequently, everything in this guide appears because @value{COMPANY} +believes that it is important. Please read and follow these +instructions carefully. +@end ifset + +@include document-list.texinfo + +@node Overview of This Guide, , Please Read the Documentation, Introduction +@section Overview of This Guide + +@noindent +The next chapter describes the decisions you need to make before +installing @value{PRODUCT}. + +@noindent +Chapter three provided instructions for building the Kerberos sources. + +@noindent +Chapter four describes installation procedures for each class of +Kerberos machines: + +@enumerate +@item +Key Distribution Centers (KDCs). + +@enumerate A +@item +The Master KDC. + +@item +Slave KDCs. +@end enumerate + +@item +UNIX client machines + +@item +UNIX application server machines +@end enumerate + +@noindent +Note that a machine can be both a client machine and an application +server. + +@noindent +Chapter five describes procedure for updating previous installations of +@value{PRODUCT}. + +@noindent +Chapter six describes our problem reporting system. + +@node Realm Configuration Decisions, Building Kerberos V5, Introduction, Top +@chapter Realm Configuration Decisions + +Before installing @value{PRODUCT}, it is necessary to consider the +following issues: + +@itemize @bullet +@item +The name of your Kerberos realm (or the name of each realm, if you need +more than one). + +@item +How you will map your hostnames onto Kerberos realms. + +@item +Which ports your KDC and and kadmin (database access) services will use. + +@item +How many slave KDCs you need and where they should be located. + +@item +The hostnames of your master and slave KDCs. + +@item +How frequently you will propagate the database from the master KDC to +the slave KDCs. + +@item +Whether you need backward compatibility with Kerberos V4. +@end itemize + +@menu +* Kerberos Realms:: +* Mapping Hostnames onto Kerberos Realms:: +* Ports for the KDC and Admin Services:: +* Slave KDCs:: +* Hostnames for the Master and Slave KDCs:: +* Database Propagation:: +@end menu + +@node Kerberos Realms, Mapping Hostnames onto Kerberos Realms, Realm Configuration Decisions, Realm Configuration Decisions +@section Kerberos Realms + +Although your Kerberos realm can be any ASCII string, convention is to +make it the same as your domain name, in upper-case letters. For +example, hosts in the domain @value{SECONDDOMAIN} would be in the +Kerberos realm @value{SECONDREALM}. + +If you need multiple Kerberos realms, @value{COMPANY} recommends that +you use descriptive names which end with your domain name, such as +BOSTON.@value{SECONDREALM} and HOUSTON.@value{SECONDREALM}. + +@node Mapping Hostnames onto Kerberos Realms, Ports for the KDC and Admin Services, Kerberos Realms, Realm Configuration Decisions +@section Mapping Hostnames onto Kerberos Realms + +@include dnstxt.texinfo + +@node Ports for the KDC and Admin Services, Slave KDCs, Mapping Hostnames onto Kerberos Realms, Realm Configuration Decisions +@section Ports for the KDC and Admin Services + +The default ports used by Kerberos are port @value{DefaultPort} for the +KDC@footnote{Kerberos V4 used port @value{DefaultSecondPort}. If +necessary, you can run on both ports for backward compatibility.} and +port @value{DefaultKadmindPort} for the admin server. You can, however, +choose to run on other ports, as long as they are specified in each +host's @code{/etc/services} and @code{krb5.conf} files, and the +@code{kdc.conf} file on each KDC. For a more thorough treatment of +port numbers used by the @value{PRODUCT} programs, refer to the +``Configuring Your Firewall to Work With @value{PRODUCT}'' section of +the @cite{@value{PRODUCT} System Administrator's Guide}. + +@node Slave KDCs, Hostnames for the Master and Slave KDCs, Ports for the KDC and Admin Services, Realm Configuration Decisions +@section Slave KDCs + +Slave KDCs provide an additional source of Kerberos ticket-granting +services in the event of inaccessibility of the master KDC. The number +of slave KDCs you need and the decision of where to place them, both +physically and logically, depends on the specifics of your network. + +All of the Kerberos authentication on your network requires that each +client be able to contact a KDC. Therefore, you need to anticipate any +likely reason a KDC might be unavailable and have a slave KDC to take up +the slack. + +Some considerations include: + +@itemize @bullet +@item +Have at least one slave KDC as a backup, for when the master KDC is +down, is being upgraded, or is otherwise unavailable. + +@item +If your network is split such that a network outage is likely to cause a +network partition (some segment or segments of the network to become cut +off or isolated from other segments), have a slave KDC accessible to +each segment. + +@item +If possible, have at least one slave KDC in a different building from +the master, in case of power outages, fires, or other localized +disasters. +@end itemize + + + +@node Hostnames for the Master and Slave KDCs, Database Propagation, Slave KDCs, Realm Configuration Decisions +@section Hostnames for the Master and Slave KDCs + +@include dnssrv.texinfo + +@node Database Propagation, , Hostnames for the Master and Slave KDCs, Realm Configuration Decisions +@section Database Propagation + +The Kerberos database resides on the master KDC, and must be propagated +regularly (usually by a cron job) to the slave KDCs. In deciding how +frequently the propagation should happen, you will need to balance the +amount of time the propagation takes against the maximum reasonable +amount of time a user should have to wait for a password change to take +effect. + +If the propagation time is longer than this maximum reasonable time +(@i{e.g.,} you have a particularly large database, you have a lot of +slaves, or you experience frequent network delays), you may wish to +cut down on your propagation delay by performing the propagation in +parallel. To do this, have the master KDC propagate the database to one +set of slaves, and then have each of these slaves propagate the database +to additional slaves. + +@node Building Kerberos V5, Installing Kerberos V5, Realm Configuration Decisions, Top +@chapter Building @value{PRODUCT} + +@include build.texinfo + +@node Installing Kerberos V5, Upgrading Existing Kerberos V5 Installations, Building Kerberos V5, Top +@chapter Installing @value{PRODUCT} + +The sections of this chapter describe procedures for installing +@value{PRODUCT} on: + +@enumerate +@item +The KDCs + +@item +UNIX client machines + +@item +UNIX Application Servers +@end enumerate + +@menu +* Installing KDCs:: +* Installing and Configuring UNIX Client Machines:: +* UNIX Application Servers:: +@end menu + +@node Installing KDCs, Installing and Configuring UNIX Client Machines, Installing Kerberos V5, Installing Kerberos V5 +@section Installing KDCs + +The Key Distribution Centers (KDCs) issue Kerberos tickets. Each KDC +contains a copy of the Kerberos database. The master KDC contains the +master copy of the database, which it propagates to the slave KDCs at +regular intervals. All database changes (such as password changes) are +made on the master KDC. + +Slave KDCs provide Kerberos ticket-granting services, but not database +administration. This allows clients to continue to obtain tickets when +the master KDC is unavailable. + +@value{COMPANY} recommends that you install all of your KDCs to be able +to function as either the master or one of the slaves. This will enable +you to easily switch your master KDC with one of the slaves if +necessary. (@xref{Switching Master and Slave KDCs}.) This installation +procedure is based on that recommendation. + +@menu +* Install the Master KDC:: +* Install the Slave KDCs:: +* Back on the Master KDC:: +* Finish Installing the Slave KDCs:: +* Add Kerberos Principals to the Database:: +* Limit Access to the KDCs:: +* Switching Master and Slave KDCs:: +@end menu + +@node Install the Master KDC, Install the Slave KDCs, Installing KDCs, Installing KDCs +@subsection Install the Master KDC + +This installation procedure will require you to go back and forth a +couple of times between the master KDC and each of the slave KDCs. The +first few steps must be done on the master KDC. + +@menu +* Edit the Configuration Files:: +* krb5.conf:: +* kdc.conf:: +* Create the Database:: +* Add Administrators to the Acl File:: +* Add Administrators to the Kerberos Database:: +* Create a kadmind Keytab (optional):: +* Start the Kerberos Daemons:: +@end menu + +@node Edit the Configuration Files, krb5.conf, Install the Master KDC, Install the Master KDC +@subsubsection Edit the Configuration Files + +Modify the configuration files, @code{/etc/krb5.conf} and +@code{@value{ROOTDIR}/var/krb5kdc/kdc.conf} to reflect the correct +information (such as the hostnames and realm name) for your realm. +@value{COMPANY} recommends that you keep @code{krb5.conf} in @code{/etc}. + +Most of the tags in the configuration have default values that will +work well for most sites. There are some tags in the @code{krb5.conf} +file whose values must be specified, and this section will explain +those as well as give an overview of all of the sections in both +configuration files. For more information on changing defaults with +the configuration files, see the @value{PRODUCT} System Administrator's +Guide sections on configuration files. + +@node krb5.conf, kdc.conf, Edit the Configuration Files, Install the Master KDC +@subsubsection krb5.conf + +@include krb5conf.texinfo + +If you are not using DNS TXT records, you must specify the +@code{default_realm} in the @code{libdefaults} section. If you are not +using DNS SRV records, you must include the @code{kdc} tag for each +realm in the @code{realms} section. To communicate with the kadmin +server in each realm, the @code{admin_server} tag must be set in the +@code{realms} section. If your domain name and realm name are not the +same, you must provide a translation in @code{domain_realm}. It is +also higly recommeneded that you create a @code{[logging]} stanza if +the computer will be functioning as a KDC so that the KDC and kadmind +will generate logging output. + +An example @code{krb5.conf} file: + +@smallexample +@group +[libdefaults] + default_realm = @value{PRIMARYREALM} + +[realms] + @value{PRIMARYREALM} = @{ + kdc = @value{KDCSERVER}.@value{PRIMARYDOMAIN} + kdc = @value{KDCSLAVE1}.@value{PRIMARYDOMAIN} + kdc = @value{KDCSLAVE2}.@value{PRIMARYDOMAIN} + admin_server = @value{KDCSERVER}.@value{PRIMARYDOMAIN} + @{ + +[logging] + kdc = FILE:/var/log/krb5kdc.log + admin_server = FILE:/var/log/kadmin.log + default = FILE:/var/log/krb5lib.log +@end group +@end smallexample + +@node kdc.conf, Create the Database, krb5.conf, Install the Master KDC +@subsubsection kdc.conf + +@include kdcconf.texinfo + +@node Create the Database, Add Administrators to the Acl File, kdc.conf, Install the Master KDC +@subsubsection Create the Database + +You will use the @code{kdb5_util} command @emph{on the Master KDC} to +create the Kerberos database and the optional stash file. The +@dfn{stash file} is a local copy of the master key that resides in +encrypted form on the KDC's local disk. The stash file is used to +authenticate the KDC to itself automatically before starting the +@code{kadmind} and @code{krb5kdc} daemons (@i{e.g.,} as part of the +machine's boot sequence). The stash file, like the keytab file +(see @xref{The Keytab File}, for more information) is a potential +point-of-entry for a break-in, +and if compromised, would allow unrestricted access to the Kerberos +database. If you choose to install a stash file, it should be readable +only by root, and should exist only on the KDC's local disk. The file +should not be part of any backup of the machine, unless access to the +backup data is secured as tightly as access to the master password +itself. + +If you choose not to install a stash file, the KDC will prompt you for +the master key each time it starts up. This means that the KDC will +not be able to start automatically, such as after a system reboot. + +Note that @code{kdb5_util} will prompt you for the master key for the +Kerberos database. This key can be any string. A good key is one you +can remember, but that no one else can guess. Examples of bad keys are +words that can be found in a dictionary, any common or popular name, +especially a famous person (or cartoon character), your username in any +form (@i{e.g.}, forward, backward, repeated twice, @i{etc.}), and any of +the sample keys that appear in this manual. One example of a key which +might be good if it did not appear in this manual is ``MITiys4K5!'', +which represents the sentence ``MIT is your source for Kerberos 5!'' +(It's the first letter of each word, substituting the numeral ``4'' for +the word ``for'', and includes the punctuation mark at the end.) + +The following is an example of how to create a Kerberos database and +stash file on the master KDC, using the @code{kdb5_util} command. (The +line that begins with @result{} is a continuation of the previous line.) +Replace @i{@value{PRIMARYREALM}} with the name of your Kerberos realm. + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/kdb5_util create -r @value{PRIMARYREALM} -s +@b{Initializing database '@value{ROOTDIR}/var/krb5kdc/principal' for +@result{} realm '@value{PRIMARYREALM}', +master key name 'K/M@@@value{PRIMARYREALM}' +You will be prompted for the database Master Password. +It is important that you NOT FORGET this password.} +@iftex +@b{Enter KDC database master key:} @i{@doubleleftarrow{} Type the master password.} +@b{Re-enter KDC database master key to verify:} @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter KDC database master key:} @i{<= Type the master password.} +@b{Re-enter KDC database master key to verify:} @i{<= Type it again.} +@end ifinfo +@ifhtml +@b{Enter KDC database master key:} @i{<= Type the master password.} +@b{Re-enter KDC database master key to verify:} @i{<= Type it again.} +@end ifhtml +@b{shell%} +@end group +@end smallexample + +This will create five files in the directory specified in your +@code{kdc.conf} file: two Kerberos database files, @code{principal.db}, +and @code{principal.ok}; the Kerberos administrative database file, +@code{principal.kadm5}; the administrative database lock file, +@code{principal.kadm5.lock}; and the stash file, @code{.k5stash}. (The +default directory is @code{@value{ROOTDIR}/var/krb5kdc}.) If you do not +want a stash file, run the above command without the @code{-s} option. + +@node Add Administrators to the Acl File, Add Administrators to the Kerberos Database, Create the Database, Install the Master KDC +@subsubsection Add Administrators to the Acl File + +Next, you need create an Access Control List (acl) file, and put the +Kerberos principal of at least one of the administrators into it. This +file is used by the @code{kadmind} daemon to control which principals +may view and make privileged modifications to the Kerberos database +files. The filename should match the value you have set for +``acl_file'' in your @code{kdc.conf} file. The default file name is +@samp{@value{DefaultAclFile}}. + +@include kadm5acl.texinfo + +@node Add Administrators to the Kerberos Database, Create a kadmind Keytab (optional), Add Administrators to the Acl File, Install the Master KDC +@subsubsection Add Administrators to the Kerberos Database + +Next you need to add administrative principals to the Kerberos database. +(You must add at least one now.) To do this, use @code{kadmin.local} +@emph{on the master KDC}. The administrative principals you create +should be the ones you added to the ACL file. (See @xref{Add +Administrators to the Acl File}.) In the following example, the +administration principal @code{admin/admin} is created: + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/kadmin.local +@b{kadmin.local:} addprinc admin/admin@@@value{PRIMARYREALM} +@b{NOTICE: no policy specified for "admin/admin@@@value{PRIMARYREALM}"; +assigning "default".} +@iftex +@b{Enter password for principal admin/admin@@@value{PRIMARYREALM}:} @i{@doubleleftarrow{} Enter a password.} +Re-enter password for principal admin/admin@@@value{PRIMARYREALM}: @i{@doubleleftarrow{} Type it again.} +@end iftex +@ifinfo +@b{Enter password for principal admin/admin@@@value{PRIMARYREALM}:} @i{<= Enter a password.} +Re-enter password for principal admin/admin@@@value{PRIMARYREALM}: @i{<= Type it again.} +@end ifinfo +@ifhtml +@b{Enter password for principal admin/admin@@@value{PRIMARYREALM}:} @i{<= Enter a password.} +Re-enter password for principal admin/admin@@@value{PRIMARYREALM}: @i{<= Type it again.} +@end ifhtml +@b{Principal "admin/admin@@@value{PRIMARYREALM}" created. +kadmin.local:} +@end group +@end smallexample + + + +@node Create a kadmind Keytab (optional), Start the Kerberos Daemons, Add Administrators to the Kerberos Database, Install the Master KDC +@subsubsection Create a kadmind Keytab (optional) + +The kadmind keytab is the key that the legacy admininstration daemons +@code{kadmind4} and @code{v5passwdd} will use to decrypt +administrators' or clients' Kerberos tickets to determine whether or +not they should have access to the database. You need to create the +kadmin keytab with entries for the principals @code{kadmin/admin} and +@code{kadmin/changepw}. (These principals are placed in the Kerberos +database automatically when you create it.) To create the kadmin +keytab, run @code{kadmin.local} and use the @code{ktadd} command, as +in the following example. (The line beginning with @result{} is a +continuation of the previous line.): + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/kadmin.local +@b{kadmin.local:} ktadd -k @value{ROOTDIR}/var/krb5kdc/kadm5.keytab +@result{} kadmin/admin kadmin/changepw +@b{ Entry for principal kadmin/admin with kvno 5, encryption + type Triple DES cbc mode with HMAC/sha1 added to keytab + WRFILE:/usr/local/var/krb5kdc/kadm5.keytab. +Entry for principal kadmin/admin with kvno 5, encryption type DES cbc mode + with CRC-32 added to keytab + WRFILE:/usr/local/var/krb5kdc/kadm5.keytab. +Entry for principal kadmin/changepw with kvno 5, encryption + type Triple DES cbc mode with HMAC/sha1 added to keytab + WRFILE:/usr/local/var/krb5kdc/kadm5.keytab. +Entry for principal kadmin/changepw with kvno 5, + encryption type DES cbc mode with CRC-32 added to keytab + WRFILE:/usr/local/var/krb5kdc/kadm5.keytab. +kadmin.local:} quit +@b{shell%} +@end group +@end smallexample + +@noindent +As specified in the @samp{-k} argument, @code{ktadd} will save the +extracted keytab as @* @code{@value{ROOTDIR}/var/krb5kdc/kadm5.keytab}. +The filename you use must be the one specified in your @code{kdc.conf} +file. + +@need 2000 +@node Start the Kerberos Daemons, , Create a kadmind Keytab (optional), Install the Master KDC +@subsubsection Start the Kerberos Daemons on the Master KDC + +At this point, you are ready to start the Kerberos daemons on the Master +KDC. To do so, type: + +@smallexample +@b{shell%} @value{ROOTDIR}/sbin/krb5kdc +@b{shell%} @value{ROOTDIR}/sbin/kadmind +@end smallexample + +@noindent +Each daemon will fork and run in the background. Assuming you want +these daemons to start up automatically at boot time, you can add them +to the KDC's @code{/etc/rc} or @code{/etc/inittab} file. You need to +have a stash file in order to do this. + +You can verify that they started properly by checking for their startup +messages in the logging locations you defined in @code{/etc/krb5.conf}. +(@xref{Edit the Configuration Files}.) For example: + +@smallexample +@b{shell%} tail /var/log/krb5kdc.log +Dec 02 12:35:47 beeblebrox krb5kdc[3187](info): commencing operation +@b{shell%} tail /var/log/kadmin.log +Dec 02 12:35:52 beeblebrox kadmind[3189](info): starting +@end smallexample + +Any errors the daemons encounter while starting will also be listed in +the logging output. + + +@node Install the Slave KDCs, Back on the Master KDC, Install the Master KDC, Installing KDCs +@subsection Install the Slave KDCs + +You are now ready to start configuring the slave KDCs. Assuming you are +setting the KDCs up so that you can easily switch the master KDC with +one of the slaves, you should perform each of these steps on the master +KDC as well as the slave KDCs, unless these instructions specify +otherwise. + + +@menu +* Create Host Keys for the Slave KDCs:: +* Extract Host Keytabs for the KDCs:: +* Set Up the Slave KDCs for Database Propagation:: +@end menu + +@node Create Host Keys for the Slave KDCs, Extract Host Keytabs for the KDCs, Install the Slave KDCs, Install the Slave KDCs +@subsubsection Create Host Keys for the Slave KDCs + +Each KDC needs a host principal in the Kerberos database. You can enter +these from any host, once the @code{kadmind} daemon is running. For +example, if your master KDC were called +@value{KDCSERVER}.@value{PRIMARYDOMAIN}, and you had two KDC slaves +named @value{KDCSLAVE1}.@value{PRIMARYDOMAIN} and +@value{KDCSLAVE2}.@value{PRIMARYDOMAIN}, you would type the following: + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/kadmin +@b{kadmin:} addprinc -randkey host/@value{KDCSERVER}.@value{PRIMARYDOMAIN} +@b{NOTICE: no policy specified for "host/@value{KDCSERVER}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}"; +assigning "default" +Principal "host/@value{KDCSERVER}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}" created. +kadmin:} addprinc -randkey host/@value{KDCSLAVE1}.@value{PRIMARYDOMAIN} +@b{NOTICE: no policy specified for "host/@value{KDCSLAVE1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}"; +assigning "default" +Principal "host/@value{KDCSLAVE1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}" created.} +@b{kadmin:} addprinc -randkey host/@value{KDCSLAVE2}.@value{PRIMARYDOMAIN} +@b{NOTICE: no policy specified for "host/@value{KDCSLAVE2}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}"; +assigning "default" +Principal "host/@value{KDCSLAVE2}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}" created. +kadmin:} +@end group +@end smallexample + +@noindent +It is not actually necessary to have the master KDC server in the +Kerberos database, but it can be handy if: + +@itemize @bullet +@item +anyone will be logging into the machine as something other than root + +@item +you want to be able to swap the master KDC with one of the slaves if +necessary. +@end itemize + +@node Extract Host Keytabs for the KDCs, Set Up the Slave KDCs for Database Propagation, Create Host Keys for the Slave KDCs, Install the Slave KDCs +@subsubsection Extract Host Keytabs for the KDCs + +Each KDC (including the master) needs a keytab to decrypt tickets. +Ideally, you should extract each keytab locally on its own KDC. If this +is not feasible, you should use an encrypted session to send them across +the network. To extract a keytab on a KDC called +@value{KDCSERVER}.@value{PRIMARYDOMAIN}, you would execute the following +command: + +@smallexample +@group +@b{kadmin:} ktadd host/@value{KDCSERVER}.@value{PRIMARYDOMAIN} +@b{kadmin: Entry for principal host/@value{KDCSERVER}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} with + kvno 1, encryption type DES-CBC-CRC added to keytab + WRFILE:/etc/krb5.keytab. +kadmin:} +@end group +@end smallexample + +@noindent +Note that the principal must exist in the Kerberos database in order to +extract the keytab. + +@node Set Up the Slave KDCs for Database Propagation, , Extract Host Keytabs for the KDCs, Install the Slave KDCs +@subsubsection Set Up the Slave KDCs for Database Propagation + +The database is propagated from the master KDC to the slave KDCs via the +@code{kpropd} daemon. To set up propagation, create a file on each KDC, +named @code{@value{ROOTDIR}/var/krb5kdc/kpropd.acl}, containing the +principals for each of the KDCs. +@need 1200 +For example, if the master KDC were +@code{@value{KDCSERVER}.@value{PRIMARYDOMAIN}}, the slave KDCs were +@code{@value{KDCSLAVE1}.@value{PRIMARYDOMAIN}} and +@code{@value{KDCSLAVE2}.@value{PRIMARYDOMAIN}}, and the realm were +@code{@value{PRIMARYREALM}}, then the file's contents would be: + +@smallexample +@group +host/@value{KDCSERVER}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} +host/@value{KDCSLAVE1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} +host/@value{KDCSLAVE2}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} +@end group +@end smallexample + +@need 1000 +Then, add the following lines to @code{/etc/inetd.conf} file on each KDC +(the line beginnng with @result{} is a continuation of the previous +line): + +@smallexample +@group +krb5_prop stream tcp nowait root @value{ROOTDIR}/sbin/kpropd kpropd +eklogin stream tcp nowait root @value{ROOTDIR}/sbin/klogind +@result{} klogind -k -c -e +@end group +@end smallexample + +@noindent +The first line sets up the @code{kpropd} database propagation daemon. +The second line sets up the @code{eklogin} daemon, allowing +Kerberos-authenticated, encrypted rlogin to the KDC. + +You also need to add the following lines to @code{/etc/services} on each +KDC: + +@smallexample +@group +kerberos 88/udp kdc # Kerberos authentication (udp) +kerberos 88/tcp kdc # Kerberos authentication (tcp) +krb5_prop 754/tcp # Kerberos slave propagation +kerberos-adm 749/tcp # Kerberos 5 admin/changepw (tcp) +kerberos-adm 749/udp # Kerberos 5 admin/changepw (udp) +eklogin 2105/tcp # Kerberos encrypted rlogin +@end group +@end smallexample + +@node Back on the Master KDC, Finish Installing the Slave KDCs, Install the Slave KDCs, Installing KDCs +@subsection Back on the Master KDC + +Now that the slave KDCs are able to accept database propagation, you'll +need to propagate the database to each of them. + +@menu +* Propagate the Database to Each Slave KDC:: +@end menu + +@node Propagate the Database to Each Slave KDC, , Back on the Master KDC, Back on the Master KDC +@subsubsection Propagate the Database to Each Slave KDC + +First, create a dump of the database on the master KDC, as follows: + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/kdb5_util dump @value{ROOTDIR}/var/krb5kdc/slave_datatrans +@b{shell%} +@end group +@end smallexample + +Next, you need to manually propagate the database to each slave KDC, as +in the following example. (The lines beginning with @result{} are +continuations of the previous line.): + +@smallexample +@group +@value{ROOTDIR}/sbin/kprop -f @value{ROOTDIR}/var/krb5kdc/slave_datatrans +@result{} @value{KDCSLAVE1}.@value{PRIMARYDOMAIN} +@value{ROOTDIR}/sbin/kprop -f @value{ROOTDIR}/var/krb5kdc/slave_datatrans +@result{} @value{KDCSLAVE2}.@value{PRIMARYDOMAIN} +@end group +@end smallexample + +You will need a script to dump and propagate the database. The +following is an example of a bourne shell script that will do this. +(Note that the line that begins with @result{} is a continuation of the +previous line. Remember that you need to replace @value{ROOTDIR} with +the name of the directory in which you installed @value{PRODUCT}.) + +@smallexample +@group +#!/bin/sh + +kdclist = "@value{KDCSLAVE1}.@value{PRIMARYDOMAIN} @value{KDCSLAVE2}.@value{PRIMARYDOMAIN}" + +@value{ROOTDIR}/sbin/kdb5_util "dump +@result{} @value{ROOTDIR}/var/krb5kdc/slave_datatrans" + +for kdc in $kdclist +do +@value{ROOTDIR}/sbin/kprop -f @value{ROOTDIR}/var/krb5kdc/slave_datatrans $kdc +done +@end group +@end smallexample + +@noindent +You will need to set up a cron job to run this script at the intervals +you decided on earlier (@xref{Database Propagation}.) + +@node Finish Installing the Slave KDCs, Add Kerberos Principals to the Database, Back on the Master KDC, Installing KDCs +@subsection Finish Installing the Slave KDCs + +Now that the slave KDCs have copies of the Kerberos database, you can +create stash files for them and start the @code{krb5kdc} daemon. + +@menu +* Create Stash Files on the Slave KDCs:: +* Start the krb5kdc Daemon on Each KDC:: +@end menu + +@node Create Stash Files on the Slave KDCs, Start the krb5kdc Daemon on Each KDC, Finish Installing the Slave KDCs, Finish Installing the Slave KDCs +@subsubsection Create Stash Files on the Slave KDCs + +Create stash files, by issuing the following commands on each slave KDC: + +@smallexample +@group +@b{shell%} kdb5_util stash +@b{kdb5_util: Cannot find/read stored master key while reading master key +kdb5_util: Warning: proceeding without master key} +@iftex +@b{Enter KDC database master key:} @i{@doubleleftarrow{} Enter the database master key.} +@end iftex +@ifinfo +@b{Enter KDC database master key:} @i{<= Enter the database master key.} +@end ifinfo +@ifhtml +@b{Enter KDC database master key:} @i{<= Enter the database master key.} +@end ifhtml +@b{shell%} +@end group +@end smallexample + +As mentioned above, the stash file is necessary for your KDCs to be able +authenticate to themselves, such as when they reboot. You could run +your KDCs without stash files, but you would then need to type in the +Kerberos database master key by hand every time you start a KDC daemon. + +@node Start the krb5kdc Daemon on Each KDC, , Create Stash Files on the Slave KDCs, Finish Installing the Slave KDCs +@subsubsection Start the krb5kdc Daemon on Each KDC + +The final step in configuing your slave KDCs is to run the KDC daemon: + +@smallexample +@group +@b{shell%} @value{ROOTDIR}/sbin/krb5kdc +@end group +@end smallexample + +As with the master KDC, you will probably want to add this command to +the KDCs' @code{/etc/rc} or @code{/etc/inittab} files, so they will +start the krb5kdc daemon automatically at boot time. + +@node Add Kerberos Principals to the Database, Limit Access to the KDCs, Finish Installing the Slave KDCs, Installing KDCs +@subsection Add Kerberos Principals to the Database + +@need 1800 +Once your KDCs are set up and running, you are ready to use +@code{kadmin} to load principals for your users, hosts, and other +services into the Kerberos database. This procedure is described fully in the +``Adding or Modifying Principals'' section of the @value{PRODUCT} System +Administrator's Guide. (@xref{Create Host Keys for the Slave KDCs}, for a +brief description.) The keytab is generated by running @code{kadmin} +and issuing the @code{ktadd} command. + +@node Limit Access to the KDCs, Switching Master and Slave KDCs, Add Kerberos Principals to the Database, Installing KDCs +@subsection Limit Access to the KDCs + +To limit the possibility that your Kerberos database could be +compromised, @value{COMPANY} recommends that each KDC be a dedicated +host, with limited access. If your KDC is also a file server, FTP +server, Web server, or even just a client machine, someone who obtained +root access through a security hole in any of those areas could gain +access to the Kerberos database. + +@need 4700 +@value{COMPANY} recommends that your KDCs use the following +@code{/etc/inetd.conf} file. (Note: each line beginning with @result{} +is a continuation of the previous line.): + +@smallexample +@group +# +# Configuration file for inetd(1M). See inetd.conf(4). +# +# To re-configure the running inetd process, edit this file, then +# send the inetd process a SIGHUP. +# +# Syntax for socket-based Internet services: +# +@result{} +# +# Syntax for TLI-based Internet services: +# +# tli +# +# Ftp and telnet are standard Internet services. +# +# This machine is a secure Kerberos Key Distribution Center (KDC). +# Services are limited. +# +# +# Time service is used for clock synchronization. +# +time stream tcp nowait root internal +time dgram udp wait root internal +# +# Limited Kerberos services +# +krb5_prop stream tcp nowait root @value{ROOTDIR}/sbin/kpropd kpropd +eklogin stream tcp nowait root @value{ROOTDIR}/sbin/klogind +@result{} klogind -5 -c -e +@end group +@end smallexample + +@node Switching Master and Slave KDCs, , Limit Access to the KDCs, Installing KDCs +@subsection Switching Master and Slave KDCs + +You may occasionally want to use one of your slave KDCs as the master. +This might happen if you are upgrading the master KDC, or if your master +KDC has a disk crash. + +Assuming you have configured all of your KDCs to be able to function as +either the master KDC or a slave KDC (as this document recommends), all +you need to do to make the changeover is: + +If the master KDC is still running, do the following on the @emph{old} +master KDC: + +@enumerate +@item +Kill the @code{kadmind} process. + +@item +Disable the cron job that propagates the database. + +@item +Run your database propagation script manually, to ensure that the slaves +all have the latest copy of the database. (@xref{Propagate the Database +to Each Slave KDC}.) If there is a need to preserve per-principal +policy information from the database, you should do a ``kdb5_util dump +-ov'' in order to preserve that information and propogate that dump file +securely by some means to the slave so that its database has the correct +state of the per-principal policy information. +@end enumerate + +On the @emph{new} master KDC: + +@enumerate +@item +Create a database keytab. (@xref{Create a kadmind Keytab (optional)}.) + +@item +Start the @code{kadmind} daemon. (@xref{Start the Kerberos Daemons}.) + +@item +Set up the cron job to propagate the database. (@xref{Propagate the +Database to Each Slave KDC}.) + +@item +Switch the CNAMEs of the old and new master KDCs. (If you don't do +this, you'll need to change the @code{krb5.conf} file on every client +machine in your Kerberos realm.) + +@end enumerate + +@node Installing and Configuring UNIX Client Machines, UNIX Application Servers, Installing KDCs, Installing Kerberos V5 +@section Installing and Configuring UNIX Client Machines + +Client machine installation is much more straightforward than +installation of the KDCs. + +@menu +* Client Programs:: +* Client Machine Configuration Files:: +@end menu + +@node Client Programs, Client Machine Configuration Files, Installing and Configuring UNIX Client Machines, Installing and Configuring UNIX Client Machines +@subsection Client Programs + +The Kerberized client programs are @code{login.krb5}, @code{rlogin}, +@code{telnet}, @code{ftp}, @code{rcp}, @code{rsh}, @code{kinit}, +@code{klist}, @code{kdestroy}, @code{kpasswd}, @code{ksu}, and +@code{krb524init}. All of these programs are in the directory +@code{@value{ROOTDIR}/bin}, except for @code{login.krb5} which is in +@code{@value{ROOTDIR}/sbin}. + +You will probably want to have your users put @code{@value{ROOTDIR}/bin} +ahead of @code{/bin} and @code{/usr/bin} in their paths, so they will by +default get the @value{PRODUCT} versions of @code{rlogin}, +@code{telnet}, @code{ftp}, @code{rcp}, and @code{rsh}. + +@value{COMPANY} recommends that you use @code{login.krb5} in place of +@code{/bin/login} to give your users a single-sign-on system. You will +need to make sure your users know to use their Kerberos passwords when +they log in. + +You will also need to educate your users to use the ticket management +programs @code{kinit}, +@c @code{krb524init}, +@code{klist}, @code{kdestroy}, and to use the Kerberos programs +@c @code{pfrom}, +@code{ksu}, and @code{kpasswd} in place of their non-Kerberos +counterparts +@c @code{from} +@code{su}, @code{passwd}, and @code{rdist}. + +@node Client Machine Configuration Files, , Client Programs, Installing and Configuring UNIX Client Machines +@subsection Client Machine Configuration Files + +Each machine running Kerberos must have a @code{/etc/krb5.conf} file. +(@xref{krb5.conf}.) + +@need 4000 +Also, for most UNIX systems, you must add the appropriate Kerberos +services to each client machine's @code{/etc/services} file. If you are +using the default configuration for @value{PRODUCT}, you should be able +to just insert the following code: + +@smallexample +@group +# +# Note --- if you are using Kerberos V4 and you either: +# +# (a) haven't converted all your master or slave KDCs to V5, or +# +# (b) are worried about inter-realm interoperability with other KDC's +# that are still using V4 +# +# you will need to switch the "kerberos" service to port 750 and create a +# "kerberos-sec" service on port 88. +# +kerberos @value{DefaultPort}/udp kdc # Kerberos V5 KDC +kerberos @value{DefaultPort}/tcp kdc # Kerberos V5 KDC +klogin @value{DefaultKloginPort}/tcp # Kerberos authenticated rlogin +kshell @value{DefaultKshellPort}/tcp cmd # and remote shell +kerberos-adm @value{DefaultKadmindPort}/tcp # Kerberos 5 admin/changepw +kerberos-adm @value{DefaultKadmindPort}/udp # Kerberos 5 admin/changepw +krb5_prop @value{DefaultKrbPropPort}/tcp # Kerberos slave propagation +@c kpop 1109/tcp # Pop with Kerberos +eklogin @value{DefaultEkloginPort}/tcp # Kerberos auth. & encrypted rlogin +krb524 @value{DefaultKrb524Port}/tcp # Kerberos 5 to 4 ticket translator +@end group +@end smallexample + +@noindent As described in the comments in the above code, if your master +KDC or any of your slave KDCs is running Kerberos V4, (or if you will be +authenticating to any Kerberos V4 KDCs in another realm) you will need +to switch the port number for @code{kerberos} to 750 and create a +@code{kerberos-sec} service (tcp and udp) on port 88, so the Kerberos +V4 KDC(s) will continue to work properly. + +@menu +* Mac OS X Configuration:: +@end menu + +@node Mac OS X Configuration, , Client Machine Configuration Files, Client Machine Configuration Files +@subsubsection Mac OS X Configuration + +To install Kerberos V5 on Mac OS X and Mac OS X Server, follow the +directions for generic Unix-based OS's, except for the +@code{/etc/services} updates described above. + +Mac OS X and Mac OS X Server use a database called NetInfo to store +the contents of files normally found in @code{/etc}. Instead of +modifying @code{/etc/services}, you should run the following commands +to add the Kerberos service entries to NetInfo: + +@smallexample +@group +$ niutil -create . /services/kerberos +$ niutil -createprop . /services/kerberos name kerberos kdc +$ niutil -createprop . /services/kerberos port 750 +$ niutil -createprop . /services/kerberos protocol tcp udp +$ niutil -create . /services/krbupdate +$ niutil -createprop . /services/krbupdate name krbupdate kreg +$ niutil -createprop . /services/krbupdate port 760 +$ niutil -createprop . /services/krbupdate protocol tcp +$ niutil -create . /services/kpasswd +$ niutil -createprop . /services/kpasswd name kpasswd kpwd +$ niutil -createprop . /services/kpasswd port 761 +$ niutil -createprop . /services/kpasswd protocol tcp +$ niutil -create . /services/klogin +$ niutil -createprop . /services/klogin port 543 +$ niutil -createprop . /services/klogin protocol tcp +$ niutil -create . /services/eklogin +$ niutil -createprop . /services/eklogin port 2105 +$ niutil -createprop . /services/eklogin protocol tcp +$ niutil -create . /services/kshell +$ niutil -createprop . /services/kshell name kshell krcmd +$ niutil -createprop . /services/kshell port 544 +$ niutil -createprop . /services/kshell protocol tcp +@end group +@end smallexample + +In addition to adding services to NetInfo, you must also modify the +resolver configuration in NetInfo so that the machine resolves its own +hostname as a FQDN (fully qualified domain name). By default, Mac OS X +and Mac OS X Server machines query NetInfo to resolve hostnames before +falling back to DNS. Because NetInfo has an unqualified name for all +the machines in the NetInfo database, the machine's own hostname will +resolve to an unqualified name. Kerberos needs a FQDN to look up keys +in the machine's keytab file. + +Fortunately, you can change the @code{lookupd} caching order to query +DNS first. Run the following NetInfo commands and reboot the machine: + +@smallexample +@group +$ niutil -create . /locations/lookupd/hosts +$ niutil -createprop . /locations/lookupd/hosts LookupOrder CacheAgent DNSAgent + NIAgent NILAgent +@end group +@end smallexample + +Once you have rebooted, you can verify that the resolver now behaves +correctly. Compile the Kerberos 5 distribution and run: + +@smallexample +@group +$ cd .../src/tests/resolve +$ ./resolve +@end group +@end smallexample + +This will tell you whether or not your machine returns FQDNs on name +lookups. If the test still fails, you can also try turning off DNS +caching. Run the following commands and reboot: + +@smallexample +@group +$ niutil -create . /locations/lookupd/hosts +$ niutil -createprop . /locations/lookupd/hosts LookupOrder DNSAgent + CacheAgent NIAgent NILAgent +@end group +@end smallexample + +The remainder of the setup of a Mac OS X client machine or application +server should be the same as for other UNIX-based systems. + +@node UNIX Application Servers, , Installing and Configuring UNIX Client Machines, Installing Kerberos V5 +@section UNIX Application Servers + +An application server is a host that provides one or more services over +the network. Application servers can be ``secure'' or ``insecure.'' A +``secure'' host is set up to require authentication from every client +connecting to it. An ``insecure'' host will still provide Kerberos +authentication, but will also allow unauthenticated clients to connect. + +If you have @value{PRODUCT} installed on all of your client machines, +@value{COMPANY} recommends that you make your hosts secure, to take +advantage of the security that Kerberos authentication affords. +However, if you have some clients that do not have @value{PRODUCT} +installed, you can run an insecure server, and still take advantage of +@value{PRODUCT}'s single sign-on capability. + +@menu +* Server Programs:: +* Server Configuration Files:: +* The Keytab File:: +* Some Advice about Secure Hosts:: +@end menu + +@node Server Programs, Server Configuration Files, UNIX Application Servers, UNIX Application Servers +@subsection Server Programs + +Just as @value{PRODUCT} provided its own Kerberos-enhanced versions of +client UNIX network programs, @value{PRODUCT} also provides +Kerberos-enhanced versions of server UNIX network daemons. These are +@code{ftpd}, @code{klogind}, @code{kshd}, and @code{telnetd}. +@c @code{popper}, +These programs are installed in the directory +@code{@value{ROOTDIR}/sbin}. You may want to add this directory to +root's path. + +@node Server Configuration Files, The Keytab File, Server Programs, UNIX Application Servers +@subsection Server Configuration Files + +For a @emph{secure} server, make the following changes to +@code{/etc/inetd.conf}: + +Find and comment out any lines for the services @code{ftp}, +@code{telnet}, @code{shell}, @code{login}, and @code{exec}. + +@need 1800 +Add the following lines. (Note: each line beginning with @result{} is +a continuation of the previous line.) + +@smallexample +@group +klogin stream tcp nowait root @value{ROOTDIR}/sbin/klogind +@result{} klogind -k -c +eklogin stream tcp nowait root @value{ROOTDIR}/sbin/klogind +@result{} klogind -k -c -e +kshell stream tcp nowait root @value{ROOTDIR}/sbin/kshd +@result{} kshd -k -c -A +ftp stream tcp nowait root @value{ROOTDIR}/sbin/ftpd +@result{} ftpd -a +telnet stream tcp nowait root @value{ROOTDIR}/sbin/telnetd +@result{} telnetd -a valid +@end group +@end smallexample + +For an @emph{insecure} server, make the following changes instead to +@code{/etc/inetd.conf}: + +@need 1800 +Find and comment out any lines for the services @code{ftp} and +@code{telnet}. + +Add the following lines. (Note: each line beginning with @result{} is +a continuation of the previous line.) +@smallexample +@group +klogin stream tcp nowait root @value{ROOTDIR}/sbin/klogind +@result{} klogind -k -c +eklogin stream tcp nowait root @value{ROOTDIR}/sbin/klogind +@result{} klogind -k -c -e +kshell stream tcp nowait root @value{ROOTDIR}/sbin/kshd +@result{} kshd -k -c -A +ftp stream tcp nowait root @value{ROOTDIR}/sbin/ftpd +@result{} ftpd +telnet stream tcp nowait root @value{ROOTDIR}/sbin/telnetd +@result{} telnetd -a none +@end group +@end smallexample + +@node The Keytab File, Some Advice about Secure Hosts, Server Configuration Files, UNIX Application Servers +@subsection The Keytab File + +All Kerberos server machines need a @dfn{keytab} file, called +@code{/etc/krb5.keytab}, to authenticate to the KDC. The keytab file is +an encrypted, local, on-disk copy of the host's key. The keytab file, +like the stash file (@ref{Create the Database}) is a potential +point-of-entry for a break-in, and if compromised, would allow +unrestricted access to its host. The keytab file should be readable +only by root, and should exist only on the machine's local disk. The +file should not be part of any backup of the machine, unless access to +the backup data is secured as tightly as access to the machine's root +password itself. + +In order to generate a keytab for a host, the host must have a principal +in the Kerberos database. The procedure for adding hosts to the +database is described fully in the ``Adding or Modifying Principals'' +section of the @cite{@value{PRODUCT} System Administrator's Guide}. +@xref{Create Host Keys for the Slave KDCs}. for a brief description.) +The keytab is generated by running @code{kadmin} and issuing the +@code{ktadd} command. + +@need 1100 +For example, to generate a keytab file to allow the host +trillium.@value{PRIMARYDOMAIN} to authenticate for the services +@code{host}, @code{ftp}, and @code{pop}, the administrator +@code{@value{ADMINUSER}} would issue the command (on +trillium.@value{PRIMARYDOMAIN}): + +@smallexample +@group +@b{trillium%} @value{ROOTDIR}/sbin/kadmin +@b{kadmin5:} ktadd host/trillium.@value{PRIMARYDOMAIN} ftp/trillium.@value{PRIMARYDOMAIN} +@result{} pop/trillium.@value{PRIMARYDOMAIN} +@b{kadmin: Entry for principal host/trillium.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} with +kvno 3, encryption type DES-CBC-CRC added to keytab +WRFILE:/etc/krb5.keytab. +kadmin: Entry for principal ftp/trillium.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} with +kvno 3, encryption type DES-CBC-CRC added to keytab +WRFILE:/etc/krb5.keytab. +kadmin: Entry for principal pop/trillium.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM} with +kvno 3, encryption type DES-CBC-CRC added to keytab +WRFILE:/etc/krb5.keytab. +kadmin5:} quit +@b{trillium%} +@end group +@end smallexample + +If you generate the keytab file on another host, you need to get a copy +of the keytab file onto the destination host (@code{trillium}, in the +above example) without sending it unencrypted over the network. If you +have installed the @value{PRODUCT} client programs, you can use +encrypted @code{rcp}. + +@node Some Advice about Secure Hosts, , The Keytab File, UNIX Application Servers +@subsection Some Advice about Secure Hosts + +@value{PRODUCT} can protect your host from certain types of break-ins, +but it is possible to install @value{PRODUCT} and still leave your host +vulnerable to attack. Obviously an installation guide is not the place +to try to include an exhaustive list of countermeasures for every +possible attack, but it is worth noting some of the larger holes and how +to close them. + +As stated earlier in this section, @value{COMPANY} recommends that on a +secure host, you disable the standard @code{ftp}, @code{login}, +@code{telnet}, @code{shell}, and @code{exec} services in +@code{/etc/inetd.conf}. We also recommend that secure hosts have an empty +@code{/etc/hosts.equiv} file and that there not be a @code{.rhosts} file +in @code{root}'s home directory. You can grant Kerberos-authenticated +root access to specific Kerberos principals by placing those principals +in the file @code{.k5login} in root's home directory. + +We recommend that backups of secure machines exclude the keytab file +(@code{/etc/krb5.keytab}). If this is not possible, the backups should +at least be done locally, rather than over a network, and the backup +tapes should be physically secured. + +Finally, the keytab file and any programs run by root, including the +@value{PRODUCT} binaries, should be kept on local disk. The keytab file +should be readable only by root. + +@node Upgrading Existing Kerberos V5 Installations, Bug Reports for Kerberos V5, Installing Kerberos V5, Top +@chapter Upgrading Existing @value{PRODUCT} Installations + +If you already have an existing Kerberos database that you created with +a prior release of Kerberos 5, you can upgrade it to work with the +current release with the @code{kdb5_util} command. It is only +necessary to perform this dump/undump procedure if you were running a +krb5-1.0.x KDC and are migrating to a krb5-1.1.x or newer KDC or if you +were running a krb5-1.1.x KDC and are migrating to a krb5-1.2.x or newer +KDC. The process for upgrading a Master KDC involves the following +steps: + +@enumerate + +@item Stop your current KDC and administration +server processes, if any. + +@item Dump your existing Kerberos database to an ASCII file with +@code{kdb5_util}'s ``dump'' command: + +@smallexample +@group +@b{shell%} cd @value{ROOTDIR}/var/krb5kdc +@b{shell%} kdb5_util dump old-kdb-dump +@b{shell%} kdb5_util dump -ov old-kdb-dump.ov +@b{shell%} +@end group +@end smallexample + +@item Create a new Master KDC installation (@xref{Install the Master +KDC}.). If you have a stash file for your current database, choose any +new master password but then copy your existing stash file to the +location specified by your kdc.conf; if you do not have a stash file for +your current database, you must choose the same master password. + +@item Load your old Kerberos database into the new system with +@code{kdb5_util}'s ``load'' command: + +@smallexample +@group +@b{shell%} cd @value{ROOTDIR}/var/krb5kdc +@b{shell%} kdb5_util load old-kdb-dump +@b{shell%} kdb5_util load -update old-kdb-dump.ov +@b{shell%} +@end group +@end smallexample + +@end enumerate + +The ``dump -ov'' and ``load -update'' commands are necessary in order to +preserve per-principal policy information, since the default dump format +filters out that information. If you omit those steps, the loaded +database database will lose the policy information for each principal +that has a policy. + +To update a Slave KDC, you must stop the old server processes on the +Slave KDC, install the new server binaries, reload the most recent slave +dump file, and re-start the server processes. + +@menu +* Upgrading to Triple-DES and RC4 Encryption Keys:: +@end menu + +@node Upgrading to Triple-DES and RC4 Encryption Keys, , Upgrading Existing Kerberos V5 Installations, Upgrading Existing Kerberos V5 Installations +@section Upgrading to Triple-DES Encryption Keys + +Beginning with the 1.2 release from @value{COMPANY}, Kerberos includes +a stronger encryption algorithm called ``triple DES'' -- essentially, +three applications of the basic DES encryption algorithm, greatly +increasing the resistance to a brute-force search for the key by an +attacker. This algorithm is more secure, but encryption is much +slower. + +Release 1.1 had some support for triple-DES service keys, but with +release 1.2 we have added support for user keys and session keys as +well. Release 1.0 had very little support for multiple cryptosystems, +and some of that software may not function properly in an environment +using triple-DES as well as plain DES. + +In the 1.3 release from @value{COMPANY}, Kerberos also includes the RC4 +encryption alogorithm, a stream cipher symmetric key algorithm +developed in 1987 by Ronald Rivest at RSA Data Security. Please note +that RC4 is not part of the IETF standard. + +Because of the way the MIT Kerberos database is structured, the KDC +will assume that a service supports only those encryption types for +which keys are found in the database. Thus, if a service has only a +single-DES key in the database, the KDC will not issue tickets for that +service that use triple-DES or RC4 session keys; it will instead issue +only single-DES session keys, even if other services are already +capable of using triple-DES or RC4. So if you make sure your +application server software is updated before adding a triple-DES or +RC4 key for the service, clients should be able to talk to services at +all times during the updating process. + +Normally, the listed @code{supported_enctypes} in @code{kdc.conf} are +all used when a new key is generated. You can control this with +command-line flags to @code{kadmin} and @code{kadmin.local}. You may +want to exclude triple-DES and RC4 by default until you have updated a +lot of your application servers, and then change the default to include +triple-DES and RC4. We recommend that you always include +@code{des-cbc-crc} in the default list. + +@node Bug Reports for Kerberos V5, , Upgrading Existing Kerberos V5 Installations, Top +@chapter Bug Reports for @value{PRODUCT} + +@include send-pr.texinfo + +@contents +@bye diff --git a/krb5-1-6/doc/kadm5/adb-unit-test.tex b/krb5-1-6/doc/kadm5/adb-unit-test.tex new file mode 100644 index 000000000..d401342df --- /dev/null +++ b/krb5-1-6/doc/kadm5/adb-unit-test.tex @@ -0,0 +1,134 @@ +\documentstyle[times,fullpage,rcsid]{article} + +\rcs$Id$ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\test}[1]{\begin{description} +\setlength{\itemsep}{0pt} +#1 +\end{description} + +} + +\newcommand{\numtest}[2]{\begin{description} +\setlength{\itemsep}{0pt} +\Number{#1} +#2 +\end{description} + +} + +\newcommand{\Number}[1]{\item[Number:] #1} +\newcommand{\Reason}[1]{\item[Reason:] #1} +%\newcommand{\Call}[1]{\item[Call:] #1} +\newcommand{\Expected}[1]{\item[Expected:] #1} +\newcommand{\Conditions}[1]{\item[Conditions:] #1} +\newcommand{\Priority}[1]{\item[Priority:] #1} +\newcommand{\Status}[1]{\item[Status:] #1} +%\newcommand{\Number}[1]{} +%\newcommand{\Reason}[1]{} +\newcommand{\Call}[1]{} +%\newcommand{\Expected}[1]{} +%\newcommand{\Conditions}[1]{} +%\newcommand{\Priority}[1]{} + +\title{OpenV*Secure Admin Database API\\ +Unit Test Description\footnote{\rcsId}} +\author{Jonathan I. Kamens} + +\begin{document} + +\maketitle + +%\tableofcontents + +\section{Introduction} + +The following is a description of a black-box unit test of the +OpenV*Secure Admin Database API (osa_adb). Each API function is +listed, followed by the tests that shoud be performed on it. + +The tests described here are based on the ``OV*Secure Admin Server +Implementation Design'' revision 1.14. + +\section{osa_adb_get_lock and osa_adb_release_lock} + +\numtest{1}{ +\Reason{A shared lock can be acquired.} +\Status{Implemented} +} + +\numtest{2}{ +\Reason{An exclusive lock can be acquired and released.} +\Status{Implemented} +} + +\numtest{3}{ +\Reason{A permanent lock can be acquired and released.} +\Status{Implemented} +} + +\numtest{4}{ +\Reason{Attempting to release a lock when none is held fails with +NOTLOCKED.} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{Two processes can both acquire a shared lock.} +\Status{Implemented} +} + +\numtest{6}{ +\Reason{An attempt to acquire a shared lock while another process holds an +exclusive lock fails with CANTLOCK_DB.} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{An attempt to acquire an exclusive lock while another process holds a +shared lock fails with CANTLOCK_DB.} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{An attempt to open the database while a process holds a +permanent lock fails with NO_LOCKFILE.} +\Status{Implemented} +} + +\numtest{9}{ +\Reason{An attempt to acquire an exclusive lock while a process holds a +permanent lock fails with NO_LOCKFILE.} +\Status{Implemented} +} + +\numtest{10}{ +\Reason{Acquiring a permanent lock deletes the lockfile.} +\Status{Implemented} +} + +\numtest{11}{ +\Reason{Releasing a permanent lock re-creates the lockfile.} +\Status{Implemented} +} + +\numtest{12}{ +\Reason{A process can perform a get operation while another process holds a +shared lock.} +\Status{Implemented} +} + +\numtest{13}{ +\Reason{A process that is running and has opened the adb principal database +can retrieve a principal created after the open occurred.} +\Status{Implemented, but not working} +} + +\end{document} diff --git a/krb5-1-6/doc/kadm5/api-funcspec.tex b/krb5-1-6/doc/kadm5/api-funcspec.tex new file mode 100644 index 000000000..bf885b464 --- /dev/null +++ b/krb5-1-6/doc/kadm5/api-funcspec.tex @@ -0,0 +1,2015 @@ +\documentstyle[12pt,fullpage,rcsid]{article} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\rcs$Id$ + +\setlength{\parskip}{.7\baselineskip} +\setlength{\parindent}{0pt} + +\def\v#1{\verb+#1+} + +\title{Kerberos Administration System \\ + KADM5 API Functional Specifications\thanks{\rcsId}} +\author{Barry Jaspan} + +\begin{document} + +\sloppy +\maketitle + +{\setlength{\parskip}{0pt}\tableofcontents} + +\section{Introduction} + +This document describes the Admin API that can be used to maintain +principals and policies. It describes the data structures used for +each function and the interpretation of each data type field, the +semantics of each API function, and the possible return codes. + +The Admin API is intended to be used by remote clients using an RPC +interface. It is implemented by the admin server running on the +Kerberos master server. It is also possible for a program running on +the Kerberos master server to use the Admin API directly, without +going through the admin server. + +\section{Versions of the API} + +The versions of this API and a brief description of the changes for +each are: + +\begin{description} +\item[KADM5_API_VERSION_1] The initial version of this API, written by +OpenVision Technologies and donated to MIT for including in the public +release. Originally called OVSEC_KADM_API_VERSION_1. Most everything +has been renamed in one way or another, including functions, header +files, and data structures. Where possible, the old OVSEC_KADM names +have been left behind for compatibility with version 1, and +KADM5_API_VERSION_1 is compatible with OVSEC_KADM_API_VERSION_1 at +compile-, link-, and run-time. + +The OVSEC_KADM name compatibility will not be extended to new +functionality in future versions because no existing OVSEC_KADM +clients will use that functionality; new clients should be written to +the KADM5 API. + +\item[KADM5_API_VERSION_2] This version contains the initial changes +necessary to make the OpenVision administration system work with the +mid-1996 MIT version of Kerberos 5. Changes include +\begin{enumerate} +\item The kadm5_init functions now take a structure of parameters +instead of just a realm name, allowing the calling program to specify +non-default values for various configuration options. See section +\ref{sec:configparams} for details. + +\item The KADM5 API has been extended to support new features of the +Kerberos database, including multiple encryption and salt types per +principal. See section \ref{sec:keys} for details. + +\item kadm5_get_principal now allows a principal's keys to be +retrieved {\it by local clients only}. This is necessary in order for +the kadm5 API to provide the primary Kerberos database interface. + +\item The KADM5 authorization system has been completely changed. + +\item The functions kadm5_flush, kadm5_get_principals, and +kadm5_get_policies have been added. + +\item The KADM5 API now obeys a caller-allocates rather than +callee-allocates system. kadm5_get_principal and kadm5_get_policy are +affected. +\end{enumerate} +\end{description} + +\section{Policies and Password Quality} + +The Admin API Password Quality mechanism provides the following +controls. Note that two strings are defined to be ``significantly +different'' if they differ by at least one character. The compare is not +case sensitive. + +\begin{itemize} +\item A minimum length can be required; a password with +fewer than the specified number of characters will not be accepted. + +\item A minimum number of character classes can be required; a +password that does not contain at least one character from at least +the specified number of character classes will not be accepted. The +character classes are defined by islower(), isupper(), isdigit(), +ispunct(), and other. + +\item Passwords can be required to be different from +previous passwords; a password that generates the same encryption key +as any of the principal's specified previous number of passwords will +not be accepted. This comparison is performed on the encryption keys +generated from the passwords, not on the passwords themselves. + +\item A single ``forbidden password'' dictionary can be specified for all +users; a password that is not significantly different from every word +in the dictionary will not be accepted. +\end{itemize} + +\section{Data Structures} + +This section describes the data structures used by the Admin API. +They are defined in $<$kadm5/admin.h$>$. + +\subsection{Principals, kadm5_principal_ent_t} +\label{sec:principal-structure} + +A Kerberos principal entry is represented by a kadm5_principal_ent_t. +It contains a subset of the information stored in the master Kerberos +database as well as the additional information maintained by the admin +system. In the current version, the only additional information is +the principal's policy and the aux_attributes flags. + +The principal may or may not have a policy enforced on it. If the +POLICY bit (see section \ref{sec:masks}) is set in aux_attributes, the +policy field names the principal's policy. If the POLICY bit is not +set in aux_attributes, no policy is enforced on the principal and the +value of the policy field is undefined. + +\begin{figure}[htbp] +\begin{verbatim} +typedef struct _kadm5_principal_ent_t { + krb5_principal principal; + + krb5_timestamp princ_expire_time; + krb5_timestamp last_pwd_change; + krb5_timestamp pw_expiration; + krb5_deltat max_life; + krb5_principal mod_name; + krb5_timestamp mod_date; + krb5_flags attributes; + krb5_kvno kvno; + krb5_kvno mkvno; + + char * policy; + u_int32 aux_attributes; + + krb5_deltat max_renewable_life; + krb5_timestamp last_success; + krb5_timestamp last_failed; + krb5_kvno fail_auth_count; + krb5_int16 n_key_data; + krb5_int16 n_tl_data; + krb5_tl_data *tl_data; + krb5_key_data *key_data; +} kadm5_principal_ent_rec, *kadm5_principal_ent_t; +\end{verbatim} +\caption{Definition of kadm5_principal_ent_t.} +\label{fig:princ-t} +\end{figure} + +The fields of an kadm5_principal_ent_t are interpreted as +follows. + +\begin{description} +\item[principal] The name of the principal; must conform to Kerberos +naming specifications. + +\item[princ_expire_time] The expire time of the principal as a Kerberos +timestamp. No Kerberos tickets will be issued for a principal after +its expire time. + +\item[last_pwd_change] The time this principal's password was last +changed, as a Kerberos timestamp. + +\item[pw_expiration] The expire time of the user's current password, as a +Kerberos timestamp. No application service tickets will be issued for the +principal once the password expire time has passed. Note that the user can +only obtain tickets for services that have the PW_CHANGE_SERVICE bit set in +the attributes field. + +\item[max_life] The maximum lifetime of any Kerberos ticket issued to +this principal. + +\item[attributes] A bitfield of attributes for use by the KDC. The +symbols and constant values are defined below; their interpretation +appears in the libkdb functional specification. + +\begin{tabular}{clr} +{\bf Name} & {\bf Value} \\ +KRB5_KDB_DISALLOW_POSTDATED & 0x00000001 \\ +KRB5_KDB_DISALLOW_FORWARDABLE & 0x00000002 \\ +KRB5_KDB_DISALLOW_TGT_BASED & 0x00000004 \\ +KRB5_KDB_DISALLOW_RENEWABLE & 0x00000008 \\ +KRB5_KDB_DISALLOW_PROXIABLE & 0x00000010 \\ +KRB5_KDB_DISALLOW_DUP_SKEY & 0x00000020 \\ +KRB5_KDB_DISALLOW_ALL_TIX & 0x00000040 \\ +KRB5_KDB_REQUIRES_PRE_AUTH & 0x00000080 \\ +KRB5_KDB_REQUIRES_HW_AUTH & 0x00000100 \\ +KRB5_KDB_REQUIRES_PWCHANGE & 0x00000200 \\ +KRB5_KDB_DISALLOW_SVR & 0x00001000 \\ +KRB5_KDB_PWCHANGE_SERVICE & 0x00002000 \\ +KRB5_KDB_SUPPORT_DESMD5 & 0x00004000 \\ +KRB5_KDB_NEW_PRINC & 0x00008000 +\end{tabular} + +\item[mod_name] The name of the Kerberos principal that most recently +modified this principal. + +\item[mod_date] The time this principal was last modified, as a Kerberos +timestamp. + +\item[kvno] The version of the principal's current key. + +\item[mkvno] The version of the Kerberos Master Key in effect when +this principal's key was last changed. In KADM5_API_VERSION_2, this +field is always zero. + +\item[policy] If the POLICY bit is set in aux_attributes, the name +of the policy controlling this principal. + +\item[aux_attributes] A bitfield of flags for use by the +administration system. Currently, the only valid flag is POLICY, and +it indicates whether or not the principal has a policy enforced on it. + +\item[max_renewable_life] The maximum renewable lifetime of any +Kerberos ticket issued to or for this principal. This field only +exists in KADM5_API_VERSION_2. + +\item[last_success] The KDC time of the last successful AS_REQ. This +is only updated if KRBCONF_KDC_MODIFIES_KDB is defined during +compilation of the KDC. This field only exists in +KADM5_API_VERSION_2. + +\item[last_failed] The KDC time of the last failed AS_REQ. This is +only updated if KRBCONF_KDC_MODIFIES_KDB is defined during compilation +of the KDC. This field only exists in KADM5_API_VERSION_2. + +\item[fail_auth_count] The number of consecutive failed AS_REQs. When +this number reaches KRB5_MAX_FAIL_COUNT, the KRB5_KDC_DISALLOW_ALL_TIX +is set on the principal. This is only updated if +KRBCONF_KDC_MODIFIES_KDB is defined during compilation. This field +only exists in KADM5_API_VERSION_2. + +\item[n_tl_data] The number of elements in the \v{tl_data} linked +list. This field only exists in KADM5_API_VERSION_2. + +\item[n_key_data] The number of elements in the \v{key_data} +array. This field only exists in KADM5_API_VERSION_2. + +\item[tl_data] A linked list of tagged data. This list is a mechanism +by which programs can store extended information in a principal entry, +without having to modify the database API. Each element is of type +krb5_tl_data: +\begin{verbatim} +typedef struct _krb5_tl_data { + struct _krb5_tl_data* tl_data_next; + krb5_int16 tl_data_type; + krb5_int16 tl_data_length; + krb5_octet * tl_data_contents; +} krb5_tl_data; +\end{verbatim} +% +The KADM5 API only allows elements whose tl_data_type is greater than +or equal to 256. Values less than 256 are reserved for internal use +by the KADM5 or kdb system. They are filtered out of the list +returned by kadm5_get_principal, and generate an error if given to +kadm5_modify_principal. + +The libkdb library defines the tagged data types +KRB5_TL_LAST_PWD_CHANGE, KRB5_TL_MOD_PRINC, and KRB5_TL_KADM_DATA, all +with values less than 256, which store the last password modification +time, time and modifier of last principal modification, and +administration system data. All of these entries are expected by the +administration system and parsed out into fields of the +kadm5_principal_ent_rec structure; as described above, they are not +included in the tl_data list. + +Tagged data elements with types greater than 256 are handled without +interpretation by KADM5. Note that an application that calls +kadm5_modify_principal with the KADM5_TL_DATA mask bit set is +responsible for providing the {\it complete} tl_data list, which it +necessarily must obtain from kadm5_get_principal. It is {\it never} +possible for an application to construct a complete tl_data list from +scratch. + +\item[key_data] An array of the principal's keys. The keys contained +in this array are encrypted in the Kerberos master key. See section +\ref{sec:keys} for a discussion of the krb5_key_data structure. +\end{description} + +\subsection{Policies, kadm5_policy_ent_t} +\label{sec:policy-fields} + +If the POLICY bit is set in aux_attributes, the \v{policy} name field +in the kadm5_principal_ent_t structure refers to a password policy +entry defined in a \v{kadm5_policy_ent_t}. + +\begin{verbatim} +typedef struct _kadm5_policy_ent_t { + char *policy; + + u_int32 pw_min_life; + u_int32 pw_max_life; + u_int32 pw_min_length; + u_int32 pw_min_classes; + u_int32 pw_history_num; + u_int32 policy_refcnt; +} kadm5_policy_ent_rec, *kadm5_policy_ent_t; +\end{verbatim} + +The fields of an kadm5_policy_ent_t are interpreted as follows. +Note that a policy's values only apply to a principal using that +policy. + +\begin{description} +\item[policy] The name of this policy, as a NULL-terminated string. +The ASCII characters between 32 (space) and 126 (tilde), inclusive, +are legal. + +\item[pw_min_life] The minimum password lifetime, in seconds. +A principal cannot change its password before pw_min_life seconds have +passed since last_pwd_change. + +\item[pw_max_life] The default duration, in seconds, used to compute +pw_expiration when a principal's password is changed. + +\item[pw_min_length] The minimum password length, in characters. A +principal cannot set its password to anything with fewer than this +number of characters. This value must be greater than zero. + +\item[pw_min_classes] The minimum number of character classes in the +password. This value can only be 1, 2, 3, 4, or 5. A principal cannot +set its password to anything with fewer than this number of character +classes in it. + +\item[pw_history_num] The number of past passwords that are +stored for the principal; the minimum value is 1 and the maximum value +is 10. A principal cannot set its password to any of its previous +pw_history_num passwords. The first ``previous'' password is the +current password; thus, a principal with a policy can never reset its +password to its current value. + +\item[policy_refcnt] The number of principals currently using this policy. +A policy cannot be deleted unless this number is zero. +\end{description} + +\subsection{Configuration parameters} +\label{sec:configparams} + +The KADM5 API acquires configuration information from the Kerberos +configuration file (\$KRB5_CONFIG or DEFAULT_PROFILE_PATH) and from +the KDC configuration file (\$KRB5_KDC_CONFIG or DEFAULT_KDC_PROFILE). +In KADM5_API_VERSION_2, some of the configuration parameters used by +the KADM5 API can be controlled by the caller by providing a +kadm5_config_params structure to kadm5_init: +% +\begin{verbatim} +typedef struct _kadm5_config_params { + u_int32 mask; + + /* Client and server fields */ + char *realm; + char *profile; + int kadmind_port; + + /* client fields */ + char *admin_server; + + /* server fields */ + char *dbname; + char *admin_dbname; + char *admin_lockfile; + char *acl_file; + char *dict_file; + char *admin_keytab; + + /* server library (database) fields */ + int mkey_from_kbd; + char *stash_file; + char *mkey_name; + krb5_enctype enctype; + krb5_deltat max_life; + krb5_deltat max_rlife; + krb5_timestamp expiration; + krb5_flags flags; + krb5_key_salt_tuple *keysalts; + krb5_int32 num_keysalts; +} kadm5_config_params; +\end{verbatim} +% +The following list describes each of the fields of the structure, +along with the profile relation it overrides, its mask value, its +default value, and whether it is valid on the client, server, or both, +or neither. +\begin{description} +\item[mask] No variable. No mask value. A bitfield specifying which +fields of the structure contain valid information. A caller sets this +mask before calling kadm5_init_*, indicating which parameters are +specified. The mask values are defined in $<$kadm5/admin.h$>$ and are +all prefixed with KADM5_CONFIG_; the prefix is not included in the +descriptions below. + +\item[realm] No variable. REALM. Client and server. The realm to +which these parameters apply, and the realm for which additional +parameters are to be acquired, if any. If this field is not specified +in the mask, the default local realm is used. + +\item[profile] Variable: profile (server only). PROFILE. Client and +server. The Kerberos profile to use. On the client, the default is +the value of the KRB5_CONFIG environment variable, or +DEFAULT_PROFILE_PATH if that is not set. On the server, the value of +the ``profile'' variable of the KDC configuration file will be used as +the first default if it exists; otherwise, the default is the value of +the KRB5_KDC_PROFILE environment variable or DEFAULT_KDC_PROFILE. + +\item[kadmind_port] Variable: kadmind_port. KADMIND_PORT. Client and +server. The port number the kadmind server listens on. The client +uses this field to determine where to connect, and the server to +determine where to listen. The default is 749, which has been +assigned by IANA. + +\item[admin_server] Variable: admin_server. ADMIN_SERVER. Client. +The host name of the admin server to which to connect. There is no +default. If the value of this field contains a colon (:), the text +following the colon is treated as an integer and assigned to the +kadmind_port field, overriding any value of the kadmind_port variable. + +\item[dbname] Variable: dbname. DBNAME. Server. The Kerberos +database name to use; the Kerberos database stores principal +information. The default is DEFAULT_KDB_FILE. + +\item[admin_dbname] Variable: admin_database_name. ADBNAME. +Neither. If the dbname field is set, this field is set to the value +of dbname followed by ``.kadm5''. + +\item[admin_lockfile] Variable: admin_database_lockfile. +ADB_LOCKFILE. Neither. If the admin_dbname field is set, this field +is set to the value of admin_dbname followed by ``.lock''. + +\item[acl_file] Variable: acl_file. ACL_FILE. Server. The admin +server's ACL file. The default is DEFAULT_KADM5_ACL_FILE. + +\item[dict_file] Variable: admin_dict_file. DICT_FILE. Server. The +admin server's dictionary file of passwords to disallow. No default. + +\item[admin_keytab] Variable: admin_keytab. ADMIN_KEYTAB. Server. +The keytab file containing the kadmin/admin and kadmin/changepw +entries for the server to use. The default is the value of the +KRB5_KTNAME environment variable, if defined, else +DEFAULT_KADM5_KEYTAB. + +\item[mkey_from_keyboard] No variable. MKEY_FROM_KEYBOARD. Server. +If non-zero, prompt for the master password via the tty instead of +using the stash file. If this mask bit is not set, or is set and the +value is zero, the stash file is used. + +\item[stash_file] Variable: key_stash_file. STASH_FILE. Server. The +file name containing the master key stash file. No default; libkdb +will work with a NULL value. + +\item[mkey_name] Variable: master_key_name. MKEY_NAME. Server. The +name of the master principal for the realm. No default; lbkdb will +work with a NULL value. + +\item[enctype] Variable: master_key_type. ENCTYPE. Server. The +encryption type of the master principal. The default is +DEFAULT_KDC_ENCTYPE. + +\item[max_life] Variable: max_life. MAX_LIFE. Maximum lifetime for +all tickets issued to the principal. The default is 28800, which is 8 +hours. + +\item[max_rlife, expiration, flags] Variables: max_renewable_life, +default_principal_expiration, default_principal_flags. MAX_LIFE, +MAX_RLIFE, EXPIRATION, FLAGS. Server. Default values for new +principals. All default to 0. + +\item[keysalts, num_keysalts] Variable: supported_enctypes. ENCTYPES. +Server. The list of supported encryption type/salt type tuples; both +fields must be assigned if ENCTYPES is set. The default is a list +containing one enctype, DES-CBC-CRC with normal salt. +\end{description} + +\subsection{Principal keys} +\label{sec:keys} + +In KADM5_API_VERSION_1, all principals had a single key. The +encryption method was always DES, and the salt type was determined +outside the API (by command-line options to the administration +server). + +In KADM5_API_VERSION_2, principals can have multiple keys, each with +its own encryption type and salt. Each time a principal's key is +changed with kadm5_create_principal, kadm5_chpass_principal or +kadm5_randkey_principal, existing key entries are removed and a key +entry for each encryption and salt type tuple specified in the +configuration parameters is added. There is no provision for +specifying encryption and salt type information on a per-principal +basis; in a future version, this will probably be part of the admin +policy. There is also presently no provision for keeping multiple key +versions for a single principal active in the database. + +A single key is represented by a krb5_key_data: +% +\begin{verbatim} +typedef struct _krb5_key_data { + krb5_int16 key_data_ver; /* Version */ + krb5_int16 key_data_kvno; /* Key Version */ + krb5_int16 key_data_type[2]; /* Array of types */ + krb5_int16 key_data_length[2]; /* Array of lengths */ + krb5_octet * key_data_contents[2]; /* Array of pointers */ +} krb5_key_data; +\end{verbatim} +% +\begin{description} +\item[key_data_ver] The verion number of the structure. Versions 1 +and 2 are currently defined. If key_data_ver is 1 then the key is +either a random key (not requiring a salt) or the salt is the normal +v5 salt which is the same as the realm and therefore doesn't need to +be saved in the database. + +\item[key_data_kvno] The key version number of this key. + +\item[key_data_type] The first element is the enctype of this key. In +a version 2 structure, the second element is the salttype of this key. +The legal encryption types are defined in $<$krb5.h$>$. The legal +salt types are defined in $<$k5-int.h$>$. + +\item[key_data_length] The first element is length this key. In a +version 2 structure, the second element is length of the salt for this +key. + +\item[key_data_contents] The first element is the content of this key. +In a version 2 structure, the second element is the contents of the +salt for this key. +\end{description} + +\subsection{Field masks} +\label{sec:masks} + +The API functions for creating, retrieving, and modifying principals +and policies allow for a relevant subset of the fields of the +kadm5_principal_ent_t and kadm5_policy_ent_t to be specified or +changed. The chosen fields are determined by a bitmask that is passed +to the relevant function. Each API function has different rules for +which mask values can be specified, and can specify whether a given +mask value is mandatory, optional, or forbidden. Mandatory fields +must be present and forbidden fields must not be present or an error +is generated. When creating a principal or policy, optional fields +have a default value if they are not specified. When modifying a +principal or policy, optional fields are unchanged if they are not +specified. When retrieving a principal, optional fields are simply +not provided if they are not specified; not specifying undeeded fields +for retrieval may improve efficiency. The values for forbidden fields +are defined in the function semantics. + +The masks for principals are in table \ref{tab:princ-bits} and the +masks for policies are in table \ref{tab:policy-bits}. They are +defined in $<$kadm5/admin.h$>$. The KADM5_ prefix has been removed +from the Name fields. In the Create and Modify fields, M means +mandatory, F means forbidden, and O means optional. Create fields +that are optional specify the default value. The notation ``K/M +value'' means that the field inherits its value from the corresponding +field in the Kerberos master principal, for KADM5_API_VERSION_1, and +from the configuration parameters for KADM5_API_VERSION_2. + +All masks for principals are optional for retrevial, {\it except} that +the KEY_DATA mask is illegal when specified by a remote client; for +details, see the function semantics for kadm5_get_principal. + +Note that the POLICY and POLICY_CLR bits are special. When POLICY is +set, the policy is assigned to the principal. When POLICY_CLR is +specified, the policy is unassigned to the principal and as a result +no policy controls the principal. + +For convenience, the mask KADM5_PRINCIPAL_NORMAL_MASK contains all of +the principal masks {\it except} KADM5_KEY_DATA and KADM5_TL_DATA, and +the mask KADM5_POLICY_NORMAL_MASK contains all of the policy masks. + +\begin{table}[htbp] +\begin{tabular}{@{}lclll} +{\bf Name} & {\bf Value} & {\bf Fields Affected} & {\bf Create} & + {\bf Modify} \\ +PRINCIPAL & 0x000001 & principal & M & F \\ +PRINC_EXPIRE_TIME & 0x000002 & princ_expire_time & O, K/M value & O \\ +PW_EXPIRATION & 0x000004 & pw_expiration & O, now+pw_max_life & O \\ +LAST_PWD_CHANGE & 0x000008 & last_pwd_change & F & F \\ +ATTRIBUTES & 0x000010 & attributes & O, 0 & O \\ +MAX_LIFE & 0x000020 & max_life & O, K/M value & O \\ +MOD_TIME & 0x000040 & mod_date & F & F \\ +MOD_NAME & 0x000080 & mod_name & F & F \\ +KVNO & 0x000100 & kvno & O, 1 & O \\ +MKVNO & 0x000200 & mkvno & F & F \\ +AUX_ATTRIBUTES & 0x000400 & aux_attributes & F & F \\ +POLICY & 0x000800 & policy & O, none & O \\ +POLICY_CLR & 0x001000 & policy & F & O \\ +MAX_RLIFE & 0x002000 & max_renewable_life & O, K/M value & O \\ +LAST_SUCCESS & 0x004000 & last_success & F & F \\ +LAST_FAILED & 0x008000 & last_failed & F & F \\ +FAIL_AUTH_COUNT & 0x010000 & fail_auth_count & F & O \\ +KEY_DATA & 0x020000 & n_key_data, key_data & F & F \\ +TL_DATA & 0x040000 & n_tl_data, tl_data & O, 0, NULL & O +\end{tabular} +\caption{Mask bits for creating, retrieving, and modifying principals.} +\label{tab:princ-bits} +\end{table} + +\begin{table}[htbp] +\begin{tabular}{@{}lclll} +Name & Value & Field Affected & Create & Modify \\ +POLICY & same & policy & M & F \\ +PW_MAX_LIFE & 0x004000 & pw_max_life & O, 0 (infinite) & O \\ +PW_MIN_LIFE & 0x008000 & pw_min_life & O, 0 & O \\ +PW_MIN_LENGTH & 0x010000 & pw_min_length & O, 1 & O \\ +PW_MIN_CLASSES & 0x020000 & pw_min_classes & O, 1 & O \\ +PW_HISTORY_NUM & 0x040000 & pw_history_num & O, 0 & O \\ +REF_COUNT & 0x080000 & pw_refcnt & F & F +\end{tabular} +\caption{Mask bits for creating/modifying policies.} +\label{tab:policy-bits} +\end{table} + +\section{Constants, Header Files, Libraries} + +$<$kadm5/admin.h$>$ includes a number of required header files, +including RPC, Kerberos 5, com_err, and admin com_err +defines. It contains prototypes for all kadm5 routines mentioned +below, as well as all Admin API data structures, type definitions and +defines mentioned in this document. + +Before \v{\#include}ing $<$kadm5/admin.h$>$, the programmer can +specify the API version number that the program will use by +\v{\#define}ing USE_KADM5_API_VERSION; for example, define that symbol +to be 1 to use KADM5_API_VERSION_1. This will ensure that the correct +functional protoypes and data structures are defined. If no version +symbol is defined, the most recent version supported by the header +files will be used. + +Some of the defines and their values contained in $<$kadm5/admin.h$>$ +include the following, whose KADM5_ prefixes have been removed. +Symbols that do not exist in KADM5_API_VERSION_2 do not have a KADM5_ +prefix, but instead retain only with OVSEC_KADM_ prefix for +compatibility. +\begin{description} +\item[admin service principal] ADMIN_SERVICE (``kadmin/admin'') +\item[admin history key] HIST_PRINCIPAL (``kadmin/history'') +\item[change password principal] CHANGEPW_SERVICE (``kadmin/changepw'') +\item[server acl file path] ACLFILE (``/krb5/ovsec_adm.acl''). In +KADM5_API_VERSION 2, this is controlled by configuration parameters. +\item[dictionary] WORDFILE (``/krb5/kadmind.dict''). In +KADM5_API_VERSION 2, this is controlled by configuration parameters. +\end{description} + +KADM5 errors are described in $<$kadm5/kadm_err.h$>$, which +is included by $<$kadm5/admin.h$>$. + +The locations of the admin policy and principal databases, as well as +defines and type definitions for the databases, are defined in +$<$kadm5/adb.h$>$. Some of the defines in that file are: +\begin{description} +\item[admin policy database] POLICY_DB (``/krb5/kadm5_policy.db''). In +KADM5_API_VERSION 2, this is controlled by configuration parameters. +\item[admin principal database] PRINCIPAL_DB +(``/krb5/ovsec_principal.db''). In KADM5_API_VERSION 2, this is +controlled by configuration parameters. +\end{description} + +Client applications will link against libkadm5clnt.a and server +programs against libkadm5srv.a. Client applications must also link +against: libgssapi_krb5.a, libkrb5.a, libcrypto.a, libgssrpc.a, +libcom_err.a, and libdyn.a. Server applications must also link +against: libkdb5.a, libkrb5.a, libcrypto.a, libgssrpc.a, libcom_err.a, +and libdyn.a. + +\section{Error Codes} + +The error codes that can be returned by admin functions are listed +below. Error codes indicated with a ``*'' can be returned by every +admin function and always have the same meaning; these codes are +omitted from the list presented with each function. + +The admin system guarantees that a function that returns an error code +has no other side effect. + +The Admin system will use \v{com_err} for error codes. Note that this +means \v{com_err} codes may be returned from functions that the admin +routines call (e.g. the kerberos library). Callers should not expect +that only KADM5 errors will be returned. The Admin system error code +table name will be ``ovk'', and the offsets will be the same as the +order presented here. As mentioned above, the error table include file +will be $<$kadm5/kadm_err.h$>$. + +Note that these error codes are also used as protocol error code +constants and therefore must not change between product releases. +Additional codes should be added at the end of the list, not in the +middle. The integer value of KADM5_FAILURE is 43787520; the +remaining values are assigned in sequentially increasing order. + +\begin{description} +\item[* KADM5_FAILURE] Operation failed for unspecified reason +\item[* KADM5_AUTH_GET] Operation requires ``get'' privilege +\item[* KADM5_AUTH_ADD] Operation requires ``add'' privilege +\item[* KADM5_AUTH_MODIFY] Operation requires ``modify'' privilege +\item[* KADM5_AUTH_DELETE] Operation requires ``delete'' privilege +\item[* KADM5_AUTH_INSUFFICIENT] Insufficient authorization for +operation +\item[* KADM5_BAD_DB] Database inconsistency detected +\item[KADM5_DUP] Principal or policy already exists +\item[KADM5_RPC_ERROR] Communication failure with server +\item[KADM5_NO_SRV] No administration server found for realm +\item[KADM5_BAD_HIST_KEY] Password history principal key version +mismatch +\item[KADM5_NOT_INIT] Connection to server not initialized +\item[KADM5_UNK_PRINC] Principal does not exist +\item[KADM5_UNK_POLICY] Policy does not exist +\item[KADM5_BAD_MASK] Invalid field mask for operation +\item[KADM5_BAD_CLASS] Invalid number of character classes +\item[KADM5_BAD_LENGTH] Invalid password length +\item[KADM5_BAD_POLICY] Illegal policy name +\item[KADM5_BAD_PRINCIPAL] Illegal principal name. +\item[KADM5_BAD_AUX_ATTR] Invalid auxillary attributes +\item[KADM5_BAD_HISTORY] Invalid password history count +\item[KADM5_BAD_MIN_PASS_LIFE] Password minimum life is greater +then password maximum life +\item[KADM5_PASS_Q_TOOSHORT] Password is too short +\item[KADM5_PASS_Q_CLASS] Password does not contain enough +character classes +\item[KADM5_PASS_Q_DICT] Password is in the password dictionary +\item[KADM5_PASS_REUSE] Cannot resuse password +\item[KADM5_PASS_TOOSOON] Current password's minimum life has not +expired +\item[KADM5_POLICY_REF] Policy is in use +\item[KADM5_INIT] Connection to server already initialized +\item[KADM5_BAD_PASSWORD] Incorrect password +\item[KADM5_PROTECT_PRINCIPAL] Cannot change protected principal +\item[* KADM5_BAD_SERVER_HANDLE] Programmer error! Bad Admin server handle +\item[* KADM5_BAD_STRUCT_VERSION] Programmer error! Bad API structure version +\item[* KADM5_OLD_STRUCT_VERSION] API structure version specified by application is no longer supported (to fix, recompile application against current Admin API header files and libraries) +\item[* KADM5_NEW_STRUCT_VERSION] API structure version specified by application is unknown to libraries (to fix, obtain current Admin API header files and libraries and recompile application) +\item[* KADM5_BAD_API_VERSION] Programmer error! Bad API version +\item[* KADM5_OLD_LIB_API_VERSION] API version specified by application is no longer supported by libraries (to fix, update application to adhere to current API version and recompile) +\item[* KADM5_OLD_SERVER_API_VERSION] API version specified by application is no longer supported by server (to fix, update application to adhere to current API version and recompile) +\item[* KADM5_NEW_LIB_API_VERSION] API version specified by application is unknown to libraries (to fix, obtain current Admin API header files and libraries and recompile application) +\item[* KADM5_NEW_SERVER_API_VERSION] API version specified by +application is unknown to server (to fix, obtain and install newest +Admin Server) +\item[KADM5_SECURE_PRINC_MISSING] Database error! Required principal missing +\item[KADM5_NO_RENAME_SALT] The salt type of the specified principal +does not support renaming +\item[KADM5_BAD_CLIENT_PARAMS] Illegal configuration parameter for +remote KADM5 client +\item[KADM5_BAD_SERVER_PARAMS] Illegal configuration parameter for +local KADM5 client. +\item[KADM5_AUTH_LIST] Operation requires ``list'' privilege +\item[KADM5_AUTH_CHANGEPW] Operation requires ``change-password'' privilege +\item[KADM5_BAD_TL_TYPE] Programmer error! Illegal tagged data list +element type +\item[KADM5_MISSING_CONF_PARAMS] Required parameters in kdc.conf missing +\item[KADM5_BAD_SERVER_NAME] Bad krb5 admin server hostname +\item[KADM5_AUTH_SETKEY] Operation requires ``set-key'' privilege +\item[KADM5_SETKEY_DUP_ENCTYPES] Multiple values for single or folded enctype +\end{description} + +\section{Authentication and Authorization} +\label{sec:auth} + +Two Kerberos principals exist for use in communicating with the Admin +system: kadmin/admin and kadmin/changepw. Both principals +have the KRB5_KDB_DISALLOW_TGT_BASED bit set in their attributes so +that service tickets for them can only be acquired via a +password-based (AS_REQ) request. Additionally, kadmin/changepw +has the KRB5_KDB_PWCHANGE_SERVICE bit set so that a principal with an +expired password can still obtain a service ticket for it. + +The Admin system accepts requests that are authenticated to either +service principal, but the sets of operations that can be performed by +a request authenticated to each service are different. In particular, +only the functions chpass_principal, randkey_principal, get_principal, +and get_policy can be performed by a request authenticated to the +kadmin/changepw service, and they can only be performed when the +target principal of the operation is the same as the authenticated +client principal; the function semantics descriptions below give the +precise details. This means that administrative operations can only +be performed when authenticated to the kadmin/admin service. The +reason for this distinction is that tickets for kadmin/changepw can be +acquired with an expired password, and the KADM system does not want +to allow an administrator with an expired password to perform +administrative operations on arbitrary principals. + +Each Admin API operation authenticated to the kadmin/admin service +requires a specific authorization to run. This version uses a simple +named privilege system with the following names and meanings: + +\begin{description} +\item[Get] Able to examine the attributes (NOT key data) of principals +and policies. +\item[Add] Able to add principals and policies. +\item[Modify] Able to modify attributes of existing principals and +policies; this does not include changing passwords. +\item[Delete] Able to remove principals and policies. +\item[List] Able to retrieve a list of principals and policies. +\item[Changepw] Able to change the password of principals. +\item[Setkey] Able to set principal keys directly. +\end{description} + +Privileges are specified via an external configuration file on the +Kerberos master server. + +Table \ref{tab:func-overview} summarizes the authorization +requirements of each function. Additionally, each API function +description identifies the privilege required to perform it. The +Authorization checks only happen if you are using the RPC mechanism. +If you are using the server-side API functions locally on the admin +server, the only authorization check is if you can access the +approporiate local files. + +\section{Functions} + +\subsection{Overview} + +The functions provided by the Admin API, and the authorization they +require, are listed in the table \ref{tab:func-overview}. The +``kadm5_'' prefix has been removed from each function name. + +The function semantics in the following sections omit details that are +the same for every function. + +\begin{itemize} +\item The effects of every function are atomic. + +\item Every function performs an authorization check and returns +the appropriate KADM5_AUTH_* error code if the caller does not +have the required privilege. No other information or error code is +ever returned to an unauthorized user. + +\item Every function checks its arguments for NULL pointers or other +obviously invalid values, and returns EINVAL if any are detected. + +\item Any function that performs a policy check uses the policy named +in the principal's policy field. If the POLICY bit is not set in the +principal's aux_attributes field, however, the principal has no +policy, so the policy check is not performed. + +\item Unless otherwise specified, all functions return KADM5_OK. +\end{itemize} + +\begin{table}[htbp] +\caption{Summary of functions and required authorization.} +\label{tab:func-overview} +\begin{tabular}{@{}llp{3.24in}} +\\ +{\bf Function Name} & {\bf Authorization} & {\bf Operation} \\ + +init & none & Open a connection with the kadm5 library. OBSOLETE +but still provided---use init_with_password instead. \\ +init_with_password & none & Open a connection with the kadm5 +library using a password to obtain initial credentials. \\ +init_with_skey & none & Open a connection with the kadm5 library +using the keytab entry to obtain initial credentials. \\ +destroy & none & Close the connection with the kadm5 library. \\ +flush & none & Flush all database changes to disk; no-op when called +remotely. \\ +create_principal & add & Create a new principal. \\ +delete_principal & delete & Delete a principal. \\ +modify_principal & modify & Modify the attributes of an existing + principal (not password). \\ +rename_principal & add and delete & Rename a principal. \\ +get_principal & get\footnotemark & Retrieve a principal. \\ +get_principals & list & Retrieve some or all principal names. \\ +chpass_principal & changepw\footnotemark[\thefootnote] & + Change a principal's password. \\ +chpass_principal_util & changepw\footnotemark[\thefootnote] & Utility wrapper around chpass_principal. \\ +randkey_principal & changepw\footnotemark[\thefootnote] & + Randomize a principal's key. \\ +setkey_principal & setkey & Explicitly set a principal's keys. \\ +decrypt_key & none & Decrypt a principal key. \\ +create_policy & add & Create a new policy. \\ +delete_policy & delete & Delete a policy. \\ +modify_policy & modify & Modify the attributes of a policy. \\ +get_policy & get & Retrieve a policy. \\ +get_policies & list & Retrieve some or all policy names. \\ +free_principal_ent & none & Free the memory associated with an + kadm5_principal_ent_t. \\ +free_policy_ent & none & Free the memory associated with an + kadm5_policy_ent_t. \\ +get_privs & none & Return the caller's admin server privileges. +\end{tabular} +\end{table} +\footnotetext[\thefootnote]{These functions also allow a principal to +perform the operation on itself; see the function's semantics for +details.} + +\subsection{kadm5_init_*} + +In KADM5_API_VERSION 1: + +\begin{verbatim} +kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass, + char *service_name, char *realm, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab, + char *service_name, char *realm, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init(char *client_name, char *pass, + char *service_name, char *realm, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) +\end{verbatim} + +In KADM5_API_VERSION 2: + +\begin{verbatim} +kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass, + char *service_name, + kadm5_config_params *realm_params, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab, + char *service_name, + kadm5_config_params *realm_params, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init(char *client_name, char *pass, + char *service_name, + kadm5_config_params *realm_params, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init_with_creds(char *client_name, + krb5_ccache ccache, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + void **server_handle) +\end{verbatim} + +AUTHORIZATION REQUIRED: none + +NOTE: kadm5_init is an obsolete function provided for backwards +compatibility. It is identical to kadm5_init_with_password. + +These three functions open a connection to the kadm5 library and +initialize any neccessary state information. They behave differently +when called from local and remote clients. + +In KADM5_API_VERSION_2, these functions take a kadm5_config_params +structure instead of a realm name as an argument. The semantics are +similar: if a NULL pointer is passed for the realm_params argument, +the default realm and default parameters for that realm, as specified +in the krb5 configuration file (e.g. /etc/krb5.conf) are used. If a +realm_params structure is provided, the fields that are set override +the default values. If a parameter is specified to the local or +remote libraries that does not apply to that side, an error code +(KADM5_BAD_CLIENT_PARAMS or KADM5_BAD_SERVER_PARAMS) is returned. See +section \ref{sec:configparams} for a discussion of configuration +parameters. + +For remote clients, the semantics are: + +\begin{enumerate} +\item Initializes all the com_err error tables used by the Admin +system. + +\item Acquires configuration parameters. In KADM5_API_VERSION_1, all +the defaults specified in the configuration file are used, according +to the realm. In KADM5_API_VERSION_2, the values in params_in are +merged with the default values. If an illegal mask value is +specified, KADM5_BAD_CLIENT_PARAMS is returned. + +\item Acquires a Kerberos ticket for the specified service. + +\begin{enumerate} +\item The ticket's client is client_name, which can be any valid +Kerberos principal. If client_name does not include a realm, the +default realm of the local host is used +\item The ticket's service is service_name@realm. service_name must +be one of the constants KADM5_ADMIN_SERVICE or +KADM5_CHANGEPW_SERVICE. +\item If realm is NULL, client_name's realm is used. + +\item For init_with_password, an initial ticket is acquired and +decoded with the password pass, which must be client_name's password. +If pass is NULL or an empty string, the user is prompted (via the tty) +for a password. + +\item For init_with_skey, an initial ticket is acquired and decoded +with client_name's key obtained from the specified keytab. If keytab +is NULL or an empty string the default keytab is used. + +\item For init_with_creds, ccache must be an open credential cache +that already has a ticket for the specified client and server. +Alternatively, if a site chooses to disable the DISALLOW_TGT_BASED +flag on the admin and changepw principals, the ccache can contain a +ticket-granting ticket for client_name. +\end{enumerate} + +\item Creates a GSS-API authenticated connection to the Admin server, +using the just-acquired Kerberos ticket. + +\item Verifies that the struct_version and api_version specified by +the caller are valid and known to the library. + +\item Sends the specified api_version to the server. + +\item Upon successful completion, fills in server_handle with a handle +for this connection, to be used in all subsequent API calls. +\end{enumerate} + +The caller should always specify KADM5_STRUCT_VERSION for the +struct_version argument, a valid and supported API version constant +for the api_version argument (currently, KADM5_API_VERSION_1 or +KADM5_API_VERSION_2), and a valid pointer in which the server handle +will be stored. + +If any kadm5_init_* is invoked locally its semantics are: + +\begin{enumerate} +\item Initializes all the com_err error tables used by the Admin +system. + +\item Acquires configuration parameters. In KADM5_API_VERSION_1, all +the defaults specified in the configuration file are used, according +to the realm. In KADM5_API_VERSION_2, the values in params_in are +merged with the default values. If an illegal mask value is +specified, KADM5_BAD_SERVER_PARAMS is returned. + +\item Initializes direct access to the KDC database. In +KADM5_API_VERISON_1, if pass (or keytab) is NULL or an empty string, +reads the master password from the stash file; otherwise, the non-NULL +password is ignored and the user is prompted for it via the tty. In +KADM5_API_VERSION_2, if the MKEY_FROM_KEYBOARD parameter mask is set +and the value is non-zero, reads the master password from the user via +the tty; otherwise, the master key is read from the stash file. +Calling init_with_skey or init_with_creds with the MKEY_FROM_KEYBOARD +mask set with a non-zero field is illegal, and calling them without +the mask set is exactly like calling init_with_password. + +\item Initializes the dictionary (if present) for dictionary checks. + +\item Parses client_name as a Kerberos principal. client_name should +usually be specified as the name of the program. + +\item Verifies that the struct_version and api_version specified by +the caller are valid. + +\item Fills in server_handle with a handle containing all state +information (version numbers and client name) for this ``connection.'' +\end{enumerate} +The service_name argument is not used. + +RETURN CODES: + +\begin{description} +\item[KADM5_NO_SRV] No Admin server can be found for the +specified realm. + +\item[KADM5_RPC_ERROR] The RPC connection to the server cannot be +initiated. + +\item[KADM5_BAD_PASSWORD] Incorrect password. + +\item[KADM5_SECURE_PRINC_MISSING] The principal +KADM5_ADMIN_SERVICE or KADM5_CHANGEPW_SERVICE does not +exist. This is a special-case replacement return code for ``Server +not found in database'' for these required principals. + +\item[KADM5_BAD_CLIENT_PARAMS] A field in the parameters mask was +specified to the remote client library that is not legal for remote +clients. + +\item[KADM5_BAD_SERVER_PARAMS] A field in the parameters mask was +specified to the local client library that is not legal for local +clients. +\end{description} + +\subsection{kadm5_flush} + +\begin{verbatim} +kadm5_ret_t kadm5_flush(void *server_handle) +\end{verbatim} + +AUTHORIZATION REQUIRED: none + +Flush all changes to the Kerberos databases, leaving the connection to +the Admin API open. This function behaves differently when called by +local and remote clients. + +For local clients, the function closes and reopens the Kerberos +database with krb5_db_fini() and krb5_db_init(), and closes and +reopens the Admin policy database with adb_policy_close() and +adb_policy_open(). Although it is unlikely, any other these functions +could return errors; in that case, this function calls +kadm5_destroy and returns the error code. Therefore, if +kadm5_flush does not return KADM5_OK, the connection to the +Admin server has been terminated and, in principle, the databases +might be corrupt. + +For remote clients, the function is a no-op. + +\subsection{kadm5_destroy} + +\begin{verbatim} +kadm5_ret_t kadm5_destroy(void *server_handle) +\end{verbatim} + +AUTHORIZATION REQUIRED: none + +Close the connection to the Admin server and releases all related +resources. This function behaves differently when called by local and +remote clients. + +For remote clients, the semantics are: + +\begin{enumerate} +\item Destroy the temporary credential cache created by +kadm5_init. + +\item Tear down the GSS-API context negotiated with the server. + +\item Close the RPC connection. + +\item Free storage space associated with server_handle, after erasing +its magic number so it won't be mistaken for a valid handle by the +library later. +\end{enumerate} + +For local clients, this function just frees the storage space +associated with server_handle after erasing its magic number. + +RETURN CODES: + +\subsection{kadm5_create_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_create_principal(void *server_handle, + kadm5_principal_ent_t princ, u_int32 mask, + char *pw); +\end{verbatim} + +AUTHORIZATION REQUIRED: add + +\begin{enumerate} + +\item Return KADM5_BAD_MASK if the mask is invalid. +\item If the named principal exists, return KADM5_DUP. +\item If the POLICY bit is set and the named policy does not exist, +return KADM5_UNK_POLICY. +\item If KADM5_POLICY bit is set in aux_attributes check to see if +the password does not meets quality standards, return the appropriate +KADM5_PASS_Q_* error code if it fails. +\item Store the principal, set the key; see section \ref{sec:keys}. +\item If the POLICY bit is set, increment the named policy's reference +count by one. + +\item Set the pw_expiration field. +\begin{enumerate} +\item If the POLICY bit is set in mask, then if pw_max_life is non-zero, +set pw_expiration to now + pw_maxlife, otherwise set pw_max_life to +never. +\item If the PW_EXPIRATION bit is set in mask, set pw_expiration to +the requested value, overriding the value set above. +\end{enumerate} +NOTE: This is a change from the original semantics, in which policy +expiration was enforced even on administrators. The old semantics are +not preserved, even for version 1 callers, because this is a +server-specific policy decision; besides, the new semantics are less +restrictive, so all previous callers should continue to function +properly. + +\item Set mod_date to now and set mod_name to caller. +\item Set last_pwd_change to now. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_MASK] The field mask is invalid for a create +operation. +\item[KADM5_DUP] Principal already exists. +\item[KADM5_UNK_POLICY] Policy named in entry does not exist. +\item[KADM5_PASS_Q_*] Specified password does not meet policy +standards. +\end{description} + +\subsection{kadm5_delete_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_delete_principal(void *server_handle, krb5_principal princ); +\end{verbatim} + +AUTHORIZATION REQUIRED: delete + +\begin{enumerate} +\item Return KADM5_UNK_PRINC if the principal does not exist. +\item If the POLICY bit is set in aux_attributes, decrement the named +policy's reference count by one. +\item Delete principal. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\end{description} + +\subsection{kadm5_modify_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_modify_principal(void *server_handle, + kadm5_principal_ent_t princ, u_int32 mask); +\end{verbatim} + +Modify the attributes of the principal named in +kadm5_principal_ent_t. This does not allow the principal to be +renamed or for its password to be changed. + +AUTHORIZATION REQUIRED: modify + +Although a principal's pw_expiration is usually computed based on its +policy and the time at which it changes its password, this function +also allows it to be specified explicitly. This allows an +administrator, for example, to create a principal and assign it to a +policy with a pw_max_life of one month, but to declare that the new +principal must change its password away from its initial value +sometime within the first week. + +\begin{enumerate} +\item Return KADM5_UNK_PRINC if the principal does not exist. +\item Return KADM5_BAD_MASK if the mask is invalid. +\item If POLICY bit is set but the new policy does not exist, return +KADM5_UNK_POLICY. +\item If either the POLICY or POLICY_CLR bits are set, update the +corresponding bits in aux_attributes. + +\item Update policy reference counts. +\begin{enumerate} +\item If the POLICY bit is set, then increment policy count on new +policy. +\item If the POLICY or POLICY_CLR bit is set, and the POLICY bit in +aux_attributes is set, decrement policy count on old policy. +\end{enumerate} + +\item Set pw_expiration appropriately. pw_expiration can change if: +the POLICY bit is set in mask, so the principal is changing to a +policy (either from another policy or no policy); the POLICY_CLR bit +is set in mask, so the principal is changing to no policy; or +PW_EXPIRATION is set. +\begin{enumerate} +\item If the POLICY bit is set in mask, set pw_expiration to +last_pwd_change + pw_max_life if pw_max_life is non-zero, otherwise +set pw_expiration to never. +\item If the POLICY_CLR biti s set in mask, set pw_expiration to +never. +\item If PW_EXPIRATION is set, set pw_expiration to the requested +value, overriding the value from the previous two cases. NOTE: This +is a change from the original semantics, in which policy expiration +was enforced even on administrators. The old semantics are not +preserved, even for version 1 callers, because this is a +server-specific policy decision; besides, the new semantics are less +restrictive, so all previous callers should continue to function +properly. +\end{enumerate} + +% Here is the previous, and confusing, text of pw_expiration semantics: +%\begin{enumerate} +%\item If the POLICY bit is not set in aux_attributes, then +%\begin{enumerate} +%\item if the PW_EXPIRATION bit is set, set pw_expiration to the given +%value, else +%\item set pw_expiration to never. +%\end{enumerate} +%\item Otherwise, if the PW_EXPIRATION bit is set, set pw_expiration to +%the sooner of the given value and last_pwd_change + pw_max_life. +%\item Otherwise, set pw_expiration to last_pwd_change + pw_max_life. +%\end{enumerate} + +\item Update the remaining fields specified in the mask. +\item Update mod_name field to caller and mod_date to now. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Entry does not exist. +\item[KADM5_BAD_MASK] The mask is not valid for a modify +operation. +\item[KADM5_UNK_POLICY] The POLICY bit is set but the new +policy does not exist. +\item[KADM5_BAD_TL_TYPE] The KADM5_TL_DATA bit is set in mask, and the +given tl_data list contains an element whose type is less than 256. +\end{description} + +\subsection{kadm5_rename_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_rename_principal(void *server_handle, krb5_principal source, + krb5_principal target); +\end{verbatim} + +AUTHORIZATION REQUIRED: add and delete + +\begin{enumerate} +\item Check to see if source principal exists, if not return +KADM5_UNK_PRINC error. +\item Check to see if target exists, if so return KADM5_DUP error. +\item Create the new principal named target, then delete the old +principal named source. All of target's fields will be the same as +source's fields, except that mod_name and mod_date will be updated to +reflect the current caller and time. +\end{enumerate} + +Note that since the principal name may have been used as the salt for +the principal's key, renaming the principal may render the principal's +current password useless; with the new salt, the key generated by +string-to-key on the password will suddenly be different. Therefore, +an application that renames a principal must also require the user to +specify a new password for the principal (and administrators should +notify the affected party). + +Note also that, by the same argument, renaming a principal will +invalidate that principal's password history information; since the +salt will be different, a user will be able to select a previous +password without error. + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Source principal does not exist. +\item[KADM5_DUP] Target principal already exist. +\end{description} + +\subsection{kadm5_chpass_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_chpass_principal(void *server_handle, krb5_principal princ, + char *pw); +\end{verbatim} + +AUTHORIZATION REQUIRED: changepw, or the calling principal being the +same as the princ argument. If the request is authenticated to the +kadmin/changepw service, the changepw privilege is disregarded. + +Change a principal's password. See section \ref{sec:keys} for a +description of how the keys are determined. + +This function enforces password policy and dictionary checks. If the new +password specified is in the password dictionary, and the policy bit is set +KADM5_PASS_DICT is returned. If the principal's POLICY bit is set in +aux_attributes, compliance with each of the named policy fields is verified +and an appropriate error code is returned if verification fails. + +Note that the policy checks are only be performed if the POLICY bit is +set in the principal's aux_attributes field. + +\begin{enumerate} +\item Make sure principal exists, if not return KADM5_UNK_PRINC error. +\item If caller does not have modify privilege, (now - last_pwd_change) $<$ +pw_min_life, and the KRB5_KDB_REQUIRES_PWCHANGE bit is not set in the +principal's attributes, return KADM5_PASS_TOOSOON. +\item If the principal your are trying to change is kadmin/history +return KADM5_PROTECT_PRINCIPAL. +\item If the password does not meet the quality +standards, return the appropriate KADM5_PASS_Q_* error code. +\item Convert password to key; see section \ref{sec:keys}. +\item If the new key is in the principal's password history, return +KADM5_PASS_REUSE. +\item Store old key in history. +\item Update principal to have new key. +\item Increment principal's key version number by one. +\item If the POLICY bit is set, set pw_expiration to now + +max_pw_life. If the POLICY bit is not set, set pw_expiration to +never. +\item If the KRB5_KDB_REQUIRES_PWCHANGE bit is set in the principal's +attributes, clear it. +\item Update last_pwd_change and mod_date to now, update mod_name to +caller. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PASS_Q_*] Requested password does not meet quality +standards. +\item[KADM5_PASS_REUSE] Requested password is in user's +password history. +\item[KADM5_PASS_TOOSOON] Current password has not reached minimum life +\item[KADM5_PROTECT_PRINCIPAL] Cannot change the password of a special principal +\end{description} + + +\subsection{kadm5_chpass_principal_util} + +\begin{verbatim} +kadm5_ret_t +kadm5_chpass_principal_util(void *server_handle, krb5_principal princ, + char *new_pw, char **pw_ret, + char *msg_ret); +\end{verbatim} + +AUTHORIZATION REQUIRED: changepw, or the calling principal being the +same as the princ argument. If the request is authenticated to the +kadmin/changepw service, the changepw privilege is disregarded. + +This function is a wrapper around kadm5_chpass_principal. It can +read a new password from a user, change a principal's password, and +return detailed error messages. msg_ret should point to a char buffer +in the caller's space of sufficient length for the error messages +described below. 1024 bytes is recommended. It will also return the +new password to the caller if pw_ret is non-NULL. + +\begin{enumerate} +\item If new_pw is NULL, this routine will prompt the user for the new +password (using the strings specified by KADM5_PW_FIRST_PROMPT and +KADM5_PW_SECOND_PROMPT) and read (without echoing) the password input. +Since it is likely that this will simply call krb5_read_password only +terminal-based applications will make use of the password reading +functionality. If the passwords don't match the string ``New passwords do +not match - password not changed.'' will be copied into msg_ret, and the +error code KRB5_LIBOS_BADPWDMATCH will be returned. For other errors that +ocurr while reading the new password, copy the string ``$ +occurred while trying to read new password.'' followed by a blank line and +the string specified by CHPASS_UTIL_PASSWORD_NOT_CHANGED into msg_ret and +return the error code returned by krb5_read_password. + +\item If pw_ret is non-NULL, and the password was prompted, set *pw_ret to +point to a static buffer containing the password. If pw_ret is non-NULL +and the password was supplied, set *pw_ret to the supplied password. + +\item Call kadm5_chpass_principal with princ, and new_pw. + +\item If successful copy the string specified by CHPASS_UTIL_PASSWORD_CHANGED +into msg_ret and return zero. + +\item For a policy related failure copy the appropriate message (from below) +followed by a newline and ``Password not changed.'' into msg_ret +filling in the parameters from the principal's policy information. If +the policy information cannot be obtained copy the generic message if +one is specified below. Return the error code from +kadm5_chpass_principal. + +Detailed messages: +\begin{description} + +\item[PASS_Q_TOO_SHORT] +New password is too short. Please choose a +password which is more than $<$pw-min-len$>$ characters. + +\item[PASS_Q_TOO_SHORT - generic] +New password is too short. Please choose a longer password. + +\item[PASS_REUSE] +New password was used previously. Please choose a +different password. + +\item[PASS_Q_CLASS] +New password does not have enough character classes. Classes include +lower class letters, upper case letters, digits, punctuation and all +other characters. Please choose a password with at least +$<$min-classes$>$ character classes. + +\item[PASS_Q_CLASS - generic] +New password does not have enough character classes. Classes include +lower class letters, upper case letters, digits, punctuation and all +other characters. + +\item[PASS_Q_DICT] +New password was found in a dictionary of possible passwords and +therefore may be easily guessed. Please choose another password. See +the kpasswd man page for help in choosing a good password. + +\item[PASS_TOOSOON] +Password cannot be changed because it was changed too recently. Please +wait until $<$last-pw-change+pw-min-life$>$ before you change it. If you +need to change your password before then, contact your system +security administrator. + +\item[PASS_TOOSOON - generic] +Password cannot be changed because it was changed too recently. If you +need to change your now please contact your system security +administrator. +\end{description} + +\item For other errors copy the string ``$<$com_err message$>$ +occurred while trying to change password.'' following by a blank line +and ``Password not changed.'' into msg_ret. Return the error code +returned by kadm5_chpass_principal. +\end{enumerate} + + +RETURN CODES: + +\begin{description} +\item[KRB5_LIBOS_BADPWDMATCH] Typed new passwords did not match. +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PASS_Q_*] Requested password does not meet quality +standards. +\item[KADM5_PASS_REUSE] Requested password is in user's +password history. +\item[KADM5_PASS_TOOSOON] Current password has not reached minimum +life. +\end{description} + +\subsection{kadm5_randkey_principal} + +In KADM5_API_VERSION_1: + +\begin{verbatim} +kadm5_ret_t +kadm5_randkey_principal(void *server_handle, krb5_principal princ, + krb5_keyblock **new_key) +\end{verbatim} + +In KADM5_API_VERSION_2: + +\begin{verbatim} +kadm5_ret_t +kadm5_randkey_principal(void *server_handle, krb5_principal princ, + krb5_keyblock **new_keys, int *n_keys) +\end{verbatim} + +AUTHORIZATION REQUIRED: changepw, or the calling principal being the +same as the princ argument. If the request is authenticated to the +kadmin/changepw service, the changepw privilege is disregarded. + +Generate and assign a new random key to the named principal, and +return the generated key in allocated storage. In +KADM5_API_VERSION_2, multiple keys may be generated and returned as an +array, and n_new_keys is filled in with the number of keys generated. +See section \ref{sec:keys} for a description of how the keys are +chosen. In KADM5_API_VERSION_1, the caller must free the returned +krb5_keyblock * with krb5_free_keyblock. In KADM5_API_VERSION_2, the +caller must free each returned keyblock with krb5_free_keyblock. + +If the principal's POLICY bit is set in aux_attributes and the caller does +not have modify privilege , compliance with the password minimum life +specified by the policy is verified and an appropriate error code is returned +if verification fails. + +\begin{enumerate} +\item If the principal does not exist, return KADM5_UNK_PRINC. +\item If caller does not have modify privilege, (now - last_pwd_change) $<$ +pw_min_life, and the KRB5_KDB_REQUIRES_PWCHANGE bit is not set in the +principal's attributes, return KADM5_PASS_TOOSOON. +\item If the principal you are trying to change is kadmin/history return +KADM5_PROTECT_PRINCIPAL. +\item Store old key in history. +\item Update principal to have new key. +\item Increment principal's key version number by one. +\item If the POLICY bit in aux_attributes is set, set pw_expiration to +now + max_pw_life. +\item If the KRB5_KDC_REQUIRES_PWCHANGE bit is set in the principal's +attributes, clear it. +\item Update last_pwd_change and mod_date to now, update mod_name to +caller. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PASS_TOOSOON] The minimum lifetime for the current +key has not expired. +\item[KADM5_PROTECT_PRINCIPAL] Cannot change the password of a special +principal +\end{description} + +This function can also be used as part of a sequence to create a new +principal with a random key. The steps to perform the operation +securely are + +\begin{enumerate} +\item Create the principal with kadm5_create_principal with a +random password string and with the KRB5_KDB_DISALLOW_ALL_TIX bit set +in the attributes field. + +\item Randomize the principal's key with kadm5_randkey_principal. + +\item Call kadm5_modify_principal to reset the +KRB5_KDB_DISALLOW_ALL_TIX bit in the attributes field. +\end{enumerate} + +The three steps are necessary to ensure secure creation. Since an +attacker might be able to guess the initial password assigned by the +client program, the principal must be disabled until the key can be +truly randomized. + +\subsection{kadm5_setkey_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_setkey_principal(void *server_handle, krb5_principal princ, + krb5_keyblock *new_keys, int n_keys) +\end{verbatim} + +AUTHORIZATION REQUIRED: setkey. This function does not allow the use +of regular changepw authorization because it bypasses the password +policy mechanism. + +This function only exists in KADM5_API_VERSION_2. + +Explicitly sets the specified principal's keys to the n_keys keys in +the new_keys array. The keys in new_keys should not be encrypted in +the Kerberos master key; this function will perform that operation +itself (the keys will be protected during transmission from the +calling client to the kadmind server by the AUTH_GSSAPI RPC layer). +This function completely bypasses the principal's password policy, if +set. + +\begin{enumerate} +\item If the principal does not exist, return KADM5_UNK_PRINC. +\item If the principal you are trying to change is kadmin/history return +KADM5_PROTECT_PRINCIPAL. +\item If new_keys contains more than one key of any ENCTYPE_DES_CBC_* +type that is folded, return KADM5_SETKEY_DUP_ENCTYPES. +\item Store old key in history. +\item Update principal to have new key. +\item Increment principal's key version number by one. +\item If the POLICY bit in aux_attributes is set, set pw_expiration to +now + max_pw_life. +\item If the KRB5_KDC_REQUIRES_PWCHANGE bit is set in the principal's +attributes, clear it. +\item Update last_pwd_change and mod_date to now, update mod_name to +caller. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PROTECT_PRINCIPAL] Cannot change the password of a special +principal +\end{description} + +This function can also be used as part of a sequence to create a new +principal with an explicitly key. The steps to perform the operation +securely are + +\begin{enumerate} +\item Create the principal with kadm5_create_principal with a +random password string and with the KRB5_KDB_DISALLOW_ALL_TIX bit set +in the attributes field. + +\item Set the principal's key with kadm5_setkey_principal. + +\item Call kadm5_modify_principal to reset the +KRB5_KDB_DISALLOW_ALL_TIX bit in the attributes field. +\end{enumerate} + +The three steps are necessary to ensure secure creation. Since an +attacker might be able to guess the initial password assigned by the +client program, the principal must be disabled until the key can be +truly randomized. + +\subsection{kadm5_get_principal} + +In KADM5_API_VERSION_1: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_principal(void *server_handle, krb5_principal princ, + kadm5_principal_ent_t *ent); +\end{verbatim} + +In KADM5_API_VERSION_2: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_principal(void *server_handle, krb5_principal princ, + kadm5_principal_ent_t ent, u_int32 mask); +\end{verbatim} + +AUTHORIZATION REQUIRED: get, or the calling principal being the same +as the princ argument. If the request is authenticated to the +kadmin/changepw service, the get privilege is disregarded. + +In KADM5_API_VERSION_1, return all of the principal's attributes in +allocated memory; if an error is returned entry is set to NULL. In +KADM5_API_VERSION_2, fill in the fields of the principal structure +specified in the mask; memory for the structure is not allocated. +Typically, a caller will specify the mask KADM5_PRINCIPAL_NORMAL_MASK, +which includes all the fields {\it except} key_data and tl_data to +improve time and memory efficiency. A caller that wants key_data and +tl_data can bitwise-OR those masks onto NORMAL_MASK. Note that even +if KADM5_TL_DATA is specified, this function will not return internal +tl_data elements whose type is less than 256. + +The caller must free the returned entry with kadm5_free_principal_ent. + +The function behaves differently for local and remote clients. For +remote clients, the KEY_DATA mask is illegal and results in a +KADM5_BAD_MASK error. + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_BAD_MASK] The mask is not valid for a get operation. + +\end{description} + +\subsection{kadm5_decyrpt_key} + +\begin{verbatim} +kadm5_ret_t kadm5_decrypt_key(void *server_handle, + kadm5_principal_ent_t entry, krb5_int32 + ktype, krb5_int32 stype, krb5_int32 + kvno, krb5_keyblock *keyblock, + krb5_keysalt *keysalt, int *kvnop) +\end{verbatim} + +AUTHORIZATION REQUIRED: none, local function + +Searches a principal's key_data array to find a key with the specified +enctype, salt type, and kvno, and decrypts the key into keyblock and +keysalt if found. entry must have been returned by +kadm5_get_principal with at least the KADM5_KEY_DATA mask set. +Returns ENOENT if the key cannot be found, EINVAL if the key_data +array is empty (as it always is in an RPC client). + +If ktype or stype is -1, it is ignored for the search. If kvno is -1, +ktype and stype are ignored and the key with the max kvno is returned. +If kvno is 0, only the key with the max kvno is returned and only if +it matches the ktype and stype; otherwise, ENOENT is returned. + +\subsection{kadm5_get_principals} + +\begin{verbatim} +kadm5_ret_t +kadm5_get_principals(void *server_handle, char *exp, + char ***princs, int *count) +\end{verbatim} + +Retrieves the list of principal names. + +AUTHORIZATION REQUIRED: list + +If \v{exp} is NULL, all principal names are retrieved; otherwise, +principal names that match the expression exp are retrieved. +\v{princs} is filled in with a pointer to a NULL-terminated array of +strings, and \v{count} is filled in with the number of principal names +in the array. \v{princs} must be freed with a call to +\v{kadm5_free_name_list}. + +All characters in the expression match themselves except ``?'' which +matches any single character, ``*'' which matches any number of +consecutive characters, and ``[chars]'' which matches any single +character of ``chars''. Any character which follows a ``$\backslash$'' +matches itself exactly, and a ``$\backslash$'' cannot be the last +character in the string. + +\subsection{kadm5_create_policy} + +\begin{verbatim} +kadm5_ret_t +kadm5_create_policy(void *server_handle, + kadm5_policy_ent_t policy, u_int32 mask); +\end{verbatim} + +Create a new policy. + +AUTHORIZATION REQUIRED: add + +\begin{enumerate} +\item Check to see if mask is valid, if not return KADM5_BAD_MASK error. +\item Return KADM5_BAD_POLICY if the policy name contains illegal +characters. + +\item Check to see if the policy already exists, if so return +KADM5_DUP error. +\item If the PW_MIN_CLASSES bit is set and pw_min_classes is not 1, 2, +3, 4, or 5, return KADM5_BAD_CLASS. +\item Create a new policy setting the appropriate fields determined +by the mask. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_DUP] Policy already exists +\item[KADM5_BAD_MASK] The mask is not valid for a create +operation. +\item[KADM5_BAD_CLASS] The specified number of character classes +is invalid. +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\end{description} + +\subsection{kadm5_delete_policy} + +\begin{verbatim} +kadm5_ret_t +kadm5_delete_policy(void *server_handle, char *policy); +\end{verbatim} + +Deletes a policy. + +AUTHORIZATION REQUIRED: delete + +\begin{enumerate} +\item Return KADM5_BAD_POLICY if the policy name contains illegal +characters. +\item Return KADM5_UNK_POLICY if the named policy does not exist. +\item Return KADM5_POLICY_REF if the named policy's refcnt is not 0. +\item Delete policy. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\item[KADM5_UNK_POLICY] Policy does not exist. +\item[KADM5_POLICY_REF] Policy is being referenced. +\end{description} + +\subsection{kadm5_modify_policy} + +\begin{verbatim} +kadm5_ret_t +kadm5_modify_policy(void *server_handle, + kadm5_policy_ent_t policy, u_int32 mask); +\end{verbatim} + +Modify an existing policy. Note that modifying a policy has no affect +on a principal using the policy until the next time the principal's +password is changed. + +AUTHORIZATION REQUIRED: modify + +\begin{enumerate} +\item Return KADM5_BAD_POLICY if the policy name contains illegal +characters. +\item Check to see if mask is legal, if not return KADM5_BAD_MASK error. +\item Check to see if policy exists, if not return +KADM5_UNK_POLICY error. +\item If the PW_MIN_CLASSES bit is set and pw_min_classes is not 1, 2, +3, 4, or 5, return KADM5_BAD_CLASS. +\item Update the fields specified in the mask. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\item[KADM5_UNK_POLICY] Policy not found. +\item[KADM5_BAD_MASK] The mask is not valid for a modify +operation. +\item[KADM5_BAD_CLASS] The specified number of character classes +is invalid. +\end{description} + +\subsection{kadm5_get_policy} + +In KADM5_API_VERSION_1: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_policy(void *server_handle, char *policy, kadm5_policy_ent_t *ent); +\end{verbatim} + +In KADM5_API_VERSION_2: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_policy(void *server_handle, char *policy, kadm5_policy_ent_t ent); +\end{verbatim} + +AUTHORIZATION REQUIRED: get, or the calling principal's policy being +the same as the policy argument. If the request is authenticated to +the kadmin/changepw service, the get privilege is disregarded. + +In KADM5_API_VERSION_1, return the policy's attributes in allocated +memory; if an error is returned entry is set to NULL. In +KADM5_API_VERSION_2, fill in fields of the policy structure allocated +by the caller. The caller must free the returned entry with +kadm5_free_policy_ent + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\item[KADM5_UNK_POLICY] Policy not found. +\end{description} + +\subsection{kadm5_get_policies} + +\begin{verbatim} +kadm5_ret_t +kadm5_get_policies(void *server_handle, char *exp, + char ***pols, int *count) +\end{verbatim} + +Retrieves the list of principal names. + +AUTHORIZATION REQUIRED: list + +If \v{exp} is NULL, all principal names are retrieved; otherwise, +principal names that match the expression exp are retrieved. \v{pols} +is filled in with a pointer to a NULL-terminated array of strings, and +\v{count} is filled in with the number of principal names in the +array. \v{pols} must be freed with a call to +\v{kadm5_free_name_list}. + +All characters in the expression match themselves except ``?'' which +matches any single character, ``*'' which matches any number of +consecutive characters, and ``[chars]'' which matches any single +character of ``chars''. Any character which follows a ``$\backslash$'' +matches itself exactly, and a ``$\backslash$'' cannot be the last +character in the string. + +\subsection{kadm5_free_principal_ent, _policy_ent} + +\begin{verbatim} +void kadm5_free_principal_ent(void *server_handle, + kadm5_principal_ent_t princ); +\end{verbatim} + +In KADM5_API_VERSION_1, free the structure and contents allocated by a +call to kadm5_get_principal. In KADM5_API_VERSION_2, free the +contents allocated by a call to kadm5_get_principal. + +AUTHORIZATION REQUIRED: none (local operation) + +\begin{verbatim} +void kadm5_free_policy_ent(kadm5_policy_ent_t policy); +\end{verbatim} + +Free memory that was allocated by a call to kadm5_get_policy. If +the argument is NULL, the function returns succesfully. + +AUTHORIZATION REQUIRED: none (local operation) + +\subsection{kadm5_free_name_list} + +\begin{verbatim} +void kadm5_free_name_list(void *server_handle, + char **names, int *count); +\end{verbatim} + +Free the memory that was allocated by kadm5_get_principals or +kadm5_get_policies. names and count must be a matched pair of +values returned from one of those two functions. + +\subsection{kadm5_free_key_data} + +\begin{verbatim} +void kadm5_free_key_data(void *server_handle, + krb5_int16 *n_key_data, krb5_key_data *key_data) +\end{verbatim} + +Free the memory that was allocated by kadm5_randkey_principal. +n_key_data and key_data must be a matched pair of values returned from +that function. + +\subsection{kadm5_get_privs} + +\begin{verbatim} +kadm5_ret_t +kadm5_get_privs(void *server_handle, u_int32 *privs); +\end{verbatim} + +Return the caller's admin server privileges in the integer pointed to +by the argument. The Admin API does not define any way for a +principal's privileges to be set. Note that this function will +probably be removed or drastically changed in future versions of this +system. + +The returned value is a bitmask indicating the caller's privileges: + +\begin{tabular}{llr} +{\bf Privilege} & {\bf Symbol} & {\bf Value} \\ +Get & KADM5_PRIV_GET & 0x01 \\ +Add & KADM5_PRIV_ADD & 0x02 \\ +Modify & KADM5_PRIV_MODIFY & 0x04 \\ +Delete & KADM5_PRIV_DELETE & 0x08 \\ +List & KADM5_PRIV_LIST & 0x10 \\ +Changepw & KADM5_PRIV_CPW & 0x20 +\end{tabular} + +There is no guarantee that a caller will have a privilege indicated by +this function for any length of time or for any particular target; +applications using this function must still be prepared to handle all +possible KADM5_AUTH_* error codes. + +In the initial MIT Kerberos version of the admin server, permissions +depend both on the caller and the target; this function returns a +bitmask representing all privileges the caller can possibly have for +any possible target. + +\end{document} diff --git a/krb5-1-6/doc/kadm5/api-server-design.tex b/krb5-1-6/doc/kadm5/api-server-design.tex new file mode 100644 index 000000000..61fc868fe --- /dev/null +++ b/krb5-1-6/doc/kadm5/api-server-design.tex @@ -0,0 +1,1042 @@ +\documentstyle[12pt,fullpage,rcsid]{article} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\rcs$Id$ + +\setlength{\parskip}{.7\baselineskip} +\setlength{\parindent}{0pt} + +\def\v#1{\verb+#1+} +\def\k#1{K$_#1$} + +\title{KADM5 Library and Server \\ Implementation Design\thanks{\rcsId}} +\author{Barry Jaspan} + +\begin{document} + +\sloppy +\maketitle + +{\setlength{\parskip}{0pt}\tableofcontents} + +\section{Overview} + +The KADM5 administration system is designed around the KADM5 API. The +``server-side'' library libkadm5srv.a implements the KADM5 API by +operating directly on the underlying KDC and admin databases. The +``client-side'' library libkadm5clnt.a implements the KADM5 API via an +RPC mechanism. The administration server kadmind accepts RPC requests +from the client-side library and translates them into calls to the +server-side library, performing authentication, authorization, and +logging along the way. + +The two libraries, libkadm5clnt.a and libkadm5srv.a, export the +identical kadm5 interface; for example, both contain definitions for +kadm5_get_principal, and all other kadm5 functions. In most cases, +the client library function just marshalls arguments and results into +and out of an RPC call, whereas the server library function performs +the actual operation on the database file. kadm5_init_*, however, are +substantially different even though they export the same interface: on +the client, they establish the RPC connection and GSS-API context, +whereas on the server side the open the database files, read in the +password dictionary, and the like. Also, the kadm5_free functions +operate on local process memory in both libraries. + +The admin server is implemented as a nearly-stateless transaction +server, where each admin API function represents a single transaction. +No per-client or per-connection information is stored; only local +database handles are maintained between requests. The RPC mechanism +provides access to remote callers' authentication credentials for +authorization purposes. + +The admin API is exported via an RPC interface that hides all details +about network encoding, authentication, and encryption of data on the +wire. The RPC mechanism does, however, allow the server to access the +underlying authentication credentials for authorization purposes. + +The admin system maintains two databases: +% +\begin{itemize} +\item The master Kerberos (KDC) database is used to store all the +information that the Kerberos server understands, thus allowing the +greatest functionality with no modifications to a standard KDC. + +\item The KDC database also stores kadm5-specific per-principal +information in each principal's krb5_tl_data list. In a prior +version, this data was stored in a separate admin principal database; +thus, when this document refers to ``the admin principal database,'' +it now refers to the appropriate krb5_tl_data entries in the KDC +database. + +\item The policy database stores kadm5 policy information. +\end{itemize} + +The per-principal information stored in the admin principal database +consists of the principal's policy name and an array of the +principal's previous keys. The old keys are stored encrypted in the +key of the special principal ``kadmin/history'' that is created by the +server library when it is first needed. Since a change in +kadmin/history's key renders every principal's key history array +useless, it can only be changed using the ovsec_adm_edit utility; that +program will reencrypt every principal's key history in the new +key.\footnote{ovsec_adm_edit has not yet been implemented, and there +are currently no plans to implement it; thus, the history cannot +currently be changed.} The server library refuses all requests to +change kadmin/history's key. + +\section{API Handles} + +Each call to kadm5_init_* on the client or server creates a new API +handle. The handles encapsulate the API and structure versions +specified by kadm5_init_*'s caller and all other internal data needed +by the library. A process can have multiple open API handles +simultaneously by calling kadm5_init_* multiple times, and call can +specify a different version, client or service principal, and so +forth. + +Each kadm5 function verifies the handle it is given with the +CHECK_HANDLE or _KADM5_CHECK_HANDLE macros. The CHECK_HANDLE macro +differs for the client and server library because the handle types +used by those libraries differ, so it is defined in both +$<$client_internal.h$>$ and $<$server_internal.h$>$ in the library +source directory. In each header file, CHECK_HANDLE first calls +GENERIC_CHECK_HANDLE, defined in $<$admin_internal.h$>$, which +verifies the magic number, API version, and structure version that is +contained in both client and server handles. CHECK_HANDLE then calls +either CLIENT_CHECK_HANDLE or SERVER_CHECK_HANDLE respectively to +verify the client- or server-library specific handle fields. + +The CHECK_HANDLE macro is useful because it inlines the handle check +instead of requiring a separate function call. However, using +CHECK_HANDLE means that a source file cannot be compiled once and +included into both the client and server library, because CHECK_HANDLE +is always either specific to either the client or server library, not +both. There are a number of functions that can be implemented with +the same code in both the client and server libraries, however, +including all of the kadm5_free functions and +kadm5_chpass_principal_util. The _KADM5_CHECK_HANDLE macro solves +this problem; instead of inlining the handle check, it calls the +function _kadm5_check_handle which is defined separately in both the +client and server library, in client_init.c and server_init.c. +Since these two files are only compiled once and put in a single +library, they simply verify the handle they are passed with +CHECK_HANDLE and return the result. + +\section{API Versioning} + +The KADM5 system is designed to support multiple versions of the KADM5 +API. Presently, two versions exist: KADM5_API_VERSION_1 and +KADM5_API_VERSION_2. The former is equivalant to the initial +OpenVision API, OVSEC_KADM_API_VERSION_1; the latter was created +during the initial integration of the OpenVision system into the MIT +release. + +Implementing a versioned API in C via with both local and RPC access +presents a number of design issues, some of them quite subtle. The +contexts in which versioning considerations must be made include: + +\begin{enumerate} +\item Typedefs, function declarations, and defined constants depend on +the API version a client is written to and must be correct at compile +time. + +\item Each function in the server library must behave according to the +API version specified by the caller at runtime to kadm5_init_*. + +\item The XDR functions used by the RPC layer to transmit function +arguments and results must encode data structures correctly depending +on the API version specified by the client at runtime. + +\item Each function in the client library must behave according to the +API version specified by the caller at runtime to kadm5_init_*. + +\item The RPC server (kadmind) must accept calls from a client using +any supported API version, and must then invoke the function in the +server library corresponding to the RPC with the API version indicated +by the client caller. + +\item When a first API function is invoked that needs to call a second +function in the API on its own behalf, and that second API function's +behavior depends on the API version specified, the first API function +must either be prepared to call the second API function at whatever +version its caller specifies or have a means of always calling the +second API function at a pre-determined version. +\end{enumerate} + +The following functions describe how each context is handled. + +\subsection{Designing for future compatibility} + +Any code whose behavior depends on the API version should be written +so as to be compatible with future, currently unknown API versions on +the grounds that any particuarly piece of API behavior will most +likely not change between versions. For example, in the current +system, the code is not written as ``if this is VERSION_1, do X, else +if this is VERSION_2, do Y''; instead, it is written as ``if this is +VERSION_1, do X; else, do Y.'' The former will require additional +work when VERSION_3 is defined, even if ``do Y'' is still the correct +action, whereas the latter will work without modification in that +case. + +\subsection{Header file declarations} + +Typedefs, defined constants and macros, and function declarations may +change between versions. A client is always written to a single, +specific API version, and thus expects the header files to define +everything according to that API. Failure of a header file to define +values correctly will result in either compiler warnings (e.g. if the +pointer type of a function argument changes) or fatal errors (e.g. if +the number of arguments to a function changes, or the fields of a +structure change). For example, in VERSION_1, kadm5_get_policy took a +pointer to a pointer to a structure, and in VERSION_2 it takes a +pointer to a structure; that would generate a warning if not correct. +In VERSION_1, kadm5_randkey_principal accepted three arguments but in +VERSION_2 accepts four; that would generate a fatal error. + +The header file defines everything correctly based on the value of the +USE_KADM5_API_VERSION constant. The constant can be assigned to an +integer corresponding to any supported API version, and defaults to +the newest version. The header files then simply use an \#ifdef to +include the right definitions: +% +\begin{verbatim} +#if USE_KADM5_API_VERSION == 1 +kadm5_ret_t kadm5_get_principal(void *server_handle, + krb5_principal principal, + kadm5_principal_ent_t *ent); +#else +kadm5_ret_t kadm5_get_principal(void *server_handle, + krb5_principal principal, + kadm5_principal_ent_t ent, + long mask); +#endif +\end{verbatim} + +\subsection{Server library functions} + +Server library functions must know how many and what type of arguments +to expect, and must operate on those arguments correctly, based on the +API version with which they are invoked. The API version is contained +in the handle that is alwasy passed as their first argument, generated +by kadm5_init_* (to which the client specified the API version to use +at run-time). + +In general, it is probably unsafe for a compiled function in a library +to re-interpret the number and type of defined arguments at run-time +since the calling conventions may not allow it; for example, a +function whose first argument was a short in one version and a pointer +in the next might fail if it simply typed-casted the argument. In +that case, the function would have to written to take variable +arguments (i.e. use $<$stdarg.h$>$) and extract them from the stack +based on the API version. Alternatively, a separate function for each +API version could be defined, and $<$kadm5/admin.h$>$ could be written +to \v{\#define} the exported function name based on the value of +USE_KADM5_API_VERSION. + +In the current system, it turns out, that isn't necessary, and future +implementors should take try to ensure that no version has semantics +that will cause such problems in the future. All the functions in +KADM5 that have different arguments or results between VERSION_1 and +VERSION_2 do so simply by type-casting their arguments to the +appropriate version and then have separate code paths to handle each +one correctly. kadm5_get_principal, in svr_principal.c, is a good +example. In VERSION_1, it took the address of a pointer to a +kadm5_principal_ent_t to fill in with a pointer to allocated memory; +in VERSION_2, it takes a pointer to a structure to fill in, and a mask +of which fields in that structure should be filled in. Also, the +contents of the kadm5_principal_ent_t changed slightly between the two +versions. kadm5_get_principal handles versioning as follows +(following along in the source code will be helpful): + +\begin{enumerate} +\item If VERSION_1, it saves away its entry argument (address of a +pointer to a structure) and resets its value to contain the address of +a locally stack-allocated entry structure; this allows most of the +function to written once, in terms of VERSION_2 semantics. If +VERSION_1, it also resets its mask argument to be +KADM5_PRINCIPAL_NORMAL_MASK, because that is the equivalent to +VERSION_1 behavior, which was to return all the fields of the +structure. + +\item The bulk of the function is implemented as expected for +VERSION_2. + +\item The new fields in the VERSION_2 entry structure are assigned +inside a block that is only execute if the caller specified +VERSION_2. This saves a little time for a VERSION_1 caller. + +\item After the entry structure is filled, the function checks again +if it was called as VERSION_1. If so, it allocates a new +kadm5_principal_ent_t_v1 structure (which is conveniently defined in +the header file) with malloc, copies the appropriate values from the +entry structure into the VERSION_1 entry structure, and then writes +the address of the newly allocated memory into address specified by +the original entry argument which it had previously saved away. +\end{enumerate} + +There is another complication involved in a function re-interpreting +the number of arguments it receives at compile time---it cannot assign +any value to an argument for which the client did not pass a value. +For example, a VERSION_1 client only passes three arguments to +kadm5_get_principal. If the implementation of kadm5_get_principal +notices that the caller is VERSION_1 and therefore assigns its fourth +argument, mask, to a value that mimics the VERSION_1 behavior, it may +inadvertently overwrite data on its caller's stack. This problem can +be avoided simply by using a true local variable in such cases, +instead of treating an unpassed argument as a local variable. + +\subsection{XDR functions} + +The XDR functions used to encode function arguments and results must +know how to encode the data for any API version. This is important +both so that all the data gets correctly transmitted and so that +protocol compatibility between clients or servers using the new +library but an old API version is maintained; specific, new kadmind +servers should support old kadm5 clients. + +The signature of all XDR functions is strictly defined: they take the +address of an XDR function and the address of the data object to be +encoded or decoded. It is thus impossible to provide the API version +of the data object as an additional argument to an XDR function. +There are two other means to convey the information, storing the API +version to use as a field in the data object itself and creating +separate XDR functions to handle each different version of the data +object, and both of them are used in KADM5. + +In the client library, each kadm5 function collects its arguments into +a single structure to be passed by the RPC; similarly, it expects all +of the results to come back as a single structure from the RPC that it +will then decode back into its constituent pieces (these are the +standard ONC RPC semantics). In order to pass versioning information +to the XDR functions, each function argument and result datatype has a +filed to store the API version. For example, consider +kadm5_get_principal's structures: +% +\begin{verbatim} +struct gprinc_arg { + krb5_ui_4 api_version; + krb5_principal princ; + long mask; +}; +typedef struct gprinc_arg gprinc_arg; +bool_t xdr_gprinc_arg(); + +struct gprinc_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + kadm5_principal_ent_rec rec; +}; +typedef struct gprinc_ret gprinc_ret; +bool_t xdr_gprinc_ret(); +\end{verbatim} +% +kadm5_get_principal (in client_principal.c) assigns the api_version +field of the gprinc_arg to the version specified by its caller, +assigns the princ field based on its arguments, and assigns the mask +field from its argument if the caller specified VERSION_2. It then +calls the RPC function clnt_call, specifying the XDR functions +xdr_gprinc_arg and xdr_gprinc_ret to handle the arguments and results. + +xdr_gprinc_arg is invoked with a pointer to the gprinc_arg structure +just described. It first encodes the api_version field; this allows +the server to know what to expect. It then encodes the krb5_principal +structure and, if api_version is VERSION_2, the mask. If api_version +is not VERSION_2, it does not encode {\it anything} in place of the +mask, because an old VERSION_1 server will not expect any other data +to arrive on the wire there. + +The server performs the kadm5_get_principal call and returns its +results in an XDR encoded gprinc_ret structure. clnt_call, which has +been blocking until the results arrived, invokes xdr_gprinc_ret with a +pointer to the encoded data for it to decode. xdr_gprinc_ret first +decodes the api_version field, and then the code field since that is +present in all versions to date. The kadm5_principal_ent_rec presents +a problem, however. The structure does not itself contain an +api_version field, but the structure is different between the two +versions. Thus, a single XDR function cannot decode both versions of +the structure because it will have no way to decide which version to +expect. The solution is to have two functions, +kadm5_principal_ent_rec_v1 and kadm5_principal_ent_rec, which always +decode according to VERSION_1 or VERSION_2, respectively. gprinc_ret +knows which one to invoke because it has the api_version field +returned by the server (which is always the same as that specified by +the client in the gpring_arg). + +In hindsight, it probably would have been better to encode the API +version of all structures directly in a version field in the structure +itself; then multiple XDR functions for a single data type wouldn't be +necessary, and the data objects would stand complete on their own. +This can be added in a future API version if desired. + +\subsection{Client library functions} + +Just as with server library functions, client library functions must +be able to interpret their arguments and provide result according to +the API version specified by the caller. Again, kadm5_get_principal +(in client_principal.c) is a good example. The gprinc_ret structure +that it gets back from clnt_call contains a kadm5_principal_ent_rec or +a kadm5_principal_ent_rec_v1 (the logic is simplified somewhat because +the VERSION_2 structure only has new fields added on the end). If +kadm5_get_principal was invoked with VERSION_2, that structure should +be copied into the pointer provided as the entry argument; if it was +invoked with VERSION_1, however, the structure should be copied into +allocated memory whose address is then written into the pointer +provided by the entry argument. Client library functions make this +determination based on the API version specified in the provided +handle, just like server library functions do. + +\subsection{Admin server stubs} + +When an RPC call arrives at the server, the RPC layer authenticates +the call using the GSS-API, decodes the arguments into their +single-structure form (ie: a gprinc_arg) and dispatches the call to a +stub function in the server (in server_stubs.c). The stub function +first checks the caller's authorization to invoke the function and, if +authorized, calls the kadm5 function corresponding to the RPC function +with the arguments specified in the single-structure argument. + +Once again, kadm5_get_principal is a good example for the issues +involved. The contents of the gprinc_arg given to the stub +(get_principal_1) depends on the API version the caller on the client +side specified; that version is available to the server in the +api_version field of the gprinc_arg. When the server calls +kadm5_get_principal in the server library, it must give that function +an API handle that contains the API version requested by the client; +otherwise the function semantics might not be correct. One +possibility would be for the server to call kadm5_init for each client +request, specifing the client's API version number and thus generating +an API handle with the correct version, but that would be +prohibitively inefficient. Instead, the server dips down in the +server library's internal abstraction barrier, using the function +new_server_handle to cons up a server handle based on the server's own +global_server_handle but using the API version specified by the +client. The server then passes the newly generated handle to +kadm5_get_principal, ensuring the right behavior, and creates the +gprinc_ret structure in a manner similar to that described above. + +Although new_server_handle solves the problem of providing the server +with an API handle containing the right API version number, it does +not solve another problem: that a single source file, server_stubs.c, +needs to be able to invoke functions with arguments appropriate for +multiple API versions. If the client specifies VERSION_1, for +example, the server must invoke kadm5_get_principal with three +arguments, but if the client specifies VERSION_2 the server must +invoke kadm5_get_principal with four arguments. The compiler will not +allow this inconsistency. The server defines wrapper functions in a +separate source file that match the old version, and the separate +source file is compiled with USE_KADM5_API_VERSION set to the old +version; see kadm5_get_principal_v1 in server_glue_v1.c. The server +then calls the correct variant of kadm5_get_principal_* based on the +API version and puts the return values into the gprinc_ret in a manner +similar to that described above. + +Neither of these solutions are necessarily correct. new_server_handle +violates the server library's abstraction barrier and is at best a +kludge; the server library should probably export a function to +provide this behavior without violating the abstraction; +alternatively, the librar should be modified so that having the server +call kadm5_init for each client RPC request would not be too +inefficient. The glue functions in server_glue_v1.c really are not +necessary, because the server stubs could always just pass dummy +arguments for the extra arguments; after all, the glue functions pass +{\it nothing} for the extra arguments, so they just end up as stack +garbage anyway. + +Another alternative to the new_server_handle problem is to have the +server always invoke server library functions at a single API version, +and then have the stubs take care of converting the function arguments +and results back into the form expected by the caller. In general, +however, this might require the stubs to duplicate substantial logic +already present in the server library and further violate the server +library's abstraction barrier. + +\subsection{KADM5 self-reference} + +Some kadm5 functions call other kadm5 functions ``on their own +behalf'' to perform functionality that is necessary but that does not +directly affect what the client sees. For example, +kadm5_chpass_principal has to enforce password policies; thus, it +needs to call kadm5_get_principal and, if the principal has a policy, +kadm5_get_policy and kadm5_modify_principal in the process of changing +a principal's password. This leads to a complication: what API handle +should kadm5_chpass_principal pass to the other kadm5 functions it +calls? + +The ``obvious,'' but wrong, answer is that it should pass the handle +it was given by its caller. The caller may provide an API handle +specifying any valid API version. Although the semantics of +kadm5_chpass_principal did not change between VERSION_1 and VERSION_2, +the declarations of both kadm5_get_principal and kadm5_get_policy +did. Thus, to use the caller's API handle, kadm5_chpass_principal +will have to have a separate code path for each API version, even +though it itself did not change bewteen versions, and duplicate a lot +of logic found elsewhere in the library. + +Instead, each API handle contains a ``local-use handle,'' or lhandle, +that kadm5 functions should use to call other kadm5 functions. For +example, the client-side library's handle structure is: +% +\begin{verbatim} +typedef struct _kadm5_server_handle_t { + krb5_ui_4 magic_number; + krb5_ui_4 struct_version; + krb5_ui_4 api_version; + char * cache_name; + int destroy_cache; + CLIENT * clnt; + krb5_context context; + kadm5_config_params params; + struct _kadm5_server_handle_t *lhandle; +} kadm5_server_handle_rec, *kadm5_server_handle_t; +\end{verbatim} +% +The lhandle field is allocated automatically when the handle is +created. All of the fields of the API handle that are accessed +outside kadm5_init are also duplicated in the lhandle; however, the +api_version field of the lhandle is always set to a {\it constant} +value, regardless of the API version specified by the caller to +kadm5_init. In the current implementation, the lhandle's api_version +is always VERSION_2. + +By passing the caller's handle's lhandle to recursively called kadm5 +functions, a kadm5 function is assured of invoking the second kadm5 +function with a known API version. Additionally, the lhandle's +lhandle field points back to the lhandle, in case kadm5 functions call +themselves more than one level deep; handle$->$lhandle always points +to the same lhandle, no matter how many times the indirection is +performed. + +This scheme might break down if a kadm5 function has to call another +kadm5 function to perform operations that they client will see and for +its own benefit, since the semantics of the recursively-called kadm5 +function may depend on the API version specified and the client may be +depending on a particular version's behavior. Future implementators +should avoid creating a situation in which this is possible. + +\section{Server Main} + +The admin server starts by trapping all fatal signals and directing +them to a cleanup-and-exit function. It then creates and exports the +RPC interface and enters its main loop. + +The main loop dispatches all incoming requests to the RPC mechanism. +In a previous version, after 15 seconds of inactivity, the server +closed all open databases; each database was be automatically reopened +by the API function implementations as necessary. That behavior +existed to protect against loss of written data before the process +exited. The current database libraries write all changes out to disk +immediately, however, so this behavior is no longer required or +performed. + +\section{Remote Procedure Calls} + +The RPC for the Admin system will be based on ONC RPC. ONC RPC is +used because it is a well-known, portable RPC mechanism. The +underlying external data representation (xdr) mechanisms for wire +encapsulation are well-known and extensible. Authentication to the +admin server and encryption of all RPC functional arguments and +results are be handled via the AUTH_GSSAPI authentication flavor of +ONC RPC. + +\section{Database Record Types} +\label{sec:db-types} + +\subsection{Admin Principal, osa_princ_ent_t} + +The admin principal database stores records of the type +osa_princ_ent_t (declared in $<$kadm5/adb.h$>$), which is the +subset of the kadm5_principal_ent_t structure that is not stored +in the Kerberos database plus the necessary bookkeeping information. +The records are keyed by the ASCII representation of the principal's +name, including the trailing NULL. + +\begin{verbatim} +typedef struct _osa_pw_hist_t { + int n_key_data; + krb5_key_data *key_data; +} osa_pw_hist_ent, *osa_pw_hist_t; + +typedef struct _osa_princ_ent_t { + char * policy; + u_int32 aux_attributes; + + unsigned int old_key_len; + unsigned int old_key_next; + krb5_kvno admin_history_kvno; + osa_pw_hist_ent *old_keys; + + + u_int32 num_old_keys; + u_int32 next_old_key; + krb5_kvno admin_history_kvno; + osa_pw_hist_ent *old_keys; +} osa_princ_ent_rec, *osa_princ_ent_t; +\end{verbatim} + +The fields that are different from kadm5_principal_ent_t are: + +\begin{description} +\item[num_old_keys] The number of previous keys in the old_keys array. +This value must be 0 $\le$ num_old_keys $<$ pw_history_num. + +\item[old_key_next] The index into old_keys where the next key should +be inserted. This value must be 0 $\le$ old_key_next $\le$ +num_old_keys. + +\item[admin_history_kvno] The key version number of the kadmin/history +principal's key used to encrypt the values in old_keys. If the server +library finds that kadmin/history's kvno is different from the value +in this field, it returns KADM5_BAD_HIST_KEY. + +\item[old_keys] The array of the principal's previous passwords, each +encrypted in the kadmin/history key. There are num_old_keys +elements. Each ``password'' in the array is itself an array of +n_key_data krb5_key_data structures, one for each keysalt type the +password was encoded in. +\end{description} + +\subsection{Policy, osa_policy_ent_t} + +The policy database stores records of the type osa_policy_ent_t +(declared in $<$kadm5/adb.h$>$) , which is all of +kadm5_policy_ent_t plus necessary bookkeeping information. The +records are keyed by the policy name. + +\begin{verbatim} +typedef struct _osa_policy_ent_t { + char *policy; + + u_int32 pw_min_life; + u_int32 pw_max_life; + u_int32 pw_min_length; + u_int32 pw_min_classes; + u_int32 pw_history_num; + + u_int32 refcnt; +} osa_policy_ent_rec, *osa_policy_ent_t; +\end{verbatim} + +\subsection{Kerberos, krb5_db_entry} + +The Kerberos database stores records of type krb5_db_entry, which is +defined in the $<$k5-int.h$>$ header file. The semantics of each +field are defined in the libkdb functional specification. + +\section{Database Access Methods} + +\subsection{Principal and Policy Databases} + +This section describes the database abstraction used for the admin +policy database; the admin principal database used to be treated in +the same manner but is now handled more directly as krb5_tl_data; +thus, nothing in this section applies to it any more. Since both +databases export equivalent functionality, the API is only described +once. The character T is used to represent both ``princ'' and +``policy''. The location of the principal database is defined by the +configuration parameters given to any of the kadm5_init functions in +the server library. + +Note that this is {\it only} a database abstraction. All functional +intelligence, such as maintaining policy reference counts or sanity +checking, must be implemented above this layer. + +Prototypes for the osa functions are supplied in +$<$kadm5/adb.h$>$. The routines are defined in libkadm5srv.a. They +require linking with the Berkely DB library. + +\subsubsection{Error codes} + +The database routines use com_err for error codes. The error code +table name is ``adb'' and the offsets are the same as the order +presented here. The error table header file is +$<$kadm5/adb_err.h$>$. Callers of the OSA routines should first call +init_adb_err_tbl() to initialize the database table. + +\begin{description} +\item[OSA_ADB_OK] Operation successful. +\item[OSA_ADB_FAILURE] General failure. +\item[OSA_ADB_DUP] Operation would create a duplicate database entry. +\item[OSA_ADB_NOENT] Named entry not in database. +\item[OSA_ADB_BAD_PRINC] The krb5_principal structure is invalid. +\item[OSA_ADB_BAD_POLICY] The specified policy name is invalid. +\item[OSA_ADB_XDR_FAILURE] The principal or policy structure cannot be +encoded for storage. +\item[OSA_ADB_BADLOCKMODE] Bad lock mode specified. +\item[OSA_ADB_CANTLOCK_DB] Cannot lock database, presumably because it +is already locked. +\item[OSA_ADB_NOTLOCKED] Internal error, database not locked when +unlock is called. +\item[OSA_ADB_NOLOCKFILE] KADM5 administration database lock file missing. +\end{description} + +Database functions can also return system errors. Unless otherwise +specified, database functions return OSA_ADB_OK. + +\subsubsection{Locking} + +All of the osa_adb functions except open and close lock and unlock the +database to prevent concurrency collisions. The overall locking +algorithm is as follows: + +\begin{enumerate} +\item osa_adb_open_T calls osa_adb_init_db to allocate the osa_adb_T_t +structure and open the locking file for further use. + +\item Each osa_adb functions locks the locking file and opens the +appropriate database with osa_adb_open_and_lock, performs its action, +and then closes the database and unlocks the locking file with +osa_adb_close_and_unlock. + +\item osa_adb_close_T calls osa_adb_fini_db to close the locking file +and deallocate the db structure. +\end{enumerate} + +Functions which modify the database acquire an exclusive lock, others +acqure a shared lock. osa_adb_iter_T acquires an exclusive lock for +safety but as stated below consequences of modifying the database in +the iteration function are undefined. + +\subsubsection{Function descriptions} + +\begin{verbatim} +osa_adb_ret_t osa_adb_create_T_db(kadm5_config_params *params) +\end{verbatim} +% +Create the database and lockfile specified in params. The database +must not already exist, or EEXIST is returned. The lock file is only +created after the database file has been created successfully. + +\begin{verbatim} +osa_adb_ret_t osa_adb_rename_T_db(kadm5_config_params *fromparams, + kadm5_config_params *toparams) +\end{verbatim} +% +Rename the database named by fromparams to that named by toparams. +The fromparams database must already exist; the toparams database may +exist or not. When the function returns, the database named by +fromparams no longer exists, and toparams has been overwritten with +fromparams. This function acquires a permanent lock on both databases +for the duration of its operation, so a failure is likely to leave the +databases unusable. + +\begin{verbatim} +osa_adb_ret_t osa_adb_destroy_policy_db(kadm5_config_params *params) +\end{verbatim} +% +Destroy the database named by params. The database file and lock file +are deleted. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_open_T(osa_adb_T_t *db, char *filename); +\end{verbatim} +% +Open the database named filename. Returns OSA_ADB_NOLOCKFILE if the +database does not exist or if the lock file is missing. The database +is not actually opened in the operating-system file sense until a lock +is acquire. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_close_T(osa_adb_T_t db); +\end{verbatim} +% +Release all shared or exclusive locks (on BOTH databases, since they +use the same lock file) and close the database. + +It is an error to exit while a permanent lock is held; +OSA_ADB_NOLOCKFILE is returned in this case. + +\begin{verbatim} +osa_adb_ret_t osa_adb_get_lock(osa_adb_T_t db, int mode) +\end{verbatim} + +Acquire a lock on the administration databases; note that both +databases are locked simultaneously by a single call. The mode +argument can be OSA_ADB_SHARED, OSA_ADB_EXCLUSIVE, or +OSA_ADB_PERMANENT. The first two and the third are really disjoint +locking semantics and should not be interleaved. + +Shared and exclusive locks have the usual semantics, and a program can +upgrade a shared lock to an exclusive lock by calling the function +again. A reference count of open locks is maintained by this function +and osa_adb_release_lock so the functions can be called multiple +times; the actual lock is not released until the final +osa_adb_release_lock. Note, however, that once a lock is upgraded +from shared to exclusive, or from exclusive to permanent, it is not +downgraded again until released completely. In other words, +get_lock(SHARED), get_lock(EXCLUSIVE), release_lock() leaves the +process with an exclusive lock with a reference count of one. An +attempt to get a shared or exclusive lock that conflicts with another +process results in the OSA_ADB_CANLOCK_DB error code. + +This function and osa_adb_release_lock are called automatically as +needed by all other osa_adb functions to acquire shared and exclusive +locks and so are not normally needed. They can be used explicitly by +a program that wants to perform multiple osa_adb functions within the +context of a single lock. + +Acquiring an OSA_ADB_PERMANENT lock is different. A permanent lock +consists of first acquiring an exclusive lock and then {\it deleting +the lock file}. Any subsequent attempt to acquire a lock by a +different process will fail with OSA_ADB_NOLOCKFILE instead of +OSA_ADB_CANTLOCK_DB (attempts in the same process will ``succeed'' +because only the reference count gets incremented). The lock file is +recreated by osa_adb_release_lock when the last pending lock is released. + +The purpose of a permanent lock is to absolutely ensure that the +database remain locked during non-atomic operations. If the locking +process dies while holding a permanent lock, all subsequent osa_adb +operations will fail, even through a system reboot. This is useful, +for example, for ovsec_adm_import which creates both new database +files in a temporary location and renames them into place. If both +renames do not fully complete the database will probably be +inconsistent and everything should stop working until an administrator +can clean it up. + +\begin{verbatim} +osa_adb_ret_t osa_adb_release_lock(osa_adb_T_t db) +\end{verbatim} + +Releases a shared, exclusive, or permanent lock acquired with +osa_adb_get_lock, or just decrements the reference count if multiple +locks are held. When a permanent lock is released, the lock file is +re-created. + +All of a process' shared or exclusive database locks are released when +the process terminates. A permanent lock is {\it not} released when +the process exits (although the exclusive lock it begins with +obviously is). + +\begin{verbatim} +osa_adb_ret_t +osa_adb_create_T(osa_adb_T_t db, osa_T_ent_t entry); +\end{verbatim} +% +Adds the entry to the database. All fields are defined. Returns +OSA_ADB_DUP if it already exists. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_destroy_T(osa_adb_T_t db, osa_T_t name); +\end{verbatim} + +Removes the named entry from the database. Returns OSA_ADB_NOENT if +it does not exist. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_get_T(osa_adb_T_t db, osa_T_t name, + osa_princ_ent_t *entry); +\end{verbatim} + +Looks up the named entry in the db, and returns it in *entry in +allocated storage that must be freed with osa_adb_free_T. Returns +OSA_ADB_NOENT if name does not exist, OSA_ADB_MEM if memory cannot be +allocated. + +\begin{verbatim} +osa_adb_ret_t +osadb_adb_put_T(osa_adb_T_t db, osa_T_ent_t entry); +\end{verbatim} + +Modifies the existing entry named in entry. All fields must be filled +in. Returns OSA_DB_NOENT if the named entry does not exist. Note +that this cannot be used to rename an entry; rename is implemented by +deleting the old name and creating the new one (NOT ATOMIC!). + +\begin{verbatim} +void osa_adb_free_T(osa_T_ent_t); +\end{verbatim} + +Frees the memory associated with an osa_T_ent_t allocated by +osa_adb_get_T. + +\begin{verbatim} +typedef osa_adb_ret_t (*osa_adb_iter_T_func)(void *data, + osa_T_ent_t entry); + +osa_adb_ret_t osa_adb_iter_T(osa_adb_T_t db, osa_adb_iter_T_func func, + void *data); +\end{verbatim} + +Iterates over every entry in the database. For each entry ent in the +database db, the function (*func)(data, ent) is called. If func +returns an error code, osa_adb_iter_T returns an error code. If all +invokations of func return OSA_ADB_OK, osa_adb_iter_T returns +OSA_ADB_OK. The function func is permitted to access the database, +but the consequences of modifying the database during the iteration +are undefined. + +\subsection{Kerberos Database} + +Kerberos uses the libkdb interface to store krb5_db_entry records. It +can be accessed and modified in parallel with the Kerberos server, +using functions that are defined inside the KDC and the libkdb.a. The +libkdb interface is defined in the libkdb functional specifications. + +\subsubsection{Initialization and Key Access} + +Keys stored in the Kerberos database are encrypted in the Kerberos +master key. The admin server will therefore have to acquire the key +before it can perform any key-changing operations, and will have to +decrypt and encrypt the keys retrieved from and placed into the +database via krb5_db_get_principal and _put_principal. This section +describes the internal admin server API that will be used to perform +these functions. + +\begin{verbatim} +krb5_principal master_princ; +krb5_encrypt_block master_encblock; +krb5_keyblock master_keyblock; + +void kdc_init_master() +\end{verbatim} + +kdc_init_master opens the database and acquires the master key. It +also sets the global variables master_princ, master_encblock, and +master_keyblock: + +\begin{itemize} +\item master_princ is set to the name of the Kerberos master principal +(\v{K/M@REALM}). + +\item master_encblock is something I have no idea about. + +\item master_keyblock is the Kerberos master key +\end{itemize} + +\begin{verbatim} +krb5_error_code kdb_get_entry_and_key(krb5_principal principal, + krb5_db_entry *entry, + krb5_keyblock *key) +\end{verbatim} + +kdb_get_entry_and_key retrieves the named principal's entry from the +database in entry, and decrypts its key into key. The caller must +free entry with krb5_dbm_db_free_principal and free key-$>$contents with +free.\footnote{The caller should also \v{memset(key-$>$contents, 0, +key-$>$length)}. There should be a function krb5_free_keyblock_contents +for this, but there is not.} + +\begin{verbatim} +krb5_error_code kdb_put_entry_pw(krb5_db_entry *entry, char *pw) +\end{verbatim} + +kdb_put_entry_pw stores entry in the database. All the entry values +must already be set; this function does not change any of them except +the key. pw, the NULL-terminated password string, is converted to a +key using string-to-key with the salt type specified in +entry-$>$salt_type.\footnote{The salt_type should be set based on the +command line arguments to the kadmin server (see the ``Command Line'' +section of the functional specification).} + +\section{Admin Principal and Policy Database Implementation} + +The admin principal and policy databases will each be stored in a +single hash table, implemented by the Berkeley 4.4BSD db library. +Each record will consist of an entire osa_T_ent_t. The key into the +hash table is the entry name (for principals, the ASCII representation +of the name). The value is the T entry structure. Since the key and +data must be self-contained, with no pointers, the Sun xdr mechanisms +will be used to marshal and unmarshal data in the database. + +The server in the first release will be single-threaded in that a +request will run to completion (or error) before the next will run, +but multiple connections will be allowed simultaneously. + +\section{ACLs, acl_check} + +The ACL mechanism described in the ``Authorization ACLs'' section of +the functional specifications will be implemented by the acl_check +function. + +\begin{verbatim} +enum access_t { + ACCESS_DENIED = 0, + ACCESS_OK = 1, +}; + +enum access_t acl_check(krb5_principal princ, char *priv); +\end{verbatim} + +The priv argument must be one of ``get'', ``add'', ``delete'', or +``modify''. acl_check returns 1 if the principal princ has the named +privilege, 0 if it does not. + +\section{Function Details} + +This section discusses specific design issues for Admin API functions +that are not addresed by the functional specifications. + +\subsection{kadm5_create_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +The principal's initial key is not stored in the key history array at +creation time. + +\subsection{kadm5_delete_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +\subsection{kadm5_modify_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +If pw_history_num changes and the new value $n$ is smaller than the +current value of num_old_keys, old_keys should end up with the $n$ +most recent keys; these are found by counting backwards $n$ elements +in old_keys from old_key_next. old_key_nexts should then be reset to +0, the oldest of the saved keys, and num_old_keys set to $n$, the +new actual number of old keys in the array. + +\subsection{kadm5_chpass_principal, randkey_principal} + +The algorithm for determining whether a password is in the principal's +key history is complicated by the use of the kadmin/history \k{h} +encrypting key. + +\begin{enumerate} +\item For kadm5_chpass_principal, convert the password to a key +using string-to-key and the salt method specified by the command line +arguments. + +\item If the POLICY bit is set and pw_history_num is not zero, check +if the new key is in the history. +\begin{enumerate} +\item Retrieve the principal's current key and decrypt it with \k{M}. +If it is the same as the new key, return KADM5_PASS_REUSE. +\item Retrieve the kadmin/history key \k{h} and decrypt it with \k{M}. +\item Encrypt the principal's new key in \k{h}. +\item If the principal's new key encrypted in \k{h} is in old_keys, +return KADM5_PASS_REUSE. +\item Encrypt the principal's current key in \k{h} and store it in +old_keys. +\item Erase the memory containing \k{h}. +\end{enumerate} + +\item Encrypt the principal's new key in \k{M} and store it in the +database. +\item Erase the memory containing \k{M}. +\end{enumerate} + +To store the an encrypted key in old_keys, insert it as the +old_key_next element of old_keys, and increment old_key_next by one +modulo pw_history_num. + +\subsection{kadm5_get_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +\end{document} diff --git a/krb5-1-6/doc/kadm5/api-unit-test.tex b/krb5-1-6/doc/kadm5/api-unit-test.tex new file mode 100644 index 000000000..3e0eb503e --- /dev/null +++ b/krb5-1-6/doc/kadm5/api-unit-test.tex @@ -0,0 +1,2679 @@ +\documentstyle[times,fullpage,rcsid]{article} + +\rcs$Id$ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\test}[1]{\begin{description} +\setlength{\itemsep}{0pt} +#1 +\end{description} + +} + +\newcommand{\numtest}[2]{\begin{description} +\setlength{\itemsep}{0pt} +\Number{#1} +#2 +\end{description} + +} + +\newcommand{\Number}[1]{\item[Number:] #1} +\newcommand{\Reason}[1]{\item[Reason:] #1} +\newcommand{\Expected}[1]{\item[Expected:] #1} +\newcommand{\Conditions}[1]{\item[Conditions:] #1} +\newcommand{\Priority}[1]{\item[Priority:] #1} +\newcommand{\Status}[1]{\item[Status:] #1} +\newcommand{\Vtwonote}[1]{\item[V2 note:] #1} +\newcommand{\Version}[1]{\item[Version:] #1} +\newcommand{\Call}[1]{} +%\newcommand{\Call}[1]{\item[Call:] #1} +%\newcommand{\Number}[1]{} +%\newcommand{\Reason}[1]{} +%\newcommand{\Expected}[1]{} +%\newcommand{\Conditions}[1]{} +%\newcommand{\Priority}[1]{} + +\title{KADM5 Admin API\\ +Unit Test Description\footnote{\rcsId}} +\author{Jonathan I. Kamens} + +\begin{document} + +\maketitle + +%\tableofcontents + +\section{Introduction} + +The following is a description of a black-box unit test of the KADM5 +API. Each API function is listed, followed by the tests that shoud be +performed on it. + +The tests described here are based on the ``Kerberos Administration +System KADM5 API Functional Specifications'', revision 1.68. This +document was originally written based on the OpenVision API functional +specifications, version 1.41, dated August 18, 1994, and many +indications of the original version remain. + +All tests which test for success should verify, using some means other +than the return value of the function being tested, that the requested +operation was successfully performed. For example: for init, test +that other operations can be performed after init; for destroy, test +that other operations can't be performed after destroy; for modify +functions, verify that all modifications to the database which should +have taken place did, and that the new, modified data is in effect; +for get operations, verify that the data retrieved is the data that +should actually be in the database. + +The tests would be better if they compared the actual contents of the +database before and after each test, rather than relying on the KADM5 +API to report the results of changes. + +Similarly, all tests which test for failure should verify that the +no component of the requested operation took place. For example: if +init fails, other operations should not work. If a modify fails, all +data in the database should be the same as it was before the attempt +to modify, and the old data should still be what is enforced. +Furthermore, tests which test for failure should verify that the +failure code returned is correct for the specific failure condition +tested. + +Most of the tests listed below should be run twice -- once locally on +the server after linking against the server API library, and once +talking to the server via authenticated Sun RPC after linking against +the client API library. Tests which should only be run locally or via +RPC are labelled with a ``local'' or ``RPC''. + +Furthermore, in addition to the tests labelled below, a test should be +implemented to verify that a client can't perform operations on the +server through the client API library when it's linked against +standard Sun RPC instead of OpenV*Secure's authenticated Sun RPC. +This will require a client with a modified version of ovsec_kadm_init +which doesn't call auth_gssapi_create. This client should call this +modified ovsec_kadm_init and then call some other admin API function, +specifying arguments to both functions that would work if the +authenticated Sun RPC had been used, but shouldn't if authentication +wasn't used. The test should verify that the API function call after +the init doesn't succeed. + +There is also another test to see if all the API functions handle getting an +invalid server handle correctly. This is not done as part of the tests that +are run through the TCL program cause the TCL program has no way of +invalidating a server handle. So there is a program that calls init and +changes the handle magic number, and then attempts to call each API function +with the corrupted server handle. + +A number of tests have been added or changed to correspond with KADM5 +API version 2. Tests which are only performed against the newer +version specify the version number in the test description. + +\section{ovsec_kadm_init} + +\numtest{1}{ +\Reason{An empty string realm is rejected.} +\Status{Implemented} +\Vtwonote{The empty string is now passed as the realm field of the +parameters structure.} +} + +\numtest{2}{ +\Reason{A realm containing invalid characters is rejected.} +\Status{Implemented} +\Vtwonote{The invalid character is now passed as the realm field of the +parameters structure.} +} + +\numtest{2.5}{ +\Reason{A non-existent realm is rejected.} +\Status{Implemented} +\Vtwonote{The non-existent realm is now passed as the realm field of the +parameters structure.} +} + +\numtest{3}{ +\Reason{A bad service name representing an existing principal + (different from the client principal) is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{4}{ +\Reason{A bad service name representing a non-existent + principal is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{A bad service name identical to the (existing) client + name is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{6}{ +\Reason{A null password causes password prompting.} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{An empty-string causes password prompting} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{An incorrect password which is the password of another + user is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{9}{ +\Reason{An incorrect password which isn't the password of any + user is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{10}{ +\Reason{A null client_name is rejected.} +\Status{Implemented} +} + +% Empty string client name is legal. +%\numtest{11}{ +%\Reason{An empty-string client_name is rejected.} +%} + +\numtest{12}{ +\Reason{A client_name referring to a non-existent principal in + the default realm is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{13}{ +\Reason{A client_name referring to a non-existent principal + with the local realm specified explicitly is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{14}{ +\Reason{A client_name referring to a non-existent principal in + a nonexistent realm is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{15}{ +\Reason{A client_name referring to an existing principal in a + nonexistent realm is rejected.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{16}{ +\Reason{Valid invocation.} +\Status{Implemented} +} + +\numtest{17}{ +\Reason{Valid invocation (explicit client realm).} +\Status{Implemented} +} + +\numtest{18}{ +\Reason{Valid invocation (CHANGEPW_SERVICE).} +\Status{Implemented} +} + +\numtest{19}{ +\Reason{Valid invocation (explicit service realm).} +\Status{Implemented} +\Vtwonote{The explicit realm is now passed as the realm field of the +configuration parameters.} +} + +\numtest{20}{ +\Reason{Valid invocation (database access allowed after init).} +\Status{Implemented} +} + +%\numtest{21}{ +%\Reason{Init fails when called twice in a row.} +%\Status{Implemented} +%} + +\numtest{22}{ +\Reason{A null password causes master-key prompting.} +\Conditions{local} +\Status{Implemented} +\Vtwonote{Obsolete.} +} + +\numtest{22.5}{ +\Reason{A empty string password causes master-key prompting.} +\Conditions{local} +\Status{Implemented} +\Vtwonote{Obsolete.} +} + +%\numtest{23}{ +%\Reason{A non-null password causes reading from the kstash.} +%\Conditions{local} +%\Status{Implemented} +%} + +\numtest{24}{ +\Reason{Null service name is ignored in local invocation.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{25}{ +\Reason{Non-null service name is ignored in local invocation.} +\Conditions{local} +\Status{Implemented} +} + +%\numtest{26}{ +%\Reason{Can't do ``get'' operation before calling init.} +%\Status{Implemented} +%} + +%\numtest{27}{ +%\Reason{Can't do ``add'' operation before calling init.} +%\Status{Implemented} +%} + +%\numtest{28}{ +%\Reason{Can't do ``modify'' operation before calling init.} +%\Status{Implemented} +%} + +%\numtest{29}{ +%\Reason{Can't do ``delete'' operation before calling init.} +%\Status{Implemented} +%} + +\numtest{30}{ +\Reason{Can init after failed init attempt.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{31}{ +\Priority{High} +\Reason{Return BAD_STRUCT_VERSION when the mask bits are set to invalid values} +\Status{Implemented} +} + +\numtest{32}{ +\Priority{High} +\Reason{Return BAD_STRUCT_VERSION when the mask bits are not set} +\Status{Implemented} +} + +\numtest{33}{ +\Priority{High} +\Reason{Return OLD_STRUCT_VERSION when attempting to use an old/unsupported + structure version} +\Status{Implemented} +} + +\numtest{34}{ +\Priority{High} +\Reason{Return NEW_STRUCT_VERSION when attempting to use a newer version of + of the structure then what is supported} +\Status{Implemented} +} + +\numtest{35}{ +\Priority{High} +\Reason{Return BAD_API_VERSION when the mask bits are set to invalid values} +\Status{Implemented} +} + +\numtest{36}{ +\Priority{High} +\Reason{Return BAD_API_VERSION when the mask bits are not set} +\Status{Implemented} +} + +\numtest{37}{ +\Priority{High} +\Reason{Return OLD_LIB_API_VERSION when using an old/unsuppored + api version number} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{38}{ +\Priority{High} +\Reason{Return OLD_SERVER_API_VERSION attempting to use an + old/unsupported api version number} +\Conditions{local} +\Status{Implemented} +} + +\numtest{39}{ +\Priority{High} +\Reason{Return NEW_LIB_API_VERSION when using a newer api + version number then supported} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{40}{ +\Priority{High} +\Reason{Return NEW_SERVER_API_VERSION when using a newer api version + number then supported} +\Conditions{local} +\Status{Implemented} +} + +\numtest{41}{ +\Priority{High} +\Reason{Return BAD_XXX_VERSION when the API and the structure + version numbers are reversed} +\Status{Implemented} +} + +\numtest{42}{ +\Priority{High} +\Reason{Succeeds when using valid api and struct version numbers and masks} +\Status{Implemented} +} + +\numtest{43}{ +\Priority{Low} +\Reason{Returns two different server handle when called twice with same info} +} + +\numtest{44}{ +\Priority{Low} +\Reason{Returns two different server handles when called twice with + different info} +} + +\numtest{45}{ +\Priority{Bug fix, secure-install/3390} +\Reason{Returns SECURE_PRINC_MISSING when ADMIN_SERVICE does not +exist.} +\Status{Implemented} +} + +\numtest{46}{ +\Priority{Bug fix, secure-install/3390} +\Reason{Returns SECURE_PRINC_MISSING when CHANGEPW_SERVICE does not +exist.} +\Status{Implemented} +} + +\numtest{100}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the profile field of the configuration parameters, if +set.} +\Status{Implemented} +} + +\numtest{101}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the kadmind_port field of the configuration parameters, +if set.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{102}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the admin_server field of the configuration parameters, +if set with only an admin server name.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{102.5}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the admin_server field of the configuratin parameters, +if set with a host name and port number.} +\Conditions{RPC} +} + +\numtest{103}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the dbname field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{104}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the admin_dbname field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{105}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the admin_lockfile field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{106}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the mkey_from_kbd field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{107}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the stash_file field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{108}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the mkey_name field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{109}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the max_life field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{110}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the max_rlife field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{111}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the expiration field of the configuration parameters, if +set.} +\Status{Implemented} +\Conditions{local} +} + +\numtest{112}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the flags field of the configuration parameters, if +set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{113}{ +\Version{KADM5_API_VERSION_2} +\Reason{Obeys the keysalts and num_keysalts field of the configuration +parameters, if set.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{114}{ +\Version{KADM5_API_VERSION_2} +\Reason{Returns KADM5_BAD_SERVER_PARAMS if any client-only parameters +are specified to server-side init.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{115}{ +\Version{KADM5_API_VERSION_2} +\Reason{Returns KADM5_BAD_CLIENT_PARAMS if any client-only parameters +are specified to server-side init.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{116}{ +\Version{KADM5_API_VERSION_2} +\Reason{Two calls to init with clients having different privileges +succeedes, and both clients maintain their correct privileges.} +\Priority{Bug fix} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{117}{ +\Version{KADM5_API_VERSION_2} +\Reason{The max_life field defaults to value specified in the API +Functional Specification when kdc.conf is unreadable.} +\Priority{Bug fix, krb5-admin/18} +\Conditions{local} +\Status{Implemented} +} + +\numtest{150}{ +\Version{KADM5_API_VERSION_2} +\Reason{init_with_creds works when given an open ccache with a valid +credential for ADMIN_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{151}{ +\Version{KADM5_API_VERSION_2} +\Reason{init_with_creds works when given an open ccache with a valid +credential for CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{152}{ +\Version{KADM5_API_VERSION_2} +\Reason{init_with_creds fails with KRB5_FCC_NOFILE (was + KADM5_GSS_ERROR) when given an open +ccache with no credentials.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{153}{ +\Version{KADM5_API_VERSION_2} +\Reason{init_with_creds fails with KRB5_CC_NOTFOUND (was + KADM5_GSS_ERROR) when given an open +ccache without credentials for ADMIN_SERVICE or CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{154}{ +\Version{KADM5_API_VERSION_2} +\Reason{If the KRB5_KDC_PROFILE environment variable is set to a filename +that does not exist, init fails with ENOENT.} +\Conditions{RPC} +\Status{Implemented} +} + +\section{ovsec_kadm_destroy} + +\numtest{1}{ +\Reason{Valid invocation.} +\Status{Implemented} +} + +%\numtest{2}{ +%\Reason{Valid invocation (``get'' not allowed after destroy).} +%\Status{Implemented} +%} + +%\numtest{3}{ +%\Reason{Valid invocation (``add'' not allowed after destroy).} +%\Status{Implemented} +%} + +%\numtest{4}{ +%\Reason{Valid invocation (``modify'' not allowed after destroy).} +%\Status{Implemented} +%} + +%\numtest{5}{ +%\Reason{Valid invocation (``delete'' not allowed after destroy).} +%\Status{Implemented} +%} + +%\numtest{6}{ +%\Reason{Fails if database not initialized.} +%\Status{Implemented} +%} + +%\numtest{7}{ +%\Reason{Fails if invoked twice in a row.} +%\Status{Implemented} +%} + +\numtest{8}{ +\Reason{Database can be reinitialized after destroy.} +\Status{Implemented} +} + +\numtest{9}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{10}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{client} +} + +\section{ovsec_kadm_create_principal} + +%In the tests below, ``getu'' refers to a user who has only ``get'' access, +%''addu'' refers to a user who has only ``add'' access, ``modifyu'' refers to +%a user who has only ``modify'' access, and ``deleteu'' refers to a user +%who has only ``delete'' access. ``amu'' refers to a user with ``add'' and +%''modify'' access. ``new_princ'' refers to a principal entry structure +%filled in as follows: +% +% krb5_parse_name("newuser", \&new_princ.principal); +% krb5_timeofday(\&new_princ.princ_expire_time); +% new_princ.princ_expire_time += 130; +% krb5_timeofday(\&new_princ.last_pwd_change); +% new_princ.last_pwd_change += 140; +% krb5_timeofday(\&new_princ.pw_expiration); +% new_princ.pw_expiration += 150; +% new_princ.max_life = 160; +% krb5_parse_name("usera", \&new_princ.mod_name); +% krb5_timeofday(\&new_princ.mod_date); +% new_princ.mod_date += 170; +% new_princ.attributes = 0xabcdabcd; +% new_princ.kvno = 180; +% new_princ.mkvno = 190; +% new_princ.policy = null; +% new_princ.aux_attributes = 0xdeadbeef; +% +%The offsets of 130 through 190 above are used to ensure that the +%fields are all known to be different from each other, so that +%accidentally switched fields can be detected. Some of the fields in +%this structure may be changed by the tests, but they should clean up +%after themselves. + +%\numtest{1}{ +%\Reason{Fails if database not initialized.} +%\Status{Implemented} +%} + +\numtest{2}{ +\Reason{Fails on null princ argument.} +\Status{Implemented} +} + +\numtest{3}{ +\Reason{Fails on null password argument.} +\Status{Implemented} +} + +\numtest{4}{ +\Reason{Fails on empty-string password argument.} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{Fails when mask contains undefined bit.} +\Status{Implemented} +} + +\numtest{6}{ +\Reason{Fails when mask contains LAST_PWD_CHANGE bit.} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{Fails when mask contains MOD_TIME bit.} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{Fails when mask contains MOD_NAME bit.} +\Status{Implemented} +} + +\numtest{9}{ +\Reason{Fails when mask contains MKVNO bit.} +\Status{Implemented} +} + +\numtest{10}{ +\Reason{Fails when mask contains AUX_ATTRIBUTES bit.} +\Status{Implemented} +} + +\numtest{11}{ +\Reason{Fails when mask contains POLICY_CLR bit.} +\Status{Implemented} +} + +\numtest{12}{ +\Reason{Fails for caller with no access bits.} +\Status{Implemented} +} + +\numtest{13}{ +\Reason{Fails when caller has ``get'' access and not ``add''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{14}{ +\Reason{Fails when caller has ``modify'' access and not ``add''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{15}{ +\Reason{Fails when caller has ``delete'' access and not ``add''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{16}{ +\Reason{Fails when caller connected with CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{17}{ +\Reason{Fails on attempt to create existing principal.} +\Status{Implemented} +} + +\numtest{18}{ +\Reason{Fails when password is too short.} +\Status{Implemented} +} + +\numtest{19}{ +\Reason{Fails when password has too few classes.} +\Status{Implemented} +} + +\numtest{20}{ +\Reason{Fails when password is in dictionary.} +\Status{Implemented} +} + +\numtest{21}{ +\Reason{Nonexistent policy is rejected.} +\Status{Implemented} +} + +\numtest{22}{ +\Reason{Fails on invalid principal name.} +\Status{Implemented} +} + +\numtest{23}{ +\Reason{Valid invocation.} +\Status{Implemented} +} + +\numtest{24}{ +\Reason{Succeeds when caller has ``add'' access and another one.} +\Status{Implemented} +} + +%\numtest{25}{ +%\Reason{Fails when password is too short, when override_qual is true.} +%} + +%\numtest{26}{ +%\Reason{Fails when password has too few classes, when +% override_qual is true.} +%} + +%\numtest{27}{ +%\Reason{Fails when password is in dictionary, when override_qual is +% true.} +%} + +\numtest{28}{ +\Reason{Succeeds when assigning policy.} +\Status{Implemented} +} + +\numtest{29}{ +\Priority{High} +\Reason{Allows 0 (never) for princ_expire_time.} +\Status{Implemented} +} + +\numtest{30}{ +\Reason{Allows 0 (never) for pw_expiration when there's no policy.} +\Status{Implemented} +} + +\numtest{31}{ +\Reason{Allows 0 (never) for pw_expiration when there's a policy with + 0 for pw_max_life.} +\Status{Implemented} +} + +\numtest{32}{ +\Reason{Accepts 0 (never) for pw_expiration when there's a policy with + non-zero pw_max_life, and sets pw_expiration to zero.} +\Status{Implemented} +} + +\numtest{33}{ +\Reason{Accepts and sets non-zero pw_expiration when no policy.} +\Status{Implemented} +} + +\numtest{34}{ +\Reason{Accepts and sets non-zero pw_expiration when there's a policy + with zero pw_max_life.} +\Status{Implemented} +} + +\numtest{35}{ +\Reason{Accepts and sets non-zero pw_expiration when there's a policy + with pw_max_life later than the specified pw_expiration.} +\Status{Implemented} +} + +\numtest{36}{ +\Reason{Accepts and sets non-zero pw_expiration greater than now_pw_max_life.} +\Status{Implemented} +} + +\numtest{37}{ +\Priority{High} +\Reason{Sets pw_expiration to 0 (never) if there's no policy and no + specified pw_expiration.} +\Status{Implemented} +} + +\numtest{38}{ +\Priority{High} +\Reason{Sets pw_expiration to 0 (never) if it isn't specified and the + policy has a 0 (never) pw_max_life.} +\Status{Implemented} +} + +\numtest{39}{ +\Priority{High} +\Reason{Sets pw_expiration to now + pw_max_life if it isn't specified + and the policy has a non-zero pw_max_life.} +\Status{Implemented} +} + +\numtest{40}{ +\Priority{High} +\Reason{Allows 0 (forever) for max_life.} +\Status{Implemented} +} + +\numtest{41}{ +\Priority{High} +\Reason{Doesn't modify or free mod_name on success.} +} + +\numtest{42}{ +\Priority{High} +\Reason{Doesn't modify or free mod_name on failure.} +} + +\numtest{43}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{44}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + + +\section{ovsec_kadm_delete_principal} + +%\numtest{1}{ +%\Reason{Fails if database not initialized.} +%\Status{Implemented} +%} + +\numtest{2}{ +\Reason{Fails on null principal.} +\Status{Implemented} +} + +% Empty string principal is legal. +%\numtest{3}{ +%\Reason{Fails on empty-string principal.} +%} + +% There is not invalid principal names +%\numtest{4}{ +%\Reason{Fails on invalid principal name.} +%} + +\numtest{5}{ +\Priority{High} +\Reason{Fails on nonexistent principal.} +\Status{Implemented} +} + +\numtest{6}{ +\Priority{High} +\Reason{Fails when caller connected with CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{7}{ +\Priority{High} +\Reason{Fails if caller has ``add'' access and not ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{8}{ +\Priority{High} +\Reason{Fails if caller has ``modify'' access and not ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{9}{ +\Priority{High} +\Reason{Fails if caller has ``get'' access and not ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{10}{ +\Priority{High} +\Reason{Fails if caller has no access bits.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{11}{ +\Priority{High} +\Reason{Valid invocation.} +\Status{Implemented} +} + +\numtest{12}{ +\Priority{High} +\Reason{Valid invocation (on principal with policy).} +\Status{Implemented} +} + +\numtest{13}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{14}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + + +\section{ovsec_kadm_modify_principal} + +%\numtest{1}{ +%\Reason{Fails if database not initialized.} +%\Status{Implemented} +%} + +\numtest{2}{ +\Priority{High} +\Reason{Fails if user connected with CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{3}{ +\Reason{Fails on mask with undefined bit set.} +\Status{Implemented} +} + +\numtest{4}{ +\Reason{Fails on mask with PRINCIPAL set.} +\Status{Implemented} +} + +\numtest{5}{ +\Priority{High} +\Reason{Fails on mask with LAST_PWD_CHANGE set.} +\Status{Implemented} +} + +\numtest{6}{ +\Reason{Fails on mask with MOD_TIME set.} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{Fails on mask with MOD_NAME set.} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{Fails on mask with MKVNO set.} +\Status{Implemented} +} + +\numtest{9}{ +\Priority{High} +\Reason{Fails on mask with AUX_ATTRIBUTES set.} +\Status{Implemented} +} + +\numtest{10}{ +\Reason{Fails on nonexistent principal.} +\Status{Implemented} +} + +\numtest{11}{ +\Priority{High} +\Reason{Fails for user with no access bits.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{12}{ +\Priority{High} +\Reason{Fails for user with ``get'' access.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{13}{ +\Priority{High} +\Reason{Fails for user with ``add'' access.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{14}{ +\Priority{High} +\Reason{Fails for user with ``delete'' access.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{15}{ +\Priority{High} +\Reason{Succeeds for user with ``modify'' access.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{16}{ +\Reason{Succeeds for user with ``modify'' and another access.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{17}{ +\Priority{High} +\Reason{Fails when nonexistent policy is specified.} +\Status{Implemented} +} + +\numtest{18}{ +\Priority{High} +\Reason{Succeeds when existent policy is specified.} +\Status{Implemented} +} + +\numtest{19}{ +\Reason{Updates policy count when setting policy from none.} +\Status{Implemented} +} + +\numtest{20}{ +\Reason{Updates policy count when clearing policy from set.} +\Status{Implemented} +} + +\numtest{21}{ +\Reason{Updates policy count when setting policy from other policy.} +\Status{Implemented} +} + +\numtest{21.5}{ +\Reason{Policy reference count remains unchanged when policy is + changed to itself.} +\Status{Implemented.} +} + +\numtest{22}{ +\Reason{Allows 0 (never) for pw_expiration when there's no policy.} +\Status{Implemented} +} + +\numtest{23}{ +\Reason{Allows 0 (never) for pw_expiration when there's a policy with + 0 for pw_max_life.} +\Status{Implemented} +} + +\numtest{24}{ +\Reason{Accepts 0 (never) for pw_expiration when there's a policy with + non-zero pw_max_life, but actually sets pw_expiration to + last_pwd_change + pw_max_life.} +\Status{Implemented} +} + +\numtest{25}{ +\Reason{Accepts and sets non-zero pw_expiration when no policy.} +\Status{Implemented} +} + +\numtest{26}{ +\Reason{Accepts and sets non-zero pw_expiration when there's a policy + with zero pw_max_life.} +\Status{Implemented} +} + +\numtest{27}{ +\Reason{Accepts and sets non-zero pw_expiration when there's a policy + with pw_max_life later than the specified pw_expiration.} +\Status{Implemented} +} + +\numtest{28}{ +\Reason{Accepts non-zero pw_expiration and limits it to last_pwd_change + + pw_max_life when it's later than last_pwd_change + non-zero + pw_max_life in policy.} +\Status{Implemented} +} + +\numtest{29}{ +\Priority{High} +\Reason{Sets pw_expiration to 0 (never) when a policy is cleared and +no pw_expiration is specified.} +\Status{Implemented} +} + +\numtest{30}{ +\Priority{High} +\Reason{Sets pw_expiration to 0 (never) if it isn't specified and the + new policy has a 0 (never) pw_max_life.} +\Status{Implemented} +} + +\numtest{31}{ +\Priority{High} +\Reason{Sets pw_expiration to now + pw_max_life if it isn't specified + and the new policy has a non-zero pw_max_life.} +\Status{Implemented} +} + +\numtest{32}{ +\Priority{High} +\Reason{Accepts princ_expire_time change.} +\Status{Implemented} +} + + + +\numtest{33}{ +\Priority{High} +\Reason{Accepts attributes change.} +\Status{Implemented} +} + +\numtest{33.25}{ +\Priority{High} +\Reason{Accepts attributes change (KRB5_KDB_REQUIRES_PW_CHANGE).} +\Status{Implemented} +} + +\numtest{33.5}{ +\Priority{High} +\Reason{Accepts attributes change (KRB5_DISALLOW_TGT_BASE).} +\Status{Implemented} +} + +\numtest{33.75}{ +\Priority{High} +\Reason{Accepts attributes change (KRB5_PW_CHANGE_SERVICE).} +\Status{Implemented} +} + +\numtest{34}{ +\Priority{High} +\Reason{Accepts max_life change.} +\Status{Implemented} +} + +\numtest{35}{ +\Priority{High} +\Reason{Accepts kvno change.} +\Status{Implemented} +} + +\numtest{36}{ +\Reason{Behaves correctly when policy is set to the same as it was + before.} +\Status{Implemented} +} + +\numtest{37}{ +\Reason{Behaves properly when POLICY_CLR is specified and there was no + policy before.} +\Status{Implemented} +} + +\numtest{38}{ +\Priority{High} +\Reason{Accepts 0 (never) for princ_expire_time.} +\Status{Implemented} +} + +\numtest{39}{ +\Priority{High} +\Reason{Accepts 0 for max_life.} +\Status{Implemented} +} + +\numtest{40}{ +\Reason{Rejects null principal argument.} +\Status{Implemented} +} + +\numtest{41}{ +\Priority{High} +\Reason{Doesn't modify or free mod_name on success.} +} + +\numtest{42}{ +\Priority{High} +\Reason{Doesn't modify or free mod_name on failure.} +} + +\numtest{43}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{44}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + +\numtest{100}{ +\Version{KADM5_API_VERSION_2} +\Priority{bug-fix} +\Reason{Accepts max_rlife change.} +\Status{Implemented} +} + +\numtest{101}{ +\Version{KADM5_API_VERSION_2} +\Reason{Rejects last_success change.} +\Status{Implemented} +} + +\numtest{102}{ +\Version{KADM5_API_VERSION_2} +\Reason{Rejects last_failed change.} +\Status{Implemented} +} + +\numtest{103}{ +\Version{KADM5_API_VERSION_2} +\Reason{Rejects fail_auth_count change.} +\Status{Implemented} +} + +\numtest{103.5}{ +\Version{KADM5_API_VERSION_2} +\Reason{Rejects key_data change.} +\Status{Implemented} +} + +\numtest{104}{ +\Version{KADM5_API_VERSION_2} +\Reason{Accepts tl_data change when all types are greater than 256.} +\Status{Implemented} +} + +\numtest{105}{ +\Version{KADM5_API_VERSION_2} +\Reason{Returns KADM5_BAD_TL_TYPE when given tl_data with a type less +than 256.} +\Status{Implemented} +} + +\section{ovsec_kadm_rename_principal} + +%\numtest{1}{ +%\Reason{Fails if database not initialized.} +%\Status{Implemented} +%} + +\numtest{2}{ +\Priority{High} +\Reason{Fails if user connected with CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{3}{ +\Priority{High} +\Reason{Fails for user with no access bits.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{4}{ +\Reason{Fails for user with ``modify'' access and not ``add'' or +``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{Fails for user with ``get'' access and not ``add'' or +``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{6}{ +\Reason{Fails for user with ``modify'' and ``add'' but not ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{Fails for user with ``modify'' and ``delete'' but not ``add''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{Fails for user with ``get'' and ``add'' but not ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{9}{ +\Reason{Fails for user with ``get'' and ``delete'' but not ``add.''} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{10}{ +\Reason{Fails for user with ``modify'', ``get'' and ``add'', but not + ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{11}{ +\Reason{Fails for user with ``modify'', ``get'' and ``delete'', but + not ``add''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{12}{ +\Priority{High} +\Reason{Fails for user with ``add'' but not ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{13}{ +\Priority{High} +\Reason{Fails for user with ``delete'' but not ``add''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{14}{ +\Priority{High} +\Reason{Succeeds for user with ``add'' and ``delete'', when that user +has non-name-based salt.} +\Status{Implemented} +} + +\numtest{15}{ +\Priority{High} +\Reason{Fails if target principal name exists.} +\Status{Implemented} +} + +\numtest{16}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{17}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + +\numtest{18}{ +\Priority{bug fix} +\Reason{Returns NO_RENAME_SALT when asked to rename a principal whose +salt depends on the principal name.} +\Status{Implemented} +} + +\section{ovsec_kadm_chpass_principal} +\label{ovseckadmchpassprincipal} + +\subsection{Quality/history enforcement tests} + +This section lists a series of tests which will be run a number of +times, with various parameter settings (e.g., which access bits user +has, whether user connected with ADMIN_SERVICE or CHANGEPW_SERVICE, +etc.). The table following the +list of tests gives the various parameter settings under which the +tests should be run, as well which should succeed and which should +fail for each choice of parameter settings. + +\subsubsection{List of tests} + +The test number of each of these tests is an offset from the base +given in the table below. + +\numtest{1}{ +\Priority{High} +\Reason{With history setting of 1, change password to itself.} +} + +\numtest{2}{ +\Reason{With history setting of 2 but no password changes since + principal creation, change password to itself.} +} + +\numtest{3}{ +\Reason{With history setting of 2 and one password change since + principal creation, change password to itself + and directly previous password.} +} + +\numtest{4}{ +\Priority{High} +\Reason{With a history setting of 3 and no password changes, + change password to itself.} +} + +\numtest{5}{ +\Priority{High} +\Reason{With a history setting of 3 and 1 password change, + change password to itself or previous password.} +} + +\numtest{6}{ +\Priority{High} +\Reason{With a history setting of 3 and 2 password changes, + change password to itself and the two previous passwords.} +} + +\numtest{7}{ +\Priority{High} +\Reason{Change to previously unused password when now - + last_pwd_change $<$ pw_min_life.} +} + +\numtest{8}{ +\Priority{High} +\Reason{Change to previously unused password that doesn't contain enough + character classes.} +} + +\numtest{9}{ +\Priority{High} +\Reason{Change to previously unused password that's too short.} +} + +\numtest{10}{ +\Priority{High} +\Reason{Change to previously unused password that's in the dictionary.} +} + +\subsubsection{List of parameter settings} + +In the table below, ``7 passes'' means that test 7 above passes and +the rest of the tests fail. + +\begin{tabular}{llllll} +Base & Modify access? & Own password? & Service & Pass/Fail \\ \hline +0 & No & Yes & ADMIN & all fail \\ +20 & No & Yes & CHANGEPW & all fail \\ +40 & No & No & ADMIN & all fail \\ +60 & No & No & CHANGEPW & all fail \\ +80 & Yes & Yes & ADMIN & 7 passes \\ +100 & Yes & Yes & CHANGEPW & all fail \\ +120 & Yes & No & ADMIN & 7 passes \\ +140 & Yes & No & CHANGEPW & all fail \\ +\end{tabular} + +\subsection{Other quality/history tests} + +\numtest{161}{ +\Priority{High} +\Reason{With history of 1, can change password to anything other than + itself that doesn't conflict with other quality + rules.} +} + +\numtest{162}{ +\Reason{With history of 2 and 2 password changes, can change password + to original password.} +} + +\numtest{163}{ +\Priority{High} +\Reason{With history of 3 and 3 password changes, can change password + to original password.} +} + +\numtest{164}{ +\Priority{High} +\Reason{Can change password when now - last_pwd_change $>$ pw_min_life.} +} + +\numtest{165}{ +\Priority{High} +\Reason{Can change password when it contains exactly the number of + classes required by the policy.} +} + +\numtest{166}{ +\Priority{High} +\Reason{Can change password when it is exactly the length required by + the policy.} +} + +\numtest{167}{ +\Priority{High} +\Reason{Can change password to a word that isn't in the dictionary.} +} + + +\subsection{Other tests} + +%\numtest{168}{ +%\Reason{Fails if database not initialized.} +%} + +\numtest{169}{ +\Reason{Fails for non-existent principal.} +} + +\numtest{170}{ +\Reason{Fails for null password.} +} + +\numtest{171}{ +\Priority{High} +\Reason{Fails for empty-string password.} +} + +\numtest{172}{ +\Priority{High} +\Reason{Pw_expiration is set to now + max_pw_life if policy exists and + has non-zero max_pw_life.} +} + +\numtest{173}{ +\Priority{High} +\Reason{Pw_expiration is set to 0 if policy exists and has zero + max_pw_life.} +} + +\numtest{174}{ +\Priority{High} +\Reason{Pw_expiration is set to 0 if no policy.} +} + +\numtest{175}{ +\Priority{High} +\Reason{KRB5_KDC_REQUIRES_PWCHANGE bit is cleared when password is + successfully changed.} +} + +\numtest{176}{ +\Priority{High} +\Reason{Fails for user with no access bits, on other's password.} +} + +\numtest{177}{ +\Priority{High} +\Reason{Fails for user with ``get'' but not ``modify'' access, on + other's password.} +} + +\numtest{178}{ +\Reason{Fails for user with ``delete'' but not ``modify'' access, on + other's password.} +} + +\numtest{179}{ +\Reason{Fails for user with ``add'' but not ``modify'' access, on + other's password.} +} + +\numtest{180}{ +\Reason{Succeeds for user with ``get'' and ``modify'' access, on + other's password.} +\Status{Implemented} +} + +\numtest{180.5}{ +\Priority{High} +\Reason{Succeeds for user with ``modify'' but not ``get'' access, on + other's password.} +\Conditions{RPC} +\Status{Implemented} +} +\numtest{180.625}{ +\Priority{High} +\Reason{Fails for user with modify when connecting with CHANGEPW_SERVICE on + others password} +\Conditions{RPC} +\Status{Implemented} +} +\numtest{180.75}{ +\Priority{High} +\Reason{Fails for user with modify when connecting with CHANGEPW_SERVICE + on other's password which has expired} +\Conditions{RPC} +\Status{Implemented} +} + +%\numtest{181}{ +%\Reason{Password that would succeed if override_qual were false fails +% if override_qual is true.} +%\Expected{Returns CANNOT_OVERRIDE.} +%} + +\numtest{182}{ +\Priority{High} +\Reason{Can not change key of ovsec_adm/history principal.} +\Status{Implemented} +} + +\numtest{183}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{184}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + +\numtest{200}{ +\Version{KADM5_API_VERSION_2} +\Reason{Creates a key for the principal for each unique encryption +type/salt type in use.} +\Status{Implemented} +} + +\section{ovsec_kadm_chpass_principal_util} + +Rerun all the tests listed for ovsec_kadm_chpass_principal above in +Section \ref{ovseckadmchpassprincipal}. Verify that they succeed +and fail in the same circumstances. Also verify that in each failure +case, the error message returned in msg_ret is as specified in the +functional specification. + +Also, run the following additional tests. + +\numtest{1}{ +\Reason{Null msg_ret is rejected.} +} + +\numtest{2}{ +\Priority{High} +\Reason{New password is put into pw_ret, when it's prompted for.} +} + +\numtest{3}{ +\Priority{High} +Reason{New password is put into pw_ret, when it's supplied by the + caller.} +} + +\numtest{4}{ +\Priority{High} +\Reason{Successful invocation when pw_ret is null.} +} + + + +\section{ovsec_kadm_randkey_principal} + +\subsection{TOOSOON enforcement tests} + +This test should be run a number of times, as indicated in the table +following it. The table also indicates the expected result of each +run of the test. + +\test{ +\Reason{Change key when now - last_pwd_change $<$ pw_min_life.} +} + +\subsubsection{List of parameter settings} + +\begin{tabular}{llllll} +Number & Modify Access? & Own Key? & Service & Pass/Fail & Implemented? \\ \hline +1 & No & Yes & ADMIN & fail & Yes \\ +3 & No & Yes & CHANGEPW & fail & Yes \\ +5 & No & No & ADMIN & fail \\ +7 & No & No & CHANGEPW & fail \\ +9 & Yes & Yes & ADMIN & pass \\ +11 & Yes & Yes & CHANGEPW & fail \\ +13 & Yes & No & ADMIN & pass & Yes \\ +15 & Yes & No & CHANGEPW & fail & Yes \\ +\end{tabular} + +\subsection{Other tests} + +\numtest{17}{ +\Reason{Fails if database not initialized.} +} + +\numtest{18}{ +\Reason{Fails for non-existent principal.} +} + +\numtest{19}{ +\Reason{Fails for null keyblock pointer.} +} + +\numtest{20}{ +\Priority{High} +\Reason{Pw_expiration is set to now + max_pw_life if policy exists and + has non-zero max_pw_life.} +} + +\numtest{21}{ +\Priority{High} +\Reason{Pw_expiration is set to 0 if policy exists and has zero + max_pw_life.} +} + +\numtest{22}{ +\Priority{High} +\Reason{Pw_expiration is set to 0 if no policy.} +} + +\numtest{23}{ +\Priority{High} +\Reason{KRB5_KDC_REQUIRES_PWCHANGE bit is cleared when key is + successfully changed.} +} + +\numtest{24}{ +\Priority{High} +\Reason{Fails for user with no access bits, on other's password.} +} + +\numtest{25}{ +\Priority{High} +\Reason{Fails for user with ``get'' but not ``modify'' access, on + other's password.} +\Vtwonote{Change-password instead of modify access.} +} + +\numtest{26}{ +\Reason{Fails for user with ``delete'' but not ``modify'' access, on + other's password.} +\Vtwonote{Change-password instead of modify access.} +} + +\numtest{27}{ +\Reason{Fails for user with ``add'' but not ``modify'' access, on + other's password.} +\Vtwonote{Change-password instead of modify access.} +} + +\numtest{28}{ +\Reason{Succeeds for user with ``get'' and ``modify'' access, on + other's password.} +\Status{Implemented} +\Vtwonote{Change-password instead of modify access.} +} + +\numtest{28.25}{ +\Priority{High} +\Reason{Fails for user with get and modify access on others password + When conneceted with CHANGEPW_SERVICE} +\Status{Implemented} +\Vtwonote{Change-password instead of modify access.} +} + +\numtest{28.5}{ +\Priority{High} +\Reason{Succeeds for user with ``modify'' but not ``get'' access, on + other's password.} +\Status{Implemented} +\Vtwonote{Change-password instead of modify access.} +} + +\numtest{29}{ +\Reason{The new key that's assigned is truly random. XXX not sure how + to test this.} +} + +\numtest{30}{ +\Reason{Succeeds for own key, no other access bits when connecting with CHANGEPW service} +\Status{Implemented} +} +\numtest{31}{ +\Reason{Succeeds for own key, no other access bits when connecting with ADMIM service} +\Status{Implemented} +} + +\numtest{32}{ +\Reason{Cannot change ovsec_adm/history key} +\Status{Implemented} +} + +\numtest{33}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{34}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + +\numtest{100}{ +\Version{KADM5_API_VERSION_2} +\Reason{Returns a key for each unique encryption type specified in the +keysalts.} +} + +\section{ovsec_kadm_get_principal} + +\numtest{1}{ +\Reason{Fails for null ent.} +\Status{Implemented} +} + +\numtest{2}{ +\Reason{Fails for non-existent principal.} +\Status{Implemented} +} + +\numtest{3}{ +\Priority{High} +\Reason{Fails for user with no access bits, retrieving other principal.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{4}{ +\Priority{High} +\Reason{Fails for user with ``add'' but not ``get'', getting principal + other than his own, using ADMIN_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{Fails for user with ``modify'' but not ``get'', getting + principal other than his own, using ADMIN_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{6}{ +\Reason{Fails for user with ``delete'' but not ``get'', getting + principal other than his own, using ADMIN_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{Fails for user with ``delete'' but not ``get'', getting + principal other than his own, using CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{8}{ +\Priority{High} +\Reason{Fails for user with ``get'', getting principal other than his + own, using CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{9}{ +\Priority{High} +\Reason{Succeeds for user without ``get'', retrieving self, using + ADMIN_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{10}{ +\Reason{Succeeds for user without ``get'', retrieving self, using + CHANGEPW_SERVICE.} +\Status{Implemented} +} + +\numtest{11}{ +\Reason{Succeeds for user with ``get'', retrieving self, using + ADMIN_SERVICE.} +\Status{Implemented} +} + +\numtest{12}{ +\Reason{Succeeds for user with ``get'', retrieving self, using + CHANGEPW_SERVICE.} +\Status{Implemented} +} + +\numtest{13}{ +\Priority{High} +\Reason{Succeeds for user with ``get'', retrieving other user, using + ADMIN_SERVICE.} +\Status{Implemented} +} + +\numtest{14}{ +\Reason{Succeeds for user with ``get'' and ``modify'', retrieving + other principal, using ADMIN_SERVICE.} +\Status{Implemented} +} + +\numtest{15}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{16}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + +\numtest{100}{ +\Version{KADM5_API_VERSION_2} +\Reason{If KADM5_PRINCIPAL_NORMAL_MASK is specified, the key_data and +tl_data fields are NULL/zero.} +\Status{Implemented} +} + +\numtest{101}{ +\Version{KADM5_API_VERSION_2} +\Reason{If KADM5_KEY_DATA is specified, the key_data fields contain +data but the contents are all NULL.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{102}{ +\Version{KADM5_API_VERSION_2} +\Reason{If KADM5_KEY_DATA is specified, the key_data fields contain +data and the contents are all non-NULL.} +\Conditions{local} +\Status{Implemented} +} + +\numtest{103}{ +\Version{KADM5_API_VERSION_2} +\Reason{If KADM5_TL_DATA is specified, the tl_data field contains the +correct tl_data and no entries whose type is less than 256.} +\Status{Implemented} +} + + +\section{ovsec_kadm_create_policy} + +\numtest{1}{ +\Reason{Fails for mask with undefined bit set.} +\Status{Implemented - untested} +} + +\numtest{2}{ +\Priority{High} +\Reason{Fails if caller connected with CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{3}{ +\Reason{Fails for mask without POLICY bit set.} +\Status{Implemented - untested} +} + +\numtest{4}{ +\Reason{Fails for mask with REF_COUNT bit set.} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{Fails for invalid policy name.} +\Status{Implemented - untested} +} + +\numtest{6}{ +\Priority{High} +\Reason{Fails for existing policy name.} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{Fails for null policy name.} +\Status{Implemented - untested} +} + +\numtest{8}{ +\Priority{High} +\Reason{Fails for empty-string policy name.} +\Status{Implemented} +} + +\numtest{9}{ +\Priority{High} +\Reason{Accepts 0 for pw_min_life.} +\Status{Implemented} +} + +\numtest{10}{ +\Priority{High} +\Reason{Accepts non-zero for pw_min_life.} +\Status{Implemented} +} + +\numtest{11}{ +\Priority{High} +\Reason{Accepts 0 for pw_max_life.} +\Status{Implemented} +} + +\numtest{12}{ +\Priority{High} +\Reason{Accepts non-zero for pw_max_life.} +\Status{Implemented} +} + +\numtest{13}{ +\Priority{High} +\Reason{Rejects 0 for pw_min_length.} +\Status{Implemented} +} + +\numtest{14}{ +\Priority{High} +\Reason{Accepts non-zero for pw_min_length.} +\Status{Implemented} +} + +\numtest{15}{ +\Priority{High} +\Reason{Rejects 0 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{16}{ +\Priority{High} +\Reason{Accepts 1 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{17}{ +\Priority{High} +\Reason{Accepts 4 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{18}{ +\Priority{High} +\Reason{Rejects 5 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{19}{ +\Priority{High} +\Reason{Rejects 0 for pw_history_num.} +\Status{Implemented} +} + +\numtest{20}{ +\Priority{High} +\Reason{Accepts 1 for pw_history_num.} +\Status{Implemented} +} + +\numtest{21}{ +\Priority{High} +\Reason{Accepts 10 for pw_history_num.} +\Status{Implemented} +} + +\numtest{21.5}{ +\Reason{Rejects 11 for pw_history_num.} +\Status{Implemented - untested} +} + +\numtest{22}{ +\Priority{High} +\Reason{Fails for user with no access bits.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{23}{ +\Priority{High} +\Reason{Fails for user with ``get'' but not ``add''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{24}{ +\Reason{Fails for user with ``modify'' but not ``add.''} +\Conditions{RPC} +\Status{Implemented - untested} +} + +\numtest{25}{ +\Reason{Fails for user with ``delete'' but not ``add.''} +\Conditions{RPC} +\Status{Implemented - untested} +} + +\numtest{26}{ +\Priority{High} +\Reason{Succeeds for user with ``add.''} +\Status{Implemented} +} + +\numtest{27}{ +\Reason{Succeeds for user with ``get'' and ``add.''} +\Status{Implemented - untested} +} + +\numtest{28}{ +\Reason{Rejects null policy argument.} +\Status{Implemented - untested} +} + +\numtest{29}{ +\Reason{Rejects pw_min_life greater than pw_max_life.} +} + +\numtest{30}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{31}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + + +\section{ovsec_kadm_delete_policy} + +\numtest{1}{ +\Reason{Fails for null policy name.} +} + +\numtest{2}{ +\Priority{High} +\Reason{Fails for empty-string policy name.} +\Status{Implemented} +} + +\numtest{3}{ +\Reason{Fails for non-existent policy name.} +} + +\numtest{4}{ +\Reason{Fails for bad policy name.} +} + +\numtest{5}{ +\Priority{High} +\Reason{Fails if caller connected with CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{6}{ +\Priority{High} +\Reason{Fails for user with no access bits.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{7}{ +\Priority{High} +\Reason{Fails for user with ``add'' but not ``delete''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{Fails for user with ``modify'' but not ``delete''.} +\Conditions{RPC} +} + +\numtest{9}{ +\Reason{Fails for user with ``get'' but not ``delete.''} +\Conditions{RPC} +} + +\numtest{10}{ +\Priority{High} +\Reason{Succeeds for user with only ``delete''.} +\Status{Implemented} +} + +\numtest{11}{ +\Reason{Succeeds for user with ``delete'' and ``add''.} +} + +\numtest{12}{ +\Priority{High} +\Reason{Fails for policy with non-zero reference count.} +\Status{Implemented} +} + +\numtest{13}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{14}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + + +\section{ovsec_kadm_modify_policy} + +\numtest{1}{ +\Reason{Fails for mask with undefined bit set.} +\Conditions{RPC} +} + +\numtest{2}{ +\Priority{High} +\Reason{Fails if caller connected with CHANGEPW_SERVICE.} +\Status{Implemented} +} + +\numtest{3}{ +\Reason{Fails for mask with POLICY bit set.} +} + +\numtest{4}{ +\Reason{Fails for mask with REF_COUNT bit set.} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{Fails for invalid policy name.} +} + +\numtest{6}{ +\Reason{Fails for non-existent policy name.} +} + +\numtest{7}{ +\Reason{Fails for null policy name.} +} + +\numtest{8}{ +\Priority{High} +\Reason{Fails for empty-string policy name.} +\Status{Implemented} +} + +\numtest{9}{ +\Priority{High} +\Reason{Accepts 0 for pw_min_life.} +\Status{Implemented} +} + +\numtest{10}{ +\Priority{High} +\Reason{Accepts non-zero for pw_min_life.} +\Status{Implemented} +} + +\numtest{11}{ +\Priority{High} +\Reason{Accepts 0 for pw_max_life.} +\Status{Implemented} +} + +\numtest{12}{ +\Priority{High} +\Reason{Accepts non-zero for pw_max_life.} +\Status{Implemented} +} + +\numtest{13}{ +\Priority{High} +\Reason{Accepts 0 for pw_min_length.} +\Status{Implemented} +} + +\numtest{14}{ +\Priority{High} +\Reason{Accepts non-zero for pw_min_length.} +\Status{Implemented} +} + +\numtest{15}{ +\Priority{High} +\Reason{Rejects 0 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{16}{ +\Priority{High} +\Reason{Accepts 1 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{17}{ +\Priority{High} +\Reason{Accepts 4 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{18}{ +\Priority{High} +\Reason{Rejects 5 for pw_min_classes.} +\Status{Implemented} +} + +\numtest{19}{ +\Priority{High} +\Reason{Rejects 0 for pw_history_num.} +\Status{Implemented} +} + +\numtest{20}{ +\Priority{High} +\Reason{Accepts 1 for pw_history_num.} +\Status{Implemented} +} + +\numtest{21}{ +\Priority{High} +\Reason{Accepts 10 for pw_history_num.} +\Status{Implemented} +} + +\numtest{22}{ +\Priority{High} +\Reason{Fails for user with no access bits.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{23}{ +\Priority{High} +\Reason{Fails for user with ``get'' but not ``modify''.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{24}{ +\Reason{Fails for user with ``add'' but not ``modify.''} +\Conditions{RPC} +} + +\numtest{25}{ +\Reason{Fails for user with ``delete'' but not ``modify.''} +\Conditions{RPC} +} + +\numtest{26}{ +\Priority{High} +\Reason{Succeeds for user with ``modify.''} +\Status{Implemented} +} + +\numtest{27}{ +\Reason{Succeeds for user with ``get'' and ``modify.''} +} + +\numtest{28}{ +\Reason{Rejects null policy argument.} +} + +\numtest{29}{ +\Reason{Rejects change which makes pw_min_life greater than + pw_max_life.} +} + +\numtest{30}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{31}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + +\section{ovsec_kadm_get_policy} + +\numtest{1}{ +\Reason{Fails for null policy.} +} + +\numtest{2}{ +\Reason{Fails for invalid policy name.} +} + +\numtest{3}{ +\Priority{High} +\Reason{Fails for empty-string policy name.} +\Status{Implemented} +} + +\numtest{4}{ +\Reason{Fails for non-existent policy name.} +} + +\numtest{5}{ +\Reason{Fails for null ent.} +} + +\numtest{6}{ +\Priority{High} +\Reason{Fails for user with no access bits trying to get other's + policy, using ADMIN_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{7}{ +\Priority{High} +\Reason{Fails for user with ``add'' but not ``get'' trying to get + other's policy, using ADMIN_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{Fails for user with ``modify'' but not ``get'' trying to get + other's policy, using ADMIN_SERVICE.} +\Conditions{RPC} +} + +\numtest{9}{ +\Reason{Fails for user with ``delete'' but not ``get'' trying to get + other's policy, using ADMIN_SERVICE.} +\Conditions{RPC} +} + +\numtest{10}{ +\Reason{Fails for user with ``delete'' but not ``get'' trying to get + other's policy, using CHANGEPW_SERVICE.} +\Conditions{RPC} +} + +\numtest{11}{ +\Priority{High} +\Reason{Succeeds for user with only ``get'', trying to get own policy, + using ADMIN_SERVICE.} +\Status{Implemented} +} + +\numtest{12}{ +\Priority{High} +\Reason{Succeeds for user with only ``get'', trying to get own policy, + using CHANGEPW_SERVICE.} +\Status{Implemented} +} + +\numtest{13}{ +\Reason{Succeeds for user with ``add'' and ``get'', trying to get own + policy, using ADMIN_SERVICE.} +} + +\numtest{14}{ +\Reason{Succeeds for user with ``add'' and ``get'', trying to get own + policy, using CHANGEPW_SERVICE.} +} + +\numtest{15}{ +\Reason{Succeeds for user without ``get'', trying to get own policy, + using ADMIN_SERVICE.} +} + +\numtest{16}{ +\Priority{High} +\Reason{Succeeds for user without ``get'', trying to get own policy, + using CHANGEPW_SERVICE.} +\Status{Implemented} +} + +\numtest{17}{ +\Priority{High} +\Reason{Succeeds for user with ``get'', trying to get other's policy, + using ADMIN_SERVICE.} +\Status{Implemented} +} + +\numtest{18}{ +\Priority{High} +\Reason{Fails for user with ``get'', trying to get other's policy, + using CHANGEPW_SERVICE.} +\Conditions{RPC} +\Status{Implemented} +} + +\numtest{19}{ +\Reason{Succeeds for user with ``modify'' and ``get'', trying to get + other's policy, using ADMIN_SERVICE.} +} + +\numtest{20}{ +\Reason{Fails for user with ``modify'' and ``get'', trying to get + other's policy, using CHANGEPW_SERVICE.} +} + +\numtest{21}{ +\Priority{High} +\Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} +\Status{Implemented} +} + +\numtest{22}{ +\Priority{Low} +\Reason{Connects to correct server when mutliple handles exist} +\Conditions{RPC} +} + + +\section{ovsec_kadm_free_principal_ent} + +In addition to the tests listed here, a memory-leak detector such as +TestCenter, Purify or dbmalloc should be used to verify that the +memory freed by this function is really freed. + +\numtest{1}{ +\Reason{Null princ succeeds.} +} + +\numtest{2}{ +\Reason{Non-null princ succeeds.} +} + + +\section{ovsec_kadm_free_policy_ent} + +In addition to the tests listed here, a memory-leak detector such as +TestCenter, Purify or dbmalloc should be used to verify that the +memory freed by this function is really freed. + +\numtest{1}{ +\Reason{Null policy succeeds.} +} + +\numtest{2}{ +\Reason{Non-null policy succeeds.} +} + + + +\section{ovsec_kadm_get_privs} + +\numtest{1}{ +\Reason{Fails for null pointer argument.} +} + +This test should be run with the 16 possible combinations of access +bits (since there are 4 access bits, there are $2^4 = 16$ possible +combinations of them): + +\numtest{2}{ +\Priority{High} +\Reason{Returns correct bit mask for access bits of user.} +\Conditions{RPC} +} + +This test should be run locally: + +\numtest{3}{ +\Priority{High} +\Reason{Returns 0x0f.} +\Conditions{local} +} + +\end{document} diff --git a/krb5-1-6/doc/kadm5/fullpage.sty b/krb5-1-6/doc/kadm5/fullpage.sty new file mode 100644 index 000000000..d5a2bf5b0 --- /dev/null +++ b/krb5-1-6/doc/kadm5/fullpage.sty @@ -0,0 +1,9 @@ +\marginparwidth 0pt +\oddsidemargin 0pt +\evensidemargin 0pt +\marginparsep 0pt + +\topmargin 0pt + +\textwidth 6.5in +\textheight 8.5 in diff --git a/krb5-1-6/doc/kadm5/rcsid.sty b/krb5-1-6/doc/kadm5/rcsid.sty new file mode 100644 index 000000000..3ad7826ff --- /dev/null +++ b/krb5-1-6/doc/kadm5/rcsid.sty @@ -0,0 +1,5 @@ +\def\rcs$#1: #2${\expandafter\def\csname rcs#1\endcsname{#2}} + +% example usage: +% \rcs$Version$ +% Version \rcsVersion diff --git a/krb5-1-6/doc/kadm5acl.texinfo b/krb5-1-6/doc/kadm5acl.texinfo new file mode 100644 index 000000000..468a9b93a --- /dev/null +++ b/krb5-1-6/doc/kadm5acl.texinfo @@ -0,0 +1,113 @@ +The format of the file is: + +@smallexample +Kerberos_principal permissions [target_principal] [restrictions] +@end smallexample + +The Kerberos principal (and optional target principal) can include the +``@b{*}'' wildcard, so if you want any principal with the instance +``admin'' to have full permissions on the database, you could use the +principal ``@code{*/admin@@REALM}'' where ``REALM'' is your Kerberos +realm. @code{target_principal} can also include backreferences to +@code{Kerberos_principal}, in which "@b{*@i{number}}" matches the +component @i{number} in the @code{Kerberos_principal}. + +Note: a common use of an @i{admin} instance is so you can grant +separate permissions (such as administrator access to the Kerberos +database) to a separate Kerberos principal. For example, the user +@code{@value{ADMINUSER}} might have a principal for his administrative +use, called @code{@value{ADMINUSER}/admin}. This way, +@code{@value{ADMINUSER}} would obtain @code{@value{ADMINUSER}/admin} +tickets only when he actually needs to use those permissions. + +The permissions are represented by single letters; UPPER-CASE letters +represent negative permissions. The permissions are: + +@table @b +@itemx a +allows the addition of principals or policies in the database. +@itemx A +disallows the addition of principals or policies in the database. +@itemx d +allows the deletion of principals or policies in the database. +@itemx D +disallows the deletion of principals or policies in the database. +@itemx m +allows the modification of principals or policies in the database. +@itemx M +disallows the modification of principals or policies in the database. +@itemx c +allows the changing of passwords for principals in the database. +@itemx C +disallows the changing of passwords for principals in the database. +@itemx i +allows inquiries to the database. +@itemx I +disallows inquiries to the database. +@itemx l +allows the listing of principals or policies in the database. +@itemx L +disallows the listing of principals or policies in the database. +@itemx s +allows the explicit setting of the key for a principal +@itemx S +disallows the explicit setting of the key for a principal +@itemx * +All privileges (admcil). +@itemx x +All privileges (admcil); identical to ``*''. +@end table + +The restrictions are a string of flags. Allowed restrictions are: + +@table @b +@itemx [+ -]@i{flagname} +flag is forced to indicated value. The permissible flags are the same +as the @code{+} and @code{-} flags for the @code{kadmin addprinc} and +@code{modprinc} commands. +@itemx -clearpolicy +policy is forced to clear +@itemx -policy @i{pol} +policy is forced to be @i{pol} +@itemx expire @i{time} +@itemx pwexpire @i{time} +@itemx maxlife @i{time} +@itemx maxrenewlife @i{time} +associated value will be forced to MIN(@i{time}, requested value) +@end table + +The above flags act as restrictions on any add or modify operation +which is allowed due to that ACL line. + +Here is an example of a @code{kadm5.acl} file. Note that order is +important; permissions are determined by the first matching entry. + +@smallexample +@group +*/admin@@@value{PRIMARYREALM} * +@value{ADMINUSER}@@@value{PRIMARYREALM} ADMCIL +@value{ADMINUSER}/*@@@value{PRIMARYREALM} il */root@@@value{PRIMARYREALM} +*@@@value{PRIMARYREALM} cil *1/admin@@@value{PRIMARYREALM} +*/*@@@value{PRIMARYREALM} i +*/admin@@@value{SECONDREALM} * -maxlife 9h -postdateable +@end group +@end smallexample + +@noindent In the above file, any principal in the +@value{PRIMARYREALM} realm with an @code{admin} instance has all +administrative privileges. The user @code{@value{ADMINUSER}} +has all permissions with his @code{admin} instance, +@code{@value{ADMINUSER}/admin@@@value{PRIMARYREALM}} (matches the first +line). He has no permissions at all with his @code{null} instance, +@code{@value{ADMINUSER}@@@value{PRIMARYREALM}} (matches the second line). +His root instance has @i{inquire} and @i{list} permissions with any +other principal that has the instance @code{root}. Any principal +in @value{PRIMARYREALM} can inquire, list, or change the password of +their @code{admin} instance, but not any other @code{admin} instance. +Any principal in the realm @code{@value{PRIMARYREALM}} (except for +@code{@value{ADMINUSER}@@@value{PRIMARYREALM}}, as mentioned above) has +@i{inquire} privileges. Finally, any principal with an admin instance +in @value{SECONDREALM} has all permissions, but any principal that they +create or modify will not be able to get postdateable tickets or tickets +with a life of longer than 9 hours. + diff --git a/krb5-1-6/doc/kadmin/README b/krb5-1-6/doc/kadmin/README new file mode 100644 index 000000000..72b369499 --- /dev/null +++ b/krb5-1-6/doc/kadmin/README @@ -0,0 +1,46 @@ +There are several different admin protocols in our source tree. + +a) V4 server protocol - not documented + +b) Old kadmin protocol - which was in the beta code (kadmin/v5passwdd) + +c) Newer kadm5 gssrpc based code (kadmin/server) + +d) Simple password changing protocol implemented in our kadmin server +with client in clients/kpasswd. + + + +This file will attempt to link the files in this directory with where +the code is used in the source tree. + + +- kpasswd.protocol: Describes the password changing protocol in + src/kadmin/v5passwdd. + include/adm.h has some defintions. + + Client and server provided + +- kadmin.protocol: Describes other administrative protocol options that + src/kadmin/v5passwdd supports + + No client in the source tree uses it. + +- draft-ietf-cat-kerb-chg-password-02.txt: Describes the + password changing service that + clients/kpasswd uses through krb5_change_password() + located in lib/krb5/os/changepw.c + + kadmin/server/schpw.c implements this as part of + the kadmin server. + + This is version 1 of the protocol. Version 2 is + in the IETF draft stage and is very different. + + Currently: Version 1 is supported - but we may not + be implementing the TCP handling aspects. + +- ../doc/kadm5: Describes the current protocol. + + kadmin/passwd (which is not installed) uses + the kadm5 protocol for password changing. diff --git a/krb5-1-6/doc/kadmin/draft-ietf-cat-kerb-chg-password-02.txt b/krb5-1-6/doc/kadmin/draft-ietf-cat-kerb-chg-password-02.txt new file mode 100644 index 000000000..e235bec58 --- /dev/null +++ b/krb5-1-6/doc/kadmin/draft-ietf-cat-kerb-chg-password-02.txt @@ -0,0 +1,311 @@ + + + + +Network Working Group M. Horowitz + Stonecast, Inc. +Internet-Draft August, 1998 + + Kerberos Change Password Protocol + +Status of this Memo + + This document is an Internet-Draft. Internet-Drafts are working + documents of the Internet Engineering Task Force (IETF), its areas, + and its working groups. Note that other groups may also distribute + working documents as Internet-Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as ``work in progress.'' + + To learn the current status of any Internet-Draft, please check the + ``1id-abstracts.txt'' listing contained in the Internet-Drafts Shadow + Directories on ftp.ietf.org (US East Coast), nic.nordu.net + (Europe), ftp.isi.edu (US West Coast), or munnari.oz.au (Pacific + Rim). + + Distribution of this memo is unlimited. Please send comments to the + mailing list. + +Abstract + + The Kerberos V5 protocol [RFC1510] does not describe any mechanism + for users to change their own passwords. In order to promote + interoperability between workstations, personal computers, terminal + servers, routers, and KDC's from multiple vendors, a common password + changing protocol is required. + + + +Overview + + When a user wishes to change his own password, or is required to by + local policy, a simple request of a password changing service is + necessary. This service must be implemented on at least one host for + each Kerberos realm, probably on one of the kdc's for that realm. + The service must accept requests on UDP port 464 (kpasswd), and may + accept requests on TCP port 464 as well. + + The protocol itself consists of a single request message followed by + a single reply message. For UDP transport, each message must be + fully contained in a single UDP packet. + + + + + + + + +Horowitz [Page 1] + +Internet Draft Kerberos Change Password Protocol August, 1998 + + +Request Message + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | message length | protocol version number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | AP_REQ length | AP-REQ data / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / KRB-PRIV message / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + message length (16 bits) + Contains the length of the message, including this field, in bytes + (big-endian integer) + protocol version number (16 bits) + Contains the hex constant 0x0001 (big-endian integer) + AP-REQ length (16 bits) + length (big-endian integer) of AP-REQ data, in bytes. + AP-REQ data, as described in RFC1510 (variable length) + This AP-REQ must be for the service principal + kadmin/changepw@REALM, where REALM is the REALM of the user who + wishes to change his password. The Ticket in the AP-REQ must be + derived from an AS request (thus having the INITIAL flag set), and + must include a subkey in the Authenticator. + KRB-PRIV message, as described in RFC1510 (variable length) + This KRB-PRIV message must be generated using the subkey in the + Authenticator in the AP-REQ data. The user-data component of the + message must consist of the user's new password. + + The server must verify the AP-REQ message, decrypt the new password, + perform any local policy checks (such as password quality, history, + authorization, etc.) required, then set the password to the new value + specified. + + The principal whose password is to be changed is the principal which + authenticated to the password changing service. This protocol does + not address administrators who want to change passwords of principal + besides their own. + + +Reply Message + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | message length | protocol version number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | AP_REP length | AP-REP data / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / KRB-PRIV or KRB-ERROR message / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + message length (16 bits) + + + +Horowitz [Page 2] + +Internet Draft Kerberos Change Password Protocol August, 1998 + + + Contains the length of the message, including this field, in bytes + (big-endian integer), + protocol version number (16 bits) + Contains the hex constant 0x0001 (big-endian integer) + AP-REP length (16 bits) + length of AP-REP data, in bytes. If the the length is zero, then + the last field will contain a KRB-ERROR message instead of a KRB- + PRIV message. + AP-REP data, as described in RFC1510 (variable length) + The AP-REP corresponding to the AP-REQ in the request packet. + KRB-PRIV or KRB-ERROR message, as described in RFC1510 (variable + length) + If the AP-REP length is zero, then this field contains a KRB-ERROR + message. Otherwise, it contains a KRB-PRIV message. This KRB- + PRIV message must be generated using the subkey in the + Authenticator in the AP-REQ data. + + The user-data component of the KRB-PRIV message, or e-data + component of the KRB-ERROR message, must consist of the following + data: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | result code | result string / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + result code (16 bits) + The result code must have one of the following values (big- + endian integer): + 0x0000 if the request succeeds. (This value is not permitted + in a KRB-ERROR message.) + 0x0001 if the request fails due to being malformed + 0x0002 if the request fails due to a "hard" error processing + the request (for example, there is a resource or other + problem causing the request to fail) + 0x0003 if the request fails due to an error in authentication + processing + 0x0004 if the request fails due to a "soft" error processing + the request (for example, some policy or other similar + consideration is causing the request to be rejected). + 0xFFFF if the request fails for some other reason. + Although only a few non-zero result codes are specified here, + the client should accept any non-zero result code as indicating + failure. + result string (variable length) + This field should contain information which the server thinks + might be useful to the user, such as feedback about policy + failures. The string must be encoded in UTF-8. It may be + omitted if the server does not wish to include it. If it is + present, the client should display the string to the user. + This field is analogous to the string which follows the numeric + code in SMTP, FTP, and similar protocols. + + + + +Horowitz [Page 3] + +Internet Draft Kerberos Change Password Protocol August, 1998 + + +Dropped and Modified Messages + + An attacker (or simply a lossy network) could cause either the + request or reply to be dropped, or modified by substituting a KRB- + ERROR message in the reply. + + If a request is dropped, no modification of the password/key database + will take place. If a reply is dropped, the server will (assuming a + valid request) make the password change. However, the client cannot + distinguish between these two cases. + + In this situation, the client should construct a new authenticator, + re-encrypt the request, and retransmit. If the original request was + lost, the server will treat this as a valid request, and the password + will be changed normally. If the reply was lost, then the server + should take care to notice that the request was a duplicate of the + prior request, because the "new" password is the current password, + and the password change time is within some implementation-defined + replay time window. The server should then return a success reply + (an AP-REP message with result code == 0x0000) without actually + changing the password or any other information (such as modification + timestamps). + + If a success reply was replaced with an error reply, then the + application performing the request would return an error to the user. + In this state, the user's password has been changed, but the user + believes that it has not. If the user attempts to change the + password again, this will probably fail, because the user cannot + successfully provide the old password to get an INITIAL ticket to + make the request. This situation requires administrative + intervention as if a password was lost. This situation is, + unfortunately, impossible to prevent. + + +Security Considerations + + This document deals with changing passwords for Kerberos. Because + Kerberos is used for authentication and key distribution, it is + important that this protocol use the highest level of security + services available to a particular installation. Mutual + authentication is performed, so that the server knows the request is + valid, and the client knows that the request has been received and + processed by the server. + + There are also security issues relating to dropped or modified + messages which are addressed explicitly. + + +References + + [RFC1510] Kohl, J. and Neuman, C., "The Kerberos Network + Authentication Service (V5)", RFC 1510, September 1993. + + + + + +Horowitz [Page 4] + +Internet Draft Kerberos Change Password Protocol August, 1998 + + +Author's Address + + Marc Horowitz + Stonecast, Inc. + 108 Stow Road + Harvard, MA 01451 + + Phone: +1 978 456 9103 + Email: marc@stonecast.net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Horowitz [Page 5] + diff --git a/krb5-1-6/doc/kadmin/kadmin.protocol b/krb5-1-6/doc/kadmin/kadmin.protocol new file mode 100644 index 000000000..5e48945f6 --- /dev/null +++ b/krb5-1-6/doc/kadmin/kadmin.protocol @@ -0,0 +1,382 @@ + +This document references, accompanies and extends the password changing +protocol document, "A Proposal for a Standardized Kerberos Password +Changing Protocol" by Theodore Ts'o. + +Administrative Command Extensions to the Password Changing Protocol +=================================================================== +The following commands and their accompanying definitions are an +extension to the password changing protocol which allow remote +administrative clients to perform functions analogous to those which +are performed using the local database editing utility. These +commands are encoded in the "command request" PDU described in the +password changing protocol, and the server's responses to these +commands are encoded in the "command reply" PDU. + +These commands are (optional commands are marked with an asterisk, new +or changed commands are marked with a plus sign): + ADD-PRINCIPAL + DELETE-PRINCIPAL + RENAME-PRINCIPAL + MODIFY-PRINCIPAL + OTHER-CHANGEPW + OTHER-RANDOM-CHANGEPW + INQUIRE-PRINCIPAL + EXTRACT-KEY (*+) + ADD-KEY (+) + DELETE-KEY (+) + +In order to support these additional commands, the following additional +status codes are also defined: + +Number Symbolic Name Meaning +64 P_ALREADY_EXISTS The specified principal already exists. +65 P_DOES_NOT_EXIST The specified principal does not exist. +66 NOT_AUTHORIZED The access control list on the server prevents + this operation. +67 BAD_OPTION Either: 1) A bad option was specified; 2) A + conflicting set of options would result from + this operation; or 3) Existing options prevent + this type of operation. +68 VALUE_REQUIRED The specified option requires a value. +69 SYSTEM_ERROR A system error occurred while processing a + request. +70(+) KEY_ALREADY_EXISTS The specified key already exists. +71(+) KEY_DOES_NOT_EXIST The specified key does not exist. + +The add principal operation +--------------------------- +o Command String "ADD-PRINCIPAL" +o Arguments + - name of new principal + - either "KEYWORD=value" or "KEYWORD". + . + . + . +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_ALREADY_EXISTS - new principal already exists + BAD_OPTION - bad option supplied + VALUE_REQUIRED - value required with keyword +o Supplemental Returns + NONE - if successful + error message text - if failure +o Description + If the specified principal does not exist, the arguments parse + correctly, and the arguments when combined with defaulted values + do not produce a conflicting set of options then add the specified + principal with the specified attributes. See below for the list of + settable attributes. +o Access Required + Client principal must have ADD_PRINCIPAL permission. + +The delete principal operation +------------------------------ +o Command String "DELETE-PRINCIPAL" +o Argument + - principal to delete +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_DOES_NOT_EXIST - old principal does not exist +o Supplemental returns + NONE - if successful + error message text - if failure +o Description + If the specified principal exists, then delete it from the database. +o Access Required + Client principal must have DELETE_PRINCIPAL permission. + +The rename principal operation +------------------------------ +o Command String "RENAME-PRINCIPAL" +o Arguments + - original name + - new name +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_DOES_NOT_EXIST - old principal does not exist + P_ALREADY_EXISTS - new principal already exists +o Supplemental Returns + NONE - if successful + error message text - if failure +o Description + If the original principal exists and the new principal name does not + exist, rename the original principal to the specified name. +o Access Required + Client principal must have ADD_PRINCIPAL and DELETE_PRINCIPAL + permission. + +The modify principal operation +------------------------------ +o Command String "MODIFY-PRINCIPAL" +o Arguments + - name of principal + - either KEYWORD=value or KEYWORD. + . + . + . +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_DOES_NOT_EXIST - principal doesn't exist + BAD_OPTION - bad option supplied + VALUE_REQUIRED - value required with keyword +o Supplemental returns + NONE - if successful + error message text - if failure +o Description + If the specified principal exists, the arguments parse correctly, and + the arguments when combined with existing values do not produce a + conflicting set of options, then modify the specified principal with + the specified attributes. See below for the list of settable + attributes. +o Access Required + Client principal must have MODIFY_PRINCIPAL permission. + +The change password operation +----------------------------- +o Command String "OTHER-CHANGEPW" +o Arguments + - principal to change password for + - new password +o Returns + SUCCESS - operation successful + PW_UNACCEPT - specified password is bad + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_DOES_NOT_EXIST - old principal does not exist + BAD_OPTION - principal has a random key +o Supplemental returns + NONE - if successful + error message text - if failure +o Description + If the specified principal exists, and does not have a random key, + then change the password to the specified password. The original + password is NOT required. +o Access Required + Client principal must have CHANGEPW permission. + +The change random password command +---------------------------------- +o Command String "OTHER-RANDOM-CHANGEPW" +o Argument + - principal to change password for +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_DOES_NOT_EXIST - old principal does not exist + BAD_OPTION - principal does not have a random key +o Supplemental Returns + NONE - if successful + error message text - if failure +o Description + If the specified principal exists, and has a random key, then + generate a new random password. The original password is NOT + required. +o Access Required + Client principal must have CHANGEPW permission. + +The inquire principal command +----------------------------- +o Command String "INQUIRE-PRINCIPAL" +o Argument + - name of principal or null argument +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_DOES_NOT_EXIST - principal doesn't exist +o Supplemental Returns + If the return is SUCCESS + - name of next principal in database + - KEYWORD=value list + . + . + . + Otherwise + error message text - if failure +o Description + If a principal is specified, then the database is searched for that + particular principal and its attributes are returned as keyword-value + pairs. If no principal is specified, then the first database entry + is returned. The name of the next principal in the database is always + returned to allow for scanning. See below for the list of attributes + that can be returned. +o Access Required + Client principal must have INQUIRE_PRINCIPAL permission. + +The OPTIONAL extract service key table entry command +---------------------------------------------------- +o Command String "EXTRACT-KEY" +o Arguments + - instance to extract for + - name to extract for +o Returns + SUCCESS - operation successful + CMD_UNKNOWN - operation not supported by server + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not allowed to perform this + P_DOES_NOT_EXIST - principal does not exist +o Supplemental Returns + - if successful + error message text - if failure +o Description + If the specified name/instance exists in the database, then + extract the service key entry and return it in . + The description of follows below. +o Access Required + Client principal must have EXTRACT permission. + +The add key operation +--------------------- +o Command String "ADD-KEY" +o Arguments + - name of the principal + - current password value + - name of the key in the form + :. + . + . + . +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not authorized to perform this + KEY_ALREADY_EXISTS - one or more of the specified + keytypes already exist. + BAD_OPTION - bad keytype:saltype specified + BAD_PW - supplied password is incorrect +o Supplemental Returns + NONE - if successful + error message text - if failure +o Description + If the specified principal exists, the keyname(s) parse + correctly the specified password is successfully verified + against the existing key(s), and the specified keyname(s) do + not exist, then these keytype(s) are added to the principal. +o Access Required + Client principal must have MODIFY_PRINCIPAL permission. + +The delete key operation +------------------------ +o Command String "DELETE-KEY" +o Arguments + - name of the principal + - current password value + - name of the key in the form + :, or name of the + key in the form :: + + . + . + . +o Returns + SUCCESS - operation successful + SYSTEM_ERROR - system error + NOT_AUTHORIZED - not authorized to perform this + KEY_DOES_NOT_EXIST - one or more of the specified + keytypes do not exist. + BAD_OPTION - bad keytype:saltype specified + BAD_PW - supplied password is incorrect +o Supplemental Returns + NONE - if successful + error message text - if failure +o Description + If the specified principal exists, the keyname(s) parse + correctly the specified password is successfully verified + against the existing key(s), and the specified keyname(s) + exist, then they are deleted from the principal. +o Access Required + Client principal must have MODIFY_PRINCIPAL permission. + +Keywords +-------- +The following list of keywords are used for the ADD-PRINCIPAL and +MODIFY-PRINCIPAL commands and are returned from the +INQUIRE-PRINCIPAL command. + +Valid Keyword Value Type Value +------- --------------- --------------- -------------------------------------- + (S) PASSWORD New password. + (SR) MAXLIFE The maximum lifetime of tickets for + this principal in seconds. + (SR) MAXRENEWLIFE The maximum renewable lifetime of + tickets for this principal in seconds. + (SR) EXPIRATION When the new principal expires. + (SR) PWEXPIRATION When the password expires for this + principal. + (SR) RANDOMKEY Specifies that this is to have a + random key generated for it. + (SR) FLAGS Specifies flag value for this + principal's attributes field in the + database. + (R) LASTSUCCESS Last successful password entry. + (R) LASTFAILED Last failed password attempt. + (R) FAILCOUNT Number of failed password attempts. + (SR) AUXDATA Tagged auxiliary value (see below) + (R) KEYDATA Key value (see below) + (SR) EXTRADATA Extra data (see below) + +The valid field indicates whether an attribute is Settable (e.g. appropriate +for use with ADD-PRINCIPAL, et. al.; Returnable (e.g. returned by +INQUIRE-PRINCIPAL); or both Settable and Returnable. + +o +The type denotes data which is stored in the database as a +tagged value. The protocol representation consists of a 4-byte network order +integer to denote the tag with the remaining data providing the value. If +encoded data is to be encapsulated, it must be in network order. In summary: + AUXDATA= +For example, to encode the value for tag 1 with a 4-byte value of 32 71 1e 30 +in network order, the encoding would be: + AUXDATA=00 00 00 01 32 71 1e 30 + +o +The type denotes data which is stored in the database on a per-key +basis. The protocol representation is consists of a 4-byte network order +integer to denote a particular key. This integer is implementation dependent +and is only used to correlate different entries. This integer +is followed by a 4-byte network order integer which denotes the attribute type. +Currently, only three are supported: -1 denotes the key version; 1 denotes the +key type and 2 denotes the salt type. This attribute type integer is followed +by the attribute value and an optional per-attribute value. In summary: + KEYDATA=[] +For example, to encode the value of a key with keytype 3, salttype 5, with key +version number 32, key data of 12 34 56 78 90 ab cd ef and salt data of f0 e1 +d2 c3 b4 a5 96 87, the encoding would be (using key-tag de ad be ef): + (key version number 32) + KEYDATA=de ad be ef ff ff ff ff 00 00 00 20 + (key keytype 3, value 1234567890abcdef) + KEYDATA=de ad be ef 00 00 00 01 00 00 00 03 12 34 56 78 90 ab cd ef + (key salttype 5, value f0e1d2c3b4a59687) + KEYDATA=de ad be ef 00 00 00 02 00 00 00 05 f0 e1 d2 c3 b4 a5 96 87 + +o +The type is exactly that. Unspecified. Any data may be encoded +here without restriction. + +Keytab Entry +------------ +If the EXTRACT SERVICE KEY function is supported, then the successful +response to this command is the key entry. This is a series of 6 +reply components as follows: + +component type value +--------- --------------- ----------------------------------------- + 1 Principal name + 2 Key entry timestamp + 3 Key's version number. + 4 Key's keytype. + 5 Key's encryption type. + 6 Key's key value. + +All of these components are mandatory. + diff --git a/krb5-1-6/doc/kadmin/kpasswd.protocol b/krb5-1-6/doc/kadmin/kpasswd.protocol new file mode 100644 index 000000000..7d77a2183 --- /dev/null +++ b/krb5-1-6/doc/kadmin/kpasswd.protocol @@ -0,0 +1,303 @@ + + + + A Proposal for a Standardized + Kerberos Password Changing Protocol + + **DRAFT** **DRAFT** **DRAFT** + + by Theodore Ts'o + September 7, 1995 + +Rationale +========= + +Currently, the Kerberos administration server which is being shipped +with the Beta Kerberos V5 distributions from MIT has not been of +sufficient quality for vendors to ship it in their products. Hence, +many vendors are creating and deploying proprietary administration +servers. In general, this is not a big problem --- relatively few +users are Kerberos administrators and thus the Kerberos administration +clients are used by relatively few users. + +There is a big exception to this, however, which is the functionality of +a user being able to change his or her own password. Application +programs may want to include this functionality in their programs; it +would be desireable for there to be a standardized protocol for doing +this. Standardized Kerberos desktop management programs (such as +Cornell's Authman) would also benefit from a standardized protocol; this +way, they will do not need to implement many vendor-specific Kerberos +administration protocols. Similarily, at least one terminal server +vendor has come to expressing their concern that there was not a +standardized password changing protocol, since they wanted their product +to offer this functionality. + +This protocol is designed to address these concerns. + + +Protocol Description +==================== + +The protocol used by the password changing protocol is intentionally +very simple. This is to encourage its widespread implementation, even +in cases where there are size constraints (i.e., in a terminal server). + +The protocol will use a TCP stream connection using port 464. The +symbolic name of this port is kpasswd: + + kpasswd 464/tcp + + +The following encoding standards are used throughout. + +Integers are sent as 4 byte objects, where the most significant byte +is sent first, and the least signifcant byte is sent last. (i.e., +standard Internet network byte order.) + +Protocol data units (PDU's) are sent across using the following +encoding. First, the size of the PDU is sent as a 4 byte integer, +followed by the PDU itself. PDU's used by the protocol will be either a +KRB_AP_REQ message, a KRB_AP_REP message, a "command request" PDU, or a +"command response" PDU. (The last two PDU's are encoded using a +KRB_PRIV message. For definitions of the KRB_AP_REQ, KRB_AP_REP, and +KRB_PRIV message, see the Kerberos V5 protocol specification found in +RFC 1510.) + +The PDU's which are encoded using the KRB_PRIV message must include the +sequence number field --- the client and server must fill in each +successive PDU that it sends with a monotonically increasing sequence +number. The initial sequence number in each direction are negotiated in +the KRB_AP_REQ and KRB_AP_REP messages. + +The size of a Protoocl Data Unit SHOULD not exceed 16,384 bytes. If an +implementation receives a PDU which is larger that 16,384 bytes, the +implementation MAY consider this a fatal error and terminate the TCP +connection. An implementation MUST be able to receive PDU's of at least +16,384 bytes. + +The "command request" PDU +------------------------- + +The "command request" PDU is sent from the client to server. This PDU +uses the following structure: First, the number of arguments, sent +across as an integer. The number of arguments MUST be greater than +zero. It is then followed by the arguments themselves, which are +encoded as an integer length followed by the value of the argument. + +The first argument is "command name". The command name is a NETASCII +string, and it may not contain an ASCII null. Command names are case +insentive. Valid command names are defined below; any site-, or vendor- +specific extensions to this protocol should use command names which +begin with the letter 'X'. + +The other arguments (if any) are dependent on the command specified by +the first argument. + +In other words: + + Number of Arguments (integer, must be greater than zero) + Arg size 1 (integer) + Arg data 1 (octet string, command name) + ... + Arg size N (integer) + Arg data N (octet string) + +This structure is then encrypted using the Kerberos V5 KRB_PRIV message. + +The "command reply" PDU +----------------------- + +In response to a "command request" PDU, the server will send to the +client a "command reply" PDU. The structure of a "command reply" PDU is +as follows: + + status code (integer) + Number of reply components (integer, may be zero) + Arg size 1 (integer) + Arg data 1 (octet string) + ... + Arg size N (integer) + Arg data N (octet string) + +This structure is then encrypted using the Kerberos V5 KRB_PRIV message. + +The status code may be one of the following values: + +# Symbolic name Meaning + +0 SUCCESS The command was executed without any errors +1 CMD_UNKNOWN Command not recognized +2 PW_UNACCEPT The password chosen by the user is unnacceptable. +3 BAD_PW The old password furnished by the user is not correct. +4 NOT_IN_TKT The ticket used to authenticate to the server + did not have the TKT_FLAG_INITIAL flag set. +5 CANT_CHANGE The server is not able to change the password + due to no fault of the user. (For + example, the database may be in + read-only mode for maintance reasons.) +6 LANG_NOT_SUPPORTED The requested language is not supported. + +The error codes below 127, and above 256 are reserved for future +expansion. Local extensions of this protocol should use error codes +between 128 and 255. + +The user text in the reply message is generally some sort of +explanatory text, which should be displayed to the user. + + +Connection Establishment +======================== + +When a connection is made the password changing client exchanges the +following PDU's: + +Client Server +------ ------ + +KRB_AP_REQ -------> + + <------- KRB_AP_REP + +KRB_AP_REQ and KRB_AP_REP are the respective Kerberos V5 messages. The +client will autenticate to the server using the service name +changepw/@, where should be +substituted with the name of the Kerberos realm of the password changing +server. The client MUST set the MUTUAL-REQUIRED flag in the KRB_AP_REQ +message, which indicates that server shall send a KRB_AP_REP message for +the purposes of establishing mutual authentication between the client +and the server. + +Protocol Commands +================== + +After the connection is established, the client may then send any +number of "command request" PDUs; after each command request PDU is +sent, the client should wait for a "command reply" PDU from the +server. + +If after 30 seconds inactivity, the client does not send a "command +request" PDU, the server MAY elect to terminate the TCP connection. + +The following commands defined in this standard: + + QUIT + CHECKPW + CHANGEPW + MOTD (*) + MIME (*) + LANGUAGE (*) + +The commands marked with a (*) are optional; servers may or may not +elect to support these commands. If the commands are not supported, the +server shall return a status code of CMD_UNKNOWN. + +The quit command +---------------- + +The name of this command is "QUIT", and it takes no arguments. The +response to this command must be the error code "NO_ERROR". There may +be an optional reply component, which will consist of user text which +should be displayed to the user. After processing this command, the +server will terminate the connection. + +Kerberos password changing servers MUST implement this command. + + +The check password command +--------------------------- + +The name of this command is "CHECKPW", and it takes one argument, +which is a proposed password. The server will evaluate this password +according to its criteria and return either an NO_ERROR or PW_UNACCEPT +error code. + +There may be an optional reply component which consists of user text +which should be displayed to the user. It will typically explain why +the password was unacceptable. + +Kerberos password changing servers MUST implement this command. + + +The change password command +--------------------------- + +The name of this command is "CHANGEPW", and it takes two arguments. The +first argument is the old password, and the second password is the new +password. The response from this command will generally be one of the +following error codes: NO_ERROR, PW_UNACCEPT, BAD_PW, NOT_IN_TKT, +CANT_CHANGE. + +This command changes the password of the Kerberos principal which the +client used to authenticate to the server. For security reasons, the +server should check to make sure that the ticket used to authenticate to +the server had the TKT_FLG_INITIAL flag set; if this flag is not set in +the ticket, then when the client attempts to use the "CHANGEPW" command, +the server should return the NOT_IN_TKT error. + +There may be an optional reply component which consists of user text +which should be displayed to the user, explaining why the password was +unacceptable or why the user's password could not be changed. + +Kerberos password changing servers MUST implement this command. + + +The Message of the Day command +------------------------------ + +The name of this command is "MOTD", and it takes zero or one additional +arguments. The optional argument is a magic token passed back from a +previous MOTD command. If this magic token is sent, the server MAY use +it to determine use it to determine what (if any) messages should be +displayed to the user. + +This command returns one or two reply components. The first reply +component is a magic token; the magic token shall be a NETASCII string +which may not contain an ASCII null character, and its length shall be +less than 64 characters. A client MAY store this magic token between +invocations of the client, and send it to the server the next time the +MOTD command is requested. + +The second (optional) reply component contains text which should be +displayed to the user. + +Kerberos password changing servers MAY optionally implement this command. + + +The MIME command +---------------- + +The name of this command is "MIME", and it takes zero additional +arguments. + +This command indicates that the client is willing to accept +MIME-enhanced textual messages in place of the standard NETASCII textual +messages. + +If this command is not sent, the server MUST send all textual messages +using NETASCII, with used as a line breaks, and line lengths no +more than 80 characters. If this command is sent, and the server +returns a status code of SUCCESS, the server MUST send textual messages +as MIME-enhanced textual messages. The server may refuse to send MIME +messages by sending a status code of CMD_UNKNOWN. + +Kerberos password changing servers MAY optionally implement this command. + + +The Language Command +--------------------- + +The name of this command is "LANGUAGE", and it takes one additional +argument, which indicates the language that the textual messages should +be sent back in. This additional argument must be consist of NETASCII +characters, with ASCII nulls not allowed. The argument shall be case +insensitive. What constitute valid arguments to this command are a +local matter. [Since ISO apparently doesn't have a standard way of +referring to different languages or dialects.] + +This command indicates that the client would prefer that textual +messages be sent back using the requested language. If the server does +not support the requested language, the server may refuse the request by +sending the error code LANG_NOT_SUPPORTED. + +Kerberos password changing servers MAY optionally implement this command. + diff --git a/krb5-1-6/doc/kdcconf.texinfo b/krb5-1-6/doc/kdcconf.texinfo new file mode 100644 index 000000000..51583714e --- /dev/null +++ b/krb5-1-6/doc/kdcconf.texinfo @@ -0,0 +1,24 @@ +The @code{kdc.conf} file contains KDC configuration information, +including defaults used when issuing Kerberos tickets. Normally, you +should install your @code{kdc.conf} file in the directory +@code{@value{ROOTDIR}/var/krb5kdc}. You can override the default +location by setting the environment variable @samp{KRB5_KDC_PROFILE}. + +The @code{kdc.conf} file is set up in the same format as the +@code{krb5.conf} file. (@xref{krb5.conf}.) The @code{kdc.conf} file +may contain any or all of the following three sections: + +@table @b +@item kdcdefaults +Contains default values for overall behavior of the KDC. + +@item realms +Contains subsections keyed by Kerberos realm names. Each subsection +describes realm-specific information, including where to find the +Kerberos servers for that realm. + +@item logging +Contains relations which determine how Kerberos programs are to perform +logging. +@end table + diff --git a/krb5-1-6/doc/krb4-xrealm.txt b/krb5-1-6/doc/krb4-xrealm.txt new file mode 100644 index 000000000..f8c4566e5 --- /dev/null +++ b/krb5-1-6/doc/krb4-xrealm.txt @@ -0,0 +1,143 @@ +The following text was taken from the patchkit disabling cross-realm +authentication and triple-DES in krb4. + +PATCH KIT DESCRIPTION +===================== + +** FLAG DAY REQUIRED ** + +One of the things we decided to do (and must do for security reasons) +was drop support for the 3DES krb4 TGTs. Unfortunately the current +code will only accept 3DES TGTs if it issues 3DES TGTs. Since the new +code issues only DES TGTs, the old code will not understand its v4 +TGTs if the site has a 3DES key available for the krbtgt principal. +The new code will understand and accept both DES and 3DES v4 TGTs. + +So, the easiest upgrade option is to deploy the code on all KDCs at +once, being sure to deploy it on the master KDC last. Under this +scenario, a brief window exists where slaves may be able to issue +tickets that the master will not understand. However, the slaves will +understand tickets issued by the master throughout the upgrade. + +An alternate and more annoying upgrade strategy exists. At least one +max TGT life time before the upgrade, the TGT key can be changed to be +a single-des key. Since we support adding a new TGT key while +preserving the old one, this does not create an interruption in +service. Since no 3DES key is available then both the old and new +code will issue and accept DES v4 TGTs. After the upgrade, the TGT +key can again be rekeyed to add 3DES keys. This does require two TGT +key changes and creates a window where DES is used for the v5 TGT, but +creates no window in which slaves will issue TGTs the master cannot +accept. + +* What the patch does +===================== + +1) Kerberos 4 cross-realm authentication is disabled by default. A + "-X" switch is added to both krb524d and krb5kdc to enable v4 + cross-realm. This switch logs a note that a security hole has been + opened in the KDC log. We said while designing the patch, that we + were going to try to allow per-realm configuration; because of a + design problem in the kadm5 library, we could not do this without + bumping the ABI version of that library. We are unwilling to bump + an ABI version in a security patch release to get that feature, so + the configuration of v4 cross-realm is a global switch. + +2) Code responsible for v5 TGTs has been changed to require that the + enctype of the ticket service key be the same as the enctype that + would currently be issued for that kvno. This means that even if a + service has multiple keys, you cannot use a weak key to fake the + KDC into accepting tickets for that service. If you have a non-DES + TGT key, this separates keys used for v4 and v5. We actually relax + this requirement for cross-realm TGT keys (which in the new code + are only used for v5) because we cannot guarantee other Kerberos + implementations will choose keys the same way. + +3) We no longer issue 3DES v4 tickets either in the KDC or krb524d. + We add code to accept either DES or 3DES tickets for v4. None of + the attacks discovered so far can be implemented given a KDC that + accepts but does not issue 3DES tickets, so we believe that leaving + this functionality in as compatibility for a version or two is + reasonable. Note however that the attacks described do allow + successful attackers to print future tickets, so sites probably + want to rekey important keys after installing this update. Note + also that even if issuance of 3DES v4 tickets has been disabled, + outstanding tickets may be used to perform the 3DES cut-and-paste + attack. + +* Test Cases +============ + +This code is difficult to test for two reasons. First, you need a +cross-realm relationship between two KDCs. Secondly, you need a KDC +that will issue 3DES v4 tickets even though the code with the patch +applied can no longer do this. + +I propose to meet these requirements by setting up a cross-realm 3DES +key between a realm I control and the test environment. In order to +provide concrete examples of what I plan to test with the automated +tests, I assume a shared key between a realm PREPATCH.KRBTEST.COM and the +test realm PATCH. + +In all of the following tests I assume the following configuration. +A principal v4test@PREPATCH.KRBTEST.COM exists with known password and +without requiring preauthentication. The PREPATCH.KRBTEST.COM KDC will +issue v4 tickets for this principal. A principal test@PATCH exists +with known password and without requiring preauthentication. A +principal service@PATCH exists. The TGT for the PATCH realm has a +3des and des key. The shared TGT keys between PATCH and +PREPATCH.KRBTEST.COM are identical in both directions (required for v4) and +support both 3DES and DES keys. + +1) Run krb524d and krb5kdc for PATCH with no special options using a + krb5.conf without permitted_enctypes (fully permissive). + + +A) Get v4 tickets as v4test@PREPATCH.KRBTEST.COM. Confirm that kvno -4 +service@PATCH fails with an unknown principal error and logs an error +about cross-realm being denied to the PATCH KDC log. This confirms +that v4 cross-realm is not accepted. + +B) Get v5 tickets as v4test@PREPATCH.KRBTEST.COM. Confirm that krb524init +-p service@PATCH fails with a prohibited by policy error, but that +klist -5 includes a ticket for service@PATCH. This confirms that v5 +cross-realm works but the krb524d denies converting such a ticket into +a cross-realm ticket. Note that the krb524init currently in the +mainline source tree will not be useful for this test because the +client denies cross-realm for the simple reason that the v4 ticket +file format is not flexible enough to support it. The krb524init in +the 1.2.x release is useful for this test. + + +2) Restart the krb5kdc and krb524d for PATCH with the -X option + enabling v4 cross-realm. + +A) Confirm that the security warning is written to kdc.log. + +B) Get v4 tickets as v4test@PREPATCH.KRBTEST.COM. Confirm that kvno -4 +service@PATCH works and leaves a service@PATCH ticket in the cache. +This confirms that v4 cross-realm works in the KDC. It also confirms +that the KDC can accept 3DES v4 TGTs. The code path for decrypting a +TGT is the same for the local realm and for foreign realms, so I don't +see a need to test local 3DES TGTs in an automated manner although I +did test it manually. + +C) Get v5 tickets as v4test@PREPATCH.KRBTEST.COM. Confirm that krb524init +-p service@PATCH works. This confirms that krb524d will issue +cross-realm tickets. They're completely useless because the v4 ticket +file can't represent them, but that's not our problem today. + +3) Start the kdc and krb524d with a krb5.conf that includes + permitted_enctypes only listing des-cbc-crc. Get tickets as + test@PATCH. Restart the KDC and confirm that kvno service fails + logging an error about permitted enctypes. This confirms that if + you manage to obtain a ticket of the wrong enctype it will not be + accepted later. + +These tests do not check to make sure that 3DES tickets are not +issued by the v4 code. I'm fairly certain that is true as I've +physically remove the calls to the routine that generates 3DES tickets +from the code in both the KDC and krb524d. These tests also do not +check to make sure that cross-realm TGTs are not required to follow +the strict enctype policy. I've tested that manually but don't know +how to test that without significantly complicating the test setup. diff --git a/krb5-1-6/doc/krb425.texinfo b/krb5-1-6/doc/krb425.texinfo new file mode 100644 index 000000000..fdeb033c1 --- /dev/null +++ b/krb5-1-6/doc/krb425.texinfo @@ -0,0 +1,322 @@ +\input texinfo @c -*-texinfo-*- +@c Note: the above texinfo file must include the "doubleleftarrow" +@c definitions added by jcb. +@c %**start of header +@c guide +@setfilename krb425.info +@settitle Upgrading to Kerberos V5 from Kerberos V4 +@c @setchapternewpage odd @c chapter begins on next odd page +@c @setchapternewpage on @c chapter begins on next page +@c @smallbook @c Format for 7" X 9.25" paper +@c %**end of header + +@paragraphindent 0 +@iftex +@parskip 6pt plus 6pt +@end iftex + +@dircategory Kerberos +@direntry +* krb425: (krb425). Upgrading to Kerberos V5 from V4 +@end direntry + +@include definitions.texinfo +@set EDITION 1.0 +@set UPDATED May 22, 2003 + +@finalout @c don't print black warning boxes + +@titlepage +@title Upgrading to @value{PRODUCT} from Kerberos V4 +@subtitle Release: @value{RELEASE} +@subtitle Document Edition: @value{EDITION} +@subtitle Last updated: @value{UPDATED} +@author @value{COMPANY} + +@page +@vskip 0pt plus 1filll + +@end titlepage + +@node Top, Copyright, (dir), (dir) + +@ifinfo +This document describes how to convert to @value{PRODUCT} from Kerberos V4. +@end ifinfo + +@menu +* Copyright:: +* Introduction:: +* Configuration Files:: +* Upgrading KDCs:: +* Upgrading Application Servers:: +* Upgrading Client machines:: +* Firewall Considerations:: +@end menu + +@node Copyright, Introduction, Top, Top +@unnumbered Copyright +@include copyright.texinfo + +@node Introduction, Configuration Files, Copyright, Top +@chapter Introduction + +As with most software upgrades, @value{PRODUCT} is generally backward +compatible but not necessarily forward compatible. The @value{PRODUCT} +daemons can interoperate with Kerberos V4 clients, but most of the +Kerberos V4 daemons can not interoperate with Kerberos V5 clients. This +suggests the following strategy for performing the upgrade: + +@enumerate +@item +@strong{Upgrade your KDCs.} This must be done first, so that +interactions with the Kerberos database, whether by Kerberos V5 clients +or by Kerberos V4 clients, will succeed. + +@item +@strong{Upgrade your servers.} This must be done before upgrading +client machines, so that the servers are able to respond to both +Kerberos V5 and Kerberos V4 queries. + +@item +@strong{Upgrade your client machines.} Do this only after your KDCs and +application servers are upgraded, so that all of your Kerberos V5 +clients will be talking to Kerberos V5 daemons. +@end enumerate + +@node Configuration Files, Upgrading KDCs, Introduction, Top +@chapter Configuration Files + +The Kerberos @code{krb5.conf} and KDC @code{kdc.conf} configuration +files allow additional tags for Kerberos V4 compatibility. + +@menu +* krb5.conf:: +* kdc.conf:: +@end menu + +@node krb5.conf, kdc.conf, Configuration Files, Configuration Files +@section krb5.conf + +If you used the defaults, both when you installed Kerberos V4 and when +you installed @value{PRODUCT}, you should not need to include any of +these tags. However, some or all of them may be necessary for +nonstandard installations. + +@menu +* libdefaults:: +* realms (krb5.conf):: +* AFS and the Appdefaults Section:: +@end menu + +@node libdefaults, realms (krb5.conf), krb5.conf, krb5.conf +@subsection [libdefaults] + +In the [libdefaults] section, the following additional tags may be used: + +@table @b +@item krb4_srvtab +Specifies the location of the Kerberos V4 srvtab file. Default is +@value{DefaultKrb4Srvtab}. + +@item krb4_config +Specifies the location of the Kerberos V4 configuration file. Default +is @value{DefaultKrb4Config}. + +@item krb4_realms +Specifies the location of the Kerberos V4 domain/realm translation +file. Default is @value{DefaultKrb4Realms}. +@end table + +@node realms (krb5.conf), AFS and the Appdefaults Section, libdefaults, krb5.conf +@subsection [realms] + +In the [realms] section, the following Kerberos V4 tags may be used: +@table @b +@itemx default_domain +Identifies the default domain for hosts in this realm. This is needed +for translating V4 principal names (which do not contain a domain name) +to V5 principal names. The default is your Kerberos realm name, +converted to lower case. + +@itemx v4_instance_convert +This subsection allows the administrator to configure exceptions to the +default_domain mapping rule. It contains V4 instances (tag name) which +should be translated to some specific hostname (tag value) as the second +component in a Kerberos V5 principal name. + +@itemx v4_realm +This relation allows the administrator to configure a different +realm name to be used when converting V5 principals to V4 +ones. This should only be used when running separate V4 and V5 +realms, with some external means of password sychronization +between the realms. + +@end table + +@node AFS and the Appdefaults Section, , realms (krb5.conf), krb5.conf +@subsection AFS and the Appdefaults Section + +Many Kerberos 4 sites also run the Andrew File System (AFS). + +Modern AFS servers (OpenAFS > 1.2.8) support the AFS 2b token format. +This allows AFS to use Kerberos 5 tickets rather than version 4 +tickets, enabling cross-realm authentication. By default, the +@file{krb524d} service will issue the new AFS 2b tokens. If you are +using old AFS servers, you will need to disable these new tokens. +Please see the documentation of the @code{appdefaults} section of +@file{krb5.conf} in the Kerberos Administration guide. + + + +@node kdc.conf, , krb5.conf, Configuration Files +@section kdc.conf + +Because Kerberos V4 requires a different type of salt for the encryption +type, you will need to change the @code{supported_enctypes} line in the +[realms] section to: + +@smallexample +supported_enctypes = des-cbc-crc:normal des-cbc-crc:v4 +@end smallexample + +This is the only change needed to the @code{kdc.conf} file. + +@node Upgrading KDCs, Upgrading Application Servers, Configuration Files, Top +@chapter Upgrading KDCs + +To convert your KDCs from Kerberos V4 to @value{PRODUCT}, do the +following: + +@enumerate +@item +Install @value{PRODUCT} on each KDC, according to the instructions in +the @value{PRODUCT} Installation Guide, up to the point where it tells +you to create the database. + +@item +Find the @code{kadmind} (V4) daemon process on the master KDC and kill +it. This will prevent changes to the Kerberos database while you +convert the database to the new Kerberos V5 format. + +@item +Create a dump of the V4 database in the directory where your V5 database +will reside by issuing the command: + +@smallexample +% kdb_util dump @value{ROOTDIR}/var/krb5kdc/v4-dump +@end smallexample + +@item +Load the V4 dump into a Kerberos V5 database, by issuing the command: + +@smallexample +% kdb5_util load_v4 v4-dump +@end smallexample + +@item +Create a Kerberos V5 stash file, if desired, by issuing the command: + +@smallexample +% kdb5_util stash +@end smallexample + +@item +Proceed with the rest of the @value{PRODUCT} installation as described +in the @value{PRODUCT} Installation Guide. When you get to the section +that tells you to start the @code{krb5kdc} and @code{kadmind} daemons, +first find and kill the Kerberos V4 @code{kerberos} daemon on each of +the KDCs. Then start the @code{krb5kdc} and @code{kadmind} daemons as +You will need to specify an argument to the @code{-4} command line option to enable Kerberos 4 compatibility. +See the @code{krb5kdc} man page for details. +directed. Finally, start the Kerberos V5 to V4 ticket translator +daemon, @code{krb524d}, by issuing the command: + +@smallexample +% @value{ROOTDIR}/sbin/krb524d -m > /dev/null & +@end smallexample + +If you have a stash file and you start the @code{krb5kdc} and +@code{kadmind} daemons at boot time, you should add the above line to +your @code{/etc/rc} (or @code{/etc/rc.local}) file on each KDC. +@end enumerate + +@node Upgrading Application Servers, Upgrading Client machines, Upgrading KDCs, Top +@chapter Upgrading Application Servers + +Install @value{PRODUCT} on each application server, according to the +instructions in the @value{PRODUCT} Installation Guide, with the +following exceptions: + +@itemize @bullet +@item +In the file @code{/etc/services}, add or edit the lines described in the +@value{PRODUCT} Installation Guide, with the following exception: + +in place of: + +@smallexample +@group +kerberos @value{DefaultPort}/udp kdc # Kerberos V5 KDC +kerberos @value{DefaultPort}/tcp kdc # Kerberos V5 KDC +@end group +@end smallexample + +@noindent +add instead: + +@smallexample +@group +kerberos-sec @value{DefaultPort}/udp kdc # Kerberos V5 KDC +kerberos-sec @value{DefaultPort}/tcp kdc # Kerberos V5 KDC +@end group +@end smallexample + +@item +Convert your Kerberos V4 srvtab file to Kerberos V5 keytab file as +follows: + +@smallexample +@group +@b{#} @value{ROOTDIR}/sbin/ktutil +@b{ktutil:} rst /etc/krb-srvtab +@b{ktutil:} wkt /etc/krb5.keytab +@b{ktutil:} q +@b{#} +@end group +@end smallexample +@end itemize + +@node Upgrading Client machines, Firewall Considerations, Upgrading Application Servers, Top +@chapter Upgrading Client machines + +Install @value{PRODUCT} on each client machine, according to the +instructions in the @value{PRODUCT} Installation Guide. + +Tell your users to add the appropriate directory to their paths. On +UNIX machines, this will probably be @code{@value{BINDIR}}. + +Note that if you upgrade your client machines before all of your +application servers are upgraded, your users will need to use the +Kerberos V4 programs to connect to application servers that are still +running Kerberos V4. (The one exception is the UNIX version of +@value{PRODUCT} telnet, which can connect to a Kerberos V4 and Kerberos +V5 application servers.) Users can use either the Kerberos V4 or +@value{PRODUCT} programs to connect to Kerberos V5 servers. + +@node Firewall Considerations, , Upgrading Client machines, Top +@chapter Firewall Considerations + +@value{PRODUCT} uses port @value{DefaultPort}, which is the port +assigned by the IETF, for KDC requests. Kerberos V4 used port +@value{DefaultSecondPort}. If your users will need to get to any KDCs +outside your firewall, you will need to allow TCP and UDP requests on +port @value{DefaultPort} for your users to get to off-site Kerberos V5 +KDCs, and on port @value{DefaultSecondPort} for your users to get to +off-site Kerberos V4 KDCs. + +@contents +@c second page break makes sure right-left page alignment works right +@c with a one-page toc, even though we don't have setchapternewpage odd. +@c end of texinfo file +@bye diff --git a/krb5-1-6/doc/krb5-protocol/draft-jaganathan-rc4-hmac-03.txt b/krb5-1-6/doc/krb5-protocol/draft-jaganathan-rc4-hmac-03.txt new file mode 100755 index 000000000..1304ae2bc --- /dev/null +++ b/krb5-1-6/doc/krb5-protocol/draft-jaganathan-rc4-hmac-03.txt @@ -0,0 +1,1013 @@ + + + +Internet Engineering Task Force K. Jaganathan +Internet-Draft L. Zhu +Intended status: Informational J. Brezak +Expires: January 31, 2007 Microsoft Corporation + July 30, 2006 + + + The RC4-HMAC Kerberos Encryption Types Used by Microsoft Windows + draft-jaganathan-rc4-hmac-03.txt + +Status of this Memo + + By submitting this Internet-Draft, each author represents that any + applicable patent or other IPR claims of which he or she is aware + have been or will be disclosed, and any of which he or she becomes + aware will be disclosed, in accordance with Section 6 of BCP 79. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress." + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt. + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + This Internet-Draft will expire on January 31, 2007. + +Copyright Notice + + Copyright (C) The Internet Society (2006). + +Abstract + + The Microsoft Windows 2000 implementation of Kerberos introduces a + new encryption type based on the RC4 encryption algorithm and using + an MD5 HMAC for checksum. This is offered as an alternative to using + the existing DES based encryption types. + + The RC4-HMAC encryption types are used to ease upgrade of existing + Windows NT environments, provide strong crypto (128-bit key lengths), + + + +Jaganathan, et al. Expires January 31, 2007 [Page 1] + +Internet-Draft RC4-HMAC July 2006 + + + and provide exportable (meet United States government export + restriction requirements) encryption. This document describes the + implementation of those encryption types. + + +Table of Contents + + 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 + 2. Key Generation . . . . . . . . . . . . . . . . . . . . . . . . 3 + 3. Basic Operations . . . . . . . . . . . . . . . . . . . . . . . 4 + 4. Checksum Types . . . . . . . . . . . . . . . . . . . . . . . . 6 + 5. Encryption Types . . . . . . . . . . . . . . . . . . . . . . . 6 + 6. Key Strength Negotiation . . . . . . . . . . . . . . . . . . . 8 + 7. GSSAPI Kerberos V5 Mechanism Type . . . . . . . . . . . . . . 8 + 7.1. Mechanism Specific Changes . . . . . . . . . . . . . . . . 8 + 7.2. GSSAPI MIC Semantics . . . . . . . . . . . . . . . . . . . 10 + 7.3. GSSAPI WRAP Semantics . . . . . . . . . . . . . . . . . . 12 + 8. Security Considerations . . . . . . . . . . . . . . . . . . . 15 + 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 15 + 10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16 + 11. References . . . . . . . . . . . . . . . . . . . . . . . . . . 16 + 11.1. Normative References . . . . . . . . . . . . . . . . . . . 16 + 11.2. Informative References . . . . . . . . . . . . . . . . . . 16 + Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 16 + Intellectual Property and Copyright Statements . . . . . . . . . . 18 + + + + + + + + + + + + + + + + + + + + + + + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 2] + +Internet-Draft RC4-HMAC July 2006 + + +1. Introduction + + The Microsoft Windows 2000 implementation of Kerberos contains new + encryption and checksum types for two reasons: for export reasons + early in the development process, 56 bit DES encryption could not be + exported, and because upon upgrade from Windows NT 4.0 to Windows + 2000, accounts will not have the appropriate DES keying material to + do the standard DES encryption. Furthermore, 3DES is not available + for export, and there was a desire to use a single flavor of + encryption in the product for both US and international products. + + As a result, there are two new encryption types and one new checksum + type introduced in Microsoft Windows 2000. + + Note that these cryptosystems aren't intended to be complete, + general-purpose Kerberos encryption or checksum systems as defined in + [RFC3961]: there is no one-one mapping between the operations in this + documents and the primitives described in [RFC3961]. + + +2. Key Generation + + On upgrade from existing Windows NT domains, the user accounts would + not have a DES based key available to enable the use of DES base + encryption types specified in [RFC4120] [RFC3961]. The key used for + RC4-HMAC is the same as the existing Windows NT key (NT Password + Hash) for compatibility reasons. Once the account password is + changed, the DES based keys are created and maintained. Once the DES + keys are available DES based encryption types can be used with + Kerberos. + + The RC4-HMAC String to key function is defined as follow: + + String2Key(password) + + K = MD4(UNICODE(password)) + + The RC4-HMAC keys are generated by using the Windows UNICODE version + of the password. Each Windows UNICODE character is encoded in + little-endian format of 2 octets each. Then performing an MD4 + [RFC1320] hash operation on just the UNICODE characters of the + password (not including the terminating zero octets). + + For an account with a password of "foo", this String2Key("foo") will + return: + + 0xac, 0x8e, 0x65, 0x7f, 0x83, 0xdf, 0x82, 0xbe, + 0xea, 0x5d, 0x43, 0xbd, 0xaf, 0x78, 0x00, 0xcc + + + +Jaganathan, et al. Expires January 31, 2007 [Page 3] + +Internet-Draft RC4-HMAC July 2006 + + +3. Basic Operations + + The MD5 HMAC function is defined in [RFC2104]. It is used in this + encryption type for checksum operations. Refer to [RFC2104] for + details on its operation. In this document this function is referred + to as HMAC(Key, Data) returning the checksum using the specified key + on the data. + + The basic MD5 hash operation is used in this encryption type and + defined in [RFC1321]. In this document this function is referred to + as MD5(Data) returning the checksum of the data. + + RC4 is a stream cipher licensed by RSA Data Security . In this + document the function is referred to as RC4(Key, Data) returning the + encrypted data using the specified key on the data. + + These encryption types use key derivation. With each message, the + message type (T) is used as a component of the keying material. This + table summarizes the different key derivation values used in the + various operations. Note that these differ from the key derivations + used in other Kerberos encryption types. T = the message type, + encoded as a little-endian four byte integer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 4] + +Internet-Draft RC4-HMAC July 2006 + + + 1. AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with + the client key (T=1) + 2. AS-REP Ticket and TGS-REP Ticket (includes TGS session key + or application session key), encrypted with the service key + (T=2) + 3. AS-REP encrypted part (includes TGS session key or + application session key), encrypted with the client key (T=8) + 4. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the + TGS session key (T=4) + 5. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the + TGS authenticator subkey (T=5) + 6. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum, + keyed with the TGS session key (T=6) + 7. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes + TGS authenticator subkey), encrypted with the TGS session key + T=7) + 8. TGS-REP encrypted part (includes application session key), + encrypted with the TGS session key (T=8) + 9. TGS-REP encrypted part (includes application session key), + encrypted with the TGS authenticator subkey (T=8) + 10. AP-REQ Authenticator cksum, keyed with the application + session key (T=10) + 11. AP-REQ Authenticator (includes application authenticator + subkey), encrypted with the application session key (T=11) + 12. AP-REP encrypted part (includes application session + subkey), encrypted with the application session key (T=12) + 13. KRB-PRIV encrypted part, encrypted with a key chosen by + the application. Also for data encrypted with GSS Wrap (T=13) + 14. KRB-CRED encrypted part, encrypted with a key chosen by + the application (T=14) + 15. KRB-SAFE cksum, keyed with a key chosen by the + application. Also for data signed in GSS MIC (T=15) + + Relative to RFC-1964 key uses: + + T = 0 in the generation of sequence number for the MIC token + T = 0 in the generation of sequence number for the WRAP token + T = 0 in the generation of encrypted data for the WRAPPED token + + All strings in this document are ASCII unless otherwise specified. + The lengths of ASCII encoded character strings include the trailing + terminator character (0). The concat(a,b,c,...) function will return + the logical concatenation (left to right) of the values of the + arguments. The nonce(n) function returns a pseudo-random number of + "n" octets. + + + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 5] + +Internet-Draft RC4-HMAC July 2006 + + +4. Checksum Types + + There is one checksum type used in this encryption type. The + Kerberos constant for this type is: + + #define KERB_CHECKSUM_HMAC_MD5 (-138) + + The function is defined as follows: + + K - is the Key + T - the message type, encoded as a little-endian four byte integer + + CHKSUM(K, T, data) + + Ksign = HMAC(K, "signaturekey") //includes zero octet at end + tmp = MD5(concat(T, data)) + CHKSUM = HMAC(Ksign, tmp) + + +5. Encryption Types + + There are two encryption types used in these encryption types. The + Kerberos constants for these types are: + + #define KERB_ETYPE_RC4_HMAC 23 + #define KERB_ETYPE_RC4_HMAC_EXP 24 + + The basic encryption function is defined as follow: + + T = the message type, encoded as a little-endian four byte integer. + + OCTET L40[14] = "fortybits"; + + The header field on the encrypted data in KDC messages is: + + typedef struct _RC4_MDx_HEADER { + OCTET Checksum[16]; + OCTET Confounder[8]; + } RC4_MDx_HEADER, *PRC4_MDx_HEADER; + + + ENCRYPT (K, export, T, data) + { + struct EDATA { + struct HEADER { + OCTET Checksum[16]; + OCTET Confounder[8]; + } Header; + + + +Jaganathan, et al. Expires January 31, 2007 [Page 6] + +Internet-Draft RC4-HMAC July 2006 + + + OCTET Data[0]; + } edata; + + if (export){ + *((DWORD *)(L40+10)) = T; + HMAC (K, L40, 10 + 4, K1); + } + else + { + HMAC (K, &T, 4, K1); + } + memcpy (K2, K1, 16); + if (export) memset (K1+7, 0xAB, 9); + + nonce (edata.Confounder, 8); + memcpy (edata.Data, data); + + edata.Checksum = HMAC (K2, edata); + K3 = HMAC (K1, edata.Checksum); + + RC4 (K3, edata.Confounder); + RC4 (K3, data.Data); + } + + DECRYPT (K, export, T, edata) + { + // edata looks like + struct EDATA { + struct HEADER { + OCTET Checksum[16]; + OCTET Confounder[8]; + } Header; + OCTET Data[0]; + } edata; + + if (export){ + *((DWORD *)(L40+10)) = T; + HMAC (K, L40, 14, K1); + } + else + { + HMAC (K, &T, 4, K1); + } + memcpy (K2, K1, 16); + if (export) memset (K1+7, 0xAB, 9); + + K3 = HMAC (K1, edata.Checksum); + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 7] + +Internet-Draft RC4-HMAC July 2006 + + + RC4 (K3, edata.Confounder); + RC4 (K3, edata.Data); + + + // verify generated and received checksums + checksum = HMAC (K2, concat(edata.Confounder, edata.Data)); + if (checksum != edata.Checksum) + printf("CHECKSUM ERROR !!!!!!\n"); + } + + The KDC message is encrypted using the ENCRYPT function not including + the Checksum in the RC4_MDx_HEADER. + + The character constant "fortybits" evolved from the time when a 40- + bit key length was all that was exportable from the United States. + It is now used to recognize that the key length is of "exportable" + length. In this description, the key size is actually 56-bits. + + The pseudo-random operation [RFC3961] for both enctypes above is + defined as follows: + + pseudo-random(K, S) = HMAC-SHA1(K, S) + + where K is the protocol key and S is the input octet string. HMAC- + SHA1 is defined in [RFC2104] and the output of HMAC-SHA1 is the 20- + octet digest. + + +6. Key Strength Negotiation + + A Kerberos client and server can negotiate over key length if they + are using mutual authentication. If the client is unable to perform + full strength encryption, it may propose a key in the "subkey" field + of the authenticator, using a weaker encryption type. The server + must then either return the same key or suggest its own key in the + subkey field of the AP reply message. The key used to encrypt data + is derived from the key returned by the server. If the client is + able to perform strong encryption but the server is not, it may + propose a subkey in the AP reply without first being sent a subkey in + the authenticator. + + +7. GSSAPI Kerberos V5 Mechanism Type + +7.1. Mechanism Specific Changes + + The GSSAPI per-message tokens also require new checksum and + encryption types. The GSS-API per-message tokens are adapted to + + + +Jaganathan, et al. Expires January 31, 2007 [Page 8] + +Internet-Draft RC4-HMAC July 2006 + + + support these new encryption types. See [RFC1964] Section 1.2.2. + + The only support quality of protection is: + + #define GSS_KRB5_INTEG_C_QOP_DEFAULT 0x0 + + When using this RC4 based encryption type, the sequence number is + always sent in big-endian rather than little-endian order. + + The Windows 2000 implementation also defines new GSSAPI flags in the + initial token passed when initializing a security context. These + flags are passed in the checksum field of the authenticator. See + [RFC1964] Section 1.1.1. + + GSS_C_DCE_STYLE - This flag was added for use with Microsoft's + implementation of DCE RPC, which initially expected three legs of + authentication. Setting this flag causes an extra AP reply to be + sent from the client back to the server after receiving the server's + AP reply. In addition, the context negotiation tokens do not have + GSSAPI per message tokens - they are raw AP messages that do not + include object identifiers. + + #define GSS_C_DCE_STYLE 0x1000 + + GSS_C_IDENTIFY_FLAG - This flag allows the client to indicate to the + server that it should only allow the server application to identify + the client by name and ID, but not to impersonate the client. + + #define GSS_C_IDENTIFY_FLAG 0x2000 + + GSS_C_EXTENDED_ERROR_FLAG - Setting this flag indicates that the + client wants to be informed of extended error information. In + particular, Windows 2000 status codes may be returned in the data + field of a Kerberos error message. This allows the client to + understand a server failure more precisely. In addition, the server + may return errors to the client that are normally handled at the + application layer in the server, in order to let the client try to + recover. After receiving an error message, the client may attempt to + resubmit an AP request. + + #define GSS_C_EXTENDED_ERROR_FLAG 0x4000 + + These flags are only used if a client is aware of these conventions + when using the SSPI on the Windows platform; they are not generally + used by default. + + When NetBIOS addresses are used in the GSSAPI, they are identified by + the GSS_C_AF_NETBIOS value. This value is defined as: + + + +Jaganathan, et al. Expires January 31, 2007 [Page 9] + +Internet-Draft RC4-HMAC July 2006 + + + #define GSS_C_AF_NETBIOS 0x14 + + NetBios addresses are 16-octet addresses typically composed of 1 to + 15 characters, trailing blank (ASCII char 20) filled, with a 16-th + octet of 0x0. + +7.2. GSSAPI MIC Semantics + + The GSSAPI checksum type and algorithm is defined in Section 5. Only + the first 8 octets of the checksum are used. The resulting checksum + is stored in the SGN_CKSUM field . See [RFC1964] Section 1.2 for + GSS_GetMIC() and GSS_Wrap(conf_flag=FALSE). + + The GSS_GetMIC token has the following format: + + Byte no Name Description + 0..1 TOK_ID Identification field. + Tokens emitted by GSS_GetMIC() contain + the hex value 01 01 in this field. + 2..3 SGN_ALG Integrity algorithm indicator. + 11 00 - HMAC + 4..7 Filler Contains ff ff ff ff + 8..15 SND_SEQ Sequence number field. + 16..23 SGN_CKSUM Checksum of "to-be-signed data", + calculated according to algorithm + specified in SGN_ALG field. + + The MIC mechanism used for GSS MIC based messages is as follow: + + GetMIC(Kss, direction, export, seq_num, data) + { + struct Token { + struct Header { + OCTET TOK_ID[2]; + OCTET SGN_ALG[2]; + OCTET Filler[4]; + }; + OCTET SND_SEQ[8]; + OCTET SGN_CKSUM[8]; + } Token; + + + Token.TOK_ID = 01 01; + Token.SGN_SLG = 11 00; + Token.Filler = ff ff ff ff; + + // Create the sequence number + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 10] + +Internet-Draft RC4-HMAC July 2006 + + + if (direction == sender_is_initiator) + { + memset(Token.SEND_SEQ+4, 0xff, 4) + } + else if (direction == sender_is_acceptor) + { + memset(Token.SEND_SEQ+4, 0, 4) + } + Token.SEND_SEQ[0] = (seq_num & 0xff000000) >> 24; + Token.SEND_SEQ[1] = (seq_num & 0x00ff0000) >> 16; + Token.SEND_SEQ[2] = (seq_num & 0x0000ff00) >> 8; + Token.SEND_SEQ[3] = (seq_num & 0x000000ff); + + // Derive signing key from session key + + Ksign = HMAC(Kss, "signaturekey"); + // length includes terminating null + + // Generate checksum of message - SGN_CKSUM + // Key derivation salt = 15 + + Sgn_Cksum = MD5((int32)15, Token.Header, data); + + // Save first 8 octets of HMAC Sgn_Cksum + + Sgn_Cksum = HMAC(Ksign, Sgn_Cksum); + memcpy(Token.SGN_CKSUM, Sgn_Cksum, 8); + + // Encrypt the sequence number + + // Derive encryption key for the sequence number + // Key derivation salt = 0 + + if (exportable) + { + Kseq = HMAC(Kss, "fortybits", (int32)0); + // len includes terminating null + memset(Kseq+7, 0xab, 7) + } + else + { + Kseq = HMAC(Kss, (int32)0); + } + Kseq = HMAC(Kseq, Token.SGN_CKSUM); + + // Encrypt the sequence number + + RC4(Kseq, Token.SND_SEQ); + + + +Jaganathan, et al. Expires January 31, 2007 [Page 11] + +Internet-Draft RC4-HMAC July 2006 + + + } + +7.3. GSSAPI WRAP Semantics + + There are two encryption keys for GSSAPI message tokens, one that is + 128 bits in strength, and one that is 56 bits in strength as defined + in Section 6. + + All padding is rounded up to 1 byte. One byte is needed to say that + there is 1 byte of padding. The DES based mechanism type uses 8 byte + padding. See [RFC1964] Section 1.2.2.3. + + The RC4-HMAC GSS_Wrap() token has the following format: + + + Byte no Name Description + 0..1 TOK_ID Identification field. + Tokens emitted by GSS_Wrap() contain + the hex value 02 01 in this field. + 2..3 SGN_ALG Checksum algorithm indicator. + 11 00 - HMAC + 4..5 SEAL_ALG ff ff - none + 00 00 - DES-CBC + 10 00 - RC4 + 6..7 Filler Contains ff ff + 8..15 SND_SEQ Encrypted sequence number field. + 16..23 SGN_CKSUM Checksum of plaintext padded data, + calculated according to algorithm + specified in SGN_ALG field. + 24..31 Confounder Random confounder + 32..last Data encrypted or plaintext padded data + + The encryption mechanism used for GSS wrap based messages is as + follow: + + + WRAP(Kss, encrypt, direction, export, seq_num, data) + { + struct Token { // 32 octets + struct Header { + OCTET TOK_ID[2]; + OCTET SGN_ALG[2]; + OCTET SEAL_ALG[2]; + OCTET Filler[2]; + }; + OCTET SND_SEQ[8]; + OCTET SGN_CKSUM[8]; + OCTET Confounder[8]; + + + +Jaganathan, et al. Expires January 31, 2007 [Page 12] + +Internet-Draft RC4-HMAC July 2006 + + + } Token; + + + Token.TOK_ID = 02 01; + Token.SGN_SLG = 11 00; + Token.SEAL_ALG = (no_encrypt)? ff ff : 10 00; + Token.Filler = ff ff; + + // Create the sequence number + + if (direction == sender_is_initiator) + { + memset(&Token.SEND_SEQ[4], 0xff, 4) + } + else if (direction == sender_is_acceptor) + { + memset(&Token.SEND_SEQ[4], 0, 4) + } + Token.SEND_SEQ[0] = (seq_num & 0xff000000) >> 24; + Token.SEND_SEQ[1] = (seq_num & 0x00ff0000) >> 16; + Token.SEND_SEQ[2] = (seq_num & 0x0000ff00) >> 8; + Token.SEND_SEQ[3] = (seq_num & 0x000000ff); + + // Generate random confounder + + nonce(&Token.Confounder, 8); + + // Derive signing key from session key + + Ksign = HMAC(Kss, "signaturekey"); + + // Generate checksum of message - + // SGN_CKSUM + Token.Confounder + // Key derivation salt = 15 + + Sgn_Cksum = MD5((int32)15, Token.Header, + Token.Confounder); + + // Derive encryption key for data + // Key derivation salt = 0 + + for (i = 0; i < 16; i++) Klocal[i] = Kss[i] ^ 0xF0; + // XOR + if (exportable) + { + Kcrypt = HMAC(Klocal, "fortybits", (int32)0); + // len includes terminating null + memset(Kcrypt+7, 0xab, 7); + + + +Jaganathan, et al. Expires January 31, 2007 [Page 13] + +Internet-Draft RC4-HMAC July 2006 + + + } + else + { + Kcrypt = HMAC(Klocal, (int32)0); + } + + // new encryption key salted with seq + + Kcrypt = HMAC(Kcrypt, (int32)seq); + + // Encrypt confounder (if encrypting) + + if (encrypt) + RC4(Kcrypt, Token.Confounder); + + // Sum the data buffer + + Sgn_Cksum += MD5(data); // Append to checksum + + // Encrypt the data (if encrypting) + + if (encrypt) + RC4(Kcrypt, data); + + // Save first 8 octets of HMAC Sgn_Cksum + + Sgn_Cksum = HMAC(Ksign, Sgn_Cksum); + memcpy(Token.SGN_CKSUM, Sgn_Cksum, 8); + + // Derive encryption key for the sequence number + // Key derivation salt = 0 + + if (exportable) + { + Kseq = HMAC(Kss, "fortybits", (int32)0); + // len includes terminating null + memset(Kseq+7, 0xab, 7) + } + else + { + Kseq = HMAC(Kss, (int32)0); + } + Kseq = HMAC(Kseq, Token.SGN_CKSUM); + + // Encrypt the sequence number + + RC4(Kseq, Token.SND_SEQ); + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 14] + +Internet-Draft RC4-HMAC July 2006 + + + // Encrypted message = Token + Data + } + + The character constant "fortybits" evolved from the time when a 40- + bit key length was all that was exportable from the United States. + It is now used to recognize that the key length is of "exportable" + length. In this description, the key size is actually 56-bits. + + +8. Security Considerations + + Care must be taken in implementing these encryption types because + they use a stream cipher. If a different IV is not used in each + direction when using a session key, the encryption is weak. By using + the sequence number as an IV, this is avoided. + + There are two classes of attack on RC4 described in [MIRONOV]. + Strong distinguishers distinguish an RC4 keystream from randomness at + the start of the stream. Weak distinguishers can operate on any part + of the keystream, and the best ones, described in [FMcG] and + [MANTIN05], can exploit data from multiple, different keystreams. A + consequence of these is that encrypting the same data (for instance, + a password) sufficiently many times in separate RC4 keystreams can be + sufficient to leak information to an adversary. The encryption types + defined in this document defend against these by constructing a new + key stream for every message. However, it is RECOMMENDED not to use + the RC4 encryption types defined in this document for high-volume + connections. + + Weaknesses in MD4 [BOER91] were demonstrated by Den Boer and + Bosselaers in 1991. In August 2004, Xiaoyun Wang et al reported MD4 + collisions generated using hand calculation [WANG04]. + Implementations based on Wang's algorithm can find collisions in real + time. However, the intended usage of MD4 described in this document + does not rely on the collision-resistant property of MD4. + Futhermore, MD4 is always used in the context of a keyed hash in this + document. Although no evidence has suggested keyed MD4 hashes are + vulnerable to collision-based attacks, no study has directly proved + that the HMAC-MD4 is secure: the existing study simply assumed that + the hash function used in HMAC is collision proof. It is thus + RECOMMENDED not to use the RC4 encryption types defined in this + document if alternative stronger encryption types, such as aes256- + cts-hmac-sha1-96 [RFC3962], are available. + + +9. Acknowledgements + + The authors wish to thank Sam Hartman, Ken Raeburn and Qunli Li for + + + +Jaganathan, et al. Expires January 31, 2007 [Page 15] + +Internet-Draft RC4-HMAC July 2006 + + + their insightful comments. + + +10. IANA Considerations + + This document has no actions for IANA. + + +11. References + +11.1. Normative References + + [RFC1320] Rivest, R., "The MD4 Message-Digest Algorithm", RFC 1320, + April 1992. + + [RFC1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, + April 1992. + + [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", + RFC 1964, June 1996. + + [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- + Hashing for Message Authentication", RFC 2104, + February 1997. + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC3961] Raeburn, K., "Encryption and Checksum Specifications for + Kerberos 5", RFC 3961, February 2005. + + [RFC3962] Raeburn, K., "Advanced Encryption Standard (AES) + Encryption for Kerberos 5", RFC 3962, February 2005. + + [RFC4120] Neuman, C., Yu, T., Hartman, S., and K. Raeburn, "The + Kerberos Network Authentication Service (V5)", RFC 4120, + July 2005. + +11.2. Informative References + + +Jaganathan, et al. Expires January 31, 2007 [Page 16] + +Internet-Draft RC4-HMAC July 2006 + + + [BOER91] Boer, D. and A. Bosselaers, "An Attack on the Last Two + Rounds of MD4", + http://citeseer.ist.psu.edu/denboer91attack.html, 1991. + + [FMcG] Fluhrer, S. and D. McGrew, "Statistical Analysis of the + Alleged RC4 Keystream Generator", Fast Software + Encryption: 7th International Workshop, FSE 2000, April + 2000, . + + [MANTIN01] Mantin, I., "Analysis of the Stream Cipher RC4", M.Sc. + Thesis, Weizmann Institute of Science, 2001, . + + [MIRONOV] Mironov, I., "(Not So) Random Shuffles of RC4", Advances + in Cryptology -- CRYPTO 2002: 22nd Annual International + Cryptology Conference, August 2002, + . + + [MANTIN05] Mantin, I., "Predicting and Distinguishing Attacks on RC4 + Keystream Generator", Advances in Cryptology -- EUROCRYPT + 2005: 24th Annual International Conference on the Theory + and Applications of Cryptographic Techniques, May 2005. + + [WANG04] Wang, X., Lai, X., Feng, D., Chen H., and X. Yu, + "Cryptanalysis of Hash functions MD4 and RIPEMD", + http://www.infosec.sdu.edu.cn/paper/md4-ripemd-attck.pdf, + Augest, 2004. + + + +Authors' Addresses + + Karthik Jaganathan + Microsoft Corporation + One Microsoft Way + Redmond, WA 98052 + US + + Email: karthikj@microsoft.com + + + Larry Zhu + Microsoft Corporation + One Microsoft Way + Redmond, WA 98052 + US + + Email: lzhu@microsoft.com + + + John Brezak + Microsoft Corporation + One Microsoft Way + Redmond, WA 98052 + US + + Email: jbrezak@microsoft.com + + + + + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 17] + +Internet-Draft RC4-HMAC July 2006 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2006). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at + ietf-ipr@ietf.org. + + +Acknowledgment + + Funding for the RFC Editor function is provided by the IETF + Administrative Support Activity (IASA). + + + + + +Jaganathan, et al. Expires January 31, 2007 [Page 18] + + diff --git a/krb5-1-6/doc/krb5-protocol/krb5.constants b/krb5-1-6/doc/krb5-protocol/krb5.constants new file mode 100644 index 000000000..e7cc5b80e --- /dev/null +++ b/krb5-1-6/doc/krb5-protocol/krb5.constants @@ -0,0 +1,156 @@ +8.3. Protocol constants and associated values + + The following tables list constants used in the protocol and defines + their meanings. + + +---------------+-----------+----------+----------------+--------------- +Encryption type|etype value|block size|minimum pad size|confounder size +---------------+-----------+----------+----------------+--------------- +NULL 0 1 0 0 +des-cbc-crc 1 8 4 8 +des-cbc-md4 2 8 0 8 +des-cbc-md5 3 8 0 8 + 4 +des3-cbc-md5 5 8 0 8 + 6 +des3-cbc-sha1 7 8 0 8 + 0x8003 + +-------------------------------+-------------------+------------- +Checksum type |sumtype value |checksum size +-------------------------------+-------------------+------------- +CRC32 1 4 +rsa-md4 2 16 +rsa-md4-des 3 24 +des-mac 4 16 +des-mac-k 5 8 +rsa-md4-des-k 6 16 +rsa-md5 7 16 +rsa-md5-des 8 24 + 9 + 10 +nist-sha1 11 20 +hmac-sha1-des3 12 20 + +-------------------------------+----------------- +padata type |padata-type value +-------------------------------+----------------- +PA-TGS-REQ 1 +PA-ENC-TIMESTAMP 2 +PA-PW-SALT 3 + 4 +PA-ENC-UNIX-TIME 5 +PA-SANDIA-SECUREID 6 +PA-SESAME 7 +PA-OSF-DCE 8 +PA-CYBERSAFE-SECUREID 9 +PA-AFS3-SALT 10 +PA-ETYPE-INFO 11 +PAM-SAM-CHALLENGE 12 +PAM-SAM-RESPONSE 13 + +-------------------------------+------------- +authorization data type |ad-type value +-------------------------------+------------- +reserved values 0-63 +AD-OSF-DCE 64 +AD-SESAME 65 + +-------------------------------+----------------- +alternate authentication type |method-type value +-------------------------------+----------------- +reserved values 0-63 +ATT-CHALLENGE-RESPONSE 64 + +-------------------------------+------------- +transited encoding type |tr-type value +-------------------------------+------------- +DOMAIN-X500-COMPRESS 1 +reserved values all others + + +--------------+-------+----------------------------------------- +Label |Value |Meaning or MIT code +--------------+-------+----------------------------------------- + +pvno 5 current Kerberos protocol version number + +message types + +KRB_AS_REQ 10 Request for initial authentication +KRB_AS_REP 11 Response to KRB_AS_REQ request +KRB_TGS_REQ 12 Request for authentication based on TGT +KRB_TGS_REP 13 Response to KRB_TGS_REQ request +KRB_AP_REQ 14 application request to server +KRB_AP_REP 15 Response to KRB_AP_REQ_MUTUAL +KRB_SAFE 20 Safe (checksummed) application message +KRB_PRIV 21 Private (encrypted) application message +KRB_CRED 22 Private (encrypted) message to forward credentials +KRB_ERROR 30 Error response + +name types + +KRB_NT_UNKNOWN 0 Name type not known +KRB_NT_PRINCIPAL 1 Just the name of the principal as in DCE, or for users +KRB_NT_SRV_INST 2 Service and other unique instance (krbtgt) +KRB_NT_SRV_HST 3 Service with host name as instance (telnet, rcommands) +KRB_NT_SRV_XHST 4 Service with host as remaining components +KRB_NT_UID 5 Unique ID + +error codes + +KDC_ERR_NONE 0 No error +KDC_ERR_NAME_EXP 1 Client's entry in database has expired +KDC_ERR_SERVICE_EXP 2 Server's entry in database has expired +KDC_ERR_BAD_PVNO 3 Requested protocol version # not supported +KDC_ERR_C_OLD_MAST_KVNO 4 Client's key encrypted in old master key +KDC_ERR_S_OLD_MAST_KVNO 5 Server's key encrypted in old master key +KDC_ERR_C_PRINCIPAL_UNKNOWN 6 Client not found in Kerberos database +KDC_ERR_S_PRINCIPAL_UNKNOWN 7 Server not found in Kerberos database +KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 Multiple principal entries in database +KDC_ERR_NULL_KEY 9 The client or server has a null key +KDC_ERR_CANNOT_POSTDATE 10 Ticket not eligible for postdating +KDC_ERR_NEVER_VALID 11 Requested start time is later than end time +KDC_ERR_POLICY 12 KDC policy rejects request +KDC_ERR_BADOPTION 13 KDC cannot accommodate requested option +KDC_ERR_ETYPE_NOSUPP 14 KDC has no support for encryption type +KDC_ERR_SUMTYPE_NOSUPP 15 KDC has no support for checksum type +KDC_ERR_PADATA_TYPE_NOSUPP 16 KDC has no support for padata type +KDC_ERR_TRTYPE_NOSUPP 17 KDC has no support for transited type +KDC_ERR_CLIENT_REVOKED 18 Clients credentials have been revoked +KDC_ERR_SERVICE_REVOKED 19 Credentials for server have been revoked +KDC_ERR_TGT_REVOKED 20 TGT has been revoked +KDC_ERR_CLIENT_NOTYET 21 Client not yet valid - try again later +KDC_ERR_SERVICE_NOTYET 22 Server not yet valid - try again later +KDC_ERR_KEY_EXPIRED 23 Password has expired - change to reset +KDC_ERR_PREAUTH_FAILED 24 Pre-authentication information was invalid +KDC_ERR_PREAUTH_REQUIRED 25 Additional pre-authentication required* +KDC_ERR_SERVER_NOMATCH 26 Requested server and ticket don't match +KDC_ERR_MUST_USE_USER2USER 27 Server principal valid for user2user only +KRB_AP_ERR_BAD_INTEGRITY 31 Integrity check on decrypted field failed +KRB_AP_ERR_TKT_EXPIRED 32 Ticket expired +KRB_AP_ERR_TKT_NYV 33 Ticket not yet valid +KRB_AP_ERR_REPEAT 34 Request is a replay +KRB_AP_ERR_NOT_US 35 The ticket isn't for us +KRB_AP_ERR_BADMATCH 36 Ticket and authenticator don't match +KRB_AP_ERR_SKEW 37 Clock skew too great +KRB_AP_ERR_BADADDR 38 Incorrect net address +KRB_AP_ERR_BADVERSION 39 Protocol version mismatch +KRB_AP_ERR_MSG_TYPE 40 Invalid msg type +KRB_AP_ERR_MODIFIED 41 Message stream modified +KRB_AP_ERR_BADORDER 42 Message out of order +KRB_AP_ERR_BADKEYVER 44 Specified version of key is not available +KRB_AP_ERR_NOKEY 45 Service key not available +KRB_AP_ERR_MUT_FAIL 46 Mutual authentication failed +KRB_AP_ERR_BADDIRECTION 47 Incorrect message direction +KRB_AP_ERR_METHOD 48 Alternative authentication method required* +KRB_AP_ERR_BADSEQ 49 Incorrect sequence number in message +KRB_AP_ERR_INAPP_CKSUM 50 Inappropriate type of checksum in message +KRB_ERR_GENERIC 60 Generic error (description in e-text) +KRB_ERR_FIELD_TOOLONG 61 Field is too long for this implementation + + *This error carries additional information in the e-data field. The + contents of the e-data field for this message is described in section + 5.9.1. + diff --git a/krb5-1-6/doc/krb5-protocol/rfc3961.txt b/krb5-1-6/doc/krb5-protocol/rfc3961.txt new file mode 100644 index 000000000..0ac50b959 --- /dev/null +++ b/krb5-1-6/doc/krb5-protocol/rfc3961.txt @@ -0,0 +1,2803 @@ + + + + + + +Network Working Group K. Raeburn +Request for Comments: 3961 MIT +Category: Standards Track February 2005 + + + Encryption and Checksum Specifications + for Kerberos 5 + +Status of This Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2005). + +Abstract + + This document describes a framework for defining encryption and + checksum mechanisms for use with the Kerberos protocol, defining an + abstraction layer between the Kerberos protocol and related + protocols, and the actual mechanisms themselves. The document also + defines several mechanisms. Some are taken from RFC 1510, modified + in form to fit this new framework and occasionally modified in + content when the old specification was incorrect. New mechanisms are + presented here as well. This document does NOT indicate which + mechanisms may be considered "required to implement". + +Table of Contents + + 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 + 2. Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . 2 + 3. Encryption Algorithm Profile . . . . . . . . . . . . . . . . 4 + 4. Checksum Algorithm Profile . . . . . . . . . . . . . . . . . 9 + 5. Simplified Profile for CBC Ciphers with Key Derivation . . . 10 + 5.1. A Key Derivation Function . . . . . . . . . . . . . . . 10 + 5.2. Simplified Profile Parameters . . . . . . . . . . . . . 12 + 5.3. Cryptosystem Profile Based on Simplified Profile . . . 13 + 5.4. Checksum Profiles Based on Simplified Profile . . . . . 16 + 6. Profiles for Kerberos Encryption and Checksum Algorithms . . 16 + 6.1. Unkeyed Checksums . . . . . . . . . . . . . . . . . . . 17 + 6.2. DES-based Encryption and Checksum Types . . . . . . . . 18 + 6.3. Triple-DES Based Encryption and Checksum Types . . . . 28 + 7. Use of Kerberos Encryption Outside This Specification . . . . 30 + + + +Raeburn Standards Track [Page 1] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + 8. Assigned Numbers . . . . . . . . . . . . . . . . . . . . . . 31 + 9. Implementation Notes . . . . . . . . . . . . . . . . . . . . 32 + 10. Security Considerations . . . . . . . . . . . . . . . . . . . 33 + 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 35 + 12. Acknowledgements. . . . . . . . . . . . . . . . . . . . . . . 36 + A. Test vectors . . . . . . . . . . . . . . . . . . . . . . . . 38 + A.1. n-fold . . . . . . . . . . . . . . . . . . . . . . . . 38 + A.2. mit_des_string_to_key . . . . . . . . . . . . . . . . . 39 + A.3. DES3 DR and DK . . . . . . . . . . . . . . . . . . . . 43 + A.4. DES3string_to_key . . . . . . . . . . . . . . . . . . . 44 + A.5. Modified CRC-32 . . . . . . . . . . . . . . . . . . . . 44 + B. Significant Changes from RFC 1510 . . . . . . . . . . . . . . 45 + Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 + Normative References. . . . . . . . . . . . . . . . . . . . . . . 47 + Informative References. . . . . . . . . . . . . . . . . . . . . . 48 + Editor's Address. . . . . . . . . . . . . . . . . . . . . . . . . 49 + Full Copyright Statement. . . . . . . . . . . . . . . . . . . . . 50 + +1. Introduction + + The Kerberos protocols [Kerb] are designed to encrypt messages of + arbitrary sizes, using block encryption ciphers or, less commonly, + stream encryption ciphers. Encryption is used to prove the + identities of the network entities participating in message + exchanges. However, nothing in the Kerberos protocol requires that + any specific encryption algorithm be used, as long as the algorithm + includes certain operations. + + The following sections specify the encryption and checksum mechanisms + currently defined for Kerberos, as well as a framework for defining + future mechanisms. The encoding, chaining, padding, and other + requirements for each are described. Appendix A gives test vectors + for several functions. + +2. Concepts + + Both encryption and checksum mechanisms are profiled in later + sections. Each profile specifies a collection of operations and + attributes that must be defined for a mechanism. A Kerberos + encryption or checksum mechanism specification is not complete if it + does not define all of these operations and attributes. + + An encryption mechanism must provide for confidentiality and + integrity of the original plaintext. (Incorporating a checksum may + permit integrity checking, if the encryption mode does not provide an + integrity check itself.) It must also provide non-malleability + + + + + +Raeburn Standards Track [Page 2] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + [Bellare98] [Dolev91]. Use of a random confounder prepended to the + plaintext is recommended. It should not be possible to determine if + two ciphertexts correspond to the same plaintext without the key. + + A checksum mechanism [1] must provide proof of the integrity of the + associated message and must preserve the confidentiality of the + message in case it is not sent in the clear. Finding two plaintexts + with the same checksum should be infeasible. It is NOT required that + an eavesdropper be unable to determine whether two checksums are for + the same message, as the messages themselves would presumably be + visible to any such eavesdropper. + + Due to advances in cryptography, some cryptographers consider using + the same key for multiple purposes unwise. Since keys are used in + performing a number of different functions in Kerberos, it is + desirable to use different keys for each of these purposes, even + though we start with a single long-term or session key. + + We do this by enumerating the different uses of keys within Kerberos + and by making the "usage number" an input to the encryption or + checksum mechanisms; such enumeration is outside the scope of this + document. Later sections define simplified profile templates for + encryption and checksum mechanisms that use a key derivation function + applied to a CBC mode (or similar) cipher and a checksum or hash + algorithm. + + We distinguish the "base key" specified by other documents from the + "specific key" for a specific encryption or checksum operation. It + is expected but not required that the specific key be one or more + separate keys derived from the original protocol key and the key + usage number. The specific key should not be explicitly referenced + outside of this document. The typical language used in other + documents should be something like, "encrypt this octet string using + this key and this usage number"; generation of the specific key and + cipher state (described in the next section) are implicit. The + creation of a new cipher-state object, or the re-use of one from a + previous encryption operation, may also be explicit. + + New protocols defined in terms of the Kerberos encryption and + checksum types should use their own key usage values. Key usages are + unsigned 32-bit integers; zero is not permitted. + + All data is assumed to be in the form of strings of octets or eight- + bit bytes. Environments with other byte sizes will have to emulate + this behavior in order to get correct results. + + + + + + +Raeburn Standards Track [Page 3] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + Each algorithm is assigned an encryption type (or "etype") or + checksum type number, for algorithm identification within the + Kerberos protocol. The full list of current type number assignments + is given in section 8. + +3. Encryption Algorithm Profile + + An encryption mechanism profile must define the following attributes + and operations. The operations must be defined as functions in the + mathematical sense. No additional or implicit inputs (such as + Kerberos principal names or message sequence numbers) are permitted. + + protocol key format + This describes which octet string values represent valid keys. + For encryption mechanisms that don't have perfectly dense key + spaces, this will describe the representation used for encoding + keys. It need not describe invalid specific values; all key + generation routines should avoid such values. + + specific key structure + This is not a protocol format at all, but a description of the + keying material derived from the chosen key and used to encrypt or + decrypt data or compute or verify a checksum. It may, for + example, be a single key, a set of keys, or a combination of the + original key with additional data. The authors recommend using + one or more keys derived from the original key via one-way key + derivation functions. + + required checksum mechanism + This indicates a checksum mechanism that must be available when + this encryption mechanism is used. Since Kerberos has no built in + mechanism for negotiating checksum mechanisms, once an encryption + mechanism is decided, the corresponding checksum mechanism can be + used. + + key-generation seed length, K + This is the length of the random bitstring needed to generate a + key with the encryption scheme's random-to-key function (described + below). This must be a fixed value so that various techniques for + producing a random bitstring of a given length may be used with + key generation functions. + + key generation functions + Keys must be generated in a number of cases, from different types + of inputs. All function specifications must indicate how to + generate keys in the proper wire format and must avoid generating + keys that significantly compromise the confidentiality of + encrypted data, if the cryptosystem has such. Entropy from each + + + +Raeburn Standards Track [Page 4] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + source should be preserved as much as possible. Many of the + inputs, although unknown, may be at least partly predictable + (e.g., a password string is likely to be entirely in the ASCII + subset and of fairly short length in many environments; a semi- + random string may include time stamps). The benefit of such + predictability to an attacker must be minimized. + + string-to-key (UTF-8 string, UTF-8 string, opaque)->(protocol-key) + This function generates a key from two UTF-8 strings and an opaque + octet string. One of the strings is usually the principal's pass + phrase, but generally it is merely a secret string. The other + string is a "salt" string intended to produce different keys from + the same password for different users or realms. Although the + strings provided will use UTF-8 encoding, no specific version of + Unicode should be assumed; all valid UTF-8 strings should be + allowed. Strings provided in other encodings MUST first be + converted to UTF-8 before applying this function. + + The third argument, the octet string, may be used to pass + mechanism-specific parameters into this function. Since doing so + implies knowledge of the specific encryption system, generating + non-default parameter values should be an uncommon operation, and + normal Kerberos applications should be able to treat this + parameter block as an opaque object supplied by the Key + Distribution Center or defaulted to some mechanism-specific + constant value. + + The string-to-key function should be a one-way function so that + compromising a user's key in one realm does not compromise it in + another, even if the same password (but a different salt) is used. + + random-to-key (bitstring[K])->(protocol-key) + This function generates a key from a random bitstring of a + specific size. All the bits of the input string are assumed to be + equally random, even though the entropy present in the random + source may be limited. + + key-derivation (protocol-key, integer)->(specific-key) + In this function, the integer input is the key usage value, as + described above. An attacker is assumed to know the usage values. + The specific-key output value was described in section 2. + + string-to-key parameter format + This describes the format of the block of data that can be passed + to the string-to-key function above to configure additional + parameters for that function. Along with the mechanism of + encoding parameter values, bounds on the allowed parameters should + also be described to avoid allowing a spoofed KDC to compromise + + + +Raeburn Standards Track [Page 5] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + the user's password. If practical it may be desirable to + construct the encoding so that values unacceptably weakening the + resulting key cannot be encoded. + + Local security policy might permit tighter bounds to avoid excess + resource consumption. If so, the specification should recommended + defaults for these bounds. The description should also outline + possible weaknesses if bounds checks or other validations are not + applied to a parameter string received from the network. + + As mentioned above, this should be considered opaque to most + normal applications. + + default string-to-key parameters (octet string) + This default value for the "params" argument to the string-to-key + function should be used when the application protocol (Kerberos or + other) does not explicitly set the parameter value. As indicated + above, in most cases this parameter block should be treated as an + opaque object. + + cipher state + This describes any information that can be carried over from one + encryption or decryption operation to the next, for use with a + given specific key. For example, a block cipher used in CBC mode + may put an initial vector of one block in the cipher state. Other + encryption modes may track nonces or other data. + + This state must be non-empty and must influence encryption so that + messages are decrypted in the same order they were a encrypted, if + the cipher state is carried over from one encryption to the next. + Distinguishing out-of-order or missing messages from corrupted + messages is not required. If desired, this can be done at a + higher level by including sequence numbers and not "chaining" the + cipher state between encryption operations. + + The cipher state may not be reused in multiple encryption or + decryption operations. These operations all generate a new cipher + state that may be used for following operations using the same key + and operation. + + The contents of the cipher state must be treated as opaque outside + of encryption system specifications. + + initial cipher state (specific-key, direction)->(state) + This describes the generation of the initial value for the cipher + state if it is not being carried over from a previous encryption + or decryption operation. + + + + +Raeburn Standards Track [Page 6] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + This describes any initial state setup needed before encrypting + arbitrary amounts of data with a given specific key. The specific + key and the direction of operations to be performed (encrypt + versus decrypt) must be the only input needed for this + initialization. + + This state should be treated as opaque in any uses outside of an + encryption algorithm definition. + + IMPLEMENTATION NOTE: [Kerb1510] was vague on whether and to what + degree an application protocol could exercise control over the + initial vector used in DES CBC operations. Some existing + implementations permit setting the initial vector. This framework + does not provide for application control of the cipher state + (beyond "initialize" and "carry over from previous encryption"), + as the form and content of the initial cipher state can vary + between encryption systems and may not always be a single block of + random data. + + New Kerberos application protocols should not assume control over + the initial vector, or that one even exists. However, a general- + purpose implementation may wish to provide the capability, in case + applications explicitly setting it are encountered. + + encrypt (specific-key, state, octet string)->(state, octet string) + This function takes the specific key, cipher state, and a non- + empty plaintext string as input and generates ciphertext and a new + cipher state as outputs. If the basic encryption algorithm itself + does not provide for integrity protection (e.g., DES in CBC mode), + then some form of verifiable MAC or checksum must be included. + Some random factor such as a confounder should be included so that + an observer cannot know if two messages contain the same + plaintext, even if the cipher state and specific keys are the + same. The exact length of the plaintext need not be encoded, but + if it is not and if padding is required, the padding must be added + at the end of the string so that the decrypted version may be + parsed from the beginning. + + The specification of the encryption function must indicate not + only the precise contents of the output octet string, but also the + output cipher state. The application protocol may carry the + output cipher state forward from one encryption with a given + specific key to another; the effect of this "chaining" must be + defined [2]. + + Assuming that values for the specific key and cipher state are + correctly-produced, no input octet string may result in an error + indication. + + + +Raeburn Standards Track [Page 7] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + decrypt (specific-key, state, octet string)->(state, octet string) + This function takes the specific key, cipher state, and ciphertext + as inputs and verifies the integrity of the supplied ciphertext. + If the ciphertext's integrity is intact, this function produces + the plaintext and a new cipher state as outputs; otherwise, an + error indication must be returned, and the data discarded. + + The result of the decryption may be longer than the original + plaintext, as, for example, when the encryption mode adds padding + to reach a multiple of a block size. If this is the case, any + extra octets must come after the decoded plaintext. An + application protocol that needs to know the exact length of the + message must encode a length or recognizable "end of message" + marker within the plaintext [3]. + + As with the encryption function, a correct specification for this + function must indicate not only the contents of the output octet + string, but also the resulting cipher state. + + pseudo-random (protocol-key, octet-string)->(octet-string) + This pseudo-random function should generate an octet string of + some size that is independent of the octet string input. The PRF + output string should be suitable for use in key generation, even + if the octet string input is public. It should not reveal the + input key, even if the output is made public. + + These operations and attributes are all that is required to support + Kerberos and various proposed preauthentication schemes. + + For convenience of certain application protocols that may wish to use + the encryption profile, we add the constraint that, for any given + plaintext input size, a message size must exist between that given + size and that size plus 65,535 such that the length of the decrypted + version of the ciphertext will never have extra octets at the end. + + Expressed mathematically, for every message length L1, there exists a + message size L2 such that + + L2 >= L1 + L2 < L1 + 65,536 + for every message M with |M| = L2, decrypt(encrypt(M)) = M + + A document defining a new encryption type should also describe known + weaknesses or attacks, so that its security may be fairly assessed, + and should include test vectors or other validation procedures for + the operations defined. Specific references to information that is + readily available elsewhere are sufficient. + + + + +Raeburn Standards Track [Page 8] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + +4. Checksum Algorithm Profile + + A checksum mechanism profile must define the following attributes and + operations: + + associated encryption algorithm(s) + This indicates the types of encryption keys this checksum + mechanism can be used with. + + A keyed checksum mechanism may have more than one associated + encryption algorithm if they share the same wire-key format, + string-to-key function, default string-to-key-parameters, and key + derivation function. (This combination means that, for example, a + checksum type, key usage value, and password are adequate to get + the specific key used to compute a checksum.) + + An unkeyed checksum mechanism can be used with any encryption + type, as the key is ignored, but its use must be limited to cases + where the checksum itself is protected, to avoid trivial attacks. + + get_mic function + This function generates a MIC token for a given specific key (see + section 3) and message (represented as an octet string) that may + be used to verify the integrity of the associated message. This + function is not required to return the same deterministic result + for each use; it need only generate a token that the verify_mic + routine can check. + + The output of this function will also dictate the size of the + checksum. It must be no larger than 65,535 octets. + + verify_mic function + Given a specific key, message, and MIC token, this function + ascertains whether the message integrity has been compromised. + For a deterministic get_mic routine, the corresponding verify_mic + may simply generate another checksum and compare the two. + + The get_mic and verify_mic operations must allow inputs of arbitrary + length; if any padding is needed, the padding scheme must be + specified as part of these functions. + + These operations and attributes are all that should be required to + support Kerberos and various proposed preauthentication schemes. + + As with encryption mechanism definition documents, documents defining + new checksum mechanisms should indicate validation processes and + known weaknesses. + + + + +Raeburn Standards Track [Page 9] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + +5. Simplified Profile for CBC Ciphers with Key Derivation + + The profile outlined in sections 3 and 4 describes a large number of + operations that must be defined for encryption and checksum + algorithms to be used with Kerberos. Here we describe a simpler + profile that can generate both encryption and checksum mechanism + definitions, filling in uses of key derivation in appropriate places, + providing integrity protection, and defining multiple operations for + the cryptosystem profile based on a smaller set of operations. Not + all of the existing cryptosystems for Kerberos fit into this + simplified profile, but we recommend that future cryptosystems use it + or something based on it [4]. + + Not all the operations in the complete profiles are defined through + this mechanism; several must still be defined for each new algorithm + pair. + +5.1. A Key Derivation Function + + Rather than define some scheme by which a "protocol key" is composed + of a large number of encryption keys, we use keys derived from a base + key to perform cryptographic operations. The base key must be used + only for generating the derived keys, and this derivation must be + non-invertible and entropy preserving. Given these restrictions, + compromise of one derived key does not compromise others. Attack of + the base key is limited, as it is only used for derivation and is not + exposed to any user data. + + To generate a derived key from a base key, we generate a pseudorandom + octet string by using an algorithm DR, described below, and generate + a key from that octet string by using a function dependent on the + encryption algorithm. The input length needed for that function, + which is also dependent on the encryption algorithm, dictates the + length of the string to be generated by the DR algorithm (the value + "k" below). These procedures are based on the key derivation in + [Blumenthal96]. + + Derived Key = DK(Base Key, Well-Known Constant) + + DK(Key, Constant) = random-to-key(DR(Key, Constant)) + + DR(Key, Constant) = k-truncate(E(Key, Constant, + initial-cipher-state)) + + Here DR is the random-octet generation function described below, and + DK is the key-derivation function produced from it. In this + construction, E(Key, Plaintext, CipherState) is a cipher, Constant is + a well-known constant determined by the specific usage of this + + + +Raeburn Standards Track [Page 10] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + function, and k-truncate truncates its argument by taking the first k + bits. Here, k is the key generation seed length needed for the + encryption system. + + The output of the DR function is a string of bits; the actual key is + produced by applying the cryptosystem's random-to-key operation on + this bitstring. + + If the Constant is smaller than the cipher block size of E, then it + must be expanded with n-fold() so it can be encrypted. If the output + of E is shorter than k bits, it is fed back into the encryption as + many times as necessary. The construct is as follows (where | + indicates concatentation): + + K1 = E(Key, n-fold(Constant), initial-cipher-state) + K2 = E(Key, K1, initial-cipher-state) + K3 = E(Key, K2, initial-cipher-state) + K4 = ... + + DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...) + + n-fold is an algorithm that takes m input bits and "stretches" them + to form n output bits with equal contribution from each input bit to + the output, as described in [Blumenthal96]: + + We first define a primitive called n-folding, which takes a + variable-length input block and produces a fixed-length output + sequence. The intent is to give each input bit approximately + equal weight in determining the value of each output bit. Note + that whenever we need to treat a string of octets as a number, the + assumed representation is Big-Endian -- Most Significant Byte + first. + + To n-fold a number X, replicate the input value to a length that + is the least common multiple of n and the length of X. Before + each repetition, the input is rotated to the right by 13 bit + positions. The successive n-bit chunks are added together using + 1's-complement addition (that is, with end-around carry) to yield + a n-bit result.... + + Test vectors for n-fold are supplied in appendix A [5]. + + In this section, n-fold is always used to produce c bits of output, + where c is the cipher block size of E. + + The size of the Constant must not be larger than c, because reducing + the length of the Constant by n-folding can cause collisions. + + + + +Raeburn Standards Track [Page 11] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + If the size of the Constant is smaller than c, then the Constant must + be n-folded to length c. This string is used as input to E. If the + block size of E is less than the random-to-key input size, then the + output from E is taken as input to a second invocation of E. This + process is repeated until the number of bits accumulated is greater + than or equal to the random-to-key input size. When enough bits have + been computed, the first k are taken as the random data used to + create the key with the algorithm-dependent random-to-key function. + + As the derived key is the result of one or more encryptions in the + base key, deriving the base key from the derived key is equivalent to + determining the key from a very small number of plaintext/ciphertext + pairs. Thus, this construction is as strong as the cryptosystem + itself. + +5.2. Simplified Profile Parameters + + These are the operations and attributes that must be defined: + + protocol key format + string-to-key function + default string-to-key parameters + key-generation seed length, k + random-to-key function + As above for the normal encryption mechanism profile. + + unkeyed hash algorithm, H + This should be a collision-resistant hash algorithm with fixed- + size output, suitable for use in an HMAC [HMAC]. It must support + inputs of arbitrary length. Its output must be at least the + message block size (below). + + HMAC output size, h + This indicates the size of the leading substring output by the + HMAC function that should be used in transmitted messages. It + should be at least half the output size of the hash function H, + and at least 80 bits; it need not match the output size. + + message block size, m + This is the size of the smallest units the cipher can handle in + the mode in which it is being used. Messages will be padded to a + multiple of this size. If a block cipher is used in a mode that + + + + + + + + + +Raeburn Standards Track [Page 12] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + can handle messages that are not multiples of the cipher block + size, such as CBC mode with cipher text stealing (CTS, see [RC5]), + this value would be one octet. For traditional CBC mode with + padding, it would be the underlying cipher's block size. + + This value must be a multiple of eight bits (one octet). + + encryption/decryption functions, E and D + These are basic encryption and decryption functions for messages + of sizes that are multiples of the message block size. No + integrity checking or confounder should be included here. For + inputs these functions take the IV or similar data, a protocol- + format key, and an octet string, returning a new IV and octet + string. + + The encryption function is not required to use CBC mode but is + assumed to be using something with similar properties. In + particular, prepending a cipher block-size confounder to the + plaintext should alter the entire ciphertext (comparable to + choosing and including a random initial vector for CBC mode). + + The result of encrypting one cipher block (of size c, above) must + be deterministic for the random octet generation function DR in + the previous section to work. For best security, it should also + be no larger than c. + + cipher block size, c + This is the block size of the block cipher underlying the + encryption and decryption functions indicated above, used for key + derivation and for the size of the message confounder and initial + vector. (If a block cipher is not in use, some comparable + parameter should be determined.) It must be at least 5 octets. + + This is not actually an independent parameter; rather, it is a + property of the functions E and D. It is listed here to clarify + the distinction between it and the message block size, m. + + Although there are still a number of properties to specify, they are + fewer and simpler than in the full profile. + +5.3. Cryptosystem Profile Based on Simplified Profile + + The above key derivation function is used to produce three + intermediate keys. One is used for computing checksums of + unencrypted data. The other two are used for encrypting and + checksumming plaintext to be sent encrypted. + + + + + +Raeburn Standards Track [Page 13] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + The ciphertext output is the concatenation of the output of the basic + encryption function E and a (possibly truncated) HMAC using the + specified hash function H, both applied to the plaintext with a + random confounder prefix and sufficient padding to bring it to a + multiple of the message block size. When the HMAC is computed, the + key is used in the protocol key form. + + Decryption is performed by removing the (partial) HMAC, decrypting + the remainder, and verifying the HMAC. The cipher state is an + initial vector, initialized to zero. + + The substring notation "[1..h]" in the following table should be read + as using 1-based indexing; leading substrings are used. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Raeburn Standards Track [Page 14] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + Cryptosystem from Simplified Profile +------------------------------------------------------------------------ +protocol key format As given. + +specific key structure Three protocol-format keys: { Kc, Ke, Ki }. + +key-generation seed As given. +length + +required checksum As defined below in section 5.4. +mechanism + +cipher state Initial vector (usually of length c) + +initial cipher state All bits zero + +encryption function conf = Random string of length c + pad = Shortest string to bring confounder + and plaintext to a length that's a + multiple of m. + (C1, newIV) = E(Ke, conf | plaintext | pad, + oldstate.ivec) + H1 = HMAC(Ki, conf | plaintext | pad) + ciphertext = C1 | H1[1..h] + newstate.ivec = newIV + +decryption function (C1,H1) = ciphertext + (P1, newIV) = D(Ke, C1, oldstate.ivec) + if (H1 != HMAC(Ki, P1)[1..h]) + report error + newstate.ivec = newIV + +default string-to-key As given. +params + +pseudo-random function tmp1 = H(octet-string) + tmp2 = truncate tmp1 to multiple of m + PRF = E(DK(protocol-key, prfconstant), + tmp2, initial-cipher-state) + + The "prfconstant" used in the PRF operation is the three-octet string + "prf". + + + + + + + + + +Raeburn Standards Track [Page 15] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + Cryptosystem from Simplified Profile +------------------------------------------------------------------------ +key generation functions: + +string-to-key function As given. + +random-to-key function As given. + +key-derivation function The "well-known constant" used for the DK + function is the key usage number, expressed as + four octets in big-endian order, followed by + one octet indicated below. + + Kc = DK(base-key, usage | 0x99); + Ke = DK(base-key, usage | 0xAA); + Ki = DK(base-key, usage | 0x55); + +5.4. Checksum Profiles Based on Simplified Profile + + When an encryption system is defined with the simplified profile + given in section 5.2, a checksum algorithm may be defined for it as + follows: + + Checksum Mechanism from Simplified Profile + -------------------------------------------------- + associated cryptosystem As defined above. + + get_mic HMAC(Kc, message)[1..h] + + verify_mic get_mic and compare + + The HMAC function and key Kc are as described in section 5.3. + +6. Profiles for Kerberos Encryption and Checksum Algorithms + + These profiles describe the encryption and checksum systems defined + for Kerberos. The astute reader will notice that some of them do not + fulfill all the requirements outlined in previous sections. These + systems are defined for backward compatibility; newer implementations + should (whenever possible) attempt to utilize encryption systems that + satisfy all the profile requirements. + + The full list of current encryption and checksum type number + assignments, including values currently reserved but not defined in + this document, is given in section 8. + + + + + + +Raeburn Standards Track [Page 16] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + +6.1. Unkeyed Checksums + + These checksum types use no encryption keys and thus can be used in + combination with any encryption type, but they may only be used with + caution, in limited circumstances where the lack of a key does not + provide a window for an attack, preferably as part of an encrypted + message [6]. Keyed checksum algorithms are recommended. + +6.1.1. The RSA MD5 Checksum + + The RSA-MD5 checksum calculates a checksum by using the RSA MD5 + algorithm [MD5-92]. The algorithm takes as input an input message of + arbitrary length and produces as output a 128-bit (sixteen octet) + checksum. + + rsa-md5 + ---------------------------------------------- + associated cryptosystem any + + get_mic rsa-md5(msg) + + verify_mic get_mic and compare + + The rsa-md5 checksum algorithm is assigned a checksum type number of + seven (7). + +6.1.2. The RSA MD4 Checksum + + The RSA-MD4 checksum calculates a checksum using the RSA MD4 + algorithm [MD4-92]. The algorithm takes as input an input message of + arbitrary length and produces as output a 128-bit (sixteen octet) + checksum. + + rsa-md4 + ---------------------------------------------- + associated cryptosystem any + + get_mic md4(msg) + + verify_mic get_mic and compare + + The rsa-md4 checksum algorithm is assigned a checksum type number of + two (2). + + + + + + + + +Raeburn Standards Track [Page 17] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + +6.1.3. CRC-32 Checksum + + This CRC-32 checksum calculates a checksum based on a cyclic + redundancy check as described in ISO 3309 [CRC] but modified as + described below. The resulting checksum is four (4) octets in + length. The CRC-32 is neither keyed nor collision-proof; thus, the + use of this checksum is not recommended. An attacker using a + probabilistic chosen-plaintext attack as described in [SG92] might be + able to generate an alternative message that satisfies the checksum. + + The CRC-32 checksum used in the des-cbc-crc encryption mode is + identical to the 32-bit FCS described in ISO 3309 with two + exceptions: The sum with the all-ones polynomial times x**k is + omitted, and the final remainder is not ones-complemented. ISO 3309 + describes the FCS in terms of bits, whereas this document describes + the Kerberos protocol in terms of octets. To clarify the ISO 3309 + definition for the purpose of computing the CRC-32 in the des-cbc-crc + encryption mode, the ordering of bits in each octet shall be assumed + to be LSB first. Given this assumed ordering of bits within an + octet, the mapping of bits to polynomial coefficients shall be + identical to that specified in ISO 3309. + + Test values for this modified CRC function are included in appendix + A.5. + + crc32 + ---------------------------------------------- + associated cryptosystem any + + get_mic crc32(msg) + + verify_mic get_mic and compare + + The crc32 checksum algorithm is assigned a checksum type number of + one (1). + +6.2. DES-Based Encryption and Checksum Types + + These encryption systems encrypt information under the Data + Encryption Standard [DES77] by using the cipher block chaining mode + [DESM80]. A checksum is computed as described below and placed in + the cksum field. DES blocks are eight bytes. As a result, the data + to be encrypted (the concatenation of confounder, checksum, and + message) must be padded to an eight byte boundary before encryption. + The values of the padding bytes are unspecified. + + + + + + +Raeburn Standards Track [Page 18] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + Plaintext and DES ciphertext are encoded as blocks of eight octets, + which are concatenated to make the 64-bit inputs for the DES + algorithms. The first octet supplies the eight most significant bits + (with the octet's MSB used as the DES input block's MSB, etc.), the + second octet the next eight bits, and so on. The eighth octet + supplies the 8 least significant bits. + + Encryption under DES using cipher block chaining requires an + additional input in the form of an initialization vector; this vector + is specified below for each encryption system. + + The DES specifications [DESI81] identify four 'weak' and twelve + 'semi-weak' keys; these keys SHALL NOT be used for encrypting + messages for use in Kerberos. The "variant keys" generated for the + RSA-MD5-DES, RSA-MD4-DES, and DES-MAC checksum types by an + eXclusive-OR of a DES key with a constant are not checked for this + property. + + A DES key is eight octets of data. This consists of 56 bits of + actual key data, and eight parity bits, one per octet. The key is + encoded as a series of eight octets written in MSB-first order. The + bits within the key are also encoded in MSB order. For example, if + the encryption key is + (B1,B2,...,B7,P1,B8,...,B14,P2,B15,...,B49,P7,B50,...,B56,P8), where + B1,B2,...,B56 are the key bits in MSB order, and P1,P2,...,P8 are the + parity bits, the first octet of the key would be B1,B2,...,B7,P1 + (with B1 as the most significant bit). See the [DESM80] introduction + for reference. + + Encryption Data Format + + The format for the data to be encrypted includes a one-block + confounder, a checksum, the encoded plaintext, and any necessary + padding, as described in the following diagram. The msg-seq field + contains the part of the protocol message to be encrypted. + + +-----------+----------+---------+-----+ + |confounder | checksum | msg-seq | pad | + +-----------+----------+---------+-----+ + + One generates a random confounder of one block, placing it in + 'confounder'; zeros out the 'checksum' field (of length appropriate + to exactly hold the checksum to be computed); adds the necessary + padding; calculates the appropriate checksum over the whole sequence, + placing the result in 'checksum'; and then encrypts using the + specified encryption type and the appropriate key. + + + + + +Raeburn Standards Track [Page 19] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + String or Random-Data to Key Transformation + + To generate a DES key from two UTF-8 text strings (password and + salt), the two strings are concatenated, password first, and the + result is then padded with zero-valued octets to a multiple of eight + octets. + + The top bit of each octet (always zero if the password is plain + ASCII, as was assumed when the original specification was written) is + discarded, and the remaining seven bits of each octet form a + bitstring. This is then fan-folded and eXclusive-ORed with itself to + produce a 56-bit string. An eight-octet key is formed from this + string, each octet using seven bits from the bitstring, leaving the + least significant bit unassigned. The key is then "corrected" by + correcting the parity on the key, and if the key matches a 'weak' or + 'semi-weak' key as described in the DES specification, it is + eXclusive-ORed with the constant 0x00000000000000F0. This key is + then used to generate a DES CBC checksum on the initial string with + the salt appended. The result of the CBC checksum is then + "corrected" as described above to form the result, which is returned + as the key. + + For purposes of the string-to-key function, the DES CBC checksum is + calculated by CBC encrypting a string using the key as IV and the + final eight byte block as the checksum. + + Pseudocode follows: + + removeMSBits(8byteblock) { + /* Treats a 64 bit block as 8 octets and removes the MSB in + each octet (in big endian mode) and concatenates the + result. E.g., the input octet string: + 01110000 01100001 11110011 01110011 11110111 01101111 + 11110010 01100100 + results in the output bitstring: + 1110000 1100001 1110011 1110011 1110111 1101111 + 1110010 1100100 */ + } + + reverse(56bitblock) { + /* Treats a 56-bit block as a binary string and reverses it. + E.g., the input string: + 1000001 1010100 1001000 1000101 1001110 1000001 + 0101110 1001101 + results in the output string: + 1011001 0111010 1000001 0111001 1010001 0001001 + 0010101 1000001 */ + } + + + +Raeburn Standards Track [Page 20] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + add_parity_bits(56bitblock) { + /* Copies a 56-bit block into a 64-bit block, left shifts + content in each octet, and add DES parity bit. + E.g., the input string: + 1100000 0001111 0011100 0110100 1000101 1100100 + 0110110 0010111 + results in the output string: + 11000001 00011111 00111000 01101000 10001010 11001000 + 01101101 00101111 */ + } + + key_correction(key) { + fixparity(key); + if (is_weak_key(key)) + key = key XOR 0xF0; + return(key); + } + + mit_des_string_to_key(string,salt) { + odd = 1; + s = string | salt; + tempstring = 0; /* 56-bit string */ + pad(s); /* with nulls to 8 byte boundary */ + for (8byteblock in s) { + 56bitstring = removeMSBits(8byteblock); + if (odd == 0) reverse(56bitstring); + odd = ! odd; + tempstring = tempstring XOR 56bitstring; + } + tempkey = key_correction(add_parity_bits(tempstring)); + key = key_correction(DES-CBC-check(s,tempkey)); + return(key); + } + + des_string_to_key(string,salt,params) { + if (length(params) == 0) + type = 0; + else if (length(params) == 1) + type = params[0]; + else + error("invalid params"); + if (type == 0) + mit_des_string_to_key(string,salt); + else + error("invalid params"); + } + + + + + +Raeburn Standards Track [Page 21] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + One common extension is to support the "AFS string-to-key" algorithm, + which is not defined here, if the type value above is one (1). + + For generation of a key from a random bitstring, we start with a 56- + bit string and, as with the string-to-key operation above, insert + parity bits. If the result is a weak or semi-weak key, we modify it + by eXclusive-OR with the constant 0x00000000000000F0: + + des_random_to_key(bitstring) { + return key_correction(add_parity_bits(bitstring)); + } + +6.2.1. DES with MD5 + + The des-cbc-md5 encryption mode encrypts information under DES in CBC + mode with an all-zero initial vector and with an MD5 checksum + (described in [MD5-92]) computed and placed in the checksum field. + + The encryption system parameters for des-cbc-md5 are as follows: + + des-cbc-md5 + -------------------------------------------------------------------- + protocol key format 8 bytes, parity in low bit of each + + specific key structure copy of original key + + required checksum rsa-md5-des + mechanism + + key-generation seed 8 bytes + length + + cipher state 8 bytes (CBC initial vector) + + initial cipher state all-zero + + encryption function des-cbc(confounder | checksum | msg | pad, + ivec=oldstate) + where + checksum = md5(confounder | 0000... + | msg | pad) + + newstate = last block of des-cbc output + + decryption function decrypt encrypted text and verify checksum + + newstate = last block of ciphertext + + + + +Raeburn Standards Track [Page 22] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + des-cbc-md5 + -------------------------------------------------------------------- + default string-to-key empty string + params + + pseudo-random function des-cbc(md5(input-string), ivec=0) + + key generation functions: + + string-to-key des_string_to_key + + random-to-key des_random_to_key + + key-derivation identity + + The des-cbc-md5 encryption type is assigned the etype value three + (3). + +6.2.2. DES with MD4 + + The des-cbc-md4 encryption mode also encrypts information under DES + in CBC mode, with an all-zero initial vector. An MD4 checksum + (described in [MD4-92]) is computed and placed in the checksum field. + + des-cbc-md4 + -------------------------------------------------------------------- + protocol key format 8 bytes, parity in low bit of each + + specific key structure copy of original key + + required checksum rsa-md4-des + mechanism + + key-generation seed 8 bytes + length + + cipher state 8 bytes (CBC initial vector) + + initial cipher state all-zero + + encryption function des-cbc(confounder | checksum | msg | pad, + ivec=oldstate) + where + checksum = md4(confounder | 0000... + | msg | pad) + + newstate = last block of des-cbc output + + + + +Raeburn Standards Track [Page 23] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + des-cbc-md4 + -------------------------------------------------------------------- + + decryption function decrypt encrypted text and verify checksum + + newstate = last block of ciphertext + + default string-to-key empty string + params + + pseudo-random function des-cbc(md5(input-string), ivec=0) + + key generation functions: + + string-to-key des_string_to_key + + random-to-key copy input, then fix parity bits + + key-derivation identity + + Note that des-cbc-md4 uses md5, not md4, in the PRF definition. + + The des-cbc-md4 encryption algorithm is assigned the etype value two + (2). + +6.2.3. DES with CRC + + The des-cbc-crc encryption type uses DES in CBC mode with the key + used as the initialization vector, with a four-octet CRC-based + checksum computed as described in section 6.1.3. Note that this is + not a standard CRC-32 checksum, but a slightly modified one. + + des-cbc-crc + -------------------------------------------------------------------- + protocol key format 8 bytes, parity in low bit of each + + specific key structure copy of original key + + required checksum rsa-md5-des + mechanism + + key-generation seed 8 bytes + length + + cipher state 8 bytes (CBC initial vector) + + + + + + +Raeburn Standards Track [Page 24] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + des-cbc-crc + -------------------------------------------------------------------- + initial cipher state copy of original key + + encryption function des-cbc(confounder | checksum | msg | pad, + ivec=oldstate) + where + checksum = crc(confounder | 00000000 + | msg | pad) + + newstate = last block of des-cbc output + + decryption function decrypt encrypted text and verify checksum + + newstate = last block of ciphertext + + default string-to-key empty string + params + + pseudo-random function des-cbc(md5(input-string), ivec=0) + + key generation functions: + + string-to-key des_string_to_key + + random-to-key copy input, then fix parity bits + + key-derivation identity + + The des-cbc-crc encryption algorithm is assigned the etype value one + (1). + +6.2.4. RSA MD5 Cryptographic Checksum Using DES + + The RSA-MD5-DES checksum calculates a keyed collision-proof checksum + by prepending an eight octet confounder before the text, applying the + RSA MD5 checksum algorithm, and encrypting the confounder and the + checksum by using DES in cipher-block-chaining (CBC) mode with a + variant of the key, where the variant is computed by eXclusive-ORing + the key with the hexadecimal constant 0xF0F0F0F0F0F0F0F0. The + initialization vector should be zero. The resulting checksum is 24 + octets long. + + + + + + + + + +Raeburn Standards Track [Page 25] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + rsa-md5-des + ---------------------------------------------------------------- + associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc + + get_mic des-cbc(key XOR 0xF0F0F0F0F0F0F0F0, + conf | rsa-md5(conf | msg)) + + verify_mic decrypt and verify rsa-md5 checksum + + The rsa-md5-des checksum algorithm is assigned a checksum type number + of eight (8). + +6.2.5. RSA MD4 Cryptographic Checksum Using DES + + The RSA-MD4-DES checksum calculates a keyed collision-proof checksum + by prepending an eight octet confounder before the text, applying the + RSA MD4 checksum algorithm [MD4-92], and encrypting the confounder + and the checksum using DES in cipher-block-chaining (CBC) mode with a + variant of the key, where the variant is computed by eXclusive-ORing + the key with the constant 0xF0F0F0F0F0F0F0F0 [7]. The initialization + vector should be zero. The resulting checksum is 24 octets long. + + rsa-md4-des + ---------------------------------------------------------------- + associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc + + get_mic des-cbc(key XOR 0xF0F0F0F0F0F0F0F0, + conf | rsa-md4(conf | msg), + ivec=0) + + verify_mic decrypt and verify rsa-md4 checksum + + The rsa-md4-des checksum algorithm is assigned a checksum type number + of three (3). + +6.2.6. RSA MD4 Cryptographic Checksum Using DES Alternative + + The RSA-MD4-DES-K checksum calculates a keyed collision-proof + checksum by applying the RSA MD4 checksum algorithm and encrypting + the results by using DES in cipher block chaining (CBC) mode with a + DES key as both key and initialization vector. The resulting + checksum is 16 octets long. This checksum is tamper-proof and + believed to be collision-proof. Note that this checksum type is the + old method for encoding the RSA-MD4-DES checksum; it is no longer + recommended. + + + + + + +Raeburn Standards Track [Page 26] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + rsa-md4-des-k + ---------------------------------------------------------------- + associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc + + get_mic des-cbc(key, md4(msg), ivec=key) + + verify_mic decrypt, compute checksum and compare + + The rsa-md4-des-k checksum algorithm is assigned a checksum type + number of six (6). + +6.2.7. DES CBC Checksum + + The DES-MAC checksum is computed by prepending an eight octet + confounder to the plaintext, padding with zero-valued octets if + necessary to bring the length to a multiple of eight octets, + performing a DES CBC-mode encryption on the result by using the key + and an initialization vector of zero, taking the last block of the + ciphertext, prepending the same confounder, and encrypting the pair + by using DES in cipher-block-chaining (CBC) mode with a variant of + the key, where the variant is computed by eXclusive-ORing the key + with the constant 0xF0F0F0F0F0F0F0F0. The initialization vector + should be zero. The resulting checksum is 128 bits (sixteen octets) + long, 64 bits of which are redundant. This checksum is tamper-proof + and collision-proof. + + des-mac + --------------------------------------------------------------------- + associated des-cbc-md5, des-cbc-md4, des-cbc-crc + cryptosystem + + get_mic des-cbc(key XOR 0xF0F0F0F0F0F0F0F0, + conf | des-mac(key, conf | msg | pad, ivec=0), + ivec=0) + + verify_mic decrypt, compute DES MAC using confounder, compare + + The des-mac checksum algorithm is assigned a checksum type number of + four (4). + +6.2.8. DES CBC Checksum Alternative + + The DES-MAC-K checksum is computed by performing a DES CBC-mode + encryption of the plaintext, with zero-valued padding bytes if + necessary to bring the length to a multiple of eight octets, and by + using the last block of the ciphertext as the checksum value. It is + keyed with an encryption key that is also used as the initialization + vector. The resulting checksum is 64 bits (eight octets) long. This + + + +Raeburn Standards Track [Page 27] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + checksum is tamper-proof and collision-proof. Note that this + checksum type is the old method for encoding the DESMAC checksum; it + is no longer recommended. + + des-mac-k + ---------------------------------------------------------------- + associated cryptosystem des-cbc-md5, des-cbc-md4, des-cbc-crc + + get_mic des-mac(key, msg | pad, ivec=key) + + verify_mic compute MAC and compare + + The des-mac-k checksum algorithm is assigned a checksum type number + of five (5). + +6.3. Triple-DES Based Encryption and Checksum Types + + This encryption and checksum type pair is based on the Triple DES + cryptosystem in Outer-CBC mode and on the HMAC-SHA1 message + authentication algorithm. + + A Triple DES key is the concatenation of three DES keys as described + above for des-cbc-md5. A Triple DES key is generated from random + data by creating three DES keys from separate sequences of random + data. + + Encrypted data using this type must be generated as described in + section 5.3. If the length of the input data is not a multiple of + the block size, zero-valued octets must be used to pad the plaintext + to the next eight-octet boundary. The confounder must be eight + random octets (one block). + + The simplified profile for Triple DES, with key derivation as defined + in section 5, is as follows: + + des3-cbc-hmac-sha1-kd, hmac-sha1-des3-kd + ------------------------------------------------ + protocol key format 24 bytes, parity in low + bit of each + + key-generation seed 21 bytes + length + + + + + + + + + +Raeburn Standards Track [Page 28] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + des3-cbc-hmac-sha1-kd, hmac-sha1-des3-kd + ------------------------------------------------ + hash function SHA-1 + + HMAC output size 160 bits + + message block size 8 bytes + + default string-to-key empty string + params + + encryption and triple-DES encrypt and + decryption functions decrypt, in outer-CBC + mode (cipher block size + 8 octets) + + key generation functions: + + random-to-key DES3random-to-key (see + below) + + string-to-key DES3string-to-key (see + below) + + The des3-cbc-hmac-sha1-kd encryption type is assigned the value + sixteen (16). The hmac-sha1-des3-kd checksum algorithm is assigned a + checksum type number of twelve (12). + +6.3.1. Triple DES Key Production (random-to-key, string-to-key) + + The 168 bits of random key data are converted to a protocol key value + as follows. First, the 168 bits are divided into three groups of 56 + bits, which are expanded individually into 64 bits as follows: + + DES3random-to-key: + 1 2 3 4 5 6 7 p + 9 10 11 12 13 14 15 p + 17 18 19 20 21 22 23 p + 25 26 27 28 29 30 31 p + 33 34 35 36 37 38 39 p + 41 42 43 44 45 46 47 p + 49 50 51 52 53 54 55 p + 56 48 40 32 24 16 8 p + + The "p" bits are parity bits computed over the data bits. The output + of the three expansions, each corrected to avoid "weak" and "semi- + weak" keys as in section 6.2, are concatenated to form the protocol + key value. + + + +Raeburn Standards Track [Page 29] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + The string-to-key function is used to transform UTF-8 passwords into + DES3 keys. The DES3 string-to-key function relies on the "N-fold" + algorithm and DK function, described in section 5. + + The n-fold algorithm is applied to the password string concatenated + with a salt value. For 3-key triple DES, the operation will involve + a 168-fold of the input password string, to generate an intermediate + key, from which the user's long-term key will be derived with the DK + function. The DES3 string-to-key function is shown here in + pseudocode: + + DES3string-to-key(passwordString, salt, params) + if (params != emptyString) + error("invalid params"); + s = passwordString + salt + tmpKey = random-to-key(168-fold(s)) + key = DK (tmpKey, KerberosConstant) + + Weak key checking is performed in the random-to-key and DK + operations. The KerberosConstant value is the byte string {0x6b 0x65 + 0x72 0x62 0x65 0x72 0x6f 0x73}. These values correspond to the ASCII + encoding for the string "kerberos". + +7. Use of Kerberos Encryption Outside This Specification + + Several Kerberos-based application protocols and preauthentication + systems have been designed and deployed that perform encryption and + message integrity checks in various ways. Although in some cases + there may be good reason for specifying these protocols in terms of + specific encryption or checksum algorithms, we anticipate that in + many cases this will not be true, and more generic approaches + independent of particular algorithms will be desirable. Rather than + have each protocol designer reinvent schemes for protecting data, + using multiple keys, etc., we have attempted to present in this + section a general framework that should be sufficient not only for + the Kerberos protocol itself but also for many preauthentication + systems and application protocols, while trying to avoid some of the + assumptions that can work their way into such protocol designs. + + Some problematic assumptions we've seen (and sometimes made) include + the following: a random bitstring is always valid as a key (not true + for DES keys with parity); the basic block encryption chaining mode + provides no integrity checking, or can easily be separated from such + checking (not true for many modes in development that do both + simultaneously); a checksum for a message always results in the same + value (not true if a confounder is incorporated); an initial vector + is used (may not be true if a block cipher in CBC mode is not in + use). + + + +Raeburn Standards Track [Page 30] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + Although such assumptions the may hold for any given set of + encryption and checksum algorithms, they may not be true of the next + algorithms to be defined, leaving the application protocol unable to + make use of those algorithms without updates to its specification. + + The Kerberos protocol uses only the attributes and operations + described in sections 3 and 4. Preauthentication systems and + application protocols making use of Kerberos are encouraged to use + them as well. The specific key and string-to-key parameters should + generally be treated as opaque. Although the string-to-key + parameters are manipulated as an octet string, the representation for + the specific key structure is implementation defined; it may not even + be a single object. + + We don't recommend doing so, but some application protocols will + undoubtedly continue to use the key data directly, even if only in + some of the currently existing protocol specifications. An + implementation intended to support general Kerberos applications may + therefore need to make the key data available, as well as the + attributes and operations described in sections 3 and 4 [8]. + +8. Assigned Numbers + + The following encryption-type numbers are already assigned or + reserved for use in Kerberos and related protocols. + + encryption type etype section or comment + ----------------------------------------------------------------- + des-cbc-crc 1 6.2.3 + des-cbc-md4 2 6.2.2 + des-cbc-md5 3 6.2.1 + [reserved] 4 + des3-cbc-md5 5 + [reserved] 6 + des3-cbc-sha1 7 + dsaWithSHA1-CmsOID 9 (pkinit) + md5WithRSAEncryption-CmsOID 10 (pkinit) + sha1WithRSAEncryption-CmsOID 11 (pkinit) + rc2CBC-EnvOID 12 (pkinit) + rsaEncryption-EnvOID 13 (pkinit from PKCS#1 v1.5) + rsaES-OAEP-ENV-OID 14 (pkinit from PKCS#1 v2.0) + des-ede3-cbc-Env-OID 15 (pkinit) + des3-cbc-sha1-kd 16 6.3 + aes128-cts-hmac-sha1-96 17 [KRB5-AES] + aes256-cts-hmac-sha1-96 18 [KRB5-AES] + rc4-hmac 23 (Microsoft) + rc4-hmac-exp 24 (Microsoft) + subkey-keymaterial 65 (opaque; PacketCable) + + + +Raeburn Standards Track [Page 31] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + (The "des3-cbc-sha1" assignment is a deprecated version using no key + derivation. It should not be confused with des3-cbc-sha1-kd.) + + Several numbers have been reserved for use in encryption systems not + defined here. Encryption-type numbers have unfortunately been + overloaded on occasion in Kerberos-related protocols, so some of the + reserved numbers do not and will not correspond to encryption systems + fitting the profile presented here. + + The following checksum-type numbers are assigned or reserved. As + with encryption-type numbers, some overloading of checksum numbers + has occurred. + + Checksum type sumtype checksum section or + value size reference + --------------------------------------------------------------------- + CRC32 1 4 6.1.3 + rsa-md4 2 16 6.1.2 + rsa-md4-des 3 24 6.2.5 + des-mac 4 16 6.2.7 + des-mac-k 5 8 6.2.8 + rsa-md4-des-k 6 16 6.2.6 + rsa-md5 7 16 6.1.1 + rsa-md5-des 8 24 6.2.4 + rsa-md5-des3 9 24 ?? + sha1 (unkeyed) 10 20 ?? + hmac-sha1-des3-kd 12 20 6.3 + hmac-sha1-des3 13 20 ?? + sha1 (unkeyed) 14 20 ?? + hmac-sha1-96-aes128 15 20 [KRB5-AES] + hmac-sha1-96-aes256 16 20 [KRB5-AES] + [reserved] 0x8003 ? [GSS-KRB5] + + Encryption and checksum-type numbers are signed 32-bit values. Zero + is invalid, and negative numbers are reserved for local use. All + standardized values must be positive. + +9. Implementation Notes + + The "interface" described here is the minimal information that must + be defined to make a cryptosystem useful within Kerberos in an + interoperable fashion. The use of functional notation used in some + places is not an attempt to define an API for cryptographic + functionality within Kerberos. Actual implementations providing + clean APIs will probably make additional information available, that + could be derived from a specification written to the framework given + here. For example, an application designer may wish to determine the + largest number of bytes that can be encrypted without overflowing a + + + +Raeburn Standards Track [Page 32] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + certain size output buffer or conversely, the maximum number of bytes + that might be obtained by decrypting a ciphertext message of a given + size. (In fact, an implementation of the GSS-API Kerberos mechanism + [GSS-KRB5] will require some of these.) + + The presence of a mechanism in this document should not be taken to + indicate that it must be implemented for compliance with any + specification; required mechanisms will be specified elsewhere. + Indeed, some of the mechanisms described here for backward + compatibility are now considered rather weak for protecting critical + data. + +10. Security Considerations + + Recent years have brought so many advancements in large-scale attacks + capability against DES that it is no longer considered a strong + encryption mechanism. Triple-DES is generally preferred in its + place, despite its poorer performance. See [ESP-DES] for a summary + of some of the potential attacks and [EFF-DES] for a detailed + discussion of the implementation of particular attacks. However, + most Kerberos implementations still have DES as their primary + interoperable encryption type. + + DES has four 'weak' keys and twelve 'semi-weak' keys, and the use of + single-DES here avoids them. However, DES also has 48 'possibly- + weak' keys [Schneier96] (note that the tables in many editions of the + reference contains errors) that are not avoided. + + DES weak keys have the property that E1(E1(P)) = P (where E1 denotes + encryption of a single block with key 1). DES semi-weak keys, or + "dual" keys, are pairs of keys with the property that E1(P) = D2(P), + and thus E2(E1(P)) = P. Because of the use of CBC mode and the + leading random confounder, however, these properties are unlikely to + present a security problem. + + Many of the choices concerning when to perform weak-key corrections + relate more to compatibility with existing implementations than to + any risk analysis. + + Although checks are also done for the component DES keys in a + triple-DES key, the nature of the weak keys make it extremely + unlikely that they will weaken the triple-DES encryption. It is only + slightly more likely than having the middle of the three sub-keys + match one of the other two, which effectively converts the encryption + to single-DES - a case we make no effort to avoid. + + + + + + +Raeburn Standards Track [Page 33] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + The true CRC-32 checksum is not collision-proof; an attacker could + use a probabilistic chosen-plaintext attack to generate a valid + message even if a confounder is used [SG92]. The use of collision- + proof checksums is of course recommended for environments where such + attacks represent a significant threat. The "simplifications" (read: + bugs) introduced when CRC-32 was implemented for Kerberos cause + leading zeros effectively to be ignored, so messages differing only + in leading zero bits will have the same checksum. + + [HMAC] and [IPSEC-HMAC] discuss weaknesses of the HMAC algorithm. + Unlike [IPSEC-HMAC], the triple-DES specification here does not use + the suggested truncation of the HMAC output. As pointed out in + [IPSEC-HMAC], SHA-1 was not developed for use as a keyed hash + function, which is a criterion of HMAC. [HMAC-TEST] contains test + vectors for HMAC-SHA-1. + + The mit_des_string_to_key function was originally constructed with + the assumption that all input would be ASCII; it ignores the top bit + of each input byte. Folding with XOR is also not an especially good + mixing mechanism for preserving randomness. + + The n-fold function used in the string-to-key operation for des3- + cbc-hmac-sha1-kd was designed to cause each bit of input to + contribute equally to the output. It was not designed to maximize or + equally distribute randomness in the input, and conceivably + randomness may be lost in cases of partially structured input. This + should only be an issue for highly structured passwords, however. + + [RFC1851] discusses the relative strength of triple-DES encryption. + The relatively slow speed of triple-DES encryption may also be an + issue for some applications. + + [Bellovin91] suggests that analyses of encryption schemes include a + model of an attacker capable of submitting known plaintexts to be + encrypted with an unknown key, as well as be able to perform many + types of operations on known protocol messages. Recent experiences + with the chosen-plaintext attacks on Kerberos version 4 bear out the + value of this suggestion. + + The use of unkeyed encrypted checksums, such as those used in the + single-DES cryptosystems specified in [Kerb1510], allows for cut- + and-paste attacks, especially if a confounder is not used. In + addition, unkeyed encrypted checksums are vulnerable to chosen- + plaintext attacks: An attacker with access to an encryption oracle + can easily encrypt the required unkeyed checksum along with the + + + + + + +Raeburn Standards Track [Page 34] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + chosen plaintext. [Bellovin99] These weaknesses, combined with a + common implementation design choice described below, allow for a + cross-protocol attack from version 4 to version 5. + + The use of a random confounder is an important means to prevent an + attacker from making effective use of protocol exchanges as an + encryption oracle. In Kerberos version 4, the encryption of constant + plaintext to constant ciphertext makes an effective encryption oracle + for an attacker. The use of random confounders in [Kerb1510] + frustrates this sort of chosen-plaintext attack. + + Using the same key for multiple purposes can enable or increase the + scope of chosen-plaintext attacks. Some software that implements + both versions 4 and 5 of the Kerberos protocol uses the same keys for + both versions. This enables the encryption oracle of version 4 to be + used to attack version 5. Vulnerabilities to attacks such as this + cross-protocol attack make it unwise to use a key for multiple + purposes. + + This document, like the Kerberos protocol, does not address limiting + the amount of data a key may be used with to a quantity based on the + robustness of the algorithm or size of the key. It is assumed that + any defined algorithms and key sizes will be strong enough to support + very large amounts of data, or they will be deprecated once + significant attacks are known. + + This document also places no bounds on the amount of data that can be + handled in various operations. To avoid denial of service attacks, + implementations will probably seek to restrict message sizes at some + higher level. + +11. IANA Considerations + + Two registries for numeric values have been created: Kerberos + Encryption Type Numbers and Kerberos Checksum Type Numbers. These + are signed values ranging from -2147483648 to 2147483647. Positive + values should be assigned only for algorithms specified in accordance + with this specification for use with Kerberos or related protocols. + Negative values are for private use; local and experimental + algorithms should use these values. Zero is reserved and may not be + assigned. + + Positive encryption- and checksum-type numbers may be assigned + following either of two policies described in [BCP26]. + + Standards-track specifications may be assigned values under the + Standards Action policy. + + + + +Raeburn Standards Track [Page 35] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + Specifications in non-standards track RFCs may be assigned values + after Expert Review. A non-IETF specification may be assigned values + by publishing an Informational or standards-track RFC referencing the + external specification; that specification must be public and + published in some permanent record, much like the IETF RFCs. It is + highly desirable, though not required, that the full specification be + published as an IETF RFC. + + Smaller encryption type values should be used for IETF standards- + track mechanisms, and much higher values (16777216 and above) for + other mechanisms. (Rationale: In the Kerberos ASN.1 encoding, + smaller numbers encode to smaller octet sequences, so this favors + standards-track mechanisms with slightly smaller messages.) Aside + from that guideline, IANA may choose numbers as it sees fit. + + Internet-Draft specifications should not include values for + encryption- and checksum-type numbers. Instead, they should indicate + that values would be assigned by IANA when the document is approved + as an RFC. For development and interoperability testing, values in + the private-use range (negative values) may be used but should not be + included in the draft specification. + + Each registered value should have an associated unique reference + name. The lists given in section 8 were used to create the initial + registry; they include reservations for specifications in progress in + parallel with this document, and certain other values believed to + already be in use. + +12. Acknowledgements + + This document is an extension of the encryption specification + included in [Kerb1510] by B. Clifford Neuman and John Kohl, and much + of the text of the background, concepts, and DES specifications is + drawn directly from that document. + + The abstract framework presented in this document was put together by + Jeff Altman, Sam Hartman, Jeff Hutzelman, Cliff Neuman, Ken Raeburn, + and Tom Yu, and the details were refined several times based on + comments from John Brezak and others. + + Marc Horowitz wrote the original specification of triple-DES and key + derivation in a pair of Internet-Drafts (under the names draft- + horowitz-key-derivation and draft-horowitz-kerb-key-derivation) that + were later folded into a draft revision of [Kerb1510], from which + this document was later split off. + + + + + + +Raeburn Standards Track [Page 36] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + Tom Yu provided the text describing the modifications to the standard + CRC algorithm as Kerberos implementations actually use it, and some + of the text in the Security Considerations section. + + Miroslav Jurisic provided information for one of the UTF-8 test cases + for the string-to-key functions. + + Marcus Watts noticed some errors in earlier versions and pointed out + that the simplified profile could easily be modified to support + cipher text stealing modes. + + Simon Josefsson contributed some clarifications to the DES "CBC + checksum" and string-to-key and weak key descriptions, and some test + vectors. + + Simon Josefsson, Louis LeVay, and others also caught some errors in + earlier versions of this document. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Raeburn Standards Track [Page 37] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + +A. Test Vectors + + This section provides test vectors for various functions defined or + described in this document. For convenience, most inputs are ASCII + strings, though some UTF-8 samples are provided for string-to-key + functions. Keys and other binary data are specified as hexadecimal + strings. + +A.1. n-fold + + The n-fold function is defined in section 5.1. As noted there, the + sample vector in the original paper defining the algorithm appears to + be incorrect. Here are some test cases provided by Marc Horowitz and + Simon Josefsson: + + 64-fold("012345") = + 64-fold(303132333435) = be072631276b1955 + + 56-fold("password") = + 56-fold(70617373776f7264) = 78a07b6caf85fa + + 64-fold("Rough Consensus, and Running Code") = + 64-fold(526f75676820436f6e73656e7375732c20616e642052756e + 6e696e6720436f6465) = bb6ed30870b7f0e0 + + 168-fold("password") = + 168-fold(70617373776f7264) = + 59e4a8ca7c0385c3c37b3f6d2000247cb6e6bd5b3e + + 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") + 192-fold(4d41535341434856534554545320494e5354495456544520 + 4f4620544543484e4f4c4f4759) = + db3b0d8f0b061e603282b308a50841229ad798fab9540c1b + + 168-fold("Q") = + 168-fold(51) = + 518a54a2 15a8452a 518a54a2 15a8452a + 518a54a2 15 + + 168-fold("ba") = + 168-fold(6261) = + fb25d531 ae897449 9f52fd92 ea9857c4 + ba24cf29 7e + + Here are some additional values corresponding to folded values of the + string "kerberos"; the 64-bit form is used in the des3 string-to-key + (section 6.3.1). + + + + +Raeburn Standards Track [Page 38] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + 64-fold("kerberos") = + 6b657262 65726f73 + 128-fold("kerberos") = + 6b657262 65726f73 7b9b5b2b 93132b93 + 168-fold("kerberos") = + 8372c236 344e5f15 50cd0747 e15d62ca + 7a5a3bce a4 + 256-fold("kerberos") = + 6b657262 65726f73 7b9b5b2b 93132b93 + 5c9bdcda d95c9899 c4cae4de e6d6cae4 + + Note that the initial octets exactly match the input string when the + output length is a multiple of the input length. + +A.2. mit_des_string_to_key + + The function mit_des_string_to_key is defined in section 6.2. We + present here several test values, with some of the intermediate + results. The fourth test demonstrates the use of UTF-8 with three + characters. The last two tests are specifically constructed so as to + trigger the weak-key fixups for the intermediate key produced by + fan-folding; we have no test cases that cause such fixups for the + final key. + +UTF-8 encodings used in test vector: +eszett U+00DF C3 9F s-caron U+0161 C5 A1 +c-acute U+0107 C4 87 g-clef U+1011E F0 9D 84 9E + +Test vector: + +salt: "ATHENA.MIT.EDUraeburn" + 415448454e412e4d49542e4544557261656275726e +password: "password" 70617373776f7264 +fan-fold result: c01e38688ac86c2e +intermediate key: c11f38688ac86d2f +DES key: cbc22fae235298e3 + +salt: "WHITEHOUSE.GOVdanny" + 5748495445484f5553452e474f5664616e6e79 +password: "potatoe" 706f7461746f65 +fan-fold result: a028944ee63c0416 +intermediate key: a129944fe63d0416 +DES key: df3d32a74fd92a01 + +salt: "EXAMPLE.COMpianist" 4558414D504C452E434F4D7069616E697374 +password: g-clef (U+1011E) f09d849e +fan-fold result: 3c4a262c18fab090 +intermediate key: 3d4a262c19fbb091 + + + +Raeburn Standards Track [Page 39] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + +DES key: 4ffb26bab0cd9413 + +salt: "ATHENA.MIT.EDUJuri" + s-caron(U+0161) + "i" + c-acute(U+0107) + 415448454e412e4d49542e4544554a757269c5a169c487 +password: eszett(U+00DF) + c39f +fan-fold result:b8f6c40e305afc9e +intermediate key: b9f7c40e315bfd9e +DES key: 62c81a5232b5e69d + +salt: "AAAAAAAA" 4141414141414141 +password: "11119999" 3131313139393939 +fan-fold result: e0e0e0e0f0f0f0f0 +intermediate key: e0e0e0e0f1f1f101 +DES key: 984054d0f1a73e31 + +salt: "FFFFAAAA" 4646464641414141 +password: "NNNN6666" 4e4e4e4e36363636 +fan-fold result: 1e1e1e1e0e0e0e0e +intermediate key: 1f1f1f1f0e0e0efe +DES key: c4bf6b25adf7a4f8 + + This trace provided by Simon Josefsson shows the intermediate + processing stages of one of the test inputs: + + string_to_key (des-cbc-md5, string, salt) + ;; string: + ;; `password' (length 8 bytes) + ;; 70 61 73 73 77 6f 72 64 + ;; salt: + ;; `ATHENA.MIT.EDUraeburn' (length 21 bytes) + ;; 41 54 48 45 4e 41 2e 4d 49 54 2e 45 44 55 72 61 + ;; 65 62 75 72 6e + des_string_to_key (string, salt) + ;; String: + ;; `password' (length 8 bytes) + ;; 70 61 73 73 77 6f 72 64 + ;; Salt: + ;; `ATHENA.MIT.EDUraeburn' (length 21 bytes) + ;; 41 54 48 45 4e 41 2e 4d 49 54 2e 45 44 55 72 61 + ;; 65 62 75 72 6e + odd = 1; + s = string | salt; + tempstring = 0; /* 56-bit string */ + pad(s); /* with nulls to 8 byte boundary */ + ;; s = pad(string|salt): + ;; `passwordATHENA.MIT.EDUraeburn\x00\x00\x00' + ;; (length 32 bytes) + + + +Raeburn Standards Track [Page 40] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + ;; 70 61 73 73 77 6f 72 64 41 54 48 45 4e 41 2e 4d + ;; 49 54 2e 45 44 55 72 61 65 62 75 72 6e 00 00 00 + for (8byteblock in s) { + ;; loop iteration 0 + ;; 8byteblock: + ;; `password' (length 8 bytes) + ;; 70 61 73 73 77 6f 72 64 + ;; 01110000 01100001 01110011 01110011 01110111 01101111 + ;; 01110010 01100100 + 56bitstring = removeMSBits(8byteblock); + ;; 56bitstring: + ;; 1110000 1100001 1110011 1110011 1110111 1101111 + ;; 1110010 1100100 + if (odd == 0) reverse(56bitstring); ;; odd=1 + odd = ! odd + tempstring = tempstring XOR 56bitstring; + ;; tempstring + ;; 1110000 1100001 1110011 1110011 1110111 1101111 + ;; 1110010 1100100 + + for (8byteblock in s) { + ;; loop iteration 1 + ;; 8byteblock: + ;; `ATHENA.M' (length 8 bytes) + ;; 41 54 48 45 4e 41 2e 4d + ;; 01000001 01010100 01001000 01000101 01001110 01000001 + ;; 00101110 01001101 + 56bitstring = removeMSBits(8byteblock); + ;; 56bitstring: + ;; 1000001 1010100 1001000 1000101 1001110 1000001 + ;; 0101110 1001101 + if (odd == 0) reverse(56bitstring); ;; odd=0 + reverse(56bitstring) + ;; 56bitstring after reverse + ;; 1011001 0111010 1000001 0111001 1010001 0001001 + ;; 0010101 1000001 + odd = ! odd + tempstring = tempstring XOR 56bitstring; + ;; tempstring + ;; 0101001 1011011 0110010 1001010 0100110 1100110 + ;; 1100111 0100101 + + for (8byteblock in s) { + ;; loop iteration 2 + ;; 8byteblock: + ;; `IT.EDUra' (length 8 bytes) + ;; 49 54 2e 45 44 55 72 61 + ;; 01001001 01010100 00101110 01000101 01000100 01010101 + + + +Raeburn Standards Track [Page 41] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + ;; 01110010 01100001 + 56bitstring = removeMSBits(8byteblock); + ;; 56bitstring: + ;; 1001001 1010100 0101110 1000101 1000100 1010101 + ;; 1110010 1100001 + if (odd == 0) reverse(56bitstring); ;; odd=1 + odd = ! odd + tempstring = tempstring XOR 56bitstring; + ;; tempstring + ;; 1100000 0001111 0011100 0001111 1100010 0110011 + ;; 0010101 1000100 + + for (8byteblock in s) { + ;; loop iteration 3 + ;; 8byteblock: + ;; `eburn\x00\x00\x00' (length 8 bytes) + ;; 65 62 75 72 6e 00 00 00 + ;; 01100101 01100010 01110101 01110010 01101110 00000000 + ;; 00000000 00000000 + 56bitstring = removeMSBits(8byteblock); + ;; 56bitstring: + ;; 1100101 1100010 1110101 1110010 1101110 0000000 + ;; 0000000 0000000 + if (odd == 0) reverse(56bitstring); ;; odd=0 + reverse(56bitstring) + ;; 56bitstring after reverse + ;; 0000000 0000000 0000000 0111011 0100111 1010111 + ;; 0100011 1010011 + odd = ! odd + tempstring = tempstring XOR 56bitstring; + ;; tempstring + ;; 1100000 0001111 0011100 0110100 1000101 1100100 + ;; 0110110 0010111 + + for (8byteblock in s) { + } + ;; for loop terminated + + tempkey = key_correction(add_parity_bits(tempstring)); + ;; tempkey + ;; `\xc1\x1f8h\x8a\xc8m\x2f' (length 8 bytes) + ;; c1 1f 38 68 8a c8 6d 2f + ;; 11000001 00011111 00111000 01101000 10001010 11001000 + ;; 01101101 00101111 + + key = key_correction(DES-CBC-check(s,tempkey)); + ;; key + ;; `\xcb\xc2\x2f\xae\x23R\x98\xe3' (length 8 bytes) + + + +Raeburn Standards Track [Page 42] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + ;; cb c2 2f ae 23 52 98 e3 + ;; 11001011 11000010 00101111 10101110 00100011 01010010 + ;; 10011000 11100011 + + ;; string_to_key key: + ;; `\xcb\xc2\x2f\xae\x23R\x98\xe3' (length 8 bytes) + ;; cb c2 2f ae 23 52 98 e3 + +A.3. DES3 DR and DK + + These tests show the derived-random and derived-key values for the + des3-hmac-sha1-kd encryption scheme, using the DR and DK functions + defined in section 6.3.1. The input keys were randomly generated; + the usage values are from this specification. + + key: dce06b1f64c857a11c3db57c51899b2cc1791008ce973b92 + usage: 0000000155 + DR: 935079d14490a75c3093c4a6e8c3b049c71e6ee705 + DK: 925179d04591a79b5d3192c4a7e9c289b049c71f6ee604cd + + key: 5e13d31c70ef765746578531cb51c15bf11ca82c97cee9f2 + usage: 00000001aa + DR: 9f58e5a047d894101c469845d67ae3c5249ed812f2 + DK: 9e58e5a146d9942a101c469845d67a20e3c4259ed913f207 + + key: 98e6fd8a04a4b6859b75a176540b9752bad3ecd610a252bc + usage: 0000000155 + DR: 12fff90c773f956d13fc2ca0d0840349dbd39908eb + DK: 13fef80d763e94ec6d13fd2ca1d085070249dad39808eabf + + key: 622aec25a2fe2cad7094680b7c64940280084c1a7cec92b5 + usage: 00000001aa + DR: f8debf05b097e7dc0603686aca35d91fd9a5516a70 + DK: f8dfbf04b097e6d9dc0702686bcb3489d91fd9a4516b703e + + key: d3f8298ccb166438dcb9b93ee5a7629286a491f838f802fb + usage: 6b65726265726f73 ("kerberos") + DR: 2270db565d2a3d64cfbfdc5305d4f778a6de42d9da + DK: 2370da575d2a3da864cebfdc5204d56df779a7df43d9da43 + + key: c1081649ada74362e6a1459d01dfd30d67c2234c940704da + usage: 0000000155 + DR: 348056ec98fcc517171d2b4d7a9493af482d999175 + DK: 348057ec98fdc48016161c2a4c7a943e92ae492c989175f7 + + key: 5d154af238f46713155719d55e2f1f790dd661f279a7917c + usage: 00000001aa + DR: a8818bc367dadacbe9a6c84627fb60c294b01215e5 + + + +Raeburn Standards Track [Page 43] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + DK: a8808ac267dada3dcbe9a7c84626fbc761c294b01315e5c1 + + key: 798562e049852f57dc8c343ba17f2ca1d97394efc8adc443 + usage: 0000000155 + DR: c813f88b3be2b2f75424ce9175fbc8483b88c8713a + DK: c813f88a3be3b334f75425ce9175fbe3c8493b89c8703b49 + + key: 26dce334b545292f2feab9a8701a89a4b99eb9942cecd016 + usage: 00000001aa + DR: f58efc6f83f93e55e695fd252cf8fe59f7d5ba37ec + DK: f48ffd6e83f83e7354e694fd252cf83bfe58f7d5ba37ec5d + +A.4. DES3string_to_key + + These are the keys generated for some of the above input strings for + triple-DES with key derivation as defined in section 6.3.1. + + salt: "ATHENA.MIT.EDUraeburn" + passwd: "password" + key: 850bb51358548cd05e86768c313e3bfef7511937dcf72c3e + + salt: "WHITEHOUSE.GOVdanny" + passwd: "potatoe" + key: dfcd233dd0a43204ea6dc437fb15e061b02979c1f74f377a + + salt: "EXAMPLE.COMbuckaroo" + passwd: "penny" + key: 6d2fcdf2d6fbbc3ddcadb5da5710a23489b0d3b69d5d9d4a + + salt: "ATHENA.MIT.EDUJuri" + s-caron(U+0161) + "i" + + c-acute(U+0107) + passwd: eszett(U+00DF) + key: 16d5a40e1ce3bacb61b9dce00470324c831973a7b952feb0 + + salt: "EXAMPLE.COMpianist" + passwd: g-clef(U+1011E) + key: 85763726585dbc1cce6ec43e1f751f07f1c4cbb098f40b19 + +A.5. Modified CRC-32 + + Below are modified-CRC32 values for various ASCII and octet strings. + Only the printable ASCII characters are checksummed, without a C- + style trailing zero-valued octet. The 32-bit modified CRC and the + sequence of output bytes as used in Kerberos are shown. (The octet + values are separated here to emphasize that they are octet values and + not 32-bit numbers, which will be the most convenient form for + manipulation in some implementations. The bit and byte order used + + + + +Raeburn Standards Track [Page 44] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + internally for such a number is irrelevant; the octet sequence + generated is what is important.) + + mod-crc-32("foo") = 33 bc 32 73 + mod-crc-32("test0123456789") = d6 88 3e b8 + mod-crc-32("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") = f7 80 41 e3 + mod-crc-32(8000) = 4b 98 83 3b + mod-crc-32(0008) = 32 88 db 0e + mod-crc-32(0080) = 20 83 b8 ed + mod-crc-32(80) = 20 83 b8 ed + mod-crc-32(80000000) = 3b b6 59 ed + mod-crc-32(00000001) = 96 30 07 77 + +B. Significant Changes from RFC 1510 + + The encryption and checksum mechanism profiles are new. The old + specification defined a few operations for various mechanisms but + didn't outline what abstract properties should be required of new + mechanisms, or how to ensure that a mechanism specification is + complete enough for interoperability between implementations. The + new profiles differ from the old specification in a few ways: + + Some message definitions in [Kerb1510] could be read as permitting + the initial vector to be specified by the application; the text + was too vague. It is explicitly not permitted in this + specification. Some encryption algorithms may not use + initialization vectors, so relying on chosen, secret + initialization vectors for security is unwise. Also, the + prepended confounder in the existing algorithms is roughly + equivalent to a per-message initialization vector that is revealed + in encrypted form. However, carrying state across from one + encryption to another is explicitly permitted through the opaque + "cipher state" object. + + The use of key derivation is new. + + Several new methods are introduced, including generation of a key + in wire-protocol format from random input data. + + The means for influencing the string-to-key algorithm are laid out + more clearly. + + Triple-DES support is new. + + The pseudo-random function is new. + + The des-cbc-crc, DES string-to-key and CRC descriptions have been + updated to align them with existing implementations. + + + +Raeburn Standards Track [Page 45] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + [Kerb1510] did not indicate what character set or encoding might be + used for pass phrases and salts. + + In [Kerb1510], key types, encryption algorithms, and checksum + algorithms were only loosely associated, and the association was not + well described. In this specification, key types and encryption + algorithms have a one-to-one correspondence, and associations between + encryption and checksum algorithms are described so that checksums + can be computed given negotiated keys, without requiring further + negotiation for checksum types. + +Notes + + [1] Although Message Authentication Code (MAC) or Message Integrity + Check (MIC) would be more appropriate terms for many of the uses + in this document, we continue to use the term checksum for + historical reasons. + + [2] Extending CBC mode across messages would be one obvious example + of this chaining. Another might be the use of counter mode, with + a counter randomly initialized and attached to the ciphertext; a + second message could continue incrementing the counter when + chaining the cipher state, thus avoiding having to transmit + another counter value. However, this chaining is only useful for + uninterrupted, ordered sequences of messages. + + [3] In the case of Kerberos, the encrypted objects will generally be + ASN.1 DER encodings, which contain indications of their length in + the first few octets. + + [4] As of the time of this writing, new modes of operation have been + proposed, some of which may permit encryption and integrity + protection simultaneously. After some of these proposals have + been subjected to adequate analysis, we may wish to formulate a + new simplified profile based on one of them. + + [5] It should be noted that the sample vector in appendix B.2 of the + original paper appears to be incorrect. Two independent + implementations from the specification (one in C by Marc + Horowitz, and another in Scheme by Bill Sommerfeld) agree on a + value different from that in [Blumenthal96]. + + [6] For example, in MIT's implementation of [Kerb1510], the rsa-md5 + unkeyed checksum of application data may be included in an + authenticator encrypted in a service's key. + + [7] Using a variant of the key limits the use of a key to a + particular function, separating the functions of generating a + + + +Raeburn Standards Track [Page 46] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + checksum from other encryption performed using the session key. + The constant 0xF0F0F0F0F0F0F0F0 was chosen because it maintains + key parity. The properties of DES precluded the use of the + complement. The same constant is used for similar purpose in the + Message Integrity Check in the Privacy Enhanced Mail standard. + + [8] Perhaps one of the more common reasons for directly performing + encryption is direct control over the negotiation and to select a + "sufficiently strong" encryption algorithm (whatever that means + in the context of a given application). Although Kerberos + directly provides no direct facility for negotiating encryption + types between the application client and server, there are other + means to accomplish similar goals (for example, requesting only + "strong" session key types from the KDC, and assuming that the + type actually returned by the KDC will be understood and + supported by the application server). + +Normative References + + [BCP26] Narten, T. and H. Alvestrand, "Guidelines for Writing + an IANA Considerations Section in RFCs", BCP 26, RFC + 2434, October 1998. + + [Bellare98] Bellare, M., Desai, A., Pointcheval, D., and P. + Rogaway, "Relations Among Notions of Security for + Public-Key Encryption Schemes". Extended abstract + published in Advances in Cryptology-Crypto 98 + Proceedings, Lecture Notes in Computer Science Vol. + 1462, H. Krawcyzk ed., Springer-Verlag, 1998. + + [Blumenthal96] Blumenthal, U. and S. Bellovin, "A Better Key Schedule + for DES-Like Ciphers", Proceedings of PRAGOCRYPT '96, + 1996. + + [CRC] International Organization for Standardization, "ISO + Information Processing Systems - Data Communication - + High-Level Data Link Control Procedure - Frame + Structure," IS 3309, 3rd Edition, October 1984. + + [DES77] National Bureau of Standards, U.S. Department of + Commerce, "Data Encryption Standard," Federal + Information Processing Standards Publication 46, + Washington, DC, 1977. + + + + + + + + +Raeburn Standards Track [Page 47] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + [DESI81] National Bureau of Standards, U.S. Department of + Commerce, "Guidelines for implementing and using NBS + Data Encryption Standard," Federal Information + Processing Standards Publication 74, Washington, DC, + 1981. + + [DESM80] National Bureau of Standards, U.S. Department of + Commerce, "DES Modes of Operation," Federal + Information Processing Standards Publication 81, + Springfield, VA, December 1980. + + [Dolev91] Dolev, D., Dwork, C., and M. Naor, "Non-malleable + cryptography", Proceedings of the 23rd Annual + Symposium on Theory of Computing, ACM, 1991. + + [HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: + Keyed-Hashing for Message Authentication", RFC 2104, + February 1997. + + [KRB5-AES] Raeburn, K., "Advanced Encryption Standard (AES) + Encryption for Kerberos 5", RFC 3962, February 2005. + + [MD4-92] Rivest, R., "The MD4 Message-Digest Algorithm", RFC + 1320, April 1992. + + [MD5-92] Rivest, R., "The MD5 Message-Digest Algorithm ", RFC + 1321, April 1992. + + [SG92] Stubblebine, S. and V. D. Gligor, "On Message + Integrity in Cryptographic Protocols," in Proceedings + of the IEEE Symposium on Research in Security and + Privacy, Oakland, California, May 1992. + +Informative References + + [Bellovin91] Bellovin, S. M. and M. Merrit, "Limitations of the + Kerberos Authentication System", in Proceedings of the + Winter 1991 Usenix Security Conference, January, 1991. + + [Bellovin99] Bellovin, S. M. and D. Atkins, private communications, + 1999. + + [EFF-DES] Electronic Frontier Foundation, "Cracking DES: Secrets + of Encryption Research, Wiretap Politics, and Chip + Design", O'Reilly & Associates, Inc., May 1998. + + [ESP-DES] Madson, C. and N. Doraswamy, "The ESP DES-CBC Cipher + Algorithm With Explicit IV", RFC 2405, November 1998. + + + +Raeburn Standards Track [Page 48] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + + [GSS-KRB5] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", + RFC 1964, June 1996. + + [HMAC-TEST] Cheng, P. and R. Glenn, "Test Cases for HMAC-MD5 and + HMAC-SHA-1", RFC 2202, September 1997. + + [IPSEC-HMAC] Madson, C. and R. Glenn, "The Use of HMAC-SHA-1-96 + within ESP and AH", RFC 2404, November 1998. + + [Kerb] Neuman, C., Yu, T., Hartman, S., and K. Raeburn, "The + Kerberos Network Authentication Service (V5)", Work in + Progress, September 2004. + + [Kerb1510] Kohl, J. and C. Neuman, "The Kerberos Network + Authentication Service (V5)", RFC 1510, September + 1993. + + [RC5] Baldwin, R. and R. Rivest, "The RC5, RC5-CBC, RC5- + CBC-Pad, and RC5-CTS Algorithms", RFC 2040, October + 1996. + + [RFC1851] Karn, P., Metzger, P., and W. Simpson, "The ESP Triple + DES Transform", RFC 1851, September 1995. + + [Schneier96] Schneier, B., "Applied Cryptography Second Edition", + John Wiley & Sons, New York, NY, 1996. ISBN 0-471- + 12845-7. + +Editor's Address + + Kenneth Raeburn + Massachusetts Institute of Technology + 77 Massachusetts Avenue + Cambridge, MA 02139 + + EMail: raeburn@mit.edu + + + + + + + + + + + + + + + +Raeburn Standards Track [Page 49] + +RFC 3961 Encryption and Checksum Specifications February 2005 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2005). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the IETF's procedures with respect to rights in IETF Documents can + be found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at ietf- + ipr@ietf.org. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + +Raeburn Standards Track [Page 50] + diff --git a/krb5-1-6/doc/krb5-protocol/rfc3962.txt b/krb5-1-6/doc/krb5-protocol/rfc3962.txt new file mode 100644 index 000000000..762beedbd --- /dev/null +++ b/krb5-1-6/doc/krb5-protocol/rfc3962.txt @@ -0,0 +1,899 @@ + + + + + + +Network Working Group K. Raeburn +Request for Comments: 3962 MIT +Category: Standards Track February 2005 + + + Advanced Encryption Standard (AES) Encryption for Kerberos 5 + +Status of This Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2005). + +Abstract + + The United States National Institute of Standards and Technology + (NIST) has chosen a new Advanced Encryption Standard (AES), which is + significantly faster and (it is believed) more secure than the old + Data Encryption Standard (DES) algorithm. This document is a + specification for the addition of this algorithm to the Kerberos + cryptosystem suite. + +1. Introduction + + This document defines encryption key and checksum types for Kerberos + 5 using the AES algorithm recently chosen by NIST. These new types + support 128-bit block encryption and key sizes of 128 or 256 bits. + + Using the "simplified profile" of [KCRYPTO], we can define a pair of + encryption and checksum schemes. AES is used with ciphertext + stealing to avoid message expansion, and SHA-1 [SHA1] is the + associated checksum function. + +2. Conventions used in this Document + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in BCP 14, RFC 2119 + [KEYWORDS]. + + + + + + +Raeburn Standards Track [Page 1] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + +3. Protocol Key Representation + + The profile in [KCRYPTO] treats keys and random octet strings as + conceptually different. But since the AES key space is dense, we can + use any bit string of appropriate length as a key. We use the byte + representation for the key described in [AES], where the first bit of + the bit string is the high bit of the first byte of the byte string + (octet string) representation. + +4. Key Generation from Pass Phrases or Random Data + + Given the above format for keys, we can generate keys from the + appropriate amounts of random data (128 or 256 bits) by simply + copying the input string. + + To generate an encryption key from a pass phrase and salt string, we + use the PBKDF2 function from PKCS #5 v2.0 ([PKCS5]), with parameters + indicated below, to generate an intermediate key (of the same length + as the desired final key), which is then passed into the DK function + with the 8-octet ASCII string "kerberos" as is done for des3-cbc- + hmac-sha1-kd in [KCRYPTO]. (In [KCRYPTO] terms, the PBKDF2 function + produces a "random octet string", hence the application of the + random-to-key function even though it's effectively a simple identity + operation.) The resulting key is the user's long-term key for use + with the encryption algorithm in question. + + tkey = random2key(PBKDF2(passphrase, salt, iter_count, keylength)) + key = DK(tkey, "kerberos") + + The pseudorandom function used by PBKDF2 will be a SHA-1 HMAC of the + passphrase and salt, as described in Appendix B.1 to PKCS#5. + + The number of iterations is specified by the string-to-key parameters + supplied. The parameter string is four octets indicating an unsigned + number in big-endian order. This is the number of iterations to be + performed. If the value is 00 00 00 00, the number of iterations to + be performed is 4,294,967,296 (2**32). (Thus the minimum expressible + iteration count is 1.) + + For environments where slower hardware is the norm, implementations + of protocols such as Kerberos may wish to limit the number of + iterations to prevent a spoofed response supplied by an attacker from + consuming lots of client-side CPU time; if such a limit is + implemented, it SHOULD be no less than 50,000. Even for environments + with fast hardware, 4 billion iterations is likely to take a fairly + long time; much larger bounds might still be enforced, and it might + be wise for implementations to permit interruption of this operation + by the user if the environment allows for it. + + + +Raeburn Standards Track [Page 2] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + If the string-to-key parameters are not supplied, the value used is + 00 00 10 00 (decimal 4,096, indicating 4,096 iterations). + + Note that this is not a requirement, nor even a recommendation, for + this value to be used in "optimistic preauthentication" (e.g., + attempting timestamp-based preauthentication using the user's long- + term key without having first communicated with the KDC) in the + absence of additional information, or as a default value for sites to + use for their principals' long-term keys in their Kerberos database. + It is simply the interpretation of the absence of the string-to-key + parameter field when the KDC has had an opportunity to provide it. + + Sample test vectors are given in Appendix B. + +5. Ciphertext Stealing + + Cipher block chaining is used to encrypt messages, with the initial + vector stored in the cipher state. Unlike previous Kerberos + cryptosystems, we use ciphertext stealing to handle the possibly + partial final block of the message. + + Ciphertext stealing is described on pages 195-196 of [AC], and + section 8 of [RC5]; it has the advantage that no message expansion is + done during encryption of messages of arbitrary sizes as is typically + done in CBC mode with padding. Some errata for [RC5] are listed in + Appendix A and are considered part of the ciphertext stealing + technique as used here. + + Ciphertext stealing, as defined in [RC5], assumes that more than one + block of plain text is available. If exactly one block is to be + encrypted, that block is simply encrypted with AES (also known as ECB + mode). Input smaller than one block is padded at the end to one + block; the values of the padding bits are unspecified. + (Implementations MAY use all-zero padding, but protocols MUST NOT + rely on the result being deterministic. Implementations MAY use + random padding, but protocols MUST NOT rely on the result not being + deterministic. Note that in most cases, the Kerberos encryption + profile will add a random confounder independent of this padding.) + + For consistency, ciphertext stealing is always used for the last two + blocks of the data to be encrypted, as in [RC5]. If the data length + is a multiple of the block size, this is equivalent to plain CBC mode + with the last two ciphertext blocks swapped. + + A test vector is given in Appendix B. + + + + + + +Raeburn Standards Track [Page 3] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + The initial vector carried out from one encryption for use in a + subsequent encryption is the next-to-last block of the encryption + output; this is the encrypted form of the last plaintext block. When + decrypting, the next-to-last block of the supplied ciphertext is + carried forward as the next initial vector. If only one ciphertext + block is available (decrypting one block, or encrypting one block or + less), then that one block is carried out instead. + +6. Kerberos Algorithm Profile Parameters + + This is a summary of the parameters to be used with the simplified + algorithm profile described in [KCRYPTO]: + + +--------------------------------------------------------------------+ + | protocol key format 128- or 256-bit string | + | | + | string-to-key function PBKDF2+DK with variable | + | iteration count (see | + | above) | + | | + | default string-to-key parameters 00 00 10 00 | + | | + | key-generation seed length key size | + | | + | random-to-key function identity function | + | | + | hash function, H SHA-1 | + | | + | HMAC output size, h 12 octets (96 bits) | + | | + | message block size, m 1 octet | + | | + | encryption/decryption functions, AES in CBC-CTS mode | + | E and D (cipher block size 16 | + | octets), with next-to- | + | last block (last block | + | if only one) as CBC-style | + | ivec | + +--------------------------------------------------------------------+ + + Using this profile with each key size gives us two each of encryption + and checksum algorithm definitions. + + + + + + + + + +Raeburn Standards Track [Page 4] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + +7. Assigned Numbers + + The following encryption type numbers are assigned: + + +--------------------------------------------------------------------+ + | encryption types | + +--------------------------------------------------------------------+ + | type name etype value key size | + +--------------------------------------------------------------------+ + | aes128-cts-hmac-sha1-96 17 128 | + | aes256-cts-hmac-sha1-96 18 256 | + +--------------------------------------------------------------------+ + + The following checksum type numbers are assigned: + + +--------------------------------------------------------------------+ + | checksum types | + +--------------------------------------------------------------------+ + | type name sumtype value length | + +--------------------------------------------------------------------+ + | hmac-sha1-96-aes128 15 96 | + | hmac-sha1-96-aes256 16 96 | + +--------------------------------------------------------------------+ + + These checksum types will be used with the corresponding encryption + types defined above. + +8. Security Considerations + + This new algorithm has not been around long enough to receive the + decades of intense analysis that DES has received. It is possible + that some weakness exists that has not been found by the + cryptographers analyzing these algorithms before and during the AES + selection process. + + The use of the HMAC function has drawbacks for certain pass phrase + lengths. For example, a pass phrase longer than the hash function + block size (64 bytes, for SHA-1) is hashed to a smaller size (20 + bytes) before applying the main HMAC algorithm. However, entropy is + generally sparse in pass phrases, especially in long ones, so this + may not be a problem in the rare cases of users with long pass + phrases. + + Also, generating a 256-bit key from a pass phrase of any length may + be deceptive, as the effective entropy in pass-phrase-derived key + cannot be nearly that large given the properties of the string-to-key + function described here. + + + + +Raeburn Standards Track [Page 5] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + The iteration count in PBKDF2 appears to be useful primarily as a + constant multiplier for the amount of work required for an attacker + using brute-force methods. Unfortunately, it also multiplies, by the + same amount, the work needed by a legitimate user with a valid + password. Thus the work factor imposed on an attacker (who may have + many powerful workstations at his disposal) must be balanced against + the work factor imposed on the legitimate user (who may have a PDA or + cell phone); the available computing power on either side increases + as time goes on, as well. A better way to deal with the brute-force + attack is through preauthentication mechanisms that provide better + protection of the user's long-term key. Use of such mechanisms is + out of the scope of this document. + + If a site does wish to use this means of protection against a brute- + force attack, the iteration count should be chosen based on the + facilities available to both attacker and legitimate user, and the + amount of work the attacker should be required to perform to acquire + the key or password. + + As an example: + + The author's tests on a 2GHz Pentium 4 system indicated that in + one second, nearly 90,000 iterations could be done, producing a + 256-bit key. This was using the SHA-1 assembly implementation + from OpenSSL, and a pre-release version of the PBKDF2 code for + MIT's Kerberos package, on a single system. No attempt was made + to do multiple hashes in parallel, so we assume an attacker doing + so can probably do at least 100,000 iterations per second -- + rounded up to 2**17, for ease of calculation. For simplicity, we + also assume the final AES encryption step costs nothing. + + Paul Leach estimates [LEACH] that a password-cracking dictionary + may have on the order of 2**21 entries, with capitalization, + punctuation, and other variations contributing perhaps a factor of + 2**11, giving a ballpark estimate of 2**32. + + Thus, for a known iteration count N and a known salt string, an + attacker with some number of computers comparable to the author's + would need roughly N*2**15 CPU seconds to convert the entire + dictionary plus variations into keys. + + An attacker using a dozen such computers for a month would have + roughly 2**25 CPU seconds available. So using 2**12 (4,096) + iterations would mean an attacker with a dozen such computers + dedicated to a brute-force attack against a single key (actually, + any password-derived keys sharing the same salt and iteration + + + + + +Raeburn Standards Track [Page 6] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + count) would process all the variations of the dictionary entries + in four months and, on average, would likely find the user's + password in two months. + + Thus, if this form of attack is of concern, users should be + required to change their passwords every few months, and an + iteration count a few orders of magnitude higher should be chosen. + Perhaps several orders of magnitude, as many users will tend to + use the shorter and simpler passwords (to the extent they can, + given a site's password quality checks) that the attacker would + likely try first. + + Since this estimate is based on currently available CPU power, the + iteration counts used for this mode of defense should be increased + over time, at perhaps 40%-60% each year or so. + + Note that if the attacker has a large amount of storage available, + intermediate results could be cached, saving a lot of work for the + next attack with the same salt and a greater number of iterations + than had been run at the point where the intermediate results were + saved. Thus, it would be wise to generate a new random salt + string when passwords are changed. The default salt string, + derived from the principal name, only protects against the use of + one dictionary of keys against multiple users. + + If the PBKDF2 iteration count can be spoofed by an intruder on the + network, and the limit on the accepted iteration count is very high, + the intruder may be able to introduce a form of denial of service + attack against the client by sending a very high iteration count, + causing the client to spend a great deal of CPU time computing an + incorrect key. + + An intruder spoofing the KDC reply, providing a low iteration count + and reading the client's reply from the network, may be able to + reduce the work needed in the brute-force attack outlined above. + Thus, implementations may seek to enforce lower bounds on the number + of iterations that will be used. + + Since threat models and typical end-user equipment will vary widely + from site to site, allowing site-specific configuration of such + bounds is recommended. + + Any benefit against other attacks specific to the HMAC or SHA-1 + algorithms is probably achieved with a fairly small number of + iterations. + + + + + + +Raeburn Standards Track [Page 7] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + In the "optimistic preauthentication" case mentioned in section 3, + the client may attempt to produce a key without first communicating + with the KDC. If the client has no additional information, it can + only guess as to the iteration count to be used. Even such + heuristics as "iteration count X was used to acquire tickets for the + same principal only N hours ago" can be wrong. Given the + recommendation above for increasing the iteration counts used over + time, it is impossible to recommend any specific default value for + this case; allowing site-local configuration is recommended. (If the + lower and upper bound checks described above are implemented, the + default count for optimistic preauthentication should be between + those bounds.) + + Ciphertext stealing mode, as it requires no additional padding in + most cases, will reveal the exact length of each message being + encrypted rather than merely bounding it to a small range of possible + lengths as in CBC mode. Such obfuscation should not be relied upon + at higher levels in any case; if the length must be obscured from an + outside observer, this should be done by intentionally varying the + length of the message to be encrypted. + +9. IANA Considerations + + Kerberos encryption and checksum type values used in section 7 were + previously reserved in [KCRYPTO] for the mechanisms defined in this + document. The registries have been updated to list this document as + the reference. + +10. Acknowledgements + + Thanks to John Brezak, Gerardo Diaz Cuellar, Ken Hornstein, Paul + Leach, Marcus Watts, Larry Zhu, and others for feedback on earlier + versions of this document. + + + + + + + + + + + + + + + + + + +Raeburn Standards Track [Page 8] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + +A. Errata for RFC 2040 Section 8 + + (Copied from the RFC Editor's errata web site on July 8, 2004.) + + Reported By: Bob Baldwin; baldwin@plusfive.com + Date: Fri, 26 Mar 2004 06:49:02 -0800 + + In Section 8, Description of RC5-CTS, of the encryption method, + it says: + + 1. Exclusive-or Pn-1 with the previous ciphertext + block, Cn-2, to create Xn-1. + + It should say: + + 1. Exclusive-or Pn-1 with the previous ciphertext + block, Cn-2, to create Xn-1. For short messages where + Cn-2 does not exist, use IV. + + Reported By: Bob Baldwin; baldwin@plusfive.com + Date: Mon, 22 Mar 2004 20:26:40 -0800 + + In Section 8, first paragraph, second sentence says: + + This mode handles any length of plaintext and produces ciphertext + whose length matches the plaintext length. + + In Section 8, first paragraph, second sentence should read: + + This mode handles any length of plaintext longer than one + block and produces ciphertext whose length matches the + plaintext length. + + In Section 8, step 6 of the decryption method says: + + 6. Decrypt En to create Pn-1. + + In Section 8, step 6 of the decryption method should read: + + 6. Decrypt En and exclusive-or with Cn-2 to create Pn-1. + For short messages where Cn-2 does not exist, use the IV. + + + + + + + + + + +Raeburn Standards Track [Page 9] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + +B. Sample Test Vectors + + Sample values for the PBKDF2 HMAC-SHA1 string-to-key function are + included below. + + Iteration count = 1 + Pass phrase = "password" + Salt = "ATHENA.MIT.EDUraeburn" + 128-bit PBKDF2 output: + cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15 + 128-bit AES key: + 42 26 3c 6e 89 f4 fc 28 b8 df 68 ee 09 79 9f 15 + 256-bit PBKDF2 output: + cd ed b5 28 1b b2 f8 01 56 5a 11 22 b2 56 35 15 + 0a d1 f7 a0 4b b9 f3 a3 33 ec c0 e2 e1 f7 08 37 + 256-bit AES key: + fe 69 7b 52 bc 0d 3c e1 44 32 ba 03 6a 92 e6 5b + bb 52 28 09 90 a2 fa 27 88 39 98 d7 2a f3 01 61 + + Iteration count = 2 + Pass phrase = "password" + Salt="ATHENA.MIT.EDUraeburn" + 128-bit PBKDF2 output: + 01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d + 128-bit AES key: + c6 51 bf 29 e2 30 0a c2 7f a4 69 d6 93 bd da 13 + 256-bit PBKDF2 output: + 01 db ee 7f 4a 9e 24 3e 98 8b 62 c7 3c da 93 5d + a0 53 78 b9 32 44 ec 8f 48 a9 9e 61 ad 79 9d 86 + 256-bit AES key: + a2 e1 6d 16 b3 60 69 c1 35 d5 e9 d2 e2 5f 89 61 + 02 68 56 18 b9 59 14 b4 67 c6 76 22 22 58 24 ff + + Iteration count = 1200 + Pass phrase = "password" + Salt = "ATHENA.MIT.EDUraeburn" + 128-bit PBKDF2 output: + 5c 08 eb 61 fd f7 1e 4e 4e c3 cf 6b a1 f5 51 2b + 128-bit AES key: + 4c 01 cd 46 d6 32 d0 1e 6d be 23 0a 01 ed 64 2a + 256-bit PBKDF2 output: + 5c 08 eb 61 fd f7 1e 4e 4e c3 cf 6b a1 f5 51 2b + a7 e5 2d db c5 e5 14 2f 70 8a 31 e2 e6 2b 1e 13 + 256-bit AES key: + 55 a6 ac 74 0a d1 7b 48 46 94 10 51 e1 e8 b0 a7 + 54 8d 93 b0 ab 30 a8 bc 3f f1 62 80 38 2b 8c 2a + + + + + +Raeburn Standards Track [Page 10] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + Iteration count = 5 + Pass phrase = "password" + Salt=0x1234567878563412 + 128-bit PBKDF2 output: + d1 da a7 86 15 f2 87 e6 a1 c8 b1 20 d7 06 2a 49 + 128-bit AES key: + e9 b2 3d 52 27 37 47 dd 5c 35 cb 55 be 61 9d 8e + 256-bit PBKDF2 output: + d1 da a7 86 15 f2 87 e6 a1 c8 b1 20 d7 06 2a 49 + 3f 98 d2 03 e6 be 49 a6 ad f4 fa 57 4b 6e 64 ee + 256-bit AES key: + 97 a4 e7 86 be 20 d8 1a 38 2d 5e bc 96 d5 90 9c + ab cd ad c8 7c a4 8f 57 45 04 15 9f 16 c3 6e 31 + (This test is based on values given in [PECMS].) + + Iteration count = 1200 + Pass phrase = (64 characters) + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Salt="pass phrase equals block size" + 128-bit PBKDF2 output: + 13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9 + 128-bit AES key: + 59 d1 bb 78 9a 82 8b 1a a5 4e f9 c2 88 3f 69 ed + 256-bit PBKDF2 output: + 13 9c 30 c0 96 6b c3 2b a5 5f db f2 12 53 0a c9 + c5 ec 59 f1 a4 52 f5 cc 9a d9 40 fe a0 59 8e d1 + 256-bit AES key: + 89 ad ee 36 08 db 8b c7 1f 1b fb fe 45 94 86 b0 + 56 18 b7 0c ba e2 20 92 53 4e 56 c5 53 ba 4b 34 + + Iteration count = 1200 + Pass phrase = (65 characters) + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Salt = "pass phrase exceeds block size" + 128-bit PBKDF2 output: + 9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61 + 128-bit AES key: + cb 80 05 dc 5f 90 17 9a 7f 02 10 4c 00 18 75 1d + 256-bit PBKDF2 output: + 9c ca d6 d4 68 77 0c d5 1b 10 e6 a6 87 21 be 61 + 1a 8b 4d 28 26 01 db 3b 36 be 92 46 91 5e c8 2a + 256-bit AES key: + d7 8c 5c 9c b8 72 a8 c9 da d4 69 7f 0b b5 b2 d2 + 14 96 c8 2b eb 2c ae da 21 12 fc ee a0 57 40 1b + + + + + + + +Raeburn Standards Track [Page 11] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + Iteration count = 50 + Pass phrase = g-clef (0xf09d849e) + Salt = "EXAMPLE.COMpianist" + 128-bit PBKDF2 output: + 6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39 + 128-bit AES key: + f1 49 c1 f2 e1 54 a7 34 52 d4 3e 7f e6 2a 56 e5 + 256-bit PBKDF2 output: + 6b 9c f2 6d 45 45 5a 43 a5 b8 bb 27 6a 40 3b 39 + e7 fe 37 a0 c4 1e 02 c2 81 ff 30 69 e1 e9 4f 52 + 256-bit AES key: + 4b 6d 98 39 f8 44 06 df 1f 09 cc 16 6d b4 b8 3c + 57 18 48 b7 84 a3 d6 bd c3 46 58 9a 3e 39 3f 9e + + Some test vectors for CBC with ciphertext stealing, using an initial + vector of all-zero. + + AES 128-bit key: + 0000: 63 68 69 63 6b 65 6e 20 74 65 72 69 79 61 6b 69 + + IV: + 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Input: + 0000: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 + 0010: 20 + Output: + 0000: c6 35 35 68 f2 bf 8c b4 d8 a5 80 36 2d a7 ff 7f + 0010: 97 + Next IV: + 0000: c6 35 35 68 f2 bf 8c b4 d8 a5 80 36 2d a7 ff 7f + + IV: + 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Input: + 0000: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 + 0010: 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 + Output: + 0000: fc 00 78 3e 0e fd b2 c1 d4 45 d4 c8 ef f7 ed 22 + 0010: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 + Next IV: + 0000: fc 00 78 3e 0e fd b2 c1 d4 45 d4 c8 ef f7 ed 22 + + + + + + + + + + +Raeburn Standards Track [Page 12] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + IV: + 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Input: + 0000: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 + 0010: 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 + Output: + 0000: 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 + 0010: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 + Next IV: + 0000: 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 + + IV: + 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Input: + 0000: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 + 0010: 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 + 0020: 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c + Output: + 0000: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 + 0010: b3 ff fd 94 0c 16 a1 8c 1b 55 49 d2 f8 38 02 9e + 0020: 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 + Next IV: + 0000: b3 ff fd 94 0c 16 a1 8c 1b 55 49 d2 f8 38 02 9e + + IV: + 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Input: + 0000: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 + 0010: 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 + 0020: 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c 20 + Output: + 0000: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 + 0010: 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8 + 0020: 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 + Next IV: + 0000: 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8 + + + + + + + + + + + + + + + +Raeburn Standards Track [Page 13] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + + IV: + 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Input: + 0000: 49 20 77 6f 75 6c 64 20 6c 69 6b 65 20 74 68 65 + 0010: 20 47 65 6e 65 72 61 6c 20 47 61 75 27 73 20 43 + 0020: 68 69 63 6b 65 6e 2c 20 70 6c 65 61 73 65 2c 20 + 0030: 61 6e 64 20 77 6f 6e 74 6f 6e 20 73 6f 75 70 2e + Output: + 0000: 97 68 72 68 d6 ec cc c0 c0 7b 25 e2 5e cf e5 84 + 0010: 39 31 25 23 a7 86 62 d5 be 7f cb cc 98 eb f5 a8 + 0020: 48 07 ef e8 36 ee 89 a5 26 73 0d bc 2f 7b c8 40 + 0030: 9d ad 8b bb 96 c4 cd c0 3b c1 03 e1 a1 94 bb d8 + Next IV: + 0000: 48 07 ef e8 36 ee 89 a5 26 73 0d bc 2f 7b c8 40 + +Normative References + + [AC] Schneier, B., "Applied Cryptography", second edition, John + Wiley and Sons, New York, 1996. + + [AES] National Institute of Standards and Technology, U.S. + Department of Commerce, "Advanced Encryption Standard", + Federal Information Processing Standards Publication 197, + Washington, DC, November 2001. + + [KCRYPTO] Raeburn, K., "Encryption and Checksum Specifications for + Kerberos 5", RFC 3961, February 2005. + + [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [PKCS5] Kaliski, B., "PKCS #5: Password-Based Cryptography + Specification Version 2.0", RFC 2898, September 2000. + + [RC5] Baldwin, R. and R. Rivest, "The RC5, RC5-CBC, RC5-CBC-Pad, + and RC5-CTS Algorithms", RFC 2040, October 1996. + + [SHA1] National Institute of Standards and Technology, U.S. + Department of Commerce, "Secure Hash Standard", Federal + Information Processing Standards Publication 180-1, + Washington, DC, April 1995. + + + + + + + + + + +Raeburn Standards Track [Page 14] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + +Informative References + + [LEACH] Leach, P., email to IETF Kerberos working group mailing + list, 5 May 2003, ftp://ftp.ietf.org/ietf-mail- + archive/krb-wg/2003-05.mail. + + [PECMS] Gutmann, P., "Password-based Encryption for CMS", RFC + 3211, December 2001. + +Author's Address + + Kenneth Raeburn + Massachusetts Institute of Technology + 77 Massachusetts Avenue + Cambridge, MA 02139 + + EMail: raeburn@mit.edu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Raeburn Standards Track [Page 15] + +RFC 3962 AES Encryption for Kerberos 5 February 2005 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2005). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the IETF's procedures with respect to rights in IETF Documents can + be found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at ietf- + ipr@ietf.org. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + +Raeburn Standards Track [Page 16] + diff --git a/krb5-1-6/doc/krb5-protocol/rfc4120.txt b/krb5-1-6/doc/krb5-protocol/rfc4120.txt new file mode 100644 index 000000000..e2816aff2 --- /dev/null +++ b/krb5-1-6/doc/krb5-protocol/rfc4120.txt @@ -0,0 +1,7731 @@ + + + + + + +Network Working Group C. Neuman +Request for Comments: 4120 USC-ISI +Obsoletes: 1510 T. Yu +Category: Standards Track S. Hartman + K. Raeburn + MIT + July 2005 + + + The Kerberos Network Authentication Service (V5) + +Status of This Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2005). + +Abstract + + This document provides an overview and specification of Version 5 of + the Kerberos protocol, and it obsoletes RFC 1510 to clarify aspects + of the protocol and its intended use that require more detailed or + clearer explanation than was provided in RFC 1510. This document is + intended to provide a detailed description of the protocol, suitable + for implementation, together with descriptions of the appropriate use + of protocol messages and fields within those messages. + + + + + + + + + + + + + + + + + + + +Neuman, et al. Standards Track [Page 1] + +RFC 4120 Kerberos V5 July 2005 + + +Table of Contents + + 1. Introduction ....................................................5 + 1.1. The Kerberos Protocol ......................................6 + 1.2. Cross-Realm Operation ......................................8 + 1.3. Choosing a Principal with Which to Communicate .............9 + 1.4. Authorization .............................................10 + 1.5. Extending Kerberos without Breaking Interoperability ......11 + 1.5.1. Compatibility with RFC 1510 ........................11 + 1.5.2. Sending Extensible Messages ........................12 + 1.6. Environmental Assumptions .................................12 + 1.7. Glossary of Terms .........................................13 + 2. Ticket Flag Uses and Requests ..................................16 + 2.1. Initial, Pre-authenticated, and + Hardware-Authenticated Tickets ............................17 + 2.2. Invalid Tickets ...........................................17 + 2.3. Renewable Tickets .........................................17 + 2.4. Postdated Tickets .........................................18 + 2.5. Proxiable and Proxy Tickets ...............................19 + 2.6. Forwardable Tickets .......................................19 + 2.7. Transited Policy Checking .................................20 + 2.8. OK as Delegate ............................................21 + 2.9. Other KDC Options .........................................21 + 2.9.1. Renewable-OK .......................................21 + 2.9.2. ENC-TKT-IN-SKEY ....................................22 + 2.9.3. Passwordless Hardware Authentication ...............22 + 3. Message Exchanges ..............................................22 + 3.1. The Authentication Service Exchange .......................22 + 3.1.1. Generation of KRB_AS_REQ Message ...................24 + 3.1.2. Receipt of KRB_AS_REQ Message ......................24 + 3.1.3. Generation of KRB_AS_REP Message ...................24 + 3.1.4. Generation of KRB_ERROR Message ....................27 + 3.1.5. Receipt of KRB_AS_REP Message ......................27 + 3.1.6. Receipt of KRB_ERROR Message .......................28 + 3.2. The Client/Server Authentication Exchange .................29 + 3.2.1. The KRB_AP_REQ Message .............................29 + 3.2.2. Generation of a KRB_AP_REQ Message .................29 + 3.2.3. Receipt of KRB_AP_REQ Message ......................30 + 3.2.4. Generation of a KRB_AP_REP Message .................33 + 3.2.5. Receipt of KRB_AP_REP Message ......................33 + 3.2.6. Using the Encryption Key ...........................33 + 3.3. The Ticket-Granting Service (TGS) Exchange ................34 + 3.3.1. Generation of KRB_TGS_REQ Message ..................35 + 3.3.2. Receipt of KRB_TGS_REQ Message .....................37 + 3.3.3. Generation of KRB_TGS_REP Message ..................38 + 3.3.4. Receipt of KRB_TGS_REP Message .....................42 + + + + + +Neuman, et al. Standards Track [Page 2] + +RFC 4120 Kerberos V5 July 2005 + + + 3.4. The KRB_SAFE Exchange .....................................42 + 3.4.1. Generation of a KRB_SAFE Message ...................42 + 3.4.2. Receipt of KRB_SAFE Message ........................43 + 3.5. The KRB_PRIV Exchange .....................................44 + 3.5.1. Generation of a KRB_PRIV Message ...................44 + 3.5.2. Receipt of KRB_PRIV Message ........................44 + 3.6. The KRB_CRED Exchange .....................................45 + 3.6.1. Generation of a KRB_CRED Message ...................45 + 3.6.2. Receipt of KRB_CRED Message ........................46 + 3.7. User-to-User Authentication Exchanges .....................47 + 4. Encryption and Checksum Specifications .........................48 + 5. Message Specifications .........................................50 + 5.1. Specific Compatibility Notes on ASN.1 .....................51 + 5.1.1. ASN.1 Distinguished Encoding Rules .................51 + 5.1.2. Optional Integer Fields ............................52 + 5.1.3. Empty SEQUENCE OF Types ............................52 + 5.1.4. Unrecognized Tag Numbers ...........................52 + 5.1.5. Tag Numbers Greater Than 30 ........................53 + 5.2. Basic Kerberos Types ......................................53 + 5.2.1. KerberosString .....................................53 + 5.2.2. Realm and PrincipalName ............................55 + 5.2.3. KerberosTime .......................................55 + 5.2.4. Constrained Integer Types ..........................55 + 5.2.5. HostAddress and HostAddresses ......................56 + 5.2.6. AuthorizationData ..................................57 + 5.2.7. PA-DATA ............................................60 + 5.2.8. KerberosFlags ......................................64 + 5.2.9. Cryptosystem-Related Types .........................65 + 5.3. Tickets ...................................................66 + 5.4. Specifications for the AS and TGS Exchanges ...............73 + 5.4.1. KRB_KDC_REQ Definition .............................73 + 5.4.2. KRB_KDC_REP Definition .............................81 + 5.5. Client/Server (CS) Message Specifications .................84 + 5.5.1. KRB_AP_REQ Definition ..............................84 + 5.5.2. KRB_AP_REP Definition ..............................88 + 5.5.3. Error Message Reply ................................89 + 5.6. KRB_SAFE Message Specification ............................89 + 5.6.1. KRB_SAFE definition ................................89 + 5.7. KRB_PRIV Message Specification ............................91 + 5.7.1. KRB_PRIV Definition ................................91 + 5.8. KRB_CRED Message Specification ............................92 + 5.8.1. KRB_CRED Definition ................................92 + 5.9. Error Message Specification ...............................94 + 5.9.1. KRB_ERROR Definition ...............................94 + 5.10. Application Tag Numbers ..................................96 + + + + + + +Neuman, et al. Standards Track [Page 3] + +RFC 4120 Kerberos V5 July 2005 + + + 6. Naming Constraints .............................................97 + 6.1. Realm Names ...............................................97 + 6.2. Principal Names .......................................... 99 + 6.2.1. Name of Server Principals .........................100 + 7. Constants and Other Defined Values ............................101 + 7.1. Host Address Types .......................................101 + 7.2. KDC Messaging: IP Transports .............................102 + 7.2.1. UDP/IP transport ..................................102 + 7.2.2. TCP/IP Transport ..................................103 + 7.2.3. KDC Discovery on IP Networks ......................104 + 7.3. Name of the TGS ..........................................105 + 7.4. OID Arc for KerberosV5 ...................................106 + 7.5. Protocol Constants and Associated Values .................106 + 7.5.1. Key Usage Numbers .................................106 + 7.5.2. PreAuthentication Data Types ......................108 + 7.5.3. Address Types .....................................109 + 7.5.4. Authorization Data Types ..........................109 + 7.5.5. Transited Encoding Types ..........................109 + 7.5.6. Protocol Version Number ...........................109 + 7.5.7. Kerberos Message Types ............................110 + 7.5.8. Name Types ........................................110 + 7.5.9. Error Codes .......................................110 + 8. Interoperability Requirements .................................113 + 8.1. Specification 2 ..........................................113 + 8.2. Recommended KDC Values ...................................116 + 9. IANA Considerations ...........................................116 + 10. Security Considerations ......................................117 + 11. Acknowledgements .............................................121 + A. ASN.1 Module ..................................................123 + B. Changes since RFC 1510 ........................................131 + Normative References .............................................134 + Informative References ...........................................135 + + + + + + + + + + + + + + + + + + + +Neuman, et al. Standards Track [Page 4] + +RFC 4120 Kerberos V5 July 2005 + + +1. Introduction + + This document describes the concepts and model upon which the + Kerberos network authentication system is based. It also specifies + Version 5 of the Kerberos protocol. The motivations, goals, + assumptions, and rationale behind most design decisions are treated + cursorily; they are more fully described in a paper available in IEEE + communications [NT94] and earlier in the Kerberos portion of the + Athena Technical Plan [MNSS87]. + + This document is not intended to describe Kerberos to the end user, + system administrator, or application developer. Higher-level papers + describing Version 5 of the Kerberos system [NT94] and documenting + version 4 [SNS88] are available elsewhere. + + The Kerberos model is based in part on Needham and Schroeder's + trusted third-party authentication protocol [NS78] and on + modifications suggested by Denning and Sacco [DS81]. The original + design and implementation of Kerberos Versions 1 through 4 was the + work of two former Project Athena staff members, Steve Miller of + Digital Equipment Corporation and Clifford Neuman (now at the + Information Sciences Institute of the University of Southern + California), along with Jerome Saltzer, Technical Director of Project + Athena, and Jeffrey Schiller, MIT Campus Network Manager. Many other + members of Project Athena have also contributed to the work on + Kerberos. + + Version 5 of the Kerberos protocol (described in this document) has + evolved because of new requirements and desires for features not + available in Version 4. The design of Version 5 was led by Clifford + Neuman and John Kohl with much input from the community. The + development of the MIT reference implementation was led at MIT by + John Kohl and Theodore Ts'o, with help and contributed code from many + others. Since RFC 1510 was issued, many individuals have proposed + extensions and revisions to the protocol. This document reflects + some of these proposals. Where such changes involved significant + effort, the document cites the contribution of the proposer. + + Reference implementations of both Version 4 and Version 5 of Kerberos + are publicly available, and commercial implementations have been + developed and are widely used. Details on the differences between + Versions 4 and 5 can be found in [KNT94]. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in [RFC2119]. + + + + + +Neuman, et al. Standards Track [Page 5] + +RFC 4120 Kerberos V5 July 2005 + + +1.1. The Kerberos Protocol + + Kerberos provides a means of verifying the identities of principals, + (e.g., a workstation user or a network server) on an open + (unprotected) network. This is accomplished without relying on + assertions by the host operating system, without basing trust on host + addresses, without requiring physical security of all the hosts on + the network, and under the assumption that packets traveling along + the network can be read, modified, and inserted at will. Kerberos + performs authentication under these conditions as a trusted third- + party authentication service by using conventional (shared secret + key) cryptography. Extensions to Kerberos (outside the scope of this + document) can provide for the use of public key cryptography during + certain phases of the authentication protocol. Such extensions + support Kerberos authentication for users registered with public key + certification authorities and provide certain benefits of public key + cryptography in situations where they are needed. + + The basic Kerberos authentication process proceeds as follows: A + client sends a request to the authentication server (AS) for + "credentials" for a given server. The AS responds with these + credentials, encrypted in the client's key. The credentials consist + of a "ticket" for the server and a temporary encryption key (often + called a "session key"). The client transmits the ticket (which + contains the client's identity and a copy of the session key, all + encrypted in the server's key) to the server. The session key (now + shared by the client and server) is used to authenticate the client + and may optionally be used to authenticate the server. It may also + be used to encrypt further communication between the two parties or + to exchange a separate sub-session key to be used to encrypt further + communication. Note that many applications use Kerberos' functions + only upon the initiation of a stream-based network connection. + Unless an application performs encryption or integrity protection for + the data stream, the identity verification applies only to the + initiation of the connection, and it does not guarantee that + subsequent messages on the connection originate from the same + principal. + + Implementation of the basic protocol consists of one or more + authentication servers running on physically secure hosts. The + authentication servers maintain a database of principals (i.e., users + and servers) and their secret keys. Code libraries provide + encryption and implement the Kerberos protocol. In order to add + authentication to its transactions, a typical network application + adds calls to the Kerberos library directly or through the Generic + Security Services Application Programming Interface (GSS-API) + described in a separate document [RFC4121]. These calls result in + the transmission of the messages necessary to achieve authentication. + + + +Neuman, et al. Standards Track [Page 6] + +RFC 4120 Kerberos V5 July 2005 + + + The Kerberos protocol consists of several sub-protocols (or + exchanges). There are two basic methods by which a client can ask a + Kerberos server for credentials. In the first approach, the client + sends a cleartext request for a ticket for the desired server to the + AS. The reply is sent encrypted in the client's secret key. Usually + this request is for a ticket-granting ticket (TGT), which can later + be used with the ticket-granting server (TGS). In the second method, + the client sends a request to the TGS. The client uses the TGT to + authenticate itself to the TGS in the same manner as if it were + contacting any other application server that requires Kerberos + authentication. The reply is encrypted in the session key from the + TGT. Though the protocol specification describes the AS and the TGS + as separate servers, in practice they are implemented as different + protocol entry points within a single Kerberos server. + + Once obtained, credentials may be used to verify the identity of the + principals in a transaction, to ensure the integrity of messages + exchanged between them, or to preserve privacy of the messages. The + application is free to choose whatever protection may be necessary. + + To verify the identities of the principals in a transaction, the + client transmits the ticket to the application server. Because the + ticket is sent "in the clear" (parts of it are encrypted, but this + encryption doesn't thwart replay) and might be intercepted and reused + by an attacker, additional information is sent to prove that the + message originated with the principal to whom the ticket was issued. + This information (called the authenticator) is encrypted in the + session key and includes a timestamp. The timestamp proves that the + message was recently generated and is not a replay. Encrypting the + authenticator in the session key proves that it was generated by a + party possessing the session key. Since no one except the requesting + principal and the server know the session key (it is never sent over + the network in the clear), this guarantees the identity of the + client. + + The integrity of the messages exchanged between principals can also + be guaranteed by using the session key (passed in the ticket and + contained in the credentials). This approach provides detection of + both replay attacks and message stream modification attacks. It is + accomplished by generating and transmitting a collision-proof + checksum (elsewhere called a hash or digest function) of the client's + message, keyed with the session key. Privacy and integrity of the + messages exchanged between principals can be secured by encrypting + the data to be passed by using the session key contained in the + ticket or the sub-session key found in the authenticator. + + + + + + +Neuman, et al. Standards Track [Page 7] + +RFC 4120 Kerberos V5 July 2005 + + + The authentication exchanges mentioned above require read-only access + to the Kerberos database. Sometimes, however, the entries in the + database must be modified, such as when adding new principals or + changing a principal's key. This is done using a protocol between a + client and a third Kerberos server, the Kerberos Administration + Server (KADM). There is also a protocol for maintaining multiple + copies of the Kerberos database. Neither of these protocols are + described in this document. + +1.2. Cross-Realm Operation + + The Kerberos protocol is designed to operate across organizational + boundaries. A client in one organization can be authenticated to a + server in another. Each organization wishing to run a Kerberos + server establishes its own "realm". The name of the realm in which a + client is registered is part of the client's name and can be used by + the end-service to decide whether to honor a request. + + By establishing "inter-realm" keys, the administrators of two realms + can allow a client authenticated in the local realm to prove its + identity to servers in other realms. The exchange of inter-realm + keys (a separate key may be used for each direction) registers the + ticket-granting service of each realm as a principal in the other + realm. A client is then able to obtain a TGT for the remote realm's + ticket-granting service from its local realm. When that TGT is used, + the remote ticket-granting service uses the inter-realm key (which + usually differs from its own normal TGS key) to decrypt the TGT; thus + it is certain that the ticket was issued by the client's own TGS. + Tickets issued by the remote ticket-granting service will indicate to + the end-service that the client was authenticated from another realm. + + Without cross-realm operation, and with appropriate permission, the + client can arrange registration of a separately-named principal in a + remote realm and engage in normal exchanges with that realm's + services. However, for even small numbers of clients this becomes + cumbersome, and more automatic methods as described here are + necessary. + + A realm is said to communicate with another realm if the two realms + share an inter-realm key, or if the local realm shares an inter-realm + key with an intermediate realm that communicates with the remote + realm. An authentication path is the sequence of intermediate realms + that are transited in communicating from one realm to another. + + Realms may be organized hierarchically. Each realm shares a key with + its parent and a different key with each child. If an inter-realm + key is not directly shared by two realms, the hierarchical + organization allows an authentication path to be easily constructed. + + + +Neuman, et al. Standards Track [Page 8] + +RFC 4120 Kerberos V5 July 2005 + + + If a hierarchical organization is not used, it may be necessary to + consult a database in order to construct an authentication path + between realms. + + Although realms are typically hierarchical, intermediate realms may + be bypassed to achieve cross-realm authentication through alternate + authentication paths. (These might be established to make + communication between two realms more efficient.) It is important + for the end-service to know which realms were transited when deciding + how much faith to place in the authentication process. To facilitate + this decision, a field in each ticket contains the names of the + realms that were involved in authenticating the client. + + The application server is ultimately responsible for accepting or + rejecting authentication and SHOULD check the transited field. The + application server may choose to rely on the Key Distribution Center + (KDC) for the application server's realm to check the transited + field. The application server's KDC will set the + TRANSITED-POLICY-CHECKED flag in this case. The KDCs for + intermediate realms may also check the transited field as they issue + TGTs for other realms, but they are encouraged not to do so. A + client may request that the KDCs not check the transited field by + setting the DISABLE-TRANSITED-CHECK flag. KDCs SHOULD honor this + flag. + +1.3. Choosing a Principal with Which to Communicate + + The Kerberos protocol provides the means for verifying (subject to + the assumptions in Section 1.6) that the entity with which one + communicates is the same entity that was registered with the KDC + using the claimed identity (principal name). It is still necessary + to determine whether that identity corresponds to the entity with + which one intends to communicate. + + When appropriate data has been exchanged in advance, the application + may perform this determination syntactically based on the application + protocol specification, information provided by the user, and + configuration files. For example, the server principal name + (including realm) for a telnet server might be derived from the + user-specified host name (from the telnet command line), the "host/" + prefix specified in the application protocol specification, and a + mapping to a Kerberos realm derived syntactically from the domain + part of the specified hostname and information from the local + Kerberos realms database. + + One can also rely on trusted third parties to make this + determination, but only when the data obtained from the third party + is suitably integrity-protected while resident on the third-party + + + +Neuman, et al. Standards Track [Page 9] + +RFC 4120 Kerberos V5 July 2005 + + + server and when transmitted. Thus, for example, one should not rely + on an unprotected DNS record to map a host alias to the primary name + of a server, accepting the primary name as the party that one intends + to contact, since an attacker can modify the mapping and impersonate + the party. + + Implementations of Kerberos and protocols based on Kerberos MUST NOT + use insecure DNS queries to canonicalize the hostname components of + the service principal names (i.e., they MUST NOT use insecure DNS + queries to map one name to another to determine the host part of the + principal name with which one is to communicate). In an environment + without secure name service, application authors MAY append a + statically configured domain name to unqualified hostnames before + passing the name to the security mechanisms, but they should do no + more than that. Secure name service facilities, if available, might + be trusted for hostname canonicalization, but such canonicalization + by the client SHOULD NOT be required by KDC implementations. + + Implementation note: Many current implementations do some degree of + canonicalization of the provided service name, often using DNS even + though it creates security problems. However, there is no + consistency among implementations as to whether the service name is + case folded to lowercase or whether reverse resolution is used. To + maximize interoperability and security, applications SHOULD provide + security mechanisms with names that result from folding the user- + entered name to lowercase without performing any other modifications + or canonicalization. + +1.4. Authorization + + As an authentication service, Kerberos provides a means of verifying + the identity of principals on a network. Authentication is usually + useful primarily as a first step in the process of authorization, + determining whether a client may use a service, which objects the + client is allowed to access, and the type of access allowed for each. + Kerberos does not, by itself, provide authorization. Possession of a + client ticket for a service provides only for authentication of the + client to that service, and in the absence of a separate + authorization procedure, an application should not consider it to + authorize the use of that service. + + Separate authorization methods MAY be implemented as application- + specific access control functions and may utilize files on the + application server, on separately issued authorization credentials + such as those based on proxies [Neu93], or on other authorization + services. Separately authenticated authorization credentials MAY be + embedded in a ticket's authorization data when encapsulated by the + KDC-issued authorization data element. + + + +Neuman, et al. Standards Track [Page 10] + +RFC 4120 Kerberos V5 July 2005 + + + Applications should not accept the mere issuance of a service ticket + by the Kerberos server (even by a modified Kerberos server) as + granting authority to use the service, since such applications may + become vulnerable to the bypass of this authorization check in an + environment where other options for application authentication are + provided, or if they interoperate with other KDCs. + +1.5. Extending Kerberos without Breaking Interoperability + + As the deployed base of Kerberos implementations grows, extending + Kerberos becomes more important. Unfortunately, some extensions to + the existing Kerberos protocol create interoperability issues because + of uncertainty regarding the treatment of certain extensibility + options by some implementations. This section includes guidelines + that will enable future implementations to maintain interoperability. + + Kerberos provides a general mechanism for protocol extensibility. + Some protocol messages contain typed holes -- sub-messages that + contain an octet-string along with an integer that defines how to + interpret the octet-string. The integer types are registered + centrally, but they can be used both for vendor extensions and for + extensions standardized through the IETF. + + In this document, the word "extension" refers to extension by + defining a new type to insert into an existing typed hole in a + protocol message. It does not refer to extension by addition of new + fields to ASN.1 types, unless the text explicitly indicates + otherwise. + +1.5.1. Compatibility with RFC 1510 + + Note that existing Kerberos message formats cannot readily be + extended by adding fields to the ASN.1 types. Sending additional + fields often results in the entire message being discarded without an + error indication. Future versions of this specification will provide + guidelines to ensure that ASN.1 fields can be added without creating + an interoperability problem. + + In the meantime, all new or modified implementations of Kerberos that + receive an unknown message extension SHOULD preserve the encoding of + the extension but otherwise ignore its presence. Recipients MUST NOT + decline a request simply because an extension is present. + + There is one exception to this rule. If an unknown authorization + data element type is received by a server other than the ticket- + granting service either in an AP-REQ or in a ticket contained in an + AP-REQ, then authentication MUST fail. One of the primary uses of + authorization data is to restrict the use of the ticket. If the + + + +Neuman, et al. Standards Track [Page 11] + +RFC 4120 Kerberos V5 July 2005 + + + service cannot determine whether the restriction applies to that + service, then a security weakness may result if the ticket can be + used for that service. Authorization elements that are optional + SHOULD be enclosed in the AD-IF-RELEVANT element. + + The ticket-granting service MUST ignore but propagate to derivative + tickets any unknown authorization data types, unless those data types + are embedded in a MANDATORY-FOR-KDC element, in which case the + request will be rejected. This behavior is appropriate because + requiring that the ticket-granting service understand unknown + authorization data types would require that KDC software be upgraded + to understand new application-level restrictions before applications + used these restrictions, decreasing the utility of authorization data + as a mechanism for restricting the use of tickets. No security + problem is created because services to which the tickets are issued + will verify the authorization data. + + Implementation note: Many RFC 1510 implementations ignore unknown + authorization data elements. Depending on these implementations to + honor authorization data restrictions may create a security weakness. + +1.5.2. Sending Extensible Messages + + Care must be taken to ensure that old implementations can understand + messages sent to them, even if they do not understand an extension + that is used. Unless the sender knows that an extension is + supported, the extension cannot change the semantics of the core + message or previously defined extensions. + + For example, an extension including key information necessary to + decrypt the encrypted part of a KDC-REP could only be used in + situations where the recipient was known to support the extension. + Thus when designing such extensions it is important to provide a way + for the recipient to notify the sender of support for the extension. + For example in the case of an extension that changes the KDC-REP + reply key, the client could indicate support for the extension by + including a padata element in the AS-REQ sequence. The KDC should + only use the extension if this padata element is present in the + AS-REQ. Even if policy requires the use of the extension, it is + better to return an error indicating that the extension is required + than to use the extension when the recipient may not support it. + Debugging implementations that do not interoperate is easier when + errors are returned. + +1.6. Environmental Assumptions + + Kerberos imposes a few assumptions on the environment in which it can + properly function, including the following: + + + +Neuman, et al. Standards Track [Page 12] + +RFC 4120 Kerberos V5 July 2005 + + + * "Denial of service" attacks are not solved with Kerberos. There + are places in the protocols where an intruder can prevent an + application from participating in the proper authentication steps. + Detection and solution of such attacks (some of which can appear + to be not-uncommon "normal" failure modes for the system) are + usually best left to the human administrators and users. + + * Principals MUST keep their secret keys secret. If an intruder + somehow steals a principal's key, it will be able to masquerade as + that principal or to impersonate any server to the legitimate + principal. + + * "Password guessing" attacks are not solved by Kerberos. If a user + chooses a poor password, it is possible for an attacker to + successfully mount an offline dictionary attack by repeatedly + attempting to decrypt, with successive entries from a dictionary, + messages obtained which are encrypted under a key derived from the + user's password. + + * Each host on the network MUST have a clock which is "loosely + synchronized" to the time of the other hosts; this synchronization + is used to reduce the bookkeeping needs of application servers + when they do replay detection. The degree of "looseness" can be + configured on a per-server basis, but it is typically on the order + of 5 minutes. If the clocks are synchronized over the network, + the clock synchronization protocol MUST itself be secured from + network attackers. + + * Principal identifiers are not recycled on a short-term basis. A + typical mode of access control will use access control lists + (ACLs) to grant permissions to particular principals. If a stale + ACL entry remains for a deleted principal and the principal + identifier is reused, the new principal will inherit rights + specified in the stale ACL entry. By not re-using principal + identifiers, the danger of inadvertent access is removed. + +1.7. Glossary of Terms + + Below is a list of terms used throughout this document. + + Authentication + Verifying the claimed identity of a principal. + + Authentication header + A record containing a Ticket and an Authenticator to be presented + to a server as part of the authentication process. + + + + + +Neuman, et al. Standards Track [Page 13] + +RFC 4120 Kerberos V5 July 2005 + + + Authentication path + A sequence of intermediate realms transited in the authentication + process when communicating from one realm to another. + + Authenticator + A record containing information that can be shown to have been + recently generated using the session key known only by the client + and server. + + Authorization + The process of determining whether a client may use a service, + which objects the client is allowed to access, and the type of + access allowed for each. + + Capability + A token that grants the bearer permission to access an object or + service. In Kerberos, this might be a ticket whose use is + restricted by the contents of the authorization data field, but + which lists no network addresses, together with the session key + necessary to use the ticket. + + Ciphertext + The output of an encryption function. Encryption transforms + plaintext into ciphertext. + + Client + A process that makes use of a network service on behalf of a user. + Note that in some cases a Server may itself be a client of some + other server (e.g., a print server may be a client of a file + server). + + Credentials + A ticket plus the secret session key necessary to use that ticket + successfully in an authentication exchange. + + Encryption Type (etype) + When associated with encrypted data, an encryption type identifies + the algorithm used to encrypt the data and is used to select the + appropriate algorithm for decrypting the data. Encryption type + tags are communicated in other messages to enumerate algorithms + that are desired, supported, preferred, or allowed to be used for + encryption of data between parties. This preference is combined + with local information and policy to select an algorithm to be + used. + + KDC + Key Distribution Center. A network service that supplies tickets + and temporary session keys; or an instance of that service or the + + + +Neuman, et al. Standards Track [Page 14] + +RFC 4120 Kerberos V5 July 2005 + + + host on which it runs. The KDC services both initial ticket and + ticket-granting ticket requests. The initial ticket portion is + sometimes referred to as the Authentication Server (or service). + The ticket-granting ticket portion is sometimes referred to as the + ticket-granting server (or service). + + Kerberos + The name given to the Project Athena's authentication service, the + protocol used by that service, or the code used to implement the + authentication service. The name is adopted from the three-headed + dog that guards Hades. + + Key Version Number (kvno) + A tag associated with encrypted data identifies which key was used + for encryption when a long-lived key associated with a principal + changes over time. It is used during the transition to a new key + so that the party decrypting a message can tell whether the data + was encrypted with the old or the new key. + + Plaintext + The input to an encryption function or the output of a decryption + function. Decryption transforms ciphertext into plaintext. + + Principal + A named client or server entity that participates in a network + communication, with one name that is considered canonical. + + Principal identifier + The canonical name used to identify each different principal + uniquely. + + Seal + To encipher a record containing several fields in such a way that + the fields cannot be individually replaced without knowledge of + the encryption key or leaving evidence of tampering. + + Secret key + An encryption key shared by a principal and the KDC, distributed + outside the bounds of the system, with a long lifetime. In the + case of a human user's principal, the secret key MAY be derived + from a password. + + Server + A particular Principal that provides a resource to network + clients. The server is sometimes referred to as the Application + Server. + + + + + +Neuman, et al. Standards Track [Page 15] + +RFC 4120 Kerberos V5 July 2005 + + + Service + A resource provided to network clients; often provided by more + than one server (for example, remote file service). + + Session key + A temporary encryption key used between two principals, with a + lifetime limited to the duration of a single login "session". In + the Kerberos system, a session key is generated by the KDC. The + session key is distinct from the sub-session key, described next. + + Sub-session key + A temporary encryption key used between two principals, selected + and exchanged by the principals using the session key, and with a + lifetime limited to the duration of a single association. The + sub-session key is also referred to as the subkey. + + Ticket + A record that helps a client authenticate itself to a server; it + contains the client's identity, a session key, a timestamp, and + other information, all sealed using the server's secret key. It + only serves to authenticate a client when presented along with a + fresh Authenticator. + +2. Ticket Flag Uses and Requests + + Each Kerberos ticket contains a set of flags that are used to + indicate attributes of that ticket. Most flags may be requested by a + client when the ticket is obtained; some are automatically turned on + and off by a Kerberos server as required. The following sections + explain what the various flags mean and give examples of reasons to + use them. With the exception of the INVALID flag, clients MUST + ignore ticket flags that are not recognized. KDCs MUST ignore KDC + options that are not recognized. Some implementations of RFC 1510 + are known to reject unknown KDC options, so clients may need to + resend a request without new KDC options if the request was rejected + when sent with options added since RFC 1510. Because new KDCs will + ignore unknown options, clients MUST confirm that the ticket returned + by the KDC meets their needs. + + Note that it is not, in general, possible to determine whether an + option was not honored because it was not understood or because it + was rejected through either configuration or policy. When adding a + new option to the Kerberos protocol, designers should consider + whether the distinction is important for their option. If it is, a + mechanism for the KDC to return an indication that the option was + understood but rejected needs to be provided in the specification of + the option. Often in such cases, the mechanism needs to be broad + enough to permit an error or reason to be returned. + + + +Neuman, et al. Standards Track [Page 16] + +RFC 4120 Kerberos V5 July 2005 + + +2.1. Initial, Pre-authenticated, and Hardware-Authenticated Tickets + + The INITIAL flag indicates that a ticket was issued using the AS + protocol, rather than issued based on a TGT. Application servers + that want to require the demonstrated knowledge of a client's secret + key (e.g., a password-changing program) can insist that this flag be + set in any tickets they accept, and can thus be assured that the + client's key was recently presented to the authentication server. + + The PRE-AUTHENT and HW-AUTHENT flags provide additional information + about the initial authentication, regardless of whether the current + ticket was issued directly (in which case INITIAL will also be set) + or issued on the basis of a TGT (in which case the INITIAL flag is + clear, but the PRE-AUTHENT and HW-AUTHENT flags are carried forward + from the TGT). + +2.2. Invalid Tickets + + The INVALID flag indicates that a ticket is invalid. Application + servers MUST reject tickets that have this flag set. A postdated + ticket will be issued in this form. Invalid tickets MUST be + validated by the KDC before use, by being presented to the KDC in a + TGS request with the VALIDATE option specified. The KDC will only + validate tickets after their starttime has passed. The validation is + required so that postdated tickets that have been stolen before their + starttime can be rendered permanently invalid (through a hot-list + mechanism) (see Section 3.3.3.1). + +2.3. Renewable Tickets + + Applications may desire to hold tickets that can be valid for long + periods of time. However, this can expose their credentials to + potential theft for equally long periods, and those stolen + credentials would be valid until the expiration time of the + ticket(s). Simply using short-lived tickets and obtaining new ones + periodically would require the client to have long-term access to its + secret key, an even greater risk. Renewable tickets can be used to + mitigate the consequences of theft. Renewable tickets have two + "expiration times": the first is when the current instance of the + ticket expires, and the second is the latest permissible value for an + individual expiration time. An application client must periodically + (i.e., before it expires) present a renewable ticket to the KDC, with + the RENEW option set in the KDC request. The KDC will issue a new + ticket with a new session key and a later expiration time. All other + fields of the ticket are left unmodified by the renewal process. + When the latest permissible expiration time arrives, the ticket + expires permanently. At each renewal, the KDC MAY consult a hot-list + to determine whether the ticket had been reported stolen since its + + + +Neuman, et al. Standards Track [Page 17] + +RFC 4120 Kerberos V5 July 2005 + + + last renewal; it will refuse to renew stolen tickets, and thus the + usable lifetime of stolen tickets is reduced. + + The RENEWABLE flag in a ticket is normally only interpreted by the + ticket-granting service (discussed below in Section 3.3). It can + usually be ignored by application servers. However, some + particularly careful application servers MAY disallow renewable + tickets. + + If a renewable ticket is not renewed by its expiration time, the KDC + will not renew the ticket. The RENEWABLE flag is reset by default, + but a client MAY request it be set by setting the RENEWABLE option in + the KRB_AS_REQ message. If it is set, then the renew-till field in + the ticket contains the time after which the ticket may not be + renewed. + +2.4. Postdated Tickets + + Applications may occasionally need to obtain tickets for use much + later; e.g., a batch submission system would need tickets to be valid + at the time the batch job is serviced. However, it is dangerous to + hold valid tickets in a batch queue, since they will be on-line + longer and more prone to theft. Postdated tickets provide a way to + obtain these tickets from the KDC at job submission time, but to + leave them "dormant" until they are activated and validated by a + further request of the KDC. If a ticket theft were reported in the + interim, the KDC would refuse to validate the ticket, and the thief + would be foiled. + + The MAY-POSTDATE flag in a ticket is normally only interpreted by the + ticket-granting service. It can be ignored by application servers. + This flag MUST be set in a TGT in order to issue a postdated ticket + based on the presented ticket. It is reset by default; a client MAY + request it by setting the ALLOW-POSTDATE option in the KRB_AS_REQ + message. This flag does not allow a client to obtain a postdated + TGT; postdated TGTs can only be obtained by requesting the postdating + in the KRB_AS_REQ message. The life (endtime-starttime) of a + postdated ticket will be the remaining life of the TGT at the time of + the request, unless the RENEWABLE option is also set, in which case + it can be the full life (endtime-starttime) of the TGT. The KDC MAY + limit how far in the future a ticket may be postdated. + + The POSTDATED flag indicates that a ticket has been postdated. The + application server can check the authtime field in the ticket to see + when the original authentication occurred. Some services MAY choose + to reject postdated tickets, or they may only accept them within a + certain period after the original authentication. When the KDC + issues a POSTDATED ticket, it will also be marked as INVALID, so that + + + +Neuman, et al. Standards Track [Page 18] + +RFC 4120 Kerberos V5 July 2005 + + + the application client MUST present the ticket to the KDC to be + validated before use. + +2.5. Proxiable and Proxy Tickets + + At times it may be necessary for a principal to allow a service to + perform an operation on its behalf. The service must be able to take + on the identity of the client, but only for a particular purpose. A + principal can allow a service to do this by granting it a proxy. + + The process of granting a proxy by using the proxy and proxiable + flags is used to provide credentials for use with specific services. + Though conceptually also a proxy, users wishing to delegate their + identity in a form usable for all purposes MUST use the ticket + forwarding mechanism described in the next section to forward a TGT. + + The PROXIABLE flag in a ticket is normally only interpreted by the + ticket-granting service. It can be ignored by application servers. + When set, this flag tells the ticket-granting server that it is OK to + issue a new ticket (but not a TGT) with a different network address + based on this ticket. This flag is set if requested by the client on + initial authentication. By default, the client will request that it + be set when requesting a TGT, and that it be reset when requesting + any other ticket. + + This flag allows a client to pass a proxy to a server to perform a + remote request on its behalf (e.g., a print service client can give + the print server a proxy to access the client's files on a particular + file server in order to satisfy a print request). + + In order to complicate the use of stolen credentials, Kerberos + tickets are often valid only from those network addresses + specifically included in the ticket, but it is permissible as a + policy option to allow requests and to issue tickets with no network + addresses specified. When granting a proxy, the client MUST specify + the new network address from which the proxy is to be used or + indicate that the proxy is to be issued for use from any address. + + The PROXY flag is set in a ticket by the TGS when it issues a proxy + ticket. Application servers MAY check this flag; and at their option + they MAY require additional authentication from the agent presenting + the proxy in order to provide an audit trail. + +2.6. Forwardable Tickets + + Authentication forwarding is an instance of a proxy where the service + that is granted is complete use of the client's identity. An example + of where it might be used is when a user logs in to a remote system + + + +Neuman, et al. Standards Track [Page 19] + +RFC 4120 Kerberos V5 July 2005 + + + and wants authentication to work from that system as if the login + were local. + + The FORWARDABLE flag in a ticket is normally only interpreted by the + ticket-granting service. It can be ignored by application servers. + The FORWARDABLE flag has an interpretation similar to that of the + PROXIABLE flag, except TGTs may also be issued with different network + addresses. This flag is reset by default, but users MAY request that + it be set by setting the FORWARDABLE option in the AS request when + they request their initial TGT. + + This flag allows for authentication forwarding without requiring the + user to enter a password again. If the flag is not set, then + authentication forwarding is not permitted, but the same result can + still be achieved if the user engages in the AS exchange, specifies + the requested network addresses, and supplies a password. + + The FORWARDED flag is set by the TGS when a client presents a ticket + with the FORWARDABLE flag set and requests a forwarded ticket by + specifying the FORWARDED KDC option and supplying a set of addresses + for the new ticket. It is also set in all tickets issued based on + tickets with the FORWARDED flag set. Application servers may choose + to process FORWARDED tickets differently than non-FORWARDED tickets. + + If addressless tickets are forwarded from one system to another, + clients SHOULD still use this option to obtain a new TGT in order to + have different session keys on the different systems. + +2.7. Transited Policy Checking + + In Kerberos, the application server is ultimately responsible for + accepting or rejecting authentication, and it SHOULD check that only + suitably trusted KDCs are relied upon to authenticate a principal. + The transited field in the ticket identifies which realms (and thus + which KDCs) were involved in the authentication process, and an + application server would normally check this field. If any of these + are untrusted to authenticate the indicated client principal + (probably determined by a realm-based policy), the authentication + attempt MUST be rejected. The presence of trusted KDCs in this list + does not provide any guarantee; an untrusted KDC may have fabricated + the list. + + Although the end server ultimately decides whether authentication is + valid, the KDC for the end server's realm MAY apply a realm-specific + policy for validating the transited field and accepting credentials + for cross-realm authentication. When the KDC applies such checks and + accepts such cross-realm authentication, it will set the + TRANSITED-POLICY-CHECKED flag in the service tickets it issues based + + + +Neuman, et al. Standards Track [Page 20] + +RFC 4120 Kerberos V5 July 2005 + + + on the cross-realm TGT. A client MAY request that the KDCs not check + the transited field by setting the DISABLE-TRANSITED-CHECK flag. + KDCs are encouraged but not required to honor this flag. + + Application servers MUST either do the transited-realm checks + themselves or reject cross-realm tickets without + TRANSITED-POLICY-CHECKED set. + +2.8. OK as Delegate + + For some applications, a client may need to delegate authority to a + server to act on its behalf in contacting other services. This + requires that the client forward credentials to an intermediate + server. The ability for a client to obtain a service ticket to a + server conveys no information to the client about whether the server + should be trusted to accept delegated credentials. The + OK-AS-DELEGATE provides a way for a KDC to communicate local realm + policy to a client regarding whether an intermediate server is + trusted to accept such credentials. + + The copy of the ticket flags in the encrypted part of the KDC reply + may have the OK-AS-DELEGATE flag set to indicate to the client that + the server specified in the ticket has been determined by the policy + of the realm to be a suitable recipient of delegation. A client can + use the presence of this flag to help it decide whether to delegate + credentials (grant either a proxy or a forwarded TGT) to this server. + It is acceptable to ignore the value of this flag. When setting this + flag, an administrator should consider the security and placement of + the server on which the service will run, as well as whether the + service requires the use of delegated credentials. + +2.9. Other KDC Options + + There are three additional options that MAY be set in a client's + request of the KDC. + +2.9.1. Renewable-OK + + The RENEWABLE-OK option indicates that the client will accept a + renewable ticket if a ticket with the requested life cannot otherwise + be provided. If a ticket with the requested life cannot be provided, + then the KDC MAY issue a renewable ticket with a renew-till equal to + the requested endtime. The value of the renew-till field MAY still + be adjusted by site-determined limits or limits imposed by the + individual principal or server. + + + + + + +Neuman, et al. Standards Track [Page 21] + +RFC 4120 Kerberos V5 July 2005 + + +2.9.2. ENC-TKT-IN-SKEY + + In its basic form, the Kerberos protocol supports authentication in a + client-server setting and is not well suited to authentication in a + peer-to-peer environment because the long-term key of the user does + not remain on the workstation after initial login. Authentication of + such peers may be supported by Kerberos in its user-to-user variant. + The ENC-TKT-IN-SKEY option supports user-to-user authentication by + allowing the KDC to issue a service ticket encrypted using the + session key from another TGT issued to another user. The + ENC-TKT-IN-SKEY option is honored only by the ticket-granting + service. It indicates that the ticket to be issued for the end + server is to be encrypted in the session key from the additional + second TGT provided with the request. See Section 3.3.3 for specific + details. + +2.9.3. Passwordless Hardware Authentication + + The OPT-HARDWARE-AUTH option indicates that the client wishes to use + some form of hardware authentication instead of or in addition to the + client's password or other long-lived encryption key. + OPT-HARDWARE-AUTH is honored only by the authentication service. If + supported and allowed by policy, the KDC will return an error code of + KDC_ERR_PREAUTH_REQUIRED and include the required METHOD-DATA to + perform such authentication. + +3. Message Exchanges + + The following sections describe the interactions between network + clients and servers and the messages involved in those exchanges. + +3.1. The Authentication Service Exchange + + Summary + + Message direction Message type Section + 1. Client to Kerberos KRB_AS_REQ 5.4.1 + 2. Kerberos to client KRB_AS_REP or 5.4.2 + KRB_ERROR 5.9.1 + + The Authentication Service (AS) Exchange between the client and the + Kerberos Authentication Server is initiated by a client when it + wishes to obtain authentication credentials for a given server but + currently holds no credentials. In its basic form, the client's + secret key is used for encryption and decryption. This exchange is + typically used at the initiation of a login session to obtain + credentials for a Ticket-Granting Server, which will subsequently be + used to obtain credentials for other servers (see Section 3.3) + + + +Neuman, et al. Standards Track [Page 22] + +RFC 4120 Kerberos V5 July 2005 + + + without requiring further use of the client's secret key. This + exchange is also used to request credentials for services that must + not be mediated through the Ticket-Granting Service, but rather + require knowledge of a principal's secret key, such as the password- + changing service (the password-changing service denies requests + unless the requester can demonstrate knowledge of the user's old + password; requiring this knowledge prevents unauthorized password + changes by someone walking up to an unattended session). + + This exchange does not by itself provide any assurance of the + identity of the user. To authenticate a user logging on to a local + system, the credentials obtained in the AS exchange may first be used + in a TGS exchange to obtain credentials for a local server; those + credentials must then be verified by a local server through + successful completion of the Client/Server exchange. + + The AS exchange consists of two messages: KRB_AS_REQ from the client + to Kerberos, and KRB_AS_REP or KRB_ERROR in reply. The formats for + these messages are described in Sections 5.4.1, 5.4.2, and 5.9.1. + + In the request, the client sends (in cleartext) its own identity and + the identity of the server for which it is requesting credentials, + other information about the credentials it is requesting, and a + randomly generated nonce, which can be used to detect replays and to + associate replies with the matching requests. This nonce MUST be + generated randomly by the client and remembered for checking against + the nonce in the expected reply. The response, KRB_AS_REP, contains + a ticket for the client to present to the server, and a session key + that will be shared by the client and the server. The session key + and additional information are encrypted in the client's secret key. + The encrypted part of the KRB_AS_REP message also contains the nonce + that MUST be matched with the nonce from the KRB_AS_REQ message. + + Without pre-authentication, the authentication server does not know + whether the client is actually the principal named in the request. + It simply sends a reply without knowing or caring whether they are + the same. This is acceptable because nobody but the principal whose + identity was given in the request will be able to use the reply. Its + critical information is encrypted in that principal's key. However, + an attacker can send a KRB_AS_REQ message to get known plaintext in + order to attack the principal's key. Especially if the key is based + on a password, this may create a security exposure. So the initial + request supports an optional field that can be used to pass + additional information that might be needed for the initial exchange. + This field SHOULD be used for pre-authentication as described in + sections 3.1.1 and 5.2.7. + + + + + +Neuman, et al. Standards Track [Page 23] + +RFC 4120 Kerberos V5 July 2005 + + + Various errors can occur; these are indicated by an error response + (KRB_ERROR) instead of the KRB_AS_REP response. The error message is + not encrypted. The KRB_ERROR message contains information that can + be used to associate it with the message to which it replies. The + contents of the KRB_ERROR message are not integrity-protected. As + such, the client cannot detect replays, fabrications, or + modifications. A solution to this problem will be included in a + future version of the protocol. + +3.1.1. Generation of KRB_AS_REQ Message + + The client may specify a number of options in the initial request. + Among these options are whether pre-authentication is to be + performed; whether the requested ticket is to be renewable, + proxiable, or forwardable; whether it should be postdated or allow + postdating of derivative tickets; and whether a renewable ticket will + be accepted in lieu of a non-renewable ticket if the requested ticket + expiration date cannot be satisfied by a non-renewable ticket (due to + configuration constraints). + + The client prepares the KRB_AS_REQ message and sends it to the KDC. + +3.1.2. Receipt of KRB_AS_REQ Message + + If all goes well, processing the KRB_AS_REQ message will result in + the creation of a ticket for the client to present to the server. + The format for the ticket is described in Section 5.3. + + Because Kerberos can run over unreliable transports such as UDP, the + KDC MUST be prepared to retransmit responses in case they are lost. + If a KDC receives a request identical to one it has recently + processed successfully, the KDC MUST respond with a KRB_AS_REP + message rather than a replay error. In order to reduce ciphertext + given to a potential attacker, KDCs MAY send the same response + generated when the request was first handled. KDCs MUST obey this + replay behavior even if the actual transport in use is reliable. + +3.1.3. Generation of KRB_AS_REP Message + + The authentication server looks up the client and server principals + named in the KRB_AS_REQ in its database, extracting their respective + keys. If the requested client principal named in the request is + unknown because it doesn't exist in the KDC's principal database, + then an error message with a KDC_ERR_C_PRINCIPAL_UNKNOWN is returned. + + If required to do so, the server pre-authenticates the request, and + if the pre-authentication check fails, an error message with the code + KDC_ERR_PREAUTH_FAILED is returned. If pre-authentication is + + + +Neuman, et al. Standards Track [Page 24] + +RFC 4120 Kerberos V5 July 2005 + + + required, but was not present in the request, an error message with + the code KDC_ERR_PREAUTH_REQUIRED is returned, and a METHOD-DATA + object will be stored in the e-data field of the KRB-ERROR message to + specify which pre-authentication mechanisms are acceptable. Usually + this will include PA-ETYPE-INFO and/or PA-ETYPE-INFO2 elements as + described below. If the server cannot accommodate any encryption + type requested by the client, an error message with code + KDC_ERR_ETYPE_NOSUPP is returned. Otherwise, the KDC generates a + 'random' session key, meaning that, among other things, it should be + impossible to guess the next session key based on knowledge of past + session keys. Although this can be achieved in a pseudo-random + number generator if it is based on cryptographic principles, it is + more desirable to use a truly random number generator, such as one + based on measurements of random physical phenomena. See [RFC4086] + for an in-depth discussion of randomness. + + In response to an AS request, if there are multiple encryption keys + registered for a client in the Kerberos database, then the etype + field from the AS request is used by the KDC to select the encryption + method to be used to protect the encrypted part of the KRB_AS_REP + message that is sent to the client. If there is more than one + supported strong encryption type in the etype list, the KDC SHOULD + use the first valid strong etype for which an encryption key is + available. + + When the user's key is generated from a password or pass phrase, the + string-to-key function for the particular encryption key type is + used, as specified in [RFC3961]. The salt value and additional + parameters for the string-to-key function have default values + (specified by Section 4 and by the encryption mechanism + specification, respectively) that may be overridden by + pre-authentication data (PA-PW-SALT, PA-AFS3-SALT, PA-ETYPE-INFO, + PA-ETYPE-INFO2, etc). Since the KDC is presumed to store a copy of + the resulting key only, these values should not be changed for + password-based keys except when changing the principal's key. + + When the AS server is to include pre-authentication data in a + KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not PA-ETYPE- + INFO, if the etype field of the client's AS-REQ lists at least one + "newer" encryption type. Otherwise (when the etype field of the + client's AS-REQ does not list any "newer" encryption types), it MUST + send both PA-ETYPE-INFO2 and PA-ETYPE-INFO (both with an entry for + each enctype). A "newer" enctype is any enctype first officially + specified concurrently with or subsequent to the issue of this RFC. + The enctypes DES, 3DES, or RC4 and any defined in [RFC1510] are not + "newer" enctypes. + + + + + +Neuman, et al. Standards Track [Page 25] + +RFC 4120 Kerberos V5 July 2005 + + + It is not possible to generate a user's key reliably given a pass + phrase without contacting the KDC, since it will not be known whether + alternate salt or parameter values are required. + + The KDC will attempt to assign the type of the random session key + from the list of methods in the etype field. The KDC will select the + appropriate type using the list of methods provided and information + from the Kerberos database indicating acceptable encryption methods + for the application server. The KDC will not issue tickets with a + weak session key encryption type. + + If the requested starttime is absent, indicates a time in the past, + or is within the window of acceptable clock skew for the KDC and the + POSTDATE option has not been specified, then the starttime of the + ticket is set to the authentication server's current time. If it + indicates a time in the future beyond the acceptable clock skew, but + the POSTDATED option has not been specified, then the error + KDC_ERR_CANNOT_POSTDATE is returned. Otherwise the requested + starttime is checked against the policy of the local realm (the + administrator might decide to prohibit certain types or ranges of + postdated tickets), and if the ticket's starttime is acceptable, it + is set as requested, and the INVALID flag is set in the new ticket. + The postdated ticket MUST be validated before use by presenting it to + the KDC after the starttime has been reached. + + The expiration time of the ticket will be set to the earlier of the + requested endtime and a time determined by local policy, possibly by + using realm- or principal-specific factors. For example, the + expiration time MAY be set to the earliest of the following: + + * The expiration time (endtime) requested in the KRB_AS_REQ + message. + + * The ticket's starttime plus the maximum allowable lifetime + associated with the client principal from the authentication + server's database. + + * The ticket's starttime plus the maximum allowable lifetime + associated with the server principal. + + * The ticket's starttime plus the maximum lifetime set by the + policy of the local realm. + + If the requested expiration time minus the starttime (as determined + above) is less than a site-determined minimum lifetime, an error + message with code KDC_ERR_NEVER_VALID is returned. If the requested + expiration time for the ticket exceeds what was determined as above, + and if the 'RENEWABLE-OK' option was requested, then the 'RENEWABLE' + + + +Neuman, et al. Standards Track [Page 26] + +RFC 4120 Kerberos V5 July 2005 + + + flag is set in the new ticket, and the renew-till value is set as if + the 'RENEWABLE' option were requested (the field and option names are + described fully in Section 5.4.1). + + If the RENEWABLE option has been requested or if the RENEWABLE-OK + option has been set and a renewable ticket is to be issued, then the + renew-till field MAY be set to the earliest of: + + * Its requested value. + + * The starttime of the ticket plus the minimum of the two maximum + renewable lifetimes associated with the principals' database + entries. + + * The starttime of the ticket plus the maximum renewable lifetime + set by the policy of the local realm. + + The flags field of the new ticket will have the following options set + if they have been requested and if the policy of the local realm + allows: FORWARDABLE, MAY-POSTDATE, POSTDATED, PROXIABLE, RENEWABLE. + If the new ticket is postdated (the starttime is in the future), its + INVALID flag will also be set. + + If all of the above succeed, the server will encrypt the ciphertext + part of the ticket using the encryption key extracted from the server + principal's record in the Kerberos database using the encryption type + associated with the server principal's key. (This choice is NOT + affected by the etype field in the request.) It then formats a + KRB_AS_REP message (see Section 5.4.2), copying the addresses in the + request into the caddr of the response, placing any required pre- + authentication data into the padata of the response, and encrypts the + ciphertext part in the client's key using an acceptable encryption + method requested in the etype field of the request, or in some key + specified by pre-authentication mechanisms being used. + +3.1.4. Generation of KRB_ERROR Message + + Several errors can occur, and the Authentication Server responds by + returning an error message, KRB_ERROR, to the client, with the + error-code and e-text fields set to appropriate values. The error + message contents and details are described in Section 5.9.1. + +3.1.5. Receipt of KRB_AS_REP Message + + If the reply message type is KRB_AS_REP, then the client verifies + that the cname and crealm fields in the cleartext portion of the + reply match what it requested. If any padata fields are present, + they may be used to derive the proper secret key to decrypt the + + + +Neuman, et al. Standards Track [Page 27] + +RFC 4120 Kerberos V5 July 2005 + + + message. The client decrypts the encrypted part of the response + using its secret key and verifies that the nonce in the encrypted + part matches the nonce it supplied in its request (to detect + replays). It also verifies that the sname and srealm in the response + match those in the request (or are otherwise expected values), and + that the host address field is also correct. It then stores the + ticket, session key, start and expiration times, and other + information for later use. The last-req field (and the deprecated + key-expiration field) from the encrypted part of the response MAY be + checked to notify the user of impending key expiration. This enables + the client program to suggest remedial action, such as a password + change. + + Upon validation of the KRB_AS_REP message (by checking the returned + nonce against that sent in the KRB_AS_REQ message), the client knows + that the current time on the KDC is that read from the authtime field + of the encrypted part of the reply. The client can optionally use + this value for clock synchronization in subsequent messages by + recording with the ticket the difference (offset) between the + authtime value and the local clock. This offset can then be used by + the same user to adjust the time read from the system clock when + generating messages [DGT96]. + + This technique MUST be used when adjusting for clock skew instead of + directly changing the system clock, because the KDC reply is only + authenticated to the user whose secret key was used, but not to the + system or workstation. If the clock were adjusted, an attacker + colluding with a user logging into a workstation could agree on a + password, resulting in a KDC reply that would be correctly validated + even though it did not originate from a KDC trusted by the + workstation. + + Proper decryption of the KRB_AS_REP message is not sufficient for the + host to verify the identity of the user; the user and an attacker + could cooperate to generate a KRB_AS_REP format message that decrypts + properly but is not from the proper KDC. If the host wishes to + verify the identity of the user, it MUST require the user to present + application credentials that can be verified using a securely-stored + secret key for the host. If those credentials can be verified, then + the identity of the user can be assured. + +3.1.6. Receipt of KRB_ERROR Message + + If the reply message type is KRB_ERROR, then the client interprets it + as an error and performs whatever application-specific tasks are + necessary for recovery. + + + + + +Neuman, et al. Standards Track [Page 28] + +RFC 4120 Kerberos V5 July 2005 + + +3.2. The Client/Server Authentication Exchange + + Summary + + Message direction Message type Section + Client to Application server KRB_AP_REQ 5.5.1 + [optional] Application server to client KRB_AP_REP or 5.5.2 + KRB_ERROR 5.9.1 + + The client/server authentication (CS) exchange is used by network + applications to authenticate the client to the server and vice versa. + The client MUST have already acquired credentials for the server + using the AS or TGS exchange. + +3.2.1. The KRB_AP_REQ Message + + The KRB_AP_REQ contains authentication information that SHOULD be + part of the first message in an authenticated transaction. It + contains a ticket, an authenticator, and some additional bookkeeping + information (see Section 5.5.1 for the exact format). The ticket by + itself is insufficient to authenticate a client, since tickets are + passed across the network in cleartext (tickets contain both an + encrypted and unencrypted portion, so cleartext here refers to the + entire unit, which can be copied from one message and replayed in + another without any cryptographic skill). The authenticator is used + to prevent invalid replay of tickets by proving to the server that + the client knows the session key of the ticket and thus is entitled + to use the ticket. The KRB_AP_REQ message is referred to elsewhere + as the 'authentication header'. + +3.2.2. Generation of a KRB_AP_REQ Message + + When a client wishes to initiate authentication to a server, it + obtains (either through a credentials cache, the AS exchange, or the + TGS exchange) a ticket and session key for the desired service. The + client MAY re-use any tickets it holds until they expire. To use a + ticket, the client constructs a new Authenticator from the system + time and its name, and optionally from an application-specific + checksum, an initial sequence number to be used in KRB_SAFE or + KRB_PRIV messages, and/or a session subkey to be used in negotiations + for a session key unique to this particular session. Authenticators + MUST NOT be re-used and SHOULD be rejected if replayed to a server. + Note that this can make applications based on unreliable transports + difficult to code correctly. If the transport might deliver + duplicated messages, either a new authenticator MUST be generated for + each retry, or the application server MUST match requests and replies + and replay the first reply in response to a detected duplicate. + + + + +Neuman, et al. Standards Track [Page 29] + +RFC 4120 Kerberos V5 July 2005 + + + If a sequence number is to be included, it SHOULD be randomly chosen + so that even after many messages have been exchanged it is not likely + to collide with other sequence numbers in use. + + The client MAY indicate a requirement of mutual authentication or the + use of a session-key based ticket (for user-to-user authentication, + see section 3.7) by setting the appropriate flag(s) in the ap-options + field of the message. + + The Authenticator is encrypted in the session key and combined with + the ticket to form the KRB_AP_REQ message, which is then sent to the + end server along with any additional application-specific + information. + +3.2.3. Receipt of KRB_AP_REQ Message + + Authentication is based on the server's current time of day (clocks + MUST be loosely synchronized), the authenticator, and the ticket. + Several errors are possible. If an error occurs, the server is + expected to reply to the client with a KRB_ERROR message. This + message MAY be encapsulated in the application protocol if its raw + form is not acceptable to the protocol. The format of error messages + is described in Section 5.9.1. + + The algorithm for verifying authentication information is as follows. + If the message type is not KRB_AP_REQ, the server returns the + KRB_AP_ERR_MSG_TYPE error. If the key version indicated by the + Ticket in the KRB_AP_REQ is not one the server can use (e.g., it + indicates an old key, and the server no longer possesses a copy of + the old key), the KRB_AP_ERR_BADKEYVER error is returned. If the + USE-SESSION-KEY flag is set in the ap-options field, it indicates to + the server that user-to-user authentication is in use, and that the + ticket is encrypted in the session key from the server's TGT rather + than in the server's secret key. See Section 3.7 for a more complete + description of the effect of user-to-user authentication on all + messages in the Kerberos protocol. + + Because it is possible for the server to be registered in multiple + realms, with different keys in each, the srealm field in the + unencrypted portion of the ticket in the KRB_AP_REQ is used to + specify which secret key the server should use to decrypt that + ticket. The KRB_AP_ERR_NOKEY error code is returned if the server + doesn't have the proper key to decipher the ticket. + + The ticket is decrypted using the version of the server's key + specified by the ticket. If the decryption routines detect a + modification of the ticket (each encryption system MUST provide + safeguards to detect modified ciphertext), the + + + +Neuman, et al. Standards Track [Page 30] + +RFC 4120 Kerberos V5 July 2005 + + + KRB_AP_ERR_BAD_INTEGRITY error is returned (chances are good that + different keys were used to encrypt and decrypt). + + The authenticator is decrypted using the session key extracted from + the decrypted ticket. If decryption shows that is has been modified, + the KRB_AP_ERR_BAD_INTEGRITY error is returned. The name and realm + of the client from the ticket are compared against the same fields in + the authenticator. If they don't match, the KRB_AP_ERR_BADMATCH + error is returned; normally this is caused by a client error or an + attempted attack. The addresses in the ticket (if any) are then + searched for an address matching the operating-system reported + address of the client. If no match is found or the server insists on + ticket addresses but none are present in the ticket, the + KRB_AP_ERR_BADADDR error is returned. If the local (server) time and + the client time in the authenticator differ by more than the + allowable clock skew (e.g., 5 minutes), the KRB_AP_ERR_SKEW error is + returned. + + Unless the application server provides its own suitable means to + protect against replay (for example, a challenge-response sequence + initiated by the server after authentication, or use of a server- + generated encryption subkey), the server MUST utilize a replay cache + to remember any authenticator presented within the allowable clock + skew. Careful analysis of the application protocol and + implementation is recommended before eliminating this cache. The + replay cache will store at least the server name, along with the + client name, time, and microsecond fields from the recently-seen + authenticators, and if a matching tuple is found, the + KRB_AP_ERR_REPEAT error is returned. Note that the rejection here is + restricted to authenticators from the same principal to the same + server. Other client principals communicating with the same server + principal should not have their authenticators rejected if the time + and microsecond fields happen to match some other client's + authenticator. + + If a server loses track of authenticators presented within the + allowable clock skew, it MUST reject all requests until the clock + skew interval has passed, providing assurance that any lost or + replayed authenticators will fall outside the allowable clock skew + and can no longer be successfully replayed. If this were not done, + an attacker could subvert the authentication by recording the ticket + and authenticator sent over the network to a server and replaying + them following an event that caused the server to lose track of + recently seen authenticators. + + Implementation note: If a client generates multiple requests to the + KDC with the same timestamp, including the microsecond field, all but + the first of the requests received will be rejected as replays. This + + + +Neuman, et al. Standards Track [Page 31] + +RFC 4120 Kerberos V5 July 2005 + + + might happen, for example, if the resolution of the client's clock is + too coarse. Client implementations SHOULD ensure that the timestamps + are not reused, possibly by incrementing the microseconds field in + the time stamp when the clock returns the same time for multiple + requests. + + If multiple servers (for example, different services on one machine, + or a single service implemented on multiple machines) share a service + principal (a practice that we do not recommend in general, but that + we acknowledge will be used in some cases), either they MUST share + this replay cache, or the application protocol MUST be designed so as + to eliminate the need for it. Note that this applies to all of the + services. If any of the application protocols does not have replay + protection built in, an authenticator used with such a service could + later be replayed to a different service with the same service + principal but no replay protection, if the former doesn't record the + authenticator information in the common replay cache. + + If a sequence number is provided in the authenticator, the server + saves it for later use in processing KRB_SAFE and/or KRB_PRIV + messages. If a subkey is present, the server either saves it for + later use or uses it to help generate its own choice for a subkey to + be returned in a KRB_AP_REP message. + + The server computes the age of the ticket: local (server) time minus + the starttime inside the Ticket. If the starttime is later than the + current time by more than the allowable clock skew, or if the INVALID + flag is set in the ticket, the KRB_AP_ERR_TKT_NYV error is returned. + Otherwise, if the current time is later than end time by more than + the allowable clock skew, the KRB_AP_ERR_TKT_EXPIRED error is + returned. + + If all these checks succeed without an error, the server is assured + that the client possesses the credentials of the principal named in + the ticket, and thus, that the client has been authenticated to the + server. + + Passing these checks provides only authentication of the named + principal; it does not imply authorization to use the named service. + Applications MUST make a separate authorization decision based upon + the authenticated name of the user, the requested operation, local + access control information such as that contained in a .k5login or + .k5users file, and possibly a separate distributed authorization + service. + + + + + + + +Neuman, et al. Standards Track [Page 32] + +RFC 4120 Kerberos V5 July 2005 + + +3.2.4. Generation of a KRB_AP_REP Message + + Typically, a client's request will include both the authentication + information and its initial request in the same message, and the + server need not explicitly reply to the KRB_AP_REQ. However, if + mutual authentication (authenticating not only the client to the + server, but also the server to the client) is being performed, the + KRB_AP_REQ message will have MUTUAL-REQUIRED set in its ap-options + field, and a KRB_AP_REP message is required in response. As with the + error message, this message MAY be encapsulated in the application + protocol if its "raw" form is not acceptable to the application's + protocol. The timestamp and microsecond field used in the reply MUST + be the client's timestamp and microsecond field (as provided in the + authenticator). If a sequence number is to be included, it SHOULD be + randomly chosen as described above for the authenticator. A subkey + MAY be included if the server desires to negotiate a different + subkey. The KRB_AP_REP message is encrypted in the session key + extracted from the ticket. + + Note that in the Kerberos Version 4 protocol, the timestamp in the + reply was the client's timestamp plus one. This is not necessary in + Version 5 because Version 5 messages are formatted in such a way that + it is not possible to create the reply by judicious message surgery + (even in encrypted form) without knowledge of the appropriate + encryption keys. + +3.2.5. Receipt of KRB_AP_REP Message + + If a KRB_AP_REP message is returned, the client uses the session key + from the credentials obtained for the server to decrypt the message + and verifies that the timestamp and microsecond fields match those in + the Authenticator it sent to the server. If they match, then the + client is assured that the server is genuine. The sequence number + and subkey (if present) are retained for later use. (Note that for + encrypting the KRB_AP_REP message, the sub-session key is not used, + even if it is present in the Authentication.) + +3.2.6. Using the Encryption Key + + After the KRB_AP_REQ/KRB_AP_REP exchange has occurred, the client and + server share an encryption key that can be used by the application. + In some cases, the use of this session key will be implicit in the + protocol; in others the method of use must be chosen from several + alternatives. The application MAY choose the actual encryption key + to be used for KRB_PRIV, KRB_SAFE, or other application-specific uses + based on the session key from the ticket and subkeys in the + KRB_AP_REP message and the authenticator. Implementations of the + protocol MAY provide routines to choose subkeys based on session keys + + + +Neuman, et al. Standards Track [Page 33] + +RFC 4120 Kerberos V5 July 2005 + + + and random numbers and to generate a negotiated key to be returned in + the KRB_AP_REP message. + + To mitigate the effect of failures in random number generation on the + client, it is strongly encouraged that any key derived by an + application for subsequent use include the full key entropy derived + from the KDC-generated session key carried in the ticket. We leave + the protocol negotiations of how to use the key (e.g., for selecting + an encryption or checksum type) to the application programmer. The + Kerberos protocol does not constrain the implementation options, but + an example of how this might be done follows. + + One way that an application may choose to negotiate a key to be used + for subsequent integrity and privacy protection is for the client to + propose a key in the subkey field of the authenticator. The server + can then choose a key using the key proposed by the client as input, + returning the new subkey in the subkey field of the application + reply. This key could then be used for subsequent communication. + + With both the one-way and mutual authentication exchanges, the peers + should take care not to send sensitive information to each other + without proper assurances. In particular, applications that require + privacy or integrity SHOULD use the KRB_AP_REP response from the + server to the client to assure both client and server of their peer's + identity. If an application protocol requires privacy of its + messages, it can use the KRB_PRIV message (section 3.5). The + KRB_SAFE message (Section 3.4) can be used to ensure integrity. + +3.3. The Ticket-Granting Service (TGS) Exchange + + Summary + + Message direction Message type Section + 1. Client to Kerberos KRB_TGS_REQ 5.4.1 + 2. Kerberos to client KRB_TGS_REP or 5.4.2 + KRB_ERROR 5.9.1 + + The TGS exchange between a client and the Kerberos TGS is initiated + by a client when it seeks to obtain authentication credentials for a + given server (which might be registered in a remote realm), when it + seeks to renew or validate an existing ticket, or when it seeks to + obtain a proxy ticket. In the first case, the client must already + have acquired a ticket for the Ticket-Granting Service using the AS + exchange (the TGT is usually obtained when a client initially + authenticates to the system, such as when a user logs in). The + message format for the TGS exchange is almost identical to that for + the AS exchange. The primary difference is that encryption and + decryption in the TGS exchange does not take place under the client's + + + +Neuman, et al. Standards Track [Page 34] + +RFC 4120 Kerberos V5 July 2005 + + + key. Instead, the session key from the TGT or renewable ticket, or + sub-session key from an Authenticator is used. As is the case for + all application servers, expired tickets are not accepted by the TGS, + so once a renewable or TGT expires, the client must use a separate + exchange to obtain valid tickets. + + The TGS exchange consists of two messages: a request (KRB_TGS_REQ) + from the client to the Kerberos Ticket-Granting Server, and a reply + (KRB_TGS_REP or KRB_ERROR). The KRB_TGS_REQ message includes + information authenticating the client plus a request for credentials. + The authentication information consists of the authentication header + (KRB_AP_REQ), which includes the client's previously obtained + ticket-granting, renewable, or invalid ticket. In the TGT and proxy + cases, the request MAY include one or more of the following: a list + of network addresses, a collection of typed authorization data to be + sealed in the ticket for authorization use by the application server, + or additional tickets (the use of which are described later). The + TGS reply (KRB_TGS_REP) contains the requested credentials, encrypted + in the session key from the TGT or renewable ticket, or, if present, + in the sub-session key from the Authenticator (part of the + authentication header). The KRB_ERROR message contains an error code + and text explaining what went wrong. The KRB_ERROR message is not + encrypted. The KRB_TGS_REP message contains information that can be + used to detect replays, and to associate it with the message to which + it replies. The KRB_ERROR message also contains information that can + be used to associate it with the message to which it replies. The + same comments about integrity protection of KRB_ERROR messages + mentioned in Section 3.1 apply to the TGS exchange. + +3.3.1. Generation of KRB_TGS_REQ Message + + Before sending a request to the ticket-granting service, the client + MUST determine in which realm the application server is believed to + be registered. This can be accomplished in several ways. It might + be known beforehand (since the realm is part of the principal + identifier), it might be stored in a nameserver, or it might be + obtained from a configuration file. If the realm to be used is + obtained from a nameserver, there is a danger of being spoofed if the + nameservice providing the realm name is not authenticated. This + might result in the use of a realm that has been compromised, which + would result in an attacker's ability to compromise the + authentication of the application server to the client. + + If the client knows the service principal name and realm and it does + not already possess a TGT for the appropriate realm, then one must be + obtained. This is first attempted by requesting a TGT for the + destination realm from a Kerberos server for which the client + possesses a TGT (by using the KRB_TGS_REQ message recursively). The + + + +Neuman, et al. Standards Track [Page 35] + +RFC 4120 Kerberos V5 July 2005 + + + Kerberos server MAY return a TGT for the desired realm, in which case + one can proceed. Alternatively, the Kerberos server MAY return a TGT + for a realm that is 'closer' to the desired realm (further along the + standard hierarchical path between the client's realm and the + requested realm server's realm). Note that in this case + misconfiguration of the Kerberos servers may cause loops in the + resulting authentication path, which the client should be careful to + detect and avoid. + + If the Kerberos server returns a TGT for a realm 'closer' than the + desired realm, the client MAY use local policy configuration to + verify that the authentication path used is an acceptable one. + Alternatively, a client MAY choose its own authentication path, + rather than rely on the Kerberos server to select one. In either + case, any policy or configuration information used to choose or + validate authentication paths, whether by the Kerberos server or by + the client, MUST be obtained from a trusted source. + + When a client obtains a TGT that is 'closer' to the destination + realm, the client MAY cache this ticket and reuse it in future + KRB-TGS exchanges with services in the 'closer' realm. However, if + the client were to obtain a TGT for the 'closer' realm by starting at + the initial KDC rather than as part of obtaining another ticket, then + a shorter path to the 'closer' realm might be used. This shorter + path may be desirable because fewer intermediate KDCs would know the + session key of the ticket involved. For this reason, clients SHOULD + evaluate whether they trust the realms transited in obtaining the + 'closer' ticket when making a decision to use the ticket in future. + + Once the client obtains a TGT for the appropriate realm, it + determines which Kerberos servers serve that realm and contacts one + of them. The list might be obtained through a configuration file or + network service, or it MAY be generated from the name of the realm. + As long as the secret keys exchanged by realms are kept secret, only + denial of service results from using a false Kerberos server. + + As in the AS exchange, the client MAY specify a number of options in + the KRB_TGS_REQ message. One of these options is the ENC-TKT-IN-SKEY + option used for user-to-user authentication. An overview of user- + to-user authentication can be found in Section 3.7. When generating + the KRB_TGS_REQ message, this option indicates that the client is + including a TGT obtained from the application server in the + additional tickets field of the request and that the KDC SHOULD + encrypt the ticket for the application server using the session key + from this additional ticket, instead of a server key from the + principal database. + + + + + +Neuman, et al. Standards Track [Page 36] + +RFC 4120 Kerberos V5 July 2005 + + + The client prepares the KRB_TGS_REQ message, providing an + authentication header as an element of the padata field, and + including the same fields as used in the KRB_AS_REQ message along + with several optional fields: the enc-authorizatfion-data field for + application server use and additional tickets required by some + options. + + In preparing the authentication header, the client can select a sub- + session key under which the response from the Kerberos server will be + encrypted. If the client selects a sub-session key, care must be + taken to ensure the randomness of the selected sub-session key. + + If the sub-session key is not specified, the session key from the TGT + will be used. If the enc-authorization-data is present, it MUST be + encrypted in the sub-session key, if present, from the authenticator + portion of the authentication header, or, if not present, by using + the session key from the TGT. + + Once prepared, the message is sent to a Kerberos server for the + destination realm. + +3.3.2. Receipt of KRB_TGS_REQ Message + + The KRB_TGS_REQ message is processed in a manner similar to the + KRB_AS_REQ message, but there are many additional checks to be + performed. First, the Kerberos server MUST determine which server + the accompanying ticket is for, and it MUST select the appropriate + key to decrypt it. For a normal KRB_TGS_REQ message, it will be for + the ticket-granting service, and the TGS's key will be used. If the + TGT was issued by another realm, then the appropriate inter-realm key + MUST be used. If (a) the accompanying ticket is not a TGT for the + current realm, but is for an application server in the current realm, + (b) the RENEW, VALIDATE, or PROXY options are specified in the + request, and (c) the server for which a ticket is requested is the + server named in the accompanying ticket, then the KDC will decrypt + the ticket in the authentication header using the key of the server + for which it was issued. If no ticket can be found in the padata + field, the KDC_ERR_PADATA_TYPE_NOSUPP error is returned. + + Once the accompanying ticket has been decrypted, the user-supplied + checksum in the Authenticator MUST be verified against the contents + of the request, and the message MUST be rejected if the checksums do + not match (with an error code of KRB_AP_ERR_MODIFIED) or if the + checksum is not collision-proof (with an error code of + KRB_AP_ERR_INAPP_CKSUM). If the checksum type is not supported, the + KDC_ERR_SUMTYPE_NOSUPP error is returned. If the authorization-data + are present, they are decrypted using the sub-session key from the + Authenticator. + + + +Neuman, et al. Standards Track [Page 37] + +RFC 4120 Kerberos V5 July 2005 + + + If any of the decryptions indicate failed integrity checks, the + KRB_AP_ERR_BAD_INTEGRITY error is returned. + + As discussed in Section 3.1.2, the KDC MUST send a valid KRB_TGS_REP + message if it receives a KRB_TGS_REQ message identical to one it has + recently processed. However, if the authenticator is a replay, but + the rest of the request is not identical, then the KDC SHOULD return + KRB_AP_ERR_REPEAT. + +3.3.3. Generation of KRB_TGS_REP Message + + The KRB_TGS_REP message shares its format with the KRB_AS_REP + (KRB_KDC_REP), but with its type field set to KRB_TGS_REP. The + detailed specification is in Section 5.4.2. + + The response will include a ticket for the requested server or for a + ticket granting server of an intermediate KDC to be contacted to + obtain the requested ticket. The Kerberos database is queried to + retrieve the record for the appropriate server (including the key + with which the ticket will be encrypted). If the request is for a + TGT for a remote realm, and if no key is shared with the requested + realm, then the Kerberos server will select the realm 'closest' to + the requested realm with which it does share a key and use that realm + instead. This is the only case where the response for the KDC will + be for a different server than that requested by the client. + + By default, the address field, the client's name and realm, the list + of transited realms, the time of initial authentication, the + expiration time, and the authorization data of the newly-issued + ticket will be copied from the TGT or renewable ticket. If the + transited field needs to be updated, but the transited type is not + supported, the KDC_ERR_TRTYPE_NOSUPP error is returned. + + If the request specifies an endtime, then the endtime of the new + ticket is set to the minimum of (a) that request, (b) the endtime + from the TGT, and (c) the starttime of the TGT plus the minimum of + the maximum life for the application server and the maximum life for + the local realm (the maximum life for the requesting principal was + already applied when the TGT was issued). If the new ticket is to be + a renewal, then the endtime above is replaced by the minimum of (a) + the value of the renew_till field of the ticket and (b) the starttime + for the new ticket plus the life (endtime-starttime) of the old + ticket. + + If the FORWARDED option has been requested, then the resulting ticket + will contain the addresses specified by the client. This option will + only be honored if the FORWARDABLE flag is set in the TGT. The PROXY + option is similar; the resulting ticket will contain the addresses + + + +Neuman, et al. Standards Track [Page 38] + +RFC 4120 Kerberos V5 July 2005 + + + specified by the client. It will be honored only if the PROXIABLE + flag in the TGT is set. The PROXY option will not be honored on + requests for additional TGTs. + + If the requested starttime is absent, indicates a time in the past, + or is within the window of acceptable clock skew for the KDC and the + POSTDATE option has not been specified, then the starttime of the + ticket is set to the authentication server's current time. If it + indicates a time in the future beyond the acceptable clock skew, but + the POSTDATED option has not been specified or the MAY-POSTDATE flag + is not set in the TGT, then the error KDC_ERR_CANNOT_POSTDATE is + returned. Otherwise, if the TGT has the MAY-POSTDATE flag set, then + the resulting ticket will be postdated, and the requested starttime + is checked against the policy of the local realm. If acceptable, the + ticket's starttime is set as requested, and the INVALID flag is set. + The postdated ticket MUST be validated before use by presenting it to + the KDC after the starttime has been reached. However, in no case + may the starttime, endtime, or renew-till time of a newly-issued + postdated ticket extend beyond the renew-till time of the TGT. + + If the ENC-TKT-IN-SKEY option has been specified and an additional + ticket has been included in the request, it indicates that the client + is using user-to-user authentication to prove its identity to a + server that does not have access to a persistent key. Section 3.7 + describes the effect of this option on the entire Kerberos protocol. + When generating the KRB_TGS_REP message, this option in the + KRB_TGS_REQ message tells the KDC to decrypt the additional ticket + using the key for the server to which the additional ticket was + issued and to verify that it is a TGT. If the name of the requested + server is missing from the request, the name of the client in the + additional ticket will be used. Otherwise, the name of the requested + server will be compared to the name of the client in the additional + ticket. If it is different, the request will be rejected. If the + request succeeds, the session key from the additional ticket will be + used to encrypt the new ticket that is issued instead of using the + key of the server for which the new ticket will be used. + + If (a) the name of the server in the ticket that is presented to the + KDC as part of the authentication header is not that of the TGS + itself, (b) the server is registered in the realm of the KDC, and (c) + the RENEW option is requested, then the KDC will verify that the + RENEWABLE flag is set in the ticket, that the INVALID flag is not set + in the ticket, and that the renew_till time is still in the future. + If the VALIDATE option is requested, the KDC will check that the + starttime has passed and that the INVALID flag is set. If the PROXY + option is requested, then the KDC will check that the PROXIABLE flag + + + + + +Neuman, et al. Standards Track [Page 39] + +RFC 4120 Kerberos V5 July 2005 + + + is set in the ticket. If the tests succeed and the ticket passes the + hotlist check described in the next section, the KDC will issue the + appropriate new ticket. + + The ciphertext part of the response in the KRB_TGS_REP message is + encrypted in the sub-session key from the Authenticator, if present, + or in the session key from the TGT. It is not encrypted using the + client's secret key. Furthermore, the client's key's expiration date + and the key version number fields are left out since these values are + stored along with the client's database record, and that record is + not needed to satisfy a request based on a TGT. + +3.3.3.1. Checking for Revoked Tickets + + Whenever a request is made to the ticket-granting server, the + presented ticket(s) is (are) checked against a hot-list of tickets + that have been canceled. This hot-list might be implemented by + storing a range of issue timestamps for 'suspect tickets'; if a + presented ticket had an authtime in that range, it would be rejected. + In this way, a stolen TGT or renewable ticket cannot be used to gain + additional tickets (renewals or otherwise) once the theft has been + reported to the KDC for the realm in which the server resides. Any + normal ticket obtained before it was reported stolen will still be + valid (because tickets require no interaction with the KDC), but only + until its normal expiration time. If TGTs have been issued for + cross-realm authentication, use of the cross-realm TGT will not be + affected unless the hot-list is propagated to the KDCs for the realms + for which such cross-realm tickets were issued. + +3.3.3.2. Encoding the Transited Field + + If the identity of the server in the TGT that is presented to the KDC + as part of the authentication header is that of the ticket-granting + service, but the TGT was issued from another realm, the KDC will look + up the inter-realm key shared with that realm and use that key to + decrypt the ticket. If the ticket is valid, then the KDC will honor + the request, subject to the constraints outlined above in the section + describing the AS exchange. The realm part of the client's identity + will be taken from the TGT. The name of the realm that issued the + TGT, if it is not the realm of the client principal, will be added to + the transited field of the ticket to be issued. This is accomplished + by reading the transited field from the TGT (which is treated as an + unordered set of realm names), adding the new realm to the set, and + then constructing and writing out its encoded (shorthand) form (this + may involve a rearrangement of the existing encoding). + + Note that the ticket-granting service does not add the name of its + own realm. Instead, its responsibility is to add the name of the + + + +Neuman, et al. Standards Track [Page 40] + +RFC 4120 Kerberos V5 July 2005 + + + previous realm. This prevents a malicious Kerberos server from + intentionally leaving out its own name (it could, however, omit other + realms' names). + + The names of neither the local realm nor the principal's realm are to + be included in the transited field. They appear elsewhere in the + ticket and both are known to have taken part in authenticating the + principal. Because the endpoints are not included, both local and + single-hop inter-realm authentication result in a transited field + that is empty. + + Because this field has the name of each transited realm added to it, + it might potentially be very long. To decrease the length of this + field, its contents are encoded. The initially supported encoding is + optimized for the normal case of inter-realm communication: a + hierarchical arrangement of realms using either domain or X.500 style + realm names. This encoding (called DOMAIN-X500-COMPRESS) is now + described. + + Realm names in the transited field are separated by a ",". The ",", + "\", trailing "."s, and leading spaces (" ") are special characters, + and if they are part of a realm name, they MUST be quoted in the + transited field by preceding them with a "\". + + A realm name ending with a "." is interpreted as being prepended to + the previous realm. For example, we can encode traversal of EDU, + MIT.EDU, ATHENA.MIT.EDU, WASHINGTON.EDU, and CS.WASHINGTON.EDU as: + + "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.". + + Note that if either ATHENA.MIT.EDU, or CS.WASHINGTON.EDU were + endpoints, they would not be included in this field, and we would + have: + + "EDU,MIT.,WASHINGTON.EDU" + + A realm name beginning with a "/" is interpreted as being appended to + the previous realm. For the purpose of appending, the realm + preceding the first listed realm is considered the null realm (""). + If a realm name beginning with a "/" is to stand by itself, then it + SHOULD be preceded by a space (" "). For example, we can encode + traversal of /COM/HP/APOLLO, /COM/HP, /COM, and /COM/DEC as: + + "/COM,/HP,/APOLLO, /COM/DEC". + + As in the example above, if /COM/HP/APOLLO and /COM/DEC were + endpoints, they would not be included in this field, and we would + have: + + + +Neuman, et al. Standards Track [Page 41] + +RFC 4120 Kerberos V5 July 2005 + + + "/COM,/HP" + + A null subfield preceding or following a "," indicates that all + realms between the previous realm and the next realm have been + traversed. For the purpose of interpreting null subfields, the + client's realm is considered to precede those in the transited field, + and the server's realm is considered to follow them. Thus, "," means + that all realms along the path between the client and the server have + been traversed. ",EDU, /COM," means that all realms from the + client's realm up to EDU (in a domain style hierarchy) have been + traversed, and that everything from /COM down to the server's realm + in an X.500 style has also been traversed. This could occur if the + EDU realm in one hierarchy shares an inter-realm key directly with + the /COM realm in another hierarchy. + +3.3.4. Receipt of KRB_TGS_REP Message + + When the KRB_TGS_REP is received by the client, it is processed in + the same manner as the KRB_AS_REP processing described above. The + primary difference is that the ciphertext part of the response must + be decrypted using the sub-session key from the Authenticator, if it + was specified in the request, or the session key from the TGT, rather + than the client's secret key. The server name returned in the reply + is the true principal name of the service. + +3.4. The KRB_SAFE Exchange + + The KRB_SAFE message MAY be used by clients requiring the ability to + detect modifications of messages they exchange. It achieves this by + including a keyed collision-proof checksum of the user data and some + control information. The checksum is keyed with an encryption key + (usually the last key negotiated via subkeys, or the session key if + no negotiation has occurred). + +3.4.1. Generation of a KRB_SAFE Message + + When an application wishes to send a KRB_SAFE message, it collects + its data and the appropriate control information and computes a + checksum over them. The checksum algorithm should be the keyed + checksum mandated to be implemented along with the crypto system used + for the sub-session or session key. The checksum is generated using + the sub-session key, if present, or the session key. Some + implementations use a different checksum algorithm for the KRB_SAFE + messages, but doing so in an interoperable manner is not always + possible. + + The control information for the KRB_SAFE message includes both a + timestamp and a sequence number. The designer of an application + + + +Neuman, et al. Standards Track [Page 42] + +RFC 4120 Kerberos V5 July 2005 + + + using the KRB_SAFE message MUST choose at least one of the two + mechanisms. This choice SHOULD be based on the needs of the + application protocol. + + Sequence numbers are useful when all messages sent will be received + by one's peer. Connection state is presently required to maintain + the session key, so maintaining the next sequence number should not + present an additional problem. + + If the application protocol is expected to tolerate lost messages + without their being resent, the use of the timestamp is the + appropriate replay detection mechanism. Using timestamps is also the + appropriate mechanism for multi-cast protocols in which all of one's + peers share a common sub-session key, but some messages will be sent + to a subset of one's peers. + + After computing the checksum, the client then transmits the + information and checksum to the recipient in the message format + specified in Section 5.6.1. + +3.4.2. Receipt of KRB_SAFE Message + + When an application receives a KRB_SAFE message, it verifies it as + follows. If any error occurs, an error code is reported for use by + the application. + + The message is first checked by verifying that the protocol version + and type fields match the current version and KRB_SAFE, respectively. + A mismatch generates a KRB_AP_ERR_BADVERSION or KRB_AP_ERR_MSG_TYPE + error. The application verifies that the checksum used is a + collision-proof keyed checksum that uses keys compatible with the + sub-session or session key as appropriate (or with the application + key derived from the session or sub-session keys). If it is not, a + KRB_AP_ERR_INAPP_CKSUM error is generated. The sender's address MUST + be included in the control information; the recipient verifies that + the operating system's report of the sender's address matches the + sender's address in the message, and (if a recipient address is + specified or the recipient requires an address) that one of the + recipient's addresses appears as the recipient's address in the + message. To work with network address translation, senders MAY use + the directional address type specified in Section 8.1 for the sender + address and not include recipient addresses. A failed match for + either case generates a KRB_AP_ERR_BADADDR error. Then the timestamp + and usec and/or the sequence number fields are checked. If timestamp + and usec are expected and not present, or if they are present but not + current, the KRB_AP_ERR_SKEW error is generated. Timestamps are not + required to be strictly ordered; they are only required to be in the + skew window. If the server name, along with the client name, time, + + + +Neuman, et al. Standards Track [Page 43] + +RFC 4120 Kerberos V5 July 2005 + + + and microsecond fields from the Authenticator match any recently-seen + (sent or received) such tuples, the KRB_AP_ERR_REPEAT error is + generated. If an incorrect sequence number is included, or if a + sequence number is expected but not present, the KRB_AP_ERR_BADORDER + error is generated. If neither a time-stamp and usec nor a sequence + number is present, a KRB_AP_ERR_MODIFIED error is generated. + Finally, the checksum is computed over the data and control + information, and if it doesn't match the received checksum, a + KRB_AP_ERR_MODIFIED error is generated. + + If all the checks succeed, the application is assured that the + message was generated by its peer and was not modified in transit. + + Implementations SHOULD accept any checksum algorithm they implement + that has both adequate security and keys compatible with the sub- + session or session key. Unkeyed or non-collision-proof checksums are + not suitable for this use. + +3.5. The KRB_PRIV Exchange + + The KRB_PRIV message MAY be used by clients requiring confidentiality + and the ability to detect modifications of exchanged messages. It + achieves this by encrypting the messages and adding control + information. + +3.5.1. Generation of a KRB_PRIV Message + + When an application wishes to send a KRB_PRIV message, it collects + its data and the appropriate control information (specified in + Section 5.7.1) and encrypts them under an encryption key (usually the + last key negotiated via subkeys, or the session key if no negotiation + has occurred). As part of the control information, the client MUST + choose to use either a timestamp or a sequence number (or both); see + the discussion in Section 3.4.1 for guidelines on which to use. + After the user data and control information are encrypted, the client + transmits the ciphertext and some 'envelope' information to the + recipient. + +3.5.2. Receipt of KRB_PRIV Message + + When an application receives a KRB_PRIV message, it verifies it as + follows. If any error occurs, an error code is reported for use by + the application. + + The message is first checked by verifying that the protocol version + and type fields match the current version and KRB_PRIV, respectively. + A mismatch generates a KRB_AP_ERR_BADVERSION or KRB_AP_ERR_MSG_TYPE + error. The application then decrypts the ciphertext and processes + + + +Neuman, et al. Standards Track [Page 44] + +RFC 4120 Kerberos V5 July 2005 + + + the resultant plaintext. If decryption shows that the data has been + modified, a KRB_AP_ERR_BAD_INTEGRITY error is generated. + + The sender's address MUST be included in the control information; the + recipient verifies that the operating system's report of the sender's + address matches the sender's address in the message. If a recipient + address is specified or the recipient requires an address, then one + of the recipient's addresses MUST also appear as the recipient's + address in the message. Where a sender's or receiver's address might + not otherwise match the address in a message because of network + address translation, an application MAY be written to use addresses + of the directional address type in place of the actual network + address. + + A failed match for either case generates a KRB_AP_ERR_BADADDR error. + To work with network address translation, implementations MAY use the + directional address type defined in Section 7.1 for the sender + address and include no recipient address. + + Next the timestamp and usec and/or the sequence number fields are + checked. If timestamp and usec are expected and not present, or if + they are present but not current, the KRB_AP_ERR_SKEW error is + generated. If the server name, along with the client name, time, and + microsecond fields from the Authenticator match any such recently- + seen tuples, the KRB_AP_ERR_REPEAT error is generated. If an + incorrect sequence number is included, or if a sequence number is + expected but not present, the KRB_AP_ERR_BADORDER error is generated. + If neither a time-stamp and usec nor a sequence number is present, a + KRB_AP_ERR_MODIFIED error is generated. + + If all the checks succeed, the application can assume the message was + generated by its peer and was securely transmitted (without intruders + seeing the unencrypted contents). + +3.6. The KRB_CRED Exchange + + The KRB_CRED message MAY be used by clients requiring the ability to + send Kerberos credentials from one host to another. It achieves this + by sending the tickets together with encrypted data containing the + session keys and other information associated with the tickets. + +3.6.1. Generation of a KRB_CRED Message + + When an application wishes to send a KRB_CRED message, it first + (using the KRB_TGS exchange) obtains credentials to be sent to the + remote host. It then constructs a KRB_CRED message using the ticket + or tickets so obtained, placing the session key needed to use each + + + + +Neuman, et al. Standards Track [Page 45] + +RFC 4120 Kerberos V5 July 2005 + + + ticket in the key field of the corresponding KrbCredInfo sequence of + the encrypted part of the KRB_CRED message. + + Other information associated with each ticket and obtained during the + KRB_TGS exchange is also placed in the corresponding KrbCredInfo + sequence in the encrypted part of the KRB_CRED message. The current + time and, if they are specifically required by the application, the + nonce, s-address, and r-address fields are placed in the encrypted + part of the KRB_CRED message, which is then encrypted under an + encryption key previously exchanged in the KRB_AP exchange (usually + the last key negotiated via subkeys, or the session key if no + negotiation has occurred). + + Implementation note: When constructing a KRB_CRED message for + inclusion in a GSSAPI initial context token, the MIT implementation + of Kerberos will not encrypt the KRB_CRED message if the session key + is a DES or triple DES key. For interoperability with MIT, the + Microsoft implementation will not encrypt the KRB_CRED in a GSSAPI + token if it is using a DES session key. Starting at version 1.2.5, + MIT Kerberos can receive and decode either encrypted or unencrypted + KRB_CRED tokens in the GSSAPI exchange. The Heimdal implementation + of Kerberos can also accept either encrypted or unencrypted KRB_CRED + messages. Since the KRB_CRED message in a GSSAPI token is encrypted + in the authenticator, the MIT behavior does not present a security + problem, although it is a violation of the Kerberos specification. + +3.6.2. Receipt of KRB_CRED Message + + When an application receives a KRB_CRED message, it verifies it. If + any error occurs, an error code is reported for use by the + application. The message is verified by checking that the protocol + version and type fields match the current version and KRB_CRED, + respectively. A mismatch generates a KRB_AP_ERR_BADVERSION or + KRB_AP_ERR_MSG_TYPE error. The application then decrypts the + ciphertext and processes the resultant plaintext. If decryption + shows the data to have been modified, a KRB_AP_ERR_BAD_INTEGRITY + error is generated. + + If present or required, the recipient MAY verify that the operating + system's report of the sender's address matches the sender's address + in the message, and that one of the recipient's addresses appears as + the recipient's address in the message. The address check does not + provide any added security, since the address, if present, has + already been checked in the KRB_AP_REQ message and there is not any + benefit to be gained by an attacker in reflecting a KRB_CRED message + back to its originator. Thus, the recipient MAY ignore the address + even if it is present in order to work better in Network Address + Translation (NAT) environments. A failed match for either case + + + +Neuman, et al. Standards Track [Page 46] + +RFC 4120 Kerberos V5 July 2005 + + + generates a KRB_AP_ERR_BADADDR error. Recipients MAY skip the + address check, as the KRB_CRED message cannot generally be reflected + back to the originator. The timestamp and usec fields (and the nonce + field, if required) are checked next. If the timestamp and usec are + not present, or if they are present but not current, the + KRB_AP_ERR_SKEW error is generated. + + If all the checks succeed, the application stores each of the new + tickets in its credentials cache together with the session key and + other information in the corresponding KrbCredInfo sequence from the + encrypted part of the KRB_CRED message. + +3.7. User-to-User Authentication Exchanges + + User-to-User authentication provides a method to perform + authentication when the verifier does not have a access to long-term + service key. This might be the case when running a server (for + example, a window server) as a user on a workstation. In such cases, + the server may have access to the TGT obtained when the user logged + in to the workstation, but because the server is running as an + unprivileged user, it might not have access to system keys. Similar + situations may arise when running peer-to-peer applications. + + Summary + + Message direction Message type Sections + 0. Message from application server Not specified + 1. Client to Kerberos KRB_TGS_REQ 3.3 & 5.4.1 + 2. Kerberos to client KRB_TGS_REP or 3.3 & 5.4.2 + KRB_ERROR 5.9.1 + 3. Client to application server KRB_AP_REQ 3.2 & 5.5.1 + + To address this problem, the Kerberos protocol allows the client to + request that the ticket issued by the KDC be encrypted using a + session key from a TGT issued to the party that will verify the + authentication. This TGT must be obtained from the verifier by means + of an exchange external to the Kerberos protocol, usually as part of + the application protocol. This message is shown in the summary above + as message 0. Note that because the TGT is encrypted in the KDC's + secret key, it cannot be used for authentication without possession + of the corresponding secret key. Furthermore, because the verifier + does not reveal the corresponding secret key, providing a copy of the + verifier's TGT does not allow impersonation of the verifier. + + Message 0 in the table above represents an application-specific + negotiation between the client and server, at the end of which both + have determined that they will use user-to-user authentication, and + the client has obtained the server's TGT. + + + +Neuman, et al. Standards Track [Page 47] + +RFC 4120 Kerberos V5 July 2005 + + + Next, the client includes the server's TGT as an additional ticket in + its KRB_TGS_REQ request to the KDC (message 1 in the table above) and + specifies the ENC-TKT-IN-SKEY option in its request. + + If validated according to the instructions in Section 3.3.3, the + application ticket returned to the client (message 2 in the table + above) will be encrypted using the session key from the additional + ticket and the client will note this when it uses or stores the + application ticket. + + When contacting the server using a ticket obtained for user-to-user + authentication (message 3 in the table above), the client MUST + specify the USE-SESSION-KEY flag in the ap-options field. This tells + the application server to use the session key associated with its TGT + to decrypt the server ticket provided in the application request. + +4. Encryption and Checksum Specifications + + The Kerberos protocols described in this document are designed to + encrypt messages of arbitrary sizes, using stream or block encryption + ciphers. Encryption is used to prove the identities of the network + entities participating in message exchanges. The Key Distribution + Center for each realm is trusted by all principals registered in that + realm to store a secret key in confidence. Proof of knowledge of + this secret key is used to verify the authenticity of a principal. + + The KDC uses the principal's secret key (in the AS exchange) or a + shared session key (in the TGS exchange) to encrypt responses to + ticket requests; the ability to obtain the secret key or session key + implies the knowledge of the appropriate keys and the identity of the + KDC. The ability of a principal to decrypt the KDC response and to + present a Ticket and a properly formed Authenticator (generated with + the session key from the KDC response) to a service verifies the + identity of the principal; likewise the ability of the service to + extract the session key from the Ticket and to prove its knowledge + thereof in a response verifies the identity of the service. + + [RFC3961] defines a framework for defining encryption and checksum + mechanisms for use with Kerberos. It also defines several such + mechanisms, and more may be added in future updates to that document. + + The string-to-key operation provided by [RFC3961] is used to produce + a long-term key for a principal (generally for a user). The default + salt string, if none is provided via pre-authentication data, is the + concatenation of the principal's realm and name components, in order, + with no separators. Unless it is indicated otherwise, the default + string-to-key opaque parameter set as defined in [RFC3961] is used. + + + + +Neuman, et al. Standards Track [Page 48] + +RFC 4120 Kerberos V5 July 2005 + + + Encrypted data, keys, and checksums are transmitted using the + EncryptedData, EncryptionKey, and Checksum data objects defined in + Section 5.2.9. The encryption, decryption, and checksum operations + described in this document use the corresponding encryption, + decryption, and get_mic operations described in [RFC3961], with + implicit "specific key" generation using the "key usage" values + specified in the description of each EncryptedData or Checksum object + to vary the key for each operation. Note that in some cases, the + value to be used is dependent on the method of choosing the key or + the context of the message. + + Key usages are unsigned 32-bit integers; zero is not permitted. The + key usage values for encrypting or checksumming Kerberos messages are + indicated in Section 5 along with the message definitions. The key + usage values 512-1023 are reserved for uses internal to a Kerberos + implementation. (For example, seeding a pseudo-random number + generator with a value produced by encrypting something with a + session key and a key usage value not used for any other purpose.) + Key usage values between 1024 and 2047 (inclusive) are reserved for + application use; applications SHOULD use even values for encryption + and odd values for checksums within this range. Key usage values are + also summarized in a table in Section 7.5.1. + + There might exist other documents that define protocols in terms of + the RFC 1510 encryption types or checksum types. These documents + would not know about key usages. In order that these specifications + continue to be meaningful until they are updated, if no key usage + values are specified, then key usages 1024 and 1025 must be used to + derive keys for encryption and checksums, respectively. (This does + not apply to protocols that do their own encryption independent of + this framework, by directly using the key resulting from the Kerberos + authentication exchange.) New protocols defined in terms of the + Kerberos encryption and checksum types SHOULD use their own key usage + values. + + Unless it is indicated otherwise, no cipher state chaining is done + from one encryption operation to another. + + Implementation note: Although it is not recommended, some application + protocols will continue to use the key data directly, even if only in + currently existing protocol specifications. An implementation + intended to support general Kerberos applications may therefore need + to make key data available, as well as the attributes and operations + described in [RFC3961]. One of the more common reasons for directly + performing encryption is direct control over negotiation and + selection of a "sufficiently strong" encryption algorithm (in the + context of a given application). Although Kerberos does not directly + provide a facility for negotiating encryption types between the + + + +Neuman, et al. Standards Track [Page 49] + +RFC 4120 Kerberos V5 July 2005 + + + application client and server, there are approaches for using + Kerberos to facilitate this negotiation. For example, a client may + request only "sufficiently strong" session key types from the KDC and + expect that any type returned by the KDC will be understood and + supported by the application server. + +5. Message Specifications + + The ASN.1 collected here should be identical to the contents of + Appendix A. In the case of a conflict, the contents of Appendix A + shall take precedence. + + The Kerberos protocol is defined here in terms of Abstract Syntax + Notation One (ASN.1) [X680], which provides a syntax for specifying + both the abstract layout of protocol messages as well as their + encodings. Implementors not utilizing an existing ASN.1 compiler or + support library are cautioned to understand the actual ASN.1 + specification thoroughly in order to ensure correct implementation + behavior. There is more complexity in the notation than is + immediately obvious, and some tutorials and guides to ASN.1 are + misleading or erroneous. + + Note that in several places, changes to abstract types from RFC 1510 + have been made. This is in part to address widespread assumptions + that various implementors have made, in some cases resulting in + unintentional violations of the ASN.1 standard. These are clearly + flagged where they occur. The differences between the abstract types + in RFC 1510 and abstract types in this document can cause + incompatible encodings to be emitted when certain encoding rules, + e.g., the Packed Encoding Rules (PER), are used. This theoretical + incompatibility should not be relevant for Kerberos, since Kerberos + explicitly specifies the use of the Distinguished Encoding Rules + (DER). It might be an issue for protocols seeking to use Kerberos + types with other encoding rules. (This practice is not recommended.) + With very few exceptions (most notably the usages of BIT STRING), the + encodings resulting from using the DER remain identical between the + types defined in RFC 1510 and the types defined in this document. + + The type definitions in this section assume an ASN.1 module + definition of the following form: + + + + + + + + + + + +Neuman, et al. Standards Track [Page 50] + +RFC 4120 Kerberos V5 July 2005 + + + KerberosV5Spec2 { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) modules(4) krb5spec2(2) + } DEFINITIONS EXPLICIT TAGS ::= BEGIN + + -- rest of definitions here + + END + + This specifies that the tagging context for the module will be + explicit and non-automatic. + + Note that in some other publications (such as [RFC1510] and + [RFC1964]), the "dod" portion of the object identifier is erroneously + specified as having the value "5". In the case of RFC 1964, use of + the "correct" OID value would result in a change in the wire + protocol; therefore, it remains unchanged for now. + + Note that elsewhere in this document, nomenclature for various + message types is inconsistent, but it largely follows C language + conventions, including use of underscore (_) characters and all-caps + spelling of names intended to be numeric constants. Also, in some + places, identifiers (especially those referring to constants) are + written in all-caps in order to distinguish them from surrounding + explanatory text. + + The ASN.1 notation does not permit underscores in identifiers, so in + actual ASN.1 definitions, underscores are replaced with hyphens (-). + Additionally, structure member names and defined values in ASN.1 MUST + begin with a lowercase letter, whereas type names MUST begin with an + uppercase letter. + +5.1. Specific Compatibility Notes on ASN.1 + + For compatibility purposes, implementors should heed the following + specific notes regarding the use of ASN.1 in Kerberos. These notes + do not describe deviations from standard usage of ASN.1. The purpose + of these notes is instead to describe some historical quirks and + non-compliance of various implementations, as well as historical + ambiguities, which, although they are valid ASN.1, can lead to + confusion during implementation. + +5.1.1. ASN.1 Distinguished Encoding Rules + + The encoding of Kerberos protocol messages shall obey the + Distinguished Encoding Rules (DER) of ASN.1 as described in [X690]. + Some implementations (believed primarily to be those derived from DCE + 1.1 and earlier) are known to use the more general Basic Encoding + + + +Neuman, et al. Standards Track [Page 51] + +RFC 4120 Kerberos V5 July 2005 + + + Rules (BER); in particular, these implementations send indefinite + encodings of lengths. Implementations MAY accept such encodings in + the interest of backward compatibility, though implementors are + warned that decoding fully-general BER is fraught with peril. + +5.1.2. Optional Integer Fields + + Some implementations do not internally distinguish between an omitted + optional integer value and a transmitted value of zero. The places + in the protocol where this is relevant include various microseconds + fields, nonces, and sequence numbers. Implementations SHOULD treat + omitted optional integer values as having been transmitted with a + value of zero, if the application is expecting this. + +5.1.3. Empty SEQUENCE OF Types + + There are places in the protocol where a message contains a SEQUENCE + OF type as an optional member. This can result in an encoding that + contains an empty SEQUENCE OF encoding. The Kerberos protocol does + not semantically distinguish between an absent optional SEQUENCE OF + type and a present optional but empty SEQUENCE OF type. + Implementations SHOULD NOT send empty SEQUENCE OF encodings that are + marked OPTIONAL, but SHOULD accept them as being equivalent to an + omitted OPTIONAL type. In the ASN.1 syntax describing Kerberos + messages, instances of these problematic optional SEQUENCE OF types + are indicated with a comment. + +5.1.4. Unrecognized Tag Numbers + + Future revisions to this protocol may include new message types with + different APPLICATION class tag numbers. Such revisions should + protect older implementations by only sending the message types to + parties that are known to understand them; e.g., by means of a flag + bit set by the receiver in a preceding request. In the interest of + robust error handling, implementations SHOULD gracefully handle + receiving a message with an unrecognized tag anyway, and return an + error message, if appropriate. + + In particular, KDCs SHOULD return KRB_AP_ERR_MSG_TYPE if the + incorrect tag is sent over a TCP transport. The KDCs SHOULD NOT + respond to messages received with an unknown tag over UDP transport + in order to avoid denial of service attacks. For non-KDC + applications, the Kerberos implementation typically indicates an + error to the application which takes appropriate steps based on the + application protocol. + + + + + + +Neuman, et al. Standards Track [Page 52] + +RFC 4120 Kerberos V5 July 2005 + + +5.1.5. Tag Numbers Greater Than 30 + + A naive implementation of a DER ASN.1 decoder may experience problems + with ASN.1 tag numbers greater than 30, due to such tag numbers being + encoded using more than one byte. Future revisions of this protocol + may utilize tag numbers greater than 30, and implementations SHOULD + be prepared to gracefully return an error, if appropriate, when they + do not recognize the tag. + +5.2. Basic Kerberos Types + + This section defines a number of basic types that are potentially + used in multiple Kerberos protocol messages. + +5.2.1. KerberosString + + The original specification of the Kerberos protocol in RFC 1510 uses + GeneralString in numerous places for human-readable string data. + Historical implementations of Kerberos cannot utilize the full power + of GeneralString. This ASN.1 type requires the use of designation + and invocation escape sequences as specified in ISO-2022/ECMA-35 + [ISO-2022/ECMA-35] to switch character sets, and the default + character set that is designated as G0 is the ISO-646/ECMA-6 + [ISO-646/ECMA-6] International Reference Version (IRV) (a.k.a. U.S. + ASCII), which mostly works. + + ISO-2022/ECMA-35 defines four character-set code elements (G0..G3) + and two Control-function code elements (C0..C1). DER prohibits the + designation of character sets as any but the G0 and C0 sets. + Unfortunately, this seems to have the side effect of prohibiting the + use of ISO-8859 (ISO Latin) [ISO-8859] character sets or any other + character sets that utilize a 96-character set, as ISO-2022/ECMA-35 + prohibits designating them as the G0 code element. This side effect + is being investigated in the ASN.1 standards community. + + In practice, many implementations treat GeneralStrings as if they + were 8-bit strings of whichever character set the implementation + defaults to, without regard to correct usage of character-set + designation escape sequences. The default character set is often + determined by the current user's operating system-dependent locale. + At least one major implementation places unescaped UTF-8 encoded + Unicode characters in the GeneralString. This failure to adhere to + the GeneralString specifications results in interoperability issues + when conflicting character encodings are utilized by the Kerberos + clients, services, and KDC. + + + + + + +Neuman, et al. Standards Track [Page 53] + +RFC 4120 Kerberos V5 July 2005 + + + This unfortunate situation is the result of improper documentation of + the restrictions of the ASN.1 GeneralString type in prior Kerberos + specifications. + + The new (post-RFC 1510) type KerberosString, defined below, is a + GeneralString that is constrained to contain only characters in + IA5String. + + KerberosString ::= GeneralString (IA5String) + + In general, US-ASCII control characters should not be used in + KerberosString. Control characters SHOULD NOT be used in principal + names or realm names. + + For compatibility, implementations MAY choose to accept GeneralString + values that contain characters other than those permitted by + IA5String, but they should be aware that character set designation + codes will likely be absent, and that the encoding should probably be + treated as locale-specific in almost every way. Implementations MAY + also choose to emit GeneralString values that are beyond those + permitted by IA5String, but they should be aware that doing so is + extraordinarily risky from an interoperability perspective. + + Some existing implementations use GeneralString to encode unescaped + locale-specific characters. This is a violation of the ASN.1 + standard. Most of these implementations encode US-ASCII in the + left-hand half, so as long as the implementation transmits only + US-ASCII, the ASN.1 standard is not violated in this regard. As soon + as such an implementation encodes unescaped locale-specific + characters with the high bit set, it violates the ASN.1 standard. + + Other implementations have been known to use GeneralString to contain + a UTF-8 encoding. This also violates the ASN.1 standard, since UTF-8 + is a different encoding, not a 94 or 96 character "G" set as defined + by ISO 2022. It is believed that these implementations do not even + use the ISO 2022 escape sequence to change the character encoding. + Even if implementations were to announce the encoding change by using + that escape sequence, the ASN.1 standard prohibits the use of any + escape sequences other than those used to designate/invoke "G" or "C" + sets allowed by GeneralString. + + Future revisions to this protocol will almost certainly allow for a + more interoperable representation of principal names, probably + including UTF8String. + + Note that applying a new constraint to a previously unconstrained + type constitutes creation of a new ASN.1 type. In this particular + case, the change does not result in a changed encoding under DER. + + + +Neuman, et al. Standards Track [Page 54] + +RFC 4120 Kerberos V5 July 2005 + + +5.2.2. Realm and PrincipalName + + Realm ::= KerberosString + + PrincipalName ::= SEQUENCE { + name-type [0] Int32, + name-string [1] SEQUENCE OF KerberosString + } + + Kerberos realm names are encoded as KerberosStrings. Realms shall + not contain a character with the code 0 (the US-ASCII NUL). Most + realms will usually consist of several components separated by + periods (.), in the style of Internet Domain Names, or separated by + slashes (/), in the style of X.500 names. Acceptable forms for realm + names are specified in Section 6.1. A PrincipalName is a typed + sequence of components consisting of the following subfields: + + name-type + This field specifies the type of name that follows. Pre-defined + values for this field are specified in Section 6.2. The name-type + SHOULD be treated as a hint. Ignoring the name type, no two names + can be the same (i.e., at least one of the components, or the + realm, must be different). + + name-string + This field encodes a sequence of components that form a name, each + component encoded as a KerberosString. Taken together, a + PrincipalName and a Realm form a principal identifier. Most + PrincipalNames will have only a few components (typically one or + two). + +5.2.3. KerberosTime + + KerberosTime ::= GeneralizedTime -- with no fractional seconds + + The timestamps used in Kerberos are encoded as GeneralizedTimes. A + KerberosTime value shall not include any fractional portions of the + seconds. As required by the DER, it further shall not include any + separators, and it shall specify the UTC time zone (Z). Example: The + only valid format for UTC time 6 minutes, 27 seconds after 9 pm on 6 + November 1985 is 19851106210627Z. + +5.2.4. Constrained Integer Types + + Some integer members of types SHOULD be constrained to values + representable in 32 bits, for compatibility with reasonable + implementation limits. + + + + +Neuman, et al. Standards Track [Page 55] + +RFC 4120 Kerberos V5 July 2005 + + + Int32 ::= INTEGER (-2147483648..2147483647) + -- signed values representable in 32 bits + + UInt32 ::= INTEGER (0..4294967295) + -- unsigned 32 bit values + + Microseconds ::= INTEGER (0..999999) + -- microseconds + + Although this results in changes to the abstract types from the RFC + 1510 version, the encoding in DER should be unaltered. Historical + implementations were typically limited to 32-bit integer values + anyway, and assigned numbers SHOULD fall in the space of integer + values representable in 32 bits in order to promote interoperability + anyway. + + Several integer fields in messages are constrained to fixed values. + + pvno + also TKT-VNO or AUTHENTICATOR-VNO, this recurring field is always + the constant integer 5. There is no easy way to make this field + into a useful protocol version number, so its value is fixed. + + msg-type + this integer field is usually identical to the application tag + number of the containing message type. + +5.2.5. HostAddress and HostAddresses + + HostAddress ::= SEQUENCE { + addr-type [0] Int32, + address [1] OCTET STRING + } + + -- NOTE: HostAddresses is always used as an OPTIONAL field and + -- should not be empty. + HostAddresses -- NOTE: subtly different from rfc1510, + -- but has a value mapping and encodes the same + ::= SEQUENCE OF HostAddress + + The host address encodings consist of two fields: + + addr-type + This field specifies the type of address that follows. Pre- + defined values for this field are specified in Section 7.5.3. + + address + This field encodes a single address of type addr-type. + + + +Neuman, et al. Standards Track [Page 56] + +RFC 4120 Kerberos V5 July 2005 + + +5.2.6. AuthorizationData + + -- NOTE: AuthorizationData is always used as an OPTIONAL field and + -- should not be empty. + AuthorizationData ::= SEQUENCE OF SEQUENCE { + ad-type [0] Int32, + ad-data [1] OCTET STRING + } + + ad-data + This field contains authorization data to be interpreted according + to the value of the corresponding ad-type field. + + ad-type + This field specifies the format for the ad-data subfield. All + negative values are reserved for local use. Non-negative values + are reserved for registered use. + + Each sequence of type and data is referred to as an authorization + element. Elements MAY be application specific; however, there is a + common set of recursive elements that should be understood by all + implementations. These elements contain other elements embedded + within them, and the interpretation of the encapsulating element + determines which of the embedded elements must be interpreted, and + which may be ignored. + + These common authorization data elements are recursively defined, + meaning that the ad-data for these types will itself contain a + sequence of authorization data whose interpretation is affected by + the encapsulating element. Depending on the meaning of the + encapsulating element, the encapsulated elements may be ignored, + might be interpreted as issued directly by the KDC, or might be + stored in a separate plaintext part of the ticket. The types of the + encapsulating elements are specified as part of the Kerberos + specification because the behavior based on these values should be + understood across implementations, whereas other elements need only + be understood by the applications that they affect. + + Authorization data elements are considered critical if present in a + ticket or authenticator. If an unknown authorization data element + type is received by a server either in an AP-REQ or in a ticket + contained in an AP-REQ, then, unless it is encapsulated in a known + authorization data element amending the criticality of the elements + it contains, authentication MUST fail. Authorization data is + intended to restrict the use of a ticket. If the service cannot + determine whether the restriction applies to that service, then a + + + + + +Neuman, et al. Standards Track [Page 57] + +RFC 4120 Kerberos V5 July 2005 + + + security weakness may result if the ticket can be used for that + service. Authorization elements that are optional can be enclosed in + an AD-IF-RELEVANT element. + + In the definitions that follow, the value of the ad-type for the + element will be specified as the least significant part of the + subsection number, and the value of the ad-data will be as shown in + the ASN.1 structure that follows the subsection heading. + + Contents of ad-data ad-type + + DER encoding of AD-IF-RELEVANT 1 + + DER encoding of AD-KDCIssued 4 + + DER encoding of AD-AND-OR 5 + + DER encoding of AD-MANDATORY-FOR-KDC 8 + +5.2.6.1. IF-RELEVANT + + AD-IF-RELEVANT ::= AuthorizationData + + AD elements encapsulated within the if-relevant element are intended + for interpretation only by application servers that understand the + particular ad-type of the embedded element. Application servers that + do not understand the type of an element embedded within the + if-relevant element MAY ignore the uninterpretable element. This + element promotes interoperability across implementations that may + have local extensions for authorization. The ad-type for + AD-IF-RELEVANT is (1). + +5.2.6.2. KDCIssued + + AD-KDCIssued ::= SEQUENCE { + ad-checksum [0] Checksum, + i-realm [1] Realm OPTIONAL, + i-sname [2] PrincipalName OPTIONAL, + elements [3] AuthorizationData + } + + ad-checksum + A cryptographic checksum computed over the DER encoding of the + AuthorizationData in the "elements" field, keyed with the session + key. Its checksumtype is the mandatory checksum type for the + encryption type of the session key, and its key usage value is 19. + + + + + +Neuman, et al. Standards Track [Page 58] + +RFC 4120 Kerberos V5 July 2005 + + + i-realm, i-sname + The name of the issuing principal if different from that of the + KDC itself. This field would be used when the KDC can verify the + authenticity of elements signed by the issuing principal, and it + allows this KDC to notify the application server of the validity + of those elements. + + elements + A sequence of authorization data elements issued by the KDC. + + The KDC-issued ad-data field is intended to provide a means for + Kerberos principal credentials to embed within themselves privilege + attributes and other mechanisms for positive authorization, + amplifying the privileges of the principal beyond what can be done + using credentials without such an a-data element. + + The above means cannot be provided without this element because the + definition of the authorization-data field allows elements to be + added at will by the bearer of a TGT at the time when they request + service tickets, and elements may also be added to a delegated ticket + by inclusion in the authenticator. + + For KDC-issued elements, this is prevented because the elements are + signed by the KDC by including a checksum encrypted using the + server's key (the same key used to encrypt the ticket or a key + derived from that key). Elements encapsulated with in the KDC-issued + element MUST be ignored by the application server if this "signature" + is not present. Further, elements encapsulated within this element + from a TGT MAY be interpreted by the KDC, and used as a basis + according to policy for including new signed elements within + derivative tickets, but they will not be copied to a derivative + ticket directly. If they are copied directly to a derivative ticket + by a KDC that is not aware of this element, the signature will not be + correct for the application ticket elements, and the field will be + ignored by the application server. + + This element and the elements it encapsulates MAY safely be ignored + by applications, application servers, and KDCs that do not implement + this element. + + The ad-type for AD-KDC-ISSUED is (4). + +5.2.6.3. AND-OR + + AD-AND-OR ::= SEQUENCE { + condition-count [0] Int32, + elements [1] AuthorizationData + } + + + +Neuman, et al. Standards Track [Page 59] + +RFC 4120 Kerberos V5 July 2005 + + + When restrictive AD elements are encapsulated within the and-or + element, the and-or element is considered satisfied if and only if at + least the number of encapsulated elements specified in condition- + count are satisfied. Therefore, this element MAY be used to + implement an "or" operation by setting the condition-count field to + 1, and it MAY specify an "and" operation by setting the condition + count to the number of embedded elements. Application servers that + do not implement this element MUST reject tickets that contain + authorization data elements of this type. + + The ad-type for AD-AND-OR is (5). + +5.2.6.4. MANDATORY-FOR-KDC + + AD-MANDATORY-FOR-KDC ::= AuthorizationData + + AD elements encapsulated within the mandatory-for-kdc element are to + be interpreted by the KDC. KDCs that do not understand the type of + an element embedded within the mandatory-for-kdc element MUST reject + the request. + + The ad-type for AD-MANDATORY-FOR-KDC is (8). + +5.2.7. PA-DATA + + Historically, PA-DATA have been known as "pre-authentication data", + meaning that they were used to augment the initial authentication + with the KDC. Since that time, they have also been used as a typed + hole with which to extend protocol exchanges with the KDC. + + PA-DATA ::= SEQUENCE { + -- NOTE: first tag is [1], not [0] + padata-type [1] Int32, + padata-value [2] OCTET STRING -- might be encoded AP-REQ + } + + padata-type + Indicates the way that the padata-value element is to be + interpreted. Negative values of padata-type are reserved for + unregistered use; non-negative values are used for a registered + interpretation of the element type. + + padata-value + Usually contains the DER encoding of another type; the padata-type + field identifies which type is encoded here. + + + + + + +Neuman, et al. Standards Track [Page 60] + +RFC 4120 Kerberos V5 July 2005 + + + padata-type Name Contents of padata-value + + 1 pa-tgs-req DER encoding of AP-REQ + + 2 pa-enc-timestamp DER encoding of PA-ENC-TIMESTAMP + + 3 pa-pw-salt salt (not ASN.1 encoded) + + 11 pa-etype-info DER encoding of ETYPE-INFO + + 19 pa-etype-info2 DER encoding of ETYPE-INFO2 + + This field MAY also contain information needed by certain + extensions to the Kerberos protocol. For example, it might be + used to verify the identity of a client initially before any + response is returned. + + The padata field can also contain information needed to help the + KDC or the client select the key needed for generating or + decrypting the response. This form of the padata is useful for + supporting the use of certain token cards with Kerberos. The + details of such extensions are specified in separate documents. + See [Pat92] for additional uses of this field. + +5.2.7.1. PA-TGS-REQ + + In the case of requests for additional tickets (KRB_TGS_REQ), + padata-value will contain an encoded AP-REQ. The checksum in the + authenticator (which MUST be collision-proof) is to be computed over + the KDC-REQ-BODY encoding. + +5.2.7.2. Encrypted Timestamp Pre-authentication + + There are pre-authentication types that may be used to pre- + authenticate a client by means of an encrypted timestamp. + + PA-ENC-TIMESTAMP ::= EncryptedData -- PA-ENC-TS-ENC + + PA-ENC-TS-ENC ::= SEQUENCE { + patimestamp [0] KerberosTime -- client's time --, + pausec [1] Microseconds OPTIONAL + } + + Patimestamp contains the client's time, and pausec contains the + microseconds, which MAY be omitted if a client will not generate more + than one request per second. The ciphertext (padata-value) consists + of the PA-ENC-TS-ENC encoding, encrypted using the client's secret + key and a key usage value of 1. + + + +Neuman, et al. Standards Track [Page 61] + +RFC 4120 Kerberos V5 July 2005 + + + This pre-authentication type was not present in RFC 1510, but many + implementations support it. + +5.2.7.3. PA-PW-SALT + + The padata-value for this pre-authentication type contains the salt + for the string-to-key to be used by the client to obtain the key for + decrypting the encrypted part of an AS-REP message. Unfortunately, + for historical reasons, the character set to be used is unspecified + and probably locale-specific. + + This pre-authentication type was not present in RFC 1510, but many + implementations support it. It is necessary in any case where the + salt for the string-to-key algorithm is not the default. + + In the trivial example, a zero-length salt string is very commonplace + for realms that have converted their principal databases from + Kerberos Version 4. + + A KDC SHOULD NOT send PA-PW-SALT when issuing a KRB-ERROR message + that requests additional pre-authentication. Implementation note: + Some KDC implementations issue an erroneous PA-PW-SALT when issuing a + KRB-ERROR message that requests additional pre-authentication. + Therefore, clients SHOULD ignore a PA-PW-SALT accompanying a + KRB-ERROR message that requests additional pre-authentication. As + noted in section 3.1.3, a KDC MUST NOT send PA-PW-SALT when the + client's AS-REQ includes at least one "newer" etype. + +5.2.7.4. PA-ETYPE-INFO + + The ETYPE-INFO pre-authentication type is sent by the KDC in a + KRB-ERROR indicating a requirement for additional pre-authentication. + It is usually used to notify a client of which key to use for the + encryption of an encrypted timestamp for the purposes of sending a + PA-ENC-TIMESTAMP pre-authentication value. It MAY also be sent in an + AS-REP to provide information to the client about which key salt to + use for the string-to-key to be used by the client to obtain the key + for decrypting the encrypted part the AS-REP. + + ETYPE-INFO-ENTRY ::= SEQUENCE { + etype [0] Int32, + salt [1] OCTET STRING OPTIONAL + } + + ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY + + The salt, like that of PA-PW-SALT, is also completely unspecified + with respect to character set and is probably locale-specific. + + + +Neuman, et al. Standards Track [Page 62] + +RFC 4120 Kerberos V5 July 2005 + + + If ETYPE-INFO is sent in an AS-REP, there shall be exactly one + ETYPE-INFO-ENTRY, and its etype shall match that of the enc-part in + the AS-REP. + + This pre-authentication type was not present in RFC 1510, but many + implementations that support encrypted timestamps for pre- + authentication need to support ETYPE-INFO as well. As noted in + Section 3.1.3, a KDC MUST NOT send PA-ETYPE-INFO when the client's + AS-REQ includes at least one "newer" etype. + +5.2.7.5. PA-ETYPE-INFO2 + + The ETYPE-INFO2 pre-authentication type is sent by the KDC in a + KRB-ERROR indicating a requirement for additional pre-authentication. + It is usually used to notify a client of which key to use for the + encryption of an encrypted timestamp for the purposes of sending a + PA-ENC-TIMESTAMP pre-authentication value. It MAY also be sent in an + AS-REP to provide information to the client about which key salt to + use for the string-to-key to be used by the client to obtain the key + for decrypting the encrypted part the AS-REP. + +ETYPE-INFO2-ENTRY ::= SEQUENCE { + etype [0] Int32, + salt [1] KerberosString OPTIONAL, + s2kparams [2] OCTET STRING OPTIONAL +} + +ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY + + The type of the salt is KerberosString, but existing installations + might have locale-specific characters stored in salt strings, and + implementors MAY choose to handle them. + + The interpretation of s2kparams is specified in the cryptosystem + description associated with the etype. Each cryptosystem has a + default interpretation of s2kparams that will hold if that element is + omitted from the encoding of ETYPE-INFO2-ENTRY. + + If ETYPE-INFO2 is sent in an AS-REP, there shall be exactly one + ETYPE-INFO2-ENTRY, and its etype shall match that of the enc-part in + the AS-REP. + + The preferred ordering of the "hint" pre-authentication data that + affect client key selection is: ETYPE-INFO2, followed by ETYPE-INFO, + followed by PW-SALT. As noted in Section 3.1.3, a KDC MUST NOT send + ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one + "newer" etype. + + + + +Neuman, et al. Standards Track [Page 63] + +RFC 4120 Kerberos V5 July 2005 + + + The ETYPE-INFO2 pre-authentication type was not present in RFC 1510. + +5.2.8. KerberosFlags + + For several message types, a specific constrained bit string type, + KerberosFlags, is used. + + KerberosFlags ::= BIT STRING (SIZE (32..MAX)) + -- minimum number of bits shall be sent, + -- but no fewer than 32 + + Compatibility note: The following paragraphs describe a change from + the RFC 1510 description of bit strings that would result in + incompatility in the case of an implementation that strictly + conformed to ASN.1 DER and RFC 1510. + + ASN.1 bit strings have multiple uses. The simplest use of a bit + string is to contain a vector of bits, with no particular meaning + attached to individual bits. This vector of bits is not necessarily + a multiple of eight bits long. The use in Kerberos of a bit string + as a compact boolean vector wherein each element has a distinct + meaning poses some problems. The natural notation for a compact + boolean vector is the ASN.1 "NamedBit" notation, and the DER require + that encodings of a bit string using "NamedBit" notation exclude any + trailing zero bits. This truncation is easy to neglect, especially + given C language implementations that naturally choose to store + boolean vectors as 32-bit integers. + + For example, if the notation for KDCOptions were to include the + "NamedBit" notation, as in RFC 1510, and a KDCOptions value to be + encoded had only the "forwardable" (bit number one) bit set, the DER + encoding MUST include only two bits: the first reserved bit + ("reserved", bit number zero, value zero) and the one-valued bit (bit + number one) for "forwardable". + + Most existing implementations of Kerberos unconditionally send 32 + bits on the wire when encoding bit strings used as boolean vectors. + This behavior violates the ASN.1 syntax used for flag values in RFC + 1510, but it occurs on such a widely installed base that the protocol + description is being modified to accommodate it. + + Consequently, this document removes the "NamedBit" notations for + individual bits, relegating them to comments. The size constraint on + the KerberosFlags type requires that at least 32 bits be encoded at + all times, though a lenient implementation MAY choose to accept fewer + than 32 bits and to treat the missing bits as set to zero. + + + + + +Neuman, et al. Standards Track [Page 64] + +RFC 4120 Kerberos V5 July 2005 + + + Currently, no uses of KerberosFlags specify more than 32 bits' worth + of flags, although future revisions of this document may do so. When + more than 32 bits are to be transmitted in a KerberosFlags value, + future revisions to this document will likely specify that the + smallest number of bits needed to encode the highest-numbered one- + valued bit should be sent. This is somewhat similar to the DER + encoding of a bit string that is declared with the "NamedBit" + notation. + +5.2.9. Cryptosystem-Related Types + + Many Kerberos protocol messages contain an EncryptedData as a + container for arbitrary encrypted data, which is often the encrypted + encoding of another data type. Fields within EncryptedData assist + the recipient in selecting a key with which to decrypt the enclosed + data. + + EncryptedData ::= SEQUENCE { + etype [0] Int32 -- EncryptionType --, + kvno [1] UInt32 OPTIONAL, + cipher [2] OCTET STRING -- ciphertext + } + + etype + This field identifies which encryption algorithm was used to + encipher the cipher. + + kvno + This field contains the version number of the key under which data + is encrypted. It is only present in messages encrypted under long + lasting keys, such as principals' secret keys. + + cipher + This field contains the enciphered text, encoded as an OCTET + STRING. (Note that the encryption mechanisms defined in [RFC3961] + MUST incorporate integrity protection as well, so no additional + checksum is required.) + + The EncryptionKey type is the means by which cryptographic keys used + for encryption are transferred. + + EncryptionKey ::= SEQUENCE { + keytype [0] Int32 -- actually encryption type --, + keyvalue [1] OCTET STRING + } + + + + + + +Neuman, et al. Standards Track [Page 65] + +RFC 4120 Kerberos V5 July 2005 + + + keytype + This field specifies the encryption type of the encryption key + that follows in the keyvalue field. Although its name is + "keytype", it actually specifies an encryption type. Previously, + multiple cryptosystems that performed encryption differently but + were capable of using keys with the same characteristics were + permitted to share an assigned number to designate the type of + key; this usage is now deprecated. + + keyvalue + This field contains the key itself, encoded as an octet string. + + Messages containing cleartext data to be authenticated will usually + do so by using a member of type Checksum. Most instances of Checksum + use a keyed hash, though exceptions will be noted. + + Checksum ::= SEQUENCE { + cksumtype [0] Int32, + checksum [1] OCTET STRING + } + + cksumtype + This field indicates the algorithm used to generate the + accompanying checksum. + + checksum + This field contains the checksum itself, encoded as an octet + string. + + See Section 4 for a brief description of the use of encryption and + checksums in Kerberos. + +5.3. Tickets + + This section describes the format and encryption parameters for + tickets and authenticators. When a ticket or authenticator is + included in a protocol message, it is treated as an opaque object. A + ticket is a record that helps a client authenticate to a service. A + Ticket contains the following information: + + Ticket ::= [APPLICATION 1] SEQUENCE { + tkt-vno [0] INTEGER (5), + realm [1] Realm, + sname [2] PrincipalName, + enc-part [3] EncryptedData -- EncTicketPart + } + + -- Encrypted part of ticket + + + +Neuman, et al. Standards Track [Page 66] + +RFC 4120 Kerberos V5 July 2005 + + + EncTicketPart ::= [APPLICATION 3] SEQUENCE { + flags [0] TicketFlags, + key [1] EncryptionKey, + crealm [2] Realm, + cname [3] PrincipalName, + transited [4] TransitedEncoding, + authtime [5] KerberosTime, + starttime [6] KerberosTime OPTIONAL, + endtime [7] KerberosTime, + renew-till [8] KerberosTime OPTIONAL, + caddr [9] HostAddresses OPTIONAL, + authorization-data [10] AuthorizationData OPTIONAL + } + + -- encoded Transited field + TransitedEncoding ::= SEQUENCE { + tr-type [0] Int32 -- must be registered --, + contents [1] OCTET STRING + } + + TicketFlags ::= KerberosFlags + -- reserved(0), + -- forwardable(1), + -- forwarded(2), + -- proxiable(3), + -- proxy(4), + -- may-postdate(5), + -- postdated(6), + -- invalid(7), + -- renewable(8), + -- initial(9), + -- pre-authent(10), + -- hw-authent(11), + -- the following are new since 1510 + -- transited-policy-checked(12), + -- ok-as-delegate(13) + + tkt-vno + This field specifies the version number for the ticket format. + This document describes version number 5. + + realm + This field specifies the realm that issued a ticket. It also + serves to identify the realm part of the server's principal + identifier. Since a Kerberos server can only issue tickets for + servers within its realm, the two will always be identical. + + + + + +Neuman, et al. Standards Track [Page 67] + +RFC 4120 Kerberos V5 July 2005 + + + sname + This field specifies all components of the name part of the + server's identity, including those parts that identify a specific + instance of a service. + + enc-part + This field holds the encrypted encoding of the EncTicketPart + sequence. It is encrypted in the key shared by Kerberos and the + end server (the server's secret key), using a key usage value of + 2. + + flags + This field indicates which of various options were used or + requested when the ticket was issued. The meanings of the flags + are as follows: + + Bit(s) Name Description + + 0 reserved Reserved for future expansion of this field. + + 1 forwardable The FORWARDABLE flag is normally only + interpreted by the TGS, and can be ignored + by end servers. When set, this flag tells + the ticket-granting server that it is OK to + issue a new TGT with a different network + address based on the presented ticket. + + 2 forwarded When set, this flag indicates that the + ticket has either been forwarded or was + issued based on authentication involving a + forwarded TGT. + + 3 proxiable The PROXIABLE flag is normally only + interpreted by the TGS, and can be ignored + by end servers. The PROXIABLE flag has an + interpretation identical to that of the + FORWARDABLE flag, except that the PROXIABLE + flag tells the ticket-granting server that + only non-TGTs may be issued with different + network addresses. + + 4 proxy When set, this flag indicates that a ticket + is a proxy. + + 5 may-postdate The MAY-POSTDATE flag is normally only + interpreted by the TGS, and can be ignored + by end servers. This flag tells the + + + + +Neuman, et al. Standards Track [Page 68] + +RFC 4120 Kerberos V5 July 2005 + + + ticket-granting server that a post-dated + ticket MAY be issued based on this TGT. + + 6 postdated This flag indicates that this ticket has + been postdated. The end-service can check + the authtime field to see when the original + authentication occurred. + + 7 invalid This flag indicates that a ticket is + invalid, and it must be validated by the KDC + before use. Application servers must reject + tickets which have this flag set. + + 8 renewable The RENEWABLE flag is normally only + interpreted by the TGS, and can usually be + ignored by end servers (some particularly + careful servers MAY disallow renewable + tickets). A renewable ticket can be used to + obtain a replacement ticket that expires at + a later date. + + 9 initial This flag indicates that this ticket was + issued using the AS protocol, and not issued + based on a TGT. + + 10 pre-authent This flag indicates that during initial + authentication, the client was authenticated + by the KDC before a ticket was issued. The + strength of the pre-authentication method is + not indicated, but is acceptable to the KDC. + + 11 hw-authent This flag indicates that the protocol + employed for initial authentication required + the use of hardware expected to be possessed + solely by the named client. The hardware + authentication method is selected by the KDC + and the strength of the method is not + indicated. + + 12 transited- This flag indicates that the KDC for + policy-checked the realm has checked the transited field + against a realm-defined policy for trusted + certifiers. If this flag is reset (0), then + the application server must check the + transited field itself, and if unable to do + so, it must reject the authentication. If + the flag is set (1), then the application + server MAY skip its own validation of the + + + +Neuman, et al. Standards Track [Page 69] + +RFC 4120 Kerberos V5 July 2005 + + + transited field, relying on the validation + performed by the KDC. At its option the + application server MAY still apply its own + validation based on a separate policy for + acceptance. + + This flag is new since RFC 1510. + + 13 ok-as-delegate This flag indicates that the server (not the + client) specified in the ticket has been + determined by policy of the realm to be a + suitable recipient of delegation. A client + can use the presence of this flag to help it + decide whether to delegate credentials + (either grant a proxy or a forwarded TGT) to + this server. The client is free to ignore + the value of this flag. When setting this + flag, an administrator should consider the + security and placement of the server on + which the service will run, as well as + whether the service requires the use of + delegated credentials. + + This flag is new since RFC 1510. + + 14-31 reserved Reserved for future use. + + key + This field exists in the ticket and the KDC response and is used + to pass the session key from Kerberos to the application server + and the client. + + crealm + This field contains the name of the realm in which the client is + registered and in which initial authentication took place. + + cname + This field contains the name part of the client's principal + identifier. + + transited + This field lists the names of the Kerberos realms that took part + in authenticating the user to whom this ticket was issued. It + does not specify the order in which the realms were transited. + See Section 3.3.3.2 for details on how this field encodes the + traversed realms. When the names of CAs are to be embedded in the + transited field (as specified for some extensions to the + + + + +Neuman, et al. Standards Track [Page 70] + +RFC 4120 Kerberos V5 July 2005 + + + protocol), the X.500 names of the CAs SHOULD be mapped into items + in the transited field using the mapping defined by RFC 2253. + + authtime + This field indicates the time of initial authentication for the + named principal. It is the time of issue for the original ticket + on which this ticket is based. It is included in the ticket to + provide additional information to the end service, and to provide + the necessary information for implementation of a "hot list" + service at the KDC. An end service that is particularly paranoid + could refuse to accept tickets for which the initial + authentication occurred "too far" in the past. This field is also + returned as part of the response from the KDC. When it is + returned as part of the response to initial authentication + (KRB_AS_REP), this is the current time on the Kerberos server. It + is NOT recommended that this time value be used to adjust the + workstation's clock, as the workstation cannot reliably determine + that such a KRB_AS_REP actually came from the proper KDC in a + timely manner. + + starttime + This field in the ticket specifies the time after which the ticket + is valid. Together with endtime, this field specifies the life of + the ticket. If the starttime field is absent from the ticket, + then the authtime field SHOULD be used in its place to determine + the life of the ticket. + + endtime + This field contains the time after which the ticket will not be + honored (its expiration time). Note that individual services MAY + place their own limits on the life of a ticket and MAY reject + tickets which have not yet expired. As such, this is really an + upper bound on the expiration time for the ticket. + + renew-till + This field is only present in tickets that have the RENEWABLE flag + set in the flags field. It indicates the maximum endtime that may + be included in a renewal. It can be thought of as the absolute + expiration time for the ticket, including all renewals. + + caddr + This field in a ticket contains zero (if omitted) or more (if + present) host addresses. These are the addresses from which the + ticket can be used. If there are no addresses, the ticket can be + used from any location. The decision by the KDC to issue or by + the end server to accept addressless tickets is a policy decision + and is left to the Kerberos and end-service administrators; they + MAY refuse to issue or accept such tickets. Because of the wide + + + +Neuman, et al. Standards Track [Page 71] + +RFC 4120 Kerberos V5 July 2005 + + + deployment of network address translation, it is recommended that + policy allow the issue and acceptance of such tickets. + + Network addresses are included in the ticket to make it harder for + an attacker to use stolen credentials. Because the session key is + not sent over the network in cleartext, credentials can't be + stolen simply by listening to the network; an attacker has to gain + access to the session key (perhaps through operating system + security breaches or a careless user's unattended session) to make + use of stolen tickets. + + Note that the network address from which a connection is received + cannot be reliably determined. Even if it could be, an attacker + who has compromised the client's workstation could use the + credentials from there. Including the network addresses only + makes it more difficult, not impossible, for an attacker to walk + off with stolen credentials and then to use them from a "safe" + location. + + authorization-data + The authorization-data field is used to pass authorization data + from the principal on whose behalf a ticket was issued to the + application service. If no authorization data is included, this + field will be left out. Experience has shown that the name of + this field is confusing, and that a better name would be + "restrictions". Unfortunately, it is not possible to change the + name at this time. + + This field contains restrictions on any authority obtained on the + basis of authentication using the ticket. It is possible for any + principal in possession of credentials to add entries to the + authorization data field since these entries further restrict what + can be done with the ticket. Such additions can be made by + specifying the additional entries when a new ticket is obtained + during the TGS exchange, or they MAY be added during chained + delegation using the authorization data field of the + authenticator. + + Because entries may be added to this field by the holder of + credentials, except when an entry is separately authenticated by + encapsulation in the KDC-issued element, it is not allowable for + the presence of an entry in the authorization data field of a + ticket to amplify the privileges one would obtain from using a + ticket. + + The data in this field may be specific to the end service; the + field will contain the names of service specific objects, and the + rights to those objects. The format for this field is described + + + +Neuman, et al. Standards Track [Page 72] + +RFC 4120 Kerberos V5 July 2005 + + + in Section 5.2.6. Although Kerberos is not concerned with the + format of the contents of the subfields, it does carry type + information (ad-type). + + By using the authorization_data field, a principal is able to + issue a proxy that is valid for a specific purpose. For example, + a client wishing to print a file can obtain a file server proxy to + be passed to the print server. By specifying the name of the file + in the authorization_data field, the file server knows that the + print server can only use the client's rights when accessing the + particular file to be printed. + + A separate service providing authorization or certifying group + membership may be built using the authorization-data field. In + this case, the entity granting authorization (not the authorized + entity) may obtain a ticket in its own name (e.g., the ticket is + issued in the name of a privilege server), and this entity adds + restrictions on its own authority and delegates the restricted + authority through a proxy to the client. The client would then + present this authorization credential to the application server + separately from the authentication exchange. Alternatively, such + authorization credentials MAY be embedded in the ticket + authenticating the authorized entity, when the authorization is + separately authenticated using the KDC-issued authorization data + element (see 5.2.6.2). + + Similarly, if one specifies the authorization-data field of a + proxy and leaves the host addresses blank, the resulting ticket + and session key can be treated as a capability. See [Neu93] for + some suggested uses of this field. + + The authorization-data field is optional and does not have to be + included in a ticket. + +5.4. Specifications for the AS and TGS Exchanges + + This section specifies the format of the messages used in the + exchange between the client and the Kerberos server. The format of + possible error messages appears in Section 5.9.1. + +5.4.1. KRB_KDC_REQ Definition + + The KRB_KDC_REQ message has no application tag number of its own. + Instead, it is incorporated into either KRB_AS_REQ or KRB_TGS_REQ, + each of which has an application tag, depending on whether the + request is for an initial ticket or an additional ticket. In either + case, the message is sent from the client to the KDC to request + credentials for a service. + + + +Neuman, et al. Standards Track [Page 73] + +RFC 4120 Kerberos V5 July 2005 + + + The message fields are as follows: + +AS-REQ ::= [APPLICATION 10] KDC-REQ + +TGS-REQ ::= [APPLICATION 12] KDC-REQ + +KDC-REQ ::= SEQUENCE { + -- NOTE: first tag is [1], not [0] + pvno [1] INTEGER (5) , + msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), + padata [3] SEQUENCE OF PA-DATA OPTIONAL + -- NOTE: not empty --, + req-body [4] KDC-REQ-BODY +} + +KDC-REQ-BODY ::= SEQUENCE { + kdc-options [0] KDCOptions, + cname [1] PrincipalName OPTIONAL + -- Used only in AS-REQ --, + realm [2] Realm + -- Server's realm + -- Also client's in AS-REQ --, + sname [3] PrincipalName OPTIONAL, + from [4] KerberosTime OPTIONAL, + till [5] KerberosTime, + rtime [6] KerberosTime OPTIONAL, + nonce [7] UInt32, + etype [8] SEQUENCE OF Int32 -- EncryptionType + -- in preference order --, + addresses [9] HostAddresses OPTIONAL, + enc-authorization-data [10] EncryptedData OPTIONAL + -- AuthorizationData --, + additional-tickets [11] SEQUENCE OF Ticket OPTIONAL + -- NOTE: not empty +} + +KDCOptions ::= KerberosFlags + -- reserved(0), + -- forwardable(1), + -- forwarded(2), + -- proxiable(3), + -- proxy(4), + -- allow-postdate(5), + -- postdated(6), + -- unused7(7), + -- renewable(8), + -- unused9(9), + -- unused10(10), + + + +Neuman, et al. Standards Track [Page 74] + +RFC 4120 Kerberos V5 July 2005 + + + -- opt-hardware-auth(11), + -- unused12(12), + -- unused13(13), +-- 15 is reserved for canonicalize + -- unused15(15), +-- 26 was unused in 1510 + -- disable-transited-check(26), +-- + -- renewable-ok(27), + -- enc-tkt-in-skey(28), + -- renew(30), + -- validate(31) + + The fields in this message are as follows: + + pvno + This field is included in each message, and specifies the protocol + version number. This document specifies protocol version 5. + + msg-type + This field indicates the type of a protocol message. It will + almost always be the same as the application identifier associated + with a message. It is included to make the identifier more + readily accessible to the application. For the KDC-REQ message, + this type will be KRB_AS_REQ or KRB_TGS_REQ. + + padata + Contains pre-authentication data. Requests for additional tickets + (KRB_TGS_REQ) MUST contain a padata of PA-TGS-REQ. + + The padata (pre-authentication data) field contains a sequence of + authentication information that may be needed before credentials + can be issued or decrypted. + + req-body + This field is a placeholder delimiting the extent of the remaining + fields. If a checksum is to be calculated over the request, it is + calculated over an encoding of the KDC-REQ-BODY sequence which is + enclosed within the req-body field. + + kdc-options + This field appears in the KRB_AS_REQ and KRB_TGS_REQ requests to + the KDC and indicates the flags that the client wants set on the + tickets as well as other information that is to modify the + behavior of the KDC. Where appropriate, the name of an option may + be the same as the flag that is set by that option. Although in + most cases, the bit in the options field will be the same as that + in the flags field, this is not guaranteed, so it is not + + + +Neuman, et al. Standards Track [Page 75] + +RFC 4120 Kerberos V5 July 2005 + + + acceptable simply to copy the options field to the flags field. + There are various checks that must be made before an option is + honored anyway. + + The kdc_options field is a bit-field, where the selected options + are indicated by the bit being set (1), and the unselected options + and reserved fields being reset (0). The encoding of the bits is + specified in Section 5.2. The options are described in more + detail above in Section 2. The meanings of the options are as + follows: + + Bits Name Description + + 0 RESERVED Reserved for future expansion of + this field. + + 1 FORWARDABLE The FORWARDABLE option indicates + that the ticket to be issued is to + have its forwardable flag set. It + may only be set on the initial + request, or in a subsequent request + if the TGT on which it is based is + also forwardable. + + 2 FORWARDED The FORWARDED option is only + specified in a request to the + ticket-granting server and will only + be honored if the TGT in the request + has its FORWARDABLE bit set. This + option indicates that this is a + request for forwarding. The + address(es) of the host from which + the resulting ticket is to be valid + are included in the addresses field + of the request. + + 3 PROXIABLE The PROXIABLE option indicates that + the ticket to be issued is to have + its proxiable flag set. It may only + be set on the initial request, or a + subsequent request if the TGT on + which it is based is also proxiable. + + 4 PROXY The PROXY option indicates that this + is a request for a proxy. This + option will only be honored if the + TGT in the request has its PROXIABLE + bit set. The address(es) of the + + + +Neuman, et al. Standards Track [Page 76] + +RFC 4120 Kerberos V5 July 2005 + + + host from which the resulting ticket + is to be valid are included in the + addresses field of the request. + + 5 ALLOW-POSTDATE The ALLOW-POSTDATE option indicates + that the ticket to be issued is to + have its MAY-POSTDATE flag set. It + may only be set on the initial + request, or in a subsequent request + if the TGT on which it is based also + has its MAY-POSTDATE flag set. + + 6 POSTDATED The POSTDATED option indicates that + this is a request for a postdated + ticket. This option will only be + honored if the TGT on which it is + based has its MAY-POSTDATE flag set. + The resulting ticket will also have + its INVALID flag set, and that flag + may be reset by a subsequent request + to the KDC after the starttime in + the ticket has been reached. + + 7 RESERVED This option is presently unused. + + 8 RENEWABLE The RENEWABLE option indicates that + the ticket to be issued is to have + its RENEWABLE flag set. It may only + be set on the initial request, or + when the TGT on which the request is + based is also renewable. If this + option is requested, then the rtime + field in the request contains the + desired absolute expiration time for + the ticket. + + 9 RESERVED Reserved for PK-Cross. + + 10 RESERVED Reserved for future use. + + 11 RESERVED Reserved for opt-hardware-auth. + + 12-25 RESERVED Reserved for future use. + + 26 DISABLE-TRANSITED-CHECK By default the KDC will check the + transited field of a TGT against the + policy of the local realm before it + will issue derivative tickets based + + + +Neuman, et al. Standards Track [Page 77] + +RFC 4120 Kerberos V5 July 2005 + + + on the TGT. If this flag is set in + the request, checking of the + transited field is disabled. + Tickets issued without the + performance of this check will be + noted by the reset (0) value of the + TRANSITED-POLICY-CHECKED flag, + indicating to the application server + that the transited field must be + checked locally. KDCs are + encouraged but not required to honor + the DISABLE-TRANSITED-CHECK option. + + This flag is new since RFC 1510. + + 27 RENEWABLE-OK The RENEWABLE-OK option indicates + that a renewable ticket will be + acceptable if a ticket with the + requested life cannot otherwise be + provided, in which case a renewable + ticket may be issued with a renew- + till equal to the requested endtime. + The value of the renew-till field + may still be limited by local + limits, or limits selected by the + individual principal or server. + + 28 ENC-TKT-IN-SKEY This option is used only by the + ticket-granting service. The ENC- + TKT-IN-SKEY option indicates that + the ticket for the end server is to + be encrypted in the session key from + the additional TGT provided. + + 29 RESERVED Reserved for future use. + + 30 RENEW This option is used only by the + ticket-granting service. The RENEW + option indicates that the present + request is for a renewal. The + ticket provided is encrypted in the + secret key for the server on which + it is valid. This option will only + be honored if the ticket to be + renewed has its RENEWABLE flag set + and if the time in its renew-till + field has not passed. The ticket to + be renewed is passed in the padata + + + +Neuman, et al. Standards Track [Page 78] + +RFC 4120 Kerberos V5 July 2005 + + + field as part of the authentication + header. + + 31 VALIDATE This option is used only by the + ticket-granting service. The + VALIDATE option indicates that the + request is to validate a postdated + ticket. It will only be honored if + the ticket presented is postdated, + presently has its INVALID flag set, + and would otherwise be usable at + this time. A ticket cannot be + validated before its starttime. The + ticket presented for validation is + encrypted in the key of the server + for which it is valid and is passed + in the padata field as part of the + authentication header. + + cname and sname + These fields are the same as those described for the ticket in + section 5.3. The sname may only be absent when the ENC-TKT-IN- + SKEY option is specified. If the sname is absent, the name of the + server is taken from the name of the client in the ticket passed + as additional-tickets. + + enc-authorization-data + The enc-authorization-data, if present (and it can only be present + in the TGS_REQ form), is an encoding of the desired + authorization-data encrypted under the sub-session key if present + in the Authenticator, or alternatively from the session key in the + TGT (both the Authenticator and TGT come from the padata field in + the KRB_TGS_REQ). The key usage value used when encrypting is 5 + if a sub-session key is used, or 4 if the session key is used. + + realm + This field specifies the realm part of the server's principal + identifier. In the AS exchange, this is also the realm part of + the client's principal identifier. + + from + This field is included in the KRB_AS_REQ and KRB_TGS_REQ ticket + requests when the requested ticket is to be postdated. It + specifies the desired starttime for the requested ticket. If this + field is omitted, then the KDC SHOULD use the current time + instead. + + + + + +Neuman, et al. Standards Track [Page 79] + +RFC 4120 Kerberos V5 July 2005 + + + till + This field contains the expiration date requested by the client in + a ticket request. It is not optional, but if the requested + endtime is "19700101000000Z", the requested ticket is to have the + maximum endtime permitted according to KDC policy. Implementation + note: This special timestamp corresponds to a UNIX time_t value of + zero on most systems. + + rtime + This field is the requested renew-till time sent from a client to + the KDC in a ticket request. It is optional. + + nonce + This field is part of the KDC request and response. It is + intended to hold a random number generated by the client. If the + same number is included in the encrypted response from the KDC, it + provides evidence that the response is fresh and has not been + replayed by an attacker. Nonces MUST NEVER be reused. + + etype + This field specifies the desired encryption algorithm to be used + in the response. + + addresses + This field is included in the initial request for tickets, and it + is optionally included in requests for additional tickets from the + ticket-granting server. It specifies the addresses from which the + requested ticket is to be valid. Normally it includes the + addresses for the client's host. If a proxy is requested, this + field will contain other addresses. The contents of this field + are usually copied by the KDC into the caddr field of the + resulting ticket. + + additional-tickets + Additional tickets MAY be optionally included in a request to the + ticket-granting server. If the ENC-TKT-IN-SKEY option has been + specified, then the session key from the additional ticket will be + used in place of the server's key to encrypt the new ticket. When + the ENC-TKT-IN-SKEY option is used for user-to-user + authentication, this additional ticket MAY be a TGT issued by the + local realm or an inter-realm TGT issued for the current KDC's + realm by a remote KDC. If more than one option that requires + additional tickets has been specified, then the additional tickets + are used in the order specified by the ordering of the options + bits (see kdc-options, above). + + + + + + +Neuman, et al. Standards Track [Page 80] + +RFC 4120 Kerberos V5 July 2005 + + + The application tag number will be either ten (10) or twelve (12) + depending on whether the request is for an initial ticket (AS-REQ) or + for an additional ticket (TGS-REQ). + + The optional fields (addresses, authorization-data, and additional- + tickets) are only included if necessary to perform the operation + specified in the kdc-options field. + + Note that in KRB_TGS_REQ, the protocol version number appears twice + and two different message types appear: the KRB_TGS_REQ message + contains these fields as does the authentication header (KRB_AP_REQ) + that is passed in the padata field. + +5.4.2. KRB_KDC_REP Definition + + The KRB_KDC_REP message format is used for the reply from the KDC for + either an initial (AS) request or a subsequent (TGS) request. There + is no message type for KRB_KDC_REP. Instead, the type will be either + KRB_AS_REP or KRB_TGS_REP. The key used to encrypt the ciphertext + part of the reply depends on the message type. For KRB_AS_REP, the + ciphertext is encrypted in the client's secret key, and the client's + key version number is included in the key version number for the + encrypted data. For KRB_TGS_REP, the ciphertext is encrypted in the + sub-session key from the Authenticator; if it is absent, the + ciphertext is encrypted in the session key from the TGT used in the + request. In that case, no version number will be present in the + EncryptedData sequence. + + The KRB_KDC_REP message contains the following fields: + + AS-REP ::= [APPLICATION 11] KDC-REP + + TGS-REP ::= [APPLICATION 13] KDC-REP + + KDC-REP ::= SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --), + padata [2] SEQUENCE OF PA-DATA OPTIONAL + -- NOTE: not empty --, + crealm [3] Realm, + cname [4] PrincipalName, + ticket [5] Ticket, + enc-part [6] EncryptedData + -- EncASRepPart or EncTGSRepPart, + -- as appropriate + } + + EncASRepPart ::= [APPLICATION 25] EncKDCRepPart + + + +Neuman, et al. Standards Track [Page 81] + +RFC 4120 Kerberos V5 July 2005 + + + EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart + + EncKDCRepPart ::= SEQUENCE { + key [0] EncryptionKey, + last-req [1] LastReq, + nonce [2] UInt32, + key-expiration [3] KerberosTime OPTIONAL, + flags [4] TicketFlags, + authtime [5] KerberosTime, + starttime [6] KerberosTime OPTIONAL, + endtime [7] KerberosTime, + renew-till [8] KerberosTime OPTIONAL, + srealm [9] Realm, + sname [10] PrincipalName, + caddr [11] HostAddresses OPTIONAL + } + + LastReq ::= SEQUENCE OF SEQUENCE { + lr-type [0] Int32, + lr-value [1] KerberosTime + } + + pvno and msg-type + These fields are described above in Section 5.4.1. msg-type is + either KRB_AS_REP or KRB_TGS_REP. + + padata + This field is described in detail in Section 5.4.1. One possible + use for it is to encode an alternate "salt" string to be used with + a string-to-key algorithm. This ability is useful for easing + transitions if a realm name needs to change (e.g., when a company + is acquired); in such a case all existing password-derived entries + in the KDC database would be flagged as needing a special salt + string until the next password change. + + crealm, cname, srealm, and sname + These fields are the same as those described for the ticket in + section 5.3. + + ticket + The newly-issued ticket, from Section 5.3. + + enc-part + This field is a place holder for the ciphertext and related + information that forms the encrypted part of a message. The + description of the encrypted part of the message follows each + appearance of this field. + + + + +Neuman, et al. Standards Track [Page 82] + +RFC 4120 Kerberos V5 July 2005 + + + The key usage value for encrypting this field is 3 in an AS-REP + message, using the client's long-term key or another key selected + via pre-authentication mechanisms. In a TGS-REP message, the key + usage value is 8 if the TGS session key is used, or 9 if a TGS + authenticator subkey is used. + + Compatibility note: Some implementations unconditionally send an + encrypted EncTGSRepPart (application tag number 26) in this field + regardless of whether the reply is a AS-REP or a TGS-REP. In the + interest of compatibility, implementors MAY relax the check on the + tag number of the decrypted ENC-PART. + + key + This field is the same as described for the ticket in Section 5.3. + + last-req + This field is returned by the KDC and specifies the time(s) of the + last request by a principal. Depending on what information is + available, this might be the last time that a request for a TGT + was made, or the last time that a request based on a TGT was + successful. It also might cover all servers for a realm, or just + the particular server. Some implementations MAY display this + information to the user to aid in discovering unauthorized use of + one's identity. It is similar in spirit to the last login time + displayed when logging in to timesharing systems. + + lr-type + This field indicates how the following lr-value field is to be + interpreted. Negative values indicate that the information + pertains only to the responding server. Non-negative values + pertain to all servers for the realm. + + If the lr-type field is zero (0), then no information is conveyed + by the lr-value subfield. If the absolute value of the lr-type + field is one (1), then the lr-value subfield is the time of last + initial request for a TGT. If it is two (2), then the lr-value + subfield is the time of last initial request. If it is three (3), + then the lr-value subfield is the time of issue for the newest TGT + used. If it is four (4), then the lr-value subfield is the time + of the last renewal. If it is five (5), then the lr-value + subfield is the time of last request (of any type). If it is (6), + then the lr-value subfield is the time when the password will + expire. If it is (7), then the lr-value subfield is the time when + the account will expire. + + + + + + + +Neuman, et al. Standards Track [Page 83] + +RFC 4120 Kerberos V5 July 2005 + + + lr-value + This field contains the time of the last request. The time MUST + be interpreted according to the contents of the accompanying lr- + type subfield. + + nonce + This field is described above in Section 5.4.1. + + key-expiration + The key-expiration field is part of the response from the KDC and + specifies the time that the client's secret key is due to expire. + The expiration might be the result of password aging or an account + expiration. If present, it SHOULD be set to the earlier of the + user's key expiration and account expiration. The use of this + field is deprecated, and the last-req field SHOULD be used to + convey this information instead. This field will usually be left + out of the TGS reply since the response to the TGS request is + encrypted in a session key and no client information has to be + retrieved from the KDC database. It is up to the application + client (usually the login program) to take appropriate action + (such as notifying the user) if the expiration time is imminent. + + flags, authtime, starttime, endtime, renew-till and caddr + These fields are duplicates of those found in the encrypted + portion of the attached ticket (see Section 5.3), provided so the + client MAY verify that they match the intended request and in + order to assist in proper ticket caching. If the message is of + type KRB_TGS_REP, the caddr field will only be filled in if the + request was for a proxy or forwarded ticket, or if the user is + substituting a subset of the addresses from the TGT. If the + client-requested addresses are not present or not used, then the + addresses contained in the ticket will be the same as those + included in the TGT. + +5.5. Client/Server (CS) Message Specifications + + This section specifies the format of the messages used for the + authentication of the client to the application server. + +5.5.1. KRB_AP_REQ Definition + + The KRB_AP_REQ message contains the Kerberos protocol version number, + the message type KRB_AP_REQ, an options field to indicate any options + in use, and the ticket and authenticator themselves. The KRB_AP_REQ + message is often referred to as the "authentication header". + + + + + + +Neuman, et al. Standards Track [Page 84] + +RFC 4120 Kerberos V5 July 2005 + + + AP-REQ ::= [APPLICATION 14] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (14), + ap-options [2] APOptions, + ticket [3] Ticket, + authenticator [4] EncryptedData -- Authenticator + } + + APOptions ::= KerberosFlags + -- reserved(0), + -- use-session-key(1), + -- mutual-required(2) + + pvno and msg-type + These fields are described above in Section 5.4.1. msg-type is + KRB_AP_REQ. + + ap-options + This field appears in the application request (KRB_AP_REQ) and + affects the way the request is processed. It is a bit-field, + where the selected options are indicated by the bit being set (1), + and the unselected options and reserved fields by being reset (0). + The encoding of the bits is specified in Section 5.2. The + meanings of the options are as follows: + + Bit(s) Name Description + + 0 reserved Reserved for future expansion of this field. + + 1 use-session-key The USE-SESSION-KEY option indicates that + the ticket the client is presenting to a + server is encrypted in the session key from + the server's TGT. When this option is not + specified, the ticket is encrypted in the + server's secret key. + + 2 mutual-required The MUTUAL-REQUIRED option tells the server + that the client requires mutual + authentication, and that it must respond + with a KRB_AP_REP message. + + 3-31 reserved Reserved for future use. + + ticket + This field is a ticket authenticating the client to the server. + + + + + + +Neuman, et al. Standards Track [Page 85] + +RFC 4120 Kerberos V5 July 2005 + + + authenticator + This contains the encrypted authenticator, which includes the + client's choice of a subkey. + + The encrypted authenticator is included in the AP-REQ; it certifies + to a server that the sender has recent knowledge of the encryption + key in the accompanying ticket, to help the server detect replays. + It also assists in the selection of a "true session key" to use with + the particular session. The DER encoding of the following is + encrypted in the ticket's session key, with a key usage value of 11 + in normal application exchanges, or 7 when used as the PA-TGS-REQ + PA-DATA field of a TGS-REQ exchange (see Section 5.4.1): + + -- Unencrypted authenticator + Authenticator ::= [APPLICATION 2] SEQUENCE { + authenticator-vno [0] INTEGER (5), + crealm [1] Realm, + cname [2] PrincipalName, + cksum [3] Checksum OPTIONAL, + cusec [4] Microseconds, + ctime [5] KerberosTime, + subkey [6] EncryptionKey OPTIONAL, + seq-number [7] UInt32 OPTIONAL, + authorization-data [8] AuthorizationData OPTIONAL + } + + authenticator-vno + This field specifies the version number for the format of the + authenticator. This document specifies version 5. + + crealm and cname + These fields are the same as those described for the ticket in + section 5.3. + + cksum + This field contains a checksum of the application data that + accompanies the KRB_AP_REQ, computed using a key usage value of 10 + in normal application exchanges, or 6 when used in the TGS-REQ + PA-TGS-REQ AP-DATA field. + + cusec + This field contains the microsecond part of the client's + timestamp. Its value (before encryption) ranges from 0 to 999999. + It often appears along with ctime. The two fields are used + together to specify a reasonably accurate timestamp. + + ctime + This field contains the current time on the client's host. + + + +Neuman, et al. Standards Track [Page 86] + +RFC 4120 Kerberos V5 July 2005 + + + subkey + This field contains the client's choice for an encryption key to + be used to protect this specific application session. Unless an + application specifies otherwise, if this field is left out, the + session key from the ticket will be used. + + seq-number + This optional field includes the initial sequence number to be + used by the KRB_PRIV or KRB_SAFE messages when sequence numbers + are used to detect replays. (It may also be used by application + specific messages.) When included in the authenticator, this + field specifies the initial sequence number for messages from the + client to the server. When included in the AP-REP message, the + initial sequence number is that for messages from the server to + the client. When used in KRB_PRIV or KRB_SAFE messages, it is + incremented by one after each message is sent. Sequence numbers + fall in the range 0 through 2^32 - 1 and wrap to zero following + the value 2^32 - 1. + + For sequence numbers to support the detection of replays + adequately, they SHOULD be non-repeating, even across connection + boundaries. The initial sequence number SHOULD be random and + uniformly distributed across the full space of possible sequence + numbers, so that it cannot be guessed by an attacker and so that + it and the successive sequence numbers do not repeat other + sequences. In the event that more than 2^32 messages are to be + generated in a series of KRB_PRIV or KRB_SAFE messages, rekeying + SHOULD be performed before sequence numbers are reused with the + same encryption key. + + Implmentation note: Historically, some implementations transmit + signed twos-complement numbers for sequence numbers. In the + interests of compatibility, implementations MAY accept the + equivalent negative number where a positive number greater than + 2^31 - 1 is expected. + + Implementation note: As noted before, some implementations omit + the optional sequence number when its value would be zero. + Implementations MAY accept an omitted sequence number when + expecting a value of zero, and SHOULD NOT transmit an + Authenticator with a initial sequence number of zero. + + authorization-data + This field is the same as described for the ticket in Section 5.3. + It is optional and will only appear when additional restrictions + are to be placed on the use of a ticket, beyond those carried in + the ticket itself. + + + + +Neuman, et al. Standards Track [Page 87] + +RFC 4120 Kerberos V5 July 2005 + + +5.5.2. KRB_AP_REP Definition + + The KRB_AP_REP message contains the Kerberos protocol version number, + the message type, and an encrypted time-stamp. The message is sent + in response to an application request (KRB_AP_REQ) for which the + mutual authentication option has been selected in the ap-options + field. + + AP-REP ::= [APPLICATION 15] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (15), + enc-part [2] EncryptedData -- EncAPRepPart + } + + EncAPRepPart ::= [APPLICATION 27] SEQUENCE { + ctime [0] KerberosTime, + cusec [1] Microseconds, + subkey [2] EncryptionKey OPTIONAL, + seq-number [3] UInt32 OPTIONAL + } + + The encoded EncAPRepPart is encrypted in the shared session key of + the ticket. The optional subkey field can be used in an + application-arranged negotiation to choose a per association session + key. + + pvno and msg-type + These fields are described above in Section 5.4.1. msg-type is + KRB_AP_REP. + + enc-part + This field is described above in Section 5.4.2. It is computed + with a key usage value of 12. + + ctime + This field contains the current time on the client's host. + + cusec + This field contains the microsecond part of the client's + timestamp. + + subkey + This field contains an encryption key that is to be used to + protect this specific application session. See Section 3.2.6 for + specifics on how this field is used to negotiate a key. Unless an + application specifies otherwise, if this field is left out, the + sub-session key from the authenticator or if the latter is also + left out, the session key from the ticket will be used. + + + +Neuman, et al. Standards Track [Page 88] + +RFC 4120 Kerberos V5 July 2005 + + + seq-number + This field is described above in Section 5.3.2. + +5.5.3. Error Message Reply + + If an error occurs while processing the application request, the + KRB_ERROR message will be sent in response. See Section 5.9.1 for + the format of the error message. The cname and crealm fields MAY be + left out if the server cannot determine their appropriate values from + the corresponding KRB_AP_REQ message. If the authenticator was + decipherable, the ctime and cusec fields will contain the values from + it. + +5.6. KRB_SAFE Message Specification + + This section specifies the format of a message that can be used by + either side (client or server) of an application to send a tamper- + proof message to its peer. It presumes that a session key has + previously been exchanged (for example, by using the + KRB_AP_REQ/KRB_AP_REP messages). + +5.6.1. KRB_SAFE definition + + The KRB_SAFE message contains user data along with a collision-proof + checksum keyed with the last encryption key negotiated via subkeys, + or with the session key if no negotiation has occurred. The message + fields are as follows: + + KRB-SAFE ::= [APPLICATION 20] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (20), + safe-body [2] KRB-SAFE-BODY, + cksum [3] Checksum + } + + KRB-SAFE-BODY ::= SEQUENCE { + user-data [0] OCTET STRING, + timestamp [1] KerberosTime OPTIONAL, + usec [2] Microseconds OPTIONAL, + seq-number [3] UInt32 OPTIONAL, + s-address [4] HostAddress, + r-address [5] HostAddress OPTIONAL + } + + pvno and msg-type + These fields are described above in Section 5.4.1. msg-type is + KRB_SAFE. + + + + +Neuman, et al. Standards Track [Page 89] + +RFC 4120 Kerberos V5 July 2005 + + + safe-body + This field is a placeholder for the body of the KRB-SAFE message. + + cksum + This field contains the checksum of the application data, computed + with a key usage value of 15. + + The checksum is computed over the encoding of the KRB-SAFE + sequence. First, the cksum is set to a type zero, zero-length + value, and the checksum is computed over the encoding of the KRB- + SAFE sequence. Then the checksum is set to the result of that + computation. Finally, the KRB-SAFE sequence is encoded again. + This method, although different than the one specified in RFC + 1510, corresponds to existing practice. + + user-data + This field is part of the KRB_SAFE and KRB_PRIV messages, and + contains the application-specific data that is being passed from + the sender to the recipient. + + timestamp + This field is part of the KRB_SAFE and KRB_PRIV messages. Its + contents are the current time as known by the sender of the + message. By checking the timestamp, the recipient of the message + is able to make sure that it was recently generated, and is not a + replay. + + usec + This field is part of the KRB_SAFE and KRB_PRIV headers. It + contains the microsecond part of the timestamp. + + seq-number + This field is described above in Section 5.3.2. + + s-address + Sender's address. + + This field specifies the address in use by the sender of the + message. + + r-address + This field specifies the address in use by the recipient of the + message. It MAY be omitted for some uses (such as broadcast + protocols), but the recipient MAY arbitrarily reject such + messages. This field, along with s-address, can be used to help + detect messages that have been incorrectly or maliciously + delivered to the wrong recipient. + + + + +Neuman, et al. Standards Track [Page 90] + +RFC 4120 Kerberos V5 July 2005 + + +5.7. KRB_PRIV Message Specification + + This section specifies the format of a message that can be used by + either side (client or server) of an application to send a message to + its peer securely and privately. It presumes that a session key has + previously been exchanged (for example, by using the + KRB_AP_REQ/KRB_AP_REP messages). + +5.7.1. KRB_PRIV Definition + + The KRB_PRIV message contains user data encrypted in the Session Key. + The message fields are as follows: + + KRB-PRIV ::= [APPLICATION 21] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (21), + -- NOTE: there is no [2] tag + enc-part [3] EncryptedData -- EncKrbPrivPart + } + + EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE { + user-data [0] OCTET STRING, + timestamp [1] KerberosTime OPTIONAL, + usec [2] Microseconds OPTIONAL, + seq-number [3] UInt32 OPTIONAL, + s-address [4] HostAddress -- sender's addr --, + r-address [5] HostAddress OPTIONAL -- recip's addr + } + + pvno and msg-type + These fields are described above in Section 5.4.1. msg-type is + KRB_PRIV. + + enc-part + This field holds an encoding of the EncKrbPrivPart sequence + encrypted under the session key, with a key usage value of 13. + This encrypted encoding is used for the enc-part field of the + KRB-PRIV message. + + user-data, timestamp, usec, s-address, and r-address + These fields are described above in Section 5.6.1. + + seq-number + This field is described above in Section 5.3.2. + + + + + + + +Neuman, et al. Standards Track [Page 91] + +RFC 4120 Kerberos V5 July 2005 + + +5.8. KRB_CRED Message Specification + + This section specifies the format of a message that can be used to + send Kerberos credentials from one principal to another. It is + presented here to encourage a common mechanism to be used by + applications when forwarding tickets or providing proxies to + subordinate servers. It presumes that a session key has already been + exchanged, perhaps by using the KRB_AP_REQ/KRB_AP_REP messages. + +5.8.1. KRB_CRED Definition + + The KRB_CRED message contains a sequence of tickets to be sent and + information needed to use the tickets, including the session key from + each. The information needed to use the tickets is encrypted under + an encryption key previously exchanged or transferred alongside the + KRB_CRED message. The message fields are as follows: + + KRB-CRED ::= [APPLICATION 22] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (22), + tickets [2] SEQUENCE OF Ticket, + enc-part [3] EncryptedData -- EncKrbCredPart + } + + EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { + ticket-info [0] SEQUENCE OF KrbCredInfo, + nonce [1] UInt32 OPTIONAL, + timestamp [2] KerberosTime OPTIONAL, + usec [3] Microseconds OPTIONAL, + s-address [4] HostAddress OPTIONAL, + r-address [5] HostAddress OPTIONAL + } + + KrbCredInfo ::= SEQUENCE { + key [0] EncryptionKey, + prealm [1] Realm OPTIONAL, + pname [2] PrincipalName OPTIONAL, + flags [3] TicketFlags OPTIONAL, + authtime [4] KerberosTime OPTIONAL, + starttime [5] KerberosTime OPTIONAL, + endtime [6] KerberosTime OPTIONAL, + renew-till [7] KerberosTime OPTIONAL, + srealm [8] Realm OPTIONAL, + sname [9] PrincipalName OPTIONAL, + caddr [10] HostAddresses OPTIONAL + } + + + + + +Neuman, et al. Standards Track [Page 92] + +RFC 4120 Kerberos V5 July 2005 + + + pvno and msg-type + These fields are described above in Section 5.4.1. msg-type is + KRB_CRED. + + tickets + These are the tickets obtained from the KDC specifically for use + by the intended recipient. Successive tickets are paired with the + corresponding KrbCredInfo sequence from the enc-part of the KRB- + CRED message. + + enc-part + This field holds an encoding of the EncKrbCredPart sequence + encrypted under the session key shared by the sender and the + intended recipient, with a key usage value of 14. This encrypted + encoding is used for the enc-part field of the KRB-CRED message. + + Implementation note: Implementations of certain applications, most + notably certain implementations of the Kerberos GSS-API mechanism, + do not separately encrypt the contents of the EncKrbCredPart of + the KRB-CRED message when sending it. In the case of those GSS- + API mechanisms, this is not a security vulnerability, as the + entire KRB-CRED message is itself embedded in an encrypted + message. + + nonce + If practical, an application MAY require the inclusion of a nonce + generated by the recipient of the message. If the same value is + included as the nonce in the message, it provides evidence that + the message is fresh and has not been replayed by an attacker. A + nonce MUST NEVER be reused. + + timestamp and usec + These fields specify the time that the KRB-CRED message was + generated. The time is used to provide assurance that the message + is fresh. + + s-address and r-address + These fields are described above in Section 5.6.1. They are used + optionally to provide additional assurance of the integrity of the + KRB-CRED message. + + key + This field exists in the corresponding ticket passed by the KRB- + CRED message and is used to pass the session key from the sender + to the intended recipient. The field's encoding is described in + Section 5.2.9. + + + + + +Neuman, et al. Standards Track [Page 93] + +RFC 4120 Kerberos V5 July 2005 + + + The following fields are optional. If present, they can be + associated with the credentials in the remote ticket file. If left + out, then it is assumed that the recipient of the credentials already + knows their values. + + prealm and pname + The name and realm of the delegated principal identity. + + flags, authtime, starttime, endtime, renew-till, srealm, sname, + and caddr + These fields contain the values of the corresponding fields from + the ticket found in the ticket field. Descriptions of the fields + are identical to the descriptions in the KDC-REP message. + +5.9. Error Message Specification + + This section specifies the format for the KRB_ERROR message. The + fields included in the message are intended to return as much + information as possible about an error. It is not expected that all + the information required by the fields will be available for all + types of errors. If the appropriate information is not available + when the message is composed, the corresponding field will be left + out of the message. + + Note that because the KRB_ERROR message is not integrity protected, + it is quite possible for an intruder to synthesize or modify it. In + particular, this means that the client SHOULD NOT use any fields in + this message for security-critical purposes, such as setting a system + clock or generating a fresh authenticator. The message can be + useful, however, for advising a user on the reason for some failure. + +5.9.1. KRB_ERROR Definition + + The KRB_ERROR message consists of the following fields: + + KRB-ERROR ::= [APPLICATION 30] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (30), + ctime [2] KerberosTime OPTIONAL, + cusec [3] Microseconds OPTIONAL, + stime [4] KerberosTime, + susec [5] Microseconds, + error-code [6] Int32, + crealm [7] Realm OPTIONAL, + cname [8] PrincipalName OPTIONAL, + realm [9] Realm -- service realm --, + sname [10] PrincipalName -- service name --, + e-text [11] KerberosString OPTIONAL, + + + +Neuman, et al. Standards Track [Page 94] + +RFC 4120 Kerberos V5 July 2005 + + + e-data [12] OCTET STRING OPTIONAL + } + + pvno and msg-type + These fields are described above in Section 5.4.1. msg-type is + KRB_ERROR. + + ctime and cusec + These fields are described above in Section 5.5.2. If the values + for these fields are known to the entity generating the error (as + they would be if the KRB-ERROR is generated in reply to, e.g., a + failed authentication service request), they should be populated + in the KRB-ERROR. If the values are not available, these fields + can be omitted. + + stime + This field contains the current time on the server. It is of type + KerberosTime. + + susec + This field contains the microsecond part of the server's + timestamp. Its value ranges from 0 to 999999. It appears along + with stime. The two fields are used in conjunction to specify a + reasonably accurate timestamp. + + error-code + This field contains the error code returned by Kerberos or the + server when a request fails. To interpret the value of this field + see the list of error codes in Section 7.5.9. Implementations are + encouraged to provide for national language support in the display + of error messages. + + crealm, and cname + These fields are described above in Section 5.3. When the entity + generating the error knows these values, they should be populated + in the KRB-ERROR. If the values are not known, the crealm and + cname fields SHOULD be omitted. + + realm and sname + These fields are described above in Section 5.3. + + e-text + This field contains additional text to help explain the error code + associated with the failed request (for example, it might include + a principal name which was unknown). + + + + + + +Neuman, et al. Standards Track [Page 95] + +RFC 4120 Kerberos V5 July 2005 + + + e-data + This field contains additional data about the error for use by the + application to help it recover from or handle the error. If the + errorcode is KDC_ERR_PREAUTH_REQUIRED, then the e-data field will + contain an encoding of a sequence of padata fields, each + corresponding to an acceptable pre-authentication method and + optionally containing data for the method: + + METHOD-DATA ::= SEQUENCE OF PA-DATA + + For error codes defined in this document other than + KDC_ERR_PREAUTH_REQUIRED, the format and contents of the e-data field + are implementation-defined. Similarly, for future error codes, the + format and contents of the e-data field are implementation-defined + unless specified otherwise. Whether defined by the implementation or + in a future document, the e-data field MAY take the form of TYPED- + DATA: + + TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + data-type [0] Int32, + data-value [1] OCTET STRING OPTIONAL + } + +5.10. Application Tag Numbers + + The following table lists the application class tag numbers used by + various data types defined in this section. + + Tag Number(s) Type Name Comments + + 0 unused + + 1 Ticket PDU + + 2 Authenticator non-PDU + + 3 EncTicketPart non-PDU + + 4-9 unused + + 10 AS-REQ PDU + + 11 AS-REP PDU + + 12 TGS-REQ PDU + + 13 TGS-REP PDU + + + + +Neuman, et al. Standards Track [Page 96] + +RFC 4120 Kerberos V5 July 2005 + + + 14 AP-REQ PDU + + 15 AP-REP PDU + + 16 RESERVED16 TGT-REQ (for user-to-user) + + 17 RESERVED17 TGT-REP (for user-to-user) + + 18-19 unused + + 20 KRB-SAFE PDU + + 21 KRB-PRIV PDU + + 22 KRB-CRED PDU + + 23-24 unused + + 25 EncASRepPart non-PDU + + 26 EncTGSRepPart non-PDU + + 27 EncApRepPart non-PDU + + 28 EncKrbPrivPart non-PDU + + 29 EncKrbCredPart non-PDU + + 30 KRB-ERROR PDU + + The ASN.1 types marked above as "PDU" (Protocol Data Unit) are the + only ASN.1 types intended as top-level types of the Kerberos + protocol, and are the only types that may be used as elements in + another protocol that makes use of Kerberos. + +6. Naming Constraints + +6.1. Realm Names + + Although realm names are encoded as GeneralStrings and technically a + realm can select any name it chooses, interoperability across realm + boundaries requires agreement on how realm names are to be assigned, + and what information they imply. + + To enforce these conventions, each realm MUST conform to the + conventions itself, and it MUST require that any realms with which + inter-realm keys are shared also conform to the conventions and + require the same from its neighbors. + + + +Neuman, et al. Standards Track [Page 97] + +RFC 4120 Kerberos V5 July 2005 + + + Kerberos realm names are case sensitive. Realm names that differ + only in the case of the characters are not equivalent. There are + presently three styles of realm names: domain, X500, and other. + Examples of each style follow: + + domain: ATHENA.MIT.EDU + X500: C=US/O=OSF + other: NAMETYPE:rest/of.name=without-restrictions + + Domain style realm names MUST look like domain names: they consist of + components separated by periods (.) and they contain neither colons + (:) nor slashes (/). Though domain names themselves are case + insensitive, in order for realms to match, the case must match as + well. When establishing a new realm name based on an internet domain + name it is recommended by convention that the characters be converted + to uppercase. + + X.500 names contain an equals sign (=) and cannot contain a colon (:) + before the equals sign. The realm names for X.500 names will be + string representations of the names with components separated by + slashes. Leading and trailing slashes will not be included. Note + that the slash separator is consistent with Kerberos implementations + based on RFC 1510, but it is different from the separator recommended + in RFC 2253. + + Names that fall into the other category MUST begin with a prefix that + contains no equals sign (=) or period (.), and the prefix MUST be + followed by a colon (:) and the rest of the name. All prefixes + expect those beginning with used. Presently none are assigned. + + The reserved category includes strings that do not fall into the + first three categories. All names in this category are reserved. It + is unlikely that names will be assigned to this category unless there + is a very strong argument for not using the 'other' category. + + These rules guarantee that there will be no conflicts between the + various name styles. The following additional constraints apply to + the assignment of realm names in the domain and X.500 categories: + either the name of a realm for the domain or X.500 formats must be + used by the organization owning (to whom it was assigned) an Internet + domain name or X.500 name, or, in the case that no such names are + registered, authority to use a realm name MAY be derived from the + authority of the parent realm. For example, if there is no domain + name for E40.MIT.EDU, then the administrator of the MIT.EDU realm can + authorize the creation of a realm with that name. + + This is acceptable because the organization to which the parent is + assigned is presumably the organization authorized to assign names to + + + +Neuman, et al. Standards Track [Page 98] + +RFC 4120 Kerberos V5 July 2005 + + + its children in the X.500 and domain name systems as well. If the + parent assigns a realm name without also registering it in the domain + name or X.500 hierarchy, it is the parent's responsibility to make + sure that in the future there will not exist a name identical to the + realm name of the child unless it is assigned to the same entity as + the realm name. + +6.2. Principal Names + + As was the case for realm names, conventions are needed to ensure + that all agree on what information is implied by a principal name. + The name-type field that is part of the principal name indicates the + kind of information implied by the name. The name-type SHOULD be + treated only as a hint to interpreting the meaning of a name. It is + not significant when checking for equivalence. Principal names that + differ only in the name-type identify the same principal. The name + type does not partition the name space. Ignoring the name type, no + two names can be the same (i.e., at least one of the components, or + the realm, MUST be different). The following name types are defined: + + Name Type Value Meaning + + NT-UNKNOWN 0 Name type not known + NT-PRINCIPAL 1 Just the name of the principal as in DCE, + or for users + NT-SRV-INST 2 Service and other unique instance (krbtgt) + NT-SRV-HST 3 Service with host name as instance + (telnet, rcommands) + NT-SRV-XHST 4 Service with host as remaining components + NT-UID 5 Unique ID + NT-X500-PRINCIPAL 6 Encoded X.509 Distinguished name [RFC2253] + NT-SMTP-NAME 7 Name in form of SMTP email name + (e.g., user@example.com) + NT-ENTERPRISE 10 Enterprise name - may be mapped to principal + name + + When a name implies no information other than its uniqueness at a + particular time, the name type PRINCIPAL SHOULD be used. The + principal name type SHOULD be used for users, and it might also be + used for a unique server. If the name is a unique machine-generated + ID that is guaranteed never to be reassigned, then the name type of + UID SHOULD be used. (Note that it is generally a bad idea to + reassign names of any type since stale entries might remain in access + control lists.) + + If the first component of a name identifies a service and the + remaining components identify an instance of the service in a + server-specified manner, then the name type of SRV-INST SHOULD be + + + +Neuman, et al. Standards Track [Page 99] + +RFC 4120 Kerberos V5 July 2005 + + + used. An example of this name type is the Kerberos ticket-granting + service whose name has a first component of krbtgt and a second + component identifying the realm for which the ticket is valid. + + If the first component of a name identifies a service and there is a + single component following the service name identifying the instance + as the host on which the server is running, then the name type + SRV-HST SHOULD be used. This type is typically used for Internet + services such as telnet and the Berkeley R commands. If the separate + components of the host name appear as successive components following + the name of the service, then the name type SRV-XHST SHOULD be used. + This type might be used to identify servers on hosts with X.500 + names, where the slash (/) might otherwise be ambiguous. + + A name type of NT-X500-PRINCIPAL SHOULD be used when a name from an + X.509 certificate is translated into a Kerberos name. The encoding + of the X.509 name as a Kerberos principal shall conform to the + encoding rules specified in RFC 2253. + + A name type of SMTP allows a name to be of a form that resembles an + SMTP email name. This name, including an "@" and a domain name, is + used as the one component of the principal name. + + A name type of UNKNOWN SHOULD be used when the form of the name is + not known. When comparing names, a name of type UNKNOWN will match + principals authenticated with names of any type. A principal + authenticated with a name of type UNKNOWN, however, will only match + other names of type UNKNOWN. + + Names of any type with an initial component of 'krbtgt' are reserved + for the Kerberos ticket-granting service. See Section 7.3 for the + form of such names. + +6.2.1. Name of Server Principals + + The principal identifier for a server on a host will generally be + composed of two parts: (1) the realm of the KDC with which the server + is registered, and (2) a two-component name of type NT-SRV-HST, if + the host name is an Internet domain name, or a multi-component name + of type NT-SRV-XHST, if the name of the host is of a form (such as + X.500) that allows slash (/) separators. The first component of the + two- or multi-component name will identify the service, and the + latter components will identify the host. Where the name of the host + is not case sensitive (for example, with Internet domain names) the + name of the host MUST be lowercase. If specified by the application + protocol for services such as telnet and the Berkeley R commands that + run with system privileges, the first component MAY be the string + 'host' instead of a service-specific identifier. + + + +Neuman, et al. Standards Track [Page 100] + +RFC 4120 Kerberos V5 July 2005 + + +7. Constants and Other Defined Values + +7.1. Host Address Types + + All negative values for the host address type are reserved for local + use. All non-negative values are reserved for officially assigned + type fields and interpretations. + + Internet (IPv4) Addresses + + Internet (IPv4) addresses are 32-bit (4-octet) quantities, encoded + in MSB order (most significant byte first). The IPv4 loopback + address SHOULD NOT appear in a Kerberos PDU. The type of IPv4 + addresses is two (2). + + Internet (IPv6) Addresses + + IPv6 addresses [RFC3513] are 128-bit (16-octet) quantities, + encoded in MSB order (most significant byte first). The type of + IPv6 addresses is twenty-four (24). The following addresses MUST + NOT appear in any Kerberos PDU: + + * the Unspecified Address + * the Loopback Address + * Link-Local addresses + + This restriction applies to the inclusion in the address fields of + Kerberos PDUs, but not to the address fields of packets that might + carry such PDUs. The restriction is necessary because the use of + an address with non-global scope could allow the acceptance of a + message sent from a node that may have the same address, but which + is not the host intended by the entity that added the restriction. + If the link-local address type needs to be used for communication, + then the address restriction in tickets must not be used (i.e., + addressless tickets must be used). + + IPv4-mapped IPv6 addresses MUST be represented as addresses of + type 2. + + DECnet Phase IV Addresses + + DECnet Phase IV addresses are 16-bit addresses, encoded in LSB + order. The type of DECnet Phase IV addresses is twelve (12). + + + + + + + + +Neuman, et al. Standards Track [Page 101] + +RFC 4120 Kerberos V5 July 2005 + + + Netbios Addresses + + Netbios addresses are 16-octet addresses typically composed of 1 + to 15 alphanumeric characters and padded with the US-ASCII SPC + character (code 32). The 16th octet MUST be the US-ASCII NUL + character (code 0). The type of Netbios addresses is twenty (20). + + Directional Addresses + + Including the sender address in KRB_SAFE and KRB_PRIV messages is + undesirable in many environments because the addresses may be + changed in transport by network address translators. However, if + these addresses are removed, the messages may be subject to a + reflection attack in which a message is reflected back to its + originator. The directional address type provides a way to avoid + transport addresses and reflection attacks. Directional addresses + are encoded as four-byte unsigned integers in network byte order. + If the message is originated by the party sending the original + KRB_AP_REQ message, then an address of 0 SHOULD be used. If the + message is originated by the party to whom that KRB_AP_REQ was + sent, then the address 1 SHOULD be used. Applications involving + multiple parties can specify the use of other addresses. + + Directional addresses MUST only be used for the sender address + field in the KRB_SAFE or KRB_PRIV messages. They MUST NOT be used + as a ticket address or in a KRB_AP_REQ message. This address type + SHOULD only be used in situations where the sending party knows + that the receiving party supports the address type. This + generally means that directional addresses may only be used when + the application protocol requires their support. Directional + addresses are type (3). + +7.2. KDC Messaging: IP Transports + + Kerberos defines two IP transport mechanisms for communication + between clients and servers: UDP/IP and TCP/IP. + +7.2.1. UDP/IP transport + + Kerberos servers (KDCs) supporting IP transports MUST accept UDP + requests and SHOULD listen for them on port 88 (decimal) unless + specifically configured to listen on an alternative UDP port. + Alternate ports MAY be used when running multiple KDCs for multiple + realms on the same host. + + + + + + + +Neuman, et al. Standards Track [Page 102] + +RFC 4120 Kerberos V5 July 2005 + + + Kerberos clients supporting IP transports SHOULD support the sending + of UDP requests. Clients SHOULD use KDC discovery [7.2.3] to + identify the IP address and port to which they will send their + request. + + When contacting a KDC for a KRB_KDC_REQ request using UDP/IP + transport, the client shall send a UDP datagram containing only an + encoding of the request to the KDC. The KDC will respond with a + reply datagram containing only an encoding of the reply message + (either a KRB_ERROR or a KRB_KDC_REP) to the sending port at the + sender's IP address. The response to a request made through UDP/IP + transport MUST also use UDP/IP transport. If the response cannot be + handled using UDP (for example, because it is too large), the KDC + MUST return KRB_ERR_RESPONSE_TOO_BIG, forcing the client to retry the + request using the TCP transport. + +7.2.2. TCP/IP Transport + + Kerberos servers (KDCs) supporting IP transports MUST accept TCP + requests and SHOULD listen for them on port 88 (decimal) unless + specifically configured to listen on an alternate TCP port. + Alternate ports MAY be used when running multiple KDCs for multiple + realms on the same host. + + Clients MUST support the sending of TCP requests, but MAY choose to + try a request initially using the UDP transport. Clients SHOULD use + KDC discovery [7.2.3] to identify the IP address and port to which + they will send their request. + + Implementation note: Some extensions to the Kerberos protocol will + not succeed if any client or KDC not supporting the TCP transport is + involved. Implementations of RFC 1510 were not required to support + TCP/IP transports. + + When the KRB_KDC_REQ message is sent to the KDC over a TCP stream, + the response (KRB_KDC_REP or KRB_ERROR message) MUST be returned to + the client on the same TCP stream that was established for the + request. The KDC MAY close the TCP stream after sending a response, + but MAY leave the stream open for a reasonable period of time if it + expects a follow-up. Care must be taken in managing TCP/IP + connections on the KDC to prevent denial of service attacks based on + the number of open TCP/IP connections. + + The client MUST be prepared to have the stream closed by the KDC at + any time after the receipt of a response. A stream closure SHOULD + NOT be treated as a fatal error. Instead, if multiple exchanges are + required (e.g., certain forms of pre-authentication), the client may + need to establish a new connection when it is ready to send + + + +Neuman, et al. Standards Track [Page 103] + +RFC 4120 Kerberos V5 July 2005 + + + subsequent messages. A client MAY close the stream after receiving a + response, and SHOULD close the stream if it does not expect to send + follow-up messages. + + A client MAY send multiple requests before receiving responses, + though it must be prepared to handle the connection being closed + after the first response. + + Each request (KRB_KDC_REQ) and response (KRB_KDC_REP or KRB_ERROR) + sent over the TCP stream is preceded by the length of the request as + 4 octets in network byte order. The high bit of the length is + reserved for future expansion and MUST currently be set to zero. If + a KDC that does not understand how to interpret a set high bit of the + length encoding receives a request with the high order bit of the + length set, it MUST return a KRB-ERROR message with the error + KRB_ERR_FIELD_TOOLONG and MUST close the TCP stream. + + If multiple requests are sent over a single TCP connection and the + KDC sends multiple responses, the KDC is not required to send the + responses in the order of the corresponding requests. This may + permit some implementations to send each response as soon as it is + ready, even if earlier requests are still being processed (for + example, waiting for a response from an external device or database). + +7.2.3. KDC Discovery on IP Networks + + Kerberos client implementations MUST provide a means for the client + to determine the location of the Kerberos Key Distribution Centers + (KDCs). Traditionally, Kerberos implementations have stored such + configuration information in a file on each client machine. + Experience has shown that this method of storing configuration + information presents problems with out-of-date information and + scaling, especially when using cross-realm authentication. This + section describes a method for using the Domain Name System [RFC1035] + for storing KDC location information. + +7.2.3.1. DNS vs. Kerberos: Case Sensitivity of Realm Names + + In Kerberos, realm names are case sensitive. Although it is strongly + encouraged that all realm names be all uppercase, this recommendation + has not been adopted by all sites. Some sites use all lowercase + names and other use mixed case. DNS, on the other hand, is case + insensitive for queries. Because the realm names "MYREALM", + "myrealm", and "MyRealm" are all different, but resolve the same in + the domain name system, it is necessary that only one of the possible + combinations of upper- and lowercase characters be used in realm + names. + + + + +Neuman, et al. Standards Track [Page 104] + +RFC 4120 Kerberos V5 July 2005 + + +7.2.3.2. Specifying KDC Location Information with DNS SRV records + + KDC location information is to be stored using the DNS SRV RR + [RFC2782]. The format of this RR is as follows: + + _Service._Proto.Realm TTL Class SRV Priority Weight Port Target + + The Service name for Kerberos is always "kerberos". + + The Proto can be either "udp" or "tcp". If these SRV records are to + be used, both "udp" and "tcp" records MUST be specified for all KDC + deployments. + + The Realm is the Kerberos realm that this record corresponds to. The + realm MUST be a domain-style realm name. + + TTL, Class, SRV, Priority, Weight, and Target have the standard + meaning as defined in RFC 2782. + + As per RFC 2782, the Port number used for "_udp" and "_tcp" SRV + records SHOULD be the value assigned to "kerberos" by the Internet + Assigned Number Authority: 88 (decimal), unless the KDC is configured + to listen on an alternate TCP port. + + Implementation note: Many existing client implementations do not + support KDC Discovery and are configured to send requests to the IANA + assigned port (88 decimal), so it is strongly recommended that KDCs + be configured to listen on that port. + +7.2.3.3. KDC Discovery for Domain Style Realm Names on IP Networks + + These are DNS records for a Kerberos realm EXAMPLE.COM. It has two + Kerberos servers, kdc1.example.com and kdc2.example.com. Queries + should be directed to kdc1.example.com first as per the specified + priority. Weights are not used in these sample records. + + _kerberos._udp.EXAMPLE.COM. IN SRV 0 0 88 kdc1.example.com. + _kerberos._udp.EXAMPLE.COM. IN SRV 1 0 88 kdc2.example.com. + _kerberos._tcp.EXAMPLE.COM. IN SRV 0 0 88 kdc1.example.com. + _kerberos._tcp.EXAMPLE.COM. IN SRV 1 0 88 kdc2.example.com. + +7.3. Name of the TGS + + The principal identifier of the ticket-granting service shall be + composed of three parts: the realm of the KDC issuing the TGS ticket, + and a two-part name of type NT-SRV-INST, with the first part "krbtgt" + and the second part the name of the realm that will accept the TGT. + For example, a TGT issued by the ATHENA.MIT.EDU realm to be used to + + + +Neuman, et al. Standards Track [Page 105] + +RFC 4120 Kerberos V5 July 2005 + + + get tickets from the ATHENA.MIT.EDU KDC has a principal identifier of + "ATHENA.MIT.EDU" (realm), ("krbtgt", "ATHENA.MIT.EDU") (name). A TGT + issued by the ATHENA.MIT.EDU realm to be used to get tickets from the + MIT.EDU realm has a principal identifier of "ATHENA.MIT.EDU" (realm), + ("krbtgt", "MIT.EDU") (name). + +7.4. OID Arc for KerberosV5 + + This OID MAY be used to identify Kerberos protocol messages + encapsulated in other protocols. It also designates the OID arc for + KerberosV5-related OIDs assigned by future IETF action. + Implementation note: RFC 1510 had an incorrect value (5) for "dod" in + its OID. + + id-krb5 OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) + } + + Assignment of OIDs beneath the id-krb5 arc must be obtained by + contacting the registrar for the id-krb5 arc, or its designee. At + the time of the issuance of this RFC, such registrations can be + obtained by contacting krb5-oid-registrar@mit.edu. + +7.5. Protocol Constants and Associated Values + + The following tables list constants used in the protocol and define + their meanings. In the "specification" section, ranges are specified + that limit the values of constants for which values are defined here. + This allows implementations to make assumptions about the maximum + values that will be received for these constants. Implementations + receiving values outside the range specified in the "specification" + section MAY reject the request, but they MUST recover cleanly. + +7.5.1. Key Usage Numbers + + The encryption and checksum specifications in [RFC3961] require as + input a "key usage number", to alter the encryption key used in any + specific message in order to make certain types of cryptographic + attack more difficult. These are the key usage values assigned in + this document: + + 1. AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with + the client key (Section 5.2.7.2) + + + + + + + +Neuman, et al. Standards Track [Page 106] + +RFC 4120 Kerberos V5 July 2005 + + + 2. AS-REP Ticket and TGS-REP Ticket (includes TGS session + key or application session key), encrypted with the + service key (Section 5.3) + 3. AS-REP encrypted part (includes TGS session key or + application session key), encrypted with the client key + (Section 5.4.2) + 4. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with + the TGS session key (Section 5.4.1) + 5. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with + the TGS authenticator subkey (Section 5.4.1) + 6. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum, + keyed with the TGS session key (Section 5.5.1) + 7. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes + TGS authenticator subkey), encrypted with the TGS session + key (Section 5.5.1) + 8. TGS-REP encrypted part (includes application session + key), encrypted with the TGS session key (Section 5.4.2) + 9. TGS-REP encrypted part (includes application session + key), encrypted with the TGS authenticator subkey + (Section 5.4.2) + 10. AP-REQ Authenticator cksum, keyed with the application + session key (Section 5.5.1) + 11. AP-REQ Authenticator (includes application authenticator + subkey), encrypted with the application session key + (Section 5.5.1) + 12. AP-REP encrypted part (includes application session + subkey), encrypted with the application session key + (Section 5.5.2) + 13. KRB-PRIV encrypted part, encrypted with a key chosen by + the application (Section 5.7.1) + 14. KRB-CRED encrypted part, encrypted with a key chosen by + the application (Section 5.8.1) + 15. KRB-SAFE cksum, keyed with a key chosen by the + application (Section 5.6.1) + 16-18. Reserved for future use in Kerberos and related + protocols. + 19. AD-KDC-ISSUED checksum (ad-checksum in 5.2.6.4) + 20-21. Reserved for future use in Kerberos and related + protocols. + 22-25. Reserved for use in the Kerberos Version 5 GSS-API + mechanisms [RFC4121]. + 26-511. Reserved for future use in Kerberos and related + protocols. + 512-1023. Reserved for uses internal to a Kerberos implementation. + 1024. Encryption for application use in protocols that do not + specify key usage values + + + + + +Neuman, et al. Standards Track [Page 107] + +RFC 4120 Kerberos V5 July 2005 + + + 1025. Checksums for application use in protocols that do not + specify key usage values + 1026-2047. Reserved for application use. + +7.5.2. PreAuthentication Data Types + + Padata and Data Type Padata-type Comment + Value + + PA-TGS-REQ 1 + PA-ENC-TIMESTAMP 2 + PA-PW-SALT 3 + [reserved] 4 + PA-ENC-UNIX-TIME 5 (deprecated) + PA-SANDIA-SECUREID 6 + PA-SESAME 7 + PA-OSF-DCE 8 + PA-CYBERSAFE-SECUREID 9 + PA-AFS3-SALT 10 + PA-ETYPE-INFO 11 + PA-SAM-CHALLENGE 12 (sam/otp) + PA-SAM-RESPONSE 13 (sam/otp) + PA-PK-AS-REQ_OLD 14 (pkinit) + PA-PK-AS-REP_OLD 15 (pkinit) + PA-PK-AS-REQ 16 (pkinit) + PA-PK-AS-REP 17 (pkinit) + PA-ETYPE-INFO2 19 (replaces pa-etype-info) + PA-USE-SPECIFIED-KVNO 20 + PA-SAM-REDIRECT 21 (sam/otp) + PA-GET-FROM-TYPED-DATA 22 (embedded in typed data) + TD-PADATA 22 (embeds padata) + PA-SAM-ETYPE-INFO 23 (sam/otp) + PA-ALT-PRINC 24 (crawdad@fnal.gov) + PA-SAM-CHALLENGE2 30 (kenh@pobox.com) + PA-SAM-RESPONSE2 31 (kenh@pobox.com) + PA-EXTRA-TGT 41 Reserved extra TGT + TD-PKINIT-CMS-CERTIFICATES 101 CertificateSet from CMS + TD-KRB-PRINCIPAL 102 PrincipalName + TD-KRB-REALM 103 Realm + TD-TRUSTED-CERTIFIERS 104 from PKINIT + TD-CERTIFICATE-INDEX 105 from PKINIT + TD-APP-DEFINED-ERROR 106 application specific + TD-REQ-NONCE 107 INTEGER + TD-REQ-SEQ 108 INTEGER + PA-PAC-REQUEST 128 (jbrezak@exchange.microsoft.com) + + + + + + +Neuman, et al. Standards Track [Page 108] + +RFC 4120 Kerberos V5 July 2005 + + +7.5.3. Address Types + + Address Type Value + + IPv4 2 + Directional 3 + ChaosNet 5 + XNS 6 + ISO 7 + DECNET Phase IV 12 + AppleTalk DDP 16 + NetBios 20 + IPv6 24 + +7.5.4. Authorization Data Types + + Authorization Data Type Ad-type Value + + AD-IF-RELEVANT 1 + AD-INTENDED-FOR-SERVER 2 + AD-INTENDED-FOR-APPLICATION-CLASS 3 + AD-KDC-ISSUED 4 + AD-AND-OR 5 + AD-MANDATORY-TICKET-EXTENSIONS 6 + AD-IN-TICKET-EXTENSIONS 7 + AD-MANDATORY-FOR-KDC 8 + Reserved values 9-63 + OSF-DCE 64 + SESAME 65 + AD-OSF-DCE-PKI-CERTID 66 (hemsath@us.ibm.com) + AD-WIN2K-PAC 128 (jbrezak@exchange.microsoft.com) + AD-ETYPE-NEGOTIATION 129 (lzhu@windows.microsoft.com) + +7.5.5. Transited Encoding Types + + Transited Encoding Type Tr-type Value + + DOMAIN-X500-COMPRESS 1 + Reserved values All others + +7.5.6. Protocol Version Number + + Label Value Meaning or MIT Code + + pvno 5 Current Kerberos protocol version number + + + + + + +Neuman, et al. Standards Track [Page 109] + +RFC 4120 Kerberos V5 July 2005 + + +7.5.7. Kerberos Message Types + + Message Type Value Meaning + + KRB_AS_REQ 10 Request for initial authentication + KRB_AS_REP 11 Response to KRB_AS_REQ request + KRB_TGS_REQ 12 Request for authentication based on TGT + KRB_TGS_REP 13 Response to KRB_TGS_REQ request + KRB_AP_REQ 14 Application request to server + KRB_AP_REP 15 Response to KRB_AP_REQ_MUTUAL + KRB_RESERVED16 16 Reserved for user-to-user krb_tgt_request + KRB_RESERVED17 17 Reserved for user-to-user krb_tgt_reply + KRB_SAFE 20 Safe (checksummed) application message + KRB_PRIV 21 Private (encrypted) application message + KRB_CRED 22 Private (encrypted) message to forward + credentials + KRB_ERROR 30 Error response + +7.5.8. Name Types + + Name Type Value Meaning + + KRB_NT_UNKNOWN 0 Name type not known + KRB_NT_PRINCIPAL 1 Just the name of the principal as in DCE, + or for users + KRB_NT_SRV_INST 2 Service and other unique instance (krbtgt) + KRB_NT_SRV_HST 3 Service with host name as instance + (telnet, rcommands) + KRB_NT_SRV_XHST 4 Service with host as remaining components + KRB_NT_UID 5 Unique ID + KRB_NT_X500_PRINCIPAL 6 Encoded X.509 Distinguished name [RFC2253] + KRB_NT_SMTP_NAME 7 Name in form of SMTP email name + (e.g., user@example.com) + KRB_NT_ENTERPRISE 10 Enterprise name; may be mapped to + principal name + +7.5.9. Error Codes + + Error Code Value Meaning + + KDC_ERR_NONE 0 No error + KDC_ERR_NAME_EXP 1 Client's entry in database + has expired + KDC_ERR_SERVICE_EXP 2 Server's entry in database + has expired + KDC_ERR_BAD_PVNO 3 Requested protocol version + number not supported + + + + +Neuman, et al. Standards Track [Page 110] + +RFC 4120 Kerberos V5 July 2005 + + + KDC_ERR_C_OLD_MAST_KVNO 4 Client's key encrypted in + old master key + KDC_ERR_S_OLD_MAST_KVNO 5 Server's key encrypted in + old master key + KDC_ERR_C_PRINCIPAL_UNKNOWN 6 Client not found in + Kerberos database + KDC_ERR_S_PRINCIPAL_UNKNOWN 7 Server not found in + Kerberos database + KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 Multiple principal entries + in database + KDC_ERR_NULL_KEY 9 The client or server has a + null key + KDC_ERR_CANNOT_POSTDATE 10 Ticket not eligible for + postdating + KDC_ERR_NEVER_VALID 11 Requested starttime is + later than end time + KDC_ERR_POLICY 12 KDC policy rejects request + KDC_ERR_BADOPTION 13 KDC cannot accommodate + requested option + KDC_ERR_ETYPE_NOSUPP 14 KDC has no support for + encryption type + KDC_ERR_SUMTYPE_NOSUPP 15 KDC has no support for + checksum type + KDC_ERR_PADATA_TYPE_NOSUPP 16 KDC has no support for + padata type + KDC_ERR_TRTYPE_NOSUPP 17 KDC has no support for + transited type + KDC_ERR_CLIENT_REVOKED 18 Clients credentials have + been revoked + KDC_ERR_SERVICE_REVOKED 19 Credentials for server have + been revoked + KDC_ERR_TGT_REVOKED 20 TGT has been revoked + KDC_ERR_CLIENT_NOTYET 21 Client not yet valid; try + again later + KDC_ERR_SERVICE_NOTYET 22 Server not yet valid; try + again later + KDC_ERR_KEY_EXPIRED 23 Password has expired; + change password to reset + KDC_ERR_PREAUTH_FAILED 24 Pre-authentication + information was invalid + KDC_ERR_PREAUTH_REQUIRED 25 Additional pre- + authentication required + KDC_ERR_SERVER_NOMATCH 26 Requested server and ticket + don't match + KDC_ERR_MUST_USE_USER2USER 27 Server principal valid for + user2user only + KDC_ERR_PATH_NOT_ACCEPTED 28 KDC Policy rejects + transited path + + + +Neuman, et al. Standards Track [Page 111] + +RFC 4120 Kerberos V5 July 2005 + + + KDC_ERR_SVC_UNAVAILABLE 29 A service is not available + KRB_AP_ERR_BAD_INTEGRITY 31 Integrity check on + decrypted field failed + KRB_AP_ERR_TKT_EXPIRED 32 Ticket expired + KRB_AP_ERR_TKT_NYV 33 Ticket not yet valid + KRB_AP_ERR_REPEAT 34 Request is a replay + KRB_AP_ERR_NOT_US 35 The ticket isn't for us + KRB_AP_ERR_BADMATCH 36 Ticket and authenticator + don't match + KRB_AP_ERR_SKEW 37 Clock skew too great + KRB_AP_ERR_BADADDR 38 Incorrect net address + KRB_AP_ERR_BADVERSION 39 Protocol version mismatch + KRB_AP_ERR_MSG_TYPE 40 Invalid msg type + KRB_AP_ERR_MODIFIED 41 Message stream modified + KRB_AP_ERR_BADORDER 42 Message out of order + KRB_AP_ERR_BADKEYVER 44 Specified version of key is + not available + KRB_AP_ERR_NOKEY 45 Service key not available + KRB_AP_ERR_MUT_FAIL 46 Mutual authentication + failed + KRB_AP_ERR_BADDIRECTION 47 Incorrect message direction + KRB_AP_ERR_METHOD 48 Alternative authentication + method required + KRB_AP_ERR_BADSEQ 49 Incorrect sequence number + in message + KRB_AP_ERR_INAPP_CKSUM 50 Inappropriate type of + checksum in message + KRB_AP_PATH_NOT_ACCEPTED 51 Policy rejects transited + path + KRB_ERR_RESPONSE_TOO_BIG 52 Response too big for UDP; + retry with TCP + KRB_ERR_GENERIC 60 Generic error (description + in e-text) + KRB_ERR_FIELD_TOOLONG 61 Field is too long for this + implementation + KDC_ERROR_CLIENT_NOT_TRUSTED 62 Reserved for PKINIT + KDC_ERROR_KDC_NOT_TRUSTED 63 Reserved for PKINIT + KDC_ERROR_INVALID_SIG 64 Reserved for PKINIT + KDC_ERR_KEY_TOO_WEAK 65 Reserved for PKINIT + KDC_ERR_CERTIFICATE_MISMATCH 66 Reserved for PKINIT + KRB_AP_ERR_NO_TGT 67 No TGT available to + validate USER-TO-USER + KDC_ERR_WRONG_REALM 68 Reserved for future use + KRB_AP_ERR_USER_TO_USER_REQUIRED 69 Ticket must be for + USER-TO-USER + KDC_ERR_CANT_VERIFY_CERTIFICATE 70 Reserved for PKINIT + KDC_ERR_INVALID_CERTIFICATE 71 Reserved for PKINIT + KDC_ERR_REVOKED_CERTIFICATE 72 Reserved for PKINIT + + + +Neuman, et al. Standards Track [Page 112] + +RFC 4120 Kerberos V5 July 2005 + + + KDC_ERR_REVOCATION_STATUS_UNKNOWN 73 Reserved for PKINIT + KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74 Reserved for PKINIT + KDC_ERR_CLIENT_NAME_MISMATCH 75 Reserved for PKINIT + KDC_ERR_KDC_NAME_MISMATCH 76 Reserved for PKINIT + +8. Interoperability Requirements + + Version 5 of the Kerberos protocol supports a myriad of options. + Among these are multiple encryption and checksum types; alternative + encoding schemes for the transited field; optional mechanisms for + pre-authentication; the handling of tickets with no addresses; + options for mutual authentication; user-to-user authentication; + support for proxies; the format of realm names; the handling of + authorization data; and forwarding, postdating, and renewing tickets. + + In order to ensure the interoperability of realms, it is necessary to + define a minimal configuration that must be supported by all + implementations. This minimal configuration is subject to change as + technology does. For example, if at some later date it is discovered + that one of the required encryption or checksum algorithms is not + secure, it will be replaced. + +8.1. Specification 2 + + This section defines the second specification of these options. + Implementations which are configured in this way can be said to + support Kerberos Version 5 Specification 2 (5.2). Specification 1 + (deprecated) may be found in RFC 1510. + + Transport + + TCP/IP and UDP/IP transport MUST be supported by clients and KDCs + claiming conformance to specification 2. + + Encryption and Checksum Methods + + The following encryption and checksum mechanisms MUST be + supported: + + Encryption: AES256-CTS-HMAC-SHA1-96 [RFC3962] + Checksums: HMAC-SHA1-96-AES256 [RFC3962] + + Implementations SHOULD support other mechanisms as well, but the + additional mechanisms may only be used when communicating with + principals known to also support them. The following mechanisms + from [RFC3961] and [RFC3962] SHOULD be supported: + + + + + +Neuman, et al. Standards Track [Page 113] + +RFC 4120 Kerberos V5 July 2005 + + + Encryption: AES128-CTS-HMAC-SHA1-96, DES-CBC-MD5, DES3-CBC-SHA1-KD + Checksums: DES-MD5, HMAC-SHA1-DES3-KD, HMAC-SHA1-96-AES128 + + Implementations MAY support other mechanisms as well, but the + additional mechanisms may only be used when communicating with + principals known to support them also. + + Implementation note: Earlier implementations of Kerberos generate + messages using the CRC-32 and RSA-MD5 checksum methods. For + interoperability with these earlier releases, implementors MAY + consider supporting these checksum methods but should carefully + analyze the security implications to limit the situations within + which these methods are accepted. + + Realm Names + + All implementations MUST understand hierarchical realms in both + the Internet Domain and the X.500 style. When a TGT for an + unknown realm is requested, the KDC MUST be able to determine the + names of the intermediate realms between the KDCs realm and the + requested realm. + + Transited Field Encoding + + DOMAIN-X500-COMPRESS (described in Section 3.3.3.2) MUST be + supported. Alternative encodings MAY be supported, but they may + only be used when that encoding is supported by ALL intermediate + realms. + + Pre-authentication Methods + + The TGS-REQ method MUST be supported. It is not used on the + initial request. The PA-ENC-TIMESTAMP method MUST be supported by + clients, but whether it is enabled by default MAY be determined on + a realm-by-realm basis. If the method is not used in the initial + request and the error KDC_ERR_PREAUTH_REQUIRED is returned + specifying PA-ENC-TIMESTAMP as an acceptable method, the client + SHOULD retry the initial request using the PA-ENC-TIMESTAMP pre- + authentication method. Servers need not support the PA-ENC- + TIMESTAMP method, but if it is not supported the server SHOULD + ignore the presence of PA-ENC-TIMESTAMP pre-authentication in a + request. + + The ETYPE-INFO2 method MUST be supported; this method is used to + communicate the set of supported encryption types, and + corresponding salt and string to key parameters. The ETYPE-INFO + method SHOULD be supported for interoperability with older + implementation. + + + +Neuman, et al. Standards Track [Page 114] + +RFC 4120 Kerberos V5 July 2005 + + + Mutual Authentication + + Mutual authentication (via the KRB_AP_REP message) MUST be + supported. + + Ticket Addresses and Flags + + All KDCs MUST pass through tickets that carry no addresses (i.e., + if a TGT contains no addresses, the KDC will return derivative + tickets). Implementations SHOULD default to requesting + addressless tickets, as this significantly increases + interoperability with network address translation. In some cases, + realms or application servers MAY require that tickets have an + address. + + Implementations SHOULD accept directional address type for the + KRB_SAFE and KRB_PRIV message and SHOULD include directional + addresses in these messages when other address types are not + available. + + Proxies and forwarded tickets MUST be supported. Individual + realms and application servers can set their own policy on when + such tickets will be accepted. + + All implementations MUST recognize renewable and postdated + tickets, but they need not actually implement them. If these + options are not supported, the starttime and endtime in the ticket + SHALL specify a ticket's entire useful life. When a postdated + ticket is decoded by a server, all implementations SHALL make the + presence of the postdated flag visible to the calling server. + + User-to-User Authentication + + Support for user-to-user authentication (via the ENC-TKT-IN-SKEY + KDC option) MUST be provided by implementations, but individual + realms MAY decide as a matter of policy to reject such requests on + a per-principal or realm-wide basis. + + Authorization Data + + Implementations MUST pass all authorization data subfields from + TGTs to any derivative tickets unless they are directed to + suppress a subfield as part of the definition of that registered + subfield type. (It is never incorrect to pass on a subfield, and + no registered subfield types presently specify suppression at the + KDC.) + + + + + +Neuman, et al. Standards Track [Page 115] + +RFC 4120 Kerberos V5 July 2005 + + + Implementations MUST make the contents of any authorization data + subfields available to the server when a ticket is used. + Implementations are not required to allow clients to specify the + contents of the authorization data fields. + + Constant Ranges + + All protocol constants are constrained to 32-bit (signed) values + unless further constrained by the protocol definition. This limit + is provided to allow implementations to make assumptions about the + maximum values that will be received for these constants. + Implementations receiving values outside this range MAY reject the + request, but they MUST recover cleanly. + +8.2. Recommended KDC Values + + Following is a list of recommended values for a KDC configuration. + + Minimum lifetime 5 minutes + Maximum renewable lifetime 1 week + Maximum ticket lifetime 1 day + Acceptable clock skew 5 minutes + Empty addresses Allowed + Proxiable, etc. Allowed + +9. IANA Considerations + + Section 7 of this document specifies protocol constants and other + defined values required for the interoperability of multiple + implementations. Until a subsequent RFC specifies otherwise, or the + Kerberos working group is shut down, allocations of additional + protocol constants and other defined values required for extensions + to the Kerberos protocol will be administered by the Kerberos working + group. Following the recommendations outlined in [RFC2434], guidance + is provided to the IANA as follows: + + "reserved" realm name types in Section 6.1 and "other" realm types + except those beginning with "X-" or "x-" will not be registered + without IETF standards action, at which point guidelines for further + assignment will be specified. Realm name types beginning with "X-" + or "x-" are for private use. + + For host address types described in Section 7.1, negative values are + for private use. Assignment of additional positive numbers is + subject to review by the Kerberos working group or other expert + review. + + + + + +Neuman, et al. Standards Track [Page 116] + +RFC 4120 Kerberos V5 July 2005 + + + Additional key usage numbers, as defined in Section 7.5.1, will be + assigned subject to review by the Kerberos working group or other + expert review. + + Additional preauthentication data type values, as defined in section + 7.5.2, will be assigned subject to review by the Kerberos working + group or other expert review. + + Additional authorization data types as defined in Section 7.5.4, will + be assigned subject to review by the Kerberos working group or other + expert review. Although it is anticipated that there may be + significant demand for private use types, provision is intentionally + not made for a private use portion of the namespace because conflicts + between privately assigned values could have detrimental security + implications. + + Additional transited encoding types, as defined in Section 7.5.5, + present special concerns for interoperability with existing + implementations. As such, such assignments will only be made by + standards action, except that the Kerberos working group or another + other working group with competent jurisdiction may make preliminary + assignments for documents that are moving through the standards + process. + + Additional Kerberos message types, as described in Section 7.5.7, + will be assigned subject to review by the Kerberos working group or + other expert review. + + Additional name types, as described in Section 7.5.8, will be + assigned subject to review by the Kerberos working group or other + expert review. + + Additional error codes described in Section 7.5.9 will be assigned + subject to review by the Kerberos working group or other expert + review. + +10. Security Considerations + + As an authentication service, Kerberos provides a means of verifying + the identity of principals on a network. By itself, Kerberos does + not provide authorization. Applications should not accept the + issuance of a service ticket by the Kerberos server as granting + authority to use the service, since such applications may become + vulnerable to the bypass of this authorization check in an + environment where they inter-operate with other KDCs or where other + options for application authentication are provided. + + + + + +Neuman, et al. Standards Track [Page 117] + +RFC 4120 Kerberos V5 July 2005 + + + Denial of service attacks are not solved with Kerberos. There are + places in the protocols where an intruder can prevent an application + from participating in the proper authentication steps. Because + authentication is a required step for the use of many services, + successful denial of service attacks on a Kerberos server might + result in the denial of other network services that rely on Kerberos + for authentication. Kerberos is vulnerable to many kinds of denial + of service attacks: those on the network, which would prevent clients + from contacting the KDC; those on the domain name system, which could + prevent a client from finding the IP address of the Kerberos server; + and those by overloading the Kerberos KDC itself with repeated + requests. + + Interoperability conflicts caused by incompatible character-set usage + (see 5.2.1) can result in denial of service for clients that utilize + character-sets in Kerberos strings other than those stored in the KDC + database. + + Authentication servers maintain a database of principals (i.e., users + and servers) and their secret keys. The security of the + authentication server machines is critical. The breach of security + of an authentication server will compromise the security of all + servers that rely upon the compromised KDC, and will compromise the + authentication of any principals registered in the realm of the + compromised KDC. + + Principals must keep their secret keys secret. If an intruder + somehow steals a principal's key, it will be able to masquerade as + that principal or impersonate any server to the legitimate principal. + + Password-guessing attacks are not solved by Kerberos. If a user + chooses a poor password, it is possible for an attacker to + successfully mount an off-line dictionary attack by repeatedly + attempting to decrypt, with successive entries from a dictionary, + messages obtained that are encrypted under a key derived from the + user's password. + + Unless pre-authentication options are required by the policy of a + realm, the KDC will not know whether a request for authentication + succeeds. An attacker can request a reply with credentials for any + principal. These credentials will likely not be of much use to the + attacker unless it knows the client's secret key, but the + availability of the response encrypted in the client's secret key + provides the attacker with ciphertext that may be used to mount brute + force or dictionary attacks to decrypt the credentials, by guessing + the user's password. For this reason it is strongly encouraged that + Kerberos realms require the use of pre-authentication. Even with + + + + +Neuman, et al. Standards Track [Page 118] + +RFC 4120 Kerberos V5 July 2005 + + + pre-authentication, attackers may try brute force or dictionary + attacks against credentials that are observed by eavesdropping on the + network. + + Because a client can request a ticket for any server principal and + can attempt a brute force or dictionary attack against the server + principal's key using that ticket, it is strongly encouraged that + keys be randomly generated (rather than generated from passwords) for + any principals that are usable as the target principal for a + KRB_TGS_REQ or KRB_AS_REQ messages. [RFC4086] + + Although the DES-CBC-MD5 encryption method and DES-MD5 checksum + methods are listed as SHOULD be implemented for backward + compatibility, the single DES encryption algorithm on which these are + based is weak, and stronger algorithms should be used whenever + possible. + + Each host on the network must have a clock that is loosely + synchronized to the time of the other hosts; this synchronization is + used to reduce the bookkeeping needs of application servers when they + do replay detection. The degree of "looseness" can be configured on + a per-server basis, but it is typically on the order of 5 minutes. + If the clocks are synchronized over the network, the clock + synchronization protocol MUST itself be secured from network + attackers. + + Principal identifiers must not recycled on a short-term basis. A + typical mode of access control will use access control lists (ACLs) + to grant permissions to particular principals. If a stale ACL entry + remains for a deleted principal and the principal identifier is + reused, the new principal will inherit rights specified in the stale + ACL entry. By not reusing principal identifiers, the danger of + inadvertent access is removed. + + Proper decryption of an KRB_AS_REP message from the KDC is not + sufficient for the host to verify the identity of the user; the user + and an attacker could cooperate to generate a KRB_AS_REP format + message that decrypts properly but is not from the proper KDC. To + authenticate a user logging on to a local system, the credentials + obtained in the AS exchange may first be used in a TGS exchange to + obtain credentials for a local server. Those credentials must then + be verified by a local server through successful completion of the + Client/Server exchange. + + Many RFC 1510-compliant implementations ignore unknown authorization + data elements. Depending on these implementations to honor + authorization data restrictions may create a security weakness. + + + + +Neuman, et al. Standards Track [Page 119] + +RFC 4120 Kerberos V5 July 2005 + + + Kerberos credentials contain clear-text information identifying the + principals to which they apply. If privacy of this information is + needed, this exchange should itself be encapsulated in a protocol + providing for confidentiality on the exchange of these credentials. + + Applications must take care to protect communications subsequent to + authentication, either by using the KRB_PRIV or KRB_SAFE messages as + appropriate, or by applying their own confidentiality or integrity + mechanisms on such communications. Completion of the KRB_AP_REQ and + KRB_AP_REP exchange without subsequent use of confidentiality and + integrity mechanisms provides only for authentication of the parties + to the communication and not confidentiality and integrity of the + subsequent communication. Applications applying confidentiality and + integrity protection mechanisms other than KRB_PRIV and KRB_SAFE must + make sure that the authentication step is appropriately linked with + the protected communication channel that is established by the + application. + + Unless the application server provides its own suitable means to + protect against replay (for example, a challenge-response sequence + initiated by the server after authentication, or use of a server- + generated encryption subkey), the server must utilize a replay cache + to remember any authenticator presented within the allowable clock + skew. All services sharing a key need to use the same replay cache. + If separate replay caches are used, then an authenticator used with + one such service could later be replayed to a different service with + the same service principal. + + If a server loses track of authenticators presented within the + allowable clock skew, it must reject all requests until the clock + skew interval has passed, providing assurance that any lost or + replayed authenticators will fall outside the allowable clock skew + and can no longer be successfully replayed. + + Implementations of Kerberos should not use untrusted directory + servers to determine the realm of a host. To allow this would allow + the compromise of the directory server to enable an attacker to + direct the client to accept authentication with the wrong principal + (i.e., one with a similar name, but in a realm with which the + legitimate host was not registered). + + Implementations of Kerberos must not use DNS to map one name to + another (canonicalize) in order to determine the host part of the + principal name with which one is to communicate. To allow this + canonicalization would allow a compromise of the DNS to result in a + client obtaining credentials and correctly authenticating to the + + + + + +Neuman, et al. Standards Track [Page 120] + +RFC 4120 Kerberos V5 July 2005 + + + wrong principal. Though the client will know who it is communicating + with, it will not be the principal with which it intended to + communicate. + + If the Kerberos server returns a TGT for a realm 'closer' than the + desired realm, the client may use local policy configuration to + verify that the authentication path used is an acceptable one. + Alternatively, a client may choose its own authentication path rather + than rely on the Kerberos server to select one. In either case, any + policy or configuration information used to choose or validate + authentication paths, whether by the Kerberos server or client, must + be obtained from a trusted source. + + The Kerberos protocol in its basic form does not provide perfect + forward secrecy for communications. If traffic has been recorded by + an eavesdropper, then messages encrypted using the KRB_PRIV message, + or messages encrypted using application-specific encryption under + keys exchanged using Kerberos can be decrypted if the user's, + application server's, or KDC's key is subsequently discovered. This + is because the session key used to encrypt such messages, when + transmitted over the network, is encrypted in the key of the + application server. It is also encrypted under the session key from + the user's TGT when it is returned to the user in the KRB_TGS_REP + message. The session key from the TGT is sent to the user in the + KRB_AS_REP message encrypted in the user's secret key and embedded in + the TGT, which was encrypted in the key of the KDC. Applications + requiring perfect forward secrecy must exchange keys through + mechanisms that provide such assurance, but may use Kerberos for + authentication of the encrypted channel established through such + other means. + +11. Acknowledgements + + This document is a revision to RFC 1510 which was co-authored with + John Kohl. The specification of the Kerberos protocol described in + this document is the result of many years of effort. Over this + period, many individuals have contributed to the definition of the + protocol and to the writing of the specification. Unfortunately, it + is not possible to list all contributors as authors of this document, + though there are many not listed who are authors in spirit, including + those who contributed text for parts of some sections, who + contributed to the design of parts of the protocol, and who + contributed significantly to the discussion of the protocol in the + IETF common authentication technology (CAT) and Kerberos working + groups. + + + + + + +Neuman, et al. Standards Track [Page 121] + +RFC 4120 Kerberos V5 July 2005 + + + Among those contributing to the development and specification of + Kerberos were Jeffrey Altman, John Brezak, Marc Colan, Johan + Danielsson, Don Davis, Doug Engert, Dan Geer, Paul Hill, John Kohl, + Marc Horowitz, Matt Hur, Jeffrey Hutzelman, Paul Leach, John Linn, + Ari Medvinsky, Sasha Medvinsky, Steve Miller, Jon Rochlis, Jerome + Saltzer, Jeffrey Schiller, Jennifer Steiner, Ralph Swick, Mike Swift, + Jonathan Trostle, Theodore Ts'o, Brian Tung, Jacques Vidrine, Assar + Westerlund, and Nicolas Williams. Many other members of MIT Project + Athena, the MIT networking group, and the Kerberos and CAT working + groups of the IETF contributed but are not listed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Neuman, et al. Standards Track [Page 122] + +RFC 4120 Kerberos V5 July 2005 + + +A. ASN.1 module + +KerberosV5Spec2 { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) modules(4) krb5spec2(2) +} DEFINITIONS EXPLICIT TAGS ::= BEGIN + +-- OID arc for KerberosV5 +-- +-- This OID may be used to identify Kerberos protocol messages +-- encapsulated in other protocols. +-- +-- This OID also designates the OID arc for KerberosV5-related OIDs. +-- +-- NOTE: RFC 1510 had an incorrect value (5) for "dod" in its OID. +id-krb5 OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) +} + +Int32 ::= INTEGER (-2147483648..2147483647) + -- signed values representable in 32 bits + +UInt32 ::= INTEGER (0..4294967295) + -- unsigned 32 bit values + +Microseconds ::= INTEGER (0..999999) + -- microseconds + +KerberosString ::= GeneralString (IA5String) + +Realm ::= KerberosString + +PrincipalName ::= SEQUENCE { + name-type [0] Int32, + name-string [1] SEQUENCE OF KerberosString +} + +KerberosTime ::= GeneralizedTime -- with no fractional seconds + +HostAddress ::= SEQUENCE { + addr-type [0] Int32, + address [1] OCTET STRING +} + +-- NOTE: HostAddresses is always used as an OPTIONAL field and +-- should not be empty. +HostAddresses -- NOTE: subtly different from rfc1510, + + + +Neuman, et al. Standards Track [Page 123] + +RFC 4120 Kerberos V5 July 2005 + + + -- but has a value mapping and encodes the same + ::= SEQUENCE OF HostAddress + +-- NOTE: AuthorizationData is always used as an OPTIONAL field and +-- should not be empty. +AuthorizationData ::= SEQUENCE OF SEQUENCE { + ad-type [0] Int32, + ad-data [1] OCTET STRING +} + +PA-DATA ::= SEQUENCE { + -- NOTE: first tag is [1], not [0] + padata-type [1] Int32, + padata-value [2] OCTET STRING -- might be encoded AP-REQ +} + +KerberosFlags ::= BIT STRING (SIZE (32..MAX)) + -- minimum number of bits shall be sent, + -- but no fewer than 32 + +EncryptedData ::= SEQUENCE { + etype [0] Int32 -- EncryptionType --, + kvno [1] UInt32 OPTIONAL, + cipher [2] OCTET STRING -- ciphertext +} + +EncryptionKey ::= SEQUENCE { + keytype [0] Int32 -- actually encryption type --, + keyvalue [1] OCTET STRING +} + +Checksum ::= SEQUENCE { + cksumtype [0] Int32, + checksum [1] OCTET STRING +} + +Ticket ::= [APPLICATION 1] SEQUENCE { + tkt-vno [0] INTEGER (5), + realm [1] Realm, + sname [2] PrincipalName, + enc-part [3] EncryptedData -- EncTicketPart +} + +-- Encrypted part of ticket +EncTicketPart ::= [APPLICATION 3] SEQUENCE { + flags [0] TicketFlags, + key [1] EncryptionKey, + crealm [2] Realm, + + + +Neuman, et al. Standards Track [Page 124] + +RFC 4120 Kerberos V5 July 2005 + + + cname [3] PrincipalName, + transited [4] TransitedEncoding, + authtime [5] KerberosTime, + starttime [6] KerberosTime OPTIONAL, + endtime [7] KerberosTime, + renew-till [8] KerberosTime OPTIONAL, + caddr [9] HostAddresses OPTIONAL, + authorization-data [10] AuthorizationData OPTIONAL +} + +-- encoded Transited field +TransitedEncoding ::= SEQUENCE { + tr-type [0] Int32 -- must be registered --, + contents [1] OCTET STRING +} + +TicketFlags ::= KerberosFlags + -- reserved(0), + -- forwardable(1), + -- forwarded(2), + -- proxiable(3), + -- proxy(4), + -- may-postdate(5), + -- postdated(6), + -- invalid(7), + -- renewable(8), + -- initial(9), + -- pre-authent(10), + -- hw-authent(11), +-- the following are new since 1510 + -- transited-policy-checked(12), + -- ok-as-delegate(13) + +AS-REQ ::= [APPLICATION 10] KDC-REQ + +TGS-REQ ::= [APPLICATION 12] KDC-REQ + +KDC-REQ ::= SEQUENCE { + -- NOTE: first tag is [1], not [0] + pvno [1] INTEGER (5) , + msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), + padata [3] SEQUENCE OF PA-DATA OPTIONAL + -- NOTE: not empty --, + req-body [4] KDC-REQ-BODY +} + +KDC-REQ-BODY ::= SEQUENCE { + kdc-options [0] KDCOptions, + + + +Neuman, et al. Standards Track [Page 125] + +RFC 4120 Kerberos V5 July 2005 + + + cname [1] PrincipalName OPTIONAL + -- Used only in AS-REQ --, + realm [2] Realm + -- Server's realm + -- Also client's in AS-REQ --, + sname [3] PrincipalName OPTIONAL, + from [4] KerberosTime OPTIONAL, + till [5] KerberosTime, + rtime [6] KerberosTime OPTIONAL, + nonce [7] UInt32, + etype [8] SEQUENCE OF Int32 -- EncryptionType + -- in preference order --, + addresses [9] HostAddresses OPTIONAL, + enc-authorization-data [10] EncryptedData OPTIONAL + -- AuthorizationData --, + additional-tickets [11] SEQUENCE OF Ticket OPTIONAL + -- NOTE: not empty +} + +KDCOptions ::= KerberosFlags + -- reserved(0), + -- forwardable(1), + -- forwarded(2), + -- proxiable(3), + -- proxy(4), + -- allow-postdate(5), + -- postdated(6), + -- unused7(7), + -- renewable(8), + -- unused9(9), + -- unused10(10), + -- opt-hardware-auth(11), + -- unused12(12), + -- unused13(13), +-- 15 is reserved for canonicalize + -- unused15(15), +-- 26 was unused in 1510 + -- disable-transited-check(26), +-- + -- renewable-ok(27), + -- enc-tkt-in-skey(28), + -- renew(30), + -- validate(31) + +AS-REP ::= [APPLICATION 11] KDC-REP + +TGS-REP ::= [APPLICATION 13] KDC-REP + + + + +Neuman, et al. Standards Track [Page 126] + +RFC 4120 Kerberos V5 July 2005 + + +KDC-REP ::= SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --), + padata [2] SEQUENCE OF PA-DATA OPTIONAL + -- NOTE: not empty --, + crealm [3] Realm, + cname [4] PrincipalName, + ticket [5] Ticket, + enc-part [6] EncryptedData + -- EncASRepPart or EncTGSRepPart, + -- as appropriate +} + +EncASRepPart ::= [APPLICATION 25] EncKDCRepPart + +EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart + +EncKDCRepPart ::= SEQUENCE { + key [0] EncryptionKey, + last-req [1] LastReq, + nonce [2] UInt32, + key-expiration [3] KerberosTime OPTIONAL, + flags [4] TicketFlags, + authtime [5] KerberosTime, + starttime [6] KerberosTime OPTIONAL, + endtime [7] KerberosTime, + renew-till [8] KerberosTime OPTIONAL, + srealm [9] Realm, + sname [10] PrincipalName, + caddr [11] HostAddresses OPTIONAL +} + +LastReq ::= SEQUENCE OF SEQUENCE { + lr-type [0] Int32, + lr-value [1] KerberosTime +} + +AP-REQ ::= [APPLICATION 14] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (14), + ap-options [2] APOptions, + ticket [3] Ticket, + authenticator [4] EncryptedData -- Authenticator +} + +APOptions ::= KerberosFlags + -- reserved(0), + -- use-session-key(1), + + + +Neuman, et al. Standards Track [Page 127] + +RFC 4120 Kerberos V5 July 2005 + + + -- mutual-required(2) + +-- Unencrypted authenticator +Authenticator ::= [APPLICATION 2] SEQUENCE { + authenticator-vno [0] INTEGER (5), + crealm [1] Realm, + cname [2] PrincipalName, + cksum [3] Checksum OPTIONAL, + cusec [4] Microseconds, + ctime [5] KerberosTime, + subkey [6] EncryptionKey OPTIONAL, + seq-number [7] UInt32 OPTIONAL, + authorization-data [8] AuthorizationData OPTIONAL +} + +AP-REP ::= [APPLICATION 15] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (15), + enc-part [2] EncryptedData -- EncAPRepPart +} + +EncAPRepPart ::= [APPLICATION 27] SEQUENCE { + ctime [0] KerberosTime, + cusec [1] Microseconds, + subkey [2] EncryptionKey OPTIONAL, + seq-number [3] UInt32 OPTIONAL +} + +KRB-SAFE ::= [APPLICATION 20] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (20), + safe-body [2] KRB-SAFE-BODY, + cksum [3] Checksum +} + +KRB-SAFE-BODY ::= SEQUENCE { + user-data [0] OCTET STRING, + timestamp [1] KerberosTime OPTIONAL, + usec [2] Microseconds OPTIONAL, + seq-number [3] UInt32 OPTIONAL, + s-address [4] HostAddress, + r-address [5] HostAddress OPTIONAL +} + +KRB-PRIV ::= [APPLICATION 21] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (21), + -- NOTE: there is no [2] tag + + + +Neuman, et al. Standards Track [Page 128] + +RFC 4120 Kerberos V5 July 2005 + + + enc-part [3] EncryptedData -- EncKrbPrivPart +} + +EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE { + user-data [0] OCTET STRING, + timestamp [1] KerberosTime OPTIONAL, + usec [2] Microseconds OPTIONAL, + seq-number [3] UInt32 OPTIONAL, + s-address [4] HostAddress -- sender's addr --, + r-address [5] HostAddress OPTIONAL -- recip's addr +} + +KRB-CRED ::= [APPLICATION 22] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (22), + tickets [2] SEQUENCE OF Ticket, + enc-part [3] EncryptedData -- EncKrbCredPart +} + +EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { + ticket-info [0] SEQUENCE OF KrbCredInfo, + nonce [1] UInt32 OPTIONAL, + timestamp [2] KerberosTime OPTIONAL, + usec [3] Microseconds OPTIONAL, + s-address [4] HostAddress OPTIONAL, + r-address [5] HostAddress OPTIONAL +} + +KrbCredInfo ::= SEQUENCE { + key [0] EncryptionKey, + prealm [1] Realm OPTIONAL, + pname [2] PrincipalName OPTIONAL, + flags [3] TicketFlags OPTIONAL, + authtime [4] KerberosTime OPTIONAL, + starttime [5] KerberosTime OPTIONAL, + endtime [6] KerberosTime OPTIONAL, + renew-till [7] KerberosTime OPTIONAL, + srealm [8] Realm OPTIONAL, + sname [9] PrincipalName OPTIONAL, + caddr [10] HostAddresses OPTIONAL +} + +KRB-ERROR ::= [APPLICATION 30] SEQUENCE { + pvno [0] INTEGER (5), + msg-type [1] INTEGER (30), + ctime [2] KerberosTime OPTIONAL, + cusec [3] Microseconds OPTIONAL, + stime [4] KerberosTime, + + + +Neuman, et al. Standards Track [Page 129] + +RFC 4120 Kerberos V5 July 2005 + + + susec [5] Microseconds, + error-code [6] Int32, + crealm [7] Realm OPTIONAL, + cname [8] PrincipalName OPTIONAL, + realm [9] Realm -- service realm --, + sname [10] PrincipalName -- service name --, + e-text [11] KerberosString OPTIONAL, + e-data [12] OCTET STRING OPTIONAL +} + +METHOD-DATA ::= SEQUENCE OF PA-DATA + +TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + data-type [0] Int32, + data-value [1] OCTET STRING OPTIONAL +} + +-- preauth stuff follows + +PA-ENC-TIMESTAMP ::= EncryptedData -- PA-ENC-TS-ENC + +PA-ENC-TS-ENC ::= SEQUENCE { + patimestamp [0] KerberosTime -- client's time --, + pausec [1] Microseconds OPTIONAL +} + +ETYPE-INFO-ENTRY ::= SEQUENCE { + etype [0] Int32, + salt [1] OCTET STRING OPTIONAL +} + +ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY + +ETYPE-INFO2-ENTRY ::= SEQUENCE { + etype [0] Int32, + salt [1] KerberosString OPTIONAL, + s2kparams [2] OCTET STRING OPTIONAL +} + +ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY + +AD-IF-RELEVANT ::= AuthorizationData + +AD-KDCIssued ::= SEQUENCE { + ad-checksum [0] Checksum, + i-realm [1] Realm OPTIONAL, + i-sname [2] PrincipalName OPTIONAL, + elements [3] AuthorizationData + + + +Neuman, et al. Standards Track [Page 130] + +RFC 4120 Kerberos V5 July 2005 + + +} + +AD-AND-OR ::= SEQUENCE { + condition-count [0] Int32, + elements [1] AuthorizationData +} + +AD-MANDATORY-FOR-KDC ::= AuthorizationData + +END + +B. Changes since RFC 1510 + + This document replaces RFC 1510 and clarifies specification of items + that were not completely specified. Where changes to recommended + implementation choices were made, or where new options were added, + those changes are described within the document and listed in this + section. More significantly, "Specification 2" in Section 8 changes + the required encryption and checksum methods to bring them in line + with the best current practices and to deprecate methods that are no + longer considered sufficiently strong. + + Discussion was added to Section 1 regarding the ability to rely on + the KDC to check the transited field, and on the inclusion of a flag + in a ticket indicating that this check has occurred. This is a new + capability not present in RFC 1510. Pre-existing implementations may + ignore or not set this flag without negative security implications. + + The definition of the secret key says that in the case of a user the + key may be derived from a password. In RFC 1510, it said that the + key was derived from the password. This change was made to + accommodate situations where the user key might be stored on a + smart-card, or otherwise obtained independently of a password. + + The introduction mentions the use of public key cryptography for + initial authentication in Kerberos by reference. RFC 1510 did not + include such a reference. + + Section 1.3 was added to explain that while Kerberos provides + authentication of a named principal, it is still the responsibility + of the application to ensure that the authenticated name is the + entity with which the application wishes to communicate. + + Discussion of extensibility has been added to the introduction. + + Discussion of how extensibility affects ticket flags and KDC options + was added to the introduction of Section 2. No changes were made to + existing options and flags specified in RFC 1510, though some of the + + + +Neuman, et al. Standards Track [Page 131] + +RFC 4120 Kerberos V5 July 2005 + + + sections in the specification were renumbered, and text was revised + to make the description and intent of existing options clearer, + especially with respect to the ENC-TKT-IN-SKEY option (now section + 2.9.2) which is used for user-to-user authentication. The new option + and ticket flag transited policy checking (Section 2.7) was added. + + A warning regarding generation of session keys for application use + was added to Section 3, urging the inclusion of key entropy from the + KDC generated session key in the ticket. An example regarding use of + the sub-session key was added to Section 3.2.6. Descriptions of the + pa-etype-info, pa-etype-info2, and pa-pw-salt pre-authentication data + items were added. The recommendation for use of pre-authentication + was changed from "MAY" to "SHOULD" and a note was added regarding + known plaintext attacks. + + In RFC 1510, Section 4 described the database in the KDC. This + discussion was not necessary for interoperability and unnecessarily + constrained implementation. The old Section 4 was removed. + + The current Section 4 was formerly Section 6 on encryption and + checksum specifications. The major part of this section was brought + up to date to support new encryption methods, and moved to a separate + document. Those few remaining aspects of the encryption and checksum + specification specific to Kerberos are now specified in Section 4. + + Significant changes were made to the layout of Section 5 to clarify + the correct behavior for optional fields. Many of these changes were + made necessary because of improper ASN.1 description in the original + Kerberos specification which left the correct behavior + underspecified. Additionally, the wording in this section was + tightened wherever possible to ensure that implementations conforming + to this specification will be extensible with the addition of new + fields in future specifications. + + Text was added describing time_t=0 issues in the ASN.1. Text was + also added, clarifying issues with implementations treating omitted + optional integers as zero. Text was added clarifying behavior for + optional SEQUENCE or SEQUENCE OF that may be empty. Discussion was + added regarding sequence numbers and behavior of some + implementations, including "zero" behavior and negative numbers. A + compatibility note was added regarding the unconditional sending of + EncTGSRepPart regardless of the enclosing reply type. Minor changes + were made to the description of the HostAddresses type. Integer + types were constrained. KerberosString was defined as a + (significantly) constrained GeneralString. KerberosFlags was defined + to reflect existing implementation behavior that departs from the + + + + + +Neuman, et al. Standards Track [Page 132] + +RFC 4120 Kerberos V5 July 2005 + + + definition in RFC 1510. The transited-policy-checked(12) and the + ok-as-delegate(13) ticket flags were added. The disable-transited- + check(26) KDC option was added. + + Descriptions of commonly implemented PA-DATA were added to Section 5. + The description of KRB-SAFE has been updated to note the existing + implementation behavior of double-encoding. + + There were two definitions of METHOD-DATA in RFC 1510. The second + one, intended for use with KRB_AP_ERR_METHOD was removed leaving the + SEQUENCE OF PA-DATA definition. + + Section 7, naming constraints, from RFC 1510 was moved to Section 6. + + Words were added describing the convention that domain-based realm + names for newly-created realms should be specified as uppercase. + This recommendation does not make lowercase realm names illegal. + Words were added highlighting that the slash-separated components in + the X.500 style of realm names is consistent with existing RFC 1510 + based implementations, but that it conflicts with the general + recommendation of X.500 name representation specified in RFC 2253. + + Section 8, network transport, constants and defined values, from RFC + 1510 was moved to Section 7. Since RFC 1510, the definition of the + TCP transport for Kerberos messages was added, and the encryption and + checksum number assignments have been moved into a separate document. + + "Specification 2" in Section 8 of the current document changes the + required encryption and checksum methods to bring them in line with + the best current practices and to deprecate methods that are no + longer considered sufficiently strong. + + Two new sections, on IANA considerations and security considerations + were added. + + The pseudo-code has been removed from the appendix. The pseudo-code + was sometimes misinterpreted to limit implementation choices and in + RFC 1510, it was not always consistent with the words in the + specification. Effort was made to clear up any ambiguities in the + specification, rather than to rely on the pseudo-code. + + An appendix was added containing the complete ASN.1 module drawn from + the discussion in Section 5 of the current document. + +END NOTES + + (*TM) Project Athena, Athena, and Kerberos are trademarks of the + Massachusetts Institute of Technology (MIT). + + + +Neuman, et al. Standards Track [Page 133] + +RFC 4120 Kerberos V5 July 2005 + + +Normative References + + [RFC3961] Raeburn, K., "Encryption and Checksum + Specifications for Kerberos 5", RFC 3961, February + 2005. + + [RFC3962] Raeburn, K., "Advanced Encryption Standard (AES) + Encryption for Kerberos 5", RFC 3962, February + 2005. + + [ISO-646/ECMA-6] International Organization for Standardization, + "7-bit Coded Character Set for Information + Interchange", ISO/IEC 646:1991. + + [ISO-2022/ECMA-35] International Organization for Standardization, + "Character code structure and extension + techniques", ISO/IEC 2022:1994. + + [RFC1035] Mockapetris, P., "Domain names - implementation + and specification", STD 13, RFC 1035, November + 1987. + + [RFC2119] Bradner, S., "Key words for use in RFCs to + Indicate Requirement Levels", BCP 14, RFC 2119, + March 1997. + + [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for + Writing an IANA Considerations Section in RFCs", + BCP 26, RFC 2434, October 1998. + + [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS + RR for specifying the location of services (DNS + SRV)", RFC 2782, February 2000. + + [RFC2253] Wahl, M., Kille, S., and T. Howes, "Lightweight + Directory Access Protocol (v3): UTF-8 String + Representation of Distinguished Names", RFC 2253, + December 1997. + + [RFC3513] Hinden, R. and S. Deering, "Internet Protocol + Version 6 (IPv6) Addressing Architecture", RFC + 3513, April 2003. + + [X680] Abstract Syntax Notation One (ASN.1): + Specification of Basic Notation, ITU-T + Recommendation X.680 (1997) | ISO/IEC + International Standard 8824-1:1998. + + + + +Neuman, et al. Standards Track [Page 134] + +RFC 4120 Kerberos V5 July 2005 + + + [X690] ASN.1 encoding rules: Specification of Basic + Encoding Rules (BER), Canonical Encoding Rules + (CER) and Distinguished Encoding Rules (DER), + ITU-T Recommendation X.690 (1997)| ISO/IEC + International Standard 8825-1:1998. + +Informative References + + [ISO-8859] International Organization for Standardization, + "8-bit Single-byte Coded Graphic Character Sets -- + Latin Alphabet", ISO/IEC 8859. + + [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API + Mechanism", RFC 1964, June 1996. + + [DGT96] Don Davis, Daniel Geer, and Theodore Ts'o, + "Kerberos With Clocks Adrift: History, Protocols, + and Implementation", USENIX Computing Systems 9:1, + January 1996. + + [DS81] Dorothy E. Denning and Giovanni Maria Sacco, + "Time-stamps in Key Distribution Protocols," + Communications of the ACM, Vol. 24 (8), p. 533- + 536, August 1981. + + [KNT94] John T. Kohl, B. Clifford Neuman, and Theodore Y. + Ts'o, "The Evolution of the Kerberos + Authentication System". In Distributed Open + Systems, pages 78-94. IEEE Computer Society Press, + 1994. + + [MNSS87] S. P. Miller, B. C. Neuman, J. I. Schiller, and J. + H. Saltzer, Section E.2.1: Kerberos Authentication + and Authorization System, M.I.T. Project Athena, + Cambridge, Massachusetts, December 21, 1987. + + [NS78] Roger M. Needham and Michael D. Schroeder, "Using + Encryption for Authentication in Large Networks of + Computers," Communications of the ACM, Vol. 21 + (12), pp. 993-999, December 1978. + + [Neu93] B. Clifford Neuman, "Proxy-Based Authorization and + Accounting for Distributed Systems," in + Proceedings of the 13th International Conference + on Distributed Computing Systems, Pittsburgh, PA, + May 1993. + + + + + +Neuman, et al. Standards Track [Page 135] + +RFC 4120 Kerberos V5 July 2005 + + + [NT94] B. Clifford Neuman and Theodore Y. Ts'o, "An + Authentication Service for Computer Networks," + IEEE Communications Magazine, Vol. 32 (9), p. 33- + 38, September 1994. + + [Pat92] J. Pato, Using Pre-Authentication to Avoid + Password Guessing Attacks, Open Software + Foundation DCE Request for Comments 26 (December + 1992. + + [RFC1510] Kohl, J. and C. Neuman, "The Kerberos Network + Authentication Service (V5)", RFC 1510, September + 1993. + + [RFC4086] Eastlake, D., 3rd, Schiller, J., and S. Crocker, + "Randomness Requirements for Security", BCP 106, + RFC 4086, June 2005. + + [SNS88] J. G. Steiner, B. C. Neuman, and J. I. Schiller, + "Kerberos: An Authentication Service for Open + Network Systems," p. 191-202, Usenix Conference + Proceedings, Dallas, Texas, February 1988. + + [RFC4121] Zhu, L., Jaganathan, K., and S. Hartman, "The + Kerberos Version 5 Generic Security Service + Application Program Interface (GSS-API) Mechanism: + Version 2", RFC 4121, July 2005. + + + + + + + + + + + + + + + + + + + + + + + + +Neuman, et al. Standards Track [Page 136] + +RFC 4120 Kerberos V5 July 2005 + + +Authors' Addresses + + Clifford Neuman + Information Sciences Institute + University of Southern California + 4676 Admiralty Way + Marina del Rey, CA 90292, USA + + EMail: bcn@isi.edu + + + Tom Yu + Massachusetts Institute of Technology + 77 Massachusetts Avenue + Cambridge, MA 02139, USA + + EMail: tlyu@mit.edu + + + Sam Hartman + Massachusetts Institute of Technology + 77 Massachusetts Avenue + Cambridge, MA 02139, USA + + EMail: hartmans-ietf@mit.edu + + + Kenneth Raeburn + Massachusetts Institute of Technology + 77 Massachusetts Avenue + Cambridge, MA 02139, USA + + EMail: raeburn@mit.edu + + + + + + + + + + + + + + + + + + +Neuman, et al. Standards Track [Page 137] + +RFC 4120 Kerberos V5 July 2005 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2005). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at ietf- + ipr@ietf.org. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + +Neuman, et al. Standards Track [Page 138] + diff --git a/krb5-1-6/doc/krb5-protocol/rfc4121.txt b/krb5-1-6/doc/krb5-protocol/rfc4121.txt new file mode 100644 index 000000000..b4115143f --- /dev/null +++ b/krb5-1-6/doc/krb5-protocol/rfc4121.txt @@ -0,0 +1,1123 @@ + + + + + + +Network Working Group L. Zhu +Request for Comments: 4121 K. Jaganathan +Updates: 1964 Microsoft +Category: Standards Track S. Hartman + MIT + July 2005 + + + The Kerberos Version 5 + Generic Security Service Application Program Interface (GSS-API) + Mechanism: Version 2 + +Status of This Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2005). + +Abstract + + This document defines protocols, procedures, and conventions to be + employed by peers implementing the Generic Security Service + Application Program Interface (GSS-API) when using the Kerberos + Version 5 mechanism. + + RFC 1964 is updated and incremental changes are proposed in response + to recent developments such as the introduction of Kerberos + cryptosystem framework. These changes support the inclusion of new + cryptosystems, by defining new per-message tokens along with their + encryption and checksum algorithms based on the cryptosystem + profiles. + + + + + + + + + + + + + + +Zhu, et al. Standards Track [Page 1] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +Table of Contents + + 1. Introduction ....................................................2 + 2. Key Derivation for Per-Message Tokens ...........................4 + 3. Quality of Protection ...........................................4 + 4. Definitions and Token Formats ...................................5 + 4.1. Context Establishment Tokens ...............................5 + 4.1.1. Authenticator Checksum ..............................6 + 4.2. Per-Message Tokens .........................................9 + 4.2.1. Sequence Number .....................................9 + 4.2.2. Flags Field .........................................9 + 4.2.3. EC Field ...........................................10 + 4.2.4. Encryption and Checksum Operations .................10 + 4.2.5. RRC Field ..........................................11 + 4.2.6. Message Layouts ....................................12 + 4.3. Context Deletion Tokens ...................................13 + 4.4. Token Identifier Assignment Considerations ................13 + 5. Parameter Definitions ..........................................14 + 5.1. Minor Status Codes ........................................14 + 5.1.1. Non-Kerberos-specific Codes ........................14 + 5.1.2. Kerberos-specific Codes ............................15 + 5.2. Buffer Sizes ..............................................15 + 6. Backwards Compatibility Considerations .........................15 + 7. Security Considerations ........................................16 + 8. Acknowledgements................................................17 + 9. References .....................................................18 + 9.1. Normative References ......................................18 + 9.2. Informative References ....................................18 + +1. Introduction + + [RFC3961] defines a generic framework for describing encryption and + checksum types to be used with the Kerberos protocol and associated + protocols. + + [RFC1964] describes the GSS-API mechanism for Kerberos Version 5. It + defines the format of context establishment, per-message and context + deletion tokens, and uses algorithm identifiers for each cryptosystem + in per-message and context deletion tokens. + + The approach taken in this document obviates the need for algorithm + identifiers. This is accomplished by using the same encryption + algorithm, specified by the crypto profile [RFC3961] for the session + key or subkey that is created during context negotiation, and its + required checksum algorithm. Message layouts of the per-message + tokens are therefore revised to remove algorithm indicators and to + add extra information to support the generic crypto framework + [RFC3961]. + + + +Zhu, et al. Standards Track [Page 2] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + Tokens transferred between GSS-API peers for security context + establishment are also described in this document. The data elements + exchanged between a GSS-API endpoint implementation and the Kerberos + Key Distribution Center (KDC) [RFC4120] are not specific to GSS-API + usage and are therefore defined within [RFC4120] rather than this + specification. + + The new token formats specified in this document MUST be used with + all "newer" encryption types [RFC4120] and MAY be used with + encryption types that are not "newer", provided that the initiator + and acceptor know from the context establishment that they can both + process these new token formats. + + "Newer" encryption types are those which have been specified along + with or since the new Kerberos cryptosystem specification [RFC3961], + as defined in section 3.1.3 of [RFC4120]. The list of not-newer + encryption types is as follows [RFC3961]: + + Encryption Type Assigned Number + ---------------------------------------------- + des-cbc-crc 1 + des-cbc-md4 2 + des-cbc-md5 3 + des3-cbc-md5 5 + des3-cbc-sha1 7 + dsaWithSHA1-CmsOID 9 + md5WithRSAEncryption-CmsOID 10 + sha1WithRSAEncryption-CmsOID 11 + rc2CBC-EnvOID 12 + rsaEncryption-EnvOID 13 + rsaES-OAEP-ENV-OID 14 + des-ede3-cbc-Env-OID 15 + des3-cbc-sha1-kd 16 + rc4-hmac 23 + + Conventions used in this document + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in [RFC2119]. + + The term "little-endian order" is used for brevity to refer to the + least-significant-octet-first encoding, while the term "big-endian + order" is for the most-significant-octet-first encoding. + + + + + + + +Zhu, et al. Standards Track [Page 3] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +2. Key Derivation for Per-Message Tokens + + To limit the exposure of a given key, [RFC3961] adopted "one-way" + "entropy-preserving" derived keys, from a base key or protocol key, + for different purposes or key usages. + + This document defines four key usage values below that are used to + derive a specific key for signing and sealing messages from the + session key or subkey [RFC4120] created during the context + establishment. + + Name Value + ------------------------------------- + KG-USAGE-ACCEPTOR-SEAL 22 + KG-USAGE-ACCEPTOR-SIGN 23 + KG-USAGE-INITIATOR-SEAL 24 + KG-USAGE-INITIATOR-SIGN 25 + + When the sender is the context acceptor, KG-USAGE-ACCEPTOR-SIGN is + used as the usage number in the key derivation function for deriving + keys to be used in MIC tokens (as defined in section 4.2.6.1). + KG-USAGE-ACCEPTOR-SEAL is used for Wrap tokens (as defined in section + 4.2.6.2). Similarly, when the sender is the context initiator, + KG-USAGE-INITIATOR-SIGN is used as the usage number in the key + derivation function for MIC tokens, while KG-USAGE-INITIATOR-SEAL is + used for Wrap tokens. Even if the Wrap token does not provide for + confidentiality, the same usage values specified above are used. + + During the context initiation and acceptance sequence, the acceptor + MAY assert a subkey in the AP-REP message. If the acceptor asserts a + subkey, the base key is the acceptor-asserted subkey and subsequent + per-message tokens MUST be flagged with "AcceptorSubkey", as + described in section 4.2.2. Otherwise, if the initiator asserts a + subkey in the AP-REQ message, the base key is this subkey; if the + initiator does not assert a subkey, the base key is the session key + in the service ticket. + +3. Quality of Protection + + The GSS-API specification [RFC2743] provides Quality of Protection + (QOP) values that can be used by applications to request a certain + type of encryption or signing. A zero QOP value is used to indicate + the "default" protection; applications that do not use the default + QOP are not guaranteed to be portable across implementations, or even + to inter-operate with different deployment configurations of the same + implementation. Using a different algorithm than the one for which + the key is defined may not be appropriate. Therefore, when the new + method in this document is used, the QOP value is ignored. + + + +Zhu, et al. Standards Track [Page 4] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + The encryption and checksum algorithms in per-message tokens are now + implicitly defined by the algorithms associated with the session key + or subkey. Therefore, algorithm identifiers as described in + [RFC1964] are no longer needed and are removed from the new token + headers. + +4. Definitions and Token Formats + + This section provides terms and definitions, as well as descriptions + for tokens specific to the Kerberos Version 5 GSS-API mechanism. + +4.1. Context Establishment Tokens + + All context establishment tokens emitted by the Kerberos Version 5 + GSS-API mechanism SHALL have the framing described in section 3.1 of + [RFC2743], as illustrated by the following pseudo-ASN.1 structures: + + GSS-API DEFINITIONS ::= + + BEGIN + + MechType ::= OBJECT IDENTIFIER + -- representing Kerberos V5 mechanism + + GSSAPI-Token ::= + -- option indication (delegation, etc.) indicated within + -- mechanism-specific token + [APPLICATION 0] IMPLICIT SEQUENCE { + thisMech MechType, + innerToken ANY DEFINED BY thisMech + -- contents mechanism-specific + -- ASN.1 structure not required + } + + END + + The innerToken field starts with a two-octet token-identifier + (TOK_ID) expressed in big-endian order, followed by a Kerberos + message. + + Following are the TOK_ID values used in the context establishment + tokens: + + Token TOK_ID Value in Hex + ----------------------------------------- + KRB_AP_REQ 01 00 + KRB_AP_REP 02 00 + KRB_ERROR 03 00 + + + +Zhu, et al. Standards Track [Page 5] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + Where Kerberos message KRB_AP_REQUEST, KRB_AP_REPLY, and KRB_ERROR + are defined in [RFC4120]. + + If an unknown token identifier (TOK_ID) is received in the initial + context establishment token, the receiver MUST return + GSS_S_CONTINUE_NEEDED major status, and the returned output token + MUST contain a KRB_ERROR message with the error code + KRB_AP_ERR_MSG_TYPE [RFC4120]. + +4.1.1. Authenticator Checksum + + The authenticator in the KRB_AP_REQ message MUST include the optional + sequence number and the checksum field. The checksum field is used + to convey service flags, channel bindings, and optional delegation + information. + + The checksum type MUST be 0x8003. When delegation is used, a + ticket-granting ticket will be transferred in a KRB_CRED message. + This ticket SHOULD have its forwardable flag set. The EncryptedData + field of the KRB_CRED message [RFC4120] MUST be encrypted in the + session key of the ticket used to authenticate the context. + + The authenticator checksum field SHALL have the following format: + + Octet Name Description + ----------------------------------------------------------------- + 0..3 Lgth Number of octets in Bnd field; Represented + in little-endian order; Currently contains + hex value 10 00 00 00 (16). + 4..19 Bnd Channel binding information, as described in + section 4.1.1.2. + 20..23 Flags Four-octet context-establishment flags in + little-endian order as described in section + 4.1.1.1. + 24..25 DlgOpt The delegation option identifier (=1) in + little-endian order [optional]. This field + and the next two fields are present if and + only if GSS_C_DELEG_FLAG is set as described + in section 4.1.1.1. + 26..27 Dlgth The length of the Deleg field in + little-endian order [optional]. + 28..(n-1) Deleg A KRB_CRED message (n = Dlgth + 28) + [optional]. + n..last Exts Extensions [optional]. + + The length of the checksum field MUST be at least 24 octets when + GSS_C_DELEG_FLAG is not set (as described in section 4.1.1.1), and at + least 28 octets plus Dlgth octets when GSS_C_DELEG_FLAG is set. When + + + +Zhu, et al. Standards Track [Page 6] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + GSS_C_DELEG_FLAG is set, the DlgOpt, Dlgth, and Deleg fields of the + checksum data MUST immediately follow the Flags field. The optional + trailing octets (namely the "Exts" field) facilitate future + extensions to this mechanism. When delegation is not used, but the + Exts field is present, the Exts field starts at octet 24 (DlgOpt, + Dlgth and Deleg are absent). + + Initiators that do not support the extensions MUST NOT include more + than 24 octets in the checksum field (when GSS_C_DELEG_FLAG is not + set) or more than 28 octets plus the KRB_CRED in the Deleg field + (when GSS_C_DELEG_FLAG is set). Acceptors that do not understand the + + Extensions MUST ignore any octets past the Deleg field of the + checksum data (when GSS_C_DELEG_FLAG is set) or past the Flags field + of the checksum data (when GSS_C_DELEG_FLAG is not set). + +4.1.1.1. Checksum Flags Field + + The checksum "Flags" field is used to convey service options or + extension negotiation information. + + The following context establishment flags are defined in [RFC2744]. + + Flag Name Value + --------------------------------- + GSS_C_DELEG_FLAG 1 + GSS_C_MUTUAL_FLAG 2 + GSS_C_REPLAY_FLAG 4 + GSS_C_SEQUENCE_FLAG 8 + GSS_C_CONF_FLAG 16 + GSS_C_INTEG_FLAG 32 + + Context establishment flags are exposed to the calling application. + If the calling application desires a particular service option, then + it requests that option via GSS_Init_sec_context() [RFC2743]. If the + corresponding return state values [RFC2743] indicate that any of the + above optional context level services will be active on the context, + the corresponding flag values in the table above MUST be set in the + checksum Flags field. + + Flag values 4096..524288 (2^12, 2^13, ..., 2^19) are reserved for use + with legacy vendor-specific extensions to this mechanism. + + + + + + + + + +Zhu, et al. Standards Track [Page 7] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + All other flag values not specified herein are reserved for future + use. Future revisions of this mechanism may use these reserved flags + and may rely on implementations of this version to not use such flags + in order to properly negotiate mechanism versions. Undefined flag + values MUST be cleared by the sender, and unknown flags MUST be + ignored by the receiver. + +4.1.1.2. Channel Binding Information + + These tags are intended to be used to identify the particular + communications channel for which the GSS-API security context + establishment tokens are intended, thus limiting the scope within + which an intercepted context establishment token can be reused by an + attacker (see [RFC2743], section 1.1.6). + + When using C language bindings, channel bindings are communicated to + the GSS-API using the following structure [RFC2744]: + + typedef struct gss_channel_bindings_struct { + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; + } *gss_channel_bindings_t; + + The member fields and constants used for different address types are + defined in [RFC2744]. + + The "Bnd" field contains the MD5 hash of channel bindings, taken over + all non-null components of bindings, in order of declaration. + Integer fields within channel bindings are represented in little- + endian order for the purposes of the MD5 calculation. + + In computing the contents of the Bnd field, the following detailed + points apply: + + (1) For purposes of MD5 hash computation, each integer field and + input length field SHALL be formatted into four octets, using + little-endian octet ordering. + + (2) All input length fields within gss_buffer_desc elements of a + gss_channel_bindings_struct even those which are zero-valued, + SHALL be included in the hash calculation. The value elements of + gss_buffer_desc elements SHALL be dereferenced, and the resulting + data SHALL be included within the hash computation, only for the + case of gss_buffer_desc elements having non-zero length + specifiers. + + + +Zhu, et al. Standards Track [Page 8] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + (3) If the caller passes the value GSS_C_NO_BINDINGS instead of a + valid channel binding structure, the Bnd field SHALL be set to 16 + zero-valued octets. + + If the caller to GSS_Accept_sec_context [RFC2743] passes in + GSS_C_NO_CHANNEL_BINDINGS [RFC2744] as the channel bindings, then the + acceptor MAY ignore any channel bindings supplied by the initiator, + returning success even if the initiator did pass in channel bindings. + + If the application supplies, in the channel bindings, a buffer with a + length field larger than 4294967295 (2^32 - 1), the implementation of + this mechanism MAY choose to reject the channel bindings altogether, + using major status GSS_S_BAD_BINDINGS [RFC2743]. In any case, the + size of channel-binding data buffers that can be used (interoperable, + without extensions) with this specification is limited to 4294967295 + octets. + +4.2. Per-Message Tokens + + Two classes of tokens are defined in this section: (1) "MIC" tokens, + emitted by calls to GSS_GetMIC() and consumed by calls to + GSS_VerifyMIC(), and (2) "Wrap" tokens, emitted by calls to + GSS_Wrap() and consumed by calls to GSS_Unwrap(). + + These new per-message tokens do not include the generic GSS-API token + framing used by the context establishment tokens. These new tokens + are designed to be used with newer crypto systems that can have + variable-size checksums. + +4.2.1. Sequence Number + + To distinguish intentionally-repeated messages from maliciously- + replayed ones, per-message tokens contain a sequence number field, + which is a 64 bit integer expressed in big-endian order. After + sending a GSS_GetMIC() or GSS_Wrap() token, the sender's sequence + numbers SHALL be incremented by one. + +4.2.2. Flags Field + + The "Flags" field is a one-octet integer used to indicate a set of + attributes for the protected message. For example, one flag is + allocated as the direction-indicator, thus preventing the acceptance + of the same message sent back in the reverse direction by an + adversary. + + + + + + + +Zhu, et al. Standards Track [Page 9] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + The meanings of bits in this field (the least significant bit is bit + 0) are as follows: + + Bit Name Description + -------------------------------------------------------------- + 0 SentByAcceptor When set, this flag indicates the sender + is the context acceptor. When not set, + it indicates the sender is the context + initiator. + 1 Sealed When set in Wrap tokens, this flag + indicates confidentiality is provided + for. It SHALL NOT be set in MIC tokens. + 2 AcceptorSubkey A subkey asserted by the context acceptor + is used to protect the message. + + The rest of available bits are reserved for future use and MUST be + cleared. The receiver MUST ignore unknown flags. + +4.2.3. EC Field + + The "EC" (Extra Count) field is a two-octet integer field expressed + in big-endian order. + + In Wrap tokens with confidentiality, the EC field SHALL be used to + encode the number of octets in the filler, as described in section + 4.2.4. + + In Wrap tokens without confidentiality, the EC field SHALL be used to + encode the number of octets in the trailing checksum, as described in + section 4.2.4. + +4.2.4. Encryption and Checksum Operations + + The encryption algorithms defined by the crypto profiles provide for + integrity protection [RFC3961]. Therefore, no separate checksum is + needed. + + The result of decryption can be longer than the original plaintext + [RFC3961] and the extra trailing octets are called "crypto-system + residue" in this document. However, given the size of any plaintext + data, one can always find a (possibly larger) size, such that when + padding the to-be-encrypted text to that size, there will be no + crypto-system residue added [RFC3961]. + + In Wrap tokens that provide for confidentiality, the first 16 octets + of the Wrap token (the "header", as defined in section 4.2.6), SHALL + be appended to the plaintext data before encryption. Filler octets + MAY be inserted between the plaintext data and the "header." The + + + +Zhu, et al. Standards Track [Page 10] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + values and size of the filler octets are chosen by implementations, + such that there SHALL be no crypto-system residue present after the + decryption. The resulting Wrap token is {"header" | + encrypt(plaintext-data | filler | "header")}, where encrypt() is the + encryption operation (which provides for integrity protection) + defined in the crypto profile [RFC3961], and the RRC field (as + defined in section 4.2.5) in the to-be-encrypted header contains the + hex value 00 00. + + In Wrap tokens that do not provide for confidentiality, the checksum + SHALL be calculated first over the to-be-signed plaintext data, and + then over the first 16 octets of the Wrap token (the "header", as + defined in section 4.2.6). Both the EC field and the RRC field in + the token header SHALL be filled with zeroes for the purpose of + calculating the checksum. The resulting Wrap token is {"header" | + plaintext-data | get_mic(plaintext-data | "header")}, where get_mic() + is the checksum operation for the required checksum mechanism of the + chosen encryption mechanism defined in the crypto profile [RFC3961]. + + The parameters for the key and the cipher-state in the encrypt() and + get_mic() operations have been omitted for brevity. + + For MIC tokens, the checksum SHALL be calculated as follows: the + checksum operation is calculated first over the to-be-signed + plaintext data, and then over the first 16 octets of the MIC token, + where the checksum mechanism is the required checksum mechanism of + the chosen encryption mechanism defined in the crypto profile + [RFC3961]. + + The resulting Wrap and MIC tokens bind the data to the token header, + including the sequence number and the direction indicator. + +4.2.5. RRC Field + + The "RRC" (Right Rotation Count) field in Wrap tokens is added to + allow the data to be encrypted in-place by existing SSPI (Security + Service Provider Interface) [SSPI] applications that do not provide + an additional buffer for the trailer (the cipher text after the in- + place-encrypted data) in addition to the buffer for the header (the + cipher text before the in-place-encrypted data). Excluding the first + 16 octets of the token header, the resulting Wrap token in the + previous section is rotated to the right by "RRC" octets. The net + result is that "RRC" octets of trailing octets are moved toward the + header. + + Consider the following as an example of this rotation operation: + Assume that the RRC value is 3 and the token before the rotation is + {"header" | aa | bb | cc | dd | ee | ff | gg | hh}. The token after + + + +Zhu, et al. Standards Track [Page 11] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + rotation would be {"header" | ff | gg | hh | aa | bb | cc | dd | ee + }, where {aa | bb | cc |...| hh} would be used to indicate the octet + sequence. + + The RRC field is expressed as a two-octet integer in big-endian + order. + + The rotation count value is chosen by the sender based on + implementation details. The receiver MUST be able to interpret all + possible rotation count values, including rotation counts greater + than the length of the token. + +4.2.6. Message Layouts + + Per-message tokens start with a two-octet token identifier (TOK_ID) + field, expressed in big-endian order. These tokens are defined + separately in the following sub-sections. + +4.2.6.1. MIC Tokens + + Use of the GSS_GetMIC() call yields a token (referred as the MIC + token in this document), separate from the user data being protected, + which can be used to verify the integrity of that data as received. + The token has the following format: + + Octet no Name Description + -------------------------------------------------------------- + 0..1 TOK_ID Identification field. Tokens emitted by + GSS_GetMIC() contain the hex value 04 04 + expressed in big-endian order in this + field. + 2 Flags Attributes field, as described in section + 4.2.2. + 3..7 Filler Contains five octets of hex value FF. + 8..15 SND_SEQ Sequence number field in clear text, + expressed in big-endian order. + 16..last SGN_CKSUM Checksum of the "to-be-signed" data and + octet 0..15, as described in section 4.2.4. + + The Filler field is included in the checksum calculation for + simplicity. + + + + + + + + + + +Zhu, et al. Standards Track [Page 12] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +4.2.6.2. Wrap Tokens + + Use of the GSS_Wrap() call yields a token (referred as the Wrap token + in this document), which consists of a descriptive header, followed + by a body portion that contains either the input user data in + plaintext concatenated with the checksum, or the input user data + encrypted. The GSS_Wrap() token SHALL have the following format: + + Octet no Name Description + -------------------------------------------------------------- + 0..1 TOK_ID Identification field. Tokens emitted by + GSS_Wrap() contain the hex value 05 04 + expressed in big-endian order in this + field. + 2 Flags Attributes field, as described in section + 4.2.2. + 3 Filler Contains the hex value FF. + 4..5 EC Contains the "extra count" field, in big- + endian order as described in section 4.2.3. + 6..7 RRC Contains the "right rotation count" in big- + endian order, as described in section + 4.2.5. + 8..15 SND_SEQ Sequence number field in clear text, + expressed in big-endian order. + 16..last Data Encrypted data for Wrap tokens with + confidentiality, or plaintext data followed + by the checksum for Wrap tokens without + confidentiality, as described in section + 4.2.4. + +4.3. Context Deletion Tokens + + Context deletion tokens are empty in this mechanism. Both peers to a + security context invoke GSS_Delete_sec_context() [RFC2743] + independently, passing a null output_context_token buffer to indicate + that no context_token is required. Implementations of + GSS_Delete_sec_context() should delete relevant locally-stored + context information. + +4.4. Token Identifier Assignment Considerations + + Token identifiers (TOK_ID) from 0x60 0x00 through 0x60 0xFF inclusive + are reserved and SHALL NOT be assigned. Thus, by examining the first + two octets of a token, one can tell unambiguously if it is wrapped + with the generic GSS-API token framing. + + + + + + +Zhu, et al. Standards Track [Page 13] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +5. Parameter Definitions + + This section defines parameter values used by the Kerberos V5 GSS-API + mechanism. It defines interface elements that support portability, + and assumes use of C language bindings per [RFC2744]. + +5.1. Minor Status Codes + + This section recommends common symbolic names for minor_status values + to be returned by the Kerberos V5 GSS-API mechanism. Use of these + definitions will enable independent implementers to enhance + application portability across different implementations of the + mechanism defined in this specification. (In all cases, + implementations of GSS_Display_status() will enable callers to + convert minor_status indicators to text representations.) Each + implementation should make available, through include files or other + means, a facility to translate these symbolic names into the concrete + values that a particular GSS-API implementation uses to represent the + minor_status values specified in this section. + + This list may grow over time and the need for additional minor_status + codes, specific to particular implementations, may arise. However, + it is recommended that implementations should return a minor_status + value as defined on a mechanism-wide basis within this section when + that code accurately represents reportable status rather than using a + separate, implementation-defined code. + +5.1.1. Non-Kerberos-specific Codes + + GSS_KRB5_S_G_BAD_SERVICE_NAME + /* "No @ in SERVICE-NAME name string" */ + GSS_KRB5_S_G_BAD_STRING_UID + /* "STRING-UID-NAME contains nondigits" */ + GSS_KRB5_S_G_NOUSER + /* "UID does not resolve to username" */ + GSS_KRB5_S_G_VALIDATE_FAILED + /* "Validation error" */ + GSS_KRB5_S_G_BUFFER_ALLOC + /* "Couldn't allocate gss_buffer_t data" */ + GSS_KRB5_S_G_BAD_MSG_CTX + /* "Message context invalid" */ + GSS_KRB5_S_G_WRONG_SIZE + /* "Buffer is the wrong size" */ + GSS_KRB5_S_G_BAD_USAGE + /* "Credential usage type is unknown" */ + GSS_KRB5_S_G_UNKNOWN_QOP + /* "Unknown quality of protection specified" */ + + + + +Zhu, et al. Standards Track [Page 14] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +5.1.2. Kerberos-specific Codes + + GSS_KRB5_S_KG_CCACHE_NOMATCH + /* "Client principal in credentials does not match + specified name" */ + GSS_KRB5_S_KG_KEYTAB_NOMATCH + /* "No key available for specified service + principal" */ + GSS_KRB5_S_KG_TGT_MISSING + /* "No Kerberos ticket-granting ticket available" */ + GSS_KRB5_S_KG_NO_SUBKEY + /* "Authenticator has no subkey" */ + GSS_KRB5_S_KG_CONTEXT_ESTABLISHED + /* "Context is already fully established" */ + GSS_KRB5_S_KG_BAD_SIGN_TYPE + /* "Unknown signature type in token" */ + GSS_KRB5_S_KG_BAD_LENGTH + /* "Invalid field length in token" */ + GSS_KRB5_S_KG_CTX_INCOMPLETE + /* "Attempt to use incomplete security context" */ + +5.2. Buffer Sizes + + All implementations of this specification MUST be capable of + accepting buffers of at least 16K octets as input to GSS_GetMIC(), + GSS_VerifyMIC(), and GSS_Wrap(). They MUST also be capable of + accepting the output_token generated by GSS_Wrap() for a 16K octet + input buffer as input to GSS_Unwrap(). Implementations SHOULD + support 64K octet input buffers, and MAY support even larger input + buffer sizes. + +6. Backwards Compatibility Considerations + + The new token formats defined in this document will only be + recognized by new implementations. To address this, implementations + can always use the explicit sign or seal algorithm in [RFC1964] when + the key type corresponds to not "newer" enctypes. As an alternative, + one might retry sending the message with the sign or seal algorithm + explicitly defined as in [RFC1964]. However, this would require + either the use of a mechanism such as [RFC2478] to securely negotiate + the method, or the use of an out-of-band mechanism to choose the + appropriate mechanism. For this reason, it is RECOMMENDED that the + new token formats defined in this document SHOULD be used only if + both peers are known to support the new mechanism during context + negotiation because of, for example, the use of "new" enctypes. + + + + + + +Zhu, et al. Standards Track [Page 15] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + + GSS_Unwrap() or GSS_VerifyMIC() can process a message token as + follows: it can look at the first octet of the token header, and if + it is 0x60, then the token must carry the generic GSS-API pseudo + ASN.1 framing. Otherwise, the first two octets of the token contain + the TOK_ID that uniquely identify the token message format. + +7. Security Considerations + + Channel bindings are validated by the acceptor. The acceptor can + ignore the channel bindings restriction supplied by the initiator and + carried in the authenticator checksum, if (1) channel bindings are + not used by GSS_Accept_sec_context [RFC2743], and (2) the acceptor + does not prove to the initiator that it has the same channel bindings + as the initiator (even if the client requested mutual + authentication). This limitation should be considered by designers + of applications that would use channel bindings, whether to limit the + use of GSS-API contexts to nodes with specific network addresses, to + authenticate other established, secure channels using Kerberos + Version 5, or for any other purpose. + + Session key types are selected by the KDC. Under the current + mechanism, no negotiation of algorithm types occurs, so server-side + (acceptor) implementations cannot request that clients not use + algorithm types not understood by the server. However, + administrators can control what enctypes can be used for session keys + for this mechanism by controlling the set of the ticket session key + enctypes which the KDC is willing to use in tickets for a given + acceptor principal. Therefore, the KDC could be given the task of + limiting session keys for a given service to types actually supported + by the Kerberos and GSSAPI software on the server. This has a + drawback for cases in which a service principal name is used for both + GSSAPI-based and non-GSSAPI-based communication (most notably the + "host" service key), if the GSSAPI implementation does not understand + (for example) AES [RFC3962], but the Kerberos implementation does. + This means that AES session keys cannot be issued for that service + principal, which keeps the protection of non-GSSAPI services weaker + than necessary. KDC administrators desiring to limit the session key + types to support interoperability with such GSSAPI implementations + should carefully weigh the reduction in protection offered by such + mechanisms against the benefits of interoperability. + + + + + + + + + + + +Zhu, et al. Standards Track [Page 16] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +8. Acknowledgements + + Ken Raeburn and Nicolas Williams corrected many of our errors in the + use of generic profiles and were instrumental in the creation of this + document. + + The text for security considerations was contributed by Nicolas + Williams and Ken Raeburn. + + Sam Hartman and Ken Raeburn suggested the "floating trailer" idea, + namely the encoding of the RRC field. + + Sam Hartman and Nicolas Williams recommended the replacing our + earlier key derivation function for directional keys with different + key usage numbers for each direction as well as retaining the + directional bit for maximum compatibility. + + Paul Leach provided numerous suggestions and comments. + + Scott Field, Richard Ward, Dan Simon, Kevin Damour, and Simon + Josefsson also provided valuable inputs on this document. + + Jeffrey Hutzelman provided comments and clarifications for the text + related to the channel bindings. + + Jeffrey Hutzelman and Russ Housley suggested many editorial changes. + + Luke Howard provided implementations of this document for the Heimdal + code base, and helped inter-operability testing with the Microsoft + code base, together with Love Hornquist Astrand. These experiments + formed the basis of this document. + + Martin Rex provided suggestions of TOK_ID assignment recommendations, + thus the token tagging in this document is unambiguous if the token + is wrapped with the pseudo ASN.1 header. + + John Linn wrote the original Kerberos Version 5 mechanism + specification [RFC1964], of which some text has been retained. + + + + + + + + + + + + + +Zhu, et al. Standards Track [Page 17] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +9. References + +9.1. Normative References + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC2743] Linn, J., "Generic Security Service Application Program + Interface Version 2, Update 1", RFC 2743, January 2000. + + [RFC2744] Wray, J., "Generic Security Service API Version 2: + C-bindings", RFC 2744, January 2000. + + [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC + 1964, June 1996. + + [RFC3961] Raeburn, K., "Encryption and Checksum Specifications for + Kerberos 5", RFC 3961, February 2005. + + [RFC4120] Neuman, C., Yu, T., Hartman, S., and K. Raeburn, "The + Kerberos Network Authentication Service (V5)", RFC 4120, + July 2005. + +9.2. Informative References + + [SSPI] Leach, P., "Security Service Provider Interface", + Microsoft Developer Network (MSDN), April 2003. + + [RFC3962] Raeburn, K., "Advanced Encryption Standard (AES) + Encryption for Kerberos 5", RFC 3962, February 2005. + + [RFC2478] Baize, E. and D. Pinkas, "The Simple and Protected GSS-API + Negotiation Mechanism", RFC 2478, December 1998. + + + + + + + + + + + + + + + + + + +Zhu, et al. Standards Track [Page 18] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +Authors' Addresses + + Larry Zhu + One Microsoft Way + Redmond, WA 98052 - USA + + EMail: LZhu@microsoft.com + + + Karthik Jaganathan + One Microsoft Way + Redmond, WA 98052 - USA + + EMail: karthikj@microsoft.com + + + Sam Hartman + Massachusetts Institute of Technology + 77 Massachusetts Avenue + Cambridge, MA 02139 - USA + + EMail: hartmans-ietf@mit.edu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Zhu, et al. Standards Track [Page 19] + +RFC 4121 Kerberos Version 5 GSS-API July 2005 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2005). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at ietf- + ipr@ietf.org. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + +Zhu, et al. Standards Track [Page 20] + diff --git a/krb5-1-6/doc/krb5conf.texinfo b/krb5-1-6/doc/krb5conf.texinfo new file mode 100644 index 000000000..09825524f --- /dev/null +++ b/krb5-1-6/doc/krb5conf.texinfo @@ -0,0 +1,83 @@ +The @code{krb5.conf} file contains Kerberos configuration information, +including the locations of KDCs and admin servers for the Kerberos +realms of interest, defaults for the current realm and for Kerberos +applications, and mappings of hostnames onto Kerberos realms. Normally, +you should install your @code{krb5.conf} file in the directory +@code{/etc}. You can override the default location by setting the +environment variable @samp{KRB5_CONFIG}. + +The @code{krb5.conf} file is set up in the style of a Windows INI file. +Sections are headed by the section name, in square brackets. Each +section may contain zero or more relations, of the form: + +@smallexample +foo = bar +@end smallexample + +@noindent +or + +@smallexample +@group +fubar = @{ + foo = bar + baz = quux +@} +@end group +@end smallexample + +Placing a `*' at the end of a line indicates that this is the +@dfn{final} value for the tag. This means that neither the remainder +of this configuration file nor any other configuration file will be +checked for any other values for this tag. + +For example, if you have the following lines: + +@smallexample +foo = bar* +foo = baz +@end smallexample + +then the second value of foo (baz) would never be read. + +The @code{krb5.conf} file may contain any or all of the following +sections: + +@table @b +@itemx libdefaults +Contains default values used by the Kerberos V5 library. + +@itemx login +Contains default values used by the Kerberos V5 login program. + +@itemx appdefaults +Contains default values that can be used by Kerberos V5 applications. + +@itemx realms +Contains subsections keyed by Kerberos realm names. Each subsection +describes realm-specific information, including where to find the +Kerberos servers for that realm. + +@itemx domain_realm +Contains relations which map domain names and subdomains onto Kerberos +realm names. This is used by programs to determine what realm a host +should be in, given its fully qualified domain name. + +@itemx logging +Contains relations which determine how Kerberos programs are to perform +logging. + +@itemx capaths +Contains the authentication paths used with direct (nonhierarchical) +cross-realm authentication. Entries in this section are used by the +client to determine the intermediate realms which may be used in +cross-realm authentication. It is also used by the end-service when +checking the transited field for trusted intermediate realms. + +@ignore +this doesn't seem to be used +@itemx kdc +For a KDC, may contain the location of the kdc.conf file. +@end ignore + +@end table diff --git a/krb5-1-6/doc/man2html b/krb5-1-6/doc/man2html new file mode 100755 index 000000000..ea45686b8 --- /dev/null +++ b/krb5-1-6/doc/man2html @@ -0,0 +1,608 @@ +#!/usr/athena/bin/perl +#!/usr/local/bin/perl +##---------------------------------------------------------------------------## +## File: +## @(#) man2html 1.2 97/08/12 12:57:30 @(#) +## Author: +## Earl Hood, ehood@medusa.acs.uci.edu +## Description: +## man2html is a Perl program to convert formatted nroff output +## to HTML. +## +## Recommend command-line options based on platform: +## +## Platform Options +## --------------------------------------------------------------------- +## c2mp +## hp9000s700/800 -leftm 1 -topm 8 +## sun4 -sun +## --------------------------------------------------------------------- +## +##---------------------------------------------------------------------------## +## Copyright (C) 1995-1997 Earl Hood, ehood@medusa.acs.uci.edu +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +## 02111-1307, USA +##---------------------------------------------------------------------------## + +package Man2Html; + +use Getopt::Long; + +($PROG = $0) =~ s/.*\///; +$VERSION = "3.0.1"; + +## Input and outputs filehandles +$InFH = \*STDIN unless $InFH; +$OutFH = \*STDOUT unless $OutFH; + +## Backspace character: Used in overstriking detection +*bs = \"\b"; + +## Hash of section titles and their HTML tag wrapper. +## This list allows customization of what HTML tag is used for +## a given section head. +## +## The section title can be a regular expression. Therefore, one must +## be careful about quoting special characters. +## +%SectionHead = ( + + '\S.*OPTIONS.*' => '

', + 'AUTHORS?' => '

', + 'BUGS' => '

', + 'COMPATIBILITY' => '

', + 'DEPENDENCIES' => '

', + 'DESCRIPTION' => '

', + 'DIAGNOSTICS' => '

', + 'ENVIRONMENT' => '

', + 'ERRORS' => '

', + 'EXAMPLES' => '

', + 'EXTERNAL INFLUENCES' => '

', + 'FILES' => '

', + 'LIMITATIONS' => '

', + 'NAME' => '

', + 'NOTES?' => '

', + 'OPTIONS' => '

', + 'REFERENCES' => '

', + 'RETURN VALUE' => '

', + 'SECTION.*:' => '

', + 'SEE ALSO' => '

', + 'STANDARDS CONFORMANCE' => '

', + 'STYLE CONVENTION' => '

', + 'SYNOPSIS' => '

', + 'SYNTAX' => '

', + 'WARNINGS' => '

', + '\s+Section.*:' => '

', + +); + +## Fallback tag if above is not found +$HeadFallback = '

'; + +## Other gobals + +$Bare = 0; # Skip printing HTML head/foot flag +$BTag = 'B'; # Overstrike tag +$CgiUrl = ''; # CGI URL expression +$Compress = 0; # Do blank line compression flag +$K = 0; # Do keyword search processing flag +$NoDepage = 0; # Do not strip page information +$NoHeads = 0; # Do no header detection flag +$SeeAlso = 0; # Do only SEE ALSO xrefs flag +$Solaris = 0; # Solaris keyword search processing flag +$Sun = 0; # Headers not overstriken flag +$Title = ''; # Title +$UTag = 'I'; # Underline tag +$ftsz = 7; # Bottome margin size +$hdsz = 7; # Top margin size +$leftm = ''; # Left margin pad +$leftmsz = 0; # Left margin size +$pgsz = 66; # Size of page size +$txsz = 52; # Text body length size + +############################################################################# +## Main Block +############################################################################# +{ + if (get_cli_opts()) { + if ($K) { + man_k(); + } else { + do_it(); + } + } else { + usage(); + } +} + +############################################################################# +## Subroutines +############################################################################# + +sub do_it { + + ## Define while loop and then eval it when used. The reason + ## is to avoid the regular expression reevaulation in the + ## section head detection code. + + $doitcode =<<'EndOfDoItCode'; + + my($line, $tmp, $i, $head, $preindent, $see_also, $do); + + $see_also = !$SeeAlso; + print $OutFH "\n"; + LOOP: while(!eof($InFH)) { + $blank = 0; + for ($i=0; $i < $hdsz; $i++) { + last LOOP unless defined($_ = <$InFH>); + } + for ($i=0; $i < $txsz; $i++) { + last LOOP unless defined($_ = <$InFH>); + + ## Check if compress consecutive blank lines + if ($Compress and !/\S/) { + if ($blank) { next; } else { $blank = 1; } + } else { + $blank = 0; + } + + ## Try to check if line space is needed at page boundaries ## + if (!$NoDepage && ($i==0 || $i==($txsz-1)) && !/^\s*$/) { + /^(\s*)/; $tmp = length($1); + if ($do) { + if ($tmp < $preindent) { print $OutFH "\n"; } + } else { + $do = 1; + } + $preindent = $tmp; + } else { + $do = 0; $preindent = 0; + } + + ## Interpret line + $line = $_; + entitize(\$_); # Convert [$<>] to entity references + + ## Check for 'SEE ALSO' link only + if (!$see_also && $CgiUrl && $SeeAlso) { + ($tmp = $line) =~ s/.\010//go; + if ($tmp =~ /^\s*SEE\s+ALSO\s*$/o) { $see_also = 1; } + else { $see_also = 0; } + } + + ## Create anchor links for manpage references + s/((((.\010)+)?[\+_\.\w-])+\(((.\010)+)? + \d((.\010)+)?\w?\)) + /make_xref($1) + /geox if $see_also; + + ## Emphasize underlined words + # s/((_\010[^_])+[\.\(\)_]?(_\010[^_])+\)?)/emphasize($1)/oge; + # s/((_\010[^_])+([\.\(\)_]?(_\010[^_])+)?)/emphasize($1)/oge; + # + # The previous expressions were trying to be clever about + # detecting underlined text which contain non-alphanumeric + # characters. nroff will not underline non-alphanumeric + # characters in an underlined phrase, and the above was trying + # to detect that. It does not work all the time, and it + # screws up other text, so a simplified expression is used. + + s/((_\010[^_])+)/emphasize($1)/oge; + + $secth = 0; + ## Check for strong text and headings + if ($Sun || /.\010./o) { + if (!$NoHeads) { + $line =~ s/.\010//go; + $tmp = $HeadFallback; +EndOfDoItCode + + ## Create switch statement for detecting a heading + ## + $doitcode .= "HEADSW: {\n"; + foreach $head (keys %SectionHead) { + $doitcode .= join("", "\$tmp = '$SectionHead{$head}', ", + "\$secth = 1, last HEADSW ", + "if \$line =~ /^$leftm$head/o;\n"); + } + $doitcode .= "}\n"; + + ## Rest of routine + ## + $doitcode .=<<'EndOfDoItCode'; + if ($secth || $line =~ /^$leftm\S/o) { + chop $line; + $_ = $tmp . $line . $tmp; + s%<([^>]*)>$%%; + $_ = "\n\n" . $_ . "
\n";
+		    } else {
+			s/(((.\010)+.)+)/strongize($1)/oge;
+		    }
+		} else {
+		    s/(((.\010)+.)+)/strongize($1)/oge;
+		}
+	    }
+	    print $OutFH $_;
+	}
+
+	for ($i=0; $i < $ftsz; $i++) {
+	    last LOOP  unless defined($_ = <$InFH>);
+	}
+    }
+EndOfDoItCode
+
+
+    ##	Perform processing.
+
+    printhead()  unless $Bare;
+    print $OutFH "
\n";
+    eval $doitcode;			# $doitcode defined above
+    print $OutFH "
\n"; + printtail() unless $Bare; +} + +##--------------------------------------------------------------------------- +## +sub get_cli_opts { + return 0 unless + GetOptions( + "bare", # Leave out HTML, HEAD, BODY tags. + "belem=s", # HTML Element for overstriked text (def: "B") + "botm=i", # Number of lines for bottom margin (def: 7) + "cgiurl=s", # CGI URL for linking to other manpages + "cgiurlexp=s", # CGI URL Perl expr for linking to other manpages + "compress", # Compress consecutive blank lines + "headmap=s", # Filename of user section head map file + "k", # Process input from 'man -k' output. + "leftm=i", # Character width of left margin (def: 0) + "nodepage", # Do not remove pagination lines + "noheads", # Do not detect for section heads + "pgsize=i", # Number of lines in a page (def: 66) + "seealso", # Link to other manpages only in the SEE ALSO section + "solaris", # Parse 'man -k' output from a solaris system + "sun", # Section heads are not overstriked in input + "title=s", # Title of manpage (def: Not defined) + "topm=i", # Number of lines for top margin (def: 7) + "uelem=s", # HTML Element for underlined text (def: "I") + + "help" # Short usage message + ); + return 0 if defined($opt_help); + + $pgsz = $opt_pgsize || $pgsz; + if (defined($opt_nodepage)) { + $hdsz = 0; + $ftsz = 0; + } else { + $hdsz = $opt_topm if defined($opt_topm); + $ftsz = $opt_botm if defined($opt_botm); + } + $txsz = $pgsz - ($hdsz + $ftsz); + $leftmsz = $opt_leftm if defined($opt_leftm); + $leftm = ' ' x $leftmsz; + + $Bare = defined($opt_bare); + $Compress = defined($opt_compress); + $K = defined($opt_k); + $NoDepage = defined($opt_nodepage); + $NoHeads = defined($opt_noheads); + $SeeAlso = defined($opt_seealso); + $Solaris = defined($opt_solaris); + $Sun = defined($opt_sun); + + $Title = $opt_title || $Title; + $CgiUrl = $opt_cgiurlexp || + ($opt_cgiurl ? qq{return "$opt_cgiurl"} : ''); + + $BTag = $opt_belem || $BTag; + $UTag = $opt_uelem || $UTag; + $BTag =~ s/[<>]//g; + $UTag =~ s/[<>]//g; + + if (defined($opt_headmap)) { + require $opt_headmap or warn "Unable to read $opt_headmap\n"; + } + 1; +} + +##--------------------------------------------------------------------------- +sub printhead { + print $OutFH "\n"; + print $OutFH "\n", + "$Title\n", + "\n" if $Title; + print $OutFH "\n"; + print $OutFH "

$Title

\n", + "
\n" if $Title; +} + +##--------------------------------------------------------------------------- +sub printtail { + print $OutFH < +
+Man(1) output converted with +man2html +
+ + +EndOfRef +} + +##--------------------------------------------------------------------------- +sub emphasize { + my($txt) = shift; + $txt =~ s/.\010//go; + $txt = "<$UTag>$txt"; + $txt; +} + +##--------------------------------------------------------------------------- +sub strongize { + my($txt) = shift; + $txt =~ s/.\010//go; + $txt = "<$BTag>$txt"; + $txt; +} + +##--------------------------------------------------------------------------- +sub entitize { + my($txt) = shift; + + ## Check for special characters in overstrike text ## + $$txt =~ s/_\010\&/strike('_', '&')/geo; + $$txt =~ s/_\010/strike('_', '>')/geo; + + $$txt =~ s/(\&\010)+\&/strike('&', '&')/geo; + $$txt =~ s/(<\010)+\010)+>/strike('>', '>')/geo; + + ## Check for special characters in regular text. Must be careful + ## to check before/after character in expression because it might be + ## a special character. + $$txt =~ s/([^\010]\&[^\010])/htmlize2($1)/geo; + $$txt =~ s/([^\010]<[^\010])/htmlize2($1)/geo; + $$txt =~ s/([^\010]>[^\010])/htmlize2($1)/geo; +} + +##--------------------------------------------------------------------------- +## escape special characters in a string, in-place +## +sub htmlize { + my($str) = shift; + $$str =~ s/&/\&/g; + $$str =~ s//\>/g; + $$str; +} + +##--------------------------------------------------------------------------- +## htmlize2() is used by entitize. +## +sub htmlize2 { + my($str) = shift; + $str =~ s/&/\&/g; + $str =~ s//\>/g; + $str; +} + +##--------------------------------------------------------------------------- +## strike converts HTML special characters in overstriked text +## into entity references. The entities are overstriked so +## strongize() and emphasize() will recognize the entity to be +## wrapped in tags. +## +sub strike { + my($w, $char) = @_; + my($ret); + if ($w eq '_') { + if ($char eq '&') { + $ret = "_$bs\&_${bs}a_${bs}m_${bs}p_${bs};"; + } elsif ($char eq '<') { + $ret = "_$bs\&_${bs}l_${bs}t_${bs};"; + } elsif ($char eq '>') { + $ret = "_$bs\&_${bs}g_${bs}t_${bs};"; + } else { + warn qq|Unrecognized character, "$char", passed to strike()\n|; + } + } else { + if ($char eq '&') { + $ret = "\&$bs\&a${bs}am${bs}mp${bs}p;${bs};"; + } elsif ($char eq '<') { + $ret = "\&$bs\&l${bs}lt${bs}t;${bs};"; + } elsif ($char eq '>') { + $ret = "\&$bs\&g${bs}gt${bs}t;${bs};"; + } else { + warn qq|Unrecognized character, "$char", passed to strike()\n|; + } + } + $ret; +} + +##--------------------------------------------------------------------------- +## make_xref() converts a manpage crossreference into a hyperlink. +## +sub make_xref { + my $str = shift; + $str =~ s/.\010//go; # Remove overstriking + + if ($CgiUrl) { + my($title,$section,$subsection) = + ($str =~ /([\+_\.\w-]+)\((\d)(\w?)\)/); + + $title =~ s/\+/%2B/g; + my($href) = (eval $CgiUrl); + qq|$str|; + } else { + qq|$str|; + } +} + +##--------------------------------------------------------------------------- +## man_k() process a keyword search. The problem we have is there +## is no standard for keyword search results from man. Solaris +## systems have a different enough format to warrent dealing +## with it as a special case. For other cases, we try our best. +## Unfortunately, there are some lines of results that may be +## skipped. +## +sub man_k { + my($line,$refs,$section,$subsection,$desc,$i, + %Sec1, %Sec1sub, %Sec2, %Sec2sub, %Sec3, %Sec3sub, + %Sec4, %Sec4sub, %Sec5, %Sec5sub, %Sec6, %Sec6sub, + %Sec7, %Sec7sub, %Sec8, %Sec8sub, %Sec9, %Sec9sub, + %SecN, %SecNsub, %SecNsec); + + printhead() unless $Bare; + print $OutFH "\n"; + + while ($line = <$InFH>) { + next if $line !~ /\(\d\w?\)\s+-\s/; # check if line can be handled + ($refs,$section,$subsection,$desc) = + $line =~ /^\s*(.*)\((\d)(\w?)\)\s*-\s*(.*)$/; + + if ($Solaris) { + $refs =~ s/^\s*([\+_\.\w-]+)\s+([\+_\.\w-]+)\s*$/$1/; + # + } else { + $refs =~ s/\s(and|or)\s/,/gi; # Convert and/or to commas + $refs =~ s/^[^:\s]:\s*//; # Remove prefixed whatis path + } + $refs =~ s/\s//g; # Remove all whitespace + $refs =~ s/,/, /g; # Put space after comma + htmlize(\$desc); # Check for special chars in desc + $desc =~ s/^(.)/\U$1/; # Uppercase first letter in desc + + if ($section eq '1') { + $Sec1{$refs} = $desc; $Sec1sub{$refs} = $subsection; + } elsif ($section eq '2') { + $Sec2{$refs} = $desc; $Sec2sub{$refs} = $subsection; + } elsif ($section eq '3') { + $Sec3{$refs} = $desc; $Sec3sub{$refs} = $subsection; + } elsif ($section eq '4') { + $Sec4{$refs} = $desc; $Sec4sub{$refs} = $subsection; + } elsif ($section eq '5') { + $Sec5{$refs} = $desc; $Sec5sub{$refs} = $subsection; + } elsif ($section eq '6') { + $Sec6{$refs} = $desc; $Sec6sub{$refs} = $subsection; + } elsif ($section eq '7') { + $Sec7{$refs} = $desc; $Sec7sub{$refs} = $subsection; + } elsif ($section eq '8') { + $Sec8{$refs} = $desc; $Sec8sub{$refs} = $subsection; + } elsif ($section eq '9') { + $Sec9{$refs} = $desc; $Sec9sub{$refs} = $subsection; + } else { # Catch all + $SecN{$refs} = $desc; $SecNsec{$refs} = $section; + $SecNsub{$refs} = $subsection; + } + } + print_mank_sec(\%Sec1, 1, \%Sec1sub); + print_mank_sec(\%Sec2, 2, \%Sec2sub); + print_mank_sec(\%Sec3, 3, \%Sec3sub); + print_mank_sec(\%Sec4, 4, \%Sec4sub); + print_mank_sec(\%Sec5, 5, \%Sec5sub); + print_mank_sec(\%Sec6, 6, \%Sec6sub); + print_mank_sec(\%Sec7, 7, \%Sec7sub); + print_mank_sec(\%Sec8, 8, \%Sec8sub); + print_mank_sec(\%Sec9, 9, \%Sec9sub); + print_mank_sec(\%SecN, 'N', \%SecNsub, \%SecNsec); + + printtail() unless $Bare; +} +##--------------------------------------------------------------------------- +## print_mank_sec() prints out manpage cross-refs of a specific section. +## +sub print_mank_sec { + my($sec, $sect, $secsub, $secsec) = @_; + my(@array, @refs, $href, $item, $title, $subsection, $i, $section, + $xref); + $section = $sect; + + @array = sort keys %$sec; + if ($#array >= 0) { + print $OutFH "

Section $section

\n", + "
\n"; + foreach $item (@array) { + @refs = split(/,/, $item); + $section = $secsec->{$item} if $sect eq 'N'; + $subsection = $secsub->{$item}; + if ($CgiUrl) { + ($title = $refs[0]) =~ s/\(\)//g; # watch out for extra ()'s + $xref = eval $CgiUrl; + } + print $OutFH "
\n"; + $i = 0; + foreach (@refs) { + if ($CgiUrl) { + print $OutFH qq|$_|; + } else { + print $OutFH $_; + } + print $OutFH ", " if $i < $#refs; + $i++; + } + print $OutFH " ($section$subsection)\n", + "
\n", + $sec->{$item}, "
\n"; + } + print $OutFH "
\n"; + } +} + +##--------------------------------------------------------------------------- +## +sub usage { + print $OutFH < outfile +Options: + -bare : Do not put in HTML, HEAD, BODY tags + -belem : HTML Element for overstriked text (def: "B") + -botm <#> : Number of lines for bottom margin (def: 7) + -cgiurl : URL for linking to other manpages + -cgiurlexp : Perl expression URL for linking to other manpages + -compress : Compress consective blank lines + -headmap : Filename of user section head map file + -help : This message + -k : Process a keyword search result + -leftm <#> : Character width of left margin (def: 0) + -nodepage : Do not remove pagination lines + -noheads : Turn off section head detection + -pgsize <#> : Number of lines in a page (def: 66) + -seealso : Link to other manpages only in the SEE ALSO section + -solaris : Process keyword search result in Solaris format + -sun : Section heads are not overstriked in input + -title : Title of manpage (def: Not defined) + -topm <#> : Number of lines for top margin (def: 7) + -uelem : HTML Element for underlined text (def: "I") + +Description: + $PROG takes formatted manpages from STDIN and converts it to HTML sent + to STDOUT. The -topm and -botm arguments are the number of lines to the + main body text and NOT to the running headers/footers. + +Version: + $VERSION + Copyright (C) 1995-1997 Earl Hood, ehood\@medusa.acs.uci.edu + $PROG comes with ABSOLUTELY NO WARRANTY and $PROG may be copied only + under the terms of the GNU General Public License, which may be found in + the $PROG distribution. + +EndOfUsage + exit 0; +} diff --git a/krb5-1-6/doc/man2html.M b/krb5-1-6/doc/man2html.M new file mode 100644 index 000000000..537d6073b --- /dev/null +++ b/krb5-1-6/doc/man2html.M @@ -0,0 +1,761 @@ +.\" sccsid = "@(#) man2html.1 1.2 08/12/97" +.\" +.\" ================================================ +.\" ARGUMENT MACRO: .Ar "arg" [B] +.de Ar +.ie \\$2B \%\fB\\$1\fR +.el \%\fI\\$1\fR +.. +.\" ================================================ +.\" BRACKETED ARGUMENT MACRO: .Br "arg" [B] +.de Br +.ie \\$2B \%[\|\fB\\$1\fR\|] +.el \%[\|\fI\\$1\fR\|] +.. +.\" ================================================ +.\" OPTION FLAG MACRO .Of -x [arg] +.de Of +.ie \\n(.$==1 \%[\|\fB\\$1\fR\|] +.el .if \\n(.$==2 \%[\|\fB\\$1\fR\0\fI\fI\\$2\fR\|] +.. +.\" ================================================ +.\" SYNOPSIS START MACRO +.de Ss .Ss name +.na +.nr aA \w\\$1\\0u +.in +\\n(aAu +'ti -\\n(aAu +.ta \\n(aAu +\&\fB\\$1\fR\t\c +.. +.\" ================================================ +.\" SYNOPSIS END MACRO +.de Se .Se +.ad +.in +.. +.\" ================================================ +.\" +.\" +.TH MAN2HTML 1 "97/08/12" +.SH NAME +.na +man2html \- convert UNIX nroff(1) manual pages to HTML format +.SH SYNOPSIS +.na +.Ss man2html +.Of -bare +.Of -belem name +.Of -botm lines +.Of -cgiurl string +.Of -cgiurlexp expr +.Of -compress +.Of -headmap mapfile +.Of -help +.Of -k +.Of -leftm chars +.Of -nodepage +.Of -noheads +.Of -pgsize lines +.Of -seealso +.Of -solaris +.Of -sun +.Of -title string +.Of -topm lines +.Of -uelem name +.Se +.sp 2 +Typical Usage: +.sp +.Ss man2html +.Of -options +.BI "\0<\0" infile +.BI "\0\0>\0" outfile +.Se +.sp +.B man +.I topic +.B | man2html +.Of -options +.BI "\0>\0" outfile +.\" +.SH DESCRIPTION +.na +The +.B man2html +filter reads formatted nroff text from standard input +.RI ( stdin ) +and writes a \s-1HTML\s+1 document to standard output +.RI ( stdout ). +.LP +The formatted nroff output is surrounded with +.B \s-1
\s+1
+tags with the following exceptions/additions:
+.RS 4n
+.LP
+.na
+'ti -2n
+'ta  2n
+\(bu	Section heads are wrapped in \s-1HTML\s+1
+.I header
+tags.
+See the
+.B "\s-1SECTION\ HEAD\ MAP\ FILE\s+1"
+section below for additional information.
+The
+.B \%-noheads
+option can be used to disable this feature.
+.ad
+.LP
+.na
+'ti -2n
+'ta  2n
+\(bu	Bold words designated by a \%""
+sequences are wrapped in
+.B \s-1\s+1
+tags (or the element specified via the
+.B \%-belem
+option).
+.ad
+.LP
+.na
+'ti -2n
+'ta  2n
+\(bu	Underlined words designated by a \%"_"
+sequences are wrapped in
+.B \s-1\s+1
+tags (or the element specified via the
+.B \%-uelem
+option).
+.ad
+.RE
+.SH OPTIONS
+.na
+.TP 0.5i
+.B -bare
+This option will eliminate \s-1HTML\s+1
+.B \s-1\s+1
+and
+.B \s-1\s+1
+tags from the output.
+This is useful when you wish to incorporate the output into another
+\s-1HTML\s+1 document.
+.TP 0.5i 
+.BI -belem\0 name
+Use
+.I name
+as the name of the element to wrap overstriken characters.
+The default is \fBB\fR.
+.TP 0.5i 
+.BI -botm\0 lines
+The
+.I lines
+argument specifies the number of lines representing the bottom
+margin of the formatted nroff input.
+The line count includes any running footers.
+The default value is 7.
+.TP 0.5i
+.BI -cgiurl\0 string
+The
+.I string
+argument specifies a template \s-1URL\s+1 for creating links to other manpages.
+See the
+.B "\s-1LINKING\ TO\ OTHER\ MANPAGES\s+1"
+section below for additional information.
+.TP 0.5i
+.BI -cgiurlexp\0 expr
+The
+.I expr
+argument specifies a Perl expression evaluting to a \s-1URL\s+1 for
+creating links to other manpages.
+See the
+.B "\s-1LINKING\ TO\ OTHER\ MANPAGES\s+1"
+section below for additional information.
+.TP 0.5i
+.B -compress
+Compress consecutive blank lines into a single line.
+.TP 0.5i
+.BI -headmap\0 mapfile
+The
+.I mapfile
+argument is read to determine which \s-1HTML\s+1
+header tags are to be used for various section heading in the manpage.
+See the
+.B "\s-1SECTION\ HEAD\ MAP\ FILE\s+1"
+section below for information on the format of the map file.
+.TP 0.5i
+.B -help
+Print out a short usage message and then exit immediately.
+.TP 0.5i
+.B -k
+Process input resulting from a manpage keyword search
+.RB ( "man\ -k" ).
+See the
+.B "\s-1KEYWORD\ SEARCH\s+1"
+section below for additional information.
+.TP 0.5i
+.BI -leftm\0 chars
+The
+.I chars
+argument specifies the width of the number of characters making
+up the left margin of the formatted nroff input.
+The default value is 0.
+.TP 0.5i
+.B -nodepage
+By default,
+.B man2html
+merges multi-page formatted nroff into a single page.
+This option may be used to disable depagination, causing
+running headers and footers in the formatted nroff input
+to be carried over into the \s-1HTML\s+1 output.
+.TP 0.5i
+.B -noheads
+By default,
+.B man2html
+wraps section heads in \s-1HTML\s+1
+header tags.
+See the
+.B "\s-1SECTION\ HEAD\ MAP\ FILE\s+1"
+section below for additional information.
+This option may be specified to disabled this feature.
+.TP 0.5i
+.BI -pgsize\0 lines
+The
+.I lines
+argument specifies the number of lines making up the page size (length)
+of the formatted nroff input.
+The default value is 66.
+.TP 0.5i
+.B -seealso
+If the
+.B -cgiurl
+option has been specified, then this option restricts the
+creation of links to other manual pages to the
+.B "\%\s-1SEE\ ALSO\s+1"
+section only.
+.TP 0.5i
+.B -solaris
+If the
+.B -k
+option has been specified, then this option modifies its operation
+to process the alternate manual page keyword search format produced
+by the
+.BR man (1)
+utility on systems running
+.IR Solaris .
+See the
+.B "\s-1KEYWORD\ SEARCH\s+1"
+section below for additional information.
+.TP 0.5i
+.B -sun
+Do not require a section head to have bold overstriking in the
+formatted nroff input.
+The option is called
+.B \%sun
+because it was on a Sun workstation that section heads in
+manpages were found to not be overstruck.
+.TP 0.5i
+.BI -title\0 string
+By default,
+.B man2html
+does not generate a \s-1HTML\s+1 title
+.RB ( \s-1\s+1 ).
+This option sets the title of the \s-1HTML\s+1 output to the specified
+.IR string .
+.TP 0.5i
+.BI -topm\0 lines
+The
+.I lines
+argument specifies number number of lines representing the
+top margin of the formatted nroff input.
+The line count includes any running headers.
+The default value is 7.
+.TP 0.5i 
+.BI -uelem\0 name
+Use
+.I name
+as the name of the element to wrap underscored characters.
+The default is \fBI\fR.
+.\"
+.SH "SECTION HEAD MAP FILE"
+.na
+.LP
+The
+.B \%-headmap
+option may be used to customize which \s-1HTML\s+1 header tags,
+.BR "\s-1<H1>\s+1 ... \s-1<H6>\s+1" ,
+are used in manpage section headings.
+Normally,
+.B man2html
+treats lines that are flush to the left margin
+.RB ( -leftm ),
+and contain overstriking (overstrike check is canceled with the
+.B -sun
+option), as section heads.
+However, you can augment/override what \s-1HTML\s+1 header tags are used for
+any given section head.
+.LP
+In order to write a section head map file, you will need to know about
+.BR perl (1)
+associative arrays.
+You do not need to be an expert in
+.B perl
+to write a map file, however, having knowledge of
+.B perl
+allows you to be more clever.
+.\"
+.SS "Augmenting the Default Map" 
+.LP
+To add to the default mapping defined by
+.BR man2html ,
+your map file will contain lines with the following syntax:
+.sp
+.if t .RS 4n
+.B "$SectionHead{'<section head text>'} = '<html header tag>';"
+.if t .RE
+.sp
+where
+.IP "\fB\%<section\ head\ text>\fR"
+is the text of the manpage section head.
+For example:
+.B  \s-1SYNOPSIS\s+1
+or
+.BR \s-1DESCRIPTION\s+1 .
+.IP "\fB\%<html\ header\ tag>\fR"
+is the \s-1HTML\s+1 header tag to wrap the section head in.
+Legal values are:
+.BR \s-1<H1>\s+1 ,
+.BR \s-1<H2>\s+1 ,
+.BR \s-1<H3>\s+1 ,
+.BR \s-1<H4>\s+1 ,
+.BR \s-1<H5>\s+1 ,
+.BR \s-1<H6>\s+1 .
+.SS "Overriding the Default Map"
+To override the default mapping with your own, then your map file will
+have the following syntax:
+.sp
+.RS 4n
+.ft B
+.nf
+.ne 6v
+%SectionHead = (
+         \&'<section head text>', '<html header tag>',
+         \&'<section head text>', '<html header tag>',
+         \&# ... More section head/tag pairs
+         \&'<section head text>', '<html header tag>',
+);
+.fi
+.ft
+.RE
+.SS "The Default Map"
+.LP
+As of this writing, this is the default map used by
+.BR man2html :
+.RS 4n
+.sp
+.ft C
+.nf
+.ne 29v
+%SectionHead = (
+.ps -1
+    \&'\\S.*OPTIONS.*'             => '<H2>',
+    \&'AUTHORS?'                  => '<H2>',
+    \&'BUGS'                      => '<H2>',
+    \&'COMPATIBILITY'             => '<H2>',
+    \&'DEPENDENCIES'              => '<H2>',
+    \&'DESCRIPTION'               => '<H2>',
+    \&'DIAGNOSTICS'               => '<H2>',
+    \&'ENVIRONMENT'               => '<H2>',
+    \&'ERRORS'                    => '<H2>',
+    \&'EXAMPLES'                  => '<H2>',
+    \&'EXTERNAL INFLUENCES'       => '<H2>',
+    \&'FILES'                     => '<H2>',
+    \&'LIMITATIONS'               => '<H2>',
+    \&'NAME'                      => '<H2>',
+    \&'NOTES?'                    => '<H2>',
+    \&'OPTIONS'                   => '<H2>',
+    \&'REFERENCES'                => '<H2>',
+    \&'RETURN VALUE'              => '<H2>',
+    \&'SECTION.*:'                => '<H2>',
+    \&'SEE ALSO'                  => '<H2>',
+    \&'STANDARDS CONFORMANCE'     => '<H2>',
+    \&'STYLE CONVENTION'          => '<H2>',
+    \&'SYNOPSIS'                  => '<H2>',
+    \&'SYNTAX'                    => '<H2>',
+    \&'WARNINGS'                  => '<H2>',
+    \&'\\s+Section.*:'             => '<H3>',
+.ps +1
+);
+$HeadFallback = '\s-1<H2>\s+1';  # Fallback tag if above is not found.
+.fi
+.ft
+.RE
+.LP
+Check the
+.B perl
+source code of
+.B man2html
+for the latest default mapping.
+.LP 
+You can reassign the
+.B \%$HeadFallback
+variable to a different value if you choose.
+This value is used as the header tag of a section head if
+no matches are found in the \%\fB%SectionHead\fR map.
+.SS "Using Regular Expressions in the Map File"
+.LP
+You may have noticed unusual characters in the default map file, like
+"\\s" or "*".
+The
+.B man2html
+utility actual treats the
+.B "\%<section\ head\ text>"
+as a
+.B perl
+regular expression.
+If you are comfortable with
+.B perl
+regular expressions, then you have their full power to use
+in your map file.
+.LP
+.I Caution:
+The
+.B man2html
+utility already anchors the regular expression to the beginning of the
+line with left margin spacing specified by the
+.B \%-leftm
+option.
+Therefore, do not use the `\fB\fR^' character to anchor your regular
+expression to the beginning.
+However, you may end your expression with a `\fB$\fR' to anchor it to
+the end of the line.
+.LP 
+Since the
+.B "\%<section\ head\ text>"
+is actually a regular expression, you will have to be careful of
+special characters if you want them to be treated literally.
+Any of the characters
+.RB ` "[ ] ( ) . ^ { } $ * ? + \\ |" '
+should be escaped by prefixing them by the
+\&`\fB\\\fR' character if you want
+.B perl
+to treat them "as is".
+.LP
+.I Caution:
+One should use single quotes instead of double quotes to delimit
+.BR "\%<section\ head\ text>" .
+This will preserve any `\fB\\\fR' characters for character escaping
+or when the `\fB\\\fR' is used for special
+.B perl
+character matching sequences (e.g.,  \fB\\s\fR, \fB\\w\fR, \fB\\S\fR).
+.SS "Other Tid-bits on the Map File"
+.LP
+Comments can be inserted in the map file by using the '\fB#\fR'
+character.
+Anything after, and including, the '\fB#\fR' character is ignored,
+up to the end of line.
+.LP 
+You might be thinking that the above is quite-a-bit-of-stuff just for
+doing manpage section heads.
+However, you will be surprised how much better the \s-1HTML\s+1 output looks
+with header tags, even though, everything else is in a
+.B \s-1<PRE>\s+1
+tag.
+.\"
+.SH "LINKING TO OTHER MANPAGES"
+.na
+.LP 
+The
+.B man2html
+utility allows the ability to link to other manpage references.
+If the
+.B \%-cgiurl
+option is specified,
+.B man2html
+will create anchors that link to other manpages.
+.LP 
+The \s-1URL\s+1 entered with the
+.B \%-cgiurl
+option is actually a template that determines the actual \s-1URL\s+1 used to
+link to other manpages.
+The following variables are defined during run time that may be used in
+the template string:
+.sp
+.RS 4n
+.IP \fB$title\fR
+The title of the manual page referenced.
+.IP \fB$section\fR
+The section number of the manual page referenced.
+.IP \fB$subsection\fR
+The subsection of the manual page referenced.
+.RE
+.LP
+Any other text in the template is preserved "as is".
+.LP
+.I Caution:
+The
+.B man2html
+utility evaluates the template string as a
+.B perl
+string expression.
+Therefore, one might need to surround the variable names with
+\&'\fB{\|}\fR' (e.g.,
+.BR ${\|title\|}\| )
+so that
+.B man2html
+properly recognizes the variable.
+.LP
+.I Note:
+If a \s-1CGI\s+1 program calling
+.B man2html
+is actually a shell script or a
+.B perl
+program, make sure to properly escape the '\fB$\fR' character
+in the \s-1URL\s+1 template to avoid variable interpolation by the \s-1CGI\s+1
+program.
+.LP
+Normally, the \s-1URL\s+1 calls a \s-1CGI\s+1 program (hence the option name),
+but the \s-1URL\s+1 can easily link to statically converted documents.
+.SS "Example1:"
+.LP 
+The following template string is specified to call a \s-1CGI\s+1 program to
+retrieve the appropriate manpage linked to:
+.LP
+.nf
+.B "/cgi-bin/man.cgi?section=${section}${subsection}&topic=${title}"
+.fi
+.LP 
+If the
+.BR ls (1)
+manpage is referenced in the
+.B "SEE ALSO"
+section, the above template will translate to the following \s-1URL\s+1:
+.LP
+.B "/cgi-bin/man.cgi?section=1&topic=ls"
+.LP 
+The actual \s-1HTML\s+1 markup will look like the following:
+.LP
+\fB<A\ HREF="/cgi-bin/man.cgi?section=1&topic=ls">ls(1)</A>\fR
+.SS "Example2:"
+.LP 
+The following template string is specified to retrieve pre-converted
+manpages:
+.LP
+.B "http://foo.org/man$section/$title.$section$subsection.html"
+.LP 
+If the
+.BR mount (1M)
+manpage is referenced, the above template will translate to the
+following \s-1URL\s+1:
+.LP
+.B "http://foo.org/man1/mount.1M.html"
+.LP 
+The actual \s-1HTML\s+1 markup will look like the following:
+.LP
+\fB<A HREF="http://foo.org/man1/mount.1M.html">mount(1M)</A>\fR
+.SS "-cgiurlexp"
+The option
+.B \%-cgiurlexp
+is a more general form of the
+.B \%-cgiurl
+option.
+.B \%-cgiurlexp
+allows one to specify a general Perl expression.  For example:
+.LP
+\fB$title=~/^db_/i?"$title.html":"/cgi-bin/man?$title+$section"\fR
+.LP
+A
+.B \%-cgiurl
+.I string
+can be expressed as follows with \fB-cgiurlexp\fR:
+.LP
+\fBreturn "\fIstring\fB"\fR
+.\"
+.SH "KEYWORD SEARCH"
+.na
+.LP
+The
+.B man2html
+utility has the ability to process keyword search output generated
+by the \%\fBman\ -k\fR or \%\fBapropos\fR commands, through the
+use of the
+.B -k
+option.
+The
+.B man2html
+utility will generate an \s-1HTML\s+1 document of the keyword search input
+having the following format:
+.RS 4n 
+.LP
+.na
+'ti -2n
+'ta  2n
+\(bu	All manpage references are listed by section.
+.ad
+.LP
+.na
+'ti -2n
+'ta  2n
+\(bu	Within each section listing, the manpage references
+are sorted alphabetically (case-sensitive) in a
+.B \s-1<DL>\s+1
+tag.
+The manpage references are listed in the
+.B \s-1<DT>\s+1
+section, and the summary text is listed in the
+.B \s-1<DD>\s+1
+section.
+.ad
+.LP
+.na
+'ti -2n
+'ta  2n
+\(bu	Each manpage reference listed is a hyperlink to the
+actual manpage as specified by the
+.B \%-cgiurl
+option.
+.ad
+.RE
+.LP 
+.na
+This ability to process keyword searches gives nice added functionality
+to a \s-1WWW\s+1 forms interface to
+.BR man (1).
+Even if you have statically converted manpages to \s-1HTML\s+1 via another
+man->\s-1HTML\s+1 program, you can use
+.B man2html
+and "\fBman\ -k\fR" to provide keyword search capabilities easily for
+your \s-1HTML\s+1 manpages.
+.SS "Processing Keyword Search Results"
+.na
+.LP 
+Unfortunately, there is no standard controlling the format of keyword
+search results.
+The
+.B man2html
+utility tries it best to handle all the variations.
+However, the keyword search results generated by the
+.I Solaris
+operating system is different enough from other systems that a
+special command-line option
+.RB ( -solaris )
+must be specified to handle its output.
+.SS "Example of raw Solaris-type keyword search results:"
+.LP
+.ft C
+.nf
+.ne 10v
+strcpy        strcpy (9f)  - copy a string from one location to another.
+strcpy        string (3c)  - string operations
+strncpy       strcpy (9f)  - copy a string from one location to another.
+strncpy       string (3c)  - string operations
+.fi
+.ft
+.LP 
+If keyword search results on your systems appear in the following format:
+.LP
+.RS 4n
+.B "<topic>  <actual_manpage> (#) - Description"
+.RE
+.LP
+then you need to specify the
+.B \%-solaris
+option in addition to the
+.B -k
+option.
+.SH "ADDITIONAL NOTES"
+.na
+.LP
+Different systems format manpages differently.
+Here is a list of recommended command-line options for certain systems:
+.RS 4n
+.LP
+.ta 1i
+.nf
+.ne 3v
+\fBConvex\fR:	<defaults should be okay>
+\fBHP\fR:	\fB-leftm 1 -topm 8\fR
+\fBSun\fR:	\fB-sun\fR (and \fB-solaris\fR when using \fB-k\fR)
+.fi
+.RE
+.LP
+Some line spacing gets lost in the formatted nroff since the
+spacing would occur in the middle of a page break.
+This can cause text to be merged that shouldn't be merged when
+.B man2html
+depaginates the text.
+To avoid this problem,
+.B man2html
+keeps track of the margin indent right before and after a page break.
+If the margin width of the line after the page break is less than the
+line before the page break, then
+.B man2html
+inserts a blank line in the \s-1HTML\s+1 output.
+.LP 
+A manpage cross-reference is detected by the following pseudo expression:
+\%\fB[A-z.-+_]+([0-9][A-z]?)\fR
+.LP
+The
+.B man2html
+utility only recognizes lines with "\fB - \fR" (the normal separator
+between manpage references and summary text) while in keyword
+search mode.
+.LP 
+The
+.B man2html
+utility can be hooked in a \s-1CGI\s+1 script/program to convert manpages
+on the fly.
+This is the reason for the
+.B \%-cgiurl
+option.
+.SH LIMITATIONS
+.na
+.LP 
+The order that section head mapping is searched is not defined.
+Therefore, if two or more
+.B "\%<section\ head\ text>"
+can match a give manpage section, there is no way to determine
+which map tag is chosen.
+.LP 
+If
+.B \%-seealso
+is specified, all xrefs are detected after the
+.B "\%SEE\ ALSO"
+heading.
+In other words, sections after
+.B "\%SEE\ ALSO"
+may contain hyperlinked xrefs.
+.SH BUGS
+.na
+.LP 
+Text that is flush to the left margin, but is not actually a
+section head, can be mistaken for a section head.
+This mistake is more likely when the
+.B \%-sun
+option is in affect.
+.SH VERSION
+.na
+This documentation describes
+.B man2html
+version 3.0.1
+.SH "SEE ALSO"
+.na
+.BR man (1),
+.BR nroff (1),
+.BR perl (1)
+.LP
+.I http://www.oac.uci.edu/indiv/ehood/man2html.html
+.SH AUTHOR
+.LP
+.B Earl Hood
+.br
+.I ehood@medusa.acs.uci.edu
+.\"
+.SH "ERRORS AND OMISSIONS"
+.na
+Troff version of this document initially created for version 2.1.0
+by C. Jeffery Small
+.RI ( jeff@cjsa.com )
+by copying, reformatting, rearranging and partially rewriting
+the contents of the ascii text file
+.BR doc/man2html.txt .
diff --git a/krb5-1-6/doc/man2ps b/krb5-1-6/doc/man2ps
new file mode 100755
index 000000000..06240e07c
--- /dev/null
+++ b/krb5-1-6/doc/man2ps
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+com=`basename $0`
+files=$*
+ROFF=groff
+ROFF_FLAGS="-C -man -Tps"
+CSPLIT=
+
+IFS="${IFS= 	}"; save_ifs="$IFS"; IFS="${IFS}:"
+for i in $PATH; do
+  if [ -f $i/gcsplit ]; then
+	CSPLIT=$i/gcsplit
+	break
+  fi
+  if [ -f $i/csplit ]; then
+	CSPLIT=$i/csplit
+	break
+  fi
+done
+IFS="$save_ifs"
+
+if [ "$files" = "" ]; then
+    echo "Usage: $com file [file2 ...]"
+    exit 1
+fi
+
+for file in $files
+do
+    filename=`basename $file | awk -F. '{print $1}'`
+    eval $ROFF $ROFF_FLAGS $file > $filename.ps
+
+    pages=`grep '%%Pages\:' $filename.ps | awk '{print $2}'`
+    pp=`expr $pages - 1`
+
+    echo $filename': '$pages' pages'
+
+    if [ "$CSPLIT"x != x ]; then
+        $CSPLIT -k $filename.ps /Page:/ \{$pp\} > /dev/null
+
+        counter=0
+
+        for number in `ls xx*`
+        do
+            cat xx00 > $filename$counter.ps
+            echo '0.85 dup scale' >> $filename$counter.ps
+            cat $number >> $filename$counter.ps
+            if [ $counter != $pages ];
+                then
+                echo '%%Trailer' >> $filename$counter.ps
+                echo 'end' >> $filename$counter.ps
+                echo '%%EOF' >> $filename$counter.ps
+            fi
+            counter=`expr $counter + 1`
+        done
+
+        rm $filename.ps $filename'0.ps' xx*
+    else
+        echo "Can't find the csplit command.  You'll have to split $filename.ps manually."
+    fi
+done
diff --git a/krb5-1-6/doc/man2ps.M b/krb5-1-6/doc/man2ps.M
new file mode 100644
index 000000000..d9c79032b
--- /dev/null
+++ b/krb5-1-6/doc/man2ps.M
@@ -0,0 +1,50 @@
+.TH MAN2PS 1
+.SH NAME
+man2ps \- create individual PostScript files for each page of a man page
+.SH SYNOPSIS
+.B man2ps
+.I file
+[\fIfile2\fP [\fI...\fP]]
+.SH DESCRIPTION
+.B man2ps
+is a bourne shell script that turns a man page into a set of PostScript
+files, for inclusion in a document.
+.B man2ps
+converts the man page to a PostScript file using
+.IR groff (1), 
+and then uses the
+.IR csplit (1)
+command to split the file into individual pages.
+.B man2ps
+inserts the PostScript command:
+.sp
+.nf
+.in +.5i
+\&0.85 dup scale
+.in -.5i
+.fi
+.sp
+at the beginning of each page, so that the pages will fit onto an
+8.5"x11" page.
+.PP
+The files created by
+.B man2ps
+have the same name as the command, with a sequential number and the
+string ".ps" appended.  For example, running
+.B man2ps
+on the file "kinit.M" would produce the PostScript files "kinit1.ps",
+"kinit2.ps", ...
+.SH SEE ALSO
+troff(1), csplit(1)
+.SH BUGS
+.B man2ps
+requires the user to have
+.I groff
+and either
+.I csplit
+or
+.I gcsplit
+in her path.
+.SH AUTHORS
+.B man2ps
+was written by Jeff Bigler at Cygnus Support and Theodore Ts'o at MIT.
diff --git a/krb5-1-6/doc/old-V4-docs/README b/krb5-1-6/doc/old-V4-docs/README
new file mode 100644
index 000000000..8858655cb
--- /dev/null
+++ b/krb5-1-6/doc/old-V4-docs/README
@@ -0,0 +1,4 @@
+These documentation files are old --- and refer to the Kerberos V4 
+implementation.  They are included because the equivalent V5 documentation
+set have not been written yet, and the concepts contained in these documents
+may be helpful.
diff --git a/krb5-1-6/doc/old-V4-docs/installation.PS b/krb5-1-6/doc/old-V4-docs/installation.PS
new file mode 100644
index 000000000..7609d4e64
--- /dev/null
+++ b/krb5-1-6/doc/old-V4-docs/installation.PS
@@ -0,0 +1,2338 @@
+%!PS-Adobe-2.0
+%%Title: installation.mss
+%%DocumentFonts: (atend)
+%%Creator: John T Kohl,,E40-351M,31510,6176432831 and Scribe 7(1700)
+%%CreationDate: 4 January 1990 11:56
+%%Pages: (atend)
+%%EndComments
+% PostScript Prelude for Scribe.
+/BS {/SV save def 0.0 792.0 translate .01 -.01 scale} bind def
+/ES {showpage SV restore} bind def
+/SC {setrgbcolor} bind def
+/FMTX matrix def
+/RDF {WFT SLT 0.0 eq 
+  {SSZ 0.0 0.0 SSZ neg 0.0 0.0 FMTX astore}
+  {SSZ 0.0 SLT neg sin SLT cos div SSZ mul SSZ neg 0.0 0.0 FMTX astore}
+  ifelse makefont setfont} bind def
+/SLT 0.0 def
+/SI { /SLT exch cvr def RDF} bind def
+/WFT /Courier findfont def
+/SF { /WFT exch findfont def RDF} bind def
+/SSZ 1000.0 def
+/SS { /SSZ exch 100.0 mul def RDF} bind def
+/AF { /WFT exch findfont def /SSZ exch 100.0 mul def RDF} bind def
+/MT /moveto load def
+/XM {currentpoint exch pop moveto} bind def
+/UL {gsave newpath moveto dup 2.0 div 0.0 exch rmoveto
+   setlinewidth 0.0 rlineto stroke grestore} bind def
+/LH {gsave newpath moveto setlinewidth
+   0.0 rlineto
+   gsave stroke grestore} bind def
+/LV {gsave newpath moveto setlinewidth
+   0.0 exch rlineto
+   gsave stroke grestore} bind def
+/BX {gsave newpath moveto setlinewidth
+   exch
+   dup 0.0 rlineto
+   exch 0.0 exch neg rlineto
+   neg 0.0 rlineto
+   closepath
+   gsave stroke grestore} bind def
+/BX1 {grestore} bind def
+/BX2 {setlinewidth 1 setgray stroke grestore} bind def
+/PB {/PV save def newpath translate
+    100.0 -100.0 scale pop /showpage {} def} bind def
+/PE {PV restore} bind def
+/GB {/PV save def newpath translate rotate
+    div dup scale 100.0 -100.0 scale /showpage {} def} bind def
+/GE {PV restore} bind def
+/FB {dict dup /FontMapDict exch def begin} bind def
+/FM {cvn exch cvn exch def} bind def
+/FE {end /original-findfont /findfont load def  /findfont
+   {dup FontMapDict exch known{FontMapDict exch get} if
+   original-findfont} def} bind def
+/BC {gsave moveto dup 0 exch rlineto exch 0 rlineto neg 0 exch rlineto closepath clip} bind def
+/EC /grestore load def
+/SH /show load def
+/MX {exch show 0.0 rmoveto} bind def
+/W {0 32 4 -1 roll widthshow} bind def
+/WX {0 32 5 -1 roll widthshow 0.0 rmoveto} bind def
+/RC {100.0 -100.0 scale
+612.0 0.0 translate
+-90.0 rotate
+.01 -.01 scale} bind def
+/URC {100.0 -100.0 scale
+90.0 rotate
+-612.0 0.0 translate
+.01 -.01 scale} bind def
+/RCC {100.0 -100.0 scale
+0.0 -792.0 translate 90.0 rotate
+.01 -.01 scale} bind def
+/URCC {100.0 -100.0 scale
+-90.0 rotate 0.0 792.0 translate
+.01 -.01 scale} bind def
+%%EndProlog
+%%Page: 0 1
+BS
+0 SI
+20 /Times-Bold AF
+18823 13788 MT
+(Kerberos Installation Notes)SH
+27156 15798 MT
+(DRAFT)SH
+16 /Times-Roman AF
+27021 23502 MT
+(Bill Bryant)SH
+25557 25150 MT
+(Jennifer Steiner)SH
+27289 26798 MT
+(John Kohl)SH
+23957 30444 MT
+(Project Athena, MIT)SH
+/Times-Bold SF
+19489 36042 MT
+(Initial Release, January 24, 1989)SH
+/Times-Italic SF
+17558 37690 MT
+(\050plus later patches through patchlevel 7\051)SH
+11 /Times-Roman AF
+7200 45644 MT
+(The release consists of three parts.)SH
+7200 47942 MT
+(The first part consists of the core Kerberos system, which was developed at MIT and does not require)SH
+7200 49138 MT
+(additional licenses for us to distribute.  Included in this part are the Kerberos authentication server, the)SH
+7200 50334 MT
+(Kerberos library, the)SH
+/Times-Italic SF
+16606 XM
+(ndbm)SH
+/Times-Roman SF
+19325 XM
+(database interface library, user programs, administration programs, manual)SH
+7200 51530 MT
+(pages, some applications which use Kerberos for authentication, and some utilities.)SH
+7200 53828 MT
+(The second part is the Data Encryption Standard \050DES\051 library, which we are distributing only within the)SH
+7200 55024 MT
+(United States.)SH
+7200 57322 MT
+(The third part contains Kerberos modifications to Sun's NFS, which we distribute as ``context diffs'' to)SH
+7200 58518 MT
+(the Sun NFS source code.  Its distribution is controlled to provide an accounting of who has retrieved the)SH
+7200 59714 MT
+(patches, so that Project Athena can comply with its agreements with Sun regarding distribution of these)SH
+7200 60910 MT
+(changes.)SH
+ES
+%%Page: 1 2
+BS
+0 SI
+16 /Times-Bold AF
+7200 8272 MT
+(1. Organization)
+400 W( of the Source Directory)SH
+11 /Times-Roman AF
+7200 10467 MT
+(The Kerberos building and installation process, as described in this document, builds the binaries and)SH
+7200 11663 MT
+(executables from the files contained in the Kerberos source tree, and deposits them in a separate object)SH
+7200 12859 MT
+(tree. This)
+275 W( is intended to easily support several different build trees from a single source tree \050this is useful)SH
+7200 14055 MT
+(if you support several machine architectures\051.  We suggest that you copy the Kerberos sources into a)SH
+/Times-Italic SF
+7200 15251 MT
+(/mit/kerberos/src)SH
+/Times-Roman SF
+14991 XM
+(directory, and create as well a)SH
+/Times-Italic SF
+28396 XM
+(/mit/kerberos/obj)SH
+/Times-Roman SF
+36249 XM
+(directory in which to hold the)SH
+7200 16447 MT
+(executables. In)
+275 W( the rest of this document, we'll refer to the Kerberos source and object directories as)SH
+7200 17643 MT
+([SOURCE_DIR] and [OBJ_DIR], respectively.)SH
+7200 19941 MT
+(Below is a brief overview of the organization of the complete source directory.  More detailed)SH
+7200 21137 MT
+(descriptions follow.)SH
+/Times-Bold SF
+7200 23088 MT
+(admin)SH
+/Times-Roman SF
+18200 XM
+(utilities for the Kerberos administrator)SH
+/Times-Bold SF
+7200 24783 MT
+(appl)SH
+/Times-Roman SF
+18200 XM
+(applications that use Kerberos)SH
+/Times-Bold SF
+7200 26478 MT
+(appl/bsd)SH
+/Times-Roman SF
+18200 XM
+(Berkeley's rsh/rlogin suite, using Kerberos)SH
+/Times-Bold SF
+7200 28173 MT
+(appl/knetd)SH
+/Times-Roman SF
+18200 XM
+(\050old\051 software for inetd-like multiplexing of a single TCP listening port)SH
+/Times-Bold SF
+7200 29868 MT
+(appl/sample)SH
+/Times-Roman SF
+18200 XM
+(sample application servers and clients)SH
+/Times-Bold SF
+7200 31563 MT
+(appl/tftp)SH
+/Times-Roman SF
+18200 XM
+(Trivial File Transfer Protocol, using Kerberos)SH
+/Times-Bold SF
+7200 33258 MT
+(include)SH
+/Times-Roman SF
+18200 XM
+(include files)SH
+/Times-Bold SF
+7200 34953 MT
+(kadmin)SH
+/Times-Roman SF
+18200 XM
+(remote administrative interface to the Kerberos master database)SH
+/Times-Bold SF
+7200 36648 MT
+(kuser)SH
+/Times-Roman SF
+18200 XM
+(assorted user programs)SH
+/Times-Bold SF
+7200 38343 MT
+(lib)SH
+/Times-Roman SF
+18200 XM
+(libraries for use with/by Kerberos)SH
+/Times-Bold SF
+7200 40038 MT
+(lib/acl)SH
+/Times-Roman SF
+18200 XM
+(Access Control List library)SH
+/Times-Bold SF
+7200 41733 MT
+(lib/des)SH
+/Times-Roman SF
+18200 XM
+(Data Encryption Standard library \050US only\051)SH
+/Times-Bold SF
+7200 43428 MT
+(lib/kadm)SH
+/Times-Roman SF
+18200 XM
+(administrative interface library)SH
+/Times-Bold SF
+7200 45123 MT
+(lib/kdb)SH
+/Times-Roman SF
+18200 XM
+(Kerberos server library interface to)SH
+/Times-Italic SF
+33925 XM
+(ndbm)SH
+/Times-Bold SF
+7200 46818 MT
+(lib/knet)SH
+/Times-Roman SF
+18200 XM
+(\050old\051 library for use with)SH
+/Times-Bold SF
+29349 XM
+(knetd)SH
+7200 48513 MT
+(lib/krb)SH
+/Times-Roman SF
+18200 XM
+(Kerberos library)SH
+/Times-Bold SF
+7200 50208 MT
+(man)SH
+/Times-Roman SF
+18200 XM
+(manual pages)SH
+/Times-Bold SF
+7200 51903 MT
+(prototypes)SH
+/Times-Roman SF
+18200 XM
+(sample configuration files)SH
+/Times-Bold SF
+7200 53598 MT
+(server)SH
+/Times-Roman SF
+18200 XM
+(the authentication server)SH
+/Times-Bold SF
+7200 55293 MT
+(slave)SH
+/Times-Roman SF
+18200 XM
+(Kerberos slave database propagation software)SH
+/Times-Bold SF
+7200 56988 MT
+(tools)SH
+/Times-Roman SF
+18200 XM
+(shell scripts for maintaining the source tree)SH
+/Times-Bold SF
+7200 58683 MT
+(util)SH
+/Times-Roman SF
+18200 XM
+(utilities)SH
+/Times-Bold SF
+7200 60378 MT
+(util/imake)SH
+/Times-Roman SF
+18200 XM
+(Imakefile-to-Makefile ``compilation'' tool)SH
+/Times-Bold SF
+7200 62073 MT
+(util/ss)SH
+/Times-Roman SF
+18200 XM
+(Sub-system library \050for command line subsystems\051)SH
+/Times-Bold SF
+7200 63768 MT
+(util/et)SH
+/Times-Roman SF
+18200 XM
+(Error-table library \050for independent, unique error codes\051)SH
+/Times-Bold SF
+7200 65463 MT
+(util/makedepend)SH
+/Times-Roman SF
+18200 XM
+(Makefile dependency generator tool)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(1)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 2 3
+BS
+0 SI
+14 /Times-Bold AF
+7200 8167 MT
+(1.1 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(admin)SH
+/Times-Bold SF
+16340 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 10362 MT
+(This directory contains source for the Kerberos master database administration tools.)SH
+/Times-Bold SF
+7200 12313 MT
+(kdb_init)SH
+/Times-Roman SF
+18200 XM
+(This program creates and initializes the Kerberos master database.  It prompts)SH
+18200 13509 MT
+(for a Kerberos realmname, and the Kerberos master password.)SH
+/Times-Bold SF
+7200 15204 MT
+(kstash)SH
+/Times-Roman SF
+18200 XM
+(This program ``stashes'' the master password in the file)SH
+/Times-Italic SF
+43033 XM
+(/.k)SH
+/Times-Roman SF
+44377 XM
+(so that the master)SH
+18200 16400 MT
+(server machine can restart the Kerberos server automatically after an unattended)SH
+18200 17596 MT
+(reboot. The)
+275 W( hidden password is also available to administrative programs that)SH
+18200 18792 MT
+(have been set to run automatically.)SH
+/Times-Bold SF
+7200 20487 MT
+(kdb_edit)SH
+/Times-Roman SF
+18200 XM
+(This program is a low-level tool for editing the master database.)SH
+/Times-Bold SF
+7200 22182 MT
+(kdb_destroy)SH
+/Times-Roman SF
+18200 XM
+(This program deletes the master database.)SH
+/Times-Bold SF
+7200 23877 MT
+(kdb_util)SH
+/Times-Roman SF
+18200 XM
+(This program can be used to dump the master database into an ascii file, and can)SH
+18200 25073 MT
+(also be used to load the ascii file into the master database.)SH
+/Times-Bold SF
+7200 26768 MT
+(ext_srvtab)SH
+/Times-Roman SF
+18200 XM
+(This program extracts information from the master database and creates a host-)SH
+18200 27964 MT
+(dependent)SH
+/Times-Italic SF
+22995 XM
+(srvtab)SH
+/Times-Roman SF
+26020 XM
+(file. This)
+275 W( file contains the Kerberos keys for the host's)SH
+18200 29160 MT
+(``Kerberized'' services.  These services look up their keys in the)SH
+/Times-Italic SF
+46846 XM
+(srvtab)SH
+/Times-Roman SF
+49871 XM
+(file for)SH
+18200 30356 MT
+(use in the authentication process.)SH
+14 /Times-Bold AF
+7200 34203 MT
+(1.2 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(kuser)SH
+/Times-Bold SF
+15874 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 36398 MT
+(This directory contains the source code for several user-oriented programs.)SH
+/Times-Bold SF
+7200 38349 MT
+(kinit)SH
+/Times-Roman SF
+18200 XM
+(This program prompts users for their usernames and Kerberos passwords, then)SH
+18200 39545 MT
+(furnishes them with Kerberos ticket-granting tickets.)SH
+/Times-Bold SF
+7200 41240 MT
+(kdestroy)SH
+/Times-Roman SF
+18200 XM
+(This program destroys any active tickets.  Users should use)SH
+/Times-Italic SF
+44563 XM
+(kdestroy)SH
+/Times-Roman SF
+48564 XM
+(before they)SH
+18200 42436 MT
+(log off their workstations.)SH
+/Times-Bold SF
+7200 44131 MT
+(klist)SH
+/Times-Roman SF
+18200 XM
+(This program lists a user's active tickets.)SH
+/Times-Bold SF
+7200 45826 MT
+(ksrvtgt)SH
+/Times-Roman SF
+18200 XM
+(This retrieves a ticket-granting ticket with a life time of five minutes, using a)SH
+18200 47022 MT
+(server's secret key in lieu of a password.  It is primarily for use in shell scripts)SH
+18200 48218 MT
+(and other batch facilities.)SH
+/Times-Bold SF
+7200 49913 MT
+(ksu)SH
+/Times-Roman SF
+18200 XM
+(Substitute user id, using Kerberos to mediate attempts to change to ``root''.)SH
+14 /Times-Bold AF
+7200 53760 MT
+(1.3 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(appl)SH
+/Times-Bold SF
+15173 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 55955 MT
+(If your site has the appropriate BSD license, your Kerberos release provides certain Unix utilities The)SH
+7200 57151 MT
+(Berkeley programs that have been modified to use Kerberos authentication are found in the)SH
+/Times-Italic SF
+47640 XM
+(appl/bsd)SH
+/Times-Roman SF
+7200 58347 MT
+(directory. They)
+275 W( include)SH
+/Times-Italic SF
+18043 XM
+(login)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+20855 XM
+(rlogin)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+24095 XM
+(rsh)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+27914 XM
+(rcp)SH
+/Times-Roman SF
+(, as well as the associated daemon programs)SH
+/Times-Italic SF
+49081 XM
+(kshd)SH
+/Times-Roman SF
+51372 XM
+(and)SH
+/Times-Italic SF
+7200 59543 MT
+(klogind)SH
+/Times-Roman SF
+(. The)275 W
+/Times-Italic SF
+13310 XM
+(login)SH
+/Times-Roman SF
+15847 XM
+(program obtains ticket-granting tickets for users upon login; the other utilities provide)SH
+7200 60739 MT
+(authenticated Unix network services.)SH
+7200 63037 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(appl)SH
+/Times-Roman SF
+11416 XM
+(directory also contains samples Kerberos application client and server programs, an)SH
+7200 64233 MT
+(authenticated)SH
+/Times-Italic SF
+13339 XM
+(tftp)SH
+/Times-Roman SF
+15082 XM
+(program,)SH
+/Times-Italic SF
+19358 XM
+(knetd)SH
+/Times-Roman SF
+(, an authenticated inet daemon.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(2)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 3 4
+BS
+0 SI
+14 /Times-Bold AF
+7200 8167 MT
+(1.4 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(server)SH
+/Times-Bold SF
+16185 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 10362 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(server)SH
+/Times-Roman SF
+12208 XM
+(directory contains the Kerberos KDC server, called)SH
+/Times-Italic SF
+35052 XM
+(kerberos)SH
+/Times-Roman SF
+(. This)
+275 W( program manages read-)SH
+7200 11558 MT
+(only requests made to the master database, distributing tickets and encryption keys to clients requesting)SH
+7200 12754 MT
+(authentication service.)SH
+14 /Times-Bold AF
+7200 16601 MT
+(1.5 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(kadmin)SH
+/Times-Bold SF
+17040 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 18796 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(kadmin)SH
+/Times-Roman SF
+12698 XM
+(directory contains the Kerberos administration server and associated client programs.  The)SH
+7200 19992 MT
+(server accepts network requests from the user program)SH
+/Times-Italic SF
+31570 XM
+(kpasswd)SH
+/Times-Roman SF
+35573 XM
+(\050used to change a user's password\051, the)SH
+7200 21188 MT
+(Kerberos administration program)SH
+/Times-Italic SF
+22137 XM
+(kadmin)SH
+/Times-Roman SF
+(, and the srvtab utility program)SH
+/Times-Italic SF
+39276 XM
+(ksrvutil)SH
+/Times-Roman SF
+(. The)
+275 W( administration)SH
+7200 22384 MT
+(server can make modifications to the master database.)SH
+14 /Times-Bold AF
+7200 26231 MT
+(1.6 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(include)SH
+/Times-Bold SF
+16962 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 28426 MT
+(This directory contains the)SH
+/Times-Italic SF
+19236 XM
+(include)SH
+/Times-Roman SF
+22749 XM
+(files needed to build the Kerberos system.)SH
+14 /Times-Bold AF
+7200 32273 MT
+(1.7 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(lib)SH
+/Times-Bold SF
+14162 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 34468 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(lib)SH
+/Times-Roman SF
+10622 XM
+(directory has six subdirectories:)SH
+/Times-Italic SF
+25193 XM
+(acl)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+27087 XM
+(des)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+29103 XM
+(kadm)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+32035 XM
+(kdb)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+34173 XM
+(knet)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+38418 XM
+(krb)SH
+/Times-Roman SF
+(. The)275 W
+/Times-Italic SF
+42694 XM
+(des)SH
+/Times-Roman SF
+44435 XM
+(directory contains)SH
+7200 35664 MT
+(source for the DES encryption library.  The)SH
+/Times-Italic SF
+26595 XM
+(kadm)SH
+/Times-Roman SF
+29252 XM
+(directory contains source for the Kerberos)SH
+7200 36860 MT
+(administration server utility library.  The)SH
+/Times-Italic SF
+25439 XM
+(kdb)SH
+/Times-Roman SF
+27302 XM
+(directory contains source for the Kerberos database routine)SH
+7200 38056 MT
+(library. The)275 W
+/Times-Italic SF
+12942 XM
+(knet)SH
+/Times-Roman SF
+15049 XM
+(directory contains source for a library used by clients of the)SH
+/Times-Italic SF
+41530 XM
+(knetd)SH
+/Times-Roman SF
+44187 XM
+(server. The)275 W
+/Times-Italic SF
+49683 XM
+(krb)SH
+/Times-Roman SF
+7200 39252 MT
+(directory contains source for the)SH
+/Times-Italic SF
+21707 XM
+(libkrb.a)SH
+/Times-Roman SF
+25435 XM
+(library. This)
+275 W( library contains routines that are used by the)SH
+7200 40448 MT
+(Kerberos server program, and by applications programs that require authentication service.)SH
+14 /Times-Bold AF
+7200 44295 MT
+(1.8 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(man)SH
+/Times-Bold SF
+15251 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 46490 MT
+(This directory contains manual pages for Kerberos programs and library routines.)SH
+14 /Times-Bold AF
+7200 50337 MT
+(1.9 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(prototypes)SH
+/Times-Bold SF
+18596 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 52532 MT
+(This directory contains prototype)SH
+/Times-Italic SF
+22108 XM
+(/etc/services)SH
+/Times-Roman SF
+27819 XM
+(and)SH
+/Times-Italic SF
+29682 XM
+(/etc/krb.conf)SH
+/Times-Roman SF
+35486 XM
+(files. New)
+275 W( entries must be added to the)SH
+/Times-Italic SF
+7200 53728 MT
+(/etc/services)SH
+/Times-Roman SF
+12911 XM
+(file for the Kerberos server, and possibly for Kerberized applications \050)SH
+/Times-Italic SF
+(services.append)SH
+/Times-Roman SF
+7200 54924 MT
+(contains the entries used by the Athena-provided servers & applications, and is suitable for appending to)SH
+7200 56120 MT
+(your existing)SH
+/Times-Italic SF
+13250 XM
+(/etc/services)SH
+/Times-Roman SF
+18961 XM
+(file.\051. The)275 W
+/Times-Italic SF
+23878 XM
+(/etc/krb.conf)SH
+/Times-Roman SF
+29682 XM
+(file defines the local Kerberos realm for its host and)SH
+7200 57316 MT
+(lists Kerberos servers for given realms.  The)SH
+/Times-Italic SF
+26961 XM
+(/etc/krb.realms)SH
+/Times-Roman SF
+33865 XM
+(file defines exceptions for mapping machine)SH
+7200 58512 MT
+(names to Kerberos realms.)SH
+14 /Times-Bold AF
+7200 62359 MT
+(1.10 The)350 W
+/Times-BoldItalic SF
+13034 XM
+(tools)SH
+/Times-Bold SF
+16107 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 64554 MT
+(This directory contains a makefile to set up a directory tree for building the software in, and a shell script)SH
+7200 65750 MT
+(to format code in the style we use.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(3)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 4 5
+BS
+0 SI
+14 /Times-Bold AF
+7200 8167 MT
+(1.11 The)350 W
+/Times-BoldItalic SF
+13034 XM
+(util)SH
+/Times-Bold SF
+15329 XM
+(Directory)SH
+11 /Times-Roman AF
+7200 10362 MT
+(This directory contains several utility programs and libraries.  Included are Larry Wall's)SH
+/Times-Italic SF
+46296 XM
+(patch)SH
+/Times-Roman SF
+49015 XM
+(program, a)SH
+/Times-Italic SF
+7200 11558 MT
+(make)SH
+/Times-Roman SF
+9795 XM
+(pre-processor program called)SH
+/Times-Italic SF
+22956 XM
+(imake)SH
+/Times-Roman SF
+(, and a program for generating Makefile dependencies,)SH
+/Times-Italic SF
+7200 12754 MT
+(makedepend)SH
+/Times-Roman SF
+(, as well as the Sub-system library and utilities \050)SH
+/Times-Italic SF
+(ss)SH
+/Times-Roman SF
+(\051, and the Error table library and utilities)SH
+7200 13950 MT
+(\050)SH
+/Times-Italic SF
+(et)SH
+/Times-Roman SF
+(\051.)SH
+16 /Times-Bold AF
+7200 18622 MT
+(2. Preparing)
+400 W( for Installation)SH
+11 /Times-Roman AF
+7200 20817 MT
+(This document assumes that you will build the system on the machine on which you plan to install the)SH
+7200 22013 MT
+(Kerberos master server and its database.  You'll need about 10 megabytes for source and executables.)SH
+7200 24311 MT
+(By default, there must be a)SH
+/Times-Italic SF
+19327 XM
+(/kerberos)SH
+/Times-Roman SF
+23756 XM
+(directory on the master server machine in which to store the)SH
+7200 25507 MT
+(Kerberos database files.  If the master server machine does not have room on its root partition for these)SH
+7200 26703 MT
+(files, create a)SH
+/Times-Italic SF
+13306 XM
+(/kerberos)SH
+/Times-Roman SF
+17735 XM
+(symbolic link to another file system.)SH
+16 /Times-Bold AF
+7200 31375 MT
+(3. Preparing)
+400 W( for the Build)SH
+11 /Times-Roman AF
+7200 33570 MT
+(Before you build the system, you have to choose a)SH
+/Times-Bold SF
+29653 XM
+(realm name)SH
+/Times-Roman SF
+(, the name that specifies the system's)SH
+7200 34766 MT
+(administrative domain.  Project Athena uses the internet domain name ATHENA.MIT.EDU to specify its)SH
+7200 35962 MT
+(Kerberos realm name.  We recommend using a name of this form.)SH
+/Times-Bold SF
+36857 XM
+(NOTE:)SH
+/Times-Roman SF
+40616 XM
+(the realm-name is case)SH
+7200 37158 MT
+(sensitive; by convention, we suggest that you use your internet domain name, in capital letters.)SH
+7200 39456 MT
+(Edit the [SOURCE_DIR]/)SH
+/Times-Italic SF
+(include/krb.h)SH
+/Times-Roman SF
+24860 XM
+(file and look for the following lines of code:)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(4)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 5 6
+BS
+0 SI
+11 /Courier AF
+8520 7886 MT
+(/*)SH
+9180 9000 MT
+(* Kerberos specific definitions)SH
+9180 10114 MT
+(*)SH
+9180 11228 MT
+(* KRBLOG is the log file for the kerberos master server.)SH
+9180 12342 MT
+(* KRB_CONF is the configuration file where different host)SH
+9180 13456 MT
+(* machines running master and slave servers can be found.)SH
+9180 14570 MT
+(* KRB_MASTER is the name of the machine with the master)SH
+9180 15684 MT
+(* database.  The admin_server runs on this machine, and all)SH
+9180 16798 MT
+(* changes to the db \050as opposed to read-only requests, which)SH
+9180 17912 MT
+(* can go to slaves\051 must go to it.)SH
+9180 19026 MT
+(* KRB_HOST is the default machine when looking for a kerberos)SH
+9180 20140 MT
+(* slave server.  Other possibilities are in the KRB_CONF file.)SH
+9180 21254 MT
+(* KRB_REALM is the name of the realm.)SH
+9180 22368 MT
+(*/)SH
+8520 24596 MT
+(#ifdef notdef)SH
+8520 25710 MT
+(this is server-only, does not belong here;)SH
+8520 26824 MT
+(#define KRBLOG)
+3960 W( "/kerberos/kerberos.log")5940 W
+8520 27938 MT
+(are these used anyplace '?';)SH
+8520 29052 MT
+(#define VX_KRB_HSTFILE)
+9240 W( "/etc/krbhst")660 W
+8520 30166 MT
+(#define PC_KRB_HSTFILE)
+9240 W( "\134\134kerberos\134\134krbhst")660 W
+8520 31280 MT
+(#endif)SH
+8520 33508 MT
+(#define KRB_CONF)
+9240 W( "/etc/krb.conf")4620 W
+8520 34622 MT
+(#define KRB_RLM_TRANS)
+9240 W( "/etc/krb.realms")1320 W
+8520 35736 MT
+(#define KRB_MASTER)
+9240 W( "kerberos")3300 W
+8520 36850 MT
+(#define KRB_HOST)
+9240 W( KRB_MASTER)5280 W
+8520 37964 MT
+(#define KRB_REALM)
+9240 W( "ATHENA.MIT.EDU")3960 W
+/Times-Roman SF
+7200 39559 MT
+(Edit the last line as follows:)SH
+9400 41510 MT
+(1.)SH
+10500 XM
+(Change the KRB_REALM definition so that it specifies the realm name you have chosen)SH
+10500 42706 MT
+(for your Kerberos system.  This is a default which is usually overridden by a configuration)SH
+10500 43902 MT
+(file on each machine; however, if that config file is absent, many programs will use this)SH
+10500 45098 MT
+("built-in" realm name.)SH
+14 /Times-Bold AF
+7200 48945 MT
+(3.1 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(/etc/krb.conf)SH
+/Times-Bold SF
+19956 XM
+(File)SH
+11 /Times-Roman AF
+7200 51140 MT
+(Create a)SH
+/Times-Italic SF
+11108 XM
+(/etc/krb.conf)SH
+/Times-Roman SF
+16912 XM
+(file using the following format:)SH
+/Times-BoldItalic SF
+8520 52740 MT
+(realm_name)SH
+8520 53854 MT
+(realm_name master_server_name)1045 W
+/Courier SF
+25594 XM
+(admin server)SH
+/Times-Roman SF
+7200 55449 MT
+(where)SH
+/Times-Italic SF
+10161 XM
+(realm_name)SH
+/Times-Roman SF
+15934 XM
+(specifies the system's realm name, and)SH
+/Times-Italic SF
+33375 XM
+(master_server_name)SH
+/Times-Roman SF
+42874 XM
+(specifies the machine)SH
+7200 56645 MT
+(name on which you will run the master server.  The words 'admin server' must appear next to the name of)SH
+7200 57841 MT
+(the server on which you intend to run the administration server \050which must be a machine with access to)SH
+7200 59037 MT
+(the database\051.)SH
+7200 61335 MT
+(For example, if your realm name is)SH
+/Times-Italic SF
+22962 XM
+(tim.edu)SH
+/Times-Roman SF
+26506 XM
+(and your master server's name is)SH
+/Times-Italic SF
+41288 XM
+(kerberos.tim.edu)SH
+/Times-Roman SF
+(, the file)SH
+7200 62531 MT
+(should have these contents:)SH
+/Courier SF
+8520 64057 MT
+(tim.edu)SH
+8520 65171 MT
+(tim.edu kerberos.tim.edu)
+660 W( admin server)SH
+/Times-Roman SF
+7200 67469 MT
+(See the [SOURCE_DIR]/)SH
+/Times-Italic SF
+(prototypes/etc.krb.conf)SH
+/Times-Roman SF
+28921 XM
+(file for an example)SH
+/Times-Italic SF
+37533 XM
+(/etc/krb.conf)SH
+/Times-Roman SF
+43337 XM
+(file. That)
+275 W( file has)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(5)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 6 7
+BS
+0 SI
+11 /Times-Roman AF
+7200 7955 MT
+(examples of how to provide backup servers for a given realm \050additional lines with the same leading)SH
+7200 9151 MT
+(realm name\051 and how to designate servers for remote realms.)SH
+14 /Times-Bold AF
+7200 12998 MT
+(3.2 The)350 W
+/Times-BoldItalic SF
+12334 XM
+(/etc/krb.realms)SH
+/Times-Bold SF
+21280 XM
+(File)SH
+11 /Times-Roman AF
+7200 15193 MT
+(In many situations, the default realm in which a host operates will be identical to the domain portion its)SH
+7200 16389 MT
+(Internet domain name.)SH
+7200 18687 MT
+(If this is not the case, you will need to establish a translation from host name or domain name to realm)SH
+7200 19883 MT
+(name. This)
+275 W( is accomplished with the)SH
+/Times-Italic SF
+23820 XM
+(/etc/krb.realms)SH
+/Times-Roman SF
+30724 XM
+(file.)SH
+7200 22181 MT
+(Each line of the translation file specifies either a hostname or domain name, and its associated realm:)SH
+/Courier SF
+8520 23707 MT
+(.domain.name kerberos.realm1)SH
+8520 24821 MT
+(host.name kerberos.realm2)SH
+/Times-Roman SF
+7200 26416 MT
+(For example, to map all hosts in the domain LSC.TIM.EDU to KRB.REALM1 but the host)SH
+7200 27612 MT
+(FILMS.LSC.TIM.EDU to KRB.REALM2 your file would read:)SH
+/Courier SF
+8520 29138 MT
+(.LSC.TIM.EDU KRB.REALM1)SH
+8520 30252 MT
+(FILMS.LSC.TIM.EDU KRB.REALM2)SH
+/Times-Roman SF
+7200 31847 MT
+(If a particular host matches both a domain and a host entry, the host entry takes precedence.)SH
+16 /Times-Bold AF
+7200 36519 MT
+(4. Building)
+400 W( the Software)SH
+11 /Times-Roman AF
+7200 38714 MT
+(Before you build the software read the)SH
+/Times-Bold SF
+24395 XM
+(README)SH
+/Times-Roman SF
+29558 XM
+(file in [SOURCE_DIR].  What follows is a more)SH
+7200 39910 MT
+(detailed description of the instructions listed in README.)SH
+9400 41861 MT
+(1.)SH
+10500 XM
+(Create an [OBJ_DIR] directory to hold the tree of Kerberos object files you are about to)SH
+10500 43057 MT
+(build, for example,)SH
+/Times-Italic SF
+19145 XM
+(/mit/kerberos/obj)SH
+/Times-Roman SF
+(.)SH
+9400 44951 MT
+(2.)SH
+10500 XM
+(Change directory to [OBJ_DIR].  The following command creates directories under)SH
+10500 46147 MT
+([OBJ_DIR] and installs Makefiles for the final build.)SH
+/Courier SF
+11820 47724 MT
+(host%)SH
+/Times-Bold SF
+15780 XM
+(make -f [SOURCE_DIR]/tools/makeconfig SRCDIR=[SOURCE_DIR])275 W
+/Times-Roman SF
+9400 49618 MT
+(3.)SH
+10500 XM
+(Change directory to util/imake.includes.  Read through config.Imakefile, turning on)SH
+10500 50814 MT
+(appropriate flags for your installation.  Change SRCTOP so that it is set to the top level of)SH
+10500 52010 MT
+(your source directory.)SH
+9400 53904 MT
+(4.)SH
+10500 XM
+(Check that your machine type has a definition in include/osconf.h & related files in the)SH
+10500 55100 MT
+(source tree \050if it doesn't, then you may need to create your own; if you get successful)SH
+10500 56296 MT
+(results, please post to kerberos@athena.mit.edu\051)SH
+9400 58190 MT
+(5.)SH
+10500 XM
+(Change directory to [OBJ_DIR].  The next command generates new Makefiles based on the)SH
+10500 59386 MT
+(configuration you selected in config.Imakefile, then adds dependency information to the)SH
+10500 60582 MT
+(Makefiles, and finally builds the system:)SH
+/Courier SF
+11820 62159 MT
+(host%)SH
+/Times-Bold SF
+15780 XM
+(make world)275 W
+/Times-Roman SF
+10500 63754 MT
+(This command takes a while to complete; you may wish to redirect the output onto a file)SH
+10500 64950 MT
+(and put the job in the background:)SH
+/Courier SF
+11820 66527 MT
+(host%)SH
+/Times-Bold SF
+15780 XM
+(make world)
+275 W( >&WORLDLOG_891201 &)SH
+/Times-Roman SF
+10500 68122 MT
+(If you need to rebuild the Kerberos programs and libraries after making a change, you can)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(6)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 7 8
+BS
+0 SI
+11 /Times-Roman AF
+10500 7955 MT
+(usually just type:)SH
+/Courier SF
+11820 9532 MT
+(host%)SH
+/Times-Bold SF
+15780 XM
+(make all)275 W
+/Times-Roman SF
+10500 11127 MT
+(However, if you changed the configuration in config.Imakefile or modified the Imakefiles)SH
+10500 12323 MT
+(or Makefiles, you should run)SH
+/Times-Italic SF
+23514 XM
+(make world)SH
+/Times-Roman SF
+28952 XM
+(to re-build all the Makefiles and dependency lists.)SH
+14 /Times-Bold AF
+7200 16141 MT
+(4.1 Testing)
+350 W( the DES Library)SH
+11 /Times-Roman AF
+7200 18336 MT
+(Use the)SH
+/Times-Italic SF
+10804 XM
+(verify)SH
+/Times-Roman SF
+13583 XM
+(command to test the DES library implementation:)SH
+/Courier SF
+8520 19913 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([OBJ_DIR]/lib/des/verify)SH
+/Times-Roman SF
+7200 21508 MT
+(The command should display the following:)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(7)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 8 9
+BS
+0 SI
+11 /Courier AF
+8520 7886 MT
+(Examples per FIPS publication 81, keys ivs and cipher)SH
+8520 9000 MT
+(in hex.  These are the correct answers, see below for)SH
+8520 10114 MT
+(the actual answers.)SH
+8520 12342 MT
+(Examples per Davies and Price.)SH
+8520 14570 MT
+(EXAMPLE ECB)
+SH( key)
+2640 W( = 08192a3b4c5d6e7f)SH
+13800 15684 MT
+(clear = 0)SH
+13800 16798 MT
+(cipher = 25 dd ac 3e 96 17 64 67)SH
+8520 17912 MT
+(ACTUAL ECB)SH
+13800 19026 MT
+(clear "")SH
+13800 20140 MT
+(cipher =)
+660 W( \050low to high bytes\051)SH
+19080 21254 MT
+(25 dd ac 3e 96 17 64 67)SH
+8520 23482 MT
+(EXAMPLE ECB)
+SH( key)
+2640 W( = 0123456789abcdef)SH
+13800 24596 MT
+(clear = "Now is the time for all ")SH
+13800 25710 MT
+(cipher = 3f a4 0e 8a 98 4d 48 15 ...)SH
+8520 26824 MT
+(ACTUAL ECB)SH
+13800 27938 MT
+(clear "Now is the time for all ")SH
+13800 29052 MT
+(cipher =)
+660 W( \050low to high bytes\051)SH
+19080 30166 MT
+(3f a4 0e 8a 98 4d 48 15)SH
+8520 32394 MT
+(EXAMPLE CBC)
+SH( key)
+2640 W( = 0123456789abcdef  iv = 1234567890abcdef)SH
+13800 33508 MT
+(clear = "Now is the time for all ")SH
+13800 34622 MT
+(cipher =)
+SH( e5)
+4620 W( c7 cd de 87 2b f2 7c)SH
+24360 35736 MT
+(43 e9 34 00 8c 38 9c 0f)SH
+24360 36850 MT
+(68 37 88 49 9a 7c 05 f6)SH
+8520 37964 MT
+(ACTUAL CBC)SH
+13800 39078 MT
+(clear "Now is the time for all ")SH
+13800 40192 MT
+(ciphertext = \050low to high bytes\051)SH
+19080 41306 MT
+(e5 c7 cd de 87 2b f2 7c)SH
+19080 42420 MT
+(43 e9 34 00 8c 38 9c 0f)SH
+19080 43534 MT
+(68 37 88 49 9a 7c 05 f6)SH
+19080 44648 MT
+(00 00 00 00 00 00 00 00)SH
+19080 45762 MT
+(00 00 00 00 00 00 00 00)SH
+19080 46876 MT
+(00 00 00 00 00 00 00 00)SH
+19080 47990 MT
+(00 00 00 00 00 00 00 00)SH
+19080 49104 MT
+(00 00 00 00 00 00 00 00)SH
+13800 50218 MT
+(decrypted clear_text = "Now is the time for all ")SH
+8520 51332 MT
+(EXAMPLE CBC checksum)
+SH( key)
+1980 W( =  0123456789abcdef iv =  1234567890abcdef)SH
+13800 52446 MT
+(clear =)
+SH( "7654321)
+5280 W( Now is the time for ")SH
+13800 53560 MT
+(checksum 58)
+4620 W( d2 e7 7e 86 06 27 33  or some part thereof)SH
+8520 54674 MT
+(ACTUAL CBC checksum)SH
+19080 55788 MT
+(encrypted cksum = \050low to high bytes\051)SH
+19080 56902 MT
+(58 d2 e7 7e 86 06 27 33)SH
+/Times-Roman SF
+7200 59200 MT
+(If the)SH
+/Times-Italic SF
+9826 XM
+(verify)SH
+/Times-Roman SF
+12605 XM
+(command fails to display this information as specified above, the implementation of DES for)SH
+7200 60396 MT
+(your hardware needs to be adjusted.  Your Kerberos system cannot work properly if your DES library)SH
+7200 61592 MT
+(fails this test.)SH
+7200 63890 MT
+(When you have finished building the software, you will find the executables in the object tree as follows:)SH
+/Times-Bold SF
+7200 65841 MT
+([OBJ_DIR]/admin)SH
+/Times-Italic SF
+18200 XM
+(ext_srvtab)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+23332 XM
+(kdb_destroy)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+29258 XM
+(kdb_edit)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+33596 XM
+(kdb_init)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+37752 XM
+(kdb_util)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+43771 XM
+(kstash)SH
+/Times-Roman SF
+(.)SH
+/Times-Bold SF
+7200 67536 MT
+([OBJ_DIR]/kuser)SH
+/Times-Italic SF
+18200 XM
+(kdestroy)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+22476 XM
+(kinit)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+24982 XM
+(klist)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+27366 XM
+(ksrvtgt)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+32773 XM
+(ksu)SH
+/Times-Roman SF
+(.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(8)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 9 10
+BS
+0 SI
+11 /Times-Bold AF
+7200 7955 MT
+([OBJ_DIR]/server)SH
+/Times-Italic SF
+18200 XM
+(kerberos)SH
+/Times-Roman SF
+(.)SH
+/Times-Bold SF
+7200 9650 MT
+([OBJ_DIR]/appl/bsd)SH
+/Times-Italic SF
+18200 XM
+(klogind)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+22050 XM
+(kshd)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+24616 XM
+(login.krb)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+29169 XM
+(rcp)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+31185 XM
+(rlogin)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+36288 XM
+(rsh)SH
+/Times-Roman SF
+(.)SH
+/Times-Bold SF
+7200 11345 MT
+([OBJ_DIR]/appl/knetd)SH
+/Times-Italic SF
+18200 XM
+(knetd)SH
+/Times-Roman SF
+(.)SH
+/Times-Bold SF
+7200 13040 MT
+([OBJ_DIR]/appl/sample)SH
+/Times-Italic SF
+18200 14236 MT
+(sample_server)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+25164 XM
+(sample_client)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+31824 XM
+(simple_server)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+40407 XM
+(simple_client)SH
+/Times-Roman SF
+(.)SH
+/Times-Bold SF
+7200 15931 MT
+([OBJ_DIR]/appl/tftp)SH
+/Times-Italic SF
+18200 XM
+(tcom)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+20888 XM
+(tftpd)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+25319 XM
+(tftp)SH
+/Times-Roman SF
+(.)SH
+/Times-Bold SF
+7200 17626 MT
+([OBJ_DIR]/slave)SH
+/Times-Italic SF
+18200 XM
+(kprop)SH
+/Times-Roman SF
+21041 XM
+(and)SH
+/Times-Italic SF
+22904 XM
+(kpropd)SH
+/Times-Roman SF
+(.)SH
+16 /Times-Bold AF
+7200 22298 MT
+(5. Installing)
+400 W( the Software)SH
+11 /Times-Roman AF
+7200 24493 MT
+(To install the software, issue the)SH
+/Times-Italic SF
+21711 XM
+(make install)SH
+/Times-Roman SF
+27333 XM
+(command from the [OBJ_DIR] \050you need to be a privileged)SH
+7200 25689 MT
+(user in order to properly install the programs\051.  Programs can either be installed in default directories, or)SH
+7200 26885 MT
+(under a given root directory, as described below.)SH
+14 /Times-Bold AF
+7200 30703 MT
+(5.1 The)
+350 W( ``Standard'' Places)SH
+11 /Times-Roman AF
+7200 32898 MT
+(If you use the)SH
+/Times-Italic SF
+13492 XM
+(make)SH
+/Times-Roman SF
+16087 XM
+(command as follows:)SH
+/Courier SF
+8520 34475 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+(make install)275 W
+/Times-Roman SF
+7200 36070 MT
+(the installation process will try to install the various parts of the system in ``standard'' directories.  This)SH
+7200 37266 MT
+(process creates the ``standard'' directories as needed.)SH
+7200 39564 MT
+(The standard installation process copies things as follows:)SH
+/Symbol SF
+9169 41640 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The)SH
+/Times-Italic SF
+11935 XM
+(include)SH
+/Times-Roman SF
+15448 XM
+(files)SH
+/Times-Italic SF
+17617 XM
+(krb.h)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+20458 XM
+(des.h)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+23299 XM
+(mit-copyright.h)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+30662 XM
+(kadm.h)SH
+/Times-Roman SF
+34144 XM
+(and)SH
+/Times-Italic SF
+36007 XM
+(kadm_err.h)SH
+/Times-Roman SF
+41383 XM
+(get copied to the)SH
+/Times-Italic SF
+9950 42836 MT
+(/usr/include)SH
+/Times-Roman SF
+15481 XM
+(directory.)SH
+/Symbol SF
+9169 44730 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The Kerberos libraries)SH
+/Times-Italic SF
+20119 XM
+(libdes.a)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+24122 XM
+(libkrb.a)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+28125 XM
+(libkdb.a)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+32250 XM
+(libkadm.a)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+37169 XM
+(libknet.a)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+43401 XM
+(libacl.a)SH
+/Times-Roman SF
+47007 XM
+(get)SH
+9950 45926 MT
+(copied to the)SH
+/Times-Italic SF
+15907 XM
+(/usr/athena/lib)SH
+/Times-Roman SF
+22662 XM
+(\050or wherever you pointed LIBDIR in config.Imakefile\051)SH
+9950 47122 MT
+(directory.)SH
+/Symbol SF
+9169 49016 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The Kerberos master database utilities)SH
+/Times-Italic SF
+27085 XM
+(kdb_init)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+31241 XM
+(kdb_destroy)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+37167 XM
+(kdb_edit)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+41505 XM
+(kdb_util)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+45661 XM
+(kstash)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+9950 50212 MT
+(ext_srvtab)SH
+/Times-Roman SF
+14807 XM
+(get copied to the)SH
+/Times-Italic SF
+22383 XM
+(/usr/etc)SH
+/Times-Roman SF
+25958 XM
+(\050DAEMDIR\051 directory.)SH
+/Symbol SF
+9169 52106 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The Kerberos user utilities)SH
+/Times-Italic SF
+21924 XM
+(kinit)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+24430 XM
+(kdestroy)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+28706 XM
+(klist)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+31090 XM
+(ksrvtgt)SH
+/Times-Roman SF
+34359 XM
+(and)SH
+/Times-Italic SF
+36222 XM
+(ksu)SH
+/Times-Roman SF
+37963 XM
+(get copied to the)SH
+/Times-Italic SF
+45539 XM
+(/usr/athena)SH
+/Times-Roman SF
+9950 53302 MT
+(\050PROGDIR\051 directory.)SH
+/Symbol SF
+9169 55196 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The modified Berkeley utilities)SH
+/Times-Italic SF
+24004 XM
+(rsh)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+25960 XM
+(rlogin)SH
+/Times-Roman SF
+28925 XM
+(get copied to the)SH
+/Times-Italic SF
+36501 XM
+(/usr/ucb)SH
+/Times-Roman SF
+40382 XM
+(\050UCBDIR\051 directory;)SH
+/Times-Italic SF
+9950 56392 MT
+(rcp)SH
+/Times-Roman SF
+11691 XM
+(gets copied to the)SH
+/Times-Italic SF
+19695 XM
+(/bin)SH
+/Times-Roman SF
+21682 XM
+(\050SLASHBINDIR\051 directory; and)SH
+/Times-Italic SF
+36375 XM
+(rlogind)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+40165 XM
+(rshd)SH
+/Times-Roman SF
+(, and)SH
+/Times-Italic SF
+44534 XM
+(login.krb)SH
+/Times-Roman SF
+48812 XM
+(get)SH
+9950 57588 MT
+(copied to the)SH
+/Times-Italic SF
+15907 XM
+(/usr/etc)SH
+/Times-Roman SF
+19482 XM
+(\050DAEMDIR\051 directory.  The old copies of the user programs are)SH
+9950 58784 MT
+(renamed)SH
+/Times-Italic SF
+14011 XM
+(rsh.ucb)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+17830 XM
+(rlogin.ucb)SH
+/Times-Roman SF
+22658 XM
+(and)SH
+/Times-Italic SF
+24521 XM
+(rcp.ucb)SH
+/Times-Roman SF
+(, respectively.  The Kerberos versions of these)SH
+9950 59980 MT
+(programs are designed to fall back and execute the original versions if something prevents)SH
+9950 61176 MT
+(the Kerberos versions from succeeding.)SH
+/Symbol SF
+9169 63070 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The Kerberos version of)SH
+/Times-Italic SF
+20944 XM
+(tftp)SH
+/Times-Roman SF
+22687 XM
+(and)SH
+/Times-Italic SF
+24550 XM
+(tcom)SH
+/Times-Roman SF
+26963 XM
+(get copied to the)SH
+/Times-Italic SF
+34539 XM
+(/usr/athena)SH
+/Times-Roman SF
+39826 XM
+(\050PROGDIR\051 directory;)SH
+/Times-Italic SF
+9950 64266 MT
+(tftpd)SH
+/Times-Roman SF
+12243 XM
+(gets copied to the)SH
+/Times-Italic SF
+20247 XM
+(/etc)SH
+/Times-Roman SF
+22110 XM
+(\050ETCDIR\051 directory.)SH
+/Times-Italic SF
+31884 XM
+(tftp)SH
+/Times-Roman SF
+33627 XM
+(and)SH
+/Times-Italic SF
+35490 XM
+(tftpd)SH
+/Times-Roman SF
+37783 XM
+(are installed set-uid to an)SH
+9950 65462 MT
+(unprivileged user \050user id of DEF_UID\051.)SH
+/Symbol SF
+9169 67356 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The)SH
+/Times-Italic SF
+11935 XM
+(knetd)SH
+/Times-Roman SF
+14592 XM
+(daemon gets copied to the)SH
+/Times-Italic SF
+26353 XM
+(/usr/etc)SH
+/Times-Roman SF
+29928 XM
+(\050DAEMDIR\051 directory.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(9)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 10 11
+BS
+0 SI
+11 /Symbol AF
+9169 8080 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The Kerberos server)SH
+/Times-Italic SF
+19201 XM
+(kerberos)SH
+/Times-Roman SF
+(, the slave propagation software)SH
+/Times-Italic SF
+37343 XM
+(kprop)SH
+/Times-Roman SF
+40184 XM
+(and)SH
+/Times-Italic SF
+42047 XM
+(kpropd)SH
+/Times-Roman SF
+(, and the)SH
+9950 9276 MT
+(administration server)SH
+/Times-Italic SF
+19542 XM
+(kadmind)SH
+/Times-Roman SF
+23605 XM
+(get copied to the)SH
+/Times-Italic SF
+31181 XM
+(/usr/etc)SH
+/Times-Roman SF
+34756 XM
+(\050SVRDIR, SVRDIR, and)SH
+9950 10472 MT
+(DAEMDIR\051 directory.)SH
+/Symbol SF
+9169 12366 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The remote administration tools)SH
+/Times-Italic SF
+24310 XM
+(kpasswd)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+28588 XM
+(ksrvutil)SH
+/Times-Roman SF
+32163 XM
+(and)SH
+/Times-Italic SF
+34026 XM
+(kadmin)SH
+/Times-Roman SF
+37539 XM
+(get copied to the)SH
+/Times-Italic SF
+45115 XM
+(/usr/athena)SH
+/Times-Roman SF
+9950 13562 MT
+(\050PROGDIR\051 directory.)SH
+/Symbol SF
+9169 15456 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The Kerberos manual pages get installed in the appropriate)SH
+/Times-Italic SF
+36187 XM
+(/usr/man)SH
+/Times-Roman SF
+40374 XM
+(directories. Don't)275 W
+9950 16652 MT
+(forget to run)SH
+/Times-Italic SF
+15723 XM
+(makewhatis)SH
+/Times-Roman SF
+21192 XM
+(after installing the manual pages.)SH
+14 /Times-Bold AF
+7200 20470 MT
+(5.2 ``Non-Standard'')
+350 W( Installation)SH
+11 /Times-Roman AF
+7200 22665 MT
+(If you'd rather install the software in a different location, you can use the)SH
+/Times-Italic SF
+39667 XM
+(make)SH
+/Times-Roman SF
+42262 XM
+(command as follows,)SH
+7200 23861 MT
+(where [DEST_DIR] specifies an alternate destination directory which will be used as the root for the)SH
+7200 25057 MT
+(installed programs, i.e. programs that would normally be installed in /usr/athena would be installed in)SH
+7200 26253 MT
+([DEST_DIR]/usr/athena.)SH
+/Courier SF
+8520 27830 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+(make install DESTDIR=[DEST_DIR])275 W
+16 SS 
+7200 32502 MT
+(6. Conclusion)400 W
+11 /Times-Roman AF
+7200 34697 MT
+(Now that you have built and installed your Kerberos system, use the accompanying Kerberos Operation)SH
+4030 50 44224 34897 UL
+4398 50 48529 34897 UL
+7200 35893 MT
+(Notes to create a Kerberos Master database, install authenticated services, and start the Kerberos server.)SH
+2566 50 7200 36093 UL
+16 /Times-Bold AF
+7200 40565 MT
+(7. Acknowledgements)400 W
+11 /Times-Roman AF
+7200 42760 MT
+(We'd like to thank Henry Mensch and Jon Rochlis for helping us debug this document.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30100 XM
+(10)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: i 12
+BS
+0 SI
+14 /Times-Bold AF
+25272 8138 MT
+(Table of Contents)SH
+13 SS 
+7200 9781 MT
+(1. Organization)
+325 W( of the Source Directory)SH
+53350 XM
+(1)SH
+12 /Times-Roman AF
+9000 11136 MT
+(1.1 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(admin)SH
+/Times-Roman SF
+16701 XM
+(Directory)SH
+53400 XM
+(2)SH
+9000 12491 MT
+(1.2 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(kuser)SH
+/Times-Roman SF
+16300 XM
+(Directory)SH
+53400 XM
+(2)SH
+9000 13846 MT
+(1.3 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(appl)SH
+/Times-Roman SF
+15700 XM
+(Directory)SH
+53400 XM
+(2)SH
+9000 15201 MT
+(1.4 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(server)SH
+/Times-Roman SF
+16566 XM
+(Directory)SH
+53400 XM
+(3)SH
+9000 16556 MT
+(1.5 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(kadmin)SH
+/Times-Roman SF
+17301 XM
+(Directory)SH
+53400 XM
+(3)SH
+9000 17911 MT
+(1.6 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(include)SH
+/Times-Roman SF
+17234 XM
+(Directory)SH
+53400 XM
+(3)SH
+9000 19266 MT
+(1.7 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(lib)SH
+/Times-Roman SF
+14834 XM
+(Directory)SH
+53400 XM
+(3)SH
+9000 20621 MT
+(1.8 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(man)SH
+/Times-Roman SF
+15767 XM
+(Directory)SH
+53400 XM
+(3)SH
+9000 21976 MT
+(1.9 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(prototypes)SH
+/Times-Roman SF
+18634 XM
+(Directory)SH
+53400 XM
+(3)SH
+9000 23331 MT
+(1.10 The)300 W
+/Times-BoldItalic SF
+13866 XM
+(tools)SH
+/Times-Roman SF
+16501 XM
+(Directory)SH
+53400 XM
+(3)SH
+9000 24686 MT
+(1.11 The)300 W
+/Times-BoldItalic SF
+13866 XM
+(util)SH
+/Times-Roman SF
+15835 XM
+(Directory)SH
+53400 XM
+(4)SH
+13 /Times-Bold AF
+7200 26329 MT
+(2. Preparing)
+325 W( for Installation)SH
+53350 XM
+(4)SH
+7200 27972 MT
+(3. Preparing)
+325 W( for the Build)SH
+53350 XM
+(4)SH
+12 /Times-Roman AF
+9000 29327 MT
+(3.1 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(/etc/krb.conf)SH
+/Times-Roman SF
+19801 XM
+(File)SH
+53400 XM
+(5)SH
+9000 30682 MT
+(3.2 The)300 W
+/Times-BoldItalic SF
+13266 XM
+(/etc/krb.realms)SH
+/Times-Roman SF
+20936 XM
+(File)SH
+53400 XM
+(6)SH
+13 /Times-Bold AF
+7200 32325 MT
+(4. Building)
+325 W( the Software)SH
+53350 XM
+(6)SH
+12 /Times-Roman AF
+9000 33674 MT
+(4.1 Testing)
+300 W( the DES Library)SH
+53400 XM
+(7)SH
+13 /Times-Bold AF
+7200 35317 MT
+(5. Installing)
+325 W( the Software)SH
+53350 XM
+(9)SH
+12 /Times-Roman AF
+9000 36666 MT
+(5.1 The)
+300 W( ``Standard'' Places)SH
+53400 XM
+(9)SH
+9000 38015 MT
+(5.2 ``Non-Standard'')
+300 W( Installation)SH
+52800 XM
+(10)SH
+13 /Times-Bold AF
+7200 39658 MT
+(6. Conclusion)325 W
+52700 XM
+(10)SH
+7200 41301 MT
+(7. Acknowledgements)325 W
+52700 XM
+(10)SH
+10 /Times-Roman AF
+7200 75600 MT
+(MIT Project Athena)SH
+30461 XM
+(i)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Trailer
+%%Pages: 12
+%%DocumentFonts: Times-Roman Times-Bold Times-Italic Times-BoldItalic Courier Symbol
diff --git a/krb5-1-6/doc/old-V4-docs/installation.mss b/krb5-1-6/doc/old-V4-docs/installation.mss
new file mode 100644
index 000000000..0a2ae7595
--- /dev/null
+++ b/krb5-1-6/doc/old-V4-docs/installation.mss
@@ -0,0 +1,681 @@
+@Comment[	$Source$]
+@Comment[	$Author$]
+@Comment[	$Id$]
+@Comment[]
+@device[postscript]
+@make[report]
+@comment[
+@DefineFont(HeadingFont,
+      P=<RawFont "NewCenturySchlbkBoldItalic">,
+      B=<RawFont "NewCenturySchlbkBold">,
+      I=<RawFont "NewCenturySchlbkBoldItalic">,
+      R=<RawFont "NewCenturySchlbkRoman">)
+]
+@DefineFont(HeadingFont,
+      P=<RawFont "TimesBoldItalic">,
+      B=<RawFont "TimesBold">,
+      I=<RawFont "TimesItalic">,
+      R=<RawFont "TimesRoman">)
+@Counter(MajorPart,TitleEnv HD0,ContentsEnv tc0,Numbered [@I],
+          IncrementedBy Use,Announced)
+@Counter(Chapter,TitleEnv HD1,ContentsEnv tc1,Numbered [@1. ],
+          IncrementedBy Use,Referenced [@1],Announced)
+@Counter(Appendix,TitleEnv HD1,ContentsEnv tc1,Numbered [@A. ],
+          IncrementedBy,Referenced [@A],Announced,Alias Chapter)
+@Counter(UnNumbered,TitleEnv HD1,ContentsEnv tc1,Announced,Alias 
+           Chapter)
+@Counter(Section,Within Chapter,TitleEnv HD2,ContentsEnv tc2,
+          Numbered [@#@:.@1 ],Referenced [@#@:.@1],IncrementedBy
+          Use,Announced)
+@Counter(AppendixSection,Within Appendix,TitleEnv HD2,
+          ContentsEnv tc2,
+          Numbered [@#@:.@1 ],Referenced [@#@:.@1],IncrementedBy 
+          Use,Announced)
+@Counter(SubSection,Within Section,TitleEnv HD3,ContentsEnv tc3,
+          Numbered [@#@:.@1 ],IncrementedBy Use,
+          Referenced [@#@:.@1 ])
+@Counter(AppendixSubSection,Within AppendixSection,TitleEnv HD3,
+          ContentsEnv tc3,
+          Numbered [@#@:.@1 ],IncrementedBy Use,
+          Referenced [@#@:.@1 ])
+@Counter(Paragraph,Within SubSection,TitleEnv HD4,ContentsEnv tc4,
+          Numbered [@#@:.@1 ],Referenced [@#@:.@1],
+          IncrementedBy Use)
+@modify(CopyrightNotice, Fixed -1 inch, Flushright)
+@Modify(Titlebox, Fixed 3.0 inches)
+@Modify(hd1, below .2 inch, facecode B, size 16, spaces kept, pagebreak off)
+@Modify(hd2, below .2 inch, facecode B, size 14, spaces kept)
+@Modify(hd3, below .2 inch, facecode B, size 12, spaces kept)
+@Modify(Description, Leftmargin +20, Indent -20,below 1 line, above 1 line)
+@Modify(Tc1, Above .5,  Facecode B)
+@Modify(Tc2, Above .25, Below .25, Facecode R)
+@Modify(Tc3,Facecode R)
+@Modify(Tc4,Facecode R)
+@Modify(Itemize,Above 1line,Below 1line)
+@Modify(Insert,LeftMargin +2, RightMargin +2)
+@libraryfile[stable]
+@comment[@Style(Font NewCenturySchoolBook, size 11)]
+@Style(Font TimesRoman, size 11)
+@Style(Spacing 1.1, indent 0)
+@Style(leftmargin 1.0inch)
+@Style(justification no)
+@Style(BottomMargin 1.5inch)
+@Style(ChangeBarLocation Right)
+@Style(ChangeBars=off)
+@pageheading[immediate]
+@pagefooting[immediate, left = "MIT Project Athena", center = "@value(page)",
+right = "@value(date)"]
+@set[page = 0]
+@blankspace[.5 inches]
+@begin[group, size 20]
+@begin(center)
+@b[Kerberos Installation Notes]
+@b[DRAFT]
+@end[center]
+@end(group)
+@blankspace[.5 inches]
+@begin[group, size 16]
+@begin(center)
+Bill Bryant
+Jennifer Steiner
+John Kohl
+@blankspace[1 line]
+Project Athena, MIT
+@blankspace[.5 inches]
+@b[Initial Release, January 24, 1989]
+@i[(plus later patches through patchlevel 7)]
+@end[center]
+@end(group)
+@begin[group, size 10]
+@end[group]
+@blankspace[.75 inches]
+
+
+The release consists of three parts.
+
+The first part consists of the core Kerberos system, which was developed
+at MIT and does not require additional licenses for us to distribute.
+Included in this part are the Kerberos authentication server, the
+Kerberos library, the
+@i[ndbm]
+database interface library, user programs, administration programs,
+manual pages, some applications which use Kerberos for authentication,
+and some utilities.
+
+The second part is the Data Encryption Standard (DES) library, which we
+are distributing only within the United States.
+
+The third part contains Kerberos modifications to Sun's NFS, which we
+distribute as ``context diffs'' to the Sun NFS source code.  Its
+distribution is controlled to provide an accounting of who has retrieved
+the patches, so that Project Athena can comply with its agreements with
+Sun regarding distribution of these changes.
+
+@newpage()
+@chapter[Organization of the Source Directory]
+
+The Kerberos building and installation process,
+as described in this document,
+builds the binaries and executables from the files contained in the Kerberos
+source tree, and deposits them in a separate object tree.
+This is intended to easily support several different build trees from a
+single source tree (this is useful if you support several machine
+architectures).
+We suggest that you copy the Kerberos sources into a
+@i[/mit/kerberos/src] directory,
+and create as well a @i[/mit/kerberos/obj] directory in which
+to hold the executables.
+In the rest of this document, we'll refer to the Kerberos
+source and object directories as [SOURCE_DIR]
+and [OBJ_DIR], respectively.
+
+Below is a brief overview of the organization of the complete
+source directory.
+More detailed descriptions follow.
+
+@begin[description]
+
+@b[admin]@\utilities for the Kerberos administrator
+
+@b[appl]@\applications that use Kerberos
+
+@b[appl/bsd]@\Berkeley's rsh/rlogin suite, using Kerberos
+
+@b[appl/knetd]@\(old) software for inetd-like multiplexing of a single
+TCP listening port
+
+@b[appl/sample]@\sample application servers and clients
+
+@b[appl/tftp]@\Trivial File Transfer Protocol, using Kerberos
+
+@b[include]@\include files
+
+@b[kadmin]@\remote administrative interface to the Kerberos master database
+
+@b[kuser]@\assorted user programs
+
+@b[lib]@\libraries for use with/by Kerberos
+
+@b[lib/acl]@\Access Control List library
+
+@b[lib/des]@\Data Encryption Standard library (US only)
+
+@b[lib/kadm]@\administrative interface library
+
+@b[lib/kdb]@\Kerberos server library interface to @i[ndbm]
+
+@b[lib/knet]@\(old) library for use with @b[knetd]
+
+@b[lib/krb]@\Kerberos library
+
+@b[man]@\manual pages
+
+@b[prototypes]@\sample configuration files
+
+@b[server]@\the authentication server
+
+@b[slave]@\Kerberos slave database propagation software
+
+@b[tools]@\shell scripts for maintaining the source tree
+
+@b[util]@\utilities
+
+@b[util/imake]@\Imakefile-to-Makefile ``compilation'' tool
+
+@b[util/ss]@\Sub-system library (for command line subsystems)
+
+@b[util/et]@\Error-table library (for independent, unique error codes)
+
+@b[util/makedepend]@\Makefile dependency generator tool
+
+@end[description]
+
+@section[The @p(admin) Directory]
+
+This directory contains source for
+the Kerberos master database administration tools.
+@begin[description]
+@b[kdb_init]@\This program creates and initializes the
+Kerberos master database.
+It prompts for a Kerberos realmname, and the Kerberos master password.
+
+@b[kstash]@\This program ``stashes'' the master password in the file
+@i[/.k] so that the master server machine can restart the Kerberos
+server automatically after an unattended reboot.
+The hidden password is also available to administrative programs
+that have been set to run automatically.
+
+@b[kdb_edit]@\This program is a low-level tool for editing
+the master database.
+
+@b[kdb_destroy]@\This program deletes the master database.
+
+@b[kdb_util]@\This program can be used to dump the master database
+into an ascii file, and can also be used to load the ascii file
+into the master database.
+
+@b[ext_srvtab]@\This program extracts information from the master
+database and creates a host-dependent @i[srvtab] file.
+This file contains the Kerberos keys for the host's
+``Kerberized'' services.
+These services look up their keys in the @i[srvtab] file
+for use in the authentication process.
+@end[description]
+
+@section[The @p(kuser) Directory]
+
+This directory contains the source code for several user-oriented
+programs.
+@begin[description]
+@b[kinit]@\This program prompts users for their usernames and
+Kerberos passwords, then furnishes them with Kerberos ticket-granting
+tickets.
+
+@b[kdestroy]@\This program destroys any active tickets.
+Users should use @i[kdestroy] before they log off their workstations.
+
+@b[klist]@\This program lists a user's active tickets.
+
+@b[ksrvtgt]@\This retrieves a ticket-granting ticket with a life time
+of five minutes, using a server's secret key in lieu of a password.  It
+is primarily for use in shell scripts and other batch facilities.
+
+@b[ksu]@\Substitute user id, using Kerberos to mediate attempts to
+change to ``root''.
+@end[description]
+
+@section[The @p(appl) Directory]
+
+If your site has the appropriate BSD license,
+your Kerberos release provides certain Unix utilities
+The Berkeley programs that have been modified to use Kerberos
+authentication are found in the @i[appl/bsd] directory.
+They include @i[login], @i[rlogin], @i[rsh], and @i[rcp], as well as the
+associated daemon programs @i[kshd] and @i[klogind].
+The @i[login] program obtains ticket-granting tickets for users
+upon login; the other utilities provide authenticated
+Unix network services.
+
+The @i[appl] directory also contains samples Kerberos application
+client and server programs, an authenticated @i[tftp] program,
+@i[knetd], an authenticated inet daemon.
+
+@section[The @p(server) Directory]
+
+The @i[server] directory contains the Kerberos KDC server, called
+@i[kerberos].
+This program manages read-only requests made to the
+master database,
+distributing tickets and encryption keys to clients requesting
+authentication service.
+
+@section[The @p(kadmin) Directory]
+
+The @i[kadmin] directory contains the Kerberos administration server and
+associated client programs.
+The server accepts network requests from the
+user program @i[kpasswd] (used to change a user's password), the
+Kerberos administration program @i(kadmin), and the srvtab utility
+program @i[ksrvutil].
+The administration server can make modifications to the master database.
+
+@section[The @p(include) Directory]
+
+This directory contains the @i[include] files needed to
+build the Kerberos system.
+
+@section[The @p(lib) Directory]
+
+The @i[lib] directory has six subdirectories:
+@i[acl], @i[des], @i[kadm], @i[kdb], @i[knet], and @i[krb].
+The @i[des] directory contains source for the DES encryption library.
+The @i[kadm] directory contains source for the Kerberos administration
+server utility library.
+The @i[kdb] directory contains source for the Kerberos database
+routine library.
+The @i[knet] directory contains source for a library used by clients of
+the @i[knetd] server.
+The @i[krb] directory contains source for the @i[libkrb.a]
+library.
+This library contains routines that are used by the Kerberos server program,
+and by applications programs that require authentication service.
+
+@section[The @p(man) Directory]
+
+This directory contains manual pages for Kerberos programs and
+library routines.
+
+@section[The @p(prototypes) Directory]
+
+This directory contains prototype
+@i[/etc/services] and @i[/etc/krb.conf] files.
+New entries must be added to the @i[/etc/services] file for
+the Kerberos server, and possibly for Kerberized applications
+(@i[services.append] contains the entries used by the Athena-provided
+servers & applications, and is suitable for appending to your existing
+@i[/etc/services] file.).
+The @i[/etc/krb.conf] file defines the local Kerberos realm
+for its host and lists Kerberos servers for given realms.
+The @i[/etc/krb.realms] file defines exceptions for mapping machine
+names to Kerberos realms.
+
+@section[The @p(tools) Directory]
+
+This directory contains
+a makefile to set up a directory tree
+for building the software in, and
+a shell script to format code in the
+style we use.
+
+
+@section[The @p(util) Directory]
+
+This directory contains several utility programs and libraries.
+Included are Larry Wall's @i[patch] program, a @i[make] pre-processor
+program called
+@i[imake], and a program for generating Makefile dependencies,
+@i[makedepend], as well as the Sub-system library and
+utilities (@i[ss]), and the Error table library and utilities (@i[et]).
+
+@chapter[Preparing for Installation]
+
+This document assumes that you will build the system
+on the machine on which you plan to install
+the Kerberos master server and its database.
+You'll need about 10 megabytes for source and executables.
+
+By default, there must be
+a @i[/kerberos] directory on the master server machine
+in which to store the Kerberos
+database files.
+If the master server machine does not have room on its root partition
+for these files,
+create a @i[/kerberos] symbolic link to another file system.
+
+@chapter[Preparing for the Build]
+
+Before you build the system,
+you have to choose a @b[realm name],
+the name that specifies the system's administrative domain.
+Project Athena uses the internet domain name ATHENA.MIT.EDU
+to specify its Kerberos realm name.
+We recommend using a name of this form.
+@b[NOTE:] the realm-name is case sensitive; by convention, we suggest
+that you use your internet domain name, in capital letters.
+
+Edit the [SOURCE_DIR]/@i[include/krb.h] file and look for the following
+lines of code:
+@begin[example]
+/*
+ * Kerberos specific definitions
+ *
+ * KRBLOG is the log file for the kerberos master server.
+ * KRB_CONF is the configuration file where different host
+ * machines running master and slave servers can be found.
+ * KRB_MASTER is the name of the machine with the master
+ * database.  The admin_server runs on this machine, and all
+ * changes to the db (as opposed to read-only requests, which
+ * can go to slaves) must go to it.
+ * KRB_HOST is the default machine when looking for a kerberos
+ * slave server.  Other possibilities are in the KRB_CONF file.
+ * KRB_REALM is the name of the realm.
+ */
+
+#ifdef notdef
+this is server-only, does not belong here;
+#define       KRBLOG          "/kerberos/kerberos.log"
+are these used anyplace '?';
+#define               VX_KRB_HSTFILE  "/etc/krbhst"
+#define               PC_KRB_HSTFILE  "\\kerberos\\krbhst"
+#endif
+
+#define               KRB_CONF        "/etc/krb.conf"
+#define               KRB_RLM_TRANS   "/etc/krb.realms"
+#define               KRB_MASTER      "kerberos"
+#define               KRB_HOST         KRB_MASTER
+#define               KRB_REALM       "ATHENA.MIT.EDU"
+@end[example]
+Edit the last line as follows:
+@begin[enumerate]
+Change the KRB_REALM definition so that it specifies the realm name
+you have chosen for your Kerberos system.  This is a default which is
+usually overridden by a configuration file on each machine; however, if
+that config file is absent, many programs will use this "built-in" realm
+name.
+@end[enumerate]
+
+@section[The @p(/etc/krb.conf) File]
+
+Create a @i[/etc/krb.conf] file using the following format:
+@begin[example]
+@p[realm_name]
+@p[realm_name]  @p[master_server_name] admin server
+@end[example]
+where @i[realm_name] specifies the system's realm name,
+and @i[master_server_name] specifies the machine name on
+which you will run the master server.  The words 'admin server' must
+appear next to the name of the server on which you intend to run the
+administration server (which must be a machine with access to the database).
+
+For example,
+if your realm name is @i[tim.edu] and your master server's name is
+@i[kerberos.tim.edu], the file should have these contents:
+@begin[example]
+tim.edu
+tim.edu  kerberos.tim.edu admin server
+@end[example]
+
+See the [SOURCE_DIR]/@i[prototypes/etc.krb.conf] file for an
+example @i[/etc/krb.conf] file.  That file has examples of how to
+provide backup servers for a given realm (additional lines with the same
+leading realm name) and how to designate servers for remote realms.
+
+@section[The @p(/etc/krb.realms) File]
+
+In many situations, the default realm in which a host operates will be
+identical to the domain portion its Internet domain name.
+
+If this is not the case, you will need to establish a translation from
+host name or domain name to realm name.  This is accomplished with the
+@i(/etc/krb.realms) file.
+
+Each line of the translation file specifies either a hostname or domain
+name, and its associated realm:
+@begin[example]
+.domain.name kerberos.realm1
+host.name kerberos.realm2
+@end[example]
+For example, to map all hosts in the domain LSC.TIM.EDU to KRB.REALM1
+but the host FILMS.LSC.TIM.EDU to KRB.REALM2 your file would read:
+@begin[example]
+.LSC.TIM.EDU KRB.REALM1
+FILMS.LSC.TIM.EDU KRB.REALM2
+@end[example]
+If a particular host matches both a domain and a host entry, the host
+entry takes precedence.
+
+@chapter[Building the Software]
+
+Before you build the software
+read the @b[README] file in [SOURCE_DIR].
+What follows is a more detailed description of the instructions
+listed in README.
+@begin[enumerate]
+Create an [OBJ_DIR] directory to hold the tree of Kerberos object files you
+are about to build, for example,
+@i[/mit/kerberos/obj].
+
+Change directory to [OBJ_DIR].
+The following command creates directories under [OBJ_DIR]
+and installs Makefiles for the final build.
+@begin[example, rightmargin -7]
+host% @b(make  -f  [SOURCE_DIR]/tools/makeconfig  SRCDIR=[SOURCE_DIR])
+@end[example]
+
+
+
+Change directory to util/imake.includes.  Read through config.Imakefile,
+turning on appropriate flags for your installation.  Change SRCTOP so
+that it is set to the top level of your source directory.
+
+Check that your machine type has a definition in include/osconf.h &
+related files in the source tree (if it doesn't, then you may need to
+create your own; if you get successful results, please post to
+kerberos@@athena.mit.edu)
+
+Change directory to [OBJ_DIR].  The next command generates new Makefiles
+based on the configuration you selected in config.Imakefile, then adds
+dependency information to the Makefiles, and finally builds the system:
+@begin[example, rightmargin -7]
+host% @b(make  world)
+@end[example]
+This command takes a while to complete; you may wish to redirect the
+output onto a file and put the job in the background:
+@begin[example, rightmargin -7]
+host% @b(make  world >&WORLDLOG_891201 &)
+@end[example]
+If you need to rebuild the Kerberos programs and libraries after making
+a change, you can usually just type:
+@begin[example, rightmargin -7]
+host% @b(make  all)
+@end[example]
+However, if you changed the configuration in config.Imakefile or modified
+the Imakefiles or Makefiles, you should run @i[make world] to re-build
+all the Makefiles and dependency lists.
+@end(enumerate)
+
+@section[Testing the DES Library]
+
+Use the @i[verify] command to test the DES library
+implementation:
+@begin[example]
+host% @b([OBJ_DIR]/lib/des/verify)
+@end[example]
+The command should display the following:
+@begin[example, rightmargin -10]
+Examples per FIPS publication 81, keys ivs and cipher
+in hex.  These are the correct answers, see below for
+the actual answers.
+
+Examples per Davies and Price.
+
+EXAMPLE ECB     key = 08192a3b4c5d6e7f
+        clear = 0
+        cipher = 25 dd ac 3e 96 17 64 67
+ACTUAL ECB
+        clear ""
+        cipher  = (low to high bytes)
+                25 dd ac 3e 96 17 64 67 
+
+EXAMPLE ECB     key = 0123456789abcdef
+        clear = "Now is the time for all "
+        cipher = 3f a4 0e 8a 98 4d 48 15 ...
+ACTUAL ECB
+        clear "Now is the time for all "
+        cipher  = (low to high bytes)
+                3f a4 0e 8a 98 4d 48 15 
+
+EXAMPLE CBC     key = 0123456789abcdef  iv = 1234567890abcdef
+        clear = "Now is the time for all "
+        cipher =        e5 c7 cd de 87 2b f2 7c
+                        43 e9 34 00 8c 38 9c 0f
+                        68 37 88 49 9a 7c 05 f6
+ACTUAL CBC
+        clear "Now is the time for all "
+        ciphertext = (low to high bytes)
+                e5 c7 cd de 87 2b f2 7c 
+                43 e9 34 00 8c 38 9c 0f 
+                68 37 88 49 9a 7c 05 f6 
+                00 00 00 00 00 00 00 00 
+                00 00 00 00 00 00 00 00 
+                00 00 00 00 00 00 00 00 
+                00 00 00 00 00 00 00 00 
+                00 00 00 00 00 00 00 00 
+        decrypted clear_text = "Now is the time for all "
+EXAMPLE CBC checksum    key =  0123456789abcdef iv =  1234567890abcdef
+        clear =         "7654321 Now is the time for "
+        checksum        58 d2 e7 7e 86 06 27 33  or some part thereof
+ACTUAL CBC checksum
+                encrypted cksum = (low to high bytes)
+                58 d2 e7 7e 86 06 27 33
+@end[example]
+
+If the @i[verify] command fails to display this information as specified
+above, the implementation of DES for your hardware needs to
+be adjusted.
+Your Kerberos system cannot work properly if your DES library
+fails this test.
+
+When you have finished building the software,
+you will find the executables in the object tree as follows:
+@begin[description]
+@b([OBJ_DIR]/admin)@\@i[ext_srvtab], @i[kdb_destroy],
+@i[kdb_edit], @i[kdb_init], @i[kdb_util], and @i[kstash].
+
+@b([OBJ_DIR]/kuser)@\@i[kdestroy], @i[kinit], @i[klist], @i[ksrvtgt],
+and @i[ksu].
+
+@b([OBJ_DIR]/server)@\@i[kerberos].
+
+@b([OBJ_DIR]/appl/bsd)@\@i[klogind], @i[kshd], @i[login.krb], @i[rcp],
+@i[rlogin], and @i[rsh].
+
+@b([OBJ_DIR]/appl/knetd)@\@i[knetd].
+
+@b([OBJ_DIR]/appl/sample)@\@i[sample_server], @i[sample_client],
+@i[simple_server], and @i[simple_client].
+
+@b([OBJ_DIR]/appl/tftp)@\@i[tcom], @i[tftpd], and @i[tftp].
+
+@b([OBJ_DIR]/slave)@\@i[kprop] and @i[kpropd].
+@end[description]
+
+@chapter[Installing the Software]
+
+To install the software, issue the @i[make install] command from
+the [OBJ_DIR] (you need to be a privileged user in order to
+properly install the programs).
+Programs can either be installed in default directories, or under
+a given root directory, as described below.
+
+@section[The ``Standard'' Places]
+
+If you use the @i[make] command as follows:
+@begin[example]
+host# @b(make  install)
+@end[example]
+the installation process will try to install the various parts of the
+system in ``standard'' directories.
+This process creates the ``standard'' directories as needed.
+
+The standard installation process copies things as follows:
+@begin[itemize]
+The @i[include] files @i[krb.h], @i[des.h], @i[mit-copyright.h],
+@i[kadm.h] and @i[kadm_err.h] get copied to the
+@i[/usr/include] directory.
+
+The Kerberos libraries @i[libdes.a], @i[libkrb.a], @i[libkdb.a],
+@i[libkadm.a], @i[libknet.a], and @i[libacl.a] get copied
+to the @i[/usr/athena/lib] (or wherever you pointed LIBDIR in
+config.Imakefile) directory.
+
+The Kerberos master database utilities @i[kdb_init], @i[kdb_destroy],
+@i[kdb_edit], @i[kdb_util], @i[kstash], and @i[ext_srvtab] get copied to
+the @i[/usr/etc] (DAEMDIR) directory.
+
+The Kerberos user utilities @i[kinit], @i[kdestroy], @i[klist],
+@i[ksrvtgt] and @i[ksu] get copied to the @i[/usr/athena] (PROGDIR)
+directory.
+
+The modified Berkeley utilities @i[rsh], @i[rlogin] get copied to the
+@i[/usr/ucb] (UCBDIR) directory; @i[rcp] gets copied to the @i[/bin]
+(SLASHBINDIR) directory; and @i[rlogind], @i[rshd], and @i[login.krb]
+get copied to the @i[/usr/etc] (DAEMDIR) directory.  The old copies of
+the user programs are renamed @i(rsh.ucb), @i(rlogin.ucb) and
+@i(rcp.ucb), respectively.  The Kerberos versions of these programs are
+designed to fall back and execute the original versions if something
+prevents the Kerberos versions from succeeding.
+
+The Kerberos version of @i[tftp] and @i[tcom] get copied to the
+@i[/usr/athena] (PROGDIR) directory; @i[tftpd] gets copied to the
+@i[/etc] (ETCDIR) directory.  @i[tftp] and @i[tftpd] are installed
+set-uid to an unprivileged user (user id of DEF_UID).
+
+The @i[knetd] daemon gets copied to the @i[/usr/etc] (DAEMDIR) directory.
+
+The Kerberos server @i[kerberos], the slave propagation software
+@i[kprop] and @i[kpropd], and the administration server @i[kadmind] get
+copied to the @i[/usr/etc] (SVRDIR, SVRDIR, and DAEMDIR) directory.
+
+The remote administration tools @i[kpasswd], @i[ksrvutil] and @i[kadmin]
+get copied to the @i[/usr/athena] (PROGDIR) directory.
+
+The Kerberos manual pages get installed in the appropriate
+@i[/usr/man] directories.  Don't forget to run @i[makewhatis]
+after installing the manual pages.
+
+@end[itemize]
+
+@section[``Non-Standard'' Installation]
+
+If you'd rather install the software in a different location,
+you can use the @i[make] command as follows,
+where [DEST_DIR] specifies an alternate destination directory
+which will be used as the root for the installed programs, i.e. programs
+that would normally be installed in /usr/athena would be installed in
+[DEST_DIR]/usr/athena.
+@begin[example]
+host# @b(make  install  DESTDIR=[DEST_DIR])
+@end[example]
+
+@chapter[Conclusion]
+
+Now that you have built and installed your Kerberos system,
+use the accompanying @u[Kerberos Operation Notes]
+to create a Kerberos Master database, install authenticated services,
+and start the Kerberos server.
+
+@chapter [Acknowledgements]
+
+We'd like to thank Henry Mensch and Jon Rochlis for helping us debug
+this document.
diff --git a/krb5-1-6/doc/old-V4-docs/operation.PS b/krb5-1-6/doc/old-V4-docs/operation.PS
new file mode 100644
index 000000000..3afb8cf06
--- /dev/null
+++ b/krb5-1-6/doc/old-V4-docs/operation.PS
@@ -0,0 +1,2669 @@
+%!PS-Adobe-2.0
+%%Title: operation.mss
+%%DocumentFonts: (atend)
+%%Creator: John T Kohl,,E40-351M,31510,6176432831 and Scribe 7(1700)
+%%CreationDate: 4 January 1990 11:55
+%%Pages: (atend)
+%%EndComments
+% PostScript Prelude for Scribe.
+/BS {/SV save def 0.0 792.0 translate .01 -.01 scale} bind def
+/ES {showpage SV restore} bind def
+/SC {setrgbcolor} bind def
+/FMTX matrix def
+/RDF {WFT SLT 0.0 eq 
+  {SSZ 0.0 0.0 SSZ neg 0.0 0.0 FMTX astore}
+  {SSZ 0.0 SLT neg sin SLT cos div SSZ mul SSZ neg 0.0 0.0 FMTX astore}
+  ifelse makefont setfont} bind def
+/SLT 0.0 def
+/SI { /SLT exch cvr def RDF} bind def
+/WFT /Courier findfont def
+/SF { /WFT exch findfont def RDF} bind def
+/SSZ 1000.0 def
+/SS { /SSZ exch 100.0 mul def RDF} bind def
+/AF { /WFT exch findfont def /SSZ exch 100.0 mul def RDF} bind def
+/MT /moveto load def
+/XM {currentpoint exch pop moveto} bind def
+/UL {gsave newpath moveto dup 2.0 div 0.0 exch rmoveto
+   setlinewidth 0.0 rlineto stroke grestore} bind def
+/LH {gsave newpath moveto setlinewidth
+   0.0 rlineto
+   gsave stroke grestore} bind def
+/LV {gsave newpath moveto setlinewidth
+   0.0 exch rlineto
+   gsave stroke grestore} bind def
+/BX {gsave newpath moveto setlinewidth
+   exch
+   dup 0.0 rlineto
+   exch 0.0 exch neg rlineto
+   neg 0.0 rlineto
+   closepath
+   gsave stroke grestore} bind def
+/BX1 {grestore} bind def
+/BX2 {setlinewidth 1 setgray stroke grestore} bind def
+/PB {/PV save def newpath translate
+    100.0 -100.0 scale pop /showpage {} def} bind def
+/PE {PV restore} bind def
+/GB {/PV save def newpath translate rotate
+    div dup scale 100.0 -100.0 scale /showpage {} def} bind def
+/GE {PV restore} bind def
+/FB {dict dup /FontMapDict exch def begin} bind def
+/FM {cvn exch cvn exch def} bind def
+/FE {end /original-findfont /findfont load def  /findfont
+   {dup FontMapDict exch known{FontMapDict exch get} if
+   original-findfont} def} bind def
+/BC {gsave moveto dup 0 exch rlineto exch 0 rlineto neg 0 exch rlineto closepath clip} bind def
+/EC /grestore load def
+/SH /show load def
+/MX {exch show 0.0 rmoveto} bind def
+/W {0 32 4 -1 roll widthshow} bind def
+/WX {0 32 5 -1 roll widthshow 0.0 rmoveto} bind def
+/RC {100.0 -100.0 scale
+612.0 0.0 translate
+-90.0 rotate
+.01 -.01 scale} bind def
+/URC {100.0 -100.0 scale
+90.0 rotate
+-612.0 0.0 translate
+.01 -.01 scale} bind def
+/RCC {100.0 -100.0 scale
+0.0 -792.0 translate 90.0 rotate
+.01 -.01 scale} bind def
+/URCC {100.0 -100.0 scale
+-90.0 rotate 0.0 792.0 translate
+.01 -.01 scale} bind def
+%%EndProlog
+%%Page: 0 1
+BS
+0 SI
+20 /Times-Bold AF
+19324 13788 MT
+(Kerberos Operation Notes)SH
+27156 15798 MT
+(DRAFT)SH
+16 /Times-Roman AF
+27021 23502 MT
+(Bill Bryant)SH
+27289 25150 MT
+(John Kohl)SH
+23957 26798 MT
+(Project Athena, MIT)SH
+/Times-Bold SF
+19489 32396 MT
+(Initial Release, January 24, 1989)SH
+/Times-Italic SF
+17558 34044 MT
+(\050plus later patches through patchlevel 7\051)SH
+11 /Times-Roman AF
+7200 43798 MT
+(These notes assume that you have used the)SH
+/Times-Italic SF
+26322 XM
+(Kerberos Installation Notes)SH
+/Times-Roman SF
+38821 XM
+(to build and install your Kerberos)SH
+7200 44994 MT
+(system. As)
+275 W( in that document, we refer to the directory that contains the built Kerberos binaries as)SH
+7200 46190 MT
+([OBJ_DIR].)SH
+7200 48488 MT
+(This document assumes that you are a Unix system manager.)SH
+ES
+%%Page: 1 2
+BS
+0 SI
+16 /Times-Bold AF
+7200 8272 MT
+(1. How)
+400 W( Kerberos Works: A Schematic Description)SH
+11 /Times-Roman AF
+7200 10467 MT
+(This section provides a simplified description of a general user's interaction with the Kerberos system.)SH
+7200 11663 MT
+(This interaction happens transparently--users don't need to know and probably don't care about what's)SH
+7200 12859 MT
+(going on--but Kerberos administrators might find a schematic description of the process useful.  The)SH
+7200 14055 MT
+(description glosses over a lot of details; for more information, see)SH
+/Times-Italic SF
+36404 XM
+(Kerberos: An Authentication Service)SH
+7200 15251 MT
+(for Open Network Systems)SH
+/Times-Roman SF
+(, a paper presented at Winter USENIX 1988, in Dallas, Texas.)SH
+14 /Times-Bold AF
+7200 19069 MT
+(1.1 Network)
+350 W( Services and Their Client Programs)SH
+11 /Times-Roman AF
+7200 21264 MT
+(In an environment that provides network services, you use)SH
+/Times-Italic SF
+33164 XM
+(client)SH
+/Times-Roman SF
+35883 XM
+(programs to request service from)SH
+/Times-Italic SF
+50696 XM
+(server)SH
+/Times-Roman SF
+7200 22460 MT
+(programs that are somewhere on the network.  Suppose you have logged in to a workstation and you want)SH
+7200 23656 MT
+(to)SH
+/Times-Italic SF
+8331 XM
+(rlogin)SH
+/Times-Roman SF
+11296 XM
+(to another machine.  You use the local)SH
+/Times-Italic SF
+28493 XM
+(rlogin)SH
+/Times-Roman SF
+31458 XM
+(client program to contact the remote machine's)SH
+/Times-Italic SF
+7200 24852 MT
+(rlogin)SH
+/Times-Roman SF
+10165 XM
+(service daemon.)SH
+14 /Times-Bold AF
+7200 28670 MT
+(1.2 Kerberos)
+350 W( Tickets)SH
+11 /Times-Roman AF
+7200 30865 MT
+(Under Kerberos, the)SH
+/Times-Italic SF
+16422 XM
+(rlogin)SH
+/Times-Roman SF
+19387 XM
+(service program allows a client to login to a remote machine if it can provide)SH
+7200 32061 MT
+(a Kerberos)SH
+/Times-Bold SF
+12268 XM
+(ticket)SH
+/Times-Roman SF
+15169 XM
+(for the request.  This ticket proves the identity of the person who has used the client)SH
+7200 33257 MT
+(program to access the server program.)SH
+14 /Times-Bold AF
+7200 37075 MT
+(1.3 The)
+350 W( Kerberos Master Database)SH
+11 /Times-Roman AF
+7200 39270 MT
+(Kerberos will give you tickets only if you have an entry in the Kerberos server's)SH
+/Times-Bold SF
+42845 XM
+(master database)SH
+/Times-Roman SF
+(. Your)275 W
+7200 40466 MT
+(database entry includes your Kerberos username \050often referred to as your Kerberos)SH
+/Times-Bold SF
+44394 XM
+(principal)SH
+/Times-Roman SF
+48949 XM
+(name\051, and)SH
+7200 41662 MT
+(your Kerberos password.  Every Kerberos user must have an entry in this database.)SH
+14 /Times-Bold AF
+7200 45480 MT
+(1.4 The)
+350 W( Ticket-Granting Ticket)SH
+11 /Times-Roman AF
+7200 47675 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(kinit)SH
+/Times-Roman SF
+11416 XM
+(command prompts for your Kerberos username and password, and if you enter them)SH
+7200 48871 MT
+(successfully, you will obtain a Kerberos)SH
+/Times-Italic SF
+25131 XM
+(ticket-granting ticket)SH
+/Times-Roman SF
+(. As)
+275 W( illustrated below, client programs use)SH
+7200 50067 MT
+(this ticket to get other Kerberos tickets as needed.)SH
+14 /Times-Bold AF
+7200 53885 MT
+(1.5 Network)
+350 W( Services and the Master Database)SH
+11 /Times-Roman AF
+7200 56080 MT
+(The master database also contains entries for all network services that require Kerberos authentication.)SH
+7200 57276 MT
+(Suppose for instance that your site has a machine)SH
+/Times-Italic SF
+29163 XM
+(laughter)SH
+/Times-Roman SF
+33166 XM
+(that requires Kerberos authentication from)SH
+7200 58472 MT
+(anyone who wants to)SH
+/Times-Italic SF
+16792 XM
+(rlogin)SH
+/Times-Roman SF
+19757 XM
+(to it.  This service must be registered in the master database.  Its entry)SH
+7200 59668 MT
+(includes the service's principal name, and its)SH
+/Times-Bold SF
+27238 XM
+(instance)SH
+/Times-Roman SF
+(.)SH
+7200 61966 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(instance)SH
+/Times-Roman SF
+13126 XM
+(is the name of the service's machine; in this case, the service's instance is the name)SH
+/Times-Italic SF
+7200 63162 MT
+(laughter)SH
+/Times-Roman SF
+(. The)
+275 W( instance provides a means for Kerberos to distinguish between machines that provide the)SH
+7200 64358 MT
+(same service.  Your site is likely to have more than one machine that provides)SH
+/Times-Italic SF
+41840 XM
+(rlogin)SH
+/Times-Roman SF
+44805 XM
+(service.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(1)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 2 3
+BS
+0 SI
+14 /Times-Bold AF
+7200 8138 MT
+(1.6 The)
+350 W( User-Kerberos Interaction)SH
+11 /Times-Roman AF
+7200 10333 MT
+(Suppose that you \050in the guise of a general user\051 walk up to a workstation intending to login to it, and)SH
+7200 11529 MT
+(then)SH
+/Times-Italic SF
+9369 XM
+(rlogin)SH
+/Times-Roman SF
+12334 XM
+(to the machine)SH
+/Times-Italic SF
+19085 XM
+(laughter)SH
+/Times-Roman SF
+(. Here's)
+275 W( what happens.)SH
+9400 13480 MT
+(1.)SH
+10500 XM
+(You login to the workstation and use the)SH
+/Times-Italic SF
+28648 XM
+(kinit)SH
+/Times-Roman SF
+30879 XM
+(command to to get a ticket-granting ticket.)SH
+10500 14676 MT
+(This command prompts you for your username \050your Kerberos Principal Name\051, and your)SH
+10500 15872 MT
+(Kerberos password [on some systems which use the new version of)SH
+/Times-Italic SF
+40465 XM
+(/bin/login)SH
+/Times-Roman SF
+(, this may be)SH
+10500 17068 MT
+(done as part of the login process, not requiring the user to run a separate program].)SH
+12762 19019 MT
+(a.)SH
+13800 XM
+(The)SH
+/Times-Italic SF
+15785 XM
+(kinit)SH
+/Times-Roman SF
+18016 XM
+(command sends your request to the Kerberos master server machine.  The)SH
+13800 20215 MT
+(server software looks for your principal name's entry in the Kerberos)SH
+/Times-Bold SF
+44555 XM
+(master)SH
+13800 21411 MT
+(database)SH
+/Times-Roman SF
+(.)SH
+12700 23305 MT
+(b.)SH
+13800 XM
+(If this entry exists, the Kerberos server creates and returns a)SH
+/Times-Italic SF
+40430 XM
+(ticket-granting ticket)SH
+/Times-Roman SF
+(,)SH
+13800 24501 MT
+(encrypted in your password.  If)SH
+/Times-Italic SF
+27819 XM
+(kinit)SH
+/Times-Roman SF
+30050 XM
+(can decrypt the Kerberos reply using the)SH
+13800 25697 MT
+(password you provide, it stores this ticket in a)SH
+/Times-Bold SF
+34270 XM
+(ticket file)SH
+/Times-Roman SF
+38912 XM
+(on your local machine for)SH
+13800 26893 MT
+(later use.  The ticket file to be used can be specified in the)SH
+/Times-Bold SF
+39609 XM
+(KRBTKFILE)SH
+/Times-Roman SF
+13800 28089 MT
+(environment variable.  If this variable is not set, the name of the file will be)SH
+/Times-Italic SF
+13800 29285 MT
+(/tmp/tkt)SH
+/Times-BoldItalic SF
+(uid)SH
+/Times-Roman SF
+(, where)SH
+/Times-BoldItalic SF
+22141 XM
+(uid)SH
+/Times-Roman SF
+23884 XM
+(is the UNIX user-id, represented in decimal.)SH
+9400 31236 MT
+(2.)SH
+10500 XM
+(Now you use the)SH
+/Times-Italic SF
+18198 XM
+(rlogin)SH
+/Times-Roman SF
+21163 XM
+(client to try to access the machine)SH
+/Times-Italic SF
+36344 XM
+(laughter)SH
+/Times-Roman SF
+(.)SH
+/Courier SF
+11820 32813 MT
+(host%)SH
+/Times-Bold SF
+15780 XM
+(rlogin laughter)275 W
+/Times-Roman SF
+12762 34764 MT
+(a.)SH
+13800 XM
+(The)SH
+/Times-Italic SF
+15785 XM
+(rlogin)SH
+/Times-Roman SF
+18750 XM
+(client checks your ticket file to see if you have a ticket for)SH
+/Times-Italic SF
+44559 XM
+(laughter)SH
+/Times-Roman SF
+('s)SH
+/Times-Italic SF
+13800 35960 MT
+(rcmd)SH
+/Times-Roman SF
+16335 XM
+(service \050the rlogin program uses the)SH
+/Times-Italic SF
+32401 XM
+(rcmd)SH
+/Times-Roman SF
+34936 XM
+(service name, mostly for historical)SH
+13800 37156 MT
+(reasons\051. You)
+275 W( don't, so)SH
+/Times-Italic SF
+24583 XM
+(rlogin)SH
+/Times-Roman SF
+27548 XM
+(uses the ticket file's)SH
+/Times-Italic SF
+36590 XM
+(ticket-granting ticket)SH
+/Times-Roman SF
+46060 XM
+(to make a)SH
+13800 38352 MT
+(request to the master server's ticket-granting service.)SH
+12700 40246 MT
+(b.)SH
+13800 XM
+(This ticket-granting service receives the)SH
+/Times-Italic SF
+31667 XM
+(rcmd-laughter)SH
+/Times-Roman SF
+38296 XM
+(request and looks in the)SH
+13800 41442 MT
+(master database for an)SH
+/Times-Italic SF
+23938 XM
+(rcmd-laughter)SH
+/Times-Roman SF
+30567 XM
+(entry. If)
+275 W( that entry exists, the ticket-granting)SH
+13800 42638 MT
+(service issues you a ticket for that service.  That ticket is also cached in your ticket)SH
+13800 43834 MT
+(file.)SH
+12762 45728 MT
+(c.)SH
+13800 XM
+(The)SH
+/Times-Italic SF
+15785 XM
+(rlogin)SH
+/Times-Roman SF
+18750 XM
+(client now uses that ticket to request service from the)SH
+/Times-Italic SF
+42454 XM
+(laughter rlogin)SH
+/Times-Roman SF
+13800 46924 MT
+(service program.  The service program lets you)SH
+/Times-Italic SF
+34843 XM
+(rlogin)SH
+/Times-Roman SF
+37808 XM
+(if the ticket is valid.)SH
+16 /Times-Bold AF
+7200 51596 MT
+(2. Setting)
+400 W( Up and Testing the Kerberos Server)SH
+11 /Times-Roman AF
+7200 53791 MT
+(The procedure for setting up and testing a Kerberos server is as follows:)SH
+9400 55742 MT
+(1.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(kdb_init)SH
+/Times-Roman SF
+17985 XM
+(command to create and initialize the master database.)SH
+9400 57636 MT
+(2.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(kdb_edit)SH
+/Times-Roman SF
+18167 XM
+(utility to add your username to the master database.)SH
+9400 59530 MT
+(3.)SH
+10500 XM
+(Start the Kerberos server.)SH
+9400 61424 MT
+(4.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(kinit)SH
+/Times-Roman SF
+16335 XM
+(command to obtain a Kerberos ticket-granting ticket.)SH
+9400 63318 MT
+(5.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(klist)SH
+/Times-Roman SF
+16213 XM
+(command to verify that the)SH
+/Times-Italic SF
+28402 XM
+(kinit)SH
+/Times-Roman SF
+30633 XM
+(command authenticated you successfully.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(2)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 3 4
+BS
+0 SI
+14 /Times-Bold AF
+7200 8138 MT
+(2.1 Creating)
+350 W( and Initializing the Master Database)SH
+11 /Times-Roman AF
+7200 10333 MT
+(Login to the Kerberos master server machine, and use the)SH
+/Times-Bold SF
+32825 XM
+(su)SH
+/Times-Roman SF
+34140 XM
+(command to become root.  If you installed)SH
+7200 11529 MT
+(the Kerberos administration tools with the)SH
+/Times-Italic SF
+26020 XM
+(make install)SH
+/Times-Roman SF
+31642 XM
+(command and the default pathnames, they should)SH
+7200 12725 MT
+(be in the)SH
+/Times-Italic SF
+11263 XM
+(/usr/etc)SH
+/Times-Roman SF
+14838 XM
+(directory. If)
+275 W( you installed the tools in a different directory, hopefully you know what it)SH
+7200 13921 MT
+(is. From)
+275 W( now on, we will refer to this directory as [ADMIN_DIR].)SH
+7200 16219 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(kdb_init)SH
+/Times-Roman SF
+13066 XM
+(command creates and initializes the master database.  It asks you to enter the system's realm)SH
+7200 17415 MT
+(name and the database's master password.  Do not forget this password.  If you do, the database becomes)SH
+7200 18611 MT
+(useless. \050Your)
+275 W( realm name should be substituted for [REALMNAME] below.\051)SH
+7200 20909 MT
+(Use)SH
+/Times-Italic SF
+9185 XM
+(kdb_init)SH
+/Times-Roman SF
+13066 XM
+(as follows:)SH
+/Courier SF
+8520 22486 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+([ADMIN_DIR]/kdb_init)SH
+/Courier SF
+8520 23600 MT
+(Realm name \050default XXX\051:)SH
+/Times-Bold SF
+25680 XM
+([REALMNAME])SH
+39600 XM
+(<--)SH
+/Times-BoldItalic SF
+41619 XM
+(Enter your system's realm name.)SH
+/Courier SF
+8520 24714 MT
+(You will be prompted for the database Master Password.)SH
+8520 25828 MT
+(It is important that you NOT FORGET this password.)SH
+8520 28056 MT
+(Enter Kerberos master key:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter the master password.)SH
+14 /Times-Bold AF
+7200 32988 MT
+(2.2 Storing)
+350 W( the Master Password)SH
+11 /Times-Roman AF
+7200 35183 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(kstash)SH
+/Times-Roman SF
+12210 XM
+(command ``stashes'' the master password in the file)SH
+/Times-Italic SF
+35424 XM
+(/.k)SH
+/Times-Roman SF
+36768 XM
+(so that the Kerberos server can be)SH
+7200 36379 MT
+(started automatically during an unattended reboot of the master server.  Other administrative programs)SH
+7200 37575 MT
+(use this hidden password so that they can access the master database without someone having to manually)SH
+7200 38771 MT
+(provide the master password.  This command is an optional one; if you'd rather enter the master password)SH
+7200 39967 MT
+(each time you start the Kerberos server, don't use)SH
+/Times-Italic SF
+29312 XM
+(kstash)SH
+/Times-Roman SF
+(.)SH
+7200 42265 MT
+(One the one hand, if you use)SH
+/Times-Italic SF
+20090 XM
+(kstash)SH
+/Times-Roman SF
+(, a copy of the master key will reside on disk which may not be)SH
+7200 43461 MT
+(acceptable; on the other hand, if you don't use)SH
+/Times-Italic SF
+27848 XM
+(kstash)SH
+/Times-Roman SF
+(, the server cannot be started unless someone is)SH
+7200 44657 MT
+(around to type the password in manually.)SH
+7200 46955 MT
+(The command prompts you twice for the master password:)SH
+/Courier SF
+8520 48532 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+([ADMIN_DIR]/kstash)SH
+/Courier SF
+8520 50760 MT
+(Enter Kerberos master key:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter the master password.)SH
+/Courier SF
+8520 51874 MT
+(Current Kerberos master key version is 1.)SH
+8520 54102 MT
+(Master key entered)
+SH( BEWARE!)1320 W
+/Times-Roman SF
+7200 56400 MT
+(A note about the Kerberos database master key:  if your master key is compromised and the database is)SH
+7200 57596 MT
+(obtained, the security of your entire authentication system is compromised.  The master key must be a)SH
+7200 58792 MT
+(carefully kept secret.  If you keep backups, you must guard all the master keys you use, in case someone)SH
+7200 59988 MT
+(has stolen an old backup and wants to attack users' whose passwords haven't changed since the backup)SH
+7200 61184 MT
+(was stolen.  This is why we provide the option not to store it on disk.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(3)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 4 5
+BS
+0 SI
+14 /Times-Bold AF
+7200 8167 MT
+(2.3 Using)350 W
+/Times-BoldItalic SF
+13423 XM
+(kdb_edit)SH
+/Times-Bold SF
+18673 XM
+(to Add Users to the Master Database)SH
+11 /Times-Roman AF
+7200 10362 MT
+(The)SH
+/Times-Italic SF
+9185 XM
+(kdb_edit)SH
+/Times-Roman SF
+13248 XM
+(program is used to add new users and services to the master database, and to modify)SH
+7200 11558 MT
+(existing database information.  The program prompts you to enter a principal's)SH
+/Times-Bold SF
+42177 XM
+(name)SH
+/Times-Roman SF
+45018 XM
+(and)SH
+/Times-Bold SF
+46881 XM
+(instance)SH
+/Times-Roman SF
+(.)SH
+7200 13856 MT
+(A principal name is typically a username or a service program's name.  An instance further qualifies the)SH
+7200 15052 MT
+(principal. If)
+275 W( the principal is a service, the instance is used to specify the name of the machine on which)SH
+7200 16248 MT
+(that service runs.  If the principal is a username that has general user privileges, the instance is usually set)SH
+7200 17444 MT
+(to null.)SH
+7200 19742 MT
+(The following example shows how to use)SH
+/Times-Italic SF
+25805 XM
+(kdb_edit)SH
+/Times-Roman SF
+29868 XM
+(to add the user)SH
+/Times-Italic SF
+36588 XM
+(wave)SH
+/Times-Roman SF
+39123 XM
+(to the Kerberos database.)SH
+/Courier SF
+8520 21319 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+([ADMIN_DIR]/kdb_edit)SH
+/Courier SF
+8520 23547 MT
+(Opening database...)SH
+8520 25775 MT
+(Enter Kerberos master key:)SH
+8520 26889 MT
+(Verifying, please re-enter)SH
+8520 28003 MT
+(Enter Kerberos master key:)SH
+8520 29117 MT
+(Current Kerberos master key version is 1)SH
+8520 31345 MT
+(Master key entered.  BEWARE!)SH
+8520 32459 MT
+(Previous or default values are in [brackets] ,)SH
+8520 33573 MT
+(enter return to leave the same, or new value.)SH
+8520 35801 MT
+(Principal name:)SH
+/Times-Bold SF
+19080 XM
+(wave)SH
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter the username.)SH
+/Courier SF
+8520 36915 MT
+(Instance:)SH
+/Times-BoldItalic SF
+28800 XM
+(<-- Enter a null instance.)SH
+/Courier SF
+8520 39143 MT
+(<Not found>, Create [y] ?)SH
+/Times-Bold SF
+25680 XM
+(y)SH
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(The user-instance does not exist.)SH
+30450 40257 MT
+(Enter y to create the user-instance.)SH
+/Courier SF
+8520 41371 MT
+(Principal: wave  Instance:  m_key_v: 1)SH
+8520 42485 MT
+(New Password:)SH
+/Times-BoldItalic SF
+28800 XM
+(<-- Enter the user-instance's password.)SH
+/Courier SF
+8520 43599 MT
+(Verifying, please re-enter)SH
+8520 44713 MT
+(New Password:)SH
+8520 45827 MT
+(Principal's new key version = 1)SH
+8520 46941 MT
+(Expiration date \050enter dd-mm-yy\051 [ 12/31/99 ] ?)SH
+/Times-Bold SF
+39600 XM
+(<--)SH
+/Times-BoldItalic SF
+41619 XM
+(Enter newlines)SH
+/Courier SF
+8520 48055 MT
+(Max ticket lifetime \050*5 minutes\051 [ 255 ] ?)SH
+/Times-Bold SF
+39600 XM
+(<--)SH
+/Times-BoldItalic SF
+41619 XM
+(to get the)SH
+/Courier SF
+8520 49169 MT
+(Attributes [ 0 ] ?)SH
+/Times-Bold SF
+30120 XM
+(<--)SH
+/Times-BoldItalic SF
+32139 XM
+(default values.)SH
+/Courier SF
+8520 50283 MT
+(Edit O.K.)SH
+8520 52511 MT
+(Principal name:)SH
+/Times-BoldItalic SF
+28800 XM
+(<-- Enter a newline to exit the program.)SH
+/Times-Roman SF
+7200 54809 MT
+(Use the)SH
+/Times-Italic SF
+10804 XM
+(kdb_edit)SH
+/Times-Roman SF
+14867 XM
+(utility to add your username to the master database.)SH
+14 /Times-Bold AF
+7200 58627 MT
+(2.4 Starting)
+350 W( the Kerberos Server)SH
+11 /Times-Roman AF
+7200 60822 MT
+(Change directories to the directory in which you have installed the server program)SH
+/Times-Italic SF
+43701 XM
+(kerberos)SH
+/Times-Roman SF
+47824 XM
+(\050the default)SH
+7200 62018 MT
+(directory is)SH
+/Times-Italic SF
+12454 XM
+(/usr/etc)SH
+/Times-Roman SF
+(\051, and start the program as a background process:)SH
+/Courier SF
+8520 63595 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+(./kerberos &)SH
+/Times-Roman SF
+7200 65190 MT
+(If you have used the)SH
+/Times-Italic SF
+16393 XM
+(kstash)SH
+/Times-Roman SF
+19418 XM
+(command to store the master database password, the server will start)SH
+7200 66386 MT
+(automatically. If)
+275 W( you did not use)SH
+/Times-Italic SF
+22048 XM
+(kstash)SH
+/Times-Roman SF
+(, use the following command:)SH
+/Courier SF
+8520 67963 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+(./kerberos -m)SH
+10 /Times-Roman AF
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(4)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 5 6
+BS
+0 SI
+11 /Times-Roman AF
+7200 7955 MT
+(The server will prompt you to enter the master password before actually starting itself.)SH
+14 /Times-Bold AF
+7200 11773 MT
+(2.5 Testing)
+350 W( the Kerberos Server)SH
+11 /Times-Roman AF
+7200 13968 MT
+(Exit the root account and use the)SH
+/Times-Italic SF
+21893 XM
+(kinit)SH
+/Times-Roman SF
+24124 XM
+(command obtain a Kerberos ticket-granting ticket.  This command)SH
+7200 15164 MT
+(creates your ticket file and stores the ticket-granting ticket in it.)SH
+7200 17462 MT
+(If you used the default)SH
+/Times-Italic SF
+17371 XM
+(make install)SH
+/Times-Roman SF
+22993 XM
+(command and directories to install the Kerberos user utilities,)SH
+/Times-Italic SF
+50365 XM
+(kinit)SH
+/Times-Roman SF
+7200 18658 MT
+(will be in the)SH
+/Times-Italic SF
+13250 XM
+(/usr/athena)SH
+/Times-Roman SF
+18537 XM
+(directory. From now on, we'll refer to the Kerberos user commands directory as)SH
+7200 19854 MT
+([K_USER].)SH
+7200 22152 MT
+(Use)SH
+/Times-Italic SF
+9185 XM
+(kinit)SH
+/Times-Roman SF
+11416 XM
+(as follows:)SH
+/Courier SF
+8520 23729 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([K_USER]/kinit)SH
+/Courier SF
+8520 24843 MT
+(MIT Project Athena, \050ariadne\051)SH
+8520 25957 MT
+(Kerberos Initialization)SH
+8520 27071 MT
+(Kerberos name:)SH
+/Times-BoldItalic SF
+18420 XM
+(yourusername)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter your Kerberos username.)SH
+/Courier SF
+8520 28185 MT
+(Password:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter your Kerberos password.)SH
+/Times-Roman SF
+7200 30483 MT
+(Use the)SH
+/Times-Italic SF
+10804 XM
+(klist)SH
+/Times-Roman SF
+12913 XM
+(program to list the contents of your ticket file.)SH
+/Courier SF
+8520 32060 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([K_USER]/klist)SH
+/Times-Roman SF
+7200 33655 MT
+(The command should display something like the following:)SH
+/Courier SF
+8520 35181 MT
+(Ticket file:)
+SH( /tmp/tkt5555)1980 W
+8520 36295 MT
+(Principal: yourusername@REALMNAME)3300 W
+9840 38523 MT
+(Issued Expires)
+6600 W( Principal)5940 W
+8520 39637 MT
+(May 6)
+660 W( 10:15:23  May  6 18:15:23  krbtgt.REALMNAME@REALMNAME)SH
+/Times-Roman SF
+7200 41935 MT
+(If you have any problems, you can examine the log file)SH
+/Times-Italic SF
+31758 XM
+(/kerberos/kerberos.log)SH
+/Times-Roman SF
+42022 XM
+(on the Kerberos server)SH
+7200 43131 MT
+(machine to see if there was some sort of error.)SH
+16 /Times-Bold AF
+7200 47803 MT
+(3. Setting)
+400 W( up and testing the Administration server)SH
+11 /Times-Roman AF
+7200 49998 MT
+(The procedure for setting up and testing the Kerberos administration server is as follows:)SH
+9400 51949 MT
+(1.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(kdb_edit)SH
+/Times-Roman SF
+18167 XM
+(utility to add your username with an administration instance to the master)SH
+10500 53145 MT
+(database.)SH
+9400 55039 MT
+(2.)SH
+10500 XM
+(Edit the access control lists for the administration server)SH
+9400 56933 MT
+(3.)SH
+10500 XM
+(Start the Kerberos administration server.)SH
+9400 58827 MT
+(4.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(kpasswd)SH
+/Times-Roman SF
+18107 XM
+(command to change your password.)SH
+9400 60721 MT
+(5.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(kadmin)SH
+/Times-Roman SF
+17617 XM
+(command to add new entries to the database.)SH
+9400 62615 MT
+(6.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(kinit)SH
+/Times-Roman SF
+16335 XM
+(command to verify that the)SH
+/Times-Italic SF
+28524 XM
+(kadmin)SH
+/Times-Roman SF
+32037 XM
+(command correctly added new entries to)SH
+10500 63811 MT
+(the database.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(5)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 6 7
+BS
+0 SI
+14 /Times-Bold AF
+7200 8138 MT
+(3.1 Adding)
+350 W( an administration instance for the administrator)SH
+11 /Times-Roman AF
+7200 10333 MT
+(Login to the Kerberos master server machine, and use the)SH
+/Times-Bold SF
+32825 XM
+(su)SH
+/Times-Roman SF
+34140 XM
+(command to become root.  Use the)SH
+/Times-Italic SF
+49780 XM
+(kdb_edit)SH
+/Times-Roman SF
+7200 11529 MT
+(program to create an entry for each administrator with the instance ``)SH
+/Times-BoldItalic SF
+(admin)SH
+/Times-Roman SF
+(''.)SH
+/Courier SF
+8520 13106 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+([ADMIN_DIR]/kdb_edit)SH
+/Courier SF
+8520 15334 MT
+(Opening database...)SH
+8520 17562 MT
+(Enter Kerberos master key:)SH
+8520 18676 MT
+(Verifying, please re-enter)SH
+8520 19790 MT
+(Enter Kerberos master key:)SH
+8520 20904 MT
+(Current Kerberos master key version is 1)SH
+8520 23132 MT
+(Master key entered.  BEWARE!)SH
+8520 24246 MT
+(Previous or default values are in [brackets] ,)SH
+8520 25360 MT
+(enter return to leave the same, or new value.)SH
+8520 27588 MT
+(Principal name:)SH
+/Times-Bold SF
+19080 XM
+(wave)SH
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter the username.)SH
+/Courier SF
+8520 28702 MT
+(Instance:)SH
+/Times-Bold SF
+(admin)SH
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter ``admin''.)SH
+/Courier SF
+8520 30930 MT
+(<Not found>, Create [y] ?)SH
+/Times-Bold SF
+25680 XM
+(y)SH
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(The user-instance does not exist.)SH
+30450 32044 MT
+(Enter y to create the user-instance.)SH
+/Courier SF
+8520 33158 MT
+(Principal: wave  Instance: admin m_key_v: 1)SH
+8520 34272 MT
+(New Password:)SH
+/Times-BoldItalic SF
+28800 XM
+(<-- Enter the user-instance's password.)SH
+/Courier SF
+8520 35386 MT
+(Verifying, please re-enter)SH
+8520 36500 MT
+(New Password:)SH
+8520 37614 MT
+(Principal's new key version = 1)SH
+8520 38728 MT
+(Expiration date \050enter dd-mm-yy\051 [ 12/31/99 ] ?)SH
+/Times-Bold SF
+39600 XM
+(<--)SH
+/Times-BoldItalic SF
+41619 XM
+(Enter newlines)SH
+/Courier SF
+8520 39842 MT
+(Max ticket lifetime \050*5 minutes\051 [ 255 ] ?)SH
+/Times-Bold SF
+39600 XM
+(<--)SH
+/Times-BoldItalic SF
+41619 XM
+(to get the)SH
+/Courier SF
+8520 40956 MT
+(Attributes [ 0 ] ?)SH
+/Times-Bold SF
+30120 XM
+(<--)SH
+/Times-BoldItalic SF
+32139 XM
+(default values.)SH
+/Courier SF
+8520 42070 MT
+(Edit O.K.)SH
+8520 44298 MT
+(Principal name:)SH
+/Times-BoldItalic SF
+28800 XM
+(<-- Enter a newline to exit the program.)SH
+14 /Times-Bold AF
+7200 48116 MT
+(3.2 The)
+350 W( Access Control Lists)SH
+11 /Times-Roman AF
+7200 50311 MT
+(The Kerberos administration server uses three access control lists to determine who is authorized to make)SH
+7200 51507 MT
+(certain requests.  The access control lists are stored on the master Kerberos server in the same directory as)SH
+7200 52703 MT
+(the principal database,)SH
+/Times-Italic SF
+17340 XM
+(/kerberos)SH
+/Times-Roman SF
+(. The)
+275 W( access control lists are simple ASCII text files, with each line)SH
+7200 53899 MT
+(specifying the name of one principal who is allowed the particular function.  To allow several people to)SH
+7200 55095 MT
+(perform the same function, put their principal names on separate lines in the same file.)SH
+7200 57393 MT
+(The first list,)SH
+/Times-Italic SF
+13128 XM
+(/kerberos/admin_acl.mod)SH
+/Times-Roman SF
+(, is a list of principals which are authorized to change entries in the)SH
+7200 58589 MT
+(database. To)
+275 W( allow the administrator `)SH
+/Times-Bold SF
+(wave)SH
+/Times-Roman SF
+(' to modify entries in the database for the realm `)SH
+/Times-Bold SF
+(TIM.EDU)SH
+/Times-Roman SF
+(',)SH
+7200 59785 MT
+(you would put the following line into the file)SH
+/Times-Italic SF
+27275 XM
+(/kerberos/admin_acl.mod)SH
+/Times-Roman SF
+(:)SH
+/Courier SF
+8520 61311 MT
+(wave.admin@TIM.EDU)SH
+/Times-Roman SF
+7200 63609 MT
+(The second list,)SH
+/Times-Italic SF
+14410 XM
+(/kerberos/admin_acl.get)SH
+/Times-Roman SF
+(, is a list of principals which are authorized to retrieve entries)SH
+7200 64805 MT
+(from the database.)SH
+7200 67103 MT
+(The third list,)SH
+/Times-Italic SF
+13434 XM
+(/kerberos/admin_acl.add)SH
+/Times-Roman SF
+(, is a list of principals which are authorized to add new entries to)SH
+7200 68299 MT
+(the database.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(6)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 7 8
+BS
+0 SI
+14 /Times-Bold AF
+7200 8138 MT
+(3.3 Starting)
+350 W( the administration server)SH
+11 /Times-Roman AF
+7200 10333 MT
+(Change directories to the directory in which you have installed the administration server program)SH
+/Times-Italic SF
+7200 11529 MT
+(kadmind)SH
+/Times-Roman SF
+11263 XM
+(\050the default directory is)SH
+/Times-Italic SF
+21831 XM
+(/usr/etc)SH
+/Times-Roman SF
+(\051, and start the program as a background process:)SH
+/Courier SF
+8520 13106 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+(./kadmind -n&)SH
+/Times-Roman SF
+7200 14701 MT
+(If you have used the)SH
+/Times-Italic SF
+16393 XM
+(kstash)SH
+/Times-Roman SF
+19418 XM
+(command to store the master database password, the server will start)SH
+7200 15897 MT
+(automatically. If)
+275 W( you did not use)SH
+/Times-Italic SF
+22048 XM
+(kstash)SH
+/Times-Roman SF
+(, use the following command:)SH
+/Courier SF
+8520 17474 MT
+(host#)SH
+/Times-Bold SF
+12480 XM
+(./kadmind)SH
+/Times-Roman SF
+7200 19069 MT
+(The server will prompt you to enter the master password before actually starting itself; after it starts, you)SH
+7200 20265 MT
+(should suspend it and put it in the background \050usually this is done by typing control-Z and then)SH
+/Times-Bold SF
+49792 XM
+(bg)SH
+/Times-Roman SF
+(\051.)SH
+14 /Times-Bold AF
+7200 24112 MT
+(3.4 Testing)350 W
+/Times-BoldItalic SF
+14434 XM
+(kpasswd)SH
+11 /Times-Roman AF
+7200 26307 MT
+(To test the administration server, you should try changing your password with the)SH
+/Times-Italic SF
+43494 XM
+(kpasswd)SH
+/Times-Roman SF
+47497 XM
+(command, and)SH
+7200 27503 MT
+(you should try adding new users with the)SH
+/Times-Italic SF
+25592 XM
+(kadmin)SH
+/Times-Roman SF
+29105 XM
+(command \050both commands are installed into)SH
+/Times-Italic SF
+48963 XM
+(/usr/athena)SH
+/Times-Roman SF
+7200 28699 MT
+(by default\051.)SH
+7200 30997 MT
+(Before testing, you should exit the root account.)SH
+7200 33295 MT
+(To change your password, run the)SH
+/Times-Italic SF
+22441 XM
+(kpasswd)SH
+/Times-Roman SF
+26444 XM
+(command:)SH
+/Courier SF
+8520 34872 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([K_USER]/kpasswd)SH
+/Courier SF
+8520 35986 MT
+(Old password for wave@TIM.EDU:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+(Enter your password)SH
+/Courier SF
+8520 37100 MT
+(New Password for wave@TIM.EDU:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+(Enter a new password)SH
+/Courier SF
+8520 38214 MT
+(Verifying, please re-enter New Password for wave@TIM.EDU:)SH
+/Times-Bold SF
+28800 39328 MT
+(<--)SH
+/Times-BoldItalic SF
+(Enter new password again)SH
+/Courier SF
+8520 40442 MT
+(Password changed.)SH
+/Times-Roman SF
+7200 42037 MT
+(Once you have changed your password, use the)SH
+/Times-Italic SF
+28365 XM
+(kinit)SH
+/Times-Roman SF
+30596 XM
+(program as shown above to verify that the password)SH
+7200 43233 MT
+(was properly changed.)SH
+14 /Times-Bold AF
+7200 47080 MT
+(3.5 Testing)350 W
+/Times-BoldItalic SF
+14434 XM
+(kadmin)SH
+11 /Times-Roman AF
+7200 49275 MT
+(You should also test the function of the)SH
+/Times-Italic SF
+24798 XM
+(kadmin)SH
+/Times-Roman SF
+28311 XM
+(program, by adding a new user \050here named)SH
+7200 50471 MT
+(``)SH
+/Courier SF
+(username)SH
+/Times-Roman SF
+(''\051:)SH
+/Courier SF
+8520 52048 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([K_USER]/kadmin)SH
+/Courier SF
+8520 53162 MT
+(Welcome to the Kerberos Administration Program, version 2)SH
+8520 54276 MT
+(Type "help" if you need it.)SH
+8520 55390 MT
+(admin:)SH
+/Times-Bold SF
+13800 XM
+(ank username)SH
+/Times-BoldItalic SF
+28800 XM
+(`ank' stands for Add New Key)SH
+/Courier SF
+8520 56504 MT
+(Admin password:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+(enter the password)SH
+28800 57618 MT
+(you chose above for wave.admin)SH
+/Courier SF
+8520 58732 MT
+(Password for username:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+(Enter the user's initial password)SH
+/Courier SF
+8520 59846 MT
+(Verifying, please re-enter Password for username:)SH
+/Times-Bold SF
+40920 XM
+(<--)SH
+/Times-BoldItalic SF
+(enter it again)SH
+/Courier SF
+8520 60960 MT
+(username added to database.)SH
+8520 63188 MT
+(admin: quit)660 W
+8520 64302 MT
+(Cleaning up and exiting.)SH
+10 /Times-Roman AF
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(7)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 8 9
+BS
+0 SI
+14 /Times-Bold AF
+7200 8167 MT
+(3.6 Verifying)
+350 W( with)SH
+/Times-BoldItalic SF
+18671 XM
+(kinit)SH
+11 /Times-Roman AF
+7200 10362 MT
+(Once you've added a new user, you should test to make sure it was added properly by using)SH
+/Times-Italic SF
+47917 XM
+(kinit)SH
+/Times-Roman SF
+(, and)SH
+7200 11558 MT
+(trying to get tickets for that user:)SH
+/Courier SF
+8520 13135 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([K_USER]/kinit username)SH
+/Courier SF
+8520 14249 MT
+(MIT Project Athena \050ariadne\051)SH
+8520 15363 MT
+(Kerberos Initialization for "username@TIM.EDU")SH
+8520 16477 MT
+(Password:)SH
+/Times-Bold SF
+15120 XM
+(<--)SH
+/Times-BoldItalic SF
+(Enter the user's password you used above)SH
+/Courier SF
+8520 17591 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([K_USER]/klist)SH
+/Courier SF
+8520 18705 MT
+(Ticket file:)
+SH( /tmp/tkt_5509_spare1)1980 W
+8520 19819 MT
+(Principal: username@TIM.MIT.EDU)3300 W
+9840 22047 MT
+(Issued Expires)
+6600 W( Principal)5940 W
+8520 23161 MT
+(Nov 20 15:58:52  Nov 20 23:58:52  krbtgt.TIM.EDU@TIM.EDU)SH
+/Times-Roman SF
+7200 25459 MT
+(If you have any problems, you can examine the log files)SH
+/Times-Italic SF
+32186 XM
+(/kerberos/kerberos.log)SH
+/Times-Roman SF
+42450 XM
+(and)SH
+/Times-Italic SF
+7200 26655 MT
+(/kerberos/admin_server.syslog)SH
+/Times-Roman SF
+21008 XM
+(on the Kerberos server machine to see if there was some sort of error.)SH
+16 /Times-Bold AF
+7200 31327 MT
+(4. Setting)
+400 W( up and testing slave server\050s\051)SH
+11 /Times-Roman AF
+7200 33522 MT
+([Unfortunately, this chapter is not yet ready.  Sorry. -ed])SH
+16 /Times-Bold AF
+7200 38194 MT
+(5. A)
+400 W( Sample Application)SH
+11 /Times-Roman AF
+7200 40389 MT
+(This release of Kerberos comes with a sample application server and a corresponding client program.)SH
+7200 41585 MT
+(You will find this software in the [OBJ_DIR])SH
+/Times-Italic SF
+(/appl/sample)SH
+/Times-Roman SF
+33170 XM
+(directory. The)
+275 W( file)SH
+/Times-Italic SF
+41691 XM
+(sample_client)SH
+/Times-Roman SF
+48076 XM
+(contains the)SH
+7200 42781 MT
+(client program's executable code, the file)SH
+/Times-Italic SF
+25677 XM
+(sample_server)SH
+/Times-Roman SF
+32366 XM
+(contains the server's executable.)SH
+7200 45079 MT
+(The programs are rudimentary.  When they have been installed \050the installation procedure is described in)SH
+7200 46275 MT
+(detail later\051, they work as follows:)SH
+/Symbol SF
+9169 48351 MT
+(\267)SH
+/Times-Roman SF
+9950 XM
+(The user starts)SH
+/Times-Italic SF
+16639 XM
+(sample_client)SH
+/Times-Roman SF
+23024 XM
+(and provides as arguments to the command the name of the)SH
+9950 49547 MT
+(server machine and a checksum.  For instance:)SH
+/Courier SF
+11270 51147 MT
+(host%)SH
+/Times-Bold SF
+15230 XM
+(sample_client)SH
+/Times-BoldItalic SF
+22966 XM
+(servername 43)385 W
+/Symbol SF
+9169 53041 MT
+(\267)SH
+/Times-Italic SF
+9950 XM
+(Sample_client)SH
+/Times-Roman SF
+16457 XM
+(contacts the server machine and authenticates the user to)SH
+/Times-Italic SF
+41654 XM
+(sample_server)SH
+/Times-Roman SF
+(.)SH
+/Symbol SF
+9169 54935 MT
+(\267)SH
+/Times-Italic SF
+9950 XM
+(Sample_server)SH
+/Times-Roman SF
+16761 XM
+(authenticates itself to)SH
+/Times-Italic SF
+26384 XM
+(sample_client)SH
+/Times-Roman SF
+(, then returns a message to the client)SH
+9950 56131 MT
+(program. This)
+275 W( message contains diagnostic information that includes the user's username,)SH
+9950 57327 MT
+(the Kerberos realm, and the user's workstation address.)SH
+/Symbol SF
+9169 59221 MT
+(\267)SH
+/Times-Italic SF
+9950 XM
+(Sample_client)SH
+/Times-Roman SF
+16457 XM
+(displays the server's message on the user's terminal screen.)SH
+14 /Times-Bold AF
+7200 63039 MT
+(5.1 The)
+350 W( Installation Process)SH
+11 /Times-Roman AF
+7200 65234 MT
+(In general, you use the following procedure to install a Kerberos-authenticated server-client system.)SH
+9400 67185 MT
+(1.)SH
+10500 XM
+(Add the appropriate entry to the Kerberos database using)SH
+/Times-Italic SF
+35881 XM
+(kdb_edit)SH
+/Times-Roman SF
+39944 XM
+(or)SH
+/Times-Italic SF
+41135 XM
+(kadmin)SH
+/Times-Roman SF
+44648 XM
+(\050described)SH
+10500 68381 MT
+(below\051.)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(8)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 9 10
+BS
+0 SI
+11 /Times-Roman AF
+9400 7955 MT
+(2.)SH
+10500 XM
+(Create a)SH
+/Times-Italic SF
+14408 XM
+(/etc/srvtab)SH
+/Times-Roman SF
+19327 XM
+(file for the server machine.)SH
+9400 9849 MT
+(3.)SH
+10500 XM
+(Install the service program and the)SH
+/Times-Italic SF
+26016 XM
+(/etc/srvtab)SH
+/Times-Roman SF
+30935 XM
+(file on the server machine.)SH
+9400 11743 MT
+(4.)SH
+10500 XM
+(Install the client program on the client machine.)SH
+9400 13637 MT
+(5.)SH
+10500 XM
+(Update the)SH
+/Times-Italic SF
+15570 XM
+(/etc/services)SH
+/Times-Roman SF
+21281 XM
+(file on the client and server machines.)SH
+7200 15935 MT
+(We will use the sample application as an example, although the procedure used to install)SH
+/Times-Italic SF
+46484 XM
+(sample_server)SH
+/Times-Roman SF
+7200 17131 MT
+(differs slightly from the general case because the)SH
+/Times-Italic SF
+29006 XM
+(sample_server)SH
+/Times-Roman SF
+35695 XM
+(takes requests via the)SH
+/Times-Italic SF
+45347 XM
+(inetd)SH
+/Times-Roman SF
+47822 XM
+(program.)SH
+/Times-Italic SF
+7200 18327 MT
+(Inetd)SH
+/Times-Roman SF
+9735 XM
+(starts)SH
+/Times-Italic SF
+12332 XM
+(sample_server)SH
+/Times-Roman SF
+19021 XM
+(each time a client process contacts the server machine.)SH
+/Times-Italic SF
+43606 XM
+(Sample_server)SH
+/Times-Roman SF
+7200 19523 MT
+(processes the request, terminiates, then is restarted when)SH
+/Times-Italic SF
+32368 XM
+(inetd)SH
+/Times-Roman SF
+34843 XM
+(receives another)SH
+/Times-Italic SF
+42293 XM
+(sample_client)SH
+/Times-Roman SF
+48678 XM
+(request.)SH
+7200 20719 MT
+(When you install the program on the server, you must add a)SH
+/Times-Italic SF
+33807 XM
+(sample)SH
+/Times-Roman SF
+37198 XM
+(entry to the server machine's)SH
+/Times-Italic SF
+7200 21915 MT
+(/etc/inetd.conf)SH
+/Times-Roman SF
+13738 XM
+(file.)SH
+7200 24213 MT
+(The following description assumes that you are installing)SH
+/Times-Italic SF
+32680 XM
+(sample_server)SH
+/Times-Roman SF
+39369 XM
+(on the machine)SH
+/Times-Italic SF
+46364 XM
+(ariadne.tim.edu)SH
+/Times-Roman SF
+(.)SH
+7200 25409 MT
+(Here's the process, step by step:)SH
+9400 27360 MT
+(1.)SH
+10500 XM
+(Login as or)SH
+/Times-Italic SF
+15785 XM
+(su)SH
+/Times-Roman SF
+17038 XM
+(to root on the Kerberos server machine.  Use the)SH
+/Times-Italic SF
+38631 XM
+(kdb_edit)SH
+/Times-Roman SF
+42694 XM
+(or)SH
+/Times-Italic SF
+43885 XM
+(kadmin)SH
+/Times-Roman SF
+47398 XM
+(program)SH
+10500 28556 MT
+(to create an entry for)SH
+/Times-Italic SF
+19935 XM
+(sample)SH
+/Times-Roman SF
+23326 XM
+(in the Kerberos database:)SH
+/Courier SF
+11820 30133 MT
+(host#)SH
+/Times-Bold SF
+15780 XM
+([ADMIN_DIR]/kdb_edit)SH
+/Courier SF
+11820 32361 MT
+(Opening database...)SH
+11820 34589 MT
+(Enter Kerberos master key:)SH
+11820 35703 MT
+(Verifying, please re-enter)SH
+11820 36817 MT
+(master key entered.  BEWARE!)SH
+11820 37931 MT
+(Previous or default values are in [brackets] ,)SH
+11820 39045 MT
+(enter return to leave the same, or new value.)SH
+11820 41273 MT
+(Principal name:)SH
+/Times-Bold SF
+22380 XM
+(sample)SH
+26220 XM
+(<--)SH
+/Times-BoldItalic SF
+28239 XM
+(Enter the principal name.)SH
+/Courier SF
+11820 42387 MT
+(Instance:)SH
+/Times-Bold SF
+18420 XM
+(ariadne)SH
+26220 XM
+(<--)SH
+/Times-BoldItalic SF
+28239 XM
+(Instances cannot have periods in them.)SH
+/Courier SF
+11820 44615 MT
+(<Not found>, Create [y] ?)SH
+/Times-Bold SF
+28980 XM
+(y)SH
+/Courier SF
+11820 46843 MT
+(Principal: sample_server  Instance: ariadne m_key_v: 1)SH
+11820 47957 MT
+(New Password:)SH
+/Times-Bold SF
+26220 XM
+(<--)SH
+/Times-BoldItalic SF
+28239 XM
+(Enter ``RANDOM'' to get random password.)SH
+/Courier SF
+11820 49071 MT
+(Verifying, please re-enter)SH
+11820 50185 MT
+(New Password:)SH
+/Times-Bold SF
+26220 XM
+(<--)SH
+/Times-BoldItalic SF
+28239 XM
+(Enter ``RANDOM'' again.)SH
+/Courier SF
+11820 51299 MT
+(Random password [y] ?)SH
+/Times-Bold SF
+26340 XM
+(y)SH
+/Courier SF
+11820 53527 MT
+(Principal's new key version = 1)SH
+11820 54641 MT
+(Expiration date \050enter dd-mm-yy\051 [ 12/31/99 ] ?)SH
+11820 55755 MT
+(Max ticket lifetime \050*5 minutes\051 [ 255 ] ?)SH
+11820 56869 MT
+(Attributes [ 0 ] ?)SH
+11820 57983 MT
+(Edit O.K.)SH
+11820 60211 MT
+(Principal name:)SH
+/Times-Bold SF
+26220 XM
+(<--)SH
+/Times-BoldItalic SF
+28239 XM
+(Enter newline to exit kdb_edit.)SH
+/Times-Roman SF
+9400 62105 MT
+(2.)SH
+10500 XM
+(Use the)SH
+/Times-Italic SF
+14104 XM
+(ext_srvtab)SH
+/Times-Roman SF
+18961 XM
+(program to create a)SH
+/Times-Italic SF
+27755 XM
+(srvtab)SH
+/Times-Roman SF
+30780 XM
+(file for)SH
+/Times-Italic SF
+34078 XM
+(sample_server)SH
+/Times-Roman SF
+('s host machine:)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30350 XM
+(9)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 10 11
+BS
+0 SI
+11 /Courier AF
+11820 7937 MT
+(host#)SH
+/Times-Bold SF
+15780 XM
+([ADMIN_DIR]/ext_srvtab ariadne)275 W
+/Courier SF
+11820 10165 MT
+(Enter Kerberos master key:)SH
+11820 11279 MT
+(Current Kerberos master key version is 1.)SH
+11820 13507 MT
+(Generating 'ariadne-new-srvtab'....)SH
+/Times-Roman SF
+10500 15102 MT
+(Transfer the)SH
+/Times-Italic SF
+16118 XM
+(ariadne-new-srvtab)SH
+/Times-Roman SF
+25069 XM
+(file to)SH
+/Times-Italic SF
+27941 XM
+(ariadne)SH
+/Times-Roman SF
+31638 XM
+(and install it as)SH
+/Times-Italic SF
+38544 XM
+(/etc/srvtab)SH
+/Times-Roman SF
+(. Note)
+275 W( that this)SH
+10500 16298 MT
+(file is equivalent to the service's password and should be treated with care.  For example, it)SH
+10500 17494 MT
+(could be transferred by removable media, but should not be sent over an open network in)SH
+10500 18690 MT
+(the clear.  Once installed, this file should be readable only by root.)SH
+9400 20584 MT
+(3.)SH
+10500 XM
+(Add the following line to the)SH
+/Times-Italic SF
+23516 XM
+(/etc/services)SH
+/Times-Roman SF
+29227 XM
+(file on)SH
+/Times-Italic SF
+32343 XM
+(ariadne)SH
+/Times-Roman SF
+(, and on all machines that will run)SH
+10500 21780 MT
+(the)SH
+/Times-Italic SF
+12119 XM
+(sample_client)SH
+/Times-Roman SF
+18504 XM
+(program:)SH
+/Courier SF
+11820 23306 MT
+(sample 906/tcp)
+2640 W( #)
+3960 W( Kerberos sample app server)SH
+/Times-Roman SF
+9400 25200 MT
+(4.)SH
+10500 XM
+(Add a line similar to the following line to the)SH
+/Times-Italic SF
+30666 XM
+(/etc/inetd.conf)SH
+/Times-Roman SF
+37204 XM
+(file on)SH
+/Times-Italic SF
+40320 XM
+(sample_server)SH
+/Times-Roman SF
+('s)SH
+10500 26396 MT
+(machine:)SH
+/Courier SF
+11820 27922 MT
+(sample stream tcp nowait switched root)1320 W
+14460 29036 MT
+([PATH]/sample_server sample_server)SH
+/Times-Roman SF
+10500 30631 MT
+(where [PATH] should be substituted with the path to the)SH
+/Times-Italic SF
+35674 XM
+(sample_server)SH
+/Times-Roman SF
+42363 XM
+(program. \050This)275 W
+/Times-Italic SF
+10500 31827 MT
+(inetd.conf)SH
+/Times-Roman SF
+15144 XM
+(information should be placed on one line.\051  You should examine existing lines in)SH
+/Times-Italic SF
+10500 33023 MT
+(/etc/inetd.conf)SH
+/Times-Roman SF
+17038 XM
+(and use the same format used by other entries \050e.g. for telnet\051.  Most systems)SH
+10500 34219 MT
+(do not have a column for the `switched' keyword, and some do not have a column for the)SH
+10500 35415 MT
+(username \050usually `root', as above\051.)SH
+9400 37309 MT
+(5.)SH
+10500 XM
+(Restart)SH
+/Times-Italic SF
+13891 XM
+(inetd)SH
+/Times-Roman SF
+16366 XM
+(by sending the current)SH
+/Times-Italic SF
+26446 XM
+(inetd)SH
+/Times-Roman SF
+28921 XM
+(process a hangup signal:)SH
+/Courier SF
+11820 38909 MT
+(host#)SH
+/Times-Bold SF
+15780 XM
+(kill -HUP)275 W
+/Times-BoldItalic SF
+21373 XM
+(process_id_number)SH
+/Times-Roman SF
+9400 40803 MT
+(6.)SH
+10500 XM
+(The)SH
+/Times-Italic SF
+12485 XM
+(sample_server)SH
+/Times-Roman SF
+19174 XM
+(is now ready to take)SH
+/Times-Italic SF
+28307 XM
+(sample_client)SH
+/Times-Roman SF
+34692 XM
+(requests.)SH
+14 /Times-Bold AF
+7200 44621 MT
+(5.2 Testing)
+350 W( the Sample Server)SH
+11 /Times-Roman AF
+7200 46816 MT
+(Assume that you have installed)SH
+/Times-Italic SF
+21223 XM
+(sample_server)SH
+/Times-Roman SF
+27912 XM
+(on)SH
+/Times-Italic SF
+29287 XM
+(ariadne)SH
+/Times-Roman SF
+(.)SH
+7200 49114 MT
+(Login to your workstation and use the)SH
+/Times-Italic SF
+24217 XM
+(kinit)SH
+/Times-Roman SF
+26448 XM
+(command to obtain a Kerberos ticket-granting ticket:)SH
+/Courier SF
+8520 50691 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([K_USER]/kinit)SH
+/Courier SF
+8520 51805 MT
+(MIT Project Athena, \050your_workstation\051)SH
+8520 52919 MT
+(Kerberos Initialization)SH
+8520 54033 MT
+(Kerberos name:)SH
+/Times-BoldItalic SF
+18420 XM
+(yourusername)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter your Kerberos username.)SH
+/Courier SF
+8520 55147 MT
+(Password:)SH
+/Times-Bold SF
+28800 XM
+(<--)SH
+/Times-BoldItalic SF
+30819 XM
+(Enter your Kerberos password.)SH
+/Times-Roman SF
+7200 57445 MT
+(Now use the)SH
+/Times-Italic SF
+12973 XM
+(sample_client)SH
+/Times-Roman SF
+19358 XM
+(program as follows:)SH
+/Courier SF
+8520 59022 MT
+(host%)SH
+/Times-Bold SF
+12480 XM
+([PATH]/sample_client ariadne)275 W
+/Times-Roman SF
+7200 60617 MT
+(The command should display something like the following:)SH
+/Courier SF
+8520 62143 MT
+(The server says:)SH
+8520 63257 MT
+(You are)SH
+/Times-BoldItalic SF
+13800 XM
+(yourusername)SH
+/Courier SF
+(.@REALMNAME \050local name)SH
+/Times-BoldItalic SF
+36180 XM
+(yourusername)SH
+/Courier SF
+(\051,)SH
+9180 64371 MT
+(at address)SH
+/Times-BoldItalic SF
+16440 XM
+(yournetaddress)SH
+/Courier SF
+(, version VERSION9, cksum 997)SH
+10 /Times-Roman AF
+7200 75600 MT
+(MIT Project Athena)SH
+30100 XM
+(10)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: 11 12
+BS
+0 SI
+16 /Times-Bold AF
+7200 8272 MT
+(6. Service)
+400 W( names and other services)SH
+14 SS 
+7200 12090 MT
+(6.1 rlogin,)
+350 W( rsh, rcp, tftp, and others)SH
+11 /Times-Roman AF
+7200 14285 MT
+(Many services use a common principal name for authentication purposes.)SH
+/Times-Italic SF
+40128 XM
+(rlogin)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+43368 XM
+(rsh)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+45324 XM
+(rcp)SH
+/Times-Roman SF
+(,)SH
+/Times-Italic SF
+47340 XM
+(tftp)SH
+/Times-Roman SF
+49083 XM
+(and others)SH
+7200 15481 MT
+(use the principal name ``)SH
+/Courier SF
+(rcmd)SH
+/Times-Roman SF
+(''. For)
+275 W( example, to set up the machine)SH
+/Times-Italic SF
+38033 XM
+(ariadne)SH
+/Times-Roman SF
+41730 XM
+(to support Kerberos rlogin,)SH
+7200 16677 MT
+(it needs to have a service key for principal ``)SH
+/Courier SF
+(rcmd)SH
+/Times-Roman SF
+('', instance ``)SH
+/Courier SF
+(ariadne)SH
+/Times-Roman SF
+(''. You)
+275 W( create this key in the)SH
+7200 17873 MT
+(same way as shown above for the sample service.)SH
+7200 20171 MT
+(After creating this key, you need to run the)SH
+/Times-Italic SF
+26382 XM
+(ext_srvtab)SH
+/Times-Roman SF
+31239 XM
+(program again to generate a new srvtab file for)SH
+7200 21367 MT
+(ariadne.)SH
+14 /Times-Bold AF
+7200 25185 MT
+(6.2 NFS)
+350 W( modifications)SH
+11 /Times-Roman AF
+7200 27380 MT
+(The NFS modifications distributed separately use the service name ``)SH
+/Courier SF
+(rvdsrv)SH
+/Times-Roman SF
+('' with the instance set to)SH
+7200 28576 MT
+(the machine name \050as for the sample server and the rlogin, rsh, rcp and tftp services\051.)SH
+14 /Times-Bold AF
+7200 32394 MT
+(6.3 inetd.conf)
+350 W( entries)SH
+11 /Times-Roman AF
+7200 34589 MT
+(The following are the)SH
+/Times-Italic SF
+16974 XM
+(/etc/inetd.conf)SH
+/Times-Roman SF
+23512 XM
+(entries necessary to support rlogin, encrypted rlogin, rsh, and rcp)SH
+7200 35785 MT
+(services on a server machine.  As above, your)SH
+/Times-Italic SF
+27631 XM
+(inetd.conf)SH
+/Times-Roman SF
+32275 XM
+(may not support all the fields shown here.)SH
+/Courier SF
+8520 37311 MT
+(eklogin stream)
+660 W( tcp nowait unswitched root)1320 W
+11160 38425 MT
+([PATH]/klogind eklogind)1320 W
+8520 39539 MT
+(kshell stream tcp nowait unswitched root)1320 W
+11160 40653 MT
+([PATH]/kshd kshd)1320 W
+8520 41767 MT
+(klogin stream tcp nowait unswitched root)1320 W
+11160 42881 MT
+([PATH]/klogind klogind)1320 W
+10 /Times-Roman AF
+7200 75600 MT
+(MIT Project Athena)SH
+30100 XM
+(11)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Page: i 13
+BS
+0 SI
+14 /Times-Bold AF
+25272 8138 MT
+(Table of Contents)SH
+13 SS 
+7200 9781 MT
+(1. How)
+325 W( Kerberos Works: A Schematic Description)SH
+53350 XM
+(1)SH
+12 /Times-Roman AF
+9000 11130 MT
+(1.1 Network)
+300 W( Services and Their Client Programs)SH
+53400 XM
+(1)SH
+9000 12479 MT
+(1.2 Kerberos)
+300 W( Tickets)SH
+53400 XM
+(1)SH
+9000 13828 MT
+(1.3 The)
+300 W( Kerberos Master Database)SH
+53400 XM
+(1)SH
+9000 15177 MT
+(1.4 The)
+300 W( Ticket-Granting Ticket)SH
+53400 XM
+(1)SH
+9000 16526 MT
+(1.5 Network)
+300 W( Services and the Master Database)SH
+53400 XM
+(1)SH
+9000 17875 MT
+(1.6 The)
+300 W( User-Kerberos Interaction)SH
+53400 XM
+(2)SH
+13 /Times-Bold AF
+7200 19518 MT
+(2. Setting)
+325 W( Up and Testing the Kerberos Server)SH
+53350 XM
+(2)SH
+12 /Times-Roman AF
+9000 20867 MT
+(2.1 Creating)
+300 W( and Initializing the Master Database)SH
+53400 XM
+(3)SH
+9000 22216 MT
+(2.2 Storing)
+300 W( the Master Password)SH
+53400 XM
+(3)SH
+9000 23571 MT
+(2.3 Using)300 W
+/Times-BoldItalic SF
+14267 XM
+(kdb_edit)SH
+/Times-Roman SF
+18768 XM
+(to Add Users to the Master Database)SH
+53400 XM
+(4)SH
+9000 24920 MT
+(2.4 Starting)
+300 W( the Kerberos Server)SH
+53400 XM
+(4)SH
+9000 26269 MT
+(2.5 Testing)
+300 W( the Kerberos Server)SH
+53400 XM
+(5)SH
+13 /Times-Bold AF
+7200 27912 MT
+(3. Setting)
+325 W( up and testing the Administration server)SH
+53350 XM
+(5)SH
+12 /Times-Roman AF
+9000 29261 MT
+(3.1 Adding)
+300 W( an administration instance for the administrator)SH
+53400 XM
+(6)SH
+9000 30610 MT
+(3.2 The)
+300 W( Access Control Lists)SH
+53400 XM
+(6)SH
+9000 31959 MT
+(3.3 Starting)
+300 W( the administration server)SH
+53400 XM
+(7)SH
+9000 33314 MT
+(3.4 Testing)300 W
+/Times-BoldItalic SF
+15001 XM
+(kpasswd)SH
+/Times-Roman SF
+53400 XM
+(7)SH
+9000 34669 MT
+(3.5 Testing)300 W
+/Times-BoldItalic SF
+15001 XM
+(kadmin)SH
+/Times-Roman SF
+53400 XM
+(7)SH
+9000 36024 MT
+(3.6 Verifying)
+300 W( with)SH
+/Times-BoldItalic SF
+18501 XM
+(kinit)SH
+/Times-Roman SF
+53400 XM
+(8)SH
+13 /Times-Bold AF
+7200 37667 MT
+(4. Setting)
+325 W( up and testing slave server\050s\051)SH
+53350 XM
+(8)SH
+7200 39310 MT
+(5. A)
+325 W( Sample Application)SH
+53350 XM
+(8)SH
+12 /Times-Roman AF
+9000 40659 MT
+(5.1 The)
+300 W( Installation Process)SH
+53400 XM
+(8)SH
+9000 42008 MT
+(5.2 Testing)
+300 W( the Sample Server)SH
+52800 XM
+(10)SH
+13 /Times-Bold AF
+7200 43651 MT
+(6. Service)
+325 W( names and other services)SH
+52700 XM
+(11)SH
+12 /Times-Roman AF
+9000 45000 MT
+(6.1 rlogin,)
+300 W( rsh, rcp, tftp, and others)SH
+52800 XM
+(11)SH
+9000 46349 MT
+(6.2 NFS)
+300 W( modifications)SH
+52800 XM
+(11)SH
+9000 47698 MT
+(6.3 inetd.conf)
+300 W( entries)SH
+52800 XM
+(11)SH
+10 SS 
+7200 75600 MT
+(MIT Project Athena)SH
+30461 XM
+(i)SH
+47890 XM
+(4 January 1990)SH
+ES
+%%Trailer
+%%Pages: 13
+%%DocumentFonts: Times-Roman Times-Bold Times-Italic Times-BoldItalic Courier Symbol
diff --git a/krb5-1-6/doc/old-V4-docs/operation.mss b/krb5-1-6/doc/old-V4-docs/operation.mss
new file mode 100644
index 000000000..a35bb9f95
--- /dev/null
+++ b/krb5-1-6/doc/old-V4-docs/operation.mss
@@ -0,0 +1,799 @@
+@Comment[	$Source$]
+@Comment[	$Author$]
+@Comment[	$Id$]
+@Comment[]
+@device[postscript]
+@make[report]
+@comment[
+@DefineFont(HeadingFont,
+      P=<RawFont "NewCenturySchlbkBoldItalic">,
+      B=<RawFont "NewCenturySchlbkBold">,
+      I=<RawFont "NewCenturySchlbkBoldItalic">,
+      R=<RawFont "NewCenturySchlbkRoman">)
+]
+@DefineFont(HeadingFont,
+      P=<RawFont "TimesBoldItalic">,
+      B=<RawFont "TimesBold">,
+      I=<RawFont "TimesItalic">,
+      R=<RawFont "TimesRoman">)
+@Counter(MajorPart,TitleEnv HD0,ContentsEnv tc0,Numbered [@I],
+          IncrementedBy Use,Announced)
+@Counter(Chapter,TitleEnv HD1,ContentsEnv tc1,Numbered [@1. ],
+          IncrementedBy Use,Referenced [@1],Announced)
+@Counter(Appendix,TitleEnv HD1,ContentsEnv tc1,Numbered [@A. ],
+          IncrementedBy,Referenced [@A],Announced,Alias Chapter)
+@Counter(UnNumbered,TitleEnv HD1,ContentsEnv tc1,Announced,Alias 
+           Chapter)
+@Counter(Section,Within Chapter,TitleEnv HD2,ContentsEnv tc2,
+          Numbered [@#@:.@1 ],Referenced [@#@:.@1],IncrementedBy
+          Use,Announced)
+@Counter(AppendixSection,Within Appendix,TitleEnv HD2,
+          ContentsEnv tc2,
+          Numbered [@#@:.@1 ],Referenced [@#@:.@1],IncrementedBy 
+          Use,Announced)
+@Counter(SubSection,Within Section,TitleEnv HD3,ContentsEnv tc3,
+          Numbered [@#@:.@1 ],IncrementedBy Use,
+          Referenced [@#@:.@1 ])
+@Counter(AppendixSubSection,Within AppendixSection,TitleEnv HD3,
+          ContentsEnv tc3,
+          Numbered [@#@:.@1 ],IncrementedBy Use,
+          Referenced [@#@:.@1 ])
+@Counter(Paragraph,Within SubSection,TitleEnv HD4,ContentsEnv tc4,
+          Numbered [@#@:.@1 ],Referenced [@#@:.@1],
+          IncrementedBy Use)
+@modify(CopyrightNotice, Fixed -1 inch, Flushright)
+@Modify(Titlebox, Fixed 3.0 inches)
+@Modify(hd1, below .2 inch, facecode B, size 16, spaces kept, pagebreak off)
+@Modify(hd2, below .2 inch, facecode B, size 14, spaces kept)
+@Modify(hd3, below .2 inch, facecode B, size 12, spaces kept)
+@Modify(Description, Leftmargin +20, Indent -20,below 1 line, above 1 line)
+@Modify(Tc1, Above .5,  Facecode B)
+@Modify(Tc2, Above .25, Below .25, Facecode R)
+@Modify(Tc3,Facecode R)
+@Modify(Tc4,Facecode R)
+@Modify(Itemize,Above 1line,Below 1line)
+@Modify(Insert,LeftMargin +2, RightMargin +2)
+@libraryfile[stable]
+@comment[@Style(Font NewCenturySchoolBook, size 11)]
+@Style(Font TimesRoman, size 11)
+@Style(Spacing 1.1, indent 0)
+@Style(leftmargin 1.0inch)
+@Style(justification no)
+@Style(BottomMargin 1.5inch)
+@Style(ChangeBarLocation Right)
+@Style(ChangeBars=off)
+@pageheading[immediate]
+@pagefooting[immediate, left = "MIT Project Athena", center = "@value(page)",
+right = "@value(date)"]
+@set[page = 0]
+@blankspace[.5 inches]
+@begin[group, size 20]
+@begin(center)
+@b[Kerberos Operation Notes]
+@b[DRAFT]
+@end[center]
+@blankspace[.5 inches]
+@end(group)
+@begin[group, size 16]
+@begin(center)
+Bill Bryant
+John Kohl
+Project Athena, MIT
+@blankspace[.5 inches]
+@b[Initial Release, January 24, 1989]
+@i[(plus later patches through patchlevel 7)]
+@end[center]
+@end(group)
+@begin[group, size 10]
+@end[group]
+@blankspace[1inches]
+
+These notes assume that you have used the
+@i[Kerberos Installation Notes] to build and install your
+Kerberos system.
+As in that document, we refer to the directory that contains
+the built Kerberos binaries as [OBJ_DIR].
+
+This document assumes that you are a Unix system manager.
+
+@newpage()
+@chapter[How Kerberos Works: A Schematic Description]
+
+This section provides a simplified description of
+a general user's interaction with the Kerberos system.
+This interaction happens transparently--users don't need to know
+and probably don't care about what's going on--but Kerberos administrators
+might find a schematic description of the process useful.
+The description glosses over a lot of details;
+for more information, see @i[Kerberos: An Authentication
+Service for Open Network Systems],
+a paper presented at Winter USENIX 1988, in Dallas, Texas.
+
+@section[Network Services and Their Client Programs]
+
+In an environment that provides network services,
+you use @i[client] programs to request service from
+@i[server] programs that are somewhere on the network.
+Suppose you have logged in to a workstation
+and you want to @i[rlogin] to another machine.
+You use the local @i[rlogin] client program to
+contact the remote machine's @i[rlogin] service daemon.
+
+@section[Kerberos Tickets]
+
+Under Kerberos, the @i[rlogin] service program
+allows a client to login to a remote machine if it
+can provide
+a Kerberos @b[ticket] for the request.
+This ticket proves the identity of the person who has used
+the client program to access the server program.
+
+@section[The Kerberos Master Database]
+
+Kerberos will give you tickets only if you
+have an entry in the Kerberos server's
+@b[master database].
+Your database entry includes your Kerberos username (often referred to
+as your Kerberos @b[principal] name), and your Kerberos password.
+Every Kerberos user must have an entry in this database.
+
+@section[The Ticket-Granting Ticket]
+
+The @i[kinit] command prompts for your Kerberos username and password,
+and if you enter them successfully, you will obtain a Kerberos
+@i[ticket-granting ticket].
+As illustrated below,
+client programs use this ticket to get other Kerberos tickets as
+needed.
+
+@section[Network Services and the Master Database]
+
+The master database also contains entries for all network services that
+require Kerberos authentication.
+Suppose for instance that your site has a machine @i[laughter]
+that requires Kerberos authentication from anyone who wants
+to @i[rlogin] to it.
+This service must be registered in the master database.
+Its entry includes the service's principal name, and its @b[instance].
+
+The @i[instance] is the name of the service's machine;
+in this case, the service's instance is the name @i[laughter].
+The instance provides a means for Kerberos to distinguish between
+machines that provide the same service.
+Your site is likely to have more than one machine that
+provides @i[rlogin] service.
+
+@section[The User-Kerberos Interaction]
+
+Suppose that you (in the guise of a general user) walk up to a workstation
+intending to login to it, and then @i[rlogin] to the machine @i[laughter].
+Here's what happens.
+@begin[enumerate]
+You login to the workstation and use the @i[kinit] command
+to to get a ticket-granting ticket.
+This command prompts you for your username (your Kerberos Principal Name),
+and your Kerberos password [on some systems which use the new version of
+@i{/bin/login}, this may be done as part of the login process, not
+requiring the user to run a separate program].
+@begin[enumerate]
+The @i[kinit] command sends your request to the Kerberos master server
+machine.
+The server software looks for your principal name's entry in the
+Kerberos @b[master database].
+
+If this entry exists, the
+Kerberos server creates and returns a
+@i[ticket-granting ticket], encrypted in your password.
+If @i[kinit] can decrypt the Kerberos reply using the password you
+provide, it stores this ticket in a @b[ticket file] on your
+local machine for later use.
+The ticket file to be used
+can be specified in the @b[KRBTKFILE] environment
+variable.  If this variable is not set, the name of the file will be
+@i[/tmp/tkt@p(uid)], where @p(uid) is the UNIX user-id, represented in decimal.
+@end[enumerate]
+
+Now you use the @i[rlogin] client to try to access the machine @i[laughter].
+@begin[example]
+host% @b[rlogin  laughter]
+@end[example]
+@begin[enumerate]
+The @i[rlogin] client checks your ticket file to see if you
+have a ticket for @i[laughter]'s @i[rcmd] service (the rlogin program
+uses the @i[rcmd] service name, mostly for historical reasons).
+You don't, so @i[rlogin] uses the ticket file's @i[ticket-granting
+ticket] to make a request to the master server's ticket-granting service.
+
+This ticket-granting service receives the @i[rcmd-laughter] request
+and looks in the master database for an @i[rcmd-laughter] entry.
+If that entry exists, the ticket-granting service issues you a ticket
+for that service.
+That ticket is also cached in your ticket file.
+
+The @i[rlogin] client now uses that ticket to request service from
+the @i[laughter] @i[rlogin] service program.
+The service program
+lets you @i[rlogin] if the ticket is valid.
+@end[enumerate]
+@end[enumerate]
+
+@chapter[Setting Up and Testing the Kerberos Server]
+
+The procedure for setting up and testing a Kerberos server
+is as follows:
+@begin[enumerate]
+Use the @i[kdb_init] command to create and initialize the master database.
+
+Use the @i[kdb_edit] utility to add your username to the
+master database.
+
+Start the Kerberos server.
+
+Use the @i[kinit] command to obtain a Kerberos ticket-granting ticket.
+
+Use the @i[klist] command to verify that the @i[kinit] command
+authenticated you successfully.
+@end[enumerate]
+
+@section[Creating and Initializing the Master Database]
+
+Login to the Kerberos master server machine,
+and use the @b[su] command to become root.
+If you installed the Kerberos administration tools
+with the @i[make install] command and the default pathnames,
+they should be in the @i[/usr/etc] directory.
+If you installed the tools in a different directory,
+hopefully you know what it is.
+From now on, we will refer to this directory as [ADMIN_DIR].
+
+The @i[kdb_init] command creates and initializes the master database.
+It asks you to enter the system's
+realm name and the database's master password.
+Do not forget this password.
+If you do, the database becomes useless.
+(Your realm name should be substituted for [REALMNAME] below.)
+
+Use @i[kdb_init] as follows:
+@tabset[3inches, +1.5inches]
+@begin[example, rightmargin -10]
+host# @b([ADMIN_DIR]/kdb_init)
+Realm name (default XXX): @b([REALMNAME])@\@b[<--] @p[Enter your system's realm name.]
+You will be prompted for the database Master Password.
+It is important that you NOT FORGET this password.
+
+Enter Kerberos master key: @\@b[<--] @p[Enter the master password.]
+@comment(this needs to be re-fixed...:
+Verifying, please re-enter
+Enter Kerberos master key: @\@b[<--] @p[Re-enter it.]
+)
+@end[example]
+
+@section[Storing the Master Password]
+
+The @i[kstash] command ``stashes'' the master password in the file @i[/.k]
+so that the Kerberos server can
+be started automatically during an unattended reboot of the
+master server.
+Other administrative programs use this hidden password so that they
+can access the master database without someone having to manually
+provide the master password.
+This command is an optional one;
+if you'd rather enter the master password each time you
+start the Kerberos server, don't use @i[kstash].
+
+One the one hand, if you use @i[kstash], a copy of the master
+key will reside
+on disk which may not be acceptable; on the other hand, if you don't
+use @i[kstash], the server cannot be started unless someone is around to
+type the password in manually.
+
+The command prompts you twice for the master password:
+@begin[example]
+@tabset[3inches]
+host# @b([ADMIN_DIR]/kstash)
+
+Enter Kerberos master key:@\@b[<--] @p[Enter the master password.]
+Current Kerberos master key version is 1.
+
+Master key entered   BEWARE!
+@end[example]
+
+A note about the Kerberos database master key:
+if your master key is compromised and the database is obtained,
+the security of your entire authentication system is compromised.
+The master key must be a carefully kept secret.  If you keep backups,
+you must guard all the master keys you use, in case someone has stolen
+an old backup and wants to attack users' whose passwords haven't changed
+since the backup was stolen.
+This is why we provide the option not to store it on disk.
+
+@section[Using @p(kdb_edit) to Add Users to the Master Database]
+
+The @i[kdb_edit] program is used to add new users and services
+to the master database, and to modify existing database information.
+The program prompts you to enter a principal's @b[name] and @b[instance].
+
+A principal name is typically a username or a service program's name.
+An instance further qualifies the principal.
+If the principal is a service,
+the instance is used to specify the name of the machine on which that
+service runs.
+If the principal is a username that has general user privileges,
+the instance is usually set to null.
+
+The following example shows how to use @i[kdb_edit] to
+add the user @i[wave] to the Kerberos database.
+@begin[example, rightmargin -10]
+@tabset[3inches, +1.5inches]
+host# @b([ADMIN_DIR]/kdb_edit)
+
+Opening database...
+
+Enter Kerberos master key:
+Verifying, please re-enter
+Enter Kerberos master key:
+Current Kerberos master key version is 1
+
+Master key entered.  BEWARE!
+Previous or default values are in [brackets] ,
+enter return to leave the same, or new value.
+
+Principal name: @b[wave]@\@b[<--] @p[Enter the username.]
+Instance:@\@p[<-- Enter a null instance.]
+
+<Not found>, Create [y] ? @b[y]@\@b[<--] @p[The user-instance does not exist.]
+@\@p[      Enter y to create the user-instance.]
+Principal: wave  Instance:  m_key_v: 1
+New Password: @\@p[<-- Enter the user-instance's password.]
+Verifying, please re-enter 
+New Password:
+Principal's new key version = 1
+Expiration date (enter dd-mm-yy) [ 12/31/99 ] ?@\@b[<--] @p[Enter newlines]
+Max ticket lifetime (*5 minutes) [ 255 ] ? @\@b[<--] @p[to get the]
+Attributes [ 0 ] ? @\@\@b[<--] @p[default values.]
+Edit O.K.
+
+Principal name:@\@p[<-- Enter a newline to exit the program.]
+@end[example]
+
+Use the @i[kdb_edit] utility to add your username to the master database.
+
+@section[Starting the Kerberos Server]
+
+Change directories to the directory in which you have installed
+the server program @i[kerberos]
+(the default directory is @i[/usr/etc]),
+and start the program as a background process:
+@begin[example]
+host# @b[./kerberos &]
+@end[example]
+If you have used the @i[kstash] command to store the master database password,
+the server will start automatically.
+If you did not use @i[kstash],
+use the following command:
+@begin[example]
+host# @b[./kerberos -m]
+@end[example]
+The server will prompt you to enter the master password before actually
+starting itself.
+
+@section[Testing the Kerberos Server]
+
+Exit the root account and use the @i[kinit] command obtain a Kerberos
+ticket-granting ticket.
+This command
+creates your ticket file
+and stores the ticket-granting ticket in it.
+
+If you used the default @i[make install] command and directories to
+install the Kerberos user utilities, @i[kinit] will be in the
+@i[/usr/athena] directory. From now on, we'll refer to the Kerberos user
+commands directory as [K_USER].
+
+Use @i[kinit] as follows:
+@begin[example]
+@tabset[3 inches]
+host% @b([K_USER]/kinit)
+MIT Project Athena, (ariadne)
+Kerberos Initialization
+Kerberos name: @p[yourusername]@\@b[<--] @p[Enter your Kerberos username.]
+Password: @\@b[<--] @p[Enter your Kerberos password.]
+@end[example]
+
+Use the @i[klist] program to list the contents of your ticket file.
+@begin[example]
+host% @b([K_USER]/klist)
+@end[example]
+The command should display something like the following:
+@begin[example]
+Ticket file:    /tmp/tkt5555
+Principal:      yourusername@@REALMNAME
+
+  Issued           Expires          Principal
+May  6 10:15:23  May  6 18:15:23  krbtgt.REALMNAME@@REALMNAME
+@end[example]
+
+If you have any problems, you can examine the log file
+@i[/kerberos/kerberos.log] on the Kerberos server machine to see if
+there was some sort of error.
+
+@chapter[Setting up and testing the Administration server]
+
+The procedure for setting up and testing the Kerberos administration server
+is as follows:
+@begin[enumerate]
+Use the @i[kdb_edit] utility to add your username with an administration
+instance to the master database.
+
+Edit the access control lists for the administration server
+
+Start the Kerberos administration server.
+
+Use the @i[kpasswd] command to change your password.
+
+Use the @i[kadmin] command to add new entries to the database.
+
+Use the @i[kinit] command to verify that the @i[kadmin] command
+correctly added new entries to the database.
+@end(enumerate)
+
+@section[Adding an administration instance for the administrator]
+
+Login to the Kerberos master server machine,
+and use the @b[su] command to become root.
+Use the @i[kdb_edit] program to create an entry for each administrator
+with the instance ``@p(admin)''.
+@begin[example]
+@tabset[3inches, +1.5inches]
+host# @b([ADMIN_DIR]/kdb_edit)
+
+Opening database...
+
+Enter Kerberos master key:
+Verifying, please re-enter
+Enter Kerberos master key:
+Current Kerberos master key version is 1
+
+Master key entered.  BEWARE!
+Previous or default values are in [brackets] ,
+enter return to leave the same, or new value.
+
+Principal name: @b[wave]@\@b[<--] @p[Enter the username.]
+Instance:@b[admin]@\@b[<--] @p[Enter ``admin''.]
+
+<Not found>, Create [y] ? @b[y]@\@b[<--] @p[The user-instance does not exist.]
+@\@p[      Enter y to create the user-instance.]
+Principal: wave  Instance: admin m_key_v: 1
+New Password: @\@p[<-- Enter the user-instance's password.]
+Verifying, please re-enter 
+New Password:
+Principal's new key version = 1
+Expiration date (enter dd-mm-yy) [ 12/31/99 ] ?@\@b[<--] @p[Enter newlines]
+Max ticket lifetime (*5 minutes) [ 255 ] ? @\@b[<--] @p[to get the]
+Attributes [ 0 ] ? @\@\@b[<--] @p[default values.]
+Edit O.K.
+
+Principal name:@\@p[<-- Enter a newline to exit the program.]
+@end[example]
+
+@section[The Access Control Lists]
+The Kerberos administration server uses three access control lists to
+determine who is authorized to make certain requests.  The access
+control lists are stored on the master Kerberos server in the same
+directory as the principal database, @i(/kerberos).  The access control
+lists are simple ASCII text files, with each line specifying the name of
+one principal who is allowed the particular function.  To allow several
+people to perform the same function, put their principal names on
+separate lines in the same file.
+
+The first list, @i(/kerberos/admin_acl.mod), is a list of principals
+which are authorized to change entries in the database.  To allow the
+administrator `@b[wave]' to modify entries in the database for the realm
+`@b[TIM.EDU]', you would put the following line into the file
+@i(/kerberos/admin_acl.mod):
+@begin(example)
+wave.admin@@TIM.EDU
+@end(example)
+
+The second list, @i(/kerberos/admin_acl.get), is a list of principals
+which are authorized to retrieve entries from the database.
+
+The third list, @i(/kerberos/admin_acl.add), is a list of principals
+which are authorized to add new entries to the database.
+
+@section(Starting the administration server)
+Change directories to the directory in which you have installed
+the administration server program @i[kadmind]
+(the default directory is @i[/usr/etc]),
+and start the program as a background process:
+@begin[example]
+host# @b[./kadmind -n&]
+@end[example]
+If you have used the @i[kstash] command to store the master database password,
+the server will start automatically.
+If you did not use @i[kstash],
+use the following command:
+@begin[example]
+host# @b[./kadmind]
+@end[example]
+The server will prompt you to enter the master password before actually
+starting itself; after it starts, you should suspend it and put it in
+the background (usually this is done by typing control-Z and then @b(bg)).
+
+@section(Testing @p[kpasswd])
+
+To test the administration server, you should try changing your password
+with the @i[kpasswd] command, and you should try adding new users with
+the @i[kadmin] command (both commands are installed into @i[/usr/athena]
+by default).
+
+Before testing, you should exit the root account.
+
+To change your password, run the @i[kpasswd] command:
+@begin(example)
+@tabset[3inches, +1.5inches]
+host% @b([K_USER]/kpasswd)
+Old password for wave@@TIM.EDU:@\@b[<--]@p[Enter your password]
+New Password for wave@@TIM.EDU:@\@b[<--]@p[Enter a new password]
+Verifying, please re-enter New Password for wave@@TIM.EDU:
+@\@b[<--]@p[Enter new password again]
+Password changed.
+@end(example)
+Once you have changed your password, use the @i[kinit] program as shown
+above to verify that the password was properly changed.
+
+@section(Testing @p[kadmin])
+You should also test the function of the @i[kadmin] program, by adding a
+new user (here named ``@t[username]''):
+@begin(example)
+@tabset[3inches, +1.5inches]
+host% @b([K_USER]/kadmin)
+Welcome to the Kerberos Administration Program, version 2
+Type "help" if you need it.
+admin:  @b(ank username)@\@p[`ank' stands for Add New Key]
+Admin password: @\@b[<--]@p[enter the password 
+@\you chose above for wave.admin]
+Password for username:@\@b[<--]@p[Enter the user's initial password]
+Verifying, please re-enter Password for username:@\@b[<--]@p[enter it again]
+username added to database.
+
+admin:  quit
+Cleaning up and exiting.
+@end[example]
+
+@section(Verifying with @p[kinit])
+Once you've added a new user, you should test to make sure it was added
+properly by using @i[kinit], and trying to get tickets for that user:
+
+@begin[example]
+@tabset[3inches, +1.5inches]
+host% @b([K_USER]/kinit username)
+MIT Project Athena (ariadne)
+Kerberos Initialization for "username@@TIM.EDU"
+Password: @b[<--]@p[Enter the user's password you used above]
+host% @b([K_USER]/klist)
+Ticket file:    /tmp/tkt_5509_spare1
+Principal:      username@@TIM.MIT.EDU
+
+  Issued           Expires          Principal
+Nov 20 15:58:52  Nov 20 23:58:52  krbtgt.TIM.EDU@@TIM.EDU
+@end[example]
+
+If you have any problems, you can examine the log files
+@i[/kerberos/kerberos.log] and @i[/kerberos/admin_server.syslog] on the
+Kerberos server machine to see if there was some sort of error.
+
+@chapter[Setting up and testing slave server(s)]
+
+[Unfortunately, this chapter is not yet ready.  Sorry. -ed]
+
+@chapter[A Sample Application]
+
+This release of Kerberos comes with a sample application
+server and a corresponding client program.
+You will find this software in the [OBJ_DIR]@i[/appl/sample] directory.
+The file @i[sample_client] contains the client program's executable
+code, the file @i[sample_server] contains the server's executable.
+
+The programs are rudimentary.
+When they have been installed (the installation procedure is described
+in detail later), they work as follows:
+@begin[itemize]
+The user starts @i[sample_client] and provides as arguments
+to the command the name of the server machine and a checksum.
+For instance:
+@begin[example]
+host% @b[sample_client]  @p[servername] @p[43]
+@end[example]
+
+@i[Sample_client] contacts the server machine and
+authenticates the user to @i[sample_server].
+
+@i[Sample_server] authenticates itself to @i[sample_client],
+then returns a message to the client program.
+This message contains diagnostic information
+that includes the user's username, the Kerberos realm,
+and the user's workstation address.
+
+@i[Sample_client] displays the server's message on the user's
+terminal screen.
+@end[itemize]
+
+@section[The Installation Process]
+
+In general,
+you use the following procedure to install a Kerberos-authenticated
+server-client system.
+@begin[enumerate]
+Add the appropriate entry to the Kerberos database using @i[kdb_edit] or
+@i[kadmin] (described below).
+
+Create a @i[/etc/srvtab] file for the server machine.
+
+Install the service program and the @i[/etc/srvtab]
+file on the server machine.
+
+Install the client program on the client machine.
+
+Update the @i[/etc/services] file on the client and server machines.
+@end[enumerate]
+
+We will use the sample application as an example, although
+the procedure used to install @i[sample_server] differs slightly
+from the general case because the @i[sample_server]
+takes requests via the
+@i[inetd] program.
+@i[Inetd] starts @i[sample_server] each time
+a client process contacts the server machine.
+@i[Sample_server] processes the request,
+terminiates, then is restarted when @i[inetd] receives another
+@i[sample_client] request.
+When you install the program on the server,
+you must add a @i[sample] entry to the server machine's
+@i[/etc/inetd.conf] file.
+
+The following description assumes that you are installing
+@i[sample_server] on the machine @i[ariadne.tim.edu].
+Here's the process, step by step:
+@begin[enumerate]
+Login as or @i[su] to root on the Kerberos server machine.
+Use the @i[kdb_edit] or @i[kadmin] program to create an entry for
+@i[sample] in the Kerberos database:
+@begin[example, rightmargin -10]
+@tabset[2.0inches, +.5inches]
+host# @b([ADMIN_DIR]/kdb_edit)
+
+Opening database...
+
+Enter Kerberos master key:
+Verifying, please re-enter
+master key entered.  BEWARE!
+Previous or default values are in [brackets] ,
+enter return to leave the same, or new value.
+
+Principal name: @b[sample]@\@b[<--] @p[Enter the principal name.]
+Instance: @b[ariadne]@\@b[<--] @p[Instances cannot have periods in them.]
+
+<Not found>, Create [y] ? @b[y]
+
+Principal: sample_server  Instance: ariadne m_key_v: 1
+New Password:@\@b[<--] @p[Enter ``RANDOM'' to get random password.]
+Verifying, please re-enter 
+New Password:@\@b[<--] @p[Enter ``RANDOM'' again.]
+Random password [y] ? @b[y]
+
+Principal's new key version = 1
+Expiration date (enter dd-mm-yy) [ 12/31/99 ] ? 
+Max ticket lifetime (*5 minutes) [ 255 ] ? 
+Attributes [ 0 ] ? 
+Edit O.K.
+
+Principal name:@\@b[<--] @p[Enter newline to exit kdb_edit.]
+@end[example]
+
+Use the @i[ext_srvtab] program to create a @i[srvtab] file
+for @i[sample_server]'s host machine:
+@begin[example]
+host# @b([ADMIN_DIR]/ext_srvtab  ariadne)
+
+Enter Kerberos master key: 
+Current Kerberos master key version is 1.
+
+Generating 'ariadne-new-srvtab'....
+@end[example]
+Transfer the @i[ariadne-new-srvtab] file to @i[ariadne] and install it as
+@i[/etc/srvtab].
+Note that this file is equivalent to the service's password and should
+be treated with care.
+For example, it could be transferred by removable media, but should
+not be sent over an open network in the clear.
+Once installed, this file should be readable only by root.
+
+Add the following line to the @i[/etc/services] file on
+@i[ariadne], and on all machines that
+will run the @i[sample_client] program:
+@begin[example]
+sample     906/tcp       # Kerberos sample app server
+@end[example]
+
+Add a line similar to the following line to the @i[/etc/inetd.conf]
+file on @i[sample_server]'s machine:
+@begin[example]
+sample   stream   tcp   nowait   switched   root
+    [PATH]/sample_server sample_server
+@end[example]
+where [PATH] should be substituted with
+the path to the @i[sample_server] program.
+(This @i[inetd.conf] information should be placed on one line.)
+You should examine existing lines in @i[/etc/inetd.conf] and use the
+same format used by other entries (e.g. for telnet).  Most systems do
+not have a column for the `switched' keyword, and some do not have a
+column for the username (usually `root', as above).
+
+Restart @i[inetd] by sending the current @i[inetd] process
+a hangup signal:
+@begin[example]
+host# @b[kill  -HUP   @p(process_id_number)]
+@end[example]
+
+The @i[sample_server] is now ready to take @i[sample_client] requests.
+@end[enumerate]
+
+@section[Testing the Sample Server]
+
+Assume that you have installed @i[sample_server] on @i[ariadne].
+
+Login to your workstation and use the @i[kinit] command to
+obtain a Kerberos ticket-granting ticket:
+@begin[example]
+@tabset[3 inches]
+host% @b([K_USER]/kinit)
+MIT Project Athena, (your_workstation)
+Kerberos Initialization
+Kerberos name: @p[yourusername]@\@b[<--] @p[Enter your Kerberos username.]
+Password: @\@b[<--] @p[Enter your Kerberos password.]
+@end[example]
+
+Now use the @i[sample_client] program as follows:
+@begin[example]
+host% @b([PATH]/sample_client  ariadne)
+@end[example]
+The command should display something like the following:
+@begin[example]
+The server says:
+You are @p[yourusername].@@REALMNAME (local name @p[yourusername]),
+ at address @p[yournetaddress], version VERSION9, cksum 997
+@end[example]
+
+@chapter[Service names and other services]
+
+@section(rlogin, rsh, rcp, tftp, and others)
+
+Many services use a common principal name for authentication purposes.
+@i[rlogin], @i[rsh], @i[rcp], @i[tftp] and others use the principal name
+``@t[rcmd]''.  For example, to set up the machine @i[ariadne] to support
+Kerberos rlogin, it needs to have a service key for principal
+``@t[rcmd]'', instance ``@t[ariadne]''.  You create this key in the same
+way as shown above for the sample service.
+
+After creating this key, you need to run the @i[ext_srvtab] program
+again to generate a new srvtab file for ariadne.
+
+@section(NFS modifications)
+
+The NFS modifications distributed separately use the service name
+``@t[rvdsrv]'' with the instance set to the machine name (as for the
+sample server and the rlogin, rsh, rcp and tftp services).
+
+@section(inetd.conf entries)
+The following are the @i(/etc/inetd.conf) entries necessary to support
+rlogin, encrypted rlogin, rsh, and rcp services on a server machine.  As
+above, your @i(inetd.conf) may not support all the fields shown here.
+@begin[example]
+eklogin  stream   tcp   nowait   unswitched   root
+    [PATH]/klogind   eklogind
+kshell   stream   tcp   nowait   unswitched   root
+    [PATH]/kshd   kshd
+klogin   stream   tcp   nowait   unswitched   root
+    [PATH]/klogind   klogind
+@end[example]
diff --git a/krb5-1-6/doc/procedures.txt b/krb5-1-6/doc/procedures.txt
new file mode 100644
index 000000000..dcc21319a
--- /dev/null
+++ b/krb5-1-6/doc/procedures.txt
@@ -0,0 +1,159 @@
+		    MIT Kerberos Development Team
+			      Procedures
+
+This is a draft of current procedures used by the MIT Kerberos
+Development Team.  They will be refined at some later point.
+
+---Tom
+
+RELEASE BRANCH HYGIENE
+======================
+
+No changes should be committed to a release branch except by the
+release engineer or other approved person.  Changes to be included on
+the release branch must first be committed to the trunk, and must have
+an associated RT ticket.  This ticket should have its "target_version"
+keyword set to the release that the change is targeted at, and should
+have the "pullup" tag set.  This ticket should clearly document the
+changes that are to be pulled up to the release branch; the
+recommended way to do this is to ensure the the subversion  commit operations
+corresponding to the changes have automatically updated the ticket --
+see the following section.  The release engineer will pull up the
+change to the release branch and set the "version_fixed" keyword on
+the ticket.
+
+USING Subversion COMMITS TO CREATE/UPDATE RT TICKETS
+=============================================
+
+The following instructions were written for cvs but also work for Subversion.
+
+To: krbdev@mit.edu
+Subject: Important: handling commit interactions with bug database
+Message-Id: <20020917204852.4AEFE151FEF@industrial-algebra.mit.edu>
+Date: Tue, 17 Sep 2002 16:48:52 -0400 (EDT)
+From: hartmans@MIT.EDU (Sam Hartman)
+
+Hi.  I've just deployed the integration between the RT bug tracking
+system and our CVS repository.
+
+Per previous discussion, we're moving to a model where any non-trivial
+functionality change needs to be accompanied by a ticket open in the
+bug database.  This will allow us to generate better release notes.
+To accomplish this we have created a syntax for manipulating tickets
+along with commits.  If you are someone who has commit access but is
+not at MIT your commits MUST create or update a ticket.
+
+To manipulate tickets you add some header lines to the top of your log
+message.  The lines can be of the form header: value or rt-header:
+value.  I'll show them without the rt-prefix.
+
+Updating a ticket
+=================
+
+To update a ticket, you include a 
+ ticket: or rt-ticket: line  in your log.  For example:
+
+ticket: 1164
+
+Return errno not retval when getpeername fails.
+
+By default when you update a ticket:
+
+* the ticket is assigned to you
+* The ticket is closed
+
+If these defaults are not appropriate for your action you can override
+them; see below.
+
+Creating a ticket
+=================
+
+You can also create a ticket at the same time as you commit. All you
+have to do is use new instead of a ticket number in a ticket line.
+However you almost certainly want to at least set the  subject.
+
+ticket: new
+subject: Add AES support
+
+Add an implementation of AES to libk5crypto.
+
+In addition to closing the ticket and marking you as the owner of a
+ticket, creating a new ticket makes you the requester of the ticket.
+
+OTher Things to Change
+======================
+
+
+The following additional commands are supported:
+
+* subject: changes the subject of ticket
+* status: [open|resolved|new|stalled]
+* owner: [username|nobody]
+* cc: [email address]
+* Component: change component of ticket [krb5-libs etc]
+* Version_Reported: 
+* Target_Version:
+* Tags: [enhancement|nochange|noresource|pullup]
+
+You could set version_fixed, but it is wrong to do so.
+
+
+Also, note that you can update multiple tickets in one log message;
+updates apply to the most recent ticket: command.
+
+MEANINGS OF RT TAGS AND VERSIONS
+================================
+
+To: krbdev@mit.edu
+Subject: Meaning of RT tags and versions
+Message-Id: <20020821205804.5764E151FEF@industrial-algebra.mit.edu>
+Date: Wed, 21 Aug 2002 16:58:04 -0400 (EDT)
+From: hartmans@MIT.EDU (Sam Hartman)
+
+We're in the middle of migrating away from Gnats for bug tracking and
+to RT.  I sent out some mail describing the bug tracking process we
+were going to use at the beginning of the summer and wanted to follow
+up on that with definitions of fields in the  tickets.
+
+Tickets have three version numbers associated with them:
+version_reported, version_fixed, and target_version.  The
+version_reported should be filled in by the submitter if they are
+using the web interface or by the first person  to edit the bug with
+the web interface; it is the version of Kerberos the bug first
+appeared in.
+
+The version_fixed field is set during the release process; you should
+never change this field  unless you are a release engineer and even
+then you'll probably be using automated scripts.
+
+The target_version field is the version of the software we plan to fix
+a bug in.  It is generally updated after release planning meetings,
+although it is reasonable for people with commit access to update this
+if they believe a particular issues should be considered for the
+specified target version.  If we notice a lot of issues we don't have
+time to deal with, we will drop the target versions as the release
+approaches.
+
+There are several tags that can be set on a ticket as well.
+
+The first tag is the enhancement tag; this roughly corresponds to the
+Gnats classification as change-request, distinguished from sw-bug.
+
+
+The next tag is the nochange tag.  This indicates that the ticket has
+been (or will be) closed with no code change and thus should not be
+processed by the next round of release scripts.  This is appropriate
+for tickets where the requester is mistaken or where no bug/change
+exists.
+
+The final tag is the noresource tag; this indicates that MIT does not
+have resources to dedicate to the problem/feature.  We'll set this tag
+on tickets when we evaluate them in release planning discussions so
+that we do not have to continue thinking about then at each
+consecutive release.  In general, if we feel an issue is not a
+problem, we'll just close the ticket.  However if we agree that in an
+ideal world the issue would be fixed but don't ever expect to be able
+to fix it ourselves, we'll set the noresource tag and forget the issue
+unless someone replies to it with a patch or proposed solution.
+
+--Sam
diff --git a/krb5-1-6/doc/rpc/design.tex b/krb5-1-6/doc/rpc/design.tex
new file mode 100644
index 000000000..fbd60f914
--- /dev/null
+++ b/krb5-1-6/doc/rpc/design.tex
@@ -0,0 +1,1037 @@
+\documentstyle[fullpage,12pt]{article}
+
+\title{GSS-API Extensions to Sun RPC}
+\date{Draft---\today}
+\author{Barry Jaspan}
+
+\setlength{\parskip}{.7\baselineskip}
+\setlength{\parindent}{0pt}
+
+\makeatletter
+\newcount\savecnt\savecnt=0
+\def\saveenum#1{\global\savecnt=\csname c@enum#1\endcsname}
+\def\restoreenum#1{\csname c@enum#1\endcsname=\savecnt}
+\makeatother
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Make _ actually generate an _, and allow line-breaking after it.
+\let\underscore=\_
+\catcode`_=13
+\def_{\underscore\penalty75\relax}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\begin{document}
+
+
+{\setlength{\parskip}{0pt}\maketitle\tableofcontents}
+
+\section{Introduction}
+
+This document describes the integration of GSS-API authentication and
+security with Sun RPC.
+
+\section{Requirements}
+
+The requirements of the GSS-API authentication system for Sun RPC are:
+
+\begin{enumerate}
+\item It must provide mutual authentication between RPC clients and
+servers.
+
+\item It must provide for integrity checking and encryption of all
+procedure arguments and results passed over the network.
+\saveenum{i}
+\end{enumerate}
+
+The following features are desired, but not mandatory:
+
+\begin{enumerate}
+\restoreenum{i}
+\item It should provide for integrity checking and encryption of all
+``header information'' that specifies the program and procedure being
+called.
+
+\item It should obey the Sun RPC protocol so that clients using
+it can interoperate with existing servers.  In this case,
+``interoperate'' means that existing servers will return an error code
+indicating that they do not understand the authentication flavor, but
+not that they do not understand the request at all.
+
+\item It should require minimal or no changes to the standard Sun RPC
+programming paradigm for either clients or servers so that existing
+code can use it with little or no effort.
+
+\item It should operate correctly with all the standard Sun RPC
+transport mechansims (e.g. UDP and TCP).
+\saveenum{i}
+\end{enumerate}
+
+\section{Functional Specification}
+
+This section describes the programmer's interface to the GSS-API
+authentication flavor.   Knowledge of standard Sun RPC programming is
+assumed.
+
+\subsection{Client Side}
+
+A RPC client can select the GSS-API authentication flavor in the same
+way it can select any other authentication flavor, by setting the
+cl_auth field of the CLIENT structure to the appropriate value:
+
+\begin{verbatim}
+    clnt = clnt_create(server_host, PROG_NUM, PROG_VERS, protocol);
+    clnt->cl_auth = auth_gssapi_create(clnt, ...);
+\end{verbatim}
+
+There are two functions that create GSS-API authentication flavor
+structures for the cl_auth field, auth_gssapi_create and
+auth_gssapi_create_default.
+
+\begin{verbatim}
+AUTH *auth_gssapi_create(CLIENT         *clnt,
+                        OM_uint32       *major_status,
+                        OM_uint32       *minor_status,
+                        gss_cred_id_t   claimant_cred_handle,
+                        gss_name_t      target_name,
+                        gss_OID         mech_type,
+                        int             req_flags,
+                        int             time_req,
+                        gss_OID         *actual_mech_type,
+                        int             *ret_flags,
+                        OM_uint32       *time_rec);
+\end{verbatim}
+
+auth_gssapi_create creates a GSS-API authentication structure and
+provides most of the flexibility of gss_init_sec_context.  The
+arguments have the same interpretation as those of
+gss_init_sec_context with the same name, except:
+
+\begin{description}
+\item[clnt] The CLIENT structure returned by client_create or one of
+its relatives.  It is not modified.
+\end{description}
+
+auth_gssapi_create calls gss_init_sec_context as needed, passing each
+generated token to and processing each token returned from the RPC
+server specified by the RPC handle clnt.  On return, if major_status
+is GSS_S_COMPLETE, the context has been established, the returned AUTH
+structure is valid, and all of the arguments filled in by
+gss_init_sec_context have the correct values.  If major_status is not
+GSS_S_COMPLETE then it and minor_status contain error codes that can
+be passed to gss_display_status and the returned value is NULL.
+
+\begin{verbatim}
+AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name);
+\end{verbatim}
+
+auth_gssapi_create_default is a shorthand for auth_gssapi_create that
+attempts to create a context that provides procedure call and result
+integrity, using the default credentials and GSS-API mechanism.
+service_name is parsed as a GSS-API ``service'' name and used as the
+target name.  The other arguments to auth_gssapi_create are as follows:
+
+\begin{verbatim}
+auth_gssapi_create(clnt,
+                   &dummy,
+                   &dummy,
+                   GSS_C_NO_CREDENTIAL,
+                   target_name,
+                   GSS_C_NULL_OID,
+                   GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+                   0,
+                   NULL,
+                   NULL,
+                   NULL);
+\end{verbatim}
+
+Note that if the underlying default mechanism does not support data
+integrity (e.g. the trust mechanism), this function will fail.
+
+The GSS-API major and minor status codes can be interpreted with
+auth_gssapi_display_status:
+
+\begin{verbatim}
+void auth_gssapi_display_status(char *msg, OM_uint32 major, 
+                                OM_uint32 minor); 
+\end{verbatim}
+
+All of the error messages associated with the major and minor status
+are displated on the standard error output, preceeded by the message
+``GSS-API authentication error $<$msg$>$:''.
+
+\subsection{Server Side}
+
+\subsubsection{Service Name Registration}
+
+An application server must register the service name(s) that it will
+use for GSS-API connections before any AUTH_GSSAPI requests will
+succeed.
+
+\begin{verbatim}
+typedef struct _auth_gssapi_name {
+     char *name;
+     gss_OID type;
+} auth_gssapi_name;
+
+bool_t _svcauth_gssapi_set_names(auth_gssapi_name *names, int num);
+\end{verbatim}
+
+names is an array of name specifications, each of which consists of a
+null-terminated ASCII representation of a name and the GSS-API name
+type that should be used to import it with gss_import_name.  The
+name type ``gss_nt_service_name'' is recommended.
+
+\subsubsection{Calling Client and Service Identification}
+
+Each application server's dispatch function is passed two arguments,
+the transport mechanism (transp) and the RPC service request (rqstp).
+If the service request's credential flavor (rq_cred.oa_flavor) is
+AUTH_GSSAPI (300001)\footnote{The value 4 was originally used, but
+300001 has been officially assigned by the IETF.}, then the call has
+been authenticated.  The rq_clntcred field of transp contains the
+gss_name_t of the authenticated caller and can be passed to
+gss_display_name to obtain a string represtation or gss_compare_name
+to compare it with other names.  The rq_svccred field of transp
+contains the GSS-API context established with the caller and can be
+passed to gss_inquire_context.
+
+\subsubsection{Error Logging}
+
+An application server can register a function to be called when a
+failure occurs during GSS-API context establishment with
+_svcauth_set_log_badauth_func.
+
+\begin{verbatim}
+typedef void (*auth_gssapi_log_badauth_func)(OM_uint32 major,
+                                             OM_uint32 minor,
+                                             struct sockaddr_in *raddr,
+                                             caddr_t data);
+   
+void _svcauth_set_log_badauth_func(auth_gssapi_log_badauth_func func,
+                                   caddr_t data); 
+\end{verbatim}
+
+The function func is called each time gss_accept_sec_context fails.
+The major and minor arguments indicate the GSS-API major and minor
+status codes returned.  The raddr field contains the INET socket that
+the request came from, and the data field contains the data argument
+of _svcauth_gssapi_set_log_badauth_func.
+
+An application server can register a function to be called when an RPC
+request with an invalid verifier arrives with
+_svcauth_set_log_badverf_func.
+
+\begin{verbatim}
+typedef void (*auth_gssapi_log_badverf_func)(gss_name_t client,
+                                             gss_name_t server,
+                                             struct svc_req *rqst,
+                                             struct rpc_msg *msg,
+                                             caddr_t data);
+
+void _svcauth_set_log_badverf_func(auth_gssapi_log_badverf_func func,
+                                   caddr_t data); 
+\end{verbatim}
+
+The function specified in func is called each time an invalid verifier
+is received.  The client and server fields identify the (falsely
+claimed) originating client and the server it originally authenticated
+to.  The raddr and addrlen fields contain the INET socket that the
+request (claims to have) come from, and data contains the data
+argument of _svcauth_set_log_badverf_func.
+
+\section{Modifications to Sun RPC}
+
+The Sun RPC extensible authentication mechanism is designed to allow
+different authentication systems to be integrated into Sun RPC easily.
+Unfortunately, it has two drawbacks.  First, the existing system has a
+number of non-general design properties that are intended specifically
+for Sun's Secure RPC, and second, the existing system has no concept
+of or ability to perform authentication-flavor-specific operations on
+function arguments and results passed over the wire.  The first
+problem merely makes the system confusing, since a number of features
+touted as ``general'' do not make any sense for arbitrary
+authentication systems.  The second problem is more substantial, and
+can only be corrected by modifications to Sun RPC internals.
+
+The following sections describe the necessary modifications to Sun
+RPC.
+
+\subsection{Client Side Authentication, AUTH Structure}
+
+The AUTH structure (figure \ref{fig:auth}) encapsulates the data and
+function pointers for an authentication flavor instance.  It has been
+changed in two ways.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+typedef struct {
+        struct  opaque_auth     ah_cred;
+        struct  opaque_auth     ah_verf;
+        union   des_block       ah_key;
+        struct auth_ops {
+                void    (*ah_nextverf)();
+                int     (*ah_marshal)();        /* nextverf & serialize */
+                int     (*ah_validate)();       /* validate varifier */
+                int     (*ah_refresh)();        /* refresh credentials */
+                int     (*ah_wrap)();           /* encode data for wire */
+                int     (*ah_unwrap)();         /* decode data from wire */
+                void    (*ah_destroy)();        /* destroy this structure */
+        } *ah_ops;
+        caddr_t ah_private;
+} AUTH;
+\end{verbatim}
+\caption{The AUTH structure, with the new function pointers ah_wrap
+and ah_unwrap.}
+\label{fig:auth}
+\end{figure}
+
+First, the new functions ah_wrap and ah_unwrap prepare function
+arguments and results for transmission over the wire.  The
+authentication mechanism can use them to sign, encrypt, or perform any
+other operation on the data.  Their prototype is:
+
+\begin{verbatim}
+bool_t ah_wrap(AUTH *auth, XDR *out_xdrs, xdrproc_t func, caddr_t ptr);
+bool_t ah_unwrap(AUTH *auth, XDR *in_xdrs, xdrproc_t func, caddr_t ptr);
+\end{verbatim}
+
+ah_wrap encodes function arguments for transmission.  func and ptr are
+the XDR procedure and pointer that serialize the arguments, and
+out_xdrs is the xdr stream that the encoded arguments should be
+written to.  ah_unwrap decodes function arguments received from the
+network.  Its arguments are the converse of those to ah_wrap.
+
+It is the responsibility of RPC transport mechanisms to call an
+authorization flavor's ah_wrap and ah_unwrap functions when function
+arguments or results would normally be written to or read from the
+wire.  Authorization flavors that do not need to perform any encoding
+or decoding can use the provided function authany_wrap for ah_wrap
+and ah_unwrap; it consists of the single statement ``return
+(*func)(out_xdrs, ptr)'' (or in_xdrs, as appropriate).
+
+Second, the function ah_refresh has been changed to take the RPC error
+message that resulted in its being called as an argument.  This is
+necessary since the contents of the error message may dictate how
+ah_refresh should go about correcting the authentication failure.
+
+\subsection{Client Side Transport Mechanisms}
+
+Each client side transport mechanism must be modified to call the
+ah_wrap and ah_unwrap functions from the cl_auth field of the CLIENT
+structure during the call and reply process.  The modification is
+fairly simple.  For example, the UDP transport mechanism used to
+encode procedure calls like this:
+
+\begin{verbatim}
+        if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+            (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+            (! (*xargs)(xdrs, argsp)))
+                return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+\end{verbatim}
+
+The last function call in the conditional serializes the arguments
+onto the xdr stream.  This must be replaced with a call to the
+appropriate ah_wrap function:
+
+\begin{verbatim}
+        if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+            (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+            (! AUTH_WRAP(cl->cl_auth, xdrs, xargs, argsp)))
+                return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+\end{verbatim}
+
+AUTH_WRAP is a macro that takes the four arguments for an ah_wrap
+function and extracts and calls the function pointer from the cl_auth
+structure with the specified arguments.
+
+Similarly, the transport mechanism must unwrap procedure results.
+Again, the UDP mechanism will be instructive.  It used to deserialize
+function results like this:
+
+\begin{verbatim}
+        reply_msg.acpted_rply.ar_results.where = resultsp;
+        reply_msg.acpted_rply.ar_results.proc = xresults;
+
+        ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+\end{verbatim}
+
+The problem here is that xdr_replymsg deserializes an entire reply
+message, including the results.  Since xresults and resultsp are the
+function and pointer to decode the results, they will be automatically
+deserialized {\it without} ah_unwrap being invoked.  The simplest
+solution (which is also the normal method used by the TCP mechanism)
+is to arrange to deserialize the function results explicitly:
+
+\begin{verbatim}
+        reply_msg.acpted_rply.ar_results.where = NULL;
+        reply_msg.acpted_rply.ar_results.proc = xdr_void;
+
+        if ((! xdr_replymsg(&reply_xdrs, &reply_msg)) ||
+            (! AUTH_UNWRAP(cl->cl_auth, reply_xdrs, xresults,
+                           resultsp))) {
+                return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+        }
+\end{verbatim}
+
+Since xdr_void does not read any data from the XDR stream, the
+function results are still available when AUTH_UNWRAP is called.  Note
+that AUTH_UNWRAP should only be called on {\it successful} calls; if
+the reply message status is not RPC_SUCCESS there are no arguments to
+read.
+
+Currently, the UDP and TCP transport mechanisms has been
+converted.\footnote{The ``raw'' mechanism, for direct connections, has
+not been.}
+
+\subsection{Service Side Authentication, SVCAUTH and XPRT}
+
+Standard Sun RPC service-side authentication consists of a single
+function per authentication flavor; there is no concept of an AUTH
+structure containing function pointers and private data as with the
+client side.  Previously, nothing else was necessary, because each
+flavor only did a single thing (authenticated individual calls in a
+stateless manner).  More functions and state are now required,
+however; they are stored in the SVCAUTH structure, see figure
+\ref{fig:svcauth}.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+typedef struct {
+     struct svc_auth_ops {
+          int   (*svc_ah_wrap)();
+          int   (*svc_ah_unwrap)();
+     } *svc_ah_ops;
+     caddr_t svc_ah_private;
+} SVCAUTH;
+\end{verbatim}
+\caption{The new SVCAUTH structure.}
+\label{fig:svcauth}
+\end{figure}
+
+There is one SVCAUTH structure per authentication flavor (there is a
+default, svc_auth_any, for existing authentication flavors that do not
+need the extra functionality).  The svc_ah_wrap and svc_ah_unwrap
+perform the same logical function as their client-side counterparts.
+
+Just as with the client side, it is the responsibility of the
+transport mechanism to call the svc_ah_wrap and svc_ah_unwrap
+functions associated with the authentication flavor associated with
+each RPC call at the appropriate time.  Unfortunately, the transport
+mechanism code does not have access to the RPC call structure
+containing the authenticator flavor because the RPC call structure
+itself is not passed as an argument to the necessary functions.  The
+present solution is to add another argument to the transport mechanism
+structure, xp_auth, that stores the SVCAUTH of the {\it current} call
+on that mechanism; see figure \ref{fig:xprt}.  xp_auth is initialized
+to svc_auth_any so that existing authentication mechanisms that do not
+set the field will still operate correctly.  \footnote{This is not an
+great solution, because it forces each transport mechanism to be
+single threaded.  The correct solution is to store the SVCAUTH
+associated with each RPC call in the RPC call structure; however,
+doing so would require changing a lot of code to pass around the RPC
+call structure that currently does not do so.  Since other parts of
+Sun RPC use the XPRT structure in a non-reentrant way, the present
+solution does not make the situation any
+worse.}$^{\mbox{,}}$\footnote{A somewhat irrelevant side effect of
+adding SVCAUTH to XPRT is that the standard include file
+$<$rpc/rpc.h$>$ had to be changed to include $<$rpc/svc_auth$>$ before
+$<$rpc/svc.h$>$, whereas they used to be in the opposite order.}
+
+\begin{figure}[htbp]
+\begin{verbatim}
+typedef struct {
+        int             xp_sock;
+        u_short         xp_port;         /* associated port number */
+        struct xp_ops {
+            bool_t      (*xp_recv)();    /* receive incomming requests */
+            enum xprt_stat (*xp_stat)(); /* get transport status */
+            bool_t      (*xp_getargs)(); /* get arguments */
+            bool_t      (*xp_reply)();   /* send reply */
+            bool_t      (*xp_freeargs)();/* free mem allocated for args */
+            void        (*xp_destroy)(); /* destroy this struct */
+        } *xp_ops;
+        int             xp_addrlen;      /* length of remote address */
+        struct sockaddr_in xp_raddr;     /* remote address */
+        struct opaque_auth xp_verf;      /* raw response verifier */
+        SVCAUTH         *xp_auth;        /* auth flavor of current req */
+        caddr_t         xp_p1;           /* private */
+        caddr_t         xp_p2;           /* private */
+} SVCXPRT;
+\end{verbatim}
+\caption{The modified XPRT structure, with the xp_auth field.}
+\label{fig:xprt}
+\end{figure}
+
+Finally, with the modified XPRT structure carrying around the
+authentication flavor structure, the functions that serialize and
+deserialize function arguments and results must be modified to use the
+svc_ah_wrap and svc_ah_unwrap functions.  Each service-side transport
+mechanism has getargs and reply functions that must be modified to use
+the SVCAUTH_UNWRAP and SVCAUTH_WRAP macros, respectively, in a manner
+completely parallel to the client side.
+
+\subsection{Authenticated Service Identification, svc_req}
+
+Sun RPC provides the authenticated credentials of a client to the
+application server via rq_clntcred (``cooked credentials'') field of
+the service request (svc_req) structure.  In many authentication
+systems, services are also named entities, and there is no reason that
+an RPC should be restricted to accepting connections as a single
+authenticated service name.  However, access control decisions may be
+based on the service name a client authenticated to, so that
+information must be available to the application server.
+
+Figure \ref{fig:svc-req} shows the modified service request structure
+that contains a single new field, rq_svccred.  Like rq_clntcred, the
+authentication flavor is responsible for setting rq_svccred to the
+``cooked'' service credentials associated with a given RPC call.
+Authentication flavors that do not have the concept of service names
+can of course leave this field blank.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+struct svc_req {
+        u_long          rq_prog;        /* service program number */
+        u_long          rq_vers;        /* service protocol version */
+        u_long          rq_proc;        /* the desired procedure */
+        struct opaque_auth rq_cred;     /* raw creds from the wire */
+        caddr_t         rq_clntcred;    /* read only cooked client cred */
+        caddr_t         rq_svccred;     /* read only cooked svc cred */
+        SVCXPRT         *rq_xprt;       /* associated transport */
+};
+\end{verbatim}
+\caption{The modified svc_req structure, with the rq_svccred field.}
+\label{fig:svc-req}
+\end{figure}
+
+
+
+\subsection{Authentication Negotiation, no_dispatch}
+
+In order to avoid having to transmit a full set of authentication
+information with every call, the service-side authentication mechanism
+must save state between calls.  Establishing that state may require
+multiple messages between the client-side and service-side
+authentication mechanisms.  The client-side authentication mechanism
+can make arbitrary RPC calls to the server simply by requiring the
+programmer to specify the CLIENT structure to the authentication
+flavor initialization routine.  The service side, however, is more
+complex.  In the normal course of events, an RPC call comes in, is
+authenticated, and is then dispatched to the appropriate procedure.
+For client- and service-side authentication flavors to communicate
+indepedent of the server implemented above the RPC layer, the
+service-side flavor must be able to send a reply to the client
+directly and {\it prevent} the call from being dispatched.
+
+This is implemented by a simple modification to the _authenticate
+routine, which dispatches each RPC call to the appropriate
+authentication flavor; see figure \ref{fig:authenticate}.  It takes an
+additional argument, no_dispatch, that instructs the mechanism not to
+dispatch the RPC call to the specified procedure.
+
+\begin{figure}[htbp]
+\begin{verbatim}
+                why=_authenticate(&r, &msg, &no_dispatch);
+                if (why != AUTH_OK) {
+                     svcerr_auth(xprt, why);
+                     goto call_done;
+                } else if (no_dispatch) {
+                     goto call_done;
+                }
+\end{verbatim}
+\caption{A call to the modified _authenticate.}
+\label{fig:authenticate}
+\end{figure}
+
+If _authenticate sets no_dispatch to true, the call is considered
+finished and no procedure dispatch takes place.  Presumably, an
+authentication flavor that sets no_dispatch to true also replies to
+the RPC call with svc_sendreply.  Authentication flavors that do not
+modify no_dispatch implicitly leave it set to false, so the normal
+dispatch takes place.
+
+\subsection{Affected Files}
+
+Table \ref{tab:modfiles} lists the files that were
+affected for each of the modifications described in previous sections.
+
+\begin{table}[htbp]
+\centering
+\caption{Files modified for each change to Sun RPC.}
+\label{tab:modfiles}
+\begin{tabular}{ll}
+AUTH structure                  & auth.h \\
+                                & auth_none.c \\
+                                & auth_exit.c \\
+                                & auth_any.c \\
+Client Transport Mechanisms     & clnt_udp.c \\
+                                & clnt_tcp.c \\
+SVCAUTH and XPRT structures     & rpc.h \\
+                                & svc.h \\
+                                & svc_auth.h \\
+                                & svc.c \\
+                                & svc_auth.c \\
+                                & svc_auth_any.c \\
+                                & svc_auth_unix.c \\
+Server Transport Mechanisms     & svc_udp.c \\
+                                & svc_tcp.c
+\end{tabular}
+\end{table}
+
+\section{GSS-API Authentication Flavor}
+
+The following sections describe the implemetation of the GSS-API
+authentication flavor for Sun RPC.
+
+\subsection{Authentication Algorithms}
+\label{sec:algorithms}
+
+\subsubsection{Context Initiation}
+
+The client creates a GSS-API context with the server each time it
+calls auth_gssapi_create.  The context is created using the standard
+gss_init_sec_context and gss_accept_sec_context function calls.  The
+generated tokens are passed between the client and server as arguments
+and results of normal RPC calls.
+
+The client side, in auth_gssapi_create, performs the following steps
+to initiate a context:
+
+\begin{enumerate}
+\item\label{item:process-token} The client calls gss_init_sec_context.
+On the first such call, no input token is provided; on subsequent
+calls, the token received from the server is provided.
+
+\item If gss_init_sec_context produces an output token:
+
+\begin{enumerate}
+\item The client transmits the token to the server, identifying itself
+with client_handle if it has already been received (see next step).
+The return value from the server will contain a client_handle and one
+or both of a token and a signed initial sequence number.  
+
+\item If this is the first response from the server, the client_handle
+is stored for subsequent calls.  Otherwise, the client_handle should be
+the same as returned on the previous call.
+
+\item If the response contains a signed initian sequence number but
+the context is not yet established, then the response also contains a
+token that will established the context.  The signed initial sequence
+number is stored.
+
+\item If the response contains a token, step \ref{item:process-token}
+repeated.
+\end{enumerate}
+
+\item The signed initial sequence number is verified using the
+established context.
+\end{enumerate}
+
+The server side, in _svcauth_gssapi, performs the following steps to
+initiate a context:
+
+\begin{enumerate}
+\item If a call arrives with no client_handle, a new client_handle is
+allocated and stored in the database.  Otherwise, the client's
+previous state is is looked up in the database.
+
+\item The received token is passed to gss_accept_sec_context.  If an
+output token is generated, it is returned to the client.  Note that
+since the application server may have registered multiple service
+names and there is no way to determine {\it a priori} which service a
+token is for, _svcauth_gssapi calls gss_accept_sec_context once for
+each registered credential until one of them succeedes.  The code
+assumes that GSS_S_FAILURE is the only error that can result from a
+credential mismatch, so any other error terminates the loop
+immediately.
+
+\item If the context is established, the server signs an initial
+sequence number and returns it to the client.
+\end{enumerate}
+
+Note that these algorithms require context establishment to be
+synchronous.  If gss_init_sec_context returns GSS_S_COMPLETE upon
+processing a token, it will either produce a token or not.  If it
+does, then gss_accept_sec_context will return GSS_S_COMPLETE when that
+token is processed; if it does not, then gss_accept_sec_context
+already returned GSS_S_COMPLETE (and presumably returned the token
+that caused gss_init_sec_context to return GSS_S_COMPLETE when
+processed).  The reverse is also true.
+
+\subsubsection{RPC Calls}
+
+After the GSS-API context is established, both the server and the
+client posess a client handle and a corresponding sequence number.
+Each call from the client contains the client handle as the
+``credential'' so that the server can identify which context to apply
+to the call.
+
+Each client call and server response includes a ``verifier'' that
+contains the sealed current sequence number.\footnote{In a future
+version, the verifier will also contain a signature block for the call
+header, including the procedure number called.} The sequence number
+prevents replay attacks\footnote{Although some GSS-API mechanisms
+provide replay detection themselves, not all of them do; explicitly
+including the sequence number in the RPC therefore provides better
+end-to-end security}, but by itself it does not prevent splicing
+attacks.
+
+Each procedure argument and result block consists of the current
+sequence number and the actual serialized argument string, all sealed
+with gss_seal.  Combining the sequence number with the argument/result
+data prevents splicing attacks.
+
+The sequence number is incremented by one for each RPC call and by one
+for each response.  The client and server will both reject messages
+that do not contain the expected sequence number.  Packets
+retransmitted by the client should use the {\it same} sequence number
+as the original packet, since even if the server receives multiple
+copies only one will be honored.
+
+\subsection{RPC Call Credential Structure}
+
+Every message transmitted from the client to the server has a
+credentials (cb_cred) field of the type auth_gssapi_creds:
+
+\begin{verbatim}
+typedef struct _auth_gssapi_creds {
+        bool_t       auth_msg;
+        gss_buffer_desc client_handle;
+};
+\end{verbatim}
+
+The auth_msg field indicates whether the message is intended for the
+authentication mechanism for the actual server.  Any message whose
+auth_msg field is true is processed by the authentication mechanism;
+any message whose auth_msg is false is passed to the application
+server's dispatch function if authentication suceeds.  All messages
+must have an auth_msg of true until the context is established, since
+authentication cannot succeed until it is.
+
+The client_handle field contains the client handle obtained from the
+first call to the server.  On the first call, this field is empty.
+
+\subsection{GSS-API Authentication Flavor Procedures}
+
+The GSS-API authentication flavor uses standard RPC calls over the
+client handle it is provided for the interactions described in
+\ref{sec:algorithms}.  All of the following procedures require the
+auth_msg field in the credentials to be true; otherwise, the
+server-side authentication flavor will simply attempt to authenticate
+the caller and pass the call to the application server.  The
+server-side authentication flavor uses the no_dispatch variable to
+indicate that it has handled the call.
+
+\subsubsection{AUTH_GSSAPI_INIT, AUTH_GSSAPI_CONTINUE_INIT}
+
+Context initiation is performed via AUTH_GSSAPI_INIT and
+AUTH_GSSAPI_CONTINUE_INIT.  The former is used to transfer the first
+token generated by gss_init_sec_context, when no client handle is
+included in the credentials; the latter is used on subsequent calls,
+when a client handle is included.
+
+Both procedures take an argument of type auth_gssapi_init_arg and
+return results of the type auth_gssapi_init_res.
+
+\begin{verbatim}
+typedef struct _auth_gssapi_init_arg {
+        u_long       version;
+        gss_buffer_desc token;
+} auth_gssapi_init_arg;
+\end{verbatim}
+
+\begin{description}
+\item[version]  Three versions are presently defined.
+
+\begin{description}
+\item[1] The original version, as described in this document
+
+\item[2] In earlier versions of Secure there was a bug in the GSS-API
+library that affected the contents of accept_sec_context output
+tokens.  A client specifies version 2 to indicate that it expects the
+correct (fixed) behavior.  If the server indicates AUTH_BADCRED or
+AUTH_FAILED it does not understand this version, so the client should
+fall back to version 1.
+
+\item[3] Version three indicates that channel bindings are in use.
+The client must specify channel bindings with the version, and the
+server will as well.  If the server indicates AUTH_BADCRED or
+AUTH_FAILED it does not understand this version, so the client should
+fall back to version 2 (and cease specifying channel bindings).
+
+\item[4] The previous versions all used the old GSS-API krb5 mechanism
+oid; this version uses the new one specified in the RFC.  
+\end{description}
+
+\item[token] The token field contains the token generated by
+gss_init_sec_context.
+\end{description}
+
+\begin{verbatim}
+typedef struct _auth_gssapi_init_res {
+        u_long       version;
+        gss_buffer_desc client_handle;
+        gss_buffer_desc token;
+        OM_uint32 gss_major, gss_minor;
+        gss_buffer_desc signed_isn;
+} auth_gssapi_init_res;
+\end{verbatim}
+
+\begin{description}
+\item[version] There are two versions currently defined.
+\begin{description}
+\item[1] The original version, as described in this document.  This is
+the response version for {\it both} versions 1 and 2.  The Secure 1.1
+server will always return this version.
+
+\item[3] Version three indicates that the server specified channel
+bindings in response to a call arg version number of three.  The
+server must not specify this version unless the client does.
+\end{description}
+
+\item[client_handle] The client_handle field contains the client
+handle that the client must use in the credentials field in all
+subsequent RPC calls.  In response to AUTH_GSSAPI_CONTINUE_INIT, it is
+the same client handle that arrived in the credentials.
+
+\item[gss_major, gss_minor] The GSS-API error codes that resulted from
+processing the auth_gssapi_init_arg.  If gss_major is GSS_S_COMPLETE,
+the argument token was processed successfully.  Otherwise, gss_major
+and gss_minor contain the relevant major and minor status codes, and
+the context currently being negotiated is no longer valid.
+
+\item[token] In any response that the client is expecting another
+token (i.e.: gss_init_sec_context last returned GSS_S_CONTINUE), the
+token field contains the output token from gss_accept_sec_context.  If
+the client is not expecting a token and this field is not empty, an
+error has occurred.
+
+\item[signed_isn]  If the client is not expecting another token (i.e.:
+the previous call to gss_init_sec_context yielded a token and returned
+GSS_S_COMPLETE) or the supplied token completes the context, the
+signed_isn field contains the signed initial sequence number.  The
+server expects the first RPC call to have a sequence number one
+greater than the initial sequence number (so that the signed_isn block
+cannot be replayed).  If the client is expecting another token and the
+signed_isn field is not empty, an error has occurred.
+\end{description}
+
+\subsubsection{AUTH_GSSAPI_DESTROY}
+
+Context tear-down is performed via AUTH_GSSAPI_DESTROY.  This
+procedure takes no arguments and returns no results; it merely informs
+the server that the client wishes to destroy the established context.
+
+When a client wishes to tear down an established context between
+itself and a server, auth_gssapi_destroy first calls the
+AUTH_GSSAPI_DESTROY procedure.  The server authenticates the message
+and immediately sends a ``success'' response with no results.  The
+client and server then both independently call gss_delete_sec_context
+and discard the context-destruction token that is generated.
+
+No RPC error checking is performed by either the client or the server.
+The client waits a brief time for a success response from the server,
+but if none arrives it destroys the context anyway since presumably
+the user is waiting for the application to exit.  The server similar
+ignores any RPC errors since it knows that the client will ignore any
+errors that are reported.
+
+\subsection{RPC Call Authentication Implementation}
+
+Once the context has been established, all subsequent RPC calls are
+authenticated via the verifier described in section
+\ref{sec:algorithms}.
+
+auth_gssapi_marshall, invoked via AUTH_MARSHALL while the RPC call is
+being created on the client side, serializes the client_handle
+obtained during context initiation {\it in plaintext} as the
+credentials and serializes the current sequence number, sealed with
+gss_seal, as the verifier.
+
+auth_gssapi_wrap, invoked next via AUTH_WRAP, serializes a sealed
+token containing both the sequence number of the current call and the
+serialized arguments.
+
+_svcauth_gssapi, invoked on the server side by _authenticate, uses the
+client_handle contained in the credentials to look up the correct
+context and verifies the sequence number provided in the verifier; if
+the sequence number is not correct, it declares a potential replay
+attack.\footnote{Retransmitted packets will appear as replay attacks,
+of course.} The response verifier is set to the serialized sealed
+incremented sequence number.
+
+svc_auth_gssapi_unwrap, invoked when either the application server or
+_svcauth_gssapi (in response to an AUTH_GSSAPI authentication flavor
+message) attempts to read its arguments, deserialzes and unseals the
+block containing the current sequence number and serialized arguments.
+If the sequence number is incorrect, it declares a splicing attack;
+otherwise, it unserializes the arguments into the original structure.
+
+svc_auth_gssapi_wrap, invoked when either the application server or
+_svcauth_gssapi attempts to write its response, performs the same
+operation as auth_gssapi_wrap.
+
+auth_gssapi_validate, invoked by the client-side RPC mechanism when
+an RPC_SUCCESS response is received, verifies that the returned sequence
+number is one greater than the previous value sent by
+auth_gssapi_marshall.
+
+Finally, auth_gssapi_unwrap, invokved by the client-side RPC mechanism
+after auth_gssapi_validate succeeds, performs the same operation as
+svc_auth_gssapi_unwrap.
+
+If an RPC request generates an error message (a status of other than
+RPC_SUCCESS), auth_gssapi_refresh is called.  If the error status is
+AUTH_REJECTEDVERF, then the server rejected the sequence number as
+invalid or replayed.  The client guesses that, on some previous call,
+the server received a message but the server's response did not make
+it back to the client; this could happen if the packet got lost or if
+the server was being debugged and the client timed out waiting for it.
+As a result, the server is expected a higher sequence number than the
+client sent.  auth_gssapi_refresh increments the sequence number and
+returns true so that the call will be tried again.  The transport
+mechanism will only call auth_gssapi_refresh twice for each RPC
+request, so if some other error occurred an infinite loop will not
+result; however, it is unlikely the the client and server will be able
+to resynchronize after such an event.
+
+\subsection{Client State Information}
+
+The client-side GSS-API authentication flavor maintains an
+auth_gssapi_data structure for each authentication instance:
+
+\begin{verbatim}
+struct auth_gssapi_data {
+     bool_t established;
+     CLIENT *clnt;
+     gss_ctx_id_t context;
+     gss_buffer_desc client_handle;
+     u_long seq_num;
+     int def_cred;
+
+     /* pre-serialized ah_cred */
+     u_char cred_buf[MAX_AUTH_BYTES];
+     u_long cred_len;
+};
+\end{verbatim}
+
+The established field indicates whether the authentication context
+between the client and server has been established.  It is set to true
+when gss_init_sec_context returns GSS_S_COM\-PLETE.  When this field is
+false, the auth_gssapi functions marshall, validate, wrap, and unwrap
+mimic the ``no authentication'' flavor since there is no context with
+which to perform authentication functions.\footnote{This field is
+necessary because, when auth_gssapi_create calls clnt_call to make an
+RPC call, it has to have set the client's authentication flavor to
+AUTH_GSSAPI; otherwise, the service-side RPC mechanism will not know
+to dispatch the call to _svcauth_gssapi.  However, with the client's
+authentication flavor set, all of the authentication flavor's
+functions will be automatically invoked, even though they are not
+ready to operate.}
+
+The clnt field contains the RPC client structure that can be used to
+communicate with the GSS-API authentication flavor on the server.
+
+The context field contains the context structure created by
+gss_init_sec_context.
+
+The client_handle field contains the client handle used on all RPC
+calls except the first one; the handle is obtained as the result of
+the first call.
+
+The sequence_number field contains the sequence number that will be
+used when transmitting RPC calls to the server and verifing the
+server's responses after the context is initialized.
+
+The def_cred field is true if gss_init_sec_context created a default
+credential, in which case the authentication mechanism is responsible
+for releasing the default credential that gets automatically
+allocated.
+
+The cred_buf and cred_len fields contain the pre-serialized
+credentials structure used in each call.  This provides a small
+performance enhancement since the credentials structure does not
+change very often; the same pre-serialized version can be used on
+virtually every call.
+
+\subsection{Server State Information}
+\label{sec:server-state}
+
+The server-side GSS-API authentication flavor maintains an
+svcauth_gssapi_data structure for each established or partially
+established context:
+
+\begin{verbatim}
+typedef struct _svc_auth_gssapi_data {
+     bool_t established;
+     gss_ctx_id_t context;
+     gss_name_t client_name, server_name;
+     gss_cred_id_t server_creds;
+
+     u_long expiration;
+     u_long seq_num;
+     u_long key;
+
+     SVCAUTH svcauth;
+} svc_auth_gssapi_data;
+\end{verbatim}
+
+The established field indicates whether the context is fully
+established.
+
+The context field contains the context created by
+gss_accept_sec_context.
+
+The client_name field contains the client's authenticated name, as
+returned by gss_accept_sec_context.  _svcauth_gssapi sets the ``cooked
+credentials'' field of the RPC call structure to this value after the
+call is authenticated; the application server can use it to perform
+authorization.
+
+The server_name field contains the service name that the client
+established a context with.  This is useful if the application server
+registered more than one service name with the library; it allows the
+server to determine which service the client chose.
+
+The server_creds field contains the service credentials that the
+client established a context with.  It is used to avoid having to scan
+through the server_creds_list multiple times in the case that context
+establishment requires more than one round-trip to the server.
+
+The expiration field contains the expiration time of the context, as a
+Unix timestamp.  If a context has no expiration (time_rec is
+GSS_C_INDEFINITE), the expiration time is set to 24 hours in the
+future.  When the structure is created, before the context is
+established, the expiration time is initialized to small duration
+(currently 5 minutes) so that partially created and abandoned contexts
+will be expired quickly.
+
+The seq_num field is the current sequence number for the client.
+
+The key field is the client's key into the hash table (see below).
+The client_handle field sent to the client is the key treated as an
+arbitrary four-byte string.
+
+The svcauth field is a kludge that allows the svc_auth_gssapi
+functions to access the per-client data structure while processing a
+call.  One SVCAUTH structure is allocated for each client structure,
+and the svc_ah_private field is set to the corresponding client.  The
+client's svcauth field is then set to the new SVCAUTH structure, so
+that client_data->svcauth->svc_ah_private == client_data.  As each
+request is processed, the transport mechanism's xp_auth field is set
+to the client's svcauth field; thus, the server-side functions that
+dispatch to server-side authentication flavors can access an
+appropriate SVCAUTH structure, and the server-side authentication
+function that is called can determine the appropriate per-client
+structure from the SVCAUTH structure.
+
+The per-client structures are all stored both in a BSD 4.4 db library
+hash table and b-tree.  The hash table maps client handles (key
+fields) the client structures, and is used to look up client
+structures based on the client_handle field of a call's credentials
+structure.  The b-tree stores the client structures as keys, sorted by
+their expiration time.  Each time _svcauth_gssapi is activated, it
+traverses the tree and destroys all client structures that have
+expired.
+
+\end{document}
diff --git a/krb5-1-6/doc/salts.texinfo b/krb5-1-6/doc/salts.texinfo
new file mode 100644
index 000000000..3ed43db0e
--- /dev/null
+++ b/krb5-1-6/doc/salts.texinfo
@@ -0,0 +1,19 @@
+@ignore 
+the information in this file should be consistent with the information
+in krb5/src/lib/krb5/krb/str_conv.c, in the struct salttype_lookup_entry
+@end ignore
+
+@table @code
+@item normal
+default for Kerberos Version 5
+@item v4
+the only type used by Kerberos Version 4, no salt
+@item norealm
+same as the default, without using realm information
+@item onlyrealm
+uses only realm information as the salt
+@item afs3
+AFS version 3, only used for compatibility with Kerberos 4 in AFS
+@item special
+only used in very special cases; not fully supported
+@end table
diff --git a/krb5-1-6/doc/send-pr.texinfo b/krb5-1-6/doc/send-pr.texinfo
new file mode 100644
index 000000000..e34ca935e
--- /dev/null
+++ b/krb5-1-6/doc/send-pr.texinfo
@@ -0,0 +1,144 @@
+In any complex software, there will be bugs.  If you have successfully
+built and installed @value{PRODUCT}, please use the @code{krb5-send-pr}
+program to fill out a Problem Report should you encounter any errors in
+our software.
+
+Bug reports that include proposed fixes are especially welcome.  If you
+do include fixes, please send them using either context diffs or unified
+diffs (using @samp{diff -c} or @samp{diff -u}, respectively).  Please be
+careful when using ``cut and paste'' or other such means to copy a patch
+into a bug report; depending on the system being used, that can result
+in converting TAB characters into spaces, which makes applying the
+patches more difficult.
+
+The @code{krb5-send-pr} program is installed in the directory
+@code{@value{ROOTDIR}/sbin}.
+
+The @code{krb5-send-pr} program enters the problem report into our
+Problem Report Management System (PRMS), which automatically assigns it
+to the engineer best able to help you with problems in the assigned
+category.
+@ifset CYGNUS
+The engineer will work with you via email, telephone, or both, and all
+email related to this Problem Report will be tracked by PRMS for future
+reference.  If you need to talk to someone else in our organization
+about the problem (@i{e.g.}, if the engineer gets hit by a truck), we
+can find out what the current state is through the PR number.
+@end ifset
+
+The @code{krb5-send-pr} program will try to intelligently fill in as
+many fields as it can.  You need to choose the @dfn{category},
+@dfn{class}, @dfn{severity}, and @dfn{priority} of the problem, as well
+as giving us as much information as you can about its exact nature.
+
+@need 1000
+The PR @b{category} will be one of:
+
+@smallexample
+@group
+krb5-admin   krb5-appl    krb5-build   krb5-clients 
+krb5-doc     krb5-kdc     krb5-libs    krb5-misc    
+pty          telnet       test         
+@end group
+@end smallexample
+
+@noindent
+Choose the category that best describes the area under which your
+problem falls.
+
+The @b{class} can be @dfn{sw-bug}, @dfn{doc-bug}, @dfn{change-request},
+or @dfn{support}.  The first two are exactly as their names imply.  Use
+@i{change-request} when the software is behaving according to
+specifications, but you want to request changes in some feature or
+behavior.  The @i{support} class is intended for more general questions
+about building or using @value{PRODUCT}.
+
+The @b{severity} of the problem indicates the problem's impact on the
+usability of @value{PRODUCT}.  If a problem is @dfn{critical}, that
+means the product, component or concept is completely non-operational,
+or some essential functionality is missing, and no workaround is known.
+A @dfn{serious} problem is one in which the product, component or
+concept is not working properly or significant functionality is missing.
+Problems that would otherwise be considered @i{critical} are rated
+@i{serious} when a workaround is known.  A @dfn{non-critical} problem is
+one that is indeed a problem, but one that is having a minimal effect on
+your ability to use @value{PRODUCT}.  @i{E.g.}, The product, component
+or concept is working in general, but lacks features, has irritating
+behavior, does something wrong, or doesn't match its documentation.  The
+default severity is @i{serious}.
+
+The @b{priority} indicates how urgent this particular problem is in
+relation to your work.  Note that low priority does not imply low
+importance.
+@ifset CYGNUS
+@value{COMPANY} considers all problems important, and
+encourages its customers to be realistic about priority ratings.
+@end ifset
+A priority of @dfn{high} means a solution is needed as soon as possible.
+A priority of @dfn{medium} means the problem should be solved no later
+than the next release.  A priority of @dfn{low} means the problem should
+be solved in a future release, but it is not important to your work how
+soon this happens.  The default priority is @i{medium}.
+
+Note that a given severity does not necessarily imply a given priority.
+For example, a non-critical problem might still have a high priority if
+you are faced with a hard deadline.  Conversely, a serious problem might
+have a low priority if the feature it is disabling is one that you do
+not need.
+
+It is important that you fill in the @i{release} field and tell us
+what changes you have made, if any.
+
+@iftex
+@vfill
+@end iftex
+
+@page
+A sample filled-out form from a company named ``Toasters, Inc.'' might
+look like this:
+
+@smallexample
+@group
+To: krb5-bugs@@mit.edu
+Subject: misspelled "Kerberos" in title of installation guide
+From: jcb
+Reply-To: jcb
+Cc: 
+X-send-pr-version: 3.99
+
+
+>Submitter-Id:	mit
+>Originator:	Jeffrey C. Gilman Bigler
+>Organization:
+mit
+>Confidential:	no
+>Synopsis:	Misspelled "Kerberos" in title of installation guide
+>Severity:	non-critical
+>Priority:	low
+>Category:	krb5-doc
+>Class:		doc-bug
+>Release:	1.0-development
+>Environment:
+	<machine, os, target, libraries (multiple lines)>
+System: ULTRIX imbrium 4.2 0 RISC
+Machine: mips
+>Description:
+        Misspelled "Kerberos" in title of "Kerboros V5 Installation Guide"
+>How-To-Repeat:
+        N/A
+>Fix:
+        Correct the spelling.
+@end group        
+@end smallexample
+
+@iftex
+@vfill
+@end iftex
+
+If the @code{krb5-send-pr} program does not work for you, or if you did
+not get far enough in the process to have an installed and working
+@code{krb5-send-pr}, you can generate your own form, using the above as
+an example.
+
+
+
diff --git a/krb5-1-6/doc/support-enc.texinfo b/krb5-1-6/doc/support-enc.texinfo
new file mode 100644
index 000000000..ca4e8faab
--- /dev/null
+++ b/krb5-1-6/doc/support-enc.texinfo
@@ -0,0 +1,33 @@
+@ignore 
+the information in this file should be consistent with the information
+in krb5/src/lib/crypto/etypes.c (and krb5/src/include/krb5.h[in]?)
+@end ignore
+
+@table @code
+@item des-cbc-crc 
+DES cbc mode with CRC-32
+@item des-cbc-md4 
+DES cbc mode with RSA-MD4
+@item des-cbc-md5 
+DES cbc mode with RSA-MD5
+@item des3-cbc-sha1 
+@itemx des3-hmac-sha1
+@itemx des3-cbc-sha1-kd
+triple DES cbc mode with HMAC/sha1
+@item des-hmac-sha1 
+DES with HMAC/sha1
+@item aes256-cts-hmac-sha1-96
+@itemx aes256-cts
+AES-256 CTS mode with 96-bit SHA-1 HMAC
+@item aes128-cts-hmac-sha1-96
+@itemx aes128-cts
+AES-128 CTS mode with 96-bit SHA-1 HMAC
+@item arcfour-hmac 
+@itemx rc4-hmac
+@itemx arcfour-hmac-md5
+RC4 with HMAC/MD5
+@item arcfour-hmac-exp 
+@itemx rc4-hmac-exp
+@itemx arcfour-hmac-md5-exp
+exportable RC4 with HMAC/MD5
+@end table
diff --git a/krb5-1-6/doc/texinfo-suppl.tex b/krb5-1-6/doc/texinfo-suppl.tex
new file mode 100644
index 000000000..4a1c0cdac
--- /dev/null
+++ b/krb5-1-6/doc/texinfo-suppl.tex
@@ -0,0 +1,7 @@
+\def\temp{
+\chapternofonts
+\def\doubleleftarrow{\realbackslash doubleleftarrow}
+}
+\let\chapternofonts=\temp
+
+\def\doubleleftarrow{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Leftarrow$\hfil}}
diff --git a/krb5-1-6/doc/texinfo.tex b/krb5-1-6/doc/texinfo.tex
new file mode 100644
index 000000000..dddd0140f
--- /dev/null
+++ b/krb5-1-6/doc/texinfo.tex
@@ -0,0 +1,7226 @@
+% texinfo.tex -- TeX macros to handle Texinfo files.
+%
+% Load plain if necessary, i.e., if running under initex.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+%
+\def\texinfoversion{2006-02-13.16}
+%
+% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free
+% Software Foundation, Inc.
+%
+% This texinfo.tex file is free software; you can redistribute it and/or
+% modify it under the terms of the GNU General Public License as
+% published by the Free Software Foundation; either version 2, or (at
+% your option) any later version.
+%
+% This texinfo.tex file is distributed in the hope that it will be
+% useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+% General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this texinfo.tex file; see the file COPYING.  If not, write
+% to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+% Boston, MA 02110-1301, USA.
+%
+% As a special exception, when this file is read by TeX when processing
+% a Texinfo source document, you may use the result without
+% restriction.  (This has been our intent since Texinfo was invented.)
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+%   http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
+%   ftp://tug.org/tex/texinfo.tex
+%     (and all CTAN mirrors, see http://www.ctan.org).
+% The texinfo.tex in any given distribution could well be out
+% of date, so if that's what you're using, please check.
+%
+% Send bug reports to bug-texinfo@gnu.org.  Please include including a
+% complete document in each bug report with which we can reproduce the
+% problem.  Patches are, of course, greatly appreciated.
+%
+% To process a Texinfo manual with TeX, it's most reliable to use the
+% texi2dvi shell script that comes with the distribution.  For a simple
+% manual foo.texi, however, you can get away with this:
+%   tex foo.texi
+%   texindex foo.??
+%   tex foo.texi
+%   tex foo.texi
+%   dvips foo.dvi -o  # or whatever; this makes foo.ps.
+% The extra TeX runs get the cross-reference information correct.
+% Sometimes one run after texindex suffices, and sometimes you need more
+% than two; texi2dvi does it as many times as necessary.
+%
+% It is possible to adapt texinfo.tex for other languages, to some
+% extent.  You can get the existing language-specific files from the
+% full Texinfo distribution.
+%
+% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+
+
+\message{Loading texinfo [version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}%
+  \catcode`+=\active \catcode`\_=\active}
+
+\message{Basics,}
+\chardef\other=12
+
+% We never want plain's \outer definition of \+ in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+% Save some plain tex macros whose names we will redefine.
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv=\equiv
+\let\ptexexclam=\!
+\let\ptexfootnote=\footnote
+\let\ptexgtr=>
+\let\ptexhat=^
+\let\ptexi=\i
+\let\ptexindent=\indent
+\let\ptexinsert=\insert
+\let\ptexlbrace=\{
+\let\ptexless=<
+\let\ptexnewwrite\newwrite
+\let\ptexnoindent=\noindent
+\let\ptexplus=+
+\let\ptexrbrace=\}
+\let\ptexslash=\/
+\let\ptexstar=\*
+\let\ptext=\t
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+  \let\linenumber = \empty % Pre-3.0.
+\else
+  \def\linenumber{l.\the\inputlineno:\space}
+\fi
+
+% Set up fixed words for English if not already set.
+\ifx\putwordAppendix\undefined  \gdef\putwordAppendix{Appendix}\fi
+\ifx\putwordChapter\undefined   \gdef\putwordChapter{Chapter}\fi
+\ifx\putwordfile\undefined      \gdef\putwordfile{file}\fi
+\ifx\putwordin\undefined        \gdef\putwordin{in}\fi
+\ifx\putwordIndexIsEmpty\undefined     \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
+\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
+\ifx\putwordInfo\undefined      \gdef\putwordInfo{Info}\fi
+\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
+\ifx\putwordMethodon\undefined  \gdef\putwordMethodon{Method on}\fi
+\ifx\putwordNoTitle\undefined   \gdef\putwordNoTitle{No Title}\fi
+\ifx\putwordof\undefined        \gdef\putwordof{of}\fi
+\ifx\putwordon\undefined        \gdef\putwordon{on}\fi
+\ifx\putwordpage\undefined      \gdef\putwordpage{page}\fi
+\ifx\putwordsection\undefined   \gdef\putwordsection{section}\fi
+\ifx\putwordSection\undefined   \gdef\putwordSection{Section}\fi
+\ifx\putwordsee\undefined       \gdef\putwordsee{see}\fi
+\ifx\putwordSee\undefined       \gdef\putwordSee{See}\fi
+\ifx\putwordShortTOC\undefined  \gdef\putwordShortTOC{Short Contents}\fi
+\ifx\putwordTOC\undefined       \gdef\putwordTOC{Table of Contents}\fi
+%
+\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
+\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
+\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
+\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
+\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
+\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
+\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
+\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
+\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
+\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
+\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
+\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
+%
+\ifx\putwordDefmac\undefined    \gdef\putwordDefmac{Macro}\fi
+\ifx\putwordDefspec\undefined   \gdef\putwordDefspec{Special Form}\fi
+\ifx\putwordDefvar\undefined    \gdef\putwordDefvar{Variable}\fi
+\ifx\putwordDefopt\undefined    \gdef\putwordDefopt{User Option}\fi
+\ifx\putwordDeffunc\undefined   \gdef\putwordDeffunc{Function}\fi
+
+% Since the category of space is not known, we have to be careful.
+\chardef\spacecat = 10
+\def\spaceisspace{\catcode`\ =\spacecat}
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+% The following is used inside several \edef's.
+\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname}
+
+% Hyphenation fixes.
+\hyphenation{
+  Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script
+  ap-pen-dix bit-map bit-maps
+  data-base data-bases eshell fall-ing half-way long-est man-u-script
+  man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm
+  par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces
+  spell-ing spell-ings
+  stand-alone strong-est time-stamp time-stamps which-ever white-space
+  wide-spread wrap-around
+}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen\bindingoffset
+\newdimen\normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+% @| inserts a changebar to the left of the current line.  It should
+% surround any changed text.  This approach does *not* work if the
+% change spans more than two lines of output.  To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+  % \vadjust can only be used in horizontal mode.
+  \leavevmode
+  %
+  % Append this vertical mode material after the current line in the output.
+  \vadjust{%
+    % We want to insert a rule with the height and depth of the current
+    % leading; that is exactly what \strutbox is supposed to record.
+    \vskip-\baselineskip
+    %
+    % \vadjust-items are inserted at the left edge of the type.  So
+    % the \llap here moves out into the left-hand margin.
+    \llap{%
+      %
+      % For a thicker or thinner bar, change the `1pt'.
+      \vrule height\baselineskip width1pt
+      %
+      % This is the space between the bar and the text.
+      \hskip 12pt
+    }%
+  }%
+}
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal.  We don't just call \tracingall here,
+% since that produces some useless output on the terminal.  We also make
+% some effort to order the tracing commands to reduce output in the log
+% file; cf. trace.sty in LaTeX.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{%
+  \tracingstats2
+  \tracingpages1
+  \tracinglostchars2  % 2 gives us more in etex
+  \tracingparagraphs1
+  \tracingoutput1
+  \tracingmacros2
+  \tracingrestores1
+  \showboxbreadth\maxdimen \showboxdepth\maxdimen
+  \ifx\eTeXversion\undefined\else % etex gives us more logging
+    \tracingscantokens1
+    \tracingifs1
+    \tracinggroups1
+    \tracingnesting2
+    \tracingassigns1
+  \fi
+  \tracingcommands3  % 3 gives us more in etex
+  \errorcontextlines16
+}%
+
+% add check for \lastpenalty to plain's definitions.  If the last thing
+% we did was a \nobreak, we don't want to insert more space.
+%
+\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
+  \removelastskip\penalty-50\smallskip\fi\fi}
+\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
+  \removelastskip\penalty-100\medskip\fi\fi}
+\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
+  \removelastskip\penalty-200\bigskip\fi\fi}
+
+% For @cropmarks command.
+% Do @cropmarks to get crop marks.
+%
+\newif\ifcropmarks
+\let\cropmarks = \cropmarkstrue
+%
+% Dimensions to add cropmarks at corners.
+% Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
+\newdimen\cornerlong  \cornerlong=1pc
+\newdimen\cornerthick \cornerthick=.3pt
+\newdimen\topandbottommargin \topandbottommargin=.75in
+
+% Main output routine.
+\chardef\PAGE = 255
+\output = {\onepageout{\pagecontents\PAGE}}
+
+\newbox\headlinebox
+\newbox\footlinebox
+
+% \onepageout takes a vbox as an argument.  Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\def\onepageout#1{%
+  \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+  %
+  \ifodd\pageno  \advance\hoffset by \bindingoffset
+  \else \advance\hoffset by -\bindingoffset\fi
+  %
+  % Do this outside of the \shipout so @code etc. will be expanded in
+  % the headline as they should be, not taken literally (outputting ''code).
+  \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+  \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+  %
+  {%
+    % Have to do this stuff outside the \shipout because we want it to
+    % take effect in \write's, yet the group defined by the \vbox ends
+    % before the \shipout runs.
+    %
+    \indexdummies         % don't expand commands in the output.
+    \normalturnoffactive  % \ in index entries must not stay \, e.g., if
+               % the page break happens to be in the middle of an example.
+               % We don't want .vr (or whatever) entries like this:
+               % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}}
+               % "\acronym" won't work when it's read back in;
+               % it needs to be 
+               % {\code {{\tt \backslashcurfont }acronym}
+    \shipout\vbox{%
+      % Do this early so pdf references go to the beginning of the page.
+      \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
+      %
+      \ifcropmarks \vbox to \outervsize\bgroup
+        \hsize = \outerhsize
+        \vskip-\topandbottommargin
+        \vtop to0pt{%
+          \line{\ewtop\hfil\ewtop}%
+          \nointerlineskip
+          \line{%
+            \vbox{\moveleft\cornerthick\nstop}%
+            \hfill
+            \vbox{\moveright\cornerthick\nstop}%
+          }%
+          \vss}%
+        \vskip\topandbottommargin
+        \line\bgroup
+          \hfil % center the page within the outer (page) hsize.
+          \ifodd\pageno\hskip\bindingoffset\fi
+          \vbox\bgroup
+      \fi
+      %
+      \unvbox\headlinebox
+      \pagebody{#1}%
+      \ifdim\ht\footlinebox > 0pt
+        % Only leave this space if the footline is nonempty.
+        % (We lessened \vsize for it in \oddfootingxxx.)
+        % The \baselineskip=24pt in plain's \makefootline has no effect.
+        \vskip 2\baselineskip
+        \unvbox\footlinebox
+      \fi
+      %
+      \ifcropmarks
+          \egroup % end of \vbox\bgroup
+        \hfil\egroup % end of (centering) \line\bgroup
+        \vskip\topandbottommargin plus1fill minus1fill
+        \boxmaxdepth = \cornerthick
+        \vbox to0pt{\vss
+          \line{%
+            \vbox{\moveleft\cornerthick\nsbot}%
+            \hfill
+            \vbox{\moveright\cornerthick\nsbot}%
+          }%
+          \nointerlineskip
+          \line{\ewbot\hfil\ewbot}%
+        }%
+      \egroup % \vbox from first cropmarks clause
+      \fi
+    }% end of \shipout\vbox
+  }% end of group with \indexdummies
+  \advancepageno
+  \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+  \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+% Here are the rules for the cropmarks.  Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.  The argument is the rest of
+% the input line (except we remove a trailing comment).  #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg{\parseargusing{}}
+\def\parseargusing#1#2{%
+  \def\next{#2}%
+  \begingroup
+    \obeylines
+    \spaceisspace
+    #1%
+    \parseargline\empty% Insert the \empty token, see \finishparsearg below.
+}
+
+{\obeylines %
+  \gdef\parseargline#1^^M{%
+    \endgroup % End of the group started in \parsearg.
+    \argremovecomment #1\comment\ArgTerm%
+  }%
+}
+
+% First remove any @comment, then any @c comment.
+\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
+\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
+
+% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space.
+%
+% \argremovec might leave us with trailing space, e.g.,
+%    @end itemize  @c foo
+% This space token undergoes the same procedure and is eventually removed
+% by \finishparsearg.
+%
+\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M}
+\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M}
+\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{%
+  \def\temp{#3}%
+  \ifx\temp\empty
+    % We cannot use \next here, as it holds the macro to run;
+    % thus we reuse \temp.
+    \let\temp\finishparsearg
+  \else
+    \let\temp\argcheckspaces
+  \fi
+  % Put the space token in:
+  \temp#1 #3\ArgTerm
+}
+
+% If a _delimited_ argument is enclosed in braces, they get stripped; so
+% to get _exactly_ the rest of the line, we had to prevent such situation.
+% We prepended an \empty token at the very beginning and we expand it now,
+% just before passing the control to \next.
+% (Similarily, we have to think about #3 of \argcheckspacesY above: it is
+% either the null string, or it ends with \^^M---thus there is no danger
+% that a pair of braces would be stripped.
+%
+% But first, we have to remove the trailing space token.
+%
+\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}}
+
+% \parseargdef\foo{...}
+%	is roughly equivalent to
+% \def\foo{\parsearg\Xfoo}
+% \def\Xfoo#1{...}
+%
+% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
+% favourite TeX trick.  --kasal, 16nov03
+
+\def\parseargdef#1{%
+  \expandafter \doparseargdef \csname\string#1\endcsname #1%
+}
+\def\doparseargdef#1#2{%
+  \def#2{\parsearg#1}%
+  \def#1##1%
+}
+
+% Several utility definitions with active space:
+{
+  \obeyspaces
+  \gdef\obeyedspace{ }
+
+  % Make each space character in the input produce a normal interword
+  % space in the output.  Don't allow a line break at this space, as this
+  % is used only in environments like @example, where each line of input
+  % should produce a line of output anyway.
+  %
+  \gdef\sepspaces{\obeyspaces\let =\tie}
+
+  % If an index command is used in an @example environment, any spaces
+  % therein should become regular spaces in the raw index file, not the
+  % expansion of \tie (\leavevmode \penalty \@M \ ).
+  \gdef\unsepspaces{\let =\space}
+}
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+% Define the framework for environments in texinfo.tex.  It's used like this:
+%
+%   \envdef\foo{...}
+%   \def\Efoo{...}
+%
+% It's the responsibility of \envdef to insert \begingroup before the
+% actual body; @end closes the group after calling \Efoo.  \envdef also
+% defines \thisenv, so the current environment is known; @end checks
+% whether the environment name matches.  The \checkenv macro can also be
+% used to check whether the current environment is the one expected.
+%
+% Non-false conditionals (@iftex, @ifset) don't fit into this, so they
+% are not treated as enviroments; they don't open a group.  (The
+% implementation of @end takes care not to call \endgroup in this
+% special case.)
+
+
+% At runtime, environments start with this:
+\def\startenvironment#1{\begingroup\def\thisenv{#1}}
+% initialize
+\let\thisenv\empty
+
+% ... but they get defined via ``\envdef\foo{...}'':
+\long\def\envdef#1#2{\def#1{\startenvironment#1#2}}
+\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}}
+
+% Check whether we're in the right environment:
+\def\checkenv#1{%
+  \def\temp{#1}%
+  \ifx\thisenv\temp
+  \else
+    \badenverr
+  \fi
+}
+
+% Evironment mismatch, #1 expected:
+\def\badenverr{%
+  \errhelp = \EMsimple
+  \errmessage{This command can appear only \inenvironment\temp,
+    not \inenvironment\thisenv}%
+}
+\def\inenvironment#1{%
+  \ifx#1\empty
+    out of any environment%
+  \else
+    in environment \expandafter\string#1%
+  \fi
+}
+
+% @end foo executes the definition of \Efoo.
+% But first, it executes a specialized version of \checkenv
+%
+\parseargdef\end{%
+  \if 1\csname iscond.#1\endcsname
+  \else
+    % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
+    \expandafter\checkenv\csname#1\endcsname
+    \csname E#1\endcsname
+    \endgroup
+  \fi
+}
+
+\newhelp\EMsimple{Press RETURN to continue.}
+
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt\char64}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt\char123}}
+\def\myrbrace {{\tt\char125}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+  % Definitions to produce \{ and \} commands for indices,
+  % and @{ and @} for the aux/toc files.
+  \catcode`\{ = \other \catcode`\} = \other
+  \catcode`\[ = 1 \catcode`\] = 2
+  \catcode`\! = 0 \catcode`\\ = \other
+  !gdef!lbracecmd[\{]%
+  !gdef!rbracecmd[\}]%
+  !gdef!lbraceatcmd[@{]%
+  !gdef!rbraceatcmd[@}]%
+!endgroup
+
+% @comma{} to avoid , parsing problems.
+\let\comma = ,
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown @ordf @ordm
+% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
+\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+  \def\temp{#1}%
+  \ifx\temp\imacro \ptexi
+  \else\ifx\temp\jmacro \j
+  \else \errmessage{@dotless can be used only with i or j}%
+  \fi\fi
+}
+
+% The \TeX{} logo, as in plain, but resetting the spacing so that a
+% period following counts as ending a sentence.  (Idea found in latex.)
+%
+\edef\TeX{\TeX \spacefactor=1000 }
+
+% @LaTeX{} logo.  Not quite the same results as the definition in
+% latex.ltx, since we use a different font for the raised A; it's most
+% convenient for us to use an explicitly smaller font, rather than using
+% the \scriptstyle font (since we don't reset \scriptstyle and
+% \scriptscriptstyle).
+%
+\def\LaTeX{%
+  L\kern-.36em
+  {\setbox0=\hbox{T}%
+   \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
+  \kern-.15em
+  \TeX
+}
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @/ allows a line break.
+\let\/=\allowbreak
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=\endofsentencespacefactor\space}
+
+% @! is an end-of-sentence bang.
+\def\!{!\spacefactor=\endofsentencespacefactor\space}
+
+% @? is an end-of-sentence query.
+\def\?{?\spacefactor=\endofsentencespacefactor\space}
+
+% @frenchspacing on|off  says whether to put extra space after punctuation.
+% 
+\def\onword{on}
+\def\offword{off}
+%
+\parseargdef\frenchspacing{%
+  \def\temp{#1}%
+  \ifx\temp\onword \plainfrenchspacing
+  \else\ifx\temp\offword \plainnonfrenchspacing
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @frenchspacing option `\temp', must be on/off}%
+  \fi\fi
+}
+
+% @w prevents a word break.  Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox.  We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line.  According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0).  If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+% Another complication is that the group might be very large.  This can
+% cause the glue on the previous page to be unduly stretched, because it
+% does not have much material.  In this case, it's better to add an
+% explicit \vfill so that the extra space is at the bottom.  The
+% threshold for doing this is if the group is more than \vfilllimit
+% percent of a page (\vfilllimit can be changed inside of @tex).
+%
+\newbox\groupbox
+\def\vfilllimit{0.7}
+%
+\envdef\group{%
+  \ifnum\catcode`\^^M=\active \else
+    \errhelp = \groupinvalidhelp
+    \errmessage{@group invalid in context where filling is enabled}%
+  \fi
+  \startsavinginserts
+  %
+  \setbox\groupbox = \vtop\bgroup
+    % Do @comment since we are called inside an environment such as
+    % @example, where each end-of-line in the input causes an
+    % end-of-line in the output.  We don't want the end-of-line after
+    % the `@group' to put extra space in the output.  Since @group
+    % should appear on a line by itself (according to the Texinfo
+    % manual), we don't worry about eating any user text.
+    \comment
+}
+%
+% The \vtop produces a box with normal height and large depth; thus, TeX puts
+% \baselineskip glue before it, and (when the next line of text is done)
+% \lineskip glue after it.  Thus, space below is not quite equal to space
+% above.  But it's pretty close.
+\def\Egroup{%
+    % To get correct interline space between the last line of the group
+    % and the first line afterwards, we have to propagate \prevdepth.
+    \endgraf % Not \par, as it may have been set to \lisppar.
+    \global\dimen1 = \prevdepth
+  \egroup           % End the \vtop.
+  % \dimen0 is the vertical size of the group's box.
+  \dimen0 = \ht\groupbox  \advance\dimen0 by \dp\groupbox
+  % \dimen2 is how much space is left on the page (more or less).
+  \dimen2 = \pageheight   \advance\dimen2 by -\pagetotal
+  % if the group doesn't fit on the current page, and it's a big big
+  % group, force a page break.
+  \ifdim \dimen0 > \dimen2
+    \ifdim \pagetotal < \vfilllimit\pageheight
+      \page
+    \fi
+  \fi
+  \box\groupbox
+  \prevdepth = \dimen1
+  \checkinserts
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil  \mil=0.001in
+
+% Old definition--didn't work.
+%\parseargdef\need{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+%\prevdepth=-1000pt
+%}}
+
+\parseargdef\need{%
+  % Ensure vertical mode, so we don't make a big box in the middle of a
+  % paragraph.
+  \par
+  %
+  % If the @need value is less than one line space, it's useless.
+  \dimen0 = #1\mil
+  \dimen2 = \ht\strutbox
+  \advance\dimen2 by \dp\strutbox
+  \ifdim\dimen0 > \dimen2
+    %
+    % Do a \strut just to make the height of this box be normal, so the
+    % normal leading is inserted relative to the preceding line.
+    % And a page break here is fine.
+    \vtop to #1\mil{\strut\vfil}%
+    %
+    % TeX does not even consider page breaks if a penalty added to the
+    % main vertical list is 10000 or more.  But in order to see if the
+    % empty box we just added fits on the page, we must make it consider
+    % page breaks.  On the other hand, we don't want to actually break the
+    % page after the empty box.  So we use a penalty of 9999.
+    %
+    % There is an extremely small chance that TeX will actually break the
+    % page at this \penalty, if there are no other feasible breakpoints in
+    % sight.  (If the user is using lots of big @group commands, which
+    % almost-but-not-quite fill up a page, TeX will have a hard time doing
+    % good page breaking, for example.)  However, I could not construct an
+    % example where a page broke at this \penalty; if it happens in a real
+    % document, then we can reconsider our strategy.
+    \penalty9999
+    %
+    % Back up by the size of the box, whether we did a page break or not.
+    \kern -#1\mil
+    %
+    % Do not allow a page break right after this kern.
+    \nobreak
+  \fi
+}
+
+% @br   forces paragraph break (and is undocumented).
+
+\let\br = \par
+
+% @page forces the start of a new page.
+%
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
+
+% This defn is used inside nofill environments such as @example.
+\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
+  \leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
+% paragraph.  For more general purposes, use the \margin insertion
+% class.  WHICH is `l' or `r'.
+%
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+%
+\def\doinmargin#1#2{\strut\vadjust{%
+  \nobreak
+  \kern-\strutdepth
+  \vtop to \strutdepth{%
+    \baselineskip=\strutdepth
+    \vss
+    % if you have multiple lines of stuff to put here, you'll need to
+    % make the vbox yourself of the appropriate size.
+    \ifx#1l%
+      \llap{\ignorespaces #2\hskip\inmarginspacing}%
+    \else
+      \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
+    \fi
+    \null
+  }%
+}}
+\def\inleftmargin{\doinmargin l}
+\def\inrightmargin{\doinmargin r}
+%
+% @inmargin{TEXT [, RIGHT-TEXT]}
+% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
+% else use TEXT for both).
+%
+\def\inmargin#1{\parseinmargin #1,,\finish}
+\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
+  \setbox0 = \hbox{\ignorespaces #2}%
+  \ifdim\wd0 > 0pt
+    \def\lefttext{#1}%  have both texts
+    \def\righttext{#2}%
+  \else
+    \def\lefttext{#1}%  have only one text
+    \def\righttext{#1}%
+  \fi
+  %
+  \ifodd\pageno
+    \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
+  \else
+    \def\temp{\inleftmargin\lefttext}%
+  \fi
+  \temp
+}
+
+% @include file    insert text of that file as input.
+%
+\def\include{\parseargusing\filenamecatcodes\includezzz}
+\def\includezzz#1{%
+  \pushthisfilestack
+  \def\thisfile{#1}%
+  {%
+    \makevalueexpandable
+    \def\temp{\input #1 }%
+    \expandafter
+  }\temp
+  \popthisfilestack
+}
+\def\filenamecatcodes{%
+  \catcode`\\=\other
+  \catcode`~=\other
+  \catcode`^=\other
+  \catcode`_=\other
+  \catcode`|=\other
+  \catcode`<=\other
+  \catcode`>=\other
+  \catcode`+=\other
+  \catcode`-=\other
+}
+
+\def\pushthisfilestack{%
+  \expandafter\pushthisfilestackX\popthisfilestack\StackTerm
+}
+\def\pushthisfilestackX{%
+  \expandafter\pushthisfilestackY\thisfile\StackTerm
+}
+\def\pushthisfilestackY #1\StackTerm #2\StackTerm {%
+  \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}%
+}
+
+\def\popthisfilestack{\errthisfilestackempty}
+\def\errthisfilestackempty{\errmessage{Internal error:
+  the stack of filenames is empty.}}
+
+\def\thisfile{}
+
+% @center line
+% outputs that line, centered.
+%
+\parseargdef\center{%
+  \ifhmode
+    \let\next\centerH
+  \else
+    \let\next\centerV
+  \fi
+  \next{\hfil \ignorespaces#1\unskip \hfil}%
+}
+\def\centerH#1{%
+  {%
+    \hfil\break
+    \advance\hsize by -\leftskip
+    \advance\hsize by -\rightskip
+    \line{#1}%
+    \break
+  }%
+}
+\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
+
+% @sp n   outputs n lines of vertical space
+
+\parseargdef\sp{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore  is another way to write a comment
+
+\def\comment{\begingroup \catcode`\^^M=\other%
+\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
+\commentxxx}
+{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
+
+\let\c=\comment
+
+% @paragraphindent NCHARS
+% We'll use ems for NCHARS, close enough.
+% NCHARS can also be the word `asis' or `none'.
+% We cannot feasibly implement @paragraphindent asis, though.
+%
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\parseargdef\paragraphindent{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \defaultparindent = 0pt
+    \else
+      \defaultparindent = #1em
+    \fi
+  \fi
+  \parindent = \defaultparindent
+}
+
+% @exampleindent NCHARS
+% We'll use ems for NCHARS like @paragraphindent.
+% It seems @exampleindent asis isn't necessary, but
+% I preserve it to make it similar to @paragraphindent.
+\parseargdef\exampleindent{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \lispnarrowing = 0pt
+    \else
+      \lispnarrowing = #1em
+    \fi
+  \fi
+}
+
+% @firstparagraphindent WORD
+% If WORD is `none', then suppress indentation of the first paragraph
+% after a section heading.  If WORD is `insert', then do indent at such
+% paragraphs.
+%
+% The paragraph indentation is suppressed or not by calling
+% \suppressfirstparagraphindent, which the sectioning commands do.
+% We switch the definition of this back and forth according to WORD.
+% By default, we suppress indentation.
+%
+\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
+\def\insertword{insert}
+%
+\parseargdef\firstparagraphindent{%
+  \def\temp{#1}%
+  \ifx\temp\noneword
+    \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
+  \else\ifx\temp\insertword
+    \let\suppressfirstparagraphindent = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @firstparagraphindent option `\temp'}%
+  \fi\fi
+}
+
+% Here is how we actually suppress indentation.  Redefine \everypar to
+% \kern backwards by \parindent, and then reset itself to empty.
+%
+% We also make \indent itself not actually do anything until the next
+% paragraph.
+%
+\gdef\dosuppressfirstparagraphindent{%
+  \gdef\indent{%
+    \restorefirstparagraphindent
+    \indent
+  }%
+  \gdef\noindent{%
+    \restorefirstparagraphindent
+    \noindent
+  }%
+  \global\everypar = {%
+    \kern -\parindent
+    \restorefirstparagraphindent
+  }%
+}
+
+\gdef\restorefirstparagraphindent{%
+  \global \let \indent = \ptexindent
+  \global \let \noindent = \ptexnoindent
+  \global \everypar = {}%
+}
+
+
+% @asis just yields its argument.  Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math outputs its argument in math mode.
+%
+% One complication: _ usually means subscripts, but it could also mean
+% an actual _ character, as in @math{@var{some_variable} + 1}.  So make
+% _ active, and distinguish by seeing if the current family is \slfam,
+% which is what @var uses.
+{
+  \catcode`\_ = \active
+  \gdef\mathunderscore{%
+    \catcode`\_=\active
+    \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
+  }
+}
+% Another complication: we want \\ (and @\) to output a \ character.
+% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
+% this is not advertised and we don't care.  Texinfo does not
+% otherwise define @\.
+%
+% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
+\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
+%
+\def\math{%
+  \tex
+  \mathunderscore
+  \let\\ = \mathbackslash
+  \mathactive
+  $\finishmath
+}
+\def\finishmath#1{#1$\endgroup}  % Close the group opened by \tex.
+
+% Some active characters (such as <) are spaced differently in math.
+% We have to reset their definitions in case the @math was an argument
+% to a command which sets the catcodes (such as @item or @section).
+%
+{
+  \catcode`^ = \active
+  \catcode`< = \active
+  \catcode`> = \active
+  \catcode`+ = \active
+  \gdef\mathactive{%
+    \let^ = \ptexhat
+    \let< = \ptexless
+    \let> = \ptexgtr
+    \let+ = \ptexplus
+  }
+}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+% @dots{} outputs an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in a typewriter
+% font as three actual period characters.
+%
+\def\dots{%
+  \leavevmode
+  \hbox to 1.5em{%
+    \hskip 0pt plus 0.25fil
+    .\hfil.\hfil.%
+    \hskip 0pt plus 0.5fil
+  }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+  \dots
+  \spacefactor=\endofsentencespacefactor
+}
+
+% @comma{} is so commas can be inserted into text without messing up
+% Texinfo's parsing.
+%
+\let\comma = ,
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% If working on a large document in chapters, it is convenient to
+% be able to disable indexing, cross-referencing, and contents, for test runs.
+% This is done with @novalidate (before @setfilename).
+%
+\newif\iflinks \linkstrue % by default we want the aux files.
+\let\novalidate = \linksfalse
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
+   \iflinks
+     \tryauxfile
+     % Open the new aux file.  TeX will close it automatically at exit.
+     \immediate\openout\auxfile=\jobname.aux
+   \fi % \openindices needs to do some work in any case.
+   \openindices
+   \let\setfilename=\comment % Ignore extra @setfilename cmds.
+   %
+   % If texinfo.cnf is present on the system, read it.
+   % Useful for site-wide @afourpaper, etc.
+   \openin 1 texinfo.cnf
+   \ifeof 1 \else \input texinfo.cnf \fi
+   \closein 1
+   %
+   \comment % Ignore the actual filename.
+}
+
+% Called from \setfilename.
+%
+\def\openindices{%
+  \newindex{cp}%
+  \newcodeindex{fn}%
+  \newcodeindex{vr}%
+  \newcodeindex{tp}%
+  \newcodeindex{ky}%
+  \newcodeindex{pg}%
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+
+\message{pdf,}
+% adobe `portable' document format
+\newcount\tempnum
+\newcount\lnkcount
+\newtoks\filename
+\newcount\filenamelength
+\newcount\pgn
+\newtoks\toksA
+\newtoks\toksB
+\newtoks\toksC
+\newtoks\toksD
+\newbox\boxA
+\newcount\countA
+\newif\ifpdf
+\newif\ifpdfmakepagedest
+
+% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1
+% can be set).  So we test for \relax and 0 as well as \undefined,
+% borrowed from ifpdf.sty.
+\ifx\pdfoutput\undefined
+\else
+  \ifx\pdfoutput\relax
+  \else
+    \ifcase\pdfoutput
+    \else
+      \pdftrue
+    \fi
+  \fi
+\fi
+
+% PDF uses PostScript string constants for the names of xref targets,
+% for display in the outlines, and in other places.  Thus, we have to
+% double any backslashes.  Otherwise, a name like "\node" will be
+% interpreted as a newline (\n), followed by o, d, e.  Not good.
+% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html
+% (and related messages, the final outcome is that it is up to the TeX
+% user to double the backslashes and otherwise make the string valid, so
+% that's what we do).
+
+% double active backslashes.
+% 
+{\catcode`\@=0 \catcode`\\=\active
+ @gdef@activebackslashdouble{%
+   @catcode`@\=@active
+   @let\=@doublebackslash}
+}
+
+% To handle parens, we must adopt a different approach, since parens are
+% not active characters.  hyperref.dtx (which has the same problem as
+% us) handles it with this amazing macro to replace tokens.  I've
+% tinkered with it a little for texinfo, but it's definitely from there.
+% 
+% #1 is the tokens to replace.
+% #2 is the replacement.
+% #3 is the control sequence with the string.
+% 
+\def\HyPsdSubst#1#2#3{%
+  \def\HyPsdReplace##1#1##2\END{%
+    ##1%
+    \ifx\\##2\\%
+    \else
+      #2%
+      \HyReturnAfterFi{%
+        \HyPsdReplace##2\END
+      }%
+    \fi
+  }%
+  \xdef#3{\expandafter\HyPsdReplace#3#1\END}%
+}
+\long\def\HyReturnAfterFi#1\fi{\fi#1}
+
+% #1 is a control sequence in which to do the replacements.
+\def\backslashparens#1{%
+  \xdef#1{#1}% redefine it as its expansion; the definition is simply
+             % \lastnode when called from \setref -> \pdfmkdest.
+  \HyPsdSubst{(}{\realbackslash(}{#1}%
+  \HyPsdSubst{)}{\realbackslash)}{#1}%
+}
+
+\ifpdf
+  \input pdfcolor
+  \pdfcatalog{/PageMode /UseOutlines}%
+  \def\dopdfimage#1#2#3{%
+    \def\imagewidth{#2}%
+    \def\imageheight{#3}%
+    % without \immediate, pdftex seg faults when the same image is
+    % included twice.  (Version 3.14159-pre-1.0-unofficial-20010704.)
+    \ifnum\pdftexversion < 14
+      \immediate\pdfimage
+    \else
+      \immediate\pdfximage
+    \fi
+      \ifx\empty\imagewidth\else width \imagewidth \fi
+      \ifx\empty\imageheight\else height \imageheight \fi
+      \ifnum\pdftexversion<13
+         #1.pdf%
+       \else
+         {#1.pdf}%
+       \fi
+    \ifnum\pdftexversion < 14 \else
+      \pdfrefximage \pdflastximage
+    \fi}
+  \def\pdfmkdest#1{{%
+    % We have to set dummies so commands such as @code, and characters
+    % such as \, aren't expanded when present in a section title.
+    \atdummies
+    \activebackslashdouble
+    \def\pdfdestname{#1}%
+    \backslashparens\pdfdestname
+    \pdfdest name{\pdfdestname} xyz%
+  }}%
+  %
+  % used to mark target names; must be expandable.
+  \def\pdfmkpgn#1{#1}%
+  %
+  \let\linkcolor = \Blue  % was Cyan, but that seems light?
+  \def\endlink{\Black\pdfendlink}
+  % Adding outlines to PDF; macros for calculating structure of outlines
+  % come from Petr Olsak
+  \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
+    \else \csname#1\endcsname \fi}
+  \def\advancenumber#1{\tempnum=\expnumber{#1}\relax
+    \advance\tempnum by 1
+    \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+  %
+  % #1 is the section text, which is what will be displayed in the
+  % outline by the pdf viewer.  #2 is the pdf expression for the number
+  % of subentries (or empty, for subsubsections).  #3 is the node text,
+  % which might be empty if this toc entry had no corresponding node.
+  % #4 is the page number
+  %
+  \def\dopdfoutline#1#2#3#4{%
+    % Generate a link to the node text if that exists; else, use the
+    % page number.  We could generate a destination for the section
+    % text in the case where a section has no node, but it doesn't
+    % seem worth the trouble, since most documents are normally structured.
+    \def\pdfoutlinedest{#3}%
+    \ifx\pdfoutlinedest\empty
+      \def\pdfoutlinedest{#4}%
+    \else
+      % Doubled backslashes in the name.
+      {\activebackslashdouble \xdef\pdfoutlinedest{#3}%
+       \backslashparens\pdfoutlinedest}%
+    \fi
+    %
+    % Also double the backslashes in the display string.
+    {\activebackslashdouble \xdef\pdfoutlinetext{#1}%
+     \backslashparens\pdfoutlinetext}%
+    %
+    \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}%
+  }
+  %
+  \def\pdfmakeoutlines{%
+    \begingroup
+      % Thanh's hack / proper braces in bookmarks
+      \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
+      \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
+      %
+      % Read toc silently, to get counts of subentries for \pdfoutline.
+      \def\numchapentry##1##2##3##4{%
+	\def\thischapnum{##2}%
+	\def\thissecnum{0}%
+	\def\thissubsecnum{0}%
+      }%
+      \def\numsecentry##1##2##3##4{%
+	\advancenumber{chap\thischapnum}%
+	\def\thissecnum{##2}%
+	\def\thissubsecnum{0}%
+      }%
+      \def\numsubsecentry##1##2##3##4{%
+	\advancenumber{sec\thissecnum}%
+	\def\thissubsecnum{##2}%
+      }%
+      \def\numsubsubsecentry##1##2##3##4{%
+	\advancenumber{subsec\thissubsecnum}%
+      }%
+      \def\thischapnum{0}%
+      \def\thissecnum{0}%
+      \def\thissubsecnum{0}%
+      %
+      % use \def rather than \let here because we redefine \chapentry et
+      % al. a second time, below.
+      \def\appentry{\numchapentry}%
+      \def\appsecentry{\numsecentry}%
+      \def\appsubsecentry{\numsubsecentry}%
+      \def\appsubsubsecentry{\numsubsubsecentry}%
+      \def\unnchapentry{\numchapentry}%
+      \def\unnsecentry{\numsecentry}%
+      \def\unnsubsecentry{\numsubsecentry}%
+      \def\unnsubsubsecentry{\numsubsubsecentry}%
+      \readdatafile{toc}%
+      %
+      % Read toc second time, this time actually producing the outlines.
+      % The `-' means take the \expnumber as the absolute number of
+      % subentries, which we calculated on our first read of the .toc above.
+      %
+      % We use the node names as the destinations.
+      \def\numchapentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
+      \def\numsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
+      \def\numsubsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}%
+      \def\numsubsubsecentry##1##2##3##4{% count is always zero
+        \dopdfoutline{##1}{}{##3}{##4}}%
+      %
+      % PDF outlines are displayed using system fonts, instead of
+      % document fonts.  Therefore we cannot use special characters,
+      % since the encoding is unknown.  For example, the eogonek from
+      % Latin 2 (0xea) gets translated to a | character.  Info from
+      % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100.
+      %
+      % xx to do this right, we have to translate 8-bit characters to
+      % their "best" equivalent, based on the @documentencoding.  Right
+      % now, I guess we'll just let the pdf reader have its way.
+      \indexnofonts
+      \setupdatafile
+      \catcode`\\=\active \otherbackslash
+      \input \jobname.toc
+    \endgroup
+  }
+  %
+  \def\skipspaces#1{\def\PP{#1}\def\D{|}%
+    \ifx\PP\D\let\nextsp\relax
+    \else\let\nextsp\skipspaces
+      \ifx\p\space\else\addtokens{\filename}{\PP}%
+        \advance\filenamelength by 1
+      \fi
+    \fi
+    \nextsp}
+  \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+  \ifnum\pdftexversion < 14
+    \let \startlink \pdfannotlink
+  \else
+    \let \startlink \pdfstartlink
+  \fi
+  % make a live url in pdf output.
+  \def\pdfurl#1{%
+    \begingroup
+      % it seems we really need yet another set of dummies; have not
+      % tried to figure out what each command should do in the context
+      % of @url.  for now, just make @/ a no-op, that's the only one
+      % people have actually reported a problem with.
+      % 
+      \normalturnoffactive
+      \def\@{@}%
+      \let\/=\empty
+      \makevalueexpandable
+      \leavevmode\Red
+      \startlink attr{/Border [0 0 0]}%
+        user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+    \endgroup}
+  \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
+  \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+  \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
+  \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
+  \def\maketoks{%
+    \expandafter\poptoks\the\toksA|ENDTOKS|\relax
+    \ifx\first0\adn0
+    \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
+    \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
+    \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
+    \else
+      \ifnum0=\countA\else\makelink\fi
+      \ifx\first.\let\next=\done\else
+        \let\next=\maketoks
+        \addtokens{\toksB}{\the\toksD}
+        \ifx\first,\addtokens{\toksB}{\space}\fi
+      \fi
+    \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+    \next}
+  \def\makelink{\addtokens{\toksB}%
+    {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
+  \def\pdflink#1{%
+    \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
+    \linkcolor #1\endlink}
+  \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\else
+  \let\pdfmkdest = \gobble
+  \let\pdfurl = \gobble
+  \let\endlink = \relax
+  \let\linkcolor = \relax
+  \let\pdfmakeoutlines = \relax
+\fi  % \ifx\pdfoutput
+
+
+\message{fonts,}
+
+% Change the current font style to #1, remembering it in \curfontstyle.
+% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in
+% italics, not bold italics.
+%
+\def\setfontstyle#1{%
+  \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd.
+  \csname ten#1\endcsname  % change the current font
+}
+
+% Select #1 fonts with the current style.
+%
+\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname}
+
+\def\rm{\fam=0 \setfontstyle{rm}}
+\def\it{\fam=\itfam \setfontstyle{it}}
+\def\sl{\fam=\slfam \setfontstyle{sl}}
+\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf}
+\def\tt{\fam=\ttfam \setfontstyle{tt}}
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf.
+\newfam\sffam
+\def\sf{\fam=\sffam \setfontstyle{sf}}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this font style.
+\def\ttsl{\setfontstyle{ttsl}}
+
+% Default leading.
+\newdimen\textleading  \textleading = 13.2pt
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly.  There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+  \normalbaselineskip = #1\relax
+  \normallineskip = \lineskipfactor\normalbaselineskip
+  \normalbaselines
+  \setbox\strutbox =\hbox{%
+    \vrule width0pt height\strutheightpercent\baselineskip
+                    depth \strutdepthpercent \baselineskip
+  }%
+}
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx}               %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+% Text fonts (11.2pt, magstep1).
+\def\textnominalsize{11pt}
+\edef\mainmagstep{\magstephalf}
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun names and args.
+\setfont\defbf\bfshape{10}{\magstep1}
+\setfont\deftt\ttshape{10}{\magstep1}
+\setfont\defttsl\ttslshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\def\smallnominalsize{9pt}
+\setfont\smallrm\rmshape{9}{1000}
+\setfont\smalltt\ttshape{9}{1000}
+\setfont\smallbf\bfshape{10}{900}
+\setfont\smallit\itshape{9}{1000}
+\setfont\smallsl\slshape{9}{1000}
+\setfont\smallsf\sfshape{9}{1000}
+\setfont\smallsc\scshape{10}{900}
+\setfont\smallttsl\ttslshape{10}{900}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+
+% Fonts for small examples (8pt).
+\def\smallernominalsize{8pt}
+\setfont\smallerrm\rmshape{8}{1000}
+\setfont\smallertt\ttshape{8}{1000}
+\setfont\smallerbf\bfshape{10}{800}
+\setfont\smallerit\itshape{8}{1000}
+\setfont\smallersl\slshape{8}{1000}
+\setfont\smallersf\sfshape{8}{1000}
+\setfont\smallersc\scshape{10}{800}
+\setfont\smallerttsl\ttslshape{10}{800}
+\font\smalleri=cmmi8
+\font\smallersy=cmsy8
+
+% Fonts for title page (20.4pt):
+\def\titlenominalsize{20pt}
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\setfont\titleit\itbshape{10}{\magstep4}
+\setfont\titlesl\slbshape{10}{\magstep4}
+\setfont\titlett\ttbshape{12}{\magstep3}
+\setfont\titlettsl\ttslshape{10}{\magstep4}
+\setfont\titlesf\sfbshape{17}{\magstep1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+\def\authortt{\sectt}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\def\chapnominalsize{17pt}
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{17}{1000}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\def\secnominalsize{14pt}
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% Subsection fonts (13.15pt).
+\def\ssecnominalsize{13pt}
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{1315}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{1315}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+
+% Reduced fonts for @acro in text (10pt).
+\def\reducednominalsize{10pt}
+\setfont\reducedrm\rmshape{10}{1000}
+\setfont\reducedtt\ttshape{10}{1000}
+\setfont\reducedbf\bfshape{10}{1000}
+\setfont\reducedit\itshape{10}{1000}
+\setfont\reducedsl\slshape{10}{1000}
+\setfont\reducedsf\sfshape{10}{1000}
+\setfont\reducedsc\scshape{10}{1000}
+\setfont\reducedttsl\ttslshape{10}{1000}
+\font\reducedi=cmmi10
+\font\reducedsy=cmsy10
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families.  Since
+% texinfo doesn't allow for producing subscripts and superscripts except
+% in the main text, we don't bother to reset \scriptfont and
+% \scriptscriptfont (which would also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+  \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy
+  \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf
+  \textfont\ttfam=\tentt \textfont\sffam=\tensf
+}
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE.  We do this because \STYLE needs to also set the
+% current \fam for math mode.  Our \STYLE (e.g., \rm) commands hardwire
+% \tenSTYLE to set the current font.
+%
+% Each font-changing command also sets the names \lsize (one size lower)
+% and \lllsize (three sizes lower).  These relative commands are used in
+% the LaTeX logo and acronyms.
+%
+% This all needs generalizing, badly.
+%
+\def\textfonts{%
+  \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+  \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+  \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+  \let\tenttsl=\textttsl
+  \def\curfontsize{text}%
+  \def\lsize{reduced}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{\textleading}}
+\def\titlefonts{%
+  \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+  \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+  \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+  \let\tenttsl=\titlettsl
+  \def\curfontsize{title}%
+  \def\lsize{chap}\def\lllsize{subsec}%
+  \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #1}}
+\def\chapfonts{%
+  \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+  \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+  \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+  \let\tenttsl=\chapttsl
+  \def\curfontsize{chap}%
+  \def\lsize{sec}\def\lllsize{text}%
+  \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+  \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+  \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+  \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+  \let\tenttsl=\secttsl
+  \def\curfontsize{sec}%
+  \def\lsize{subsec}\def\lllsize{reduced}%
+  \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+  \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+  \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+  \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+  \let\tenttsl=\ssecttsl
+  \def\curfontsize{ssec}%
+  \def\lsize{text}\def\lllsize{small}%
+  \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts
+\def\reducedfonts{%
+  \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl
+  \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc
+  \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy
+  \let\tenttsl=\reducedttsl
+  \def\curfontsize{reduced}%
+  \def\lsize{small}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{10.5pt}}
+\def\smallfonts{%
+  \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl
+  \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc
+  \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy
+  \let\tenttsl=\smallttsl
+  \def\curfontsize{small}%
+  \def\lsize{smaller}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{10.5pt}}
+\def\smallerfonts{%
+  \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl
+  \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc
+  \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy
+  \let\tenttsl=\smallerttsl
+  \def\curfontsize{smaller}%
+  \def\lsize{smaller}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{9.5pt}}
+
+% Set the fonts to use with the @small... environments.
+\let\smallexamplefonts = \smallfonts
+
+% About \smallexamplefonts.  If we use \smallfonts (9pt), @smallexample
+% can fit this many characters:
+%   8.5x11=86   smallbook=72  a4=90  a5=69
+% If we use \scriptfonts (8pt), then we can fit this many characters:
+%   8.5x11=90+  smallbook=80  a4=90+  a5=77
+% For me, subjectively, the few extra characters that fit aren't worth
+% the additional smallness of 8pt.  So I'm making the default 9pt.
+%
+% By the way, for comparison, here's what fits with @example (10pt):
+%   8.5x11=71  smallbook=60  a4=75  a5=58
+%
+% I wish the USA used A4 paper.
+% --karl, 24jan03.
+
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts \rm
+
+% Define these so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bfshape{10}{\magstep1}  % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}
+\setfont\shortconttt\ttshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
+                    \ptexslash\fi\fi\fi}
+\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally uses \ttsl.
+% @var is set to this for defun arguments.
+\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally use \sl.  We never want
+% ttsl for book titles, do we?
+\def\cite#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\slanted=\smartslanted
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+
+% @b, explicit bold.
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% @sansserif, explicit sans.
+\def\sansserif#1{{\sf #1}}
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph.  Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1  \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+% Set sfcode to normal for the chars that usually have another value.
+% Can't use plain's \frenchspacing because it uses the `\x notation, and
+% sometimes \x has an active definition that messes things up.
+%
+\chardef\colonChar = `\:
+\chardef\commaChar = `\,
+\chardef\dotChar   = `\.
+\chardef\exclamChar= `\!
+\chardef\questChar = `\?
+\chardef\semiChar  = `\;
+%
+\catcode`@=11
+  \def\plainfrenchspacing{%
+    \sfcode\dotChar  =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m
+    \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m
+    \def\endofsentencespacefactor{1000}% for @. and friends
+  }
+  \def\plainnonfrenchspacing{%
+    \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000
+    \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250
+    \def\endofsentencespacefactor{3000}% for @. and friends
+  }
+\catcode`@=\other
+\def\endofsentencespacefactor{3000}% default
+
+\def\t#1{%
+  {\tt \rawbackslash \plainfrenchspacing #1}%
+  \null
+}
+\def\samp#1{`\tclose{#1}'\null}
+\setfont\keyrm\rmshape{8}{1000}
+\font\keysy=cmsy9
+\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
+  \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+    \vbox{\hrule\kern-0.4pt
+     \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+    \kern-0.4pt\hrule}%
+  \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+  {%
+    % Change normal interword space to be same as for the current font.
+    \spaceskip = \fontdimen2\font
+    %
+    % Switch to typewriter.
+    \tt
+    %
+    % But `\ ' produces the large typewriter interword space.
+    \def\ {{\spaceskip = 0pt{} }}%
+    %
+    % Turn off hyphenation.
+    \nohyphenation
+    %
+    \rawbackslash
+    \plainfrenchspacing
+    #1%
+  }%
+  \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in @code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+%  -- rms.
+{
+  \catcode`\-=\active
+  \catcode`\_=\active
+  %
+  \global\def\code{\begingroup
+    \catcode`\-=\active  \catcode`\_=\active
+    \ifallowcodebreaks
+     \let-\codedash
+     \let_\codeunder
+    \else
+     \let-\realdash
+     \let_\realunder
+    \fi
+    \codex
+  }
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{%
+  % this is all so @math{@code{var_name}+1} can work.  In math mode, _
+  % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
+  % will therefore expand the active definition of _, which is us
+  % (inside @code that is), therefore an endless loop.
+  \ifusingtt{\ifmmode
+               \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
+             \else\normalunderscore \fi
+             \discretionary{}{}{}}%
+            {\_}%
+}
+\def\codex #1{\tclose{#1}\endgroup}
+
+% An additional complication: the above will allow breaks after, e.g.,
+% each of the four underscores in __typeof__.  This is undesirable in
+% some manuals, especially if they don't have long identifiers in
+% general.  @allowcodebreaks provides a way to control this.
+% 
+\newif\ifallowcodebreaks  \allowcodebreakstrue
+
+\def\keywordtrue{true}
+\def\keywordfalse{false}
+
+\parseargdef\allowcodebreaks{%
+  \def\txiarg{#1}%
+  \ifx\txiarg\keywordtrue
+    \allowcodebreakstrue
+  \else\ifx\txiarg\keywordfalse
+    \allowcodebreaksfalse
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @allowcodebreaks option `\txiarg'}%
+  \fi\fi
+}
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+%   `example' (@kbd uses ttsl only inside of @example and friends),
+%   or `code' (@kbd uses normal tty font always).
+\parseargdef\kbdinputstyle{%
+  \def\txiarg{#1}%
+  \ifx\txiarg\worddistinct
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+  \else\ifx\txiarg\wordexample
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+  \else\ifx\txiarg\wordcode
+    \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @kbdinputstyle option `\txiarg'}%
+  \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is `distinct.'
+\kbdinputstyle distinct
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% For @indicateurl, @env, @command quotes seem unnecessary, so use \code.
+\let\indicateurl=\code
+\let\env=\code
+\let\command=\code
+
+% @uref (abbreviation for `urlref') takes an optional (comma-separated)
+% second argument specifying the text to display and an optional third
+% arg as text to display instead of (rather than in addition to) the url
+% itself.  First (mandatory) arg is the url.  Perhaps eventually put in
+% a hypertex \special here.
+%
+\def\uref#1{\douref #1,,,\finish}
+\def\douref#1,#2,#3,#4\finish{\begingroup
+  \unsepspaces
+  \pdfurl{#1}%
+  \setbox0 = \hbox{\ignorespaces #3}%
+  \ifdim\wd0 > 0pt
+    \unhbox0 % third arg given, show only that
+  \else
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0 > 0pt
+      \ifpdf
+        \unhbox0             % PDF: 2nd arg given, show only it
+      \else
+        \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
+      \fi
+    \else
+      \code{#1}% only url given, so show it
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% @url synonym for @uref, since that's how everyone uses it.
+%
+\let\url=\uref
+
+% rms does not like angle brackets --karl, 17may97.
+% So now @email is just like @uref, unless we are pdf.
+%
+%\def\email#1{\angleleft{\tt #1}\angleright}
+\ifpdf
+  \def\email#1{\doemail#1,,\finish}
+  \def\doemail#1,#2,#3\finish{\begingroup
+    \unsepspaces
+    \pdfurl{mailto:#1}%
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
+    \endlink
+  \endgroup}
+\else
+  \let\email=\uref
+\fi
+
+% Check if we are currently using a typewriter font.  Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'.  The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find.  We need it for
+% Polish suppressed-l.  --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}}              % roman font
+\def\sc#1{{\smallcaps#1}}       % smallcaps font
+\def\ii#1{{\it #1}}             % italic font
+
+% @acronym for "FBI", "NATO", and the like.
+% We print this one point size smaller, since it's intended for
+% all-uppercase.
+% 
+\def\acronym#1{\doacronym #1,,\finish}
+\def\doacronym#1,#2,#3\finish{%
+  {\selectfonts\lsize #1}%
+  \def\temp{#2}%
+  \ifx\temp\empty \else
+    \space ({\unsepspaces \ignorespaces \temp \unskip})%
+  \fi
+}
+
+% @abbr for "Comput. J." and the like.
+% No font change, but don't do end-of-sentence spacing.
+% 
+\def\abbr#1{\doabbr #1,,\finish}
+\def\doabbr#1,#2,#3\finish{%
+  {\plainfrenchspacing #1}%
+  \def\temp{#2}%
+  \ifx\temp\empty \else
+    \space ({\unsepspaces \ignorespaces \temp \unskip})%
+  \fi
+}
+
+% @pounds{} is a sterling sign, which Knuth put in the CM italic font.
+%
+\def\pounds{{\it\$}}
+
+% @euro{} comes from a separate font, depending on the current style.
+% We use the free feym* fonts from the eurosym package by Henrik
+% Theiling, which support regular, slanted, bold and bold slanted (and
+% "outlined" (blackboard board, sort of) versions, which we don't need).
+% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
+% 
+% Although only regular is the truly official Euro symbol, we ignore
+% that.  The Euro is designed to be slightly taller than the regular
+% font height.
+% 
+% feymr - regular
+% feymo - slanted
+% feybr - bold
+% feybo - bold slanted
+% 
+% There is no good (free) typewriter version, to my knowledge.
+% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide.
+% Hmm.
+% 
+% Also doesn't work in math.  Do we need to do math with euro symbols?
+% Hope not.
+% 
+% 
+\def\euro{{\eurofont e}}
+\def\eurofont{%
+  % We set the font at each command, rather than predefining it in
+  % \textfonts and the other font-switching commands, so that
+  % installations which never need the symbol don't have to have the
+  % font installed.
+  % 
+  % There is only one designed size (nominal 10pt), so we always scale
+  % that to the current nominal size.
+  % 
+  % By the way, simply using "at 1em" works for cmr10 and the like, but
+  % does not work for cmbx10 and other extended/shrunken fonts.
+  % 
+  \def\eurosize{\csname\curfontsize nominalsize\endcsname}%
+  %
+  \ifx\curfontstyle\bfstylename 
+    % bold:
+    \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize
+  \else 
+    % regular:
+    \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize
+  \fi
+  \thiseurofont
+}
+
+% @registeredsymbol - R in a circle.  The font for the R should really
+% be smaller yet, but lllsize is the best we can do for now.
+% Adapted from the plain.tex definition of \copyright.
+%
+\def\registeredsymbol{%
+  $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}%
+               \hfil\crcr\Orb}}%
+    }$%
+}
+
+% Laurent Siebenmann reports \Orb undefined with:
+%  Textures 1.7.7 (preloaded format=plain 93.10.14)  (68K)  16 APR 2004 02:38
+% so we'll define it if necessary.
+% 
+\ifx\Orb\undefined
+\def\Orb{\mathhexbox20D}
+\fi
+
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page.  Must do @settitle before @titlepage.
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+% Do an implicit @contents or @shortcontents after @end titlepage if the
+% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+%
+\newif\ifsetcontentsaftertitlepage
+ \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
+\newif\ifsetshortcontentsaftertitlepage
+ \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
+
+\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+        \endgroup\page\hbox{}\page}
+
+\envdef\titlepage{%
+  % Open one extra group, as we want to close it in the middle of \Etitlepage.
+  \begingroup
+    \parindent=0pt \textfonts
+    % Leave some space at the very top of the page.
+    \vglue\titlepagetopglue
+    % No rule at page bottom unless we print one at the top with @title.
+    \finishedtitlepagetrue
+    %
+    % Most title ``pages'' are actually two pages long, with space
+    % at the top of the second.  We don't want the ragged left on the second.
+    \let\oldpage = \page
+    \def\page{%
+      \iffinishedtitlepage\else
+	 \finishtitlepage
+      \fi
+      \let\page = \oldpage
+      \page
+      \null
+    }%
+}
+
+\def\Etitlepage{%
+    \iffinishedtitlepage\else
+	\finishtitlepage
+    \fi
+    % It is important to do the page break before ending the group,
+    % because the headline and footline are only empty inside the group.
+    % If we use the new definition of \page, we always get a blank page
+    % after the title page, which we certainly don't want.
+    \oldpage
+  \endgroup
+  %
+  % Need this before the \...aftertitlepage checks so that if they are
+  % in effect the toc pages will come out with page numbers.
+  \HEADINGSon
+  %
+  % If they want short, they certainly want long too.
+  \ifsetshortcontentsaftertitlepage
+    \shortcontents
+    \contents
+    \global\let\shortcontents = \relax
+    \global\let\contents = \relax
+  \fi
+  %
+  \ifsetcontentsaftertitlepage
+    \contents
+    \global\let\contents = \relax
+    \global\let\shortcontents = \relax
+  \fi
+}
+
+\def\finishtitlepage{%
+  \vskip4pt \hrule height 2pt width \hsize
+  \vskip\titlepagebottomglue
+  \finishedtitlepagetrue
+}
+
+%%% Macros to be used within @titlepage:
+
+\let\subtitlerm=\tenrm
+\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}
+
+\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines
+		\let\tt=\authortt}
+
+\parseargdef\title{%
+  \checkenv\titlepage
+  \leftline{\titlefonts\rm #1}
+  % print a rule at the page bottom also.
+  \finishedtitlepagefalse
+  \vskip4pt \hrule height 4pt width \hsize \vskip4pt
+}
+
+\parseargdef\subtitle{%
+  \checkenv\titlepage
+  {\subtitlefont \rightline{#1}}%
+}
+
+% @author should come last, but may come many times.
+% It can also be used inside @quotation.
+%
+\parseargdef\author{%
+  \def\temp{\quotation}%
+  \ifx\thisenv\temp
+    \def\quotationauthor{#1}% printed in \Equotation.
+  \else
+    \checkenv\titlepage
+    \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi
+    {\authorfont \leftline{#1}}%
+  \fi
+}
+
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks\evenheadline    % headline on even pages
+\newtoks\oddheadline     % headline on odd pages
+\newtoks\evenfootline    % footline on even pages
+\newtoks\oddfootline     % footline on odd pages
+
+% Now make TeX use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+                            \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+                            \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what  @headings on  does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish}
+\def\evenheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish}
+\def\oddheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish}
+\def\evenfootingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish}
+\def\oddfootingyyy #1\|#2\|#3\|#4\finish{%
+  \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+  %
+  % Leave some space for the footline.  Hopefully ok to assume
+  % @evenfooting will not be used by itself.
+  \global\advance\pageheight by -\baselineskip
+  \global\advance\vsize by -\baselineskip
+}
+
+\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+
+
+% @headings double      turns headings on for double-sided printing.
+% @headings single      turns headings on for single-sided printing.
+% @headings off         turns them off.
+% @headings on          same as @headings double, retained for compatibility.
+% @headings after       turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{%
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% This produces Day Month Year style of output.
+% Only define if not already defined, in case a txi-??.tex file has set
+% up a different format (e.g., txi-cs.tex does this).
+\ifx\today\undefined
+\def\today{%
+  \number\day\space
+  \ifcase\month
+  \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
+  \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
+  \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
+  \fi
+  \space\number\year}
+\fi
+
+% @settitle line...  specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg{\gdef\thistitle}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent  \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin  \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @ftable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\itemzzz #1{\begingroup %
+  \advance\hsize by -\rightskip
+  \advance\hsize by -\tableindent
+  \setbox0=\hbox{\itemindicate{#1}}%
+  \itemindex{#1}%
+  \nobreak % This prevents a break before @itemx.
+  %
+  % If the item text does not fit in the space we have, put it on a line
+  % by itself, and do not allow a page break either before or after that
+  % line.  We do not start a paragraph here because then if the next
+  % command is, e.g., @kindex, the whatsit would get put into the
+  % horizontal list on a line by itself, resulting in extra blank space.
+  \ifdim \wd0>\itemmax
+    %
+    % Make this a paragraph so we get the \parskip glue and wrapping,
+    % but leave it ragged-right.
+    \begingroup
+      \advance\leftskip by-\tableindent
+      \advance\hsize by\tableindent
+      \advance\rightskip by0pt plus1fil
+      \leavevmode\unhbox0\par
+    \endgroup
+    %
+    % We're going to be starting a paragraph, but we don't want the
+    % \parskip glue -- logically it's part of the @item we just started.
+    \nobreak \vskip-\parskip
+    %
+    % Stop a page break at the \parskip glue coming up.  However, if
+    % what follows is an environment such as @example, there will be no
+    % \parskip glue; then the negative vskip we just inserted would
+    % cause the example and the item to crash together.  So we use this
+    % bizarre value of 10001 as a signal to \aboveenvbreak to insert
+    % \parskip glue after all.  Section titles are handled this way also.
+    % 
+    \penalty 10001
+    \endgroup
+    \itemxneedsnegativevskipfalse
+  \else
+    % The item text fits into the space.  Start a paragraph, so that the
+    % following text (if any) will end up on the same line.
+    \noindent
+    % Do this with kerns and \unhbox so that if there is a footnote in
+    % the item text, it can migrate to the main vertical list and
+    % eventually be printed.
+    \nobreak\kern-\tableindent
+    \dimen0 = \itemmax  \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
+    \unhbox0
+    \nobreak\kern\dimen0
+    \endgroup
+    \itemxneedsnegativevskiptrue
+  \fi
+}
+
+\def\item{\errmessage{@item while not in a list environment}}
+\def\itemx{\errmessage{@itemx while not in a list environment}}
+
+% @table, @ftable, @vtable.
+\envdef\table{%
+  \let\itemindex\gobble
+  \tablecheck{table}%
+}
+\envdef\ftable{%
+  \def\itemindex ##1{\doind {fn}{\code{##1}}}%
+  \tablecheck{ftable}%
+}
+\envdef\vtable{%
+  \def\itemindex ##1{\doind {vr}{\code{##1}}}%
+  \tablecheck{vtable}%
+}
+\def\tablecheck#1{%
+  \ifnum \the\catcode`\^^M=\active
+    \endgroup
+    \errmessage{This command won't work in this context; perhaps the problem is
+      that we are \inenvironment\thisenv}%
+    \def\next{\doignore{#1}}%
+  \else
+    \let\next\tablex
+  \fi
+  \next
+}
+\def\tablex#1{%
+  \def\itemindicate{#1}%
+  \parsearg\tabley
+}
+\def\tabley#1{%
+  {%
+    \makevalueexpandable
+    \edef\temp{\noexpand\tablez #1\space\space\space}%
+    \expandafter
+  }\temp \endtablez
+}
+\def\tablez #1 #2 #3 #4\endtablez{%
+  \aboveenvbreak
+  \ifnum 0#1>0 \advance \leftskip by #1\mil \fi
+  \ifnum 0#2>0 \tableindent=#2\mil \fi
+  \ifnum 0#3>0 \advance \rightskip by #3\mil \fi
+  \itemmax=\tableindent
+  \advance \itemmax by -\itemmargin
+  \advance \leftskip by \tableindent
+  \exdentamount=\tableindent
+  \parindent = 0pt
+  \parskip = \smallskipamount
+  \ifdim \parskip=0pt \parskip=2pt \fi
+  \let\item = \internalBitem
+  \let\itemx = \internalBitemx
+}
+\def\Etable{\endgraf\afterenvbreak}
+\let\Eftable\Etable
+\let\Evtable\Etable
+\let\Eitemize\Etable
+\let\Eenumerate\Etable
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\envdef\itemize{\parsearg\doitemize}
+
+\def\doitemize#1{%
+  \aboveenvbreak
+  \itemmax=\itemindent
+  \advance\itemmax by -\itemmargin
+  \advance\leftskip by \itemindent
+  \exdentamount=\itemindent
+  \parindent=0pt
+  \parskip=\smallskipamount
+  \ifdim\parskip=0pt \parskip=2pt \fi
+  \def\itemcontents{#1}%
+  % @itemize with no arg is equivalent to @itemize @bullet.
+  \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
+  \let\item=\itemizeitem
+}
+
+% Definition of @item while inside @itemize and @enumerate.
+%
+\def\itemizeitem{%
+  \advance\itemno by 1  % for enumerations
+  {\let\par=\endgraf \smallbreak}% reasonable place to break
+  {%
+   % If the document has an @itemize directly after a section title, a
+   % \nobreak will be last on the list, and \sectionheading will have
+   % done a \vskip-\parskip.  In that case, we don't want to zero
+   % parskip, or the item text will crash with the heading.  On the
+   % other hand, when there is normal text preceding the item (as there
+   % usually is), we do want to zero parskip, or there would be too much
+   % space.  In that case, we won't have a \nobreak before.  At least
+   % that's the theory.
+   \ifnum\lastpenalty<10000 \parskip=0in \fi
+   \noindent
+   \hbox to 0pt{\hss \itemcontents \kern\itemmargin}%
+   \vadjust{\penalty 1200}}% not good to break after first line of item.
+  \flushcr
+}
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list.  No
+% argument is the same as `1'.
+%
+\envparseargdef\enumerate{\enumeratey #1  \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+  % If we were given no argument, pretend we were given `1'.
+  \def\thearg{#1}%
+  \ifx\thearg\empty \def\thearg{1}\fi
+  %
+  % Detect if the argument is a single token.  If so, it might be a
+  % letter.  Otherwise, the only valid thing it can be is a number.
+  % (We will always have one token, because of the test we just made.
+  % This is a good thing, since \splitoff doesn't work given nothing at
+  % all -- the first parameter is undelimited.)
+  \expandafter\splitoff\thearg\endmark
+  \ifx\rest\empty
+    % Only one token in the argument.  It could still be anything.
+    % A ``lowercase letter'' is one whose \lccode is nonzero.
+    % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+    %   not equal to itself.
+    % Otherwise, we assume it's a number.
+    %
+    % We need the \relax at the end of the \ifnum lines to stop TeX from
+    % continuing to look for a <number>.
+    %
+    \ifnum\lccode\expandafter`\thearg=0\relax
+      \numericenumerate % a number (we hope)
+    \else
+      % It's a letter.
+      \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+        \lowercaseenumerate % lowercase letter
+      \else
+        \uppercaseenumerate % uppercase letter
+      \fi
+    \fi
+  \else
+    % Multiple tokens in the argument.  We hope it's a number.
+    \numericenumerate
+  \fi
+}
+
+% An @enumerate whose labels are integers.  The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+  \itemno = \thearg
+  \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more lowercase letters in @enumerate; get a bigger
+                  alphabet}%
+    \fi
+    \char\lccode\itemno
+  }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more uppercase letters in @enumerate; get a bigger
+                  alphabet}
+    \fi
+    \char\uccode\itemno
+  }%
+}
+
+% Call \doitemize, adding a period to the first argument and supplying the
+% common last two arguments.  Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+  \advance\itemno by -1
+  \doitemize{#1.}\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble.  Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+%   @multitable @columnfractions .25 .3 .45
+%   @item ...
+%
+%   Numbers following @columnfractions are the percent of the total
+%   current hsize to be used for each column. You may use as many
+%   columns as desired.
+
+
+% Or use a template:
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item ...
+%   using the widest term desired in each column.
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab do not need to be on their own lines, but it will not hurt
+% if they are.
+
+% Sample multitable:
+
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item first col stuff @tab second col stuff @tab third col
+%   @item
+%   first col stuff
+%   @tab
+%   second col stuff
+%   @tab
+%   third col
+%   @item first col stuff @tab second col stuff
+%   @tab Many paragraphs of text may be used in any column.
+%
+%         They will wrap at the width determined by the template.
+%   @item@tab@tab This will be in third column.
+%   @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+%                                                            to baseline.
+%   0pt means it depends on current normal line spacing.
+%
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+% Macros used to set up halign preamble:
+%
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+% #1 is the @columnfraction, usually a decimal number like .5, but might
+% be just 1.  We just use it, whatever it is.
+%
+\def\pickupwholefraction#1 {%
+  \global\advance\colcount by 1
+  \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}%
+  \setuptable
+}
+
+\newcount\colcount
+\def\setuptable#1{%
+  \def\firstarg{#1}%
+  \ifx\firstarg\xendsetuptable
+    \let\go = \relax
+  \else
+    \ifx\firstarg\xcolumnfractions
+      \global\setpercenttrue
+    \else
+      \ifsetpercent
+         \let\go\pickupwholefraction
+      \else
+         \global\advance\colcount by 1
+         \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a
+                   % separator; typically that is always in the input, anyway.
+         \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+      \fi
+    \fi
+    \ifx\go\pickupwholefraction
+      % Put the argument back for the \pickupwholefraction call, so
+      % we'll always have a period there to be parsed.
+      \def\go{\pickupwholefraction#1}%
+    \else
+      \let\go = \setuptable
+    \fi%
+  \fi
+  \go
+}
+
+% multitable-only commands.
+%
+% @headitem starts a heading row, which we typeset in bold.
+% Assignments have to be global since we are inside the implicit group
+% of an alignment entry.  Note that \everycr resets \everytab.
+\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}%
+%
+% A \tab used to include \hskip1sp.  But then the space in a template
+% line is not enough.  That is bad.  So let's go back to just `&' until
+% we encounter the problem it was intended to solve again.
+%					--karl, nathan@acm.org, 20apr99.
+\def\tab{\checkenv\multitable &\the\everytab}%
+
+% @multitable ... @end multitable definitions:
+%
+\newtoks\everytab  % insert after every tab.
+%
+\envdef\multitable{%
+  \vskip\parskip
+  \startsavinginserts
+  %
+  % @item within a multitable starts a normal row.
+  % We use \def instead of \let so that if one of the multitable entries
+  % contains an @itemize, we don't choke on the \item (seen as \crcr aka
+  % \endtemplate) expanding \doitemize.
+  \def\item{\crcr}%
+  %
+  \tolerance=9500
+  \hbadness=9500
+  \setmultitablespacing
+  \parskip=\multitableparskip
+  \parindent=\multitableparindent
+  \overfullrule=0pt
+  \global\colcount=0
+  %
+  \everycr = {%
+    \noalign{%
+      \global\everytab={}%
+      \global\colcount=0 % Reset the column counter.
+      % Check for saved footnotes, etc.
+      \checkinserts
+      % Keeps underfull box messages off when table breaks over pages.
+      %\filbreak
+	% Maybe so, but it also creates really weird page breaks when the
+	% table breaks over pages. Wouldn't \vfil be better?  Wait until the
+	% problem manifests itself, so it can be fixed for real --karl.
+    }%
+  }%
+  %
+  \parsearg\domultitable
+}
+\def\domultitable#1{%
+  % To parse everything between @multitable and @item:
+  \setuptable#1 \endsetuptable
+  %
+  % This preamble sets up a generic column definition, which will
+  % be used as many times as user calls for columns.
+  % \vtop will set a single line and will also let text wrap and
+  % continue for many paragraphs if desired.
+  \halign\bgroup &%
+    \global\advance\colcount by 1
+    \multistrut
+    \vtop{%
+      % Use the current \colcount to find the correct column width:
+      \hsize=\expandafter\csname col\the\colcount\endcsname
+      %
+      % In order to keep entries from bumping into each other
+      % we will add a \leftskip of \multitablecolspace to all columns after
+      % the first one.
+      %
+      % If a template has been used, we will add \multitablecolspace
+      % to the width of each template entry.
+      %
+      % If the user has set preamble in terms of percent of \hsize we will
+      % use that dimension as the width of the column, and the \leftskip
+      % will keep entries from bumping into each other.  Table will start at
+      % left margin and final column will justify at right margin.
+      %
+      % Make sure we don't inherit \rightskip from the outer environment.
+      \rightskip=0pt
+      \ifnum\colcount=1
+	% The first column will be indented with the surrounding text.
+	\advance\hsize by\leftskip
+      \else
+	\ifsetpercent \else
+	  % If user has not set preamble in terms of percent of \hsize
+	  % we will advance \hsize by \multitablecolspace.
+	  \advance\hsize by \multitablecolspace
+	\fi
+       % In either case we will make \leftskip=\multitablecolspace:
+      \leftskip=\multitablecolspace
+      \fi
+      % Ignoring space at the beginning and end avoids an occasional spurious
+      % blank line, when TeX decides to break the line at the space before the
+      % box from the multistrut, so the strut ends up on a line by itself.
+      % For example:
+      % @multitable @columnfractions .11 .89
+      % @item @code{#}
+      % @tab Legal holiday which is valid in major parts of the whole country.
+      % Is automatically provided with highlighting sequences respectively
+      % marking characters.
+      \noindent\ignorespaces##\unskip\multistrut
+    }\cr
+}
+\def\Emultitable{%
+  \crcr
+  \egroup % end the \halign
+  \global\setpercentfalse
+}
+
+\def\setmultitablespacing{%
+  \def\multistrut{\strut}% just use the standard line spacing
+  %
+  % Compute \multitablelinespace (if not defined by user) for use in
+  % \multitableparskip calculation.  We used define \multistrut based on
+  % this, but (ironically) that caused the spacing to be off.
+  % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100.
+\ifdim\multitablelinespace=0pt
+\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
+\global\advance\multitablelinespace by-\ht0
+\fi
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%%        If so, set to same dimension as multitablelinespace.
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi}
+
+
+\message{conditionals,}
+
+% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext,
+% @ifnotxml always succeed.  They currently do nothing; we don't
+% attempt to check whether the conditionals are properly nested.  But we
+% have to remember that they are conditionals, so that @end doesn't
+% attempt to close an environment group.
+%
+\def\makecond#1{%
+  \expandafter\let\csname #1\endcsname = \relax
+  \expandafter\let\csname iscond.#1\endcsname = 1
+}
+\makecond{iftex}
+\makecond{ifnotdocbook}
+\makecond{ifnothtml}
+\makecond{ifnotinfo}
+\makecond{ifnotplaintext}
+\makecond{ifnotxml}
+
+% Ignore @ignore, @ifhtml, @ifinfo, and the like.
+%
+\def\direntry{\doignore{direntry}}
+\def\documentdescription{\doignore{documentdescription}}
+\def\docbook{\doignore{docbook}}
+\def\html{\doignore{html}}
+\def\ifdocbook{\doignore{ifdocbook}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\ifplaintext{\doignore{ifplaintext}}
+\def\ifxml{\doignore{ifxml}}
+\def\ignore{\doignore{ignore}}
+\def\menu{\doignore{menu}}
+\def\xml{\doignore{xml}}
+
+% Ignore text until a line `@end #1', keeping track of nested conditionals.
+%
+% A count to remember the depth of nesting.
+\newcount\doignorecount
+
+\def\doignore#1{\begingroup
+  % Scan in ``verbatim'' mode:
+  \obeylines
+  \catcode`\@ = \other
+  \catcode`\{ = \other
+  \catcode`\} = \other
+  %
+  % Make sure that spaces turn into tokens that match what \doignoretext wants.
+  \spaceisspace
+  %
+  % Count number of #1's that we've seen.
+  \doignorecount = 0
+  %
+  % Swallow text until we reach the matching `@end #1'.
+  \dodoignore{#1}%
+}
+
+{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source.
+  \obeylines %
+  %
+  \gdef\dodoignore#1{%
+    % #1 contains the command name as a string, e.g., `ifinfo'.
+    %
+    % Define a command to find the next `@end #1'.
+    \long\def\doignoretext##1^^M@end #1{%
+      \doignoretextyyy##1^^M@#1\_STOP_}%
+    %
+    % And this command to find another #1 command, at the beginning of a
+    % line.  (Otherwise, we would consider a line `@c @ifset', for
+    % example, to count as an @ifset for nesting.)
+    \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}%
+    %
+    % And now expand that command.
+    \doignoretext ^^M%
+  }%
+}
+
+\def\doignoreyyy#1{%
+  \def\temp{#1}%
+  \ifx\temp\empty			% Nothing found.
+    \let\next\doignoretextzzz
+  \else					% Found a nested condition, ...
+    \advance\doignorecount by 1
+    \let\next\doignoretextyyy		% ..., look for another.
+    % If we're here, #1 ends with ^^M\ifinfo (for example).
+  \fi
+  \next #1% the token \_STOP_ is present just after this macro.
+}
+
+% We have to swallow the remaining "\_STOP_".
+%
+\def\doignoretextzzz#1{%
+  \ifnum\doignorecount = 0	% We have just found the outermost @end.
+    \let\next\enddoignore
+  \else				% Still inside a nested condition.
+    \advance\doignorecount by -1
+    \let\next\doignoretext      % Look for the next @end.
+  \fi
+  \next
+}
+
+% Finish off ignored text.
+{ \obeylines%
+  % Ignore anything after the last `@end #1'; this matters in verbatim
+  % environments, where otherwise the newline after an ignored conditional
+  % would result in a blank line in the output.
+  \gdef\enddoignore#1^^M{\endgroup\ignorespaces}%
+}
+
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+% We rely on the fact that \parsearg sets \catcode`\ =10.
+%
+\parseargdef\set{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+  {%
+    \makevalueexpandable
+    \def\temp{#2}%
+    \edef\next{\gdef\makecsname{SET#1}}%
+    \ifx\temp\empty
+      \next{}%
+    \else
+      \setzzz#2\endsetzzz
+    \fi
+  }%
+}
+% Remove the trailing space \setxxx inserted.
+\def\setzzz#1 \endsetzzz{\next{#1}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\parseargdef\clear{%
+  {%
+    \makevalueexpandable
+    \global\expandafter\let\csname SET#1\endcsname=\relax
+  }%
+}
+
+% @value{foo} gets the text saved in variable foo.
+\def\value{\begingroup\makevalueexpandable\valuexxx}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+{
+  \catcode`\- = \active \catcode`\_ = \active
+  %
+  \gdef\makevalueexpandable{%
+    \let\value = \expandablevalue
+    % We don't want these characters active, ...
+    \catcode`\-=\other \catcode`\_=\other
+    % ..., but we might end up with active ones in the argument if
+    % we're called from @code, as @code{@value{foo-bar_}}, though.
+    % So \let them to their normal equivalents.
+    \let-\realdash \let_\normalunderscore
+  }
+}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we call \makevalueexpandable in \indexdummies).
+% The command has to be fully expandable (if the variable is set), since
+% the result winds up in the index file.  This means that if the
+% variable's value contains other Texinfo commands, it's almost certain
+% it will fail (although perhaps we could fix that with sufficient work
+% to do a one-level expansion on the result, instead of complete).
+%
+\def\expandablevalue#1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    {[No value for ``#1'']}%
+    \message{Variable `#1', used in @value, is not set.}%
+  \else
+    \csname SET#1\endcsname
+  \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+% To get special treatment of `@end ifset,' call \makeond and the redefine.
+%
+\makecond{ifset}
+\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}}
+\def\doifset#1#2{%
+  {%
+    \makevalueexpandable
+    \let\next=\empty
+    \expandafter\ifx\csname SET#2\endcsname\relax
+      #1% If not set, redefine \next.
+    \fi
+    \expandafter
+  }\next
+}
+\def\ifsetfail{\doignore{ifset}}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+% The `\else' inside the `\doifset' parameter is a trick to reuse the
+% above code: if the variable is not set, do nothing, if it is set,
+% then redefine \next to \ifclearfail.
+%
+\makecond{ifclear}
+\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
+\def\ifclearfail{\doignore{ifclear}}
+
+% @dircategory CATEGORY  -- specify a category of the dir file
+% which this file should belong to.  Ignore this in TeX.
+\let\dircategory=\comment
+
+% @defininfoenclose.
+\let\definfoenclose=\comment
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within macros and \if's.
+\edef\newwrite{\makecsname{ptexnewwrite}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index.  The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+%
+\def\newindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%     % Define @#1index
+    \noexpand\doindex{#1}}
+}
+
+% @defindex foo  ==  \newindex{foo}
+%
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+%
+\def\defcodeindex{\parsearg\newcodeindex}
+%
+\def\newcodeindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%
+    \noexpand\docodeindex{#1}}%
+}
+
+
+% @synindex foo bar    makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+%
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+%
+\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}}
+\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}}
+
+% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo),
+% #3 the target index (bar).
+\def\dosynindex#1#2#3{%
+  % Only do \closeout if we haven't already done it, else we'll end up
+  % closing the target index.
+  \expandafter \ifx\csname donesynindex#2\endcsname \undefined
+    % The \closeout helps reduce unnecessary open files; the limit on the
+    % Acorn RISC OS is a mere 16 files.
+    \expandafter\closeout\csname#2indfile\endcsname
+    \expandafter\let\csname\donesynindex#2\endcsname = 1
+  \fi
+  % redefine \fooindfile:
+  \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
+  \expandafter\let\csname#2indfile\endcsname=\temp
+  % redefine \fooindex:
+  \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+%  and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+% Take care of Texinfo commands that can appear in an index entry.
+% Since there are some commands we want to expand, and others we don't,
+% we have to laboriously prevent expansion for those that we don't.
+%
+\def\indexdummies{%
+  \escapechar = `\\     % use backslash in output files.
+  \def\@{@}% change to @@ when we switch to @ as escape char in index files.
+  \def\ {\realbackslash\space }%
+  % Need these in case \tex is in effect and \{ is a \delimiter again.
+  % But can't use \lbracecmd and \rbracecmd because texindex assumes
+  % braces and backslashes are used only as delimiters.
+  \let\{ = \mylbrace
+  \let\} = \myrbrace
+  %
+  % Do the redefinitions.
+  \commondummies
+}
+
+% For the aux and toc files, @ is the escape character.  So we want to
+% redefine everything using @ as the escape character (instead of
+% \realbackslash, still used for index files).  When everything uses @,
+% this will be simpler.
+%
+\def\atdummies{%
+  \def\@{@@}%
+  \def\ {@ }%
+  \let\{ = \lbraceatcmd
+  \let\} = \rbraceatcmd
+  %
+  % Do the redefinitions.
+  \commondummies
+  \otherbackslash
+}
+
+% Called from \indexdummies and \atdummies.
+%
+\def\commondummies{%
+  %
+  % \definedummyword defines \#1 as \string\#1\space, thus effectively
+  % preventing its expansion.  This is used only for control% words,
+  % not control letters, because the \space would be incorrect for
+  % control characters, but is needed to separate the control word
+  % from whatever follows.
+  %
+  % For control letters, we have \definedummyletter, which omits the
+  % space.
+  %
+  % These can be used both for control words that take an argument and
+  % those that do not.  If it is followed by {arg} in the input, then
+  % that will dutifully get written to the index (or wherever).
+  %
+  \def\definedummyword  ##1{\def##1{\string##1\space}}%
+  \def\definedummyletter##1{\def##1{\string##1}}%
+  \let\definedummyaccent\definedummyletter
+  %
+  \commondummiesnofonts
+  %
+  \definedummyletter\_%
+  %
+  % Non-English letters.
+  \definedummyword\AA
+  \definedummyword\AE
+  \definedummyword\L
+  \definedummyword\OE
+  \definedummyword\O
+  \definedummyword\aa
+  \definedummyword\ae
+  \definedummyword\l
+  \definedummyword\oe
+  \definedummyword\o
+  \definedummyword\ss
+  \definedummyword\exclamdown
+  \definedummyword\questiondown
+  \definedummyword\ordf
+  \definedummyword\ordm
+  %
+  % Although these internal commands shouldn't show up, sometimes they do.
+  \definedummyword\bf
+  \definedummyword\gtr
+  \definedummyword\hat
+  \definedummyword\less
+  \definedummyword\sf
+  \definedummyword\sl
+  \definedummyword\tclose
+  \definedummyword\tt
+  %
+  \definedummyword\LaTeX
+  \definedummyword\TeX
+  %
+  % Assorted special characters.
+  \definedummyword\bullet
+  \definedummyword\comma
+  \definedummyword\copyright
+  \definedummyword\registeredsymbol
+  \definedummyword\dots
+  \definedummyword\enddots
+  \definedummyword\equiv
+  \definedummyword\error
+  \definedummyword\euro
+  \definedummyword\expansion
+  \definedummyword\minus
+  \definedummyword\pounds
+  \definedummyword\point
+  \definedummyword\print
+  \definedummyword\result
+  %
+  % We want to disable all macros so that they are not expanded by \write.
+  \macrolist
+  %
+  \normalturnoffactive
+  %
+  % Handle some cases of @value -- where it does not contain any
+  % (non-fully-expandable) commands.
+  \makevalueexpandable
+}
+
+% \commondummiesnofonts: common to \commondummies and \indexnofonts.
+%
+\def\commondummiesnofonts{%
+  % Control letters and accents.
+  \definedummyletter\!%
+  \definedummyaccent\"%
+  \definedummyaccent\'%
+  \definedummyletter\*%
+  \definedummyaccent\,%
+  \definedummyletter\.%
+  \definedummyletter\/%
+  \definedummyletter\:%
+  \definedummyaccent\=%
+  \definedummyletter\?%
+  \definedummyaccent\^%
+  \definedummyaccent\`%
+  \definedummyaccent\~%
+  \definedummyword\u
+  \definedummyword\v
+  \definedummyword\H
+  \definedummyword\dotaccent
+  \definedummyword\ringaccent
+  \definedummyword\tieaccent
+  \definedummyword\ubaraccent
+  \definedummyword\udotaccent
+  \definedummyword\dotless
+  %
+  % Texinfo font commands.
+  \definedummyword\b
+  \definedummyword\i
+  \definedummyword\r
+  \definedummyword\sc
+  \definedummyword\t
+  %
+  % Commands that take arguments.
+  \definedummyword\acronym
+  \definedummyword\cite
+  \definedummyword\code
+  \definedummyword\command
+  \definedummyword\dfn
+  \definedummyword\emph
+  \definedummyword\env
+  \definedummyword\file
+  \definedummyword\kbd
+  \definedummyword\key
+  \definedummyword\math
+  \definedummyword\option
+  \definedummyword\pxref
+  \definedummyword\ref
+  \definedummyword\samp
+  \definedummyword\strong
+  \definedummyword\tie
+  \definedummyword\uref
+  \definedummyword\url
+  \definedummyword\var
+  \definedummyword\verb
+  \definedummyword\w
+  \definedummyword\xref
+}
+
+% \indexnofonts is used when outputting the strings to sort the index
+% by, and when constructing control sequence names.  It eliminates all
+% control sequences and just writes whatever the best ASCII sort string
+% would be for a given command (usually its argument).
+%
+\def\indexnofonts{%
+  % Accent commands should become @asis.
+  \def\definedummyaccent##1{\let##1\asis}%
+  % We can just ignore other control letters.
+  \def\definedummyletter##1{\let##1\empty}%
+  % Hopefully, all control words can become @asis.
+  \let\definedummyword\definedummyaccent
+  %
+  \commondummiesnofonts
+  %
+  % Don't no-op \tt, since it isn't a user-level command
+  % and is used in the definitions of the active chars like <, >, |, etc.
+  % Likewise with the other plain tex font commands.
+  %\let\tt=\asis
+  %
+  \def\ { }%
+  \def\@{@}%
+  % how to handle braces?
+  \def\_{\normalunderscore}%
+  %
+  % Non-English letters.
+  \def\AA{AA}%
+  \def\AE{AE}%
+  \def\L{L}%
+  \def\OE{OE}%
+  \def\O{O}%
+  \def\aa{aa}%
+  \def\ae{ae}%
+  \def\l{l}%
+  \def\oe{oe}%
+  \def\o{o}%
+  \def\ss{ss}%
+  \def\exclamdown{!}%
+  \def\questiondown{?}%
+  \def\ordf{a}%
+  \def\ordm{o}%
+  %
+  \def\LaTeX{LaTeX}%
+  \def\TeX{TeX}%
+  %
+  % Assorted special characters.
+  % (The following {} will end up in the sort string, but that's ok.)
+  \def\bullet{bullet}%
+  \def\comma{,}%
+  \def\copyright{copyright}%
+  \def\registeredsymbol{R}%
+  \def\dots{...}%
+  \def\enddots{...}%
+  \def\equiv{==}%
+  \def\error{error}%
+  \def\euro{euro}%
+  \def\expansion{==>}%
+  \def\minus{-}%
+  \def\pounds{pounds}%
+  \def\point{.}%
+  \def\print{-|}%
+  \def\result{=>}%
+  %
+  % We need to get rid of all macros, leaving only the arguments (if present).
+  % Of course this is not nearly correct, but it is the best we can do for now.
+  % makeinfo does not expand macros in the argument to @deffn, which ends up
+  % writing an index entry, and texindex isn't prepared for an index sort entry
+  % that starts with \.
+  % 
+  % Since macro invocations are followed by braces, we can just redefine them
+  % to take a single TeX argument.  The case of a macro invocation that
+  % goes to end-of-line is not handled.
+  % 
+  \macrolist
+}
+
+\let\indexbackslash=0  %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% Most index entries go through here, but \dosubind is the general case.
+% #1 is the index name, #2 is the entry text.
+\def\doind#1#2{\dosubind{#1}{#2}{}}
+
+% Workhorse for all \fooindexes.
+% #1 is name of index, #2 is stuff to put there, #3 is subentry --
+% empty if called from \doind, as we usually are (the main exception
+% is with most defuns, which call us directly).
+%
+\def\dosubind#1#2#3{%
+  \iflinks
+  {%
+    % Store the main index entry text (including the third arg).
+    \toks0 = {#2}%
+    % If third arg is present, precede it with a space.
+    \def\thirdarg{#3}%
+    \ifx\thirdarg\empty \else
+      \toks0 = \expandafter{\the\toks0 \space #3}%
+    \fi
+    %
+    \edef\writeto{\csname#1indfile\endcsname}%
+    %
+    \ifvmode
+      \dosubindsanitize
+    \else
+      \dosubindwrite
+    \fi
+  }%
+  \fi
+}
+
+% Write the entry in \toks0 to the index file:
+%
+\def\dosubindwrite{%
+  % Put the index entry in the margin if desired.
+  \ifx\SETmarginindex\relax\else
+    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
+  \fi
+  %
+  % Remember, we are within a group.
+  \indexdummies % Must do this here, since \bf, etc expand at this stage
+  \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now
+      % so it will be output as is; and it will print as backslash.
+  %
+  % Process the index entry with all font commands turned off, to
+  % get the string to sort by.
+  {\indexnofonts
+   \edef\temp{\the\toks0}% need full expansion
+   \xdef\indexsorttmp{\temp}%
+  }%
+  %
+  % Set up the complete index entry, with both the sort key and
+  % the original text, including any font commands.  We write
+  % three arguments to \entry to the .?? file (four in the
+  % subentry case), texindex reduces to two when writing the .??s
+  % sorted result.
+  \edef\temp{%
+    \write\writeto{%
+      \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}%
+  }%
+  \temp
+}
+
+% Take care of unwanted page breaks:
+%
+% If a skip is the last thing on the list now, preserve it
+% by backing up by \lastskip, doing the \write, then inserting
+% the skip again.  Otherwise, the whatsit generated by the
+% \write will make \lastskip zero.  The result is that sequences
+% like this:
+% @end defun
+% @tindex whatever
+% @defun ...
+% will have extra space inserted, because the \medbreak in the
+% start of the @defun won't see the skip inserted by the @end of
+% the previous defun.
+%
+% But don't do any of this if we're not in vertical mode.  We
+% don't want to do a \vskip and prematurely end a paragraph.
+%
+% Avoid page breaks due to these extra skips, too.
+%
+% But wait, there is a catch there:
+% We'll have to check whether \lastskip is zero skip.  \ifdim is not
+% sufficient for this purpose, as it ignores stretch and shrink parts
+% of the skip.  The only way seems to be to check the textual
+% representation of the skip.
+%
+% The following is almost like \def\zeroskipmacro{0.0pt} except that
+% the ``p'' and ``t'' characters have catcode \other, not 11 (letter).
+%
+\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname}
+%
+% ..., ready, GO:
+%
+\def\dosubindsanitize{%
+  % \lastskip and \lastpenalty cannot both be nonzero simultaneously.
+  \skip0 = \lastskip
+  \edef\lastskipmacro{\the\lastskip}%
+  \count255 = \lastpenalty
+  %
+  % If \lastskip is nonzero, that means the last item was a
+  % skip.  And since a skip is discardable, that means this
+  % -\skip0 glue we're inserting is preceded by a
+  % non-discardable item, therefore it is not a potential
+  % breakpoint, therefore no \nobreak needed.
+  \ifx\lastskipmacro\zeroskipmacro
+  \else
+    \vskip-\skip0
+  \fi
+  %
+  \dosubindwrite
+  %
+  \ifx\lastskipmacro\zeroskipmacro
+    % If \lastskip was zero, perhaps the last item was a penalty, and
+    % perhaps it was >=10000, e.g., a \nobreak.  In that case, we want
+    % to re-insert the same penalty (values >10000 are used for various
+    % signals); since we just inserted a non-discardable item, any
+    % following glue (such as a \parskip) would be a breakpoint.  For example:
+    % 
+    %   @deffn deffn-whatever
+    %   @vindex index-whatever
+    %   Description.
+    % would allow a break between the index-whatever whatsit
+    % and the "Description." paragraph.
+    \ifnum\count255>9999 \penalty\count255 \fi
+  \else
+    % On the other hand, if we had a nonzero \lastskip,
+    % this make-up glue would be preceded by a non-discardable item
+    % (the whatsit from the \write), so we must insert a \nobreak.
+    \nobreak\vskip\skip0
+  \fi
+}
+
+% The index entry written in the file actually looks like
+%  \entry {sortstring}{page}{topic}
+% or
+%  \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+%  \initial {c}
+%     before the first topic whose initial is c
+%  \entry {topic}{pagelist}
+%     for a topic that is used without subtopics
+%  \primary {topic}
+%     for the beginning of a topic that is used with subtopics
+%  \secondary {subtopic}{pagelist}
+%     for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% @printindex causes a particular index (the ??s file) to get printed.
+% It does not print any chapter heading (usually an @unnumbered).
+%
+\parseargdef\printindex{\begingroup
+  \dobreak \chapheadingskip{10000}%
+  %
+  \smallfonts \rm
+  \tolerance = 9500
+  \everypar = {}% don't want the \kern\-parindent from indentation suppression.
+  %
+  % See if the index file exists and is nonempty.
+  % Change catcode of @ here so that if the index file contains
+  % \initial {@}
+  % as its first line, TeX doesn't complain about mismatched braces
+  % (because it thinks @} is a control sequence).
+  \catcode`\@ = 11
+  \openin 1 \jobname.#1s
+  \ifeof 1
+    % \enddoublecolumns gets confused if there is no text in the index,
+    % and it loses the chapter title and the aux file entries for the
+    % index.  The easiest way to prevent this problem is to make sure
+    % there is some text.
+    \putwordIndexNonexistent
+  \else
+    %
+    % If the index file exists but is empty, then \openin leaves \ifeof
+    % false.  We have to make TeX try to read something from the file, so
+    % it can discover if there is anything in it.
+    \read 1 to \temp
+    \ifeof 1
+      \putwordIndexIsEmpty
+    \else
+      % Index files are almost Texinfo source, but we use \ as the escape
+      % character.  It would be better to use @, but that's too big a change
+      % to make right now.
+      \def\indexbackslash{\backslashcurfont}%
+      \catcode`\\ = 0
+      \escapechar = `\\
+      \begindoublecolumns
+      \input \jobname.#1s
+      \enddoublecolumns
+    \fi
+  \fi
+  \closein 1
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+\def\initial#1{{%
+  % Some minor font changes for the special characters.
+  \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+  %
+  % Remove any glue we may have, we'll be inserting our own.
+  \removelastskip
+  %
+  % We like breaks before the index initials, so insert a bonus.
+  \nobreak
+  \vskip 0pt plus 3\baselineskip
+  \penalty 0
+  \vskip 0pt plus -3\baselineskip
+  %
+  % Typeset the initial.  Making this add up to a whole number of
+  % baselineskips increases the chance of the dots lining up from column
+  % to column.  It still won't often be perfect, because of the stretch
+  % we need before each entry, but it's better.
+  %
+  % No shrink because it confuses \balancecolumns.
+  \vskip 1.67\baselineskip plus .5\baselineskip
+  \leftline{\secbf #1}%
+  % Do our best not to break after the initial.
+  \nobreak
+  \vskip .33\baselineskip plus .1\baselineskip
+}}
+
+% \entry typesets a paragraph consisting of the text (#1), dot leaders, and
+% then page number (#2) flushed to the right margin.  It is used for index
+% and table of contents entries.  The paragraph is indented by \leftskip.
+%
+% A straightforward implementation would start like this:
+%	\def\entry#1#2{...
+% But this frozes the catcodes in the argument, and can cause problems to
+% @code, which sets - active.  This problem was fixed by a kludge---
+% ``-'' was active throughout whole index, but this isn't really right.
+%
+% The right solution is to prevent \entry from swallowing the whole text.
+%                                 --kasal, 21nov03
+\def\entry{%
+  \begingroup
+    %
+    % Start a new paragraph if necessary, so our assignments below can't
+    % affect previous text.
+    \par
+    %
+    % Do not fill out the last line with white space.
+    \parfillskip = 0in
+    %
+    % No extra space above this paragraph.
+    \parskip = 0in
+    %
+    % Do not prefer a separate line ending with a hyphen to fewer lines.
+    \finalhyphendemerits = 0
+    %
+    % \hangindent is only relevant when the entry text and page number
+    % don't both fit on one line.  In that case, bob suggests starting the
+    % dots pretty far over on the line.  Unfortunately, a large
+    % indentation looks wrong when the entry text itself is broken across
+    % lines.  So we use a small indentation and put up with long leaders.
+    %
+    % \hangafter is reset to 1 (which is the value we want) at the start
+    % of each paragraph, so we need not do anything with that.
+    \hangindent = 2em
+    %
+    % When the entry text needs to be broken, just fill out the first line
+    % with blank space.
+    \rightskip = 0pt plus1fil
+    %
+    % A bit of stretch before each entry for the benefit of balancing
+    % columns.
+    \vskip 0pt plus1pt
+    %
+    % Swallow the left brace of the text (first parameter):
+    \afterassignment\doentry
+    \let\temp =
+}
+\def\doentry{%
+    \bgroup % Instead of the swallowed brace.
+      \noindent
+      \aftergroup\finishentry
+      % And now comes the text of the entry.
+}
+\def\finishentry#1{%
+    % #1 is the page number.
+    %
+    % The following is kludged to not output a line of dots in the index if
+    % there are no page numbers.  The next person who breaks this will be
+    % cursed by a Unix daemon.
+    \def\tempa{{\rm }}%
+    \def\tempb{#1}%
+    \edef\tempc{\tempa}%
+    \edef\tempd{\tempb}%
+    \ifx\tempc\tempd
+      \ %
+    \else
+      %
+      % If we must, put the page number on a line of its own, and fill out
+      % this line with blank space.  (The \hfil is overwhelmed with the
+      % fill leaders glue in \indexdotfill if the page number does fit.)
+      \hfil\penalty50
+      \null\nobreak\indexdotfill % Have leaders before the page number.
+      %
+      % The `\ ' here is removed by the implicit \unskip that TeX does as
+      % part of (the primitive) \par.  Without it, a spurious underfull
+      % \hbox ensues.
+      \ifpdf
+	\pdfgettoks#1.%
+	\ \the\toksA
+      \else
+	\ #1%
+      \fi
+    \fi
+    \par
+  \endgroup
+}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+  \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+\def\secondary#1#2{{%
+  \parfillskip=0in
+  \parskip=0in
+  \hangindent=1in
+  \hangafter=1
+  \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill
+  \ifpdf
+    \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+  \else
+    #2
+  \fi
+  \par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+  % Grab any single-column material above us.
+  \output = {%
+    %
+    % Here is a possibility not foreseen in manmac: if we accumulate a
+    % whole lot of material, we might end up calling this \output
+    % routine twice in a row (see the doublecol-lose test, which is
+    % essentially a couple of indexes with @setchapternewpage off).  In
+    % that case we just ship out what is in \partialpage with the normal
+    % output routine.  Generally, \partialpage will be empty when this
+    % runs and this will be a no-op.  See the indexspread.tex test case.
+    \ifvoid\partialpage \else
+      \onepageout{\pagecontents\partialpage}%
+    \fi
+    %
+    \global\setbox\partialpage = \vbox{%
+      % Unvbox the main output page.
+      \unvbox\PAGE
+      \kern-\topskip \kern\baselineskip
+    }%
+  }%
+  \eject % run that output routine to set \partialpage
+  %
+  % Use the double-column output routine for subsequent pages.
+  \output = {\doublecolumnout}%
+  %
+  % Change the page size parameters.  We could do this once outside this
+  % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+  % format, but then we repeat the same computation.  Repeating a couple
+  % of assignments once per index is clearly meaningless for the
+  % execution time, so we may as well do it in one place.
+  %
+  % First we halve the line length, less a little for the gutter between
+  % the columns.  We compute the gutter based on the line length, so it
+  % changes automatically with the paper format.  The magic constant
+  % below is chosen so that the gutter has the same value (well, +-<1pt)
+  % as it did when we hard-coded it.
+  %
+  % We put the result in a separate register, \doublecolumhsize, so we
+  % can restore it in \pagesofar, after \hsize itself has (potentially)
+  % been clobbered.
+  %
+  \doublecolumnhsize = \hsize
+    \advance\doublecolumnhsize by -.04154\hsize
+    \divide\doublecolumnhsize by 2
+  \hsize = \doublecolumnhsize
+  %
+  % Double the \vsize as well.  (We don't need a separate register here,
+  % since nobody clobbers \vsize.)
+  \vsize = 2\vsize
+}
+
+% The double-column output routine for all double-column pages except
+% the last.
+%
+\def\doublecolumnout{%
+  \splittopskip=\topskip \splitmaxdepth=\maxdepth
+  % Get the available space for the double columns -- the normal
+  % (undoubled) page height minus any material left over from the
+  % previous page.
+  \dimen@ = \vsize
+  \divide\dimen@ by 2
+  \advance\dimen@ by -\ht\partialpage
+  %
+  % box0 will be the left-hand column, box2 the right.
+  \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+  \onepageout\pagesofar
+  \unvbox255
+  \penalty\outputpenalty
+}
+%
+% Re-output the contents of the output page -- any previous material,
+% followed by the two boxes we just split, in box0 and box2.
+\def\pagesofar{%
+  \unvbox\partialpage
+  %
+  \hsize = \doublecolumnhsize
+  \wd0=\hsize \wd2=\hsize
+  \hbox to\pagewidth{\box0\hfil\box2}%
+}
+%
+% All done with double columns.
+\def\enddoublecolumns{%
+  \output = {%
+    % Split the last of the double-column material.  Leave it on the
+    % current page, no automatic page break.
+    \balancecolumns
+    %
+    % If we end up splitting too much material for the current page,
+    % though, there will be another page break right after this \output
+    % invocation ends.  Having called \balancecolumns once, we do not
+    % want to call it again.  Therefore, reset \output to its normal
+    % definition right away.  (We hope \balancecolumns will never be
+    % called on to balance too much material, but if it is, this makes
+    % the output somewhat more palatable.)
+    \global\output = {\onepageout{\pagecontents\PAGE}}%
+  }%
+  \eject
+  \endgroup % started in \begindoublecolumns
+  %
+  % \pagegoal was set to the doubled \vsize above, since we restarted
+  % the current page.  We're now back to normal single-column
+  % typesetting, so reset \pagegoal to the normal \vsize (after the
+  % \endgroup where \vsize got restored).
+  \pagegoal = \vsize
+}
+%
+% Called at the end of the double column material.
+\def\balancecolumns{%
+  \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
+  \dimen@ = \ht0
+  \advance\dimen@ by \topskip
+  \advance\dimen@ by-\baselineskip
+  \divide\dimen@ by 2 % target to split to
+  %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}%
+  \splittopskip = \topskip
+  % Loop until we get a decent breakpoint.
+  {%
+    \vbadness = 10000
+    \loop
+      \global\setbox3 = \copy0
+      \global\setbox1 = \vsplit3 to \dimen@
+    \ifdim\ht3>\dimen@
+      \global\advance\dimen@ by 1pt
+    \repeat
+  }%
+  %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
+  \setbox0=\vbox to\dimen@{\unvbox1}%
+  \setbox2=\vbox to\dimen@{\unvbox3}%
+  %
+  \pagesofar
+}
+\catcode`\@ = \other
+
+
+\message{sectioning,}
+% Chapters, sections, etc.
+
+% \unnumberedno is an oxymoron, of course.  But we count the unnumbered
+% sections so that we can refer to them unambiguously in the pdf
+% outlines by their "section number".  We avoid collisions with chapter
+% numbers by starting them at 10000.  (If a document ever has 10000
+% chapters, we're in trouble anyway, I'm sure.)
+\newcount\unnumberedno \unnumberedno = 10000
+\newcount\chapno
+\newcount\secno        \secno=0
+\newcount\subsecno     \subsecno=0
+\newcount\subsubsecno  \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount\appendixno  \appendixno = `\@
+%
+% \def\appendixletter{\char\the\appendixno}
+% We do the following ugly conditional instead of the above simple
+% construct for the sake of pdftex, which needs the actual
+% letter in the expansion, not just typeset.
+%
+\def\appendixletter{%
+  \ifnum\appendixno=`A A%
+  \else\ifnum\appendixno=`B B%
+  \else\ifnum\appendixno=`C C%
+  \else\ifnum\appendixno=`D D%
+  \else\ifnum\appendixno=`E E%
+  \else\ifnum\appendixno=`F F%
+  \else\ifnum\appendixno=`G G%
+  \else\ifnum\appendixno=`H H%
+  \else\ifnum\appendixno=`I I%
+  \else\ifnum\appendixno=`J J%
+  \else\ifnum\appendixno=`K K%
+  \else\ifnum\appendixno=`L L%
+  \else\ifnum\appendixno=`M M%
+  \else\ifnum\appendixno=`N N%
+  \else\ifnum\appendixno=`O O%
+  \else\ifnum\appendixno=`P P%
+  \else\ifnum\appendixno=`Q Q%
+  \else\ifnum\appendixno=`R R%
+  \else\ifnum\appendixno=`S S%
+  \else\ifnum\appendixno=`T T%
+  \else\ifnum\appendixno=`U U%
+  \else\ifnum\appendixno=`V V%
+  \else\ifnum\appendixno=`W W%
+  \else\ifnum\appendixno=`X X%
+  \else\ifnum\appendixno=`Y Y%
+  \else\ifnum\appendixno=`Z Z%
+  % The \the is necessary, despite appearances, because \appendixletter is
+  % expanded while writing the .toc file.  \char\appendixno is not
+  % expandable, thus it is written literally, thus all appendixes come out
+  % with the same letter (or @) in the toc without it.
+  \else\char\the\appendixno
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it.  @section does likewise.
+% However, they are not reliable, because we don't use marks.
+\def\thischapter{}
+\def\thissection{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% we only have subsub.
+\chardef\maxseclevel = 3
+%
+% A numbered section within an unnumbered changes to unnumbered too.
+% To achive this, remember the "biggest" unnum. sec. we are currently in:
+\chardef\unmlevel = \maxseclevel
+%
+% Trace whether the current chapter is an appendix or not:
+% \chapheadtype is "N" or "A", unnumbered chapters are ignored.
+\def\chapheadtype{N}
+
+% Choose a heading macro
+% #1 is heading type
+% #2 is heading level
+% #3 is text for heading
+\def\genhead#1#2#3{%
+  % Compute the abs. sec. level:
+  \absseclevel=#2
+  \advance\absseclevel by \secbase
+  % Make sure \absseclevel doesn't fall outside the range:
+  \ifnum \absseclevel < 0
+    \absseclevel = 0
+  \else
+    \ifnum \absseclevel > 3
+      \absseclevel = 3
+    \fi
+  \fi
+  % The heading type:
+  \def\headtype{#1}%
+  \if \headtype U%
+    \ifnum \absseclevel < \unmlevel
+      \chardef\unmlevel = \absseclevel
+    \fi
+  \else
+    % Check for appendix sections:
+    \ifnum \absseclevel = 0
+      \edef\chapheadtype{\headtype}%
+    \else
+      \if \headtype A\if \chapheadtype N%
+	\errmessage{@appendix... within a non-appendix chapter}%
+      \fi\fi
+    \fi
+    % Check for numbered within unnumbered:
+    \ifnum \absseclevel > \unmlevel
+      \def\headtype{U}%
+    \else
+      \chardef\unmlevel = 3
+    \fi
+  \fi
+  % Now print the heading:
+  \if \headtype U%
+    \ifcase\absseclevel
+	\unnumberedzzz{#3}%
+    \or \unnumberedseczzz{#3}%
+    \or \unnumberedsubseczzz{#3}%
+    \or \unnumberedsubsubseczzz{#3}%
+    \fi
+  \else
+    \if \headtype A%
+      \ifcase\absseclevel
+	  \appendixzzz{#3}%
+      \or \appendixsectionzzz{#3}%
+      \or \appendixsubseczzz{#3}%
+      \or \appendixsubsubseczzz{#3}%
+      \fi
+    \else
+      \ifcase\absseclevel
+	  \chapterzzz{#3}%
+      \or \seczzz{#3}%
+      \or \numberedsubseczzz{#3}%
+      \or \numberedsubsubseczzz{#3}%
+      \fi
+    \fi
+  \fi
+  \suppressfirstparagraphindent
+}
+
+% an interface:
+\def\numhead{\genhead N}
+\def\apphead{\genhead A}
+\def\unnmhead{\genhead U}
+
+% @chapter, @appendix, @unnumbered.  Increment top-level counter, reset
+% all lower-level sectioning counters to zero.
+%
+% Also set \chaplevelprefix, which we prepend to @float sequence numbers
+% (e.g., figures), q.v.  By default (before any chapter), that is empty.
+\let\chaplevelprefix = \empty
+%
+\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz#1{%
+  % section resetting is \global in case the chapter is in a group, such
+  % as an @include file.
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\chapno by 1
+  %
+  % Used for \float.
+  \gdef\chaplevelprefix{\the\chapno.}%
+  \resetallfloatnos
+  %
+  \message{\putwordChapter\space \the\chapno}%
+  %
+  % Write the actual heading.
+  \chapmacro{#1}{Ynumbered}{\the\chapno}%
+  %
+  % So @section and the like are numbered underneath this chapter.
+  \global\let\section = \numberedsec
+  \global\let\subsection = \numberedsubsec
+  \global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\appendixno by 1
+  \gdef\chaplevelprefix{\appendixletter.}%
+  \resetallfloatnos
+  %
+  \def\appendixnum{\putwordAppendix\space \appendixletter}%
+  \message{\appendixnum}%
+  %
+  \chapmacro{#1}{Yappendix}{\appendixletter}%
+  %
+  \global\let\section = \appendixsec
+  \global\let\subsection = \appendixsubsec
+  \global\let\subsubsection = \appendixsubsubsec
+}
+
+\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\unnumberedno by 1
+  %
+  % Since an unnumbered has no number, no prefix for figures.
+  \global\let\chaplevelprefix = \empty
+  \resetallfloatnos
+  %
+  % This used to be simply \message{#1}, but TeX fully expands the
+  % argument to \message.  Therefore, if #1 contained @-commands, TeX
+  % expanded them.  For example, in `@unnumbered The @cite{Book}', TeX
+  % expanded @cite (which turns out to cause errors because \cite is meant
+  % to be executed, not expanded).
+  %
+  % Anyway, we don't want the fully-expanded definition of @cite to appear
+  % as a result of the \message, we just want `@cite' itself.  We use
+  % \the<toks register> to achieve this: TeX expands \the<toks> only once,
+  % simply yielding the contents of <toks register>.  (We also do this for
+  % the toc entries.)
+  \toks0 = {#1}%
+  \message{(\the\toks0)}%
+  %
+  \chapmacro{#1}{Ynothing}{\the\unnumberedno}%
+  %
+  \global\let\section = \unnumberedsec
+  \global\let\subsection = \unnumberedsubsec
+  \global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\parseargdef\centerchap{%
+  % Well, we could do the following in a group, but that would break
+  % an assumption that \chapmacro is called at the outermost level.
+  % Thus we are safer this way:		--kasal, 24feb04
+  \let\centerparametersmaybe = \centerparameters
+  \unnmhead0{#1}%
+  \let\centerparametersmaybe = \relax
+}
+
+% @top is like @unnumbered.
+\let\top\unnumbered
+
+% Sections.
+\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz
+\def\seczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
+}
+
+\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
+}
+\let\appendixsec\appendixsection
+
+\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}%
+}
+
+% Subsections.
+\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno}%
+}
+
+% Subsubsections.
+\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynumbered}%
+                 {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\let\section = \numberedsec
+\let\subsection = \numberedsubsec
+\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+%       1) We use \vbox rather than the earlier \line to permit
+%          overlong headings to fold.
+%       2) \hyphenpenalty is set to 10000 because hyphenation in a
+%          heading is obnoxious; this forbids it.
+%       3) Likewise, headings look best if no \parindent is used, and
+%          if justification is not attempted.  Hence \raggedright.
+
+
+\def\majorheading{%
+  {\advance\chapheadingskip by 10pt \chapbreak }%
+  \parsearg\chapheadingzzz
+}
+
+\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
+\def\chapheadingzzz#1{%
+  {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                    \parindent=0pt\raggedright
+                    \rm #1\hfill}}%
+  \bigskip \par\penalty 200\relax
+  \suppressfirstparagraphindent
+}
+
+% @heading, @subheading, @subsubheading.
+\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{%
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+% Chapter opening.
+%
+% #1 is the text, #2 is the section type (Ynumbered, Ynothing,
+% Yappendix, Yomitfromtoc), #3 the chapter number.
+%
+% To test against our argument.
+\def\Ynothingkeyword{Ynothing}
+\def\Yomitfromtockeyword{Yomitfromtoc}
+\def\Yappendixkeyword{Yappendix}
+%
+\def\chapmacro#1#2#3{%
+  \pchapsepmacro
+  {%
+    \chapfonts \rm
+    %
+    % Have to define \thissection before calling \donoderef, because the
+    % xref code eventually uses it.  On the other hand, it has to be called
+    % after \pchapsepmacro, or the headline will change too soon.
+    \gdef\thissection{#1}%
+    \gdef\thischaptername{#1}%
+    %
+    % Only insert the separating space if we have a chapter/appendix
+    % number, and don't print the unnumbered ``number''.
+    \def\temptype{#2}%
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unnchap}%
+      \gdef\thischapter{#1}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      \setbox0 = \hbox{}% contents like unnumbered, but no toc entry
+      \def\toctype{omit}%
+      \gdef\thischapter{}%
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
+      \def\toctype{app}%
+      % We don't substitute the actual chapter name into \thischapter
+      % because we don't want its macros evaluated now.  And we don't
+      % use \thissection because that changes with each section.
+      %
+      \xdef\thischapter{\putwordAppendix{} \appendixletter:
+                        \noexpand\thischaptername}%
+    \else
+      \setbox0 = \hbox{#3\enspace}%
+      \def\toctype{numchap}%
+      \xdef\thischapter{\putwordChapter{} \the\chapno:
+                        \noexpand\thischaptername}%
+    \fi\fi\fi
+    %
+    % Write the toc entry for this chapter.  Must come before the
+    % \donoderef, because we include the current node name in the toc
+    % entry, and \donoderef resets it to empty.
+    \writetocentry{\toctype}{#1}{#3}%
+    %
+    % For pdftex, we have to write out the node definition (aka, make
+    % the pdfdest) after any page break, but before the actual text has
+    % been typeset.  If the destination for the pdf outline is after the
+    % text, then jumping from the outline may wind up with the text not
+    % being visible, for instance under high magnification.
+    \donoderef{#2}%
+    %
+    % Typeset the actual heading.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0 \centerparametersmaybe
+          \unhbox0 #1\par}%
+  }%
+  \nobreak\bigskip % no page break after a chapter title
+  \nobreak
+}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerparameters{%
+  \advance\rightskip by 3\rightskip
+  \leftskip = \rightskip
+  \parfillskip = 0pt
+}
+
+
+% I don't think this chapter style is supported any more, so I'm not
+% updating it with the new noderef stuff.  We'll see.  --karl, 11aug03.
+%
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+%
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}\bigskip \par\nobreak
+}
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt
+                       \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+}
+\def\CHAPFopen{%
+  \global\let\chapmacro=\chfopen
+  \global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.  These macros combine the section number parts and
+% call the generic \sectionheading to do the printing.
+%
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
+
+% Subsection titles.
+\newskip\subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
+
+% Subsubsection titles.
+\def\subsubsecheadingskip{\subsecheadingskip}
+\def\subsubsecheadingbreak{\subsecheadingbreak}
+
+
+% Print any size, any type, section title.
+%
+% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is
+% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
+% section number.
+%
+\def\sectionheading#1#2#3#4{%
+  {%
+    % Switch to the right set of fonts.
+    \csname #2fonts\endcsname \rm
+    %
+    % Insert space above the heading.
+    \csname #2headingbreak\endcsname
+    %
+    % Only insert the space after the number if we have a section number.
+    \def\sectionlevel{#2}%
+    \def\temptype{#3}%
+    %
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unn}%
+      \gdef\thissection{#1}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      % for @headings -- no section number, don't include in toc,
+      % and don't redefine \thissection.
+      \setbox0 = \hbox{}%
+      \def\toctype{omit}%
+      \let\sectionlevel=\empty
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{app}%
+      \gdef\thissection{#1}%
+    \else
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{num}%
+      \gdef\thissection{#1}%
+    \fi\fi\fi
+    %
+    % Write the toc entry (before \donoderef).  See comments in \chapmacro.
+    \writetocentry{\toctype\sectionlevel}{#1}{#4}%
+    %
+    % Write the node reference (= pdf destination for pdftex).
+    % Again, see comments in \chapmacro.
+    \donoderef{#3}%
+    %
+    % Interline glue will be inserted when the vbox is completed.
+    % That glue will be a valid breakpoint for the page, since it'll be
+    % preceded by a whatsit (usually from the \donoderef, or from the
+    % \writetocentry if there was no node).  We don't want to allow that
+    % break, since then the whatsits could end up on page n while the
+    % section is on page n+1, thus toc/etc. are wrong.  Debian bug 276000.
+    \nobreak
+    %
+    % Output the actual section heading.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0  % zero if no section number
+          \unhbox0 #1}%
+  }%
+  % Add extra space after the heading -- half of whatever came above it.
+  % Don't allow stretch, though.
+  \kern .5 \csname #2headingskip\endcsname
+  %
+  % Do not let the kern be a potential breakpoint, as it would be if it
+  % was followed by glue.
+  \nobreak
+  %
+  % We'll almost certainly start a paragraph next, so don't let that
+  % glue accumulate.  (Not a breakpoint because it's preceded by a
+  % discardable item.)
+  \vskip-\parskip
+  % 
+  % This is purely so the last item on the list is a known \penalty >
+  % 10000.  This is so \startdefun can avoid allowing breakpoints after
+  % section headings.  Otherwise, it would insert a valid breakpoint between:
+  % 
+  %   @section sec-whatever
+  %   @deffn def-whatever
+  \penalty 10001
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc.
+%
+% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno}
+% We append the current node name (if any) and page number as additional
+% arguments for the \{chap,sec,...}entry macros which will eventually
+% read this.  The node name is used in the pdf outlines as the
+% destination to jump to.
+%
+% We open the .toc file for writing here instead of at @setfilename (or
+% any other fixed time) so that @contents can be anywhere in the document.
+% But if #1 is `omit', then we don't do anything.  This is used for the
+% table of contents chapter openings themselves.
+%
+\newif\iftocfileopened
+\def\omitkeyword{omit}%
+%
+\def\writetocentry#1#2#3{%
+  \edef\writetoctype{#1}%
+  \ifx\writetoctype\omitkeyword \else
+    \iftocfileopened\else
+      \immediate\openout\tocfile = \jobname.toc
+      \global\tocfileopenedtrue
+    \fi
+    %
+    \iflinks
+      {\atdummies
+       \edef\temp{%
+         \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}%
+       \temp
+      }%
+    \fi
+  \fi
+  %
+  % Tell \shipout to create a pdf destination on each page, if we're
+  % writing pdf.  These are used in the table of contents.  We can't
+  % just write one on every page because the title pages are numbered
+  % 1 and 2 (the page numbers aren't printed), and so are the first
+  % two pages of the document.  Thus, we'd have two destinations named
+  % `1', and two named `2'.
+  \ifpdf \global\pdfmakepagedesttrue \fi
+}
+
+
+% These characters do not print properly in the Computer Modern roman
+% fonts, so we must take special care.  This is more or less redundant
+% with the Texinfo input format setup at the end of this file.
+% 
+\def\activecatcodes{%
+  \catcode`\"=\active
+  \catcode`\$=\active
+  \catcode`\<=\active
+  \catcode`\>=\active
+  \catcode`\\=\active
+  \catcode`\^=\active
+  \catcode`\_=\active
+  \catcode`\|=\active
+  \catcode`\~=\active
+}
+
+
+% Read the toc file, which is essentially Texinfo input.
+\def\readtocfile{%
+  \setupdatafile
+  \activecatcodes
+  \input \jobname.toc
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Prepare to read what we've written to \tocfile.
+%
+\def\startcontents#1{%
+  % If @setchapternewpage on, and @headings double, the contents should
+  % start on an odd page, unlike chapters.  Thus, we maintain
+  % \contentsalignmacro in parallel with \pagealignmacro.
+  % From: Torbjorn Granlund <tege@matematik.su.se>
+  \contentsalignmacro
+  \immediate\closeout\tocfile
+  %
+  % Don't need to put `Contents' or `Short Contents' in the headline.
+  % It is abundantly clear what they are.
+  \def\thischapter{}%
+  \chapmacro{#1}{Yomitfromtoc}{}%
+  %
+  \savepageno = \pageno
+  \begingroup                  % Set up to handle contents files properly.
+    \raggedbottom              % Worry more about breakpoints than the bottom.
+    \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+    %
+    % Roman numerals for page numbers.
+    \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
+}
+
+
+% Normal (long) toc.
+\def\contents{%
+  \startcontents{\putwordTOC}%
+    \openin 1 \jobname.toc
+    \ifeof 1 \else
+      \readtocfile
+    \fi
+    \vfill \eject
+    \contentsalignmacro % in case @setchapternewpage odd is in effect
+    \ifeof 1 \else
+      \pdfmakeoutlines
+    \fi
+    \closein 1
+  \endgroup
+  \lastnegativepageno = \pageno
+  \global\pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+  \startcontents{\putwordShortTOC}%
+    %
+    \let\numchapentry = \shortchapentry
+    \let\appentry = \shortchapentry
+    \let\unnchapentry = \shortunnchapentry
+    % We want a true roman here for the page numbers.
+    \secfonts
+    \let\rm=\shortcontrm \let\bf=\shortcontbf
+    \let\sl=\shortcontsl \let\tt=\shortconttt
+    \rm
+    \hyphenpenalty = 10000
+    \advance\baselineskip by 1pt % Open it up a little.
+    \def\numsecentry##1##2##3##4{}
+    \let\appsecentry = \numsecentry
+    \let\unnsecentry = \numsecentry
+    \let\numsubsecentry = \numsecentry
+    \let\appsubsecentry = \numsecentry
+    \let\unnsubsecentry = \numsecentry
+    \let\numsubsubsecentry = \numsecentry
+    \let\appsubsubsecentry = \numsecentry
+    \let\unnsubsubsecentry = \numsecentry
+    \openin 1 \jobname.toc
+    \ifeof 1 \else
+      \readtocfile
+    \fi
+    \closein 1
+    \vfill \eject
+    \contentsalignmacro % in case @setchapternewpage odd is in effect
+  \endgroup
+  \lastnegativepageno = \pageno
+  \global\pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g., `A' for an appendix, or `3' for a chapter.
+%
+\def\shortchaplabel#1{%
+  % This space should be enough, since a single number is .5em, and the
+  % widest letter (M) is 1em, at least in the Computer Modern fonts.
+  % But use \hss just in case.
+  % (This space doesn't include the extra space that gets added after
+  % the label; that gets put in by \shortchapentry above.)
+  %
+  % We'd like to right-justify chapter numbers, but that looks strange
+  % with appendix letters.  And right-justifying numbers and
+  % left-justifying letters looks strange when there is less than 10
+  % chapters.  Have to read the whole toc once to know how many chapters
+  % there are before deciding ...
+  \hbox to 1em{#1\hss}%
+}
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapters, in the main contents.
+\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}}
+%
+% Chapters, in the short toc.
+% See comments in \dochapentry re vbox and related settings.
+\def\shortchapentry#1#2#3#4{%
+  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}%
+}
+
+% Appendices, in the main contents.
+% Need the word Appendix, and a fixed-size box.
+%
+\def\appendixbox#1{%
+  % We use M since it's probably the widest letter.
+  \setbox0 = \hbox{\putwordAppendix{} M}%
+  \hbox to \wd0{\putwordAppendix{} #1\hss}}
+%
+\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}}
+
+% Unnumbered chapters.
+\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}}
+\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}}
+
+% Sections.
+\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}}
+\let\appsecentry=\numsecentry
+\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}}
+
+% Subsections.
+\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsecentry=\numsubsecentry
+\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}}
+
+% And subsubsections.
+\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsubsecentry=\numsubsubsecentry
+\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}}
+
+% This parameter controls the indentation of the various levels.
+% Same as \defaultparindent.
+\newdimen\tocindent \tocindent = 15pt
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+   \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+   \begingroup
+     \chapentryfonts
+     \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+   \endgroup
+   \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+  \secentryfonts \leftskip=\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+  \subsecentryfonts \leftskip=2\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+  \subsubsecentryfonts \leftskip=3\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+% We use the same \entry macro as for the index entries.
+\let\tocentry = \entry
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\def\subsecentryfonts{\textfonts}
+\def\subsubsecentryfonts{\textfonts}
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+%
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% The @error{} command.
+% Adapted from the TeXbook's \boxit.
+%
+\newbox\errorbox
+%
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+%
+\setbox\errorbox=\hbox to \dimen0{\hfil
+   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+   \advance\hsize by -2\dimen2 % Rules.
+   \vbox{%
+      \hrule height\dimen2
+      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
+         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+         \kern3pt\vrule width\dimen2}% Space to right.
+      \hrule height\dimen2}
+    \hfil}
+%
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex    escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\envdef\tex{%
+  \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+  \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+  \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
+  \catcode `\%=14
+  \catcode `\+=\other
+  \catcode `\"=\other
+  \catcode `\|=\other
+  \catcode `\<=\other
+  \catcode `\>=\other
+  \escapechar=`\\
+  %
+  \let\b=\ptexb
+  \let\bullet=\ptexbullet
+  \let\c=\ptexc
+  \let\,=\ptexcomma
+  \let\.=\ptexdot
+  \let\dots=\ptexdots
+  \let\equiv=\ptexequiv
+  \let\!=\ptexexclam
+  \let\i=\ptexi
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \let\{=\ptexlbrace
+  \let\+=\tabalign
+  \let\}=\ptexrbrace
+  \let\/=\ptexslash
+  \let\*=\ptexstar
+  \let\t=\ptext
+  \let\frenchspacing=\plainfrenchspacing
+  %
+  \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+  \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+  \def\@{@}%
+}
+% There is no need to define \Etex.
+
+% Define @lisp ... @end lisp.
+% @lisp environment forms a group so it can rebind things,
+% including the definition of @end lisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments.  \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical.  We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip.
+%
+\def\aboveenvbreak{{%
+  % =10000 instead of <10000 because of a special case in \itemzzz and
+  % \sectionheading, q.v.
+  \ifnum \lastpenalty=10000 \else
+    \advance\envskipamount by \parskip
+    \endgraf
+    \ifdim\lastskip<\envskipamount
+      \removelastskip
+      % it's not a good place to break if the last penalty was \nobreak
+      % or better ...
+      \ifnum\lastpenalty<10000 \penalty-50 \fi
+      \vskip\envskipamount
+    \fi
+  \fi
+}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins; it will
+% also clear it, so that its embedded environments do the narrowing again.
+\let\nonarrowing=\relax
+
+% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
+% environment contents.
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+        \ctl\leaders\hrule height\circthick\hfil\ctr
+        \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+        \cbl\leaders\hrule height\circthick\hfil\cbr
+        \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\envdef\cartouche{%
+  \ifhmode\par\fi  % can't be in the midst of a paragraph.
+  \startsavinginserts
+  \lskip=\leftskip \rskip=\rightskip
+  \leftskip=0pt\rightskip=0pt % we want these *outside*.
+  \cartinner=\hsize \advance\cartinner by-\lskip
+  \advance\cartinner by-\rskip
+  \cartouter=\hsize
+  \advance\cartouter by 18.4pt	% allow for 3pt kerns on either
+				% side, and for 6pt waste from
+				% each corner char, and rule thickness
+  \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+  % Flag to tell @lisp, etc., not to narrow margin.
+  \let\nonarrowing = t%
+  \vbox\bgroup
+      \baselineskip=0pt\parskip=0pt\lineskip=0pt
+      \carttop
+      \hbox\bgroup
+	  \hskip\lskip
+	  \vrule\kern3pt
+	  \vbox\bgroup
+	      \kern3pt
+	      \hsize=\cartinner
+	      \baselineskip=\normbskip
+	      \lineskip=\normlskip
+	      \parskip=\normpskip
+	      \vskip -\parskip
+	      \comment % For explanation, see the end of \def\group.
+}
+\def\Ecartouche{%
+              \ifhmode\par\fi
+	      \kern3pt
+	  \egroup
+	  \kern3pt\vrule
+	  \hskip\rskip
+      \egroup
+      \cartbot
+  \egroup
+  \checkinserts
+}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+  \aboveenvbreak
+  \hfuzz = 12pt % Don't be fussy
+  \sepspaces % Make spaces be word-separators rather than space tokens.
+  \let\par = \lisppar % don't ignore blank lines
+  \obeylines % each line of input is a line of output
+  \parskip = 0pt
+  \parindent = 0pt
+  \emergencystretch = 0pt % don't try to avoid overfull boxes
+  \ifx\nonarrowing\relax
+    \advance \leftskip by \lispnarrowing
+    \exdentamount=\lispnarrowing
+  \else
+    \let\nonarrowing = \relax
+  \fi
+  \let\exdent=\nofillexdent
+}
+
+% If you want all examples etc. small: @set dispenvsize small.
+% If you want even small examples the full size: @set dispenvsize nosmall.
+% This affects the following displayed environments:
+%    @example, @display, @format, @lisp
+%
+\def\smallword{small}
+\def\nosmallword{nosmall}
+\let\SETdispenvsize\relax
+\def\setnormaldispenv{%
+  \ifx\SETdispenvsize\smallword
+    \smallexamplefonts \rm
+  \fi
+}
+\def\setsmalldispenv{%
+  \ifx\SETdispenvsize\nosmallword
+  \else
+    \smallexamplefonts \rm
+  \fi
+}
+
+% We often define two environments, @foo and @smallfoo.
+% Let's do it by one command:
+\def\makedispenv #1#2{
+  \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}
+  \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}
+  \expandafter\let\csname E#1\endcsname \afterenvbreak
+  \expandafter\let\csname Esmall#1\endcsname \afterenvbreak
+}
+
+% Define two synonyms:
+\def\maketwodispenvs #1#2#3{
+  \makedispenv{#1}{#3}
+  \makedispenv{#2}{#3}
+}
+
+% @lisp: indented, narrowed, typewriter font; @example: same as @lisp.
+%
+% @smallexample and @smalllisp: use smaller fonts.
+% Originally contributed by Pavel@xerox.
+%
+\maketwodispenvs {lisp}{example}{%
+  \nonfillstart
+  \tt
+  \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+  \gobble       % eat return
+}
+
+% @display/@smalldisplay: same as @lisp except keep current font.
+%
+\makedispenv {display}{%
+  \nonfillstart
+  \gobble
+}
+
+% @format/@smallformat: same as @display except don't narrow margins.
+%
+\makedispenv{format}{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \gobble
+}
+
+% @flushleft: same as @format, but doesn't obey \SETdispenvsize.
+\envdef\flushleft{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \gobble
+}
+\let\Eflushleft = \afterenvbreak
+
+% @flushright.
+%
+\envdef\flushright{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \advance\leftskip by 0pt plus 1fill
+  \gobble
+}
+\let\Eflushright = \afterenvbreak
+
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.  We keep \parskip nonzero in general, since
+% we're doing normal filling.  So, when using \aboveenvbreak and
+% \afterenvbreak, temporarily make \parskip 0.
+%
+\envdef\quotation{%
+  {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+  \parindent=0pt
+  %
+  % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+  \ifx\nonarrowing\relax
+    \advance\leftskip by \lispnarrowing
+    \advance\rightskip by \lispnarrowing
+    \exdentamount = \lispnarrowing
+  \else
+    \let\nonarrowing = \relax
+  \fi
+  \parsearg\quotationlabel
+}
+
+% We have retained a nonzero parskip for the environment, since we're
+% doing normal filling.
+%
+\def\Equotation{%
+  \par
+  \ifx\quotationauthor\undefined\else
+    % indent a bit.
+    \leftline{\kern 2\leftskip \sl ---\quotationauthor}%
+  \fi
+  {\parskip=0pt \afterenvbreak}%
+}
+
+% If we're given an argument, typeset it in bold with a colon after.
+\def\quotationlabel#1{%
+  \def\temp{#1}%
+  \ifx\temp\empty \else
+    {\bf #1: }%
+  \fi
+}
+
+
+% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>}
+% If we want to allow any <char> as delimiter,
+% we need the curly braces so that makeinfo sees the @verb command, eg:
+% `@verbx...x' would look like the '@verbx' command.  --janneke@gnu.org
+%
+% [Knuth]: Donald Ervin Knuth, 1996.  The TeXbook.
+%
+% [Knuth] p.344; only we need to do the other characters Texinfo sets
+% active too.  Otherwise, they get lost as the first character on a
+% verbatim line.
+\def\dospecials{%
+  \do\ \do\\\do\{\do\}\do\$\do\&%
+  \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
+  \do\<\do\>\do\|\do\@\do+\do\"%
+}
+%
+% [Knuth] p. 380
+\def\uncatcodespecials{%
+  \def\do##1{\catcode`##1=\other}\dospecials}
+%
+% [Knuth] pp. 380,381,391
+% Disable Spanish ligatures ?` and !` of \tt font
+\begingroup
+  \catcode`\`=\active\gdef`{\relax\lq}
+\endgroup
+%
+% Setup for the @verb command.
+%
+% Eight spaces for a tab
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }}
+\endgroup
+%
+\def\setupverb{%
+  \tt  % easiest (and conventionally used) font for verbatim
+  \def\par{\leavevmode\endgraf}%
+  \catcode`\`=\active
+  \tabeightspaces
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+}
+
+% Setup for the @verbatim environment
+%
+% Real tab expansion
+\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
+%
+\def\starttabbox{\setbox0=\hbox\bgroup}
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabexpand{%
+    \catcode`\^^I=\active
+    \def^^I{\leavevmode\egroup
+      \dimen0=\wd0 % the width so far, or since the previous tab
+      \divide\dimen0 by\tabw
+      \multiply\dimen0 by\tabw % compute previous multiple of \tabw
+      \advance\dimen0 by\tabw  % advance to next multiple of \tabw
+      \wd0=\dimen0 \box0 \starttabbox
+    }%
+  }
+\endgroup
+\def\setupverbatim{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  % Easiest (and conventionally used) font for verbatim
+  \tt
+  \def\par{\leavevmode\egroup\box0\endgraf}%
+  \catcode`\`=\active
+  \tabexpand
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+  \everypar{\starttabbox}%
+}
+
+% Do the @verb magic: verbatim text is quoted by unique
+% delimiter characters.  Before first delimiter expect a
+% right brace, after last delimiter expect closing brace:
+%
+%    \def\doverb'{'<char>#1<char>'}'{#1}
+%
+% [Knuth] p. 382; only eat outer {}
+\begingroup
+  \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other
+  \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next]
+\endgroup
+%
+\def\verb{\begingroup\setupverb\doverb}
+%
+%
+% Do the @verbatim magic: define the macro \doverbatim so that
+% the (first) argument ends when '@end verbatim' is reached, ie:
+%
+%     \def\doverbatim#1@end verbatim{#1}
+%
+% For Texinfo it's a lot easier than for LaTeX,
+% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
+% we need not redefine '\', '{' and '}'.
+%
+% Inspired by LaTeX's verbatim command set [latex.ltx]
+%
+\begingroup
+  \catcode`\ =\active
+  \obeylines %
+  % ignore everything up to the first ^^M, that's the newline at the end
+  % of the @verbatim input line itself.  Otherwise we get an extra blank
+  % line in the output.
+  \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}%
+  % We really want {...\end verbatim} in the body of the macro, but
+  % without the active space; thus we have to use \xdef and \gobble.
+\endgroup
+%
+\envdef\verbatim{%
+    \setupverbatim\doverbatim
+}
+\let\Everbatim = \afterenvbreak
+
+
+% @verbatiminclude FILE - insert text of file in verbatim environment.
+%
+\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude}
+%
+\def\doverbatiminclude#1{%
+  {%
+    \makevalueexpandable
+    \setupverbatim
+    \input #1
+    \afterenvbreak
+  }%
+}
+
+% @copying ... @end copying.
+% Save the text away for @insertcopying later.
+%
+% We save the uninterpreted tokens, rather than creating a box.
+% Saving the text in a box would be much easier, but then all the
+% typesetting commands (@smallbook, font changes, etc.) have to be done
+% beforehand -- and a) we want @copying to be done first in the source
+% file; b) letting users define the frontmatter in as flexible order as
+% possible is very desirable.
+%
+\def\copying{\checkenv{}\begingroup\scanargctxt\docopying}
+\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}}
+%
+\def\insertcopying{%
+  \begingroup
+    \parindent = 0pt  % paragraph indentation looks wrong on title page
+    \scanexp\copyingtext
+  \endgroup
+}
+
+\message{defuns,}
+% @defun etc.
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+% Start the processing of @deffn:
+\def\startdefun{%
+  \ifnum\lastpenalty<10000
+    \medbreak
+  \else
+    % If there are two @def commands in a row, we'll have a \nobreak,
+    % which is there to keep the function description together with its
+    % header.  But if there's nothing but headers, we need to allow a
+    % break somewhere.  Check specifically for penalty 10002, inserted
+    % by \defargscommonending, instead of 10000, since the sectioning
+    % commands also insert a nobreak penalty, and we don't want to allow
+    % a break between a section heading and a defun.
+    % 
+    \ifnum\lastpenalty=10002 \penalty2000 \fi
+    %
+    % Similarly, after a section heading, do not allow a break.
+    % But do insert the glue.
+    \medskip  % preceded by discardable penalty, so not a breakpoint
+  \fi
+  %
+  \parindent=0in
+  \advance\leftskip by \defbodyindent
+  \exdentamount=\defbodyindent
+}
+
+\def\dodefunx#1{%
+  % First, check whether we are in the right environment:
+  \checkenv#1%
+  %
+  % As above, allow line break if we have multiple x headers in a row.
+  % It's not a great place, though.
+  \ifnum\lastpenalty=10002 \penalty3000 \fi
+  %
+  % And now, it's time to reuse the body of the original defun:
+  \expandafter\gobbledefun#1%
+}
+\def\gobbledefun#1\startdefun{}
+
+% \printdefunline \deffnheader{text}
+%
+\def\printdefunline#1#2{%
+  \begingroup
+    % call \deffnheader:
+    #1#2 \endheader
+    % common ending:
+    \interlinepenalty = 10000
+    \advance\rightskip by 0pt plus 1fil
+    \endgraf
+    \nobreak\vskip -\parskip
+    \penalty 10002  % signal to \startdefun and \dodefunx
+    % Some of the @defun-type tags do not enable magic parentheses,
+    % rendering the following check redundant.  But we don't optimize.
+    \checkparencounts
+  \endgroup
+}
+
+\def\Edefun{\endgraf\medbreak}
+
+% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn;
+% the only thing remainnig is to define \deffnheader.
+%
+\def\makedefun#1{%
+  \expandafter\let\csname E#1\endcsname = \Edefun
+  \edef\temp{\noexpand\domakedefun
+    \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}%
+  \temp
+}
+
+% \domakedefun \deffn \deffnx \deffnheader
+%
+% Define \deffn and \deffnx, without parameters.
+% \deffnheader has to be defined explicitly.
+%
+\def\domakedefun#1#2#3{%
+  \envdef#1{%
+    \startdefun
+    \parseargusing\activeparens{\printdefunline#3}%
+  }%
+  \def#2{\dodefunx#1}%
+  \def#3%
+}
+
+%%% Untyped functions:
+
+% @deffn category name args
+\makedefun{deffn}{\deffngeneral{}}
+
+% @deffn category class name args
+\makedefun{defop}#1 {\defopon{#1\ \putwordon}}
+
+% \defopon {category on}class name args
+\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deffngeneral {subind}category name args
+%
+\def\deffngeneral#1#2 #3 #4\endheader{%
+  % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}.
+  \dosubind{fn}{\code{#3}}{#1}%
+  \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}%
+}
+
+%%% Typed functions:
+
+% @deftypefn category type name args
+\makedefun{deftypefn}{\deftypefngeneral{}}
+
+% @deftypeop category class type name args
+\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}}
+
+% \deftypeopon {category on}class type name args
+\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypefngeneral {subind}category type name args
+%
+\def\deftypefngeneral#1#2 #3 #4 #5\endheader{%
+  \dosubind{fn}{\code{#4}}{#1}%
+  \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Typed variables:
+
+% @deftypevr category type var args
+\makedefun{deftypevr}{\deftypecvgeneral{}}
+
+% @deftypecv category class type var args
+\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}}
+
+% \deftypecvof {category of}class type var args
+\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypecvgeneral {subind}category type var args
+%
+\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{%
+  \dosubind{vr}{\code{#4}}{#1}%
+  \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Untyped variables:
+
+% @defvr category var args
+\makedefun{defvr}#1 {\deftypevrheader{#1} {} }
+
+% @defcv category class var args
+\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}}
+
+% \defcvof {category of}class var args
+\def\defcvof#1#2 {\deftypecvof{#1}#2 {} }
+
+%%% Type:
+% @deftp category name args
+\makedefun{deftp}#1 #2 #3\endheader{%
+  \doind{tp}{\code{#2}}%
+  \defname{#1}{}{#2}\defunargs{#3\unskip}%
+}
+
+% Remaining @defun-like shortcuts:
+\makedefun{defun}{\deffnheader{\putwordDeffunc} }
+\makedefun{defmac}{\deffnheader{\putwordDefmac} }
+\makedefun{defspec}{\deffnheader{\putwordDefspec} }
+\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} }
+\makedefun{defvar}{\defvrheader{\putwordDefvar} }
+\makedefun{defopt}{\defvrheader{\putwordDefopt} }
+\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} }
+\makedefun{defmethod}{\defopon\putwordMethodon}
+\makedefun{deftypemethod}{\deftypeopon\putwordMethodon}
+\makedefun{defivar}{\defcvof\putwordInstanceVariableof}
+\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof}
+
+% \defname, which formats the name of the @def (not the args).
+% #1 is the category, such as "Function".
+% #2 is the return type, if any.
+% #3 is the function name.
+%
+% We are followed by (but not passed) the arguments, if any.
+%
+\def\defname#1#2#3{%
+  % Get the values of \leftskip and \rightskip as they were outside the @def...
+  \advance\leftskip by -\defbodyindent
+  %
+  % How we'll format the type name.  Putting it in brackets helps
+  % distinguish it from the body text that may end up on the next line
+  % just below it.
+  \def\temp{#1}%
+  \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi}
+  %
+  % Figure out line sizes for the paragraph shape.
+  % The first line needs space for \box0; but if \rightskip is nonzero,
+  % we need only space for the part of \box0 which exceeds it:
+  \dimen0=\hsize  \advance\dimen0 by -\wd0  \advance\dimen0 by \rightskip
+  % The continuations:
+  \dimen2=\hsize  \advance\dimen2 by -\defargsindent
+  % (plain.tex says that \dimen1 should be used only as global.)
+  \parshape 2 0in \dimen0 \defargsindent \dimen2
+  %
+  % Put the type name to the right margin.
+  \noindent
+  \hbox to 0pt{%
+    \hfil\box0 \kern-\hsize
+    % \hsize has to be shortened this way:
+    \kern\leftskip
+    % Intentionally do not respect \rightskip, since we need the space.
+  }%
+  %
+  % Allow all lines to be underfull without complaint:
+  \tolerance=10000 \hbadness=10000
+  \exdentamount=\defbodyindent
+  {%
+    % defun fonts. We use typewriter by default (used to be bold) because:
+    % . we're printing identifiers, they should be in tt in principle.
+    % . in languages with many accents, such as Czech or French, it's
+    %   common to leave accents off identifiers.  The result looks ok in
+    %   tt, but exceedingly strange in rm.
+    % . we don't want -- and --- to be treated as ligatures.
+    % . this still does not fix the ?` and !` ligatures, but so far no
+    %   one has made identifiers using them :).
+    \df \tt
+    \def\temp{#2}% return value type
+    \ifx\temp\empty\else \tclose{\temp} \fi
+    #3% output function name
+  }%
+  {\rm\enskip}% hskip 0.5 em of \tenrm
+  %
+  \boldbrax
+  % arguments will be output next, if any.
+}
+
+% Print arguments in slanted roman (not ttsl), inconsistently with using
+% tt for the name.  This is because literal text is sometimes needed in
+% the argument list (groff manual), and ttsl and tt are not very
+% distinguishable.  Prevent hyphenation at `-' chars.
+%
+\def\defunargs#1{%
+  % use sl by default (not ttsl),
+  % tt for the names.
+  \df \sl \hyphenchar\font=0
+  %
+  % On the other hand, if an argument has two dashes (for instance), we
+  % want a way to get ttsl.  Let's try @var for that.
+  \let\var=\ttslanted
+  #1%
+  \sl\hyphenchar\font=45
+}
+
+% We want ()&[] to print specially on the defun line.
+%
+\def\activeparens{%
+  \catcode`\(=\active \catcode`\)=\active
+  \catcode`\[=\active \catcode`\]=\active
+  \catcode`\&=\active
+}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+% Be sure that we always have a definition for `(', etc.  For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+{
+  \activeparens
+  \global\let(=\lparen \global\let)=\rparen
+  \global\let[=\lbrack \global\let]=\rbrack
+  \global\let& = \&
+
+  \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+  \gdef\magicamp{\let&=\amprm}
+}
+
+\newcount\parencount
+
+% If we encounter &foo, then turn on ()-hacking afterwards
+\newif\ifampseen
+\def\amprm#1 {\ampseentrue{\bf\ }}
+
+\def\parenfont{%
+  \ifampseen
+    % At the first level, print parens in roman,
+    % otherwise use the default font.
+    \ifnum \parencount=1 \rm \fi
+  \else
+    % The \sf parens (in \boldbrax) actually are a little bolder than
+    % the contained text.  This is especially needed for [ and ] .
+    \sf
+  \fi
+}
+\def\infirstlevel#1{%
+  \ifampseen
+    \ifnum\parencount=1
+      #1%
+    \fi
+  \fi
+}
+\def\bfafterword#1 {#1 \bf}
+
+\def\opnr{%
+  \global\advance\parencount by 1
+  {\parenfont(}%
+  \infirstlevel \bfafterword
+}
+\def\clnr{%
+  {\parenfont)}%
+  \infirstlevel \sl
+  \global\advance\parencount by -1
+}
+
+\newcount\brackcount
+\def\lbrb{%
+  \global\advance\brackcount by 1
+  {\bf[}%
+}
+\def\rbrb{%
+  {\bf]}%
+  \global\advance\brackcount by -1
+}
+
+\def\checkparencounts{%
+  \ifnum\parencount=0 \else \badparencount \fi
+  \ifnum\brackcount=0 \else \badbrackcount \fi
+}
+\def\badparencount{%
+  \errmessage{Unbalanced parentheses in @def}%
+  \global\parencount=0
+}
+\def\badbrackcount{%
+  \errmessage{Unbalanced square braces in @def}%
+  \global\brackcount=0
+}
+
+
+\message{macros,}
+% @macro.
+
+% To do this right we need a feature of e-TeX, \scantokens,
+% which we arrange to emulate with a temporary file in ordinary TeX.
+\ifx\eTeXversion\undefined
+  \newwrite\macscribble
+  \def\scantokens#1{%
+    \toks0={#1}%
+    \immediate\openout\macscribble=\jobname.tmp
+    \immediate\write\macscribble{\the\toks0}%
+    \immediate\closeout\macscribble
+    \input \jobname.tmp
+  }
+\fi
+
+\def\scanmacro#1{%
+  \begingroup
+    \newlinechar`\^^M
+    \let\xeatspaces\eatspaces
+    % Undo catcode changes of \startcontents and \doprintindex
+    % When called from @insertcopying or (short)caption, we need active
+    % backslash to get it printed correctly.  Previously, we had
+    % \catcode`\\=\other instead.  We'll see whether a problem appears
+    % with macro expansion.				--kasal, 19aug04
+    \catcode`\@=0 \catcode`\\=\active \escapechar=`\@
+    % ... and \example
+    \spaceisspace
+    %
+    % Append \endinput to make sure that TeX does not see the ending newline.
+    %
+    % I've verified that it is necessary both for e-TeX and for ordinary TeX
+    %							--kasal, 29nov03
+    \scantokens{#1\endinput}%
+  \endgroup
+}
+
+\def\scanexp#1{%
+  \edef\temp{\noexpand\scanmacro{#1}}%
+  \temp
+}
+
+\newcount\paramno   % Count of parameters
+\newtoks\macname    % Macro name
+\newif\ifrecursive  % Is it recursive?
+
+% List of all defined macros in the form
+%    \definedummyword\macro1\definedummyword\macro2...
+% Currently is also contains all @aliases; the list can be split
+% if there is a need.
+\def\macrolist{}
+
+% Add the macro to \macrolist
+\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname}
+\def\addtomacrolistxxx#1{%
+     \toks0 = \expandafter{\macrolist\definedummyword#1}%
+     \xdef\macrolist{\the\toks0}%
+}
+
+% Utility routines.
+% This does \let #1 = #2, with \csnames; that is,
+%   \let \csname#1\endcsname = \csname#2\endcsname
+% (except of course we have to play expansion games).
+% 
+\def\cslet#1#2{%
+  \expandafter\let
+  \csname#1\expandafter\endcsname
+  \csname#2\endcsname
+}
+
+% Trim leading and trailing spaces off a string.
+% Concepts from aro-bend problem 15 (see CTAN).
+{\catcode`\@=11
+\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
+\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+\def\unbrace#1{#1}
+\unbrace{\gdef\trim@@@ #1 } #2@{#1}
+}
+
+% Trim a single trailing ^^M off a string.
+{\catcode`\^^M=\other \catcode`\Q=3%
+\gdef\eatcr #1{\eatcra #1Q^^MQ}%
+\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
+\gdef\eatcrb#1Q#2Q{#1}%
+}
+
+% Macro bodies are absorbed as an argument in a context where
+% all characters are catcode 10, 11 or 12, except \ which is active
+% (as in normal texinfo). It is necessary to change the definition of \.
+
+% It's necessary to have hard CRs when the macro is executed. This is
+% done by  making ^^M (\endlinechar) catcode 12 when reading the macro
+% body, and then making it the \newlinechar in \scanmacro.
+
+\def\scanctxt{%
+  \catcode`\"=\other
+  \catcode`\+=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\@=\other
+  \catcode`\^=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\~=\other
+}
+
+\def\scanargctxt{%
+  \scanctxt
+  \catcode`\\=\other
+  \catcode`\^^M=\other
+}
+
+\def\macrobodyctxt{%
+  \scanctxt
+  \catcode`\{=\other
+  \catcode`\}=\other
+  \catcode`\^^M=\other
+  \usembodybackslash
+}
+
+\def\macroargctxt{%
+  \scanctxt
+  \catcode`\\=\other
+}
+
+% \mbodybackslash is the definition of \ in @macro bodies.
+% It maps \foo\ => \csname macarg.foo\endcsname => #N
+% where N is the macro parameter number.
+% We define \csname macarg.\endcsname to be \realbackslash, so
+% \\ in macro replacement text gets you a backslash.
+
+{\catcode`@=0 @catcode`@\=@active
+ @gdef@usembodybackslash{@let\=@mbodybackslash}
+ @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
+}
+\expandafter\def\csname macarg.\endcsname{\realbackslash}
+
+\def\macro{\recursivefalse\parsearg\macroxxx}
+\def\rmacro{\recursivetrue\parsearg\macroxxx}
+
+\def\macroxxx#1{%
+  \getargs{#1}%           now \macname is the macname and \argl the arglist
+  \ifx\argl\empty       % no arguments
+     \paramno=0%
+  \else
+     \expandafter\parsemargdef \argl;%
+  \fi
+  \if1\csname ismacro.\the\macname\endcsname
+     \message{Warning: redefining \the\macname}%
+  \else
+     \expandafter\ifx\csname \the\macname\endcsname \relax
+     \else \errmessage{Macro name \the\macname\space already defined}\fi
+     \global\cslet{macsave.\the\macname}{\the\macname}%
+     \global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
+     \addtomacrolist{\the\macname}%
+  \fi
+  \begingroup \macrobodyctxt
+  \ifrecursive \expandafter\parsermacbody
+  \else \expandafter\parsemacbody
+  \fi}
+
+\parseargdef\unmacro{%
+  \if1\csname ismacro.#1\endcsname
+    \global\cslet{#1}{macsave.#1}%
+    \global\expandafter\let \csname ismacro.#1\endcsname=0%
+    % Remove the macro name from \macrolist:
+    \begingroup
+      \expandafter\let\csname#1\endcsname \relax
+      \let\definedummyword\unmacrodo
+      \xdef\macrolist{\macrolist}%
+    \endgroup
+  \else
+    \errmessage{Macro #1 not defined}%
+  \fi
+}
+
+% Called by \do from \dounmacro on each macro.  The idea is to omit any
+% macro definitions that have been changed to \relax.
+%
+\def\unmacrodo#1{%
+  \ifx #1\relax
+    % remove this
+  \else
+    \noexpand\definedummyword \noexpand#1%
+  \fi
+}
+
+% This makes use of the obscure feature that if the last token of a
+% <parameter list> is #, then the preceding argument is delimited by
+% an opening brace, and that opening brace is not consumed.
+\def\getargs#1{\getargsxxx#1{}}
+\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
+\def\getmacname #1 #2\relax{\macname={#1}}
+\def\getmacargs#1{\def\argl{#1}}
+
+% Parse the optional {params} list.  Set up \paramno and \paramlist
+% so \defmacro knows what to do.  Define \macarg.blah for each blah
+% in the params list, to be ##N where N is the position in that list.
+% That gets used by \mbodybackslash (above).
+
+% We need to get `macro parameter char #' into several definitions.
+% The technique used is stolen from LaTeX:  let \hash be something
+% unexpandable, insert that wherever you need a #, and then redefine
+% it to # just before using the token list produced.
+%
+% The same technique is used to protect \eatspaces till just before
+% the macro is used.
+
+\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+        \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+\def\parsemargdefxxx#1,{%
+  \if#1;\let\next=\relax
+  \else \let\next=\parsemargdefxxx
+    \advance\paramno by 1%
+    \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
+        {\xeatspaces{\hash\the\paramno}}%
+    \edef\paramlist{\paramlist\hash\the\paramno,}%
+  \fi\next}
+
+% These two commands read recursive and nonrecursive macro bodies.
+% (They're different since rec and nonrec macros end differently.)
+
+\long\def\parsemacbody#1@end macro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\long\def\parsermacbody#1@end rmacro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+% This defines the macro itself. There are six cases: recursive and
+% nonrecursive macros of zero, one, and many arguments.
+% Much magic with \expandafter here.
+% \xdef is used so that macro definitions will survive the file
+% they're defined in; @include reads the file inside a group.
+\def\defmacro{%
+  \let\hash=##% convert placeholders to macro parameter chars
+  \ifrecursive
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\scanmacro{\temp}}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+         \egroup\noexpand\scanmacro{\temp}}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+        \csname\the\macname xxx\endcsname
+          \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+    \fi
+  \else
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+        \egroup
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \expandafter\noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+      \csname\the\macname xxx\endcsname
+      \paramlist{%
+          \egroup
+          \noexpand\norecurse{\the\macname}%
+          \noexpand\scanmacro{\temp}\egroup}%
+    \fi
+  \fi}
+
+\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+% \braceorline decides whether the next nonwhitespace character is a
+% {.  If so it reads up to the closing }, if not, it reads the whole
+% line.  Whatever was read is then fed to the next control sequence
+% as an argument (by \parsebrace or \parsearg)
+\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
+\def\braceorlinexxx{%
+  \ifx\nchar\bgroup\else
+    \expandafter\parsearg
+  \fi \next}
+
+
+% @alias.
+% We need some trickery to remove the optional spaces around the equal
+% sign.  Just make them active and then expand them all to nothing.
+\def\alias{\parseargusing\obeyspaces\aliasxxx}
+\def\aliasxxx #1{\aliasyyy#1\relax}
+\def\aliasyyy #1=#2\relax{%
+  {%
+    \expandafter\let\obeyedspace=\empty
+    \addtomacrolist{#1}%
+    \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}%
+  }%
+  \next
+}
+
+
+\message{cross references,}
+
+\newwrite\auxfile
+
+\newif\ifhavexrefs    % True if xref values are known.
+\newif\ifwarnedxrefs  % True if we warned once that they aren't known.
+
+% @inforef is relatively simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+  node \samp{\ignorespaces#1{}}}
+
+% @node's only job in TeX is to define \lastnode, which is used in
+% cross-references.  The @node line might or might not have commas, and
+% might or might not have spaces before the first comma, like:
+% @node foo , bar , ...
+% We don't want such trailing spaces in the node name.
+%
+\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse}
+%
+% also remove a trailing comma, in case of something like this:
+% @node Help-Cross,  ,  , Cross-refs
+\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse}
+\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}}
+
+\let\nwnode=\node
+\let\lastnode=\empty
+
+% Write a cross-reference definition for the current node.  #1 is the
+% type (Ynumbered, Yappendix, Ynothing).
+%
+\def\donoderef#1{%
+  \ifx\lastnode\empty\else
+    \setref{\lastnode}{#1}%
+    \global\let\lastnode=\empty
+  \fi
+}
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+\newcount\savesfregister
+%
+\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
+\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
+\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
+% anchor), which consists of three parts:
+% 1) NAME-title - the current sectioning name taken from \thissection,
+%                 or the anchor name.
+% 2) NAME-snt   - section number and type, passed as the SNT arg, or
+%                 empty for anchors.
+% 3) NAME-pg    - the page number.
+%
+% This is called from \donoderef, \anchor, and \dofloat.  In the case of
+% floats, there is an additional part, which is not written here:
+% 4) NAME-lof   - the text as it should appear in a @listoffloats.
+%
+\def\setref#1#2{%
+  \pdfmkdest{#1}%
+  \iflinks
+    {%
+      \atdummies  % preserve commands, but don't expand them
+      \edef\writexrdef##1##2{%
+	\write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
+	  ##1}{##2}}% these are parameters of \writexrdef
+      }%
+      \toks0 = \expandafter{\thissection}%
+      \immediate \writexrdef{title}{\the\toks0 }%
+      \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
+      \writexrdef{pg}{\folio}% will be written later, during \shipout
+    }%
+  \fi
+}
+
+% @xref, @pxref, and @ref generate cross-references.  For \xrefX, #1 is
+% the node name, #2 the name of the Info cross-reference, #3 the printed
+% node name, #4 the name of the Info file, #5 the name of the printed
+% manual.  All but the node name can be omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+  \unsepspaces
+  \def\printedmanual{\ignorespaces #5}%
+  \def\printedrefname{\ignorespaces #3}%
+  \setbox1=\hbox{\printedmanual\unskip}%
+  \setbox0=\hbox{\printedrefname\unskip}%
+  \ifdim \wd0 = 0pt
+    % No printed node name was explicitly given.
+    \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+      % Use the node name inside the square brackets.
+      \def\printedrefname{\ignorespaces #1}%
+    \else
+      % Use the actual chapter/section title appear inside
+      % the square brackets.  Use the real section title if we have it.
+      \ifdim \wd1 > 0pt
+        % It is in another manual, so we don't have it.
+        \def\printedrefname{\ignorespaces #1}%
+      \else
+        \ifhavexrefs
+          % We know the real title if we have the xref values.
+          \def\printedrefname{\refx{#1-title}{}}%
+        \else
+          % Otherwise just copy the Info node name.
+          \def\printedrefname{\ignorespaces #1}%
+        \fi%
+      \fi
+    \fi
+  \fi
+  %
+  % Make link in pdf output.
+  \ifpdf
+    \leavevmode
+    \getfilename{#4}%
+    {\turnoffactive
+     % See comments at \activebackslashdouble.
+     {\activebackslashdouble \xdef\pdfxrefdest{#1}%
+      \backslashparens\pdfxrefdest}%
+     %
+     \ifnum\filenamelength>0
+       \startlink attr{/Border [0 0 0]}%
+         goto file{\the\filename.pdf} name{\pdfxrefdest}%
+     \else
+       \startlink attr{/Border [0 0 0]}%
+         goto name{\pdfmkpgn{\pdfxrefdest}}%
+     \fi
+    }%
+    \linkcolor
+  \fi
+  %
+  % Float references are printed completely differently: "Figure 1.2"
+  % instead of "[somenode], p.3".  We distinguish them by the
+  % LABEL-title being set to a magic string.
+  {%
+    % Have to otherify everything special to allow the \csname to
+    % include an _ in the xref name, etc.
+    \indexnofonts
+    \turnoffactive
+    \expandafter\global\expandafter\let\expandafter\Xthisreftitle
+      \csname XR#1-title\endcsname
+  }%
+  \iffloat\Xthisreftitle
+    % If the user specified the print name (third arg) to the ref,
+    % print it instead of our usual "Figure 1.2".
+    \ifdim\wd0 = 0pt
+      \refx{#1-snt}{}%
+    \else
+      \printedrefname
+    \fi
+    %
+    % if the user also gave the printed manual name (fifth arg), append
+    % "in MANUALNAME".
+    \ifdim \wd1 > 0pt
+      \space \putwordin{} \cite{\printedmanual}%
+    \fi
+  \else
+    % node/anchor (non-float) references.
+    %
+    % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+    % insert empty discretionaries after hyphens, which means that it will
+    % not find a line break at a hyphen in a node names.  Since some manuals
+    % are best written with fairly long node names, containing hyphens, this
+    % is a loss.  Therefore, we give the text of the node name again, so it
+    % is as if TeX is seeing it for the first time.
+    \ifdim \wd1 > 0pt
+      \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}%
+    \else
+      % _ (for example) has to be the character _ for the purposes of the
+      % control sequence corresponding to the node, but it has to expand
+      % into the usual \leavevmode...\vrule stuff for purposes of
+      % printing. So we \turnoffactive for the \refx-snt, back on for the
+      % printing, back off for the \refx-pg.
+      {\turnoffactive
+       % Only output a following space if the -snt ref is nonempty; for
+       % @unnumbered and @anchor, it won't be.
+       \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+       \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
+      }%
+      % output the `[mynode]' via a macro so it can be overridden.
+      \xrefprintnodename\printedrefname
+      %
+      % But we always want a comma and a space:
+      ,\space
+      %
+      % output the `page 3'.
+      \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% This macro is called from \xrefX for the `[nodename]' part of xref
+% output.  It's a separate macro only so it can be changed more easily,
+% since square brackets don't work well in some documents.  Particularly
+% one that Bob is working on :).
+%
+\def\xrefprintnodename#1{[#1]}
+
+% Things referred to by \setref.
+%
+\def\Ynothing{}
+\def\Yomitfromtoc{}
+\def\Ynumbered{%
+  \ifnum\secno=0
+    \putwordChapter@tie \the\chapno
+  \else \ifnum\subsecno=0
+    \putwordSection@tie \the\chapno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+\def\Yappendix{%
+  \ifnum\secno=0
+     \putwordAppendix@tie @char\the\appendixno{}%
+  \else \ifnum\subsecno=0
+     \putwordSection@tie @char\the\appendixno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie
+      @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+%
+\def\refx#1#2{%
+  {%
+    \indexnofonts
+    \otherbackslash
+    \expandafter\global\expandafter\let\expandafter\thisrefX
+      \csname XR#1\endcsname
+  }%
+  \ifx\thisrefX\relax
+    % If not defined, say something at least.
+    \angleleft un\-de\-fined\angleright
+    \iflinks
+      \ifhavexrefs
+        \message{\linenumber Undefined cross reference `#1'.}%
+      \else
+        \ifwarnedxrefs\else
+          \global\warnedxrefstrue
+          \message{Cross reference values unknown; you must run TeX again.}%
+        \fi
+      \fi
+    \fi
+  \else
+    % It's defined, so just use it.
+    \thisrefX
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file.  Usually it's
+% just a \def (we prepend XR to the control sequence name to avoid
+% collisions).  But if this is a float type, we have more work to do.
+%
+\def\xrdef#1#2{%
+  \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value.
+  %
+  % Was that xref control sequence that we just defined for a float?
+  \expandafter\iffloat\csname XR#1\endcsname
+    % it was a float, and we have the (safe) float type in \iffloattype.
+    \expandafter\let\expandafter\floatlist
+      \csname floatlist\iffloattype\endcsname
+    %
+    % Is this the first time we've seen this float type?
+    \expandafter\ifx\floatlist\relax
+      \toks0 = {\do}% yes, so just \do
+    \else
+      % had it before, so preserve previous elements in list.
+      \toks0 = \expandafter{\floatlist\do}%
+    \fi
+    %
+    % Remember this xref in the control sequence \floatlistFLOATTYPE,
+    % for later use in \listoffloats.
+    \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}%
+  \fi
+}
+
+% Read the last existing aux file, if any.  No error if none exists.
+%
+\def\tryauxfile{%
+  \openin 1 \jobname.aux
+  \ifeof 1 \else
+    \readdatafile{aux}%
+    \global\havexrefstrue
+  \fi
+  \closein 1
+}
+
+\def\setupdatafile{%
+  \catcode`\^^@=\other
+  \catcode`\^^A=\other
+  \catcode`\^^B=\other
+  \catcode`\^^C=\other
+  \catcode`\^^D=\other
+  \catcode`\^^E=\other
+  \catcode`\^^F=\other
+  \catcode`\^^G=\other
+  \catcode`\^^H=\other
+  \catcode`\^^K=\other
+  \catcode`\^^L=\other
+  \catcode`\^^N=\other
+  \catcode`\^^P=\other
+  \catcode`\^^Q=\other
+  \catcode`\^^R=\other
+  \catcode`\^^S=\other
+  \catcode`\^^T=\other
+  \catcode`\^^U=\other
+  \catcode`\^^V=\other
+  \catcode`\^^W=\other
+  \catcode`\^^X=\other
+  \catcode`\^^Z=\other
+  \catcode`\^^[=\other
+  \catcode`\^^\=\other
+  \catcode`\^^]=\other
+  \catcode`\^^^=\other
+  \catcode`\^^_=\other
+  % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc.
+  % in xref tags, i.e., node names.  But since ^^e4 notation isn't
+  % supported in the main text, it doesn't seem desirable.  Furthermore,
+  % that is not enough: for node names that actually contain a ^
+  % character, we would end up writing a line like this: 'xrdef {'hat
+  % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+  % argument, and \hat is not an expandable control sequence.  It could
+  % all be worked out, but why?  Either we support ^^ or we don't.
+  %
+  % The other change necessary for this was to define \auxhat:
+  % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+  % and then to call \auxhat in \setq.
+  %
+  \catcode`\^=\other
+  %
+  % Special characters.  Should be turned off anyway, but...
+  \catcode`\~=\other
+  \catcode`\[=\other
+  \catcode`\]=\other
+  \catcode`\"=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\$=\other
+  \catcode`\#=\other
+  \catcode`\&=\other
+  \catcode`\%=\other
+  \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
+  %
+  % This is to support \ in node names and titles, since the \
+  % characters end up in a \csname.  It's easier than
+  % leaving it active and making its active definition an actual \
+  % character.  What I don't understand is why it works in the *value*
+  % of the xrdef.  Seems like it should be a catcode12 \, and that
+  % should not typeset properly.  But it works, so I'm moving on for
+  % now.  --karl, 15jan04.
+  \catcode`\\=\other
+  %
+  % Make the characters 128-255 be printing characters.
+  {%
+    \count1=128
+    \def\loop{%
+      \catcode\count1=\other
+      \advance\count1 by 1
+      \ifnum \count1<256 \loop \fi
+    }%
+  }%
+  %
+  % @ is our escape character in .aux files, and we need braces.
+  \catcode`\{=1
+  \catcode`\}=2
+  \catcode`\@=0
+}
+
+\def\readdatafile#1{%
+\begingroup
+  \setupdatafile
+  \input\jobname.#1
+\endgroup}
+
+\message{insertions,}
+% including footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only.
+\let\footnotestyle=\comment
+
+{\catcode `\@=11
+%
+% Auto-number footnotes.  Otherwise like plain.
+\gdef\footnote{%
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \global\advance\footnoteno by \@ne
+  \edef\thisfootno{$^{\the\footnoteno}$}%
+  %
+  % In case the footnote comes at the end of a sentence, preserve the
+  % extra spacing after we do the footnote number.
+  \let\@sf\empty
+  \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
+  %
+  % Remove inadvertent blank space before typesetting the footnote number.
+  \unskip
+  \thisfootno\@sf
+  \dofootnote
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter.  Our footnotes don't need to be so general.
+%
+% Oh yes, they do; otherwise, @ifset (and anything else that uses
+% \parseargline) fails inside footnotes because the tokens are fixed when
+% the footnote is read.  --karl, 16nov96.
+%
+\gdef\dofootnote{%
+  \insert\footins\bgroup
+  % We want to typeset this text as a normal paragraph, even if the
+  % footnote reference occurs in (for example) a display environment.
+  % So reset some parameters.
+  \hsize=\pagewidth
+  \interlinepenalty\interfootnotelinepenalty
+  \splittopskip\ht\strutbox % top baseline for broken footnotes
+  \splitmaxdepth\dp\strutbox
+  \floatingpenalty\@MM
+  \leftskip\z@skip
+  \rightskip\z@skip
+  \spaceskip\z@skip
+  \xspaceskip\z@skip
+  \parindent\defaultparindent
+  %
+  \smallfonts \rm
+  %
+  % Because we use hanging indentation in footnotes, a @noindent appears
+  % to exdent this text, so make it be a no-op.  makeinfo does not use
+  % hanging indentation so @noindent can still be needed within footnote
+  % text after an @example or the like (not that this is good style).
+  \let\noindent = \relax
+  %
+  % Hang the footnote text off the number.  Use \everypar in case the
+  % footnote extends for more than one paragraph.
+  \everypar = {\hang}%
+  \textindent{\thisfootno}%
+  %
+  % Don't crash into the line above the footnote text.  Since this
+  % expands into a box, it must come within the paragraph, lest it
+  % provide a place where TeX can split the footnote.
+  \footstrut
+  \futurelet\next\fo@t
+}
+}%end \catcode `\@=11
+
+% In case a @footnote appears in a vbox, save the footnote text and create
+% the real \insert just after the vbox finished.  Otherwise, the insertion
+% would be lost.
+% Similarily, if a @footnote appears inside an alignment, save the footnote
+% text to a box and make the \insert when a row of the table is finished.
+% And the same can be done for other insert classes.  --kasal, 16nov03.
+
+% Replace the \insert primitive by a cheating macro.
+% Deeper inside, just make sure that the saved insertions are not spilled
+% out prematurely.
+%
+\def\startsavinginserts{%
+  \ifx \insert\ptexinsert
+    \let\insert\saveinsert
+  \else
+    \let\checkinserts\relax
+  \fi
+}
+
+% This \insert replacement works for both \insert\footins{foo} and
+% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}.
+%
+\def\saveinsert#1{%
+  \edef\next{\noexpand\savetobox \makeSAVEname#1}%
+  \afterassignment\next
+  % swallow the left brace
+  \let\temp =
+}
+\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}}
+\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1}
+
+\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi}
+
+\def\placesaveins#1{%
+  \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname
+    {\box#1}%
+}
+
+% eat @SAVE -- beware, all of them have catcode \other:
+{
+  \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials  %  ;-)
+  \gdef\gobblesave @SAVE{}
+}
+
+% initialization:
+\def\newsaveins #1{%
+  \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}%
+  \next
+}
+\def\newsaveinsX #1{%
+  \csname newbox\endcsname #1%
+  \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts
+    \checksaveins #1}%
+}
+
+% initialize:
+\let\checkinserts\empty
+\newsaveins\footins
+\newsaveins\margin
+
+
+% @image.  We use the macros from epsf.tex to support this.
+% If epsf.tex is not installed and @image is used, we complain.
+%
+% Check for and read epsf.tex up front.  If we read it only at @image
+% time, we might be inside a group, and then its definitions would get
+% undone and the next image would fail.
+\openin 1 = epsf.tex
+\ifeof 1 \else
+  % Do not bother showing banner with epsf.tex v2.7k (available in
+  % doc/epsf.tex and on ctan).
+  \def\epsfannounce{\toks0 = }%
+  \input epsf.tex
+\fi
+\closein 1
+%
+% We will only complain once about lack of epsf.tex.
+\newif\ifwarnednoepsf
+\newhelp\noepsfhelp{epsf.tex must be installed for images to
+  work.  It is also included in the Texinfo distribution, or you can get
+  it from ftp://tug.org/tex/epsf.tex.}
+%
+\def\image#1{%
+  \ifx\epsfbox\undefined
+    \ifwarnednoepsf \else
+      \errhelp = \noepsfhelp
+      \errmessage{epsf.tex not found, images will be ignored}%
+      \global\warnednoepsftrue
+    \fi
+  \else
+    \imagexxx #1,,,,,\finish
+  \fi
+}
+%
+% Arguments to @image:
+% #1 is (mandatory) image filename; we tack on .eps extension.
+% #2 is (optional) width, #3 is (optional) height.
+% #4 is (ignored optional) html alt text.
+% #5 is (ignored optional) extension.
+% #6 is just the usual extra ignored arg for parsing this stuff.
+\newif\ifimagevmode
+\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
+  \catcode`\^^M = 5     % in case we're inside an example
+  \normalturnoffactive  % allow _ et al. in names
+  % If the image is by itself, center it.
+  \ifvmode
+    \imagevmodetrue
+    \nobreak\bigskip
+    % Usually we'll have text after the image which will insert
+    % \parskip glue, so insert it here too to equalize the space
+    % above and below.
+    \nobreak\vskip\parskip
+    \nobreak
+    \line\bgroup
+  \fi
+  %
+  % Output the image.
+  \ifpdf
+    \dopdfimage{#1}{#2}{#3}%
+  \else
+    % \epsfbox itself resets \epsf?size at each figure.
+    \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+    \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+    \epsfbox{#1.eps}%
+  \fi
+  %
+  \ifimagevmode \egroup \bigbreak \fi  % space after the image
+\endgroup}
+
+
+% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables,
+% etc.  We don't actually implement floating yet, we always include the
+% float "here".  But it seemed the best name for the future.
+%
+\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish}
+
+% There may be a space before second and/or third parameter; delete it.
+\def\eatcommaspace#1, {#1,}
+
+% #1 is the optional FLOATTYPE, the text label for this float, typically
+% "Figure", "Table", "Example", etc.  Can't contain commas.  If omitted,
+% this float will not be numbered and cannot be referred to.
+%
+% #2 is the optional xref label.  Also must be present for the float to
+% be referable.
+%
+% #3 is the optional positioning argument; for now, it is ignored.  It
+% will somehow specify the positions allowed to float to (here, top, bottom).
+%
+% We keep a separate counter for each FLOATTYPE, which we reset at each
+% chapter-level command.
+\let\resetallfloatnos=\empty
+%
+\def\dofloat#1,#2,#3,#4\finish{%
+  \let\thiscaption=\empty
+  \let\thisshortcaption=\empty
+  %
+  % don't lose footnotes inside @float.
+  %
+  % BEWARE: when the floats start float, we have to issue warning whenever an
+  % insert appears inside a float which could possibly float. --kasal, 26may04
+  %
+  \startsavinginserts
+  %
+  % We can't be used inside a paragraph.
+  \par
+  %
+  \vtop\bgroup
+    \def\floattype{#1}%
+    \def\floatlabel{#2}%
+    \def\floatloc{#3}% we do nothing with this yet.
+    %
+    \ifx\floattype\empty
+      \let\safefloattype=\empty
+    \else
+      {%
+        % the floattype might have accents or other special characters,
+        % but we need to use it in a control sequence name.
+        \indexnofonts
+        \turnoffactive
+        \xdef\safefloattype{\floattype}%
+      }%
+    \fi
+    %
+    % If label is given but no type, we handle that as the empty type.
+    \ifx\floatlabel\empty \else
+      % We want each FLOATTYPE to be numbered separately (Figure 1,
+      % Table 1, Figure 2, ...).  (And if no label, no number.)
+      %
+      \expandafter\getfloatno\csname\safefloattype floatno\endcsname
+      \global\advance\floatno by 1
+      %
+      {%
+        % This magic value for \thissection is output by \setref as the
+        % XREFLABEL-title value.  \xrefX uses it to distinguish float
+        % labels (which have a completely different output format) from
+        % node and anchor labels.  And \xrdef uses it to construct the
+        % lists of floats.
+        %
+        \edef\thissection{\floatmagic=\safefloattype}%
+        \setref{\floatlabel}{Yfloat}%
+      }%
+    \fi
+    %
+    % start with \parskip glue, I guess.
+    \vskip\parskip
+    %
+    % Don't suppress indentation if a float happens to start a section.
+    \restorefirstparagraphindent
+}
+
+% we have these possibilities:
+% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap
+% @float Foo,lbl & no caption:    Foo 1.1
+% @float Foo & @caption{Cap}:     Foo: Cap
+% @float Foo & no caption:        Foo
+% @float ,lbl & Caption{Cap}:     1.1: Cap
+% @float ,lbl & no caption:       1.1
+% @float & @caption{Cap}:         Cap
+% @float & no caption:
+%
+\def\Efloat{%
+    \let\floatident = \empty
+    %
+    % In all cases, if we have a float type, it comes first.
+    \ifx\floattype\empty \else \def\floatident{\floattype}\fi
+    %
+    % If we have an xref label, the number comes next.
+    \ifx\floatlabel\empty \else
+      \ifx\floattype\empty \else % if also had float type, need tie first.
+        \appendtomacro\floatident{\tie}%
+      \fi
+      % the number.
+      \appendtomacro\floatident{\chaplevelprefix\the\floatno}%
+    \fi
+    %
+    % Start the printed caption with what we've constructed in
+    % \floatident, but keep it separate; we need \floatident again.
+    \let\captionline = \floatident
+    %
+    \ifx\thiscaption\empty \else
+      \ifx\floatident\empty \else
+	\appendtomacro\captionline{: }% had ident, so need a colon between
+      \fi
+      %
+      % caption text.
+      \appendtomacro\captionline{\scanexp\thiscaption}%
+    \fi
+    %
+    % If we have anything to print, print it, with space before.
+    % Eventually this needs to become an \insert.
+    \ifx\captionline\empty \else
+      \vskip.5\parskip
+      \captionline
+      %
+      % Space below caption.
+      \vskip\parskip
+    \fi
+    %
+    % If have an xref label, write the list of floats info.  Do this
+    % after the caption, to avoid chance of it being a breakpoint.
+    \ifx\floatlabel\empty \else
+      % Write the text that goes in the lof to the aux file as
+      % \floatlabel-lof.  Besides \floatident, we include the short
+      % caption if specified, else the full caption if specified, else nothing.
+      {%
+        \atdummies
+        %
+        % since we read the caption text in the macro world, where ^^M
+        % is turned into a normal character, we have to scan it back, so
+        % we don't write the literal three characters "^^M" into the aux file.
+	\scanexp{%
+	  \xdef\noexpand\gtemp{%
+	    \ifx\thisshortcaption\empty
+	      \thiscaption
+	    \else
+	      \thisshortcaption
+	    \fi
+	  }%
+	}%
+        \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident
+	  \ifx\gtemp\empty \else : \gtemp \fi}}%
+      }%
+    \fi
+  \egroup  % end of \vtop
+  %
+  % place the captured inserts
+  %
+  % BEWARE: when the floats start floating, we have to issue warning
+  % whenever an insert appears inside a float which could possibly
+  % float. --kasal, 26may04
+  %
+  \checkinserts
+}
+
+% Append the tokens #2 to the definition of macro #1, not expanding either.
+%
+\def\appendtomacro#1#2{%
+  \expandafter\def\expandafter#1\expandafter{#1#2}%
+}
+
+% @caption, @shortcaption
+%
+\def\caption{\docaption\thiscaption}
+\def\shortcaption{\docaption\thisshortcaption}
+\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption}
+\def\defcaption#1#2{\egroup \def#1{#2}}
+
+% The parameter is the control sequence identifying the counter we are
+% going to use.  Create it if it doesn't exist and assign it to \floatno.
+\def\getfloatno#1{%
+  \ifx#1\relax
+      % Haven't seen this figure type before.
+      \csname newcount\endcsname #1%
+      %
+      % Remember to reset this floatno at the next chap.
+      \expandafter\gdef\expandafter\resetallfloatnos
+        \expandafter{\resetallfloatnos #1=0 }%
+  \fi
+  \let\floatno#1%
+}
+
+% \setref calls this to get the XREFLABEL-snt value.  We want an @xref
+% to the FLOATLABEL to expand to "Figure 3.1".  We call \setref when we
+% first read the @float command.
+%
+\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}%
+
+% Magic string used for the XREFLABEL-title value, so \xrefX can
+% distinguish floats from other xref types.
+\def\floatmagic{!!float!!}
+
+% #1 is the control sequence we are passed; we expand into a conditional
+% which is true if #1 represents a float ref.  That is, the magic
+% \thissection value which we \setref above.
+%
+\def\iffloat#1{\expandafter\doiffloat#1==\finish}
+%
+% #1 is (maybe) the \floatmagic string.  If so, #2 will be the
+% (safe) float type for this float.  We set \iffloattype to #2.
+%
+\def\doiffloat#1=#2=#3\finish{%
+  \def\temp{#1}%
+  \def\iffloattype{#2}%
+  \ifx\temp\floatmagic
+}
+
+% @listoffloats FLOATTYPE - print a list of floats like a table of contents.
+%
+\parseargdef\listoffloats{%
+  \def\floattype{#1}% floattype
+  {%
+    % the floattype might have accents or other special characters,
+    % but we need to use it in a control sequence name.
+    \indexnofonts
+    \turnoffactive
+    \xdef\safefloattype{\floattype}%
+  }%
+  %
+  % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE.
+  \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax
+    \ifhavexrefs
+      % if the user said @listoffloats foo but never @float foo.
+      \message{\linenumber No `\safefloattype' floats to list.}%
+    \fi
+  \else
+    \begingroup
+      \leftskip=\tocindent  % indent these entries like a toc
+      \let\do=\listoffloatsdo
+      \csname floatlist\safefloattype\endcsname
+    \endgroup
+  \fi
+}
+
+% This is called on each entry in a list of floats.  We're passed the
+% xref label, in the form LABEL-title, which is how we save it in the
+% aux file.  We strip off the -title and look up \XRLABEL-lof, which
+% has the text we're supposed to typeset here.
+%
+% Figures without xref labels will not be included in the list (since
+% they won't appear in the aux file).
+%
+\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish}
+\def\listoffloatsdoentry#1-title\finish{{%
+  % Can't fully expand XR#1-lof because it can contain anything.  Just
+  % pass the control sequence.  On the other hand, XR#1-pg is just the
+  % page number, and we want to fully expand that so we can get a link
+  % in pdf output.
+  \toksA = \expandafter{\csname XR#1-lof\endcsname}%
+  %
+  % use the same \entry macro we use to generate the TOC and index.
+  \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}%
+  \writeentry
+}}
+
+\message{localization,}
+% and i18n.
+
+% @documentlanguage is usually given very early, just after
+% @setfilename.  If done too late, it may not override everything
+% properly.  Single argument is the language abbreviation.
+% It would be nice if we could set up a hyphenation file here.
+%
+\parseargdef\documentlanguage{%
+  \tex % read txi-??.tex file in plain TeX.
+    % Read the file if it exists.
+    \openin 1 txi-#1.tex
+    \ifeof 1
+      \errhelp = \nolanghelp
+      \errmessage{Cannot read language file txi-#1.tex}%
+    \else
+      \input txi-#1.tex
+    \fi
+    \closein 1
+  \endgroup
+}
+\newhelp\nolanghelp{The given language definition file cannot be found or
+is empty.  Maybe you need to install it?  In the current directory
+should work if nowhere else does.}
+
+
+% @documentencoding should change something in TeX eventually, most
+% likely, but for now just recognize it.
+\let\documentencoding = \comment
+
+
+% Page size parameters.
+%
+\newdimen\defaultparindent \defaultparindent = 15pt
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness = 10000
+
+% Don't be so finicky about underfull hboxes, either.
+\hbadness = 2000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything.  We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize.  We call this whenever the paper size is set.
+%
+\def\setemergencystretch{%
+  \ifx\emergencystretch\thisisundefined
+    % Allow us to assign to \emergencystretch anyway.
+    \def\emergencystretch{\dimen0}%
+  \else
+    \emergencystretch = .15\hsize
+  \fi
+}
+
+% Parameters in order: 1) textheight; 2) textwidth;
+% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip;
+% 7) physical page height; 8) physical page width.
+%
+% We also call \setleading{\textleading}, so the caller should define
+% \textleading.  The caller should also set \parskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6#7#8{%
+  \voffset = #3\relax
+  \topskip = #6\relax
+  \splittopskip = \topskip
+  %
+  \vsize = #1\relax
+  \advance\vsize by \topskip
+  \outervsize = \vsize
+  \advance\outervsize by 2\topandbottommargin
+  \pageheight = \vsize
+  %
+  \hsize = #2\relax
+  \outerhsize = \hsize
+  \advance\outerhsize by 0.5in
+  \pagewidth = \hsize
+  %
+  \normaloffset = #4\relax
+  \bindingoffset = #5\relax
+  %
+  \ifpdf
+    \pdfpageheight #7\relax
+    \pdfpagewidth #8\relax
+  \fi
+  %
+  \setleading{\textleading}
+  %
+  \parindent = \defaultparindent
+  \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % If page is nothing but text, make it come out even.
+  \internalpagesizes{46\baselineskip}{6in}%
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{36pt}%
+                    {11in}{8.5in}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.25 trim size.
+\def\smallbook{{\globaldefs = 1
+  \parskip = 2pt plus 1pt
+  \textleading = 12pt
+  %
+  \internalpagesizes{7.5in}{5in}%
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{16pt}%
+                    {9.25in}{7in}%
+  %
+  \lispnarrowing = 0.3in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = .5cm
+}}
+
+% Use @smallerbook to reset parameters for 6x9 trim size.
+% (Just testing, parameters still in flux.)
+\def\smallerbook{{\globaldefs = 1
+  \parskip = 1.5pt plus 1pt
+  \textleading = 12pt
+  %
+  \internalpagesizes{7.4in}{4.8in}%
+                    {-.2in}{-.4in}%
+                    {0pt}{14pt}%
+                    {9in}{6in}%
+  %
+  \lispnarrowing = 0.25in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = .4cm
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % Double-side printing via postscript on Laserjet 4050
+  % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
+  % To change the settings for a different printer or situation, adjust
+  % \normaloffset until the front-side and back-side texts align.  Then
+  % do the same for \bindingoffset.  You can set these for testing in
+  % your texinfo source file like this:
+  % @tex
+  % \global\normaloffset = -6mm
+  % \global\bindingoffset = 10mm
+  % @end tex
+  \internalpagesizes{51\baselineskip}{160mm}
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{44pt}%
+                    {297mm}{210mm}%
+  %
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 5mm
+}}
+
+% Use @afivepaper to print on European A5 paper.
+% From romildo@urano.iceb.ufop.br, 2 July 2000.
+% He also recommends making @example and @lisp be small.
+\def\afivepaper{{\globaldefs = 1
+  \parskip = 2pt plus 1pt minus 0.1pt
+  \textleading = 12.5pt
+  %
+  \internalpagesizes{160mm}{120mm}%
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{8pt}%
+                    {210mm}{148mm}%
+  %
+  \lispnarrowing = 0.2in
+  \tolerance = 800
+  \hfuzz = 1.2pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 2mm
+  \tableindent = 12mm
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper.
+\def\afourlatex{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{237mm}{150mm}%
+                    {\voffset}{4.6mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  %
+  % Must explicitly reset to 0 because we call \afourpaper.
+  \globaldefs = 0
+}}
+
+% Use @afourwide to print on A4 paper in landscape format.
+\def\afourwide{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{241mm}{165mm}%
+                    {\voffset}{-2.95mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  \globaldefs = 0
+}}
+
+% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
+% Perhaps we should allow setting the margins, \topskip, \parskip,
+% and/or leading, also. Or perhaps we should compute them somehow.
+%
+\parseargdef\pagesizes{\pagesizesyyy #1,,\finish}
+\def\pagesizesyyy#1,#2,#3\finish{{%
+  \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
+  \globaldefs = 1
+  %
+  \parskip = 3pt plus 2pt minus 1pt
+  \setleading{\textleading}%
+  %
+  \dimen0 = #1
+  \advance\dimen0 by \voffset
+  %
+  \dimen2 = \hsize
+  \advance\dimen2 by \normaloffset
+  %
+  \internalpagesizes{#1}{\hsize}%
+                    {\voffset}{\normaloffset}%
+                    {\bindingoffset}{44pt}%
+                    {\dimen0}{\dimen2}%
+}}
+
+% Set default to letter.
+%
+\letterpaper
+
+
+\message{and turning on texinfo input format.}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\catcode`\$=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+\def\normaldollar{$}%$ font-lock fix
+
+% This macro is used to make a character print one way in \tt
+% (where it can probably be output as-is), and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise.  Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
+
+% Same as above, but check for italic font.  Actually this also catches
+% non-italic slanted fonts since it is impossible to distinguish them from
+% italic fonts.  But since this is only used by $ and it uses \sl anyway
+% this is not a problem.
+\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt\char34}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt\char126}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+\let\realunder=_
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
+
+\catcode`\|=\active
+\def|{{\tt\char124}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+\catcode`\$=\active
+\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+% Used sometimes to turn off (effectively) the active characters even after
+% parsing them.
+\def\turnoffactive{%
+  \normalturnoffactive
+  \otherbackslash
+}
+
+\catcode`\@=0
+
+% \backslashcurfont outputs one backslash character in current font,
+% as in \char`\\.
+\global\chardef\backslashcurfont=`\\
+\global\let\rawbackslashxx=\backslashcurfont  % let existing .??s files work
+
+% \realbackslash is an actual character `\' with catcode other, and
+% \doublebackslash is two of them (for the pdf outlines).
+{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}}
+
+% In texinfo, backslash is an active character; it prints the backslash
+% in fixed width font.
+\catcode`\\=\active
+@def@normalbackslash{{@tt@backslashcurfont}}
+% On startup, @fixbackslash assigns:
+%  @let \ = @normalbackslash
+
+% \rawbackslash defines an active \ to do \backslashcurfont.
+% \otherbackslash defines an active \ to be a literal `\' character with
+% catcode other.
+@gdef@rawbackslash{@let\=@backslashcurfont}
+@gdef@otherbackslash{@let\=@realbackslash}
+
+% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
+% the literal character `\'.
+% 
+@def@normalturnoffactive{%
+  @let\=@normalbackslash
+  @let"=@normaldoublequote
+  @let~=@normaltilde
+  @let^=@normalcaret
+  @let_=@normalunderscore
+  @let|=@normalverticalbar
+  @let<=@normalless
+  @let>=@normalgreater
+  @let+=@normalplus
+  @let$=@normaldollar %$ font-lock fix
+  @unsepspaces
+}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\' in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also turn back on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{%
+  @ifx\@eatinput @let\ = @normalbackslash @fi
+  @catcode`+=@active
+  @catcode`@_=@active
+}
+
+% Say @foo, not \foo, in error messages.
+@escapechar = `@@
+
+% These look ok in all fonts, so just make them not special.
+@catcode`@& = @other
+@catcode`@# = @other
+@catcode`@% = @other
+
+
+@c Local variables:
+@c eval: (add-hook 'write-file-hooks 'time-stamp)
+@c page-delimiter: "^\\\\message"
+@c time-stamp-start: "def\\\\texinfoversion{"
+@c time-stamp-format: "%:y-%02m-%02d.%02H"
+@c time-stamp-end: "}"
+@c End:
+
+@c vim:sw=2:
+
+@ignore
+   arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115
+@end ignore
diff --git a/krb5-1-6/doc/thread-safe.txt b/krb5-1-6/doc/thread-safe.txt
new file mode 100644
index 000000000..0996b329a
--- /dev/null
+++ b/krb5-1-6/doc/thread-safe.txt
@@ -0,0 +1,257 @@
+In general, it's assumed that the library initialization function (if
+initialization isn't delayed) and the library finalization function
+are run in some thread-safe fashion, with no other parts of the
+library in question in use.  (If dlopen or dlsym in one thread starts
+running the initializer, and then dlopen/dlsym in another thread
+returns and lets you start accessing functions or data in the library
+before the initializer is finished, that really seems like a
+dlopen/dlsym bug.)
+
+It's also assumed that if library A depends on library B, then library
+B's initializer runs first, and its finalizer last, whether loading
+dynamically at run time or at process startup/exit.  (It appears that
+AIX 4.3.3 may violate this, at least when we use gcc's
+constructor/destructor attributes in shared libraries.)
+
+Support for freeing the heap storage allocated by a library has NOT,
+in general, been written.  There are hooks, but often they ignore some
+of the library's local storage, mutexes, etc.
+
+If shared library finalization code doesn't get run at all at dlclose
+time, or if we can't use it because the execution order is wrong, then
+you'll get memory leaks.  Deal with it.
+
+Several debugging variables that are not part of our official API are
+not protected by mutexes.  In general, the only way to set them is by
+changing the sources and recompiling, which obviously has no run-time
+thread safety issues, or by stopping the process under a debugger,
+which we blithely assert is "safe enough".
+
+Debug code that we don't normally enable may be less thread safe than
+might be desired.  For example, multiple printf calls may be made,
+with the assumption that the output will not be intermixed with output
+from some other thread.  Offhand, I'm not aware of any cases where
+debugging code is "really" unsafe, as in likely to crash the program
+or produce insecure results.
+
+Various libraries may call assert() and abort().  This should only be
+for "can't happen" cases, and indicate programming errors.  In some
+cases, the compiler may be able to infer that the "can't happen" cases
+really can't happen, and drop the calls, but in many cases, this is
+not possible.
+
+There are cases (e.g., in the com_err library) where errors arising
+when dealing with other errors are handled by calling abort, for lack
+of anything better.  We should probably clean those up someday.
+
+Various libraries call getenv().  This is perfectly safe, as long as
+nothing is calling setenv or putenv or what have you, while multiple
+threads are executing.  Of course, that severely curtails the ability
+to control our libraries through that "interface".
+
+Various libraries call the ctype functions/macros (isupper, etc).  It
+is assumed that the program does not call setlocale, or does so only
+while the program is still single-threaded or while calls into the
+Kerberos libraries are not in progress.
+
+The Windows thread safety support is unfinished.
+
+I'm assuming that structure fields that are never written to (e.g.,
+after a structure has been initialized and *then* made possibly
+visible to multiple threads) are safe to read from one thread while
+another field is being updated by another thread.  If that's not the
+case, some more work is needed (and I'd like details on why it's not
+safe).
+
+----------------
+
+libcom_err
+
+Issues:
+
+The callback hook support (set_com_err_hook, reset_com_err_hook, and
+calls to com_err and com_err_va) uses a mutex to protect the handle on
+the hook function.  As a side effect of this, if a callback function
+is registered which pops up a window and waits for the users'
+acknowledgement, then other errors cannot be reported by other threads
+until after the acknowledgement.  This could be fixed with
+multiple-reader-one-writer type locks, but that's a bit more
+complicated.
+
+The string returned by error_message may be per-thread storage.  It
+can be passed off between threads, but it shouldn't be in use by any
+thread by the time the originating thread calls error_message again.
+
+Error tables must no longer be in use (including pointers returned by
+error_message) when the library containing them is unloaded.
+
+Temporary: A flag variable has been created in error_message.c which
+is used to try to catch cases where remove_error_table is called after
+the library finalization function.  This generally indicates
+out-of-order execution of the library finalization functions.  The
+handling of this flag is not thread-safe, but if the finalization
+function is called, other threads should in theory be finished with
+this library anyways.
+
+Statics: error_message.c, com_err.c, covered above.
+
+----------------
+
+libprofile (and its use in libkrb5)
+
+Does no checks to see if it's opened multiple instances of the same
+file under different names.  Does not guard against trying to open a
+file while another thread or process is in the process of replacing
+it, or two threads trying to update a file at the same time.  The
+former should be pretty safe on UNIX with atomic rename, but on
+Windows there's a race condition; there's a window (so to speak) where
+the filename does not correspond to an actual file.
+
+Statics: prof_file.c, a list of opened config files and their parse
+trees, and a mutex to protect it.
+
+----------------
+
+libk5crypto
+
+Uses of the Yarrow code from the krb5 crypto interface are protected
+by a single mutex.  Initialization of the Yarrow state will be done
+once, the first time these routines are called.  Calls directly to the
+Yarrow functions are not protected.
+
+Uses ctype macros; what happens if the locale is changed in a
+multi-threaded program?
+
+Debug var in pbkdf2.c.
+
+Statics: pbkdf2.c: debug variable.
+
+Statics: prng.c: Global Yarrow data and mutex.
+
+Statics: crypto_libinit.c: library initializer aux data.
+
+----------------
+
+libkrb5
+
+(TBD)
+
+Uses: ctype macros
+
+Uses: getaddrinfo, getnameinfo.  According to current specifications,
+getaddrinfo should be thread-safe; some implementations are not, and
+we're not attempting to figure out which ones.  NetBSD 1.6, for
+example, had an unsafe implementation.
+
+Uses: res_ninit, res_nsearch.  If these aren't available, the non-'n'
+versions will be used, and they are sometimes not thread-safe.
+
+Uses: mkstemp, mktemp -- Are these, or our uses of them, likely to be
+thread-safe?
+
+Uses: sigaction
+
+The use of sigaction is in the code prompting for a password; we try
+to catch the keyboard interrupt character being used and turn it into
+an error return from that function.  THIS IS NOT THREAD-SAFE.
+
+Uses: tcgetattr, tcsetattr.  This is also in the password-prompting
+code.  These are fine as long as no other threads are accessing the
+same terminal at the same time.
+
+Uses: fopen.  This is thread-safe, actually, but a multi-threaded
+server is likely to be using lots of file descriptors.  On 32-bit
+Solaris platforms, fopen will not work if the next available file
+descriptor number is 256 or higher.  This can cause the keytab code to
+fail.
+
+Statics: prompter.c: interrupt flag
+
+Statics: ccdefops.c: default operations table pointer
+
+Statics: ktdefname.c: variable to override default keytab name, NO
+LOCKING.  DON'T TOUCH THESE VARIABLES, at least in threaded programs.
+
+Statics: conv_creds.c: debug variable
+
+Statics: sendto_kdc.c: debug variable, in export list for KDC
+
+Statics: parse.c: default realm cache, changed to not cache
+
+Statics: krb5_libinit.c: lib init aux data
+
+Statics: osconfig.c: various internal variables, probably should be const
+
+Statics: init_ctx.c: "brand" string; not written.
+
+Statics: cc_memory.c: list of caches, with mutex.
+
+Statics: c_ustime.c: last timestamp, to implement "microseconds must
+always increment"
+
+Statics: ktbase.c, ccbase.c, rc_base.c: type registries and mutexes.
+
+----------------
+
+libgssapi_krb5
+
+(TBD)
+
+Uses: ctype macros
+
+Statics: acquire_cred.c: name of keytab to use, and mutex.
+
+Statics: gssapi_krb5.c:
+
+Statics: init_sec_context.c:
+
+Statics: set_ccache.c:
+
+Statics: gssapi_generic.c: OID definitions, non-const by
+specification.  We probably could make them const anyways.
+
+The keytab name saved away by krb5_gss_register_acceptor_identity is
+global and protected by a mutex; the ccache name stored by
+gss_krb5_ccache_name is per-thread.  This inconsistency is due to the
+anticipated usage patterns.
+
+The old ccache name returned by gss_krb5_ccache_name if the last
+parameter is not a null pointer is also stored per-thread, and will be
+discarded at the next call to that routine from the same thread, or at
+thread termination.
+
+Needs work: check various objects for thread safety
+
+----------------
+
+libkrb4
+libdes425
+
+I don't think we're likely to bother with these.
+
+Part of the krb4 API requires keeping some internal storage across
+calls.
+
+----------------
+
+libgssrpc
+
+New version is in place.  Ignore it for now?
+
+----------------
+
+libkadm5*
+libkdb5
+
+Skip these for now.  We may want the KDC libraries to be thread-safe
+eventually, so the KDC can take better advantage of hyperthreaded or
+multiprocessor systems.
+
+----------------
+
+libapputils
+libpty
+libss
+
+Used by single-threaded programs only (but see above re KDC).  Don't
+bother for now.
diff --git a/krb5-1-6/doc/threads.txt b/krb5-1-6/doc/threads.txt
new file mode 100644
index 000000000..b161dafbc
--- /dev/null
+++ b/krb5-1-6/doc/threads.txt
@@ -0,0 +1,101 @@
+Thread safety in the MIT Kerberos libraries
+
+The return value from krb5_cc_default_name is a handle on internal
+storage from the krb5_context.  It is valid only until
+krb5_cc_set_default_name or krb5_free_context is called.  If
+krb5_cc_set_default_name may be called, the calling code must ensure
+that the storage returned by krb5_cc_default_name is no longer in use
+by that time.
+
+Any use of krb5_context must be confined to one thread at a time by
+the application code.
+
+Uses of credentials caches, replay caches, and keytabs may happen in
+multiple threads simultaneously as long as none of them destroys the
+object while other threads may still be using it.  (Any internal data
+modification in those objects will be protected by mutexes or other
+means, within the krb5 library.)
+
+The simple, exposed data structures in krb5.h like krb5_principal are
+not protected; they should not be used in one thread while another
+thread might be modifying them.  (TO DO: Build a list of which calls
+keep references to supplied data or return references to
+otherwise-referenced data, as opposed to everything making copies.)
+
+
+
+[ This part is a little outdated already. ]
+
+   // Between these two, we should be able to do pure compile-time
+   // and pure run-time initialization.
+   //   POSIX: partial initializer is PTHREAD_MUTEX_INITIALIZER,
+   //          finish does nothing
+   //   Windows: partial initializer is zero/empty,
+   //            finish does the actual work and runs at load time
+   //   debug: partial initializer sets one magic value,
+   //          finish verifies, sets a new magic value
+   k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+   int k5_mutex_finish_init(k5_mutex_t *);
+   // for dynamic allocation
+   int k5_mutex_init(k5_mutex_t *);
+   // Must work for both kinds of allocation, even if it means adding
+   // a flag.
+   int k5_mutex_destroy(k5_mutex_t *);
+   //
+   // Per library, one function to finish the static mutex
+   // initialization.
+   //
+   // A second function called at various possible "first" entry
+   // points which either calls pthread_once on the first function
+   // (POSIX), or checks some flag set by the first function (Windows,
+   // debug support), and possibly returns an error.
+   //
+   // A third function for library termination calls mutex_destroy on
+   // each mutex for the library.
+   //
+   // 
+   int k5_mutex_lock(k5_mutex_t *);
+   int k5_mutex_unlock(k5_mutex_t *);
+   // Optional (always defined, but need not do anything):
+   void k5_mutex_assert_locked(k5_mutex_t *);
+   void k5_mutex_assert_unlocked(k5_mutex_t *);
+
+
+   k5_key_t key;
+   int k5_key_create(k5_key_t *, void (*destructor)(void *));
+   void *k5_getspecific(k5_key_t);
+   int k5_setspecific(k5_key_t, const void *);
+   ... stuff to signal library termination ...
+
+This is **NOT** an exported interface, and is subject to change.
+
+On many platforms with weak reference support, we can declare certain
+symbols to be weak, and test the addresses before calling them.  The
+references generally will be non-null if the application pulls in the
+pthread support.  Sometimes stubs are present in the C library for
+some of these routines, and sometimes they're not functional; if so,
+we need to figure out which ones, and check for the presence of some
+*other* routines.
+
+AIX 4.3.3 doesn't support weak references.  However, it looks like
+calling dlsym(NULL) causes the pthread library to get loaded, so we're
+going to just go ahead and link against it anyways.
+
+On Tru64 we also link against the thread library always.
+
+
+For now, the basic model is:
+
+  If weak references supported, use them.
+  Else, assume support is present; if that means explicitly pulling in
+  the thread library, so be it.
+
+
+
+The locking described above may not be sufficient, at least for good
+performance.  At some point we may want to switch to read/write locks,
+so multiple threads can grovel over a data structure at once as long
+as they don't change it.
+
+
+See also notes in src/include/k5-thread.h.
diff --git a/krb5-1-6/doc/user-guide.texinfo b/krb5-1-6/doc/user-guide.texinfo
new file mode 100644
index 000000000..56f1c61dd
--- /dev/null
+++ b/krb5-1-6/doc/user-guide.texinfo
@@ -0,0 +1,1705 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@c guide
+@setfilename krb5-user.info
+@settitle Kerberos V5 UNIX User's Guide
+@setchapternewpage odd                  @c chapter begins on next odd page
+@c @setchapternewpage on                   @c chapter begins on next page
+@c @smallbook                              @c Format for 7" X 9.25" paper
+@c %**end of header
+
+@paragraphindent 0
+@iftex
+@parskip 6pt plus 6pt
+@end iftex
+
+@dircategory Kerberos
+@direntry
+* krb5-user: (krb5-user).               Kerberos V5 UNIX User's Guide
+@end direntry
+
+@include definitions.texinfo
+@set EDITION 1.0
+
+@finalout                               @c don't print black warning boxes
+
+@titlepage
+@title @value{PRODUCT} UNIX User's Guide
+@subtitle Release:  @value{RELEASE}
+@subtitle Document Edition:  @value{EDITION}
+@subtitle Last updated:  @value{UPDATED}
+@author @value{COMPANY}
+
+@page
+@vskip 0pt plus 1filll
+
+@end titlepage
+
+@comment  node-name,  next,  previous,  up
+@node Top, Copyright, (dir), (dir)
+
+@ifinfo
+This file describes how to use the @value{PRODUCT} client programs.
+@end ifinfo
+
+@c The master menu is updated using emacs19's M-x texinfo-all-menus-update
+@c function.  Don't forget to run M-x texinfo-every-node-update after
+@c you add a new section or subsection, or after you've rearranged the
+@c comand before each @section or @subsection!  All you need to enter
+@c is:
+@c
+@c @section New Section Name
+@c
+@c M-x texinfo-every-node-update will take care of calculating the
+@c node's forward and back pointers.
+@c
+@c ---------------------------------------------------------------------
+
+@menu
+* Copyright::                   
+* Introduction::                
+* Kerberos V5 Tutorial::        
+* Kerberos V5 Reference::       
+* Kerberos Glossary::           
+@end menu
+
+@node Copyright, Introduction, Top, Top
+@unnumbered Copyright
+
+@include copyright.texinfo
+
+@node Introduction, Kerberos V5 Tutorial, Copyright, Top
+@chapter Introduction
+
+@ifset CYGNUS
+@value{PRODUCT} is based on the Kerberos V5 authentication system
+developed at MIT.
+@end ifset
+@ifset MIT
+Kerberos V5 is an authentication system developed at MIT.
+@end ifset
+Kerberos is named for the three-headed watchdog from Greek mythology,
+who guarded the entrance to the underworld.
+
+Under Kerberos, a client (generally either a user or a service) sends a
+request for a ticket to the @i{Key Distribution Center} (KDC).  The KDC
+creates a @dfn{ticket-granting ticket} (TGT) for the client, encrypts it
+using the client's password as the key, and sends the encrypted TGT back
+to the client.  The client then attempts to decrypt the TGT, using its
+password.  If the client successfully decrypts the TGT (@i{i.e.}, if the
+client gave the correct password), it keeps the decrypted TGT, which
+indicates proof of the client's identity.
+
+The TGT, which expires at a specified time, permits the client to obtain
+additional tickets, which give permission for specific services.  The
+requesting and granting of these additional tickets is user-transparent.
+
+Since Kerberos negotiates authenticated, and optionally encrypted,
+communications between two points anywhere on the internet, it provides
+a layer of security that is not dependent on which side of a firewall
+either client is on.  Since studies have shown that half of the computer
+security breaches in industry happen from @i{inside} firewalls,
+@value{COMPANY}'s @value{PRODUCT} plays a vital role in maintaining your
+network security.
+
+The @value{PRODUCT} package is designed to be easy to use.  Most of the
+commands are nearly identical to UNIX network programs you already
+use.  @value{PRODUCT} is a @dfn{single-sign-on} system, which means
+that you have to type your password only once per session, and Kerberos
+does the authenticating and encrypting transparently.
+
+@menu
+* What is a Ticket?::           
+* What is a Kerberos Principal?::  
+@end menu
+
+@node What is a Ticket?, What is a Kerberos Principal?, Introduction, Introduction
+@section What is a Ticket?
+
+Your Kerberos @dfn{credentials}, or ``@dfn{tickets}'', are a set of
+electronic information that can be used to verify your identity.  Your
+Kerberos tickets may be stored in a file, or they may exist only in
+memory.
+
+The first ticket you obtain is a @dfn{ticket-granting ticket}, which
+permits you to obtain additional tickets.  These additional tickets give
+you permission for specific services.  The requesting and granting of
+these additional tickets happens transparently.
+
+A good analogy for the ticket-granting ticket is a three-day ski pass
+that is good at four different resorts.  You show the pass at whichever
+resort you decide to go to (until it expires), and you receive a lift
+ticket for that resort.  Once you have the lift ticket, you can ski all
+you want at that resort.  If you go to another resort the next day, you
+once again show your pass, and you get an additional lift ticket for the
+new resort.  The difference is that the @value{PRODUCT} programs notice
+that you have the weekend ski pass, and get the lift ticket for you, so
+you don't have to perform the transactions yourself.
+
+@node What is a Kerberos Principal?,  , What is a Ticket?, Introduction
+@section What is a Kerberos Principal?
+
+A Kerberos @dfn{principal} is a unique identity to which Kerberos can
+assign tickets.  Principals can have an arbitrary number of
+components.  Each component is separated by a component separator,
+generally `/'.  The last component is the realm, separated from the
+rest of the principal by the realm separator, generally `@@'.  If there
+is no realm component in the principal, then it will be assumed that
+the principal is in the default realm for the context in which it is
+being used.
+
+Traditionally, a principal is divided into three parts:  the
+@dfn{primary}, the @dfn{instance}, and the @dfn{realm}.  The format of
+a typical Kerberos V5 principal is @code{primary/instance@@REALM}.
+
+@itemize @bullet
+@item The @dfn{primary} is the first part of the principal.  In the case
+of a user, it's the same as your username.  For a host, the primary is
+the word @code{host}.
+
+@item The @dfn{instance} is an optional string that qualifies the
+primary.  The instance is separated from the primary by a slash
+(@code{/}).  In the case of a user, the instance is usually null, but a
+user might also have an additional principal, with an instance called
+@samp{admin}, which he/she uses to administrate a database.  The
+principal @code{@value{RANDOMUSER1}@@@value{PRIMARYREALM}} is completely
+separate from the principal
+@code{@value{RANDOMUSER1}/admin@@@value{PRIMARYREALM}}, with a separate
+password, and separate permissions.  In the case of a host, the instance
+is the fully qualified hostname, e.g.,
+@code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}}.
+
+@item The @dfn{realm} is your Kerberos realm.  In most cases, your
+Kerberos realm is your domain name, in upper-case letters.  For example,
+the machine @code{@value{RANDOMHOST1}.@value{SECONDDOMAIN}} would be in
+the realm @code{@value{SECONDREALM}}.
+@end itemize
+
+@node Kerberos V5 Tutorial, Kerberos V5 Reference, Introduction, Top
+@chapter Kerberos V5 Tutorial
+
+This tutorial is intended to familiarize you with the @value{PRODUCT}
+client programs.  We will represent your prompt as ``@code{shell%}''.
+So an instruction to type the ``@kbd{ls}'' command would be represented as
+follows:
+
+@need 600
+@smallexample
+@group
+@b{shell%} ls
+@end group
+@end smallexample
+
+In these examples, we will use sample usernames, such as
+@code{@value{RANDOMUSER1}} and @code{@value{RANDOMUSER2}}, sample
+hostnames, such as @code{@value{RANDOMHOST1}} and
+@code{@value{RANDOMHOST2}}, and sample domain names, such as
+@code{@value{PRIMARYDOMAIN}} and @code{@value{SECONDDOMAIN}}.  When you
+see one of these, substitute your username, hostname, or domain name
+accordingly.
+
+@menu
+* Setting Up to Use Kerberos V5::  
+* Ticket Management::           
+* Password Management::         
+* Kerberos V5 Applications::    
+@end menu
+
+@node Setting Up to Use Kerberos V5, Ticket Management, Kerberos V5 Tutorial, Kerberos V5 Tutorial
+@section Setting Up to Use @value{PRODUCT}
+
+Your system administrator will have installed the @value{PRODUCT}
+programs in whichever directory makes the most sense for your system.
+We will use @code{@value{ROOTDIR}} throughout this guide to refer to the
+top-level directory @value{PRODUCT} directory.  We will therefor use
+@code{@value{BINDIR}} to denote the location of the @value{PRODUCT} user
+programs.  In your installation, the directory name may be different,
+but whatever the directory name is, you should make sure it is included
+in your path.  You will probably want to put it @i{ahead of} the
+directories @code{/bin} and @code{/usr/bin} so you will get the
+@value{PRODUCT} network programs, rather than the standard UNIX
+versions, when you type their command names.
+
+@node Ticket Management, Password Management, Setting Up to Use Kerberos V5, Kerberos V5 Tutorial
+@section Ticket Management
+
+On many systems, Kerberos is built into the login program, and you get
+tickets automatically when you log in.  Other programs, such as
+@code{rsh}, @code{rcp}, @code{telnet}, and @code{rlogin}, can forward
+copies of your tickets to the remote host.  Most of these programs also
+automatically destroy your tickets when they exit.  However,
+@value{COMPANY} recommends that you explicitly destroy your Kerberos
+tickets when you are through with them, just to be sure.  One way to
+help ensure that this happens is to add the @code{kdestroy} command to
+your @code{.logout} file.  Additionally, if you are going to be away
+from your machine and are concerned about an intruder using your
+permissions, it is safest to either destroy all copies of your tickets,
+or use a screensaver that locks the screen.
+
+@need 2000
+@menu
+* Kerberos Ticket Properties::  
+* Obtaining Tickets with kinit::  
+* Viewing Your Tickets with klist::  
+* Destroying Your Tickets with kdestroy::  
+@end menu
+
+@node Kerberos Ticket Properties, Obtaining Tickets with kinit, Ticket Management, Ticket Management
+@subsection Kerberos Ticket Properties
+
+@noindent
+There are various properties that Kerberos tickets can have:
+
+If a ticket is @dfn{forwardable}, then the KDC can issue a new ticket with
+a different network address based on the forwardable ticket.  This
+allows for authentication forwarding without requiring a password to be
+typed in again.  For example, if a user with a forwardable TGT logs
+into a remote system, the KDC could issue a new TGT for that user with
+the network address of the remote system, allowing authentication on
+that host to work as though the user were logged in locally.
+
+When the KDC creates a new ticket based on a forwardable ticket, it
+sets the @dfn{forwarded} flag on that new ticket.  Any tickets that are
+created based on a ticket with the forwarded flag set will also have
+their forwarded flags set.
+
+A @dfn{proxiable} ticket is similar to a forwardable ticket in that it
+allows a service to take on the identity of the client.  Unlike a
+forwardable ticket, however, a proxiable ticket is only issued for
+specific services.  In other words, a ticket-granting ticket cannot be
+issued based on a ticket that is proxiable but not forwardable.
+
+A @dfn{proxy} ticket is one that was issued based on a proxiable ticket.
+
+A @dfn{postdated} ticket is issued with the @i{invalid} flag set.
+After the starting time listed on the ticket, it can be presented to
+the KDC to obtain valid tickets.  
+
+Tickets with the @dfn{postdateable} flag set can be used to issue postdated
+tickets.
+
+@dfn{Renewable} tickets can be used to obtain new session keys without
+the user entering their password again.  A renewable ticket has two
+expiration times.  The first is the time at which this particular
+ticket expires.  The second is the latest possible expiration time for
+any ticket issued based on this renewable ticket.
+
+A ticket with the @dfn{initial} flag set was issued based on the
+authentication protocol, and not on a ticket-granting ticket.   Clients
+that wish to ensure that the user's key has been recently presented for
+verification could specify that this flag must be set to accept the
+ticket.
+
+An @dfn{invalid} ticket must be rejected by application servers.  Postdated
+tickets are usually issued with this flag set, and must be validated by
+the KDC before they can be used.
+
+A @dfn{preauthenticated} ticket is one that was only issued after the
+client requesting the ticket had authenticated itself to the KDC.
+
+The @dfn{hardware authentication} flag is set on a ticket which
+required the use of hardware for authentication.  The hardware is
+expected to be possessed only by the client which requested the
+tickets.
+
+If a ticket has the @dfn{transit policy checked} flag set, then the KDC that
+issued this ticket implements the transited-realm check policy and
+checked the transited-realms list on the ticket.  The transited-realms
+list contains a list of all intermediate realms between the realm of the
+KDC that issued the first ticket and that of the one that issued the
+current ticket.  If this flag is not set, then the application server
+must check the transited realms itself or else reject the ticket.
+
+The @dfn{okay as delegate} flag indicates that the server specified in
+the ticket is suitable as a delegate as determined by the policy of
+that realm.  A server that is acting as a delegate has been granted a
+proxy or a forwarded TGT.  This flag is a new addition to the
+@value{PRODUCT} protocol and is not yet implemented on MIT servers.
+
+An @dfn{anonymous}  ticket is one in which the named principal is a generic
+principal for that realm; it does not actually specify the individual
+that will be using the ticket.  This ticket is meant only to securely
+distribute a session key.  This is a new addition to the @value{PRODUCT}
+protocol and is not yet implemented on MIT servers.
+
+@node Obtaining Tickets with kinit, Viewing Your Tickets with klist, Kerberos Ticket Properties, Ticket Management
+@subsection Obtaining Tickets with kinit
+
+If your site is using the @value{PRODUCT} login program, you will get
+Kerberos tickets automatically when you log in.  If your site uses a
+different login program, you may need to explicitly obtain your Kerberos
+tickets, using the @code{kinit} program.  Similarly, if your Kerberos
+tickets expire, use the @code{kinit} program to obtain new ones.
+
+@need 1500
+To use the @code{kinit} program, simply type @kbd{kinit} and then type
+your password at the prompt.  For example, Jennifer (whose username is
+@code{@value{RANDOMUSER1}}) works for Bleep, Inc. (a fictitious company
+with the domain name @code{@value{PRIMARYDOMAIN}} and the Kerberos realm
+@code{@value{PRIMARYREALM}}).  She would type:
+
+@smallexample
+@group
+@b{shell%} kinit
+@b{Password for @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<-- [Type @value{RANDOMUSER1}'s password here.]}
+@b{shell%}
+@end group
+@end smallexample
+
+@need 1000
+If you type your password incorrectly, kinit will give you the following
+error message:
+
+@smallexample
+@group
+@b{shell%} kinit
+@b{Password for @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<-- [Type the wrong password here.]}
+@b{kinit: Password incorrect}
+@b{shell%}
+@end group
+@end smallexample
+
+@noindent and you won't get Kerberos tickets.
+
+@noindent Notice that @code{kinit} assumes you want tickets for your own
+username in your default realm.  
+@need 1500
+Suppose Jennifer's friend David is visiting, and he wants to borrow a
+window to check his mail.  David needs to get tickets for himself in his
+own realm, @value{SECONDREALM}.@footnote{Note:  the realm
+@value{SECONDREALM} must be listed in your computer's Kerberos
+configuration file, @code{/etc/krb5.conf}.}  He would type:
+
+@smallexample
+@group
+@b{shell%} kinit @value{RANDOMUSER2}@@@value{SECONDREALM}
+@b{Password for @value{RANDOMUSER2}@@@value{SECONDREALM}:} @i{<-- [Type @value{RANDOMUSER2}'s password here.]}
+@b{shell%}
+@end group
+@end smallexample
+
+@noindent David would then have tickets which he could use to log onto
+his own machine.  Note that he typed his password locally on Jennifer's
+machine, but it never went over the network.  Kerberos on the local host
+performed the authentication to the KDC in the other realm.
+
+@need 1000
+If you want to be able to forward your tickets to another host, you need
+to request @dfn{forwardable} tickets.  You do this by specifying the
+@kbd{-f} option:
+
+@smallexample
+@group
+@b{shell%} kinit -f
+@b{Password for @value{RANDOMUSER1}@@@value{PRIMARYREALM}:} @i{<-- [Type your password here.]}
+@b{shell%}
+@end group
+@end smallexample
+
+@noindent
+Note that @code{kinit} does not tell you that it obtained forwardable
+tickets; you can verify this using the @code{klist} command
+(@pxref{Viewing Your Tickets with klist}).
+
+Normally, your tickets are good for your system's default ticket
+lifetime, which is ten hours on many systems.  You can specify a
+different ticket lifetime with the @samp{-l} option.  Add the letter
+@samp{s} to the value for seconds, @samp{m} for minutes, @samp{h} for
+hours, or @samp{d} for days.
+@need 1500
+For example, to obtain forwardable tickets for
+@code{@value{RANDOMUSER2}@@@value{SECONDREALM}} that would be good for
+three hours, you would type:
+
+@smallexample
+@group
+@b{shell%} kinit -f -l 3h @value{RANDOMUSER2}@@@value{SECONDREALM}
+@b{Password for @value{RANDOMUSER2}@@@value{SECONDREALM}:} @i{<-- [Type @value{RANDOMUSER2}'s password here.]}
+@b{shell%}
+@end group
+@end smallexample
+
+@noindent
+You cannot mix units; specifying a lifetime of @samp{3h30m} would result
+in an error.  Note also that most systems specify a maximum ticket
+lifetime.  If you request a longer ticket lifetime, it will be
+automatically truncated to the maximum lifetime.
+
+@node Viewing Your Tickets with klist, Destroying Your Tickets with kdestroy, Obtaining Tickets with kinit, Ticket Management
+@subsection Viewing Your Tickets with klist
+
+The @code{klist} command shows your tickets.  When you first obtain
+tickets, you will have only the ticket-granting ticket.  (@xref{What is
+a Ticket?}.)  The listing would look like this:
+
+@smallexample
+@group
+@b{shell%} klist
+Ticket cache: /tmp/krb5cc_ttypa
+Default principal: @value{RANDOMUSER1}@@@value{PRIMARYREALM}
+
+Valid starting     Expires            Service principal
+06/07/04 19:49:21  06/08/04 05:49:19  krbtgt/@value{PRIMARYREALM}@@@value{PRIMARYREALM}
+@b{shell%}
+@end group
+@end smallexample
+
+@noindent
+The ticket cache is the location of your ticket file.  In the above
+example, this file is named @code{/tmp/krb5cc_ttypa}.  The default
+principal is your kerberos @dfn{principal}.  (@pxref{What is a Kerberos
+Principal?})
+
+The ``valid starting'' and ``expires'' fields describe the period of
+time during which the ticket is valid.  The @dfn{service principal}
+describes each ticket.  The ticket-granting ticket has the primary
+@code{krbtgt}, and the instance is the realm name.
+
+@need 2000
+Now, if @value{RANDOMUSER1} connected to the machine
+@code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}}, and then typed
+@kbd{klist} again, she would have gotten the following result:
+
+@smallexample
+@group
+@b{shell%} klist
+Ticket cache: /tmp/krb5cc_ttypa
+Default principal: @value{RANDOMUSER1}@@@value{PRIMARYREALM}
+
+Valid starting     Expires            Service principal
+06/07/04 19:49:21  06/08/04 05:49:19  krbtgt/@value{PRIMARYREALM}@@@value{PRIMARYREALM}
+06/07/04 20:22:30  06/08/04 05:49:19  host/@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}
+@b{shell%}
+@end group
+@end smallexample
+
+@noindent
+Here's what happened:  when @value{RANDOMUSER1} used telnet to connect
+to the host @code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}}, the telnet
+program presented her ticket-granting ticket to the KDC and requested a
+host ticket for the host
+@code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}}.  The KDC sent the host
+ticket, which telnet then presented to the host
+@code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}}, and she was allowed to
+log in without typing her password.
+
+@need 3000
+Suppose your Kerberos tickets allow you to log into a host in another
+domain, such as @code{@value{RANDOMHOST2}.@value{SECONDDOMAIN}}, which
+is also in another Kerberos realm, @code{@value{SECONDREALM}}.  If you
+telnet to this host, you will receive a ticket-granting ticket for the
+realm @code{@value{SECONDREALM}}, plus the new @code{host} ticket for
+@code{@value{RANDOMHOST2}.@value{SECONDDOMAIN}}.  @kbd{klist} will now
+show:
+
+@smallexample
+@group
+@b{shell%} klist
+Ticket cache: /tmp/krb5cc_ttypa
+Default principal: @value{RANDOMUSER1}@@@value{PRIMARYREALM}
+
+Valid starting     Expires            Service principal
+06/07/04 19:49:21  06/08/04 05:49:19  krbtgt/@value{PRIMARYREALM}@@@value{PRIMARYREALM}
+06/07/04 20:22:30  06/08/04 05:49:19  host/@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}
+06/07/04 20:24:18  06/08/04 05:49:19  krbtgt/@value{SECONDREALM}@@@value{PRIMARYREALM}
+06/07/04 20:24:18  06/08/04 05:49:19  host/@value{RANDOMHOST2}.@value{SECONDDOMAIN}@@@value{PRIMARYREALM}
+@b{shell%}
+@end group
+@end smallexample
+
+You can use the @code{-f} option to view the @dfn{flags} that apply to
+your tickets.  The flags are:
+
+@table @b
+@itemx F
+@b{F}orwardable
+@itemx f
+@b{f}orwarded
+@itemx P
+@b{P}roxiable
+@itemx p
+@b{p}roxy
+@itemx D
+post@b{D}ateable
+@itemx d
+post@b{d}ated
+@itemx R
+@b{R}enewable
+@itemx I
+@b{I}nitial
+@itemx i
+@b{i}nvalid
+@itemx H
+@b{H}ardware authenticated
+@itemx A
+pre@b{A}uthenticated
+@itemx T
+@b{T}ransit policy checked
+@itemx O
+@b{O}kay as delegate
+@itemx a
+@b{a}nonymous
+@end table
+
+@need 1500
+Here is a sample listing.  In this example, the user @value{RANDOMUSER1}
+obtained her initial tickets (@samp{I}), which are forwardable
+(@samp{F}) and postdated (@samp{d}) but not yet validated (@samp{i}).
+(@xref{kinit Reference}, for more information about postdated tickets.)
+
+@smallexample
+@group
+@b{shell%} klist -f
+@b{Ticket cache: /tmp/krb5cc_320
+Default principal: @value{RANDOMUSER1}@@@value{PRIMARYREALM}
+
+Valid starting      Expires             Service principal
+31/07/05 19:06:25  31/07/05 19:16:25  krbtgt/@value{PRIMARYREALM}@@@value{PRIMARYREALM}
+        Flags: FdiI
+shell%}
+@end group
+@end smallexample
+
+@need 1500
+In the following example, the user @value{RANDOMUSER2}'s tickets were
+forwarded (@samp{f}) to this host from another host.  The tickets are
+reforwardable (@samp{F}).
+
+@smallexample
+@group
+@b{shell%} klist -f
+@b{Ticket cache: /tmp/krb5cc_p11795
+Default principal: @value{RANDOMUSER2}@@@value{SECONDREALM}
+
+Valid starting     Expires            Service principal
+07/31/05 11:52:29  07/31/05 21:11:23  krbtgt/@value{SECONDREALM}@@@value{SECONDREALM}
+        Flags: Ff
+07/31/05 12:03:48  07/31/05 21:11:23  host/@value{RANDOMHOST2}.@value{SECONDDOMAIN}@@@value{SECONDREALM}
+        Flags: Ff
+shell%}
+@end group
+@end smallexample
+
+@node Destroying Your Tickets with kdestroy,  , Viewing Your Tickets with klist, Ticket Management
+@subsection Destroying Your Tickets with kdestroy
+
+Your Kerberos tickets are proof that you are indeed yourself, and
+tickets can be stolen.  If this happens, the person who has them can
+masquerade as you until they expire.  For this reason, you should
+destroy your Kerberos tickets when you are away from your computer.
+
+@need 1000
+Destroying your tickets is easy.  Simply type @kbd{kdestroy}.
+
+@smallexample
+@group
+@b{shell%} kdestroy
+@b{shell%}
+@end group
+@end smallexample
+
+@need 1500
+If @code{kdestroy} fails to destroy your tickets, it will beep and give
+an error message.  For example, if @code{kdestroy} can't find any
+tickets to destroy, it will give the following message:
+
+@smallexample
+@group
+@b{shell%} kdestroy
+@b{kdestroy: No credentials cache file found while destroying cache
+shell%}
+@end group
+@end smallexample
+
+@node Password Management, Kerberos V5 Applications, Ticket Management, Kerberos V5 Tutorial
+@section Password Management
+
+Your password is the only way Kerberos has of verifying your identity.
+If someone finds out your password, that person can masquerade as
+you---send email that comes from you, read, edit, or delete your files,
+or log into other hosts as you---and no one will be able to tell the
+difference.  For this reason, it is important that you choose a good
+password (@pxref{Password Advice}), and keep it secret.  If you need to
+give access to your account to someone else, you can do so through
+Kerberos.  (@xref{Granting Access to Your Account}.)  You should
+@i{never} tell your password to anyone, including your system
+administrator, for any reason.  You should change your password
+frequently, particularly any time you think someone may have found out
+what it is.
+
+@menu
+* Changing Your Password::      
+* Password Advice::             
+* Granting Access to Your Account::  
+@end menu
+
+@node Changing Your Password, Password Advice, Password Management, Password Management
+@subsection Changing Your Password
+
+@need 2500
+To change your Kerberos password, use the @code{kpasswd} command.  It
+will ask you for your old password (to prevent someone else from walking
+up to your computer when you're not there and changing your password),
+and then prompt you for the new one twice.  (The reason you have to type
+it twice is to make sure you have typed it correctly.)  For example,
+user @code{@value{RANDOMUSER2}} would do the following:
+
+@smallexample
+@group
+@b{shell%} kpasswd
+@b{Password for @value{RANDOMUSER2}:}    @i{<- Type your old password.}
+@b{Enter new password:}    @i{<- Type your new password.}
+@b{Enter it again:}  @i{<- Type the new password again.}
+@b{Password changed.}
+@b{shell%}
+@end group
+@end smallexample
+
+@need 1800
+If @value{RANDOMUSER2} typed the incorrect old password, he would get
+the following message:
+
+@smallexample
+@group
+@b{shell%} kpasswd
+@b{Password for @value{RANDOMUSER2}:}  @i{<- Type the incorrect old password.}
+@b{kpasswd: Password incorrect while getting initial ticket
+shell%}
+@end group
+@end smallexample
+
+@need 2500
+If you make a mistake and don't type the new password the same way
+twice, @code{kpasswd} will ask you to try again:
+
+@smallexample
+@group
+@b{shell%} kpasswd
+@b{Password for @value{RANDOMUSER2}:}  @i{<- Type the old password.}
+@b{Enter new password:}  @i{<- Type the new password.}
+@b{Enter it again:} @i{<- Type a different new password.}
+@b{kpasswd: Password mismatch while reading password
+shell%}
+@end group
+@end smallexample
+
+Once you change your password, it takes some time for the change to
+propagate through the system.  Depending on how your system is set up,
+this might be anywhere from a few minutes to an hour or more.  If you
+need to get new Kerberos tickets shortly after changing your password,
+try the new password.  If the new password doesn't work, try again using
+the old one.
+
+@node Password Advice, Granting Access to Your Account, Changing Your Password, Password Management
+@subsection Password Advice
+
+Your password can include almost any character you can type (except
+control keys and the ``enter'' key).  A good password is one you can
+remember, but that no one else can easily guess.  Examples of @i{bad}
+passwords are words that can be found in a dictionary, any common or
+popular name, especially a famous person (or cartoon character), your
+name or username in any form (@i{e.g.}, forward, backward, repeated
+twice, @i{etc.}), your spouse's, child's, or pet's name, your birth
+date, your social security number, and any sample password that appears
+in this (or any other) manual.
+
+@need 2200
+@value{COMPANY} recommends that your password be at least 6 characters
+long, and contain UPPER- and lower-case letters, numbers, and/or
+punctuation marks.  Some passwords that would be good if they weren't
+listed in this manual include:
+
+@itemize @bullet
+@item some initials, like ``GykoR-66.'' for ``Get your kicks on Route
+66.''
+
+@item an easy-to-pronounce nonsense word, like ``slaRooBey'' or
+``krang-its''
+
+@item a misspelled phrase, like ``2HotPeetzas!'' or ``ItzAGurl!!!''
+@end itemize
+
+@noindent Note:  don't actually use any of the above passwords.  They're
+only meant to show you how to make up a good password.  Passwords that
+appear in a manual are the first ones intruders will try.
+
+@need 3800 
+@value{PRODUCT} allows your system administrators to automatically
+reject bad passwords, based on certain criteria, such as a password
+dictionary or a minimum length.  For example, if the user
+@code{@value{RANDOMUSER1}}, who had a policy "strict" that required a
+minimum of 8 characaters, chose a password that was less than 8
+characters, Kerberos would give an error message like the following:
+
+@smallexample
+@group
+@b{shell%} kpasswd
+@b{Password for @value{RANDOMUSER1}:}  @i{<- Type your old password here.}
+
+@value{RANDOMUSER1}'s password is controlled by the policy strict, which
+requires a minimum of 8 characters from at least 3 classes (the five classes
+are lowercase, uppercase, numbers, punctuation, and all other characters).
+
+@b{Enter new password:}  @i{<- Type an insecure new password.}
+@b{Enter it again:}  @i{<- Type it again.}
+
+kpasswd: Password is too short while attempting to change password.
+Please choose another password.
+
+@b{Enter new password:}  @i{<- Type a good password here.}
+@b{Enter it again:}  @i{<- Type it again.}
+@b{Password changed.
+shell%}
+@end group
+@end smallexample
+
+@noindent Your system administrators can choose the message that is
+displayed if you choose a bad password, so the message you see may be
+different from the above example.
+
+@node Granting Access to Your Account,  , Password Advice, Password Management
+@subsection Granting Access to Your Account
+
+@need 1800
+If you need to give someone access to log into your account, you can do
+so through Kerberos, without telling the person your password.  Simply
+create a file called @code{.k5login} in your home directory.  This file
+should contain the Kerberos principal (@xref{What is a Kerberos
+Principal?}.) of each person to whom you wish to give access.  Each
+principal must be on a separate line.  Here is a sample @code{.k5login}
+file:
+
+@smallexample
+@group
+@value{RANDOMUSER1}@@@value{PRIMARYREALM}
+@value{RANDOMUSER2}@@@value{SECONDREALM}
+@end group
+@end smallexample
+
+@noindent This file would allow the users @code{@value{RANDOMUSER1}} and
+@code{@value{RANDOMUSER2}} to use your user ID, provided that they had
+Kerberos tickets in their respective realms.  If you will be logging
+into other hosts across a network, you will want to include your own
+Kerberos principal in your @code{.k5login} file on each of these hosts.
+
+@need 1000
+Using a @code{.k5login} file is much safer than giving out your
+password, because:
+
+@itemize @bullet
+@item You can take access away any time simply by removing the principal
+from your @code{.k5login} file.
+
+@item Although the user has full access to your account on one
+particular host (or set of hosts if your @code{.k5login} file is shared,
+@i{e.g.}, over NFS), that user does not inherit your network privileges.
+
+@item Kerberos keeps a log of who obtains tickets, so a system
+administrator could find out, if necessary, who was capable of using
+your user ID at a particular time.
+@end itemize
+
+One common application is to have a @code{.k5login} file in
+@code{root}'s home directory, giving root access to that machine to the
+Kerberos principals listed.  This allows system administrators to allow
+users to become root locally, or to log in remotely as @code{root},
+without their having to give out the root password, and without anyone
+having to type the root password over the network.
+
+@node Kerberos V5 Applications,  , Password Management, Kerberos V5 Tutorial
+@section Kerberos V5 Applications
+
+@value{PRODUCT} is a @dfn{single-sign-on} system.  This means that you
+only have to type your password once, and the @value{PRODUCT} programs
+do the authenticating (and optionally encrypting) for you.  The way this
+works is that Kerberos has been built into each of a suite of network
+programs.  For example, when you use a @value{PRODUCT} program to
+connect to a remote host, the program, the KDC, and the remote host
+perform a set of rapid negotiations.  When these negotiations are
+completed, your program has proven your identity on your behalf to the
+remote host, and the remote host has granted you access, all in the
+space of a few seconds.
+
+The @value{PRODUCT} applications are versions of existing UNIX network
+programs with the Kerberos features added.
+
+@menu
+* Overview of Additional Features::  
+* telnet::                      
+* rlogin::                      
+* FTP::                         
+* rsh::                         
+* rcp::                         
+* ksu::                         
+@end menu
+
+@node Overview of Additional Features, telnet, Kerberos V5 Applications, Kerberos V5 Applications
+@subsection Overview of Additional Features
+
+The @value{PRODUCT} @dfn{network programs} are those programs that
+connect to another host somewhere on the internet.  These programs
+include @code{rlogin}, @code{telnet}, @code{ftp}, @code{rsh},
+@code{rcp}, and @code{ksu}.  These programs have all of the original
+features of the corresponding non-Kerberos @code{rlogin}, @code{telnet},
+@code{ftp}, @code{rsh}, @code{rcp}, and @code{su} programs, plus
+additional features that transparently use your Kerberos tickets for
+negotiating authentication and optional encryption with the remote host.
+In most cases, all you'll notice is that you no longer have to type your
+password, because Kerberos has already proven your identity.
+
+The @value{PRODUCT} network programs allow you the options of forwarding
+your tickets to the remote host (if you obtained forwardable tickets
+with the @code{kinit} program; @pxref{Obtaining Tickets with kinit}), and
+encrypting data transmitted between you and the remote host.
+
+This section of the tutorial assumes you are familiar with the
+non-Kerberos versions of these programs, and highlights the Kerberos
+functions added in the @value{PRODUCT} package.
+
+@node telnet, rlogin, Overview of Additional Features, Kerberos V5 Applications
+@subsection telnet
+
+The @value{PRODUCT} @code{telnet} command works exactly like the
+standard UNIX telnet program, with the following Kerberos options added:
+
+@table @kbd
+@itemx -f
+forwards a copy of your tickets to the remote host.
+
+@itemx -F
+forwards a copy of your tickets to the remote host, and marks them
+re-forwardable from the remote host.
+
+@itemx -k @i{realm}
+requests tickets for the remote host in the specified realm, instead of
+determining the realm itself.
+
+@itemx -K
+uses your tickets to authenticate to the remote host, but does not log
+you in.
+
+@itemx -a
+attempt automatic login using your tickets.  @code{telnet} will assume
+the same username unless you explicitly specify another.
+
+@itemx -x
+turns on encryption.
+
+@end table
+
+@need 4000
+For example, if @code{@value{RANDOMUSER2}} wanted to use the standard
+UNIX telnet to connect to the machine
+@code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}}, he would type:
+
+@smallexample
+@group
+@b{shell%} telnet @value{RANDOMHOST1}.@value{SECONDDOMAIN}
+@b{Trying 128.0.0.5 ...
+Connected to @value{RANDOMHOST1}.@value{SECONDDOMAIN}.
+Escape character is '^]'.
+
+NetBSD/i386 (daffodil) (ttyp3)
+
+login:} @value{RANDOMUSER2}
+@b{Password:}    @i{<- @value{RANDOMUSER2} types his password here}
+@b{Last login: Fri Jun 21 17:13:11 from @value{RANDOMHOST2}.@value{PRIMARYDOMAIN}
+Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
+        The Regents of the University of California.   All rights reserved.
+
+NetBSD 1.1: Tue May 21 00:31:42 EDT 1996
+
+Welcome to NetBSD!
+shell%}
+@end group
+@end smallexample
+
+@noindent Note that the machine
+@code{@value{RANDOMHOST1}.@value{SECONDDOMAIN}} asked for
+@code{@value{RANDOMUSER2}}'s password.  When he typed it, his password
+was sent over the network unencrypted.  If an intruder were watching
+network traffic at the time, that intruder would know
+@code{@value{RANDOMUSER2}}'s password.
+
+@need 4000
+If, on the other hand, @code{@value{RANDOMUSER1}} wanted to use the
+@value{PRODUCT} telnet to connect to the machine
+@code{@value{RANDOMHOST2}.@value{PRIMARYDOMAIN}}, she could forward a
+copy of her tickets, request an encrypted session, and log on as herself
+as follows:
+
+@smallexample
+@group
+@b{shell%} telnet -a -f -x @value{RANDOMHOST2}.@value{PRIMARYDOMAIN}
+@b{Trying 128.0.0.5...
+Connected to @value{RANDOMHOST2}.@value{PRIMARYDOMAIN}.
+Escape character is '^]'.
+[ Kerberos V5 accepts you as ``@value{RANDOMUSER1}@@@value{PRIMARYDOMAIN}'' ]
+[ Kerberos V5 accepted forwarded credentials ]
+What you type is protected by encryption.
+Last login: Tue Jul 30 18:47:44 from @value{RANDOMHOST1}.@value{SECONDDOMAIN}
+Athena Server (sun4) Version 9.1.11 Tue Jul 30 14:40:08 EDT 2002
+
+shell%}
+@end group
+@end smallexample
+
+@noindent Note that @code{@value{RANDOMUSER1}}'s machine used Kerberos
+to authenticate her to @code{@value{RANDOMHOST2}.@value{PRIMARYDOMAIN}},
+and logged her in automatically as herself.  She had an encrypted
+session, a copy of her tickets already waiting for her, and she never
+typed her password.
+
+If you forwarded your Kerberos tickets, @code{telnet} automatically
+destroys them when it exits.  The full set of options to @value{PRODUCT}
+@code{telnet} are discussed in the Reference section of this manual.
+(@pxref{telnet Reference})
+
+@need 2000
+@node rlogin, FTP, telnet, Kerberos V5 Applications
+@subsection rlogin
+
+@need 1000
+The @value{PRODUCT} @code{rlogin} command works exactly like the
+standard UNIX rlogin program, with the following Kerberos options added:
+
+@table @kbd
+@itemx -f
+forwards a copy of your tickets to the remote host.
+
+@itemx -F
+forwards a copy of your tickets to the remote host, and marks them
+re-forwardable from the remote host.
+
+@itemx -k @i{realm}
+requests tickets for the remote host in the specified realm, instead of
+determining the realm itself.
+
+@itemx -x
+encrypts the input and output data streams (the username is sent unencrypted)
+
+@end table
+
+@need 3000
+For example, if @code{@value{RANDOMUSER2}} wanted to use the standard
+UNIX rlogin to connect to the machine
+@code{@value{RANDOMHOST1}.@value{SECONDDOMAIN}}, he would type:
+
+@smallexample
+@group
+@b{shell%} rlogin @value{RANDOMHOST1}.@value{SECONDDOMAIN} -l @value{RANDOMUSER2}
+@b{Password:}  @i{<- @value{RANDOMUSER2} types his password here}
+@b{Last login: Fri Jun 21 10:36:32 from :0.0
+Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
+        The Regents of the University of California.   All rights reserved.
+
+NetBSD 1.1: Tue May 21 00:31:42 EDT 1996
+
+Welcome to NetBSD!
+shell%}
+@end group
+@end smallexample
+
+@noindent Note that the machine
+@code{@value{RANDOMHOST1}.@value{SECONDDOMAIN}} asked for
+@code{@value{RANDOMUSER2}}'s password.  When he typed it, his password
+was sent over the network unencrypted.  If an intruder were watching
+network traffic at the time, that intruder would know
+@code{@value{RANDOMUSER2}}'s password.
+
+@need 4000
+If, on the other hand, @code{@value{RANDOMUSER1}} wanted to use
+@value{PRODUCT} rlogin to connect to the machine
+@code{@value{RANDOMHOST2}.@value{PRIMARYDOMAIN}}, she could forward a
+copy of her tickets, mark them as not forwardable from the remote host,
+and request an encrypted session as follows:
+
+@smallexample
+@group
+@b{shell%} rlogin @value{RANDOMHOST2}.@value{PRIMARYDOMAIN} -f -x
+@b{This rlogin session is using DES encryption for all data transmissions.
+Last login: Thu Jun 20 16:20:50 from @value{RANDOMHOST1}
+Athena Server (sun4) Version 9.1.11 Tue Jul 30 14:40:08 EDT 2002
+shell%}
+@end group
+@end smallexample
+
+@noindent Note that @code{@value{RANDOMUSER1}}'s machine used Kerberos
+to authenticate her to @code{@value{RANDOMHOST2}.@value{PRIMARYDOMAIN}},
+and logged her in automatically as herself.  She had an encrypted
+session, a copy of her tickets were waiting for her, and she never typed
+her password.
+
+If you forwarded your Kerberos tickets, @code{rlogin} automatically
+destroys them when it exits.  The full set of options to @value{PRODUCT}
+@code{rlogin} are discussed in the Reference section of this manual.
+(@pxref{rlogin Reference})
+
+@node FTP, rsh, rlogin, Kerberos V5 Applications
+@subsection FTP
+
+@need 1000
+The @value{PRODUCT} @code{FTP} program works exactly like the standard
+UNIX FTP program, with the following Kerberos features added:
+
+@table @kbd
+@itemx -k @i{realm}
+requests tickets for the remote host in the specified realm, instead of
+determining the realm itself.
+
+@itemx -f
+requests that your tickets be forwarded to the remote host.  The
+@kbd{-f} argument must be the last argument on the command line.
+
+@itemx protect @i{level}
+(issued at the @code{ftp>} prompt) sets the protection level.  ``Clear''
+is no protection; ``safe'' ensures data integrity by verifying the
+checksum, and ``private'' encrypts the data.  Encryption also ensures
+data integrity.
+@end table
+
+@need 5000
+For example, suppose @code{@value{RANDOMUSER1}} wants to get her
+@code{RMAIL} file from the directory @code{~@value{RANDOMUSER1}/Mail},
+on the host @code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}}.  She wants
+to encrypt the file transfer.  The exchange would look like the
+following:
+
+@smallexample
+@group
+@b{shell%} ftp @value{RANDOMHOST1}.@value{PRIMARYDOMAIN}
+Connected to @value{RANDOMHOST1}.@value{PRIMARYDOMAIN}.
+220 @value{RANDOMHOST1}.@value{PRIMARYDOMAIN} FTP server (Version 5.60) ready.
+334 Using authentication type GSSAPI; ADAT must follow
+GSSAPI accepted as authentication type
+GSSAPI authentication succeeded
+200 Data channel protection level set to private.
+Name (@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}:@value{RANDOMUSER1}): 
+232 GSSAPI user @value{RANDOMUSER1}@@@value{PRIMARYREALM} is authorized as @value{RANDOMUSER1}
+230 User @value{RANDOMUSER1} logged in.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> protect private
+200 Protection level set to Private.
+ftp> cd ~@value{RANDOMUSER1}/MAIL
+250 CWD command successful.
+ftp> get RMAIL
+227 Entering Passive Mode (128,0,0,5,16,49)
+150 Opening BINARY mode data connection for RMAIL (361662 bytes).
+226 Transfer complete.
+361662 bytes received in 2.5 seconds (1.4e+02 Kbytes/s)
+ftp> quit
+@b{shell%}
+@end group
+@end smallexample
+
+The full set of options to @value{PRODUCT} @code{FTP} are discussed
+in the Reference section of this manual.  (@pxref{FTP Reference})
+
+@node rsh, rcp, FTP, Kerberos V5 Applications
+@subsection rsh
+
+The @value{PRODUCT} @code{rsh} program works exactly like the standard
+UNIX rlogin program, with the following Kerberos features added:
+
+@table @kbd
+@itemx -f
+forwards a copy of your tickets to the remote host.
+
+@itemx -F
+forwards a copy of your tickets to the remote host, and marks them
+re-forwardable from the remote host.
+
+@itemx -k @i{realm}
+requests tickets for the remote host in the specified realm, instead of
+determining the realm itself.
+
+@itemx -x
+encrypts the input and output data streams (the command line is not encrypted)
+
+@end table
+
+@need 1800
+For example, if your Kerberos tickets allowed you to run programs on the
+host @* @code{@value{RANDOMHOST2}@@@value{SECONDDOMAIN}} as root, you could
+run the @samp{date} program as follows:
+
+@smallexample
+@group
+@b{shell%} rsh @value{RANDOMHOST2}.@value{SECONDDOMAIN} -l root -x date
+@b{This rsh session is using DES encryption for all data transmissions.
+Tue Jul 30 19:34:21 EDT 2002
+shell%}
+@end group
+@end smallexample
+
+If you forwarded your Kerberos tickets, @code{rsh} automatically
+destroys them when it exits.  The full set of options to @value{PRODUCT}
+@code{rsh} are discussed in the Reference section of this manual.
+(@pxref{rsh Reference})
+
+@node rcp, ksu, rsh, Kerberos V5 Applications
+@subsection rcp
+
+@need 1000
+The @value{PRODUCT} @code{rcp} program works exactly like the standard
+UNIX rcp program, with the following Kerberos features added:
+
+@table @kbd
+@itemx -k @i{realm}
+requests tickets for the remote host in the specified realm, instead of
+determining the realm itself.
+
+@itemx -x
+turns on encryption.
+@end table
+
+
+@need 1500
+For example, if you wanted to copy the file @code{/etc/motd} from the
+host @code{@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}} into the current
+directory, via an encrypted connection, you would simply type:
+
+@smallexample
+@b{shell%} rcp -x @value{RANDOMHOST1}.@value{PRIMARYDOMAIN}:/etc/motd .
+@end smallexample
+
+The @kbd{rcp} program negotiates authentication and encryption
+transparently.  The full set of options to @value{PRODUCT} @code{rcp}
+are discussed in the Reference section of this manual.  (@pxref{rcp
+Reference})
+
+@node ksu,  , rcp, Kerberos V5 Applications
+@subsection ksu
+
+The @value{PRODUCT} @code{ksu} program replaces the standard UNIX su
+program.  @code{ksu} first authenticates you to Kerberos.  Depending on
+the configuration of your system, @code{ksu} may ask for your Kerberos
+password if authentication fails.  @emph{Note that you should never type
+your password if you are remotely logged in using an unencrypted
+connection.}
+
+Once @code{ksu} has authenticated you, if your Kerberos principal
+appears in the target's @code{.k5login} file (@pxref{Granting Access to
+Your Account}) or in the target's @code{.k5users} file (see below), it
+switches your user ID to the target user ID.
+
+@need 2000
+For example, @code{@value{RANDOMUSER2}} has put
+@code{@value{RANDOMUSER1}}'s Kerberos principal in his @code{.k5login}
+file.  If @code{@value{RANDOMUSER1}} uses @code{ksu} to become
+@code{@value{RANDOMUSER2}}, the exchange would look like this.  (To
+differentiate between the two shells, @code{@value{RANDOMUSER1}}'s
+prompt is represented as @code{@value{RANDOMUSER1}%} and
+@code{@value{RANDOMUSER2}}'s prompt is represented as
+@code{@value{RANDOMUSER2}%}.)
+
+@smallexample
+@group
+@b{@value{RANDOMUSER1}%} ksu @value{RANDOMUSER2}
+@b{Account @value{RANDOMUSER2}: authorization for @value{RANDOMUSER1}@@@value{PRIMARYREALM} successful
+Changing uid to @value{RANDOMUSER2} (3382)
+@value{RANDOMUSER2}%}
+@end group
+@end smallexample
+
+@noindent
+Note that the new shell has a copy of @code{@value{RANDOMUSER1}}'s
+tickets.  The ticket filename contains @code{@value{RANDOMUSER2}}'s UID
+with @samp{.1} appended to it:
+
+@smallexample
+@group
+@b{@value{RANDOMUSER2}%} klist
+@b{Ticket cache: /tmp/krb5cc_3382.1
+Default principal: @value{RANDOMUSER1}@@@value{PRIMARYREALM}
+
+Valid starting      Expires             Service principal
+07/31/04 21:53:01  08/01/04 07:52:53  krbtgt/@value{PRIMARYREALM}@@@value{PRIMARYREALM}
+07/31/04 21:53:39  08/01/04 07:52:53  host/@value{RANDOMHOST1}.@value{PRIMARYDOMAIN}@@@value{PRIMARYREALM}
+@value{RANDOMUSER2}%}
+@end group
+@end smallexample
+
+@need 2500
+If @code{@value{RANDOMUSER1}} had not appeared in
+@code{@value{RANDOMUSER2}}'s @code{.k5login} file (and the system was
+configured to ask for a password), the exchange would have looked like
+this (assuming @code{@value{RANDOMUSER2}} has taken appropriate
+precautions in protecting his password):
+
+@smallexample
+@group
+@b{@value{RANDOMUSER1}%} ksu @value{RANDOMUSER2}
+@b{WARNING: Your password may be exposed if you enter it here and are logged 
+         in remotely using an unsecure (non-encrypted) channel. 
+Kerberos password for @value{RANDOMUSER2}@@@value{PRIMARYREALM}:}  @i{<-  @code{@value{RANDOMUSER1}} types the wrong password here.}
+@b{ksu: Password incorrect
+Authentication failed.
+@value{RANDOMUSER1}%}
+@end group
+@end smallexample
+
+Now, suppose @code{@value{RANDOMUSER2}} did not want to give
+@code{@value{RANDOMUSER1}} full access to his account, but wanted to
+give her permission to list his files and use the "more" command to view
+them.  He could create a @code{.k5users} file giving her permission to
+run only those specific commands.
+
+@need 3500
+The @code{.k5users} file is like the @code{.k5login} file, except that
+each principal is optionally followed by a list of commands.  @code{ksu}
+will let those principals execute only the commands listed, using the
+@kbd{-e} option.  @code{@value{RANDOMUSER2}}'s @code{.k5users} file
+might look like the following:
+
+@smallexample
+@group
+@value{RANDOMUSER1}@@@value{PRIMARYREALM}       /bin/ls /usr/bin/more
+@value{ADMINUSER}@@@value{PRIMARYREALM}         /bin/ls
+@value{ADMINUSER}/admin@@@value{PRIMARYREALM}   *
+@value{RANDOMUSER2}@@@value{SECONDREALM}
+@end group
+@end smallexample
+
+@noindent The above @code{.k5users} file would let
+@code{@value{RANDOMUSER1}} run only the commands @code{/bin/ls} and
+@code{/usr/bin/more}.  It would let @code{@value{ADMINUSER}} run only
+the command @code{/bin/ls} if he had regular tickets, but if he had
+tickets for his @code{admin} instance,
+@code{@value{ADMINUSER}/admin@@@value{PRIMARYREALM}}, he would be able
+to execute any command.  The last line gives @code{@value{RANDOMUSER2}}
+in the realm @value{SECONDREALM} permission to execute any command.
+(@i{I.e.}, having only a Kerberos principal on a line is equivalent to
+giving that principal permission to execute @code{*}.)  This is so that
+@value{RANDOMUSER2} can allow himself to execute commands when he logs
+in, using Kerberos, from a machine in the realm @value{SECONDREALM}.
+
+@need 2500
+Then, when @code{@value{RANDOMUSER1}} wanted to list his home directory,
+she would type:
+
+@smallexample
+@group
+@b{@value{RANDOMUSER1}%} ksu @value{RANDOMUSER2} -e ls ~@value{RANDOMUSER2}
+@b{Authenticated @value{RANDOMUSER1}@@@value{PRIMARYREALM}
+Account @value{RANDOMUSER2}: authorization for @value{RANDOMUSER1}@@@value{PRIMARYREALM} for execution of
+               /bin/ls successful
+Changing uid to @value{RANDOMUSER2} (3382)
+Mail            News            Personal        misc            bin
+@value{RANDOMUSER1}%}
+@end group
+@end smallexample
+
+@noindent If @code{@value{RANDOMUSER1}} had tried to give a different
+command to @code{ksu}, it would have prompted for a password as with the
+previous example.
+
+Note that unless the @code{.k5users} file gives the target permission to
+run any command, the user must use @code{ksu} with the @kbd{-e}
+@i{command} option.
+
+@need 1000
+The @code{ksu} options you are most likely to use are:
+
+@table @kbd
+@itemx -n @i{principal}
+specifies which Kerberos principal you want to use for @code{ksu}.
+(@i{e.g.}, the user @code{@value{ADMINUSER}} might want to use his
+@code{admin} instance.  @xref{What is a Ticket?}.)
+
+@itemx -c
+specifies the location of your Kerberos credentials cache (ticket file).
+
+@itemx -k
+tells @code{ksu} not to destroy your Kerberos tickets when @code{ksu} is
+finished.
+
+@itemx -f
+requests forwardable tickets.  (@xref{Obtaining Tickets with kinit}.)  This
+is only applicable if @code{ksu} needs to obtain tickets.
+
+@itemx -l @i{lifetime}
+sets the ticket lifetime.  (@xref{Obtaining Tickets with kinit}.)  This is
+only applicable if @code{ksu} needs to obtain tickets.
+
+@itemx -z
+tells @code{ksu} to copy your Kerberos tickets only if the UID you are
+switching is the same as the Kerberos primary (either yours or the one
+specified by the @kbd{-n} option).
+
+@itemx -Z
+tells @code{ksu} not to copy any Kerberos tickets to the new UID.
+
+@itemx -e @i{command}
+tells @code{ksu} to execute @i{command} and then exit.  See the
+description of the @code{.k5users} file above.
+
+@itemx -a @i{text}
+(at the end of the command line) tells @code{ksu} to pass everything
+after @samp{-a} to the target shell.
+@end table
+
+The full set of options to @value{PRODUCT} @code{ksu} are discussed
+in the Reference section of this manual.  (@pxref{ksu Reference})
+
+@node Kerberos V5 Reference, Kerberos Glossary, Kerberos V5 Tutorial, Top
+@chapter Kerberos V5 Reference
+
+This section will include copies of the manual pages for the
+@value{PRODUCT} client programs.  You can read the manual entry for any
+command by typing @code{man} @i{command}, where @i{command} is the name
+of the command for which you want to read the manual entry.  For
+example, to read the @code{kinit} manual entry, you would type:
+
+@smallexample
+@b{shell%} man kinit
+@end smallexample
+
+Note:  To be able to view the @value{PRODUCT} manual pages on line, you
+may need to add the directory @code{@value{ROOTDIR}/man} to your MANPATH
+environment variable.  (Remember to replace @code{@value{ROOTDIR}} with
+the top-level directory in which @value{PRODUCT} is installed.)  For
+example, if you had the the following line in your @code{.login}
+file@footnote{The MANPATH variable may be specified in a different
+initialization file, depending on your operating system.  Some of the
+files in which you might specify environment variables include
+@code{.login}, @code{.profile}, or @code{.cshrc}.}:
+
+@smallexample
+setenv MANPATH /usr/local/man:/usr/man
+@end smallexample
+
+@noindent
+and the @value{PRODUCT} man pages were in the directory
+@code{/usr/@value{LCPRODUCT}/man}, you would change the line to the following:
+
+@smallexample
+setenv MANPATH /usr/@value{LCPRODUCT}/man:/usr/local/man:/usr/man
+@end smallexample
+
+@ifinfo
+Note to info users:  the manual pages are not available within this info
+tree.  You can read them from emacs with the command:
+
+@smallexample
+M-x manual-entry @emph{command}
+@end smallexample
+@end ifinfo
+
+@page
+
+@menu
+* kinit Reference::             
+* klist Reference::             
+* ksu Reference::               
+* kdestroy Reference::          
+* kpasswd Reference::           
+* telnet Reference::            
+* FTP Reference::               
+* rlogin Reference::            
+* rsh Reference::               
+* rcp Reference::               
+@end menu
+
+@node kinit Reference, klist Reference, Kerberos V5 Reference, Kerberos V5 Reference
+@section kinit Reference
+
+@iftex
+@special{psfile=kinit1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{kinit}}
+@page
+
+@special{psfile=kinit2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{kinit}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry kinit} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="kinit.html"> kinit manpage</a>
+@end html
+@end ifhtml
+
+@node klist Reference, ksu Reference, kinit Reference, Kerberos V5 Reference
+@section klist Reference
+
+@iftex
+@special{psfile=klist1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{klist}}
+@page
+@end iftex
+
+@iftex
+@special{psfile=klist2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{klist}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry klist} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="klist.html"> klist manpage</a>
+@end html
+@end ifhtml
+
+@node ksu Reference, kdestroy Reference, klist Reference, Kerberos V5 Reference
+@section ksu Reference
+
+@iftex
+@special{psfile=ksu1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{ksu}}
+@page
+
+@special{psfile=ksu2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{ksu}}
+@page
+
+@special{psfile=ksu3.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{ksu}}
+@page
+
+@special{psfile=ksu4.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{ksu}}
+@page
+
+@special{psfile=ksu5.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{ksu}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry ksu} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="ksu.html"> ksu manpage</a>
+@end html
+@end ifhtml
+
+@node kdestroy Reference, kpasswd Reference, ksu Reference, Kerberos V5 Reference
+@section kdestroy Reference
+
+@iftex
+@special{psfile=kdestroy1.ps voffset=-700 hoffset=-60}
+@centerline{Reference Manual for @code{kdestroy}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry kdestroy} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="kdestroy.html"> kdestroy manpage</a>
+@end html
+@end ifhtml
+
+@node kpasswd Reference, telnet Reference, kdestroy Reference, Kerberos V5 Reference
+@section kpasswd Reference
+
+@iftex
+@special{psfile=kpasswd1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{kpasswd}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry kpasswd} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="kpasswd.html"> kpasswd manpage</a>
+@end html
+@end ifhtml
+
+@node telnet Reference, FTP Reference, kpasswd Reference, Kerberos V5 Reference
+@section telnet Reference
+
+@iftex
+@special{psfile=telnet1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet3.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet4.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet5.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet6.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet7.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet8.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+
+@special{psfile=telnet9.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{telnet}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry telnet} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="telnet.html"> telnet manpage</a>
+@end html
+@end ifhtml
+
+@node FTP Reference, rlogin Reference, telnet Reference, Kerberos V5 Reference
+@section FTP Reference
+
+@iftex
+@special{psfile=ftp1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp3.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp4.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp5.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp6.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp7.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp8.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+
+@special{psfile=ftp9.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{FTP}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry FTP} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="ftp.html"> ftp manpage</a>
+@end html
+@end ifhtml
+
+@node rlogin Reference, rsh Reference, FTP Reference, Kerberos V5 Reference
+@section rlogin Reference
+
+@iftex
+@special{psfile=rlogin1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{rlogin}}
+@page
+
+@special{psfile=rlogin2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{rlogin}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry rlogin} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="rlogin.html"> rlogin manpage</a>
+@end html
+@end ifhtml
+
+@node rsh Reference, rcp Reference, rlogin Reference, Kerberos V5 Reference
+@section rsh Reference
+
+@iftex
+@special{psfile=rsh1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{rsh}}
+@page
+
+@special{psfile=rsh2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{rsh}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry rsh} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="rsh.html"> rsh manpage</a>
+@end html
+@end ifhtml
+
+@node rcp Reference, , rsh Reference, Kerberos V5 Reference
+@section rcp Reference
+
+@iftex
+@special{psfile=rcp1.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{rcp}}
+@page
+@end iftex
+
+@iftex
+@special{psfile=rcp2.ps voffset=-700 hoffset=-40}
+@centerline{Reference Manual for @code{rcp}}
+@page
+@end iftex
+
+@ifinfo
+Type @kbd{M-x manual-entry rcp} to read this manual page.
+@end ifinfo
+
+@ifhtml
+@html
+<a href="rcp.html"> rcp manpage</a>
+@end html
+@end ifhtml
+
+@node Kerberos Glossary,  , Kerberos V5 Reference, Top
+@appendix Kerberos Glossary
+
+@include glossary.texinfo
+
+@contents
+@bye
diff --git a/krb5-1-6/src/BADSYMS b/krb5-1-6/src/BADSYMS
new file mode 100644
index 000000000..882bd7b04
--- /dev/null
+++ b/krb5-1-6/src/BADSYMS
@@ -0,0 +1,282 @@
+./appl/bsd/configure.in: const HAVE_KRB_GET_ERR_TEXT HAVE_KRB_SAVE_CREDENTIALS HAVE_REGCOMP HAVE_SETLUID HAVE_SETOWN HAVE_SETUTENT HAVE_SETUTXENT HAVE_SHADOW HAVE_STDARG_H HAVE_STREAMS HAVE_UPDWTMP HAVE_UPDWTMPX HAVE_VARARGS_H HAVE_VFORK_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM krb5_sigtype mode_t NEED_SETENV NO_UT_EXIT NO_UT_HOST NO_UT_PID NO_UT_TYPE pid_t POSIX_SETJMP POSIX_SIGNALS POSIX_SIGTYPE POSIX_TERMIOS SETPAG SETPGRP_TWOARG STDC_HEADERS USE_DIRENT_H vfork WAIT_USES_INT HAVE_COMPILE HAVE_GETDTABLESIZE HAVE_GETENV HAVE_GETTOSBYNAME HAVE_INET_ATON HAVE_INITGROUPS HAVE_ISATTY HAVE_KILLPG HAVE_KRB_GET_ERR_TEXT HAVE_KRB_SAVE_CREDENTIALS HAVE_PTSNAME HAVE_RMUFILE HAVE_SETLOGIN HAVE_SETPGID HAVE_SETPRIORITY HAVE_SETRESUID HAVE_SETREUID HAVE_SETSID HAVE_STEP HAVE_STRSAVE HAVE_TCGETPGRP HAVE_TCSETPGRP HAVE_UTIMES HAVE_WAITPID HAVE_ARPA_NAMESER_H HAVE_KRB4_PROTO_H HAVE_LASTLOG_H HAVE_PATHS_H HAVE_STDLIB_H HAVE_STRING_H HAVE_SYS_FILIO_H HAVE_SYS_IOCTL_COMPAT_H HAVE_SYS_LABEL_H HAVE_SYS_PTYVAR_H HAVE_SYS_SELECT_H HAVE_SYS_SOCKIO_H HAVE_SYS_TIME_H HAVE_SYS_TTY_H HAVE_TTYENT_H HAVE_UNISTD_H HAVE_UTMP_H HAVE_LIBCRYPT HAVE_LIBNSL HAVE_LIBSOCKET HAVE_LIBUTIL
+./appl/bsd/defines.h: KRB5_KRB4_COMPAT SKIP_V4_PROTO
+./appl/bsd/fieldbits.h: KRB5_FIELDBITS__
+./appl/bsd/forward.c: KERBEROS KRB5
+./appl/bsd/getdtablesize.c: _SC_OPEN_MAX
+./appl/bsd/kcmd.c: KRB5_KRB4_COMPAT MAXPATHLEN min roundup sigmask sun SYSV tek tex _TYPES_ ultrix
+./appl/bsd/krcp.c: __cplusplus hpux __hpux KERBEROS KRB5_ATHENA_COMPAT KRB5_KRB4_COMPAT lint NOFCHMOD _TYPES_ UCB_RCP unicos61
+./appl/bsd/krlogin.c: CNUL CRAY hpux __hpux IEXTEN KERBEROS KRB5_ATHENA_COMPAT KRB5_KRB4_COMPAT lint LLITOUT LPASS8 NO_WINSIZE ONOCR _POSIX_VDISABLE __SCO__ sgi sigmask SIGWINCH SYSV TABDLY TIOCFLUSH TIOCGLTC TIOCGWINSZ TIOCPKT_NOSTOP TIOCPKT_WINDOW UCB_RLOGIN ultrix USE_TERMIO VDSUSP VLNEXT
+./appl/bsd/krlogind.c: _AIX ALWAYS_V5_KUSEROK CRYPT DO_NOT_USE_K_LOGIN HEIMDAL_FRIENDLY hpux __hpux i386 ibm032 KERBEROS KRB5_KRB4_COMPAT KRB_SENDAUTH_VLEN lint LOG_ALL_LOGINS LOG_AUTH LOGIN_PROGRAM LOG_NDELAY LOG_OTHER_USERS LOG_REMOTE_REALM MAXDNAME NEED_DAEMON_PROTO NO_WINSIZE roundup __SCO__ solaris20 STDERR_FILENO SunOS __svr4__ sysvimp TIOCFLUSH TIOCPKT TIOCPKT_NOSTOP TIOCPKT_WINDOW TIOCSWINSZ ultrix USE_LOGIN_F UT_NAMESIZE vax
+./appl/bsd/krsh.c: ATHENA KERBEROS KRB5_ATHENA_COMPAT KRB5_KRB4_COMPAT lint RLOGIN_PROGRAM sgi UCB_RLOGIN UCB_RSH
+./appl/bsd/krshd.c: ALWAYS_V5_KUSEROK BSD __cplusplus CRAY CRAY2 DEBUG HEIMDAL_FRIENDLY IP_SECURITY IP_TOS KERBEROS KRB5_KRB4_COMPAT KRB_SENDAUTH_VLEN lint LOG_ALL_LOGINS LOG_CMD LOG_DAEMON LOG_ODELAY LOG_OTHER_USERS LOG_REMOTE_REALM MAX MAXDNAME MIN NCARGS NO_UDB _PATH_NOLOGIN __SCO__ sgi TOS_WARN ULTRIX unicos61
+./appl/bsd/login.c: _AIX BIND_HACK BSD CDISCARD CNUL CSTATUS CSUSP CSWTCH ECHOCTL ECHOKE HAVE_ETC_ENVIRONMENT HAVE_ETC_TIMEZONE __hpux _IBMR2 KRB4 KRB4_CONVERT KRB4_GET_TICKETS KRB4_KLOGIN KRB5_GET_TICKETS KRB5_KRB4_COMPAT KRB_RUN_AKLOG lint linux __linux__ LOG_ODELAY NO_INIT_CC NO_MAILCHECK NO_MOTD NTTYDISC OLD_PASSWD O_NDELAY O_NONBLOCK OQUOTA _PATH_BSHELL _PATH_LASTLOG _PATH_MAILDIR _PATH_NOLOGIN QUOTAWARN sgi SIGSYS __STDC__ __SVR4 SYSLOG42 TAB3 TIOCHPCL TIOCLSET TIOCNOTTY TIOCNXCL TIOCSETD UT_HOSTSIZE UT_NAMESIZE VDISCARD VDISCRD VDSUSP VEOL2 VLNEXT volatile VREPRINT VSTATUS VSUSP VWERASE VWERSE
+./appl/bsd/loginpaths.h: __386BSD__ __alpha __DGUX hpux __hpux _IBMR2 linux LPATH __m88k__ MIPSEB __NetBSD__ NeXT __osf__ _PATH_DEFPATH __pyrsoft RPATH __SCO__ sgi sun __svr4__ __SVR4 __ultrix
+./appl/bsd/rpaths.h: RPROGS_IN_USR_BIN RPROGS_IN_USR_BSD RPROGS_IN_USR_UCB RSH_IS_RCMD RSH_IS_REMSH
+./appl/bsd/v4rcp.c: ATHENA _AUX_SOURCE __cplusplus KERBEROS lint NEED_SYS_FCNTL_H NOENCRYPTION NO_FCHMOD NOSTBLKSIZE NOVFORK roundup __SCO__
+./appl/configure.in: BROKEN_STREAMS_SOCKETS const HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_COMPILE HAVE_STEP HAVE_STDLIB_H HAVE_STRING_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./appl/gssftp/configure.in: const HAVE_REGCOMP HAVE_SETLUID HAVE_SETUTENT HAVE_SETUTXENT HAVE_SHADOW HAVE_STDARG_H HAVE_SYS_ERRLIST HAVE_UPDWTMP HAVE_UPDWTMPX HAVE_VARARGS_H HAVE_VFORK_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM krb5_sigtype NEED_SETENV NEED_SYS_ERRLIST NO_UT_EXIT NO_UT_HOST NO_UT_PID NO_UT_TYPE pid_t POSIX_SETJMP POSIX_SIGNALS POSIX_SIGTYPE POSIX_TERMIOS STDC_HEADERS SYS_ERRLIST_DECLARED USE_SIGPROCMASK vfork WAIT_USES_INT HAVE_COMPILE HAVE_GETCWD HAVE_GETDTABLESIZE HAVE_GETENV HAVE_GETUSERSHELL HAVE_SETEUID HAVE_SETRESUID HAVE_SETREUID HAVE_STEP HAVE_STRERROR HAVE_PATHS_H HAVE_STDLIB_H HAVE_STRING_H HAVE_SYS_SELECT_H HAVE_SYS_SOCKIO_H HAVE_UNISTD_H HAVE_LIBCRYPT HAVE_LIBNSL HAVE_LIBSOCKET HAVE_LIBUTIL
+./appl/telnet/configure.in: const KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_LIBNSL HAVE_LIBSOCKET
+./appl/telnet/libtelnet/configure.in: const KRB4 KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM NEED_SETENV HAVE_CGETENT HAVE_GETENV HAVE_GETOPT HAVE_GETTOSBYNAME HAVE_HERROR HAVE_PARSETOS HAVE_SETENV HAVE_SETSID HAVE_STRCASECMP HAVE_STRDUP HAVE_STRERROR HAVE_STRFTIME HAVE_UNSETENV HAVE_STDLIB_H HAVE_STRING_H HAVE_LIBNSL HAVE_LIBSOCKET
+./appl/telnet/libtelnet/auth.c: AUTHENTICATION ENCRYPTION KANNAN KRB5 SPX __STDC__
+./appl/telnet/libtelnet/auth.h: __AUTH__ P __STDC__
+./appl/telnet/libtelnet/auth-proto.h: AUTHENTICATION KRB5 P __STDC__
+./appl/telnet/libtelnet/enc_des.c: AUTHENTICATION DES_ENCRYPTION ENCRYPTION __STDC__
+./appl/telnet/libtelnet/enc-proto.h: ENCRYPTION P __STDC__ TELENTD
+./appl/telnet/libtelnet/encrypt.c: DES_ENCRYPTION ENCRYPTION notdef __STDC__
+./appl/telnet/libtelnet/encrypt.h: ENCRYPTION __ENCRYPTION__ P __STDC__
+./appl/telnet/libtelnet/forward.c: KERBEROS KRB5
+./appl/telnet/libtelnet/getent.c: SOLARIS
+./appl/telnet/libtelnet/getopt.c: __STDC__
+./appl/telnet/libtelnet/gettytab.h: SOLARIS
+./appl/telnet/libtelnet/herror.c: sun
+./appl/telnet/libtelnet/kerberos5.c: ENCRYPTION FORWARD KRB5
+./appl/telnet/libtelnet/kerberos.c: ENCRYPTION notdef __STDC__
+./appl/telnet/libtelnet/key-proto.h: __KEY_PROTO__ P __STDC__
+./appl/telnet/libtelnet/mem.c: BZERO __STDC__ UINT_MAX
+./appl/telnet/libtelnet/misc.c: AUTHENTICATION ENCRYPTION
+./appl/telnet/libtelnet/misc.h: P __STDC__
+./appl/telnet/libtelnet/misc-proto.h: __MISC_PROTO__ NEED_PARSETOS P __STDC__
+./appl/telnet/libtelnet/setenv.c: __STDC__
+./appl/telnet/libtelnet/setsid.c: convex
+./appl/telnet/libtelnet/spx.c: ENCRYPTION notdef SPX __STDC__
+./appl/telnet/libtelnet/strcasecmp.c: __STDC__
+./appl/telnet/libtelnet/strdup.c: __STDC__
+./appl/telnet/libtelnet/strftime.c: notdef __P __STDC__
+./appl/telnet/telnet/configure.in: const HAVE_ HAVE_REGCOMP HAVE_SA_LEN HAVE_STDARG_H HAVE_VARARGS_H HAVE_VFORK_H KRB4 KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM KRB5_USE_INET6 NO_CC_T pid_t POSIX_SIGNALS STDC_HEADERS SYSV_TERMIO TERMCAP USE_TERMIO vfork HAVE_COMPILE HAVE_GETADDRINFO HAVE_GETNAMEINFO HAVE_GETTOSBYNAME HAVE_INET_NTOP HAVE_INET_PTON HAVE_SETUPTERM HAVE_STEP HAVE_ARPA_INET_H HAVE_ARPA_NAMESER_H HAVE_CURSES_H HAVE_MACSOCK_H HAVE_NETDB_H HAVE_NETINET_IN_H HAVE_STDLIB_H HAVE_STRING_H HAVE_SYS_FILIO_H HAVE_SYS_SELECT_H HAVE_SYS_SOCKET_H HAVE_SYS_TYPES_H HAVE_TERM_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./appl/telnet/telnet/authenc.c: AUTHENTICATION ENCRYPTION
+./appl/telnet/telnet/commands.c: AF_INET6 AUTHENTICATION CRAY ENCRYPTION ENV_HACK F_GETOWN FORWARD h_addr hp300 INADDR_NONE IP_OPTIONS IPPROTO_IP IP_TOS KLUDGELINEMODE MAXDNAME NEED_HERROR_PROTO NOT43 notdef OLD_ENVIRON SIGINFO SIGTSTP __STDC__ sysV88 tahoe TN3270 ultrix unix vax
+./appl/telnet/telnet/defines.h: TN3270
+./appl/telnet/telnet/externs.h: BSD CRAY ENCRYPTION KLUDGELINEMODE NO_BSD_SETJMP P _POSIX_VDISABLE __STDC__ sun __svr4__ TN3270 VDISABLE VDISCARD VEOL VEOL2 VFLUSHO VINTR VLNEXT VREPRINT VSTART VSTATUS VSTOP VSUSP VWERASE
+./appl/telnet/telnet/fdset.h: FD_SETSIZE
+./appl/telnet/telnet/main.c: AUTHENTICATION CRAY ENCRYPTION FORWARD IPPROTO_IP IP_TOS KRB5 lint NEED_PARSETOS_PROTO __STDC__ TN3270 unix
+./appl/telnet/telnet/network.c: ENCRYPTION
+./appl/telnet/telnet/ring.c: ENCRYPTION MIN NO_STRING_H notdef size_t
+./appl/telnet/telnet/ring.h: ENCRYPTION LINT_ARGS notdef P __STDC__
+./appl/telnet/telnet/sys_bsd.c: B19200 B38400 CIBAUD CRAY ECHOCTL KLUDGELINEMODE LNOFLSH NOKERNINFO NOT43 notdef OXTABS PUTCHAR SA_INTERRUPT SA_NOMASK SIGINFO SIGTSTP SIGWINCH SO_OOBINLINE sysV88 TABDLY TCSANOW TCSETA TCSETS TIOCFLUSH TIOCGWINSZ TN3270 VDISCARD VDSUSP VEOL2 VLNEXT VREPRINT VSTART VSTATUS VSTOP VSUSP VWERASE
+./appl/telnet/telnet/telnet.c: AUTHENTICATION ENCRYPTION ENV_HACK KLUDGELINEMODE notdef OLD_ENVIRON TN3270 unix
+./appl/telnet/telnet/terminal.c: ENCRYPTION KLUDGELINEMODE VDISCARD VEOL VEOL2 VLNEXT VREPRINT VSTART VSTATUS VSTOP VSUSP VWERASE
+./appl/telnet/telnet/tn3270.c: NOT43 PUTCHAR sun TN3270 unix
+./appl/telnet/telnet/utilities.c: AUTHENTICATION ENCRYPTION ENV_HACK NOT43 OLD_ENVIRON TN3270 unix
+./appl/telnet/telnetd/configure.in: const HAVE_ HAVE_REGCOMP HAVE_SA_LEN KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM KRB5_USE_INET6 NO_CC_T SETPGRP_TWOARG STREAMSPTY SYSV_TERMIO TERMCAP TIME_WITH_SYS_TIME USE_TERMIO HAVE_COMPILE HAVE_GETADDRINFO HAVE_GETNAMEINFO HAVE_GETTOSBYNAME HAVE_INET_NTOP HAVE_INET_PTON HAVE_STEP HAVE_VSNPRINTF HAVE_ARPA_NAMESER_H HAVE_MACSOCK_H HAVE_MEMORY_H HAVE_NETDB_H HAVE_NETINET_IN_H HAVE_SAC_H HAVE_STRING_H HAVE_SYS_FILIO_H HAVE_SYS_PTYVAR_H HAVE_SYS_SOCKET_H HAVE_SYS_STREAM_H HAVE_SYS_TIME_H HAVE_SYS_TTY_H HAVE_SYS_TYPES_H HAVE_SYS_UTSNAME_H HAVE_UTMP_H HAVE_LIBNSL HAVE_LIBSOCKET HAVE_LIBUTIL
+./appl/telnet/telnetd/authenc.c: AUTHENTICATION ENCRYPTION
+./appl/telnet/telnetd/defs.h: __alpha BSD CRAY CRAY1 DIAGNOSTICS ENCRYPTION FD_SET FD_ZERO __hpux LINEMODE LOG_DAEMON LOG_ODELAY NO_SETSID P _POSIX_VDISABLE PRINTOPTIONS __STDC__ TCSETCTTY TIOCSCTTY UNICOS5 UNICOS50 VDISABLE
+./appl/telnet/telnetd/ext.h: AUTHENTICATION BFTPDAEMON convex CRAY2 DIAGNOSTICS ENCRYPTION KLUDGELINEMODE LINEMODE NEED_SETENV_PROTO NEED_UNSETENV_PROTO SecurID UNICOS5
+./appl/telnet/telnetd/pathnames.h: BFTPDAEMON _PATH_LOGIN
+./appl/telnet/telnetd/slc.c: LINEMODE
+./appl/telnet/telnetd/state.c: AUTHENTICATION CRAY2 ENCRYPTION ENV_HACK KLUDGELINEMODE LINEMODE TELOPT_ENVIRON TELOPT_NEW_ENVIRON UNICOS5
+./appl/telnet/telnetd/sys_term.c: _AIX AUTHENTICATION BFTPDAEMON CIBAUD convex CRAY CRAY2 DECCTQ ECHOCTL EXTPROC __hpux KRB5 LINEMODE LOGIN_ARGS LOGIN_CAP_F LOGIN_HOST LOGIN_PROGRAM LOGIN_R NEWINIT NO_LOGIN_F NO_LOGIN_H NO_LOGIN_P O_NOCTTY OXTABS _PATH_UTMP _PATH_WTMP _SC_CRAY_NPTY _SC_CRAY_SECURE_SYS SCM_SECURITY SecurID SOLARIS TABDLY TCSANOW TCSETA TCSETS TCTLECH t_erase TIOCEXT TIOCGSTATE TIOCGWINSZ TIOCPKT_IOCTL UNICOS5 VDISCARD VEOL VEOL2 VFLUSHO VLNEXT VREPRINT VSTART VSTATUS VSTOP VSUSP VWERASE
+./appl/telnet/telnetd/telnetd.c: _AIX AUTHENTICATION BFTPDAEMON convex CRAY CRAY2 DIAGNOSTICS EAGAIN ENCRYPTION IPPROTO_IP IP_TOS KLUDGELINEMODE KRB5 LINEMODE lint MAXDNAME NEWINIT NO_URGENT _SC_CRAY_SECURE_SYS SCM_SECURITY SecurID SIGINFO SIGTSTP SIGTTOU SO_OOBINLINE SO_SEC_MULTI TCSIG TIOCNOTTY TIOCSCTTY TIOCSIG UNICOS5 UNICOS50
+./appl/telnet/telnetd/telnetd.h: DIAGNOSTICS
+./appl/telnet/telnetd/telnetd-ktd.c: AUTHENTICATION BFTPDAEMON convex CRAY CRAY2 DIAGNOSTICS EAGAIN ENCRYPTION IPPROTO_IP IP_TOS KLUDGELINEMODE LINEMODE lint MAXHOSTNAMELEN NEWINIT NO_URGENT _SC_CRAY_SECURE_SYS SecurID SIGINFO SIGTSTP SIGTTOU SO_OOBINLINE TCSIG TIOCNOTTY TIOCSCTTY TIOCSIG UNICOS5 UNICOS50
+./appl/telnet/telnetd/termios-tn.c: _AIX TCSETS
+./appl/telnet/telnetd/termstat.c: CRAY2 ENCRYPTION KLUDGELINEMODE LINEMODE TIOCSWINSZ UNICOS5
+./appl/telnet/telnetd/utility.c: AUTHENTICATION DIAGNOSTICS ENCRYPTION
+./clients/configure.in: const HAVE_REGCOMP HAVE_SETLUID HAVE_STDARG_H HAVE_VARARGS_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_COMPILE HAVE_GETENV HAVE_GETUSERSHELL HAVE_INET_NTOP HAVE_LSTAT HAVE_SETENV HAVE_STEP HAVE_UNSETENV HAVE_ARPA_INET_H HAVE_PWD_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./configure.in: const HAVE_REGCOMP HAVE_TCL_H HAVE_TCL_TCL_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_COMPILE HAVE_MEMMOVE HAVE_STEP HAVE_LIBNSL HAVE_LIBSOCKET
+./wconfig.c: _WIN32
+./include/configure.in: ANSI_STDIO const gid_t HAVE_ HAVE_SA_LEN HAVE_SOCKLEN_T HAVE_STDARG_H HAVE_VARARGS_H KRB5_ATHENA_COMPAT KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM KRB5_KRB4_COMPAT krb5_sigtype KRB5_USE_INET6 NO_YYLINENO POSIX_SIGTYPE POSIX_TERMIOS STDC_HEADERS time_t TIME_WITH_SYS_TIME uid_t USE_DIRENT_H HAVE_BCOPY HAVE_GETADDRINFO HAVE_GETNAMEINFO HAVE_INET_ATON HAVE_INET_NTOA HAVE_INET_NTOP HAVE_INET_PTON HAVE_LABS HAVE_MEMMOVE HAVE_SETVBUF HAVE_STRDUP HAVE_MACSOCK_H HAVE_NETDB_H HAVE_NETINET_IN_H HAVE_STDDEF_H HAVE_STDLIB_H HAVE_STRING_H HAVE_SYS_FILE_H HAVE_SYS_PARAM_H HAVE_SYS_SOCKET_H HAVE_SYS_STAT_H HAVE_SYS_TIME_H HAVE_SYS_TYPES_H HAVE_UNISTD_H HAVE_XOM_H HAVE_LIBNSL HAVE_LIBSOCKET
+./include/bsdlib.h: __BSDLIB__ FILE __STDC__ _WINDOWS
+./include/bstring.h: __BSTRING__ __STDC__ _WINDOWS
+./include/fake-addrinfo.c: NETDB_INTERNAL
+./include/fake-addrinfo.h: AI_NUMERICHOST BROKEN_GETADDRINFO FAI_DEFINED FAI_PREFIX NI_MAXHOST NI_MAXSERV
+./include/fake-stdlib.h: abort abs FD_SETSIZE __GNUC__ hpux ibm032 memcpy memset mips __mips__ __STDC__ SYSTEM_FIVE ultrix __ultrix__ vax __vax__ _WINDOWS
+./include/k5-int.h: applec __CFM68K__ KRB5_ASN1__ KRB5_AUTOCONF__ KRB5_CALLCONV KRB5_CONFIG__ KRB5_ERRORS__ KRB5_EXT_PROTO__ _KRB5_INT_H KRB5_LIBOS__ KRB5_LIBOS_PROTO__ KRB5_OLD_CRYPTO KRB5_PREAUTH__ KRB5_SYSINCL__ KRB5_SYSTYPES__ macintosh MIT_DES_KEYSIZE __MWERKS__ NEED_SOCKETS O_BINARY _SIZET SOCK_DGRAM THINK_C __USING_STATIC_LIBS__ _WIN32
+./include/k5-util.h: KRB_DEFS SOCK_DGRAM
+./include/port-sockets.h: _PORT_SOCKET_H _WIN32
+./include/socket-utils.h: __GNUC__ SOCKET_UTILS_H socklen
+./include/syslog.h: KERNEL va_start
+./include/win-mac.h: CYGNUS KRB4 KRB5_CALLCONV KRB5_SYSTYPES__ _KRB5_WIN_MAC_H macintosh MAXPATHLEN __MWERKS__ NEED_LOWLEVEL_IO NEED_SYSERROR RES_ONLY _WIN32
+./kadmin/configure.in: const HAVE_REGCOMP HAVE_TCL_H HAVE_TCL_TCL_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM NDBM_PW_CHECK POSIX_SETJMP POSIX_SIGNALS TIME_WITH_SYS_TIME WAIT_USES_INT HAVE_COMPILE HAVE_FTIME HAVE_GETCWD HAVE_MEMMOVE HAVE_STEP HAVE_STRFTIME HAVE_STRSTR HAVE_TIMEZONE HAVE_VSPRINTF HAVE_WAITPID HAVE_ALLOCA_H HAVE_ARPA_INET_H HAVE_KDC_H HAVE_KRB_DB_H HAVE_MEMORY_H HAVE_REGEX_H HAVE_STDLIB_H HAVE_SYS_SELECT_H HAVE_SYS_TIME_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./kdc/configure.in: ATHENA_DES3_KLUDGE const HAVE_ HAVE_REGCOMP HAVE_SA_LEN KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM KRB5_USE_INET6 KRBCONF_KDC_MODIFIES_KDB KRBCONF_VAGUE_ERRORS NOCACHE POSIX_SIGNALS USE_RCACHE HAVE_CLOSELOG HAVE_COMPILE HAVE_GETADDRINFO HAVE_GETNAMEINFO HAVE_INET_NTOP HAVE_INET_PTON HAVE_OPENLOG HAVE_STEP HAVE_STRFTIME HAVE_SYSLOG HAVE_VSPRINTF HAVE_IFADDRS_H HAVE_MACSOCK_H HAVE_NETDB_H HAVE_NETINET_IN_H HAVE_STDARG_H HAVE_SYSLOG_H HAVE_SYS_SELECT_H HAVE_SYS_SOCKET_H HAVE_SYS_SOCKIO_H HAVE_SYS_TYPES_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./kdc/dispatch.c: KRB5_KRB4_COMPAT
+./kdc/do_as_req.c: hpux
+./kdc/do_tgs_req.c: hpux
+./kdc/extern.h: __KRB5_KDC_EXTERN__
+./kdc/kdc_preauth.c: DEBUG KRB5INT_DES_TYPES_DEFINED
+./kdc/kdc_util.h: __KRB5_KDC_UTIL__ KRB5_KRB4_COMPAT min
+./kdc/kerberos_v4.c: BACKWARD_COMPAT KRB5_KRB4_COMPAT NEED_SWAB_PROTO NOENCRYPTION notdef notdef_DIE TIME_WITH_SYS_TIME
+./kdc/main.c: KRB5_KRB4_COMPAT NEED_DAEMON_PROTO POSIX_SIGTYPE
+./kdc/network.c: AF_INET6 ARPHRD_ETHER DEBUG IFF_LOOPBACK max SIOCGSIZIFCONF TEST
+./kdc/policy.h: __KRB5_KDC_POLICY__
+./krb524/configure.in: const HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM RETSIGTYPE HAVE_COMPILE HAVE_STEP HAVE_SYS_SELECT_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./krb524/cnv_tkt_skey.c: NOENCRYPTION _WIN32
+./krb524/conv_creds.c: _WIN32
+./krb524/encode.c: _WIN32
+./krb524/k524init.c: _WIN32
+./krb524/krb524d.c: NEED_DAEMON_PROTO
+./krb524/krb524.h: __KRB524_H__
+./krb524/libinit.c: _WIN32
+./krb524/misc.c: _WIN32
+./krb524/sendmsg.c: _AIX _WIN32
+./krb524/test.c: _WIN32
+./lib/crypto/configure.in: ATHENA_DES3_KLUDGE const HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_COMPILE HAVE_STEP HAVE_MEMORY_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/crypto/crypto_libinit.h: KRB5_LIBINIT_H
+./lib/des425/configure.in: const HAVE_PRAGMA_WEAK HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_COMPILE HAVE_STEP HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/des425/quad_cksum.c: DEBUG HAVE_ERRNO
+./lib/des425/read_passwd.c: ECHO_PASSWORD _WIN32
+./lib/des425/string2key.c: DEBUG
+./lib/des425/str_to_key.c: DEBUG
+./lib/des425/unix_time.c: _WIN32
+./lib/gssapi/configure.in: const KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM size_t STDC_HEADERS HAVE_LIMITS_H HAVE_MEMORY_H HAVE_STDLIB_H HAVE_SYS_TYPES_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/gssapi/gss_libinit.h: KRB5_LIBINIT_H
+./lib/kadm5/configure.in: const HAVE_REGCOMP HAVE_TCL_H HAVE_TCL_TCL_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_CLOSELOG HAVE_COMPILE HAVE_OPENLOG HAVE_RE_COMP HAVE_RE_EXEC HAVE_REGEXEC HAVE_SRAND HAVE_SRAND48 HAVE_SRANDOM HAVE_STEP HAVE_STRFTIME HAVE_SYSLOG HAVE_VSPRINTF HAVE_MEMORY_H HAVE_SYSLOG_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/kadm5/adb.h: __ADB_H__
+./lib/kadm5/admin.h: __KADM5_ADMIN_H__ USE_KADM5_API_VERSION
+./lib/kadm5/admin_internal.h: __KADM5_ADMIN_INTERNAL_H__
+./lib/kadm5/chpass_util.c: ZEROPASSWD
+./lib/kadm5/get_admhst.c: lint
+./lib/kadm5/kadm_rpc.h: __KADM_RPC_H__
+./lib/kadm5/logger.c: HAVE_STDARG_H LOG_ALERT LOG_AUTH LOG_AUTHPRIV LOG_CRIT LOG_CRON LOG_DAEMON LOG_DEBUG LOG_EMERG LOG_ERR LOG_FTP LOG_INFO LOG_KERN LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_LPR LOG_MAIL LOG_NEWS LOG_NOTICE LOG_USER LOG_UUCP LOG_WARNING MAXHOSTNAMELEN VERBOSE_LOGS
+./lib/kadm5/misc_free.c: __CODECENTER__ lint
+./lib/kadm5/server_internal.h: __KADM5_SERVER_INTERNAL_H__
+./lib/kdb/configure.in: const HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM mode_t off_t STDC_HEADERS HAVE_COMPILE HAVE_SRAND HAVE_SRAND48 HAVE_SRANDOM HAVE_STEP HAVE_UMASK HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/kdb/fetch_mkey.c: ANSI_STDIO min
+./lib/kdb/kdb_db2.c: EFTYPE NOFSYNC OLD_COMPAT_VERSION_1
+./lib/kdb/kdb_db2.h: KRB5_KDB_DB2_H
+./lib/kdb/kdb_dbm.c: DEBUG NOFSYNC OLD_COMPAT_VERSION_1
+./lib/kdb/store_mkey.c: ANSI_STDIO MAXPATHLEN min
+./lib/kdb/t_kdb.c: BERK_DB_DBM dbm_clearerr dbm_dirfno dbm_error dbm_pagfno HAVE_DBM_CLEARERR HAVE_DBM_ERROR MISSING_CLEARERR_PROTO MISSING_ERROR_PROTO NDBM ODBM
+./lib/krb4/configure.in: BITS16 BITS32 const gid_t KRB4_USE_KEYTAB KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM LSBFIRST mode_t MSBFIRST STDC_HEADERS uid_t HAVE_SETEUID HAVE_SETRESUID HAVE_SETREUID HAVE_STRDUP HAVE_STDLIB_H HAVE_SYS_SELECT_H HAVE_TIME_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/krb4/ad_print.c: NOENCRYPTION _WINDOWS
+./lib/krb4/cr_ciph.c: NOENCRYPTION
+./lib/krb4/cr_death_pkt.c: DEBUG
+./lib/krb4/cr_tkt.c: NOENCRYPTION
+./lib/krb4/decomp_tkt.c: KRB_CRYPT_DEBUG NOENCRYPTION notdef
+./lib/krb4/dest_tkt.c: NO_FSYNC O_SYNC TKT_SHMEM
+./lib/krb4/err_txt.c: MULTIDIMENSIONAL_ERR_TXT
+./lib/krb4/g_ad_tkt.c: NOENCRYPTION
+./lib/krb4/g_cnffile.c: ATHENA_CONF_FALLBACK
+./lib/krb4/gethostname.c: GETHOSTNAME
+./lib/krb4/g_in_tkt.c: DECRYPT_TKT_TYPE_DEFINED KEY_PROC_TYPE_DEFINED NOENCRYPTION
+./lib/krb4/g_phost.c: DO_REVERSE_RESOLVE
+./lib/krb4/g_pw_in_tkt.c: BSDUNIX CROSSMSDOS INTK_PW_NULL macintosh NOENCRYPTION NULL __svr4__ __SVR4 _WINDOWS
+./lib/krb4/g_svc_in_tkt.c: NULL
+./lib/krb4/in_tkt.c: NO_FSYNC O_SYNC TKT_SHMEM
+./lib/krb4/klog.c: VMS _WINDOWS
+./lib/krb4/kparse.c: DEBUG FALSE GTOK_TEST KVTEST PSTEST
+./lib/krb4/krb4int.h: KRB_DB_DEFS _WINDOWS
+./lib/krb4/kuserok.c: ATHENA_COMPAT ATHENA_OLD_KLOGIN __SCO__ _WINDOWS
+./lib/krb4/lifetime.c: SHORT_LIFETIME
+./lib/krb4/log.c: KRB_CRYPT_DEBUG VMS _WINDOWS
+./lib/krb4/macsock.c: ENOMEM
+./lib/krb4/memcache.c: _AIX unix _WINDOWS
+./lib/krb4/mk_auth.c: ATHENA_COMPAT NOENCRYPTION
+./lib/krb4/mk_preauth.c: NOENCRYPTION
+./lib/krb4/mk_priv.c: NOENCRYPTION notdef
+./lib/krb4/mk_req.c: NOENCRYPTION
+./lib/krb4/mk_safe.c: NOENCRYPTION
+./lib/krb4/netread.c: _WINDOWS
+./lib/krb4/netwrite.c: _WINDOWS
+./lib/krb4/rd_preauth.c: NOENCRYPTION
+./lib/krb4/rd_priv.c: NOENCRYPTION notdef
+./lib/krb4/rd_req.c: KRB_CRYPT_DEBUG lint NOENCRYPTION
+./lib/krb4/rd_safe.c: DEBUG NOENCRYPTION
+./lib/krb4/rd_svc_key.c: ATHENA_COMPAT ATHENA_OLD_SRVTAB __i960__
+./lib/krb4/realmofhost.c: DO_REVERSE_RESOLVE
+./lib/krb4/recvauth.c: max NOENCRYPTION _WINDOWS
+./lib/krb4/sendauth.c: ATHENA_COMPAT
+./lib/krb4/send_to_kdc.c: DEBUG SunOS ULTRIX022
+./lib/krb4/setenv.c: HAVE_GETENV LIBC_SCCS lint
+./lib/krb4/tf_shm.c: _AIX
+./lib/krb4/tf_util.c: NEED_UTIMES __SCO__ __svr4__ __SVR4 TKT_SHMEM
+./lib/krb4/tkt_string.c: _WINDOWS
+./lib/krb4/win_time.c: _WIN32
+./lib/krb5/configure.in: const GETPEERNAME_ARG2_TYPE GETPEERNAME_ARG3_TYPE GETSOCKNAME_ARG2_TYPE GETSOCKNAME_ARG3_TYPE gid_t HAVE_REGCOMP HAVE_SA_LEN HAVE_STDARG_H HAVE_VARARGS_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM off_t STDC_HEADERS uid_t HAVE_CHMOD HAVE_COMPILE HAVE_DAEMON HAVE_FCHMOD HAVE_FLOCK HAVE_GETENV HAVE_GETEUID HAVE_GETHOSTBYNAME2 HAVE_GETIFADDRS HAVE_GETUID HAVE_MEMMOVE HAVE_RE_COMP HAVE_RE_EXEC HAVE_REGEXEC HAVE_SETENV HAVE_SETSID HAVE_SSCANF HAVE_STEP HAVE_STRCASECMP HAVE_STRDUP HAVE_STRERROR HAVE_STRFTIME HAVE_STRPTIME HAVE_SYSLOG HAVE_UNSETENV HAVE_VFPRINTF HAVE_VSPRINTF HAVE_FCNTL_H HAVE_IFADDRS_H HAVE_MEMORY_H HAVE_PATHS_H HAVE_REGEX_H HAVE_REGEXP_H HAVE_REGEXPR_H HAVE_SYS_FILIO_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/krb5/krb5_libinit.c: macintosh _WIN32
+./lib/krb5/krb5_libinit.h: KRB5_LIBINIT_H
+./lib/krb5util/configure.in: const KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_SETEGID HAVE_SETEUID HAVE_SETREGID HAVE_SETRESGID HAVE_SETRESUID HAVE_SETREUID HAVE_STDLIB_H HAVE_SYS_TYPES_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/krb5util/compat_recv.c: KRB5_KRB4_COMPAT _MACINTOSH max NOENCRYPTION
+./lib/rpc/configure.in: const ENDRPCENT_TYPE GETGROUPS_T gid_t HAVE_SYS_ERRLIST KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM NEED_SYS_ERRLIST SETRPCENT_TYPE SYS_ERRLIST_DECLARED uid_t HAVE_STRERROR HAVE_SYS_UIO_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/rpc/auth_gssapi.c: __CODECENTER__ DEBUG_GSSAPI GSSAPI_KRB5
+./lib/rpc/auth_gssapi.h: major minor PROTOTYPE __STDC__ __ultrix _WIN32
+./lib/rpc/auth_gssapi_misc.c: __CODECENTER__ DEBUG_GSSAPI
+./lib/rpc/auth_none.c: lint SCCSIDS
+./lib/rpc/auth_unix.c: KERNEL lint SCCSIDS
+./lib/rpc/authunix_prot.c: lint SCCSIDS
+./lib/rpc/bindresvport.c: lint SCCSIDS
+./lib/rpc/clnt_generic.c: lint SCCSIDS
+./lib/rpc/clnt.h: _CLNT_
+./lib/rpc/clnt_perror.c: lint SCCSIDS
+./lib/rpc/clnt_raw.c: lint SCCSIDS
+./lib/rpc/clnt_simple.c: lint SCCSIDS
+./lib/rpc/clnt_tcp.c: FD_SETSIZE lint SCCSIDS
+./lib/rpc/clnt_udp.c: FD_SETSIZE lint SCCSIDS sun
+./lib/rpc/get_myaddress.c: GSSAPI_KRB5 lint OSF1 SCCSIDS sun
+./lib/rpc/getrpcent.c: lint PROTOTYPE SCCSIDS __STDC__ __ultrix _WIN32
+./lib/rpc/getrpcport.c: lint SCCSIDS
+./lib/rpc/netdb.h: RPC_NETDB_H STRUCT_RPCENT_IN_RPC_NETDB_H
+./lib/rpc/pmap_clnt.c: lint SCCSIDS
+./lib/rpc/pmap_getmaps.c: lint OSF1 SCCSIDS
+./lib/rpc/pmap_getport.c: lint OSF1 SCCSIDS
+./lib/rpc/pmap_prot2.c: lint SCCSIDS
+./lib/rpc/pmap_prot.c: lint SCCSIDS
+./lib/rpc/pmap_rmt.c: __alpha__ FD_SETSIZE hpux lint linux MAX notdef __osf__ OSF1 SCCSIDS SIOCGIFBRDADDR SO_BROADCAST sun __svr4__
+./lib/rpc/rpc_callmsg.c: lint SCCSIDS
+./lib/rpc/rpc_commondata.c: FD_SETSIZE
+./lib/rpc/rpc_dtablesize.c: FD_SETSIZE lint SCCSIDS _SC_OPEN_MAX
+./lib/rpc/rpc.h: __RPC_HEADER__
+./lib/rpc/rpc_prot.c: lint SCCSIDS
+./lib/rpc/svc_auth.c: lint SCCSIDS
+./lib/rpc/svc_auth_gssapi.c: __CODECENTER__ DEBUG_GSSAPI GSSAPI_KRB5 GSS_BACKWARD_HACK PURIFY
+./lib/rpc/svc_auth_unix.c: lint SCCSIDS
+./lib/rpc/svc.c: FD_SETSIZE lint SCCSIDS
+./lib/rpc/svc.h: FD_SETSIZE __SVC_HEADER__
+./lib/rpc/svc_raw.c: lint SCCSIDS
+./lib/rpc/svc_run.c: FD_SETSIZE lint SCCSIDS
+./lib/rpc/svc_simple.c: lint SCCSIDS
+./lib/rpc/svc_tcp.c: FD_SETSIZE lint SCCSIDS
+./lib/rpc/svc_udp.c: lint MAX SCCSIDS
+./lib/rpc/xdr_alloc.c: lint SCCSIDS
+./lib/rpc/xdr_array.c: lint SCCSIDS
+./lib/rpc/xdr.c: lint SCCSIDS
+./lib/rpc/xdr_float.c: IGNORE lint SCCSIDS vax
+./lib/rpc/xdr.h: PROTOTYPE __STDC__ __ultrix _WIN32 __XDR_HEADER__
+./lib/rpc/xdr_mem.c: lint SCCSIDS
+./lib/rpc/xdr_rec.c: lint __osf__ SCCSIDS
+./lib/rpc/xdr_reference.c: lint SCCSIDS
+./lib/rpc/xdr_stdio.c: lint SCCSIDS
+./lib/rpc/unit-test/configure.in: const HAVE_REGCOMP HAVE_TCL_H HAVE_TCL_TCL_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM POSIX_SIGNALS HAVE_COMPILE HAVE_STEP HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./lib/rpc/unit-test/client.c: __CODECENTER__ lint
+./lib/rpc/unit-test/rpc_test.h: _RPC_TEST_H_RPCGEN
+./lib/rpc/unit-test/server.c: __CODECENTER__ lint SERVICE_NAME
+./slave/configure.in: const HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM mode_t STDC_HEADERS HAVE_COMPILE HAVE_STEP HAVE_LIBNSL HAVE_LIBSOCKET HAVE_LIBUTIL
+./slave/kpropd.c: NEED_DAEMON_PROTO PID_FILE WEXITSTATUS
+./tests/configure.in: const HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM POSIX_SIGNALS RETSIGTYPE STDC_HEADERS HAVE_COMPILE HAVE_STEP HAVE_STRCHR HAVE_STDLIB_H HAVE_SYS_PARAM_H HAVE_SYS_SOCKET_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./util/autoconf/configure.in:
+./util/db2/configure.in: const HAVE_REGCOMP int16_t int32_t int8_t KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM memmove MEMMOVE size_t ssize_t STDC_HEADERS u_char u_int u_int16_t u_int32_t u_int8_t u_long u_short WORDS_BIGENDIAN HAVE_COMPILE HAVE_MKSTEMP HAVE_STEP HAVE_STRERROR HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./util/et/configure.in: const HAVE_STDARG_H HAVE_SYS_ERRLIST HAVE_VARARGS_H HDR_HAS_PERROR KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM NEED_SYS_ERRLIST NO_YYLINENO SYS_ERRLIST_DECLARED HAVE_STRERROR HAVE_STDLIB_H HAVE_LIBNSL HAVE_LIBSOCKET
+./util/et/com_err.c: macintosh _WIN32
+./util/et/com_err.h: __COM_ERR_H __cplusplus KRB5_CALLCONV macintosh _WIN32
+./util/et/compile_et.c: lint NEED_STRCASECMP
+./util/et/error_message.c: DEBUG_TABLE_LIST macintosh __sgi _WIN32
+./util/et/error_table.h: _ET_H macintosh _WIN32
+./util/et/internal.h: __STDC__ WIN32
+./util/et/vfprintf.c: macintosh _WIN32
+./util/profile/configure.in: const HAVE_REGCOMP KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM HAVE_ACCESS HAVE_COMPILE HAVE_STAT HAVE_STEP HAVE_STDLIB_H HAVE_UNISTD_H HAVE_LIBNSL HAVE_LIBSOCKET
+./util/profile/argv_parse.c: DEBUG
+./util/profile/prof_file.c: macintosh NO_SYS_STAT_H NO_SYS_TYPES_H PROFILE_USES_PATHS _WIN32
+./util/profile/prof_init.c: macintosh PROFILE_USES_PATHS
+./util/profile/prof_int.h: macintosh PROFILE_USES_PATHS __STDC__ _WIN32
+./util/profile/prof_parse.c: EOL macintosh _WIN32
+./util/pty/configure.in: const GETPGRP_ONEARG HAS_STRSAVE HAVE_ HAVE_OPENPTY HAVE_REGCOMP HAVE_SA_LEN HAVE_SETLUID HAVE_SETOWN HAVE_STREAMS HAVE_SYS_ERRLIST KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM krb5_sigtype KRB5_USE_INET6 mode_t NEED_SYS_ERRLIST OPEN_CTTY_ONLY_ONCE POSIX_SETJMP POSIX_SIGNALS POSIX_SIGTYPE POSIX_TERMIOS PTY_UTMP_E_EXIT PTY_UTMP_E_TERMINATION PTY_UTMPX_E_EXIT PTY_UTMPX_E_TERMINATION PUSH_LDTERM PUSH_PTEM PUSH_TTCOMPAT REVOKE_NEEDS_OPEN SETPGRP_TWOARG STDC_HEADERS SYS_ERRLIST_DECLARED time_t USE_DIRENT_H HAVE_COMPILE HAVE_FCHMOD HAVE_FCHOWN HAVE_GETADDRINFO HAVE_GETNAMEINFO HAVE__GETPTY HAVE_GETTOSBYNAME HAVE_GETUTMP HAVE_GETUTMPX HAVE_GRANTPT HAVE_INET_NTOP HAVE_INET_PTON HAVE_KILLPG HAVE_LINE_PUSH HAVE_LOGWTMP HAVE_OPENPTY HAVE_PTSNAME HAVE_REVOKE HAVE_SETREUID HAVE_SETSID HAVE_SETUTENT HAVE_SETUTXENT HAVE_STEP HAVE_TTYNAME HAVE_UPDWTMP HAVE_UPDWTMPX HAVE_UTMPNAME HAVE_UTMPXNAME HAVE_VHANGUP HAVE_WAITPID HAVE_LASTLOG_H HAVE_LIBUTIL_H HAVE_MACSOCK_H HAVE_NETDB_H HAVE_NETINET_IN_H HAVE_PTY_H HAVE_STDLIB_H HAVE_STRING_H HAVE_SYS_FILIO_H HAVE_SYS_LABEL_H HAVE_SYS_PTYVAR_H HAVE_SYS_SELECT_H HAVE_SYS_SOCKET_H HAVE_SYS_SOCKIO_H HAVE_SYS_TTY_H HAVE_SYS_TYPES_H HAVE_SYS_WAIT_H HAVE_TTYENT_H HAVE_UNISTD_H HAVE_UTIL_H HAVE_UTMP_H HAVE_UTMPX_H HAVE_LIBNSL HAVE_LIBSOCKET
+./util/pty/cleanup.c: VHANG_LAST
+./util/pty/dump-utmp.c: UTMPX UTN
+./util/pty/init_slave.c: TIOCSPGRP ultrix
+./util/pty/libpty.h: __LIBPTY_H__ SOCK_DGRAM
+./util/pty/logwtmp.c: NEED_LOGWTMP_PROTO
+./util/pty/open_ctty.c: TIOCSCTTY ultrix
+./util/pty/open_slave.c: VHANG_FIRST
+./util/pty/pty-int.h: hpux NEED_GETUTMPX_PROTOTYPE NEED_REVOKE_PROTO __PTY_INT_H__ __SCO__ sysvimp ultrix WTMPX_FILE
+./util/pty/pty_paranoia.c: O_NOCTTY TIOCSCTTY
+./util/pty/update_utmp.c: __hpux _PATH_UTMP UTMP_FILE
+./util/pty/update_wtmp.c: NEED_GETUTMP_PROTO _PATH_WTMP _PATH_WTMPX WTMP_FILE WTMPX_FILE
+./util/pty/void_assoc.c: TIOCNOTTY
+./util/ss/configure.in: const HAVE_STDARG_H HAVE_VARARGS_H KRB5_DNS_LOOKUP KRB5_DNS_LOOKUP_KDC KRB5_DNS_LOOKUP_REALM NO_YYLINENO POSIX_SIGNALS RETSIGTYPE USE_DIRENT_H USE_SIGPROCMASK WAIT_USES_INT HAVE_STRDUP HAVE_STDLIB_H HAVE_LIBNSL HAVE_LIBSOCKET
+./util/ss/error.c: ibm032 NeXT __STDC__
+./util/ss/execute_cmd.c: __SABER__
+./util/ss/invocation.c: silly
+./util/ss/list_rqs.c: lint NO_FORK __STDC__
+./util/ss/pager.c: NO_FORK
+./util/ss/parse.c: DEBUG
+./util/ss/ss.h: _ss_h __STDC__
+./util/ss/ss_internal.h: __GNUC__ __HIGHC__ sigmask _ss_ss_internal_h __STDC__ vax
diff --git a/krb5-1-6/src/Makefile.in b/krb5-1-6/src/Makefile.in
new file mode 100644
index 000000000..055fb5d8b
--- /dev/null
+++ b/krb5-1-6/src/Makefile.in
@@ -0,0 +1,600 @@
+datadir=@datadir@
+
+thisconfigdir=.
+myfulldir=.
+mydir=.
+# Don't build sample by default: plugins/locate/python plugins/preauth/wpse plugins/preauth/cksum_body
+SUBDIRS=util include lib @krb524@ kdc kadmin @ldap_plugin_dir@ slave clients \
+	plugins/kdb/db2 \
+	plugins/preauth/pkinit \
+	appl tests \
+	config-files gen-manpages
+BUILDTOP=$(REL)$(C)
+LOCALINCLUDES = -I$(srcdir) 
+
+SRCS =  
+HDRS = 
+
+DISTFILES = $(SRCS) $(HDRS) COPYING COPYING.LIB ChangeLog Makefile.in
+
+all-unix:: krb5-config
+
+# Lots of things will start to depend on the thread support, which
+# needs autoconf.h, but building "all" in include requires that util/et
+# have been built first.  Until we can untangle this, let's just check
+# that autoconf.h is up to date before going into any of the subdirectories.
+all-prerecurse generate-files-mac-prerecurse: update-autoconf-h
+update-autoconf-h:
+	(cd include && $(MAKE) autoconf.h osconf.h)
+
+##DOS##!if 0
+# This makefile doesn't use lib.in, but we still need shlib.conf here.
+config.status: $(SRCTOP)/config/shlib.conf
+##DOS##!endif
+
+all-windows:: maybe-awk Makefile-windows
+	@echo Making autoconf.h in include
+	cd include
+	$(MAKE) -$(MFLAGS) autoconf.h
+	@echo Making in util
+	cd ..\util
+	$(MAKE) -$(MFLAGS)
+	@echo Making in include
+	cd ..\include
+	$(MAKE) -$(MFLAGS) 
+	@echo Making in lib
+	cd ..\lib
+	$(MAKE) -$(MFLAGS) 
+	@echo Making in windows
+	cd ..\windows
+	$(MAKE) -$(MFLAGS) 
+	@echo Making in clients
+	cd ..\clients
+	$(MAKE) -$(MFLAGS)
+	@echo Making in appl\gss-sample
+	cd ..\appl\gss-sample
+	$(MAKE) -$(MFLAGS)
+	@echo Making in appl\gssftp\ftp
+	cd ..\..\appl\gssftp\ftp
+	$(MAKE) -$(MFLAGS)
+	cd ..\..\..
+
+world::
+	date
+	make $(MFLAGS) all
+	date
+
+INSTALLMKDIRS = $(KRB5ROOT) $(KRB5MANROOT) $(KRB5OTHERMKDIRS) \
+		$(ADMIN_BINDIR) $(SERVER_BINDIR) $(CLIENT_BINDIR) \
+		$(ADMIN_MANDIR) $(SERVER_MANDIR) $(CLIENT_MANDIR) \
+		$(FILE_MANDIR) $(KRB5_LIBDIR) $(KRB5_INCDIR) \
+		$(KRB5_DB_MODULE_DIR) $(KRB5_PA_MODULE_DIR) \
+		$(KRB5_LIBKRB5_MODULE_DIR) \
+		@localstatedir@ @localstatedir@/krb5kdc \
+		$(KRB5_INCSUBDIRS) $(datadir) $(EXAMPLEDIR)
+
+install-strip:
+	$(MAKE) install INSTALL_STRIP=-s
+
+install-recurse: install-mkdirs
+
+install-mkdirs:
+	@for i in $(INSTALLMKDIRS); do \
+		$(srcdir)/config/mkinstalldirs $(DESTDIR)$$i; \
+	done
+
+install-headers-mkdirs:
+	$(srcdir)/config/mkinstalldirs $(DESTDIR)$(KRB5_INCDIR)
+	$(srcdir)/config/mkinstalldirs $(DESTDIR)$(KRB5_INCDIR)/gssapi
+	$(srcdir)/config/mkinstalldirs $(DESTDIR)$(KRB5_INCDIR)/gssrpc
+	$(srcdir)/config/mkinstalldirs $(DESTDIR)$(KRB5_INCDIR)/kerberosIV
+install-headers-prerecurse: install-headers-mkdirs
+
+# install::
+#	$(MAKE) $(MFLAGS) install.man
+
+fake-install:
+	$(RM) -r $(FAKEPREFIX)
+	@for i in $(INSTALLMKDIRS); do \
+		$(srcdir)/config/mkinstalldirs util/fakedest$$i; \
+	done
+	(w=`pwd`; cd util && $(MAKE) install DESTDIR="$$w/util/fakedest")
+	(w=`pwd`; cd lib && $(MAKE) install DESTDIR="$$w/util/fakedest")
+	(w=`pwd`; cd plugins/kdb/db2 && $(MAKE) install DESTDIR="$$w/util/fakedest")
+	if test -r plugins/preauth/pkinit/Makefile; then \
+	  (w=`pwd`; cd plugins/preauth/pkinit && $(MAKE) install DESTDIR="$$w/util/fakedest"); \
+	fi
+
+#	(w=`pwd`; cd plugins/locate/python && $(MAKE) install DESTDIR="$$w/util/fakedest")
+
+TAGS: $(SRCS)
+	etags $(SRCS)
+
+clean-:: clean-windows
+clean-unix::
+	$(RM) *.o core krb5-config
+	$(RM) -r util/fakedest
+
+mostlyclean: clean
+
+# This doesn't work; if you think you need it, you should use a
+# separate build directory.
+# 
+# distclean: clean
+# 	rm -f Makefile config.status
+# 
+# realclean: distclean
+# 	rm -f TAGS
+
+dist: $(DISTFILES)
+	echo cpio-`sed -e '/version_string/!d' \
+	-e 's/[^0-9.]*\([0-9.]*\).*/\1/' -e q version.c` > .fname
+	rm -rf `cat .fname`
+	mkdir `cat .fname`
+	-ln $(DISTFILES) `cat .fname`
+	for file in $(DISTFILES); do \
+	  test -r `cat .fname`/$$file || cp -p $$file `cat .fname`; \
+	done
+	tar chzf `cat .fname`.tar.gz `cat .fname`
+	rm -rf `cat .fname` .fname
+
+GZIPPROG= gzip -9v
+PKGDIR=`pwd`/pkgdir
+pkgdir:
+	if test ! -d $(PKGDIR); then mkdir $(PKGDIR); else true; fi
+tgz-bin: pkgdir
+	rm -rf $(PKGDIR)/install cns5-bin.tgz
+	mkdir $(PKGDIR)/install
+	$(MAKE) install DESTDIR=$(PKGDIR)/install
+	(cd $(PKGDIR)/install && tar cf - usr/cygnus) | $(GZIPPROG) > cns5-bin.tgz
+	rm -rf $(PKGDIR)/install
+
+# Microsoft Windows build process...
+#
+
+config-windows:: Makefile-windows
+#	@echo Making in include
+#	cd include
+#	$(MAKE) -$(MFLAGS)
+#	cd ..
+
+#
+# We need outpre-dir explicitly in here because we may
+# try to build wconfig on a config-windows.
+#
+##DOS##$(WCONFIG_EXE): outpre-dir wconfig.c
+##DOS##	$(CC) -Fe$@ -Fo$*.obj wconfig.c $(CCLINKOPTION)
+##DOS## $(_VC_MANIFEST_EMBED_EXE)
+
+##DOS##MKFDEP=$(WCONFIG_EXE) config\win-pre.in config\win-post.in
+
+WINMAKEFILES=Makefile \
+	appl\gss-sample\Makefile \
+	appl\gssftp\ftp\Makefile \
+	clients\Makefile clients\kdestroy\Makefile \
+	clients\kinit\Makefile clients\klist\Makefile \
+	clients\kpasswd\Makefile clients\kvno\Makefile \
+	clients\kcpytkt\Makefile clients\kdeltkt\Makefile \
+	include\Makefile \
+	krb524\Makefile \
+	lib\Makefile lib\crypto\Makefile \
+	lib\crypto\crc32\Makefile lib\crypto\des\Makefile \
+	lib\crypto\dk\Makefile lib\crypto\enc_provider\Makefile \
+	lib\crypto\hash_provider\Makefile \
+	lib\crypto\keyhash_provider\Makefile \
+	lib\crypto\raw\Makefile lib\crypto\old\Makefile \
+	lib\crypto\sha1\Makefile lib\crypto\arcfour\Makefile \
+	lib\crypto\md4\Makefile lib\crypto\md5\Makefile \
+	lib\crypto\yarrow\Makefile lib\crypto\aes\Makefile \
+	lib\des425\Makefile \
+	lib\gssapi\Makefile lib\gssapi\generic\Makefile \
+	lib\gssapi\krb5\Makefile lib\gssapi\mechglue\Makefile \
+	lib\gssapi\spnego\Makefile \
+	lib\krb4\Makefile lib\krb5\Makefile \
+	lib\krb5\asn.1\Makefile lib\krb5\ccache\Makefile \
+	lib\krb5\ccache\ccapi\Makefile \
+	lib\krb5\error_tables\Makefile \
+	lib\krb5\keytab\Makefile \
+	lib\krb5\krb\Makefile \
+	lib\krb5\os\Makefile lib\krb5\posix\Makefile \
+	lib\krb5\rcache\Makefile \
+	util\Makefile \
+	util\et\Makefile util\profile\Makefile \
+	util\support\Makefile \
+	util\windows\Makefile \
+	windows\Makefile windows\lib\Makefile \
+	windows\cns\Makefile windows\gina\Makefile \
+	windows\gss\Makefile windows\ms2mit\Makefile \
+	windows\wintel\Makefile windows\kfwlogon\Makefile
+
+##DOS##Makefile-windows:: $(MKFDEP) $(WINMAKEFILES)
+
+##DOS##Makefile: Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##appl\gss-sample\Makefile: appl\gss-sample\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##appl\gssftp\ftp\Makefile: appl\gssftp\ftp\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\Makefile: clients\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\kdestroy\Makefile: clients\kdestroy\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\kinit\Makefile: clients\kinit\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\klist\Makefile: clients\klist\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\kpasswd\Makefile: clients\kpasswd\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\kvno\Makefile: clients\kvno\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\kcpytkt\Makefile: clients\kcpytkt\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##clients\kdeltkt\Makefile: clients\kdeltkt\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##include\Makefile: include\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##krb524\Makefile: krb524\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\Makefile: lib\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\Makefile: lib\crypto\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\crc32\Makefile: lib\crypto\crc32\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\des\Makefile: lib\crypto\des\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\dk\Makefile: lib\crypto\dk\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\enc_provider\Makefile: lib\crypto\enc_provider\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\hash_provider\Makefile: lib\crypto\hash_provider\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\keyhash_provider\Makefile: lib\crypto\keyhash_provider\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\sha1\Makefile: lib\crypto\sha1\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\arcfour\Makefile: lib\crypto\arcfour\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\md4\Makefile: lib\crypto\md4\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\md5\Makefile: lib\crypto\md5\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\yarrow\Makefile: lib\crypto\yarrow\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\aes\Makefile: lib\crypto\aes\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\old\Makefile: lib\crypto\old\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\crypto\raw\Makefile: lib\crypto\raw\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\des425\Makefile: lib\des425\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\gssapi\Makefile: lib\gssapi\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\gssapi\generic\Makefile: lib\gssapi\generic\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\gssapi\mechglue\Makefile: lib\gssapi\mechglue\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\gssapi\spnego\Makefile: lib\gssapi\spnego\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\gssapi\krb5\Makefile: lib\gssapi\krb5\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb4\Makefile: lib\krb4\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\Makefile: lib\krb5\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\asn.1\Makefile: lib\krb5\asn.1\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\ccache\Makefile: lib\krb5\ccache\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\ccache\ccapi\Makefile: lib\krb5\ccache\ccapi\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\error_tables\Makefile: lib\krb5\error_tables\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\keytab\Makefile: $$@.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\krb\Makefile: lib\krb5\krb\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\os\Makefile: lib\krb5\os\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\posix\Makefile: lib\krb5\posix\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##lib\krb5\rcache\Makefile: lib\krb5\rcache\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##util\Makefile: util\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##util\et\Makefile: util\et\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##util\profile\Makefile: util\profile\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##util\support\Makefile: util\support\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##util\windows\Makefile: util\windows\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\Makefile: windows\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\lib\Makefile: windows\lib\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\cns\Makefile: windows\cns\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\gina\Makefile: windows\gina\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\gss\Makefile: windows\gss\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\ms2mit\Makefile: windows\ms2mit\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\wintel\Makefile: windows\wintel\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+##DOS##windows\kfwlogon\Makefile: windows\kfwlogon\Makefile.in $(MKFDEP)
+##DOS##	$(WCONFIG) config < $@.in > $@
+
+clean-windows:: Makefile-windows
+	@echo Making clean in util
+	cd util
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in include
+	cd ..\include
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in lib
+	cd ..\lib
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in windows
+	cd ..\windows
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in clients
+	cd ..\clients
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making in appl\gss-sample
+	cd ..\appl\gss-sample
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making in appl\gssftp\ftp
+	cd ..\..\appl\gssftp\ftp
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\..\..
+	@echo Making clean in root
+
+#
+# Renames DOS 8.3 filenames back to their proper, longer names.
+#
+ren2long:
+	-sh config/ren2long
+
+#
+# Builds the file that distributes Kerberos sources for DOS and 
+# Macintosh sites from the source tree on Unix.
+#
+ZIP=zip
+FILES= ./* \
+	clients/* clients/kdestroy/* clients/kinit/* clients/klist/* \
+	clients/kpasswd/* clients/kcpytkt/* clients/kdeltkt/* \
+	config/* include/* include/kerberosIV/* \
+	include/krb5/* include/krb5/stock/* include/sys/* krb524/* lib/* \
+	lib/crypto/* lib/crypto/crc32/* lib/crypto/des/* lib/crypto/dk/* \
+	lib/crypto/enc_provider/* lib/crypto/hash_provider/* \
+	lib/crypto/keyhash_provider/* lib/crypto/old/* lib/crypto/raw/* \
+	lib/crypto/sha1/* lib/crypto/arcfour/* lib/crypto/md4/* \
+	lib/crypto/md5/* lib/crypto/yarrow/* \
+	lib/des425/* lib/gssapi/* lib/gssapi/generic/* lib/gssapi/krb5/* \
+	lib/gssapi/mechglue/* lib/gssapi/spnego/* lib/krb4/* \
+	lib/krb5/* lib/krb5/asn.1/* lib/krb5/krb/* \
+	lib/krb5/ccache/* lib/krb5/ccache/ccapi/* \
+	lib/krb5/error_tables/* \
+	lib/krb5/keytab/* lib/krb5/keytab/file/* lib/krb5/keytab/srvtab/* \
+	lib/krb5/os/* lib/krb5/posix/* lib/krb5/rcache/* \
+	util/* util/et/* util/profile/*
+
+WINFILES= util/windows/* windows/* windows/lib/* windows/cns/* \
+	windows/wintel/* windows/gss/* windows/gina/* windows/ms2mit/* \
+	windows/kfwlogon/*
+
+WINBINARYFILES=	windows/*/*.ico windows/*/*.doc windows/*/*.hlp \
+	windows/*/*.hpj windows/lib/*.lib
+
+#
+# Part of building the PC release has to be done on Unix. This includes
+# anything the requires awk.
+#
+AWK = awk
+AH  = util/et/et_h.awk
+AC  = util/et/et_c.awk
+INC = include/
+ET  = lib/krb5/error_tables/
+GG  = lib/gssapi/generic/
+GK  = lib/gssapi/krb5/
+PR  = util/profile/
+CE  = util/et/
+
+ETOUT =	\
+	$(INC)asn1_err.h $(ET)asn1_err.c \
+	$(INC)kdb5_err.h $(ET)kdb5_err.c \
+	$(INC)krb5_err.h $(ET)krb5_err.c \
+	$(INC)kv5m_err.h $(ET)kv5m_err.c \
+	$(INC)krb524_err.h $(ET)krb524_err.c \
+	$(INC)/kerberosIV/kadm_err.h lib/krb4/kadm_err.c \
+	$(INC)/kerberosIV/krb_err.h lib/krb4/krb_err.c \
+	$(PR)prof_err.h $(PR)prof_err.c \
+	$(GG)gssapi_err_generic.h $(GG)gssapi_err_generic.c \
+	$(GK)gssapi_err_krb5.h $(GK)gssapi_err_krb5.c \
+	lib/krb4/krb_err_txt.c
+
+HOUT =	$(INC)krb5\krb5.h $(GG)gssapi.h $(PR)profile.h
+
+CLEANUP= Makefile $(ETOUT) $(HOUT) \
+	include/profile.h include/osconf.h \
+	winfile.list
+
+
+kerbsrc.win: kerbsrc.zip
+
+winfile.list:
+	echo $(FILES) $(WINFILES) | tr ' ' \\012 | \
+		sed -f config/winexclude.sed > winfile.list
+
+dos-Makefile:
+	cat config/win-pre.in Makefile.in config/win-post.in | \
+		sed -e "s/^##DOS##//" -e "s/^##DOS//" > Makefile.tmp
+	mv Makefile.tmp Makefile
+
+prep-windows: dos-Makefile awk-windows-mac
+
+krbsrc83.zip: krbsrc83-is-obsolete
+
+krbsrc83-is-obsolete:
+	@echo "Win16 and krbsrc83.zip are no longer supported."
+	@echo "We don't support building under 8.3 restricted filesystems"
+	@echo "anymore.  You can still build for Win32 on filesystems"
+	@echo "without 8.3 restrictions using kerbsrc.zip"
+	@echo " "
+
+kerbsrc.zip: dos-Makefile awk-windows-mac winfile.list
+	rm -f kerbsrc.zip
+	$(ZIP) -@Dl kerbsrc.zip < winfile.list
+	$(ZIP) -D kerbsrc.zip $(WINBINARYFILES)
+	rm -f $(CLEANUP)
+
+kerbsrc-nt.zip: kerbsrc-nt-is-obsolete
+
+kerbsrc-nt-is-obsolete:
+	@echo "kerbsrc-nt.zip is now obsolete.  Just use and build kerbsrc.zip"
+	@echo "We don't support building under 8.3 restricted filesystems"
+	@echo "anymore, so what was kerbsrc-nt.zip is now kerbsrc.zip."
+	@echo " "
+
+$(INC)asn1_err.h: $(AH) $(ET)asn1_err.et
+	$(AWK) -f $(AH) outfile=$@ $(ET)asn1_err.et
+$(INC)kdb5_err.h: $(AH) $(ET)kdb5_err.et
+	$(AWK) -f $(AH) outfile=$@ $(ET)kdb5_err.et
+$(INC)krb5_err.h: $(AH) $(ET)krb5_err.et
+	$(AWK) -f $(AH) outfile=$@ $(ET)krb5_err.et
+$(INC)kv5m_err.h: $(AH) $(ET)kv5m_err.et
+	$(AWK) -f $(AH) outfile=$@ $(ET)kv5m_err.et
+$(INC)krb524_err.h: $(AH) $(ET)krb524_err.et
+	$(AWK) -f $(AH) outfile=$@ $(ET)krb524_err.et
+$(INC)/kerberosIV/kadm_err.h: $(AH) lib/krb4/kadm_err.et
+	$(AWK) -f $(AH) outfile=$@ lib/krb4/kadm_err.et
+$(INC)/kerberosIV/krb_err.h: $(AH) lib/krb4/krb_err.et
+	$(AWK) -f $(AH) outfile=$@ lib/krb4/krb_err.et
+$(PR)prof_err.h: $(AH) $(PR)prof_err.et
+	$(AWK) -f $(AH) outfile=$@ $(PR)prof_err.et
+$(GG)gssapi_err_generic.h: $(AH) $(GG)gssapi_err_generic.et
+	$(AWK) -f $(AH) outfile=$@ $(GG)gssapi_err_generic.et
+$(GK)gssapi_err_krb5.h: $(AH) $(GK)gssapi_err_krb5.et
+	$(AWK) -f $(AH) outfile=$@ $(GK)gssapi_err_krb5.et
+$(CE)test1.h: $(AH) $(CE)test1.et
+	$(AWK) -f $(AH) outfile=$@ $(CE)test1.et
+$(CE)test2.h: $(AH) $(CE)test2.et
+	$(AWK) -f $(AH) outfile=$@ $(CE)test2.et
+
+$(ET)asn1_err.c: $(AC) $(ET)asn1_err.et
+	$(AWK) -f $(AC) outfile=$@ $(ET)asn1_err.et
+$(ET)kdb5_err.c: $(AC) $(ET)kdb5_err.et
+	$(AWK) -f $(AC) outfile=$@ $(ET)kdb5_err.et
+$(ET)krb5_err.c: $(AC) $(ET)krb5_err.et
+	$(AWK) -f $(AC) outfile=$@ $(ET)krb5_err.et
+$(ET)kv5m_err.c: $(AC) $(ET)kv5m_err.et
+	$(AWK) -f $(AC) outfile=$@ $(ET)kv5m_err.et
+$(ET)krb524_err.c: $(AC) $(ET)krb524_err.et
+	$(AWK) -f $(AC) outfile=$@ $(ET)krb524_err.et
+lib/krb4/kadm_err.c: $(AC) lib/krb4/kadm_err.et
+	$(AWK) -f $(AC) outfile=$@ lib/krb4/kadm_err.et
+lib/krb4/krb_err.c: $(AC) lib/krb4/krb_err.et
+	$(AWK) -f $(AC) outfile=$@ lib/krb4/krb_err.et
+$(PR)prof_err.c: $(AC) $(PR)prof_err.et
+	$(AWK) -f $(AC) outfile=$@ $(PR)prof_err.et
+$(GG)gssapi_err_generic.c: $(AC) $(GG)gssapi_err_generic.et
+	$(AWK) -f $(AC) outfile=$@ $(GG)gssapi_err_generic.et
+$(GK)gssapi_err_krb5.c: $(AC) $(GK)gssapi_err_krb5.et
+	$(AWK) -f $(AC) outfile=$@ $(GK)gssapi_err_krb5.et
+$(CE)test1.c: $(AC) $(CE)test1.et
+	$(AWK) -f $(AC) outfile=$@ $(CE)test1.et
+$(CE)test2.c: $(AC) $(CE)test2.et
+	$(AWK) -f $(AC) outfile=$@ $(CE)test2.et
+
+lib/krb4/krb_err_txt.c: lib/krb4/krb_err.et
+	$(AWK) -f lib/krb4/et_errtxt.awk outfile=$@ \
+		lib/krb4/krb_err.et
+
+KRBHDEP = $(INC)krb5\krb5.hin $(INC)krb5_err.h $(INC)kdb5_err.h \
+	$(INC)kv5m_err.h $(INC)krb524_err.h $(INC)asn1_err.h
+
+$(INC)krb5\krb5.h: $(KRBHDEP)
+	rm -f $@
+	cat $(KRBHDEP) > $@
+$(PR)profile.h: $(PR)profile.hin $(PR)prof_err.h
+	rm -f $@
+	cat $(PR)profile.hin $(PR)prof_err.h > $@
+$(GG)gssapi.h: $(GG)gssapi.hin
+	rm -f $@
+	cat $(GG)gssapi.hin > $@
+
+awk-windows-mac: $(ETOUT) $(HOUT)
+
+#
+# The maybe-awk target needs to happen after AWK is defined.
+#
+
+##DOS##maybe-awk::
+##DOS##!ifdef WHICH_CMD
+##DOS##!if ![ $(WHICH_CMD) $(AWK) ]
+##DOS##maybe-awk:: awk-windows-mac
+##DOS##!endif
+##DOS##!endif
+
+clean-windows-mac:
+	rm -f $(CLEANUP)
+
+distclean-windows:
+	config\rm.bat $(CLEANUP:^/=^\)
+	config\rm.bat $(WINMAKEFILES)
+	config\rm.bat $(KBINDIR)\*.dll $(KBINDIR)\*.exe
+	@if exist $(KBINDIR)\nul rmdir $(KBINDIR)
+
+install-windows::
+	@if "$(KRB_INSTALL_DIR)"=="" @echo KRB_INSTALL_DIR is not defined!  Please define it.
+	@if "$(KRB_INSTALL_DIR)"=="" @dir /b \nul\nul
+	@if not exist "$(KRB_INSTALL_DIR)\$(NULL)" @echo The directory $(KRB_INSTALL_DIR) does not exist.  Please create it.
+	@if not exist "$(KRB_INSTALL_DIR)\$(NULL)" @dir /b $(KRB_INSTALL_DIR)\nul
+	@if not exist "$(KRB_INSTALL_DIR)\include\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\include"
+	@if not exist "$(KRB_INSTALL_DIR)\include\krb5\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\include\krb5"
+	@if not exist "$(KRB_INSTALL_DIR)\include\gssapi\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\include\gssapi"
+	@if not exist "$(KRB_INSTALL_DIR)\lib\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\lib"
+	@if not exist "$(KRB_INSTALL_DIR)\bin\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\bin"
+	$(CP) include\krb5.h "$(KRB_INSTALL_DIR)\include\."
+	$(CP) include\krb5\krb5.h "$(KRB_INSTALL_DIR)\include\krb5\."
+	$(CP) include\win-mac.h "$(KRB_INSTALL_DIR)\include\."
+	$(CP) include\profile.h "$(KRB_INSTALL_DIR)\include\."
+	$(CP) include\com_err.h "$(KRB_INSTALL_DIR)\include\."
+	$(CP) include\gssapi\gssapi.h "$(KRB_INSTALL_DIR)\include\gssapi\."
+	$(CP) include\gssapi\gssapi_krb5.h "$(KRB_INSTALL_DIR)\include\gssapi\."
+	$(CP) lib\$(OUTPRE)*.lib "$(KRB_INSTALL_DIR)\lib\."
+	$(CP) lib\$(OUTPRE)*.dll "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) windows\cns\$(OUTPRE)krb5.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) windows\wintel\$(OUTPRE)telnet.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) windows\gss\$(OUTPRE)gss.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) appl\gss-sample\$(OUTPRE)gss-server.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) appl\gss-sample\$(OUTPRE)gss-client.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) windows\ms2mit\$(OUTPRE)ms2mit.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) appl\gssftp\ftp\$(OUTPRE)ftp.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) clients\kvno\$(OUTPRE)kvno.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) clients\klist\$(OUTPRE)klist.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) clients\kinit\$(OUTPRE)kinit.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) clients\kdestroy\$(OUTPRE)kdestroy.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) clients\kcpytkt\$(OUTPRE)kcpytkt.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) clients\kdeltkt\$(OUTPRE)kdeltkt.exe "$(KRB_INSTALL_DIR)\bin\."
+	$(CP) clients\kpasswd\$(OUTPRE)kpasswd.exe "$(KRB_INSTALL_DIR)\bin\."
+	@if exist "$(KRB_INSTALL_DIR)\bin\krb4_32.dll" del "$(KRB_INSTALL_DIR)\bin\krb4_32.dll"
+	@if exist "$(KRB_INSTALL_DIR)\lib\krb4_32.lib" del "$(KRB_INSTALL_DIR)\lib\krb4_32.lib"
+
+install-unix:: 
+	$(INSTALL_SCRIPT) krb5-config \
+		$(DESTDIR)$(CLIENT_BINDIR)/krb5-config
+	$(INSTALL_DATA) $(srcdir)/krb5-config.M $(DESTDIR)$(CLIENT_MANDIR)/krb5-config.1
+
+krb5-config: $(srcdir)/krb5-config.in $(thisconfigdir)/config.status
+	cd $(thisconfigdir) && $(SHELL) config.status krb5-config
+
+# Test to ensure that krb5-config does not spit out things like
+# $(PURE) or $(LDFLAGS) in case someone changes config/shlib.conf
+check-unix:: krb5-config
+	$(SHELL) $(srcdir)/t_krbconf
+check-prerecurse: fake-install
diff --git a/krb5-1-6/src/aclocal.m4 b/krb5-1-6/src/aclocal.m4
new file mode 100644
index 000000000..c4ce88aa5
--- /dev/null
+++ b/krb5-1-6/src/aclocal.m4
@@ -0,0 +1,1825 @@
+AC_PREREQ(2.52)
+AC_COPYRIGHT([Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Massachusetts Institute of Technology.
+])
+dnl
+dnl Figure out the top of the source and build trees.  We depend on localdir
+dnl being a relative pathname; we could make it general later, but for now 
+dnl this is good enough.
+dnl
+dnl esyscmd([test -r aclocal.m4 && echo YES])
+define([fileexists],[dnl
+pushdef([x],esyscmd([if test -r $1; then echo YES;else echo NO; fi]))dnl
+dnl Strip out newline.
+ifelse(x,[YES
+],[YES],x,[NO
+],[NO],UNKNOWN)[]popdef([x])])
+define([K5_TOPDIR],dnl
+ifelse(fileexists(./aclocal.m4),YES,[.],[dnl
+ifelse(fileexists(../aclocal.m4),YES,[..],[dnl
+ifelse(fileexists(../../aclocal.m4),YES,[../..],[dnl
+ifelse(fileexists(../../../aclocal.m4),YES,[../../..],[dnl
+ifelse(fileexists(../../../../aclocal.m4),YES,[../../../..],[dnl
+errprint(__file__:__line__: Cannot find path to aclocal.m4[
+]) m4exit(1) dnl sometimes that does not work?
+builtin(m4exit,1)UNKNOWN])])])])]))
+dnl
+AC_DEFUN(V5_SET_TOPDIR,[dnl
+ac_reltopdir="K5_TOPDIR"
+if test ! -r "$srcdir/K5_TOPDIR/aclocal.m4"; then
+  AC_MSG_ERROR([Configure could not determine the relative topdir])
+fi
+ac_topdir=$srcdir/$ac_reltopdir
+ac_config_fragdir=$ac_reltopdir/config
+# echo "Looking for $srcdir/$ac_config_fragdir"
+if test -d "$srcdir/$ac_config_fragdir"; then
+  AC_CONFIG_AUX_DIR(K5_TOPDIR/config)
+else
+  AC_MSG_ERROR([can not find config/ directory in $ac_reltopdir])
+fi
+])dnl
+dnl
+dnl Version info.
+dnl
+pushdef([x],esyscmd([sed -n 's/#define \([A-Z0-9_]*\)[ \t]*\(.*\)/\1=\2/p' < ]K5_TOPDIR/patchlevel.h))
+define([PL_KRB5_MAJOR_RELEASE],regexp(x,[KRB5_MAJOR_RELEASE=\(.*\)],[\1]))
+ifelse(PL_KRB5_MAJOR_RELEASE,,[errprint([Can't determine KRB5_MAJOR_RELEASE value from patchlevel.h.
+]) m4exit(1) dnl sometimes that does not work?
+builtin(m4exit,1)])
+define([PL_KRB5_MINOR_RELEASE],regexp(x,[KRB5_MINOR_RELEASE=\(.*\)],[\1]))
+ifelse(PL_KRB5_MINOR_RELEASE,,[errprint([Can't determine KRB5_MINOR_RELEASE value from patchlevel.h.
+]) m4exit(1) dnl sometimes that does not work?
+builtin(m4exit,1)])
+define([PL_KRB5_PATCHLEVEL],regexp(x,[KRB5_PATCHLEVEL=\(.*\)],[\1]))
+ifelse(PL_KRB5_PATCHLEVEL,,[errprint([Can't determine KRB5_PATCHLEVEL value from patchlevel.h.
+]) m4exit(1) dnl sometimes that does not work?
+builtin(m4exit,1)])
+define([PL_KRB5_RELTAIL],regexp(x,[KRB5_RELTAIL="\(.*\)"],[\1]))
+dnl RELTAIL is allowed to not be defined.
+popdef([x])
+define([K5_VERSION],PL_KRB5_MAJOR_RELEASE.PL_KRB5_MINOR_RELEASE[]ifelse(PL_KRB5_PATCHLEVEL,0,,.PL_KRB5_PATCHLEVEL)ifelse(PL_KRB5_RELTAIL,,,-PL_KRB5_RELTAIL))
+define([K5_BUGADDR],krb5-bugs@mit.edu)
+define([K5_AC_INIT],[AC_INIT(Kerberos 5, K5_VERSION, K5_BUGADDR, krb5)
+AC_CONFIG_SRCDIR($1)
+build_dynobj=no])
+dnl
+dnl drop in standard rules for all configure files -- CONFIG_RULES
+dnl
+AC_DEFUN(CONFIG_RULES,[dnl
+AC_REQUIRE([V5_SET_TOPDIR]) dnl
+EXTRA_FILES=""
+AC_SUBST(EXTRA_FILES)
+WITH_CC dnl
+AC_REQUIRE_CPP
+if test -z "$LD" ; then LD=$CC; fi
+AC_ARG_VAR(LD,[linker command [CC]])
+AC_SUBST(LDFLAGS) dnl
+WITH_KRB4 dnl
+KRB5_AC_CHOOSE_ET dnl
+KRB5_AC_CHOOSE_SS dnl
+KRB5_AC_CHOOSE_DB dnl
+dnl allow stuff in tree to access deprecated/private stuff for now
+dnl AC_DEFINE([KRB5_PRIVATE], 1, [Define only if building in-tree])
+dnl AC_DEFINE([KRB5_DEPRECATED], 1, [Define only if building in-tree])
+AC_C_CONST dnl
+WITH_NETLIB dnl
+WITH_HESIOD dnl
+KRB5_AC_MAINTAINER_MODE dnl
+AC_ARG_PROGRAM dnl
+dnl
+dnl This identifies the top of the source tree relative to the directory 
+dnl in which the configure file lives.
+dnl
+CONFIG_RELTOPDIR=$ac_reltopdir
+AC_SUBST(CONFIG_RELTOPDIR)
+AC_SUBST(subdirs)
+lib_frag=$srcdir/$ac_config_fragdir/lib.in
+AC_SUBST_FILE(lib_frag)
+libobj_frag=$srcdir/$ac_config_fragdir/libobj.in
+AC_SUBST_FILE(libobj_frag)
+libnover_frag=$srcdir/$ac_config_fragdir/libnover.in
+AC_SUBST_FILE(libnover_frag)
+dnl
+KRB5_AC_PRAGMA_WEAK_REF
+WITH_LDAP
+KRB5_LIB_PARAMS
+KRB5_AC_INITFINI
+KRB5_AC_ENABLE_THREADS
+KRB5_AC_FIND_DLOPEN
+KRB5_AC_KEYRING_CCACHE
+])dnl
+
+dnl Maintainer mode, akin to what automake provides, 'cept we don't
+dnl want to use automake right now.
+AC_DEFUN([KRB5_AC_MAINTAINER_MODE],
+[AC_ARG_ENABLE([maintainer-mode],
+AC_HELP_STRING([--enable-maintainer-mode],[enable rebuilding of source files, Makefiles, etc]),
+USE_MAINTAINER_MODE=$enableval,
+USE_MAINTAINER_MODE=no)
+if test "$USE_MAINTAINER_MODE" = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+  AC_MSG_NOTICE(enabling maintainer mode)
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+MAINT=$MAINTAINER_MODE_TRUE
+AC_SUBST(MAINTAINER_MODE_TRUE)
+AC_SUBST(MAINTAINER_MODE_FALSE)
+AC_SUBST(MAINT)
+])
+
+dnl
+AC_DEFUN([KRB5_AC_INITFINI],[
+dnl Do we want initialization at load time?
+AC_ARG_ENABLE([delayed-initialization],
+AC_HELP_STRING([--disable-delayed-initialization],initialize library code when loaded @<:@delay until first use@:>@), , enable_delayed_initialization=yes)
+case "$enable_delayed_initialization" in
+  yes)
+    AC_DEFINE(DELAY_INITIALIZER,1,[Define if library initialization should be delayed until first use]) ;;
+  no) ;;
+  *)  AC_MSG_ERROR(invalid option $enable_delayed_initialization for delayed-initialization) ;;
+esac
+dnl We always want finalization at unload time.
+dnl
+dnl Can we do things through gcc?
+KRB5_AC_GCC_ATTRS
+dnl How about with the linker?
+if test -z "$use_linker_init_option" ; then
+  AC_MSG_ERROR(ran INITFINI before checking shlib.conf?)
+fi
+if test "$use_linker_init_option" = yes; then
+  AC_DEFINE(USE_LINKER_INIT_OPTION,1,[Define if link-time options for library initialization will be used])
+fi
+if test "$use_linker_fini_option" = yes; then
+  AC_DEFINE(USE_LINKER_FINI_OPTION,1,[Define if link-time options for library finalization will be used])
+fi
+])
+
+dnl find dlopen
+AC_DEFUN([KRB5_AC_FIND_DLOPEN],[
+old_LIBS="$LIBS"
+DL_LIB=
+AC_SEARCH_LIBS(dlopen, dl, [
+if test "$ac_cv_search_dlopen" != "none required"; then
+  DL_LIB=$ac_cv_search_dlopen
+fi
+LIBS="$old_LIBS"
+AC_DEFINE(USE_DLOPEN,1,[Define if dlopen should be used])])
+AC_SUBST(DL_LIB)
+])
+
+
+dnl Hack for now.
+AC_DEFUN([KRB5_AC_ENABLE_THREADS],[
+AC_ARG_ENABLE([thread-support],
+AC_HELP_STRING([--disable-thread-support],don't enable thread support @<:@enabled@:>@), , enable_thread_support=yes)
+if test "$enable_thread_support" = yes ; then
+  AC_MSG_NOTICE(enabling thread support)
+  AC_DEFINE(ENABLE_THREADS,1,[Define if thread support enabled])
+fi
+dnl Maybe this should be inside the conditional above?  Doesn't cache....
+if test "$enable_thread_support" = yes; then
+  ACX_PTHREAD(,[AC_MSG_ERROR([cannot determine options for enabling thread support; try --disable-thread-support])])
+  AC_MSG_NOTICE(PTHREAD_CC = $PTHREAD_CC)
+  AC_MSG_NOTICE(PTHREAD_CFLAGS = $PTHREAD_CFLAGS)
+  AC_MSG_NOTICE(PTHREAD_LIBS = $PTHREAD_LIBS)
+  dnl Not really needed -- if pthread.h isn't found, ACX_PTHREAD will fail.
+  dnl AC_CHECK_HEADERS(pthread.h)
+  # AIX and Tru64 don't support weak references, and don't have
+  # stub versions of the pthread code in libc.
+  case "${host_os}" in
+    aix* | osf*)
+      # On these platforms, we'll always pull in the thread support.
+      LIBS="$LIBS $PTHREAD_LIBS"
+      CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+      # We don't need to sometimes add the flags we've just folded in...
+      PTHREAD_LIBS=
+      PTHREAD_CFLAGS=
+      ;;
+    hpux*)
+      # These are the flags that "gcc -pthread" adds.  But we don't
+      # want "-pthread" because that has link-time effects, and we
+      # don't exclude CFLAGS when linking.  *sigh*
+      PTHREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_C_SOURCE=199506L"
+      ;;
+    solaris*)
+      # On Solaris 10 with gcc 3.4.3, the autoconf archive macro doesn't
+      # get the right result.
+      if test "$GCC" = yes ; then
+        PTHREAD_CFLAGS="-D_REENTRANT -pthreads"
+      fi
+      ;;
+  esac
+  THREAD_SUPPORT=1
+else
+  PTHREAD_CC="$CC"
+  PTHREAD_CFLAGS=""
+  PTHREAD_LIBS=""
+  THREAD_SUPPORT=0
+fi
+AC_SUBST(THREAD_SUPPORT)
+dnl We want to know where these routines live, so on systems with weak
+dnl reference support we can figure out whether or not the pthread library
+dnl has been linked in.
+dnl If we don't add any libraries for thread support, don't bother.
+AC_CHECK_FUNCS(pthread_once pthread_rwlock_init)
+old_CC="$CC"
+test "$PTHREAD_CC" != "" && test "$ac_cv_c_compiler_gnu" = no && CC=$PTHREAD_CC
+old_CFLAGS="$CFLAGS"
+# On Solaris, -pthreads is added to CFLAGS, no extra explicit libraries.
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+AC_SUBST(PTHREAD_CFLAGS)
+old_LIBS="$LIBS"
+LIBS="$PTHREAD_LIBS $LIBS"
+AC_MSG_NOTICE(rechecking with PTHREAD_... options)
+AC_CHECK_LIB(c, pthread_rwlock_init,
+  [AC_DEFINE(HAVE_PTHREAD_RWLOCK_INIT_IN_THREAD_LIB,1,[Define if pthread_rwlock_init is provided in the thread library.])])
+LIBS="$old_LIBS"
+CC="$old_CC"
+CFLAGS="$old_CFLAGS"
+])
+
+dnl This is somewhat gross and should go away when the build system
+dnl is revamped. -- tlyu
+dnl DECLARE_SYS_ERRLIST - check for sys_errlist in libc
+dnl
+AC_DEFUN([DECLARE_SYS_ERRLIST],
+[AC_CACHE_CHECK([for sys_errlist declaration], krb5_cv_decl_sys_errlist,
+[AC_TRY_COMPILE([#include <stdio.h>
+#include <errno.h>], [1+sys_nerr;],
+krb5_cv_decl_sys_errlist=yes, krb5_cv_decl_sys_errlist=no)])
+# assume sys_nerr won't be declared w/o being in libc
+if test $krb5_cv_decl_sys_errlist = yes; then
+  AC_DEFINE(SYS_ERRLIST_DECLARED,1,[Define if sys_errlist is defined in errno.h])
+  AC_DEFINE(HAVE_SYS_ERRLIST,1,[Define if sys_errlist in libc])
+else
+  # This means that sys_errlist is not declared in errno.h, but may still
+  # be in libc.
+  AC_CACHE_CHECK([for sys_errlist in libc], krb5_cv_var_sys_errlist,
+  [AC_TRY_LINK([extern int sys_nerr;], [if (1+sys_nerr < 0) return 1;],
+  krb5_cv_var_sys_errlist=yes, krb5_cv_var_sys_errlist=no;)])
+  if test $krb5_cv_var_sys_errlist = yes; then
+    AC_DEFINE(HAVE_SYS_ERRLIST,1,[Define if sys_errlist in libc])
+    # Do this cruft for backwards compatibility for now.
+    AC_DEFINE(NEED_SYS_ERRLIST,1,[Define if need to declare sys_errlist])
+  else
+    AC_MSG_WARN([sys_errlist is neither in errno.h nor in libc])
+  fi
+fi])
+
+dnl
+dnl check for sigmask/sigprocmask -- CHECK_SIGPROCMASK
+dnl
+AC_DEFUN(CHECK_SIGPROCMASK,[
+AC_MSG_CHECKING([for use of sigprocmask])
+AC_CACHE_VAL(krb5_cv_func_sigprocmask_use,
+[AC_TRY_LINK([#include <signal.h>], [sigprocmask(SIG_SETMASK,0,0);],
+ krb5_cv_func_sigprocmask_use=yes,
+AC_TRY_LINK([#include <signal.h>], [sigmask(1);], 
+ krb5_cv_func_sigprocmask_use=no, krb5_cv_func_sigprocmask_use=yes))])
+AC_MSG_RESULT($krb5_cv_func_sigprocmask_use)
+if test $krb5_cv_func_sigprocmask_use = yes; then
+ AC_DEFINE(USE_SIGPROCMASK,1,[Define if sigprocmask should be used])
+fi
+])dnl
+dnl
+AC_DEFUN(AC_PROG_ARCHIVE, [AC_CHECK_PROG(ARCHIVE, ar, ar cqv, false)])dnl
+AC_DEFUN(AC_PROG_ARCHIVE_ADD, [AC_CHECK_PROG(ARADD, ar, ar cruv, false)])dnl
+dnl
+dnl check for <dirent.h> -- CHECK_DIRENT
+dnl (may need to be more complex later)
+dnl
+AC_DEFUN(CHECK_DIRENT,[
+AC_CHECK_HEADER(dirent.h,AC_DEFINE(USE_DIRENT_H,1,[Define if you have dirent.h functionality]))])dnl
+dnl
+dnl check if union wait is defined, or if WAIT_USES_INT -- CHECK_WAIT_TYPE
+dnl
+AC_DEFUN(CHECK_WAIT_TYPE,[
+AC_MSG_CHECKING([if argument to wait is int *])
+AC_CACHE_VAL(krb5_cv_struct_wait,
+dnl Test for prototype clash - if there is none - then assume int * works
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/wait.h>
+extern pid_t wait(int *);],[], krb5_cv_struct_wait=no,dnl
+dnl Else fallback on old stuff
+[AC_TRY_COMPILE(
+[#include <sys/wait.h>], [union wait i;
+#ifdef WEXITSTATUS
+  WEXITSTATUS (i);
+#endif
+], 
+	krb5_cv_struct_wait=yes, krb5_cv_struct_wait=no)])])
+AC_MSG_RESULT($krb5_cv_struct_wait)
+if test $krb5_cv_struct_wait = no; then
+	AC_DEFINE(WAIT_USES_INT,1,[Define if wait takes int as a argument])
+fi
+])dnl
+dnl
+dnl check for POSIX signal handling -- CHECK_SIGNALS
+dnl
+AC_DEFUN(CHECK_SIGNALS,[
+AC_CHECK_FUNC(sigprocmask,
+AC_MSG_CHECKING(for sigset_t and POSIX_SIGNALS)
+AC_CACHE_VAL(krb5_cv_type_sigset_t,
+[AC_TRY_COMPILE(
+[#include <signal.h>],
+[sigset_t x],
+krb5_cv_type_sigset_t=yes, krb5_cv_type_sigset_t=no)])
+AC_MSG_RESULT($krb5_cv_type_sigset_t)
+if test $krb5_cv_type_sigset_t = yes; then
+  AC_DEFINE(POSIX_SIGNALS,1,[Define if POSIX signal handling is used])
+fi
+)])dnl
+dnl
+dnl check for signal type
+dnl
+dnl AC_RETSIGTYPE isn't quite right, but almost.
+AC_DEFUN(KRB5_SIGTYPE,[
+AC_MSG_CHECKING([POSIX signal handlers])
+AC_CACHE_VAL(krb5_cv_has_posix_signals,
+[AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+extern void (*signal ()) ();], [],
+krb5_cv_has_posix_signals=yes, krb5_cv_has_posix_signals=no)])
+AC_MSG_RESULT($krb5_cv_has_posix_signals)
+if test $krb5_cv_has_posix_signals = yes; then
+   stype=void
+   AC_DEFINE(POSIX_SIGTYPE, 1, [Define if POSIX signal handlers are used])
+else
+  if test $ac_cv_type_signal = void; then
+     stype=void
+  else
+     stype=int
+  fi
+fi
+AC_DEFINE_UNQUOTED(krb5_sigtype, $stype, [Define krb5_sigtype to type of signal handler])dnl
+])dnl
+dnl
+dnl check for POSIX setjmp/longjmp -- CHECK_SETJMP
+dnl
+AC_DEFUN(CHECK_SETJMP,[
+AC_CHECK_FUNC(sigsetjmp,
+AC_MSG_CHECKING(for sigjmp_buf)
+AC_CACHE_VAL(krb5_cv_struct_sigjmp_buf,
+[AC_TRY_COMPILE(
+[#include <setjmp.h>],[sigjmp_buf x],
+krb5_cv_struct_sigjmp_buf=yes,krb5_cv_struct_sigjmp_buf=no)])
+AC_MSG_RESULT($krb5_cv_struct_sigjmp_buf)
+if test $krb5_cv_struct_sigjmp_buf = yes; then
+  AC_DEFINE(POSIX_SETJMP,1,[Define if setjmp indicates POSIX interface])
+fi
+)])dnl
+dnl
+dnl Check for IPv6 compile-time support.
+dnl
+AC_DEFUN(KRB5_AC_INET6,[
+AC_CHECK_HEADERS(sys/types.h sys/socket.h netinet/in.h netdb.h)
+AC_CHECK_FUNCS(inet_ntop inet_pton getnameinfo)
+dnl getaddrinfo test needs netdb.h, for proper compilation on alpha
+dnl under OSF/1^H^H^H^H^HDigital^H^H^H^H^H^H^HTru64 UNIX, where it's
+dnl a macro
+AC_MSG_CHECKING(for getaddrinfo)
+AC_CACHE_VAL(ac_cv_func_getaddrinfo,
+[AC_TRY_LINK([#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif],[
+struct addrinfo *ai;
+getaddrinfo("kerberos.mit.edu", "echo", 0, &ai);
+], ac_cv_func_getaddrinfo=yes, ac_cv_func_getaddrinfo=no)])
+AC_MSG_RESULT($ac_cv_func_getaddrinfo)
+if test $ac_cv_func_getaddrinfo = yes; then
+  AC_DEFINE(HAVE_GETADDRINFO,1,[Define if you have the getaddrinfo function])
+fi
+dnl
+AC_REQUIRE([KRB5_SOCKADDR_SA_LEN])dnl
+AC_ARG_ENABLE([ipv6], , AC_MSG_WARN(enable/disable-ipv6 option is deprecated))dnl
+KRB5_AC_CHECK_INET6
+])dnl
+dnl
+AC_DEFUN(KRB5_AC_CHECK_TYPE_WITH_HEADERS,[
+AC_MSG_CHECKING(for type $1)
+changequote(<<,>>)dnl
+varname=`echo $1 | sed 's,[ -],_,g'`
+changequote([,])dnl
+AC_CACHE_VAL(krb5_cv_$varname,[
+AC_TRY_COMPILE([$2],[ $1 foo; ], eval krb5_cv_$varname=yes, eval krb5_cv_$varname=no)])
+eval x="\$krb5_cv_$varname"
+AC_MSG_RESULT($x)
+if eval test "$x" = yes ; then
+  AC_DEFINE_UNQUOTED(HAVE_`echo $varname | tr '[[[a-z]]]' '[[[A-Z]]]'`)
+fi])
+dnl
+dnl
+AC_DEFUN(KRB5_AC_CHECK_SOCKADDR_STORAGE,[
+KRB5_AC_CHECK_TYPE_WITH_HEADERS(struct sockaddr_storage, [
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+])])dnl
+dnl
+dnl
+AC_DEFUN(KRB5_AC_CHECK_INET6,[
+AC_REQUIRE([KRB5_AC_CHECK_SOCKADDR_STORAGE])dnl
+AC_MSG_CHECKING(for IPv6 compile-time support)
+AC_CACHE_VAL(krb5_cv_inet6,[
+if test "$ac_cv_func_inet_ntop" != "yes" ; then
+  krb5_cv_inet6=no
+else
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+],[
+  struct sockaddr_in6 in;
+  AF_INET6;
+  IN6_IS_ADDR_LINKLOCAL (&in.sin6_addr);
+],krb5_cv_inet6=yes,krb5_cv_inet6=no)])
+fi
+AC_MSG_RESULT($krb5_cv_inet6)
+if test "$krb5_cv_inet6" = no && test "$ac_cv_func_inet_ntop" = yes; then
+AC_MSG_CHECKING(for IPv6 compile-time support with -DINET6)
+AC_CACHE_VAL(krb5_cv_inet6_with_dinet6,[
+old_CC="$CC"
+CC="$CC -DINET6"
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+],[
+  struct sockaddr_in6 in;
+  AF_INET6;
+  IN6_IS_ADDR_LINKLOCAL (&in.sin6_addr);
+],krb5_cv_inet6_with_dinet6=yes,krb5_cv_inet6_with_dinet6=no)
+CC="$old_CC"])
+AC_MSG_RESULT($krb5_cv_inet6_with_dinet6)
+fi
+if test $krb5_cv_inet6 = yes || test "$krb5_cv_inet6_with_dinet6" = yes; then
+  if test "$krb5_cv_inet6_with_dinet6" = yes; then
+    AC_DEFINE(INET6,1,[May need to be defined to enable IPv6 support, for example on IRIX])
+  fi
+  AC_DEFINE(KRB5_USE_INET6,1,[Define if we should compile in IPv6 support (even if we can't use it at run time)])
+fi
+])dnl
+dnl
+dnl Generic File existence tests
+dnl 
+dnl K5_AC_CHECK_FILE(FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl
+AC_DEFUN(K5_AC_CHECK_FILE,
+[AC_REQUIRE([AC_PROG_CC])dnl
+dnl Do the transliteration at runtime so arg 1 can be a shell variable.
+ac_safe=`echo "$1" | sed 'y%./+-%__p_%'`
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(ac_cv_file_$ac_safe,
+[if test "$cross_compiling" = yes; then
+  errprint(__file__:__line__: warning: Cannot check for file existence when cross compiling
+)dnl
+  AC_MSG_ERROR(Cannot check for file existence when cross compiling)
+else
+  if test -r $1; then
+    eval "ac_cv_file_$ac_safe=yes"
+  else
+    eval "ac_cv_file_$ac_safe=no"
+  fi
+fi])dnl
+if eval "test \"`echo '$ac_cv_file_'$ac_safe`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  ifelse([$2], , :, [$2])
+else
+  AC_MSG_RESULT(no)
+ifelse([$3], , , [$3
+np])dnl
+fi
+])
+dnl
+dnl K5_AC_CHECK_FILES(FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl
+AC_DEFUN(K5_AC_CHECK_FILES,
+[AC_REQUIRE([AC_PROG_CC])dnl
+for ac_file in $1
+do
+K5_AC_CHECK_FILE($ac_file,
+[changequote(, )dnl
+  ac_tr_file=HAVE`echo $ac_file | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+changequote([, ])dnl
+  AC_DEFINE_UNQUOTED($ac_tr_file) $2], $3)dnl
+done
+])
+dnl
+dnl set $(KRB4) from --with-krb4=value -- WITH_KRB4
+dnl
+AC_DEFUN(WITH_KRB4,[
+AC_ARG_WITH([krb4],
+[  --without-krb4          don't include Kerberos V4 backwards compatibility
+  --with-krb4             use V4 libraries included with V5 (default)
+  --with-krb4=KRB4DIR     use preinstalled V4 libraries],
+,
+withval=yes
+)dnl
+if test $withval = no; then
+	AC_MSG_NOTICE(no krb4 support)
+	KRB4_LIB=
+	KRB4_DEPLIB=
+	KRB4_INCLUDES=
+	KRB4_LIBPATH=
+	KRB_ERR_H_DEP=
+	krb5_cv_build_krb4_libs=no
+	krb5_cv_krb4_libdir=
+else
+ AC_DEFINE([KRB5_KRB4_COMPAT], 1, [Define this if building with krb4 compat])
+ if test $withval = yes; then
+	AC_MSG_NOTICE(enabling built in krb4 support)
+	KRB4_DEPLIB='$(TOPLIBD)/libkrb4$(DEPLIBEXT)'
+	KRB4_LIB=-lkrb4
+	KRB4_INCLUDES='-I$(SRCTOP)/include/kerberosIV -I$(BUILDTOP)/include/kerberosIV'
+	KRB4_LIBPATH=
+	KRB_ERR_H_DEP='$(BUILDTOP)/include/kerberosIV/krb_err.h'
+	krb5_cv_build_krb4_libs=yes
+	krb5_cv_krb4_libdir=
+ else
+	AC_MSG_NOTICE(using preinstalled krb4 in $withval)
+	KRB4_LIB="-lkrb"
+dnl	DEPKRB4_LIB="$withval/lib/libkrb.a"
+	KRB4_INCLUDES="-I$withval/include"
+	KRB4_LIBPATH="-L$withval/lib"
+	KRB_ERR_H_DEP=
+	krb5_cv_build_krb4_libs=no
+	krb5_cv_krb4_libdir="$withval/lib"
+ fi
+fi
+AC_SUBST(KRB4_INCLUDES)
+AC_SUBST(KRB4_LIBPATH)
+AC_SUBST(KRB4_LIB)
+AC_SUBST(KRB4_DEPLIB)
+AC_SUBST(KRB_ERR_H_DEP)
+dnl We always compile the des425 library
+DES425_DEPLIB='$(TOPLIBD)/libdes425$(DEPLIBEXT)'
+DES425_LIB=-ldes425
+AC_SUBST(DES425_DEPLIB)
+AC_SUBST(DES425_LIB)
+])dnl
+dnl
+dnl
+AC_DEFUN(KRB5_AC_CHECK_FOR_CFLAGS,[
+AC_BEFORE([$0],[AC_PROG_CC])
+krb5_ac_cflags_set=${CFLAGS+set}
+])
+dnl
+AC_DEFUN(WITH_CC,[dnl
+AC_REQUIRE([KRB5_AC_CHECK_FOR_CFLAGS])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+krb5_cv_prog_gcc=$ac_cv_c_compiler_gnu
+if test $ac_cv_c_compiler_gnu = yes ; then
+     HAVE_GCC=yes
+     else HAVE_GCC=
+fi
+AC_SUBST(HAVE_GCC)
+AC_CACHE_CHECK([for GNU linker], krb5_cv_prog_gnu_ld,
+[krb5_cv_prog_gnu_ld=no
+if test "$GCC" = yes; then
+  if AC_TRY_COMMAND([$CC -Wl,-v 2>&1 dnl
+			| grep "GNU ld" > /dev/null]); then
+    krb5_cv_prog_gnu_ld=yes
+  fi
+fi])
+# maybe add -Waggregate-return, or can we assume that actually works by now?
+# -Wno-comment used to be used for SunOS system header <sys/stream.h>
+# -Wno-long-long, if needed, for k5-platform.h without inttypes.h etc.
+extra_gcc_warn_opts="-Wall -Wmissing-prototypes -Wcast-qual \
+ -Wcast-align -Wconversion -Wshadow"
+if test "$GCC" = yes ; then
+  if test "x$krb5_ac_cflags_set" = xset ; then
+    AC_MSG_NOTICE(not adding extra gcc warning flags because CFLAGS was set)
+  else
+    AC_MSG_NOTICE(adding extra warning flags for gcc)
+    CFLAGS="$CFLAGS $extra_gcc_warn_opts"
+    if test "`uname -s`" = Darwin ; then
+      AC_MSG_NOTICE(skipping pedantic warnings on Darwin)
+    elif test "`uname -s`" = Linux ; then
+      AC_MSG_NOTICE(skipping pedantic warnings on Linux)
+    else
+      CFLAGS="$CFLAGS -pedantic"
+    fi
+  fi
+  if test "`uname -s`" = Darwin ; then
+    # Someday this should be a feature test.
+    # One current (Jaguar = OS 10.2) problem:
+    # Archive library with foo.o undef sym X and bar.o common sym X,
+    # if foo.o is pulled in at link time, bar.o may not be, causing
+    # the linker to complain.
+    # Dynamic library problems too?
+    case "$CC $CFLAGS" in
+    *-fcommon*) ;; # why someone would do this, I don't know
+    *-fno-common*) ;; # okay, they're already doing the right thing
+    *)
+      AC_MSG_NOTICE(disabling the use of common storage on Darwin)
+      CFLAGS="$CFLAGS -fno-common"
+      ;;
+    esac
+    case "$LD $LDFLAGS" in
+    *-Wl,-search_paths_first*) ;;
+    *) LDFLAGS="${LDFLAGS} -Wl,-search_paths_first" ;;
+    esac
+  fi
+else
+  if test "`uname -s`" = AIX ; then
+    # Using AIX but not GCC, assume native compiler.
+    # The native compiler appears not to give a nonzero exit
+    # status for certain classes of errors, like missing arguments
+    # in function calls.  Let's try to fix that with -qhalt=e.
+    case "$CC $CFLAGS" in
+      *-qhalt=*) ;;
+      *)
+	CFLAGS="$CFLAGS -qhalt=e"
+	AC_MSG_NOTICE(adding -qhalt=e for better error reporting)
+	;;
+    esac
+    # Also, the optimizer isn't turned on by default, which means
+    # the static inline functions get left in random object files,
+    # leading to references to pthread_mutex_lock from anything that
+    # includes k5-int.h whether it uses threads or not.
+    case "$CC $CFLAGS" in
+      *-O*) ;;
+      *)
+	CFLAGS="$CFLAGS -O"
+	AC_MSG_NOTICE(adding -O for inline thread-support function elimination)
+	;;
+    esac
+  fi
+fi
+])dnl
+dnl
+dnl
+dnl check for yylineno -- HAVE_YYLINENO
+dnl
+AC_DEFUN(HAVE_YYLINENO,[dnl
+AC_REQUIRE_CPP()AC_REQUIRE([AC_PROG_LEX])dnl
+AC_MSG_CHECKING([for yylineno declaration])
+AC_CACHE_VAL(krb5_cv_type_yylineno,
+# some systems have yylineno, others don't...
+  echo '%%
+%%' | ${LEX} -t > conftest.out
+  if egrep yylineno conftest.out >/dev/null 2>&1; then
+	krb5_cv_type_yylineno=yes
+  else
+	krb5_cv_type_yylineno=no
+  fi
+  rm -f conftest.out)
+  AC_MSG_RESULT($krb5_cv_type_yylineno)
+  if test $krb5_cv_type_yylineno = no; then
+	AC_DEFINE(NO_YYLINENO, 1, [Define if lex produes code with yylineno])
+  fi
+])dnl
+dnl
+dnl K5_GEN_MAKEFILE([dir, [frags]])
+dnl
+AC_DEFUN(K5_GEN_MAKEFILE,[dnl
+ifelse($1, ,[_K5_GEN_MAKEFILE(.,$2)],[_K5_GEN_MAKEFILE($1,$2)])
+])
+dnl
+dnl _K5_GEN_MAKEFILE(dir, [frags])
+dnl  dir must be present in this case
+dnl  Note: Be careful in quoting. 
+dnl        The ac_foreach generates the list of fragments to include
+dnl        or "" if $2 is empty
+AC_DEFUN(_K5_GEN_MAKEFILE,[dnl
+AC_CONFIG_FILES([$1/Makefile:$srcdir/]K5_TOPDIR[/config/pre.in:$1/Makefile.in:$srcdir/]K5_TOPDIR[/config/post.in])
+])
+dnl
+dnl K5_GEN_FILE( <ac_output arguments> )
+dnl
+AC_DEFUN(K5_GEN_FILE,[AC_CONFIG_FILES($1)])dnl
+dnl
+dnl K5_AC_OUTPUT
+dnl    Note: Adds the variables to config.status for individual 
+dnl          Makefile generation from config.status
+AC_DEFUN(K5_AC_OUTPUT,[AC_OUTPUT])dnl
+dnl
+dnl V5_AC_OUTPUT_MAKEFILE
+dnl
+AC_DEFUN(V5_AC_OUTPUT_MAKEFILE,
+[ifelse($1, , [_V5_AC_OUTPUT_MAKEFILE(.,$2)],[_V5_AC_OUTPUT_MAKEFILE($1,$2)])])
+dnl
+define(_V5_AC_OUTPUT_MAKEFILE,
+[ifelse($2, , ,AC_CONFIG_FILES($2))
+AC_FOREACH([DIR], [$1],dnl
+ [AC_CONFIG_FILES(DIR[/Makefile:$srcdir/]K5_TOPDIR[/config/pre.in:]DIR[/Makefile.in:$srcdir/]K5_TOPDIR[/config/post.in])])
+K5_AC_OUTPUT])dnl
+dnl
+dnl
+dnl KRB5_SOCKADDR_SA_LEN: define HAVE_SA_LEN if sockaddr contains the sa_len
+dnl component
+dnl
+AC_DEFUN([KRB5_SOCKADDR_SA_LEN],[ dnl
+AC_CHECK_MEMBER(struct sockaddr.sa_len,
+  AC_DEFINE(HAVE_SA_LEN,1,[Define if struct sockaddr contains sa_len])
+,,[#include <sys/types.h>
+#include <sys/socket.h>])])
+dnl
+dnl
+dnl CHECK_UTMP: check utmp structure and functions
+dnl
+AC_DEFUN(CHECK_UTMP,[
+AC_CHECK_MEMBERS([struct utmp.ut_pid, struct utmp.ut_type, struct utmp.ut_host, struct utmp.ut_exit],,,
+[#include <sys/types.h>
+#include <utmp.h>])
+
+# Define the names actually used in the krb5 code currently:
+if test $ac_cv_member_struct_utmp_ut_pid = no; then
+  AC_DEFINE(NO_UT_PID,1,[Define if ut_pid field not found])
+fi
+if test $ac_cv_member_struct_utmp_ut_type = no; then
+  AC_DEFINE(NO_UT_TYPE,1,[Define if ut_type field not found])
+fi
+if test $ac_cv_member_struct_utmp_ut_host = no; then
+  AC_DEFINE(NO_UT_HOST,1,[Define if ut_host field not found])
+fi
+if test $ac_cv_member_struct_utmp_ut_exit = no; then
+  AC_DEFINE(NO_UT_EXIT,1,[Define if ut_exit field not found])
+fi
+
+AC_CHECK_FUNCS(setutent setutxent updwtmp updwtmpx)
+])dnl
+dnl
+dnl WITH_NETLIB
+dnl 
+dnl
+AC_DEFUN(WITH_NETLIB,[
+AC_ARG_WITH([netlib],
+AC_HELP_STRING([--with-netlib=LIBS], use user defined resolver library),
+[  if test "$withval" = yes -o "$withval" = no ; then
+	AC_MSG_RESULT("netlib will link with C library resolver only")
+  else
+	LIBS="$LIBS $withval"
+	AC_MSG_RESULT("netlib will use \'$withval\'")
+  fi
+],dnl
+[AC_LIBRARY_NET]
+)])dnl
+dnl
+dnl
+AC_DEFUN(KRB5_AC_NEED_DAEMON, [
+KRB5_NEED_PROTO([#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif],daemon,1)])dnl
+dnl
+dnl Check if stdarg or varargs is available *and compiles*; prefer stdarg.
+dnl (This was sent to djm for incorporation into autoconf 3/12/1996.  KR)
+dnl
+AC_DEFUN(AC_HEADER_STDARG, [
+
+AC_MSG_CHECKING([for stdarg.h])
+AC_CACHE_VAL(ac_cv_header_stdarg_h,
+[AC_TRY_COMPILE([#include <stdarg.h>], [
+  } /* ac_try_compile will have started a function body */
+  int aoeu (char *format, ...) {
+    va_list v;
+    int i;
+    va_start (v, format);
+    i = va_arg (v, int);
+    va_end (v);
+],ac_cv_header_stdarg_h=yes,ac_cv_header_stdarg_h=no)])dnl
+AC_MSG_RESULT($ac_cv_header_stdarg_h)
+if test $ac_cv_header_stdarg_h = yes; then
+  AC_DEFINE(HAVE_STDARG_H, 1, [Define if stdarg available and compiles])
+else
+
+AC_MSG_CHECKING([for varargs.h])
+AC_CACHE_VAL(ac_cv_header_varargs_h,
+[AC_TRY_COMPILE([#include <varargs.h>],[
+  } /* ac_try_compile will have started a function body */
+  int aoeu (va_alist) va_dcl {
+    va_list v;
+    int i;
+    va_start (v);
+    i = va_arg (v, int);
+    va_end (v);
+],ac_cv_header_varargs_h=yes,ac_cv_header_varargs_h=no)])dnl
+AC_MSG_RESULT($ac_cv_header_varargs_h)
+if test $ac_cv_header_varargs_h = yes; then
+  AC_DEFINE(HAVE_VARARGS_H, 1, [Define if varargs available and compiles])
+else
+  AC_MSG_ERROR(Neither stdarg nor varargs compile?)
+fi
+
+fi dnl stdarg test failure
+
+])dnl
+
+dnl
+dnl KRB5_AC_NEED_LIBGEN --- check if libgen needs to be linked in for
+dnl 				compile/step	
+dnl
+dnl
+AC_DEFUN(KRB5_AC_NEED_LIBGEN,[
+AC_REQUIRE([AC_PROG_CC])dnl
+dnl
+dnl regcomp is present but non-functional on Solaris 2.4
+dnl
+AC_MSG_CHECKING(for working regcomp)
+AC_CACHE_VAL(ac_cv_func_regcomp,[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <regex.h>
+regex_t x; regmatch_t m;
+int main() { return regcomp(&x,"pat.*",0) || regexec(&x,"pattern",1,&m,0); }
+], ac_cv_func_regcomp=yes, ac_cv_func_regcomp=no, AC_MSG_ERROR([Cannot test regcomp when cross compiling]))])
+AC_MSG_RESULT($ac_cv_func_regcomp)
+test $ac_cv_func_regcomp = yes && AC_DEFINE(HAVE_REGCOMP,1,[Define if regcomp exists and functions])
+dnl
+dnl Check for the compile and step functions - only if regcomp is not available
+dnl
+if test $ac_cv_func_regcomp = no; then
+ save_LIBS="$LIBS"
+ LIBS=-lgen
+dnl this will fail if there's no compile/step in -lgen, or if there's
+dnl no -lgen.  This is fine.
+ AC_CHECK_FUNCS(compile step)
+ LIBS="$save_LIBS"
+dnl
+dnl Set GEN_LIB if necessary 
+dnl
+ AC_CHECK_LIB(gen, compile, GEN_LIB=-lgen, GEN_LIB=)
+ AC_SUBST(GEN_LIB)
+fi
+])
+dnl
+dnl KRB5_AC_REGEX_FUNCS --- check for different regular expression 
+dnl				support functions
+dnl
+AC_DEFUN(KRB5_AC_REGEX_FUNCS,[
+AC_CHECK_FUNCS(re_comp re_exec regexec)
+AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl
+])dnl
+dnl
+dnl AC_KRB5_TCL_FIND_CONFIG (uses tcl_dir)
+dnl
+AC_DEFUN(AC_KRB5_TCL_FIND_CONFIG,[
+AC_REQUIRE([KRB5_LIB_AUX])dnl
+AC_MSG_CHECKING(for tclConfig.sh)
+dnl On Debian, we might be given --with-tcl=/usr, or tclsh might
+dnl point us to /usr/lib/tcl8.4; either way, we need to find
+dnl /usr/lib/tcl8.4/tclConfig.sh.
+dnl On NetBSD, we might be given --with-tcl=/usr/pkg, or tclsh
+dnl might point us to /usr/pkg/lib/tcl8.4; we need to find
+dnl /usr/pkg/lib/tclConfig.sh.
+if test -r "$tcl_dir/lib/tclConfig.sh" ; then
+  tcl_conf="$tcl_dir/lib/tclConfig.sh"
+elif test -r "$tcl_dir/tclConfig.sh" ; then
+  tcl_conf="$tcl_dir/tclConfig.sh"
+elif test -r "$tcl_dir/../tclConfig.sh" ; then
+  tcl_conf="$tcl_dir/../tclConfig.sh"
+else
+  tcl_conf=
+  lib="$tcl_dir/lib"
+  changequote(<<,>>)dnl
+  for d in "$lib" "$lib"/tcl7.[0-9] "$lib"/tcl8.[0-9] ; do
+    if test -r "$d/tclConfig.sh" ; then
+      tcl_conf="$tcl_conf $d/tclConfig.sh"
+    fi
+  done
+  changequote([,])dnl
+fi
+if test -n "$tcl_conf" ; then
+  AC_MSG_RESULT($tcl_conf)
+else
+  AC_MSG_RESULT(not found)
+fi
+tcl_ok_conf=
+tcl_vers_maj=
+tcl_vers_min=
+old_CPPFLAGS=$CPPFLAGS
+old_LIBS=$LIBS
+old_LDFLAGS=$LDFLAGS
+if test -n "$tcl_conf" ; then
+  for file in $tcl_conf ; do
+    TCL_MAJOR_VERSION=x ; TCL_MINOR_VERSION=x
+    AC_MSG_CHECKING(Tcl info in $file)
+    . $file
+    v=$TCL_MAJOR_VERSION.$TCL_MINOR_VERSION
+    if test -z "$tcl_vers_maj" \
+	|| test "$tcl_vers_maj" -lt "$TCL_MAJOR_VERSION" \
+	|| test "$tcl_vers_maj" = "$TCL_MAJOR_VERSION" -a "$tcl_vers_min" -lt "$TCL_MINOR_VERSION" ; then
+      for incdir in "$TCL_PREFIX/include/tcl$v" "$TCL_PREFIX/include" ; do
+	if test -r "$incdir/tcl.h" -o -r "$incdir/tcl/tcl.h" ; then
+	  CPPFLAGS="$old_CPPFLAGS -I$incdir"
+	  break
+	fi
+      done
+      LIBS="$old_LIBS `eval echo x $TCL_LIB_SPEC $TCL_LIBS | sed 's/^x//'`"
+      LDFLAGS="$old_LDFLAGS $TCL_LD_FLAGS"
+      AC_TRY_LINK( , [Tcl_CreateInterp ();],
+	tcl_ok_conf=$file
+	tcl_vers_maj=$TCL_MAJOR_VERSION
+	tcl_vers_min=$TCL_MINOR_VERSION
+	AC_MSG_RESULT($v - working),
+	AC_MSG_RESULT($v - compilation failed)
+      )
+    else
+      AC_MSG_RESULT(older version $v)
+    fi
+  done
+fi
+CPPFLAGS=$old_CPPFLAGS
+LIBS=$old_LIBS
+LDFLAGS=$old_LDFLAGS
+tcl_header=no
+tcl_lib=no
+if test -n "$tcl_ok_conf" ; then
+  . $tcl_ok_conf
+  TCL_INCLUDES=
+  for incdir in "$TCL_PREFIX/include/tcl$v" "$TCL_PREFIX/include" ; do
+    if test -r "$incdir/tcl.h" -o -r "$incdir/tcl/tcl.h" ; then
+      if test "$incdir" != "/usr/include" ; then
+        TCL_INCLUDES=-I$incdir
+      fi
+      break
+    fi
+  done
+  # Need eval because the first-level expansion could reference
+  # variables like ${TCL_DBGX}.
+  eval TCL_LIBS='"'$TCL_LIB_SPEC $TCL_LIBS $TCL_DL_LIBS'"'
+  TCL_LIBPATH="-L$TCL_EXEC_PREFIX/lib"
+  TCL_RPATH=":$TCL_EXEC_PREFIX/lib"
+  if test "$DEPLIBEXT" != "$SHLIBEXT" && test -n "$RPATH_FLAG"; then
+    TCL_MAYBE_RPATH='$(RPATH_FLAG)'"$TCL_EXEC_PREFIX/lib$RPATH_TAIL"
+  else
+    TCL_MAYBE_RPATH=
+  fi
+  CPPFLAGS="$old_CPPFLAGS $TCL_INCLUDES"
+  AC_CHECK_HEADER(tcl.h,AC_DEFINE(HAVE_TCL_H,1,[Define if tcl.h is available]) tcl_header=yes)
+  if test $tcl_header=no; then
+     AC_CHECK_HEADER(tcl/tcl.h,AC_DEFINE(HAVE_TCL_TCL_H,1,[Define if tcl/tcl.h is available]) tcl_header=yes)
+  fi
+  CPPFLAGS="$old_CPPFLAGS"
+  tcl_lib=yes
+else
+  # If we read a tclConfig.sh file, it probably set this.
+  TCL_LIBS=
+fi  
+AC_SUBST(TCL_INCLUDES)
+AC_SUBST(TCL_LIBS)
+AC_SUBST(TCL_LIBPATH)
+AC_SUBST(TCL_RPATH)
+AC_SUBST(TCL_MAYBE_RPATH)
+])dnl
+dnl
+dnl AC_KRB5_TCL_TRYOLD
+dnl attempt to use old search algorithm for locating tcl
+dnl
+AC_DEFUN(AC_KRB5_TCL_TRYOLD, [
+AC_REQUIRE([KRB5_AC_FIND_DLOPEN])
+AC_MSG_WARN([trying old tcl search code])
+if test "$with_tcl" != yes -a "$with_tcl" != no; then
+	TCL_INCLUDES=-I$with_tcl/include
+	TCL_LIBPATH=-L$with_tcl/lib
+	TCL_RPATH=:$with_tcl/lib
+fi
+if test "$with_tcl" != no ; then
+	krb5_save_CPPFLAGS="$CPPFLAGS"
+	krb5_save_LDFLAGS="$LDFLAGS"
+	CPPFLAGS="$CPPFLAGS $TCL_INCLUDES"
+	LDFLAGS="$LDFLAGS $TCL_LIBPATH"
+	tcl_header=no
+	AC_CHECK_HEADER(tcl.h,AC_DEFINE(HAVE_TCL_H,1,[Define if tcl.h found]) tcl_header=yes)
+	if test $tcl_header=no; then
+	   AC_CHECK_HEADER(tcl/tcl.h,AC_DEFINE(HAVE_TCL_TCL_H,1,[Define if tcl/tcl.h found]) tcl_header=yes)
+	fi
+
+	if test $tcl_header = yes ; then
+		tcl_lib=no
+
+		if test $tcl_lib = no; then
+			AC_CHECK_LIB(tcl8.0, Tcl_CreateCommand, 
+				TCL_LIBS="$TCL_LIBS -ltcl8.0 -lm $DL_LIB $LIBS"
+				tcl_lib=yes,,-lm $DL_LIB)
+		fi
+		if test $tcl_lib = no; then
+			AC_CHECK_LIB(tcl7.6, Tcl_CreateCommand, 
+				TCL_LIBS="$TCL_LIBS -ltcl7.6 -lm $DL_LIB $LIBS"
+				tcl_lib=yes,,-lm $DL_LIB)
+		fi
+		if test $tcl_lib = no; then
+			AC_CHECK_LIB(tcl7.5, Tcl_CreateCommand, 
+				TCL_LIBS="$TCL_LIBS -ltcl7.5 -lm $DL_LIB $LIBS"
+				tcl_lib=yes,,-lm $DL_LIB)
+
+		fi
+		if test $tcl_lib = no ; then
+			AC_CHECK_LIB(tcl, Tcl_CreateCommand, 
+				TCL_LIBS="$TCL_LIBS -ltcl -lm $DL_LIB $LIBS"
+				tcl_lib=yes,,-lm $DL_LIB)
+
+		fi
+		if test $tcl_lib = no ; then		
+			AC_MSG_WARN("tcl.h found but not library")
+		fi
+	else
+		AC_MSG_WARN(Could not find Tcl which is needed for the kadm5 tests)
+		TCL_LIBS=
+	fi
+	CPPFLAGS="$krb5_save_CPPFLAGS"
+	LDFLAGS="$krb5_save_LDFLAGS"
+	AC_SUBST(TCL_INCLUDES)
+	AC_SUBST(TCL_LIBS)
+	AC_SUBST(TCL_LIBPATH)
+	AC_SUBST(TCL_RPATH)
+else
+	AC_MSG_RESULT("Not looking for Tcl library")
+fi
+])dnl
+dnl
+dnl AC_KRB5_TCL - determine if the TCL library is present on system
+dnl
+AC_DEFUN(AC_KRB5_TCL,[
+TCL_INCLUDES=
+TCL_LIBPATH=
+TCL_RPATH=
+TCL_LIBS=
+TCL_WITH=
+tcl_dir=
+AC_ARG_WITH(tcl,
+[  --with-tcl=path         where Tcl resides], , with_tcl=try)
+if test "$with_tcl" = no ; then
+  true
+elif test "$with_tcl" = yes -o "$with_tcl" = try ; then
+  tcl_dir=/usr
+  if test ! -r /usr/lib/tclConfig.sh; then
+    cat >> conftest <<\EOF
+puts "tcl_dir=$tcl_library"
+EOF
+    if tclsh conftest >conftest.out 2>/dev/null; then
+      if grep tcl_dir= conftest.out >/dev/null 2>&1; then
+        t=`sed s/tcl_dir=// conftest.out`
+        tcl_dir=$t
+      fi
+    fi # tclsh ran script okay
+  rm -f conftest conftest.out
+  fi # no /usr/lib/tclConfig.sh
+else
+  tcl_dir=$with_tcl
+fi
+if test "$with_tcl" != no ; then
+  AC_KRB5_TCL_FIND_CONFIG
+  if test $tcl_lib = no ; then
+    if test "$with_tcl" != try ; then
+      AC_KRB5_TCL_TRYOLD
+    else
+      AC_MSG_WARN(Could not find Tcl which is needed for some tests)
+    fi
+  fi
+fi
+# If "yes" or pathname, error out if not found.
+if test "$with_tcl" != no -a "$with_tcl" != try ; then
+  if test "$tcl_header $tcl_lib" != "yes yes" ; then
+    AC_MSG_ERROR(Could not find Tcl)
+  fi
+fi
+])dnl
+
+dnl
+dnl WITH_HESIOD
+dnl
+AC_DEFUN(WITH_HESIOD,
+[AC_ARG_WITH(hesiod, AC_HELP_STRING(--with-hesiod[=path], compile with hesiod support @<:@omitted@:>@),
+	hesiod=$with_hesiod, with_hesiod=no)
+if test "$with_hesiod" != "no"; then
+	HESIOD_DEFS=-DHESIOD
+	AC_CHECK_LIB(resolv, res_send, res_lib=-lresolv)
+	if test "$hesiod" != "yes"; then
+		HESIOD_LIBS="-L${hesiod}/lib -lhesiod $res_lib"
+	else
+		HESIOD_LIBS="-lhesiod $res_lib"
+	fi
+else
+	HESIOD_DEFS=
+	HESIOD_LIBS=
+fi
+AC_SUBST(HESIOD_DEFS)
+AC_SUBST(HESIOD_LIBS)])
+
+
+dnl
+dnl KRB5_BUILD_LIBRARY
+dnl
+dnl Pull in the necessary stuff to create the libraries.
+
+AC_DEFUN(KRB5_BUILD_LIBRARY,
+[KRB5_BUILD_LIBRARY_WITH_DEPS
+# null out SHLIB_EXPFLAGS because we lack any dependencies
+SHLIB_EXPFLAGS=])
+
+dnl
+dnl KRB5_BUILD_LIBRARY_STATIC
+dnl
+dnl Force static library build.
+
+AC_DEFUN(KRB5_AC_FORCE_STATIC,[dnl
+AC_BEFORE([$0],[KRB5_LIB_AUX])dnl
+krb5_force_static=yes])
+AC_DEFUN(KRB5_BUILD_LIBRARY_STATIC,
+dnl Use define rather than AC_DEFUN to avoid ordering problems.
+[AC_REQUIRE([KRB5_AC_FORCE_STATIC])dnl
+KRB5_BUILD_LIBRARY
+# If we're only building static libraries, they're for build-time use only,
+# so don't install.
+LIBINSTLIST=])
+
+dnl
+dnl KRB5_BUILD_LIBRARY_WITH_DEPS
+dnl
+dnl Like KRB5_BUILD_LIBRARY, but adds in explicit dependencies in the
+dnl generated shared library.
+
+AC_DEFUN(KRB5_BUILD_LIBRARY_WITH_DEPS,
+[AC_REQUIRE([KRB5_LIB_AUX])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_PROG_RANLIB])dnl
+AC_REQUIRE([AC_PROG_ARCHIVE])dnl
+AC_REQUIRE([AC_PROG_ARCHIVE_ADD])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+AC_CHECK_PROG(AR, ar, ar, false)
+AC_CHECK_PROG(PERL, perl, perl, false)
+if test "$ac_cv_prog_PERL" = "false"; then
+  AC_MSG_ERROR(Perl is now required for Kerberos builds.)
+fi
+AC_SUBST(LIBLIST)
+AC_SUBST(LIBLINKS)
+AC_SUBST(MAKE_SHLIB_COMMAND)
+AC_SUBST(SHLIB_EXPFLAGS)
+AC_SUBST(SHLIB_EXPORT_FILE_DEP)
+AC_SUBST(DYNOBJ_EXPDEPS)
+AC_SUBST(DYNOBJ_EXPFLAGS)
+AC_SUBST(INSTALL_SHLIB)
+AC_SUBST(STLIBEXT)
+AC_SUBST(SHLIBEXT)
+AC_SUBST(SHLIBVEXT)
+AC_SUBST(SHLIBSEXT)
+AC_SUBST(DEPLIBEXT)
+AC_SUBST(PFLIBEXT)
+AC_SUBST(LIBINSTLIST)
+AC_SUBST(DYNOBJEXT)
+AC_SUBST(MAKE_DYNOBJ_COMMAND)
+])
+
+dnl
+dnl KRB5_BUILD_LIBOBJS
+dnl
+dnl Pull in the necessary stuff to build library objects.
+
+AC_DEFUN(KRB5_BUILD_LIBOBJS,
+[AC_REQUIRE([KRB5_LIB_AUX])dnl
+AC_SUBST(OBJLISTS)
+AC_SUBST(STOBJEXT)
+AC_SUBST(SHOBJEXT)
+AC_SUBST(PFOBJEXT)
+AC_SUBST(PICFLAGS)
+AC_SUBST(PROFFLAGS)])
+
+dnl
+dnl KRB5_BUILD_PROGRAM
+dnl
+dnl Set variables to build a program.
+
+AC_DEFUN(KRB5_BUILD_PROGRAM,
+[AC_REQUIRE([KRB5_LIB_AUX])dnl
+AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl
+AC_SUBST(CC_LINK)
+AC_SUBST(RPATH_FLAG)
+AC_SUBST(DEPLIBEXT)])
+
+dnl
+dnl KRB5_RUN_FLAGS
+dnl
+dnl Set up environment for running dynamic executables out of build tree
+
+AC_DEFUN(KRB5_RUN_FLAGS,
+[AC_REQUIRE([KRB5_LIB_AUX])dnl
+KRB5_RUN_ENV="$RUN_ENV"
+AC_SUBST(KRB5_RUN_ENV)])
+
+dnl
+dnl KRB5_LIB_AUX
+dnl
+dnl Parse configure options related to library building.
+
+AC_DEFUN(KRB5_LIB_AUX,
+[AC_REQUIRE([KRB5_LIB_PARAMS])dnl
+
+# Check whether to build static libraries.
+dnl AC_HELP_STRING([--enable-static],[build static libraries @<:@disabled for most platforms@:>@])
+dnl AC_HELP_STRING([--disable-static],[don't build static libraries])
+AC_ARG_ENABLE([static],, ,
+[enable_static=$default_static])
+
+if test "$enable_static" = yes; then
+  AC_MSG_ERROR([Sorry, static libraries do not work in this release.])
+fi
+
+if test "$enable_static" = no && test "$krb5_force_static" != yes; then
+	AC_MSG_NOTICE([disabling static libraries])
+	LIBLINKS=
+	LIBLIST=
+	OBJLISTS=
+else
+	LIBLIST='lib$(LIBBASE)$(STLIBEXT)'
+	LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT)'
+	OBJLISTS=OBJS.ST
+	LIBINSTLIST=install-static
+	DEPLIBEXT=$STLIBEXT
+#	CFLAGS="$CFLAGS -D_KDB5_STATIC_LINK"
+fi
+
+# Check whether to build shared libraries.
+AC_ARG_ENABLE([shared],
+dnl AC_HELP_STRING([--enable-shared],[build shared libraries @<:@enabled for most platforms@:>@])
+dnl AC_HELP_STRING([--disable-shared],[don't build shared libraries])
+, ,
+[enable_shared=$default_shared])
+
+if test "$enable_shared" != yes; then
+  AC_MSG_ERROR([Sorry, this release builds only shared libraries, cannot disable them.])
+fi
+
+if test "$enable_shared" = yes; then
+	case "$SHLIBEXT" in
+	.so-nobuild)
+		AC_MSG_WARN([shared libraries not supported on this architecture])
+		RUN_ENV=
+		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
+			SHLIBVEXT=.so.v-nobuild
+			SHLIBSEXT=.so.s-nobuild
+		else
+			AC_MSG_NOTICE([enabling shared libraries])
+			# Clear some stuff in case of AIX, etc.
+			if test "$STLIBEXT" = "$SHLIBEXT" ; then
+				STLIBEXT=.a-nobuild
+				LIBLIST=
+				LIBLINKS=
+				OBJLISTS=
+				LIBINSTLIST=
+			fi
+			LIBLIST="$LIBLIST "'lib$(LIBBASE)$(SHLIBEXT)'
+			LIBLINKS="$LIBLINKS "'$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)'
+			case "$SHLIBSEXT" in
+			.so.s-nobuild)
+				LIBINSTLIST="$LIBINSTLIST install-shared"
+				;;
+			*)
+				LIBLIST="$LIBLIST "'lib$(LIBBASE)$(SHLIBSEXT)'
+				LIBLINKS="$LIBLINKS "'$(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)'
+				LIBINSTLIST="$LIBINSTLIST install-shlib-soname"
+				;;
+			esac
+			OBJLISTS="$OBJLISTS OBJS.SH"
+		fi
+		CC_LINK="$CC_LINK_SHARED"
+		;;
+	esac
+else
+	RUN_ENV=
+	CC_LINK="$CC_LINK_STATIC"
+	SHLIBEXT=.so-nobuild
+	SHLIBVEXT=.so.v-nobuild
+	SHLIBSEXT=.so.s-nobuild
+fi
+
+if test "$build_dynobj" = yes; then
+	OBJLISTS=`echo $OBJLISTS | sed -e s/OBJS.ST//g -e s/OBJS.SH//g`
+	OBJLISTS="$OBJLISTS OBJS.SH"
+fi
+
+if test -z "$LIBLIST"; then
+	AC_MSG_ERROR([must enable one of shared or static libraries])
+fi
+
+# Check whether to build profiled libraries.
+AC_ARG_ENABLE([profiled],
+dnl [  --enable-profiled       build profiled libraries @<:@disabled@:>@]
+,
+[if test "$enableval" = yes; then
+  AC_MSG_ERROR([Sorry, profiled libraries do not work in this release.])
+fi
+if false; then
+	case $PFLIBEXT in
+	.po-nobuild)
+		AC_MSG_WARN([Profiled libraries not supported on this architecture.])
+		;;
+	*)
+		AC_MSG_NOTICE([enabling profiled libraries])
+		LIBLIST="$LIBLIST "'lib$(LIBBASE)$(PFLIBEXT)'
+		LIBLINKS="$LIBLINKS "'$(TOPLIBD)/lib$(LIBBASE)$(PFLIBEXT)'
+		OBJLISTS="$OBJLISTS OBJS.PF"
+		LIBINSTLIST="$LIBINSTLIST install-profiled"
+		;;
+	esac
+fi])])
+
+dnl
+dnl KRB5_LIB_PARAMS
+dnl
+dnl Determine parameters related to libraries, e.g. various extensions.
+
+AC_DEFUN(KRB5_LIB_PARAMS,
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+krb5_cv_host=$host
+AC_SUBST(krb5_cv_host)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([V5_SET_TOPDIR])dnl
+. $ac_topdir/config/shlib.conf])
+dnl
+dnl The following was written by jhawk@mit.edu
+dnl
+dnl AC_LIBRARY_NET: Id: net.m4,v 1.4 1997/10/25 20:49:53 jhawk Exp 
+dnl
+dnl This test is for network applications that need socket() and
+dnl gethostbyname() -ish functions.  Under Solaris, those applications need to
+dnl link with "-lsocket -lnsl".  Under IRIX, they should *not* link with
+dnl "-lsocket" because libsocket.a breaks a number of things (for instance:
+dnl gethostbyname() under IRIX 5.2, and snoop sockets under most versions of
+dnl IRIX).
+dnl 
+dnl Unfortunately, many application developers are not aware of this, and
+dnl mistakenly write tests that cause -lsocket to be used under IRIX.  It is
+dnl also easy to write tests that cause -lnsl to be used under operating
+dnl systems where neither are necessary (or useful), such as SunOS 4.1.4, which
+dnl uses -lnsl for TLI.
+dnl 
+dnl This test exists so that every application developer does not test this in
+dnl a different, and subtly broken fashion.
+dnl 
+dnl It has been argued that this test should be broken up into two seperate
+dnl tests, one for the resolver libraries, and one for the libraries necessary
+dnl for using Sockets API. Unfortunately, the two are carefully intertwined and
+dnl allowing the autoconf user to use them independantly potentially results in
+dnl unfortunate ordering dependancies -- as such, such component macros would
+dnl have to carefully use indirection and be aware if the other components were
+dnl executed. Since other autoconf macros do not go to this trouble, and almost
+dnl no applications use sockets without the resolver, this complexity has not
+dnl been implemented.
+dnl
+dnl The check for libresolv is in case you are attempting to link statically
+dnl and happen to have a libresolv.a lying around (and no libnsl.a).
+dnl
+AC_DEFUN(AC_LIBRARY_NET, [
+   # Most operating systems have gethostbyname() in the default searched
+   # libraries (i.e. libc):
+   AC_CHECK_FUNC(gethostbyname, , [
+     # Some OSes (eg. Solaris) place it in libnsl:
+     AC_CHECK_LIB(nsl, gethostbyname, , [
+       # Some strange OSes (SINIX) have it in libsocket:
+       AC_CHECK_LIB(socket, gethostbyname, , [
+          # Unfortunately libsocket sometimes depends on libnsl.
+          # AC_CHECK_LIB's API is essentially broken so the following
+          # ugliness is necessary:
+          AC_CHECK_LIB(socket, gethostbyname,
+             LIBS="-lsocket -lnsl $LIBS",
+               [AC_CHECK_LIB(resolv, gethostbyname,
+			     LIBS="-lresolv $LIBS" )],
+             -lnsl)
+       ])
+     ])
+   ])
+  AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, ,
+    AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl)))
+  KRB5_AC_ENABLE_DNS
+  if test "$enable_dns" = yes ; then
+    # We assume that if libresolv exists we can link against it.
+    # This may get us a gethostby* that doesn't respect nsswitch.
+    AC_CHECK_LIB(resolv, main)
+
+_KRB5_AC_CHECK_RES_FUNCS(res_ninit res_nclose res_ndestroy res_nsearch dnl
+ns_initparse ns_name_uncompress dn_skipname res_search)
+    if test $krb5_cv_func_res_nsearch = no \
+      && test $krb5_cv_func_res_search = no; then
+	# Attempt to link with res_search(), in case it's not prototyped.
+	AC_CHECK_FUNC(res_search,
+	  [AC_DEFINE(HAVE_RES_SEARCH, 1,
+	    [Define to 1 if you have the `res_search' function])],
+	  [AC_ERROR([cannot find res_nsearch or res_search])])
+    fi
+  fi
+])
+AC_DEFUN([_KRB5_AC_CHECK_RES_FUNCS],
+[AC_FOREACH([AC_Func], [$1],
+  [AH_TEMPLATE(AS_TR_CPP(HAVE_[]AC_Func),
+               [Define to 1 if you have the `]AC_Func[' function.])])dnl
+for krb5_func in $1; do
+_KRB5_AC_CHECK_RES_FUNC($krb5_func)
+done
+])
+AC_DEFUN([_KRB5_AC_CHECK_RES_FUNC], [
+# Solaris 9 prototypes ns_name_uncompress() in arpa/nameser.h, but
+# doesn't export it from libresolv.so, so we use extreme paranoia here
+# and check both for the declaration and that we can link against the
+# function.
+AC_CACHE_CHECK([for $1], [krb5_cv_func_$1], [AC_TRY_LINK(
+[#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+@%:@include <resolv.h>],
+[/*
+ * Use volatile, or else optimization can cause false positives.
+ */
+void (* volatile p)() = (void (*)())$1;],
+			     [AS_VAR_SET(krb5_cv_func_$1, yes)],
+			     [AS_VAR_SET(krb5_cv_func_$1, no)])])
+AS_IF([test AS_VAR_GET(krb5_cv_func_$1) = yes],
+      [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]), 1,
+			  [Define to 1 if you have the `$1' function])])[]dnl
+])
+dnl
+dnl
+dnl KRB5_AC_ENABLE_DNS
+dnl
+AC_DEFUN(KRB5_AC_ENABLE_DNS, [
+enable_dns=yes
+enable_dns_for_kdc=yes
+AC_DEFINE(KRB5_DNS_LOOKUP_KDC,1,[Define to enable DNS lookups of Kerberos KDCs])
+
+  AC_ARG_ENABLE([dns-for-realm],
+[  --enable-dns-for-realm  enable DNS lookups of Kerberos realm names], ,
+[enable_dns_for_realm=no])
+  if test "$enable_dns_for_realm" = yes; then
+    AC_DEFINE(KRB5_DNS_LOOKUP_REALM,1,[Define to enable DNS lookups of Kerberos realm names])
+  fi
+
+AC_DEFINE(KRB5_DNS_LOOKUP, 1,[Define for DNS support of locating realms and KDCs])
+
+])
+dnl
+dnl
+dnl Check if we need the prototype for a function - we give it a bogus 
+dnl prototype and if it complains - then a valid prototype exists on the 
+dnl system.
+dnl
+dnl KRB5_NEED_PROTO(includes, function, [bypass])
+dnl if $3 set, don't see if library defined. 
+dnl Useful for case where we will define in libkrb5 the function if need be
+dnl but want to know if a prototype exists in either case on system.
+dnl
+AC_DEFUN([KRB5_NEED_PROTO], [
+ifelse([$3], ,[if test "x$ac_cv_func_$2" = xyes; then])
+AC_CACHE_CHECK([if $2 needs a prototype provided], krb5_cv_func_$2_noproto,
+AC_TRY_COMPILE([$1],
+[struct k5foo {int foo; } xx;
+extern int $2 (struct k5foo*);
+$2(&xx);
+],
+krb5_cv_func_$2_noproto=yes,krb5_cv_func_$2_noproto=no))
+if test $krb5_cv_func_$2_noproto = yes; then
+	AC_DEFINE([NEED_]translit($2, [a-z], [A-Z])[_PROTO], 1, dnl
+[define if the system header files are missing prototype for $2()])
+fi
+ifelse([$3], ,[fi])
+])
+dnl
+dnl =============================================================
+dnl Internal function for testing for getpeername prototype
+dnl
+AC_DEFUN([KRB5_GETPEERNAME_ARGS],[
+AC_DEFINE([GETPEERNAME_ARG2_TYPE],GETSOCKNAME_ARG2_TYPE,[Type of getpeername second argument.])
+AC_DEFINE([GETPEERNAME_ARG3_TYPE],GETSOCKNAME_ARG3_TYPE,[Type of getpeername second argument.])
+])
+dnl
+dnl =============================================================
+dnl Internal function for testing for getsockname arguments
+dnl
+AC_DEFUN([TRY_GETSOCK_INT],[
+krb5_lib_var=`echo "$1 $2" | sed 'y% ./+-*%___p_p%'`
+AC_MSG_CHECKING([if getsockname() takes arguments $1 and $2])
+AC_CACHE_VAL(krb5_cv_getsockname_proto_$krb5_lib_var,
+[
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+extern int getsockname(int, $1, $2);
+],,eval "krb5_cv_getsockname_proto_$krb5_lib_var=yes",
+    eval "krb5_cv_getsockname_proto_$krb5_lib_var=no")])
+if eval "test \"`echo '$krb5_cv_getsockname_proto_'$krb5_lib_var`\" = yes"; then
+	AC_MSG_RESULT(yes)
+	sock_set=yes; res1="$1"; res2="$2"
+else
+	AC_MSG_RESULT(no)
+fi
+])
+dnl
+dnl Determines the types of the second and third arguments to getsockname().
+dnl
+AC_DEFUN([KRB5_GETSOCKNAME_ARGS],[
+sock_set=no
+for sock_arg1 in "struct sockaddr *" "void *"
+do
+  for sock_arg2 in "size_t *" "int *" "socklen_t *"
+  do
+	if test $sock_set = no; then
+	  TRY_GETSOCK_INT($sock_arg1, $sock_arg2)
+	fi
+  done 
+done
+if test "$sock_set" = no; then
+  AC_MSG_NOTICE(assuming struct sockaddr and socklen_t for getsockname args)
+  res1="struct sockaddr *"
+  res2="socklen_t *"
+fi
+res1=`echo "$res1" | tr -d '*' | sed -e 's/ *$//'`
+res2=`echo "$res2" | tr -d '*' | sed -e 's/ *$//'`
+AC_DEFINE_UNQUOTED([GETSOCKNAME_ARG2_TYPE],$res1,[Type of pointer target for argument 2 to getsockname])
+AC_DEFINE_UNQUOTED([GETSOCKNAME_ARG3_TYPE],$res2,[Type of pointer target for argument 3 to getsockname])
+])
+dnl
+dnl
+AC_DEFUN([KRB5_AC_CHOOSE_ET],[
+AC_ARG_WITH([system-et],
+AC_HELP_STRING(--with-system-et,use system compile_et and -lcom_err @<:@default: build and install a local version@:>@))
+AC_MSG_CHECKING(which version of com_err to use)
+if test "x$with_system_et" = xyes ; then
+  COM_ERR_VERSION=sys
+  AC_MSG_RESULT(system)
+else
+  COM_ERR_VERSION=k5
+  AC_MSG_RESULT(krb5)
+fi
+if test $COM_ERR_VERSION = sys; then
+  # check for various functions we need
+  AC_CHECK_LIB(com_err, add_error_table, :, AC_MSG_ERROR(cannot find add_error_table in com_err library))
+  AC_CHECK_LIB(com_err, remove_error_table, :, AC_MSG_ERROR(cannot find remove_error_table in com_err library))
+  # make sure compile_et provides "et_foo" name
+  cat >> conf$$e.et <<EOF
+error_table foo
+error_code ERR_FOO, "foo"
+end
+EOF
+  AC_CHECK_PROGS(compile_et,compile_et,false)
+  if test "$compile_et" = false; then
+    AC_MSG_ERROR(cannot find compile_et)
+  fi
+  AC_CACHE_CHECK(whether compile_et is useful,krb5_cv_compile_et_useful,[
+  if compile_et conf$$e.et >/dev/null 2>&1 ; then true ; else
+    AC_MSG_ERROR(execution failed)
+  fi
+  AC_TRY_COMPILE([#include "conf$$e.h"
+      		 ],[ &et_foo_error_table; ],:,
+		 [AC_MSG_ERROR(cannot use et_foo_error_table)])
+  # Anything else we need to test for?
+  rm -f conf$$e.et conf$$e.c conf$$e.h
+  krb5_cv_compile_et_useful=yes
+  ])
+fi
+AC_SUBST(COM_ERR_VERSION)
+])
+AC_DEFUN([KRB5_AC_CHOOSE_SS],[
+AC_ARG_WITH(system-ss,
+	    AC_HELP_STRING(--with-system-ss,use system -lss and mk_cmds @<:@private version@:>@))
+AC_ARG_VAR(SS_LIB,[system libraries for 'ss' package [-lss]])
+AC_MSG_CHECKING(which version of subsystem package to use)
+if test "x$with_system_ss" = xyes ; then
+  SS_VERSION=sys
+  AC_MSG_RESULT(system)
+  # todo: check for various libraries we might need
+  # in the meantime...
+  test "x${SS_LIB+set}" = xset || SS_LIB=-lss
+  old_LIBS="$LIBS"
+  LIBS="$LIBS $SS_LIB"
+  AC_CACHE_CHECK(whether system ss package works, krb5_cv_system_ss_okay,[
+  AC_TRY_RUN([
+#include <ss/ss.h>
+int main(int argc, char *argv[]) {
+  if (argc == 42) {
+    int i, err;
+    i = ss_create_invocation("foo","foo","",0,&err);
+    ss_listen(i);
+  }
+  return 0;
+}], krb5_cv_system_ss_okay=yes, AC_MSG_ERROR(cannot run test program),
+  krb5_cv_system_ss_okay="assumed")])
+  LIBS="$old_LIBS"
+else
+  SS_VERSION=k5
+  AC_MSG_RESULT(krb5)
+fi
+AC_SUBST(SS_LIB)
+AC_SUBST(SS_VERSION)
+])
+dnl
+AC_DEFUN([KRB5_AC_CHOOSE_DB],[
+AC_ARG_WITH(system-db,
+	    AC_HELP_STRING(--with-system-db,use system Berkeley db @<:@private version@:>@))
+AC_ARG_VAR(DB_HEADER,[header file for system Berkeley db package [db.h]])
+AC_ARG_VAR(DB_LIB,[library for system Berkeley db package [-ldb]])
+if test "x$with_system_db" = xyes ; then
+  DB_VERSION=sys
+  # TODO: Do we have specific routines we should check for?
+  # How about known, easily recognizable bugs?
+  # We want to use bt_rseq in some cases, but no other version but
+  # ours has it right now.
+  #
+  # Okay, check the variables.
+  test "x${DB_HEADER+set}" = xset || DB_HEADER=db.h
+  test "x${DB_LIB+set}" = xset || DB_LIB=-ldb
+  #
+  if test "x${DB_HEADER}" = xdb.h ; then
+    DB_HEADER_VERSION=sys
+  else
+    DB_HEADER_VERSION=redirect
+  fi
+  KDB5_DB_LIB="$DB_LIB"
+else
+  DB_VERSION=k5
+  AC_DEFINE(HAVE_BT_RSEQ,1,[Define if bt_rseq is available, for recursive btree traversal.])
+  DB_HEADER=db.h
+  DB_HEADER_VERSION=k5
+  # libdb gets sucked into libkdb
+  KDB5_DB_LIB=
+  # needed for a couple of things that need libdb for its own sake
+  DB_LIB=-ldb
+fi
+AC_SUBST(DB_VERSION)
+AC_SUBST(DB_HEADER)
+AC_SUBST(DB_HEADER_VERSION)
+AC_SUBST(DB_LIB)
+AC_SUBST(KDB5_DB_LIB)
+])
+dnl
+dnl KRB5_AC_PRIOCNTL_HACK
+dnl
+dnl
+AC_DEFUN([KRB5_AC_PRIOCNTL_HACK],
+[AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_LANG_COMPILER_REQUIRE])dnl
+AC_CACHE_CHECK([whether to use priocntl hack], [krb5_cv_priocntl_hack],
+[case $krb5_cv_host in
+*-*-solaris2.9*)
+	if test "$cross_compiling" = yes; then
+		krb5_cv_priocntl_hack=yes
+	else
+		# Solaris patch 117171-11 (sparc) or 117172-11 (x86)
+		# fixes the Solaris 9 bug where final pty output
+		# gets lost on close.
+		if showrev -p | $AWK 'BEGIN { e = 1 }
+/Patch: 11717[[12]]/ { x = index[]([$]2, "-");
+if (substr[]([$]2, x + 1, length([$]2) - x) >= 11)
+{ e = 0 } else { e = 1 } }
+END { exit e; }'; then
+			krb5_cv_priocntl_hack=no
+		else
+			krb5_cv_priocntl_hack=yes
+		fi
+	fi
+	;;
+*)
+	krb5_cv_priocntl_hack=no
+	;;
+esac])
+if test "$krb5_cv_priocntl_hack" = yes; then
+	PRIOCNTL_HACK=1
+else
+	PRIOCNTL_HACK=0
+fi
+AC_SUBST(PRIOCNTL_HACK)])
+dnl
+dnl
+dnl KRB5_AC_GCC_ATTRS
+AC_DEFUN([KRB5_AC_GCC_ATTRS],
+[AC_CACHE_CHECK([for constructor/destructor attribute support],krb5_cv_attr_constructor_destructor,
+[rm -f conftest.1 conftest.2
+if test -r conftest.1 || test -r conftest.2 ; then
+  AC_MSG_ERROR(write error in local file system?)
+fi
+true > conftest.1
+true > conftest.2
+if test -r conftest.1 && test -r conftest.2 ; then true ; else
+  AC_MSG_ERROR(write error in local file system?)
+fi
+a=no
+b=no
+# blindly assume we have 'unlink'...
+AC_TRY_RUN([void foo1() __attribute__((constructor));
+void foo1() { unlink("conftest.1"); }
+void foo2() __attribute__((destructor));
+void foo2() { unlink("conftest.2"); }
+int main () { return 0; }],
+[test -r conftest.1 || a=yes
+test -r conftest.2 || b=yes], , AC_MSG_ERROR(Cannot test for constructor/destructor support when cross compiling))
+case $krb5_cv_host in
+*-*-aix4.*)
+	# Under AIX 4.3.3, at least, shared library destructor functions
+	# appear to get executed in reverse link order (right to left),
+	# so that a library's destructor function may run after that of
+	# libraries it depends on, and may still have to access in the
+	# destructor.
+	#
+	# That counts as "not working", for me, but it's a much more
+	# complicated test case to set up.
+	b=no
+	;;
+esac
+krb5_cv_attr_constructor_destructor="$a,$b"
+])
+# Okay, krb5_cv_... should be set now.
+case $krb5_cv_attr_constructor_destructor in
+  yes,*)
+    AC_DEFINE(CONSTRUCTOR_ATTR_WORKS,1,[Define if __attribute__((constructor)) works]) ;;
+esac
+case $krb5_cv_attr_constructor_destructor in
+  *,yes)
+    AC_DEFINE(DESTRUCTOR_ATTR_WORKS,1,[Define if __attribute__((destructor)) works]) ;;
+esac
+dnl End of attributes we care about right now.
+])
+dnl
+dnl
+dnl KRB5_AC_PRAGMA_WEAK_REF
+AC_DEFUN([KRB5_AC_PRAGMA_WEAK_REF],
+[AC_CACHE_CHECK([whether pragma weak references are supported],
+krb5_cv_pragma_weak_ref,
+[AC_TRY_LINK([#pragma weak flurbl
+extern int flurbl(void);],[if (&flurbl != 0) return flurbl();],
+krb5_cv_pragma_weak_ref=yes,krb5_cv_pragma_weak_ref=no)])
+if test $krb5_cv_pragma_weak_ref = yes ; then
+  AC_DEFINE(HAVE_PRAGMA_WEAK_REF,1,[Define if #pragma weak references work])
+fi])
+dnl
+dnl
+m4_include(config/ac-archive/acx_pthread.m4)
+#
+# KRB5_AC_LIBUTIL
+#
+# Check for libutil, for NetBSD, et al.; needed for openpty() and
+# logwtmp() on some platforms.
+#
+AC_DEFUN([KRB5_AC_LIBUTIL],
+	[AC_CHECK_LIB(util, main,
+		[AC_DEFINE(HAVE_LIBUTIL,1,[Define if util library is available with openpty, logwtmp, etc])
+  UTIL_LIB=-lutil])dnl
+AC_SUBST(UTIL_LIB)
+])
+dnl
+dnl
+dnl
+dnl --with-ldap=value
+dnl
+AC_DEFUN(WITH_LDAP,[
+AC_ARG_WITH([ldap],
+[  --with-ldap             compile OpenLDAP database backend module],
+[case "$withval" in
+    OPENLDAP) with_ldap=yes ;;
+    yes | no) ;;
+    EDIRECTORY) AC_MSG_ERROR(Option --with-ldap=EDIRECTORY is deprecated; use --with-edirectory instead.) ;;
+    *)  AC_MSG_ERROR(Invalid option value --with-ldap="$withval") ;;
+esac], with_ldap=no)dnl
+AC_ARG_WITH([edirectory],
+[  --with-edirectory       compile eDirectory database backend module],
+[case "$withval" in
+    yes | no) ;;
+    *)  AC_MSG_ERROR(Invalid option value --with-edirectory="$withval") ;;
+esac], with_edirectory=no)dnl
+
+if test $with_ldap = yes; then
+  if test $with_edirectory = yes; then
+    AC_MSG_ERROR(Cannot enable both OpenLDAP and eDirectory backends; choose one.)
+  fi
+  AC_MSG_NOTICE(enabling OpenLDAP database backend module support)
+  OPENLDAP_PLUGIN=yes
+elif test $with_edirectory = yes; then
+  AC_MSG_NOTICE(enabling eDirectory database backend module support)
+  OPENLDAP_PLUGIN=yes
+  AC_DEFINE(HAVE_EDIRECTORY,1,[Define if LDAP KDB interface should assume eDirectory.])
+else
+  : # neither enabled
+dnl  AC_MSG_NOTICE(disabling ldap backend module support)
+fi
+AC_SUBST(OPENLDAP_PLUGIN)
+])dnl
+dnl
+dnl If libkeyutils exists (on Linux) include it and use keyring ccache
+AC_DEFUN(KRB5_AC_KEYRING_CCACHE,[
+  AC_CHECK_HEADERS([keyutils.h],
+    AC_CHECK_LIB(keyutils, add_key, 
+      [dnl Pre-reqs were found
+       AC_DEFINE(USE_KEYRING_CCACHE, 1, [Define if the keyring ccache should be enabled])
+       LIBS="-lkeyutils $LIBS"
+      ]))
+])dnl
+dnl
diff --git a/krb5-1-6/src/appl/Makefile.in b/krb5-1-6/src/appl/Makefile.in
new file mode 100644
index 000000000..2a7d80aea
--- /dev/null
+++ b/krb5-1-6/src/appl/Makefile.in
@@ -0,0 +1,7 @@
+thisconfigdir=.
+myfulldir=appl
+mydir=.
+BUILDTOP=$(REL)..
+
+LOCAL_SUBDIRS= sample simple user_user gss-sample
+
diff --git a/krb5-1-6/src/appl/bsd/Makefile.in b/krb5-1-6/src/appl/bsd/Makefile.in
new file mode 100644
index 000000000..7e59d8237
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/Makefile.in
@@ -0,0 +1,182 @@
+thisconfigdir=.
+myfulldir=appl/bsd
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+LOCALINCLUDES=@KRB4_INCLUDES@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SETENVSRC=@SETENVSRC@
+SETENVOBJ=@SETENVOBJ@
+
+LOGINLIBS=@LOGINLIBS@
+LIBOBJS=@LIBOBJS@
+V4RCP=@V4RCP@
+V4RCPO=@V4RCPO@
+KRSHDLIBS=@KRSHDLIBS@
+
+SRCS= $(srcdir)/krcp.c $(srcdir)/krlogin.c $(srcdir)/krsh.c $(srcdir)/kcmd.c \
+	$(srcdir)/forward.c $(srcdir)/compat_recv.c \
+	$(srcdir)/login.c $(srcdir)/krshd.c $(srcdir)/krlogind.c \
+	$(srcdir)/v4rcp.c
+OBJS= krcp.o krlogin.o krsh.o kcmd.o forward.o compat_recv.o $(SETENVOBJ) \
+	login.o krshd.o krlogind.o $(V4RCPO) $(LIBOBJS)
+
+UCB_RLOGIN = @UCB_RLOGIN@
+UCB_RSH = @UCB_RSH@
+UCB_RCP = @UCB_RCP@
+
+RSH=	-DKRB5_PATH_RLOGIN=\"$(CLIENT_BINDIR)/rlogin\"
+BSD=	-DUCB_RLOGIN=\"$(UCB_RLOGIN)\" \
+	-DUCB_RSH=\"$(UCB_RSH)\" -DUCB_RCP=\"$(UCB_RCP)\"
+
+DEFINES = $(RSH) $(BSD) $(RPROGS) -DKERBEROS \
+	-DLOGIN_PROGRAM=\"$(SERVER_BINDIR)/login.krb5\" -DKPROGDIR=\"$(CLIENT_BINDIR)\" \
+	-DHEIMDAL_FRIENDLY
+
+all:: rsh rcp rlogin kshd klogind login.krb5 $(V4RCP)
+
+clean:: 
+	$(RM) rsh rcp rlogin kshd klogind login.krb5 v4rcp
+
+rsh: krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o rsh krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_LIBS)
+
+rcp: krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o rcp krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_LIBS)
+
+v4rcp: v4rcp.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o v4rcp v4rcp.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_LIBS)
+
+rlogin: krlogin.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o rlogin krlogin.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_LIBS)
+
+install::
+	for f in rsh rcp rlogin; do \
+	 ($(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'` && \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		${DESTDIR}$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1 \
+	  ) || exit 1; \
+	done
+	f=$(V4RCP); \
+	if test -n "$$f" ; then	$(INSTALL_SETUID) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	$(INSTALL_DATA) $(srcdir)/$$f.M \
+		${DESTDIR}$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	fi
+
+kshd: krshd.o kcmd.o forward.o compat_recv.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB4COMPAT_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o kshd krshd.o kcmd.o forward.o compat_recv.o $(SETENVOBJ) $(LIBOBJS) $(KRSHDLIBS) $(PTY_LIB) $(UTIL_LIB) $(KRB4COMPAT_LIBS) $(APPUTILS_LIB)
+
+klogind: krlogind.o kcmd.o forward.o compat_recv.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB4COMPAT_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o klogind krlogind.o  kcmd.o forward.o compat_recv.o $(SETENVOBJ) $(LIBOBJS) $(PTY_LIB) $(UTIL_LIB) $(KRB4COMPAT_LIBS) $(APPUTILS_LIB)
+
+install::
+	for f in kshd klogind; do \
+	 ($(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(SERVER_BINDIR)/`echo $$f|sed '$(transform)'` && \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		${DESTDIR}$(SERVER_MANDIR)/`echo $$f|sed '$(transform)'`.8 \
+	 ) || exit 1 ; \
+	done
+
+# No program name transformation is done with login.krb5 since it is directly
+# referenced by klogind.
+#
+login.krb5: login.o  $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o login.krb5 login.o $(SETENVOBJ) $(LIBOBJS) $(LOGINLIBS) $(PTY_LIB) $(KRB4COMPAT_LIBS)
+
+install::
+	$(INSTALL_PROGRAM) login.krb5 $(DESTDIR)$(SERVER_BINDIR)/login.krb5
+	$(INSTALL_DATA) $(srcdir)/login.M \
+		${DESTDIR}$(SERVER_MANDIR)/login.krb5.8
+
+getdtablesize.o: $(srcdir)/getdtablesize.c
+
+kcmd.o krcp.o krlogin.o krlogind.o krsh.o krshd.o forward.o: defines.h
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)krcp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/k5-util.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h defines.h krcp.c
+$(OUTPRE)krlogin.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  defines.h krlogin.c rpaths.h
+$(OUTPRE)krsh.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  defines.h krsh.c
+$(OUTPRE)kcmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  defines.h kcmd.c
+$(OUTPRE)forward.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h defines.h forward.c
+$(OUTPRE)compat_recv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h compat_recv.c defines.h
+$(OUTPRE)login.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/libpty.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  login.c loginpaths.h
+$(OUTPRE)krshd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/libpty.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h defines.h krshd.c loginpaths.h
+$(OUTPRE)krlogind.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/libpty.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h defines.h krlogind.c
+$(OUTPRE)v4rcp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/krbports.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/port-sockets.h \
+  rpaths.h v4rcp.c
diff --git a/krb5-1-6/src/appl/bsd/compat_recv.c b/krb5-1-6/src/appl/bsd/compat_recv.c
new file mode 100644
index 000000000..c76c4142c
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/compat_recv.c
@@ -0,0 +1,581 @@
+/*
+ * lib/krb5/krb/compat_recv.c
+ *
+ * Copyright 1993 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * convenience sendauth/recvauth functions, with compatibility with V4
+ * recvauth.
+ *
+ * NOTE: linking in this function will pull in V4 kerberos routines.
+ *
+ * WARNING: In the V4-style arguments, the ticket and kdata arguments
+ * have different types than the V4 recvauth; in V4, they were KTEXT
+ * and AUTH_DAT *, respectively.  Here, they are KTEXT * and AUTH_DAT **
+ * and they are allocated by recvauth if and only if we end up talking
+ * to a V4 sendauth.
+ */
+
+#include "k5-int.h"
+#if !defined(_MACINTOSH)
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+#include "com_err.h"
+#include <errno.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "defines.h"
+
+#ifdef KRB5_KRB4_COMPAT
+static int krb_v4_recvauth(long options, int fd, KTEXT ticket,
+			   char *service, char *instance, 
+			   struct sockaddr_in *faddr,
+			   struct sockaddr_in *laddr,
+			   AUTH_DAT *kdata,
+			   char *filename,
+			   Key_schedule schedule,
+			   char *version);
+#endif
+
+#define	KRB_V4_SENDAUTH_VERS	"AUTHV0.1" /* MUST be 8 chars long */
+#define KRB_V5_SENDAUTH_VERS	"KRB5_SENDAUTH_V1.0"
+
+#define KRB5_RECVAUTH_V4	4
+#define KRB5_RECVAUTH_V5	5
+
+#ifdef KRB5_KRB4_COMPAT
+krb5_error_code
+krb5_compat_recvauth(context, auth_context,
+	             /* IN */
+		     fdp, appl_version, server, flags, keytab,
+		     v4_options, v4_service, v4_instance, v4_faddr, v4_laddr,
+		     v4_filename, 
+		     /* OUT */
+		     ticket,
+		     auth_sys, v4_kdata, v4_schedule, v4_version)
+    krb5_context context;
+    krb5_auth_context  *auth_context;
+	krb5_pointer	fdp;
+	char	*appl_version;
+	krb5_principal	server;
+	krb5_int32	flags;
+	krb5_keytab    	keytab;
+	krb5_ticket  ** ticket;
+        krb5_int32      *auth_sys;
+
+	/*
+	 * Version 4 arguments
+	 */
+	krb5_int32 v4_options;	 /* bit-pattern of options */
+	char *v4_service;	 /* service expected */
+	char *v4_instance;	 /* inst expected (may be filled in) */
+	struct sockaddr_in *v4_faddr; /* foreign address */
+	struct sockaddr_in *v4_laddr; /* local address */
+	AUTH_DAT **v4_kdata;	 /* kerberos data (returned) */
+	char *v4_filename;	 /* name of file with service keys */
+	Key_schedule v4_schedule; /* key schedule (return) */
+	char *v4_version;		 /* version string (filled in) */
+{
+	union verslen {
+		krb5_int32	len;
+		char		vers[4];
+	} vers;
+	char	*buf;
+	int	len, length;
+	krb5_int32	retval;
+	int		fd = *( (int *) fdp);
+#ifdef KRB5_KRB4_COMPAT
+	KTEXT		v4_ticket;	 /* storage for client's ticket */
+#endif
+		
+	if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+		return((retval < 0) ? errno : ECONNABORTED);
+
+#ifdef KRB5_KRB4_COMPAT
+	if (!strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) {
+		/*
+		 * We must be talking to a V4 sendauth; read in the
+		 * rest of the version string and make sure.
+		 */
+		if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+			return((retval < 0) ? errno : ECONNABORTED);
+		
+		if (strncmp(vers.vers, KRB_V4_SENDAUTH_VERS+4, 4))
+			return KRB5_SENDAUTH_BADAUTHVERS;
+
+		*auth_sys = KRB5_RECVAUTH_V4;
+
+		*v4_kdata = (AUTH_DAT *) malloc( sizeof(AUTH_DAT) );
+		v4_ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
+
+		retval = krb_v4_recvauth(v4_options, fd, v4_ticket,
+					 v4_service, v4_instance, v4_faddr,
+					 v4_laddr, *v4_kdata, v4_filename,
+					 v4_schedule, v4_version);
+		krb5_xfree(v4_ticket);
+		/*
+		 * XXX error code translation?
+		 */
+		switch (retval) {
+		case RD_AP_OK:
+		    return 0;
+		case RD_AP_TIME:
+		    return KRB5KRB_AP_ERR_SKEW;
+		case RD_AP_EXP:
+		    return KRB5KRB_AP_ERR_TKT_EXPIRED;
+		case RD_AP_NYV:
+		    return KRB5KRB_AP_ERR_TKT_NYV;
+		case RD_AP_NOT_US:
+		    return KRB5KRB_AP_ERR_NOT_US;
+		case RD_AP_UNDEC:
+		    return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+		case RD_AP_REPEAT:
+		    return KRB5KRB_AP_ERR_REPEAT;
+		case RD_AP_MSG_TYPE:
+		    return KRB5KRB_AP_ERR_MSG_TYPE;
+		case RD_AP_MODIFIED:
+		    return KRB5KRB_AP_ERR_MODIFIED;
+		case RD_AP_ORDER:
+		    return KRB5KRB_AP_ERR_BADORDER;
+		case RD_AP_BADD:
+		    return KRB5KRB_AP_ERR_BADADDR;
+		default:
+		    return KRB5_SENDAUTH_BADRESPONSE;
+		}
+	}
+#endif
+
+	/*
+	 * Assume that we're talking to a V5 recvauth; read in the
+	 * the version string, and make sure it matches.
+	 */
+	
+	len = (int) ntohl(vers.len);
+
+	if (len < 0 || len > 255)
+		return KRB5_SENDAUTH_BADAUTHVERS;
+
+	buf = malloc((unsigned) len);
+	if (!buf)
+		return ENOMEM;
+	
+	length = krb5_net_read(context, fd, buf, len);
+	if (len != length) {
+		krb5_xfree(buf);
+		if (len < 0)
+			return errno;
+		else
+			return ECONNABORTED;
+	}
+
+	if (strcmp(buf, KRB_V5_SENDAUTH_VERS)) {
+		krb5_xfree(buf);
+		return KRB5_SENDAUTH_BADAUTHVERS;
+	}
+	krb5_xfree(buf);
+
+	*auth_sys = KRB5_RECVAUTH_V5;
+	
+	retval = krb5_recvauth(context, auth_context, fdp, appl_version, server,
+			       flags | KRB5_RECVAUTH_SKIP_VERSION, 
+			       keytab, ticket);
+
+	return retval;
+}
+
+krb5_error_code
+krb5_compat_recvauth_version(context, auth_context,
+			     /* IN */
+			     fdp, server, flags, keytab,
+			     v4_options, v4_service, v4_instance, v4_faddr,
+			     v4_laddr,
+			     v4_filename, 
+			     /* OUT */
+			     ticket,
+			     auth_sys, v4_kdata, v4_schedule,
+			     version)
+    krb5_context context;
+    krb5_auth_context  *auth_context;
+	krb5_pointer	fdp;
+	krb5_principal	server;
+	krb5_int32	flags;
+	krb5_keytab    	keytab;
+	krb5_ticket  ** ticket;
+        krb5_int32      *auth_sys;
+
+	/*
+	 * Version 4 arguments
+	 */
+	krb5_int32 v4_options;	 /* bit-pattern of options */
+	char *v4_service;	 /* service expected */
+	char *v4_instance;	 /* inst expected (may be filled in) */
+	struct sockaddr_in *v4_faddr; /* foreign address */
+	struct sockaddr_in *v4_laddr; /* local address */
+	AUTH_DAT **v4_kdata;	 /* kerberos data (returned) */
+	char *v4_filename;	 /* name of file with service keys */
+	Key_schedule v4_schedule; /* key schedule (return) */
+    krb5_data *version;		/* application version filled in */
+{
+	union verslen {
+		krb5_int32	len;
+		char		vers[4];
+	} vers;
+	char	*buf;
+	int	len, length;
+	krb5_int32	retval;
+	int		fd = *( (int *) fdp);
+#ifdef KRB5_KRB4_COMPAT
+	KTEXT		v4_ticket;	 /* storage for client's ticket */
+#endif
+		
+	if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+		return((retval < 0) ? errno : ECONNABORTED);
+
+#ifdef KRB5_KRB4_COMPAT
+	if (v4_faddr->sin_family == AF_INET
+	    && !strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) {
+		/*
+		 * We must be talking to a V4 sendauth; read in the
+		 * rest of the version string and make sure.
+		 */
+		if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+			return((retval < 0) ? errno : ECONNABORTED);
+		
+		if (strncmp(vers.vers, KRB_V4_SENDAUTH_VERS+4, 4))
+			return KRB5_SENDAUTH_BADAUTHVERS;
+
+		*auth_sys = KRB5_RECVAUTH_V4;
+
+		*v4_kdata = (AUTH_DAT *) malloc( sizeof(AUTH_DAT) );
+		v4_ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
+
+		version->length = KRB_SENDAUTH_VLEN; /* no trailing \0! */
+		version->data = malloc (KRB_SENDAUTH_VLEN + 1);
+		version->data[KRB_SENDAUTH_VLEN] = 0;
+		if (version->data == 0)
+		    return errno;
+		retval = krb_v4_recvauth(v4_options, fd, v4_ticket,
+					 v4_service, v4_instance, v4_faddr,
+					 v4_laddr, *v4_kdata, v4_filename,
+					 v4_schedule, version->data);
+		krb5_xfree(v4_ticket);
+		/*
+		 * XXX error code translation?
+		 */
+		switch (retval) {
+		case RD_AP_OK:
+		    return 0;
+		case RD_AP_TIME:
+		    return KRB5KRB_AP_ERR_SKEW;
+		case RD_AP_EXP:
+		    return KRB5KRB_AP_ERR_TKT_EXPIRED;
+		case RD_AP_NYV:
+		    return KRB5KRB_AP_ERR_TKT_NYV;
+		case RD_AP_NOT_US:
+		    return KRB5KRB_AP_ERR_NOT_US;
+		case RD_AP_UNDEC:
+		    return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+		case RD_AP_REPEAT:
+		    return KRB5KRB_AP_ERR_REPEAT;
+		case RD_AP_MSG_TYPE:
+		    return KRB5KRB_AP_ERR_MSG_TYPE;
+		case RD_AP_MODIFIED:
+		    return KRB5KRB_AP_ERR_MODIFIED;
+		case RD_AP_ORDER:
+		    return KRB5KRB_AP_ERR_BADORDER;
+		case RD_AP_BADD:
+		    return KRB5KRB_AP_ERR_BADADDR;
+		default:
+		    return KRB5_SENDAUTH_BADRESPONSE;
+		}
+	}
+#endif
+
+	/*
+	 * Assume that we're talking to a V5 recvauth; read in the
+	 * the version string, and make sure it matches.
+	 */
+	
+	len = (int) ntohl(vers.len);
+
+	if (len < 0 || len > 255)
+		return KRB5_SENDAUTH_BADAUTHVERS;
+
+	buf = malloc((unsigned) len);
+	if (!buf)
+		return ENOMEM;
+	
+	length = krb5_net_read(context, fd, buf, len);
+	if (len != length) {
+		krb5_xfree(buf);
+		if (len < 0)
+			return errno;
+		else
+			return ECONNABORTED;
+	}
+
+	if (strcmp(buf, KRB_V5_SENDAUTH_VERS)) {
+		krb5_xfree(buf);
+		return KRB5_SENDAUTH_BADAUTHVERS;
+	}
+	krb5_xfree(buf);
+
+	*auth_sys = KRB5_RECVAUTH_V5;
+	
+	retval = krb5_recvauth_version(context, auth_context, fdp, server,
+				       flags | KRB5_RECVAUTH_SKIP_VERSION, 
+				       keytab, ticket, version);
+
+	return retval;
+}
+#endif /* KRB5_KRB4_COMPAT */
+
+
+#ifndef max
+#define	max(a,b) (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+#ifdef KRB5_KRB4_COMPAT	
+static int
+krb_v4_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
+		filename, schedule, version)
+long options;			 /* bit-pattern of options */
+int fd;				 /* file descr. to read from */
+KTEXT ticket;			 /* storage for client's ticket */
+char *service;			 /* service expected */
+char *instance;			 /* inst expected (may be filled in) */
+struct sockaddr_in *faddr;	 /* address of foreign host on fd */
+struct sockaddr_in *laddr;	 /* local address */
+AUTH_DAT *kdata;		 /* kerberos data (returned) */
+char *filename;			 /* name of file with service keys */
+Key_schedule schedule;		 /* key schedule (return) */
+char *version;			 /* version string (filled in) */
+{
+    int cc, old_vers = 0;
+    int rem;
+    krb5_int32 tkt_len, priv_len;
+    krb5_ui_4 cksum;
+    u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
+
+    /* read the application version string */
+    if ((krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
+	 KRB_SENDAUTH_VLEN))
+	return(errno);
+    version[KRB_SENDAUTH_VLEN] = '\0';
+
+    /* get the length of the ticket */
+    if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
+	sizeof(tkt_len))
+	return(errno);
+    
+    /* sanity check */
+    ticket->length = ntohl((unsigned long)tkt_len);
+    if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
+	if (options & KOPT_DO_MUTUAL) {
+	    rem = KFAILURE;
+	    goto mutual_fail;
+	} else
+	    return(KFAILURE); /* XXX there may still be junk on the fd? */
+    }		
+
+    /* read the ticket */
+    if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
+	!= ticket->length)
+	return(errno);
+
+    /*
+     * now have the ticket.  decrypt it to get the authenticated
+     * data.
+     */
+    rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
+		     kdata,filename);
+
+    if (old_vers) return(rem);	 /* XXX can't do mutual with old client */
+
+    /* if we are doing mutual auth, compose a response */
+    if (options & KOPT_DO_MUTUAL) {
+	if (rem != KSUCCESS)
+	    /* the krb_rd_req failed */
+	    goto mutual_fail;
+
+	/* add one to the (formerly) sealed checksum, and re-seal it
+	   for return to the client */
+	cksum = kdata->checksum + 1;
+	cksum = htonl(cksum);
+#ifndef NOENCRYPTION
+	key_sched(kdata->session,schedule);
+#endif /* !NOENCRYPTION */
+	priv_len = krb_mk_priv((unsigned char *)&cksum,
+			       tmp_buf,
+			       (unsigned long) sizeof(cksum),
+			       schedule,
+			       &kdata->session,
+			       laddr,
+			       faddr);
+	if (priv_len < 0) {
+	    /* re-sealing failed; notify the client */
+	    rem = KFAILURE;	 /* XXX */
+mutual_fail:
+	    priv_len = -1;
+	    tkt_len = htonl((unsigned long) priv_len);
+	    /* a length of -1 is interpreted as an authentication
+	       failure by the client */
+	    if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+		!= sizeof(tkt_len))
+		return(cc);
+	    return(rem);
+	} else {
+	    /* re-sealing succeeded, send the private message */
+	    tkt_len = htonl((unsigned long)priv_len);
+	    if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+		 != sizeof(tkt_len))
+		return(cc);
+	    if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
+		!= (int) priv_len)
+		return(cc);
+	}
+    }
+    return(rem);
+}
+#endif
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include "port-sockets.h"
+
+int
+accept_a_connection (int debug_port, struct sockaddr *from,
+		     socklen_t *fromlenp)
+{
+    int n, s, fd, s4 = -1, s6 = -1, on = 1;
+    fd_set sockets;
+
+    FD_ZERO(&sockets);
+
+#ifdef KRB5_USE_INET6
+    {
+	struct sockaddr_in6 sock_in6;
+
+	if ((s = socket(AF_INET6, SOCK_STREAM, PF_UNSPEC)) < 0) {
+	    if ((errno == EPROTONOSUPPORT) || (errno == EAFNOSUPPORT))
+		goto skip_ipv6;
+	    fprintf(stderr, "Error in socket(INET6): %s\n", strerror(errno));
+	    exit(2);
+	}
+
+	memset((char *) &sock_in6, 0,sizeof(sock_in6));
+	sock_in6.sin6_family = AF_INET6;
+	sock_in6.sin6_port = htons(debug_port);
+	sock_in6.sin6_addr = in6addr_any;
+
+	(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+			  (char *)&on, sizeof(on));
+
+	if ((bind(s, (struct sockaddr *) &sock_in6, sizeof(sock_in6))) < 0) {
+	    fprintf(stderr, "Error in bind(INET6): %s\n", strerror(errno));
+	    exit(2);
+	}
+
+	if ((listen(s, 5)) < 0) {
+	    fprintf(stderr, "Error in listen(INET6): %s\n", strerror(errno));
+	    exit(2);
+	}
+	s6 = s;
+	FD_SET(s, &sockets);
+    skip_ipv6:
+	;
+    }
+#endif
+
+    {
+	struct sockaddr_in sock_in;
+
+	if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
+	    fprintf(stderr, "Error in socket: %s\n", strerror(errno));
+	    exit(2);
+	}
+
+	memset((char *) &sock_in, 0,sizeof(sock_in));
+	sock_in.sin_family = AF_INET;
+	sock_in.sin_port = htons(debug_port);
+	sock_in.sin_addr.s_addr = INADDR_ANY;
+
+	(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+			  (char *)&on, sizeof(on));
+
+	if ((bind(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) < 0) {
+	    if (s6 >= 0 && errno == EADDRINUSE)
+		goto try_ipv6_only;
+	    fprintf(stderr, "Error in bind: %s\n", strerror(errno));
+	    exit(2);
+	}
+
+	if ((listen(s, 5)) < 0) {
+	    fprintf(stderr, "Error in listen: %s\n", strerror(errno));
+	    exit(2);
+	}
+	s4 = s;
+	FD_SET(s, &sockets);
+    try_ipv6_only:
+	;
+    }
+    if (s4 == -1 && s6 == -1) {
+	fprintf(stderr, "No valid sockets established, exiting\n");
+	exit(2);
+    }
+    n = select(((s4 < s6) ? s6 : s4) + 1, &sockets, 0, 0, 0);
+    if (n < 0) {
+	fprintf(stderr, "select error: %s\n", strerror(errno));
+	exit(2);
+    } else if (n == 0) {
+	fprintf(stderr, "internal error? select returns 0\n");
+	exit(2);
+    }
+    if (s6 != -1 && FD_ISSET(s6, &sockets)) {
+	if (s4 != -1)
+	    close(s4);
+	s = s6;
+    } else if (FD_ISSET(s4, &sockets)) {
+	if (s6 != -1)
+	    close(s6);
+	s = s4;
+    } else {
+	fprintf(stderr,
+		"internal error? select returns positive, "
+		"but neither fd available\n");
+	exit(2);
+    }
+
+    if ((fd = accept(s, from, fromlenp)) < 0) {
+	fprintf(stderr, "Error in accept: %s\n", strerror(errno));
+	exit(2);
+    }
+
+    close(s);
+    return fd;
+}
diff --git a/krb5-1-6/src/appl/bsd/configure.in b/krb5-1-6/src/appl/bsd/configure.in
new file mode 100644
index 000000000..9a425edb9
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/configure.in
@@ -0,0 +1,195 @@
+K5_AC_INIT(krlogind.c)
+CONFIG_RULES
+KRB5_AC_INET6
+LOGINLIBS=
+AC_ARG_WITH([afs],
+[  --without-afs        don't have afs libraries to build against (default)
+  --with-afs=AFSDIR    use preinstalled AFS library tree],
+,with_afs=no)dnl
+if test $with_afs != no; then
+	AC_DEFINE(SETPAG,1,[Define if setpag should be used])
+	LOGINLIBS="$LOGINLIBS -L$with_afs/lib -L$with_afs/lib/afs -lauth -lsys -lrx -llwp"
+fi
+AC_PROG_INSTALL
+dnl dbm libs for use of an_to_ln
+save_LIBS="$LIBS"
+ LIBS=
+ AC_CHECK_LIB(crypt,crypt)
+ LOGINLIBS="$LOGINLIBS $LIBS"
+LIBS="$save_LIBS"
+dnl
+dnl AIX has them all; SCO might too
+AC_CHECK_LIB(odm,main,
+  AC_CHECK_LIB(s,main,
+    AC_CHECK_LIB(cfg,main, 
+      LOGINLIBS="$LOGINLIBS -lodm -ls -lcfg" 
+      )))
+dnl
+dnl Make our operating system-specific security checks and definitions for
+dnl login.
+dnl
+case $krb5_cv_host in
+*-*-aix3*)
+	# AIX has streams include files but not streams TTY
+	# Moreover, strops.h trashes sys/ioctl.h
+	krb5_cv_has_streams=no
+	;;
+alpha*-dec-osf*)
+	AC_CHECK_LIB(security,setluid,
+		AC_DEFINE(HAVE_SETLUID,1,[Define if setluid is supplied by the OSF/1 security library])
+		LOGINLIBS="$LOGINLIBS -lsecurity"
+	)
+	;;
+*-*-sunos4*)
+	ac_cv_header_termios_h=no
+	;;
+esac
+dnl
+dnl krshd does not use krb524...
+dnl
+KRSHDLIBS="$LOGINLIBS"
+dnl 
+dnl After beta6 this functionality will be integrated with aclocal.m4
+AC_ARG_WITH([krb4],
+[  --without-krb4          don't include Kerberos V4 backwards compatibility
+  --with-krb4             use V4 libraries included with V5 (default)
+  --with-krb4=KRB4DIR     use preinstalled V4 libraries],
+,
+withval=yes
+)dnl
+if test $withval = no; then
+	AC_MSG_RESULT(no krb4 support)
+	V4RCP=
+	V4RCPO=
+else 
+	AC_MSG_RESULT(Adding in krb4 rcp support)
+	V4RCP=v4rcp
+	V4RCPO=v4rcp.o
+fi
+dnl
+dnl
+AC_SUBST(KRSHDLIBS)
+AC_SUBST(LOGINLIBS)
+AC_SUBST(V4RCP)
+AC_SUBST(V4RCPO)
+dnl
+AC_FUNC_VFORK
+AC_TYPE_MODE_T
+AC_CHECK_FUNCS(isatty inet_aton getenv gettosbyname killpg initgroups setpriority setreuid setresuid waitpid setsid ptsname setlogin tcgetpgrp tcsetpgrp setpgid strsave utimes rmufile rresvport_af)
+AC_CHECK_HEADERS(unistd.h stdlib.h string.h sys/filio.h sys/sockio.h sys/label.h sys/tty.h ttyent.h lastlog.h sys/select.h sys/ptyvar.h utmp.h sys/time.h krb4-proto.h sys/ioctl_compat.h paths.h arpa/nameser.h)
+AC_HEADER_STDARG
+AC_REPLACE_FUNCS(getdtablesize)
+dnl
+KRB5_AC_NEED_DAEMON
+dnl
+KRB5_SIGTYPE
+CHECK_SIGNALS
+CHECK_SETJMP
+CHECK_DIRENT
+CHECK_WAIT_TYPE
+AC_CHECK_HEADER(termios.h,[AC_CHECK_FUNC(cfsetispeed,AC_DEFINE(POSIX_TERMIOS,1,[Define if POSIX-compatible termios interface is found]))])
+CHECK_UTMP
+KRB5_GETSOCKNAME_ARGS
+dnl
+dnl Check for where the BSD rlogin, rcp, and rsh programs live.
+dnl
+save_path=$PATH
+ifdef([_AC_PROG_ECHO], [_AC_PROG_ECHO])
+ifdef([AC_PROG_ECHO_N], [AC_PROG_ECHO_N])
+AC_ARG_ENABLE([athena],
+[  --enable-athena         build with MIT Project Athena configuration],
+[PATH=/usr/athena/bin:/bin:/usr/bin:/usr/bsd:/usr/ucb],
+[PATH=/bin:/usr/bin:/usr/bsd:/usr/ucb])
+AC_PATH_PROG(UCB_RLOGIN,rlogin,/usr/ucb/rlogin)
+AC_PATH_PROG(UCB_RSH,rsh,/usr/ucb/rsh)
+AC_PATH_PROG(UCB_RCP,rcp,/usr/ucb/rcp)
+PATH=$save_path
+ifdef([_AC_PROG_ECHO], [_AC_PROG_ECHO])
+ifdef([AC_PROG_ECHO_N], [AC_PROG_ECHO_N])
+dnl
+dnl
+AC_MSG_CHECKING([streams interface])
+AC_CACHE_VAL(krb5_cv_has_streams,
+[AC_TRY_COMPILE(
+[#include <sys/stream.h>
+#include <sys/stropts.h>], [],
+krb5_cv_has_streams=yes, krb5_cv_has_streams=no)])
+AC_MSG_RESULT($krb5_cv_has_streams)
+if test $krb5_cv_has_streams = yes; then
+AC_DEFINE(HAVE_STREAMS,1,[Define if the OS uses streams])
+fi
+dnl
+dnl
+AC_MSG_CHECKING([F_SETOWN])
+AC_CACHE_VAL(krb5_cv_f_setown,
+[AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <fcntl.h>], [1+F_SETOWN;],
+krb5_cv_f_setown=yes,krb5_cv_f_setown=no)])
+AC_MSG_RESULT($krb5_cv_f_setown)
+if test $krb5_cv_f_setown = yes; then
+AC_DEFINE(HAVE_SETOWN,1,[Define if F_SETOWN is available])
+fi
+dnl
+dnl
+AC_MSG_CHECKING([setenv])
+AC_CACHE_VAL(krb5_cv_setenv,
+[AC_TRY_LINK(
+[],[setenv("PATH","/bin",0);],
+krb5_cv_setenv=yes,krb5_cv_setenv=no)])
+AC_MSG_RESULT($krb5_cv_setenv)
+if test $krb5_cv_setenv = no; then
+SETENVSRC=setenv.c
+SETENVOBJ=setenv.o
+AC_SUBST([SETENVSRC])
+AC_SUBST([SETENVOBJ])
+AC_DEFINE([NEED_SETENV],1,[Define if setenv needs to be defined])
+fi
+dnl
+dnl
+AC_MSG_CHECKING([number of arguments to setpgrp])
+AC_CACHE_VAL(krb5_cv_setpgrp_args,
+[AC_TRY_COMPILE(
+[#ifndef __STDC__
+#define __STDC__ 1
+#endif
+#include <unistd.h>],[setpgrp(0,0)],
+krb5_cv_setpgrp_args=two, krb5_cv_setpgrp_args=void)])
+AC_MSG_RESULT($krb5_cv_setpgrp_args)
+if test $krb5_cv_setpgrp_args = two; then
+AC_DEFINE(SETPGRP_TWOARG,1,[Define if setpgrp takes two arguments])
+fi
+dnl
+dnl
+AC_MSG_CHECKING([shadow password support])
+AC_CACHE_VAL(krb5_cv_shadow_pwd,
+[AC_TRY_LINK(
+[#include <sys/types.h>
+#include <pwd.h>
+#include <shadow.h>],
+[struct spwd *sp = getspnam("root")],
+krb5_cv_shadow_pwd=yes, krb5_cv_shadow_pwd=no)])
+AC_MSG_RESULT($krb5_cv_shadow_pwd)
+if test $krb5_cv_shadow_pwd = yes; then
+AC_DEFINE(HAVE_SHADOW,1,[Define if shadow password interface is available])
+fi
+dnl
+dnl
+K5_AC_CHECK_FILES(/etc/environment /etc/TIMEZONE)
+dnl
+dnl
+AC_C_CONST
+if test "$krb5_cv_build_krb4_libs" = yes; then
+	AC_DEFINE(HAVE_KRB_GET_ERR_TEXT)
+	AC_DEFINE(HAVE_KRB_SAVE_CREDENTIALS)
+else
+	oldlibs=$LIBS
+	LIBS=" $KRB4_LIB -lkrb5 -lcrypto -lcom_err"
+	AC_CHECK_FUNCS(krb_get_err_text krb_save_credentials)
+	LIBS=$oldlibs
+fi
+
+AC_CHECK_HEADERS(krb4-proto.h)
+KRB5_AC_LIBUTIL
+KRB5_BUILD_PROGRAM
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/appl/bsd/defines.h b/krb5-1-6/src/appl/bsd/defines.h
new file mode 100644
index 000000000..ac7948ab9
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/defines.h
@@ -0,0 +1,100 @@
+#define OPTS_FORWARD_CREDS           0x00000020
+#define OPTS_FORWARDABLE_CREDS       0x00000010
+#define RCMD_BUFSIZ	5120
+
+enum kcmd_proto {
+  /* Old protocol: DES encryption only.  No subkeys.  No protection
+     for cleartext length.  No ivec supplied.  OOB hacks used for
+     rlogin.  Checksum may be omitted at connection startup.  */
+  KCMD_OLD_PROTOCOL = 1,
+  /* New protocol: Any encryption scheme.  Client-generated subkey
+     required.  Prepend cleartext-length to cleartext data (but don't
+     include it in count).  Starting ivec defined, chained.  In-band
+     signalling.  Checksum required.  */
+  KCMD_NEW_PROTOCOL,
+  /* Hack: Get credentials, and use the old protocol iff the session
+     key type is single-DES.  */
+  KCMD_PROTOCOL_COMPAT_HACK,
+  /* Using Kerberos version 4.  */
+  KCMD_V4_PROTOCOL,
+  /* ??? */
+  KCMD_UNKNOWN_PROTOCOL
+};
+
+extern int kcmd (int *sock, char **ahost, int /* u_short */ rport,
+		 char *locuser, char *remuser, char *cmd,
+		 int *fd2p, char *service, char *realm,
+		 krb5_creds **cred,
+		 krb5_int32 *seqno, krb5_int32 *server_seqno,
+		 struct sockaddr_in *laddr,
+		 struct sockaddr_in *faddr,
+		 krb5_auth_context *authconp,
+		 krb5_flags authopts,
+		 int anyport, int suppress_err,
+		 enum kcmd_proto *protonum /* input and output */
+		 );
+
+extern int rcmd_stream_read (int fd, char *buf, size_t len, int secondary);
+extern int rcmd_stream_write (int fd, char *buf, size_t len, int secondary);
+extern int getport (int * /* portnum */, int * /* addrfamily */);
+
+extern void rcmd_stream_init_krb5 (krb5_keyblock *in_keyblock,
+				   int encrypt_flag, int lencheck,
+				   int am_client, enum kcmd_proto protonum);
+
+extern void rcmd_stream_init_normal(void);
+
+#if defined(KRB5_KRB4_COMPAT) && !defined(SKIP_V4_PROTO)
+extern void rcmd_stream_init_krb4(C_Block, int, int, int);
+
+extern int k4cmd(int *sock, char **ahost, unsigned int rport,
+		 char *locuser,
+		 char *remuser, char *cmd, int *fd2p, KTEXT ticket,
+		 char *service, char *realm, CREDENTIALS *cred, 
+		 Key_schedule schedule, MSG_DAT *msg_data, 
+		 struct sockaddr_in *laddr, struct sockaddr_in *faddr, 
+		 long authopts, int anyport);
+#endif
+
+#ifndef HAVE_STRSAVE
+extern char *strsave(const char *sp);
+#endif
+
+krb5_error_code rd_and_store_for_creds(krb5_context context, 
+				       krb5_auth_context auth_context,
+				       krb5_data *inbuf, krb5_ticket *ticket,
+				       krb5_ccache *ccache);
+
+
+int princ_maps_to_lname(krb5_principal principal, char *luser);
+int default_realm(krb5_principal principal);
+
+#ifdef NEED_SETENV
+extern int setenv(char *, char *, int);
+#endif
+
+#include "fake-addrinfo.h"
+
+#ifdef KRB_DEFS
+krb5_error_code krb5_compat_recvauth(krb5_context, krb5_auth_context *,
+				     krb5_pointer, char *, krb5_principal, 
+				     krb5_int32, krb5_keytab,
+				     krb5_int32, char *, char *,
+				     struct sockaddr_in *, 
+				     struct sockaddr_in *, char *,
+				     krb5_ticket **, krb5_int32 *, 
+				     AUTH_DAT **, Key_schedule, char *);
+
+krb5_error_code
+krb5_compat_recvauth_version(krb5_context, krb5_auth_context *,
+			     krb5_pointer, krb5_principal, krb5_int32, 
+			     krb5_keytab, krb5_int32, char *, char *,
+			     struct sockaddr_in *, struct sockaddr_in *,
+			     char *, krb5_ticket **, krb5_int32*, 
+			     AUTH_DAT **,  Key_schedule, krb5_data *);
+#endif
+
+#include "port-sockets.h"
+
+int accept_a_connection (int debug_port, struct sockaddr *from,
+			 socklen_t *fromlenp);
diff --git a/krb5-1-6/src/appl/bsd/forward.c b/krb5-1-6/src/appl/bsd/forward.c
new file mode 100644
index 000000000..53f67e667
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/forward.c
@@ -0,0 +1,77 @@
+/*
+ * appl/bsd/forward.c
+ */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(KERBEROS) || defined(KRB5)
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "k5-int.h"
+
+#define SKIP_V4_PROTO /* To skip the krb4 prototypes */
+#include "defines.h"
+
+/* Decode, decrypt and store the forwarded creds in the local ccache. */
+krb5_error_code
+rd_and_store_for_creds(context, auth_context, inbuf, ticket, ccache)
+    krb5_context context;
+    krb5_auth_context auth_context;
+    krb5_data *inbuf;
+    krb5_ticket *ticket;
+    krb5_ccache *ccache;
+{
+    krb5_creds ** creds;
+    krb5_error_code retval;
+    char ccname[35];
+
+    *ccache  = NULL;
+
+    retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL);
+    if (retval) 
+	return(retval);
+
+    /* Set the KRB5CCNAME ENV variable to keep sessions 
+     * seperate. Use the process id of this process which is 
+     * the rlogind or rshd. Set the environment variable as well.
+     */
+  
+    sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", (long) getpid());
+    setenv("KRB5CCNAME", ccname, 1);
+  
+    retval = krb5_cc_resolve(context, ccname, ccache);
+    if (retval) 
+	goto cleanup;
+
+    retval = krb5_cc_initialize(context, *ccache, ticket->enc_part2->client);
+    if (retval)
+	goto cleanup;
+
+    retval = krb5_cc_store_cred(context, *ccache, *creds);
+    if (retval) 
+	goto cleanup;
+
+cleanup:
+    krb5_free_creds(context, *creds);
+    return retval;
+}
+
+#endif /* KERBEROS */
diff --git a/krb5-1-6/src/appl/bsd/getdtablesize.c b/krb5-1-6/src/appl/bsd/getdtablesize.c
new file mode 100644
index 000000000..244616cc9
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/getdtablesize.c
@@ -0,0 +1,19 @@
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <limits.h>
+
+#ifdef _SC_OPEN_MAX
+int getdtablesize() {
+    return sysconf(_SC_OPEN_MAX);
+}
+#else
+#include <sys/resource.h>
+/* Placed in the Public Domain by Mark Eichin, Cygnus Support 1994 */
+
+int getdtablesize() {
+    struct rlimit rl;
+    getrlimit(RLIMIT_NOFILE, &rl);
+    return rl.rlim_cur;
+}
+#endif
diff --git a/krb5-1-6/src/appl/bsd/kcmd.c b/krb5-1-6/src/appl/bsd/kcmd.c
new file mode 100644
index 000000000..7c00d9746
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/kcmd.c
@@ -0,0 +1,1369 @@
+/*
+ * appl/bsd/kcmd.c
+ */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * 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
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <pwd.h>
+#include <sys/param.h>
+#ifndef _TYPES_
+#include <sys/types.h>
+#define _TYPES_
+#endif
+#include <fcntl.h>
+     
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+#include <signal.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+
+#ifndef POSIX_SIGNALS
+#ifndef sigmask
+#define sigmask(m)    (1 << ((m)-1))
+#endif
+#endif
+     
+#ifndef roundup
+#define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
+#endif
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <errno.h>
+#include <krb5.h>
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+
+#include "defines.h"
+
+extern krb5_context bsd_context;
+#ifdef KRB5_KRB4_COMPAT
+extern Key_schedule v4_schedule;
+#endif
+
+
+#define START_PORT      5120     /* arbitrary */
+char *default_service = "host";
+
+#define KCMD_KEYUSAGE	1026 /* Key usage used   with 3des or any old-protocol enctype*/
+/* New protocol enctypes that use cipher state have keyusage defined later*/
+
+#ifndef GETSOCKNAME_ARG3_TYPE
+#define GETSOCKNAME_ARG3_TYPE int
+#endif
+
+/*
+ * 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
+ * performance penalty is suffered (at least one RTT per character, two if we
+ * are waiting for a shell to echo) by writing the data separately from the 
+ * length.  So, unlike the input buffer, which just contains the output
+ * data, the output buffer represents the entire packet.
+ */
+
+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;
+
+/* XXX Overloaded: use_ivecs!=0 -> new protocol, inband signalling, etc.  */
+static int use_ivecs;
+static krb5_keyusage enc_keyusage_i[2], enc_keyusage_o[2];
+static krb5_data encivec_i[2], encivec_o[2];
+
+static krb5_keyblock *keyblock;		 /* key for encrypt/decrypt */
+static int (*input)(int, char *, size_t, int);
+static int (*output)(int, char *, size_t, int);
+static char storage[2*RCMD_BUFSIZ];	 /* storage for the decryption */
+static size_t nstored = 0;
+static char *store_ptr = storage;
+static int twrite(int, char *, size_t, int);
+static int v5_des_read(int, char *, size_t, int), 
+    v5_des_write(int, char *, size_t, int);
+#ifdef KRB5_KRB4_COMPAT
+static int v4_des_read(int, char *, size_t, int), 
+    v4_des_write(int, char *, size_t, int);
+static C_Block v4_session;
+static int right_justify;
+#endif
+static int do_lencheck;
+
+#ifdef KRB5_KRB4_COMPAT
+extern int
+krb_sendauth(long options, int fd, KTEXT ticket,
+	     char *service, char *inst, char *realm,
+	     unsigned KRB4_32 checksum,
+	     MSG_DAT *msg_data,
+	     CREDENTIALS *cred,
+	     Key_schedule schedule,
+	     struct sockaddr_in *laddr,
+	     struct sockaddr_in *faddr,
+	     char *version);
+#endif
+
+#ifdef POSIX_SIGNALS
+typedef sigset_t masktype;
+#else
+typedef sigmasktype masktype;
+#endif
+
+static void
+block_urgent (masktype *oldmask)
+{
+#ifdef POSIX_SIGNALS
+    sigset_t urgmask;
+
+    sigemptyset(&urgmask);
+    sigaddset(&urgmask, SIGURG);
+    sigprocmask(SIG_BLOCK, &urgmask, oldmask);
+#else
+    *oldmask = sigblock(sigmask(SIGURG));
+#endif /* POSIX_SIGNALS */
+}
+
+static void
+restore_sigs (masktype *oldmask)
+{
+#ifdef POSIX_SIGNALS
+    sigprocmask(SIG_SETMASK, oldmask, (sigset_t*)0);
+#else
+    sigsetmask(*oldmask);
+#endif /* POSIX_SIGNALS */
+}
+
+static int
+kcmd_connect (int *sp, int *addrfamilyp, struct sockaddr_in *sockinp,
+	      char *hname, char **host_save, unsigned int rport, int *lportp,
+	      struct sockaddr_in *laddrp)
+{
+    int s, aierr;
+    struct addrinfo *ap, *ap2, aihints;
+    char rport_buf[10];
+    GETSOCKNAME_ARG3_TYPE  sin_len;
+
+    if (rport == 0) {
+	fprintf(stderr, "can't connect to %s port 0\n", hname);
+	return -1;
+    }
+    sprintf(rport_buf, "%d", ntohs(rport));
+    memset(&aihints, 0, sizeof(aihints));
+    aihints.ai_socktype = SOCK_STREAM;
+    aihints.ai_flags = AI_CANONNAME;
+    aihints.ai_family = *addrfamilyp;
+    aierr = getaddrinfo(hname, rport_buf, &aihints, &ap);
+    if (aierr) {
+	const char *msg;
+	/* We want to customize some messages.  */
+	switch (aierr) {
+	case EAI_NONAME:
+	    msg = "host unknown";
+	    break;
+	default:
+	    fprintf(stderr, "foo\n");
+	    msg = gai_strerror(aierr);
+	    break;
+	}
+	fprintf(stderr, "%s: %s\n", hname, msg);
+	return -1;
+    }
+    if (ap == 0) {
+	fprintf(stderr, "%s: no addresses?\n", hname);
+	return -1;
+    }
+
+    *host_save = strdup(ap->ai_canonname ? ap->ai_canonname : hname);
+
+    for (ap2 = ap; ap; ap = ap->ai_next) {
+	char hostbuf[NI_MAXHOST];
+	char portbuf[NI_MAXSERV];
+	int oerrno;
+	int af = ap->ai_family;
+
+	/* @@ Debugging.  Yuck.  */
+	switch (af) {
+	case AF_INET:
+	    if (((struct sockaddr_in *)ap->ai_addr)->sin_port == 0) {
+		fprintf(stderr, "internal error: got ipv4 address but port zero?\n");
+		continue;
+	    }
+	    break;
+#ifdef KRB5_USE_INET6
+	case AF_INET6:
+	    if (((struct sockaddr_in6 *)ap->ai_addr)->sin6_port == 0) {
+		fprintf(stderr, "internal error: got ipv6 address but port zero?\n");
+		continue;
+	    }
+	    break;
+#endif
+	}
+
+	for (;;) {
+	    s = getport(lportp, &af);
+	    if (s < 0) {
+		if (errno == EAGAIN)
+		    fprintf(stderr, "socket: All ports in use\n");
+		else
+		    perror("kcmd: socket");
+		return -1;
+	    }
+	    if (connect(s, ap->ai_addr, ap->ai_addrlen) >= 0)
+		goto connected;
+	    (void) close(s);
+	    if (errno != EADDRINUSE)
+		break;
+	    if (lportp)
+		(*lportp)--;
+	}
+
+	oerrno = errno;
+	aierr = getnameinfo(ap->ai_addr, ap->ai_addrlen,
+			    hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf),
+			    NI_NUMERICHOST | NI_NUMERICSERV);
+	if (aierr)
+	    fprintf(stderr, "connect to <error formatting address: %s>: ",
+		    gai_strerror (aierr));
+	else
+	    fprintf(stderr, "connect to address %s port %s: ", hostbuf,
+		    portbuf);
+	errno = oerrno;
+	perror(0);
+
+	if (ap->ai_next)
+	    fprintf(stderr, "Trying next address...\n");
+    }
+    freeaddrinfo(ap2);
+    return -1;
+
+connected:
+    sin_len = sizeof(struct sockaddr_in);
+    if (getsockname(s, (struct sockaddr *)laddrp, &sin_len) < 0) {
+	perror("getsockname");
+	close(s);
+	return -1;
+    }
+
+    *sp = s;
+    *sockinp = *(struct sockaddr_in *) ap->ai_addr;
+    *addrfamilyp = ap->ai_family;
+    freeaddrinfo(ap2);
+    return 0;
+}
+
+static int
+setup_secondary_channel (int s, int *fd2p, int *lportp, int *addrfamilyp,
+			 struct sockaddr_in *fromp, int anyport)
+{
+    if (fd2p == 0) {
+    	write(s, "", 1);
+    	*lportp = 0;
+    } else {
+    	char num[8];
+    	socklen_t len = sizeof (*fromp);
+	size_t slen;
+    	int s2 = getport(lportp, addrfamilyp), s3;
+	fd_set rfds, xfds;
+	struct timeval waitlen;
+	int n;
+
+	*fd2p = -1;
+	if (s2 < 0)
+	    return -1;
+	FD_ZERO(&rfds);
+	FD_ZERO(&xfds);
+	FD_SET(s, &rfds);
+	FD_SET(s, &xfds);
+	listen(s2, 1);
+	FD_SET(s2, &rfds);
+    	(void) sprintf(num, "%d", *lportp);
+	slen = strlen(num)+1;
+    	if (write(s, num, slen) != slen) {
+	    perror("write: setting up stderr");
+	    (void) close(s2);
+	    return -1;
+    	}
+	waitlen.tv_sec = 600;	/* long, but better than infinite */
+	waitlen.tv_usec = 0;
+	n = (s < s2) ? s2 : s;
+	n = select(n+1, &rfds, 0, &xfds, &waitlen);
+	if (n <= 0) {
+	    /* timeout or error */
+	    fprintf(stderr, "timeout in circuit setup\n");
+	    close(s2);
+	    *fd2p = -1;
+	    return -1;
+	} else {
+	    if (FD_ISSET(s, &rfds) || FD_ISSET(s, &xfds)) {
+		fprintf(stderr, "socket: protocol error or closed connection in circuit setup\n");
+		close(s2);
+		*fd2p = -1;
+		return -1;
+	    }
+	    /* ready to accept a connection; yay! */
+	}
+    	s3 = accept(s2, (struct sockaddr *)fromp, &len);
+    	(void) close(s2);
+    	if (s3 < 0) {
+	    perror("accept");
+	    *lportp = 0;
+	    return -1;
+    	}
+    	*fd2p = s3;
+    	fromp->sin_port = ntohs(fromp->sin_port);
+	/* This check adds nothing when using Kerberos.  */
+    	if (! anyport &&
+	    (fromp->sin_family != AF_INET ||
+    	     fromp->sin_port >= IPPORT_RESERVED)) {
+	    fprintf(stderr, "socket: protocol failure in circuit setup.\n");
+	    close(s3);
+	    *fd2p = -1;
+	    return -1;
+    	}
+    }
+    return 0;
+}
+
+int
+kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
+     cred, seqno, server_seqno, laddr, faddr, authconp, authopts, anyport,
+     suppress_err, protonump)
+     int *sock;
+     char **ahost;
+     u_short rport;
+     char *locuser, *remuser, *cmd;
+     int *fd2p;
+     char *service;
+     char *realm;
+     krb5_creds **cred; /* output only */
+     krb5_int32 *seqno;
+     krb5_int32 *server_seqno;
+     struct sockaddr_in *laddr, *faddr;
+     krb5_auth_context *authconp;
+     krb5_flags authopts;
+     int anyport;
+     int suppress_err;		/* Don't print if authentication fails */
+     enum kcmd_proto *protonump;
+{
+    int s;
+    masktype oldmask;
+    struct sockaddr_in sockin, from, local_laddr;
+    krb5_creds *get_cred = 0, *ret_cred = 0;
+    char c;
+    int lport;
+    int rc;
+    char *host_save;
+    krb5_error_code status;
+    krb5_ap_rep_enc_part *rep_ret;
+    krb5_error	*error = 0;
+    krb5_ccache cc;
+    krb5_data outbuf;
+    krb5_flags options = authopts;
+    krb5_auth_context auth_context = NULL;
+    char *cksumbuf;
+    krb5_data cksumdat;
+    char *kcmd_version;
+    enum kcmd_proto protonum = *protonump;
+    int addrfamily = /* AF_INET */0;
+
+    if ((cksumbuf = malloc(strlen(cmd)+strlen(remuser)+64)) == 0 ) {
+	fprintf(stderr, "Unable to allocate memory for checksum buffer.\n");
+	return(-1);
+    }
+    sprintf(cksumbuf, "%u:", ntohs(rport));
+    strcat(cksumbuf, cmd);
+    strcat(cksumbuf, remuser);
+    cksumdat.data = cksumbuf;
+    cksumdat.length = strlen(cksumbuf);
+	
+    block_urgent(&oldmask);
+    
+    if (!laddr) laddr = &local_laddr;
+    if (kcmd_connect(&s, &addrfamily, &sockin, *ahost, &host_save, rport, 0, laddr) == -1) {
+	restore_sigs(&oldmask);
+	return -1;
+    }
+    *ahost = host_save;
+    /* If no service is given set to the default service */
+    if (!service) service = default_service;
+    
+    if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
+        fprintf(stderr,"kcmd: no memory\n");
+        return(-1);
+    }
+    status = krb5_sname_to_principal(bsd_context, host_save, service,
+				     KRB5_NT_SRV_HST, &get_cred->server);
+    if (status) {
+	fprintf(stderr, "kcmd: krb5_sname_to_principal failed: %s\n",
+		error_message(status));
+	return(-1);
+    }
+
+    if (realm && *realm) {
+        status = krb5_set_principal_realm(bsd_context, get_cred->server,
+					  realm);
+	if (status) {
+	  fprintf(stderr, "kcmd: krb5_set_principal_realm failed %s\n", 
+		  error_message(status));
+	  return(-1);
+	}
+    }
+    status = setup_secondary_channel(s, fd2p, &lport, &addrfamily, &from,
+				     anyport);
+    if (status)
+	goto bad;
+
+    if (faddr)
+	*faddr = sockin;
+
+    status = krb5_cc_default(bsd_context, &cc);
+    if (status)
+    	goto bad2;
+
+    status = krb5_cc_get_principal(bsd_context, cc, &get_cred->client);
+    if (status) {
+    	(void) krb5_cc_close(bsd_context, cc);
+    	goto bad2;
+    }
+
+    /* Get ticket from credentials cache or kdc */
+    status = krb5_get_credentials(bsd_context, 0, cc, get_cred, &ret_cred);
+    krb5_free_creds(bsd_context, get_cred);
+    (void) krb5_cc_close(bsd_context, cc);
+    if (status) {
+	fprintf (stderr, "error getting credentials: %s\n",
+		 error_message (status));
+	goto bad2;
+    }
+
+    /* Reset internal flags; these should not be sent. */
+    authopts &= (~OPTS_FORWARD_CREDS);
+    authopts &= (~OPTS_FORWARDABLE_CREDS);
+
+    if (krb5_auth_con_init(bsd_context, &auth_context)) 
+	goto bad2;
+
+    if (krb5_auth_con_setflags(bsd_context, auth_context, 
+			       KRB5_AUTH_CONTEXT_RET_TIME))
+	goto bad2;
+
+    /* Only need local address for mk_cred() to send to krlogind */
+    status = krb5_auth_con_genaddrs(bsd_context, auth_context, s,
+				   KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
+    if (status)
+	goto bad2;
+
+    if (protonum == KCMD_PROTOCOL_COMPAT_HACK) {
+	krb5_boolean is_des;
+	status = krb5_c_enctype_compare (bsd_context, ENCTYPE_DES_CBC_CRC,
+					 ret_cred->keyblock.enctype, &is_des);
+	if (status)
+	    goto bad2;
+	protonum = is_des ? KCMD_OLD_PROTOCOL : KCMD_NEW_PROTOCOL;
+    }
+
+    switch (protonum) {
+    case KCMD_NEW_PROTOCOL:
+	authopts |= AP_OPTS_USE_SUBKEY;
+	kcmd_version = "KCMDV0.2";
+	break;
+    case KCMD_OLD_PROTOCOL:
+	kcmd_version = "KCMDV0.1";
+	break;
+    default:
+	status = EINVAL;
+	goto bad2;
+    }
+
+    /* Call Kerberos library routine to obtain an authenticator,
+       pass it over the socket to the server, and obtain mutual
+       authentication.  */
+    status = krb5_sendauth(bsd_context, &auth_context, (krb5_pointer) &s,
+			   kcmd_version, ret_cred->client, ret_cred->server,
+			   authopts, &cksumdat, ret_cred, 0,
+			   &error, &rep_ret, NULL);
+    free(cksumbuf);
+    if (status) {
+	if (!suppress_err)
+	    fprintf(stderr, "Couldn't authenticate to server: %s\n",
+		    error_message(status));
+	if (error) {
+	    if (!suppress_err) {
+		fprintf(stderr, "Server returned error code %d (%s)\n",
+			error->error,
+			error_message(ERROR_TABLE_BASE_krb5 + 
+				      (int) error->error));
+		if (error->text.length) {
+		    fprintf(stderr, "Error text sent from server: %s\n",
+			    error->text.data);
+		}
+	    }
+	    krb5_free_error(bsd_context, error);
+	    error = 0;
+	}
+    }	
+    if (status) goto bad2;
+    if (rep_ret && server_seqno) {
+	*server_seqno = rep_ret->seq_number;
+	krb5_free_ap_rep_enc_part(bsd_context, rep_ret);
+    }
+    
+    (void) write(s, remuser, strlen(remuser)+1);
+    (void) write(s, cmd, strlen(cmd)+1);
+    (void) write(s, locuser, strlen(locuser)+1);
+    
+    if (options & OPTS_FORWARD_CREDS) {   /* Forward credentials */
+	status = krb5_fwd_tgt_creds(bsd_context, auth_context,
+				    host_save,
+				    ret_cred->client, ret_cred->server,
+				    0, options & OPTS_FORWARDABLE_CREDS,
+				    &outbuf);
+	if (status) {
+	    fprintf(stderr, "kcmd: Error getting forwarded creds\n");
+	    goto bad2;
+	}
+
+	/* Send forwarded credentials */
+	status = krb5_write_message(bsd_context, (krb5_pointer)&s, &outbuf);
+	if (status)
+	  goto bad2;
+    }
+    else { /* Dummy write to signal no forwarding */
+	outbuf.length = 0;
+	status = krb5_write_message(bsd_context, (krb5_pointer)&s, &outbuf);
+	if (status)
+	  goto bad2;
+    }
+
+    if ((rc=read(s, &c, 1)) != 1) {
+	if (rc==-1) {
+	    perror(*ahost);
+	} else {
+	    fprintf(stderr,"kcmd: bad connection with remote host\n");
+	}
+	status = -1;
+	goto bad2;
+    }
+    if (c != 0) {
+	while (read(s, &c, 1) == 1) {
+	    (void) write(2, &c, 1);
+	    if (c == '\n')
+	      break;
+	}
+	status = -1;
+	goto bad2;
+    }
+    restore_sigs(&oldmask);
+    *sock = s;
+    *protonump = protonum;
+    
+    /* pass back credentials if wanted */
+    if (cred) krb5_copy_creds(bsd_context, ret_cred, cred);
+    krb5_free_creds(bsd_context, ret_cred);
+    if (authconp)
+	*authconp = auth_context;
+    
+    return (0);
+  bad2:
+    if (lport)
+      (void) close(*fd2p);
+  bad:
+    (void) close(s);
+    restore_sigs(&oldmask);
+    if (ret_cred)
+      krb5_free_creds(bsd_context, ret_cred);
+    return (status);
+}
+
+
+
+#ifdef KRB5_KRB4_COMPAT
+int
+k4cmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
+      cred, schedule, msg_data, laddr, faddr, authopts, anyport)
+     int *sock;
+     char **ahost;
+     unsigned int rport;
+     char *locuser, *remuser, *cmd;
+     int *fd2p;
+     KTEXT ticket;
+     char *service;
+     char *realm;
+     CREDENTIALS *cred;
+     Key_schedule schedule;
+     MSG_DAT *msg_data;
+     struct sockaddr_in *laddr, *faddr;
+     long authopts;
+     int anyport;
+{
+    int s;
+    masktype oldmask;
+    struct sockaddr_in sockin, from;
+    char c;
+    int lport = START_PORT;
+    int rc;
+    char *host_save;
+    int status;
+    int addrfamily = AF_INET;
+
+    block_urgent(&oldmask);
+    if (kcmd_connect (&s, &addrfamily, &sockin, *ahost, &host_save, rport, &lport, laddr) == -1) {
+	restore_sigs(&oldmask);
+	return -1;
+    }
+    *ahost = host_save;
+    /* If realm is null, look up from table */
+    if ((realm == NULL) || (realm[0] == '\0')) {
+	realm = krb_realmofhost(host_save);
+    }
+    lport--;
+    status = setup_secondary_channel(s, fd2p, &lport, &addrfamily, &from,
+				     anyport);
+    if (status)
+	goto bad;
+
+    /* set up the needed stuff for mutual auth */
+    *faddr = sockin;
+
+    status = krb_sendauth(authopts, s, ticket, service, *ahost,
+			  realm, (unsigned long) getpid(), msg_data,
+			  cred, schedule, laddr, faddr, "KCMDV0.1");
+    if (status != KSUCCESS) {
+	fprintf(stderr, "krb_sendauth failed: %s\n", krb_get_err_text(status));
+	status = -1;
+	goto bad2;
+    }
+    (void) write(s, remuser, strlen(remuser)+1);
+    (void) write(s, cmd, strlen(cmd)+1);
+
+reread:
+    if ((rc=read(s, &c, 1)) != 1) {
+	if (rc==-1) {
+	    perror(*ahost);
+	} else {
+	    fprintf(stderr,"rcmd: bad connection with remote host\n");
+	}
+	status = -1;
+	goto bad2;
+    }
+    if (c != 0) {
+	/* If rlogind was compiled on SunOS4, and it somehow
+	   got the shared library version numbers wrong, it
+	   may give an ld.so warning about an old version of a
+	   shared library.  Just ignore any such warning.
+	   Note that the warning is a characteristic of the
+	   server; we may not ourselves be running under
+	   SunOS4.  */
+	if (c == 'l') {
+	    char *check = "d.so: warning:";
+	    char *p;
+	    char cc;
+
+	    p = check;
+	    while (read(s, &c, 1) == 1) {
+		if (*p == '\0') {
+		    if (c == '\n')
+			break;
+		} else {
+		    if (c != *p)
+			break;
+		    ++p;
+		}
+	    }
+
+	    if (*p == '\0')
+		goto reread;
+
+	    cc = 'l';
+	    (void) write(2, &cc, 1);
+	    if (p != check)
+		(void) write(2, check, (unsigned) (p - check));
+	}
+
+	(void) write(2, &c, 1);
+	while (read(s, &c, 1) == 1) {
+	    (void) write(2, &c, 1);
+	    if (c == '\n')
+		break;
+	}
+	status = -1;
+	goto bad2;
+    }
+    restore_sigs(&oldmask);
+    *sock = s;
+    return (KSUCCESS);
+ bad2:
+    if (lport)
+	(void) close(*fd2p);
+ bad:
+    (void) close(s);
+    restore_sigs(&oldmask);
+    return (status);
+}
+#endif /* KRB5_KRB4_COMPAT */
+
+
+static int
+setup_socket (struct sockaddr *sa, GETSOCKNAME_ARG3_TYPE len)
+{
+    int s;
+
+    s = socket(sa->sa_family, SOCK_STREAM, 0);
+    if (s < 0)
+	return -1;
+
+    if (bind(s, sa, len) < 0)
+	return -1;
+    if (getsockname(s, sa, &len) < 0) {
+	close(s);
+	return -1;
+    }
+    return s;
+}
+
+
+int
+getport(alport, family)
+    int *alport, *family;
+{
+    int s;
+
+    if (*family == 0) {
+#ifdef KRB5_USE_INET6
+	*family = AF_INET6;
+	s = getport (alport, family);
+	if (s >= 0)
+	    return s;
+#endif
+	*family = AF_INET;
+    }
+
+#ifdef KRB5_USE_INET6
+    if (*family == AF_INET6) {
+	struct sockaddr_in6 sockin6;
+
+	memset(&sockin6, 0, sizeof(sockin6));
+	sockin6.sin6_family = AF_INET6;
+	sockin6.sin6_addr = in6addr_any;
+
+	s = setup_socket((struct sockaddr *)&sockin6, sizeof (sockin6));
+	if (s >= 0 && alport)
+	    *alport = ntohs(sockin6.sin6_port);
+	return s;
+    }
+#endif
+
+    if (*family == AF_INET) {
+	struct sockaddr_in sockin;
+
+	memset(&sockin, 0, sizeof(sockin));
+	sockin.sin_family = AF_INET;
+	sockin.sin_addr.s_addr = INADDR_ANY;
+
+	s = setup_socket((struct sockaddr *)&sockin, sizeof (sockin));
+	if (s >= 0 && alport)
+	    *alport = ntohs(sockin.sin_port);
+	return s;
+    }
+
+    return -1;
+}
+
+static int
+normal_read (int fd, char *buf, size_t len, int secondary)
+{
+    return read (fd, buf, len);
+}
+
+void rcmd_stream_init_normal()
+{
+    input = normal_read;
+    output = twrite;
+}
+
+void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client,
+			   protonum)
+     krb5_keyblock *in_keyblock;
+     int encrypt_flag;
+     int lencheck;
+     int am_client;
+     enum kcmd_proto protonum;
+{
+    krb5_error_code status;
+    size_t blocksize;
+    int i;
+    krb5_error_code ret;
+
+    if (!encrypt_flag) {
+	rcmd_stream_init_normal();
+	return;
+    }
+    desinbuf.data = des_inbuf;
+    desoutbuf.data = des_outpkt+4;	/* Set up des buffers */
+    keyblock = in_keyblock;
+
+    do_lencheck = lencheck;
+    input = v5_des_read;
+    output = v5_des_write;
+    enc_keyusage_i[0] = KCMD_KEYUSAGE;
+    enc_keyusage_i[1] = KCMD_KEYUSAGE;
+    enc_keyusage_o[0] = KCMD_KEYUSAGE;
+    enc_keyusage_o[1] = KCMD_KEYUSAGE;
+
+    if (protonum == KCMD_OLD_PROTOCOL) {
+	use_ivecs = 0;
+	return;
+    }
+
+    use_ivecs = 1;
+    switch (in_keyblock->enctype) {
+      /* 
+       * For the DES-based enctypes and the 3DES enctype we  want to use
+       *  a non-zero  IV because that's what we did.  In the future we
+       * use different keyusage for each channel and direction and a fresh
+       * cipher state
+       */
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES3_CBC_SHA1:
+      
+      status = krb5_c_block_size(bsd_context, keyblock->enctype,
+				 &blocksize);
+      if (status) {
+	/* XXX what do I do? */
+	abort();
+      }
+
+      encivec_i[0].length = encivec_i[1].length = encivec_o[0].length
+	= encivec_o[1].length = blocksize;
+
+      if ((encivec_i[0].data = malloc(encivec_i[0].length * 4)) == NULL) {
+	/* XXX what do I do? */
+	abort();
+      }
+      encivec_i[1].data = encivec_i[0].data + encivec_i[0].length;
+      encivec_o[0].data = encivec_i[1].data + encivec_i[0].length;
+      encivec_o[1].data = encivec_o[0].data + encivec_i[0].length;
+
+    /* is there a better way to initialize this? */
+      memset(encivec_i[0].data, am_client, blocksize);
+      memset(encivec_o[0].data, 1 - am_client, blocksize);
+      memset(encivec_i[1].data, 2 | am_client, blocksize);
+      memset(encivec_o[1].data, 2 | (1 - am_client), blocksize);
+      break;
+    default:
+      if (am_client) {
+	enc_keyusage_i[0] = 1028;
+	enc_keyusage_i[1] = 1030;
+	enc_keyusage_o[0] = 1032;
+	enc_keyusage_o[1] = 1034;
+      } else { /*am_client*/
+	enc_keyusage_i[0] = 1032;
+	enc_keyusage_i[1] = 1034;
+	enc_keyusage_o[0] = 1028;
+	enc_keyusage_o[1] = 1030;
+      }
+      for (i = 0; i < 2; i++) {
+	ret = krb5_c_init_state (bsd_context, in_keyblock, enc_keyusage_i[i],
+				 &encivec_i[i]);
+	if (ret)
+	  goto fail;
+	ret = krb5_c_init_state (bsd_context, in_keyblock, enc_keyusage_o[i],
+				 &encivec_o[i]);
+	if (ret)
+	  goto fail;
+      }
+      break;
+    }
+    return;
+ fail:
+    com_err ("kcmd", ret, "Initializing cipher state");
+    abort();
+    }
+
+#ifdef KRB5_KRB4_COMPAT
+void rcmd_stream_init_krb4(session, encrypt_flag, lencheck, justify)
+     C_Block session;
+     int encrypt_flag;
+     int lencheck;
+     int justify;
+{
+    if (!encrypt_flag) {
+	rcmd_stream_init_normal();
+	return;
+    }
+    do_lencheck = lencheck;
+    right_justify = justify;
+    input = v4_des_read;
+    output = v4_des_write;
+    memcpy(v4_session, session, sizeof(v4_session));
+}
+#endif
+
+int rcmd_stream_read(fd, buf, len, sec)
+     int fd;
+     register char *buf;
+     size_t len;
+     int sec;
+{
+    return (*input)(fd, buf, len, sec);
+}
+
+int rcmd_stream_write(fd, buf, len, sec)
+     int fd;
+     register char *buf;
+     size_t len;
+     int sec;
+{
+    return (*output)(fd, buf, len, sec);
+}
+
+/* Because of rcp lossage, translate fd 0 to 1 when writing. */
+static int twrite(fd, buf, len, secondary)
+     int fd;
+     char *buf;
+     size_t len;
+     int secondary;
+{
+    return write((fd == 0) ? 1 : fd, buf, len);
+}
+
+static int v5_des_read(fd, buf, len, secondary)
+     int fd;
+     char *buf;
+     size_t len;
+     int secondary;
+{
+    int nreturned = 0;
+    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);
+	store_ptr += len;
+	nstored -= len;
+	return(len);
+    } else if (nstored) {
+	memcpy(buf, store_ptr, nstored);
+	nreturned += nstored;
+	buf += nstored;
+	len -= nstored;
+	nstored = 0;
+    }
+
+    /* See the comment in v4_des_read. */
+    while (1) {
+	cc = krb5_net_read(bsd_context, fd, &c, 1);
+	/* we should check for non-blocking here, but we'd have
+	   to make it save partial reads as well. */
+	if (cc <= 0) return cc; /* read error */
+	if (cc == 1) {
+	    if (c == 0 || !do_lencheck) break;
+	}
+    }
+
+    rd_len = c;
+    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
+    rd_len = (rd_len << 8) | c;
+    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
+    rd_len = (rd_len << 8) | c;
+    if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
+    rd_len = (rd_len << 8) | c;
+
+    ret = krb5_c_encrypt_length(bsd_context, keyblock->enctype,
+				use_ivecs ? rd_len + 4 : rd_len,
+				&net_len);
+    if (ret) {
+	errno = ret;
+	return(-1);
+    }
+
+    if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
+	/* preposterous length, probably out of sync */
+	errno = EIO;
+	return(-1);
+    }
+    if ((cc = krb5_net_read(bsd_context, fd, desinbuf.data, net_len)) != net_len) {
+	/* probably out of sync */
+	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 */
+    ret = krb5_c_decrypt(bsd_context, keyblock, enc_keyusage_i[secondary],
+			 use_ivecs ? encivec_i + secondary : 0,
+			 &cipher, &plain);
+    if (ret) {
+	/* probably out of sync */
+	errno = EIO;
+	return(-1);
+    }
+    store_ptr = storage;
+    nstored = rd_len;
+    if (use_ivecs) {
+	int rd_len2;
+	rd_len2 = storage[0] & 0xff;
+	rd_len2 <<= 8; rd_len2 |= storage[1] & 0xff;
+	rd_len2 <<= 8; rd_len2 |= storage[2] & 0xff;
+	rd_len2 <<= 8; rd_len2 |= storage[3] & 0xff;
+	if (rd_len2 != rd_len) {
+	    /* cleartext length trashed? */
+	    errno = EIO;
+	    return -1;
+	}
+	store_ptr += 4;
+    }
+    if (nstored > len) {
+	memcpy(buf, store_ptr, len);
+	nreturned += len;
+	store_ptr += len;
+	nstored -= len;
+    } else {
+	memcpy(buf, store_ptr, nstored);
+	nreturned += nstored;
+	nstored = 0;
+    }
+
+    return(nreturned);
+}
+
+
+
+static int v5_des_write(fd, buf, len, secondary)
+     int fd;
+     char *buf;
+     size_t len;
+     int secondary;
+{
+    krb5_data plain;
+    krb5_enc_data cipher;
+    char tmpbuf[2*RCMD_BUFSIZ+8];
+    unsigned char *len_buf = (unsigned char *) tmpbuf;
+
+    if (use_ivecs) {
+	unsigned char *lenbuf2 = (unsigned char *) tmpbuf;
+	if (len + 4 > sizeof(tmpbuf))
+	    abort ();
+	lenbuf2[0] = (len & 0xff000000) >> 24;
+	lenbuf2[1] = (len & 0xff0000) >> 16;
+	lenbuf2[2] = (len & 0xff00) >> 8;
+	lenbuf2[3] = (len & 0xff);
+	memcpy (tmpbuf + 4, buf, len);
+
+	plain.data = tmpbuf;
+	plain.length = len + 4;
+    } else {
+	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, enc_keyusage_o[secondary],
+		       use_ivecs ? encivec_o + secondary : 0,
+		       &plain, &cipher)) {
+	errno = EIO;
+	return(-1);
+    }
+
+    desoutbuf.length = cipher.ciphertext.length;
+
+    len_buf = (unsigned char *) des_outpkt;
+    len_buf[0] = (len & 0xff000000) >> 24;
+    len_buf[1] = (len & 0xff0000) >> 16;
+    len_buf[2] = (len & 0xff00) >> 8;
+    len_buf[3] = (len & 0xff);
+
+    if (write(fd, des_outpkt,desoutbuf.length+4) != desoutbuf.length+4){
+	errno = EIO;
+	return(-1);
+    }
+
+    else return(len);
+}
+
+
+
+#ifdef KRB5_KRB4_COMPAT
+
+static int
+v4_des_read(fd, buf, len, secondary)
+int fd;
+char *buf;
+size_t len;
+int secondary;
+{
+	int nreturned = 0;
+	krb5_ui_4 net_len, rd_len;
+	int cc;
+	unsigned char c;
+
+	if (nstored >= len) {
+		memcpy(buf, store_ptr, len);
+		store_ptr += len;
+		nstored -= len;
+		return(len);
+	} else if (nstored) {
+		memcpy(buf, store_ptr, nstored);
+		nreturned += nstored;
+		buf += nstored;
+		len -= nstored;
+		nstored = 0;
+	}
+
+	/* We're fetching the length which is MSB first, and the MSB
+	   has to be zero unless the client is sending more than 2^24
+	   (16M) bytes in a single write (which is why this code is used
+	   in rlogin but not rcp or rsh.) The only reasons we'd get
+	   something other than zero are:
+		-- corruption of the tcp stream (which will show up when
+		   everything else is out of sync too)
+		-- un-caught Berkeley-style "pseudo out-of-band data" which
+		   happens any time the user hits ^C twice.
+	   The latter is *very* common, as shown by an 'rlogin -x -d' 
+	   using the CNS V4 rlogin.         Mark EIchin 1/95
+	   */
+	while (1) {
+	    cc = krb_net_read(fd, &c, 1);
+	    if (cc <= 0) return cc; /* read error */
+	    if (cc == 1) {
+		if (c == 0 || !do_lencheck) break;
+	    }
+	}
+
+	net_len = c;
+	if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
+	net_len = (net_len << 8) | c;
+	if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
+	net_len = (net_len << 8) | c;
+	if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
+	net_len = (net_len << 8) | c;
+
+	/* Note: net_len is unsigned */
+	if (net_len > sizeof(des_inbuf)) {
+		errno = EIO;
+		return(-1);
+	}
+	/* the writer tells us how much real data we are getting, but
+	   we need to read the pad bytes (8-byte boundary) */
+	rd_len = roundup(net_len, 8);
+	if ((cc = krb_net_read(fd, des_inbuf, rd_len)) != rd_len) {
+		errno = EIO;
+		return(-1);
+	}
+	(void) pcbc_encrypt((des_cblock *) des_inbuf,
+			    (des_cblock *) storage,
+			    (int) ((net_len < 8) ? 8 : net_len),
+			    v4_schedule,
+			    &v4_session,
+			    DECRYPT);
+	/* 
+	 * when the cleartext block is < 8 bytes, it is "right-justified"
+	 * in the block, so we need to adjust the pointer to the data
+	 */
+	if (net_len < 8 && right_justify)
+		store_ptr = storage + 8 - net_len;
+	else
+		store_ptr = storage;
+	nstored = net_len;
+	if (nstored > len) {
+		memcpy(buf, store_ptr, len);
+		nreturned += len;
+		store_ptr += len;
+		nstored -= len;
+	} else {
+		memcpy(buf, store_ptr, nstored);
+		nreturned += nstored;
+		nstored = 0;
+	}
+	
+	return(nreturned);
+}
+
+static int
+v4_des_write(fd, buf, len, secondary)
+int fd;
+char *buf;
+size_t len;
+int secondary;
+{
+	static char garbage_buf[8];
+	unsigned char *len_buf = (unsigned char *) des_outpkt;
+
+	/* 
+	 * pcbc_encrypt outputs in 8-byte (64 bit) increments
+	 *
+	 * it zero-fills the cleartext to 8-byte padding,
+	 * so if we have cleartext of < 8 bytes, we want
+	 * to insert random garbage before it so that the ciphertext
+	 * differs for each transmission of the same cleartext.
+	 * if len < 8 - sizeof(long), sizeof(long) bytes of random
+	 * garbage should be sufficient; leave the rest as-is in the buffer.
+	 * if len > 8 - sizeof(long), just garbage fill the rest.
+	 */
+
+#ifdef min
+#undef min
+#endif
+#define min(a,b) ((a < b) ? a : b)
+
+	if (len < 8) {
+		if (right_justify) {
+			krb5_random_confounder(8 - len, garbage_buf);
+			/* this "right-justifies" the data in the buffer */
+			(void) memcpy(garbage_buf + 8 - len, buf, len);
+		} else {
+			krb5_random_confounder(8 - len, garbage_buf + len);
+			(void) memcpy(garbage_buf, buf, len);
+		}
+	}
+	(void) pcbc_encrypt((des_cblock *) ((len < 8) ? garbage_buf : buf),
+			    (des_cblock *) (des_outpkt+4),
+			    (int) ((len < 8) ? 8 : len),
+			    v4_schedule,
+			    &v4_session,
+			    ENCRYPT);
+
+	/* tell the other end the real amount, but send an 8-byte padded
+	   packet */
+	len_buf[0] = (len & 0xff000000) >> 24;
+	len_buf[1] = (len & 0xff0000) >> 16;
+	len_buf[2] = (len & 0xff00) >> 8;
+	len_buf[3] = (len & 0xff);
+	if (write(fd, des_outpkt, roundup(len,8)+4) != roundup(len,8)+4) {
+		errno = EIO;
+		return(-1);
+	}
+	return(len);
+}
+
+#endif /* KRB5_KRB4_COMPAT */
+
+#ifndef HAVE_STRSAVE
+/* Strsave was a routine in the version 4 krb library: we put it here
+   for compatablilty with version 5 krb library, since kcmd.o is linked
+   into all programs. */
+
+char *
+strsave(sp)
+    const char *sp;
+{
+    register char *ret;
+    
+    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
+
+/* Server side authentication, etc */
+
+int princ_maps_to_lname(principal, luser)	
+     krb5_principal principal;
+     char *luser;
+{
+    char kuser[10];
+    if (!(krb5_aname_to_localname(bsd_context, principal,
+				  sizeof(kuser), kuser))
+	&& (strcmp(kuser, luser) == 0)) {
+	return 1;
+    }
+    return 0;
+}
+
+int default_realm(principal)
+     krb5_principal principal;
+{
+    char *def_realm;
+    unsigned int realm_length;
+    int retval;
+    
+    realm_length = krb5_princ_realm(bsd_context, principal)->length;
+    
+    if ((retval = krb5_get_default_realm(bsd_context, &def_realm))) {
+	return 0;
+    }
+    
+    if ((realm_length != strlen(def_realm)) ||
+	(memcmp(def_realm, krb5_princ_realm(bsd_context, principal)->data, 
+		realm_length))) {
+	free(def_realm);
+	return 0;
+    }	
+    free(def_realm);
+    return 1;
+}
+
diff --git a/krb5-1-6/src/appl/bsd/klogind.M b/krb5-1-6/src/appl/bsd/klogind.M
new file mode 100644
index 000000000..de4cd342e
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/klogind.M
@@ -0,0 +1,194 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rlogind.8	6.3 (Berkeley) 5/24/86
+.\"
+.TH KLOGIND 8
+.SH NAME
+klogind \- remote login server
+.SH SYNOPSIS
+.B klogind
+[
+.B \-kr54cpPef
+]
+[[ \fB\-w\fP[\fBip\fP|\fImaxhostlen\fP[\fB,\fP[\fBno\fP]\fBstriplocal\fP ]] ]
+[ \fB\-D\fP \fIport\fP ]
+.SH DESCRIPTION
+.I Klogind
+is the server for the 
+.IR rlogin (1)
+program.  The server is 
+based on rlogind(8) but uses Kerberos authentication.
+.PP
+The 
+.I klogind
+server is invoked by \fIinetd(8)\fP when it receives a connection on
+the port indicated in /etc/inetd.conf.  A typical /etc/inetd.conf
+configuration line for \fIklogind\fP might be:
+
+klogin stream tcp nowait root /usr/cygnus/sbin/klogind klogind -e5c
+
+When a service request is received, the following protocol is initiated:
+
+.IP 1)
+Check authentication.
+.IP 2)
+Check authorization via the access-control files \fI.k5login\fP and
+\fI.klogin\fP in the user's home directory.
+.IP 3)
+Prompt for password if any checks fail and the \fI-p\fP option was supplied.
+.PP
+If the authentication succeeds, login the user by calling the accompanying 
+login.krb5 or /bin/login, according to the definition of 
+DO_NOT_USE_K_LOGIN.
+.PP 
+The configuration of \fIklogind\fP is done
+by command line arguments passed by inetd.  The options are:
+.IP \fB\-5\fP 10
+Allow Kerberos V5 authentication with the \fI.k5login\fP access control
+file to be trusted.  If this authentication system is used by the client
+and the authorization check is passed, then the user is allowed to log in.
+If the user has no \fI.k5login\fP file, the login will be authorized if
+the results of krb5_aname_to_localname conversion matches the account
+name.  Unless special rules are configured, this will be true if and only
+if the Kerberos principal of the connecting user is in the default local
+realm and the principal portion matches the account name.
+
+.IP \fB\-4\fP 
+Allow Kerberos V4 authentication with the \fI.klogin\fP access control
+file to be trusted.  If this authentication system is used by the client
+and the authorization check is passed, then the user is allowed to log
+in.
+
+.IP \fB\-k\fP 
+Allow Kerberos V5 and Kerberos V4 as acceptable authentication
+mechanisms.  This is the same as including \fB\-4\fP and \fB\-5\fP.
+
+
+.IP \fB\-p\fP
+ If all other authorization checks fail, prompt the user
+for a password If this option is not included, access is denied
+without successful authentication and authorization using one of the
+previous mechanisms.
+
+.IP \fB\-P\fP
+Prompt the user for a password.
+If the -P option is passed, then the password is verified in addition
+to all other checks.
+
+.IP \fB\-e\fP
+Create an encrypted session. 
+
+.IP \fB\-c\fP 
+Require Kerberos V5 clients to present a cryptographic checksum of
+initial connection information like the name of the user that the client
+is trying to access in the initial authenticator.  This checksum
+provides additionl security by preventing an attacker from changing the
+initial connection information.  To benefit from this security, only
+Kerberos V5 should be trusted; Kerberos V4 and rhosts authentication do
+not include this checksum.  If this option is specified, older Kerberos
+V5 clients that do not send a checksum in the authenticator will not be
+able to authenticate to this server.  This option is mutually exclusive
+with the \fB-i\fP option.
+
+	If neither the \fB-c\fP or \fB-i\fP options are specified,then
+checksums are validated if presented.  Since it is difficult to remove
+a checksum from an authenticator without making the authenticator
+invalid, this default mode is almost as significant of a security
+improvement as \fB-c\fP if new clients are used.  It has the additional
+advantage of backwards compatability with some clients.
+Unfortunately, clients before Kerberos V5, Beta5, generate invalid
+checksums; if these clients are used, the \fB-i\fP option must be
+used.
+
+.IP \fB\-i\fP 
+Ignore authenticator checksums if provided.  This option
+ignore authenticator checksusm presented by current Kerberos clients
+to protect initial connection information; it is the opposite of
+\fB-c\fP.  This option is provided because some older
+clients--particularly clients predating the release of Kerberos V5
+Beta5 (May 1995)--present bogus checksums that prevent Kerberos
+authentication from succeeding in the default mode.
+
+.PP
+The parent of the login process manipulates the master side of the
+pseduo terminal, operating as an intermediary between the login
+process and the client instance of the
+.I rlogin(1)
+program.  In normal operation, the packet protocol described in
+.IR pty (4)
+is invoked to provide ^S/^Q type facilities and propagate interrupt
+signals to the remote programs.  The login process propagates the
+client terminal's baud rate and terminal type, as found in the
+environment variable, ``TERM''; see
+.IR environ (7).
+The screen or
+window size of the terminal is requested from the client, and window
+size changes from the client are propagated to the pseudo terminal.
+
+.PP
+.I Klogind
+supports the following options to control the form of the hostname
+passed to login(1):
+
+.TP
+\fB\-w \fP[\fBip\fP|\fImaxhostlen\fP[\fB,\fP[\fBno\fP]\fBstriplocal\fP]]
+Controls the form of the remote hostname passed to login(1).
+Specifying \fBip\fP results in the numeric IP address always being
+passed to login(1).  Specifying a number, \fImaxhostlen\fP, sets the
+maximum length of the hostname passed to login(1) before it will be
+passed as a numeric IP address.  If \fImaxhostlen\fP is 0, then the
+system default, as determined by the utmp or utmpx structures, is
+used.  The \fBnostriplocal\fP and \fBstriplocal\fP options, which must
+be preceded by a comma, control whether or not the local host domain
+is stripped from the remote hostname.  By default, the equivalent of
+\fBstriplocal\fP is in effect.
+
+.PP
+.I Klogind
+supports five options which are used for testing
+purposes:
+
+.IP \fB\-S\ keytab\fP 10
+Set the \fIkeytab\fP file to use.
+
+.IP \fB\-M\ realm\fP
+Set the Kerberos realm to use.
+
+.IP \fB\-L\ login\fP
+Set the login program to use.  This option only has an effect if
+DO_NOT_USE_K_LOGIN was not defined when
+.I klogind
+was compiled.
+
+.IP \fB\-D\ port\fP
+Run in standalone mode, listening on \fBport\fP.  The daemon will exit
+after one connection and will not background itself.
+
+.IP \fB\-f\fP
+Allows for standalone daemon operation.  A new child is started for
+each incoming connection and waits for it to finish before accepting
+the next connection.  This automagically figures out which port to bind
+to if no port is specified.
+
+.SH DIAGNOSTICS
+All diagnostic messages are returned on the connection
+associated with the
+.BR stderr ,
+after which any network connections are closed.
+An error is indicated by a leading byte with a value of 1.
+.PP
+.B ``Try again.''
+.br
+A
+.I fork
+by the server failed.
+.PP
+.B ``/bin/sh: ...''
+.br
+The user's login shell could not be started.
+.SH SEE ALSO
+rlogind(8), rlogin(1)
+.SH BUGS
+A more extensible protocol should be used.
diff --git a/krb5-1-6/src/appl/bsd/krcp.c b/krb5-1-6/src/appl/bsd/krcp.c
new file mode 100644
index 000000000..9cf85ed37
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/krcp.c
@@ -0,0 +1,1455 @@
+/*
+ *	appl/bsd/krcp.c
+ */
+
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+  "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)rcp.c	5.10 (Berkeley) 9/20/88 */
+
+     /*
+      * rcp
+      */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <sys/param.h>
+#ifndef _TYPES_
+#include <sys/types.h>
+#define _TYPES_
+#endif
+#include <sys/file.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+     
+#include <netinet/in.h>
+     
+#include <stdio.h>
+#include <signal.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <sys/wait.h>
+
+#ifdef KERBEROS
+#include <krb5.h>
+#include <k5-util.h>
+#include <com_err.h>
+
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+
+#include "defines.h"
+
+#define RCP_BUFSIZ 4096
+     
+int sock;
+struct sockaddr_in local, foreign; /* set up by kcmd used by v4_send_auth */
+char *krb_realm = NULL;
+char *krb_cache = NULL;
+char *krb_config = NULL;
+krb5_encrypt_block eblock;         /* eblock for encrypt/decrypt */
+krb5_context bsd_context;
+
+#ifdef KRB5_KRB4_COMPAT
+Key_schedule v4_schedule;
+CREDENTIALS v4_cred;
+KTEXT_ST v4_ticket;
+MSG_DAT v4_msg_data;
+#endif
+
+void	v4_send_auth(char *, char *), try_normal(char **);
+char	**save_argv(int, char **);
+#ifndef HAVE_STRSAVE
+char	*strsave();
+#endif
+int	rcmd_stream_write(), rcmd_stream_read();
+void 	usage(void), sink(int, char **),
+    source(int, char **), rsource(char *, struct stat *), verifydir(char *), 
+    answer_auth(char *, char *);
+int	response(void), hosteq(char *, char *), okname(char *), 
+    susystem(char *);
+int	encryptflag = 0;
+
+#ifndef UCB_RCP
+#define	UCB_RCP	"/bin/rcp"
+#endif
+
+#endif /* KERBEROS */
+
+int	rem;
+char	*colon(char *);
+int	errs;
+krb5_sigtype	lostconn(int);
+int	iamremote, targetshouldbedirectory;
+int	iamrecursive;
+int	pflag;
+int	forcenet;
+struct	passwd *pwd;
+int	userid;
+int	port = 0;
+
+struct buffer {
+    unsigned int cnt;
+    char	*buf;
+};
+
+struct buffer *allocbuf(struct buffer *, int, int);
+
+#define	NULLBUF	(struct buffer *) 0
+  
+void 	error (char *fmt, ...)
+#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
+       __attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+     ;
+
+#define	ga()	 	(void) rcmd_stream_write(rem, "", 1, 0)
+
+int main(argc, argv)
+     int argc;
+     char **argv;
+{
+    char *targ, *host, *src;
+    char *suser, *tuser, *thost;
+    int i;
+    unsigned int cmdsiz = 30;
+    char buf[RCP_BUFSIZ], cmdbuf[30];
+    char *cmd = cmdbuf;
+    struct servent *sp;
+    static char curhost[256];
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+#ifdef KERBEROS
+    krb5_flags authopts;
+    krb5_error_code status;	
+    int euid;
+    char **orig_argv = save_argv(argc, argv);
+    krb5_auth_context auth_context;
+    enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
+
+    status = krb5_init_context(&bsd_context);
+    if (status) {
+	    com_err(argv[0], status, "while initializing krb5");
+	    exit(1);
+    }
+#endif
+
+    pwd = getpwuid(userid = getuid());
+    if (pwd == 0) {
+	fprintf(stderr, "who are you?\n");
+	exit(1);
+    }
+    
+    for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
+	(*argv)++;
+	while (**argv) switch (*(*argv)++) {
+	    
+	  case 'r':
+	    iamrecursive++;
+	    break;
+	    
+	  case 'p':		/* preserve mtimes and atimes */
+	    pflag++;
+	    break;
+	    
+	  case 'D':
+	    argc--, argv++;
+	    if (argc == 0)
+	      usage();
+	    port = htons(atoi(*argv));
+	    goto next_arg;
+
+	  case 'N':
+	    forcenet++;
+	    break;
+
+#ifdef KERBEROS
+	  case 'x':
+	    encryptflag++;
+	    break;
+	  case 'k':		/* Change kerberos realm */
+	    argc--, argv++;
+	    if (argc == 0) 
+	      usage();
+	    if(!(krb_realm = (char *)malloc(strlen(*argv) + 1))){
+		fprintf(stderr, "rcp: Cannot malloc.\n");
+		exit(1);
+	    }
+	    strcpy(krb_realm, *argv);	
+	    goto next_arg;
+	  case 'c':		/* Change default ccache file */
+	    argc--, argv++;
+	    if (argc == 0) 
+	      usage();
+	    if(!(krb_cache = (char *)malloc(strlen(*argv) + 1))){
+		fprintf(stderr, "rcp: Cannot malloc.\n");
+		exit(1);
+	    }
+	    strcpy(krb_cache, *argv);	
+	    goto next_arg;
+	  case 'C':		/* Change default config file */
+	    argc--, argv++;
+	    if (argc == 0) 
+	      usage();
+	    if(!(krb_config = (char *)malloc(strlen(*argv) + 1))){
+		fprintf(stderr, "rcp: Cannot malloc.\n");
+		exit(1);
+	    }
+	    strcpy(krb_config, *argv);	
+	    goto next_arg;
+	  case 'P':
+	    if (!strcmp (*argv, "O"))
+		kcmd_proto = KCMD_OLD_PROTOCOL;
+	    else if (!strcmp (*argv, "N"))
+		kcmd_proto = KCMD_NEW_PROTOCOL;
+	    else
+		usage ();
+	    goto next_arg;
+#endif /* KERBEROS */
+	    /* The rest of these are not for users. */
+	  case 'd':
+	    targetshouldbedirectory = 1;
+	    break;
+	    
+	  case 'f':		/* "from" */
+	    iamremote = 1;
+	    rcmd_stream_init_normal();
+#if defined(KERBEROS)
+	    if (encryptflag)
+	      answer_auth(krb_config, krb_cache);
+#endif /* KERBEROS */
+
+	    (void) response();
+	    source(--argc, ++argv);
+	    exit(errs);
+	    
+	  case 't':		/* "to" */
+	    iamremote = 1;
+	    rcmd_stream_init_normal();
+#if defined(KERBEROS)
+	    if (encryptflag)
+	      answer_auth(krb_config, krb_cache);
+#endif /* KERBEROS */
+
+	    sink(--argc, ++argv);
+	    exit(errs);
+	    
+	  default:
+	    usage();
+	}
+      next_arg: ;
+    }
+    
+    if (argc < 2)
+      usage();
+    if (argc > 2)
+      targetshouldbedirectory = 1;
+    rem = -1;
+
+
+    if (port == 0) {
+#ifdef KERBEROS
+      sp = getservbyname("kshell", "tcp");
+#else
+      sp = getservbyname("shell", "tcp");
+#endif /* KERBEROS */
+    
+      if (sp == NULL) {
+#ifdef KERBEROS
+	fprintf(stderr, "rcp: kshell/tcp: unknown service\n");
+	try_normal(orig_argv);
+#else
+	fprintf(stderr, "rcp: shell/tcp: unknown service\n");
+	exit(1);
+#endif /* KERBEROS */
+      }
+      port = sp->s_port;
+    }
+
+#ifdef KERBEROS
+    if (krb_realm != NULL)
+	cmdsiz += strlen(krb_realm);
+    if (krb_cache != NULL)
+	cmdsiz += strlen(krb_cache);
+    if (krb_config != NULL)
+	cmdsiz += strlen(krb_config);
+
+    if ((cmd = (char *)malloc(cmdsiz)) == NULL) {
+	fprintf(stderr, "rcp: Cannot malloc.\n");
+	exit(1);
+    }
+    (void) sprintf(cmd, "%srcp %s%s%s%s%s%s%s%s%s",
+		   encryptflag ? "-x " : "",
+
+		   iamrecursive ? " -r" : "", pflag ? " -p" : "", 
+		   targetshouldbedirectory ? " -d" : "",
+		   krb_realm != NULL ? " -k " : "",
+		   krb_realm != NULL ? krb_realm : "",
+		   krb_cache != NULL ? " -c " : "",
+		   krb_cache != NULL ? krb_cache : "",
+		   krb_config != NULL ? " -C " : "",
+		   krb_config != NULL ? krb_config : "");
+
+#else /* !KERBEROS */
+    (void) sprintf(cmd, "rcp%s%s%s",
+		   iamrecursive ? " -r" : "", pflag ? " -p" : "", 
+		   targetshouldbedirectory ? " -d" : "");
+#endif /* KERBEROS */
+    
+#ifdef POSIX_SIGNALS
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = lostconn;
+    (void) sigaction(SIGPIPE, &sa, (struct sigaction *)0);
+#else
+    (void) signal(SIGPIPE, lostconn);
+#endif
+    targ = colon(argv[argc - 1]);
+    
+    /* Check if target machine is the current machine. */
+    
+    gethostname(curhost, sizeof(curhost));
+    if (targ) {				/* ... to remote */
+	*targ++ = 0;
+	if (hosteq(argv[argc - 1], curhost)) {
+	    
+	    /* If so, pretend there wasn't even one given
+	     * check for an argument of just "host:", it
+	     * should become "."
+	     */
+	    
+	    if (*targ == 0) {
+		targ = ".";
+		argv[argc - 1] = targ;
+	    }
+	    else
+	      argv[argc - 1] = targ;
+	    targ = 0;
+	}
+    }
+    if (targ) {
+	/* Target machine is some remote machine */
+	if (*targ == 0)
+	  targ = ".";
+	thost = strchr(argv[argc - 1], '@');
+	if (thost) {
+	    *thost++ = 0;
+	    tuser = argv[argc - 1];
+	    if (*tuser == '\0')
+	      tuser = NULL;
+	    else if (!okname(tuser))
+	      exit(1);
+	} else {
+	    thost = argv[argc - 1];
+	    tuser = NULL;
+	}
+	for (i = 0; i < argc - 1; i++) {
+	    src = colon(argv[i]);
+	    if (src) {		/* remote to remote */
+		*src++ = 0;
+		if (*src == 0)
+		  src = ".";
+		host = strchr(argv[i], '@');
+		if (host) {
+		    *host++ = 0;
+		    suser = argv[i];
+		    if (*suser == '\0')
+		      suser = pwd->pw_name;
+		    else if (!okname(suser))
+		      continue;
+		    (void) sprintf(buf,
+#if defined(hpux) || defined(__hpux)
+				   "remsh %s -l %s -n %s %s '%s%s%s:%s'",
+#else
+				   "rsh %s -l %s -n %s %s '%s%s%s:%s'",
+#endif
+				   host, suser, cmd, src,
+				   tuser ? tuser : "",
+				   tuser ? "@" : "",
+				   thost, targ);
+	       } else
+		   (void) sprintf(buf,
+#if defined(hpux) || defined(__hpux)
+				  "remsh %s -n %s %s '%s%s%s:%s'",
+#else
+				  "rsh %s -n %s %s '%s%s%s:%s'",
+#endif
+				   argv[i], cmd, src,
+				   tuser ? tuser : "",
+				   tuser ? "@" : "",
+				   thost, targ);
+		(void) susystem(buf);
+	    } else {		/* local to remote */
+		krb5_creds *cred;
+		if (rem == -1) {
+		    (void) sprintf(buf, "%s -t %s",
+				   cmd, targ);
+		    host = thost;
+#ifdef KERBEROS
+		    authopts = AP_OPTS_MUTUAL_REQUIRED;
+		    status = kcmd(&sock, &host,
+				  port,
+				  pwd->pw_name,
+				  tuser ? tuser :
+				  pwd->pw_name,
+				  buf,
+				  0,
+				  "host",
+				  krb_realm,
+				  &cred,  
+				  0,  /* No seq # */
+				  0,  /* No server seq # */
+				  &local,
+				  &foreign,
+				  &auth_context, authopts,
+				  0, /* Not any port # */
+				  0,
+				  &kcmd_proto);
+		    if (status) {
+			if (kcmd_proto == KCMD_NEW_PROTOCOL)
+			    /* Don't fall back to less safe methods.  */
+			    exit (1);
+#ifdef KRB5_KRB4_COMPAT
+			fprintf(stderr, "Trying krb4 rcp...\n");
+			if (strncmp(buf, "-x rcp", 6) == 0)
+			    memcpy(buf, "rcp -x", 6);
+			status = k4cmd(&sock, &host, port,
+				       pwd->pw_name,
+				       tuser ? tuser : pwd->pw_name, buf,
+				       0, &v4_ticket, "rcmd", krb_realm,
+				       NULL, NULL, NULL,
+				       &local, &foreign, 0L, 0);
+			if (status)
+			    try_normal(orig_argv);
+			if (encryptflag)
+			    v4_send_auth(host, krb_realm);
+			rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
+					      0);
+#else
+			try_normal(orig_argv);
+#endif
+		    }
+		    else {
+			krb5_boolean similar;
+			krb5_keyblock *key = &cred->keyblock;
+
+			status = krb5_c_enctype_compare(bsd_context,
+							ENCTYPE_DES_CBC_CRC,
+							cred->keyblock.enctype,
+							&similar);
+			if (status)
+			    try_normal(orig_argv); /* doesn't return */
+
+			if (!similar) {
+			    status = krb5_auth_con_getsendsubkey (bsd_context,
+								  auth_context,
+								  &key);
+			    if ((status || !key) && encryptflag)
+				try_normal(orig_argv);
+			}
+			if (key == 0)
+			    key = &cred->keyblock;
+
+			rcmd_stream_init_krb5(key, encryptflag, 0, 1,
+					      kcmd_proto);
+		    }
+		    rem = sock;
+#else
+		    rem = rcmd(&host, port, pwd->pw_name,
+			       tuser ? tuser : pwd->pw_name,
+			       buf, 0);
+		    if (rem < 0)
+		      exit(1);
+#endif /* KERBEROS */
+		    if (response() < 0)
+		      exit(1);
+		}
+		source(1, argv+i);
+	    }
+	}
+    } else {				/* ... to local */
+	if (targetshouldbedirectory)
+	  verifydir(argv[argc - 1]);
+	for (i = 0; i < argc - 1; i++) {
+	    src = colon(argv[i]);
+	    /* Check if source machine is current machine */
+	    if (src) {
+		*src++ = 0;
+		if (hosteq(argv[i], curhost)) {
+		    
+		    /* If so, pretend src machine never given */
+		    
+		    if (*src == 0) {
+			error("rcp: no path given in arg: %s:\n",
+			      argv[i]);
+			errs++;
+			continue;
+		    }
+		    argv[i] = src;
+		    src = 0;
+		} else {
+		    /* not equiv, return colon */
+		    *(--src) = ':';
+		}
+	    }
+	    if (src == 0) {		/* local to local */
+		(void) sprintf(buf, "/bin/cp%s%s %s %s",
+			       iamrecursive ? " -r" : "",
+			       pflag ? " -p" : "",
+			       argv[i], argv[argc - 1]);
+		(void) susystem(buf);
+	    } else {		/* remote to local */
+		krb5_creds *cred;
+		*src++ = 0;
+		if (*src == 0)
+		  src = ".";
+		host = strchr(argv[i], '@');
+		if (host) {
+		    *host++ = 0;
+		    suser = argv[i];
+		    if (*suser == '\0')
+		      suser = pwd->pw_name;
+		    else if (!okname(suser))
+		      continue;
+		} else {
+		    host = argv[i];
+		    suser = pwd->pw_name;
+		}
+		(void) sprintf(buf, "%s -f %s", cmd, src);
+#ifdef KERBEROS
+		authopts = AP_OPTS_MUTUAL_REQUIRED;
+		status = kcmd(&sock, &host,
+			      port,
+			      pwd->pw_name,  suser,
+			      buf,
+			      0,
+			      "host",
+			      krb_realm,
+			      &cred,  
+			      0,  /* No seq # */
+			      0,  /* No server seq # */
+			      (struct sockaddr_in *) 0,
+			      &foreign,
+			      &auth_context, authopts,
+			      0, /* Not any port # */
+			      0,
+			      &kcmd_proto);
+		if (status) {
+			if (kcmd_proto == KCMD_NEW_PROTOCOL)
+			    /* Don't fall back to less safe methods.  */
+			    exit (1);
+#ifdef KRB5_KRB4_COMPAT
+			fprintf(stderr, "Trying krb4 rcp...\n");
+			if (strncmp(buf, "-x rcp", 6) == 0)
+			    memcpy(buf, "rcp -x", 6);
+			status = k4cmd(&sock, &host, port,
+				       pwd->pw_name, suser, buf,
+				       0, &v4_ticket, "rcmd", krb_realm,
+				       NULL, NULL, NULL,
+				       &local, &foreign, 0L, 0);
+			if (status)
+			    try_normal(orig_argv);
+			if (encryptflag)
+			    v4_send_auth(host, krb_realm);
+			rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
+					      0);
+#else
+			try_normal(orig_argv);
+#endif
+		} else {
+		    krb5_keyblock *key = &cred->keyblock;
+
+		    if (kcmd_proto == KCMD_NEW_PROTOCOL) {
+			status = krb5_auth_con_getsendsubkey (bsd_context,
+							      auth_context,
+							      &key);
+			if (status) {
+			    com_err (argv[0], status,
+				     "determining subkey for session");
+			    exit (1);
+			}
+			if (!key) {
+			    com_err (argv[0], 0,
+				     "no subkey negotiated for connection");
+			    exit (1);
+			}
+		    }
+
+		    rcmd_stream_init_krb5(key, encryptflag, 0, 1, kcmd_proto);
+		}
+		rem = sock; 
+				   
+		euid = geteuid();
+		if (euid == 0) {
+		    if (setuid(0)) {
+			perror("rcp setuid 0"); errs++; exit(errs);
+		    }
+		    if(krb5_seteuid(userid)) {
+			perror("rcp seteuid user"); errs++; exit(errs);
+		    }
+		}
+		sink(1, argv+argc-1);
+		if (euid == 0) {
+		    if(krb5_seteuid(0)) {
+			perror("rcp seteuid 0"); errs++; exit(errs);
+		    }
+		}
+#else
+		rem = rcmd(&host, port, pwd->pw_name, suser,
+			   buf, 0);
+		if (rem < 0)
+		  continue;
+		rcmd_stream_init_normal();
+#ifdef HAVE_SETREUID
+		if (setreuid(0, userid)) {
+		    perror("rcp setreuid 0,user"); errs++; exit(errs);
+		}
+		sink(1, argv+argc-1);
+		if (setreuid(userid, 0)) {
+		    perror("rcp setreuid user,0"); errs++; exit(errs);
+		}
+#else
+		if (setuid(0)) {
+		  perror("rcp setuid 0"); errs++; exit(errs);
+		}
+		if(seteuid(userid)) {
+		  perror("rcp seteuid user"); errs++; exit(errs);
+		}
+		sink(1, argv+argc-1);
+		if(seteuid(0)) {
+		  perror("rcp seteuid 0"); errs++; exit(errs);
+		}
+#endif
+#endif /* KERBEROS */
+		(void) close(rem);
+		rem = -1;
+	    }
+	}
+    }
+    exit(errs);
+}
+
+
+
+void verifydir(cp)
+     char *cp;
+{
+    struct stat stb;
+    
+    if (stat(cp, &stb) >= 0) {
+	if ((stb.st_mode & S_IFMT) == S_IFDIR)
+	  return;
+	errno = ENOTDIR;
+    }
+    error("rcp: %s: %s.\n", cp, error_message(errno));
+    exit(1);
+}
+
+
+
+char *colon(cp)
+     char *cp;
+{
+    
+    while (*cp) {
+	if (*cp == ':')
+	  return (cp);
+	if (*cp == '/')
+	  return (0);
+	cp++;
+    }
+    return (0);
+}
+
+
+
+int okname(cp0)
+     char *cp0;
+{
+    register char *cp = cp0;
+    register int c;
+    
+    do {
+	c = *cp;
+	if (c & 0200)
+	  goto bad;
+	if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
+	  goto bad;
+	cp++;
+    } while (*cp);
+    return (1);
+  bad:
+    fprintf(stderr, "rcp: invalid user name %s\n", cp0);
+    return (0);
+}
+
+
+
+int susystem(s)
+     char *s;
+{
+    int status;
+    pid_t pid, w;
+#ifdef POSIX_SIGNALS
+    struct sigaction sa, isa, qsa;
+#else
+    register krb5_sigtype (bsd_context, *istat)(), (*qstat)();
+#endif
+    
+    if ((pid = vfork()) == 0) {
+	execl("/bin/sh", "sh", "-c", s, (char *)0);
+	_exit(127);
+    }
+
+#ifdef POSIX_SIGNALS
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    (void) sigaction(SIGINT, &sa, &isa);
+    (void) sigaction(SIGQUIT, &sa, &qsa);
+#else
+    istat = signal(SIGINT, SIG_IGN);
+    qstat = signal(SIGQUIT, SIG_IGN);
+#endif
+    
+#ifdef HAVE_WAITPID
+    w = waitpid(pid, &status, 0);
+#else
+    while ((w = wait(&status)) != pid && w != -1) /*void*/ ;
+#endif
+    if (w == (pid_t)-1)
+      status = -1;
+
+#ifdef POSIX_SIGNALS
+    (void) sigaction(SIGINT, &isa, (struct sigaction *)0);
+    (void) sigaction(SIGQUIT, &qsa, (struct sigaction *)0);
+#else    
+    (void) signal(SIGINT, istat);
+    (void) signal(SIGQUIT, qstat);
+#endif
+    
+    return (status);
+}
+
+void source(argc, argv)
+     int argc;
+     char **argv;
+{
+    char *last, *name;
+    struct stat stb;
+    static struct buffer buffer;
+    struct buffer *bp;
+    int x, readerr, f;
+    unsigned int amt;
+    off_t i;
+    char buf[RCP_BUFSIZ];
+    
+    for (x = 0; x < argc; x++) {
+	name = argv[x];
+	if ((f = open(name, 0)) < 0) {
+	    error("rcp: %s: %s\n", name, error_message(errno));
+	    continue;
+	}
+	if (fstat(f, &stb) < 0)
+	  goto notreg;
+	switch (stb.st_mode&S_IFMT) {
+	    
+	  case S_IFREG:
+	    break;
+	    
+	  case S_IFDIR:
+	    if (iamrecursive) {
+		(void) close(f);
+		rsource(name, &stb);
+		continue;
+	    }
+	    /* fall into ... */
+	  default:
+	  notreg:
+	    (void) close(f);
+	    error("rcp: %s: not a plain file\n", name);
+	    continue;
+	}
+	last = strrchr(name, '/');
+	if (last == 0)
+	  last = name;
+	else
+	  last++;
+	if (pflag) {
+	    /*
+	     * Make it compatible with possible future
+	     * versions expecting microseconds.
+	     */
+	    (void) sprintf(buf, "T%ld 0 %ld 0\n",
+			   stb.st_mtime, stb.st_atime);
+	    (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
+	    if (response() < 0) {
+		(void) close(f);
+		continue;
+	    }
+	}
+	(void) sprintf(buf, "C%04o %ld %s\n",
+		       (int) stb.st_mode&07777, (long ) stb.st_size, last);
+	(void) rcmd_stream_write(rem, buf, strlen(buf), 0);
+	if (response() < 0) {
+	    (void) close(f);
+	    continue;
+	}
+	if ((bp = allocbuf(&buffer, f, RCP_BUFSIZ)) == NULLBUF) {
+	    (void) close(f);
+	    continue;
+	}
+	readerr = 0;
+	for (i = 0; i < stb.st_size; i += bp->cnt) {
+	    amt = bp->cnt;
+	    if (i + amt > stb.st_size)
+	      amt = stb.st_size - i;
+	    if (readerr == 0 && read(f, bp->buf, amt) != amt)
+	      readerr = errno;
+	    (void) rcmd_stream_write(rem, bp->buf, amt, 0);
+	}
+	(void) close(f);
+	if (readerr == 0)
+	  ga();
+	else
+	  error("rcp: %s: %s\n", name, error_message(readerr));
+	(void) response();
+    }
+}
+
+
+
+#ifndef USE_DIRENT_H
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#endif
+
+void rsource(name, statp)
+     char *name;
+     struct stat *statp;
+{
+    DIR *d = opendir(name);
+    char *last;
+#ifdef USE_DIRENT_H
+    struct dirent *dp;
+#else
+    struct direct *dp;
+#endif
+    char buf[RCP_BUFSIZ];
+    char *bufv[1];
+    
+    if (d == 0) {
+	error("rcp: %s: %s\n", name, error_message(errno));
+	return;
+    }
+    last = strrchr(name, '/');
+    if (last == 0)
+      last = name;
+    else
+      last++;
+    if (pflag) {
+	(void) sprintf(buf, "T%ld 0 %ld 0\n",
+		       statp->st_mtime, statp->st_atime);
+	(void) rcmd_stream_write(rem, buf, strlen(buf), 0);
+	if (response() < 0) {
+	    closedir(d);
+	    return;
+	}
+    }
+    (void) sprintf(buf, "D%04lo %d %s\n", (long) statp->st_mode&07777, 0, 
+		   last);
+    (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
+    if (response() < 0) {
+	closedir(d);
+	return;
+    }
+    while ((dp = readdir(d)) != NULL) {
+	if (dp->d_ino == 0)
+	  continue;
+	if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+	  continue;
+	if (strlen(name) + 1 + strlen(dp->d_name) >= RCP_BUFSIZ - 1) {
+	    error("%s/%s: Name too long.\n", name, dp->d_name);
+	    continue;
+	}
+	(void) sprintf(buf, "%s/%s", name, dp->d_name);
+	bufv[0] = buf;
+	source(1, bufv);
+    }
+    closedir(d);
+    (void) rcmd_stream_write(rem, "E\n", 2, 0);
+    (void) response();
+}
+
+
+
+int response()
+{
+    char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
+    if (rcmd_stream_read(rem, &resp, 1, 0) != 1)
+      lostconn(0);
+    switch (resp) {
+	
+      case 0:				/* ok */
+	return (0);
+	
+      default:
+	*cp++ = resp;
+	/* fall into... */
+      case 1:				/* error, followed by err msg */
+      case 2:				/* fatal error, "" */
+	do {
+	    if (rcmd_stream_read(rem, &c, 1, 0) != 1)
+	      lostconn(0);
+	    *cp++ = c;
+	} while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
+	if (iamremote == 0)
+	  (void) write(2, rbuf, (unsigned) (cp - rbuf));
+	errs++;
+	if (resp == 1)
+	  return (-1);
+	exit(1);
+    }
+    /*NOTREACHED*/
+}
+
+
+
+krb5_sigtype
+  lostconn(signumber)
+    int signumber;
+{
+    if (iamremote == 0)
+      fprintf(stderr, "rcp: lost connection\n");
+    exit(1);
+}
+
+
+#if !defined(HAVE_UTIMES)
+#include <utime.h>
+#include <sys/time.h>
+
+/*
+ * We emulate utimes() instead of utime() as necessary because
+ * utimes() is more powerful than utime(), and rcp actually tries to
+ * set the microsecond values; we don't want to take away
+ * functionality unnecessarily.
+ */
+int utimes(file, tvp)
+const char *file;
+struct timeval *tvp;
+{
+	struct utimbuf times;
+
+	times.actime = tvp[0].tv_sec;
+	times.modtime = tvp[1].tv_sec;
+	return(utime(file, ×));
+}
+#endif
+
+
+void sink(argc, argv)
+     int argc;
+     char **argv;
+{
+    mode_t mode;
+    mode_t mask = umask(0);
+    off_t i, j;
+    char *targ, *whopp, *cp;
+    int of, wrerr, exists, first;
+    off_t size;
+    unsigned int amt, count;
+    struct buffer *bp;
+    static struct buffer buffer;
+    struct stat stb;
+    int targisdir = 0;
+    char *myargv[1];
+    char cmdbuf[RCP_BUFSIZ], nambuf[RCP_BUFSIZ];
+    int setimes = 0;
+    struct timeval tv[2];
+#define atime	tv[0]
+#define mtime	tv[1]
+#define	SCREWUP(str)	{ whopp = str; goto screwup; }
+    
+    if (!pflag)
+      (void) umask(mask);
+    if (argc != 1) {
+	error("rcp: ambiguous target\n");
+	exit(1);
+    }
+    targ = *argv;
+    if (targetshouldbedirectory)
+      verifydir(targ);
+    ga();
+    if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
+      targisdir = 1;
+    for (first = 1; ; first = 0) {
+	cp = cmdbuf;
+	if (rcmd_stream_read(rem, cp, 1, 0) <= 0)
+	  return;
+	if (*cp++ == '\n')
+	  SCREWUP("unexpected '\\n'");
+	do {
+	    if (rcmd_stream_read(rem, cp, 1, 0) != 1)
+	      SCREWUP("lost connection");
+	} while (*cp++ != '\n');
+	*cp = 0;
+	if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
+	    if (iamremote == 0)
+	      (void) write(2, cmdbuf+1, strlen(cmdbuf+1));
+	    if (cmdbuf[0] == '\02')
+	      exit(1);
+	    errs++;
+	    continue;
+	}
+	*--cp = 0;
+	cp = cmdbuf;
+	if (*cp == 'E') {
+	    ga();
+	    return;
+	}
+	
+#define getnum(t) (t) = 0; while (isdigit((int) *cp)) (t) = (t) * 10 + (*cp++ - '0');
+	if (*cp == 'T') {
+	    setimes++;
+	    cp++;
+	    getnum(mtime.tv_sec);
+	    if (*cp++ != ' ')
+	      SCREWUP("mtime.sec not delimited");
+	    getnum(mtime.tv_usec);
+	    if (*cp++ != ' ')
+	      SCREWUP("mtime.usec not delimited");
+	    getnum(atime.tv_sec);
+	    if (*cp++ != ' ')
+	      SCREWUP("atime.sec not delimited");
+	    getnum(atime.tv_usec);
+	    if (*cp++ != '\0')
+	      SCREWUP("atime.usec not delimited");
+	    ga();
+	    continue;
+	}
+	if (*cp != 'C' && *cp != 'D') {
+	    /*
+	     * Check for the case "rcp remote:foo\* local:bar".
+	     * In this case, the line "No match." can be returned
+	     * by the shell before the rcp command on the remote is
+	     * executed so the ^Aerror_message convention isn't
+	     * followed.
+	     */
+	    if (first) {
+		error("%s\n", cp);
+		exit(1);
+	    }
+	    SCREWUP("expected control record");
+	}
+	cp++;
+	mode = 0;
+	for (; cp < cmdbuf+5; cp++) {
+	    if (*cp < '0' || *cp > '7')
+	      SCREWUP("bad mode");
+	    mode = (mode << 3) | (*cp - '0');
+	}
+	if (*cp++ != ' ')
+	  SCREWUP("mode not delimited");
+	size = 0;
+	while (isdigit((int) *cp))
+	  size = size * 10 + (*cp++ - '0');
+	if (*cp++ != ' ')
+	  SCREWUP("size not delimited");
+	if (targisdir) {
+          if(strlen(targ) + strlen(cp) + 2 >= sizeof(nambuf))
+	    SCREWUP("target name too long");
+	  (void) sprintf(nambuf, "%s%s%s", targ,
+			 *targ ? "/" : "", cp);
+	} else {
+	  if (strlen(targ) + 1 >= sizeof (nambuf))
+	    SCREWUP("target name too long");
+	  (void) strncpy(nambuf, targ, sizeof(nambuf) - 1);
+	}
+	nambuf[sizeof(nambuf) - 1] = '\0';
+	exists = stat(nambuf, &stb) == 0;
+	if (cmdbuf[0] == 'D') {
+	    if (exists) {
+		if ((stb.st_mode&S_IFMT) != S_IFDIR) {
+		    errno = ENOTDIR;
+		    goto bad;
+		}
+		if (pflag)
+		  (void) chmod(nambuf, mode);
+	    } else if (mkdir(nambuf, mode) < 0)
+	      goto bad;
+	    myargv[0] = nambuf;
+	    sink(1, myargv);
+	    if (setimes) {
+		setimes = 0;
+		if (utimes(nambuf, tv) < 0)
+		  error("rcp: can't set times on %s: %s\n",
+			nambuf, error_message(errno));
+	    }
+	    continue;
+	}
+	if ((of = open(nambuf, O_WRONLY|O_CREAT, mode)) < 0) {
+	  bad:
+	    error("rcp: %s: %s\n", nambuf, error_message(errno));
+	    continue;
+	}
+	if (exists && pflag) {
+#ifdef NOFCHMOD
+	    (void) chmod(nambuf, mode);
+#else
+	    (void) fchmod(of, mode);
+#endif
+	}
+	ga();
+	if ((bp = allocbuf(&buffer, of, RCP_BUFSIZ)) == NULLBUF) {
+	    (void) close(of);
+	    continue;
+	}
+	cp = bp->buf;
+	count = 0;
+	wrerr = 0;
+	for (i = 0; i < size; i += RCP_BUFSIZ) {
+	    amt = RCP_BUFSIZ;
+	    if (i + amt > size)
+	      amt = size - i;
+	    count += amt;
+	    do {
+		j = rcmd_stream_read(rem, cp, amt, 0);
+		if (j <= 0) {
+		    if (j == 0)
+		      error("rcp: dropped connection");
+		    else
+		      error("rcp: %s\n", error_message(errno));
+		    exit(1);
+		}
+		amt -= j;
+		cp += j;
+	    } while (amt > 0);
+	    if (count == bp->cnt) {
+		if (wrerr == 0 &&
+		    write(of, bp->buf, count) != count)
+		  wrerr++;
+		count = 0;
+		cp = bp->buf;
+	    }
+	}
+	if (count != 0 && wrerr == 0 &&
+	    write(of, bp->buf, count) != count)
+	  wrerr++;
+	if (ftruncate(of, size))
+	  error("rcp: can't truncate %s: %s\n", nambuf, error_message(errno));
+	(void) close(of);
+	(void) response();
+	if (setimes) {
+	    setimes = 0;
+	    if (utimes(nambuf, tv) < 0)
+	      error("rcp: can't set times on %s: %s\n",
+		    nambuf, error_message(errno));
+	}				   
+	if (wrerr)
+	  error("rcp: %s: %s\n", nambuf, error_message(errno));
+	else
+	  ga();
+    }
+  screwup:
+    error("rcp: protocol screwup: %s\n", whopp);
+    exit(1);
+}
+
+
+
+struct buffer *allocbuf(bp, fd, blksize)
+     struct buffer *bp;
+     int fd, blksize;
+{
+    struct stat stb;
+    int size;
+    
+    if (fstat(fd, &stb) < 0) {
+	error("rcp: fstat: %s\n", error_message(errno));
+	return (NULLBUF);
+    }
+
+    size = blksize;
+    if (bp->cnt < size) {
+	if (bp->buf != 0)
+	  free(bp->buf);
+	bp->buf = (char *)malloc((unsigned) size);
+	if (bp->buf == 0) {
+	    error("rcp: malloc: out of memory\n");
+	    return (NULLBUF);
+	}
+    }
+    bp->cnt = size;
+    return (bp);
+}
+
+void
+#ifdef HAVE_STDARG_H
+error(char *fmt, ...)
+#else
+/*VARARGS1*/
+error(fmt, va_alist)
+     char *fmt;
+     va_dcl
+#endif
+{
+    va_list ap;
+    char buf[RCP_BUFSIZ], *cp = buf;
+
+#ifdef HAVE_STDARG_H
+    va_start(ap, fmt);
+#else
+    va_start(ap);
+#endif
+
+    errs++;
+    *cp++ = 1;
+    (void) vsprintf(cp, fmt, ap);
+    va_end(ap);
+
+    if (iamremote)
+      (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
+    else
+      (void) write(2, buf+1, strlen(buf+1));
+}
+
+
+
+void usage()
+{
+#ifdef KERBEROS
+    fprintf(stderr,
+	    "Usage: \trcp [-PN | -PO] [-p] [-x] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-x] [-k realm] f1 ... fn d2\n");
+#else
+    fputs("usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n", stderr);
+#endif
+    exit(1);
+}
+
+
+
+int hosteq(h1, h2)
+     char *h1, *h2;
+{
+    struct hostent *h_ptr;
+    char hname1[256];
+    
+    if (forcenet)
+      return(0);
+
+    /* get the official names for the two hosts */
+    
+    if ((h_ptr = gethostbyname(h1)) == NULL)
+      return(0);
+    strncpy(hname1, h_ptr->h_name, sizeof (hname1));
+    hname1[sizeof (hname1) - 1] = '\0';
+    if ((h_ptr = gethostbyname(h2)) == NULL)
+      return(0);
+    
+    /*return if they are equal (strcmp returns 0 for equal - I return 1) */
+    
+    return(!strcmp(hname1, h_ptr->h_name));
+}
+
+
+
+#ifdef KERBEROS
+void try_normal(argv)
+     char **argv;
+{
+    register int i;
+#ifndef     KRB5_ATHENA_COMPAT
+    if (!encryptflag)
+#endif
+	{
+	fprintf(stderr,"trying normal rcp (%s)\n", UCB_RCP);
+	fflush(stderr);
+	/* close all but stdin, stdout, stderr */
+	for (i = getdtablesize(); i > 2; i--)
+	  (void) close(i);
+	execv(UCB_RCP, argv);
+	perror("exec");
+    }
+    exit(1);
+}
+
+
+
+char **save_argv(argc, argv)
+     int argc;
+     char **argv;
+{
+    register int i;
+    
+    char **local_argv = (char **)calloc((unsigned) argc+1,
+					(unsigned) sizeof(char *));
+    /* allocate an extra pointer, so that it is initialized to NULL
+       and execv() will work */
+    for (i = 0; i < argc; i++)
+      local_argv[i] = strsave(argv[i]);
+    return(local_argv);
+}
+
+
+
+#ifdef unicos61
+#define SIZEOF_INADDR  SIZEOF_in_addr
+#else
+#define SIZEOF_INADDR sizeof(struct in_addr)
+#endif
+
+
+/* This function is mostly vestigial, since under normal operation
+ * the -x flag doesn't get set for the server process for encrypted
+ * rcp.  It only gets called by beta clients attempting user-to-user
+ * authentication. */
+void
+  answer_auth(config_file, ccache_file)
+    char *config_file;
+    char *ccache_file;
+{
+    krb5_data pname_data, msg;
+    krb5_creds creds, *new_creds;
+    krb5_ccache cc;
+    krb5_error_code status;
+    krb5_auth_context auth_context = NULL;
+    
+    if (config_file) {
+    	const char * filenames[2];
+    	filenames[1] = NULL;
+    	filenames[0] = config_file;
+    	if ((status = krb5_set_config_files(bsd_context, filenames)))
+	    exit(1);
+    }
+    
+    memset ((char*)&creds, 0, sizeof(creds));
+
+    if ((status = krb5_read_message(bsd_context, (krb5_pointer)&rem,
+				    &pname_data)))
+	exit(1);
+    
+    if ((status = krb5_read_message(bsd_context, (krb5_pointer) &rem,
+				    &creds.second_ticket)))
+	exit(1);
+    
+    if (ccache_file == NULL) {
+    	if ((status = krb5_cc_default(bsd_context, &cc)))
+	    exit(1);
+    } else {
+	if ((status = krb5_cc_resolve(bsd_context, ccache_file, &cc)))
+	    exit(1);
+    }
+
+    if ((status = krb5_cc_get_principal(bsd_context, cc, &creds.client)))
+	exit(1);
+
+    if ((status = krb5_parse_name(bsd_context, pname_data.data,
+				  &creds.server)) )
+	exit(1);
+
+    krb5_free_data_contents(bsd_context, &pname_data);
+
+    if ((status = krb5_get_credentials(bsd_context, KRB5_GC_USER_USER, cc, 
+				       &creds, &new_creds)))
+	exit(1);
+
+    if ((status = krb5_mk_req_extended(bsd_context, &auth_context,
+				       AP_OPTS_USE_SESSION_KEY,
+				       NULL, new_creds, &msg)))
+	exit(1);
+    
+    if ((status = krb5_write_message(bsd_context, (krb5_pointer) &rem,
+				     &msg))) {
+    	krb5_free_data_contents(bsd_context, &msg);
+	exit(1);
+    }
+    
+    rcmd_stream_init_krb5(&new_creds->keyblock, encryptflag, 0, 0,
+			  KCMD_OLD_PROTOCOL);
+    
+    /* cleanup */
+    krb5_free_cred_contents(bsd_context, &creds);
+    krb5_free_creds(bsd_context, new_creds);
+    krb5_free_data_contents(bsd_context, &msg);
+
+    return;
+}
+
+
+
+char storage[2*RCP_BUFSIZ];		/* storage for the decryption */
+int nstored = 0;
+char *store_ptr = storage;
+
+#ifdef KRB5_KRB4_COMPAT
+void
+v4_send_auth(host,realm)
+char *host;
+char *realm;
+{
+	long authopts;
+
+	if ((realm == NULL) || (realm[0] == '\0'))
+	     realm = krb_realmofhost(host);
+	/* this needs to be sent again, because the
+	   rcp process needs the key.  the rshd has
+	   grabbed the first one. */
+	authopts = KOPT_DO_MUTUAL;
+	if ((rem = krb_sendauth(authopts, sock, &v4_ticket,
+				"rcmd", host,
+				realm, (unsigned long) getpid(),
+				&v4_msg_data,
+				&v4_cred, v4_schedule,
+				&local,
+				&foreign,
+				"KCMDV0.1")) != KSUCCESS) {
+		fprintf(stderr,
+			"krb_sendauth mutual fail: %s\n",
+			krb_get_err_text(rem));
+		exit(1);
+	}
+}
+#endif /* KRB5_KRB4_COMPAT */
+
+#endif /* KERBEROS */
diff --git a/krb5-1-6/src/appl/bsd/krlogin.c b/krb5-1-6/src/appl/bsd/krlogin.c
new file mode 100644
index 000000000..05913f607
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/krlogin.c
@@ -0,0 +1,1857 @@
+/*
+ *    appl/bsd/krlogin.c
+ */
+
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * 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\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)rlogin.c	5.12 (Berkeley) 9/19/88 */
+
+     
+     /*
+      * rlogin - remote login
+      */
+     
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#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
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef POSIX_TERMIOS
+#include <termios.h>
+#ifndef CNUL
+#define CNUL (char) 0
+#endif
+
+#else /* POSIX_TERMIOS */
+#include <sgtty.h>
+#endif /* POSIX_TERMIOS */
+
+#ifdef HAVE_SYS_SOCKIO_H
+/* for SIOCATMARK */
+#include <sys/sockio.h>
+#endif
+
+#ifdef HAVE_STREAMS
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#endif
+
+#ifdef __SCO__
+/* for TIOCPKT_* */
+#include <sys/spt.h>
+/* for struct winsize */
+#include <sys/ptem.h>
+#endif
+
+#ifdef HAVE_STREAMS
+#ifdef HAVE_SYS_PTYVAR_H
+#include <sys/tty.h>
+#include <sys/ttold.h>
+/* solaris actually uses packet mode, so the real macros are needed too */
+#include <sys/ptyvar.h>
+#endif
+#endif
+
+#ifndef TIOCPKT_NOSTOP
+/* These values are over-the-wire protocol, *not* local values */
+#define TIOCPKT_NOSTOP          0x10
+#define TIOCPKT_DOSTOP          0x20
+#define TIOCPKT_FLUSHWRITE      0x02
+#endif
+
+#ifdef HAVE_SYS_IOCTL_COMPAT_H
+#include <sys/ioctl_compat.h>
+#endif
+
+#ifdef CRAY
+#include <sys/ttold.h>
+#endif
+
+
+#ifdef KERBEROS
+#include <krb5.h>
+#include <com_err.h>
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+#include "defines.h"
+     
+#define RLOGIN_BUFSIZ 5120
+
+void try_normal();
+char *krb_realm = (char *)0;
+int encrypt_flag = 0;
+int fflag = 0, Fflag = 0;
+krb5_creds *cred;
+struct sockaddr_in local, foreign;
+krb5_context bsd_context;
+krb5_auth_context auth_context;
+
+#ifdef KRB5_KRB4_COMPAT
+Key_schedule v4_schedule;
+CREDENTIALS v4_cred;
+#endif
+
+#ifndef UCB_RLOGIN
+#define UCB_RLOGIN      "/usr/ucb/rlogin"
+#endif
+
+#include "rpaths.h"
+#endif /* KERBEROS */
+
+# ifndef TIOCPKT_WINDOW
+# define TIOCPKT_WINDOW 0x80
+# endif /* TIOCPKT_WINDOW */
+
+#ifndef ONOCR
+#define ONOCR 0
+#endif
+
+#ifdef POSIX_TERMIOS
+struct termios deftty;
+#endif
+
+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;
+int	null_local_username = 0;
+int	flow = 1;			/* Default is to allow flow
+					   control at the local terminal */
+int	flowcontrol;			/* Since emacs can alter the
+					   flow control characteristics
+					   of a session we need a
+					   variable to keep track of
+					   the original characteristics */
+int	confirm = 0;			/* ask if ~. is given before dying. */
+int	litout;
+#if defined(hpux) || defined(__hpux)
+char	*speeds[] =
+{ "0", "50", "75", "110", "134", "150", "200", "300", "600",
+    "900", "1200", "1800", "2400", "3600", "4800", "7200", "9600",
+    "19200", "38400", "EXTA", "EXTB" };
+#else
+/* Solaris note: There are higher values we could use.  But Casper Dik
+   <Casper.Dik@Holland.Sun.Com> mentions in article
+   <casper.938167062@uk-usenet.uk.sun.com> in comp.protocols.kerberos
+   on 1999-09-24 some problems in sending higher values to remote
+   systems (for non-Kerberos rlogind?).  So let's stick with this
+   list.  Even if our current klogind doesn't have the problems, older
+   versions are likely to.
+
+   Daniel S. Riley <dsr@mail.lns.cornell.edu> gives 57600, 76800,
+   115200, 153600, 230400, 307200, 460800 as the higher values.
+   (article <sh6711s713.fsf@lnscu4.lns.cornell.edu> in
+   comp.protocols.kerberos, 1999-09-23) */
+char    *speeds[] =
+{ "0", "50", "75", "110", "134", "150", "200", "300",
+    "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
+#endif
+char	term[256] = "network";
+
+#ifndef POSIX_SIGNALS
+#ifndef sigmask
+#define sigmask(m)    (1 << ((m)-1))
+#endif
+#endif /* POSIX_SIGNALS */
+
+#ifdef NO_WINSIZE
+struct winsize {
+    unsigned short ws_row, ws_col;
+    unsigned short ws_xpixel, ws_ypixel;
+};
+#endif /* NO_WINSIZE */
+int	dosigwinch = 0;
+struct	winsize winsize;
+
+char	*host=0;			/* external, so it can be
+					   reached from confirm_death() */
+
+krb5_sigtype	sigwinch (int);
+int server_message (int);
+void oob (void);
+krb5_sigtype	lostpeer (int);
+void setsignal (int sig, krb5_sigtype (*act)());
+static int read_wrapper(int fd, char *buf, int size, int *got_esc);
+static void prf(char *f);
+void try_normal(char **);
+static void mode(int);
+#ifdef POSIX_SIGNALS
+static int reader(sigset_t *);
+static void doit(sigset_t *);
+#else
+static int reader(int);
+static void doit(int);
+#endif
+static int control(char *, unsigned int);
+static void sendwindow(void);
+static void stop(int), echo(int);
+static void writer(void), done(int);
+static int confirm_death (void);
+
+
+/* to allow exits from signal handlers, without conflicting declarations */
+static krb5_sigtype exit_handler() {
+  exit(1);
+}
+
+
+/*
+ * The following routine provides compatibility (such as it is)
+ * between 4.2BSD Suns and others.  Suns have only a `ttysize',
+ * so we convert it to a winsize.
+ */
+#ifdef TIOCGWINSZ
+#define get_window_size(fd, wp)       ioctl(fd, TIOCGWINSZ, wp)
+#else
+#ifdef SYSV
+#ifndef SIGWINCH
+#define SIGWINCH SIGWINDOW
+#endif
+struct ttysize {
+    int ts_lines;
+    int ts_cols;
+};
+#define DEFAULT_LINES 24
+#define DEFAULT_COLS 80
+#endif
+
+
+
+int
+  get_window_size(fd, wp)
+int fd;
+struct winsize *wp;
+{
+    struct ttysize ts;
+    int error;
+#ifdef SYSV
+    char *envbuf;
+    ts.ts_lines = DEFAULT_LINES;
+    ts.ts_cols = DEFAULT_COLS;
+    if (( envbuf = getenv("LINES")) != (char *) 0)
+      ts.ts_lines = atoi(envbuf);
+    if (( envbuf = getenv("COLUMNS")) != (char *) 0)
+      ts.ts_cols = atoi(envbuf);
+#else
+    if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
+      return (error);
+#endif
+    
+    wp->ws_row = ts.ts_lines;
+    wp->ws_col = ts.ts_cols;
+    wp->ws_xpixel = 0;
+    wp->ws_ypixel = 0;
+    return (0);
+}
+#endif /* TIOCGWINSZ */
+
+
+#ifdef POSIX_TERMIOS
+/* Globals for terminal modes and flow control */
+struct  termios defmodes;
+struct  termios ixon_state;
+#else
+#ifdef USE_TERMIO
+/* Globals for terminal modes and flow control */
+struct  termio defmodes;
+struct  termio ixon_state;
+#endif
+#endif
+
+
+int
+main(argc, argv)
+     int argc;
+     char **argv;
+{
+    char *cp = (char *) NULL;
+#ifdef POSIX_TERMIOS
+    struct termios ttyb;
+#else
+#ifdef USE_TERMIO
+    struct termio ttyb;
+#else
+    struct sgttyb ttyb;
+#endif
+#endif
+    struct passwd *pwd;
+    struct servent *sp;
+    struct servent defaultservent;
+    int uid, options = 0;
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+    sigset_t *oldmask, omask, urgmask;
+#else
+    int oldmask;
+#endif
+    int on = 1;
+#ifdef KERBEROS
+    char **orig_argv = argv;
+    int sock;
+    krb5_flags authopts;
+    krb5_error_code status;
+#ifdef KRB5_KRB4_COMPAT
+    KTEXT_ST v4_ticket;
+    MSG_DAT v4_msg_data;
+    int v4only = 0;
+#endif
+#endif
+    int port, debug_port = 0;
+    enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
+
+    memset(&defaultservent, 0, sizeof(struct servent));
+    if (strrchr(argv[0], '/'))
+      argv[0] = strrchr(argv[0], '/')+1;
+
+    if ( argc < 2 ) goto usage;
+    argc--;
+    argv++;
+
+  another:
+    if (argc > 0 && host == 0 && strncmp(*argv, "-", 1)) {
+	host = *argv;
+	argv++, argc--;
+	goto another;
+    }
+
+    if (argc > 0 && !strcmp(*argv, "-D")) {
+	argv++; argc--;
+	if (*argv == NULL) {
+	    fprintf (stderr,
+		     "rlogin: -D flag must be followed by the debug port.\n");
+	    exit (1);
+	}
+	debug_port = htons(atoi(*argv));
+	argv++; argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-d")) {
+	argv++, argc--;
+	options |= SO_DEBUG;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-c")) {
+	confirm = 1;
+	argv++; argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-a")) {	   /* ask -- make remote */
+	argv++; argc--;			/* machine ask for password */
+	null_local_username = 1;	/* by giving null local user */
+	goto another;			/* id */
+    }
+    if (argc > 0 && !strcmp(*argv, "-t")) {
+	argv++; argc--;
+	if (argc == 0) goto usage;
+	cp = *argv++; argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-n")) {
+	no_local_escape = 1;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-7")) {  /* Pass only 7 bits */
+	eight = 0;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-noflow")) {
+	flow = 0;		/* Turn off local flow control so
+				   that ^S can be passed to emacs. */
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-l")) {
+	argv++, argc--;
+	if (argc == 0)
+	  goto usage;
+	name = *argv++; argc--;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-e", 2)) {
+	cmdchar = argv[0][2];
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-8")) {
+	eight = 1;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-L")) {
+	litout = 1;
+	argv++, argc--;
+	goto another;
+    }
+#ifdef KERBEROS
+    if (argc > 0 && !strcmp(*argv, "-k")) {
+	argv++, argc--;
+	if (argc == 0) {
+	    fprintf(stderr,
+		    "rlogin: -k flag must be followed with a realm name.\n");
+	    exit (1);
+	}
+	if(!(krb_realm = (char *)malloc(strlen(*argv) + 1))){
+	    fprintf(stderr, "rlogin: Cannot malloc.\n");
+	    exit(1);
+	}
+	strcpy(krb_realm, *argv);
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-x")) {
+	encrypt_flag++;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-f")) {
+	if (Fflag) {
+	    fprintf(stderr, "rlogin: Only one of -f and -F allowed\n");
+	    goto usage;
+	}
+	fflag++;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-F")) {
+	if (fflag) {
+	    fprintf(stderr, "rlogin: Only one of -f and -F allowed\n");
+	    goto usage;
+	}
+	Fflag++;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-PO")) {
+	kcmd_proto = KCMD_OLD_PROTOCOL;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-PN")) {
+	kcmd_proto = KCMD_NEW_PROTOCOL;
+	argv++, argc--;
+	goto another;
+    }
+#ifdef KRB5_KRB4_COMPAT
+    if (argc > 0 && !strcmp(*argv, "-4")) {
+	v4only++;
+	argv++, argc--;
+	goto another;
+    }
+#endif /* krb4 */
+#endif /* KERBEROS */
+    if (host == 0)
+      goto usage;
+    if (argc > 0)
+      goto usage;
+#ifdef KRB5_KRB4_COMPAT
+    if (kcmd_proto != KCMD_PROTOCOL_COMPAT_HACK && v4only) {
+	com_err (argv[0], 0,
+		 "-4 is incompatible with -PO/-PN");
+	exit(1);
+    }
+#endif
+    pwd = getpwuid(getuid());
+    if (pwd == 0) {
+	fprintf(stderr, "Who are you?\n");
+	exit(1);
+    }
+#ifdef KERBEROS
+    status = krb5_init_context(&bsd_context);
+    if (status) {
+	    com_err(argv[0], status, "while initializing krb5");
+	    exit(1);
+    }
+#endif
+
+
+    if (debug_port)
+      port = debug_port;
+    else {
+#ifdef KERBEROS
+    /*
+     * if there is an entry in /etc/services for Kerberos login,
+     * attempt to login with Kerberos. 
+     * If we fail at any step,  use the standard rlogin
+     */
+      if (encrypt_flag)
+	sp = getservbyname("eklogin","tcp");
+      else 
+	sp = getservbyname("klogin","tcp");
+      if (sp == 0) {
+		sp = &defaultservent;   /* ANL */
+		sp->s_port = encrypt_flag ? htons(2105) : htons(543);
+      }
+#else
+      sp = getservbyname("login", "tcp");
+      if (sp == 0) {
+	fprintf(stderr, "rlogin: login/tcp: unknown service\n");
+	exit(2);
+      }
+#endif /* KERBEROS */
+
+      port = sp->s_port;
+    }
+
+
+    if (cp == (char *) NULL) cp = getenv("TERM");
+    if (cp) {
+      (void) strncpy(term, cp, sizeof (term));
+      term[sizeof (term) - 1] = '\0';
+    }
+#ifdef POSIX_TERMIOS
+	if (tcgetattr(0, &ttyb) == 0) {
+		int ospeed = cfgetospeed (&ttyb);
+
+                term[sizeof(term) - 1] = '\0';
+		(void) strncat(term, "/", sizeof(term) - 1 - strlen(term));
+		if (ospeed >= 50)
+			/* On some systems, ospeed is the baud rate itself,
+			   not a table index.  */
+			sprintf (term + strlen (term), "%d", ospeed);
+		else if (ospeed >= sizeof(speeds)/sizeof(char*))
+			/* Past end of table, but not high enough to
+			   look like a real speed.  */
+			(void) strncat (term, speeds[sizeof(speeds)/sizeof(char*) - 1], sizeof(term) - 1 - strlen(term));
+		else {
+			(void) strncat(term, speeds[ospeed], sizeof(term) - 1 - strlen(term));
+		}
+                term[sizeof (term) - 1] = '\0';
+	}
+#else
+    if (ioctl(0, TIOCGETP, &ttyb) == 0) {
+	(void) strncat(term, "/", sizeof(term) - 1 - strlen(term));
+	(void) strncat(term, speeds[ttyb.sg_ospeed], sizeof(term) - 1 - strlen(term));
+    }
+#endif
+    (void) get_window_size(0, &winsize);
+    
+#ifdef POSIX_TERMIOS
+    tcgetattr(0, &defmodes);
+    tcgetattr(0, &ixon_state);
+#else
+#ifdef USE_TERMIO
+    /**** moved before rcmd call so that if get a SIGPIPE in rcmd **/
+    /**** we will have the defmodes set already. ***/
+    (void)ioctl(fileno(stdin), TIOCGETP, &defmodes);
+    (void)ioctl(fileno(stdin), TIOCGETP, &ixon_state);
+#endif
+#endif
+
+    /* Catch SIGPIPE, as that means we lost the connection */
+    /* will use SIGUSR1 for window size hack, so hold it off */
+#ifdef POSIX_SIGNALS
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = lostpeer;
+    (void) sigaction(SIGPIPE, &sa, (struct sigaction *)0);
+    
+    (void) sigemptyset(&urgmask);
+    (void) sigaddset(&urgmask, SIGUSR1);
+    oldmask = &omask;
+    (void) sigprocmask(SIG_BLOCK, &urgmask, oldmask);
+#else
+    (void) signal(SIGPIPE, lostpeer);
+#ifdef sgi
+    oldmask = sigignore( sigmask(SIGUSR1));
+#else
+    oldmask = sigblock( sigmask(SIGUSR1));
+#endif
+#endif /* POSIX_SIGNALS */
+
+#ifdef KERBEROS
+    authopts = AP_OPTS_MUTUAL_REQUIRED;
+
+    /* Piggy-back forwarding flags on top of authopts; */
+    /* they will be reset in kcmd */
+    if (fflag || Fflag)
+      authopts |= OPTS_FORWARD_CREDS;
+    if (Fflag)
+      authopts |= OPTS_FORWARDABLE_CREDS;
+
+#ifdef KRB5_KRB4_COMPAT
+    if (v4only)
+	goto try_v4;
+#endif
+    status = kcmd(&sock, &host, port,
+		  null_local_username ? "" : pwd->pw_name,
+		  name ? name : pwd->pw_name, term,
+		  0, "host", krb_realm,
+		  &cred,
+		  0,		/* No need for sequence number */
+		  0,		/* No need for server seq # */
+		  &local, &foreign,
+		  &auth_context, authopts,
+		  0,		/* Not any port # */
+		  0,
+		  &kcmd_proto);
+    if (status) {
+	if (kcmd_proto == KCMD_NEW_PROTOCOL && encrypt_flag)
+	    /* Don't fall back to something less secure.  */
+	    exit (1);
+#ifdef KRB5_KRB4_COMPAT
+	fprintf(stderr, "Trying krb4 rlogin...\n");
+    try_v4:
+	status = k4cmd(&sock, &host, port,
+		       null_local_username ? "" : pwd->pw_name,
+		       name ? name : pwd->pw_name, term,
+		       0, &v4_ticket, "rcmd", krb_realm,
+		       &v4_cred, v4_schedule, &v4_msg_data, &local, &foreign,
+		       (encrypt_flag) ? KOPT_DO_MUTUAL : 0L, 0);
+	if (status)
+	    try_normal(orig_argv);
+	rcmd_stream_init_krb4(v4_cred.session, encrypt_flag, 1, 1);
+#else
+	try_normal(orig_argv);
+#endif
+    } else {
+	krb5_keyblock *key = 0;
+
+	if (kcmd_proto == KCMD_NEW_PROTOCOL) {
+	    do_inband = 1;
+
+	    status = krb5_auth_con_getsendsubkey (bsd_context, auth_context,
+						  &key);
+	    if ((status || !key) && encrypt_flag)
+		try_normal(orig_argv);
+	}
+	if (key == 0)
+	    key = &cred->keyblock;
+
+	rcmd_stream_init_krb5(key, encrypt_flag, 1, 1, kcmd_proto);
+    }
+	
+    rem = sock;
+    
+#else
+    rem = rcmd(&host, port,
+	       null_local_username ? "" : pwd->pw_name,
+	       name ? name : pwd->pw_name, term, 0);
+#endif /* KERBEROS */
+
+    if (rem < 0)
+      exit(1);
+    
+    if (options & SO_DEBUG &&
+	setsockopt(rem, SOL_SOCKET, SO_DEBUG, (char*)&on, sizeof (on)) < 0)
+      perror("rlogin: setsockopt (SO_DEBUG)");
+    uid = getuid();
+    if (setuid(uid) < 0) {
+	perror("rlogin: setuid");
+	exit(1);
+    }
+    flowcontrol = flow;  /* Set up really correct non-volatile variable */
+    doit(oldmask);
+    /*NOTREACHED*/
+  usage:
+#ifdef KERBEROS
+    fprintf (stderr,
+	     "usage: rlogin host [-option] [-option...] [-k realm ] [-t ttytype] [-l username]\n");
+#ifdef KRB5_KRB4_COMPAT
+    fprintf (stderr, "     where option is e, 7, 8, noflow, n, a, x, f, F, c, 4, PO, or PN\n");
+#else
+    fprintf (stderr, "     where option is e, 7, 8, noflow, n, a, x, f, F, c, PO, or PN\n");
+#endif
+#else /* !KERBEROS */
+    fprintf (stderr,
+	     "usage: rlogin host [-option] [-option...] [-t ttytype] [-l username]\n");
+    fprintf (stderr, "     where option is e, 7, 8, noflow, n, a, or c\n");
+#endif /* KERBEROS */
+    exit(1);
+}
+
+
+
+static int confirm_death ()
+{
+    char hostname[33];
+    char input;
+    int answer;
+    if (!confirm) return (1);	/* no confirm, just die */
+    
+    if (gethostname (hostname, sizeof(hostname)-1) != 0)
+      strcpy (hostname, "???");
+    else
+      hostname[sizeof(hostname)-1] = '\0';
+    
+    fprintf (stderr, "\r\nKill session on %s from %s (y/n)?  ",
+	     host, hostname);
+    fflush (stderr);
+    if (read(0, &input, 1) != 1)
+      answer = EOF;	/* read from stdin */
+    else
+      answer = (int) input;
+    fprintf (stderr, "%c\r\n", answer);
+    fflush (stderr);
+    return (answer == 'y' || answer == 'Y' || answer == EOF ||
+	    answer == 4);	/* control-D */
+}
+
+
+
+#define CRLF "\r\n"
+
+int	child;
+krb5_sigtype	catchild (int);
+krb5_sigtype	writeroob (int);
+
+int	defflags, tabflag;
+int	deflflags;
+char	deferase, defkill;
+
+#ifdef USE_TERMIO
+char defvtim, defvmin;
+#if defined(hpux) || defined(__hpux)
+#include <sys/bsdtty.h>
+#include <sys/ptyio.h>
+#endif
+struct tchars {
+    char    t_intrc;        /* interrupt */
+    char    t_quitc;        /* quit */
+    char    t_startc;       /* start output */
+    char    t_stopc;        /* stop output */
+    char    t_eofc;         /* end-of-file */
+    char    t_brkc;         /* input delimiter (like nl) */
+};
+#endif
+
+
+#ifndef POSIX_TERMIOS
+#ifdef TIOCGLTC
+/*
+ * POSIX 1003.1-1988 does not define a 'suspend' character.
+ * POSIX 1003.1-1990 does define an optional VSUSP but not a VDSUSP character.
+ * Some termio implementations (A/UX, Ultrix 4.2) include both.
+ *
+ * However, since this is all derived from the BSD ioctl() and ltchars
+ * concept, all these implementations generally also allow for the BSD-style
+ * ioctl().  So we'll simplify the problem by only testing for the ioctl().
+ */
+struct	ltchars defltc;
+struct	ltchars noltc =	{ -1, -1, -1, -1, -1, -1 };
+#endif
+struct	tchars deftc;
+struct	tchars notc =	{ -1, -1, -1, -1, -1, -1 };
+#endif
+
+static void doit(oldmask)
+#ifdef POSIX_SIGNALS
+    sigset_t *oldmask;
+#else
+    int oldmask;
+#endif
+{
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+
+#ifdef POSIX_TERMIOS
+    (void) tcgetattr(0, &deftty);
+#ifdef VLNEXT
+    /* there's a POSIX way of doing this, but do we need it general? */
+    deftty.c_cc[VLNEXT] = 0;
+#endif
+#else
+#ifdef USE_TERMIO
+    struct termio sb;
+#else
+    struct sgttyb sb;
+#endif
+    
+    (void) ioctl(0, TIOCGETP, (char *)&sb);
+    defflags = sb.sg_flags;
+#ifdef USE_TERMIO
+    tabflag = sb.c_oflag & TABDLY;
+    defflags |= ECHO;
+    deferase = sb.c_cc[VERASE];
+    defkill = sb.c_cc[VKILL];
+    sb.c_cc[VMIN] = 1;
+    sb.c_cc[VTIME] = 1;
+    defvtim = sb.c_cc[VTIME];
+    defvmin = sb.c_cc[VMIN];
+    deftc.t_quitc = CQUIT;
+    deftc.t_startc = CSTART;
+    deftc.t_stopc = CSTOP ;
+    deftc.t_eofc = CEOF;
+    deftc.t_brkc =  '\n';
+#else
+    tabflag = defflags & TBDELAY;
+    defflags &= ECHO | CRMOD;
+    deferase = sb.sg_erase;
+    defkill = sb.sg_kill;
+    (void) ioctl(0, TIOCLGET, (char *)&deflflags);
+    (void) ioctl(0, TIOCGETC, (char *)&deftc);
+#endif
+
+    notc.t_startc = deftc.t_startc;
+    notc.t_stopc = deftc.t_stopc;
+    (void) ioctl(0, TIOCGLTC, (char *)&defltc);
+#endif
+#ifdef POSIX_SIGNALS
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    (void) sigaction(SIGINT, &sa, (struct sigaction *)0);
+#else
+    (void) signal(SIGINT, SIG_IGN);
+#endif
+
+    setsignal(SIGHUP, exit_handler);
+    setsignal(SIGQUIT, exit_handler);
+
+    child = fork();
+    if (child == -1) {
+	perror("rlogin: fork");
+	done(1);
+    }
+    if (child == 0) {
+	mode(1);
+	if (reader(oldmask) == 0) {
+	    prf("Connection closed.");
+	    exit(0);
+	}
+	sleep(1);
+	prf("\007Connection closed.");
+	exit(3);
+    }
+    
+#ifdef POSIX_SIGNALS
+    /* "sa" has already been initialized above. */
+
+    sa.sa_handler = writeroob;
+    (void) sigaction(SIGUSR1, &sa, (struct sigaction *)0);
+    
+    sigprocmask(SIG_SETMASK, oldmask, (sigset_t*)0);
+
+    sa.sa_handler = catchild;
+    (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+#else
+    (void) signal(SIGUSR1, writeroob);
+#ifndef sgi
+    (void) sigsetmask(oldmask);
+#endif
+    (void) signal(SIGCHLD, catchild);
+#endif /* POSIX_SIGNALS */
+    writer();
+    prf("Closed connection.");
+    done(0);
+}
+
+
+
+/*
+ * Trap a signal, unless it is being ignored.
+ */
+void
+setsignal(sig, act)
+     int sig;
+     krb5_sigtype (*act)();
+{
+#ifdef POSIX_SIGNALS
+    sigset_t omask, igmask;
+    struct sigaction sa;
+    
+    sigemptyset(&igmask);
+    sigaddset(&igmask, sig);
+    sigprocmask(SIG_BLOCK, &igmask, &omask);
+#else
+#ifdef sgi
+    int omask = sigignore(sigmask(sig));
+#else
+    int omask = sigblock(sigmask(sig));
+#endif
+#endif /* POSIX_SIGNALS */
+    
+#ifdef POSIX_SIGNALS
+    (void) sigaction(sig, (struct sigaction *)0, &sa);
+    if (sa.sa_handler != SIG_IGN) {
+	(void) sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	sa.sa_handler = act;
+	(void) sigaction(sig, &sa, (struct sigaction *)0);
+    }
+    sigprocmask(SIG_SETMASK, &omask, (sigset_t*)0);
+#else    
+    if (signal(sig, act) == SIG_IGN)
+	(void) signal(sig, SIG_IGN);
+#ifndef sgi
+    (void) sigsetmask(omask);
+#endif
+#endif
+}
+
+
+
+static void
+done(status)
+     int status;
+{
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+#ifndef HAVE_WAITPID
+    pid_t w;
+#endif
+    
+    mode(0);
+    if (child > 0) {
+	/* make sure catchild does not snap it up */
+#ifdef POSIX_SIGNALS
+	(void) sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	sa.sa_handler = SIG_DFL;
+	(void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+#else
+	(void) signal(SIGCHLD, SIG_DFL);
+#endif
+	
+	if (kill(child, SIGKILL) >= 0) {
+#ifdef HAVE_WAITPID
+	    (void) waitpid(child, 0, 0);
+#else
+	    while ((w = wait(0)) > 0 && w != child)
+		/*void*/;
+#endif
+	}
+    }
+    exit(status);
+}
+
+
+
+
+
+
+/*
+ * This is called when the reader process gets the out-of-band (urgent)
+ * request to turn on the window-changing protocol.
+ */
+krb5_sigtype
+  writeroob(signo)
+int signo;
+{
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+    
+    if (dosigwinch == 0) {
+	sendwindow();
+#ifdef POSIX_SIGNALS
+	(void) sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	sa.sa_handler = sigwinch;
+	(void) sigaction(SIGWINCH, &sa, (struct sigaction *)0);
+#else
+	(void) signal(SIGWINCH, sigwinch);
+#endif
+    }
+    dosigwinch = 1;
+}
+
+
+
+krb5_sigtype
+  catchild(signo)
+int signo;
+{
+#ifdef WAIT_USES_INT
+    int status;
+#else
+    union wait status;
+#endif
+    int pid;
+    
+  again:
+#ifdef HAVE_WAITPID
+    pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
+#else
+    pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
+#endif
+    if (pid == 0)
+      return;
+    /*
+     * if the child (reader) dies, just quit
+     */
+#ifdef WAIT_USES_INT
+    if (pid < 0 || (pid == child && !WIFSTOPPED(status)))
+      done(status);
+#else
+    if ((pid < 0) || ((pid == child) && (!WIFSTOPPED(status))))
+	done((int)(status.w_termsig | status.w_retcode));
+#endif
+    goto again;
+}
+
+
+
+/*
+ * writer: write to remote: 0 -> line.
+ * ~.	terminate
+ * ~^Z	suspend rlogin process.
+ * ~^Y  suspend rlogin process, but leave reader alone.
+ */
+static void writer()
+{
+    int n_read;
+    char buf[1024];
+    int got_esc; /* set to true by read_wrapper if an escape char
+		    was encountered */
+    char c;
+
+#ifdef ultrix             
+    fd_set waitread;
+    register n;
+    
+    /* we need to wait until the reader() has set up the terminal, else
+       the read() below may block and not unblock when the terminal
+       state is reset.
+       */
+    for (;;) {
+	FD_ZERO(&waitread);
+	FD_SET(0, &waitread);
+	n = select(1, &waitread, 0, 0, 0, 0);
+	if (n < 0 && errno == EINTR)
+	  continue;
+	if (n > 0)
+	  break;
+	else
+	  if (n < 0) {
+	      perror("select");
+	      break;
+	  }
+    }
+#endif /* ultrix */
+
+    /* This loop works as follows.  Call read_wrapper to get data until
+       we would block or until we read a cmdchar at the beginning of a line.
+       If got_esc is false, we just send everything we got back.  If got_esc 
+       is true, we send everything except the cmdchar at the end and look at 
+       the next char.  If its a "." we break out of the loop and terminate.
+       If its ^Z or ^Y we call stop with the value of the char and continue.
+       If its none of those, we send the cmdchar and then send the char we 
+       just read, unless that char is also the cmdchar (in which case we are
+       only supposed to send one of them).  When this loop ends, so does the
+       program.
+    */
+
+    for (;;) {
+
+      /* read until we would block or we get a cmdchar */
+      n_read = read_wrapper(0,buf,sizeof(buf),&got_esc);
+  
+      /* if read returns an error or 0 bytes, just quit */
+      if (n_read <= 0) {
+	break;
+      }
+      
+      if (!got_esc) {
+	if (rcmd_stream_write(rem, buf, (unsigned) n_read, 0) == 0) {
+	  prf("line gone");
+	  break;
+	}
+	continue;
+      }
+      else {
+	/* This next test is necessary to avoid sending 0 bytes of data
+	   in the event that we got just a cmdchar */
+	if (n_read > 1) {
+	  if (rcmd_stream_write(rem, buf, (unsigned) (n_read-1), 0) == 0) {
+	    prf("line gone");
+	    break;
+	  }
+	}
+	if (read_wrapper(0,&c,1,&got_esc) <= 0) {
+	  break;
+	}
+
+#ifdef POSIX_TERMIOS
+	if (c == '.' || c == deftty.c_cc[VEOF]) 
+#else
+	  if (c == '.' || c == deftc.t_eofc) 
+#endif
+	    {
+	      if (confirm_death()) {
+		echo(c);
+		break; 
+	      }
+	    }
+
+#ifdef POSIX_TERMIOS
+	if ( (
+	      (c == deftty.c_cc[VSUSP]) 
+#ifdef VDSUSP
+	      || (c == deftty.c_cc[VDSUSP]) 
+#endif
+	      )
+	     && !no_local_escape) {
+	  echo(c);
+	  stop(c);
+	  continue;
+	}
+#else /*POSIX_TERMIOS*/
+#ifdef TIOCGLTC
+	if ((c == defltc.t_suspc || c == defltc.t_dsuspc)
+	    && !no_local_escape) {
+	  echo(c);
+	  stop(c);
+	  continue;
+	}
+#endif /*TIOCGLTC*/
+#endif
+
+      
+	if (c != cmdchar) {
+	  rcmd_stream_write(rem, &cmdchar, 1, 0);
+	}
+
+	if (rcmd_stream_write(rem,&c,1,0) == 0) {
+	  prf("line gone");
+	  break;
+	}
+      }
+    }
+}
+
+/* This function reads up to size bytes from file desciptor fd into buf.
+   It will copy as much data as it can without blocking, but will never
+   copy more than size bytes.  In addition, if it encounters a cmdchar
+   at the beginning of a line, it will copy everything up to and including
+   the cmdchar, but nothing after that.  In this instance *esc_char is set
+   to true and any remaining data is buffered and copied on a subsequent 
+   call.  Otherwise, *esc_char will be set to false and the minimum of size,
+   1024, and the number of bytes that can be read without blocking will
+   be copied.  In all cases, a non-negative return value indicates the number 
+   of bytes actually copied and a return value of -1 indicates that there
+   was a read error (other than EINTR) and errno is set appropriately. 
+*/
+
+static int read_wrapper(fd,buf,size,got_esc) 
+     int fd;
+     char *buf;
+     int size;
+     int *got_esc;
+{
+  static char tbuf[1024];
+  static char *data_start = tbuf;
+  static char *data_end = tbuf;
+  static int bol = 1;
+  unsigned int return_length = 0;
+  char c;
+
+  /* if we have no data buffered, get more */
+  if (data_start == data_end) {
+    int n_read;
+    while ((n_read = read(fd, tbuf, sizeof(tbuf))) <= 0) {
+      if (n_read < 0 && errno == EINTR)
+	continue;
+      return n_read;
+    }
+    data_start = tbuf;
+    data_end = tbuf+n_read;
+  }
+
+  *got_esc = 0;
+
+  /* We stop when we've fully checked the buffer or have checked size
+     bytes.  We break out and set *got_esc if we encounter a cmdchar
+     at the beginning of a line.
+  */
+
+  while (data_start+return_length < data_end && return_length < size) {
+    
+    c = *(data_start+return_length);
+    return_length++;
+
+    if (bol == 1 && c == cmdchar) {
+      bol = 0;
+      *got_esc = 1;
+      break;
+    }
+
+#ifdef POSIX_TERMIOS
+    bol = (c == deftty.c_cc[VKILL] ||
+	   c == deftty.c_cc[VINTR] ||
+	   c == '\r' || c == '\n');
+	
+#else /* !POSIX_TERMIOS */
+    bol = c == defkill || c == deftc.t_eofc ||
+      c == deftc.t_intrc || c == defltc.t_suspc ||
+      c == '\r' || c == '\n';
+#endif
+  }
+   
+  memcpy(buf, data_start, return_length);
+  data_start = data_start + return_length;
+  return return_length;
+}
+
+static void echo(c)
+     register char c;
+{
+    char buf[8];
+    register char *p = buf;
+    
+    c &= 0177;
+    *p++ = cmdchar;
+    if (c < ' ') {
+	*p++ = '^';
+	*p++ = c + '@';
+    } else if (c == 0177) {
+	*p++ = '^';
+	*p++ = '?';
+    } else
+      *p++ = c;
+    *p++ = '\r';
+    *p++ = '\n';
+    (void) write(1, buf, (unsigned) (p - buf));
+}
+
+
+
+static void stop(cmdc)
+     char cmdc;
+{
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+    
+    mode(0);
+
+#ifdef POSIX_SIGNALS
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+#else
+    (void) signal(SIGCHLD, SIG_IGN);
+#endif
+    
+#ifdef POSIX_TERMIOS
+    (void) kill(cmdc == deftty.c_cc[VSUSP] ? 0 : getpid(), SIGTSTP);
+#else
+#ifdef TIOCGLTC
+    (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
+#endif
+#endif
+#ifdef POSIX_SIGNALS
+    sa.sa_handler = catchild;
+    (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+#else
+    (void) signal(SIGCHLD, catchild);
+#endif
+    
+    mode(1);
+    sigwinch(SIGWINCH);		/* check for size changes */
+}
+
+
+
+krb5_sigtype
+  sigwinch(signo)
+int signo;
+{
+    struct winsize ws;
+    
+    if (dosigwinch && get_window_size(0, &ws) == 0 &&
+	memcmp(&winsize, &ws, sizeof (ws))) {
+	winsize = ws;
+	sendwindow();
+    }
+}
+
+
+
+/*
+ * Send the window size to the server via the magic escape
+ */
+static void sendwindow()
+{
+    char obuf[4 + sizeof (struct winsize)];
+    struct winsize *wp = (struct winsize *)(void *)(obuf+4);
+    
+    obuf[0] = 0377;
+    obuf[1] = 0377;
+    obuf[2] = 's';
+    obuf[3] = 's';
+    wp->ws_row = htons(winsize.ws_row);
+    wp->ws_col = htons(winsize.ws_col);
+    wp->ws_xpixel = htons(winsize.ws_xpixel);
+    wp->ws_ypixel = htons(winsize.ws_ypixel);
+    (void) rcmd_stream_write(rem, obuf, sizeof(obuf), 0);
+}
+
+
+
+/*
+ * reader: read from remote: line -> 1
+ */
+#define	READING	1
+#define	WRITING	2
+
+char	rcvbuf[8 * 1024];
+int	rcvcnt;
+int	rcvstate;
+int	ppid;
+
+/* returns 1 if flush, 0 otherwise */
+
+int server_message(mark)
+     int mark;
+{
+#ifndef POSIX_TERMIOS
+    int out = FWRITE;
+#endif
+#ifdef POSIX_TERMIOS
+    struct termios tty;
+#else
+#ifdef USE_TERMIO
+    struct termio sb;
+#else
+    struct sgttyb sb;
+#endif
+#endif
+
+    if (mark & TIOCPKT_WINDOW) {
+	/*
+	 * Let server know about window size changes
+	 */
+	(void) kill(ppid, SIGUSR1);
+    }
+#ifdef POSIX_TERMIOS
+    if (!eight && (mark & TIOCPKT_NOSTOP)) {
+      (void) tcgetattr(0, &tty);
+      tty.c_iflag &= ~IXON;
+      (void) tcsetattr(0, TCSADRAIN, &tty);
+    }
+    if (!eight && (mark & TIOCPKT_DOSTOP)) {
+      (void) tcgetattr(0, &tty);
+      tty.c_iflag |= IXON;
+      (void) tcsetattr(0, TCSADRAIN, &tty);
+    }
+#else
+    if (!eight && (mark & TIOCPKT_NOSTOP)) {
+	(void) ioctl(0, TIOCGETP, (char *)&sb);
+#ifdef USE_TERMIO
+	sb.c_iflag |= IXOFF;
+	sb.sg_flags &= ~ICANON;
+#else
+	sb.sg_flags &= ~CBREAK;
+	sb.sg_flags |= RAW;
+	notc.t_stopc = -1;
+	notc.t_startc = -1;
+	(void) ioctl(0, TIOCSETC, (char *)¬c);
+#endif
+	(void) ioctl(0, TIOCSETN, (char *)&sb);
+    }
+    if (!eight && (mark & TIOCPKT_DOSTOP)) {
+	(void) ioctl(0, TIOCGETP, (char *)&sb);
+#ifdef USE_TERMIO
+	sb.sg_flags  |= ICANON;
+	sb.c_iflag |= IXON;
+#else
+	sb.sg_flags &= ~RAW;
+	sb.sg_flags |= CBREAK;
+	notc.t_stopc = deftc.t_stopc;
+	notc.t_startc = deftc.t_startc;
+	(void) ioctl(0, TIOCSETC, (char *)¬c);
+#endif
+	(void) ioctl(0, TIOCSETN, (char *)&sb);
+    }
+#endif
+    if (mark & TIOCPKT_FLUSHWRITE) {
+#ifdef POSIX_TERMIOS
+        (void) tcflush(1, TCOFLUSH);
+#else
+#ifdef  TIOCFLUSH
+	(void) ioctl(1, TIOCFLUSH, (char *)&out);
+#else
+	(void) ioctl(1, TCFLSH, 1);
+#endif
+#endif
+	return(1);
+    }
+
+    return(0);
+}
+
+void oob()
+{
+    char mark;
+    static char waste[RLOGIN_BUFSIZ];
+    int atmark, n;
+
+    mark = 0;
+    
+    recv(rem, &mark, 1, MSG_OOB);
+
+    if (server_message(mark)) {
+	for (;;) {
+	    if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
+		perror("ioctl");
+		return;
+	    }
+	    if (atmark)
+		break;
+	    n = read(rem, waste, sizeof (waste));
+	    if (n <= 0)
+		break;
+	}
+    }
+}
+
+/* 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.  */
+
+static int control(cp, n)
+     char *cp;
+     unsigned 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 
+ */
+static int 
+reader(oldmask)
+#ifdef POSIX_SIGNALS
+    sigset_t *oldmask;
+#else
+     int oldmask;
+#endif
+{
+    fd_set readset, excset, writeset;
+    int n, remaining;
+    unsigned int left;
+    char *bufp = rcvbuf;
+    char *cp;
+
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0);
+
+#else    
+    (void) signal(SIGTTOU, SIG_IGN);
+#endif
+    
+    ppid = getppid();
+    FD_ZERO(&readset);
+    FD_ZERO(&excset);
+    FD_ZERO(&writeset);
+#ifdef POSIX_SIGNALS
+    sigprocmask(SIG_SETMASK, oldmask, (sigset_t*)0);
+#else
+#ifndef sgi
+    (void) sigsetmask(oldmask);
+#endif
+#endif /* POSIX_SIGNALS */
+
+    for (;;) {
+	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);
+	}
+	if (!do_inband)
+	    FD_SET(rem,&excset);
+	if (select(rem+1, &readset, &writeset, &excset, 0) > 0 ) {
+	    if (!do_inband)
+		if (FD_ISSET(rem, &excset))
+		    oob();
+	    if (FD_ISSET(1,&writeset)) {
+		n = write(1, bufp, remaining);
+		if (n < 0) {
+		    if (errno != EINTR)
+			return (-1);
+		    continue;
+		}
+		bufp += n;
+	    }
+	    if (FD_ISSET(rem, &readset)) {
+	  	rcvcnt = rcmd_stream_read(rem, rcvbuf, sizeof (rcvbuf), 0);
+		if (rcvcnt == 0)
+		    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);
+			    /* |n| <= 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:
+	{
+	    if (errno == EINTR)
+	      continue;
+	    perror("read");
+	    return (-1);
+	}
+    }
+}
+
+
+
+static void mode(f)
+int f;
+{
+#ifdef POSIX_TERMIOS
+    struct termios newtty;
+#ifndef IEXTEN
+#define IEXTEN 0 /* No effect*/
+#endif
+#ifndef _POSIX_VDISABLE
+#define _POSIX_VDISABLE 0 /*A good guess at the disable-this-character character*/
+#endif
+
+    switch(f) {
+    case 0:
+	(void) tcsetattr(0, TCSADRAIN, &deftty);
+	break;
+    case 1:
+	(void) tcgetattr(0, &newtty);
+	/* was __svr4__ */
+#ifdef VLNEXT
+	/* there's a POSIX way of doing this, but do we need it general? */
+	newtty.c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+		
+	newtty.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN);
+	newtty.c_iflag &= ~(ISTRIP|INLCR|ICRNL);
+
+	if (!flow) {
+	    newtty.c_iflag &= ~(BRKINT|IXON|IXANY);
+	    newtty.c_oflag &= ~(OPOST);
+	} else {
+	    /* XXX - should we set ixon ? */
+	    newtty.c_iflag &= ~(IXON|IXANY);
+	    newtty.c_iflag |=  (BRKINT);
+	    newtty.c_oflag &= ~(ONLCR|ONOCR);
+	    newtty.c_oflag |=  (OPOST);
+	}
+#ifdef TABDLY
+	/* preserve tab delays, but turn off XTABS */
+	if ((newtty.c_oflag & TABDLY) == TAB3)
+	    newtty.c_oflag &= ~TABDLY;
+#endif
+	if (!eight)
+	    newtty.c_iflag |= ISTRIP;
+	if (litout)
+	    newtty.c_oflag &= ~OPOST;
+
+	newtty.c_cc[VMIN] = 1;
+	newtty.c_cc[VTIME] = 0;
+	(void) tcsetattr(0, TCSADRAIN, &newtty);
+	break;
+    default:
+	return;
+	/* NOTREACHED */
+    }
+#else
+    struct ltchars *ltc;
+#ifdef USE_TERMIO
+    struct termio sb;
+#else
+    struct tchars *tc;
+    struct sgttyb sb;
+    int	lflags;
+    (void) ioctl(0, TIOCLGET, (char *)&lflags);
+#endif
+    
+    (void) ioctl(0, TIOCGETP, (char *)&sb);
+    switch (f) {
+	
+    case 0:
+#ifdef USE_TERMIO
+	/*
+	**      remember whether IXON was set, so it can be restored
+	**      when mode(1) is next done
+	*/
+	(void) ioctl(fileno(stdin), TIOCGETP, &ixon_state);
+	/*
+	**      copy the initial modes we saved into sb; this is
+	**      for restoring to the initial state
+	*/
+	(void)memcpy(&sb, &defmodes, sizeof(defmodes));
+	
+#else
+	sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
+	sb.sg_flags |= defflags|tabflag;
+	sb.sg_kill = defkill;
+	sb.sg_erase = deferase;
+	lflags = deflflags;
+	tc = &deftc;
+#endif
+	ltc = &defltc;
+	break;
+	
+    case 1:
+#ifdef USE_TERMIO
+	/*
+	**      turn off output mappings
+	*/
+	sb.c_oflag &= ~(ONLCR|OCRNL);
+	/*
+	**      turn off canonical processing and character echo;
+	**      also turn off signal checking -- ICANON might be
+	**      enough to do this, but we're being careful
+	*/
+	sb.c_lflag &= ~(ECHO|ICANON|ISIG);
+	sb.c_cc[VTIME] = 1;
+	sb.c_cc[VMIN] = 1;
+	if (eight)
+	    sb.c_iflag &= ~(ISTRIP);
+#ifdef TABDLY
+	/* preserve tab delays, but turn off tab-to-space expansion */
+	if ((sb.c_oflag & TABDLY) == TAB3)
+	    sb.c_oflag &= ~TAB3;
+#endif
+	/*
+	**  restore current flow control state
+	*/
+	if ((ixon_state.c_iflag & IXON) && flow ) {
+	    sb.c_iflag |= IXON;
+	} else {
+	    sb.c_iflag &= ~IXON;
+	}
+#else /* ! USE_TERMIO */
+	sb.sg_flags &= ~(CBREAK|RAW);
+	sb.sg_flags |= (!flow ? RAW : CBREAK);
+	/* preserve tab delays, but turn off XTABS */
+	if ((sb.sg_flags & TBDELAY) == XTABS)
+	    sb.sg_flags &= ~TBDELAY;
+	sb.sg_kill = sb.sg_erase = -1;
+#ifdef LLITOUT
+	if (litout)
+	    lflags |= LLITOUT;
+#endif
+#ifdef LPASS8
+	if (eight)
+	    lflags |= LPASS8;
+#endif /* LPASS8 */
+	tc = ¬c;
+	sb.sg_flags &= ~defflags;
+#endif /* USE_TERMIO */
+	
+	ltc = &noltc;
+	break;
+	
+    default:
+	return;
+    }
+    (void) ioctl(0, TIOCSLTC, (char *)ltc);
+#ifndef USE_TERMIO
+    (void) ioctl(0, TIOCSETC, (char *)tc);
+    (void) ioctl(0, TIOCLSET, (char *)&lflags);
+#endif
+    (void) ioctl(0, TIOCSETN, (char *)&sb);
+#endif /* !POSIX_TERMIOS */
+}
+
+
+
+static void
+prf(f)
+     char *f;
+{
+    fprintf(stderr, f);
+    fprintf(stderr, CRLF);
+}
+
+
+
+#ifdef KERBEROS
+void try_normal(argv)
+     char **argv;
+{
+    register char *nhost;
+#ifdef POSIX_SIGNALS
+    sigset_t mask;
+#endif
+    
+#ifndef KRB5_ATHENA_COMPAT
+    if (encrypt_flag)
+      exit(1);
+#endif
+    fprintf(stderr,"trying normal rlogin (%s)\n",
+	    UCB_RLOGIN);
+    fflush(stderr);
+    
+    nhost = strrchr(argv[0], '/');
+    if (nhost)
+      nhost++;
+    else
+      nhost = argv[0];
+    if (!strcmp(nhost, "rlogin") || !strcmp(nhost, "rsh"))
+      argv[0] = UCB_RLOGIN;
+    
+#ifdef POSIX_SIGNALS
+    sigemptyset(&mask);
+    sigprocmask(SIG_SETMASK, &mask, NULL);
+#endif
+
+    execv(UCB_RLOGIN, argv);
+    perror("exec");
+    exit(1);
+}
+#endif
+
+
+
+krb5_sigtype lostpeer(signo)
+    int signo;
+{
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    (void) sigaction(SIGPIPE, &sa, (struct sigaction *)0);
+#else
+    (void) signal(SIGPIPE, SIG_IGN);
+#endif
+    
+    prf("\007Connection closed.");
+    done(1);
+}
diff --git a/krb5-1-6/src/appl/bsd/krlogind.c b/krb5-1-6/src/appl/bsd/krlogind.c
new file mode 100644
index 000000000..8387f18db
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/krlogind.c
@@ -0,0 +1,1575 @@
+/*
+ *	appl/bsd/krlogind.c
+ */
+
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * 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\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)rlogind.c	5.17 (Berkeley) 8/31/88 */
+     
+     /*
+      * remote login server:
+      *	remuser\0
+      *	locuser\0
+      *	terminal info\0
+      *	data
+      */
+     
+/*
+ * This is the rlogin daemon. The very basic protocol for checking 
+ * authentication and authorization is:
+ * 1) Check authentication.
+ * 2) Check authorization via the access-control files: 
+ *    ~/.k5login (using krb5_kuserok) and/or
+ * 3) Prompt for password if any checks fail, or if so configured.
+ * Allow login if all goes well either by calling the accompanying 
+ * login.krb5 or /bin/login, according to the definition of 
+ * DO_NOT_USE_K_LOGIN.l
+ * 
+ * The configuration is done either by command-line arguments passed by 
+ * inetd, or by the name of the daemon. If command-line arguments are
+ * present, they  take priority. The options are:
+ * -k means trust krb4 or krb5
+* -5 means trust krb5
+* -4 means trust krb4
+ * -p and -P means prompt for password.
+ *    If the -P option is passed, then the password is verified in 
+ * addition to all other checks. If -p is not passed with -k or -r,
+ * and both checks fail, then login permission is denied.
+ *    - -e means use encryption.
+ *
+ *    If no command-line arguments are present, then the presence of the 
+ * letters kKrRexpP in the program-name before "logind" determine the 
+ * behaviour of the program exactly as with the command-line arguments.
+ *
+ * If the ruserok check is to be used, then the client should connect
+ * from a privileged port, else deny permission.
+ */ 
+     
+/* DEFINES:
+ *   KERBEROS - Define this if application is to be kerberised.
+ *   CRYPT    - Define this if encryption is to be an option.
+ *   DO_NOT_USE_K_LOGIN - Define this if you want to use /bin/login
+ *              instead  of the accompanying login.krb5. 
+ *   KRB5_KRB4_COMPAT - Define this if v4 rlogin clients are also to be served.
+ *   ALWAYS_V5_KUSEROK - Define this if you want .k5login to be
+ *              checked even for v4 clients (instead of .klogin).
+ *   LOG_ALL_LOGINS - Define this if you want to log all logins.
+ *   LOG_OTHER_USERS - Define this if you want to log all principals
+ *              that do not map onto the local user.
+ *   LOG_REMOTE_REALM - Define this if you want to log all principals from 
+ *              remote realms.
+ *       Note:  Root logins are always logged.
+ */
+
+/*
+ * This is usually done in the Makefile.  Actually, these sources may
+ * not work without the KERBEROS #defined.
+ *
+ * #define KERBEROS
+ */
+#define LOG_REMOTE_REALM
+#define CRYPT
+#define USE_LOGIN_F
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef __SCO__
+#include <sys/unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef KERBEROS
+/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
+#include <sys/socket.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <pwd.h>
+     
+#ifdef HAVE_SYS_LABEL_H
+/* only SunOS 4? */
+#include <sys/label.h>
+#include <sys/audit.h>
+#include <pwdadj.h>
+#endif
+     
+#include <signal.h>
+
+#if defined(hpux) || defined(__hpux)
+#include <sys/ptyio.h>
+#endif
+#ifdef sysvimp
+#include <compat.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_STREAMS
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#endif
+
+#if defined(POSIX_TERMIOS) && !defined(ultrix)
+#include <termios.h>
+#else
+#include <sgtty.h>
+#endif
+
+#ifndef KERBEROS
+/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
+#include <netdb.h>
+#endif
+#include <syslog.h>
+#include <string.h>
+#include <sys/param.h>
+
+#ifdef HAVE_STREAMS
+/* krlogin doesn't test sys/tty... */
+#ifdef HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif
+
+#ifdef HAVE_SYS_PTYVAR_H
+/* Solaris actually uses packet mode, so the real macros are needed too */
+#include <sys/ptyvar.h>
+#endif
+#endif
+
+
+#ifndef TIOCPKT_NOSTOP
+/* These values are over-the-wire protocol, *not* local values */
+#define TIOCPKT_NOSTOP          0x10
+#define TIOCPKT_DOSTOP          0x20
+#define TIOCPKT_FLUSHWRITE      0x02
+#endif
+
+#ifdef HAVE_SYS_FILIO_H
+/* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
+#include <sys/filio.h>
+#endif
+
+#ifndef HAVE_KILLPG
+#define killpg(pid, sig) kill(-(pid), (sig))
+#endif
+
+#ifdef HAVE_PTSNAME
+/* HP/UX 9.04 has but does not declare ptsname.  */
+extern char *ptsname ();
+#endif
+
+#ifdef NO_WINSIZE
+struct winsize {
+    unsigned short ws_row, ws_col;
+    unsigned short ws_xpixel, ws_ypixel;
+};
+#endif /* NO_WINSIZE */
+     
+#ifndef roundup
+#define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
+#endif
+
+#include "fake-addrinfo.h"
+
+#ifdef KERBEROS
+     
+#include <krb5.h>
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+#include <libpty.h>
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#include <k5-util.h>
+#endif
+
+int auth_sys = 0;	/* Which version of Kerberos used to authenticate */
+
+#define KRB5_RECVAUTH_V4	4
+#define KRB5_RECVAUTH_V5	5
+
+int non_privileged = 0; /* set when connection is seen to be from */
+			/* a non-privileged port */
+
+#ifdef KRB5_KRB4_COMPAT
+AUTH_DAT	*v4_kdata;
+Key_schedule v4_schedule;
+#endif
+
+#include "com_err.h"
+#include "defines.h"
+     
+#define SECURE_MESSAGE  "This rlogin session is encrypting all data transmissions.\r\n"
+
+krb5_authenticator      *kdata;
+krb5_ticket     *ticket = 0;
+krb5_context bsd_context;
+krb5_ccache ccache = NULL;
+
+krb5_keytab keytab = NULL;
+
+#define ARGSTR	"k54ciepPD:S:M:L:fw:?"
+#else /* !KERBEROS */
+#define ARGSTR	"rpPD:f?"
+#endif /* KERBEROS */
+
+#ifndef LOGIN_PROGRAM
+#ifdef DO_NOT_USE_K_LOGIN
+#ifdef sysvimp
+#define LOGIN_PROGRAM "/bin/remlogin"
+#else
+#define LOGIN_PROGRAM "/bin/login"
+#endif
+#else /* DO_NOT_USE_K_LOGIN */
+#define LOGIN_PROGRAM KRB5_PATH_LOGIN
+#endif /* DO_NOT_USE_K_LOGIN */
+#endif /* LOGIN_PROGRAM */
+
+char *login_program = LOGIN_PROGRAM;
+
+#define MAXRETRIES 4
+#define MAX_PROG_NAME 16
+
+#ifndef UT_NAMESIZE	/* linux defines it directly in <utmp.h> */
+#define	UT_NAMESIZE	sizeof(((struct utmp *)0)->ut_name)
+#endif
+
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+
+#ifndef MAXDNAME
+#define MAXDNAME 256 /*per the rfc*/
+#endif
+
+char		lusername[UT_NAMESIZE+1];
+char		rusername[UT_NAMESIZE+1];
+char            *krusername = 0;
+char		term[64];
+char            rhost_name[MAXDNAME];
+char		rhost_addra[16];
+krb5_principal  client;
+int		do_inband = 0;
+
+int	reapchild();
+char 	*progname;
+
+static	int Pfd;
+
+#if defined(NEED_DAEMON_PROTO)
+extern int daemon(int, int);
+#endif
+
+#if (defined(_AIX) && defined(i386)) || defined(ibm032) || (defined(vax) && !defined(ultrix)) || (defined(SunOS) && SunOS > 40) || defined(solaris20)
+#define VHANG_FIRST
+#endif
+
+#if defined(ultrix)
+#define VHANG_LAST		/* vhangup must occur on close, not open */
+#endif
+
+void	fatal(int, const char *), fatalperror(int, const char *), doit(int, struct sockaddr *), usage(void), do_krb_login(char *, char *), getstr(int, char *, int, char *);
+void	protocol(int, int);
+int	princ_maps_to_lname(krb5_principal, char *), default_realm(krb5_principal);
+krb5_sigtype	cleanup(int);
+krb5_error_code recvauth(int *);
+
+/* There are two authentication related masks:
+   * auth_ok and auth_sent.
+* The auth_ok mask is the oring of authentication systems any one
+* of which can be used.  
+* The auth_sent mask is the oring of one or more authentication/authorization
+* systems that succeeded.  If the anding
+* of these two masks is true, then authorization is successful.
+*/
+#define AUTH_KRB4 (0x1)
+#define AUTH_KRB5 (0x2)
+int auth_ok = 0, auth_sent = 0;
+int do_encrypt = 0, passwd_if_fail = 0, passwd_req = 0;
+int checksum_required = 0, checksum_ignored = 0;
+
+int stripdomain = 1;
+int maxhostlen = 0;
+int always_ip = 0;
+
+int main(argc, argv)
+     int argc;
+     char **argv;
+{
+    extern int opterr, optind;
+    extern char * optarg;
+    int on = 1, ch;
+    socklen_t fromlen;
+    struct sockaddr_storage from;
+    int debug_port = 0;
+    int fd;
+    int do_fork = 0;
+#ifdef KERBEROS
+    krb5_error_code status;
+#endif
+    
+    progname = *argv;
+    
+    pty_init();
+    
+#ifndef LOG_NDELAY
+#define LOG_NDELAY 0
+#endif
+    
+#ifndef LOG_AUTH /* 4.2 syslog */
+    openlog(progname, LOG_PID | LOG_NDELAY);
+#else
+    openlog(progname, LOG_PID | LOG_NDELAY, LOG_AUTH);
+#endif /* 4.2 syslog */
+    
+#ifdef KERBEROS
+    status = krb5_init_context(&bsd_context);
+    if (status) {
+	    syslog(LOG_ERR, "Error initializing krb5: %s",
+		   error_message(status));
+	    exit(1);
+    }
+#endif
+    
+    /* Analyse parameters. */
+    opterr = 0;
+    while ((ch = getopt(argc, argv, ARGSTR)) != -1)
+      switch (ch) {
+#ifdef KERBEROS
+	case 'k':
+#ifdef KRB5_KRB4_COMPAT
+	auth_ok |= (AUTH_KRB5|AUTH_KRB4);
+#else
+	auth_ok |= AUTH_KRB5;
+#endif /* KRB5_KRB4_COMPAT*/
+	break;
+	
+      case '5':
+	  auth_ok |= AUTH_KRB5;
+	break;
+      case 'c':
+	checksum_required = 1;
+	break;
+      case 'i':
+	checksum_ignored = 1;
+	break;
+	
+#ifdef KRB5_KRB4_COMPAT
+      case '4':
+	auth_ok |= AUTH_KRB4;
+	break;
+#endif
+#ifdef CRYPT
+	case 'x':         /* Use encryption. */
+	case 'X':
+	case 'e':
+	case 'E':
+	  do_encrypt = 1;
+	  break;
+#endif
+	case 'S':
+	  if ((status = krb5_kt_resolve(bsd_context, optarg, &keytab))) {
+		  com_err(progname, status, "while resolving srvtab file %s",
+			  optarg);
+		  exit(2);
+	  }
+	  break;
+	case 'M':
+	  krb5_set_default_realm(bsd_context, optarg);
+	  break;
+#endif
+	case 'p':
+	  passwd_if_fail = 1; /* Passwd reqd if any check fails */
+	  break;
+	case 'P':         /* passwd is a must */
+	  passwd_req = 1;
+	  break;
+	case 'D':
+	  debug_port = atoi(optarg);
+	  break;
+	case 'L':
+	  login_program = optarg;
+	  break;
+        case 'f':
+	  do_fork = 1;
+	  break;
+	case 'w':
+	  if (!strcmp(optarg, "ip"))
+	    always_ip = 1;
+	  else {
+	    char *cp;
+	    cp = strchr(optarg, ',');
+	    if (cp == NULL)
+	      maxhostlen = atoi(optarg);
+	    else if (*(++cp)) {
+	      if (!strcmp(cp, "striplocal"))
+		stripdomain = 1;
+	      else if (!strcmp(cp, "nostriplocal"))
+		stripdomain = 0;
+	      else {
+		usage();
+		exit(1);
+	      }
+	      *(--cp) = '\0';
+	      maxhostlen = atoi(optarg);
+	    }
+	  }
+	  break;
+	case '?':
+	default:
+	  usage();
+	  exit(1);
+	  break;
+      }
+    argc -= optind;
+    argv += optind;
+    
+    fromlen = sizeof (from);
+
+    if (debug_port || do_fork) {
+	int s;
+	struct servent *ent;
+	struct sockaddr_in sock_in;
+
+	if (!debug_port) {
+	    if (do_encrypt) {
+		ent = getservbyname("eklogin", "tcp");
+		if (ent == NULL)
+		    debug_port = 2105;
+		else
+		    debug_port = ent->s_port;
+	    } else {
+		ent = getservbyname("klogin", "tcp");
+		if (ent == NULL)
+		    debug_port = 543;
+		else
+		    debug_port = ent->s_port;
+	    }
+	}
+	if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
+	    fprintf(stderr, "Error in socket: %s\n", strerror(errno));
+	    exit(2);
+	}
+	memset((char *) &sock_in, 0,sizeof(sock_in));
+	sock_in.sin_family = AF_INET;
+	sock_in.sin_port = htons(debug_port);
+	sock_in.sin_addr.s_addr = INADDR_ANY;
+
+	if (!do_fork)
+	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+			      (char *)&on, sizeof(on));
+
+	if ((bind(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) < 0) {
+	    fprintf(stderr, "Error in bind: %s\n", strerror(errno));
+	    exit(2);
+	}
+
+	if ((listen(s, 5)) < 0) {
+	    fprintf(stderr, "Error in listen: %s\n", strerror(errno));
+	    exit(2);
+	}
+
+	if (do_fork) {
+	    if (daemon(0, 0)) {
+		fprintf(stderr, "daemon() failed\n");
+		exit(2);
+	    }
+	    while (1) {
+		int child_pid;
+
+		fd = accept(s, (struct sockaddr *) &from, &fromlen);
+		if (s < 0) {
+		    if (errno != EINTR)
+			syslog(LOG_ERR, "accept: %s", error_message(errno));
+		    continue;
+		}
+		child_pid = fork();
+		switch (child_pid) {
+		case -1:
+		    syslog(LOG_ERR, "fork: %s", error_message(errno));
+		case 0:
+		    (void) close(s);
+		    doit(fd, (struct sockaddr *) &from);
+		    close(fd);
+		    exit(0);
+		default:
+		    wait(0);
+		    close(fd);
+		}
+	    }
+	}
+
+	if ((fd = accept(s, (struct sockaddr *) &from, &fromlen)) < 0) {
+	    fprintf(stderr, "Error in accept: %s\n", strerror(errno));
+	    exit(2);
+	}
+
+	close(s);
+    } else {			/* !do_fork && !debug_port */
+	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+	    syslog(LOG_ERR,"Can't get peer name of remote host: %m");
+#ifdef STDERR_FILENO
+	    fatal(STDERR_FILENO, "Can't get peer name of remote host");
+#else
+	    fatal(2, "Can't get peer name of remote host");
+#endif
+	}
+	fd = 0;
+    }
+
+    doit(fd, (struct sockaddr *) &from);
+    return 0;
+}
+
+
+
+#ifndef LOG_AUTH
+#define LOG_AUTH 0
+#endif
+
+int	child;
+int	netf;
+char	line[MAXPATHLEN];
+extern	char	*inet_ntoa();
+
+#ifdef TIOCSWINSZ
+struct winsize win = { 0, 0, 0, 0 };
+#endif
+
+int pid; /* child process id */
+
+void doit(f, fromp)
+  int f;
+  struct sockaddr *fromp;
+{
+    int p, t, on = 1;
+    char c;
+    char hname[NI_MAXHOST];
+    char buferror[255];
+    struct passwd *pwd;
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+    int retval;
+    char *rhost_sane;
+    int syncpipe[2];
+
+    netf = -1;
+    if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE,
+		   (const char *) &on, sizeof (on)) < 0)
+	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+    if (auth_ok == 0) {
+	syslog(LOG_CRIT, "No authentication systems were enabled; all connections will be refused.");
+	fatal(f, "All authentication systems disabled; connection refused.");
+    }
+
+    if (checksum_required&&checksum_ignored) {
+	syslog( LOG_CRIT, "Checksums are required and ignored; these options are mutually exclusive--check the documentation.");
+	fatal(f, "Configuration error: mutually exclusive options specified");
+    }
+    
+    alarm(60);
+    read(f, &c, 1);
+    
+    if (c != 0){
+	exit(1);
+    }
+
+    alarm(0);
+    /* Initialize syncpipe */
+    if (pipe( syncpipe ) < 0 )
+	fatalperror ( f , "");
+    
+
+#ifdef POSIX_SIGNALS
+    /* Initialize "sa" structure. */
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+#endif
+
+    retval = getnameinfo(fromp, socklen(fromp), hname, sizeof(hname), 0, 0,
+			 NI_NUMERICHOST);
+    if (retval)
+	fatal(f, gai_strerror(retval));
+    strncpy(rhost_addra, hname, sizeof(rhost_addra));
+    rhost_addra[sizeof (rhost_addra) -1] = '\0';
+    
+    retval = getnameinfo(fromp, socklen(fromp), hname, sizeof(hname), 0, 0, 0);
+    if (retval)
+	fatal(f, gai_strerror(retval));
+    strncpy(rhost_name, hname, sizeof(rhost_name));
+    rhost_name[sizeof (rhost_name) - 1] = '\0';
+
+#ifndef KERBEROS
+    if (fromp->sin_family != AF_INET)
+	/* Not a real problem, we just haven't bothered to update
+	   the port number checking code to handle ipv6.  */
+      fatal(f, "Permission denied - Malformed from address\n");
+    
+    if (fromp->sin_port >= IPPORT_RESERVED ||
+	fromp->sin_port < IPPORT_RESERVED/2)
+      fatal(f, "Permission denied - Connection from bad port");
+#endif /* KERBEROS */
+    
+    /* Set global netf to f now : we may need to drop everything
+       in do_krb_login. */
+    netf = f;
+    
+#if defined(KERBEROS)
+    /* All validation, and authorization goes through do_krb_login() */
+    do_krb_login(rhost_addra, rhost_name);
+#else
+    getstr(f, rusername, sizeof(rusername), "remuser");
+    getstr(f, lusername, sizeof(lusername), "locuser");
+    getstr(f, term, sizeof(term), "Terminal type");
+    rcmd_stream_init_normal();
+#endif
+    
+    write(f, "", 1);
+    if ((retval = pty_getpty(&p,line, sizeof(line)))) {
+	com_err(progname, retval, "while getting master pty");
+	exit(2);
+    }
+    
+    Pfd = p;
+#ifdef TIOCSWINSZ
+    (void) ioctl(p, TIOCSWINSZ, &win);
+#endif
+    
+#ifdef POSIX_SIGNALS
+    sa.sa_handler = cleanup;
+    (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+    (void) sigaction(SIGTERM, &sa, (struct sigaction *)0);
+#else
+    signal(SIGCHLD, cleanup);
+    signal(SIGTERM, cleanup);
+#endif
+    pid = fork();
+    if (pid < 0)
+      fatalperror(f, "");
+    if (pid == 0) {
+#if defined(POSIX_TERMIOS) && !defined(ultrix)
+	struct termios new_termio;
+#else
+	struct sgttyb b;
+#endif /* POSIX_TERMIOS */
+	if ((retval = pty_open_slave(line, &t))) {
+	    fatal(f, error_message(retval));
+	    exit(1);
+	}
+	
+
+#if defined(POSIX_TERMIOS) && !defined(ultrix)
+	tcgetattr(t,&new_termio);
+#if !defined(USE_LOGIN_F)
+	new_termio.c_lflag &= ~(ICANON|ECHO|ISIG|IEXTEN);
+	new_termio.c_iflag &= ~(IXON|IXANY|BRKINT|INLCR|ICRNL);
+#else
+	new_termio.c_lflag |= (ICANON|ECHO|ISIG|IEXTEN);
+	new_termio.c_oflag |= (ONLCR|OPOST);
+	new_termio.c_iflag |= (IXON|IXANY|BRKINT|INLCR|ICRNL);
+#endif /*Do we need binary stream?*/
+	new_termio.c_iflag &= ~(ISTRIP);
+	/* new_termio.c_iflag = 0; */
+	/* new_termio.c_oflag = 0; */
+	new_termio.c_cc[VMIN] = 1;
+	new_termio.c_cc[VTIME] = 0;
+	tcsetattr(t,TCSANOW,&new_termio);
+#else
+	(void)ioctl(t, TIOCGETP, &b);
+	b.sg_flags = RAW|ANYP;
+	(void)ioctl(t, TIOCSETP, &b);
+#endif /* POSIX_TERMIOS */
+
+	pid = 0;			/*reset pid incase exec fails*/
+	    
+	/*
+	 **      signal the parent that we have turned off echo
+	 **      on the slave side of the pty ... he's waiting
+	 **      because otherwise the rlogin protocol junk gets
+	 **      echo'd to the user (locuser^@remuser^@term/baud)
+	 **      and we don't get the right tty affiliation, and
+	 **      other kinds of hell breaks loose ...
+	 */
+	(void) write(syncpipe[1], &c, 1);
+	(void) close(syncpipe[1]);
+	(void) close(syncpipe[0]);
+		
+	close(f), close(p);
+	dup2(t, 0), dup2(t, 1), dup2(t, 2);
+	if (t > 2)
+	  close(t);
+	
+#if defined(sysvimp)
+	setcompat (COMPAT_CLRPGROUP | (getcompat() & ~COMPAT_BSDTTY));
+#endif
+	
+	/* Log access to account */
+	pwd = (struct passwd *) getpwnam(lusername);
+	if (pwd && (pwd->pw_uid == 0)) {
+	    if (passwd_req)
+	      syslog(LOG_NOTICE, "ROOT login by %s (%s@%s (%s)) forcing password access",
+		     krusername ? krusername : "",
+		     rusername, rhost_addra, rhost_name);
+	    else
+	      syslog(LOG_NOTICE, "ROOT login by %s (%s@%s (%s))", 
+		     krusername ? krusername : "",
+		     rusername, rhost_addra, rhost_name);
+	}
+#ifdef KERBEROS
+#if defined(LOG_REMOTE_REALM) && !defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
+	/* Log if principal is from a remote realm */
+        else if (client && !default_realm(client))
+#endif /* LOG_REMOTE_REALM */
+  
+#if defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS) 
+	/* Log if principal name does not map to local username */
+        else if (client && !princ_maps_to_lname(client, lusername))
+#endif /* LOG_OTHER_USERS */
+
+#if defined(LOG_ALL_LOGINS)
+        else
+#endif /* LOG_ALL_LOGINS */
+
+#if defined(LOG_REMOTE_REALM) || defined(LOG_OTHER_USERS) || defined(LOG_ALL_LOGINS)
+	{
+	    if (passwd_req)
+	      syslog(LOG_NOTICE,
+		     "login by %s (%s@%s (%s)) as %s forcing password access",
+		     krusername ? krusername : "", rusername,
+		     rhost_addra, rhost_name, lusername);
+	    else 
+	      syslog(LOG_NOTICE,
+		     "login by %s (%s@%s (%s)) as %s",
+		     krusername ? krusername : "", rusername,
+		     rhost_addra, rhost_name, lusername); 
+	}
+#endif /* LOG_REMOTE_REALM || LOG_OTHER_USERS || LOG_ALL_LOGINS */
+#endif /* KERBEROS */
+
+#ifndef NO_UT_PID
+	{
+
+	    pty_update_utmp(PTY_LOGIN_PROCESS, getpid(), "rlogin", line,
+			    ""/*host*/, PTY_TTYSLOT_USABLE);
+	}
+#endif
+
+#ifdef USE_LOGIN_F
+/* use the vendors login, which has -p and -f. Tested on 
+ * AIX 4.1.4 and HPUX 10 
+ */
+    {
+        char *cp;
+        if ((cp = strchr(term,'/')))
+            *cp = '\0';
+        setenv("TERM",term, 1);
+    }
+
+    retval = pty_make_sane_hostname((struct sockaddr *) fromp, maxhostlen,
+				    stripdomain, always_ip,
+				    &rhost_sane);
+    if (retval)
+        fatalperror(f, "failed make_sane_hostname");
+    if (passwd_req)
+        execl(login_program, "login", "-p", "-h", rhost_sane,
+          lusername, (char *)NULL);
+    else
+        execl(login_program, "login", "-p", "-h", rhost_sane,
+             "-f", lusername, (char *)NULL);
+#else /* USE_LOGIN_F */
+	execl(login_program, "login", "-r", rhost_sane, (char *)NULL);
+#endif /* USE_LOGIN_F */
+	syslog(LOG_ERR, "failed exec of %s: %s",
+	       login_program, error_message(errno));
+	fatalperror(f, login_program);
+	/*NOTREACHED*/
+    } /* if (pid == 0) */
+
+    /*
+     **      wait for child to start ... read one byte
+     **      -- see the child, who writes one byte after
+     **      turning off echo on the slave side ...
+     **      The master blocks here until it reads a byte.
+     */
+    
+(void) close(syncpipe[1]);
+    if (read(syncpipe[0], &c, 1) != 1) {
+	/*
+	 * Problems read failed ...
+	 */
+	sprintf(buferror, "Cannot read slave pty %s ",line);
+	fatalperror(p,buferror);
+    }
+    close(syncpipe[0]);
+
+    
+#if defined(KERBEROS) 
+    if (do_encrypt) {
+	if (rcmd_stream_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE), 0) < 0){
+	    sprintf(buferror, "Cannot encrypt-write network.");
+	    fatal(p,buferror);
+	}
+    }
+    else 
+      /*
+       * if encrypting, don't turn on NBIO, else the read/write routines
+       * will fail to work properly
+       */
+#endif /* KERBEROS */
+      ioctl(f, FIONBIO, &on);
+    ioctl(p, FIONBIO, &on);
+
+    /* FIONBIO doesn't always work on ptys, use fcntl to set O_NDELAY? */
+    (void) fcntl(p,F_SETFL,fcntl(p,F_GETFL,0) | O_NDELAY);
+
+#ifdef POSIX_SIGNALS
+    sa.sa_handler = SIG_IGN;
+    (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
+#else
+    signal(SIGTSTP, SIG_IGN);
+#endif
+
+    
+#if !defined(USE_LOGIN_F)
+    /* Pass down rusername and lusername to login. */
+    (void) write(p, rusername, strlen(rusername) +1);
+    (void) write(p, lusername, strlen(lusername) +1);
+    /* stuff term info down to login */
+    if ((write(p, term, strlen(term)+1) != (int) strlen(term)+1)) {
+	/*
+	 * Problems write failed ...
+	 */
+	sprintf(buferror,"Cannot write slave pty %s ",line);
+	fatalperror(f,buferror);
+    }
+
+#endif
+    protocol(f, p);
+    signal(SIGCHLD, SIG_IGN);
+    cleanup(0);
+}
+
+unsigned char	magic[2] = { 0377, 0377 };
+#ifdef TIOCSWINSZ
+#ifndef TIOCPKT_WINDOW
+#define TIOCPKT_WINDOW 0x80
+#endif
+unsigned char	oobdata[] = {TIOCPKT_WINDOW};
+#else
+char    oobdata[] = {0};
+#endif
+
+static 
+void 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), 0);
+	while (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+	    /* also shouldn't happen */
+	    sleep(5);
+	    cc = rcmd_stream_write(fd, message, sizeof(message), 0);
+	}
+    } 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
+ * window size changes.
+ */
+static int control(pty, cp, n)
+     int pty;
+     unsigned char *cp;
+     int n;
+{
+    struct winsize w;
+    int pgrp, got_pgrp;
+    
+    if (n < (int) 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
+      return (0);
+#ifdef TIOCSWINSZ
+    oobdata[0] &= ~TIOCPKT_WINDOW;	/* we know he heard */
+    memcpy((char *)&w,cp+4, sizeof(w));
+    w.ws_row = ntohs(w.ws_row);
+    w.ws_col = ntohs(w.ws_col);
+    w.ws_xpixel = ntohs(w.ws_xpixel);
+    w.ws_ypixel = ntohs(w.ws_ypixel);
+    (void)ioctl(pty, TIOCSWINSZ, &w);
+#ifdef HAVE_TCGETPGRP
+    pgrp = tcgetpgrp (pty);
+    got_pgrp = pgrp != -1;
+#else
+    got_pgrp = ioctl(pty, TIOCGPGRP, &pgrp) >= 0;
+#endif
+    if (got_pgrp)
+      (void) killpg(pgrp, SIGWINCH);
+#endif
+    return (4+sizeof (w));
+}
+
+
+
+/*
+ * rlogin "protocol" machine.
+ */
+void protocol(f, p)
+     int f, p;
+{
+    unsigned char pibuf[BUFSIZ], qpibuf[BUFSIZ*2], fibuf[BUFSIZ], *pbp=0, *fbp=0;
+    register int pcc = 0, fcc = 0;
+    int cc;
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+#ifdef TIOCPKT
+    register int tiocpkt_on = 0;
+    int on = 1;
+#endif
+    
+#if defined(TIOCPKT) && !(defined(__svr4__) || defined(HAVE_STREAMS)) \
+	|| defined(solaris20)
+    /* if system has TIOCPKT, try to turn it on. Some drivers
+     * may not support it. Save flag for later. 
+     */
+   if ( ioctl(p, TIOCPKT, &on) < 0)
+	tiocpkt_on = 0;
+   else tiocpkt_on = 1;
+#endif
+
+    /*
+     * Must ignore SIGTTOU, otherwise we'll stop
+     * when we try and set slave pty's window shape
+     * (our controlling tty is the master pty).
+     */
+#ifdef POSIX_SIGNALS
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0);
+#else
+    signal(SIGTTOU, SIG_IGN);
+#endif
+#ifdef TIOCSWINSZ
+    sendoob(f, oobdata);
+#endif
+    for (;;) {
+	fd_set ibits, obits, ebits;
+
+	FD_ZERO(&ibits);
+	FD_ZERO(&obits);
+	FD_ZERO(&ebits);
+
+	if (fcc)
+	    FD_SET(p, &obits);
+	else
+	    FD_SET(f, &ibits);
+	if (pcc >= 0) {
+	    if (pcc) {
+		FD_SET(f, &obits);
+	    } else {
+		FD_SET(p, &ibits);
+	    }
+	}
+
+	if (select(((p > f) ? p : f) + 1, &ibits, &obits, &ebits, 0) < 0) {
+	    if (errno == EINTR)
+	      continue;
+	    fatalperror(f, "select");
+	}
+#define	pkcontrol(c)	((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
+	if (FD_ISSET(f, &ibits)) {
+	    fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf), 0);
+	    if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+		fcc = 0;
+	    } else {
+		register unsigned char *cp;
+		int n;
+		size_t left;
+		
+		if (fcc <= 0)
+		    break;
+		fbp = fibuf;
+		
+		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--;
+			}
+		    }
+		}
+	    }
+	}
+	
+	if (FD_ISSET(p, &obits) && fcc > 0) {
+	    cc = write(p, fbp, fcc);
+	    if (cc > 0) {
+		fcc -= cc;
+		fbp += cc;
+	    }
+	}
+	
+	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;
+	    }
+#ifdef TIOCPKT
+	    else if (tiocpkt_on) {
+		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, 0);
+	    if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+		/* also shouldn't happen */
+		sleep(5);
+		continue;
+	    }
+	    if (cc > 0) {
+		pcc -= cc;
+		pbp += cc;
+	    }
+	}
+    }
+}
+
+
+
+krb5_sigtype cleanup(signumber)
+    int signumber;
+{
+    pty_cleanup (line, pid, 1);
+    shutdown(netf, 2);
+    if (ccache)
+	krb5_cc_destroy(bsd_context, ccache);
+    exit(1);
+}
+
+
+void fatal(f, msg)
+     int f;
+     const char *msg;
+{
+    char buf[512];
+    int out = 1 ;          /* Output queue of f */
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+    
+    buf[0] = '\01';		/* error indicator */
+    (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
+    if ((f == netf) && (pid > 0))
+      (void) rcmd_stream_write(f, buf, strlen(buf), 0);
+    else
+      (void) write(f, buf, strlen(buf));
+    syslog(LOG_ERR,"%s\n",msg);
+    if (pid > 0) {
+#ifdef POSIX_SIGNALS
+	(void) sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	sa.sa_handler = SIG_IGN;
+	(void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+#else
+	signal(SIGCHLD,SIG_IGN);
+#endif
+	kill(pid,SIGKILL);
+#ifdef  TIOCFLUSH
+	(void) ioctl(f, TIOCFLUSH, (char *)&out);
+#else
+	(void) ioctl(f, TCFLSH, out);
+#endif
+	cleanup(0);
+    }
+    exit(1);
+}
+
+
+
+void fatalperror(f, msg)
+     int f;
+     const char *msg;
+{
+    char buf[512];
+    
+    (void) sprintf(buf, "%s: %s", msg, error_message(errno));
+    fatal(f, buf);
+}
+
+#ifdef KERBEROS
+
+void
+do_krb_login(host_addr, hostname)
+     char *host_addr, *hostname;
+{
+    krb5_error_code status;
+    char *msg_fail = NULL;
+    int valid_checksum;
+
+    if (getuid()) {
+	exit(1);
+    }
+
+    /* Check authentication. This can be either Kerberos V5, */
+    /* Kerberos V4, or host-based. */
+    if ((status = recvauth(&valid_checksum))) {
+	if (ticket)
+	  krb5_free_ticket(bsd_context, ticket);
+	if (status != 255)
+	  syslog(LOG_ERR,
+		 "Authentication failed from %s (%s): %s\n",host_addr,
+		 hostname,error_message(status));
+	fatal(netf, "Kerberos authentication failed");
+	return;
+    }
+    
+    /* OK we have authenticated this user - now check authorization. */
+    /* The Kerberos authenticated programs must use krb5_kuserok or kuserok*/
+    
+#ifndef KRB5_KRB4_COMPAT
+    if (auth_sys == KRB5_RECVAUTH_V4) {
+	  fatal(netf, "This server does not support Kerberos V4");
+  }
+#endif
+    
+
+#if (defined(ALWAYS_V5_KUSEROK) || !defined(KRB5_KRB4_COMPAT))
+	/* krb5_kuserok returns 1 if OK */
+	if (client && krb5_kuserok(bsd_context, client, lusername))
+	  auth_sent |= ((auth_sys == KRB5_RECVAUTH_V4)?AUTH_KRB4:AUTH_KRB5);
+#else
+	if (auth_sys == KRB5_RECVAUTH_V4) {
+	    /* kuserok returns 0 if OK */
+	    if (!kuserok(v4_kdata, lusername))
+	      auth_sent |= AUTH_KRB4;
+	} else {
+	    /* krb5_kuserok returns 1 if OK */
+	    if (client && krb5_kuserok(bsd_context, client, lusername))
+	      auth_sent |= AUTH_KRB5;
+	}
+#endif
+
+    
+
+    if (checksum_required && !valid_checksum) {
+	if (auth_sent & AUTH_KRB5) {
+	    syslog(LOG_WARNING, "Client did not supply required checksum--connection rejected.");
+	
+	    fatal(netf, "You are using an old Kerberos5 without initial connection support; only newer clients are authorized.");
+	} else {
+	  syslog(LOG_WARNING,
+		 "Configuration error: Requiring checksums with -c is inconsistent with allowing Kerberos V4 connections.");
+	}
+    }
+    if (auth_ok&auth_sent) /* This should be bitwise.*/
+	return;
+    
+    if (ticket)
+	krb5_free_ticket(bsd_context, ticket);
+
+    if (krusername)
+	msg_fail = (char *)malloc(strlen(krusername) + strlen(lusername) + 80);
+    if (!msg_fail)
+	fatal(netf, "User is not authorized to login to specified account");
+
+    if (auth_sent)
+	sprintf(msg_fail, "Access denied because of improper credentials");
+    else
+	sprintf(msg_fail, "User %s is not authorized to login to account %s",
+		krusername, lusername);
+    
+    fatal(netf, msg_fail);
+    /* NOTREACHED */
+}
+
+#endif /* KERBEROS */
+
+
+
+void getstr(fd, buf, cnt, err)
+     int fd;
+     char *buf;
+     int cnt;
+     char *err;
+{
+    
+    char c;
+    
+    do {
+	if (read(fd, &c, 1) != 1) {
+	    exit(1);
+	}
+	if (--cnt < 0) {
+	    printf("%s too long\r\n", err);
+	    exit(1);
+	}
+	*buf++ = c;
+    } while (c != 0);
+}
+
+
+
+void usage()
+{
+#ifdef KERBEROS
+    syslog(LOG_ERR, 
+	   "usage: klogind [-ke45pPf] [-D port] [-w[ip|maxhostlen[,[no]striplocal]]] or [r/R][k/K][x/e][p/P]logind");
+#else
+    syslog(LOG_ERR, 
+	   "usage: rlogind [-rpPf] [-D port] or [r/R][p/P]logind");
+#endif
+}
+
+
+
+#ifdef KERBEROS
+
+#ifndef KRB_SENDAUTH_VLEN
+#define	KRB_SENDAUTH_VLEN 8	    /* length for version strings */
+#endif
+
+#define	KRB_SENDAUTH_VERS	"AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
+					      chars */
+
+krb5_error_code
+recvauth(valid_checksum)
+    int *valid_checksum;
+{
+    krb5_auth_context auth_context = NULL;
+    krb5_error_code status;
+    struct sockaddr_storage peersin, laddr;
+    socklen_t len;
+    krb5_data inbuf;
+#ifdef KRB5_KRB4_COMPAT
+    char v4_instance[INST_SZ];	/* V4 Instance */
+#endif
+    krb5_data version;
+    krb5_authenticator *authenticator;
+    krb5_rcache rcache;
+    enum kcmd_proto kcmd_proto;
+    krb5_keyblock *key;
+
+    *valid_checksum = 0;
+    len = sizeof(laddr);
+    if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
+	    exit(1);
+    }
+	
+    len = sizeof(peersin);
+    if (getpeername(netf, (struct sockaddr *)&peersin, &len)) {
+	syslog(LOG_ERR, "get peer name failed %d", netf);
+	exit(1);
+    }
+
+#ifdef KRB5_KRB4_COMPAT
+    strcpy(v4_instance, "*");
+#endif
+
+    if ((status = krb5_auth_con_init(bsd_context, &auth_context)))
+        return status;
+ 
+    /* Only need remote address for rd_cred() to verify client */
+    if ((status = krb5_auth_con_genaddrs(bsd_context, auth_context, netf,
+		 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)))
+	return status;
+
+    status = krb5_auth_con_getrcache(bsd_context, auth_context, &rcache);
+    if (status) return status;
+
+    if (! rcache) {
+	krb5_principal server;
+
+	status = krb5_sname_to_principal(bsd_context, 0, 0,
+					 KRB5_NT_SRV_HST, &server);
+	if (status) return status;
+
+	status = krb5_get_server_rcache(bsd_context,
+				krb5_princ_component(bsd_context, server, 0),
+				&rcache);
+	krb5_free_principal(bsd_context, server);
+	if (status) return status;
+
+	status = krb5_auth_con_setrcache(bsd_context, auth_context, rcache);
+	if (status) return status;
+    }
+
+#ifdef KRB5_KRB4_COMPAT
+    status = krb5_compat_recvauth_version(bsd_context, &auth_context,
+					       &netf,
+				  NULL, 	/* Specify daemon principal */
+				  0, 		/* no flags */
+				  keytab, /* normally NULL to use v5srvtab */
+
+				  do_encrypt ? KOPT_DO_MUTUAL : 0, /*v4_opts*/
+				  "rcmd", 	/* v4_service */
+				  v4_instance, 	/* v4_instance */
+				  ss2sin(&peersin), /* foriegn address */
+				  ss2sin(&laddr), /* our local address */
+				  "", 		/* use default srvtab */
+
+				  &ticket, 	/* return ticket */
+				  &auth_sys, 	/* which authentication system*/
+				  &v4_kdata, v4_schedule,
+					       &version);
+#else
+    auth_sys = KRB5_RECVAUTH_V5;
+    status = krb5_recvauth_version(bsd_context, &auth_context, &netf,
+				   NULL, 0, keytab, &ticket, &version);
+#endif
+    if (status) {
+	if (auth_sys == KRB5_RECVAUTH_V5) {
+	    /*
+	     * clean up before exiting
+	     */
+	    getstr(netf, lusername, sizeof (lusername), "locuser");
+	    getstr(netf, term, sizeof(term), "Terminal type");
+	    getstr(netf, rusername, sizeof(rusername), "remuser");
+	}
+	return status;
+    }
+
+    getstr(netf, lusername, sizeof (lusername), "locuser");
+    getstr(netf, term, sizeof(term), "Terminal type");
+
+    kcmd_proto = KCMD_UNKNOWN_PROTOCOL;
+    if (auth_sys == KRB5_RECVAUTH_V5) {
+	if (version.length != 9) {
+	    fatal (netf, "bad application version length");
+	}
+	if (!memcmp (version.data, "KCMDV0.1", 9))
+	    kcmd_proto = KCMD_OLD_PROTOCOL;
+	else if (!memcmp (version.data, "KCMDV0.2", 9))
+	    kcmd_proto = KCMD_NEW_PROTOCOL;
+    }
+#ifdef KRB5_KRB4_COMPAT
+    if (auth_sys == KRB5_RECVAUTH_V4)
+	kcmd_proto = KCMD_V4_PROTOCOL;
+#endif
+
+    if ((auth_sys == KRB5_RECVAUTH_V5)
+	&& !(checksum_ignored
+	     && kcmd_proto == KCMD_OLD_PROTOCOL)) {
+      
+      if ((status = krb5_auth_con_getauthenticator(bsd_context, auth_context,
+						   &authenticator)))
+	return status;
+    
+      if (authenticator->checksum) {
+	struct sockaddr_in adr;
+	socklen_t adr_length = sizeof(adr);
+	char * chksumbuf = (char *) malloc(strlen(term)+strlen(lusername)+32);
+	if (getsockname(netf, (struct sockaddr *) &adr, &adr_length) != 0)
+	    goto error_cleanup;
+	if (chksumbuf == 0)
+	    goto error_cleanup;
+
+	sprintf(chksumbuf,"%u:", ntohs(adr.sin_port));
+	strcat(chksumbuf,term);
+	strcat(chksumbuf,lusername);
+
+	status = krb5_verify_checksum(bsd_context,
+				      authenticator->checksum->checksum_type,
+				      authenticator->checksum,
+				      chksumbuf, strlen(chksumbuf),
+				      ticket->enc_part2->session->contents, 
+				      ticket->enc_part2->session->length);
+    error_cleanup:
+	if (chksumbuf)
+	    free(chksumbuf);
+	if (status) {
+	  krb5_free_authenticator(bsd_context, authenticator);
+	  return status;
+	}
+	*valid_checksum = 1;
+      }
+      krb5_free_authenticator(bsd_context, authenticator);
+    }
+
+
+#ifdef KRB5_KRB4_COMPAT
+    if (auth_sys == KRB5_RECVAUTH_V4) {
+
+	rcmd_stream_init_krb4(v4_kdata->session, do_encrypt, 1, 1);
+
+	/* We do not really know the remote user's login name.
+         * Assume it to be the same as the first component of the
+	 * principal's name. 
+         */
+	strncpy(rusername, v4_kdata->pname, sizeof(rusername) - 1);
+	rusername[sizeof(rusername) - 1] = '\0';
+
+	status = krb5_425_conv_principal(bsd_context, v4_kdata->pname,
+					 v4_kdata->pinst, v4_kdata->prealm,
+					 &client);
+	if (status) return status;
+
+	status = krb5_unparse_name(bsd_context, client, &krusername);
+	
+	return status;
+    }
+#endif
+
+    /* Must be V5  */
+	
+    if ((status = krb5_copy_principal(bsd_context, ticket->enc_part2->client, 
+				      &client)))
+	return status;
+
+    key = 0;
+    status = krb5_auth_con_getrecvsubkey (bsd_context, auth_context, &key);
+    if (status)
+	fatal (netf, "Server can't get session subkey");
+    if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL)
+	fatal (netf, "No session subkey sent");
+    if (key && kcmd_proto == KCMD_OLD_PROTOCOL) {
+#ifdef HEIMDAL_FRIENDLY
+	key = 0;
+#else
+	fatal (netf, "Session subkey not permitted under old kcmd protocol");
+#endif
+    }
+    if (key == 0)
+	key = ticket->enc_part2->session;
+
+    rcmd_stream_init_krb5 (key, do_encrypt, 1, 0, kcmd_proto);
+
+    do_inband = (kcmd_proto == KCMD_NEW_PROTOCOL);
+
+    getstr(netf, rusername, sizeof(rusername), "remuser");
+
+    if ((status = krb5_unparse_name(bsd_context, client, &krusername)))
+	return status;
+    
+    if ((status = krb5_read_message(bsd_context, (krb5_pointer)&netf, &inbuf)))
+	fatal(netf, "Error reading message");
+
+    if ((inbuf.length) && /* Forwarding being done, read creds */
+	(status = rd_and_store_for_creds(bsd_context, auth_context, &inbuf, 
+					  ticket, &ccache))) {
+         fatal(netf, "Can't get forwarded credentials");
+    }
+    return 0;
+}
+
+#endif /* KERBEROS */
diff --git a/krb5-1-6/src/appl/bsd/krsh.c b/krb5-1-6/src/appl/bsd/krsh.c
new file mode 100644
index 000000000..155223fab
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/krsh.c
@@ -0,0 +1,635 @@
+/*
+ *	appl/bsd/krsh.c
+ */
+
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+  "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)rsh.c	5.7 (Berkeley) 9/20/88 */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <pwd.h>
+#include <netdb.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_SYS_FILIO_H
+/* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
+#include <sys/filio.h>
+#endif
+
+#ifdef KERBEROS
+#include <krb5.h>
+#include <com_err.h>
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+#include "defines.h"
+#endif /* KERBEROS */
+
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+Key_schedule v4_schedule;
+#endif
+
+/*
+ * rsh - remote shell
+ */
+#define SECURE_MESSAGE "This rsh session is encrypting input/output data transmissions.\r\n"
+
+int	error();
+     
+int	options;
+int	rfd2;
+int	nflag;
+krb5_sigtype  sendsig(int);
+
+#ifdef KERBEROS
+
+#ifndef UCB_RSH
+#define UCB_RSH "/usr/ucb/rsh"
+#endif
+
+krb5_context bsd_context;
+krb5_creds *cred;
+
+#ifdef KRB5_KRB4_COMPAT
+Key_schedule v4_schedule;
+CREDENTIALS v4_cred;
+#endif
+
+int	encrypt_flag = 0;
+char	*krb_realm = (char *)0;
+void	try_normal(char **);
+
+#endif /* KERBEROS */
+
+#ifndef RLOGIN_PROGRAM
+#ifdef KERBEROS
+#define RLOGIN_PROGRAM KRB5_PATH_RLOGIN
+#else /* KERBEROS */
+#ifndef UCB_RLOGIN
+#define UCB_RLOGIN "/usr/ucb/rlogin"
+#endif
+#define RLOGIN_PROGRAM UCB_RLOGIN
+#endif  /* KERBEROS */
+#endif /* !RLOGIN_PROGRAM */
+     
+#ifndef POSIX_SIGNALS
+#define	mask(s)	(1 << ((s) - 1))
+#endif /* POSIX_SIGNALS */
+     
+int
+main(argc, argv0)
+     int argc;
+     char **argv0;
+{
+    int rem, pid = 0;
+    char *host=0, *cp, **ap, buf[RCMD_BUFSIZ], *args, **argv = argv0, *user = 0;
+    register int cc;
+    struct passwd *pwd;
+    fd_set readfrom, ready;
+    int one = 1;
+    struct servent *sp;
+    struct servent defaultservent;
+    struct sockaddr_in local, foreign;
+    int suppress = 0;
+
+#ifdef POSIX_SIGNALS
+    sigset_t omask, igmask;
+    struct sigaction sa, osa;
+#else
+    int omask;
+#endif
+#ifdef KERBEROS
+    krb5_flags authopts;
+    krb5_error_code status;
+    krb5_auth_context auth_context;
+    int fflag = 0, Fflag = 0;
+#ifdef KRB5_KRB4_COMPAT
+    KTEXT_ST v4_ticket;
+    MSG_DAT v4_msg_data;
+#endif
+#endif  /* KERBEROS */
+    int debug_port = 0;
+    enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
+
+    memset(&defaultservent, 0, sizeof(struct servent));
+    if (strrchr(argv[0], '/'))
+      argv[0] = strrchr(argv[0], '/')+1; 
+
+    if ( argc < 2 ) goto usage;
+    argc--;
+    argv++;
+    
+  another:
+    if (argc > 0 && host == 0 && strncmp(*argv, "-", 1)) {
+	host = *argv;
+	argv++, argc--;
+	goto another;
+    }
+
+    if (argc > 0 && !strcmp(*argv, "-D")) {
+	argv++; argc--;
+	debug_port = htons(atoi(*argv));
+	argv++; argc--;
+	goto another;
+    }
+
+    if (argc > 0 && !strcmp(*argv, "-l")) {
+	argv++, argc--;
+	if (argc > 0)
+	  user = *argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-n")) {
+	argv++, argc--;
+	nflag++;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-d")) {
+	argv++, argc--;
+	options |= SO_DEBUG;
+	goto another;
+    }
+#ifdef KERBEROS
+    if (argc > 0 && !strcmp(*argv, "-k")) {
+	argv++, argc--;
+	if (argc == 0) {
+	    fprintf(stderr, "rsh(kerberos): -k flag must have a realm after it.\n");
+	    exit (1);
+	}
+	if(!(krb_realm = (char *)malloc(strlen(*argv) + 1))){
+	    fprintf(stderr, "rsh(kerberos): Cannot malloc.\n");
+	    exit(1);
+	}
+	strcpy(krb_realm, *argv);
+	argv++, argc--;
+	goto another;
+    }
+    /*
+     * Ignore -x from kerberos rlogin
+     */
+    if (argc > 0 && !strncmp(*argv, "-x", 2)) {
+	argv++, argc--;
+	encrypt_flag++;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-f", 2)) {
+	if (Fflag) {
+	    fprintf(stderr, "rsh: Only one of -f and -F allowed\n");
+	    goto usage;
+	}
+	fflag++;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-F", 2)) {
+	if (fflag) {
+	    fprintf(stderr, "rsh: Only one of -f and -F allowed\n");
+	    goto usage;
+	}
+	Fflag++;
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-A", 2)) {
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-PO")) {
+	argv++, argc--;
+	kcmd_proto = KCMD_OLD_PROTOCOL;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-PN")) {
+	argv++, argc--;
+	kcmd_proto = KCMD_NEW_PROTOCOL;
+	goto another;
+    }
+#endif  /* KERBEROS */
+    /*
+     * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin
+     * to work
+     *
+     * There must be a better way to do this! -jmb
+     */
+    if (argc > 0 && !strncmp(*argv, "-L", 2)) {
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-w", 2)) {
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-e", 2)) {
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strncmp(*argv, "-8", 2)) {
+	argv++, argc--;
+	goto another;
+    }
+#ifdef ATHENA
+    /* additional Athena flags to be ignored */
+    if (argc > 0 && !strcmp(*argv, "-noflow")) {	/* No local flow control option for rlogin */
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-7")) {
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-c")) {
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-a")) {
+	argv++, argc--;
+	goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-n")) {
+	argv++, argc--;
+	goto another;
+    }
+    /*
+     ** Also ignore -t ttytype
+     */
+    if (argc > 0 && !strcmp(*argv, "-t")) {
+	argv++; argv++; argc--; argc--;
+	goto another;
+    }
+#endif /* ATHENA */
+    if (host == 0)
+      goto usage;
+    if (argv[0] == 0) {
+	execv(RLOGIN_PROGRAM, argv0);
+	perror(RLOGIN_PROGRAM);
+	exit(1);
+    }
+
+    pwd = getpwuid(getuid());
+    if (pwd == 0) {
+	fprintf(stderr, "who are you?\n");
+	exit(1);
+    }
+    cc = 0;
+    for (ap = argv; *ap; ap++)
+      cc += strlen(*ap) + 1;
+    if (encrypt_flag)
+      cc += 3;
+    cp = args = (char *) malloc((unsigned) cc);
+    if (encrypt_flag) {
+      strcpy(args, "-x ");
+      cp += 3;
+    }
+    for (ap = argv; *ap; ap++) {
+	(void) strcpy(cp, *ap);
+	while (*cp)
+	  cp++;
+	if (ap[1])
+	  *cp++ = ' ';
+    }
+
+    if(debug_port == 0) {
+#ifdef KERBEROS
+      sp = getservbyname("kshell", "tcp");
+#else 
+      sp = getservbyname("shell", "tcp");
+#endif  /* KERBEROS */
+      if (sp == 0) {
+#ifdef KERBEROS
+	sp = &defaultservent;
+	sp->s_port = htons(544);
+#else 
+	fprintf(stderr, "rsh: shell/tcp: unknown service\n");
+	exit(1);
+#endif /* KERBEROS */
+      }
+
+      debug_port = sp->s_port;
+    }
+
+#ifdef KERBEROS
+    status = krb5_init_context(&bsd_context);
+    if (status) {
+	    com_err(argv[0], status, "while initializing krb5");
+	    exit(1);
+    }
+    authopts = AP_OPTS_MUTUAL_REQUIRED;
+
+    /* Piggy-back forwarding flags on top of authopts; */
+    /* they will be reset in kcmd */
+    if (fflag || Fflag)
+      authopts |= OPTS_FORWARD_CREDS;
+    if (Fflag)
+      authopts |= OPTS_FORWARDABLE_CREDS;    
+#ifdef HAVE_ISATTY
+    suppress = !isatty(fileno(stderr));
+#endif
+    status = kcmd(&rem, &host, debug_port,
+		  pwd->pw_name,
+		  user ? user : pwd->pw_name,
+		  args, &rfd2, "host", krb_realm,
+		  &cred,
+		  0,           /* No need for sequence number */
+		  0,           /* No need for server seq # */
+		  &local, &foreign,
+		  &auth_context, authopts,
+		  1,	/* Always set anyport, there is no need not to. --proven */
+		  suppress,
+		  &kcmd_proto);
+    if (status) {
+	/* If new protocol requested, don't fall back to less secure
+	   ones.  */
+	if (kcmd_proto == KCMD_NEW_PROTOCOL)
+	    exit (1);
+#ifdef KRB5_KRB4_COMPAT
+	/* No encrypted Kerberos 4 rsh. */
+	if (encrypt_flag)
+	    exit(1);
+#ifdef HAVE_ISATTY
+	if (isatty(fileno(stderr)))
+	    fprintf(stderr, "Trying krb4 rsh...\n");
+#endif
+	status = k4cmd(&rem, &host, debug_port,
+		       pwd->pw_name,
+		       user ? user : pwd->pw_name, args,
+		       &rfd2, &v4_ticket, "rcmd", krb_realm,
+		       &v4_cred, v4_schedule, &v4_msg_data,
+		       &local, &foreign, 0L, 0);
+	if (status)
+	    try_normal(argv0);
+	rcmd_stream_init_krb4(v4_cred.session, encrypt_flag, 0, 1);
+#else
+	try_normal(argv0);
+#endif
+    } else {
+	krb5_keyblock *key = &cred->keyblock;
+
+	if (kcmd_proto == KCMD_NEW_PROTOCOL) {
+	    status = krb5_auth_con_getsendsubkey (bsd_context, auth_context,
+						  &key);
+	    if (status) {
+		com_err (argv[0], status, "determining subkey for session");
+		exit (1);
+	    }
+	    if (!key) {
+		com_err (argv[0], 0, "no subkey negotiated for connection");
+		exit (1);
+	    }
+	}
+
+	rcmd_stream_init_krb5(key, encrypt_flag, 0, 1, kcmd_proto);
+    }
+
+#ifdef HAVE_ISATTY
+    if(encrypt_flag&&isatty(2)) {
+	write(2,SECURE_MESSAGE, strlen(SECURE_MESSAGE));
+    }
+#endif
+    
+#else /* !KERBEROS */
+    rem = rcmd(&host, debug_port, pwd->pw_name,
+	       user ? user : pwd->pw_name, args, &rfd2);
+    if (rem < 0)
+      exit(1);
+#endif /* KERBEROS */
+    if (rfd2 < 0) {
+	fprintf(stderr, "rsh: can't establish stderr\n");
+	exit(2);
+    }
+    if (options & SO_DEBUG) {
+	if (setsockopt(rem, SOL_SOCKET, SO_DEBUG,
+		       (const char *) &one, sizeof (one)) < 0)
+	  perror("setsockopt (stdin)");
+	if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG,
+		       (const char *) &one, sizeof (one)) < 0)
+	  perror("setsockopt (stderr)");
+    }
+    (void) setuid(getuid());
+#ifdef POSIX_SIGNALS
+    sigemptyset(&igmask);
+    sigaddset(&igmask, SIGINT);
+    sigaddset(&igmask, SIGQUIT);
+    sigaddset(&igmask, SIGTERM);
+    sigprocmask(SIG_BLOCK, &igmask, &omask);
+
+    (void)sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = sendsig;
+
+    (void)sigaction(SIGINT, (struct sigaction *)0, &osa);
+    if (osa.sa_handler != SIG_IGN)
+	(void)sigaction(SIGINT, &sa, (struct sigaction *)0);
+
+    (void)sigaction(SIGQUIT, (struct sigaction *)0, &osa);
+    if (osa.sa_handler != SIG_IGN)
+	(void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
+
+    (void)sigaction(SIGTERM, (struct sigaction *)0, &osa);
+    if (osa.sa_handler != SIG_IGN)
+	(void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
+#else
+#ifdef sgi
+    omask = sigignore(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
+#else
+    omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
+#endif
+    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+      signal(SIGINT, sendsig);
+    if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+      signal(SIGQUIT, sendsig);
+    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+      signal(SIGTERM, sendsig);
+#endif /* POSIX_SIGNALS */
+    if (nflag == 0) {
+	pid = fork();
+	if (pid < 0) {
+	    perror("fork");
+	    exit(1);
+	}
+    }
+    if (!encrypt_flag) {
+	ioctl(rfd2, FIONBIO, &one);
+	ioctl(rem, FIONBIO, &one);
+    }
+    if (nflag == 0 && pid == 0) {
+	char *bp;
+	int wc;
+	fd_set rembits;
+	
+	(void) close(rfd2);
+      reread:
+	errno = 0;
+	cc = read(0, buf, sizeof buf);
+	if (cc <= 0)
+	  goto done;
+	bp = buf;
+      rewrite:
+	FD_ZERO(&rembits);
+	FD_SET(rem, &rembits);
+	if (select(rem + 1, 0, &rembits, 0, 0) < 0) {
+	    if (errno != EINTR) {
+		perror("select");
+		exit(1);
+	    }
+	    goto rewrite;
+	}
+	if (FD_ISSET(rem, &rembits) == 0)
+	  goto rewrite;
+	wc = rcmd_stream_write(rem, bp, cc, 0);
+	if (wc < 0) {
+	    if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
+	      goto rewrite;
+	    goto done;
+	}
+	cc -= wc; bp += wc;
+	if (cc == 0)
+	  goto reread;
+	goto rewrite;
+      done:
+	(void) shutdown(rem, 1);
+#ifdef KERBEROS 
+	krb5_free_context(bsd_context);
+#endif
+	exit(0);
+    }
+#ifdef POSIX_SIGNALS
+    sigprocmask(SIG_SETMASK, &omask, (sigset_t*)0);
+#else
+#ifndef sgi
+    sigsetmask(omask);
+#endif
+#endif /* POSIX_SIGNALS */
+    FD_ZERO(&readfrom);
+    FD_SET(rfd2, &readfrom);
+    FD_SET(rem, &readfrom);
+    do {
+	ready = readfrom;
+	if (select(((rfd2 > rem) ? rfd2 : rem) + 1, &ready, 0, 0, 0) < 0) {
+	    if (errno != EINTR) {
+		perror("select");
+		exit(1);
+	    }
+	    continue;
+	}
+	if (FD_ISSET(rfd2, &ready)) {
+	    errno = 0;
+	    cc = rcmd_stream_read(rfd2, buf, sizeof buf, 1);
+	    if (cc <= 0) {
+		if ((errno != EWOULDBLOCK) && (errno != EAGAIN))
+		    FD_CLR(rfd2, &readfrom);
+	    } else
+	      (void) write(2, buf, (unsigned) cc);
+	}
+	if (FD_ISSET(rem, &ready)) {
+	    errno = 0;
+	    cc = rcmd_stream_read(rem, buf, sizeof buf, 0);
+	    if (cc <= 0) {
+		if ((errno != EWOULDBLOCK) && (errno != EAGAIN))
+		    FD_CLR(rem, &readfrom);
+	    } else
+	      (void) write(1, buf, (unsigned) cc);
+	}
+    } while (FD_ISSET(rem, &readfrom) || FD_ISSET(rfd2, &readfrom));
+    if (nflag == 0)
+      (void) kill(pid, SIGKILL);
+#ifdef KERBEROS 
+    krb5_free_context(bsd_context);
+#endif
+    exit(0);
+  usage:
+    fprintf(stderr,
+	    "usage: \trsh host [ -PN / -PO ] [ -l login ] [ -n ] [ -x ] [ -f / -F] command\n");
+    fprintf(stderr,
+	    "OR \trsh [ -PN / -PO ] [ -l login ] [-n ] [ -x ] [ -f / -F ] host command\n");
+    exit(1);
+}
+
+
+
+krb5_sigtype sendsig(signo)
+     char signo;
+{
+    (void) rcmd_stream_write(rfd2, &signo, 1, 1);
+}
+
+
+
+#ifdef KERBEROS
+void try_normal(argv)
+     char **argv;
+{
+    char *host;
+    
+#ifndef KRB5_ATHENA_COMPAT
+    if (encrypt_flag)
+	exit(1);
+#endif
+    /*
+     * if we were invoked as 'rsh host mumble', strip off the rsh
+     * from arglist.
+     *
+     * We always want to call the Berkeley rsh as 'host mumble'
+     */
+    host = strrchr(argv[0], '/');
+    if (host)
+      host++;
+    else
+      host = argv[0];
+    
+    if (!strcmp(host, "rsh"))
+      argv++;
+    
+    fprintf(stderr,"trying normal rsh (%s)\n",
+	    UCB_RSH);
+    fflush(stderr);
+    execv(UCB_RSH, argv);
+    perror("exec");
+    exit(1);
+}
+#endif /* KERBEROS */
diff --git a/krb5-1-6/src/appl/bsd/krshd.c b/krb5-1-6/src/appl/bsd/krshd.c
new file mode 100644
index 000000000..3642501f6
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/krshd.c
@@ -0,0 +1,2084 @@
+/*
+ *	appl/bsd/krshd.c
+ */
+
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+  "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)rshd.c	5.12 (Berkeley) 9/12/88 */
+
+     /*
+      * remote shell server:
+      *	remuser\0
+      *	locuser\0
+      *	command\0
+      *	data
+      */
+     
+/*
+ * This is the rshell daemon. The very basic protocol for checking 
+ * authentication and authorization is:
+ * 1) Check authentication.
+ * 2) Check authorization via the access-control files: 
+ *    ~/.k5login (using krb5_kuserok) and/or
+ * Execute command if configured authoriztion checks pass, else deny 
+ * permission.
+ *
+ * The configuration is done either by command-line arguments passed by inetd, 
+ * or by the name of the daemon. If command-line arguments are present, they 
+ * take priority. The options are:
+ * -k means trust krb4 or krb5
+ * -5 means trust krb5
+ * -4 means trust krb4 (using .klogin)
+ * 
+ */
+     
+/* DEFINES:
+ *   KERBEROS - Define this if application is to be kerberised.
+ *   KRB5_KRB4_COMPAT - Define this if v4 rlogin clients are also to be served.
+ *   ALWAYS_V5_KUSEROK - Define this if you want .k5login to be
+ *              checked even for v4 clients (instead of .klogin).
+ *   LOG_ALL_LOGINS - Define this if you want to log all logins.
+ *   LOG_OTHER_USERS - Define this if you want to log all principals that do
+ *              not map onto the local user.
+ *   LOG_REMOTE_REALM - Define this if you want to log all principals from 
+ *              remote realms.
+ *   LOG_CMD - Define this if you want to log not only the user but also the
+ *             command executed. This only decides the type of information
+ *             logged. Whether or not to log is still decided by the above 
+ *             three DEFINES.
+ *       Note:  Root account access is always logged.
+ */
+     
+#define SERVE_NON_KRB     
+#define LOG_REMOTE_REALM
+#define LOG_CMD
+   
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef __SCO__
+#include <sys/unistd.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#if !defined(KERBEROS) || !defined(KRB5_KRB4_COMPAT)
+/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
+#include <sys/socket.h>
+#endif
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+     
+#include <netinet/in.h>
+#include <arpa/inet.h>
+     
+#include <stdio.h>
+#include <grp.h>
+#include <errno.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <string.h>
+#include <libpty.h>
+#include <sys/wait.h>
+     
+#ifdef HAVE_SYS_LABEL_H
+/* only SunOS 4? */
+#include <sys/label.h>
+#include <sys/audit.h>
+#include <pwdadj.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+     
+#include <signal.h>
+#if !defined(KERBEROS) || !defined(KRB5_KRB4_COMPAT)
+/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
+#include <netdb.h>
+#endif
+
+#ifdef CRAY
+#ifndef NO_UDB
+#include <udb.h>
+#endif  /* !NO_UDB */
+#include <sys/category.h>
+#include <netinet/ip.h>
+#include <sys/tfm.h>
+#include <sys/nal.h>
+#include <sys/secparm.h>
+#include <sys/usrv.h>
+#include <sys/utsname.h>
+#include <sys/sysv.h>
+#include <sys/slrec.h>
+#include <sys/unistd.h>
+#include <path.h>
+#endif /* CRAY */
+     
+#include <syslog.h>
+
+#ifdef POSIX_TERMIOS
+#include <termios.h>
+#endif
+     
+#ifdef HAVE_SYS_FILIO_H
+/* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
+#include <sys/filio.h>
+#endif
+
+#ifdef KERBEROS
+#include <krb5.h>
+#include <com_err.h>
+#include "loginpaths.h"
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+Key_schedule v4_schedule;
+#endif
+#include <k5-util.h>
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#if defined(_PATH_NOLOGIN)
+#define NOLOGIN		_PATH_NOLOGIN
+#else
+#define NOLOGIN		"/etc/nologin"
+#endif
+
+#include "defines.h"
+
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+
+#ifndef MAXDNAME
+#define MAXDNAME 256 /*per the rfc*/
+#endif
+
+#define ARGSTR	"ek54ciD:S:M:AP:?L:w:"
+
+
+
+
+#define MAXRETRIES 4
+
+krb5_context bsd_context;
+char *srvtab = NULL;
+krb5_keytab keytab = NULL;
+krb5_ccache ccache = NULL;
+
+void fatal(int, const char *);
+
+int require_encrypt = 0;
+int do_encrypt = 0;
+int anyport = 0;
+char *kprogdir = KPROGDIR;
+int netf;
+int maxhostlen = 0;
+int stripdomain = 1;
+int always_ip = 0;
+
+static krb5_error_code recvauth(int netfd, struct sockaddr *peersin,
+				int *valid_checksum);
+
+#else /* !KERBEROS */
+
+#define ARGSTR	"RD:?"
+     
+#endif /* KERBEROS */
+
+     
+#ifndef HAVE_KILLPG
+#define killpg(pid, sig) kill(-(pid), (sig))
+#endif
+
+/* There are two authentication related masks:
+   * auth_ok and auth_sent.
+* The auth_ok mask is the oring of authentication systems any one
+* of which can be used.  
+* The auth_sent mask is the oring of one or more authentication/authorization
+* systems that succeeded.  If the anding
+* of these two masks is true, then authorization is successful.
+*/
+#define AUTH_KRB4 (0x1)
+#define AUTH_KRB5 (0x2)
+int auth_ok = 0, auth_sent = 0;
+int checksum_required = 0, checksum_ignored = 0;
+char *progname;
+
+#define MAX_PROG_NAME 10
+
+/* Leave room for 4 environment variables to be passed */
+#define MAXENV 4
+#define SAVEENVPAD 0,0,0,0 /* padding for envinit slots */
+char *save_env[MAXENV];
+int num_env = 0;
+
+#ifdef CRAY
+int     secflag;
+extern
+#endif /* CRAY */
+
+void 	error (char *fmt, ...)
+#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
+       __attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+     ;
+
+void usage(void), getstr(int, char *, int, char *), 
+    doit(int, struct sockaddr *);
+
+#ifndef HAVE_INITGROUPS
+int initgroups(char* name, gid_t basegid) {
+  gid_t others[NGROUPS_MAX+1];
+  int ngrps;
+
+  others[0] = basegid;
+  ngrps = getgroups(NGROUPS_MAX, others+1);
+  return setgroups(ngrps+1, others);
+}
+#endif
+
+
+int main(argc, argv)
+     int argc;
+     char **argv;
+{
+#if defined(BSD) && BSD+0 >= 43
+    struct linger linger;
+#endif
+    int on = 1;
+    socklen_t fromlen;
+    struct sockaddr_storage from;
+    extern int opterr, optind;
+    extern char *optarg;
+    int ch;
+    int fd;
+    int debug_port = 0;
+#ifdef KERBEROS
+    krb5_error_code status;
+#endif
+
+#ifdef CRAY
+    secflag = sysconf(_SC_CRAY_SECURE_SYS);
+#endif
+    
+    progname = strrchr (*argv, '/');
+    progname = progname ? progname + 1 : *argv;
+    
+#ifndef LOG_ODELAY /* 4.2 syslog */
+    openlog(progname, LOG_PID);
+#else
+#ifndef LOG_AUTH
+#define LOG_AUTH 0
+#endif
+    openlog(progname, LOG_PID | LOG_ODELAY, LOG_AUTH);
+#endif /* 4.2 syslog */
+    
+#ifdef KERBEROS
+    status = krb5_init_context(&bsd_context);
+    if (status) {
+	    syslog(LOG_ERR, "Error initializing krb5: %s",
+		   error_message(status));
+	    exit(1);
+    }
+#endif
+    
+    /* Analyze parameters. */
+    opterr = 0;
+    while ((ch = getopt(argc, argv, ARGSTR)) != -1)
+      switch (ch) {
+#ifdef KERBEROS
+	case 'k':
+#ifdef KRB5_KRB4_COMPAT
+	auth_ok |= (AUTH_KRB5|AUTH_KRB4);
+#else
+	auth_ok |= AUTH_KRB5;
+#endif /* KRB5_KRB4_COMPAT*/
+	break;
+	
+      case '5':
+	  auth_ok |= AUTH_KRB5;
+	break;
+      case 'c':
+	checksum_required = 1;
+	break;
+      case 'i':
+	checksum_ignored = 1;
+	break;
+	
+#ifdef KRB5_KRB4_COMPAT
+      case '4':
+	auth_ok |= AUTH_KRB4;
+	break;
+#endif
+	  
+        case 'e':
+	require_encrypt = 1;
+	  break;
+
+	case 'S':
+	  if ((status = krb5_kt_resolve(bsd_context, optarg, &keytab))) {
+	      com_err(progname, status, "while resolving srvtab file %s",
+		      optarg);
+	      exit(2);
+	  }
+	  break;
+
+	case 'M':
+	  krb5_set_default_realm(bsd_context, optarg);
+	  break;
+
+	case 'A':
+	  anyport = 1;
+	  break;
+
+	case 'P':
+	  kprogdir = optarg;
+	  break;
+
+        case 'L':
+	  if (num_env < MAXENV) {
+		  save_env[num_env] = strdup(optarg);
+		  if(!save_env[num_env++]) {
+			  com_err(progname, ENOMEM, "in saving environment");
+			  exit(2);
+		  }		  
+	  } else  {
+		  fprintf(stderr, "%s: Only %d -L arguments allowed\n",
+			  progname, MAXENV);
+		  exit(2);
+	  }
+	  break;
+#endif
+	case 'D':
+	  debug_port = atoi(optarg);
+	  break;
+      case 'w':
+	  if (!strcmp(optarg, "ip"))
+	      always_ip = 1;
+	  else {
+	      char *cp;
+	      cp = strchr(optarg, ',');
+	      if (cp == NULL)
+		  maxhostlen = atoi(optarg);
+	      else if (*(++cp)) {
+		  if (!strcmp(cp, "striplocal"))
+		      stripdomain = 1;
+		  else if (!strcmp(cp, "nostriplocal"))
+		      stripdomain = 0;
+		  else {
+		      usage();
+		      exit(1);
+		  }
+		  *(--cp) = '\0';
+		  maxhostlen = atoi(optarg);
+	      }
+	  }
+	  break;
+      case '?':
+      default:
+	  usage();
+	  exit(1);
+	  break;
+      }
+
+    if (optind == 0) {
+	usage();
+	exit(1);
+    }
+    
+    argc -= optind;
+    argv += optind;
+    
+    fromlen = sizeof (from);
+
+    if (debug_port)
+	fd = accept_a_connection(debug_port, (struct sockaddr *)&from,
+				 &fromlen);
+    else {
+	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+	    fprintf(stderr, "%s: ", progname);
+	    perror("getpeername");
+	    _exit(1);
+	}
+
+	fd = 0;
+    }
+
+/*
+ * AIX passes an IPv4-mapped IPv6 address back from getpeername, but if
+ * that address is later used in connect(), it returns an error.  Convert
+ * IPv4-mapped IPv6 addresses to simple IPv4 addresses on AIX (but don't
+ * do this everywhere since it isn't always the right thing to do, just
+ * the least wrong on AIX).
+ */
+#if defined(_AIX) && defined(KRB5_USE_INET6)
+    if (((struct sockaddr*)&from)->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa2sin6(&from)->sin6_addr)) {
+	sa2sin(&from)->sin_len = sizeof(struct sockaddr_in);
+	sa2sin(&from)->sin_family = AF_INET;
+	sa2sin(&from)->sin_port = sa2sin6(&from)->sin6_port;
+	memmove(&(sa2sin(&from)->sin_addr.s_addr), &(sa2sin6(&from)->sin6_addr.u6_addr.u6_addr8[12]), 4);
+    }
+#endif
+
+    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
+		   sizeof (on)) < 0)
+	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+#if defined(BSD) && BSD+0 >= 43
+    linger.l_onoff = 1;
+    linger.l_linger = 60;			/* XXX */
+    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&linger,
+		   sizeof (linger)) < 0)
+	syslog(LOG_WARNING , "setsockopt (SO_LINGER): %m");
+#endif
+
+    if (checksum_required&&checksum_ignored) {
+	syslog(LOG_CRIT, "Checksums are required and ignored; these options are mutually exclusive--check the documentation.");
+	fatal(fd, "Configuration error: mutually exclusive options specified");
+    }
+
+    doit(dup(fd), (struct sockaddr *) &from);
+    return 0;
+}
+
+#ifdef CRAY
+char    username[32] = "LOGNAME=";
+#include <tmpdir.h>
+char tmpdir[64] = "TMPDIR=";
+#else
+char	username[20] = "USER=";
+#endif
+
+char	homedir[64] = "HOME=";
+char	shell[64] = "SHELL=";
+char    term[64] = "TERM=network";
+char	path_rest[] = RPATH;
+
+char	remote_addr[64+NI_MAXHOST]; /* = "KRB5REMOTEADDR=" */
+char	remote_port[64+NI_MAXSERV]; /* = "KRB5REMOTEPORT=" */
+char	local_addr[64+NI_MAXHOST]; /* = "KRB5LOCALADDR=" */
+char	local_port[64+NI_MAXSERV]; /* = "KRB5LOCALPORT=" */
+#define ADDRPAD 0,0,0,0
+#define KRBPAD 0		/* KRB5CCNAME, optional */
+
+/* The following include extra space for TZ and MAXENV pointers... */
+#define COMMONVARS homedir, shell, 0/*path*/, username, term
+#ifdef CRAY
+char    *envinit[] = 
+{COMMONVARS, "TZ=GMT0", tmpdir, SAVEENVPAD, KRBPAD, ADDRPAD, 0};
+#define TMPDIRENV 6
+char    *getenv();
+#else /* CRAY */
+#ifdef KERBEROS
+char    *envinit[] = 
+{COMMONVARS, 0/*tz*/, SAVEENVPAD, KRBPAD, ADDRPAD, 0};
+#else /* KERBEROS */
+char	*envinit[] = 
+{COMMONVARS, 0/*tz*/, SAVEENVPAD, ADDRPAD, 0};
+#endif /* KERBEROS */
+#endif /* CRAY */
+
+#define TZENV 5
+#define PATHENV 2
+
+extern char	**environ;
+char ttyn[12];		/* Line string for wtmp entries */
+
+#ifdef CRAY
+#define SIZEOF_INADDR  SIZEOF_in_addr
+int maxlogs;
+#else
+#define SIZEOF_INADDR sizeof(struct in_addr)
+#endif
+
+#ifndef NCARGS
+/* linux doesn't seem to have it... */
+#define NCARGS 1024
+#endif
+
+#define NMAX   16 
+
+int pid;
+char locuser[NMAX+1];
+char remuser[NMAX +1];
+char cmdbuf[NCARGS+1];
+char *kremuser;
+krb5_principal client;
+krb5_authenticator *kdata;
+
+#ifdef KRB5_KRB4_COMPAT
+AUTH_DAT	*v4_kdata;
+KTEXT		v4_ticket;
+#endif
+
+int auth_sys = 0;	/* Which version of Kerberos used to authenticate */
+
+#define KRB5_RECVAUTH_V4	4
+#define KRB5_RECVAUTH_V5	5
+
+static void
+ignore_signals()
+{
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+
+    (void)sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
+    (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
+    (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
+    (void)sigaction(SIGPIPE, &sa, (struct sigaction *)0);
+    (void)sigaction(SIGHUP, &sa, (struct sigaction *)0);
+
+    (void)kill(-pid, SIGTERM);
+#else
+    signal(SIGINT, SIG_IGN);
+    signal(SIGQUIT, SIG_IGN);
+    signal(SIGTERM, SIG_IGN);
+    signal(SIGPIPE, SIG_IGN);
+    signal(SIGHUP, SIG_IGN);
+    
+    killpg(pid, SIGTERM);
+#endif
+}
+
+static krb5_sigtype
+cleanup(signumber)
+     int signumber;
+{
+    ignore_signals();
+    wait(0);
+    
+    pty_logwtmp(ttyn,"","");
+    syslog(LOG_INFO ,"Daemon terminated via signal %d.", signumber);
+    if (ccache)
+	krb5_cc_destroy(bsd_context, ccache);
+    exit(0);
+}
+
+
+void doit(f, fromp)
+     int f;
+     struct sockaddr *fromp;
+{
+    char *cp;
+#ifdef KERBEROS
+    krb5_error_code status;
+#endif
+    int valid_checksum;
+    int cnt;
+    char *crypt();
+    struct passwd *pwd;
+    char *path;
+#ifdef CRAY
+#ifndef NO_UDB
+    struct udb    *ue;
+    struct udb ue_static;
+    extern struct udb *getudbnam();
+#endif
+    extern struct passwd *getpwnam(), *getpwuid();
+    static int      jid;
+    int error();
+    int paddr;
+    struct  nal nal;
+    int     nal_error;
+    struct usrv usrv;
+    struct  sysv sysv;
+    char    *makejtmp(), *jtmpnam = 0;
+    int packet_level;               /* Packet classification level */
+    long packet_compart;            /* Packet compartments */
+#endif  /* CRAY */
+    
+    int s = -1;
+    char hostname[NI_MAXHOST];
+    char *sane_host;
+    char hostaddra[NI_MAXHOST];
+    int aierr;
+    short port;
+    int pv[2], pw[2], px[2], cc;
+    fd_set ready, readfrom;
+    char buf[RCMD_BUFSIZ], sig;
+    struct sockaddr_storage localaddr;
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+#endif
+
+#ifdef IP_TOS
+/* solaris has IP_TOS, but only IPTOS_* values */
+#ifdef HAVE_GETTOSBYNAME
+    struct tosent *tp;
+
+
+    if ((tp = gettosbyname("interactive", "tcp")) &&
+	(setsockopt(f, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
+#ifdef  TOS_WARN
+      syslog(LOG_NOTICE, "setsockopt (IP_TOS): %m");
+#else
+    ;       /* silently ignore TOS errors in 6E */
+#endif
+#endif
+#endif /* IP_TOS */
+    
+    { 
+	socklen_t sin_len = sizeof (localaddr);
+	if (getsockname(f, (struct sockaddr*)&localaddr, &sin_len) < 0) {
+	    perror("getsockname");
+	    exit(1);
+	}
+    }
+
+#ifdef POSIX_SIGNALS
+    (void)sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_DFL;
+    (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
+    (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
+    (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
+#else
+    signal(SIGINT, SIG_DFL);
+    signal(SIGQUIT, SIG_DFL);
+    signal(SIGTERM, SIG_DFL);
+#endif
+#ifdef DEBUG
+    { int t = open("/dev/tty", 2);
+      if (t >= 0) {
+	  ioctl(t, TIOCNOTTY, (char *)0);
+	  (void) close(t);
+      }
+  }
+#endif
+    if (fromp->sa_family != AF_INET
+#if defined(KRB5_USE_INET6) && defined(KERBEROS)
+	&& fromp->sa_family != AF_INET6
+#endif
+	) {
+	syslog(LOG_ERR , "malformed from address\n");
+	exit(1);
+    }
+#ifdef KERBEROS
+    netf = f;
+#else
+    {
+	struct sockaddr_in *frompin = sa2sin(fromp);
+	frompin->sin_port = ntohs((u_short)frompin->sin_port);
+	if (frompin->sin_port >= IPPORT_RESERVED ||
+	    frompin->sin_port < IPPORT_RESERVED/2) {
+	    syslog(LOG_ERR , "connection from bad port\n");
+	    exit(1);
+	}
+    }
+#endif /* KERBEROS */
+    
+#ifdef CRAY
+    
+    /* If this is a secure system then get the packet classification
+       of f.  ( Note IP_SECURITY is checked in get_packet_classification:
+       if it's not set then the user's (root) default
+       classification level and compartments are returned. )
+       Then set this process to that level/compart so that the stderr
+       connection will be labeled appropriately.
+       */
+    if (secflag) {
+	if (get_packet_classification(f,getuid(),
+				      &packet_level,&packet_compart) < 0) {
+	    syslog(LOG_ERR, "cannot get ip packet level\n");
+	    exit(1);
+	}
+	if(secflag == TFM_UDB_5) {
+	    if(setucmp(packet_compart, C_PROC) != 0) {
+		error("Unable to setucmp.\n");
+		exit(1);
+	    }
+	} else if(secflag == TFM_UDB_6) {
+	    if(setulvl(packet_level,C_PROC) != 0) {
+		error("Unable to setulvl.\n");
+		exit(1);
+	    }
+	    if(setucmp(packet_compart, C_PROC) != 0) {
+		error("Unable to setucmp.\n");
+		exit(1);
+	    }
+	}
+	
+    }
+#endif /* CRAY */
+    
+    (void) alarm(60);
+    port = 0;
+    for (;;) {
+	char c;
+	if ((cc = read(f, &c, 1)) != 1) {
+	    if (cc < 0)
+	      syslog(LOG_NOTICE , "read: %m");
+	    shutdown(f, 1+1);
+	    exit(1);
+	}
+	if (c == 0)
+	  break;
+	port = port * 10 + c - '0';
+    }
+    (void) alarm(0);
+    if (port != 0) {
+	if (anyport) {
+	    int addrfamily = fromp->sa_family;
+	    s = getport(0, &addrfamily);
+	} else {
+	    int lport = IPPORT_RESERVED - 1;
+#ifdef HAVE_RRESVPORT_AF
+	    s = rresvport_af(&lport, fromp->sa_family);
+#else
+	    s = rresvport(&lport);
+#endif
+	}
+	if (s < 0) {
+	    syslog(LOG_ERR ,
+		   "can't get stderr port: %m");
+	    exit(1);
+	}
+#ifndef KERBEROS
+	if (port >= IPPORT_RESERVED) {
+	    syslog(LOG_ERR , "2nd port not reserved\n");
+	    exit(1);
+	}
+#endif /* KERBEROS */
+	switch (fromp->sa_family) {
+	case AF_INET:
+	    sa2sin(fromp)->sin_port = htons((u_short)port);
+	    break;
+#ifdef KRB5_USE_INET6
+	case AF_INET6:
+	    sa2sin6(fromp)->sin6_port = htons((u_short)port);
+	    break;
+#endif
+	}
+	if (connect(s, (struct sockaddr *)fromp, socklen(fromp)) < 0) {
+	    syslog(LOG_INFO ,
+		   "connect second port: %m");
+	    exit(1);
+	}
+    }
+    dup2(f, 0);
+    dup2(f, 1);
+    dup2(f, 2);
+    aierr = getnameinfo(fromp, socklen(fromp), hostname, sizeof(hostname),
+			0, 0, 0);
+    if (aierr) {
+	error("failed to get remote host address: %s", gai_strerror(aierr));
+	exit(1);
+    }
+    aierr = getnameinfo(fromp, socklen(fromp), hostaddra, sizeof(hostaddra),
+			0, 0, NI_NUMERICHOST);
+    if (aierr) {
+	error("failed to get remote host address: %s", gai_strerror(aierr));
+	exit(1);
+    }
+
+#ifdef KERBEROS
+    status = pty_make_sane_hostname((struct sockaddr *) fromp, maxhostlen,
+				    stripdomain, always_ip, &sane_host);
+    if (status) {
+	error("failed make_sane_hostname: %s\n", error_message(status));
+	exit(1);
+    }
+
+    if ((status = recvauth(f, fromp, &valid_checksum))) {
+	error("Authentication failed: %s\n", error_message(status));
+	exit(1);
+    }
+#else
+    getstr(f, remuser, sizeof(remuser), "remuser");
+    getstr(f, locuser, sizeof(locuser), "locuser");
+    getstr(f, cmdbuf, sizeof(cmdbuf), "command");
+    rcmd_stream_init_normal();
+#endif /* KERBEROS */
+    
+#ifdef CRAY
+    paddr = inet_addr(inet_ntoa(fromp->sin_addr));
+    if(secflag){
+	/*
+	 *      check network authorization list
+	 */
+	if (fetchnal(paddr,&nal) < 0) {
+	    /*
+	     *      NAL file inaccessible, abort connection.
+	     */
+	    error("Permission denied.\n");
+	    exit(1);
+	}
+    }
+#endif /* CRAY */
+    
+    pwd = getpwnam(locuser);
+    if (pwd == (struct passwd *) 0 ) {
+	syslog(LOG_ERR ,
+	       "Principal %s (%s@%s (%s)) for local user %s has no account.\n",
+	       kremuser, remuser, hostaddra, hostname,
+	       locuser); /* xxx sprintf buffer in syslog*/
+	error("Login incorrect.\n");
+	exit(1);
+    }
+    
+#ifdef CRAY
+    /* Setup job entry, and validate udb entry. 
+       ( against packet level also ) */
+    if ((jid = setjob(pwd->pw_uid, 0)) < 0) {
+	error("Unable to create new job.\n");
+	exit(1);
+    }
+    if ((jtmpnam = makejtmp(pwd->pw_uid, pwd->pw_gid, jid))) {
+	register int pid, tpid;
+	int status;
+	switch(pid = fork()) {
+	  case -1:
+	    cleanjtmp(locuser, jtmpnam);
+	    envinit[TMPDIRENV] = 0;
+	    break;
+	  case 0:
+	    break;
+	  default:
+	    close(0);
+	    close(1);
+	    close(2);
+	    close(f);
+	    if (port)
+	      close(s);
+	    while ((tpid = wait(&status)) != pid) {
+		if (tpid < 0)
+		  break;
+	    }
+	    cleanjtmp(locuser, jtmpnam);
+	    exit(status>>8);
+	    /* NOTREACHED */
+	}
+    } else {
+	envinit[TMPDIRENV] = 0;
+    }
+#ifndef NO_UDB
+    (void)getsysudb();
+    
+    if ((ue = getudbnam(pwd->pw_name)) == (struct udb *)NULL) {
+	error("Unable to fetch account id.\n");
+	exit(1);
+    }
+    ue_static = *ue;                /* save from setlimits call */
+    endudb();
+    if (secflag) {
+	if(getsysv(&sysv, sizeof(struct sysv)) != 0) {
+	    loglogin(sane_host, SLG_LLERR, 0, ue);
+	    error("Permission denied.\n");
+	    exit(1);
+	}
+	if ((packet_level != ue->ue_deflvl) ||
+	    ((packet_compart & ue->ue_comparts) != packet_compart )){
+	    loglogin(sane_host, SLG_LLERR, 0, ue);
+	    error("Permission denied.\n");
+	    exit(1);
+	}
+	if (ue->ue_disabled != 0) {
+	    loglogin(sane_host,SLG_LOCK,ue->ue_logfails,ue);
+	    error("Permission denied.\n");
+	    exit(1);
+	}
+	maxlogs = sysv.sy_maxlogs;
+    }
+    if (acctid(getpid(), ue->ue_acids[0]) == -1) {
+	error("Unable to set account id.\n");
+	exit(1);
+    }
+    if (setshares(pwd->pw_uid, acctid(0, -1), error, 1, 0)) {
+	error("Unable to set shares.\n");
+	exit(1);
+    }
+    if (setlimits(pwd->pw_name, C_PROC, getpid(), UDBRC_INTER)) {
+	error("Unable to set limits.\n");
+	exit(1);
+    }
+    if (setlimits(pwd->pw_name, C_JOB, jid, UDBRC_INTER)) {
+	error("Unable to set limits.\n");
+	exit(1);
+    }
+    ue = &ue_static;                /* restore after setlimits call */
+    endudb();			/* setlimits opens udb and leaves it
+				   open so close it here. */
+#endif  /* !NO_UDB */
+#endif /*CRAY*/
+    
+    /* Setup wtmp entry : we do it here so that if this is a CRAY
+       the Process Id is correct and we have not lost our trusted
+       privileges. */
+    if (port) {
+	/* Place entry into wtmp */
+	sprintf(ttyn,"krsh%ld",(long) (getpid() % 9999999));
+	pty_logwtmp(ttyn,locuser,sane_host);
+    }
+    /*      We are simply execing a program over rshd : log entry into wtmp,
+	    as kexe(pid), then finish out the session right after that.
+	    Syslog should have the information as to what was exec'd */
+    else {
+	pty_logwtmp(ttyn,locuser,sane_host);
+    }
+    
+#ifdef CRAY
+    
+    /* If  we are a secure system then we need to get rid of our
+       trusted facility, so that MAC on the chdir we work. Before we
+       do this make an entry into wtmp, and any other audit recording. */
+    
+    if (secflag) {
+	if (getusrv(&usrv)){
+	    syslog(LOG_ERR,"Cannot getusrv");
+	    error("Permission denied.\n");
+	    loglogin(sane_host, SLG_LVERR, ue->ue_logfails,ue);
+	    goto signout_please;
+	}
+	/*
+	 *      6.0 no longer allows any form ofTRUSTED_PROCESS logins.
+	 */
+	if((ue->ue_valcat & TFM_TRUSTED) ||
+	   (sysv.sy_oldtfm &&
+	    ((ue->ue_comparts & TRUSTED_SUBJECT) == TRUSTED_SUBJECT))) {
+	    loglogin(sane_host, SLG_TRSUB, ue->ue_logfails,ue);
+	    error("Permission denied.\n");
+	    goto signout_please;
+	}
+	
+	loglogin(sane_host, SLG_OKLOG, ue->ue_logfails,ue);
+	
+	/*	Setup usrv structure with user udb info and 
+		packet_level and packet_compart. */
+	usrv.sv_actlvl = packet_level;
+	usrv.sv_actcmp = packet_compart; /*Note get_packet_level sets
+					   compartment to users default
+					   compartments....*/
+	usrv.sv_permit = ue->ue_permits;
+	usrv.sv_intcls = ue->ue_intcls;
+	usrv.sv_maxcls = ue->ue_maxcls;
+	usrv.sv_intcat = ue->ue_intcat;
+	usrv.sv_valcat = ue->ue_valcat;
+	usrv.sv_savcmp = 0;
+	usrv.sv_savlvl = 0;
+	
+	/*
+	 *      Set user values to workstation boundaries
+	 */
+#ifdef MIN
+#undef MIN
+#endif
+#ifdef MAX
+#undef MAX
+#endif
+	
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+	
+	nal_error = 0;
+	
+	if (nal.na_sort) {
+	    if ((ue->ue_minlvl > nal.na_smax) ||
+		(ue->ue_maxlvl < nal.na_smin))
+	      nal_error++;
+	    else {
+		usrv.sv_minlvl=MAX(ue->ue_minlvl, nal.na_smin);
+		usrv.sv_maxlvl=MIN(ue->ue_maxlvl, nal.na_smax);
+		
+#ifndef IP_SECURITY
+
+		if (usrv.sv_actlvl < usrv.sv_minlvl)
+		    usrv.sv_actlvl = usrv.sv_minlvl;
+		if (usrv.sv_actlvl > usrv.sv_maxlvl)
+		  usrv.sv_actlvl = usrv.sv_maxlvl;
+		
+#else /*IP_SECURITY*/
+		if (usrv.sv_actlvl < usrv.sv_minlvl)
+		  nal_error++;
+		if (usrv.sv_actlvl > usrv.sv_maxlvl)
+		  nal_error++;
+		if (usrv.sv_actlvl != ue->ue_deflvl)
+		  nal_error++;
+		
+		usrv.sv_valcmp = ue->ue_comparts & nal.na_scmp;
+		usrv.sv_actcmp &= nal.na_scmp;
+#endif /*IP_SECURITY*/
+		usrv.sv_valcmp = ue->ue_comparts & nal.na_scmp;
+		usrv.sv_actcmp = (usrv.sv_valcmp &
+				  ue->ue_defcomps);
+	    }
+	} else {
+	    /*
+	     *      If the user's minimum level is greater than
+	     *      zero, they cannot log on from this (ie. an
+	     *      unclassified) host.
+	     */
+	    if (ue->ue_minlvl > 0)
+	      nal_error++;
+	    /*
+	     *      Address not in NAL, if EXEMPT_NAL is not
+	     *      true, then even an unclassified user is
+	     *      not allowed.
+	     */
+	    if (!EXEMPT_NAL)
+		nal_error++;
+	    else {
+		usrv.sv_minlvl = 0;
+		usrv.sv_maxlvl = 0;
+		usrv.sv_valcmp = 0;
+		usrv.sv_actcmp = 0;
+		usrv.sv_actlvl = 0;
+	    }
+	}
+	if (nal_error) {
+	    loglogin(sane_host, SLG_LVERR, ue->ue_logfails,ue);
+	    error("Permission denied.\n");
+	    goto signout_please;
+	}
+#undef  MIN
+#undef  MAX
+	/* Before the setusrv is done then do a sethost for paddr */
+	sethost(paddr);
+	
+	if (setusrv(&usrv) == -1) {
+	    loglogin(sane_host, SLG_LVERR, ue->ue_logfails,ue);
+	    error("Permission denied.\n");
+	    goto signout_please;
+	}
+	if (getusrv(&usrv) == -1) {
+	    error("Getusrv Permission denied.\n");
+	    goto signout_please;
+	}
+	
+    }
+#endif /*CRAY*/
+    
+    if (chdir(pwd->pw_dir) < 0) {
+      if(chdir("/") < 0) {
+      	error("No remote directory.\n");
+	goto signout_please;
+      }
+	   pwd->pw_dir = "/";
+    }
+
+#ifdef KERBEROS
+
+#if defined(KRB5_KRB4_COMPAT) && !defined(ALWAYS_V5_KUSEROK)
+	if (auth_sys == KRB5_RECVAUTH_V4) {
+	    /* kuserok returns 0 if OK */
+	    if (kuserok(v4_kdata, locuser)){
+		syslog(LOG_ERR ,
+		       "Principal %s (%s@%s (%s)) for local user %s failed kuserok.\n",
+		       kremuser, remuser, hostaddra, hostname, locuser);
+		}
+	    else auth_sent |= AUTH_KRB4;
+	} else
+#endif
+	{
+	    /* krb5_kuserok returns 1 if OK */
+	    if (!krb5_kuserok(bsd_context, client, locuser)){
+		syslog(LOG_ERR ,
+		       "Principal %s (%s@%s (%s)) for local user %s failed krb5_kuserok.\n",
+		       kremuser, remuser, hostaddra, hostname, locuser);
+	    }
+	    else
+		auth_sent |=
+		    ((auth_sys == KRB5_RECVAUTH_V4) ? AUTH_KRB4 : AUTH_KRB5);
+	}
+
+	
+#else
+    if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
+	ruserok(hostname[0] ? hostname : hostaddra,
+		pwd->pw_uid == 0, remuser, locuser) < 0) {
+	error("Permission denied.\n");
+	goto signout_please;
+    }
+#endif /* KERBEROS */
+
+
+    if (checksum_required && !valid_checksum) {
+	if (auth_sent & AUTH_KRB5) {
+	    syslog(LOG_WARNING, "Client did not supply required checksum--connection rejected.");
+	    error( "You are using an old Kerberos5 client without checksum support; only newer clients are authorized.\n");
+	    goto signout_please;
+	} else {
+	    syslog(LOG_WARNING,
+   "Configuration error: Requiring checksums with -c is inconsistent with allowing Kerberos V4 connections.");
+	}
+    }
+    if (require_encrypt&&(!do_encrypt)) {
+	error("You must use encryption.\n");
+	goto signout_please;
+    }
+    if (!(auth_ok&auth_sent)) {
+	if (auth_sent)
+	    error("Another authentication mechanism must be used to access this host.\n");
+	else
+	    error("Permission denied.\n");
+	goto signout_please;
+    }
+    
+    if (pwd->pw_uid && !access(NOLOGIN, F_OK)) {
+	error("Logins currently disabled.\n");
+	goto signout_please;
+    }
+    
+    /* Log access to account */
+    pwd = (struct passwd *) getpwnam(locuser);
+    if (pwd && (pwd->pw_uid == 0)) {
+#ifdef LOG_CMD
+	syslog(LOG_NOTICE, "Executing %s for principal %s (%s@%s (%s)) as ROOT", 
+	       cmdbuf, kremuser, remuser, hostaddra, hostname);
+#else
+	syslog(LOG_NOTICE ,"Access as ROOT by principal %s (%s@%s (%s))",
+	       kremuser, remuser, hostaddra, hostname);
+#endif
+    }
+#if defined(KERBEROS) && defined(LOG_REMOTE_REALM) && !defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
+    /* Log if principal is from a remote realm */
+    else if (client && !default_realm(client))
+#endif
+  
+#if defined(KERBEROS) && defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS) 
+    /* Log if principal name does not map to local username */
+    else if (client && !princ_maps_to_lname(client, locuser))
+#endif /* LOG_OTHER_USERS */
+  
+#ifdef LOG_ALL_LOGINS /* Log everything */
+    else 
+#endif 
+  
+#if defined(LOG_REMOTE_REALM) || defined(LOG_OTHER_USERS) || defined(LOG_ALL_LOGINS)
+      {
+#ifdef LOG_CMD
+	  syslog(LOG_NOTICE, "Executing %s for principal %s (%s@%s (%s)) as local user %s", 
+		 cmdbuf, kremuser, remuser, hostaddra, hostname, locuser);
+#else
+	  syslog(LOG_NOTICE ,"Access as %s by principal %s (%s@%s (%s))",
+		 locuser, kremuser, remuser, hostaddra, hostname);
+#endif
+      }
+#endif
+    
+    (void) write(2, "", 1);
+    
+    if (port||do_encrypt) {
+	if (port&&(pipe(pv) < 0)) {
+	    error("Can't make pipe.\n");
+	    goto signout_please;
+	}
+	if (pipe(pw) < 0) {
+	    error("Can't make pipe 2.\n");
+	    goto signout_please;
+	}
+	if (pipe(px) < 0) {
+	    error("Can't make pipe 3.\n");
+	    goto signout_please;
+	}
+	pid = fork();
+	if (pid == -1)  {
+	    error("Fork failed.\n");
+	    goto signout_please;
+	}
+	if (pid) {
+	    int maxfd;
+#ifdef POSIX_SIGNALS
+	    sa.sa_handler = cleanup;
+	    (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
+	    (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
+	    (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
+	    (void)sigaction(SIGHUP, &sa, (struct sigaction *)0);
+
+	    sa.sa_handler = SIG_IGN;
+	    /* SIGPIPE is a crutch that we don't need if we check 
+	       the exit status of write. */
+	    (void)sigaction(SIGPIPE, &sa, (struct sigaction *)0);
+	    (void)sigaction(SIGCHLD, &sa, (struct sigaction *)0);
+#else
+	    signal(SIGINT, cleanup);
+	    signal(SIGQUIT, cleanup);
+	    signal(SIGTERM, cleanup);
+	    signal(SIGHUP, cleanup);
+	    /* SIGPIPE is a crutch that we don't need if we check 
+	       the exit status of write. */
+	    signal(SIGPIPE, SIG_IGN);
+	    signal(SIGCHLD,SIG_IGN);
+#endif
+	    
+	    (void) close(0); (void) close(1); (void) close(2);
+	    if(port)
+		(void) close(pv[1]);
+	    (void) close(pw[1]);
+	    (void) close(px[0]);
+	    
+	    
+	    
+	    FD_ZERO(&readfrom);
+	    FD_SET(f, &readfrom);
+	    maxfd = f;
+	    if(port) {
+		FD_SET(s, &readfrom);
+		if (s > maxfd)
+		    maxfd = s;
+		FD_SET(pv[0], &readfrom);
+		if (pv[0] > maxfd)
+		    maxfd = pv[0];
+	    }
+	    FD_SET(pw[0], &readfrom);
+	    if (pw[0] > maxfd)
+		maxfd = pw[0];
+	    
+	    /* read from f, write to px[1] -- child stdin */
+	    /* read from s, signal child */
+	    /* read from pv[0], write to s -- child stderr */
+	    /* read from pw[0], write to f -- child stdout */
+
+	    do {
+		ready = readfrom;
+		if (select(maxfd + 1, &ready, (fd_set *)0,
+			   (fd_set *)0, (struct timeval *)0) < 0) {
+		    if (errno == EINTR) {
+			continue;
+		    } else {
+			break;
+		}
+		}
+
+		if (port&&FD_ISSET(pv[0], &ready)) {
+		    /* read from the child stderr, write to the net */
+		    errno = 0;
+		    cc = read(pv[0], buf, sizeof (buf));
+		    if (cc <= 0) {
+			shutdown(s, 1+1);
+			FD_CLR(pv[0], &readfrom);
+		    } else {
+			(void) rcmd_stream_write(s, buf, (unsigned) cc, 1);
+		    }
+		}
+		if (FD_ISSET(pw[0], &ready)) {
+		    /* read from the child stdout, write to the net */
+		    errno = 0;
+		    cc = read(pw[0], buf, sizeof (buf));
+		    if (cc <= 0) {
+			shutdown(f, 1+1);
+			FD_CLR(pw[0], &readfrom);
+		    } else {
+			(void) rcmd_stream_write(f, buf, (unsigned) cc, 0);
+		    }
+		}
+		if (port&&FD_ISSET(s, &ready)) {
+		    /* read from the alternate channel, signal the child */
+		    if (rcmd_stream_read(s, &sig, 1, 1) <= 0) {
+			FD_CLR(s, &readfrom);
+		    } else {
+#ifdef POSIX_SIGNALS
+			sa.sa_handler = cleanup;
+			(void)sigaction(sig, &sa, (struct sigaction *)0);
+			kill(-pid, sig);
+#else
+			signal(sig, cleanup);
+			killpg(pid, sig);
+#endif
+		    }
+		}
+		if (FD_ISSET(f, &ready)) {
+		    /* read from the net, write to child stdin */
+		    errno = 0;
+		    cc = rcmd_stream_read(f, buf, sizeof(buf), 0);
+		    if (cc <= 0) {
+			(void) close(px[1]);
+			FD_CLR(f, &readfrom);
+		    } else {
+		        int wcc;
+		        wcc = write(px[1], buf, (unsigned) cc);
+			if (wcc == -1) {
+			  /* pipe closed, don't read any more */
+			  /* might check for EPIPE */
+			  (void) close(px[1]);
+			  FD_CLR(f, &readfrom);
+			} else if (wcc != cc) {
+			  syslog(LOG_INFO, "only wrote %d/%d to child", 
+				 wcc, cc);
+			}
+		    }
+		}
+	    } while ((port&&FD_ISSET(s, &readfrom)) ||
+		     FD_ISSET(f, &readfrom) ||
+		     (port&&FD_ISSET(pv[0], &readfrom) )||
+		     FD_ISSET(pw[0], &readfrom));
+	    ignore_signals();
+#ifdef KERBEROS
+	    syslog(LOG_INFO ,
+		   "Shell process completed.");
+#endif
+	    /* Finish session in wmtp */
+	    pty_logwtmp(ttyn,"","");
+	    if (ccache)
+		krb5_cc_destroy(bsd_context, ccache);
+	    exit(0);
+	}
+#if defined(HAVE_SETSID)&&(!defined(ULTRIX))
+	setsid();
+#else
+#ifdef SETPGRP_TWOARG
+	setpgrp(0, getpid());
+#else
+	setpgrp();
+#endif /*setpgrp_twoarg*/
+#endif /*HAVE_SETSID*/
+	(void) close(s);
+	(void) close(f);
+	(void) close(pw[0]);
+	if (port)
+	    (void) close(pv[0]);
+	(void) close(px[1]);
+
+	(void) dup2(px[0], 0);
+	(void) dup2(pw[1], 1);
+	if(port)
+	    (void) dup2(pv[1], 2);
+	else dup2(pw[1], 2);
+
+	(void) close(px[0]);
+	(void) close(pw[1]);
+	if(port)
+	    (void) close(pv[1]);
+    }
+    
+    /*      We are simply execing a program over rshd : log entry into wtmp, 
+	    as kexe(pid), then finish out the session right after that.
+	    Syslog should have the information as to what was exec'd */
+    else {
+	pty_logwtmp(ttyn,"","");
+    }
+    
+    if (*pwd->pw_shell == '\0')
+      pwd->pw_shell = "/bin/sh";
+    (void) close(f);
+    (void) setgid((gid_t)pwd->pw_gid);
+#ifndef sgi
+    if (getuid() == 0 || getuid() != pwd->pw_uid) {
+        /* For testing purposes, we don't call initgroups if we
+           already have the right uid, and it is not root.  This is
+           because on some systems initgroups outputs an error message
+           if not called by root.  */
+        initgroups(pwd->pw_name, pwd->pw_gid);
+    }
+#endif
+#ifdef	HAVE_SETLUID
+    /*
+     * If we're on a system which keeps track of login uids, then
+     * set the login uid. 
+     */
+    if (setluid((uid_t) pwd->pw_uid) < 0) {
+	perror("setluid");
+	_exit(1);
+    }
+#endif	/* HAVE_SETLUID */
+    if (setuid((uid_t)pwd->pw_uid) < 0) {
+	perror("setuid");
+	_exit(1);
+    }
+    /* if TZ is set in the parent, drag it in */
+    {
+      char **findtz = environ;
+      while(*findtz) {
+	if(!strncmp(*findtz,"TZ=",3)) {
+	  envinit[TZENV] = *findtz;
+	  break;
+	}
+	findtz++;
+      }
+    }
+    strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
+    strncat(shell, pwd->pw_shell, sizeof(shell)-7);
+    strncat(username, pwd->pw_name, sizeof(username)-6);
+    path = (char *) malloc(strlen(kprogdir) + strlen(path_rest) + 7);
+    if (path == NULL) {
+        perror("malloc");
+	_exit(1);
+    }
+    sprintf(path, "PATH=%s:%s", kprogdir, path_rest);
+    envinit[PATHENV] = path;
+
+    /* If we have KRB5CCNAME set, then copy into the
+     * child's environment.  This can't really have
+     * a fixed position because tz may or may not be set.
+     */
+    if (getenv("KRB5CCNAME")) {
+	int i;
+	char *buf2 = (char *)malloc(strlen(getenv("KRB5CCNAME"))
+			 		   +strlen("KRB5CCNAME=")+1);
+	if (buf2) {
+	  sprintf(buf2, "KRB5CCNAME=%s",getenv("KRB5CCNAME"));
+
+	  for (i = 0; envinit[i]; i++);
+	  envinit[i] = buf2;
+	}
+    }
+
+    {
+      char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+      int i;
+      /* these four are covered by ADDRPAD */
+
+      for (i = 0; envinit[i]; i++);
+
+      aierr = getnameinfo((struct sockaddr *)&localaddr,
+			  socklen((struct sockaddr *)&localaddr),
+			  hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+			  NI_NUMERICHOST | NI_NUMERICSERV);
+      if (aierr)
+	  goto skip_localaddr_env;
+      sprintf(local_addr,  "KRB5LOCALADDR=%s", hbuf);
+      envinit[i++] =local_addr;
+
+      sprintf(local_port,  "KRB5LOCALPORT=%s", sbuf);
+      envinit[i++] =local_port;
+    skip_localaddr_env:
+
+      aierr = getnameinfo(fromp, socklen(fromp),
+			  hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+			  NI_NUMERICHOST | NI_NUMERICSERV);
+      if (aierr)
+	  goto skip_remoteaddr_env;
+      sprintf(remote_addr, "KRB5REMOTEADDR=%s", hbuf);
+      envinit[i++] =remote_addr;
+
+      sprintf(remote_port, "KRB5REMOTEPORT=%s", sbuf);
+      envinit[i++] =remote_port;
+
+    skip_remoteaddr_env:
+      ;
+    }
+
+    /* If we do anything else, make sure there is space in the array. */
+
+    for(cnt=0; cnt < num_env; cnt++) {
+	    int i;
+	    char *buf2;
+
+	    if(getenv(save_env[cnt])) {
+		    buf2 = (char *)malloc(strlen(getenv(save_env[cnt]))
+					 +strlen(save_env[cnt])+2);
+		    if (buf2) {
+			    sprintf(buf2, "%s=%s", save_env[cnt], 
+				    getenv(save_env[cnt]));
+			    for (i = 0; envinit[i]; i++);
+			    envinit[i] = buf2;
+		    }
+	    }
+    }
+
+    /* XXX - If we do anything else, make sure there is space in the array. */
+
+    environ = envinit;
+    
+#ifdef KERBEROS
+    /* To make Kerberos rcp work correctly, we must ensure that we
+       invoke Kerberos rcp on this end, not normal rcp, even if the
+       shell startup files change PATH.  */
+    if (!strncmp(cmdbuf, "rcp ", 4) ||
+	(do_encrypt && !strncmp(cmdbuf, "-x rcp ", 7))) {
+        char *copy;
+	struct stat s2;
+	int offst = 0;
+
+	copy = malloc(strlen(cmdbuf) + 1);
+	if (copy == NULL) {
+	    perror("malloc");
+	    _exit(1);
+	}
+	strcpy(copy, cmdbuf);
+	if (do_encrypt && !strncmp(cmdbuf, "-x ", 3)) {
+		offst = 3;
+	}
+
+        strcpy((char *) cmdbuf + offst, kprogdir);
+	cp = copy + 3 + offst;
+
+	cmdbuf[sizeof(cmdbuf) - 1] = '\0';
+	if (auth_sys == KRB5_RECVAUTH_V4) {
+	  strncat(cmdbuf, "/v4rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
+	} else {
+	  strncat(cmdbuf, "/rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
+	}
+	if (stat((char *)cmdbuf + offst, &s2) >= 0)
+	  strncat(cmdbuf, cp, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
+	else
+	  strncpy(cmdbuf, copy, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
+	free(copy);
+    }
+#endif
+
+    cp = strrchr(pwd->pw_shell, '/');
+    if (cp)
+      cp++;
+    else
+      cp = pwd->pw_shell;
+    
+    if (do_encrypt && !strncmp(cmdbuf, "-x ", 3)) {
+	execl(pwd->pw_shell, cp, "-c", (char *)cmdbuf + 3, (char *)NULL);
+    }
+    else {
+	execl(pwd->pw_shell, cp, "-c", cmdbuf, (char *)NULL);
+    }
+    perror(pwd->pw_shell);
+    perror(cp);
+    exit(1);
+    
+  signout_please:
+    if (ccache)
+	krb5_cc_destroy(bsd_context, ccache);
+    ccache = NULL;
+    pty_logwtmp(ttyn,"","");
+    exit(1);
+}
+
+
+void
+#ifdef HAVE_STDARG_H
+error(char *fmt, ...)
+#else
+/*VARARGS1*/
+error(fmt, va_alist)
+     char *fmt;
+     va_dcl
+#endif
+{
+    va_list ap;
+    char buf[RCMD_BUFSIZ],  *cp = buf;
+    
+#ifdef HAVE_STDARG_H
+    va_start(ap, fmt);
+#else
+    va_start(ap);
+#endif
+
+    *cp++ = 1;
+    (void) sprintf(cp, "%s: ", progname);
+    (void) vsprintf(buf+strlen(buf), fmt, ap);
+    va_end(ap);
+    (void) write(2, buf, strlen(buf));
+    syslog(LOG_ERR ,"%s",buf+1);
+}
+
+
+void getstr(fd, buf, cnt, err)
+    int fd;
+    char *buf;
+    int cnt;
+    char *err;
+{
+    char c;
+    
+    do {
+	if (read(fd, &c, 1) != 1)
+	  exit(1);
+	*buf++ = c;
+	if (--cnt == 0) {
+	    error("%s too long\n", err);
+	    exit(1);
+	}
+    } while (c != 0);
+}
+
+#ifdef	CRAY
+char *makejtmp(uid, gid, jid)
+     register int uid, gid, jid;
+{
+    register char *endc, *tdp = &tmpdir[strlen(tmpdir)];
+    register int i;
+    
+    sprintf(tdp, "%s/jtmp.%06d", JTMPDIR, jid);
+    endc = &tmpdir[strlen(tmpdir)];
+    
+    endc[1] = '\0';
+    for (i = 0; i < 26; i++) {
+	endc[0] = 'a' + i;
+	if (mkdir(tdp, JTMPMODE) != -1) {
+	    chown(tdp, uid, gid);
+	    return (tdp);
+	} else if (errno != EEXIST)
+	  break;
+    }
+    return(NULL);
+}
+
+
+
+cleanjtmp(user, tpath)
+     register char *user, *tpath;
+{
+    switch(fork()) {
+      case -1:
+	break;
+      case 0:
+	if (secflag) {
+	    execl("/bin/rm", "rm", "-rf", tpath, 0);
+	    error("exec of %s failed; errno = %d\n",
+		  "/bin/rm", errno);
+	} else {
+	    execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
+	    error("exec of %s failed; errno = %d\n",
+		  CLEANTMPCMD, errno);
+	}
+	exit(1);
+	break;
+      default:
+	/*
+	 * Just forget about the child, let init will pick it
+	 * up after we exit.
+	 */
+	break;
+    }
+}
+
+
+
+/***get_packet_classification
+ *
+ *
+ *      int get_packet_classification():
+ *      Obtain packet level and compartments from passed fd...
+ *
+ *      Returns:
+ *             -1: If could not get user defaults.
+ *              0: success
+ */
+#ifdef IP_SECURITY
+static int get_packet_classification(fd,useruid,level,comp)
+     int fd;
+     uid_t useruid;
+     int *level;
+     long *comp;
+{
+    struct socket_security pkt_sec;
+    struct udb *udb;
+    int retval;
+    int sockoptlen;
+    
+    retval = 0;
+    getsysudb ();
+    udb = getudbuid ((int) useruid);
+    endudb ();
+    if (udb == (struct udb *) 0) return(-1);
+    /* Get packet IP packet label */
+    sockoptlen = SIZEOF_sec;
+    if ( getsockopt(fd,SOL_SOCKET,SO_SECURITY,
+		    (char *) &pkt_sec,&sockoptlen)){  /* Failed */
+	return(-2);
+    }
+    *level = pkt_sec.sec_level;
+    *comp = udb->ue_defcomps;
+    return(0);
+}
+
+#else  /* If no IP_SECURITY set level to users default */
+
+static int get_packet_classification(fd,useruid,level,comp)
+     int fd;
+     uid_t useruid;
+     int *level;
+     long *comp;
+{
+    struct udb    *udb;
+    getsysudb ();
+    udb = getudbuid ((int) useruid);
+    endudb ();
+    if (udb == (struct udb *) 0) return(-1);
+    *level = udb->ue_deflvl;
+    *comp = udb->ue_defcomps;
+    return(0);
+}
+
+#endif /* IP_SECURITY */
+	
+	
+
+/*
+ * Make a security log entry for the login attempt.
+ *     host = pointer to host id
+ *     flag = status of login
+ *     failures = current losing streak in login attempts
+ */
+/* Make a security log entry for the login attempt.
+ *  host = pointer to host id
+ *  flag = status of login
+ *  failures = current losing streak in login attempts
+ */
+
+loglogin(host, flag, failures, ue)
+     char    *host;
+     int     flag;
+     int     failures;
+     struct udb * ue;
+{
+    char   urec[sizeof(struct slghdr) + sizeof(struct slglogin)];
+    struct slghdr   *uhdr = (struct slghdr *)urec;
+    struct slglogin *ulogin=(struct slglogin *)&urec[sizeof(struct slghdr)];
+    
+    strncpy(ulogin->sl_line, ttyn, sizeof(ulogin->sl_line));
+    strncpy(ulogin->sl_host, host, sizeof(ulogin->sl_host));
+    ulogin->sl_failures = failures;
+    if ( maxlogs && (failures >= maxlogs))
+      flag |= SLG_DSABL;
+    ulogin->sl_result = flag;
+    uhdr->sl_uid = ue->ue_uid;
+    uhdr->sl_ruid = ue->ue_uid;
+    uhdr->sl_juid = ue->ue_uid;
+    uhdr->sl_gid = ue->ue_gids[0];
+    uhdr->sl_rgid = ue->ue_gids[0];
+    uhdr->sl_slvl = ue->ue_deflvl;
+    /*      uhdr->sl_scls = ue->ue_defcls;  enable for integrity policy */
+    uhdr->sl_olvl = 0;
+    uhdr->sl_len = sizeof(urec);
+    
+#ifdef  CRAY2
+    slgentry(SLG_LOGN, (word *)urec);
+#else /*        ! CRAY2 */
+    slgentry(SLG_LOGN, (waddr_t)urec);
+#endif
+    return;
+}
+
+#endif /* CRAY */
+	
+
+
+void usage()
+{
+#ifdef KERBEROS
+    syslog(LOG_ERR, "usage: kshd [-54ecikK]  ");
+#else
+    syslog(LOG_ERR, "usage: rshd");
+#endif
+}
+
+
+#ifdef KERBEROS
+
+#ifndef KRB_SENDAUTH_VLEN
+#define	KRB_SENDAUTH_VLEN 8	    /* length for version strings */
+#endif
+
+#define	KRB_SENDAUTH_VERS	"AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
+					      chars */
+
+static krb5_error_code
+recvauth(netfd, peersin, valid_checksum)
+     int netfd;
+     struct sockaddr *peersin;
+     int *valid_checksum;
+{
+    krb5_auth_context auth_context = NULL;
+    krb5_error_code status;
+    struct sockaddr_in laddr;
+    socklen_t len;
+    krb5_data inbuf;
+#ifdef KRB5_KRB4_COMPAT
+    char v4_instance[INST_SZ];	/* V4 Instance */
+#endif
+    krb5_authenticator *authenticator;
+    krb5_ticket        *ticket;
+    krb5_rcache		rcache;
+    struct passwd *pwd;
+    uid_t uid;
+    gid_t gid;
+    enum kcmd_proto kcmd_proto;
+    krb5_data version;
+
+    *valid_checksum = 0;
+    len = sizeof(laddr);
+    if (getsockname(netfd, (struct sockaddr *)&laddr, &len)) {
+	    exit(1);
+    }
+	
+#ifdef unicos61
+#define SIZEOF_INADDR  SIZEOF_in_addr
+#else
+#define SIZEOF_INADDR sizeof(struct in_addr)
+#endif
+
+#ifdef KRB5_KRB4_COMPAT
+    strcpy(v4_instance, "*");
+#endif
+
+    status = krb5_auth_con_init(bsd_context, &auth_context);
+    if (status)
+	return status;
+
+    status = krb5_auth_con_genaddrs(bsd_context, auth_context, netfd,
+			        KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
+    if (status)
+	return status;
+
+    status = krb5_auth_con_getrcache(bsd_context, auth_context, &rcache);
+    if (status) return status;
+
+    if (! rcache) {
+	krb5_principal server;
+
+	status = krb5_sname_to_principal(bsd_context, 0, 0,
+					 KRB5_NT_SRV_HST, &server);
+	if (status) return status;
+
+	status = krb5_get_server_rcache(bsd_context,
+				krb5_princ_component(bsd_context, server, 0),
+				&rcache);
+	krb5_free_principal(bsd_context, server);
+	if (status) return status;
+
+	status = krb5_auth_con_setrcache(bsd_context, auth_context, rcache);
+	if (status) return status;
+    }
+
+#ifdef KRB5_KRB4_COMPAT
+    status = krb5_compat_recvauth_version(bsd_context, &auth_context, &netfd,
+				  NULL,		/* Specify daemon principal */
+				  0, 		/* no flags */
+				  keytab, /* normally NULL to use v5srvtab */
+				  0, 		/* v4_opts */
+				  "rcmd", 	/* v4_service */
+				  v4_instance, 	/* v4_instance */
+				  (struct sockaddr_in *)peersin, /* foreign address */
+				  &laddr, 	/* our local address */
+				  "", 		/* use default srvtab */
+
+				  &ticket, 	/* return ticket */
+				  &auth_sys, 	/* which authentication system*/
+				  &v4_kdata, 0, &version);
+#else
+    status = krb5_recvauth_version(bsd_context, &auth_context, &netfd,
+				   NULL,        /* daemon principal */
+				   0,           /* no flags */
+				   keytab,      /* normally NULL to use v5srvtab */
+				   &ticket,    /* return ticket */
+				   &version); /* application version string */
+    auth_sys = KRB5_RECVAUTH_V5;
+#endif
+    if (status) {
+	if (auth_sys == KRB5_RECVAUTH_V5) {
+	    /*
+	     * clean up before exiting
+	     */
+	    getstr(netfd, locuser, sizeof(locuser), "locuser");
+	    getstr(netfd, cmdbuf, sizeof(cmdbuf), "command");
+	    getstr(netfd, remuser, sizeof(locuser), "remuser");
+	}
+	return status;
+    }
+
+    getstr(netfd, locuser, sizeof(locuser), "locuser");
+    getstr(netfd, cmdbuf, sizeof(cmdbuf), "command");
+
+#ifdef KRB5_KRB4_COMPAT
+    if (auth_sys == KRB5_RECVAUTH_V4) {
+	rcmd_stream_init_normal();
+	
+	/* We do not really know the remote user's login name.
+         * Assume it to be the same as the first component of the
+	 * principal's name. 
+         */
+	strcpy(remuser, v4_kdata->pname);
+
+	status = krb5_425_conv_principal(bsd_context, v4_kdata->pname,
+					 v4_kdata->pinst, v4_kdata->prealm,
+					 &client);
+	if (status) return status;
+
+	status = krb5_unparse_name(bsd_context, client, &kremuser);
+	
+	return status;
+    }
+#endif /* KRB5_KRB4_COMPAT */
+
+    /* Must be V5  */
+	
+    kcmd_proto = KCMD_UNKNOWN_PROTOCOL;
+    if (version.length != 9)
+	fatal (netfd, "bad application version length");
+    if (!memcmp (version.data, "KCMDV0.1", 9))
+	kcmd_proto = KCMD_OLD_PROTOCOL;
+    if (!memcmp (version.data, "KCMDV0.2", 9))
+	kcmd_proto = KCMD_NEW_PROTOCOL;
+
+    getstr(netfd, remuser, sizeof(locuser), "remuser");
+
+    if ((status = krb5_unparse_name(bsd_context, ticket->enc_part2->client, 
+				    &kremuser)))
+	return status;
+    
+    if ((status = krb5_copy_principal(bsd_context, ticket->enc_part2->client, 
+				      &client)))
+	return status;
+    if ((status = krb5_auth_con_getauthenticator(bsd_context, auth_context,
+						 &authenticator)))
+      return status;
+    
+    if (authenticator->checksum && !checksum_ignored) {
+	struct sockaddr_storage adr;
+	unsigned int adr_length = sizeof(adr);
+	int e;
+	unsigned int buflen = strlen(cmdbuf)+strlen(locuser)+32;
+	char * chksumbuf = (char *) malloc(buflen);
+
+	if (chksumbuf == 0)
+	    goto error_cleanup;
+	if (getsockname(netfd, (struct sockaddr *) &adr, &adr_length) != 0)
+	    goto error_cleanup;
+
+	e = getnameinfo((struct sockaddr *)&adr, adr_length, 0, 0,
+			chksumbuf, buflen, NI_NUMERICSERV);
+	if (e) {
+	    free(chksumbuf);
+	    fatal(netfd, "local error: can't examine port number");
+	}
+	if (strlen(chksumbuf) > 30) {
+	    free(chksumbuf);
+	    fatal(netfd, "wacky local port number?!");
+	}
+	strcat(chksumbuf, ":");
+	strcat(chksumbuf,cmdbuf);
+	strcat(chksumbuf,locuser);
+
+	status = krb5_verify_checksum(bsd_context,
+				      authenticator->checksum->checksum_type,
+				      authenticator->checksum,
+				      chksumbuf, strlen(chksumbuf),
+				      ticket->enc_part2->session->contents, 
+				      ticket->enc_part2->session->length);
+
+    error_cleanup:
+	if (chksumbuf)
+	    free(chksumbuf);
+	if (status) {
+	    krb5_free_authenticator(bsd_context, authenticator);
+	    return status;
+	}
+	*valid_checksum = 1;
+    }
+    krb5_free_authenticator(bsd_context, authenticator);
+
+
+    if (!strncmp(cmdbuf, "-x ", 3))
+	do_encrypt = 1;
+
+    {
+	krb5_keyblock *key;
+	status = krb5_auth_con_getrecvsubkey (bsd_context, auth_context,
+					      &key);
+	if (status)
+	    fatal (netfd, "Server can't get session subkey");
+	if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL)
+	    fatal (netfd, "No session subkey sent");
+	if (key && kcmd_proto == KCMD_OLD_PROTOCOL) {
+#ifdef HEIMDAL_FRIENDLY
+	    key = 0;
+#else
+	    fatal (netfd, "Session subkey not allowed in old kcmd protocol");
+#endif
+	}
+	if (key == 0)
+	    key = ticket->enc_part2->session;
+	rcmd_stream_init_krb5 (key, do_encrypt, 0, 0, kcmd_proto);
+    }
+
+    /* Null out the "session" because kcmd.c references the session
+     * key here, and we do not want krb5_free_ticket() to destroy it. */
+    ticket->enc_part2->session = 0;
+
+    if ((status = krb5_read_message(bsd_context, (krb5_pointer)&netfd,
+				    &inbuf))) {
+	error("Error reading message: %s\n", error_message(status));
+	exit(1);
+    }
+
+    if (inbuf.length) { /* Forwarding being done, read creds */
+	pwd = getpwnam(locuser);
+	if (!pwd) {
+	    error("Login incorrect.\n");
+	    exit(1);
+	}
+	uid = pwd->pw_uid;
+	gid = pwd->pw_gid;
+	if ((status = rd_and_store_for_creds(bsd_context, auth_context, &inbuf,
+					     ticket, &ccache))) {
+	    error("Can't get forwarded credentials: %s\n",
+		  error_message(status));
+	    exit(1);
+	}
+	if (chown(krb5_cc_get_name(bsd_context, ccache), uid, gid) == -1) {
+	    error("Can't chown forwarded credentials: %s\n",
+		  error_message(errno));
+	    exit(1);
+	}
+    }
+    krb5_free_ticket(bsd_context, ticket);
+    return 0;
+}
+#endif /* KERBEROS */
+
+
+
+void fatal(f, msg)
+     int f;
+     const char *msg;
+{
+    char buf[512];
+#ifndef POSIX_TERMIOS
+    int out = 1 ;          /* Output queue of f */
+#endif
+
+    buf[0] = '\01';             /* error indicator */
+    (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
+    if ((f == netf) && (pid > 0))
+      (void) rcmd_stream_write(f, buf, strlen(buf), 0);
+    else
+      (void) write(f, buf, strlen(buf));
+    syslog(LOG_ERR,"%s\n",msg);
+    if (pid > 0) {
+        signal(SIGCHLD,SIG_IGN);
+        kill(pid,SIGKILL);
+#ifdef POSIX_TERMIOS
+        (void) tcflush(1, TCOFLUSH);
+#else
+        (void) ioctl(f, TIOCFLUSH, (char *)&out);
+#endif
+        cleanup(-1);
+    }
+    exit(1);
+}
diff --git a/krb5-1-6/src/appl/bsd/kshd.M b/krb5-1-6/src/appl/bsd/kshd.M
new file mode 100644
index 000000000..b6d50390a
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/kshd.M
@@ -0,0 +1,211 @@
+.\" Copyright (c) 1983 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"	@(#)rshd.8	6.3 (Berkeley) 5/24/86
+.\"
+.TH KRSHD 8
+.SH NAME
+kshd \- kerberized remote shell server
+.SH SYNOPSIS
+.B /usr/local/sbin/kshd 
+[
+.B \-kr45ec
+]
+[\fB\-D\fP \fIport\fP]
+[\fB\-L\fP \fIvariable\fP]
+.SH DESCRIPTION
+.I Krshd
+is the server for the 
+.IR rcmd (3)
+routine and, consequently, for the
+.IR rsh (1)
+program.  The server provides remote execution facilities
+with authentication based on privileged port numbers from trusted hosts or 
+the Kerberos authentication system.
+.PP
+The
+.I kshd
+server is invoked by \fIinetd(8c)\fP when it receives a connection
+on the port indicated in /etc/inetd.conf.  A typical /etc/inetd.conf
+configuration line for \fIkrshd\fP might be:
+
+kshell	stream	tcp	nowait	root	/usr/local/sbin/kshd	kshd -5c
+
+When a service request is received, the following protocol is initiated:
+
+.IP 1) 
+Authentication is checked
+.IP 2)
+Check authorization via the access-control files \fI.k5login\fP and
+\fI.klogin\fP in the user's home directory.
+.IP 3)
+A null byte is returned on the initial socket
+and the command line is passed to the normal login
+shell of the user.  The
+shell inherits the network connections established
+by
+.IR krshd .
+
+\fIKrshd\fP can be configured  by command-line arguments passed
+by \fIinetd(8)\fP.
+ The options are:
+
+.IP \fB\-5\fP 10
+Allow Kerberos5 authentication with the \fI.k5login\fP access control file
+to be trusted.  If this authentication system is used by the client and
+the authorization check is passed, then the user is allowed to log in.  If
+the user has no \fI.k5login\fP file, the login will be authorized if the
+results of krb5_aname_to_localname conversion matches the account name.
+Unless special rules are configured, this will be true if and only if the
+Kerberos principal of the connecting user is in the default local realm
+and the principal portion matches the account name.
+
+.IP \fB\-4\fP 
+Allow Kerberos4 authentication with the \fI.klogin\fP access control file
+to be trusted.  If this authentication system is used by the client and the
+authorization check is passed, then the user is allowed to log in.
+
+.IP \fB\-k\fP 
+Allow Kerberos5 and Kerberos4 as acceptable authentication
+mechanisms.  This is the same as including \fB\-4\fP and \fB\-5\fP.
+
+.IP \fB\-e\fP
+Require the client to encrypt the connection.  Only Kerberos5 clients
+support encryption.
+
+.IP \fB\-L\ variable\fP
+Carry through the current value of the specified variable into the
+environment of the child.  This option can be used to preserve up to
+four variables.
+
+
+.IP \fB\-c\fP 
+Require Kerberos5 clients to present a cryptographic
+checksum of initial connection information like the name of the user
+that the client is trying to access in the initial authenticator.
+This checksum provides additionl security by preventing an attacker
+from changing the initial connection information.  To benefit from
+this security, only Kerberos5 should be trusted; Kerberos4 and rhosts
+authentication do not include this checksum.  If this option is
+specified, older Kerberos5 clients that do not send a checksum in the
+authenticator will not be able to authenticate to this server.  This
+option is mutually exclusive with the \fB-i\fP option.
+
+	If neither the \fB-c\fP or \fB-i\fP options are specified,then
+checksums are validated if presented.  Since it is difficult to remove
+a checksum from an authenticator without making the authenticator
+invalid, this default mode is almost as significant of a security
+improvement as \fB-c\fP if new clients are used.  It has the additional
+advantage of backwards compatability with some clients.
+Unfortunately, clients before Kerberos V5, Beta5, generate invalid
+checksums; if these clients are used, the \fB-i\fP option must be
+used.
+
+.IP \fB\-i\fP 
+Ignore authenticator checksums if provided.  This option
+ignore authenticator checksusm presented by current Kerberos clients
+to protect initial connection information; it is the opposite of
+\fB-c\fP.  This option is provided because some older
+clients--particularly clients predating the release of Kerberos V5
+Beta5 (May 1995)--present bogus checksums that prevent Kerberos
+authentication from succeeding in the default mode.
+
+
+.PP
+\fIKrshd\fP supports six options which may be used for testing:
+
+.IP \fB\-S\ keytab\fP 10
+Set the \fIkeytab\fP file to use.
+
+.IP \fB\-M\ realm\fP
+Set the Kerberos realm to use.
+
+.IP \fB\-A\fP
+Don't allocate a reserved port for the stderr connection.
+
+.IP \fB\-P\ path\fP
+Use the argument to find the Kerberos binaries.  Normally a compiled
+in argument is used.
+
+.IP \fB\-D\ port\fP
+Run in standalone mode, listening on \fBport\fP.  The daemon will exit
+after one connection and will not background itself.
+
+.TP
+\fB\-w \fP[\fBip\fP|\fImaxhostlen\fP[\fB,\fP[\fBno\fP]\fBstriplocal\fP]]
+Controls the form of the remote hostname passed to login(1).
+Specifying \fBip\fP results in the numeric IP address always being
+passed to login(1).  Specifying a number, \fImaxhostlen\fP, sets the
+maximum length of the hostname passed to login(1) before it will be
+passed as a numeric IP address.  If \fImaxhostlen\fP is 0, then the
+system default, as determined by the utmp or utmpx structures, is
+used.  The \fBnostriplocal\fP and \fBstriplocal\fP options, which must
+be preceded by a comma, control whether or not the local host domain
+is stripped from the remote hostname.  By default, the equivalent of
+\fBstriplocal\fP is in effect.
+
+.SH DIAGNOSTICS
+Except for the last one listed below,
+all diagnostic messages
+are returned on the initial socket,
+after which any network connections are closed.
+An error is indicated by a leading byte with a value of
+1 (0 is returned in step 3 above upon successful completion
+of all the steps prior to the execution of the login shell).
+.PP
+.B ``locuser too long''
+.br
+The name of the user on the client's machine is
+longer than 16 characters.
+.PP
+.B ``remuser too long''
+.br
+The name of the user on the remote machine is
+longer than 16 characters.
+.PP
+.B ``command too long ''
+.br
+The command line passed exceeds the size of the argument
+list (as configured into the system).
+.PP
+.B ``Login incorrect.''
+.br
+No password file entry for the user name existed.
+.PP
+.B ``No remote directory.''
+.br
+The 
+.I chdir
+command to the home directory failed.
+.PP
+.B ``Permission denied.''
+.br
+The authentication procedure described above failed.
+.PP
+.B ``Can't make pipe.''
+.br
+The pipe needed for the 
+.BR stderr ,
+wasn't created.
+.PP
+.B ``Try again.''
+.br
+A
+.I fork
+by the server failed.
+.PP
+.B ``<shellname>: ...''
+.br
+The user's login shell could not be started.  This message is returned
+on the connection associated with the
+.BR stderr ,
+and is not preceded by a flag byte.
+.SH SEE ALSO
+rshd(8), rsh(1),
+rcmd(3)
+.SH BUGS
+A facility to allow all data exchanges to be encrypted should be
+present.
+.PP
+A more extensible protocol should be used.
diff --git a/krb5-1-6/src/appl/bsd/login.M b/krb5-1-6/src/appl/bsd/login.M
new file mode 100644
index 000000000..0fceb3529
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/login.M
@@ -0,0 +1,97 @@
+.\"	login.1
+.\"
+.TH LOGIN 8
+.SH NAME
+login.krb5 \- kerberos enhanced login program
+.SH SYNOPSIS
+.B login.krb5
+[\fB\-p\fP] [\fB\-fFe\fP \fIusername\fP] 
+[\fB\-r | \-k | \-K | \-h \fP\fIhostname\fP]
+.SH DESCRIPTION
+.I login.krb5
+is a modification of the BSD login program which is used for two
+functions.  It is the sub-process used by krlogind and telnetd to
+initiate a user session and it is a replacement for the command-line
+login program which, when invoked with a password, acquires Kerberos
+tickets for the user.
+.PP
+.I login.krb5 
+will prompt for a username, or take one on the command line, as
+.I login.krb5 username
+and will then prompt for a password. This password will be used to
+acquire Kerberos Version 5 tickets and Kerberos Version 4 tickets (if
+possible.) It will also attempt to run
+.I aklog
+to get \fIAFS\fP tokens for the user. The version 5 tickets will be
+tested against a local 
+.I krb5.keytab
+if it is available, in order to verify the tickets, before letting the
+user in. However, if the password matches the entry in
+\fI/etc/passwd\fP the user will be unconditionally allowed (permitting
+use of the machine in case of network failure.)
+.SH OPTIONS
+.TP
+\fB\-p\fP
+preserve the current environment
+.TP
+\fB\-r\fP \fIhostname\fP
+pass hostname to rlogind.  Must be the last argument.
+.TP
+\fB\-h\fP \fIhostname\fP
+pass hostname to telnetd, etc.  Must be the last argument.
+.TP
+\fB\-k\fP \fIhostname\fP
+Use Kerberos V4 to login.  Must be the last argument.
+.TP
+\fB\-K\fP \fIhostname\fP
+Use Kerberos V4 to login.  Must be the last argument.
+.TP
+\fB\-f\fP \fIname\fP
+Perform pre-authenticated login, e.g., datakit, xterm, etc.; 
+allows preauthenticated login as root.
+.TP
+\fB\-F\fP \fIname\fP
+Perform pre-authenticated login, e.g., datakit, xterm, etc.; allows
+preauthenticated login as root.
+.TP
+\fB\-e\fP \fIname\fP
+Perform pre-authenticated, encrypted login.  Must do term negotiation.
+.SH CONFIGURATION
+.I login.krb5
+is also configured via 
+.I krb5.conf
+using the
+.I login
+stanza. A collection of options dealing with initial authentication are
+provided:
+.IP krb5_get_tickets
+Use password to get V5 tickets. Default value true.
+.IP krb4_get_tickets
+Use password to get V4 tickets. Default value false.
+.IP krb4_convert
+Use Kerberos conversion daemon to get V4 tickets. Default value
+false. If false, and krb4_get_tickets is true, then login will get
+the V5 tickets directly using the Kerberos V4 protocol directly.  
+This does not currently work with non MIT-V4 salt types
+(such as the AFS3 salt type.)  Note that if configuration parameter 
+is true, and the krb524d is not running, login will hang for 
+approximately a minute  under Solaris, 
+due to a Solaris socket emulation bug.
+.IP krb_run_aklog
+Attempt to run aklog. Default value false.
+.IP aklog_path
+Where to find it [not yet implemented.] Default value 
+.I $(prefix)/bin/aklog.
+.IP accept_passwd
+Don't accept plaintext passwords [not yet implemented]. Default value false.
+
+.SH DIAGNOSTICS
+All diagnostic messages are returned on the connection or tty
+associated with
+.BR stderr.
+.PP
+.SH SEE ALSO
+rlogind(8), rlogin(1), telnetd(8)
+.SH BUGS
+Should use a config file to select use of V5, V4, and AFS, as well as
+policy for startup.
diff --git a/krb5-1-6/src/appl/bsd/login.c b/krb5-1-6/src/appl/bsd/login.c
new file mode 100644
index 000000000..861b9a57a
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/login.c
@@ -0,0 +1,2505 @@
+/*
+ *	appl/bsd/login.c
+ */
+
+/*
+ * Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)login.c	5.25 (Berkeley) 1/6/89 */
+
+/* The configuration, with defaults as listed, is of the form:
+   [login]
+   # login stanza
+   krb5_get_tickets = 1
+   # use password to get v5 tickets
+   krb4_get_tickets = 0
+   # use password to get v4 tickets
+   krb4_convert = 0
+   # use kerberos conversion daemon to get v4 tickets
+   krb_run_aklog = 0
+   # attempt to run aklog
+   aklog_path = $(prefix)/bin/aklog
+   # where to find it [not yet implemented]
+   accept_passwd = 0
+   # don't accept plaintext passwords [not yet implemented]
+*/
+#define KRB5_GET_TICKETS
+int login_krb5_get_tickets = 1;
+
+#ifdef KRB5_KRB4_COMPAT
+#define KRB4_GET_TICKETS
+int login_krb4_get_tickets = 0;
+#define KRB4_CONVERT
+int login_krb4_convert = 0;
+#define KRB_RUN_AKLOG
+int login_krb_run_aklog = 0;
+#endif /* KRB5_KRB4_COMPAT */
+
+int login_accept_passwd = 0;
+
+/*
+ * login [ name ]
+ * login -r hostname	(for rlogind)
+ * login -h hostname	(for telnetd, etc.)
+ * login -f name	(for pre-authenticated login: datakit, xterm, etc.,
+ *			 does allow preauthenticated login as root)
+ * login -F name	(for pre-authenticated login: datakit, xterm, etc.,
+ *			 allows preauthenticated login as root)
+ * login -e name	(for pre-authenticated encrypted, must do term
+ *			 negotiation)
+ * ifdef KRB4_KLOGIN
+ * login -k hostname (for Kerberos V4 rlogind with password access)
+ * login -K hostname (for Kerberos V4 rlogind with restricted access)
+ * endif KRB4_KLOGIN
+ *
+ * only one of: -r -f -e -k -K -F
+ * only one of: -r -h -k -K
+ */
+
+#include <libpty.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef OQUOTA
+#include <sys/quota.h>
+#endif
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <utmp.h>
+#include <signal.h>
+
+#include <assert.h>
+
+#ifdef HAVE_LASTLOG_H
+#include <lastlog.h>
+#endif
+
+#ifdef linux
+/* linux has V* but not C* in headers. Perhaps we shouldn't be
+ * initializing these values anyway -- tcgetattr *should* give
+ * them reasonable defaults... */
+#define NO_INIT_CC
+#endif
+
+#include <errno.h>
+#ifdef HAVE_TTYENT_H
+#include <ttyent.h>
+#endif
+#include <syslog.h>
+#include <stdio.h>
+#include <grp.h>
+#include <pwd.h>
+#include <string.h>
+
+#include <setjmp.h>
+#ifndef POSIX_SETJMP
+#undef sigjmp_buf
+#undef sigsetjmp
+#undef siglongjmp
+#define sigjmp_buf	jmp_buf
+#define sigsetjmp(j,s)	setjmp(j)
+#define siglongjmp	longjmp
+#endif
+
+#ifdef POSIX_SIGNALS
+typedef struct sigaction handler;
+#define handler_init(H,F)		(sigemptyset(&(H).sa_mask), \
+					 (H).sa_flags=0, \
+					 (H).sa_handler=(F))
+#define handler_swap(S,NEW,OLD)		sigaction(S, &NEW, &OLD)
+#define handler_set(S,OLD)		sigaction(S, &OLD, NULL)
+#else
+typedef sigtype (*handler)();
+#define handler_init(H,F)		((H) = (F))
+#define handler_swap(S,NEW,OLD)		((OLD) = signal ((S), (NEW)))
+#define handler_set(S,OLD)		(signal ((S), (OLD)))
+#endif
+
+
+#ifdef HAVE_SHADOW
+#include <shadow.h>
+#endif
+
+#ifdef KRB5_GET_TICKETS
+/* #include "krb5.h" */
+/* need k5-int.h to get ->profile from krb5_context */
+#include "k5-int.h"
+#include "com_err.h"
+#include "osconf.h"
+#endif /* KRB5_GET_TICKETS */
+
+#ifdef KRB4_KLOGIN
+/* support for running under v4 klogind, -k -K flags */
+#define KRB4
+#endif
+
+#if (defined(KRB4_GET_TICKETS) || defined(KRB4_CONVERT))
+/* support for prompting for v4 initial tickets */
+#define KRB4
+#endif
+
+#ifdef KRB4
+#include <krb.h>
+#include <netinet/in.h>
+#ifdef HAVE_KRB4_PROTO_H
+#include <krb4-proto.h>
+#endif
+#include <arpa/inet.h>
+#ifdef BIND_HACK
+#include <arpa/nameser.h>
+#include <arpa/resolv.h>
+#endif /* BIND_HACK */
+
+/* Hacks to maintain compatability with Athena libkrb*/
+#ifndef HAVE_KRB_SAVE_CREDENTIALS
+#define krb_save_credentials save_credentials
+#endif /*HAVE_KRB_SAVE_CREDENTIALS*/
+
+#ifndef HAVE_KRB_GET_ERR_TEXT
+
+static const char *krb_get_err_text(kerror)
+     int kerror;
+{
+    return krb_err_txt[kerror];
+}
+
+#endif /*HAVE_KRB_GET_ERR_TEXT*/
+#endif /* KRB4 */
+
+#ifndef __STDC__
+#ifndef volatile
+#define volatile
+#endif
+#endif
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#include "loginpaths.h"
+
+#ifdef POSIX_TERMIOS
+#include <termios.h>
+#ifndef CNUL
+#define CNUL (char) 0
+#endif
+
+#endif
+
+#ifdef _IBMR2
+#include <usersec.h>
+#include <sys/id.h>
+#endif
+
+#if defined(_AIX)
+#define PRIO_OFFSET 20
+#else
+#define PRIO_OFFSET 0
+#endif
+
+#if !defined(TAB3)
+#define TAB3 0
+#endif
+
+#define	TTYGRPNAME	"tty"		/* name of group to own ttys */
+
+#if defined(_PATH_MAILDIR)
+#define MAILDIR		_PATH_MAILDIR
+#else
+#define MAILDIR		"/usr/spool/mail"
+#endif
+#if defined(_PATH_NOLOGIN)
+#define NOLOGIN		_PATH_NOLOGIN
+#else
+#define NOLOGIN		"/etc/nologin"
+#endif
+#if defined(_PATH_LASTLOG)
+#define LASTLOG		_PATH_LASTLOG
+#else
+#define LASTLOG		"/usr/adm/lastlog"
+#endif
+#if defined(_PATH_BSHELL)
+#define BSHELL		_PATH_BSHELL
+#else
+#define BSHELL		"/bin/sh"
+#endif
+
+#if (defined(BSD) && (BSD >= 199103))	/* no /usr/ucb */
+#define QUOTAWARN	"/usr/bin/quota"
+#endif
+
+#define	MOTDFILE	"/etc/motd"
+#define	HUSHLOGIN	".hushlogin"
+
+#if !defined(OQUOTA) && !defined(QUOTAWARN)
+#define QUOTAWARN	"/usr/ucb/quota" /* warn user about quotas */
+#endif
+
+#ifndef NO_UT_HOST
+#ifndef UT_HOSTSIZE
+/* linux defines it directly in <utmp.h> */
+#define	UT_HOSTSIZE	sizeof(((struct utmp *)0)->ut_host)
+#endif /* UT_HOSTSIZE */
+#endif
+#ifndef UT_NAMESIZE
+/* linux defines it directly in <utmp.h> */
+#define	UT_NAMESIZE	sizeof(((struct utmp *)0)->ut_name)
+#endif
+
+#ifndef HAVE_SETPRIORITY
+/* if we don't have it, punt it cleanly */
+#define setpriority(which,who,prio)
+#endif /* HAVE_SETPRIORITY */
+
+#define MAXENVIRON	32
+
+#ifdef NEED_SETENV
+extern int setenv(char *, char *, int);
+#endif
+
+/*
+ * This bounds the time given to login.  Not a define so it can
+ * be patched on machines where it's too small.
+ */
+int	timeout = 300;
+
+#if 0
+char term[64], *hostname, *username;
+#else
+char term[64], *username;
+#endif
+
+
+
+#ifdef KRB4
+#define KRB_ENVIRON	"KRBTKFILE"	/* Ticket file environment variable */
+#define KRB_TK_DIR	"/tmp/tkt_"	/* Where to put the ticket */
+#endif /* KRB4_GET_TICKETS */
+
+#if defined(KRB4_GET_TICKETS) || defined(KRB5_GET_TICKETS)
+#define MAXPWSIZE	128		/* Biggest string accepted for KRB4
+					   passsword */
+#endif
+
+#if defined(__SVR4) || defined(sgi)
+#define NO_MOTD
+#define NO_MAILCHECK
+#endif
+
+char *getenv();
+void dofork(void);
+
+char *stypeof(char *);
+void term_init(int);
+int doremotelogin(char *), do_krb_login(char *, int), rootterm(char *);
+void lgetstr(char *, int, char *), getloginname(void), checknologin(void);
+void dolastlog(char *, int, char *), motd(void), check_mail(void);
+void sleepexit(int);
+
+#ifndef HAVE_STRSAVE
+char * strsave(char *);
+#endif
+
+typedef krb5_sigtype sigtype;
+
+sigtype timedout(int);
+
+
+#ifndef HAVE_INITGROUPS
+static int initgroups(char* name, gid_t basegid) {
+    gid_t others[NGROUPS_MAX+1];
+    int ngrps;
+
+    others[0] = basegid;
+    ngrps = getgroups(NGROUPS_MAX, others+1);
+    return setgroups(ngrps+1, others);
+}
+#endif
+
+static struct login_confs {
+    char *flagname;
+    int *flag;
+} login_conf_set[] = {
+#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},
+#endif /* KRB5_KRB4_COMPAT */
+};
+
+static char *conf_yes[] = {
+    "y", "yes", "true", "t", "1", "on",
+    0
+};
+
+static char *conf_no[] = {
+    "n", "no", "false", "nil", "0", "off",
+    0
+};
+
+/* 1 = true, 0 = false, -1 = ambiguous */
+static int conf_affirmative(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;
+}
+
+#ifdef KRB5_GET_TICKETS
+krb5_data tgtname = {
+    0,
+    KRB5_TGS_NAME_SIZE,
+    KRB5_TGS_NAME
+};
+#endif
+
+/* get flags (listed above) from the profile */
+static void login_get_kconf(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 && *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;
+	    }
+	}
+    }
+}
+
+/* UNIX password support */
+
+struct passwd *pwd;
+static char *salt;
+
+#ifdef HAVE_SHADOW
+struct spwd *spwd;
+#endif
+
+static void lookup_user (name)
+    char *name;
+{
+    pwd = getpwnam (name);
+    salt = pwd ? pwd->pw_passwd : "xx";
+#ifdef HAVE_SHADOW
+    spwd = getspnam (name);
+    if (spwd)
+	salt = spwd->sp_pwdp;
+#endif
+}
+
+static int unix_needs_passwd ()
+{
+#ifdef HAVE_SHADOW
+    if (spwd)
+	return spwd->sp_pwdp[0] != 0;
+#endif
+    if (pwd)
+	return pwd->pw_passwd[0] != 0;
+    return 1;
+}
+
+static int unix_passwd_okay (pass)
+    char *pass;
+{
+    char user_pwcopy[9], *namep;
+    char *crypt ();
+
+    assert (pwd != 0);
+
+    /* copy the first 8 chars of the password for unix crypt */
+    strncpy(user_pwcopy, pass, sizeof(user_pwcopy));
+    user_pwcopy[sizeof(user_pwcopy) - 1]='\0';
+    namep = crypt(user_pwcopy, salt);
+    memset (user_pwcopy, 0, sizeof(user_pwcopy));
+    /* ... and wipe the copy now that we have the string */
+
+    /* verify the local password string */
+#ifdef HAVE_SHADOW
+    if (spwd)
+	return !strcmp(namep, spwd->sp_pwdp);
+#endif
+    return !strcmp (namep, pwd->pw_passwd);
+}
+
+/* Kerberos support */
+#ifdef KRB5_GET_TICKETS
+krb5_context kcontext;
+krb5_ccache ccache;
+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;
+char tkfile[MAXPATHLEN];
+#endif
+
+#ifdef KRB4_GET_TICKETS
+static void k_init (ttyn, realm)
+    char *ttyn;
+    char *realm;
+#else
+void k_init (ttyn)
+    char *ttyn;
+#endif
+{
+#ifdef KRB5_GET_TICKETS
+    krb5_error_code retval;
+    
+    retval = krb5_init_secure_context(&kcontext);
+    if (retval) {
+	com_err("login", retval, "while initializing krb5");
+	exit(1);
+    }
+
+    login_get_kconf(kcontext);
+
+    /* Set up the credential cache environment variable */
+    if (!getenv(KRB5_ENV_CCNAME)) {
+	sprintf(ccfile, "FILE:/tmp/krb5cc_p%ld", (long) getpid());
+	setenv(KRB5_ENV_CCNAME, ccfile, 1);
+	krb5_cc_set_default_name(kcontext, ccfile);
+	unlink(ccfile+strlen("FILE:"));
+    } else {
+	/* note it correctly */
+	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) {
+	strncpy(realm, KRB_REALM, sizeof(realm));
+	realm[sizeof(realm) - 1] = '\0';
+    }
+    if (login_krb4_get_tickets || login_krb4_convert) {
+	/* Set up the ticket file environment variable */
+	strncpy(tkfile, KRB_TK_DIR, sizeof(tkfile));
+	tkfile[sizeof(tkfile) - 1] = '\0';
+	strncat(tkfile, strrchr(ttyn, '/')+1,
+		sizeof(tkfile) - strlen(tkfile));
+	(void) unlink (tkfile);
+	setenv(KRB_ENVIRON, tkfile, 1);
+    }
+#endif
+
+#ifdef BIND_HACK
+    /* Set name server timeout to be reasonable,
+       so that people don't take 5 minutes to
+       log in.  Can you say abstraction violation? */
+    _res.retrans = 1;
+#endif /* BIND_HACK */
+}
+
+#ifdef KRB5_GET_TICKETS
+static int k5_get_password (user_pwstring, pwsize)
+    char *user_pwstring;
+    unsigned int pwsize;
+{
+    krb5_error_code code;
+    char prompt[255];			
+    sprintf(prompt,"Password for %s", username);
+
+    /* reduce opportunities to be swapped out */
+    code = krb5_read_password(kcontext, prompt, 0, user_pwstring, &pwsize);
+    if (code || pwsize == 0) {
+	fprintf(stderr, "Error while reading password for '%s'\n", username);
+	/* reading password failed... */
+	return 0;
+    }
+    if (pwsize == 0) {
+	fprintf(stderr, "No password read\n");
+	/* reading password failed... */
+	return 0;
+    }
+    return 1;
+}
+
+static int try_krb5 (me_p, pass)
+    krb5_principal *me_p;
+    char *pass;
+{
+    krb5_error_code code;
+    krb5_principal me;
+
+    code = krb5_parse_name(kcontext, username, &me);
+    if (code) {
+	com_err ("login", code, "when parsing name %s",username);
+	return 0;
+    }
+
+    *me_p = me;
+
+    code = krb5_get_init_creds_password(kcontext, &my_creds, me, pass,
+					krb5_prompter_posix, NULL,
+					0, NULL, NULL);
+    if (code) {
+	if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+	    fprintf (stderr,
+		     "%s: Kerberos password incorrect\n", 
+		     username);
+	else
+	    com_err ("login", code,
+		     "while getting initial credentials");
+	return 0;
+    }
+
+    krbflag = got_v5_tickets = 1;
+
+    return 1;
+}
+
+static int have_v5_tickets (me)
+    krb5_principal *me;
+{
+    if (krb5_cc_default (kcontext, &ccache))
+	return 0;
+    if (krb5_cc_get_principal (kcontext, ccache, me)) {
+	krb5_cc_close (kcontext, ccache);
+	return 0;
+    }
+    krbflag = 1;
+    return 1;
+}
+#endif /* KRB5_GET_TICKETS */
+
+#ifdef KRB4_CONVERT
+static int
+try_convert524(kctx, me, use_ccache)
+    krb5_context kctx;
+    krb5_principal me;
+    int use_ccache;
+{
+    krb5_principal kpcserver;
+    krb5_error_code kpccode;
+    int kpcval;
+    krb5_creds increds, *v5creds;
+    CREDENTIALS v4creds;
+
+
+    /* If we have forwarded v5 tickets, retrieve the credentials from
+     * the cache; otherwise, the v5 credentials are in my_creds.
+     */
+    if (use_ccache) {
+	/* cc->ccache, already set up */
+	/* client->me, already set up */
+	kpccode = krb5_build_principal(kctx, &kpcserver, 
+				       krb5_princ_realm(kctx, me)->length,
+				       krb5_princ_realm(kctx, me)->data,
+				       "krbtgt",
+				       krb5_princ_realm(kctx, me)->data,
+				       NULL);
+	if (kpccode) {
+	    com_err("login/v4", kpccode,
+		    "while creating service principal name");
+	    return 0;
+	}
+
+	memset((char *) &increds, 0, sizeof(increds));
+	increds.client = me;
+	increds.server = kpcserver;
+	increds.times.endtime = 0;
+	increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+	kpccode = krb5_get_credentials(kctx, 0, ccache,
+				       &increds, &v5creds);
+	krb5_free_principal(kctx, kpcserver);
+	increds.server = NULL;
+	if (kpccode) {
+	    com_err("login/v4", kpccode, "getting V5 credentials");
+	    return 0;
+	}
+
+	kpccode = krb524_convert_creds_kdc(kctx, v5creds, &v4creds);
+	krb5_free_creds(kctx, v5creds);
+    } else
+	kpccode = krb524_convert_creds_kdc(kctx, &my_creds, &v4creds);
+    if (kpccode) {
+	com_err("login/v4", kpccode, "converting to V4 credentials");
+	return 0;
+    }
+    /* this is stolen from the v4 kinit */
+    /* initialize ticket cache */
+    if ((kpcval = in_tkt(v4creds.pname,v4creds.pinst)
+	 != KSUCCESS)) {
+	com_err("login/v4", kpcval,
+		"trying to create the V4 ticket file");
+	return 0;
+    }
+    /* stash ticket, session key, etc. for future use */
+    if ((kpcval = krb_save_credentials(v4creds.service,
+				       v4creds.instance,
+				       v4creds.realm, 
+				       v4creds.session,
+				       v4creds.lifetime,
+				       v4creds.kvno,
+				       &(v4creds.ticket_st), 
+				       v4creds.issue_date))) {
+	com_err("login/v4", kpcval,
+		"trying to save the V4 ticket");
+	return 0;
+    }
+    got_v4_tickets = 1;
+    strncpy(tkfile, tkt_string(), sizeof(tkfile));
+    tkfile[sizeof(tkfile) - 1] = '\0';
+    return 1;
+}
+#endif
+
+#ifdef KRB4_GET_TICKETS
+static int
+try_krb4 (user_pwstring, realm)
+    char *user_pwstring;
+    char *realm;
+{
+    int krbval, kpass_ok = 0;
+
+    krbval = krb_get_pw_in_tkt(username, "", realm,
+			       "krbtgt", realm, 
+			       DEFAULT_TKT_LIFE,
+			       user_pwstring);
+
+    switch (krbval) {
+    case INTK_OK:
+	kpass_ok = 1;
+	krbflag = 1;
+	strncpy(tkfile, tkt_string(), sizeof(tkfile));
+	tkfile[sizeof(tkfile) - 1] = '\0';
+	break;	
+	/* These errors should be silent */
+	/* So the Kerberos database can't be probed */
+    case KDC_NULL_KEY:
+    case KDC_PR_UNKNOWN:
+    case INTK_BADPW:
+    case KDC_PR_N_UNIQUE:
+    case -1:
+	break;
+#if 0 /* I want to see where INTK_W_NOTALL comes from before letting
+	 kpass_ok be set in that case.  KR  */
+	/* These should be printed but are not fatal */
+    case INTK_W_NOTALL:
+	krbflag = 1;
+	kpass_ok = 1;
+	fprintf(stderr, "Kerberos error: %s\n",
+		krb_get_err_text(krbval));
+	break;
+#endif
+    default:
+	fprintf(stderr, "Kerberos error: %s\n",
+		krb_get_err_text(krbval));
+	break;
+    }
+    got_v4_tickets = kpass_ok;
+    return kpass_ok;
+}
+#endif /* KRB4_GET_TICKETS */
+
+/* Kerberos ticket-handling routines */
+
+#ifdef KRB4_GET_TICKETS
+/* call already conditionalized on login_krb4_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 rcmd.<host> service is unknown (i.e.,
+ * the local srvtab doesn't have it), let her in.
+ *
+ * Returns 1 for confirmation, -1 for failure, 0 for uncertainty.
+ */
+static int verify_krb_v4_tgt (realm)
+    char *realm;
+{
+    char hostname[MAXHOSTNAMELEN], phost[BUFSIZ];
+    struct hostent *hp;
+    KTEXT_ST ticket;
+    AUTH_DAT authdata;
+    unsigned KRB4_32 addr;
+    static /*const*/ char rcmd_str[] = "rcmd";
+#if 0
+    char key[8];
+#endif
+    int krbval, retval, have_keys;
+
+    if (gethostname(hostname, sizeof(hostname)) == -1) {
+	perror ("cannot retrieve local hostname");
+	return -1;
+    }
+    strncpy (phost, krb_get_phost (hostname), sizeof (phost));
+    phost[sizeof(phost)-1] = 0;
+    hp = gethostbyname (hostname);
+    if (!hp) {
+	perror ("cannot retrieve local host address");
+	return -1;
+    }
+    memcpy ((char *) &addr, (char *)hp->h_addr, sizeof (addr));
+    /* Do we have rcmd.<host> keys? */
+#if 0 /* Be paranoid.  If srvtab exists, assume it must contain the
+	 right key.  The more paranoid mode also helps avoid a
+	 possible DNS spoofing issue.  */
+    have_keys = read_service_key (rcmd_str, phost, realm, 0, KEYFILE, key)
+	? 0 : 1;
+    memset (key, 0, sizeof (key));
+#else
+    have_keys = 0 == access (KEYFILE, F_OK);
+#endif
+    krbval = krb_mk_req (&ticket, rcmd_str, phost, realm, 0);
+    if (krbval == KDC_PR_UNKNOWN) {
+	/*
+	 * Our rcmd.<host> principal isn't known -- just assume valid
+	 * for now?  This is one case that the user _could_ fake out.
+	 */
+	if (have_keys)
+	    return -1;
+	else
+	    return 0;
+    }
+    else if (krbval != KSUCCESS) {
+	printf ("Unable to verify Kerberos TGT: %s\n", 
+		krb_get_err_text(krbval));
+#ifndef SYSLOG42
+	syslog (LOG_NOTICE|LOG_AUTH, "Kerberos TGT bad: %s",
+		krb_get_err_text(krbval));
+#endif
+	return -1;
+    }
+    /* got ticket, try to use it */
+    krbval = krb_rd_req (&ticket, rcmd_str, phost, addr, &authdata, "");
+    if (krbval != KSUCCESS) {
+	if (krbval == RD_AP_UNDEC && !have_keys)
+	    retval = 0;
+	else {
+	    retval = -1;
+	    printf ("Unable to verify `rcmd' ticket: %s\n",
+		    krb_get_err_text(krbval));
+	}
+#ifndef SYSLOG42
+	syslog (LOG_NOTICE|LOG_AUTH, "can't verify rcmd ticket: %s;%s\n",
+		krb_get_err_text(krbval),
+		retval
+		? "srvtab found, assuming failure"
+		: "no srvtab found, assuming success");
+#endif
+	goto EGRESS;
+    }
+    /*
+     * The rcmd.<host> ticket has been received _and_ verified.
+     */
+    retval = 1;
+    /* do cleanup and return */
+EGRESS:
+    memset (&ticket, 0, sizeof (ticket));
+    memset (&authdata, 0, sizeof (authdata));
+    return retval;
+}
+#endif /* KRB4_GET_TICKETS */
+
+static void destroy_tickets()
+{
+#ifdef KRB5_GET_TICKETS
+    krb5_ccache cache;
+
+    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)
+	dest_tkt();
+#endif /* KRB4_GET_TICKETS */
+}
+
+/* AFS support routines */
+#ifdef SETPAG
+
+int pagflag = 0;			/* true if setpag() has been called */
+
+/* This doesn't seem to be declared in the AFS header files.  */
+extern ktc_ForgetAllTokens (), setpag ();
+
+#ifdef SIGSYS
+static sigjmp_buf setpag_buf;
+
+static sigtype sigsys ()
+{
+    siglongjmp(setpag_buf, 1);
+}
+
+static int try_afscall (scall)
+	int (*scall)();
+{
+    handler sa, osa;
+    volatile int retval = 0;
+
+    (void) &retval;
+    handler_init (sa, sigsys);
+    handler_swap (SIGSYS, sa, osa);
+    if (sigsetjmp(setpag_buf, 1) == 0) {
+	(*scall)();
+	retval = 1;
+    }
+    handler_set (SIGSYS, osa);
+    return retval;
+}
+
+#define try_setpag()	try_afscall(setpag)
+#define try_unlog()	try_afscall(ktc_ForgetAllTokens)
+#else
+#define try_setpag()	(setpag() == 0)
+#define try_unlog()	(ktc_ForgetAllTokens() == 0)
+#endif /* SIGSYS */
+#endif /* SETPAG */
+
+static void
+afs_login ()
+{
+#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
+#ifdef KRB_RUN_AKLOG
+    if (got_v4_tickets && login_krb_run_aklog) {
+	/* KPROGDIR is $(prefix)/bin */
+	char aklog_path[MAXPATHLEN];
+	struct stat st;
+	/* construct the name */
+	/* get this from profile later */
+	aklog_path[sizeof(aklog_path) - 1] = '\0';
+	strncpy (aklog_path, KPROGDIR, sizeof(aklog_path) - 1);
+	strncat (aklog_path, "/aklog", sizeof(aklog_path) - 1 - strlen(aklog_path));
+	/* only run it if we can find it */
+	if (stat (aklog_path, &st) == 0) {
+	    system(aklog_path);
+	}
+    }
+#endif /* KRB_RUN_AKLOG */
+}
+
+static void
+afs_cleanup ()
+{
+#ifdef SETPAG
+    if (pagflag)
+      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); \
+}
+
+#define EXCL_HOST_TEST if (rflag || kflag || Kflag || hflag) { \
+    fprintf(stderr, \
+	    "login: only one of -r, -k, -K, and -h allowed.\n"); \
+    exit(1); \
+}
+
+#if defined(HAVE_ETC_ENVIRONMENT) || defined(HAVE_ETC_TIMEZONE)
+static void
+read_env_vars_from_file (filename)
+    char *filename;
+{
+    FILE *fp;
+    char *p, *eq;
+    char tbuf[MAXPATHLEN+2];
+
+    if ((fp = fopen(filename, "r")) != NULL) {
+	while (fgets(tbuf, sizeof(tbuf), fp)) {
+	    if (tbuf[0] == '#')
+		continue;
+	    eq = strchr(tbuf, '=');
+	    if (eq == 0)
+		continue;
+	    p = strchr (tbuf, '\n');
+	    if (p)
+		*p = 0;
+	    *eq++ = 0;
+	    /* Don't override, in case -p was used.  */
+	    setenv (tbuf, eq, 0);
+	}
+	fclose(fp);
+    }
+}
+#endif
+
+static void
+log_repeated_failures (tty, hostname)
+    char *tty, *hostname;
+{
+    if (hostname) {
+#ifdef UT_HOSTSIZE
+	syslog(LOG_ERR,
+	       "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
+	       tty, UT_HOSTSIZE, hostname, UT_NAMESIZE,
+	       username);
+#else
+	syslog(LOG_ERR,
+	       "REPEATED LOGIN FAILURES ON %s FROM %s, %.*s",
+	       tty, hostname, UT_NAMESIZE,
+	       username);
+#endif
+    } else {
+	syslog(LOG_ERR,
+	       "REPEATED LOGIN FAILURES ON %s, %.*s",
+	       tty, UT_NAMESIZE, username);
+    }
+}
+
+int main(argc, 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;
+    char *domain, **envinit, *ttyn, *tty;
+    char tbuf[MAXPATHLEN + 2];
+    char *ttyname(), *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_ccache xtra_creds = NULL;
+#endif
+#ifdef KRB4_GET_TICKETS
+    CREDENTIALS save_v4creds;
+    char realm[REALM_SZ];
+#endif
+    char *ccname = 0;   /* name of forwarded cache */
+    char *tz = 0;
+    char *hostname = 0;
+
+    off_t lseek();
+    handler sa;
+
+    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);
+#ifdef OQUOTA
+    (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;
+#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;
+#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;
+    /* Throw away too-long names, they can't be usernames.  */
+    if (*argv) {
+	if (strlen (*argv) <= UT_NAMESIZE)
+	    username = *argv;
+	else
+	    fprintf (stderr, "login name '%s' too long\n", *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);
+#endif
+	
+#ifdef TIOCNXCL
+    (void)ioctl(0, TIOCNXCL, (char *)0);
+#endif
+	
+    ioctlval = fcntl(0, F_GETFL);
+#ifdef O_NONBLOCK
+    ioctlval &= ~O_NONBLOCK;
+#endif
+#ifdef O_NDELAY
+    ioctlval &= ~O_NDELAY;
+#endif
+    (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';
+	}
+    }
+	
+    term_init (rflag || kflag || Kflag || eflag);
+
+    for (cnt = getdtablesize(); cnt > 2; cnt--)
+	(void) close(cnt);
+
+    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;
+
+#ifndef LOG_ODELAY /* 4.2 syslog ... */                      
+    openlog("login", 0);
+#else
+    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?
+    */
+
+#ifdef KRB4_GET_TICKETS
+    k_init (ttyn, realm);
+#else
+    k_init (ttyn);
+#endif
+
+    for (cnt = 0;; username = NULL) {
+#ifdef KRB5_GET_TICKETS
+	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();
+
+	/*
+	 * Allows automatic login by root.
+	 * If not invoked by root, disallow if the uid's differ.
+	 */
+
+	if (fflag && pwd) {
+	    int uid = (int) getuid();
+	    passwd_req = (uid && uid != pwd->pw_uid);
+	}
+
+	/*
+	 * 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.
+	*/
+
+#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;
+	    }
+
+	    /* 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);
+
+	    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(user_pwstring, realm);
+#endif
+		krbflag = (got_v5_tickets
+#ifdef KRB4_GET_TICKETS
+			   || got_v4_tickets
+#endif
+			   );
+		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) {
+		retval = krb5_verify_init_creds(kcontext, &my_creds, NULL,
+						NULL, &xtra_creds,
+						NULL);
+		if (retval) {
+		    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 {
+		    break;	/* we're ok */
+		}
+	    }
+#ifdef KRB4_GET_TICKETS
+	    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 */
+	}
+#endif /* KRB5_GET_TICKETS */
+
+#ifdef OLD_PASSWD
+	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 */
+#ifdef TIOCHPCL
+	    (void)ioctl(0, TIOCHPCL, (char *)0);
+#endif
+	    sleepexit(1);
+	}
+    } /* end of password retry loop */
+
+    /* 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) {
+#ifdef UT_HOSTSIZE
+	    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);
+#endif
+	} 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);
+    }
+#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");
+    }
+
+    quietlog = access(HUSHLOGIN, F_OK) == 0;
+    dolastlog(hostname, quietlog, tty);
+
+    (void)chown(ttyn, pwd->pw_uid,
+		(gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+
+    (void)chmod(ttyn, 0620);
+
+#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, forwarded_v5_tickets);
+    }
+#endif
+
+#ifdef KRB5_GET_TICKETS
+    if (login_krb5_get_tickets)
+	dofork();
+#endif
+#ifdef KRB4_GET_TICKETS
+    else if (login_krb4_get_tickets)
+	dofork();
+#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
+   to match, otherwise stray signals may be delivered to login.krb5 or
+   telnetd or rlogind if they don't properly detach from their
+   controlling tty, which is the case (under SunOS at least.) */
+
+    {
+	int pid = getpid(); 
+	struct sigaction sa2, osa;
+
+	/* this will set the PGID to the PID. */
+#ifdef HAVE_SETPGID
+	if (setpgid(pid,pid) < 0)
+	    perror("login.krb5: setpgid");
+#elif defined(SETPGRP_TWOARG)
+	if (setpgrp(pid,pid) < 0)
+	    perror("login.krb5: setpgrp");
+#else
+	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. */
+
+	sa2.sa_flags = 0;
+	sa2.sa_handler = SIG_IGN;
+	sigemptyset(&(sa2.sa_mask));
+
+	if (sigaction(SIGTTOU, &sa2, &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). */
+#ifdef HAVE_TCSETPGRP
+	if (tcsetpgrp(0, pid) < 0)
+	    perror("login.krb5: tcsetpgrp");
+#else
+	if (ioctl(0, TIOCSPGRP, &pid) < 0)
+	    perror("login.krb5: tiocspgrp");
+#endif
+
+	/* This will reset the SIGTTOU 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);
+
+    /*
+     * 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 (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;
+
+	    retval = krb5_cc_retrieve_cred(kcontext, ccache, 0,
+					   &mcreds, &save_v5creds);
+	    if (retval) {
+		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;
+	}
+    }
+#endif /* KRB4_GET_TICKETS */
+
+#ifdef KRB5_GET_TICKETS
+    if (forwarded_v5_tickets)
+	destroy_tickets();
+#endif
+#ifdef KRB4_GET_TICKETS
+    else if (got_v4_tickets)
+        destroy_tickets();
+#endif
+
+#ifdef OQUOTA
+    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);
+#endif
+
+#ifdef	HAVE_SETLUID
+  	/*
+  	 * If we're on a system which keeps track of login uids, then
+ 	 * set the login uid. If this fails this opens up a problem on DEC OSF
+ 	 * with C2 enabled.
+	 */
+ 	if (setluid((uid_t) pwd->pw_uid) < 0) {
+	    perror("setuid");
+	    sleepexit(1);
+	}
+#endif	/* HAVE_SETLUID */
+#ifdef _IBMR2
+    if (setuidx(ID_LOGIN, pwd->pw_uid) < 0) {
+	perror("setuidx");
+	sleepexit(1);
+    };
+#endif
+
+    /* 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.
+     */
+
+#ifdef KRB5_GET_TICKETS
+    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");
+	}
+
+	if (xtra_creds)
+	    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) {
+	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 */
+
+    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);
+#endif
+
+    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;
+    }
+
+    setenv ("LOGNAME", pwd->pw_name, 1);
+    setenv ("LOGIN", pwd->pw_name, 1);
+
+    /* read the /etc/environment file on AIX */
+#ifdef HAVE_ETC_ENVIRONMENT
+    read_env_vars_from_file ("/etc/environment");
+#endif
+
+    /* Set login timezone for date information (sgi PDG) */
+#ifdef HAVE_ETC_TIMEZONE
+    read_env_vars_from_file ("/etc/TIMEZONE");
+#else
+    if (tz)
+	setenv ("TZ", tz, 1);
+#endif
+
+    if (ccname)
+	setenv("KRB5CCNAME", ccname, 1);
+
+    setenv("HOME", pwd->pw_dir, 1);
+    setenv("PATH", LPATH, 0);
+    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);
+
+#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);
+#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);
+	krb5_cc_set_default_name(kcontext, ccfile);
+    }
+#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)
+#ifdef KRB4_KLOGIN
+	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);
+#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);
+#else
+		    syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %s",
+			   tty, hostname);
+#endif
+		} else {
+		    syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
+		}
+	    }
+
+    afs_login();
+
+    if (!quietlog) {
+#ifdef KRB4_KLOGIN
+	if (!krbflag && !fflag && !eflag )
+	    printf("\nWarning: No Kerberos tickets obtained.\n\n");
+#endif /* KRB4_KLOGIN */
+	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] = '-';
+    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, (char *)NULL);
+    fprintf(stderr, "login: no shell: ");
+    perror(pwd->pw_shell);
+    exit(0);
+}
+
+char *speeds[] = {
+	"0", "50", "75", "110", "134", "150", "200", "300", "600",
+	"1200", "1800", "2400", "4800", "9600", "19200", "38400",
+};
+#define	NSPEEDS	(sizeof(speeds) / sizeof(speeds[0]))
+
+#ifdef POSIX_TERMIOS
+/* this must be in sync with the list above */
+speed_t b_speeds[] = {
+	B0, B50, B75, B110, B134, B150, B200, B300, B600,
+	B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+};
+#endif
+
+void
+term_init (do_rlogin)
+int do_rlogin;
+{
+    int line_speed = -1;
+
+    if (do_rlogin) {
+	register char *cp = strchr(term, '/'), **cpp;
+	char *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;
+		}
+	}
+    }
+#ifdef POSIX_TERMIOS
+    {
+	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;
+#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;
+#ifndef CNUL
+#define CNUL CEOL
+#endif
+	tc.c_cc[VEOL] = CNUL;
+	/* The following are common extensions to POSIX */
+#ifdef VEOL2
+	tc.c_cc[VEOL2] = CNUL;
+#endif
+#ifdef VSUSP
+#if !defined(CSUSP) && defined(CSWTCH)
+#define CSUSP CSWTCH
+#endif
+	tc.c_cc[VSUSP] = CSUSP;
+#endif
+#ifdef VDSUSP
+	tc.c_cc[VDSUSP] = CDSUSP;
+#endif
+#ifdef VLNEXT
+	tc.c_cc[VLNEXT] = CLNEXT;
+#endif
+#ifdef VREPRINT
+	tc.c_cc[VREPRINT] = CRPRNT;
+#endif
+#ifdef VDISCRD
+	tc.c_cc[VDISCRD] = CFLUSH;
+#endif
+#ifdef VDISCARD
+#ifndef CDISCARD
+#define CDISCARD CFLUSH
+#endif
+	tc.c_cc[VDISCARD] = CDISCARD;
+#endif
+#ifdef VWERSE
+	tc.c_cc[VWERSE] = CWERASE;
+#endif
+#ifdef VWERASE
+	tc.c_cc[VWERASE] = CWERASE;
+#endif
+#if defined (VSTATUS) && defined (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);
+#ifdef 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;
+#endif
+	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 *)<c);
+	(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
+    }
+#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;
+	    }
+	}
+    }
+}
+
+sigtype
+timedout(signumber)
+    int signumber;
+{
+    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);
+#else
+    struct ttyent *t;
+
+    return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
+#endif /* HAVE_TTYENT_H */
+}
+
+#ifndef NO_MOTD
+sigjmp_buf motdinterrupt;
+
+static sigtype
+sigint(signum)
+    int signum;
+{
+    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);
+}
+#else
+void motd()
+{
+}
+#endif
+
+#ifndef NO_MAILCHECK
+void check_mail()
+{
+    char tbuf[MAXPATHLEN+2];
+    struct stat st;
+    (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
+    if (stat(tbuf, &st) == 0 && st.st_size != 0)
+	printf("You have %smail.\n",
+	       (st.st_mtime > st.st_atime) ? "new " : "");
+}
+#else
+void check_mail()
+{
+}
+#endif
+
+void checknologin()
+{
+    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, (unsigned) nchars);
+	sleepexit(0);
+    }
+}
+
+void dolastlog(hostname, quiet, tty)
+     char *hostname;
+     int quiet;
+     char *tty;
+{
+#if defined(HAVE_LASTLOG_H) || (defined(BSD) && (BSD >= 199103))
+    struct lastlog ll;
+    time_t lltime;
+    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)) {
+
+		/* .ll_time may not be a time_t.  */
+		lltime = ll.ll_time;
+		printf("Last login: %.*s ", 24-5, (char *)ctime(&lltime));
+
+		if (*ll.ll_host != '\0')
+		    printf("from %.*s\n", (int) sizeof(ll.ll_host), 
+			   ll.ll_host);
+		else
+		    printf("on %.*s\n", (int) sizeof(ll.ll_line), ll.ll_line);
+	    }
+	    (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+	}
+	(void) time(&lltime);
+	ll.ll_time = lltime;
+
+	(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
+}
+
+#undef	UNKNOWN
+#ifdef __hpux
+#define UNKNOWN 0
+#else
+#define	UNKNOWN	"su"
+#endif
+
+char *
+stypeof(ttyid)
+     char *ttyid;
+{
+    char *cp = getenv("term");
+
+#ifndef HAVE_TTYENT_H
+    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);
+#endif
+}
+
+int doremotelogin(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));
+}
+
+#ifdef KRB4_KLOGIN
+int do_krb_login(host, 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];
+    
+    /*
+     * 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");
+	/*
+	 * No host addr prevents auth, so
+	 * punt krb and require password
+	 */
+	if (strict) {
+	    goto paranoid;
+	} else {
+	    pwd = NULL;
+	    return(-1);
+	}
+    }
+
+    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) {
+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);
+    }
+
+    /*
+     * 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);
+    }
+    return(0);
+}
+#endif /* KRB4_KLOGIN */
+
+void lgetstr(buf, cnt, err)
+     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);
+}
+
+void sleepexit(eval)
+     int eval;
+{
+#ifdef KRB4_GET_TICKETS
+    if (login_krb4_get_tickets && krbflag)
+	(void) destroy_tickets();
+#endif /* KRB4_GET_TICKETS */
+    sleep((u_int)5);
+    exit(eval);
+}
+
+#if defined(KRB4_GET_TICKETS) || defined(KRB5_GET_TICKETS)
+static int hungup = 0;
+
+static sigtype
+sighup() {
+    hungup = 1;
+}
+
+/* call already conditionalized on login_krb4_get_tickets */
+/*
+ * This routine handles cleanup stuff, and the like.
+ * It exits only in the child process.
+ */
+#include <sys/wait.h>
+void
+dofork()
+{
+    int child,pid;
+    handler sa;
+    int syncpipe[2];
+    char c;
+    int n;
+    
+#ifdef _IBMR2
+    update_ref_count(1);
+#endif
+    if (pipe(syncpipe) < 0) {
+	perror("login: dofork: setting up syncpipe");
+	exit(1);
+    }
+    if (!(child=fork())) {
+	close(syncpipe[1]);
+	while ((n = read(syncpipe[0], &c, 1)) < 0) {
+	    if (errno != EINTR) {
+		perror("login: dofork: waiting for sync from parent");
+		exit(1);
+	    }
+	}
+	if (n == 0) {
+	    fprintf(stderr, "login: dofork: unexpected EOF waiting for sync\n");
+	    exit(1);
+	}
+	close(syncpipe[0]);
+	return; /* Child process returns */
+    }
+
+    /* The parent continues here */
+
+    /* On receipt of SIGHUP, pass that along to child's process group. */
+    handler_init (sa, sighup);
+    handler_set (SIGHUP, sa);
+    /* Tell child we're ready. */
+    close(syncpipe[0]);
+    write(syncpipe[1], "", 1);
+    close(syncpipe[1]);
+
+    /* Setup stuff?  This would be things we could do in parallel with login */
+    (void) chdir("/");	/* Let's not keep the fs busy... */
+    
+    /* If we're the parent, watch the child until it dies */
+
+    while (1) {
+#ifdef HAVE_WAITPID
+        pid = waitpid(child, 0, 0);
+#elif defined(WAIT_USES_INT)
+        pid = wait((int *)0);
+#else
+        pid = wait((union wait *)0);
+#endif
+
+	if (hungup) {
+#ifdef HAVE_KILLPG
+	    killpg(child, SIGHUP);
+#else
+	    kill(-child, SIGHUP);
+#endif
+	}
+
+	if (pid == child)
+	    break;
+    }
+    
+    /* Cleanup stuff */
+    /* Run destroy_tickets to destroy tickets */
+    (void) destroy_tickets();		/* If this fails, we lose quietly */
+    afs_cleanup ();
+#ifdef _IBMR2
+    update_ref_count(-1);
+#endif
+
+    /* Leave */
+    exit(0);
+}
+#endif /* KRB4_GET_TICKETS */
+
+
+#ifndef HAVE_STRSAVE
+/* Strsave was a routine in the version 4 krb library: we put it here
+   for compatablilty with version 5 krb library, since kcmd.o is linked
+   into all programs. */
+
+char *strsave(sp)
+     char *sp;
+{
+    register char *ret;
+    
+    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
+update_ref_count(int adj)
+{
+    struct passwd *save_pwd;
+    static char *empty = "\0";
+    char *grp;
+    int i;
+
+    /* save pwd before calling getuserattr() */
+    save_pwd = (struct passwd *)malloc(sizeof(struct passwd));
+    save_pwd->pw_name = strdup(pwd->pw_name);
+    save_pwd->pw_passwd = strdup(pwd->pw_passwd);
+    save_pwd->pw_uid = pwd->pw_uid;
+    save_pwd->pw_gid = pwd->pw_gid;
+    save_pwd->pw_gecos = strdup(pwd->pw_gecos);
+    save_pwd->pw_dir = strdup(pwd->pw_dir);
+    save_pwd->pw_shell = strdup(pwd->pw_shell);
+    pwd = save_pwd;
+
+    /* Update reference count on all user's temporary groups */
+    setuserdb(S_READ|S_WRITE);
+    if (getuserattr(username, S_GROUPS, (void *)&grp, SEC_LIST) == 0) {
+	while (*grp) {
+	    if (getgroupattr(grp, "athena_temp", (void *)&i, SEC_INT) == 0) {
+		i += adj;
+		if (i > 0) {
+		    putgroupattr(grp, "athena_temp", (void *)i, SEC_INT);
+		    putgroupattr(grp, (char *)0, (void *)0, SEC_COMMIT);
+		} else {
+		    putgroupattr(grp, S_USERS, (void *)empty, SEC_LIST);
+#ifdef HAVE_RMUFILE /* pre-4.3.0 AIX */
+		    putgroupattr(grp, (char *)0, (void *)0, SEC_COMMIT);
+		    rmufile(grp, 0, GROUP_TABLE);
+#else
+		    putgroupattr(grp, (char *)0, (void *)0, SEC_DELETE);
+		    putgroupattr(grp, (char *)0, (void *)0, SEC_COMMIT);
+#endif
+		}
+	    }
+	    while (*grp) grp++;
+	    grp++;
+	}
+    }
+    enduserdb();
+}
+#endif
diff --git a/krb5-1-6/src/appl/bsd/loginpaths.h b/krb5-1-6/src/appl/bsd/loginpaths.h
new file mode 100644
index 000000000..0f2580bb9
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/loginpaths.h
@@ -0,0 +1,113 @@
+/* here are actual path values from each operating system supported. */
+/* LPATH is from rlogin, for login.c; RPATH is from rsh, for rshd.c */
+#ifdef sun
+#ifdef __SVR4
+#define RPATH "/usr/bin"
+#define LPATH "/usr/bin"
+#else
+/* sun3 and sun4 */
+#define LPATH "/usr/ucb:/bin:/usr/bin"
+#define RPATH "/usr/ucb:/bin:/usr/bin"
+#endif
+#endif
+
+#ifdef __ultrix
+#define LPATH "/usr/ucb:/bin:/usr/bin"
+#define RPATH "/usr/ucb:/bin:/usr/bin"
+#endif
+
+#ifdef hpux
+/* hpux 8, both hppa and s300 */
+#define LPATH "/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin"
+#define RPATH "/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin"
+#else
+#ifdef __hpux /* 9.04 */
+#define LPATH_root ":/bin:/usr/bin:/etc"
+#define LPATH "/bin:/usr/bin"
+#define RPATH "/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin"
+#endif
+#endif
+
+#ifdef NeXT
+#define LPATH "/usr/ucb:/bin:/usr/bin:/usr/local/bin"
+#define RPATH "/bin:/usr/ucb:/usr/bin"
+#endif
+
+#ifdef _IBMR2
+/* 3.2.0 */ 
+#define LPATH "/usr/bin:/usr/ucb:/usr/bin/X11"
+#define RPATH "/usr/bin:/usr/ucb:/usr/bin/X11"
+#endif
+
+#ifdef __SCO__
+#define LPATH "/bin:/usr/bin:/usr/dbin:/usr/ldbin"
+#define RPATH "/bin:/usr/bin:/usr/local/bin"
+#endif
+
+#ifdef sgi
+#define LPATH "/usr/sbin:/usr/bsd:/usr/bin:/bin:/usr/bin/X11"
+#define RPATH "/usr/sbin:/usr/bsd:/usr/bin:/bin:/usr/bin/X11"
+#endif
+
+#ifdef linux
+#define LPATH "/local/bin:/usr/bin:/bin:/usr/local/bin:/usr/bin/X11:."
+#define RPATH "/local/bin:/usr/bin:/bin:/usr/local/bin:/usr/bin/X11:."
+#endif
+
+#ifdef __386BSD__
+#define LPATH "/usr/bin:/bin"
+#define RPATH "/usr/bin:/bin"
+#endif
+
+#ifdef __alpha
+#ifdef __osf__
+#define LPATH "/usr/bin:."
+#define RPATH "/usr/bin:/bin"
+#endif
+#endif
+
+#ifdef __pyrsoft
+#ifdef MIPSEB
+#define RPATH "/bin:/usr/bin"
+#define LPATH "/usr/bin:/usr/ccs/bin:/usr/ucb:."
+#endif
+#endif
+
+#ifdef __DGUX
+#ifdef __m88k__
+#define RPATH "/usr/bin"
+#define LPATH "/usr/bin"
+#endif
+#endif
+
+#ifndef LPATH
+#ifdef __svr4__
+/* taken from unixware, sirius... */
+#define RPATH "/bin:/usr/bin:/usr/X/bin"
+#define LPATH "/usr/bin:/usr/dbin:/usr/dbin"
+#endif
+#endif
+
+#ifndef LPATH
+#ifdef __NetBSD__
+#define LPATH "/usr/bin:/bin"
+#define RPATH "/usr/bin:/bin"
+#endif
+#endif
+
+#ifdef _PATH_DEFPATH
+#undef LPATH
+#define LPATH _PATH_DEFPATH
+#undef RPATH
+#define RPATH _PATH_DEFPATH
+#endif
+
+/* catch-all entries for operating systems we haven't looked up
+   hardcoded paths for */
+#ifndef LPATH
+#define LPATH "/usr/bin:/bin"
+#endif
+
+#ifndef RPATH
+#define RPATH "/usr/bin:/bin"
+#endif
diff --git a/krb5-1-6/src/appl/bsd/rcp.M b/krb5-1-6/src/appl/bsd/rcp.M
new file mode 100644
index 000000000..a388e80ed
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/rcp.M
@@ -0,0 +1,160 @@
+.\" appl/bsd/rcp.M
+.\"
+.\" Copyright (c) 1983 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley.  The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"	@(#)rcp.1	6.6 (Berkeley) 9/20/88
+.\"
+.TH RCP 1
+.SH NAME
+rcp \- remote file copy
+.SH SYNOPSIS
+.B rcp
+[\fB\-p\fP] [\fB\-x\fP] [\fB\-k\fP \fIrealm\fP ] [\fB-c\fP \fIccachefile\fP] [\fB-C\fP \fIconfigfile\fP] [\fB\-D\fP \fIport\fP]
+[\fB\-N\fP]
+[\fB\-PN | \-PO\fP]
+.I file1 file2
+.sp
+.B rcp
+[\fB\-p\fB] [\fB\-x\fP] [\fP\-k\fP \fIrealm\fP] [\fB\-r\fP] [\fB\-D\fP
+\fIport\fP] [\fB\-N\fP]
+[\fB\-PN | \-PO\fP]
+.I file ... directory
+.sp
+.B rcp
+[\fB\-f | \-t\fP]
+.I ...
+.SH DESCRIPTION
+.B Rcp
+copies files between machines.  Each
+.I file
+or
+.I directory
+argument is either a remote file name of the form ``rhost:path'', or a
+local file name (containing no `:' characters, or a `/' before any
+`:'s).
+.PP
+By default, the mode and owner of
+.I file2
+are preserved if it already existed; otherwise the mode of the source
+file modified by the
+.IR umask (2)
+on the destination host is used.
+.PP
+If
+.I path
+is not a full path name, it is interpreted relative to your login
+directory on
+.IR rhost .
+A 
+.I path
+on a remote host may be quoted (using \e, ", or \(aa) so that the
+metacharacters are interpreted remotely.
+.PP
+.B Rcp
+does not prompt for passwords; it uses Kerberos authentication when
+connecting to
+.IR rhost .
+Each user may have a private authorization list in a file \&.k5login in
+his login directory.  Each line in this file should contain a Kerberos
+principal name of the form
+.IR principal/instance@realm .
+If there is a ~/.k5login file, then access is granted to the account if
+and only if the originater user is authenticated to one of the
+principals named in the ~/.k5login file.  Otherwise, the originating
+user will be granted access to the account if and only if the
+authenticated principal name of the user can be mapped to the local
+account name using the aname -> lname mapping rules (see
+.IR krb5_anadd (8)
+for more details).
+.SH OPTIONS
+.TP
+.B \-p
+attempt to preserve (duplicate) the modification times and modes of the
+source files in the copies, ignoring the
+.IR umask .
+.TP
+\fB\-x\fP
+encrypt all information transferring between hosts.
+.TP
+\fB\-k\fP \fIrealm\fP
+obtain tickets for the remote host in
+.I realm
+instead of the remote host's realm as determined by
+.IR krb_realmofhost (3).
+.TP
+\fB\-c\fP \fIccachefile\fP
+change the default credentials cache file to 
+.I ccachefile
+.TP
+\fB\-C\fP \fIconfigfile\fP
+change the default configuation file to
+.I configfile
+.TP
+.B \-r
+if any of the source files are directories, copy each subtree rooted at
+that name; in this case the destination must be a directory.
+.TP
+\fB-PN\fP
+.TP
+\fB-PO\fP
+Explicitly request new or old version of the Kerberos ``rcmd''
+protocol.  The new protocol avoids many security problems found in the
+old one, but is not interoperable with older servers.  (An
+"input/output error" and a closed connection is the most likely result
+of attempting this combination.)  If neither option is specified, some
+simple heuristics are used to guess which to try.
+.TP
+\fB\-D\fP \fIport\fP
+connect to port
+.I port
+on the remote machine.  
+.TP
+.B \-N
+use a network connection, even when copying files on the local machine
+(used for testing purposes).
+.TP
+.B \-f \-t
+These options are for internal use only.  They tell the
+remotely-running rcp process (started via the Kerberos remote shell
+daemon) which direction files are being sent.  These options should
+not be used by the user.  In particular, \fB-f\fP does \fBnot\fP mean
+that the user's Kerberos ticket should be forwarded!
+.PP
+.B Rcp
+handles third party copies, where neither source nor target files are on
+the current machine.  Hostnames may also take the form ``rname@rhost''
+to use
+.I rname
+rather than the current user name on the remote host.
+.SH FILES
+.TP "\w'~/.k5login\ \ 'u"
+~/.k5login
+(on remote host) - file containing Kerberos principals that are allowed
+access.
+.SH SEE ALSO
+cp(1), ftp(1), rsh(1), rlogin(1), kerberos(3), krb_getrealm(3), kshd(8), rcp(1) 
+[UCB version]
+.SH BUGS
+.B Rcp
+doesn't detect all cases where the target of a copy might be a file in
+cases where only a directory should be legal.
+.PP
+.B Rcp
+is confused by any output generated by commands in a \&.login,
+\&.profile, or \&.cshrc file on the remote host.
+.PP
+Kerberos is only used for the first connection of a third-party copy;
+the second connection uses the standard Berkeley rcp protocol.
diff --git a/krb5-1-6/src/appl/bsd/rlogin.M b/krb5-1-6/src/appl/bsd/rlogin.M
new file mode 100644
index 000000000..e2597823e
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/rlogin.M
@@ -0,0 +1,160 @@
+.\" appl/bsd/rlogin.M
+.\"
+.\" Copyright (c) 1983 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley.  The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"	@(#)rlogin.1	6.9 (Berkeley) 9/19/88
+.\" "
+.TH RLOGIN 1
+.SH NAME
+rlogin \- remote login
+.SH SYNOPSIS
+.B rlogin
+.I rhost
+[\fB\-e\fP\fI\|c\fP] [\fB\-8\fP] [\fB\-c\fP] [ \fB\-a\fP] [\fB\-f\fP]
+[\fB\-F\fP] [\fB\-t\fP \fItermtype\fP] [\fB\-n\fP] [\fB\-7\fP]
+[\fB\-PN | \-PO\fP] [\fB\-4\fP]
+[\fB\-d\fP] [\fB\-k\fP \fIrealm\fP] [\fB\-x\fP] [\fB\-L\fP] [\fB\-l\fP
+\fIusername\fP]
+.PP
+.SH DESCRIPTION
+.I Rlogin
+connects your terminal on the current local host system
+.I lhost
+to the remote host system
+.I rhost.
+.PP
+The version built to use Kerberos authentication is very similar to the
+standard Berkeley rlogin(1), except that instead of the \fIrhosts\fP
+mechanism, it uses Kerberos authentication to determine the
+authorization to use a remote account.
+.PP
+Each user may have a private authorization list in a file \&.k5login in
+his login directory.  Each line in this file should contain a Kerberos
+principal name of the form
+.IR principal/instance@realm .
+If the originating user is authenticated to one of the principals named
+in \&.k5login, access is granted to the account.  If there is no
+/.k5login file, the principal will be granted access to the account
+according to the aname\->lname mapping rules.  (See
+.IR krb5_anadd(8) 
+for more details.)  Otherwise a login and password will be prompted for
+on the remote machine as in
+.IR login (1).
+To avoid some security problems, the \&.k5login file must be owned by
+the remote user.
+.PP
+If there is some problem in marshaling the Kerberos authentication
+information, an error message is printed and the standard UCB rlogin is
+executed in place of the Kerberos rlogin.
+.PP
+A line of the form ``~.'' disconnects from the remote host, where ``~''
+is the escape character.  Similarly, the line ``~^Z'' (where ^Z,
+control-Z, is the suspend character) will suspend the rlogin session.
+Substitution of the delayed-suspend character (normally ^Y) for the
+suspend character suspends the send portion of the rlogin, but allows
+output from the remote system.
+.PP
+The remote terminal type is the same as your local terminal type (as
+given in your environment TERM variable), unless the
+.B \-t
+option is specified (see below).  The terminal or window size is also
+copied to the remote system if the server supports the option, and
+changes in size are reflected as well.
+.PP
+All echoing takes place at the remote site, so that (except for delays)
+the rlogin is transparent.  Flow control via ^S and ^Q and flushing of
+input and output on interrupts are handled properly.
+.SH OPTIONS
+.TP
+.B \-8
+allows an eight-bit input data path at all times; otherwise parity bits
+are stripped except when the remote side's stop and start characters are
+other than ^S/^Q.  Eight-bit mode is the default.
+.TP
+.B \-L
+allows the rlogin session to be run in litout mode.
+.TP
+\fB\-e\fP\fIc\fP
+sets the escape character to
+.IR c .
+There is no space separating this option flag and the new escape
+character.
+.TP
+.B \-c
+require confirmation before disconnecting via ``~.''
+.TP
+.B \-a
+force the remote machine to ask for a password by sending a null local
+username.  This option has no effect unless the standard UCB rlogin is
+executed in place of the Kerberos rlogin (see above).
+.TP
+\fB\-f\fP
+forward a copy of the local credentials to the remote system.
+.TP
+\fB\-F\fP
+forward a
+.I forwardable
+copy of the local credentials to the remote system.
+.TP
+\fB\-t\fP \fItermtype\fP
+replace the terminal type passed to the remote host with
+.IR termtype .
+.TP
+.B \-n
+prevent suspension of rlogin via ``~^Z'' or ``~^Y''.
+.TP
+.B \-7
+force seven-bit transmissions.
+.TP
+.B \-d
+turn on socket debugging (via
+.IR setsockopt (2))
+on the TCP sockets used for communication with the remote host.
+.TP
+.B \-k
+request rlogin to obtain tickets for the remote host in realm
+.I realm
+instead of the remote host's realm as determined by 
+.IR krb_realmofhost (3).
+.TP
+\fB\-x\fP
+turn on DES encryption for data passed via the rlogin session.  This
+applies only to input and output streams, so the username is sent
+unencrypted.  This significantly reduces response time and
+significantly increases CPU utilization.
+.TP
+\fB-PN\fP
+.TP
+\fB-PO\fP
+Explicitly request new or old version of the Kerberos ``rcmd''
+protocol.  The new protocol avoids many security problems found in the
+old one, but is not interoperable with older servers.  (An
+"input/output error" and a closed connection is the most likely result
+of attempting this combination.)  If neither option is specified, some
+simple heuristics are used to guess which to try.
+.TP
+\fB\-4\fP
+Use Kerberos V4 authentication only; don't try Kerberos V5.
+.SH SEE ALSO
+rsh(1), kerberos(1), krb_sendauth(3), krb_realmofhost(3), rlogin(1) [UCB
+version], klogind(8)
+.SH FILES
+.TP "\w'~/\&.k5login\ \ 'u"
+~/\&.k5login
+(on remote host) - file containing Kerberos principals that are allowed
+access.
+.SH BUGS
+More of the environment should be propagated.
diff --git a/krb5-1-6/src/appl/bsd/rpaths.h b/krb5-1-6/src/appl/bsd/rpaths.h
new file mode 100644
index 000000000..4925ea33a
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/rpaths.h
@@ -0,0 +1,31 @@
+/* fallback pathnames */
+
+#ifdef RPROGS_IN_USR_UCB
+#define	UCB_RLOGIN	"/usr/ucb/rlogin"
+#define	UCB_RCP	"/usr/ucb/rcp"
+#define	UCB_RSH	"/usr/ucb/rsh"
+/* all in /usr/ucb/, don't look for /bin/rcp */
+#endif
+
+#ifdef RPROGS_IN_USR_BIN
+#define UCB_RLOGIN "/usr/bin/rlogin"
+#define UCB_RCP "/usr/bin/rcp"
+#define UCB_RSH "/usr/bin/rsh"
+#endif
+
+#ifdef RPROGS_IN_USR_BSD
+#define UCB_RLOGIN "/usr/bsd/rlogin"
+#define UCB_RCP "/usr/bsd/rcp"
+#define UCB_RSH "/usr/bsd/rsh"
+#endif
+
+#ifdef RSH_IS_RCMD
+#undef UCB_RSH
+#define UCB_RSH "/usr/bin/rcmd"
+#endif
+
+#ifdef RSH_IS_REMSH
+#undef UCB_RSH
+#define UCB_RSH "/usr/bin/remsh"
+#endif
+
diff --git a/krb5-1-6/src/appl/bsd/rsh.M b/krb5-1-6/src/appl/bsd/rsh.M
new file mode 100644
index 000000000..ce0ebfb20
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/rsh.M
@@ -0,0 +1,173 @@
+.\" appl/bsd/rsh.M
+.\"
+.\" Copyright (c) 1983 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley.  The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"	@(#)rsh.1	6.2 (Berkeley) 9/20/88
+.\" "
+.TH RSH 1
+.SH NAME
+rsh \- remote shell
+.SH SYNOPSIS
+.B rsh
+.I host
+[\fB\-l\fP \fIusername\fP] [\fB\-n\fP] [\fB\-d\fP] [\fB\-k\fP
+\fIrealm\fP] [\fB\-f\fP | \fB\-F\fP] [\fB\-x\fP]
+[\fB\-PN | \-PO\fP]
+.I command
+.SH DESCRIPTION
+.B Rsh
+connects to the specified
+.I host,
+and executes the specified \fIcommand\fR.
+.B Rsh
+copies its standard input to the remote command, the standard output of
+the remote command to its standard output, and the standard error of the
+remote command to its standard error.  This implementation of
+.B rsh
+will accept any port for the standard error stream.  Interrupt, quit and
+terminate signals are propagated to the remote command; \fIrsh\fP
+normally terminates when the remote command does.
+.PP
+Each user may have a private authorization list in a file \&.k5login in
+his login directory.  Each line in this file should contain a Kerberos
+principal name of the form
+.IR principal/instance@realm .
+If there is a ~/.k5login file, then access is granted to the account if
+and only if the originater user is authenticated to one of the
+princiapls named in the ~/.k5login file.  Otherwise, the originating
+user will be granted access to the account if and only if the
+authenticated principal name of the user can be mapped to the local
+account name using the aname -> lname mapping rules (see
+.IR krb5_anadd (8)
+for more details).
+.SH OPTIONS
+.TP
+\fB\-l\fP \fIusername\fP
+sets the remote username to
+.IR username .
+Otherwise, the remote username will be the same as the local username.
+.TP
+\fB\-x\fP
+causes the network session traffic to be encrypted.  This applies only
+to the input and output streams, and not the command line.
+.TP
+\fB\-f\fP
+cause nonforwardable Kerberos credentials to be forwarded to the remote
+machine for use by the specified
+.IR command .
+They will be removed when
+.I command
+finishes.  This option is mutually exclusive with the
+.B \-F
+option.
+.TP
+\fB\-F\fP
+cause
+.I forwardable
+Kerberos credentials to be forwarded to the remote machine for use by
+the specified
+.IR command .
+They will be removed when
+.I command
+finishes.  This option is mutually exclusive with the
+.B \-f
+option.
+.TP
+\fB\-k\fP \fIrealm\fP
+causes 
+.I rsh
+to obtain tickets for the remote host in
+.I realm
+instead of the remote host's realm as determined by
+.IR krb_realmofhost (3).
+.TP
+.B \-d
+turns on socket debugging (via
+.IR setsockopt (2))
+on the TCP sockets used for communication with the remote host.
+.TP
+.B \-n
+redirects input from the special device
+.I /dev/null
+(see the BUGS section below).
+.TP
+\fB-PN\fP
+.TP
+\fB-PO\fP
+Explicitly request new or old version of the Kerberos ``rcmd''
+protocol.  The new protocol avoids many security problems found in the
+old one, but is not interoperable with older servers.  (An
+"input/output error" and a closed connection is the most likely result
+of attempting this combination.)  If neither option is specified, some
+simple heuristics are used to guess which to try.
+.PP
+If you omit
+.IR command ,
+then instead of executing a single command, you will be logged in on the
+remote host using
+.IR rlogin (1).
+.PP
+Shell metacharacters which are not quoted are interpreted on the local
+machine, while quoted metacharacters are interpreted on the remote
+machine.  Thus the command
+.PP
+\ \ \ rsh otherhost cat remotefile >> localfile
+.PP
+appends the remote file
+.I remotefile
+to the local file
+.IR localfile ,
+while
+.PP
+\ \ \ rsh otherhost cat remotefile ">>" otherremotefile
+.PP
+appends
+.I remotefile
+to
+.IR otherremotefile .
+.SH FILES
+.TP "\w'~/.k5login\ \ 'u"
+/etc/hosts
+.sp -1v
+.TP
+~/\&.k5login
+(on remote host) - file containing Kerberos principals that are allowed
+access.
+.SH SEE ALSO
+rlogin(1), kerberos(3), krb_sendauth(3), krb_realmofhost(3), kshd(8)
+.SH BUGS
+If you are using
+.IR csh (1)
+and put a
+.IR rsh (1)
+in the background without redirecting its input away from the terminal,
+it will block even if no reads are posted by the remote command.  If no
+input is desired you should redirect the input of
+.I rsh
+to /dev/null using the
+.B \-n
+option.
+.PP
+You cannot run an interactive command (like
+.IR rogue (6)
+or
+.IR vi (1));
+use
+.IR rlogin (1).
+.PP
+Stop signals stop the local \fIrsh\fP process only; this is arguably
+wrong, but currently hard to fix for reasons too complicated to explain
+here.
diff --git a/krb5-1-6/src/appl/bsd/setenv.c b/krb5-1-6/src/appl/bsd/setenv.c
new file mode 100644
index 000000000..0191d9c8c
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/setenv.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)setenv.c	5.2 (Berkeley) 6/27/88 */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NEED_SETENV
+extern int setenv(char *, char *, int);
+extern void unsetenv(char *);
+#endif
+
+static char *_findenv(char *, int*);
+/*
+ * setenv --
+ *	Set the value of the environmental variable "name" to be
+ *	"value".  If rewrite is set, replace any current value.
+ */
+int
+setenv(name, value, rewrite)
+	register char *name, *value;
+	int rewrite;
+{
+	extern char **environ;
+	static int alloced;			/* if allocated space before */
+	register char *C;
+	int l_value, offset;
+
+	if (*value == '=')			/* no `=' in value */
+		++value;
+	l_value = strlen(value);
+	if ((C = _findenv(name, &offset))) {	/* find if already exists */
+		if (!rewrite)
+			return(0);
+		if (strlen(C) >= l_value) {	/* old larger; copy over */
+			while ((*C++ = *value++));
+			return(0);
+		}
+	}
+	else {					/* create new slot */
+		register int	cnt;
+		register char	**P;
+
+		for (P = environ, cnt = 0; *P; ++P, ++cnt);
+		if (alloced) {			/* just increase size */
+			environ = (char **)realloc((char *)environ,
+			    (u_int)(sizeof(char *) * (cnt + 2)));
+			if (!environ)
+				return(-1);
+		}
+		else {				/* get new space */
+			alloced = 1;		/* copy old entries into it */
+			P = (char **)malloc((u_int)(sizeof(char *) *
+			    (cnt + 2)));
+			if (!P)
+				return(-1);
+			memcpy(P, environ, cnt * sizeof(char *));
+			environ = P;
+		}
+		environ[cnt + 1] = NULL;
+		offset = cnt;
+	}
+	for (C = name; *C && *C != '='; ++C);	/* no `=' in name */
+	if (!(environ[offset] =			/* name + `=' + value */
+	    malloc((u_int)((int)(C - name) + l_value + 2))))
+		return(-1);
+	for (C = environ[offset]; (*C = *name++) &&( *C != '='); ++C);
+	for (*C++ = '='; (*C++ = *value++););
+	return(0);
+}
+
+/*
+ * unsetenv(name) --
+ *	Delete environmental variable "name".
+ */
+void
+unsetenv(name)
+	char	*name;
+{
+	extern	char	**environ;
+	register char	**P;
+	int	offset;
+
+	while (_findenv(name, &offset))		/* if set multiple times */
+		for (P = &environ[offset];; ++P)
+			if (!(*P = *(P + 1)))
+				break;
+}
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)getenv.c	5.5 (Berkeley) 6/27/88 */
+
+#ifndef HAVE_GETENV
+/*
+ * getenv --
+ *	Returns ptr to value associated with name, if any, else NULL.
+ */
+char *
+getenv(name)
+	char *name;
+{
+	int offset;
+
+	return(_findenv(name, &offset));
+}
+#endif
+
+/*
+ * _findenv --
+ *	Returns pointer to value associated with name, if any, else NULL.
+ *	Sets offset to be the offset of the name/value combination in the
+ *	environmental array, for use by setenv(3) and unsetenv(3).
+ *	Explicitly removes '=' in argument name.
+ *
+ *	This routine *should* be a static; don't use it.
+ */
+static char *
+_findenv(name, offset)
+	register char *name;
+	int *offset;
+{
+	extern char **environ;
+	register unsigned int len;
+	register char **P, *C;
+
+	for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+	for (P = environ; *P; ++P)
+		if (!strncmp(*P, name, len))
+			if (*(C = *P + len) == '=') {
+				*offset = P - environ;
+				return(++C);
+			}
+	return(NULL);
+}
diff --git a/krb5-1-6/src/appl/bsd/v4rcp.M b/krb5-1-6/src/appl/bsd/v4rcp.M
new file mode 100644
index 000000000..771709fd5
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/v4rcp.M
@@ -0,0 +1,52 @@
+.\" appl/bsd/v4rcp.M
+.TH RCP 1 \*h
+.SH NAME
+v4rcp \- back end for Kerberos V4 rcp
+.SH SYNOPSIS
+.B v4rcp
+.I not invoked by users
+.SH DESCRIPTION
+This program is
+.B not
+for user execution. The usage message indicates this. 
+.PP
+Kerberos Version 4 
+.I rsh
+did not support encryption. In order to perform
+encrypted file transfer, the version 4
+.I rcp
+program did a second authentication, directly to the 
+.I rcp
+process at the other end. This meant that
+.I rcp
+needed to be
+.IR setuid
+to root in order to read the
+.IR krb-srvtab
+file on the remote end.
+.PP
+Rather than add this complexity into the main Kerberos 5 
+.I rcp
+the Kerberos 5 
+.I kshd
+instead detects the use of Kerberos 4 authentication, and checks the
+command for the program name
+.I rcp
+and then substitutes the full pathname of
+.I v4rcp
+instead.  Since
+.I v4rcp
+is installed
+.IR setuid
+to root, it can perform the the authentication and get the session key
+needed to encrypt the file transfer.
+.PP
+Kerberos 5 
+.I rcp 
+instead uses the encryption support built in to Kerberos 5
+.I rsh
+and
+.I kshd
+directly.
+.SH SEE ALSO
+rsh(1), rcp(1), kshd(8)
diff --git a/krb5-1-6/src/appl/bsd/v4rcp.c b/krb5-1-6/src/appl/bsd/v4rcp.c
new file mode 100644
index 000000000..67bf87786
--- /dev/null
+++ b/krb5-1-6/src/appl/bsd/v4rcp.c
@@ -0,0 +1,1114 @@
+/* Stripped down Kerberos V4 rcp, for server-side use only */
+/* based on Cygnus CNS V4-96q1 src/appl/bsd/rcp.c. */
+
+/*
+ *	rcp.c
+ */
+
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rcp.c	5.10 (Berkeley) 9/20/88";
+#endif /* not lint */
+
+/*
+ * rcp
+ */
+#ifdef KERBEROS
+#include <krb5.h>
+#include <com_err.h>
+#include <k5-util.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#ifndef KERBEROS
+/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
+#include <sys/socket.h>
+#endif
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#ifdef NEED_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#include <netinet/in.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <pwd.h>
+#include <ctype.h>
+#ifndef KERBEROS
+/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
+#include <netdb.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "port-sockets.h"
+
+#ifdef KERBEROS
+#include <krb.h>
+#include <krbports.h>
+
+
+void sink(int, char **), source(int, char **), 
+    rsource(char *, struct stat *), usage(void);
+/*VARARGS*/
+void 	error (char *fmt, ...)
+#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
+       __attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+     ;
+int	response(void);
+#if !defined(HAVE_UTIMES)
+int	utimes();
+#endif
+
+
+#if 0
+#include <kstream.h>
+#else
+/* we don't have full kstream in v5, so fake it... */
+
+typedef struct {
+  int encrypting;
+  int read_fd, write_fd;
+  des_key_schedule *sched;
+  des_cblock *ivec;
+  /* used on the read side */
+  char *inbuf;
+  char *outbuf;
+  int writelen;
+  char* retbuf;
+  int retbuflen;
+  int retlen;
+  int returned;
+} *kstream;
+
+static kstream kstream_create_rcp_from_fd(read_fd, write_fd, sched, ivec)
+     int read_fd, write_fd;
+     des_key_schedule *sched;
+     des_cblock *ivec;
+{
+  kstream tmp = (kstream)malloc(sizeof(*tmp));
+  tmp->encrypting = 1;
+  tmp->read_fd = read_fd;
+  tmp->write_fd = write_fd;
+  /* they're static in this file, so just hang on to the pointers */
+  tmp->sched = sched;
+  tmp->ivec = ivec;
+  tmp->inbuf = 0;
+  tmp->outbuf = 0;
+  tmp->writelen = 0;
+  tmp->retbuf = 0;
+  tmp->retbuflen = 0;
+  tmp->returned = 0;
+  tmp->retlen = 0;
+  return tmp;
+}
+
+static kstream kstream_create_from_fd(read_fd, write_fd, sched, session)
+     int read_fd, write_fd;
+     Key_schedule *sched;
+     des_cblock *session;
+{
+  /* just set it up... */
+  kstream tmp = (kstream)malloc(sizeof(*tmp));
+  tmp->encrypting = 0;
+  tmp->read_fd = read_fd;
+  tmp->write_fd = write_fd;
+  return tmp;
+}
+
+
+/* always set to 0 here anyway */
+#define kstream_set_buffer_mode(x,y)
+
+static int kstream_read(krem, buf, len)
+     kstream krem;
+     char *buf;
+     unsigned int len;
+{
+  if(krem->encrypting) {
+    /* when we get a length, we have to read the whole block. However,
+       we have to hand it to the user in the chunks they want, which 
+       may be smaller if BUFSIZ doesn't match. [the caller can deal if
+       the incoming blocks are smaller...] */
+    if (krem->returned) {
+      int remaining = krem->retlen - krem->returned;
+      int returning;
+      
+      if (remaining <= len) {
+	returning = remaining;
+      } else {
+	returning = len;
+      }
+      memcpy(buf, krem->retbuf+krem->returned, returning);
+      krem->returned += returning;
+      if (krem->returned == krem->retlen) krem->returned = 0;
+
+      return returning;
+    }
+
+    /* we need 4 bytes to get a length, and once we have that we know how
+       much to get to fill the buffer. Then we can hand back bits, or loop. */
+    {
+      int cc;
+      unsigned char clen[4];
+      unsigned int x = 0;
+      unsigned int sz, off;
+
+      cc = read(krem->read_fd, clen, 4);
+      if (cc != 4) return cc;
+      x <<= 8; x += clen[0] & 0xff;
+      x <<= 8; x += clen[1] & 0xff;
+      x <<= 8; x += clen[2] & 0xff;
+      x <<= 8; x += clen[3] & 0xff;
+      sz = (x + 7) & (~7U);
+
+      if (krem->retbuflen < sz) {
+	if (krem->retbuflen == 0) 
+	  krem->retbuf = (char*)malloc(sz>(BUFSIZ)?sz:(BUFSIZ));
+	else 
+	  krem->retbuf = (char*)realloc(krem->retbuf, sz);
+	if(!krem->retbuf) { errno = ENOMEM; return -1; }
+	krem->retbuflen = sz>(BUFSIZ)?sz:(BUFSIZ);
+      }
+
+      /* get all of it */
+      off = 0;
+      do {
+	cc = read(krem->read_fd, krem->retbuf+off, sz-off);
+	if (cc <= 0) return cc;
+	off += cc;
+      } while (off < sz);
+      
+      /* decrypt it */
+      des_pcbc_encrypt ((des_cblock *)krem->retbuf, 
+			(des_cblock *)krem->retbuf, 
+			(int) sz, *krem->sched, krem->ivec, 
+			DECRYPT);
+
+      /* now retbuf has sz bytes, return len or x of them to the user */
+      if (x <= len) {
+	memcpy(buf, krem->retbuf, x);
+	return x;
+      } else {
+	memcpy(buf, krem->retbuf, len);
+	/* defer the rest */
+	krem->returned = len;
+	krem->retlen = x;
+	return len;
+      }
+    }
+  } else {
+    return read(krem->read_fd, buf, len);
+  }
+}
+
+static int kstream_write(krem, buf, len)
+     kstream krem;
+     char *buf;
+     unsigned int len;
+{
+  if (krem->encrypting) {
+    unsigned long x;
+    int st;
+    unsigned int outlen = (len + 7) & (~7U);
+
+    if (krem->writelen < outlen) {
+      if (krem->writelen == 0) {
+	krem->inbuf = (char*)malloc(outlen);
+	krem->outbuf = (char*)malloc(outlen+8);
+      } else {
+	krem->inbuf = (char*)realloc(krem->inbuf, outlen);
+	krem->outbuf = (char*)realloc(krem->outbuf, outlen+8);
+      }
+      if(!krem->inbuf || !krem->outbuf) { errno = ENOMEM; return -1; }
+      krem->writelen = outlen;
+    }
+
+    outlen = (len + 7) & (~7U);
+
+    memcpy(krem->inbuf, buf, len);
+    krb5_random_confounder(outlen-len, krem->inbuf+len);
+    buf = krem->inbuf;
+
+    x = len;
+    krem->outbuf[3+4] = x & 0xff; x >>= 8;
+    krem->outbuf[2+4] = x & 0xff; x >>= 8;
+    krem->outbuf[1+4] = x & 0xff; x >>= 8;
+    krem->outbuf[0+4] = x & 0xff; x >>= 8;
+    if (x)
+      abort ();
+    /* memset(outbuf+4+4, 0x42, BUFSIZ); */
+    st = des_pcbc_encrypt ((des_cblock *)buf, (des_cblock *)(krem->outbuf+4+4),
+			   (int) outlen,
+			   *krem->sched, krem->ivec, ENCRYPT);
+
+    if (st) abort();
+    return write(krem->write_fd, krem->outbuf+4, 4+outlen);
+  } else {
+    return write(krem->write_fd, buf, len);
+  }
+}
+
+/* 0 = stdin, read; 1 = stdout, write */
+#define rem 0,1
+
+#endif
+
+
+#ifdef _AUX_SOURCE
+#define vfork fork
+#endif
+#ifdef NOVFORK
+#define vfork fork
+#endif
+
+#ifndef roundup
+#define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
+#endif
+
+int	sock;
+CREDENTIALS cred;
+MSG_DAT msg_data;
+struct sockaddr_in foreign, local;
+Key_schedule schedule;
+
+KTEXT_ST ticket;
+AUTH_DAT kdata;
+static des_cblock crypt_session_key;
+char	krb_realm[REALM_SZ];
+char	**save_argv(int, char **), *krb_realmofhost();
+#ifndef HAVE_STRSAVE
+static char *strsave(char *);
+#endif
+#ifdef NOENCRYPTION
+#define	des_read	read
+#define	des_write	write
+#else /* !NOENCRYPTION */
+void	answer_auth(void);
+int	encryptflag = 0;
+#endif /* NOENCRYPTION */
+#include "rpaths.h"
+#else /* !KERBEROS */
+#define	des_read	read
+#define	des_write	write
+#endif /* KERBEROS */
+
+kstream krem;
+int	errs;
+krb5_sigtype lostconn(int);
+int	iamremote, targetshouldbedirectory;
+int	iamrecursive;
+int	pflag;
+int	force_net;
+struct	passwd *pwd;
+int	userid;
+int	port;
+
+char	*getenv();
+
+struct buffer {
+	int	cnt;
+	char	*buf;
+} *allocbuf(struct buffer *, int, int);
+
+#define	NULLBUF	(struct buffer *) 0
+
+#define	ga()		(void) kstream_write (krem, "", 1)
+
+int main(argc, argv)
+	int argc;
+	char **argv;
+{
+	char portarg[20], rcpportarg[20];
+#ifdef ATHENA
+	static char curhost[256];
+#endif /* ATHENA */
+#ifdef KERBEROS
+	char realmarg[REALM_SZ + 5];
+#endif /* KERBEROS */
+
+	portarg[0] = '\0';
+	rcpportarg[0] = '\0';
+	realmarg[0] = '\0';
+
+	pwd = getpwuid(userid = getuid());
+	if (pwd == 0) {
+		fprintf(stderr, "who are you?\n");
+		exit(1);
+	}
+
+#ifdef KERBEROS
+	krb_realm[0] = '\0';		/* Initially no kerberos realm set */
+#endif /* KERBEROS */
+	for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
+		(*argv)++;
+		while (**argv) switch (*(*argv)++) {
+
+		    case 'r':
+			iamrecursive++;
+			break;
+
+		    case 'p':		/* preserve mtimes and atimes */
+			pflag++;
+			break;
+
+		    case 'P':		/* Set port to use.  */
+			port = atoi(*argv);
+			sprintf(portarg, " -p%d", port);
+			sprintf(rcpportarg, " -P%d", port);
+			port = htons(port);
+			goto next_arg;
+
+		    case 'N':
+			/* Force use of network even on local machine.  */
+			force_net++;
+			break;
+
+#ifdef KERBEROS
+#ifndef NOENCRYPTION
+		    case 'x':
+			encryptflag++;
+			break;
+#endif
+		    case 'k':		/* Change kerberos realm */
+			argc--, argv++;
+			if (argc == 0) 
+			  usage();
+			strncpy(krb_realm,*argv,REALM_SZ);
+			krb_realm[REALM_SZ-1] = 0;
+			sprintf(realmarg, " -k %s", krb_realm);
+			goto next_arg;
+#endif /* KERBEROS */
+		    /* The rest of these are not for users. */
+		    case 'd':
+			targetshouldbedirectory = 1;
+			break;
+
+		    case 'f':		/* "from" */
+			iamremote = 1;
+#if defined(KERBEROS) && !defined(NOENCRYPTION)
+			if (encryptflag) {
+				answer_auth();
+				krem = kstream_create_rcp_from_fd (rem,
+								   &schedule,
+								   &crypt_session_key);
+			} else
+				krem = kstream_create_from_fd (rem, 0, 0);
+			kstream_set_buffer_mode (krem, 0);
+#endif /* KERBEROS && !NOENCRYPTION */
+			(void) response();
+			if (setuid(userid)) {
+			    error("rcp: can't setuid(user)\n");
+			    exit(1);
+			}
+			source(--argc, ++argv);
+			exit(errs);
+
+		    case 't':		/* "to" */
+			iamremote = 1;
+#if defined(KERBEROS) && !defined(NOENCRYPTION)
+			if (encryptflag) {
+				answer_auth();
+				krem = kstream_create_rcp_from_fd (rem,
+								   &schedule,
+								   &crypt_session_key);
+			} else
+				krem = kstream_create_from_fd (rem, 0, 0);
+			kstream_set_buffer_mode (krem, 0);
+#endif /* KERBEROS && !NOENCRYPTION */
+			if (setuid(userid)) {
+			    error("rcp: can't setuid(user)\n");
+			    exit(1);
+			}
+			sink(--argc, ++argv);
+			exit(errs);
+
+		    default:
+			usage();
+		}
+#ifdef KERBEROS
+	      next_arg: ;
+#endif /* KERBEROS */
+	}
+	usage();
+	return 1;
+}
+
+static void verifydir(cp)
+	char *cp;
+{
+	struct stat stb;
+
+	if (stat(cp, &stb) >= 0) {
+		if ((stb.st_mode & S_IFMT) == S_IFDIR)
+			return;
+		errno = ENOTDIR;
+	}
+	error("rcp: %s: %s.\n", cp, error_message(errno));
+	exit(1);
+}
+
+void source(argc, argv)
+	int argc;
+	char **argv;
+{
+	char *last, *name;
+	struct stat stb;
+	static struct buffer buffer;
+	struct buffer *bp;
+	int x, readerr, f;
+	unsigned int amt;
+	off_t i;
+	char buf[BUFSIZ];
+
+	for (x = 0; x < argc; x++) {
+		name = argv[x];
+		if ((f = open(name, 0)) < 0) {
+			error("rcp: %s: %s\n", name, error_message(errno));
+			continue;
+		}
+		if (fstat(f, &stb) < 0)
+			goto notreg;
+		switch (stb.st_mode&S_IFMT) {
+
+		case S_IFREG:
+			break;
+
+		case S_IFDIR:
+			if (iamrecursive) {
+				(void) close(f);
+				rsource(name, &stb);
+				continue;
+			}
+			/* fall into ... */
+		default:
+notreg:
+			(void) close(f);
+			error("rcp: %s: not a plain file\n", name);
+			continue;
+		}
+		last = strrchr(name, '/');
+		if (last == 0)
+			last = name;
+		else
+			last++;
+		if (pflag) {
+			/*
+			 * Make it compatible with possible future
+			 * versions expecting microseconds.
+			 */
+			(void) sprintf(buf, "T%ld 0 %ld 0\n",
+			    stb.st_mtime, stb.st_atime);
+			kstream_write (krem, buf, strlen (buf));
+			if (response() < 0) {
+				(void) close(f);
+				continue;
+			}
+		}
+		(void) sprintf(buf, "C%04o %ld %s\n",
+		    (unsigned int) stb.st_mode&07777, (long) stb.st_size, last);
+		kstream_write (krem, buf, strlen (buf));
+		if (response() < 0) {
+			(void) close(f);
+			continue;
+		}
+		if ((bp = allocbuf(&buffer, f, BUFSIZ)) == NULLBUF) {
+			(void) close(f);
+			continue;
+		}
+		readerr = 0;
+		for (i = 0; i < stb.st_size; i += bp->cnt) {
+			amt = bp->cnt;
+			if (i + amt > stb.st_size)
+				amt = stb.st_size - i;
+			if (readerr == 0 && read(f, bp->buf, amt) != amt)
+				readerr = errno;
+			kstream_write (krem, bp->buf, amt);
+		}
+		(void) close(f);
+		if (readerr == 0)
+			ga();
+		else
+			error("rcp: %s: %s\n", name, error_message(readerr));
+		(void) response();
+	}
+}
+
+#ifndef USE_DIRENT_H
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#endif
+
+void rsource(name, statp)
+	char *name;
+	struct stat *statp;
+{
+	DIR *d = opendir(name);
+	char *last;
+	char buf[BUFSIZ];
+	char *bufv[1];
+#ifdef USE_DIRENT_H
+	struct dirent *dp;
+#else
+	struct direct *dp;
+#endif
+
+	if (d == 0) {
+		error("rcp: %s: %s\n", name, error_message(errno));
+		return;
+	}
+	last = strrchr(name, '/');
+	if (last == 0)
+		last = name;
+	else
+		last++;
+	if (pflag) {
+		(void) sprintf(buf, "T%ld 0 %ld 0\n",
+		    statp->st_mtime, statp->st_atime);
+		kstream_write (krem, buf, strlen (buf));
+		if (response() < 0) {
+			closedir(d);
+			return;
+		}
+	}
+	(void) sprintf(buf, "D%04o %d %s\n",
+		       (unsigned int) statp->st_mode&07777, 0, last);
+	kstream_write (krem, buf, strlen (buf));
+	if (response() < 0) {
+		closedir(d);
+		return;
+	}
+	while ((dp = readdir(d))) {
+		if (dp->d_ino == 0)
+			continue;
+		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+			continue;
+		if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
+			error("%s/%s: Name too long.\n", name, dp->d_name);
+			continue;
+		}
+		(void) sprintf(buf, "%s/%s", name, dp->d_name);
+		bufv[0] = buf;
+		source(1, bufv);
+	}
+	closedir(d);
+	kstream_write (krem, "E\n", 2);
+	(void) response();
+}
+
+int response()
+{
+	char resp, c, rbuf[BUFSIZ], *cp = rbuf;
+
+	if (kstream_read (krem, &resp, 1) != 1)
+		lostconn(0);
+	switch (resp) {
+
+	case 0:				/* ok */
+		return (0);
+
+	default:
+		*cp++ = resp;
+		/* fall into... */
+	case 1:				/* error, followed by err msg */
+	case 2:				/* fatal error, "" */
+		do {
+			if (kstream_read (krem, &c, 1) != 1)
+				lostconn(0);
+			*cp++ = c;
+		} while (cp < &rbuf[BUFSIZ] && c != '\n');
+		if (iamremote == 0)
+			(void) write(2, rbuf, (unsigned) (cp - rbuf));
+		errs++;
+		if (resp == 1)
+			return (-1);
+		exit(1);
+	}
+	/*NOTREACHED*/
+	return -1;
+}
+
+krb5_sigtype lostconn(signum)
+    int signum;
+{
+
+	if (iamremote == 0)
+		fprintf(stderr, "rcp: lost connection\n");
+	exit(1);
+}
+
+#if !defined(HAVE_UTIMES)
+#include <utime.h>
+#include <sys/time.h>
+
+/*
+ * We emulate utimes() instead of utime() as necessary because
+ * utimes() is more powerful than utime(), and rcp actually tries to
+ * set the microsecond values; we don't want to take away
+ * functionality unnecessarily.
+ */
+int utimes(file, tvp)
+const char *file;
+struct timeval *tvp;
+{
+	struct utimbuf times;
+
+	times.actime = tvp[0].tv_sec;
+	times.modtime = tvp[1].tv_sec;
+	return(utime(file, ×));
+}
+#endif
+
+void sink(argc, argv)
+	int argc;
+	char **argv;
+{
+	off_t i, j;
+	char *targ, *whopp, *cp;
+	int of, wrerr, exists, first, amt;
+	mode_t mode;
+	unsigned int count;
+	off_t size;
+	struct buffer *bp;
+	static struct buffer buffer;
+	struct stat stb;
+	int targisdir = 0;
+	mode_t mask = umask(0);
+	char *myargv[1];
+	char cmdbuf[BUFSIZ], nambuf[BUFSIZ];
+	int setimes = 0;
+	struct timeval tv[2];
+#define atime	tv[0]
+#define mtime	tv[1]
+#define	SCREWUP(str)	{ whopp = str; goto screwup; }
+
+	if (!pflag)
+		(void) umask(mask);
+	if (argc != 1) {
+		error("rcp: ambiguous target\n");
+		exit(1);
+	}
+	targ = *argv;
+	if (targetshouldbedirectory)
+		verifydir(targ);
+	ga();
+	if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
+		targisdir = 1;
+	for (first = 1; ; first = 0) {
+		cp = cmdbuf;
+		if (kstream_read (krem, cp, 1) <= 0)
+			return;
+		if (*cp++ == '\n')
+			SCREWUP("unexpected '\\n'");
+		do {
+			if (kstream_read(krem, cp, 1) != 1)
+				SCREWUP("lost connection");
+		} while (*cp++ != '\n');
+		*cp = 0;
+		if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
+			if (iamremote == 0)
+				(void) write(2, cmdbuf+1, strlen(cmdbuf+1));
+			if (cmdbuf[0] == '\02')
+				exit(1);
+			errs++;
+			continue;
+		}
+		*--cp = 0;
+		cp = cmdbuf;
+		if (*cp == 'E') {
+			ga();
+			return;
+		}
+
+#define getnum(t) (t) = 0; while (isdigit((int) *cp)) (t) = (t) * 10 + (*cp++ - '0');
+		if (*cp == 'T') {
+			setimes++;
+			cp++;
+			getnum(mtime.tv_sec);
+			if (*cp++ != ' ')
+				SCREWUP("mtime.sec not delimited");
+			getnum(mtime.tv_usec);
+			if (*cp++ != ' ')
+				SCREWUP("mtime.usec not delimited");
+			getnum(atime.tv_sec);
+			if (*cp++ != ' ')
+				SCREWUP("atime.sec not delimited");
+			getnum(atime.tv_usec);
+			if (*cp++ != '\0')
+				SCREWUP("atime.usec not delimited");
+			ga();
+			continue;
+		}
+		if (*cp != 'C' && *cp != 'D') {
+			/*
+			 * Check for the case "rcp remote:foo\* local:bar".
+			 * In this case, the line "No match." can be returned
+			 * by the shell before the rcp command on the remote is
+			 * executed so the ^Aerror_message convention isn't
+			 * followed.
+			 */
+			if (first) {
+				error("%s\n", cp);
+				exit(1);
+			}
+			SCREWUP("expected control record");
+		}
+		cp++;
+		mode = 0;
+		for (; cp < cmdbuf+5; cp++) {
+			if (*cp < '0' || *cp > '7')
+				SCREWUP("bad mode");
+			mode = (mode << 3) | (*cp - '0');
+		}
+		if (*cp++ != ' ')
+			SCREWUP("mode not delimited");
+		size = 0;
+		while (isdigit((int) *cp))
+			size = size * 10 + (*cp++ - '0');
+		if (*cp++ != ' ')
+			SCREWUP("size not delimited");
+		if (targisdir) {
+			if (strlen(targ) + strlen(cp) + 1 < sizeof(nambuf)) {
+				(void) sprintf(nambuf, "%s%s%s", targ,
+				    *targ ? "/" : "", cp);
+			} else {
+				SCREWUP("target directory name too long");
+			}
+		} else {
+		    if (strlen(targ) + 1 < sizeof(nambuf))
+			(void) strncpy(nambuf, targ, sizeof(nambuf)-1);
+		    else
+			SCREWUP("target pathname too long");
+		}
+		nambuf[sizeof(nambuf)-1] = '\0';
+		exists = stat(nambuf, &stb) == 0;
+		if (cmdbuf[0] == 'D') {
+			if (exists) {
+				if ((stb.st_mode&S_IFMT) != S_IFDIR) {
+					errno = ENOTDIR;
+					goto bad;
+				}
+				if (pflag)
+					(void) chmod(nambuf, mode);
+			} else if (mkdir(nambuf, mode) < 0)
+				goto bad;
+			myargv[0] = nambuf;
+			sink(1, myargv);
+			if (setimes) {
+				setimes = 0;
+				if (utimes(nambuf, tv) < 0)
+					error("rcp: can't set times on %s: %s\n",
+					    nambuf, error_message(errno));
+			}
+			continue;
+		}
+		if ((of = open(nambuf, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0) {
+	bad:
+			error("rcp: %s: %s\n", nambuf, error_message(errno));
+			continue;
+		}
+#ifdef NO_FCHMOD
+		if (exists && pflag)
+			(void) chmod(nambuf, mode);
+#else
+		if (exists && pflag)
+			(void) fchmod(of, mode);
+#endif
+		ga();
+		if ((bp = allocbuf(&buffer, of, BUFSIZ)) == NULLBUF) {
+			(void) close(of);
+			continue;
+		}
+		cp = bp->buf;
+		count = 0;
+		wrerr = 0;
+		for (i = 0; i < size; i += BUFSIZ) {
+			amt = BUFSIZ;
+			if (i + amt > size)
+				amt = size - i;
+			count += amt;
+			do {
+				j = kstream_read(krem, cp, amt);
+				if (j <= 0) {
+					if (j == 0)
+					    error("rcp: dropped connection");
+					else
+					    error("rcp: %s\n",
+						error_message(errno));
+					exit(1);
+				}
+				amt -= j;
+				cp += j;
+			} while (amt > 0);
+			if (count == bp->cnt) {
+				if (wrerr == 0 &&
+				    write(of, bp->buf, count) != count)
+					wrerr++;
+				count = 0;
+				cp = bp->buf;
+			}
+		}
+		if (count != 0 && wrerr == 0 &&
+		    write(of, bp->buf, count) != count)
+			wrerr++;
+#ifndef __SCO__
+		if (ftruncate(of, size))
+			error("rcp: can't truncate %s: %s\n",
+			    nambuf, error_message(errno));
+#endif
+		(void) close(of);
+		(void) response();
+		if (setimes) {
+			setimes = 0;
+			if (utimes(nambuf, tv) < 0)
+				error("rcp: can't set times on %s: %s\n",
+				    nambuf, error_message(errno));
+		}				   
+		if (wrerr)
+			error("rcp: %s: %s\n", nambuf, error_message(errno));
+		else
+			ga();
+	}
+screwup:
+	error("rcp: protocol screwup: %s\n", whopp);
+	exit(1);
+}
+
+struct buffer *
+allocbuf(bp, fd, blksize)
+	struct buffer *bp;
+	int fd, blksize;
+{
+	int size;
+#ifndef NOSTBLKSIZE
+	struct stat stb;
+
+	if (fstat(fd, &stb) < 0) {
+		error("rcp: fstat: %s\n", error_message(errno));
+		return (NULLBUF);
+	}
+	size = roundup(stb.st_blksize, blksize);
+	if (size == 0)
+#endif
+		size = blksize;
+	if (bp->cnt < size) {
+		if (bp->buf != 0)
+			free(bp->buf);
+		bp->buf = (char *)malloc((unsigned) size);
+		if (bp->buf == 0) {
+			error("rcp: malloc: out of memory\n");
+			return (NULLBUF);
+		}
+	}
+	bp->cnt = size;
+	return (bp);
+}
+
+void
+#ifdef HAVE_STDARG_H
+error(char *fmt, ...)
+#else
+/*VARARGS1*/
+error(fmt, va_alist)
+     char *fmt;
+     va_dcl
+#endif
+{
+    va_list ap;
+    char buf[BUFSIZ], *cp = buf;
+    
+#ifdef HAVE_STDARG_H
+    va_start(ap, fmt);
+#else
+    va_start(ap);
+#endif
+
+    errs++;
+    *cp++ = 1;
+    (void) vsprintf(cp, fmt, ap);
+    va_end(ap);
+
+    if (krem)
+	(void) kstream_write(krem, buf, strlen(buf));
+    if (iamremote == 0)
+	(void) write(2, buf+1, strlen(buf+1));
+}
+
+void usage()
+{
+  fprintf(stderr,
+"v4rcp: this program only acts as a server, and is not for user function.\n");
+  exit(1);
+}
+
+#ifdef KERBEROS
+
+char **
+save_argv(argc, argv)
+int argc;
+char **argv;
+{
+	register int i;
+
+	char **local_argv = (char **)calloc((unsigned) argc+1,
+					    (unsigned) sizeof(char *));
+	/* allocate an extra pointer, so that it is initialized to NULL
+	   and execv() will work */
+	for (i = 0; i < argc; i++)
+		local_argv[i] = strsave(argv[i]);
+	return(local_argv);
+}
+
+#ifndef HAVE_STRSAVE
+static char *
+strsave(sp)
+char *sp;
+{
+	register char *ret;
+	
+	if((ret = (char *)malloc((unsigned) strlen(sp)+1)) == NULL) {
+		fprintf(stderr, "rcp: no memory for saving args\n");
+		exit(1);
+	}
+	(void) strcpy(ret,sp);
+	return(ret);
+}
+#endif
+
+#ifndef NOENCRYPTION
+#undef rem
+#define rem 0
+
+void
+answer_auth()
+{
+	int status;
+	long authopts = KOPT_DO_MUTUAL;
+	char instance[INST_SZ];
+	char version[9];
+	char *srvtab;
+	char *envaddr;
+
+#if 0
+	int sin_len;
+	
+	sin_len = sizeof (struct sockaddr_in);
+	if (getpeername(rem, &foreign, &sin_len) < 0) {
+		perror("getpeername");
+		exit(1);
+	}
+
+	sin_len = sizeof (struct sockaddr_in);
+	if (getsockname(rem, &local, &sin_len) < 0) {
+		perror("getsockname");
+		exit(1);
+	}
+#else
+	if ((envaddr = getenv("KRB5LOCALADDR"))) {
+#ifdef HAVE_INET_ATON
+	  inet_aton(envaddr,  &local.sin_addr);
+#else
+	  local.sin_addr.s_addr = inet_addr(envaddr);
+#endif
+	  local.sin_family = AF_INET;
+	  envaddr = getenv("KRB5LOCALPORT");
+	  if (envaddr)
+	    local.sin_port = htons(atoi(envaddr));
+	  else
+	    local.sin_port = 0;
+	} else {
+	  fprintf(stderr, "v4rcp: couldn't get local address (KRB5LOCALADDR)\n");
+	  exit(1);
+	}
+	if ((envaddr = getenv("KRB5REMOTEADDR"))) {
+#ifdef HAVE_INET_ATON
+	  inet_aton(envaddr,  &foreign.sin_addr);
+#else
+	  foreign.sin_addr.s_addr = inet_addr(envaddr);
+#endif
+	  foreign.sin_family = AF_INET;
+	  envaddr = getenv("KRB5REMOTEPORT");
+	  if (envaddr)
+	    foreign.sin_port = htons(atoi(envaddr));
+	  else
+	    foreign.sin_port = 0;
+	} else {
+	  fprintf(stderr, "v4rcp: couldn't get remote address (KRB5REMOTEADDR)\n");
+	  exit(1);
+	}
+
+#endif
+	strcpy(instance, "*");
+
+	/* If rshd was invoked with the -s argument, it will set the
+           environment variable KRB_SRVTAB.  We use that to get the
+           srvtab file to use.  If we do use the environment variable,
+           we reset to our real user ID (which will already have been
+           set up by rsh).  Since rcp is setuid root, we would
+           otherwise have a security hole.  If we are using the normal
+           srvtab (KEYFILE in krb.h, normally set to /etc/krb-srvtab),
+           we must keep our effective uid of root, because that file
+           can only be read by root.  */
+	srvtab = (char *) getenv("KRB_SRVTAB");
+	if (srvtab == NULL)
+		srvtab = "";
+	if (*srvtab != '\0')
+		(void) setuid (userid);
+
+	if ((status = krb_recvauth(authopts, rem, &ticket, "rcmd", instance,
+				   &foreign,
+				   &local,
+				   &kdata,
+				   srvtab,
+				   schedule,
+				   version)) != KSUCCESS) {
+		fprintf(stderr, "krb_recvauth mutual fail: %s\n",
+			krb_get_err_text(status));
+		exit(1);
+	}
+	memcpy(&crypt_session_key, &kdata.session, sizeof (crypt_session_key));
+	return;
+}
+#endif /* !NOENCRYPTION */
+
+#endif /* KERBEROS */
diff --git a/krb5-1-6/src/appl/configure.in b/krb5-1-6/src/appl/configure.in
new file mode 100644
index 000000000..e8d2f6512
--- /dev/null
+++ b/krb5-1-6/src/appl/configure.in
@@ -0,0 +1,21 @@
+K5_AC_INIT(configure.in)
+CONFIG_RULES
+KRB5_AC_INET6
+AC_PROG_INSTALL
+AC_CHECK_HEADERS(unistd.h stdlib.h string.h)
+AC_C_CONST
+dnl gss-misc.c needs this:
+AC_CHECK_HEADERS(sys/time.h time.h)
+dnl
+dnl Kludge for simple server --- FIXME is this the best way to do this?
+dnl
+if test "$ac_cv_lib_socket" = "yes" -a "$ac_cv_lib_nsl" = "yes"; then
+	AC_DEFINE(BROKEN_STREAMS_SOCKETS,1,[Define if socket can't be bound to 0.0.0.0])
+fi
+dnl
+dnl
+KRB5_GETSOCKNAME_ARGS
+KRB5_GETPEERNAME_ARGS
+KRB5_BUILD_PROGRAM
+AC_CONFIG_SUBDIRS(libpty bsd gssftp telnet)
+V5_AC_OUTPUT_MAKEFILE(. sample sample/sclient sample/sserver simple simple/client simple/server gss-sample user_user)
diff --git a/krb5-1-6/src/appl/gss-sample/Makefile.in b/krb5-1-6/src/appl/gss-sample/Makefile.in
new file mode 100644
index 000000000..da68f128c
--- /dev/null
+++ b/krb5-1-6/src/appl/gss-sample/Makefile.in
@@ -0,0 +1,65 @@
+thisconfigdir=./..
+myfulldir=appl/gss-sample
+mydir=gss-sample
+BUILDTOP=$(REL)..$(S)..
+DEFINES = -DUSE_AUTOCONF_H -DGSSAPI_V2
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SRCS= $(srcdir)/gss-client.c $(srcdir)/gss-misc.c $(srcdir)/gss-server.c
+
+OBJS= gss-client.o gss-misc.o gss-server.o
+
+all-unix:: gss-server gss-client
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##GSSCLIENT=$(OUTPRE)gss-client.exe
+##WIN32##GSSSERVER=$(OUTPRE)gss-server.exe
+
+##WIN32##CLIENTRES=$(GSSCLIENT:.exe=.res)
+##WIN32##SERVERRES=$(GSSSERVER:.exe=.res)
+
+##WIN32##$(CLIENTRES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DGSS_CLIENT_APP -fo $@ -r $**
+##WIN32##$(SERVERRES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DGSS_SERVER_APP -fo $@ -r $**
+
+
+##WIN32##all-windows:: $(OUTPRE)gss-server.exe $(OUTPRE)gss-client.exe
+
+gss-server: gss-server.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o gss-server gss-server.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
+
+gss-client: gss-client.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o gss-client gss-client.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
+
+##WIN32##$(GSSSERVER): $(OUTPRE)gss-server.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) $(SERVERRES)
+##WIN32##	link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+##WIN32##$(GSSCLIENT): $(OUTPRE)gss-client.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) $(CLIENTRES)
+##WIN32##	link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) gss-server gss-client
+
+install-unix::
+	$(INSTALL_PROGRAM) gss-client $(DESTDIR)$(CLIENT_BINDIR)/gss-client
+	$(INSTALL_PROGRAM) gss-server $(DESTDIR)$(SERVER_BINDIR)/gss-server
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)gss-client.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h gss-client.c \
+  gss-misc.h
+$(OUTPRE)gss-misc.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h gss-misc.c \
+  gss-misc.h
+$(OUTPRE)gss-server.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(SRCTOP)/include/port-sockets.h gss-misc.h gss-server.c
diff --git a/krb5-1-6/src/appl/gss-sample/README b/krb5-1-6/src/appl/gss-sample/README
new file mode 100644
index 000000000..dc51fca1b
--- /dev/null
+++ b/krb5-1-6/src/appl/gss-sample/README
@@ -0,0 +1,163 @@
+# Copyright 1993 by OpenVision Technologies, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software
+# and its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appears in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of OpenVision not be used
+# in advertising or publicity pertaining to distribution of the software
+# without specific, written prior permission. OpenVision makes no
+# representations about the suitability of this software for any
+# purpose.  It is provided "as is" without express or implied warranty.
+# 
+# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+This directory contains a sample GSS-API client and server
+application.  In addition to serving as an example of GSS-API
+programming, this application is also intended to be a tool for
+testing the performance of GSS-API implementations.
+
+Each time the client is invoked, it performs one or more exchanges
+with the server.  Each exchange with the server consists primarily of
+the following steps:
+
+	1. A TCP/IP connection is established.
+
+	2. (optional, on by default) The client and server establish a
+	   GSS-API context, and the server prints the identify of the
+	   client.
+
+      /	3. The client sends a message to the server.  The message may
+     /     be plaintext, cryptographically "signed" but not encrypted,
+     |     or encrypted (default).
+     |
+0 or |  4. The server decrypts the message (if necessary), verifies
+more |     its signature (if there is one) and prints it.
+times|
+     |  5. The server sends either a signature block (the default) or an
+     |     empty token back to the client to acknowledge the message.
+     \
+      \ 6. If the server sent a signature block, the client verifies
+           it and prints a message indicating that it was verified.
+  
+	7. The client sends an empty block to the server to tell it
+	   that the exchange is finished.
+  
+	8. The client and server close the TCP/IP connection and
+	   destroy the GSS-API context.
+
+The client also supports the -v1 flag which uses an older exchange
+format compatible with previous releases of Kerberos and with samples
+shipped in the Microsoft SDK.
+  
+The server's command line usage is
+  
+	gss-server [-port port] [-verbose] [-once] [-inetd] [-export]
+		[-logfile file] service_name
+  
+where service_name is a GSS-API service name of the form
+"service@host" (or just "service", in which case the local host name
+is used).  The command-line options have the following meanings:
+  
+-port	The TCP port on which to accept connections.  Default is 4444.
+  
+-once	Tells the server to exit after a single exchange, rather than
+	persisting.
+  
+-inetd	Tells the server that it is running out of inetd, so it should
+	interact with the client on stdin rather than binding to a
+	network port.  Implies "-once".
+  
+-export	Tells the server to test the gss_export_sec_context function
+	after establishing a context with a client.
+
+-logfile
+	The file to which the server should append its output, rather
+	than sending it to stdout.
+  
+The client's command line usage is
+
+	gss-client [-port port] [-mech mechanism] [-d] [-f] [-q]
+        [-seq] [-noreplay] [-nomutual]		
+        [-ccount count] [-mcount count] [-na] [-nw] [-nx] [-nm]
+		host service_name msg
+
+where host is the host running the server, service_name is the service
+name that the server will establish connections as (if you don't
+specify the host name in the service name when running gss-server, and
+it's running on a different machine from gss-client, make sure to
+specify the server's host name in the service name you specify to
+gss-client!) and msg is the message.  The command-line options have
+the following meanings:
+
+-port	The TCP port to which to connect.  Default is 4444.
+
+-mech	The OID of the GSS-API mechanism to use.
+
+-d	Tells the client to delegate credentials to the server.  For
+	the Kerberos GSS-API mechanism, this means that a forwardable
+	TGT will be sent to the server, which will put it in its
+	credential cache (you must have acquired your tickets with
+	"kinit -f" for this to work).
+
+-seq Tells the client to enforce ordered message delivery via
+    sequencing.  
+
+-noreplay Tells the client to disable the use of replay
+    detection.
+
+-nomutual Tells the client to disable the use of mutual authentication.
+
+-f	Tells the client that the "msg" argument is actually the name
+	of a file whose contents should be used as the message.
+
+-q	Tells the client to be quiet, i.e., to only print error
+	messages.
+
+-ccount	Specifies how many sessions the client should initiate with
+	the server (the "connection count").
+
+-mcount	Specifies how many times the message should be sent to the
+	server in each session (the "message count").
+
+-na	Tells the client not to do any authentication with the
+	server.  Implies "-nw", "-nx" and "-nm".
+
+-nw	Tells the client not to "wrap" messages.  Implies "-nx".
+
+-nx	Tells the client not to encrypt messages.
+
+-nm	Tells the client not to ask the server to send back a
+	cryptographic checksum ("MIC").
+
+To run the server on a host, you need to make sure that the principal
+corresponding to service_name is in the default keytab on the server
+host, and that the gss-server process can read the keytab.  For
+example, the service name "host@server" corresponds to the Kerberos
+principal "host/server.domain.com@REALM".
+
+This sample application uses the following GSS-API functions:
+
+	gss_accept_sec_context		gss_inquire_names_for_mech
+	gss_acquire_cred		gss_oid_to_str
+	gss_delete_sec_context		gss_release_buffer
+	gss_display_name		gss_release_cred
+	gss_display_status		gss_release_name
+	gss_export_sec_context		gss_release_oid
+	gss_get_mic			gss_release_oid_set
+	gss_import_name			gss_str_to_oid
+	gss_import_sec_context		gss_unwrap
+	gss_init_sec_context		gss_verify_mic
+	gss_inquire_context		gss_wrap
+  
+This application was originally written by Barry Jaspan of OpenVision
+Technologies, Inc.  It was updated significantly by Jonathan Kamens of
+OpenVision Technologies, Inc.
+
+$Id$
diff --git a/krb5-1-6/src/appl/gss-sample/gss-client.c b/krb5-1-6/src/appl/gss-sample/gss-client.c
new file mode 100644
index 000000000..0ee268499
--- /dev/null
+++ b/krb5-1-6/src/appl/gss-sample/gss-client.c
@@ -0,0 +1,808 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (C) 2003, 2004, 2005 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock.h>
+#else
+#include <assert.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+
+#include <gssapi/gssapi_generic.h>
+#include "gss-misc.h"
+
+static int verbose = 1;
+
+static void
+usage()
+{
+    fprintf(stderr, "Usage: gss-client [-port port] [-mech mechanism] [-d]\n");
+    fprintf(stderr, "       [-seq] [-noreplay] [-nomutual]");
+#ifdef _WIN32
+    fprintf(stderr, " [-threads num]");
+#endif
+    fprintf(stderr, "\n");
+    fprintf(stderr, "       [-f] [-q] [-ccount count] [-mcount count]\n");
+    fprintf(stderr, "       [-v1] [-na] [-nw] [-nx] [-nm] host service msg\n");
+    exit(1);
+}
+
+/*
+ * Function: connect_to_server
+ *
+ * Purpose: Opens a TCP connection to the name host and port.
+ *
+ * Arguments:
+ *
+ * 	host		(r) the target host name
+ * 	port		(r) the target port, in host byte order
+ *
+ * Returns: the established socket file desciptor, or -1 on failure
+ *
+ * Effects:
+ *
+ * The host name is resolved with gethostbyname(), and the socket is
+ * opened and connected.  If an error occurs, an error message is
+ * displayed and -1 is returned.
+ */
+static int
+connect_to_server(host, port)
+    char   *host;
+    u_short port;
+{
+    struct sockaddr_in saddr;
+    struct hostent *hp;
+    int     s;
+
+    if ((hp = gethostbyname(host)) == NULL) {
+	fprintf(stderr, "Unknown host: %s\n", host);
+	return -1;
+    }
+
+    saddr.sin_family = hp->h_addrtype;
+    memcpy((char *) &saddr.sin_addr, hp->h_addr, sizeof(saddr.sin_addr));
+    saddr.sin_port = htons(port);
+
+    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	perror("creating socket");
+	return -1;
+    }
+    if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
+	perror("connecting to server");
+	(void) close(s);
+	return -1;
+    }
+    return s;
+}
+
+/*
+ * Function: client_establish_context
+ *
+ * Purpose: establishes a GSS-API context with a specified service and
+ * returns the context handle
+ *
+ * Arguments:
+ *
+ * 	s		    (r) an established TCP connection to the service
+ * 	service_name(r) the ASCII service name of the service
+ *	gss_flags	(r) GSS-API delegation flag (if any)
+ *	auth_flag	(r) whether to actually do authentication
+ *  v1_format   (r) whether the v1 sample protocol should be used
+ *	oid		    (r) OID of the mechanism to use
+ * 	context		(w) the established GSS-API context
+ *	ret_flags	(w) the returned flags from init_sec_context
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * service_name is imported as a GSS-API name and a GSS-API context is
+ * established with the corresponding service; the service should be
+ * listening on the TCP connection s.  The default GSS-API mechanism
+ * is used, and mutual authentication and replay detection are
+ * requested.
+ * 
+ * If successful, the context handle is returned in context.  If
+ * unsuccessful, the GSS-API error messages are displayed on stderr
+ * and -1 is returned.
+ */
+static int
+client_establish_context(s, service_name, gss_flags, auth_flag,
+			 v1_format, oid, gss_context, ret_flags)
+    int     s;
+    char   *service_name;
+    gss_OID oid;
+    OM_uint32 gss_flags;
+    int     auth_flag;
+    int     v1_format;
+    gss_ctx_id_t *gss_context;
+    OM_uint32 *ret_flags;
+{
+    if (auth_flag) {
+	gss_buffer_desc send_tok, recv_tok, *token_ptr;
+	gss_name_t target_name;
+	OM_uint32 maj_stat, min_stat, init_sec_min_stat;
+	int     token_flags;
+
+	/*
+	 * Import the name into target_name.  Use send_tok to save
+	 * local variable space.
+	 */
+	send_tok.value = service_name;
+	send_tok.length = strlen(service_name);
+	maj_stat = gss_import_name(&min_stat, &send_tok,
+				   (gss_OID) gss_nt_service_name,
+				   &target_name);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("parsing name", maj_stat, min_stat);
+	    return -1;
+	}
+
+	if (!v1_format) {
+	    if (send_token(s, TOKEN_NOOP | TOKEN_CONTEXT_NEXT, empty_token) <
+		0) {
+		(void) gss_release_name(&min_stat, &target_name);
+		return -1;
+	    }
+	}
+
+	/*
+	 * Perform the context-establishement loop.
+	 *
+	 * On each pass through the loop, token_ptr points to the token
+	 * to send to the server (or GSS_C_NO_BUFFER on the first pass).
+	 * Every generated token is stored in send_tok which is then
+	 * transmitted to the server; every received token is stored in
+	 * recv_tok, which token_ptr is then set to, to be processed by
+	 * the next call to gss_init_sec_context.
+	 * 
+	 * GSS-API guarantees that send_tok's length will be non-zero
+	 * if and only if the server is expecting another token from us,
+	 * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
+	 * and only if the server has another token to send us.
+	 */
+
+	token_ptr = GSS_C_NO_BUFFER;
+	*gss_context = GSS_C_NO_CONTEXT;
+
+	do {
+	    maj_stat = gss_init_sec_context(&init_sec_min_stat, GSS_C_NO_CREDENTIAL, gss_context, target_name, oid, gss_flags, 0, NULL,	/* no channel bindings */
+					    token_ptr, NULL,	/* ignore mech type */
+					    &send_tok, ret_flags, NULL);	/* ignore time_rec */
+
+	    if (token_ptr != GSS_C_NO_BUFFER)
+		free(recv_tok.value);
+
+	    if (send_tok.length != 0) {
+		if (verbose)
+		    printf("Sending init_sec_context token (size=%d)...",
+			   (int) send_tok.length);
+		if (send_token(s, v1_format ? 0 : TOKEN_CONTEXT, &send_tok) <
+		    0) {
+		    (void) gss_release_buffer(&min_stat, &send_tok);
+		    (void) gss_release_name(&min_stat, &target_name);
+		    return -1;
+		}
+	    }
+	    (void) gss_release_buffer(&min_stat, &send_tok);
+
+	    if (maj_stat != GSS_S_COMPLETE
+		&& maj_stat != GSS_S_CONTINUE_NEEDED) {
+		display_status("initializing context", maj_stat,
+			       init_sec_min_stat);
+		(void) gss_release_name(&min_stat, &target_name);
+		if (*gss_context != GSS_C_NO_CONTEXT)
+		    gss_delete_sec_context(&min_stat, gss_context,
+					   GSS_C_NO_BUFFER);
+		return -1;
+	    }
+
+	    if (maj_stat == GSS_S_CONTINUE_NEEDED) {
+		if (verbose)
+		    printf("continue needed...");
+		if (recv_token(s, &token_flags, &recv_tok) < 0) {
+		    (void) gss_release_name(&min_stat, &target_name);
+		    return -1;
+		}
+		token_ptr = &recv_tok;
+	    }
+	    if (verbose)
+		printf("\n");
+	} while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+	(void) gss_release_name(&min_stat, &target_name);
+    } else {
+	if (send_token(s, TOKEN_NOOP, empty_token) < 0)
+	    return -1;
+    }
+
+    return 0;
+}
+
+static void
+read_file(file_name, in_buf)
+    char   *file_name;
+    gss_buffer_t in_buf;
+{
+    int     fd, count;
+    struct stat stat_buf;
+
+    if ((fd = open(file_name, O_RDONLY, 0)) < 0) {
+	perror("open");
+	fprintf(stderr, "Couldn't open file %s\n", file_name);
+	exit(1);
+    }
+    if (fstat(fd, &stat_buf) < 0) {
+	perror("fstat");
+	exit(1);
+    }
+    in_buf->length = stat_buf.st_size;
+
+    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",
+		(int) in_buf->length);
+	exit(1);
+    }
+
+    /* 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 (count < in_buf->length)
+	fprintf(stderr, "Warning, only read in %d bytes, expected %d\n",
+		count, (int) in_buf->length);
+}
+
+/*
+ * Function: call_server
+ *
+ * Purpose: Call the "sign" service.
+ *
+ * Arguments:
+ *
+ * 	host		(r) the host providing the service
+ * 	port		(r) the port to connect to on host
+ * 	service_name	(r) the GSS-API service name to authenticate to
+ *	gss_flags	(r) GSS-API delegation flag (if any)
+ *	auth_flag	(r) whether to do authentication
+ *	wrap_flag	(r) whether to do message wrapping at all
+ *	encrypt_flag	(r) whether to do encryption while wrapping
+ *	mic_flag	(r) whether to request a MIC from the server
+ * 	msg		(r) the message to have "signed"
+ *	use_file	(r) whether to treat msg as an input file name
+ *	mcount		(r) the number of times to send the message
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * call_server opens a TCP connection to <host:port> and establishes a
+ * GSS-API context with service_name over the connection.  It then
+ * seals msg in a GSS-API token with gss_wrap, 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.  */
+static int
+call_server(host, port, oid, service_name, gss_flags, auth_flag,
+	    wrap_flag, encrypt_flag, mic_flag, v1_format, msg, use_file,
+	    mcount)
+    char   *host;
+    u_short port;
+    gss_OID oid;
+    char   *service_name;
+    OM_uint32 gss_flags;
+    int     auth_flag, wrap_flag, encrypt_flag, mic_flag;
+    int     v1_format;
+    char   *msg;
+    int     use_file;
+    int     mcount;
+{
+    gss_ctx_id_t context;
+    gss_buffer_desc in_buf, out_buf;
+    int     s, state;
+    OM_uint32 ret_flags;
+    OM_uint32 maj_stat, min_stat;
+    gss_name_t src_name, targ_name;
+    gss_buffer_desc sname, tname;
+    OM_uint32 lifetime;
+    gss_OID mechanism, name_type;
+    int     is_local;
+    OM_uint32 context_flags;
+    int     is_open;
+    gss_qop_t qop_state;
+    gss_OID_set mech_names;
+    gss_buffer_desc oid_name;
+    size_t  i;
+    int     token_flags;
+
+    /* Open connection */
+    if ((s = connect_to_server(host, port)) < 0)
+	return -1;
+
+    /* Establish context */
+    if (client_establish_context(s, service_name, gss_flags, auth_flag,
+				 v1_format, oid, &context, &ret_flags) < 0) {
+	(void) close(s);
+	return -1;
+    }
+
+    if (auth_flag && verbose) {
+	/* display the flags */
+	display_ctx_flags(ret_flags);
+
+	/* Get context information */
+	maj_stat = gss_inquire_context(&min_stat, context,
+				       &src_name, &targ_name, &lifetime,
+				       &mechanism, &context_flags,
+				       &is_local, &is_open);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("inquiring context", maj_stat, min_stat);
+	    return -1;
+	}
+
+	maj_stat = gss_display_name(&min_stat, src_name, &sname, &name_type);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("displaying source name", maj_stat, min_stat);
+	    return -1;
+	}
+	maj_stat = gss_display_name(&min_stat, targ_name, &tname,
+				    (gss_OID *) NULL);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("displaying target name", maj_stat, min_stat);
+	    return -1;
+	}
+	printf("\"%.*s\" to \"%.*s\", lifetime %d, flags %x, %s, %s\n",
+	       (int) sname.length, (char *) sname.value,
+	       (int) tname.length, (char *) tname.value, lifetime,
+	       context_flags,
+	       (is_local) ? "locally initiated" : "remotely initiated",
+	       (is_open) ? "open" : "closed");
+
+	(void) gss_release_name(&min_stat, &src_name);
+	(void) gss_release_name(&min_stat, &targ_name);
+	(void) gss_release_buffer(&min_stat, &sname);
+	(void) gss_release_buffer(&min_stat, &tname);
+
+	maj_stat = gss_oid_to_str(&min_stat, name_type, &oid_name);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("converting oid->string", maj_stat, min_stat);
+	    return -1;
+	}
+	printf("Name type of source name is %.*s.\n",
+	       (int) oid_name.length, (char *) oid_name.value);
+	(void) gss_release_buffer(&min_stat, &oid_name);
+
+	/* Now get the names supported by the mechanism */
+	maj_stat = gss_inquire_names_for_mech(&min_stat,
+					      mechanism, &mech_names);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("inquiring mech names", maj_stat, min_stat);
+	    return -1;
+	}
+
+	maj_stat = gss_oid_to_str(&min_stat, mechanism, &oid_name);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("converting oid->string", maj_stat, min_stat);
+	    return -1;
+	}
+	printf("Mechanism %.*s supports %d names\n",
+	       (int) oid_name.length, (char *) oid_name.value,
+	       (int) mech_names->count);
+	(void) gss_release_buffer(&min_stat, &oid_name);
+
+	for (i = 0; i < mech_names->count; i++) {
+	    maj_stat = gss_oid_to_str(&min_stat,
+				      &mech_names->elements[i], &oid_name);
+	    if (maj_stat != GSS_S_COMPLETE) {
+		display_status("converting oid->string", maj_stat, min_stat);
+		return -1;
+	    }
+	    printf("  %d: %.*s\n", (int) i,
+		   (int) oid_name.length, (char *) oid_name.value);
+
+	    (void) gss_release_buffer(&min_stat, &oid_name);
+	}
+	(void) gss_release_oid_set(&min_stat, &mech_names);
+    }
+
+    if (use_file) {
+	read_file(msg, &in_buf);
+    } else {
+	/* Seal the message */
+	in_buf.value = msg;
+	in_buf.length = strlen(msg);
+    }
+
+    for (i = 0; i < mcount; i++) {
+	if (wrap_flag) {
+	    maj_stat =
+		gss_wrap(&min_stat, context, encrypt_flag, GSS_C_QOP_DEFAULT,
+			 &in_buf, &state, &out_buf);
+	    if (maj_stat != GSS_S_COMPLETE) {
+		display_status("wrapping message", maj_stat, min_stat);
+		(void) close(s);
+		(void) gss_delete_sec_context(&min_stat, &context,
+					      GSS_C_NO_BUFFER);
+		return -1;
+	    } else if (encrypt_flag && !state) {
+		fprintf(stderr, "Warning!  Message not encrypted.\n");
+	    }
+	} else {
+	    out_buf = in_buf;
+	}
+
+	/* Send to server */
+	if (send_token(s, (v1_format ? 0
+			   : (TOKEN_DATA |
+			      (wrap_flag ? TOKEN_WRAPPED : 0) |
+			      (encrypt_flag ? TOKEN_ENCRYPTED : 0) |
+			      (mic_flag ? TOKEN_SEND_MIC : 0))),
+		       &out_buf) < 0) {
+	    (void) close(s);
+	    (void) gss_delete_sec_context(&min_stat, &context,
+					  GSS_C_NO_BUFFER);
+	    return -1;
+	}
+	if (out_buf.value != in_buf.value)
+	    (void) gss_release_buffer(&min_stat, &out_buf);
+
+	/* Read signature block into out_buf */
+	if (recv_token(s, &token_flags, &out_buf) < 0) {
+	    (void) close(s);
+	    (void) gss_delete_sec_context(&min_stat, &context,
+					  GSS_C_NO_BUFFER);
+	    return -1;
+	}
+
+	if (mic_flag) {
+	    /* Verify signature block */
+	    maj_stat = gss_verify_mic(&min_stat, context, &in_buf,
+				      &out_buf, &qop_state);
+	    if (maj_stat != GSS_S_COMPLETE) {
+		display_status("verifying signature", maj_stat, min_stat);
+		(void) close(s);
+		(void) gss_delete_sec_context(&min_stat, &context,
+					      GSS_C_NO_BUFFER);
+		return -1;
+	    }
+
+	    if (verbose)
+		printf("Signature verified.\n");
+	} else {
+	    if (verbose)
+		printf("Response received.\n");
+	}
+
+	free(out_buf.value);
+    }
+
+    if (use_file)
+	free(in_buf.value);
+
+    /* Send NOOP */
+    if (!v1_format)
+	(void) send_token(s, TOKEN_NOOP, empty_token);
+
+    if (auth_flag) {
+	/* Delete context */
+	maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("deleting context", maj_stat, min_stat);
+	    (void) close(s);
+	    (void) gss_delete_sec_context(&min_stat, &context,
+					  GSS_C_NO_BUFFER);
+	    return -1;
+	}
+
+	(void) gss_release_buffer(&min_stat, &out_buf);
+    }
+
+    (void) close(s);
+    return 0;
+}
+
+static void
+parse_oid(char *mechanism, gss_OID * oid)
+{
+    char   *mechstr = 0, *cp;
+    gss_buffer_desc tok;
+    OM_uint32 maj_stat, min_stat;
+
+    if (isdigit((int) mechanism[0])) {
+	mechstr = malloc(strlen(mechanism) + 5);
+	if (!mechstr) {
+	    fprintf(stderr, "Couldn't allocate mechanism scratch!\n");
+	    return;
+	}
+	sprintf(mechstr, "{ %s }", mechanism);
+	for (cp = mechstr; *cp; cp++)
+	    if (*cp == '.')
+		*cp = ' ';
+	tok.value = mechstr;
+    } else
+	tok.value = mechanism;
+    tok.length = strlen(tok.value);
+    maj_stat = gss_str_to_oid(&min_stat, &tok, oid);
+    if (maj_stat != GSS_S_COMPLETE) {
+	display_status("str_to_oid", maj_stat, min_stat);
+	return;
+    }
+    if (mechstr)
+	free(mechstr);
+}
+
+static int max_threads = 1;
+
+#ifdef _WIN32
+static  thread_count = 0;
+static HANDLE hMutex = NULL;
+static HANDLE hEvent = NULL;
+
+void
+InitHandles(void)
+{
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+void
+CleanupHandles(void)
+{
+    CloseHandle(hMutex);
+    CloseHandle(hEvent);
+}
+
+BOOL
+WaitAndIncrementThreadCounter(void)
+{
+    for (;;) {
+	if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+	    if (thread_count < max_threads) {
+		thread_count++;
+		ReleaseMutex(hMutex);
+		return TRUE;
+	    } else {
+		ReleaseMutex(hMutex);
+
+		if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) {
+		    continue;
+		} else {
+		    return FALSE;
+		}
+	    }
+	} else {
+	    return FALSE;
+	}
+    }
+}
+
+BOOL
+DecrementAndSignalThreadCounter(void)
+{
+    if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+	if (thread_count == max_threads)
+	    ResetEvent(hEvent);
+	thread_count--;
+	ReleaseMutex(hMutex);
+	return TRUE;
+    } else {
+	return FALSE;
+    }
+}
+#endif
+
+static char *service_name, *server_host, *msg;
+static char *mechanism = 0;
+static u_short port = 4444;
+static int use_file = 0;
+static OM_uint32 gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
+static OM_uint32 min_stat;
+static gss_OID oid = GSS_C_NULL_OID;
+static int mcount = 1, ccount = 1;
+static int auth_flag, wrap_flag, encrypt_flag, mic_flag, v1_format;
+
+static void
+worker_bee(void *unused)
+{
+    if (call_server(server_host, port, oid, service_name,
+		    gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag,
+		    v1_format, msg, use_file, mcount) < 0)
+	exit(1);
+
+#ifdef _WIN32
+    if (max_threads > 1)
+	DecrementAndSignalThreadCounter();
+#endif
+}
+
+int
+main(argc, argv)
+    int     argc;
+    char  **argv;
+{
+    int     i;
+
+    display_file = stdout;
+    auth_flag = wrap_flag = encrypt_flag = mic_flag = 1;
+    v1_format = 0;
+
+    /* Parse arguments. */
+    argc--;
+    argv++;
+    while (argc) {
+	if (strcmp(*argv, "-port") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    port = atoi(*argv);
+	} else if (strcmp(*argv, "-mech") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    mechanism = *argv;
+	}
+#ifdef _WIN32
+	else if (strcmp(*argv, "-threads") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    max_threads = atoi(*argv);
+	}
+#endif
+	else if (strcmp(*argv, "-d") == 0) {
+	    gss_flags |= GSS_C_DELEG_FLAG;
+	} else if (strcmp(*argv, "-seq") == 0) {
+	    gss_flags |= GSS_C_SEQUENCE_FLAG;
+	} else if (strcmp(*argv, "-noreplay") == 0) {
+	    gss_flags &= ~GSS_C_REPLAY_FLAG;
+	} else if (strcmp(*argv, "-nomutual") == 0) {
+	    gss_flags &= ~GSS_C_MUTUAL_FLAG;
+	} else if (strcmp(*argv, "-f") == 0) {
+	    use_file = 1;
+	} else if (strcmp(*argv, "-q") == 0) {
+	    verbose = 0;
+	} else if (strcmp(*argv, "-ccount") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    ccount = atoi(*argv);
+	    if (ccount <= 0)
+		usage();
+	} else if (strcmp(*argv, "-mcount") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    mcount = atoi(*argv);
+	    if (mcount < 0)
+		usage();
+	} else if (strcmp(*argv, "-na") == 0) {
+	    auth_flag = wrap_flag = encrypt_flag = mic_flag = 0;
+	} else if (strcmp(*argv, "-nw") == 0) {
+	    wrap_flag = 0;
+	} else if (strcmp(*argv, "-nx") == 0) {
+	    encrypt_flag = 0;
+	} else if (strcmp(*argv, "-nm") == 0) {
+	    mic_flag = 0;
+	} else if (strcmp(*argv, "-v1") == 0) {
+	    v1_format = 1;
+	} else
+	    break;
+	argc--;
+	argv++;
+    }
+    if (argc != 3)
+	usage();
+
+#ifdef _WIN32
+    if (max_threads < 1) {
+	fprintf(stderr, "warning: there must be at least one thread\n");
+	max_threads = 1;
+    }
+#endif
+
+    server_host = *argv++;
+    service_name = *argv++;
+    msg = *argv++;
+
+    if (mechanism)
+	parse_oid(mechanism, &oid);
+
+    if (max_threads == 1) {
+	for (i = 0; i < ccount; i++) {
+	    worker_bee(0);
+	}
+    } else {
+#ifdef _WIN32
+	for (i = 0; i < ccount; i++) {
+	    if (WaitAndIncrementThreadCounter()) {
+		uintptr_t handle = _beginthread(worker_bee, 0, (void *) 0);
+		if (handle == (uintptr_t) - 1) {
+		    exit(1);
+		}
+	    } else {
+		exit(1);
+	    }
+	}
+#else
+	/* boom */
+	assert(max_threads == 1);
+#endif
+    }
+
+    if (oid != GSS_C_NULL_OID)
+	(void) gss_release_oid(&min_stat, &oid);
+
+#ifdef _WIN32
+    CleanupHandles();
+#endif
+
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/gss-sample/gss-misc.c b/krb5-1-6/src/appl/gss-sample/gss-misc.c
new file mode 100644
index 000000000..fe578d1ab
--- /dev/null
+++ b/krb5-1-6/src/appl/gss-sample/gss-misc.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock.h>
+#else
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+
+/* need struct timeval */
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+#include <gssapi/gssapi_generic.h>
+#include "gss-misc.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *malloc();
+#endif
+
+FILE   *display_file;
+
+gss_buffer_desc empty_token_buf = { 0, (void *) "" };
+gss_buffer_t empty_token = &empty_token_buf;
+
+static void display_status_1(char *m, OM_uint32 code, int type);
+
+static int
+write_all(int fildes, char *buf, unsigned int nbyte)
+{
+    int     ret;
+    char   *ptr;
+
+    for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
+	ret = send(fildes, ptr, nbyte, 0);
+	if (ret < 0) {
+	    if (errno == EINTR)
+		continue;
+	    return (ret);
+	} else if (ret == 0) {
+	    return (ptr - buf);
+	}
+    }
+
+    return (ptr - buf);
+}
+
+static int
+read_all(int fildes, char *buf, unsigned int nbyte)
+{
+    int     ret;
+    char   *ptr;
+    fd_set  rfds;
+    struct timeval tv;
+
+    FD_ZERO(&rfds);
+    FD_SET(fildes, &rfds);
+    tv.tv_sec = 10;
+    tv.tv_usec = 0;
+
+    for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
+	if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0
+	    || !FD_ISSET(fildes, &rfds))
+	    return (ptr - buf);
+	ret = recv(fildes, ptr, nbyte, 0);
+	if (ret < 0) {
+	    if (errno == EINTR)
+		continue;
+	    return (ret);
+	} else if (ret == 0) {
+	    return (ptr - buf);
+	}
+    }
+
+    return (ptr - buf);
+}
+
+/*
+ * Function: send_token
+ *
+ * Purpose: Writes a token to a file descriptor.
+ *
+ * Arguments:
+ *
+ * 	s		(r) an open file descriptor
+ *	flags		(r) the flags to write
+ * 	tok		(r) the token to write
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ *
+ * If the flags are non-null, send_token writes the token flags (a
+ * single byte, even though they're passed in in an integer). Next,
+ * the token length (as a network long) and then the token data are
+ * written to the file descriptor s.  It returns 0 on success, and -1
+ * if an error occurs or if it could not write all the data.
+ */
+int
+send_token(s, flags, tok)
+    int     s;
+    int     flags;
+    gss_buffer_t tok;
+{
+    int     ret;
+    unsigned char char_flags = (unsigned char) flags;
+    unsigned char lenbuf[4];
+
+    if (char_flags) {
+	ret = write_all(s, (char *) &char_flags, 1);
+	if (ret != 1) {
+	    perror("sending token flags");
+	    return -1;
+	}
+    }
+    if (tok->length > 0xffffffffUL)
+	abort();
+    lenbuf[0] = (tok->length >> 24) & 0xff;
+    lenbuf[1] = (tok->length >> 16) & 0xff;
+    lenbuf[2] = (tok->length >> 8) & 0xff;
+    lenbuf[3] = tok->length & 0xff;
+
+    ret = write_all(s, lenbuf, 4);
+    if (ret < 0) {
+	perror("sending token length");
+	return -1;
+    } else if (ret != 4) {
+	if (display_file)
+	    fprintf(display_file,
+		    "sending token length: %d of %d bytes written\n", ret, 4);
+	return -1;
+    }
+
+    ret = write_all(s, tok->value, tok->length);
+    if (ret < 0) {
+	perror("sending token data");
+	return -1;
+    } else if (ret != tok->length) {
+	if (display_file)
+	    fprintf(display_file,
+		    "sending token data: %d of %d bytes written\n",
+		    ret, (int) tok->length);
+	return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * Function: recv_token
+ *
+ * Purpose: Reads a token from a file descriptor.
+ *
+ * Arguments:
+ *
+ * 	s		(r) an open file descriptor
+ *	flags		(w) the read flags
+ * 	tok		(w) the read token
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * recv_token reads the token flags (a single byte, even though
+ * they're stored into an integer, then reads the token length (as a
+ * network long), allocates memory to hold the data, and then reads
+ * the token data from the file descriptor s.  It blocks to read the
+ * length and data, if necessary.  On a successful return, the token
+ * should be freed with gss_release_buffer.  It returns 0 on success,
+ * and -1 if an error occurs or if it could not read all the data.
+ */
+int
+recv_token(s, flags, tok)
+    int     s;
+    int    *flags;
+    gss_buffer_t tok;
+{
+    int     ret;
+    unsigned char char_flags;
+    unsigned char lenbuf[4];
+
+    ret = read_all(s, (char *) &char_flags, 1);
+    if (ret < 0) {
+	perror("reading token flags");
+	return -1;
+    } else if (!ret) {
+	if (display_file)
+	    fputs("reading token flags: 0 bytes read\n", display_file);
+	return -1;
+    } else {
+	*flags = (int) char_flags;
+    }
+
+    if (char_flags == 0) {
+	lenbuf[0] = 0;
+	ret = read_all(s, &lenbuf[1], 3);
+	if (ret < 0) {
+	    perror("reading token length");
+	    return -1;
+	} else if (ret != 3) {
+	    if (display_file)
+		fprintf(display_file,
+			"reading token length: %d of %d bytes read\n", ret, 3);
+	    return -1;
+	}
+    } else {
+	ret = read_all(s, lenbuf, 4);
+	if (ret < 0) {
+	    perror("reading token length");
+	    return -1;
+	} else if (ret != 4) {
+	    if (display_file)
+		fprintf(display_file,
+			"reading token length: %d of %d bytes read\n", ret, 4);
+	    return -1;
+	}
+    }
+
+    tok->length = ((lenbuf[0] << 24)
+		   | (lenbuf[1] << 16)
+		   | (lenbuf[2] << 8)
+		   | lenbuf[3]);
+    tok->value = (char *) malloc(tok->length ? tok->length : 1);
+    if (tok->length && tok->value == NULL) {
+	if (display_file)
+	    fprintf(display_file, "Out of memory allocating token data\n");
+	return -1;
+    }
+
+    ret = read_all(s, (char *) tok->value, tok->length);
+    if (ret < 0) {
+	perror("reading token data");
+	free(tok->value);
+	return -1;
+    } else if (ret != tok->length) {
+	fprintf(stderr, "sending token data: %d of %d bytes written\n",
+		ret, (int) tok->length);
+	free(tok->value);
+	return -1;
+    }
+
+    return 0;
+}
+
+static void
+display_status_1(m, code, type)
+    char   *m;
+    OM_uint32 code;
+    int     type;
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc msg;
+    OM_uint32 msg_ctx;
+
+    msg_ctx = 0;
+    while (1) {
+	maj_stat = gss_display_status(&min_stat, code,
+				      type, GSS_C_NULL_OID, &msg_ctx, &msg);
+	if (display_file)
+	    fprintf(display_file, "GSS-API error %s: %s\n", m,
+		    (char *) msg.value);
+	(void) gss_release_buffer(&min_stat, &msg);
+
+	if (!msg_ctx)
+	    break;
+    }
+}
+
+/*
+ * Function: display_status
+ *
+ * Purpose: displays GSS-API messages
+ *
+ * Arguments:
+ *
+ * 	msg		a string to be displayed with the message
+ * 	maj_stat	the GSS-API major status code
+ * 	min_stat	the GSS-API minor status code
+ *
+ * Effects:
+ *
+ * The GSS-API messages associated with maj_stat and min_stat are
+ * displayed on stderr, each preceeded by "GSS-API error <msg>: " and
+ * followed by a newline.
+ */
+void
+display_status(msg, maj_stat, min_stat)
+    char   *msg;
+    OM_uint32 maj_stat;
+    OM_uint32 min_stat;
+{
+    display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
+    display_status_1(msg, min_stat, GSS_C_MECH_CODE);
+}
+
+/*
+ * Function: display_ctx_flags
+ *
+ * Purpose: displays the flags returned by context initation in
+ *	    a human-readable form
+ *
+ * Arguments:
+ *
+ * 	int		ret_flags
+ *
+ * Effects:
+ *
+ * Strings corresponding to the context flags are printed on
+ * stdout, preceded by "context flag: " and followed by a newline
+ */
+
+void
+display_ctx_flags(flags)
+    OM_uint32 flags;
+{
+    if (flags & GSS_C_DELEG_FLAG)
+	fprintf(display_file, "context flag: GSS_C_DELEG_FLAG\n");
+    if (flags & GSS_C_MUTUAL_FLAG)
+	fprintf(display_file, "context flag: GSS_C_MUTUAL_FLAG\n");
+    if (flags & GSS_C_REPLAY_FLAG)
+	fprintf(display_file, "context flag: GSS_C_REPLAY_FLAG\n");
+    if (flags & GSS_C_SEQUENCE_FLAG)
+	fprintf(display_file, "context flag: GSS_C_SEQUENCE_FLAG\n");
+    if (flags & GSS_C_CONF_FLAG)
+	fprintf(display_file, "context flag: GSS_C_CONF_FLAG \n");
+    if (flags & GSS_C_INTEG_FLAG)
+	fprintf(display_file, "context flag: GSS_C_INTEG_FLAG \n");
+}
+
+void
+print_token(tok)
+    gss_buffer_t tok;
+{
+    int     i;
+    unsigned char *p = tok->value;
+
+    if (!display_file)
+	return;
+    for (i = 0; i < tok->length; i++, p++) {
+	fprintf(display_file, "%02x ", *p);
+	if ((i % 16) == 15) {
+	    fprintf(display_file, "\n");
+	}
+    }
+    fprintf(display_file, "\n");
+    fflush(display_file);
+}
+
+#ifdef _WIN32
+#include <sys\timeb.h>
+#include <time.h>
+
+int
+gettimeofday(struct timeval *tv, void *ignore_tz)
+{
+    struct _timeb tb;
+    _tzset();
+    _ftime(&tb);
+    if (tv) {
+	tv->tv_sec = tb.time;
+	tv->tv_usec = tb.millitm * 1000;
+    }
+    return 0;
+}
+#endif /* _WIN32 */
diff --git a/krb5-1-6/src/appl/gss-sample/gss-misc.h b/krb5-1-6/src/appl/gss-sample/gss-misc.h
new file mode 100644
index 000000000..35b3b7390
--- /dev/null
+++ b/krb5-1-6/src/appl/gss-sample/gss-misc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef _GSSMISC_H_
+#define _GSSMISC_H_
+
+#include <gssapi/gssapi_generic.h>
+#include <stdio.h>
+
+extern FILE *display_file;
+
+int send_token
+	(int s, int flags, gss_buffer_t tok);
+int recv_token
+	(int s, int *flags, gss_buffer_t tok);
+void display_status
+	(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat);
+void display_ctx_flags
+	(OM_uint32 flags);
+void print_token
+	(gss_buffer_t tok);
+
+/* Token types */
+#define TOKEN_NOOP		(1<<0)
+#define TOKEN_CONTEXT		(1<<1)
+#define TOKEN_DATA		(1<<2)
+#define TOKEN_MIC		(1<<3)
+
+/* Token flags */
+#define TOKEN_CONTEXT_NEXT	(1<<4)
+#define TOKEN_WRAPPED		(1<<5)
+#define TOKEN_ENCRYPTED		(1<<6)
+#define TOKEN_SEND_MIC		(1<<7)
+
+extern gss_buffer_t empty_token;
+
+#endif
diff --git a/krb5-1-6/src/appl/gss-sample/gss-server.c b/krb5-1-6/src/appl/gss-sample/gss-server.c
new file mode 100644
index 000000000..488f14ccc
--- /dev/null
+++ b/krb5-1-6/src/appl/gss-sample/gss-server.c
@@ -0,0 +1,793 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (C) 2004,2005 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdio.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock.h>
+#else
+#include "port-sockets.h"
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <gssapi/gssapi_generic.h>
+#include "gss-misc.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+static void
+usage()
+{
+    fprintf(stderr, "Usage: gss-server [-port port] [-verbose] [-once]");
+#ifdef _WIN32
+    fprintf(stderr, " [-threads num]");
+#endif
+    fprintf(stderr, "\n");
+    fprintf(stderr,
+	    "       [-inetd] [-export] [-logfile file] service_name\n");
+    exit(1);
+}
+
+static FILE *logfile;
+
+int     verbose = 0;
+
+/*
+ * Function: server_acquire_creds
+ *
+ * Purpose: imports a service name and acquires credentials for it
+ *
+ * Arguments:
+ *
+ * 	service_name	(r) the ASCII service name
+ * 	server_creds	(w) the GSS-API service credentials
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ *
+ * The service name is imported with gss_import_name, and service
+ * credentials are acquired with gss_acquire_cred.  If either opertion
+ * fails, an error message is displayed and -1 is returned; otherwise,
+ * 0 is returned.
+ */
+static int
+server_acquire_creds(service_name, server_creds)
+    char   *service_name;
+    gss_cred_id_t *server_creds;
+{
+    gss_buffer_desc name_buf;
+    gss_name_t server_name;
+    OM_uint32 maj_stat, min_stat;
+
+    name_buf.value = service_name;
+    name_buf.length = strlen(name_buf.value) + 1;
+    maj_stat = gss_import_name(&min_stat, &name_buf,
+			       (gss_OID) gss_nt_service_name, &server_name);
+    if (maj_stat != GSS_S_COMPLETE) {
+	display_status("importing name", maj_stat, min_stat);
+	return -1;
+    }
+
+    maj_stat = gss_acquire_cred(&min_stat, server_name, 0,
+				GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+				server_creds, NULL, NULL);
+    if (maj_stat != GSS_S_COMPLETE) {
+	display_status("acquiring credentials", maj_stat, min_stat);
+	return -1;
+    }
+
+    (void) gss_release_name(&min_stat, &server_name);
+
+    return 0;
+}
+
+/*
+ * Function: server_establish_context
+ *
+ * Purpose: establishses a GSS-API context as a specified service with
+ * an incoming client, and returns the context handle and associated
+ * client name
+ *
+ * Arguments:
+ *
+ * 	s		(r) an established TCP connection to the client
+ * 	service_creds	(r) server credentials, from gss_acquire_cred
+ * 	context		(w) the established GSS-API context
+ * 	client_name	(w) the client's ASCII name
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ *
+ * Any valid client request is accepted.  If a context is established,
+ * its handle is returned in context and the client name is returned
+ * in client_name and 0 is returned.  If unsuccessful, an error
+ * message is displayed and -1 is returned.
+ */
+static int
+server_establish_context(s, server_creds, context, client_name, ret_flags)
+    int     s;
+    gss_cred_id_t server_creds;
+    gss_ctx_id_t *context;
+    gss_buffer_t client_name;
+    OM_uint32 *ret_flags;
+{
+    gss_buffer_desc send_tok, recv_tok;
+    gss_name_t client;
+    gss_OID doid;
+    OM_uint32 maj_stat, min_stat, acc_sec_min_stat;
+    gss_buffer_desc oid_name;
+    int     token_flags;
+
+    if (recv_token(s, &token_flags, &recv_tok) < 0)
+	return -1;
+
+    if (recv_tok.value) {
+	free(recv_tok.value);
+	recv_tok.value = NULL;
+    }
+
+    if (!(token_flags & TOKEN_NOOP)) {
+	if (logfile)
+	    fprintf(logfile, "Expected NOOP token, got %d token instead\n",
+		    token_flags);
+	return -1;
+    }
+
+    *context = GSS_C_NO_CONTEXT;
+
+    if (token_flags & TOKEN_CONTEXT_NEXT) {
+	do {
+	    if (recv_token(s, &token_flags, &recv_tok) < 0)
+		return -1;
+
+	    if (verbose && logfile) {
+		fprintf(logfile, "Received token (size=%d): \n",
+			(int) recv_tok.length);
+		print_token(&recv_tok);
+	    }
+
+	    maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context, server_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &client, &doid, &send_tok, ret_flags, NULL,	/* ignore time_rec */
+					      NULL);	/* ignore del_cred_handle */
+
+	    if (recv_tok.value) {
+		free(recv_tok.value);
+		recv_tok.value = NULL;
+	    }
+
+	    if (send_tok.length != 0) {
+		if (verbose && logfile) {
+		    fprintf(logfile,
+			    "Sending accept_sec_context token (size=%d):\n",
+			    (int) send_tok.length);
+		    print_token(&send_tok);
+		}
+		if (send_token(s, TOKEN_CONTEXT, &send_tok) < 0) {
+		    if (logfile)
+			fprintf(logfile, "failure sending token\n");
+		    return -1;
+		}
+
+		(void) gss_release_buffer(&min_stat, &send_tok);
+	    }
+	    if (maj_stat != GSS_S_COMPLETE
+		&& maj_stat != GSS_S_CONTINUE_NEEDED) {
+		display_status("accepting context", maj_stat,
+			       acc_sec_min_stat);
+		if (*context != GSS_C_NO_CONTEXT)
+		    gss_delete_sec_context(&min_stat, context,
+					   GSS_C_NO_BUFFER);
+		return -1;
+	    }
+
+	    if (verbose && logfile) {
+		if (maj_stat == GSS_S_CONTINUE_NEEDED)
+		    fprintf(logfile, "continue needed...\n");
+		else
+		    fprintf(logfile, "\n");
+		fflush(logfile);
+	    }
+	} while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+	/* display the flags */
+	display_ctx_flags(*ret_flags);
+
+	if (verbose && logfile) {
+	    maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name);
+	    if (maj_stat != GSS_S_COMPLETE) {
+		display_status("converting oid->string", maj_stat, min_stat);
+		return -1;
+	    }
+	    fprintf(logfile, "Accepted connection using mechanism OID %.*s.\n",
+		    (int) oid_name.length, (char *) oid_name.value);
+	    (void) gss_release_buffer(&min_stat, &oid_name);
+	}
+
+	maj_stat = gss_display_name(&min_stat, client, client_name, &doid);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("displaying name", maj_stat, min_stat);
+	    return -1;
+	}
+	maj_stat = gss_release_name(&min_stat, &client);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("releasing name", maj_stat, min_stat);
+	    return -1;
+	}
+    } else {
+	client_name->length = *ret_flags = 0;
+
+	if (logfile)
+	    fprintf(logfile, "Accepted unauthenticated connection.\n");
+    }
+
+    return 0;
+}
+
+/*
+ * Function: create_socket
+ *
+ * Purpose: Opens a listening TCP socket.
+ *
+ * Arguments:
+ *
+ * 	port		(r) the port number on which to listen
+ *
+ * Returns: the listening socket file descriptor, or -1 on failure
+ *
+ * Effects:
+ *
+ * A listening socket on the specified port and created and returned.
+ * On error, an error message is displayed and -1 is returned.
+ */
+static int
+create_socket(port)
+    u_short port;
+{
+    struct sockaddr_in saddr;
+    int     s;
+    int     on = 1;
+
+    saddr.sin_family = AF_INET;
+    saddr.sin_port = htons(port);
+    saddr.sin_addr.s_addr = INADDR_ANY;
+
+    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	perror("creating socket");
+	return -1;
+    }
+    /* Let the socket be reused right away */
+    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
+    if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
+	perror("binding socket");
+	(void) close(s);
+	return -1;
+    }
+    if (listen(s, 5) < 0) {
+	perror("listening on socket");
+	(void) close(s);
+	return -1;
+    }
+    return s;
+}
+
+static float
+timeval_subtract(tv1, tv2)
+    struct timeval *tv1, *tv2;
+{
+    return ((tv1->tv_sec - tv2->tv_sec) +
+	    ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
+}
+
+/*
+ * Yes, yes, this isn't the best place for doing this test.
+ * DO NOT REMOVE THIS UNTIL A BETTER TEST HAS BEEN WRITTEN, THOUGH.
+ * 					-TYT
+ */
+static int
+test_import_export_context(context)
+    gss_ctx_id_t *context;
+{
+    OM_uint32 min_stat, maj_stat;
+    gss_buffer_desc context_token, copied_token;
+    struct timeval tm1, tm2;
+
+    /*
+     * Attempt to save and then restore the context.
+     */
+    gettimeofday(&tm1, (struct timezone *) 0);
+    maj_stat = gss_export_sec_context(&min_stat, context, &context_token);
+    if (maj_stat != GSS_S_COMPLETE) {
+	display_status("exporting context", maj_stat, min_stat);
+	return 1;
+    }
+    gettimeofday(&tm2, (struct timezone *) 0);
+    if (verbose && logfile)
+	fprintf(logfile, "Exported context: %d bytes, %7.4f seconds\n",
+		(int) context_token.length, timeval_subtract(&tm2, &tm1));
+    copied_token.length = context_token.length;
+    copied_token.value = malloc(context_token.length);
+    if (copied_token.value == 0) {
+	if (logfile)
+	    fprintf(logfile,
+		    "Couldn't allocate memory to copy context token.\n");
+	return 1;
+    }
+    memcpy(copied_token.value, context_token.value, copied_token.length);
+    maj_stat = gss_import_sec_context(&min_stat, &copied_token, context);
+    if (maj_stat != GSS_S_COMPLETE) {
+	display_status("importing context", maj_stat, min_stat);
+	return 1;
+    }
+    free(copied_token.value);
+    gettimeofday(&tm1, (struct timezone *) 0);
+    if (verbose && logfile)
+	fprintf(logfile, "Importing context: %7.4f seconds\n",
+		timeval_subtract(&tm1, &tm2));
+    (void) gss_release_buffer(&min_stat, &context_token);
+    return 0;
+}
+
+/*
+ * Function: sign_server
+ *
+ * Purpose: Performs the "sign" service.
+ *
+ * Arguments:
+ *
+ * 	s		(r) a TCP socket on which a connection has been
+ *			accept()ed
+ * 	service_name	(r) the ASCII name of the GSS-API service to
+ * 			establish a context as
+ *	export		(r) whether to test context exporting
+ * 
+ * Returns: -1 on error
+ *
+ * Effects:
+ *
+ * sign_server establishes a context, and performs a single sign request.
+ *
+ * A sign request is a single GSS-API sealed token.  The token is
+ * unsealed and a signature block, produced with gss_sign, is returned
+ * to the sender.  The context is the destroyed and the connection
+ * closed.
+ *
+ * If any error occurs, -1 is returned.
+ */
+static int
+sign_server(s, server_creds, export)
+    int     s;
+    gss_cred_id_t server_creds;
+    int     export;
+{
+    gss_buffer_desc client_name, xmit_buf, msg_buf;
+    gss_ctx_id_t context;
+    OM_uint32 maj_stat, min_stat;
+    int     i, conf_state, ret_flags;
+    char   *cp;
+    int     token_flags;
+
+    /* Establish a context with the client */
+    if (server_establish_context(s, server_creds, &context,
+				 &client_name, &ret_flags) < 0)
+	return (-1);
+
+    if (context == GSS_C_NO_CONTEXT) {
+	printf("Accepted unauthenticated connection.\n");
+    } else {
+	printf("Accepted connection: \"%.*s\"\n",
+	       (int) client_name.length, (char *) client_name.value);
+	(void) gss_release_buffer(&min_stat, &client_name);
+
+	if (export) {
+	    for (i = 0; i < 3; i++)
+		if (test_import_export_context(&context))
+		    return -1;
+	}
+    }
+
+    do {
+	/* Receive the message token */
+	if (recv_token(s, &token_flags, &xmit_buf) < 0)
+	    return (-1);
+
+	if (token_flags & TOKEN_NOOP) {
+	    if (logfile)
+		fprintf(logfile, "NOOP token\n");
+	    if (xmit_buf.value) {
+		free(xmit_buf.value);
+		xmit_buf.value = 0;
+	    }
+	    break;
+	}
+
+	if (verbose && logfile) {
+	    fprintf(logfile, "Message token (flags=%d):\n", token_flags);
+	    print_token(&xmit_buf);
+	}
+
+	if ((context == GSS_C_NO_CONTEXT) &&
+	    (token_flags & (TOKEN_WRAPPED | TOKEN_ENCRYPTED | TOKEN_SEND_MIC)))
+	{
+	    if (logfile)
+		fprintf(logfile,
+			"Unauthenticated client requested authenticated services!\n");
+	    if (xmit_buf.value) {
+		free(xmit_buf.value);
+		xmit_buf.value = 0;
+	    }
+	    return (-1);
+	}
+
+	if (token_flags & TOKEN_WRAPPED) {
+	    maj_stat = gss_unwrap(&min_stat, context, &xmit_buf, &msg_buf,
+				  &conf_state, (gss_qop_t *) NULL);
+	    if (maj_stat != GSS_S_COMPLETE) {
+		display_status("unsealing message", maj_stat, min_stat);
+		if (xmit_buf.value) {
+		    free(xmit_buf.value);
+		    xmit_buf.value = 0;
+		}
+		return (-1);
+	    } else if (!conf_state && (token_flags & TOKEN_ENCRYPTED)) {
+		fprintf(stderr, "Warning!  Message not encrypted.\n");
+	    }
+
+	    if (xmit_buf.value) {
+		free(xmit_buf.value);
+		xmit_buf.value = 0;
+	    }
+	} else {
+	    msg_buf = xmit_buf;
+	}
+
+	if (logfile) {
+	    fprintf(logfile, "Received message: ");
+	    cp = msg_buf.value;
+	    if ((isprint((int) cp[0]) || isspace((int) cp[0])) &&
+		(isprint((int) cp[1]) || isspace((int) cp[1]))) {
+		fprintf(logfile, "\"%.*s\"\n", (int) msg_buf.length,
+			(char *) msg_buf.value);
+	    } else {
+		fprintf(logfile, "\n");
+		print_token(&msg_buf);
+	    }
+	}
+
+	if (token_flags & TOKEN_SEND_MIC) {
+	    /* Produce a signature block for the message */
+	    maj_stat = gss_get_mic(&min_stat, context, GSS_C_QOP_DEFAULT,
+				   &msg_buf, &xmit_buf);
+	    if (maj_stat != GSS_S_COMPLETE) {
+		display_status("signing message", maj_stat, min_stat);
+		return (-1);
+	    }
+
+	    if (msg_buf.value) {
+		free(msg_buf.value);
+		msg_buf.value = 0;
+	    }
+
+	    /* Send the signature block to the client */
+	    if (send_token(s, TOKEN_MIC, &xmit_buf) < 0)
+		return (-1);
+
+	    if (xmit_buf.value) {
+		free(xmit_buf.value);
+		xmit_buf.value = 0;
+	    }
+	} else {
+	    if (msg_buf.value) {
+		free(msg_buf.value);
+		msg_buf.value = 0;
+	    }
+	    if (send_token(s, TOKEN_NOOP, empty_token) < 0)
+		return (-1);
+	}
+    } while (1 /* loop will break if NOOP received */ );
+
+    if (context != GSS_C_NO_CONTEXT) {
+	/* Delete context */
+	maj_stat = gss_delete_sec_context(&min_stat, &context, NULL);
+	if (maj_stat != GSS_S_COMPLETE) {
+	    display_status("deleting context", maj_stat, min_stat);
+	    return (-1);
+	}
+    }
+
+    if (logfile)
+	fflush(logfile);
+
+    return (0);
+}
+
+static int max_threads = 1;
+
+#ifdef _WIN32
+static  thread_count = 0;
+static HANDLE hMutex = NULL;
+static HANDLE hEvent = NULL;
+
+void
+InitHandles(void)
+{
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+void
+CleanupHandles(void)
+{
+    CloseHandle(hMutex);
+    CloseHandle(hEvent);
+}
+
+BOOL
+WaitAndIncrementThreadCounter(void)
+{
+    for (;;) {
+	if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+	    if (thread_count < max_threads) {
+		thread_count++;
+		ReleaseMutex(hMutex);
+		return TRUE;
+	    } else {
+		ReleaseMutex(hMutex);
+
+		if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) {
+		    continue;
+		} else {
+		    return FALSE;
+		}
+	    }
+	} else {
+	    return FALSE;
+	}
+    }
+}
+
+BOOL
+DecrementAndSignalThreadCounter(void)
+{
+    if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+	if (thread_count == max_threads)
+	    ResetEvent(hEvent);
+	thread_count--;
+	ReleaseMutex(hMutex);
+	return TRUE;
+    } else {
+	return FALSE;
+    }
+}
+#endif
+
+struct _work_plan
+{
+    int     s;
+    gss_cred_id_t server_creds;
+    int     export;
+};
+
+static void
+worker_bee(void *param)
+{
+    struct _work_plan *work = (struct _work_plan *) param;
+
+    /* this return value is not checked, because there's
+     * not really anything to do if it fails 
+     */
+    sign_server(work->s, work->server_creds, work->export);
+    closesocket(work->s);
+    free(work);
+
+#ifdef _WIN32
+    if (max_threads > 1)
+	DecrementAndSignalThreadCounter();
+#endif
+}
+
+int
+main(argc, argv)
+    int     argc;
+    char  **argv;
+{
+    char   *service_name;
+    gss_cred_id_t server_creds;
+    OM_uint32 min_stat;
+    u_short port = 4444;
+    int     once = 0;
+    int     do_inetd = 0;
+    int     export = 0;
+
+    logfile = stdout;
+    display_file = stdout;
+    argc--;
+    argv++;
+    while (argc) {
+	if (strcmp(*argv, "-port") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    port = atoi(*argv);
+	}
+#ifdef _WIN32
+	else if (strcmp(*argv, "-threads") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    max_threads = atoi(*argv);
+	}
+#endif
+	else if (strcmp(*argv, "-verbose") == 0) {
+	    verbose = 1;
+	} else if (strcmp(*argv, "-once") == 0) {
+	    once = 1;
+	} else if (strcmp(*argv, "-inetd") == 0) {
+	    do_inetd = 1;
+	} else if (strcmp(*argv, "-export") == 0) {
+	    export = 1;
+	} else if (strcmp(*argv, "-logfile") == 0) {
+	    argc--;
+	    argv++;
+	    if (!argc)
+		usage();
+	    /* Gross hack, but it makes it unnecessary to add an
+	     * extra argument to disable logging, and makes the code
+	     * more efficient because it doesn't actually write data
+	     * to /dev/null. */
+	    if (!strcmp(*argv, "/dev/null")) {
+		logfile = display_file = NULL;
+	    } else {
+		logfile = fopen(*argv, "a");
+		display_file = logfile;
+		if (!logfile) {
+		    perror(*argv);
+		    exit(1);
+		}
+	    }
+	} else
+	    break;
+	argc--;
+	argv++;
+    }
+    if (argc != 1)
+	usage();
+
+    if ((*argv)[0] == '-')
+	usage();
+
+#ifdef _WIN32
+    if (max_threads < 1) {
+	fprintf(stderr, "warning: there must be at least one thread\n");
+	max_threads = 1;
+    }
+
+    if (max_threads > 1 && do_inetd)
+	fprintf(stderr,
+		"warning: one thread may be used in conjunction with inetd\n");
+
+    InitHandles();
+#endif
+
+    service_name = *argv;
+
+    if (server_acquire_creds(service_name, &server_creds) < 0)
+	return -1;
+
+    if (do_inetd) {
+	close(1);
+	close(2);
+
+	sign_server(0, server_creds, export);
+	close(0);
+    } else {
+	int     stmp;
+
+	if ((stmp = create_socket(port)) >= 0) {
+	    if (listen(stmp, max_threads == 1 ? 0 : max_threads) < 0)
+		perror("listening on socket");
+
+	    do {
+		struct _work_plan *work = malloc(sizeof(struct _work_plan));
+
+		if (work == NULL) {
+		    fprintf(stderr, "fatal error: out of memory");
+		    break;
+		}
+
+		/* Accept a TCP connection */
+		if ((work->s = accept(stmp, NULL, 0)) < 0) {
+		    perror("accepting connection");
+		    continue;
+		}
+
+		work->server_creds = server_creds;
+		work->export = export;
+
+		if (max_threads == 1) {
+		    worker_bee((void *) work);
+		}
+#ifdef _WIN32
+		else {
+		    if (WaitAndIncrementThreadCounter()) {
+			uintptr_t handle =
+			    _beginthread(worker_bee, 0, (void *) work);
+			if (handle == (uintptr_t) - 1) {
+			    closesocket(work->s);
+			    free(work);
+			}
+		    } else {
+			fprintf(stderr,
+				"fatal error incrementing thread counter");
+			closesocket(work->s);
+			free(work);
+			break;
+		    }
+		}
+#endif
+	    } while (!once);
+
+	    closesocket(stmp);
+	}
+    }
+
+    (void) gss_release_cred(&min_stat, &server_creds);
+
+#ifdef _WIN32
+    CleanupHandles();
+#endif
+
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/gssftp/Makefile.in b/krb5-1-6/src/appl/gssftp/Makefile.in
new file mode 100644
index 000000000..4ea8995e8
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/Makefile.in
@@ -0,0 +1,6 @@
+thisconfigdir=.
+myfulldir=appl/gssftp
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+LOCAL_SUBDIRS=ftp ftpd
+LDFLAGS = -g
diff --git a/krb5-1-6/src/appl/gssftp/README.gssftp b/krb5-1-6/src/appl/gssftp/README.gssftp
new file mode 100644
index 000000000..e0dff5200
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/README.gssftp
@@ -0,0 +1,45 @@
+Notes on "Secure FTP" Implementation
+===============================================
+Mark Eichin <eichin@cygnus.com>, Cygnus Support
+last modified: 1995 Jan 14
+===============================================
+
+This implementation is supplied by Cygnus Support for inclusion in the MIT
+Kerberos V5 Release. 
+
+Copyrights:
+The original BSD ftp implementation is:
+ * Copyright (c) 1980, 1983, 1985, 1988, 1989, 1990, 1991 Regents of the
+   University of California.
+
+History and Credits (as of 1995 Jan 14)
+================================================
+
+Steve Lunt at Bellcore developed the original V4 kerberized ftp. He
+also started writing the IETF ftpsec draft at the time. This was
+available to the public, and Cygnus eventually incorporated it into
+CNS V4.
+
+Steve Lunt left Bellcore, and dropped out of the computer security
+field altogether, after handing the draft off to Marc Horowitz at
+OpenVision, who was working on a commercial GSSAPI implementation.
+
+Marc Horowitz left OpenVision and is back at MIT currently; in the
+mean time, Cygnus took the V4 ftp and upgraded it to use GSSAPI and
+draft-08, as well as integrating it into the Kerberos V5 autoconf
+based configuration scheme.
+
+Bill Schoofs <wjs@cray.com> supplied corrections to the implementation
+to more correctly match draft 8, as well as correcting some of the
+remaining KERBEROS_V4 code.
+
+Karri Balk - Contractor <kbalk@cup.hp.com> supplied additional
+corrections based on interoperation testing with non-free
+implementations.
+
+Marc Horowitz has indicated that a draft 9 is forthcoming, with some
+clarifications based on experience with this implementation.
+
+No other free implementation of draft-8 is known at this time. 
+
+
diff --git a/krb5-1-6/src/appl/gssftp/arpa/ftp.h b/krb5-1-6/src/appl/gssftp/arpa/ftp.h
new file mode 100644
index 000000000..e20285c4c
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/arpa/ftp.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 1983, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ftp.h	5.6 (Berkeley) 4/3/91
+ */
+
+#ifndef _FTP_H_
+#define	_FTP_H_
+
+/* Definitions for FTP; see RFC-765. */
+
+/*
+ * Reply codes.
+ */
+#define PRELIM		1	/* positive preliminary */
+#define COMPLETE	2	/* positive completion */
+#define CONTINUE	3	/* positive intermediate */
+#define TRANSIENT	4	/* transient negative completion */
+#define ERROR		5	/* permanent negative completion */
+
+/*
+ * Type codes
+ */
+#define	TYPE_A		1	/* ASCII */
+#define	TYPE_E		2	/* EBCDIC */
+#define	TYPE_I		3	/* image */
+#define	TYPE_L		4	/* local byte size */
+
+#ifdef FTP_NAMES
+char *typenames[] =  {"0", "ASCII", "EBCDIC", "Image", "Local" };
+#endif
+
+/*
+ * Form codes
+ */
+#define	FORM_N		1	/* non-print */
+#define	FORM_T		2	/* telnet format effectors */
+#define	FORM_C		3	/* carriage control (ASA) */
+#ifdef FTP_NAMES
+char *formnames[] =  {"0", "Nonprint", "Telnet", "Carriage-control" };
+#endif
+
+/*
+ * Structure codes
+ */
+#define	STRU_F		1	/* file (no record structure) */
+#define	STRU_R		2	/* record structure */
+#define	STRU_P		3	/* page structure */
+#ifdef FTP_NAMES
+char *strunames[] =  {"0", "File", "Record", "Page" };
+#endif
+
+/*
+ * Mode types
+ */
+#define	MODE_S		1	/* stream */
+#define	MODE_B		2	/* block */
+#define	MODE_C		3	/* compressed */
+#ifdef FTP_NAMES
+char *modenames[] =  {"0", "Stream", "Block", "Compressed" };
+#endif
+
+/*
+ * Protection levels
+ */
+#define	PROT_C		1	/* clear */
+#define	PROT_S		2	/* safe */
+#define	PROT_P		3	/* private */
+#define	PROT_E		4	/* confidential */
+
+#ifdef FTP_NAMES
+char *levelnames[] =  {"0", "Clear", "Safe", "Private", "Confidential" };
+#endif
+
+#if defined(KERBEROS) && defined(NOENCRYPTION)
+/* define away krb_rd_priv and krb_mk_priv.  Don't need them anyway. */
+/* This might not be the best place for this ... */
+#define krb_rd_priv(o,l,ses,s,h,c,m) krb_rd_safe(o,l,s,h,c,m)
+#define krb_mk_priv(i,o,l,ses,s,h,c) krb_mk_safe(i,o,l,s,h,c)
+#endif
+
+/*
+ * Record Tokens
+ */
+#define	REC_ESC		'\377'	/* Record-mode Escape */
+#define	REC_EOR		'\001'	/* Record-mode End-of-Record */
+#define REC_EOF		'\002'	/* Record-mode End-of-File */
+
+/*
+ * Block Header
+ */
+#define	BLK_EOR		0x80	/* Block is End-of-Record */
+#define	BLK_EOF		0x40	/* Block is End-of-File */
+#define BLK_ERRORS	0x20	/* Block is suspected of containing errors */
+#define	BLK_RESTART	0x10	/* Block is Restart Marker */
+
+#define	BLK_BYTECOUNT	2	/* Bytes in this block */
+
+#endif /* !_FTP_H_ */
diff --git a/krb5-1-6/src/appl/gssftp/arpa/telnet.h b/krb5-1-6/src/appl/gssftp/arpa/telnet.h
new file mode 100644
index 000000000..019bfeb60
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/arpa/telnet.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)telnet.h	5.14 (Berkeley) 4/3/91
+ */
+
+#ifndef _TELNET_H_
+#define	_TELNET_H_
+
+/*
+ * Definitions for the TELNET protocol.
+ */
+#define	IAC	255		/* interpret as command: */
+#define	DONT	254		/* you are not to use option */
+#define	DO	253		/* please, you use option */
+#define	WONT	252		/* I won't use option */
+#define	WILL	251		/* I will use option */
+#define	SB	250		/* interpret as subnegotiation */
+#define	GA	249		/* you may reverse the line */
+#define	EL	248		/* erase the current line */
+#define	EC	247		/* erase the current character */
+#define	AYT	246		/* are you there */
+#define	AO	245		/* abort output--but let prog finish */
+#define	IP	244		/* interrupt process--permanently */
+#define	BREAK	243		/* break */
+#define	DM	242		/* data mark--for connect. cleaning */
+#define	NOP	241		/* nop */
+#define	SE	240		/* end sub negotiation */
+#define EOR     239             /* end of record (transparent mode) */
+#define	ABORT	238		/* Abort process */
+#define	SUSP	237		/* Suspend process */
+#define	xEOF	236		/* End of file: EOF is already used... */
+
+#define SYNCH	242		/* for telfunc calls */
+
+#ifdef TELCMDS
+char *telcmds[] = {
+	"EOF", "SUSP", "ABORT", "EOR",
+	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
+	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
+};
+#else
+extern char *telcmds[];
+#endif
+
+#define	TELCMD_FIRST	xEOF
+#define	TELCMD_LAST	IAC
+#define	TELCMD_OK(x)	((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST)
+#define	TELCMD(x)	telcmds[(x)-TELCMD_FIRST]
+
+/* telnet options */
+#define TELOPT_BINARY	0	/* 8-bit data path */
+#define TELOPT_ECHO	1	/* echo */
+#define	TELOPT_RCP	2	/* prepare to reconnect */
+#define	TELOPT_SGA	3	/* suppress go ahead */
+#define	TELOPT_NAMS	4	/* approximate message size */
+#define	TELOPT_STATUS	5	/* give status */
+#define	TELOPT_TM	6	/* timing mark */
+#define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
+#define TELOPT_NAOL 	8	/* negotiate about output line width */
+#define TELOPT_NAOP 	9	/* negotiate about output page size */
+#define TELOPT_NAOCRD	10	/* negotiate about CR disposition */
+#define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops */
+#define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
+#define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition */
+#define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
+#define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
+#define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
+#define TELOPT_XASCII	17	/* extended ascic character set */
+#define	TELOPT_LOGOUT	18	/* force logout */
+#define	TELOPT_BM	19	/* byte macro */
+#define	TELOPT_DET	20	/* data entry terminal */
+#define	TELOPT_SUPDUP	21	/* supdup protocol */
+#define	TELOPT_SUPDUPOUTPUT 22	/* supdup output */
+#define	TELOPT_SNDLOC	23	/* send location */
+#define	TELOPT_TTYPE	24	/* terminal type */
+#define	TELOPT_EOR	25	/* end or record */
+#define	TELOPT_TUID	26	/* TACACS user identification */
+#define	TELOPT_OUTMRK	27	/* output marking */
+#define	TELOPT_TTYLOC	28	/* terminal location number */
+#define	TELOPT_3270REGIME 29	/* 3270 regime */
+#define	TELOPT_X3PAD	30	/* X.3 PAD */
+#define	TELOPT_NAWS	31	/* window size */
+#define	TELOPT_TSPEED	32	/* terminal speed */
+#define	TELOPT_LFLOW	33	/* remote flow control */
+#define TELOPT_LINEMODE	34	/* Linemode option */
+#define TELOPT_XDISPLOC	35	/* X Display Location */
+#define TELOPT_ENVIRON	36	/* Environment variables */
+#define	TELOPT_AUTHENTICATION 37/* Authenticate */
+#define	TELOPT_ENCRYPT	38	/* Encryption option */
+#define	TELOPT_EXOPL	255	/* extended-options-list */
+
+
+#define	NTELOPTS	(1+TELOPT_ENCRYPT)
+#ifdef TELOPTS
+char *telopts[NTELOPTS+1] = {
+	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
+	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
+	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
+	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
+	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
+	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
+	"LINEMODE", "XDISPLOC", "ENVIRON", "AUTHENTICATION",
+	"ENCRYPT",
+	0,
+};
+#define	TELOPT_FIRST	TELOPT_BINARY
+#define	TELOPT_LAST	TELOPT_ENCRYPT
+#define	TELOPT_OK(x)	((x) <= TELOPT_LAST && (x) >= TELOPT_FIRST)
+#define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
+#endif
+
+/* sub-option qualifiers */
+#define	TELQUAL_IS	0	/* option is... */
+#define	TELQUAL_SEND	1	/* send option */
+#define	TELQUAL_INFO	2	/* ENVIRON: informational version of IS */
+#define	TELQUAL_REPLY	2	/* AUTHENTICATION: client version of IS */
+#define	TELQUAL_NAME	3	/* AUTHENTICATION: client version of IS */
+
+/*
+ * LINEMODE suboptions
+ */
+
+#define	LM_MODE		1
+#define	LM_FORWARDMASK	2
+#define	LM_SLC		3
+
+#define	MODE_EDIT	0x01
+#define	MODE_TRAPSIG	0x02
+#define	MODE_ACK	0x04
+#define MODE_SOFT_TAB	0x08
+#define MODE_LIT_ECHO	0x10
+
+#define	MODE_MASK	0x1f
+
+/* Not part of protocol, but needed to simplify things... */
+#define MODE_FLOW		0x0100
+#define MODE_ECHO		0x0200
+#define MODE_INBIN		0x0400
+#define MODE_OUTBIN		0x0800
+#define MODE_FORCE		0x1000
+
+#define	SLC_SYNCH	1
+#define	SLC_BRK		2
+#define	SLC_IP		3
+#define	SLC_AO		4
+#define	SLC_AYT		5
+#define	SLC_EOR		6
+#define	SLC_ABORT	7
+#define	SLC_EOF		8
+#define	SLC_SUSP	9
+#define	SLC_EC		10
+#define	SLC_EL		11
+#define	SLC_EW		12
+#define	SLC_RP		13
+#define	SLC_LNEXT	14
+#define	SLC_XON		15
+#define	SLC_XOFF	16
+#define	SLC_FORW1	17
+#define	SLC_FORW2	18
+
+#define	NSLC		18
+
+/*
+ * For backwards compatability, we define SLC_NAMES to be the
+ * list of names if SLC_NAMES is not defined.
+ */
+#define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
+			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
+			"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
+#ifdef	SLC_NAMES
+char *slc_names[] = {
+	SLC_NAMELIST
+};
+#else
+extern char *slc_names[];
+#define	SLC_NAMES SLC_NAMELIST
+#endif
+
+#define	SLC_NAME_OK(x)	((x) >= 0 && (x) < NSLC)
+#define SLC_NAME(x)	slc_names[x]
+
+#define	SLC_NOSUPPORT	0
+#define	SLC_CANTCHANGE	1
+#define	SLC_VARIABLE	2
+#define	SLC_DEFAULT	3
+#define	SLC_LEVELBITS	0x03
+
+#define	SLC_FUNC	0
+#define	SLC_FLAGS	1
+#define	SLC_VALUE	2
+
+#define	SLC_ACK		0x80
+#define	SLC_FLUSHIN	0x40
+#define	SLC_FLUSHOUT	0x20
+
+#define	ENV_VALUE	0
+#define	ENV_VAR		1
+#define	ENV_ESC		2
+
+/*
+ * AUTHENTICATION suboptions
+ */
+
+/*
+ * Who is authenticating who ...
+ */
+#define	AUTH_WHO_CLIENT		0	/* Client authenticating server */
+#define	AUTH_WHO_SERVER		1	/* Server authenticating client */
+#define	AUTH_WHO_MASK		1
+
+/*
+ * amount of authentication done
+ */
+#define	AUTH_HOW_ONE_WAY	0
+#define	AUTH_HOW_MUTUAL		2
+#define	AUTH_HOW_MASK		2
+
+#define	AUTHTYPE_NULL		0
+#define	AUTHTYPE_KERBEROS_V4	1
+#define	AUTHTYPE_KERBEROS_V5	2
+#define	AUTHTYPE_SPX		3
+#define	AUTHTYPE_MINK		4
+#define	AUTHTYPE_CNT		5
+
+#define	AUTHTYPE_TEST		99
+
+#ifdef	AUTH_NAMES
+char *authtype_names[] = {
+	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
+};
+#else
+extern char *authtype_names[];
+#endif
+
+#define	AUTHTYPE_NAME_OK(x)	((x) >= 0 && (x) < AUTHTYPE_CNT)
+#define	AUTHTYPE_NAME(x)	authtype_names[x]
+
+/*
+ * ENCRYPTion suboptions
+ */
+#define	ENCRYPT_IS		0	/* I pick encryption type ... */
+#define	ENCRYPT_SUPPORT		1	/* I support encryption types ... */
+#define	ENCRYPT_REPLY		2	/* Initial setup response */
+#define	ENCRYPT_START		3	/* Am starting to send encrypted */
+#define	ENCRYPT_END		4	/* Am ending encrypted */
+#define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
+#define	ENCRYPT_REQEND		6	/* Request you send encrypting */
+#define	ENCRYPT_ENC_KEYID	7
+#define	ENCRYPT_DEC_KEYID	8
+#define	ENCRYPT_CNT		9
+
+#define	ENCTYPE_ANY		0
+#define	ENCTYPE_DES_CFB64	1
+#define	ENCTYPE_DES_OFB64	2
+#define	ENCTYPE_CNT		3
+
+#ifdef	ENCRYPT_NAMES
+char *encrypt_names[] = {
+	"IS", "SUPPORT", "REPLY", "START", "END",
+	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
+	0,
+};
+char *enctype_names[] = {
+	"ANY", "DES_CFB64",  "DES_OFB64",  0,
+};
+#else
+extern char *encrypt_names[];
+extern char *enctype_names[];
+#endif
+
+
+#define	ENCRYPT_NAME_OK(x)	((x) >= 0 && (x) < ENCRYPT_CNT)
+#define	ENCRYPT_NAME(x)		encrypt_names[x]
+
+#define	ENCTYPE_NAME_OK(x)	((x) >= 0 && (x) < ENCTYPE_CNT)
+#define	ENCTYPE_NAME(x)		enctype_names[x]
+
+#endif /* !_TELNET_H_ */
diff --git a/krb5-1-6/src/appl/gssftp/configure.in b/krb5-1-6/src/appl/gssftp/configure.in
new file mode 100644
index 000000000..e483b649c
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/configure.in
@@ -0,0 +1,68 @@
+K5_AC_INIT(README.gssftp)
+CONFIG_RULES
+AC_C_CONST
+AC_PROG_INSTALL
+AC_PROG_YACC
+KRB5_SIGTYPE
+CHECK_SIGNALS
+CHECK_SIGPROCMASK
+CHECK_SETJMP
+CHECK_WAIT_TYPE
+DECLARE_SYS_ERRLIST
+AC_HEADER_STDARG
+AC_CHECK_HEADER(termios.h,[AC_CHECK_FUNC(cfsetispeed,AC_DEFINE(POSIX_TERMIOS,1,[Define if POSIX termios interface found]))])
+AC_CHECK_HEADERS(unistd.h stdlib.h string.h sys/select.h sys/sockio.h paths.h)
+CHECK_UTMP
+DECLARE_SYS_ERRLIST
+AC_REPLACE_FUNCS(getdtablesize)
+AC_CHECK_FUNCS(getcwd getdtablesize getusershell seteuid setreuid setresuid strerror getenv)
+AC_CHECK_LIB(crypt,crypt) dnl 
+KRB5_AC_LIBUTIL
+dnl 
+dnl copied from appl/bsd/configure.in
+dnl
+AC_MSG_CHECKING([setenv])
+AC_CACHE_VAL(krb5_cv_setenv,
+[AC_TRY_LINK(
+[],[setenv("PATH","/bin",0);],
+krb5_cv_setenv=yes,krb5_cv_setenv=no)])
+AC_MSG_RESULT($krb5_cv_setenv)
+if test $krb5_cv_setenv = no; then
+SETENVSRC='$(srcdir)/../../bsd/setenv.c'
+SETENVOBJ=setenv.o
+AC_SUBST([SETENVSRC])
+AC_SUBST([SETENVOBJ])
+AC_DEFINE([NEED_SETENV],1,[Define if setenv needs to be defined])
+fi
+dnl
+dnl
+dnl
+AC_MSG_CHECKING([shadow password support])
+AC_CACHE_VAL(krb5_cv_shadow_pwd,
+[AC_TRY_LINK(
+[#include <sys/types.h>
+#include <pwd.h>
+#include <shadow.h>],
+[struct spwd *sp = getspnam("root")],
+krb5_cv_shadow_pwd=yes, krb5_cv_shadow_pwd=no)])
+AC_MSG_RESULT($krb5_cv_shadow_pwd)
+if test $krb5_cv_shadow_pwd = yes; then
+AC_DEFINE(HAVE_SHADOW,1,[Define if shadow password interface found])
+fi
+case $krb5_cv_host in
+alpha*-dec-osf*)
+	AC_CHECK_LIB(security,setluid,
+		AC_DEFINE(HAVE_SETLUID,1,[Define if setluid provided in OSF/1 security library])
+		FTPD_LIBS="$FTPD_LIBS -lsecurity"
+	)
+	;;
+esac
+dnl
+dnl
+dnl
+AC_SUBST(FTPD_LIBS)
+dnl
+dnl
+dnl
+KRB5_BUILD_PROGRAM
+V5_AC_OUTPUT_MAKEFILE(. ftp ftpd)
diff --git a/krb5-1-6/src/appl/gssftp/ftp/Makefile.in b/krb5-1-6/src/appl/gssftp/ftp/Makefile.in
new file mode 100644
index 000000000..490b5dc3b
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/Makefile.in
@@ -0,0 +1,104 @@
+thisconfigdir=./..
+myfulldir=appl/gssftp/ftp
+mydir=ftp
+BUILDTOP=$(REL)..$(S)..$(S)..
+#
+# appl/gssftp/ftp/Makefile.in
+#
+DEFINES = -DGSSAPI -DFTP_BUFSIZ=65535
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SRCS	= $(srcdir)/cmds.c $(srcdir)/cmdtab.c $(srcdir)/domacro.c \
+	  $(srcdir)/ftp.c $(srcdir)/getpass.c $(srcdir)/glob.c \
+	  $(srcdir)/main.c $(srcdir)/radix.c \
+	  $(srcdir)/ruserpass.c $(srcdir)/secure.c 
+
+
+OBJS	= $(OUTPRE)cmds.$(OBJEXT) $(OUTPRE)cmdtab.$(OBJEXT) \
+	  $(OUTPRE)domacro.$(OBJEXT) $(OUTPRE)ftp.$(OBJEXT) \
+	  $(OUTPRE)getpass.$(OBJEXT) $(OUTPRE)glob.$(OBJEXT) \
+	  $(OUTPRE)main.$(OBJEXT) $(OUTPRE)radix.$(OBJEXT) \
+	  $(OUTPRE)ruserpass.$(OBJEXT) $(OUTPRE)secure.$(OBJEXT)
+
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir) @KRB4_INCLUDES@
+
+#
+# We cannot have @KRB4_INCLUDES@ under Windows, since we do not use
+# configure, so we redefine LOCALINCLUDES not to have that.
+#
+
+##WIN32##LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)
+
+all-unix::	ftp
+all-windows::	$(OUTPRE)ftp.exe
+
+ftp:	$(OBJS) $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o ftp $(OBJS) $(GSS_LIBS) $(KRB4COMPAT_LIBS)
+
+$(OUTPRE)ftp.exe: $(OBJS) $(GLIB) $(KLIB)
+	link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib advapi32.lib $(SCLIB)
+	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) ftp
+
+depend::
+
+install-unix::
+	for f in ftp; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
+
+ftp.o cmds.o main.o:	$(srcdir)/../arpa/ftp.h
+ftp.o cmds.o cmdtab.o domacro.o main.o ruserpass.o: $(srcdir)/ftp_var.h 
+secure.o: secure.h
+
+cmds.o: $(srcdir)/cmds.c
+cmdtab.o: $(srcdir)/cmdtab.c
+ftp.o: $(srcdir)/ftp.c
+getpass.o: $(srcdir)/getpass.c
+glob.o: $(srcdir)/glob.c
+main.o: $(srcdir)/main.c
+pclose.o: $(srcdir)/pclose.c
+ruserpass.o: $(srcdir)/ruserpass.c
+domacro.o: $(srcdir)/domacro.c
+radix.o: $(srcdir)/radix.c
+secure.o: $(srcdir)/secure.c
+
+# NOPOSTFIX
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)cmds.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/port-sockets.h $(srcdir)/../arpa/ftp.h \
+  cmds.c ftp_var.h pathnames.h
+$(OUTPRE)cmdtab.$(OBJEXT): cmdtab.c ftp_var.h
+$(OUTPRE)domacro.$(OBJEXT): domacro.c ftp_var.h
+$(OUTPRE)ftp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(KRB_ERR_H_DEP) \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(srcdir)/../arpa/ftp.h \
+  $(srcdir)/../arpa/telnet.h ftp.c ftp_var.h secure.h
+$(OUTPRE)getpass.$(OBJEXT): ftp_var.h getpass.c
+$(OUTPRE)glob.$(OBJEXT): ftp_var.h glob.c
+$(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/port-sockets.h $(srcdir)/../arpa/ftp.h \
+  ftp_var.h main.c
+$(OUTPRE)radix.$(OBJEXT): ftp_var.h radix.c
+$(OUTPRE)ruserpass.$(OBJEXT): ftp_var.h ruserpass.c
+$(OUTPRE)secure.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(srcdir)/../arpa/ftp.h secure.c secure.h
diff --git a/krb5-1-6/src/appl/gssftp/ftp/cmds.c b/krb5-1-6/src/appl/gssftp/ftp/cmds.c
new file mode 100644
index 000000000..5044b4482
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/cmds.c
@@ -0,0 +1,2529 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmds.c	5.26 (Berkeley) 3/5/91";
+#endif /* not lint */
+
+/*
+ * FTP User Program -- Command Routines.
+ */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <port-sockets.h>
+
+#ifdef _WIN32
+#include <sys/stat.h>
+#include <direct.h>
+#include <mbstring.h>
+#undef ERROR
+#else
+#include <sys/wait.h>
+#include <sys/stat.h>
+#endif
+
+#include <arpa/ftp.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+
+#ifdef HAVE_GETCWD
+#define getwd(x) getcwd(x,MAXPATHLEN)
+#endif
+
+#include "ftp_var.h"
+#include "pathnames.h"
+
+extern	char *globerr;
+extern	char *home;
+extern	char *remglob();
+#ifndef HAVE_STRERROR
+#define strerror(error) (sys_errlist[error])
+#ifdef NEED_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+#endif
+
+extern off_t restart_point;
+extern char reply_string[];
+
+char *mname;
+jmp_buf jabort;
+
+extern	char *auth_type;
+extern int do_auth();
+
+static int globulize (char **);
+static int confirm (char *, char *);
+static int getit (int, char **, int, char *);
+static sigtype mabort (int);
+static void quote1 (char *, int, char **);
+static char *dotrans (char *);
+static char *domap (char *);
+
+/*
+ * `Another' gets another argument, and stores the new argc and argv.
+ * It reverts to the top level (via main.c's intr()) on EOF/error.
+ *
+ * Returns false if no new arguments have been added.
+ */
+int 
+another(pargc, pargv, prompt)
+	int *pargc;
+	char ***pargv;
+	char *prompt;
+{
+        int len = strlen(line), ret;
+	extern sig_t intr();
+
+	if (len >= sizeof(line) - 3) {
+		printf("sorry, arguments too long\n");
+		intr();
+	}
+	printf("(%s) ", prompt);
+	line[len++] = ' ';
+	if (fgets(&line[len], (signed) sizeof(line) - len, stdin) == NULL)
+		intr();
+	len += strlen(&line[len]);
+	if (len > 0 && line[len - 1] == '\n')
+		line[len - 1] = '\0';
+	makeargv();
+	ret = margc > *pargc;
+	*pargc = margc;
+	*pargv = margv;
+	return (ret);
+}
+
+/*
+ * Connect to peer server and
+ * auto-login, if possible.
+ */
+void setpeer(argc, argv)
+	int argc;
+	char *argv[];
+{
+	char *host, *hookup();
+	unsigned short port;
+
+	if (connected) {
+		printf("Already connected to %s, use close first.\n",
+			hostname);
+		code = -1;
+		return;
+	}
+	if (argc < 2)
+		(void) another(&argc, &argv, "to");
+	if (argc < 2 || argc > 3) {
+		printf("usage: %s host-name [port]\n", argv[0]);
+		code = -1;
+		return;
+	}
+	port = sp->s_port;
+	if (argc > 2) {
+		int iport = atoi (argv[2]);
+		if (iport <= 0 || iport >= 65536) {
+			printf("%s: bad port number-- %s\n", argv[1], argv[2]);
+			printf ("usage: %s host-name [port]\n", argv[0]);
+			code = -1;
+			return;
+		}
+		port = htons(iport);
+	}
+	host = hookup(argv[1], port);
+	if (host) {
+		int overbose;
+
+		connected = 1;
+		/*
+		 * Set up defaults for FTP.
+		 */
+		clevel = dlevel = PROT_C;
+		type = TYPE_A;
+		curtype = TYPE_A;
+		form = FORM_N;
+		mode = MODE_S;
+		stru = STRU_F;
+		(void) strcpy(bytename, "8"), bytesize = 8;
+		if (autoauth) {
+			if (do_auth() && autoencrypt) {
+ 				clevel = PROT_P;
+				setpbsz(1<<20);
+				if (command("PROT P") == COMPLETE)
+					dlevel = PROT_P;
+				else
+					fprintf(stderr, "ftp: couldn't enable encryption\n");
+			}
+			if(auth_type && clevel == PROT_C)
+				clevel = PROT_S;
+			if(autologin)
+				(void) login(argv[1]);
+		}
+
+#ifndef unix
+/* sigh */
+#if defined(_AIX) || defined(__hpux) || defined(BSD)
+#define unix
+#endif
+#endif
+
+/* XXX - WIN32 - Is this really ok for Win32 (binary vs text mode)? */
+#if defined(unix) && (NBBY == 8 || defined(linux)) || defined(_WIN32)
+/*
+ * this ifdef is to keep someone form "porting" this to an incompatible
+ * system and not checking this out. This way they have to think about it.
+ */
+		overbose = verbose;
+		if (debug == 0)
+			verbose = -1;
+		if (debug)
+		    printf("%s:%d: verbose=%d debug=%d overbose=%d\n",
+			   __FILE__, __LINE__, verbose, debug, overbose);
+		if (command("SYST") == COMPLETE && overbose) {
+			register char *cp, c=0;
+			cp = strchr(reply_string+4, ' ');
+			if (cp == NULL)
+				cp = strchr(reply_string+4, '\r');
+			if (cp) {
+				if (cp[-1] == '.')
+					cp--;
+				c = *cp;
+				*cp = '\0';
+			}
+
+			printf("Remote system type is %s.\n",
+				reply_string+4);
+			if (cp)
+				*cp = c;
+		}
+		if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
+			if (proxy)
+				unix_proxy = 1;
+			else
+				unix_server = 1;
+			/*
+			 * Set type to 0 (not specified by user),
+			 * meaning binary by default, but don't bother
+			 * telling server.  We can use binary
+			 * for text files unless changed by the user.
+			 */
+			type = 0;
+			if (overbose)
+			    printf("Using %s mode to transfer files.\n",
+				"binary");
+		} else {
+			if (proxy)
+				unix_proxy = 0;
+			else
+				unix_server = 0;
+			if (overbose && 
+			    !strncmp(reply_string, "215 TOPS20", 10))
+				printf(
+"Remember to set tenex mode when transfering binary files from this machine.\n");
+		}
+		verbose = overbose;
+#else
+		if (debug)
+		    printf("(!defined(unix): not checking remote system type)\n");
+#endif /* unix */
+	}
+}
+
+struct	levels {
+	char	*p_name;
+	char	*p_mode;
+	int	p_level;
+} levels[] = {
+	{ "clear",	"C",	PROT_C },
+	{ "safe",	"S",	PROT_S },
+#ifndef NOENCRYPTION
+	{ "private",	"P",	PROT_P },
+#endif
+	{ 0,             0,     0}
+};
+
+static char *
+getclevel()
+{
+	register struct levels *p;
+
+	for (p = levels; p->p_level != clevel; p++);
+	return(p->p_name);
+}
+
+static char *
+getdlevel()
+{
+	register struct levels *p;
+
+	for (p = levels; p->p_level != dlevel; p++);
+	return(p->p_name);
+}
+
+char *plevel[] = {
+	"protect",
+	"",
+	0
+};
+
+/*
+ * Set control channel protection level.
+ */
+void setclevel(argc, argv)
+	char *argv[];
+{
+	register struct levels *p;
+	int comret;
+
+	if (argc > 2) {
+		char *sep;
+
+		printf("usage: %s [", argv[0]);
+		sep = " ";
+		for (p = levels; p->p_name; p++) {
+			printf("%s%s", sep, p->p_name);
+			if (*sep == ' ')
+				sep = " | ";
+		}
+		printf(" ]\n");
+		code = -1;
+		return;
+	}
+	if (argc < 2) {
+		printf("Using %s protection level for commands.\n",
+			getclevel());
+		code = 0;
+		return;
+	}
+	for (p = levels; p->p_name; p++)
+		if (strcmp(argv[1], p->p_name) == 0)
+			break;
+	if (p->p_name == 0) {
+		printf("%s: unknown protection level\n", argv[1]);
+		code = -1;
+		return;
+	}
+	if (!auth_type) {
+		if (strcmp(p->p_name, "clear"))
+			printf("Cannot set protection level to %s\n", argv[1]);
+		return;
+	}
+	if (!strcmp(p->p_name, "clear")) {
+		comret = command("CCC");
+		if (comret == COMPLETE)
+			clevel = PROT_C; 
+		return;
+	}
+	clevel = p->p_level;
+	printf("Control channel protection level set to %s.\n", p->p_name);
+}
+
+/*
+ * Set data channel protection level.
+ */
+void
+setdlevel(argc, argv)
+	char *argv[];
+{
+	register struct levels *p;
+	int comret;
+
+	if (argc > 2) {
+		char *sep;
+
+		printf("usage: %s [", argv[0]);
+		sep = " ";
+		for (p = levels; p->p_name; p++) {
+			printf("%s%s", sep, p->p_name);
+			if (*sep == ' ')
+				sep = " | ";
+		}
+		printf(" ]\n");
+		code = -1;
+		return;
+	}
+	if (argc < 2) {
+		printf("Using %s protection level to transfer files.\n",
+			getdlevel());
+		code = 0;
+		return;
+	}
+	for (p = levels; p->p_name; p++)
+		if (strcmp(argv[1], p->p_name) == 0)
+			break;
+	if (p->p_name == 0) {
+		printf("%s: unknown protection level\n", argv[1]);
+		code = -1;
+		return;
+	}
+	if (!auth_type) {
+		if (strcmp(p->p_name, "clear"))
+			printf("Cannot set protection level to %s\n", argv[1]);
+		return;
+	}
+	/* Start with a PBSZ of 1 meg */
+	if (p->p_level != PROT_C) setpbsz(1<<20);
+	comret = command("PROT %s", p->p_mode);
+	if (comret == COMPLETE)
+		dlevel = p->p_level;
+}
+
+
+/*
+ * Set clear command protection level.
+ */
+/*VARARGS*/
+void
+ccc()
+{
+	plevel[1] = "clear";
+	setclevel(2, plevel);
+}
+
+/*
+ * Set clear data protection level.
+ */
+/*VARARGS*/
+void
+setclear()
+{
+	plevel[1] = "clear";
+	setdlevel(2, plevel);
+}
+
+/*
+ * Set safe data protection level.
+ */
+/*VARARGS*/
+void
+setsafe()
+{
+	plevel[1] = "safe";
+	setdlevel(2, plevel);
+}
+
+#ifndef NOENCRYPTION
+/*
+ * Set private data protection level.
+ */
+/*VARARGS*/
+void
+setprivate()
+{
+	plevel[1] = "private";
+	setdlevel(2, plevel);
+}
+#endif
+
+struct	types {
+	char	*t_name;
+	char	*t_mode;
+	int	t_type;
+	char	*t_arg;
+} types[] = {
+	{ "ascii",	"A",	TYPE_A,	0 },
+	{ "binary",	"I",	TYPE_I,	0 },
+	{ "image",	"I",	TYPE_I,	0 },
+	{ "ebcdic",	"E",	TYPE_E,	0 },
+	{ "tenex",	"L",	TYPE_L,	bytename },
+	{  0,            0 ,    0,      0}
+};
+
+static char *
+gettype()
+{
+	register struct types *p;
+	int t;
+
+	t = type;
+	if (t == 0)
+		t = TYPE_I;
+	for (p = types; p->t_type != t; p++);
+	return(p->t_name);
+}
+
+/*
+ * Set transfer type.
+ */
+void
+settype(argc, argv)
+	int argc;
+	char *argv[];
+{
+	register struct types *p;
+	int comret;
+
+	if (argc > 2) {
+		char *sep;
+
+		printf("usage: %s [", argv[0]);
+		sep = " ";
+		for (p = types; p->t_name; p++) {
+			printf("%s%s", sep, p->t_name);
+			sep = " | ";
+		}
+		printf(" ]\n");
+		code = -1;
+		return;
+	}
+	if (argc < 2) {
+		printf("Using %s mode to transfer files.\n", gettype());
+		code = 0;
+		return;
+	}
+	for (p = types; p->t_name; p++)
+		if (strcmp(argv[1], p->t_name) == 0)
+			break;
+	if (p->t_name == 0) {
+		printf("%s: unknown mode\n", argv[1]);
+		code = -1;
+		return;
+	}
+	if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
+		comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
+	else
+		comret = command("TYPE %s", p->t_mode);
+	if (comret == COMPLETE)
+		curtype = type = p->t_type;
+}
+
+/*
+ * Internal form of settype; changes current type in use with server
+ * without changing our notion of the type for data transfers.
+ * Used to change to and from ascii for listings.
+ */
+void changetype(newtype, show)
+	int newtype, show;
+{
+	register struct types *p;
+	int comret, oldverbose = verbose;
+
+	if (newtype == 0)
+		newtype = TYPE_I;
+	if (newtype == curtype)
+		return;
+	if (debug == 0 && show == 0)
+		verbose = 0;
+	for (p = types; p->t_name; p++)
+		if (newtype == p->t_type)
+			break;
+	if (p->t_name == 0) {
+		printf("ftp: internal error: unknown type %d\n", newtype);
+		return;
+	}
+	if (newtype == TYPE_L && bytename[0] != '\0')
+		comret = command("TYPE %s %s", p->t_mode, bytename);
+	else
+		comret = command("TYPE %s", p->t_mode);
+	if (comret == COMPLETE)
+		curtype = newtype;
+	verbose = oldverbose;
+}
+
+char *stype[] = {
+	"type",
+	"",
+	0
+};
+
+/*
+ * Set binary transfer type.
+ */
+/*VARARGS*/
+void setbinary()
+{
+	stype[1] = "binary";
+	settype(2, stype);
+}
+
+/*
+ * Set ascii transfer type.
+ */
+/*VARARGS*/
+void setascii()
+{
+	stype[1] = "ascii";
+	settype(2, stype);
+}
+
+/*
+ * Set tenex transfer type.
+ */
+/*VARARGS*/
+void settenex()
+{
+	stype[1] = "tenex";
+	settype(2, stype);
+}
+
+static char *
+get_mode()
+{
+	return("stream");
+}
+
+/*
+ * Set file transfer mode.
+ */
+/*ARGSUSED*/
+void set_mode(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	printf("We only support %s mode, sorry.\n", get_mode());
+	code = -1;
+}
+
+static char *
+getform()
+{
+	return("non-print");
+}
+
+/*
+ * Set file transfer format.
+ */
+/*ARGSUSED*/
+void setform(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	printf("We only support %s format, sorry.\n", getform());
+	code = -1;
+}
+
+static char *
+getstruct()
+{
+	return("file");
+}
+
+/*
+ * Set file transfer structure.
+ */
+/*ARGSUSED*/
+void setstruct(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	printf("We only support %s structure, sorry.\n", getstruct());
+	code = -1;
+}
+
+/*
+ * Send a single file.
+ */
+void put(argc, argv)
+	int argc;
+	char *argv[];
+{
+	char *cmd;
+	int loc = 0;
+	char *oldargv1, *oldargv2;
+
+	if (argc == 2) {
+		argc++;
+		argv[2] = argv[1];
+		loc++;
+	}
+	if (argc < 2 && !another(&argc, &argv, "local-file"))
+		goto usage;
+	if (argc < 3 && !another(&argc, &argv, "remote-file")) {
+usage:
+		printf("usage: %s local-file remote-file\n", argv[0]);
+		code = -1;
+		return;
+	}
+	oldargv1 = argv[1];
+	oldargv2 = argv[2];
+	if (!globulize(&argv[1])) {
+		code = -1;
+		return;
+	}
+	/*
+	 * If "globulize" modifies argv[1], and argv[2] is a copy of
+	 * the old argv[1], make it a copy of the new argv[1].
+	 */
+	if (argv[1] != oldargv1 && argv[2] == oldargv1) {
+		argv[2] = argv[1];
+	}
+	cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
+	if (loc && ntflag) {
+		argv[2] = dotrans(argv[2]);
+	}
+	if (loc && mapflag) {
+		argv[2] = domap(argv[2]);
+	}
+	sendrequest(cmd, argv[1], argv[2],
+	    argv[1] != oldargv1 || argv[2] != oldargv2);
+}
+
+/*
+ * Send multiple files.
+ */
+void mput(argc, argv)
+	int argc;
+	char **argv;
+{
+	register int i;
+	sig_t oldintr;
+	int ointer;
+	char *tp;
+
+	if (argc < 2 && !another(&argc, &argv, "local-files")) {
+		printf("usage: %s local-files\n", argv[0]);
+		code = -1;
+		return;
+	}
+	mname = argv[0];
+	mflag = 1;
+	oldintr = signal(SIGINT, mabort);
+	(void) setjmp(jabort);
+	if (proxy) {
+		char *cp, *tp2, tmpbuf[MAXPATHLEN];
+
+		while ((cp = remglob(argv,0)) != NULL) {
+			if (*cp == 0) {
+				mflag = 0;
+				continue;
+			}
+			if (mflag && confirm(argv[0], cp)) {
+				tp = cp;
+				if (mcase) {
+					while (*tp && !islower((unsigned char) (*tp))) {
+						tp++;
+					}
+					if (!*tp) {
+						tp = cp;
+						tp2 = tmpbuf;
+						while ((*tp2 = *tp) != 0) {
+						     if (isupper((unsigned char) *tp2)) {
+						        *tp2 = 'a' + *tp2 - 'A';
+						     }
+						     tp++;
+						     tp2++;
+						}
+					}
+					tp = tmpbuf;
+				}
+				if (ntflag) {
+					tp = dotrans(tp);
+				}
+				if (mapflag) {
+					tp = domap(tp);
+				}
+				sendrequest((sunique) ? "STOU" : "STOR",
+				    cp, tp, cp != tp || !interactive);
+				if (!mflag && fromatty) {
+					ointer = interactive;
+					interactive = 1;
+					if (confirm("Continue with","mput")) {
+						mflag++;
+					}
+					interactive = ointer;
+				}
+			}
+		}
+		(void) signal(SIGINT, oldintr);
+		mflag = 0;
+		return;
+	}
+	for (i = 1; i < argc; i++) {
+		register char **cpp, **gargs;
+
+		if (!doglob) {
+			if (mflag && confirm(argv[0], argv[i])) {
+				tp = (ntflag) ? dotrans(argv[i]) : argv[i];
+				tp = (mapflag) ? domap(tp) : tp;
+				sendrequest((sunique) ? "STOU" : "STOR",
+				    argv[i], tp, tp != argv[i] || !interactive);
+				if (!mflag && fromatty) {
+					ointer = interactive;
+					interactive = 1;
+					if (confirm("Continue with","mput")) {
+						mflag++;
+					}
+					interactive = ointer;
+				}
+			}
+			continue;
+		}
+		gargs = ftpglob(argv[i]);
+		if (globerr != NULL) {
+			printf("%s\n", globerr);
+			if (gargs) {
+				blkfree(gargs);
+				free((char *)gargs);
+			}
+			continue;
+		}
+		for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
+			if (mflag && confirm(argv[0], *cpp)) {
+				tp = (ntflag) ? dotrans(*cpp) : *cpp;
+				tp = (mapflag) ? domap(tp) : tp;
+				sendrequest((sunique) ? "STOU" : "STOR",
+				    *cpp, tp, *cpp != tp || !interactive);
+				if (!mflag && fromatty) {
+					ointer = interactive;
+					interactive = 1;
+					if (confirm("Continue with","mput")) {
+						mflag++;
+					}
+					interactive = ointer;
+				}
+			}
+		}
+		if (gargs != NULL) {
+			blkfree(gargs);
+			free((char *)gargs);
+		}
+	}
+	(void) signal(SIGINT, oldintr);
+	mflag = 0;
+}
+
+void reget(argc, argv)
+	int argc;
+	char *argv[];
+{
+	(void) getit(argc, argv, 1, "r+w");
+}
+
+void get(argc, argv)
+	int argc;
+	char *argv[];
+{
+	(void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
+}
+
+/*
+ * Receive one file.
+ */
+static int getit(argc, argv, restartit, rmode)
+	int argc;
+	char *argv[];
+	char *rmode;
+{
+	int loc = 0;
+	char *oldargv1, *oldargv2;
+
+	if (argc == 2) {
+		argc++;
+		argv[2] = argv[1];
+		loc++;
+	}
+	if (argc < 2 && !another(&argc, &argv, "remote-file"))
+		goto usage;
+	if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+		printf("usage: %s remote-file [ local-file ]\n", argv[0]);
+		code = -1;
+		return (0);
+	}
+	oldargv1 = argv[1];
+	oldargv2 = argv[2];
+	if (!globulize(&argv[2])) {
+		code = -1;
+		return (0);
+	}
+	if (loc && mcase) {
+		char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
+
+		while (*tp && !islower((unsigned char) *tp)) {
+			tp++;
+		}
+		if (!*tp) {
+			tp = argv[2];
+			tp2 = tmpbuf;
+			while ((*tp2 = *tp) != 0) {
+				if (isupper((unsigned char) *tp2)) {
+					*tp2 = 'a' + *tp2 - 'A';
+				}
+				tp++;
+				tp2++;
+			}
+			argv[2] = tmpbuf;
+		}
+	}
+	if (loc && ntflag)
+		argv[2] = dotrans(argv[2]);
+	if (loc && mapflag)
+		argv[2] = domap(argv[2]);
+	if (restartit) {
+		struct stat stbuf;
+		int ret;
+
+		ret = stat(argv[2], &stbuf);
+		if (restartit == 1) {
+			if (ret < 0) {
+				fprintf(stderr, "local: %s: %s\n", argv[2],
+					strerror(errno));
+				return (0);
+			}
+			restart_point = stbuf.st_size;
+		} else {
+			if (ret == 0) {
+				int overbose;
+
+				overbose = verbose;
+				if (debug == 0)
+					verbose = -1;
+				if (command("MDTM %s", argv[1]) == COMPLETE) {
+					int yy, mo, day, hour, min, sec;
+					struct tm *tm;
+					verbose = overbose;
+					sscanf(reply_string,
+					    "%*s %04d%02d%02d%02d%02d%02d",
+					    &yy, &mo, &day, &hour, &min, &sec);
+					tm = gmtime(&stbuf.st_mtime);
+					tm->tm_mon++;
+					if (tm->tm_year > yy-1900)
+						return (1);
+					else if (tm->tm_year == yy-1900) {
+						if (tm->tm_mon > mo)
+							return (1);
+					} else if (tm->tm_mon == mo) {
+						if (tm->tm_mday > day)
+							return (1);
+					} else if (tm->tm_mday == day) {
+						if (tm->tm_hour > hour)
+							return (1);
+					} else if (tm->tm_hour == hour) {
+						if (tm->tm_min > min)
+							return (1);
+					} else if (tm->tm_min == min) {
+						if (tm->tm_sec > sec)
+							return (1);
+					}
+				} else {
+					printf("%s\n", reply_string);
+					verbose = overbose;
+					return (0);
+				}
+			}
+		}
+	}
+
+	recvrequest("RETR", argv[2], argv[1], rmode,
+	    argv[1] != oldargv1 || argv[2] != oldargv2, loc);
+	restart_point = 0;
+	return (0);
+}
+
+static sigtype
+mabort(sig)
+	int sig;
+{
+	int ointer;
+
+	printf("\n");
+	(void) fflush(stdout);
+	if (mflag && fromatty) {
+		ointer = interactive;
+		interactive = 1;
+		if (confirm("Continue with", mname)) {
+			interactive = ointer;
+			longjmp(jabort,0);
+		}
+		interactive = ointer;
+	}
+	mflag = 0;
+	longjmp(jabort,0);
+}
+
+/*
+ * Get multiple files.
+ */
+void mget(argc, argv)
+	int argc;
+	char **argv;
+{
+	sig_t oldintr;
+	int ointer;
+	char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
+
+	if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+		printf("usage: %s remote-files\n", argv[0]);
+		code = -1;
+		return;
+	}
+	mname = argv[0];
+	mflag = 1;
+	oldintr = signal(SIGINT,mabort);
+	(void) setjmp(jabort);
+	while ((cp = remglob(argv,proxy)) != NULL) {
+		if (*cp == '\0') {
+			mflag = 0;
+			continue;
+		}
+		if (mflag && confirm(argv[0], cp)) {
+			tp = cp;
+			if (mcase) {
+				while (*tp && !islower((unsigned char) *tp)) {
+					tp++;
+				}
+				if (!*tp) {
+					tp = cp;
+					tp2 = tmpbuf;
+					while ((*tp2 = *tp) != 0) {
+						if (isupper((unsigned char) *tp2)) {
+							*tp2 = 'a' + *tp2 - 'A';
+						}
+						tp++;
+						tp2++;
+					}
+				}
+				tp = tmpbuf;
+			}
+			if (ntflag) {
+				tp = dotrans(tp);
+			}
+			if (mapflag) {
+				tp = domap(tp);
+			}
+			recvrequest("RETR", tp, cp, "w",
+			    tp != cp || !interactive, 1);
+			if (!mflag && fromatty) {
+				ointer = interactive;
+				interactive = 1;
+				if (confirm("Continue with","mget")) {
+					mflag++;
+				}
+				interactive = ointer;
+			}
+		}
+	}
+	(void) signal(SIGINT,oldintr);
+	mflag = 0;
+}
+
+char *
+remglob(argv,doswitch)
+	char *argv[];
+	int doswitch;
+{
+#ifdef _WIN32
+	char *temp = NULL;
+#else
+	char temp[16];
+#endif
+	static char buf[MAXPATHLEN];
+	static FILE *ftemp = NULL;
+	static char **args;
+	int oldverbose, oldhash;
+	char *cp, *rmode;
+
+	if (!mflag) {
+		if (!doglob) {
+			args = NULL;
+		}
+		else {
+			if (ftemp) {
+				(void) fclose(ftemp);
+				ftemp = NULL;
+			}
+		}
+		return(NULL);
+	}
+	if (!doglob) {
+		if (args == NULL)
+			args = argv;
+		if ((cp = *++args) == NULL)
+			args = NULL;
+		return (cp);
+	}
+	if (ftemp == NULL) {
+#ifdef _WIN32
+		temp = _tempnam(_PATH_TMP, "ftpglob");
+		if (temp == NULL) {
+			printf("can't get temporary file name\n");
+			return (NULL);
+		}
+#else
+		(void) strncpy(temp, _PATH_TMP, sizeof(temp) - 1);
+		temp[sizeof(temp) - 1] = '\0';
+		(void) mktemp(temp);
+#endif /* !_WIN32 */
+		oldverbose = verbose, verbose = 0;
+		oldhash = hash, hash = 0;
+		if (doswitch) {
+			pswitch(!proxy);
+		}
+		for (rmode = "w"; *++argv != NULL; rmode = "a")
+			recvrequest ("NLST", temp, *argv, rmode, 0, 0);
+		if (doswitch) {
+			pswitch(!proxy);
+		}
+		verbose = oldverbose; hash = oldhash;
+		ftemp = fopen(temp, "r");
+		(void) unlink(temp);
+#ifdef _WIN32
+		free(temp);
+		temp = NULL;
+#endif /* _WIN32 */
+		if (ftemp == NULL) {
+			printf("can't find list of remote files, oops\n");
+			return (NULL);
+		}
+	}
+	if (fgets(buf, sizeof (buf), ftemp) == NULL) {
+		(void) fclose(ftemp), ftemp = NULL;
+		return (NULL);
+	}
+	if ((cp = strchr(buf, '\n')) != NULL)
+		*cp = '\0';
+	return (buf);
+}
+
+static char *
+onoff(bool)
+	int bool;
+{
+
+	return (bool ? "on" : "off");
+}
+
+static void cstatus()
+{
+	if (!connected) {
+		printf(proxy ? "No proxy connection.\n" : "Not connected.\n");
+		return;
+	}
+	printf("Connected %sto %s.\n",
+		proxy ? "for proxy commands " : "", hostname);
+	if (auth_type) printf("Authentication type: %s\n", auth_type);
+	printf("Control Channel Protection Level: %s\n", getclevel());
+	printf("Data Channel Protection Level: %s\n", getdlevel());
+	printf("Passive mode %s\n", onoff(passivemode));
+	printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
+		get_mode(), gettype(), getform(), getstruct());
+	printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
+		onoff(runique));
+	printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
+	if (ntflag) {
+		printf("Ntrans: (in) %s (out) %s\n", ntin,ntout);
+	}
+	else {
+		printf("Ntrans: off\n");
+	}
+	if (mapflag) {
+		printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
+	}
+	else {
+		printf("Nmap: off\n");
+	}
+}
+
+/*
+ * Show status.
+ */
+/*ARGSUSED*/
+void status(argc, argv)
+	char *argv[];
+{
+	int i;
+
+	cstatus();
+	if (!proxy) {
+		pswitch(1);
+		if (connected) putchar('\n');
+		cstatus(argc,argv);
+		if (connected) putchar('\n');
+		pswitch(0);
+	}
+	printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
+		onoff(hash), onoff(sendport));
+	printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 
+		onoff(verbose), onoff(bell), onoff(interactive),
+		onoff(doglob));
+	if (macnum > 0) {
+		printf("Macros:\n");
+		for (i=0; i<macnum; i++) {
+			printf("\t%s\n",macros[i].mac_name);
+		}
+	}
+	code = 0;
+}
+
+/*
+ * Set beep on cmd completed mode.
+ */
+/*VARARGS*/
+void setbell()
+{
+
+	bell = !bell;
+	printf("Bell mode %s.\n", onoff(bell));
+	code = bell;
+}
+
+/*
+ * Turn on packet tracing.
+ */
+/*VARARGS*/
+void settrace()
+{
+
+	trace = !trace;
+	printf("Packet tracing %s.\n", onoff(trace));
+	code = trace;
+}
+
+/*
+ * Toggle hash mark printing during transfers.
+ */
+/*VARARGS*/
+void sethash()
+{
+
+	hash = !hash;
+	printf("Hash mark printing %s", onoff(hash));
+	code = hash;
+	if (hash)
+		printf(" (%d bytes/hash mark)", 1024);
+	printf(".\n");
+}
+
+/*
+ * Turn on printing of server echo's.
+ */
+/*VARARGS*/
+void setverbose()
+{
+
+	verbose = !verbose;
+	printf("Verbose mode %s.\n", onoff(verbose));
+	code = verbose;
+}
+
+/*
+ * Toggle PORT cmd use before each data connection.
+ */
+/*VARARGS*/
+void setport()
+{
+
+	sendport = !sendport;
+	printf("Use of PORT cmds %s.\n", onoff(sendport));
+	code = sendport;
+}
+
+/*
+ * Turn on interactive prompting
+ * during mget, mput, and mdelete.
+ */
+/*VARARGS*/
+void setprompt()
+{
+
+	interactive = !interactive;
+	printf("Interactive mode %s.\n", onoff(interactive));
+	code = interactive;
+}
+
+/*
+ * Toggle metacharacter interpretation
+ * on local file names.
+ */
+/*VARARGS*/
+void setglob()
+{
+	
+	doglob = !doglob;
+	printf("Globbing %s.\n", onoff(doglob));
+	code = doglob;
+}
+
+/*
+ * Set debugging mode on/off and/or
+ * set level of debugging.
+ */
+/*VARARGS*/
+void setdebug(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int val;
+
+	if (argc > 1) {
+		val = atoi(argv[1]);
+		if (val < 0) {
+			printf("%s: bad debugging value.\n", argv[1]);
+			code = -1;
+			return;
+		}
+	} else
+		val = !debug;
+	debug = val;
+	if (debug)
+		options |= SO_DEBUG;
+	else
+		options &= ~SO_DEBUG;
+	printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
+	code = debug > 0;
+}
+
+/*
+ * Set current working directory
+ * on remote machine.
+ */
+void cd(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "remote-directory")) {
+		printf("usage: %s remote-directory\n", argv[0]);
+		code = -1;
+		return;
+	}
+	if (command("CWD %s", argv[1]) == ERROR && code == 500) {
+		if (verbose)
+			printf("CWD command not recognized, trying XCWD\n");
+		(void) command("XCWD %s", argv[1]);
+	}
+}
+
+/*
+ * Set current working directory
+ * on local machine.
+ */
+void lcd(argc, argv)
+	int argc;
+	char *argv[];
+{
+	char buf[MAXPATHLEN];
+
+	if (argc < 2)
+		argc++, argv[1] = home;
+	if (argc != 2) {
+		printf("usage: %s local-directory\n", argv[0]);
+		code = -1;
+		return;
+	}
+	if (!globulize(&argv[1])) {
+		code = -1;
+		return;
+	}
+	if (chdir(argv[1]) < 0) {
+		fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno));
+		code = -1;
+		return;
+	}
+	printf("Local directory now %s\n", getcwd(buf, sizeof buf));
+	code = 0;
+}
+
+/*
+ * Delete a single file.
+ */
+void delete_file(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "remote-file")) {
+		printf("usage: %s remote-file\n", argv[0]);
+		code = -1;
+		return;
+	}
+	(void) command("DELE %s", argv[1]);
+}
+
+/*
+ * Delete multiple files.
+ */
+void mdelete(argc, argv)
+	int argc;
+	char **argv;
+{
+	sig_t oldintr;
+	int ointer;
+	char *cp;
+
+	if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+		printf("usage: %s remote-files\n", argv[0]);
+		code = -1;
+		return;
+	}
+	mname = argv[0];
+	mflag = 1;
+	oldintr = signal(SIGINT, mabort);
+	(void) setjmp(jabort);
+	while ((cp = remglob(argv,0)) != NULL) {
+		if (*cp == '\0') {
+			mflag = 0;
+			continue;
+		}
+		if (mflag && confirm(argv[0], cp)) {
+			(void) command("DELE %s", cp);
+			if (!mflag && fromatty) {
+				ointer = interactive;
+				interactive = 1;
+				if (confirm("Continue with", "mdelete")) {
+					mflag++;
+				}
+				interactive = ointer;
+			}
+		}
+	}
+	(void) signal(SIGINT, oldintr);
+	mflag = 0;
+}
+
+/*
+ * Rename a remote file.
+ */
+void renamefile(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "from-name"))
+		goto usage;
+	if (argc < 3 && !another(&argc, &argv, "to-name")) {
+usage:
+		printf("%s from-name to-name\n", argv[0]);
+		code = -1;
+		return;
+	}
+	if (command("RNFR %s", argv[1]) == CONTINUE)
+		(void) command("RNTO %s", argv[2]);
+}
+
+/*
+ * Get a directory listing
+ * of remote files.
+ */
+void ls(argc, argv)
+	int argc;
+	char *argv[];
+{
+	char *cmd;
+
+	if (argc < 2)
+		argc++, argv[1] = NULL;
+	if (argc < 3)
+		argc++, argv[2] = "-";
+	if (argc > 3) {
+		printf("usage: %s remote-directory local-file\n", argv[0]);
+		code = -1;
+		return;
+	}
+	cmd = argv[0][0] == 'n' ? "NLST" : "LIST";
+	if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
+		code = -1;
+		return;
+	}
+	if (strcmp(argv[2], "-") && *argv[2] != '|')
+		if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) {
+			code = -1;
+			return;
+	}
+	recvrequest(cmd, argv[2], argv[1], "w", 0, 0);
+}
+
+/*
+ * Get a directory listing
+ * of multiple remote files.
+ */
+void mls(argc, argv)
+	int argc;
+	char **argv;
+{
+	sig_t oldintr;
+	int ointer, i;
+	char *volatile cmd, rmode[1], *dest;
+
+	if (argc < 2 && !another(&argc, &argv, "remote-files"))
+		goto usage;
+	if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+		printf("usage: %s remote-files local-file\n", argv[0]);
+		code = -1;
+		return;
+	}
+	dest = argv[argc - 1];
+	argv[argc - 1] = NULL;
+	if (strcmp(dest, "-") && *dest != '|')
+		if (!globulize(&dest) ||
+		    !confirm("output to local-file:", dest)) {
+			code = -1;
+			return;
+	}
+	cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
+	mname = argv[0];
+	mflag = 1;
+	oldintr = signal(SIGINT, mabort);
+	(void) setjmp(jabort);
+	for (i = 1; mflag && i < argc-1; ++i) {
+		*rmode = (i == 1) ? 'w' : 'a';
+		recvrequest(cmd, dest, argv[i], rmode, 0, 0);
+		if (!mflag && fromatty) {
+			ointer = interactive;
+			interactive = 1;
+			if (confirm("Continue with", argv[0])) {
+				mflag ++;
+			}
+			interactive = ointer;
+		}
+	}
+	(void) signal(SIGINT, oldintr);
+	mflag = 0;
+}
+
+/*
+ * Do a shell escape
+ */
+/*ARGSUSED*/
+#ifdef _WIN32
+void shell(int argc, char **argv)
+{
+	char *AppName;
+	char ShellCmd[MAX_PATH];
+	char CmdLine[MAX_PATH];
+	int i;
+	PROCESS_INFORMATION ProcessInformation;
+	BOOL Result;
+	STARTUPINFO StartupInfo;
+	int NumBytes;
+
+#ifdef _DEBUG
+	if (trace)
+	{
+		fprintf(stderr, "entered shell\n");
+		fprintf(stderr, "arguments = \n");
+		fprintf(stderr, "   argc = %d\n", argc);
+		for (i = 0; i < argc; i++)
+		{
+			fprintf(stderr, "    argv %d = %s\n", i, argv[i]);
+		}
+	}
+#endif /* _DEBUG */
+
+	NumBytes = GetEnvironmentVariable("COMSPEC", ShellCmd, sizeof(ShellCmd));
+
+	if (NumBytes == 0)
+	{
+		code = -1;
+		return;
+	}
+
+	AppName = ShellCmd;
+	_mbscpy(CmdLine, ShellCmd);
+
+	if (argc > 1)
+	{
+		_mbsncat(CmdLine, " /C", sizeof(CmdLine));
+	}
+
+	for (i = 1; i < argc; i++)
+	{
+		_mbsncat(CmdLine, " ", sizeof(CmdLine));
+		_mbsncat(CmdLine, argv[i], sizeof(CmdLine));
+	}
+	CmdLine[sizeof(CmdLine)-1] = 0;
+
+	memset(&StartupInfo, 0, sizeof(StartupInfo));
+	StartupInfo.cb = sizeof(StartupInfo);
+	Result = CreateProcess(AppName,              /* command name */
+			       CmdLine,              /* command line w/args */
+			       NULL,                 /* sec attr (app) */
+			       NULL,                 /* sec attr (thread) */
+			       FALSE,                /* inherit flags */
+			       0,                    /* creation flags */
+			       NULL,                 /* environment */
+			       NULL,                 /* working directory */
+			       &StartupInfo,         /* startup info struct */
+			       &ProcessInformation); /* process info struct */
+
+	if (Result)
+	{
+		WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
+		CloseHandle(ProcessInformation.hProcess);
+		code = 0;
+	}
+	else {
+		code = -1;
+	}
+}
+#else
+void shell(argc, argv)
+	int argc;
+	char **argv;
+{
+	int pid;
+	sig_t old1, old2;
+	char shellnam[40], *shellprog, *namep; 
+#ifdef WAIT_USES_INT
+	int w_status;
+#else
+	union wait w_status;
+#endif
+
+	old1 = signal (SIGINT, SIG_IGN);
+	old2 = signal (SIGQUIT, SIG_IGN);
+	if ((pid = fork()) == 0) {
+		for (pid = 3; pid < 20; pid++)
+			(void) close(pid);
+		(void) signal(SIGINT, SIG_DFL);
+		(void) signal(SIGQUIT, SIG_DFL);
+		shellprog = getenv("SHELL");
+		if (shellprog == NULL)
+			shellprog = "/bin/sh";
+		namep = strrchr(shellprog,'/');
+		if (namep == NULL)
+			namep = shellprog;
+		(void) strcpy(shellnam,"-");
+		(void) strncat(shellnam, ++namep, sizeof(shellnam) - 1 - strlen(shellnam));
+		shellnam[sizeof(shellnam) - 1] = '\0';
+		if (strcmp(namep, "sh") != 0)
+			shellnam[0] = '+';
+		if (debug) {
+			printf ("%s\n", shellprog);
+			(void) fflush (stdout);
+		}
+		if (argc > 1) {
+			execl(shellprog,shellnam,"-c",altarg,(char *)0);
+		}
+		else {
+			execl(shellprog,shellnam,(char *)0);
+		}
+		perror(shellprog);
+		code = -1;
+		exit(1);
+		}
+	if (pid > 0)
+		while (wait(&w_status) != pid)
+			;
+	(void) signal(SIGINT, old1);
+	(void) signal(SIGQUIT, old2);
+	if (pid == -1) {
+		perror("Try again later");
+		code = -1;
+	}
+	else {
+		code = 0;
+	}
+	return;
+}
+#endif
+
+/*
+ * Send new user information (re-login)
+ */
+void user(argc, argv)
+	int argc;
+	char **argv;
+{
+	char macct[80];
+	int n, aflag = 0;
+
+	if (argc < 2)
+		(void) another(&argc, &argv, "username");
+	if (argc < 2 || argc > 4) {
+		printf("usage: %s username [password] [account]\n", argv[0]);
+		code = -1;
+		return;
+	}
+	n = command("USER %s", argv[1]);
+	if (n == COMPLETE)
+		n = command("PASS dummy");
+	else if (n == CONTINUE) {
+#ifndef NOENCRYPTION
+		int oldclevel;
+#endif
+		if (argc < 3)
+			argv[2] = mygetpass("Password: "), argc++;
+#ifndef NOENCRYPTION
+		if ((oldclevel = clevel) == PROT_S) clevel = PROT_P;
+#endif
+		n = command("PASS %s", argv[2]);
+#ifndef NOENCRYPTION
+		/* level may have changed */
+		if (clevel == PROT_P) clevel = oldclevel;
+#endif
+	}
+	if (n == CONTINUE) {
+		if (argc < 4) {
+			printf("Account: "); (void) fflush(stdout);
+			(void) fgets(macct, sizeof(macct) - 1, stdin);
+			macct[strlen(macct) - 1] = '\0';
+			argv[3] = macct; argc++;
+		}
+		n = command("ACCT %s", argv[3]);
+		aflag++;
+	}
+	if (n != COMPLETE) {
+		fprintf(stdout, "Login failed.\n");
+		/* code = -1;*/
+		return;
+	}
+	if (!aflag && argc == 4) {
+		(void) command("ACCT %s", argv[3]);
+	}
+	return;
+}
+
+/*
+ * Print working directory.
+ */
+/*VARARGS*/
+void pwd()
+{
+	int oldverbose = verbose;
+
+	/*
+	 * If we aren't verbose, this doesn't do anything!
+	 */
+	verbose = 1;
+	if (command("PWD") == ERROR && code == 500) {
+		printf("PWD command not recognized, trying XPWD\n");
+		(void) command("XPWD");
+	}
+	verbose = oldverbose;
+}
+
+/*
+ * Make a directory.
+ */
+void makedir(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+		printf("usage: %s directory-name\n", argv[0]);
+		code = -1;
+		return;
+	}
+	if (command("MKD %s", argv[1]) == ERROR && code == 500) {
+		if (verbose)
+			printf("MKD command not recognized, trying XMKD\n");
+		(void) command("XMKD %s", argv[1]);
+	}
+}
+
+/*
+ * Remove a directory.
+ */
+void removedir(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+		printf("usage: %s directory-name\n", argv[0]);
+		code = -1;
+		return;
+	}
+	if (command("RMD %s", argv[1]) == ERROR && code == 500) {
+		if (verbose)
+			printf("RMD command not recognized, trying XRMD\n");
+		(void) command("XRMD %s", argv[1]);
+	}
+}
+
+/*
+ * Send a line, verbatim, to the remote machine.
+ */
+void quote(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "command line to send")) {
+		printf("usage: %s line-to-send\n", argv[0]);
+		code = -1;
+		return;
+	}
+	quote1("", argc, argv);
+}
+
+/*
+ * Send a SITE command to the remote machine.  The line
+ * is sent verbatim to the remote machine, except that the
+ * word "SITE" is added at the front.
+ */
+void site(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
+		printf("usage: %s line-to-send\n", argv[0]);
+		code = -1;
+		return;
+	}
+	quote1("SITE ", argc, argv);
+}
+
+/*
+ * Turn argv[1..argc) into a space-separated string, then prepend initial text.
+ * Send the result as a one-line command and get response.
+ */
+static void quote1(initial, argc, argv)
+	char *initial;
+	int argc;
+	char **argv;
+{
+	register int i, len;
+	char buf[FTP_BUFSIZ];		/* must be >= sizeof(line) */
+
+	(void) strncpy(buf, initial, sizeof(buf) - 1);
+	buf[sizeof(buf) - 1] = '\0';
+	if (argc > 1) {
+		len = strlen(buf);
+		len += strlen(strncpy(&buf[len], argv[1], sizeof(buf) - 1 - len));
+		for (i = 2; i < argc; i++) {
+			buf[len++] = ' ';
+			len += strlen(strncpy(&buf[len], argv[i], sizeof(buf) - 1 - len));
+		}
+	}
+	if (command(buf) == PRELIM) {
+		while (getreply(0) == PRELIM);
+	}
+}
+
+void do_chmod(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "mode"))
+		goto usage;
+	if (argc < 3 && !another(&argc, &argv, "file-name")) {
+usage:
+		printf("usage: %s mode file-name\n", argv[0]);
+		code = -1;
+		return;
+	}
+	(void) command("SITE CHMOD %s %s", argv[1], argv[2]);
+}
+
+void do_umask(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int oldverbose = verbose;
+
+	verbose = 1;
+	(void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
+	verbose = oldverbose;
+}
+
+void siteidle(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int oldverbose = verbose;
+
+	verbose = 1;
+	(void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
+	verbose = oldverbose;
+}
+
+/*
+ * Ask the other side for help.
+ */
+void rmthelp(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int oldverbose = verbose;
+
+	verbose = 1;
+	(void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
+	verbose = oldverbose;
+}
+
+/*
+ * Terminate session and exit.
+ */
+/*VARARGS*/
+void quit()
+{
+
+	if (connected)
+		disconnect();
+	pswitch(1);
+	if (connected) {
+		disconnect();
+	}
+	exit(0);
+}
+
+/*
+ * Terminate session, but don't exit.
+ */
+void disconnect()
+{
+	extern FILE *cout;
+	extern SOCKET data;
+
+	if (!connected)
+		return;
+	(void) command("QUIT");
+	if (cout) {
+		(void) FCLOSE_SOCKET(cout);	
+		cout = NULL;
+	}
+	connected = 0;
+	data = INVALID_SOCKET;
+	if (!proxy) {
+		macnum = 0;
+	}
+	auth_type = NULL;
+	dlevel = PROT_C;
+}
+
+static int confirm(cmd, file)
+	char *cmd, *file;
+{
+	char mline[FTP_BUFSIZ];
+
+	if (!interactive)
+		return (1);
+	printf("%s %s? ", cmd, file);
+	(void) fflush(stdout);
+	if (fgets(mline, sizeof mline, stdin) == NULL)
+		return (0);
+	return (*mline != 'n' && *mline != 'N');
+}
+
+void fatal(msg)
+	char *msg;
+{
+
+	fprintf(stderr, "ftp: %s\n", msg);
+	exit(1);
+}
+
+/*
+ * Glob a local file name specification with
+ * the expectation of a single return value.
+ * Can't control multiple values being expanded
+ * from the expression, we return only the first.
+ */
+static int globulize(cpp)
+	char **cpp;
+{
+	char **globbed;
+	char **globbed1;
+
+	if (!doglob)
+		return (1);
+	globbed = ftpglob(*cpp);
+	if (globerr != NULL) {
+		printf("%s: %s\n", *cpp, globerr);
+		if (globbed) {
+			blkfree(globbed);
+			free((char *)globbed);
+		}
+		return (0);
+	}
+	if (globbed) {
+		globbed1 = globbed;
+		*cpp = *globbed1++;
+		/* don't waste too much memory */
+		if (*globbed) {
+			blkfree(globbed1);
+			free((char *)globbed);
+		}
+	}
+	return (1);
+}
+
+void account(argc,argv)
+	int argc;
+	char **argv;
+{
+	char macct[50], *ap;
+
+	if (argc > 1) {
+		++argv;
+		--argc;
+		(void) strncpy(macct,*argv,49);
+		macct[49] = '\0';
+		while (argc > 1) {
+			--argc;
+			++argv;
+			(void) strncat(macct,*argv, 49-strlen(macct));
+		}
+		ap = macct;
+	}
+	else {
+		ap = mygetpass("Account:");
+	}
+	(void) command("ACCT %s", ap);
+}
+
+jmp_buf abortprox;
+
+static sigtype
+proxabort(int sig)
+{
+	extern int proxy;
+
+	if (!proxy) {
+		pswitch(1);
+	}
+	if (connected) {
+		proxflag = 1;
+	}
+	else {
+		proxflag = 0;
+	}
+	pswitch(0);
+	longjmp(abortprox,1);
+}
+
+void doproxy(argc,argv)
+	int argc;
+	char *argv[];
+{
+	register struct cmd *c;
+	struct cmd *getcmd();
+	sig_t oldintr;
+
+	if (argc < 2 && !another(&argc, &argv, "command")) {
+		printf("usage: %s command\n", argv[0]);
+		code = -1;
+		return;
+	}
+	c = getcmd(argv[1]);
+	if (c == (struct cmd *) -1) {
+		printf("?Ambiguous command\n");
+		(void) fflush(stdout);
+		code = -1;
+		return;
+	}
+	if (c == 0) {
+		printf("?Invalid command\n");
+		(void) fflush(stdout);
+		code = -1;
+		return;
+	}
+	if (!c->c_proxy) {
+		printf("?Invalid proxy command\n");
+		(void) fflush(stdout);
+		code = -1;
+		return;
+	}
+	if (setjmp(abortprox)) {
+		code = -1;
+		return;
+	}
+	oldintr = signal(SIGINT, proxabort);
+	pswitch(1);
+	if (c->c_conn && !connected) {
+		printf("Not connected\n");
+		(void) fflush(stdout);
+		pswitch(0);
+		(void) signal(SIGINT, oldintr);
+		code = -1;
+		return;
+	}
+	(*c->c_handler)(argc-1, argv+1);
+	if (connected) {
+		proxflag = 1;
+	}
+	else {
+		proxflag = 0;
+	}
+	pswitch(0);
+	(void) signal(SIGINT, oldintr);
+}
+
+void setcase()
+{
+	mcase = !mcase;
+	printf("Case mapping %s.\n", onoff(mcase));
+	code = mcase;
+}
+
+void setcr()
+{
+	crflag = !crflag;
+	printf("Carriage Return stripping %s.\n", onoff(crflag));
+	code = crflag;
+}
+
+void setntrans(argc,argv)
+	int argc;
+	char *argv[];
+{
+	if (argc == 1) {
+		ntflag = 0;
+		printf("Ntrans off.\n");
+		code = ntflag;
+		return;
+	}
+	ntflag++;
+	code = ntflag;
+	(void) strncpy(ntin, argv[1], 16);
+	ntin[16] = '\0';
+	if (argc == 2) {
+		ntout[0] = '\0';
+		return;
+	}
+	(void) strncpy(ntout, argv[2], 16);
+	ntout[16] = '\0';
+}
+
+static char *
+dotrans(name)
+	char *name;
+{
+	static char new[MAXPATHLEN];
+	char *cp1, *cp2 = new;
+	register int i, ostop, found;
+
+	for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++);
+	for (cp1 = name; *cp1; cp1++) {
+		found = 0;
+		for (i = 0; *(ntin + i) && i < 16; i++) {
+			if (*cp1 == *(ntin + i)) {
+				found++;
+				if (i < ostop) {
+					*cp2++ = *(ntout + i);
+				}
+				break;
+			}
+		}
+		if (!found) {
+			*cp2++ = *cp1;
+		}
+	}
+	*cp2 = '\0';
+	return(new);
+}
+
+void setnmap(argc, argv)
+	int argc;
+	char *argv[];
+{
+	char *cp;
+
+	if (argc == 1) {
+		mapflag = 0;
+		printf("Nmap off.\n");
+		code = mapflag;
+		return;
+	}
+	if (argc < 3 && !another(&argc, &argv, "mapout")) {
+		printf("Usage: %s [mapin mapout]\n",argv[0]);
+		code = -1;
+		return;
+	}
+	mapflag = 1;
+	code = 1;
+	cp = strchr(altarg, ' ');
+	if (proxy) {
+		while(*++cp == ' ');
+		altarg = cp;
+		cp = strchr(altarg, ' ');
+	}
+	*cp = '\0';
+	(void) strncpy(mapin, altarg, MAXPATHLEN - 1);
+	while (*++cp == ' ');
+	(void) strncpy(mapout, cp, MAXPATHLEN - 1);
+}
+
+static char *
+domap(name)
+	char *name;
+{
+	static char new[MAXPATHLEN];
+	register char *cp1 = name, *cp2 = mapin;
+	char *tp[9], *te[9];
+	int i, toks[9], toknum = 0, match = 1;
+
+	for (i=0; i < 9; ++i) {
+		toks[i] = 0;
+	}
+	while (match && *cp1 && *cp2) {
+		switch (*cp2) {
+			case '\\':
+				if (*++cp2 != *cp1) {
+					match = 0;
+				}
+				break;
+			case '$':
+				if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
+					if (*cp1 != *(++cp2+1)) {
+						toks[toknum = *cp2 - '1']++;
+						tp[toknum] = cp1;
+						while (*++cp1 && *(cp2+1)
+							!= *cp1);
+						te[toknum] = cp1;
+					}
+					cp2++;
+					break;
+				}
+				/* FALLTHROUGH */
+			default:
+				if (*cp2 != *cp1) {
+					match = 0;
+				}
+				break;
+		}
+		if (match && *cp1) {
+			cp1++;
+		}
+		if (match && *cp2) {
+			cp2++;
+		}
+	}
+	if (!match && *cp1) /* last token mismatch */
+	{
+		toks[toknum] = 0;
+	}
+	cp1 = new;
+	*cp1 = '\0';
+	cp2 = mapout;
+	while (*cp2) {
+		match = 0;
+		switch (*cp2) {
+			case '\\':
+				if (*(cp2 + 1)) {
+					*cp1++ = *++cp2;
+				}
+				break;
+			case '[':
+LOOP:
+				if (*++cp2 == '$' && isdigit((int) *(cp2+1))) { 
+					if (*++cp2 == '0') {
+						char *cp3 = name;
+
+						while (*cp3) {
+							*cp1++ = *cp3++;
+						}
+						match = 1;
+					}
+					else if (toks[toknum = *cp2 - '1']) {
+						char *cp3 = tp[toknum];
+
+						while (cp3 != te[toknum]) {
+							*cp1++ = *cp3++;
+						}
+						match = 1;
+					}
+				}
+				else {
+					while (*cp2 && *cp2 != ',' && 
+					    *cp2 != ']') {
+						if (*cp2 == '\\') {
+							cp2++;
+						}
+						else if (*cp2 == '$' &&
+   						        isdigit((int) *(cp2+1))) {
+							if (*++cp2 == '0') {
+							   char *cp3 = name;
+
+							   while (*cp3) {
+								*cp1++ = *cp3++;
+							   }
+							}
+							else if (toks[toknum =
+							    *cp2 - '1']) {
+							   char *cp3=tp[toknum];
+
+							   while (cp3 !=
+								  te[toknum]) {
+								*cp1++ = *cp3++;
+							   }
+							}
+						}
+						else if (*cp2) {
+							*cp1++ = *cp2++;
+						}
+					}
+					if (!*cp2) {
+						printf("nmap: unbalanced brackets\n");
+						return(name);
+					}
+					match = 1;
+					cp2--;
+				}
+				if (match) {
+					while (*++cp2 && *cp2 != ']') {
+					      if (*cp2 == '\\' && *(cp2 + 1)) {
+							cp2++;
+					      }
+					}
+					if (!*cp2) {
+						printf("nmap: unbalanced brackets\n");
+						return(name);
+					}
+					break;
+				}
+				switch (*++cp2) {
+					case ',':
+						goto LOOP;
+					case ']':
+						break;
+					default:
+						cp2--;
+						goto LOOP;
+				}
+				break;
+			case '$':
+				if (isdigit((int) *(cp2 + 1))) {
+					if (*++cp2 == '0') {
+						char *cp3 = name;
+
+						while (*cp3) {
+							*cp1++ = *cp3++;
+						}
+					}
+					else if (toks[toknum = *cp2 - '1']) {
+						char *cp3 = tp[toknum];
+
+						while (cp3 != te[toknum]) {
+							*cp1++ = *cp3++;
+						}
+					}
+					break;
+				}
+				/* intentional drop through */
+			default:
+				*cp1++ = *cp2;
+				break;
+		}
+		cp2++;
+	}
+	*cp1 = '\0';
+	if (!*new) {
+		return(name);
+	}
+	return(new);
+}
+
+void setsunique()
+{
+	sunique = !sunique;
+	printf("Store unique %s.\n", onoff(sunique));
+	code = sunique;
+}
+
+void setrunique()
+{
+	runique = !runique;
+	printf("Receive unique %s.\n", onoff(runique));
+	code = runique;
+}
+
+/* change directory to perent directory */
+void cdup()
+{
+	if (command("CDUP") == ERROR && code == 500) {
+		if (verbose)
+			printf("CDUP command not recognized, trying XCUP\n");
+		(void) command("XCUP");
+	}
+}
+
+/* restart transfer at specific point */
+void restart(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern long atol();
+	if (argc != 2)
+		printf("restart: offset not specified\n");
+	else {
+		restart_point = atol(argv[1]);
+		printf("restarting at %ld. %s\n", (long) restart_point,
+		    "execute get, put or append to initiate transfer");
+	}
+}
+
+/* show remote system type */
+void syst()
+{
+	(void) command("SYST");
+}
+
+void macdef(argc, argv)
+	int argc;
+	char *argv[];
+{
+	char *tmp;
+	int c;
+
+	if (macnum == 16) {
+		printf("Limit of 16 macros have already been defined\n");
+		code = -1;
+		return;
+	}
+	if (argc < 2 && !another(&argc, &argv, "macro name")) {
+		printf("Usage: %s macro_name\n",argv[0]);
+		code = -1;
+		return;
+	}
+	if (interactive) {
+		printf("Enter macro line by line, terminating it with a null line\n");
+	}
+	(void) strncpy(macros[macnum].mac_name, argv[1], 8);
+	if (macnum == 0) {
+		macros[macnum].mac_start = macbuf;
+	}
+	else {
+		macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
+	}
+	tmp = macros[macnum].mac_start;
+	while (tmp != macbuf+4096) {
+		if ((c = getchar()) == EOF) {
+			printf("macdef:end of file encountered\n");
+			code = -1;
+			return;
+		}
+		if ((*tmp = c) == '\n') {
+			if (tmp == macros[macnum].mac_start) {
+				macros[macnum++].mac_end = tmp;
+				code = 0;
+				return;
+			}
+			if (*(tmp-1) == '\0') {
+				macros[macnum++].mac_end = tmp - 1;
+				code = 0;
+				return;
+			}
+			*tmp = '\0';
+		}
+		tmp++;
+	}
+	while (1) {
+		while ((c = getchar()) != '\n' && c != EOF)
+			/* LOOP */;
+		if (c == EOF || getchar() == '\n') {
+			printf("Macro not defined - 4k buffer exceeded\n");
+			code = -1;
+			return;
+		}
+	}
+}
+
+/*
+ * get size of file on remote machine
+ */
+void sizecmd(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	if (argc < 2 && !another(&argc, &argv, "filename")) {
+		printf("usage: %s filename\n", argv[0]);
+		code = -1;
+		return;
+	}
+	(void) command("SIZE %s", argv[1]);
+}
+
+/*
+ * get last modification time of file on remote machine
+ */
+void modtime(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int overbose;
+
+	if (argc < 2 && !another(&argc, &argv, "filename")) {
+		printf("usage: %s filename\n", argv[0]);
+		code = -1;
+		return;
+	}
+	overbose = verbose;
+	if (debug == 0)
+		verbose = -1;
+	if (command("MDTM %s", argv[1]) == COMPLETE) {
+		int yy, mo, day, hour, min, sec;
+		sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
+			&day, &hour, &min, &sec);
+		/* might want to print this in local time */
+		printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
+			mo, day, yy, hour, min, sec);
+	} else
+		printf("%s\n", reply_string);
+	verbose = overbose;
+}
+
+/*
+ * show status on remote machine
+ */
+void rmtstatus(argc, argv)
+	int argc;
+	char *argv[];
+{
+	(void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
+}
+
+/*
+ * get file if modtime is more recent than current file
+ */
+void newer(argc, argv)
+	int argc;
+	char *argv[];
+{
+	if (getit(argc, argv, -1, "w"))
+		printf("Local file \"%s\" is newer than remote file \"%s\"\n",
+			argv[1], argv[2]);
+}
+
+#ifndef NO_PASSIVE_MODE
+/*
+ * Start up passive mode interaction
+ */
+
+/*VARARGS*/
+void setpassive()
+{
+
+	passivemode = !passivemode;
+	printf("Passive mode %s.\n", onoff(passivemode));
+	code = passivemode;
+}
+#endif
diff --git a/krb5-1-6/src/appl/gssftp/ftp/cmdtab.c b/krb5-1-6/src/appl/gssftp/ftp/cmdtab.c
new file mode 100644
index 000000000..cfa11e371
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/cmdtab.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmdtab.c	5.10 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+#include <stdio.h>
+#include "ftp_var.h"
+
+/*
+ * User FTP -- Command Tables.
+ */
+
+char	accounthelp[] =	"send account command to remote server";
+char	appendhelp[] =	"append to a file";
+char	asciihelp[] =	"set ascii transfer type";
+char	beephelp[] =	"beep when command completed";
+char	binaryhelp[] =	"set binary transfer type";
+char	casehelp[] =	"toggle mget upper/lower case id mapping";
+char	ccchelp[] =	"set clear protection level for commands";
+char	cdhelp[] =	"change remote working directory";
+char	cduphelp[] = 	"change remote working directory to parent directory";
+char	chmodhelp[] =	"change file permissions of remote file";
+char	clearhelp[] =	"set clear protection level for file transfer";
+char	connecthelp[] =	"connect to remote ftp";
+char	crhelp[] =	"toggle carriage return stripping on ascii gets";
+char	deletehelp[] =	"delete remote file";
+char	debughelp[] =	"toggle/set debugging mode";
+char	dirhelp[] =	"list contents of remote directory";
+char	disconhelp[] =	"terminate ftp session";
+char	domachelp[] = 	"execute macro";
+char	formhelp[] =	"set file transfer format";
+char	globhelp[] =	"toggle metacharacter expansion of local file names";
+char	hashhelp[] =	"toggle printing `#' for each buffer transferred";
+char	helphelp[] =	"print local help information";
+char	idlehelp[] =	"get (set) idle timer on remote side";
+char	lcdhelp[] =	"change local working directory";
+char	levelhelp[] =	"set protection level for file transfer";
+char	clevelhelp[] =	"set protection level for commands";
+char	lshelp[] =	"list contents of remote directory";
+char	macdefhelp[] =  "define a macro";
+char	mdeletehelp[] =	"delete multiple files";
+char	mdirhelp[] =	"list contents of multiple remote directories";
+char	mgethelp[] =	"get multiple files";
+char	mkdirhelp[] =	"make directory on the remote machine";
+char	mlshelp[] =	"list contents of multiple remote directories";
+char	modtimehelp[] = "show last modification time of remote file";
+char	modehelp[] =	"set file transfer mode";
+char	mputhelp[] =	"send multiple files";
+char	newerhelp[] =	"get file if remote file is newer than local file ";
+char	nlisthelp[] =	"nlist contents of remote directory";
+char	nmaphelp[] =	"set templates for default file name mapping";
+char	ntranshelp[] =	"set translation table for default file name mapping";
+char	porthelp[] =	"toggle use of PORT cmd for each data connection";
+#ifndef NOENCRYPTION
+char	privatehelp[] =	"set private protection level for file transfer";
+#endif
+char	prompthelp[] =	"force interactive prompting on multiple commands";
+char	proxyhelp[] =	"issue command on alternate connection";
+char	pwdhelp[] =	"print working directory on remote machine";
+char	quithelp[] =	"terminate ftp session and exit";
+char	quotehelp[] =	"send arbitrary ftp command";
+char	receivehelp[] =	"receive file";
+char	regethelp[] =	"get file restarting at end of local file";
+char	remotehelp[] =	"get help from remote server";
+char	renamehelp[] =	"rename file";
+char	restarthelp[]=	"restart file transfer at bytecount";
+char	rmdirhelp[] =	"remove directory on the remote machine";
+char	rmtstatushelp[]="show status of remote machine";
+char	runiquehelp[] = "toggle store unique for local files";
+char	resethelp[] =	"clear queued command replies";
+char	safehelp[] =	"set safe protection level for file transfer";
+char	sendhelp[] =	"send one file";
+char	sitehelp[] =	"send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information";
+char	shellhelp[] =	"escape to the shell";
+char	sizecmdhelp[] = "show size of remote file";
+char	statushelp[] =	"show current status";
+char	structhelp[] =	"set file transfer structure";
+char	suniquehelp[] = "toggle store unique on remote machine";
+char	systemhelp[] =  "show remote system type";
+char	tenexhelp[] =	"set tenex file transfer type";
+char	tracehelp[] =	"toggle packet tracing";
+char	typehelp[] =	"set file transfer type";
+char	umaskhelp[] =	"get (set) umask on remote side";
+char	userhelp[] =	"send new user information";
+char	verbosehelp[] =	"toggle verbose mode";
+#ifndef NO_PASSIVE_MODE
+char	setpassivehelp[] = "toggle passive transfer mode";
+#endif
+
+struct cmd cmdtab[] = {
+	{ "!",		shellhelp,	0,	0,	0,	shell },
+	{ "$",		domachelp,	1,	0,	0,	domacro },
+	{ "account",	accounthelp,	0,	1,	1,	account},
+	{ "append",	appendhelp,	1,	1,	1,	put },
+	{ "ascii",	asciihelp,	0,	1,	1,	setascii },
+	{ "bell",	beephelp,	0,	0,	0,	setbell },
+	{ "binary",	binaryhelp,	0,	1,	1,	setbinary },
+	{ "bye",	quithelp,	0,	0,	0,	quit },
+	{ "case",	casehelp,	0,	0,	1,	setcase },
+	{ "ccc",	ccchelp,	0,	1,	1,	ccc },
+	{ "cd",		cdhelp,		0,	1,	1,	cd },
+	{ "cdup",	cduphelp,	0,	1,	1,	cdup },
+	{ "chmod",	chmodhelp,	0,	1,	1,	do_chmod },
+	{ "clear",	clearhelp,	0,	1,	1,	setclear },
+	{ "close",	disconhelp,	0,	1,	1,	disconnect },
+	{ "cprotect",	clevelhelp,	0,	1,	1,	setclevel },
+	{ "cr",		crhelp,		0,	0,	0,	setcr },
+	{ "delete",	deletehelp,	0,	1,	1,	delete_file },
+	{ "debug",	debughelp,	0,	0,	0,	setdebug },
+	{ "dir",	dirhelp,	1,	1,	1,	ls },
+	{ "disconnect",	disconhelp,	0,	1,	1,	disconnect },
+	{ "form",	formhelp,	0,	1,	1,	setform },
+	{ "get",	receivehelp,	1,	1,	1,	get },
+	{ "glob",	globhelp,	0,	0,	0,	setglob },
+	{ "hash",	hashhelp,	0,	0,	0,	sethash },
+	{ "help",	helphelp,	0,	0,	1,	help },
+	{ "idle",	idlehelp,	0,	1,	1,	siteidle },
+	{ "image",	binaryhelp,	0,	1,	1,	setbinary },
+	{ "lcd",	lcdhelp,	0,	0,	0,	lcd },
+	{ "ls",		lshelp,		1,	1,	1,	ls },
+	{ "macdef",	macdefhelp,	0,	0,	0,	macdef },
+	{ "mdelete",	mdeletehelp,	1,	1,	1,	mdelete },
+	{ "mdir",	mdirhelp,	1,	1,	1,	mls },
+	{ "mget",	mgethelp,	1,	1,	1,	mget },
+	{ "mkdir",	mkdirhelp,	0,	1,	1,	makedir },
+	{ "mls",	mlshelp,	1,	1,	1,	mls },
+	{ "mode",	modehelp,	0,	1,	1,	set_mode },
+	{ "modtime",	modtimehelp,	0,	1,	1,	modtime },
+	{ "mput",	mputhelp,	1,	1,	1,	mput },
+	{ "newer",	newerhelp,	1,	1,	1,	newer },
+	{ "nmap",	nmaphelp,	0,	0,	1,	setnmap },
+	{ "nlist",	nlisthelp,	1,	1,	1,	ls },
+	{ "ntrans",	ntranshelp,	0,	0,	1,	setntrans },
+	{ "open",	connecthelp,	0,	0,	1,	setpeer },
+#ifndef NO_PASSIVE_MODE
+	{ "passive",	setpassivehelp,	0,	0,	0,	setpassive },
+#endif
+#ifndef NOENCRYPTION
+	{ "private",	privatehelp,	0,	1,	1,	setprivate },
+#endif
+	{ "prompt",	prompthelp,	0,	0,	0,	setprompt },
+	{ "protect",	levelhelp,	0,	1,	1,	setdlevel },
+	{ "proxy",	proxyhelp,	0,	0,	1,	doproxy },
+	{ "sendport",	porthelp,	0,	0,	0,	setport },
+	{ "put",	sendhelp,	1,	1,	1,	put },
+	{ "pwd",	pwdhelp,	0,	1,	1,	pwd },
+	{ "quit",	quithelp,	0,	0,	0,	quit },
+	{ "quote",	quotehelp,	1,	1,	1,	quote },
+	{ "recv",	receivehelp,	1,	1,	1,	get },
+	{ "reget",	regethelp,	1,	1,	1,	reget },
+	{ "rstatus",	rmtstatushelp,	0,	1,	1,	rmtstatus },
+	{ "rhelp",	remotehelp,	0,	1,	1,	rmthelp },
+	{ "rename",	renamehelp,	0,	1,	1,	renamefile },
+	{ "reset",	resethelp,	0,	1,	1,	reset },
+	{ "restart",	restarthelp,	1,	1,	1,	restart },
+	{ "rmdir",	rmdirhelp,	0,	1,	1,	removedir },
+	{ "runique",	runiquehelp,	0,	0,	1,	setrunique },
+	{ "safe",	safehelp,	0,	1,	1,	setsafe },
+	{ "send",	sendhelp,	1,	1,	1,	put },
+	{ "site",	sitehelp,	0,	1,	1,	site },
+	{ "size",	sizecmdhelp,	1,	1,	1,	sizecmd },
+	{ "status",	statushelp,	0,	0,	1,	status },
+	{ "struct",	structhelp,	0,	1,	1,	setstruct },
+	{ "system",	systemhelp,	0,	1,	1,	syst },
+	{ "sunique",	suniquehelp,	0,	0,	1,	setsunique },
+	{ "tenex",	tenexhelp,	0,	1,	1,	settenex },
+	{ "trace",	tracehelp,	0,	0,	0,	settrace },
+	{ "type",	typehelp,	0,	1,	1,	settype },
+	{ "user",	userhelp,	0,	1,	1,	user },
+	{ "umask",	umaskhelp,	0,	1,	1,	do_umask },
+	{ "verbose",	verbosehelp,	0,	0,	0,	setverbose },
+	{ "?",		helphelp,	0,	0,	1,	help },
+	{ 0 },
+};
+
+int	NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1;
+
diff --git a/krb5-1-6/src/appl/gssftp/ftp/domacro.c b/krb5-1-6/src/appl/gssftp/ftp/domacro.c
new file mode 100644
index 000000000..50684a72b
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/domacro.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)domacro.c	1.8 (Berkeley) 9/28/90";
+#endif /* not lint */
+
+#include <stdio.h>
+
+#include "ftp_var.h"
+
+#include <signal.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+
+void domacro(argc, argv)
+	int argc;
+	char *argv[];
+{
+	register int i, j;
+	register char *cp1, *cp2;
+	int count = 2, loopflg = 0;
+	char line2[200];
+	extern char **glob();
+	struct cmd *getcmd(), *c;
+
+	if (argc < 2 && !another(&argc, &argv, "macro name")) {
+		printf("Usage: %s macro_name.\n", argv[0]);
+		code = -1;
+		return;
+	}
+	for (i = 0; i < macnum; ++i) {
+		if (!strncmp(argv[1], macros[i].mac_name, 9)) {
+			break;
+		}
+	}
+	if (i == macnum) {
+		printf("'%s' macro not found.\n", argv[1]);
+		code = -1;
+		return;
+	}
+	(void) strncpy(line2, line, sizeof(line2) - 1);
+	line2[sizeof(line2) - 1] = '\0';
+TOP:
+	cp1 = macros[i].mac_start;
+	while (cp1 != macros[i].mac_end) {
+		while (isspace((int) *cp1)) {
+			cp1++;
+		}
+		cp2 = line;
+		while (*cp1 != '\0') {
+		      switch(*cp1) {
+		   	    case '\\':
+				 *cp2++ = *++cp1;
+				 break;
+			    case '$':
+				 if (isdigit((int) *(cp1+1))) {
+				    j = 0;
+				    while (isdigit((int) (*++cp1))) {
+					  j = 10*j +  *cp1 - '0';
+				    }
+				    cp1--;
+				    if (argc - 2 >= j) {
+                                        if(cp2 + strlen(argv[j+1]) - line < sizeof(line))
+					(void) strncpy(cp2, argv[j+1],
+						       sizeof(line) - 1 -
+						       (cp2 - line));
+					line[sizeof(line) - 1] = '\0';
+					cp2 += strlen(argv[j+1]);
+				    }
+				    break;
+				 }
+				 if (*(cp1+1) == 'i') {
+					loopflg = 1;
+					cp1++;
+					if (count < argc) {
+                                           if(cp2 + strlen(argv[count]) - line < sizeof(line))
+					   (void) strncpy(cp2, argv[count],
+							  sizeof(line) - 1 -
+							  (cp2 - line));
+					   line[sizeof(line) - 1] = '\0';
+					   cp2 += strlen(argv[count]);
+					}
+					break;
+				}
+				/* intentional drop through */
+			    default:
+				*cp2++ = *cp1;
+				break;
+		      }
+		      if (*cp1 != '\0') {
+			 cp1++;
+		      }
+		}
+		*cp2 = '\0';
+		makeargv();
+		c = getcmd(margv[0]);
+		if (c == (struct cmd *)-1) {
+			printf("?Ambiguous command\n");
+			code = -1;
+		}
+		else if (c == 0) {
+			printf("?Invalid command\n");
+			code = -1;
+		}
+		else if (c->c_conn && !connected) {
+			printf("Not connected.\n");
+			code = -1;
+		}
+		else {
+			if (verbose) {
+				printf("%s\n",line);
+			}
+			(*c->c_handler)(margc, margv);
+			if (bell && c->c_bell) {
+				(void) putchar('\007');
+			}
+			(void) strncpy(line, line2, sizeof(line) - 1);
+			line[sizeof(line) - 1] = '\0';
+			makeargv();
+			argc = margc;
+			argv = margv;
+		}
+		if (cp1 != macros[i].mac_end) {
+			cp1++;
+		}
+	}
+	if (loopflg && ++count < argc) {
+		goto TOP;
+	}
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftp/ftp.M b/krb5-1-6/src/appl/gssftp/ftp/ftp.M
new file mode 100644
index 000000000..9c890cfb1
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/ftp.M
@@ -0,0 +1,1131 @@
+.\" Copyright (c) 1985, 1989, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)ftp.1	6.18 (Berkeley) 7/30/91
+.\" "
+.TH FTP 1
+.SH NAME
+ftp \- ARPANET file transfer program
+.SH SYNOPSIS
+.B ftp
+[\fB\-v\fP] [\fB\-d\fP] [\fB\-i\fP] [\fB\-n\fP] [\fB\-g\fP] [\fB\-k\fP
+\fIrealm\fP] [\fB\-f\fP] [\fB\-x\fP] [\fB\-u\fP] [\fB\-t\fP] [\fIhost\fP]
+.SH DESCRIPTION
+.B FTP
+is the user interface to the
+.SM ARPANET
+standard File Transfer Protocol.  The program allows a user to transfer
+files to and from a remote network site.
+.SH OPTIONS
+Options may be specified at the command line, or to the command
+interpreter.
+.TP
+.B \-v
+Verbose option forces
+.B ftp
+to show all responses from the remote server, as well as report on data
+transfer statistics.
+.TP
+.B \-n
+Restrains
+.B ftp
+from attempting ``auto-login'' upon initial connection.  If auto-login
+is enabled,
+.B ftp
+will check the
+.I .netrc
+(see below) file in the user's home directory for an entry describing an
+account on the remote machine.  If no entry exists,
+.B ftp
+will prompt for the remote machine login name (default is the user
+identity on the local machine), and, if necessary, prompt for a password
+and an account with which to login.
+.TP
+.B \-u
+Restrains
+.B ftp
+from attempting ``auto-authentication'' upon initial connection.  If
+auto-authentication is enabled,
+.B ftp
+attempts to authenticate to the
+.SM FTP
+server by sending the
+.SM AUTH
+command, using whichever authentication types are locally supported.
+Once an authentication type is accepted, an authentication protocol
+will proceed by issuing
+.SM ADAT
+commands.  This option also disables auto-login.
+.TP
+.B \-i
+Turns off interactive prompting during multiple file transfers.
+.TP
+.B \-d
+Enables debugging.
+.TP
+.B \-g
+Disables file name globbing.
+.TP
+\fB\-k\fP \fIrealm\fP
+When using Kerberos v4 authentication, gets tickets in
+.IR realm .
+.TP
+.B \-f
+Causes credentials to be forwarded to the remote host.
+.TP
+.B \-x
+Causes the client to attempt to negotiate encryption (data and command
+protection levels ``private'') immediately after successfully
+authenticating.
+.TP
+.B \-t
+Enables packet tracing.
+.SH COMMANDS
+The client host with which
+.B ftp
+is to communicate may be specified on the command line.  If this is
+done,
+.B ftp
+will immediately attempt to establish a connection to an
+.SM FTP
+server on that host; otherwise,
+.B ftp
+will enter its command interpreter and await instructions from the user.
+When
+.B ftp
+is awaiting commands from the user the prompt
+``ftp>''
+is provided to the user.  The following commands are recognized by
+.BR ftp :
+.TP
+\fB\&!\fP [\fIcommand\fP] [\fIargs\fP]]
+Invoke an interactive shell on the local machine.  If there are
+arguments, the first is taken to be a command to execute directly, with
+the rest of the arguments as its arguments.
+.TP
+\fB\&$\fP \fImacro-name\fP [\fIargs\fP]
+Execute the macro
+.I macro-name
+that was defined with the
+.B macdef
+command.  Arguments are passed to the macro unglobbed.
+.TP
+\fBaccount\fP [\fIpasswd\fP]
+Supply a supplemental password required by a remote system for access to
+resources once a login has been successfully completed.  If no argument
+is included, the user will be prompted for an account password in a
+non-echoing input mode.
+.TP
+\fBappend\fP \fIlocal-file\fP [\fIremote-file\fP]
+Append a local file to a file on the remote machine.  If
+.I remote-file
+is left unspecified, the local file name is used in naming the remote
+file after being altered by any
+.B ntrans
+or
+.B nmap
+setting.  File transfer uses the current settings for
+.BR type ,
+.BR format ,
+.BR mode ,
+and
+.BR structure .
+.TP
+.B ascii
+Set the file transfer
+.B type
+to network
+.SM ASCII .
+This is the default type.
+.TP
+.B bell
+Arrange that a bell be sounded after each file transfer command is
+completed.
+.TP
+.B binary
+Set the file transfer
+.B type
+to support binary file transfer.
+.TP
+.B bye
+Terminate the
+.SM FTP
+session with the remote server and exit
+.BR ftp .
+An end of file will also terminate the session and exit.
+.TP
+.B case
+Toggle remote computer file name case mapping during
+.B mget
+commands.  When
+.B case
+is on (default is off), remote computer file names with all letters in
+upper case are written in the local directory with the letters mapped to
+lower case.
+.TP
+.B ccc
+Turn off integrity protection on the command channel.  This command
+must be sent integrity protected, and must be proceeded by a successful
+.SM ADAT
+command.  Since turning off integrity protection potentially
+allows an attacker to insert commands onto the command channel, some
+.SM FTP
+servers may refuse to honor this command.
+.TP
+\fBcd\fP \fIremote-directory\fP
+Change the working directory on the remote machine to
+.IR remote-directory .
+.TP
+.B cdup
+Change the remote machine working directory to the parent of the current
+remote machine working directory.
+.TP
+\fBchmod\fP \fImode\fP \fIfile-name\fP
+Change the permission modes of the file
+.I file-name
+on the remote system to
+.IR mode .
+.TP
+.B clear
+Set the protection level on data transfers to ``clear''.  If no
+.SM ADAT
+command succeeded, then this is the default protection level.
+.TP
+.B close
+Terminate the
+.SM FTP
+session with the remote server, and return to the command interpreter.
+Any defined macros are erased.
+.TP
+\fBcprotect\fP [\fIprotection-level\fP]
+Set the protection level on commands to
+.IR protection-level .
+The valid protection levels are ``clear'' for unprotected commands,
+``safe'' for commands integrity protected by
+cryptographic checksum, and ``private'' for commands
+confidentiality and integrity protected by encryption.  If an
+.SM ADAT
+command succeeded, then the default command protection level is
+``safe'', otherwise the only possible level is ``clear''.  If no
+level is specified, the current level is printed.
+.B cprotect clear
+is equivalent to the
+.B ccc
+command.
+.TP
+.B cr
+Toggle carriage return stripping during ascii type file retrieval.
+Records are denoted by a carriage return/linefeed sequence during ascii
+type file transfer.  When
+.B cr
+is on (the default), carriage returns are stripped from this sequence to
+conform with the
+.SM UNIX
+single linefeed record delimiter.  Records on non-UNIX remote systems
+may contain single linefeeds; when an ascii type transfer is made, these
+linefeeds may be distinguished from a record delimiter only when
+.B cr
+is off.
+.TP
+\fBdelete\fP \fIremote-file\fP
+Delete the file
+.I remote-file
+on the remote machine.
+.TP
+\fBdebug\fP [\fIdebug-value\fP]
+Toggle debugging mode.  If an optional
+.I debug-value
+is specified it is used to set the debugging level.  When debugging is
+on,
+.B ftp
+prints each command sent to the remote machine, preceded by the string
+`\-\->'
+.TP
+\fBdir\fP [\fIremote-directory\fP] [\fIlocal-file\fP]
+Print a listing of the directory contents in the directory,
+.IR remote-directory ,
+and, optionally, placing the output in
+.IR local-file .
+If interactive prompting is on,
+.B ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.B dir
+output.  If no directory is specified, the current working directory on
+the remote machine is used.  If no local file is specified, or
+.I local-file
+is
+`\fB\-\fP',
+output comes to the terminal.
+.TP
+.B disconnect
+A synonym for
+.IR close .
+.TP
+\fBform\fP \fIformat\fP
+Set the file transfer
+.B form
+to
+.IR format .
+The default format is ``file''.
+.TP
+\fBget\fP \fIremote-file\fP [\fIlocal-file\fP]
+Retrieve the file
+.I remote-file
+and store it on the local machine.  If the local file name is not
+specified, it is given the same name it has on the remote machine,
+subject to alteration by the current
+.BR case ,
+.BR ntrans ,
+and
+.B nmap
+settings.  The current settings for
+.BR type ,
+.BR form ,
+.BR mode ,
+and
+.B structure
+are used while transferring the file.
+.TP
+.B glob
+Toggle filename expansion for
+.BR mdelete ,
+.BR mget ,
+and
+.BR mput .
+If globbing is turned off with
+.BR glob ,
+the file name arguments are taken literally and not expanded.  Globbing
+for
+.B mput
+is done as in
+.IR csh (1).
+For
+.B mdelete
+and
+.BR mget ,
+each remote file name is expanded separately on the remote machine and
+the lists are not merged.  Expansion of a directory name is likely to be
+different from expansion of the name of an ordinary file: the exact
+result depends on the foreign operating system and ftp server, and can
+be previewed by doing
+`mls remote-files \-'
+Note:
+.B mget
+and
+.B mput
+are not meant to transfer entire directory subtrees of files.  That can
+be done by transferring a
+.IR tar (1)
+archive of the subtree (in binary mode).
+.TP
+.B hash
+Toggle hash-sign (``#'') printing for each data block transferred.  The
+size of a data block is 1024 bytes.
+.TP
+\fBhelp\fP [\fIcommand\fP]
+Print an informative message about the meaning of
+.IR command .
+If no argument is given,
+.B ftp
+prints a list of the known commands.
+.TP
+\fBidle\fP [\fIseconds\fP]
+Set the inactivity timer on the remote server to
+.I seconds
+seconds.  If
+.I seconds
+is omitted, the current inactivity timer is printed.
+.TP
+\fBlcd\fP [\fIdirectory\fP]
+Change the working directory on the local machine.  If no
+.I directory
+is specified, the user's home directory is used.
+.TP
+\fBls\fP [\fIremote-directory\fP] [\fIlocal-file\fP]
+Print a listing of the contents of a directory on the remote machine.
+The listing includes any system-dependent information that the server
+chooses to include; for example, most
+.SM UNIX
+systems will produce output from the command `ls \-l'.  (See also
+.BR nlist .)
+If
+.I remote-directory
+is left unspecified, the current working directory is used.  If
+interactive prompting is on,
+.B ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.B ls
+output.  If no local file is specified, or if
+.I local-file
+is
+`\fB\-\fP',
+the output is sent to the terminal.
+.TP
+\fBmacdef\fP\fImacro-name\fP
+Define a macro.  Subsequent lines are stored as the macro
+.IR macro-name ;
+a null line (consecutive newline characters in a file or carriage
+returns from the terminal) terminates macro input mode.  There is a
+limit of 16 macros and 4096 total characters in all defined macros.
+Macros remain defined until a
+.B close
+command is executed.  The macro processor interprets `$' and `\e' as
+special characters.  A `$' followed by a number (or numbers) is replaced
+by the corresponding argument on the macro invocation command line.  A
+`$' followed by an `i' signals that macro processor that the executing
+macro is to be looped.  On the first pass `$i' is replaced by the first
+argument on the macro invocation command line, on the second pass it is
+replaced by the second argument, and so on.  A `\e' followed by any
+character is replaced by that character.  Use the `\e' to prevent
+special treatment of the `$'.
+.TP
+\fBmdelete\fP [\fIremote-files\fP]
+Delete
+.I remote-files
+on the remote machine.
+.TP
+\fBmdir\fP \fIremote-files\fP \fIlocal-file\fP
+Like
+.BR dir ,
+except multiple remote files may be specified.  If interactive prompting
+is on,
+.B ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.B mdir
+output.
+.TP
+\fBmget\fP \fIremote-files\fP
+Expand the
+.I remote-files
+on the remote machine and do a
+.B get
+for each file name thus produced.  See
+.B glob
+for details on the filename expansion.  Resulting file names will then
+be processed according to
+.BR case ,
+.BR ntrans ,
+and
+.B nmap
+settings.  Files are transferred into the local working directory, which
+can be changed with `lcd directory'; new local directories can be
+created with
+`\&! mkdir directory'.
+.TP
+\fBmkdir\fP \fIdirectory-name\fP
+Make a directory on the remote machine.
+.TP
+\fBmls\fP \fIremote-files\fP \fIlocal-file\fP
+Like
+.BR nlist ,
+except multiple remote files may be specified, and the
+.I local-file
+must be specified.  If interactive prompting is on,
+.B ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.B mls
+output.
+.TP
+\fBmode\fP [\fImode-name\fP]
+Set the file transfer
+.B mode
+to
+.IR mode-name .
+The default mode is ``stream'' mode.
+.TP
+\fBmodtime\fP \fIfile-name\fP
+Show the last modification time of the file on the remote machine.
+.TP
+\fBmput\fP \fIlocal-files\fP
+Expand wild cards in the list of local files given as arguments and do a
+.B put
+for each file in the resulting list.  See
+.B glob
+for details of filename expansion.  Resulting file names will then be
+processed according to
+.B ntrans
+and
+.B nmap
+settings.
+.TP
+\fBnewer\fP \fIfile-name\fP
+Get the file only if the modification time of the remote file is more
+recent that the file on the current system.  If the file does not exist
+on the current system, the remote file is considered
+.BR newer .
+Otherwise, this command is identical to
+.BR get .
+.TP
+\fBnlist\fP [\fIremote-directory\fP] [\fIlocal-file\fP]
+Print a list of the files in a directory on the remote machine.  If
+.I remote-directory
+is left unspecified, the current working directory is used.  If
+interactive prompting is on,
+.B ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.B nlist
+output.  If no local file is specified, or if
+.I local-file
+is `\fB\-\fP', the output is sent to the terminal.
+.TP
+\fBnmap\fP [\fIinpattern\fP \fIoutpattern\fP]
+Set or unset the filename mapping mechanism.  If no arguments are
+specified, the filename mapping mechanism is unset.  If arguments are
+specified, remote filenames are mapped during
+.B mput
+commands and
+.B put
+commands issued without a specified remote target filename.
+If arguments are specified, local filenames are mapped during
+.B mget
+commands and
+.B get
+commands issued without a specified local target filename.  This command
+is useful when connecting to non\-UNIX remote computer with different
+file naming conventions or practices.  The mapping follows the pattern
+set by
+.I inpattern
+and
+.IR outpattern .
+[\fIInpattern\fP] is a template for incoming filenames (which may have
+already been processed according to the
+.B ntrans
+and
+.B case
+settings).  Variable templating is accomplished by including the
+sequences `$1', `$2', ..., `$9' in
+.IR inpattern .
+Use `\e' to prevent this special treatment of the `$' character.  All
+other characters are treated literally, and are used to determine the
+.B nmap
+[\fIinpattern\fP] variable values.  For example, given
+.I inpattern
+$1.$2 and the remote file name "mydata.data", $1 would have the value
+"mydata", and $2 would have the value "data".  The
+.I outpattern
+determines the resulting mapped filename.  The sequences `$1', `$2',
+...., `$9' are replaced by any value resulting from the
+.I inpattern
+template.  The sequence `$0' is replace by the original filename.
+Additionally, the sequence `[\fIseq1\fP, \fIseq2\fP]' is replaced by
+[\fIseq1\fP] if
+.I seq1
+is not a null string; otherwise it is replaced by
+.IR seq2 .
+For example, the command
+.sp
+.nf
+	nmap $1.$2.$3 [$1,$2].[$2,file]
+.fi
+.sp
+would yield the output filename "myfile.data" for input filenames
+"myfile.data" and "myfile.data.old", "myfile.file" for the input
+filename "myfile", and "myfile.myfile" for the input filename ".myfile".
+Spaces may be included in
+.IR outpattern ,
+as in the example: `nmap $1 sed "s/ *$//" > $1'.  Use the `\e' character
+to prevent special treatment of the `$','[',']', and `,' characters.
+.TP
+\fBntrans\fP [\fIinchars\fP [\fIoutchars\fP]]
+Set or unset the filename character translation mechanism.  If no
+arguments are specified, the filename character translation mechanism is
+unset.  If arguments are specified, characters in remote filenames are
+translated during
+.B mput
+commands and
+.B put
+commands issued without a specified remote target filename.  If
+arguments are specified, characters in local filenames are translated
+during
+.B mget
+commands and
+.B get
+commands issued without a specified local target filename.  This command
+is useful when connecting to a non-UNIX remote computer with different
+file naming conventions or practices.  Characters in a filename matching
+a character in
+.I inchars
+are replaced with the corresponding character in
+.IR outchars .
+If the character's position in
+.I inchars
+is longer than the length of
+.IR outchars ,
+the character is deleted from the file name.
+.TP
+\fBopen\fP \fIhost\fP [\fIport\fP] [\fB\-forward\fP]
+Establish a connection to the specified
+.I host
+.SM FTP
+server.  An optional port number may be supplied, in which case,
+.B ftp
+will attempt to contact an
+.SM FTP
+server at that port.  If the
+.B auto-authenticate
+option is on (default),
+.B ftp
+will attempt to authenticate to the
+.SM FTP
+server by sending the
+.SM AUTH
+command, using whichever authentication types which are locally
+supported.  Once an authentication type is accepted, an authentication
+protocol will proceed by issuing
+.SM ADAT
+commands.  If the
+.B auto-login
+option is on (default),
+.B ftp
+will also attempt to automatically log the user in to the
+.SM FTP
+server (see below).  If the
+.B \-forward
+option is specified,
+.B ftp
+will forward a copy of the user's Kerberos tickets to the remote host.
+.TP
+.B passive
+Toggle passive data transfer mode.  In passive mode, the client initiates
+the data connection by listening on the data port.  Passive mode may
+be necessary for operation from behind firewalls which do not permit
+incoming connections.
+.TP
+.B private
+Set the protection level on data transfers to ``private''.  Data
+transmissions are confidentiality and integrity protected by encryption.
+If no
+.SM ADAT
+command succeeded, then the only possible level is ``clear''.
+.TP
+.B prompt
+Toggle interactive prompting.  Interactive prompting occurs during
+multiple file transfers to allow the user to selectively retrieve or
+store files.  If prompting is turned off (default is on), any
+.B mget
+or
+.B mput
+will transfer all files, and any
+.B mdelete
+will delete all files.
+.TP
+\fBprotect\fP [\fIprotection-level\fP]
+Set the protection level on data transfers to
+.IR protection-level .
+The valid protection levels are ``clear'' for unprotected data
+transmissions, ``safe'' for data transmissions integrity protected by
+cryptographic checksum, and ``private'' for data transmissions
+confidentiality and integrity protected by encryption.  If no
+.SM ADAT
+command succeeded, then the only possible level is ``clear''.  If no
+level is specified, the current level is printed.  The default
+protection level is ``clear''.
+.TP
+\fBproxy\fP \fIftp-command\fP
+Execute an ftp command on a secondary control connection.  This command
+allows simultaneous connection to two remote ftp servers for
+transferring files between the two servers.  The first
+.B proxy
+command should be an
+.B open  ,
+to establish the secondary control connection.  Enter the command 
+"proxy ?" to see other ftp commands executable on the secondary connection.
+The following commands behave differently when prefaced by
+.BR proxy :
+.B open
+will not define new macros during the auto-login process,
+.B close
+will not erase existing macro definitions,
+.B get
+and
+.B mget
+transfer files from the host on the primary control connection to the
+host on the secondary control connection, and
+.BR put ,
+.BR mput ,
+and
+.B append
+transfer files from the host on the secondary control connection to the
+host on the primary control connection.  Third party file transfers
+depend upon support of the ftp protocol
+.SM PASV
+command by the server on the secondary control connection.
+.TP
+\fBput\fP \fIlocal-file\fP [\fIremote-file\fP]
+Store a local file on the remote machine.  If
+.I remote-file
+is left unspecified, the local file name is used after processing
+according to any
+.B ntrans
+or
+.B nmap
+settings in naming the remote file.  File transfer uses the current
+settings for
+.BR type ,
+.BR format ,
+.BR mode ,
+and
+.BR structure .
+.TP
+.B pwd
+Print the name of the current working directory on the remote machine.
+.TP
+.B quit
+A synonym for
+.BR bye .
+.TP
+\fBquote\fP \fIarg1\fP [\fIarg2\fP] [\fI...\fP]
+The arguments specified are sent, verbatim, to the remote
+.SM FTP
+server.
+.TP
+\fBrecv\fP \fIremote-file\fP [\fIlocal-file\fP]
+A synonym for get.
+.TP
+\fBreget\fP \fIremote-file\fP [\fIlocal-file\fP]
+Reget acts like get, except that if
+.I local-file
+exists and is smaller than
+.IR remote-file ,
+.I local-file
+is presumed to be a partially transferred copy of
+.I remote-file
+and the transfer is continued from the apparent point of failure.  This
+command is useful when transferring very large files over networks that
+are prone to dropping connections.
+.TP
+\fBremotehelp\fP [\fIcommand-name\fP]
+Request help from the remote
+.SM FTP
+server.  If a
+.I command-name
+is specified it is supplied to the server as well.
+.TP
+\fBremotestatus\fP [\fIfile-name\fP]
+With no arguments, show status of remote machine.  If
+.I file-name
+is specified, show status of
+.I file-name
+on remote machine.
+.TP
+\fBrename\fP [\fIfrom\fP] [\fIto\fP]
+Rename the file
+.I from
+on the remote machine, to the file
+.IR to .
+.TP
+.B reset
+Clear reply queue.  This command re-synchronizes command/reply
+sequencing with the remote ftp server.  Resynchronization may be
+necessary following a violation of the ftp protocol by the remote
+server.
+.TP
+\fBrestart\fP \fImarker\fP
+Restart the immediately following
+.B get
+or
+.B put
+at the indicated
+.IR marker .
+On UNIX systems, marker is usually a byte offset into the file.
+.TP
+\fBrmdir\fP \fIdirectory-name\fP
+Delete a directory on the remote machine.
+.TP
+.B runique
+Toggle storing of files on the local system with unique filenames.  If a
+file already exists with a name equal to the target local filename for a
+.B get
+or
+.B mget
+command, a ".1" is appended to the name.  If the resulting name matches
+another existing file, a ".2" is appended to the original name.  If this
+process continues up to ".99", an error message is printed, and the
+transfer does not take place.  The generated unique filename will be
+reported.  Note that
+.B runique
+will not affect local files generated from a shell command (see below).
+The default value is off.
+.TP
+.B safe
+Set the protection level on data transfers to ``safe''.  Data
+transmissions are integrity-protected by cryptographic checksum.  If no
+.SM ADAT
+command succeeded, then the only possible level is ``clear''.
+.TP
+\fBsend\fP \fIlocal-file\fP [\fIremote-file\fP]
+A synonym for put.
+.TP
+.B sendport
+Toggle the use of
+.SM PORT
+commands.  By default,
+.B ftp
+will attempt to use a
+.SM PORT
+command when establishing a connection for each data transfer.  The use
+of
+.SM PORT
+commands can prevent delays when performing multiple file transfers.  If
+the
+.SM PORT
+command fails,
+.B ftp
+will use the default data port.  When the use of
+.SM PORT
+commands is disabled, no attempt will be made to use
+.SM PORT
+commands for each data transfer.  This is useful for certain
+.SM FTP
+implementations which do ignore
+.SM PORT
+commands but, incorrectly, indicate they've been accepted.
+.TP
+\fBsite\fP \fIarg1\fP [\fIarg2\fP] [\fI...\fP]
+The arguments specified are sent, verbatim, to the remote
+.SM FTP
+server as a
+.SM SITE
+command.
+.TP
+\fBsize\fP \fIfile-name\fP
+Return size of
+.I file-name
+on remote machine.
+.TP
+.B status
+Show the current status of
+.BR ftp .
+.TP
+\fBstruct\fP \fIstruct-name\fP
+Set the file transfer
+.I structure
+to
+.IR struct-name .
+By default ``stream'' structure is used.
+.TP
+.B sunique
+Toggle storing of files on remote machine under unique file names.
+Remote ftp server must support ftp protocol
+.SM STOU
+command for successful completion.  The remote server will report unique
+name.  Default value is off.
+.TP
+.B system
+Show the type of operating system running on the remote machine.
+.TP
+.B tenex
+Set the file transfer type to that needed to talk to
+.SM TENEX
+machines.
+.TP
+.B trace
+Toggle packet tracing.
+.TP
+\fBtype\fP [\fItype-name\fP]
+Set the file transfer
+.B type
+to
+.IR type-name .
+If no type is specified, the current type is printed.  The default type
+is network
+.SM ASCII.
+.TP
+\fBumask\fP [\fInewmask\fP]
+Set the default umask on the remote server to
+.IR newmask .
+If
+.I newmask
+is omitted, the current umask is printed.
+.TP
+\fBuser\fP \fIuser-name\fP [\fIpassword\fP] [\fIaccount\fP]
+Identify yourself to the remote
+.SM FTP
+server.  If the
+.I password
+is not specified and the server requires it,
+.B ftp
+will prompt the user for it (after disabling local echo).  If an
+.I account
+field is not specified, and the
+.SM FTP
+server requires it, the user will be prompted for it.  If an
+.I account
+field is specified, an account command will be relayed to the remote
+server after the login sequence is completed if the remote server did
+not require it for logging in.  Unless
+.B ftp
+is invoked with ``auto-login'' disabled, this process is done
+automatically on initial connection to the
+.SM FTP
+server.
+.TP
+.B verbose
+Toggle verbose mode.  In verbose mode, all responses from the
+.SM FTP
+server are displayed to the user.  In addition, if verbose is on, when a
+file transfer completes, statistics regarding the efficiency of the
+transfer are reported.  By default, verbose is on.
+.TP
+\fB \&? [\fIcommand\fP]
+A synonym for help.
+.PP
+Command arguments which have embedded spaces may be quoted with quote
+`"' marks.
+.SH ABORTING A FILE TRANSFER
+To abort a file transfer, use the terminal interrupt key (usually
+Ctrl-C).  Sending transfers will be immediately halted.  Receiving
+transfers will be halted by sending a 
+.SM FTP
+protocol
+.SM ABOR
+command to the remote server, and discarding any further data received.
+The speed at which this is accomplished depends upon the remote server's
+support for
+.SM ABOR
+processing.  If the remote server does not support the
+.SM ABOR
+command, an `ftp>' prompt will not appear until the remote server has
+completed sending the requested file.
+.PP
+The terminal interrupt key sequence will be ignored when
+.B ftp
+has completed any local processing and is awaiting a reply from the
+remote server.  A long delay in this mode may result from the
+.SM ABOR
+processing described above, or from unexpected behavior by the remote
+server, including violations of the ftp protocol.  If the delay results
+from unexpected remote server behavior, the local
+.B ftp
+program must be killed by hand.
+.SH FILE NAMING CONVENTIONS
+Files specified as arguments to
+.B ftp
+commands are processed according to the following rules.
+.TP
+1.
+If the file name `\fB-\fP' is specified,
+.I stdin
+(for reading) or
+.I stdout
+(for writing) is used.
+.TP
+2.
+If the first character of the file name is `\&|', the remainder of the
+argument is interpreted as a shell command.
+.B Ftp
+then forks a shell, using
+.IR popen (3)
+with the argument supplied, and reads from (writes to) stdout (stdin).
+If the shell command includes spaces, the argument must be quoted; e.g.
+``" ls -lt"''.  A particularly useful example of this mechanism is:
+``dir more''.
+.TP
+3.
+Failing the above checks, if ``globbing'' is enabled, local file names
+are expanded according to the rules used in
+.IR csh (1);
+c.f. the
+.B glob
+command.  If the
+.B ftp
+command expects a single local file (.e.g.
+.BR put ),
+only the first filename generated by the ``globbing'' operation is used.
+.TP
+4.
+For
+.B mget
+commands and
+.B get
+commands with unspecified local file names, the local filename is the
+remote filename, which may be altered by a
+.BR case ,
+.BR ntrans ,
+or
+.B nmap
+setting.  The resulting filename may then be altered if
+.B runique
+is on.
+.TP
+5.
+For
+.B mput
+commands and
+.B put
+commands with unspecified remote file names, the remote filename is the
+local filename, which may be altered by a
+.B ntrans
+or
+.B nmap
+setting.  The resulting filename may then be altered by the remote
+server if
+.B sunique
+is on.
+.SH FILE TRANSFER PARAMETERS
+The FTP specification specifies many parameters which may affect a file
+transfer.  The
+.B type
+may be one of ``ascii'', ``image'' (binary), ``ebcdic'', and ``local
+byte size'' (mostly for PDP-10's and PDP-20's).
+.B Ftp
+supports the ascii and image types of file transfer, plus local byte
+size 8 for
+.B tenex
+mode transfers.
+.PP
+.B Ftp
+supports only the default values for the remaining file transfer
+parameters:
+.BR mode ,
+.BR form ,
+and
+.BR struct .
+.SH THE .netrc FILE
+The
+.I .netrc
+file contains login and initialization information used by the
+auto-login process.  It resides in the user's home directory.  The
+following tokens are recognized; they may be separated by spaces, tabs,
+or new-lines:
+.TP
+\fBmachine\fP \fIname\fP
+Identify a remote machine
+.IR name .
+The auto-login process searches the
+.I .netrc
+file for a
+.B machine
+token that matches the remote machine specified on the
+.B ftp
+command line or as an
+.B open
+command argument.  Once a match is made, the subsequent
+.I .netrc
+tokens are processed, stopping when the end of file is reached or
+another
+.B machine
+or a
+.B default
+token is encountered.
+.TP
+.B default
+This is the same as
+.B machine
+.I name
+except that
+.B default
+matches any name.  There can be only one
+.B default
+token, and it must be after all
+.B machine
+tokens.  This is normally used as:
+.sp
+     default login anonymous password user@site
+.sp
+thereby giving the user
+.I automatic
+anonymous ftp login to machines not specified in
+.IR .netrc .
+This can be overridden by using the
+.B \-n
+flag to disable auto-login.
+.TP
+\fBlogin\fP \fIname\fP
+Identify a user on the remote machine.  If this token is present, the
+auto-login process will initiate a login using the specified
+.IR name .
+.TP
+\fBpassword\fP \fIstring\fP
+Supply a password.  If this token is present, the auto-login process
+will supply the specified string if the remote server requires a
+password as part of the login process.  Note that if this token is
+present in the
+.I .netrc
+file for any user other than
+.IR anonymous ,
+.B ftp
+will abort the auto-login process if the
+.I .netrc
+is readable by anyone besides the user.
+.TP
+\fBaccount\fP \fIstring\fP
+Supply an additional account password.  If this token is present, the
+auto-login process will supply the specified string if the remote server
+requires an additional account password, or the auto-login process will
+initiate an
+.SM ACCT
+command if it does not.
+.TP
+\fBmacdef\fP \fIname\fP
+Define a macro.  This token functions like the
+.B ftp
+.B macdef
+command functions.  A macro is defined with the specified name; its
+contents begin with the next
+.I .netrc
+line and continue until a null line (consecutive new-line characters) is
+encountered.  If a macro named
+.B init
+is defined, it is automatically executed as the last step in the
+auto-login process.
+.SH ENVIRONMENT
+.B Ftp
+utilizes the following environment variables.
+.TP
+.SM HOME
+For default location of a
+.I .netrc
+file, if one exists.
+.TP
+.SM SHELL
+For default shell.
+.SH SEE ALSO
+.IR ftpd (8)
+.PP
+Lunt, S. J., FTP Security Extensions, Internet Draft, November 1993.
+.SH HISTORY
+The
+.B ftp
+command appeared in 4.2BSD.
+.SH BUGS
+Correct execution of many commands depends upon proper behavior by the
+remote server.
+.PP
+An error in the treatment of carriage returns in the 4.2BSD ascii-mode
+transfer code has been corrected.  This correction may result in
+incorrect transfers of binary files to and from 4.2BSD servers using the
+ascii type.  Avoid this problem by using the binary image type.
diff --git a/krb5-1-6/src/appl/gssftp/ftp/ftp.c b/krb5-1-6/src/appl/gssftp/ftp/ftp.c
new file mode 100644
index 000000000..c16d4544b
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/ftp.c
@@ -0,0 +1,2368 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * 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 */
+
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock2.h>
+#include <sys/timeb.h>
+#include <time.h>
+#include <crtdbg.h>
+#undef ERROR
+#define NOSTBLKSIZE
+
+#define popen _popen
+#define pclose _pclose
+#define sleep(secs) Sleep(secs * 1000)
+int gettimeofday(struct timeval *tv, void *tz);
+
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef _WIN32
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#ifndef KRB5_KRB4_COMPAT
+/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+#include <sys/time.h>
+#include <sys/file.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <pwd.h>
+#endif
+
+#include <arpa/ftp.h>
+#include <arpa/telnet.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include <port-sockets.h>
+
+#ifndef L_SET
+#define L_SET 0
+#endif
+#ifndef L_INCR
+#define L_INCR 1
+#endif
+
+#ifdef KRB5_KRB4_COMPAT
+#include <krb.h>
+
+KTEXT_ST ticket;
+CREDENTIALS cred;
+Key_schedule schedule;
+MSG_DAT msg_data;
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+#include <gssapi/gssapi.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_generic.h>
+#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? */
+
+unsigned int maxbuf, actualbuf;
+unsigned char *ucbuf;
+ 
+#define DEFINITIONS
+#include "ftp_var.h"
+#include "secure.h"
+
+#ifdef GSSAPI
+void user_gss_error (OM_uint32, OM_uint32, char *);
+#endif
+
+static void proxtrans (char *, char *, char *);
+static int initconn (void);
+static void ptransfer (char *, long, struct timeval *, struct timeval *);
+static void abort_remote (FILE *);
+static void tvsub (struct timeval *, struct timeval *, struct timeval *);
+static char *gunique (char *);
+
+struct	sockaddr_in hisctladdr;
+struct	sockaddr_in hisdataaddr;
+struct	sockaddr_in data_addr;
+SOCKET	data = -1;
+int	abrtflag = 0;
+int	ptflag = 0;
+struct	sockaddr_in myctladdr;
+#ifndef _WIN32
+uid_t	getuid();
+#endif
+sig_t	lostpeer();
+off_t	restart_point = 0;
+jmp_buf ptabort;
+
+#ifndef HAVE_STRERROR
+#define strerror(error) (sys_errlist[error])
+#ifdef NEED_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+#endif
+
+extern int connected;
+
+#define herror()	printf("unknown host\n")
+
+FILE	*cin, *cout;
+FILE	*dataconn (char *);
+
+char *
+hookup(char* host, int port)
+{
+	register struct hostent *hp = 0;
+	int s;
+	socklen_t len;
+#ifdef IP_TOS
+#ifdef IPTOS_LOWDELAY
+	int tos;
+#endif
+#endif
+	static char hostnamebuf[80];
+
+	memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
+	hisctladdr.sin_addr.s_addr = inet_addr(host);
+	if (hisctladdr.sin_addr.s_addr != -1) {
+		hisctladdr.sin_family = AF_INET;
+		(void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
+	} else {
+		hp = gethostbyname(host);
+		if (hp == NULL) {
+			fprintf(stderr, "ftp: %s: ", host);
+			herror();
+			code = -1;
+			return((char *) 0);
+		}
+		hisctladdr.sin_family = hp->h_addrtype;
+		memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0],
+		       sizeof(hisctladdr.sin_addr));
+		(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
+	}
+	hostname = hostnamebuf;
+	s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
+	if (s == INVALID_SOCKET) {
+		PERROR_SOCKET("ftp: socket");
+		code = -1;
+		return (0);
+	}
+	hisctladdr.sin_port = port;
+	while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) == SOCKET_ERROR) {
+		if (hp && hp->h_addr_list[1]) {
+			int oerrno = SOCKET_ERRNO;
+#ifndef _WIN32
+			extern char *inet_ntoa();
+#endif
+			fprintf(stderr, "ftp: connect to address %s: ",
+				inet_ntoa(hisctladdr.sin_addr));
+			SOCKET_SET_ERRNO(oerrno);
+			PERROR_SOCKET((char *) 0);
+			hp->h_addr_list++;
+			memcpy(&hisctladdr.sin_addr,
+			       hp->h_addr_list[0], 
+			       sizeof(hisctladdr.sin_addr));
+			fprintf(stdout, "Trying %s...\n",
+				inet_ntoa(hisctladdr.sin_addr));
+			(void) closesocket(s);
+			s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
+			if (s == INVALID_SOCKET) {
+				PERROR_SOCKET("ftp: socket");
+				code = -1;
+				return (0);
+			}
+			continue;
+		}
+		PERROR_SOCKET("ftp: connect");
+		code = -1;
+		goto bad;
+	}
+	len = sizeof (myctladdr);
+	if (getsockname(s, (struct sockaddr *)&myctladdr, &len) == SOCKET_ERROR) {
+		PERROR_SOCKET("ftp: getsockname");
+		code = -1;
+		goto bad;
+	}
+#ifdef IP_TOS
+#ifdef IPTOS_LOWDELAY
+	tos = IPTOS_LOWDELAY;
+	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) == SOCKET_ERROR) {
+		PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
+	}
+#endif
+#endif
+	cin = FDOPEN_SOCKET(s, "r");
+	cout = FDOPEN_SOCKET(s, "w");
+	if (cin == NULL || cout == NULL) {
+		fprintf(stderr, "ftp: fdopen failed.\n");
+		if (cin) {
+			(void) FCLOSE_SOCKET(cin);
+			cin = NULL;
+		}
+		if (cout) {
+			(void) FCLOSE_SOCKET(cout);
+			cout = NULL;
+		}
+		code = -1;
+		goto bad;
+	}
+	if (verbose)
+		printf("Connected to %s.\n", hostname);
+	if (getreply(0) > 2) { 	/* read startup message from server */
+		if (cin) {
+			(void) FCLOSE_SOCKET(cin);
+			cin = NULL;
+		}
+		if (cout) {
+			(void) FCLOSE_SOCKET(cout);
+			cout = NULL;
+		}
+		code = -1;
+		goto bad;
+	}
+#ifdef SO_OOBINLINE
+	{
+	int on = 1;
+
+	if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
+		== SOCKET_ERROR && debug) {
+			PERROR_SOCKET("ftp: setsockopt");
+		}
+	}
+#endif /* SO_OOBINLINE */
+
+	return (hostname);
+bad:
+	(void) closesocket(s);
+	return ((char *)0);
+}
+
+int login(char *host)
+{
+	char tmp[80];
+	char *l_user, *pass, *l_acct, *getenv(), *getlogin();
+	int n, aflag = 0;
+
+	l_user = pass = l_acct = 0;
+	if (ruserpass(host, &l_user, &pass, &l_acct) < 0) {
+		code = -1;
+		return(0);
+	}
+	while (l_user == NULL) {
+		char *myname;
+
+		myname = getenv("LOGNAME");
+		if (myname == NULL)
+			myname = getenv("USER");
+#ifndef _WIN32
+		if (myname == NULL)
+			myname = getlogin();
+		if (myname == NULL) {
+			struct passwd *pp = getpwuid(getuid());
+
+			if (pp != NULL)
+				myname = pp->pw_name;
+		}
+#else
+		if (myname == NULL) {
+			static char buffer[200];
+			int len = sizeof(buffer);
+			if (GetUserName(buffer, &len))
+				myname = buffer;
+			else
+				myname = "<Unknown>";
+		}
+#endif
+		if (myname)
+			printf("Name (%s:%s): ", host, myname);
+		else
+			printf("Name (%s): ", host);
+		(void) fgets(tmp, sizeof(tmp) - 1, stdin);
+		tmp[strlen(tmp) - 1] = '\0';
+		if (*tmp == '\0')
+			l_user = myname;
+		else
+			l_user = tmp;
+	}
+	n = command("USER %s", l_user);
+	if (n == COMPLETE) {
+	        /* determine if we need to send a dummy password */
+		int oldverbose = verbose;
+
+		verbose = 0;
+		if (command("PWD") != COMPLETE) {
+			verbose = oldverbose;
+			command("PASS dummy");
+		} else {
+			verbose = oldverbose;
+		}
+	}
+	else if (n == CONTINUE) {
+#ifndef NOENCRYPTION
+		int oldclevel;
+#endif
+		if (pass == NULL)
+			pass = mygetpass("Password:");
+#ifndef NOENCRYPTION
+		oldclevel = clevel;
+		clevel = PROT_P;
+#endif
+		n = command("PASS %s", pass);
+#ifndef NOENCRYPTION
+		/* level may have changed */
+		if (clevel == PROT_P) clevel = oldclevel;
+#endif
+	}
+	if (n == CONTINUE) {
+		aflag++;
+		l_acct = mygetpass("Account:");
+		n = command("ACCT %s", l_acct);
+	}
+	if (n != COMPLETE) {
+		fprintf(stderr, "Login failed.\n");
+		return (0);
+	}
+	if (!aflag && l_acct != NULL)
+		(void) command("ACCT %s", l_acct);
+	if (proxy)
+		return(1);
+	for (n = 0; n < macnum; ++n) {
+		if (!strcmp("init", macros[n].mac_name)) {
+			(void) strcpy(line, "$init");
+			makeargv();
+			domacro(margc, margv);
+			break;
+		}
+	}
+	return (1);
+}
+
+static sigtype
+cmdabort(int sig)
+{
+	printf("\n");
+	(void) fflush(stdout);
+	abrtflag++;
+	if (ptflag)
+		longjmp(ptabort,1);
+}
+
+static int secure_command(char* cmd)
+{
+	unsigned char in[FTP_BUFSIZ], out[FTP_BUFSIZ];
+	int length;
+
+	if (auth_type && clevel != PROT_C) {
+#ifdef KRB5_KRB4_COMPAT
+		if (strcmp(auth_type, "KERBEROS_V4") == 0)
+		    if ((length = clevel == PROT_P ?
+			krb_mk_priv((unsigned char *)cmd, (unsigned char *)out,
+				strlen(cmd), schedule,
+				&cred.session, &myctladdr, &hisctladdr)
+		      : krb_mk_safe((unsigned char *)cmd, (unsigned char *)out,
+				strlen(cmd), &cred.session,
+				&myctladdr, &hisctladdr)) == -1) {
+			fprintf(stderr, "krb_mk_%s failed for KERBEROS_V4\n",
+					clevel == PROT_P ? "priv" : "safe");
+			return(0);
+		    }
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+		/* secure_command (based on level) */
+		if (strcmp(auth_type, "GSSAPI") == 0) {
+			gss_buffer_desc in_buf, out_buf;
+			OM_uint32 maj_stat, min_stat;
+			int conf_state;
+/* clevel = PROT_P; */
+			in_buf.value = cmd;
+			in_buf.length = strlen(cmd) + 1;
+			maj_stat = gss_seal(&min_stat, gcontext,
+					    (clevel==PROT_P), /* private */
+					    GSS_C_QOP_DEFAULT,
+					    &in_buf, &conf_state,
+					    &out_buf);
+			if (maj_stat != GSS_S_COMPLETE) {
+				/* generally need to deal */
+				user_gss_error(maj_stat, min_stat,
+					       (clevel==PROT_P)?
+						 "gss_seal ENC didn't complete":
+						 "gss_seal MIC didn't complete");
+			} else if ((clevel == PROT_P) && !conf_state) {
+				fprintf(stderr, 
+					"GSSAPI didn't encrypt message");
+			} else {
+				if (debug)
+				  fprintf(stderr, "sealed (%s) %d bytes\n",
+					  clevel==PROT_P?"ENC":"MIC", 
+					  out_buf.length);
+				length=out_buf.length;
+				memcpy(out, out_buf.value, out_buf.length);
+				gss_release_buffer(&min_stat, &out_buf);
+			}
+		}
+#endif /* GSSAPI */
+		/* Other auth types go here ... */
+		kerror = radix_encode(out, in, &length, 0);
+		if (kerror) {
+			fprintf(stderr,"Couldn't base 64 encode command (%s)\n",
+					radix_error(kerror));
+			return(0);
+		}
+		fprintf(cout, "%s %s", clevel == PROT_P ? "ENC" : "MIC", in);
+		if(debug) 
+		  fprintf(stderr, "secure_command(%s)\nencoding %d bytes %s %s\n",
+			  cmd, length, clevel==PROT_P ? "ENC" : "MIC", in);
+	} else	fputs(cmd, cout);
+	fprintf(cout, "\r\n");
+	(void) fflush(cout);
+	return(1);
+}
+
+int command(char *fmt, ...)
+{
+	char in[FTP_BUFSIZ];
+	va_list ap;
+	int r;
+	sig_t oldintr;
+
+	abrtflag = 0;
+	if (debug) {
+		if (proxflag) printf("%s ", hostname);
+		printf("---> ");
+		va_start(ap, fmt);
+		if (strncmp("PASS ", fmt, 5) == 0)
+			printf("PASS XXXX");
+		else 
+			vfprintf(stdout, fmt, ap);
+		va_end(ap);
+		printf("\n");
+		(void) fflush(stdout);
+	}
+	if (cout == NULL) {
+		perror ("No control connection for command");
+		code = -1;
+		return (0);
+	}
+	oldintr = signal(SIGINT, cmdabort);
+	va_start(ap, fmt);
+	vsprintf(in, fmt, ap);
+	va_end(ap);
+again:	if (secure_command(in) == 0)
+		return(0);
+	cpend = 1;
+	r = getreply(!strcmp(fmt, "QUIT"));
+#ifndef NOENCRYPTION
+	if (r == 533 && clevel == PROT_P) {
+		fprintf(stderr,
+			"ENC command not supported at server; retrying under MIC...\n");
+		clevel = PROT_S;
+		goto again;
+	}
+#endif
+	if (abrtflag && oldintr && oldintr != SIG_IGN)
+		(*oldintr)(SIGINT);
+	(void) signal(SIGINT, oldintr);
+	return(r);
+}
+
+char reply_string[FTP_BUFSIZ];		/* last line of previous reply */
+
+/* for parsing replies to the ADAT command */
+char *reply_parse, reply_buf[FTP_BUFSIZ], *reply_ptr;
+
+#include <ctype.h>
+
+int getreply(int expecteof)
+{
+	register int i, c, n;
+	register int dig;
+	register char *cp;
+	int originalcode = 0, continuation = 0;
+	sig_t oldintr;
+	int pflag = 0;
+	char *pt = pasv;
+	char ibuf[FTP_BUFSIZ], obuf[FTP_BUFSIZ];
+	int safe = 0;
+#ifndef strpbrk
+	extern char *strpbrk();
+#endif
+#ifndef strstr
+	extern char *strstr();
+#endif
+
+	ibuf[0] = '\0';
+	if (reply_parse) reply_ptr = reply_buf;
+	oldintr = signal(SIGINT, cmdabort);
+	for (;;) {
+		obuf[0] = '\0';
+		dig = n = code = i = 0;
+		cp = reply_string;
+		while ((c = ibuf[0] ? ibuf[i++] : getc(cin)) != '\n') {
+			if (c == IAC) {     /* handle telnet commands */
+				switch (c = getc(cin)) {
+				case WILL:
+				case WONT:
+					c = getc(cin);
+					fprintf(cout, "%c%c%c", IAC, DONT, c);
+					(void) fflush(cout);
+					break;
+				case DO:
+				case DONT:
+					c = getc(cin);
+					fprintf(cout, "%c%c%c", IAC, WONT, c);
+					(void) fflush(cout);
+					break;
+				default:
+					break;
+				}
+				continue;
+			}
+			dig++;
+			if (c == EOF) {
+				if (expecteof) {
+					(void) signal(SIGINT,oldintr);
+					code = 221;
+					return (0);
+				}
+				lostpeer();
+				if (verbose) {
+					printf("421 Service not available, remote server has closed connection\n");
+					(void) fflush(stdout);
+				}
+				code = 421;
+				return(4);
+			}
+			if (n == 0)
+				n = c;
+			if (auth_type && !ibuf[0] &&
+				(n == '6' || continuation)) {
+			    if (c != '\r' && dig > 4)
+				obuf[i++] = c;
+			} else {
+			    if (auth_type && !ibuf[0] && dig == 1 && verbose)
+			printf("Unauthenticated reply received from server:\n");
+			    if (reply_parse) *reply_ptr++ = c;
+			    if (c != '\r' && (verbose > 0 ||
+				(verbose > -1 && n == '5' && dig > 4))) {
+				    if (proxflag &&
+					(dig == 1 || (dig == 5 && verbose == 0)))
+						printf("%s:",hostname);
+				    (void) putchar(c);
+			    }
+			}
+			if (auth_type && !ibuf[0] && n != '6') continue;
+			if (dig < 4 && isdigit(c))
+				code = code * 10 + (c - '0');
+			if (!pflag && code == 227)
+				pflag = 1;
+			if (dig > 4 && pflag == 1 && isdigit(c))
+				pflag = 2;
+			if (pflag == 2) {
+				if (c != '\r' && c != ')')
+					*pt++ = c;
+				else {
+					*pt = '\0';
+					pflag = 3;
+				}
+			}
+			if (dig == 4 && c == '-' && n != '6') {
+				if (continuation)
+					code = 0;
+				continuation++;
+			}
+			if (cp < &reply_string[sizeof(reply_string) - 1])
+				*cp++ = c;
+		}
+		if (auth_type && !ibuf[0] && n != '6')
+			return(getreply(expecteof));
+		ibuf[0] = obuf[i] = '\0';
+		if (code && n == '6') {
+		    if (code != 631 && code != 632 && code != 633) {
+			printf("Unknown reply: %d %s\n", code, obuf);
+			n = '5';
+		    } else safe = (code == 631);
+		}
+		if (obuf[0])	/* if there is a string to decode */
+		    if (!auth_type) {
+			printf("Cannot decode reply:\n%d %s\n", code, obuf);
+			n = '5';
+		    }
+#ifdef NOENCRYPTION
+		    else if (code == 632) {
+			printf("Cannot decrypt %d reply: %s\n", code, obuf);
+			n = '5';
+		    }
+#endif
+#ifdef NOCONFIDENTIAL
+		    else if (code == 633) {
+			printf("Cannot decrypt %d reply: %s\n", code, obuf);
+			n = '5';
+		    }
+#endif
+		    else {
+			int len;
+			kerror = radix_encode((unsigned char *)obuf,
+					      (unsigned char *)ibuf, 
+					      &len, 1);
+			if (kerror) {
+			    printf("Can't base 64 decode reply %d (%s)\n\"%s\"\n",
+					code, radix_error(kerror), obuf);
+			    n = '5';
+			}
+#ifdef KRB5_KRB4_COMPAT
+			else if (strcmp(auth_type, "KERBEROS_V4") == 0) {
+			    if (safe)
+				kerror = krb_rd_safe((unsigned char *)ibuf,
+						     (unsigned int) len,
+						     &cred.session,
+						     &hisctladdr,
+						     &myctladdr, &msg_data);
+			    else
+				kerror = krb_rd_priv((unsigned char *)ibuf,
+						     (unsigned int) len,
+						     schedule, &cred.session,
+						     &hisctladdr, &myctladdr,
+						     &msg_data);
+			    if (kerror != KSUCCESS) {
+				printf("%d reply %s! (krb_rd_%s: %s)\n", code,
+				       safe ? "modified" : "garbled",
+				       safe ? "safe" : "priv",
+				       krb_get_err_text(kerror));
+				n = '5';
+			    } else {
+				if (debug) printf("%c:", safe ? 'S' : 'P');
+				if(msg_data.app_length < sizeof(ibuf) - 2) {
+				    memmove(ibuf, msg_data.app_data,
+					    msg_data.app_length);
+				    strcpy(&ibuf[msg_data.app_length], "\r\n");
+				} else {
+			            printf("Message too long!");
+				}
+				continue;
+			    }
+			}
+#endif
+#ifdef GSSAPI
+			else if (strcmp(auth_type, "GSSAPI") == 0) {
+				gss_buffer_desc xmit_buf, msg_buf;
+				OM_uint32 maj_stat, min_stat;
+				int conf_state;
+				xmit_buf.value = ibuf;
+				xmit_buf.length = len;
+				/* decrypt/verify the message */
+				conf_state = safe;
+				maj_stat = gss_unseal(&min_stat, gcontext, 
+						      &xmit_buf, &msg_buf, 
+						      &conf_state, NULL);
+				if (maj_stat != GSS_S_COMPLETE) {
+				  user_gss_error(maj_stat, min_stat, 
+						 "failed unsealing reply");
+				  n = '5';
+				} else {
+				  if(msg_buf.length < sizeof(ibuf) - 2 - 1) {
+				    memcpy(ibuf, msg_buf.value, 
+					   msg_buf.length);
+				    strcpy(&ibuf[msg_buf.length], "\r\n");
+				  } else {
+				    user_gss_error(maj_stat, min_stat, 
+						   "reply was too long");
+				  }
+				  gss_release_buffer(&min_stat,&msg_buf);
+				  continue;
+				}
+			}
+#endif
+			/* Other auth types go here... */
+		    }
+		else
+		if (verbose > 0 || (verbose > -1 && n == '5')) {
+			(void) putchar(c);
+			(void) fflush (stdout);
+		}
+		if (continuation && code != originalcode) {
+			if (originalcode == 0)
+				originalcode = code;
+			continue;
+		}
+		*cp = '\0';
+		if (n != '1')
+			cpend = 0;
+		(void) signal(SIGINT,oldintr);
+		if (code == 421 || originalcode == 421)
+			lostpeer();
+		if (abrtflag && oldintr && oldintr != cmdabort && oldintr != SIG_IGN)
+			(*oldintr)(SIGINT);
+		if (reply_parse) {
+			*reply_ptr = '\0';
+			reply_ptr = strstr(reply_buf, reply_parse);
+			if (reply_ptr) {
+				reply_parse = reply_ptr + strlen(reply_parse);
+				reply_ptr = strpbrk(reply_parse, " \r");
+				if (reply_ptr)
+					*reply_ptr = '\0';
+			} else reply_parse = reply_ptr;
+		}
+		return (n - '0');
+	}
+}
+
+static int empty(fd_set *mask, int sec)
+{
+	struct timeval t;
+
+	t.tv_sec = (long) sec;
+	t.tv_usec = 0;
+	return(select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
+}
+
+jmp_buf	sendabort;
+
+static sigtype
+abortsend(int sig)
+{
+
+	mflag = 0;
+	abrtflag = 0;
+	printf("\nsend aborted\nwaiting for remote to finish abort\n");
+	(void) fflush(stdout);
+	longjmp(sendabort, 1);
+}
+
+void secure_error(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	putc('\n', stderr);
+}
+
+#define HASHBYTES 1024
+
+void sendrequest(char *cmd, char *local, char *remote, int printnames)
+{
+	struct stat st;
+	struct timeval start, stop;
+	register int c, d;
+	FILE *volatile fin, *volatile dout = 0;
+	int (*volatile closefunc)();
+	volatile sig_t oldintr, oldintp;
+	volatile long bytes = 0, hashbytes = HASHBYTES;
+	char *volatile lmode;
+	unsigned char buf[FTP_BUFSIZ], *bufp;
+
+	if (verbose && printnames) {
+		if (local && *local != '-')
+			printf("local: %s ", local);
+		if (remote)
+			printf("remote: %s\n", remote);
+	}
+	if (proxy) {
+		proxtrans(cmd, local, remote);
+		return;
+	}
+	if (curtype != type)
+		changetype(type, 0);
+	closefunc = NULL;
+	oldintr = NULL;
+	oldintp = NULL;
+	lmode = "w";
+	if (setjmp(sendabort)) {
+		while (cpend) {
+			(void) getreply(0);
+		}
+		if (data != INVALID_SOCKET) {
+			(void) closesocket(data);
+			data = INVALID_SOCKET;
+		}
+		if (oldintr)
+			(void) signal(SIGINT,oldintr);
+#ifdef SIGPIPE
+		if (oldintp)
+			(void) signal(SIGPIPE,oldintp);
+#endif
+		code = -1;
+		return;
+	}
+	oldintr = signal(SIGINT, abortsend);
+	if (strcmp(local, "-") == 0)
+		fin = stdin;
+	else if (*local == '|') {
+#ifdef SIGPIPE
+		oldintp = signal(SIGPIPE,SIG_IGN);
+#endif
+		fin = popen(local + 1, "r");
+		if (fin == NULL) {
+			perror(local + 1);
+			(void) signal(SIGINT, oldintr);
+#ifdef SIGPIPE
+			(void) signal(SIGPIPE, oldintp);
+#endif
+			code = -1;
+			return;
+		}
+		closefunc = pclose;
+	} else {
+#ifdef _WIN32
+		if ((curtype == TYPE_I) || (curtype == TYPE_L))
+			fin = fopen(local, "rb");
+		else
+			fin = fopen(local, "rt");
+#else /* !_WIN32 */
+		fin = fopen(local, "r");
+#endif /* !_WIN32 */			
+		if (fin == NULL) {
+			fprintf(stderr, "local: %s: %s\n", local,
+				strerror(errno));
+			(void) signal(SIGINT, oldintr);
+			code = -1;
+			return;
+		}
+		closefunc = fclose;
+		if (fstat(fileno(fin), &st) < 0 ||
+		    (st.st_mode&S_IFMT) != S_IFREG) {
+			fprintf(stdout, "%s: not a plain file.\n", local);
+			(void) signal(SIGINT, oldintr);
+			fclose(fin);
+			code = -1;
+			return;
+		}
+	}
+	if (initconn()) {
+		(void) signal(SIGINT, oldintr);
+#ifdef SIGPIPE
+		if (oldintp)
+			(void) signal(SIGPIPE, oldintp);
+#endif
+		code = -1;
+		if (closefunc != NULL)
+			(*closefunc)(fin);
+		return;
+	}
+	if (setjmp(sendabort))
+		goto die;
+
+	if (restart_point &&
+	    (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
+		if (fseek(fin, (long) restart_point, 0) < 0) {
+			fprintf(stderr, "local: %s: %s\n", local,
+				strerror(errno));
+			restart_point = 0;
+			if (closefunc != NULL)
+				(*closefunc)(fin);
+			return;
+		}
+		if (command("REST %ld", (long) restart_point)
+			!= CONTINUE) {
+			restart_point = 0;
+			if (closefunc != NULL)
+				(*closefunc)(fin);
+			return;
+		}
+		restart_point = 0;
+		lmode = "r+w";
+	}
+	if (remote) {
+		if (command("%s %s", cmd, remote) != PRELIM) {
+			(void) signal(SIGINT, oldintr);
+#ifdef SIGPIPE
+			if (oldintp)
+				(void) signal(SIGPIPE, oldintp);
+#endif
+			if (closefunc != NULL)
+				(*closefunc)(fin);
+			return;
+		}
+	} else
+		if (command("%s", cmd) != PRELIM) {
+			(void) signal(SIGINT, oldintr);
+#ifdef SIGPIPE
+			if (oldintp)
+				(void) signal(SIGPIPE, oldintp);
+#endif
+			if (closefunc != NULL)
+				(*closefunc)(fin);
+			return;
+		}
+	dout = dataconn(lmode);
+	if (dout == NULL)
+		goto die;
+	(void) gettimeofday(&start, (struct timezone *)0);
+#ifdef SIGPIPE
+	oldintp = signal(SIGPIPE, SIG_IGN);
+#endif
+	switch (curtype) {
+
+	case TYPE_I:
+	case TYPE_L:
+		errno = d = 0;
+		while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
+			bytes += c;
+			for (bufp = buf; c > 0; c -= d, bufp += d)
+				if ((d = secure_write(fileno(dout), bufp, 
+						      (unsigned int) c)) <= 0)
+					break;
+			if (hash) {
+				while (bytes >= hashbytes) {
+					(void) putchar('#');
+					hashbytes += HASHBYTES;
+				}
+				(void) fflush(stdout);
+			}
+			if (d <= 0 ) 
+  break;
+		}
+		if (hash && bytes > 0) {
+			if (bytes < HASHBYTES)
+				(void) putchar('#');
+			(void) putchar('\n');
+			(void) fflush(stdout);
+		}
+		if (c < 0)
+			fprintf(stderr, "local: %s: %s\n", local,
+				strerror(errno));
+		if (d < 0 || (d = secure_flush(fileno(dout))) < 0) {
+			if (d == -1 && errno != EPIPE) 
+				perror("netout");
+			bytes = -1;
+		}
+		break;
+
+	case TYPE_A:
+		while ((c = getc(fin)) != EOF) {
+			if (c == '\n') {
+				while (hash && (bytes >= hashbytes)) {
+					(void) putchar('#');
+					(void) fflush(stdout);
+					hashbytes += HASHBYTES;
+				}
+				if (ferror(dout) ||
+				    secure_putc('\r', dout) < 0)
+					break;
+				bytes++;
+			}
+			if (secure_putc(c, dout) < 0)
+				break;
+			bytes++;
+	/*		if (c == '\r') {			  	*/
+	/*		(void)	putc('\0', dout);   this violates rfc */
+	/*			bytes++;				*/
+	/*		}                          			*/	
+		}
+		if (hash) {
+			if (bytes < hashbytes)
+				(void) putchar('#');
+			(void) putchar('\n');
+			(void) fflush(stdout);
+		}
+		if (ferror(fin))
+			fprintf(stderr, "local: %s: %s\n", local,
+				strerror(errno));
+		d = 0;
+		if (ferror(dout) || (d = secure_flush(fileno(dout))) < 0) {
+			if ((ferror(dout) || d == -1) && errno != EPIPE)
+				perror("netout");
+			bytes = -1;
+		}
+		break;
+	}
+	(void) gettimeofday(&stop, (struct timezone *)0);
+	if (closefunc != NULL)
+		(*closefunc)(fin);
+	(void) FCLOSE_SOCKET(dout);
+	dout = NULL;
+	(void) getreply(0);
+	(void) signal(SIGINT, oldintr);
+#ifdef SIGPIPE
+	if (oldintp)
+		(void) signal(SIGPIPE, oldintp);
+#endif
+	if (bytes > 0)
+		ptransfer("sent", bytes, &start, &stop);
+	return;
+die:
+	(void) gettimeofday(&stop, (struct timezone *)0);
+	(void) signal(SIGINT, oldintr);
+#ifdef SIGPIPE
+	if (oldintp)
+		(void) signal(SIGPIPE, oldintp);
+#endif
+	if (!cpend) {
+		code = -1;
+		return;
+	}
+	if (data != INVALID_SOCKET) {
+		(void) closesocket(data);
+		data = INVALID_SOCKET;
+	}
+	if (dout) {
+		(void) FCLOSE_SOCKET(dout);
+		dout = NULL;
+	}
+	(void) getreply(0);
+	code = -1;
+	if (closefunc != NULL && fin != NULL)
+		(*closefunc)(fin);
+	if (bytes > 0)
+		ptransfer("sent", bytes, &start, &stop);
+}
+
+jmp_buf	recvabort;
+
+static sigtype
+abortrecv(int sig)
+{
+
+	mflag = 0;
+	abrtflag = 0;
+	printf("\nreceive aborted\nwaiting for remote to finish abort\n");
+	(void) fflush(stdout);
+	longjmp(recvabort, 1);
+}
+
+void recvrequest(char *cmd, char *volatile local, char *remote, char *lmode,
+		 int printnames, int fnameonly)
+{
+	FILE *volatile fout, *volatile din = 0, *popen();
+	int (*volatile closefunc)(), pclose(), fclose();
+	volatile sig_t oldintr, oldintp;
+	volatile int is_retr, tcrflag, bare_lfs = 0;
+	static unsigned int bufsize;
+	static char *buf;
+	unsigned int blksize;
+	volatile long bytes = 0, hashbytes = HASHBYTES;
+	register int c, d;
+	struct timeval start, stop;
+#ifndef NOSTBLKSIZE
+	struct stat st;
+#endif
+	off_t lseek();
+
+	is_retr = strcmp(cmd, "RETR") == 0;
+	if (is_retr && verbose && printnames) {
+		if (local && *local != '-')
+			printf("local: %s ", local);
+		if (remote)
+			printf("remote: %s\n", remote);
+	}
+	if (proxy && is_retr) {
+		proxtrans(cmd, local, remote);
+		return;
+	}
+	closefunc = NULL;
+	oldintr = NULL;
+	oldintp = NULL;
+	tcrflag = !crflag && is_retr;
+	if (setjmp(recvabort)) {
+		while (cpend) {
+			(void) getreply(0);
+		}
+		if (data != INVALID_SOCKET) {
+			(void) closesocket(data);
+			data = INVALID_SOCKET;
+		}
+		if (oldintr)
+			(void) signal(SIGINT, oldintr);
+		code = -1;
+		return;
+	}
+	oldintr = signal(SIGINT, abortrecv);
+	if (fnameonly || (strcmp(local, "-") && *local != '|')) {
+		if (access(local, 2) < 0) {
+			char *dir = strrchr(local, '/');
+
+			if (errno != ENOENT && errno != EACCES) {
+				fprintf(stderr, "local: %s: %s\n", local,
+					strerror(errno));
+				(void) signal(SIGINT, oldintr);
+				code = -1;
+				return;
+			}
+			if (dir != NULL)
+				*dir = 0;
+			d = access(dir ? local : ".", 2);
+			if (dir != NULL)
+				*dir = '/';
+			if (d < 0) {
+				fprintf(stderr, "local: %s: %s\n", local,
+					strerror(errno));
+				(void) signal(SIGINT, oldintr);
+				code = -1;
+				return;
+			}
+			if (!runique && errno == EACCES &&
+			    chmod(local, 0600) < 0) {
+				fprintf(stderr, "local: %s: %s\n", local,
+					strerror(errno));
+				(void) signal(SIGINT, oldintr);
+				(void) signal(SIGINT, oldintr);
+				code = -1;
+				return;
+			}
+			if (runique && errno == EACCES &&
+			   (local = gunique(local)) == NULL) {
+				(void) signal(SIGINT, oldintr);
+				code = -1;
+				return;
+			}
+		}
+		else if (runique && (local = gunique(local)) == NULL) {
+			(void) signal(SIGINT, oldintr);
+			code = -1;
+			return;
+		}
+	}
+	if (!is_retr) {
+		if (curtype != TYPE_A)
+			changetype(TYPE_A, 0);
+	} else if (curtype != type)
+		changetype(type, 0);
+	if (initconn()) {
+		(void) signal(SIGINT, oldintr);
+		code = -1;
+		return;
+	}
+	if (setjmp(recvabort))
+		goto die;
+	if (is_retr && restart_point &&
+	    command("REST %ld", (long) restart_point) != CONTINUE)
+		return;
+	if (remote) {
+		if (command("%s %s", cmd, remote) != PRELIM) {
+			(void) signal(SIGINT, oldintr);
+			return;
+		}
+	} else {
+		if (command("%s", cmd) != PRELIM) {
+			(void) signal(SIGINT, oldintr);
+			return;
+		}
+	}
+	din = dataconn("r");
+	if (din == NULL)
+		goto die;
+	if (strcmp(local, "-") == 0 && !fnameonly)
+		fout = stdout;
+	else if (*local == '|' && !fnameonly) {
+#ifdef SIGPIPE
+		oldintp = signal(SIGPIPE, SIG_IGN);
+#endif
+		fout = popen(local + 1, "w");
+		if (fout == NULL) {
+			perror(local+1);
+			goto die;
+		}
+		closefunc = pclose;
+	} else {
+#ifdef _WIN32
+		int old_fmode = _fmode;
+
+		if ((curtype == TYPE_I) || (curtype == TYPE_L))
+			_fmode = _O_BINARY;
+#endif /* _WIN32 */
+		fout = fopen(local, lmode);
+#ifdef _WIN32
+		_fmode = old_fmode;
+#endif
+		if (fout == NULL) {
+			fprintf(stderr, "local: %s: %s\n", local,
+				strerror(errno));
+			goto die;
+		}
+		closefunc = fclose;
+	}
+	blksize = FTP_BUFSIZ;
+#ifndef NOSTBLKSIZE
+	if (fstat(fileno(fout), &st) == 0 && st.st_blksize != 0)
+		blksize = st.st_blksize;
+#endif
+	if (blksize > bufsize) {
+		if (buf)
+			(void) free(buf);
+		buf = (char *)malloc((unsigned)blksize);
+		if (buf == NULL) {
+			perror("malloc");
+			bufsize = 0;
+			goto die;
+		}
+		bufsize = blksize;
+	}
+	(void) gettimeofday(&start, (struct timezone *)0);
+	switch (curtype) {
+
+	case TYPE_I:
+	case TYPE_L:
+		if (restart_point &&
+		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
+			fprintf(stderr, "local: %s: %s\n", local,
+				strerror(errno));
+			if (closefunc != NULL)
+				(*closefunc)(fout);
+			return;
+		}
+		errno = d = 0;
+		while ((c = secure_read(fileno(din), buf, bufsize)) > 0) {
+		        d = write(fileno(fout), buf,(unsigned int) c);
+			if (d != c)
+				break;
+			bytes += c;
+			if (hash) {
+				while (bytes >= hashbytes) {
+					(void) putchar('#');
+					hashbytes += HASHBYTES;
+				}
+				(void) fflush(stdout);
+			}
+		}
+		if (hash && bytes > 0) {
+			if (bytes < HASHBYTES)
+				(void) putchar('#');
+			(void) putchar('\n');
+			(void) fflush(stdout);
+		}
+		if (c < 0) {
+			if (c == -1 && errno != EPIPE)
+				perror("netin");
+			bytes = -1;
+		}
+		if (d < c) {
+			if (d < 0)
+				fprintf(stderr, "local: %s: %s\n", local,
+					strerror(errno));
+			else
+				fprintf(stderr, "%s: short write\n", local);
+		}
+		break;
+
+	case TYPE_A:
+		if (restart_point) {
+			register int i, n, ch;
+
+			if (fseek(fout, 0L, L_SET) < 0)
+				goto done;
+			n = restart_point;
+			for (i = 0; i++ < n;) {
+				if ((ch = getc(fout)) == EOF)
+					goto done;
+				if (ch == '\n')
+					i++;
+			}
+			if (fseek(fout, 0L, L_INCR) < 0) {
+done:
+				fprintf(stderr, "local: %s: %s\n", local,
+					strerror(errno));
+				if (closefunc != NULL)
+					(*closefunc)(fout);
+				return;
+			}
+		}
+		while ((c = secure_getc(din)) >= 0) {
+			if (c == '\n')
+				bare_lfs++;
+			while (c == '\r') {
+				while (hash && (bytes >= hashbytes)) {
+					(void) putchar('#');
+					(void) fflush(stdout);
+					hashbytes += HASHBYTES;
+				}
+				bytes++;
+				if ((c = secure_getc(din)) != '\n' || tcrflag) {
+					if (ferror(fout))
+						goto break2;
+					(void) putc('\r', fout);
+					if (c == '\0') {
+						bytes++;
+						goto contin2;
+					}
+				}
+			}
+			if (c < 0) break;
+			(void) putc(c, fout);
+			bytes++;
+	contin2:	;
+		}
+break2:
+		if (bare_lfs) {
+			printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
+			printf("File may not have transferred correctly.\n");
+		}
+		if (hash) {
+			if (bytes < hashbytes)
+				(void) putchar('#');
+			(void) putchar('\n');
+			(void) fflush(stdout);
+		}
+		if (ferror(din)) {
+			if (errno != EPIPE)
+				perror("netin");
+			bytes = -1;
+		}
+		if (ferror(fout) || c == -2) {
+		    if (c != -2)
+			fprintf(stderr, "local: %s: %s\n", local,
+				strerror(errno));
+			bytes = -1;
+		}
+		break;
+	}
+	if (closefunc != NULL)
+		(*closefunc)(fout);
+	(void) signal(SIGINT, oldintr);
+#ifdef SIGPIPE
+	if (oldintp)
+		(void) signal(SIGPIPE, oldintp);
+#endif
+	(void) gettimeofday(&stop, (struct timezone *)0);
+	(void) FCLOSE_SOCKET(din);
+	din = NULL;
+	(void) getreply(0);
+	if (bytes > 0 && is_retr)
+		ptransfer("received", bytes, &start, &stop);
+	return;
+die:
+
+/* abort using RFC959 recommended IP,SYNC sequence  */
+
+	(void) gettimeofday(&stop, (struct timezone *)0);
+#ifdef SIGPIPE
+	if (oldintp)
+		(void) signal(SIGPIPE, oldintr);
+#endif
+	(void) signal(SIGINT, SIG_IGN);
+	if (!cpend) {
+		code = -1;
+		(void) signal(SIGINT, oldintr);
+		return;
+	}
+
+	abort_remote(din);
+	code = -1;
+	if (data != INVALID_SOCKET) {
+		(void) closesocket(data);
+		data = INVALID_SOCKET;
+	}
+	if (closefunc != NULL && fout != NULL)
+		(*closefunc)(fout);
+	if (din) {
+		(void) FCLOSE_SOCKET(din);
+		din = NULL;
+	}
+	if (bytes > 0)
+		ptransfer("received", bytes, &start, &stop);
+	(void) signal(SIGINT, oldintr);
+}
+
+/*
+ * Need to start a listen on the data channel before we send the command,
+ * otherwise the server's connect may fail.
+ */
+static int initconn()
+{
+	register char *p, *a;
+	int result, tmpno = 0;
+	socklen_t len;
+	int on = 1;
+#ifndef NO_PASSIVE_MODE
+	int a1,a2,a3,a4,p1,p2;
+
+	if (passivemode) {
+		data = socket(AF_INET, SOCK_STREAM, 0);
+		if (data == INVALID_SOCKET) {
+			PERROR_SOCKET("ftp: socket");
+			return(1);
+		}
+		if (options & SO_DEBUG &&
+		    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) == SOCKET_ERROR)
+			PERROR_SOCKET("ftp: setsockopt (ignored)");
+		if (command("PASV") != COMPLETE) {
+			printf("Passive mode refused.  Turning off passive mode.\n");
+			passivemode = 0;
+			return initconn();
+		}
+
+/*
+ * What we've got at this point is a string of comma separated
+ * one-byte unsigned integer values, separated by commas.
+ * The first four are the an IP address. The fifth is the MSB
+ * of the port number, the sixth is the LSB. From that we'll
+ * prepare a sockaddr_in.
+ */
+
+		if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2) != 6) {
+			printf("Passive mode address scan failure. Shouldn't happen!\n");
+			return(1);
+		};
+
+		data_addr.sin_family = AF_INET;
+		data_addr.sin_addr.s_addr = htonl((a1<<24)|(a2<<16)|(a3<<8)|a4);
+		data_addr.sin_port = htons((p1<<8)|p2);
+
+		if (connect(data, (struct sockaddr *) &data_addr, sizeof(data_addr)) == SOCKET_ERROR) {
+			PERROR_SOCKET("ftp: connect");
+			return(1);
+		}
+#ifdef IP_TOS
+#ifdef IPTOS_THROUGHPUT
+	on = IPTOS_THROUGHPUT;
+	if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) == SOCKET_ERROR)
+		PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
+#endif
+#endif
+		hisdataaddr = data_addr;
+		return(0);
+	}
+#endif
+
+noport:
+	data_addr = myctladdr;
+	if (sendport)
+		data_addr.sin_port = 0;	/* let system pick one */ 
+	if (data != INVALID_SOCKET)
+		(void) closesocket(data);
+	data = socket(AF_INET, SOCK_STREAM, 0);
+	if (data == INVALID_SOCKET) {
+		PERROR_SOCKET("ftp: socket");
+		if (tmpno)
+			sendport = 1;
+		return (1);
+	}
+	if (!sendport)
+		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) == SOCKET_ERROR) {
+			PERROR_SOCKET("ftp: setsockopt (reuse address)");
+			goto bad;
+		}
+	if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) == SOCKET_ERROR) {
+		PERROR_SOCKET("ftp: bind");
+		goto bad;
+	}
+	if (options & SO_DEBUG &&
+	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) == SOCKET_ERROR)
+		PERROR_SOCKET("ftp: setsockopt (ignored)");
+	len = sizeof (data_addr);
+	if (getsockname(data, (struct sockaddr *)&data_addr, &len) == SOCKET_ERROR) {
+		PERROR_SOCKET("ftp: getsockname");
+		goto bad;
+	}
+	if (listen(data, 1) == SOCKET_ERROR)
+		PERROR_SOCKET("ftp: listen");
+	if (sendport) {
+		a = (char *)&data_addr.sin_addr;
+		p = (char *)&data_addr.sin_port;
+#define	UC(b)	(((int)b)&0xff)
+		result =
+		    command("PORT %d,%d,%d,%d,%d,%d",
+		      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
+		      UC(p[0]), UC(p[1]));
+		if (result == ERROR && sendport == -1) {
+			sendport = 0;
+			tmpno = 1;
+			goto noport;
+		}
+		return (result != COMPLETE);
+	}
+	if (tmpno)
+		sendport = 1;
+#ifdef IP_TOS
+#ifdef IPTOS_THROUGHPUT
+	on = IPTOS_THROUGHPUT;
+	if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) == SOCKET_ERROR)
+		PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
+#endif
+#endif
+	return (0);
+bad:
+	(void) closesocket(data), data = INVALID_SOCKET;
+	if (tmpno)
+		sendport = 1;
+	return (1);
+}
+
+FILE *
+dataconn(char *lmode)
+{
+	int s;
+	socklen_t fromlen = sizeof (hisdataaddr);
+#ifdef IP_TOS
+#ifdef IPTOS_LOWDELAY
+        int tos;
+#endif
+#endif
+
+#ifndef NO_PASSIVE_MODE
+	if (passivemode)
+		return (FDOPEN_SOCKET(data, lmode));
+#endif
+	s = accept(data, (struct sockaddr *) &hisdataaddr, &fromlen);
+	if (s == INVALID_SOCKET) {
+		PERROR_SOCKET("ftp: accept");
+		(void) closesocket(data), data = INVALID_SOCKET;
+		return (NULL);
+	}
+	(void) closesocket(data);
+	data = s;
+#ifdef IP_TOS
+#ifdef IPTOS_THROUGHPUT
+	tos = IPTOS_THROUGHPUT;
+	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) == SOCKET_ERROR)
+		PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
+#endif
+#endif
+	return (FDOPEN_SOCKET(data, lmode));
+}
+
+static void ptransfer(char *direction, long bytes,
+		      struct timeval *t0, struct timeval *t1)
+{
+	struct timeval td;
+	float s, kbs;
+
+	if (verbose) {
+		tvsub(&td, t1, t0);
+		s = td.tv_sec + (td.tv_usec / 1000000.);
+#define	nz(x)	((x) == 0 ? 1 : (x))
+		kbs = (bytes / nz(s))/1024.0;
+		printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
+		    bytes, direction, s, kbs);
+	}
+}
+
+/*tvadd(tsum, t0)
+	struct timeval *tsum, *t0;
+{
+
+	tsum->tv_sec += t0->tv_sec;
+	tsum->tv_usec += t0->tv_usec;
+	if (tsum->tv_usec > 1000000)
+		tsum->tv_sec++, tsum->tv_usec -= 1000000;
+} */
+
+static void tvsub(struct timeval *tdiff, struct timeval *t1,
+		  struct timeval *t0)
+{
+
+	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+	if (tdiff->tv_usec < 0)
+		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
+}
+
+static sigtype
+psabort(int sig)
+{
+	abrtflag++;
+}
+
+void pswitch(int flag)
+{
+	sig_t oldintr;
+	static struct comvars {
+		int connect;
+		char name[MAXHOSTNAMELEN];
+		struct sockaddr_in mctl;
+		struct sockaddr_in hctl;
+		FILE *in;
+		FILE *out;
+		int tpe;
+		int curtpe;
+		int cpnd;
+		int sunqe;
+		int runqe;
+		int mcse;
+		int ntflg;
+		char nti[17];
+		char nto[17];
+		int mapflg;
+		char mi[MAXPATHLEN];
+		char mo[MAXPATHLEN];
+		char *authtype;
+		int clvl;
+	        int dlvl;
+#ifdef KRB5_KRB4_COMPAT
+		C_Block session;
+		Key_schedule schedule;
+#endif /* KRB5_KRB4_COMPAT */
+	} proxstruct, tmpstruct;
+	struct comvars *ip, *op;
+
+	abrtflag = 0;
+	oldintr = signal(SIGINT, psabort);
+	if (flag) {
+		if (proxy)
+			return;
+		ip = &tmpstruct;
+		op = &proxstruct;
+		proxy++;
+	} else {
+		if (!proxy)
+			return;
+		ip = &proxstruct;
+		op = &tmpstruct;
+		proxy = 0;
+	}
+	ip->connect = connected;
+	connected = op->connect;
+	if (hostname) {
+		if (ip->name != hostname)
+			(void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
+		ip->name[strlen(ip->name)] = '\0';
+	} else
+		ip->name[0] = 0;
+	hostname = op->name;
+	ip->hctl = hisctladdr;
+	hisctladdr = op->hctl;
+	ip->mctl = myctladdr;
+	myctladdr = op->mctl;
+	ip->in = cin;
+	cin = op->in;
+	ip->out = cout;
+	cout = op->out;
+	ip->tpe = type;
+	type = op->tpe;
+	ip->curtpe = curtype;
+	curtype = op->curtpe;
+	ip->cpnd = cpend;
+	cpend = op->cpnd;
+	ip->sunqe = sunique;
+	sunique = op->sunqe;
+	ip->runqe = runique;
+	runique = op->runqe;
+	ip->mcse = mcase;
+	mcase = op->mcse;
+	ip->ntflg = ntflag;
+	ntflag = op->ntflg;
+	(void) strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
+	(ip->nti)[strlen(ip->nti)] = '\0';
+	(void) strncpy(ntin, op->nti, sizeof(ntin) - 1);
+	ntin[sizeof(ntin) - 1] = '\0';
+	(void) strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
+	(ip->nto)[strlen(ip->nto)] = '\0';
+	(void) strncpy(ntout, op->nto, sizeof(ntout) - 1);
+	ntout[sizeof(ntout) - 1] = '\0';
+	ip->mapflg = mapflag;
+	mapflag = op->mapflg;
+	(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
+	(ip->mi)[strlen(ip->mi)] = '\0';
+	(void) strncpy(mapin, op->mi, sizeof(mapin) - 1);
+	mapin[sizeof(mapin) - 1] = '\0';
+	(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
+	(ip->mo)[strlen(ip->mo)] = '\0';
+	(void) strncpy(mapout, op->mo, sizeof(mapout) - 1);
+	mapout[sizeof(mapout) - 1] = '\0';
+	ip->authtype = auth_type;
+	auth_type = op->authtype;
+	ip->clvl = clevel;
+	clevel = op->clvl;
+	ip->dlvl = dlevel;
+	dlevel = op->dlvl;
+	if (!clevel)
+	     clevel = PROT_C;
+	if (!dlevel)
+	     dlevel = PROT_C;
+#ifdef KRB5_KRB4_COMPAT
+	memcpy(ip->session, cred.session, sizeof(cred.session));
+	memcpy(cred.session, op->session, sizeof(cred.session));
+	memcpy(ip->schedule, schedule, sizeof(schedule));
+	memcpy(schedule, op->schedule, sizeof(schedule));
+#endif /* KRB5_KRB4_COMPAT */
+	(void) signal(SIGINT, oldintr);
+	if (abrtflag) {
+		abrtflag = 0;
+		if (oldintr)
+			(*oldintr)(SIGINT);
+	}
+}
+
+int ptabflg;
+
+static sigtype
+abortpt(int sig)
+{
+	printf("\n");
+	(void) fflush(stdout);
+	ptabflg++;
+	mflag = 0;
+	abrtflag = 0;
+	longjmp(ptabort, 1);
+}
+
+static void
+proxtrans(char *cmd, char *local, char *remote)
+{
+	volatile sig_t oldintr;
+	volatile int secndflag = 0;
+	int prox_type, nfnd;
+	char *volatile cmd2;
+	 fd_set mask;
+
+	if (strcmp(cmd, "RETR"))
+		cmd2 = "RETR";
+	else
+		cmd2 = runique ? "STOU" : "STOR";
+	if ((prox_type = type) == 0) {
+		if (unix_server && unix_proxy)
+			prox_type = TYPE_I;
+		else
+			prox_type = TYPE_A;
+	}
+	if (curtype != prox_type)
+		changetype(prox_type, 1);
+	if (command("PASV") != COMPLETE) {
+		printf("proxy server does not support third party transfers.\n");
+		return;
+	}
+	pswitch(0);
+	if (!connected) {
+		printf("No primary connection\n");
+		pswitch(1);
+		code = -1;
+		return;
+	}
+	if (curtype != prox_type)
+		changetype(prox_type, 1);
+	if (command("PORT %s", pasv) != COMPLETE) {
+		pswitch(1);
+		return;
+	}
+	if (setjmp(ptabort))
+		goto die;
+	oldintr = signal(SIGINT, abortpt);
+	if (command("%s %s", cmd, remote) != PRELIM) {
+		(void) signal(SIGINT, oldintr);
+		pswitch(1);
+		return;
+	}
+	sleep(2);
+	pswitch(1);
+	secndflag++;
+	if (command("%s %s", cmd2, local) != PRELIM)
+		goto die;
+	ptflag++;
+	(void) getreply(0);
+	pswitch(0);
+	(void) getreply(0);
+	(void) signal(SIGINT, oldintr);
+	pswitch(1);
+	ptflag = 0;
+	printf("local: %s remote: %s\n", local, remote);
+	return;
+die:
+	(void) signal(SIGINT, SIG_IGN);
+	ptflag = 0;
+	if (strcmp(cmd, "RETR") && !proxy)
+		pswitch(1);
+	else if (!strcmp(cmd, "RETR") && proxy)
+		pswitch(0);
+	if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
+		if (command("%s %s", cmd2, local) != PRELIM) {
+			pswitch(0);
+			if (cpend)
+				abort_remote((FILE *) NULL);
+		}
+		pswitch(1);
+		if (ptabflg)
+			code = -1;
+		(void) signal(SIGINT, oldintr);
+		return;
+	}
+	if (cpend)
+		abort_remote((FILE *) NULL);
+	pswitch(!proxy);
+	if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
+		if (command("%s %s", cmd2, local) != PRELIM) {
+			pswitch(0);
+			if (cpend)
+				abort_remote((FILE *) NULL);
+			pswitch(1);
+			if (ptabflg)
+				code = -1;
+			(void) signal(SIGINT, oldintr);
+			return;
+		}
+	}
+	if (cpend)
+		abort_remote((FILE *) NULL);
+	pswitch(!proxy);
+	if (cpend) {
+		FD_ZERO(&mask);
+		FD_SET(SOCKETNO(fileno(cin)), &mask);
+		if ((nfnd = empty(&mask, 10)) <= 0) {
+			if (nfnd < 0) {
+				perror("abort");
+			}
+			if (ptabflg)
+				code = -1;
+			lostpeer();
+		}
+		(void) getreply(0);
+		(void) getreply(0);
+	}
+	if (proxy)
+		pswitch(0);
+	pswitch(1);
+	if (ptabflg)
+		code = -1;
+	(void) signal(SIGINT, oldintr);
+}
+
+void reset()
+{
+   fd_set mask;
+	int nfnd = 1;
+
+	FD_ZERO(&mask);
+	while (nfnd > 0) {
+		FD_SET(SOCKETNO(fileno(cin)), &mask);
+		if ((nfnd = empty(&mask,0)) < 0) {
+			perror("reset");
+			code = -1;
+			lostpeer();
+		}
+		else if (nfnd) {
+			(void) getreply(0);
+		}
+	}
+}
+
+static char *
+gunique(char *local)
+{
+	static char new[MAXPATHLEN];
+	char *cp = strrchr(local, '/');
+	int d, count=0;
+	char ext = '1';
+
+	if (cp)
+		*cp = '\0';
+	d = access(cp ? local : ".", 2);
+	if (cp)
+		*cp = '/';
+	if (d < 0) {
+		fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
+		return((char *) 0);
+	}
+	(void) strncpy(new, local, sizeof(new) - 3);
+	new[sizeof(new) - 1] = '\0';
+	cp = new + strlen(new);
+	*cp++ = '.';
+	while (!d) {
+		if (++count == 100) {
+			printf("runique: can't find unique file name.\n");
+			return((char *) 0);
+		}
+		*cp++ = ext;
+		*cp = '\0';
+		if (ext == '9')
+			ext = '0';
+		else
+			ext++;
+		if ((d = access(new, 0)) < 0)
+			break;
+		if (ext != '0')
+			cp--;
+		else if (*(cp - 2) == '.')
+			*(cp - 1) = '1';
+		else {
+			*(cp - 2) = *(cp - 2) + 1;
+			cp--;
+		}
+	}
+	return(new);
+}
+
+#ifdef KRB5_KRB4_COMPAT
+char realm[REALM_SZ + 1];
+#endif /* KRB5_KRB4_COMPAT */
+
+#ifdef GSSAPI
+struct {
+    gss_OID mech_type;
+    char *service_name;
+} gss_trials[] = {
+    { GSS_C_NO_OID, "ftp" },
+    { GSS_C_NO_OID, "host" },
+};
+int n_gss_trials = sizeof(gss_trials)/sizeof(gss_trials[0]);
+#endif /* GSSAPI */
+
+int do_auth()
+{
+	int oldverbose = verbose;
+#ifdef KRB5_KRB4_COMPAT
+	char *service, inst[INST_SZ];
+	KRB4_32 cksum, checksum = getpid();
+#endif /* KRB5_KRB4_COMPAT */
+#if defined(KRB5_KRB4_COMPAT) || defined(GSSAPI)
+	u_char out_buf[FTP_BUFSIZ];
+	int i;
+#endif /* KRB5_KRB4_COMPAT */
+
+	if (auth_type) return(1);	/* auth already succeeded */
+
+	/* Other auth types go here ... */
+
+#ifdef GSSAPI
+	if (command("AUTH %s", "GSSAPI") == CONTINUE) {
+	  OM_uint32 maj_stat, min_stat, dummy_stat;
+	  gss_name_t target_name;
+	  gss_buffer_desc send_tok, recv_tok, *token_ptr;
+	  char stbuf[FTP_BUFSIZ];
+	  int comcode, trial;
+	  struct gss_channel_bindings_struct chan;
+	  chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */ 
+	  chan.initiator_address.length = 4;
+	  chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
+	  chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
+	  chan.acceptor_address.length = 4;
+	  chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
+	  chan.application_data.length = 0;
+	  chan.application_data.value = 0;
+
+	  if (verbose)
+	    printf("GSSAPI accepted as authentication type\n");
+	  
+	  /* blob from gss-client */
+	  
+	  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", gss_trials[trial].service_name, hostname);
+	    if (debug)
+	      fprintf(stderr, "Trying to authenticate to <%s>\n", stbuf);
+
+	    send_tok.value = stbuf;
+	    send_tok.length = strlen(stbuf) + 1;
+	    maj_stat = gss_import_name(&min_stat, &send_tok,
+				       gss_nt_service_name, &target_name);
+	    
+	    if (maj_stat != GSS_S_COMPLETE) {
+		    user_gss_error(maj_stat, min_stat, "parsing name");
+		    secure_error("name parsed <%s>\n", stbuf);
+		    continue;
+	    }
+
+	    token_ptr = GSS_C_NO_BUFFER;
+	    gcontext = GSS_C_NO_CONTEXT; /* structure copy */
+	    
+	    do {
+	      if (debug)
+		fprintf(stderr, "calling gss_init_sec_context\n");
+	      maj_stat =
+		gss_init_sec_context(&min_stat,
+				     GSS_C_NO_CREDENTIAL,
+				     &gcontext,
+				     target_name,
+				     (gss_OID_desc *)gss_trials[trial].mech_type,
+				     GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
+				       (forward ? GSS_C_DELEG_FLAG : 
+					(unsigned) 0),
+				     0,
+				     &chan,	/* channel bindings */
+				     token_ptr,
+				     NULL,	/* ignore mech type */
+				     &send_tok,
+				     NULL,	/* ignore ret_flags */
+				     NULL);	/* ignore time_rec */
+	      
+
+	      if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED){
+		if (trial == n_gss_trials-1)
+		  user_gss_error(maj_stat, min_stat, "initializing context");
+		/* could just be that we missed on the service name */
+		goto outer_loop;
+	      }
+	    
+	      if (send_tok.length != 0) {
+		int len = send_tok.length;
+		reply_parse = "ADAT="; /* for command() later */
+		oldverbose = verbose;
+		verbose = (trial == n_gss_trials-1)?0:-1;
+		kerror = radix_encode(send_tok.value, out_buf, &len, 0);
+		gss_release_buffer(&dummy_stat, &send_tok);
+		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) */) {
+		    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");
+		  if (maj_stat == GSS_S_COMPLETE) {
+		    fprintf(stderr, "...but no more was needed\n");
+		    goto gss_complete_loop;
+		  } else {
+		    user_gss_error(maj_stat, min_stat, "no reply, huh?");
+		    goto gss_complete_loop;
+		  }
+		} else if ((kerror = radix_encode((unsigned char *)reply_parse,
+						  out_buf,&i,1))) {
+		  fprintf(stderr, "Base 64 decoding failed: %s\n",
+			  radix_error(kerror));
+		} else {
+		  /* everything worked */
+		  token_ptr = &recv_tok;
+		  recv_tok.value = out_buf;
+		  recv_tok.length = i;
+		  continue;
+		}
+
+		/* get out of loop clean */
+	      gss_complete_loop:
+		trial = n_gss_trials-1;
+		goto outer_loop;
+	      }
+	    } while (maj_stat == GSS_S_CONTINUE_NEEDED);
+    outer_loop:
+	    gss_release_name(&dummy_stat, &target_name);
+	    if (maj_stat == GSS_S_COMPLETE)
+	        break;
+	  }
+	  verbose = oldverbose;
+	  if (maj_stat == GSS_S_COMPLETE) {
+	    printf("GSSAPI authentication succeeded\n");
+	    reply_parse = NULL;
+	    auth_type = "GSSAPI";
+	    return(1);
+	  } else {
+	    fprintf(stderr, "GSSAPI authentication failed\n");
+	    verbose = oldverbose;
+	    reply_parse = NULL;
+	  }
+	}
+#endif /* GSSAPI */
+#ifdef KRB5_KRB4_COMPAT
+	if (command("AUTH %s", "KERBEROS_V4") == CONTINUE) {
+	    if (verbose)
+		printf("%s accepted as authentication type\n", "KERBEROS_V4");
+
+	    strncpy(inst, (char *) krb_get_phost(hostname), sizeof(inst) - 1);
+	    inst[sizeof(inst) - 1] = '\0';
+	    if (realm[0] == '\0')
+	    	strncpy(realm, (char *) krb_realmofhost(hostname), sizeof(realm) - 1);
+	    realm[sizeof(realm) - 1] = '\0';
+	    if ((kerror = krb_mk_req(&ticket, service = "ftp",
+					inst, realm, checksum))
+		&& (kerror != KDC_PR_UNKNOWN ||
+	        (kerror = krb_mk_req(&ticket, service = "rcmd",
+					inst, realm, checksum))))
+			fprintf(stderr, "Kerberos V4 krb_mk_req failed: %s\n",
+					krb_get_err_text(kerror));
+	    else if ((kerror = krb_get_cred(service, inst, realm, &cred)))
+			fprintf(stderr, "Kerberos V4 krb_get_cred failed: %s\n",
+					krb_get_err_text(kerror));
+	    else {
+		key_sched(cred.session, schedule);
+		reply_parse = "ADAT=";
+		oldverbose = verbose;
+		verbose = 0;
+		i = ticket.length;
+		if ((kerror = radix_encode(ticket.dat, out_buf, &i, 0)))
+			fprintf(stderr, "Base 64 encoding failed: %s\n",
+					radix_error(kerror));
+		else if (command("ADAT %s", out_buf) != COMPLETE)
+			fprintf(stderr, "Kerberos V4 authentication failed\n");
+		else if (!reply_parse)
+			fprintf(stderr,
+			       "No authentication data received from server\n");
+		else if ((kerror = radix_encode((unsigned char *)reply_parse, out_buf, &i, 1)))
+			fprintf(stderr, "Base 64 decoding failed: %s\n",
+					radix_error(kerror));
+		else if ((kerror = krb_rd_safe(out_buf, (unsigned )i,
+					       &cred.session,
+					       &hisctladdr, &myctladdr, 
+					       &msg_data)))
+			fprintf(stderr, "Kerberos V4 krb_rd_safe failed: %s\n",
+					krb_get_err_text(kerror));
+		else {
+		    /* fetch the (modified) checksum */
+		    (void) memcpy(&cksum, msg_data.app_data, sizeof(cksum));
+		    if (ntohl(cksum) == checksum + 1) {
+			verbose = oldverbose;
+			if (verbose)
+			   printf("Kerberos V4 authentication succeeded\n");
+			reply_parse = NULL;
+			auth_type = "KERBEROS_V4";
+			return(1);
+		    } else fprintf(stderr,
+				"Kerberos V4 mutual authentication failed\n");
+		}
+		verbose = oldverbose;
+		reply_parse = NULL;
+	    }
+	} else	fprintf(stderr, "%s rejected as an authentication type\n",
+				"KERBEROS_V4");
+#endif /* KRB5_KRB4_COMPAT */
+
+	/* Other auth types go here ... */
+
+	return(0);
+}
+
+void
+setpbsz(unsigned int size)
+{
+	int oldverbose;
+
+	if (ucbuf) (void) free(ucbuf);
+	actualbuf = size;
+	while ((ucbuf = (unsigned char *)malloc(actualbuf)) == NULL)
+		if (actualbuf)
+			actualbuf >>= 2;
+		else {
+			perror("Error while trying to malloc PROT buffer:");
+			exit(1);
+		}
+	oldverbose = verbose;
+	verbose = 0;
+	reply_parse = "PBSZ=";
+	if (command("PBSZ %u", actualbuf) != COMPLETE)
+		fatal("Cannot set PROT buffer size");
+	if (reply_parse) {
+		if ((maxbuf = (unsigned int) atol(reply_parse)) > actualbuf)
+			maxbuf = actualbuf;
+	} else	maxbuf = actualbuf;
+	reply_parse = NULL;
+	verbose = oldverbose;
+}
+
+static void abort_remote(FILE *din)
+{
+	char buf[FTP_BUFSIZ];
+	int nfnd;
+	fd_set mask;
+
+	/*
+	 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
+	 * after urgent byte rather than before as is protocol now
+	 */
+	sprintf(buf, "%c%c%c", IAC, IP, IAC);
+	if (send(SOCKETNO(fileno(cout)), buf, 3, MSG_OOB) != 3)
+		PERROR_SOCKET("abort");
+	putc(DM, cout);
+	(void) secure_command("ABOR");
+	FD_ZERO(&mask);
+	FD_SET(SOCKETNO(fileno(cin)), &mask);
+	if (din) { 
+		FD_SET(SOCKETNO(fileno(din)), &mask);
+	}
+	if ((nfnd = empty(&mask, 10)) <= 0) {
+		if (nfnd < 0) {
+			perror("abort");
+		}
+		if (ptabflg)
+			code = -1;
+		lostpeer();
+	}
+	if (din && FD_ISSET(SOCKETNO(fileno(din)), &mask)) {
+		/* Security: No threat associated with this read. */
+		while (read(fileno(din), buf, FTP_BUFSIZ) > 0)
+			/* LOOP */;
+	}
+	if (getreply(0) == ERROR && code == 552) {
+		/* 552 needed for nic style abort */
+		(void) getreply(0);
+	}
+	(void) getreply(0);
+}
+
+#ifdef GSSAPI
+void user_gss_error(OM_uint32 maj_stat, OM_uint32 min_stat, char *s)
+{
+	/* a lot of work just to report the error */
+	OM_uint32 gmaj_stat, gmin_stat, msg_ctx;
+	gss_buffer_desc msg;
+	msg_ctx = 0;
+	while (!msg_ctx) {
+		gmaj_stat = gss_display_status(&gmin_stat, maj_stat,
+					       GSS_C_GSS_CODE,
+					       GSS_C_NULL_OID,
+					       &msg_ctx, &msg);
+		if ((gmaj_stat == GSS_S_COMPLETE)||
+		    (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
+			fprintf(stderr, "GSSAPI error major: %s\n",
+				(char*)msg.value);
+			(void) gss_release_buffer(&gmin_stat, &msg);
+		}
+		if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
+			break;
+	}
+	msg_ctx = 0;
+	while (!msg_ctx) {
+		gmaj_stat = gss_display_status(&gmin_stat, min_stat,
+					       GSS_C_MECH_CODE,
+					       GSS_C_NULL_OID,
+					       &msg_ctx, &msg);
+		if ((gmaj_stat == GSS_S_COMPLETE)||
+		    (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
+			fprintf(stderr, "GSSAPI error minor: %s\n",
+				(char*)msg.value);
+			(void) gss_release_buffer(&gmin_stat, &msg);
+		}
+		if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
+			break;
+	}
+	fprintf(stderr, "GSSAPI error: %s\n", s);
+}
+
+void secure_gss_error(OM_uint32 maj_stat, OM_uint32 min_stat, char *s)
+{
+  user_gss_error(maj_stat, min_stat, s);
+  return;
+}
+#endif /* GSSAPI */
+
+#ifdef _WIN32
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+	struct _timeb tb;
+	_tzset();
+	_ftime(&tb);
+	if (tv) {
+		tv->tv_sec = tb.time;
+		tv->tv_usec = tb.millitm * 1000;
+	}
+#if 0
+	if (tz) {
+		tz->tz_minuteswest = tb.timezone;
+		tz->tz_dsttime = tb.dstflag;
+	}
+#else
+	_ASSERTE(!tz);
+#endif
+	return 0;
+}
+
+int fclose_socket(FILE* f)
+{
+	int rc = 0;
+	SOCKET _s = _get_osfhandle(_fileno(f));
+
+	rc = fclose(f);
+	if (rc)
+		return rc;
+	if (closesocket(_s) == SOCKET_ERROR)
+		return SOCKET_ERRNO;
+	return 0;
+}
+
+FILE* fdopen_socket(SOCKET s, char* mode)
+{
+	int o_mode = 0;
+	int old_fmode = _fmode;
+	FILE* f = 0;
+
+	if (strstr(mode, "a+")) o_mode |= _O_RDWR | _O_APPEND;
+	if (strstr(mode, "r+")) o_mode |= _O_RDWR;
+	if (strstr(mode, "w+")) o_mode |= _O_RDWR;
+	if (strchr(mode, 'a')) o_mode |= _O_WRONLY | _O_APPEND;
+	if (strchr(mode, 'r')) o_mode |= _O_RDONLY;
+	if (strchr(mode, 'w')) o_mode |= _O_WRONLY;
+
+	/* In theory, _open_osfhandle only takes: _O_APPEND, _O_RDONLY, _O_TEXT */
+
+	_fmode = _O_BINARY;
+	f = fdopen(_open_osfhandle(s, o_mode), mode);
+	_fmode = old_fmode;
+
+	return f;
+}
+#endif /* _WIN32 */
diff --git a/krb5-1-6/src/appl/gssftp/ftp/ftp_var.h b/krb5-1-6/src/appl/gssftp/ftp/ftp_var.h
new file mode 100644
index 000000000..9baa04730
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/ftp_var.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ftp_var.h	5.9 (Berkeley) 6/1/90
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#ifdef _WIN32
+int fclose_socket(FILE* f);
+FILE* fdopen_socket(SOCKET s, char* mode);
+#define FCLOSE_SOCKET(f) fclose_socket(f)
+#define FDOPEN_SOCKET(s, mode) fdopen_socket(s, mode)
+#define SOCKETNO(fd) _get_osfhandle(fd)
+#define PERROR_SOCKET(str) do { errno = SOCKET_ERRNO; perror(str); } while(0)
+#else
+#define FCLOSE_SOCKET(f) fclose(f)
+#define FDOPEN_SOCKET(s, mode) fdopen(s, mode)
+#define SOCKETNO(fd) (fd)
+#define PERROR_SOCKET(str) perror(str)
+#endif
+
+#ifdef _WIN32
+typedef void (*sig_t)(int);
+typedef void sigtype;
+#else
+#define sig_t my_sig_t
+#define sigtype krb5_sigtype
+typedef sigtype (*sig_t)();
+#endif
+
+/*
+ * FTP global variables.
+ */
+
+#ifdef DEFINITIONS
+#define extern
+#endif
+
+/*
+ * Options and other state info.
+ */
+extern int	trace;		/* trace packets exchanged */
+extern int	hash;		/* print # for each buffer transferred */
+extern int	sendport;	/* use PORT cmd for each data connection */
+extern int	verbose;	/* print messages coming back from server */
+extern int	connected;	/* connected to server */
+extern int	fromatty;	/* input is from a terminal */
+extern int	interactive;	/* interactively prompt on m* cmds */
+extern int	debug;		/* debugging level */
+extern int	bell;		/* ring bell on cmd completion */
+extern int	doglob;		/* glob local file names */
+extern int autoauth;		/* Do authentication on connect */
+extern int	autologin;	/* establish user account on connection */
+extern int	autoencrypt;	/* negotiate encryption on connection */
+extern int	forward;	/* forward credentials */
+extern int	proxy;		/* proxy server connection active */
+extern int	proxflag;	/* proxy connection exists */
+extern int	sunique;	/* store files on server with unique name */
+extern int	runique;	/* store local files with unique name */
+extern int	mcase;		/* map upper to lower case for mget names */
+extern int	ntflag;		/* use ntin ntout tables for name translation */
+extern int	mapflag;	/* use mapin mapout templates on file names */
+extern int	code;		/* return/reply code for ftp command */
+extern int	crflag;		/* if 1, strip car. rets. on ascii gets */
+extern char	pasv[64];	/* passive port for proxy data connection */
+#ifndef NO_PASSIVE_MODE
+extern int	passivemode;	/* passive mode enabled */
+#endif
+extern char	*altarg;	/* argv[1] with no shell-like preprocessing  */
+extern char	ntin[17];	/* input translation table */
+extern char	ntout[17];	/* output translation table */
+#ifdef _WIN32
+#ifndef MAXPATHLEN
+#define MAXPATHLEN MAX_PATH
+#endif
+#else
+#include <sys/param.h>
+#endif
+extern char	mapin[MAXPATHLEN];	/* input map template */
+extern char	mapout[MAXPATHLEN];	/* output map template */
+extern int	clevel;		/* command channel protection level */
+extern int	dlevel;		/* data channel protection level */
+extern int	type;		/* requested file transfer type */
+extern int	curtype;	/* current file transfer type */
+extern int	stru;		/* file transfer structure */
+extern int	form;		/* file transfer format */
+extern int	mode;		/* file transfer mode */
+extern char	bytename[32];	/* local byte size in ascii */
+extern int	bytesize;	/* local byte size in binary */
+
+extern char	*hostname;	/* name of host connected to */
+extern int	unix_server;	/* server is unix, can use binary for ascii */
+extern int	unix_proxy;	/* proxy is unix, can use binary for ascii */
+
+extern struct	servent *sp;	/* service spec for tcp/ftp */
+
+#include <setjmp.h>
+extern jmp_buf	toplevel;	/* non-local goto stuff for cmd scanner */
+
+extern char	line[500];	/* input line buffer */
+extern char	*stringbase;	/* current scan point in line buffer */
+extern char	argbuf[500];	/* argument storage buffer */
+extern char	*argbase;	/* current storage point in arg buffer */
+extern int	margc;		/* count of arguments on input line */
+extern char	*margv[20];	/* args parsed from input line */
+extern int     cpend;           /* flag: if != 0, then pending server reply */
+extern int	mflag;		/* flag: if != 0, then active multi command */
+
+extern int	options;	/* used during socket creation */
+
+/*
+ * Format of command table.
+ */
+struct cmd {
+	char	*c_name;	/* name of command */
+	char	*c_help;	/* help string */
+	char	c_bell;		/* give bell when command completes */
+	char	c_conn;		/* must be connected to use command */
+	char	c_proxy;	/* proxy server may execute */
+	void	(*c_handler)();	/* function to call */
+};
+
+struct macel {
+	char mac_name[9];	/* macro name */
+	char *mac_start;	/* start of macro in macbuf */
+	char *mac_end;		/* end of macro in macbuf */
+};
+
+extern int macnum;		/* number of defined macros */
+extern struct macel macros[16];
+extern char macbuf[4096];
+
+#ifdef DEFINITIONS
+#undef extern
+#endif
+
+extern	char *tail();
+#ifndef _WIN32
+extern	char *mktemp();
+#endif
+
+extern int command(char *, ...);
+
+char *remglob (char **, int);
+int another (int *, char ***, char *);
+void makeargv (void);
+void setpeer (int, char **);
+void setclevel (int, char **);
+void setdlevel (int, char **);
+void ccc (void);
+void setclear (void);
+void setsafe (void);
+void setprivate (void);
+void settype (int, char **);
+void changetype (int, int);
+void setbinary (void);
+void setascii (void);
+void settenex (void);
+void set_mode  (int, char **);
+void setform  (int, char **);
+void setstruct  (int, char **);
+void siteidle  (int, char **);
+void put  (int, char **);
+void mput  (int, char **);
+void reget  (int, char **);
+void get  (int, char **);
+void mget  (int, char **);
+void status  (int, char **);
+void setbell (void);
+void settrace (void);
+void sethash (void);
+void setverbose (void);
+void setport (void);
+void setprompt (void);
+void setglob (void);
+void setdebug (int, char **);
+void cd (int, char **);
+void lcd (int, char **);
+void delete_file (int, char **);
+void mdelete (int, char **);
+void renamefile (int, char **);
+void ls (int, char **);
+void mls (int, char **);
+void shell (int, char **);
+void user (int, char **);
+void pwd (void);
+void makedir (int, char **);
+void removedir (int, char **);
+void quote (int, char **);
+void site (int, char **);
+void do_chmod (int, char **);
+void do_umask (int, char **);
+void setidle (int, char **);
+void rmthelp (int, char **);
+void quit (void);
+void disconnect (void);
+void fatal (char *);
+void account (int, char **);
+void doproxy (int, char **);
+void setcase (void);
+void setcr (void);
+void setntrans (int, char **);
+void setnmap (int, char **);
+void setsunique (void);
+void setrunique (void);
+void cdup (void);
+void restart (int, char **);
+void syst (void);
+void macdef (int, char **);
+void sizecmd (int, char **);
+void modtime (int, char **);
+void rmtstatus (int, char **);
+void newer (int, char **);
+void setpassive (void);
+
+/* ftp.c */
+void sendrequest (char *, char *, char *, int);
+void recvrequest (char *, char *volatile, char *, char *, int, int);
+int login (char *);
+void setpbsz (unsigned int);
+void pswitch (int);
+int getreply (int);
+void reset (void);
+char *hookup (char *, int);
+int do_auth (void);
+
+/* glob.c */
+void blkfree (char **);
+
+/* domacro.c */
+void domacro (int, char **);
+
+
+/* main.c */
+void help (int, char **);
+struct cmd *getcmd (char *);
+
+
+/* ruserpass.c */
+int ruserpass (char *, char **, char **, char **);
+
+/* radix.h */
+int radix_encode (unsigned char *, unsigned char *, int *, int);
+char *radix_error (int);
+
+/* getpass.c */
+char *mygetpass (char *);
+
+/* glob.c */
+char **ftpglob (char *);
diff --git a/krb5-1-6/src/appl/gssftp/ftp/getpass.c b/krb5-1-6/src/appl/gssftp/ftp/getpass.c
new file mode 100644
index 000000000..cd27cdce5
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/getpass.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static	char sccsid[] = "@(#)getpass.c 1.1 90/04/28 SMI"; /* from UCB 5.4 3/7/86 */
+#endif /* not lint */
+
+#ifdef _WIN32
+#include <io.h>
+#include <windows.h>
+#include <stdio.h>
+
+static DWORD old_mode;
+static HANDLE cons_handle;
+
+BOOL WINAPI
+GetPassConsoleControlHandler(DWORD dwCtrlType)
+{
+	switch(dwCtrlType){
+	case CTRL_BREAK_EVENT:
+	case CTRL_C_EVENT:
+		printf("Interrupt\n");
+		fflush(stdout);
+		(void) SetConsoleMode(cons_handle, old_mode);
+		ExitProcess(-1);
+		break;
+	default:
+		break;
+	}
+	return TRUE;
+}
+
+char *
+mygetpass(char *prompt)
+{
+	DWORD new_mode;
+	char *ptr;
+	int scratchchar;
+	static char password[50+1];
+	int pwsize = sizeof(password);
+
+	cons_handle = GetStdHandle(STD_INPUT_HANDLE);
+	if (cons_handle == INVALID_HANDLE_VALUE)
+		return NULL;
+	if (!GetConsoleMode(cons_handle, &old_mode))
+		return NULL;
+
+	new_mode = old_mode;
+	new_mode |=  ( ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT );
+	new_mode &= ~( ENABLE_ECHO_INPUT );
+
+	if (!SetConsoleMode(cons_handle, new_mode))
+		return NULL;
+
+	SetConsoleCtrlHandler(&GetPassConsoleControlHandler, TRUE);
+
+	(void) fputs(prompt, stdout);
+	(void) fflush(stdout);
+	(void) memset(password, 0, pwsize);
+
+	if (fgets(password, pwsize, stdin) == NULL) {
+		if (ferror(stdin))
+			goto out;
+		(void) putchar('\n');
+	}
+	else {
+		(void) putchar('\n');
+
+		if ((ptr = strchr(password, '\n')))
+			*ptr = '\0';
+		else /* need to flush */
+			do {
+				scratchchar = getchar();
+			} while (scratchchar != EOF && scratchchar != '\n');
+	}
+
+out:
+	(void) SetConsoleMode(cons_handle, old_mode);
+	SetConsoleCtrlHandler(&GetPassConsoleControlHandler, FALSE);
+
+	return password;
+}
+
+#else /* !_WIN32 */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <signal.h>
+
+#if defined (POSIX) || defined (POSIX_TERMIOS)
+#include <termios.h>
+static	struct termios ttyo, ttyb;
+#define stty(f, t) tcsetattr(f, TCSANOW, t)
+#define gtty(f, t) tcgetattr(f, t)
+#else
+#include <sgtty.h>
+static	struct sgttyb ttyo, ttyb;
+#endif
+
+#include "ftp_var.h"
+
+static	FILE *fi;
+
+static sigtype
+intfix(sig)
+	int sig;
+{
+	if (fi != NULL)
+		(void) stty(fileno(fi), &ttyo);
+	exit(SIGINT);
+}
+
+char *
+mygetpass(prompt)
+char *prompt;
+{
+	register char *p;
+	register int c;
+	static char pbuf[50+1];
+	sigtype (*sig)();
+
+	if ((fi = fopen("/dev/tty", "r")) == NULL)
+		fi = stdin;
+	else
+		setbuf(fi, (char *)NULL);
+	sig = signal(SIGINT, intfix);
+	(void) gtty(fileno(fi), &ttyb);
+	ttyo = ttyb;
+#if defined (POSIX) || defined (POSIX_TERMIOS)
+	ttyb.c_lflag &= ~ECHO;
+#else
+	ttyb.sg_flags &= ~ECHO;
+#endif
+	(void) stty(fileno(fi), &ttyb);
+	fprintf(stderr, "%s", prompt); (void) fflush(stderr);
+	for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) {
+		if (p < &pbuf[sizeof(pbuf)-1])
+			*p++ = c;
+	}
+	*p = '\0';
+	fprintf(stderr, "\n"); (void) fflush(stderr);
+	(void) stty(fileno(fi), &ttyo);
+	(void) signal(SIGINT, sig);
+	if (fi != stdin)
+		(void) fclose(fi);
+	return(pbuf);
+}
+
+#endif /* !_WIN32 */
diff --git a/krb5-1-6/src/appl/gssftp/ftp/glob.c b/krb5-1-6/src/appl/gssftp/ftp/glob.c
new file mode 100644
index 000000000..272e50305
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/glob.c
@@ -0,0 +1,784 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)glob.c	5.9 (Berkeley) 2/25/91";
+#endif /* not lint */
+
+/*
+ * C-shell glob for random programs.
+ */
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef _WIN32
+#include <sys/param.h>
+#include <dirent.h>
+#include <pwd.h>
+#endif
+
+#ifdef POSIX
+#include <limits.h>
+#endif
+
+#include "ftp_var.h"
+
+#ifdef ARG_MAX
+#undef NCARGS
+#define NCARGS ARG_MAX
+#endif
+
+#ifndef NCARGS
+#define NCARGS 4096
+#endif
+
+#define	QUOTE 0200
+#define	TRIM 0177
+#define	eq(a,b)		(strcmp(a, b)==0)
+#define	GAVSIZ		(NCARGS/6)
+#define	isdir(d)	((d.st_mode & S_IFMT) == S_IFDIR)
+
+static	char **gargv;		/* Pointer to the (stack) arglist */
+static	int gargc;		/* Number args in gargv */
+static	int gnleft;
+static	short gflag;
+char	**ftpglob();
+char	*globerr;
+char	*home;
+static	char *strspl (char *, char *), *strend (char *);
+char	**copyblk (char **);
+
+static void acollect (char *), addpath (int), 
+  collect (char *), expand (char *), 
+  Gcat (char *, char *);
+static void ginit (char **), matchdir (char *),
+  rscan (char **, int (*f)()), sort (void);
+static int amatch (char *, char *), 
+  execbrc (char *, char *), match (char *, char *);
+static int digit (int), letter (int),
+  any (int, char *);
+#ifndef _WIN32
+static int gethdir (char *);
+#endif
+static int tglob (int );
+
+static	int globcnt;
+
+char	*globchars = "`{[*?";
+
+static	char *gpath, *gpathp, *lastgpathp;
+static	int globbed;
+static	char *entp;
+static	char **sortbas;
+
+char **
+ftpglob(v)
+	register char *v;
+{
+	char agpath[FTP_BUFSIZ];
+	char *agargv[GAVSIZ];
+	char *vv[2];
+	vv[0] = v;
+	vv[1] = 0;
+	gflag = 0;
+	rscan(vv, tglob);
+	if (gflag == 0) {
+	  /* Caller will always free the contents, so make a copy.  */
+	  size_t len = strlen (v) + 1;
+	  vv[0] = malloc (len);
+	  if (vv[0] == 0) {
+	    globerr = "Can't allocate memory";
+	    return 0;
+	  }
+	  memcpy (vv[0], v, len);
+	  return (copyblk(vv));
+	}
+
+	globerr = 0;
+	gpath = agpath; gpathp = gpath; *gpathp = 0;
+	lastgpathp = &gpath[sizeof(agpath) - 1];
+	ginit(agargv); globcnt = 0;
+	collect(v);
+	if (globcnt == 0 && (gflag&1)) {
+		blkfree(gargv), gargv = 0;
+		return (0);
+	} else
+		return (gargv = copyblk(gargv));
+}
+
+static void
+ginit(agargv)
+	char **agargv;
+{
+
+	agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
+	gnleft = NCARGS - 4;
+}
+
+static void
+collect(as)
+	register char *as;
+{
+	if (eq(as, "{") || eq(as, "{}")) {
+		Gcat(as, "");
+		sort();
+	} else
+		acollect(as);
+}
+
+static void
+acollect(as)
+	register char *as;
+{
+	register int ogargc = gargc;
+
+	gpathp = gpath; *gpathp = 0; globbed = 0;
+	expand(as);
+	if (gargc != ogargc)
+		sort();
+}
+
+static void
+sort()
+{
+	register char **p1, **p2, *c;
+	char **Gvp = &gargv[gargc];
+
+	p1 = sortbas;
+	while (p1 < Gvp-1) {
+		p2 = p1;
+		while (++p2 < Gvp)
+			if (strcmp(*p1, *p2) > 0)
+				c = *p1, *p1 = *p2, *p2 = c;
+		p1++;
+	}
+	sortbas = Gvp;
+}
+
+static void
+expand(as)
+	char *as;
+{
+	register char *cs;
+	register char *sgpathp, *oldcs;
+	struct stat stb;
+
+	sgpathp = gpathp;
+	cs = as;
+#ifndef _WIN32
+	if (*cs == '~' && gpathp == gpath) {
+		addpath('~');
+		for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
+			addpath(*cs++);
+		if (!*cs || *cs == '/') {
+			if (gpathp != gpath + 1) {
+				*gpathp = 0;
+				if (gethdir(gpath + 1))
+					globerr = "Unknown user name after ~";
+				(void) strcpy(gpath, gpath + 1);
+			} else
+				(void) strncpy(gpath, home, FTP_BUFSIZ - 1);
+			gpath[FTP_BUFSIZ - 1] = '\0';
+			gpathp = strend(gpath);
+		}
+	}
+#endif
+	while (!any(*cs, globchars)) {
+		if (*cs == 0) {
+			if (!globbed)
+				Gcat(gpath, "");
+			else if (stat(gpath, &stb) >= 0) {
+				Gcat(gpath, "");
+				globcnt++;
+			}
+			goto endit;
+		}
+		addpath(*cs++);
+	}
+	oldcs = cs;
+	while (cs > as && *cs != '/')
+		cs--, gpathp--;
+	if (*cs == '/')
+		cs++, gpathp++;
+	*gpathp = 0;
+	if (*oldcs == '{') {
+		(void) execbrc(cs, ((char *)0));
+		return;
+	}
+	matchdir(cs);
+endit:
+	gpathp = sgpathp;
+	*gpathp = 0;
+}
+
+#ifdef _WIN32
+
+static void
+matchdir(pattern)
+	char *pattern;
+{
+	HANDLE hFile = INVALID_HANDLE_VALUE;
+	WIN32_FIND_DATA file_data;
+	char *base = *gpath ? gpath : ".";
+	char *buffer = 0;
+
+	buffer = malloc(strlen(base) + strlen("\\*") + 1);
+	if (!buffer) return;
+	strcpy(buffer, base);
+	strcat(buffer, "\\*");
+	hFile = FindFirstFile(buffer, &file_data);
+	if (hFile == INVALID_HANDLE_VALUE) {
+		if (!globbed)
+			globerr = "Bad directory components";
+		return;
+	}
+	do {
+		if (match(file_data.cFileName, pattern)) {
+			Gcat(gpath, file_data.cFileName);
+			globcnt++;
+		}
+	} while (FindNextFile(hFile, &file_data));
+	FindClose(hFile);
+}
+
+#else /* !_WIN32 */
+
+static void
+matchdir(pattern)
+	char *pattern;
+{
+#if 0
+	struct stat stb;
+#endif
+	register struct dirent *dp;
+	DIR *dirp;
+
+	dirp = opendir(*gpath?gpath:".");
+	if (dirp == NULL) {
+		if (globbed)
+			return;
+		goto patherr2;
+	}
+	/* This fails on systems where you can't inspect the contents of
+	   the DIR structure.  If there are systems whose opendir does
+	   not check for a directory, then use stat, not fstat. */
+#if 0
+	if (fstat(dirp->dd_fd, &stb) < 0)
+		goto patherr1;
+	if (!isdir(stb)) {
+		errno = ENOTDIR;
+		goto patherr1;
+	}
+#endif
+	while ((dp = readdir(dirp)) != NULL) {
+		if (dp->d_ino == 0)
+			continue;
+		if (match(dp->d_name, pattern)) {
+			Gcat(gpath, dp->d_name);
+			globcnt++;
+		}
+	}
+	closedir(dirp);
+	return;
+
+#if 0
+patherr1:
+#endif
+	closedir(dirp);
+patherr2:
+	globerr = "Bad directory components";
+}
+
+#endif /* !_WIN32 */
+
+static int
+execbrc(p, s)
+	char *p, *s;
+{
+	char restbuf[FTP_BUFSIZ + 2];
+	register char *pe, *pm, *pl;
+	int brclev = 0;
+	char *lm, savec, *sgpathp;
+
+	for (lm = restbuf; *p != '{'; *lm++ = *p++)
+		continue;
+	/* pe starts pointing to one past the first '{'. */
+	for (pe = ++p; *pe; pe++)
+	switch (*pe) {
+
+	case '{':
+		brclev++;
+		continue;
+
+	case '}':
+		if (brclev == 0)
+			goto pend;
+		brclev--;
+		continue;
+
+	case '[':
+		for (pe++; *pe && *pe != ']'; pe++)
+			continue;
+		if (!*pe)
+			pe--;
+		continue;
+	}
+pend:
+	brclev = 0;
+	for (pl = pm = p; pm <= pe; pm++)
+	switch (*pm & (QUOTE|TRIM)) {
+
+	case '{':
+		brclev++;
+		continue;
+
+	case '}':
+		if (brclev) {	/* brclev = 0 is outermost brace set */
+			brclev--;
+			continue;
+		}
+		goto doit;
+
+	case ','|QUOTE:
+	case ',':
+		if (brclev)
+			continue;
+doit:
+		savec = *pm;
+		*pm = 0;
+		(void) strncpy(lm, pl, sizeof(restbuf) - 1 - (lm - restbuf));
+		restbuf[sizeof(restbuf) - 1] = '\0';
+		if (*pe) {
+			(void) strncat(restbuf, pe + 1,
+				       sizeof(restbuf) - 1 - strlen(restbuf));
+		}
+		*pm = savec;
+		if (s == 0) {
+			sgpathp = gpathp;
+			expand(restbuf);
+			gpathp = sgpathp;
+			*gpathp = 0;
+		} else if (amatch(s, restbuf))
+			return (1);
+		sort();
+		pl = pm + 1;
+		if (brclev)
+			return (0);
+		continue;
+
+	case '[':
+		for (pm++; *pm && *pm != ']'; pm++)
+			continue;
+		if (!*pm)
+			pm--;
+		continue;
+	}
+	if (brclev)
+		goto doit;
+	return (0);
+}
+
+static int
+match(s, p)
+	char *s, *p;
+{
+	register int c;
+	register char *sentp;
+	char sglobbed = globbed;
+
+	if (*s == '.' && *p != '.')
+		return (0);
+	sentp = entp;
+	entp = s;
+	c = amatch(s, p);
+	entp = sentp;
+	globbed = sglobbed;
+	return (c);
+}
+
+static int
+amatch(s, p)
+	register char *s, *p;
+{
+	register int scc;
+	int ok, lc;
+	char *sgpathp;
+	struct stat stb;
+	int c, cc;
+
+	globbed = 1;
+	for (;;) {
+		scc = *s++ & TRIM;
+		switch (c = *p++) {
+
+		case '{':
+			return (execbrc(p - 1, s - 1));
+
+		case '[':
+			ok = 0;
+			lc = 077777;
+			while ((cc = *p++)) {
+				if (cc == ']') {
+					if (ok)
+						break;
+					return (0);
+				}
+				if (cc == '-') {
+					if (lc <= scc && scc <= *p++)
+						ok++;
+				} else
+					if (scc == (lc = cc))
+						ok++;
+			}
+			if (cc == 0) {
+				if (ok)
+					p--;
+				else
+					return 0;
+			}
+			continue;
+
+		case '*':
+			/* Multiple stars are equivalent to one.
+			   Don't chew up cpu time with O(n**2)
+			   recursion if a long string of them is
+			   given.  */
+			while (*p == '*')
+				p++;
+			if (!*p)
+				return (1);
+			if (*p == '/') {
+				p++;
+				goto slash;
+			}
+			s--;
+			do {
+				if (amatch(s, p))
+					return (1);
+			} while (*s++);
+			return (0);
+
+		case 0:
+			return (scc == 0);
+
+		default:
+			if (c != scc)
+				return (0);
+			continue;
+
+		case '?':
+			if (scc == 0)
+				return (0);
+			continue;
+
+		case '/':
+			if (scc)
+				return (0);
+slash:
+			s = entp;
+			sgpathp = gpathp;
+			while (*s)
+				addpath(*s++);
+			addpath('/');
+			if (stat(gpath, &stb) == 0 && isdir(stb)) {
+				if (*p == 0) {
+					Gcat(gpath, "");
+					globcnt++;
+				} else
+					expand(p);
+			}
+			gpathp = sgpathp;
+			*gpathp = 0;
+			return (0);
+		}
+	}
+}
+
+static int
+Gmatch(s, p)
+	register char *s, *p;
+{
+	register int scc;
+	int ok, lc;
+	int c, cc;
+
+	for (;;) {
+		scc = *s++ & TRIM;
+		switch (c = *p++) {
+
+		case '[':
+			ok = 0;
+			lc = 077777;
+			while ((cc = *p++)) {
+				if (cc == ']') {
+					if (ok)
+						break;
+					return (0);
+				}
+				if (cc == '-') {
+					if (lc <= scc && scc <= *p++)
+						ok++;
+				} else
+					if (scc == (lc = cc))
+						ok++;
+			}
+			if (cc == 0) {
+				if (ok)
+					p--;
+				else
+					return 0;
+			}
+			continue;
+
+		case '*':
+			if (!*p)
+				return (1);
+			for (s--; *s; s++)
+				if (Gmatch(s, p))
+					return (1);
+			return (0);
+
+		case 0:
+			return (scc == 0);
+
+		default:
+			if ((c & TRIM) != scc)
+				return (0);
+			continue;
+
+		case '?':
+			if (scc == 0)
+				return (0);
+			continue;
+
+		}
+	}
+}
+
+static void
+Gcat(s1, s2)
+	register char *s1, *s2;
+{
+	register int len = strlen(s1) + strlen(s2) + 1;
+
+	if (len >= gnleft || gargc >= GAVSIZ - 1)
+		globerr = "Arguments too long";
+	else {
+		gargc++;
+		gnleft -= len;
+		gargv[gargc] = 0;
+		gargv[gargc - 1] = strspl(s1, s2);
+	}
+}
+
+static void
+addpath(c)
+	int c;
+{
+
+	if (gpathp >= lastgpathp)
+		globerr = "Pathname too long";
+	else {
+		*gpathp++ = c & 0xff;
+		*gpathp = 0;
+	}
+}
+
+static void
+rscan(t, f)
+	register char **t;
+	int (*f)();
+{
+	register char *p, c;
+
+	while ((p = *t++)) {
+		if (f == tglob) {
+			if (*p == '~')
+				gflag |= 2;
+			else if (eq(p, "{") || eq(p, "{}"))
+				continue;
+		}
+		while ((c = *p++))
+			(*f)(c);
+	}
+}
+/*
+static
+scan(t, f)
+	register char **t;
+	int (*f)();
+{
+	register char *p, c;
+
+	while (p = *t++)
+		while (c = *p)
+			*p++ = (*f)(c);
+} */
+
+static int
+tglob(c)
+	register int c;
+{
+
+	if (any(c, globchars))
+		gflag |= c == '{' ? 2 : 1;
+	return (c);
+}
+/*
+static
+trim(c)
+	char c;
+{
+
+	return (c & TRIM);
+} */
+
+
+static int
+letter(c)
+	register int c;
+{
+
+	return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
+}
+
+static int
+digit(c)
+	register int c;
+{
+
+	return (c >= '0' && c <= '9');
+}
+
+static int any(c, s)
+	register int c;
+	register char *s;
+{
+
+	while (*s)
+		if (*s++ == c)
+			return(1);
+	return(0);
+}
+static int blklen(av)
+	register char **av;
+{
+	register int i = 0;
+
+	while (*av++)
+		i++;
+	return (i);
+}
+
+static char **
+blkcpy(oav, bv)
+	char **oav;
+	register char **bv;
+{
+	register char **av = oav;
+
+	while ((*av++ = *bv++))
+		continue;
+	return (oav);
+}
+
+void blkfree(av0)
+	char **av0;
+{
+	register char **av = av0;
+
+	while (*av)
+		free(*av++);
+}
+
+static
+char *
+strspl(cp, dp)
+	register char *cp, *dp;
+{
+	register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
+
+	if (ep == (char *)0)
+		fatal("Out of memory");
+	(void) strcpy(ep, cp);
+	(void) strcat(ep, dp);
+	return (ep);
+}
+
+char **
+copyblk(v)
+	register char **v;
+{
+	register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
+						sizeof(char **)));
+	if (nv == (char **)0)
+		fatal("Out of memory");
+
+	return (blkcpy(nv, v));
+}
+
+static
+char *
+strend(cp)
+	register char *cp;
+{
+
+	while (*cp)
+		cp++;
+	return (cp);
+}
+
+#ifndef _WIN32
+/*
+ * Extract a home directory from the password file
+ * The argument points to a buffer where the name of the
+ * user whose home directory is sought is currently.
+ * We write the home directory of the user back there.
+ */
+static int gethdir(mhome)
+	char *mhome;
+{
+	register struct passwd *pp = getpwnam(mhome);
+
+	if (!pp || ((mhome + strlen(pp->pw_dir)) >= lastgpathp))
+		return (1);
+	(void) strcpy(mhome, pp->pw_dir);
+	return (0);
+}
+#endif
diff --git a/krb5-1-6/src/appl/gssftp/ftp/main.c b/krb5-1-6/src/appl/gssftp/ftp/main.c
new file mode 100644
index 000000000..8e4cfe5ef
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/main.c
@@ -0,0 +1,633 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c	5.18 (Berkeley) 3/1/91";
+#endif /* not lint */
+
+/*
+ * FTP User Program -- Command Interface.
+ */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include "ftp_var.h"
+#ifndef _WIN32
+#ifndef KRB5_KRB4_COMPAT
+/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <pwd.h>
+#endif /* !_WIN32 */
+
+#ifdef _WIN32
+#include <io.h>
+#undef ERROR
+#endif
+
+#include <arpa/ftp.h>
+
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <port-sockets.h>
+
+#ifdef _WIN32
+/* For SO_SYNCHRONOUS_NONALERT and SO_OPENTYPE: */
+#include <mswsock.h>
+#endif
+
+#ifndef _WIN32
+uid_t	getuid();
+#endif
+
+sigtype	intr (int), lostpeer (int);
+extern	char *home;
+char	*getlogin();
+#ifdef KRB5_KRB4_COMPAT
+#include <krb.h>
+struct servent staticsp;
+extern char realm[];
+#endif /* KRB5_KRB4_COMPAT */
+
+static void cmdscanner (int);
+static char *slurpstring (void);
+
+
+int 
+main(argc, argv)
+	volatile int argc;
+	char **volatile argv;
+{
+	register char *cp;
+	int top;
+#ifndef _WIN32
+	struct passwd *pw = NULL;
+#endif
+	char homedir[MAXPATHLEN];
+	char *progname = argv[0];
+
+#ifdef _WIN32
+	DWORD optionValue = SO_SYNCHRONOUS_NONALERT;
+	if (setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue)) == SOCKET_ERROR) {
+		fprintf(stderr, "ftp: cannot enable synchronous sockets\n");
+		exit(1);
+	}
+#endif
+
+	sp = getservbyname("ftp", "tcp");
+	if (sp == 0) {
+		fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
+		exit(1);
+	}
+#ifdef KRB5_KRB4_COMPAT
+/* GDM need to static sp so that the information is not lost
+   when kerberos calls getservbyname */
+	memcpy(&staticsp,sp,sizeof(struct servent));
+	sp = &staticsp;
+#endif /* KRB5_KRB4_COMPAT */
+	doglob = 1;
+	interactive = 1;
+	autoauth = 1;
+	autologin = 1;
+	forward = 0;
+	autoencrypt = 0;
+	argc--, argv++;
+	while (argc > 0 && **argv == '-') {
+		for (cp = *argv + 1; *cp; cp++)
+			switch (*cp) {
+
+			case 'd':
+				options |= SO_DEBUG;
+				debug++;
+				break;
+
+#ifdef KRB5_KRB4_COMPAT
+			case 'k':
+				if (*++cp != '\0')
+					strncpy(realm, ++cp, REALM_SZ);
+				else if (argc > 1) {
+					argc--, argv++;
+					strncpy(realm, *argv, REALM_SZ);
+				}
+				else
+					fprintf(stderr, "ftp: -k expects arguments\n");
+				goto nextopt;
+#endif
+
+			case 'v':
+				verbose++;
+				break;
+
+			case 't':
+				trace++;
+				break;
+
+			case 'i':
+				interactive = 0;
+				break;
+
+			case 'n':
+				autologin = 0;
+				break;
+
+			case 'g':
+				doglob = 0;
+				break;
+
+			case 'u':
+				autoauth = 0;
+				break;
+
+			case 'f':
+				forward = 1;
+				break;
+
+			case 'x':
+				autoencrypt = 1;
+				break;
+
+			default:
+			  fprintf(stderr,
+				  "ftp: %c: unknown option\n", *cp);
+			  fprintf(stderr, "Usage: %s [-v] [-d] [-i] [-n] [-g] "
+				  "[-k realm] [-f] [-x] [-u] [-t] [host]\n",
+				  progname);
+			  exit(1);
+			}
+	nextopt:
+		argc--, argv++;
+	}
+	fromatty = isatty(fileno(stdin));
+	if (fromatty)
+		verbose++;
+	cpend = 0;	/* no pending replies */
+	proxy = 0;	/* proxy not active */
+#ifndef NO_PASSIVE_MODE
+	passivemode = 0; /* passive mode not active */
+#endif
+	crflag = 1;	/* strip c.r. on ascii gets */
+	sendport = -1;	/* not using ports */
+	/*
+	 * Set up the home directory in case we're globbing.
+	 */
+#ifdef _WIN32
+	cp = getenv("HOME");
+	if (cp != NULL) {
+		home = homedir;
+		(void) strncpy(home, cp, sizeof(homedir) - 1);
+		homedir[sizeof(homedir) - 1] = '\0';
+	}
+#else /* !_WIN32 */
+	cp = getlogin();
+	if (cp != NULL) {
+		pw = getpwnam(cp);
+	}
+	if (pw == NULL)
+		pw = getpwuid(getuid());
+	if (pw != NULL) {
+		home = homedir;
+		(void) strncpy(home, pw->pw_dir, sizeof(homedir) - 1);
+		homedir[sizeof(homedir) - 1] = '\0';
+	}
+#endif /* !_WIN32 */
+	if (argc > 0) {
+		if (setjmp(toplevel))
+			exit(0);
+		(void) signal(SIGINT, intr);
+#ifdef SIGPIPE
+		(void) signal(SIGPIPE, lostpeer);
+#endif
+		setpeer(argc + 1, argv - 1);
+	}
+	top = setjmp(toplevel) == 0;
+	if (top) {
+		(void) signal(SIGINT, intr);
+#ifdef SIGPIPE
+		(void) signal(SIGPIPE, lostpeer);
+#endif
+	}
+	for (;;) {
+		cmdscanner(top);
+		top = 1;
+	}
+}
+
+sigtype
+intr(sig)
+	int sig;
+{
+
+	longjmp(toplevel, 1);
+}
+
+sigtype
+lostpeer(sig)
+	int sig;
+{
+	extern FILE *cout;
+	extern SOCKET data;
+	extern char *auth_type;
+	extern int clevel;
+	extern int dlevel;
+
+	if (connected) {
+		if (cout != NULL) {
+			(void) shutdown(SOCKETNO(fileno(cout)), 1+1);
+			(void) FCLOSE_SOCKET(cout);
+			cout = NULL;
+		}
+		if (data != INVALID_SOCKET) {
+			(void) shutdown(data, 1+1);
+			(void) closesocket(data);
+			data = INVALID_SOCKET;
+		}
+		connected = 0;
+		auth_type = NULL;
+		clevel = dlevel = PROT_C;
+	}
+	pswitch(1);
+	if (connected) {
+		if (cout != NULL) {
+			(void) shutdown(SOCKETNO(fileno(cout)), 1+1);
+			(void) FCLOSE_SOCKET(cout);
+			cout = NULL;
+		}
+		connected = 0;
+		auth_type = NULL;
+		clevel = dlevel = PROT_C;
+	}
+	proxflag = 0;
+	pswitch(0);
+}
+
+/*char *
+tail(filename)
+	char *filename;
+{
+	register char *s;
+	
+	while (*filename) {
+		s = strrchr(filename, '/');
+		if (s == NULL)
+			break;
+		if (s[1])
+			return (s + 1);
+		*s = '\0';
+	}
+	return (filename);
+}
+*/
+/*
+ * Command parser.
+ */
+static void
+cmdscanner(top)
+	int top;
+{
+	register struct cmd *c;
+	register int l;
+
+	if (!top)
+		(void) putchar('\n');
+	for (;;) {
+		if (fromatty) {
+			printf("ftp> ");
+			(void) fflush(stdout);
+		}
+		if (fgets(line, sizeof line, stdin) == NULL)
+			quit();
+		l = strlen(line);
+		if (l == 0)
+			break;
+		if (line[--l] == '\n') {
+			if (l == 0)
+				break;
+			line[l] = '\0';
+		} else if (l == sizeof(line) - 2) {
+			printf("sorry, input line too long\n");
+			while ((l = getchar()) != '\n' && l != EOF)
+				/* void */;
+			break;
+		} /* else it was a line without a newline */
+		makeargv();
+		if (margc == 0) {
+			continue;
+		}
+		c = getcmd(margv[0]);
+		if (c == (struct cmd *)-1) {
+			printf("?Ambiguous command\n");
+			continue;
+		}
+		if (c == 0) {
+			printf("?Invalid command\n");
+			continue;
+		}
+		if (c->c_conn && !connected) {
+			printf("Not connected.\n");
+			continue;
+		}
+		(*c->c_handler)(margc, margv);
+		if (bell && c->c_bell)
+			(void) putchar('\007');
+		if (c->c_handler != help)
+			break;
+	}
+	(void) signal(SIGINT, intr);
+#ifdef SIGPIPE
+	(void) signal(SIGPIPE, lostpeer);
+#endif
+}
+
+struct cmd *
+getcmd(name)
+	register char *name;
+{
+	extern struct cmd cmdtab[];
+	register char *p, *q;
+	register struct cmd *c, *found;
+	register int nmatches, longest;
+
+	longest = 0;
+	nmatches = 0;
+	found = 0;
+	for (c = cmdtab; (p = c->c_name) != NULL; c++) {
+		for (q = name; *q == *p++; q++)
+			if (*q == 0)		/* exact match? */
+				return (c);
+		if (!*q) {			/* the name was a prefix */
+			if (q - name > longest) {
+				longest = q - name;
+				nmatches = 1;
+				found = c;
+			} else if (q - name == longest)
+				nmatches++;
+		}
+	}
+	if (nmatches > 1)
+		return ((struct cmd *)-1);
+	return (found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+
+int slrflag;
+
+void makeargv()
+{
+	char **argp;
+
+	margc = 0;
+	argp = margv;
+	stringbase = line;		/* scan from first of buffer */
+	argbase = argbuf;		/* store from first of buffer */
+	slrflag = 0;
+	while ((*argp++ = slurpstring())) {
+		margc++;
+		if (margc == sizeof(margv)/sizeof(margv[0])) {
+			printf("sorry, too many arguments in input line\n");
+			margc = 0;
+			margv[0] = 0;
+			return;
+		}
+	}
+}
+
+/*
+ * Parse string into argbuf;
+ * implemented with FSM to
+ * handle quoting and strings
+ */
+static char *
+slurpstring()
+{
+	int got_one = 0;
+	register char *sb = stringbase;
+	register char *ap = argbase;
+	char *tmp = argbase;		/* will return this if token found */
+
+	if (*sb == '!' || *sb == '$') {	/* recognize ! as a token for shell */
+		switch (slrflag) {	/* and $ as token for macro invoke */
+			case 0:
+				slrflag++;
+				stringbase++;
+				return ((*sb == '!') ? "!" : "$");
+				/* NOTREACHED */
+			case 1:
+				slrflag++;
+				altarg = stringbase;
+				break;
+			default:
+				break;
+		}
+	}
+
+S0:
+	switch (*sb) {
+
+	case '\0':
+		goto EXIT;
+
+	case ' ':
+	case '\t':
+		sb++; goto S0;
+
+	default:
+		switch (slrflag) {
+			case 0:
+				slrflag++;
+				break;
+			case 1:
+				slrflag++;
+				altarg = sb;
+				break;
+			default:
+				break;
+		}
+		goto S1;
+	}
+
+S1:
+	switch (*sb) {
+
+	case ' ':
+	case '\t':
+	case '\0':
+		goto EXIT;	/* end of token */
+
+	case '\\':
+		sb++; goto S2;	/* slurp next character */
+
+	case '"':
+		sb++; goto S3;	/* slurp quoted string */
+
+	default:
+		*ap++ = *sb++;	/* add character to token */
+		got_one = 1;
+		goto S1;
+	}
+
+S2:
+	switch (*sb) {
+
+	case '\0':
+		goto EXIT;
+
+	default:
+		*ap++ = *sb++;
+		got_one = 1;
+		goto S1;
+	}
+
+S3:
+	switch (*sb) {
+
+	case '\0':
+		goto EXIT;
+
+	case '"':
+		sb++; goto S1;
+
+	default:
+		*ap++ = *sb++;
+		got_one = 1;
+		goto S3;
+	}
+
+EXIT:
+	if (got_one)
+		*ap++ = '\0';
+	argbase = ap;			/* update storage pointer */
+	stringbase = sb;		/* update scan pointer */
+	if (got_one) {
+		return(tmp);
+	}
+	switch (slrflag) {
+		case 0:
+			slrflag++;
+			break;
+		case 1:
+			slrflag++;
+			altarg = (char *) 0;
+			break;
+		default:
+			break;
+	}
+	return((char *)0);
+}
+
+#define	HELPINDENT ((int) sizeof("disconnect"))
+
+/*
+ * Help command.
+ * Call each command handler with argc == 0 and argv[0] == name.
+ */
+void help(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern struct cmd cmdtab[];
+	register struct cmd *c;
+
+	if (argc == 1) {
+		register int i, j, w, k;
+		int columns, width = 0, lines;
+		extern int NCMDS;
+
+		printf("Commands may be abbreviated.  Commands are:\n\n");
+		for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+			int len = strlen(c->c_name);
+
+			if (len > width)
+				width = len;
+		}
+		width = (width + 8) &~ 7;
+		columns = 80 / width;
+		if (columns == 0)
+			columns = 1;
+		lines = (NCMDS + columns - 1) / columns;
+		for (i = 0; i < lines; i++) {
+			for (j = 0; j < columns; j++) {
+				c = cmdtab + j * lines + i;
+				if (c->c_name && (!proxy || c->c_proxy)) {
+					printf("%s", c->c_name);
+				}
+				else if (c->c_name) {
+					for (k=0; k < strlen(c->c_name); k++) {
+						(void) putchar(' ');
+					}
+				}
+				if (c + lines >= &cmdtab[NCMDS]) {
+					printf("\n");
+					break;
+				}
+				w = strlen(c->c_name);
+				while (w < width) {
+					w = (w + 8) &~ 7;
+					(void) putchar('\t');
+				}
+			}
+		}
+		return;
+	}
+	while (--argc > 0) {
+		register char *arg;
+		arg = *++argv;
+		c = getcmd(arg);
+		if (c == (struct cmd *)-1)
+			printf("?Ambiguous help command %s\n", arg);
+		else if (c == (struct cmd *)0)
+			printf("?Invalid help command %s\n", arg);
+		else
+			printf("%-*s\t%s\n", HELPINDENT,
+				c->c_name, c->c_help);
+	}
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftp/pathnames.h b/krb5-1-6/src/appl/gssftp/ftp/pathnames.h
new file mode 100644
index 000000000..7c0de5b0e
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/pathnames.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)pathnames.h	5.2 (Berkeley) 6/1/90
+ */
+
+#undef _PATH_TMP
+#define	_PATH_TMP	"/tmp/ftpXXXXXX"
diff --git a/krb5-1-6/src/appl/gssftp/ftp/pclose.c b/krb5-1-6/src/appl/gssftp/ftp/pclose.c
new file mode 100644
index 000000000..5d6a5aa57
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/pclose.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static	char sccsid[] = "@(#)pclose.c 1.1 90/04/28 SMI"; /* from UCB 1.2 3/7/86 */
+#endif /* not lint */
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/wait.h>
+#define sig_t my_sig_t
+#define sigtype krb5_sigtype
+typedef sigtype (*sig_t)();
+
+#define	tst(a,b)	(*mode == 'r'? (b) : (a))
+#define	RDR	0
+#define	WTR	1
+
+static	int *popen_pid;
+static	int nfiles;
+
+#ifndef HAVE_GETDTABLESIZE
+#include <sys/resource.h>
+int getdtablesize() {
+  struct rlimit rl;
+  getrlimit(RLIMIT_NOFILE, &rl);
+  return rl.rlim_cur;
+}
+#endif
+
+FILE *
+mypopen(cmd,mode)
+	char *cmd;
+	char *mode;
+{
+	int p[2];
+	volatile int myside, hisside;
+	int pid;
+
+	if (nfiles <= 0)
+		nfiles = getdtablesize();
+	if (popen_pid == NULL) {
+		popen_pid = (int *)malloc((unsigned) nfiles * sizeof *popen_pid);
+		if (popen_pid == NULL)
+			return (NULL);
+		for (pid = 0; pid < nfiles; pid++)
+			popen_pid[pid] = -1;
+	}
+	if (pipe(p) < 0)
+		return (NULL);
+	myside = tst(p[WTR], p[RDR]);
+	hisside = tst(p[RDR], p[WTR]);
+	if ((pid = fork()) == 0) {
+		/* myside and hisside reverse roles in child */
+		(void) close(myside);
+		if (hisside != tst(0, 1)) {
+			(void) dup2(hisside, tst(0, 1));
+			(void) close(hisside);
+		}
+		execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
+		_exit(127);
+	}
+	if (pid == -1) {
+		(void) close(myside);
+		(void) close(hisside);
+		return (NULL);
+	}
+	popen_pid[myside] = pid;
+	(void) close(hisside);
+	return (fdopen(myside, mode));
+}
+
+sigtype
+pabort(sig)
+	int sig;
+{
+	extern int mflag;
+
+	mflag = 0;
+}
+
+mypclose(ptr)
+	FILE *ptr;
+{
+	int child, pid;
+#ifdef USE_SIGPROCMASK
+	sigset_t old, new;
+#else
+	int omask;
+#endif
+	sigtype pabort(), (*istat)();
+#ifdef WAIT_USES_INT
+	int status;
+#else
+	union wait status;
+#endif
+
+	child = popen_pid[fileno(ptr)];
+	popen_pid[fileno(ptr)] = -1;
+	(void) fclose(ptr);
+	if (child == -1)
+		return (-1);
+	istat = signal(SIGINT, pabort);
+#ifdef USE_SIGPROCMASK
+	sigemptyset(&old);
+	sigemptyset(&new);
+	sigaddset(&new,SIGQUIT);
+	sigaddset(&new,SIGHUP);
+	sigprocmask(SIG_BLOCK, &new, &old);
+	while ((pid = wait(&status)) != child && pid != -1)
+		;
+	sigprocmask(SIG_SETMASK, &old, NULL);
+#else
+	omask = sigblock(sigmask(SIGQUIT)|sigmask(SIGHUP));
+	while ((pid = wait(&status)) != child && pid != -1)
+		;
+	sigsetmask(omask);
+#endif
+	(void) signal(SIGINT, istat);
+	return (pid == -1 ? -1 : 0);
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftp/radix.c b/krb5-1-6/src/appl/gssftp/ftp/radix.c
new file mode 100644
index 000000000..2d6dfd18d
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/radix.c
@@ -0,0 +1,166 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "ftp_var.h"
+
+static char *radixN =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static char pad = '=';
+
+int radix_encode(inbuf, outbuf, len, decode)
+unsigned char inbuf[], outbuf[];
+int *len, decode;
+{
+	int i,j,D = 0;
+	char *p;
+	unsigned char c = 0;
+
+	if (decode) {
+		for (i=0,j=0; inbuf[i] && inbuf[i] != pad; i++) {
+		    if ((p = strchr(radixN, inbuf[i])) == NULL) return(1);
+		    D = p - radixN;
+		    switch (i&3) {
+			case 0:
+			    c = D<<2;
+			    break;
+			case 1:
+			    outbuf[j++] = c | D>>4;
+			    c = (D&15)<<4;
+			    break;
+			case 2:
+			    outbuf[j++] = c | D>>2;
+			    c = (D&3)<<6;
+			    break;
+			case 3:
+			    outbuf[j++] = c | D;
+		    }
+		}
+		switch (i&3) {
+			case 1: return(3);
+			case 2: if (D&15) return(3);
+				if (strcmp((char *)&inbuf[i], "==")) return(2);
+				break;
+			case 3: if (D&3) return(3);
+				if (strcmp((char *)&inbuf[i], "="))  return(2);
+		}
+		*len = j;
+	} else {
+		for (i=0,j=0; i < *len; i++)
+		    switch (i%3) {
+			case 0:
+			    outbuf[j++] = radixN[inbuf[i]>>2];
+			    c = (inbuf[i]&3)<<4;
+			    break;
+			case 1:
+			    outbuf[j++] = radixN[c|inbuf[i]>>4];
+			    c = (inbuf[i]&15)<<2;
+			    break;
+			case 2:
+			    outbuf[j++] = radixN[c|inbuf[i]>>6];
+			    outbuf[j++] = radixN[inbuf[i]&63];
+			    c = 0;
+		    }
+		if (i%3) outbuf[j++] = radixN[c];
+		switch (i%3) {
+			case 1: outbuf[j++] = pad;
+			case 2: outbuf[j++] = pad;
+		}
+		outbuf[*len = j] = '\0';
+	}
+	return(0);
+}
+
+char *
+radix_error(e)
+int e;
+{
+	switch (e) {
+	    case 0:  return("Success");
+	    case 1:  return("Bad character in encoding");
+	    case 2:  return("Encoding not properly padded");
+	    case 3:  return("Decoded # of bits not a multiple of 8");
+	    default: return("Unknown error");
+	}
+}
+
+#ifdef STANDALONE
+usage(s)
+char *s;
+{
+	fprintf(stderr, "Usage: %s [ -d ] [ string ]\n", s);
+	exit(2);
+}
+
+static int n;
+
+putbuf(inbuf, outbuf, len, decode)
+unsigned char inbuf[], outbuf[];
+int len, decode;
+{
+	int c;
+
+	if (c = radix_encode(inbuf, outbuf, &len, decode)) {
+		fprintf(stderr, "Couldn't %scode input: %s\n",
+				decode ? "de" : "en", radix_error(c));
+		exit(1);
+	}
+	if (decode)
+		write(1, outbuf, len);
+	else
+		for (c = 0; c < len;) {
+			putchar(outbuf[c++]);
+			if (++n%76 == 0) putchar('\n');
+		}
+}
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+	unsigned char *inbuf, *outbuf;
+	int c, len = 0, decode = 0;
+	extern int optind;
+
+	while ((c = getopt(argc, argv, "d")) != -1)
+		switch(c) {
+			default:
+				usage(argv[0]);
+			case 'd':
+				decode++;
+		}
+
+	switch (argc - optind) {
+		case 0:
+			inbuf  = (unsigned char *) malloc(5);
+			outbuf = (unsigned char *) malloc(5);
+			while ((c = getchar()) != EOF)
+			    if (c != '\n') {
+				inbuf[len++] = c;
+				if (len == (decode ? 4 : 3)) {
+					inbuf[len] = '\0';
+					putbuf(inbuf, outbuf, len, decode);
+					len=0;
+				}
+			    }
+			if (len) {
+				inbuf[len] = '\0';
+				putbuf(inbuf, outbuf, len, decode);
+			}
+			break;
+		case 1:
+			inbuf = (unsigned char *)argv[optind];
+			len = strlen(inbuf);
+			outbuf = (unsigned char *)
+				malloc((len * (decode?3:4)) / (decode?4:3) + 1);
+			putbuf(inbuf, outbuf, len, decode);
+			break;
+		default:
+			fprintf(stderr, "Only one argument allowed\n");
+			usage(argv[0]);
+	}
+	if (n%76) putchar('\n');
+	exit(0);
+}
+#endif /* STANDALONE */
diff --git a/krb5-1-6/src/appl/gssftp/ftp/ruserpass.c b/krb5-1-6/src/appl/gssftp/ftp/ruserpass.c
new file mode 100644
index 000000000..acfabfa2d
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/ruserpass.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)ruserpass.c	5.3 (Berkeley) 3/1/91";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "ftp_var.h"
+
+#ifdef _WIN32
+#include <win-mac.h>
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+static int token (void);
+static	FILE *cfile;
+
+#define	DEFAULT	1
+#define	LOGIN	2
+#define	PASSWD	3
+#define	ACCOUNT 4
+#define MACDEF  5
+#define	ID	10
+#define	MACH	11
+
+static char tokval[100];
+
+static struct toktab {
+	char *tokstr;
+	int tval;
+} toktab[]= {
+	{ "default",	DEFAULT },
+	{ "login",	LOGIN },
+	{ "password",	PASSWD },
+	{ "passwd",	PASSWD },
+	{ "account",	ACCOUNT },
+	{ "machine",	MACH },
+	{ "macdef",	MACDEF },
+	{ NULL,		0 }
+};
+
+
+static int
+token()
+{
+	char *cp;
+	int c;
+	struct toktab *t;
+
+	if (feof(cfile))
+		return (0);
+	while ((c = getc(cfile)) != EOF &&
+	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
+		continue;
+	if (c == EOF)
+		return (0);
+	cp = tokval;
+	if (c == '"') {
+		while ((c = getc(cfile)) != EOF && c != '"') {
+			if (c == '\\')
+				c = getc(cfile);
+			*cp++ = c;
+		}
+	} else {
+		*cp++ = c;
+		while ((c = getc(cfile)) != EOF
+		    && c != '\n' && c != '\t' && c != ' ' && c != ',') {
+			if (c == '\\')
+				c = getc(cfile);
+			*cp++ = c;
+		}
+	}
+	*cp = 0;
+	if (tokval[0] == 0)
+		return (0);
+	for (t = toktab; t->tokstr; t++)
+		if (!strcmp(t->tokstr, tokval))
+			return (t->tval);
+	return (ID);
+}
+
+int 
+ruserpass(host, aname, apass, aacct)
+	char *host, **aname, **apass, **aacct;
+{
+	char *hdir, buf[FTP_BUFSIZ], *tmp;
+	char myname[MAXHOSTNAMELEN + 1], *mydomain;
+	int t, i, c, usedefault = 0;
+	struct stat stb;
+
+	hdir = getenv("HOME");
+	if (hdir == NULL)
+		hdir = ".";
+	(void) sprintf(buf, "%s/.netrc", hdir);
+	cfile = fopen(buf, "r");
+	if (cfile == NULL) {
+		if (errno != ENOENT)
+			perror(buf);
+		return(0);
+	}
+	if (gethostname(myname, sizeof(myname)) < 0)
+		myname[0] = '\0';
+	if ((mydomain = strchr(myname, '.')) == NULL)
+		mydomain = "";
+next:
+	while ((t = token())) switch(t) {
+
+	case DEFAULT:
+		usedefault = 1;
+		/* FALL THROUGH */
+
+	case MACH:
+		if (!usedefault) {
+			if (token() != ID)
+				continue;
+			/*
+			 * Allow match either for user's input host name
+			 * or official hostname.  Also allow match of 
+			 * incompletely-specified host in local domain.
+			 */
+			if (strcasecmp(host, tokval) == 0)
+				goto match;
+			if (strcasecmp(hostname, tokval) == 0)
+				goto match;
+			if ((tmp = strchr(hostname, '.')) != NULL &&
+			    strcasecmp(tmp, mydomain) == 0 &&
+			    strncasecmp(hostname, tokval,
+					(unsigned) (tmp-hostname)) == 0 &&
+			    tokval[tmp - hostname] == '\0')
+				goto match;
+			if ((tmp = strchr(host, '.')) != NULL &&
+			    strcasecmp(tmp, mydomain) == 0 &&
+			    strncasecmp(host, tokval,
+					(unsigned ) (tmp - host)) == 0 &&
+			    tokval[tmp - host] == '\0')
+				goto match;
+			continue;
+		}
+	match:
+		while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
+
+		case LOGIN:
+			if (token()) {
+				if (*aname == 0) { 
+					*aname = malloc((unsigned) strlen(tokval) + 1);
+					(void) strcpy(*aname, tokval);
+				} else {
+					if (strcmp(*aname, tokval))
+						goto next;
+				}
+			}
+			break;
+		case PASSWD:
+			if (strcmp(*aname, "anonymous") &&
+			    fstat(fileno(cfile), &stb) >= 0 &&
+			    (stb.st_mode & 077) != 0) {
+	fprintf(stderr, "Error - .netrc file not correct mode.\n");
+	fprintf(stderr, "Remove password or correct mode.\n");
+				goto bad;
+			}
+			if (token() && *apass == 0) {
+				*apass = malloc((unsigned) strlen(tokval) + 1);
+				(void) strcpy(*apass, tokval);
+			}
+			break;
+		case ACCOUNT:
+			if (fstat(fileno(cfile), &stb) >= 0
+			    && (stb.st_mode & 077) != 0) {
+	fprintf(stderr, "Error - .netrc file not correct mode.\n");
+	fprintf(stderr, "Remove account or correct mode.\n");
+				goto bad;
+			}
+			if (token() && *aacct == 0) {
+				*aacct = malloc((unsigned) strlen(tokval) + 1);
+				(void) strcpy(*aacct, tokval);
+			}
+			break;
+		case MACDEF:
+			if (proxy) {
+				(void) fclose(cfile);
+				return(0);
+			}
+			while ((c = getc(cfile)) != EOF)
+				if (c != ' ' && c != '\t')
+					break;
+			if (c == EOF || c == '\n') {
+				printf("Missing macdef name argument.\n");
+				goto bad;
+			}
+			if (macnum == 16) {
+				printf("Limit of 16 macros have already been defined\n");
+				goto bad;
+			}
+			tmp = macros[macnum].mac_name;
+			*tmp++ = c;
+			for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
+			    !isspace(c); ++i) {
+				*tmp++ = c;
+			}
+			if (c == EOF) {
+				printf("Macro definition missing null line terminator.\n");
+				goto bad;
+			}
+			*tmp = '\0';
+			if (c != '\n') {
+				while ((c=getc(cfile)) != EOF && c != '\n');
+			}
+			if (c == EOF) {
+				printf("Macro definition missing null line terminator.\n");
+				goto bad;
+			}
+			if (macnum == 0) {
+				macros[macnum].mac_start = macbuf;
+			}
+			else {
+				macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
+			}
+			tmp = macros[macnum].mac_start;
+			while (tmp != macbuf + 4096) {
+				if ((c=getc(cfile)) == EOF) {
+				printf("Macro definition missing null line terminator.\n");
+					goto bad;
+				}
+				*tmp = c;
+				if (*tmp == '\n') {
+					if (*(tmp-1) == '\0') {
+					   macros[macnum++].mac_end = tmp - 1;
+					   break;
+					}
+					*tmp = '\0';
+				}
+				tmp++;
+			}
+			if (tmp == macbuf + 4096) {
+				printf("4K macro buffer exceeded\n");
+				goto bad;
+			}
+			break;
+		default:
+	fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
+			break;
+		}
+		goto done;
+	}
+done:
+	(void) fclose(cfile);
+	return(0);
+bad:
+	(void) fclose(cfile);
+	return(-1);
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftp/secure.c b/krb5-1-6/src/appl/gssftp/ftp/secure.c
new file mode 100644
index 000000000..0998a18e4
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/secure.c
@@ -0,0 +1,481 @@
+/*
+ * Shared routines for client and server for
+ * secure read(), write(), getc(), and putc().
+ * Only one security context, thus only work on one fd at a time!
+ */
+#include "autoconf.h"
+
+#ifdef GSSAPI
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+extern gss_ctx_id_t gcontext;
+#endif /* GSSAPI */
+
+#include <secure.h>	/* stuff which is specific to client or server */
+
+#ifdef KRB5_KRB4_COMPAT
+#include <krb.h>
+
+CRED_DECL
+extern KTEXT_ST ticket;
+extern MSG_DAT msg_data;
+extern Key_schedule schedule;
+#endif /* KRB5_KRB4_COMPAT */
+
+#ifdef _WIN32
+#undef ERROR
+#endif
+
+#include <arpa/ftp.h>
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#ifdef _WIN32
+#include <port-sockets.h>
+#else
+#include <netinet/in.h>
+#endif
+#include <errno.h>
+
+#ifndef HAVE_STRERROR
+#define strerror(error) (sys_errlist[error])
+#ifdef NEED_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+#endif
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+typedef uint32_t ftp_uint32;
+typedef int32_t ftp_int32;
+
+static int secure_putbuf (int, unsigned char *, unsigned int);
+
+extern struct	sockaddr_in hisaddr;
+extern struct	sockaddr_in myaddr;
+extern int	dlevel;
+extern char	*auth_type;
+
+/* Some libc's (GNU libc, at least) define MAX as a macro. Forget that. */
+#ifdef MAX
+#undef MAX
+#endif
+
+#define MAX maxbuf
+extern unsigned int maxbuf; 	/* maximum output buffer size */
+extern unsigned char *ucbuf;	/* cleartext buffer */
+static unsigned int nout;	/* number of chars in ucbuf,
+				 * pointer into ucbuf */
+static unsigned int smaxbuf;    /* Internal saved value of maxbuf 
+				   in case changes on us */
+static unsigned int smaxqueue;  /* Maximum allowed to queue before 
+				   flush buffer. < smaxbuf by fudgefactor */
+
+#ifdef KRB5_KRB4_COMPAT
+#define KRB4_FUDGE_FACTOR 32	/* Amount of growth
+				 * from cleartext to ciphertext.
+				 * krb_mk_priv adds this # bytes.
+				 * Must be defined for each auth type.
+				 */
+#endif /* KRB5_KRB4_COMPAT */
+
+#ifdef KRB5_KRB4_COMPAT
+/* XXX - The following must be redefined if KERBEROS_V4 is not used
+ * but some other auth type is.  They must have the same properties. */
+#define looping_write krb_net_write
+#define looping_read krb_net_read
+#endif
+
+/* perhaps use these in general, certainly use them for GSSAPI */
+
+#ifndef looping_write
+static int
+looping_write(fd, buf, len)
+    int fd;
+    register const char *buf;
+    int len;
+{
+    int cc;
+    register int wrlen = len;
+    do {
+	cc = write(fd, buf, wrlen);
+	if (cc < 0) {
+	    if (errno == EINTR)
+		continue;
+	    return(cc);
+	}
+	else {
+	    buf += cc;
+	    wrlen -= cc;
+	}
+    } while (wrlen > 0);
+    return(len);
+}
+#endif
+#ifndef looping_read
+static int
+looping_read(fd, buf, len)
+    int fd;
+    register char *buf;
+    register int len;
+{
+    int cc, len2 = 0;
+
+    do {
+	cc = read(fd, buf, len);
+	if (cc < 0) {
+	    if (errno == EINTR)
+		continue;
+	    return(cc);		 /* errno is already set */
+	}		
+	else if (cc == 0) {
+	    return(len2);
+	} else {
+	    buf += cc;
+	    len2 += cc;
+	    len -= cc;
+	}
+    } while (len > 0);
+    return(len2);
+}
+#endif
+
+
+
+#define ERR	-2
+
+/* 
+ * Given maxbuf as a buffer size, determine how much can we
+ * really transfer given the overhead of different algorithms 
+ *
+ * Sets smaxbuf and smaxqueue
+ */
+
+static int secure_determine_constants()
+{
+    smaxbuf = maxbuf;
+    smaxqueue = maxbuf;
+
+#ifdef KRB5_KRB4_COMPAT
+    /* For KRB4 - we know the fudge factor to be 32 */
+    if (strcmp(auth_type, "KERBEROS_V4") == 0) {
+	smaxqueue = smaxbuf - KRB4_FUDGE_FACTOR;
+    }
+#endif
+#ifdef GSSAPI
+    if (strcmp(auth_type, "GSSAPI") == 0) {
+	OM_uint32 maj_stat, min_stat, mlen;
+	OM_uint32 msize = maxbuf;
+	maj_stat = gss_wrap_size_limit(&min_stat, gcontext, 
+				       (dlevel == PROT_P),
+				       GSS_C_QOP_DEFAULT,
+				       msize, &mlen);
+	if (maj_stat != GSS_S_COMPLETE) {
+			secure_gss_error(maj_stat, min_stat, 
+					 "GSSAPI fudge determination");
+			/* Return error how? */
+			return ERR;
+	}
+	smaxqueue = mlen;
+    }
+#endif
+    
+	return 0;
+}
+
+static int
+secure_putbyte(fd, c)
+int fd;
+unsigned char c;
+{
+	int ret;
+
+	if ((smaxbuf == 0) || (smaxqueue == 0) || (smaxbuf != maxbuf)) {
+	    ret = secure_determine_constants();
+	    if (ret) return ret;
+	}
+	ucbuf[nout++] = c;
+	if (nout == smaxqueue) {
+	  nout = 0;
+	  ret = secure_putbuf(fd, ucbuf, smaxqueue);
+	  return(ret?ret:c);
+	}
+	return (c);
+}
+
+/* returns:
+ *	 0  on success
+ *	-1  on error (errno set)
+ *	-2  on security error
+ */
+int secure_flush(fd)
+int fd;
+{
+	int ret;
+
+	if (dlevel == PROT_C)
+		return(0);
+	if (nout) {
+ 	        ret = secure_putbuf(fd, ucbuf, nout);
+		if (ret)
+			return(ret);
+	}
+	return(secure_putbuf(fd, (unsigned char *) "", nout = 0));
+}
+
+/* returns:
+ *	c>=0  on success
+ *	-1    on error
+ *	-2    on security error
+ */
+int secure_putc(c, stream)
+int c;
+FILE *stream;
+{
+	if (dlevel == PROT_C)
+		return(putc(c,stream));
+	return(secure_putbyte(fileno(stream), (unsigned char) c));
+}
+
+/* returns:
+ *	nbyte on success
+ *	-1  on error (errno set)
+ *	-2  on security error
+ */
+int 
+secure_write(fd, buf, nbyte)
+int fd;
+unsigned char *buf;
+unsigned int nbyte;
+{
+	unsigned int i;
+	int c;
+
+	if (dlevel == PROT_C)
+		return(write(fd,buf,nbyte));
+	for (i=0; nbyte>0; nbyte--)
+		if ((c = secure_putbyte(fd, buf[i++])) < 0)
+			return(c);
+	return(i);
+}
+
+/* returns:
+ *	 0  on success
+ *	-1  on error (errno set)
+ *	-2  on security error
+ */
+static int
+secure_putbuf(fd, buf, nbyte)
+  int fd;
+unsigned char *buf;
+unsigned int nbyte;
+{
+	static char *outbuf;		/* output ciphertext */
+	static unsigned int bufsize;	/* size of outbuf */
+	ftp_int32 length;
+	ftp_uint32 net_len;
+	unsigned int fudge = smaxbuf - smaxqueue; /* Difference in length
+						     buffer lengths required */
+
+	/* Other auth types go here ... */
+#ifdef KRB5_KRB4_COMPAT
+	if (bufsize < nbyte + fudge) {
+		if (outbuf?
+		    (outbuf = realloc(outbuf, (unsigned) (nbyte + fudge))):
+		    (outbuf = malloc((unsigned) (nbyte + fudge)))) {
+		    bufsize = nbyte + fudge;
+		} else {
+			bufsize = 0;
+			secure_error("%s (in malloc of PROT buffer)",
+				     strerror(errno));
+			return(ERR);
+		}
+	}
+
+	if (strcmp(auth_type, "KERBEROS_V4") == 0)
+	  if ((length = dlevel == PROT_P ?
+	    krb_mk_priv(buf, (unsigned char *) outbuf, nbyte, schedule,
+			SESSION, &myaddr, &hisaddr)
+	  : krb_mk_safe(buf, (unsigned char *) outbuf, nbyte, SESSION,
+			&myaddr, &hisaddr)) == -1) {
+		secure_error("krb_mk_%s failed for KERBEROS_V4",
+				dlevel == PROT_P ? "priv" : "safe");
+		return(ERR);
+	  }
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+	if (strcmp(auth_type, "GSSAPI") == 0) {
+		gss_buffer_desc in_buf, out_buf;
+		OM_uint32 maj_stat, min_stat;
+		int conf_state;
+		
+		in_buf.value = buf;
+		in_buf.length = nbyte;
+		maj_stat = gss_seal(&min_stat, gcontext,
+				    (dlevel == PROT_P), /* confidential */
+				    GSS_C_QOP_DEFAULT,
+				    &in_buf, &conf_state,
+				    &out_buf);
+		if (maj_stat != GSS_S_COMPLETE) {
+			/* generally need to deal */
+			/* ie. should loop, but for now just fail */
+			secure_gss_error(maj_stat, min_stat,
+					 dlevel == PROT_P?
+					 "GSSAPI seal failed":
+					 "GSSAPI sign failed");
+			return(ERR);
+		}
+
+		if (bufsize < out_buf.length) {
+			if (outbuf?
+			    (outbuf = realloc(outbuf, (unsigned) out_buf.length)):
+			    (outbuf = malloc((unsigned) out_buf.length))) {
+				bufsize = out_buf.length;
+			} else {
+				bufsize = 0;
+				secure_error("%s (in malloc of PROT buffer)",
+					     strerror(errno));
+				return(ERR);
+			}
+		}
+
+		length=out_buf.length;
+		memcpy(outbuf, out_buf.value, out_buf.length);
+		gss_release_buffer(&min_stat, &out_buf);
+	}
+#endif /* GSSAPI */
+	net_len = htonl((u_long) length);
+	if (looping_write(fd, (char *) &net_len, 4) == -1) return(-1);
+	if (looping_write(fd, outbuf, length) != length) return(-1);
+	return(0);
+}
+
+static int
+secure_getbyte(fd)
+int fd;
+{
+	/* number of chars in ucbuf, pointer into ucbuf */
+	static unsigned int nin, bufp;
+	int kerror;
+	ftp_uint32 length;
+
+	if (nin == 0) {
+		if ((kerror = looping_read(fd, (char *) &length,
+				sizeof(length)))
+				!= sizeof(length)) {
+			secure_error("Couldn't read PROT buffer length: %d/%s",
+				     kerror,
+				     kerror == -1 ? strerror(errno)
+				     : "premature EOF");
+			return(ERR);
+		}
+		if ((length = (u_long) ntohl(length)) > MAX) {
+			secure_error("Length (%d) of PROT buffer > PBSZ=%u", 
+				     length, MAX);
+			return(ERR);
+		}
+		if ((kerror = looping_read(fd, (char *) ucbuf, (int) length)) != length) {
+			secure_error("Couldn't read %u byte PROT buffer: %s",
+					length, kerror == -1 ?
+					strerror(errno) : "premature EOF");
+			return(ERR);
+		}
+		/* Other auth types go here ... */
+#ifdef KRB5_KRB4_COMPAT
+		if (strcmp(auth_type, "KERBEROS_V4") == 0) {
+		  if ((kerror = dlevel == PROT_P ?
+		    krb_rd_priv(ucbuf, length, schedule, SESSION,
+				&hisaddr, &myaddr, &msg_data)
+		  : krb_rd_safe(ucbuf, length, SESSION,
+				&hisaddr, &myaddr, &msg_data))) {
+			secure_error("krb_rd_%s failed for KERBEROS_V4 (%s)",
+					dlevel == PROT_P ? "priv" : "safe",
+					krb_get_err_text(kerror));
+			return(ERR);
+		  }
+		  memmove(ucbuf, msg_data.app_data, msg_data.app_length);
+		  nin = bufp = msg_data.app_length;
+		}
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+		if (strcmp(auth_type, "GSSAPI") == 0) {
+		  gss_buffer_desc xmit_buf, msg_buf;
+		  OM_uint32 maj_stat, min_stat;
+		  int conf_state;
+
+		  xmit_buf.value = ucbuf;
+		  xmit_buf.length = length;
+		  conf_state = (dlevel == PROT_P);
+		  /* decrypt/verify the message */
+		  maj_stat = gss_unseal(&min_stat, gcontext, &xmit_buf,
+					&msg_buf, &conf_state, NULL);
+		  if (maj_stat != GSS_S_COMPLETE) {
+		    secure_gss_error(maj_stat, min_stat, 
+				     (dlevel == PROT_P)?
+				     "failed unsealing ENC message":
+				     "failed unsealing MIC message");
+		    return ERR;
+		  }
+
+		  memcpy(ucbuf, msg_buf.value, nin = bufp = msg_buf.length);
+		  gss_release_buffer(&min_stat, &msg_buf);
+	      }
+#endif /* GSSAPI */
+		/* Other auth types go here ... */
+	}
+	if (nin == 0)
+		return(EOF);
+	else	return(ucbuf[bufp - nin--]);
+}
+
+/* returns:
+ *	c>=0 on success
+ *	-1   on EOF
+ *	-2   on security error
+ */
+int secure_getc(stream)
+FILE *stream;
+{
+	if (dlevel == PROT_C)
+		return(getc(stream));
+	return(secure_getbyte(fileno(stream)));
+}
+
+/* returns:
+ *	n>0 on success (n == # of bytes read)
+ *	0   on EOF
+ *	-1  on error (errno set), only for PROT_C
+ *	-2  on security error
+ */
+int secure_read(fd, buf, nbyte)
+int fd;
+char *buf;
+unsigned int nbyte;
+{
+	static int c;
+	int i;
+
+	if (dlevel == PROT_C)
+		return(read(fd,buf,nbyte));
+	if (c == EOF)
+		return(c = 0);
+	for (i=0; nbyte>0; nbyte--)
+		switch (c = secure_getbyte(fd)) {
+			case ERR: return(c);
+			case EOF: if (!i) c = 0;
+				  return(i);
+			default:  buf[i++] = c;
+		}
+	return(i);
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftp/secure.h b/krb5-1-6/src/appl/gssftp/ftp/secure.h
new file mode 100644
index 000000000..5d1bd0bdb
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftp/secure.h
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#define CRED_DECL	extern CREDENTIALS cred;
+#define SESSION		&cred.session
+#define myaddr		data_addr
+#define hisaddr		hisdataaddr
+
+int secure_flush (int);
+int secure_putc (int, FILE *);
+int secure_getc (FILE *);
+int secure_write (int, unsigned char *, unsigned int);
+int secure_read (int, char *, unsigned int);
+void secure_gss_error (OM_uint32 maj_stat, OM_uint32 min_stat, char *s);
+
+void secure_error(char *, ...);
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/CHANGES b/krb5-1-6/src/appl/gssftp/ftpd/CHANGES
new file mode 100644
index 000000000..39c7ebda0
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/CHANGES
@@ -0,0 +1,31 @@
+This version of ftpd has been fixed to conform to RFC959.
+
+Unfortunately, this conformance introduces a user visible change.  While
+technically, this is the fault of the client (ftp) instead of the server
+(ftpd), the change will be seen whenever an old ftp client calls a new ftpd
+server.
+
+The problem is that the old ftpd implemented the NLST command by execing
+/bin/ls.  This produced non-conformant output in some cases.  The new
+ftpd no longer executes /bin/ls for the NLST command as it has it's own
+built-in code.
+
+The user visible change in the ftp behavior is caused by the ftp client
+"knowing" that the daemon will exec /bin/ls.  This assumption should not
+have been made.
+
+When the old ftp client is used, one of the options is the "ls" command
+which sends the command NLST to the ftpd server.  The client should really
+be sending the LIST command.  The new ftp client has been corrected to do
+this.
+
+NLST should not normally be used directly by humans.  It is intended to
+interface with commands like mget or mput.
+
+Users who are not able to upgrade their ftp client may obtain the previous
+behavior, by using the command "dir" instead of "ls".
+
+These changes only apply to those sites using code derived from the Berkeley
+software releases (which means almost every UNIX based implementation will
+see this problem).
+
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/Makefile.in b/krb5-1-6/src/appl/gssftp/ftpd/Makefile.in
new file mode 100644
index 000000000..005089326
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/Makefile.in
@@ -0,0 +1,113 @@
+thisconfigdir=./..
+myfulldir=appl/gssftp/ftpd
+mydir=ftpd
+BUILDTOP=$(REL)..$(S)..$(S)..
+#
+# appl/gssftp/ftpd/Makefile.in
+#
+DEFINES = -DGSSAPI -DFTP_BUFSIZ=10240 #-DNOCONFIDENTIAL
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SETENVSRC=@SETENVSRC@
+SETENVOBJ=@SETENVOBJ@
+LIBOBJS=@LIBOBJS@
+COMERRLIB=$(BUILDTOP)/util/et/libcom_err.a
+FTPD_LIBS=@FTPD_LIBS@
+
+SRCS	= $(srcdir)/ftpd.c ftpcmd.c $(srcdir)/popen.c \
+	  $(srcdir)/vers.c \
+	  $(srcdir)/../ftp/glob.c \
+	  $(srcdir)/../ftp/radix.c \
+	  $(srcdir)/../ftp/secure.c \
+	  $(srcdir)/../../bsd/getdtablesize.c $(SETENVSRC)
+
+OBJS	= ftpd.o ftpcmd.o glob.o popen.o vers.o radix.o \
+	  secure.o $(LIBOBJS) $(SETENVOBJ)
+
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir) @KRB4_INCLUDES@
+
+all::	ftpd
+
+ftpd:	$(OBJS) $(PTY_DEPLIB) $(GSS_DEPLIBS) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $@ $(OBJS) $(FTPD_LIBS) $(PTY_LIB) $(UTIL_LIB) $(GSS_LIBS) $(KRB4COMPAT_LIBS)
+
+generate-files-mac: ftpcmd.c
+
+clean::
+	$(RM) ftpd ftpcmd.c
+
+depend::
+
+install::
+	for f in ftpd; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(SERVER_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		${DESTDIR}$(SERVER_MANDIR)/`echo $$f|sed '$(transform)'`.8; \
+	done
+
+
+ftpcmd.c: $(srcdir)/ftpcmd.y
+	$(RM) ftpcmd.c y.tab.c
+	$(YACC) $(srcdir)/ftpcmd.y
+	$(MV) y.tab.c ftpcmd.c
+
+glob.o: $(srcdir)/../ftp/glob.c
+	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../ftp/glob.c
+radix.o: $(srcdir)/../ftp/radix.c
+	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../ftp/radix.c
+secure.o: $(srcdir)/../ftp/secure.c
+	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../ftp/secure.c
+
+getdtablesize.o: $(srcdir)/../../bsd/getdtablesize.c
+	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../../bsd/getdtablesize.c
+
+setenv.o: $(srcdir)/../../bsd/setenv.c
+	$(CC) -c $(ALL_CFLAGS) $(srcdir)/../../bsd/setenv.c
+
+
+ftpd.o: $(srcdir)/pathnames.h
+secure.o: $(srcdir)/secure.h
+
+ftpd.o: $(srcdir)/ftpd.c
+ftpcmd.o: ftpcmd.c
+popen.o: $(srcdir)/popen.c
+vers.o: $(srcdir)/vers.c
+
+# NOPOSTFIX
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)ftpd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(KRB_ERR_H_DEP) \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/libpty.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-util.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/ftp.h \
+  $(srcdir)/../arpa/telnet.h ftpd.c ftpd_var.h pathnames.h \
+  secure.h
+$(OUTPRE)ftpcmd.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h $(KRB_ERR_H_DEP) \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/syslog.h \
+  $(srcdir)/../arpa/ftp.h $(srcdir)/../arpa/telnet.h \
+  ftpcmd.c ftpd_var.h
+$(OUTPRE)popen.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h ftpd_var.h \
+  popen.c
+$(OUTPRE)vers.$(OBJEXT): vers.c
+$(OUTPRE)glob.$(OBJEXT): $(srcdir)/../ftp/ftp_var.h \
+  $(srcdir)/../ftp/glob.c
+$(OUTPRE)radix.$(OBJEXT): $(srcdir)/../ftp/ftp_var.h \
+  $(srcdir)/../ftp/radix.c
+$(OUTPRE)secure.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(srcdir)/../arpa/ftp.h $(srcdir)/../ftp/secure.c secure.h
+$(OUTPRE)getdtablesize.$(OBJEXT): $(srcdir)/../../bsd/getdtablesize.c
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/ftpcmd.y b/krb5-1-6/src/appl/gssftp/ftpd/ftpcmd.y
new file mode 100644
index 000000000..30bced06a
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/ftpcmd.y
@@ -0,0 +1,1557 @@
+/* -*- fundamental -*-
+ * Copyright (c) 1985, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ftpcmd.y	5.24 (Berkeley) 2/25/91
+ */
+
+/*
+ * Grammar for FTP commands.
+ * See RFC 959.
+ * See Also draft-ietf-cat-ftpsec-08.txt.
+ */
+
+%{
+
+#ifndef lint
+static char sccsid[] = "@(#)ftpcmd.y	5.24 (Berkeley) 2/25/91";
+#endif /* not lint */
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/ftp.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <syslog.h>
+#include <time.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ftpd_var.h"
+
+extern	char *auth_type;
+
+unsigned int maxbuf, actualbuf;
+unsigned char *ucbuf;
+
+static int kerror;	/* XXX needed for all auth types */
+#ifdef KRB5_KRB4_COMPAT
+extern	struct sockaddr_in his_addr, ctrl_addr;
+#include <krb.h>
+extern AUTH_DAT kdata;
+extern Key_schedule schedule;
+extern MSG_DAT msg_data;
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+extern gss_ctx_id_t gcontext;
+#endif
+
+#ifndef unix
+/* sigh */
+#if defined(_AIX) || defined(__hpux) || defined(BSD)
+#define unix
+#endif
+#endif
+
+#ifndef NBBY
+#define NBBY 8
+#endif
+
+static struct sockaddr_in host_port;
+
+extern	struct sockaddr_in data_dest;
+extern	int logged_in;
+extern	struct passwd *pw;
+extern	int guest;
+extern	int logging;
+extern	int type;
+extern	int form;
+extern	int clevel;
+extern	int debug;
+
+
+extern	int allow_ccc;
+extern	int ccc_ok;
+extern	int timeout;
+extern	int maxtimeout;
+extern  int pdata;
+extern	int authlevel;
+extern	char hostname[], remotehost[];
+extern	char proctitle[];
+extern	char *globerr;
+extern	int usedefault;
+extern  int transflag;
+extern  char tmpline[];
+
+char	**ftpglob();
+
+off_t	restart_point;
+
+static	int cmd_type;
+static	int cmd_form;
+static	int cmd_bytesz;
+char	cbuf[FTP_BUFSIZ]; /* was 512 */
+char	*fromname;
+
+/* bison needs these decls up front */
+extern jmp_buf errcatch;
+
+#define	CMD	0	/* beginning of command */
+#define	ARGS	1	/* expect miscellaneous arguments */
+#define	STR1	2	/* expect SP followed by STRING */
+#define	STR2	3	/* expect STRING */
+#define	OSTR	4	/* optional SP then STRING */
+#define	ZSTR1	5	/* SP then optional STRING */
+#define	ZSTR2	6	/* optional STRING after SP */
+#define	SITECMD	7	/* SITE command */
+#define	NSTR	8	/* Number followed by a string */
+
+struct tab {
+	char	*name;
+	short	token;
+	short	state;
+	short	implemented;	/* 1 if command is implemented */
+	char	*help;
+};
+struct tab cmdtab[];
+struct tab sitetab[];
+
+void sizecmd(char *);
+void help(struct tab *, char *);
+static int yylex(void);
+static char *copy(char *);
+%}
+
+%union { int num; char *str; }
+
+%token
+	SP	CRLF	COMMA	STRING	NUMBER
+
+	USER	PASS	ACCT	REIN	QUIT	PORT
+	PASV	TYPE	STRU	MODE	RETR	STOR
+	APPE	MLFL	MAIL	MSND	MSOM	MSAM
+	MRSQ	MRCP	ALLO	REST	RNFR	RNTO
+	ABOR	DELE	CWD	LIST	NLST	SITE
+	STAT	HELP	NOOP	MKD	RMD	PWD
+	CDUP	STOU	SMNT	SYST	SIZE	MDTM
+	AUTH	ADAT	PROT    PBSZ
+	CCC
+
+	UMASK	IDLE	CHMOD
+
+	LEXERR
+
+%type <num> NUMBER
+%type <num> form_code prot_code struct_code mode_code octal_number
+%type <num> check_login byte_size nonguest
+
+%type <str> STRING
+%type <str> password pathname username pathstring
+
+%start	cmd_list
+
+%%
+
+cmd_list:	/* empty */
+	|	cmd_list cmd
+		{
+			fromname = (char *) 0;
+			restart_point = (off_t) 0;
+		}
+	|	cmd_list rcmd
+	;
+
+cmd:		USER SP username CRLF
+		{
+			user((char *) $3);
+			free((char *) $3);
+		}
+	|	PASS SP password CRLF
+		{
+			pass((char *) $3);
+			free((char *) $3);
+		}
+	|	PORT SP host_port CRLF
+		{
+			/*
+			 * Don't allow a port < 1024 if we're not
+			 * connecting back to the original source address
+			 * This prevents nastier forms of the bounce attack.
+			 */
+			if (ntohs(host_port.sin_port) < 1024)
+				reply(504, "Port number too low");
+			else {
+				data_dest = host_port;
+				usedefault = 0;
+				if (pdata >= 0) {
+					(void) close(pdata);
+					pdata = -1;
+				}
+				reply(200, "PORT command successful.");
+			}
+		}
+	|	PASV check_login CRLF
+		{
+			if ($2)
+				passive();
+		}
+	|	PROT SP prot_code CRLF
+		{
+		    if (maxbuf)
+			setdlevel ($3);
+		    else
+			reply(503, "Must first set PBSZ");
+		}
+	|	CCC CRLF
+		{
+			if (!allow_ccc) {
+			    reply(534, "CCC not supported");
+			}
+			else {
+			    if(clevel == PROT_C && !ccc_ok) {
+			        reply(533, "CCC command must be integrity protected");
+			    } else {
+			        reply(200, "CCC command successful.");
+				ccc_ok = 1;
+			    }
+			}
+		}
+	|	PBSZ SP STRING CRLF
+		{
+			/* Others may want to do something more fancy here */
+			if (!auth_type)
+			    reply(503, "Must first perform authentication");
+			else if (strlen($3) > 10 ||
+				 (strlen($3) == 10 && 
+				  strcmp($3,"4294967296") >= 0))
+			    reply(501, "Bad value for PBSZ: %s", $3);
+			else {
+			    if (ucbuf) (void) free(ucbuf);
+			    actualbuf = (unsigned int) atol($3);
+			    /* I attempt what is asked for first, and if that
+			       fails, I try dividing by 4 */
+			    while ((ucbuf = (unsigned char *)malloc(actualbuf)) == NULL)
+				if (actualbuf)
+				    lreply(200, "Trying %u", actualbuf >>= 2);
+				else {
+				    perror_reply(421,
+					"Local resource failure: malloc");
+				    dologout(1);
+				}
+			    reply(200, "PBSZ=%u", maxbuf = actualbuf);
+			}
+		}
+	|	TYPE SP type_code CRLF
+		{
+			switch (cmd_type) {
+
+			case TYPE_A:
+				if (cmd_form == FORM_N) {
+					reply(200, "Type set to A.");
+					type = cmd_type;
+					form = cmd_form;
+				} else
+					reply(504, "Form must be N.");
+				break;
+
+			case TYPE_E:
+				reply(504, "Type E not implemented.");
+				break;
+
+			case TYPE_I:
+				reply(200, "Type set to I.");
+				type = cmd_type;
+				break;
+
+			case TYPE_L:
+#if NBBY == 8
+				if (cmd_bytesz == 8) {
+					reply(200,
+					    "Type set to L (byte size 8).");
+					type = cmd_type;
+				} else
+					reply(504, "Byte size must be 8.");
+#else /* NBBY == 8 */
+				UNIMPLEMENTED for NBBY != 8
+#endif /* NBBY == 8 */
+			}
+		}
+	|	STRU SP struct_code CRLF
+		{
+			switch ($3) {
+
+			case STRU_F:
+				reply(200, "STRU F ok.");
+				break;
+
+			default:
+				reply(504, "Unimplemented STRU type.");
+			}
+		}
+	|	MODE SP mode_code CRLF
+		{
+			switch ($3) {
+
+			case MODE_S:
+				reply(200, "MODE S ok.");
+				break;
+
+			default:
+				reply(502, "Unimplemented MODE type.");
+			}
+		}
+	|	ALLO SP NUMBER CRLF
+		{
+			reply(202, "ALLO command ignored.");
+		}
+	|	ALLO SP NUMBER SP 'R' SP NUMBER CRLF
+		{
+			reply(202, "ALLO command ignored.");
+		}
+	|	RETR check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				retrieve((char *) 0, (char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	STOR check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				store_file((char *) $4, "w", 0);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	APPE check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				store_file((char *) $4, "a", 0);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	NLST check_login CRLF
+		{
+			if ($2)
+				send_file_list(".");
+		}
+	|	NLST check_login SP STRING CRLF
+		{
+			if ($2 && $4 != NULL) 
+				send_file_list((char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	LIST check_login CRLF
+		{
+			if ($2)
+				retrieve("/bin/ls -lgA", "");
+		}
+	|	LIST check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				retrieve("/bin/ls -lgA %s", (char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	STAT check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				statfilecmd((char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	STAT CRLF
+		{
+			statcmd();
+		}
+	|	DELE check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				delete_file((char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	RNTO SP pathname CRLF
+		{
+			if (fromname) {
+				renamecmd(fromname, (char *) $3);
+				free(fromname);
+				fromname = (char *) 0;
+			} else {
+				reply(503, "Bad sequence of commands.");
+			}
+			free((char *) $3);
+		}
+	|	ABOR CRLF
+		{
+			reply(225, "ABOR command successful.");
+		}
+	|	CWD check_login CRLF
+		{
+			if ($2)
+				cwd(pw->pw_dir);
+		}
+	|	CWD check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				cwd((char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	HELP CRLF
+		{
+			help(cmdtab, (char *) 0);
+		}
+	|	HELP SP STRING CRLF
+		{
+			register char *cp = (char *)$3;
+
+			if (strncasecmp(cp, "SITE", 4) == 0) {
+				cp = (char *)$3 + 4;
+				if (*cp == ' ')
+					cp++;
+				if (*cp)
+					help(sitetab, cp);
+				else
+					help(sitetab, (char *) 0);
+			} else
+				help(cmdtab, (char *) $3);
+		}
+	|	NOOP CRLF
+		{
+			reply(200, "NOOP command successful.");
+		}
+	|	MKD nonguest SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				makedir((char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	RMD nonguest SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				removedir((char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	PWD check_login CRLF
+		{
+			if ($2)
+				pwd();
+		}
+	|	CDUP check_login CRLF
+		{
+			if ($2)
+				cwd("..");
+		}
+	|	SITE SP HELP CRLF
+		{
+			help(sitetab, (char *) 0);
+		}
+	|	SITE SP HELP SP STRING CRLF
+		{
+			help(sitetab, (char *) $5);
+		}
+	|	SITE SP UMASK check_login CRLF
+		{
+			int oldmask;
+
+			if ($4) {
+				oldmask = umask(0);
+				(void) umask(oldmask);
+				reply(200, "Current UMASK is %03o", oldmask);
+			}
+		}
+	|	SITE SP UMASK nonguest SP octal_number CRLF
+		{
+			int oldmask;
+
+			if ($4) {
+				if (($6 == -1) || ($6 > 0777)) {
+					reply(501, "Bad UMASK value");
+				} else {
+					oldmask = umask($6);
+					reply(200,
+					    "UMASK set to %03o (was %03o)",
+					    $6, oldmask);
+				}
+			}
+		}
+	|	SITE SP CHMOD nonguest SP octal_number SP pathname CRLF
+		{
+			if ($4 && ($8 != NULL)) {
+				if ($6 > 0777)
+					reply(501,
+				"CHMOD: Mode value must be between 0 and 0777");
+				else if (chmod((char *) $8, $6) < 0)
+					perror_reply(550, (char *) $8);
+				else
+					reply(200, "CHMOD command successful.");
+			}
+			if ($8 != NULL)
+				free((char *) $8);
+		}
+	|	SITE SP IDLE CRLF
+		{
+			reply(200,
+			    "Current IDLE time limit is %d seconds; max %d",
+				timeout, maxtimeout);
+		}
+	|	SITE SP IDLE SP NUMBER CRLF
+		{
+			if ($5 < 30 || $5 > maxtimeout) {
+				reply(501,
+			"Maximum IDLE time must be between 30 and %d seconds",
+				    maxtimeout);
+			} else {
+				timeout = $5;
+				(void) alarm((unsigned) timeout);
+				reply(200,
+				    "Maximum IDLE time set to %d seconds",
+				    timeout);
+			}
+		}
+	|	STOU check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				store_file((char *) $4, "w", 1);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	SYST CRLF
+		{
+#ifdef unix
+#ifdef __svr4__
+#undef BSD
+#endif
+#ifdef BSD
+			reply(215, "UNIX Type: L%d Version: BSD-%d",
+				NBBY, BSD);
+#else /* BSD */
+			reply(215, "UNIX Type: L%d", NBBY);
+#endif /* BSD */
+#else /* unix */
+			reply(215, "UNKNOWN Type: L%d", NBBY);
+#endif /* unix */
+		}
+
+		/*
+		 * SIZE is not in RFC959, but Postel has blessed it and
+		 * it will be in the updated RFC.
+		 *
+		 * Return size of file in a format suitable for
+		 * using with RESTART (we just count bytes).
+		 */
+	|	SIZE check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL)
+				sizecmd((char *) $4);
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+
+		/*
+		 * MDTM is not in RFC959, but Postel has blessed it and
+		 * it will be in the updated RFC.
+		 *
+		 * Return modification time of file as an ISO 3307
+		 * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx
+		 * where xxx is the fractional second (of any precision,
+		 * not necessarily 3 digits)
+		 */
+	|	MDTM check_login SP pathname CRLF
+		{
+			if ($2 && $4 != NULL) {
+				struct stat stbuf;
+				if (stat($4, &stbuf) < 0)
+					perror_reply(550, $4);
+				else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
+					reply(550, "%s: not a plain file.",
+						(char *) $4);
+				} else {
+					register struct tm *t;
+					struct tm *gmtime();
+					t = gmtime(&stbuf.st_mtime);
+					reply(213,
+					    "%4d%02d%02d%02d%02d%02d",
+					    1900+t->tm_year, t->tm_mon+1, 
+					    t->tm_mday, t->tm_hour, 
+					    t->tm_min, t->tm_sec);
+				}
+			}
+			if ($4 != NULL)
+				free((char *) $4);
+		}
+	|	AUTH SP STRING CRLF
+		{
+			auth((char *) $3);
+		}
+	|	ADAT SP STRING CRLF
+		{
+			auth_data((char *) $3);
+			free((char *) $3);
+		}
+	|	QUIT CRLF
+		{
+			reply(221, "Goodbye.");
+			dologout(0);
+		}
+	|	error CRLF
+		{
+			yyerrok;
+		}
+	;
+rcmd:		RNFR check_login SP pathname CRLF
+		{
+			restart_point = (off_t) 0;
+			if ($2 && $4) {
+				fromname = renamefrom((char *) $4);
+				if (fromname == (char *) 0 && $4) {
+					free((char *) $4);
+				}
+			}
+		}
+	|	REST SP byte_size CRLF
+		{
+			fromname = (char *) 0;
+			restart_point = $3;
+			reply(350, "Restarting at %ld. %s", 
+			      (long) restart_point,
+			      "Send STORE or RETRIEVE to initiate transfer.");
+		}
+	;
+		
+username:	STRING
+	;
+
+password:	/* empty */
+		{
+			*(char **)&($$) = (char *)calloc(1, sizeof(char));
+		}
+	|	STRING
+	;
+
+byte_size:	NUMBER
+	;
+
+host_port:	NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA 
+		NUMBER COMMA NUMBER
+		{
+			register char *a, *p;
+
+			a = (char *)&host_port.sin_addr;
+			a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7;
+			p = (char *)&host_port.sin_port;
+			p[0] = $9; p[1] = $11;
+			host_port.sin_family = AF_INET;
+		}
+	;
+
+form_code:	'N'
+	{
+		$$ = FORM_N;
+	}
+	|	'T'
+	{
+		$$ = FORM_T;
+	}
+	|	'C'
+	{
+		$$ = FORM_C;
+	}
+	;
+
+prot_code:	'C'
+	{
+		$$ = PROT_C;
+	}
+	|	'S'
+	{
+		$$ = PROT_S;
+	}
+	|	'P'
+	{
+		$$ = PROT_P;
+	}
+	|	'E'
+	{
+		$$ = PROT_E;
+	}
+	;
+
+type_code:	'A'
+	{
+		cmd_type = TYPE_A;
+		cmd_form = FORM_N;
+	}
+	|	'A' SP form_code
+	{
+		cmd_type = TYPE_A;
+		cmd_form = $3;
+	}
+	|	'E'
+	{
+		cmd_type = TYPE_E;
+		cmd_form = FORM_N;
+	}
+	|	'E' SP form_code
+	{
+		cmd_type = TYPE_E;
+		cmd_form = $3;
+	}
+	|	'I'
+	{
+		cmd_type = TYPE_I;
+	}
+	|	'L'
+	{
+		cmd_type = TYPE_L;
+		cmd_bytesz = NBBY;
+	}
+	|	'L' SP byte_size
+	{
+		cmd_type = TYPE_L;
+		cmd_bytesz = $3;
+	}
+	/* this is for a bug in the BBN ftp */
+	|	'L' byte_size
+	{
+		cmd_type = TYPE_L;
+		cmd_bytesz = $2;
+	}
+	;
+
+struct_code:	'F'
+	{
+		$$ = STRU_F;
+	}
+	|	'R'
+	{
+		$$ = STRU_R;
+	}
+	|	'P'
+	{
+		$$ = STRU_P;
+	}
+	;
+
+mode_code:	'S'
+	{
+		$$ = MODE_S;
+	}
+	|	'B'
+	{
+		$$ = MODE_B;
+	}
+	|	'C'
+	{
+		$$ = MODE_C;
+	}
+	;
+
+pathname:	pathstring
+	{
+		/*
+		 * Problem: this production is used for all pathname
+		 * processing, but only gives a 550 error reply.
+		 * This is a valid reply in some cases but not in others.
+		 */
+		if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) {
+			char **vv;
+
+			vv = ftpglob((char *) $1);
+			$$ = (vv != NULL) ? *vv : NULL;
+			if ($$ == NULL) {
+				if (globerr == NULL)
+					$$ = $1;
+				else {
+					reply(550, "%s", globerr);
+					free((char *) $1);
+				}
+			} else
+				free((char *) $1);
+		} else
+			$$ = $1;
+	}
+	;
+
+pathstring:	STRING
+	;
+
+octal_number:	NUMBER
+	{
+		register int ret, dec, multby, digit;
+
+		/*
+		 * Convert a number that was read as decimal number
+		 * to what it would be if it had been read as octal.
+		 */
+		dec = $1;
+		multby = 1;
+		ret = 0;
+		while (dec) {
+			digit = dec%10;
+			if (digit > 7) {
+				ret = -1;
+				break;
+			}
+			ret += digit * multby;
+			multby *= 8;
+			dec /= 10;
+		}
+		$$ = ret;
+	}
+	;
+
+check_login:	/* empty */
+	{
+		if (logged_in)
+			$$ = 1;
+		else {
+			reply(530, "Please login with USER and PASS.");
+			$$ = 0;
+		}
+	}
+	;
+
+nonguest: check_login
+	{
+		if (guest) {
+			reply(550, "Operation prohibited for anonymous users.");
+			$$ = 0;
+		}
+		else
+			$$ = $1;
+	}
+	;
+%%
+
+struct tab cmdtab[] = {		/* In order defined in RFC 765 */
+	{ "USER", USER, STR1, 1,	"<sp> username" },
+	{ "PASS", PASS, ZSTR1, 1,	"<sp> password" },
+	{ "ACCT", ACCT, STR1, 0,	"(specify account)" },
+	{ "SMNT", SMNT, ARGS, 0,	"(structure mount)" },
+	{ "REIN", REIN, ARGS, 0,	"(reinitialize server state)" },
+	{ "QUIT", QUIT, ARGS, 1,	"(terminate service)", },
+	{ "PORT", PORT, ARGS, 1,	"<sp> b0, b1, b2, b3, b4" },
+	{ "PASV", PASV, ARGS, 1,	"(set server in passive mode)" },
+	{ "TYPE", TYPE, ARGS, 1,	"<sp> [ A | E | I | L ]" },
+	{ "STRU", STRU, ARGS, 1,	"(specify file structure)" },
+	{ "MODE", MODE, ARGS, 1,	"(specify transfer mode)" },
+	{ "RETR", RETR, STR1, 1,	"<sp> file-name" },
+	{ "STOR", STOR, STR1, 1,	"<sp> file-name" },
+	{ "APPE", APPE, STR1, 1,	"<sp> file-name" },
+	{ "MLFL", MLFL, OSTR, 0,	"(mail file)" },
+	{ "MAIL", MAIL, OSTR, 0,	"(mail to user)" },
+	{ "MSND", MSND, OSTR, 0,	"(mail send to terminal)" },
+	{ "MSOM", MSOM, OSTR, 0,	"(mail send to terminal or mailbox)" },
+	{ "MSAM", MSAM, OSTR, 0,	"(mail send to terminal and mailbox)" },
+	{ "MRSQ", MRSQ, OSTR, 0,	"(mail recipient scheme question)" },
+	{ "MRCP", MRCP, STR1, 0,	"(mail recipient)" },
+	{ "ALLO", ALLO, ARGS, 1,	"allocate storage (vacuously)" },
+	{ "REST", REST, ARGS, 1,	"(restart command)" },
+	{ "RNFR", RNFR, STR1, 1,	"<sp> file-name" },
+	{ "RNTO", RNTO, STR1, 1,	"<sp> file-name" },
+	{ "ABOR", ABOR, ARGS, 1,	"(abort operation)" },
+	{ "DELE", DELE, STR1, 1,	"<sp> file-name" },
+	{ "CWD",  CWD,  OSTR, 1,	"[ <sp> directory-name ]" },
+	{ "XCWD", CWD,	OSTR, 1,	"[ <sp> directory-name ]" },
+	{ "LIST", LIST, OSTR, 1,	"[ <sp> path-name ]" },
+	{ "NLST", NLST, OSTR, 1,	"[ <sp> path-name ]" },
+	{ "SITE", SITE, SITECMD, 1,	"site-cmd [ <sp> arguments ]" },
+	{ "SYST", SYST, ARGS, 1,	"(get type of operating system)" },
+	{ "STAT", STAT, OSTR, 1,	"[ <sp> path-name ]" },
+	{ "HELP", HELP, OSTR, 1,	"[ <sp> <string> ]" },
+	{ "NOOP", NOOP, ARGS, 1,	"" },
+	{ "MKD",  MKD,  STR1, 1,	"<sp> path-name" },
+	{ "XMKD", MKD,  STR1, 1,	"<sp> path-name" },
+	{ "RMD",  RMD,  STR1, 1,	"<sp> path-name" },
+	{ "XRMD", RMD,  STR1, 1,	"<sp> path-name" },
+	{ "PWD",  PWD,  ARGS, 1,	"(return current directory)" },
+	{ "XPWD", PWD,  ARGS, 1,	"(return current directory)" },
+	{ "CDUP", CDUP, ARGS, 1,	"(change to parent directory)" },
+	{ "XCUP", CDUP, ARGS, 1,	"(change to parent directory)" },
+	{ "STOU", STOU, STR1, 1,	"<sp> file-name" },
+	{ "AUTH", AUTH, STR1, 1,	"<sp> auth-type" },
+	{ "ADAT", ADAT, STR1, 1,	"<sp> auth-data" },
+	{ "PROT", PROT, ARGS, 1,	"<sp> protection-level" },
+	{ "PBSZ", PBSZ, STR1, 1,	"<sp> buffer-size" },
+	{ "CCC",  CCC,  ARGS, 1,	"(clear command channel)" },
+	{ "SIZE", SIZE, OSTR, 1,	"<sp> path-name" },
+	{ "MDTM", MDTM, OSTR, 1,	"<sp> path-name" },
+	{ NULL,   0,    0,    0,	0 }
+};
+
+struct tab sitetab[] = {
+	{ "UMASK", UMASK, ARGS, 1,	"[ <sp> umask ]" },
+	{ "IDLE", IDLE, ARGS, 1,	"[ <sp> maximum-idle-time ]" },
+	{ "CHMOD", CHMOD, NSTR, 1,	"<sp> mode <sp> file-name" },
+	{ "HELP", HELP, OSTR, 1,	"[ <sp> <string> ]" },
+	{ NULL,   0,    0,    0,	0 }
+};
+
+static struct tab *
+lookup(p, cmd)
+	register struct tab *p;
+	char *cmd;
+{
+
+	for (; p->name != NULL; p++)
+		if (strcmp(cmd, p->name) == 0)
+			return (p);
+	return (0);
+}
+
+/*
+ * urgsafe_getc - hacked up getc to ignore EOF if SIOCATMARK returns TRUE
+ */
+static int
+urgsafe_getc(f)
+	FILE *f;
+{
+	register int c;
+	int atmark;
+
+	c = getc(f);
+	if (c == EOF) {
+		if (ioctl(fileno(f), SIOCATMARK, &atmark) != -1) {
+			c = getc(f);
+			syslog(LOG_DEBUG, "atmark: c=%d", c);
+		}
+	}
+	return c;
+}
+
+#include <arpa/telnet.h>
+
+/*
+ * getline - a hacked up version of fgets to ignore TELNET escape codes.
+ */
+char *
+ftpd_getline(s, n, iop)
+	char *s;
+	int n;
+	register FILE *iop;
+{
+	register int c;
+	register char *cs;
+
+	cs = s;
+/* tmpline may contain saved command from urgent mode interruption */
+	for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
+		*cs++ = tmpline[c];
+		if (tmpline[c] == '\n') {
+			*cs++ = '\0';
+			if (debug)
+				syslog(LOG_DEBUG, "command: %s", s);
+			tmpline[0] = '\0';
+			return(s);
+		}
+		if (c == 0)
+			tmpline[0] = '\0';
+	}
+	while ((c = urgsafe_getc(iop)) != EOF) {
+		c &= 0377;
+		if (c == IAC) {
+			if (debug) syslog(LOG_DEBUG, "got IAC");
+		    if ((c = urgsafe_getc(iop)) != EOF) {
+			c &= 0377;
+			if (debug) syslog(LOG_DEBUG, "got IAC %d", c);
+			switch (c) {
+			case WILL:
+			case WONT:
+				c = urgsafe_getc(iop);
+				printf("%c%c%c", IAC, DONT, 0377&c);
+				(void) fflush(stdout);
+				continue;
+			case DO:
+			case DONT:
+				c = urgsafe_getc(iop);
+				printf("%c%c%c", IAC, WONT, 0377&c);
+				(void) fflush(stdout);
+				continue;
+			case IAC:
+				break;
+			default:
+				continue;	/* ignore command */
+			}
+		    }
+		}
+		*cs++ = c;
+		if (--n <= 0 || c == '\n')
+			break;
+	}
+	if (c == EOF && cs == s)
+		return (NULL);
+	*cs++ = '\0';
+	if (auth_type) {
+	    char out[sizeof(cbuf)], *cp;
+	    int len, mic;
+
+
+	    /* Check to see if we have a protected command. */
+	    if (!((mic = strncmp(s, "ENC", 3)) && strncmp(s, "MIC", 3)
+		&& strncmp(s, "AUTH", 4)
+#ifndef NOCONFIDENTIAL
+	        && strncmp(s, "CONF", 4)
+#endif
+	        ) && (cs = strpbrk(s, " \r\n"))) {
+	    	    *cs++ = '\0'; /* If so, split it into s and cs. */
+	    } else { /* If not, check if unprotected commands are allowed. */
+		if(ccc_ok) {
+		    clevel = PROT_C;
+		    upper(s);
+		    return(s);
+		} else {
+		    reply(533, "All commands must be protected.");
+		    syslog(LOG_ERR, "Unprotected command received");
+		    *s = '\0';
+		    return(s);
+		}
+	    }
+	    upper(s);
+	    if (debug)
+	        syslog(LOG_INFO, "command %s received (mic=%d)", s, mic);
+#ifdef NOCONFIDENTIAL
+	    if (!strcmp(s, "CONF")) {
+		reply(537, "CONF protected commands not supported.");
+		*s = '\0';
+		return(s);
+	    }
+#endif
+/* Some paranoid sites may want to require that commands be encrypted. */
+#ifdef PARANOID
+	    if (mic) {
+		reply(533, "All commands must be ENC protected.  Retry command under ENC.");
+		*s = '\0';
+		return(s);
+	    }
+#endif /* PARANOID */
+#ifdef NOENCRYPTION
+	    if (!mic) {
+		reply(533, "ENC protection not supported.  Retry command under MIC.");
+		*s = '\0';
+		return(s);
+	    }
+#endif /* NOENCRYPTION */
+	    if ((cp = strpbrk(cs, " \r\n")))
+		*cp = '\0';
+	    kerror = radix_encode(cs, out, &len, 1);
+	    if (kerror) {
+		reply(501, "Can't base 64 decode argument to %s command (%s)",
+		      mic ? "MIC" : "ENC", radix_error(kerror));
+		*s = '\0';
+		return(s);
+	    }
+	    if (debug) syslog(LOG_DEBUG, "getline got %d from %s <%s>\n", 
+			      len, cs, mic?"MIC":"ENC");
+	    clevel = mic ? PROT_S : PROT_P;
+#ifdef KRB5_KRB4_COMPAT
+	    if (strcmp(auth_type, "KERBEROS_V4") == 0) {
+		if ((kerror = mic ?
+		    krb_rd_safe((unsigned char *)out, len, &kdata.session,
+			    &his_addr, &ctrl_addr, &msg_data)
+		  : krb_rd_priv((unsigned char *)out, len, schedule,
+			    &kdata.session, &his_addr, &ctrl_addr, &msg_data))
+			!= KSUCCESS) {
+		    reply(535, "%s! (%s)",
+			   mic ? "MIC command modified" : "ENC command garbled",
+			   krb_get_err_text(kerror));
+		    syslog(LOG_ERR,"%s failed: %s",
+			   mic ? "MIC krb_rd_safe" : "ENC krb_rd_priv",
+			   krb_get_err_text(kerror));
+		    *s = '\0';
+		    return(s);
+		}
+		(void) memcpy(s, msg_data.app_data, msg_data.app_length);
+		(void) strcpy(s+msg_data.app_length, "\r\n");
+	    }
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+/* we know this is a MIC or ENC already, and out/len already has the bits */
+	    if (strcmp(auth_type, "GSSAPI") == 0) {
+		gss_buffer_desc xmit_buf, msg_buf;
+		OM_uint32 maj_stat, min_stat;
+		int conf_state;
+
+		xmit_buf.value = out;
+		xmit_buf.length = len;
+		/* decrypt the message */
+		conf_state = !mic;
+		maj_stat = gss_unseal(&min_stat, gcontext, &xmit_buf,
+				      &msg_buf, &conf_state, NULL);
+		if (maj_stat == GSS_S_CONTINUE_NEEDED) {
+			if (debug) syslog(LOG_DEBUG, "%s-unseal continued", 
+					  mic?"MIC":"ENC");
+			reply(535, "%s-unseal continued, oops",
+			      mic?"MIC":"ENC");
+			*s = 0; return s;
+		}
+		if (maj_stat != GSS_S_COMPLETE) {
+			reply_gss_error(535, maj_stat, min_stat, 
+					mic? "failed unsealing MIC message":
+					"failed unsealing ENC message");
+			*s = 0;
+			return s;
+		}
+
+		memcpy(s, msg_buf.value, msg_buf.length);
+		strcpy(s+msg_buf.length-(s[msg_buf.length-1]?0:1), "\r\n");
+		gss_release_buffer(&min_stat, &msg_buf);
+	    }
+#endif /* GSSAPI */
+	    /* Other auth types go here ... */
+
+	    /* A password should never be MICed, but the CNS ftp
+	     * client and the pre-6/98 Krb5 client did this if you
+	     * authenticated but didn't encrypt.
+	     */
+	    if (authlevel && mic && !strncmp(s, "PASS", 4)) {
+	    	lreply(530, "There is a problem with your ftp client. Password refused.");
+		reply(530, "Enable encryption before logging in, or update your ftp program.");
+		*s = 0;
+		return s;
+	    }
+
+	}
+#if defined KRB5_KRB4_COMPAT || defined GSSAPI	/* or other auth types */
+	else {	/* !auth_type */
+	    if ( (!(strncmp(s, "ENC", 3))) || (!(strncmp(s, "MIC", 3)))
+#ifndef NOCONFIDENTIAL
+                || (!(strncmp(s, "CONF", 4)))
+#endif
+                                        ) {
+                reply(503, "Must perform authentication before sending protected commands");
+                *s = '\0';
+                return(s);
+	    }
+	}
+#endif /* KRB5_KRB4_COMPAT || GSSAPI */
+
+	if (debug) {
+		if (!strncmp(s, "PASS ", 5) && !guest)
+			syslog(LOG_DEBUG, "command: <PASS XXX>");
+		else
+			syslog(LOG_DEBUG, "command: <%.*s>(%d)",
+			       strlen(s) - 2, s, strlen(s));
+	}
+	return (s);
+}
+
+static krb5_sigtype
+toolong(sig)
+	int sig;
+{
+	time_t now;
+
+	reply(421,
+	  "Timeout (%d seconds): closing control connection.", timeout);
+	(void) time(&now);
+	if (logging) {
+		syslog(LOG_INFO,
+			"User %s timed out after %d seconds at %s",
+			(pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
+	}
+	dologout(1);
+}
+
+static int
+yylex()
+{
+	static int cpos, state;
+	register char *cp, *cp2;
+	register struct tab *p;
+	int n;
+	char c;
+
+	for (;;) {
+		switch (state) {
+
+		case CMD:
+			(void) signal(SIGALRM, toolong);
+			(void) alarm((unsigned) timeout);
+			if (ftpd_getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
+				reply(221, "You could at least say goodbye.");
+				dologout(0);
+			}
+			(void) alarm(0);
+
+			/* If getline() finds an error, the string is null */
+			if (*cbuf == '\0')
+				continue;
+
+#ifdef SETPROCTITLE
+			if (strncasecmp(cbuf, "PASS", 4) != NULL)
+				setproctitle("%s: %s", proctitle, cbuf);
+#endif /* SETPROCTITLE */
+			if ((cp = strchr(cbuf, '\r'))) {
+				*cp++ = '\n';
+				*cp = '\0';
+			}
+			if ((cp = strpbrk(cbuf, " \n")))
+				cpos = cp - cbuf;
+			if (cpos == 0)
+				cpos = 4;
+			c = cbuf[cpos];
+			cbuf[cpos] = '\0';
+			upper(cbuf);
+			p = lookup(cmdtab, cbuf);
+			cbuf[cpos] = c;
+			if (p != 0) {
+				if (p->implemented == 0) {
+					nack(p->name);
+					longjmp(errcatch,0);
+					/* NOTREACHED */
+				}
+				state = p->state;
+				yylval.str = p->name;
+				return (p->token);
+			}
+			break;
+
+		case SITECMD:
+			if (cbuf[cpos] == ' ') {
+				cpos++;
+				return (SP);
+			}
+			cp = &cbuf[cpos];
+			if ((cp2 = strpbrk(cp, " \n")))
+				cpos = cp2 - cbuf;
+			c = cbuf[cpos];
+			cbuf[cpos] = '\0';
+			upper(cp);
+			p = lookup(sitetab, cp);
+			cbuf[cpos] = c;
+			if (p != 0) {
+				if (p->implemented == 0) {
+					state = CMD;
+					nack(p->name);
+					longjmp(errcatch,0);
+					/* NOTREACHED */
+				}
+				state = p->state;
+				yylval.str = p->name;
+				return (p->token);
+			}
+			state = CMD;
+			break;
+
+		case OSTR:
+			if (cbuf[cpos] == '\n') {
+				state = CMD;
+				return (CRLF);
+			}
+			/* FALLTHROUGH */
+
+		case STR1:
+		case ZSTR1:
+		dostr1:
+			if (cbuf[cpos] == ' ') {
+				cpos++;
+				state = state == OSTR ? STR2 : state+1;
+				return (SP);
+			}
+			break;
+
+		case ZSTR2:
+			if (cbuf[cpos] == '\n') {
+				state = CMD;
+				return (CRLF);
+			}
+			/* FALLTHROUGH */
+
+		case STR2:
+			cp = &cbuf[cpos];
+			n = strlen(cp);
+			cpos += n - 1;
+			/*
+			 * Make sure the string is nonempty and \n terminated.
+			 */
+			if (n > 1 && cbuf[cpos] == '\n') {
+				cbuf[cpos] = '\0';
+				yylval.str = copy(cp);
+				cbuf[cpos] = '\n';
+				state = ARGS;
+				return (STRING);
+			}
+			break;
+
+		case NSTR:
+			if (cbuf[cpos] == ' ') {
+				cpos++;
+				return (SP);
+			}
+			if (isdigit((int) cbuf[cpos])) {
+				cp = &cbuf[cpos];
+				while (isdigit((int) cbuf[++cpos]))
+					;
+				c = cbuf[cpos];
+				cbuf[cpos] = '\0';
+				yylval.num = atoi(cp);
+				cbuf[cpos] = c;
+				state = STR1;
+				return (NUMBER);
+			}
+			state = STR1;
+			goto dostr1;
+
+		case ARGS:
+			if (isdigit((int) cbuf[cpos])) {
+				cp = &cbuf[cpos];
+				while (isdigit((int) cbuf[++cpos]))
+					;
+				c = cbuf[cpos];
+				cbuf[cpos] = '\0';
+				yylval.num = atoi(cp);
+				cbuf[cpos] = c;
+				return (NUMBER);
+			}
+			switch (cbuf[cpos++]) {
+
+			case '\n':
+				state = CMD;
+				return (CRLF);
+
+			case ' ':
+				return (SP);
+
+			case ',':
+				return (COMMA);
+
+			case 'A':
+			case 'a':
+				return ('A');
+
+			case 'B':
+			case 'b':
+				return ('B');
+
+			case 'C':
+			case 'c':
+				return ('C');
+
+			case 'E':
+			case 'e':
+				return ('E');
+
+			case 'F':
+			case 'f':
+				return ('F');
+
+			case 'I':
+			case 'i':
+				return ('I');
+
+			case 'L':
+			case 'l':
+				return ('L');
+
+			case 'N':
+			case 'n':
+				return ('N');
+
+			case 'P':
+			case 'p':
+				return ('P');
+
+			case 'R':
+			case 'r':
+				return ('R');
+
+			case 'S':
+			case 's':
+				return ('S');
+
+			case 'T':
+			case 't':
+				return ('T');
+
+			}
+			break;
+
+		default:
+			fatal("Unknown state in scanner.");
+		}
+		yyerror((char *) 0);
+		state = CMD;
+		longjmp(errcatch,0);
+	}
+}
+
+void
+upper(s)
+	register char *s;
+{
+	while (*s != '\0') {
+		if (islower((int) (*s)))
+			*s = toupper((int) (*s));
+		s++;
+	}
+}
+
+static char *
+copy(s)
+	char *s;
+{
+	char *p;
+
+	p = malloc((unsigned) strlen(s) + 1);
+	if (p == NULL)
+		fatal("Ran out of memory.");
+	(void) strcpy(p, s);
+	return (p);
+}
+
+void
+help(ctab, s)
+	struct tab *ctab;
+	char *s;
+{
+	register struct tab *c;
+	register int width, NCMDS;
+	char str[80];
+	char *ftype;
+
+	if (ctab == sitetab)
+		ftype = "SITE ";
+	else
+		ftype = "";
+	width = 0, NCMDS = 0;
+	for (c = ctab; c->name != NULL; c++) {
+		int len = strlen(c->name);
+
+		if (len > width)
+			width = len;
+		NCMDS++;
+	}
+	width = (width + 8) &~ 7;
+	if (s == 0) {
+		register int i, j, w;
+		int columns, lines;
+
+		lreply(214, "The following %scommands are recognized %s.",
+		    ftype, "(* =>'s unimplemented)");
+		columns = 76 / width;
+		if (columns == 0)
+			columns = 1;
+		lines = (NCMDS + columns - 1) / columns;
+		for (i = 0; i < lines; i++) {
+			strcpy(str, "   ");
+			for (j = 0; j < columns; j++) {
+				c = ctab + j * lines + i;
+				sprintf(&str[strlen(str)], "%s%c", c->name,
+					c->implemented ? ' ' : '*');
+				if (c + lines >= &ctab[NCMDS])
+					break;
+				w = strlen(c->name) + 1;
+				while (w < width) {
+					strcat(str, " ");
+					w++;
+				}
+			}
+			reply(0, "%s", str);
+		}
+		reply(214, "Direct comments to ftp-bugs@%s.", hostname);
+		return;
+	}
+	upper(s);
+	c = lookup(ctab, s);
+	if (c == (struct tab *)0) {
+		reply(502, "Unknown command %s.", s);
+		return;
+	}
+	if (c->implemented)
+		reply(214, "Syntax: %s%s %s", ftype, c->name, c->help);
+	else
+		reply(214, "%s%-*s\t%s; unimplemented.", ftype, width,
+		    c->name, c->help);
+}
+
+void
+sizecmd(filename)
+char *filename;
+{
+	switch (type) {
+	case TYPE_L:
+	case TYPE_I: {
+		struct stat stbuf;
+		if (stat(filename, &stbuf) < 0 ||
+		    (stbuf.st_mode&S_IFMT) != S_IFREG)
+			reply(550, "%s: not a plain file.", filename);
+		else
+			reply(213, "%lu", (long) stbuf.st_size);
+		break;}
+	case TYPE_A: {
+		FILE *fin;
+		register int c;
+		register long count;
+		struct stat stbuf;
+		fin = fopen(filename, "r");
+		if (fin == NULL) {
+			perror_reply(550, filename);
+			return;
+		}
+		if (fstat(fileno(fin), &stbuf) < 0 ||
+		    (stbuf.st_mode&S_IFMT) != S_IFREG) {
+			reply(550, "%s: not a plain file.", filename);
+			(void) fclose(fin);
+			return;
+		}
+
+		count = 0;
+		while((c=getc(fin)) != EOF) {
+			if (c == '\n')	/* will get expanded to \r\n */
+				count++;
+			count++;
+		}
+		(void) fclose(fin);
+
+		reply(213, "%ld", count);
+		break;}
+	default:
+		reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
+	}
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/ftpd.M b/krb5-1-6/src/appl/gssftp/ftpd/ftpd.M
new file mode 100644
index 000000000..b26a4bd94
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/ftpd.M
@@ -0,0 +1,513 @@
+.\" Copyright (c) 1985, 1988, 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)ftpd.8	6.9 (Berkeley) 3/16/91
+.\" "
+.TH FTPD 8
+.SH NAME
+ftpd \- DARPA Internet File Transfer Protocol server
+.SH SYNOPSIS
+.B ftpd
+[\fB\-A \fP|\fB -a\fP] [\fB\-C\fP] [\fB\-c\fP] [\fB\-d\fP] [\fB-E\fP]
+[\fB\-l\fP] [\fB\-v\fP] [\fB\-T\fP \fImaxtimeout\fP] [\fB\-t\fP \fItimeout\fP]
+[\fB\-p\fP \fIport\fP] [\fB\-U\fP \fIftpusers-file\fP] [\fB\-u\fP \fIumask\fP]
+[\fB\-r\fP \fIrealm-file\fP] [\fB\-s\fP \fIsrvtab\fP]
+[\fB\-w\fP{\fBip\fP|\fImaxhostlen\fP[\fB,\fP{\fBstriplocal\fP|\fBnostriplocal\fP}]}]
+.SH DESCRIPTION
+.B Ftpd
+is the
+.SM DARPA
+Internet File Transfer Protocol server process.  The server uses the
+.SM TCP
+protocol and listens at the port specified in the ``ftp'' service
+specification; see
+.IR services (5).
+.PP
+Available options:
+.TP
+.B \-A
+Connections are only allowed for users who can authenticate via the
+ftp AUTH mechanism. (Anonymous ftp may also be allowed if it is 
+configured.) Ftpd will ask the user for a password if one is
+required.
+.TP
+.B \-a
+Connections are only allowed for users who can authenticate (via the
+ftp AUTH mechanism) and who are authorized to connect to the named 
+account without a password. (Anonymous ftp may also be allowed if it is 
+configured.)
+.TP
+.B \-C
+Non-anonymous users need local credentials (for example, to authenticate
+to remote fileservers), and so they should be prompted for a password
+unless they forwarded credentials as part of authentication.
+.TP
+.B \-c
+Allow the CCC (Clear Command Channel) command to be used. This allows
+less secure connections, and should probably only be used when debugging.
+.TP
+.B \-d
+Debugging information is written to the syslog.  (Identical to -v)
+.TP
+.B \-E
+Don't allow passwords to be typed across unencrypted connections.
+.TP
+.B \-l
+Each
+.IR ftp (1)
+session is logged in the syslog.  If this flag appears twice, additional
+information about operations performed (such as files retrieved, directories
+created, etc.) will be logged via syslog.  If it appears three times, some
+other statistics such as the number of bytes transferred will be logged via
+syslog as well.
+.TP
+.B \-v
+Debugging information is written to the syslog.  (Identical to -d)
+.TP
+\fB\-T\fP \fImaxtimeout\fP
+A client may request a maximum timeout period allowed set to
+.I timeout
+seconds with the
+.B \-T
+option.  The default limit is 2 hours.  This is different from the normal
+inactivity timeout specified by the
+.B \-t
+option (see below).
+.TP
+\fB\-t\fP \fItimeout\fP
+The inactivity timeout period is set to
+.I timeout
+seconds (the default is 15 minutes).
+.TP
+\fB\-p\fP \fIport\fP
+Run as a server and accept a connection on
+.IR port .
+Normally the ftp server is invoked by
+.IR inetd (8).
+.TP
+\fB\-U\fP \fIftpusers-file\fP
+Sets the full path and name of the
+.I ftpusers
+file to use.  The default value is normally
+.IR /etc/ftpusers .
+.TP
+\fB\-u\fP \fIumask\fP
+Sets the umask for the ftpd process.  The default value is normally 027.
+.TP
+\fB\-r\fP \fIrealm-file\fP
+Sets the name of the
+.I krb.conf
+file to use.  The default value is normally set by
+.IR /etc/krb5.conf .
+.TP
+\fB\-s\fP \fIsrvtab\fP
+Sets the name of the
+.I srvtab
+file to use for Kerberos V4 authentication.  The default value is normally
+.IR /etc/srvtab .
+.TP
+\fB\-w \fP{\fBip\fP|\fImaxhostlen\fP[\fB,\fP{\fBstriplocal\fP|\fBnostriplocal\fP}]}
+Controls the form of the remote hostname passed to login(1).
+Specifying \fBip\fP results in the numeric IP address always being
+passed to login(1).  Specifying a number, \fImaxhostlen\fP, sets the
+maximum length of the hostname passed to login(1) before it will be
+passed as a numeric IP address.  If \fImaxhostlen\fP is 0, then the
+system default, as determined by the utmp or utmpx structures, is
+used.  The \fBnostriplocal\fP and \fBstriplocal\fP options, which must
+be preceded by a comma, control whether or not the local host domain
+is stripped from the remote hostname.  By default, the equivalent of
+\fBstriplocal\fP is in effect.
+.PP
+The ftp server currently supports the following ftp requests; case is
+not distinguished.
+.TP "\w'Request\ \ 'u"
+.B Request
+.B Description
+.sp -1
+.TP
+ABOR
+abort previous command
+.sp -1
+.TP
+ACCT
+specify account (ignored)
+.sp -1
+.TP
+ADAT
+send an authentication protocol message
+.sp -1
+.TP
+ALLO
+allocate storage (vacuously)
+.sp -1
+.TP
+APPE
+append to a file
+.sp -1
+.TP
+AUTH
+specify an authentication protocol to be performed
+.sp -1
+.TP
+CCC
+set the command channel protection mode to "Clear" (no protection).
+Only available if the \fB-c\fP command-line option was given.
+.sp -1
+.TP
+CDUP
+change to parent of current working directory
+.sp -1
+.TP
+CWD
+change working directory
+.sp -1
+.TP
+DELE
+delete a file
+.sp -1
+.TP
+ENC
+send a privacy and integrity protected command (given in argument)
+.sp -1
+.TP
+HELP
+give help information
+.sp -1
+.TP
+LIST
+give list files in a directory (``ls -lgA'')
+.sp -1
+.TP
+MIC
+send an integrity protected command (given in argument)
+.sp -1
+.TP
+MKD
+make a directory
+.sp -1
+.TP
+MDTM
+show last modification time of file
+.sp -1
+.TP
+MODE
+specify data transfer
+.I mode
+.sp -1
+.TP
+NLST
+give name list of files in directory
+.sp -1
+.TP
+NOOP
+do nothing
+.sp -1
+.TP
+PASS
+specify password
+.sp -1
+.TP
+PASV
+prepare for server-to-server transfer
+.sp -1
+.TP
+PBSZ
+specify a protection buffer size
+.sp -1
+.TP
+PORT
+specify data connection port
+.sp -1
+.TP
+PROT
+specify a protection level under which to protect data transfers
+.sp -1
+.TP
+PWD
+print the current working directory
+.sp -1
+.TP
+QUIT
+terminate session
+.sp -1
+.TP
+REST
+restart incomplete transfer
+.sp -1
+.TP
+RETR
+retrieve a file
+.sp -1
+.TP
+RMD
+remove a directory
+.sp -1
+.TP
+RNFR
+specify rename-from file name
+.sp -1
+.TP
+RNTO
+specify rename-to file name
+.sp -1
+.TP
+SITE
+non-standard commands (see next section)
+.sp -1
+.TP
+SIZE
+return size of file
+.sp -1
+.TP
+STAT
+return status of server
+.sp -1
+.TP
+STOR
+store a file
+.sp -1
+.TP
+STOU
+store a file with a unique name
+.sp -1
+.TP
+STRU
+specify data transfer
+.I structure
+.sp -1
+.TP
+SYST
+show operating system type of server system
+.sp -1
+.TP
+TYPE
+specify data transfer
+.I type
+.sp -1
+.TP
+USER
+specify user name
+.sp -1
+.TP
+XCUP
+change to parent of current working directory (deprecated)
+.sp -1
+.TP
+XCWD
+change working directory (deprecated)
+.sp -1
+.TP
+XMKD
+make a directory (deprecated)
+.sp -1
+.TP
+XPWD
+print the current working directory (deprecated)
+.sp -1
+.TP
+XRMD
+remove a directory (deprecated)
+.PP
+The following non-standard or
+.SM UNIX
+specific commands are supported by the SITE request.
+.TP "\w'Request\ \ 'u"
+.B Request
+.B Description
+.sp -1
+.TP
+UMASK
+change umask. 
+.IR E.g. ,
+SITE UMASK 002
+.sp -1
+.TP
+IDLE
+set idle-timer. 
+.IR E.g. ,
+SITE IDLE 60
+.sp -1
+.TP
+CHMOD
+change mode of a file. 
+.IR E.g. ,
+SITE CHMOD 755 filename
+.sp -1
+.TP
+HELP
+give help information.
+.IR E.g. ,
+SITE HELP
+.PP
+The remaining ftp requests specified in Internet
+.I RFC 959
+are recognized, but not implemented.  MDTM and SIZE are not specified in
+.I RFC
+.IR 959 ,
+but will appear in the next updated FTP RFC.
+.PP
+The ftp server will abort an active file transfer only when the ABOR
+command is preceded by a Telnet "Interrupt Process" (IP) signal and a
+Telnet "Synch" signal in the command Telnet stream, as described in
+Internet
+.I RFC
+.IR 959 .
+If a STAT command is received during a data transfer, preceded by a
+Telnet IP and Synch, transfer status will be returned.
+.PP
+.B Ftpd
+interprets file names according to the
+``globbing''
+conventions used by
+.IR csh (1).
+This allows users to utilize the metacharacters ``\&*?[]{}~''.
+.PP
+.B Ftpd
+authenticates users according to the following rules:
+.sp
+.TP
+  1.
+The user name must be in the password data base,
+.IR /etc/passwd .
+.TP
+  2.
+An
+.SM AUTH
+command must be accepted, the ensuing authentication protocol (conducted
+via
+.SM ADAT
+commands and replies) must successfully complete, and the authenticated
+user must permitted access.  Otherwise, a valid password which is not
+null must be provided by the client.
+.TP
+  3.
+The user name must not appear in the file
+.IR /etc/ftpusers .
+.TP
+  4.
+The user must have a standard shell returned by 
+.IR getusershell (3).
+.TP
+  5.
+If the user name is ``anonymous'' or ``ftp'', an anonymous ftp account
+must be present in the password file (user ``ftp'').  In this case the
+user is allowed to log in by specifying any password (by convention this
+is given as the client host's name).
+.PP
+In the last case,
+.B ftpd
+takes special measures to restrict the client's access privileges.  The
+server performs a
+.IR chroot (2)
+command to the home directory of the ``ftp'' user.  In order that system
+security is not breached, it is recommended that the ``ftp'' subtree be
+constructed with care; the following rules are recommended.
+.TP
+.I ~ftp
+Make the home directory owned by ``ftp'' and unwritable by anyone.
+.TP
+.I ~ftp/bin
+Make this directory owned by the super-user and unwritable by anyone.
+The program
+.IR ls (1)
+must be present to support the list command.  This program should have
+mode 111.
+.TP
+.I ~ftp/etc
+Make this directory owned by the super-user and unwritable by anyone.
+The files
+.IR passwd (5)
+and
+.IR group (5)
+must be present for the
+.I ls
+command to be able to produce owner names rather than numbers.  The
+password field in
+.I passwd
+is not used, and should not contain real encrypted passwords.  These
+files should be mode 444.
+.TP
+.I ~ftp/pub
+Make this directory mode 777 and owned by ``ftp''.  Users should then
+place files which are to be accessible via the anonymous account in this
+directory.
+.PP
+If an
+.SM ADAT
+command succeeds, the control channel must be either integrity or
+privacy protected.  In this case, the
+.SM MIC
+and
+.SM ENC
+commands are the only commands allowed over the control channel.  The
+argument to the
+.SM MIC
+command is a base 64 encoded string which, when decoded, is an ftp
+command integrity protected with a cryptographic checksum.  The argument
+to the
+.SM ENC
+command is a base 64 encoded string which, when decoded, is an ftp
+command privacy and integrity protected with encryption.
+.PP
+If an
+.SM ADAT
+command succeeds, ftp replies will also be either integrity or privacy
+protected.
+.PP
+If an
+.SM ADAT
+command succeeds, the data channel can also be integrity or privacy
+protected.  The
+.SM PROT
+command accepts S for integrity and P for privacy protection.  Unless an
+.SM ADAT
+command succeeds, the only protection level accepted by the
+.SM PROT
+command is C (clear).
+.SH SEE ALSO
+.IR ftp (1),
+.IR getusershell (3),
+.IR syslogd (8)
+.PP
+Lunt, S. J., FTP Security Extensions, Internet Draft, November 1993.
+.SH BUGS
+The anonymous account is inherently dangerous and should avoided when
+possible.
+.PP
+The server must run as the super-user to create sockets with privileged
+port numbers.  It maintains an effective user id of the logged in user,
+reverting to the super-user only when binding addresses to sockets.  The
+possible security holes have been extensively scrutinized, but are
+possibly incomplete.
+.SH HISTORY
+The
+.B ftpd
+command appeared in 4.2BSD.
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/ftpd.c b/krb5-1-6/src/appl/gssftp/ftpd/ftpd.c
new file mode 100644
index 000000000..94b40dcc5
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/ftpd.c
@@ -0,0 +1,3007 @@
+/*
+ * Copyright (c) 1985, 1988, 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1985, 1988, 1990 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ftpd.c	5.40 (Berkeley) 7/2/91";
+#endif /* not lint */
+
+/*
+ * FTP server.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#ifndef KRB5_KRB4_COMPAT
+/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
+#include <sys/socket.h>
+#endif
+#include <sys/wait.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#define	FTP_NAMES
+#include <arpa/ftp.h>
+#include <arpa/inet.h>
+#include <arpa/telnet.h>
+
+#include <signal.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <time.h>
+#include <pwd.h>
+#ifdef HAVE_SHADOW
+#include <shadow.h>
+#endif
+#include <grp.h> 
+#include <setjmp.h>
+#ifndef POSIX_SETJMP
+#undef sigjmp_buf
+#undef sigsetjmp
+#undef siglongjmp
+#define sigjmp_buf	jmp_buf
+#define sigsetjmp(j,s)	setjmp(j)
+#define siglongjmp	longjmp
+#endif
+#ifndef KRB5_KRB4_COMPAT
+/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
+#include <netdb.h>
+#endif
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef STDARG
+#if (defined(__STDC__) && ! defined(VARARGS)) || defined(HAVE_STDARG_H)
+#define STDARG
+#endif
+#endif
+#ifdef STDARG
+#include <stdarg.h>
+#endif
+#include "pathnames.h"
+#include <libpty.h>
+
+#ifdef NEED_SETENV
+extern int setenv(char *, char *, int);
+#endif
+
+#ifndef L_SET
+#define L_SET 0
+#endif
+#ifndef L_INCR
+#define L_INCR 1
+#endif
+
+#ifndef HAVE_STRERROR
+#define strerror(error)	(sys_errlist[error])
+#ifdef NEED_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+#endif
+
+extern char *mktemp ();
+char *ftpusers;
+extern int yyparse(void);
+
+#include <k5-util.h>
+#include "port-sockets.h"
+
+#ifdef KRB5_KRB4_COMPAT
+#include <krb5.h>
+#include <krb.h>
+
+AUTH_DAT kdata;
+KTEXT_ST ticket;
+MSG_DAT msg_data;
+Key_schedule schedule;
+char *keyfile;
+static char *krb4_services[] = { "ftp", "rcmd", NULL };
+#endif /* KRB5_KRB4_COMPAT */
+
+#ifdef GSSAPI
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+gss_ctx_id_t gcontext;
+gss_buffer_desc client_name;
+static char *gss_services[] = { "ftp", "host", NULL };
+
+#include <krb5.h>
+krb5_context kcontext;
+krb5_ccache ccache;
+
+static void ftpd_gss_convert_creds(char *name, gss_cred_id_t);
+static int ftpd_gss_userok(gss_buffer_t, char *name);
+
+static void log_gss_error(int, OM_uint32, OM_uint32, const char *);
+
+#endif /* GSSAPI */
+
+char *auth_type;	/* Authentication succeeded?  If so, what type? */
+static char *temp_auth_type;
+int authorized;		/* Auth succeeded and was accepted by krb4 or gssapi */
+int have_creds;		/* User has credentials on disk */
+
+/*
+ * File containing login names
+ * NOT to be used on this machine.
+ * Commonly used to disallow uucp.
+ */
+#include "ftpd_var.h"
+#include "secure.h"
+
+extern	char *crypt();
+extern	char version[];
+extern	char *home;		/* pointer to home directory for glob */
+extern	FILE *ftpd_popen(), *fopen(), *freopen();
+extern	int  ftpd_pclose(), fclose();
+extern	char cbuf[];
+extern	off_t restart_point;
+
+struct	sockaddr_in ctrl_addr;
+struct	sockaddr_in data_source;
+struct	sockaddr_in data_dest;
+struct	sockaddr_in his_addr;
+struct	sockaddr_in pasv_addr;
+
+int	data;
+jmp_buf	errcatch;
+sigjmp_buf urgcatch;
+int	logged_in;
+struct	passwd *pw;
+int	debug;
+int	allow_ccc = 0;    /* whether or not the CCC command is allowed */
+int	ccc_ok = 0;       /* whether or not to accept cleartext commands */
+int	timeout = 900;    /* timeout after 15 minutes of inactivity */
+int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
+int	logging;
+int	authlevel;
+int	want_creds;
+int	guest;
+int	restricted;
+int	type;
+int	clevel;			/* control protection level */
+int	dlevel;			/* data protection level */
+int	form;
+int	stru;			/* avoid C keyword */
+int	mode;
+int	usedefault = 1;		/* for data transfers */
+int	pdata = -1;		/* for passive mode */
+int	transflag;
+off_t	file_size;
+off_t	byte_count;
+#if !defined(CMASK) || CMASK == 0
+#undef CMASK
+#define CMASK 027
+#endif
+int	defumask = CMASK;		/* default umask value */
+char	tmpline[FTP_BUFSIZ];
+char    pathbuf[MAXPATHLEN + 1];
+char	hostname[MAXHOSTNAMELEN];
+char	remotehost[MAXHOSTNAMELEN];
+char	rhost_addra[16];
+char	*rhost_sane;
+
+/* Defines for authlevel */
+#define AUTHLEVEL_NONE		0
+#define AUTHLEVEL_AUTHENTICATE	1
+#define AUTHLEVEL_AUTHORIZE	2
+
+/*
+ * Timeout intervals for retrying connections
+ * to hosts that don't accept PORT cmds.  This
+ * is a kludge, but given the problems with TCP...
+ */
+#define	SWAITMAX	90	/* wait at most 90 seconds */
+#define	SWAITINT	5	/* interval between retries */
+
+int	swaitmax = SWAITMAX;
+int	swaitint = SWAITINT;
+
+void	lostconn(int), myoob(int);
+FILE	*getdatasock(char *); 
+#if defined(__STDC__)
+/* 
+ * The following prototypes must be ANSI for systems for which
+ * sizeof(off_t) > sizeof(int) to prevent stack overflow problems 
+ */
+FILE	*dataconn(char *name, off_t size, char *mymode);
+void	send_data(FILE *instr, FILE *outstr, off_t blksize);
+#else
+void	send_data();
+FILE	*dataconn();
+#endif
+static void dolog(struct sockaddr_in *);
+static int receive_data(FILE *, FILE *);
+static void login(char *passwd, int logincode);
+static void end_login(void);
+static int disallowed_user(char *);
+static int restricted_user(char *);
+static int checkuser(char *);
+static char *gunique(char *);
+
+#ifdef SETPROCTITLE
+char	**Argv = NULL;		/* pointer to argument vector */
+char	*LastArgv = NULL;	/* end of argv */
+char	proctitle[FTP_BUFSIZ];	/* initial part of title */
+#endif /* SETPROCTITLE */
+
+#ifdef __SCO__
+/* sco has getgroups and setgroups but no initgroups */
+int initgroups(char* name, gid_t basegid) {
+  gid_t others[NGROUPS_MAX+1];
+  int ngrps;
+
+  others[0] = basegid;
+  ngrps = getgroups(NGROUPS_MAX, others+1);
+  return setgroups(ngrps+1, others);
+}
+#endif
+
+int stripdomain = 1;
+int maxhostlen = 0;
+int always_ip = 0;
+
+int
+main(argc, argv, envp)
+	int argc;
+	char *argv[];
+	char **envp;
+{
+	int addrlen, c, on = 1, tos, port = -1;
+	extern char *optarg;
+	extern int optopt;
+#ifdef KRB5_KRB4_COMPAT
+	char *option_string = "AaCcdElp:r:s:T:t:U:u:vw:";
+#else /* !KRB5_KRB4_COMPAT */
+	char *option_string = "AaCcdElp:r:T:t:U:u:vw:";
+#endif /* KRB5_KRB4_COMPAT */
+	ftpusers = _PATH_FTPUSERS_DEFAULT;
+
+#ifdef KRB5_KRB4_COMPAT
+	keyfile = KEYFILE;
+#endif /* KRB5_KRB4_COMPAT */
+	debug = 0;
+#ifdef SETPROCTITLE
+	/*
+	 *  Save start and extent of argv for setproctitle.
+	 */
+	Argv = argv;
+	while (*envp)
+		envp++;
+	LastArgv = envp[-1] + strlen(envp[-1]);
+#endif /* SETPROCTITLE */
+
+#ifdef GSSAPI
+	krb5_init_context(&kcontext);
+#endif
+
+	while ((c = getopt(argc, argv, option_string)) != -1) {
+		switch (c) {
+
+		case 'v':
+			debug = 1;
+			break;
+
+		case 'd':
+			debug = 1;
+			break;
+
+		case 'E':
+			if (!authlevel)
+				authlevel = AUTHLEVEL_AUTHENTICATE;
+			break;
+
+		case 'l':
+			logging ++;
+			break;
+
+		case 'a':
+			authlevel = AUTHLEVEL_AUTHORIZE;
+			break;
+
+		case 'A':
+			authlevel = AUTHLEVEL_AUTHENTICATE;
+			break;
+
+		case 'C':
+			want_creds = 1;
+			break;
+
+		case 'c':
+			allow_ccc = 1;
+			break;
+
+		case 'p':
+			port = atoi(optarg);
+			break;
+
+		case 'r':
+			setenv("KRB_CONF", optarg, 1);
+			break;
+
+#ifdef KRB5_KRB4_COMPAT
+		case 's':
+			keyfile = optarg;
+			break;
+#endif /* KRB5_KRB4_COMPAT */
+
+		case 't':
+			timeout = atoi(optarg);
+			if (maxtimeout < timeout)
+				maxtimeout = timeout;
+			break;
+
+		case 'T':
+			maxtimeout = atoi(optarg);
+			if (timeout > maxtimeout)
+				timeout = maxtimeout;
+			break;
+
+		case 'u':
+			{
+			    int val = 0;
+			    char *umask_val = optarg;
+
+			    while (*umask_val >= '0' && *umask_val <= '9') {
+				    val = val*8 + *umask_val - '0';
+				    umask_val++;
+			    }
+			    if (*umask_val != ' ' && *umask_val != '\0')
+				    fprintf(stderr, "ftpd: Bad value for -u\n");
+			    else
+				    defumask = val;
+			    break;
+			}
+
+		case 'U':
+			ftpusers = optarg;
+			break;
+
+		case 'w':
+		{
+			char *foptarg;
+			foptarg = optarg;
+
+			if (!strcmp(foptarg, "ip"))
+				always_ip = 1;
+			else {
+				char *cp2;
+				cp2 = strchr(foptarg, ',');
+				if (cp2 == NULL)
+					maxhostlen = atoi(foptarg);
+				else if (*(++cp2)) {
+					if (!strcmp(cp2, "striplocal"))
+						stripdomain = 1;
+					else if (!strcmp(cp2, "nostriplocal"))
+						stripdomain = 0;
+					else {
+						fprintf(stderr,
+							"ftpd: bad arg to -w\n");
+						exit(1);
+					}
+					*(--cp2) = '\0';
+					maxhostlen = atoi(foptarg);
+				}
+			}
+			break;
+		}
+		default:
+			fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n",
+			     (char)optopt);
+			break;
+		}
+	}
+
+	if (port != -1) {
+		struct sockaddr_in sin4;
+		int s, ns;
+		socklen_t sz;
+
+		/* Accept an incoming connection on port.  */
+		sin4.sin_family = AF_INET;
+		sin4.sin_addr.s_addr = INADDR_ANY;
+		sin4.sin_port = htons(port);
+		s = socket(AF_INET, SOCK_STREAM, 0);
+		if (s < 0) {
+			perror("socket");
+			exit(1);
+		}
+		(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+				  (char *)&on, sizeof(on));
+		if (bind(s, (struct sockaddr *)&sin4, sizeof sin4) < 0) {
+			perror("bind");
+			exit(1);
+		}
+		if (listen(s, 1) < 0) {
+			perror("listen");
+			exit(1);
+		}
+		sz = sizeof sin4;
+		ns = accept(s, (struct sockaddr *)&sin4, &sz);
+		if (ns < 0) {
+			perror("accept");
+			exit(1);
+		}
+		(void) close(s);
+		(void) dup2(ns, 0);
+		(void) dup2(ns, 1);
+		(void) dup2(ns, 2);
+		if (ns > 2)
+		  (void) close(ns);
+	}
+
+	/*
+	 * LOG_NDELAY sets up the logging connection immediately,
+	 * necessary for anonymous ftp's that chroot and can't do it later.
+	 */
+#ifndef LOG_NDELAY
+/* Ultrix syslog does not support NDELAY.  */
+#define LOG_NDELAY 0
+#endif
+#ifndef LOG_DAEMON
+#define LOG_DAEMON 0
+#endif
+	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
+
+	addrlen = sizeof (his_addr);
+	if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
+		syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
+		exit(1);
+	}
+	addrlen = sizeof (ctrl_addr);
+	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
+		syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
+		exit(1);
+	}
+#ifdef IP_TOS
+#ifdef IPTOS_LOWDELAY
+	tos = IPTOS_LOWDELAY;
+	if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+#endif
+	port = ntohs(ctrl_addr.sin_port);
+	data_source.sin_port = htons(port - 1);
+
+	(void) freopen("/dev/null", "w", stderr);
+	(void) signal(SIGPIPE, lostconn);
+	(void) signal(SIGCHLD, SIG_IGN);
+#ifdef SIGURG
+#ifdef POSIX_SIGNALS
+	{
+		struct sigaction sa;
+
+		sigemptyset(&sa.sa_mask);
+		sa.sa_flags = 0;
+		sa.sa_handler = myoob;
+		if (sigaction(SIGURG, &sa, NULL) < 0)
+			syslog(LOG_ERR, "signal: %m");
+	}
+#else
+	if ((long)signal(SIGURG, myoob) < 0)
+		syslog(LOG_ERR, "signal: %m");
+#endif /* POSIX_SIGNALS */
+#endif /* SIGURG */
+
+	/* Try to handle urgent data inline */
+#ifdef SO_OOBINLINE
+	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)
+		syslog(LOG_ERR, "setsockopt: %m");
+#endif
+
+#ifdef	F_SETOWN
+	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
+		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
+#endif
+	dolog(&his_addr);
+	/*
+	 * Set up default state
+	 */
+	data = -1;
+	clevel = dlevel = PROT_C;
+	type = TYPE_A;
+	form = FORM_N;
+	stru = STRU_F;
+	mode = MODE_S;
+	tmpline[0] = '\0';
+	(void) gethostname(hostname, sizeof (hostname));
+	reply(220, "%s FTP server (%s) ready.", hostname, version);
+	(void) setjmp(errcatch);
+	for (;;)
+		(void) yyparse();
+	/* NOTREACHED */
+}
+
+void
+lostconn(sig)
+int sig;
+{
+	if (debug)
+		syslog(LOG_DEBUG, "lost connection");
+	dologout(-1);
+}
+
+static char ttyline[20];
+
+/*
+ * Helper function for sgetpwnam().
+ */
+static char *
+sgetsave(s)
+	char *s;
+{
+	char *new = malloc((unsigned) strlen(s) + 1);
+
+	if (new == NULL) {
+		perror_reply(421, "Local resource failure: malloc");
+		dologout(1);
+		/* NOTREACHED */
+	}
+	(void) strcpy(new, s);
+	return (new);
+}
+
+/*
+ * Save the result of a getpwnam.  Used for USER command, since
+ * the data returned must not be clobbered by any other command
+ * (e.g., globbing).
+ */
+static struct passwd *
+sgetpwnam(name)
+	char *name;
+{
+	static struct passwd save;
+	register struct passwd *p;
+#ifdef HAVE_SHADOW
+	register struct spwd *sp;
+#endif
+	if ((p = getpwnam(name)) == NULL)
+		return (p);
+	if (save.pw_name) {
+		free(save.pw_name);
+		free(save.pw_passwd);
+		free(save.pw_gecos);
+		free(save.pw_dir);
+		free(save.pw_shell);
+	}
+	save = *p;
+	save.pw_name = sgetsave(p->pw_name);
+#ifdef HAVE_SHADOW
+	if ((sp = getspnam(name)) == NULL)
+	    save.pw_passwd = sgetsave(p->pw_passwd);
+	else
+	    save.pw_passwd = sgetsave(sp->sp_pwdp);
+#else
+	save.pw_passwd = sgetsave(p->pw_passwd);
+#endif
+	save.pw_gecos = sgetsave(p->pw_gecos);
+	save.pw_dir = sgetsave(p->pw_dir);
+	save.pw_shell = sgetsave(p->pw_shell);
+	return (&save);
+}
+
+/*
+ * Expand the given pathname relative to the current working directory.
+ */
+static char *
+path_expand(path)
+       char *path;
+{
+	pathbuf[0] = '\x0';
+	if (!path) return pathbuf;
+	/* Don't bother with getcwd() if the path is absolute */
+	if (path[0] != '/') {
+	        if (!getcwd(pathbuf, sizeof pathbuf)) {
+		        pathbuf[0] = '\x0';
+			syslog(LOG_ERR, "getcwd() failed");
+		}
+		else {
+		        int len = strlen(pathbuf);
+			if (pathbuf[len-1] != '/') {
+			        pathbuf[len++] = '/';
+				pathbuf[len] = '\x0';
+			}
+		}
+	}
+	return strncat(pathbuf, path,
+		       sizeof (pathbuf) - strlen(pathbuf) - 1);
+}
+
+/*
+ * Set data channel protection level
+ */
+void
+setdlevel(prot_level)
+int prot_level;
+{
+	switch (prot_level) {
+		case PROT_S:
+#ifndef NOENCRYPTION
+		case PROT_P:
+#endif
+			if (auth_type)
+		case PROT_C:
+				reply(200, "Data channel protection level set to %s.",
+					(dlevel = prot_level) == PROT_S ?
+						"safe" : dlevel == PROT_P ?
+						"private" : "clear");
+			else
+		default:	reply(536, "%s protection level not supported.",
+					levelnames[prot_level]);
+	}
+}
+
+int login_attempts;		/* number of failed login attempts */
+int askpasswd;			/* had user command, ask for passwd */
+
+/*
+ * USER command.
+ * Sets global passwd pointer pw if named account exists and is acceptable;
+ * sets askpasswd if a PASS command is expected.  If logged in previously,
+ * need to reset state.  If name is "ftp" or "anonymous", the name is not in
+ * ftpusers, and ftp account exists, set guest and pw, then just return.
+ * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
+ * requesting login privileges.  Disallow anyone who does not have a standard
+ * shell as returned by getusershell().  Disallow anyone mentioned in the file
+ * ftpusers to allow people such as root and uucp to be avoided, except
+ * for users whose names are followed by whitespace and then the keyword
+ * "restrict."  Restricted users are allowed to login, but a chroot() is
+ * done to their home directory.
+ */
+void
+user(name)
+	char *name;
+{
+	register char *cp;
+	char *shell;
+	char buf[FTP_BUFSIZ];
+#ifdef HAVE_GETUSERSHELL
+	char *getusershell();
+#endif
+
+	if (logged_in) {
+		if (guest) {
+			reply(530, "Can't change user from guest login.");
+			return;
+		}
+		end_login();
+	}
+
+	authorized = guest = 0;
+	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
+		if (disallowed_user("ftp") || disallowed_user("anonymous"))
+			reply(530, "User %s access denied.", name);
+		else if ((pw = sgetpwnam("ftp")) != NULL) {
+			guest = 1;
+			askpasswd = 1;
+			reply(331, "Guest login ok, send ident as password.");
+		} else
+			reply(530, "User %s unknown.", name);
+		return;
+	}
+
+	/*
+	 * If authentication is required, check that before anything
+	 * else to avoid leaking information.
+	 */
+	if (authlevel && !auth_type) {
+		reply(530,
+		      "Must perform authentication before identifying USER.");
+		return;
+	}
+
+	pw = sgetpwnam(name);
+	if (pw) {
+		if ((shell = pw->pw_shell) == NULL || *shell == 0)
+			shell = "/bin/sh";
+#ifdef HAVE_GETUSERSHELL
+		setusershell();
+		while ((cp = getusershell()) != NULL)
+			if (strcmp(cp, shell) == 0)
+				break;
+		endusershell();
+#else
+		cp = shell;
+#endif
+		if (cp == NULL || disallowed_user(name)) {
+			reply(530, "User %s access denied.", name);
+			if (logging)
+				syslog(LOG_NOTICE,
+				    "FTP LOGIN REFUSED FROM %s, %s (%s)",
+				    rhost_addra, remotehost, name);
+			pw = (struct passwd *) NULL;
+			return;
+		}
+		restricted = restricted_user(name);
+	}
+
+	if (auth_type) {
+		int result;
+#ifdef GSSAPI
+		if (auth_type && strcmp(auth_type, "GSSAPI") == 0) {
+			int len;
+
+			authorized = ftpd_gss_userok(&client_name, name) == 0;
+			len = sizeof("GSSAPI user  is not authorized as "
+				     "; Password required.")
+				+ strlen(client_name.value)
+				+ strlen(name);
+			if (len >= sizeof(buf)) {
+				syslog(LOG_ERR, "user: username too long");
+				name = "[username too long]";
+			}
+			sprintf(buf, "GSSAPI user %s is%s authorized as %s",
+				(char *) client_name.value, 
+				authorized ? "" : " not",
+				name);
+		}
+#ifdef KRB5_KRB4_COMPAT
+		else
+#endif /* KRB5_KRB4_COMPAT */
+#endif /* GSSAPI */
+#ifdef KRB5_KRB4_COMPAT
+		if (auth_type && strcmp(auth_type, "KERBEROS_V4") == 0) {
+			int len;
+
+			authorized = kuserok(&kdata,name) == 0;
+			len = sizeof("Kerberos user .@ is not authorized as "
+				     "; Password required.")
+				+ strlen(kdata.pname)
+				+ strlen(kdata.pinst)
+				+ strlen(kdata.prealm)
+				+ strlen(name);
+			if (len >= sizeof(buf)) {
+				syslog(LOG_ERR, "user: username too long");
+				name = "[username too long]";
+			}
+			sprintf(buf, "Kerberos user %s%s%s@%s is%s authorized as %s",
+				kdata.pname, *kdata.pinst ? "." : "",
+				kdata.pinst, kdata.prealm,
+				authorized ? "" : " not", name);
+		}
+#endif /* KRB5_KRB4_COMPAT */
+
+		if (!authorized && authlevel == AUTHLEVEL_AUTHORIZE) {
+			strncat(buf, "; Access denied.",
+				sizeof(buf) - strlen(buf) - 1);
+			result = 530;
+			pw = NULL;
+		} else if (!authorized || (want_creds && !have_creds)) {
+			strncat(buf, "; Password required.",
+				sizeof(buf) - strlen(buf) - 1);
+			askpasswd = 1;
+			result = 331;
+		} else
+			result = 232;
+		reply(result, "%s", buf);
+		syslog(authorized ? LOG_INFO : LOG_ERR, "%s", buf);
+
+		if (result == 232)
+			login(NULL, result);
+		return;
+	}
+
+	/* User didn't authenticate and authentication wasn't required. */
+	reply(331, "Password required for %s.", name);
+	askpasswd = 1;
+
+	/*
+	 * Delay before reading passwd after first failed
+	 * attempt to slow down passwd-guessing programs.
+	 */
+	if (login_attempts)
+		sleep((unsigned) login_attempts);
+}
+
+/*
+ * Check if a user is in the file ftpusers.
+ * Return 1 if they are (a disallowed user), -1 if their username
+ * is followed by "restrict." (a restricted user).  Otherwise return 0.
+ */
+static int
+checkuser(name)
+	char *name;
+{
+	register FILE *fd;
+	register char *p;
+	char line[FTP_BUFSIZ];
+
+	if ((fd = fopen(ftpusers, "r")) != NULL) {
+	     while (fgets(line, sizeof(line), fd) != NULL) {
+	          if ((p = strchr(line, '\n')) != NULL) {
+			*p = '\0';
+			if (line[0] == '#')
+			     continue;
+			if (strcmp(line, name) == 0)
+			     return (1);
+			if (strncmp(line, name, strlen(name)) == 0) {
+			     int i = strlen(name) + 1;
+			     
+			     /* Make sure foo doesn't match foobar */
+			     if (line[i] == '\0' || !isspace((int) line[i]))
+			          continue;
+			     /* Ignore whitespace */
+			     while (isspace((int) line[++i]));
+
+			     if (strcmp(&line[i], "restrict") == 0)
+			          return (-1);
+			     else
+			          return (1);
+			}
+		  }
+	     }
+	     (void) fclose(fd);
+	}
+
+	return (0);
+}
+
+static int
+disallowed_user(name)
+        char *name;
+{
+        return(checkuser(name) == 1);
+}
+
+static int
+restricted_user(name)
+        char *name;
+{
+        return(checkuser(name) == -1);
+}
+
+/*
+ * Terminate login as previous user, if any, resetting state;
+ * used when USER command is given or login fails.
+ */
+static void 
+end_login()
+{
+
+	(void) krb5_seteuid((uid_t)0);
+	if (logged_in)
+		pty_logwtmp(ttyline, "", "");
+	if (have_creds) {
+#ifdef GSSAPI
+		krb5_cc_destroy(kcontext, ccache);
+#endif
+#ifdef KRB5_KRB4_COMPAT
+		dest_tkt();
+#endif
+		have_creds = 0;
+	}
+	pw = NULL;
+	logged_in = 0;
+	guest = 0;
+}
+
+static int
+kpass(name, passwd)
+char *name, *passwd;
+{
+#ifdef GSSAPI
+	krb5_principal server, me;
+	krb5_creds my_creds;
+	krb5_timestamp now;
+#endif /* GSSAPI */
+#ifdef KRB5_KRB4_COMPAT
+	char realm[REALM_SZ];
+#ifndef GSSAPI
+	char **service;
+	KTEXT_ST ticket;
+	AUTH_DAT authdata;
+	des_cblock key;
+	char instance[INST_SZ];
+	unsigned long faddr;
+	struct hostent *hp;
+#endif /* GSSAPI */
+#endif /* KRB5_KRB4_COMPAT */
+	char ccname[MAXPATHLEN];
+
+#ifdef GSSAPI
+	memset((char *)&my_creds, 0, sizeof(my_creds));
+	if (krb5_parse_name(kcontext, name, &me))
+		return 0;
+	my_creds.client = me;
+
+	sprintf(ccname, "FILE:/tmp/krb5cc_ftpd%ld", (long) getpid());
+	if (krb5_cc_resolve(kcontext, ccname, &ccache))
+		return(0);
+	if (krb5_cc_initialize(kcontext, ccache, me))
+		return(0);
+	if (krb5_build_principal_ext(kcontext, &server,
+				     krb5_princ_realm(kcontext, me)->length,
+				     krb5_princ_realm(kcontext, me)->data,
+				     KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
+				     krb5_princ_realm(kcontext, me)->length,
+				     krb5_princ_realm(kcontext, me)->data,
+				     0))
+		goto nuke_ccache;
+
+	my_creds.server = server;
+	if (krb5_timeofday(kcontext, &now))
+		goto nuke_ccache;
+	my_creds.times.starttime = 0; /* start timer when 
+					 request gets to KDC */
+	my_creds.times.endtime = now + 60 * 60 * 10;
+	my_creds.times.renew_till = 0;
+
+	if (krb5_get_init_creds_password(kcontext, &my_creds, me,
+					 passwd, NULL, NULL, 0, NULL, NULL))
+	  goto nuke_ccache;
+
+	if (krb5_cc_store_cred(kcontext, ccache, &my_creds))
+	  goto nuke_ccache;
+
+	if (!want_creds) {
+		krb5_cc_destroy(kcontext, ccache);
+		return(1);
+	}
+#endif /* GSSAPI */
+
+#ifdef KRB5_KRB4_COMPAT
+	if (krb_get_lrealm(realm, 1) != KSUCCESS)
+		goto nuke_ccache;
+
+	sprintf(ccname, "%s_ftpd%ld", TKT_ROOT, (long) getpid());
+	krb_set_tkt_string(ccname);
+
+	if (krb_get_pw_in_tkt(name, "", realm, "krbtgt", realm, 1, passwd))
+		goto nuke_ccache;
+
+#ifndef GSSAPI
+	/* Verify the ticket since we didn't verify the krb5 one. */
+	strncpy(instance, krb_get_phost(hostname), sizeof(instance));
+
+	if ((hp = gethostbyname(instance)) == NULL)
+		goto nuke_ccache;
+	memcpy((char *) &faddr, (char *)hp->h_addr, sizeof(faddr));
+
+	for (service = krb4_services; *service; service++) {
+		if (!read_service_key(*service, instance,
+				      realm, 0, keyfile, key)) {
+			(void) memset(key, 0, sizeof(key));
+			if (krb_mk_req(&ticket, *service,
+				       instance, realm, 33) ||
+			    krb_rd_req(&ticket, *service, instance,
+				       faddr, &authdata,keyfile) ||
+			    kuserok(&authdata, name)) {
+				dest_tkt();
+				goto nuke_ccache;
+			} else
+				break;
+		}
+	}
+
+	if (!*service) {
+		dest_tkt();
+		goto nuke_ccache;
+	}
+
+	if (!want_creds) {
+		dest_tkt();
+		return(1);
+	}
+#endif /* GSSAPI */
+#endif /* KRB5_KRB4_COMPAT */
+
+#if defined(GSSAPI) || defined(KRB5_KRB4_COMPAT)
+	have_creds = 1;
+	return(1);
+#endif /* GSSAPI || KRB5_KRB4_COMPAT */
+
+nuke_ccache:
+#ifdef GSSAPI
+	krb5_cc_destroy(kcontext, ccache);
+#endif /* GSSAPI */
+	return(0);
+}
+
+void
+pass(passwd)
+	char *passwd;
+{
+	char *xpasswd, *salt;
+
+	if (authorized && !want_creds) {
+		reply(202, "PASS command superfluous.");
+		return;
+	}
+
+	if (logged_in || askpasswd == 0) {
+	  	reply(503, "Login with USER first.");
+		return;
+	} 
+
+	if (!guest) {
+	    	/* "ftp" is only account allowed no password */
+		if (pw == NULL)
+			salt = "xx";
+		else
+			salt = pw->pw_passwd;
+#ifdef __SCO__
+		/* SCO does not provide crypt.  */
+		xpasswd = "";
+#else
+		xpasswd = crypt(passwd, salt);
+#endif
+		/* Fail if:
+		 *   pw is NULL
+		 *   kpass fails and we want_creds
+		 *   kpass fails and the user has no local password
+		 *   kpass fails and the provided password doesn't match pw
+		 */
+		if (pw == NULL || (!kpass(pw->pw_name, passwd) &&
+				   (want_creds || !*pw->pw_passwd ||
+				    strcmp(xpasswd, pw->pw_passwd)))) {
+			pw = NULL;
+			sleep(5);
+			if (++login_attempts >= 3) {
+				reply(421,
+				      "Login incorrect, closing connection.");
+				syslog(LOG_NOTICE,
+				       "repeated login failures from %s (%s)",
+				       rhost_addra, remotehost);
+				dologout(0);
+			}
+			reply(530, "Login incorrect.");
+			return;
+	        }
+	}
+	login_attempts = 0;		/* this time successful */
+
+	login(passwd, 0);
+	return;
+}
+
+static void
+login(passwd, logincode)
+	char *passwd;
+	int logincode;
+{
+	if (have_creds) {
+#ifdef GSSAPI
+		const char *ccname = krb5_cc_get_name(kcontext, ccache);
+		chown(ccname, pw->pw_uid, pw->pw_gid);
+#endif
+#ifdef KRB5_KRB4_COMPAT
+		chown(tkt_string(), pw->pw_uid, pw->pw_gid);
+#endif
+	}
+
+	(void) krb5_setegid((gid_t)pw->pw_gid);
+	(void) initgroups(pw->pw_name, pw->pw_gid);
+
+	/* open wtmp before chroot */
+	(void) sprintf(ttyline, "ftp%ld", (long) getpid());
+	pty_logwtmp(ttyline, pw->pw_name, rhost_sane);
+	logged_in = 1;
+
+	if (guest || restricted) {
+		if (chroot(pw->pw_dir) < 0) {
+			reply(550, "Can't set privileges.");
+			goto bad;
+		}
+	}
+#ifdef HAVE_SETLUID
+  	/*
+  	 * If we're on a system which keeps track of login uids, then
+ 	 * set the login uid. If this fails this opens up a problem on DEC OSF
+ 	 * with C2 enabled.
+	 */
+	if (((uid_t)getluid() != pw->pw_uid)
+	    && setluid((uid_t)pw->pw_uid) < 0) {
+	        reply(550, "Can't set luid.");
+		goto bad;
+	}
+#endif
+	if (krb5_seteuid((uid_t)pw->pw_uid) < 0) {
+	        reply(550, "Can't set uid.");
+		goto bad;
+	}
+	if (guest) {
+		/*
+		 * We MUST do a chdir() after the chroot. Otherwise
+		 * the old current directory will be accessible as "."
+		 * outside the new root!
+		 */
+		if (chdir("/") < 0) {
+			reply(550, "Can't set guest privileges.");
+			goto bad;
+		}
+	} else {
+	        if (chdir(restricted ? "/" : pw->pw_dir) < 0) {
+		        if (chdir("/") < 0) {
+			        reply(530, "User %s: can't change directory to %s.",
+				      pw->pw_name, pw->pw_dir);
+				goto bad;
+			} else {
+				if (!logincode)
+					logincode = 230;
+			        lreply(logincode, "No directory! Logging in with home=/");
+			}
+		}
+	}
+	if (guest) {
+		reply(230, "Guest login ok, access restrictions apply.");
+#ifdef SETPROCTITLE
+		sprintf(proctitle, "%s: anonymous/%.*s", rhost_sane,
+		    sizeof(proctitle) - strlen(rhost_sane) -
+		    sizeof(": anonymous/"), passwd);
+		setproctitle(proctitle);
+#endif /* SETPROCTITLE */
+		if (logging)
+			syslog(LOG_INFO,
+			       "ANONYMOUS FTP LOGIN FROM %s, %s (%s)",
+			       rhost_addra, remotehost, passwd);
+	} else {
+		if (askpasswd) {
+			askpasswd = 0;
+			reply(230, "User %s logged in.", pw->pw_name);
+		}
+#ifdef SETPROCTITLE
+		sprintf(proctitle, "%s: %s", rhost_sane, pw->pw_name);
+		setproctitle(proctitle);
+#endif /* SETPROCTITLE */
+		if (logging)
+			syslog(LOG_INFO, "FTP LOGIN FROM %s, %s (%s)",
+			    rhost_addra, remotehost, pw->pw_name);
+	}
+	home = pw->pw_dir;		/* home dir for globbing */
+	(void) umask(defumask);
+	return;
+bad:
+	/* Forget all about it... */
+	end_login();
+}
+
+void
+retrieve(cmd, name)
+	char *cmd, *name;
+{
+	FILE *fin, *dout;
+	struct stat st;
+	int (*closefunc)();
+
+	if (logging > 1 && !cmd)
+	        syslog(LOG_NOTICE, "get %s", path_expand(name));
+	if (cmd == 0) {
+		fin = fopen(name, "r"), closefunc = fclose;
+		st.st_size = 0;
+	} else {
+		char line[FTP_BUFSIZ];
+
+		if (strlen(cmd) + strlen(name) + 1 >= sizeof(line)) {
+			syslog(LOG_ERR, "retrieve: filename too long");
+			reply(501, "filename too long");
+			return;
+		}
+		(void) sprintf(line, cmd, name), name = line;
+		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
+		st.st_size = -1;
+#ifndef NOSTBLKSIZE
+		st.st_blksize = FTP_BUFSIZ;
+#endif
+	}
+	if (fin == NULL) {
+		if (errno != 0)
+			perror_reply(550, name);
+		return;
+	}
+	if (cmd == 0 &&
+	    (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) {
+		reply(550, "%s: not a plain file.", name);
+		goto done;
+	}
+	if (restart_point) {
+		if (type == TYPE_A) {
+			register int i, n, c;
+
+			n = restart_point;
+			i = 0;
+			while (i++ < n) {
+				if ((c=getc(fin)) == EOF) {
+					perror_reply(550, name);
+					goto done;
+				}
+				if (c == '\n')
+					i++;
+			}	
+		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
+			perror_reply(550, name);
+			goto done;
+		}
+	}
+	dout = dataconn(name, st.st_size, "w");
+	if (dout == NULL)
+		goto done;
+#ifndef NOSTBLKSIZE
+	send_data(fin, dout, st.st_blksize);
+#else
+	send_data(fin, dout, FTP_BUFSIZ);
+#endif
+	(void) fclose(dout);
+	data = -1;
+	pdata = -1;
+done:
+	(*closefunc)(fin);
+	if (logging > 2 && !cmd)
+	        syslog(LOG_NOTICE, "get: %i bytes transferred", byte_count);
+}
+
+void
+store_file(name, fmode, unique)
+	char *name, *fmode;
+	int unique;
+{
+	FILE *fout, *din;
+	struct stat st;
+	int (*closefunc)();
+
+	if (logging > 1) syslog(LOG_NOTICE, "put %s", path_expand(name));
+
+	if (unique && stat(name, &st) == 0 &&
+	    (name = gunique(name)) == NULL)
+		return;
+
+	if (restart_point)
+		fmode = "r+w";
+	fout = fopen(name, fmode);
+	closefunc = fclose;
+	if (fout == NULL) {
+		perror_reply(553, name);
+		return;
+	}
+	if (restart_point) {
+		if (type == TYPE_A) {
+			register int i, n, c;
+
+			n = restart_point;
+			i = 0;
+			while (i++ < n) {
+				if ((c=getc(fout)) == EOF) {
+					perror_reply(550, name);
+					goto done;
+				}
+				if (c == '\n')
+					i++;
+			}	
+			/*
+			 * We must do this seek to "current" position
+			 * because we are changing from reading to
+			 * writing.
+			 */
+			if (fseek(fout, 0L, L_INCR) < 0) {
+				perror_reply(550, name);
+				goto done;
+			}
+		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
+			perror_reply(550, name);
+			goto done;
+		}
+	}
+	din = dataconn(name, (off_t)-1, "r");
+	if (din == NULL)
+		goto done;
+	if (receive_data(din, fout) == 0) {
+		if (unique)
+			reply(226, "Transfer complete (unique file name:%s).",
+			    name);
+		else
+			reply(226, "Transfer complete.");
+	}
+	(void) fclose(din);
+	data = -1;
+	pdata = -1;
+done:
+	(*closefunc)(fout);
+	if (logging > 2)
+	        syslog(LOG_NOTICE, "put: %i bytes transferred", byte_count);
+}
+
+FILE *
+getdatasock(fmode)
+	char *fmode;
+{
+	int s, on = 1, tries;
+
+	if (data >= 0)
+		return (fdopen(data, fmode));
+	(void) krb5_seteuid((uid_t)0);
+	s = socket(AF_INET, SOCK_STREAM, 0);
+	if (s < 0)
+		goto bad;
+	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+	    (char *) &on, sizeof (on)) < 0)
+		goto bad;
+	/* anchor socket to avoid multi-homing problems */
+	data_source.sin_family = AF_INET;
+	data_source.sin_addr = ctrl_addr.sin_addr;
+	for (tries = 1; ; tries++) {
+		if (bind(s, (struct sockaddr *)&data_source,
+		    sizeof (data_source)) >= 0)
+			break;
+		if (errno != EADDRINUSE || tries > 10)
+			goto bad;
+		sleep(tries);
+	}
+	if (krb5_seteuid((uid_t)pw->pw_uid)) {
+		fatal("seteuid user");
+	}
+#ifdef IP_TOS
+#ifdef IPTOS_THROUGHPUT
+	on = IPTOS_THROUGHPUT;
+	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
+		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+#endif
+	return (fdopen(s, fmode));
+bad:
+	if (krb5_seteuid((uid_t)pw->pw_uid)) {
+		fatal("seteuid user");
+	}
+	(void) close(s);
+	return (NULL);
+}
+
+FILE *
+dataconn(name, size, fmode)
+	char *name;
+	off_t size;
+	char *fmode;
+{
+	char sizebuf[32];
+	FILE *file;
+	int retry = 0, tos;
+
+	file_size = size;
+	byte_count = 0;
+	if (size != (off_t) -1)
+		/* cast size to long in case sizeof(off_t) > sizeof(long) */
+		(void) sprintf (sizebuf, " (%ld bytes)", (long)size);
+	else
+		(void) strcpy(sizebuf, "");
+	if (pdata >= 0) {
+		int s, fromlen = sizeof(data_dest);
+
+		s = accept(pdata, (struct sockaddr *)&data_dest, &fromlen);
+		if (s < 0) {
+			reply(425, "Can't open data connection.");
+			(void) close(pdata);
+			pdata = -1;
+			return(NULL);
+		}
+		(void) close(pdata);
+		pdata = s;
+#ifdef IP_TOS
+#ifdef IPTOS_LOWDELAY
+		tos = IPTOS_LOWDELAY;
+		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
+		    sizeof(int));
+#endif
+#endif
+		reply(150, "Opening %s mode data connection for %s%s.",
+		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+		return(fdopen(pdata, fmode));
+	}
+	if (data >= 0) {
+		reply(125, "Using existing data connection for %s%s.",
+		    name, sizebuf);
+		usedefault = 1;
+		return (fdopen(data, fmode));
+	}
+	if (usedefault)
+		data_dest = his_addr;
+	usedefault = 1;
+	file = getdatasock(fmode);
+	if (file == NULL) {
+		reply(425, "Can't create data socket (%s,%d): %s.",
+		    inet_ntoa(data_source.sin_addr),
+		    ntohs(data_source.sin_port), strerror(errno));
+		return (NULL);
+	}
+	data = fileno(file);
+	while (connect(data, (struct sockaddr *)&data_dest,
+	    sizeof (data_dest)) < 0) {
+		if (errno == EADDRINUSE && retry < swaitmax) {
+			sleep((unsigned) swaitint);
+			retry += swaitint;
+			continue;
+		}
+		perror_reply(425, "Can't build data connection");
+		(void) fclose(file);
+		data = -1;
+		return (NULL);
+	}
+	reply(150, "Opening %s mode data connection for %s%s.",
+	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+	return (file);
+}
+
+/*
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ
+ */
+#ifdef STDARG
+void
+secure_error(char *fmt, ...)
+#else
+/* VARARGS1 */
+void
+secure_error(fmt, p1, p2, p3, p4, p5)
+	char *fmt;
+#endif
+{
+	char buf[FTP_BUFSIZ];
+#ifdef STDARG
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buf, fmt, ap);
+	va_end(ap);
+#else
+	sprintf(buf, fmt, p1, p2, p3, p4, p5);
+#endif
+	reply(535, "%s", buf);
+	syslog(LOG_ERR, "%s", buf);
+}
+
+/*
+ * Tranfer the contents of "instr" to
+ * "outstr" peer using the appropriate
+ * encapsulation of the data subject
+ * to Mode, Structure, and Type.
+ *
+ * NB: Form isn't handled.
+ */
+void send_data(instr, outstr, blksize)
+	FILE *instr, *outstr;
+	off_t blksize;
+{
+	register int c, cnt;
+	register char *buf;
+	int netfd, filefd;
+	volatile int ret = 0;
+
+	transflag++;
+	if (sigsetjmp(urgcatch, 1)) {
+		transflag = 0;
+		(void)secure_flush(fileno(outstr));
+		return;
+	}
+	switch (type) {
+
+	case TYPE_A:
+		while ((c = getc(instr)) != EOF) {
+			byte_count++;
+			if (c == '\n') {
+				if (ferror(outstr) ||
+				    (ret = secure_putc('\r', outstr)) < 0)
+					goto data_err;
+			}
+			if ((ret = secure_putc(c, outstr)) < 0)
+				goto data_err;
+		}
+		transflag = 0;
+		if (ferror(instr))
+			goto file_err;
+		if (ferror(outstr) ||
+		    (ret = secure_flush(fileno(outstr))) < 0)
+			goto data_err;
+		reply(226, "Transfer complete.");
+		return;
+
+	case TYPE_I:
+	case TYPE_L:
+		if ((buf = malloc((u_int)blksize)) == NULL) {
+			transflag = 0;
+			perror_reply(451, "Local resource failure: malloc");
+			return;
+		}
+		netfd = fileno(outstr);
+		filefd = fileno(instr);
+		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
+		    (ret = secure_write(netfd, buf, cnt)) == cnt)
+			byte_count += cnt;
+		transflag = 0;
+		(void)free(buf);
+		if (cnt != 0) {
+			if (cnt < 0)
+				goto file_err;
+			goto data_err;
+		}
+		if ((ret = secure_flush(netfd)) < 0)
+			goto data_err;
+		reply(226, "Transfer complete.");
+		return;
+	default:
+		transflag = 0;
+		reply(550, "Unimplemented TYPE %d in send_data", type);
+		return;
+	}
+
+data_err:
+	transflag = 0;
+	if (ret != -2) perror_reply(426, "Data connection");
+	return;
+
+file_err:
+	transflag = 0;
+	perror_reply(551, "Error on input file");
+}
+
+/*
+ * Transfer data from peer to
+ * "outstr" using the appropriate
+ * encapulation of the data subject
+ * to Mode, Structure, and Type.
+ *
+ * N.B.: Form isn't handled.
+ */
+static int
+receive_data(instr, outstr)
+	FILE *instr, *outstr;
+{
+	register int c;
+	volatile int cnt, bare_lfs = 0;
+	char buf[FTP_BUFSIZ];
+	int ret = 0;
+
+	transflag++;
+	if (sigsetjmp(urgcatch, 1)) {
+		transflag = 0;
+		return (-1);
+	}
+	switch (type) {
+
+	case TYPE_I:
+	case TYPE_L:
+		while ((cnt = secure_read(fileno(instr), buf, sizeof buf)) > 0) {
+			if (write(fileno(outstr), buf, cnt) != cnt)
+				goto file_err;
+			byte_count += cnt;
+		}
+		transflag = 0;
+		ret = cnt;
+		if (cnt < 0)
+			goto data_err;
+		return (0);
+
+	case TYPE_E:
+		reply(553, "TYPE E not implemented.");
+		transflag = 0;
+		return (-1);
+
+	case TYPE_A:
+		while ((c = secure_getc(instr)) >= 0) {
+			byte_count++;
+			if (c == '\n')
+				bare_lfs++;
+			while (c == '\r') {
+				if (ferror(outstr))
+					goto data_err;
+				if ((c = secure_getc(instr)) != '\n') {
+					(void) putc ('\r', outstr);
+					if (c == '\0')
+						goto contin2;
+				}
+			}
+			if (c < 0) break;
+			(void) putc(c, outstr);
+	contin2:	;
+		}
+		fflush(outstr);
+		ret = c;
+		if (c == -2 || ferror(instr))
+			goto data_err;
+		if (ferror(outstr))
+			goto file_err;
+		transflag = 0;
+		if (bare_lfs) {
+			lreply(226, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs);
+			reply(0, "   File may not have transferred correctly.");
+		}
+		return (0);
+	default:
+		reply(550, "Unimplemented TYPE %d in receive_data", type);
+		transflag = 0;
+		return (-1);
+	}
+
+data_err:
+	transflag = 0;
+	if (ret != -2) perror_reply(426, "Data Connection");
+	return (-1);
+
+file_err:
+	transflag = 0;
+	perror_reply(452, "Error writing file");
+	return (-1);
+}
+
+void
+statfilecmd(filename)
+	char *filename;
+{
+	char line[FTP_BUFSIZ];
+	FILE *fin;
+	int c, n;
+	char str[FTP_BUFSIZ], *p;
+
+	if (strlen(filename) + sizeof("/bin/ls -lgA ")
+	    >= sizeof(line)) {
+		reply(501, "filename too long");
+		return;
+	}
+	(void) sprintf(line, "/bin/ls -lgA %s", filename);
+	fin = ftpd_popen(line, "r");
+	lreply(211, "status of %s:", filename);
+	p = str;
+	n = 0;
+	while ((c = getc(fin)) != EOF) {
+		if (c == '\n') {
+			if (ferror(stdout)){
+				perror_reply(421, "control connection");
+				(void) ftpd_pclose(fin);
+				dologout(1);
+				/* NOTREACHED */
+			}
+			if (ferror(fin)) {
+				perror_reply(551, filename);
+				(void) ftpd_pclose(fin);
+				return;
+			}
+			*p = '\0';
+			reply(0, "%s", str);
+			p = str;
+			n = 0;
+		} else {
+			*p++ = c;
+			n++;
+			if (n >= sizeof(str)) {
+				reply(551, "output line too long");
+				(void) ftpd_pclose(fin);
+				return;
+			}
+		}
+	}
+	if (p != str) {
+		*p = '\0';
+		reply(0, "%s", str);
+	}
+	(void) ftpd_pclose(fin);
+	reply(211, "End of Status");
+}
+
+void
+statcmd()
+{
+	struct sockaddr_in *sin4;
+	u_char *a, *p;
+	char str[FTP_BUFSIZ];
+
+	lreply(211, "%s FTP server status:", hostname);
+	reply(0, "     %s", version);
+	sprintf(str, "     Connected to %s", remotehost[0] ? remotehost : "");
+	sprintf(&str[strlen(str)], " (%s)", rhost_addra);
+	reply(0, "%s", str);
+	if (auth_type) reply(0, "     Authentication type: %s", auth_type);
+	if (logged_in) {
+		if (guest)
+			reply(0, "     Logged in anonymously");
+		else
+			reply(0, "     Logged in as %s", pw->pw_name);
+	} else if (askpasswd)
+		reply(0, "     Waiting for password");
+	else if (temp_auth_type)
+		reply(0, "     Waiting for authentication data");
+	else
+		reply(0, "     Waiting for user name");
+	reply(0, "     Protection level: %s", levelnames[dlevel]);
+	sprintf(str, "     TYPE: %s", typenames[type]);
+	if (type == TYPE_A || type == TYPE_E)
+		sprintf(&str[strlen(str)], ", FORM: %s", formnames[form]);
+	if (type == TYPE_L)
+#if 1
+		strncat(str, " 8", sizeof (str) - strlen(str) - 1);
+#else
+/* this is silly. -- eichin@cygnus.com */
+#if NBBY == 8
+		sprintf(&str[strlen(str)], " %d", NBBY);
+#else
+		sprintf(&str[strlen(str)], " %d", bytesize);	/* need definition! */
+#endif
+#endif
+	sprintf(&str[strlen(str)], "; STRUcture: %s; transfer MODE: %s",
+	    strunames[stru], modenames[mode]);
+	reply(0, "%s", str);
+	if (data != -1)
+		strcpy(str, "     Data connection open");
+	else if (pdata != -1) {
+		strcpy(str, "     in Passive mode");
+		sin4 = &pasv_addr;
+		goto printaddr;
+	} else if (usedefault == 0) {
+		strcpy(str, "     PORT");
+		sin4 = &data_dest;
+printaddr:
+		a = (u_char *) &sin4->sin_addr;
+		p = (u_char *) &sin4->sin_port;
+#define UC(b) (((int) b) & 0xff)
+		sprintf(&str[strlen(str)], " (%d,%d,%d,%d,%d,%d)", UC(a[0]),
+			UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+#undef UC
+	} else
+		strcpy(str, "     No data connection");
+	reply(0, "%s", str);
+	reply(211, "End of status");
+}
+
+void
+fatal(s)
+	char *s;
+{
+	reply(451, "Error in server: %s", s);
+	reply(221, "Closing connection due to server error.");
+	dologout(0);
+	/* NOTREACHED */
+}
+
+char cont_char = ' ';
+
+/*
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ bytes for now.
+ */
+#ifdef STDARG
+void
+reply(int n, char *fmt, ...)
+#else
+/* VARARGS2 */
+void
+reply(n, fmt, p0, p1, p2, p3, p4, p5)
+	int n;
+	char *fmt;
+#endif
+{
+	char buf[FTP_BUFSIZ];
+#ifdef STDARG
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buf, fmt, ap);
+	va_end(ap);
+#else
+	sprintf(buf, fmt, p0, p1, p2, p3, p4, p5);
+#endif
+
+	if (auth_type) {
+		/*
+		 * Deal with expansion in mk_{safe,priv},
+		 * radix_encode, gss_seal, plus slop.
+		 */
+		char in[FTP_BUFSIZ*3/2], out[FTP_BUFSIZ*3/2];
+		int length, kerror;
+		if (n) sprintf(in, "%d%c", n, cont_char);
+		else in[0] = '\0';
+		strncat(in, buf, sizeof (in) - strlen(in) - 1);
+#ifdef KRB5_KRB4_COMPAT
+		if (strcmp(auth_type, "KERBEROS_V4") == 0) {
+			if (clevel == PROT_P)
+				length = krb_mk_priv((unsigned char *)in,
+						     (unsigned char *)out,
+						     strlen(in),
+						     schedule, &kdata.session,
+						     &ctrl_addr,
+						     &his_addr);
+			else
+				length = krb_mk_safe((unsigned char *)in,
+						     (unsigned char *)out,
+						     strlen(in),
+						     &kdata.session,
+						     &ctrl_addr,
+						     &his_addr);
+			if (length == -1) {
+				syslog(LOG_ERR,
+				       "krb_mk_%s failed for KERBEROS_V4",
+				       clevel == PROT_P ? "priv" : "safe");
+				fputs(in,stdout);
+			}
+		} else
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+		/* reply (based on level) */
+		if (strcmp(auth_type, "GSSAPI") == 0) {
+			gss_buffer_desc in_buf, out_buf;
+			OM_uint32 maj_stat, min_stat;
+			int conf_state;
+		
+			in_buf.value = in;
+			in_buf.length = strlen(in);
+			maj_stat = gss_seal(&min_stat, gcontext,
+					    clevel == PROT_P, /* private */
+					    GSS_C_QOP_DEFAULT,
+					    &in_buf, &conf_state,
+					    &out_buf);
+			if (maj_stat != GSS_S_COMPLETE) {
+#if 0
+/* Don't setup an infinite loop */
+				/* generally need to deal */
+				secure_gss_error(maj_stat, min_stat,
+					       (clevel==PROT_P)?
+						 "gss_seal ENC didn't complete":
+						 "gss_seal MIC didn't complete");
+#endif /* 0 */
+			} else if ((clevel == PROT_P) && !conf_state) {
+#if 0
+/* Don't setup an infinite loop */
+				secure_error("GSSAPI didn't encrypt message");
+#endif /* 0 */
+			} else {
+				memcpy(out, out_buf.value, 
+				       length=out_buf.length);
+				gss_release_buffer(&min_stat, &out_buf);
+			}
+		}
+#endif /* GSSAPI */
+		/* Other auth types go here ... */
+		if (length >= sizeof(in) / 4 * 3) {
+			syslog(LOG_ERR, "input to radix_encode too long");
+			fputs(in, stdout);
+		} else if ((kerror = radix_encode(out, in, &length, 0))) {
+			syslog(LOG_ERR, "Couldn't encode reply (%s)",
+					radix_error(kerror));
+			fputs(in,stdout);
+		} else
+			printf("%s%c%s", clevel == PROT_P ? "632" : "631",
+			       n ? cont_char : '-', in);
+	} else {
+		if (n) printf("%d%c", n, cont_char);
+		fputs(buf, stdout);
+	}
+	printf("\r\n");
+	(void)fflush(stdout);
+	if (debug) {
+		if (n) syslog(LOG_DEBUG, "<--- %d%c", n, cont_char);
+		syslog(LOG_DEBUG, "%s", buf);
+	}
+}
+
+/*
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ
+ */
+#ifdef STDARG
+void
+lreply(int n, char *fmt, ...)
+#else
+/* VARARGS2 */
+void
+lreply(n, fmt, p0, p1, p2, p3, p4, p5)
+	int n;
+	char *fmt;
+#endif
+{
+	char buf[FTP_BUFSIZ];
+#ifdef STDARG
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buf, fmt, ap);
+	va_end(ap);
+#else
+	sprintf(buf, fmt, p0, p1, p2, p3, p4, p5);
+#endif
+	cont_char = '-';
+	reply(n, "%s", buf);
+	cont_char = ' ';
+}
+
+void
+ack(s)
+	char *s;
+{
+	reply(250, "%s command successful.", s);
+}
+
+void
+nack(s)
+	char *s;
+{
+	reply(502, "%s command not implemented.", s);
+}
+
+/* ARGSUSED */
+void
+yyerror(s)
+	char *s;
+{
+	char *cp;
+
+	cp = strchr(cbuf,'\n');
+	if (cp)
+		*cp = '\0';
+	reply(500, "'%.*s': command not understood.",
+	      (int) (FTP_BUFSIZ - sizeof("'': command not understood.")),
+	      cbuf);
+}
+
+void
+delete_file(name)
+	char *name;
+{
+	struct stat st;
+
+	if (logging > 1) syslog(LOG_NOTICE, "del %s", path_expand(name));
+
+	if (stat(name, &st) < 0) {
+		perror_reply(550, name);
+		return;
+	}
+	if ((st.st_mode&S_IFMT) == S_IFDIR) {
+		if (rmdir(name) < 0) {
+			perror_reply(550, name);
+			return;
+		}
+		goto done;
+	}
+	if (unlink(name) < 0) {
+		perror_reply(550, name);
+		return;
+	}
+done:
+	ack("DELE");
+}
+
+void
+cwd(path)
+	char *path;
+{
+	if (chdir(path) < 0)
+		perror_reply(550, path);
+	else
+		ack("CWD");
+}
+
+void
+makedir(name)
+	char *name;
+{
+        if (logging > 1) syslog(LOG_NOTICE, "mkdir %s", path_expand(name));
+
+	if (mkdir(name, 0777) < 0)
+		perror_reply(550, name);
+	else
+		reply(257, "MKD command successful.");
+}
+
+void
+removedir(name)
+	char *name;
+{
+        if (logging > 1) syslog(LOG_NOTICE, "rmdir %s", path_expand(name));
+
+	if (rmdir(name) < 0)
+		perror_reply(550, name);
+	else
+		ack("RMD");
+}
+
+void
+pwd()
+{
+	if (getcwd(pathbuf, sizeof pathbuf) == (char *)NULL)
+#ifdef POSIX
+		perror_reply(550, pathbuf);
+#else
+		reply(550, "%s.", pathbuf);
+#endif
+	else
+		reply(257, "\"%s\" is current directory.", pathbuf);
+}
+
+char *
+renamefrom(name)
+	char *name;
+{
+	struct stat st;
+
+	if (stat(name, &st) < 0) {
+		perror_reply(550, name);
+		return ((char *)0);
+	}
+	reply(350, "File exists, ready for destination name");
+	return (name);
+}
+
+void
+renamecmd(from, to)
+	char *from, *to;
+{
+        if(logging > 1)
+                syslog(LOG_NOTICE, "rename %s %s", path_expand(from), to);
+
+	if (rename(from, to) < 0)
+		perror_reply(550, "rename");
+	else
+		ack("RNTO");
+}
+
+static void
+dolog(sin4)
+	struct sockaddr_in *sin4;
+{
+	struct hostent *hp = gethostbyaddr((char *)&sin4->sin_addr,
+		sizeof (struct in_addr), AF_INET);
+	time_t t, time();
+	extern char *ctime();
+	krb5_error_code retval;
+
+	if (hp != NULL) {
+		(void) strncpy(remotehost, hp->h_name, sizeof (remotehost));
+		remotehost[sizeof (remotehost) - 1] = '\0';
+	} else
+		remotehost[0] = '\0';
+	strncpy(rhost_addra, inet_ntoa(sin4->sin_addr), sizeof (rhost_addra));
+	rhost_addra[sizeof (rhost_addra) - 1] = '\0';
+	retval = pty_make_sane_hostname((struct sockaddr *) sin4, maxhostlen,
+					stripdomain, always_ip, &rhost_sane);
+	if (retval) {
+		fprintf(stderr, "make_sane_hostname: %s\n",
+			error_message(retval));
+		exit(1);
+	}
+#ifdef SETPROCTITLE
+	sprintf(proctitle, "%s: connected", rhost_sane);
+	setproctitle(proctitle);
+#endif /* SETPROCTITLE */
+
+	if (logging) {
+		t = time((time_t *) 0);
+		syslog(LOG_INFO, "connection from %s (%s) at %s",
+		    rhost_addra, remotehost, ctime(&t));
+	}
+}
+
+/*
+ * Record logout in wtmp file
+ * and exit with supplied status.
+ */
+void
+dologout(status)
+	int status;
+{
+	if (logged_in) {
+		(void) krb5_seteuid((uid_t)0);
+		pty_logwtmp(ttyline, "", "");
+	}
+	if (have_creds) {
+#ifdef GSSAPI
+		krb5_cc_destroy(kcontext, ccache);
+#endif
+#ifdef KRB5_KRB4_COMPAT
+		dest_tkt();
+#endif
+	}
+	/* beware of flushing buffers after a SIGPIPE */
+	_exit(status);
+}
+
+void
+myoob(sig)
+    int sig;
+{
+	char *cp, *cs;
+#ifndef strpbrk
+	extern char *strpbrk();
+#endif
+
+	/* only process if transfer occurring */
+	if (!transflag)
+		return;
+	cp = tmpline;
+	if (ftpd_getline(cp, sizeof(tmpline), stdin) == NULL) {
+		reply(221, "You could at least say goodbye.");
+		dologout(0);
+	}
+	upper(cp);
+	if ((cs = strpbrk(cp, "\r\n")))
+		*cs++ = '\0';
+	if (strcmp(cp, "ABOR") == 0) {
+		tmpline[0] = '\0';
+		reply(426, "Transfer aborted. Data connection closed.");
+		reply(226, "Abort successful");
+		siglongjmp(urgcatch, 1);
+	}
+	if (strcmp(cp, "STAT") == 0) {
+		if (file_size != (off_t) -1)
+			reply(213, "Status: %lu of %lu bytes transferred",
+			      (unsigned long) byte_count, 
+			      (unsigned long) file_size);
+		else
+			reply(213, "Status: %lu bytes transferred", 
+			      (unsigned long) byte_count);
+	}
+}
+
+/*
+ * Note: a response of 425 is not mentioned as a possible response to
+ * 	the PASV command in RFC959. However, it has been blessed as
+ * 	a legitimate response by Jon Postel in a telephone conversation
+ *	with Rick Adams on 25 Jan 89.
+ */
+void
+passive()
+{
+	int len;
+	register char *p, *a;
+
+	pdata = socket(AF_INET, SOCK_STREAM, 0);
+	if (pdata < 0) {
+		perror_reply(425, "Can't open passive connection");
+		return;
+	}
+	pasv_addr = ctrl_addr;
+	pasv_addr.sin_port = 0;
+	(void) krb5_seteuid((uid_t)0);
+	if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) {
+		(void) krb5_seteuid((uid_t)pw->pw_uid);
+		goto pasv_error;
+	}
+	if (krb5_seteuid((uid_t)pw->pw_uid)) {
+		fatal("seteuid user");
+	}
+	len = sizeof(pasv_addr);
+	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
+		goto pasv_error;
+	if (listen(pdata, 1) < 0)
+		goto pasv_error;
+	a = (char *) &pasv_addr.sin_addr;
+	p = (char *) &pasv_addr.sin_port;
+
+#define UC(b) (((int) b) & 0xff)
+
+	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
+		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+	return;
+
+pasv_error:
+	(void) close(pdata);
+	pdata = -1;
+	perror_reply(425, "Can't open passive connection");
+	return;
+}
+
+/*
+ * Generate unique name for file with basename "local".
+ * The file named "local" is already known to exist.
+ * Generates failure reply on error.
+ */
+static char *
+gunique(local)
+	char *local;
+{
+	static char new[MAXPATHLEN];
+	struct stat st;
+	char *cp = strrchr(local, '/');
+	int count = 0;
+
+	if (cp)
+		*cp = '\0';
+	if (stat(cp ? local : ".", &st) < 0) {
+		perror_reply(553, cp ? local : ".");
+		return((char *) 0);
+	}
+	if (cp)
+		*cp = '/';
+	(void) strncpy(new, local, sizeof(new) - 1);
+	new[sizeof(new) - 1] = '\0';
+	cp = new + strlen(new);
+	*cp++ = '.';
+	for (count = 1; count < 100; count++) {
+		(void) sprintf(cp, "%d", count);
+		if (stat(new, &st) < 0)
+			return(new);
+	}
+	reply(452, "Unique file name cannot be created.");
+	return((char *) 0);
+}
+
+/*
+ * Format and send reply containing system error number.
+ */
+void
+perror_reply(code, string)
+	int code;
+	char *string;
+{
+	char *err_string;
+	size_t extra_len;
+
+	err_string = strerror(errno);
+	if (err_string == NULL)
+		err_string = "(unknown error)";
+	extra_len = strlen(err_string) + sizeof("(truncated): .");
+
+	/*
+	 * XXX knows about FTP_BUFSIZ in reply()
+	 */
+	if (strlen(string) + extra_len > FTP_BUFSIZ) {
+		reply(code, "(truncated)%.*s: %s.",
+		      (int) (FTP_BUFSIZ - extra_len), string, err_string);
+	} else {
+		reply(code, "%s: %s.", string, err_string);
+	}
+}
+
+void
+auth(atype)
+char *atype;
+{
+	if (auth_type)
+		reply(534, "Authentication type already set to %s", auth_type);
+	else
+#ifdef KRB5_KRB4_COMPAT
+	if (strcmp(atype, "KERBEROS_V4") == 0)
+		reply(334, "Using authentication type %s; ADAT must follow",
+				temp_auth_type = atype);
+	else
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+	if (strcmp(atype, "GSSAPI") == 0)
+		reply(334, "Using authentication type %s; ADAT must follow",
+				temp_auth_type = atype);
+	else
+#endif /* GSSAPI */
+	/* Other auth types go here ... */
+		reply(504, "Unknown authentication type: %s", atype);
+}
+
+int
+auth_data(adata)
+char *adata;
+{
+	int kerror, length;
+#ifdef KRB5_KRB4_COMPAT
+	static char **service=NULL;
+	char instance[INST_SZ];
+	KRB4_32 cksum;
+	char buf[FTP_BUFSIZ];
+	u_char out_buf[sizeof(buf)];
+#endif /* KRB5_KRB4_COMPAT */
+
+	if (auth_type) {
+		reply(503, "Authentication already established");
+		return(0);
+	}
+	if (!temp_auth_type) {
+		reply(503, "Must identify AUTH type before ADAT");
+		return(0);
+	}
+#ifdef KRB5_KRB4_COMPAT
+	if (strcmp(temp_auth_type, "KERBEROS_V4") == 0) {
+	        kerror = radix_encode(adata, out_buf, &length, 1);
+		if (kerror) {
+			reply(501, "Couldn't decode ADAT (%s)",
+			      radix_error(kerror));
+			syslog(LOG_ERR, "Couldn't decode ADAT (%s)",
+			       radix_error(kerror));
+			return(0);
+		}
+		(void) memcpy((char *)ticket.dat, (char *)out_buf, ticket.length = length);
+		strcpy(instance, "*");
+
+		kerror = 255;
+		for (service = krb4_services; *service; service++) {
+		  kerror = krb_rd_req(&ticket, *service, instance,
+				      his_addr.sin_addr.s_addr, 
+				      &kdata, keyfile);
+		  /* Success */
+		  if(!kerror) break;
+		} 
+		/* rd_req failed.... */
+		if(kerror) {
+		  secure_error("ADAT: Kerberos V4 krb_rd_req: %s",
+			       krb_get_err_text(kerror));
+		  return(0);
+		}
+
+		/* add one to the (formerly) sealed checksum, and re-seal it */
+		cksum = kdata.checksum + 1;
+		cksum = htonl(cksum);
+		key_sched(kdata.session,schedule);
+		if ((length = krb_mk_safe((u_char *)&cksum, out_buf, sizeof(cksum),
+					  &kdata.session,&ctrl_addr, &his_addr)) == -1) {
+			secure_error("ADAT: krb_mk_safe failed");
+			return(0);
+		}
+		if (length >= (FTP_BUFSIZ - sizeof("ADAT=")) / 4 * 3) {
+			secure_error("ADAT: reply too long");
+			return(0);
+		}
+
+		kerror = radix_encode(out_buf, buf, &length, 0);
+		if (kerror) {
+			secure_error("Couldn't encode ADAT reply (%s)",
+				     radix_error(kerror));
+			return(0);
+		}
+		reply(235, "ADAT=%s", buf);
+		/* Kerberos V4 authentication succeeded */
+		auth_type = temp_auth_type;
+		temp_auth_type = NULL;
+		return(1);
+	}
+#endif /* KRB5_KRB4_COMPAT */
+#ifdef GSSAPI
+	if (strcmp(temp_auth_type, "GSSAPI") == 0) {
+		int replied = 0;
+		int found = 0;
+		gss_cred_id_t server_creds, deleg_creds;
+		gss_name_t client;
+		OM_uint32 ret_flags;
+		int rad_len;
+		gss_buffer_desc name_buf;
+		gss_name_t server_name;
+		OM_uint32 acquire_maj, acquire_min, accept_maj, accept_min,
+				stat_maj, stat_min;
+		gss_OID mechid;
+		gss_buffer_desc tok, out_tok;
+		char gbuf[FTP_BUFSIZ];
+		u_char gout_buf[FTP_BUFSIZ];
+		char localname[MAXHOSTNAMELEN];
+		char service_name[MAXHOSTNAMELEN+10];
+		char **gservice;
+		struct hostent *hp;
+		stat_maj = 0;
+		accept_maj = 0;
+		acquire_maj = 0;
+
+		kerror = radix_encode(adata, gout_buf, &length, 1);
+		if (kerror) {
+			reply(501, "Couldn't decode ADAT (%s)",
+			      radix_error(kerror));
+			syslog(LOG_ERR, "Couldn't decode ADAT (%s)",
+			       radix_error(kerror));
+			return(0);
+		}
+		tok.value = gout_buf;
+		tok.length = length;
+
+		if (gethostname(localname, MAXHOSTNAMELEN)) {
+			reply(501, "couldn't get local hostname (%d)\n", errno);
+			syslog(LOG_ERR, "Couldn't get local hostname (%d)", errno);
+			return 0;
+		}
+		if (!(hp = gethostbyname(localname))) {
+			reply(501, "couldn't canonicalize local hostname\n");
+			syslog(LOG_ERR, "Couldn't canonicalize local hostname");
+			return 0;
+		}
+		strncpy(localname, hp->h_name, sizeof(localname) - 1);
+		localname[sizeof(localname) - 1] = '\0';
+
+		for (gservice = gss_services; *gservice; gservice++) {
+			sprintf(service_name, "%s@%s", *gservice, localname);
+			name_buf.value = service_name;
+			name_buf.length = strlen(name_buf.value) + 1;
+			if (debug)
+				syslog(LOG_INFO, "importing <%s>", service_name);
+			stat_maj = gss_import_name(&stat_min, &name_buf, 
+						   gss_nt_service_name,
+						   &server_name);
+			if (stat_maj != GSS_S_COMPLETE) {
+				reply_gss_error(501, stat_maj, stat_min,
+						"importing name");
+				syslog(LOG_ERR, "gssapi error importing name");
+				return 0;
+			}
+			
+			acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
+						       GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+						       &server_creds, NULL, NULL);
+			(void) gss_release_name(&stat_min, &server_name);
+
+			if (acquire_maj != GSS_S_COMPLETE)
+				continue;
+
+			found++;
+
+			gcontext = GSS_C_NO_CONTEXT;
+
+			accept_maj = gss_accept_sec_context(&accept_min,
+							    &gcontext, /* context_handle */
+							    server_creds, /* verifier_cred_handle */
+							    &tok, /* input_token */
+							    GSS_C_NO_CHANNEL_BINDINGS, /* channel bindings */
+							    &client, /* src_name */
+							    &mechid, /* mech_type */
+							    &out_tok, /* output_token */
+							    &ret_flags,
+							    NULL, 	/* ignore time_rec */
+							    &deleg_creds  /* forwarded credentials */
+							    );
+			if (accept_maj==GSS_S_COMPLETE||accept_maj==GSS_S_CONTINUE_NEEDED)
+				break;
+		}
+
+		if (found) {
+			if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
+				reply_gss_error(535, accept_maj, accept_min,
+						"accepting context");
+				syslog(LOG_ERR, "failed accepting context");
+				(void) gss_release_cred(&stat_min, &server_creds);
+				if (ret_flags & GSS_C_DELEG_FLAG)
+					(void) gss_release_cred(&stat_min,
+								&deleg_creds);
+				return 0;
+			}
+		} else {
+			/* Kludge to make sure the right error gets reported, so we don't *
+			 * get those nasty "error: no error" messages.			  */
+			if(stat_maj != GSS_S_COMPLETE)
+			        reply_gss_error(501, stat_maj, stat_min,
+						"acquiring credentials");
+			else
+			        reply_gss_error(501, acquire_maj, acquire_min,
+						"acquiring credentials");
+			syslog(LOG_ERR, "gssapi error acquiring credentials");
+			return 0;
+		}
+
+		if (out_tok.length) {
+			if (out_tok.length >= ((FTP_BUFSIZ - sizeof("ADAT="))
+					       / 4 * 3)) {
+				secure_error("ADAT: reply too long");
+				syslog(LOG_ERR, "ADAT: reply too long");
+				(void) gss_release_cred(&stat_min, &server_creds);
+				if (ret_flags & GSS_C_DELEG_FLAG)
+					(void) gss_release_cred(&stat_min,
+								&deleg_creds);
+				return(0);
+			}
+
+			rad_len = out_tok.length;
+			kerror = radix_encode(out_tok.value, gbuf, 
+					      &rad_len, 0);
+			out_tok.length = rad_len;
+			if (kerror) {
+				secure_error("Couldn't encode ADAT reply (%s)",
+					     radix_error(kerror));
+				syslog(LOG_ERR, "couldn't encode ADAT reply");
+				(void) gss_release_cred(&stat_min, &server_creds);
+				if (ret_flags & GSS_C_DELEG_FLAG)
+					(void) gss_release_cred(&stat_min,
+								&deleg_creds);
+				return(0);
+			}
+			if (accept_maj == GSS_S_COMPLETE) {
+				reply(235, "ADAT=%s", gbuf);
+			} else {
+				/* If the server accepts the security data, and
+				   requires additional data, it should respond
+				   with reply code 335. */
+				reply(335, "ADAT=%s", gbuf);
+			}
+			replied = 1;
+			(void) gss_release_buffer(&stat_min, &out_tok);
+		}
+		if (accept_maj == GSS_S_COMPLETE) {
+			/* GSSAPI authentication succeeded */
+			stat_maj = gss_display_name(&stat_min, client,
+						    &client_name, &mechid);
+			if (stat_maj != GSS_S_COMPLETE) {
+				/* "If the server rejects the security data (if
+				   a checksum fails, for instance), it should 
+				   respond with reply code 535." */
+				reply_gss_error(535, stat_maj, stat_min,
+						"extracting GSSAPI identity name");
+				log_gss_error(LOG_ERR, stat_maj, stat_min,
+					      "gssapi error extracting identity");
+				(void) gss_release_cred(&stat_min, &server_creds);
+				if (ret_flags & GSS_C_DELEG_FLAG)
+					(void) gss_release_cred(&stat_min,
+								&deleg_creds);
+				return 0;
+			}
+			auth_type = temp_auth_type;
+			temp_auth_type = NULL;
+
+			(void) gss_release_cred(&stat_min, &server_creds);
+			if (ret_flags & GSS_C_DELEG_FLAG) {
+			  if (want_creds)
+			    ftpd_gss_convert_creds(client_name.value,
+						   deleg_creds);
+			  (void) gss_release_cred(&stat_min, &deleg_creds);
+			}
+
+			/* If the server accepts the security data, but does
+			   not require any additional data (i.e., the security
+			   data exchange has completed successfully), it must
+			   respond with reply code 235. */
+			if (!replied)
+			  {
+			    if (ret_flags & GSS_C_DELEG_FLAG && !have_creds)
+			      reply(235, "GSSAPI Authentication succeeded, but could not accept forwarded credentials");
+			    else
+			      reply(235, "GSSAPI Authentication succeeded");
+			  }
+				
+			return(1);
+		} else if (accept_maj == GSS_S_CONTINUE_NEEDED) {
+			/* If the server accepts the security data, and
+			   requires additional data, it should respond with
+			   reply code 335. */
+			if (!replied)
+			    reply(335, "more data needed");
+			(void) gss_release_cred(&stat_min, &server_creds);
+			if (ret_flags & GSS_C_DELEG_FLAG)
+			  (void) gss_release_cred(&stat_min, &deleg_creds);
+			return(0);
+		} else {
+			/* "If the server rejects the security data (if 
+			   a checksum fails, for instance), it should 
+			   respond with reply code 535." */
+			reply_gss_error(535, stat_maj, stat_min, 
+					"GSSAPI failed processing ADAT");
+			syslog(LOG_ERR, "GSSAPI failed processing ADAT");
+			(void) gss_release_cred(&stat_min, &server_creds);
+			if (ret_flags & GSS_C_DELEG_FLAG)
+			  (void) gss_release_cred(&stat_min, &deleg_creds);
+			return(0);
+		}
+	}
+#endif /* GSSAPI */
+	/* Other auth types go here ... */
+	/* Also need to check authorization, but that is done in user() */
+	return(0);
+}
+
+static char *onefile[] = {
+	"",
+	0
+};
+
+/* returns:
+ *	n>=0 on success
+ *	-1 on error
+ *	-2 on security error
+ *
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ
+ */
+#ifdef STDARG
+static int
+secure_fprintf(FILE *stream, char *fmt, ...)
+#else
+static int
+secure_fprintf(stream, fmt, p1, p2, p3, p4, p5)
+FILE *stream;
+char *fmt;
+#endif
+{
+        char s[FTP_BUFSIZ];
+        int rval;
+#ifdef STDARG
+        va_list ap;
+
+        va_start(ap, fmt);
+        if (dlevel == PROT_C) rval = vfprintf(stream, fmt, ap);
+        else {
+                vsprintf(s, fmt, ap);
+                rval = secure_write(fileno(stream), s, strlen(s));
+        }
+        va_end(ap);
+
+        return(rval);
+#else
+        if (dlevel == PROT_C)
+                return(fprintf(stream, fmt, p1, p2, p3, p4, p5));
+        sprintf(s, fmt, p1, p2, p3, p4, p5);
+        return(secure_write(fileno(stream), s, strlen(s)));
+#endif
+}
+
+void
+send_file_list(whichfiles)
+	char *whichfiles;
+{
+	struct stat st;
+	DIR *dirp = NULL;
+	struct dirent *dir;
+	FILE *volatile dout = NULL;
+	register char **volatile dirlist, *dirname;
+	volatile int simple = 0;
+#ifndef strpbrk
+	char *strpbrk();
+#endif
+	volatile int ret = 0;
+
+	if (strpbrk(whichfiles, "~{[*?") != NULL) {
+		extern char **ftpglob(), *globerr;
+
+		globerr = NULL;
+		dirlist = ftpglob(whichfiles);
+		if (globerr != NULL) {
+			reply(550, globerr);
+			return;
+		} else if (dirlist == NULL) {
+			errno = ENOENT;
+			perror_reply(550, whichfiles);
+			return;
+		}
+	} else {
+		onefile[0] = whichfiles;
+		dirlist = onefile;
+		simple = 1;
+	}
+
+	if (sigsetjmp(urgcatch, 1)) {
+		transflag = 0;
+		(void)secure_flush(fileno(dout));
+		return;
+	}
+	while ((dirname = *dirlist++)) {
+		if (stat(dirname, &st) < 0) {
+			/*
+			 * If user typed "ls -l", etc, and the client
+			 * used NLST, do what the user meant.
+			 */
+			if (dirname[0] == '-' && *dirlist == NULL &&
+			    transflag == 0) {
+				retrieve("/bin/ls %s", dirname);
+				return;
+			}
+			perror_reply(550, whichfiles);
+			if (dout != NULL) {
+				(void) fclose(dout);
+				transflag = 0;
+				data = -1;
+				pdata = -1;
+			}
+			return;
+		}
+
+		if ((st.st_mode&S_IFMT) == S_IFREG) {
+			if (dout == NULL) {
+				dout = dataconn("file list", (off_t)-1, "w");
+				if (dout == NULL)
+					return;
+				transflag++;
+			}
+			if ((ret = secure_fprintf(dout, "%s%s\n", dirname,
+				type == TYPE_A ? "\r" : "")) < 0)
+					goto data_err;
+			byte_count += strlen(dirname) + 1;
+			continue;
+		} else if ((st.st_mode&S_IFMT) != S_IFDIR)
+			continue;
+
+		if ((dirp = opendir(dirname)) == NULL)
+			continue;
+
+		while ((dir = readdir(dirp)) != NULL) {
+			char nbuf[MAXPATHLEN];
+
+			if (dir->d_name[0] == '.' && dir->d_name[1] == '\0')
+				continue;
+			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
+			    dir->d_name[2] == '\0')
+				continue;
+
+			if (strlen(dirname) + strlen(dir->d_name)
+			    + 1 /* slash */
+			    + 2	/* CRLF */
+			    + 1 > sizeof(nbuf)) {
+				syslog(LOG_ERR,
+				       "send_file_list: pathname too long");
+				ret = -2; /* XXX */
+				goto data_err;
+			}
+			sprintf(nbuf, "%s/%s", dirname, dir->d_name);
+
+			/*
+			 * We have to do a stat to insure it's
+			 * not a directory or special file.
+			 */
+			if (simple || (stat(nbuf, &st) == 0 &&
+			    (st.st_mode&S_IFMT) == S_IFREG)) {
+				if (dout == NULL) {
+					dout = dataconn("file list", (off_t)-1,
+						"w");
+					if (dout == NULL)
+						return;
+					transflag++;
+				}
+				if (nbuf[0] == '.' && nbuf[1] == '/')
+				{
+					if ((ret = secure_fprintf(dout, "%s%s\n", &nbuf[2],
+						type == TYPE_A ? "\r" : "")) < 0)
+							goto data_err;
+				}
+				else
+					if ((ret = secure_fprintf(dout, "%s%s\n", nbuf,
+						type == TYPE_A ? "\r" : "")) < 0)
+							goto data_err;
+				byte_count += strlen(nbuf) + 1;
+			}
+		}
+		(void) closedir(dirp);
+	}
+	if (dout != NULL ) {
+	  ret = secure_write(fileno(dout), "", 0);
+	  if (ret >= 0)
+	    ret = secure_flush(fileno(dout));
+	}
+data_err:
+	if (dout == NULL)
+		reply(550, "No files found.");
+	else if (ferror(dout) != 0 || ret == EOF)
+		perror_reply(550, "Data connection");
+	else if (ret != -2)
+		reply(226, "Transfer complete.");
+
+	transflag = 0;
+	if (dout != NULL)
+	  (void) fclose(dout);
+	data = -1;
+	pdata = -1;
+}
+
+#ifdef SETPROCTITLE
+/*
+ * clobber argv so ps will show what we're doing.
+ * (stolen from sendmail)
+ * warning, since this is usually started from inetd.conf, it
+ * often doesn't have much of an environment or arglist to overwrite.
+ */
+
+setproctitle(buf)
+char *buf;
+{
+	register char *p, *bp, ch;
+	register int i;
+
+	/* make ps print our process name */
+	p = Argv[0];
+	*p++ = '-';
+
+	i = strlen(buf);
+	if (i > LastArgv - p - 2) {
+		i = LastArgv - p - 2;
+		buf[i] = '\0';
+	}
+	bp = buf;
+	while (ch = *bp++)
+		if (ch != '\n' && ch != '\r')
+			*p++ = ch;
+	while (p < LastArgv)
+		*p++ = ' ';
+}
+#endif /* SETPROCTITLE */
+
+#ifdef GSSAPI
+/* A more general callback would probably use a void*, but currently I
+   only need an int in both cases.  */
+static void with_gss_error_text(void (*cb)(const char *, int, int),
+				OM_uint32 maj_stat, OM_uint32 min_stat,
+				int misc);
+
+static void
+log_gss_error_1(const char *msg, int severity, int is_major)
+{
+    syslog(severity, "... GSSAPI error %s: %s",
+	   is_major ? "major" : "minor", msg);
+}
+
+static void
+log_gss_error(int severity, OM_uint32 maj_stat, OM_uint32 min_stat,
+	      const char *s)
+{
+    syslog(severity, s);
+    with_gss_error_text(log_gss_error_1, maj_stat, min_stat, severity);
+}
+
+static void
+reply_gss_error_1(const char *msg, int code, int is_major)
+{
+    lreply(code, "GSSAPI error %s: %s",
+	   is_major ? "major" : "minor", msg);
+}
+
+void
+reply_gss_error(int code, OM_uint32 maj_stat, OM_uint32 min_stat, char *s)
+{
+    with_gss_error_text(reply_gss_error_1, maj_stat, min_stat, code);
+    reply(code, "GSSAPI error: %s", s);
+}
+
+static void with_gss_error_text(void (*cb)(const char *, int, int),
+				OM_uint32 maj_stat, OM_uint32 min_stat,
+				int misc)
+{
+	/* a lot of work just to report the error */
+	OM_uint32 gmaj_stat, gmin_stat;
+	gss_buffer_desc msg;
+	OM_uint32 msg_ctx;
+	msg_ctx = 0;
+	while (!msg_ctx) {
+		gmaj_stat = gss_display_status(&gmin_stat, maj_stat,
+					       GSS_C_GSS_CODE,
+					       GSS_C_NULL_OID,
+					       &msg_ctx, &msg);
+		if ((gmaj_stat == GSS_S_COMPLETE)||
+		    (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
+			(*cb)((char*)msg.value, misc, 1);
+			(void) gss_release_buffer(&gmin_stat, &msg);
+		}
+		if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
+			break;
+	}
+	msg_ctx = 0;
+	while (!msg_ctx) {
+		gmaj_stat = gss_display_status(&gmin_stat, min_stat,
+					       GSS_C_MECH_CODE,
+					       GSS_C_NULL_OID,
+					       &msg_ctx, &msg);
+		if ((gmaj_stat == GSS_S_COMPLETE)||
+		    (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
+			(*cb)((char*)msg.value, misc, 0);
+			(void) gss_release_buffer(&gmin_stat, &msg);
+		}
+		if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
+			break;
+	}
+}
+
+void
+secure_gss_error(maj_stat, min_stat, s)
+OM_uint32 maj_stat, min_stat;
+char *s;
+{
+  reply_gss_error(535, maj_stat, min_stat, s);
+  return;
+}
+
+
+/* ftpd_gss_userok -- hide details of getting the name and verifying it */
+/* returns 0 for OK */
+static int
+ftpd_gss_userok(gclient_name, name)
+	gss_buffer_t gclient_name;
+	char *name;
+{
+	int retval = -1;
+	krb5_principal p;
+	
+	if (krb5_parse_name(kcontext, gclient_name->value, &p) != 0)
+		return -1;
+	if (krb5_kuserok(kcontext, p, name))
+		retval = 0;
+	else 
+		retval = 1;
+	krb5_free_principal(kcontext, p);
+	return retval;
+}
+
+/* ftpd_gss_convert_creds -- write out forwarded creds */
+/* (code lifted from login.krb5) */
+static void
+ftpd_gss_convert_creds(name, creds)
+	char *name;
+	gss_cred_id_t creds;
+{
+	OM_uint32 major_status, minor_status;
+	krb5_principal me;
+	char ccname[MAXPATHLEN];
+#ifdef KRB5_KRB4_COMPAT
+	krb5_principal kpcserver;
+	krb5_creds increds, *v5creds;
+	CREDENTIALS v4creds;
+#endif
+
+	/* Set up ccache */
+	if (krb5_parse_name(kcontext, name, &me))
+		return;
+
+	sprintf(ccname, "FILE:/tmp/krb5cc_ftpd%ld", (long) getpid());
+	if (krb5_cc_resolve(kcontext, ccname, &ccache))
+		return;
+	if (krb5_cc_initialize(kcontext, ccache, me))
+		return;
+
+	/* Copy GSS creds into ccache */
+	major_status = gss_krb5_copy_ccache(&minor_status, creds, ccache);
+	if (major_status != GSS_S_COMPLETE)
+		goto cleanup;
+
+#ifdef KRB5_KRB4_COMPAT
+	/* Convert krb5 creds to krb4 */
+
+	if (krb5_build_principal_ext(kcontext, &kpcserver, 
+				     krb5_princ_realm(kcontext, me)->length,
+				     krb5_princ_realm(kcontext, me)->data,
+				     6, "krbtgt",
+				     krb5_princ_realm(kcontext, me)->length,
+				     krb5_princ_realm(kcontext, me)->data,
+				     0))
+		goto cleanup;
+
+	memset((char *) &increds, 0, sizeof(increds));
+	increds.client = me;
+	increds.server = kpcserver;
+	increds.times.endtime = 0;
+	increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+	if (krb5_get_credentials(kcontext, 0, ccache, &increds, &v5creds))
+		goto cleanup;
+	if (krb524_convert_creds_kdc(kcontext, v5creds, &v4creds))
+		goto cleanup;
+
+	sprintf(ccname, "%s_ftpd%ld", TKT_ROOT, (long) getpid());
+	krb_set_tkt_string(ccname);
+
+	if (in_tkt(v4creds.pname, v4creds.pinst) != KSUCCESS)
+		goto cleanup;
+
+	if (krb_save_credentials(v4creds.service, v4creds.instance,
+				 v4creds.realm, v4creds.session,
+				 v4creds.lifetime, v4creds.kvno,
+				 &(v4creds.ticket_st), v4creds.issue_date))
+		goto cleanup_v4;
+#endif /* KRB5_KRB4_COMPAT */
+	have_creds = 1;
+	return;
+
+#ifdef KRB5_KRB4_COMPAT
+cleanup_v4:
+	dest_tkt();
+#endif
+cleanup:
+	krb5_cc_destroy(kcontext, ccache);
+}
+
+
+#endif /* GSSAPI */
+
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/ftpd_var.h b/krb5-1-6/src/appl/gssftp/ftpd/ftpd_var.h
new file mode 100644
index 000000000..8d833e4ec
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/ftpd_var.h
@@ -0,0 +1,97 @@
+/*
+ * appl/gssftp/ftpd/ftp_var.h
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Prototypes for various functions in the ftpd sources.
+ */
+
+#ifndef FTPD_VAR_H__
+#define FTPD_VAR_H__
+
+/* Prototypes */
+
+#ifdef GSSAPI
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#endif
+
+/* radix.c */
+char *radix_error (int);
+int radix_encode (unsigned char *, unsigned char *, int *, int);
+
+/* ftpd.c */
+void ack(char *);
+int auth_data(char *);
+void auth(char *);
+void cwd(char *);
+void delete_file(char *);
+void dologout(int);
+void fatal(char *);
+void makedir(char *);
+void nack(char *);
+void pass(char *);
+void passive(void);
+void perror_reply(int, char *);
+void pwd(void);
+void removedir(char *);
+void renamecmd(char *, char *);
+char *renamefrom(char *);
+void retrieve(char *, char *);
+void send_file_list(char *);
+void setdlevel(int);
+void statcmd(void);
+void statfilecmd(char *);
+void store_file(char *, char *, int);
+void user(char *);
+void yyerror(char *);
+
+#ifdef GSSAPI
+void
+reply_gss_error(int, OM_uint32, OM_uint32, char *);
+#endif
+
+
+#if defined(STDARG) || (defined(__STDC__) && ! defined(VARARGS)) || defined(HAVE_STDARG_H)
+extern void reply(int, char *, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+     __attribute__ ((__format__ (__printf__, 2, 3)))
+#endif
+     ;
+extern void lreply(int, char *, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+     __attribute__ ((__format__ (__printf__, 2, 3)))
+#endif
+     ;
+#endif
+
+
+/* ftpcmd.y */
+void upper(char *);
+char *ftpd_getline(char *, int, FILE *);
+#endif /* FTPD_VAR_H__ */
+
+/* popen.c */
+FILE * ftpd_popen(char *, char *);
+int ftpd_pclose(FILE *);
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/logwtmp.c b/krb5-1-6/src/appl/gssftp/ftpd/logwtmp.c
new file mode 100644
index 000000000..06b97b986
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/logwtmp.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)logwtmp.c	5.7 (Berkeley) 2/25/91";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifdef WTMP_FILE
+#define WTMPFILE WTMP_FILE
+#else
+#ifdef _PATH_WTMP
+#define WTMPFILE _PATH_WTMP
+#endif 	/* _PATH_WTMP  */
+#endif	/* WTMP_FILE */
+
+#ifndef WTMPFILE
+#define	WTMPFILE	"/usr/adm/wtmp"
+#endif
+
+static int fd = -1;
+
+/*
+ * Modified version of logwtmp that holds wtmp file open
+ * after first call, for use with ftp (which may chroot
+ * after login, but before logout).
+ */
+void ftp_logwtmp(line, name, host)
+	char *line, *name, *host;
+{
+	struct utmp ut;
+	struct stat buf;
+	time_t time();
+
+	if (fd < 0 && (fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
+		return;
+	if (fstat(fd, &buf) == 0) {
+		(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+		(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+#ifndef NO_UT_HOST
+		(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+#endif
+		(void)time(&ut.ut_time);
+		if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
+		    sizeof(struct utmp))
+			(void)ftruncate(fd, buf.st_size);
+	}
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/pathnames.h b/krb5-1-6/src/appl/gssftp/ftpd/pathnames.h
new file mode 100644
index 000000000..41398bc5f
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/pathnames.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)pathnames.h	5.2 (Berkeley) 6/1/90
+ */
+
+#define	_PATH_FTPUSERS_DEFAULT	"/etc/ftpusers"
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/popen.c b/krb5-1-6/src/appl/gssftp/ftpd/popen.c
new file mode 100644
index 000000000..e9e589594
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/popen.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)popen.c	5.9 (Berkeley) 2/25/91";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ftpd_var.h"
+
+/*
+ * Special version of popen which avoids call to shell.  This insures noone
+ * may create a pipe to a hidden program as a side effect of a list or dir
+ * command.
+ */
+static int *pids;
+static int fds;
+
+#define MAX_ARGV	100
+#define MAX_GARGV	1000
+
+FILE *
+ftpd_popen(program, type)
+	char *program, *type;
+{
+	register char *cp;
+	FILE *volatile iop;
+	int argc, gargc, pdes[2], pid;
+	char **pop, *argv[MAX_ARGV], *gargv[MAX_GARGV], *vv[2];
+	extern char **ftpglob(), **copyblk();
+	extern void blkfree(char **);
+
+	if ((*type != 'r' && *type != 'w') || type[1])
+		return(NULL);
+
+	if (!pids) {
+		if ((fds = getdtablesize()) <= 0)
+			return(NULL);
+		if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
+			return(NULL);
+		memset((char *)pids, 0, fds * sizeof(int));
+	}
+	if (pipe(pdes) < 0)
+		return(NULL);
+
+	/* break up string into pieces */
+	for (argc = 0, cp = program; argc < MAX_ARGV - 1; cp = NULL)
+		if (!(argv[argc++] = strtok(cp, " \t\n")))
+			break;
+	argv[MAX_ARGV-1] = NULL;
+	for (argc = 0; argv[argc]; argc++)
+		argv[argc] = strdup(argv[argc]);
+
+	/* glob each piece */
+	gargv[0] = argv[0];
+	for (gargc = argc = 1; argv[argc]; argc++) {
+		if (!(pop = ftpglob(argv[argc]))) {	/* globbing failed */
+			vv[0] = argv[argc];
+			vv[1] = NULL;
+			pop = copyblk(vv);
+		}
+		argv[argc] = (char *)pop;		/* save to free later */
+		while (*pop && gargc < MAX_GARGV)
+			gargv[gargc++] = *pop++;
+	}
+	gargv[gargc] = NULL;
+
+	iop = NULL;
+	switch(pid = fork()) {
+	case -1:			/* error */
+		(void)close(pdes[0]);
+		(void)close(pdes[1]);
+		goto pfree;
+		/* NOTREACHED */
+	case 0:				/* child */
+		if (*type == 'r') {
+			if (pdes[1] != 1) {
+				dup2(pdes[1], 1);
+				dup2(pdes[1], 2);	/* stderr, too! */
+				(void)close(pdes[1]);
+			}
+			(void)close(pdes[0]);
+		} else {
+			if (pdes[0] != 0) {
+				dup2(pdes[0], 0);
+				(void)close(pdes[0]);
+			}
+			(void)close(pdes[1]);
+		}
+		execv(gargv[0], gargv);
+		_exit(1);
+	}
+	/* parent; assume fdopen can't fail...  */
+	if (*type == 'r') {
+		iop = fdopen(pdes[0], type);
+		(void)close(pdes[1]);
+	} else {
+		iop = fdopen(pdes[1], type);
+		(void)close(pdes[0]);
+	}
+	pids[fileno(iop)] = pid;
+
+pfree:	for (argc = 1; argv[argc] != NULL; argc++) {
+		blkfree((char **)argv[argc]);
+		free((char *)argv[argc]);
+	}
+	return(iop);
+}
+
+int
+ftpd_pclose(iop)
+	FILE *iop;
+{
+	register int fdes;
+#ifdef USE_SIGPROCMASK
+	sigset_t old, new;
+#else
+	int omask;
+#endif
+#ifdef WAIT_USES_INT
+	int stat_loc;
+#else
+	union wait stat_loc;
+#endif
+	int pid;
+
+	/*
+	 * pclose returns -1 if stream is not associated with a
+	 * `popened' command, or, if already `pclosed'.
+	 */
+	if (pids == 0 || pids[fdes = fileno(iop)] == 0)
+		return(-1);
+	(void)fclose(iop);
+#ifdef USE_SIGPROCMASK
+	sigemptyset(&old);
+	sigemptyset(&new);
+	sigaddset(&new,SIGINT);
+	sigaddset(&new,SIGQUIT);
+	sigaddset(&new,SIGHUP);
+	sigprocmask(SIG_BLOCK, &new, &old);
+	while ((pid = wait((int *)&stat_loc)) != pids[fdes] && pid != -1);
+	sigprocmask(SIG_SETMASK, &old, NULL);
+#else
+	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
+	while ((pid = wait((int *)&stat_loc)) != pids[fdes] && pid != -1);
+	sigsetmask(omask);
+#endif
+	pids[fdes] = 0;
+#ifdef WAIT_USES_INT
+	return(pid == -1 ? -1 : stat_loc);
+#else
+	return(pid == -1 ? -1 : stat_loc.w_status);
+#endif
+}
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/secure.h b/krb5-1-6/src/appl/gssftp/ftpd/secure.h
new file mode 100644
index 000000000..97fd0c752
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/secure.h
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+#define CRED_DECL	extern AUTH_DAT kdata;
+#define SESSION		&kdata.session
+#define myaddr		data_source
+#define hisaddr		data_dest
+
+int secure_flush (int);
+int secure_putc (int, FILE *);
+int secure_getc (FILE *);
+int secure_write (int, unsigned char *, unsigned int);
+int secure_read (int, char *, unsigned int);
+void secure_gss_error (OM_uint32 maj_stat, OM_uint32 min_stat, char *s);
+
+#if defined(STDARG) || (defined(__STDC__) && ! defined(VARARGS)) || defined(HAVE_STDARG_H)
+void secure_error(char *, ...);
+#else
+void secure_error();
+#endif
diff --git a/krb5-1-6/src/appl/gssftp/ftpd/vers.c b/krb5-1-6/src/appl/gssftp/ftpd/vers.c
new file mode 100644
index 000000000..76846bda7
--- /dev/null
+++ b/krb5-1-6/src/appl/gssftp/ftpd/vers.c
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)vers.c	5.1 (Berkeley) 6/24/90";
+#endif /* not lint */
+
+char version[] = "Version 5.60";
diff --git a/krb5-1-6/src/appl/libpty/Makefile.in b/krb5-1-6/src/appl/libpty/Makefile.in
new file mode 100644
index 000000000..521341db0
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/Makefile.in
@@ -0,0 +1,157 @@
+thisconfigdir=.
+myfulldir=appl/libpty
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+RELDIR=../appl/libpty
+
+SED = sed
+
+KRB5_RUN_ENV= @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+LIBBASE=pty
+LIBMAJOR=1
+LIBMINOR=2
+
+STLIBOBJS= cleanup.o getpty.o init_slave.o open_ctty.o open_slave.o \
+	update_utmp.o update_wtmp.o vhangup.o void_assoc.o pty_err.o \
+	logwtmp.o init.o sane_hostname.o
+
+STOBJLISTS=OBJS.ST
+
+INSTALLFILE = cp
+
+# for pty-int.h
+LOCALINCLUDES=-I. -I$(srcdir)
+
+FILES= Makefile cleanup.c getpty.c init_slave.c open_ctty.c open_slave.c update_utmp.c update_wtmp.c vhangup.c void_assoc.c pty_err.h pty_err.c\
+logwtmp.c init.c
+
+CFILES=$(srcdir)/cleanup.c $(srcdir)/getpty.c $(srcdir)/init_slave.c \
+	$(srcdir)/open_ctty.c $(srcdir)/open_slave.c \
+	$(srcdir)/update_utmp.c $(srcdir)/update_wtmp.c $(srcdir)/vhangup.c \
+	$(srcdir)/void_assoc.c $(srcdir)/logwtmp.c \
+	$(srcdir)/init.c $(srcdir)/sane_hostname.c
+
+
+SRCS=pty_err.c $(CFILES)
+SHLIB_EXPDEPS = \
+	$(COM_ERR_DEPLIB)
+SHLIB_EXPLIBS= -lcom_err 
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+DEPLIBS=
+
+#
+all-unix:: includes pty_err.h
+
+all-unix:: all-liblinks
+
+dump-utmp: dump-utmp.o
+	$(CC) $(LDFLAGS) -o dump-utmp dump-utmp.o
+dump-utmp.o: dump-utmp.c
+
+pty_paranoia: pty_paranoia.o $(COM_ERR_DEPLIB) $(PTY_DEPLIB)
+	$(CC_LINK) -o pty_paranoia pty_paranoia.o $(PTY_LIB) $(COM_ERR_LIB) $(LIBS)
+
+check-paranoia: pty_paranoia
+	$(KRB5_RUN_ENV) $(VALGRIND) ./pty_paranoia
+
+install-unix:: install-libs
+
+clean-unix::
+	$(RM) libpty.a $(BUILDTOP)/include/libpty.h pty_err.c pty_err.h
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+depend::  pty_err.h
+
+#install:: libpty.h
+#	$(INSTALL_DATA) $(srcdir)/libpty.h  $(DESTDIR)$(KRB5_INCDIR)/libpty.h
+
+includes:: libpty.h
+	if cmp $(srcdir)/libpty.h \
+	$(BUILDTOP)/include/libpty.h >/dev/null 2>&1; then :; \
+	else \
+		(set -x; $(RM) $(BUILDTOP)/include/libpty.h; \
+		 $(CP) $(srcdir)/libpty.h \
+			$(BUILDTOP)/include/libpty.h) ; \
+	fi
+
+includes:: $(BUILDTOP)/include/autoconf.h
+
+clean-unix::
+	$(RM) $(BUILDTOP)/include/libpty.h
+
+
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs clean-files
+
+clean-files::
+	rm -f *~ \#* *.bak \
+		*.otl *.aux *.toc *.PS *.dvi *.x9700 *.ps \
+		*.cp *.fn *.ky *.log *.pg *.tp *.vr \
+		*.o profiled/?*.o libcom_err.a libcom_err_p.a \
+		com_err.o compile_et \
+		et.ar TAGS y.tab.c lex.yy.c error_table.c \
+		et_lex.lex.c \
+		test1.h test1.c test2.h test2.c test_et \
+		eddep makedep *.ln
+
+pty_err.o: pty_err.c
+pty_err.h: pty_err.et
+pty_err.c: pty_err.et
+
+$(BUILDTOP)/include/autoconf.h: $(SRCTOP)/include/autoconf.h.in
+	(cd $(BUILDTOP)/include; $(MAKE) autoconf.h)
+
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+pty_err.so pty_err.po $(OUTPRE)pty_err.$(OBJEXT): $(COM_ERR_DEPS) \
+  pty_err.c
+cleanup.so cleanup.po $(OUTPRE)cleanup.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h cleanup.c \
+  libpty.h pty-int.h pty_err.h
+getpty.so getpty.po $(OUTPRE)getpty.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h getpty.c \
+  libpty.h pty-int.h pty_err.h
+init_slave.so init_slave.po $(OUTPRE)init_slave.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h \
+  init_slave.c libpty.h pty-int.h pty_err.h
+open_ctty.so open_ctty.po $(OUTPRE)open_ctty.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h \
+  libpty.h open_ctty.c pty-int.h pty_err.h
+open_slave.so open_slave.po $(OUTPRE)open_slave.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h \
+  libpty.h open_slave.c pty-int.h pty_err.h
+update_utmp.so update_utmp.po $(OUTPRE)update_utmp.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h \
+  libpty.h pty-int.h pty_err.h update_utmp.c
+update_wtmp.so update_wtmp.po $(OUTPRE)update_wtmp.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h \
+  libpty.h pty-int.h pty_err.h update_wtmp.c
+vhangup.so vhangup.po $(OUTPRE)vhangup.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h libpty.h \
+  pty-int.h pty_err.h vhangup.c
+void_assoc.so void_assoc.po $(OUTPRE)void_assoc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h \
+  libpty.h pty-int.h pty_err.h void_assoc.c
+logwtmp.so logwtmp.po $(OUTPRE)logwtmp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h libpty.h \
+  logwtmp.c pty-int.h pty_err.h
+init.so init.po $(OUTPRE)init.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h init.c \
+  libpty.h pty-int.h pty_err.h
+sane_hostname.so sane_hostname.po $(OUTPRE)sane_hostname.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  libpty.h pty-int.h pty_err.h sane_hostname.c
diff --git a/krb5-1-6/src/appl/libpty/README b/krb5-1-6/src/appl/libpty/README
new file mode 100644
index 000000000..f10dd2b37
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/README
@@ -0,0 +1,108 @@
+	This file is to serve as documentation and usage notes on
+libpty until
+more formal docs are written.  By that point, it will probably
+describe how pty can be broken out of the Kerberos distribution.
+
+void pty_init(void);
+
+	 Initialize error tables.
+
+
+long pty_getpty ( int *fd, char *slave, int slavelength);
+	Find and initialize a clean master pty.  This should open the
+pty as fd, and return the name of the slave.  It should return 0 or an
+error code.  The slavelength parameter should include the maximum
+length allocated for a slave name.  The slave may not be initialized, although any
+
+operating-system specific initialization (for example, unlockpt and
+grantpt) may be performed.
+
+long pty_open_slave (/*in */ char * slave, /* out*/ int *fd)
+
+	Initialize the slave side by dissociating the current terminal
+and by setting process groups, etc.  In addition, it will initialize
+the terminal flags (termios or old BSD) appropriately; the application
+may have to do additional customization, but this should sanitize
+things.  In addition, the pty will be opened securely, and will become
+the controlling terminal.  This procedure will fail unless the process
+is running as root.  Ideally, pty_open_slave will be called in a child
+process of the process that called pty_getpty.  If an operating system
+implements setsid() per the POSIX spec, but does not implement
+TIOCNOTTY, this procedure will not be able to insure that the
+controlling terminal is established if it is called in the parent
+process.  Unfortunately, the parent process must not write to the pty
+until the slave side is opened.  Also, the parent process should not
+open the slave side through other means unless it is prepared to have
+that file descriptor subjected to a vhangup() or revoke() when
+pty_open_slave is called in the child.  So, ideally, the parent calls
+pty_getpty, forks, waits for the slave to call pty_open_slave, then
+continues.  Since this synchronization may be difficult to build in to
+existing programs, pty_open_slave makes an effort to function if
+called in the parent under operating systems where this is possible.
+Currently, I haven't found any operating systems where this isn't
+possible.  Also note that pty_open_slave will succeed only once per process.
+
+long pty_open_ctty(int *fd, char *line)
+
+	Attempt to disassociate the current process from its controlling terminal and open line as a new controlling terminal.  No assumption about line being the slave side of a pty is made.
+
+long pty_initialize_slave (int fd)
+
+	Perform the non-security related initializations on the slave
+side of a pty.  For example, push the appropriate streams, set termios
+structures, etc.  This is included in pty_open_slave.  I am interested
+in any suggestions on how to pass information on the state to which
+the application wants the terminal initialized.  For example, rlogind
+wants a transparent channel, while other programs likely want cooked
+mode.  I can't take a termios structure because I may be on a
+non-termios system.  Currently, I push the streams, do a bit of
+cleanup, but don't really modify the terminal that much. Another
+possible goal for this function would be to do enough initialization
+that the slave side of the pty can be treated simply as a tty instead
+of a pty after this call.
+
+
+long pty_update_utmp ( int process_type, int pid, char *user, char
+*line, char *host, int flags)
+
+	Update the utmp information or return an error.The
+process_type is one of the magic types defined in libpty.h.  The flags
+are logical combinations of one of the following:
+
+    		PTY_TTYSLOT_USABLE: The tty pointed to by the line
+		  parameter is the first tty that would be found by
+		  searching stdin then stdout.  In other words,
+		  ttyslot() would return the right slot in utmp on
+		  systems where ttyslot() is cannonically used.  Note
+		  that for inserting utmp entries for new logins, it
+		  is not always possible to find the right place if
+		  this flag is not given. Thus, for programs like
+		  telnetd that set up utmp entries, it is important to
+		  be able to set this flag on the initial utmp update.
+		  It is expected that this flag may be cleared on
+		  update_utmp calls to remove utmp entries.
+
+		PTY_UTMP_USERNAME_VALID: the username field in the
+		  utmp entry associated with this line contains the
+		  user who (is/was) associated with the line.
+		  Regardless of this flag, the utmp file will contain
+		  the username specified after this call.  However, if
+		  a username is needed by the system for wtmp logout
+		  (Solaris 2.1 for example), then the system can fetch
+		  the user from the utmp record before doing the wtmp
+		  update.  This will only be attempted if the username
+		  is a null pointer.  
+
+long pty_cleanup(char *slave, pid_t pid, int update_wtmp)
+
+	Clean up after the slave application has exited.  Close down
+the pty, HUPing processes associated with it.  (pid is the pid of the
+slave process that may have died, slave is the name of the slave
+terminal.)  PID is allowed to be zero if unknown; this may disable
+some cleanup operations.  This routine may fork on some systems.  As
+such, SIGCHLD may be generated and blocked for some time during the
+routine.  In addition, on systems without waitpid() or wait4(), wait()
+may be called.
+
+
+    
diff --git a/krb5-1-6/src/appl/libpty/cleanup.c b/krb5-1-6/src/appl/libpty/cleanup.c
new file mode 100644
index 000000000..57cc796ac
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/cleanup.c
@@ -0,0 +1,112 @@
+/*
+ * pty_cleanup: Kill processes associated with pty.
+ *
+ * (C)Copyright 1995, 1996 by the Massachusetts Institute of Technology.
+ *
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+long pty_cleanup (char *slave,
+		  /* May be zero for unknown.  */
+		  int pid,
+		  int update_utmp)
+{
+#ifdef VHANG_LAST
+    int retval, fd;
+#endif
+    
+    if (update_utmp)
+	pty_update_utmp(PTY_DEAD_PROCESS, pid,  "", slave, (char *)0, PTY_UTMP_USERNAME_VALID);
+    
+    (void)chmod(slave, 0666);
+    (void)chown(slave, 0, 0);
+#ifdef HAVE_REVOKE
+    revoke(slave);
+    /*
+     * Revoke isn't guaranteed to send a SIGHUP to the processes it
+     * dissociates from the terminal.  The best solution without a Posix
+     * mechanism for forcing a hangup is to killpg() the process
+     * group of the pty.  This will at least kill the shell and
+     * hopefully, the child processes.  This is not always the case, however.
+     * If the shell puts each job in a process group and doesn't pass
+     * along SIGHUP, all processes may not die.
+     */
+    if ( pid > 0 ) {
+#ifdef HAVE_KILLPG
+	killpg(pid, SIGHUP);
+#else
+	kill( -(pid), SIGHUP );
+#endif /*HAVE_KILLPG*/
+    }
+#else /* HAVE_REVOKE*/
+#ifdef VHANG_LAST
+    {
+      int status;
+#ifdef POSIX_SIGNALS
+      sigset_t old, new;
+      sigemptyset(&new);
+      sigaddset(&new, SIGCHLD);
+      sigprocmask ( SIG_BLOCK, &new, &old);
+#else /*POSIX_SIGNALS*/
+      int mask = sigblock(sigmask(SIGCHLD));
+#endif /*POSIX_SIGNALS*/
+      switch (retval = fork()) {
+      case -1:
+#ifdef POSIX_SIGNALS
+	sigprocmask(SIG_SETMASK, &old, 0);
+#else /*POSIX_SIGNALS*/
+	sigsetmask(mask);
+#endif /*POSIX_SIGNALS*/
+	return errno;
+      case 0:
+	ptyint_void_association();
+	if ((retval = pty_open_ctty(slave, &fd)))
+	  exit(retval);
+	ptyint_vhangup();
+	exit(0);
+	break;
+      default:
+#ifdef HAVE_WAITPID
+	waitpid(retval, &status, 0);
+#else /*HAVE_WAITPID*/
+	wait(&status);
+#endif
+#ifdef POSIX_SIGNALS
+	sigprocmask(SIG_SETMASK, &old, 0);
+#else /*POSIX_SIGNALS*/
+	sigsetmask(mask);
+#endif /*POSIX_SIGNALS*/
+
+	break;
+      }
+    }
+#endif /*VHANG_LAST*/
+#endif /* HAVE_REVOKE*/
+#ifndef HAVE_STREAMS
+    slave[strlen("/dev/")] = 'p';
+    (void)chmod(slave, 0666);
+    (void)chown(slave, 0, 0);
+#endif
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/libpty/configure.in b/krb5-1-6/src/appl/libpty/configure.in
new file mode 100644
index 000000000..cb5fe7e71
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/configure.in
@@ -0,0 +1,263 @@
+K5_AC_INIT(getpty.c)
+CONFIG_RULES
+AC_PROG_AWK
+AC_CHECK_FUNCS(fchmod fchown revoke vhangup killpg _getpty)
+dnl
+LOGINLIBS=
+dnl
+dnl Make our operating system-specific security checks and definitions for
+dnl login.
+dnl  In addition, the following code decides what streams modules will
+dnl be pushed onto a pty.In particular, if HAVE_STREAMS is defined and
+dnl HAVE_LINE_PUSH is not defined, modules may be pushed by inserting
+dnl An appropriate generic ifdef for each module in init_slave.c and
+dnl  AC_DEFINES for the operating systems that need the modules.
+dnl  Each OS that supports streams has a different idea of what you want to
+dnl push.
+dnl
+case $krb5_cv_host in
+*-*-ultrix*)
+echo "Disabling initial vhangup and setsid because they break under Ultrix..."
+AC_DEFINE([OPEN_CTTY_ONLY_ONCE],[1],[Define on Ultrix where an initial vhangup breaks])
+ac_cv_func_setsid=no # setsid doesn't do the right thing under Ultrix even though present
+;;
+
+*-*-aix3*) # AIX has streams include files but not streams TTY
+# Moreover, strops.h trashes sys/ioctl.h
+krb5_cv_has_streams=no
+;;
+alpha*-dec-osf*)
+	AC_MSG_RESULT(will open ctty prior to revoke due to OSF/1 lossage)
+	AC_DEFINE(REVOKE_NEEDS_OPEN,1,[Define if ctty needs to be opened before revoke as on OSF/1])
+	;;
+*-*-solaris*)
+     AC_DEFINE(PUSH_PTEM,1,[push ptem?])
+     AC_DEFINE(PUSH_LDTERM,1,[push ldterm?])
+     AC_DEFINE(PUSH_TTCOMPAT,1,[push ttcompat?])
+     ;;
+*-*-hpux*)
+     krb5_cv_has_streams=no
+     ;;
+esac
+dnl
+AC_CHECK_LIB(util,openpty, [AC_DEFINE(HAVE_OPENPTY,1,[Define if openpty is provided in util library]) LIBS="$LIBS -lutil"])
+AC_TYPE_MODE_T
+AC_CHECK_TYPE(time_t, long)
+AC_CHECK_FUNCS(setreuid gettosbyname setsid ttyname line_push ptsname grantpt openpty)
+AC_CHECK_HEADERS(unistd.h stdlib.h string.h libutil.h pty.h sys/filio.h sys/sockio.h sys/label.h sys/tty.h sys/wait.h ttyent.h lastlog.h sys/select.h util.h sys/stream.h)
+AC_CHECK_FUNCS(waitpid)
+CHECK_SIGNALS
+AC_CHECK_HEADER(termios.h,[AC_CHECK_FUNC(cfsetispeed,AC_DEFINE(POSIX_TERMIOS,1,[Define for POSIX termios interface]))])
+
+AC_CHECK_HEADER(sys/ptyvar.h, [], [],
+[#if HAVE_SYS_STREAM_H
+#include <sys/stream.h>
+#endif
+#if HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif])
+
+######################################################################
+#
+# utmp related hair here.  There's lots of it.
+#
+
+AC_CHECK_HEADERS(utmp.h utmpx.h)
+AC_CHECK_FUNCS(setutent setutxent setutsent updwtmp updwtmpx logwtmp getutmp getutmpx)
+AC_CHECK_FUNCS(utmpname utmpxname)
+
+AC_DEFUN(K5_CHECK_UT_MEMBER,
+[AC_MSG_CHECKING([for $2 in struct $1])
+AC_CACHE_VAL([krb5_cv_struct_$1_$2],
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <$1.h>], [struct $1 u; u.$2;],
+eval "krb5_cv_struct_$1_$2=yes", eval "krb5_cv_struct_$1_$2=no")])
+if eval "test \"`echo '$krb5_cv_struct_'$1'_'$2`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  krb5_tr_ut=HAVE_STRUCT_`echo $1'_'$2 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  AC_DEFINE_UNQUOTED($krb5_tr_ut,1,[Define if $2 field present in $1])
+else
+  AC_MSG_RESULT(no)
+fi])
+
+if test "$ac_cv_header_utmp_h" = yes; then
+  AC_MSG_RESULT(checking struct utmp members)
+  for krb5_mem in ut_host ut_syslen ut_addr ut_id ut_pid ut_type ut_exit; do
+    K5_CHECK_UT_MEMBER(utmp, $krb5_mem)
+  done
+fi
+
+if test "$ac_cv_header_utmpx_h" = yes; then
+  AC_MSG_RESULT(checking struct utmpx members)
+  for krb5_mem in ut_host ut_syslen ut_addr ut_id ut_pid ut_type ut_exit; do
+    K5_CHECK_UT_MEMBER(utmpx, $krb5_mem)
+  done
+fi
+
+AC_DEFUN(K5_CHECK_UT_EXIT_MEMBER,
+[AC_MSG_CHECKING([for ut_exit.$2 in struct $1])
+AC_CACHE_VAL([krb5_cv_struct_$1_ut_exit_$2],
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <$1.h>], [struct $1 u; u.ut_exit.$2;],
+eval "krb5_cv_struct_$1_ut_exit_$2=yes",
+eval "krb5_cv_struct_$1_ut_exit_$2=no")])
+if eval "test \"`echo '$krb5_cv_struct_'$1'_ut_exit_'$2`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  ifelse([$3], , :, [$3])
+else
+  AC_MSG_RESULT(no)
+  ifelse([$4], , :, [$4])
+fi])
+
+if test "$krb5_cv_struct_utmp_ut_exit" = yes; then
+  AC_MSG_RESULT(checking for working ut_exit.e_exit in struct utmp)
+  for krb5_mem in __e_exit ut_e_exit ut_exit e_exit; do
+    K5_CHECK_UT_EXIT_MEMBER(utmp, $krb5_mem,
+[krb5_utmp_e_exit=$krb5_mem
+krb5_utmp_e_termination=`echo $krb5_mem|sed -e 's%_exit$%_termination%'`], )
+  done
+  if test "${krb5_utmp_e_exit+set}" = set; then
+    AC_MSG_RESULT([working ut_exit.e_exit in utmp is $krb5_utmp_e_exit])
+    AC_DEFINE_UNQUOTED(PTY_UTMP_E_EXIT, $krb5_utmp_e_exit,[Define to utmp exit field name])
+    AC_DEFINE_UNQUOTED(PTY_UTMP_E_TERMINATION, $krb5_utmp_e_termination,[Define to utmp termination field name])
+  else
+    AC_MSG_RESULT([cannot find working ut_exit.e_exit in utmp])
+  fi
+fi
+
+if test "$krb5_cv_struct_utmpx_ut_exit" = yes; then
+  AC_MSG_RESULT(checking for working ut_exit.e_exit in struct utmpx)
+  for krb5_mem in __e_exit ut_e_exit ut_exit e_exit; do
+    K5_CHECK_UT_EXIT_MEMBER(utmpx, $krb5_mem,
+[krb5_utmpx_e_exit=$krb5_mem
+krb5_utmpx_e_termination=`echo $krb5_mem|sed -e 's%_exit$%_termination%'`], )
+  done
+  if test "${krb5_utmpx_e_exit+set}" = set; then
+    AC_MSG_RESULT([working ut_exit.e_exit in utmpx is $krb5_utmpx_e_exit])
+    AC_DEFINE_UNQUOTED(PTY_UTMPX_E_EXIT, $krb5_utmpx_e_exit,[Define to utmpx exit field name])
+    AC_DEFINE_UNQUOTED(PTY_UTMPX_E_TERMINATION, $krb5_utmpx_e_termination,[Define to utmpx termination field name])
+  else
+    AC_MSG_RESULT([cannot find working ut_exit.e_exit in utmpx])
+  fi
+fi
+
+if test "$ac_cv_header_utmpx_h" = yes; then
+  AC_MSG_CHECKING(consistency of utmpx API)
+  if test "$ac_cv_func_setutxent" = yes; then
+    if test "$krb5_cv_struct_utmpx_ut_id" = yes \
+      && test "$krb5_cv_struct_utmpx_ut_type" = yes \
+      && test "$krb5_cv_struct_utmpx_ut_pid" = yes; then
+      AC_MSG_RESULT(ok)
+    else
+      AC_MSG_RESULT(not ok)
+      AC_MSG_ERROR([have setutxent but no ut_id, ut_type, or ut_pid in utmpx])
+    fi
+  else
+    AC_MSG_RESULT(not ok)
+    AC_MSG_ERROR([have utmpx.h but no setutxent])
+  fi
+fi
+
+if test "$ac_cv_func_setutent" = yes && \
+  test "$ac_cv_header_utmpx_h" = no; then
+  AC_MSG_CHECKING(consistency of sysV-ish utmp API)
+  if test "$ac_cv_header_utmp_h" = yes; then
+    if test "$krb5_cv_struct_utmp_ut_id" = yes \
+      && test "$krb5_cv_struct_utmp_ut_type" = yes \
+      && test "$krb5_cv_struct_utmp_ut_pid" = yes; then
+      AC_MSG_RESULT(ok)
+    else
+      AC_MSG_RESULT(not ok)
+      AC_MSG_ERROR([have setutent but no ut_id, ut_type, or ut_pid in utmp])
+    fi
+  else
+    AC_MSG_RESULT(not ok)
+    AC_MSG_ERROR([have setutent but no utmp.h])
+  fi
+fi
+
+#
+# end of utmp-related hair
+#
+######################################################################
+dnl
+KRB5_NEED_PROTO([#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+],getutmp)
+dnl
+#########################################
+KRB5_NEED_PROTO([#include <sys/types.h>
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+],logwtmp)
+########################################
+KRB5_NEED_PROTO([#include <unistd.h>
+],revoke)
+########################################
+dnl
+AC_MSG_CHECKING([streams interface])
+AC_CACHE_VAL(krb5_cv_has_streams,
+[AC_TRY_COMPILE(
+[#include <sys/stream.h>
+#include <sys/stropts.h>], [],
+krb5_cv_has_streams=yes, krb5_cv_has_streams=no)])
+AC_MSG_RESULT($krb5_cv_has_streams)
+if test $krb5_cv_has_streams = yes; then
+AC_DEFINE(HAVE_STREAMS,1,[Define if have streams])
+fi
+dnl
+dnl
+dnl
+AC_MSG_CHECKING([arguments to getpgrp])
+AC_CACHE_VAL(krb5_cv_getpgrp_args,
+[AC_TRY_COMPILE(
+[#ifndef __STDC__
+#define __STDC__ 1
+#endif
+#include <unistd.h>
+#include <sys/types.h>], [pid_t pid = getpgrp(getpid())],
+krb5_cv_getpgrp_args=pid, krb5_cv_getpgrp_args=void)])
+AC_MSG_RESULT($krb5_cv_getpgrp_args)
+if test $krb5_cv_getpgrp_args = pid; then
+AC_DEFINE(GETPGRP_ONEARG,1,[Define if getpgrp takes one arg])
+fi
+dnl
+dnl
+AC_MSG_CHECKING([number of arguments to setpgrp])
+AC_CACHE_VAL(krb5_cv_setpgrp_args,
+[AC_TRY_COMPILE(
+[#ifndef __STDC__
+#define __STDC__ 1
+#endif
+#include <unistd.h>],[setpgrp(0,0)],
+krb5_cv_setpgrp_args=two, krb5_cv_setpgrp_args=void)])
+AC_MSG_RESULT($krb5_cv_setpgrp_args)
+if test $krb5_cv_setpgrp_args = two; then
+AC_DEFINE(SETPGRP_TWOARG,1,[Define if setpgrp takes two args])
+fi
+dnl
+KRB5_AC_INET6
+AC_C_CONST
+dnl KRB5_BUILD_LIBRARY_WITH_DEPS
+KRB5_BUILD_LIBRARY_STATIC
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_PROGRAM
+KRB5_RUN_FLAGS
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/appl/libpty/dump-utmp.c b/krb5-1-6/src/appl/libpty/dump-utmp.c
new file mode 100644
index 000000000..d4c303fb3
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/dump-utmp.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ *
+ * dump-utmp.c: dump utmp and utmpx format files for debugging purposes.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef UTMPX
+#ifdef HAVE_UTMPX_H
+#define UTMPX
+#endif
+#endif
+
+#if defined(HAVE_UTMPNAME) || defined(HAVE_UTMPXNAME)
+#define UTN			/* we can set utmp or utmpx for getut*() */
+#endif
+
+#ifdef UTMPX
+#include <utmpx.h>
+void print_utx(int, const struct utmpx *);
+#endif
+#include <utmp.h>
+
+void print_ut(int, const struct utmp *);
+
+void usage(const char *);
+
+#if defined (HAVE_STRUCT_UTMP_UT_TYPE) || defined (UTMPX)
+char *ut_typename(int);
+
+char *
+ut_typename(int t) {
+    switch (t) {
+#define S(N) case N : return #N
+#define S2(N,N2) case N : return #N2
+	S(EMPTY);
+	S(RUN_LVL);
+	S(BOOT_TIME);
+	S(OLD_TIME);
+	S(NEW_TIME);
+	S2(INIT_PROCESS,INIT);
+	S2(LOGIN_PROCESS,LOGIN);
+	S2(USER_PROCESS,USER);
+	S2(DEAD_PROCESS,DEAD);
+	S(ACCOUNTING);
+    default: return "??";
+    }
+}
+#endif
+
+#define S2D(x) (sizeof(x) * 2.4 + 1.5)
+
+void
+print_ut(int all, const struct utmp *u)
+{
+    int lu, ll;
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+    int lid;
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+    int lpid;
+#endif
+#ifdef PTY_UTMP_E_EXIT
+    int let, lee;
+#endif
+
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+    if (!all && ((u->ut_type == EMPTY) || (u->ut_type == DEAD_PROCESS)))
+	return;
+#endif
+
+    lu = sizeof(u->ut_name);
+    ll = sizeof(u->ut_line);
+    printf("%-*.*s:", lu, lu, u->ut_name);
+    printf("%-*.*s:", ll, ll, u->ut_line);
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+    lid = sizeof(u->ut_id);
+    printf("%-*.*s:", lid, lid, u->ut_id);
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+    lpid = S2D(u->ut_pid);
+    printf("%*ld", lpid, (long)u->ut_pid);
+#endif
+#ifdef PTY_UTMP_E_EXIT
+    let = S2D(u->ut_exit.PTY_UTMP_E_TERMINATION);
+    lee = S2D(u->ut_exit.PTY_UTMP_E_EXIT);
+    printf("(%*ld,", let, (long)u->ut_exit.PTY_UTMP_E_TERMINATION);
+    printf("%*ld)", lee, (long)u->ut_exit.PTY_UTMP_E_EXIT);
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+    printf(" %-9s", ut_typename(u->ut_type));
+#endif
+    printf(" %s", ctime(&u->ut_time) + 4);
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+    if (u->ut_host[0])
+	printf(" %.*s\n", (int) sizeof(u->ut_host), u->ut_host);
+#endif
+
+    return;
+}
+
+#ifdef UTMPX
+void
+print_utx(int all, const struct utmpx *u)
+{
+    int lu, ll, lid, lpid;
+#ifdef PTY_UTMPX_E_EXIT
+    int let, lee;
+#endif
+
+    if (!all && ((u->ut_type == EMPTY) || (u->ut_type == DEAD_PROCESS)))
+	return;
+
+    lu = sizeof(u->ut_user);
+    ll = sizeof(u->ut_line);
+    lid = sizeof(u->ut_id);
+    printf("%-*.*s:", lu, lu, u->ut_user);
+    printf("%-*.*s:", ll, ll, u->ut_line);
+    printf("%-*.*s", lid, lid, u->ut_id);
+    if (lu + ll + lid >= 60)
+	printf("\n");
+    else
+	printf(":");
+    lpid = S2D(u->ut_pid);
+    printf("%*ld", lpid, (long)u->ut_pid);
+#ifdef PTY_UTMPX_E_EXIT
+    let = S2D(u->ut_exit.PTY_UTMPX_E_TERMINATION);
+    lee = S2D(u->ut_exit.PTY_UTMPX_E_EXIT);
+    printf("(%*ld,", let, (long)u->ut_exit.PTY_UTMPX_E_TERMINATION);
+    printf("%*ld)", lee, (long)u->ut_exit.PTY_UTMPX_E_EXIT);
+#endif
+    printf(" %-9s", ut_typename(u->ut_type));
+    printf(" %s", ctime(&u->ut_tv.tv_sec) + 4);
+#ifdef HAVE_STRUCT_UTMPX_UT_HOST
+    if (u->ut_host[0])
+	printf(" %s\n", u->ut_host);
+#endif
+
+    return;
+}
+#endif
+
+#ifdef UTMPX
+#define OPTX "x"
+#else
+#define OPTX
+#endif
+#ifdef UTN
+#define OPTG "g"
+#else
+#define OPTG
+#endif
+#define OPTS "a" OPTX OPTG
+
+void
+usage(const char *prog)
+{
+    fprintf(stderr, "usage: %s [-" OPTS "] file\n", prog);
+    exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+    int c;
+    int all, is_utmpx, do_getut;
+    int f;
+    char *fn;
+    size_t recsize;
+    size_t nread;
+    union {
+	struct utmp ut;
+#ifdef UTMPX
+	struct utmpx utx;
+#endif
+    } u;
+
+    all = is_utmpx = do_getut = 0;
+    recsize = sizeof(struct utmp);
+
+    while ((c = getopt(argc, argv, OPTS)) != EOF) {
+	switch (c) {
+	case 'a':
+	    all = 1;
+	    break;
+#ifdef UTMPX
+	case 'x':
+	    is_utmpx = 1;
+	    recsize = sizeof(struct utmpx);
+	    break;
+#endif
+#ifdef UTN
+	case 'g':
+	    do_getut = 1;
+	    break;
+#endif
+	default:
+	    usage(argv[0]);
+	}
+    }
+    if (argc <= optind)
+	usage(argv[0]);
+    fn = argv[optind];
+    if (!do_getut) {
+	f = open(fn, O_RDONLY);
+	if (f == -1) {
+	    perror(fn);
+	    exit(1);
+	}
+	while ((nread = read(f, &u, recsize)) > 0) {
+	    if (nread < recsize) {
+		fprintf(stderr, "short read");
+		close(f);
+		exit(1);
+	    }
+	    if (is_utmpx) {
+#ifdef UTMPX
+		print_utx(all, &u.utx);
+#else
+		abort();
+#endif
+	    } else {
+		print_ut(all, &u.ut);
+	    }
+	}
+	if (nread == -1) {
+	    perror("read");
+	    exit(1);
+	}
+	close(f);
+    } else {
+	if (is_utmpx) {
+#ifdef UTMPX
+#ifdef HAVE_UTMPXNAME
+	    struct utmpx *utxp;
+	    utmpxname(fn);
+	    setutxent();
+	    while ((utxp = getutxent()) != NULL)
+		print_utx(all, utxp);
+#else
+	    fprintf(stderr, "no utmpxname(); can't use getutxent()\n");
+	    exit(1);
+#endif
+#else
+	    abort();
+#endif
+	} else {
+#ifdef HAVE_UTMPNAME
+	    struct utmp *utp;
+	    utmpname(fn);
+	    setutxent();
+	    while ((utp = getutent()) != NULL)
+		print_ut(all, utp);
+#else
+	    fprintf(stderr, "no utmpname(); can't use getutent()\n");
+	    exit(1);
+#endif
+	}
+    }
+    exit(0);    
+}
diff --git a/krb5-1-6/src/appl/libpty/getpty.c b/krb5-1-6/src/appl/libpty/getpty.c
new file mode 100644
index 000000000..610a471e6
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/getpty.c
@@ -0,0 +1,150 @@
+/*
+ * pty_getpty: open a PTY master.
+ *
+ * Copyright 1995, 1996 by the Massachusetts Institute of Technology.
+ *
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+long
+ptyint_getpty_ext(int *fd, char *slave, int slavelength, int do_grantpt)
+{
+#if !defined(HAVE__GETPTY) && !defined(HAVE_OPENPTY)
+    char *cp;
+    char *p;
+    int i,ptynum;
+    struct stat stb;
+    char slavebuf[1024];
+#endif
+
+#ifdef HAVE__GETPTY
+    char *slaveret; /*Temporary to hold pointer to slave*/
+#endif /*HAVE__GETPTY*/
+
+#ifdef HAVE_OPENPTY
+    int slavefd;
+
+    if(openpty(fd, &slavefd, slave, (struct termios *) 0,
+         (struct winsize *) 0)) return 1;
+    close(slavefd);
+    return 0;
+#else /*HAVE_OPENPTY*/
+#ifdef HAVE__GETPTY
+    /* This code is included for Irix; as of version 5.3, Irix has /dev/ptmx,
+     * but it fails to work properly; even after calling unlockpt,
+     * root gets permission denied opening the pty.
+     * The code to support _getpty should be removed if Irix gets working
+     * streams ptys in favor of maintaining the least needed code
+     * paths.
+     */
+    if ((slaveret = _getpty(fd, O_RDWR|O_NDELAY, 0600, 0)) == 0) {
+	*fd = -1;
+	return PTY_GETPTY_NOPTY;
+    }
+    if (strlen(slaveret) > slavelength - 1) {
+	close(*fd);
+	*fd = -1;
+	return PTY_GETPTY_SLAVE_TOOLONG;
+    }
+    else strcpy(slave, slaveret);
+    return 0;
+#else /*HAVE__GETPTY*/
+    
+    *fd = open("/dev/ptym/clone", O_RDWR|O_NDELAY);	/* HPUX*/
+#ifdef HAVE_STREAMS
+    if (*fd < 0) *fd = open("/dev/ptmx",O_RDWR|O_NDELAY); /*Solaris*/
+#endif
+    if (*fd < 0) *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */
+    if (*fd < 0) *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */
+
+    if (*fd >= 0) {
+
+#if defined(HAVE_GRANTPT)&&defined(HAVE_STREAMS)
+	if (do_grantpt)
+	    if (grantpt(*fd) || unlockpt(*fd)) return PTY_GETPTY_STREAMS;
+#endif
+    
+#ifdef HAVE_PTSNAME
+	p = ptsname(*fd);
+#else
+#ifdef	HAVE_TTYNAME
+	p = ttyname(*fd);
+#else
+	/* XXX If we don't have either what do we do */
+#endif
+#endif
+	if (p) {
+	    if (strlen(p) > slavelength - 1) {
+		    close (*fd);
+		    *fd = -1;
+		    return PTY_GETPTY_SLAVE_TOOLONG;
+	    }
+	    strcpy(slave, p);
+	    return 0;
+	}
+
+	if (fstat(*fd, &stb) < 0) {
+	    close(*fd);
+	    return PTY_GETPTY_FSTAT;
+	}
+	ptynum = (int)(stb.st_rdev&0xFF);
+	sprintf(slavebuf, "/dev/ttyp%x", ptynum);
+	if (strlen(slavebuf) > slavelength - 1) {
+	    close(*fd);
+	    *fd = -1;
+	    return PTY_GETPTY_SLAVE_TOOLONG;
+	}
+	strncpy(slave, slavebuf, slavelength);
+	return 0;
+    } else {
+    	for (cp = "pqrstuvwxyzPQRST";*cp; cp++) {
+	    sprintf(slavebuf,"/dev/ptyXX");
+	    slavebuf[sizeof("/dev/pty") - 1] = *cp;
+	    slavebuf[sizeof("/dev/ptyp") - 1] = '0';
+	    if (stat(slavebuf, &stb) < 0)
+		break;
+	    for (i = 0; i < 16; i++) {
+		slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
+		*fd = open(slavebuf, O_RDWR);
+		if (*fd < 0) continue;
+
+		/* got pty */
+		slavebuf[sizeof("/dev/") - 1] = 't';
+		if (strlen(slavebuf) > slavelength -1) {
+		    close(*fd);
+		    *fd = -1;
+		    return PTY_GETPTY_SLAVE_TOOLONG;
+		}
+		strncpy(slave, slavebuf, slavelength);
+		return 0;
+	    }
+	}
+	return PTY_GETPTY_NOPTY;
+    }
+#endif /*HAVE__GETPTY*/
+#endif /* HAVE_OPENPTY */
+}
+
+long
+pty_getpty(int *fd, char *slave, int slavelength)
+{
+    return ptyint_getpty_ext(fd, slave, slavelength, 1);
+}
diff --git a/krb5-1-6/src/appl/libpty/init.c b/krb5-1-6/src/appl/libpty/init.c
new file mode 100644
index 000000000..b48a1f8a7
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/init.c
@@ -0,0 +1,33 @@
+/*
+ * pty_init: Initialize internal state of pty.
+ * 
+ * Currently initializes error tables.
+ * 
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ *
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+long pty_init(void)
+{
+    initialize_pty_error_table();
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/libpty/init_slave.c b/krb5-1-6/src/appl/libpty/init_slave.c
new file mode 100644
index 000000000..ce7507645
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/init_slave.c
@@ -0,0 +1,100 @@
+/*
+ * pty_init_slave: open slave side of terminal, clearing for use.
+ *
+ * Copyright 1995, 1996 by the Massachusetts Institute of Technology.
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+/* * The following is an array of modules that should be pushed on the
+ *  stream.  See configure.in for caviats and notes about when this
+ *  array is used and not used.
+ */
+#if defined(HAVE_STREAMS)&&(!defined(HAVE_LINE_PUSH))
+static char *push_list[] = {
+#ifdef PUSH_PTEM
+  "ptem",
+#endif
+#ifdef PUSH_LDTERM
+  "ldterm",
+#endif
+#ifdef PUSH_TTCOMPAT
+"ttcompat",
+#endif
+  0};
+#endif /*HAVE_STREAMS but not HAVE_LINE_PUSH*/
+
+ 
+
+long pty_initialize_slave (int fd)
+{
+#if defined(POSIX_TERMIOS) && !defined(ultrix)
+    struct termios new_termio;
+#else
+    struct sgttyb b;
+#endif /* POSIX_TERMIOS */
+    int pid;
+	    
+#ifdef HAVE_STREAMS
+#ifdef HAVE_LINE_PUSH
+        while (ioctl (fd, I_POP, 0) == 0); /*Clear out any old lined's*/
+
+    if (line_push(fd) < 0)
+	{
+	    (void) close(fd); fd = -1;
+	    return PTY_OPEN_SLAVE_LINE_PUSHFAIL;
+	}
+#else /*No line_push */
+    {
+       char **module = &push_list[0];
+      while (*module)
+		if (ioctl(fd, I_PUSH, *(module++)) < 0)
+		  	return PTY_OPEN_SLAVE_PUSH_FAIL;
+    }
+
+#endif /*LINE_PUSH*/
+#endif /*HAVE_STREAMS*/
+
+    /*
+	 * Under Ultrix 3.0, the pgrp of the slave pty terminal
+	 * needs to be set explicitly.  Why rlogind works at all
+	 * without this on 4.3BSD is a mystery.
+	 */
+#ifdef GETPGRP_ONEARG
+    pid = getpgrp(getpid());
+#else
+    pid = getpgrp();
+#endif
+
+#ifdef TIOCSPGRP
+    ioctl(fd, TIOCSPGRP, &pid);
+#endif
+
+    
+#if defined(POSIX_TERMIOS) && !defined(ultrix)
+	tcsetpgrp(fd, pid);
+	tcgetattr(fd,&new_termio);
+	new_termio.c_cc[VMIN] = 1;
+	new_termio.c_cc[VTIME] = 0;
+    tcsetattr(fd,TCSANOW,&new_termio);
+#endif /* POSIX_TERMIOS */
+
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/libpty/libpty.h b/krb5-1-6/src/appl/libpty/libpty.h
new file mode 100644
index 000000000..d95c8fe08
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/libpty.h
@@ -0,0 +1,54 @@
+/*
+ * Header file for manipulation of ptys and utmp entries.
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ *
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#ifndef __LIBPTY_H__
+
+/* Constants for pty_update_utmp */
+#define PTY_LOGIN_PROCESS 0
+#define PTY_USER_PROCESS 1
+#define PTY_DEAD_PROCESS 2
+
+/* flags to update_utmp*/
+#define PTY_TTYSLOT_USABLE (0x1)
+#define PTY_UTMP_USERNAME_VALID (0x2)
+
+long pty_init(void);
+long pty_getpty ( int *fd, char *slave, int slavelength);
+
+long pty_open_slave (const char *slave, int *fd);
+long pty_open_ctty (const char *slave, int *fd);
+
+long pty_initialize_slave ( int fd);
+long pty_update_utmp(int process_type, int pid, const char *user,
+		     const char *tty_line, const char *host, int flags);
+
+long pty_logwtmp(const char *tty, const char *user, const char *host);
+
+long pty_cleanup(char *slave, int pid, int update_utmp);
+
+#ifndef SOCK_DGRAM
+struct sockaddr;
+#endif
+
+long pty_make_sane_hostname(const struct sockaddr *, int, int, int, char **);
+#define __LIBPTY_H__
+#endif
diff --git a/krb5-1-6/src/appl/libpty/logwtmp.c b/krb5-1-6/src/appl/libpty/logwtmp.c
new file mode 100644
index 000000000..21a35d3a9
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/logwtmp.c
@@ -0,0 +1,112 @@
+/*
+ * pty_logwtmp: Implement the logwtmp function if not present.
+ *
+ * Copyright 1995, 2001 by the Massachusetts Institute of Technology.
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+#if defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT)
+#ifdef HAVE_SETUTXENT
+#define PTY_STRUCT_UTMPX struct utmpx
+#else
+#define PTY_STRUCT_UTMPX struct utmp
+#endif
+
+#ifdef NEED_LOGWTMP_PROTO
+void logwtmp(const char *, const char *, const char *);
+#endif
+
+long
+pty_logwtmp(const char *tty, const char *user, const char *host)
+{
+#ifndef HAVE_LOGWTMP
+    PTY_STRUCT_UTMPX utx;
+    int loggingin;
+    size_t len;
+    const char *cp;
+    char utmp_id[5];
+#endif
+
+#ifdef HAVE_LOGWTMP
+    logwtmp(tty,user,host);
+    return 0;
+#else
+
+    loggingin = (user[0] != '\0');
+
+    memset(&utx, 0, sizeof(utx));
+    strncpy(utx.ut_line, tty, sizeof(utx.ut_line));
+    strncpy(utx.ut_user, user, sizeof(utx.ut_user));
+#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_HOST))	   \
+	|| (!defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_HOST))
+    strncpy(utx.ut_host, host, sizeof(utx.ut_host));
+    utx.ut_host[sizeof(utx.ut_host) - 1] = '\0';
+#endif
+#ifdef HAVE_SETUTXENT
+    gettimeofday(&utx.ut_tv, NULL);
+#else
+    (void)time(&utx.ut_time);
+#endif
+    utx.ut_pid = (loggingin ? getpid() : 0);
+    utx.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);
+
+    len = strlen(tty);
+    if (len >= 2)
+	cp = tty + len - 2;
+    else
+	cp = tty;
+    sprintf(utmp_id, "kr%s", cp);
+    strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id));
+
+#ifdef HAVE_SETUTXENT
+    return ptyint_update_wtmpx(&utx);
+#else
+    return ptyint_update_wtmp(&utx);
+#endif
+
+#endif /* !HAVE_LOGWTMP */
+}
+
+#else  /* !(defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT)) */
+
+long
+pty_logwtmp(const char *tty, const char *user, const char *host)
+{
+    struct utmp ut;
+
+#ifdef HAVE_LOGWTMP
+    logwtmp(tty,user,host);
+    return 0;
+#else
+
+    memset(&ut, 0, sizeof(ut));
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+    strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+    ut.ut_host[sizeof(ut.ut_host) - 1] = '\0';
+#endif
+    strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
+    strncpy(ut.ut_name, user, sizeof(ut.ut_name));
+    return ptyint_update_wtmp(&ut);
+
+#endif /* !HAVE_LOGWTMP */
+}
+
+#endif /* !(defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT)) */
diff --git a/krb5-1-6/src/appl/libpty/open_ctty.c b/krb5-1-6/src/appl/libpty/open_ctty.c
new file mode 100644
index 000000000..5a1730b31
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/open_ctty.c
@@ -0,0 +1,67 @@
+/*
+ * pty_open_ctty: Open and establish controlling terminal.
+ *
+ * Copyright 1995, 1996 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+/* 
+ * This function will be called twice.  The first time it will acquire
+ * a controlling terminal from which to vhangup() or revoke() (see
+ * comments in open_slave.c); the second time, it will be to open the
+ * actual slave device for use by the application.  We no longer call
+ * ptyint_void_association(), as that will be called in
+ * pty_open_slave() to avoid spurious calls to setsid(), etc.
+ *
+ * It is assumed that systems where vhangup() exists and does break
+ * the ctty association will allow the slave to be re-acquired as the
+ * ctty.  Also, if revoke() or vhangup() doesn't break the ctty
+ * association, we assume that we can successfully reopen the slave.
+ *
+ * This function doesn't check whether we actually acquired the ctty;
+ * we assume that the caller will check that, or that it doesn't
+ * matter in the particular case.
+ */
+long
+pty_open_ctty(const char *slave, int *fd)
+{
+
+#ifdef ultrix
+    /*
+     * The Ultrix (and other BSD tty drivers) require the process
+     * group to be zero, in order to acquire the new tty as a
+     * controlling tty.  This may actually belong in
+     * ptyint_void_association().
+     */
+    (void) setpgrp(0, 0);
+#endif
+    *fd = open(slave, O_RDWR);
+    if (*fd < 0)
+	return PTY_OPEN_SLAVE_OPENFAIL;
+#ifdef ultrix
+    setpgrp(0, getpid());
+#endif
+
+#ifdef TIOCSCTTY
+    ioctl(*fd, TIOCSCTTY, 0); /* Don't check return.*/
+#endif /* TIOCSTTY */
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/libpty/open_slave.c b/krb5-1-6/src/appl/libpty/open_slave.c
new file mode 100644
index 000000000..5bab6bc36
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/open_slave.c
@@ -0,0 +1,101 @@
+/*
+ * pty_open_slave: open slave side of terminal, clearing for use.
+ *
+ * Copyright 1995, 1996, 2001 by the Massachusetts Institute of
+ * Technology.
+ *
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+long
+pty_open_slave(const char *slave, int *fd)
+{
+    int tmpfd;
+    long retval;
+
+    /* Sanity check. */
+    if (slave == NULL || *slave == '\0')
+	return PTY_OPEN_SLAVE_TOOSHORT;
+
+    /* First, set up a new session and void old associations. */
+    ptyint_void_association();
+
+    /*
+     * Make a first attempt at acquiring the ctty under certain
+     * condisions.  This is necessary for several reasons:
+     *
+     * Under Irix, if you open a pty slave and then close it, a
+     * subsequent open of the slave will cause the master to read EOF.
+     * To prevent this, don't close the first fd until we do the real
+     * open following vhangup().
+     *
+     * Under Tru64 v5.0, if there isn't a fd open on the slave,
+     * revoke() fails with ENOTTY, curiously enough.
+     *
+     * Anyway, sshd seems to make a practice of doing this.
+     */
+#if defined(VHANG_FIRST) || defined(REVOKE_NEEDS_OPEN)
+    retval = pty_open_ctty(slave, fd);
+    if (retval)
+	return retval;
+    if (*fd < 0)
+	return PTY_OPEN_SLAVE_OPENFAIL;
+#endif
+
+    /* chmod and chown the slave. */
+    if (chmod(slave, 0))
+	return PTY_OPEN_SLAVE_CHMODFAIL;
+    if (chown(slave, 0, 0) == -1)
+	return PTY_OPEN_SLAVE_CHOWNFAIL;
+
+#ifdef HAVE_REVOKE
+    if (revoke(slave) < 0) {
+	return PTY_OPEN_SLAVE_REVOKEFAIL;
+    }
+#else /* !HAVE_REVOKE */
+#ifdef VHANG_FIRST
+    ptyint_vhangup();
+#endif
+#endif /* !HAVE_REVOKE */
+
+    /* Open the pty for real. */
+    retval = pty_open_ctty(slave, &tmpfd);
+#if defined(VHANG_FIRST) || defined(REVOKE_NEEDS_OPEN)
+    close(*fd);
+#endif
+    if (retval) {
+	*fd = -1;
+	return PTY_OPEN_SLAVE_OPENFAIL;
+    }
+    *fd = tmpfd;
+    retval = pty_initialize_slave(*fd);
+    if (retval)
+	return retval;
+    /* Make sure it's really our ctty. */
+    tmpfd = open("/dev/tty", O_RDWR|O_NDELAY);
+    if (tmpfd < 0) {
+	close(*fd);
+	*fd = -1;
+	return PTY_OPEN_SLAVE_NOCTTY;
+    }
+    close(tmpfd);
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/libpty/pty-int.h b/krb5-1-6/src/appl/libpty/pty-int.h
new file mode 100644
index 000000000..b94a65c0e
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/pty-int.h
@@ -0,0 +1,138 @@
+/* Includes needed by libpty*/
+#ifndef __PTY_INT_H__
+#include <pty_err.h>
+#include <sys/types.h>
+
+#if defined(_AIX) && defined(_THREAD_SAFE)
+/* On AIX 4.3.3, both utmp.h and utmpx.h will define struct utmp_data,
+   and they'll define them differently, if _THREAD_SAFE is defined.
+
+   We don't actually care about this library being thread-safe, but
+   for various reasons we do use both versions of the interface at the
+   moment.
+
+   So trick the system headers into not "helping" us in that area.
+
+   This is an ugly hack, and shouldn't be needed.  Bleah.  */
+# undef _THREAD_SAFE
+#endif
+
+#include "autoconf.h"
+
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef __SCO__
+#include <sys/unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pwd.h>
+     
+#ifdef HAVE_SYS_LABEL_H
+/* only SunOS 4? */
+#include <sys/label.h>
+#include <sys/audit.h>
+#include <pwdadj.h>
+#endif
+     
+#include <signal.h>
+
+#ifdef hpux
+#include <sys/ptyio.h>
+#endif
+#ifdef sysvimp
+#include <compat.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_STREAMS
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#endif
+
+#if defined(POSIX_TERMIOS) && !defined(ultrix)
+#include <termios.h>
+#else
+#include <sgtty.h>
+#endif
+     
+#include "port-sockets.h"
+#include <string.h>
+#include <sys/param.h>
+
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#ifdef HAVE_STREAMS
+/* krlogin doesn't test sys/tty... */
+#ifdef HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif
+
+
+
+#ifdef HAVE_SYS_PTYVAR_H
+/* Solaris actually uses packet mode, so the real macros are needed too */
+#include <sys/ptyvar.h>
+#endif
+#endif
+
+#if defined(HAVE_VHANGUP) && !defined(OPEN_CTTY_ONLY_ONCE) \
+	&& !defined(HAVE_REVOKE)
+/*
+ * Breaks under Ultrix and others where you cannot get controlling
+ * terminal twice.
+ */
+#define VHANG_FIRST
+#define VHANG_LAST
+#endif
+
+#if defined(NEED_GETUTMPX_PROTOTYPE)
+extern void getutmpx (const struct utmp *, struct utmpx *);
+#endif
+
+#if defined(NEED_REVOKE_PROTO)
+extern int revoke(const char *);
+#endif
+
+/* Internal functions */
+long ptyint_void_association(void);
+long ptyint_open_ctty (char *slave, int *fd);
+long ptyint_getpty_ext(int *, char *, int, int);
+#ifdef HAVE_SETUTXENT
+long ptyint_update_wtmpx(struct utmpx *utx);
+#endif
+#if !(defined(WTMPX_FILE) && defined(HAVE_UPDWTMPX)) \
+	|| !defined(HAVE_SETUXENT)
+long ptyint_update_wtmp(struct utmp *ut);
+#endif
+void ptyint_vhangup(void);
+
+#define __PTY_INT_H__
+#endif
diff --git a/krb5-1-6/src/appl/libpty/pty_err.et b/krb5-1-6/src/appl/libpty/pty_err.et
new file mode 100644
index 000000000..770cce7a9
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/pty_err.et
@@ -0,0 +1,50 @@
+#
+# util/pty/pty_err.et
+#
+# Copyright 1995 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# 
+# Permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+
+# libpty--pty handling error table
+
+error_table pty
+
+error_code PTY_GETPTY_STREAMS, "Failed to unlock or grant streams pty."
+
+error_code PTY_GETPTY_FSTAT, "fstat of master pty failed"
+
+error_code PTY_GETPTY_NOPTY, "All terminal ports in use"
+
+error_code PTY_GETPTY_SLAVE_TOOLONG, "buffer to hold slave pty name is too short"
+
+error_code PTY_OPEN_SLAVE_OPENFAIL, "Failed to open slave side of pty"
+error_code PTY_OPEN_SLAVE_CHMODFAIL, "Failed to chmod slave side of pty"
+
+error_code PTY_OPEN_SLAVE_NOCTTY, "Unable to set controlling terminal"
+error_code PTY_OPEN_SLAVE_CHOWNFAIL, "Failed to chown slave side of pty"
+error_code PTY_OPEN_SLAVE_LINE_PUSHFAIL, "Call to line_push failed to push streams on slave pty"
+
+error_code PTY_OPEN_SLAVE_PUSH_FAIL, "Failed to push stream on slave side of pty"
+
+
+error_code PTY_OPEN_SLAVE_REVOKEFAIL, "Failed to revoke slave side of pty"
+
+error_code PTY_UPDATE_UTMP_PROCTYPE_INVALID, "bad process type passed to pty_update_utmp"
+error_code PTY_OPEN_SLAVE_TOOSHORT, "Slave pty name is zero-length"
+
+end
diff --git a/krb5-1-6/src/appl/libpty/pty_paranoia.c b/krb5-1-6/src/appl/libpty/pty_paranoia.c
new file mode 100644
index 000000000..466a65888
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/pty_paranoia.c
@@ -0,0 +1,650 @@
+/*
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ */
+
+/*
+ * A rant on the nature of pseudo-terminals:
+ * -----------------------------------------
+ *
+ * Controlling terminals and job control:
+ *
+ * First, some explanation of job control and controlling terminals is
+ * necessary for background.  This discussion applies to hardwired
+ * terminals as well as ptys.  On most modern systems, all processes
+ * belong to a process group.  A process whose process group id (pgid)
+ * is the sames as its pid is the process group leader of its process
+ * group.  Process groups belong to sessions.  On a modern system, a
+ * process that is not currently a process group leader may create a
+ * new session by calling setsid(), which makes it a session leader as
+ * well as a process group leader, and also removes any existing
+ * controlling terminal (ctty) association.  Only a session leader may
+ * acquire a ctty.  It's not clear how systems that don't have
+ * setsid() handle ctty acquisition, though probably any process group
+ * leader that doesn't have a ctty may acquire one that way.
+ *
+ * A terminal that is a ctty has an associated foreground process
+ * group, which is a member of the terminal's associated session.
+ * This process group gets read/write access to the terminal and will
+ * receive terminal-generated signals (e.g. SIGINT, SIGTSTP).  Process
+ * groups belonging to the session but not in the foreground may get
+ * signals that suspend them if they try to read/write from the ctty,
+ * depending on various terminal settings.
+ *
+ * On many systems, the controlling process (the session leader
+ * associated with a ctty) exiting will cause the session to lose its
+ * ctty, even though some processes may continue to have open file
+ * descriptors on the former ctty.  It is possible for a process to
+ * have no file descriptors open on its controlling tty, but to
+ * reacquire such by opening /dev/tty, as long as its session still
+ * has a ctty.
+ *
+ * On ptys in general:
+ *
+ * Ptys have a slave side and a master side.  The slave side looks
+ * like a hardwired serial line to the application that opens it;
+ * usually, telnetd or rlogind, etc. opens the slave and hands it to
+ * the login program as stdin/stdout/stderr.  The master side usually
+ * gets the actual network traffic written to/from it.  Roughly, the
+ * master and slave are two ends of a bidirectional pair of FIFOs,
+ * though this can get complicated by other things.
+ *
+ * The master side of a pty is theoretically a single-open device.
+ * This MUST be true on systems that have BSD-style ptys, since there
+ * is usually no way to allocate an unused pty except by attempting to
+ * open all the master pty nodes in the system.
+ *
+ * Often, but not always, the last close of a slave device will cause
+ * the master to get an EOF.  Closing the master device will sometimes
+ * cause the foreground process group of the slave to get a SIGHUP,
+ * but that may depend on terminal settings.
+ *
+ * BSD ptys:
+ *
+ * On a BSD-derived system, the master nodes are named like
+ * /dev/ptyp0, and the slave nodes are named like /dev/ttyp0.  The
+ * last two characters are the variable ones, and a shell-glob type
+ * pattern for a slave device is usually of the form
+ * /dev/tty[p-z][0-9a-f], though variants are known to exist.
+ *
+ * System V cloning ptys:
+ *
+ * There is a cloning master device (usually /dev/ptmx, but the name
+ * can vary) that gets opened.  Each open of the cloning master
+ * results in an open file descriptor of a unique master device.  The
+ * application calls ptsname() to find the pathname to the slave node.
+ *
+ * In theory, the slave side of the pty is locked out until the
+ * process opening the master calls grantpt() to adjust permissions
+ * and unlockpt() to unlock the slave.  It turns out that Unix98
+ * doesn't require that the slave actually get locked out, or that
+ * unlockpt() actually do anything on such systems.  At least AIX
+ * allows the slave to be opened prior to calling unlockpt(), but most
+ * other SysV-ish systems seem to actually lock out the slave.
+ *
+ * Pty security:
+ *
+ * It's not guaranteed on a BSD-ish system that a slave can't be
+ * opened when the master isn't open.  It's even possible to acquire
+ * the slave as a ctty (!) if the open is done as non-blocking.  It's
+ * possible to open the master corresponding to an open slave, which
+ * creates some security issues: once this master is open, data
+ * written to the slave will actually pass to the master.
+ *
+ * On a SysV-ish system, the close of the master will invalidate any
+ * open file descriptors on the slave.
+ *
+ * In general, there are two functions that can be used to "clean" a
+ * pty slave, revoke() and vhangup().  revoke() will invalidate all
+ * file descriptors open on a particular pathname (often this only
+ * works on terminal devices), usually by invalidating the underlying
+ * vnode.  vhangup() will send a SIGHUP to the foreground process
+ * group of the control terminal.  On many systems, it also has
+ * revoke() semantics.
+ *
+ * If a process acquires a controlling terminal in order to perform a
+ * vhangup(), the reopen of the controlling terminal after the
+ * vhangup() call should be done prior to the close of the file
+ * descriptor used to initially acquire the controlling terminal,
+ * since that will likely prevent the process on the master side from
+ * reading a spurious EOF due to all file descriptors to the slave
+ * being closed.
+ *
+ * Known quirks of various OSes:
+ *
+ * AIX 4.3.3:
+ *
+ * If the environment variable XPG_SUS_ENV is not equal to "ON", then
+ * it's possible to open the slave prior to calling unlockpt().
+ */
+
+/*
+ * NOTE: this program will get reworked at some point to actually test
+ * passing of data between master and slave, and to do general cleanup.
+ *
+ * This is rather complex, so it bears some explanation.
+ *
+ * There are multiple child processes and a parent process.  These
+ * communicate via pipes (which we assume here to be unidirectional).
+ * The pipes are:
+ *
+ * pp1 - parent -> any children
+ *
+ * p1p - any children -> parent
+ *
+ * p21 - only child2 -> child1
+ *
+ * A parent process will acquire a pty master and slave via
+ * pty_getpty().  It will then fork a process, child1.  It then does a
+ * waitpid() for child1, and then writes to child2 via syncpipe pp1.
+ * It then reads from child3 via syncpipe p1p, then closes the
+ * master.  It writes to child3 via syncpipe pp1 to indicate that it
+ * has closed the master.  It then reads from child3 via syncpipe p1p
+ * and exits with a value appropriate to what it read from child3.
+ *
+ * child1 will acquire the slave as its ctty and fork child2; child1
+ * will exit once it reads from the syncpipe p21 from child2.
+ *
+ * child2 will set a signal handler for SIGHUP and then write to
+ * child1 via syncpipe p21 to indicate that child2 has set up the
+ * handler.  It will then read from the syncpipe pp1 from the parent
+ * to confirm that the parent has seen child1 exit, and then checks to
+ * see if it still has a ctty.  Under Unix98, and likely earlier
+ * System V derivatives, the exiting of the session leader associated
+ * with a ctty (in this case, child1) will cause the entire session to
+ * lose its ctty.
+ *
+ * child2 will then check to see if it can reopen the slave, and
+ * whether it has a ctty after reopening it.  This should fail on most
+ * systems.
+ *
+ * child2 will then fork child3 and immediately exit.
+ *
+ * child3 will write to the syncpipe p1p and read from the syncpipe
+ * pp1.  It will then check if it has a ctty and then attempt to
+ * reopen the slave.  This should fail.  It will then write to the
+ * parent via syncpipe p1p and exit.
+ *
+ * If this doesn't fail, child3 will attempt to write to the open
+ * slave fd.  This should fail unless a prior call to revoke(),
+ * etc. failed due to lack of permissions, e.g. NetBSD when running as
+ * non-root.
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+#include <sys/wait.h>
+#include <stdlib.h>
+
+char *prog;
+int masterfd, slavefd;
+char slave[64], slave2[64];
+pid_t pid1, pid2, pid3;
+int status1, status2;
+int pp1[2], p1p[2], p21[2];
+
+void handler(int);
+void rdsync(int, int *, const char *);
+void wrsync(int, int, const char *);
+void testctty(const char *);
+void testex(int, const char *);
+void testwr(int, const char *);
+void child1(void);
+void child2(void);
+void child3(void);
+
+void
+handler(int sig)
+{
+    printf("pid %ld got signal %d\n", (long)getpid(), sig);
+    fflush(stdout);
+    return;
+}
+
+void
+rdsync(int fd, int *status, const char *caller)
+{
+    int n;
+    char c;
+
+#if 0
+    printf("rdsync: %s: starting\n", caller);
+    fflush(stdout);
+#endif
+    while ((n = read(fd, &c, 1)) < 0) {
+	if (errno != EINTR) {
+	    fprintf(stderr, "rdsync: %s", caller);
+	    perror("");
+	    exit(1);
+	} else {
+	    printf("rdsync: %s: got EINTR; looping\n", caller);
+	    fflush(stdout);
+	}
+    }
+    if (!n) {
+	fprintf(stderr, "rdsync: %s: unexpected EOF\n", caller);
+	exit(1);
+    }
+    printf("rdsync: %s: got sync byte\n", caller);
+    fflush(stdout);
+    if (status != NULL)
+	*status = c;
+}
+
+void
+wrsync(int fd, int status, const char *caller)
+{
+    int n;
+    char c;
+
+    c = status;
+    while ((n = write(fd, &c, 1)) < 0) {
+	if (errno != EINTR) {
+	    fprintf(stderr, "wrsync: %s", caller);
+	    perror("");
+	    exit(1);
+	} else {
+	    printf("wrsync: %s: got EINTR; looping\n", caller);
+	    fflush(stdout);
+	}
+    }
+#if 0
+    printf("wrsync: %s: sent sync byte\n", caller);
+#endif
+    fflush(stdout);
+}
+
+void
+testctty(const char *caller)
+{
+    int fd;
+
+    fd = open("/dev/tty", O_RDWR|O_NONBLOCK);
+    if (fd < 0) {
+	printf("%s: no ctty\n", caller);
+    } else {
+	printf("%s: have ctty\n", caller);
+    }
+}
+
+void
+testex(int fd, const char *caller)
+{
+    fd_set rfds, xfds;
+    struct timeval timeout;
+    int n;
+    char c;
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+    FD_ZERO(&rfds);
+    FD_ZERO(&xfds);
+    FD_SET(fd, &rfds);
+    FD_SET(fd, &xfds);
+
+    n = select(fd + 1, &rfds, NULL, &xfds, &timeout);
+    if (n < 0) {
+	fprintf(stderr, "testex: %s: ", caller);
+	perror("select");
+    }
+    if (n) {
+	if (FD_ISSET(fd, &rfds) || FD_ISSET(fd, &xfds)) {
+	    n = read(fd, &c, 1);
+	    if (!n) {
+		printf("testex: %s: got EOF\n", caller);
+		fflush(stdout);
+		return;
+	    } else if (n == -1) {
+		printf("testex: %s: got errno=%ld (%s)\n",
+		       caller, (long)errno, strerror(errno));
+	    } else {
+		printf("testex: %s: read 1 byte!?\n", caller);
+	    }
+	}
+    } else {
+	printf("testex: %s: no exceptions or readable fds\n", caller);
+    }
+}
+
+void
+testwr(int fd, const char *caller)
+{
+    fd_set wfds;
+    struct timeval timeout;
+    int n;
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+    FD_ZERO(&wfds);
+    FD_SET(fd, &wfds);
+
+    n = select(fd + 1, NULL, &wfds, NULL, &timeout);
+    if (n < 0) {
+	fprintf(stderr, "testwr: %s: ", caller);
+	perror("select");
+    }
+    if (n) {
+	if (FD_ISSET(fd, &wfds)) {
+	    printf("testwr: %s: is writable\n", caller);
+	    fflush(stdout);
+	}
+    }
+}
+
+
+void
+child3(void)
+{
+    int n;
+
+    ptyint_void_association();
+    slavefd = open(slave, O_RDWR|O_NONBLOCK);
+    if (slavefd < 0) {
+	wrsync(p1p[1], 1, "[02] child3->parent");
+	printf("child3: failed reopen of slave\n");
+	fflush(stdout);
+	exit(1);
+    }
+#ifdef TIOCSCTTY
+    ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+
+    printf("child3: reopened slave\n");
+    testctty("child3: after reopen of slave");
+    testwr(slavefd, "child3: after reopen of slave");
+    testex(slavefd, "child3: after reopen of slave");
+    close(slavefd);
+    testctty("child3: after close of slave");
+
+    /*
+     * Sync for parent to close master.
+     */
+    wrsync(p1p[1], 0, "[02] child3->parent");
+    rdsync(pp1[0], NULL, "[03] parent->child3");
+
+    testctty("child3: after close of master");
+    printf("child3: attempting reopen of slave\n");
+    fflush(stdout);
+    slavefd = open(slave, O_RDWR|O_NONBLOCK);
+    if (slavefd < 0) {
+	printf("child3: failed reopen of slave after master close: "
+	       "errno=%ld (%s)\n", (long)errno, strerror(errno));
+	wrsync(p1p[1], 0, "[04] child3->parent");
+	fflush(stdout);
+	exit(0);
+    }
+    if (fcntl(slavefd, F_SETFL, 0) == -1) {
+	perror("child3: fcntl");
+	wrsync(p1p[1], 2, "[04] child3->parent");
+	exit(1);
+    }
+#ifdef TIOCSCTTY
+    ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+    printf("child3: reopened slave after master close\n");
+    testctty("child3: after reopen of slave after master close");
+    testwr(slavefd, "child3: after reopen of slave after master close");
+    testex(slavefd, "child3: after reopen of slave after master close");
+    n = write(slavefd, "foo", 4);
+    if (n < 0) {
+	printf("child3: writing to slave of closed master: errno=%ld (%s)\n",
+	       (long)errno, strerror(errno));
+	wrsync(p1p[1], 1, "[04] child3->parent");
+    } else {
+	printf("child3: wrote %d byes to slave of closed master\n", n);
+	fflush(stdout);
+	wrsync(p1p[1], 2, "[04] child3->parent");
+    }
+    rdsync(pp1[0], NULL, "[05] parent->child3");
+    testex(slavefd, "child3: after parent reopen of master");
+    testwr(slavefd, "child3: after parent reopen of master");
+    fflush(stdout);
+    n = write(slavefd, "bar", 4);
+    if (n < 0) {
+	perror("child3: writing to slave");
+    } else {
+	printf("child3: wrote %d bytes to slave\n", n);
+	fflush(stdout);
+    }
+    wrsync(p1p[1], 0, "[06] child3->parent");
+    rdsync(pp1[0], NULL, "[07] parent->child3");
+    wrsync(p1p[1], 0, "[08] child3->parent");
+    exit(0);
+}
+
+void
+child2(void)
+{
+    struct sigaction sa;
+
+    close(p21[0]);
+    setpgid(0, 0);
+    sa.sa_flags = 0;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_handler = handler;
+    if (sigaction(SIGHUP, &sa, NULL) < 0) {
+	wrsync(p21[1], 1, "[00] child2->child1");
+	perror("child2: sigaction");
+	fflush(stdout);
+	exit(1);
+    }
+    printf("child2: set up signal handler\n");
+    testctty("child2: after start");
+    testwr(slavefd, "child2: after start");
+    wrsync(p21[1], 0, "[00] child2->child1");
+    rdsync(pp1[0], NULL, "[01] parent->child2");
+
+    testctty("child2: after child1 exit");
+    testex(slavefd, "child2: after child1 exit");
+    testwr(slavefd, "child2: after child1 exit");
+    close(slavefd);
+    testctty("child2: after close of slavefd");
+    slavefd = open(slave, O_RDWR|O_NONBLOCK);
+    if (slavefd < 0) {
+	wrsync(p1p[1], 1, "[02] child2->parent");
+	printf("child2: failed reopen of slave\n");
+	fflush(stdout);
+	exit(1);
+    }
+#ifdef TIOCSCTTY
+    ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+    printf("child2: reopened slave\n");
+    testctty("child2: after reopen of slave");
+    fflush(stdout);
+    close(slavefd);
+    pid3 = fork();
+    if (!pid3) {
+	child3();
+    } else if (pid3 == -1) {
+	wrsync(p1p[1], 1, "[02] child2->parent");
+	perror("child2: fork of child3");
+	exit(1);
+    }
+    printf("child2: forked child3=%ld\n", (long)pid3);
+    fflush(stdout);
+    exit(0);
+}
+
+void
+child1(void)
+{
+    int status;
+
+#if 0
+    setuid(1);
+#endif
+    close(pp1[1]);
+    close(p1p[0]);
+    close(masterfd);
+    ptyint_void_association();
+    slavefd = open(slave, O_RDWR|O_NONBLOCK);
+    if (slavefd < 0) {
+	perror("child1: open slave");
+	exit(1);
+    }
+#ifdef TIOCSCTTY
+    ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+
+    printf("child1: opened slave\n");
+    testctty("child1: after slave open");
+
+    if (pipe(p21) < 0) {
+	perror("pipe child2->child1");
+	exit(1);
+    }
+    pid2 = fork();
+    if (!pid2) {
+	child2();
+    } else if (pid2 == -1) {
+	perror("child1: fork child2");
+	exit(1);
+    }
+    close(p21[1]);
+    printf("child1: forked child2=%ld\n", (long)pid2);
+    fflush(stdout);
+    rdsync(p21[0], &status, "[00] child2->child1");
+    exit(status);
+}
+
+int
+main(int argc, char *argv[])
+{
+    long retval;
+    int status;
+    char buf[4];
+    int n;
+
+    prog = argv[0];
+
+    printf("parent: pid=%ld\n", (long)getpid());
+
+    retval = ptyint_getpty_ext(&masterfd, slave, sizeof(slave), 0);
+
+    if (retval) {
+	com_err(prog, retval, "open master");
+	exit(1);
+    }
+#if 0
+    chown(slave, 1, -1);
+#endif
+    printf("parent: master opened; slave=%s\n", slave);
+    fflush(stdout);
+
+#if defined(HAVE_GRANTPT) && defined(HAVE_STREAMS)
+#ifdef O_NOCTTY
+    printf("parent: attempting to open slave before unlockpt\n");
+    fflush(stdout);
+    slavefd = open(slave, O_RDWR|O_NONBLOCK|O_NOCTTY);
+    if (slavefd < 0) {
+	printf("parent: failed slave open before unlockpt errno=%ld (%s)\n",
+	       (long)errno, strerror(errno));
+    } else {
+	printf("parent: WARNING: "
+	       "succeeded in opening slave before unlockpt\n");
+    }
+    close(slavefd);
+#endif
+    if (grantpt(masterfd) < 0) {
+	perror("parent: grantpt");
+	exit(1);
+    }
+    if (unlockpt(masterfd) < 0) {
+	perror("parent: unlockpt");
+	exit(1);
+    }
+#endif /* HAVE_GRANTPT && HAVE_STREAMS */
+
+    if (pipe(pp1) < 0) {
+	perror("pipe parent->child1");
+	exit(1);
+    }
+    if (pipe(p1p) < 0) {
+	perror("pipe child1->parent");
+	exit(1);
+    }
+
+    pid1 = fork();
+    if (!pid1) {
+	child1();
+    } else if (pid1 == -1) {
+	perror("fork of child1");
+	exit(1);
+    }
+    printf("parent: forked child1=%ld\n", (long)pid1);
+    fflush(stdout);
+    if (waitpid(pid1, &status1, 0) < 0) {
+	perror("waitpid for child1");
+	exit(1);
+    }
+    printf("parent: child1 exited, status=%d\n", status1);
+    if (status1)
+	exit(status1);
+
+    wrsync(pp1[1], 0, "[01] parent->child2");
+    rdsync(p1p[0], &status, "[02] child3->parent");
+    if (status) {
+	fprintf(stderr, "child2 or child3 got an error\n");
+	exit(1);
+    }
+
+    printf("parent: closing master\n");
+    fflush(stdout);
+    close(masterfd);
+    chmod(slave, 0666);
+    printf("parent: closed master\n");
+    wrsync(pp1[1], 0, "[03] parent->child3");
+
+    rdsync(p1p[0], &status, "[04] child3->parent");
+    switch (status) {
+    case 1:
+	break;
+    case 0:
+	exit(0);
+    default:
+	fprintf(stderr, "child3 got an error\n");
+	fflush(stdout);
+	exit(1);
+    }
+
+    retval = pty_getpty(&masterfd, slave2, sizeof(slave2));
+    printf("parent: new master opened; slave=%s\n", slave2);
+#if 0
+#ifdef HAVE_REVOKE
+    printf("parent: revoking\n");
+    revoke(slave2);
+#endif
+#endif
+    fflush(stdout);
+    wrsync(pp1[1], 0, "[05] parent->child3");
+    rdsync(p1p[0], NULL, "[06] child3->parent");
+
+    n = read(masterfd, buf, 4);
+    if (n < 0) {
+	perror("parent: reading from master");
+    } else {
+	printf("parent: read %d bytes (%.*s) from master\n", n, n, buf);
+	fflush(stdout);
+    }
+    chmod(slave2, 0666);
+    close(masterfd);
+    wrsync(pp1[1], 0, "[07] parent->child3");
+    rdsync(p1p[0], NULL, "[08] child3->parent");
+    fflush(stdout);
+    exit(0);
+}
diff --git a/krb5-1-6/src/appl/libpty/sane_hostname.c b/krb5-1-6/src/appl/libpty/sane_hostname.c
new file mode 100644
index 000000000..8ef6de875
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/sane_hostname.c
@@ -0,0 +1,116 @@
+/*
+ * pty_make_sane_hostname: Make a sane hostname from an IP address.
+ * This returns allocated memory!
+ * 
+ * Copyright 1999, 2000, 2001 by the Massachusetts Institute of
+ * Technology.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+#include "com_err.h"
+#include "pty-int.h"
+#include <sys/socket.h>
+#include "libpty.h"
+#include <arpa/inet.h>
+
+#include "socket-utils.h"
+#include "fake-addrinfo.h"
+
+static void
+downcase (char *s)
+{
+    for (; *s != '\0'; s++)
+	*s = tolower ((int) *s);
+}
+
+long
+pty_make_sane_hostname(const struct sockaddr *addr, int maxlen,
+		       int strip_ldomain, int always_ipaddr, char **out)
+{
+    struct addrinfo *ai = 0;
+    char addrbuf[NI_MAXHOST];
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+    struct utmp ut;
+#else
+    struct utmpx utx;
+#endif
+    char *cp, *domain;
+    char lhost[MAXHOSTNAMELEN];
+    size_t ut_host_len;
+
+    /* Note that on some systems (e.g., AIX 4.3.3), we may get an IPv6
+       address such as ::FFFF:18.18.1.71 when an IPv4 connection comes
+       in.  That's okay; at least on AIX, getnameinfo will deal with
+       that properly.  */
+
+    *out = NULL;
+    if (maxlen && maxlen < 16)
+	/* assume they meant 16, otherwise IPv4 addr won't fit */
+	maxlen = 16;
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+    ut_host_len = sizeof (ut.ut_host);
+#else
+    ut_host_len = sizeof (utx.ut_host);
+#endif
+    if (maxlen == 0)
+	maxlen = ut_host_len;
+    *out = malloc(ut_host_len);
+    if (*out == NULL)
+	return ENOMEM;
+
+    if (always_ipaddr) {
+    use_ipaddr:
+	if (getnameinfo (addr, socklen (addr), addrbuf, sizeof (addrbuf),
+			 (char *)0, 0, NI_NUMERICHOST) == 0)
+	    strncpy(*out, addrbuf, ut_host_len);
+	else
+	    strncpy(*out, "??", ut_host_len);
+	(*out)[ut_host_len - 1] = '\0';
+	return 0;
+    }
+
+    /* If we didn't want to chop off the local domain, this would be
+       much simpler -- just a single getnameinfo call and a strncpy.  */
+    if (getnameinfo(addr, socklen (addr), addrbuf, sizeof (addrbuf),
+		    (char *) NULL, 0, NI_NAMEREQD) != 0)
+	goto use_ipaddr;
+    downcase (addrbuf);
+    if (strip_ldomain) {
+	struct addrinfo hints;
+	(void) gethostname(lhost, sizeof (lhost));
+	memset (&hints, 0, sizeof (hints));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_flags = AI_CANONNAME;
+	if (getaddrinfo(lhost, (char *)NULL, &hints, &ai) == 0
+	    && ai != NULL) {
+		if (ai->ai_canonname != NULL) {
+			downcase (ai->ai_canonname);
+			domain = strchr (ai->ai_canonname, '.');
+			if (domain != NULL) {
+				cp = strstr (addrbuf, domain);
+				if (cp != NULL)
+					*cp = '\0';
+			}
+		}
+		freeaddrinfo (ai);
+	}
+    }
+    strncpy(*out, addrbuf, ut_host_len);
+    (*out)[ut_host_len - 1] = '\0';
+    if (strlen(*out) >= maxlen)
+	goto use_ipaddr;
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/libpty/update_utmp.c b/krb5-1-6/src/appl/libpty/update_utmp.c
new file mode 100644
index 000000000..d2de6428f
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/update_utmp.c
@@ -0,0 +1,723 @@
+/*
+ * pty_update_utmp: Update or create a utmp entry
+ * 
+ * Copyright 1995, 2001 by the Massachusetts Institute of Technology.
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ */
+
+/*
+ * Rant about the historical vagaries of utmp:
+ * -------------------------------------------
+ *
+ * There exist many subtly incompatible incarnations of utmp, ranging
+ * from BSD to System V to Unix98 and everywhere in between.  This
+ * rant attempts to collect in one place as much knowledge as possible
+ * about this portability nightmare.
+ *
+ * BSD:
+ * ----
+ *
+ * The simplest (and earliest? possibly dating back to Version 7...)
+ * case is 4.x BSD utmp/wtmp.  There are no auxiliary files.  There is
+ * only a struct utmp, declared in utmp.h.  Its contents usually
+ * include:
+ *
+ *	char ut_line[]
+ *	char ut_name[]
+ *	char ut_host[]
+ *	long ut_time
+ *
+ * The meanings of these fields follow their names reasonbly well.
+ * The ut_line field usually is the pathname of the tty device
+ * associated with the login, with the leading "/dev/" stripped off.
+ *
+ * It is believed that ut_host is nul-terminated, while the other
+ * strings are merely nul-padded.
+ *
+ * Generally, ut_name is an empty string for a logout record in both
+ * utmp and wtmp.  For entries made by the window system or other
+ * terminal emulation stuff, ut_host is an empty string (at least
+ * under SunOS 4.x, it seems).  The macro nonuser() is used to
+ * determine this if a utmp entry is made by the window system on at
+ * least SunOS 4.x.
+ *
+ * The native login never clears its own utmp entry or writes its own
+ * logout record; its parent (one of init, rlogind, telnetd, etc.)
+ * should handle that.  In theory, getty could do that, but getty
+ * usually doesn't fork to exec login.
+ *
+ * Old (c. 1984) System V:
+ * -----------------------
+ *
+ * This is partially conjecture, based on some reading of
+ * /usr/xpg2include/utmp.h on a SunOS 4.x system.  There appears to
+ * only be a struct utmp, declared in utmp.h.  It is likely used for
+ * both utmp and wtmp files.  It is quite likely that the utmp is only
+ * supposed to be accessed via the getutline()/pututline() API.  The
+ * contents of struct utmp seem to include:
+ *
+ *	char	ut_user[]
+ *	char	ut_id[]
+ *	char	ut_line[]
+ *	short	ut_pid
+ *	short	ut_type
+ *	struct exit_status ut_exit
+ *	time_t	ut_time
+ *
+ * On these systems, ut_name is often #define'ed to be ut_user to be
+ * somewhat compatible with the BSD-style utmp.  Note that there is
+ * not necessarily a ut_host field in this utmp structure.
+ *
+ * The ut_id field bears some explanation.  The systems that use this
+ * style of utmp also use a sysV-ish init, which starts processes out
+ * of /etc/inittab rather than /etc/ttys, and has the concept of
+ * runlevels.  The first field in each line of /etc/inittab contains a
+ * unique ID field.  init probably gets really confused if there are
+ * conflicts here.  Every process that init starts gets its own entry
+ * written to utmp.
+ *
+ * It is possible for multiple entries to have the same ut_line but
+ * different ut_id values, since the sysadmin will be responsible for
+ * assigning values to ut_id.  Usually, ut_id is four characters,
+ * while the permissible unique ID values for entries in /etc/inittab
+ * are constrained to two characters, but this is not always the
+ * case.  In the case where we are emulating the vendor's login
+ * program and being run out of getty, we need to account for which
+ * value of ut_id was used by the getty, since pututline() will search
+ * based on ut_id and not ut_line for some reason.
+ *
+ * The ut_pid and ut_type fields are used for bookkeeping by init.
+ * The ut_type field gets the value INIT_PROCESS for processes started
+ * by init.  It gets the value LOGIN_PROCESS if it is a process that
+ * is prompting for a login name, and it gets the value USER_PROCESS
+ * for an actual valid login.  When the process dies, either init
+ * cleans up after it and records a DEAD_PROCESS entry in utmp, or the
+ * process itself does so.  It's not completely clear which actually
+ * happens, though it is quite possible that init only cleans up after
+ * processes that it starts itself.
+ *
+ * Other values of ut_type exist; they're largely internal bookkeeping
+ * for init's runlevels and such, and don't really interest this
+ * library at all.
+ *
+ * The ut_exit field contains the following members:
+ *
+ *	short	e_termination
+ *	short	e_exit
+ *
+ * It is not clear how these values are used; presumably they record
+ * the process termination status of dead processes.
+ *
+ * There is no uniform API for manipulating wtmp on systems that use
+ * this sort of utmp structure; it can be assumed that the structure
+ * can be directly written to the wtmp file.
+ *
+ * Unix98:
+ * -------
+ *
+ * This description also likely applies to later System V derivatives
+ * as well as systems conforming to earlier X/Open standards such as
+ * XPG4.  There is a new header, utmpx.h, which defines a struct utmpx
+ * and a new getutxline()/pututxline() API for accessing it.  Some
+ * systems actually have a utmpx file on disk; others use the utmpx
+ * API to access a file named utmp, just to further confuse matters.
+ *
+ * The utmpx structure is guaranteed (by Unix98) to contain at least
+ * the following:
+ *
+ *	char	ut_user[]
+ *	char	ut_line[]
+ *	char	ut_id[]
+ *	pid_t	ut_pid
+ *	short	ut_type
+ *	struct timeval ut_tv
+ *
+ * It is not guaranteed to contain, but often does contain, the
+ * following:
+ *
+ *	char	ut_host[]
+ *	int	ut_syslen
+ *	int	ut_session
+ *	struct exit_status ut_exit
+ *
+ * The ut_syslen field, on systems that contain it, contains the
+ * number of significant characters in ut_host, including the
+ * terminating nul character.
+ *
+ * The main difference between this struct utmpx and the struct utmp
+ * used by early sysV derivatives is the change from a time_t or long
+ * for ut_time to a struct timeval for ut_tv.
+ *
+ * Comments in various header files imply that ut_session is used for
+ * window systems, but it's not clear how.  Perhaps it contains the
+ * session ID of the session running the window system, e.g. the xdm
+ * or X server on an X11 system.
+ *
+ * Most of the description of the earlier sysV format probably applies
+ * here, with suitable changes of names.  On systems that maintain
+ * utmpx and utmp files in parallel, it is assumed that using the
+ * pututxline() API is sufficient to keep them in sync.  There are no
+ * known counterexamples to this.
+ *
+ * Nevertheless, there are, on some systems, API functions getutmp()
+ * and getutmpx() that appear to convert from struct utmpx to struct
+ * utmp and vice versa.  This could be useful when there is a wtmp
+ * file but not a corresponding wtmpx file.
+ *
+ * Incidentally, ut_exit is sometimes present in the struct utmp but
+ * not the struct utmpx for a given system.  Sometimes, it exists in
+ * both, but contains differently named members.  It's probably one of
+ * the least portable pieces in this whole mess.
+ *
+ * Known Quirks of Specific OSes:
+ * ------------------------------
+ *
+ * Solaris 2.x:
+ *
+ * Has utmpd, which will automatically clean up utmpx, utmp, wtmpx,
+ * wtmp after process termination, provided that pututxline() was
+ * used.
+ *
+ * Solaris 8 seems to have a bug in utmpname() that causes
+ * garbage filenames to be generated.  Solaris 7 (and possibly Solaris
+ * 8) have a bug in utmpxname() that prevents them from looking at
+ * anything other than /var/adm/utmpx, it seems.  For some reason,
+ * though, utmpname() goes and looks at the corresponding utmpx file.
+ *
+ * Solaris 7 (and may be 8 as well) has a bug in pututline() that
+ * interacts badly with prior invocation of getutline(): if
+ * getutline() finds an entry, calling pututline() without first
+ * calling setutent() will overwrite the record following the one that
+ * was intended.
+ *
+ * Also, ut_exit in utmpx contains ut_e_termination and
+ * ut_e_exit (otherwise it contains the expected e_termination and
+ * e_exit) only if _XPG4_2 is defined and __EXTENSIONS__ is not, which
+ * is not a compilation environment we're likely to encourage.  The
+ * ut_exit field of utmp contains the expected fields.
+ *
+ * If _XPG4_2 is not defined or __EXTENSIONS__ is defined, the
+ * functions getutmp(), getutmpx(), updwtmp(), and updwtmpx() are
+ * available, as well as the undocumented functions makeutx() and
+ * modutx().
+ *
+ * All the files utmp, utmpx, wtmp, and wtmpx exist.
+ *
+ * HP-UX 10.x:
+ *
+ * There is a curious interaction between how we allocate pty masters
+ * and how ttyname() works.  It seems that if /dev/ptmx/clone is
+ * opened, a call to ptsname() on the master fd gets a filename of the
+ * form /dev/pty/tty[pqrs][0-9a-f], while ttyname() called on a fd
+ * opened with that filename returns a filename of the form
+ * /dev/tty[pqrs][0-9a-f] instead.  These two filenames are actually
+ * hardlinks to the same special device node, so it shouldn't be a
+ * security problem.
+ *
+ * We can't call ttyname() in the parent because it would involve
+ * possibly acquiring a controlling terminal (which would be
+ * potentially problematic), so we have to resort to some trickery in
+ * order to ensure that the ut_line in the wtmp logout and login
+ * records match.  If they don't match, various utilities such as last
+ * will get confused.  Of course it's likely an OS bug that ttyname()
+ * and ptsname() are inconsistent in this way, but it's one that isn't
+ * too painful to work around.
+ *
+ * It seems that the HP-UX native telnetd has problems similar to ours
+ * in this area, though it manages to write the correct logout record
+ * to wtmp somehow.  It probably does basically what we do here:
+ * search for a record with a matching ut_pid and grab its ut_line for
+ * writing into the logout record.  Interestingly enough, its
+ * LOGIN_PROCESS record is of the form pty/tty[pqrs][0-9][a-f].
+ *
+ * Uses four-character unique IDs for /etc/inittab, which means that
+ * programs not running out of init should use two-character ut_id
+ * fields to avoid conflict.
+ *
+ * In utmpx, ut_exit contains __e_termination and __e_exit, while
+ * ut_exit in utmp contains the expected fields.
+ *
+ * There is no wtmpx file, despite there being utmp and utmpx files.
+ *
+ * HP-UX 11.23:
+ *
+ * In addition to other HP-UX issues, 11.23 includes yet another utmp
+ * management interface in utmps.h.  This interface updates a umtpd
+ * daemon which then manages local files.  Directly accessing the files
+ * through the existing, yet deprecated, utmp.h interface results in 
+ * nothing.
+ *
+ * Irix 6.x:
+ *
+ * In utmpx, ut_exit contains __e_termination and __e_exit, which get
+ * #define aliases e_termination and e_exit if _NO_XOPEN4 is true.
+ * Curiously enough, utmp.h declares ut_exit to have __e_termination
+ * and __e_exit as well, but does #define e_termination
+ * __e_termination, etc. if another header (utmpx.h) hasn't already
+ * declared struct __exit_status.  It seems that the default
+ * compilation environment has the effect of making _NO_XOPEN4 true
+ * though.
+ *
+ * If _NO_XOPEN4 is true, getutmp(), getutmpx(), updwtmp(), and
+ * updwtmpx() are available, as well as the undocumented functions
+ * makeutx() and modutx().
+ *
+ * All the files utmp, utmpx, wtmp, and wtmpx exist.
+ *
+ * Tru64 Unix 4.x:
+ *
+ * In utmpx, ut_exit contains ut_termination and ut_exit, while utmp
+ * contains the expected fields.  The files utmp and wtmp seem to
+ * exist, but not utmpx or wtmpx.
+ *
+ * When writing a logout entry, the presence of a non-empty username
+ * confuses last.
+ *
+ * AIX 4.3.x:
+ *
+ * The ut_exit field seems to exist in utmp, but not utmpx. The files
+ * utmp and wtmp seem to exist, but not utmpx, or wtmpx.
+ *
+ * libpty Implementation Decisions:
+ * --------------------------------
+ *
+ * We choose to use the pututxline() whenever possible, falling back
+ * to pututline() and calling write() to write out struct utmp if
+ * necessary.  The code to handle pututxline() and pututline() is
+ * rather similar, since the structure members are quite similar, and
+ * we make the assumption that it will never be necessary to call
+ * both.  This allows us to avoid duplicating lots of code, by means
+ * of some slightly demented macros.
+ *
+ * If neither pututxline() nor pututline() are available, we assume
+ * BSD-style utmp files and behave accordingly, writing the structure
+ * out to disk ourselves.
+ *
+ * On systems where updwtmpx() or updwtmp() are available, we use
+ * those to update the wtmpx or wtmp file.  When they're not
+ * available, we write the utmpx or utmp structure out to disk
+ * ourselves, though sometimes conversion from utmpx to utmp format is
+ * needed.
+ *
+ * We assume that at logout the system is ok with with having an empty
+ * username both in utmp and wtmp.
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+#if !defined(UTMP_FILE) && defined(_PATH_UTMP)
+#define UTMP_FILE _PATH_UTMP
+#endif
+
+/* if it is *still* missing, assume SunOS */
+#ifndef UTMP_FILE
+#define	UTMP_FILE	"/etc/utmp"
+#endif
+
+/*
+ * The following grossness exists to avoid duplicating lots of code
+ * between the cases where we have an old-style sysV utmp and where we
+ * have a modern (Unix98 or XPG4) utmpx, or the new (hp-ux 11.23) utmps.  
+ * See the above history rant for further explanation.
+ */
+#if defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT) || defined(HAVE_SETUTSENT)
+#ifdef HAVE_SETUTSENT
+#include <utmps.h>
+#define PTY_STRUCT_UTMPX struct utmps
+#define PTY_SETUTXENT setutsent
+#define PTY_GETUTXENT GETUTSENT
+#define PTY_GETUTXLINE GETUTSLINE
+#define PTY_PUTUTXLINE PUTUTSLINE
+#define PTY_ENDUTXENT endutsent
+#else
+#ifdef HAVE_SETUTXENT
+#define PTY_STRUCT_UTMPX struct utmpx
+#define PTY_SETUTXENT setutxent
+#define PTY_GETUTXENT getutxent
+#define PTY_GETUTXLINE getutxline
+#define PTY_PUTUTXLINE pututxline
+#define PTY_ENDUTXENT endutxent
+#else
+#define PTY_STRUCT_UTMPX struct utmp
+#define PTY_SETUTXENT setutent
+#define PTY_GETUTXENT getutent
+#define PTY_GETUTXLINE getutline
+#define PTY_PUTUTXLINE pututline
+#define PTY_ENDUTXENT endutent
+#endif
+#endif
+static int better(const PTY_STRUCT_UTMPX *, const PTY_STRUCT_UTMPX *,
+		  const PTY_STRUCT_UTMPX *);
+static int match_pid(const PTY_STRUCT_UTMPX *,
+		     const PTY_STRUCT_UTMPX *);
+static PTY_STRUCT_UTMPX *best_utxent(const PTY_STRUCT_UTMPX *);
+
+/*
+ * Utility function to determine whether A is a better match for
+ * SEARCH than B.  Should only be called by best_utxent().
+ */
+static int
+better(const PTY_STRUCT_UTMPX *search,
+       const PTY_STRUCT_UTMPX *a, const PTY_STRUCT_UTMPX *b)
+{
+    if (strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) {
+	if (!strncmp(search->ut_id, a->ut_id, sizeof(a->ut_id))) {
+	    return 1;
+	}
+    }
+
+    if (strncmp(a->ut_id, b->ut_id, sizeof(b->ut_id))) {
+	/* Got different UT_IDs; find the right one. */
+	if (!strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) {
+	    /* Old entry already matches; use it. */
+	    return 0;
+	}
+	if (a->ut_type == LOGIN_PROCESS
+	    && b->ut_type != LOGIN_PROCESS) {
+	    /* Prefer LOGIN_PROCESS */
+	    return 1;
+	}
+	if (search->ut_type == DEAD_PROCESS
+	    && a->ut_type == USER_PROCESS
+	    && b->ut_type != USER_PROCESS) {
+	    /*
+	     * Try USER_PROCESS if we're entering a DEAD_PROCESS.
+	     */
+	    return 1;
+	}
+	return 0;
+    } else {
+	/*
+	 * Bad juju.  We shouldn't get two entries with identical
+	 * ut_id fields for the same value of ut_line.  pututxline()
+	 * will probably pick the first entry, in spite of the strange
+	 * state of utmpx, if we rewind with setutxent() first.
+	 *
+	 * For now, return 0, to force the earlier entry to be used.
+	 */
+	return 0;
+    }
+}
+
+static int
+match_pid(const PTY_STRUCT_UTMPX *search, const PTY_STRUCT_UTMPX *u)
+{
+    if (u->ut_type != LOGIN_PROCESS && u->ut_type != USER_PROCESS)
+	return 0;
+    if (u->ut_pid == search->ut_pid) {
+	/*
+	 * One of ut_line or ut_id should match, else some nastiness
+	 * may result.  We can fall back to searching by ut_line if
+	 * need be.  This should only really break if we're login.krb5
+	 * running out of getty, or we're cleaning up after the vendor
+	 * login, and either the vendor login or the getty has
+	 * different ideas than we do of what both ut_id and ut_line
+	 * should be.  It should be rare, though.  We may want to
+	 * remove this restriction later.
+	 */
+	if (!strncmp(u->ut_line, search->ut_line, sizeof(u->ut_line)))
+	    return 1;
+	if (!strncmp(u->ut_id, search->ut_id, sizeof(u->ut_id)))
+	    return 1;
+    }
+    return 0;
+}
+
+/*
+ * This expects to be called with SEARCH pointing to a struct utmpx
+ * with its ut_type equal to USER_PROCESS or DEAD_PROCESS, since if
+ * we're making a LOGIN_PROCESS entry, we presumably don't care about
+ * preserving existing state.  At the very least, the ut_pid, ut_line,
+ * ut_id, and ut_type fields must be filled in by the caller.
+ */
+static PTY_STRUCT_UTMPX *
+best_utxent(const PTY_STRUCT_UTMPX *search)
+{
+    PTY_STRUCT_UTMPX utxtmp, *utxp;
+    int i, best;
+
+    memset(&utxtmp, 0, sizeof(utxtmp));
+
+    /*
+     * First, search based on pid, but only if non-zero.
+     */
+    if (search->ut_pid) {
+	i = 0;
+	PTY_SETUTXENT();
+	while ((utxp = PTY_GETUTXENT()) != NULL) {
+	    if (match_pid(search, utxp)) {
+		return utxp;
+	    }
+	    i++;
+	}
+    }
+    /*
+     * Uh-oh, someone didn't enter our pid.  Try valiantly to search
+     * by terminal line.
+     */
+    i = 0;
+    best = -1;
+    PTY_SETUTXENT();
+    while ((utxp = PTY_GETUTXLINE(search)) != NULL) {
+	if (better(search, utxp, &utxtmp)) {
+	    utxtmp = *utxp;
+	    best = i;
+	}
+	memset(utxp, 0, sizeof(*utxp));
+	i++;
+    }
+    if (best == -1)
+	return NULL;
+    PTY_SETUTXENT();
+    for (i = 0; i <= best; i++) {
+	if (utxp != NULL)
+	    memset(utxp, 0, sizeof(*utxp));
+	utxp = PTY_GETUTXLINE(search);
+    }
+    return utxp;
+}
+
+/*
+ * All calls to this function for a given login session must have the
+ * pids be equal; various things will break if this is not the case,
+ * since we do some searching based on the pid.  Note that if a parent
+ * process calls this via pty_cleanup(), it should still pass the
+ * child's pid rather than its own.
+ */
+long
+pty_update_utmp(int process_type, int pid, const char *username,
+		    const char *line, const char *host, int flags)
+{
+    PTY_STRUCT_UTMPX utx, *utxtmp, utx2;
+    const char *cp;
+    size_t len;
+    char utmp_id[5];
+
+    /*
+     * Zero things out in case there are fields we don't handle here.
+     * They tend to be non-portable anyway.
+     */
+    memset(&utx, 0, sizeof(utx));
+    utxtmp = NULL;
+    cp = line;
+    if (strncmp(cp, "/dev/", sizeof("/dev/") - 1) == 0)
+	cp += sizeof("/dev/") - 1;
+    strncpy(utx.ut_line, cp, sizeof(utx.ut_line));
+    utx.ut_pid = pid;
+    switch (process_type) {
+    case PTY_LOGIN_PROCESS:
+	utx.ut_type = LOGIN_PROCESS;
+	break;
+    case PTY_USER_PROCESS:
+	utx.ut_type = USER_PROCESS;
+	break;
+    case PTY_DEAD_PROCESS:
+	utx.ut_type = DEAD_PROCESS;
+	break;
+    default:
+	return PTY_UPDATE_UTMP_PROCTYPE_INVALID;
+    }
+    len = strlen(line);
+    if (len >= 2) {
+	cp = line + len - 1;
+	if (*(cp - 1) != '/')
+	    cp--;		/* last two characters, unless it's a / */
+    } else
+	cp = line;
+    /*
+     * HP-UX has mostly 4-character inittab ids, while most other sysV
+     * variants use only 2-charcter inittab ids, so to avoid
+     * conflicts, we pick 2-character ut_ids for our own use.  We may
+     * want to feature-test for this, but it would be somewhat of a
+     * pain, and would eit cross-compiling.
+     */
+#ifdef __hpux
+    strcpy(utmp_id, cp);
+#else
+    if (len > 2 && *(cp - 1) != '/')
+      sprintf(utmp_id, "k%s", cp - 1);
+    else
+      sprintf(utmp_id, "k0%s", cp);
+#endif
+    strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id));
+    /*
+     * Get existing utmpx entry for PID or LINE, if any, so we can
+     * copy some stuff from it.  This is particularly important if we
+     * are login.krb5 and are running out of getty, since getty will
+     * have written the entry for the line with ut_type ==
+     * LOGIN_PROCESS, and what it has recorded in ut_id may not be
+     * what we come up with, since that's up to the whim of the
+     * sysadmin who writes the inittab entry.
+     *
+     * Note that we may be screwed if we try to write a logout record
+     * for a vendor's login program, since it may construct ut_line
+     * and ut_id differently from us; even though we search on ut_pid,
+     * we validate against ut_id or ut_line to sanity-check.  We may
+     * want to rethink whether to actually include this check, since
+     * it should be highly unlikely that there will be a bogus entry
+     * in utmpx matching our pid.
+     */
+    if (process_type != PTY_LOGIN_PROCESS)
+	utxtmp = best_utxent(&utx);
+
+#ifdef HAVE_SETUTXENT
+    if (gettimeofday(&utx.ut_tv, NULL))
+	return errno;
+#else
+    (void)time(&utx.ut_time);
+#endif
+    /*
+     * On what system is there not ut_host?  Unix98 doesn't mandate
+     * this field, but we have yet to see a system that supports utmpx
+     * that doesn't have it.  For what it's worth, some ancient utmp
+     * headers on svr4 systems imply that there's no ut_host in struct
+     * utmp...
+     */
+#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_HOST))	\
+	|| (!defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_HOST))
+    if (host != NULL) {
+	strncpy(utx.ut_host, host, sizeof(utx.ut_host));
+	/* Unlike other things in utmpx, ut_host is nul-terminated? */
+	utx.ut_host[sizeof(utx.ut_host) - 1] = '\0';
+    } else
+	utx.ut_host[0] = '\0';
+#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_SYSLEN))	\
+	|| (!defined (HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_SYSLEN))
+    if (host != NULL)
+	utx.ut_syslen = strlen(utx.ut_host) + 1;
+    else
+	utx.ut_syslen = 0;
+#endif
+#endif
+
+    /* XXX deal with ut_addr? */
+
+    if (utxtmp != NULL) {
+	/*
+	 * For entries not of type LOGIN_PROCESS, override some stuff
+	 * with what was in the previous entry we found, if any.
+	 */
+	strncpy(utx.ut_id, utxtmp->ut_id, sizeof(utx.ut_id));
+	utx.ut_pid = utxtmp->ut_pid;
+    }
+
+    strncpy(utx.ut_user, username, sizeof(utx.ut_user));
+
+    /*
+     * Make a copy now and deal with copying relevant things out of
+     * utxtmp in case setutxline() or pututxline() clobbers utxtmp.
+     * (After all, the returned pointer from the getutx*() functions
+     * is allowed to point to static storage that may get overwritten
+     * by subsequent calls to related functions.)
+     */
+    utx2 = utx;
+    if (process_type == PTY_DEAD_PROCESS && utxtmp != NULL) {
+	/*
+	 * Use ut_line from old entry to avoid confusing last on
+	 * HP-UX.
+	 */
+	strncpy(utx2.ut_line, utxtmp->ut_line, sizeof(utx2.ut_line));
+    }
+
+    PTY_SETUTXENT();
+    PTY_PUTUTXLINE(&utx);
+    PTY_ENDUTXENT();
+
+    /* Don't record LOGIN_PROCESS entries. */
+    if (process_type == PTY_LOGIN_PROCESS)
+	return 0;
+
+#ifdef HAVE_SETUTXENT
+    return ptyint_update_wtmpx(&utx2);
+#else
+    return ptyint_update_wtmp(&utx2);
+#endif
+}
+
+#else /* !(HAVE_SETUTXENT || HAVE_SETUTENT) */
+
+long
+pty_update_utmp(int process_type, int pid, const char *username,
+		const char *line, const char *host, int flags)
+{
+    struct utmp ent, ut;
+    const char *cp;
+    int tty, lc, fd;
+    off_t seekpos;
+    ssize_t ret;
+    struct stat statb;
+
+    memset(&ent, 0, sizeof(ent));
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+    if (host)
+	strncpy(ent.ut_host, host, sizeof(ent.ut_host));
+#endif
+    strncpy(ent.ut_name, username, sizeof(ent.ut_name));
+    cp = line;
+    if (strncmp(cp, "/dev/", sizeof("/dev/") - 1) == 0)
+	cp += sizeof("/dev/") - 1;
+    strncpy(ent.ut_line, cp, sizeof(ent.ut_line));
+    (void)time(&ent.ut_time);
+
+    if (flags & PTY_TTYSLOT_USABLE)
+	tty = ttyslot();
+    else {
+	tty = -1;
+	fd = open(UTMP_FILE, O_RDONLY);
+	if (fd == -1)
+	    return errno;
+	for (lc = 0; ; lc++) {
+	    seekpos = lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET);
+	    if (seekpos != (off_t)(lc * sizeof(struct utmp)))
+		break;
+	    if (read(fd, (char *) &ut, sizeof(struct utmp))
+		!= sizeof(struct utmp))
+		break;
+	    if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
+		tty = lc;
+		break;
+	    }
+	}
+	close(fd);
+    }
+    if (tty > 0) {
+	fd = open(UTMP_FILE, O_WRONLY);
+	if (fd == -1)
+	    return 0;
+	if (fstat(fd, &statb)) {
+	    close(fd);
+	    return 0;
+	}
+	seekpos = lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
+	if (seekpos != (off_t)(tty * sizeof(struct utmp))) {
+	    close(fd);
+	    return 0;
+	}
+	ret = write(fd, (char *)&ent, sizeof(struct utmp));
+	if (ret != sizeof(struct utmp)) {
+	    ftruncate(fd, statb.st_size);
+	}
+	close(fd);
+    }
+    /* Don't record LOGIN_PROCESS entries. */
+    if (process_type == PTY_LOGIN_PROCESS)
+	return 0;
+    else
+	return ptyint_update_wtmp(&ent);
+}
+#endif
diff --git a/krb5-1-6/src/appl/libpty/update_wtmp.c b/krb5-1-6/src/appl/libpty/update_wtmp.c
new file mode 100644
index 000000000..988bae61a
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/update_wtmp.c
@@ -0,0 +1,127 @@
+/*
+ * ptyint_update_wtmp: Update wtmp.
+ *
+ * Copyright 1995, 2001 by the Massachusetts Institute of Technology.
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+#if !defined(WTMP_FILE) && defined(_PATH_WTMP)
+#define WTMP_FILE _PATH_WTMP
+#endif
+
+#if !defined(WTMPX_FILE) && defined(_PATH_WTMPX)
+#define WTMPX_FILE _PATH_WTMPX
+#endif
+
+/* if it is *still* missing, assume SunOS */
+#ifndef WTMP_FILE
+#define	WTMP_FILE	"/usr/adm/wtmp"
+#endif
+
+#ifdef HAVE_SETUTXENT
+
+#if defined(HAVE_GETUTMP) && defined(NEED_GETUTMP_PROTO)
+extern void getutmp(const struct utmpx *, struct utmp *);
+#endif
+
+/*
+ * Welcome to conditional salad.
+ *
+ * This really wants to take a (const struct utmpx *) but updutmpx()
+ * on Solaris at least doesn't take a const argument.  *sigh*
+ */
+long
+ptyint_update_wtmpx(struct utmpx *ent)
+{
+#if !(defined(HAVE_UPDWTMPX) && defined(WTMPX_FILE))
+    struct utmp ut;
+#endif
+
+#if defined(HAVE_UPDWTMPX) && defined(WTMPX_FILE)
+    updwtmpx(WTMPX_FILE, ent);
+    return 0;
+#else
+
+#ifdef HAVE_GETUTMP
+    getutmp(ent, &ut);
+#else  /* Emulate getutmp().  Yuck. */
+    memset(&ut, 0, sizeof(ut));
+    strncpy(ut.ut_name, ent->ut_user, sizeof(ut.ut_name));
+    strncpy(ut.ut_line, ent->ut_line, sizeof(ut.ut_line));
+    ut.ut_time = ent->ut_tv.tv_sec;
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+    strncpy(ut.ut_host, ent->ut_host, sizeof(ut.ut_host));
+    ut.ut_host[sizeof(ut.ut_host) - 1] = '\0';
+#ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
+    ut.ut_syslen = strlen(ut.ut_host) + 1;
+#endif
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+    strncpy(ut.ut_id, ent->ut_id, sizeof(ut.ut_id));
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+    ut.ut_pid = ent->ut_pid;
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+    ut.ut_type = ent->ut_type;
+#endif
+#if defined(PTY_UTMP_E_EXIT) && defined(PTY_UTMPX_E_EXIT)
+    ut.ut_exit.PTY_UTMP_E_EXIT = ent->ut_exit.PTY_UTMPX_E_EXIT;
+    ut.ut_exit.PTY_UTMP_E_TERMINATION =
+	ent->ut_exit.PTY_UTMPX_E_TERMINATION;
+#endif
+#endif /* !HAVE_GETUTMP */
+
+    return ptyint_update_wtmp(&ut);
+#endif /* !(defined(WTMPX_FILE) && defined(HAVE_UPDWTMPX)) */
+}
+
+#endif  /* HAVE_SETUTXENT */
+
+#if !(defined(WTMPX_FILE) && defined(HAVE_UPDWTMPX)) \
+	|| !defined(HAVE_SETUTXENT)
+
+long
+ptyint_update_wtmp(struct utmp *ent)
+{
+#ifndef HAVE_UPDWTMP
+    int fd;
+    struct stat statb;
+#endif
+
+#ifdef HAVE_UPDWTMP
+    updwtmp(WTMP_FILE, ent);
+#else
+    fd = open(WTMP_FILE, O_WRONLY | O_APPEND, 0);
+    if (fd != -1 && !fstat(fd, &statb)) {
+	if (write(fd, (char *)ent, sizeof(struct utmp))
+	    != sizeof(struct utmp))
+	    (void)ftruncate(fd, statb.st_size);
+	(void)close(fd);
+    }
+#endif
+    /*
+     * no current failure cases; file not found is not failure!
+     */
+    return 0;
+}
+
+#endif
diff --git a/krb5-1-6/src/appl/libpty/vhangup.c b/krb5-1-6/src/appl/libpty/vhangup.c
new file mode 100644
index 000000000..292437142
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/vhangup.c
@@ -0,0 +1,50 @@
+/*
+ * pty_open_slave: open slave side of terminal, clearing for use.
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ *
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+void ptyint_vhangup(void)
+{
+#ifdef HAVE_VHANGUP
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+    /* Initialize "sa" structure. */
+    (void) sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    
+#endif
+
+#ifdef POSIX_SIGNALS
+	sa.sa_handler = SIG_IGN;
+	(void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
+	vhangup();
+	sa.sa_handler = SIG_DFL;
+	(void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
+#else
+	signal(SIGHUP, SIG_IGN);
+	vhangup();
+	signal(SIGHUP, SIG_DFL);
+#endif
+#endif
+}
diff --git a/krb5-1-6/src/appl/libpty/void_assoc.c b/krb5-1-6/src/appl/libpty/void_assoc.c
new file mode 100644
index 000000000..a39c9c723
--- /dev/null
+++ b/krb5-1-6/src/appl/libpty/void_assoc.c
@@ -0,0 +1,49 @@
+/*
+ * ptyint_void_association(): Void association with controlling terminal
+ *
+ * Copyright 1995, 1996 by the Massachusetts Institute of Technology.
+ *
+ * 
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ * 
+ */
+
+#include "com_err.h"
+#include "libpty.h"
+#include "pty-int.h"
+
+/*
+ * This function gets called to set up the current process as a
+ * session leader (hence, can't be called except from a process that
+ * isn't already a session leader) and dissociates the controlling
+ * terminal (if any) from the session.
+ */
+long
+ptyint_void_association(void)
+{
+    int fd;
+#ifdef HAVE_SETSID
+    (void) setsid();
+#endif
+    /* Void tty association first */
+#ifdef TIOCNOTTY
+    fd = open("/dev/tty", O_RDWR);
+    if (fd >= 0) {
+	ioctl(fd, TIOCNOTTY, 0);
+	close(fd);
+    }
+#endif
+    return 0;
+}
diff --git a/krb5-1-6/src/appl/sample/Makefile.in b/krb5-1-6/src/appl/sample/Makefile.in
new file mode 100644
index 000000000..a580359e4
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/Makefile.in
@@ -0,0 +1,5 @@
+thisconfigdir=./..
+myfulldir=appl/sample
+mydir=sample
+LOCAL_SUBDIRS = sclient sserver
+BUILDTOP=$(REL)..$(S)..
diff --git a/krb5-1-6/src/appl/sample/sample.h b/krb5-1-6/src/appl/sample/sample.h
new file mode 100644
index 000000000..6c81d9351
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/sample.h
@@ -0,0 +1,36 @@
+/*
+ * appl/sample/sample.h
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Common definitions for the sample client/server.
+ */
+
+#ifndef KRB5_SAMPLE__
+#define KRB5_SAMPLE__
+
+#define SAMPLE_SERVICE "sample"
+#define SAMPLE_PORT "sample"
+#define SAMPLE_VERSION "KRB5_sample_protocol_v1.0"
+
+#endif /* KRB5_SAMPLE__ */
diff --git a/krb5-1-6/src/appl/sample/sclient/Makefile.in b/krb5-1-6/src/appl/sample/sclient/Makefile.in
new file mode 100644
index 000000000..868f678eb
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/sclient/Makefile.in
@@ -0,0 +1,19 @@
+thisconfigdir=./../..
+myfulldir=appl/sample/sclient
+mydir=sample/sclient
+
+BUILDTOP=$(REL)..$(S)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+all:: sclient
+
+sclient: sclient.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o sclient sclient.o $(KRB5_BASE_LIBS)
+
+clean::
+	$(RM) sclient.o sclient
+
+install::
+	$(INSTALL_PROGRAM) sclient ${DESTDIR}$(CLIENT_BINDIR)/sclient
+	$(INSTALL_DATA) $(srcdir)/sclient.M ${DESTDIR}$(CLIENT_MANDIR)/sclient.1
diff --git a/krb5-1-6/src/appl/sample/sclient/sclient.M b/krb5-1-6/src/appl/sample/sclient/sclient.M
new file mode 100644
index 000000000..1b5a8d6b7
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/sclient/sclient.M
@@ -0,0 +1,38 @@
+.\" appl/sample/sclient/sclient.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" 
+.\"
+.TH SCLIENT 1
+.SH NAME
+sclient \- sample Kerberos version 5 client
+.SH SYNOPSIS
+.B sclient
+.I remotehost
+.br
+.SH DESCRIPTION
+.I sclient
+will contact a sample server (\fIsserver\fR(8)) and authenticate to it
+using Kerberos version 5 tickets, then display the server's response.
+.SH SEE ALSO
+kinit(1), sserver(8)
+.SH BUGS
diff --git a/krb5-1-6/src/appl/sample/sclient/sclient.c b/krb5-1-6/src/appl/sample/sclient/sclient.c
new file mode 100644
index 000000000..6ad305a88
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/sclient/sclient.c
@@ -0,0 +1,255 @@
+/*
+ * appl/sample/sclient/sclient.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Sample Kerberos v5 client.
+ *
+ * Usage: sample_client hostname
+ */
+
+#include "krb5.h"
+#include "com_err.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "fake-addrinfo.h" /* not everyone implements getaddrinfo yet */
+
+#include <signal.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+
+#include "../sample.h"
+
+#ifndef GETSOCKNAME_ARG3_TYPE
+#define GETSOCKNAME_ARG3_TYPE int
+#endif
+
+static int
+net_read(fd, buf, len)
+    int fd;
+    char *buf;
+    int len;
+{
+    int cc, len2 = 0;
+
+    do {
+	cc = SOCKET_READ((SOCKET)fd, buf, len);
+	if (cc < 0) {
+	    if (SOCKET_ERRNO == SOCKET_EINTR)
+		continue;
+		
+		/* XXX this interface sucks! */
+        errno = SOCKET_ERRNO;    
+               
+	    return(cc);		 /* errno is already set */
+	}		
+	else if (cc == 0) {
+	    return(len2);
+	} else {
+	    buf += cc;
+	    len2 += cc;
+	    len -= cc;
+	}
+    } while (len > 0);
+    return(len2);
+}
+
+int
+main(int argc, char *argv[])
+{
+    struct addrinfo *ap, aihints, *apstart;
+    int aierr;
+    int sock;
+    krb5_context context;
+    krb5_data recv_data;
+    krb5_data cksum_data;
+    krb5_error_code retval;
+    krb5_ccache ccdef;
+    krb5_principal client, server;
+    krb5_error *err_ret;
+    krb5_ap_rep_enc_part *rep_ret;
+    krb5_auth_context auth_context = 0;
+    short xmitlen;
+    char *portstr;
+    char *service = SAMPLE_SERVICE;
+
+    if (argc != 2 && argc != 3 && argc != 4) {
+	fprintf(stderr, "usage: %s <hostname> [port] [service]\n",argv[0]);
+	exit(1);
+    }
+
+    retval = krb5_init_context(&context);
+    if (retval) {
+	    com_err(argv[0], retval, "while initializing krb5");
+	    exit(1);
+    }
+
+    (void) signal(SIGPIPE, SIG_IGN);
+
+    if (argc > 2)
+	portstr = argv[2];
+    else
+	portstr = SAMPLE_PORT;
+
+    memset(&aihints, 0, sizeof(aihints));
+    aihints.ai_socktype = SOCK_STREAM;
+    aierr = getaddrinfo(argv[1], portstr, &aihints, &ap);
+    if (aierr) {
+	fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: %s\n",
+		argv[0], argv[1], portstr, gai_strerror(aierr));
+	exit(1);
+    }
+    if (ap == 0) {
+	/* Should never happen.  */
+	fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: no addresses returned?\n",
+		argv[0], argv[1], portstr);
+	exit(1);
+    }
+
+    if (argc > 3) {
+	service = argv[3];
+    }
+
+    retval = krb5_sname_to_principal(context, argv[1], service,
+				     KRB5_NT_SRV_HST, &server);
+    if (retval) {
+	com_err(argv[0], retval, "while creating server name for host %s service %s",
+		argv[1], service);
+	exit(1);
+    }
+
+    /* set up the address of the foreign socket for connect() */
+    apstart = ap; /* For freeing later */
+    for (sock = -1; ap && sock == -1; ap = ap->ai_next) {
+	char abuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+	char mbuf[NI_MAXHOST + NI_MAXSERV + 64];
+	if (getnameinfo(ap->ai_addr, ap->ai_addrlen, abuf, sizeof(abuf),
+			pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+	    memset(abuf, 0, sizeof(abuf));
+	    strncpy(abuf, "[error, cannot print address?]",
+		    sizeof(abuf)-1);
+	    strcpy(pbuf, "[?]");
+	}
+	sprintf(mbuf, "error contacting %s port %s", abuf, pbuf);
+	sock = socket(ap->ai_family, SOCK_STREAM, 0);
+	if (sock < 0) {
+	    fprintf(stderr, "%s: socket: %s\n", mbuf, strerror(errno));
+	    continue;
+	}
+	if (connect(sock, ap->ai_addr, ap->ai_addrlen) < 0) {
+	    fprintf(stderr, "%s: connect: %s\n", mbuf, strerror(errno));
+	    close(sock);
+	    sock = -1;
+	    continue;
+	}
+	/* connected, yay! */
+    }
+    if (sock == -1)
+	/* Already printed error message above.  */
+	exit(1);
+    printf("connected\n");
+
+    cksum_data.data = argv[1];
+    cksum_data.length = strlen(argv[1]);
+
+    retval = krb5_cc_default(context, &ccdef);
+    if (retval) {
+	com_err(argv[0], retval, "while getting default ccache");
+	exit(1);
+    }
+
+    retval = krb5_cc_get_principal(context, ccdef, &client);
+    if (retval) {
+	com_err(argv[0], retval, "while getting client principal name");
+	exit(1);
+    }
+    retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &sock,
+			   SAMPLE_VERSION, client, server,
+			   AP_OPTS_MUTUAL_REQUIRED,
+			   &cksum_data,
+			   0,		/* no creds, use ccache instead */
+			   ccdef, &err_ret, &rep_ret, NULL);
+
+    krb5_free_principal(context, server);	/* finished using it */
+    krb5_free_principal(context, client);      
+    krb5_cc_close(context, ccdef);
+    if (auth_context) krb5_auth_con_free(context, auth_context);
+
+    if (retval && retval != KRB5_SENDAUTH_REJECTED) {
+	com_err(argv[0], retval, "while using sendauth");
+	exit(1);
+    }
+    if (retval == KRB5_SENDAUTH_REJECTED) {
+	/* got an error */
+	printf("sendauth rejected, error reply is:\n\t\"%*s\"\n",
+	       err_ret->text.length, err_ret->text.data);
+    } else if (rep_ret) {
+	/* got a reply */
+	krb5_free_ap_rep_enc_part(context, rep_ret);
+
+	printf("sendauth succeeded, reply is:\n");
+	if ((retval = net_read(sock, (char *)&xmitlen,
+			       sizeof(xmitlen))) <= 0) {
+	    if (retval == 0)
+		errno = ECONNABORTED;
+	    com_err(argv[0], errno, "while reading data from server");
+	    exit(1);
+	}
+	recv_data.length = ntohs(xmitlen);
+	if (!(recv_data.data = (char *)malloc((size_t) recv_data.length + 1))) {
+	    com_err(argv[0], ENOMEM,
+		    "while allocating buffer to read from server");
+	    exit(1);
+	}
+	if ((retval = net_read(sock, (char *)recv_data.data,
+			       recv_data.length)) <= 0) {
+	    if (retval == 0)
+		errno = ECONNABORTED;
+	    com_err(argv[0], errno, "while reading data from server");
+	    exit(1);
+	}
+	recv_data.data[recv_data.length] = '\0';
+	printf("reply len %d, contents:\n%s\n",
+	       recv_data.length,recv_data.data);
+	free(recv_data.data);
+    } else {
+	com_err(argv[0], 0, "no error or reply from sendauth!");
+	exit(1);
+    }
+    freeaddrinfo(apstart);
+    krb5_free_context(context);
+    exit(0);
+}
diff --git a/krb5-1-6/src/appl/sample/sserver/Makefile.in b/krb5-1-6/src/appl/sample/sserver/Makefile.in
new file mode 100644
index 000000000..32e8864ef
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/sserver/Makefile.in
@@ -0,0 +1,19 @@
+thisconfigdir=./../..
+myfulldir=appl/sample/sserver
+mydir=sample/sserver
+
+BUILDTOP=$(REL)..$(S)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+all:: sserver
+
+sserver: sserver.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o sserver sserver.o $(KRB5_BASE_LIBS)
+
+clean::
+	$(RM) sserver.o sserver
+
+install::
+	$(INSTALL_PROGRAM) sserver ${DESTDIR}$(SERVER_BINDIR)/sserver
+	$(INSTALL_DATA) $(srcdir)/sserver.M ${DESTDIR}$(SERVER_MANDIR)/sserver.8
diff --git a/krb5-1-6/src/appl/sample/sserver/sserver.M b/krb5-1-6/src/appl/sample/sserver/sserver.M
new file mode 100644
index 000000000..4323fd11b
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/sserver/sserver.M
@@ -0,0 +1,130 @@
+.\" appl/sample/sserver/sserver.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH SSERVER 8
+.SH NAME
+sserver \- sample Kerberos version 5 server
+.SH SYNOPSIS
+.B sserver
+[
+.I \-p
+port ] [
+.I \-S
+keytab ] [
+.I server_port
+]
+.br
+.SH DESCRIPTION
+
+\fIsserver\fP and \fIsclient\fP are a simple demonstration
+client/server application.  When \fIsclient\fP connects to
+\fIsserver\fP, it performs a Kerberos authentication, and then
+\fIsserver\fP returns to \fIsclient\fP the Kerberos
+principal which was used for the Kerberos authentication.  It makes a
+good test that Kerberos has been successfully installed on a machine.
+.PP
+The service name used by \fIsserver\fP and \fIsclient\fP is
+\fBsample\fP.  Hence, \fIsserver\fP will require that there be a keytab
+entry for the service "sample/hostname.domain.name@REALM.NAME".  This
+keytab is generated using the
+.IR kadmin(8)
+program.  The keytab file is usually installed as "/etc/krb5.keytab".
+.PP
+The 
+.B \-S
+option allows for a different keytab than the default.
+.PP
+\fIsserver\fP is normally invoked out of 
+.IR inetd(8), 
+using a line in
+/etc/inetd.conf that looks like this:
+.PP
+sample  stream  tcp     nowait  root /usr/local/sbin/sserver	sserver
+.PP
+Since \fBsample\fP is normally not a port defined in /etc/services, you will
+usually have to add a line to /etc/services which looks like this:
+.PP
+sample          13135/tcp
+.PP
+When using \fIsclient,\fP you will first have to have an entry in the Kerberos
+database, by using 
+.IR kadmin(8),
+and then you have to get Kerberos
+tickets, by using 
+.IR kinit(8).  
+Also, if you are running the \fIsclient\fP
+program on a different host than the \fIsserver\fP it will be
+connecting to, be
+sure that both hosts have an entry in /etc/services for the \fBsample\fP tcp
+port, and that the same port number is in both files.
+.PP
+When you run sclient you should see something like this:
+.PP
+sendauth succeeded, reply is:
+.br
+reply len 32, contents:
+.br
+You are nlgilman@JIMI.MIT.EDU
+.br
+.SH COMMON ERROR MESSAGES
+
+1)  \fIkinit\fP returns the error:
+.PP
+kinit: Client not found in Kerberos database while getting initial credentials
+.PP
+This means that you didn't create an entry for your username in the
+Kerberos database.
+.PP
+2)  \fIsclient\fP returns the error:
+.PP
+unknown service sample/tcp; check /etc/services
+.PP
+This means that you don't have an entry in /etc/services for the
+\fBsample\fP tcp port.
+.PP
+3)  \fIsclient\fP returns the error:
+.PP
+connect: Connection refused
+.PP
+This probably means you didn't edit /etc/inetd.conf correctly, or you
+didn't restart \fIinetd\fP after editing inetd.conf.
+.PP
+4)  \fIsclient\fP returns the error:
+.PP
+sclient: Server not found in Kerberos database while using sendauth
+.PP
+This means that the "sample/hostname@LOCAL.REALM" service was not
+defined in the Kerberos database; it should be created using \fIkadmin,\fP
+and a keytab file needs to be generated to make the key for that service
+principal available for \fIssclient\fP.
+.PP
+5)  \fIsclient\fP returns the error:
+.PP
+sendauth rejected, error reply is:
+        " No such file or directory"
+.PP
+This probably means \fIsserver\fP couldn't find the keytab file.  It was
+probably not installed in the proper directory.
+.br
+.SH SEE ALSO
+sclient(1), services(5), inetd(8)
diff --git a/krb5-1-6/src/appl/sample/sserver/sserver.c b/krb5-1-6/src/appl/sample/sserver/sserver.c
new file mode 100644
index 000000000..4bbcdda2d
--- /dev/null
+++ b/krb5-1-6/src/appl/sample/sserver/sserver.c
@@ -0,0 +1,242 @@
+/*
+ * appl/sample/sserver/sserver.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Sample Kerberos v5 server.
+ *
+ * sample_server:
+ * A sample Kerberos server, which reads an AP_REQ from a TCP socket,
+ * decodes it, and writes back the results (in ASCII) to the client.
+ *
+ * Usage:
+ * sample_server servername
+ *
+ * file descriptor 0 (zero) should be a socket connected to the requesting
+ * client (this will be correct if this server is started by inetd).
+ */
+
+#include "krb5.h"
+#include "com_err.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <syslog.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "../sample.h"
+
+extern krb5_deltat krb5_clockskew;
+
+#ifndef GETPEERNAME_ARG3_TYPE
+#define GETPEERNAME_ARG3_TYPE int
+#endif
+
+#define DEBUG
+
+static void
+usage(name)
+    char *name;
+{
+	fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n",
+		name);
+}	
+
+int
+main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_context context;
+    krb5_auth_context auth_context = NULL;
+    krb5_ticket * ticket;
+    struct sockaddr_in peername;
+    GETPEERNAME_ARG3_TYPE  namelen = sizeof(peername);
+    int sock = -1;			/* incoming connection fd */
+    krb5_data recv_data;
+    short xmitlen;
+    krb5_error_code retval;
+    krb5_principal server;
+    char repbuf[BUFSIZ];
+    char *cname;
+    char *service = SAMPLE_SERVICE;
+    short port = 0;		/* If user specifies port */
+    extern int opterr, optind;
+    extern char * optarg;
+    int ch;
+    krb5_keytab keytab = NULL;	/* Allow specification on command line */
+    char *progname;
+    int on = 1;
+
+    progname = *argv;
+
+    retval = krb5_init_context(&context);
+    if (retval) {
+	    com_err(argv[0], retval, "while initializing krb5");
+	    exit(1);
+    }
+
+    /* open a log connection */
+    openlog("sserver", 0, LOG_DAEMON);
+
+    /*
+     * Parse command line arguments
+     *  
+     */
+    opterr = 0;
+    while ((ch = getopt(argc, argv, "p:S:s:")) != -1)
+    switch (ch) {
+    case 'p':
+	port = atoi(optarg);
+	break;
+    case 's':
+	service = optarg;
+	break;
+    case 'S':
+	if ((retval = krb5_kt_resolve(context, optarg, &keytab))) {
+	    com_err(progname, retval,
+		    "while resolving keytab file %s", optarg);
+	    exit(2);
+	}
+	break;
+
+      case '?':
+    default:
+	usage(progname);
+	exit(1);
+	break;
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    /* Backwards compatibility, allow port to be specified at end */
+    if (argc > 1) {
+	    port = atoi(argv[1]);
+    }
+
+    retval = krb5_sname_to_principal(context, NULL, service, 
+				     KRB5_NT_SRV_HST, &server);
+    if (retval) {
+	syslog(LOG_ERR, "while generating service name (%s): %s",
+	       service, error_message(retval));
+	exit(1);
+    }
+    
+    /*
+     * If user specified a port, then listen on that port; otherwise,
+     * assume we've been started out of inetd. 
+     */
+
+    if (port) {
+	int acc;
+	struct sockaddr_in sockin;
+
+	if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+	    syslog(LOG_ERR, "socket: %m");
+	    exit(3);
+	}
+	/* Let the socket be reused right away */
+	(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
+			  sizeof(on));
+
+	sockin.sin_family = AF_INET;
+	sockin.sin_addr.s_addr = 0;
+	sockin.sin_port = htons(port);
+	if (bind(sock, (struct sockaddr *) &sockin, sizeof(sockin))) {
+	    syslog(LOG_ERR, "bind: %m");
+	    exit(3);
+	}
+	if (listen(sock, 1) == -1) {
+	    syslog(LOG_ERR, "listen: %m");
+	    exit(3);
+	}
+	if ((acc = accept(sock, (struct sockaddr *)&peername, &namelen)) == -1){
+	    syslog(LOG_ERR, "accept: %m");
+	    exit(3);
+	}
+	dup2(acc, 0);
+	close(sock);
+	sock = 0;
+    } else {
+	/*
+	 * To verify authenticity, we need to know the address of the
+	 * client.
+	 */
+	if (getpeername(0, (struct sockaddr *)&peername, &namelen) < 0) {
+	    syslog(LOG_ERR, "getpeername: %m");
+	    exit(1);
+	}
+	sock = 0;
+    }
+
+    retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock,
+			   SAMPLE_VERSION, server, 
+			   0,	/* no flags */
+			   keytab,	/* default keytab is NULL */
+			   &ticket);
+    if (retval) {
+	syslog(LOG_ERR, "recvauth failed--%s", error_message(retval));
+	exit(1);
+    }
+
+    /* Get client name */
+    retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname);
+    if (retval){
+	syslog(LOG_ERR, "unparse failed: %s", error_message(retval));
+        sprintf(repbuf, "You are <unparse error>\n");
+    } else {
+        sprintf(repbuf, "You are %s\n", cname);
+	free(cname);
+    }
+    xmitlen = htons(strlen(repbuf));
+    recv_data.length = strlen(repbuf);
+    recv_data.data = repbuf;
+    if ((retval = krb5_net_write(context, 0, (char *)&xmitlen,
+				 sizeof(xmitlen))) < 0) {
+	syslog(LOG_ERR, "%m: while writing len to client");
+	exit(1);
+    }
+    if ((retval = krb5_net_write(context, 0, (char *)recv_data.data,
+				 recv_data.length)) < 0) {
+	syslog(LOG_ERR, "%m: while writing data to client");
+	exit(1);
+    }
+
+    krb5_free_ticket(context, ticket);
+    if(keytab)
+      krb5_kt_close(context, keytab);
+    krb5_free_principal(context, server);
+    krb5_auth_con_free(context, auth_context);
+    krb5_free_context(context);
+    exit(0);
+}
diff --git a/krb5-1-6/src/appl/simple/Makefile.in b/krb5-1-6/src/appl/simple/Makefile.in
new file mode 100644
index 000000000..9e6f16da2
--- /dev/null
+++ b/krb5-1-6/src/appl/simple/Makefile.in
@@ -0,0 +1,5 @@
+thisconfigdir=./..
+myfulldir=appl/simple
+mydir=simple
+LOCAL_SUBDIRS = client server
+BUILDTOP=$(REL)..$(S)..
diff --git a/krb5-1-6/src/appl/simple/client/Makefile.in b/krb5-1-6/src/appl/simple/client/Makefile.in
new file mode 100644
index 000000000..c7023ca1d
--- /dev/null
+++ b/krb5-1-6/src/appl/simple/client/Makefile.in
@@ -0,0 +1,19 @@
+thisconfigdir=./../..
+myfulldir=appl/simple/client
+mydir=simple/client
+BUILDTOP=$(REL)..$(S)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+all:: sim_client
+
+LOCALINCLUDES= -I.. -I$(srcdir)/..
+
+sim_client: sim_client.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o sim_client sim_client.o $(KRB5_BASE_LIBS)
+
+install::
+	$(INSTALL_PROGRAM) sim_client $(DESTDIR)$(CLIENT_BINDIR)/sim_client
+
+clean::
+	$(RM) sim_client.o sim_client
diff --git a/krb5-1-6/src/appl/simple/client/sim_client.c b/krb5-1-6/src/appl/simple/client/sim_client.c
new file mode 100644
index 000000000..d9a40dc82
--- /dev/null
+++ b/krb5-1-6/src/appl/simple/client/sim_client.c
@@ -0,0 +1,332 @@
+/*
+ * appl/simple/client/sim_client.c
+ *
+ * Copyright 1989,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Simple UDP-based sample client program.  For demonstration.
+ * This program performs no useful function.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <krb5.h>
+#include "com_err.h"
+
+#include "simple.h"
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* for old Unixes and friends ... */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#define MSG "hi there!"			/* message text */
+
+void usage (char *);
+
+void
+usage(name)
+    char *name;
+{
+	fprintf(stderr, "usage: %s [-p port] [-h host] [-m message] [-s service] [host]\n", name);
+}	
+
+int
+main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int sock, i;
+    unsigned int len;
+    int flags = 0;			/* flags for sendto() */
+    struct servent *serv;
+    struct hostent *host;
+    char *cp;
+    char full_hname[MAXHOSTNAMELEN];
+#ifdef BROKEN_STREAMS_SOCKETS
+    char my_hostname[MAXHOSTNAMELEN];
+#endif
+    struct sockaddr_in s_sock;		/* server address */
+    struct sockaddr_in c_sock;		/* client address */
+    extern int opterr, optind;
+    extern char * optarg;
+    int	ch;
+    
+    short port = 0;
+    char *message = MSG;
+    char *hostname = 0;
+    char *service = SIMPLE_SERVICE;
+    char *progname = 0;
+
+    krb5_error_code retval;
+    krb5_data packet, inbuf;
+    krb5_ccache ccdef;
+    krb5_address addr, *portlocal_addr;
+    krb5_rcache rcache;
+    krb5_data	rcache_name;
+
+    krb5_context 	  context;
+    krb5_auth_context 	  auth_context = NULL;
+
+    retval = krb5_init_context(&context);
+    if (retval) {
+	    com_err(argv[0], retval, "while initializing krb5");
+	    exit(1);
+    }
+
+    progname = argv[0];
+
+    /*
+     * Parse command line arguments
+     *  
+     */
+    opterr = 0;
+    while ((ch = getopt(argc, argv, "p:m:h:s:")) != -1)
+    switch (ch) {
+    case 'p':
+	port = atoi(optarg);
+	break;
+    case 'm':
+	message = optarg;
+	break;
+    case 'h':
+	hostname = optarg;
+	break;
+    case 's':
+	service = optarg;
+	break;
+    case '?':
+    default:
+	usage(progname);
+	exit(1);
+	break;
+    }
+    argc -= optind;
+    argv += optind;
+    if (argc > 0) {
+	if (hostname)
+	    usage(progname);
+	hostname = argv[0];
+    }
+
+    if (hostname == 0) {
+	fprintf(stderr, "You must specify a hostname to contact.\n\n");
+	usage(progname);
+	exit(1);
+    }
+
+    /* Look up server host */
+    if ((host = gethostbyname(hostname)) == (struct hostent *) 0) {
+	fprintf(stderr, "%s: unknown host\n", hostname);
+	exit(1);
+    }
+    strncpy(full_hname, host->h_name, sizeof(full_hname)-1);
+    full_hname[sizeof(full_hname)-1] = '\0';
+
+    /* lower-case to get name for "instance" part of service name */
+    for (cp = full_hname; *cp; cp++)
+        if (isupper((int) *cp))
+            *cp = tolower((int) *cp);
+
+    /* Set server's address */
+    (void) memset((char *)&s_sock, 0, sizeof(s_sock));
+
+    memcpy((char *)&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr));
+#ifdef DEBUG
+    printf("s_sock.sin_addr is %s\n", inet_ntoa(s_sock.sin_addr));
+#endif
+    s_sock.sin_family = AF_INET;
+
+    if (port == 0) {
+	/* Look up service */
+	if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) {
+	    fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT);
+	    exit(1);
+	}
+	s_sock.sin_port = serv->s_port;
+    } else {
+	s_sock.sin_port = htons(port);
+    }
+
+    /* Open a socket */
+    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	com_err(progname, errno, "opening datagram socket");
+	exit(1);
+    }
+
+    memset((char *)&c_sock, 0, sizeof(c_sock));
+    c_sock.sin_family = AF_INET;
+#ifdef BROKEN_STREAMS_SOCKETS
+    if (gethostname(my_hostname, sizeof(my_hostname)) < 0) {
+	perror("gethostname");
+	exit(1);
+    }
+
+    if ((host = gethostbyname(my_hostname)) == (struct hostent *)0) {
+	fprintf(stderr, "%s: unknown host\n", hostname);
+	exit(1);
+    }
+    memcpy((char *)&c_sock.sin_addr, host->h_addr, sizeof(c_sock.sin_addr));
+#endif
+    
+
+    /* Bind it to set the address; kernel will fill in port # */
+    if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) {
+	com_err(progname, errno, "while binding datagram socket");
+	exit(1);
+    }
+	
+    /* PREPARE KRB_AP_REQ MESSAGE */
+
+    inbuf.data = hostname;
+    inbuf.length = strlen(hostname);
+
+    /* Get credentials for server */
+    if ((retval = krb5_cc_default(context, &ccdef))) {
+	com_err(progname, retval, "while getting default ccache");
+	exit(1);
+    }
+
+    if ((retval = krb5_mk_req(context, &auth_context, 0, service, full_hname,
+			      &inbuf, ccdef, &packet))) {
+	com_err(progname, retval, "while preparing AP_REQ");
+	exit(1);
+    }
+    printf("Got credentials for %s.\n", service);
+
+    /* "connect" the datagram socket; this is necessary to get a local address
+       properly bound for getsockname() below. */
+
+    if (connect(sock, (struct sockaddr *)&s_sock, sizeof(s_sock)) == -1) {
+	com_err(progname, errno, "while connecting to server");
+	exit(1);
+    }
+    /* Send authentication info to server */
+    if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, 
+		  flags)) < 0) 
+	com_err(progname, errno, "while sending KRB_AP_REQ message");
+    printf("Sent authentication data: %d bytes\n", i);
+    krb5_free_data_contents(context, &packet);
+
+    /* PREPARE KRB_SAFE MESSAGE */
+
+    /* Get my address */
+    memset((char *) &c_sock, 0, sizeof(c_sock));
+    len = sizeof(c_sock);
+    if (getsockname(sock, (struct sockaddr *)&c_sock, &len) < 0) {
+	com_err(progname, errno, "while getting socket name");
+	exit(1);
+    }
+
+    addr.addrtype = ADDRTYPE_IPPORT;
+    addr.length = sizeof(c_sock.sin_port);
+    addr.contents = (krb5_octet *)&c_sock.sin_port;
+    if ((retval = krb5_auth_con_setports(context, auth_context,
+					 &addr, NULL))) {
+	com_err(progname, retval, "while setting local port\n");
+	exit(1);
+    }
+
+    addr.addrtype = ADDRTYPE_INET;
+    addr.length = sizeof(c_sock.sin_addr);
+    addr.contents = (krb5_octet *)&c_sock.sin_addr;
+    if ((retval = krb5_auth_con_setaddrs(context, auth_context,
+					 &addr, NULL))) {
+	com_err(progname, retval, "while setting local addr\n");
+	exit(1);
+    }
+
+    /* THIS IS UGLY */
+    if ((retval = krb5_gen_portaddr(context, &addr,
+				    (krb5_pointer) &c_sock.sin_port,
+				    &portlocal_addr))) {
+	com_err(progname, retval, "while generating port address");
+	exit(1);
+    }
+    
+    if ((retval = krb5_gen_replay_name(context,portlocal_addr,
+				       "_sim_clt",&cp))) {
+	com_err(progname, retval, "while generating replay cache name");
+	exit(1);
+    }
+
+    rcache_name.length = strlen(cp);
+    rcache_name.data = cp;
+
+    if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) {
+	com_err(progname, retval, "while getting server rcache");
+	exit(1);
+    }
+
+    /* set auth_context rcache */
+    krb5_auth_con_setrcache(context, auth_context, rcache);
+
+    /* Make the safe message */
+    inbuf.data = message;
+    inbuf.length = strlen(message);
+
+    if ((retval = krb5_mk_safe(context, auth_context, &inbuf, &packet, NULL))){
+	com_err(progname, retval, "while making KRB_SAFE message");
+	exit(1);
+    }
+
+    /* Send it */
+    if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, 
+		  flags)) < 0)
+	com_err(progname, errno, "while sending SAFE message");
+    printf("Sent checksummed message: %d bytes\n", i);
+    krb5_free_data_contents(context, &packet);
+
+    /* PREPARE KRB_PRIV MESSAGE */
+
+    /* Make the encrypted message */
+    if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+			       &packet, NULL))) {
+	com_err(progname, retval, "while making KRB_PRIV message");
+	exit(1);
+    }
+
+    /* Send it */
+    if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, 
+		  flags)) < 0)
+	com_err(progname, errno, "while sending PRIV message");
+    printf("Sent encrypted message: %d bytes\n", i);
+    krb5_free_data_contents(context, &packet);
+
+    krb5_auth_con_free(context, auth_context);
+    krb5_free_context(context);
+    
+    exit(0);
+}
diff --git a/krb5-1-6/src/appl/simple/server/Makefile.in b/krb5-1-6/src/appl/simple/server/Makefile.in
new file mode 100644
index 000000000..d670edaa7
--- /dev/null
+++ b/krb5-1-6/src/appl/simple/server/Makefile.in
@@ -0,0 +1,20 @@
+thisconfigdir=./../..
+myfulldir=appl/simple/server
+mydir=simple/server
+BUILDTOP=$(REL)..$(S)..$(S)..
+
+LOCALINCLUDES= -I.. -I$(srcdir)/..
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+all:: sim_server
+
+sim_server: sim_server.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o sim_server sim_server.o $(KRB5_BASE_LIBS)
+
+install::
+	$(INSTALL_PROGRAM) sim_server $(DESTDIR)$(SERVER_BINDIR)/sim_server
+
+clean::
+	$(RM) sim_server.o sim_server
diff --git a/krb5-1-6/src/appl/simple/server/sim_server.c b/krb5-1-6/src/appl/simple/server/sim_server.c
new file mode 100644
index 000000000..137cc49f0
--- /dev/null
+++ b/krb5-1-6/src/appl/simple/server/sim_server.c
@@ -0,0 +1,279 @@
+/*
+ * appl/simple/server/sim_server.c
+ *
+ * Copyright 1989,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Usage:
+ * sample_server servername
+ *
+ * Simple UDP-based server application.  For demonstration.
+ * This program performs no useful function.
+ */
+
+#include "krb5.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "com_err.h"
+
+#include "simple.h"
+
+/* for old Unixes and friends ... */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#define PROGNAME argv[0]
+
+static void
+usage(name)
+    char *name;
+{
+	fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n", name);
+}	
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    int sock, i;
+    unsigned int len;
+    int flags = 0;			/* for recvfrom() */
+    int on = 1;
+    struct servent *serv;
+    struct hostent *host;
+    struct sockaddr_in s_sock;		/* server's address */
+    struct sockaddr_in c_sock;		/* client's address */
+    char full_hname[MAXHOSTNAMELEN];
+    char *cp;
+    extern int opterr, optind;
+    extern char * optarg;
+    int	ch;
+
+    short port = 0;		/* If user specifies port */
+    krb5_keytab keytab = NULL;	/* Allow specification on command line */
+    char *service = SIMPLE_SERVICE;
+
+    krb5_error_code retval;
+    krb5_data packet, message;
+    unsigned char pktbuf[BUFSIZ];
+    krb5_principal sprinc;
+    krb5_context context;
+    krb5_auth_context auth_context = NULL;
+    krb5_address addr;
+    krb5_ticket *ticket = NULL;
+
+    retval = krb5_init_context(&context);
+    if (retval) {
+	    com_err(argv[0], retval, "while initializing krb5");
+	    exit(1);
+    }
+
+    /*
+     * Parse command line arguments
+     *  
+     */
+    opterr = 0;
+    while ((ch = getopt(argc, argv, "p:s:S:")) != -1)
+    switch (ch) {
+    case 'p':
+	port = atoi(optarg);
+	break;
+    case 's':
+	service = optarg;
+	break;
+    case 'S':
+	if ((retval = krb5_kt_resolve(context, optarg, &keytab))) {
+	    com_err(PROGNAME, retval,
+		    "while resolving keytab file %s", optarg);
+	    exit(2);
+	}
+	break;
+
+    case '?':
+    default:
+	usage(PROGNAME);
+	exit(1);
+	break;
+    }
+
+    if ((retval = krb5_sname_to_principal(context, NULL, service, 
+					  KRB5_NT_SRV_HST, &sprinc))) {
+	com_err(PROGNAME, retval, "while generating service name %s", service);
+	exit(1);
+    }
+
+    /* Set up server address */
+    memset((char *)&s_sock, 0, sizeof(s_sock));
+    s_sock.sin_family = AF_INET;
+
+    if (port == 0) {
+	/* Look up service */
+	if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) {
+	    fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT);
+	    exit(1);
+	}
+	s_sock.sin_port = serv->s_port;
+    } else {
+	s_sock.sin_port = htons(port);
+    }
+    
+    if (gethostname(full_hname, sizeof(full_hname)) < 0) {
+	perror("gethostname");
+	exit(1);
+    }
+
+    if ((host = gethostbyname(full_hname)) == (struct hostent *)0) {
+	fprintf(stderr, "%s: host unknown\n", full_hname);
+	exit(1);
+    }
+    memcpy((char *)&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr));
+
+    /* Open socket */
+    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	perror("opening datagram socket");
+	exit(1);
+    }
+
+     /* Let the socket be reused right away */
+     (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
+		       sizeof(on));
+
+    /* Bind the socket */
+    if (bind(sock, (struct sockaddr *)&s_sock, sizeof(s_sock))) {
+	perror("binding datagram socket");
+	exit(1);
+    }
+
+#ifdef DEBUG
+    printf("socket has port # %d\n", ntohs(s_sock.sin_port));
+#endif
+
+    /* GET KRB_AP_REQ MESSAGE */
+
+    /* use "recvfrom" so we know client's address */
+    len = sizeof(struct sockaddr_in);
+    if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
+		 (struct sockaddr *)&c_sock, &len)) < 0) {
+	perror("receiving datagram");
+	exit(1);
+    }
+
+    printf("Received %d bytes\n", i);
+    packet.length = i;
+    packet.data = (krb5_pointer) pktbuf;
+
+    /* Check authentication info */
+    if ((retval = krb5_rd_req(context, &auth_context, &packet, 
+			      sprinc, keytab, NULL, &ticket))) {
+	com_err(PROGNAME, retval, "while reading request");
+	exit(1);
+    }
+    if ((retval = krb5_unparse_name(context, ticket->enc_part2->client,
+				    &cp))) {
+	com_err(PROGNAME, retval, "while unparsing client name");
+	exit(1);
+    }
+    printf("Got authentication info from %s\n", cp);
+    free(cp);
+
+    /* Set foreign_addr for rd_safe() and rd_priv() */
+    addr.addrtype = ADDRTYPE_INET;
+    addr.length = sizeof(c_sock.sin_addr);
+    addr.contents = (krb5_octet *)&c_sock.sin_addr;
+    if ((retval = krb5_auth_con_setaddrs(context, auth_context,
+					 NULL, &addr))) {
+	com_err(PROGNAME, retval, "while setting foreign addr");
+        exit(1);
+    }
+
+    addr.addrtype = ADDRTYPE_IPPORT;
+    addr.length = sizeof(c_sock.sin_port);
+    addr.contents = (krb5_octet *)&c_sock.sin_port;
+    if ((retval = krb5_auth_con_setports(context, auth_context,
+					 NULL, &addr))) {
+	com_err(PROGNAME, retval, "while setting foreign port");
+        exit(1);
+    }
+
+    /* GET KRB_MK_SAFE MESSAGE */
+
+    /* use "recvfrom" so we know client's address */
+    len = sizeof(struct sockaddr_in);
+    if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
+		 (struct sockaddr *)&c_sock, &len)) < 0) {
+	perror("receiving datagram");
+	exit(1);
+    }
+#ifdef DEBUG
+    printf("&c_sock.sin_addr is %s\n", inet_ntoa(c_sock.sin_addr));
+#endif
+    printf("Received %d bytes\n", i);
+
+    packet.length = i;
+    packet.data = (krb5_pointer) pktbuf;
+
+    if ((retval = krb5_rd_safe(context, auth_context, &packet,
+			       &message, NULL))) {
+	com_err(PROGNAME, retval, "while verifying SAFE message");
+	exit(1);
+    }
+    printf("Safe message is: '%.*s'\n", (int) message.length, message.data);
+
+    krb5_free_data_contents(context, &message);
+
+    /* NOW GET ENCRYPTED MESSAGE */
+
+    /* use "recvfrom" so we know client's address */
+    len = sizeof(struct sockaddr_in);
+    if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags,
+		      (struct sockaddr *)&c_sock, &len)) < 0) {
+	perror("receiving datagram");
+	exit(1);
+    }
+    printf("Received %d bytes\n", i);
+
+    packet.length = i;
+    packet.data = (krb5_pointer) pktbuf;
+    
+    if ((retval = krb5_rd_priv(context, auth_context, &packet,
+			       &message, NULL))) {
+	com_err(PROGNAME, retval, "while verifying PRIV message");
+	exit(1);
+    }
+    printf("Decrypted message is: '%.*s'\n", (int) message.length, 
+	   message.data);
+
+    krb5_auth_con_free(context, auth_context);
+    krb5_free_context(context);
+
+    exit(0);
+}
diff --git a/krb5-1-6/src/appl/simple/simple.h b/krb5-1-6/src/appl/simple/simple.h
new file mode 100644
index 000000000..f230592e6
--- /dev/null
+++ b/krb5-1-6/src/appl/simple/simple.h
@@ -0,0 +1,32 @@
+/*
+ * appl/simple/simple.h
+ *
+ * Copyright 1988,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Common definitions for the simple UDP-based Kerberos-mediated
+ * server & client applications.
+ */
+
+#define SIMPLE_SERVICE	"sample"
+#define SIMPLE_PORT	"sample"
diff --git a/krb5-1-6/src/appl/telnet/Config.generic b/krb5-1-6/src/appl/telnet/Config.generic
new file mode 100644
index 000000000..c6f88a52b
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/Config.generic
@@ -0,0 +1,830 @@
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted provided
+# that: (1) source distributions retain this entire copyright notice and
+# comment, and (2) distributions including binaries display the following
+# acknowledgement:  ``This product includes software developed by the
+# University of California, Berkeley and its contributors'' in the
+# documentation or other materials provided with the distribution and in
+# all advertising materials mentioning features or use of this software.
+# Neither the name of the University nor the names of its contributors may
+# be used to endorse or promote products derived from this software without
+# specific prior written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+#	@(#)Config.generic	5.5 (Berkeley) 3/1/91
+#
+
+# This is the configuration file for building all of
+# telnet/telnetd/libtelnet.  If you want to add your
+# own local configuration for a specific machine that
+# is already listed here, it is best to create a new
+# file called "Config.local", and put the definitions
+# there.  If you are adding definitions for a new system
+# type, you can add them here.  In this case, please send
+# the new definition, and any changes you have to make to
+# the code, back to "dab@cray.com" so that your changes
+# can be put into the next release.
+#
+# Each definition must have the form:
+#
+#	<target>:
+#		make -f Makefile.generic ${WHAT} \
+#			<definitions>
+
+# DEFINES=
+#
+#    Variables to be defined when actually compiling the source.  Defined
+#    as: DEFINES="-D<var> -D<var2> ... -D<varn>"
+#
+#    TELNET/TELNETD CONFIGURATION
+#
+# 	LINEMODE	Turns on support in telnetd for the linemode option.
+#			(Linemode is always on in the client).
+#
+#	KLUDGELINEMODE	Define this to get the kludged up version of linemode
+#			that was in 4.3BSD.  This is a good thing to have
+#			around for talking to older systems.  This has no
+#			effect on telnetd if LINEMODE has not been defined.
+#
+#	DIAGNOSTICS	Turns on diagnostic code in telnetd; adds extra
+#			logic and checks, and debuging output if started
+#			with the -D option.
+#
+#	NO_URGENT	Define this if you don't want telnetd to send
+#			IAC DM in urgent mode when the pty output queue
+#			is flushed.
+#
+#	GENERATE_GA	Turns on code to allow the generation of Go Ahead(GA)
+#			if the server is WONT SGA.  This code is imprecise,
+#			it generates the GA when two seconds have elapsed
+#			and no input or output has occurred.
+#
+#	AUTHENTICATION	Enable the AUTHENTICATION option.
+#
+#	ENCRYPTION	Enable the ENCRYPT option.
+#
+#	KRB4		Enable Kerberos Version 4 Authentication code
+#			in libtelnet/libtelnet.a
+#
+#	KRB5		Enable Kerberos Version 5 Authentication code
+#			in libtelnet/libtelnet.a
+#
+#	SPX		Enable SPX authentication code in.
+#			libtelnet/libtelnet.a
+#
+#	RSA_ENCPWD
+#
+#	KRB4_ENCPWD
+#
+#
+#	DES_ENCRYPTION	Enable DES encryption/decryption, requires
+#			getting a the initial key from Kerberos.  This
+#			works with both Kerberos Version 4 and 5.
+#
+#	ENV_HACK	Turn on code to recognize and allow
+#			interoperability with systems that have their
+#			definitions for ENV_VALUE and ENV_VAR reversed.
+#
+#    LOCAL SYSYTEM PARAMATERS
+#
+#	TERMCAP		Define this if your system is termcap based,
+#			otherwise a terminfo based system is assumed.
+#
+#	SYSV_TERMIO	Use the System V termio structure. (implies USE_TERMIO)
+#
+#	NO_CC_T		Define this if your termio.h file does not have
+#			a typedef for cc_t.
+#
+#	USE_TERMIO	Define this if you have the POSIX termios structures.
+#			This code works under the BSD 4.4 terminal driver.
+#
+#	HAS_GETTOS	Define this if you have the setsockopt() option for
+#			setting the IP Type Of Service bits, (IP_TOS) and
+#			you have the gettosbyname() function.
+#
+#	NEWINIT		Turns on the new init code for UNICOS systems.
+#
+#	STREAMS		This system needs <sys/stream.h> for <sys/tty.h>
+#			(Sun 4.0.3)
+#
+#	FILIO_H		This system should use <sys/fileo.h> instead
+#			of <sys/ioctl.h> (Sun 4.0.3)
+#
+#	HAVE_fd_set	This system has a typedef for fd_set, but does
+#			not have FDSET() defined.
+#
+#	NO_STRING_H	If you don't have <string.h>, but have <strings.h>
+#
+#	LOGIN_PROGRAM=	Specifies the login program to use.  By default,
+#			it is /bin/login, or whatever is specified by 
+#			_PATH_LOGIN in <paths.h>
+#
+#	NO_LOGIN_P	If /bin/login doesn't understand the "-p"
+#			(preserve environment) option.
+#
+#	LOGIN_ARGS	if /bin/login understands environment variables
+#			after the login name.  Only used if NO_LOGIN_P
+#			is defined.
+#
+#	NO_LOGIN_F	If /bin/login doesn't understand the "-f" option.
+#			Only used if AUTHENTICATION is defined.
+#
+#	LOGIN_CAP_F	If /bin/login understands the "-F" option (which
+#			works like "-f", but root logins are allowed).
+#			Only used if NO_LOGIN_F is not defined.
+#
+#	LOGIN_R		This says that /bin/login understands the "-r host"
+#			option.  Only used if NO_LOGIN_F is defined (and
+#			the system supports the TIOCSTI ioctl).
+#
+#	LOGIN_HOST	Only applies if LOGIN_R is defined.  This
+#			specifies the hostname to be passed to "login -r"
+#			for successfully authenticated logins.  This
+#			defaults to "localhost" (don't forget to include
+#			the quotes, e.g. -DLOGIN_HOST=\"localhost\").
+#
+#			It can also be set to host (-DLOGIN_HOST=host)
+#			to have the real hostname passed to "/bin/login -r".
+#			  NOTE: If you do this, then anyone that wants to
+#				allow authenticated login access will have
+#				to add those remote hosts to their .rhosts,
+#				which sort of defeats the whole purpose of
+#				authenticated login... 
+#
+#	NO_BSD_SETJMP	For UNICOS releases prior to 7.0.  Turns off
+#			the inclusion of <bsdsetjmp.h>.
+#
+#	STREAMS		If the system has streams; causes <sys/stream.h>
+#			to be included instead of <sys/tty.h>
+#
+#	MUST_ALIGN	If !KRB & !HAVE_KRB4_DES_LIB and your words
+#			must be word aligned.
+#
+#	STREAMSPTY	Use /dev/ptmx to get a clean pty.  Uses
+#			streams packet mode rather than Berkeley.
+#			Appropriate for SVr4 derivatives.
+#
+#	UTMPX		System has /etc/utmpx as well as /etc/utmp.
+#			Use makeutx and modutx to update utmp/x and wtmp/x.
+#			Appropriate for SVr4 derivatives.
+#
+#	HAS_CGETENT	If your system has the cgetent() and cgetstr()
+#			routines.  This is a 4.4BSD feature, that
+#			eliminates grabbing the getty gettytab.c source.
+#			You need to include getent.o on the LIB_OBJ
+#			line if this is defined.
+#
+#	OLD_ENVIRON	Support for the old environment option.
+
+# LIB_OBJ=
+#    This is a list of object files that are needed but are not in
+#    the standard C library.
+#
+# 	    strcasecmp.o	If you don't have strncasecmp(3)
+#	    strdup.o		If you don't have strdup(3)
+#	    setenv.o		If you don't have setenv(3) and unsetenv(3)
+#	    setsid.o		If you don't have the POSIX setsid() call
+#	    strerror.o		If you don't have strerror(3)
+#	    strftime.o		If you don't have strftime(3)
+#	    getopt.o		If you don't have getopt(3)
+#	    herror.o		If you don't have herror(3)
+#	    gettytab.o		If you can get gettytab.c from getty source.
+#	    getent.o		If you can't get gettytab.c (or have
+#				HAS_CGETENT defined...)
+#	    mem.o		If you don't have mem*(3) routines.
+
+# LIB_SRC=
+#    This is a list of source modules for specificed in LIB_OBJ.
+#    This information is used by make for checking dependencies.
+
+
+# LIBS=
+#    This is a list of libraries to be included.  This will always
+#    include the telnet library, and will also include either -lcurses
+#    or -ltermcap, -lutil for 4.4bsd, and -lnet for UNICOS5.0 and earlier.
+#    Also -lkrb & -ldes if Kerberos.
+
+# LIBPATH=
+#    This is a list of the paths to all the libraries listed in LIBS.
+#    This information is used by make for checking dependencies.
+#    Don't forget libc.a
+
+# VPATH=
+#    Directory where gettytab.c can be found, if you have it.
+
+# LIBEXEC=
+#    Directory where the telnetd executable should be installed.
+
+# LCCFLAGS=
+#    Local flags for ${CC} (like -O)
+
+# AR=
+#    Name of "ar" program, usually just "ar".
+
+# ARFLAGS
+#    Flags to pass to ${AR}
+
+# RANLIB
+#    Name of "ranlib" program, set it to "NONE" if you don't
+#    have a "ranlib".
+
+all:
+	@echo "You must specify what type of system you are on,"
+	@echo "or setup a Config.local file for your system."
+	@echo "Known system types are:"
+	@echo
+	@echo " 4.4bsd 4.3reno 4.4bsd.auth 4.3reno.auth 4.3tahoe 4.3bsd"
+	@echo " bsdi1.0 bsdi1.0.auth"
+	@echo " unicos8.1 unicos8.0 unicos7.C unicos7.0"
+	@echo " unicos8.1.auth unicos8.0.auth unicos7.0.auth"
+	@echo " unicos7.C.auth unicos7.0.des.auth"
+	@echo " unicos6.1 unicos6.0 unicos5.1 unicos5.0"
+	@echo " sun3.5 sun4.0.3c sun4.0 sun4.1 sun4.1.auth"
+	@echo " solaris2.2 solaris2.2.auth"
+	@echo " dynix3.0.12 dynix3.0.17"
+	@echo " ultrix3.1 ultrix4.0 ultrix4.1 ultrix4.3 ultrix4.3.auth"
+	@echo " irix4.0.1"
+	@echo " hpux8.0"
+	@echo " next1.0"
+	@echo " convex"
+
+4.4bsd:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lutil -ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/usr/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/bin \
+		DEFINES=${ODEFS}"-DLINEMODE -DTERMCAP -DKLUDGELINEMODE \
+		    -DDEFAULT_IM='\"\r\n4.4 BSD UNIX (%h) (%t)\r\n\r\r\n\r\"' \
+			-DUSE_TERMIO -DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON \
+			-DHAS_CGETENT" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o" \
+		LIB_SRC="getent.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/libexec \
+		CC="${CC}" LCCFLAGS="-O"
+
+4.3reno:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lutil -ltermcap ../libtelnet/libtelnet.a ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a ${AUTH_LIBPATH}" \
+		DEST=${DESTDIR}/usr/bin \
+		DEFINES=${ODEFS}"-DLINEMODE -DTERMCAP -DKLUDGELINEMODE \
+	-DDEFAULT_IM='\"\r\n4.3BSD-Reno UNIX (%h) (%t)\r\n\r\r\n\r\"' \
+			-DUSE_TERMIO -DDIAGNOSTICS -DENV_HACK \
+			-DOLD_ENVIRON ${AUTH_DEF}" \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="gettytab.o" \
+		LIB_SRC="gettytab.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		VPATH=/usr/src/libexec/getty \
+		LIBEXEC=${DESTDIR}/usr/libexec \
+		CC="${CC}" LCCFLAGS="-O"
+
+
+4.4bsd.auth 4.3reno.auth:
+	make -f ../Config.generic `basename $@ .auth` WHAT=${WHAT} \
+		AUTH_LIB="-lkrb -ldes" \
+		AUTH_LIBPATH="/usr/lib/libkrb.a /usr/lib/libdes.a" \
+		AUTH_DEF="-DAUTHENTICATION -DENCRYPTION -DKRB4 -DDES_ENCRYPTION"
+
+4.3tahoe:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/bin \
+		DEFINES=${ODEFS}"-DTERMCAP -DKLUDGELINEMODE \
+		 -DDEFAULT_IM='\"\r\n4.3BSD-Tahoe UNIX (%h) (%t)\r\n\r\r\n\r\"'\
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		INCLUDES="-I.." \
+		LIB_OBJ="strdup.o setsid.o strftime.o gettytab.o" \
+		LIB_SRC="strdup.c setsid.c strftime.c gettytab.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		VPATH=/usr/src/etc/getty \
+		LIBEXEC=${DESTDIR}/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+4.3bsd:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/bin \
+		DEFINES=${ODEFS}"-DTERMCAP -DKLUDGELINEMODE \
+		    -DDEFAULT_IM='\"\r\n4.3BSD UNIX (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		INCLUDES="-I.." \
+		LIB_OBJ="strdup.o setsid.o strftime.o \
+			gettytab.o getopt.o herror.o" \
+		LIB_SRC="strdup.c setsid.c strftime.c \
+			gettytab.c getopt.c herror.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		VPATH=/usr/src/etc/getty \
+		LIBEXEC=${DESTDIR}/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+bsdi1.0:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lutil -ltermcap ../libtelnet/libtelnet.a ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+			../libtelnet/libtelnet.a ${AUTH_LIBPATH}" \
+		DEST=${DESTDIR}/usr/bin \
+		DEFINES=${ODEFS}"-DLINEMODE -DTERMCAP -DKLUDGELINEMODE \
+	-DDEFAULT_IM='\"\r\nBSDI BSD/386 1.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DUSE_TERMIO -DDIAGNOSTICS -DENV_HACK \
+			-DOLD_ENVIRON ${AUTH_DEF}" \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="gettytab.o" \
+		LIB_SRC="gettytab.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		VPATH=/usr/src/libexec/getty \
+		LIBEXEC=${DESTDIR}/usr/libexec \
+		CC="${CC}" LCCFLAGS="-O"
+
+bsdi1.0.auth:
+	make -f ../Config.generic `basename $@ .auth` WHAT=${WHAT} \
+		AUTH_LIB="-lkrb -ldes" \
+		AUTH_LIBPATH="/usr/lib/libkrb.a /usr/lib/libdes.a" \
+		AUTH_DEF="-DAUTHENTICATION -DENCRYPTION -DKRB4 -DDES_ENCRYPTION"
+		AUTH_INC=-I/usr/include/kerberosIV
+
+unicos8.1:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lcurses -L../libtelnet -ltelnet ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a ${AUTH_LIBPATH}" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=bsdsignal \
+			-DLINEMODE -DKLUDGELINEMODE \
+			-DSYSV_TERMIO -DHAS_GETTOS ${AUTH_DEF} \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 8.1 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="getent.o" \
+		LIB_SRC="getent.c" \
+
+unicos8.0:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lcurses -L../libtelnet -ltelnet ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a ${AUTH_LIBPATH}" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=bsdsignal \
+			-DLINEMODE -DKLUDGELINEMODE \
+			-DSYSV_TERMIO -DHAS_GETTOS ${AUTH_DEF} \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 8.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="getent.o" \
+		LIB_SRC="getent.c" \
+		CC="${CC}" LCCFLAGS="-O"
+
+unicos7.C:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lcurses -L../libtelnet -ltelnet ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a ${AUTH_LIBPATH}"\
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=bsdsignal \
+			-DLINEMODE -DKLUDGELINEMODE \
+			-DSYSV_TERMIO -DHAS_GETTOS ${AUTH_DEF} \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 7.C (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="getent.o" \
+		LIB_SRC="getent.c" \
+		CC="${CC}" LCCFLAGS="-O"
+
+
+unicos7.0:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lcurses -L../libtelnet -ltelnet -lkrb" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a /usr/lib/libkrb.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=bsdsignal \
+			-DLINEMODE -DKLUDGELINEMODE \
+			-DSYSV_TERMIO -DHAS_GETTOS \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 7.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o" \
+		LIB_SRC="getent.c" \
+		CC="${CC}" LCCFLAGS="-O"
+
+# As of UNICOS 7.0.5.2, there is no longer a /usr/lib/libdes.a
+# If you still have a /usr/lib/libdes.a, use the "unicos7.0.des.auth"
+# target instead of "unicos7.0.auth".
+
+unicos8.1.auth unicos8.0.auth unicos7.0.auth:
+	make -f ../Config.generic `basename $@ .auth` WHAT=${WHAT} \
+		AUTH_LIB=-lkrb AUTH_LIBPATH=/usr/lib/libkrb.a \
+		AUTH_INC=-I/usr/include/krb \
+		AUTH_DEF="-DAUTHENTICATION -DENCRYPTION -DKRB4 -DDES_ENCRYPTION"
+
+unicos7.C.auth unicos7.0.des.auth:
+	make -f ../Config.generic `basename $@ .des.auth` WHAT=${WHAT} \
+		AUTH_LIB="-lkrb -ldes" \
+		AUTH_LIBPATH="/usr/lib/libkrb.a /usr/lib/libdes.a" \
+		AUTH_INC=-I/usr/include/krb \
+		AUTH_DEF="-DAUTHENTICATION -DENCRYPTION -DKRB4 -DDES_ENCRYPTION"
+
+unicos6.1:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lcurses -L../libtelnet -ltelnet" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=bsdsignal \
+			-DKLUDGELINEMODE -DUSE_TERMIO -DHAS_GETTOS \
+			-DLINEMODE -DSYSV_TERMIO -DNEWINIT \
+			-DNO_LOGIN_F -DNO_LOGIN_P -DNO_BSD_SETJMP \
+			-DLOGIN_ARGS \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 6.1 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o parsetos.o" \
+		LIB_SRC="getent.c parsetos.c" \
+		CC="${CC}" LCCFLAGS="-O"
+
+unicos6.0:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lcurses -L../libtelnet -ltelnet" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=bsdsignal \
+			-DKLUDGELINEMODE -DUSE_TERMIO -DHAS_GETTOS \
+			-DLINEMODE -DSYSV_TERMIO -DNEWINIT \
+			-DNO_LOGIN_F -DNO_LOGIN_P -DNO_BSD_SETJMP \
+			-DLOGIN_ARGS \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 6.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o parsetos.o" \
+		LIB_SRC="getent.c parsetos.c" \
+		CC="${CC}" LCCFLAGS="-O"
+
+unicos5.1:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lnet -lcurses -L../libtelnet -ltelnet" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=sigset \
+			-DKLUDGELINEMODE -DSYSV_TERMIO -DNO_CC_T \
+			-DUNICOS5 -DLINEMODE -DSYSV_TERMIO \
+			-DNEWINIT -DNO_LOGIN_F -DNO_LOGIN_P -DNO_BSD_SETJMP \
+			-DLOGIN_ARGS \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 5.1 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strerror.o setsid.o strftime.o" \
+		LIB_SRC="getent.c strerror.c setsid.c strftime.c" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+unicos5.0:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-lnet -lcurses -L../libtelnet -ltelnet" \
+		LIBPATH="/lib/libc.a /usr/lib/libcurses.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-Dvfork=fork -Dsignal=sigset \
+			-DKLUDGELINEMODE -DSYSV_TERMIO -DNO_CC_T \
+			-DUNICOS5 -DUNICOS50 -DLINEMODE -DSYSV_TERMIO \
+			-DNEWINIT -DNO_LOGIN_F -DNO_LOGIN_P -DNO_BSD_SETJMP \
+			-DLOGIN_ARGS \
+		  -DDEFAULT_IM='\"\r\nCray UNICOS 5.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strerror.o setsid.o strftime.o" \
+		LIB_SRC="getent.c strerror.c setsid.c strftime.c" \
+		AR=bld ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+sun3.5:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DTERMCAP -DKLUDGELINEMODE \
+			-DHAVE_fd_set \
+			-DDIAGNOSTICS  -DENV_HACK -DOLD_ENVIRON \
+		   -DDEFAULT_IM='\"\r\nSunOS UNIX 3.5 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DNO_LOGIN_P" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strdup.o strerror.o setsid.o \
+			setenv.o strftime.o strcasecmp.o herror.o" \
+		LIB_SRC="getent.c strdup.c strerror.c setsid.c \
+			setenv.c strftime.c strcasecmp.c herror.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc/in.telnetd \
+		CC="${CC}" LCCFLAGS="-O"
+
+sun4.0.3c sun4.0:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DFILIO_H -DTERMCAP -DUSE_TERMIO -DNO_CC_T \
+			-DKLUDGELINEMODE \
+		   -DDEFAULT_IM='\"\r\nSunOS UNIX 4.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DSTREAMS -DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON \
+			" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strerror.o setsid.o setenv.o \
+				strcasecmp.o strftime.o herror.o" \
+		LIB_SRC="getent.c strerror.c setsid.c setenv.c \
+				strcasecmp.c strftime.c herror.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc/in.telnetd \
+		CC="${CC}" LCCFLAGS="-O"
+
+sun4.1:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+			../libtelnet/libtelnet.a ${AUTH_LIBPATH}" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DFILIO_H -DTERMCAP -DUSE_TERMIO \
+			-DKLUDGELINEMODE -DSTREAMS \
+		   -DDEFAULT_IM='\"\r\nSunOS UNIX 4.1 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON ${AUTH_DEF}" \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="getent.o strerror.o setenv.o herror.o" \
+		LIB_SRC="getent.c strerror.c setenv.c herror.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc/in.telnetd \
+		CC="${CC}" LCCFLAGS="-O"
+
+sun4.1.auth:
+	make -f ../Config.generic `basename $@ .auth` WHAT=${WHAT} \
+		AUTH_LIB="-lkrb -ldes" \
+		AUTH_LIBPATH="/usr/lib/libkrb.a /usr/lib/libdes.a" \
+		AUTH_DEF="-DAUTHENTICATION -DENCRYPTION -DKRB4 -DDES_ENCRYPTION"
+
+sol2.2 solaris2.2:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermlib ../libtelnet/libtelnet.a" \
+		LIBPATH="/usr/ccs/lib/libtermlib.a ../libtelnet/libtelnet.a \
+			/usr/lib/libc.a /usr/ucblib/libucb.a \
+			/usr/lib/libsocket.a /usr/lib/libnsl.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES="-DFILIO_H -DUSE_TERMIO -DKLUDGELINEMODE \
+			-DSTREAMS -DSTREAMSPTY -DDIAGNOSTICS -DSOLARIS \
+			-DENV_HACK -DOLD_ENVIRON -DNO_LOGIN_P -DUTMPX \
+	-DDEFAULT_IM='\"\r\n\r\nUNIX(r) System V Release 4.0 (%h)\r\n\r\n\"' \
+			-DLOGIN_ARGS" \
+		INCLUDES="-I.. -I/usr/ucbinclude" \
+		LIB_OBJ="getent.o strerror.o setenv.o herror.o" \
+		LIB_SRC="getent.c strerror.c setenv.c herror.c" \
+		AR=ar ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/usr/etc/in.telnetd \
+		CC="${CC}" LCCFLAGS="-O"
+
+sol2.2.auth solaris2.2.auth:
+	make -f ../Config.generic `basename $@ .auth` WHAT=${WHAT} \
+		AUTH_LIB="-lkrb" AUTH_LIBPATH="/usr/lib/libkrb.a" \
+		AUTH_INC=-I/usr/include/kerberos \
+		AUTH_DEF="-DAUTHENTICATION -DKRB4"
+
+dynix3.0.12:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DTERMCAP -DKLUDGELINEMODE \
+		 -DDEFAULT_IM='\"\r\nDYNIX(R) V3.0.12 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON -DNO_STRING_H " \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strchr.o strrchr.o strdup.o strerror.o \
+			setsid.o setenv.o strcasecmp.o strftime.o getopt.o \
+			mem.o" \
+		LIB_SRC="getent.c strchr.c strrchr.c strdup.c strerror.c \
+			setsid.c setenv.c strcasecmp.c strftime.c getopt.c \
+			mem.o" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+dynix3.0.17:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a -lseq" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+			../libtelnet/libtelnet.a /usr/lib/libseq.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DTERMCAP -DKLUDGELINEMODE \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON -DNO_STRING_H \
+		 -DDEFAULT_IM='\"\r\nDYNIX(R) V3.0.17 (%h) (%t)\r\n\r\r\n\r\"' \
+			" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strchr.o strrchr.o strdup.o strerror.o \
+			setsid.o strftime.o mem.o" \
+		LIB_SRC="getent.c strchr.c strrchr.c strdup.c strerror.c \
+			setsid.c strftime.c mem.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+ultrix3.1:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DTERMCAP -DKLUDGELINEMODE \
+			-DNO_LOGIN_F -DNO_LOGIN_P -DNO_LOGIN_H \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON -DUSE_TERMIO \
+		    -DDEFAULT_IM='\"\r\nULTRIX V3.1 (%h) (%t)\r\n\r\r\n\r\"' \
+			-YPOSIX" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strdup.o strerror.o setenv.o \
+			strftime.o herror.o" \
+		LIB_SRC="getent.c strdup.c strerror.c setenv.c \
+			strftime.c herror.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+ultrix4.0:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DUSE_TERMIO -DTERMCAP \
+		    -DDEFAULT_IM='\"\r\nULTRIX V4.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DKLUDGELINEMODE -DDIAGNOSTICS \
+			-DNO_LOGIN_F -DNO_LOGIN_P -DNO_LOGIN_H \
+			-DENV_HACK -DOLD_ENVIRON" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strdup.o strerror.o setsid.o \
+			setenv.o strftime.o" \
+		LIB_SRC="getent.c strdup.c strerror.c setsid.c \
+			setenv.c strftime.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+ultrix4.1:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DUSE_TERMIO -DTERMCAP \
+		    -DDEFAULT_IM='\"\r\nULTRIX V4.1 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DKLUDGELINEMODE -DDIAGNOSTICS \
+			-DNO_LOGIN_F -DNO_LOGIN_P -DNO_LOGIN_H \
+			-DENV_HACK -DOLD_ENVIRON" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o strdup.o" \
+		LIB_SRC="getent.c strdup.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+ultrix4.3:
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a ${AUTH_LIBPATH}" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-DUSE_TERMIO -DTERMCAP \
+		    -DDEFAULT_IM='\"\r\nULTRIX V4.3 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DKLUDGELINEMODE -DDIAGNOSTICS \
+			-DNO_LOGIN_F -DNO_LOGIN_P -DNO_LOGIN_H \
+			-DENV_HACK -DOLD_ENVIRON ${AUTH_DEF}" \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="getent.o strdup.o" \
+		LIB_SRC="getent.c strdup.c" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc \
+		CC="${CC}" LCCFLAGS="-g"
+
+ultrix4.3.auth:
+	make -f ../Config.generic `basename $@ .auth` WHAT=${WHAT} \
+		AUTH_LIB="-lkrb -ldes" \
+		AUTH_LIBPATH="/usr/lib/libkrb.a /usr/lib/libdes.a" \
+		AUTH_DEF="-DAUTHENTICATION -DKRB4"
+
+irix4.0.1:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermlib ../libtelnet/libtelnet.a" \
+		LIBPATH="/usr/lib/libc.a /usr/lib/libtermlib.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/bin \
+		DEFINES=${ODEFS}"-Dvfork=fork -DUSE_TERMIO \
+		    -DDEFAULT_IM='\"\r\n\r\nIRIX System V.3 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DNO_LOGIN_F -DNO_LOGIN_P \
+			-DDIAGNOSTICS " \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o setenv.o" \
+		LIB_SRC="getent.c setenv.c" \
+		AR=ar ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+hpux8.0:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="/lib/libc.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a" \
+		DEST=${DESTDIR}/usr/bin \
+		DEFINES=${ODEFS}"-Dvfork=fork -DUSE_TERMIO \
+		    -DDEFAULT_IM='\"\r\n\r\nHP-UX 8.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DNO_LOGIN_F -DNO_LOGIN_P -DNO_LOGIN_H \
+			-DDIAGNOSTICS -DLOGIN_ARGS" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o setenv.o" \
+		LIB_SRC="getent.c setenv.c" \
+		AR=ar ARFLAGS=cq RANLIB=NONE \
+		LIBEXEC=${DESTDIR}/etc \
+		CC="${CC}" LCCFLAGS="-O"
+
+next1.0:
+	@echo $@ is untested... it may or may not work..."
+	make -f Makefile.generic ${WHAT} \
+		LIBS="../libtelnet/libtelnet.a -ltermcap -lsys_s ${AUTH_LIB}" \
+		LIBPATH="/lib/libc.a /lib/libsys_s.a /usr/lib/libtermcap.a \
+				../libtelnet/libtelnet.a ${AUTH_LIBPATH}" \
+		DEST=${DESTDIR}/usr/ucb \
+		DEFINES=${ODEFS}"-bsd -DTERMCAP -DKLUDGELINEMODE \
+			-DDEFAULT_IM='\"\r\nNeXT 1.0 (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON \
+			-DNO_STRING_H -Dgetenv=getenv_ ${AUTH_DEF}" \
+		INCLUDES="-I.. ${AUTH_INC}" \
+		LIB_OBJ="strdup.o setenv.o setsid.o strftime.o \
+			strcasecmp.o gettytab.o" \
+		LIB_SRC=s"trdup.c setenv.c setsid.c strftime.c \
+			strcasecmp.c gettytab.c" \
+		CC="${CC}" LCCFLAGS="-O" \
+		VPATH=../../getty \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc
+
+#
+# For the convex, make symbolic links to the tc[sg]getattr.c routines,
+# because we are using posix stuff, but not the posix library...
+# Pass the stuff to Makefile.generic by passing the object/source names
+# in through LIB_OBJ and LIB_SRC
+#
+convex:
+	@echo $@ is untested... it may or may not work..."
+	ln -s ../../rel_usr/src/lib/libc/posix/tcsetattr.c tcsetattr.c
+	ln -s ../../rel_usr/src/lib/libc/posix/tcgetattr.c tcgetattr.c
+	make -f Makefile.generic ${WHAT} \
+		LIBS="-ltermcap ../libtelnet/libtelnet.a" \
+		LIBPATH="../libtelnet/libtelnet.a" \
+		AR=ar ARFLAGS=cq RANLIB=ranlib \
+		LIBEXEC=${DESTDIR}/usr/etc/in.telnetd \
+		CC="${CC}" LCCFLAGS="-g ${OPTLEV} -Dconvex" \
+		DEFINES=${ODEFS}"-DUSE_TERMIO -DLINEMODE \
+			-DDEFAULT_IM='\"\r\nConvex (%h) (%t)\r\n\r\r\n\r\"' \
+			-DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON" \
+		INCLUDES="-I.." \
+		LIB_OBJ="getent.o setsid.o strftime.o \
+			tcsetattr.o tcgetattr.o" \
+		LIB_SRC="getent.c setsid.c strftime.c \
+			tcsetattr.c tcgetattr.c"
+
+clean cleandir:
+	make -f Makefile.generic $@
diff --git a/krb5-1-6/src/appl/telnet/Makefile.in b/krb5-1-6/src/appl/telnet/Makefile.in
new file mode 100644
index 000000000..32e41551f
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/Makefile.in
@@ -0,0 +1,5 @@
+thisconfigdir=.
+myfulldir=appl/telnet
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+LOCAL_SUBDIRS=libtelnet telnet telnetd
diff --git a/krb5-1-6/src/appl/telnet/README b/krb5-1-6/src/appl/telnet/README
new file mode 100644
index 000000000..29d51a392
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/README
@@ -0,0 +1,679 @@
+
+This is a distribution of both client and server telnet.  These programs
+have been compiled on:
+			telnet	telnetd
+	BSD 4.4		  x	  x
+	BSD 4.3 Reno	  X	  X
+	UNICOS 8.0	  X	  X
+	UNICOS 7.C	  X	  X
+	UNICOS 7.0	  X	  X
+	UNICOS 6.1	  X	  X
+	BSDI 1.0	  X	  X
+	Solaris 2.2       x       x (no linemode in server)
+	Solaris 2.3       x       x (no linemode in server)
+	SunOs 4.1.3	  X	  X (no linemode in server)
+	Ultrix 4.3	  X	  X (no linemode in server)
+	DYNIX V3.0.17.9	  X	  X (no linemode in server)
+	HP-UX 8.0	  x       x (no linemode in server)
+
+In addition, previous versions have been compiled on the following
+machines, but were not available for testing this version.
+			telnet	telnetd
+	Next1.0		  X	  X
+	UNICOS 6.0	  X	  X
+	UNICOS 5.1	  X	  X
+	UNICOS 5.0	  X	  X
+	SunOs 4.0.3c	  X	  X (no linemode in server)
+	BSD 4.3		  X  	  X (no linemode in server)
+	DYNIX V3.0.12	  X	  X (no linemode in server)
+	Ultrix 3.1	  X	  X (no linemode in server)
+	Ultrix 4.0	  X	  X (no linemode in server)
+	SunOs 3.5	  X	  X (no linemode in server)
+
+This code should work, but there are no guarantees.
+
+January 19, 1994
+
+This is a list of some of the changes since the last tar release
+of telnet/telnetd.  There are probably other changes that aren't
+listed here, but this should hit a lot of the main ones.
+
+   General:
+	Changed #define for AUTHENTICATE to AUTHENTICATION
+	Changed #define for ENCRYPT to ENCRYPTION
+	Changed #define for DES_ENCRYPT to DES_ENCRYPTION
+
+	Added support for SPX authentication: -DSPX
+
+	Added support for Kerberos Version 5 authentication: -DKRB5
+
+	Added support for ANSI C function prototypes
+
+	Added support for the NEW-ENVIRON option (RFC-1572)
+	including support for USERVAR.
+
+	Made support for the old Environment Option (RFC-1408)
+	conditional on -DOLD_ENVIRON
+
+	Added #define ENV_HACK - support for RFC 1571
+
+	The encryption code is removed from the public distributions.
+	Domestic 4.4 BSD distributions contain the encryption code.
+
+	ENV_HACK: Code to deal with systems that only implement
+		the old ENVIRON option, and have reversed definitions
+		of ENV_VAR and ENV_VAL.  Also fixes ENV processing in
+		client to handle things besides just the default set...
+
+	NO_BSD_SETJMP: UNICOS configuration for
+		UNICOS 6.1/6.0/5.1/5.0 systems.
+
+	STREAMSPTY: Use /dev/ptmx to get a clean pty.  This
+		is for SVr4 derivatives (Like Solaris)
+
+	UTMPX: For systems that have /etc/utmpx. This is for
+		SVr4 derivatives (Like Solaris)
+
+	Definitions for BSDI 1.0
+
+	Definitions for 4.3 Reno and 4.4 BSD.
+
+	Definitions for UNICOS 8.0 and UNICOS 7.C
+
+	Definitions for Solaris 2.0
+
+	Definitions for HP-UX 8.0
+
+	Latest Copyright notices from Berkeley.
+
+	FLOW-CONTROL: support for RFC-XXXx
+
+
+   Client Specific:
+
+	Fix the "send" command to not send garbage...
+
+	Fix status message for "skiprc"
+
+	Make sure to send NAWS after telnet has been suspended
+	or an external command has been run, if the window size
+	has changed.
+
+	sysV88 support.
+
+   Server Specific:
+
+	Support flowcontrol option in non-linemode servers.
+
+	-k Server supports Kludge Linemode, but will default to
+	   either single character mode or real Linemode support.
+	   The user will have to explicitly ask to switch into
+	   kludge linemode. ("stty extproc", or escape back to
+	   to telnet and say "mode line".)
+
+	-u Specify the length of the hostname field in the utmp
+	   file.  Hostname longer than this length will be put
+	   into the utmp file in dotted decimal notation, rather
+	   than putting in a truncated hostname.
+	
+	-U Registered hosts only.  If a reverse hostname lookup
+	   fails, the connection will be refused.
+
+	-f/-F
+	   Allows forwarding of credentials for KRB5.
+
+Februrary 22, 1991:
+
+    Features:
+
+	This version of telnet/telnetd has support for both
+	the AUTHENTICATION and ENCRYPTION options.  The
+	AUTHENTICATION option is fairly well defined, and
+	an option number has been assigned to it.  The
+	ENCRYPTION option is still in a state of flux; an
+	option number has been assigned to, but it is still
+	subject to change.  The code is provided in this release
+	for experimental and testing purposes.
+
+	The telnet "send" command can now be used to send
+	do/dont/will/wont commands, with any telnet option
+	name.  The rules for when do/dont/will/wont are sent
+	are still followed, so just because the user requests
+	that one of these be sent doesn't mean that it will
+	be sent...
+
+	The telnet "getstatus" command no longer requires
+	that option printing be enabled to see the response
+	to the "DO STATUS" command.
+
+	A -n flag has been added to telnetd to disable
+	keepalives.
+
+	A new telnet command, "auth" has been added (if
+	AUTHENTICATE is defined).  It has four sub-commands,
+	"status", "disable", "enable" and "help".
+
+	A new telnet command, "encrypt" has been added (if
+	ENCRYPT is defined).  It has many sub-commands:
+	"enable", "type", "start", "stop", "input",
+	"-input", "output", "-output", "status", and "help".
+
+	The LOGOUT option is now supported by both telnet
+	and telnetd, a new command, "logout", was added
+	to support this.
+
+	Several new toggle options were added:
+	    "autoencrypt", "autodecrypt", "autologin", "authdebug",
+	    "encdebug", "skiprc", "verbose_encrypt"
+
+	An "rlogin" interface has been added.  If the program
+	is named "rlogin", or the "-r" flag is given, then
+	an rlogin type of interface will be used.
+		~.	Terminates the session
+		~<susp> Suspend the session
+		~^]	Escape to telnet command mode
+		~~	Pass through the ~.
+	    BUG: If you type the rlogin escape character
+		 in the middle of a line while in rlogin
+		 mode, you cannot erase it or any characters
+		 before it.  Hopefully this can be fixed
+		 in a future release...
+
+    General changes:
+
+	A "libtelnet.a" has now been created.  This libraray
+	contains code that is common to both telnet and
+	telnetd.  This is also where library routines that
+	are needed, but are not in the standard C library,
+	are placed.
+
+	The makefiles have been re-done.  All of the site
+	specific configuration information has now been put
+	into a single "Config.generic" file, in the top level
+	directory.  Changing this one file will take care of
+	all three subdirectories.  Also, to add a new/local
+	definition, a "Config.local" file may be created
+	at the top level; if that file exists, the subdirectories
+	will use that file instead of "Config.generic".
+
+	Many 1-2 line functions in commands.c have been
+	removed, and just inserted in-line, or replaced
+	with a macro.
+
+    Bug Fixes:
+
+	The non-termio code in both telnet and telnetd was
+	setting/clearing CTLECH in the sg_flags word.  This
+	was incorrect, and has been changed to set/clear the
+	LCTLECH bit in the local mode word.
+
+	The SRCRT #define has been removed.  If IP_OPTIONS
+	and IPPROTO_IP are defined on the system, then the
+	source route code is automatically enabled.
+
+	The NO_GETTYTAB #define has been removed; there
+	is a compatability routine that can be built into
+	libtelnet to achive the same results.
+
+	The server, telnetd, has been switched to use getopt()
+	for parsing the argument list.
+
+	The code for getting the input/output speeds via
+	cfgetispeed()/cfgetospeed() was still not quite
+	right in telnet.  Posix says if the ispeed is 0,
+	then it is really equal to the ospeed.
+
+	The suboption processing code in telnet now has
+	explicit checks to make sure that we received
+	the entire suboption (telnetd was already doing this).
+
+	The telnet code for processing the terminal type
+	could cause a core dump if an existing connection
+	was closed, and a new connection opened without
+	exiting telnet.
+
+	Telnetd was doing a TCSADRAIN when setting the new
+	terminal settings;  This is not good, because it means
+	that the tcsetattr() will hang waiting for output to
+	drain, and telnetd is the only one that will drain
+	the output...  The fix is to use TCSANOW which does
+	not wait.
+
+	Telnetd was improperly setting/clearing the ISTRIP
+	flag in the c_lflag field, it should be using the
+	c_iflag field. 
+
+	When the child process of telnetd was opening the
+	slave side of the pty, it was re-setting the EXTPROC
+	bit too early, and some of the other initialization
+	code was wiping it out.  This would cause telnetd
+	to go out of linemode and into single character mode.
+
+	One instance of leaving linemode in telnetd forgot
+	to send a WILL ECHO to the client, the net result
+	would be that the user would see double character
+	echo.
+
+	If the MODE was being changed several times very
+	quickly, telnetd could get out of sync with the
+	state changes and the returning acks; and wind up
+	being left in the wrong state.
+
+September 14, 1990:
+
+	Switch the client to use getopt() for parsing the
+	argument list.  The 4.3Reno getopt.c is included for
+	systems that don't have getopt().
+
+	Use the posix _POSIX_VDISABLE value for what value
+	to use when disabling special characters.  If this
+	is undefined, it defaults to 0x3ff.
+
+	For non-termio systems, TIOCSETP was being used to
+	change the state of the terminal.  This causes the
+	input queue to be flushed, which we don't want.  This
+	is now changed to TIOCSETN.
+
+	Take out the "#ifdef notdef" around the code in the
+	server that generates a "sync" when the pty oputput
+	is flushed.  The potential problem is that some older
+	telnet clients may go into an infinate loop when they
+	receive a "sync", if so, the server can be compiled
+	with "NO_URGENT" defined.
+
+	Fix the client where it was setting/clearing the OPOST
+	bit in the c_lflag field, not the c_oflag field.
+
+	Fix the client where it was setting/clearing the ISTRIP
+	bit in the c_lflag field, not the c_iflag field.  (On
+	4.3Reno, this is the ECHOPRT bit in the c_lflag field.)
+	The client also had its interpretation of WILL BINARY
+	and DO BINARY reversed.
+
+	Fix a bug in client that would cause a core dump when
+	attempting to remove the last environment variable.
+
+	In the client, there were a few places were switch()
+	was being passed a character, and if it was a negative
+	value, it could get sign extended, and not match
+	the 8 bit case statements.  The fix is to and the
+	switch value with 0xff.
+
+	Add a couple more printoption() calls in the client, I
+	don't think there are any more places were a telnet
+	command can be received and not printed out when
+	"options" is on.
+
+	A new flag has been added to the client, "-a".  Currently,
+	this just causes the USER name to be sent across, in
+	the future this may be used to signify that automatic
+	authentication is requested.
+
+	The USER variable is now only sent by the client if
+	the "-a" or "-l user" options are explicity used, or
+	if the user explicitly asks for the "USER" environment
+	variable to be exported.  In the server, if it receives
+	the "USER" environment variable, it won't print out the
+	banner message, so that only "Password:" will be printed.
+	This makes the symantics more like rlogin, and should be
+	more familiar to the user.  (People are not used to
+	getting a banner message, and then getting just a
+	"Password:" prompt.)
+
+	Re-vamp the code for starting up the child login
+	process.  The code was getting ugly, and it was
+	hard to tell what was really going on.  What we
+	do now is after the fork(), in the child:
+		1) make sure we have no controlling tty
+		2) open and initialize the tty
+		3) do a setsid()/setpgrp()
+		4) makes the tty our controlling tty.
+	On some systems, #2 makes the tty our controlling
+	tty, and #4 is a no-op.  The parent process does
+	a gets rid of any controlling tty after the child
+	is fork()ed.
+
+	Use the strdup() library routine in telnet, instead
+	of the local savestr() routine.  If you don't have
+	strdup(), you need to define NO_STRDUP.
+
+	Add support for ^T (SIGINFO/VSTATUS), found in the
+	4.3Reno distribution.  This maps to the AYT character.
+	You need a 4-line bugfix in the kernel to get this
+	to work properly:
+
+	> *** tty_pty.c.ORG	Tue Sep 11 09:41:53 1990
+	> --- tty_pty.c	Tue Sep 11 17:48:03 1990
+	> ***************
+	> *** 609,613 ****
+	> 			if ((tp->t_lflag&NOFLSH) == 0)
+	> 				ttyflush(tp, FREAD|FWRITE);
+	> ! 			pgsignal(tp->t_pgrp, *(unsigned int *)data);
+	> 			return(0);
+	> 		}
+	> --- 609,616 ----
+	> 			if ((tp->t_lflag&NOFLSH) == 0)
+	> 				ttyflush(tp, FREAD|FWRITE);
+	> ! 			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
+	> ! 			if ((*(unsigned int *)data == SIGINFO) &&
+	> ! 			    ((tp->t_lflag&NOKERNINFO) == 0))
+	> ! 				ttyinfo(tp);
+	> 			return(0);
+	> 		}
+
+	The client is now smarter when setting the telnet escape
+	character; it only sets it to one of VEOL and VEOL2 if
+	one of them is undefined, and the other one is not already
+	defined to the telnet escape character.
+
+	Handle TERMIOS systems that have seperate input and output
+	line speed settings imbedded in the flags.
+
+	Many other minor bug fixes.
+
+June 20, 1990:
+	Re-organize makefiles and source tree.  The telnet/Source
+	directory is now gone, and all the source that was in
+	telnet/Source is now just in the telnet directory.
+
+	Seperate makefile for each system are now gone.  There
+	are two makefiles, Makefile and Makefile.generic.
+	The "Makefile" has the definitions for the various
+	system, and "Makefile.generic" does all the work.
+	There is a variable called "WHAT" that is used to
+	specify what to make.  For example, in the telnet
+	directory, you might say:
+		make 4.4bsd WHAT=clean
+	to clean out the directory.
+
+	Add support for the ENVIRON and XDISPLOC options.
+	In order for the server to work, login has to have
+	the "-p" option to preserve environment variables.
+
+	Add the SOFT_TAB and LIT_ECHO modes in the LINEMODE support.
+
+	Add the "-l user" option to command line and open command
+	(This is passed through the ENVIRON option).
+
+	Add the "-e" command line option, for setting the escape
+	character.
+
+	Add the "-D", diagnostic, option to the server.  This allows
+	the server to print out debug information, which is very
+	useful when trying to debug a telnet that doesn't have any
+	debugging ability.
+
+	Turn off the literal next character when not in LINEMODE.
+
+	Don't recognize ^Y locally, just pass it through.
+
+	Make minor modifications for Sun4.0 and Sun4.1
+
+	Add support for both FORW1 and FORW2 characters.  The
+	telnet escpape character is set to whichever of the
+	two is not being used.  If both are in use, the escape
+	character is not set, so when in linemode the user will
+	have to follow the escape character with a <CR> or <EOF)
+	to get it passed through.
+
+	Commands can now be put in single and double quotes, and
+	a backslash is now an escape character.  This is needed
+	for allowing arbitrary strings to be assigned to environment
+	variables.
+
+	Switch telnetd to use macros like telnet for keeping
+	track of the state of all the options.
+
+	Fix telnetd's processing of options so that we always do
+	the right processing of the LINEMODE option, regardless
+	of who initiates the request to turn it on.  Also, make
+	sure that if the other side went "WILL ECHO" in response
+	to our "DO ECHO", that we send a "DONT ECHO" to get the
+	option turned back off!
+
+	Fix the TERMIOS setting of the terminal speed to handle both
+	BSD's seperate fields, and the SYSV method of CBAUD bits.
+
+	Change how we deal with the other side refusing to enable
+	an option.  The sequence used to be: send DO option; receive
+	WONT option; send DONT option.  Now, the sequence is: send
+	DO option; receive WONT option.  Both should be valid
+	according to the spec, but there has been at least one
+	client implementation of telnet identified that can get
+	really confused by this.  (The exact sequence, from a trace
+	on the server side, is (numbers are number of responses that
+	we expect to get after that line...):
+
+		send WILL ECHO	1 (initial request)
+		send WONT ECHO	2 (server is changing state)
+		recv DO ECHO	1 (first reply, ok.  expect DONT ECHO next)
+		send WILL ECHO	2 (server changes state again)
+		recv DONT ECHO	1 (second reply, ok.  expect DO ECHO next)
+		recv DONT ECHO	0 (third reply, wrong answer. got DONT!!!)
+	***	send WONT ECHO	  (send WONT to acknowledge the DONT)
+		send WILL ECHO	1 (ask again to enable option)
+		recv DO ECHO	0
+
+		recv DONT ECHO	0
+		send WONT ECHO	1
+		recv DONT ECHO	0
+		recv DO ECHO	1
+		send WILL ECHO	0
+		(and the last 5 lines loop forever)
+
+	The line with the "***" is last of the WILL/DONT/WONT sequence.
+	The change to the server to not generate that makes this same
+	example become:
+
+		send will ECHO	1
+		send wont ECHO	2
+		recv do ECHO	1
+		send will ECHO	2
+		recv dont ECHO	1
+		recv dont ECHO	0
+		recv do ECHO	1
+		send will ECHO	0
+
+	There is other option negotiation going on, and not sending
+	the third part changes some of the timings, but this specific
+	example no longer gets stuck in a loop.  The "telnet.state"
+	file has been modified to reflect this change to the algorithm.
+
+	A bunch of miscellaneous bug fixes and changes to make
+	lint happier.
+
+	This version of telnet also has some KERBEROS stuff in
+	it. This has not been tested, it uses an un-authorized
+	telnet option number, and uses an out-of-date version
+	of the (still being defined) AUTHENTICATION option.
+	There is no support for this code, do not enable it.
+
+
+March 1, 1990:
+CHANGES/BUGFIXES SINCE LAST RELEASE:
+	Some support for IP TOS has been added.  Requires that the
+	kernel support the IP_TOS socket option (currently this
+	is only in UNICOS 6.0).
+
+	Both telnet and telnetd now use the cc_t typedef.  typedefs are
+	included for systems that don't have it (in termios.h).
+
+	SLC_SUSP was not supported properly before.  It is now.
+
+	IAC EOF was not translated  properly in telnetd for SYSV_TERMIO
+	when not in linemode.  It now saves a copy of the VEOF character,
+	so that when ICANON is turned off and we can't trust it anymore
+	(because it is now the VMIN character) we use the saved value.
+
+	There were two missing "break" commands in the linemode
+	processing code in telnetd.
+
+	Telnetd wasn't setting the kernel window size information
+	properly.  It was using the rows for both rows and columns...
+
+Questions/comments go to
+		David Borman
+		Cray Research, Inc.
+		655F Lone Oak Drive
+		Eagan, MN 55123
+		dab@cray.com.
+
+README:	You are reading it.
+
+Config.generic:
+	This file contains all the OS specific definitions.  It
+	has pre-definitions for many common system types, and is
+	in standard makefile fromat.  See the comments at the top
+	of the file for more information.
+
+Config.local:
+	This is not part of the distribution, but if this file exists,
+	it is used instead of "Config.generic".  This allows site
+	specific configuration without having to modify the distributed
+	"Config.generic" file.
+
+kern.diff:
+	This file contains the diffs for the changes needed for the
+	kernel to support LINEMODE is the server.  These changes are
+	for a 4.3BSD system.  You may need to make some changes for
+	your particular system.
+
+	There is a new bit in the terminal state word, TS_EXTPROC.
+	When this bit is set, several aspects of the terminal driver
+	are disabled.  Input line editing, character echo, and
+	mapping of signals are all disabled.  This allows the telnetd
+	to turn of these functions when in linemode, but still keep
+	track of what state the user wants the terminal to be in.
+
+	New ioctl()s:
+
+		TIOCEXT		Turn on/off the TS_EXTPROC bit
+		TIOCGSTATE	Get t_state of tty to look at TS_EXTPROC bit
+		TIOCSIG		Generate a signal to processes in the
+				current process group of the pty.
+
+	There is a new mode for packet driver, the TIOCPKT_IOCTL bit.
+	When packet mode is turned on in the pty, and the TS_EXTPROC
+	bit is set, then whenever the state of the pty is changed, the
+	next read on the master side of the pty will have the TIOCPKT_IOCTL
+	bit set, and the data will contain the following:
+		struct xx {
+			struct sgttyb a;
+			struct tchars b;
+			struct ltchars c;
+			int t_state;
+			int t_flags;
+		}
+	This allows the process on the server side of the pty to know
+	when the state of the terminal has changed, and what the new
+	state is.
+
+	However, if you define USE_TERMIO or SYSV_TERMIO, the code will
+	expect that the structure returned in the TIOCPKT_IOCTL is
+	the termio/termios structure.
+
+stty.diff:
+	This file contains the changes needed for the stty(1) program
+	to report on the current status of the TS_EXTPROC bit.  It also
+	allows the user to turn on/off the TS_EXTPROC bit.  This is useful
+	because it allows the user to say "stty -extproc", and the
+	LINEMODE option will be automatically disabled, and saying "stty
+	extproc" will re-enable the LINEMODE option.
+
+telnet.state:
+	Both the client and server have code in them to deal
+	with option negotiation loops.  The algorithm that is
+	used is described in this file.
+
+telnet:
+	This directory contains the client code.  No kernel changes are
+	needed to use this code.
+
+telnetd:
+	This directory contains the server code.  If LINEMODE or KLUDGELINEMODE
+	are defined, then the kernel modifications listed above are needed.
+
+libtelnet:
+	This directory contains code that is common to both the client
+	and the server.
+
+arpa:
+	This directory has a new <arpa/telnet.h>
+
+libtelnet/Makefile.4.4:
+telnet/Makefile.4.4:
+telnetd/Makefile.4.4:
+	These are the makefiles that can be used on a 4.3Reno
+	system when this software is installed in /usr/src/lib/libtelnet,
+	/usr/src/libexec/telnetd, and /usr/src/usr.bin/telnet.
+
+
+The following TELNET options are supported:
+	
+	LINEMODE:
+		The LINEMODE option is supported as per RFC1116.  The
+		FORWARDMASK option is not currently supported.
+
+	BINARY: The client has the ability to turn on/off the BINARY
+		option in each direction.  Turning on BINARY from
+		server to client causes the LITOUT bit to get set in
+		the terminal driver on both ends,  turning on BINARY
+		from the client to the server causes the PASS8 bit
+		to get set in the terminal driver on both ends.
+
+	TERMINAL-TYPE:
+		This is supported as per RFC1091.  On the server side,
+		when a terminal type is received, termcap/terminfo
+		is consulted to determine if it is a known terminal
+		type.  It keeps requesting terminal types until it
+		gets one that it recongnizes, or hits the end of the
+		list.  The server side looks up the entry in the
+		termcap/terminfo data base, and generates a list of
+		names which it then passes one at a time to each
+		request for a terminal type, duplicating the last
+		entry in the list before cycling back to the beginning.
+
+	NAWS:	The Negotiate about Window Size, as per RFC 1073.
+
+	TERMINAL-SPEED:
+		Implemented as per RFC 1079
+
+	TOGGLE-FLOW-CONTROL:
+		Implemented as per RFC 1080
+
+	TIMING-MARK:
+		As per RFC 860
+
+	SGA:	As per RFC 858
+
+	ECHO:	As per RFC 857
+
+	LOGOUT: As per RFC 727
+
+	STATUS:
+		The server will send its current status upon
+		request.  It does not ask for the clients status.
+		The client will request the servers current status
+		from the "send getstatus" command.
+
+	ENVIRON:
+		This option is currently being defined by the IETF
+		Telnet Working Group, and an RFC has not yet been
+		issued, but should be in the near future...
+
+	X-DISPLAY-LOCATION:
+		This functionality can be done through the ENVIRON
+		option, it is added here for completeness.
+
+	AUTHENTICATION:
+		This option is currently being defined by the IETF
+		Telnet Working Group, and an RFC has not yet been
+		issued.  The basic framework is pretty much decided,
+		but the definitions for the specific authentication
+		schemes is still in a state of flux.
+
+	ENCRYPTION:
+		This option is currently being defined by the IETF
+		Telnet Working Group, and an RFC has not yet been
+		issued.  The draft RFC is still in a state of flux,
+		so this code may change in the future.
diff --git a/krb5-1-6/src/appl/telnet/arpa/telnet.h b/krb5-1-6/src/appl/telnet/arpa/telnet.h
new file mode 100644
index 000000000..f6d0eb566
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/arpa/telnet.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)telnet.h	8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _TELNET_H_
+#define	_TELNET_H_
+
+/*
+ * Definitions for the TELNET protocol.
+ */
+#define	IAC	255		/* interpret as command: */
+#define	DONT	254		/* you are not to use option */
+#define	DO	253		/* please, you use option */
+#define	WONT	252		/* I won't use option */
+#define	WILL	251		/* I will use option */
+#define	SB	250		/* interpret as subnegotiation */
+#define	GA	249		/* you may reverse the line */
+#define	EL	248		/* erase the current line */
+#define	EC	247		/* erase the current character */
+#define	AYT	246		/* are you there */
+#define	AO	245		/* abort output--but let prog finish */
+#define	IP	244		/* interrupt process--permanently */
+#define	BREAK	243		/* break */
+#define	DM	242		/* data mark--for connect. cleaning */
+#define	NOP	241		/* nop */
+#define	SE	240		/* end sub negotiation */
+#define EOR     239             /* end of record (transparent mode) */
+#define	ABORT	238		/* Abort process */
+#define	SUSP	237		/* Suspend process */
+#define	xEOF	236		/* End of file: EOF is already used... */
+
+#define SYNCH	242		/* for telfunc calls */
+
+#ifdef TELCMDS
+char *telcmds[] = {
+	"EOF", "SUSP", "ABORT", "EOR",
+	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
+	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
+};
+#else
+extern char *telcmds[];
+#endif
+
+#define	TELCMD_FIRST	xEOF
+#define	TELCMD_LAST	IAC
+#define	TELCMD_OK(x)	((unsigned int)(x) <= TELCMD_LAST && \
+			 (unsigned int)(x) >= TELCMD_FIRST)
+#define	TELCMD(x)	telcmds[(x)-TELCMD_FIRST]
+
+/* telnet options */
+#define TELOPT_BINARY	0	/* 8-bit data path */
+#define TELOPT_ECHO	1	/* echo */
+#define	TELOPT_RCP	2	/* prepare to reconnect */
+#define	TELOPT_SGA	3	/* suppress go ahead */
+#define	TELOPT_NAMS	4	/* approximate message size */
+#define	TELOPT_STATUS	5	/* give status */
+#define	TELOPT_TM	6	/* timing mark */
+#define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
+#define TELOPT_NAOL 	8	/* negotiate about output line width */
+#define TELOPT_NAOP 	9	/* negotiate about output page size */
+#define TELOPT_NAOCRD	10	/* negotiate about CR disposition */
+#define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops */
+#define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
+#define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition */
+#define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
+#define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
+#define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
+#define TELOPT_XASCII	17	/* extended ascic character set */
+#define	TELOPT_LOGOUT	18	/* force logout */
+#define	TELOPT_BM	19	/* byte macro */
+#define	TELOPT_DET	20	/* data entry terminal */
+#define	TELOPT_SUPDUP	21	/* supdup protocol */
+#define	TELOPT_SUPDUPOUTPUT 22	/* supdup output */
+#define	TELOPT_SNDLOC	23	/* send location */
+#define	TELOPT_TTYPE	24	/* terminal type */
+#define	TELOPT_EOR	25	/* end or record */
+#define	TELOPT_TUID	26	/* TACACS user identification */
+#define	TELOPT_OUTMRK	27	/* output marking */
+#define	TELOPT_TTYLOC	28	/* terminal location number */
+#define	TELOPT_3270REGIME 29	/* 3270 regime */
+#define	TELOPT_X3PAD	30	/* X.3 PAD */
+#define	TELOPT_NAWS	31	/* window size */
+#define	TELOPT_TSPEED	32	/* terminal speed */
+#define	TELOPT_LFLOW	33	/* remote flow control */
+#define TELOPT_LINEMODE	34	/* Linemode option */
+#define TELOPT_XDISPLOC	35	/* X Display Location */
+#define TELOPT_OLD_ENVIRON 36	/* Old - Environment variables */
+#define	TELOPT_AUTHENTICATION 37/* Authenticate */
+#define	TELOPT_ENCRYPT	38	/* Encryption option */
+#define TELOPT_NEW_ENVIRON 39	/* New - Environment variables */
+#define	TELOPT_EXOPL	255	/* extended-options-list */
+
+
+#define	NTELOPTS	(1+TELOPT_NEW_ENVIRON)
+#ifdef TELOPTS
+char *telopts[NTELOPTS+1] = {
+	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
+	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
+	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
+	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
+	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
+	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
+	"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
+	"ENCRYPT", "NEW-ENVIRON",
+	0,
+};
+#define	TELOPT_FIRST	TELOPT_BINARY
+#define	TELOPT_LAST	TELOPT_NEW_ENVIRON
+#define	TELOPT_OK(x)	((unsigned int)(x) <= TELOPT_LAST)
+#define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
+#endif
+
+/* sub-option qualifiers */
+#define	TELQUAL_IS	0	/* option is... */
+#define	TELQUAL_SEND	1	/* send option */
+#define	TELQUAL_INFO	2	/* ENVIRON: informational version of IS */
+#define	TELQUAL_REPLY	2	/* AUTHENTICATION: client version of IS */
+#define	TELQUAL_NAME	3	/* AUTHENTICATION: client version of IS */
+
+#define	LFLOW_OFF		0	/* Disable remote flow control */
+#define	LFLOW_ON		1	/* Enable remote flow control */
+#define	LFLOW_RESTART_ANY	2	/* Restart output on any char */
+#define	LFLOW_RESTART_XON	3	/* Restart output only on XON */
+
+/*
+ * LINEMODE suboptions
+ */
+
+#define	LM_MODE		1
+#define	LM_FORWARDMASK	2
+#define	LM_SLC		3
+
+#define	MODE_EDIT	0x01
+#define	MODE_TRAPSIG	0x02
+#define	MODE_ACK	0x04
+#define MODE_SOFT_TAB	0x08
+#define MODE_LIT_ECHO	0x10
+
+#define	MODE_MASK	0x1f
+
+/* Not part of protocol, but needed to simplify things... */
+#define MODE_FLOW		0x0100
+#define MODE_ECHO		0x0200
+#define MODE_INBIN		0x0400
+#define MODE_OUTBIN		0x0800
+#define MODE_FORCE		0x1000
+
+#define	SLC_SYNCH	1
+#define	SLC_BRK		2
+#define	SLC_IP		3
+#define	SLC_AO		4
+#define	SLC_AYT		5
+#define	SLC_EOR		6
+#define	SLC_ABORT	7
+#define	SLC_EOF		8
+#define	SLC_SUSP	9
+#define	SLC_EC		10
+#define	SLC_EL		11
+#define	SLC_EW		12
+#define	SLC_RP		13
+#define	SLC_LNEXT	14
+#define	SLC_XON		15
+#define	SLC_XOFF	16
+#define	SLC_FORW1	17
+#define	SLC_FORW2	18
+
+#define	NSLC		18
+
+/*
+ * For backwards compatability, we define SLC_NAMES to be the
+ * list of names if SLC_NAMES is not defined.
+ */
+#define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
+			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
+			"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
+#ifdef	SLC_NAMES
+char *slc_names[] = {
+	SLC_NAMELIST
+};
+#else
+extern char *slc_names[];
+#define	SLC_NAMES SLC_NAMELIST
+#endif
+
+#define	SLC_NAME_OK(x)	((unsigned int)(x) <= NSLC)
+#define SLC_NAME(x)	slc_names[x]
+
+#define	SLC_NOSUPPORT	0
+#define	SLC_CANTCHANGE	1
+#define	SLC_VARIABLE	2
+#define	SLC_DEFAULT	3
+#define	SLC_LEVELBITS	0x03
+
+#define	SLC_FUNC	0
+#define	SLC_FLAGS	1
+#define	SLC_VALUE	2
+
+#define	SLC_ACK		0x80
+#define	SLC_FLUSHIN	0x40
+#define	SLC_FLUSHOUT	0x20
+
+#define	OLD_ENV_VAR	1
+#define	OLD_ENV_VALUE	0
+#define	NEW_ENV_VAR	0
+#define	NEW_ENV_VALUE	1
+#define	ENV_ESC		2
+#define ENV_USERVAR	3
+
+/*
+ * AUTHENTICATION suboptions
+ */
+
+/*
+ * Who is authenticating who ...
+ */
+#define	AUTH_WHO_CLIENT		0	/* Client authenticating server */
+#define	AUTH_WHO_SERVER		1	/* Server authenticating client */
+#define	AUTH_WHO_MASK		1
+
+/*
+ * amount of authentication done
+ */
+#define	AUTH_HOW_ONE_WAY	0
+#define	AUTH_HOW_MUTUAL		2
+#define	AUTH_HOW_MASK		2
+
+/*
+ * should we be encrypting? (not yet formally standardized)
+ */
+#define AUTH_ENCRYPT_OFF	0
+#define AUTH_ENCRYPT_ON		4
+#define AUTH_ENCRYPT_MASK	4
+
+#define	AUTHTYPE_NULL		0
+#define	AUTHTYPE_KERBEROS_V4	1
+#define	AUTHTYPE_KERBEROS_V5	2
+#define	AUTHTYPE_SPX		3
+#define	AUTHTYPE_MINK		4
+#define	AUTHTYPE_CNT		5
+
+#define	AUTHTYPE_TEST		99
+
+#ifdef	AUTH_NAMES
+char *authtype_names[] = {
+	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
+};
+#else
+extern char *authtype_names[];
+#endif
+
+#define	AUTHTYPE_NAME_OK(x)	((unsigned int)(x) < AUTHTYPE_CNT)
+#define	AUTHTYPE_NAME(x)	authtype_names[x]
+
+/*
+ * ENCRYPTion suboptions
+ */
+#define	ENCRYPT_IS		0	/* I pick encryption type ... */
+#define	ENCRYPT_SUPPORT		1	/* I support encryption types ... */
+#define	ENCRYPT_REPLY		2	/* Initial setup response */
+#define	ENCRYPT_START		3	/* Am starting to send encrypted */
+#define	ENCRYPT_END		4	/* Am ending encrypted */
+#define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
+#define	ENCRYPT_REQEND		6	/* Request you send encrypting */
+#define	ENCRYPT_ENC_KEYID	7
+#define	ENCRYPT_DEC_KEYID	8
+#define	ENCRYPT_CNT		9
+
+#define	ENCTYPE_ANY		0
+#define	ENCTYPE_DES_CFB64	1
+#define	ENCTYPE_DES_OFB64	2
+#define	ENCTYPE_CNT		3
+
+#ifdef	ENCRYPT_NAMES
+char *encrypt_names[] = {
+	"IS", "SUPPORT", "REPLY", "START", "END",
+	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
+	0,
+};
+char *enctype_names[] = {
+	"ANY", "DES_CFB64",  "DES_OFB64",  0,
+};
+#else
+extern char *encrypt_names[];
+extern char *enctype_names[];
+#endif
+
+
+#define	ENCRYPT_NAME_OK(x)	((unsigned int)(x) < ENCRYPT_CNT)
+#define	ENCRYPT_NAME(x)		encrypt_names[x]
+
+#define	ENCTYPE_NAME_OK(x)	((unsigned int)(x) < ENCTYPE_CNT)
+#define	ENCTYPE_NAME(x)		enctype_names[x]
+
+#endif /* !_TELNET_H_ */
diff --git a/krb5-1-6/src/appl/telnet/configure.in b/krb5-1-6/src/appl/telnet/configure.in
new file mode 100644
index 000000000..04173afc4
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/configure.in
@@ -0,0 +1,176 @@
+K5_AC_INIT(configure.in)
+CONFIG_RULES
+dnl AC_CONFIG_SUBDIRS(libtelnet telnet telnetd)
+dnl
+dnl from old libtelnet/configure.in, plus additional header & func checks
+dnl
+AC_REPLACE_FUNCS([strcasecmp strdup setsid strerror strftime getopt herror parsetos])
+AC_CHECK_FUNCS(setenv unsetenv getenv gettosbyname cgetent gettosbyname vsnprintf)
+AC_CHECK_HEADERS(stdlib.h string.h unistd.h arpa/nameser.h sys/select.h arpa/inet.h sys/filio.h curses.h utmp.h sys/time.h sys/tty.h sac.h sys/ptyvar.h sys/stream.h sys/utsname.h memory.h)
+if test $ac_cv_func_setenv = no || test $ac_cv_func_unsetenv = no \
+  || test $ac_cv_func_getenv = no; then
+  SETENVSRC=setenv.c
+  SETENVOBJ=setenv.o
+  AC_SUBST([SETENVSRC])
+  AC_SUBST([SETENVOBJ])
+  AC_DEFINE([NEED_SETENV],1,[Define if setenv needs to be defined])
+fi
+dnl
+KRB5_NEED_PROTO([#include <stdlib.h>],setenv)
+AC_C_CONST
+if test "$KRB4_LIB" = ''; then
+	AC_MSG_RESULT(No Kerberos 4 authentication)
+else
+	AC_MSG_RESULT(Kerberos 4 authentication enabled)
+	AC_DEFINE(KRB4,1,[Define if krb4 authentication is enabled])
+fi
+KRB5_BUILD_LIBRARY_STATIC
+KRB5_BUILD_LIBOBJS
+dnl
+old_LIBS="$LIBS"
+dnl
+dnl from old telnet/configure.in
+dnl
+AC_PROG_INSTALL
+AC_FUNC_VFORK
+AC_HEADER_STDARG
+case $krb5_cv_host in
+*-*-solaris*)
+	if test "$krb5_cv_prog_gcc" = yes; then
+		# Solaris 8 at least has curses.h that is noisy under gcc
+		ac_cv_header_curses_h=yes
+	fi
+	;;
+esac
+dnl
+dnl On some systems, term.h requires curses.h inclusion
+AC_CHECK_HEADERS(term.h,,,dnl
+[#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+])
+dnl
+AC_CHECK_LIB(termcap,main,AC_DEFINE(TERMCAP,1,[Define if termcap library is available])
+LIBS="$LIBS -ltermcap")
+AC_CHECK_LIB(curses,setupterm,LIBS="$LIBS -lcurses",
+  AC_CHECK_LIB(ncurses,setupterm,LIBS="$LIBS -lncurses")
+)
+AC_CHECK_FUNC(tgetent, , [AC_MSG_ERROR([Could not find tgetent; are you missing a curses/ncurses library?])])
+KRB5_AC_INET6
+AC_CHECK_FUNCS(setupterm)
+AC_CHECK_HEADER(termios.h,AC_DEFINE(USE_TERMIO,1,[Define if termio should be used]) ac_termio=1)
+if test -z "$ac_termio"; then
+AC_CHECK_HEADER(termio.h,AC_DEFINE(SYSV_TERMIO,1,[Define if SysV termio interface is found]),ac_sysv_termio=1)
+if test -z "$ac_sysv_termio"; then
+  AC_MSG_CHECKING([for cc_t in termio.h])
+  AC_CACHE_VAL(krb_cv_type_cc_t,
+  [AC_TRY_LINK([cc_t],[#include <termio.h>],
+  [cc_t foo;],krb_cv_type_cc_t=yes,krb_cv_type_cc_t=no)])
+  AC_MSG_RESULT($krb_cv_type_cc_t)
+  if test $krb_cv_type_cc_t = no; then
+    AC_DEFINE(NO_CC_T,1,[Define if termio.h does not define type cc_t])
+  fi
+fi
+fi
+KRB5_NEED_PROTO([#include <unistd.h>
+#include <stdlib.h>],parsetos,1)
+dnl
+KRB5_NEED_PROTO([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>],herror,1)
+dnl
+CHECK_SIGNALS
+if test "$KRB4_LIB" = ''; then
+	AC_MSG_RESULT(No Kerberos 4 authentication)
+else
+	AC_MSG_RESULT(Kerberos 4 authentication enabled)
+	AC_DEFINE(KRB4)
+fi
+dnl
+KRB5_BUILD_PROGRAM
+dnl
+TELNET_LIBS="$LIBS"
+AC_SUBST(TELNET_LIBS)
+LIBS="$old_LIBS"
+dnl
+dnl from old telnetd/configure.in
+dnl
+dnl AC_PROG_INSTALL
+AC_CHECK_LIB(termcap,main,AC_DEFINE(TERMCAP)
+LIBS="$LIBS -ltermcap",
+  AC_CHECK_LIB(curses,setupterm,LIBS="$LIBS -lcurses",
+  AC_CHECK_LIB(ncurses,setupterm,LIBS="$LIBS -lncurses")
+))
+dnl ... whole termios.h/termio.h/NO_CC_T thing again ...
+AC_HEADER_TIME
+dnl KRB5_AC_INET6
+dnl
+dnl Test if speed_t needs to be defined
+AC_CACHE_CHECK([if speed_t is defined], krb5_cv_type_speed_t,
+[AC_TRY_COMPILE(dnl
+[#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifndef	USE_TERMIO
+#include <sgtty.h>
+#else
+# ifdef	SYSV_TERMIO
+# include <termio.h>
+# else
+# include <termios.h>
+# endif
+#endif
+],[speed_t termspeed],krb5_cv_type_speed_t=yes, krb5_cv_type_speed_t=no)])
+if test $krb5_cv_type_speed_t = no; then
+   AC_DEFINE(speed_t, int, [Define if system termios interface doesn't define speed_t])
+fi;
+dnl
+dnl
+dnl Make our operating system-specific security checks and definitions for
+dnl login.
+dnl
+case $krb5_cv_host in
+*-*-hpux*)
+     broken_streams=yes
+     ;;
+*-*-linux*)
+     # Someday Linux may have a Streams user-level interface, so checking
+     # for sys/stream.h may not always work.  But I'm reasonably
+     # sure Linux will never require pushing magic streams modules onto 
+     # pty's! :-)   --- TYT
+     broken_streams=yes
+     ;;
+*-*-irix*)
+     # Irix doesn't have a working granpt, and more over
+     # you can't push anything onto a pty, so telnetd really
+     # Really wants to treat it as if it doesn't have streams
+     broken_streams=yes
+     ;;
+esac
+if test -z "$broken_streams" -a "$ac_cv_header_sys_stream_h" = yes; then
+    AC_CHECK_FUNC(grantpt,AC_DEFINE(STREAMSPTY,1,[Define if streams pty interface should be used]))
+fi
+AC_MSG_CHECKING([if setpgrp takes two arguments])
+dnl
+AC_CACHE_VAL(krb5_cv_sys_setpgrp_two,
+[AC_TRY_LINK( 
+[#include <unistd.h>],[setpgrp(0,0)],
+krb5_cv_sys_setpgrp_two=yes,krb5_cv_sys_setpgrp_two=no)])
+AC_MSG_RESULT($krb5_cv_sys_setpgrp_two)
+if test $krb5_cv_sys_setpgrp_two = yes; then
+  AC_DEFINE(SETPGRP_TWOARG,1,[Define if setpgrp takes two arguments])
+fi
+dnl
+KRB5_NEED_PROTO([#include <stdlib.h>],unsetenv,1)
+dnl KRB5_NEED_PROTO([#include <stdlib.h>],setenv,1)
+dnl KRB5_BUILD_PROGRAM
+dnl
+TELNETD_LIBS="$LIBS"
+AC_SUBST(TELNETD_LIBS)
+LIBS="$old_LIBS"
+dnl
+KRB5_AC_LIBUTIL
+V5_AC_OUTPUT_MAKEFILE(. libtelnet telnet telnetd)
diff --git a/krb5-1-6/src/appl/telnet/kern.diff b/krb5-1-6/src/appl/telnet/kern.diff
new file mode 100644
index 000000000..3c1153bab
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/kern.diff
@@ -0,0 +1,308 @@
+*** h/ioctl.h.old	Tue May 23 14:50:42 1989
+--- h/ioctl.h	Tue Aug 29 18:24:49 1989
+***************
+*** 214,219 ****
+--- 214,220 ----
+  #define		TIOCPKT_START		0x08	/* start output */
+  #define		TIOCPKT_NOSTOP		0x10	/* no more ^S, ^Q */
+  #define		TIOCPKT_DOSTOP		0x20	/* now do ^S ^Q */
++ #define		TIOCPKT_IOCTL		0x40	/* state change of pty driver */
+  #define	TIOCSTOP	_IO('t', 111)		/* stop output, like ^S */
+  #define	TIOCSTART	_IO('t', 110)		/* start output, like ^Q */
+  #define	TIOCMSET	_IOW('t', 109, int)	/* set all modem bits */
+***************
+*** 226,231 ****
+--- 227,235 ----
+  #define	TIOCUCNTL	_IOW('t', 102, int)	/* pty: set/clr usr cntl mode */
+  #define		UIOCCMD(n)	_IO('u', n)		/* usr cntl op "n" */
+  #define	TIOCCONS	_IO('t', 98)		/* become virtual console */
++ #define	TIOCEXT		_IOW('t', 97, int)	/* pty: external processing */
++ #define	TIOCGSTATE	_IOR('t', 96, int)	/* pty: get internal state */
++ #define	TIOCSIG		_IO('t', 95)		/* pty: generate signal */
+  
+  #define	OTTYDISC	0		/* old, v7 std tty driver */
+  #define	NETLDISC	1		/* line discip for berk net */
+*** h/tty.h.old	Tue May 23 14:51:01 1989
+--- h/tty.h	Wed Aug 23 11:30:40 1989
+***************
+*** 70,75 ****
+--- 70,76 ----
+  	struct	ttychars t_chars;	/* tty */
+  	struct	winsize t_winsize;	/* window size */
+  /* be careful of tchars & co. */
++ #ifndef	NO_T_CHARS_DEFINES
+  #define	t_erase		t_chars.tc_erase
+  #define	t_kill		t_chars.tc_kill
+  #define	t_intrc		t_chars.tc_intrc
+***************
+*** 84,89 ****
+--- 85,91 ----
+  #define	t_flushc	t_chars.tc_flushc
+  #define	t_werasc	t_chars.tc_werasc
+  #define	t_lnextc	t_chars.tc_lnextc
++ #endif
+  };
+  
+  #define	TTIPRI	28
+***************
+*** 124,129 ****
+--- 126,132 ----
+  #define	TS_LNCH		0x080000	/* next character is literal */
+  #define	TS_TYPEN	0x100000	/* retyping suspended input (PENDIN) */
+  #define	TS_CNTTB	0x200000	/* counting tab width; leave FLUSHO alone */
++ #define	TS_EXTPROC	0x400000	/* external processing of data */
+  
+  #define	TS_LOCAL	(TS_BKSL|TS_QUOT|TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB)
+  
+*** sys/tty.c.old	Tue May 23 14:52:28 1989
+--- sys/tty.c	Thu Aug 24 09:31:49 1989
+***************
+*** 275,280 ****
+--- 275,285 ----
+  	 */
+  	switch (com) {
+  
++ 	/* get internal state - needed for TS_EXTPROC bit */
++ 	case TIOCGSTATE:
++ 		*(int *)data = tp->t_state;
++ 		break;
++ 
+  	/* get discipline number */
+  	case TIOCGETD:
+  		*(int *)data = tp->t_line;
+***************
+*** 752,757 ****
+--- 757,763 ----
+  	 */
+  	if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0)
+  		c &= 0177;
++     if ((tp->t_state&TS_EXTPROC) == 0) {
+  	/*
+  	 * Check for literal nexting very first
+  	 */
+***************
+*** 834,839 ****
+--- 840,846 ----
+  		else if (c == '\\')
+  			tp->t_state |= TS_BKSL;
+  	}
++     }
+  
+  	/*
+  	 * Cbreak mode, don't process line editing
+***************
+*** 851,856 ****
+--- 858,864 ----
+  		goto endcase;
+  	}
+  
++     if ((tp->t_state&TS_EXTPROC) == 0) {
+  	/*
+  	 * From here on down cooked mode character
+  	 * processing takes place.
+***************
+*** 911,916 ****
+--- 919,925 ----
+  			goto endcase;
+  		}
+  	}
++     }
+  
+  	/*
+  	 * Check for input buffer overflow
+***************
+*** 933,938 ****
+--- 942,948 ----
+  		} else if (tp->t_rocount++ == 0)
+  			tp->t_rocol = tp->t_col;
+  		tp->t_state &= ~TS_QUOT;
++ 	    if ((tp->t_state&TS_EXTPROC) == 0) {
+  		if (c == '\\')
+  			tp->t_state |= TS_QUOT;
+  		if (tp->t_state&TS_ERASE) {
+***************
+*** 948,953 ****
+--- 958,964 ----
+  				i--;
+  			}
+  		}
++ 	    }
+  	}
+  endcase:
+  	/*
+***************
+*** 998,1005 ****
+  		return (-1);
+  	/*
+  	 * Turn tabs to spaces as required
+  	 */
+! 	if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
+  		register int s;
+  
+  		c = 8 - (tp->t_col&7);
+--- 1009,1022 ----
+  		return (-1);
+  	/*
+  	 * Turn tabs to spaces as required
++ 	 *
++ 	 * Special case if we have external processing, we don't
++ 	 * do the tab expansion because we'll probably get it
++ 	 * wrong.  If tab expansion needs to be done, let it
++ 	 * happen externally.
+  	 */
+! 	if ((tp->t_state&TS_EXTPROC) == 0 &&
+! 	    c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
+  		register int s;
+  
+  		c = 8 - (tp->t_col&7);
+***************
+*** 1497,1503 ****
+  	int s;
+  	char *nextc();
+  
+! 	if ((tp->t_flags&ECHO) == 0)
+  		return;
+  	tp->t_flags &= ~FLUSHO;
+  	c &= 0377;
+--- 1514,1520 ----
+  	int s;
+  	char *nextc();
+  
+! 	if ((tp->t_flags&ECHO) == 0 || (tp->t_state&TS_EXTPROC))
+  		return;
+  	tp->t_flags &= ~FLUSHO;
+  	c &= 0377;
+***************
+*** 1618,1624 ****
+  
+  	if ((tp->t_state&TS_CNTTB) == 0)
+  		tp->t_flags &= ~FLUSHO;
+! 	if ((tp->t_flags&ECHO) == 0)
+  		return;
+  	c &= 0377;
+  	if (tp->t_flags&RAW) {
+--- 1635,1641 ----
+  
+  	if ((tp->t_state&TS_CNTTB) == 0)
+  		tp->t_flags &= ~FLUSHO;
+! 	if ((tp->t_flags&ECHO) == 0 || (tp->t_state&TS_EXTPROC))
+  		return;
+  	c &= 0377;
+  	if (tp->t_flags&RAW) {
+*** sys/tty_pty.c.old	Tue May 23 14:52:43 1989
+--- sys/tty_pty.c	Tue Aug 29 18:48:36 1989
+***************
+*** 208,213 ****
+--- 208,214 ----
+  		return (EIO);
+  	tp->t_oproc = ptsstart;
+  	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
++ 	tp->t_state &= ~TS_EXTPROC;
+  	pti = &pt_ioctl[minor(dev)];
+  	pti->pt_flags = 0;
+  	pti->pt_send = 0;
+***************
+*** 247,252 ****
+--- 248,275 ----
+  				error = ureadc((int)pti->pt_send, uio);
+  				if (error)
+  					return (error);
++ 				if (pti->pt_send & TIOCPKT_IOCTL) {
++ 					struct xx {
++ 						struct sgttyb a;
++ 						struct tchars b;
++ 						struct ltchars c;
++ 						int d;
++ 						int e;
++ 					} cb;
++ 					cb.a.sg_ispeed = tp->t_ispeed;
++ 					cb.a.sg_ospeed = tp->t_ospeed;
++ 					cb.a.sg_erase = tp->t_erase;
++ 					cb.a.sg_kill = tp->t_kill;
++ 					cb.a.sg_flags = tp->t_flags;
++ 					bcopy((caddr_t)&tp->t_intrc,
++ 					      (caddr_t)&cb.b, sizeof(cb.b));
++ 					bcopy((caddr_t)&tp->t_suspc,
++ 					      (caddr_t)&cb.c, sizeof(cb.c));
++ 					cb.d = tp->t_state;
++ 					cb.e = ((unsigned)tp->t_flags)>>16;
++ 					cc = MIN(uio->uio_resid, sizeof(cb));
++ 					uiomove(&cb, cc, UIO_READ, uio);
++ 				}
+  				pti->pt_send = 0;
+  				return (0);
+  			}
+***************
+*** 483,488 ****
+--- 506,533 ----
+  	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
+  	 * ttywflush(tp) will hang if there are characters in the outq.
+  	 */
++ 	if (cmd == TIOCEXT) {
++ 		/*
++ 		 * When the TS_EXTPROC bit is being toggled, we need
++ 		 * to send an TIOCPKT_IOCTL if the packet driver
++ 		 * is turned on.
++ 		 */
++ 		if (*(int *)data) {
++ 			if (pti->pt_flags & PF_PKT) {
++ 				pti->pt_send |= TIOCPKT_IOCTL;
++ 				ptcwakeup(tp);
++ 			}
++ 			tp->t_state |= TS_EXTPROC;
++ 		} else {
++ 			if ((tp->t_state & TS_EXTPROC) &&
++ 			    (pti->pt_flags & PF_PKT)) {
++ 				pti->pt_send |= TIOCPKT_IOCTL;
++ 				ptcwakeup(tp);
++ 			}
++ 			tp->t_state &= ~TS_EXTPROC;
++ 		}
++ 		return (0);
++ 	} else
+  	if (cdevsw[major(dev)].d_open == ptcopen)
+  		switch (cmd) {
+  
+***************
+*** 525,530 ****
+--- 570,583 ----
+  			while (getc(&tp->t_outq) >= 0)
+  				;
+  			break;
++ 
++ 		case TIOCSIG:
++ 			if (*(unsigned int *)data >= NSIG)
++ 				return(EINVAL);
++ 			if ((tp->t_flags&NOFLSH) == 0)
++ 				ttyflush(tp, FREAD|FWRITE);
++ 			gsignal(tp->t_pgrp, *(unsigned int *)data);
++ 			return(0);
+  		}
+  	error = ttioctl(tp, cmd, data, flag);
+  	/*
+***************
+*** 549,554 ****
+--- 602,624 ----
+  			return (0);
+  		}
+  		error = ENOTTY;
++ 	}
++ 	/*
++ 	 * If external processing and packet mode send ioctl packet.
++ 	 */
++ 	if ((tp->t_state & TS_EXTPROC) && (pti->pt_flags & PF_PKT)) {
++ 		switch(cmd) {
++ 		case TIOCSETP:
++ 		case TIOCSETN:
++ 		case TIOCSETC:
++ 		case TIOCSLTC:
++ 		case TIOCLBIS:
++ 		case TIOCLBIC:
++ 		case TIOCLSET:
++ 			pti->pt_send |= TIOCPKT_IOCTL;
++ 		default:
++ 			break;
++ 		}
+  	}
+  	stop = (tp->t_flags & RAW) == 0 &&
+  	    tp->t_stopc == CTRL('s') && tp->t_startc == CTRL('q');
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/Makefile.in b/krb5-1-6/src/appl/telnet/libtelnet/Makefile.in
new file mode 100644
index 000000000..2a6c7dc51
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/Makefile.in
@@ -0,0 +1,141 @@
+thisconfigdir=..
+myfulldir=appl/telnet/libtelnet
+mydir=libtelnet
+BUILDTOP=$(REL)..$(S)..$(S)..
+# derived from the original Makefile.generic
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted provided
+# that: (1) source distributions retain this entire copyright notice and
+# comment, and (2) distributions including binaries display the following
+# acknowledgement:  ``This product includes software developed by the
+# University of California, Berkeley and its contributors'' in the
+# documentation or other materials provided with the distribution and in
+# all advertising materials mentioning features or use of this software.
+# Neither the name of the University nor the names of its contributors may
+# be used to endorse or promote products derived from this software without
+# specific prior written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+#	@(#)Makefile.generic	5.5 (Berkeley) 3/1/91
+#
+AUTH_DEF=-DAUTHENTICATION -DENCRYPTION -DDES_ENCRYPTION -DKRB5 -DFORWARD \
+	-UNO_LOGIN_F -DLOGIN_CAP_F -DLOGIN_PROGRAM=KRB5_PATH_LOGIN
+LOCALINCLUDES=-I.. -I$(srcdir)/.. @KRB4_INCLUDES@
+DEFINES = -DTELNET_BUFSIZE=65535 $(AUTH_DEF)
+LIBOBJS=@LIBOBJS@
+
+SETENVSRC=@SETENVSRC@
+SETENVOBJ=@SETENVOBJ@
+
+LIBBASE=telnet
+LIBMAJOR=0
+LIBMINOR=0
+RELDIR=../../../appl/telnet/libtelnet
+STOBJLISTS=OBJS.ST
+
+SRCS=   $(srcdir)/auth.c \
+	$(srcdir)/encrypt.c \
+	$(srcdir)/genget.c \
+	$(srcdir)/misc.c \
+	$(srcdir)/kerberos.c \
+	$(srcdir)/kerberos5.c \
+	$(srcdir)/forward.c \
+	$(srcdir)/spx.c \
+	$(srcdir)/enc_des.c \
+	$(srcdir)/setenv.c \
+	$(srcdir)/getent.c \
+	$(srcdir)/parsetos.c \
+	$(srcdir)/strdup.c \
+	$(srcdir)/strcasecmp.c \
+	$(srcdir)/strchr.c \
+	$(srcdir)/strrchr.c \
+	$(srcdir)/strftime.c \
+	$(srcdir)/strerror.c
+
+STLIBOBJS=   auth.o encrypt.o genget.o \
+	misc.o kerberos.o kerberos5.o forward.o spx.o enc_des.o \
+	$(LIBOBJS) getent.o $(SETENVOBJ)
+
+TELNET_H= $(srcdir)/../arpa/telnet.h
+
+all:: all-libs
+
+clean:: clean-libs clean-libobjs
+
+auth.o: $(TELNET_H)
+auth.o: encrypt.h
+auth.o: auth.h
+auth.o: misc-proto.h
+encrypt.o: $(TELNET_H)
+encrypt.o: encrypt.h
+encrypt.o: misc.h
+kerberos.o: $(TELNET_H)
+kerberos.o: encrypt.h
+kerberos.o: auth.h
+kerberos.o: misc.h
+kerberos5.o: $(TELNET_H)
+kerberos5.o: encrypt.h
+kerberos5.o: auth.h
+kerberos5.o: misc.h
+misc.o: misc.h
+enc_des.o: $(TELNET_H)
+enc_des.o: encrypt.h
+enc_des.o: key-proto.h
+enc_des.o: misc-proto.h
+install::
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+auth.so auth.po $(OUTPRE)auth.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  auth-proto.h auth.c auth.h enc-proto.h encrypt.h misc-proto.h
+encrypt.so encrypt.po $(OUTPRE)encrypt.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  enc-proto.h encrypt.c encrypt.h misc-proto.h misc.h
+genget.so genget.po $(OUTPRE)genget.$(OBJEXT): genget.c \
+  misc-proto.h misc.h
+misc.so misc.po $(OUTPRE)misc.$(OBJEXT): auth-proto.h \
+  auth.h enc-proto.h encrypt.h misc-proto.h misc.c misc.h
+kerberos.so kerberos.po $(OUTPRE)kerberos.$(OBJEXT): \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(srcdir)/../arpa/telnet.h auth-proto.h auth.h enc-proto.h \
+  encrypt.h kerberos.c misc-proto.h misc.h
+kerberos5.so kerberos5.po $(OUTPRE)kerberos5.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  auth-proto.h auth.h enc-proto.h encrypt.h kerberos5.c \
+  krb5forw.h misc-proto.h misc.h
+forward.so forward.po $(OUTPRE)forward.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h forward.c \
+  krb5forw.h
+spx.so spx.po $(OUTPRE)spx.$(OBJEXT): misc-proto.h \
+  spx.c
+enc_des.so enc_des.po $(OUTPRE)enc_des.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h $(srcdir)/../arpa/telnet.h \
+  enc-proto.h enc_des.c encrypt.h key-proto.h misc-proto.h
+setenv.so setenv.po $(OUTPRE)setenv.$(OBJEXT): misc-proto.h \
+  setenv.c
+getent.so getent.po $(OUTPRE)getent.$(OBJEXT): getent.c \
+  gettytab.h
+parsetos.so parsetos.po $(OUTPRE)parsetos.$(OBJEXT): \
+  misc-proto.h parsetos.c
+strdup.so strdup.po $(OUTPRE)strdup.$(OBJEXT): strdup.c
+strcasecmp.so strcasecmp.po $(OUTPRE)strcasecmp.$(OBJEXT): \
+  strcasecmp.c
+strchr.so strchr.po $(OUTPRE)strchr.$(OBJEXT): strchr.c
+strrchr.so strrchr.po $(OUTPRE)strrchr.$(OBJEXT): strrchr.c
+strftime.so strftime.po $(OUTPRE)strftime.$(OBJEXT): \
+  strftime.c
+strerror.so strerror.po $(OUTPRE)strerror.$(OBJEXT): \
+  strerror.c
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/auth-proto.h b/krb5-1-6/src/appl/telnet/libtelnet/auth-proto.h
new file mode 100644
index 000000000..6b4957032
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/auth-proto.h
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)auth-proto.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#if	defined(AUTHENTICATION)
+Authenticator *findauthenticator (int, int);
+
+void auth_init (char *, int);
+int auth_cmd (int, char **);
+void auth_request (void);
+void auth_send (unsigned char *, int);
+void auth_send_retry (void);
+void auth_is (unsigned char *, int);
+void auth_reply (unsigned char *, int);
+void auth_finished (Authenticator *, int);
+void auth_wait (char *);
+int auth_check (char *);
+int auth_must_encrypt (void);
+void auth_disable_name (char *);
+void auth_gen_printsub (unsigned char *, int, unsigned char *, unsigned int);
+
+
+int getauthmask (char *, int *);
+int auth_enable (char *);
+int auth_disable (char *);
+int auth_onoff (char *, int);
+int auth_togdebug (int);
+int auth_status (void);
+void auth_name (unsigned char *, int);
+int auth_sendname (unsigned char *, int);
+void auth_debug (int);
+void auth_printsub (unsigned char *, int, unsigned char *, unsigned int);
+
+
+#ifdef	KRB4
+int kerberos4_init (Authenticator *, int);
+int kerberos4_send (Authenticator *);
+void kerberos4_is (Authenticator *, unsigned char *, int);
+void kerberos4_reply (Authenticator *, unsigned char *, int);
+int kerberos4_status (Authenticator *, char *, int);
+void kerberos4_printsub (unsigned char *, int, unsigned char *, unsigned int);
+#endif
+
+#ifdef	KRB5
+int kerberos5_init (Authenticator *, int);
+int kerberos5_send (Authenticator *);
+void kerberos5_is (Authenticator *, unsigned char *, int);
+void kerberos5_reply (Authenticator *, unsigned char *, int);
+int kerberos5_status (Authenticator *, char *, int);
+void kerberos5_printsub (unsigned char *, int, unsigned char *, unsigned int);
+void kerberos5_cleanup (void);
+#endif
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/auth.c b/krb5-1-6/src/appl/telnet/libtelnet/auth.c
new file mode 100644
index 000000000..28b8ae8d1
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/auth.c
@@ -0,0 +1,669 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)auth.c	8.1 (Berkeley) 6/4/93 */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may 
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#if	defined(AUTHENTICATION)
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#define	AUTH_NAMES
+#include <arpa/telnet.h>
+#ifdef	__STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc-proto.h"
+#include "auth-proto.h"
+
+#define	typemask(x)		(1<<((x)-1))
+
+
+
+int auth_debug_mode = 0;
+int auth_has_failed = 0;
+int auth_enable_encrypt = 0;
+int auth_client_non_unix = 0;
+static 	char	*Name = "Noname";
+static	int	Server = 0;
+static	Authenticator	*authenticated = 0;
+static	int	authenticating = 0;
+static	int	validuser = 0;
+static	unsigned char	_auth_send_data[256];
+static	unsigned char	*auth_send_data;
+static	int	auth_send_cnt = 0;
+
+/*
+ * Authentication types supported.  Plese note that these are stored
+ * in priority order, i.e. try the first one first.
+ */
+Authenticator authenticators[] = {
+#ifdef	SPX
+	{ AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
+				spx_init,
+				spx_send,
+				spx_is,
+				spx_reply,
+				spx_status,
+				spx_printsub },
+	{ AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+				spx_init,
+				spx_send,
+				spx_is,
+				spx_reply,
+				spx_status,
+				spx_printsub },
+#endif
+#ifdef	KRB5
+#ifdef ENCRYPTION
+	{ AUTHTYPE_KERBEROS_V5,
+		  AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL|AUTH_ENCRYPT_ON,
+				kerberos5_init,
+				kerberos5_send,
+				kerberos5_is,
+				kerberos5_reply,
+				kerberos5_status,
+				kerberos5_printsub },
+#endif	
+	{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
+				kerberos5_init,
+				kerberos5_send,
+				kerberos5_is,
+				kerberos5_reply,
+				kerberos5_status,
+				kerberos5_printsub },
+	{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+				kerberos5_init,
+				kerberos5_send,
+				kerberos5_is,
+				kerberos5_reply,
+				kerberos5_status,
+				kerberos5_printsub },
+#endif
+#ifdef	KRB4
+# ifdef ENCRYPTION
+	{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
+				kerberos4_init,
+				kerberos4_send,
+				kerberos4_is,
+				kerberos4_reply,
+				kerberos4_status,
+				kerberos4_printsub },
+# endif	/* ENCRYPTION */
+	{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+				kerberos4_init,
+				kerberos4_send,
+				kerberos4_is,
+				kerberos4_reply,
+				kerberos4_status,
+				kerberos4_printsub },
+#endif
+	{ 0, },
+};
+
+static Authenticator NoAuth = { 0 };
+
+static int	i_support = 0;
+static int	i_wont_support = 0;
+
+	Authenticator *
+findauthenticator(type, way)
+	int type;
+	int way;
+{
+	Authenticator *ap = authenticators;
+
+	while (ap->type && (ap->type != type || ap->way != way))
+		++ap;
+	return(ap->type ? ap : 0);
+}
+
+	void
+auth_init(name, server)
+	char *name;
+	int server;
+{
+	Authenticator *ap = authenticators;
+
+	Server = server;
+	Name = name;
+
+	i_support = 0;
+	authenticated = 0;
+	authenticating = 0;
+	while (ap->type) {
+		if (!ap->init || (*ap->init)(ap, server)) {
+			i_support |= typemask(ap->type);
+			if (auth_debug_mode)
+				printf(">>>%s: I support auth type %d %d\r\n",
+					Name,
+					ap->type, ap->way);
+		}
+		++ap;
+	}
+}
+
+	void
+auth_disable_name(name)
+	char *name;
+{
+	int x;
+	for (x = 0; x < AUTHTYPE_CNT; ++x) {
+		if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
+			i_wont_support |= typemask(x);
+			break;
+		}
+	}
+}
+
+	int
+getauthmask(type, maskp)
+	char *type;
+	int *maskp;
+{
+	register int x;
+
+	if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
+		*maskp = -1;
+		return(1);
+	}
+
+	for (x = 1; x < AUTHTYPE_CNT; ++x) {
+		if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
+			*maskp = typemask(x);
+			return(1);
+		}
+	}
+	return(0);
+}
+
+	int
+auth_enable(type)
+	char * type;
+{
+	return(auth_onoff(type, 1));
+}
+
+	int
+auth_disable(type)
+	char * type;
+{
+	return(auth_onoff(type, 0));
+}
+
+	int
+auth_onoff(type, on)
+	char *type;
+	int on;
+{
+	int i, mask = -1;
+	Authenticator *ap;
+
+	if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
+                printf("auth %s 'type'\n", on ? "enable" : "disable");
+		printf("Where 'type' is one of:\n");
+		printf("\t%s\n", AUTHTYPE_NAME(0));
+		mask = 0;
+		for (ap = authenticators; ap->type; ap++) {
+			if ((mask & (i = typemask(ap->type))) != 0)
+				continue;
+			mask |= i;
+			printf("\t%s\n", AUTHTYPE_NAME(ap->type));
+		}
+		return(0);
+	}
+
+	if (!getauthmask(type, &mask)) {
+		printf("%s: invalid authentication type\n", type);
+		return(0);
+	}
+	if (on)
+		i_wont_support &= ~mask;
+	else
+		i_wont_support |= mask;
+	return(1);
+}
+
+	int
+auth_togdebug(on)
+	int on;
+{
+	if (on < 0)
+		auth_debug_mode ^= 1;
+	else
+		auth_debug_mode = on;
+	printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
+	return(1);
+}
+
+	int
+auth_status()
+{
+	Authenticator *ap;
+	int i, mask;
+
+	if (i_wont_support == -1)
+		printf("Authentication disabled\n");
+	else
+		printf("Authentication enabled\n");
+
+	mask = 0;
+	for (ap = authenticators; ap->type; ap++) {
+		if ((mask & (i = typemask(ap->type))) != 0)
+			continue;
+		mask |= i;
+		printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
+			(i_wont_support & typemask(ap->type)) ?
+					"disabled" : "enabled");
+	}
+	return(1);
+}
+
+/*
+ * This routine is called by the server to start authentication
+ * negotiation.
+ */
+	void
+auth_request()
+{
+	static unsigned char str_request[64] = { IAC, SB,
+						 TELOPT_AUTHENTICATION,
+						 TELQUAL_SEND, };
+	Authenticator *ap = authenticators;
+	unsigned char *e = str_request + 4;
+
+	if (!authenticating) {
+		authenticating = 1;
+		while (ap->type) {
+			if (i_support & ~i_wont_support & typemask(ap->type)) {
+				if (ap->type == AUTHTYPE_KERBEROS_V4 ||
+				    !auth_client_non_unix) {
+					if (auth_debug_mode) {
+						printf(">>>%s: Sending type %d %d\r\n",
+						       Name, ap->type, ap->way);
+					}
+					*e++ = ap->type;
+					*e++ = ap->way;
+				}
+			}
+			++ap;
+		}
+		if (auth_client_non_unix) {
+			ap = authenticators;
+			while (ap->type) {
+				if (i_support & ~i_wont_support & typemask(ap->type)) {
+					*e++ = ap->type;
+					*e++ = ap->way;
+				}
+				++ap;
+			}
+		}
+		*e++ = IAC;
+		*e++ = SE;
+		net_write(str_request, e - str_request);
+		printsub('>', &str_request[2], e - str_request - 2);
+	}
+}
+
+/*
+ * This is called when an AUTH SEND is received.
+ * It should never arrive on the server side (as only the server can
+ * send an AUTH SEND).
+ * You should probably respond to it if you can...
+ *
+ * If you want to respond to the types out of order (i.e. even
+ * if he sends  LOGIN KERBEROS and you support both, you respond
+ * with KERBEROS instead of LOGIN (which is against what the
+ * protocol says)) you will have to hack this code...
+ */
+	void
+auth_send(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	if (Server) {
+		if (auth_debug_mode) {
+			printf(">>>%s: auth_send called!\r\n", Name);
+		}
+		return;
+	}
+
+	if (auth_debug_mode) {
+		printf(">>>%s: auth_send got:", Name);
+		printd(data, cnt); printf("\r\n");
+	}
+
+	/*
+	 * Save the list of authentication mechanisms
+	 */
+	auth_send_cnt = cnt;
+	if (auth_send_cnt > sizeof(_auth_send_data))
+	    auth_send_cnt = sizeof(_auth_send_data);
+	memcpy((void *)_auth_send_data, (void *)data, 
+	       (unsigned) auth_send_cnt);
+	auth_send_data = _auth_send_data;
+
+	auth_send_retry();
+}
+
+/*
+ * Try the next authentication mechanism on the list, and see if it
+ * works.
+ */
+void auth_send_retry()
+{
+	Authenticator *ap;
+	static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
+					    TELQUAL_IS, AUTHTYPE_NULL, 0,
+					    IAC, SE };
+	
+	if (Server) {
+		if (auth_debug_mode) {
+			printf(">>>%s: auth_send_retry called!\r\n", Name);
+		}
+		return;
+	}
+
+	for (;(auth_send_cnt -= 2) >= 0; auth_send_data += 2) {
+	    if (auth_debug_mode)
+		printf(">>>%s: He supports %d\r\n", Name, *auth_send_data);
+	    if (!(i_support & typemask(*auth_send_data)))
+		continue;
+	    if (i_wont_support & typemask(*auth_send_data))
+		continue;
+	    ap = findauthenticator(auth_send_data[0], auth_send_data[1]);
+	    if (!ap || !ap->send)
+		continue;
+	    if ((ap->way & AUTH_ENCRYPT_MASK) && !auth_enable_encrypt)
+		continue;
+
+	    if (auth_debug_mode)
+		printf(">>>%s: Trying %d %d\r\n", Name, auth_send_data[0],
+		       auth_send_data[1]);
+	    if ((*ap->send)(ap)) {
+		/*
+		 * Okay, we found one we like and did it.  we can go
+		 * home now.
+		 */
+		if (auth_debug_mode)
+		    printf(">>>%s: Using type %d\r\n", Name, *auth_send_data);
+		auth_send_data += 2;
+		return;
+	    }
+	}
+	net_write(str_none, sizeof(str_none));
+	printsub('>', &str_none[2], sizeof(str_none) - 2);
+	if (auth_debug_mode)
+		printf(">>>%s: Sent failure message\r\n", Name);
+	auth_finished(0, AUTH_REJECT);
+	auth_has_failed = 1;
+#ifdef KANNAN
+	/*
+	 *  We requested strong authentication, however no mechanisms worked.
+	 *  Therefore, exit on client end.
+	 */
+	printf("Unable to securely authenticate user ... exit\n"); 
+	exit(0);
+#endif /* KANNAN */
+}
+
+	void
+auth_is(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	Authenticator *ap;
+
+	if (cnt < 2)
+		return;
+
+	if (data[0] == AUTHTYPE_NULL) {
+		auth_finished(0, AUTH_REJECT);
+		return;
+	}
+
+	if ((ap = findauthenticator(data[0], data[1]))) {
+		if (ap->is)
+			(*ap->is)(ap, data+2, cnt-2);
+	} else if (auth_debug_mode)
+		printf(">>>%s: Invalid authentication in IS: %d\r\n",
+			Name, *data);
+}
+
+	void
+auth_reply(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	Authenticator *ap;
+
+	if (cnt < 2)
+		return;
+
+	if ((ap = findauthenticator(data[0], data[1]))) {
+		if (ap->reply)
+			(*ap->reply)(ap, data+2, cnt-2);
+	} else if (auth_debug_mode)
+		printf(">>>%s: Invalid authentication in SEND: %d\r\n",
+			Name, *data);
+}
+
+	void
+auth_name(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	unsigned char savename[256];
+
+	if (cnt < 1) {
+		if (auth_debug_mode)
+			printf(">>>%s: Empty name in NAME\r\n", Name);
+		return;
+	}
+	if (cnt > sizeof(savename) - 1) {
+		if (auth_debug_mode)
+			printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
+					Name, cnt, (int) sizeof(savename)-1);
+		return;
+	}
+	memcpy((void *)savename, (void *)data, (unsigned) cnt);
+	savename[cnt] = '\0';	/* Null terminate */
+	if (auth_debug_mode)
+		printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
+	auth_encrypt_user((const char *)savename);
+}
+
+	int
+auth_sendname(cp, len)
+	unsigned char *cp;
+	int len;
+{
+	static unsigned char str_request[256+6]
+			= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
+	register unsigned char *e = str_request + 4;
+	register unsigned char *ee = &str_request[sizeof(str_request)-2];
+
+	while (--len >= 0) {
+		if ((*e++ = *cp++) == IAC)
+			*e++ = IAC;
+		if (e >= ee)
+			return(0);
+	}
+	*e++ = IAC;
+	*e++ = SE;
+	net_write(str_request, e - str_request);
+	printsub('>', &str_request[2], e - &str_request[2]);
+	return(1);
+}
+
+	void
+auth_finished(ap, result)
+	Authenticator *ap;
+	int result;
+{
+	if (!(authenticated = ap))
+		authenticated = &NoAuth;
+	validuser = result;
+}
+
+	/* ARGSUSED */
+	static void
+auth_intr(sig)
+	int sig;
+{
+	auth_finished(0, AUTH_REJECT);
+}
+
+	void
+auth_wait(name)
+	char *name;
+{
+	if (auth_debug_mode)
+		printf(">>>%s: in auth_wait.\r\n", Name);
+
+	if (Server && !authenticating)
+		return;
+
+	(void) signal(SIGALRM, auth_intr);
+	alarm(30);
+	while (!authenticated)
+		if (telnet_spin())
+			break;
+	alarm(0);
+	(void) signal(SIGALRM, SIG_DFL);
+}
+
+	int
+auth_check(name)
+	char *name;
+{
+	/*
+	 * Now check to see if the user is valid or not
+	 */
+	if (!authenticated || authenticated == &NoAuth)
+		return(AUTH_REJECT);
+
+	if (validuser == AUTH_VALID)
+		validuser = AUTH_USER;
+
+	if (authenticated->status)
+		validuser = (*authenticated->status)(authenticated,
+						     name, validuser);
+	return(validuser);
+}
+
+int auth_must_encrypt()
+{
+    if (authenticated &&
+	((authenticated->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON))
+	return 1;
+    return 0;
+}
+
+	void
+auth_debug(mode)
+	int mode;
+{
+	auth_debug_mode = mode;
+}
+
+	void
+auth_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt;
+	unsigned int buflen;
+{
+	Authenticator *ap;
+
+	if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
+		(*ap->printsub)(data, cnt, buf, buflen);
+	else
+		auth_gen_printsub(data, cnt, buf, buflen);
+}
+
+	void
+auth_gen_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt;
+	unsigned int buflen;
+{
+	register unsigned char *cp;
+	unsigned char tbuf[16];
+
+	cnt -= 3;
+	data += 3;
+	buf[buflen-1] = '\0';
+	buf[buflen-2] = '*';
+	buflen -= 2;
+	for (; cnt > 0; cnt--, data++) {
+		sprintf((char *)tbuf, " %d", *data);
+		for (cp = tbuf; *cp && buflen > 0; --buflen)
+			*buf++ = *cp++;
+		if (buflen <= 0)
+			return;
+	}
+	*buf = '\0';
+}
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/auth.h b/krb5-1-6/src/appl/telnet/libtelnet/auth.h
new file mode 100644
index 000000000..f9f31d8e7
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/auth.h
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)auth.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef	__AUTH__
+#define	__AUTH__
+
+#define	AUTH_REJECT	0	/* Rejected */
+#define	AUTH_UNKNOWN	1	/* We don't know who he is, but he's okay */
+#define	AUTH_OTHER	2	/* We know him, but not his name */
+#define	AUTH_USER	3	/* We know he name */
+#define	AUTH_VALID	4	/* We know him, and he needs no password */
+
+typedef struct XauthP {
+	int	type;
+	int	way;
+	int	(*init) (struct XauthP *, int);
+	int	(*send) (struct XauthP *);
+	void	(*is) (struct XauthP *, unsigned char *, int);
+	void	(*reply) (struct XauthP *, unsigned char *, int);
+	int	(*status) (struct XauthP *, char *, int);
+	void	(*printsub) (unsigned char *, int, unsigned char *, unsigned int);
+} Authenticator;
+
+#include "auth-proto.h"
+
+#define OPTS_FORWARD_CREDS           0x00000002
+#define OPTS_FORWARDABLE_CREDS       0x00000001
+
+extern int auth_debug_mode;
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/enc-proto.h b/krb5-1-6/src/appl/telnet/libtelnet/enc-proto.h
new file mode 100644
index 000000000..eed7db66b
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/enc-proto.h
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)enc-proto.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+#ifdef	ENCRYPTION
+void encrypt_init (char *, int);
+Encryptions *findencryption (int);
+Encryptions *finddecryption (int);
+void encrypt_send_supprt (void);
+void encrypt_auto (int);
+void decrypt_auto (int);
+void encrypt_debug (int);
+void encrypt_is (unsigned char *, int);
+void encrypt_reply (unsigned char *, int);
+void encrypt_start_input (int);
+void encrypt_session_key (Session_Key *, int);
+void encrypt_end_input (void);
+void encrypt_start_output (int);
+void encrypt_end_output (void);
+void encrypt_send_request_start (void);
+void encrypt_send_request_end (void);
+void encrypt_send_end (void);
+void encrypt_wait (void);
+int encrypt_is_encrypting (void);
+int EncryptAutoEnc (int);
+int EncryptAutoDec (int);
+int EncryptEnable (char *, char *);
+int EncryptDisable (char *, char *);
+int EncryptDebug (int);
+int EncryptType (char *, char *);
+int EncryptStart (char *);
+int EncryptStartInput (void);
+int EncryptStartOutput (void);
+int EncryptStop (char *);
+int EncryptStopInput (void);
+int EncryptStopOutput (void);
+int EncryptStatus (void);
+int EncryptVerbose (int);
+void encrypt_send_support (void);
+void encrypt_send_keyid (int, unsigned char *, unsigned int, int);
+int net_write (unsigned char *, int);
+void encrypt_gen_printsub (unsigned char *, int, unsigned char *, int);
+void encrypt_printsub (unsigned char *, int, unsigned char *, int);
+
+
+void encrypt_request_start (unsigned char *, int);
+void encrypt_request_end (void);
+void encrypt_enc_keyid (unsigned char *, int);
+void encrypt_dec_keyid (unsigned char *, int);
+void encrypt_support (unsigned char *, int);
+void encrypt_start (unsigned char *, int);
+void encrypt_end (void);
+
+
+#ifdef	TELENTD
+void encrypt_wait (void);
+#else
+void printsub (int, unsigned char *, int);
+int encrypt_cmd (int, char **);
+void encrypt_display (void);
+#endif
+
+void krbdes_encrypt (unsigned char *, int);
+int krbdes_decrypt (int);
+int krbdes_is (unsigned char *, int);
+int krbdes_reply (unsigned char *, int);
+void krbdes_init (int);
+int krbdes_start (int, int);
+void krbdes_session (Session_Key *, int);
+void krbdes_printsub (unsigned char *, int, unsigned char *, int);
+
+void cfb64_encrypt (unsigned char *, int);
+int cfb64_decrypt (int);
+void cfb64_init (int);
+int cfb64_start (int, int);
+int cfb64_is (unsigned char *, int);
+int cfb64_reply (unsigned char *, int);
+void cfb64_session (Session_Key *, int);
+int cfb64_keyid (int, unsigned char *, int *);
+void cfb64_printsub (unsigned char *, int, unsigned char *, int);
+
+void ofb64_encrypt (unsigned char *, int);
+int ofb64_decrypt (int);
+void ofb64_init (int);
+int ofb64_start (int, int);
+int ofb64_is (unsigned char *, int);
+int ofb64_reply (unsigned char *, int);
+void ofb64_session (Session_Key *, int);
+int ofb64_keyid (int, unsigned char *, int *);
+void ofb64_printsub (unsigned char *, int, unsigned char *, int);
+#endif	/* ENCRYPTION */
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/enc_des.c b/krb5-1-6/src/appl/telnet/libtelnet/enc_des.c
new file mode 100644
index 000000000..c399d22c7
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/enc_des.c
@@ -0,0 +1,780 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * 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__
+#include <stdlib.h>
+#endif
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include "encrypt.h"
+#include "key-proto.h"
+#include "misc-proto.h"
+
+extern int encrypt_debug_mode;
+
+extern krb5_context telnet_context;
+
+#define	CFB	0
+#define	OFB	1
+
+#define	NO_SEND_IV	1
+#define	NO_RECV_IV	2
+#define	NO_KEYID	4
+#define	IN_PROGRESS	(NO_SEND_IV|NO_RECV_IV|NO_KEYID)
+#define	SUCCESS		0
+#define	FAILED		-1
+
+
+struct fb {
+	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;
+		unsigned char	str_keybytes[8]; /* yuck */
+		krb5_keyblock	str_key;
+		int		str_index;
+		int		str_flagshift;
+	} streams[2];
+};
+
+static struct fb fb[2];
+
+struct keyidlist {
+	char	*keyid;
+	int	keyidlen;
+	char	*key;
+	int	keylen;
+	int	flags;
+} keyidlist [] = {
+	{ "\0", 1, 0, 0, 0 },		/* default key of zero */
+	{ 0, 0, 0, 0, 0 }
+};
+
+#define	KEYFLAG_MASK	03
+
+#define	KEYFLAG_NOINIT	00
+#define	KEYFLAG_INIT	01
+#define	KEYFLAG_OK	02
+#define	KEYFLAG_BAD	03
+
+#define	KEYFLAG_SHIFT	2
+
+#define	SHIFT_VAL(a,b)	(KEYFLAG_SHIFT*((a)+((b)*2)))
+
+#define	FB64_IV		1
+#define	FB64_IV_OK	2
+#define	FB64_IV_BAD	3
+
+
+void fb64_stream_iv (Block, struct stinfo *);
+void fb64_init (struct fb *);
+static int fb64_start (struct fb *, int, int);
+int fb64_is (unsigned char *, int, struct fb *);
+int fb64_reply (unsigned char *, int, struct fb *);
+static void fb64_session (Session_Key *, int, struct fb *);
+void fb64_stream_key (Block, struct stinfo *);
+int fb64_keyid (int, unsigned char *, int *, struct fb *);
+void fb64_printsub (unsigned char *, int, unsigned char *, int, 
+		     unsigned char *);
+
+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;
+{
+	fb64_init(&fb[CFB]);
+	fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
+	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
+	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
+}
+
+	void
+ofb64_init(server)
+	int server;
+{
+	fb64_init(&fb[OFB]);
+	fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
+	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
+	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
+}
+
+	void
+fb64_init(fbp)
+	register struct fb *fbp;
+{
+	memset((void *)fbp, 0, sizeof(*fbp));
+	fbp->state[0] = fbp->state[1] = FAILED;
+	fbp->fb_feed[0] = IAC;
+	fbp->fb_feed[1] = SB;
+	fbp->fb_feed[2] = TELOPT_ENCRYPT;
+	fbp->fb_feed[3] = ENCRYPT_IS;
+}
+
+/*
+ * Returns:
+ *	-1: some error.  Negotiation is done, encryption not ready.
+ *	 0: Successful, initial negotiation all done.
+ *	 1: successful, negotiation not done yet.
+ *	 2: Not yet.  Other things (like getting the key from
+ *	    Kerberos) have to happen before we can continue.
+ */
+	int
+cfb64_start(dir, server)
+	int dir;
+	int server;
+{
+	return(fb64_start(&fb[CFB], dir, server));
+}
+	int
+ofb64_start(dir, server)
+	int dir;
+	int server;
+{
+	return(fb64_start(&fb[OFB], dir, server));
+}
+
+	static int
+fb64_start(fbp, dir, server)
+	struct fb *fbp;
+	int dir;
+	int server;
+{
+	int x;
+	unsigned char *p;
+	register int state;
+
+	switch (dir) {
+	case DIR_DECRYPT:
+		/*
+		 * This is simply a request to have the other side
+		 * start output (our input).  He will negotiate an
+		 * IV so we need not look for it.
+		 */
+		state = fbp->state[dir-1];
+		if (state == FAILED)
+			state = IN_PROGRESS;
+		break;
+
+	case DIR_ENCRYPT:
+		state = fbp->state[dir-1];
+		if (state == FAILED)
+			state = IN_PROGRESS;
+		else if ((state & NO_SEND_IV) == 0)
+			break;
+
+		if (!fbp->validkey) {
+			fbp->need_start = 1;
+			break;
+		}
+		state &= ~NO_SEND_IV;
+		state |= NO_RECV_IV;
+		if (encrypt_debug_mode)
+			printf("Creating new feed\r\n");
+		/*
+		 * Create a random feed and send it over.
+		 */
+		{
+			krb5_data d;
+
+			d.data = fbp->temp_feed;
+			d.length = sizeof(fbp->temp_feed);
+
+			if (krb5_c_random_make_octets(telnet_context, &d))
+				return(FAILED);
+		}
+
+		p = fbp->fb_feed + 3;
+		*p++ = ENCRYPT_IS;
+		p++;
+		*p++ = FB64_IV;
+		for (x = 0; x < sizeof(Block); ++x) {
+			if ((*p++ = fbp->temp_feed[x]) == IAC)
+				*p++ = IAC;
+		}
+		*p++ = IAC;
+		*p++ = SE;
+		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
+		net_write(fbp->fb_feed, p - fbp->fb_feed);
+		break;
+	default:
+		return(FAILED);
+	}
+	return(fbp->state[dir-1] = state);
+}
+
+/*
+ * Returns:
+ *	-1: some error.  Negotiation is done, encryption not ready.
+ *	 0: Successful, initial negotiation all done.
+ *	 1: successful, negotiation not done yet.
+ */
+	int
+cfb64_is(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	return(fb64_is(data, cnt, &fb[CFB]));
+}
+	int
+ofb64_is(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	return(fb64_is(data, cnt, &fb[OFB]));
+}
+
+	int
+fb64_is(data, cnt, fbp)
+	unsigned char *data;
+	int cnt;
+	struct fb *fbp;
+{
+	unsigned char *p;
+	register int state = fbp->state[DIR_DECRYPT-1];
+
+	if (cnt-- < 1)
+		goto failure;
+
+	switch (*data++) {
+	case FB64_IV:
+		if (cnt != sizeof(Block)) {
+			if (encrypt_debug_mode)
+				printf("CFB64: initial vector failed on size\r\n");
+			state = FAILED;
+			goto failure;
+		}
+
+		if (encrypt_debug_mode)
+			printf("CFB64: initial vector received\r\n");
+
+		if (encrypt_debug_mode)
+			printf("Initializing Decrypt stream\r\n");
+
+		fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]);
+
+		p = fbp->fb_feed + 3;
+		*p++ = ENCRYPT_REPLY;
+		p++;
+		*p++ = FB64_IV_OK;
+		*p++ = IAC;
+		*p++ = SE;
+		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
+		net_write(fbp->fb_feed, p - fbp->fb_feed);
+
+		state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
+		break;
+
+	default:
+		if (encrypt_debug_mode) {
+			printf("Unknown option type: %d\r\n", *(data-1));
+			printd(data, cnt);
+			printf("\r\n");
+		}
+		/* FALL THROUGH */
+	failure:
+		/*
+		 * We failed.  Send an FB64_IV_BAD option
+		 * to the other side so it will know that
+		 * things failed.
+		 */
+		p = fbp->fb_feed + 3;
+		*p++ = ENCRYPT_REPLY;
+		p++;
+		*p++ = FB64_IV_BAD;
+		*p++ = IAC;
+		*p++ = SE;
+		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
+		net_write(fbp->fb_feed, p - fbp->fb_feed);
+
+		break;
+	}
+	return(fbp->state[DIR_DECRYPT-1] = state);
+}
+
+/*
+ * Returns:
+ *	-1: some error.  Negotiation is done, encryption not ready.
+ *	 0: Successful, initial negotiation all done.
+ *	 1: successful, negotiation not done yet.
+ */
+	int
+cfb64_reply(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	return(fb64_reply(data, cnt, &fb[CFB]));
+}
+	int
+ofb64_reply(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	return(fb64_reply(data, cnt, &fb[OFB]));
+}
+
+
+	int
+fb64_reply(data, cnt, fbp)
+	unsigned char *data;
+	int cnt;
+	struct fb *fbp;
+{
+	register int state = fbp->state[DIR_ENCRYPT-1];
+
+	if (cnt-- < 1)
+		goto failure;
+
+	switch (*data++) {
+	case FB64_IV_OK:
+		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
+		if (state == FAILED)
+			state = IN_PROGRESS;
+		state &= ~NO_RECV_IV;
+		encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1);
+		break;
+
+	case FB64_IV_BAD:
+		memset(fbp->temp_feed, 0, sizeof(Block));
+		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
+		state = FAILED;
+		break;
+
+	default:
+		if (encrypt_debug_mode) {
+			printf("Unknown option type: %d\r\n", data[-1]);
+			printd(data, cnt);
+			printf("\r\n");
+		}
+		/* FALL THROUGH */
+	failure:
+		state = FAILED;
+		break;
+	}
+	return(fbp->state[DIR_ENCRYPT-1] = state);
+}
+
+	void
+cfb64_session(key, server)
+	Session_Key *key;
+	int server;
+{
+	fb64_session(key, server, &fb[CFB]);
+}
+
+	void
+ofb64_session(key, server)
+	Session_Key *key;
+	int server;
+{
+	fb64_session(key, server, &fb[OFB]);
+}
+
+	static void
+fb64_session(key, server, fbp)
+	Session_Key *key;
+	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;
+	}
+
+	fbp->validkey = 1;
+
+	fb64_stream_key(key->data, &fbp->streams[DIR_ENCRYPT-1]);
+	fb64_stream_key(key->data, &fbp->streams[DIR_DECRYPT-1]);
+
+	/*
+	 * Now look to see if krbdes_start() was was waiting for
+	 * the key to show up.  If so, go ahead an call it now
+	 * that we have the key.
+	 */
+	if (fbp->need_start) {
+		fbp->need_start = 0;
+		fb64_start(fbp, DIR_ENCRYPT, server);
+	}
+}
+
+/*
+ * We only accept a keyid of 0.  If we get a keyid of
+ * 0, then mark the state as SUCCESS.
+ */
+	int
+cfb64_keyid(dir, kp, lenp)
+	int dir, *lenp;
+	unsigned char *kp;
+{
+	return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
+}
+
+	int
+ofb64_keyid(dir, kp, lenp)
+	int dir, *lenp;
+	unsigned char *kp;
+{
+	return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
+}
+
+	int
+fb64_keyid(dir, kp, lenp, fbp)
+	int dir, *lenp;
+	unsigned char *kp;
+	struct fb *fbp;
+{
+	register int state = fbp->state[dir-1];
+
+	if (*lenp != 1 || (*kp != '\0')) {
+		*lenp = 0;
+		return(state);
+	}
+
+	if (state == FAILED)
+		state = IN_PROGRESS;
+
+	state &= ~NO_KEYID;
+
+	return(fbp->state[dir-1] = state);
+}
+
+	void
+fb64_printsub(data, cnt, buf, buflen, type)
+	unsigned char *data, *buf, *type;
+	int cnt, buflen;
+{
+	char lbuf[32];
+	register int i;
+	char *cp;
+
+	buf[buflen-1] = '\0';		/* make sure it's NULL terminated */
+	buflen -= 1;
+
+	switch(data[2]) {
+	case FB64_IV:
+		sprintf(lbuf, "%s_IV", type);
+		cp = lbuf;
+		goto common;
+
+	case FB64_IV_OK:
+		sprintf(lbuf, "%s_IV_OK", type);
+		cp = lbuf;
+		goto common;
+
+	case FB64_IV_BAD:
+		sprintf(lbuf, "%s_IV_BAD", type);
+		cp = lbuf;
+		goto common;
+
+	default:
+		sprintf(lbuf, " %d (unknown)", data[2]);
+		cp = lbuf;
+	common:
+		for (; (buflen > 0) && (*buf = *cp++); buf++)
+			buflen--;
+		for (i = 3; i < cnt; i++) {
+			sprintf(lbuf, " %d", data[i]);
+			for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
+				buflen--;
+		}
+		break;
+	}
+}
+
+	void
+cfb64_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt, buflen;
+{
+	fb64_printsub(data, cnt, buf, buflen, (unsigned char *) "CFB64");
+}
+
+	void
+ofb64_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt, buflen;
+{
+	fb64_printsub(data, cnt, buf, buflen, (unsigned char *) "OFB64");
+}
+
+	void
+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));
+
+	stp->str_index = sizeof(Block);
+}
+
+	void
+fb64_stream_key(key, stp)
+	Block key;
+	register struct stinfo *stp;
+{
+	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));
+
+	stp->str_index = sizeof(Block);
+}
+
+/*
+ * DES 64 bit Cipher Feedback
+ *
+ *     key --->+-----+
+ *          +->| DES |--+
+ *          |  +-----+  |
+ *	    |           v
+ *  INPUT --(--------->(+)+---> DATA
+ *          |             |
+ *	    +-------------+
+ *         
+ *
+ * Given:
+ *	iV: Initial vector, 64 bits (8 bytes) long.
+ *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
+ *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
+ *
+ *	V0 = DES(iV, key)
+ *	On = Dn ^ Vn
+ *	V(n+1) = DES(On, key)
+ */
+
+	void
+cfb64_encrypt(s, c)
+	register unsigned char *s;
+	int c;
+{
+	register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1];
+	register int idx;
+
+	idx = stp->str_index;
+	while (c-- > 0) {
+		if (idx == sizeof(Block)) {
+			Block b;
+			ecb_encrypt(stp, stp->str_output, b);
+			memcpy((void *)stp->str_feed,(void *)b,sizeof(Block));
+			idx = 0;
+		}
+
+		/* On encryption, we store (feed ^ data) which is cypher */
+		*s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s);
+		s++;
+		idx++;
+	}
+	stp->str_index = idx;
+}
+
+	int
+cfb64_decrypt(data)
+	int data;
+{
+	register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
+	int idx;
+
+	if (data == -1) {
+		/*
+		 * Back up one byte.  It is assumed that we will
+		 * never back up more than one byte.  If we do, this
+		 * may or may not work.
+		 */
+		if (stp->str_index)
+			--stp->str_index;
+		return(0);
+	}
+
+	idx = stp->str_index++;
+	if (idx == sizeof(Block)) {
+		Block b;
+		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 */
+		idx = 0;		/* But now use 0 */ 
+	}
+
+	/* On decryption we store (data) which is cypher. */
+	stp->str_output[idx] = data;
+	return(data ^ stp->str_feed[idx]);
+}
+
+/*
+ * DES 64 bit Output Feedback
+ *
+ * key --->+-----+
+ *	+->| DES |--+
+ *	|  +-----+  |
+ *	+-----------+
+ *	            v
+ *  INPUT -------->(+) ----> DATA
+ *
+ * Given:
+ *	iV: Initial vector, 64 bits (8 bytes) long.
+ *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
+ *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
+ *
+ *	V0 = DES(iV, key)
+ *	V(n+1) = DES(Vn, key)
+ *	On = Dn ^ Vn
+ */
+	void
+ofb64_encrypt(s, c)
+	register unsigned char *s;
+	int c;
+{
+	register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1];
+	register int idx;
+
+	idx = stp->str_index;
+	while (c-- > 0) {
+		if (idx == sizeof(Block)) {
+			Block b;
+			ecb_encrypt(stp, stp->str_feed, b);
+			memcpy((void *)stp->str_feed,(void *)b,sizeof(Block));
+			idx = 0;
+		}
+		*s++ ^= stp->str_feed[idx];
+		idx++;
+	}
+	stp->str_index = idx;
+}
+
+	int
+ofb64_decrypt(data)
+	int data;
+{
+	register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
+	int idx;
+
+	if (data == -1) {
+		/*
+		 * Back up one byte.  It is assumed that we will
+		 * never back up more than one byte.  If we do, this
+		 * may or may not work.
+		 */
+		if (stp->str_index)
+			--stp->str_index;
+		return(0);
+	}
+
+	idx = stp->str_index++;
+	if (idx == sizeof(Block)) {
+		Block b;
+		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 */
+		idx = 0;		/* But now use 0 */ 
+	}
+
+	return(data ^ stp->str_feed[idx]);
+}
+#  endif /* DES_ENCRYPTION */
+# endif	/* AUTHENTICATION */
+#else	/* ENCRYPTION */
+#include "misc-proto.h"
+#endif	/* ENCRYPTION */
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/encrypt.c b/krb5-1-6/src/appl/telnet/libtelnet/encrypt.c
new file mode 100644
index 000000000..e99f346c4
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/encrypt.c
@@ -0,0 +1,1014 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)encrypt.c	8.1 (Berkeley) 6/4/93 */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifdef	ENCRYPTION
+
+#include <stdio.h>
+#define	ENCRYPT_NAMES
+#include <arpa/telnet.h>
+
+#include "encrypt.h"
+#include "misc.h"
+
+#ifdef	__STDC__
+#include <stdlib.h>
+#endif
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/*
+ * These functions pointers point to the current routines
+ * for encrypting and decrypting data.
+ */
+void	(*encrypt_output) (unsigned char *, int);
+int	(*decrypt_input) (int);
+
+int encrypt_debug_mode = 0;
+static int decrypt_mode = 0;
+static int encrypt_mode = 0;
+static int encrypt_verbose = 0;
+static int autoencrypt = 0;
+static int autodecrypt = 0;
+static int havesessionkey = 0;
+static int Server = 0;
+static char *Name = "Noname";
+
+#define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
+
+static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64)
+				| typemask(ENCTYPE_DES_OFB64);
+static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64)
+				| typemask(ENCTYPE_DES_OFB64);
+static long i_wont_support_encrypt = 0;
+static long i_wont_support_decrypt = 0;
+#define	I_SUPPORT_ENCRYPT	(i_support_encrypt & ~i_wont_support_encrypt)
+#define	I_SUPPORT_DECRYPT	(i_support_decrypt & ~i_wont_support_decrypt)
+
+static long remote_supports_encrypt = 0;
+static long remote_supports_decrypt = 0;
+
+static Encryptions encryptions[] = {
+#ifdef	DES_ENCRYPTION
+    { "DES_CFB64",	ENCTYPE_DES_CFB64,
+			cfb64_encrypt,	
+			cfb64_decrypt,
+			cfb64_init,
+			cfb64_start,
+			cfb64_is,
+			cfb64_reply,
+			cfb64_session,
+			cfb64_keyid,
+			cfb64_printsub },
+    { "DES_OFB64",	ENCTYPE_DES_OFB64,
+			ofb64_encrypt,	
+			ofb64_decrypt,
+			ofb64_init,
+			ofb64_start,
+			ofb64_is,
+			ofb64_reply,
+			ofb64_session,
+			ofb64_keyid,
+			ofb64_printsub },
+#endif	/* DES_ENCRYPTION */
+    { 0, },
+};
+
+static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
+					 ENCRYPT_SUPPORT };
+static unsigned char str_suplen = 0;
+static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
+static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
+
+	Encryptions *
+findencryption(type)
+	int type;
+{
+	Encryptions *ep = encryptions;
+
+	if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))
+		return(0);
+	while (ep->type && ep->type != type)
+		++ep;
+	return(ep->type ? ep : 0);
+}
+
+	Encryptions *
+finddecryption(type)
+	int type;
+{
+	Encryptions *ep = encryptions;
+
+	if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))
+		return(0);
+	while (ep->type && ep->type != type)
+		++ep;
+	return(ep->type ? ep : 0);
+}
+
+#define	MAXKEYLEN 64
+
+static struct key_info {
+	unsigned char keyid[MAXKEYLEN];
+	int keylen;
+	int dir;
+	int *modep;
+	Encryptions *(*getcrypt)();
+} ki[2] = {
+	{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
+	{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
+};
+
+	void
+encrypt_init(name, server)
+	char *name;
+	int server;
+{
+	Encryptions *ep = encryptions;
+
+	Name = name;
+	Server = server;
+	i_support_encrypt = i_support_decrypt = 0;
+	remote_supports_encrypt = remote_supports_decrypt = 0;
+	encrypt_mode = 0;
+	decrypt_mode = 0;
+	encrypt_output = 0;
+	decrypt_input = 0;
+#ifdef notdef
+	encrypt_verbose = !server;
+#endif
+
+	str_suplen = 4;
+
+	while (ep->type) {
+		if (encrypt_debug_mode)
+			printf(">>>%s: I will support %s\r\n",
+				Name, ENCTYPE_NAME(ep->type));
+		i_support_encrypt |= typemask(ep->type);
+		i_support_decrypt |= typemask(ep->type);
+		if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
+			if ((str_send[str_suplen++] = ep->type) == IAC)
+				str_send[str_suplen++] = IAC;
+		if (ep->init)
+			(*ep->init)(Server);
+		++ep;
+	}
+	str_send[str_suplen++] = IAC;
+	str_send[str_suplen++] = SE;
+}
+
+static	void
+encrypt_list_types()
+{
+	Encryptions *ep = encryptions;
+
+	printf("Valid encryption types:\n");
+	while (ep->type) {
+		printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
+		++ep;
+	}
+}
+
+	int
+EncryptEnable(type, mode)
+	char *type, *mode;
+{
+	if (isprefix(type, "help") || isprefix(type, "?")) {
+		printf("Usage: encrypt enable <type> [input|output]\n");
+		encrypt_list_types();
+		return(0);
+	}
+	if (EncryptType(type, mode))
+		return(EncryptStart(mode));
+	return(0);
+}
+
+	int
+EncryptDisable(type, mode)
+	char *type, *mode;
+{
+	register Encryptions *ep;
+	int ret = 0;
+
+	if (isprefix(type, "help") || isprefix(type, "?")) {
+		printf("Usage: encrypt disable <type> [input|output]\n");
+		encrypt_list_types();
+	} else if ((ep = (Encryptions *)genget(type, (char **) encryptions,
+						sizeof(Encryptions))) == 0) {
+		printf("%s: invalid encryption type\n", type);
+	} else if (Ambiguous(ep)) {
+		printf("Ambiguous type '%s'\n", type);
+	} else {
+		if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
+			if (decrypt_mode == ep->type)
+				EncryptStopInput();
+			i_wont_support_decrypt |= typemask(ep->type);
+			ret = 1;
+		}
+		if ((mode == 0) || (isprefix(mode, "output"))) {
+			if (encrypt_mode == ep->type)
+				EncryptStopOutput();
+			i_wont_support_encrypt |= typemask(ep->type);
+			ret = 1;
+		}
+		if (ret == 0)
+			printf("%s: invalid encryption mode\n", mode);
+	}
+	return(ret);
+}
+
+	int
+EncryptType(type, mode)
+	char *type;
+	char *mode;
+{
+	register Encryptions *ep;
+	int ret = 0;
+
+	if (isprefix(type, "help") || isprefix(type, "?")) {
+		printf("Usage: encrypt type <type> [input|output]\n");
+		encrypt_list_types();
+	} else if ((ep = (Encryptions *)genget(type, (char **) encryptions,
+						sizeof(Encryptions))) == 0) {
+		printf("%s: invalid encryption type\n", type);
+	} else if (Ambiguous(ep)) {
+		printf("Ambiguous type '%s'\n", type);
+	} else {
+		if ((mode == 0) || isprefix(mode, "input")) {
+			decrypt_mode = ep->type;
+			i_wont_support_decrypt &= ~typemask(ep->type);
+			ret = 1;
+		}
+		if ((mode == 0) || isprefix(mode, "output")) {
+			encrypt_mode = ep->type;
+			i_wont_support_encrypt &= ~typemask(ep->type);
+			ret = 1;
+		}
+		if (ret == 0)
+			printf("%s: invalid encryption mode\n", mode);
+	}
+	return(ret);
+}
+
+	int
+EncryptStart(mode)
+	char *mode;
+{
+	register int ret = 0;
+	if (mode) {
+		if (isprefix(mode, "input"))
+			return(EncryptStartInput());
+		if (isprefix(mode, "output"))
+			return(EncryptStartOutput());
+		if (isprefix(mode, "help") || isprefix(mode, "?")) {
+			printf("Usage: encrypt start [input|output]\n");
+			return(0);
+		}
+		printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
+		return(0);
+	}
+	ret += EncryptStartInput();
+	ret += EncryptStartOutput();
+	return(ret);
+}
+
+	int
+EncryptStartInput()
+{
+	if (decrypt_mode) {
+		encrypt_send_request_start();
+		return(1);
+	}
+	if (!Server)
+	    printf("No previous decryption mode, decryption not enabled\r\n");
+	return(0);
+}
+
+	int
+EncryptStartOutput()
+{
+	if (encrypt_mode) {
+		encrypt_start_output(encrypt_mode);
+		return(1);
+	}
+	if (!Server)
+	    printf("No previous encryption mode, encryption not enabled\r\n");
+	return(0);
+}
+
+	int
+EncryptStop(mode)
+	char *mode;
+{
+	int ret = 0;
+	if (mode) {
+		if (isprefix(mode, "input"))
+			return(EncryptStopInput());
+		if (isprefix(mode, "output"))
+			return(EncryptStopOutput());
+		if (isprefix(mode, "help") || isprefix(mode, "?")) {
+			printf("Usage: encrypt stop [input|output]\n");
+			return(0);
+		}
+		printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
+		return(0);
+	}
+	ret += EncryptStopInput();
+	ret += EncryptStopOutput();
+	return(ret);
+}
+
+	int
+EncryptStopInput()
+{
+	encrypt_send_request_end();
+	return(1);
+}
+
+	int
+EncryptStopOutput()
+{
+	encrypt_send_end();
+	return(1);
+}
+
+	void
+encrypt_display()
+{
+	if (encrypt_output)
+		printf("Currently encrypting output with %s\r\n",
+			ENCTYPE_NAME(encrypt_mode));
+	if (decrypt_input)
+		printf("Currently decrypting input with %s\r\n",
+			ENCTYPE_NAME(decrypt_mode));
+}
+
+	int
+EncryptStatus()
+{
+	if (encrypt_output)
+		printf("Currently encrypting output with %s\r\n",
+			ENCTYPE_NAME(encrypt_mode));
+	else if (encrypt_mode) {
+		printf("Currently output is clear text.\r\n");
+		printf("Last encryption mode was %s\r\n",
+			ENCTYPE_NAME(encrypt_mode));
+	}
+	if (decrypt_input) {
+		printf("Currently decrypting input with %s\r\n",
+			ENCTYPE_NAME(decrypt_mode));
+	} else if (decrypt_mode) {
+		printf("Currently input is clear text.\r\n");
+		printf("Last decryption mode was %s\r\n",
+			ENCTYPE_NAME(decrypt_mode));
+	}
+	return 1;
+}
+
+	void
+encrypt_send_support()
+{
+	if (str_suplen) {
+		/*
+		 * If the user has requested that decryption start
+		 * immediatly, then send a "REQUEST START" before
+		 * we negotiate the type.
+		 */
+		if (!Server && autodecrypt)
+			encrypt_send_request_start();
+		net_write(str_send, str_suplen);
+		printsub('>', &str_send[2], str_suplen - 2);
+		str_suplen = 0;
+	}
+}
+
+	int
+EncryptDebug(on)
+	int on;
+{
+	if (on < 0)
+		encrypt_debug_mode ^= 1;
+	else
+		encrypt_debug_mode = on;
+	printf("Encryption debugging %s\r\n",
+		encrypt_debug_mode ? "enabled" : "disabled");
+	return(1);
+}
+
+	int
+EncryptVerbose(on)
+	int on;
+{
+	if (on < 0)
+		encrypt_verbose ^= 1;
+	else
+		encrypt_verbose = on;
+	printf("Encryption %s verbose\r\n",
+		encrypt_verbose ? "is" : "is not");
+	return(1);
+}
+
+	int
+EncryptAutoEnc(on)
+	int on;
+{
+	encrypt_auto(on);
+	printf("Automatic encryption of output is %s\r\n",
+		autoencrypt ? "enabled" : "disabled");
+	return(1);
+}
+
+	int
+EncryptAutoDec(on)
+	int on;
+{
+	decrypt_auto(on);
+	printf("Automatic decryption of input is %s\r\n",
+		autodecrypt ? "enabled" : "disabled");
+	return(1);
+}
+
+/*
+ * Called when ENCRYPT SUPPORT is received.
+ */
+	void
+encrypt_support(typelist, cnt)
+	unsigned char *typelist;
+	int cnt;
+{
+	register int type, use_type = 0;
+	Encryptions *ep;
+
+	/*
+	 * Forget anything the other side has previously told us.
+	 */
+	remote_supports_decrypt = 0;
+
+	while (cnt-- > 0) {
+		type = *typelist++;
+		if (encrypt_debug_mode)
+			printf(">>>%s: He is supporting %s (%d)\r\n",
+				Name,
+				ENCTYPE_NAME(type), type);
+		if ((type < ENCTYPE_CNT) &&
+		    (I_SUPPORT_ENCRYPT & typemask(type))) {
+			remote_supports_decrypt |= typemask(type);
+			if (use_type == 0)
+				use_type = type;
+		}
+	}
+	if (use_type) {
+		ep = findencryption(use_type);
+		if (!ep)
+			return;
+		type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
+		if (encrypt_debug_mode)
+			printf(">>>%s: (*ep->start)() returned %d\r\n",
+					Name, type);
+		if (type < 0)
+			return;
+		encrypt_mode = use_type;
+		if (type == 0)
+			encrypt_start_output(use_type);
+	}
+}
+
+	void
+encrypt_is(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	Encryptions *ep;
+	register int type, ret;
+
+	if (--cnt < 0)
+		return;
+	type = *data++;
+	if (type < ENCTYPE_CNT)
+		remote_supports_encrypt |= typemask(type);
+	if (!(ep = finddecryption(type))) {
+		if (encrypt_debug_mode)
+			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
+				Name,
+				ENCTYPE_NAME_OK(type)
+					? ENCTYPE_NAME(type) : "(unknown)",
+				type);
+		return;
+	}
+	if (!ep->is) {
+		if (encrypt_debug_mode)
+			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
+				Name,
+				ENCTYPE_NAME_OK(type)
+					? ENCTYPE_NAME(type) : "(unknown)",
+				type);
+		ret = 0;
+	} else {
+		ret = (*ep->is)(data, cnt);
+		if (encrypt_debug_mode)
+			printf("(*ep->is)(%lx, %d) returned %s(%d)\n", 
+			        (unsigned long) data, cnt,
+				(ret < 0) ? "FAIL " :
+				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
+	}
+	if (ret < 0) {
+		autodecrypt = 0;
+	} else {
+		decrypt_mode = type;
+		if (ret == 0 && autodecrypt)
+			encrypt_send_request_start();
+	}
+}
+
+	void
+encrypt_reply(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	Encryptions *ep;
+	register int ret, type;
+
+	if (--cnt < 0)
+		return;
+	type = *data++;
+	if (!(ep = findencryption(type))) {
+		if (encrypt_debug_mode)
+			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
+				Name,
+				ENCTYPE_NAME_OK(type)
+					? ENCTYPE_NAME(type) : "(unknown)",
+				type);
+		return;
+	}
+	if (!ep->reply) {
+		if (encrypt_debug_mode)
+			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
+				Name,
+				ENCTYPE_NAME_OK(type)
+					? ENCTYPE_NAME(type) : "(unknown)",
+				type);
+		ret = 0;
+	} else {
+		ret = (*ep->reply)(data, cnt);
+		if (encrypt_debug_mode)
+			printf("(*ep->reply)(%lx, %d) returned %s(%d)\n",
+				(unsigned long) data, cnt,
+				(ret < 0) ? "FAIL " :
+				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
+	}
+	if (encrypt_debug_mode)
+		printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
+	if (ret < 0) {
+		autoencrypt = 0;
+	} else {
+		encrypt_mode = type;
+		if (ret == 0 && autoencrypt)
+			encrypt_start_output(type);
+	}
+}
+
+/*
+ * Called when a ENCRYPT START command is received.
+ */
+	void
+encrypt_start(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	Encryptions *ep;
+
+	if (!decrypt_mode) {
+		/*
+		 * Something is wrong.  We should not get a START
+		 * command without having already picked our
+		 * decryption scheme.  Send a REQUEST-END to
+		 * attempt to clear the channel...
+		 */
+		printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
+		encrypt_send_request_end();
+		return;
+	}
+
+	if ((ep = finddecryption(decrypt_mode))) {
+		decrypt_input = ep->input;
+		if (encrypt_verbose)
+			printf("[ Input is now decrypted with type %s ]\r\n",
+				ENCTYPE_NAME(decrypt_mode));
+		if (encrypt_debug_mode)
+			printf(">>>%s: Start to decrypt input with type %s\r\n",
+				Name, ENCTYPE_NAME(decrypt_mode));
+	} else {
+		printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
+				Name,
+				ENCTYPE_NAME_OK(decrypt_mode)
+					? ENCTYPE_NAME(decrypt_mode)
+					: "(unknown)",
+				decrypt_mode);
+		encrypt_send_request_end();
+	}
+}
+
+	void
+encrypt_session_key(key, server)
+	Session_Key *key;
+	int server;
+{
+	Encryptions *ep = encryptions;
+
+	havesessionkey = 1;
+
+	while (ep->type) {
+		if (ep->session)
+			(*ep->session)(key, server);
+#ifdef notdef
+		if (!encrypt_output && autoencrypt && !server)
+			encrypt_start_output(ep->type);
+		if (!decrypt_input && autodecrypt && !server)
+			encrypt_send_request_start();
+#endif
+		++ep;
+	}
+}
+
+/*
+ * Called when ENCRYPT END is received.
+ */
+	void
+encrypt_end()
+{
+	decrypt_input = 0;
+	if (encrypt_debug_mode)
+		printf(">>>%s: Input is back to clear text\r\n", Name);
+	if (encrypt_verbose)
+		printf("[ Input is now clear text ]\r\n");
+}
+
+/*
+ * Called when ENCRYPT REQUEST-END is received.
+ */
+	void
+encrypt_request_end()
+{
+	encrypt_send_end();
+}
+
+/*
+ * Called when ENCRYPT REQUEST-START is received.  If we receive
+ * this before a type is picked, then that indicates that the
+ * other side wants us to start encrypting data as soon as we
+ * can. 
+ */
+	void
+encrypt_request_start(data, cnt)
+	unsigned char *data;
+	int cnt;
+{
+	if (encrypt_mode == 0)  {
+		if (Server)
+			autoencrypt = 1;
+		return;
+	}
+	encrypt_start_output(encrypt_mode);
+}
+
+static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
+
+static void encrypt_keyid (struct key_info *kp, unsigned char *, unsigned int);
+		
+void encrypt_enc_keyid(keyid, len)
+	unsigned char *keyid;
+	int len;
+{
+	encrypt_keyid(&ki[1], keyid, (unsigned) len);
+}
+
+void encrypt_dec_keyid(keyid, len)
+	unsigned char *keyid;
+	int len;
+{
+	encrypt_keyid(&ki[0], keyid, (unsigned) len);
+}
+
+static void encrypt_keyid(kp, keyid, len)
+	struct key_info *kp;
+	unsigned char *keyid;
+	unsigned int len;
+{
+	Encryptions *ep;
+	int dir = kp->dir;
+	register int ret = 0;
+
+	if (!(ep = (*kp->getcrypt)(*kp->modep))) {
+		if (len == 0)
+			return;
+		kp->keylen = 0;
+	} else if (len == 0) {
+		/*
+		 * Empty option, indicates a failure.
+		 */
+		if (kp->keylen == 0)
+			return;
+		kp->keylen = 0;
+		if (ep->keyid)
+			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
+
+	} else if ((len != kp->keylen) || 
+		   (memcmp(keyid, kp->keyid, len) != 0)) {
+		/*
+		 * Length or contents are different
+		 */
+		kp->keylen = len;
+		memcpy(kp->keyid, keyid, len);
+		if (ep->keyid)
+			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
+	} else {
+		if (ep->keyid)
+			ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
+		if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
+			encrypt_start_output(*kp->modep);
+		return;
+	}
+
+	encrypt_send_keyid(dir, kp->keyid, (unsigned) kp->keylen, 0);
+}
+
+	void
+encrypt_send_keyid(dir, keyid, keylen, saveit)
+	int dir;
+	unsigned char *keyid;
+	unsigned int keylen;
+	int saveit;
+{
+	unsigned char *strp;
+
+	str_keyid[3] = (dir == DIR_ENCRYPT)
+			? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
+	if (saveit) {
+		struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
+		memcpy(kp->keyid, keyid, keylen);
+		kp->keylen = keylen;
+	}
+
+	for (strp = &str_keyid[4]; keylen > 0; --keylen) {
+		if ((*strp++ = *keyid++) == IAC)
+			*strp++ = IAC;
+	}
+	*strp++ = IAC;
+	*strp++ = SE;
+	net_write(str_keyid, strp - str_keyid);
+	printsub('>', &str_keyid[2], strp - str_keyid - 2);
+}
+
+	void
+encrypt_auto(on)
+	int on;
+{
+	if (on < 0)
+		autoencrypt ^= 1;
+	else
+		autoencrypt = on ? 1 : 0;
+}
+
+	void
+decrypt_auto(on)
+	int on;
+{
+	if (on < 0)
+		autodecrypt ^= 1;
+	else
+		autodecrypt = on ? 1 : 0;
+}
+
+	void
+encrypt_start_output(type)
+	int type;
+{
+	Encryptions *ep;
+	register unsigned char *p;
+	register int i;
+
+	if (!(ep = findencryption(type))) {
+		if (encrypt_debug_mode) {
+			printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
+				Name,
+				ENCTYPE_NAME_OK(type)
+					? ENCTYPE_NAME(type) : "(unknown)",
+				type);
+		}
+		return;
+	}
+	if (ep->start) {
+		i = (*ep->start)(DIR_ENCRYPT, Server);
+		if (encrypt_debug_mode) {
+			printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
+				Name, 
+				(i < 0) ? "failed" :
+					"initial negotiation in progress",
+				i, ENCTYPE_NAME(type));
+		}
+		if (i)
+			return;
+	}
+	p = str_start + 3;
+	*p++ = ENCRYPT_START;
+	for (i = 0; i < ki[0].keylen; ++i) {
+		if ((*p++ = ki[0].keyid[i]) == IAC)
+			*p++ = IAC;
+	}
+	*p++ = IAC;
+	*p++ = SE;
+	net_write(str_start, p - str_start);
+	net_encrypt();
+	printsub('>', &str_start[2], p - &str_start[2]);
+	/*
+	 * If we are already encrypting in some mode, then
+	 * encrypt the ring (which includes our request) in
+	 * the old mode, mark it all as "clear text" and then
+	 * switch to the new mode.
+	 */
+	encrypt_output = ep->output;
+	encrypt_mode = type;
+	if (encrypt_debug_mode)
+		printf(">>>%s: Started to encrypt output with type %s\r\n",
+			Name, ENCTYPE_NAME(type));
+	if (encrypt_verbose)
+		printf("[ Output is now encrypted with type %s ]\r\n",
+			ENCTYPE_NAME(type));
+}
+
+	void
+encrypt_send_end()
+{
+	if (!encrypt_output)
+		return;
+
+	str_end[3] = ENCRYPT_END;
+	net_write(str_end, sizeof(str_end));
+	net_encrypt();
+	printsub('>', &str_end[2], sizeof(str_end) - 2);
+	/*
+	 * Encrypt the output buffer now because it will not be done by
+	 * netflush...
+	 */
+	encrypt_output = 0;
+	if (encrypt_debug_mode)
+		printf(">>>%s: Output is back to clear text\r\n", Name);
+	if (encrypt_verbose)
+		printf("[ Output is now clear text ]\r\n");
+}
+
+	void
+encrypt_send_request_start()
+{
+	register unsigned char *p;
+	register int i;
+
+	p = &str_start[3];
+	*p++ = ENCRYPT_REQSTART;
+	for (i = 0; i < ki[1].keylen; ++i) {
+		if ((*p++ = ki[1].keyid[i]) == IAC)
+			*p++ = IAC;
+	}
+	*p++ = IAC;
+	*p++ = SE;
+	net_write(str_start, p - str_start);
+	printsub('>', &str_start[2], p - &str_start[2]);
+	if (encrypt_debug_mode)
+		printf(">>>%s: Request input to be encrypted\r\n", Name);
+}
+
+	void
+encrypt_send_request_end()
+{
+	str_end[3] = ENCRYPT_REQEND;
+	net_write(str_end, sizeof(str_end));
+	printsub('>', &str_end[2], sizeof(str_end) - 2);
+
+	if (encrypt_debug_mode)
+		printf(">>>%s: Request input to be clear text\r\n", Name);
+}
+
+	void
+encrypt_wait()
+{
+	if (encrypt_debug_mode)
+		printf(">>>%s: in encrypt_wait\r\n", Name);
+	if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
+		return;
+	while (autoencrypt && !encrypt_output)
+		if (telnet_spin())
+			return;
+}
+
+int encrypt_is_encrypting()
+{
+    if (encrypt_output && decrypt_input)
+	return 1;
+    return 0;
+}
+
+	void
+encrypt_debug(mode)
+	int mode;
+{
+	encrypt_debug_mode = mode;
+}
+
+	void
+encrypt_gen_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt, buflen;
+{
+	char tbuf[16], *cp;
+
+	cnt -= 2;
+	data += 2;
+	buf[buflen-1] = '\0';
+	buf[buflen-2] = '*';
+	buflen -= 2;;
+	for (; cnt > 0; cnt--, data++) {
+		sprintf(tbuf, " %d", *data);
+		for (cp = tbuf; *cp && buflen > 0; --buflen)
+			*buf++ = *cp++;
+		if (buflen <= 0)
+			return;
+	}
+	*buf = '\0';
+}
+
+	void
+encrypt_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt, buflen;
+{
+	Encryptions *ep;
+	register int type = data[1];
+
+	for (ep = encryptions; ep->type && ep->type != type; ep++)
+		;
+
+	if (ep->printsub)
+		(*ep->printsub)(data, cnt, buf, buflen);
+	else
+		encrypt_gen_printsub(data, cnt, buf, buflen);
+}
+#else	/* ENCRYPTION */
+#include "misc-proto.h"
+#endif	/* ENCRYPTION */
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/encrypt.h b/krb5-1-6/src/appl/telnet/libtelnet/encrypt.h
new file mode 100644
index 000000000..4efac570b
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/encrypt.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)encrypt.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifdef	ENCRYPTION
+# ifndef __ENCRYPTION__
+# define __ENCRYPTION__
+
+#define	DIR_DECRYPT		1
+#define	DIR_ENCRYPT		2
+
+typedef	unsigned char Block[8];
+typedef unsigned char *BlockT;
+typedef struct { Block _; } Schedule[16];
+
+#define	VALIDKEY(key)	( key[0] | key[1] | key[2] | key[3] | \
+			  key[4] | key[5] | key[6] | key[7])
+
+#define	SAMEKEY(k1, k2)	(!memcmp((void *)k1, (void *)k2, sizeof(Block)))
+
+typedef	struct {
+	short		type;
+	int		length;
+	unsigned char	*data;
+} Session_Key;
+
+typedef struct {
+	char	*name;
+	int	type;
+	void	(*output) (unsigned char *, int);
+	int	(*input) (int);
+	void	(*init) (int);
+	int	(*start) (int, int);
+	int	(*is) (unsigned char *, int);
+	int	(*reply) (unsigned char *, int);
+	void	(*session) (Session_Key *, int);
+	int	(*keyid) (int, unsigned char *, int *);
+	void	(*printsub) (unsigned char *, int, unsigned char *, int);
+} Encryptions;
+
+#define	SK_DES		1	/* Matched Kerberos v5 ENCTYPE_DES */
+
+#include "enc-proto.h"
+
+extern int encrypt_debug_mode;
+extern int (*decrypt_input) (int);
+extern void (*encrypt_output) (unsigned char *, int);
+# endif /* __ENCRYPTION__ */
+#endif /* ENCRYPTION */
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/forward.c b/krb5-1-6/src/appl/telnet/libtelnet/forward.c
new file mode 100644
index 000000000..09d558906
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/forward.c
@@ -0,0 +1,78 @@
+/*
+ * appl/telnet/libtelnet/forward.c
+ */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/* General-purpose forwarding routines. These routines may be put into */
+/* libkrb5.a to allow widespread use */ 
+
+#if defined(KERBEROS) || defined(KRB5)
+#include <stdio.h>
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+ 
+#include "krb5.h"
+#include <errno.h>
+
+#include "krb5forw.h"
+ 
+#if defined(NEED_SETENV) || defined(NEED_SETENV_PROTO)
+extern int setenv(char *, char *, int);
+#endif
+
+extern char *line;		/* see sys_term.c */
+
+/* Decode, decrypt and store the forwarded creds in the local ccache. */
+krb5_error_code
+rd_and_store_for_creds(context, auth_context, inbuf, ticket)
+    krb5_context context;
+    krb5_auth_context auth_context;
+    krb5_data *inbuf;
+    krb5_ticket *ticket;
+{
+    krb5_creds **creds;
+    krb5_error_code retval;
+    char ccname[35];
+    krb5_ccache ccache = NULL;
+
+    if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
+	return(retval);
+
+    sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", (long) getpid());
+    setenv("KRB5CCNAME", ccname, 1);
+
+    if ((retval = krb5_cc_resolve(context, ccname, &ccache)))
+	goto cleanup;
+
+    if ((retval = krb5_cc_initialize(context, ccache, 
+				     ticket->enc_part2->client)))
+	goto cleanup;
+
+    if ((retval = krb5_cc_store_cred(context, ccache, *creds))) 
+	goto cleanup;
+
+cleanup:
+    krb5_free_creds(context, *creds);
+    return retval;
+}
+
+#endif /* defined(KRB5) && defined(FORWARD) */
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/genget.c b/krb5-1-6/src/appl/telnet/libtelnet/genget.c
new file mode 100644
index 000000000..bc307c81f
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/genget.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)genget.c	8.1 (Berkeley) 6/4/93 */
+
+#include <ctype.h>
+#include "misc.h"
+
+#define	LOWER(x) (isupper((int) x) ? tolower((int) x) : (x))
+/*
+ * The prefix function returns 0 if *s1 is not a prefix
+ * of *s2.  If *s1 exactly matches *s2, the negative of
+ * the length is returned.  If *s1 is a prefix of *s2,
+ * the length of *s1 is returned.
+ */
+	int
+isprefix(s1, s2)
+	register char *s1, *s2;
+{
+        char *os1;
+	register char c1, c2;
+
+        if (*s1 == '\0')
+                return(-1);
+        os1 = s1;
+	c1 = *s1;
+	c2 = *s2;
+        while (LOWER(c1) == LOWER(c2)) {
+		if (c1 == '\0')
+			break;
+                c1 = *++s1;
+                c2 = *++s2;
+        }
+        return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1)));
+}
+
+static char *ambiguous;		/* special return value for command routines */
+
+	char **
+genget(name, table, stlen)
+	char	*name;		/* name to match */
+	char	**table;	/* name entry in table */
+	int	stlen;
+{
+	register char **c, **found;
+	register int n;
+
+	if (name == 0)
+	    return 0;
+
+	found = 0;
+	for (c = table; *c != 0; c = (char **)((char *)c + stlen)) {
+		if ((n = isprefix(name, *c)) == 0)
+			continue;
+		if (n < 0)		/* exact match */
+			return(c);
+		if (found)
+			return(&ambiguous);
+		found = c;
+	}
+	return(found);
+}
+
+/*
+ * Function call version of Ambiguous()
+ */
+	int
+Ambiguous(s)
+	void *s;
+{
+	return((char **)s == &ambiguous);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/getent.c b/krb5-1-6/src/appl/telnet/libtelnet/getent.c
new file mode 100644
index 000000000..b80439e6e
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/getent.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)getent.c	8.1 (Berkeley) 6/4/93 */
+
+#include "gettytab.h"
+
+#ifdef	HAVE_CGETENT
+static char *area;
+#endif
+
+/*ARGSUSED*/
+int
+getent(cp, name)
+char *cp, *name;
+{
+#ifdef	HAVE_CGETENT
+	char *dba[2];
+
+	dba[0] = "/etc/gettytab";
+	dba[1] = 0;
+	return((cgetent(&area, dba, name) == 0) ? 1 : 0);
+#else
+	return(0);
+#endif
+}
+
+#ifndef	SOLARIS
+/*ARGSUSED*/
+char *
+getstr(id, cpp)
+char *id, **cpp;
+{
+#ifdef	HAVE_CGETENT
+	char *answer;
+	return((cgetstr(area, id, &answer) > 0) ? answer : 0);
+#else
+	return(0);
+#endif
+}
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/getopt.c b/krb5-1-6/src/appl/telnet/libtelnet/getopt.c
new file mode 100644
index 000000000..d61cc3c1f
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/getopt.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)getopt.c	8.1 (Berkeley) 6/4/93 */
+
+#ifndef __STDC__
+#define const
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * get option letter from argument vector
+ */
+int	opterr = 1,		/* if error message should be printed */
+	optind = 1,		/* index into parent argv vector */
+	optopt,			/* character checked for validity */
+	optreset;		/* reset getopt */
+char	*optarg;		/* argument associated with option */
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+int
+getopt(nargc, nargv, ostr)
+	int nargc;
+	char * const *nargv;
+	const char *ostr;
+{
+	static char *place = EMSG;		/* option letter processing */
+	register char *oli;			/* option letter list index */
+	char *p;
+
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+			place = EMSG;
+			return(-1);
+		}
+		if (place[1] && *++place == '-') {	/* found "--" */
+			++optind;
+			place = EMSG;
+			return(-1);
+		}
+	}					/* option letter okay? */
+	if ((optopt = (int)*place++) == (int)':' ||
+	    !(oli = index(ostr, optopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means EOF.
+		 */
+		if (optopt == (int)'-')
+			return(-1);
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':') {
+			if (!(p = rindex(*nargv, '/')))
+				p = *nargv;
+			else
+				++p;
+			(void)fprintf(stderr, "%s: illegal option -- %c\n",
+			    p, optopt);
+		}
+		return(BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		optarg = NULL;
+		if (!*place)
+			++optind;
+	}
+	else {					/* need an argument */
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (nargc <= ++optind) {	/* no arg */
+			place = EMSG;
+			if (!(p = rindex(*nargv, '/')))
+				p = *nargv;
+			else
+				++p;
+			if (*ostr == ':')
+				return(BADARG);
+			if (opterr)
+				(void)fprintf(stderr,
+				    "%s: option requires an argument -- %c\n",
+				    p, optopt);
+			return(BADCH);
+		}
+	 	else				/* white space */
+			optarg = nargv[optind];
+		place = EMSG;
+		++optind;
+	}
+	return(optopt);				/* dump back option letter */
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/gettytab.c b/krb5-1-6/src/appl/telnet/libtelnet/gettytab.c
new file mode 100644
index 000000000..aaad43aad
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/gettytab.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/* based on @(#)gettytab.c	5.1 (Berkeley) 4/29/85 */
+
+#include <ctype.h>
+
+#define	TABBUFSIZ	512
+
+static	char *tbuf;
+int	hopcount;	/* detect infinite loops in termcap, init 0 */
+char	*skip();
+char	*getstr();
+char	*decode();
+
+/*
+ * Get an entry for terminal name in buffer bp,
+ * from the termcap file.  Parse is very rudimentary;
+ * we just notice escaped newlines.
+ */
+getent(bp, name)
+	char *bp, *name;
+{
+	register char *cp;
+	register int c;
+	register int i = 0, cnt = 0;
+	char ibuf[TABBUFSIZ];
+	char *cp2;
+	int tf;
+
+	tbuf = bp;
+	tf = open("/etc/gettytab", 0);
+	if (tf < 0)
+		return (-1);
+	for (;;) {
+		cp = bp;
+		for (;;) {
+			if (i == cnt) {
+				cnt = read(tf, ibuf, TABBUFSIZ);
+				if (cnt <= 0) {
+					close(tf);
+					return (0);
+				}
+				i = 0;
+			}
+			c = ibuf[i++];
+			if (c == '\n') {
+				if (cp > bp && cp[-1] == '\\'){
+					cp--;
+					continue;
+				}
+				break;
+			}
+			if (cp >= bp+TABBUFSIZ) {
+				write(2,"Gettytab entry too long\n", 24);
+				break;
+			} else
+				*cp++ = c;
+		}
+		*cp = 0;
+
+		/*
+		 * The real work for the match.
+		 */
+		if (namatch(name)) {
+			close(tf);
+			return(nchktc());
+		}
+	}
+}
+
+/*
+ * tnchktc: check the last entry, see if it's tc=xxx. If so,
+ * recursively find xxx and append that entry (minus the names)
+ * to take the place of the tc=xxx entry. This allows termcap
+ * entries to say "like an HP2621 but doesn't turn on the labels".
+ * Note that this works because of the left to right scan.
+ */
+#define	MAXHOP	32
+nchktc()
+{
+	register char *p, *q;
+	char tcname[16];	/* name of similar terminal */
+	char tcbuf[TABBUFSIZ];
+	char *holdtbuf = tbuf;
+	int l;
+
+	p = tbuf + strlen(tbuf) - 2;	/* before the last colon */
+	while (*--p != ':')
+		if (p<tbuf) {
+			write(2, "Bad gettytab entry\n", 19);
+			return (0);
+		}
+	p++;
+	/* p now points to beginning of last field */
+	if (p[0] != 't' || p[1] != 'c')
+		return(1);
+	strncpy(tcname, p + 3, sizeof(tcname) - 1);
+	tcname[sizeof(tcname) - 1] = '\0';
+	q = tcname;
+	while (*q && *q != ':')
+		q++;
+	*q = 0;
+	if (++hopcount > MAXHOP) {
+		write(2, "Getty: infinite tc= loop\n", 25);
+		return (0);
+	}
+	if (getent(tcbuf, tcname) != 1)
+		return(0);
+	for (q=tcbuf; *q != ':'; q++)
+		;
+	l = p - holdtbuf + strlen(q);
+	if (l > TABBUFSIZ) {
+		write(2, "Gettytab entry too long\n", 24);
+		q[TABBUFSIZ - (p-tbuf)] = 0;
+	}
+	strcpy(p, q+1);
+	tbuf = holdtbuf;
+	return(1);
+}
+
+/*
+ * Tnamatch deals with name matching.  The first field of the termcap
+ * entry is a sequence of names separated by |'s, so we compare
+ * against each such name.  The normal : terminator after the last
+ * name (before the first field) stops us.
+ */
+namatch(np)
+	char *np;
+{
+	register char *Np, *Bp;
+
+	Bp = tbuf;
+	if (*Bp == '#')
+		return(0);
+	for (;;) {
+		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
+			continue;
+		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
+			return (1);
+		while (*Bp && *Bp != ':' && *Bp != '|')
+			Bp++;
+		if (*Bp == 0 || *Bp == ':')
+			return (0);
+		Bp++;
+	}
+}
+
+/*
+ * Skip to the next field.  Notice that this is very dumb, not
+ * knowing about \: escapes or any such.  If necessary, :'s can be put
+ * into the termcap file in octal.
+ */
+static char *
+skip(bp)
+	register char *bp;
+{
+
+	while (*bp && *bp != ':')
+		bp++;
+	if (*bp == ':')
+		bp++;
+	return (bp);
+}
+
+/*
+ * Return the (numeric) option id.
+ * Numeric options look like
+ *	li#80
+ * i.e. the option string is separated from the numeric value by
+ * a # character.  If the option is not found we return -1.
+ * Note that we handle octal numbers beginning with 0.
+ */
+long
+getnum(id)
+	char *id;
+{
+	register long i, base;
+	register char *bp = tbuf;
+
+	for (;;) {
+		bp = skip(bp);
+		if (*bp == 0)
+			return (-1);
+		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+			continue;
+		if (*bp == '@')
+			return(-1);
+		if (*bp != '#')
+			continue;
+		bp++;
+		base = 10;
+		if (*bp == '0')
+			base = 8;
+		i = 0;
+		while (isdigit(*bp))
+			i *= base, i += *bp++ - '0';
+		return (i);
+	}
+}
+
+/*
+ * Handle a flag option.
+ * Flag options are given "naked", i.e. followed by a : or the end
+ * of the buffer.  Return 1 if we find the option, or 0 if it is
+ * not given.
+ */
+getflag(id)
+	char *id;
+{
+	register char *bp = tbuf;
+
+	for (;;) {
+		bp = skip(bp);
+		if (!*bp)
+			return (-1);
+		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+			if (!*bp || *bp == ':')
+				return (1);
+			else if (*bp == '!')
+				return (0);
+			else if (*bp == '@')
+				return(-1);
+		}
+	}
+}
+
+/*
+ * Get a string valued option.
+ * These are given as
+ *	cl=^Z
+ * Much decoding is done on the strings, and the strings are
+ * placed in area, which is a ref parameter which is updated.
+ * No checking on area overflow.
+ */
+char *
+getstr(id, area)
+	char *id, **area;
+{
+	register char *bp = tbuf;
+
+	for (;;) {
+		bp = skip(bp);
+		if (!*bp)
+			return (0);
+		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+			continue;
+		if (*bp == '@')
+			return(0);
+		if (*bp != '=')
+			continue;
+		bp++;
+		return (decode(bp, area));
+	}
+}
+
+/*
+ * Tdecode does the grung work to decode the
+ * string capability escapes.
+ */
+static char *
+decode(str, area)
+	register char *str;
+	char **area;
+{
+	register char *cp;
+	register int c;
+	register char *dp;
+	int i;
+
+	cp = *area;
+	while ((c = *str++) && c != ':') {
+		switch (c) {
+
+		case '^':
+			c = *str++ & 037;
+			break;
+
+		case '\\':
+			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
+			c = *str++;
+nextc:
+			if (*dp++ == c) {
+				c = *dp++;
+				break;
+			}
+			dp++;
+			if (*dp)
+				goto nextc;
+			if (isdigit(c)) {
+				c -= '0', i = 2;
+				do
+					c <<= 3, c |= *str++ - '0';
+				while (--i && isdigit(*str));
+			}
+			break;
+		}
+		*cp++ = c;
+	}
+	*cp++ = 0;
+	str = *area;
+	*area = cp;
+	return (str);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/gettytab.h b/krb5-1-6/src/appl/telnet/libtelnet/gettytab.h
new file mode 100644
index 000000000..02e5050a8
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/gettytab.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ *	@(#)gettytab.h	5.2 (Berkeley) 1/7/86
+ */
+
+/*
+ * Getty description definitions.
+ */
+struct	gettystrs {
+	char	*field;		/* name to lookup in gettytab */
+	char	*defalt;	/* value we find by looking in defaults */
+	char	*value;		/* value that we find there */
+};
+
+struct	gettynums {
+	char	*field;		/* name to lookup */
+	long	defalt;		/* number we find in defaults */
+	long	value;		/* number we find there */
+	int	set;		/* we actually got this one */
+};
+
+struct gettyflags {
+	char	*field;		/* name to lookup */
+	char	invrt;		/* name existing in gettytab --> false */
+	char	defalt;		/* true/false in defaults */
+	char	value;		/* true/false flag */
+	char	set;		/* we found it */
+};
+
+/*
+ * String values.
+ */
+#define	NX	gettystrs[0].value
+#define	CL	gettystrs[1].value
+#define IM	gettystrs[2].value
+#define	LM	gettystrs[3].value
+#define	ER	gettystrs[4].value
+#define	KL	gettystrs[5].value
+#define	ET	gettystrs[6].value
+#define	PC	gettystrs[7].value
+#define	TT	gettystrs[8].value
+#define	EV	gettystrs[9].value
+#define	LO	gettystrs[10].value
+#define HN	gettystrs[11].value
+#define HE	gettystrs[12].value
+#define IN	gettystrs[13].value
+#define QU	gettystrs[14].value
+#define XN	gettystrs[15].value
+#define XF	gettystrs[16].value
+#define BK	gettystrs[17].value
+#define SU	gettystrs[18].value
+#define DS	gettystrs[19].value
+#define RP	gettystrs[20].value
+#define FL	gettystrs[21].value
+#define WE	gettystrs[22].value
+#define LN	gettystrs[23].value
+
+/*
+ * Numeric definitions.
+ */
+#define	IS	gettynums[0].value
+#define	OS	gettynums[1].value
+#define	SP	gettynums[2].value
+#define	ND	gettynums[3].value
+#define	CD	gettynums[4].value
+#define	TD	gettynums[5].value
+#define	FD	gettynums[6].value
+#define	BD	gettynums[7].value
+#define	TO	gettynums[8].value
+#define	F0	gettynums[9].value
+#define	F0set	gettynums[9].set
+#define	F1	gettynums[10].value
+#define	F1set	gettynums[10].set
+#define	F2	gettynums[11].value
+#define	F2set	gettynums[11].set
+#define	PF	gettynums[12].value
+
+/*
+ * Boolean values.
+ */
+#define	HT	gettyflags[0].value
+#define	NL	gettyflags[1].value
+#define	EP	gettyflags[2].value
+#define	EPset	gettyflags[2].set
+#define	OP	gettyflags[3].value
+#define	OPset	gettyflags[2].set
+#define	AP	gettyflags[4].value
+#define	APset	gettyflags[2].set
+#define	EC	gettyflags[5].value
+#define	CO	gettyflags[6].value
+#define	CB	gettyflags[7].value
+#define	CK	gettyflags[8].value
+#define	CE	gettyflags[9].value
+#define	PE	gettyflags[10].value
+#define	RW	gettyflags[11].value
+#define	XC	gettyflags[12].value
+#define	LC	gettyflags[13].value
+#define	UC	gettyflags[14].value
+#define	IG	gettyflags[15].value
+#define	PS	gettyflags[16].value
+#define	HC	gettyflags[17].value
+#define UB	gettyflags[18].value
+#define AB	gettyflags[19].value
+#define DX	gettyflags[20].value
+#define RM	gettyflags[21].value
+
+int	getent (char *, char *);
+long	getnum();
+int	getflag();
+#ifndef SOLARIS
+char	*getstr(char *, char **);
+#endif
+
+extern	struct gettyflags gettyflags[];
+extern	struct gettynums gettynums[];
+extern	struct gettystrs gettystrs[];
+extern	int hopcount;
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/herror.c b/krb5-1-6/src/appl/telnet/libtelnet/herror.c
new file mode 100644
index 000000000..3b20f807f
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/herror.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)herror.c	8.1 (Berkeley) 6/4/93 */
+
+#include <stdio.h>
+
+char	*h_errlist[] = {
+	"Error 0",
+	"Unknown host",				/* 1 HOST_NOT_FOUND */
+	"Host name lookup failure",		/* 2 TRY_AGAIN */
+	"Unknown server error",			/* 3 NO_RECOVERY */
+	"No address associated with name",	/* 4 NO_ADDRESS */
+};
+int	h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
+
+int h_errno;		/* In some version of SunOS this is necessary */
+
+/*
+ * herror --
+ *	print the error indicated by the h_errno value.
+ */
+herror(s)
+	char *s;
+{
+	if (s && *s) {
+		fprintf(stderr, "%s: ", s);
+	}
+	if ((h_errno < 0) || (h_errno >= h_nerr)) {
+		fprintf(stderr, "Unknown error\n");
+	} else if (h_errno == 0) {
+#if	defined(sun)
+		fprintf(stderr, "Host unknown\n");
+#endif	/* defined(sun) */
+	} else {
+		fprintf(stderr, "%s\n", h_errlist[h_errno]);
+	}
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/kerberos.c b/krb5-1-6/src/appl/telnet/libtelnet/kerberos.c
new file mode 100644
index 000000000..7e0d7360c
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/kerberos.c
@@ -0,0 +1,744 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)kerberos.c	8.1 (Berkeley) 6/4/93 */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Copyright (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 <errno.h>
+#include <arpa/telnet.h>
+#include <stdio.h>
+#include <des.h>        /* BSD wont include this in krb.h, so we do it here */
+#include <krb.h>
+#ifdef	__STDC__
+#include <stdlib.h>
+#endif
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+extern int auth_debug_mode;
+extern krb5_context telnet_context;
+
+int kerberos4_cksum (unsigned char *, int);
+
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+			  		AUTHTYPE_KERBEROS_V4, };
+#if 0
+static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
+					TELQUAL_NAME, };
+#endif
+
+#define	KRB_AUTH	0		/* Authentication data follows */
+#define	KRB_REJECT	1		/* Rejected (reason might follow) */
+#define	KRB_ACCEPT	2		/* Accepted */
+#define	KRB_CHALLENGE	3		/* Challenge for mutual auth. */
+#define	KRB_RESPONSE	4		/* Response for mutual auth. */
+
+#define KRB_SERVICE_NAME   "rcmd"
+
+static	KTEXT_ST auth;
+static	char name[ANAME_SZ];
+static	AUTH_DAT adat = { 0 };
+#ifdef	ENCRYPTION
+static Block	session_key	= { 0 };
+static krb5_keyblock krbkey;
+static Block	challenge	= { 0 };
+#endif	/* ENCRYPTION */
+
+	static int
+Data(ap, type, d, c)
+	Authenticator *ap;
+	int type;
+	const void *d;
+	int c;
+{
+        unsigned char *p = str_data + 4;
+	const unsigned char *cd = (const unsigned char *)d;
+	size_t spaceleft = sizeof(str_data) - 4;
+	if (c == -1)
+		c = strlen((const char *)cd);
+
+        if (auth_debug_mode) {
+                printf("%s:%d: [%d] (%d)",
+                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
+                        str_data[3],
+                        type, c);
+                printd(d, c);
+                printf("\r\n");
+        }
+	*p++ = ap->type;
+	*p++ = ap->way;
+	*p++ = type;
+	spaceleft -= 3;
+        while (c-- > 0) {
+		if ((*p++ = *cd++) == IAC) {
+			*p++ = IAC;
+			spaceleft--;
+		}
+		if ((--spaceleft < 4) && c) {
+			errno = ENOMEM;
+			return -1;
+		}
+        }
+        *p++ = IAC;
+        *p++ = SE;
+	if (str_data[3] == TELQUAL_IS)
+		printsub('>', &str_data[2], p - (&str_data[2]));
+        return(net_write(str_data, p - str_data));
+}
+
+	int
+kerberos4_init(ap, server)
+	Authenticator *ap;
+	int server;
+{
+	FILE *fp;
+
+	if (server) {
+		str_data[3] = TELQUAL_REPLY;
+		if ((fp = fopen(KEYFILE, "r")) == NULL)
+			return(0);
+		fclose(fp);
+	} else {
+		str_data[3] = TELQUAL_IS;
+	}
+
+	kerberos5_init(NULL, server);
+
+	return(1);
+}
+
+char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
+unsigned int dst_realm_sz = REALM_SZ;
+
+	int
+kerberos4_send(ap)
+	Authenticator *ap;
+{
+	KTEXT_ST kauth;
+	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 rand_key;
+#endif
+
+	printf("[ Trying KERBEROS4 ... ]\r\n");	
+	if (!UserNameRequested) {
+		if (auth_debug_mode) {
+			printf("Kerberos V4: no user name supplied\r\n");
+		}
+		return(0);
+	}
+
+	memset(instance, 0, sizeof(instance));
+
+	if ((realm = krb_get_phost(RemoteHostName)))
+		strncpy(instance, realm, sizeof(instance));
+
+	instance[sizeof(instance)-1] = '\0';
+
+	realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
+
+	if (!realm) {
+		printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
+		return(0);
+	}
+	if ((r = krb_mk_req(&kauth, KRB_SERVICE_NAME, instance, realm, 0))) {
+		printf("mk_req failed: %s\r\n", krb_get_err_text(r));
+		return(0);
+	}
+	if ((r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred))) {
+		printf("get_cred failed: %s\r\n", krb_get_err_text(r));
+		return(0);
+	}
+	if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+		if (auth_debug_mode)
+			printf("Not enough room for user name\r\n");
+		return(0);
+	}
+	if (auth_debug_mode)
+		printf("Sent %d bytes of authentication data\r\n", kauth.length);
+	if (!Data(ap, KRB_AUTH, (void *)kauth.dat, kauth.length)) {
+		if (auth_debug_mode)
+			printf("Not enough room for authentication data\r\n");
+		return(0);
+	}
+#ifdef	ENCRYPTION
+	/*
+	 * If we are doing mutual authentication, get set up to send
+	 * the challenge, and verify it when the response comes back.
+	 */
+	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+		register int i;
+
+		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,
+						   &rand_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 = rand_key.contents;
+		encdata.ciphertext.length = rand_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, &rand_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.
+		 */
+		for (i = 7; i >= 0; --i) {
+			register int x;
+			x = (unsigned int)challenge[i] + 1;
+			challenge[i] = x;	/* ignore overflow */
+			if (x < 256)		/* if no overflow, all done */
+				break;
+		}
+
+		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 */
+	
+	if (auth_debug_mode) {
+		printf("CK: %d:", kerberos4_cksum(kauth.dat, kauth.length));
+		printd(kauth.dat, kauth.length);
+		printf("\r\n");
+		printf("Sent Kerberos V4 credentials to server\r\n");
+	}
+	return(1);
+}
+
+	void
+kerberos4_is(ap, data, cnt)
+	Authenticator *ap;
+	unsigned char *data;
+	int cnt;
+{
+#ifdef	ENCRYPTION
+	Session_Key skey;
+	Block datablock, tmpkey;
+	krb5_data kdata;
+	krb5_enc_data encdata;
+	krb5_error_code code;
+#endif	/* ENCRYPTION */
+	char realm[REALM_SZ];
+	char instance[INST_SZ];
+	int r;
+
+	if (cnt-- < 1)
+		return;
+	switch (*data++) {
+	case KRB_AUTH:
+		if (krb_get_lrealm(realm, 1) != KSUCCESS) {
+			Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
+			auth_finished(ap, AUTH_REJECT);
+			if (auth_debug_mode)
+				printf("No local realm\r\n");
+			return;
+		}
+		memcpy((void *)auth.dat, (void *)data, auth.length = cnt);
+		if (auth_debug_mode) {
+			printf("Got %d bytes of authentication data\r\n", cnt);
+			printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
+			printd(auth.dat, auth.length);
+			printf("\r\n");
+		}
+		instance[0] = '*'; instance[1] = 0;
+		if ((r = krb_rd_req(&auth, KRB_SERVICE_NAME,
+				    instance, 0, &adat, ""))) {
+			if (auth_debug_mode)
+				printf("Kerberos failed him as %s\r\n", name);
+			Data(ap, KRB_REJECT, (const void *)krb_get_err_text(r), -1);
+			auth_finished(ap, AUTH_REJECT);
+			return;
+		}
+#ifdef	ENCRYPTION
+		memcpy((void *)session_key, (void *)adat.session, sizeof(Block));
+#endif	/* ENCRYPTION */
+		krb_kntoln(&adat, name);
+
+		if (UserNameRequested && !kuserok(&adat, UserNameRequested))
+			Data(ap, KRB_ACCEPT, (void *)0, 0);
+		else
+			Data(ap, KRB_REJECT,
+				(void *)"user is not authorized", -1);
+		auth_finished(ap, AUTH_USER);
+		break;
+
+	case KRB_CHALLENGE:
+#ifndef	ENCRYPTION
+		Data(ap, KRB_RESPONSE, (void *)0, 0);
+#else	/* ENCRYPTION */
+		if (!VALIDKEY(session_key)) {
+			/*
+			 * We don't have a valid session key, so just
+			 * send back a response with an empty session
+			 * key.
+			 */
+			Data(ap, KRB_RESPONSE, (void *)0, 0);
+			break;
+		}
+
+		/*
+		 * Initialize the random number generator since it's
+		 * used later on by the encryption routine.
+		 */
+
+		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.
+		 */
+		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 = tmpkey;
+		encrypt_session_key(&skey, 1);
+		/*
+		 * Now decrypt the received encrypted challenge,
+		 * increment by one, re-encrypt it and send it back.
+		 */
+		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;
+			challenge[r] = t;	/* ignore overflow */
+			if (t < 256)		/* if no overflow, all done */
+				break;
+		}
+
+		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;
+
+	default:
+		if (auth_debug_mode)
+			printf("Unknown Kerberos option %d\r\n", data[-1]);
+		Data(ap, KRB_REJECT, 0, 0);
+		break;
+	}
+}
+
+	void
+kerberos4_reply(ap, data, cnt)
+	Authenticator *ap;
+	unsigned char *data;
+	int cnt;
+{
+#ifdef	ENCRYPTION
+	Session_Key skey;
+	krb5_data kdata;
+	krb5_enc_data encdata;
+	krb5_error_code code;
+
+#endif	/* ENCRYPTION */
+
+	if (cnt-- < 1)
+		return;
+	switch (*data++) {
+	case KRB_REJECT:
+		if (cnt > 0) {
+			printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n",
+				cnt, data);
+		} else
+			printf("[ Kerberos V4 refuses authentication ]\r\n");
+		auth_send_retry();
+		return;
+	case KRB_ACCEPT:
+		printf("[ Kerberos V4 accepts you ]\r\n");
+		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+			/*
+			 * Send over the encrypted challenge.
+		 	 */
+#ifndef	ENCRYPTION
+			Data(ap, KRB_CHALLENGE, (void *)0, 0);
+#else	/* ENCRYPTION */
+			Data(ap, KRB_CHALLENGE, (void *)session_key,
+						sizeof(session_key));
+
+			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;
+			encrypt_session_key(&skey, 0);
+#endif	/* ENCRYPTION */
+			return;
+		}
+		auth_finished(ap, AUTH_USER);
+		return;
+	case KRB_RESPONSE:
+#ifdef	ENCRYPTION
+		/*
+		 * Verify that the response to the challenge is correct.
+		 */
+		if ((cnt != sizeof(Block)) ||
+		    (0 != memcmp((void *)data, (void *)challenge,
+						sizeof(challenge))))
+		{
+#endif	/* ENCRYPTION */
+			printf("[ Kerberos V4 challenge failed!!! ]\r\n");
+			auth_send_retry();
+			return;
+#ifdef	ENCRYPTION
+		}
+		printf("[ Kerberos V4 challenge successful ]\r\n");
+		auth_finished(ap, AUTH_USER);
+#endif	/* ENCRYPTION */
+		break;
+	default:
+		if (auth_debug_mode)
+			printf("Unknown Kerberos option %d\r\n", data[-1]);
+		return;
+	}
+}
+
+	int
+kerberos4_status(ap, kname, level)
+	Authenticator *ap;
+	char *kname;
+	int level;
+{
+	if (level < AUTH_USER)
+		return(level);
+
+	/*
+	 * Always copy in UserNameRequested if the authentication
+	 * is valid, because the higher level routines need it.
+	 */
+	if (UserNameRequested) {
+		/* the name buffer comes from telnetd/telnetd{-ktd}.c */
+		strncpy(kname, UserNameRequested, 255);
+		kname[255] = '\0';
+	}
+
+	if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
+		return(AUTH_VALID);
+	} else
+		return(AUTH_USER);
+}
+
+#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
+#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+	void
+kerberos4_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt;
+	unsigned int buflen;
+{
+	char lbuf[32];
+	register int i;
+
+	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
+	buflen -= 1;
+
+	switch(data[3]) {
+	case KRB_REJECT:		/* Rejected (reason might follow) */
+		strncpy((char *)buf, " REJECT ", buflen);
+		goto common;
+
+	case KRB_ACCEPT:		/* Accepted (name might follow) */
+		strncpy((char *)buf, " ACCEPT ", buflen);
+	common:
+		BUMP(buf, buflen);
+		if (cnt <= 4)
+			break;
+		ADDC(buf, buflen, '"');
+		for (i = 4; i < cnt; i++)
+			ADDC(buf, buflen, data[i]);
+		ADDC(buf, buflen, '"');
+		ADDC(buf, buflen, '\0');
+		break;
+
+	case KRB_AUTH:			/* Authentication data follows */
+		strncpy((char *)buf, " AUTH", buflen);
+		goto common2;
+
+	case KRB_CHALLENGE:
+		strncpy((char *)buf, " CHALLENGE", buflen);
+		goto common2;
+
+	case KRB_RESPONSE:
+		strncpy((char *)buf, " RESPONSE", buflen);
+		goto common2;
+
+	default:
+		sprintf(lbuf, " %d (unknown)", data[3]);
+		strncpy((char *)buf, lbuf, buflen);
+	common2:
+		BUMP(buf, buflen);
+		for (i = 4; i < cnt; i++) {
+			sprintf(lbuf, " %d", data[i]);
+			strncpy((char *)buf, lbuf, buflen);
+			BUMP(buf, buflen);
+		}
+		break;
+	}
+}
+
+	int
+kerberos4_cksum(d, n)
+	unsigned char *d;
+	int n;
+{
+	int ck = 0;
+
+	/*
+	 * A comment is probably needed here for those not
+	 * well versed in the "C" language.  Yes, this is
+	 * supposed to be a "switch" with the body of the
+	 * "switch" being a "while" statement.  The whole
+	 * purpose of the switch is to allow us to jump into
+	 * the middle of the while() loop, and then not have
+	 * to do any more switch()s.
+	 *
+	 * Some compilers will spit out a warning message
+	 * about the loop not being entered at the top.
+	 */
+	switch (n&03)
+	while (n > 0) {
+	case 0:
+		ck ^= (int)*d++ << 24;
+		--n;
+	case 3:
+		ck ^= (int)*d++ << 16;
+		--n;
+	case 2:
+		ck ^= (int)*d++ << 8;
+		--n;
+	case 1:
+		ck ^= (int)*d++;
+		--n;
+	}
+	return(ck);
+}
+#else
+#include <krb5.h>
+#include <errno.h>
+
+#endif
+
+#ifdef notdef
+
+prkey(msg, key)
+	char *msg;
+	unsigned char *key;
+{
+	register int i;
+	printf("%s:", msg);
+	for (i = 0; i < 8; i++)
+		printf(" %3d", key[i]);
+	printf("\r\n");
+}
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/kerberos5.c b/krb5-1-6/src/appl/telnet/libtelnet/kerberos5.c
new file mode 100644
index 000000000..1ef6fbace
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/kerberos5.c
@@ -0,0 +1,903 @@
+/*
+ *	appl/telnet/libtelnet/kerberos5.c
+ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)kerberos5.c	8.1 (Berkeley) 6/4/93 */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#ifdef	KRB5
+#include <arpa/telnet.h>
+#include <errno.h>
+#include <stdio.h>
+#include "krb5.h"
+
+#include "com_err.h"
+#include <netdb.h>
+#include <ctype.h>
+#include <syslog.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *malloc();
+#endif
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+ 
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+extern int auth_debug_mode;
+extern int net;
+
+#ifdef	FORWARD
+int forward_flags = 0;  /* Flags get set in telnet/main.c on -f and -F */
+
+static void kerberos5_forward(Authenticator *);
+
+#include "krb5forw.h"
+
+#endif	/* FORWARD */
+
+static unsigned char str_data[TELNET_BUFSIZE] = {IAC, SB, TELOPT_AUTHENTICATION, 0,
+			  		AUTHTYPE_KERBEROS_V5, };
+/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
+					TELQUAL_NAME, };*/
+
+#define	KRB_AUTH		0	/* Authentication data follows */
+#define	KRB_REJECT		1	/* Rejected (reason might follow) */
+#define	KRB_ACCEPT		2	/* Accepted */
+#define	KRB_RESPONSE		3	/* Response for mutual auth. */
+
+#ifdef	FORWARD
+#define KRB_FORWARD     	4       /* Forwarded credentials follow */
+#define KRB_FORWARD_ACCEPT     	5       /* Forwarded credentials accepted */
+#define KRB_FORWARD_REJECT     	6       /* Forwarded credentials rejected */
+#endif	/* FORWARD */
+
+krb5_auth_context auth_context = 0;
+
+static	krb5_data auth;
+	/* telnetd gets session key from here */
+static	krb5_ticket * ticket = NULL;
+/* telnet matches the AP_REQ and AP_REP with this */
+
+/* some compilers can't hack void *, so we use the Kerberos krb5_pointer,
+   which is either void * or char *, depending on the compiler. */
+
+#define Voidptr krb5_pointer
+
+krb5_keyblock	*session_key = 0;
+char *		telnet_srvtab = NULL;
+char *		telnet_krb5_realm = NULL;
+
+	static int
+Data(ap, type, d, c)
+	Authenticator *ap;
+	int type;
+	Voidptr d;
+	int c;
+{
+        unsigned char *p = str_data + 4;
+	unsigned char *cd = (unsigned char *)d;
+	size_t spaceleft = sizeof(str_data) - 4;
+
+	if (c == -1)
+		c = strlen((char *)cd);
+
+        if (auth_debug_mode) {
+                printf("%s:%d: [%d] (%d)",
+                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
+                        str_data[3],
+                        type, c);
+                printd(d, c);
+                printf("\r\n");
+        }
+	*p++ = ap->type;
+	*p++ = ap->way;
+	*p++ = type;
+	spaceleft -= 3;
+        while (c-- > 0) {
+		if ((*p++ = *cd++) == IAC) {
+			*p++ = IAC;
+			spaceleft--;
+		}
+		if ((--spaceleft < 4) && c) {
+			errno = ENOMEM;
+			return -1;
+		}
+        }
+        *p++ = IAC;
+        *p++ = SE;
+	if (str_data[3] == TELQUAL_IS)
+		printsub('>', &str_data[2], p - &str_data[2]);
+        return(net_write(str_data, p - str_data));
+}
+
+krb5_context telnet_context = 0;
+int
+kerberos5_init(ap, server)
+	Authenticator *ap;
+	int server;
+{
+	krb5_error_code retval;
+	
+	if (server)
+		str_data[3] = TELQUAL_REPLY;
+	else
+		str_data[3] = TELQUAL_IS;
+	if (telnet_context == 0) {
+		retval = krb5_init_context(&telnet_context);
+		if (retval)
+			return 0;
+	}
+	return(1);
+}
+
+void
+kerberos5_cleanup()
+{
+    krb5_error_code retval;
+    krb5_ccache ccache;
+    char *ccname;
+    
+    if (telnet_context == 0)
+	return;
+
+    ccname = getenv("KRB5CCNAME");
+    if (ccname) {
+	retval = krb5_cc_resolve(telnet_context, ccname, &ccache);
+	if (!retval)
+	    retval = krb5_cc_destroy(telnet_context, ccache);
+    }
+
+    krb5_free_context(telnet_context);
+    telnet_context = 0;
+}
+
+
+	int
+kerberos5_send(ap)
+	Authenticator *ap;
+{
+	krb5_error_code r;
+	krb5_ccache ccache;
+	krb5_creds creds;		/* telnet gets session key from here */
+	krb5_creds * new_creds = 0;
+	int ap_opts;
+	char type_check[2];
+	krb5_data check_data;
+
+#ifdef	ENCRYPTION
+	krb5_keyblock *newkey = 0;
+#endif	/* ENCRYPTION */
+
+        if (!UserNameRequested) {
+                if (auth_debug_mode) {
+                        printf(
+			"telnet: Kerberos V5: no user name supplied\r\n");
+                }
+                return(0);
+        }
+
+	if ((r = krb5_cc_default(telnet_context, &ccache))) {
+		if (auth_debug_mode) {
+		    printf(
+		    "telnet: Kerberos V5: could not get default ccache\r\n");
+		}
+		return(0);
+	}
+
+	memset((char *)&creds, 0, sizeof(creds));
+	if (auth_debug_mode)
+	    printf("telnet: calling krb5_sname_to_principal\n");
+	if ((r = krb5_sname_to_principal(telnet_context, RemoteHostName,
+					 "host", KRB5_NT_SRV_HST,
+					 &creds.server))) {
+	    if (auth_debug_mode)
+		printf("telnet: Kerberos V5: error while constructing service name: %s\r\n", error_message(r));
+	    return(0);
+	}
+	if (auth_debug_mode)
+	    printf("telnet: done calling krb5_sname_to_principal\n");
+
+	if (telnet_krb5_realm != NULL) {
+	    krb5_data rdata;
+
+	    rdata.magic = 0;
+	    rdata.length = strlen(telnet_krb5_realm);
+	    rdata.data = (char *) malloc(rdata.length + 1);
+	    if (rdata.data == NULL) {
+	        fprintf(stderr, "malloc failed\n");
+		return(0);
+	    }
+	    strcpy(rdata.data, telnet_krb5_realm);
+	    krb5_princ_set_realm(telnet_context, creds.server, &rdata);
+	}
+
+	if ((r = krb5_cc_get_principal(telnet_context, ccache,
+				       &creds.client))) {
+		if (auth_debug_mode) {
+			printf(
+			"telnet: Kerberos V5: failure on principal (%s)\r\n",
+				error_message(r));
+		}
+		krb5_free_cred_contents(telnet_context, &creds);
+		return(0);
+	}
+
+	creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
+	if ((r = krb5_get_credentials(telnet_context, 0,
+				      ccache, &creds, &new_creds))) {
+		if (auth_debug_mode) {
+			printf(
+			"telnet: Kerberos V5: failure on credentials(%s)\r\n",
+			       error_message(r));
+		}
+		krb5_free_cred_contents(telnet_context, &creds);
+		return(0);
+	}
+
+	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+	    ap_opts = AP_OPTS_MUTUAL_REQUIRED;
+	else
+	    ap_opts = 0;
+
+#ifdef ENCRYPTION
+	ap_opts |= AP_OPTS_USE_SUBKEY;
+#endif	/* ENCRYPTION */
+	    
+	if (auth_context) {
+	    krb5_auth_con_free(telnet_context, auth_context);
+	    auth_context = 0;
+	}
+	if ((r = krb5_auth_con_init(telnet_context, &auth_context))) {
+	    if (auth_debug_mode) {
+		printf("Kerberos V5: failed to init auth_context (%s)\r\n",
+		       error_message(r));
+	    }
+	    return(0);
+	}
+	
+	krb5_auth_con_setflags(telnet_context, auth_context,
+			       KRB5_AUTH_CONTEXT_RET_TIME);
+	
+	type_check[0] = ap->type;
+	type_check[1] = ap->way;
+	check_data.magic = KV5M_DATA;
+	check_data.length = 2;
+	check_data.data = (char *) &type_check;
+
+	r = krb5_mk_req_extended(telnet_context, &auth_context, ap_opts,
+				 &check_data, new_creds, &auth);
+
+#ifdef	ENCRYPTION
+	krb5_auth_con_getsendsubkey(telnet_context, auth_context, &newkey);
+	if (session_key) {
+		krb5_free_keyblock(telnet_context, session_key);
+		session_key = 0;
+	}
+
+	if (newkey) {
+	    /* keep the key in our private storage, but don't use it
+	       yet---see kerberos5_reply() below */
+	    if ((newkey->enctype != ENCTYPE_DES_CBC_CRC) &&
+		(newkey-> enctype != ENCTYPE_DES_CBC_MD5)) {
+		if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
+		    (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
+		    /* use the session key in credentials instead */
+		    krb5_copy_keyblock(telnet_context,&new_creds->keyblock,
+				       &session_key);
+		else
+		    /* XXX ? */;
+	    } else {
+		krb5_copy_keyblock(telnet_context, newkey, &session_key);
+	    }
+	    krb5_free_keyblock(telnet_context, newkey);
+	}
+#endif	/* ENCRYPTION */
+	krb5_free_cred_contents(telnet_context, &creds);
+	krb5_free_creds(telnet_context, new_creds);
+	if (r) {
+		if (auth_debug_mode) {
+			printf("telnet: Kerberos V5: mk_req failed (%s)\r\n",
+			       error_message(r));
+		}
+		return(0);
+	}
+
+        if (!auth_sendname((unsigned char *) UserNameRequested, 
+			   (int) strlen(UserNameRequested))) {
+                if (auth_debug_mode)
+                        printf("telnet: Not enough room for user name\r\n");
+                return(0);
+        }
+	if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
+		if (auth_debug_mode)
+		    printf(
+		    "telnet: Not enough room for authentication data\r\n");
+		return(0);
+	}
+	if (auth_debug_mode) {
+		printf("telnet: Sent Kerberos V5 credentials to server\r\n");
+	}
+	return(1);
+}
+
+	void
+kerberos5_is(ap, data, cnt)
+	Authenticator *ap;
+	unsigned char *data;
+	int cnt;
+{
+	int r = 0;
+	krb5_principal server;
+	krb5_keyblock *newkey = NULL;
+	krb5_keytab keytabid = 0;
+	krb5_data outbuf;
+#ifdef ENCRYPTION
+	Session_Key skey;
+#endif
+	char errbuf[320];
+	char *name;
+	char *getenv();
+	krb5_data inbuf;
+	krb5_authenticator *authenticator;
+
+	if (cnt-- < 1)
+		return;
+	switch (*data++) {
+	case KRB_AUTH:
+		auth.data = (char *)data;
+		auth.length = cnt;
+
+		if (!r && !auth_context)
+		    r = krb5_auth_con_init(telnet_context, &auth_context);
+		if (!r) {
+		    krb5_rcache rcache;
+		    
+		    r = krb5_auth_con_getrcache(telnet_context, auth_context,
+						&rcache);
+		    if (!r && !rcache) {
+			r = krb5_sname_to_principal(telnet_context, 0, 0,
+						    KRB5_NT_SRV_HST, &server);
+			if (!r) {
+			    r = krb5_get_server_rcache(telnet_context,
+					krb5_princ_component(telnet_context,
+							     server, 0),
+						       &rcache);
+			    krb5_free_principal(telnet_context, server);
+			}
+		    }
+		    if (!r)
+			r = krb5_auth_con_setrcache(telnet_context,
+						    auth_context, rcache);
+		}
+		if (!r && telnet_srvtab)
+		    r = krb5_kt_resolve(telnet_context, 
+					telnet_srvtab, &keytabid);
+		if (!r)
+		    r = krb5_rd_req(telnet_context, &auth_context, &auth,
+				    NULL, keytabid, NULL, &ticket);
+		if (r) {
+			(void) strcpy(errbuf, "krb5_rd_req failed: ");
+			errbuf[sizeof(errbuf) - 1] = '\0';
+			(void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+			goto errout;
+		}
+
+		/*
+		 * 256 bytes should be much larger than any reasonable
+		 * first component of a service name especially since
+		 * the default is of length 4.
+		 */
+		if (krb5_princ_size(telnet_context,ticket->server) < 1) {
+		    (void) strcpy(errbuf, "malformed service name");
+		    goto errout;
+		}
+		if (krb5_princ_component(telnet_context,ticket->server,0)->length < 256) {
+		    char princ[256];
+		    strncpy(princ,	
+			    krb5_princ_component(telnet_context, ticket->server,0)->data,
+			    krb5_princ_component(telnet_context, ticket->server,0)->length);
+		    princ[krb5_princ_component(telnet_context, 
+					       ticket->server,0)->length] = '\0';
+		    if (strcmp("host", princ)) {
+                        if(strlen(princ) < sizeof(errbuf) - 39) {
+                            (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"host\"",
+                                           princ);
+                        } else {
+                            (void) sprintf(errbuf, "incorrect service name: principal != \"host\"");
+                        }
+			goto errout;
+		    }
+		} else {
+		    (void) strcpy(errbuf, "service name too long");
+		    goto errout;
+		}
+
+		r = krb5_auth_con_getauthenticator(telnet_context,
+						   auth_context,
+						   &authenticator);
+		if (r) {
+		    (void) strcpy(errbuf,
+				  "krb5_auth_con_getauthenticator failed: ");
+		    errbuf[sizeof(errbuf) - 1] = '\0';
+		    (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+		    goto errout;
+		}
+		if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
+		    !authenticator->checksum) {
+			(void) strcpy(errbuf,
+				"authenticator is missing required checksum");
+			goto errout;
+		}
+		if (authenticator->checksum) {
+		    char type_check[2];
+		    krb5_checksum *cksum = authenticator->checksum;
+		    krb5_keyblock *key;
+
+		    type_check[0] = ap->type;
+		    type_check[1] = ap->way;
+
+		    r = krb5_auth_con_getkey(telnet_context, auth_context,
+					     &key);
+		    if (r) {
+			(void) strcpy(errbuf, "krb5_auth_con_getkey failed: ");
+			errbuf[sizeof(errbuf) - 1] = '\0';
+			(void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+			goto errout;
+		    }
+		    r = krb5_verify_checksum(telnet_context,
+					     cksum->checksum_type, cksum,
+					     &type_check, 2, key->contents,
+					     key->length);
+		/*
+		 * Note that krb5_verify_checksum() will fail if a pre-
+		 * MIT Kerberos Beta 5 client is attempting to connect
+		 * to this server (Beta 6 or later). There is not way to
+		 * fix this without compromising encryption. It would be
+		 * reasonable to add a -i option to telnetd to ignore
+		 * checksums (like in klogind). Such an option is not
+		 * present at this time.
+		 */
+		    if (r) {
+			(void) strcpy(errbuf,
+				      "checksum verification failed: ");
+		        errbuf[sizeof(errbuf) - 1] = '\0';
+			(void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+			goto errout;
+		    }
+		    krb5_free_keyblock(telnet_context, key);
+		}
+		krb5_free_authenticator(telnet_context, authenticator);
+		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+		    /* do ap_rep stuff here */
+		    if ((r = krb5_mk_rep(telnet_context, auth_context,
+					 &outbuf))) {
+			(void) strcpy(errbuf, "Make reply failed: ");
+		        errbuf[sizeof(errbuf) - 1] = '\0';
+			(void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+			goto errout;
+		    }
+
+		    Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
+		} 
+		if (krb5_unparse_name(telnet_context, 
+				      ticket->enc_part2 ->client,
+				      &name))
+			name = 0;
+		Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
+		if (auth_debug_mode) {
+			printf(
+			"telnetd: Kerberos5 identifies him as ``%s''\r\n",
+							name ? name : "");
+		}
+                auth_finished(ap, AUTH_USER);
+		
+		if (name)
+		    free(name);
+		krb5_auth_con_getrecvsubkey(telnet_context, auth_context,
+					      &newkey);
+		if (session_key) {
+		    krb5_free_keyblock(telnet_context, session_key);
+		    session_key = 0;
+		}
+	    	if (newkey) {
+		    krb5_copy_keyblock(telnet_context, newkey, &session_key);
+		    krb5_free_keyblock(telnet_context, newkey);
+		} else {
+		    krb5_copy_keyblock(telnet_context,
+				       ticket->enc_part2->session,
+				       &session_key);
+		}
+		
+#ifdef ENCRYPTION
+		skey.type = SK_DES;
+		skey.length = 8;
+		skey.data = session_key->contents;
+		encrypt_session_key(&skey, 1);
+#endif
+		break;
+#ifdef	FORWARD
+	case KRB_FORWARD:
+		inbuf.length = cnt;
+		inbuf.data = (char *)data;
+		if ((r = krb5_auth_con_genaddrs(telnet_context, auth_context, 
+			net, KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) || 
+		    (r = rd_and_store_for_creds(telnet_context, auth_context,
+			   &inbuf, ticket))) {
+
+		    char kerrbuf[128];
+		    
+		    (void) strcpy(kerrbuf, "Read forwarded creds failed: ");
+		    kerrbuf[sizeof(kerrbuf) - 1] = '\0';
+		    (void) strncat(kerrbuf, error_message(r), 
+			sizeof(kerrbuf) - 1 - strlen(kerrbuf));
+		    Data(ap, KRB_FORWARD_REJECT, kerrbuf, -1);
+		    if (auth_debug_mode)
+		      printf(
+			"telnetd: Could not read forwarded credentials\r\n");
+		}
+		else 
+		  Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
+		  if (auth_debug_mode)
+		    printf("telnetd: Forwarded credentials obtained\r\n");
+		break;
+#endif	/* FORWARD */
+	default:
+		if (auth_debug_mode)
+			printf("telnetd: Unknown Kerberos option %d\r\n",
+			data[-1]);
+		Data(ap, KRB_REJECT, 0, 0);
+		break;
+	}
+	return;
+	
+    errout:
+	{
+	    char eerrbuf[329];
+
+	    strcpy(eerrbuf, "telnetd: ");
+	    eerrbuf[sizeof(eerrbuf) - 1] = '\0';
+	    strncat(eerrbuf, errbuf, sizeof(eerrbuf) - 1 - strlen(eerrbuf));
+	    Data(ap, KRB_REJECT, eerrbuf, -1);
+	}
+	if (auth_debug_mode)
+	    printf("telnetd: %s\r\n", errbuf);
+	syslog(LOG_ERR, "%s", errbuf);
+	if (auth_context) {
+	    krb5_auth_con_free(telnet_context, auth_context);
+	    auth_context = 0;
+	}
+	return;
+}
+
+	void
+kerberos5_reply(ap, data, cnt)
+	Authenticator *ap;
+	unsigned char *data;
+	int cnt;
+{
+#ifdef ENCRYPTION
+        Session_Key skey;
+#endif
+	static int mutual_complete = 0;
+
+	if (cnt-- < 1)
+		return;
+	switch (*data++) {
+	case KRB_REJECT:
+		if (cnt > 0) {
+			printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
+				cnt, data);
+		} else
+			printf("[ Kerberos V5 refuses authentication ]\r\n");
+		auth_send_retry();
+		return;
+	case KRB_ACCEPT:
+		if (!mutual_complete) {
+		    if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+			printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
+			auth_send_retry();
+			return;
+		    }
+#ifdef	ENCRYPTION
+		    if (session_key) {
+			skey.type = SK_DES;
+			skey.length = 8;
+			skey.data = session_key->contents;
+			encrypt_session_key(&skey, 0);
+		    }
+#endif	/* ENCRYPTION */
+		}
+		if (cnt)
+		    printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
+		else
+		    printf("[ Kerberos V5 accepts you ]\r\n");
+		auth_finished(ap, AUTH_USER);
+#ifdef	FORWARD
+		if (forward_flags & OPTS_FORWARD_CREDS)
+		  kerberos5_forward(ap);
+#endif	/* FORWARD */
+		break;
+	case KRB_RESPONSE:
+		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+		    /* the rest of the reply should contain a krb_ap_rep */
+		    krb5_ap_rep_enc_part *reply;
+		    krb5_data inbuf;
+		    krb5_error_code r;
+
+		    inbuf.length = cnt;
+		    inbuf.data = (char *)data;
+
+		    if ((r = krb5_rd_rep(telnet_context, auth_context, &inbuf,
+					 &reply))) {
+			printf("[ Mutual authentication failed: %s ]\r\n",
+			       error_message(r));
+			auth_send_retry();
+			return;
+		    }
+		    krb5_free_ap_rep_enc_part(telnet_context, reply);
+#ifdef	ENCRYPTION
+		    if (session_key) {
+			skey.type = SK_DES;
+			skey.length = 8;
+			skey.data = session_key->contents;
+			encrypt_session_key(&skey, 0);
+		      }
+#endif	/* ENCRYPTION */
+		    mutual_complete = 1;
+		}
+		return;
+#ifdef	FORWARD
+	case KRB_FORWARD_ACCEPT:
+		printf("[ Kerberos V5 accepted forwarded credentials ]\r\n");
+		return;
+	case KRB_FORWARD_REJECT:
+		printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
+				cnt, data);
+		return;
+#endif	/* FORWARD */
+	default:
+		if (auth_debug_mode)
+			printf("Unknown Kerberos option %d\r\n", data[-1]);
+		return;
+	}
+	return;
+}
+
+	int
+kerberos5_status(ap, name, level)
+	Authenticator *ap;
+	char *name;
+	int level;
+{
+	if (level < AUTH_USER)
+		return(level);
+
+	/*
+	 * Always copy in UserNameRequested if the authentication
+	 * is valid, because the higher level routines need it.
+	 * the name buffer comes from telnetd/telnetd{-ktd}.c
+	 */
+	if (UserNameRequested) {
+		strncpy(name, UserNameRequested, 255);
+		name[255] = '\0';
+	}
+
+	if (UserNameRequested &&
+	    krb5_kuserok(telnet_context, ticket->enc_part2->client, 
+			 UserNameRequested))
+	{
+		return(AUTH_VALID);
+	} else
+		return(AUTH_USER);
+}
+
+#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
+#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+	void
+kerberos5_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt;
+	unsigned int buflen;
+{
+	char lbuf[32];
+	register int i;
+
+	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
+	buflen -= 1;
+
+	switch(data[3]) {
+	case KRB_REJECT:		/* Rejected (reason might follow) */
+		strncpy((char *)buf, " REJECT ", buflen);
+		goto common;
+
+	case KRB_ACCEPT:		/* Accepted (name might follow) */
+		strncpy((char *)buf, " ACCEPT ", buflen);
+	common:
+		BUMP(buf, buflen);
+		if (cnt <= 4)
+			break;
+		ADDC(buf, buflen, '"');
+		for (i = 4; i < cnt; i++)
+			ADDC(buf, buflen, data[i]);
+		ADDC(buf, buflen, '"');
+		ADDC(buf, buflen, '\0');
+		break;
+
+
+	case KRB_AUTH:			/* Authentication data follows */
+		strncpy((char *)buf, " AUTH", buflen);
+		goto common2;
+
+	case KRB_RESPONSE:
+		strncpy((char *)buf, " RESPONSE", buflen);
+		goto common2;
+
+#ifdef	FORWARD
+	case KRB_FORWARD:               /* Forwarded credentials follow */
+		strncpy((char *)buf, " FORWARD", buflen);
+		goto common2;
+
+	case KRB_FORWARD_ACCEPT:               /* Forwarded credentials accepted */
+		strncpy((char *)buf, " FORWARD_ACCEPT", buflen);
+		goto common2;
+
+	case KRB_FORWARD_REJECT:               /* Forwarded credentials rejected */
+					       /* (reason might follow) */
+		strncpy((char *)buf, " FORWARD_REJECT", buflen);
+		goto common2;
+#endif	/* FORWARD */
+
+	default:
+		sprintf(lbuf, " %d (unknown)", data[3]);
+		strncpy((char *)buf, lbuf, buflen);
+	common2:
+		BUMP(buf, buflen);
+		for (i = 4; i < cnt; i++) {
+			sprintf(lbuf, " %d", data[i]);
+			strncpy((char *)buf, lbuf, buflen);
+			BUMP(buf, buflen);
+		}
+		break;
+	}
+}
+
+#ifdef	FORWARD
+
+static void
+kerberos5_forward(ap)
+     Authenticator *ap;
+{
+    krb5_error_code r;
+    krb5_ccache ccache;
+    krb5_principal client = 0;
+    krb5_principal server = 0;
+    krb5_data forw_creds;
+
+    forw_creds.data = 0;
+
+    if ((r = krb5_cc_default(telnet_context, &ccache))) {
+	if (auth_debug_mode) 
+	    printf("Kerberos V5: could not get default ccache - %s\r\n",
+		   error_message(r));
+	return;
+    }
+
+    if ((r = krb5_cc_get_principal(telnet_context, ccache, &client))) {
+	if (auth_debug_mode) 
+	    printf("Kerberos V5: could not get default principal - %s\r\n",
+		   error_message(r));
+	goto cleanup;
+    }
+
+    if ((r = krb5_sname_to_principal(telnet_context, RemoteHostName, "host",
+				     KRB5_NT_SRV_HST, &server))) {
+	if (auth_debug_mode) 
+	    printf("Kerberos V5: could not make server principal - %s\r\n",
+		   error_message(r));
+	goto cleanup;
+    }
+
+    if ((r = krb5_auth_con_genaddrs(telnet_context, auth_context, net,
+			    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))) {
+	if (auth_debug_mode)
+	    printf("Kerberos V5: could not gen local full address - %s\r\n",
+		    error_message(r));
+	goto cleanup;
+    }
+
+    if ((r = krb5_fwd_tgt_creds(telnet_context, auth_context, 0, client,
+				server, ccache,
+				forward_flags & OPTS_FORWARDABLE_CREDS,
+				&forw_creds))) {
+	if (auth_debug_mode) 
+	    printf("Kerberos V5: error getting forwarded creds - %s\r\n",
+	  	   error_message(r));
+	goto cleanup;
+    }
+    
+    /* Send forwarded credentials */
+    if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) {
+	if (auth_debug_mode)
+	    printf("Not enough room for authentication data\r\n");
+    } else {
+	if (auth_debug_mode)
+	    printf("Forwarded local Kerberos V5 credentials to server\r\n");
+    }
+    
+cleanup:
+    if (client)
+	krb5_free_principal(telnet_context, client);
+    if (server)
+	krb5_free_principal(telnet_context, server);
+    if (forw_creds.data)
+	free(forw_creds.data);
+    krb5_cc_close(telnet_context, ccache);
+}
+#endif	/* FORWARD */
+
+#endif /* KRB5 */
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/key-proto.h b/krb5-1-6/src/appl/telnet/libtelnet/key-proto.h
new file mode 100644
index 000000000..0a19c97bc
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/key-proto.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)key-proto.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef	__KEY_PROTO__
+#define	__KEY_PROTO__
+
+int key_file_exists (void);
+void key_lookup (unsigned char *, Block);
+void key_stream_init (Block, Block, int);
+unsigned char key_stream (int, int);
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/krb5forw.h b/krb5-1-6/src/appl/telnet/libtelnet/krb5forw.h
new file mode 100644
index 000000000..1fb757ddf
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/krb5forw.h
@@ -0,0 +1,4 @@
+extern krb5_error_code 
+rd_and_store_for_creds(krb5_context, krb5_auth_context, krb5_data *, 
+		       krb5_ticket *);
+
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/mem.c b/krb5-1-6/src/appl/telnet/libtelnet/mem.c
new file mode 100644
index 000000000..5a2ced8d5
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/mem.c
@@ -0,0 +1,190 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on:
+   @(#)memcmp.c	8.1 (Berkeley) 6/4/93
+   @(#)memset.c	8.1 (Berkeley) 6/4/93
+   @(#)memcpy.c	8.1 (Berkeley) 6/4/93
+   @(#)memmove.c	8.1 (Berkeley) 6/4/93
+ */
+
+#ifndef	__STDC__
+#define	const
+#endif
+typedef int size_t;
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include <limits.h>
+
+/*
+ * Compare memory regions.
+ */
+int
+memcmp(s1, s2, n)
+	const void *s1, *s2;
+	size_t n;
+{
+	if (n != 0) {
+		register const unsigned char *p1 = s1, *p2 = s2;
+
+		do {
+			if (*p1++ != *p2++)
+				return (*--p1 - *--p2);
+		} while (--n != 0);
+	}
+	return (0);
+}
+
+/*
+ * Copy a block of memory.
+ */
+void *
+memcpy(dst, src, n)
+	void *dst;
+	const void *src;
+	size_t n;
+{
+	bcopy((const char *)src, (char *)dst, n);
+	return(dst);
+}
+
+/*
+ * Copy a block of memory, handling overlap.
+ */
+void *
+memmove(dst, src, length)
+	void *dst;
+	const void *src;
+	register size_t length;
+{
+	bcopy((const char *)src, (char *)dst, length);
+	return(dst);
+}
+
+#define	wsize	sizeof(u_int)
+#define	wmask	(wsize - 1)
+
+#ifdef BZERO
+#define	RETURN	return
+#define	VAL	0
+#define	WIDEVAL	0
+
+void
+memset(dst0, 0, length)
+	void *dst0;
+	register size_t length;
+#else
+#define	RETURN	return (dst0)
+#define	VAL	c0
+#define	WIDEVAL	c
+
+void *
+memset(dst0, c0, length)
+	void *dst0;
+	register int c0;
+	register size_t length;
+#endif
+{
+	register size_t t;
+	register u_int c;
+	register u_char *dst;
+
+	dst = dst0;
+	/*
+	 * If not enough words, just fill bytes.  A length >= 2 words
+	 * guarantees that at least one of them is `complete' after
+	 * any necessary alignment.  For instance:
+	 *
+	 *	|-----------|-----------|-----------|
+	 *	|00|01|02|03|04|05|06|07|08|09|0A|00|
+	 *	          ^---------------------^
+	 *		 dst		 dst+length-1
+	 *
+	 * but we use a minimum of 3 here since the overhead of the code
+	 * to do word writes is substantial.
+	 */ 
+	if (length < 3 * wsize) {
+		while (length != 0) {
+			*dst++ = VAL;
+			--length;
+		}
+		RETURN;
+	}
+
+#ifndef BZERO
+	if ((c = (u_char)c0) != 0) {	/* Fill the word. */
+#ifndef UINT_MAX
+		UINT_MAX must be defined, try 0xFFFFFFFF;
+#endif
+		c = (c << 8) | c;	/* u_int is 16 bits. */
+#if UINT_MAX > 0xffff
+		c = (c << 16) | c;	/* u_int is 32 bits. */
+#endif
+#if UINT_MAX > 0xffffffff
+		c = (c << 32) | c;	/* u_int is 64 bits. */
+#endif
+	}
+#endif
+	/* Align destination by filling in bytes. */
+	if ((t = (int)dst & wmask) != 0) {
+		t = wsize - t;
+		length -= t;
+		do {
+			*dst++ = VAL;
+		} while (--t != 0);
+	}
+
+	/* Fill words.  Length was >= 2*words so we know t >= 1 here. */
+	t = length / wsize;
+	do {
+		*(u_int *)dst = WIDEVAL;
+		dst += wsize;
+	} while (--t != 0);
+
+	/* Mop up trailing bytes, if any. */
+	t = length & wmask;
+	if (t != 0)
+		do {
+			*dst++ = VAL;
+		} while (--t != 0);
+	RETURN;
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/misc-proto.h b/krb5-1-6/src/appl/telnet/libtelnet/misc-proto.h
new file mode 100644
index 000000000..66e9dd7bf
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/misc-proto.h
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)misc-proto.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef	__MISC_PROTO__
+#define	__MISC_PROTO__
+
+void auth_encrypt_init (char *, char *, char *, int);
+void auth_encrypt_user (const char *);
+void auth_encrypt_connect (int);
+void printd (const unsigned char *, int);
+
+/*
+ * These functions are imported from the application
+ */
+int net_write (unsigned char *, int);
+void net_encrypt (void);
+int telnet_spin (void);
+char *telnet_getenv (char *);
+char *telnet_gets (char *, char *, int, int);
+
+
+#ifdef NEED_PARSETOS
+int parsetos(char *, char *);
+#endif
+
+#ifdef NEED_SETENV
+int setenv(const char *, const char *, int);
+#ifndef HAVE_UNSETENV
+void unsetenv(const char *);
+#endif
+#endif
+
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/misc.c b/krb5-1-6/src/appl/telnet/libtelnet/misc.c
new file mode 100644
index 000000000..86e14cb1b
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/misc.c
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)misc.c	8.1 (Berkeley) 6/4/93 */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "misc.h"
+#include "auth.h"
+#include "encrypt.h"
+
+char *RemoteHostName;
+char *LocalHostName;
+char *UserNameRequested = 0;
+int ConnectedCount = 0;
+
+	void
+auth_encrypt_init(local, remote, name, server)
+	char *local;
+	char *remote;
+	char *name;
+	int server;
+{
+	RemoteHostName = remote;
+	LocalHostName = local;
+#if	defined(AUTHENTICATION)
+	auth_init(name, server);
+#endif
+#ifdef	ENCRYPTION
+	encrypt_init(name, server);
+#endif	/* ENCRYPTION */
+	if (UserNameRequested) {
+		free(UserNameRequested);
+		UserNameRequested = 0;
+	}
+}
+
+	void
+auth_encrypt_user(name)
+	const char *name;
+{
+	extern char *strdup();
+
+	if (UserNameRequested)
+		free(UserNameRequested);
+	UserNameRequested = name ? strdup(name) : 0;
+}
+
+	void
+auth_encrypt_connect(cnt)
+	int cnt;
+{
+}
+
+	void
+printd(data, cnt)
+	const unsigned char *data;
+	int cnt;
+{
+	if (cnt > 16)
+		cnt = 16;
+	while (cnt-- > 0) {
+		printf(" %02x", *data);
+		++data;
+	}
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/misc.h b/krb5-1-6/src/appl/telnet/libtelnet/misc.h
new file mode 100644
index 000000000..8ae603836
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/misc.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)misc.h	8.1 (Berkeley) 6/4/93
+ */
+
+extern char *UserNameRequested;
+extern char *LocalHostName;
+extern char *RemoteHostName;
+extern int ConnectedCount;
+extern int ReservedPort;
+
+int isprefix (char *, char *);
+char **genget (char *, char **, int);
+int Ambiguous (void *);
+
+#include "misc-proto.h"
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/parsetos.c b/krb5-1-6/src/appl/telnet/libtelnet/parsetos.c
new file mode 100644
index 000000000..303d7c3e5
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/parsetos.c
@@ -0,0 +1,42 @@
+
+/*
+ * The routine parsetos() for UNICOS 6.0/6.1, as well as more traditional
+ * Unix systems.  This is part of UNICOS 7.0 and later.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <errno.h>
+#define NEED_PARSETOS
+#include "misc-proto.h"
+
+#define	MIN_TOS	0
+#define	MAX_TOS	255
+
+int
+parsetos(name, proto)
+char	*name;
+char	*proto;
+{
+#if 0
+	register char	*c;
+#endif
+	int		tos;
+
+#ifdef HAVE_GETTOSBYNAME
+	struct tosent	*tosp;
+
+	tosp = gettosbyname(name, proto);
+	if (tosp)
+		tos = tosp->t_tos;
+	else
+#endif
+		tos = (int)strtol(name, (char **)NULL, 0);
+
+	if (tos < MIN_TOS || tos > MAX_TOS) {
+		return (-1);
+	}
+	return (tos);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/setenv.c b/krb5-1-6/src/appl/telnet/libtelnet/setenv.c
new file mode 100644
index 000000000..941b816ca
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/setenv.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)setenv.c	8.1 (Berkeley) 6/4/93 */
+/* based on @(#)getenv.c	8.1 (Berkeley) 6/4/93 */
+
+#ifndef __STDC__
+#define const
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "misc-proto.h"
+
+static char *__findenv (const char *, int *); 
+
+/*
+ * setenv --
+ *	Set the value of the environmental variable "name" to be
+ *	"value".  If rewrite is set, replace any current value.
+ */
+#ifndef HAVE_SETENV
+int
+setenv(name, value, rewrite)
+	register const char *name;
+	register const char *value;
+	int rewrite;
+{
+	extern char **environ;
+	static int alloced;			/* if allocated space before */
+	register char *c;
+	const char *c2;
+	int l_value, offset;
+
+	if (*value == '=')			/* no `=' in value */
+		++value;
+	l_value = strlen(value);
+	if ((c = __findenv(name, &offset))) {	/* find if already exists */
+		if (!rewrite)
+			return (0);
+		if (strlen(c) >= l_value) {	/* old larger; copy over */
+			while ((*c++ = *value++));
+			return (0);
+		}
+	} else {					/* create new slot */
+		register int cnt;
+		register char **p;
+
+		for (p = environ, cnt = 0; *p; ++p, ++cnt);
+		if (alloced) {			/* just increase size */
+			environ = (char **)realloc((char *)environ,
+			    (size_t)(sizeof(char *) * (cnt + 2)));
+			if (!environ)
+				return (-1);
+		}
+		else {				/* get new space */
+			alloced = 1;		/* copy old entries into it */
+			p = (char **)malloc((size_t)(sizeof(char *) * (cnt + 2)));
+			if (!p)
+				return (-1);
+			memcpy(p, environ, cnt * sizeof(char *));
+			environ = p;
+		}
+		environ[cnt + 1] = NULL;
+		offset = cnt;
+	}
+	for (c2 = name; *c2 && *c2 != '='; ++c2);	/* no `=' in name */
+	if (!(environ[offset] =			/* name + `=' + value */
+	    malloc((size_t)((int)(c2 - name) + l_value + 2))))
+		return (-1);
+	for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
+	for (*c++ = '='; (*c++ = *value++););
+	return (0);
+}
+#endif
+
+/*
+ * unsetenv(name) --
+ *	Delete environmental variable "name".
+ */
+#ifndef HAVE_UNSETENV
+void
+unsetenv(name)
+	const char *name;
+{
+	extern char **environ;
+	register char **p;
+	int offset;
+
+	while (__findenv(name, &offset))	/* if set multiple times */
+		for (p = &environ[offset];; ++p)
+			if (!(*p = *(p + 1)))
+				break;
+}
+#endif
+
+/*
+ * getenv --
+ *	Returns ptr to value associated with name, if any, else NULL.
+ */
+#ifndef HAVE_GETENV
+char *
+getenv(name)
+	const char *name;
+{
+	int offset;
+
+	return (__findenv(name, &offset));
+}
+#endif
+
+/*
+ * __findenv --
+ *	Returns pointer to value associated with name, if any, else NULL.
+ *	Sets offset to be the offset of the name/value combination in the
+ *	environmental array, for use by setenv(3) and unsetenv(3).
+ *	Explicitly removes '=' in argument name.
+ */
+static char *
+__findenv(name, offset)
+	register const char *name;
+	int *offset;
+{
+	extern char **environ;
+	register unsigned int len;
+	register const char *np;
+	register char **p, *c;
+
+	if (name == NULL || environ == NULL)
+		return (NULL);
+	for (np = name; *np && *np != '='; ++np)
+		continue;
+	len = np - name;
+	for (p = environ; (c = *p) != NULL; ++p)
+		if (strncmp(c, name, len) == 0 && c[len] == '=') {
+			*offset = p - environ;
+			return (c + len + 1);
+		}
+	return (NULL);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/setsid.c b/krb5-1-6/src/appl/telnet/libtelnet/setsid.c
new file mode 100644
index 000000000..48c861c8c
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/setsid.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)setsid.c	8.1 (Berkeley) 6/4/93 */
+
+/*
+ * Emulate the functionality of setsid(), called when forking
+ * and execing the new process.
+ */
+
+extern char *line;
+setsid()
+{
+#ifndef	convex
+	if (setpgrp(0, 0) < 0)
+		return(-1);
+#endif
+	return(0);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/spx.c b/krb5-1-6/src/appl/telnet/libtelnet/spx.c
new file mode 100644
index 000000000..b3e0e9dfc
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/spx.c
@@ -0,0 +1,594 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)spx.c	8.1 (Berkeley) 6/4/93 */
+
+#ifdef	SPX
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1.  Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2.  This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility.  DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3.  Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4.  This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc.  It may cease to generate certificates after the expiration
+ * date.  Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5.  Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <sys/types.h>
+#include <arpa/telnet.h>
+#include <stdio.h>
+#include "gssapi_defs.h"
+#ifdef	__STDC__
+#include <stdlib.h>
+#endif
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include <pwd.h>
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+extern auth_debug_mode;
+
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+			  		AUTHTYPE_SPX, };
+static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
+					TELQUAL_NAME, };
+
+#define	SPX_AUTH	0		/* Authentication data follows */
+#define	SPX_REJECT	1		/* Rejected (reason might follow) */
+#define SPX_ACCEPT	2		/* Accepted */
+
+#ifdef	ENCRYPTION
+static Block	session_key	= { 0 };
+#endif	/* ENCRYPTION */
+static Schedule sched;
+static Block	challenge	= { 0 };
+
+
+/*******************************************************************/
+
+gss_OID_set           actual_mechs;
+gss_OID               actual_mech_type, output_name_type;
+int                   major_status, status, msg_ctx = 0, new_status;
+int                   req_flags = 0, ret_flags, lifetime_rec;
+gss_cred_id_t         gss_cred_handle;
+gss_ctx_id_t          actual_ctxhandle, context_handle;
+gss_buffer_desc       output_token, input_token, input_name_buffer;
+gss_buffer_desc       status_string;
+gss_name_t            desired_targname, src_name;
+gss_channel_bindings  input_chan_bindings;
+char                  lhostname[GSS_C_MAX_PRINTABLE_NAME];
+char                  targ_printable[GSS_C_MAX_PRINTABLE_NAME];
+int                   to_addr=0, from_addr=0;
+char                  *address;
+gss_buffer_desc       fullname_buffer;
+gss_OID               fullname_type;
+gss_cred_id_t         gss_delegated_cred_handle;
+
+/*******************************************************************/
+
+
+
+	static int
+Data(ap, type, d, c)
+	Authenticator *ap;
+	int type;
+	void *d;
+	int c;
+{
+        unsigned char *p = str_data + 4;
+	unsigned char *cd = (unsigned char *)d;
+
+	if (c == -1)
+		c = strlen((char *)cd);
+
+        if (0) {
+                printf("%s:%d: [%d] (%d)",
+                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
+                        str_data[3],
+                        type, c);
+                printd(d, c);
+                printf("\r\n");
+        }
+	*p++ = ap->type;
+	*p++ = ap->way;
+	*p++ = type;
+        while (c-- > 0) {
+                if ((*p++ = *cd++) == IAC)
+                        *p++ = IAC;
+        }
+        *p++ = IAC;
+        *p++ = SE;
+	if (str_data[3] == TELQUAL_IS)
+		printsub('>', &str_data[2], p - (&str_data[2]));
+        return(net_write(str_data, p - str_data));
+}
+
+	int
+spx_init(ap, server)
+	Authenticator *ap;
+	int server;
+{
+        gss_cred_id_t    tmp_cred_handle;
+
+	if (server) {
+		str_data[3] = TELQUAL_REPLY;
+		gethostname(lhostname, sizeof(lhostname));
+		strcpy(targ_printable, "SERVICE:rcmd@");
+		strncat(targ_printable, lhostname, sizeof(targ_printable) - 1 - 13);
+		targ_printable[sizeof(targ_printable) - 1] = '\0';
+		input_name_buffer.length = strlen(targ_printable);
+		input_name_buffer.value = targ_printable;
+		major_status = gss_import_name(&status,
+                                       &input_name_buffer,
+                                       GSS_C_NULL_OID,
+                                       &desired_targname);
+		major_status = gss_acquire_cred(&status,
+                                        desired_targname,
+                                        0,
+                                        GSS_C_NULL_OID_SET,
+                                        GSS_C_ACCEPT,
+                                        &tmp_cred_handle,
+                                        &actual_mechs,
+                                        &lifetime_rec);
+		if (major_status != GSS_S_COMPLETE) return(0);
+	} else {
+		str_data[3] = TELQUAL_IS;
+	}
+	return(1);
+}
+
+	int
+spx_send(ap)
+	Authenticator *ap;
+{
+	Block enckey;
+	int r;
+
+	gss_OID  actual_mech_type, output_name_type;
+	int           msg_ctx = 0, new_status, status;
+	int           req_flags = 0, ret_flags, lifetime_rec, major_status;
+	gss_buffer_desc  output_token, input_token, input_name_buffer;
+	gss_buffer_desc  output_name_buffer, status_string;
+	gss_name_t    desired_targname;
+	gss_channel_bindings  input_chan_bindings;
+	char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
+	int  from_addr=0, to_addr=0, myhostlen, j;
+	int  deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0;
+	char *address;
+
+	printf("[ Trying SPX ... ]\n");
+	strcpy(targ_printable, "SERVICE:rcmd@");
+	strncat(targ_printable, RemoteHostName, sizeof(targ_printable) - 1 - 13);
+	targ_printable[sizeof(targ_printable) - 1] = '\0';
+
+	input_name_buffer.length = strlen(targ_printable);
+	input_name_buffer.value = targ_printable;
+
+	if (!UserNameRequested) {
+		return(0);
+	}
+
+	major_status = gss_import_name(&status,
+				       &input_name_buffer,
+				       GSS_C_NULL_OID,
+				       &desired_targname);
+
+
+	major_status = gss_display_name(&status,
+					desired_targname,
+					&output_name_buffer,
+					&output_name_type);
+
+	printf("target is '%s'\n", output_name_buffer.value); fflush(stdout);
+
+	major_status = gss_release_buffer(&status, &output_name_buffer);
+
+	input_chan_bindings = (gss_channel_bindings)
+	  malloc(sizeof(gss_channel_bindings_desc));
+
+	input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
+	input_chan_bindings->initiator_address.length = 4;
+	address = (char *) malloc(4);
+	input_chan_bindings->initiator_address.value = (char *) address;
+	address[0] = ((from_addr & 0xff000000) >> 24);
+	address[1] = ((from_addr & 0xff0000) >> 16);
+	address[2] = ((from_addr & 0xff00) >> 8);
+	address[3] = (from_addr & 0xff);
+	input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
+	input_chan_bindings->acceptor_address.length = 4;
+	address = (char *) malloc(4);
+	input_chan_bindings->acceptor_address.value = (char *) address;
+	address[0] = ((to_addr & 0xff000000) >> 24);
+	address[1] = ((to_addr & 0xff0000) >> 16);
+	address[2] = ((to_addr & 0xff00) >> 8);
+	address[3] = (to_addr & 0xff);
+	input_chan_bindings->application_data.length = 0;
+
+        req_flags = 0;
+        if (deleg_flag)  req_flags = req_flags | 1;
+        if (mutual_flag) req_flags = req_flags | 2;
+        if (replay_flag) req_flags = req_flags | 4;
+        if (seq_flag)    req_flags = req_flags | 8;
+
+        major_status = gss_init_sec_context(&status,         /* minor status */
+					GSS_C_NO_CREDENTIAL, /* cred handle */
+                                        &actual_ctxhandle,   /* ctx handle */
+                                        desired_targname,    /* target name */
+                                        GSS_C_NULL_OID,      /* mech type */
+                                        req_flags,           /* req flags */
+                                        0,                   /* time req */
+                                        input_chan_bindings, /* chan binding */
+                                        GSS_C_NO_BUFFER,     /* input token */
+                                        &actual_mech_type,   /* actual mech */
+                                        &output_token,       /* output token */
+                                        &ret_flags,          /* ret flags */
+                                        &lifetime_rec);      /* time rec */
+
+	if ((major_status != GSS_S_COMPLETE) &&
+	    (major_status != GSS_S_CONTINUE_NEEDED)) {
+          gss_display_status(&new_status,
+                             status,
+                             GSS_C_MECH_CODE,
+                             GSS_C_NULL_OID,
+                             &msg_ctx,
+                             &status_string);
+          printf("%s\n", status_string.value);
+	  return(0);
+	}
+
+	if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+		return(0);
+	}
+
+	if (!Data(ap, SPX_AUTH, (void *)output_token.value, output_token.length)) {
+		return(0);
+	}
+
+	return(1);
+}
+
+	void
+spx_is(ap, data, cnt)
+	Authenticator *ap;
+	unsigned char *data;
+	int cnt;
+{
+	Session_Key skey;
+	Block datablock;
+	int r;
+
+	if (cnt-- < 1)
+		return;
+	switch (*data++) {
+	case SPX_AUTH:
+	        input_token.length = cnt;
+		input_token.value = (char *) data;
+
+		gethostname(lhostname, sizeof(lhostname));
+
+		strcpy(targ_printable, "SERVICE:rcmd@");
+		strncat(targ_printable, lhostname, sizeof(targ_printable) - 1 - 13);
+		targ_printable[sizeof(targ_printable) - 1] = '\0';
+
+		input_name_buffer.length = strlen(targ_printable);
+		input_name_buffer.value = targ_printable;
+
+		major_status = gss_import_name(&status,
+                                       &input_name_buffer,
+                                       GSS_C_NULL_OID,
+                                       &desired_targname);
+
+		major_status = gss_acquire_cred(&status,
+                                        desired_targname,
+                                        0,
+                                        GSS_C_NULL_OID_SET,
+                                        GSS_C_ACCEPT,
+                                        &gss_cred_handle,
+                                        &actual_mechs,
+                                        &lifetime_rec);
+
+		major_status = gss_release_name(&status, desired_targname);
+
+		input_chan_bindings = (gss_channel_bindings)
+		  malloc(sizeof(gss_channel_bindings_desc));
+
+		input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
+		input_chan_bindings->initiator_address.length = 4;
+		address = (char *) malloc(4);
+		input_chan_bindings->initiator_address.value = (char *) address;
+		address[0] = ((from_addr & 0xff000000) >> 24);
+		address[1] = ((from_addr & 0xff0000) >> 16);
+		address[2] = ((from_addr & 0xff00) >> 8);
+		address[3] = (from_addr & 0xff);
+		input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
+		input_chan_bindings->acceptor_address.length = 4;
+		address = (char *) malloc(4);
+		input_chan_bindings->acceptor_address.value = (char *) address;
+		address[0] = ((to_addr & 0xff000000) >> 24);
+		address[1] = ((to_addr & 0xff0000) >> 16);
+		address[2] = ((to_addr & 0xff00) >> 8);
+		address[3] = (to_addr & 0xff);
+		input_chan_bindings->application_data.length = 0;
+
+		major_status = gss_accept_sec_context(&status,
+					      &context_handle,
+                                              gss_cred_handle,
+                                              &input_token,
+                                              input_chan_bindings,
+                                              &src_name,
+                                              &actual_mech_type,
+                                              &output_token,
+                                              &ret_flags,
+                                              &lifetime_rec,
+                                              &gss_delegated_cred_handle);
+
+
+		if (major_status != GSS_S_COMPLETE) {
+
+		  major_status = gss_display_name(&status,
+					  src_name,
+                                          &fullname_buffer,
+                                          &fullname_type);
+			Data(ap, SPX_REJECT, (void *)"auth failed", -1);
+			auth_finished(ap, AUTH_REJECT);
+			return;
+		}
+
+		major_status = gss_display_name(&status,
+                                          src_name,
+                                          &fullname_buffer,
+                                          &fullname_type);
+
+
+		Data(ap, SPX_ACCEPT, (void *)output_token.value, output_token.length);
+		auth_finished(ap, AUTH_USER);
+		break;
+
+	default:
+		Data(ap, SPX_REJECT, 0, 0);
+		break;
+	}
+}
+
+
+	void
+spx_reply(ap, data, cnt)
+	Authenticator *ap;
+	unsigned char *data;
+	int cnt;
+{
+	Session_Key skey;
+
+	if (cnt-- < 1)
+		return;
+	switch (*data++) {
+	case SPX_REJECT:
+		if (cnt > 0) {
+			printf("[ SPX refuses authentication because %.*s ]\r\n",
+				cnt, data);
+		} else
+			printf("[ SPX refuses authentication ]\r\n");
+		auth_send_retry();
+		return;
+	case SPX_ACCEPT:
+		printf("[ SPX accepts you ]\n");
+		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+			/*
+			 * Send over the encrypted challenge.
+		 	 */
+		  input_token.value = (char *) data;
+		  input_token.length = cnt;
+
+		  major_status = gss_init_sec_context(&status, /* minor stat */
+                                        GSS_C_NO_CREDENTIAL, /* cred handle */
+                                        &actual_ctxhandle,   /* ctx handle */
+                                        desired_targname,    /* target name */
+                                        GSS_C_NULL_OID,      /* mech type */
+                                        req_flags,           /* req flags */
+                                        0,                   /* time req */
+                                        input_chan_bindings, /* chan binding */
+                                        &input_token,        /* input token */
+                                        &actual_mech_type,   /* actual mech */
+                                        &output_token,       /* output token */
+                                        &ret_flags,          /* ret flags */
+                                        &lifetime_rec);      /* time rec */
+
+		  if (major_status != GSS_S_COMPLETE) {
+		    gss_display_status(&new_status,
+				       status,
+				       GSS_C_MECH_CODE,
+				       GSS_C_NULL_OID,
+				       &msg_ctx,
+				       &status_string);
+		    printf("[ SPX mutual response fails ... '%s' ]\r\n",
+			 status_string.value);
+		    auth_send_retry();
+		    return;
+		  }
+		}
+		auth_finished(ap, AUTH_USER);
+		return;
+
+	default:
+		return;
+	}
+}
+
+	int
+spx_status(ap, name, level)
+	Authenticator *ap;
+	char *name;
+	int level;
+{
+
+	gss_buffer_desc  fullname_buffer, acl_file_buffer;
+	gss_OID          fullname_type;
+        char acl_file[MAXPATHLEN], fullname[160];
+        int major_status, status = 0;
+	struct passwd  *pwd;
+
+        /*
+         * hard code fullname to
+         *   "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan"
+         * and acl_file to "~kannan/.sphinx"
+         */
+
+	pwd = getpwnam(UserNameRequested);
+	if (pwd == NULL) {
+          return(AUTH_USER);   /*  not authenticated  */
+        }
+
+	acl_file[sizeof(acl_file) - 1] = '\0';
+	strncpy(acl_file, pwd->pw_dir, sizeof(acl_file) - 1);
+	strncat(acl_file, "/.sphinx", sizeof(acl_file) - 1 - strlen(acl_file));
+        acl_file_buffer.value = acl_file;
+        acl_file_buffer.length = strlen(acl_file);
+
+	major_status = gss_display_name(&status,
+					src_name,
+					&fullname_buffer,
+					&fullname_type);
+
+	if (level < AUTH_USER)
+		return(level);
+
+        major_status = gss__check_acl(&status, &fullname_buffer,
+                                      &acl_file_buffer);
+
+        if (major_status == GSS_S_COMPLETE) {
+          /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+	  strncpy(name, UserNameRequested, 255);
+	  name[255] = '\0';
+	  return(AUTH_VALID);
+        } else {
+           return(AUTH_USER);
+        }
+
+}
+
+#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
+#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+	void
+spx_printsub(data, cnt, buf, buflen)
+	unsigned char *data, *buf;
+	int cnt;
+	unsigned int buflen;
+{
+	char lbuf[32];
+	register int i;
+
+	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
+	buflen -= 1;
+
+	switch(data[3]) {
+	case SPX_REJECT:		/* Rejected (reason might follow) */
+		strncpy((char *)buf, " REJECT ", buflen);
+		goto common;
+
+	case SPX_ACCEPT:		/* Accepted (name might follow) */
+		strncpy((char *)buf, " ACCEPT ", buflen);
+	common:
+		BUMP(buf, buflen);
+		if (cnt <= 4)
+			break;
+		ADDC(buf, buflen, '"');
+		for (i = 4; i < cnt; i++)
+			ADDC(buf, buflen, data[i]);
+		ADDC(buf, buflen, '"');
+		ADDC(buf, buflen, '\0');
+		break;
+
+	case SPX_AUTH:			/* Authentication data follows */
+		strncpy((char *)buf, " AUTH", buflen);
+		goto common2;
+
+	default:
+		sprintf(lbuf, " %d (unknown)", data[3]);
+		strncpy((char *)buf, lbuf, buflen);
+	common2:
+		BUMP(buf, buflen);
+		for (i = 4; i < cnt; i++) {
+			sprintf(lbuf, " %d", data[i]);
+			strncpy((char *)buf, lbuf, buflen);
+			BUMP(buf, buflen);
+		}
+		break;
+	}
+}
+#else
+#include "misc-proto.h"
+#endif
+
+#ifdef notdef
+
+prkey(msg, key)
+	char *msg;
+	unsigned char *key;
+{
+	register int i;
+	printf("%s:", msg);
+	for (i = 0; i < 8; i++)
+		printf(" %3d", key[i]);
+	printf("\r\n");
+}
+#endif
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/strcasecmp.c b/krb5-1-6/src/appl/telnet/libtelnet/strcasecmp.c
new file mode 100644
index 000000000..edd9f1415
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/strcasecmp.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __STDC__
+#define const
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/* based on @(#)strcasecmp.c	8.1 (Berkeley) 6/4/93 */
+
+typedef unsigned char u_char;
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static const u_char charmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+	'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+	'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+	'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+int
+strcasecmp(s1, s2)
+	const char *s1, *s2;
+{
+	register const u_char *cm = charmap,
+			*us1 = (const u_char *)s1,
+			*us2 = (const u_char *)s2;
+
+	while (cm[*us1] == cm[*us2++])
+		if (*us1++ == '\0')
+			return (0);
+	return (cm[*us1] - cm[*--us2]);
+}
+
+int
+strncasecmp(s1, s2, n)
+	const char *s1, *s2;
+	register size_t n;
+{
+	if (n != 0) {
+		register const u_char *cm = charmap,
+				*us1 = (const u_char *)s1,
+				*us2 = (const u_char *)s2;
+
+		do {
+			if (cm[*us1] != cm[*us2++])
+				return (cm[*us1] - cm[*--us2]);
+			if (*us1++ == '\0')
+				break;
+		} while (--n != 0);
+	}
+	return (0);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/strchr.c b/krb5-1-6/src/appl/telnet/libtelnet/strchr.c
new file mode 100644
index 000000000..91f5612fa
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/strchr.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)strchr.c	8.1 (Berkeley) 6/4/93 */
+
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+char *
+strchr(p, ch)
+	char *p, ch;
+{
+	return(index(p, ch));
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/strdup.c b/krb5-1-6/src/appl/telnet/libtelnet/strdup.c
new file mode 100644
index 000000000..d501ed992
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/strdup.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)strdup.c	8.1 (Berkeley) 6/4/93 */
+
+#ifndef __STDC__
+#define const
+#endif
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+char *
+strdup(str)
+	const char *str;
+{
+	size_t len;
+	char *copy;
+
+	len = strlen(str) + 1;
+	if (!(copy = malloc((u_int)len)))
+		return (NULL);
+	memcpy(copy, str, len);
+	return (copy);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/strerror.c b/krb5-1-6/src/appl/telnet/libtelnet/strerror.c
new file mode 100644
index 000000000..8bed9c670
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/strerror.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)strerror.c	8.1 (Berkeley) 6/4/93 */
+
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+char *
+strerror(num)
+	int num;
+{
+	extern int sys_nerr;
+	extern char *sys_errlist[];
+#define	UPREFIX	"Unknown error: "
+	static char ebuf[40] = UPREFIX;		/* 64-bit number + slop */
+	register unsigned int errnum;
+	register char *p, *t;
+	char tmp[40];
+
+	errnum = num;				/* convert to unsigned */
+	if (errnum < sys_nerr)
+		return(sys_errlist[errnum]);
+
+	/* Do this by hand, so we don't include stdio(3). */
+	t = tmp;
+	do {
+		*t++ = "0123456789"[errnum % 10];
+	} while (errnum /= 10);
+	for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+		*p++ = *--t;
+		if (t <= tmp)
+			break;
+	}
+	return(ebuf);
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/strftime.c b/krb5-1-6/src/appl/telnet/libtelnet/strftime.c
new file mode 100644
index 000000000..f2bcc676c
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/strftime.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)strftime.c	8.1 (Berkeley) 6/4/93 */
+
+#ifndef __STDC__
+#define const
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef notdef
+#include <tzfile.h>
+#else
+#define TM_YEAR_BASE	1900	/* from <tzfile.h> */
+#endif
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+static char *afmt[] = {
+	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+};
+static char *Afmt[] = {
+	"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+	"Saturday",
+};
+static char *bfmt[] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+	"Oct", "Nov", "Dec",
+};
+static char *Bfmt[] = {
+	"January", "February", "March", "April", "May", "June", "July",
+	"August", "September", "October", "November", "December",
+};
+
+static size_t gsize;
+static char *pt;
+#ifndef	__P
+#define	__P(x)	()
+#endif
+static int _add __P((char *));
+static int _conv __P((int, int, int));
+static int _secs __P((const struct tm *));
+static size_t _fmt __P((const char *, const struct tm *));
+
+size_t
+strftime(s, maxsize, format, t)
+	char *s;
+	size_t maxsize;
+	const char *format;
+	const struct tm *t;
+{
+
+	pt = s;
+	if ((gsize = maxsize) < 1)
+		return(0);
+	if (_fmt(format, t)) {
+		*pt = '\0';
+		return(maxsize - gsize);
+	}
+	return(0);
+}
+
+static size_t
+_fmt(format, t)
+	register const char *format;
+	const struct tm *t;
+{
+	for (; *format; ++format) {
+		if (*format == '%')
+			switch(*++format) {
+			case '\0':
+				--format;
+				break;
+			case 'A':
+				if (t->tm_wday < 0 || t->tm_wday > 6)
+					return(0);
+				if (!_add(Afmt[t->tm_wday]))
+					return(0);
+				continue;
+			case 'a':
+				if (t->tm_wday < 0 || t->tm_wday > 6)
+					return(0);
+				if (!_add(afmt[t->tm_wday]))
+					return(0);
+				continue;
+			case 'B':
+				if (t->tm_mon < 0 || t->tm_mon > 11)
+					return(0);
+				if (!_add(Bfmt[t->tm_mon]))
+					return(0);
+				continue;
+			case 'b':
+			case 'h':
+				if (t->tm_mon < 0 || t->tm_mon > 11)
+					return(0);
+				if (!_add(bfmt[t->tm_mon]))
+					return(0);
+				continue;
+			case 'C':
+				if (!_fmt("%a %b %e %H:%M:%S %Y", t))
+					return(0);
+				continue;
+			case 'c':
+				if (!_fmt("%m/%d/%y %H:%M:%S", t))
+					return(0);
+				continue;
+			case 'D':
+				if (!_fmt("%m/%d/%y", t))
+					return(0);
+				continue;
+			case 'd':
+				if (!_conv(t->tm_mday, 2, '0'))
+					return(0);
+				continue;
+			case 'e':
+				if (!_conv(t->tm_mday, 2, ' '))
+					return(0);
+				continue;
+			case 'H':
+				if (!_conv(t->tm_hour, 2, '0'))
+					return(0);
+				continue;
+			case 'I':
+				if (!_conv(t->tm_hour % 12 ?
+				    t->tm_hour % 12 : 12, 2, '0'))
+					return(0);
+				continue;
+			case 'j':
+				if (!_conv(t->tm_yday + 1, 3, '0'))
+					return(0);
+				continue;
+			case 'k':
+				if (!_conv(t->tm_hour, 2, ' '))
+					return(0);
+				continue;
+			case 'l':
+				if (!_conv(t->tm_hour % 12 ?
+				    t->tm_hour % 12 : 12, 2, ' '))
+					return(0);
+				continue;
+			case 'M':
+				if (!_conv(t->tm_min, 2, '0'))
+					return(0);
+				continue;
+			case 'm':
+				if (!_conv(t->tm_mon + 1, 2, '0'))
+					return(0);
+				continue;
+			case 'n':
+				if (!_add("\n"))
+					return(0);
+				continue;
+			case 'p':
+				if (!_add(t->tm_hour >= 12 ? "PM" : "AM"))
+					return(0);
+				continue;
+			case 'R':
+				if (!_fmt("%H:%M", t))
+					return(0);
+				continue;
+			case 'r':
+				if (!_fmt("%I:%M:%S %p", t))
+					return(0);
+				continue;
+			case 'S':
+				if (!_conv(t->tm_sec, 2, '0'))
+					return(0);
+				continue;
+			case 's':
+				if (!_secs(t))
+					return(0);
+				continue;
+			case 'T':
+			case 'X':
+				if (!_fmt("%H:%M:%S", t))
+					return(0);
+				continue;
+			case 't':
+				if (!_add("\t"))
+					return(0);
+				continue;
+			case 'U':
+				if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7,
+				    2, '0'))
+					return(0);
+				continue;
+			case 'W':
+				if (!_conv((t->tm_yday + 7 -
+				    (t->tm_wday ? (t->tm_wday - 1) : 6))
+				    / 7, 2, '0'))
+					return(0);
+				continue;
+			case 'w':
+				if (!_conv(t->tm_wday, 1, '0'))
+					return(0);
+				continue;
+			case 'x':
+				if (!_fmt("%m/%d/%y", t))
+					return(0);
+				continue;
+			case 'y':
+				if (!_conv((t->tm_year + TM_YEAR_BASE)
+				    % 100, 2, '0'))
+					return(0);
+				continue;
+			case 'Y':
+				if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0'))
+					return(0);
+				continue;
+#ifdef notdef
+			case 'Z':
+				if (!t->tm_zone || !_add(t->tm_zone))
+					return(0);
+				continue;
+#endif
+			case '%':
+			/*
+			 * X311J/88-090 (4.12.3.5): if conversion char is
+			 * undefined, behavior is undefined.  Print out the
+			 * character itself as printf(3) does.
+			 */
+			default:
+				break;
+		}
+		if (!gsize--)
+			return(0);
+		*pt++ = *format;
+	}
+	return(gsize);
+}
+
+static int
+_secs(t)
+	const struct tm *t;
+{
+	static char buf[15];
+	register time_t s;
+	register char *p;
+	struct tm tmp;
+
+	/* Make a copy, mktime(3) modifies the tm struct. */
+	tmp = *t;
+	s = mktime(&tmp);
+	for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
+		*p-- = s % 10 + '0';
+	return(_add(++p));
+}
+
+static int
+_conv(n, digits, pad)
+	int n, digits, pad;
+{
+	static char buf[10];
+	register char *p;
+
+	for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
+		*p-- = n % 10 + '0';
+	while (p > buf && digits-- > 0)
+		*p-- = pad;
+	return(_add(++p));
+}
+
+static int
+_add(str)
+	register char *str;
+{
+	for (;; ++pt, --gsize) {
+		if (!gsize)
+			return(0);
+		if (!(*pt = *str++))
+			return(1);
+	}
+}
diff --git a/krb5-1-6/src/appl/telnet/libtelnet/strrchr.c b/krb5-1-6/src/appl/telnet/libtelnet/strrchr.c
new file mode 100644
index 000000000..f65a7e805
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/libtelnet/strrchr.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)strrchr.c	8.1 (Berkeley) 6/4/93 */
+
+#ifdef	HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+char *
+strrchr(p, ch)
+	char *p, ch;
+{
+	return(rindex(p, ch));
+}
diff --git a/krb5-1-6/src/appl/telnet/stty.diff b/krb5-1-6/src/appl/telnet/stty.diff
new file mode 100644
index 000000000..3c1b02acc
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/stty.diff
@@ -0,0 +1,72 @@
+*** stty.c.old	Tue May 23 13:54:29 1989
+--- stty.c	Wed Aug 23 13:42:32 1989
+***************
+*** 20,25 ****
+--- 20,28 ----
+  
+  #include <stdio.h>
+  #include <sys/ioctl.h>
++ #include <sys/types.h>
++ #define	NO_T_CHARS_DEFINES
++ #include <sys/tty.h>
+  
+  struct
+  {
+***************
+*** 145,150 ****
+--- 148,156 ----
+  struct winsize win;
+  int	lmode;
+  int	oldisc, ldisc;
++ #ifdef	TIOCGSTATE
++ int	extproc;
++ #endif
+  
+  struct	special {
+  	char	*name;
+***************
+*** 188,193 ****
+--- 194,203 ----
+  	ioctl(1, TIOCLGET, &lmode);
+  	ioctl(1, TIOCGLTC, <c);
+  	ioctl(1, TIOCGWINSZ, &win);
++ #ifdef	TIOCGSTATE
++ 	ioctl(1, TIOCGSTATE, &extproc);
++ 	extproc &= TS_EXTPROC;
++ #endif
+  	if(argc == 1) {
+  		prmodes(0);
+  		exit(0);
+***************
+*** 292,297 ****
+--- 302,316 ----
+  			printf("%d %d\n", win.ws_row, win.ws_col);
+  			exit(0);
+  		}
++ #if	defined(TIOCEXT)
++ 		if (eq("extproc") || eq("-extproc")) {
++ 			if (**argv == '-')
++ 				extproc = 0;
++ 			else
++ 				extproc = 1;
++ 			ioctl(1, TIOCEXT, &extproc);
++ 		}
++ #endif
+  		for(i=0; speeds[i].string; i++)
+  			if(eq(speeds[i].string)) {
+  				mode.sg_ispeed = mode.sg_ospeed = speeds[i].speed;
+***************
+*** 438,443 ****
+--- 457,468 ----
+  		lpit(LPENDIN, "-pendin ");
+  		lpit(LDECCTQ, "-decctlq ");
+  		lpit(LNOFLSH, "-noflsh ");
++ #ifdef	TIOCGSTATE
++ 		if (all==2||extproc) {
++ 			fprintf(stderr,"-extproc"+(extproc!=0));
++ 			any++;
++ 		}
++ #endif
+  		if (any || nothing)
+  			fprintf(stderr,"\n");
+  	} else if (!all)
diff --git a/krb5-1-6/src/appl/telnet/telnet.state b/krb5-1-6/src/appl/telnet/telnet.state
new file mode 100644
index 000000000..1927a2b4b
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet.state
@@ -0,0 +1,80 @@
+
+   Three pieces of state need to be kept for each side of each option.
+   (You need the localside, sending WILL/WONT & receiving DO/DONT, and
+   the remoteside, sending DO/DONT and receiving WILL/WONT)
+
+	MY_STATE:	What state am I in?
+	WANT_STATE:	What state do I want?
+	WANT_RESP:	How many requests have I initiated?
+
+   Default values:
+	MY_STATE = WANT_STATE = DONT
+	WANT_RESP = 0
+
+   The local setup will change based on the state of the Telnet
+   variables.  When we are the originator, we can either make the
+   local setup changes at option request time (in which case if
+   the option is denied we need to change things back) or when
+   the option is acknowledged.
+
+   To initiate a switch to NEW_STATE:
+
+	if ((WANT_RESP == 0 && NEW_STATE == MY_STATE) ||
+			WANT_STATE == NEW_STATE) {
+	    do nothing;
+	} else {
+	    /*
+	     * This is where the logic goes to change the local setup
+	     * if we are doing so at request initiation
+	     */
+	    WANT_STATE = NEW_STATE;
+	    send NEW_STATE;
+	    WANT_RESP += 1;
+	}
+
+   When receiving NEW_STATE:
+
+	if (WANT_RESP) {
+	    --WANT_RESP;
+	    if (WANT_RESP && (NEW_STATE == MY_STATE))
+		--WANT_RESP;
+	}
+	if (WANT_RESP == 0) {
+	    if (NEW_STATE != WANT_STATE) {
+		/*
+		 * This is where the logic goes to decide if it is ok
+		 * to switch to NEW_STATE, and if so, do any necessary
+		 * local setup changes.
+		 */
+		if (ok_to_switch_to NEW_STATE)
+		    WANT_STATE = NEW_STATE;
+		else
+		    WANT_RESP++;
+*		if (MY_STATE != WANT_STATE)
+		    reply with WANT_STATE;
+	    } else {
+		/*
+		 * This is where the logic goes to change the local setup
+		 * if we are doing so at request acknowledgment
+		 */
+	    }
+	}
+	MY_STATE = NEW_STATE;
+
+* This if() line is not needed, it should be ok to always do the
+  "reply with WANT_STATE".  With the if() line, asking to turn on
+  an option that the other side doesn't understand is:
+		Send DO option
+		Recv WONT option
+  Without the if() line, it is:
+		Send DO option
+		Recv WONT option
+		Send DONT option
+  If the other side does not expect to receive the latter case,
+  but generates the latter case, then there is a potential for
+  option negotiation loops.  An implementation that does not expect
+  to get the second case should not generate it, an implementation
+  that does expect to get it may or may not generate it, and things
+  will still work.  Being conservative in what we send, we have the
+  if() statement in, but we expect the other side to generate the
+  last response.
diff --git a/krb5-1-6/src/appl/telnet/telnet/Makefile.in b/krb5-1-6/src/appl/telnet/telnet/Makefile.in
new file mode 100644
index 000000000..42a057899
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/Makefile.in
@@ -0,0 +1,112 @@
+thisconfigdir=..
+myfulldir=appl/telnet/telnet
+mydir=telnet
+BUILDTOP=$(REL)..$(S)..$(S)..
+# derived from the original Makefile.generic
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted provided
+# that: (1) source distributions retain this entire copyright notice and
+# comment, and (2) distributions including binaries display the following
+# acknowledgement:  ``This product includes software developed by the
+# University of California, Berkeley and its contributors'' in the
+# documentation or other materials provided with the distribution and in
+# all advertising materials mentioning features or use of this software.
+# Neither the name of the University nor the names of its contributors may
+# be used to endorse or promote products derived from this software without
+# specific prior written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+#	@(#)Makefile.generic	5.5 (Berkeley) 3/1/91
+#
+
+AUTH_DEF=-DAUTHENTICATION -DENCRYPTION -DKRB5 -DFORWARD -UNO_LOGIN_F -DLOGIN_CAP_F -DLOGIN_PROGRAM=KRB5_PATH_LOGIN
+OTHERDEFS=-DLINEMODE -DKLUDGELINEMODE -DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON
+LOCALINCLUDES=-I.. -I$(srcdir)/..
+DEFINES = -DTELNET_BUFSIZE=65535 $(AUTH_DEF) $(OTHERDEFS)
+ARPA_TELNET= $(srcdir)/../arpa/telnet.h
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+LIBS=	@TELNET_LIBS@
+
+SRCS=	$(srcdir)/authenc.c $(srcdir)/commands.c $(srcdir)/main.c $(srcdir)/network.c $(srcdir)/ring.c \
+	$(srcdir)/sys_bsd.c $(srcdir)/telnet.c $(srcdir)/terminal.c \
+	$(srcdir)/utilities.c $(GETOPT_SRC)
+ALLHC=	$(SRCS) \
+	defines.h externs.h fdset.h general.h \
+	ring.h types.h
+
+OBJS=	authenc.o commands.o main.o network.o ring.o sys_bsd.o \
+	telnet.o terminal.o utilities.o $(GETOPT_OBJ)
+
+all:: telnet
+
+telnet:	$(OBJS) $(KRB4COMPAT_DEPLIBS) ../libtelnet/libtelnet.a
+	$(CC_LINK) -o $@ $(OBJS) ../libtelnet/libtelnet.a $(KRB4COMPAT_LIBS)
+
+clean::
+	$(RM) telnet
+
+install::
+	for f in telnet; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.1 \
+		${DESTDIR}$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
+	$(INSTALL_DATA) $(srcdir)/tmac.doc ${DESTDIR}$(CLIENT_MANDIR)/tmac.doc
+
+authenc.o: defines.h externs.h general.h ring.h types.h $(ARPA_TELNET)
+commands.o: defines.h externs.h general.h ring.h types.h $(ARPA_TELNET)
+main.o: defines.h externs.h ring.h
+network.o: defines.h externs.h fdset.h ring.h $(ARPA_TELNET)
+ring.o: general.h ring.h
+sys_bsd.o: defines.h externs.h fdset.h ring.h types.h $(ARPA_TELNET)
+telnet.o: defines.h externs.h general.h ring.h types.h $(ARPA_TELNET)
+terminal.o: externs.h ring.h types.h $(ARPA_TELNET)
+tn3270.o: defines.h externs.h fdset.h general.h ring.h $(ARPA_TELNET)
+utilities.o: defines.h externs.h fdset.h general.h ring.h $(ARPA_TELNET)
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)authenc.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  $(srcdir)/../libtelnet/misc-proto.h $(srcdir)/../libtelnet/misc.h \
+  authenc.c defines.h externs.h general.h ring.h types.h
+$(OUTPRE)commands.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/auth-proto.h $(srcdir)/../libtelnet/auth.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  $(srcdir)/../libtelnet/misc-proto.h commands.c defines.h \
+  externs.h general.h ring.h types.h
+$(OUTPRE)main.$(OBJEXT): $(srcdir)/../libtelnet/auth-proto.h \
+  $(srcdir)/../libtelnet/auth.h $(srcdir)/../libtelnet/enc-proto.h \
+  $(srcdir)/../libtelnet/encrypt.h defines.h externs.h \
+  main.c ring.h
+$(OUTPRE)network.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  defines.h externs.h fdset.h network.c ring.h
+$(OUTPRE)ring.$(OBJEXT): general.h ring.c ring.h
+$(OUTPRE)sys_bsd.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  defines.h externs.h fdset.h ring.h sys_bsd.c types.h
+$(OUTPRE)telnet.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/auth-proto.h $(srcdir)/../libtelnet/auth.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  $(srcdir)/../libtelnet/misc-proto.h defines.h externs.h \
+  general.h ring.h telnet.c types.h
+$(OUTPRE)terminal.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  externs.h ring.h terminal.c types.h
+$(OUTPRE)utilities.$(OBJEXT): $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/auth-proto.h $(srcdir)/../libtelnet/auth.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  defines.h externs.h fdset.h general.h ring.h utilities.c
diff --git a/krb5-1-6/src/appl/telnet/telnet/authenc.c b/krb5-1-6/src/appl/telnet/telnet/authenc.c
new file mode 100644
index 000000000..aa4459f27
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/authenc.c
@@ -0,0 +1,115 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)authenc.c	8.1 (Berkeley) 6/6/93 */
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+#include <sys/types.h>
+#include <arpa/telnet.h>
+#include <libtelnet/encrypt.h>
+#include <libtelnet/misc.h>
+
+#include "general.h"
+#include "ring.h"
+#include "externs.h"
+#include "defines.h"
+#include "types.h"
+
+	int
+net_write(str, len)
+	unsigned char *str;
+	int len;
+{
+	if (NETROOM() > len) {
+		ring_supply_data(&netoring, str, len);
+		if (str[0] == IAC && str[1] == SE)
+			printsub('>', &str[2], len-2);
+		return(len);
+	}
+	return(0);
+}
+
+	void
+net_encrypt()
+{
+#ifdef	ENCRYPTION
+	if (encrypt_output)
+		ring_encrypt(&netoring, encrypt_output);
+	else
+		ring_clearto(&netoring);
+#endif	/* ENCRYPTION */
+}
+
+	int
+telnet_spin()
+{
+    extern int scheduler_lockout_tty;
+
+    scheduler_lockout_tty = 1;
+    Scheduler(0);
+    scheduler_lockout_tty = 0;
+    
+    return 0;
+}
+
+	char *
+telnet_getenv(val)
+	char *val;
+{
+	return((char *)env_getvalue((unsigned char *)val));
+}
+
+	char *
+telnet_gets(tprompt, result, length, echo)
+	char *tprompt;
+	char *result;
+	int length;
+	int echo;
+{
+	extern char *getpass();
+	extern int globalmode;
+	int om = globalmode;
+	char *res;
+
+	TerminalNewMode(-1);
+	if (echo) {
+		printf("%s", tprompt);
+		res = fgets(result, length, stdin);
+	} else if ((res = getpass(tprompt))) {
+		strncpy(result, res, (unsigned) length);
+		res = result;
+	}
+	TerminalNewMode(om);
+	return(res);
+}
+#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
diff --git a/krb5-1-6/src/appl/telnet/telnet/commands.c b/krb5-1-6/src/appl/telnet/telnet/commands.c
new file mode 100644
index 000000000..f6c0fcdb4
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/commands.c
@@ -0,0 +1,3191 @@
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)commands.c	8.1 (Berkeley) 6/6/93 */
+
+#if	defined(unix)
+#include <sys/param.h>
+#if	defined(CRAY) || defined(sysV88)
+#include <sys/types.h>
+#endif
+#include <sys/file.h>
+#else
+#include <sys/types.h>
+#endif	/* defined(unix) */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif /* HAVE_ARPA_INET_H */
+#ifdef	CRAY
+#include <fcntl.h>
+#endif	/* CRAY */
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <signal.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <pwd.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+
+#include <arpa/telnet.h>
+
+#include "general.h"
+
+#include "ring.h"
+
+#include "externs.h"
+#include "defines.h"
+#include "types.h"
+
+#if defined(AUTHENTICATION) || defined(FORWARD)
+#include <libtelnet/auth.h>
+#endif
+
+#ifdef	ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+#include <libtelnet/misc-proto.h>
+#endif
+
+#if !defined(CRAY) && !defined(sysV88)
+#include <netinet/in_systm.h>
+# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
+# include <machine/endian.h>
+# endif /* vax */
+#endif /* !defined(CRAY) && !defined(sysV88) */
+#include <netinet/ip.h>
+
+
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#include <netdb.h>
+
+#ifndef MAXDNAME
+#define MAXDNAME 256 /*per the rfc*/
+#endif
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#if	defined(IPPROTO_IP) && defined(IP_TOS)
+int tos = -1;
+static	unsigned long sourceroute(char *, char **, int *);
+#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+#include "fake-addrinfo.h"
+
+char	*hostname;
+static char _hostname[MAXDNAME];
+static char hostaddrstring[NI_MAXHOST];
+
+extern char *getenv();
+
+extern int isprefix();
+extern char **genget();
+extern int Ambiguous();
+
+typedef int (*intrtn_t)();
+static int call (intrtn_t, ...);
+void cmdrc (char *, char *);
+static    int
+send_tncmd (void (*func)(), char *, char *);
+static int help(int, char **);
+
+#ifdef NEED_HERROR_PROTO
+extern void herror(const char *);
+#endif
+
+typedef struct {
+	char	*name;		/* command name */
+	char	*help;		/* help string (NULL for no help) */
+	int	(*handler)	/* routine which executes command */
+                        (int, char *[]);
+	int	needconnect;	/* Do we need to be connected to execute? */
+} Command;
+
+static char line[256];
+static char saveline[256];
+static int margc;
+static char *margv[20];
+
+    static void
+makeargv()
+{
+    register char *cp, *cp2, c;
+    register char **argp = margv;
+
+    margc = 0;
+    cp = line;
+    if (*cp == '!') {		/* Special case shell escape */
+	strncpy(saveline, line, sizeof(saveline) - 1);
+				/* save for shell command */
+	saveline[sizeof(saveline)  - 1] = '\0';
+	*argp++ = "!";		/* No room in string to get this */
+	margc++;
+	cp++;
+    }
+    while ((c = *cp)) {
+	register int inquote = 0;
+	while (isspace((int) c))
+	    c = *++cp;
+	if (c == '\0')
+	    break;
+	*argp++ = cp;
+	margc += 1;
+	for (cp2 = cp; c != '\0'; c = *++cp) {
+	    if (inquote) {
+		if (c == inquote) {
+		    inquote = 0;
+		    continue;
+		}
+	    } else {
+		if (c == '\\') {
+		    if ((c = *++cp) == '\0')
+			break;
+		} else if (c == '"') {
+		    inquote = '"';
+		    continue;
+		} else if (c == '\'') {
+		    inquote = '\'';
+		    continue;
+		} else if (isspace((int) c))
+		    break;
+	    }
+	    *cp2++ = c;
+	}
+	*cp2 = '\0';
+	if (c == '\0')
+	    break;
+	cp++;
+    }
+    *argp++ = 0;
+}
+
+/*
+ * Make a character string into a number.
+ *
+ * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
+ */
+
+	static int
+special(s)
+	register char *s;
+{
+	register char c;
+	char b;
+
+	switch (*s) {
+	case '^':
+		b = *++s;
+		if (b == '?') {
+		    c = b | 0x40;		/* DEL */
+		} else {
+		    c = b & 0x1f;
+		}
+		break;
+	default:
+		c = *s;
+		break;
+	}
+	return c;
+}
+
+/*
+ * Construct a control character sequence
+ * for a special character.
+ */
+	static char *
+control(c)
+	register cc_t c;
+{
+	static char buf[5];
+	/*
+	 * The only way I could get the Sun 3.5 compiler
+	 * to shut up about
+	 *	if ((unsigned int)c >= 0x80)
+	 * was to assign "c" to an unsigned int variable...
+	 * Arggg....
+	 */
+	register unsigned int uic = (unsigned int)c;
+
+	if (uic == 0x7f)
+		return ("^?");
+	if (c == (cc_t)_POSIX_VDISABLE) {
+		return "off";
+	}
+	if (uic >= 0x80) {
+		buf[0] = '\\';
+		buf[1] = ((c>>6)&07) + '0';
+		buf[2] = ((c>>3)&07) + '0';
+		buf[3] = (c&07) + '0';
+		buf[4] = 0;
+	} else if (uic >= 0x20) {
+		buf[0] = c;
+		buf[1] = 0;
+	} else {
+		buf[0] = '^';
+		buf[1] = '@'+c;
+		buf[2] = 0;
+	}
+	return (buf);
+}
+
+
+
+/*
+ *	The following are data structures and routines for
+ *	the "send" command.
+ *
+ */
+ 
+struct sendlist {
+    char	*name;		/* How user refers to it (case independent) */
+    char	*help;		/* Help information (0 ==> no help) */
+    int		needconnect;	/* Need to be connected */
+    int		narg;		/* Number of arguments */
+    int		(*handler)	/* Routine to perform (for special ops) */
+			(char *);
+    int		nbyte;		/* Number of bytes to send this command */
+    int		what;		/* Character to be sent (<0 ==> special) */
+};
+
+
+static int
+	send_esc (char *),
+	send_help (char *),
+	send_docmd (char *),
+	send_dontcmd (char *),
+	send_willcmd (char *),
+	send_wontcmd (char *);
+
+static struct sendlist Sendlist[] = {
+    { "ao",	"Send Telnet Abort output",		1, 0, 0, 2, AO },
+    { "ayt",	"Send Telnet 'Are You There'",		1, 0, 0, 2, AYT },
+    { "brk",	"Send Telnet Break",			1, 0, 0, 2, BREAK },
+    { "break",	0,					1, 0, 0, 2, BREAK },
+    { "ec",	"Send Telnet Erase Character",		1, 0, 0, 2, EC },
+    { "el",	"Send Telnet Erase Line",		1, 0, 0, 2, EL },
+    { "escape",	"Send current escape character",	1, 0, send_esc, 1, 0 },
+    { "ga",	"Send Telnet 'Go Ahead' sequence",	1, 0, 0, 2, GA },
+    { "ip",	"Send Telnet Interrupt Process",	1, 0, 0, 2, IP },
+    { "intp",	0,					1, 0, 0, 2, IP },
+    { "interrupt", 0,					1, 0, 0, 2, IP },
+    { "intr",	0,					1, 0, 0, 2, IP },
+    { "nop",	"Send Telnet 'No operation'",		1, 0, 0, 2, NOP },
+    { "eor",	"Send Telnet 'End of Record'",		1, 0, 0, 2, EOR },
+    { "abort",	"Send Telnet 'Abort Process'",		1, 0, 0, 2, ABORT },
+    { "susp",	"Send Telnet 'Suspend Process'",	1, 0, 0, 2, SUSP },
+    { "eof",	"Send Telnet End of File Character",	1, 0, 0, 2, xEOF },
+    { "synch",	"Perform Telnet 'Synch operation'",	1, 0, dosynch, 2, 0 },
+    { "getstatus", "Send request for STATUS",		1, 0, get_status, 6, 0 },
+    { "?",	"Display send options",			0, 0, send_help, 0, 0 },
+    { "help",	0,					0, 0, send_help, 0, 0 },
+    { "do",	0,					0, 1, send_docmd, 3, 0 },
+    { "dont",	0,					0, 1, send_dontcmd, 3, 0 },
+    { "will",	0,					0, 1, send_willcmd, 3, 0 },
+    { "wont",	0,					0, 1, send_wontcmd, 3, 0 },
+    { 0 }
+};
+
+#define	GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
+				sizeof(struct sendlist)))
+
+    static int
+sendcmd(argc, argv)
+    int  argc;
+    char **argv;
+{
+    int count;		/* how many bytes we are going to need to send */
+    int i;
+    struct sendlist *s;	/* pointer to current command */
+    int success = 0;
+    int needconnect = 0;
+
+    if (argc < 2) {
+	printf("need at least one argument for 'send' command\r\n");
+	printf("'send ?' for help\n");
+	return 0;
+    }
+    /*
+     * First, validate all the send arguments.
+     * In addition, we see how much space we are going to need, and
+     * whether or not we will be doing a "SYNCH" operation (which
+     * flushes the network queue).
+     */
+    count = 0;
+    for (i = 1; i < argc; i++) {
+	s = GETSEND(argv[i]);
+	if (s == 0) {
+	    printf("Unknown send argument '%s'\n'send ?' for help.\r\n",
+			argv[i]);
+	    return 0;
+	} else if (Ambiguous(s)) {
+	    printf("Ambiguous send argument '%s'\n'send ?' for help.\r\n",
+			argv[i]);
+	    return 0;
+	}
+	if (i + s->narg >= argc) {
+	    fprintf(stderr,
+	    "Need %d argument%s to 'send %s' command.  'send %s ?' for help.\n",
+		s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
+	    return 0;
+	}
+	count += s->nbyte;
+	if (s->handler == send_help) {
+	    send_help(NULL);
+	    return 0;
+	}
+
+	i += s->narg;
+	needconnect += s->needconnect;
+    }
+    if (!connected && needconnect) {
+	printf("?Need to be connected first.\r\n");
+	printf("'send ?' for help\r\n");
+	return 0;
+    }
+    /* Now, do we have enough room? */
+    if (NETROOM() < count) {
+	printf("There is not enough room in the buffer TO the network\r\n");
+	printf("to process your request.  Nothing will be done.\r\n");
+	printf("('send synch' will throw away most data in the network\r\n");
+	printf("buffer, if this might help.)\r\n");
+	return 0;
+    }
+    /* OK, they are all OK, now go through again and actually send */
+    count = 0;
+    for (i = 1; i < argc; i++) {
+	if ((s = GETSEND(argv[i])) == 0) {
+	    fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
+	    (void) quit(0, NULL);
+	    /*NOTREACHED*/
+	}
+	if (s->handler) {
+	    count++;
+	    success += (*s->handler)(argv[i+1]);
+	    i += s->narg;
+	} else {
+	    NET2ADD(IAC, s->what);
+	    printoption("SENT", IAC, s->what);
+	}
+    }
+    return (count == success);
+}
+
+    static int
+send_esc(s)
+    char *s;
+{
+    NETADD(escape);
+    return 1;
+}
+
+    static int
+send_docmd(name)
+    char *name;
+{
+    return(send_tncmd(send_do, "do", name));
+}
+
+    static int
+send_dontcmd(name)
+    char *name;
+{
+    return(send_tncmd(send_dont, "dont", name));
+}
+    static int
+send_willcmd(name)
+    char *name;
+{
+    return(send_tncmd(send_will, "will", name));
+}
+    static int
+send_wontcmd(name)
+    char *name;
+{
+    return(send_tncmd(send_wont, "wont", name));
+}
+
+static    int
+send_tncmd(func, cmd, name)
+    void	(*func)();
+    char	*cmd, *name;
+{
+    char **cpp;
+    extern char *telopts[];
+    register int val = 0;
+
+    if (isprefix(name, "help") || isprefix(name, "?")) {
+	register int col, len;
+
+	printf("Usage: send %s <value|option>\r\n", cmd);
+	printf("\"value\" must be from 0 to 255\r\n");
+	printf("Valid options are:\r\n\t");
+
+	col = 8;
+	for (cpp = telopts; *cpp; cpp++) {
+	    len = strlen(*cpp) + 3;
+	    if (col + len > 65) {
+		printf("\r\n\t");
+		col = 8;
+	    }
+	    printf(" \"%s\"", *cpp);
+	    col += len;
+	}
+	printf("\r\n");
+	return 0;
+    }
+    cpp = (char **)genget(name, telopts, sizeof(char *));
+    if (Ambiguous(cpp)) {
+	fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
+					name, cmd);
+	return 0;
+    }
+    if (cpp) {
+	val = cpp - telopts;
+    } else {
+	register char *cp = name;
+
+	while (*cp >= '0' && *cp <= '9') {
+	    val *= 10;
+	    val += *cp - '0';
+	    cp++;
+	}
+	if (*cp != 0) {
+	    fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
+					name, cmd);
+	    return 0;
+	} else if (val < 0 || val > 255) {
+	    fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
+					name, cmd);
+	    return 0;
+	}
+    }
+    if (!connected) {
+	printf("?Need to be connected first.\r\n");
+	return 0;
+    }
+    (*func)(val, 1);
+    return 1;
+}
+
+    static int
+send_help(n)
+     char *n;
+{
+    struct sendlist *s;	/* pointer to current command */
+    for (s = Sendlist; s->name; s++) {
+	if (s->help)
+	    printf("%-15s %s\r\n", s->name, s->help);
+    }
+    return(0);
+}
+
+/*
+ * The following are the routines and data structures referred
+ * to by the arguments to the "toggle" command.
+ */
+
+    static int
+lclchars(s)
+     int s;
+{
+    donelclchars = 1;
+    return 1;
+}
+
+    static int
+togdebug(s)
+     int s;
+{
+#ifndef	NOT43
+    if (net > 0 &&
+	(SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
+	    perror("setsockopt (SO_DEBUG)");
+    }
+#else	/* NOT43 */
+    if (debug) {
+	if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+	    perror("setsockopt (SO_DEBUG)");
+    } else
+	printf("Cannot turn off socket debugging\r\n");
+#endif	/* NOT43 */
+    return 1;
+}
+
+
+    static int
+togcrlf(s)
+     int s;
+{
+    if (crlf) {
+	printf("Will send carriage returns as telnet <CR><LF>.\r\n");
+    } else {
+	printf("Will send carriage returns as telnet <CR><NUL>.\r\n");
+    }
+    return 1;
+}
+
+int binmode;
+
+    static int
+togbinary(val)
+    int val;
+{
+    donebinarytoggle = 1;
+
+    if (val >= 0) {
+	binmode = val;
+    } else {
+	if (my_want_state_is_will(TELOPT_BINARY) &&
+				my_want_state_is_do(TELOPT_BINARY)) {
+	    binmode = 1;
+	} else if (my_want_state_is_wont(TELOPT_BINARY) &&
+				my_want_state_is_dont(TELOPT_BINARY)) {
+	    binmode = 0;
+	}
+	val = binmode ? 0 : 1;
+    }
+
+    if (val == 1) {
+	if (my_want_state_is_will(TELOPT_BINARY) &&
+					my_want_state_is_do(TELOPT_BINARY)) {
+	    printf("Already operating in binary mode with remote host.\r\n");
+	} else {
+	    printf("Negotiating binary mode with remote host.\r\n");
+	    tel_enter_binary(3);
+	}
+    } else {
+	if (my_want_state_is_wont(TELOPT_BINARY) &&
+					my_want_state_is_dont(TELOPT_BINARY)) {
+	    printf("Already in network ascii mode with remote host.\r\n");
+	} else {
+	    printf("Negotiating network ascii mode with remote host.\r\n");
+	    tel_leave_binary(3);
+	}
+    }
+    return 1;
+}
+
+    static int
+togrbinary(val)
+    int val;
+{
+    donebinarytoggle = 1;
+
+    if (val == -1)
+	val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
+
+    if (val == 1) {
+	if (my_want_state_is_do(TELOPT_BINARY)) {
+	    printf("Already receiving in binary mode.\r\n");
+	} else {
+	    printf("Negotiating binary mode on input.\r\n");
+	    tel_enter_binary(1);
+	}
+    } else {
+	if (my_want_state_is_dont(TELOPT_BINARY)) {
+	    printf("Already receiving in network ascii mode.\r\n");
+	} else {
+	    printf("Negotiating network ascii mode on input.\r\n");
+	    tel_leave_binary(1);
+	}
+    }
+    return 1;
+}
+
+    static int
+togxbinary(val)
+    int val;
+{
+    donebinarytoggle = 1;
+
+    if (val == -1)
+	val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
+
+    if (val == 1) {
+	if (my_want_state_is_will(TELOPT_BINARY)) {
+	    printf("Already transmitting in binary mode.\r\n");
+	} else {
+	    printf("Negotiating binary mode on output.\r\n");
+	    tel_enter_binary(2);
+	}
+    } else {
+	if (my_want_state_is_wont(TELOPT_BINARY)) {
+	    printf("Already transmitting in network ascii mode.\r\n");
+	} else {
+	    printf("Negotiating network ascii mode on output.\r\n");
+	    tel_leave_binary(2);
+	}
+    }
+    return 1;
+}
+
+
+static int togglehelp (int);
+#if	defined(AUTHENTICATION)
+extern int auth_togdebug (int);
+#endif
+
+struct togglelist {
+    char	*name;		/* name of toggle */
+    char	*help;		/* help message */
+    int		(*handler)	/* routine to do actual setting */
+			(int);
+    int		*variable;
+    char	*actionexplanation;
+};
+
+static struct togglelist Togglelist[] = {
+    { "autoflush",
+	"flushing of output when sending interrupt characters",
+	    0,
+		&autoflush,
+		    "flush output when sending interrupt characters" },
+    { "autosynch",
+	"automatic sending of interrupt characters in urgent mode",
+	    0,
+		&autosynch,
+		    "send interrupt characters in urgent mode" },
+#if	defined(AUTHENTICATION)
+    { "autologin",
+	"automatic sending of login and/or authentication info",
+	    0,
+		&autologin,
+		    "send login name and/or authentication information" },
+    { "authdebug",
+	"Toggle authentication debugging",
+	    auth_togdebug,
+		0,
+		     "print authentication debugging information" },
+#endif
+#ifdef	ENCRYPTION
+    { "autoencrypt",
+	"automatic encryption of data stream",
+	    EncryptAutoEnc,
+		0,
+		    "automatically encrypt output" },
+    { "autodecrypt",
+	"automatic decryption of data stream",
+	    EncryptAutoDec,
+		0,
+		    "automatically decrypt input" },
+    { "verbose_encrypt",
+	"Toggle verbose encryption output",
+	    EncryptVerbose,
+		0,
+		    "print verbose encryption output" },
+    { "encdebug",
+	"Toggle encryption debugging",
+	    EncryptDebug,
+		0,
+		    "print encryption debugging information" },
+#endif	/* ENCRYPTION */
+    { "skiprc",
+	"don't read ~/.telnetrc file",
+	    0,
+		&skiprc,
+		    "skip reading of ~/.telnetrc file" },
+    { "binary",
+	"sending and receiving of binary data",
+	    togbinary,
+		0,
+		    0 },
+    { "inbinary",
+	"receiving of binary data",
+	    togrbinary,
+		0,
+		    0 },
+    { "outbinary",
+	"sending of binary data",
+	    togxbinary,
+		0,
+		    0 },
+    { "crlf",
+	"sending carriage returns as telnet <CR><LF>",
+	    togcrlf,
+		&crlf,
+		    0 },
+    { "crmod",
+	"mapping of received carriage returns",
+	    0,
+		&crmod,
+		    "map carriage return on output" },
+    { "localchars",
+	"local recognition of certain control characters",
+	    lclchars,
+		&localchars,
+		    "recognize certain control characters" },
+    { " ", "", 0 },		/* empty line */
+#if	defined(unix) && defined(TN3270)
+    { "apitrace",
+	"(debugging) toggle tracing of API transactions",
+	    0,
+		&apitrace,
+		    "trace API transactions" },
+    { "cursesdata",
+	"(debugging) toggle printing of hexadecimal curses data",
+	    0,
+		&cursesdata,
+		    "print hexadecimal representation of curses data" },
+#endif	/* defined(unix) && defined(TN3270) */
+    { "debug",
+	"debugging",
+	    togdebug,
+		&debug,
+		    "turn on socket level debugging" },
+    { "netdata",
+	"printing of hexadecimal network data (debugging)",
+	    0,
+		&netdata,
+		    "print hexadecimal representation of network traffic" },
+    { "prettydump",
+	"output of \"netdata\" to user readable format (debugging)",
+	    0,
+		&prettydump,
+		    "print user readable output for \"netdata\"" },
+    { "options",
+	"viewing of options processing (debugging)",
+	    0,
+		&showoptions,
+		    "show option processing" },
+    { "termdata",
+	"(debugging) toggle printing of hexadecimal terminal data",
+	    0,
+		&termdata,
+		    "print hexadecimal representation of terminal traffic" },
+    { "?",
+	0,
+	    togglehelp },
+    { "help",
+	0,
+	    togglehelp },
+    { 0 }
+};
+
+    static int
+togglehelp(n)
+    int n;
+{
+    struct togglelist *c;
+
+    for (c = Togglelist; c->name; c++) {
+	if (c->help) {
+	    if (*c->help)
+		printf("%-15s toggle %s\r\n", c->name, c->help);
+	    else
+		printf("\r\n");
+	}
+    }
+    printf("\r\n");
+    printf("%-15s %s\r\n", "?", "display help information");
+    return 0;
+}
+
+    static void
+settogglehelp(set)
+    int set;
+{
+    struct togglelist *c;
+
+    for (c = Togglelist; c->name; c++) {
+	if (c->help) {
+	    if (*c->help)
+		printf("%-15s %s %s\r\n", c->name, set ? "enable" : "disable",
+						c->help);
+	    else
+		printf("\r\n");
+	}
+    }
+}
+
+#define	GETTOGGLE(name) (struct togglelist *) \
+		genget(name, (char **) Togglelist, sizeof(struct togglelist))
+
+    static int
+toggle(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    int retval = 1;
+    char *name;
+    struct togglelist *c;
+
+    if (argc < 2) {
+	fprintf(stderr,
+	    "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
+	return 0;
+    }
+    argc--;
+    argv++;
+    while (argc--) {
+	name = *argv++;
+	c = GETTOGGLE(name);
+	if (Ambiguous(c)) {
+	    fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
+					name);
+	    return 0;
+	} else if (c == 0) {
+	    fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
+					name);
+	    return 0;
+	} else {
+	    if (c->variable) {
+		*c->variable = !*c->variable;		/* invert it */
+		if (c->actionexplanation) {
+		    printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
+							c->actionexplanation);
+		}
+	    }
+	    if (c->handler) {
+		retval &= (*c->handler)(-1);
+	    }
+	}
+    }
+    return retval;
+}
+
+/*
+ * The following perform the "set" command.
+ */
+
+#ifdef	USE_TERMIO
+struct termio new_tc = { 0 };
+#endif
+
+struct setlist {
+    char *name;				/* name */
+    char *help;				/* help information */
+    void (*handler)();
+    cc_t *charp;			/* where it is located at */
+};
+
+static struct setlist Setlist[] = {
+#ifdef	KLUDGELINEMODE
+    { "echo", 	"character to toggle local echoing on/off", 0, &echoc },
+#endif
+    { "escape",	"character to escape back to telnet command mode", 0, &escape },
+    { "rlogin", "rlogin escape character", 0, &rlogin },
+    { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
+    { " ", "" },
+    { " ", "The following need 'localchars' to be toggled true", 0, 0 },
+    { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
+    { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
+    { "quit",	"character to cause an Abort process", 0, termQuitCharp },
+    { "eof",	"character to cause an EOF ", 0, termEofCharp },
+    { " ", "" },
+    { " ", "The following are for local editing in linemode", 0, 0 },
+    { "erase",	"character to use to erase a character", 0, termEraseCharp },
+    { "kill",	"character to use to erase a line", 0, termKillCharp },
+    { "lnext",	"character to use for literal next", 0, termLiteralNextCharp },
+    { "susp",	"character to cause a Suspend Process", 0, termSuspCharp },
+    { "reprint", "character to use for line reprint", 0, termRprntCharp },
+    { "worderase", "character to use to erase a word", 0, termWerasCharp },
+    { "start",	"character to use for XON", 0, termStartCharp },
+    { "stop",	"character to use for XOFF", 0, termStopCharp },
+    { "forw1",	"alternate end of line character", 0, termForw1Charp },
+    { "forw2",	"alternate end of line character", 0, termForw2Charp },
+    { "ayt",	"alternate AYT character", 0, termAytCharp },
+    { 0 }
+};
+
+#if	defined(CRAY) && !defined(__STDC__)
+/* Work around compiler bug in pcc 4.1.5 */
+    void
+_setlist_init()
+{
+#ifndef	KLUDGELINEMODE
+#define	N 5
+#else
+#define	N 6
+#endif
+	Setlist[N+0].charp = &termFlushChar;
+	Setlist[N+1].charp = &termIntChar;
+	Setlist[N+2].charp = &termQuitChar;
+	Setlist[N+3].charp = &termEofChar;
+	Setlist[N+6].charp = &termEraseChar;
+	Setlist[N+7].charp = &termKillChar;
+	Setlist[N+8].charp = &termLiteralNextChar;
+	Setlist[N+9].charp = &termSuspChar;
+	Setlist[N+10].charp = &termRprntChar;
+	Setlist[N+11].charp = &termWerasChar;
+	Setlist[N+12].charp = &termStartChar;
+	Setlist[N+13].charp = &termStopChar;
+	Setlist[N+14].charp = &termForw1Char;
+	Setlist[N+15].charp = &termForw2Char;
+	Setlist[N+16].charp = &termAytChar;
+#undef	N
+}
+#endif	/* defined(CRAY) && !defined(__STDC__) */
+
+    static struct setlist *
+getset(name)
+    char *name;
+{
+    return (struct setlist *)
+		genget(name, (char **) Setlist, sizeof(struct setlist));
+}
+
+    void
+set_escape_char(s)
+    char *s;
+{
+	if (rlogin != _POSIX_VDISABLE) {
+		rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
+		printf("Telnet rlogin escape character is '%s'.\r\n",
+					control(rlogin));
+	} else {
+		escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
+		printf("Telnet escape character is '%s'.\r\n", control(escape));
+	}
+}
+
+    static int
+setcmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    int value;
+    struct setlist *ct;
+    struct togglelist *c;
+
+    if (argc < 2 || argc > 3) {
+	printf("Format is 'set Name Value'\n'set ?' for help.\r\n");
+	return 0;
+    }
+    if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
+	for (ct = Setlist; ct->name; ct++)
+	    printf("%-15s %s\r\n", ct->name, ct->help);
+	printf("\r\n");
+	settogglehelp(1);
+	printf("%-15s %s\r\n", "?", "display help information");
+	return 0;
+    }
+
+    ct = getset(argv[1]);
+    if (ct == 0) {
+	c = GETTOGGLE(argv[1]);
+	if (c == 0) {
+	    fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
+			argv[1]);
+	    return 0;
+	} else if (Ambiguous(c)) {
+	    fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
+			argv[1]);
+	    return 0;
+	}
+	if (c->variable) {
+	    if ((argc == 2) || (strcmp("on", argv[2]) == 0))
+		*c->variable = 1;
+	    else if (strcmp("off", argv[2]) == 0)
+		*c->variable = 0;
+	    else {
+		printf("Format is 'set togglename [on|off]'\n'set ?' for help.\r\n");
+		return 0;
+	    }
+	    if (c->actionexplanation) {
+		printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
+							c->actionexplanation);
+	    }
+	}
+	if (c->handler)
+	    (*c->handler)(1);
+    } else if (argc != 3) {
+	printf("Format is 'set Name Value'\n'set ?' for help.\r\n");
+	return 0;
+    } else if (Ambiguous(ct)) {
+	fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
+			argv[1]);
+	return 0;
+    } else if (ct->handler) {
+	(*ct->handler)(argv[2]);
+	printf("%s set to \"%s\".\r\n", ct->name, (char *)ct->charp);
+    } else {
+	if (strcmp("off", argv[2])) {
+	    value = special(argv[2]);
+	} else {
+	    value = _POSIX_VDISABLE;
+	}
+	*(ct->charp) = (cc_t)value;
+	printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp)));
+    }
+    slc_check();
+    return 1;
+}
+
+    static int
+unsetcmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct setlist *ct;
+    struct togglelist *c;
+    register char *name;
+
+    if (argc < 2) {
+	fprintf(stderr,
+	    "Need an argument to 'unset' command.  'unset ?' for help.\n");
+	return 0;
+    }
+    if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
+	for (ct = Setlist; ct->name; ct++)
+	    printf("%-15s %s\r\n", ct->name, ct->help);
+	printf("\r\n");
+	settogglehelp(0);
+	printf("%-15s %s\r\n", "?", "display help information");
+	return 0;
+    }
+
+    argc--;
+    argv++;
+    while (argc--) {
+	name = *argv++;
+	ct = getset(name);
+	if (ct == 0) {
+	    c = GETTOGGLE(name);
+	    if (c == 0) {
+		fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
+			name);
+		return 0;
+	    } else if (Ambiguous(c)) {
+		fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
+			name);
+		return 0;
+	    }
+	    if (c->variable) {
+		*c->variable = 0;
+		if (c->actionexplanation) {
+		    printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
+							c->actionexplanation);
+		}
+	    }
+	    if (c->handler)
+		(*c->handler)(0);
+	} else if (Ambiguous(ct)) {
+	    fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
+			name);
+	    return 0;
+	} else if (ct->handler) {
+	    (*ct->handler)(0);
+	    printf("%s reset to \"%s\".\r\n", ct->name, (char *)ct->charp);
+	} else {
+	    *(ct->charp) = _POSIX_VDISABLE;
+	    printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp)));
+	}
+    }
+    return 1;
+}
+
+/*
+ * The following are the data structures and routines for the
+ * 'mode' command.
+ */
+#ifdef	KLUDGELINEMODE
+extern int kludgelinemode;
+
+    static int
+dokludgemode()
+{
+    kludgelinemode = 1;
+    send_wont(TELOPT_LINEMODE, 1);
+    send_dont(TELOPT_SGA, 1);
+    send_dont(TELOPT_ECHO, 1);
+    return 1;			/* I'm guessing here -- eichin -- XXX */
+}
+#endif
+
+    static int
+dolinemode()
+{
+#ifdef	KLUDGELINEMODE
+    if (kludgelinemode)
+	send_dont(TELOPT_SGA, 1);
+#endif
+    send_will(TELOPT_LINEMODE, 1);
+    send_dont(TELOPT_ECHO, 1);
+    return 1;
+}
+
+    static int
+docharmode()
+{
+#ifdef	KLUDGELINEMODE
+    if (kludgelinemode)
+	send_do(TELOPT_SGA, 1);
+    else
+#endif
+    send_wont(TELOPT_LINEMODE, 1);
+    send_do(TELOPT_ECHO, 1);
+    return 1;
+}
+
+    static int
+dolmmode(bit, on)
+    int bit, on;
+{
+    unsigned char c;
+    extern int linemode;
+
+    if (my_want_state_is_wont(TELOPT_LINEMODE)) {
+	printf("?Need to have LINEMODE option enabled first.\r\n");
+	printf("'mode ?' for help.\r\n");
+	return 0;
+    }
+
+    if (on)
+	c = (linemode | bit);
+    else
+	c = (linemode & ~bit);
+    lm_mode(&c, 1, 1);
+    return 1;
+}
+
+static int
+tel_setmode(bit)
+    int bit;
+{
+    return dolmmode(bit, 1);
+}
+
+static int
+tel_clearmode(bit)
+    int bit;
+{
+    return dolmmode(bit, 0);
+}
+
+struct modelist {
+	char	*name;		/* command name */
+	char	*help;		/* help string */
+	int	(*handler)();	/* routine which executes command */
+	int	needconnect;	/* Do we need to be connected to execute? */
+	int	arg1;
+};
+
+static int modehelp(void);
+
+static struct modelist ModeList[] = {
+    { "character", "Disable LINEMODE option",	docharmode, 1 },
+#ifdef	KLUDGELINEMODE
+    { "",	"(or disable obsolete line-by-line mode)", 0 },
+#endif
+    { "line",	"Enable LINEMODE option",	dolinemode, 1 },
+#ifdef	KLUDGELINEMODE
+    { "",	"(or enable obsolete line-by-line mode)", 0 },
+#endif
+    { "", "", 0 },
+    { "",	"These require the LINEMODE option to be enabled", 0 },
+    { "isig",	"Enable signal trapping",	tel_setmode, 1, MODE_TRAPSIG },
+    { "+isig",	0,				tel_setmode, 1, MODE_TRAPSIG },
+    { "-isig",	"Disable signal trapping",	tel_clearmode, 1, MODE_TRAPSIG },
+    { "edit",	"Enable character editing",	tel_setmode, 1, MODE_EDIT },
+    { "+edit",	0,				tel_setmode, 1, MODE_EDIT },
+    { "-edit",	"Disable character editing",	tel_clearmode, 1, MODE_EDIT },
+    { "softtabs", "Enable tab expansion",	tel_setmode, 1, MODE_SOFT_TAB },
+    { "+softtabs", 0,				tel_setmode, 1, MODE_SOFT_TAB },
+    { "-softtabs", "Disable character editing",	tel_clearmode, 1, MODE_SOFT_TAB },
+    { "litecho", "Enable literal character echo", tel_setmode, 1, MODE_LIT_ECHO },
+    { "+litecho", 0,				tel_setmode, 1, MODE_LIT_ECHO },
+    { "-litecho", "Disable literal character echo", tel_clearmode, 1, MODE_LIT_ECHO },
+    { "help",	0,				modehelp, 0 },
+#ifdef	KLUDGELINEMODE
+    { "kludgeline", 0,				dokludgemode, 1 },
+#endif
+    { "", "", 0 },
+    { "?",	"Print help information",	modehelp, 0 },
+    { 0 },
+};
+
+
+static int
+modehelp()
+{
+    struct modelist *mt;
+
+    printf("format is:  'mode Mode', where 'Mode' is one of:\r\n\r\n");
+    for (mt = ModeList; mt->name; mt++) {
+	if (mt->help) {
+	    if (*mt->help)
+		printf("%-15s %s\r\n", mt->name, mt->help);
+	    else
+		printf("\r\n");
+	}
+    }
+    return 0;
+}
+
+#define	GETMODECMD(name) (struct modelist *) \
+		genget(name, (char **) ModeList, sizeof(struct modelist))
+
+    static int
+modecmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct modelist *mt;
+
+    if (argc != 2) {
+	printf("'mode' command requires an argument\r\n");
+	printf("'mode ?' for help.\r\n");
+    } else if ((mt = GETMODECMD(argv[1])) == 0) {
+	fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
+    } else if (Ambiguous(mt)) {
+	fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
+    } else if (mt->needconnect && !connected) {
+	printf("?Need to be connected first.\r\n");
+	printf("'mode ?' for help.\r\n");
+    } else if (mt->handler) {
+	return (*mt->handler)(mt->arg1);
+    }
+    return 0;
+}
+
+/*
+ * The following data structures and routines implement the
+ * "display" command.
+ */
+
+    static int
+display(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct togglelist *tl;
+    struct setlist *sl;
+
+#define	dotog(tl)	if (tl->variable && tl->actionexplanation) { \
+			    if (*tl->variable) { \
+				printf("will"); \
+			    } else { \
+				printf("won't"); \
+			    } \
+			    printf(" %s.\r\n", tl->actionexplanation); \
+			}
+
+#define	doset(sl)   if (sl->name && *sl->name != ' ') { \
+			if (sl->handler == 0) \
+			    printf("%-15s [%s]\r\n", sl->name, control(*sl->charp)); \
+			else \
+			    printf("%-15s \"%s\"\r\n", sl->name, (char *)sl->charp); \
+		    }
+
+    if (argc == 1) {
+	for (tl = Togglelist; tl->name; tl++) {
+	    dotog(tl);
+	}
+	printf("\r\n");
+	for (sl = Setlist; sl->name; sl++) {
+	    doset(sl);
+	}
+    } else {
+	int i;
+
+	for (i = 1; i < argc; i++) {
+	    sl = getset(argv[i]);
+	    tl = GETTOGGLE(argv[i]);
+	    if (Ambiguous(sl) || Ambiguous(tl)) {
+		printf("?Ambiguous argument '%s'.\r\n", argv[i]);
+		return 0;
+	    } else if (!sl && !tl) {
+		printf("?Unknown argument '%s'.\r\n", argv[i]);
+		return 0;
+	    } else {
+		if (tl) {
+		    dotog(tl);
+		}
+		if (sl) {
+		    doset(sl);
+		}
+	    }
+	}
+    }
+    /*@*/optionstatus();
+#ifdef	ENCRYPTION
+    EncryptStatus();
+#endif	/* ENCRYPTION */
+    return 1;
+#undef	doset
+#undef	dotog
+}
+
+/*
+ * The following are the data structures, and many of the routines,
+ * relating to command processing.
+ */
+
+/*
+ * Set the escape character.
+ */
+	static int
+setescape(argc, argv)
+	int argc;
+	char *argv[];
+{
+	register char *arg;
+	char buf[50];
+
+	printf(
+	    "Deprecated usage - please use 'set escape%s%s' in the future.\r\n",
+				(argc > 2)? " ":"", (argc > 2)? argv[1]: "");
+	if (argc > 2)
+		arg = argv[1];
+	else {
+		printf("new escape character: ");
+		(void) fgets(buf, sizeof(buf), stdin);
+		arg = buf;
+	}
+	if (arg[0] != '\0')
+		escape = arg[0];
+	if (!In3270) {
+		printf("Escape character is '%s'.\r\n", control(escape));
+	}
+	(void) fflush(stdout);
+	return 1;
+}
+
+    /*VARARGS*/
+    static int
+togcrmod(argc, argv)
+     int argc;
+     char **argv;
+{
+    crmod = !crmod;
+    printf("Deprecated usage - please use 'toggle crmod' in the future.\r\n");
+    printf("%s map carriage return on output.\r\n", crmod ? "Will" : "Won't");
+    (void) fflush(stdout);
+    return 1;
+}
+
+    /*VARARGS*/
+static int
+suspend(argc, argv)
+     int argc;
+     char **argv;
+{
+#ifdef	SIGTSTP
+    setcommandmode();
+    {
+	long oldrows, oldcols, newrows, newcols, err;
+
+	err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+	(void) kill(0, SIGTSTP);
+	/*
+	 * If we didn't get the window size before the SUSPEND, but we
+	 * can get them now (???), then send the NAWS to make sure that
+	 * we are set up for the right window size.
+	 */
+	if (TerminalWindowSize(&newrows, &newcols) && connected &&
+	    (err || ((oldrows != newrows) || (oldcols != newcols)))) {
+		sendnaws();
+	}
+    }
+    /* reget parameters in case they were changed */
+    TerminalSaveState();
+    setconnmode(0);
+#else
+    printf("Suspend is not supported.  Try the '!' command instead\r\n");
+#endif
+    return 1;
+}
+
+#if	!defined(TN3270)
+    /*ARGSUSED*/
+static int
+shell(argc, argv)
+    int argc;
+    char *argv[];
+{
+    long oldrows, oldcols, newrows, newcols, err;
+
+    setcommandmode();
+
+    err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+    switch(vfork()) {
+    case -1:
+	perror("Fork failed");
+	break;
+
+    case 0:
+	{
+	    /*
+	     * Fire up the shell in the child.
+	     */
+	    register char *shellp, *shellname;
+
+	    shellp = getenv("SHELL");
+	    if (shellp == NULL)
+		shellp = "/bin/sh";
+	    if ((shellname = strrchr(shellp, '/')) == 0)
+		shellname = shellp;
+	    else
+		shellname++;
+	    if (argc > 1)
+		execl(shellp, shellname, "-c", &saveline[1], (char *)NULL);
+	    else
+		execl(shellp, shellname, (char *)NULL);
+	    perror("Execl");
+	    _exit(1);
+	}
+    default:
+	    (void)wait((int *)0);	/* Wait for the shell to complete */
+
+	    if (TerminalWindowSize(&newrows, &newcols) && connected &&
+		(err || ((oldrows != newrows) || (oldcols != newcols)))) {
+		    sendnaws();
+	    }
+	    break;
+    }
+    return 1;
+}
+#else	/* !defined(TN3270) */
+extern int shell();
+#endif	/* !defined(TN3270) */
+
+/*VARARGS*/
+static int
+bye(argc, argv)
+    int  argc;		/* Number of arguments */
+    char *argv[];	/* arguments */
+{
+    extern int resettermname;
+
+    if (connected) {
+	(void) shutdown(net, 2);
+	printf("Connection closed.\r\n");
+	(void) NetClose(net);
+	connected = 0;
+	resettermname = 1;
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+	auth_encrypt_connect(connected);
+#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+	/* reset options */
+	tninit();
+#if	defined(TN3270)
+	SetIn3270();		/* Get out of 3270 mode */
+#endif	/* defined(TN3270) */
+    }
+    if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
+	longjmp(toplevel, 1);
+	/* NOTREACHED */
+    }
+    return 1;			/* Keep lint, etc., happy */
+}
+
+/*VARARGS*/
+int
+quit(argc, argv)
+	int argc;
+	char *argv[];
+{
+	(void) call(bye, "bye", "fromquit", 0);
+	Exit(0);
+	/*NOTREACHED*/
+	return 0;
+}
+
+/*VARARGS*/
+static int
+logout(argc, argv)
+     int argc;
+     char **argv;
+{
+	send_do(TELOPT_LOGOUT, 1);
+	(void) netflush();
+	return 1;
+}
+
+
+/*
+ * The SLC command.
+ */
+
+struct slclist {
+	char	*name;
+	char	*help;
+	void	(*handler)();
+	int	arg;
+};
+
+static void slc_help(void);
+
+struct slclist SlcList[] = {
+    { "export",	"Use local special character definitions",
+						slc_mode_export,	0 },
+    { "import",	"Use remote special character definitions",
+						slc_mode_import,	1 },
+    { "check",	"Verify remote special character definitions",
+						slc_mode_import,	0 },
+    { "help",	0,				slc_help,		0 },
+    { "?",	"Print help information",	slc_help,		0 },
+    { 0 },
+};
+
+    static void
+slc_help()
+{
+    struct slclist *c;
+
+    for (c = SlcList; c->name; c++) {
+	if (c->help) {
+	    if (*c->help)
+		printf("%-15s %s\r\n", c->name, c->help);
+	    else
+		printf("\r\n");
+	}
+    }
+}
+
+static struct slclist *
+getslc(name)
+    char *name;
+{
+    return (struct slclist *)
+		genget(name, (char **) SlcList, sizeof(struct slclist));
+}
+
+static int
+slccmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct slclist *c;
+
+    if (argc != 2) {
+	fprintf(stderr,
+	    "Need an argument to 'slc' command.  'slc ?' for help.\n");
+	return 0;
+    }
+    c = getslc(argv[1]);
+    if (c == 0) {
+        fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (Ambiguous(c)) {
+        fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    (*c->handler)(c->arg);
+    slcstate();
+    return 1;
+}
+
+/*
+ * The ENVIRON command.
+ */
+
+struct envlist {
+	char	*name;
+	char	*help;
+	void	(*handler)();
+	int	narg;
+};
+
+extern struct env_lst *
+	env_define (unsigned char *, unsigned char *);
+extern void
+	env_undefine (unsigned char *),
+	env_export (unsigned char *),
+	env_unexport (unsigned char *),
+	env_send (unsigned char *),
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+	env_varval (unsigned char *),
+#endif
+	env_list (void);
+static void
+	env_help (void);
+
+struct envlist EnvList[] = {
+    { "define",	"Define an environment variable",
+						(void (*)())env_define,	2 },
+    { "undefine", "Undefine an environment variable",
+						env_undefine,	1 },
+    { "export",	"Mark an environment variable for automatic export",
+						env_export,	1 },
+    { "unexport", "Don't mark an environment variable for automatic export",
+						env_unexport,	1 },
+    { "send",	"Send an environment variable", env_send,	1 },
+    { "list",	"List the current environment variables",
+						env_list,	0 },
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+    { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
+						env_varval,    1 },
+#endif
+    { "help",	0,				env_help,		0 },
+    { "?",	"Print help information",	env_help,		0 },
+    { 0 },
+};
+
+    static void
+env_help()
+{
+    struct envlist *c;
+
+    for (c = EnvList; c->name; c++) {
+	if (c->help) {
+	    if (*c->help)
+		printf("%-15s %s\r\n", c->name, c->help);
+	    else
+		printf("\r\n");
+	}
+    }
+}
+
+    static struct envlist *
+getenvcmd(name)
+    char *name;
+{
+    return (struct envlist *)
+		genget(name, (char **) EnvList, sizeof(struct envlist));
+}
+
+static int
+env_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct envlist *c;
+
+    if (argc < 2) {
+	fprintf(stderr,
+	    "Need an argument to 'environ' command.  'environ ?' for help.\n");
+	return 0;
+    }
+    c = getenvcmd(argv[1]);
+    if (c == 0) {
+        fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (Ambiguous(c)) {
+        fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (c->narg + 2 != argc) {
+	fprintf(stderr,
+	    "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
+		c->narg < argc - 2 ? "only " : "",
+		c->narg, c->narg == 1 ? "" : "s", c->name);
+	return 0;
+    }
+    (*c->handler)(argv[2], argv[3]);
+    return 1;
+}
+
+struct env_lst {
+	struct env_lst *next;	/* pointer to next structure */
+	struct env_lst *prev;	/* pointer to previous structure */
+	unsigned char *var;	/* pointer to variable name */
+	unsigned char *value;	/* pointer to variable value */
+	int export;		/* 1 -> export with default list of variables */
+	int welldefined;	/* A well defined variable */
+};
+
+struct env_lst envlisthead;
+
+static	struct env_lst *
+env_find(var)
+	unsigned char *var;
+{
+	register struct env_lst *ep;
+
+	for (ep = envlisthead.next; ep; ep = ep->next) {
+		if (strcmp((char *)ep->var, (char *)var) == 0)
+			return(ep);
+	}
+	return(NULL);
+}
+
+	void
+env_init()
+{
+	extern char **environ;
+	register char **epp, *cp;
+	register struct env_lst *ep;
+
+	for (epp = environ; *epp; epp++) {
+		if ((cp = strchr(*epp, '='))) {
+			*cp = '\0';
+			ep = env_define((unsigned char *)*epp,
+					(unsigned char *)cp+1);
+			ep->export = 0;
+			*cp = '=';
+		}
+	}
+	/*
+	 * Special case for DISPLAY variable.  If it is ":0.0" or
+	 * "unix:0.0", we have to get rid of "unix" and insert our
+	 * hostname.
+	 */
+	if ((ep = env_find("DISPLAY"))
+	    && ((*ep->value == ':')
+	        || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
+		char hbuf[256+1];
+		char *cp2 = strchr((char *)ep->value, ':');
+
+		gethostname(hbuf, 256);
+		hbuf[256] = '\0';
+		cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
+		sprintf((char *)cp, "%s%s", hbuf, cp2);
+		free(ep->value);
+		ep->value = (unsigned char *)cp;
+	}
+	/*
+	 * If USER is not defined, but LOGNAME is, then add
+	 * USER with the value from LOGNAME.  By default, we
+	 * don't export the USER variable.
+	 */
+	if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
+		env_define((unsigned char *)"USER", ep->value);
+		env_unexport((unsigned char *)"USER");
+	}
+	env_export((unsigned char *)"DISPLAY");
+	env_export((unsigned char *)"PRINTER");
+}
+
+	struct env_lst *
+env_define(var, value)
+	unsigned char *var, *value;
+{
+	register struct env_lst *ep;
+
+	if ((ep = env_find(var))) {
+		if (ep->var)
+			free(ep->var);
+		if (ep->value)
+			free(ep->value);
+	} else {
+		ep = (struct env_lst *)malloc(sizeof(struct env_lst));
+		ep->next = envlisthead.next;
+		envlisthead.next = ep;
+		ep->prev = &envlisthead;
+		if (ep->next)
+			ep->next->prev = ep;
+	}
+	ep->welldefined = opt_welldefined((char *)var);
+	ep->export = 1;
+	ep->var = (unsigned char *)strdup((char *)var);
+	ep->value = (unsigned char *)strdup((char *)value);
+	return(ep);
+}
+
+	void
+env_undefine(var)
+	unsigned char *var;
+{
+	register struct env_lst *ep;
+
+	if ((ep = env_find(var))) {
+		ep->prev->next = ep->next;
+		if (ep->next)
+			ep->next->prev = ep->prev;
+		if (ep->var)
+			free(ep->var);
+		if (ep->value)
+			free(ep->value);
+		free(ep);
+	}
+}
+
+	void
+env_export(var)
+	unsigned char *var;
+{
+	register struct env_lst *ep;
+
+	if ((ep = env_find(var)))
+		ep->export = 1;
+}
+
+	void
+env_unexport(var)
+	unsigned char *var;
+{
+	register struct env_lst *ep;
+
+	if ((ep = env_find(var)))
+		ep->export = 0;
+}
+
+	void
+env_send(var)
+	unsigned char *var;
+{
+	register struct env_lst *ep;
+
+        if (my_state_is_wont(TELOPT_NEW_ENVIRON)
+#ifdef	OLD_ENVIRON
+	    && my_state_is_wont(TELOPT_OLD_ENVIRON)
+#endif
+		) {
+		fprintf(stderr,
+		    "Cannot send '%s': Telnet ENVIRON option not enabled\n",
+									var);
+		return;
+	}
+	ep = env_find(var);
+	if (ep == 0) {
+		fprintf(stderr, "Cannot send '%s': variable not defined\n",
+									var);
+		return;
+	}
+	env_opt_start_info();
+	env_opt_add(ep->var);
+	env_opt_end(0);
+}
+
+	void
+env_list()
+{
+	register struct env_lst *ep;
+
+	for (ep = envlisthead.next; ep; ep = ep->next) {
+		printf("%c %-20s %s\r\n", ep->export ? '*' : ' ',
+					ep->var, ep->value);
+	}
+}
+
+	unsigned char *
+env_default(init, welldefined)
+	int init;
+{
+	static struct env_lst *nep = NULL;
+
+	if (init) {
+		nep = &envlisthead;
+		return NULL;	/* guessing here too -- eichin -- XXX */
+	}
+	if (nep) {
+		while ((nep = nep->next)) {
+			if (nep->export && (nep->welldefined == welldefined))
+				return(nep->var);
+		}
+	}
+	return(NULL);
+}
+
+	unsigned char *
+env_getvalue(var)
+	unsigned char *var;
+{
+	register struct env_lst *ep;
+
+	if ((ep = env_find(var)))
+		return(ep->value);
+	return(NULL);
+}
+
+	int
+env_is_exported(var)
+	unsigned char *var;
+{
+	register struct env_lst *ep;
+
+	if ((ep = env_find(var)))
+		return ep->export;
+	return 0;
+}
+	    
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+	void
+env_varval(what)
+	unsigned char *what;
+{
+	extern int old_env_var, old_env_value, env_auto;
+	unsigned int len = strlen((char *)what);
+
+	if (len == 0)
+		goto unknown;
+
+	if (strncasecmp((char *)what, "status", len) == 0) {
+		if (env_auto)
+			printf("%s%s", "VAR and VALUE are/will be ",
+					"determined automatically\r\n");
+		if (old_env_var == OLD_ENV_VAR)
+			printf("VAR and VALUE set to correct definitions\r\n");
+		else
+			printf("VAR and VALUE definitions are reversed\r\n");
+	} else if (strncasecmp((char *)what, "auto", len) == 0) {
+		env_auto = 1;
+		old_env_var = OLD_ENV_VALUE;
+		old_env_value = OLD_ENV_VAR;
+	} else if (strncasecmp((char *)what, "right", len) == 0) {
+		env_auto = 0;
+		old_env_var = OLD_ENV_VAR;
+		old_env_value = OLD_ENV_VALUE;
+	} else if (strncasecmp((char *)what, "wrong", len) == 0) {
+		env_auto = 0;
+		old_env_var = OLD_ENV_VALUE;
+		old_env_value = OLD_ENV_VAR;
+	} else {
+unknown:
+		printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\r\n");
+	}
+}
+#endif
+
+#if	defined(AUTHENTICATION)
+/*
+ * The AUTHENTICATE command.
+ */
+
+struct authlist {
+	char	*name;
+	char	*help;
+	int	(*handler)();
+	int	narg;
+};
+
+extern int
+	auth_enable (char *),
+	auth_disable (char *),
+	auth_status (void);
+static int
+	auth_help (void);
+
+struct authlist AuthList[] = {
+    { "status",	"Display current status of authentication information",
+						auth_status,	0 },
+    { "disable", "Disable an authentication type ('auth disable ?' for more)",
+						auth_disable,	1 },
+    { "enable", "Enable an authentication type ('auth enable ?' for more)",
+						auth_enable,	1 },
+    { "help",	0,				auth_help,		0 },
+    { "?",	"Print help information",	auth_help,		0 },
+    { 0 },
+};
+
+    static int
+auth_help()
+{
+    struct authlist *c;
+
+    for (c = AuthList; c->name; c++) {
+	if (c->help) {
+	    if (*c->help)
+		printf("%-15s %s\r\n", c->name, c->help);
+	    else
+		printf("\r\n");
+	}
+    }
+    return 0;
+}
+
+int
+auth_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct authlist *c;
+
+    if (argc < 2) {
+      fprintf(stderr,
+          "Need an argument to 'auth' command.  'auth ?' for help.\n");
+      return 0;
+    }
+
+    c = (struct authlist *)
+		genget(argv[1], (char **) AuthList, sizeof(struct authlist));
+    if (c == 0) {
+        fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (Ambiguous(c)) {
+        fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (c->narg + 2 != argc) {
+	fprintf(stderr,
+	    "Need %s%d argument%s to 'auth %s' command.  'auth ?' for help.\n",
+		c->narg < argc + 2 ? "only " : "",
+		c->narg, c->narg == 1 ? "" : "s", c->name);
+	return 0;
+    }
+    return((*c->handler)(argv[2], argv[3]));
+}
+#endif
+
+#ifdef	ENCRYPTION
+/*
+ * The ENCRYPT command.
+ */
+
+struct encryptlist {
+	char	*name;
+	char	*help;
+	int	(*handler)();
+	int	needconnect;
+	int	minarg;
+	int	maxarg;
+};
+
+extern int
+	EncryptEnable (char *, char *),
+	EncryptDisable (char *, char *),
+	EncryptType (char *, char *),
+	EncryptStart (char *),
+	EncryptStartInput (void),
+	EncryptStartOutput (void),
+	EncryptStop (char *),
+	EncryptStopInput (void),
+	EncryptStopOutput (void),
+	EncryptStatus (void);
+static int
+	EncryptHelp (void);
+
+struct encryptlist EncryptList[] = {
+    { "enable", "Enable encryption. ('encrypt enable ?' for more)",
+						EncryptEnable, 1, 1, 2 },
+    { "disable", "Disable encryption. ('encrypt enable ?' for more)",
+						EncryptDisable, 0, 1, 2 },
+    { "type", "Set encryption type. ('encrypt type ?' for more)",
+						EncryptType, 0, 1, 1 },
+    { "start", "Start encryption. ('encrypt start ?' for more)",
+						EncryptStart, 1, 0, 1 },
+    { "stop", "Stop encryption. ('encrypt stop ?' for more)",
+						EncryptStop, 1, 0, 1 },
+    { "input", "Start encrypting the input stream",
+						EncryptStartInput, 1, 0, 0 },
+    { "-input", "Stop encrypting the input stream",
+						EncryptStopInput, 1, 0, 0 },
+    { "output", "Start encrypting the output stream",
+						EncryptStartOutput, 1, 0, 0 },
+    { "-output", "Stop encrypting the output stream",
+						EncryptStopOutput, 1, 0, 0 },
+
+    { "status",	"Display current status of authentication information",
+						EncryptStatus,	0, 0, 0 },
+    { "help",	0,				EncryptHelp,	0, 0, 0 },
+    { "?",	"Print help information",	EncryptHelp,	0, 0, 0 },
+    { 0 },
+};
+
+    static int
+EncryptHelp()
+{
+    struct encryptlist *c;
+
+    for (c = EncryptList; c->name; c++) {
+	if (c->help) {
+	    if (*c->help)
+		printf("%-15s %s\r\n", c->name, c->help);
+	    else
+		printf("\r\n");
+	}
+    }
+    return 0;
+}
+
+int
+encrypt_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct encryptlist *c;
+
+    if (argc < 2) {
+	fprintf(stderr,
+	    "Need an argument to 'encrypt' command.  'encrypt ?' for help.\n");
+	return 0;
+    }
+
+    c = (struct encryptlist *)
+		genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
+    if (c == 0) {
+        fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (Ambiguous(c)) {
+        fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    argc -= 2;
+    if (argc < c->minarg || argc > c->maxarg) {
+	if (c->minarg == c->maxarg) {
+	    fprintf(stderr, "Need %s%d argument%s ",
+		c->minarg < argc ? "only " : "", c->minarg,
+		c->minarg == 1 ? "" : "s");
+	} else {
+	    fprintf(stderr, "Need %s%d-%d arguments ",
+		c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
+	}
+	fprintf(stderr, "to 'encrypt %s' command.  'encrypt ?' for help.\n",
+		c->name);
+	return 0;
+    }
+    if (c->needconnect && !connected) {
+	if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
+	    printf("?Need to be connected first.\r\n");
+	    return 0;
+	}
+    }
+    return ((*c->handler)(argc > 0 ? argv[2] : 0,
+			argc > 1 ? argv[3] : 0,
+			argc > 2 ? argv[4] : 0));
+}
+#endif	/* ENCRYPTION */
+
+#if	defined(FORWARD)
+
+/*
+ * The FORWARD command.
+ */
+
+
+extern int forward_flags;
+
+struct forwlist {
+	char	*name;
+	char	*help;
+	int	(*handler)();
+	int	f_flags;
+};
+
+static int
+	forw_status (void),
+	forw_set (int),
+	forw_help (void);
+
+struct forwlist ForwList[] = {
+    { "status",	"Display current status of credential forwarding",
+						forw_status,	0 },
+    { "disable", "Disable credential forwarding",
+						forw_set,	0 },
+    { "enable", "Enable credential forwarding",
+						forw_set,
+						OPTS_FORWARD_CREDS },
+    { "forwardable", "Enable credential forwarding of forwardable credentials",
+						forw_set,
+						OPTS_FORWARD_CREDS |
+						OPTS_FORWARDABLE_CREDS },
+    { "help",	0,				forw_help,		0 },
+    { "?",	"Print help information",	forw_help,		0 },
+    { 0 },
+};
+
+    static int
+forw_status()
+{
+    if (forward_flags & OPTS_FORWARD_CREDS) {
+	if (forward_flags & OPTS_FORWARDABLE_CREDS) {
+	    printf("Credential forwarding of forwardable credentials enabled\n");
+	} else {
+	    printf("Credential forwarding enabled\n");
+	}
+    } else {
+	printf("Credential forwarding disabled\n");
+    }
+    return(0);
+}
+
+int
+forw_set(f_flags)
+     int f_flags;
+{
+    forward_flags = f_flags;
+    return(0);
+}
+
+static int
+forw_help()
+{
+    struct forwlist *c;
+
+    for (c = ForwList; c->name; c++) {
+	if (c->help) {
+	    if (*c->help)
+		printf("%-15s %s\n", c->name, c->help);
+	    else
+		printf("\n");
+	}
+    }
+    return 0;
+}
+
+static int
+forw_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct forwlist *c;
+
+    if (argc < 2) {
+      fprintf(stderr,
+          "Need an argument to 'forward' command.  'forward ?' for help.\n");
+      return 0;
+    }
+
+    c = (struct forwlist *)
+		genget(argv[1], (char **) ForwList, sizeof(struct forwlist));
+    if (c == 0) {
+        fprintf(stderr, "'%s': unknown argument ('forw ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (Ambiguous(c)) {
+        fprintf(stderr, "'%s': ambiguous argument ('forw ?' for help).\n",
+    				argv[1]);
+        return 0;
+    }
+    if (argc != 2) {
+	fprintf(stderr,
+       "No arguments needed to 'forward %s' command.  'forward ?' for help.\n",
+		c->name);
+	return 0;
+    }
+    return((*c->handler)(c->f_flags));
+}
+#endif
+
+#if	defined(unix) && defined(TN3270)
+    static void
+filestuff(fd)
+    int fd;
+{
+    int res;
+
+#ifdef	F_GETOWN
+    setconnmode(0);
+    res = fcntl(fd, F_GETOWN, 0);
+    setcommandmode();
+
+    if (res == -1) {
+	perror("fcntl");
+	return;
+    }
+    printf("\tOwner is %d.\r\n", res);
+#endif
+
+    setconnmode(0);
+    res = fcntl(fd, F_GETFL, 0);
+    setcommandmode();
+
+    if (res == -1) {
+	perror("fcntl");
+	return;
+    }
+#ifdef notdef
+    printf("\tFlags are 0x%x: %s\r\n", res, decodeflags(res));
+#endif
+}
+#endif /* defined(unix) && defined(TN3270) */
+
+/*
+ * Print status about the connection.
+ */
+    /*ARGSUSED*/
+static int
+status(argc, argv)
+    int	 argc;
+    char *argv[];
+{
+    if (connected) {
+	printf("Connected to %s (%s).\r\n", hostname, hostaddrstring);
+	if ((argc < 2) || strcmp(argv[1], "notmuch")) {
+	    int mode = getconnmode();
+
+	    if (my_want_state_is_will(TELOPT_LINEMODE)) {
+		printf("Operating with LINEMODE option\r\n");
+		printf("%s line editing\r\n", (mode&MODE_EDIT) ? "Local" : "No");
+		printf("%s catching of signals\r\n",
+					(mode&MODE_TRAPSIG) ? "Local" : "No");
+		slcstate();
+#ifdef	KLUDGELINEMODE
+	    } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
+		printf("Operating in obsolete linemode\r\n");
+#endif
+	    } else {
+		printf("Operating in single character mode\r\n");
+		if (localchars)
+		    printf("Catching signals locally\r\n");
+	    }
+	    printf("%s character echo\r\n", (mode&MODE_ECHO) ? "Local" : "Remote");
+	    if (my_want_state_is_will(TELOPT_LFLOW))
+		printf("%s flow control\r\n", (mode&MODE_FLOW) ? "Local" : "No");
+#ifdef	ENCRYPTION
+	    encrypt_display();
+#endif	/* ENCRYPTION */
+	}
+    } else {
+	printf("No connection.\r\n");
+    }
+#   if !defined(TN3270)
+    printf("Escape character is '%s'.\r\n", control(escape));
+    (void) fflush(stdout);
+#   else /* !defined(TN3270) */
+    if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
+	printf("Escape character is '%s'.\r\n", control(escape));
+    }
+#   if defined(unix)
+    if ((argc >= 2) && !strcmp(argv[1], "everything")) {
+	printf("SIGIO received %d time%s.\r\n",
+				sigiocount, (sigiocount == 1)? "":"s");
+	if (In3270) {
+	    printf("Process ID %d, process group %d.\r\n",
+					    getpid(), getpgrp(getpid()));
+	    printf("Terminal input:\r\n");
+	    filestuff(tin);
+	    printf("Terminal output:\r\n");
+	    filestuff(tout);
+	    printf("Network socket:\r\n");
+	    filestuff(net);
+	}
+    }
+    if (In3270 && transcom) {
+       printf("Transparent mode command is '%s'.\r\n", transcom);
+    }
+#   endif /* defined(unix) */
+    (void) fflush(stdout);
+    if (In3270) {
+	return 0;
+    }
+#   endif /* defined(TN3270) */
+    return 1;
+}
+
+#ifdef	SIGINFO
+/*
+ * Function that gets called when SIGINFO is received.
+ */
+#if	defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO))
+void 
+ayt_status()
+{
+    (void) call(status, "status", "notmuch", 0);
+}
+#else
+int
+ayt_status()
+{
+    (void) call(status, "status", "notmuch", 0);
+    return 0;
+}
+#endif
+#endif
+
+    int
+tn(argc, argv)
+    int argc;
+    char *argv[];
+{
+#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
+    char *srp = 0;
+    int srlen;
+#endif
+    char *cmd, *hostp = 0, *portp = 0, *volatile user = 0;
+    struct addrinfo *addrs = 0, *addrp;
+    struct addrinfo hints;
+    int error;
+
+    if (connected) {
+	printf("?Already connected to %s\r\n", hostname);
+	return 0;
+    }
+    if (argc < 2) {
+	(void) strcpy(line, "open ");
+	printf("(to) ");
+	(void) fgets(&line[strlen(line)], (int) (sizeof(line) - strlen(line)),
+		     stdin);
+	makeargv();
+	argc = margc;
+	argv = margv;
+    }
+    cmd = *argv;
+    --argc; ++argv;
+    while (argc) {
+	if (isprefix(*argv, "?"))
+	    goto usage;
+	if (strcmp(*argv, "-l") == 0) {
+	    --argc; ++argv;
+	    if (argc == 0)
+		goto usage;
+	    user = *argv++;
+	    --argc;
+	    continue;
+	}
+	if (strcmp(*argv, "-a") == 0) {
+	    --argc; ++argv;
+	    autologin = 1;
+	    continue;
+	}
+	if (hostp == 0) {
+	    hostp = *argv++;
+	    --argc;
+	    continue;
+	}
+	if (portp == 0) {
+	    portp = *argv++;
+	    --argc;
+	    continue;
+	}
+    usage:
+	printf("usage: %s [-l user] [-a] host-name [port]\r\n", cmd);
+	return 0;
+    }
+    if (hostp == 0)
+	goto usage;
+
+    if (portp) {
+	if (*portp == '-') {
+	    portp++;
+	    telnetport = 1;
+	} else
+	    telnetport = 0;
+    } else {
+	portp = "telnet";
+	telnetport = 1;
+    }
+
+#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
+    if (hostp[0] == '@' || hostp[0] == '!') {
+	static struct sockaddr_in sr_sin4;
+	static struct addrinfo sr_addr;
+	unsigned long temp;
+	if ((hostname = strrchr(hostp, ':')) == NULL)
+	    hostname = strrchr(hostp, '@');
+	hostname++;
+	srp = 0;
+	temp = sourceroute(hostp, &srp, &srlen);
+	if (temp == 0) {
+	    herror(srp);
+	    return 0;
+	} else if (temp == -1) {
+	    printf("Bad source route option: %s\r\n", hostp);
+	    return 0;
+	} else {
+	    sr_sin4.sin_addr.s_addr = temp;
+	    sr_sin4.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+	    sr_sin4.sin_len = sizeof (sr_sin4);
+#endif
+	    sr_addr.ai_family = AF_INET;
+	    sr_addr.ai_addrlen = sizeof (sr_sin4);
+	    sr_addr.ai_addr = (struct sockaddr *) &sr_sin4;
+	    sr_addr.ai_next = 0;
+	    sr_addr.ai_canonname = hostname;
+	    addrs = &sr_addr;
+	}
+    } else {
+#endif
+	memset (&hints, 0, sizeof (hints));
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_family = PF_UNSPEC;
+
+
+	/* The GNU Libc (Red Hat Linux 6.1, on x86, which MIT is using
+	   at this time) implementation seems to completely ignore
+	   AI_NUMERICHOST, and contacts DNS anyways.  But other
+	   versions will not, and we do want to treat the two cases a
+	   little differently.  */
+#ifdef AF_INET6
+#define IS_NUMERIC_ADDR(P) \
+	('\0' == (P)[strspn((P), (strchr((P),':') ? "abcdefABCDEF:0123456789." : "0123456789."))])
+#else
+#define IS_NUMERIC_ADDR(P) \
+	('\0' == (P)[strspn((P), "0123456789.")])
+#endif
+	if (! IS_NUMERIC_ADDR (hostp))
+	    goto not_numeric;
+
+
+	hints.ai_flags = AI_NUMERICHOST;
+	error = getaddrinfo (hostp, portp, &hints, &addrs);
+	if (error == 0) {
+	    if (getnameinfo (addrs->ai_addr, addrs->ai_addrlen,
+			     _hostname, sizeof(_hostname), 0, 0, NI_NAMEREQD) != 0)
+		strncpy(_hostname, hostp, sizeof (_hostname));
+	    hostname = _hostname;
+	} else {
+	not_numeric:
+	    hints.ai_flags = AI_CANONNAME;
+	    error = getaddrinfo (hostp, portp, &hints, &addrs);
+	    if (error == 0) {
+
+		/* Stupid glibc lossage again.  */
+		if (! IS_NUMERIC_ADDR (addrs->ai_canonname)) {
+		    strncpy(_hostname, addrs->ai_canonname, sizeof(_hostname));
+		} else {
+		    fprintf (stderr,
+			     "telnet: system library bug? getaddrinfo returns numeric address\n"
+			     "\tas canonical name of %s\n",
+			     hostp);
+		    strncpy(_hostname, hostp, sizeof (_hostname));
+		}
+
+	    } else {
+		strncpy(_hostname, hostp, sizeof (_hostname));
+	    }
+	    hostname = _hostname;
+	}
+	if (error) {
+	    fprintf (stderr, "%s/%s: %s\n", hostp, portp, gai_strerror (error));
+	    return 0;
+	}
+#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
+    }
+#endif
+    for (addrp = addrs; addrp && !connected; addrp = addrp->ai_next) {
+	error = getnameinfo (addrp->ai_addr, addrp->ai_addrlen,
+			     hostaddrstring, sizeof (hostaddrstring),
+			     (char *) NULL, 0, NI_NUMERICHOST);
+	if (error) {
+	    fprintf (stderr, "getnameinfo() error printing address: %s\n",
+		     gai_strerror (error));
+	    strcpy (hostaddrstring, "[address unprintable]");
+	}
+	printf("Trying %s...\r\n", hostaddrstring);
+#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
+	if (srp && addrp->ai_family != AF_INET) {
+	    printf ("source routing not supported (yet) for address family,"
+		    " trying another address\n");
+	    continue;
+	}
+#endif
+	net = socket(addrp->ai_family, SOCK_STREAM, 0);
+	if (net < 0) {
+	    perror("telnet: socket");
+	    continue;
+	}
+#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
+	if (srp) {
+	    if (addrp->ai_family != AF_INET)
+		printf ("source routing not supported (yet)"
+			" for address family\n");
+	    else if (setsockopt(net, IPPROTO_IP, IP_OPTIONS,
+				(char *)srp, srlen) < 0)
+		perror("setsockopt (IP_OPTIONS)");
+	}
+#endif
+#if	defined(IPPROTO_IP) && defined(IP_TOS)
+	if (addrp->ai_family == AF_INET) {
+# if	defined(HAVE_GETTOSBYNAME)
+	    struct tosent *tp;
+	    if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+		tos = tp->t_tos;
+# endif
+	    if (tos < 0)
+		tos = 020;	/* Low Delay bit */
+	    if (tos
+		&& (setsockopt(net, IPPROTO_IP, IP_TOS,
+		    (char *)&tos, sizeof(int)) < 0)
+		&& (errno != ENOPROTOOPT))
+		    perror("telnet: setsockopt (IP_TOS) (ignored)");
+	}
+#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+	if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
+		perror("setsockopt (SO_DEBUG)");
+	}
+
+	if (connect(net, addrp->ai_addr, addrp->ai_addrlen) < 0) {
+	    if (hostaddrstring[0]) {
+		fprintf(stderr, "telnet: connect to address %s: %s\n",
+			hostaddrstring, strerror (errno));
+		(void) NetClose(net);
+		continue;
+	    }
+	}
+	connected++;
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+	auth_encrypt_connect(connected);
+#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+    }
+    if (!connected) {
+	perror("telnet: Unable to connect to remote host");
+	return 0;
+    }
+    if (user)
+      user = strdup(user);
+    if (hostp)
+      hostp = strdup(hostp);
+    cmdrc(hostp, hostname);
+    if (hostp)
+      free(hostp);
+    if (autologin && user == NULL) {
+	struct passwd *pw;
+
+	user = getenv("USER");
+	if (user == NULL ||
+	    ((pw = getpwnam(user)) && pw->pw_uid != getuid())) {
+	        pw = getpwuid(getuid());
+		if (pw)
+			user = pw->pw_name;
+		else
+			user = NULL;
+	}
+	if (user)
+	  user = strdup(user);
+    }
+    if (user) {
+	env_define((unsigned char *)"USER", (unsigned char *)user);
+	env_export((unsigned char *)"USER");
+    }
+    (void) call(status, "status", "notmuch", 0);
+    if (setjmp(peerdied) == 0)
+	telnet(user);
+    if (user)
+      free(user);
+    (void) NetClose(net);
+    ExitString("Connection closed by foreign host.\r\n",1);
+    /*NOTREACHED*/
+    return 0;
+}
+
+#define HELPINDENT ((int) sizeof ("connect"))
+
+static char
+	openhelp[] =	"connect to a site",
+	closehelp[] =	"close current connection",
+	logouthelp[] =	"forcibly logout remote user and close the connection",
+	quithelp[] =	"exit telnet",
+	statushelp[] =	"print status information",
+	helphelp[] =	"print help information",
+	sendhelp[] =	"transmit special characters ('send ?' for more)",
+	sethelp[] = 	"set operating parameters ('set ?' for more)",
+	unsethelp[] = 	"unset operating parameters ('unset ?' for more)",
+	togglestring[] ="toggle operating parameters ('toggle ?' for more)",
+	slchelp[] =	"change state of special charaters ('slc ?' for more)",
+	displayhelp[] =	"display operating parameters",
+#if	defined(TN3270) && defined(unix)
+	transcomhelp[] = "specify Unix command for transparent mode pipe",
+#endif	/* defined(TN3270) && defined(unix) */
+#if	defined(AUTHENTICATION)
+	authhelp[] =	"turn on (off) authentication ('auth ?' for more)",
+#endif
+#ifdef	ENCRYPTION
+	encrypthelp[] =	"turn on (off) encryption ('encrypt ?' for more)",
+#endif	/* ENCRYPTION */
+#ifdef  FORWARD
+	forwardhelp[] = "turn on (off) credential forwarding ('forward ?' for more)",
+#endif
+#if	defined(unix)
+	zhelp[] =	"suspend telnet",
+#endif	/* defined(unix) */
+	shellhelp[] =	"invoke a subshell",
+	envhelp[] =	"change environment variables ('environ ?' for more)",
+	modestring[] = "try to enter line or character mode ('mode ?' for more)";
+
+static int	help();
+
+static Command cmdtab[] = {
+	{ "close",	closehelp,	bye,		1 },
+	{ "logout",	logouthelp,	logout,		1 },
+	{ "display",	displayhelp,	display,	0 },
+	{ "mode",	modestring,	modecmd,	0 },
+	{ "open",	openhelp,	tn,		0 },
+	{ "quit",	quithelp,	quit,		0 },
+	{ "send",	sendhelp,	sendcmd,	0 },
+	{ "set",	sethelp,	setcmd,		0 },
+	{ "unset",	unsethelp,	unsetcmd,	0 },
+	{ "status",	statushelp,	status,		0 },
+	{ "toggle",	togglestring,	toggle,		0 },
+	{ "slc",	slchelp,	slccmd,		0 },
+#if	defined(TN3270) && defined(unix)
+	{ "transcom",	transcomhelp,	settranscom,	0 },
+#endif	/* defined(TN3270) && defined(unix) */
+#if	defined(AUTHENTICATION)
+	{ "auth",	authhelp,	auth_cmd,	0 },
+#endif
+#ifdef	ENCRYPTION
+	{ "encrypt",	encrypthelp,	encrypt_cmd,	0 },
+#endif	/* ENCRYPTION */
+#ifdef  FORWARD
+	{ "forward",    forwardhelp,    forw_cmd,       0 },
+#endif
+#if	defined(unix)
+	{ "z",		zhelp,		suspend,	0 },
+#endif	/* defined(unix) */
+#if	defined(TN3270)
+	{ "!",		shellhelp,	shell,		1 },
+#else
+	{ "!",		shellhelp,	shell,		0 },
+#endif
+	{ "environ",	envhelp,	env_cmd,	0 },
+	{ "?",		helphelp,	help,		0 },
+	{  0,           0,              0,              0 }
+};
+
+static char	crmodhelp[] =	"deprecated command -- use 'toggle crmod' instead";
+static char	escapehelp[] =	"deprecated command -- use 'set escape' instead";
+
+static Command cmdtab2[] = {
+	{ "help",	0,		help,		0 },
+	{ "escape",	escapehelp,	setescape,	0 },
+	{ "crmod",	crmodhelp,	togcrmod,	0 },
+	{  0,           0,              0,              0 }
+};
+
+
+/*
+ * Call routine with argc, argv set from args (terminated by 0).
+ */
+
+    /*VARARGS1*/
+static int
+#ifdef HAVE_STDARG_H
+call(intrtn_t routine, ...)
+#else
+call(routine, va_alist)
+    intrtn_t routine;
+    va_dcl
+#endif
+{
+    va_list ap;
+    char *args[100];
+    int argno = 0;
+
+#ifdef HAVE_STDARG_H
+    va_start(ap, routine);
+#else
+    va_start(ap);
+#endif
+
+    while ((args[argno++] = va_arg(ap, char *)) != 0) {
+	;
+    }
+    va_end(ap);
+    return (*routine)(argno-1, args);
+}
+
+
+    static Command *
+getcmd(name)
+    char *name;
+{
+    Command *cm;
+
+    if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command))))
+	return cm;
+    return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
+}
+
+    void
+command(top, tbuf, cnt)
+    int top;
+    char *tbuf;
+    int cnt;
+{
+    register Command *c;
+
+    setcommandmode();
+    if (!top) {
+	putchar('\n');
+#if	defined(unix)
+    } else {
+	(void) signal(SIGINT, SIG_DFL);
+	(void) signal(SIGQUIT, SIG_DFL);
+#endif	/* defined(unix) */
+    }
+    for (;;) {
+	if (rlogin == _POSIX_VDISABLE)
+		printf("%s> ", prompt);
+	if (tbuf) {
+	    register char *cp;
+	    cp = line;
+	    while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
+		cnt--;
+	    tbuf = 0;
+	    if (cp == line || *--cp != '\n' || cp == line)
+		goto getline;
+	    *cp = '\0';
+	    if (rlogin == _POSIX_VDISABLE)
+	        printf("%s\r\n", line);
+	} else {
+	getline:
+	    if (rlogin != _POSIX_VDISABLE)
+		printf("%s> ", prompt);
+	    if (fgets(line, sizeof(line), stdin) == NULL) {
+		if (feof(stdin) || ferror(stdin)) {
+		    (void) quit(0, NULL);
+		    /*NOTREACHED*/
+		}
+		break;
+	    }
+	}
+	if (line[0] == 0)
+	    break;
+	makeargv();
+	if (margv[0] == 0) {
+	    break;
+	}
+	c = getcmd(margv[0]);
+	if (Ambiguous(c)) {
+	    printf("?Ambiguous command\r\n");
+	    continue;
+	}
+	if (c == 0) {
+	    printf("?Invalid command\r\n");
+	    continue;
+	}
+	if (c->needconnect && !connected) {
+	    printf("?Need to be connected first.\r\n");
+	    continue;
+	}
+	if ((*c->handler)(margc, margv)) {
+	    break;
+	}
+    }
+    if (!top) {
+	if (!connected) {
+	    longjmp(toplevel, 1);
+	    /*NOTREACHED*/
+	}
+#if	defined(TN3270)
+	if (shell_active == 0) {
+	    setconnmode(0);
+	}
+#else	/* defined(TN3270) */
+	setconnmode(0);
+#endif	/* defined(TN3270) */
+    }
+}
+
+/*
+ * Help command.
+ */
+static int
+help(argc, argv)
+	int argc;
+	char *argv[];
+{
+	register Command *c;
+
+	if (argc == 1) {
+		printf("Commands may be abbreviated.  Commands are:\r\n\r\n");
+		for (c = cmdtab; c->name; c++)
+			if (c->help) {
+				printf("%-*s\t%s\r\n", HELPINDENT, c->name,
+								    c->help);
+			}
+		return 0;
+	}
+	while (--argc > 0) {
+		register char *arg;
+		arg = *++argv;
+		c = getcmd(arg);
+		if (Ambiguous(c))
+			printf("?Ambiguous help command %s\r\n", arg);
+		else if (c == (Command *)0)
+			printf("?Invalid help command %s\r\n", arg);
+		else
+			printf("%s\r\n", c->help);
+	}
+	return 0;
+}
+
+static char *rcname = 0;
+static char rcbuf[128];
+
+void
+cmdrc(m1, m2)
+	char *m1, *m2;
+{
+    register Command *c;
+    FILE *rcfile;
+    int gotmachine = 0;
+    unsigned int l1 = strlen(m1);
+    unsigned int l2 = strlen(m2);
+    char m1save[64];
+
+    if (skiprc)
+	return;
+
+    strncpy(m1save, m1, sizeof(m1save) - 1);
+    m1save[sizeof(m1save) - 1] = '\0';
+    m1 = m1save;
+
+    if (rcname == 0) {
+	rcname = getenv("HOME");
+	if (rcname)
+	    strncpy(rcbuf, rcname, sizeof(rcbuf) - 1);
+	else
+	    rcbuf[0] = '\0';
+	rcbuf[sizeof(rcbuf) - 1] = '\0';
+	strncat(rcbuf, "/.telnetrc", sizeof(rcbuf) - 1 - strlen(rcbuf));
+	rcname = rcbuf;
+    }
+
+    if ((rcfile = fopen(rcname, "r")) == 0) {
+	return;
+    }
+
+    for (;;) {
+	if (fgets(line, sizeof(line), rcfile) == NULL)
+	    break;
+	if (line[0] == 0)
+	    break;
+	if (line[0] == '#')
+	    continue;
+	if (gotmachine) {
+	    if (!isspace((int) line[0]))
+		gotmachine = 0;
+	}
+	if (gotmachine == 0) {
+	    if (isspace((int) line[0]))
+		continue;
+	    if (strncasecmp(line, m1, l1) == 0)
+		strncpy(line, &line[l1], sizeof(line) - l1);
+	    else if (strncasecmp(line, m2, l2) == 0)
+		strncpy(line, &line[l2], sizeof(line) - l2);
+	    else if (strncasecmp(line, "DEFAULT", 7) == 0)
+		strncpy(line, &line[7], sizeof(line) - 7);
+	    else
+		continue;
+	    if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
+		continue;
+	    gotmachine = 1;
+	}
+	makeargv();
+	if (margv[0] == 0)
+	    continue;
+	c = getcmd(margv[0]);
+	if (Ambiguous(c)) {
+	    printf("?Ambiguous command: %s\r\n", margv[0]);
+	    continue;
+	}
+	if (c == 0) {
+	    printf("?Invalid command: %s\r\n", margv[0]);
+	    continue;
+	}
+	/*
+	 * This should never happen...
+	 */
+	if (c->needconnect && !connected) {
+	    printf("?Need to be connected first for %s.\r\n", margv[0]);
+	    continue;
+	}
+	(*c->handler)(margc, margv);
+    }
+    fclose(rcfile);
+}
+
+#if	defined(IP_OPTIONS) && defined(IPPROTO_IP)
+
+/*
+ * Source route is handed in as
+ *	[!]@hop1@hop2...[@|:]dst
+ * If the leading ! is present, it is a
+ * strict source route, otherwise it is
+ * assmed to be a loose source route.
+ *
+ * We fill in the source route option as
+ *	hop1,hop2,hop3...dest
+ * and return a pointer to hop1, which will
+ * be the address to connect() to.
+ *
+ * Arguments:
+ *	arg:	pointer to route list to decipher
+ *
+ *	cpp: 	If *cpp is not equal to NULL, this is a
+ *		pointer to a pointer to a character array
+ *		that should be filled in with the option.
+ *
+ *	lenp:	pointer to an integer that contains the
+ *		length of *cpp if *cpp != NULL.
+ *
+ * Return values:
+ *
+ *	Returns the address of the host to connect to.  If the
+ *	return value is -1, there was a syntax error in the
+ *	option, either unknown characters, or too many hosts.
+ *	If the return value is 0, one of the hostnames in the
+ *	path is unknown, and *cpp is set to point to the bad
+ *	hostname.
+ *
+ *	*cpp:	If *cpp was equal to NULL, it will be filled
+ *		in with a pointer to our static area that has
+ *		the option filled in.  This will be 32bit aligned.
+ * 
+ *	*lenp:	This will be filled in with how long the option
+ *		pointed to by *cpp is.
+ *	
+ */
+static	unsigned long
+sourceroute(arg, cpp, lenp)
+	char	*arg;
+	char	**cpp;
+	int	*lenp;
+{
+	static char lsr[44];
+#ifdef	sysV88
+	static IOPTN ipopt;
+#endif
+	char *cp, *cp2, *lsrp, *lsrep;
+	register int tmp;
+	struct in_addr sin_addr;
+	register struct hostent *host = 0;
+	register char c;
+
+	/*
+	 * Verify the arguments, and make sure we have
+	 * at least 7 bytes for the option.
+	 */
+	if (cpp == NULL || lenp == NULL)
+		return((unsigned long)-1);
+	if (*cpp != NULL && *lenp < 7)
+		return((unsigned long)-1);
+	/*
+	 * Decide whether we have a buffer passed to us,
+	 * or if we need to use our own static buffer.
+	 */
+	if (*cpp) {
+		lsrp = *cpp;
+		lsrep = lsrp + *lenp;
+	} else {
+		*cpp = lsrp = lsr;
+		lsrep = lsrp + 44;
+	}
+
+	cp = arg;
+
+	/*
+	 * Next, decide whether we have a loose source
+	 * route or a strict source route, and fill in
+	 * the begining of the option.
+	 */
+#ifndef	sysV88
+	if (*cp == '!') {
+		cp++;
+		*lsrp++ = IPOPT_SSRR;
+	} else
+		*lsrp++ = IPOPT_LSRR;
+#else
+	if (*cp == '!') {
+		cp++;
+		ipopt.io_type = IPOPT_SSRR;
+	} else
+		ipopt.io_type = IPOPT_LSRR;
+#endif
+
+	if (*cp != '@')
+		return((unsigned long)-1);
+
+#ifndef	sysV88
+	lsrp++;		/* skip over length, we'll fill it in later */
+	*lsrp++ = 4;
+#endif
+
+	cp++;
+
+	sin_addr.s_addr = 0;
+
+	for (c = 0;;) {
+		if (c == ':')
+			cp2 = 0;
+		else for (cp2 = cp; (c = *cp2); cp2++) {
+			if (c == ',') {
+				*cp2++ = '\0';
+				if (*cp2 == '@')
+					cp2++;
+			} else if (c == '@') {
+				*cp2++ = '\0';
+			} else if (c == ':') {
+				*cp2++ = '\0';
+			} else
+				continue;
+			break;
+		}
+		if (!c)
+			cp2 = 0;
+
+		if ((tmp = inet_addr(cp)) != -1) {
+			sin_addr.s_addr = tmp;
+		} else if ((host = gethostbyname(cp))) {
+#if	defined(h_addr)
+			memcpy((caddr_t)&sin_addr,
+				host->h_addr_list[0], sizeof(sin_addr));
+#else
+			memcpy((caddr_t)&sin_addr, host->h_addr, 
+			       sizeof(sin_addr));
+#endif
+		} else {
+			*cpp = cp;
+			return(0);
+		}
+		memcpy(lsrp, (char *)&sin_addr, 4);
+		lsrp += 4;
+		if (cp2)
+			cp = cp2;
+		else
+			break;
+		/*
+		 * Check to make sure there is space for next address
+		 */
+		if (lsrp + 4 > lsrep)
+			return((unsigned long)-1);
+	}
+#ifndef	sysV88
+	if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
+		*cpp = 0;
+		*lenp = 0;
+		return((unsigned long)-1);
+	}
+	*lsrp++ = IPOPT_NOP; /* 32 bit word align it */
+	*lenp = lsrp - *cpp;
+#else
+	ipopt.io_len = lsrp - *cpp;
+	if (ipopt.io_len <= 5) {		/* Is 3 better ? */
+		*cpp = 0;
+		*lenp = 0;
+		return((unsigned long)-1);
+	}
+	*lenp = sizeof(ipopt);
+	*cpp = (char *) &ipopt;
+#endif
+	return(sin_addr.s_addr);
+}
+#endif
diff --git a/krb5-1-6/src/appl/telnet/telnet/defines.h b/krb5-1-6/src/appl/telnet/telnet/defines.h
new file mode 100644
index 000000000..0978173ea
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/defines.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)defines.h	8.1 (Berkeley) 6/6/93
+ */
+
+#define	settimer(x)	clocks.x = clocks.system++
+
+#if	!defined(TN3270)
+
+#define	SetIn3270()
+
+#endif	/* !defined(TN3270) */
+
+#define	NETADD(c)	{ *netoring.supply = c; ring_supplied(&netoring, 1); }
+#define	NET2ADD(c1,c2)	{ NETADD(c1); NETADD(c2); }
+#define	NETBYTES()	(ring_full_count(&netoring))
+#define	NETROOM()	(ring_empty_count(&netoring))
+
+#define	TTYADD(c)	if (!(SYNCHing||flushout)) { \
+				*ttyoring.supply = c; \
+				ring_supplied(&ttyoring, 1); \
+			}
+#define	TTYBYTES()	(ring_full_count(&ttyoring))
+#define	TTYROOM()	(ring_empty_count(&ttyoring))
+
+/*	Various modes */
+#define	MODE_LOCAL_CHARS(m)	((m)&(MODE_EDIT|MODE_TRAPSIG))
+#define	MODE_LOCAL_ECHO(m)	((m)&MODE_ECHO)
+#define	MODE_COMMAND_LINE(m)	((m)==-1)
+
+#define	CONTROL(x)	((x)&0x1f)		/* CTRL(x) is not portable */
diff --git a/krb5-1-6/src/appl/telnet/telnet/externs.h b/krb5-1-6/src/appl/telnet/telnet/externs.h
new file mode 100644
index 000000000..3d098adff
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/externs.h
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)externs.h	8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+
+#ifndef	BSD
+# define BSD 43
+#endif
+
+/*
+ * ucb stdio.h defines BSD as something wierd
+ */
+#if defined(sun) && defined(__svr4__)
+#define BSD 43
+#endif
+
+#ifndef	USE_TERMIO
+# if BSD > 43 || defined(SYSV_TERMIO)
+#  define USE_TERMIO
+# endif
+#endif
+
+#include <stdio.h>
+#include <setjmp.h>
+#if defined(CRAY) && !defined(NO_BSD_SETJMP)
+#include <bsdsetjmp.h>
+#endif
+#include <sys/ioctl.h>
+#ifdef	HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#ifdef CRAY
+# include <errno.h>
+#endif /* CRAY */
+#ifdef	USE_TERMIO
+# ifndef	VINTR
+#  ifdef SYSV_TERMIO
+#   include <sys/termio.h>
+#  else
+#   include <termios.h>
+#  endif
+# endif
+#endif
+#if defined(USE_TERMIO) && !defined(SYSV_TERMIO)
+# define termio termios
+#endif
+#if defined(NO_CC_T) || !defined(USE_TERMIO)
+# if !defined(USE_TERMIO)
+typedef char cc_t;
+# else
+typedef unsigned char cc_t;
+# endif
+#endif
+
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *malloc(), *calloc(), *realloc();
+#endif
+
+#ifndef	HAVE_STRING_H
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+
+#ifndef	_POSIX_VDISABLE
+# ifdef sun
+#  include <sys/param.h>	/* pick up VDISABLE definition, mayby */
+# endif
+# ifdef VDISABLE
+#  define _POSIX_VDISABLE VDISABLE
+# else
+#  define _POSIX_VDISABLE ((cc_t)'\377')
+# endif
+#endif
+
+#define	SUBBUFSIZE	256
+
+extern int
+    autologin,		/* Autologin enabled */
+    skiprc,		/* Don't process the ~/.telnetrc file */
+    eight,		/* use eight bit mode (binary in and/or out */
+    flushout,		/* flush output */
+    connected,		/* Are we connected to the other side? */
+    globalmode,		/* Mode tty should be in */
+    In3270,			/* Are we in 3270 mode? */
+    telnetport,		/* Are we connected to the telnet port? */
+    localflow,		/* Flow control handled locally */
+    restartany,		/* If flow control, restart output on any character */
+    localchars,		/* we recognize interrupt/quit */
+    donelclchars,		/* the user has set "localchars" */
+    showoptions,
+    wantencryption,	/* User has requested encryption */
+    net,		/* Network file descriptor */
+    tin,		/* Terminal input file descriptor */
+    tout,		/* Terminal output file descriptor */
+    crlf,		/* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
+    autoflush,		/* flush output when interrupting? */
+    autosynch,		/* send interrupt characters with SYNCH? */
+    SYNCHing,		/* Is the stream in telnet SYNCH mode? */
+    donebinarytoggle,	/* the user has put us in binary */
+    dontlecho,		/* do we suppress local echoing right now? */
+    crmod,
+    netdata,		/* Print out network data flow */
+    prettydump,		/* Print "netdata" output in user readable format */
+#if	defined(TN3270)
+    cursesdata,		/* Print out curses data flow */
+    apitrace,		/* Trace API transactions */
+#endif	/* defined(TN3270) */
+    termdata,		/* Print out terminal data flow */
+    debug;			/* Debug level */
+
+extern int intr_happened, intr_waiting;	/* for interrupt handling */
+
+extern cc_t escape;	/* Escape to command mode */
+extern cc_t rlogin;	/* Rlogin mode escape character */
+#ifdef	KLUDGELINEMODE
+extern cc_t echoc;	/* Toggle local echoing */
+#endif
+
+extern char
+    *prompt;		/* Prompt for command. */
+
+extern char
+    doopt[],
+    dont[],
+    will[],
+    wont[],
+    options[],		/* All the little options */
+    *hostname;		/* Who are we connected to? */
+#ifdef	ENCRYPTION
+extern void (*encrypt_output) (unsigned char *, int);
+extern int (*decrypt_input) (int);
+#endif	/* ENCRYPTION */
+
+/*
+ * We keep track of each side of the option negotiation.
+ */
+
+#define	MY_STATE_WILL		0x01
+#define	MY_WANT_STATE_WILL	0x02
+#define	MY_STATE_DO		0x04
+#define	MY_WANT_STATE_DO	0x08
+
+/*
+ * Macros to check the current state of things
+ */
+
+#define	my_state_is_do(opt)		(options[opt]&MY_STATE_DO)
+#define	my_state_is_will(opt)		(options[opt]&MY_STATE_WILL)
+#define my_want_state_is_do(opt)	(options[opt]&MY_WANT_STATE_DO)
+#define my_want_state_is_will(opt)	(options[opt]&MY_WANT_STATE_WILL)
+
+#define	my_state_is_dont(opt)		(!my_state_is_do(opt))
+#define	my_state_is_wont(opt)		(!my_state_is_will(opt))
+#define my_want_state_is_dont(opt)	(!my_want_state_is_do(opt))
+#define my_want_state_is_wont(opt)	(!my_want_state_is_will(opt))
+
+#define	set_my_state_do(opt)		{options[opt] |= MY_STATE_DO;}
+#define	set_my_state_will(opt)		{options[opt] |= MY_STATE_WILL;}
+#define	set_my_want_state_do(opt)	{options[opt] |= MY_WANT_STATE_DO;}
+#define	set_my_want_state_will(opt)	{options[opt] |= MY_WANT_STATE_WILL;}
+
+#define	set_my_state_dont(opt)		{options[opt] &= ~MY_STATE_DO;}
+#define	set_my_state_wont(opt)		{options[opt] &= ~MY_STATE_WILL;}
+#define	set_my_want_state_dont(opt)	{options[opt] &= ~MY_WANT_STATE_DO;}
+#define	set_my_want_state_wont(opt)	{options[opt] &= ~MY_WANT_STATE_WILL;}
+
+/*
+ * Make everything symetrical
+ */
+
+#define	HIS_STATE_WILL			MY_STATE_DO
+#define	HIS_WANT_STATE_WILL		MY_WANT_STATE_DO
+#define HIS_STATE_DO			MY_STATE_WILL
+#define HIS_WANT_STATE_DO		MY_WANT_STATE_WILL
+
+#define	his_state_is_do			my_state_is_will
+#define	his_state_is_will		my_state_is_do
+#define his_want_state_is_do		my_want_state_is_will
+#define his_want_state_is_will		my_want_state_is_do
+
+#define	his_state_is_dont		my_state_is_wont
+#define	his_state_is_wont		my_state_is_dont
+#define his_want_state_is_dont		my_want_state_is_wont
+#define his_want_state_is_wont		my_want_state_is_dont
+
+#define	set_his_state_do		set_my_state_will
+#define	set_his_state_will		set_my_state_do
+#define	set_his_want_state_do		set_my_want_state_will
+#define	set_his_want_state_will		set_my_want_state_do
+
+#define	set_his_state_dont		set_my_state_wont
+#define	set_his_state_wont		set_my_state_dont
+#define	set_his_want_state_dont		set_my_want_state_wont
+#define	set_his_want_state_wont		set_my_want_state_dont
+
+
+extern FILE
+    *NetTrace;		/* Where debugging output goes */
+extern unsigned char
+    NetTraceFile[];	/* Name of file where debugging output goes */
+extern void
+    SetNetTrace (char *);	/* Function to change where debugging goes */
+
+extern jmp_buf
+    peerdied,
+    toplevel;		/* For error conditions. */
+
+extern void
+    command (int, char *, int),
+    Dump (int, unsigned char *, int),
+    init_3270 (void),
+    init_terminal (void),
+    init_telnet (void),
+    init_network (void),
+    init_sys (void),
+    printoption (char *, int, int),
+    printsub (int, unsigned char *, int),
+    sendnaws (void),
+    sendabort (void),
+    sendeof (void),
+    sendayt (void),
+    sendsusp (void),
+    setconnmode (int),
+    setcommandmode (void),
+    setneturg (void),
+    set_escape_char (char *),
+    sys_telnet_init (void),
+    telnet (char *),
+    tel_enter_binary (int),
+    tel_leave_binary (int),
+    TerminalDefaultChars (void),
+    TerminalFlushOutput (void),
+    TerminalNewMode (int),
+    TerminalRestoreState (void),
+    TerminalSaveState (void),
+    TerminalSpeeds (long *, long *),
+    tninit (void),
+    upcase (char *),
+    willoption (int),
+    wontoption (int);
+
+extern void
+    send_do (int, int),
+    send_dont (int, int),
+    send_will (int, int),
+    send_wont (int, int);
+
+extern void
+    sendbrk (void),
+    intp (void),
+    xmitAO (void),
+    xmitEL (void),
+    xmitEC (void);
+
+extern void
+    lm_will (unsigned char *, int),
+    lm_wont (unsigned char *, int),
+    lm_do (unsigned char *, int),
+    lm_dont (unsigned char *, int),
+    lm_mode (unsigned char *, int, int);
+
+extern void
+    ExitString (char *, int), 
+    Exit (int),
+    SetForExit (void),
+    EmptyTerminal (void),
+    slc_init (void),
+    slcstate (void),
+    slc_mode_export (void),
+    slc_mode_import (int),
+    slc_import (int),
+    slc_export (void),
+    slc (unsigned char *, int),
+    slc_check (void),
+    slc_start_reply (void),
+    slc_add_reply (int, int, int),
+    slc_end_reply (void);
+
+extern int
+    quit (int, char *[]), 
+    ttyflush (int),
+    rlogin_susp (void),
+    tn (int, char **),
+    getconnmode (void),
+    netflush (void),
+    NetClose (int),
+    opt_welldefined (char *),
+    process_rings (int, int, int, int, int, int),
+    slc_update (void),
+    Scheduler (int),
+    SetSockOpt (int, int, int, int),
+    stilloob (void), 
+    telrcv (void),
+    telnet_spin (void),
+    TerminalWrite (unsigned char *, int),
+    TerminalRead (unsigned char *, int),
+    TerminalAutoFlush (void),
+    TerminalSpecialChars (int),
+    TerminalWindowSize (long *, long *);
+
+
+extern void
+    env_init (void),
+    env_opt (unsigned char *, int),
+    env_opt_start (void),
+    env_opt_start_info (void),
+    env_opt_add (unsigned char *),
+    env_opt_end (int),
+    optionstatus (void);
+
+extern unsigned char
+    *env_default (int, int),
+    *env_getvalue (unsigned char *);
+
+extern int
+    env_is_exported (unsigned char *);
+
+extern int
+    get_status (char *),
+    dosynch (char *);
+
+extern cc_t
+    *tcval (int);
+
+#ifndef	USE_TERMIO
+
+extern struct	tchars ntc;
+extern struct	ltchars nltc;
+extern struct	sgttyb nttyb;
+
+# define termEofChar		ntc.t_eofc
+# define termEraseChar		nttyb.sg_erase
+# define termFlushChar		nltc.t_flushc
+# define termIntChar		ntc.t_intrc
+# define termKillChar		nttyb.sg_kill
+# define termLiteralNextChar	nltc.t_lnextc
+# define termQuitChar		ntc.t_quitc
+# define termSuspChar		nltc.t_suspc
+# define termRprntChar		nltc.t_rprntc
+# define termWerasChar		nltc.t_werasc
+# define termStartChar		ntc.t_startc
+# define termStopChar		ntc.t_stopc
+# define termForw1Char		ntc.t_brkc
+extern cc_t termForw2Char;
+extern cc_t termAytChar;
+
+# define termEofCharp		(cc_t *)&ntc.t_eofc
+# define termEraseCharp		(cc_t *)&nttyb.sg_erase
+# define termFlushCharp		(cc_t *)&nltc.t_flushc
+# define termIntCharp		(cc_t *)&ntc.t_intrc
+# define termKillCharp		(cc_t *)&nttyb.sg_kill
+# define termLiteralNextCharp	(cc_t *)&nltc.t_lnextc
+# define termQuitCharp		(cc_t *)&ntc.t_quitc
+# define termSuspCharp		(cc_t *)&nltc.t_suspc
+# define termRprntCharp		(cc_t *)&nltc.t_rprntc
+# define termWerasCharp		(cc_t *)&nltc.t_werasc
+# define termStartCharp		(cc_t *)&ntc.t_startc
+# define termStopCharp		(cc_t *)&ntc.t_stopc
+# define termForw1Charp		(cc_t *)&ntc.t_brkc
+# define termForw2Charp		(cc_t *)&termForw2Char
+# define termAytCharp		(cc_t *)&termAytChar
+
+# else
+
+extern struct	termio new_tc;
+
+# define termEofChar		new_tc.c_cc[VEOF]
+# define termEraseChar		new_tc.c_cc[VERASE]
+# define termIntChar		new_tc.c_cc[VINTR]
+# define termKillChar		new_tc.c_cc[VKILL]
+# define termQuitChar		new_tc.c_cc[VQUIT]
+
+# ifndef	VSUSP
+extern cc_t termSuspChar;
+# else
+#  define termSuspChar		new_tc.c_cc[VSUSP]
+# endif
+# if	defined(VFLUSHO) && !defined(VDISCARD)
+#  define VDISCARD VFLUSHO
+# endif
+# ifndef	VDISCARD
+extern cc_t termFlushChar;
+# else
+#  define termFlushChar		new_tc.c_cc[VDISCARD]
+# endif
+# ifndef VWERASE
+extern cc_t termWerasChar;
+# else
+#  define termWerasChar		new_tc.c_cc[VWERASE]
+# endif
+# ifndef	VREPRINT
+extern cc_t termRprntChar;
+# else
+#  define termRprntChar		new_tc.c_cc[VREPRINT]
+# endif
+# ifndef	VLNEXT
+extern cc_t termLiteralNextChar;
+# else
+#  define termLiteralNextChar	new_tc.c_cc[VLNEXT]
+# endif
+# ifndef	VSTART
+extern cc_t termStartChar;
+# else
+#  define termStartChar		new_tc.c_cc[VSTART]
+# endif
+# ifndef	VSTOP
+extern cc_t termStopChar;
+# else
+#  define termStopChar		new_tc.c_cc[VSTOP]
+# endif
+# ifndef	VEOL
+extern cc_t termForw1Char;
+# else
+#  define termForw1Char		new_tc.c_cc[VEOL]
+# endif
+# ifndef	VEOL2
+extern cc_t termForw2Char;
+# else
+#  define termForw2Char		new_tc.c_cc[VEOL]
+# endif
+# ifndef	VSTATUS
+extern cc_t termAytChar;
+#else
+#  define termAytChar		new_tc.c_cc[VSTATUS]
+#endif
+
+# if !defined(CRAY) || defined(__STDC__)
+#  define termEofCharp		&termEofChar
+#  define termEraseCharp	&termEraseChar
+#  define termIntCharp		&termIntChar
+#  define termKillCharp		&termKillChar
+#  define termQuitCharp		&termQuitChar
+#  define termSuspCharp		&termSuspChar
+#  define termFlushCharp	&termFlushChar
+#  define termWerasCharp	&termWerasChar
+#  define termRprntCharp	&termRprntChar
+#  define termLiteralNextCharp	&termLiteralNextChar
+#  define termStartCharp	&termStartChar
+#  define termStopCharp		&termStopChar
+#  define termForw1Charp	&termForw1Char
+#  define termForw2Charp	&termForw2Char
+#  define termAytCharp		&termAytChar
+# else
+	/* Work around a compiler bug */
+#  define termEofCharp		0
+#  define termEraseCharp	0
+#  define termIntCharp		0
+#  define termKillCharp		0
+#  define termQuitCharp		0
+#  define termSuspCharp		0
+#  define termFlushCharp	0
+#  define termWerasCharp	0
+#  define termRprntCharp	0
+#  define termLiteralNextCharp	0
+#  define termStartCharp	0
+#  define termStopCharp		0
+#  define termForw1Charp	0
+#  define termForw2Charp	0
+#  define termAytCharp		0
+# endif
+#endif
+
+
+/* Ring buffer structures which are shared */
+
+extern Ring
+    netoring,
+    netiring,
+    ttyoring,
+    ttyiring;
+
+/* Tn3270 section */
+#if	defined(TN3270)
+
+extern int
+    HaveInput,		/* Whether an asynchronous I/O indication came in */
+    noasynchtty,	/* Don't do signals on I/O (SIGURG, SIGIO) */
+    noasynchnet,	/* Don't do signals on I/O (SIGURG, SIGIO) */
+    sigiocount,		/* Count of SIGIO receptions */
+    shell_active;	/* Subshell is active */
+
+extern char
+    *Ibackp,		/* Oldest byte of 3270 data */
+    Ibuf[],		/* 3270 buffer */
+    *Ifrontp,		/* Where next 3270 byte goes */
+    tline[200],
+    *transcom;		/* Transparent command */
+
+extern int
+    settranscom (int, char**);
+
+extern void
+    inputAvailable (int);
+#endif	/* defined(TN3270) */
diff --git a/krb5-1-6/src/appl/telnet/telnet/fdset.h b/krb5-1-6/src/appl/telnet/telnet/fdset.h
new file mode 100644
index 000000000..045bb7221
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/fdset.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)fdset.h	8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * The following is defined just in case someone should want to run
+ * this telnet on a 4.2 system.
+ *
+ */
+
+#ifndef	FD_SETSIZE
+
+#define	FD_SET(n, p)	((p)->fds_bits[0] |= (1<<(n)))
+#define	FD_CLR(n, p)	((p)->fds_bits[0] &= ~(1<<(n)))
+#define	FD_ISSET(n, p)	((p)->fds_bits[0] & (1<<(n)))
+#define FD_ZERO(p)	((p)->fds_bits[0] = 0)
+
+#endif
diff --git a/krb5-1-6/src/appl/telnet/telnet/general.h b/krb5-1-6/src/appl/telnet/telnet/general.h
new file mode 100644
index 000000000..4efa95194
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/general.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)general.h	8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Some general definitions.
+ */
+
+
+#define	numberof(x)	(sizeof x/sizeof x[0])
+#define	highestof(x)	(numberof(x)-1)
+
+#define	ClearElement(x)		memset((char *)&x, 0, sizeof x)
+#define	ClearArray(x)		memset((char *)x, 0, sizeof x)
diff --git a/krb5-1-6/src/appl/telnet/telnet/main.c b/krb5-1-6/src/appl/telnet/telnet/main.c
new file mode 100644
index 000000000..77832f912
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/main.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 1988, 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1988, 1990 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)main.c	5.5 (Berkeley) 12/18/92 */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <libtelnet/auth.h>
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+# include <netinet/in.h>
+
+#include "ring.h"
+#include "externs.h"
+#include "defines.h"
+
+#ifdef NEED_PARSETOS_PROTO
+extern int parsetos(char *, char *);
+#endif
+
+#if 0
+#define FORWARD
+#endif
+
+/*
+ * Initialize variables.
+ */
+    void
+tninit()
+{
+    init_terminal();
+
+    init_network();
+    
+    init_telnet();
+
+    init_sys();
+
+#if defined(TN3270)
+    init_3270();
+#endif
+}
+
+static void
+usage()
+{
+	fprintf(stderr, "Usage: %s %s%s%s%s\n",
+	    prompt,
+#ifdef	AUTHENTICATION
+	    " [-8] [-E] [-K] [-L] [-X atype] [-a] [-d] [-e char] [-k realm]",
+	    "\n\t[-l user] [-f/-F] [-n tracefile] ",
+#else
+	    " [-8] [-E] [-L] [-a] [-d] [-e char] [-l user] [-n tracefile]",
+	    "\n\t",
+#endif
+#if defined(TN3270) && defined(unix)
+# ifdef AUTHENTICATION
+	    "[-noasynch] [-noasynctty] [-noasyncnet]\n\t[-r] [-t transcom] ",
+# else
+	    "[-noasynch] [-noasynctty] [-noasyncnet] [-r] [-t transcom]\n\t",
+# endif
+#else
+	    "[-r] ",
+#endif
+#ifdef	ENCRYPTION
+	    "[-x] [host-name [port]]"
+#else
+	    "[host-name [port]]"
+#endif
+	);
+	exit(1);
+}
+
+/*
+ * main.  Parse arguments, invoke the protocol or command parser.
+ */
+
+/* see forward.c -- indicate that we're in telnet, not telnetd. */
+char *line = 0;
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	int ch;
+	char *user;
+#ifdef	FORWARD
+	extern int forward_flags;
+#endif	/* FORWARD */
+#ifdef ENCRYPTION
+	extern int auth_enable_encrypt;
+#endif /* ENCRYPTION */
+
+	tninit();		/* Clear out things */
+#if	defined(CRAY) && !defined(__STDC__)
+	_setlist_init();	/* Work around compiler bug */
+#endif
+
+	TerminalSaveState();
+
+	if ((prompt = strrchr(argv[0], '/')))
+		++prompt;
+	else
+		prompt = argv[0];
+
+	user = NULL;
+
+	rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
+	autologin = -1;
+
+	while ((ch = getopt(argc, argv, "8EKLS:X:acde:fFk:l:n:rt:x")) != -1) {
+		switch(ch) {
+		case '8':
+			eight = 3;	/* binary output and input */
+			break;
+		case 'E':
+			rlogin = escape = _POSIX_VDISABLE;
+			break;
+		case 'K':
+#ifdef	AUTHENTICATION
+			autologin = 0;
+#endif
+			break;
+		case 'L':
+			eight |= 2;	/* binary output only */
+			break;
+		case 'S':
+		    {
+#if defined(HAVE_GETTOSBYNAME) || (defined(IPPROTO_IP) && defined(IP_TOS))
+			extern int tos;
+
+			if ((tos = parsetos(optarg, "tcp")) < 0)
+				fprintf(stderr, "%s%s%s%s\n",
+					prompt, ": Bad TOS argument '",
+					optarg,
+					"; will try to use default TOS");
+
+                      fprintf(stderr, "Setting TOS to 0x%x\n", tos);
+#else
+			fprintf(stderr,
+			   "%s: Warning: -S ignored, no parsetos() support.\n",
+								prompt);
+#endif
+		    }
+			break;
+		case 'X':
+#ifdef	AUTHENTICATION
+			auth_disable_name(optarg);
+#endif
+			break;
+		case 'a':
+			autologin = 1;
+			break;
+		case 'c':
+			skiprc = 1;
+			break;
+		case 'd':
+			debug = 1;
+			break;
+		case 'e':
+			set_escape_char(optarg);
+			break;
+		case 'f':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+			if (forward_flags & OPTS_FORWARD_CREDS) {
+			    fprintf(stderr, 
+				    "%s: Only one of -f and -F allowed.\n",
+				    prompt);
+			    usage();
+			}
+			forward_flags |= OPTS_FORWARD_CREDS;
+#else
+			fprintf(stderr,
+			 "%s: Warning: -f ignored, no Kerberos V5 support.\n", 
+				prompt);
+#endif
+			break;
+		case 'F':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+			if (forward_flags & OPTS_FORWARD_CREDS) {
+			    fprintf(stderr, 
+				    "%s: Only one of -f and -F allowed.\n",
+				    prompt);
+			    usage();
+			}
+			forward_flags |= OPTS_FORWARD_CREDS;
+			forward_flags |= OPTS_FORWARDABLE_CREDS;
+#else
+			fprintf(stderr,
+			 "%s: Warning: -F ignored, no Kerberos V5 support.\n", 
+				prompt);
+#endif
+			break;
+		case 'k':
+#if defined(AUTHENTICATION) && defined(KRB4)
+		    {
+			extern char *dest_realm, dst_realm_buf[];
+			extern unsigned int dst_realm_sz;
+			dest_realm = dst_realm_buf;
+			(void)strncpy(dest_realm, optarg, dst_realm_sz);
+		    }
+#endif
+#if defined(AUTHENTICATION) && defined(KRB5)
+		    {
+			extern char *telnet_krb5_realm;
+
+			telnet_krb5_realm = optarg;
+			break;
+		    }
+#endif
+#if !defined(AUTHENTICATION) || (!defined(KRB4) && !defined(KRB5))
+			fprintf(stderr,
+			   "%s: Warning: -k ignored, no Kerberos V4 support.\n",
+								prompt);
+#endif
+			break;
+		case 'l':
+			autologin = 1;
+			user = optarg;
+			break;
+		case 'n':
+#if defined(TN3270) && defined(unix)
+			/* distinguish between "-n oasynch" and "-noasynch" */
+			if (argv[optind - 1][0] == '-' && argv[optind - 1][1]
+			    == 'n' && argv[optind - 1][2] == 'o') {
+				if (!strcmp(optarg, "oasynch")) {
+					noasynchtty = 1;
+					noasynchnet = 1;
+				} else if (!strcmp(optarg, "oasynchtty"))
+					noasynchtty = 1;
+				else if (!strcmp(optarg, "oasynchnet"))
+					noasynchnet = 1;
+			} else
+#endif	/* defined(TN3270) && defined(unix) */
+				SetNetTrace(optarg);
+			break;
+		case 'r':
+			rlogin = '~';
+			break;
+		case 't':
+#if defined(TN3270) && defined(unix)
+			transcom = tline;
+			(void)strncpy(transcom, optarg, sizeof(tline) - 1);
+			tline[sizeof(tline) - 1] = '\0';
+#else
+			fprintf(stderr,
+			   "%s: Warning: -t ignored, no TN3270 support.\n",
+								prompt);
+#endif
+			break;
+		case 'x':
+#ifdef	ENCRYPTION
+			encrypt_auto(1);
+			decrypt_auto(1);
+			wantencryption = 1;
+			autologin = 1;
+			auth_enable_encrypt = 1;
+#else
+			fprintf(stderr,
+			    "%s: Warning: -x ignored, no ENCRYPT support.\n",
+								prompt);
+#endif
+			break;
+		case '?':
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+	}
+	if (autologin == -1)
+		autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc) {
+		char *args[7], **volatile argp = args;
+
+		if (argc > 2)
+			usage();
+		*argp++ = prompt;
+		if (user) {
+			*argp++ = "-l";
+			*argp++ = user;
+		}
+		*argp++ = argv[0];		/* host */
+		if (argc > 1)
+			*argp++ = argv[1];	/* port */
+		*argp = 0;
+
+		if (setjmp(toplevel) != 0)
+			Exit(0);
+		if (tn(argp - args, args) == 1)
+			return (0);
+		else
+			return (1);
+	}
+	(void)setjmp(toplevel);
+	for (;;) {
+#ifdef TN3270
+		if (shell_active)
+			shell_continue();
+		else
+#endif
+			command(1, 0, 0);
+	}
+}
diff --git a/krb5-1-6/src/appl/telnet/telnet/network.c b/krb5-1-6/src/appl/telnet/telnet/network.c
new file mode 100644
index 000000000..60dc3bdcf
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/network.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)network.c	8.1 (Berkeley) 6/6/93 */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <errno.h>
+
+#include <arpa/telnet.h>
+
+#include "ring.h"
+
+#include "defines.h"
+#include "externs.h"
+#include "fdset.h"
+
+Ring		netoring, netiring;
+unsigned char	netobuf[2*TELNET_BUFSIZE], netibuf[TELNET_BUFSIZE];
+
+/*
+ * Initialize internal network data structures.
+ */
+
+    void
+init_network()
+{
+    if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
+	exit(1);
+    }
+    if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
+	exit(1);
+    }
+    NetTrace = stdout;
+}
+
+
+/*
+ * Check to see if any out-of-band data exists on a socket (for
+ * Telnet "synch" processing).
+ */
+
+    int
+stilloob()
+{
+    static struct timeval timeout = { 0 };
+    fd_set	excepts;
+    int value;
+
+    do {
+	FD_ZERO(&excepts);
+	FD_SET(net, &excepts);
+	value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
+    } while ((value == -1) && (errno == EINTR));
+
+    if (value < 0) {
+	perror("select");
+	(void) quit(0, NULL);
+	/* NOTREACHED */
+    }
+    if (FD_ISSET(net, &excepts)) {
+	return 1;
+    } else {
+	return 0;
+    }
+}
+
+
+/*
+ *  setneturg()
+ *
+ *	Sets "neturg" to the current location.
+ */
+
+    void
+setneturg()
+{
+    ring_mark(&netoring);
+}
+
+
+/*
+ *  netflush
+ *		Send as much data as possible to the network,
+ *	handling requests for urgent data.
+ *
+ *		The return value indicates whether we did any
+ *	useful work.
+ */
+
+
+    int
+netflush()
+{
+    register int n, n1;
+
+#ifdef	ENCRYPTION
+    if (encrypt_output)
+	ring_encrypt(&netoring, encrypt_output);
+#endif	/* ENCRYPTION */
+    if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
+	if (!ring_at_mark(&netoring)) {
+	    n = send(net, (char *)netoring.consume, n, 0); /* normal write */
+	} else {
+	    /*
+	     * In 4.2 (and 4.3) systems, there is some question about
+	     * what byte in a sendOOB operation is the "OOB" data.
+	     * To make ourselves compatible, we only send ONE byte
+	     * out of band, the one WE THINK should be OOB (though
+	     * we really have more the TCP philosophy of urgent data
+	     * rather than the Unix philosophy of OOB data).
+	     */
+	    n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
+	}
+    }
+    if (n < 0) {
+	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
+	    setcommandmode();
+	    perror(hostname);
+	    (void)NetClose(net);
+	    ring_clear_mark(&netoring);
+	    longjmp(peerdied, -1);
+	    /*NOTREACHED*/
+	}
+	n = 0;
+    }
+    if (netdata && n) {
+	Dump('>', netoring.consume, n);
+    }
+    if (n) {
+	ring_consumed(&netoring, n);
+	/*
+	 * If we sent all, and more to send, then recurse to pick
+	 * up the other half.
+	 */
+	if ((n1 == n) && ring_full_consecutive(&netoring)) {
+	    (void) netflush();
+	}
+	return 1;
+    } else {
+	return 0;
+    }
+}
diff --git a/krb5-1-6/src/appl/telnet/telnet/ring.c b/krb5-1-6/src/appl/telnet/telnet/ring.c
new file mode 100644
index 000000000..fdff682b5
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/ring.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)ring.c	8.1 (Berkeley) 6/6/93 */
+
+/*
+ * This defines a structure for a ring buffer.
+ *
+ * The circular buffer has two parts:
+ *(((
+ *	full:	[consume, supply)
+ *	empty:	[supply, consume)
+ *]]]
+ *
+ */
+
+#include	<stdio.h>
+#include	<errno.h>
+
+#ifdef	size_t
+#undef	size_t
+#endif
+
+#include	<sys/types.h>
+#ifndef	HAVE_SYS_FILIO_H
+#include	<sys/ioctl.h>
+#endif
+#include	<sys/socket.h>
+
+#include	"ring.h"
+#include	"general.h"
+
+#ifndef	NO_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/* Internal macros */
+
+#if	!defined(MIN)
+#define	MIN(a,b)	(((a)<(b))? (a):(b))
+#endif	/* !defined(MIN) */
+
+#define	ring_subtract(d,a,b)	(((a)-(b) >= 0)? \
+					(a)-(b): (((a)-(b))+(d)->size))
+
+#define	ring_increment(d,a,c)	(((a)+(c) < (d)->top)? \
+					(a)+(c) : (((a)+(c))-(d)->size))
+
+#define	ring_decrement(d,a,c)	(((a)-(c) >= (d)->bottom)? \
+					(a)-(c) : (((a)-(c))-(d)->size))
+
+
+/*
+ * The following is a clock, used to determine full, empty, etc.
+ *
+ * There is some trickiness here.  Since the ring buffers are initialized
+ * to ZERO on allocation, we need to make sure, when interpreting the
+ * clock, that when the times are EQUAL, then the buffer is FULL.
+ */
+static u_long ring_clock = 0;
+
+
+#define	ring_empty(d) (((d)->consume == (d)->supply) && \
+				((d)->consumetime >= (d)->supplytime))
+#define	ring_full(d) (((d)->supply == (d)->consume) && \
+				((d)->supplytime > (d)->consumetime))
+
+
+
+
+
+/* Buffer state transition routines */
+
+int
+ring_init(ring, buffer, count)
+Ring *ring;
+    unsigned char *buffer;
+    int count;
+{
+    memset((char *)ring, 0, sizeof *ring);
+
+    ring->size = count;
+
+    ring->supply = ring->consume = ring->bottom = buffer;
+
+    ring->top = ring->bottom+ring->size;
+
+#ifdef	ENCRYPTION
+    ring->clearto = 0;
+#endif	/* ENCRYPTION */
+
+    return 1;
+}
+
+/* Mark routines */
+
+/*
+ * Mark the most recently supplied byte.
+ */
+
+    void
+ring_mark(ring)
+    Ring *ring;
+{
+    ring->mark = ring_decrement(ring, ring->supply, 1);
+}
+
+/*
+ * Is the ring pointing to the mark?
+ */
+
+    int
+ring_at_mark(ring)
+    Ring *ring;
+{
+    if (ring->mark == ring->consume) {
+	return 1;
+    } else {
+	return 0;
+    }
+}
+
+/*
+ * Clear any mark set on the ring.
+ */
+
+    void
+ring_clear_mark(ring)
+    Ring *ring;
+{
+    ring->mark = 0;
+}
+
+/*
+ * Add characters from current segment to ring buffer.
+ */
+    void
+ring_supplied(ring, count)
+    Ring *ring;
+    int count;
+{
+    ring->supply = ring_increment(ring, ring->supply, count);
+    ring->supplytime = ++ring_clock;
+}
+
+/*
+ * We have just consumed "c" bytes.
+ */
+    void
+ring_consumed(ring, count)
+    Ring *ring;
+    int count;
+{
+    if (count == 0)	/* don't update anything */
+	return;
+
+    if (ring->mark &&
+		(ring_subtract(ring, ring->mark, ring->consume) < count)) {
+	ring->mark = 0;
+    }
+#ifdef	ENCRYPTION
+    if (ring->consume < ring->clearto &&
+		ring->clearto <= ring->consume + count)
+	ring->clearto = 0;
+    else if (ring->consume + count > ring->top &&
+		ring->bottom <= ring->clearto &&
+		ring->bottom + ((ring->consume + count) - ring->top))
+	ring->clearto = 0;
+#endif	/* ENCRYPTION */
+    ring->consume = ring_increment(ring, ring->consume, count);
+    ring->consumetime = ++ring_clock;
+    /*
+     * Try to encourage "ring_empty_consecutive()" to be large.
+     */
+    if (ring_empty(ring)) {
+	ring->consume = ring->supply = ring->bottom;
+    }
+}
+
+
+
+/* Buffer state query routines */
+
+
+/* Number of bytes that may be supplied */
+    int
+ring_empty_count(ring)
+    Ring *ring;
+{
+    if (ring_empty(ring)) {	/* if empty */
+	    return ring->size;
+    } else {
+	return ring_subtract(ring, ring->consume, ring->supply);
+    }
+}
+
+/* number of CONSECUTIVE bytes that may be supplied */
+    int
+ring_empty_consecutive(ring)
+    Ring *ring;
+{
+    if ((ring->consume < ring->supply) || ring_empty(ring)) {
+			    /*
+			     * if consume is "below" supply, or empty, then
+			     * return distance to the top
+			     */
+	return ring_subtract(ring, ring->top, ring->supply);
+    } else {
+				    /*
+				     * else, return what we may.
+				     */
+	return ring_subtract(ring, ring->consume, ring->supply);
+    }
+}
+
+/* Return the number of bytes that are available for consuming
+ * (but don't give more than enough to get to cross over set mark)
+ */
+
+    int
+ring_full_count(ring)
+    Ring *ring;
+{
+    if ((ring->mark == 0) || (ring->mark == ring->consume)) {
+	if (ring_full(ring)) {
+	    return ring->size;	/* nothing consumed, but full */
+	} else {
+	    return ring_subtract(ring, ring->supply, ring->consume);
+	}
+    } else {
+	return ring_subtract(ring, ring->mark, ring->consume);
+    }
+}
+
+/*
+ * Return the number of CONSECUTIVE bytes available for consuming.
+ * However, don't return more than enough to cross over set mark.
+ */
+    int
+ring_full_consecutive(ring)
+    Ring *ring;
+{
+    if ((ring->mark == 0) || (ring->mark == ring->consume)) {
+	if ((ring->supply < ring->consume) || ring_full(ring)) {
+	    return ring_subtract(ring, ring->top, ring->consume);
+	} else {
+	    return ring_subtract(ring, ring->supply, ring->consume);
+	}
+    } else {
+	if (ring->mark < ring->consume) {
+	    return ring_subtract(ring, ring->top, ring->consume);
+	} else {	/* Else, distance to mark */
+	    return ring_subtract(ring, ring->mark, ring->consume);
+	}
+    }
+}
+
+/*
+ * Move data into the "supply" portion of of the ring buffer.
+ */
+    void
+ring_supply_data(ring, buffer, count)
+    Ring *ring;
+    unsigned char *buffer;
+    int count;
+{
+    int i;
+
+    while (count) {
+	i = MIN(count, ring_empty_consecutive(ring));
+	memcpy(ring->supply, buffer, i);
+	ring_supplied(ring, i);
+	count -= i;
+	buffer += i;
+    }
+}
+
+#ifdef notdef
+
+/*
+ * Move data from the "consume" portion of the ring buffer
+ */
+    void
+ring_consume_data(ring, buffer, count)
+    Ring *ring;
+    unsigned char *buffer;
+    int count;
+{
+    int i;
+
+    while (count) {
+	i = MIN(count, ring_full_consecutive(ring));
+	memcpy(buffer, ring->consume, i);
+	ring_consumed(ring, i);
+	count -= i;
+	buffer += i;
+    }
+}
+#endif
+
+#ifdef	ENCRYPTION
+    void
+ring_encrypt(ring, encryptor)
+    Ring *ring;
+    void (*encryptor)();
+{
+    unsigned char *s, *c;
+
+    if (ring_empty(ring) || ring->clearto == ring->supply)
+	return;
+
+    if (!(c = ring->clearto))
+	c = ring->consume;
+
+    s = ring->supply;
+
+    if (s <= c) {
+	(*encryptor)(c, ring->top - c);
+	(*encryptor)(ring->bottom, s - ring->bottom);
+    } else
+	(*encryptor)(c, s - c);
+
+    ring->clearto = ring->supply;
+}
+
+    void
+ring_clearto(ring)
+    Ring *ring;
+{
+    if (!ring_empty(ring))
+	ring->clearto = ring->supply;
+    else
+	ring->clearto = 0;
+}
+#endif	/* ENCRYPTION */
diff --git a/krb5-1-6/src/appl/telnet/telnet/ring.h b/krb5-1-6/src/appl/telnet/telnet/ring.h
new file mode 100644
index 000000000..87f0ab77a
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/ring.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ring.h	8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * This defines a structure for a ring buffer.
+ *
+ * The circular buffer has two parts:
+ *(((
+ *	full:	[consume, supply)
+ *	empty:	[supply, consume)
+ *]]]
+ *
+ */
+typedef struct {
+    unsigned char	*consume,	/* where data comes out of */
+			*supply,	/* where data comes in to */
+			*bottom,	/* lowest address in buffer */
+			*top,		/* highest address+1 in buffer */
+			*mark;		/* marker (user defined) */
+#ifdef	ENCRYPTION
+    unsigned char	*clearto;	/* Data to this point is clear text */
+    unsigned char	*encryyptedto;	/* Data is encrypted to here */
+#endif	/* ENCRYPTION */
+    int		size;		/* size in bytes of buffer */
+    u_long	consumetime,	/* help us keep straight full, empty, etc. */
+		supplytime;
+} Ring;
+
+/* Here are some functions and macros to deal with the ring buffer */
+
+/* Initialization routine */
+extern int
+	ring_init (Ring *ring, unsigned char *buffer, int count);
+
+/* Data movement routines */
+extern void
+	ring_supply_data (Ring *ring, unsigned char *buffer, int count);
+#ifdef notdef
+extern void
+	ring_consume_data (Ring *ring, unsigned char *buffer, int count);
+#endif
+
+/* Buffer state transition routines */
+extern void
+	ring_supplied (Ring *ring, int count),
+	ring_consumed (Ring *ring, int count);
+
+/* Buffer state query routines */
+extern int
+	ring_empty_count (Ring *ring),
+	ring_empty_consecutive (Ring *ring),
+	ring_full_count (Ring *ring),
+	ring_full_consecutive (Ring *ring);
+
+#ifdef	ENCRYPTION
+extern void
+	ring_encrypt (Ring *ring, void (*func)()),
+	ring_clearto (Ring *ring);
+#endif	/* ENCRYPTION */
+
+extern void
+    ring_clear_mark (Ring *ring),
+    ring_mark (Ring *ring);
+
+extern int
+    ring_at_mark (Ring *);
diff --git a/krb5-1-6/src/appl/telnet/telnet/sys_bsd.c b/krb5-1-6/src/appl/telnet/telnet/sys_bsd.c
new file mode 100644
index 000000000..89f9d4b5a
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/sys_bsd.c
@@ -0,0 +1,1208 @@
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)sys_bsd.c	8.1 (Berkeley) 6/6/93 */
+
+/*
+ * The following routines try to encapsulate what is system dependent
+ * (at least between 4.x and dos) which is used in telnet.c.
+ */
+
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <signal.h>
+#ifdef POSIX_SIGNALS
+#include <unistd.h>
+#endif /* POSIX_SIGNALS */
+#include <errno.h>
+#include <arpa/telnet.h>
+
+#include "ring.h"
+
+#include "fdset.h"
+
+#include "defines.h"
+#include "externs.h"
+#include "types.h"
+
+#if	defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO))
+#define	SIG_FUNC_RET	void
+#else
+#define	SIG_FUNC_RET	int
+#endif
+
+#ifdef	SIGTSTP
+static SIG_FUNC_RET susp(int);
+#endif	/* SIGTSTP */
+#ifdef	SIGINFO
+SIG_FUNC_RET ayt(int);
+#endif
+#ifdef	SIGINFO
+extern SIG_FUNC_RET ayt_status();
+#endif
+
+#ifdef POSIX_SIGNALS
+static struct sigaction new_sa_rec, old_sa_rec;
+
+#ifdef SA_INTERRUPT
+#define SIGACTION_INTERRUPT SA_INTERRUPT
+#else
+#define SIGACTION_INTERRUPT 0
+#endif
+
+#ifdef SA_NOMASK
+#define SIGACTION_NOMASK SA_NOMASK
+#else
+#define SIGACTION_NOMASK 0
+#endif
+
+#define signal(sig, func) ((new_sa_rec.sa_handler = func), \
+			   sigemptyset(&new_sa_rec.sa_mask), \
+			   (new_sa_rec.sa_flags = SIGACTION_INTERRUPT | \
+			    SIGACTION_NOMASK), \
+			   sigaction(sig, &new_sa_rec, &old_sa_rec), \
+			   old_sa_rec.sa_handler)
+
+#endif /* POSIX_SIGNALS */
+
+int
+	tout,			/* Output file descriptor */
+	tin,			/* Input file descriptor */
+	net;
+
+#ifndef	USE_TERMIO
+struct	tchars otc = { 0 }, ntc = { 0 };
+struct	ltchars oltc = { 0 }, nltc = { 0 };
+struct	sgttyb ottyb = { 0 }, nttyb = { 0 };
+int	olmode = 0;
+# define cfgetispeed(ptr)	(ptr)->sg_ispeed
+# define cfgetospeed(ptr)	(ptr)->sg_ospeed
+# define old_tc ottyb
+
+#else	/* USE_TERMIO */
+struct	termio old_tc = { 0 };
+extern struct termio new_tc;
+
+# ifndef	TCSANOW
+#  ifdef TCSETS
+#   define	TCSANOW		TCSETS
+#   define	TCSADRAIN	TCSETSW
+#   define	tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
+#  else
+#   ifdef TCSETA
+#    define	TCSANOW		TCSETA
+#    define	TCSADRAIN	TCSETAW
+#    define	tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
+#   else
+#    define	TCSANOW		TIOCSETA
+#    define	TCSADRAIN	TIOCSETAW
+#    define	tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
+#   endif
+#  endif
+#  define	tcsetattr(f, a, t) ioctl(f, a, (char *)t)
+#  define	cfgetospeed(ptr)	((ptr)->c_cflag&CBAUD)
+#  ifdef CIBAUD
+#   define	cfgetispeed(ptr)	(((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
+#  else
+#   define	cfgetispeed(ptr)	cfgetospeed(ptr)
+#  endif
+# endif /* TCSANOW */
+# ifdef	sysV88
+# define TIOCFLUSH TC_PX_DRAIN
+# endif
+#endif	/* USE_TERMIO */
+
+static fd_set ibits, obits, xbits;
+
+
+    void
+init_sys()
+{
+    tout = fileno(stdout);
+    tin = fileno(stdin);
+    FD_ZERO(&ibits);
+    FD_ZERO(&obits);
+    FD_ZERO(&xbits);
+
+    errno = 0;
+}
+
+
+    int
+TerminalWrite(buf, n)
+    unsigned char *buf;
+    int  n;
+{
+    return write(tout, buf, n);
+}
+
+    int
+TerminalRead(buf, n)
+    unsigned char *buf;
+    int  n;
+{
+    return read(tin, buf, n);
+}
+
+/*
+ *
+ */
+
+    int
+TerminalAutoFlush()
+{
+#if	defined(LNOFLSH)
+    int flush;
+
+    ioctl(0, TIOCLGET, (char *)&flush);
+    return !(flush&LNOFLSH);	/* if LNOFLSH, no autoflush */
+#else	/* LNOFLSH */
+    return 1;
+#endif	/* LNOFLSH */
+}
+
+#ifdef	KLUDGELINEMODE
+extern int kludgelinemode;
+#endif
+/*
+ * TerminalSpecialChars()
+ *
+ * Look at an input character to see if it is a special character
+ * and decide what to do.
+ *
+ * Output:
+ *
+ *	0	Don't add this character.
+ *	1	Do add this character
+ */
+
+    int
+TerminalSpecialChars(c)
+    int	c;
+{
+    if (c == termIntChar) {
+	intp();
+	return 0;
+    } else if (c == termQuitChar) {
+#ifdef	KLUDGELINEMODE
+	if (kludgelinemode)
+	    sendbrk();
+	else
+#endif
+	    sendabort();
+	return 0;
+    } else if (c == termEofChar) {
+	if (my_want_state_is_will(TELOPT_LINEMODE)) {
+	    sendeof();
+	    return 0;
+	}
+	return 1;
+    } else if (c == termSuspChar) {
+	sendsusp();
+	return(0);
+    } else if (c == termFlushChar) {
+	xmitAO();		/* Transmit Abort Output */
+	return 0;
+    } else if (!MODE_LOCAL_CHARS(globalmode)) {
+	if (c == termKillChar) {
+	    xmitEL();
+	    return 0;
+	} else if (c == termEraseChar) {
+	    xmitEC();		/* Transmit Erase Character */
+	    return 0;
+	}
+    }
+    return 1;
+}
+
+
+/*
+ * Flush output to the terminal
+ */
+    void
+TerminalFlushOutput()
+{
+#ifdef	TIOCFLUSH
+    (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
+#else
+    (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
+#endif
+}
+
+    void
+TerminalSaveState()
+{
+#ifndef	USE_TERMIO
+    ioctl(0, TIOCGETP, (char *)&ottyb);
+    ioctl(0, TIOCGETC, (char *)&otc);
+    ioctl(0, TIOCGLTC, (char *)&oltc);
+    ioctl(0, TIOCLGET, (char *)&olmode);
+
+    ntc = otc;
+    nltc = oltc;
+    nttyb = ottyb;
+
+#else	/* USE_TERMIO */
+    tcgetattr(0, &old_tc);
+
+    new_tc = old_tc;
+
+#ifndef	VDISCARD
+    termFlushChar = CONTROL('O');
+#endif
+#ifndef	VWERASE
+    termWerasChar = CONTROL('W');
+#endif
+#ifndef	VREPRINT
+    termRprntChar = CONTROL('R');
+#endif
+#ifndef	VLNEXT
+    termLiteralNextChar = CONTROL('V');
+#endif
+#ifndef	VSTART
+    termStartChar = CONTROL('Q');
+#endif
+#ifndef	VSTOP
+    termStopChar = CONTROL('S');
+#endif
+#ifndef	VSTATUS
+    termAytChar = CONTROL('T');
+#endif
+#endif	/* USE_TERMIO */
+}
+
+    cc_t *
+tcval(func)
+    register int func;
+{
+    switch(func) {
+    case SLC_IP:	return(&termIntChar);
+    case SLC_ABORT:	return(&termQuitChar);
+    case SLC_EOF:	return(&termEofChar);
+    case SLC_EC:	return(&termEraseChar);
+    case SLC_EL:	return(&termKillChar);
+    case SLC_XON:	return(&termStartChar);
+    case SLC_XOFF:	return(&termStopChar);
+    case SLC_FORW1:	return(&termForw1Char);
+#ifdef	USE_TERMIO
+    case SLC_FORW2:	return(&termForw2Char);
+# ifdef	VDISCARD
+    case SLC_AO:	return(&termFlushChar);
+# endif
+# ifdef	VSUSP
+    case SLC_SUSP:	return(&termSuspChar);
+# endif
+# ifdef	VWERASE
+    case SLC_EW:	return(&termWerasChar);
+# endif
+# ifdef	VREPRINT
+    case SLC_RP:	return(&termRprntChar);
+# endif
+# ifdef	VLNEXT
+    case SLC_LNEXT:	return(&termLiteralNextChar);
+# endif
+# ifdef	VSTATUS
+    case SLC_AYT:	return(&termAytChar);
+# endif
+#endif
+
+    case SLC_SYNCH:
+    case SLC_BRK:
+    case SLC_EOR:
+    default:
+	return((cc_t *)0);
+    }
+}
+
+    void
+TerminalDefaultChars()
+{
+#ifndef	USE_TERMIO
+    ntc = otc;
+    nltc = oltc;
+    nttyb.sg_kill = ottyb.sg_kill;
+    nttyb.sg_erase = ottyb.sg_erase;
+#else	/* USE_TERMIO */
+    memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
+# ifndef	VDISCARD
+    termFlushChar = CONTROL('O');
+# endif
+# ifndef	VWERASE
+    termWerasChar = CONTROL('W');
+# endif
+# ifndef	VREPRINT
+    termRprntChar = CONTROL('R');
+# endif
+# ifndef	VLNEXT
+    termLiteralNextChar = CONTROL('V');
+# endif
+# ifndef	VSTART
+    termStartChar = CONTROL('Q');
+# endif
+# ifndef	VSTOP
+    termStopChar = CONTROL('S');
+# endif
+# ifndef	VSTATUS
+    termAytChar = CONTROL('T');
+# endif
+#endif	/* USE_TERMIO */
+}
+
+#ifdef notdef
+void
+TerminalRestoreState()
+{
+}
+#endif
+
+/*
+ * TerminalNewMode - set up terminal to a specific mode.
+ *	MODE_ECHO: do local terminal echo
+ *	MODE_FLOW: do local flow control
+ *	MODE_TRAPSIG: do local mapping to TELNET IAC sequences
+ *	MODE_EDIT: do local line editing
+ *
+ *	Command mode:
+ *		MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
+ *		local echo
+ *		local editing
+ *		local xon/xoff
+ *		local signal mapping
+ *
+ *	Linemode:
+ *		local/no editing
+ *	Both Linemode and Single Character mode:
+ *		local/remote echo
+ *		local/no xon/xoff
+ *		local/no signal mapping
+ */
+
+
+    void
+TerminalNewMode(f)
+    register int f;
+{
+    static int prevmode = 0;
+#ifndef	USE_TERMIO
+    struct tchars tc;
+    struct ltchars ltc;
+    struct sgttyb sb;
+    int lmode;
+#else	/* USE_TERMIO */
+    struct termio tmp_tc;
+#endif	/* USE_TERMIO */
+    int onoff;
+    int old;
+    cc_t esc;
+
+    globalmode = f&~MODE_FORCE;
+    if (prevmode == f)
+	return;
+
+    /*
+     * Write any outstanding data before switching modes
+     * ttyflush() returns 0 only when there is no more data
+     * left to write out, it returns -1 if it couldn't do
+     * anything at all, otherwise it returns 1 + the number
+     * of characters left to write.
+#ifndef	USE_TERMIO
+     * We would really like ask the kernel to wait for the output
+     * to drain, like we can do with the TCSADRAIN, but we don't have
+     * that option.  The only ioctl that waits for the output to
+     * drain, TIOCSETP, also flushes the input queue, which is NOT
+     * what we want (TIOCSETP is like TCSADFLUSH).
+#endif
+     */
+    old = ttyflush(SYNCHing|flushout);
+    if (old < 0 || old > 1) {
+#ifdef	USE_TERMIO
+	tcgetattr(tin, &tmp_tc);
+#endif	/* USE_TERMIO */
+	do {
+	    /*
+	     * Wait for data to drain, then flush again.
+	     */
+#ifdef	USE_TERMIO
+	    tcsetattr(tin, TCSADRAIN, &tmp_tc);
+#endif	/* USE_TERMIO */
+	    old = ttyflush(SYNCHing|flushout);
+	} while (old < 0 || old > 1);
+    }
+
+    old = prevmode;
+    prevmode = f&~MODE_FORCE;
+#ifndef	USE_TERMIO
+    sb = nttyb;
+    tc = ntc;
+    ltc = nltc;
+    lmode = olmode;
+#else
+    tmp_tc = new_tc;
+#endif
+
+    if (f&MODE_ECHO) {
+#ifndef	USE_TERMIO
+	sb.sg_flags |= ECHO;
+#else
+	tmp_tc.c_lflag |= ECHO;
+	tmp_tc.c_oflag |= ONLCR;
+	if (crlf)
+		tmp_tc.c_iflag |= ICRNL;
+#endif
+    } else {
+#ifndef	USE_TERMIO
+	sb.sg_flags &= ~ECHO;
+#else
+	tmp_tc.c_lflag &= ~ECHO;
+	tmp_tc.c_oflag &= ~ONLCR;
+# ifdef notdef
+	if (crlf)
+		tmp_tc.c_iflag &= ~ICRNL;
+# endif
+#endif
+    }
+
+    if ((f&MODE_FLOW) == 0) {
+#ifndef	USE_TERMIO
+	tc.t_startc = _POSIX_VDISABLE;
+	tc.t_stopc = _POSIX_VDISABLE;
+#else
+	tmp_tc.c_iflag &= ~(IXOFF|IXON);	/* Leave the IXANY bit alone */
+    } else {
+	if (restartany < 0) {
+		tmp_tc.c_iflag |= IXOFF|IXON;	/* Leave the IXANY bit alone */
+	} else if (restartany > 0) {
+		tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
+	} else {
+		tmp_tc.c_iflag |= IXOFF|IXON;
+		tmp_tc.c_iflag &= ~IXANY;
+	}
+#endif
+    }
+
+    if ((f&MODE_TRAPSIG) == 0) {
+#ifndef	USE_TERMIO
+	tc.t_intrc = _POSIX_VDISABLE;
+	tc.t_quitc = _POSIX_VDISABLE;
+	tc.t_eofc = _POSIX_VDISABLE;
+	ltc.t_suspc = _POSIX_VDISABLE;
+	ltc.t_dsuspc = _POSIX_VDISABLE;
+#else
+	tmp_tc.c_lflag &= ~ISIG;
+#endif
+	localchars = 0;
+    } else {
+#ifdef	USE_TERMIO
+	tmp_tc.c_lflag |= ISIG;
+#endif
+	localchars = 1;
+    }
+
+    if (f&MODE_EDIT) {
+#ifndef	USE_TERMIO
+	sb.sg_flags &= ~CBREAK;
+	sb.sg_flags |= CRMOD;
+#else
+	tmp_tc.c_lflag |= ICANON;
+#endif
+    } else {
+#ifndef	USE_TERMIO
+	sb.sg_flags |= CBREAK;
+	if (f&MODE_ECHO)
+	    sb.sg_flags |= CRMOD;
+	else
+	    sb.sg_flags &= ~CRMOD;
+#else
+	tmp_tc.c_lflag &= ~ICANON;
+	tmp_tc.c_iflag &= ~ICRNL;
+	tmp_tc.c_cc[VMIN] = 1;
+	tmp_tc.c_cc[VTIME] = 0;
+#endif
+    }
+
+    if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
+#ifndef	USE_TERMIO
+	ltc.t_lnextc = _POSIX_VDISABLE;
+#else
+# ifdef VLNEXT
+	tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
+# endif
+#endif
+    }
+
+    if (f&MODE_SOFT_TAB) {
+#ifndef USE_TERMIO
+	sb.sg_flags |= XTABS;
+#else
+# ifdef	OXTABS
+	tmp_tc.c_oflag |= OXTABS;
+# endif
+# ifdef	TABDLY
+	tmp_tc.c_oflag &= ~TABDLY;
+	tmp_tc.c_oflag |= TAB3;
+# endif
+#endif
+    } else {
+#ifndef USE_TERMIO
+	sb.sg_flags &= ~XTABS;
+#else
+# ifdef	OXTABS
+	tmp_tc.c_oflag &= ~OXTABS;
+# endif
+# ifdef	TABDLY
+	tmp_tc.c_oflag &= ~TABDLY;
+# endif
+#endif
+    }
+
+    if (f&MODE_LIT_ECHO) {
+#ifndef USE_TERMIO
+	lmode &= ~LCTLECH;
+#else
+# ifdef	ECHOCTL
+	tmp_tc.c_lflag &= ~ECHOCTL;
+# endif
+#endif
+    } else {
+#ifndef USE_TERMIO
+	lmode |= LCTLECH;
+#else
+# ifdef	ECHOCTL
+	tmp_tc.c_lflag |= ECHOCTL;
+# endif
+#endif
+    }
+
+    if (f == -1) {
+	onoff = 0;
+    } else {
+#ifndef	USE_TERMIO
+	if (f & MODE_OUTBIN)
+		lmode |= LLITOUT;
+	else
+		lmode &= ~LLITOUT;
+
+	if (f & MODE_INBIN)
+		lmode |= LPASS8;
+	else
+		lmode &= ~LPASS8;
+#else
+	if (f & MODE_INBIN)
+		tmp_tc.c_iflag &= ~ISTRIP;
+	else
+		tmp_tc.c_iflag |= ISTRIP;
+	if (f & MODE_OUTBIN) {
+		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+		tmp_tc.c_cflag |= CS8;
+		tmp_tc.c_oflag &= ~OPOST;
+	} else {
+		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+		tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
+		tmp_tc.c_oflag |= OPOST;
+	}
+#endif
+	onoff = 1;
+    }
+
+    if (f != -1) {
+
+#ifdef	SIGTSTP
+	(void) signal(SIGTSTP, susp);
+#endif	/* SIGTSTP */
+#ifdef	SIGINFO
+	(void) signal(SIGINFO, ayt);
+#endif
+#if	defined(USE_TERMIO) && defined(NOKERNINFO)
+	tmp_tc.c_lflag |= NOKERNINFO;
+#endif
+	/*
+	 * We don't want to process ^Y here.  It's just another
+	 * character that we'll pass on to the back end.  It has
+	 * to process it because it will be processed when the
+	 * user attempts to read it, not when we send it.
+	 */
+#ifndef	USE_TERMIO
+	ltc.t_dsuspc = _POSIX_VDISABLE;
+#else
+# ifdef	VDSUSP
+	tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
+# endif
+#endif
+#ifdef	USE_TERMIO
+	/*
+	 * If the VEOL character is already set, then use VEOL2,
+	 * otherwise use VEOL.
+	 */
+	esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
+	if ((tmp_tc.c_cc[VEOL] != esc)
+# ifdef	VEOL2
+	    && (tmp_tc.c_cc[VEOL2] != esc)
+# endif
+	    ) {
+		if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
+		    tmp_tc.c_cc[VEOL] = esc;
+# ifdef	VEOL2
+		else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
+		    tmp_tc.c_cc[VEOL2] = esc;
+# endif
+	}
+#else
+	if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
+		tc.t_brkc = esc;
+#endif
+    } else {
+#ifdef	SIGINFO
+	SIG_FUNC_RET ayt_status();
+
+	(void) signal(SIGINFO, ayt_status);
+#endif
+#ifdef	SIGTSTP
+	(void) signal(SIGTSTP, SIG_DFL);
+#ifdef POSIX_SIGNALS
+	{
+	  sigset_t tmask;
+	  sigemptyset(&tmask);
+	  sigaddset(&tmask, SIGTSTP);
+	  sigprocmask(SIG_UNBLOCK, &tmask, (sigset_t*)0);
+	}
+#else
+	(void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
+#endif
+#endif	/* SIGTSTP */
+#ifndef USE_TERMIO
+	ltc = oltc;
+	tc = otc;
+	sb = ottyb;
+	lmode = olmode;
+#else
+	tmp_tc = old_tc;
+#endif
+    }
+#ifndef USE_TERMIO
+    ioctl(tin, TIOCLSET, (char *)&lmode);
+    ioctl(tin, TIOCSLTC, (char *)<c);
+    ioctl(tin, TIOCSETC, (char *)&tc);
+    ioctl(tin, TIOCSETN, (char *)&sb);
+#else
+    if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
+	tcsetattr(tin, TCSANOW, &tmp_tc);
+#endif
+
+#if	(!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
+# if	!defined(sysV88)
+    ioctl(tin, FIONBIO, (char *)&onoff);
+    ioctl(tout, FIONBIO, (char *)&onoff);
+# endif
+#endif	/* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
+#if	defined(TN3270)
+    if (noasynchtty == 0) {
+	ioctl(tin, FIOASYNC, (char *)&onoff);
+    }
+#endif	/* defined(TN3270) */
+
+}
+
+#ifndef	B19200
+# define B19200 B9600
+#endif
+
+#ifndef	B38400
+# define B38400 B19200
+#endif
+
+/*
+ * This code assumes that the values B0, B50, B75...
+ * are in ascending order.  They do not have to be
+ * contiguous.
+ */
+struct termspeeds {
+	long speed;
+	long value;
+} termspeeds[] = {
+	{ 0,     B0 },     { 50,    B50 },   { 75,    B75 },
+	{ 110,   B110 },   { 134,   B134 },  { 150,   B150 },
+	{ 200,   B200 },   { 300,   B300 },  { 600,   B600 },
+	{ 1200,  B1200 },  { 1800,  B1800 }, { 2400,  B2400 },
+	{ 4800,  B4800 },  { 9600,  B9600 }, { 19200, B19200 },
+	{ 38400, B38400 }, { -1,    B38400 }
+};
+
+    void
+TerminalSpeeds(ispeed, ospeed)
+    long *ispeed;
+    long *ospeed;
+{
+    register struct termspeeds *tp;
+    register long in, out;
+
+    out = cfgetospeed(&old_tc);
+    in = cfgetispeed(&old_tc);
+    if (in == 0)
+	in = out;
+
+    tp = termspeeds;
+    while ((tp->speed != -1) && (tp->value < in))
+	tp++;
+    *ispeed = tp->speed;
+
+    tp = termspeeds;
+    while ((tp->speed != -1) && (tp->value < out))
+	tp++;
+    *ospeed = tp->speed;
+}
+
+    int
+TerminalWindowSize(rows, cols)
+    long *rows, *cols;
+{
+#ifdef	TIOCGWINSZ
+    struct winsize ws;
+
+    if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
+	*rows = ws.ws_row;
+	*cols = ws.ws_col;
+	return 1;
+    }
+#endif	/* TIOCGWINSZ */
+    return 0;
+}
+
+    int
+NetClose(fd)
+    int	fd;
+{
+    return close(fd);
+}
+
+
+static void
+NetNonblockingIO(fd, onoff)
+    int fd;
+    int onoff;
+{
+    ioctl(fd, FIONBIO, (char *)&onoff);
+}
+
+#if	defined(TN3270)
+    void
+NetSigIO(fd, onoff)
+    int fd;
+    int onoff;
+{
+    ioctl(fd, FIOASYNC, (char *)&onoff);	/* hear about input */
+}
+
+    void
+NetSetPgrp(fd)
+    int fd;
+{
+    int myPid;
+
+    myPid = getpid();
+    fcntl(fd, F_SETOWN, myPid);
+}
+#endif	/*defined(TN3270)*/
+
+/*
+ * Various signal handling routines.
+ */
+
+    /* ARGSUSED */
+static  SIG_FUNC_RET
+deadpeer(sig)
+    int sig;
+{
+	setcommandmode();
+	longjmp(peerdied, -1);
+}
+
+int intr_happened = 0;
+int intr_waiting = 0;
+
+    /* ARGSUSED */
+static SIG_FUNC_RET
+intr(sig)
+    int sig;
+{
+    if (intr_waiting) {
+	intr_happened = 1;
+	return;
+    }
+    if (localchars) {
+	intp();
+	return;
+    }
+    setcommandmode();
+    longjmp(toplevel, -1);
+}
+
+    /* ARGSUSED */
+static SIG_FUNC_RET
+intr2(sig)
+    int sig;
+{
+    if (localchars) {
+#ifdef	KLUDGELINEMODE
+	if (kludgelinemode)
+	    sendbrk();
+	else
+#endif
+	    sendabort();
+	return;
+    }
+}
+
+#ifdef	SIGTSTP
+    /* ARGSUSED */
+static SIG_FUNC_RET
+susp(sig)
+    int sig;
+{
+    if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
+	return;
+    if (localchars)
+	sendsusp();
+}
+#endif
+
+#ifdef	SIGWINCH
+    /* ARGSUSED */
+static  SIG_FUNC_RET
+sendwin(sig)
+    int sig;
+{
+    if (connected) {
+	sendnaws();
+    }
+}
+#endif
+
+#ifdef	SIGINFO
+    /* ARGSUSED */
+    SIG_FUNC_RET
+ayt(sig)
+    int sig;
+{
+    if (connected)
+	sendayt();
+    else
+	ayt_status();
+}
+#endif
+
+
+    void
+sys_telnet_init()
+{
+    (void) signal(SIGINT, intr);
+    (void) signal(SIGQUIT, intr2);
+    (void) signal(SIGPIPE, deadpeer);
+#ifdef	SIGWINCH
+    (void) signal(SIGWINCH, sendwin);
+#endif
+#ifdef	SIGTSTP
+    (void) signal(SIGTSTP, susp);
+#endif
+#ifdef	SIGINFO
+    (void) signal(SIGINFO, ayt);
+#endif
+
+    setconnmode(0);
+
+    NetNonblockingIO(net, 1);
+
+#if	defined(TN3270)
+    if (noasynchnet == 0) {			/* DBX can't handle! */
+	NetSigIO(net, 1);
+	NetSetPgrp(net);
+    }
+#endif	/* defined(TN3270) */
+
+#if	defined(SO_OOBINLINE)
+    if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
+	perror("SetSockOpt");
+    }
+#endif	/* defined(SO_OOBINLINE) */
+}
+
+/*
+ * Process rings -
+ *
+ *	This routine tries to fill up/empty our various rings.
+ *
+ *	The parameter specifies whether this is a poll operation,
+ *	or a block-until-something-happens operation.
+ *
+ *	The return value is 1 if something happened, 0 if not.
+ */
+
+    int
+process_rings(netin, netout, netex, ttyin, ttyout, poll)
+    int poll;		/* If 0, then block until something to do */
+{
+    register int c;
+		/* One wants to be a bit careful about setting returnValue
+		 * to one, since a one implies we did some useful work,
+		 * and therefore probably won't be called to block next
+		 * time (TN3270 mode only).
+		 */
+    int returnValue = 0;
+    static struct timeval TimeValue = { 0 };
+
+    if (netout) {
+	FD_SET(net, &obits);
+    } 
+    if (ttyout) {
+	FD_SET(tout, &obits);
+    }
+#if	defined(TN3270)
+    if (ttyin) {
+	FD_SET(tin, &ibits);
+    }
+#else	/* defined(TN3270) */
+    if (ttyin) {
+	FD_SET(tin, &ibits);
+    }
+#endif	/* defined(TN3270) */
+#if	defined(TN3270)
+    if (netin) {
+	FD_SET(net, &ibits);
+    }
+#   else /* !defined(TN3270) */
+    if (netin) {
+	FD_SET(net, &ibits);
+    }
+#   endif /* !defined(TN3270) */
+    if (netex) {
+	FD_SET(net, &xbits);
+    }
+    if ((c = select(16, &ibits, &obits, &xbits,
+			(poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
+	if (c == -1) {
+		    /*
+		     * we can get EINTR if we are in line mode,
+		     * and the user does an escape (TSTP), or
+		     * some other signal generator.
+		     */
+	    if (errno == EINTR) {
+		return 0;
+	    }
+#	    if defined(TN3270)
+		    /*
+		     * we can get EBADF if we were in transparent
+		     * mode, and the transcom process died.
+		    */
+	    if (errno == EBADF) {
+			/*
+			 * zero the bits (even though kernel does it)
+			 * to make sure we are selecting on the right
+			 * ones.
+			*/
+		FD_ZERO(&ibits);
+		FD_ZERO(&obits);
+		FD_ZERO(&xbits);
+		return 0;
+	    }
+#	    endif /* defined(TN3270) */
+		    /* I don't like this, does it ever happen? */
+	    printf("sleep(5) from telnet, after select\r\n");
+	    sleep(5);
+	}
+	return 0;
+    }
+
+    /*
+     * Any urgent data?
+     */
+    if (FD_ISSET(net, &xbits)) {
+	FD_CLR(net, &xbits);
+	SYNCHing = 1;
+	(void) ttyflush(1);	/* flush already enqueued data */
+    }
+
+    /*
+     * Something to read from the network...
+     */
+    if (FD_ISSET(net, &ibits)) {
+	int canread;
+
+	FD_CLR(net, &ibits);
+	canread = ring_empty_consecutive(&netiring);
+#if	!defined(SO_OOBINLINE)
+	    /*
+	     * In 4.2 (and some early 4.3) systems, the
+	     * OOB indication and data handling in the kernel
+	     * is such that if two separate TCP Urgent requests
+	     * come in, one byte of TCP data will be overlaid.
+	     * This is fatal for Telnet, but we try to live
+	     * with it.
+	     *
+	     * In addition, in 4.2 (and...), a special protocol
+	     * is needed to pick up the TCP Urgent data in
+	     * the correct sequence.
+	     *
+	     * What we do is:  if we think we are in urgent
+	     * mode, we look to see if we are "at the mark".
+	     * If we are, we do an OOB receive.  If we run
+	     * this twice, we will do the OOB receive twice,
+	     * but the second will fail, since the second
+	     * time we were "at the mark", but there wasn't
+	     * any data there (the kernel doesn't reset
+	     * "at the mark" until we do a normal read).
+	     * Once we've read the OOB data, we go ahead
+	     * and do normal reads.
+	     *
+	     * There is also another problem, which is that
+	     * since the OOB byte we read doesn't put us
+	     * out of OOB state, and since that byte is most
+	     * likely the TELNET DM (data mark), we would
+	     * stay in the TELNET SYNCH (SYNCHing) state.
+	     * So, clocks to the rescue.  If we've "just"
+	     * received a DM, then we test for the
+	     * presence of OOB data when the receive OOB
+	     * fails (and AFTER we did the normal mode read
+	     * to clear "at the mark").
+	     */
+	if (SYNCHing) {
+	    int atmark;
+	    static int bogus_oob = 0, first = 1;
+
+	    ioctl(net, SIOCATMARK, (char *)&atmark);
+	    if (atmark) {
+		c = recv(net, netiring.supply, canread, MSG_OOB);
+		if ((c == -1) && (errno == EINVAL)) {
+		    c = recv(net, netiring.supply, canread, 0);
+		    if (clocks.didnetreceive < clocks.gotDM) {
+			SYNCHing = stilloob(net);
+		    }
+		} else if (first && c > 0) {
+		    /*
+		     * Bogosity check.  Systems based on 4.2BSD
+		     * do not return an error if you do a second
+		     * recv(MSG_OOB).  So, we do one.  If it
+		     * succeeds and returns exactly the same
+		     * data, then assume that we are running
+		     * on a broken system and set the bogus_oob
+		     * flag.  (If the data was different, then
+		     * we probably got some valid new data, so
+		     * increment the count...)
+		     */
+		    int i;
+		    i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
+		    if (i == c &&
+			memcmp(netiring.supply, netiring.supply + c, i) == 0) {
+			bogus_oob = 1;
+			first = 0;
+		    } else if (i < 0) {
+			bogus_oob = 0;
+			first = 0;
+		    } else
+			c += i;
+		}
+		if (bogus_oob && c > 0) {
+		    int i;
+		    /*
+		     * Bogosity.  We have to do the read
+		     * to clear the atmark to get out of
+		     * an infinate loop.
+		     */
+		    i = read(net, netiring.supply + c, canread - c);
+		    if (i > 0)
+			c += i;
+		}
+	    } else {
+		c = recv(net, netiring.supply, canread, 0);
+	    }
+	} else {
+	    c = recv(net, netiring.supply, canread, 0);
+	}
+	settimer(didnetreceive);
+#else	/* !defined(SO_OOBINLINE) */
+	c = recv(net, (char *)netiring.supply, canread, 0);
+#endif	/* !defined(SO_OOBINLINE) */
+	if (c < 0 && errno == EWOULDBLOCK) {
+	    c = 0;
+	} else if (c <= 0) {
+	    return -1;
+	}
+	if (netdata) {
+	    Dump('<', netiring.supply, c);
+	}
+	if (c)
+	    ring_supplied(&netiring, c);
+	returnValue = 1;
+    }
+
+    /*
+     * Something to read from the tty...
+     */
+    if (FD_ISSET(tin, &ibits)) {
+	FD_CLR(tin, &ibits);
+	c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
+	if (c < 0 && errno == EWOULDBLOCK) {
+	    c = 0;
+	} else {
+	    /* EOF detection for line mode!!!! */
+	    if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
+			/* must be an EOF... */
+		*ttyiring.supply = termEofChar;
+		c = 1;
+	    }
+	    if (c <= 0) {
+		return -1;
+	    }
+	    if (termdata) {
+		Dump('<', ttyiring.supply, c);
+	    }
+	    ring_supplied(&ttyiring, c);
+	}
+	returnValue = 1;		/* did something useful */
+    }
+
+    if (FD_ISSET(net, &obits)) {
+	FD_CLR(net, &obits);
+	returnValue |= netflush();
+    }
+    if (FD_ISSET(tout, &obits)) {
+	FD_CLR(tout, &obits);
+	returnValue |= (ttyflush(SYNCHing|flushout) > 0);
+    }
+
+    return returnValue;
+}
diff --git a/krb5-1-6/src/appl/telnet/telnet/telnet.0.ps b/krb5-1-6/src/appl/telnet/telnet/telnet.0.ps
new file mode 100644
index 000000000..9edd0b321
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/telnet.0.ps
@@ -0,0 +1,1008 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Courier-Bold
+%%+ font Courier-Oblique
+%%+ font Courier
+%%+ font Symbol
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 10
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier-Oblique
+%%IncludeResource: font Courier
+%%IncludeResource: font Symbol
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Courier@0 ENC0/Courier RE/Courier-Oblique@0 ENC0/Courier-Oblique RE
+/Courier-Bold@0 ENC0/Courier-Bold RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R/F1 10/Times-Bold@0 SF -.2(NA)72
+108 S(ME).2 E/F2 10/Courier-Bold@0 SF(telnet)102 120 Q F0 2.5<ad75>2.5 G
+(ser interf)153.64 120 Q(ace to the)-.1 E/F3 9/Times-Roman@0 SF(TELNET)2.5 E F0
+(protocol)2.5 E F1(SYNOPSIS)72 144 Q F2(telnet)102 156 Q F0([)3.333 E F2<ad38>
+2.499 E F0 3.333(][).833 G F2<ad45>-.834 E F0 3.333(][).833 G F2<ad46>-.834 E
+F0 3.333(][).833 G F2<ad4b>-.834 E F0 3.333(][).833 G F2<ad4c>-.834 E F0 3.333
+(][).833 G F2<ad53>-.834 E/F4 10/Courier-Oblique@0 SF(tos)6 E F0 3.333(][).833
+G F2<ad58>-.834 E F4(authtype)6 E F0 3.333(][).833 G F2<ad61>-.834 E F0 3.333
+(][).833 G F2<ad63>-.834 E F0 3.333(][).833 G F2<ad64>-.834 E F0 3.333(][).833
+G F2<ad65>-.834 E F4(escapechar)144 168 Q F0 3.333(][).833 G F2<ad66>-.834 E F0
+3.333(][).833 G F2<ad6b>-.834 E F4(realm)6 E F0 3.333(][).833 G F2<ad6c>-.834 E
+F4(user)6 E F0 3.333(][).833 G F2<ad6e>-.834 E F4(tracefile)6 E F0 3.333(][)
+.833 G F2<ad72>-.834 E F0 3.333(][).833 G F2<ad78>-.834 E F0 2.5(][).833 G F4
+(host)491.943 168 Q F0 .833([p)144.833 180 S -1.667(ort ]])-.833 F F1
+(DESCRIPTION)72 204 Q F0(The)102 216 Q F2(telnet)2.523 E F0 .023
+(command is used to communicate with another host using the)2.523 F F3(TELNET)
+2.523 E F0 2.523(protocol. If)2.523 F F2(telnet)2.523 E F0(is)2.522 E(in)102
+228 Q -.2(vo)-.4 G -.1(ke).2 G 2.693(dw).1 G .193(ithout the)143.433 228 R F4
+(host)2.693 E F0(ar)2.693 E .194
+(gument, it enters command mode, indicated by its prompt)-.18 F(\()4.36 E F2
+(telnet>)1.666 E F0 -3.138 1.666(\). I)1.666 H 2.694(nt)-1.666 G(his)528.33 228
+Q 1.07(mode, it accepts and e)102 240 R -.15(xe)-.15 G 1.07
+(cutes the commands listed belo).15 F 4.87 -.65(w. I)-.25 H 3.57(fi).65 G 3.57
+(ti)361.18 240 S 3.57(si)370.31 240 S -1.9 -.4(nv o)380.55 240 T -.1(ke).4 G
+3.57(dw).1 G 1.07(ith ar)420.08 240 R 1.07(guments, it performs an)-.18 F F2
+(open)102 252 Q F0(command with those ar)2.5 E(guments.)-.18 E(Options:)102 270
+Q F2<ad38>103.666 288 Q F0 .352(Speci\214es an 8-bit data path.)143 288 R .353
+(This causes an attempt to ne)5.352 F .353(gotiate the)-.15 F/F5 10/Courier@0
+SF .353(TELNET BINARY)2.853 F F0 .353(option on)2.853 F(both input and output.)
+143 300 Q F2<ad45>103.666 318 Q F0(Stops an)143 318 Q 2.5(yc)-.15 G
+(haracter from being recognized as an escape character)188.96 318 Q(.)-.55 E F2
+<ad46>103.666 336 Q F0 .691(If K)143 336 R .691
+(erberos V5 authentication is being used, the)-.25 F F2<ad46>4.856 E F0 .69
+(option allo)3.19 F .69(ws the local credentials to be for)-.25 F(-)-.2 E -.1
+(wa)143 348 S .615(rded to the remote system, including an).1 F 3.116(yc)-.15 G
+.616(redentials that ha)328.698 348 R .916 -.15(ve a)-.2 H .616
+(lready been forw).15 F .616(arded into the)-.1 F(local en)143 360 Q
+(vironment.)-.4 E F2<ad4b>103.666 378 Q F0
+(Speci\214es no automatic login to the remote system.)143 378 Q F2<ad4c>103.666
+396 Q F0 .147(Speci\214es an 8-bit data path on output.)143 396 R .146
+(This causes the BIN)5.146 F(AR)-.35 E 2.646(Yo)-.65 G .146(ption to be ne)
+409.42 396 R .146(gotiated on output.)-.15 F F2<ad53>103.666 414 Q F4(tos)6 E
+F0 .288(Sets the IP type-of-service \(T)143 426 R .288
+(OS\) option for the telnet connection to the v)-.18 F(alue)-.25 E F4(tos,)
+2.788 E F0 .289(which can be)2.788 F 3.12(an)143 438 S .62(umeric T)155.56 438
+R .62(OS v)-.18 F .62(alue or)-.25 F 3.12(,o)-.4 G 3.12(ns)251.36 438 S .619
+(ystems that support it, a symbolic T)263.37 438 R .619
+(OS name found in the /etc/iptos)-.18 F(\214le.)143 450 Q F2<ad58>103.666 468 Q
+F4(atype)6 E F0(Disables the)143 480 Q F4(atype)2.5 E F0
+(type of authentication.)2.5 E F2<ad61>103.666 498 Q F0 2.562
+(Attempt automatic login.)143 498 R(Currently)7.563 E 5.063(,t)-.65 G 2.563
+(his sends the user name via the)303.99 498 R F5(USER)5.063 E F0 -.25(va)5.063
+G 2.563(riable of the).25 F F5(ENVIRON)143 510 Q F0 .444
+(option if supported by the remote system.)2.945 F .444
+(The name used is that of the current user as)5.444 F .168(returned by)143 522
+R F5(getlogin)2.668 E F0 .168(\(2\) if it agrees with the current user ID, oth\
+erwise it is the name associated)B(with the user ID.)143 534 Q F2<ad63>103.666
+552 Q F0 .022(Disables the reading of the user')143 552 R(s)-.55 E F5
+(.telnetrc)2.522 E F0 2.522(\214le. \(See)2.522 F(the)2.522 E F2 .022
+(toggle skiprc)2.522 F F0 .022(command on this)2.522 F(man page.\))143 564 Q F2
+<ad64>103.666 582 Q F0(Sets the initial v)143 582 Q(alue of the)-.25 E F2
+(debug)2.5 E F0(toggle to)2.5 E F5(TRUE)2.5 E F2<ad65>103.666 600 Q F4
+(escape char)6 E F0 1.759(Sets the initial)143 612 R F2 -1.741(telnet telnet)
+4.259 F F0 1.759(escape character to)4.259 F F4 1.759(escape char.)4.259 F F0
+(If)4.259 E F4 1.76(escape char)4.26 F F0(is)4.26 E
+(omitted, then there will be no escape character)143 624 Q(.)-.55 E F2<ad66>
+103.666 642 Q F0 .691(If K)143 642 R .691
+(erberos V5 authentication is being used, the)-.25 F F2<ad66>4.856 E F0 .69
+(option allo)3.19 F .69(ws the local credentials to be for)-.25 F(-)-.2 E -.1
+(wa)143 654 S(rded to the remote system.).1 E F2<ad6b>103.666 672 Q F4(realm)6
+E F0 .008(If K)143 684 R .008(erberos authentication is being used, the)-.25 F
+F2<ad6b>4.174 E F0 .009(option requests that telnet obtain tick)2.508 F .009
+(ets for the re-)-.1 F 6.61
+(mote host in realm realm instead of the remote host')143 696 R 9.11(sr)-.55 G
+6.61(ealm, as determined by)427.41 696 R(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)
+-.15 G(istrib)132.57 750 Q 95.71(ution February)-.2 F(3, 1994)2.5 E(1)535 750 Q
+EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R/F1 10/Courier@0 SF
+(krb_realmofhost)143 96 Q F0(\(3\).)A/F2 10/Courier-Bold@0 SF<ad6c>103.666 114
+Q/F3 10/Courier-Oblique@0 SF(user)6 E F0 1.135
+(When connecting to the remote system, if the remote system understands the)143
+126 R F1(ENVIRON)3.636 E F0(option,)3.636 E(then)143 138 Q F3(user)2.974 E F0
+.474(will be sent to the remote system as the v)2.974 F .474(alue for the v)
+-.25 F .474(ariable USER.)-.25 F .473(This option im-)5.474 F(plies the)143 150
+Q F2<ad61>4.166 E F0 2.5(option. This)2.5 F(option may also be used with the)
+2.5 E F2(open)2.5 E F0(command.)2.5 E F2<ad6e>103.666 168 Q F3(tracefile)6 E F0
+(Opens)143 180 Q F3(tracefile)2.561 E F0 .062(for recording trace information.)
+2.561 F .062(See the)5.062 F F2 .062(set tracefile)2.562 F F0 .062
+(command belo)2.562 F -.65(w.)-.25 G F2<ad72>103.666 198 Q F0 .936
+(Speci\214es a user interf)143 198 R .936(ace similar to)-.1 F F1(rlogin)3.435
+E F0 4.37(\(1\). In)B .935(this mode, the escape character is set to the)3.435
+F(tilde \(~\) character)143 210 Q 2.5(,u)-.4 G
+(nless modi\214ed by the -e option.)222.01 210 Q F2<ad78>103.666 228 Q F0 -.45
+(Tu)143 228 S .123(rns on encryption of the data stream if possible.).45 F .124
+(This option is not a)5.124 F -.25(va)-.2 G .124(ilable outside of the Unit-)
+.25 F(ed States and Canada.)143 240 Q F3(host)102 258 Q F0(Indicates the of)143
+258 Q(\214cial name, an alias, or the Internet address of a remote host.)-.25 E
+F3(port)102 276 Q F0 1.96
+(Indicates a port number \(address of an application\).)143 276 R 1.96
+(If a number is not speci\214ed, the def)6.96 F(ault)-.1 E F2(telnet)143 288 Q
+F0(port is used.)2.5 E .237(When in rlogin mode, a line of the form ~.)102 306
+R .238(disconnects from the remote host; ~ is the telnet escape character)5.237
+F(.)-.55 E(Similarly)102 318 Q 2.5(,t)-.65 G
+(he line ~^Z suspends the telnet session.)146.36 318 Q
+(The line ~^] escapes to the normal telnet escape prompt.)5 E 1.008
+(Once a connection has been opened,)102 336 R F2(telnet)3.507 E F0 1.007
+(will attempt to enable the)3.507 F F1 1.007(TELNET LINEMODE)3.507 F F0 3.507
+(option. If)3.507 F .73(this f)102 348 R .73(ails, then)-.1 F F2(telnet)3.23 E
+F0 .73(will re)3.23 F -.15(ve)-.25 G .73(rt to one of tw).15 F 3.23(oi)-.1 G
+.731(nput modes: either `)308.3 348 R .731(`character at a time')-.74 F 3.231
+('o)-.74 G 3.231(r`)483.277 348 S .731(`old line by)492.428 348 R(line')102 360
+Q 2.5('d)-.74 G(epending on what the remote system supports.)130.42 360 Q(When)
+102 378 Q F1(LINEMODE)3.143 E F0 .642(is enabled, character processing is done\
+ on the local system, under the control of the re-)3.143 F .123(mote system.)
+102 390 R .123(When input editing or character echoing is to be disabled, the \
+remote system will relay that in-)5.123 F 3.397(formation. The)102 402 R .897
+(remote system will also relay changes to an)3.397 F 3.397(ys)-.15 G .897
+(pecial characters that happen on the remote)361.34 402 R(system, so that the)
+102 414 Q 2.5(yc)-.15 G(an tak)187.68 414 Q 2.5(ee)-.1 G -.25(ff)223.12 414 S
+(ect on the local system.).25 E(In `)102 432 Q(`character at a time')-.74 E 2.5
+('m)-.74 G(ode, most te)208.53 432 Q
+(xt typed is immediately sent to the remote host for processing.)-.15 E .323
+(In `)102 450 R .323(`old line by line')-.74 F 2.823('m)-.74 G .323
+(ode, all te)196.845 450 R .323(xt is echoed locally)-.15 F 2.823(,a)-.65 G
+.323(nd \(normally\) only completed lines are sent to the re-)324.073 450 R
+.757(mote host.)102 462 R .757(The `)5.757 F .757(`local echo character')-.74 F
+3.257('\()-.74 G .756(initially `)268.892 462 R(`^E')-.74 E .756
+('\) may be used to turn of)-.74 F 3.256(fa)-.25 G .756
+(nd on the local echo \(this)435.4 462 R -.1(wo)102 474 S
+(uld mostly be used to enter passw).1 E(ords without the passw)-.1 E
+(ord being echoed\).)-.1 E 1.076(If the)102 492 R F1(LINEMODE)3.576 E F0 1.076
+(option is enabled, or if the)3.576 F F2(localchars)3.577 E F0 1.077(toggle is)
+3.577 F F1(TRUE)3.577 E F0 1.077(\(the def)3.577 F 1.077(ault for `)-.1 F 1.077
+(`old line by)-.74 F(line`)102 504 Q .866(`; see belo)-.74 F .866
+(w\), the user')-.25 F(s)-.55 E F2(quit)3.366 E F0(,)A F2(intr)3.366 E F0 3.366
+(,a)C(nd)285.042 504 Q F2(flush)3.365 E F0 .865(characters are trapped locally)
+3.365 F 3.365(,a)-.65 G .865(nd sent as)461.472 504 R/F4 9/Times-Roman@0 SF
+(TELNET)3.365 E F0 .368(protocol sequences to the remote side.)102 516 R(If)
+5.368 E F1(LINEMODE)2.868 E F0 .368(has e)2.868 F -.15(ve)-.25 G 2.868(rb).15 G
+.368(een enabled, then the user')363.23 516 R(s)-.55 E F2(susp)2.869 E F0(and)
+2.869 E F2(eof)2.869 E F0 1.308(are also sent as)102 528 R F4(TELNET)3.808 E F0
+1.308(protocol sequences, and)3.808 F F2(quit)3.808 E F0 1.307(is sent as a)
+3.807 F F1 1.307(TELNET ABORT)3.807 F F0 1.307(instead of)3.807 F F1(BREAK)
+3.807 E F0 .474(There are options \(see)102 540 R F2 -3.026(toggle autoflush)
+2.974 F F0(and)2.974 E F2 -3.026(toggle autosynch)2.974 F F0(belo)2.974 E .475
+(w\) which cause this action to)-.25 F .194
+(\215ush subsequent output to the terminal \(until the remote host ackno)102
+552 R .194(wledges the)-.25 F F4(TELNET)2.694 E F0 .193(sequence\) and \215ush)
+2.693 F(pre)102 564 Q(vious terminal input \(in the case of)-.25 E F2(quit)2.5
+E F0(and)2.5 E F2(intr)2.5 E F0(\).)A .235(While connected to a remote host,)
+102 582 R F2(telnet)2.735 E F0 .235(command mode may be entered by typing the)
+2.735 F F2(telnet)2.735 E F0 -.74(``)2.735 G(escape).74 E(character')102 594 Q
+2.5('\()-.74 G(initially `)150.39 594 Q(`^]')-.74 E 2.5('\). When)-.74 F
+(in command mode, the normal terminal editing con)2.5 E -.15(ve)-.4 G
+(ntions are a).15 E -.25(va)-.2 G(ilable.).25 E .018(The follo)102 612 R(wing)
+-.25 E F2(telnet)2.518 E F0 .018(commands are a)2.518 F -.25(va)-.2 G 2.517
+(ilable. Only).25 F .017(enough of each command to uniquely identify it need)
+2.517 F 2.478(be typed \(this is also true for ar)102 624 R 2.478
+(guments to the)-.18 F F2(mode)4.978 E F0(,)A F2(set)4.978 E F0(,)A F2(toggle)
+4.978 E F0(,)A F2(unset)4.978 E F0(,)A F2(slc)4.978 E F0(,)A F2(environ)4.979 E
+F0 4.979(,a)C(nd)530 624 Q F2(display)102 636 Q F0(commands\).)2.5 E F2(auth)
+102 654 Q F3(argument ...)6 E F0 .308
+(The auth command manipulates the information sent through the)161 666 R F1
+.308(TELNET AUTHENTICATE)2.808 F F0 2.5(option. V)161 678 R(alid ar)-1.11 E
+(guments for the auth command are as follo)-.18 E(ws:)-.25 E(4.2 Berk)72 750 Q
+(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71(ution February)-.2 F
+(3, 1994)2.5 E(2)535 750 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R/F1 10/Courier-Bold@0 SF(disable)
+161 96 Q/F2 10/Courier-Oblique@0 SF(type)6.76 E F0 .76
+(Disables the speci\214ed type of authentication.)5 F 2.36 -.8(To o)5.76 H .76
+(btain a list of a).8 F -.25(va)-.2 G(ilable).25 E(types, use the)238 108 Q F1
+(auth disable ?)2.5 E F0(command.)2.5 E F1(enable)161 126 Q F2(type)6.992 E F0
+.992(Enables the speci\214ed type of authentication.)238.992 126 R 2.592 -.8
+(To o)5.992 H .991(btain a list of a).8 F -.25(va)-.2 G(ilable).25 E
+(types, use the)238 138 Q F1(auth enable ?)2.5 E F0(command.)2.5 E F1(status)
+161 156 Q F0(Lists the current status of the v)238 156 Q
+(arious types of authentication.)-.25 E F1(close)102 174 Q F0(Close a)161 174 Q
+/F3 9/Times-Roman@0 SF(TELNET)2.5 E F0(session and return to command mode.)2.5
+E F1(display)102 192 Q F2(argument ...)6 E F0(Displays all, or some, of the)161
+204 Q F1(set)2.5 E F0(and)2.5 E F1(toggle)2.5 E F0 -.25(va)2.5 G
+(lues \(see belo).25 E(w\).)-.25 E F1(encrypt)102 222 Q F2(argument ...)6 E F0
+.407(The encrypt command manipulates the information sent through the)161 234 R
+/F4 10/Courier@0 SF .408(TELNET ENCRYPT)2.908 F F0(op-)2.908 E(tion.)161 246 Q
+2.856(Note: Because)161 264 R .356(of e)2.856 F .356(xport controls, the)-.15 F
+F4 .355(TELNET ENCRYPT)2.855 F F0 .355(option is not supported outside of)2.855
+F(the United States and Canada.)161 276 Q -1.11(Va)161 294 S(lid ar)1.11 E
+(guments for the encrypt command are as follo)-.18 E(ws:)-.25 E F1(disable)161
+312 Q F2(type)6 E F1([input|output])6 E F0 1.099
+(Disables the speci\214ed type of encryption.)226 324 R 1.099
+(If you omit the input and output,)6.099 F .357
+(both input and output are disabled.)226 336 R 1.957 -.8(To o)5.357 H .357
+(btain a list of a).8 F -.25(va)-.2 G .357(ilable types, use the).25 F F1
+(encrypt disable ?)226 348 Q F0(command.)2.5 E F1(enable)161 366 Q F2(type)6 E
+F1([input|output])6 E F0 .867(Enables the speci\214ed type of encryption.)226
+378 R .868(If you omit input and output, both)5.867 F 2.117
+(input and output are enabled.)226 390 R 3.716 -.8(To o)7.116 H 2.116
+(btain a list of a).8 F -.25(va)-.2 G 2.116(ilable types, use the).25 F F1
+(encrypt enable ?)226 402 Q F0(command.)2.5 E F1(input)161 420 Q F0
+(This is the same as the)226 420 Q F1(encrypt start input)2.5 E F0(command.)2.5
+E F1(-input)161 438 Q F0(This is the same as the)226 438 Q F1
+(encrypt stop input)2.5 E F0(command.)2.5 E F1(output)161 456 Q F0
+(This is the same as the)226 456 Q F1(encrypt start output)2.5 E F0(command.)
+2.5 E F1(-output)161 474 Q F0(This is the same as the)226 474 Q F1
+(encrypt stop output)2.5 E F0(command.)2.5 E F1(start [input|output])161 492 Q
+F0 1.116(Attempts to start encryption.)226 504 R 1.116(If you omit)6.116 F F1
+(input)3.616 E F0(and)3.617 E F1(output,)3.617 E F0 1.117(both input)3.617 F
+.467(and output are enabled.)226 516 R 2.067 -.8(To o)5.467 H .467
+(btain a list of a).8 F -.25(va)-.2 G .467(ilable types, use the).25 F F1
+(encrypt)2.966 E(enable ?)226 528 Q F0(command.)2.5 E F1(status)161 546 Q F0
+(Lists the current status of encryption.)226 546 Q F1(stop [input|output])161
+564 Q F0 1.096(Stops encryption.)226 576 R 1.097
+(If you omit input and output, encryption is on both input)6.096 F(and output.)
+226 588 Q F1(type)161 606 Q F2(type)6.121 E F0 .121(Sets the def)226.121 606 R
+.121(ault type of encryption to be used with later)-.1 F F1 .12(encrypt start)
+2.62 F F0(or)2.62 E F1(encrypt stop)226 618 Q F0(commands.)2.5 E F1(environ)102
+636 Q F2(arguments...)6 E F0(The)161 648 Q F1(environ)3.189 E F0 .689
+(command is used to manipulate the the v)3.189 F .69
+(ariables that my be sent through the)-.25 F F4 .552(TELNET ENVIRON)161 660 R
+F0 3.052(option. The)3.052 F .552(initial set of v)3.052 F .551
+(ariables is tak)-.25 F .551(en from the users en)-.1 F(vironment,)-.4 E .501
+(with only the)161 672 R F4(DISPLAY)3.001 E F0(and)3.001 E F4(PRINTER)3.001 E
+F0 -.25(va)3.001 G .502(riables being e).25 F .502(xported by def)-.15 F 3.002
+(ault. The)-.1 F F4(USER)3.002 E F0 -.25(va)3.002 G(ri-).25 E(able is also e)
+161 684 Q(xported if the)-.15 E F1<ad61>4.166 E F0(or)2.5 E F1<ad6c>4.166 E F0
+(options are used.)2.5 E(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)
+132.57 750 Q 95.71(ution February)-.2 F(3, 1994)2.5 E(3)535 750 Q EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R -1.11(Va)161 96 S(lid ar)1.11 E
+(guments for the)-.18 E/F1 10/Courier-Bold@0 SF(environ)2.5 E F0(command are:)
+2.5 E F1(define)161 114 Q/F2 10/Courier-Oblique@0 SF(variable value)6 E F0
+1.082(De\214ne the v)216 126 R(ariable)-.25 E F2(variable)3.582 E F0 1.082
+(to ha)3.582 F 1.382 -.15(ve a v)-.2 H 1.082(alue of)-.1 F F2(value.)3.581 E F0
+(An)3.581 E 3.581(yv)-.15 G 1.081(ariables de-)492.549 126 R 1.922
+(\214ned by this command are automatically e)216 138 R 4.422(xported. The)-.15
+F F2(value)4.422 E F0 1.922(may be en-)4.422 F
+(closed in single or double quotes so that tabs and spaces may be included.)216
+150 Q F1(undefine)161 168 Q F2(variable)6 E F0(Remo)216 180 Q -.15(ve)-.15 G F2
+(variable)2.65 E F0(from the list of en)2.5 E(vironment v)-.4 E(ariables.)-.25
+E F1(export)161 198 Q F2(variable)6 E F0(Mark the v)216 210 Q(ariable)-.25 E F2
+(variable)2.5 E F0(to be e)2.5 E(xported to the remote side.)-.15 E F1
+(unexport)161 228 Q F2(variable)6 E F0 .697(Mark the v)216 240 R(ariable)-.25 E
+F2(variable)3.197 E F0 .697(to not be e)3.197 F .697(xported unless e)-.15 F
+.696(xplicitly ask)-.15 F .696(ed for by)-.1 F(the remote side.)216 252 Q F1
+(list)161 270 Q F0 1.416(List the current set of en)216 270 R 1.416
+(vironment v)-.4 F 3.916(ariables. Those)-.25 F(mark)3.916 E 1.416(ed with a)
+-.1 F/F3 10/Symbol SF(*)3.916 E F0 1.417(will be)3.917 F(sent automatically)216
+282 Q 2.5(,o)-.65 G(ther v)298.4 282 Q(ariables will only be sent if e)-.25 E
+(xplicitly requested.)-.15 E F1(?)161 300 Q F0
+(Prints out help information for the)216 300 Q F1(environ)2.5 E F0(command.)2.5
+E F1(logout)102 318 Q F0 .104(Sends the)161 318 R/F4 10/Courier@0 SF .104
+(TELNET LOGOUT)2.604 F F0 .104(option to the remote side.)2.604 F .104
+(This command is similar to a)5.104 F F1(close)2.604 E F0 .228(command; ho)161
+330 R(we)-.25 E -.15(ve)-.25 G 1.028 -.4(r, i).15 H 2.728(ft).4 G .228
+(he remote side does not support the)256.174 330 R F4(LOGOUT)2.729 E F0 .229
+(option, nothing happens.)2.729 F .233(If, ho)161 342 R(we)-.25 E -.15(ve)-.25
+G 1.033 -.4(r, t).15 H .233(he remote side does support the).4 F F4(LOGOUT)
+2.733 E F0 .233(option, this command should cause the)2.733 F .652
+(remote side to close the)161 354 R/F5 9/Times-Roman@0 SF(TELNET)3.152 E F0
+3.152(connection. If)3.152 F .653(the remote side also supports the concept of)
+3.152 F 1.904(suspending a user')161 366 R 4.404(ss)-.55 G 1.903
+(ession for later reattachment, the logout ar)250.872 366 R 1.903
+(gument indicates that you)-.18 F(should terminate the session immediately)161
+378 Q(.)-.65 E F1(mode)102 396 Q F2 -1(type Type)6.889 F F0 .889(is one of se)
+3.389 F -.15(ve)-.25 G .889(ral options, depending on the state of the).15 F F5
+(TELNET)3.389 E F0 3.39(session. The)3.39 F(remote)3.39 E .882(host is ask)161
+408 R .881(ed for permission to go into the requested mode.)-.1 F .881
+(If the remote host is capable of)5.881 F
+(entering that mode, the requested mode will be entered.)161 420 Q F1
+(character)161 438 Q F0 .715(Disable the)226 438 R F4 .716(TELNET LINEMODE)
+3.215 F F0 .716(option, or)3.216 F 3.216(,i)-.4 G 3.216(ft)416.834 438 S .716
+(he remote side does not un-)426.16 438 R(derstand the)226 450 Q F4(LINEMODE)
+2.5 E F0(option, then enter `)2.5 E(`character at a time`)-.74 E 2.5(`m)-.74 G
+(ode.)496.07 450 Q F1(line)161 468 Q F0 .948(Enable the)226 468 R F4 .948
+(TELNET LINEMODE)3.448 F F0 .948(option, or)3.448 F 3.448(,i)-.4 G 3.447(ft)
+415.448 468 S .947(he remote side does not un-)425.005 468 R 2.78(derstand the)
+226 480 R F4(LINEMODE)5.28 E F0 2.78(option, then attempt to enter `)5.28 F
+(`old-line-by-line`)-.74 E(`)-.74 E(mode.)226 492 Q F1(isig)161 510 Q F0(\()
+7.666 E F1(\255isig)1.666 E F0(\))1.666 E 1.43
+(Attempt to enable \(disable\) the)226 522 R F4(TRAPSIG)3.93 E F0 1.43
+(mode of the)3.93 F F4(LINEMODE)3.93 E F0(option.)3.93 E
+(This requires that the)226 534 Q F4(LINEMODE)2.5 E F0(option be enabled.)2.5 E
+F1(edit)161 552 Q F0(\()7.666 E F1(\255edit)1.666 E F0(\))1.666 E .865
+(Attempt to enable \(disable\) the)226 564 R F4(EDIT)3.365 E F0 .866
+(mode of the)3.365 F F4(LINEMODE)3.366 E F0 3.366(option. This)3.366 F
+(requires that the)226 576 Q F4(LINEMODE)2.5 E F0(option be enabled.)2.5 E F1
+(softtabs)161 594 Q F0(\()7.666 E F1(\255softtabs)1.666 E F0(\))1.666 E .83
+(Attempt to enable \(disable\) the)226 606 R F4(SOFT_TAB)3.33 E F0 .83
+(mode of the)3.33 F F4(LINEMODE)3.33 E F0(option.)3.33 E
+(This requires that the)226 618 Q F4(LINEMODE)2.5 E F0(option be enabled.)2.5 E
+F1(litecho)161 636 Q F0(\()7.666 E F1(\255litecho)1.666 E F0(\))1.666 E .83
+(Attempt to enable \(disable\) the)226 648 R F4(LIT_ECHO)3.33 E F0 .83
+(mode of the)3.33 F F4(LINEMODE)3.33 E F0(option.)3.33 E
+(This requires that the)226 660 Q F4(LINEMODE)2.5 E F0(option be enabled.)2.5 E
+F1(?)161 678 Q F0(Prints out help information for the)226 678 Q F1(mode)2.5 E
+F0(command.)2.5 E(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q
+95.71(ution February)-.2 F(3, 1994)2.5 E(4)535 750 Q EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R/F1 10/Courier-Bold@0 SF(open)102
+102 Q/F2 10/Courier-Oblique@0 SF(host)6 E F0 .833([[)2.5 G F1<ad6c>1.666 E F0
+(]).833 E F2(user)6 E F0(][)A F1<ad>1.666 E F2(port)A F0(])A .207
+(Open a connection to the named host.)161 114 R .207
+(If no port number is speci\214ed,)5.207 F F1(telnet)2.707 E F0 .206
+(will attempt to)2.707 F .263(contact a)161 126 R/F3 9/Times-Roman@0 SF(TELNET)
+2.763 E F0(serv)2.763 E .263(er at the def)-.15 F .263(ault port.)-.1 F .264
+(The host speci\214cation may be either a host name)5.264 F(\(see)161 138 Q/F4
+10/Courier@0 SF(hosts)3.531 E F0 4.562(\(5\)\) or)B 1.031
+(an Internet address speci\214ed in the `)3.531 F 1.03(`dot notation')-.74 F
+3.53('\()-.74 G(see)459.6 138 Q F4(inet)3.53 E F0 4.56(\(3\)\). The)B([)161.833
+150 Q F1<ad6c>2.499 E F0 3.03(]o).833 G .531(ption may be used to specify the \
+user name to be passed to the remote system via the)191.855 150 R F4(ENVIRON)
+161 162 Q F0 3.971(option. When)3.971 F 1.471
+(connecting to a non-standard port,)3.971 F F1(telnet)3.971 E F0 1.471
+(omits an)3.971 F 3.97(ya)-.15 G(utomatic)505 162 Q .631(initiation of)161 174
+R F3(TELNET)3.131 E F0 3.131(options. When)3.131 F .631
+(the port number is preceded by a minus sign, the initial)3.131 F .441
+(option ne)161 186 R .441(gotiation is done.)-.15 F .441
+(After establishing a connection, the \214le)5.441 F F4(.telnetrc)2.941 E F0
+.44(in the users)2.94 F .928(home directory is opened.)161 198 R .928(Lines be)
+5.928 F .928(ginning with a # are comment lines.)-.15 F .928
+(Blank lines are ig-)5.928 F 3.255(nored. Lines)161 210 R .755(that be)3.255 F
+.755(gin without white space are the start of a machine entry)-.15 F 5.755(.T)
+-.65 G .755(he \214rst thing)487.93 210 R .022
+(on the line is the name of the machine that is being connected to.)161 222 R
+.023(The rest of the line, and suc-)5.023 F(cessi)161 234 Q .856 -.15(ve l)-.25
+H .556(ines that be).15 F .556(gin with white space are assumed to be)-.15 F F1
+(telnet)3.056 E F0 .556(commands and are pro-)3.056 F(cessed as if the)161 246
+Q 2.5(yh)-.15 G(ad been typed in manually to the)233.61 246 Q F1(telnet)2.5 E
+F0(command prompt.)2.5 E F1(quit)102 264 Q F0 .114(Close an)161 264 R 2.614(yo)
+-.15 G(pen)208.298 264 Q F3(TELNET)2.614 E F0 .115(session and e)2.615 F(xit)
+-.15 E F1(telnet)2.615 E F0 2.615(.A)C 2.615(ne)376.32 264 S .115
+(nd of \214le \(in command mode\) will al-)388.375 264 R
+(so close a session and e)161 276 Q(xit.)-.15 E F1(send)102 294 Q F2(arguments)
+6 E F0 .024(Sends one or more special character sequences to the remote host.)
+161 306 R .024(The follo)5.024 F .024(wing are the ar)-.25 F(gu-)-.18 E
+(ments which may be speci\214ed \(more than one ar)161 318 Q
+(gument may be speci\214ed at a time\):)-.18 E F1(abort)161 336 Q F0(Sends the)
+202 336 Q F4(TELNET ABORT)2.5 E F0(\(Abort processes\) sequence.)2.5 E F1(ao)
+161 354 Q F0 1.15(Sends the)202 354 R F4 1.151(TELNET AO)3.651 F F0 1.151
+(\(Abort Output\) sequence, which should cause the remote)3.651 F
+(system to \215ush all output)202 366 Q/F5 10/Times-Italic@0 SF(fr)2.5 E(om)
+-.45 E F0(the remote system)2.5 E F5(to)2.5 E F0(the user')2.5 E 2.5(st)-.55 G
+(erminal.)454.89 366 Q F1(ayt)161 384 Q F0 1.18(Sends the)202 384 R F4 1.18
+(TELNET AYT)3.68 F F0 1.18(\(Are Y)3.68 F 1.18
+(ou There\) sequence, to which the remote system)-1.1 F
+(may or may not choose to respond.)202 396 Q F1(brk)161 414 Q F0 .47(Sends the)
+202 414 R F4 .47(TELNET BRK)2.97 F F0 .47(\(Break\) sequence, which may ha)2.97
+F .77 -.15(ve s)-.2 H .47(igni\214cance to the re-).15 F(mote system.)202 426 Q
+F1(ec)161 444 Q F0 .245(Sends the)202 444 R F4 .245(TELNET EC)2.745 F F0 .244
+(\(Erase Character\) sequence, which should cause the remote)2.745 F
+(system to erase the last character entered.)202 456 Q F1(el)161 474 Q F0 .385
+(Sends the)202 474 R F4 .385(TELNET EL)2.885 F F0 .385
+(\(Erase Line\) sequence, which should cause the remote sys-)2.885 F
+(tem to erase the line currently being entered.)202 486 Q F1(eof)161 504 Q F0
+(Sends the)202 504 Q F4(TELNET EOF)2.5 E F0(\(End Of File\) sequence.)2.5 E F1
+(eor)161 522 Q F0(Sends the)202 522 Q F4(TELNET EOR)2.5 E F0
+(\(End of Record\) sequence.)2.5 E F1(escape)161 540 Q F0(Sends the current)5 E
+F1(telnet)2.5 E F0(escape character \(initially `)2.5 E(`^')-.74 E('\).)-.74 E
+F1(ga)161 558 Q F0 .855(Sends the)202 558 R F4 .855(TELNET GA)3.355 F F0 .855
+(\(Go Ahead\) sequence, which lik)3.355 F .855(ely has no signi\214cance to)-.1
+F(the remote system.)202 570 Q F1(getstatus)161 588 Q F0 1.713
+(If the remote side supports the)202 600 R F4 1.713(TELNET STATUS)4.213 F F0
+(command,)4.213 E F1(getstatus)4.213 E F0(will)4.213 E(send the subne)202 612 Q
+(gotiation to request that the serv)-.15 E(er send its current option status.)
+-.15 E F1(ip)161 630 Q F0 1.355(Sends the)202 630 R F4 1.355(TELNET IP)3.855 F
+F0 1.354(\(Interrupt Process\) sequence, which should cause the re-)3.855 F
+(mote system to abort the currently running process.)202 642 Q F1(nop)161 660 Q
+F0(Sends the)202 660 Q F4(TELNET NOP)2.5 E F0(\(No OPeration\) sequence.)2.5 E
+F1(susp)161 678 Q F0(Sends the)202 678 Q F4(TELNET SUSP)2.5 E F0
+(\(SUSPend process\) sequence.)2.5 E(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G
+(istrib)132.57 750 Q 95.71(ution February)-.2 F(3, 1994)2.5 E(5)535 750 Q EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R/F1 10/Courier-Bold@0 SF(synch)
+161 96 Q F0 .65(Sends the)202 96 R/F2 10/Courier@0 SF .651(TELNET SYNCH)3.151 F
+F0 3.151(sequence. This)3.151 F .651(sequence causes the remote system to)3.151
+F .777(discard all pre)202 108 R .777(viously typed \(b)-.25 F .777
+(ut not yet read\) input.)-.2 F .776(This sequence is sent as)5.777 F/F3 9
+/Times-Roman@0 SF(TCP)3.276 E F0(ur)202 120 Q 1.665(gent data \(and may not w)
+-.18 F 1.665(ork if the remote system is a 4.2)-.1 F F3(BSD)A F0 1.666
+(system -- if it)4.166 F(doesn')202 132 Q 2.5(tw)-.18 G(ork, a lo)240.88 132 Q
+(wer case `)-.25 E(`r')-.74 E 2.5('m)-.74 G(ay be echoed on the terminal\).)
+336.33 132 Q F1(do)161 150 Q/F4 10/Courier-Oblique@0 SF(cmd)6 E F1(dont)161 168
+Q F4(cmd)6 E F1(will)161 186 Q F4(cmd)6 E F1(wont)161 204 Q F4(cmd)6 E F0 1.134
+(Sends the)202 216 R F2 1.133(TELNET DO)3.633 F F4(cmd)3.633 E F0(sequence.)
+3.633 E F4(Cmd)6.133 E F0 1.133(can be either a decimal number be-)3.633 F .865
+(tween 0 and 255, or a symbolic name for a speci\214c)202 228 R F2(TELNET)3.365
+E F0(command.)3.365 E F4(Cmd)5.865 E F0(can)3.365 E 1.181(also be either)202
+240 R F1(help)3.681 E F0(or)3.681 E F1(?)3.681 E F0 1.18
+(to print out help information, including a list of kno)3.681 F(wn)-.25 E
+(symbolic names.)202 252 Q F1(?)161 270 Q F0
+(Prints out help information for the)202 270 Q F1(send)2.5 E F0(command.)2.5 E
+F1(set)102 288 Q F4(argument value)6 E F1(unset)102 306 Q F4(argument value)6 E
+F0(The)161 318 Q F1(set)2.601 E F0 .101(command will set an)2.601 F 2.601(yo)
+-.15 G .101(ne of a number of)295.556 318 R F1(telnet)2.601 E F0 -.25(va)2.601
+G .101(riables to a speci\214c v).25 F .102(alue or to)-.25 F F2(TRUE)161 330 Q
+F0 2.722(.T)C .222(he special v)196.332 330 R(alue)-.25 E F1(off)2.722 E F0
+.222(turns of)2.722 F 2.722(ft)-.25 G .222(he function associated with the v)
+323.474 330 R .222(ariable, this is equi)-.25 F(v-)-.25 E .37
+(alent to using the)161 342 R F1(unset)2.87 E F0 2.871(command. The)2.87 F F1
+(unset)2.871 E F0 .371(command will disable or set to)2.871 F F2(FALSE)2.871 E
+F0(an)2.871 E(y)-.15 E 1.248(of the speci\214ed functions.)161 354 R 1.248
+(The v)6.248 F 1.248(alues of v)-.25 F 1.248(ariables may be interrog)-.25 F
+1.247(ated with the)-.05 F F1(display)3.747 E F0 2.886(command. The)161 366 R
+-.25(va)2.886 G .386(riables which may be set or unset, b).25 F .386
+(ut not toggled, are listed here.)-.2 F .387(In addi-)5.387 F .763(tion, an)161
+378 R 3.263(yo)-.15 G 3.263(ft)204.876 378 S .763(he v)214.249 378 R .763
+(ariables for the)-.25 F F1(toggle)3.263 E F0 .762(command may be e)3.263 F
+.762(xplicitly set or unset using the)-.15 F F1(set)161 390 Q F0(and)2.5 E F1
+(unset)2.5 E F0(commands.)2.5 E F1(ayt)161 408 Q F0(If)202 408 Q F3(TELNET)
+2.689 E F0 .189(is in localchars mode, or)2.689 F F2(LINEMODE)2.689 E F0 .189
+(is enabled, and the status character)2.689 F 1.056(is typed, a)202 420 R F2
+1.056(TELNET AYT)3.556 F F0 1.056(sequence \(see)3.556 F F1 1.056(send ayt)
+3.556 F F0 1.055(preceding\) is sent to the re-)3.556 F .327(mote host.)202 432
+R .328(The initial v)5.327 F .328(alue for the "Are Y)-.25 F .328
+(ou There" character is the terminal')-1.1 F 2.828(ss)-.55 G(ta-)529.45 432 Q
+(tus character)202 444 Q(.)-.55 E F1(echo)161 462 Q F0 .805(This is the v)202
+462 R .805(alue \(initially `)-.25 F(`^E')-.74 E .804('\) which, when in `)-.74
+F .804(`line by line')-.74 F 3.304('m)-.74 G .804(ode, toggles be-)474.792 462
+R .988(tween doing local echoing of entered characters \(for normal processing\
+\), and sup-)202 474 R
+(pressing echoing of entered characters \(for entering, say)202 486 Q 2.5(,ap)
+-.65 G(assw)442.66 486 Q(ord\).)-.1 E F1(eof)161 504 Q F0(If)202 504 Q F1
+(telnet)3.864 E F0 1.364(is operating in)3.864 F F2(LINEMODE)3.864 E F0 1.364
+(or `)3.864 F 1.364(`old line by line')-.74 F 3.864('m)-.74 G 1.363
+(ode, entering this)468.114 504 R .199(character as the \214rst character on a\
+ line will cause this character to be sent to the re-)202 516 R .12
+(mote system.)202 528 R .12(The initial v)5.12 F .119
+(alue of the eof character is tak)-.25 F .119(en to be the terminal')-.1 F(s)
+-.55 E F1(eof)2.619 E F0(character)202 540 Q(.)-.55 E F1(erase)161 558 Q F0(If)
+202 558 Q F1(telnet)3.12 E F0 .62(is in)3.12 F F1(localchars)3.12 E F0 .62
+(mode \(see)3.12 F F1 -2.88(toggle localchars)3.12 F F0(belo)3.12 E(w\),)-.25 E
+/F5 10/Times-Bold@0 SF(and)3.12 E F0(if)3.12 E F1(telnet)202 570 Q F0 1.385
+(is operating in `)3.885 F 1.385(`character at a time')-.74 F 3.885('m)-.74 G
+1.384(ode, then when this character is)407 570 R .417(typed, a)202 582 R F2
+.418(TELNET EC)2.917 F F0 .418(sequence \(see)2.918 F F1 -3.082(send ec)2.918 F
+F0(abo)2.918 E -.15(ve)-.15 G 2.918(\)i).15 G 2.918(ss)427.36 582 S .418
+(ent to the remote system.)438.058 582 R .325(The initial v)202 594 R .325
+(alue for the erase character is tak)-.25 F .325(en to be the terminal')-.1 F
+(s)-.55 E F1(erase)2.825 E F0(charac-)2.825 E(ter)202 606 Q(.)-.55 E F1(escape)
+161 624 Q F0 2.873(This is the)5 F F1(telnet)5.373 E F0 2.874
+(escape character \(initially `)5.373 F(`^[')-.74 E 2.874
+('\) which causes entry into)-.74 F F1(telnet)202 636 Q F0
+(command mode \(when connected to a remote system\).)2.5 E F1(flushoutput)161
+654 Q F0(If)202 666 Q F1(telnet)2.945 E F0 .445(is in)2.945 F F1(localchars)
+2.945 E F0 .445(mode \(see)2.945 F F1 -3.056(toggle localchars)2.944 F F0(belo)
+2.944 E .444(w\) and the)-.25 F F1(flushoutput)202 678 Q F0 .442
+(character is typed, a)2.942 F F2 .443(TELNET AO)2.943 F F0 .443
+(sequence \(see)2.943 F F1 -3.057(send ao)2.943 F F0(abo)2.943 E -.15(ve)-.15 G
+(\)).15 E .314(is sent to the remote host.)202 690 R .314(The initial v)5.314 F
+.314(alue for the \215ush character is tak)-.25 F .314(en to be the)-.1 F
+(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71
+(ution February)-.2 F(3, 1994)2.5 E(6)535 750 Q EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R(terminal')202 96 Q(s)-.55 E/F1
+10/Courier-Bold@0 SF(flush)2.5 E F0(character)2.5 E(.)-.55 E F1(forw1)161 114 Q
+(forw2)161 132 Q F0(If)202 132 Q/F2 9/Times-Roman@0 SF(TELNET)3.769 E F0 1.269
+(is operating in)3.769 F/F3 10/Courier@0 SF(LINEMODE)3.77 E F0 3.77(,t)C 1.27
+(hese are the characters that, when typed,)370.77 132 R .958
+(cause partial lines to be forw)202 144 R .958(arded to the remote system.)-.1
+F .958(The initial v)5.958 F .957(alue for the)-.25 F(forw)202 156 Q
+(arding characters are tak)-.1 E(en from the terminal')-.1 E 2.5(se)-.55 G
+(ol and eol2 characters.)414.23 156 Q F1(interrupt)161 174 Q F0(If)202 186 Q F1
+(telnet)2.944 E F0 .444(is in)2.944 F F1(localchars)2.944 E F0 .445(mode \(see)
+2.944 F F1 -3.055(toggle localchars)2.945 F F0(belo)2.945 E .445(w\) and the)
+-.25 F F1(interrupt)202 198 Q F0 .642(character is typed, a)3.142 F F3 .642
+(TELNET IP)3.142 F F0 .642(sequence \(see)3.142 F F1 -2.859(send ip)3.141 F F0
+(abo)3.141 E -.15(ve)-.15 G 3.141(\)i).15 G(s)536.11 198 Q .949
+(sent to the remote host.)202 210 R .949(The initial v)5.949 F .949
+(alue for the interrupt character is tak)-.25 F .95(en to be)-.1 F
+(the terminal')202 222 Q(s)-.55 E F1(intr)2.5 E F0(character)2.5 E(.)-.55 E F1
+(kill)161 240 Q F0(If)202 240 Q F1(telnet)2.95 E F0 .449(is in)2.949 F F1
+(localchars)2.949 E F0 .449(mode \(see)2.949 F F1 -3.051(toggle localchars)
+2.949 F F0(belo)2.949 E(w\),)-.25 E F1(and)2.949 E F0(if)2.949 E F1(telnet)202
+252 Q F0 1.384(is operating in `)3.884 F 1.385(`character at a time')-.74 F
+3.885('m)-.74 G 1.385(ode, then when this character is)406.995 252 R .418
+(typed, a)202 264 R F3 .418(TELNET EL)2.918 F F0 .418(sequence \(see)2.918 F F1
+-3.082(send el)2.918 F F0(abo)2.918 E -.15(ve)-.15 G 2.918(\)i).15 G 2.918(ss)
+427.362 264 S .418(ent to the remote system.)438.06 264 R(The initial v)202 276
+Q(alue for the kill character is tak)-.25 E(en to be the terminal')-.1 E(s)-.55
+E F1(kill)2.5 E F0(character)2.5 E(.)-.55 E F1(lnext)161 294 Q F0(If)202 294 Q
+F1(telnet)2.597 E F0 .097(is operating in)2.597 F F3(LINEMODE)2.597 E F0 .097
+(or `)2.597 F .097(`old line by line`)-.74 F 2.597(`m)-.74 G .098
+(ode, then this charac-)454.177 294 R 1.405(ter is tak)202 306 R 1.405
+(en to be the terminal')-.1 F(s)-.55 E F1(lnext)3.904 E F0(character)3.904 E
+6.404(.T)-.55 G 1.404(he initial v)422.56 306 R 1.404(alue for the lne)-.25 F
+(xt)-.15 E(character is tak)202 318 Q(en to be the terminal')-.1 E(s)-.55 E F1
+(lnext)2.5 E F0(character)2.5 E(.)-.55 E F1(quit)161 336 Q F0(If)202 336 Q F1
+(telnet)2.944 E F0 .444(is in)2.944 F F1(localchars)2.944 E F0 .445(mode \(see)
+2.944 F F1 -3.055(toggle localchars)2.945 F F0(belo)2.945 E .445(w\) and the)
+-.25 F F1(quit)202 348 Q F0 .546(character is typed, a)3.046 F F3 .545
+(TELNET BRK)3.046 F F0 .545(sequence \(see)3.045 F F1 -2.955(send brk)3.045 F
+F0(abo)3.045 E -.15(ve)-.15 G 3.045(\)i).15 G 3.045(ss)516.955 348 S(ent)527.78
+348 Q .629(to the remote host.)202 360 R .629(The initial v)5.629 F .629
+(alue for the quit character is tak)-.25 F .63(en to be the termi-)-.1 F(nal')
+202 372 Q(s)-.55 E F1(quit)2.5 E F0(character)2.5 E(.)-.55 E F1(reprint)161 390
+Q F0(If)202 402 Q F1(telnet)2.598 E F0 .097(is operating in)2.598 F F3
+(LINEMODE)2.597 E F0 .097(or `)2.597 F .097(`old line by line`)-.74 F 2.597(`m)
+-.74 G .097(ode, then this charac-)454.179 402 R .06(ter is tak)202 414 R .06
+(en to be the terminal')-.1 F(s)-.55 E F1(reprint)2.561 E F0(character)2.561 E
+5.061(.T)-.55 G .061(he initial v)422.465 414 R .061(alue for the reprint)-.25
+F(character is tak)202 426 Q(en to be the terminal')-.1 E(s)-.55 E F1(reprint)
+2.5 E F0(character)2.5 E(.)-.55 E F1(rlogin)161 444 Q F0 .956
+(This is the rlogin escape character)5 F 5.956(.I)-.55 G 3.456(fs)354.366 444 S
+.956(et, the normal)365.042 444 R F2(TELNET)3.456 E F0 .956
+(escape character is)3.456 F .357
+(ignored unless it is preceded by this character at the be)202 456 R .358
+(ginning of a line.)-.15 F .358(This char)5.358 F(-)-.2 E(acter)202 468 Q 3.14
+(,a)-.4 G 3.14(tt)231.11 468 S .64(he be)239.81 468 R .64
+(ginning of a line follo)-.15 F .639(wed by a ".")-.25 F .639
+(closes the connection; when fol-)5.639 F(lo)202 480 Q 1.31
+(wed by a ^Z it suspends the telnet command.)-.25 F 1.311
+(The initial state is to disable the)6.311 F(rlogin escape character)202 492 Q
+(.)-.55 E F1(start)161 510 Q F0 2.232(If the)202 510 R F3 2.231
+(TELNET TOGGLE-FLOW-CONTROL)4.731 F F0 2.231
+(option has been enabled, then this)4.731 F .005(character is tak)202 522 R
+.005(en to be the terminal')-.1 F(s)-.55 E F1(start)2.506 E F0(character)2.506
+E 5.006(.T)-.55 G .006(he initial v)436.06 522 R .006(alue for the kill)-.25 F
+(character is tak)202 534 Q(en to be the terminal')-.1 E(s)-.55 E F1(start)2.5
+E F0(character)2.5 E(.)-.55 E F1(stop)161 552 Q F0 2.232(If the)202 552 R F3
+2.231(TELNET TOGGLE-FLOW-CONTROL)4.731 F F0 2.231
+(option has been enabled, then this)4.731 F .434(character is tak)202 564 R
+.434(en to be the terminal')-.1 F(s)-.55 E F1(stop)2.934 E F0(character)2.934 E
+5.434(.T)-.55 G .434(he initial v)433.916 564 R .435(alue for the kill)-.25 F
+(character is tak)202 576 Q(en to be the terminal')-.1 E(s)-.55 E F1(stop)2.5 E
+F0(character)2.5 E(.)-.55 E F1(susp)161 594 Q F0(If)202 594 Q F1(telnet)2.576 E
+F0 .076(is in)2.576 F F1(localchars)2.576 E F0 .076(mode, or)2.576 F F3
+(LINEMODE)2.576 E F0 .076(is enabled, and the)2.576 F F1(suspend)2.575 E F0 .87
+(character is typed, a)202 606 R F3 .87(TELNET SUSP)3.37 F F0 .87
+(sequence \(see)3.37 F F1 -2.63(send susp)3.37 F F0(abo)3.37 E -.15(ve)-.15 G
+3.37(\)i).15 G 3.37(ss)505.48 606 S .87(ent to)516.63 606 R .246
+(the remote host.)202 618 R .246(The initial v)5.246 F .246
+(alue for the suspend character is tak)-.25 F .246(en to be the termi-)-.1 F
+(nal')202 630 Q(s)-.55 E F1(suspend)2.5 E F0(character)2.5 E(.)-.55 E F1
+(tracefile)161 648 Q F0 .537(This is the \214le to which the output, caused by)
+202 660 R F1(netdata)3.037 E F0(or)3.037 E F1(option)3.037 E F0 .538
+(tracing being)3.038 F F3(TRUE)202 672 Q F0 3.079(,w)C .579(ill be written.)
+238.799 672 R .579(If it is set to `)5.579 F(`)-.74 E F1<ad>1.666 E F0 -.74('')
+1.666 G 3.078(,t).74 G .578(hen tracing information will be written)381.85 672
+R(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71
+(ution February)-.2 F(3, 1994)2.5 E(7)535 750 Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R(to standard output \(the def)202
+96 Q(ault\).)-.1 E/F1 10/Courier-Bold@0 SF(worderase)161 114 Q F0(If)202 126 Q
+F1(telnet)2.597 E F0 .097(is operating in)2.597 F/F2 10/Courier@0 SF(LINEMODE)
+2.597 E F0 .097(or `)2.597 F .097(`old line by line`)-.74 F 2.597(`m)-.74 G
+.098(ode, then this charac-)454.177 126 R 1.386(ter is tak)202 138 R 1.386
+(en to be the terminal')-.1 F(s)-.55 E F1(worderase)3.885 E F0(character)3.885
+E 6.385(.T)-.55 G 1.385(he initial v)446.39 138 R 1.385(alue for the)-.25 F -.1
+(wo)202 150 S(rderase character is tak).1 E(en to be the terminal')-.1 E(s)-.55
+E F1(worderase)2.5 E F0(character)2.5 E(.)-.55 E F1(?)161 168 Q F0
+(Displays the le)202 168 Q -.05(ga)-.15 G(l).05 E F1(set)2.5 E F0(\()4.166 E F1
+(unset)1.666 E F0 4.166(\)c)1.666 G(ommands.)346.724 168 Q F1(slc)102 186 Q/F3
+10/Courier-Oblique@0 SF(state)6.383 E F0(The)5 E F1(slc)2.883 E F0 .384(comman\
+d \(Set Local Characters\) is used to set or change the state of the the speci\
+al)2.884 F 1.231(characters when the)161 198 R F2 1.231(TELNET LINEMODE)3.731 F
+F0 1.231(option has been enabled.)3.731 F 1.231(Special characters are)6.231 F
+.139(characters that get mapped to)161 210 R/F4 9/Times-Roman@0 SF(TELNET)2.639
+E F0 .139(commands sequences \(lik)2.639 F(e)-.1 E F1(ip)2.639 E F0(or)2.639 E
+F1(quit)2.639 E F0 2.639(\)o)C 2.639(rl)488.611 210 S .14(ine editing)497.36
+210 R(characters \(lik)161 222 Q(e)-.1 E F1(erase)2.5 E F0(and)2.5 E F1(kill)
+2.5 E F0(\). By def)A(ault, the local special characters are e)-.1 E(xported.)
+-.15 E F1(check)161 240 Q F0 -1.11(Ve)216 240 S .526
+(rify the current settings for the current special characters.)1.11 F .525
+(The remote side is)5.526 F .925(requested to send all the current special cha\
+racter settings, and if there are an)216 252 R(y)-.15 E
+(discrepancies with the local side, the local side will switch to the remote v)
+216 264 Q(alue.)-.25 E F1(export)161 282 Q F0 .497(Switch to the local def)216
+282 R .497(aults for the special characters.)-.1 F .496(The local def)5.496 F
+.496(ault charac-)-.1 F(ters are those of the local terminal at the time when)
+216 294 Q F1(telnet)2.5 E F0 -.1(wa)2.5 G 2.5(ss).1 G(tarted.)483.8 294 Q F1
+(import)161 312 Q F0 1.929(Switch to the remote def)216 312 R 1.929
+(aults for the special characters.)-.1 F 1.929(The remote def)6.929 F(ault)-.1
+E .37(characters are those of the remote system at the time when the)216 324 R
+F4(TELNET)2.869 E F0(connec-)2.869 E(tion w)216 336 Q(as established.)-.1 E F1
+(?)161 354 Q F0(Prints out help information for the)216 354 Q F1(slc)2.5 E F0
+(command.)2.5 E F1(status)102 372 Q F0(Sho)161 372 Q 2.808(wt)-.25 G .308
+(he current status of)189.118 372 R F1(telnet)2.809 E F0 2.809(.T)C .309
+(his includes the peer one is connected to, as well as the)316.641 372 R
+(current mode.)161 384 Q F1(toggle)102 402 Q F3(arguments ...)6 E F0 -.8(To)161
+414 S 2.112(ggle \(between).8 F F2(TRUE)4.612 E F0(and)4.612 E F2(FALSE)4.612 E
+F0 4.612(\)v)C 2.112(arious \215ags that control ho)324.76 414 R(w)-.25 E F1
+(telnet)4.611 E F0 2.111(responds to)4.611 F -2.15 -.25(ev e)161 426 T 2.73
+(nts. These).25 F .23(\215ags may be set e)2.73 F .231(xplicitly to)-.15 F F2
+(TRUE)2.731 E F0(or)2.731 E F2(FALSE)2.731 E F0 .231(using the)2.731 F F1(set)
+2.731 E F0(and)2.731 E F1(unset)2.731 E F0(com-)2.731 E .544(mands listed abo)
+161 438 R -.15(ve)-.15 G 5.544(.M).15 G .544(ore than one ar)255.382 438 R .543
+(gument may be speci\214ed.)-.18 F .543(The state of these \215ags may)5.543 F
+(be interrog)161 450 Q(ated with the)-.05 E F1(display)2.5 E F0 2.5(command. V)
+2.5 F(alid ar)-1.11 E(guments are:)-.18 E F1(authdebug)161 468 Q F0 -.45(Tu)226
+468 S(rns on deb).45 E(ugging information for the authentication code.)-.2 E F1
+(autoflush)161 486 Q F0(If)226 486 Q F1(autoflush)4.407 E F0(and)4.407 E F1
+(localchars)4.407 E F0 1.907(are both)4.407 F F2(TRUE)4.407 E F0 4.407(,t)C
+1.907(hen when the)451.219 486 R F1(ao)4.408 E F0 4.408(,o)C(r)536.67 486 Q F1
+(quit)226 498 Q F0 1.803(characters are recognized \(and transformed into)4.304
+F F4(TELNET)4.303 E F0(sequences;)4.303 E(see)226 510 Q F1(set)2.966 E F0(abo)
+2.966 E .766 -.15(ve f)-.15 H .466(or details\),).15 F F1(telnet)2.966 E F0
+.466(refuses to display an)2.966 F 2.966(yd)-.15 G .467(ata on the user')473.89
+510 R(s)-.55 E 2.241(terminal until the remote system ackno)226 522 R 2.241
+(wledges \(via a)-.25 F F2 2.241(TELNET TIMING)4.741 F(MARK)226 534 Q F0 .496
+(option\) that it has processed those)2.996 F F4(TELNET)2.996 E F0 2.996
+(sequences. The)2.996 F .497(initial v)2.996 F(al-)-.25 E .754
+(ue for this toggle is)226 546 R F2(TRUE)3.254 E F0 .753
+(if the terminal user had not done an "stty no\215sh",)3.253 F(otherwise)226
+558 Q F2(FALSE)2.5 E F0(\(see)2.5 E F2(stty)2.5 E F0(\(1\)\).)A F1(autodecrypt)
+161 576 Q F0 .556(When the)226 588 R F2 .556(TELNET ENCRYPT)3.056 F F0 .556
+(option is ne)3.056 F .556(gotiated, by def)-.15 F .557(ault the actual en-)-.1
+F .403(cryption \(decryption\) of the data stream does not start automatically)
+226 600 R 5.402(.T)-.65 G .402(he au-)514.888 600 R .789(toencrypt \(autodecry\
+pt\) command states that encryption of the output \(input\))226 612 R
+(stream should be enabled as soon as possible.)226 624 Q 2.87(Note: Because)226
+642 R .369(of e)2.869 F .369(xport controls, the)-.15 F F2 .369(TELNET ENCRYPT)
+2.869 F F0 .369(option is not sup-)2.869 F
+(ported outside the United States and Canada.)226 654 Q F1(autologin)161 672 Q
+F0 4.509(If the remote side supports the)226 672 R F2 4.509
+(TELNET AUTHENTICATION)7.009 F F0(option)7.009 E F4(TELNET)226 684 Q F0 3.448
+(attempts to use it to perform automatic authentication.)5.948 F 3.447(If the)
+8.447 F F2(AUTHENTICATION)226 696 Q F0 .197(option is not supported, the user')
+2.697 F 2.697(sl)-.55 G .197(ogin name are propa-)454.159 696 R -.05(ga)226 708
+S .41(ted through the).05 F F2 .41(TELNET ENVIRON)2.91 F F0 2.91(option. This)
+2.91 F .41(command is the same as)2.91 F(4.2 Berk)72 756 Q(ele)-.1 E 2.5(yD)
+-.15 G(istrib)132.57 756 Q 95.71(ution February)-.2 F(3, 1994)2.5 E(8)535 756 Q
+EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R(specifying)226 96 Q/F1 10
+/Courier-Oblique@0 SF(a)2.5 E F0(option on the)2.5 E/F2 10/Courier-Bold@0 SF
+(open)2.5 E F0(command.)2.5 E F2(autosynch)161 114 Q F0(If)226 114 Q F2
+(autosynch)4.854 E F0(and)4.854 E F2(localchars)4.854 E F0 2.354(are both)4.854
+F/F3 10/Courier@0 SF(TRUE)4.854 E F0 4.854(,t)C 2.354(hen when either the)
+454.348 114 R F2(intr)226 126 Q F0(or)4.17 E F2(quit)4.17 E F0 1.669
+(characters is typed \(see)4.169 F F2(set)4.169 E F0(abo)4.169 E 1.969 -.15
+(ve f)-.15 H 1.669(or descriptions of the).15 F F2(intr)226 138 Q F0(and)2.925
+E F2(quit)2.925 E F0 .426(characters\), the resulting)2.925 F/F4 9
+/Times-Roman@0 SF(TELNET)2.926 E F0 .426(sequence sent is follo)2.926 F(wed)
+-.25 E 1.634(by the)226 150 R F3 1.634(TELNET SYNCH)4.134 F F0 4.134
+(sequence. This)4.134 F(procedure)4.134 E F2(should)4.134 E F0 1.634
+(cause the re-)4.134 F .871(mote system to be)226 162 R .871(gin thro)-.15 F
+.872(wing a)-.25 F -.1(wa)-.15 G 3.372(ya).1 G .872(ll pre)385.008 162 R .872
+(viously typed input until both of)-.25 F(the)226 174 Q F4(TELNET)3.622 E F0
+1.122(sequences ha)3.622 F 1.422 -.15(ve b)-.2 H 1.121
+(een read and acted upon.).15 F 1.121(The initial v)6.121 F 1.121(alue of)-.25
+F(this toggle is)226 186 Q F3(FALSE)2.5 E F0(.)A F2(binary)161 204 Q F0
+(Enable or disable the)226 204 Q F3(TELNET BINARY)2.5 E F0
+(option on both input and output.)2.5 E F2(inbinary)161 222 Q F0
+(Enable or disable the)226 222 Q F3(TELNET BINARY)2.5 E F0(option on input.)2.5
+E F2(outbinary)161 240 Q F0(Enable or disable the)226 240 Q F3(TELNET BINARY)
+2.5 E F0(option on output.)2.5 E F2(crlf)161 258 Q F0 1.415(If this is)226 258
+R F3(TRUE)3.915 E F0 3.915(,t)C 1.415(hen carriage returns will be sent as)
+298.72 258 R F3(<CR><LF>)3.915 E F0 3.915(.I)C 3.915(ft)507.72 258 S 1.415
+(his is)517.745 258 R F3(FALSE)226 270 Q F0 3.26(,t)C .759
+(hen carriage returns will be send as)264.54 270 R F3(<CR><NUL>)3.259 E F0
+3.259(.T)C .759(he initial v)479.292 270 R(alue)-.25 E(for this toggle is)226
+282 Q F3(FALSE)2.5 E F0(.)A F2(crmod)161 300 Q F0 -.8(To)226 300 S 1.1
+(ggle carriage return mode.).8 F 1.1
+(When this mode is enabled, most carriage re-)6.1 F .745(turn characters recei)
+226 312 R -.15(ve)-.25 G 3.244(df).15 G .744
+(rom the remote host will be mapped into a carriage)329.174 312 R 1.492
+(return follo)226 324 R 1.492(wed by a line feed.)-.25 F 1.493
+(This mode does not af)6.492 F 1.493(fect those characters)-.25 F .207
+(typed by the user)226 336 R 2.707(,o)-.4 G .207(nly those recei)305.028 336 R
+-.15(ve)-.25 G 2.706(df).15 G .206(rom the remote host.)383.838 336 R .206
+(This mode is not)5.206 F -.15(ve)226 348 S 1.026
+(ry useful unless the remote host only sends carriage return, b).15 F 1.026
+(ut ne)-.2 F -.15(ve)-.25 G 3.526(rl).15 G(ine)527.78 348 Q 2.5(feed. The)226
+360 R(initial v)2.5 E(alue for this toggle is)-.25 E F3(FALSE)2.5 E F0(.)A F2
+(debug)161 378 Q F0 -.8(To)226 378 S .073(ggles sock).8 F .073(et le)-.1 F -.15
+(ve)-.25 G 2.573(ld).15 G(eb)314.629 378 Q .073(ugging \(useful only to the)-.2
+F F2 .072(super user)2.573 F F0 .072(\). The initial)B -.25(va)226 390 S
+(lue for this toggle is).25 E F3(FALSE)2.5 E F0(.)A F2(encdebug)161 408 Q F0
+-.45(Tu)226 408 S(rns on deb).45 E(ugging information for the encryption code.)
+-.2 E F2(localchars)161 426 Q F0 1.485(If this is)5 F F3(TRUE)3.985 E F0 3.985
+(,t)C 1.485(hen the)299 426 R F2(flush)3.985 E F0(,)A F2(interrupt)3.986 E F0
+(,)A F2(quit)3.986 E F0(,)A F2(erase)3.986 E F0 3.986(,a)C(nd)502.014 426 Q F2
+(kill)3.986 E F0 2.944(characters \(see)226 438 R F2(set)5.444 E F0(abo)5.444 E
+-.15(ve)-.15 G 5.443(\)a).15 G 2.943(re recognized locally)353.755 438 R 5.443
+(,a)-.65 G 2.943(nd transformed into)455.234 438 R 3.265
+(\(hopefully\) appropriate)226 450 R F4(TELNET)5.765 E F0 3.265
+(control sequences \(respecti)5.765 F -.15(ve)-.25 G(ly).15 E F2(ao)5.766 E F0
+(,)A F2(ip)5.766 E F0(,)A F2(brk)226 462 Q F0(,)A F2(ec)2.788 E F0 2.788(,a)C
+(nd)271.016 462 Q F2(el)2.787 E F0 2.787(;s)C(ee)305.26 462 Q F2(send)2.787 E
+F0(abo)2.787 E -.15(ve)-.15 G 2.787(\). The).15 F .287(initial v)2.787 F .287
+(alue for this toggle is)-.25 F F3(TRUE)2.787 E F0 .045(in `)226 474 R .045
+(`old line by line')-.74 F 2.546('m)-.74 G .046(ode, and)318.906 474 R F3
+(FALSE)2.546 E F0 .046(in `)2.546 F .046(`character at a time')-.74 F 2.546('m)
+-.74 G 2.546(ode. When)494.134 474 R(the)226 486 Q F3(LINEMODE)2.894 E F0 .394
+(option is enabled, the v)2.894 F .394(alue of)-.25 F F2(localchars)2.893 E F0
+.393(is ignored, and)2.893 F 2.388(assumed to al)226 498 R -.1(wa)-.1 G 2.388
+(ys be).1 F F3(TRUE)4.888 E F0 4.888(.I)C(f)359.5 498 Q F3(LINEMODE)4.888 E F0
+2.388(has e)4.888 F -.15(ve)-.25 G 4.888(rb).15 G 2.389(een enabled, then)
+465.522 498 R F2(quit)226 510 Q F0 1.574(is sent as)4.074 F F2(abort)4.074 E F0
+4.074(,a)C(nd)338.42 510 Q F2 1.574(eof and)4.074 F F0 1.573(are sent as)4.074
+F F2 1.573(eof and)4.073 F(susp)4.073 E F0 4.073(,s)C(ee)531.12 510 Q F2(send)
+226 522 Q F0(abo)2.5 E -.15(ve)-.15 G(\).).15 E F2(netdata)161 540 Q F0 -.8(To)
+226 540 S .993(ggles the display of all netw).8 F .994(ork data \(in he)-.1 F
+.994(xadecimal format\).)-.15 F .994(The initial)5.994 F -.25(va)226 552 S
+(lue for this toggle is).25 E F3(FALSE)2.5 E F0(.)A F2(options)161 570 Q F0 -.8
+(To)226 570 S .625(ggles the display of some internal).8 F F2(telnet)3.125 E F0
+.625(protocol processing \(ha)3.125 F .625(ving to)-.2 F(do with)226 582 Q F4
+(TELNET)2.5 E F0 2.5(options\). The)2.5 F(initial v)2.5 E
+(alue for this toggle is)-.25 E F3(FALSE)2.5 E F0(.)A F2(prettydump)161 600 Q
+F0 .133(When the)5 F F2(netdata)2.633 E F0 .134(toggle is enabled, if)2.633 F
+F2(prettydump)2.634 E F0 .134(is enabled the output)2.634 F .745(from the)226
+612 R F2(netdata)3.245 E F0 .744
+(command will be formatted in a more user readable for)3.244 F(-)-.2 E 3.199
+(mat. Spaces)226 624 R .699
+(are put between each character in the output, and the be)3.199 F(ginning)-.15
+E(of an)226 636 Q(y)-.15 E F4(TELNET)2.5 E F0
+(escape sequence is preceded by a ')2.5 E/F5 10/Symbol SF(*)A F0 2.5('t)C 2.5
+(oa)442.553 636 S(id in locating them.)454.493 636 Q F2(skiprc)161 654 Q F0
+4.589(When the skiprc toggle is)226 654 R F3(TRUE)7.089 E F0(,)A F4(TELNET)
+7.089 E F0 4.589(skips the reading of the)7.089 F F3(.telnetrc)226 666 Q F0
+1.033(\214le in the users home directory when connections are opened.)3.533 F
+(The initial v)226 678 Q(alue for this toggle is)-.25 E F3(FALSE.)2.5 E F0
+(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71
+(ution February)-.2 F(3, 1994)2.5 E(9)535 750 Q EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNET \( 1 \))72 48 R(BSD Reference Manual)
+258.235 48 Q -.834(TELNET \( 1 \))485.572 48 R/F1 10/Courier-Bold@0 SF
+(termdata)161 96 Q F0 -.8(To)226 96 S .934
+(ggles the display of all terminal data \(in he).8 F .933(xadecimal format\).)
+-.15 F .933(The initial)5.933 F -.25(va)226 108 S(lue for this toggle is).25 E
+/F2 10/Courier@0 SF(FALSE)2.5 E F0(.)A F1(verbose_encrypt)161 126 Q F0 1.129
+(When the)226 138 R F1(verbose_encrypt)3.629 E F0 1.13(toggle is)3.629 F F2
+(TRUE)3.63 E F0(,)A/F3 9/Times-Roman@0 SF(TELNET)3.63 E F0 1.13
+(prints out a mes-)3.63 F 1.377
+(sage each time encryption is enabled or disabled.)226 150 R 1.376
+(The initial v)6.377 F 1.376(alue for this)-.25 F 1.223(toggle is)226 162 R F2
+(FALSE.)3.723 E F0 3.723(Note: Because)3.723 F 1.224(of e)3.724 F 1.224
+(xport controls, data encryption is not)-.15 F
+(supported outside of the United States and Canada.)226 174 Q F1(?)161 192 Q F0
+(Displays the le)226 192 Q -.05(ga)-.15 G(l).05 E F1(toggle)2.5 E F0(commands.)
+2.5 E F1(z)102 210 Q F0(Suspend)161 210 Q F1(telnet)2.5 E F0 2.5(.T)C
+(his command only w)244.5 210 Q(orks when the user is using the)-.1 E F2(csh)
+2.5 E F0(\(1\).)A F1(!)102 228 Q F0([)6.833 E/F4 10/Courier-Oblique@0 SF
+(command).833 E F0(]).833 E(Ex)161 240 Q .293
+(ecute a single command in a subshell on the local system.)-.15 F(If)5.292 E F1
+(command)2.792 E F0 .292(is omitted, then an)2.792 F(interacti)161 252 Q .3
+-.15(ve s)-.25 H(ubshell is in).15 E -.2(vo)-.4 G -.1(ke).2 G(d.).1 E F1(?)102
+270 Q F0([)6.833 E F4(command).833 E F0(]).833 E 1.177(Get help.)161 282 R -.4
+(Wi)6.177 G 1.178(th no ar).4 F(guments,)-.18 E F1(telnet)3.678 E F0 1.178
+(prints a help summary)3.678 F 6.178(.I)-.65 G 3.678(fac)433.358 282 S 1.178
+(ommand is speci\214ed,)452.924 282 R F1(telnet)161 294 Q F0
+(will print the help information for just that command.)2.5 E/F5 10
+/Times-Bold@0 SF(ENVIR)72 318 Q(ONMENT)-.3 E F1(Telnet)102 330 Q F0 .666
+(uses at least the)3.166 F F2(HOME)3.166 E F0(,)A F2(SHELL)3.165 E F0(,)A F2
+(DISPLAY)3.165 E F0 3.165(,a)C(nd)326.255 330 Q F2(TERM)3.165 E F0(en)3.165 E
+.665(vironment v)-.4 F 3.165(ariables. Other)-.25 F(en)3.165 E(vironment)-.4 E
+-.25(va)102 342 S(riables may be propag).25 E(ated to the other side via the)
+-.05 E F2(TELNET ENVIRON)2.5 E F0(option.)2.5 E F5(FILES)72 366 Q F2
+(~/.telnetrc)102 378 Q F0(user customized telnet startup v)5 E(alues)-.25 E F5
+(HIST)72 402 Q(OR)-.18 E(Y)-.35 E F0(The)102 414 Q F1(Telnet)2.5 E F0
+(command appeared in 4.2)2.5 E F3(BSD)A F0(.)A F5(NO)72 438 Q(TES)-.4 E F0
+(On some remote systems, echo has to be turned of)102 450 Q 2.5(fm)-.25 G
+(anually when in `)316.44 450 Q(`old line by line')-.74 E 2.5('m)-.74 G(ode.)
+465.22 450 Q .691(In `)102 468 R .691(`old line by line')-.74 F 3.191('m)-.74 G
+.691(ode or)198.685 468 R F2(LINEMODE)3.191 E F0 .691(the terminal')3.191 F(s)
+-.55 E F1(eof)3.191 E F0 .691(character is only recognized \(and sent to the)
+3.191 F(remote system\) when it is the \214rst character on a line.)102 480 Q
+(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71
+(ution February)-.2 F(3, 1994)2.5 E(10)530 750 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/appl/telnet/telnet/telnet.0.txt b/krb5-1-6/src/appl/telnet/telnet/telnet.0.txt
new file mode 100644
index 000000000..41d410bab
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/telnet.0.txt
@@ -0,0 +1,718 @@
+TELNET(1)                    BSD Reference Manual                    TELNET(1)
+
+NNAAMMEE
+     tteellnneett - user interface to the TELNET protocol
+
+SSYYNNOOPPSSIISS
+     tteellnneett [--88] [--EE] [--FF] [--KK] [--LL] [--SS _t_o_s] [--XX _a_u_t_h_t_y_p_e] [--aa] [--cc] [--dd] [--ee
+            _e_s_c_a_p_e_c_h_a_r] [--ff] [--kk _r_e_a_l_m] [--ll _u_s_e_r] [--nn _t_r_a_c_e_f_i_l_e] [--rr] [--xx]
+            [_h_o_s_t [port]]
+
+DDEESSCCRRIIPPTTIIOONN
+     The tteellnneett command is used to communicate with another host using the
+     TELNET protocol.  If tteellnneett is invoked without the _h_o_s_t argument, it en-
+     ters command mode, indicated by its prompt (tteellnneett>>). In this mode, it
+     accepts and executes the commands listed below.  If it is invoked with
+     arguments, it performs an ooppeenn command with those arguments.
+
+     Options:
+
+     --88      Specifies an 8-bit data path.  This causes an attempt to negoti-
+             ate the TELNET BINARY option on both input and output.
+
+     --EE      Stops any character from being recognized as an escape character.
+
+     --FF      If Kerberos V5 authentication is being used, the --FF option allows
+             the local credentials to be forwarded to the remote system, in-
+             cluding any credentials that have already been forwarded into the
+             local environment.
+
+     --KK      Specifies no automatic login to the remote system.
+
+     --LL      Specifies an 8-bit data path on output.  This causes the BINARY
+             option to be negotiated on output.
+
+     --SS _t_o_s  Sets the IP type-of-service (TOS) option for the telnet connec-
+             tion to the value _t_o_s_, which can be a numeric TOS value or, on
+             systems that support it, a symbolic TOS name found in the
+             /etc/iptos file.
+
+     --XX _a_t_y_p_e
+             Disables the _a_t_y_p_e type of authentication.
+
+     --aa      Attempt automatic login.  Currently, this sends the user name via
+             the USER variable of the ENVIRON option if supported by the re-
+             mote system.  The name used is that of the current user as re-
+             turned by getlogin(2) if it agrees with the current user ID, oth-
+             erwise it is the name associated with the user ID.
+
+     --cc      Disables the reading of the user's _._t_e_l_n_e_t_r_c file.  (See the
+             ttooggggllee sskkiipprrcc command on this man page.)
+
+     --dd      Sets the initial value of the ddeebbuugg toggle to TRUE
+
+     --ee _e_s_c_a_p_e _c_h_a_r
+             Sets the initial tteellnneett tteellnneett escape character to _e_s_c_a_p_e _c_h_a_r_.
+             If _e_s_c_a_p_e _c_h_a_r is omitted, then there will be no escape charac-
+             ter.
+
+     --ff      If Kerberos V5 authentication is being used, the --ff option allows
+             the local credentials to be forwarded to the remote system.
+
+     --kk _r_e_a_l_m
+             If Kerberos authentication is being used, the --kk option requests
+             that telnet obtain tickets for the remote host in realm realm in-
+             stead of the remote host's realm, as determined by
+
+             krb_realmofhost(3).
+
+     --ll _u_s_e_r
+             When connecting to the remote system, if the remote system under-
+             stands the ENVIRON option, then _u_s_e_r will be sent to the remote
+             system as the value for the variable USER.  This option implies
+             the --aa option.  This option may also be used with the ooppeenn com-
+             mand.
+
+     --nn _t_r_a_c_e_f_i_l_e
+             Opens _t_r_a_c_e_f_i_l_e for recording trace information.  See the sseett
+             ttrraacceeffiillee command below.
+
+     --rr      Specifies a user interface similar to rlogin(1).  In this mode,
+             the escape character is set to the tilde (~) character, unless
+             modified by the -e option.
+
+     --xx      Turns on encryption of the data stream if possible.  This option
+             is not available outside of the United States and Canada.
+
+     _h_o_s_t    Indicates the official name, an alias, or the Internet address of
+             a remote host.
+
+     _p_o_r_t    Indicates a port number (address of an application).  If a number
+             is not specified, the default tteellnneett port is used.
+
+     When in rlogin mode, a line of the form ~.  disconnects from the remote
+     host; ~ is the telnet escape character.  Similarly, the line ~^Z suspends
+     the telnet session.  The line ~^] escapes to the normal telnet escape
+     prompt.
+
+     Once a connection has been opened, tteellnneett will attempt to enable the
+     TELNET LINEMODE option.  If this fails, then tteellnneett will revert to one of
+     two input modes: either ``character at a time'' or ``old line by line''
+     depending on what the remote system supports.
+
+     When LINEMODE is enabled, character processing is done on the local sys-
+     tem, under the control of the remote system.  When input editing or char-
+     acter echoing is to be disabled, the remote system will relay that infor-
+     mation.  The remote system will also relay changes to any special charac-
+     ters that happen on the remote system, so that they can take effect on
+     the local system.
+
+     In ``character at a time'' mode, most text typed is immediately sent to
+     the remote host for processing.
+
+     In ``old line by line'' mode, all text is echoed locally, and (normally)
+     only completed lines are sent to the remote host.  The ``local echo char-
+     acter'' (initially ``^E'') may be used to turn off and on the local echo
+     (this would mostly be used to enter passwords without the password being
+     echoed).
+
+     If the LINEMODE option is enabled, or if the llooccaallcchhaarrss toggle is TRUE
+     (the default for ``old line by line``; see below), the user's qquuiitt, iinnttrr,
+     and fflluusshh characters are trapped locally, and sent as TELNET protocol se-
+     quences to the remote side.  If LINEMODE has ever been enabled, then the
+     user's ssuusspp and eeooff are also sent as TELNET protocol sequences, and qquuiitt
+     is sent as a TELNET ABORT instead of BREAK There are options (see ttooggggllee
+     aauuttoofflluusshh and ttooggggllee aauuttoossyynncchh below) which cause this action to flush
+     subsequent output to the terminal (until the remote host acknowledges the
+     TELNET sequence) and flush previous terminal input (in the case of qquuiitt
+     and iinnttrr).
+
+     While connected to a remote host, tteellnneett command mode may be entered by
+     typing the tteellnneett ``escape character'' (initially ``^]'').  When in com-
+     mand mode, the normal terminal editing conventions are available.
+
+     The following tteellnneett commands are available.  Only enough of each command
+     to uniquely identify it need be typed (this is also true for arguments to
+     the mmooddee, sseett, ttooggggllee, uunnsseett, ssllcc, eennvviirroonn, and ddiissppllaayy commands).
+
+     aauutthh _a_r_g_u_m_e_n_t _._._.
+                The auth command manipulates the information sent through the
+                TELNET AUTHENTICATE option.  Valid arguments for the auth com-
+                mand are as follows:
+
+                ddiissaabbllee _t_y_p_e  Disables the specified type of authentication.
+                              To obtain a list of available types, use the
+                              aauutthh ddiissaabbllee ?? command.
+
+                eennaabbllee _t_y_p_e   Enables the specified type of authentication.
+                              To obtain a list of available types, use the
+                              aauutthh eennaabbllee ?? command.
+
+                ssttaattuuss        Lists the current status of the various types of
+                              authentication.
+
+     cclloossee      Close a TELNET session and return to command mode.
+
+     ddiissppllaayy _a_r_g_u_m_e_n_t _._._.
+                Displays all, or some, of the sseett and ttooggggllee values (see be-
+                low).
+
+     eennccrryypptt _a_r_g_u_m_e_n_t _._._.
+                The encrypt command manipulates the information sent through
+                the TELNET ENCRYPT option.
+
+                Note:  Because of export controls, the TELNET ENCRYPT option
+                is not supported outside of the United States and Canada.
+
+                Valid arguments for the encrypt command are as follows:
+
+                ddiissaabbllee _t_y_p_e [[iinnppuutt||oouuttppuutt]]
+                              Disables the specified type of encryption.  If
+                              you omit the input and output, both input and
+                              output are disabled.  To obtain a list of avail-
+                              able types, use the eennccrryypptt ddiissaabbllee ?? command.
+
+                eennaabbllee _t_y_p_e [[iinnppuutt||oouuttppuutt]]
+                              Enables the specified type of encryption.  If
+                              you omit input and output, both input and output
+                              are enabled.  To obtain a list of available
+                              types, use the eennccrryypptt eennaabbllee ?? command.
+
+                iinnppuutt         This is the same as the eennccrryypptt ssttaarrtt iinnppuutt com-
+                              mand.
+
+                --iinnppuutt        This is the same as the eennccrryypptt ssttoopp iinnppuutt com-
+                              mand.
+
+                oouuttppuutt        This is the same as the eennccrryypptt ssttaarrtt oouuttppuutt
+                              command.
+
+                --oouuttppuutt       This is the same as the eennccrryypptt ssttoopp oouuttppuutt com-
+                              mand.
+
+                ssttaarrtt [[iinnppuutt||oouuttppuutt]]
+                              Attempts to start encryption.  If you omit iinnppuutt
+                              and oouuttppuutt,, both input and output are enabled.
+                              To obtain a list of available types, use the
+
+                              eennccrryypptt eennaabbllee ?? command.
+
+                ssttaattuuss        Lists the current status of encryption.
+
+                ssttoopp [[iinnppuutt||oouuttppuutt]]
+                              Stops encryption.  If you omit input and output,
+                              encryption is on both input and output.
+
+                ttyyppee _t_y_p_e     Sets the default type of encryption to be used
+                              with later eennccrryypptt ssttaarrtt or eennccrryypptt ssttoopp com-
+                              mands.
+
+     eennvviirroonn _a_r_g_u_m_e_n_t_s_._._.
+                The eennvviirroonn command is used to manipulate the the variables
+                that my be sent through the TELNET ENVIRON option.  The ini-
+                tial set of variables is taken from the users environment,
+                with only the DISPLAY and PRINTER variables being exported by
+                default.  The USER variable is also exported if the --aa or --ll
+                options are used.
+                Valid arguments for the eennvviirroonn command are:
+
+                ddeeffiinnee _v_a_r_i_a_b_l_e _v_a_l_u_e
+                            Define the variable _v_a_r_i_a_b_l_e to have a value of
+                            _v_a_l_u_e_. Any variables defined by this command are
+                            automatically exported.  The _v_a_l_u_e may be enclosed
+                            in single or double quotes so that tabs and spaces
+                            may be included.
+
+                uunnddeeffiinnee _v_a_r_i_a_b_l_e
+                            Remove _v_a_r_i_a_b_l_e from the list of environment vari-
+                            ables.
+
+                eexxppoorrtt _v_a_r_i_a_b_l_e
+                            Mark the variable _v_a_r_i_a_b_l_e to be exported to the
+                            remote side.
+
+                uunneexxppoorrtt _v_a_r_i_a_b_l_e
+                            Mark the variable _v_a_r_i_a_b_l_e to not be exported un-
+                            less explicitly asked for by the remote side.
+
+                lliisstt        List the current set of environment variables.
+                            Those marked with a ** will be sent automatically,
+                            other variables will only be sent if explicitly
+                            requested.
+
+                ??           Prints out help information for the eennvviirroonn com-
+                            mand.
+
+     llooggoouutt     Sends the TELNET LOGOUT option to the remote side.  This com-
+                mand is similar to a cclloossee command; however, if the remote
+                side does not support the LOGOUT option, nothing happens.  If,
+                however, the remote side does support the LOGOUT option, this
+                command should cause the remote side to close the TELNET con-
+                nection.  If the remote side also supports the concept of sus-
+                pending a user's session for later reattachment, the logout
+                argument indicates that you should terminate the session imme-
+                diately.
+
+     mmooddee _t_y_p_e  _T_y_p_e is one of several options, depending on the state of the
+                TELNET session.  The remote host is asked for permission to go
+                into the requested mode.  If the remote host is capable of en-
+                tering that mode, the requested mode will be entered.
+
+                cchhaarraacctteerr     Disable the TELNET LINEMODE option, or, if the
+                              remote side does not understand the LINEMODE op-
+
+                              tion, then enter ``character at a time`` mode.
+
+                lliinnee          Enable the TELNET LINEMODE option, or, if the
+                              remote side does not understand the LINEMODE op-
+                              tion, then attempt to enter ``old-line-by-line``
+                              mode.
+
+                iissiigg (--iissiigg)  Attempt to enable (disable) the TRAPSIG mode of
+                              the LINEMODE option.  This requires that the
+                              LINEMODE option be enabled.
+
+                eeddiitt (--eeddiitt)  Attempt to enable (disable) the EDIT mode of the
+                              LINEMODE option.  This requires that the
+                              LINEMODE option be enabled.
+
+                ssooffttttaabbss (--ssooffttttaabbss)
+                              Attempt to enable (disable) the SOFT_TAB mode of
+                              the LINEMODE option.  This requires that the
+                              LINEMODE option be enabled.
+
+                lliitteecchhoo (--lliitteecchhoo)
+                              Attempt to enable (disable) the LIT_ECHO mode of
+                              the LINEMODE option.  This requires that the
+                              LINEMODE option be enabled.
+
+                ??             Prints out help information for the mmooddee com-
+                              mand.
+
+     ooppeenn _h_o_s_t [[--ll] _u_s_e_r][--_p_o_r_t]
+                Open a connection to the named host.  If no port number is
+                specified, tteellnneett will attempt to contact a TELNET server at
+                the default port.  The host specification may be either a host
+                name (see hosts(5))  or an Internet address specified in the
+                ``dot notation'' (see inet(3)).  The [--ll] option may be used
+                to specify the user name to be passed to the remote system via
+                the ENVIRON option.  When connecting to a non-standard port,
+                tteellnneett omits any automatic initiation of TELNET options.  When
+                the port number is preceded by a minus sign, the initial op-
+                tion negotiation is done.  After establishing a connection,
+                the file _._t_e_l_n_e_t_r_c in the users home directory is opened.
+                Lines beginning with a # are comment lines.  Blank lines are
+                ignored.  Lines that begin without white space are the start
+                of a machine entry.  The first thing on the line is the name
+                of the machine that is being connected to.  The rest of the
+                line, and successive lines that begin with white space are as-
+                sumed to be tteellnneett commands and are processed as if they had
+                been typed in manually to the tteellnneett command prompt.
+
+     qquuiitt       Close any open TELNET session and exit tteellnneett. An end of file
+                (in command mode) will also close a session and exit.
+
+     sseenndd _a_r_g_u_m_e_n_t_s
+                Sends one or more special character sequences to the remote
+                host.  The following are the arguments which may be specified
+                (more than one argument may be specified at a time):
+
+                aabboorrtt   Sends the TELNET ABORT (Abort processes) sequence.
+
+                aaoo      Sends the TELNET AO (Abort Output) sequence, which
+                        should cause the remote system to flush all output
+                        _f_r_o_m the remote system _t_o the user's terminal.
+
+                aayytt     Sends the TELNET AYT (Are You There) sequence, to
+                        which the remote system may or may not choose to re-
+
+
+                        spond.
+
+                bbrrkk     Sends the TELNET BRK (Break) sequence, which may have
+                        significance to the remote system.
+
+                eecc      Sends the TELNET EC (Erase Character) sequence, which
+                        should cause the remote system to erase the last char-
+                        acter entered.
+
+                eell      Sends the TELNET EL (Erase Line) sequence, which
+                        should cause the remote system to erase the line cur-
+                        rently being entered.
+
+                eeooff     Sends the TELNET EOF (End Of File) sequence.
+
+                eeoorr     Sends the TELNET EOR (End of Record) sequence.
+
+                eessccaappee  Sends the current tteellnneett escape character (initially
+                        ``^'').
+
+                ggaa      Sends the TELNET GA (Go Ahead) sequence, which likely
+                        has no significance to the remote system.
+
+                ggeettssttaattuuss
+                        If the remote side supports the TELNET STATUS command,
+                        ggeettssttaattuuss will send the subnegotiation to request that
+                        the server send its current option status.
+
+                iipp      Sends the TELNET IP (Interrupt Process) sequence,
+                        which should cause the remote system to abort the cur-
+                        rently running process.
+
+                nnoopp     Sends the TELNET NOP (No OPeration) sequence.
+
+                ssuusspp    Sends the TELNET SUSP (SUSPend process) sequence.
+
+                ssyynncchh   Sends the TELNET SYNCH sequence.  This sequence causes
+                        the remote system to discard all previously typed (but
+                        not yet read) input.  This sequence is sent as TCP ur-
+                        gent data (and may not work if the remote system is a
+                        4.2BSD system -- if it doesn't work, a lower case
+                        ``r'' may be echoed on the terminal).
+
+                ddoo _c_m_d
+
+                ddoonntt _c_m_d
+
+                wwiillll _c_m_d
+
+                wwoonntt _c_m_d
+                        Sends the TELNET DO _c_m_d sequence.  _C_m_d can be either a
+                        decimal number between 0 and 255, or a symbolic name
+                        for a specific TELNET command.  _C_m_d can also be either
+                        hheellpp or ?? to print out help information, including a
+                        list of known symbolic names.
+
+                ??       Prints out help information for the sseenndd command.
+
+     sseett _a_r_g_u_m_e_n_t _v_a_l_u_e
+
+     uunnsseett _a_r_g_u_m_e_n_t _v_a_l_u_e
+                The sseett command will set any one of a number of tteellnneett vari-
+                ables to a specific value or to TRUE. The special value ooffff
+                turns off the function associated with the variable, this is
+                equivalent to using the uunnsseett command.  The uunnsseett command will
+                disable or set to FALSE any of the specified functions.  The
+                values of variables may be interrogated with the ddiissppllaayy com-
+                mand.  The variables which may be set or unset, but not tog-
+                gled, are listed here.  In addition, any of the variables for
+                the ttooggggllee command may be explicitly set or unset using the
+                sseett and uunnsseett commands.
+
+                aayytt     If TELNET is in localchars mode, or LINEMODE is en-
+                        abled, and the status character is typed, a TELNET AYT
+                        sequence (see sseenndd aayytt preceding) is sent to the re-
+                        mote host.  The initial value for the "Are You There"
+                        character is the terminal's status character.
+
+                eecchhoo    This is the value (initially ``^E'') which, when in
+                        ``line by line'' mode, toggles between doing local
+                        echoing of entered characters (for normal processing),
+                        and suppressing echoing of entered characters (for en-
+                        tering, say, a password).
+
+                eeooff     If tteellnneett is operating in LINEMODE or ``old line by
+                        line'' mode, entering this character as the first
+                        character on a line will cause this character to be
+                        sent to the remote system.  The initial value of the
+                        eof character is taken to be the terminal's eeooff char-
+                        acter.
+
+                eerraassee   If tteellnneett is in llooccaallcchhaarrss mode (see ttooggggllee llooccaallcchhaarrss
+                        below), aanndd if tteellnneett is operating in ``character at a
+                        time'' mode, then when this character is typed, a
+                        TELNET EC sequence (see sseenndd eecc above) is sent to the
+                        remote system.  The initial value for the erase char-
+                        acter is taken to be the terminal's eerraassee character.
+
+                eessccaappee  This is the tteellnneett escape character (initially ``^['')
+                        which causes entry into tteellnneett command mode (when con-
+                        nected to a remote system).
+
+                fflluusshhoouuttppuutt
+                        If tteellnneett is in llooccaallcchhaarrss mode (see ttooggggllee llooccaallcchhaarrss
+                        below) and the fflluusshhoouuttppuutt character is typed, a
+                        TELNET AO sequence (see sseenndd aaoo above) is sent to the
+                        remote host.  The initial value for the flush charac-
+                        ter is taken to be the terminal's fflluusshh character.
+
+                ffoorrww11
+
+                ffoorrww22   If TELNET is operating in LINEMODE, these are the
+                        characters that, when typed, cause partial lines to be
+                        forwarded to the remote system.  The initial value for
+                        the forwarding characters are taken from the termi-
+                        nal's eol and eol2 characters.
+
+                iinntteerrrruupptt
+                        If tteellnneett is in llooccaallcchhaarrss mode (see ttooggggllee llooccaallcchhaarrss
+                        below) and the iinntteerrrruupptt character is typed, a TELNET
+                        IP sequence (see sseenndd iipp above) is sent to the remote
+                        host.  The initial value for the interrupt character
+                        is taken to be the terminal's iinnttrr character.
+
+                kkiillll    If tteellnneett is in llooccaallcchhaarrss mode (see ttooggggllee llooccaallcchhaarrss
+                        below), aanndd if tteellnneett is operating in ``character at a
+                        time'' mode, then when this character is typed, a
+                        TELNET EL sequence (see sseenndd eell above) is sent to the
+                        remote system.  The initial value for the kill charac-
+                        ter is taken to be the terminal's kkiillll character.
+
+                llnneexxtt   If tteellnneett is operating in LINEMODE or ``old line by
+                        line`` mode, then this character is taken to be the
+                        terminal's llnneexxtt character.  The initial value for the
+                        lnext character is taken to be the terminal's llnneexxtt
+                        character.
+
+                qquuiitt    If tteellnneett is in llooccaallcchhaarrss mode (see ttooggggllee llooccaallcchhaarrss
+                        below) and the qquuiitt character is typed, a TELNET BRK
+                        sequence (see sseenndd bbrrkk above) is sent to the remote
+                        host.  The initial value for the quit character is
+                        taken to be the terminal's qquuiitt character.
+
+                rreepprriinntt
+                        If tteellnneett is operating in LINEMODE or ``old line by
+                        line`` mode, then this character is taken to be the
+                        terminal's rreepprriinntt character.  The initial value for
+                        the reprint character is taken to be the terminal's
+                        rreepprriinntt character.
+
+                rrllooggiinn  This is the rlogin escape character.  If set, the nor-
+                        mal TELNET escape character is ignored unless it is
+                        preceded by this character at the beginning of a line.
+                        This character, at the beginning of a line followed by
+                        a "."  closes the connection; when followed by a ^Z it
+                        suspends the telnet command.  The initial state is to
+                        disable the rlogin escape character.
+
+                ssttaarrtt   If the TELNET TOGGLE-FLOW-CONTROL option has been en-
+                        abled, then this character is taken to be the termi-
+                        nal's ssttaarrtt character.  The initial value for the kill
+                        character is taken to be the terminal's ssttaarrtt charac-
+                        ter.
+
+                ssttoopp    If the TELNET TOGGLE-FLOW-CONTROL option has been en-
+                        abled, then this character is taken to be the termi-
+                        nal's ssttoopp character.  The initial value for the kill
+                        character is taken to be the terminal's ssttoopp charac-
+                        ter.
+
+                ssuusspp    If tteellnneett is in llooccaallcchhaarrss mode, or LINEMODE is en-
+                        abled, and the ssuussppeenndd character is typed, a TELNET
+                        SUSP sequence (see sseenndd ssuusspp above) is sent to the re-
+                        mote host.  The initial value for the suspend charac-
+                        ter is taken to be the terminal's ssuussppeenndd character.
+
+                ttrraacceeffiillee
+                        This is the file to which the output, caused by
+                        nneettddaattaa or ooppttiioonn tracing being TRUE, will be written.
+                        If it is set to ``--'', then tracing information will
+                        be written to standard output (the default).
+
+                wwoorrddeerraassee
+                        If tteellnneett is operating in LINEMODE or ``old line by
+                        line`` mode, then this character is taken to be the
+                        terminal's wwoorrddeerraassee character.  The initial value for
+                        the worderase character is taken to be the terminal's
+                        wwoorrddeerraassee character.
+
+                ??       Displays the legal sseett (uunnsseett) commands.
+
+     ssllcc _s_t_a_t_e  The ssllcc command (Set Local Characters) is used to set or
+                change the state of the the special characters when the TELNET
+                LINEMODE option has been enabled.  Special characters are
+                characters that get mapped to TELNET commands sequences (like
+                iipp or qquuiitt) or line editing characters (like eerraassee and kkiillll).
+
+
+                By default, the local special characters are exported.
+
+                cchheecckk       Verify the current settings for the current spe-
+                            cial characters.  The remote side is requested to
+                            send all the current special character settings,
+                            and if there are any discrepancies with the local
+                            side, the local side will switch to the remote
+                            value.
+
+                eexxppoorrtt      Switch to the local defaults for the special char-
+                            acters.  The local default characters are those of
+                            the local terminal at the time when tteellnneett was
+                            started.
+
+                iimmppoorrtt      Switch to the remote defaults for the special
+                            characters.  The remote default characters are
+                            those of the remote system at the time when the
+                            TELNET connection was established.
+
+                ??           Prints out help information for the ssllcc command.
+
+     ssttaattuuss     Show the current status of tteellnneett. This includes the peer one
+                is connected to, as well as the current mode.
+
+     ttooggggllee _a_r_g_u_m_e_n_t_s _._._.
+                Toggle (between TRUE and FALSE) various flags that control how
+                tteellnneett responds to events.  These flags may be set explicitly
+                to TRUE or FALSE using the sseett and uunnsseett commands listed
+                above.  More than one argument may be specified.  The state of
+                these flags may be interrogated with the ddiissppllaayy command.
+                Valid arguments are:
+
+                aauutthhddeebbuugg     Turns on debugging information for the authenti-
+                              cation code.
+
+                aauuttoofflluusshh     If aauuttoofflluusshh and llooccaallcchhaarrss are both TRUE, then
+                              when the aaoo, or qquuiitt characters are recognized
+                              (and transformed into TELNET sequences; see sseett
+                              above for details), tteellnneett refuses to display
+                              any data on the user's terminal until the remote
+                              system acknowledges (via a TELNET TIMING MARK
+                              option) that it has processed those TELNET se-
+                              quences.  The initial value for this toggle is
+                              TRUE if the terminal user had not done an "stty
+                              noflsh", otherwise FALSE (see stty(1)).
+
+                aauuttooddeeccrryypptt   When the TELNET ENCRYPT option is negotiated, by
+                              default the actual encryption (decryption) of
+                              the data stream does not start automatically.
+                              The autoencrypt (autodecrypt) command states
+                              that encryption of the output (input) stream
+                              should be enabled as soon as possible.
+
+                              Note:  Because of export controls, the TELNET
+                              ENCRYPT option is not supported outside the
+                              United States and Canada.
+
+                aauuttoollooggiinn     If the remote side supports the TELNET
+                              AUTHENTICATION option TELNET attempts to use it
+                              to perform automatic authentication.  If the
+                              AUTHENTICATION option is not supported, the us-
+                              er's login name are propagated through the
+                              TELNET ENVIRON option.  This command is the same
+                              as specifying _a option on the ooppeenn command.
+
+                aauuttoossyynncchh     If aauuttoossyynncchh and llooccaallcchhaarrss are both TRUE, then
+                              when either the iinnttrr or qquuiitt characters is typed
+                              (see sseett above for descriptions of the iinnttrr and
+                              qquuiitt characters), the resulting TELNET sequence
+                              sent is followed by the TELNET SYNCH sequence.
+                              This procedure sshhoouulldd cause the remote system to
+                              begin throwing away all previously typed input
+                              until both of the TELNET sequences have been
+                              read and acted upon.  The initial value of this
+                              toggle is FALSE.
+
+                bbiinnaarryy        Enable or disable the TELNET BINARY option on
+                              both input and output.
+
+                iinnbbiinnaarryy      Enable or disable the TELNET BINARY option on
+                              input.
+
+                oouuttbbiinnaarryy     Enable or disable the TELNET BINARY option on
+                              output.
+
+                ccrrllff          If this is TRUE, then carriage returns will be
+                              sent as <CR><LF>. If this is FALSE, then car-
+                              riage returns will be send as <CR><NUL>. The
+                              initial value for this toggle is FALSE.
+
+                ccrrmmoodd         Toggle carriage return mode.  When this mode is
+                              enabled, most carriage return characters re-
+                              ceived from the remote host will be mapped into
+                              a carriage return followed by a line feed.  This
+                              mode does not affect those characters typed by
+                              the user, only those received from the remote
+                              host.  This mode is not very useful unless the
+                              remote host only sends carriage return, but nev-
+                              er line feed.  The initial value for this toggle
+                              is FALSE.
+
+                ddeebbuugg         Toggles socket level debugging (useful only to
+                              the ssuuppeerr uusseerr). The initial value for this tog-
+                              gle is FALSE.
+
+                eennccddeebbuugg      Turns on debugging information for the encryp-
+                              tion code.
+
+                llooccaallcchhaarrss    If this is TRUE, then the fflluusshh, iinntteerrrruupptt,
+                              qquuiitt, eerraassee, and kkiillll characters (see sseett above)
+                              are recognized locally, and transformed into
+                              (hopefully) appropriate TELNET control sequences
+                              (respectively aaoo, iipp, bbrrkk, eecc, and eell; see sseenndd
+                              above).  The initial value for this toggle is
+                              TRUE in ``old line by line'' mode, and FALSE in
+                              ``character at a time'' mode.  When the LINEMODE
+                              option is enabled, the value of llooccaallcchhaarrss is
+                              ignored, and assumed to always be TRUE. If
+                              LINEMODE has ever been enabled, then qquuiitt is
+                              sent as aabboorrtt, and eeooff aanndd are sent as eeooff aanndd
+                              ssuusspp, see sseenndd above).
+
+                nneettddaattaa       Toggles the display of all network data (in hex-
+                              adecimal format).  The initial value for this
+                              toggle is FALSE.
+
+                ooppttiioonnss       Toggles the display of some internal tteellnneett pro-
+                              tocol processing (having to do with TELNET op-
+                              tions).  The initial value for this toggle is
+                              FALSE.
+
+                pprreettttyydduummpp    When the nneettddaattaa toggle is enabled, if
+                              pprreettttyydduummpp is enabled the output from the
+                              nneettddaattaa command will be formatted in a more user
+                              readable format.  Spaces are put between each
+                              character in the output, and the beginning of
+                              any TELNET escape sequence is preceded by a '*'
+                              to aid in locating them.
+
+                sskkiipprrcc        When the skiprc toggle is TRUE, TELNET skips the
+                              reading of the _._t_e_l_n_e_t_r_c file in the users home
+                              directory when connections are opened.  The ini-
+                              tial value for this toggle is FALSE.
+
+                tteerrmmddaattaa      Toggles the display of all terminal data (in
+                              hexadecimal format).  The initial value for this
+                              toggle is FALSE.
+
+                vveerrbboossee__eennccrryypptt
+                              When the vveerrbboossee__eennccrryypptt toggle is TRUE, TELNET
+                              prints out a message each time encryption is en-
+                              abled or disabled.  The initial value for this
+                              toggle is FALSE. Note:  Because of export con-
+                              trols, data encryption is not supported outside
+                              of the United States and Canada.
+
+                ??             Displays the legal ttooggggllee commands.
+
+     zz          Suspend tteellnneett. This command only works when the user is using
+                the csh(1).
+
+     !! [_c_o_m_m_a_n_d]
+                Execute a single command in a subshell on the local system.
+                If ccoommmmaanndd is omitted, then an interactive subshell is in-
+                voked.
+
+     ?? [_c_o_m_m_a_n_d]
+                Get help.  With no arguments, tteellnneett prints a help summary.
+                If a command is specified, tteellnneett will print the help informa-
+                tion for just that command.
+
+EENNVVIIRROONNMMEENNTT
+     TTeellnneett uses at least the HOME, SHELL, DISPLAY, and TERM environment vari-
+     ables.  Other environment variables may be propagated to the other side
+     via the TELNET ENVIRON option.
+
+FFIILLEESS
+     ~/.telnetrc  user customized telnet startup values
+
+HHIISSTTOORRYY
+     The TTeellnneett command appeared in 4.2BSD.
+
+NNOOTTEESS
+     On some remote systems, echo has to be turned off manually when in ``old
+     line by line'' mode.
+
+     In ``old line by line'' mode or LINEMODE the terminal's eeooff character is
+     only recognized (and sent to the remote system) when it is the first
+     character on a line.
+
+4.2 Berkeley Distribution      February 3, 1994                             11
diff --git a/krb5-1-6/src/appl/telnet/telnet/telnet.1 b/krb5-1-6/src/appl/telnet/telnet/telnet.1
new file mode 100644
index 000000000..e354c2a12
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/telnet.1
@@ -0,0 +1,1339 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)telnet.1	8.4 (Berkeley) 2/3/94
+.\" "
+.TH TELNET 1
+.SH NAME
+telnet \- user interface to the TELNET protocol
+.SH SYNOPSIS
+.B telnet
+[\fB\-8\fP] [\fB\-E\fP] [\fB\-F\fP] [\fB\-K\fP] [\fB\-L\fP] [\fB\-S\fP
+\fItos\fP] [\fB\-X\fP \fIauthtype\fP] [\fB\-a\fP] [\fB\-c\fP]
+[\fB\-d\fP] [\fB\-e\fP \fIescapechar\fP] [\fB\-f\fP] [\fB\-k\fP
+\fIrealm\fP] [\fB\-l\fP \fIuser\fP] [\fB\-n\fP \fItracefile\fP]
+[\fB\-r\fP] [\fB\-x\fP] [\fIhost\fP [\fIport\fP]]
+.SH DESCRIPTION
+The 
+.B telnet
+command is used to communicate with another host using the
+.SM TELNET
+protocol.  If
+.B telnet
+is invoked without the
+.I host
+argument, it enters command mode, indicated by its prompt (
+.BR telnet\&> ).
+In this mode, it accepts and executes the commands listed below.  If it
+is invoked with arguments, it performs an
+.B open
+command with those arguments.
+.SH OPTIONS
+.TP
+.B \-8
+Specify an 8-bit data path.  This causes an attempt to negotiate the
+.SM TELNET BINARY
+option on both input and output.
+.TP
+.B \-E
+Stop any character from being recognized as an escape character.
+.TP
+\fB\-F\fP
+forward a
+.I forwardable
+copy of the local credentials to the remote system.
+.TP
+\fB\-K\fP
+Specify no automatic login to the remote system.
+.TP
+.B \-L
+Specify an 8-bit data path on output.  This causes the BINARY option to
+be negotiated on output.
+.TP
+\fB\-S\fP \fItos\fP
+Set the IP type-of-service (TOS) option for the telnet connection to the
+value
+.I tos,
+which can be a numeric TOS value (in decimal, or a hex value preceded
+by 0x, or an octal value preceded by a leading 0) or, on systems that support it, a
+symbolic TOS name found in the /etc/iptos file.
+.TP
+\fB\-X\fP \fIatype\fP
+Disable the
+.I atype
+type of authentication.
+.TP
+\fB\-a\fP
+Attempt automatic login.  This sends the user name via the
+.SM USER
+variable of the
+.SM ENVIRON
+option, if supported by the remote system.  The name used is that of the
+current user as returned by
+.IR getlogin (2)
+if it agrees with the current user ID; otherwise it is the name
+associated with the user ID.
+.TP
+.B \-c
+Disable the reading of the user's
+.B \&.telnetrc
+file.  (See the
+.B toggle skiprc
+command on this man page.)
+.TP
+.B \-d
+Set the initial value of the
+.B debug
+flag to TRUE
+.TP
+\fB\-e\fP \fIescape char\fP
+Set the initial
+.B telnet
+escape character to
+.I escape char.
+If
+.I escape char
+is omitted, then there will be no escape character.
+.TP
+\fB\-f\fP
+forward a copy of the local credentials to the remote system.
+.TP
+\fB\-k\fP \fIrealm\fP
+If Kerberos authentication is being used, request that telnet obtain
+tickets for the remote host in realm
+.I realm
+instead of the remote host's realm, as determined by
+.IR krb_realmofhost (3).
+.TP
+\fB\-l\fP \fIuser\fP
+If the remote system understands the
+.SM ENVIRON
+option, then
+.I user
+will be sent to the remote system as the value for the variable 
+.SM USER.
+This option implies the
+.B \-a
+option.  This option may also be used with the
+.B open
+command.
+.TP
+\fB\-n\fP \fItracefile\fP
+Open
+.I tracefile
+for recording trace information.  See the
+.B set tracefile
+command below.
+.TP
+.B \-r
+Specify a user interface similar to
+.IR rlogin (1).
+In this mode, the escape character is set to the tilde (~) character,
+unless modified by the
+.B \-e
+option.
+.TP
+\fB\-x\fP
+Turn on encryption of the data stream.  When this option is turned on,
+.B telnet
+will exit with an error if authentication cannot be negotiated or if
+encryption cannot be turned on.
+.TP
+.I host
+Indicates the name, alias, or Internet address of the remote host.
+.TP
+.I port
+Indicates a port number (address of an application).  If the port is not
+specified, the default
+.B telnet
+port (23) is used.
+.PP
+When in rlogin mode, ~ is the telnet escape character; a line of the
+form ~. disconnects from the remote host.  Similarly, the line ~^Z
+suspends the telnet session.  The line ~^] escapes to the normal telnet
+escape prompt.
+.PP
+Once a connection has been opened,
+.B telnet
+will attempt to enable the
+.SM TELNET LINEMODE
+option.  If this fails, then
+.B telnet
+will revert to one of two input modes: either ``character at a time'' or
+``old line by line,'' depending on what the remote system supports.
+.PP
+When
+.SM LINEMODE
+is enabled, character processing is done on the local system, under the
+control of the remote system.  When input editing or character echoing
+is to be disabled, the remote system will relay that information.  The
+remote system will also relay changes to any special characters that
+happen on the remote system, so that they can take effect on the local
+system.
+.PP
+In ``character at a time'' mode, most text typed is immediately sent to
+the remote host for processing.
+.PP
+In ``old line by line'' mode, all text is echoed locally, and (normally)
+only completed lines are sent to the remote host.  The ``local echo
+character'' (initially ``^E'') may be used to turn off and on the local
+echo.  (This would mostly be used to enter passwords without the
+password being echoed).
+.PP
+If the LINEMODE option is enabled, or if the
+.B localchars
+flag is TRUE (the default for ``old line by line''; see below), the
+user's
+.BR quit  ,
+.BR intr ,
+and
+.BR flush
+characters are trapped locally, and sent as
+.SM TELNET
+protocol sequences to the remote side.  If
+.SM LINEMODE
+has ever been enabled, then the user's
+.B susp
+and
+.B eof
+are also sent as
+.SM TELNET
+protocol sequences, and
+.B quit
+is sent as a
+.SM TELNET ABORT
+instead of
+.SM BREAK.
+There are options (see
+.B toggle autoflush
+and
+.B toggle autosynch
+below) which cause this action to flush subsequent output to the
+terminal (until the remote host acknowledges the 
+.SM TELNET
+sequence) and flush previous terminal input (in the case of
+.B quit
+and
+.BR intr  ).
+.PP
+While connected to a remote host,
+.B telnet
+command mode may be entered by typing the
+.B telnet
+``escape character'' (initially ``^]'').  When in command mode, the
+normal terminal editing conventions are available.
+.PP
+The following
+.B telnet
+commands are available.  Only enough of each command to uniquely
+identify it need be typed (this is also true for arguments to the
+.BR mode ,
+.BR set ,
+.BR toggle ,
+.BR unset ,
+.BR slc ,
+.BR environ ,
+and
+.B display
+commands).
+.PP
+.TP
+\fBauth\fP \fIargument ...\fP
+The auth command manipulates the information sent through the
+.SM TELNET AUTHENTICATE
+option.  Valid arguments for the auth command are as
+follows:
+.RS
+.TP
+\fBdisable\fP \fItype\fP 
+Disables the specified type of authentication.  To obtain a list of
+available types, use the
+.B auth disable \&?
+command.
+.TP
+\fBenable\fP \fItype\fP
+Enables the specified type of authentication.  To obtain a list of
+available types, use the
+.B auth enable \&?
+command.
+.TP
+.B status
+Lists the current status of the various types of authentication.
+.RE
+.TP
+.B close
+Close a
+.SM TELNET
+session and return to command mode.
+.TP
+\fBdisplay\fP \fIargument ...\fP
+Displays some or all of the
+.B set
+and
+.B toggle
+values (see below).
+.TP
+\fBencrypt\fP \fIargument ...\fP
+The encrypt command manipulates the information sent through the
+.SM TELNET ENCRYPT
+option.
+.PP
+Note:  Because of export controls, the
+.SM TELNET ENCRYPT
+option is not supported outside of the United States and Canada.
+.PP
+Valid arguments for the encrypt command are as follows:
+.RS
+.TP
+\fBdisable\fP \fItype\fP [\fBinput\fP|\fBoutput\fP]
+Disables the specified type of encryption.  If you omit the input and
+output, both input and output are disabled.  To obtain a list of
+available types, use the
+.B encrypt disable \&?
+command.
+.TP
+\fBenable\fP \fItype]fP [\fBinput\fP|\fBoutput\fP]
+Enables the specified type of encryption.  If you omit input and output,
+both input and output are enabled.  To obtain a list of available types,
+use the
+.B encrypt enable \&?
+command.
+.TP
+.B input
+This is the same as the
+.B encrypt start input
+command.
+.TP
+.B \-input
+This is the same as the
+.B encrypt stop input
+command.
+.TP
+.B output
+This is the same as the
+.B encrypt start output
+command.
+.TP
+.B \-output
+This is the same as the
+.B encrypt stop output
+command.
+.TP
+\fBstart\fP [\fBinput\fP|\fBoutput\fP]
+Attempts to start encryption.  If you omit
+.B input
+and
+.BR output ,
+both input and output are enabled.  To obtain a list of available types,
+use the
+.B encrypt enable \&?
+command.
+.TP
+.B status
+Lists the current status of encryption.
+.TP
+\fBstop\fP [\fBinput\fP|\fBoutput\fP]
+Stops encryption.  If you omit input and output, encryption is on both
+input and output.
+.TP
+\fBtype\fP \fItype\fP
+Sets the default type of encryption to be used with later
+.B encrypt start
+or
+.B encrypt stop
+commands.
+.RE
+.TP
+\fBenviron\fP \fIarguments ...\fP
+The
+.B environ
+command is used to manipulate the the variables that my be sent through
+the
+.SM TELNET ENVIRON
+option.  The initial set of variables is taken from the users
+environment, with only the
+.SM DISPLAY
+and
+.SM PRINTER
+variables being exported by default.  The
+.SM USER
+variable is also exported if the
+.B \-a
+or
+.B \-l
+options are used.
+.PP
+Valid arguments for the
+.B environ
+command are:
+.RS
+.TP
+\fBdefine\fP \fIvariable value\fP
+Define the variable
+.I variable
+to have a value of
+.IR value .
+Any variables defined by this command are automatically exported.  The
+.I value
+may be enclosed in single or double quotes so that tabs and spaces may
+be included.
+.TP
+\fBundefine\fP \fIvariable\fP
+Remove
+.I variable
+from the list of environment variables.
+.TP
+\fBexport\fP \fIvariable\fP
+Mark the variable
+.I variable
+to be exported to the remote side.
+.TP
+\fBunexport\fP \fIvariable\fP
+Mark the variable
+.I variable
+to not be exported unless explicitly asked for by the remote side.
+.TP
+.B list
+List the current set of environment variables.  Those marked with a \&*
+will be sent automatically; other variables will only be sent if
+explicitly requested.
+.TP
+.B \&?
+Prints out help information for the
+.B environ
+command.
+.RE
+.TP
+.B logout
+Sends the
+.SM TELNET LOGOUT
+option to the remote side.  This command is similar to a
+.B close
+command; however, if the remote side does not support the
+.SM LOGOUT
+option, nothing happens.  If, however, the remote side does support the
+.SM LOGOUT
+option, this command should cause the remote side to close the
+.SM TELNET
+connection.  If the remote side also supports the concept of suspending
+a user's session for later reattachment, the logout argument indicates
+that you should terminate the session immediately.
+.TP
+\fBmode\fP \fItype\fP
+.I Type
+is one of several options, depending on the state of the
+.SM TELNET
+session.  The remote host is asked for permission to go into the
+requested mode.  If the remote host is capable of entering that mode,
+the requested mode will be entered.
+.RS
+.TP
+.B character
+Disable the
+.SM TELNET LINEMODE
+option, or, if the remote side does not understand the
+.SM LINEMODE
+option, then enter ``character at a time'' mode.
+.TP
+.B line
+Enable the
+.SM TELNET LINEMODE
+option, or, if the remote side does not understand the
+.SM LINEMODE
+option, then attempt to enter ``old-line-by-line'' mode.
+.TP
+\fBisig\fP (\fI\-isig\fP)
+Attempt to enable (disable) the 
+.SM TRAPSIG
+mode of the 
+.SM LINEMODE
+option.  This requires that the
+.SM LINEMODE
+option be enabled.
+.TP
+\fBedit\fP (\fB\-edit\fP)
+Attempt to enable (disable) the
+.SM EDIT
+mode of the 
+.SM LINEMODE
+option.  This requires that the
+.SM LINEMODE
+option be enabled.
+.TP
+\fBsofttabs\fP (\fB\-softtabs\fP)
+Attempt to enable (disable) the
+.SM SOFT_TAB
+mode of the 
+.SM LINEMODE
+option.  This requires that the
+.SM LINEMODE
+option be enabled.
+.TP
+\fBlitecho\fP (\fB\-litecho\fP)
+Attempt to enable (disable) the 
+.SM LIT_ECHO
+mode of the 
+.SM LINEMODE
+option.  This requires that the
+.SM LINEMODE
+option be enabled.
+.TP
+.B \&?
+Prints out help information for the
+.B mode
+command.
+.RE
+.TP
+\fBopen\fP \fIhost\fP [\fB-a\fP] [[\fB\-l\fP] \fIuser\fP] [\fB\-\fP\fIport\fP]
+Open a connection to the named host.  If no port number is specified,
+.B telnet
+will attempt to contact a
+.SM TELNET
+server at the default port.  The host specification may be either a host
+name (see
+.IR hosts (5)
+or an Internet address specified in the ``dot notation'' (see
+.IR inet (3).
+After establishing a connection, the file
+.B \&.telnetrc
+in the user's home directory is opened.  Lines beginning with a # are
+comment lines.  Blank lines are ignored.  Lines that begin without white
+space are the start of a machine entry.  The first thing on the line is
+the name of the machine that is being connected to.  The rest of the
+line, and successive lines that begin with white space are assumed to be
+.B telnet
+commands and are processed as if they had been typed in manually to the
+.B telnet
+command prompt.
+.RS
+.TP
+.B \-a
+Attempt automatic login.  This sends the user name via the
+.SM USER
+variable of the
+.SM ENVIRON
+option, if supported by the remote system.  The name used is that of the
+current user as returned by
+.IR getlogin (2)
+if it agrees with the current user ID; otherwise it is the name
+associated with the user ID.  
+.TP
+[\fB\-l\fP] \fIuser\fP
+may be used to specify the user name to be passed to the remote system
+via the
+.SM ENVIRON
+option.
+.TP
+\fB\-\fP\fIport\fP
+When connecting to a non-standard port,
+.B telnet
+omits any automatic initiation of
+.SM TELNET
+options.  When the port number is preceded by a minus sign, the initial
+option negotiation is done.
+.RE
+.TP
+.B quit
+Close any open
+.SM TELNET
+session and exit
+.BR telnet .
+An end of file (in command mode) will also close a session and exit.
+.TP
+\fBsend\fP \fIarguments\fP
+Sends one or more special character sequences to the remote host.  The
+following are the arguments which may be specified (more than one
+argument may be specified at a time):
+.PP
+.RS
+.TP
+.B abort
+Sends the
+.SM TELNET ABORT
+(Abort processes) sequence.
+.TP
+.B ao
+Sends the
+.SM TELNET AO
+(Abort Output) sequence, which should cause the remote system to flush
+all output
+.I from
+the remote system
+.I to
+the user's terminal.
+.TP
+.B ayt
+Sends the
+.SM TELNET AYT
+(Are You There) sequence, to which the remote system may or may not
+choose to respond.
+.TP
+.B brk
+Sends the
+.SM TELNET BRK
+(Break) sequence, which may have significance to the remote system.
+.TP
+.B ec
+Sends the
+.SM TELNET EC
+(Erase Character) sequence, which should cause the remote system to
+erase the last character entered.
+.TP
+.B el
+Sends the
+.SM TELNET EL
+(Erase Line) sequence, which should cause the remote system to erase the
+line currently being entered.
+.TP
+.B eof
+Sends the
+.SM TELNET EOF
+(End Of File) sequence.
+.TP
+.B eor
+Sends the
+.SM TELNET EOR
+(End of Record) sequence.
+.TP
+.B escape
+Sends the current
+.b telnet
+escape character (initially ``^''.
+.TP
+.B ga
+Sends the
+.SM TELNET GA
+(Go Ahead) sequence, which likely has no significance to the remote
+system.
+.TP
+.B getstatus
+If the remote side supports the
+.SM TELNET STATUS
+command,
+.B getstatus
+will send the subnegotiation to request that the server send its current
+option status.
+.TP
+.B ip
+Sends the
+.SM TELNET IP
+(Interrupt Process) sequence, which should cause the remote system to
+abort the currently running process.
+.TP
+.B nop
+Sends the
+.SM TELNET NOP
+(No OPeration) sequence.
+.TP
+.B susp
+Sends the
+.SM TELNET SUSP
+(SUSPend process) sequence.
+.TP
+.B synch
+Sends the
+.SM TELNET SYNCH
+sequence.  This sequence causes the remote system to discard all
+previously typed (but not yet read) input.  This sequence is sent as
+.SM TCP
+urgent data (and may not work if the remote system is a 4.2BSD system --
+if it doesn't work, a lower case ``r'' may be echoed on the terminal).
+.TP
+\fBdo\fP \fIcmd\fP
+.TP
+\fBdont\fP \fIcmd\fP
+.TP
+\fBwill\fP \fIcmd\fP
+.TP
+\fBwont\fP \fIcmd\fP
+Sends the
+.SM TELNET DO
+.I cmd
+sequence.
+.I Cmd
+can be either a decimal number between 0 and 255, or a symbolic name for
+a specific
+.SM TELNET
+command.
+.I Cmd
+can also be either
+.B help
+or
+.B \&?
+to print out help information, including a list of known symbolic names.
+.TP
+.B \&?
+Prints out help information for the
+.B send
+command.
+.RE
+.TP
+\fBset\fP \fIargument value\fP 
+.TP
+\fBunset\fP \fIargument value\fP
+The
+.B set
+command will set any one of a number of
+.B telnet
+variables to a specific value or to
+.SM TRUE.
+The special value
+.B off
+turns off the function associated with the variable; this is equivalent
+to using the
+.B unset
+command.  The
+.B unset
+command will disable or set to
+.SM FALSE
+any of the specified functions.  The values of variables may be
+interrogated with the
+.B display
+command.  The variables which may be set or unset, but not toggled, are
+listed here.  In addition, any of the variables for the
+.B toggle
+command may be explicitly set or unset using the
+.B set
+and
+.B unset
+commands.
+.RS
+.TP
+.B ayt
+If
+.B telnet
+is in localchars mode, or
+.SM LINEMODE
+is enabled, and the status character is typed, a
+.SM TELNET AYT
+sequence (see
+.B send ayt
+preceding) is sent to the remote host.  The initial value for the "Are
+You There" character is the terminal's status character.
+.TP
+.B echo
+This is the value (initially ``^E'') which, when in ``line by line''
+mode, toggles between doing local echoing of entered characters (for
+normal processing), and suppressing echoing of entered characters (for
+entering, say, a password).
+.TP
+.B eof
+If
+.B telnet
+is operating in
+.SM LINEMODE
+or ``old line by line'' mode, entering this character as the first
+character on a line will cause this character to be sent to the remote
+system.  The initial value of the eof character is taken to be the
+terminal's
+.B eof
+character.
+.TP
+.B erase
+If
+.B telnet
+is in
+.b localchars
+mode (see
+.B toggle localchars
+below),
+.I and
+if
+.B telnet
+is operating in ``character at a time'' mode, then when this character
+is typed, a
+.SM TELNET EC
+sequence (see
+.B send ec
+above) is sent to the remote system.  The initial value for the erase
+character is taken to be the terminal's
+.B erase
+character.
+.TP
+.B escape
+This is the
+.B telnet
+escape character (initially ``^['') which causes entry into
+.B telnet
+command mode (when connected to a remote system).
+.TP
+.B flushoutput
+If
+.B telnet
+is in
+.B localchars
+mode (see
+.B toggle localchars
+below) and the
+.B flushoutput
+character is typed, a
+.SM TELNET AO
+sequence (see
+.B send ao
+above) is sent to the remote host.  The initial value for the flush
+character is taken to be the terminal's
+.B flush
+character.
+.TP
+.B forw1
+.TP
+.B forw2
+If
+.B telnet
+is operating in
+.SM LINEMODE,
+these are the characters that, when typed, cause partial lines to be
+forwarded to the remote system.  The initial value for the forwarding
+characters are taken from the terminal's eol and eol2 characters.
+.TP
+.B interrupt
+If
+.B telnet
+is in
+.B localchars
+mode (see
+.B toggle localchars
+below) and the
+.B interrupt
+character is typed, a
+.SM TELNET IP
+sequence (see
+.B send ip
+above) is sent to the remote host.  The initial value for the interrupt
+character is taken to be the terminal's
+.B intr
+character.
+.TP
+.B kill
+If
+.B telnet
+is in
+.B localchars
+mode (see
+.B toggle localchars
+below),
+.I and
+if
+.B telnet
+is operating in ``character at a time'' mode, then when this character
+is typed, a
+.SM TELNET EL
+sequence (see
+.B send el
+above) is sent to the remote system.  The initial value for the kill
+character is taken to be the terminal's
+.B kill
+character.
+.TP
+.B lnext
+If
+.B telnet
+is operating in
+.SM LINEMODE
+or ``old line by line'' mode, then this character is taken to be the
+terminal's
+.B lnext
+character.  The initial value for the lnext character is taken to be the
+terminal's
+.B lnext
+character.
+.TP
+.B quit
+If
+.B telnet
+is in
+.B localchars
+mode (see
+.B toggle localchars
+below) and the
+.B quit
+character is typed, a
+.SM TELNET BRK
+sequence (see
+.B send brk
+above) is sent to the remote host.  The initial value for the quit
+character is taken to be the terminal's
+.B quit
+character.
+.TP
+.B reprint
+If
+.B telnet
+is operating in
+.SM LINEMODE
+or ``old line by line'' mode, then this character is taken to be the
+terminal's
+.B reprint
+character.  The initial value for the reprint character is taken to be
+the terminal's
+.B reprint
+character.
+.TP
+.B rlogin
+This is the rlogin escape character.  If set, the normal
+.B TELNET
+escape character is ignored unless it is preceded by this character at
+the beginning of a line.  This character, at the beginning of a line
+followed by a "."  closes the connection; when followed by a ^Z it
+suspends the telnet command.  The initial state is to disable the rlogin
+escape character.
+.TP
+.B start
+If the
+.SM TELNET TOGGLE-FLOW-CONTROL
+option has been enabled, then this character is taken to be the
+terminal's
+.B start
+character.  The initial value for the kill character is taken to be the
+terminal's
+.B start
+character.
+.TP
+.B stop
+If the
+.SM TELNET TOGGLE-FLOW-CONTROL
+option has been enabled, then this character is taken to be the
+terminal's
+.B stop
+character.  The initial value for the kill character is taken to be the
+terminal's
+.B stop
+character.
+.TP
+.B susp
+If
+.B telnet
+is in
+.B localchars
+mode, or
+.SM LINEMODE
+is enabled, and the
+.B suspend
+character is typed, a
+.SM TELNET SUSP
+sequence (see
+.B send susp
+above) is sent to the remote host.  The initial value for the suspend
+character is taken to be the terminal's
+.B suspend
+character.
+.TP
+.B tracefile
+This is the file to which the output, caused by
+.B netdata
+or
+.B option
+tracing being
+.SM TRUE,
+will be written.  If it is set to ``\fB\-\fP'', then tracing information
+will be written to standard output (the default).
+.TP
+.B worderase
+If
+.B telnet
+is operating in
+.SM LINEMODE
+or ``old line by line'' mode, then this character is taken to be the
+terminal's
+.B worderase
+character.  The initial value for the worderase character is taken to be
+the terminal's
+.B worderase
+character.
+.TP
+.B \&?
+Displays the legal \fBset\fP (\fBunset\fP) commands.
+.RE
+.TP
+\fBslc\fP \fIstate\fP
+The
+.B slc
+command (Set Local Characters) is used to set or change the state of the
+the special characters when the
+.SM TELNET LINEMODE
+option has been enabled.  Special characters are characters that get
+mapped to
+.B telnet
+commands sequences (like
+.B ip
+or
+.B quit  )
+or line editing characters (like
+.B erase
+and
+.BR kill ).
+By default, the local special characters are exported.
+.RS
+.TP
+.B check
+Verify the current settings for the current special characters.  The
+remote side is requested to send all the current special character
+settings, and if there are any discrepancies with the local side, the
+local side will switch to the remote value.
+.TP
+.B export
+Switch to the local defaults for the special characters.  The local
+default characters are those of the local terminal at the time when
+.B telnet
+was started.
+.TP
+.B import
+Switch to the remote defaults for the special characters.  The remote
+default characters are those of the remote system at the time when the
+.SM TELNET
+connection was established.
+.TP
+.B \&?
+Prints out help information for the
+.B slc
+command.
+.RE
+.TP
+.B status
+Show the current status of
+.BR telnet  .
+This includes the peer one is connected to, as well as the current mode.
+.TP
+\fBtoggle\fP \fIarguments ...\fP
+Toggle (between
+.SM TRUE
+and
+.SM FALSE)
+various flags that control how
+.B telnet
+responds to events.  These flags may be set explicitly to
+.SM TRUE
+or
+.SM FALSE
+using the
+.B set
+and
+.B unset
+commands listed above.  More than one argument may be specified.  The
+state of these flags may be interrogated with the
+.B display
+command.  Valid arguments are:
+.RS
+.TP
+.B authdebug
+Turns on debugging information for the authentication code.
+.TP
+.B autoflush
+If
+.B autoflush
+and
+.B localchars
+are both
+.SM TRUE ,
+then when the
+.BR ao  ,
+or
+.B quit
+characters are recognized (and transformed into
+.SM TELNET
+sequences; see
+.B set
+above for details),
+.B telnet
+refuses to display any data on the user's terminal until the remote
+system acknowledges (via a
+.SM TELNET TIMING MARK
+option) that it has processed those
+.SM TELNET
+sequences.  The initial value for this toggle is
+.SM TRUE
+if the terminal user had not done an "stty noflsh", otherwise
+.SM FALSE
+(see
+.BR stty  (1).
+.TP
+.B autodecrypt
+When the
+.SM TELNET ENCRYPT
+option is negotiated, by default the actual encryption (decryption) of
+the data stream does not start automatically.  The autoencrypt
+(autodecrypt) command states that encryption of the output (input)
+stream should be enabled as soon as possible.
+.PP
+Note:  Because of export controls, the
+.SM TELNET ENCRYPT
+option is not supported outside the United States and Canada.
+.TP
+.B autologin
+If the remote side supports the
+.SM TELNET AUTHENTICATION
+option
+.B telnet
+attempts to use it to perform automatic authentication.  If the
+.SM AUTHENTICATION
+option is not supported, the user's login name are propagated through
+the
+.SM TELNET ENVIRON
+option.  This command is the same as specifying the
+.B \-a
+option on the
+.B open
+command.
+.TP
+.B autosynch
+If
+.B autosynch
+and
+.B localchars
+are both
+.SM TRUE,
+then when either the
+.B intr
+or
+.B quit
+characters is typed (see
+.B set
+above for descriptions of the
+.B intr
+and
+.B quit
+characters), the resulting
+.SM TELNET
+sequence sent is followed by the
+.SM TELNET SYNCH
+sequence.  This procedure
+.I should
+cause the remote system to begin throwing away all previously typed
+input until both of the
+.SM TELNET
+sequences have been read and acted upon.  The initial value of this
+toggle is
+.SM FALSE.
+.TP
+.B binary
+Enable or disable the
+.SM TELNET BINARY
+option on both input and output.
+.TP
+.B inbinary
+Enable or disable the
+.SM TELNET BINARY
+option on input.
+.TP
+.B outbinary
+Enable or disable the
+.SM TELNET BINARY
+option on output.
+.TP
+.B crlf
+If this is
+.SM TRUE,
+then carriage returns will be sent as <CR><LF>.  If this is
+.SM FALSE,
+then carriage returns will be send as <CR><NUL>.  The initial value for
+this toggle is
+.SM FALSE.
+.TP
+.B crmod
+Toggle carriage return mode.  When this mode is enabled, most carriage
+return characters received from the remote host will be mapped into a
+carriage return followed by a line feed.  This mode does not affect
+those characters typed by the user, only those received from the remote
+host.  This mode is not very useful unless the remote host only sends
+carriage return, but never line feed.  The initial value for this toggle
+is
+.SM FALSE .
+.TP
+.B debug
+Toggles socket level debugging (useful only to the \fBsuper user\fP).
+The initial value for this toggle is
+.SM FALSE .
+.TP
+.B encdebug
+Turns on debugging information for the encryption code.
+.TP
+.B localchars
+If this is
+.SM TRUE ,
+then the
+.BR flush ,
+.BR interrupt ,
+.BR quit ,
+.BR erase ,
+and
+.B kill
+characters (see
+.B set
+above) are recognized locally, and transformed into (hopefully)
+appropriate
+.SM TELNET
+control sequences (respectively
+.BR ao ,
+.BR ip ,
+.BR brk ,
+.BR ec ,
+and
+.BR el ;
+see
+.B send
+above).  The initial value for this toggle is
+.SM TRUE
+in ``old line by line'' mode, and
+.SM FALSE
+in ``character at a time'' mode.  When the
+.SM LINEMODE
+option is enabled, the value of
+.B localchars
+is ignored, and assumed to always be
+.SM TRUE.
+If
+.SM LINEMODE
+has ever been enabled, then
+.B quit
+is sent as
+.BR abort ,
+and
+.B eof
+and
+.B suspend
+are sent as
+.B eof
+and
+.BR susp ,
+see
+.B send
+above).
+.TP
+.B netdata
+Toggles the display of all network data (in hexadecimal format).  The
+initial value for this toggle is
+.SM FALSE.
+.TP
+.B options
+Toggles the display of some internal
+.B telnet
+protocol processing (having to do with
+.SM TELNET
+options).  The initial value for this flag is
+.SM FALSE .
+.TP
+.B prettydump
+When the
+.B netdata
+flag is enabled, if
+.B prettydump
+is enabled the output from the
+.B netdata
+command will be formatted in a more user-readable format.  Spaces are
+put between each character in the output, and the beginning of any
+.SM TELNET
+escape sequence is preceded by a '*' to aid in locating them.
+.TP
+.B skiprc
+When the skiprc flag is
+.SM TRUE,
+.SM TELNET
+skips the reading of the \&.telnetrc file in the user's home directory
+when connections are opened.  The initial value for this flag is
+.SM FALSE.
+.TP
+.B termdata
+Toggles the display of all terminal data (in hexadecimal format).  The
+initial value for this flag is
+.SM FALSE.
+.TP
+.B verbose_encrypt
+When the
+.B verbose_encrypt
+flag is
+.SM TRUE,
+.SM TELNET
+prints out a message each time encryption is enabled or disabled.  The
+initial value for this toggle is
+.SM FALSE.
+Note:  Because of export controls, data encryption is not supported
+outside of the United States and Canada.
+.TP
+.B \&?
+Displays the legal
+.B toggle
+commands.
+.RE
+.TP
+.B z
+Suspend
+.BR telnet .
+This command only works when the user's shell is
+.IR csh (1).
+.TP
+\fB\&!\fP [\fIcommand\fP]
+Execute a single command in a subshell on the local system.  If
+.B command
+is omitted, then an interactive subshell is invoked.
+.TP
+\fB\&?\fP \fIcommand\fP
+Get help.  With no arguments,
+.b telnet
+prints a help summary.  If a command is specified,
+.b telnet
+will print the help information for just that command.
+.SH ENVIRONMENT
+.B Telnet
+uses at least the
+.SM HOME,
+.SM SHELL,
+.SM DISPLAY,
+and
+.SM TERM
+environment variables.  Other environment variables may be propagated to
+the other side via the
+.SM TELNET ENVIRON
+option.
+.SH FILES
+.TP "\w'~/.telnetrc\ \ 'u"
+.TP
+~/.telnetrc
+user-customized telnet startup values
+.sp -1v
+.TP
+~/.k5login
+(on remote host) - file containing Kerberos principals that are allowed
+access.
+.SH HISTORY
+The
+.B Telnet
+command appeared in 4.2BSD.
+.SH NOTES
+.PP
+On some remote systems, echo has to be turned off manually when in ``old
+line by line'' mode.
+.PP
+In ``old line by line'' mode or
+.SM LINEMODE
+the terminal's
+.B eof
+character is only recognized (and sent to the remote system) when it is
+the first character on a line.
diff --git a/krb5-1-6/src/appl/telnet/telnet/telnet.c b/krb5-1-6/src/appl/telnet/telnet/telnet.c
new file mode 100644
index 000000000..3b8a82d74
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/telnet.c
@@ -0,0 +1,2758 @@
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)telnet.c	8.1 (Berkeley) 6/6/93 */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sys/types.h>
+#include <time.h>
+
+#if	defined(unix)
+#include <signal.h>
+/* By the way, we need to include curses.h before telnet.h since,
+ * among other things, telnet.h #defines 'DO', which is a variable
+ * declared in curses.h.
+ */
+#endif	/* defined(unix) */
+
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+
+#ifdef HAVE_TERM_H
+#include <term.h>
+#endif
+
+#include <arpa/telnet.h>
+
+#include <ctype.h>
+
+#include "ring.h"
+
+#include "defines.h"
+#include "externs.h"
+#include "types.h"
+#include "general.h"
+
+#ifdef AUTHENTICATION
+#include <libtelnet/auth.h>
+#endif
+
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION) 
+#include <libtelnet/misc-proto.h>
+#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION)  */
+
+static int is_unique (char *, char **, char **);
+
+
+#define	strip(x)	((x)&0x7f)
+
+static unsigned char	subbuffer[SUBBUFSIZE],
+			*subpointer, *subend;	 /* buffer for sub-options */
+#define	SB_CLEAR()	subpointer = subbuffer;
+#define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
+#define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
+				*subpointer++ = (c); \
+			}
+
+#define	SB_GET()	((*subpointer++)&0xff)
+#define	SB_PEEK()	((*subpointer)&0xff)
+#define	SB_EOF()	(subpointer >= subend)
+#define	SB_LEN()	(subend - subpointer)
+
+char	options[256];		/* The combined options */
+char	do_dont_resp[256];
+char	will_wont_resp[256];
+
+int
+	eight = 0,
+	autologin = 0,	/* Autologin anyone? */
+	skiprc = 0,
+	connected,
+	showoptions,
+	In3270,		/* Are we in 3270 mode? */
+	ISend,		/* trying to send network data in */
+	debug = 0,
+	crmod,
+	netdata,	/* Print out network data flow */
+	crlf,		/* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
+#if	defined(TN3270)
+	noasynchtty = 0,/* User specified "-noasynch" on command line */
+	noasynchnet = 0,/* User specified "-noasynch" on command line */
+	askedSGA = 0,	/* We have talked about suppress go ahead */
+#endif	/* defined(TN3270) */
+	telnetport,
+        wantencryption = 0,
+	SYNCHing,	/* we are in TELNET SYNCH mode */
+	flushout,	/* flush output */
+	autoflush = 0,	/* flush output when interrupting? */
+	autosynch,	/* send interrupt characters with SYNCH? */
+	localflow,	/* we handle flow control locally */
+	restartany,	/* if flow control enabled, restart on any character */
+	localchars,	/* we recognize interrupt/quit */
+	donelclchars,	/* the user has set "localchars" */
+	donebinarytoggle,	/* the user has put us in binary */
+	dontlecho,	/* do we suppress local echoing right now? */
+	globalmode;
+
+char *prompt = 0;
+
+int scheduler_lockout_tty = 0;
+
+cc_t escape;
+cc_t rlogin;
+#ifdef	KLUDGELINEMODE
+cc_t echoc;
+#endif
+
+/*
+ * Telnet receiver states for fsm
+ */
+#define	TS_DATA		0
+#define	TS_IAC		1
+#define	TS_WILL		2
+#define	TS_WONT		3
+#define	TS_DO		4
+#define	TS_DONT		5
+#define	TS_CR		6
+#define	TS_SB		7		/* sub-option collection */
+#define	TS_SE		8		/* looking for sub-option end */
+
+static int	telrcv_state;
+#ifdef	OLD_ENVIRON
+unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
+#else
+# define telopt_environ TELOPT_NEW_ENVIRON
+#endif
+
+jmp_buf	toplevel = { 0 };
+jmp_buf	peerdied;
+
+int	flushline;
+int	linemode;
+
+#ifdef	KLUDGELINEMODE
+int	kludgelinemode = 1;
+#endif
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+Clocks clocks;
+
+#ifdef	notdef
+Modelist modelist[] = {
+	{ "telnet command mode", COMMAND_LINE },
+	{ "character-at-a-time mode", 0 },
+	{ "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
+	{ "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
+	{ "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
+	{ "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
+	{ "3270 mode", 0 },
+};
+#endif
+
+
+/*
+ * Initialize telnet environment.
+ */
+
+    void
+init_telnet()
+{
+    env_init();
+
+    SB_CLEAR();
+    ClearArray(options);
+
+    connected = In3270 = ISend = localflow = donebinarytoggle = 0;
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION) 
+    auth_encrypt_connect(connected);
+#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION)  */
+    restartany = -1;
+
+    SYNCHing = 0;
+
+    /* Don't change NetTrace */
+
+    escape = CONTROL(']');
+    rlogin = _POSIX_VDISABLE;
+#ifdef	KLUDGELINEMODE
+    echoc = CONTROL('E');
+#endif
+
+    flushline = 1;
+    telrcv_state = TS_DATA;
+}
+
+
+#ifdef	notdef
+#include <varargs.h>
+
+    /*VARARGS*/
+    static void
+printring(va_alist)
+    va_dcl
+{
+    va_list ap;
+    char buffer[100];		/* where things go */
+    char *ptr;
+    char *format;
+    char *string;
+    Ring *ring;
+    int i;
+
+    va_start(ap);
+
+    ring = va_arg(ap, Ring *);
+    format = va_arg(ap, char *);
+    ptr = buffer;
+
+    while ((i = *format++) != 0) {
+	if (i == '%') {
+	    i = *format++;
+	    switch (i) {
+	    case 'c':
+		*ptr++ = va_arg(ap, int);
+		break;
+	    case 's':
+		string = va_arg(ap, char *);
+		ring_supply_data(ring, buffer, ptr-buffer);
+		ring_supply_data(ring, string, strlen(string));
+		ptr = buffer;
+		break;
+	    case 0:
+		ExitString("printring: trailing %%.\n", 1);
+		/*NOTREACHED*/
+	    default:
+		ExitString("printring: unknown format character.\n", 1);
+		/*NOTREACHED*/
+	    }
+	} else {
+	    *ptr++ = i;
+	}
+    }
+    ring_supply_data(ring, buffer, ptr-buffer);
+}
+#endif
+
+/*
+ * These routines are in charge of sending option negotiations
+ * to the other side.
+ *
+ * The basic idea is that we send the negotiation if either side
+ * is in disagreement as to what the current state should be.
+ */
+
+    void
+send_do(c, init)
+    register int c, init;
+{
+    if (init) {
+	if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
+				my_want_state_is_do(c))
+	    return;
+	set_my_want_state_do(c);
+	do_dont_resp[c]++;
+    }
+    NET2ADD(IAC, DO);
+    NETADD(c);
+    printoption("SENT", DO, c);
+}
+
+    void
+send_dont(c, init)
+    register int c, init;
+{
+    if (init) {
+	if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
+				my_want_state_is_dont(c))
+	    return;
+	set_my_want_state_dont(c);
+	do_dont_resp[c]++;
+    }
+    NET2ADD(IAC, DONT);
+    NETADD(c);
+    printoption("SENT", DONT, c);
+}
+
+    void
+send_will(c, init)
+    register int c, init;
+{
+    if (init) {
+	if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
+				my_want_state_is_will(c))
+	    return;
+	set_my_want_state_will(c);
+	will_wont_resp[c]++;
+    }
+    NET2ADD(IAC, WILL);
+    NETADD(c);
+    printoption("SENT", WILL, c);
+}
+
+    void
+send_wont(c, init)
+    register int c, init;
+{
+    if (init) {
+	if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
+				my_want_state_is_wont(c))
+	    return;
+	set_my_want_state_wont(c);
+	will_wont_resp[c]++;
+    }
+    NET2ADD(IAC, WONT);
+    NETADD(c);
+    printoption("SENT", WONT, c);
+}
+
+
+	void
+willoption(option)
+	int option;
+{
+	int new_state_ok = 0;
+
+	if (do_dont_resp[option]) {
+	    --do_dont_resp[option];
+	    if (do_dont_resp[option] && my_state_is_do(option))
+		--do_dont_resp[option];
+	}
+
+	if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
+
+	    switch (option) {
+
+	    case TELOPT_ECHO:
+#	    if defined(TN3270)
+		/*
+		 * The following is a pain in the rear-end.
+		 * Various IBM servers (some versions of Wiscnet,
+		 * possibly Fibronics/Spartacus, and who knows who
+		 * else) will NOT allow us to send "DO SGA" too early
+		 * in the setup proceedings.  On the other hand,
+		 * 4.2 servers (telnetd) won't set SGA correctly.
+		 * So, we are stuck.  Empirically (but, based on
+		 * a VERY small sample), the IBM servers don't send
+		 * out anything about ECHO, so we postpone our sending
+		 * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
+		 * DO send).
+		  */
+		{
+		    if (askedSGA == 0) {
+			askedSGA = 1;
+			if (my_want_state_is_dont(TELOPT_SGA))
+			    send_do(TELOPT_SGA, 1);
+		    }
+		}
+		    /* Fall through */
+	    case TELOPT_EOR:
+#endif	    /* defined(TN3270) */
+	    case TELOPT_BINARY:
+	    case TELOPT_SGA:
+		settimer(modenegotiated);
+		/* FALL THROUGH */
+	    case TELOPT_STATUS:
+#if	defined(AUTHENTICATION)
+	    case TELOPT_AUTHENTICATION:
+#endif
+#ifdef	ENCRYPTION
+	    case TELOPT_ENCRYPT:
+#endif /* ENCRYPTION */
+		new_state_ok = 1;
+		break;
+
+	    case TELOPT_TM:
+		if (flushout)
+		    flushout = 0;
+		/*
+		 * Special case for TM.  If we get back a WILL,
+		 * pretend we got back a WONT.
+		 */
+		set_my_want_state_dont(option);
+		set_my_state_dont(option);
+		return;			/* Never reply to TM will's/wont's */
+
+	    case TELOPT_LINEMODE:
+	    default:
+		break;
+	    }
+
+	    if (new_state_ok) {
+		set_my_want_state_do(option);
+		send_do(option, 0);
+		setconnmode(0);		/* possibly set new tty mode */
+	    } else {
+		do_dont_resp[option]++;
+		send_dont(option, 0);
+	    }
+	}
+	set_my_state_do(option);
+#ifdef	ENCRYPTION
+	if (option == TELOPT_ENCRYPT)
+		encrypt_send_support();
+#endif	/* ENCRYPTION */
+}
+
+	void
+wontoption(option)
+	int option;
+{
+	if (do_dont_resp[option]) {
+	    --do_dont_resp[option];
+	    if (do_dont_resp[option] && my_state_is_dont(option))
+		--do_dont_resp[option];
+	}
+
+	if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
+
+	    switch (option) {
+
+#ifdef	KLUDGELINEMODE
+	    case TELOPT_SGA:
+		if (!kludgelinemode)
+		    break;
+		/* FALL THROUGH */
+#endif
+	    case TELOPT_ECHO:
+		settimer(modenegotiated);
+		break;
+
+	    case TELOPT_TM:
+		if (flushout)
+		    flushout = 0;
+		set_my_want_state_dont(option);
+		set_my_state_dont(option);
+		return;		/* Never reply to TM will's/wont's */
+
+	    default:
+		break;
+	    }
+	    set_my_want_state_dont(option);
+	    if (my_state_is_do(option))
+		send_dont(option, 0);
+	    setconnmode(0);			/* Set new tty mode */
+	} else if (option == TELOPT_TM) {
+	    /*
+	     * Special case for TM.
+	     */
+	    if (flushout)
+		flushout = 0;
+	    set_my_want_state_dont(option);
+	}
+	set_my_state_dont(option);
+}
+
+	static void
+dooption(option)
+	int option;
+{
+	int new_state_ok = 0;
+
+	if (will_wont_resp[option]) {
+	    --will_wont_resp[option];
+	    if (will_wont_resp[option] && my_state_is_will(option))
+		--will_wont_resp[option];
+	}
+
+	if (will_wont_resp[option] == 0) {
+	  if (my_want_state_is_wont(option)) {
+
+	    switch (option) {
+
+	    case TELOPT_TM:
+		/*
+		 * Special case for TM.  We send a WILL, but pretend
+		 * we sent WONT.
+		 */
+		send_will(option, 0);
+		set_my_want_state_wont(TELOPT_TM);
+		set_my_state_wont(TELOPT_TM);
+		return;
+
+#	if defined(TN3270)
+	    case TELOPT_EOR:		/* end of record */
+#	endif	/* defined(TN3270) */
+	    case TELOPT_BINARY:		/* binary mode */
+	    case TELOPT_NAWS:		/* window size */
+	    case TELOPT_TSPEED:		/* terminal speed */
+	    case TELOPT_LFLOW:		/* local flow control */
+	    case TELOPT_TTYPE:		/* terminal type option */
+	    case TELOPT_SGA:		/* no big deal */
+#ifdef	ENCRYPTION
+	    case TELOPT_ENCRYPT:	/* encryption variable option */
+#endif	/* ENCRYPTION */
+		new_state_ok = 1;
+		break;
+
+	    case TELOPT_NEW_ENVIRON:	/* New environment variable option */
+#ifdef	OLD_ENVIRON
+		if (my_state_is_will(TELOPT_OLD_ENVIRON))
+			send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
+		goto env_common;
+	    case TELOPT_OLD_ENVIRON:	/* Old environment variable option */
+		if (my_state_is_will(TELOPT_NEW_ENVIRON))
+			break;		/* Don't enable if new one is in use! */
+	    env_common:
+		telopt_environ = option;
+#endif
+		new_state_ok = 1;
+		break;
+
+#if	defined(AUTHENTICATION)
+	    case TELOPT_AUTHENTICATION:
+		if (autologin)
+			new_state_ok = 1;
+		break;
+#endif
+
+	    case TELOPT_XDISPLOC:	/* X Display location */
+		if (env_getvalue((unsigned char *)"DISPLAY") &&
+		    env_is_exported((unsigned char *)"DISPLAY"))
+		    new_state_ok = 1;
+		break;
+
+	    case TELOPT_LINEMODE:
+#ifdef	KLUDGELINEMODE
+		kludgelinemode = 0;
+		send_do(TELOPT_SGA, 1);
+#endif
+		set_my_want_state_will(TELOPT_LINEMODE);
+		send_will(option, 0);
+		set_my_state_will(TELOPT_LINEMODE);
+		slc_init();
+		return;
+
+	    case TELOPT_ECHO:		/* We're never going to echo... */
+	    default:
+		break;
+	    }
+
+	    if (new_state_ok) {
+		set_my_want_state_will(option);
+		send_will(option, 0);
+		setconnmode(0);			/* Set new tty mode */
+	    } else {
+		will_wont_resp[option]++;
+		send_wont(option, 0);
+	    }
+	  } else {
+	    /*
+	     * Handle options that need more things done after the
+	     * other side has acknowledged the option.
+	     */
+	    switch (option) {
+	    case TELOPT_LINEMODE:
+#ifdef	KLUDGELINEMODE
+		kludgelinemode = 0;
+		send_do(TELOPT_SGA, 1);
+#endif
+		set_my_state_will(option);
+		slc_init();
+		send_do(TELOPT_SGA, 0);
+		return;
+	    }
+	  }
+	}
+	set_my_state_will(option);
+}
+
+	static void
+dontoption(option)
+	int option;
+{
+
+	if (will_wont_resp[option]) {
+	    --will_wont_resp[option];
+	    if (will_wont_resp[option] && my_state_is_wont(option))
+		--will_wont_resp[option];
+	}
+
+	if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
+	    switch (option) {
+	    case TELOPT_LINEMODE:
+		linemode = 0;	/* put us back to the default state */
+		break;
+#ifdef	OLD_ENVIRON
+	    case TELOPT_NEW_ENVIRON:
+		/*
+		 * The new environ option wasn't recognized, try
+		 * the old one.
+		 */
+		send_will(TELOPT_OLD_ENVIRON, 1);
+		telopt_environ = TELOPT_OLD_ENVIRON;
+		break;
+#endif
+	    }
+	    /* we always accept a DONT */
+	    set_my_want_state_wont(option);
+	    if (my_state_is_will(option))
+		send_wont(option, 0);
+	    setconnmode(0);			/* Set new tty mode */
+	}
+	set_my_state_wont(option);
+}
+
+/*
+ * Given a buffer returned by tgetent(), this routine will turn
+ * the pipe seperated list of names in the buffer into an array
+ * of pointers to null terminated names.  We toss out any bad,
+ * duplicate, or verbose names (names with spaces).
+ */
+
+static char *name_unknown = "UNKNOWN";
+static char *unknown[] = { 0, 0 };
+
+static	char **
+mklist(buf, name)
+	char *buf, *name;
+{
+	register int n;
+	register char c, *cp, **argvp, *cp2, **argv, **avt;
+
+	if (name) {
+		if (strlen(name) > 40) {
+			name = 0;
+			unknown[0] = name_unknown;
+		} else {
+			unknown[0] = name;
+			upcase(name);
+		}
+	} else
+		unknown[0] = name_unknown;
+	/*
+	 * Count up the number of names.
+	 */
+	for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
+		if (*cp == '|')
+			n++;
+	}
+	/*
+	 * Allocate an array to put the name pointers into
+	 */
+	argv = (char **)malloc((n+3)*sizeof(char *));
+	if (argv == 0)
+		return(unknown);
+	while (--n >= 0)
+	    argv[n] = 0;
+
+	/*
+	 * Fill up the array of pointers to names.
+	 */
+	*argv = 0;
+	argvp = argv+1;
+	n = 0;
+	for (cp = cp2 = buf; (c = *cp);  cp++) {
+		if (c == '|' || c == ':') {
+			*cp++ = '\0';
+			/*
+			 * Skip entries that have spaces or are over 40
+			 * characters long.  If this is our environment
+			 * name, then put it up front.  Otherwise, as
+			 * long as this is not a duplicate name (case
+			 * insensitive) add it to the list.
+			 */
+			if (n || (cp - cp2 > 41))
+				;
+			else if (name && (strncasecmp(name, cp2, 
+						      (unsigned) (cp-cp2)) 
+					  == 0))
+				*argv = cp2;
+			else if (is_unique(cp2, argv+1, argvp))
+				*argvp++ = cp2;
+			if (c == ':')
+				break;
+			/*
+			 * Skip multiple delimiters. Reset cp2 to
+			 * the beginning of the next name. Reset n,
+			 * the flag for names with spaces.
+			 */
+			while ((c = *cp) == '|')
+				cp++;
+			cp2 = cp;
+			n = 0;
+		}
+		/*
+		 * Skip entries with spaces or non-ascii values.
+		 * Convert lower case letters to upper case.
+		 */
+		if ((c == ' ') || !isascii(c))
+			n = 1;
+		else if (islower((unsigned char) c))
+			*cp = toupper((unsigned char) c);
+	}
+	
+	/*
+	 * Check for an old V6 2 character name.  If the second
+	 * name points to the beginning of the buffer, and is
+	 * only 2 characters long, move it to the end of the array.
+	 */
+	if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
+		--argvp;
+		for (avt = &argv[1]; avt < argvp; avt++)
+			*avt = *(avt+1);
+		*argvp++ = buf;
+	}
+
+	/*
+	 * Duplicate last name, for TTYPE option, and null
+	 * terminate the array.  If we didn't find a match on
+	 * our terminal name, put that name at the beginning.
+	 */
+	cp = *(argvp-1);
+	*argvp++ = cp;
+	*argvp = 0;
+
+	if (*argv == 0) {
+		if (name)
+			*argv = name;
+		else {
+			--argvp;
+			for (avt = argv; avt < argvp; avt++)
+				*avt = *(avt+1);
+		}
+	}
+	if (*argv)
+		return(argv);
+	else
+		return(unknown);
+}
+
+static int
+is_unique(name, as, ae)
+	register char *name, **as, **ae;
+{
+	register char **ap;
+	register unsigned int n;
+
+	n = strlen(name) + 1;
+	for (ap = as; ap < ae; ap++)
+		if (strncasecmp(*ap, name, n) == 0)
+			return(0);
+	return (1);
+}
+
+#ifndef	HAVE_SETUPTERM
+char termbuf[1024];
+
+	/*ARGSUSED*/
+static int
+setupterm(tname, fd, errp)
+	char *tname;
+	int fd, *errp;
+{
+	if (tgetent(termbuf, tname) == 1) {
+		termbuf[1023] = '\0';
+		if (errp)
+			*errp = 1;
+		return(0);
+	}
+	if (errp)
+		*errp = 0;
+	return(-1);
+}
+#else
+#define	termbuf	ttytype
+extern char ttytype[];
+#endif
+
+int resettermname = 1;
+
+static	char *
+gettermname()
+{
+	char *tname;
+	static char **tnamep = 0;
+	static char **next;
+	int err;
+
+	if (resettermname) {
+		resettermname = 0;
+		if (tnamep && tnamep != unknown)
+			free(tnamep);
+		if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
+				(setupterm(tname, 1, &err) == 0)) {
+			tnamep = mklist(termbuf, tname);
+		} else {
+			if (tname && (strlen(tname) <= 40)) {
+				unknown[0] = tname;
+				upcase(tname);
+			} else
+				unknown[0] = name_unknown;
+			tnamep = unknown;
+		}
+		next = tnamep;
+	}
+	if (*next == 0)
+		next = tnamep;
+	return(*next++);
+}
+/*
+ * suboption()
+ *
+ *	Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ *
+ *	Currently we recognize:
+ *
+ *		Terminal type, send request.
+ *		Terminal speed (send request).
+ *		Local flow control (is request).
+ *		Linemode
+ */
+
+    static void
+suboption()
+{
+    unsigned char subchar;
+
+    printsub('<', subbuffer, SB_LEN()+2);
+    switch (subchar = SB_GET()) {
+    case TELOPT_TTYPE:
+	if (my_want_state_is_wont(TELOPT_TTYPE))
+	    return;
+	if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
+	    return;
+	} else {
+	    char *name;
+	    unsigned char temp[50];
+	    int len;
+
+#if	defined(TN3270)
+	    if (tn3270_ttype()) {
+		return;
+	    }
+#endif	/* defined(TN3270) */
+	    name = gettermname();
+	    len = strlen(name) + 4 + 2;
+	    if (len < NETROOM()) {
+		sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
+				TELQUAL_IS, name, IAC, SE);
+		ring_supply_data(&netoring, temp, len);
+		printsub('>', &temp[2], len-2);
+	    } else {
+		ExitString("No room in buffer for terminal type.\n", 1);
+		/*NOTREACHED*/
+	    }
+	}
+	break;
+    case TELOPT_TSPEED:
+	if (my_want_state_is_wont(TELOPT_TSPEED))
+	    return;
+	if (SB_EOF())
+	    return;
+	if (SB_GET() == TELQUAL_SEND) {
+	    long o_speed, ispeed;
+	    unsigned char temp[50];
+	    int len;
+
+	    TerminalSpeeds(&ispeed, &o_speed);
+
+	    sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
+		    TELQUAL_IS, o_speed, ispeed, IAC, SE);
+	    len = strlen((char *)temp+4) + 4;	/* temp[3] is 0 ... */
+
+	    if (len < NETROOM()) {
+		ring_supply_data(&netoring, temp, len);
+		printsub('>', temp+2, len - 2);
+	    }
+/*@*/	    else printf("lm_will: not enough room in buffer\n");
+	}
+	break;
+    case TELOPT_LFLOW:
+	if (my_want_state_is_wont(TELOPT_LFLOW))
+	    return;
+	if (SB_EOF())
+	    return;
+	switch(SB_GET()) {
+	case LFLOW_RESTART_ANY:
+	    restartany = 1;
+	    break;
+	case LFLOW_RESTART_XON:
+	    restartany = 0;
+	    break;
+	case LFLOW_ON:
+	    localflow = 1;
+	    break;
+	case LFLOW_OFF:
+	    localflow = 0;
+	    break;
+	default:
+	    return;
+	}
+	setcommandmode();
+	setconnmode(0);
+	break;
+
+    case TELOPT_LINEMODE:
+	if (my_want_state_is_wont(TELOPT_LINEMODE))
+	    return;
+	if (SB_EOF())
+	    return;
+	switch (SB_GET()) {
+	case WILL:
+	    lm_will(subpointer, SB_LEN());
+	    break;
+	case WONT:
+	    lm_wont(subpointer, SB_LEN());
+	    break;
+	case DO:
+	    lm_do(subpointer, SB_LEN());
+	    break;
+	case DONT:
+	    lm_dont(subpointer, SB_LEN());
+	    break;
+	case LM_SLC:
+	    slc(subpointer, SB_LEN());
+	    break;
+	case LM_MODE:
+	    lm_mode(subpointer, SB_LEN(), 0);
+	    break;
+	default:
+	    break;
+	}
+	break;
+
+#ifdef	OLD_ENVIRON
+    case TELOPT_OLD_ENVIRON:
+#endif
+    case TELOPT_NEW_ENVIRON:
+	if (SB_EOF())
+	    return;
+	switch(SB_PEEK()) {
+	case TELQUAL_IS:
+	case TELQUAL_INFO:
+	    if (my_want_state_is_dont(subchar))
+		return;
+	    break;
+	case TELQUAL_SEND:
+	    if (my_want_state_is_wont(subchar)) {
+		return;
+	    }
+	    break;
+	default:
+	    return;
+	}
+	env_opt(subpointer, SB_LEN());
+	break;
+
+    case TELOPT_XDISPLOC:
+	if (my_want_state_is_wont(TELOPT_XDISPLOC))
+	    return;
+	if (SB_EOF())
+	    return;
+	if (SB_GET() == TELQUAL_SEND) {
+	    unsigned char temp[50], *dp;
+	    int len;
+
+	    if (((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) ||
+		(! env_is_exported((unsigned char *)"DISPLAY"))) {
+		/*
+		 * Something happened, we no longer have a DISPLAY
+		 * variable.  So, turn off the option.
+		 */
+		send_wont(TELOPT_XDISPLOC, 1);
+		break;
+	    }
+	    sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
+		    TELQUAL_IS, dp, IAC, SE);
+	    len = strlen((char *)temp+4) + 4;	/* temp[3] is 0 ... */
+
+	    if (len < NETROOM()) {
+		ring_supply_data(&netoring, temp, len);
+		printsub('>', temp+2, len - 2);
+	    }
+/*@*/	    else printf("lm_will: not enough room in buffer\n");
+	}
+	break;
+
+#if	defined(AUTHENTICATION)
+	case TELOPT_AUTHENTICATION: {
+		if (!autologin)
+			break;
+		if (SB_EOF())
+			return;
+		switch(SB_GET()) {
+		case TELQUAL_IS:
+			if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+				return;
+			auth_is(subpointer, SB_LEN());
+			break;
+		case TELQUAL_SEND:
+			if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+				return;
+			auth_send(subpointer, SB_LEN());
+			break;
+		case TELQUAL_REPLY:
+			if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+				return;
+			auth_reply(subpointer, SB_LEN());
+			break;
+		case TELQUAL_NAME:
+			if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+				return;
+			auth_name(subpointer, SB_LEN());
+			break;
+		}
+	}
+	break;
+#endif
+#ifdef	ENCRYPTION
+	case TELOPT_ENCRYPT:
+		if (SB_EOF())
+			return;
+		switch(SB_GET()) {
+		case ENCRYPT_START:
+			if (my_want_state_is_dont(TELOPT_ENCRYPT))
+				return;
+			encrypt_start(subpointer, SB_LEN());
+			break;
+		case ENCRYPT_END:
+			if (my_want_state_is_dont(TELOPT_ENCRYPT))
+				return;
+			encrypt_end();
+			break;
+		case ENCRYPT_SUPPORT:
+			if (my_want_state_is_wont(TELOPT_ENCRYPT))
+				return;
+			encrypt_support(subpointer, SB_LEN());
+			break;
+		case ENCRYPT_REQSTART:
+			if (my_want_state_is_wont(TELOPT_ENCRYPT))
+				return;
+			encrypt_request_start(subpointer, SB_LEN());
+			break;
+		case ENCRYPT_REQEND:
+			if (my_want_state_is_wont(TELOPT_ENCRYPT))
+				return;
+			/*
+			 * We can always send an REQEND so that we cannot
+			 * get stuck encrypting.  We should only get this
+			 * if we have been able to get in the correct mode
+			 * anyhow.
+			 */
+			encrypt_request_end();
+			break;
+		case ENCRYPT_IS:
+			if (my_want_state_is_dont(TELOPT_ENCRYPT))
+				return;
+			encrypt_is(subpointer, SB_LEN());
+			break;
+		case ENCRYPT_REPLY:
+			if (my_want_state_is_wont(TELOPT_ENCRYPT))
+				return;
+			encrypt_reply(subpointer, SB_LEN());
+			break;
+		case ENCRYPT_ENC_KEYID:
+			if (my_want_state_is_dont(TELOPT_ENCRYPT))
+				return;
+			encrypt_enc_keyid(subpointer, SB_LEN());
+			break;
+		case ENCRYPT_DEC_KEYID:
+			if (my_want_state_is_wont(TELOPT_ENCRYPT))
+				return;
+			encrypt_dec_keyid(subpointer, SB_LEN());
+			break;
+		default:
+			break;
+		}
+		break;
+#endif	/* ENCRYPTION */
+    default:
+	break;
+    }
+}
+
+static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
+
+    void
+lm_will(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/	printf("lm_will: no command!!!\n");	/* Should not happen... */
+	return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:	/* We shouldn't ever get this... */
+    default:
+	str_lm[3] = DONT;
+	str_lm[4] = cmd[0];
+	if (NETROOM() > sizeof(str_lm)) {
+	    ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+	    printsub('>', &str_lm[2], sizeof(str_lm)-2);
+	}
+/*@*/	else printf("lm_will: not enough room in buffer\n");
+	break;
+    }
+}
+
+    void
+lm_wont(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/	printf("lm_wont: no command!!!\n");	/* Should not happen... */
+	return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:	/* We shouldn't ever get this... */
+    default:
+	/* We are always DONT, so don't respond */
+	return;
+    }
+}
+
+    void
+lm_do(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/	printf("lm_do: no command!!!\n");	/* Should not happen... */
+	return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:
+    default:
+	str_lm[3] = WONT;
+	str_lm[4] = cmd[0];
+	if (NETROOM() > sizeof(str_lm)) {
+	    ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+	    printsub('>', &str_lm[2], sizeof(str_lm)-2);
+	}
+/*@*/	else printf("lm_do: not enough room in buffer\n");
+	break;
+    }
+}
+
+    void
+lm_dont(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/	printf("lm_dont: no command!!!\n");	/* Should not happen... */
+	return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:
+    default:
+	/* we are always WONT, so don't respond */
+	break;
+    }
+}
+
+static unsigned char str_lm_mode[] = {
+	IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
+};
+
+	void
+lm_mode(cmd, len, init)
+	unsigned char *cmd;
+	int len, init;
+{
+	if (len != 1)
+		return;
+	if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
+		return;
+	if (*cmd&MODE_ACK)
+		return;
+	linemode = *cmd&(MODE_MASK&~MODE_ACK);
+	str_lm_mode[4] = linemode;
+	if (!init)
+	    str_lm_mode[4] |= MODE_ACK;
+	if (NETROOM() > sizeof(str_lm_mode)) {
+	    ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
+	    printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
+	}
+/*@*/	else printf("lm_mode: not enough room in buffer\n");
+	setconnmode(0);	/* set changed mode */
+}
+
+
+
+/*
+ * slc()
+ * Handle special character suboption of LINEMODE.
+ */
+
+struct spc {
+	cc_t val;
+	cc_t *valp;
+	char flags;	/* Current flags & level */
+	char mylevel;	/* Maximum level & flags */
+} spc_data[NSLC+1];
+
+#define SLC_IMPORT	0
+#define	SLC_EXPORT	1
+#define SLC_RVALUE	2
+static int slc_mode = SLC_EXPORT;
+
+	void
+slc_init()
+{
+	register struct spc *spcp;
+
+	localchars = 1;
+	for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
+		spcp->val = 0;
+		spcp->valp = 0;
+		spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
+	}
+
+#define	initfunc(func, flags) { \
+					spcp = &spc_data[func]; \
+					if ((spcp->valp = tcval(func)) != NULL) { \
+					    spcp->val = *spcp->valp; \
+					    spcp->mylevel = SLC_VARIABLE|flags; \
+					} else { \
+					    spcp->val = 0; \
+					    spcp->mylevel = SLC_DEFAULT; \
+					} \
+				    }
+
+	initfunc(SLC_SYNCH, 0);
+	/* No BRK */
+	initfunc(SLC_AO, 0);
+	initfunc(SLC_AYT, 0);
+	/* No EOR */
+	initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
+	initfunc(SLC_EOF, 0);
+#ifndef	SYSV_TERMIO
+	initfunc(SLC_SUSP, SLC_FLUSHIN);
+#endif
+	initfunc(SLC_EC, 0);
+	initfunc(SLC_EL, 0);
+#ifndef	SYSV_TERMIO
+	initfunc(SLC_EW, 0);
+	initfunc(SLC_RP, 0);
+	initfunc(SLC_LNEXT, 0);
+#endif
+	initfunc(SLC_XON, 0);
+	initfunc(SLC_XOFF, 0);
+#ifdef	SYSV_TERMIO
+	spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
+	spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
+#endif
+	initfunc(SLC_FORW1, 0);
+#ifdef	USE_TERMIO
+	initfunc(SLC_FORW2, 0);
+	/* No FORW2 */
+#endif
+
+	initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
+#undef	initfunc
+
+	if (slc_mode == SLC_EXPORT)
+		slc_export();
+	else
+		slc_import(1);
+
+}
+
+    void
+slcstate()
+{
+    printf("Special characters are %s values\n",
+		slc_mode == SLC_IMPORT ? "remote default" :
+		slc_mode == SLC_EXPORT ? "local" :
+					 "remote");
+}
+
+    void
+slc_mode_export()
+{
+    slc_mode = SLC_EXPORT;
+    if (my_state_is_will(TELOPT_LINEMODE))
+	slc_export();
+}
+
+    void
+slc_mode_import(def)
+    int def;
+{
+    slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
+    if (my_state_is_will(TELOPT_LINEMODE))
+	slc_import(def);
+}
+
+unsigned char slc_import_val[] = {
+	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
+};
+unsigned char slc_import_def[] = {
+	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
+};
+
+    void
+slc_import(def)
+    int def;
+{
+    if (NETROOM() > sizeof(slc_import_val)) {
+	if (def) {
+	    ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
+	    printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
+	} else {
+	    ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
+	    printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
+	}
+    }
+/*@*/ else printf("slc_import: not enough room\n");
+}
+
+    void
+slc_export()
+{
+    register struct spc *spcp;
+
+    TerminalDefaultChars();
+
+    slc_start_reply();
+    for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+	if (spcp->mylevel != SLC_NOSUPPORT) {
+	    if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+		spcp->flags = SLC_NOSUPPORT;
+	    else
+		spcp->flags = spcp->mylevel;
+	    if (spcp->valp)
+		spcp->val = *spcp->valp;
+	    slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+	}
+    }
+    slc_end_reply();
+    (void)slc_update();
+    setconnmode(1);	/* Make sure the character values are set */
+}
+
+	void
+slc(cp, len)
+	register unsigned char *cp;
+	int len;
+{
+	register struct spc *spcp;
+	register int func,level;
+
+	slc_start_reply();
+
+	for (; len >= 3; len -=3, cp +=3) {
+
+		func = cp[SLC_FUNC];
+
+		if (func == 0) {
+			/*
+			 * Client side: always ignore 0 function.
+			 */
+			continue;
+		}
+		if (func > NSLC) {
+			if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
+				slc_add_reply(func, SLC_NOSUPPORT, 0);
+			continue;
+		}
+
+		spcp = &spc_data[func];
+
+		level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
+
+		if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
+		    ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
+			continue;
+		}
+
+		if (level == (SLC_DEFAULT|SLC_ACK)) {
+			/*
+			 * This is an error condition, the SLC_ACK
+			 * bit should never be set for the SLC_DEFAULT
+			 * level.  Our best guess to recover is to
+			 * ignore the SLC_ACK bit.
+			 */
+			cp[SLC_FLAGS] &= ~SLC_ACK;
+		}
+
+		if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
+			spcp->val = (cc_t)cp[SLC_VALUE];
+			spcp->flags = cp[SLC_FLAGS];	/* include SLC_ACK */
+			continue;
+		}
+
+		level &= ~SLC_ACK;
+
+		if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
+			spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
+			spcp->val = (cc_t)cp[SLC_VALUE];
+		}
+		if (level == SLC_DEFAULT) {
+			if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
+				spcp->flags = spcp->mylevel;
+			else
+				spcp->flags = SLC_NOSUPPORT;
+		}
+		slc_add_reply(func, spcp->flags, spcp->val);
+	}
+	slc_end_reply();
+	if (slc_update())
+		setconnmode(1);	/* set the  new character values */
+}
+
+    void
+slc_check()
+{
+    register struct spc *spcp;
+
+    slc_start_reply();
+    for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+	if (spcp->valp && spcp->val != *spcp->valp) {
+	    spcp->val = *spcp->valp;
+	    if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+		spcp->flags = SLC_NOSUPPORT;
+	    else
+		spcp->flags = spcp->mylevel;
+	    slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+	}
+    }
+    slc_end_reply();
+    setconnmode(1);
+}
+
+
+unsigned char slc_reply[128];
+unsigned char *slc_replyp;
+
+	void
+slc_start_reply()
+{
+	slc_replyp = slc_reply;
+	*slc_replyp++ = IAC;
+	*slc_replyp++ = SB;
+	*slc_replyp++ = TELOPT_LINEMODE;
+	*slc_replyp++ = LM_SLC;
+}
+
+	void
+slc_add_reply(func, flags, value)
+	unsigned char func;
+	unsigned char flags;
+	cc_t value;
+{
+	if ((slc_replyp - slc_reply) + 6 > sizeof(slc_reply))
+		return;
+	if ((*slc_replyp++ = func) == IAC)
+		*slc_replyp++ = IAC;
+	if ((*slc_replyp++ = flags) == IAC)
+		*slc_replyp++ = IAC;
+	if ((*slc_replyp++ = (unsigned char)value) == IAC)
+		*slc_replyp++ = IAC;
+}
+
+    void
+slc_end_reply()
+{
+    register int len;
+
+    len = slc_replyp - slc_reply;
+    if (len <= 4 || (len + 2 > sizeof(slc_reply)))
+	return;
+    *slc_replyp++ = IAC;
+    *slc_replyp++ = SE;
+    len += 2;
+    if (NETROOM() > len) {
+	ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
+	printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
+    }
+/*@*/else printf("slc_end_reply: not enough room\n");
+}
+
+	int
+slc_update()
+{
+	register struct spc *spcp;
+	int need_update = 0;
+
+	for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+		if (!(spcp->flags&SLC_ACK))
+			continue;
+		spcp->flags &= ~SLC_ACK;
+		if (spcp->valp && (*spcp->valp != spcp->val)) {
+			*spcp->valp = spcp->val;
+			need_update = 1;
+		}
+	}
+	return(need_update);
+}
+
+#ifdef	OLD_ENVIRON
+# ifdef	ENV_HACK
+/*
+ * Earlier version of telnet/telnetd from the BSD code had
+ * the definitions of VALUE and VAR reversed.  To ensure
+ * maximum interoperability, we assume that the server is
+ * an older BSD server, until proven otherwise.  The newer
+ * BSD servers should be able to handle either definition,
+ * so it is better to use the wrong values if we don't
+ * know what type of server it is.
+ */
+int env_auto = 1;
+int old_env_var = OLD_ENV_VAR;
+int old_env_value = OLD_ENV_VALUE;
+# else
+#  define old_env_var OLD_ENV_VAR
+#  define old_env_value OLD_ENV_VALUE
+# endif
+#endif
+
+	void
+env_opt(buf, len)
+	register unsigned char *buf;
+	register int len;
+{
+	register unsigned char *ep = 0, *epc = 0;
+	register int i;
+
+	switch(buf[0]&0xff) {
+	case TELQUAL_SEND:
+		env_opt_start();
+		if (len == 1) {
+			env_opt_add(NULL);
+		} else for (i = 1; i < len; i++) {
+			switch (buf[i]&0xff) {
+#ifdef	OLD_ENVIRON
+			case OLD_ENV_VAR:
+# ifdef	ENV_HACK
+				if (telopt_environ == TELOPT_OLD_ENVIRON
+				    && env_auto) {
+					/* Server has the same definitions */
+					old_env_var = OLD_ENV_VAR;
+					old_env_value = OLD_ENV_VALUE;
+				}
+				/* FALL THROUGH */
+# endif
+			case OLD_ENV_VALUE:
+				/*
+				 * Although OLD_ENV_VALUE is not legal, we will
+				 * still recognize it, just in case it is an
+				 * old server that has VAR & VALUE mixed up...
+				 */
+				/* FALL THROUGH */
+#else
+			case NEW_ENV_VAR:
+#endif
+			case ENV_USERVAR:
+				if (ep) {
+					*epc = 0;
+					env_opt_add(ep);
+				}
+				ep = epc = &buf[i+1];
+				break;
+			case ENV_ESC:
+				i++;
+				/*FALL THROUGH*/
+			default:
+				if (epc)
+					*epc++ = buf[i];
+				break;
+			}
+		}
+		if (ep) {
+			*epc = 0;
+			env_opt_add(ep);
+		}
+		env_opt_end(1);
+		break;
+
+	case TELQUAL_IS:
+	case TELQUAL_INFO:
+		/* Ignore for now.  We shouldn't get it anyway. */
+		break;
+
+	default:
+		break;
+	}
+}
+
+#define	OPT_REPLY_SIZE	256
+unsigned char *opt_reply;
+unsigned char *opt_replyp;
+unsigned char *opt_replyend;
+
+	void
+env_opt_start()
+{
+	if (opt_reply)
+		opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
+	else
+		opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE);
+	if (opt_reply == NULL) {
+/*@*/		printf("env_opt_start: malloc()/realloc() failed!!!\n");
+		opt_reply = opt_replyp = opt_replyend = NULL;
+		return;
+	}
+	opt_replyp = opt_reply;
+	opt_replyend = opt_reply + OPT_REPLY_SIZE;
+	*opt_replyp++ = IAC;
+	*opt_replyp++ = SB;
+	*opt_replyp++ = telopt_environ;
+	*opt_replyp++ = TELQUAL_IS;
+}
+
+	void
+env_opt_start_info()
+{
+	env_opt_start();
+	if (opt_replyp)
+	    opt_replyp[-1] = TELQUAL_INFO;
+}
+
+	void
+env_opt_add(ep)
+	register unsigned char *ep;
+{
+	register unsigned char *vp, c;
+	unsigned int len, olen, elen;
+
+	if (opt_reply == NULL)		/*XXX*/
+		return;			/*XXX*/
+
+	if (ep == NULL || *ep == '\0') {
+		/* Send user defined variables first. */
+		env_default(1, 0);
+		while ((ep = env_default(0, 0)) != NULL)
+			env_opt_add(ep);
+
+		/* Now add the list of well know variables.  */
+		env_default(1, 1);
+		while ((ep = env_default(0, 1)) != NULL)
+			env_opt_add(ep);
+		return;
+	}
+	vp = env_getvalue(ep);
+	elen = 2 * (vp ? strlen((char *)vp) : 0) +
+		2 * strlen((char *)ep) + 6;
+	if ((opt_replyend - opt_replyp) < elen)
+	{
+		len = opt_replyend - opt_reply + elen;
+		olen = opt_replyp - opt_reply;
+		opt_reply = (unsigned char *)realloc(opt_reply, len);
+		if (opt_reply == NULL) {
+/*@*/			printf("env_opt_add: realloc() failed!!!\n");
+			opt_reply = opt_replyp = opt_replyend = NULL;
+			return;
+		}
+		opt_replyp = opt_reply + olen;
+		opt_replyend = opt_reply + len;
+	}
+	if (opt_welldefined((char *) ep))
+#ifdef	OLD_ENVIRON
+		if (telopt_environ == TELOPT_OLD_ENVIRON)
+			*opt_replyp++ = old_env_var;
+		else
+#endif
+			*opt_replyp++ = NEW_ENV_VAR;
+	else
+		*opt_replyp++ = ENV_USERVAR;
+	for (;;) {
+		while ((c = *ep++)) {
+			switch(c&0xff) {
+			case IAC:
+				*opt_replyp++ = IAC;
+				break;
+			case NEW_ENV_VAR:
+			case NEW_ENV_VALUE:
+			case ENV_ESC:
+			case ENV_USERVAR:
+				*opt_replyp++ = ENV_ESC;
+				break;
+			}
+			*opt_replyp++ = c;
+		}
+		if ((ep = vp) != NULL) {
+#ifdef	OLD_ENVIRON
+			if (telopt_environ == TELOPT_OLD_ENVIRON)
+				*opt_replyp++ = old_env_value;
+			else
+#endif
+				*opt_replyp++ = NEW_ENV_VALUE;
+			vp = NULL;
+		} else
+			break;
+	}
+}
+
+	int
+opt_welldefined(ep)
+	char *ep;
+{
+	if ((strcmp(ep, "USER") == 0) ||
+	    (strcmp(ep, "DISPLAY") == 0) ||
+	    (strcmp(ep, "PRINTER") == 0) ||
+	    (strcmp(ep, "SYSTEMTYPE") == 0) ||
+	    (strcmp(ep, "JOB") == 0) ||
+	    (strcmp(ep, "ACCT") == 0))
+		return(1);
+	return(0);
+}
+	void
+env_opt_end(emptyok)
+	register int emptyok;
+{
+	register int len;
+
+	len = opt_replyp - opt_reply + 2;
+	if (emptyok || len > 6) {
+		*opt_replyp++ = IAC;
+		*opt_replyp++ = SE;
+		if (NETROOM() > len) {
+			ring_supply_data(&netoring, opt_reply, len);
+			printsub('>', &opt_reply[2], len - 2);
+		}
+/*@*/		else printf("slc_end_reply: not enough room\n");
+	}
+	if (opt_reply) {
+		free(opt_reply);
+		opt_reply = opt_replyp = opt_replyend = NULL;
+	}
+}
+
+
+
+    int
+telrcv()
+{
+    register int c;
+    register int scc;
+    register unsigned char *sbp = NULL;
+    int count;
+    int returnValue = 0;
+
+    scc = 0;
+    count = 0;
+    while (TTYROOM() > 2) {
+	if (scc == 0) {
+	    if (count) {
+		ring_consumed(&netiring, count);
+		returnValue = 1;
+		count = 0;
+	    }
+	    sbp = netiring.consume;
+	    scc = ring_full_consecutive(&netiring);
+	    if (scc == 0) {
+		/* No more data coming in */
+		break;
+	    }
+	}
+
+	c = *sbp++ & 0xff, scc--; count++;
+#ifdef	ENCRYPTION
+	if (decrypt_input)
+		c = (*decrypt_input)(c);
+#endif	/* ENCRYPTION */
+
+	switch (telrcv_state) {
+
+	case TS_CR:
+	    telrcv_state = TS_DATA;
+	    if (c == '\0') {
+		break;	/* Ignore \0 after CR */
+	    }
+	    else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
+		TTYADD(c);
+		break;
+	    }
+	    /* Else, fall through */
+
+	case TS_DATA:
+	    if (c == IAC) {
+		telrcv_state = TS_IAC;
+		break;
+	    }
+#	    if defined(TN3270)
+	    if (In3270) {
+		*Ifrontp++ = c;
+		while (scc > 0) {
+		    c = *sbp++ & 0377, scc--; count++;
+#ifdef	ENCRYPTION
+		    if (decrypt_input)
+			c = (*decrypt_input)(c);
+#endif	/* ENCRYPTION */
+		    if (c == IAC) {
+			telrcv_state = TS_IAC;
+			break;
+		    }
+		    *Ifrontp++ = c;
+		}
+	    } else
+#	    endif /* defined(TN3270) */
+		    /*
+		     * The 'crmod' hack (see following) is needed
+		     * since we can't * set CRMOD on output only.
+		     * Machines like MULTICS like to send \r without
+		     * \n; since we must turn off CRMOD to get proper
+		     * input, the mapping is done here (sigh).
+		     */
+	    if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
+		if (scc > 0) {
+		    c = *sbp&0xff;
+#ifdef	ENCRYPTION
+		    if (decrypt_input)
+			c = (*decrypt_input)(c);
+#endif	/* ENCRYPTION */
+		    if (c == 0) {
+			sbp++, scc--; count++;
+			/* a "true" CR */
+			TTYADD('\r');
+		    } else if (my_want_state_is_dont(TELOPT_ECHO) &&
+					(c == '\n')) {
+			sbp++, scc--; count++;
+			TTYADD('\n');
+		    } else {
+#ifdef	ENCRYPTION
+		        if (decrypt_input)
+			    (*decrypt_input)(-1);
+#endif	/* ENCRYPTION */
+
+			TTYADD('\r');
+			if (crmod) {
+				TTYADD('\n');
+			}
+		    }
+		} else {
+		    telrcv_state = TS_CR;
+		    TTYADD('\r');
+		    if (crmod) {
+			    TTYADD('\n');
+		    }
+		}
+	    } else {
+		TTYADD(c);
+	    }
+	    continue;
+
+	case TS_IAC:
+process_iac:
+	    switch (c) {
+	    
+	    case WILL:
+		telrcv_state = TS_WILL;
+		continue;
+
+	    case WONT:
+		telrcv_state = TS_WONT;
+		continue;
+
+	    case DO:
+		telrcv_state = TS_DO;
+		continue;
+
+	    case DONT:
+		telrcv_state = TS_DONT;
+		continue;
+
+	    case DM:
+		    /*
+		     * We may have missed an urgent notification,
+		     * so make sure we flush whatever is in the
+		     * buffer currently.
+		     */
+		printoption("RCVD", IAC, DM);
+		SYNCHing = 1;
+		(void) ttyflush(1);
+		SYNCHing = stilloob();
+		settimer(gotDM);
+		break;
+
+	    case SB:
+		SB_CLEAR();
+		telrcv_state = TS_SB;
+		continue;
+
+#	    if defined(TN3270)
+	    case EOR:
+		if (In3270) {
+		    if (Ibackp == Ifrontp) {
+			Ibackp = Ifrontp = Ibuf;
+			ISend = 0;	/* should have been! */
+		    } else {
+			Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
+			ISend = 1;
+		    }
+		}
+		printoption("RCVD", IAC, EOR);
+		break;
+#	    endif /* defined(TN3270) */
+
+	    case IAC:
+#	    if !defined(TN3270)
+		TTYADD(IAC);
+#	    else /* !defined(TN3270) */
+		if (In3270) {
+		    *Ifrontp++ = IAC;
+		} else {
+		    TTYADD(IAC);
+		}
+#	    endif /* !defined(TN3270) */
+		break;
+
+	    case NOP:
+	    case GA:
+	    default:
+		printoption("RCVD", IAC, c);
+		break;
+	    }
+	    telrcv_state = TS_DATA;
+	    continue;
+
+	case TS_WILL:
+	    printoption("RCVD", WILL, c);
+	    willoption(c);
+	    SetIn3270();
+	    telrcv_state = TS_DATA;
+	    continue;
+
+	case TS_WONT:
+	    printoption("RCVD", WONT, c);
+	    wontoption(c);
+	    SetIn3270();
+	    telrcv_state = TS_DATA;
+	    continue;
+
+	case TS_DO:
+	    printoption("RCVD", DO, c);
+	    dooption(c);
+	    SetIn3270();
+	    if (c == TELOPT_NAWS) {
+		sendnaws();
+	    } else if (c == TELOPT_LFLOW) {
+		localflow = 1;
+		setcommandmode();
+		setconnmode(0);
+	    }
+	    telrcv_state = TS_DATA;
+	    continue;
+
+	case TS_DONT:
+	    printoption("RCVD", DONT, c);
+	    dontoption(c);
+	    flushline = 1;
+	    setconnmode(0);	/* set new tty mode (maybe) */
+	    SetIn3270();
+	    telrcv_state = TS_DATA;
+	    continue;
+
+	case TS_SB:
+	    if (c == IAC) {
+		telrcv_state = TS_SE;
+	    } else {
+		SB_ACCUM(c);
+	    }
+	    continue;
+
+	case TS_SE:
+	    if (c != SE) {
+		if (c != IAC) {
+		    /*
+		     * This is an error.  We only expect to get
+		     * "IAC IAC" or "IAC SE".  Several things may
+		     * have happend.  An IAC was not doubled, the
+		     * IAC SE was left off, or another option got
+		     * inserted into the suboption are all possibilities.
+		     * If we assume that the IAC was not doubled,
+		     * and really the IAC SE was left off, we could
+		     * get into an infinate loop here.  So, instead,
+		     * we terminate the suboption, and process the
+		     * partial suboption if we can.
+		     */
+		    SB_ACCUM(IAC);
+		    SB_ACCUM(c);
+		    subpointer -= 2;
+		    SB_TERM();
+
+		    printoption("In SUBOPTION processing, RCVD", IAC, c);
+		    suboption();	/* handle sub-option */
+		    SetIn3270();
+		    telrcv_state = TS_IAC;
+		    goto process_iac;
+		}
+		SB_ACCUM(c);
+		telrcv_state = TS_SB;
+	    } else {
+		SB_ACCUM(IAC);
+		SB_ACCUM(SE);
+		subpointer -= 2;
+		SB_TERM();
+		suboption();	/* handle sub-option */
+		SetIn3270();
+		telrcv_state = TS_DATA;
+	    }
+	}
+    }
+    if (count)
+	ring_consumed(&netiring, count);
+    return returnValue||count;
+}
+
+static int bol = 1, local = 0;
+
+    int
+rlogin_susp()
+{
+    if (local) {
+	local = 0;
+	bol = 1;
+	command(0, "z\n", 2);
+	return(1);
+    }
+    return(0);
+}
+
+    static int
+telsnd()
+{
+    int tcc;
+    int count;
+    int returnValue = 0;
+    unsigned char *tbp = NULL;
+
+    tcc = 0;
+    count = 0;
+    while (NETROOM() > 2) {
+	register int sc;
+	register int c;
+
+	if (tcc == 0) {
+	    if (count) {
+		ring_consumed(&ttyiring, count);
+		returnValue = 1;
+		count = 0;
+	    }
+	    tbp = ttyiring.consume;
+	    tcc = ring_full_consecutive(&ttyiring);
+	    if (tcc == 0) {
+		break;
+	    }
+	}
+	c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
+	if (rlogin != _POSIX_VDISABLE) {
+		if (bol) {
+			bol = 0;
+			if (sc == rlogin) {
+				local = 1;
+				continue;
+			}
+		} else if (local) {
+			local = 0;
+			if (sc == '.' || c == termEofChar) {
+				bol = 1;
+				command(0, "close\n", 6);
+				continue;
+			}
+			if (sc == termSuspChar) {
+				bol = 1;
+				command(0, "z\n", 2);
+				continue;
+			}
+			if (sc == escape) {
+				command(0, (char *)tbp, tcc);
+				bol = 1;
+				count += tcc;
+				tcc = 0;
+				flushline = 1;
+				break;
+			}
+			if (sc != rlogin) {
+				++tcc;
+				--tbp;
+				--count;
+				c = sc = rlogin;
+			}
+		}
+		if ((sc == '\n') || (sc == '\r'))
+			bol = 1;
+	} else if (sc == escape) {
+	    /*
+	     * Double escape is a pass through of a single escape character.
+	     */
+	    if (tcc && strip(*tbp) == escape) {
+		tbp++;
+		tcc--;
+		count++;
+		bol = 0;
+	    } else {
+		command(0, (char *)tbp, tcc);
+		bol = 1;
+		count += tcc;
+		tcc = 0;
+		flushline = 1;
+		break;
+	    }
+	} else
+	    bol = 0;
+#ifdef	KLUDGELINEMODE
+	if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
+	    if (tcc > 0 && strip(*tbp) == echoc) {
+		tcc--; tbp++; count++;
+	    } else {
+		dontlecho = !dontlecho;
+		settimer(echotoggle);
+		setconnmode(0);
+		flushline = 1;
+		break;
+	    }
+	}
+#endif
+	if (MODE_LOCAL_CHARS(globalmode)) {
+	    if (TerminalSpecialChars(sc) == 0) {
+		bol = 1;
+		break;
+	    }
+	}
+	if (my_want_state_is_wont(TELOPT_BINARY)) {
+	    switch (c) {
+	    case '\n':
+		    /*
+		     * If we are in CRMOD mode (\r ==> \n)
+		     * on our local machine, then probably
+		     * a newline (unix) is CRLF (TELNET).
+		     */
+		if (MODE_LOCAL_CHARS(globalmode)) {
+		    NETADD('\r');
+		}
+		NETADD('\n');
+		bol = flushline = 1;
+		break;
+	    case '\r':
+		if (!crlf) {
+		    NET2ADD('\r', '\0');
+		} else {
+		    NET2ADD('\r', '\n');
+		}
+		bol = flushline = 1;
+		break;
+	    case IAC:
+		NET2ADD(IAC, IAC);
+		break;
+	    default:
+		NETADD(c);
+		break;
+	    }
+	} else if (c == IAC) {
+	    NET2ADD(IAC, IAC);
+	} else {
+	    NETADD(c);
+	}
+    }
+    if (count)
+	ring_consumed(&ttyiring, count);
+    return returnValue||count;		/* Non-zero if we did anything */
+}
+
+/*
+ * Scheduler()
+ *
+ * Try to do something.
+ *
+ * If we do something useful, return 1; else return 0.
+ *
+ */
+
+
+    int
+Scheduler(block)
+    int	block;			/* should we block in the select ? */
+{
+		/* One wants to be a bit careful about setting returnValue
+		 * to one, since a one implies we did some useful work,
+		 * and therefore probably won't be called to block next
+		 * time (TN3270 mode only).
+		 */
+    int returnValue;
+    int netin, netout, netex, ttyin, ttyout;
+
+    /* Decide which rings should be processed */
+
+    netout = ring_full_count(&netoring) &&
+	    (flushline ||
+		(my_want_state_is_wont(TELOPT_LINEMODE)
+#ifdef	KLUDGELINEMODE
+			&& (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
+#endif
+		) ||
+			my_want_state_is_will(TELOPT_BINARY));
+    ttyout = ring_full_count(&ttyoring);
+
+#if	defined(TN3270)
+    ttyin = ring_empty_count(&ttyiring) && (shell_active == 0);
+#else	/* defined(TN3270) */
+    ttyin = ring_empty_count(&ttyiring);
+#endif	/* defined(TN3270) */
+
+#if	defined(TN3270)
+    netin = ring_empty_count(&netiring);
+#   else /* !defined(TN3270) */
+    netin = !ISend && ring_empty_count(&netiring);
+#   endif /* !defined(TN3270) */
+
+    netex = !SYNCHing;
+
+    /* If we have seen a signal recently, reset things */
+#   if defined(TN3270) && defined(unix)
+    if (HaveInput) {
+	HaveInput = 0;
+	(void) signal(SIGIO, inputAvailable);
+    }
+#endif	/* defined(TN3270) && defined(unix) */
+
+    if (scheduler_lockout_tty) {
+	ttyin = ttyout = 0;
+    }
+
+    /* Call to system code to process rings */
+
+    returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
+
+    /* Now, look at the input rings, looking for work to do. */
+
+    if (ring_full_count(&ttyiring)) {
+#   if defined(TN3270)
+	if (In3270) {
+	    int c;
+
+	    c = DataFromTerminal(ttyiring.consume,
+					ring_full_consecutive(&ttyiring));
+	    if (c) {
+		returnValue = 1;
+	        ring_consumed(&ttyiring, c);
+	    }
+	} else {
+#   endif /* defined(TN3270) */
+	    returnValue |= telsnd();
+#   if defined(TN3270)
+	}
+#   endif /* defined(TN3270) */
+    }
+
+    if (ring_full_count(&netiring)) {
+#	if !defined(TN3270)
+	returnValue |= telrcv();
+#	else /* !defined(TN3270) */
+	returnValue = Push3270();
+#	endif /* !defined(TN3270) */
+    }
+    return returnValue;
+}
+
+/*
+ * Select from tty and network...
+ */
+    void
+telnet(user)
+    char *user;
+{
+    int printed_encrypt = 0;
+    
+    sys_telnet_init();
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION) 
+    {
+	static char local_host[256] = { 0 };
+
+	if (!local_host[0]) {
+		gethostname(local_host, sizeof(local_host));
+		local_host[sizeof(local_host)-1] = 0;
+	}
+	auth_encrypt_init(local_host, hostname, "TELNET", 0);
+	auth_encrypt_user(user);
+    }
+#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION)  */
+#   if !defined(TN3270)
+#if	defined(AUTHENTICATION)
+    if (autologin)
+	send_will(TELOPT_AUTHENTICATION, 1);
+#endif
+#ifdef	ENCRYPTION
+    if (telnetport || wantencryption) {
+	send_do(TELOPT_ENCRYPT, 1);
+	send_will(TELOPT_ENCRYPT, 1);
+    }
+#endif	/* ENCRYPTION */
+    if (telnetport) {
+	send_do(TELOPT_SGA, 1);
+	send_will(TELOPT_TTYPE, 1);
+	send_will(TELOPT_NAWS, 1);
+	send_will(TELOPT_TSPEED, 1);
+	send_will(TELOPT_LFLOW, 1);
+	send_will(TELOPT_LINEMODE, 1);
+	send_will(TELOPT_NEW_ENVIRON, 1);
+	send_do(TELOPT_STATUS, 1);
+	if (env_getvalue((unsigned char *)"DISPLAY") &&
+	    env_is_exported((unsigned char *)"DISPLAY"))
+	    send_will(TELOPT_XDISPLOC, 1);
+	if (eight)
+	    tel_enter_binary(eight);
+    }
+#   endif /* !defined(TN3270) */
+
+#ifdef ENCRYPTION
+    /*
+     * Note: we assume a tie to the authentication option here.  This
+     * is necessary so that authentication fails, we don't spin
+     * forever. 
+     */
+    if (wantencryption) {
+	extern int auth_has_failed;
+	time_t time_out = time(0) + 60;
+
+	send_do(TELOPT_ENCRYPT, 1);
+	send_will(TELOPT_ENCRYPT, 1);
+	while (1) {
+	    if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) {
+		printf("\nServer refused to negotiate authentication, which is required\n");
+		printf("for encryption.  Good-bye.\n\r");
+		Exit(1);
+	    }
+	    if (auth_has_failed) {
+		printf("\nNegotiation of authentication, which is required for encryption,\n");
+		printf("has failed.  Good-bye.\n\r");
+		Exit(1);
+	    }
+	    if (my_want_state_is_dont(TELOPT_ENCRYPT) ||
+		my_want_state_is_wont(TELOPT_ENCRYPT)) {
+		printf("\nServer refused to negotiate encryption.  Good-bye.\n\r");
+		Exit(1);
+	    }
+	    if (encrypt_is_encrypting())
+		break;
+	    if (time(0) > time_out) {
+		printf("\nEncryption could not be enabled.  Good-bye.\n\r");
+		Exit(1);
+	    }
+	    if (printed_encrypt == 0) {
+		    printed_encrypt = 1;
+		    printf("Waiting for encryption to be negotiated...\n");
+		    /*
+		     * Turn on MODE_TRAPSIG and then turn off localchars 
+		     * so that ^C will cause telnet to exit.
+		     */
+		    TerminalNewMode(getconnmode()|MODE_TRAPSIG);
+		    intr_waiting = 1;
+	    }
+	    if (intr_happened) {
+		    printf("\nUser requested an interrupt.  Good-bye.\n\r");
+		    Exit(1);
+	    }
+	    telnet_spin();
+	}
+	if (printed_encrypt) {
+		printf("done.\n");
+		intr_waiting = 0;
+		setconnmode(0);
+	}
+    }
+#endif
+
+
+#   if !defined(TN3270)
+    for (;;) {
+	int schedValue;
+
+	while ((schedValue = Scheduler(0)) != 0) {
+	    if (schedValue == -1) {
+		setcommandmode();
+		return;
+	    }
+	}
+
+	if (Scheduler(1) == -1) {
+	    setcommandmode();
+	    return;
+	}
+    }
+#   else /* !defined(TN3270) */
+    for (;;) {
+	int schedValue;
+
+	while (!In3270 && !shell_active) {
+	    if (Scheduler(1) == -1) {
+		setcommandmode();
+		return;
+	    }
+	}
+
+	while ((schedValue = Scheduler(0)) != 0) {
+	    if (schedValue == -1) {
+		setcommandmode();
+		return;
+	    }
+	}
+		/* If there is data waiting to go out to terminal, don't
+		 * schedule any more data for the terminal.
+		 */
+	if (ring_full_count(&ttyoring)) {
+	    schedValue = 1;
+	} else {
+	    if (shell_active) {
+		if (shell_continue() == 0) {
+		    ConnectScreen();
+		}
+	    } else if (In3270) {
+		schedValue = DoTerminalOutput();
+	    }
+	}
+	if (schedValue && (shell_active == 0)) {
+	    if (Scheduler(1) == -1) {
+		setcommandmode();
+		return;
+	    }
+	}
+    }
+#   endif /* !defined(TN3270) */
+}
+
+#if	0	/* XXX - this not being in is a bug */
+/*
+ * nextitem()
+ *
+ *	Return the address of the next "item" in the TELNET data
+ * stream.  This will be the address of the next character if
+ * the current address is a user data character, or it will
+ * be the address of the character following the TELNET command
+ * if the current address is a TELNET IAC ("I Am a Command")
+ * character.
+ */
+
+    static char *
+nextitem(current)
+    char *current;
+{
+    if ((*current&0xff) != IAC) {
+	return current+1;
+    }
+    switch (*(current+1)&0xff) {
+    case DO:
+    case DONT:
+    case WILL:
+    case WONT:
+	return current+3;
+    case SB:		/* loop forever looking for the SE */
+	{
+	    register char *look = current+2;
+
+	    for (;;) {
+		if ((*look++&0xff) == IAC) {
+		    if ((*look++&0xff) == SE) {
+			return look;
+		    }
+		}
+	    }
+	}
+    default:
+	return current+2;
+    }
+}
+#endif	/* 0 */
+
+/*
+ * netclear()
+ *
+ *	We are about to do a TELNET SYNCH operation.  Clear
+ * the path to the network.
+ *
+ *	Things are a bit tricky since we may have sent the first
+ * byte or so of a previous TELNET command into the network.
+ * So, we have to scan the network buffer from the beginning
+ * until we are up to where we want to be.
+ *
+ *	A side effect of what we do, just to keep things
+ * simple, is to clear the urgent data pointer.  The principal
+ * caller should be setting the urgent data pointer AFTER calling
+ * us in any case.
+ */
+
+    static void
+netclear()
+{
+#if	0	/* XXX */
+    register char *thisitem, *next;
+    char *good;
+#define	wewant(p)	((nfrontp > p) && ((*p&0xff) == IAC) && \
+				((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+
+    thisitem = netobuf;
+
+    while ((next = nextitem(thisitem)) <= netobuf.send) {
+	thisitem = next;
+    }
+
+    /* Now, thisitem is first before/at boundary. */
+
+    good = netobuf;	/* where the good bytes go */
+
+    while (netoring.add > thisitem) {
+	if (wewant(thisitem)) {
+	    int length;
+
+	    next = thisitem;
+	    do {
+		next = nextitem(next);
+	    } while (wewant(next) && (nfrontp > next));
+	    length = next-thisitem;
+	    memcpy(good, thisitem, length);
+	    good += length;
+	    thisitem = next;
+	} else {
+	    thisitem = nextitem(thisitem);
+	}
+    }
+
+#endif	/* 0 */
+}
+
+/*
+ * These routines add various telnet commands to the data stream.
+ */
+
+    static void
+doflush()
+{
+    NET2ADD(IAC, DO);
+    NETADD(TELOPT_TM);
+    flushline = 1;
+    flushout = 1;
+    (void) ttyflush(1);			/* Flush/drop output */
+    /* do printoption AFTER flush, otherwise the output gets tossed... */
+    printoption("SENT", DO, TELOPT_TM);
+}
+
+    void
+xmitAO()
+{
+    NET2ADD(IAC, AO);
+    printoption("SENT", IAC, AO);
+    if (autoflush) {
+	doflush();
+    }
+}
+
+
+    void
+xmitEL()
+{
+    NET2ADD(IAC, EL);
+    printoption("SENT", IAC, EL);
+}
+
+    void
+xmitEC()
+{
+    NET2ADD(IAC, EC);
+    printoption("SENT", IAC, EC);
+}
+
+
+    int
+dosynch(s)
+     char *s;
+{
+    netclear();			/* clear the path to the network */
+    NETADD(IAC);
+    setneturg();
+    NETADD(DM);
+    printoption("SENT", IAC, DM);
+    return 1;
+}
+
+int want_status_response = 0;
+
+    int
+get_status(s)
+    char *s;
+{
+    unsigned char tmp[16];
+    register unsigned char *cp;
+
+    if (my_want_state_is_dont(TELOPT_STATUS)) {
+	printf("Remote side does not support STATUS option\n");
+	return 0;
+    }
+    cp = tmp;
+
+    *cp++ = IAC;
+    *cp++ = SB;
+    *cp++ = TELOPT_STATUS;
+    *cp++ = TELQUAL_SEND;
+    *cp++ = IAC;
+    *cp++ = SE;
+    if (NETROOM() >= cp - tmp) {
+	ring_supply_data(&netoring, tmp, cp-tmp);
+	printsub('>', tmp+2, cp - tmp - 2);
+    }
+    ++want_status_response;
+    return 1;
+}
+
+    void
+intp()
+{
+    NET2ADD(IAC, IP);
+    printoption("SENT", IAC, IP);
+    flushline = 1;
+    if (autoflush) {
+	doflush();
+    }
+    if (autosynch) {
+	dosynch(NULL);
+    }
+}
+
+    void
+sendbrk()
+{
+    NET2ADD(IAC, BREAK);
+    printoption("SENT", IAC, BREAK);
+    flushline = 1;
+    if (autoflush) {
+	doflush();
+    }
+    if (autosynch) {
+	dosynch(NULL);
+    }
+}
+
+    void
+sendabort()
+{
+    NET2ADD(IAC, ABORT);
+    printoption("SENT", IAC, ABORT);
+    flushline = 1;
+    if (autoflush) {
+	doflush();
+    }
+    if (autosynch) {
+	dosynch(NULL);
+    }
+}
+
+    void
+sendsusp()
+{
+    NET2ADD(IAC, SUSP);
+    printoption("SENT", IAC, SUSP);
+    flushline = 1;
+    if (autoflush) {
+	doflush();
+    }
+    if (autosynch) {
+	dosynch(NULL);
+    }
+}
+
+    void
+sendeof()
+{
+    NET2ADD(IAC, xEOF);
+    printoption("SENT", IAC, xEOF);
+}
+
+    void
+sendayt()
+{
+    NET2ADD(IAC, AYT);
+    printoption("SENT", IAC, AYT);
+}
+
+/*
+ * Send a window size update to the remote system.
+ */
+
+    void
+sendnaws()
+{
+    long rows, cols;
+    unsigned char tmp[16];
+    register unsigned char *cp;
+
+    if (my_state_is_wont(TELOPT_NAWS))
+	return;
+
+#define	PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
+			    if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
+
+    if (TerminalWindowSize(&rows, &cols) == 0) {	/* Failed */
+	return;
+    }
+
+    cp = tmp;
+
+    *cp++ = IAC;
+    *cp++ = SB;
+    *cp++ = TELOPT_NAWS;
+    PUTSHORT(cp, cols);
+    PUTSHORT(cp, rows);
+    *cp++ = IAC;
+    *cp++ = SE;
+    if (NETROOM() >= cp - tmp) {
+	ring_supply_data(&netoring, tmp, cp-tmp);
+	printsub('>', tmp+2, cp - tmp - 2);
+    }
+}
+
+    void
+tel_enter_binary(rw)
+    int rw;
+{
+    if (rw&1)
+	send_do(TELOPT_BINARY, 1);
+    if (rw&2)
+	send_will(TELOPT_BINARY, 1);
+}
+
+    void
+tel_leave_binary(rw)
+    int rw;
+{
+    if (rw&1)
+	send_dont(TELOPT_BINARY, 1);
+    if (rw&2)
+	send_wont(TELOPT_BINARY, 1);
+}
diff --git a/krb5-1-6/src/appl/telnet/telnet/terminal.c b/krb5-1-6/src/appl/telnet/telnet/terminal.c
new file mode 100644
index 000000000..611270373
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/terminal.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)terminal.c	8.1 (Berkeley) 6/6/93 */
+
+#include <arpa/telnet.h>
+#include <sys/types.h>
+
+#include "ring.h"
+
+#include "externs.h"
+#include "types.h"
+
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+Ring		ttyoring, ttyiring;
+unsigned char	ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ];
+
+int termdata;			/* Debugging flag */
+
+#ifdef	USE_TERMIO
+# ifndef VDISCARD
+cc_t termFlushChar;
+# endif
+# ifndef VLNEXT
+cc_t termLiteralNextChar;
+# endif
+# ifndef VSUSP
+cc_t termSuspChar;
+# endif
+# ifndef VWERASE
+cc_t termWerasChar;
+# endif
+# ifndef VREPRINT
+cc_t termRprntChar;
+# endif
+# ifndef VSTART
+cc_t termStartChar;
+# endif
+# ifndef VSTOP
+cc_t termStopChar;
+# endif
+# ifndef VEOL
+cc_t termForw1Char;
+# endif
+# ifndef VEOL2
+cc_t termForw2Char;
+# endif
+# ifndef VSTATUS
+cc_t termAytChar;
+# endif
+#else
+cc_t termForw2Char;
+cc_t termAytChar;
+#endif
+
+/*
+ * initialize the terminal data structures.
+ */
+
+    void
+init_terminal()
+{
+    if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) {
+	exit(1);
+    }
+    if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) {
+	exit(1);
+    }
+    autoflush = TerminalAutoFlush();
+}
+
+
+/*
+ *		Send as much data as possible to the terminal.
+ *
+ *		Return value:
+ *			-1: No useful work done, data waiting to go out.
+ *			 0: No data was waiting, so nothing was done.
+ *			 1: All waiting data was written out.
+ *			 n: All data - n was written out.
+ */
+
+
+    int
+ttyflush(drop)
+    int drop;
+{
+    register int n, n0, n1;
+
+    n0 = ring_full_count(&ttyoring);
+    if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
+	if (drop) {
+	    TerminalFlushOutput();
+	    /* we leave 'n' alone! */
+	} else {
+	    n = TerminalWrite(ttyoring.consume, n);
+	}
+    }
+    if (n > 0) {
+	if (termdata && n) {
+	    Dump('>', ttyoring.consume, n);
+	}
+	/*
+	 * If we wrote everything, and the full count is
+	 * larger than what we wrote, then write the
+	 * rest of the buffer.
+	 */
+	if (n1 == n && n0 > n) {
+		n1 = n0 - n;
+		if (!drop)
+			n1 = TerminalWrite(ttyoring.bottom, n1);
+		n += n1;
+	}
+	ring_consumed(&ttyoring, n);
+    }
+    if (n < 0)
+	return -1;
+    if (n == n0) {
+	if (n0)
+	    return -1;
+	return 0;
+    }
+    return n0 - n + 1;
+}
+
+
+/*
+ * These routines decides on what the mode should be (based on the values
+ * of various global variables).
+ */
+
+
+    int
+getconnmode()
+{
+    extern int linemode;
+    int mode = 0;
+#ifdef	KLUDGELINEMODE
+    extern int kludgelinemode;
+#endif
+
+    if (In3270)
+	return(MODE_FLOW);
+
+    if (my_want_state_is_dont(TELOPT_ECHO))
+	mode |= MODE_ECHO;
+
+    if (localflow)
+	mode |= MODE_FLOW;
+
+    if (my_want_state_is_will(TELOPT_BINARY))
+	mode |= MODE_INBIN;
+
+    if (his_want_state_is_will(TELOPT_BINARY))
+	mode |= MODE_OUTBIN;
+
+#ifdef	KLUDGELINEMODE
+    if (kludgelinemode) {
+	if (my_want_state_is_dont(TELOPT_SGA)) {
+	    mode |= (MODE_TRAPSIG|MODE_EDIT);
+	    if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
+		mode &= ~MODE_ECHO;
+	    }
+	}
+	return(mode);
+    }
+#endif
+    if (my_want_state_is_will(TELOPT_LINEMODE))
+	mode |= linemode;
+    return(mode);
+}
+
+    void
+setconnmode(force)
+    int force;
+{
+#ifdef	ENCRYPTION
+    static int enc_passwd = 0;
+#endif	/* ENCRYPTION */
+    register int newmode;
+
+    newmode = getconnmode()|(force?MODE_FORCE:0);
+
+    TerminalNewMode(newmode);
+
+#ifdef  ENCRYPTION
+    if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
+	if (my_want_state_is_will(TELOPT_ENCRYPT)
+				&& (enc_passwd == 0) && !encrypt_output) {
+	    encrypt_request_start(0, 0);
+	    enc_passwd = 1;
+	}
+    } else {
+	if (enc_passwd) {
+	    encrypt_request_end();
+	    enc_passwd = 0;
+	}
+    }
+#endif	/* ENCRYPTION */
+
+}
+
+
+    void
+setcommandmode()
+{
+    TerminalNewMode(-1);
+}
diff --git a/krb5-1-6/src/appl/telnet/telnet/tmac.doc b/krb5-1-6/src/appl/telnet/telnet/tmac.doc
new file mode 100644
index 000000000..464023fea
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/tmac.doc
@@ -0,0 +1,4102 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)doc	5.8 (Berkeley) 8/5/91
+.\"
+.\" .mdoc-parse - attempt to parse troff request arguments
+.\" This version has had comments stripped; an unstripped version is available.
+.if \n(.g \{\
+.cp 0
+.ftr C CR
+.\}
+.if t \{\
+.\" tmac.mdoc-ditroff
+.ds aD \fI\s10
+.ds aR \f(CO\s10
+.ds cM \f(CB\s10
+.ds dF \fR\s10
+.ds eM \fI\s10
+.ds eR \fC\s10
+.ds eV \fC\s10
+.ds fA \f(CO\s10
+.ds fD \f(CB\s10
+.ds fL \f(CB\s10
+.ds fN \f(CB\s10
+.ds fP \fP\s0
+.ds fS \s0
+.ds fT \f(CO\s10
+.ds Hs \fR\s10
+.ds iC \f(CB\s10
+.ds lI \fC
+.ds lP \fR\|(\|\fP\s10
+.ds lp \fR(\fP\s10
+.ds rP \fR\|)\|\fP\s10
+.ds rp \fR)\fP\s10
+.ds lB \fR\^[\^\fP\s10
+.ds rB \fR\^]\fP\s10
+.ds mL \fB\s10
+.ds nM \f(CB\s10
+.ds nO \fR\s10
+.ds nT \s0
+.ds pA \fC\s10
+.ds Pu \fR{\ .\ ,\ :\ ;\ (\ )\ [\ ]\ \fR}
+.ds rA \fR\s10
+.ds rT \f(CO\s10
+.ds sH \fB\s10
+.ds sP \s0
+.ds sY \fB\s10
+.ds sX \fR\s10
+.ds tF \fR
+.ds tN \s9
+.ds vA \fI\s10
+.ds Vs \fR\s10
+.ds vT \f(CB\s10
+.ds xR \fC\s10
+.tr *\(**
+.nr sI \w\fC,u*5
+.nr Ti \n(sIu
+.nr Pp .5v
+.ds lS \0
+.nr lS \w'\0'u
+.nr dI 6n
+.de pL
+.nr Hm .5i
+.nr Fm .5i
+.nr ll 6.5i
+.ll 6.5i
+.nr lt 6.5i
+.lt 6.5i
+.nr po 1i
+.po 1.i
+.nr dV .5v
+..
+.ds <= \(<=
+.ds >= \(>=
+.ds Lq \&``
+.ds Rq \&''
+.ds ua \(ua
+.ds aa \(aa
+.ds ga \(ga
+.ds sR \&'
+.ds sL \&`
+.ds q \&"
+.ds Pi \(*p
+.ds Ne \(!=
+.ds Le \(<=
+.ds Ge \(>=
+.ds Lt <
+.ds Gt >
+.ds Pm \(+-
+.ds If \(if
+.ds Na \fINaN\fP
+.ds Ba \fR\&|\fP
+.nr gX 0
+.de hK
+.ds hT \\*(dT
+.if !"\\*(cH"Null" \{\
+.       ie !"\\*(gP"Null" .as hT \|(\|\\*(cH\\*(gP\|)
+.       el .as hT \\|(\\|\\*(cH\\|)
+.\}
+.if "\\*(cH"Null" \{\
+.	if !"\\*(gP"Null" .as hT \&\|(\|\\*(gP\|)
+.\}
+.wh 0 hM
+.wh -1.25i fM
+.ie \\n(gX==1 \{\
+.	rm n1
+.	if \\n(.g .br
+.	if !\\n(.g .bp
+.\}
+.el \{\
+.	if \\n(.g .br
+.	if !\\n(.g 'bp
+.\}
+.nr % 1
+.nr gX 0
+.em lM
+..
+.nr fW \w\fC0
+.de sW
+.nr sW \w\fC\\$1
+.ie \\n(sW>=\\n(fW \{\
+.       ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+.       el .nr sW \\n(sW/\\n(fW
+.\}
+.el \{\
+.	ie \\n(sW>0 .nr sW 1
+.	el .nr sW 0
+.\}
+..
+.de aW
+.nr sW \w\fC\\*(A\\$1
+.ie \\n(sW>=\\n(fW \{\
+.       ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+.       el .nr sW \\n(sW/\\n(fW
+.\}
+.el \{\
+.	ie \\n(sW>0 .nr sW 1
+.	el .nr sW 0
+.\}
+..
+.de Ql
+.if \\n(aC==0  \{\
+.	ds mN Ql
+.       ds A1 \\$1
+.       ds A2 \\$2
+.       ds A3 \\$3
+.       ds A4 \\$4
+.       ds A5 \\$5
+.       ds A6 \\$6
+.       ds A7 \\$7
+.       ds A8 \\$8
+. 	nr fV \\n(.$
+. 	fV
+.\}
+.nr aP \\n(aP+1
+.aW \\n(aP
+.nr aP \\n(aP-1
+.if \\n(sW>2 .Li
+.if \\n(sW<=2 \{\
+.	if (\\n(aP>0) \{\
+.		ds A\\n(aP Li
+.		nr aP \\n(aP -1
+.	\}		
+.	if (\\n(aP==0) \{\
+.		rm C0 C1 C2 C3 C4 C5 C6 C7 C8 C9
+.		rm S1 S2 S3 S4 S5 S6 S7 S8 S9
+.		rn A8 A9
+.		rn A7 A8
+.		rn A6 A7
+.		rn A5 A6
+.		rn A4 A5
+.		rn A3 A4
+.		rn A2 A3
+.		rn A1 A2
+.		ds A1 Li
+.	 	nr fV \\n(aC+1
+.		nr aC 0
+.		fV
+.	\}
+.	ds qL \&\\*(sL
+.	ds qR \&\\*(sR
+.	En
+.\}
+..
+.de Sh
+.nr nS 0
+.nr sE 0
+.nr iS 0
+'ad
+.ie "\\$1"NAME" \{\
+.       hK
+'       in 0
+.\}
+.el \{\
+.       nr nS 0
+.       nr nA 0
+.       nr nF 0
+.       nr nT 0
+.       nr nY 0
+.       nr oT 0
+.       if "\\$1"SYNOPSIS" \{\
+.		na
+.		nr nS 1
+.	\}
+.       if "\\$1"DESCRIPTION" \{\
+.		nr fY 0
+.		nr fZ 0
+.		nr fB 0
+.		nr Fb 0
+.		ds Fb
+.	\}
+.       if "\\$1"SEE" \{\
+.               nr nA 1
+.               na
+.       \}
+.       if "\\$1"FILES" .nr nF 1
+.       if "\\$1"STANDARDS" .nr nT 1
+.       if "\\$1"AUTHORS" .nr nY 1
+.	if "\\$1"SEE" .nr sE 1
+.       in 0
+.       nr aN 0
+.\}
+.pL
+'sp
+.ns
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.if !\\n(cR .ne 3
+'fi
+\&\\*(sH\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\s0\&
+.in \\n(.iu+\\n(Tiu
+.ns
+..
+.\}
+.if n \{\
+.\" tmac.mdoc-nroff
+.ds aD \fI
+.ds aR \fI
+.ds cM \fB
+.ds dF \fR
+.ds eM \fI
+.ds eR \fR
+.ds eV \fR
+.ds fA \fI
+.ds fD \fB
+.ds fL \fB
+.ds fN \fB
+.ds fP \fP
+.ds fS
+.ds fT \fI
+.ds Hs \fR
+.ds iC \fB
+.ds lI \fR
+.ds lP \fR\|(\fP
+.ds rP \fR\|)\fP
+.ds lp \fR\|(\fP
+.ds rp \fR\|)\fP
+.ds lB \fR\|[\|\fP
+.ds rB \fR\|]\fP
+.ds mL \fB
+.ds nM \fB
+.ds nO \fR
+.ds pA \fI
+.ds Pu {\ .\ ,\ ;\ :\ (\ )\ [\ ]}
+.ds rA \fR
+.ds rT \fI
+.ds sH \fB
+.ds sP
+.ds sY \fB
+.ds sX \fI
+.ds tF \fR
+.ds tN
+.ds vA \fI
+.ds Vs \fR
+.ds vT \fB
+.ds xR \fR
+.nr sI .5i
+.nr Ti .5i
+.nr cR 1
+.nr Pp 1v
+.ds lS \0\0
+.nr lS \w'\0\0'u
+.nr dI 6n
+.de pL
+.ie \\n(cR .nr Hm 0
+.el .nr Hm .5i
+.nr Fm .5i
+.nr ll 78n
+.ll 78n
+.nr lt 78n
+.lt 78n
+.nr po 0i
+.po 0i
+.nr dV 1v
+.ad l
+.na
+..
+.ds <= \&<\&=
+.ds >= \&>\&=
+.ds Rq ''
+.ds Lq ``
+.ds ua ^
+.ds aa \'
+.ds ga \`
+.ds sL `
+.ds sR '
+.ds q \&"
+.ds Pi pi
+.ds Ne !=
+.ds Le <=
+.ds Ge >=
+.ds Lt <
+.ds Gt >
+.ds Pm +-
+.ds If infinity
+.ds Na \fINaN\fP
+.ds Ba \fR\&|\fP
+.de hK
+.nr % 1
+.ds hT \\*(dT
+.if !"\\*(cH"Null" \{\
+.	ie !"\\*(gP"Null" .as hT \|(\|\\*(cH\\*(gP\|)
+.	el .as hT \\|(\\|\\*(cH\\|)
+.\}
+.if "\\*(cH"Null" .if !"\\*(gP"Null" .as hT \&\|(\|\\*(gP\|)
+.ie \\n(cR \{\
+.	hM
+.	wh -1v fM
+.\}
+.el \{\
+.	wh 0 hM
+.	wh -1.167i fM
+.\}
+.if \\n(nl==0:\\n(nl==-1 'bp
+.em lM
+..
+.nr fW \w'0'
+.de sW
+.nr sW \w\\$1
+.ie \\n(sW>=\\n(fW \{\
+.       ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+.       el .nr sW \\n(sW/\\n(fW
+.\}
+.el .nr sW 0
+..
+.de aW
+.nr sW \w\\*(A\\$1
+.ie \\n(sW>=\\n(fW \{\
+.       ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+.       el .nr sW \\n(sW/\\n(fW
+.\}
+.el .nr sW 0
+..
+.de Ql
+.if \\n(aC==0  \{\
+.	ds mN Ql
+.	ds A1 \\$1
+.	ds A2 \\$2
+.	ds A3 \\$3
+.	ds A4 \\$4
+.	ds A5 \\$5
+.	ds A6 \\$6
+.	ds A7 \\$7
+.	ds A8 \\$8
+.	ds A9 \\$9
+.	nr fV \\n(.$
+. 	fV
+.\}
+.ds qL \&\\*(sL
+.ds qR \&\\*(sR
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Sh
+.nr nS 0
+.nr sE 0
+.nr iS 0
+.ie "\\$1"NAME" \{\
+.       hK
+'       in 0
+.\}
+.el \{\
+.       nr nS 0
+.       nr nA 0
+.       nr nF 0
+.       nr nT 0
+.       nr nY 0
+.       nr aN 0
+.       nr oT 0
+.       if "\\$1"SEE" .nr nA 1
+.       if "\\$1"FILES" .nr nF 1
+.       if "\\$1"STANDARDS" .nr nT 1
+.       if "\\$1"SYNOPSIS" .nr nS 1
+.       if "\\$1"DESCRIPTION" \{\
+.               rr fB
+.               rr Fb
+.               ds Fb
+.               nr fY 0
+.               nr fZ 0
+.       \}
+.	if "\\$1"AUTHORS" .nr nY 1
+.       in 0
+.\}
+.pL
+'sp
+.ns
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.if !\\n(cR .ne 3
+'fi
+\&\\*(sH\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\s0\&
+.in \\n(.iu+\\n(Tiu
+.if "\\$1"SEE" .nr sE 1
+.ns
+..
+.\}
+.\"     @(#)doc-common	5.7 (Berkeley) 8/5/91
+.nr %A 1
+.nr %J 1
+.nr %N 1
+.nr %O 1
+.nr %R 1
+.nr %T 1
+.nr %V 1
+.nr Ad 12n
+.nr Ac 3
+.nr Ao 12n
+.nr Ap 2
+.nr An 12n
+.nr Aq 12n
+.nr Ar 12n
+.nr Bc 3
+.nr Bl 1
+.nr Bo 12n
+.nr Bq 12n
+.nr Bx 12n
+.nr Cd 12n
+.nr Cm 10n
+.nr Co 15n
+.nr Cx 20n
+.nr Dc 3
+.nr Do 10n
+.nr Dq 12n
+.nr Ds 6n
+.nr Dq 12n
+.nr Dv 12n
+.nr tI \n(Dsu
+.nr Ec 3
+.nr El 1
+.nr Eo 12n
+.nr Eq 12n
+.nr Em 10n
+.nr Er 12n
+.nr Ev 15n
+.nr Ex 10n
+.nr Fa 12n
+.nr Fl 10n
+.nr Fc 3
+.nr Fo 16n
+.nr Fn 16n
+.nr Hl 1
+.nr I1 6n
+.nr I2 12n
+.nr I3 18n
+.nr Ic 10n
+.nr Li 16n
+.nr Ms 6n
+.nr Nm 10n
+.nr No 12n
+.nr Ns 2
+.nr Oo 10n
+.nr Oc 3
+.nr Op 14n
+.nr Pa 32n
+.nr Pf 12n
+.nr Pc 3
+.nr Po 12n
+.nr Pq 12n
+.nr Ql 16n
+.nr Qc 3
+.nr Qo 12n
+.nr Qq 12n
+.nr Sc 3
+.nr So 12n
+.nr Sq 12n
+.nr Sy 6n
+.nr Sx 16n
+.nr Ra 1
+.nr Rj 1
+.nr Rn 1
+.nr Ro 1
+.nr Rr 1
+.nr Rt 1
+.nr Rv 1
+.nr Tn 10n
+.nr Ta 1
+.nr Tv 1
+.nr Tx 22n
+.nr Ux 10n
+.nr Va 12n
+.nr Xc 3
+.nr Xo 1
+.nr Xr 10n
+.ds sV \& \&
+.ds hV \&\ \&
+.ds iV \& \&
+.ds tV \&\\t\&
+.nr z. 3
+.nr z, 3
+.nr z: 3
+.nr z; 3
+.nr z( 4
+.nr z) 3
+.nr z[ 4
+.nr z] 3
+.ds z( z)
+.ds z[ z]
+.ds z< z>
+.nr z0 0
+.nr z1 0
+.nr z2 0
+.nr z3 0
+.nr z4 0
+.nr z5 0
+.nr z6 0
+.nr z7 0
+.nr z8 0
+.nr z9 0
+.nr z# 0
+.de Dt
+.ds dT UNTITLED
+.ds vT LOCAL
+.ds cH Null
+.if !"\\$1"" .ds dT \\$1
+.if !"\\$2"" \{\
+.	ds cH \\$2
+.		if \\$2>=1 .if \\$2<=8 \{\
+.			ds vT NetBSD Reference Manual
+.			if \\$2>1 .if \\$2<6 .ds vT NetBSD Programmer's Manual
+.			if "\\$2"8" .ds vT NetBSD System Manager's Manual
+.			nr sN \\$2
+.		\}
+.		if "\\$2"unass"  .ds vT DRAFT
+.		if "\\$2"draft"  .ds vT DRAFT
+.		if "\\$2"paper"  .ds vT UNTITLED
+.\}
+.if !"\\$3"" \{\
+.	if "\\$3"USD"   .ds vT NetBSD User's Supplementary Documents
+.	if "\\$3"PS1"   .ds vT NetBSD Programmers's Supplementary Documents
+.	if "\\$3"AMD"   .ds vT NetBSD Ancestral Manual Documents
+.	if "\\$3"SMM"   .ds vT NetBSD System Manager's Manual
+.	if "\\$3"URM"   .ds vT NetBSD Reference Manual
+.	if "\\$3"PRM"   .ds vT NetBSD Programmers's Manual
+.	if "\\$3"IND"   .ds vT NetBSD Manual Master Index
+.	if "\\$3"LOCAL" .ds vT NetBSD Local Manual
+.	if "\\$3"tahoe" .as vT \ (Tahoe Architecture)
+.	if "\\$3"vax" .as vT \ (VAX Architecture)
+.	if "\\$3"hp300" .as vT \ (HP300 Architecture)
+.	if "\\*(vT"LOCAL" .ds vT \\$3
+.\}
+..
+.de Os
+.ds oS Null
+.if "\\$1"" \{\
+.	ds oS BSD Experimental
+.\}
+.if "\\$2"" \{\
+.	ds aa Non-Null
+.\}
+.if "\\$1"ATT"   \{\
+.	ds oS AT&T
+.	if "\\$2""    .as oS \0UNIX
+.	if "\\$2"7th" .as oS \07th Edition
+.	if "\\$2"7"   .as oS \07th Edition
+.	if "\\$2"III" .as oS \0System III
+.	if "\\$2"3"   .as oS \0System III
+.	if "\\$2"V"   .as oS \0System V
+.	if "\\$2"V.2" .as oS \0System V Release 2
+.	if "\\$2"V.3" .as oS \0System V Release 3
+.	if "\\$2"V.4" .as oS \0System V Release 4
+.\}
+.if "\\$1"BSD" \{\
+.	if "\\$2"3"    .ds oS 3rd Berkeley Distribution
+.	if "\\$2"4"    .ds oS 4th Berkeley Distribution
+.	if "\\$2"4.1"  .ds oS 4.1 Berkeley Distribution
+.	if "\\$2"4.2"  .ds oS 4.2 Berkeley Distribution
+.	if "\\$2"4.3"  .ds oS 4.3 Berkeley Distribution
+.	if "\\$2"4.3T" .ds oS 4.3-Tahoe Berkeley Distribution
+.	if "\\$2"4.3R" .ds oS 4.3-Reno Berkeley Distribution
+.	if "\\$2"4.3t" .ds oS 4.3-Tahoe Berkeley Distribution
+.	if "\\$2"4.3r" .ds oS 4.3-Reno Berkeley Distribution
+.	if "\\$2"4.4"  .ds oS BSD Experimental
+.\}
+.if "\\$1"NetBSD" \{\
+.	ds oS NetBSD
+.	if "\\$2"0.8"  .as oS \00.8
+.	if "\\$2"0.8a" .as oS \00.8a
+.	if "\\$2"0.9"  .as oS \00.9
+.	if "\\$2"0.9a" .as oS \00.9a Experimental
+.	if "\\$2"1.0"  .as oS \01.0 Experimental
+.\}
+.if "\\*(oS"Null" .ds oS \0\\$1
+.if "\\*(aa"Non-Null" .as oS \0\\$2
+.rm aa
+..
+.de Dd
+.if !"\\*(dD"" .nr gX 1
+.ie \\n(.$>0 \{\
+.	ie \\n(.$==3 \{\
+.		ds dD \\$1 \\$2 \\$3
+.	\}
+.	el \{\
+.		if "\\n(mo"1"  .ds dD January
+.		if "\\n(mo"2"  .ds dD February
+.		if "\\n(mo"3"  .ds dD March
+.		if "\\n(mo"4"  .ds dD April
+.		if "\\n(mo"5"  .ds dD May
+.		if "\\n(mo"6"  .ds dD June
+.		if "\\n(mo"7"  .ds dD July
+.		if "\\n(mo"8"  .ds dD August
+.		if "\\n(mo"9"  .ds dD September
+.		if "\\n(mo"10" .ds dD October
+.		if "\\n(mo"11" .ds dD November
+.		if "\\n(mo"12" .ds dD December
+.		as dD \&\ \\n(dy, 19\\n(yr
+.	\}
+.\}
+.el \{\
+.	ds dD Epoch
+.\}
+..
+.de hM
+.ev 1
+.pL
+.if !\\n(cR 'sp \\n(Hmu
+.tl @\\*(Hs\\*(hT\fP@\\*(Vs\\*(vT\fP@\\*(Hs\\*(hT\fP@
+'sp \\n(Hmu
+.ev
+..
+.de fM
+.ie \\n(cR 'br
+.el \{\
+.	ev 1
+.	pL
+.	if !\\n(cR \{\
+'		sp \\n(Fmu
+.		tl @\\*(Hs\\*(oS\fP@\\*(Vs\\*(dD\fP@%@
+'		bp
+.	\}
+.	ev
+.\}
+..
+.de lM
+.fl
+.if \\n(cR \{\
+'	sp
+.	tl @\\*(Hs\\*(oS\fP@\\*(Vs\\*(dD\fP@%@
+.       pl \\n(nlu
+.\}
+..
+.de Pp
+.sp \\n(Ppu
+.ne 2
+.ns
+..
+.de Lp
+.Pp
+..
+.de LP
+.tm Not a \-mdoc command: .LP
+..
+.de PP
+.tm Not a \-mdoc command: .PP
+..
+.de pp
+.tm Not a \-mdoc command: .pp
+..
+.de Nd
+\&\-\& \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Ss
+.sp
+.ne 2
+.ti -.25i
+\&\\*(sH\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\s0
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.if !\\n(cR .ne 2
+.br
+..
+.de Rd
+.tm MDOC REGISTER DUMP
+.tm Db==\\n(Db register DEBUG MODE
+.tm L[0-9] registers - stack of list types
+.tm L0==\\n(L0
+.tm L1==\\n(L1
+.tm L2==\\n(L2
+.tm L3==\\n(L3
+.tm L4==\\n(L4
+.tm L5==\\n(L5
+.tm L6==\\n(L6
+.tm L7==\\n(L7
+.tm L8==\\n(L8
+.tm L9==\\n(L9
+.tm O[0-9] registers - stack of indent
+.tm O0==\\n(O0
+.tm O1==\\n(O1
+.tm O2==\\n(O2
+.tm O3==\\n(O3
+.tm O4==\\n(O4
+.tm O5==\\n(O5
+.tm O6==\\n(O6
+.tm O7==\\n(O7
+.tm O8==\\n(O8
+.tm O9==\\n(O9
+.tm aC==\\n(aC register argument counter (aV/fV)
+.tm aJ==\\n(aJ register (for vR)
+.tm aN==\\n(aN register
+.tm aP==\\n(aP register argument pointer (aV)
+.tm aT==\\n(aT register argument type
+.tm aa==\\n(aa local register
+.tm bK==\\n(bK register - Book Name flag
+.tm cF==\\n(cF register save current font
+.tm cI==\\n(cI register - column indent width
+.tm cZ==\\n(cZ register save current font size
+.tm dK==\\n(dK register - Date flag
+.tm d[0-9] registers - display-type stack
+.tm d0==\\n(d0
+.tm d1==\\n(d1
+.tm d2==\\n(d2
+.tm d3==\\n(d3
+.tm d4==\\n(d4
+.tm d5==\\n(d5
+.tm d6==\\n(d6
+.tm d7==\\n(d7
+.tm d8==\\n(d8
+.tm d9==\\n(d9
+.tm dZ==\\n(dZ register diversion count
+.tm fD==\\n(fD register subroutine test (in synopsis only)
+.tm fV==\\n(fV register argument counter (must set to \\n(.$ prior to
+.tm fY==\\n(fY register - dick with old style function declarations (fortran)
+.tm fZ==\\n(fZ register also subroutine count (in synopsis only)
+.tm h[0-9] register horizontal tag stack (continuous if 1, break if
+.tm h0==\\n(h0
+.tm h1==\\n(h1
+.tm h2==\\n(h2
+.tm h3==\\n(h3
+.tm h4==\\n(h4
+.tm h5==\\n(h5
+.tm h6==\\n(h6
+.tm h7==\\n(h7
+.tm h8==\\n(h8
+.tm h9==\\n(h9
+.tm iD==\\n(iD local register
+.tm iI==\\n(iI local register (indent for inline debug mode)
+.tm iN==\\n(iN register DEBUG MODE (inline if 1, to stderr if
+.tm iS==\\n(iS register - indent second command line in a synopsis
+.tm jK==\\n(jK register - [reference] Journal Name flag
+.tm jM==\\n(jM local register
+.tm jN==\\n(jN local register
+.tm lC==\\n(lC register - list type stack counter
+.tm lK==\\n(lK register count of lines read from input file
+.tm nK==\\n(nK register - [reference] issue number flag
+.tm nU==\\n(nU register count
+.tm oK==\\n(oK register - [reference] optional information flag
+.tm oM==\\n(oM register (extension possible)
+.tm o[0-9] register offset stack (nested tags)
+.tm o0==\\n(o0
+.tm o1==\\n(o1
+.tm o2==\\n(o2
+.tm o3==\\n(o3
+.tm o4==\\n(o4
+.tm o5==\\n(o5
+.tm o6==\\n(o6
+.tm o7==\\n(o7
+.tm o8==\\n(o8
+.tm o9==\\n(o9
+.tm oM==\\n(oM register open ended line flag
+.tm pK==\\n(pK register - [reference] page number flag
+.tm qK==\\n(qK register - Corporate or Foreign Author flag
+.tm rK==\\n(rK register - [reference] report flag
+.tm rS==\\n(rS register - Reference Start flag
+.tm sM==\\n(sM register - default is one (space mode on)
+.tm tK==\\n(tK register - reference title flag
+.tm tP==\\n(tP register tag flag (for diversions)
+.tm tX==\\n(tX register (initial class)
+.tm tY==\\n(tY register (next possible lC value)
+.tm t[0-9] register tag string stack (nested tags)
+.tm t0==\\n(t0
+.tm t1==\\n(t1
+.tm t2==\\n(t2
+.tm t3==\\n(t3
+.tm t4==\\n(t4
+.tm t5==\\n(t5
+.tm t6==\\n(t6
+.tm t7==\\n(t7
+.tm t8==\\n(t8
+.tm t9==\\n(t9
+.tm uK==\\n(uK register - reference author(s) counter
+.tm vK==\\n(vK register - reference volume flag
+.tm v[0-9] register vertical tag break stack
+.tm v0==\\n(v0
+.tm v1==\\n(v1
+.tm v2==\\n(v2
+.tm v3==\\n(v3
+.tm v4==\\n(v4
+.tm v5==\\n(v5
+.tm v6==\\n(v6
+.tm v7==\\n(v7
+.tm v8==\\n(v8
+.tm v9==\\n(v9
+.tm w[0-9] register tag stack (nested tags)
+.tm w0==\\n(w0
+.tm w1==\\n(w1
+.tm w2==\\n(w2
+.tm w3==\\n(w3
+.tm w4==\\n(w4
+.tm w5==\\n(w5
+.tm w6==\\n(w6
+.tm w7==\\n(w7
+.tm w8==\\n(w8
+.tm w9==\\n(w9
+.tm xX==\\n(xX local register
+.tm END OF REGISTER DUMP
+..
+.\"     @(#)doc-syms	5.6 (Berkeley) 8/5/91
+.de Ux
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ds aa \&\f\\n(cF\s\\n(cZ
+.as b1 \&\\*(tNUNIX\\*(aa
+.rm aa
+.if \\n(aC==0 \{\
+.       if \\n(.$>0 .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.ie \\n(aC>\\n(aP \{\
+.       nr aP \\n(aP+1
+.       ie \\n(C\\n(aP==1 \{\
+.               \\*(A\\n(aP
+.       \}
+.       el .nR
+.\}
+.el .aZ
+..
+.de Bx
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ds aa \&\f\\n(cF\s\\n(cZ
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 \&\\*(tNBSD\\*(aa \\*(tNUNIX\\*(aa
+.       el .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.if "\\$1"-alpha" \{\
+\¤tly in alpha test.
+.	aY
+.\}
+.if "\\$1"-beta" \{\
+\¤tly in beta test.
+.	aY
+.\}
+.if "\\$1"-devel" \{\
+\¤tly under development.
+.	aY
+.\}
+.if \\n(aC>\\n(aP \{\
+.       nr aP \\n(aP+1
+.	ie \\n(C\\n(aP==2 \{\
+.		as b1 \&\\*(A\\n(aP\&\\*(tNBSD\\*(aa
+.		ie \\n(aC>\\n(aP \{\
+.			nr jj \\n(aP+1
+.			ie \\n(C\\n(jj==2 \{\
+.				if "\\*(A\\n(jj"Reno" \{\
+.					nr aP \\n(aP+1
+.					as b1 \&\-\\*(A\\n(jj
+.				\}
+.				if "\\*(A\\n(jj"reno" \{\
+.					nr aP \\n(aP+1
+.					as b1 \&\-Reno
+.				\}
+.				if "\\*(A\\n(jj"Tahoe" \{\
+.					nr aP \\n(aP+1
+.					as b1 \&\-\\*(A\\n(jj
+.				\}
+.				if "\\*(A\\n(jj"tahoe" \{\
+.					nr aP \\n(aP+1
+.					as b1 \&\-Tahoe
+.				\}
+.				ie \\n(aC>\\n(aP \{\
+.					nr aP \\n(aP+1
+.					nR
+.				\}
+.				el .aZ
+.			\}
+.			el \{\
+.				nr aP \\n(aP+1
+.				nR
+.			\}
+.			rr jj
+.		\}
+.		el .aZ
+.	\}
+.	el \{\
+.	       as b1 \&\\*(tNBSD\\*(aa U\\*(tNNIX\\*(aa
+.	       nR
+.	\}
+.\}
+..
+.de Ud
+\¤tly under development.
+..
+.de Nx
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ds aa \&\f\\n(cF\s\\n(cZ
+.if \\n(.$==2 \{\
+.	if "\\$1"0.8"  \&\\*(tNNetBSD\\*(aa 0.8\\*(aa\\$2
+.	if "\\$1"0.8a"  \&\\*(tNNetBSD\\*(aa 0.8a\\*(aa\\$2
+.	if "\\$1"0.9"  \&\\*(tNNetBSD\\*(aa 0.9\\*(aa\\$2
+.	if "\\$1"0.9a"  \&\\*(tNNetBSD\\*(aa 0.9a\\*(aa\\$2
+.	if "\\$1"1.0"  \&\\*(tNNetBSD\\*(aa 1.0\\*(aa\\$2
+.	if "\\$1"1.0a"  \&\\*(tNNetBSD\\*(aa 1.0a\\*(aa\\$2
+.\}
+.if \\n(.$==1 \{\
+.	if "\\$1"0.8"  \&\\*(tNNetBSD\\*(aa 0.8\\*(aa
+.	if "\\$1"0.8a"  \&\\*(tNNetBSD\\*(aa 0.8a\\*(aa
+.	if "\\$1"0.9"  \&\\*(tNNetBSD\\*(aa 0.9\\*(aa
+.	if "\\$1"0.9a"  \&\\*(tNNetBSD\\*(aa 0.9a\\*(aa
+.	if "\\$1"1.0"  \&\\*(tNNetBSD\\*(aa 1.0\\*(aa
+.	if "\\$1"1.0a"  \&\\*(tNNetBSD\\*(aa 1.0a\\*(aa
+.\}
+..
+.de At
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ds aa \&\f\\n(cF\s\\n(cZ
+.if \\n(.$==2 \{\
+.	if "\\$1"32v" \&Version 32V \\*(tNAT&T UNIX\\*(aa\\$2
+.	if "\\$1"v6"  \&Version 6 \\*(tNAT&T UNIX\\*(aa\\$2
+.	if "\\$1"v7"  \&Version 7 \\*(tNAT&T UNIX\\*(aa\\$2
+.	if "\\$1"V"  \&\\*(tNAT&T\\*(aa System V \\*(tNUNIX\\*(aa\\$2
+.	if "\\$1"V.1"  \&\\*(tNAT&T\\*(aa System V.1 \\*(tNUNIX\\*(aa\\$2
+.	if "\\$1"V.2"  \&\\*(tNAT&T\\*(aa System V.2 \\*(tNUNIX\\*(aa\\$2
+.	if "\\$1"V.4"  \&\\*(tNAT&T\\*(aa System V.4 \\*(tNUNIX\\*(aa\\$2
+.\}
+.if \\n(.$==1 \{\
+.	if "\\$1"32v" \&Version 32V \\*(tNAT&T UNIX\\*(aa
+.	if "\\$1"v6"  \&Version 6 \\*(tNAT&T UNIX\\*(aa
+.	if "\\$1"v7"  \&Version 7 \\*(tNAT&T UNIX\\*(aa
+.	if "\\$1"V"  \&\\*(tNAT&T\\*(aa System V \\*(tNUNIX\\*(aa
+.	if "\\$1"V.1"  \&\\*(tNAT&T\\*(aa System V.1 \\*(tNUNIX\\*(aa
+.	if "\\$1"V.2"  \&\\*(tNAT&T\\*(aa System V.2 \\*(tNUNIX\\*(aa
+.	if "\\$1"V.4"  \&\\*(tNAT&T\\*(aa System V.4 \\*(tNUNIX\\*(aa
+.\}
+..
+.de Bt
+\&is currently in beta test.
+..
+.ds Px \\*(tNPOSIX
+.ds Ai \\*(tNANSI
+.de St
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 \{\
+.tm Usage: .St [-p1003.1-90 | -p1003.2 | -ansiC-89 | -iso ] \\*(Pu ... (#\\n(.c)
+.	\}
+.	el \{\
+.		ds mN St
+.		nr aP 0
+.		ds A1 \\$1
+.		ds A2 \\$2
+.		ds A3 \\$3
+.		ds A4 \\$4
+.		ds A5 \\$5
+.		ds A6 \\$6
+.		ds A7 \\$7
+.		ds A8 \\$8
+.		ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr cF \\n(.f
+.	nr cZ \\n(.s
+.	ds aa \&\f\\n(cF\s\\n(cZ
+.	nr aP \\n(aP+1
+.       if "\\*(A\\n(aP"-p1003.1-90" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.1-1990\\*(sV
+.			as b1 (``\\*(tN\\*(Px\\*(aa'')
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.1-1990\\*(sV
+.			as b1 (``\\*(tN\\*(Px\\*(aa'')
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-p1003.1-88" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.1-1988\\*(sV
+.			as b1 (``\\*(tN\\*(Px\\*(aa'')
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.1-1988\\*(sV
+.			as b1 (``\\*(tN\\*(Px\\*(aa'')
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-p1003.1" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.1\\*(sV
+.			as b1 (``\\*(tN\\*(Px\\*(aa'')
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.1\\*(sV
+.			as b1 (``\\*(tN\\*(Px\\*(aa'')
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-p1003.2-92" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.2-1992\\*(sV
+.			as b1 (``\\*(tN\\*(Px.2\\*(aa'')
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.2-1992\\*(sV
+.			as b1 (``\\*(tN\\*(Px.2\\*(aa'')
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-p1003.2" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.2\\*(sV
+.			as b1 (``\\*(tN\\*(Px.2\\*(aa'')
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa1003.2\\*(sV
+.			as b1 (``\\*(tN\\*(Px.2\\*(aa'')
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-ansiC" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNANSI \\*(aaX3.159-1989\\*(sV
+.			as b1 (``\\*(tNANSI C\\*(aa'')
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNANSI \\*(aaX3.159-1989\\*(sV
+.			as b1 (``\\*(tNANSI C\\*(aa'')
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-ansiC-89" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNANSI \\*(aaX3.159-1989\\*(sV
+.			as b1 (``\\*(tNANSI C\\*(aa'')
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNANSI \\*(aaX3.159-1989\\*(sV
+.			as b1 (``\\*(tNANSI C\\*(aa'')
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-ieee754" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa754-1985
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNIEEE Std\\*(aa754-1985
+.		\}
+.       \}
+.       if "\\*(A\\n(aP"-iso8802-3" \{\
+.		ie \\n(sT==1 \{\
+.			ds b1 \&\\*(tNISO \\*(aa8802-3: 1989\\*(sV
+.		\}
+.		el \{\
+.			ds b1 \&\\*(tNISO \\*(aa8802-3: 1989\\*(sV
+.		\}
+.       \}
+.	ie \\n(aC>\\n(aP \{\
+.		nr aP \\n(aP+1
+.		nR
+.	\}
+.	el .aZ
+.\}
+..
+.nr Db 0
+.de Db
+.ie \\n(.$==0 \{\
+.	ie \\n(Db==0 \{\
+.tm DEBUGGING ON
+.		nr Db 1
+.	\}
+.	el \{\
+.tm DEBUGGING OFF
+.		nr Db 0
+.	\}
+.\}
+.el \{\
+.	if "\\$1"on" \{\
+.tm DEBUGGING ON
+.		nr Db 1
+.	\}
+.	if "\\$1"off" \{\
+.tm DEBUGGING OFF
+.		nr Db 0
+.	\}
+.\}
+..
+.de aV
+.nr aC \\n(aC+1
+.ie "\\$1"|" \{\
+.	if "\\*(mN"Op" .ds A\\n(aC \fR\\$1\fP
+.	if "\\*(mN"Ar" .ds A\\n(aC \fR\\$1\fP
+.	if "\\*(mN"Fl" .ds A\\n(aC \fR\\$1\fP
+.	if "\\*(mN"Cm" .ds A\\n(aC \fR\\$1\fP
+.	if "\\*(mN"It" .ds A\\n(aC \fR\\$1\fP
+.\}
+.el .ds A\\n(aC \\$1
+.aU \\n(aC
+.nr C\\n(aC \\n(aT
+.s\\n(aT
+.if \\n(Db \{\
+.	if \\n(aT==1 .ds yU Executable
+.	if \\n(aT==2 .ds yU String
+.	if \\n(aT==3 .ds yU Closing Punctuation or suffix
+.	if \\n(aT==4 .ds yU Opening Punctuation or prefix
+.	if \\n(iN==1 \{\
+.		br
+.		nr iI \\n(.iu
+.		in -\\n(iIu
+.		if \\n(aC==1 \{\
+\&\fBDEBUG(argv) MACRO:\fP `.\\*(mN'  \fBLine #:\fP \\n(.c
+.		\}
+\&\t\fBArgc:\fP \\n(aC  \fBArgv:\fP `\\*(A\\n(aC'  \fBLength:\fP \\n(sW
+\&\t\fBSpace:\fP `\\*(S\\n(aC'  \fBClass:\fP \\*(yU
+.	\}
+.	if \\n(iN==0 \{\
+.		if \\n(aC==1 \{\
+.			tm DEBUG(argv) MACRO: `.\\*(mN'  Line #: \\n(.c
+.		\}
+.		tm \tArgc: \\n(aC  Argv: `\\*(A\\n(aC'  Length: \\n(sW
+.		tm \tSpace: `\\*(S\\n(aC'  Class: \\*(yU
+.	\}
+.\}
+.ie \\n(.$==1 \{\
+.	nr aP 0
+.	ie \\n(dZ==1 \{\
+.		if \\n(oM>1 .as b1 \\*(S0
+.	\}
+.	el \{\
+.		if \\n(oM>0 \{\
+.			if \\n(fC==0 .as b1 \\*(S0
+.		\}
+.	\}
+.	ds S0 \\*(S\\n(aC
+.	if \\n(Db \{\
+.		if \\n(iN==1 \{\
+\&MACRO REQUEST: \t.\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+.			br
+.			in \\n(iIu
+.		\}
+.		if \\n(iN==0 \{\
+.tm \tMACRO REQUEST: .\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+.		\}
+.	\}
+.\}
+.el .aV \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de fV
+.nr aC \\n(aC+1
+.if "\\*(A\\n(aC"|" \{\
+.	if "\\*(mN"Op" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+.	if "\\*(mN"Ar" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+.	if "\\*(mN"Fl" .ds A\\n(aC \fR\&\\*(A\\n(aC\fP
+.	if "\\*(mN"Cm" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+.	if "\\*(mN"It" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+.\}
+.aU \\n(aC
+.nr C\\n(aC \\n(aT
+.s\\n(aT
+.if \\n(Db \{\
+.	if \\n(aT==1 .ds yU Executable
+.	if \\n(aT==2 .ds yU String
+.	if \\n(aT==3 .ds yU Closing Punctuation or suffix
+.	if \\n(aT==4 .ds yU Opening Punctuation or prefix
+.	if \\n(iN==1 \{\
+.		br
+.		nr iI \\n(.iu
+.		in -\\n(iIu
+.		if \\n(aC==1 \{\
+\&\fBDEBUG(fargv) MACRO:\fP `.\\*(mN'  \fBLine #:\fP \\n(.c
+.		\}
+\&\t\fBArgc:\fP \\n(aC  \fBArgv:\fP `\\*(A\\n(aC'  \fBLength:\fP \\n(sW
+\&\t\fBSpace:\fP `\\*(S\\n(aC'  \fBClass:\fP \\*(yU
+.	\}
+.	if \\n(iN==0 \{\
+.		if \\n(aC==1 \{\
+.			tm DEBUG(fargv) MACRO: `.\\*(mN'  Line #: \\n(.c
+.		\}
+.		tm \tArgc: \\n(aC  Argv: `\\*(A\\n(aC'  Length: \\n(sW
+.		tm \tSpace: `\\*(S\\n(aC'  Class: \\*(yU
+.	\}
+.\}
+.ie \\n(fV==1 \{\
+.	nr aP 0
+.	ie \\n(dZ==1 \{\
+.		if \\n(oM>1 .as b1 \\*(S0
+.	\}
+.	el \{\
+.		if \\n(oM>0 \{\
+.			if \\n(fC==0 .as b1 \\*(S0
+.		\}
+.	\}
+.	ds S0 \\*(S\\n(aC
+.	nr fV 0
+.	if \\n(Db \{\
+.		ie \\n(iN \{\
+\&\tMACRO REQUEST: .\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+.			br
+.			in \\n(iIu
+.		\}
+.		el \{\
+.tm \tMACRO REQUEST: .\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+.		\}
+.	\}
+.\}
+.el \{\
+.	nr fV \\n(fV-1
+.	fV
+.\}
+..
+.de aX
+.nr aP \\n(aP+1
+.as b1 \&\\*(A\\n(aP
+.ie \\n(fV==1 \{\
+.	nr aP 0
+.	nr fV 0
+.\}
+.el \{\
+.	as b1 \&\\*(sV
+.	nr fV \\n(fV-1
+.	aX
+.\}
+..
+.de aI
+.ie \\n(aC<9 \{\
+.	nr aC \\n(aC+1
+.	ds A\\n(aC \\$1
+.	nr C\\n(aC \\$2
+.	s\\$2
+.	ds xV S\\n(aC
+.\}
+.el \{\
+.	tm Usage: Too many arguments (maximum of 8 accepted) (#\\n(.c)
+.	tm \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+.\}
+..
+.de aZ
+.pB
+.aY
+..
+.de aY
+.rm C0 C1 C2 C3 C4 C5 C6 C7 C8 C9
+.rm A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
+.rm S1 S2 S3 S4 S5 S6 S7 S8 S9
+.nr aC 0
+.nr aP 0
+..
+.de pB
+.ie \\n(dZ==1 \{\
+.	if \\n(oM==1 \{\&\\*(b1
+.		rm S0
+.		ds b1
+.	\}
+.	if \\n(oM==0 \{\
+.		x2
+.	\}
+.\}
+.el \{\
+.	ie \\n(oM==0 \{\&\\*(b1
+.		rm S0
+.		ds b1
+.	\}
+.	el \{\
+.		if ((\\n(sM==1)&(\\n(tP==0)) \{\
+.			x1
+.		\}
+.	\}
+.\}
+.hy
+..
+.de x1
+.nr dZ \\n(dZ+1
+.ds b2 \\*(b1
+.ds b1
+.nr lK \\n(.c
+.ev 2
+.fi
+.di eB
+..
+.de x2
+.br
+.di
+.ev
+.ie (\\n(.c-\\n(lK>1) \{\
+.	ds b0 \&\\*(eB\\
+.	ds b1 \\*(b2\\*(b0\\*(b1
+.\}
+.el .ds b1 \\*(b2\\*(b1
+\&\\*(b1
+.rm eB b2 b0 b1
+.nr dZ \\n(dZ-1
+..
+.de Fl
+.as b1 \&\\*(fL
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 \{\
+.		as b1 \&\|\-\|\fP\s0
+.		pB
+.	\}
+.	el \{\
+.		ds mN Fl
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>0 \{\
+.	ie (\\n(aC-\\n(aP)==0 \{\
+.		as b1 \&\|\-\fP\s0
+.		aZ
+.	\}
+.	el \{\
+.		nr aP \\n(aP+1
+.		ie \\n(C\\n(aP==1 \{\
+.			as b1 \&\|\-\fP\s0
+.			\\*(A\\n(aP
+.		\}
+.		el \{\
+.			nr cF \\n(.f
+.			nr cZ \\n(.s
+.			if \\n(C\\n(aP==3 \{\
+.				as b1 \&\|\-\|
+.			\}
+.			fR
+.		\}
+.	\}
+.\}
+..
+.de fR
+.hy 0
+.nr jM \\n(C\\n(aP
+.ie \\n(jM==1 \{\
+.	as b1 \&\fP\s0
+.	\\*(A\\n(aP
+.\}
+.el \{\
+.	nr jN \\n(aP
+.	ie \\n(jM==2 \{\
+.		ie !"\\*(A\\n(aP"\\*(Ba" \{\
+.			ie !"\\*(A\\n(aP"\fR|\fP" \{\
+.		               ie "\\*(A\\n(aP"-" .as b1 \&\|\-\^\-\|
+.		               el .as b1 \&\|\-\\*(A\\n(aP
+.			\}
+.			el .as b1 \&\\*(A\\n(aP
+.		\}
+.		el .as b1 \&\\*(A\\n(aP
+.	\}
+.	el .as b1 \&\f\\n(cF\s\\n(cZ\\*(A\\n(aP\fP\s0
+.	ie \\n(aC==\\n(aP \{\
+.		if \\n(jM==4 .as b1 \&\|\-
+.		as b1 \&\fP\s0
+.		aZ
+.	\}
+.	el \{\
+.		nr aP \\n(aP+1
+.		ie ((\\n(C\\n(aP==3)&(\\n(C\\n(jN==4)) .as b1 \&\|\-
+.		el .as b1 \&\\*(S\\n(jN
+.		fR \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.rr jM jN
+..
+.de nR
+.hy 0
+.nr jM \\n(C\\n(aP
+.ie \\n(jM==1 \{\
+.	as b1 \&\f\\n(cF\s\\n(cZ
+.	\\*(A\\n(aP
+.\}
+.el \{\
+.	nr jN \\n(aP
+.	ie \\n(jM==2 .as b1 \&\\*(A\\n(aP
+.	el .as b1 \&\f\\n(cF\s\\n(cZ\\*(A\\n(aP\fP\s0
+.	ie \\n(aC==\\n(aP \{\
+.		as b1 \&\f\\n(cF\s\\n(cZ
+.		aZ
+.	\}
+.	el \{\
+.		nr aP \\n(aP+1
+.		as b1 \&\\*(S\\n(jN
+.		nR
+.	\}
+.\}
+.rr jM jN
+..
+.de Ar
+.as b1 \\*(aR
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 \{\
+.		as b1 file\ ...\fP\s0
+.		pB
+.	\}
+.	el \{\
+.		ds mN Ar
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>0 \{\
+.	ie (\\n(aC-\\n(aP)==0 \{\
+.		as b1 \&file\ ...\fP\s0
+.		aZ
+.	\}
+.	el \{\
+.		nr aP \\n(aP+1
+.		ie \\n(C\\n(aP==1 \{\
+.			as b1 \&file\ ...\fP\s0
+.			\\*(A\\n(aP
+.               \}
+.               el \{\
+.                       nr cF \\n(.f
+.			nr cZ \\n(.s
+.			if \\n(C\\n(aP==3 \{\
+.				as b1 \&file\ ...
+.			\}
+.                       nR
+.		\}
+.       \}
+.\}
+..
+.de Ad
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Ad address ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Ad
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(aD
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Cd
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Cd Configuration file declaration (#\\n(.c)
+. 	el \{\
+.		ds mN Cd
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+. 		nr fV \\n(.$
+. 		fV
+.	\}
+.\}
+.br
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(nM
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.	ie \\n(nS \{\
+.		if "\\*(mN"Cd" \{\
+.			rs
+.			ie \\n(nS>1 .br
+.			el \{\
+.				if \\n(iS==0 .nr iS \\n(Dsu
+.			\}
+.			in +\\n(iSu
+.			ti -\\n(iSu
+.			nr nS \\n(nS+1
+.		\}
+.	nR
+.	in -\\n(iSu
+.	\}
+.	el .nR
+.\}
+..
+.de Cm
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Cm Interactive command modifier ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Cm
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(cM
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Dv
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Dv define_variable ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Dv
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(eR
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Em
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 \{\
+.		tm Usage: .Em text ... \\*(Pu (#\\n(.c)
+.	\}
+.	el \{\
+.		ds mN Em
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(eM
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Er
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Er ERRNOTYPE ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Er
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(eR
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Ev
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Ev ENVIRONMENT_VARIABLE ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Ev
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(eV
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Fd
+.ds mN Fd
+.if \\n(nS>0 \{\
+.	if \\n(fX>0 \{\
+.		Pp
+.		nr fX 0
+.	\}
+.	if \\n(fZ>0 \{\
+.		ie \\n(fD==0 \{\
+.			Pp
+.			rs
+.		\}
+.		el .br
+.	\}
+.	nr fD \\n(fD+1
+.\}
+.nr cF \\n(.f
+.nr cZ \\n(.s
+\&\\*(fD\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.br
+.ft \\n(cF
+.fs \\n(cZ
+..
+.de Fr
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Fr Function_return_value... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Fr
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(aR
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Ic
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Ic Interactive command ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Ic
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(iC
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Li
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage .Li argument ... \\*(Pu (#\\n(.c)
+.       el \{\
+.		ds mN Li
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.               nr fV \\n(.$
+.               fV
+.       \}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(lI
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Or
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Or ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Or
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(iC
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Ms
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Ms Math symbol ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Ms
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(sY
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Nm
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 \{\
+.		ie "\\*(n1"" .tm Usage: .Nm Name(s) ... \\*(Pu (#\\n(.c)
+.		el \&\\*(nM\\*(n1\fP\s0
+.	\}
+.	el \{\
+.		ds mN Nm
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.               nr fV \\n(.$
+.               fV
+.       \}
+.\}
+.if \\n(aC>0 \{\
+.	ie \\n(aC==\\n(aP \{\
+.		as b1 \&\\*(nM\\*(n1\fP\s0
+.		aZ
+.	\}
+.	el \{\
+.		as b1 \\*(nM
+.		nr aP \\n(aP+1
+.		ie \\n(C\\n(aP==1 \{\
+.			as b1 \&\\*(n1\fP\s0
+.			\\*(A\\n(aP
+.		\}
+.		el \{\
+.			nr cF \\n(.f
+.			nr cZ \\n(.s
+.			if \\n(nS \{\
+.				if "\\*(mN"Nm" \{\
+.					rs
+.					in -\\n(iSu
+.					ie \\n(nS>1 .br
+.					el \{\
+.						if \\n(iS==0 \{\
+.							sw \\$1
+.					nr iS ((\\n(sWu+1)*\\n(fW)u
+.						\}
+.					\}
+.					in +\\n(iSu
+.					ti -\\n(iSu
+.					nr nS \\n(nS+1
+.				\}
+.			\}
+.			if "\\*(n1"" .ds n1 \\*(A\\n(aP
+.			nR
+.		\}
+.	\}
+.\}
+..
+.de Pa
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 \&\\*(pA~\fP\s0
+.	el \{\
+.		ds mN Pa
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(pA
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Sy
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Sy symbolic_text ... \\*(Pu (#\\n(.c)
+. 	el \{\
+.		ds mN Sy
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+. 		nr fV \\n(.$
+. 		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(sY
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Tn
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Tn Trade_name(s) ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Tn
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(tN\\*(tF
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de nN
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Tn Trade_name(s) ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Tn
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(tN
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de Va
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Va variable_name(s) ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Va
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	as b1 \\*(vA
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de No
+.as b1 \\*(nO
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 .tm Usage: .No must be called with arguments (#\\n(.c)
+.	el \{\
+.		ds mN No
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       ie \\n(C\\n(aP==1 \{\
+.		\\*(A\\n(aP
+.       \}
+.       el \{\
+.		nr cF \\n(.f
+.		nr cZ \\n(.s
+.		nR
+.       \}
+.\}
+..
+.de Op
+.if \\n(aC==0 \{\
+.	ds mN Op
+.\}
+.ds qL \&\\*(lB
+.ds qR \&\\*(rB
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+..
+.de Aq
+.if \\n(aC==0 .ds mN Aq
+.ds qL \&<
+.ds qR \&>
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Bq
+.if \\n(aC==0 .ds mN Bq
+.ds qL \&\\*(lB
+.ds qR \&\\*(rB
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Dq
+.if \\n(aC==0 .ds mN Dq
+.ds qL \&\\*(Lq
+.ds qR \&\\*(Rq
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Eq
+.if \\n(aC==0 .ds mN Eq
+.ds qL \\$1
+.ds qR \\$2
+.En \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Pq
+.if \\n(aC==0 .ds mN Pq
+.ds qL \&\\*(lP
+.ds qR \&\\*(rP
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Qq
+.if \\n(aC==0 .ds mN Qq
+.ds qL \&\\*q
+.ds qR \&\\*q
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Sq
+.if \\n(aC==0 .ds mN Sq
+.ds qL \&\\*(sL
+.ds qR \&\\*(sR
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Es
+.if \\n(aC==0 \{\
+.	ie \\n(.$>2 .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	el \{\
+.		ds qL \\$1
+.		ds qR \\$2
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.	ds qL \\*(A\\n(aP
+.	nr aP \\n(aP+1
+.	ds qR \\*(A\\n(aP
+.	ie \\n(aC>\\n(aP .c\\n(C\\n(aP
+.	el .aZ
+.\}
+..
+.de En
+.ie \\n(aC==0 \{\
+.	ie \\n(.$==0 \{\
+.		as b1 \&\\*(qL\\*(qR
+.		pB
+.	\}
+.	el \{\
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.		as b1 \&\\*(qL
+.	\}
+.\}
+.el \{\
+.	as b1 \&\\*(qL
+.\}
+.if \\n(aC>0 \{\
+.	ie (\\n(aC-\\n(aP)==0 \{\
+.		as b1 \&\\*(qR
+.		aZ
+.	\}
+.	el \{\
+.		ie \\n(C\\n(aC==3 \{\
+.			nr aJ \\n(aC-1
+.			vR
+.			nr aJ \\n(aJ+1
+.			ds A\\n(aJ \&\\*(qR\\*(A\\n(aJ
+.			nr aJ 0
+.		\}
+.		el .aI \&\\*(qR 3
+.		nr aP \\n(aP+1
+.		if \\n(C\\n(aP==1 .\\*(A\\n(aP
+.		if \\n(C\\n(aP>1 \{\
+.			nr aP \\n(aP-1
+.			No
+.		\}
+.	\}
+.\}
+..
+.de vR
+.if \\n(C\\n(aJ==3 \{\
+.	nr aJ \\n(aJ-1
+.	vR
+.\}
+..
+.de Ao
+.if \\n(aC==0 .ds mN Ao
+.ds qL \&<
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Ac
+.if \\n(aC==0 .ds mN Ac
+.ds qR \&>
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Bo
+.if \\n(aC==0 .ds mN Bo
+.ds qL \&[
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Bc
+.if \\n(aC==0 .ds mN Bc
+.ds qR \&]
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Do
+.if \\n(aC==0 .ds mN Do
+.ds qL \&\\*(Lq
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Dc
+.if \\n(aC==0 .ds mN Dc
+.ds qR \&\\*(Rq
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Eo
+.if \\n(aC==0 .ds mN Eo
+.ds qL \\$1
+.eO \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Ec
+.if \\n(aC==0 .ds mN Ec
+.ds qR \\$1
+.eC \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Oo
+.if \\n(aC==0 .ds mN Oo
+.ds qL \&[
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Oc
+.if \\n(aC==0 .ds mN Oc
+.ds qR \&]
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Po
+.if \\n(aC==0 .ds mN Po
+.ds qL \&(
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Pc
+.if \\n(aC==0 .ds mN Pc
+.ds qR \&)
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Qo
+.if \\n(aC==0 .ds mN Qo
+.ds qL \&\\*q
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Qc
+.if \\n(aC==0 .ds mN Qc
+.ds qR \&\\*q
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de So
+.if \\n(aC==0 .ds mN So
+.ds qL \&\\*(sL
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Sc
+.if \\n(aC==0 .ds mN Sc
+.ds qR \&\\*(sR
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Xo
+.if \\n(aC==0 .ds mN Xo
+.ds qL
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Xc
+.if \\n(aC==0 .ds mN Xc
+.ds qR
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de eO
+.nr oM \\n(oM+1
+.ie \\n(aC==0 \{\
+.       ie \\n(.$>0 \{\
+.               aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.		as b1 \\*(qL
+.       \}
+.	el \{\
+.		as b1 \\*(qL
+.		if (\\n(dZ==0)&(\\n(sM==1) \{\
+.			nr dZ \\n(dZ+1
+.			ds b2 \\*(b1
+.			ds b1
+.			nr lK \\n(.c
+.			ev 2
+.			fi
+.			di eB
+.		\}
+.	\}
+.\}
+.el \{\
+.	as b1 \\*(qL
+.\}
+.ie \\n(aC>0 \{\
+.	if \\n(aC>\\n(aP \{\
+.		nr aP \\n(aP+1
+.		ie \\n(C\\n(aP==1 .\\*(A\\n(aP
+.		el  \{\
+.			nr aP \\n(aP-1
+.			No
+.		\}
+.	\}
+.	if \\n(aC==\\n(aP \{\
+.		if \\n(tP==1 \{\
+.			nr Xt 1
+.		\}
+.		aY
+.	\}
+.\}
+.el \{\
+.	if \\n(oM>1 .as b1 \\*(sV
+.\}
+..
+.de eC
+.nr oM \\n(oM-1
+.as b1 \\*(qR
+.if \\n(aC==0 \{\
+.       ie \\n(.$>0 \{\
+.               aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.       \}
+.	el \{\
+.		ie "\\*(xB"" \{\
+.			pB
+.		\}
+.		el \{\
+.			pB
+.\\*(L\\n(lC
+.			nr Xt 0
+.			ds xB
+.		\}
+.	\}
+.\}
+.if \\n(aC>0 \{\
+.	ie \\n(aC==\\n(aP \{\
+.		ie \\n(oM==0 \{\
+.			aZ
+.		\}
+.		el .aY
+.	\}
+.	el \{\
+.		nr aa \\n(aP+1
+.		if \\n(C\\n(aa==2 .as b1 \\*(S\\n(aC
+.		rr aa
+.		if \\n(tP>0 \{\
+.			if \\n(Xt>0 .nr Xt \\n(Xt-1
+.		\}
+.		No
+.	\}
+.\}
+..
+.de Pf
+.if \\n(aC==0 .ds mN Pf
+.ds qL \&\\$1
+.pF \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de pF
+.ie \\n(aC==0 \{\
+.	as b1 \&\\*(qL
+.	ie \\n(.$<2 \{\
+.		tm Warning: Missing arguments - prefix .Pf)
+.		pB
+.	\}
+.	el .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.el \{\
+.	ie (\\n(aC-\\n(aP)>1 \{\
+.		nr aP \\n(aP+1
+.		as b1 \&\\*(A\\n(aP
+.	\}
+.	el .tm Warning: .Pf: trailing prefix (#\\n(.c)
+.\}
+.if \\n(aC>0 \{\
+.	ie (\\n(aC-\\n(aP)==0 .aZ
+.	el \{\
+.		nr aP \\n(aP+1
+.		c\\n(C\\n(aP
+.	\}
+.\}
+..
+.de Ns
+.if \\n(aC==0 \{\
+.	ds mN Ns
+.	ie \\n(.$>0 .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	el .tm Usage: .Ns must be called with arguments (#\\n(.c)
+.\}
+.No
+..
+.de Ap
+.if \\n(aC==0 \{\
+.	ds mN Ap
+.	tm Usage: Ap "cannot be first request on a line (no .Ap)" (#\\n(.c)
+.\}
+.as b1 \&'
+.No
+..
+.de Hv
+.ds iV \\*(sV
+.ds sV \\*(hV
+..
+.de Sv
+.ds sV \\*(iV
+..
+.de Tv
+.ds sV \\*(tV
+..
+.nr sM 1
+.de Sm
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 .tm "Usage: .Sm [off | on]" (#\\n(.c)
+.	el \{\
+.		ds mN Sm
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>0 \{\
+.	nr aP \\n(aP+1
+.	if "\\*(A\\n(aP"on" \{\
+.		ds sV \\*(iV
+.		nr sM 1
+.	\}
+.	if "\\*(A\\n(aP"off" \{\
+.		ds sV
+.		rm S0 S1 S2 S3 S4 S5 S6 S7 S8 S9
+.		nr sM 0
+.	\}
+.	ie \\n(aC>\\n(aP \{\
+.		No
+.	\}
+.	el .aY
+.\}
+..
+.if \n(.g \{\
+.de aT
+.nr aT 0
+.ie \\n(sW>2:(\A'\\$1'==0) \{\
+.	nr aT 2
+.\}
+.el \{\
+.	if \\n(sW==1 \{\
+.		ie \\n(z\\$1>2 \{\
+.			nr aT \\n(z\\$1
+.		\}
+.		el .nr aT 2
+.	\}
+.	if \\n(sW==2 \{\
+.		ie \\n(\\$1 \{\
+.			nr aT 1
+.		\}
+.		el .nr aT 2
+.	\}
+.\}
+..
+.de aU
+.nr aT 0
+.aW \\$1
+.ie \\n(sW>2:(\A'\\*(A\\$1'==0) .nr aT 2
+.el \{\
+.	if \\n(sW==1 \{\
+.		ie \\n(z\\*(A\\$1>2 \{\
+.			nr aT \\n(z\\*(A\\$1
+.		\}
+.		el .nr aT 2
+.	\}
+.	if \\n(sW==2 \{\
+.		ie (\\n(\\*(A\\$1) \{\
+.			nr aT 1
+.		\}
+.		el .nr aT 2
+.	\}
+.\}
+..
+.\}
+.if !\n(.g \{\
+.de aT
+.nr aT 0
+.ie \\n(sW>2 \{\
+.	nr aT 2
+.\}
+.el \{\
+.	if \\n(sW==1 \{\
+.		ie \\n(z\\$1>2 \{\
+.			nr aT \\n(z\\$1
+.		\}
+.		el .nr aT 2
+.	\}
+.	if \\n(sW==2 \{\
+.		ie \\n(\\$1 \{\
+.			nr aT 1
+.		\}
+.		el .nr aT 2
+.	\}
+.\}
+..
+.de aU
+.nr aT 0
+.aW \\$1
+.ie \\n(sW>2 .nr aT 2
+.el \{\
+.	if \\n(sW==1 \{\
+.		ie \\n(z\\*(A\\$1>2 \{\
+.			nr aT \\n(z\\*(A\\$1
+.		\}
+.		el .nr aT 2
+.	\}
+.	if \\n(sW==2 \{\
+.		ie (\\n(\\*(A\\$1) \{\
+.			nr aT 1
+.		\}
+.		el .nr aT 2
+.	\}
+.\}
+..
+.\}
+.de s0
+.tm MDOC-ERROR: bogus type 0 (can't set space '\\*(A\\n(aC') (#\\n(.c)
+..
+.de s1
+.if \\n(\\*(A\\n(aC==3 \{\
+.	nr xX \\n(aC-1
+.	rm S\\n(xX
+.	ds S\\n(aC \\*(sV
+.\}
+.if \\n(\\*(A\\n(aC==2 \{\
+.	nr xX \\n(aC-1
+.	ie "\\*(A\\n(aC"Nb" .ds S\\n(xX \\*(hV
+.	el .rm S\\n(xX
+.\}
+..
+.de s2
+.ds S\\n(aC \\*(sV
+..
+.de s3
+.if \\n(aC>1 \{\
+.	nr xX \\n(aC-1
+.	rm S\\n(xX
+.\}
+.ds S\\n(aC \\*(sV
+..
+.de s4
+.nr aa 0
+..
+.de c0
+.tm MDOC-ERROR: bogus class 0 (can't determine '\\*(A\\n(aC') (#\\n(.c)
+..
+.de c1
+.\\*(A\\n(aP
+..
+.de c2
+.nr aP \\n(aP-1
+.No
+..
+.de c3
+.nr aP \\n(aP-1
+.No
+..
+.de c4
+.nr aP \\n(aP-1
+.No
+..
+.de y1
+.nr aa 1
+..
+.de y2
+.nr aa 1
+..
+.de y3
+.as b1 \\*(A\\n(aP
+.nr aP \\n(aP+1
+.n\\C\\n(aP
+..
+.de y4
+.as b1 \\*(A\\n(aP
+.nr aP \\n(aP+1
+.n\\C\\n(aP
+..
+.de Bf
+.ds mN Bf
+.ie \\n(.$>0 \{\
+.	nr bF \\n(.f
+.	nr bZ \\n(.s
+.	if "\\$1"Em" \&\\*(eM\c
+.	if "\\$1"Li" \&\\*(lI\c
+.	if "\\$1"Sy" \&\\*(sY\c
+.	if "\\$1"-emphasis" \&\\*(eM\c
+.	if "\\$1"-literal" \&\\*(lI\c
+.	if "\\$1"-symbolic" \&\\*(sY\c
+.\}
+.el .tm Usage .Bf [Em | emphasis | Li | literal | Sy | symbolic] (#\\n(.c)
+..
+.de Ef
+.ds mN Ef
+.ie \\n(.$>0 .tm Usage .Ef (does not take arguments) (#\\n(.c)
+.el \&\f\\n(bF\s\\n(bZ
+..
+.de Bk
+.ds mN Bk
+.ie \\n(.$==0 \{\
+.tm Usage: .Bk [-lines | -words] (#\\n(.c)
+.\}
+.el \{\
+.	if !"\\*(kS"" .tm .Bk: nesting keeps not implemented yet. (#\\n(.c)
+.	if "\\$1"-lines" .tm .Bd -lines: Not implemented yet. (#\\n(.c)
+.	if "\\$1"-words" .Hv
+.	ds kS \\$1
+.\}
+..
+.de Ek
+.ds mN Ek
+.ie \\n(.$>0 .tm Usage .Ek (does not take arguments) (#\\n(.c)
+.el \{\
+.	if "\\*(kS"-lines" .tm .Bd -lines: Not implemented yet. (#\\n(.c)
+.	if "\\*(kS"-words" .Sv
+.	rm kS
+.\}
+..
+.de Bd
+.ds mN Bd
+.ie \\n(.$==0 \{\
+.tm Usage: .Bd [-literal | -filled | -ragged | -unfilled] [-offset [string]] [-compact] (#\\n(.c)
+.\}
+.el \{\
+.	ds aa
+.	nr bV 0
+.       nr iD 0
+.	nr dP \\n(dP+1
+.       if "\\$1"-literal" \{\
+.		nr iD \\n(iD+1
+.               ds d\\n(dP dL
+.		nr cF \\n(.f
+.		nr cZ \\n(.s
+.		ie t \{\&\\*(lI
+'			ta 9n 18n 27n 36n 45n 54n 63n 72n
+.		\}
+.		el \{\
+'			ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
+.		\}
+.		nf
+.       \}
+.       if "\\$1"-filled" \{\
+.		nr iD \\n(iD+1
+.               ds d\\n(dP dF
+.		br
+.       \}
+.       if "\\$1"-ragged" \{\
+.		nr iD \\n(iD+1
+.               ds d\\n(dP dR
+.		na
+.       \}
+.       if "\\$1"-unfilled" \{\
+.		nr iD \\n(iD+1
+.               ds d\\n(dP dU
+.		nf
+.       \}
+.       if ((\\n(iD>=1)&(\\n(.$>\\n(iD)) \{\
+.		bV \\$2 \\$3 \\$4
+.	\}
+.	if \\n(O\\n(dP>0 'in \\n(.iu+\\n(O\\n(dPu
+.	if (\\n(bV==0) \{\
+.		if (\\n(nS==0) \{\
+.			ie "\\*(d\\n(dP"dR" .sp \\n(dVu
+.			el 'sp \\n(dVu
+.		\}
+.	\}
+.	if \\n(cR==0 .ne 2v
+.	nr bV 0
+.	nr iD 0
+.\}
+..
+.de bV
+.nr iD 1
+.ds bY
+.if "\\$1"-offset" \{\
+.	ds bY \\$2
+.	if "\\*(bY"left" \{\
+.		nr iD \\n(iD+1
+.		nr O\\n(dP 0
+.	\}
+.	if "\\*(bY"right" \{\
+.		nr iD \\n(iD+1
+.		nr O\\n(dP (\\n(.l/3)u
+.	\}
+.	if "\\*(bY"center" \{\
+.		nr iD \\n(iD+1
+.		nr O\\n(dP (\\n(.l-\\n(.i)/4u
+.	\}
+.	if "\\*(bY"indent" \{\
+.		nr iD \\n(iD+1
+.		nr O\\n(dP \\n(dIu
+.	\}
+.	if "\\*(bY"indent-two" \{\
+.		nr iD \\n(iD+1
+.		nr O\\n(dP \\n(dIu+\\n(dIu
+.	\}
+.	if \\n(iD==1 \{\
+.		nr iD \\n(iD+1
+.		sW "\\*(bY"
+.		ie \\n(sW>2 \{\
+.			ie ((\\*(bY>9n)&(\\*(bY<100n)) \{\
+.				nr O\\n(dP \\*(bY
+.			\}
+.			el .nr O\\n(dP (\\n(sW)*\\n(fWu
+.		\}
+.		el \{\
+.			if \\n(sW==2 .aT \\*(bY
+.			ie \\n(aT==1 \{\
+.				nr O\\n(dP \\n(\\*(bY
+.			\}
+.			el .nr O\\n(dP \\*(bY
+.		\}
+.	\}
+.\}
+.if "\\$1"-compact" \{\
+.	nr bV 1
+.\}
+.if \\n(iD<\\n(.$ \{\
+.	ie "\\*(bY"" \{\
+.		bV \\$2 \\$3
+.	\}
+.	el \{\
+.		bV \\$3
+.	\}
+.\}
+..
+.de Ed
+.ds mN Ed
+.br
+.if \\n(dP==0 .tm mdoc: Extraneous .Ed
+.if "\\*(d\\n(dP"dL" \{\
+.	ft \\n(cF
+.	fz \\n(cZ
+.\}
+.in \\n(.iu-\\n(O\\n(dPu
+.rr O\\n(dP
+.rm d\\n(dP
+.nr dP \\n(dP-1
+.fi
+.if t .ad
+..
+.de Bl
+.ie \\n(.$==0 \{\
+.tm Usage: .Bl [[-hang | -tag] [-width]] [ -item | -enum | -bullet | -diag] (#\\n(.c)
+.\}
+.el \{\
+.	ds mN Bl
+.	nr aP 0
+.	nr lC \\n(lC+1
+.	ds A1 \\$2
+.	ds A2 \\$3
+.	ds A3 \\$4
+.	ds A4 \\$5
+.	ds A5 \\$6
+.	ds A6 \\$7
+.	ds A7 \\$8
+.	ds A8 \\$9
+.	nr fV \\n(.$-1
+.	if "\\$1"-hang" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC hL
+.		nr w\\n(lC 6n
+.		nr tC  1
+.	\}
+.	if "\\$1"-tag" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC tL
+.		nr tC  1
+.	\}
+.	if "\\$1"-item" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC iT
+.		nr tC  1
+.	\}
+.	if "\\$1"-enum" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC nU
+.		nr w\\n(lC 3n
+.		nr tC  1
+.	\}
+.	if "\\$1"-bullet" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC bU
+.		nr w\\n(lC 2n
+.		nr tC  1
+.	\}
+.	if "\\$1"-dash" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC hU
+.		nr w\\n(lC 2n
+.		nr tC  1
+.	\}
+.	if "\\$1"-hyphen" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC hU
+.		nr w\\n(lC 2n
+.		nr tC  1
+.	\}
+.	if "\\$1"-inset" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC lL
+.		nr tC  1
+.	\}
+.	if "\\$1"-diag" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC mL
+.		nr mL 1
+.	\}
+.	if "\\$1"-ohang" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC oL
+.		nr tC 1
+.	\}
+.	if "\\$1"-column" \{\
+.		nr aP \\n(aP+1
+.		ds L\\n(lC cL
+.	\}
+.	ie \\n(aP==0 \{\
+.	tm \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	tm Usage: .Bl [[-inset|-tag] -width] [-item|-enum|-bullet|-diag] (#\\n(.c)
+.	\}
+.	el \{\
+.		tY
+.		if (\\n(aP==1)&(\\n(aP<\\n(.$) \{\
+.			nr aP 0
+.			lV
+.			if "\\*(L\\n(lC"cL" \{\
+.				W\\n(wV
+.				nr w\\n(lC 0
+'				in -\\n(eWu
+.				ie \\n(v\\n(lC==1 \{\
+.				       nr aa 0
+.				\}
+.				el \{\
+.					sp \\n(dVu
+.				\}
+.				nf
+.				nr wV 0
+.			\}
+.		\}
+.	\}
+.	nr aP 0
+.	aY
+.\}
+..
+.if \n(.g \{\
+.	nr i 10
+.	while \ni<100 \{\
+.	     nr num!\nin 1
+.	     nr i +1
+.	\}
+.\}
+.de lV
+.nr aP \\n(aP+1
+.if \\n(fV>=\\n(aP \{\
+.	nr iD 0
+.	if "\\*(A\\n(aP"-compact" \{\
+.		nr iD 1
+.		nr v\\n(lC 1
+.	\}
+.	if "\\*(A\\n(aP"-width" \{\
+.		nr iD 1
+.		nr aP \\n(aP+1
+.		nr tW 1
+.		ds t\\n(lC TagwidtH
+.		ds tS \\*(A\\n(aP
+.		aW \\n(aP
+.		ie \\n(sW>2 \{\
+.			nr w\\n(lC (\\n(sW)*\\n(fWu
+.			if \\n(sW==3 \{\
+.				ie \\n(.g \{\
+.					if \A'\\*(tS' .if r num!\\*(tS \{\
+.						nr w\\n(lC \\*(tS
+.					\}
+.				\}
+.				el \{\
+.					if (\\*(tS>9n)&(\\*(tS<99n) \{\
+.						nr w\\n(lC \\*(tSu
+.					\}
+.				\}
+.			\}
+.		\}
+.		el \{\
+.			aT \\*(tS
+.			ie \\n(aT==1 \{\
+.				nr w\\n(lC \\n(\\*(tS
+.			\}
+.			el \{\
+.				nr w\\n(lC \\*(tSu
+.			\}
+.		\}
+.	\}
+.	if "\\*(A\\n(aP"-offset" \{\
+.		nr iD 1
+.		nr aP \\n(aP+1
+.		ie "\\*(A\\n(aP"indent" \{\
+.			nr o\\n(lC \\n(Dsu
+.		\}
+.		el \{\
+.			ds tS \\*(A\\n(aP
+.			aW \\n(aP
+.			ie \\n(sW>2 \{\
+.				nr o\\n(lC (\\n(sW)*\\n(fWu
+.				ie \\n(.g \{\
+.					if \A'\\*(tS' .if r num!\\*(tS \{\
+.						nr o\\n(lC \\*(tS
+.					\}
+.				\}
+.				el \{\
+.					if (\\*(tS>9n)&(\\*(tS<100n) \{\
+.						nr o\\n(lC \\*(tS
+.					\}
+.				\}
+.			\}
+.			el \{\
+.				ie \\n(C\\n(aP==1 .nr o\\n(lC \\n(\\*(tS
+.				el .nr o\\n(lC \\*(tS
+.			\}
+.		\}
+.	\}
+.	if \\n(iD==0 \{\
+.		if "\\*(L\\n(lC"cL" \{\
+.			nr wV \\n(wV+1
+.			ds A\\n(wV \\*(A\\n(aP
+.		\}
+.	\}
+.	if \\n(fV>\\n(aP .lV
+.\}
+..
+.de El
+.ie \\n(.$>0 \{\
+.	tm Usage: .El (#\\n(.c)
+.\}
+.el \{\
+.	ds mN El
+.	nr iD 0
+.	if "\\*(L\\n(lC"cL" \{\
+.		nr iD 1
+.		cC
+.	\}
+.	if "\\*(L\\n(lC"nU" \{\
+.		nr nU 0
+.	\}
+.	if \\n(mL>0 \{\
+.		nr iD 1
+.		nr mL 0
+.		tZ
+.		nr lC \\n(lC-1
+.		tY
+.	\}
+.	if "\\*(L\\n(lC"iT" \{\
+'		in \\n(.iu-\\n(o\\n(lCu
+.		tZ
+.		nr lC \\n(lC-1
+.		tY
+.		nr iD 1
+.	\}
+.	if "\\*(L\\n(lC"oL" \{\
+'		in \\n(.iu-\\n(o\\n(lCu
+.		tZ
+.		nr lC \\n(lC-1
+.		tY
+.		nr iD 1
+.	\}
+.	if "\\*(L\\n(lC"lL" \{\
+'		in \\n(.iu-\\n(o\\n(lCu
+.		tZ
+.		nr lC \\n(lC-1
+.		tY
+.		nr iD 1
+.	\}
+.	if \\n(iD==0 \{\
+.		lE
+.	\}
+.	br
+.	nr iD 0
+.\}
+..
+.de It
+.if "\\*(L\\n(lC"" \{\
+.	tm Usage .Bl -list-type [-width [string] | -compact | -offset [string]] (#\\n(.c)
+.	tm .It \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+.\}
+.ne 3v
+.ie \\n(.$>0 \{\
+.	ds mN It
+.	ds b1
+.	nr iD 0
+.	ds A1 \\$1
+.	ds A2 \\$2
+.	ds A3 \\$3
+.	ds A4 \\$4
+.	ds A5 \\$5
+.	ds A6 \\$6
+.	ds A7 \\$7
+.	ds A8 \\$8
+.	ds A9 \\$9
+.	nr fV \\n(.$
+.	if "\\*(L\\n(lC"mL" \{\
+.		nr iD 1
+.		nr aP 0
+.		aX
+.		\\*(L\\n(lC
+.	\}
+.	if "\\*(L\\n(lC"cL" \{\
+.		ds b1
+.		nr aP 0
+.		nr iD 1
+.		\\*(L\\n(lC
+.	\}
+.	if "\\*(L\\n(lC"iT" \{\
+.		nr aP 0
+.		nr iD 1
+.		\\*(L\\n(lC
+.	\}
+.	if \\n(iD==0 \{\
+.		fV
+.		nr oM \\n(oM+1
+.		nr tP 1
+.		nr aP \\n(aP+1
+.		nr tX \\n(C\\n(aP
+.		ds tX \\*(A\\n(aP
+.		if \\n(nF==1 \{\
+.			ds aA \\*(pA
+.			if n .ds pA \\*(nO
+.		\}
+.		ie \\n(C\\n(aP==1 \{\
+.			\\*(A\\n(aP
+.		\}
+.		el \{\
+.			nr aP \\n(aP-1
+.			No
+.		\}
+.		ie \\n(Xt==1 .ds xB \&\\*(L\\n(lC
+.		el .\\*(L\\n(lC
+.	\}
+.	nr iD 0
+.\}
+.el .\\*(L\\n(lC
+..
+.de lL
+.lY
+.br
+\&\\*(b1
+.nr oM \\n(oM-1
+.nr tP 0
+.ds b1
+.aY
+'fi
+..
+.de hL
+.lX
+.nr bb \\n(w\\n(lCu+\\n(lSu
+.ti -\\n(bbu
+.ie \w\\*(b1u>=(\\n(w\\n(lCu) \&\\*(b1
+.el \&\\*(b1\h'|\\n(bbu'\c
+.nr oM \\n(oM-1
+.ds b1
+.nr tP 0
+.aY
+'fi
+..
+.de oL
+.lY
+\&\\*(b1
+.br
+.nr oM \\n(oM-1
+.ds b1
+.nr tP 0
+.aY
+'fi
+..
+.de iT
+.lY
+.br
+.aY
+'fi
+..
+.de nU
+.nr oM \\n(oM+1
+.nr nU \\n(nU+1
+.ds b1 \&\\n(nU.
+.uL
+..
+.de bU
+.nr oM \\n(oM+1
+.nr bU \\n(bU+1
+.ds b1 \&\\*(sY\&\(bu\fP
+.uL
+..
+.de hU
+.nr oM \\n(oM+1
+.nr bU \\n(bU+1
+.ds b1 \&\\*(sY\&\-\fP
+.uL
+..
+.de uL
+.lX
+.nr bb \\n(w\\n(lCu+\\n(lSu
+.ti -\\n(bbu
+.ie \w\\*(b1u>=(\\n(w\\n(lCu) \&\\*(b1
+.el \&\\*(b1\h'|\\n(bbu'\c
+.nr oM \\n(oM-1
+.ds b1
+.nr tP 0
+.aY
+'fi
+..
+.de mL
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ie \\n(mL==1 \{\
+.	nr zB \\n(.c
+.	ie (\\n(zB-\\n(zA)>1 .Pp
+.	el .br
+.	nr zA \\n(zB
+.	nr zB 0
+.\}
+.el \{\
+.	nr zA \\n(.c
+.	br
+.\}
+\&\\*(sY\\*(b1\f\\n(cF\s\\n(cZ\\*(lS\c
+.aY
+.ds b1
+'fi
+..
+.de tL
+.if \\n(tW==0 .lW
+.lX
+.nr bb \\n(w\\n(lCu+\\n(lSu
+.ti -\\n(bbu
+.ie (\w\\*(b1u)>(\\n(w\\n(lCu) \{\&\\*(b1
+.       br
+.\}
+.el \&\\*(b1\h'|\\n(bbu'\c
+.if \\n(nF==1 \{\
+.	if n .ds pA \\*(aA
+.\}
+.nr oM \\n(oM-1
+.nr tP 0
+.ds b1
+.aY
+'fi
+..
+.de lW
+.if !"TagwidtH"\\*(t\\n(lC" \{\
+.       ie \\n(tX==1 \{\
+.               ds t\\n(lN \\*(tX
+.               nr w\\n(lN \\n(\\*(tX
+.       \}
+.       el \{\
+.               ds t\\n(lN No
+.               nr w\\n(lN \\n(No
+.       \}
+.       if !"\\*(t\\n(lC"\\*(t\\n(lN" .nr tC 1
+.\}
+..
+.de lX
+.ie \\n(tC \{\
+.       nr tC 0
+.       nr tW 0
+.       if \\n(v\\n(lC==0 .sp \\n(dVu
+.       in \\n(.iu+\\n(w\\n(lCu+\\n(o\\n(lCu+\\n(lSu
+.\}
+.el \{\
+.	ie \\n(v\\n(lC==1 \{\
+.	       nr aa 0
+.	\}
+.	el \{\
+.		sp \\n(dVu
+.	\}
+.\}
+.if !\\n(cR .ne 2v
+..
+.de lY
+.ie \\n(tC \{\
+.       nr tC 0
+.       nr tW 0
+.       if \\n(v\\n(lC==0 .sp \\n(dVu
+.       in \\n(.iu+\\n(o\\n(lCu
+.\}
+.el \{\
+.	ie \\n(v\\n(lC==1 \{\
+.	       nr aa 0
+.	\}
+.	el \{\
+.		sp \\n(dVu
+.	\}
+.\}
+.if !\\n(cR .ne 2v
+..
+.nr lC 0
+.nr wV 0
+.nr w1 0
+.nr o1 0
+.nr v1 0
+.nr h1 0
+.ds t\n(lC
+.de lE
+.ie \\n(o\\n(lC>0 \{\
+'	in \\n(.iu-(\\n(w\\n(lCu)-(\\n(o\\n(lCu)-\\n(lSu
+.	rr o\\n(lC
+.\}
+.el 'in \\n(.iu-\\n(w\\n(lCu-\\n(lSu
+.if \\n(lC<=0 .tm Extraneous .El call (#\\n(.c)
+.tZ
+.nr lC \\n(lC-1
+.tY
+..
+.de tY
+.nr tY (\\n(lC+1)
+.nr w\\n(tY 0
+.nr h\\n(tY 0
+.nr o\\n(tY 0
+.ds t\\n(tY \\*(t\\n(lC
+.ds L\\n(tY
+.nr v\\n(tY 0
+..
+.de tZ
+.rm L\\n(tY
+.rr w\\n(tY
+.rr h\\n(tY
+.rr o\\n(tY
+.rm t\\n(tY
+.rr v\\n(tY
+.nr tY \\n(tY-1
+..
+.nr w1 0
+.nr o1 0
+.nr h1 0
+.ds t1
+.nr v1 0
+.nr tY 1
+.de Xr
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 .tm Usage: .Xr manpage_name [section#] \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Xr
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.	ie \\n(C\\n(aP==1 .tm Usage: .Xr manpage_name [section#] \\*(Pu (#\\n(.c)
+.	el \{\
+.		ie \\n(C\\n(aP>2 .y\\n(C\\n(aP
+.		el \{\
+.			as b1 \&\\*(xR\\*(A\\n(aP\fP\s0
+.			if \\n(aC>\\n(aP \{\
+.				nr aP \\n(aP+1
+.				if \\n(C\\n(aP==2 \{\
+.					as b1 \&(\\*(A\\n(aP)
+.					nr aP \\n(aP+1
+.				\}
+.				if \\n(aC>=\\n(aP \{\
+.					c\\n(C\\n(aP
+.				\}
+.			\}
+.		\}
+.		aZ
+.       \}
+.\}
+..
+.de Sx
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 .tm Sx Usage: .Sx Section Header \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Sx
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.	as b1 \\*(sX
+.	nr cF \\n(.f
+.	nr cZ \\n(.s
+.	nR
+.\}
+..
+.de cC
+'in \\n(.iu-\\n(o\\n(lCu-\\n(w\\n(lCu
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.fi
+.tZ
+.nr lC \\n(lC-1
+.tY
+..
+.de W1
+.ta \w\\*(A1    u
+.nr eW \w\\*(A1    u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W2
+.ta \w\\*(A1    u +\w\\*(A2    u
+.nr eW \w\\*(A1    u+\w\\*(A2    u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W3
+.ta \w\\*(A1    u +\w\\*(A2    u +\w\\*(A3    u
+.nr eW \w\\*(A1    u+\w\\*(A2    u+\w\\*(A3    u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W4
+.ta \w\\*(A1    u +\w\\*(A2    u +\w\\*(A3    u +\w\\*(A4    u
+.nr eW \w\\*(A1    u+\w\\*(A2    u +\w\\*(A3    u +\w\\*(A4    u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W5
+.ta \w\\*(A1   u +\w\\*(A2   u +\w\\*(A3   u +\w\\*(A4   u +\w\\*(A5   u
+.nr eW \w\\*(A1   u +\w\\*(A2   u +\w\\*(A3   u +\w\\*(A4   u +\w\\*(A5   u
+'	in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W6
+.ta \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u +\w\\*(A5 u +\w\\*(A6
+.nr eW \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u +\w\\*(A5 u +\w\\*(A6
+'	in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de cL
+.if \\n(w\\n(lC==0 .nr w\\n(lC \\n(eWu
+.if \\n(.u==0 \{\
+.	fi
+'	in \\n(.iu+\\n(eWu
+.\}
+.ti -\\n(eWu
+.fV
+.nr aP \\n(aP+1
+.ie \\n(aC>=\\n(aP  \{\
+.	if "\\*(A\\n(aP"Ta" \{\
+.		nr jJ \\n(aP-1
+.		rm S\\n(jJ
+.		rr jJ
+.	\}
+.	c\\n(C\\n(aP
+.\}
+.el .tm Usage: .It column_string [Ta [column_string ...] ] (#\\n(.c)
+..
+.de Ta
+.ie \\n(aC>0 \{\
+.	nr aP \\n(aP+1
+.	ie \\n(aC>=\\n(aP \{\
+.		if "\\*(A\\n(aP"Ta" \{\
+.			nr jJ \\n(aP-1
+.			rm S\\n(jJ
+.			rr jJ
+.		\}
+.		as b1 \\t
+.		c\\n(C\\n(aP
+.	\}
+.	el \{\
+.		as b1 \\t\\c
+.		rm S\\n(aP
+.		pB
+.		aY
+.	\}
+.\}
+.el \{\
+.	tm Usage: Ta must follow column entry: e.g. (#\\n(.c)
+.	tm .It column_string [Ta [column_string ...] ]
+.\}
+..
+.de Dl
+'ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.in \\n(.iu+\\n(Dsu
+.ie \\n(aC==0 \{\
+.	ie \\n(.$==0 \{\
+.		tm Usage: .Dl argument ... (#\\n(.c)
+.	\}
+.	el \{\
+.		ds mN Dl
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.		Li
+.	\}
+.\}
+.el \{\
+.	tm Usage: .Dl not callable by other macros (#\\n(.c)
+.\}
+.in \\n(.iu-\\n(Dsu
+..
+.de D1
+'ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.in \\n(.iu+\\n(Dsu
+.ie \\n(aC==0 \{\
+.	ie \\n(.$==0 \{\
+.		tm Usage: .D1 argument ... (#\\n(.c)
+.	\}
+.	el \{\
+.		ds mN D1
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.		nr aP \\n(aP+1
+.		ie \\n(C\\n(aP==1 .\\*(A\\n(aP
+.		el .No
+.	\}
+.\}
+.el \{\
+.	tm Usage: .D1 not callable by other macros (#\\n(.c)
+.\}
+.in \\n(.iu-\\n(Dsu
+..
+.de Ex
+.tm Ex defunct, Use .D1: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Ex
+.tm Ex defunct, Use .D1: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Vt
+.if \\n(fD>0 \{\
+.	Pp
+.	nr fD 0
+.\}
+.if \\n(fZ>0 \{\
+.	ie \\n(fX==0 \{\
+.		Pp
+.		rs
+.	\}
+.	el .br
+.\}
+.nr fX \\n(fX+1
+.nr cF \\n(.f
+.nr cZ \\n(.s
+\\*(fT\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ie \\n(oT==0 .br
+.el \&\ \&
+.ft \\n(cF
+.fs \\n(cZ
+..
+.nr fZ 0
+.de Ft
+.if \\n(nS>0 \{\
+.	if \\n(fZ>0 \{\
+.		Pp
+.		nr fD 0
+.		nr fX 0
+.	\}
+.	if \\n(fD>0 \{\
+.		Pp
+.		nr fD 0
+.		nr fX 0
+.	\}
+.	if \\n(fX>0 \{\
+.		Pp
+.		nr fX 0
+.	\}
+.	nr fY 1
+.\}
+.nr cF \\n(.f
+.nr cZ \\n(.s
+\&\\*(fT\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ft \\n(cF
+.fs \\n(cZ
+..
+.nr oT 0
+.de Ot
+.nr oT 1
+.if \\n(nS>0 \{\
+.	if \\n(fZ>0 \{\
+.		Pp
+.		nr fD 0
+.		nr fX 0
+.	\}
+.	if \\n(fD>0 \{\
+.		Pp
+.		nr fD 0
+.		nr fX 0
+.	\}
+.	if \\n(fX>0 \{\
+.		Pp
+.		nr fX 0
+.	\}
+.	nr fY 1
+.\}
+.if \\n(.$==4 .as b1 \&\\*(fT\&\\$1 \\$2 \\$3 \\$4
+.if \\n(.$==3 .as b1 \&\\*(fT\&\\$1 \\$2 \\$3
+.if \\n(.$==2 .as b1 \&\\*(fT\&\\$1 \\$2
+.if \\n(.$==1 .as b1 \&\\*(fT\&\\$1
+.as b1 \&\ \fP
+..
+.de Fa
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .Fa Function Arguments ... \\*(Pu (#\\n(.c)
+.       el \{\
+.		ds mN Fa
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.ie \\n(fC>0 \{\
+.	fC
+.\}
+.el \{\
+.	if \\n(aC>\\n(aP \{\
+.		as b1 \\*(fA
+.		nr aP \\n(aP+1
+.		nr cF \\n(.f
+.		nr cZ \\n(.s
+.		nR
+.		if \\n(nS>0 \{\
+.			if \\n(fZ>0 .br
+.		\}
+.	\}
+.\}
+..
+.de fC
+.ie \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.		ds Fb
+.		nr fB 0
+.		nr Fb 0
+.		fB \\*(A\\n(aP
+.		if \\n(fB>1 \{\
+.			rm A\\n(aP
+.			rn Fb A\\n(aP
+.		\}
+.	if \\n(fC>1 \{\
+.		as b1 \&\f\\n(cF\s\\n(cZ,\\*(S\\n(aP\\*(fA\\*(A\\n(aP\fP\s0
+.	\}
+.	if \\n(fC==1 \{\
+.		as b1 \&\|\\*(fA\\*(A\\n(aP\fP\s0
+.	\}
+.	nr fC \\n(fC+1
+.	fC
+.\}
+.el  \{\
+.	aY
+.\}
+..
+.de Fn
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 .tm Usage: .Fn function_name function_arg(s) ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN Fn
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(nS>0 \{\
+.	if \\n(fY==0 \{\
+.		if \\n(fZ>0 \{\
+.			Pp
+.			nr fX 0
+.			nr fD 0
+.		\}
+.	\}
+.	if \\n(fY==1 \{\
+.		br
+.		nr fX 0
+.		nr fD 0
+.		nr fY 0
+.	\}
+.	if \\n(fD>0 \{\
+.		Pp
+.		nr fX 0
+.	\}
+.	if \\n(fX>0 \{\
+.		Pp
+.		nr fD 0
+.	\}
+.	nr fZ \\n(fZ+1
+.	nr fY 0
+.	rs
+.	ie \\n(nS>1 .br
+.	el \{\
+.		if \\n(iS==0 \{\
+.			nr iS ((8)*\\n(fW)u
+.		\}
+.	\}
+.	in +\\n(iSu
+.	ti -\\n(iSu
+.	nr nS \\n(nS+1
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.	nr cF \\n(.f
+.	nr cZ \\n(.s
+.	as b1 \\*(fN\\*(A\\n(aP\fP\s0\\*(lp
+.	ie \\n(aC>\\n(aP \{\
+.		as b1 \\*(fA
+.		nr aP \\n(aP+1
+.		f\\n(C\\n(aP
+.	\}
+.	el \{\
+.		as b1 \|\\*(rp
+.		aZ
+.	\}
+.	if \\n(nS>0 \{\
+. 		in -\\n(iSu
+.	\}
+.\}
+..
+.de f1
+.as b1 \\*(rp\f\\n(cF\s\\n(cZ
+.\\*(A\\n(aP
+..
+.de f2
+.if \\n(nS>0 \{\
+.	ds Fb
+.	nr fB 0
+.	nr Fb 0
+.	fB \\*(A\\n(aP
+.	if \\n(fB>1 \{\
+.		rm A\\n(aP
+.		rn Fb A\\n(aP
+.	\}
+.\}
+.as b1 \\*(A\\n(aP
+.ie \\n(aC>\\n(aP \{\
+.	nr aa \\n(aP
+.	nr aP \\n(aP+1
+.	if \\n(C\\n(aP==2 \{\
+.		as b1 \&\|\f\\n(cF\s\\n(cZ,\\*(S\\n(aa\fP\s0\|
+.	\}
+.	f\\n(C\\n(aP
+.\}
+.el  \{\
+.	as b1 \\*(rp\f\\n(cF\s\\n(cZ
+.	aZ
+.\}
+..
+.de f3
+.as b1 \\*(rp\f\\n(cF\s\\n(cZ\\*(A\\n(aP
+.ie \\n(aC>\\n(aP \{\
+.	No
+.\}
+.el .aZ
+..
+.de f4
+.as b1 \\*(rp\f\\n(cF\s\\n(cZ\\*(S\\n(aP\\*(A\\n(aP
+.ie \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.	No
+.\}
+.el .aZ
+..
+.de Fo
+.hy 0
+.if \\n(aC==0 \{\
+.	ie \\n(.$==0 .tm Usage: .Fo function_name
+.	el \{\
+.		ds mN Fo
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(nS>0 \{\
+.	if \\n(fY==0 \{\
+.		if \\n(fZ>0 \{\
+.			Pp
+.			nr fX 0
+.			nr fD 0
+.		\}
+.	\}
+.	if \\n(fY==1 \{\
+.		br
+.		nr fX 0
+.		nr fD 0
+.		nr fY 0
+.	\}
+.	if \\n(fD>0 \{\
+.		Pp
+.		nr fX 0
+.	\}
+.	if \\n(fX>0 \{\
+.		Pp
+.		nr fD 0
+.	\}
+.	nr fZ \\n(fZ+1
+.	nr fY 0
+.	rs
+.	ie \\n(nS>1 .br
+.	el \{\
+.		if \\n(iS==0 \{\
+.			nr iS ((8)*\\n(fW)u
+.		\}
+.	\}
+.	in +\\n(iSu
+.	ti -\\n(iSu
+.	nr nS \\n(nS+1
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr oM \\n(oM+1
+.	nr fC 1
+.	nr aP \\n(aP+1
+.	nr cF \\n(.f
+.	nr cZ \\n(.s
+.	as b1 \\*(fN\\*(A\\n(aP\fP\s0\\*(lp
+.	aY
+.\}
+..
+.de Fc
+.if \\n(aC==0 \{\
+.	if \\n(.$>0 \{\
+.		ds mN Fo
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.nr fC 0
+.nr oM \\n(oM-1
+.as b1 \|\\*(rp
+.ie \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.	\\*(A\\n(aP
+.\}
+.el \{\
+.	aZ
+.\}
+.if \\n(nS>0 \{\
+.	in -\\n(iSu
+.\}
+.hy
+..
+.de fB
+.if \\n(fB==0 \{\
+.	nr fB \\n(.$
+.	nr Fb 0
+.	ds Fb
+.\}
+.nr Fb \\n(Fb+1
+.as Fb \&\\$1
+.if \\n(Fb<\\n(fB \{\
+.	as Fb \&\\*(hV
+.	fB \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+..
+.de Rs
+.nr rS 1
+.rC
+.if \\n(nA==1 .Pp
+.nr Kl 0
+..
+.de Re
+.rZ
+.rC
+.nr rS 0
+..
+.de rC
+.nr uK 0
+.nr jK 0
+.nr nK 0
+.nr oK 0
+.nr qK 0
+.nr rK 0
+.nr tK 0
+.nr vK 0
+.nr dK 0
+.nr pK 0
+.nr bK 0
+.ds rS
+.rm U1 U2 U3 U4 U5 U6 U7 U8
+.rm uK jK nK oK rK qK tK vK dK pK bK
+..
+.de rZ
+.if \\n(uK \{\&\\*(U1,
+.	nr aK 1
+.	if (\\n(uK>1 \{\
+.		aK
+.	\}
+.	nr Kl -\\n(uK
+.\}
+.if \\n(tK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \{\
+.		ie (\\n(jK==1):(\\n(bK==1) \{\&\\*q\\*(tK\\*q.
+.		\}
+.		el \{\&\\*(eM\\*(tK\\*(nO.
+.		\}
+.	\}
+.	if \\n(Kl>0 \{\
+.		ie (\\n(jK==1):(\\n(bK==1) \{\&\\*q\\*(tK\\*q,
+.		\}
+.		el \{\&\\*(eM\\*(tK\\*(nO,
+.		\}
+.	\}
+.\}
+.if \\n(bK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(eM\\*(bK\\*(nO.
+.	if \\n(Kl>0 \&\\*(eM\\*(bK\\*(nO,
+.\}
+.if \\n(jK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(eM\\*(jK\\*(nO.
+.	if \\n(Kl>0 \&\\*(eM\\*(jK\\*(nO,
+.\}
+.if \\n(rK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(rK.
+.	if \\n(Kl>0 \&\\*(rK,
+.\}
+.if \\n(nK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(nK.
+.	if \\n(Kl>0 \&\\*(nK,
+.\}
+.if \\n(vK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(vK.
+.	if \\n(Kl>0 \&\\*(vK,
+.\}
+.if \\n(pK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(pK.
+.	if \\n(Kl>0 \&\\*(pK,
+.\}
+.if \\n(qK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(qK.
+.	if \\n(Kl>0 \&\\*(qK,
+.\}
+.if \\n(dK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(dK.
+.	if \\n(Kl>0 \&\\*(dK,
+.\}
+.if \\n(oK \{\
+.	nr Kl \\n(Kl-1
+.	if \\n(Kl==0 \&\\*(oK.
+.	if \\n(Kl>0 \&\\*(oK,
+.\}
+.if \\n(Kl>0 .tm unresolved reference problem
+..
+.de aK
+.nr aK \\n(aK+1
+.ie (\\n(uK-\\n(aK)==0 \{\&and \\*(U\\n(aK,
+.\}
+.el \{\&\\*(U\\n(aK,
+.	aK
+.\}
+..
+.de %A
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%A Author_name (#\\n(.c)
+.	el \{\
+.		nr uK \\n(uK+1
+.		nr Kl \\n(Kl+1
+.		ds rS U\\n(uK
+.		ds mN %A
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %B
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%B Book Name (#\\n(.c)
+.       el \{\
+.		ds mN %B
+.		if \\n(rS>0 \{\
+.			nr bK \\n(bK+1
+.			nr Kl \\n(Kl+1
+.			ds rS bK
+.		\}
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.	ie \\n(rS==0 \{\
+.		as b1 \&\\*(eM
+.		nR
+.	\}
+.	el .rR
+.\}
+..
+.de %D
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%D Date (#\\n(.c)
+.       el \{\
+.		ds mN %D
+.		nr dK \\n(dK+1
+.		nr Kl \\n(Kl+1
+.		ds rS dK
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %J
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%J Journal Name (#\\n(.c)
+.       el \{\
+.		ds mN %J
+.		nr jK \\n(jK+1
+.		ds rS jK
+.		nr Kl \\n(Kl+1
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %N
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%N issue number (#\\n(.c)
+.	el \{\
+.		nr nK \\n(nK+1
+.		nr Kl \\n(Kl+1
+.		ds rS nK
+.		ds mN %N
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %O
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%O optional information ... \\*(Pu (#\\n(.c)
+.       el \{\
+.		ds mN %O
+.		nr oK \\n(oK+1
+.		nr Kl \\n(Kl+1
+.		ds rS oK
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %P
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%P page numbers ... \\*(Pu (#\\n(.c)
+.       el \{\
+.		ds mN %P
+.		nr pK \\n(pK+1
+.		nr Kl \\n(Kl+1
+.		ds rS pK
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %Q
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%Q Corporate or Foreign Author (#\\n(.c)
+.       el \{\
+.		ds mN %Q
+.		nr qK \\n(qK+1
+.		nr Kl \\n(Kl+1
+.		ds rS qK
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %R
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%R reference report (#\\n(.c)
+.       el \{\
+.		ds mN %R
+.		nr rK \\n(rK+1
+.		nr Kl \\n(Kl+1
+.		ds rS rK
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de %T
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%T (#\\n(.c)
+.       el \{\
+.		ds mN %T
+.		if \\n(rS>0 \{\
+.			nr tK \\n(tK+1
+.			nr Kl \\n(Kl+1
+.			ds rS tK
+.		\}
+.               ds A1 \\$1
+.               ds A2 \\$2
+.               ds A3 \\$3
+.               ds A4 \\$4
+.               ds A5 \\$5
+.               ds A6 \\$6
+.               ds A7 \\$7
+.               ds A8 \\$8
+.               ds A9 \\$9
+.		nr fV \\n(.$
+.		fV
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.		nr aP \\n(aP+1
+.		nr cF \\n(.f
+.		nr cZ \\n(.s
+.		ie \\n(rS==0 \{\
+.			as b1 \&\\*(eM
+.			nR
+.		\}
+.		el .rR
+.\}
+..
+.de %V
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .%V Volume , ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN %V
+.		nr vK \\n(vK+1
+.		nr Kl \\n(Kl+1
+.		ds rS vK
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       rR
+.\}
+..
+.de rR
+.hy 0
+.nr jM \\n(C\\n(aP
+.ie \\n(jM==1 \{\
+.	ie "\\*(A\\n(aP"Tn" \{\
+.		nN
+.	\}
+.	el \{\
+.		if \\n(aC>8 .tm Usage: \\*(mN - maximum 8 arguments (#\\n(.c)
+.		aI rR 1
+.		\\*(A\\n(aP
+.	\}
+.\}
+.el \{\
+.	nr jN \\n(aP
+.	ie \\n(jM==2 .as b1 \&\\*(A\\n(aP
+.	el .as b1 \&\\*(A\\n(aP
+.	ie \\n(aC==\\n(aP \{\
+.		rD
+.	\}
+.	el \{\
+.		nr aP \\n(aP+1
+.		as b1 \&\\*(S\\n(jN
+.		rR
+.	\}
+.\}
+.rr jM jN
+..
+.de rD
+.as \\*(rS \\*(b1
+.ds b1
+.ds rS
+.aY
+..
+.de Hf
+.Pp
+File:
+.Pa \\$1
+.Pp
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ie t \{\
+\&\\*(lI
+.br
+.ta +9n 18n 27n 36n 45n 54n 63n 72n
+.\}
+.el \{\
+.ta +8n 16n 24n 32n 40n 48n 56n 64n 72n
+.\}
+.nf
+.so  \\$1
+.fi
+.ft \\n(cF
+.fz \\n(cZ
+.Pp
+..
+.nr aN 0
+.de An
+.if \\n(nY==1 \{\
+.	ie \\n(aN==1 \{\
+.		br
+.	\}
+.	el \{\
+.		nr aN 1
+.	\}
+.\}
+.if \\n(aC==0 \{\
+.       ie \\n(.$==0 .tm Usage: .An author_name ... \\*(Pu (#\\n(.c)
+.	el \{\
+.		ds mN An
+.		aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.	\}
+.\}
+.if \\n(aC>\\n(aP \{\
+.	nr aP \\n(aP+1
+.       nr cF \\n(.f
+.	nr cZ \\n(.s
+.       nR
+.\}
+..
+.de Sf
+.tm .Sf defunct, use prefix or Ns
+..
+.ds rV "function returns the value 0 if successful; otherwise the value -1 is returned and the global variable \\*(vAerrno\fP is set to indicate the error.
+.de Rv
+.ie \\n(.$==0 \{\
+.tm Usage: .Rv [-std] (#\\n(.c)
+.\}
+.el \{\
+.	ds mN Rv
+.	if "\\$1"-std" \{\
+.	nr cH \\*(cH
+.	if (\\n(cH<2):(\\n(cH>3) .tm Usage: .Rv -std sections 2 and 3 only
+.		br
+\&The
+.Fn \\$2
+\&\\*(rV
+.	\}
+.\}
+..
diff --git a/krb5-1-6/src/appl/telnet/telnet/tn3270.c b/krb5-1-6/src/appl/telnet/telnet/tn3270.c
new file mode 100644
index 000000000..c46ae7eb8
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/tn3270.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)tn3270.c	8.1 (Berkeley) 6/6/93 */
+
+#include <sys/types.h>
+#include <arpa/telnet.h>
+
+#include "general.h"
+
+#include "defines.h"
+#include "ring.h"
+#include "externs.h"
+#include "fdset.h"
+
+#if	defined(TN3270)
+
+#include "../ctlr/screen.h"
+#include "../general/globals.h"
+
+#include "../sys_curses/telextrn.h"
+#include "../ctlr/externs.h"
+
+#if	defined(unix)
+int
+	HaveInput,		/* There is input available to scan */
+	cursesdata,		/* Do we dump curses data? */
+	sigiocount;		/* Number of times we got a SIGIO */
+
+char	tline[200];
+char	*transcom = 0;	/* transparent mode command (default: none) */
+#endif	/* defined(unix) */
+
+char	Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
+
+static char	sb_terminal[] = { IAC, SB,
+			TELOPT_TTYPE, TELQUAL_IS,
+			'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
+			IAC, SE };
+#define	SBTERMMODEL	13
+
+static int
+	Sent3270TerminalType;	/* Have we said we are a 3270? */
+
+#endif	/* defined(TN3270) */
+
+
+    void
+init_3270()
+{
+#if	defined(TN3270)
+#if	defined(unix)
+    HaveInput = 0;
+    sigiocount = 0;
+#endif	/* defined(unix) */
+    Sent3270TerminalType = 0;
+    Ifrontp = Ibackp = Ibuf;
+    init_ctlr();		/* Initialize some things */
+    init_keyboard();
+    init_screen();
+    init_system();
+#endif	/* defined(TN3270) */
+}
+
+
+#if	defined(TN3270)
+
+/*
+ * DataToNetwork - queue up some data to go to network.  If "done" is set,
+ * then when last byte is queued, we add on an IAC EOR sequence (so,
+ * don't call us with "done" until you want that done...)
+ *
+ * We actually do send all the data to the network buffer, since our
+ * only client needs for us to do that.
+ */
+
+    int
+DataToNetwork(buffer, count, done)
+    register char *buffer;	/* where the data is */
+    register int  count;	/* how much to send */
+    int		  done;		/* is this the last of a logical block */
+{
+    register int loop, c;
+    int origCount;
+
+    origCount = count;
+
+    while (count) {
+	/* If not enough room for EORs, IACs, etc., wait */
+	if (NETROOM() < 6) {
+	    fd_set o;
+
+	    FD_ZERO(&o);
+	    netflush();
+	    while (NETROOM() < 6) {
+		FD_SET(net, &o);
+		(void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
+						(struct timeval *) 0);
+		netflush();
+	    }
+	}
+	c = ring_empty_count(&netoring);
+	if (c > count) {
+	    c = count;
+	}
+	loop = c;
+	while (loop) {
+	    if (((unsigned char)*buffer) == IAC) {
+		break;
+	    }
+	    buffer++;
+	    loop--;
+	}
+	if ((c = c-loop)) {
+	    ring_supply_data(&netoring, buffer-c, c);
+	    count -= c;
+	}
+	if (loop) {
+	    NET2ADD(IAC, IAC);
+	    count--;
+	    buffer++;
+	}
+    }
+
+    if (done) {
+	NET2ADD(IAC, EOR);
+	netflush();		/* try to move along as quickly as ... */
+    }
+    return(origCount - count);
+}
+
+
+#if	defined(unix)
+    void
+inputAvailable(signo)
+	int signo;
+{
+    HaveInput = 1;
+    sigiocount++;
+}
+#endif	/* defined(unix) */
+
+    void
+outputPurge()
+{
+    (void) ttyflush(1);
+}
+
+
+/*
+ * The following routines are places where the various tn3270
+ * routines make calls into telnet.c.
+ */
+
+/*
+ * DataToTerminal - queue up some data to go to terminal.
+ *
+ * Note: there are people who call us and depend on our processing
+ * *all* the data at one time (thus the select).
+ */
+
+    int
+DataToTerminal(buffer, count)
+    register char	*buffer;		/* where the data is */
+    register int	count;			/* how much to send */
+{
+    register int c;
+    int origCount;
+
+    origCount = count;
+
+    while (count) {
+	if (TTYROOM() == 0) {
+#if	defined(unix)
+	    fd_set o;
+
+	    FD_ZERO(&o);
+#endif	/* defined(unix) */
+	    (void) ttyflush(0);
+	    while (TTYROOM() == 0) {
+#if	defined(unix)
+		FD_SET(tout, &o);
+		(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
+						(struct timeval *) 0);
+#endif	/* defined(unix) */
+		(void) ttyflush(0);
+	    }
+	}
+	c = TTYROOM();
+	if (c > count) {
+	    c = count;
+	}
+	ring_supply_data(&ttyoring, buffer, c);
+	count -= c;
+	buffer += c;
+    }
+    return(origCount);
+}
+
+
+/*
+ * Push3270 - Try to send data along the 3270 output (to screen) direction.
+ */
+
+    int
+Push3270()
+{
+    int save = ring_full_count(&netiring);
+
+    if (save) {
+	if (Ifrontp+save > Ibuf+sizeof Ibuf) {
+	    if (Ibackp != Ibuf) {
+		memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
+		Ifrontp -= (Ibackp-Ibuf);
+		Ibackp = Ibuf;
+	    }
+	}
+	if (Ifrontp+save < Ibuf+sizeof Ibuf) {
+	    (void)telrcv();
+	}
+    }
+    return save != ring_full_count(&netiring);
+}
+
+
+/*
+ * Finish3270 - get the last dregs of 3270 data out to the terminal
+ *		before quitting.
+ */
+
+    void
+Finish3270()
+{
+    while (Push3270() || !DoTerminalOutput()) {
+#if	defined(unix)
+	HaveInput = 0;
+#endif	/* defined(unix) */
+	;
+    }
+}
+
+
+/* StringToTerminal - output a null terminated string to the terminal */
+
+    void
+StringToTerminal(s)
+    char *s;
+{
+    int count;
+
+    count = strlen(s);
+    if (count) {
+	(void) DataToTerminal(s, count);	/* we know it always goes... */
+    }
+}
+
+
+#if	((!defined(NOT43)) || defined(PUTCHAR))
+/* _putchar - output a single character to the terminal.  This name is so that
+ *	curses(3x) can call us to send out data.
+ */
+
+    void
+_putchar(c)
+    char c;
+{
+#if	defined(sun)		/* SunOS 4.0 bug */
+    c &= 0x7f;
+#endif	/* defined(sun) */
+    if (cursesdata) {
+	Dump('>', &c, 1);
+    }
+    if (!TTYROOM()) {
+	(void) DataToTerminal(&c, 1);
+    } else {
+	TTYADD(c);
+    }
+}
+#endif	/* ((!defined(NOT43)) || defined(PUTCHAR)) */
+
+    void
+SetIn3270()
+{
+    if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
+		&& my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
+	if (!In3270) {
+	    In3270 = 1;
+	    Init3270();		/* Initialize 3270 functions */
+	    /* initialize terminal key mapping */
+	    InitTerminal();	/* Start terminal going */
+	    setconnmode(0);
+	}
+    } else {
+	if (In3270) {
+	    StopScreen(1);
+	    In3270 = 0;
+	    Stop3270();		/* Tell 3270 we aren't here anymore */
+	    setconnmode(0);
+	}
+    }
+}
+
+/*
+ * tn3270_ttype()
+ *
+ *	Send a response to a terminal type negotiation.
+ *
+ *	Return '0' if no more responses to send; '1' if a response sent.
+ */
+
+    int
+tn3270_ttype()
+{
+    /*
+     * Try to send a 3270 type terminal name.  Decide which one based
+     * on the format of our screen, and (in the future) color
+     * capaiblities.
+     */
+    InitTerminal();		/* Sets MaxNumberColumns, MaxNumberLines */
+    if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
+	Sent3270TerminalType = 1;
+	if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
+	    MaxNumberLines = 27;
+	    MaxNumberColumns = 132;
+	    sb_terminal[SBTERMMODEL] = '5';
+	} else if (MaxNumberLines >= 43) {
+	    MaxNumberLines = 43;
+	    MaxNumberColumns = 80;
+	    sb_terminal[SBTERMMODEL] = '4';
+	} else if (MaxNumberLines >= 32) {
+	    MaxNumberLines = 32;
+	    MaxNumberColumns = 80;
+	    sb_terminal[SBTERMMODEL] = '3';
+	} else {
+	    MaxNumberLines = 24;
+	    MaxNumberColumns = 80;
+	    sb_terminal[SBTERMMODEL] = '2';
+	}
+	NumberLines = 24;		/* before we start out... */
+	NumberColumns = 80;
+	ScreenSize = NumberLines*NumberColumns;
+	if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
+	    ExitString("Programming error:  MAXSCREENSIZE too small.\n",
+								1);
+	    /*NOTREACHED*/
+	}
+	printsub('>', sb_terminal+2, sizeof sb_terminal-2);
+	ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
+	return 1;
+    } else {
+	return 0;
+    }
+}
+
+#if	defined(unix)
+	int
+settranscom(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int i;
+
+	if (argc == 1 && transcom) {
+	   transcom = 0;
+	}
+	if (argc == 1) {
+	   return 1;
+	}
+	transcom = tline;
+	(void) strncpy(transcom, argv[1], sizeof(tline) - 1);
+	tline[sizeof(tline) - 1] = '\0';
+	for (i = 2; i < argc; ++i) {
+	    (void) strncat(transcom, " ", sizeof(tline) - 1 - (transcom - tline));
+	    (void) strncat(transcom, argv[i], sizeof(tline) - 1 - (transcom - tline));
+	}
+	return 1;
+}
+#endif	/* defined(unix) */
+
+#endif	/* defined(TN3270) */
diff --git a/krb5-1-6/src/appl/telnet/telnet/types.h b/krb5-1-6/src/appl/telnet/telnet/types.h
new file mode 100644
index 000000000..191d311fd
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/types.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)types.h	8.1 (Berkeley) 6/6/93
+ */
+
+typedef struct {
+    char *modedescriptions;
+    char modetype;
+} Modelist;
+
+extern Modelist modelist[];
+
+typedef struct {
+    int
+	system,			/* what the current time is */
+	echotoggle,		/* last time user entered echo character */
+	modenegotiated,		/* last time operating mode negotiated */
+	didnetreceive,		/* last time we read data from network */
+	gotDM;			/* when did we last see a data mark */
+} Clocks;
+
+extern Clocks clocks;
diff --git a/krb5-1-6/src/appl/telnet/telnet/utilities.c b/krb5-1-6/src/appl/telnet/telnet/utilities.c
new file mode 100644
index 000000000..4b198dabf
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnet/utilities.c
@@ -0,0 +1,949 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)utilities.c	8.1 (Berkeley) 6/6/93 */
+
+#define	TELOPTS
+#define	TELCMDS
+#define	SLC_NAMES
+#include <arpa/telnet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+
+#include "general.h"
+
+#include "fdset.h"
+
+#include "ring.h"
+
+#include "defines.h"
+
+#include "externs.h"
+
+#ifdef AUTHENTICATION
+#include <libtelnet/auth.h>
+#endif
+
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+FILE	*NetTrace = 0;		/* Not in bss, since needs to stay */
+int	prettydump;
+
+/*
+ * upcase()
+ *
+ *	Upcase (in place) the argument.
+ */
+
+    void
+upcase(argument)
+    register char *argument;
+{
+    register int c;
+
+    while ((c = *argument) != 0) {
+	if (islower(c)) {
+	    *argument = toupper(c);
+	}
+	argument++;
+    }
+}
+
+/*
+ * SetSockOpt()
+ *
+ * Compensate for differences in 4.2 and 4.3 systems.
+ */
+
+    int
+SetSockOpt(fd, level, option, yesno)
+    int fd, level, option, yesno;
+{
+#ifndef	NOT43
+    return setsockopt(fd, level, option,
+				(char *)&yesno, sizeof yesno);
+#else	/* NOT43 */
+    if (yesno == 0) {		/* Can't do that in 4.2! */
+	fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
+				option);
+	return -1;
+    }
+    return setsockopt(fd, level, option, 0, 0);
+#endif	/* NOT43 */
+}
+
+/*
+ * The following are routines used to print out debugging information.
+ */
+
+unsigned char NetTraceFile[256] = "(standard output)";
+
+    void
+SetNetTrace(file)
+    register char *file;
+{
+    if (NetTrace && NetTrace != stdout)
+	fclose(NetTrace);
+    if (file  && (strcmp(file, "-") != 0)) {
+	NetTrace = fopen(file, "w");
+	if (NetTrace) {
+	    strncpy((char *)NetTraceFile, file, sizeof(NetTraceFile) - 1);
+	    NetTraceFile[sizeof(NetTraceFile) - 1] = '\0';
+	    return;
+	}
+	fprintf(stderr, "Cannot open %s.\n", file);
+    }
+    NetTrace = stdout;
+    strncpy((char *)NetTraceFile, "(standard output)", sizeof(NetTraceFile) - 1);
+    NetTraceFile[sizeof(NetTraceFile) - 1] = '\0';
+}
+
+    void
+Dump(direction, buffer, length)
+    char direction;
+    unsigned char *buffer;
+    int length;
+{
+#   define BYTES_PER_LINE	32
+#   define min(x,y)	((x<y)? x:y)
+    unsigned char *pThis;
+    int offset;
+
+    offset = 0;
+
+    while (length) {
+	/* print one line */
+	fprintf(NetTrace, "%c 0x%x\t", direction, offset);
+	pThis = buffer;
+	if (prettydump) {
+	    buffer = buffer + min(length, BYTES_PER_LINE/2);
+	    while (pThis < buffer) {
+		fprintf(NetTrace, "%c%.2x",
+		    (((*pThis)&0xff) == 0xff) ? '*' : ' ',
+		    (*pThis)&0xff);
+		pThis++;
+	    }
+	    length -= BYTES_PER_LINE/2;
+	    offset += BYTES_PER_LINE/2;
+	} else {
+	    buffer = buffer + min(length, BYTES_PER_LINE);
+	    while (pThis < buffer) {
+		fprintf(NetTrace, "%.2x", (*pThis)&0xff);
+		pThis++;
+	    }
+	    length -= BYTES_PER_LINE;
+	    offset += BYTES_PER_LINE;
+	}
+	if (NetTrace == stdout) {
+	    fprintf(NetTrace, "\r\n");
+	} else {
+	    fprintf(NetTrace, "\n");
+	}
+	if (length < 0) {
+	    fflush(NetTrace);
+	    return;
+	}
+	/* find next unique line */
+    }
+    fflush(NetTrace);
+}
+
+
+	void
+printoption(direction, cmd, option)
+	char *direction;
+	int cmd, option;
+{
+	if (!showoptions)
+		return;
+	if (cmd == IAC) {
+		if (TELCMD_OK(option))
+		    fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
+		else
+		    fprintf(NetTrace, "%s IAC %d", direction, option);
+	} else {
+		register char *fmt;
+		fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
+			(cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
+		if (fmt) {
+		    fprintf(NetTrace, "%s %s ", direction, fmt);
+		    if (TELOPT_OK(option))
+			fprintf(NetTrace, "%s", TELOPT(option));
+		    else if (option == TELOPT_EXOPL)
+			fprintf(NetTrace, "EXOPL");
+		    else
+			fprintf(NetTrace, "%d", option);
+		} else
+		    fprintf(NetTrace, "%s %d %d", direction, cmd, option);
+	}
+	if (NetTrace == stdout) {
+	    fprintf(NetTrace, "\r\n");
+	    fflush(NetTrace);
+	} else {
+	    fprintf(NetTrace, "\n");
+	}
+	return;
+}
+
+    void
+optionstatus()
+{
+    register int i;
+    extern char will_wont_resp[], do_dont_resp[];
+
+    for (i = 0; i < 256; i++) {
+	if (do_dont_resp[i]) {
+	    if (TELOPT_OK(i))
+		printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
+	    else if (TELCMD_OK(i))
+		printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
+	    else
+		printf("resp DO_DONT %d: %d\n", i,
+				do_dont_resp[i]);
+	    if (my_want_state_is_do(i)) {
+		if (TELOPT_OK(i))
+		    printf("want DO   %s\n", TELOPT(i));
+		else if (TELCMD_OK(i))
+		    printf("want DO   %s\n", TELCMD(i));
+		else
+		    printf("want DO   %d\n", i);
+	    } else {
+		if (TELOPT_OK(i))
+		    printf("want DONT %s\n", TELOPT(i));
+		else if (TELCMD_OK(i))
+		    printf("want DONT %s\n", TELCMD(i));
+		else
+		    printf("want DONT %d\n", i);
+	    }
+	} else {
+	    if (my_state_is_do(i)) {
+		if (TELOPT_OK(i))
+		    printf("     DO   %s\n", TELOPT(i));
+		else if (TELCMD_OK(i))
+		    printf("     DO   %s\n", TELCMD(i));
+		else
+		    printf("     DO   %d\n", i);
+	    }
+	}
+	if (will_wont_resp[i]) {
+	    if (TELOPT_OK(i))
+		printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
+	    else if (TELCMD_OK(i))
+		printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
+	    else
+		printf("resp WILL_WONT %d: %d\n",
+				i, will_wont_resp[i]);
+	    if (my_want_state_is_will(i)) {
+		if (TELOPT_OK(i))
+		    printf("want WILL %s\n", TELOPT(i));
+		else if (TELCMD_OK(i))
+		    printf("want WILL %s\n", TELCMD(i));
+		else
+		    printf("want WILL %d\n", i);
+	    } else {
+		if (TELOPT_OK(i))
+		    printf("want WONT %s\n", TELOPT(i));
+		else if (TELCMD_OK(i))
+		    printf("want WONT %s\n", TELCMD(i));
+		else
+		    printf("want WONT %d\n", i);
+	    }
+	} else {
+	    if (my_state_is_will(i)) {
+		if (TELOPT_OK(i))
+		    printf("     WILL %s\n", TELOPT(i));
+		else if (TELCMD_OK(i))
+		    printf("     WILL %s\n", TELCMD(i));
+		else
+		    printf("     WILL %d\n", i);
+	    }
+	}
+    }
+
+}
+
+    void
+printsub(direction, pointer, length)
+    char direction;	/* '<' or '>' */
+    unsigned char *pointer;	/* where suboption data sits */
+    int		  length;	/* length of suboption data */
+{
+    register int i;
+    unsigned char buf[512];
+    extern int want_status_response;
+
+    if (showoptions || direction == 0 ||
+	(want_status_response && (pointer[0] == TELOPT_STATUS))) {
+	if (direction) {
+	    fprintf(NetTrace, "%s IAC SB ",
+				(direction == '<')? "RCVD":"SENT");
+	    if (length >= 3) {
+		register int j;
+
+		i = pointer[length-2];
+		j = pointer[length-1];
+
+		if (i != IAC || j != SE) {
+		    fprintf(NetTrace, "(terminated by ");
+		    if (TELOPT_OK(i))
+			fprintf(NetTrace, "%s ", TELOPT(i));
+		    else if (TELCMD_OK(i))
+			fprintf(NetTrace, "%s ", TELCMD(i));
+		    else
+			fprintf(NetTrace, "%d ", i);
+		    if (TELOPT_OK(j))
+			fprintf(NetTrace, "%s", TELOPT(j));
+		    else if (TELCMD_OK(j))
+			fprintf(NetTrace, "%s", TELCMD(j));
+		    else
+			fprintf(NetTrace, "%d", j);
+		    fprintf(NetTrace, ", not IAC SE!) ");
+		}
+	    }
+	    length -= 2;
+	}
+	if (length < 1) {
+	    fprintf(NetTrace, "(Empty suboption??\?)");
+	    if (NetTrace == stdout)
+		fflush(NetTrace);
+	    return;
+	}
+	switch (pointer[0]) {
+	case TELOPT_TTYPE:
+	    fprintf(NetTrace, "TERMINAL-TYPE ");
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+		break;
+	    case TELQUAL_SEND:
+		fprintf(NetTrace, "SEND");
+		break;
+	    default:
+		fprintf(NetTrace,
+				"- unknown qualifier %d (0x%x).",
+				pointer[1], pointer[1]);
+	    }
+	    break;
+	case TELOPT_TSPEED:
+	    fprintf(NetTrace, "TERMINAL-SPEED");
+	    if (length < 2) {
+		fprintf(NetTrace, " (empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		fprintf(NetTrace, " IS ");
+		fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
+		break;
+	    default:
+		if (pointer[1] == 1)
+		    fprintf(NetTrace, " SEND");
+		else
+		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
+		for (i = 2; i < length; i++)
+		    fprintf(NetTrace, " ?%d?", pointer[i]);
+		break;
+	    }
+	    break;
+
+	case TELOPT_LFLOW:
+	    fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
+	    if (length < 2) {
+		fprintf(NetTrace, " (empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case LFLOW_OFF:
+		fprintf(NetTrace, " OFF"); break;
+	    case LFLOW_ON:
+		fprintf(NetTrace, " ON"); break;
+	    case LFLOW_RESTART_ANY:
+		fprintf(NetTrace, " RESTART-ANY"); break;
+	    case LFLOW_RESTART_XON:
+		fprintf(NetTrace, " RESTART-XON"); break;
+	    default:
+		fprintf(NetTrace, " %d (unknown)", pointer[1]);
+	    }
+	    for (i = 2; i < length; i++)
+		fprintf(NetTrace, " ?%d?", pointer[i]);
+	    break;
+
+	case TELOPT_NAWS:
+	    fprintf(NetTrace, "NAWS");
+	    if (length < 2) {
+		fprintf(NetTrace, " (empty suboption??\?)");
+		break;
+	    }
+	    if (length == 2) {
+		fprintf(NetTrace, " ?%d?", pointer[1]);
+		break;
+	    }
+	    fprintf(NetTrace, " %d %d (%d)",
+		pointer[1], pointer[2],
+		(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
+	    if (length == 4) {
+		fprintf(NetTrace, " ?%d?", pointer[3]);
+		break;
+	    }
+	    fprintf(NetTrace, " %d %d (%d)",
+		pointer[3], pointer[4],
+		(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
+	    for (i = 5; i < length; i++)
+		fprintf(NetTrace, " ?%d?", pointer[i]);
+	    break;
+
+#if	defined(AUTHENTICATION)
+	case TELOPT_AUTHENTICATION:
+	    fprintf(NetTrace, "AUTHENTICATION");
+	    if (length < 2) {
+		fprintf(NetTrace, " (empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case TELQUAL_REPLY:
+	    case TELQUAL_IS:
+		fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
+							"IS" : "REPLY");
+		if (AUTHTYPE_NAME_OK(pointer[2]))
+		    fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
+		else
+		    fprintf(NetTrace, "%d ", pointer[2]);
+		if (length < 3) {
+		    fprintf(NetTrace, "(partial suboption??\?)");
+		    break;
+		}
+		fprintf(NetTrace, "%s|%s%s",
+			((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+			"CLIENT" : "SERVER",
+			((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+			"MUTUAL" : "ONE-WAY",
+			((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON) ?
+			"|ENCRYPT" : "");
+		auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+		fprintf(NetTrace, "%s", buf);
+		break;
+
+	    case TELQUAL_SEND:
+		i = 2;
+		fprintf(NetTrace, " SEND ");
+		while (i < length) {
+		    if (AUTHTYPE_NAME_OK(pointer[i]))
+			fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
+		    else
+			fprintf(NetTrace, "%d ", pointer[i]);
+		    if (++i >= length) {
+			fprintf(NetTrace, "(partial suboption??\?)");
+			break;
+		    }
+		    fprintf(NetTrace, "%s|%s%s ",
+			((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+							"CLIENT" : "SERVER",
+			((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+							"MUTUAL" : "ONE-WAY",
+			((pointer[i] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON) ?
+							"|ENCRYPT" : "");
+		    ++i;
+		}
+		break;
+
+	    case TELQUAL_NAME:
+		i = 2;
+		fprintf(NetTrace, " NAME \"");
+		while (i < length)
+		    putc(pointer[i++], NetTrace);
+		putc('"', NetTrace);
+		break;
+
+	    default:
+		    for (i = 2; i < length; i++)
+			fprintf(NetTrace, " ?%d?", pointer[i]);
+		    break;
+	    }
+	    break;
+#endif
+
+#ifdef	ENCRYPTION
+	case TELOPT_ENCRYPT:
+	    fprintf(NetTrace, "ENCRYPT");
+	    if (length < 2) {
+		fprintf(NetTrace, " (empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case ENCRYPT_START:
+		fprintf(NetTrace, " START");
+		break;
+
+	    case ENCRYPT_END:
+		fprintf(NetTrace, " END");
+		break;
+
+	    case ENCRYPT_REQSTART:
+		fprintf(NetTrace, " REQUEST-START");
+		break;
+
+	    case ENCRYPT_REQEND:
+		fprintf(NetTrace, " REQUEST-END");
+		break;
+
+	    case ENCRYPT_IS:
+	    case ENCRYPT_REPLY:
+		fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
+							"IS" : "REPLY");
+		if (length < 3) {
+		    fprintf(NetTrace, " (partial suboption??\?)");
+		    break;
+		}
+		if (ENCTYPE_NAME_OK(pointer[2]))
+		    fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
+		else
+		    fprintf(NetTrace, " %d (unknown)", pointer[2]);
+
+		encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+		fprintf(NetTrace, "%s", buf);
+		break;
+
+	    case ENCRYPT_SUPPORT:
+		i = 2;
+		fprintf(NetTrace, " SUPPORT ");
+		while (i < length) {
+		    if (ENCTYPE_NAME_OK(pointer[i]))
+			fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
+		    else
+			fprintf(NetTrace, "%d ", pointer[i]);
+		    i++;
+		}
+		break;
+
+	    case ENCRYPT_ENC_KEYID:
+		fprintf(NetTrace, " ENC_KEYID ");
+		goto encommon;
+
+	    case ENCRYPT_DEC_KEYID:
+		fprintf(NetTrace, " DEC_KEYID ");
+		goto encommon;
+
+	    default:
+		fprintf(NetTrace, " %d (unknown)", pointer[1]);
+	    encommon:
+		for (i = 2; i < length; i++)
+		    fprintf(NetTrace, " %d", pointer[i]);
+		break;
+	    }
+	    break;
+#endif	/* ENCRYPTION */
+
+	case TELOPT_LINEMODE:
+	    fprintf(NetTrace, "LINEMODE ");
+	    if (length < 2) {
+		fprintf(NetTrace, " (empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case WILL:
+		fprintf(NetTrace, "WILL ");
+		goto common;
+	    case WONT:
+		fprintf(NetTrace, "WONT ");
+		goto common;
+	    case DO:
+		fprintf(NetTrace, "DO ");
+		goto common;
+	    case DONT:
+		fprintf(NetTrace, "DONT ");
+	    common:
+		if (length < 3) {
+		    fprintf(NetTrace, "(no option??\?)");
+		    break;
+		}
+		switch (pointer[2]) {
+		case LM_FORWARDMASK:
+		    fprintf(NetTrace, "Forward Mask");
+		    for (i = 3; i < length; i++)
+			fprintf(NetTrace, " %x", pointer[i]);
+		    break;
+		default:
+		    fprintf(NetTrace, "%d (unknown)", pointer[2]);
+		    for (i = 3; i < length; i++)
+			fprintf(NetTrace, " %d", pointer[i]);
+		    break;
+		}
+		break;
+		
+	    case LM_SLC:
+		fprintf(NetTrace, "SLC");
+		for (i = 2; i < length - 2; i += 3) {
+		    if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
+			fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
+		    else
+			fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
+		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
+		    case SLC_NOSUPPORT:
+			fprintf(NetTrace, " NOSUPPORT"); break;
+		    case SLC_CANTCHANGE:
+			fprintf(NetTrace, " CANTCHANGE"); break;
+		    case SLC_VARIABLE:
+			fprintf(NetTrace, " VARIABLE"); break;
+		    case SLC_DEFAULT:
+			fprintf(NetTrace, " DEFAULT"); break;
+		    }
+		    fprintf(NetTrace, "%s%s%s",
+			pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
+			pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
+			pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
+		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
+						SLC_FLUSHOUT| SLC_LEVELBITS))
+			fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
+		    fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
+		    if ((pointer[i+SLC_VALUE] == IAC) &&
+			(pointer[i+SLC_VALUE+1] == IAC))
+				i++;
+		}
+		for (; i < length; i++)
+		    fprintf(NetTrace, " ?%d?", pointer[i]);
+		break;
+
+	    case LM_MODE:
+		fprintf(NetTrace, "MODE ");
+		if (length < 3) {
+		    fprintf(NetTrace, "(no mode??\?)");
+		    break;
+		}
+		{
+		    char tbuf[64];
+		    sprintf(tbuf, "%s%s%s%s%s",
+			pointer[2]&MODE_EDIT ? "|EDIT" : "",
+			pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
+			pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
+			pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
+			pointer[2]&MODE_ACK ? "|ACK" : "");
+		    fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
+		}
+		if (pointer[2]&~(MODE_MASK))
+		    fprintf(NetTrace, " (0x%x)", pointer[2]);
+		for (i = 3; i < length; i++)
+		    fprintf(NetTrace, " ?0x%x?", pointer[i]);
+		break;
+	    default:
+		fprintf(NetTrace, "%d (unknown)", pointer[1]);
+		for (i = 2; i < length; i++)
+		    fprintf(NetTrace, " %d", pointer[i]);
+	    }
+	    break;
+
+	case TELOPT_STATUS: {
+	    register char *cp;
+	    register int j, k;
+
+	    fprintf(NetTrace, "STATUS");
+
+	    switch (pointer[1]) {
+	    default:
+		if (pointer[1] == TELQUAL_SEND)
+		    fprintf(NetTrace, " SEND");
+		else
+		    fprintf(NetTrace, " %d (unknown)", pointer[1]);
+		for (i = 2; i < length; i++)
+		    fprintf(NetTrace, " ?%d?", pointer[i]);
+		break;
+	    case TELQUAL_IS:
+		if (--want_status_response < 0)
+		    want_status_response = 0;
+		if (NetTrace == stdout)
+		    fprintf(NetTrace, " IS\r\n");
+		else
+		    fprintf(NetTrace, " IS\n");
+
+		for (i = 2; i < length; i++) {
+		    switch(pointer[i]) {
+		    case DO:	cp = "DO"; goto common2;
+		    case DONT:	cp = "DONT"; goto common2;
+		    case WILL:	cp = "WILL"; goto common2;
+		    case WONT:	cp = "WONT"; goto common2;
+		    common2:
+			i++;
+			if (TELOPT_OK((int)pointer[i]))
+			    fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
+			else
+			    fprintf(NetTrace, " %s %d", cp, pointer[i]);
+
+			if (NetTrace == stdout)
+			    fprintf(NetTrace, "\r\n");
+			else
+			    fprintf(NetTrace, "\n");
+			break;
+
+		    case SB:
+			fprintf(NetTrace, " SB ");
+			i++;
+			j = k = i;
+			while (j < length) {
+			    if (pointer[j] == SE) {
+				if (j+1 == length)
+				    break;
+				if (pointer[j+1] == SE)
+				    j++;
+				else
+				    break;
+			    }
+			    pointer[k++] = pointer[j++];
+			}
+			printsub(0, &pointer[i], k - i);
+			if (i < length) {
+			    fprintf(NetTrace, " SE");
+			    i = j;
+			} else
+			    i = j - 1;
+
+			if (NetTrace == stdout)
+			    fprintf(NetTrace, "\r\n");
+			else
+			    fprintf(NetTrace, "\n");
+
+			break;
+				
+		    default:
+			fprintf(NetTrace, " %d", pointer[i]);
+			break;
+		    }
+		}
+		break;
+	    }
+	    break;
+	  }
+
+	case TELOPT_XDISPLOC:
+	    fprintf(NetTrace, "X-DISPLAY-LOCATION ");
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+		break;
+	    case TELQUAL_SEND:
+		fprintf(NetTrace, "SEND");
+		break;
+	    default:
+		fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
+				pointer[1], pointer[1]);
+	    }
+	    break;
+
+	case TELOPT_NEW_ENVIRON:
+	    fprintf(NetTrace, "NEW-ENVIRON ");
+#ifdef	OLD_ENVIRON
+	    goto env_common1;
+	case TELOPT_OLD_ENVIRON:
+	    fprintf(NetTrace, "OLD-ENVIRON");
+	env_common1:
+#endif
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		fprintf(NetTrace, "IS ");
+		goto env_common;
+	    case TELQUAL_SEND:
+		fprintf(NetTrace, "SEND ");
+		goto env_common;
+	    case TELQUAL_INFO:
+		fprintf(NetTrace, "INFO ");
+	    env_common:
+		{
+		    register int noquote = 2;
+#if defined(ENV_HACK) && defined(OLD_ENVIRON)
+		    extern int old_env_var, old_env_value;
+#endif
+		    for (i = 2; i < length; i++ ) {
+			switch (pointer[i]) {
+			case NEW_ENV_VALUE:
+#ifdef OLD_ENVIRON
+		     /*	case NEW_ENV_OVAR: */
+			    if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef	ENV_HACK
+				if (old_env_var == OLD_ENV_VALUE)
+				    fprintf(NetTrace, "\" (VALUE) " + noquote);
+				else
+# endif
+				    fprintf(NetTrace, "\" VAR " + noquote);
+			    } else
+#endif /* OLD_ENVIRON */
+				fprintf(NetTrace, "\" VALUE " + noquote);
+			    noquote = 2;
+			    break;
+
+			case NEW_ENV_VAR:
+#ifdef OLD_ENVIRON
+		     /* case OLD_ENV_VALUE: */
+			    if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef	ENV_HACK
+				if (old_env_value == OLD_ENV_VAR)
+				    fprintf(NetTrace, "\" (VAR) " + noquote);
+				else
+# endif
+				    fprintf(NetTrace, "\" VALUE " + noquote);
+			    } else
+#endif /* OLD_ENVIRON */
+				fprintf(NetTrace, "\" VAR " + noquote);
+			    noquote = 2;
+			    break;
+
+			case ENV_ESC:
+			    fprintf(NetTrace, "\" ESC " + noquote);
+			    noquote = 2;
+			    break;
+
+			case ENV_USERVAR:
+			    fprintf(NetTrace, "\" USERVAR " + noquote);
+			    noquote = 2;
+			    break;
+
+			default:
+			    if (isprint(pointer[i]) && pointer[i] != '"') {
+				if (noquote) {
+				    putc('"', NetTrace);
+				    noquote = 0;
+				}
+				putc(pointer[i], NetTrace);
+			    } else {
+				fprintf(NetTrace, "\" %03o " + noquote,
+							pointer[i]);
+				noquote = 2;
+			    }
+			    break;
+			}
+		    }
+		    if (!noquote)
+			putc('"', NetTrace);
+		    break;
+		}
+	    }
+	    break;
+
+	default:
+	    if (TELOPT_OK(pointer[0]))
+		fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
+	    else
+		fprintf(NetTrace, "%d (unknown)", pointer[0]);
+	    for (i = 1; i < length; i++)
+		fprintf(NetTrace, " %d", pointer[i]);
+	    break;
+	}
+	if (direction) {
+	    if (NetTrace == stdout)
+		fprintf(NetTrace, "\r\n");
+	    else
+		fprintf(NetTrace, "\n");
+	}
+	if (NetTrace == stdout)
+	    fflush(NetTrace);
+    }
+}
+
+/* EmptyTerminal - called to make sure that the terminal buffer is empty.
+ *			Note that we consider the buffer to run all the
+ *			way to the kernel (thus the select).
+ */
+
+    void
+EmptyTerminal()
+{
+#if	defined(unix)
+    fd_set	o;
+
+    FD_ZERO(&o);
+#endif	/* defined(unix) */
+
+    if (TTYBYTES() == 0) {
+#if	defined(unix)
+	FD_SET(tout, &o);
+	(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
+			(struct timeval *) 0);	/* wait for TTLOWAT */
+#endif	/* defined(unix) */
+    } else {
+	while (TTYBYTES()) {
+	    (void) ttyflush(0);
+#if	defined(unix)
+	    FD_SET(tout, &o);
+	    (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
+				(struct timeval *) 0);	/* wait for TTLOWAT */
+#endif	/* defined(unix) */
+	}
+    }
+}
+
+    void
+SetForExit()
+{
+    setconnmode(0);
+#if	defined(TN3270)
+    if (In3270) {
+	Finish3270();
+    }
+#else	/* defined(TN3270) */
+    do {
+	(void)telrcv();			/* Process any incoming data */
+	EmptyTerminal();
+    } while (ring_full_count(&netiring));	/* While there is any */
+#endif	/* defined(TN3270) */
+    setcommandmode();
+    fflush(stdout);
+    fflush(stderr);
+#if	defined(TN3270)
+    if (In3270) {
+	StopScreen(1);
+    }
+#endif	/* defined(TN3270) */
+    setconnmode(0);
+    EmptyTerminal();			/* Flush the path to the tty */
+    setcommandmode();
+}
+
+    void
+Exit(returnCode)
+    int returnCode;
+{
+    SetForExit();
+    exit(returnCode);
+}
+
+    void
+ExitString(string, returnCode)
+    char *string;
+    int returnCode;
+{
+    SetForExit();
+    fwrite(string, 1, strlen(string), stderr);
+    exit(returnCode);
+}
diff --git a/krb5-1-6/src/appl/telnet/telnetd/ISSUES b/krb5-1-6/src/appl/telnet/telnetd/ISSUES
new file mode 100644
index 000000000..5b61997bb
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/ISSUES
@@ -0,0 +1,7 @@
+Issues to be dealt with in telnetd:
+
+Debug mode won't do ipv6.
+
+FIX: Rewrite listener setup code in main after argument parsing.
+
+Needs auditing.
diff --git a/krb5-1-6/src/appl/telnet/telnetd/Makefile.in b/krb5-1-6/src/appl/telnet/telnetd/Makefile.in
new file mode 100644
index 000000000..58bc2491b
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/Makefile.in
@@ -0,0 +1,148 @@
+thisconfigdir=..
+myfulldir=appl/telnet/telnetd
+mydir=telnetd
+BUILDTOP=$(REL)..$(S)..$(S)..
+# derived from the original Makefile.generic
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted provided
+# that: (1) source distributions retain this entire copyright notice and
+# comment, and (2) distributions including binaries display the following
+# acknowledgement:  ``This product includes software developed by the
+# University of California, Berkeley and its contributors'' in the
+# documentation or other materials provided with the distribution and in
+# all advertising materials mentioning features or use of this software.
+# Neither the name of the University nor the names of its contributors may
+# be used to endorse or promote products derived from this software without
+# specific prior written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+#	@(#)Makefile.generic	5.5 (Berkeley) 3/1/91
+#
+
+AUTH_DEF=-DAUTHENTICATION -DENCRYPTION -DKRB5 -DFORWARD -UNO_LOGIN_F -ULOGIN_CAP_F -DLOGIN_PROGRAM=KRB5_PATH_LOGIN
+OTHERDEFS=-DKLUDGELINEMODE -DDIAGNOSTICS -DENV_HACK -DOLD_ENVIRON
+LOCALINCLUDES=-I.. -I$(srcdir)/..
+DEFINES = -DTELNET_BUFSIZE=65535 $(AUTH_DEF) $(OTHERDEFS)
+ARPA_TELNET= $(srcdir)/../arpa/telnet.h
+
+PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+LIBS=	@TELNETD_LIBS@
+
+SRCS=	$(srcdir)/telnetd.c \
+	$(srcdir)/termio-tn.c \
+	$(srcdir)/termios-tn.c \
+	$(srcdir)/state.c \
+	$(srcdir)/termstat.c \
+	$(srcdir)/slc.c \
+	$(srcdir)/sys_term.c \
+	$(srcdir)/utility.c \
+	$(srcdir)/global.c \
+	$(srcdir)/authenc.c \
+	$(GETTYSRC)
+OBJS=	telnetd.o \
+	termio-tn.o \
+	termios-tn.o \
+	state.o \
+	termstat.o \
+	slc.o \
+	sys_term.o \
+	utility.o \
+	global.o \
+	authenc.o \
+	$(GETTYOBJ)
+
+all:: telnetd
+
+telnetd: $(OBJS) $(PTY_DEPLIB) $(KRB4COMPAT_DEPLIBS) ../libtelnet/libtelnet.a
+	$(CC_LINK) -o $@ $(OBJS) ../libtelnet/libtelnet.a $(PTY_LIB) $(UTIL_LIB) $(KRB4COMPAT_LIBS)
+
+clean::
+	$(RM) telnetd
+
+install::
+	for f in telnetd; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(SERVER_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.8 \
+		${DESTDIR}$(SERVER_MANDIR)/`echo $$f|sed '$(transform)'`.8; \
+	done
+
+authenc.o: telnetd.h
+global.o: defs.h ext.h $(ARPA_TELNET)
+slc.o: telnetd.h defs.h ext.h $(ARPA_TELNET)
+state.o: telnetd.h defs.h ext.h $(ARPA_TELNET)
+sys_term.o: telnetd.h pathnames.h defs.h ext.h $(ARPA_TELNET)
+telnetd.o: telnetd.h defs.h ext.h $(ARPA_TELNET)
+termstat.o: telnetd.h defs.h ext.h $(ARPA_TELNET)
+utility.o: telnetd.h defs.h ext.h $(ARPA_TELNET)
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)telnetd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/libpty.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/auth-proto.h $(srcdir)/../libtelnet/auth.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  $(srcdir)/../libtelnet/misc-proto.h defs.h ext.h pathnames.h \
+  telnetd.c telnetd.h
+$(OUTPRE)termio-tn.$(OBJEXT): termio-tn.c
+$(OUTPRE)termios-tn.$(OBJEXT): termios-tn.c
+$(OUTPRE)state.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/auth-proto.h $(srcdir)/../libtelnet/auth.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  defs.h ext.h state.c telnetd.h
+$(OUTPRE)termstat.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  defs.h ext.h telnetd.h termstat.c
+$(OUTPRE)slc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  defs.h ext.h slc.c telnetd.h
+$(OUTPRE)sys_term.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/libpty.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  $(srcdir)/../arpa/telnet.h $(srcdir)/../libtelnet/auth-proto.h \
+  $(srcdir)/../libtelnet/auth.h defs.h ext.h pathnames.h \
+  sys_term.c telnetd.h
+$(OUTPRE)utility.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/auth-proto.h $(srcdir)/../libtelnet/auth.h \
+  $(srcdir)/../libtelnet/enc-proto.h $(srcdir)/../libtelnet/encrypt.h \
+  defs.h ext.h telnetd.h utility.c
+$(OUTPRE)global.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  defs.h ext.h global.c
+$(OUTPRE)authenc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../arpa/telnet.h \
+  $(srcdir)/../libtelnet/misc-proto.h $(srcdir)/../libtelnet/misc.h \
+  authenc.c defs.h ext.h telnetd.h
diff --git a/krb5-1-6/src/appl/telnet/telnetd/authenc.c b/krb5-1-6/src/appl/telnet/telnetd/authenc.c
new file mode 100644
index 000000000..6d8b04ced
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/authenc.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)authenc.c	8.1 (Berkeley) 6/4/93 */
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+#include "telnetd.h"
+#include <libtelnet/misc.h>
+
+int
+net_write(str, len)
+	unsigned char *str;
+	int len;
+{
+	if (len < 0)
+		return 0;
+	return netwrite(str, (size_t) len);
+}
+
+void
+net_encrypt()
+{
+#ifdef	ENCRYPTION
+	char *s = (nclearto > nbackp) ? nclearto : nbackp;
+	if (s < nfrontp && encrypt_output) {
+		(*encrypt_output)((unsigned char *)s, nfrontp - s);
+	}
+	nclearto = nfrontp;
+#endif /* ENCRYPTION */
+}
+
+	int
+telnet_spin()
+{
+	ttloop();
+	return(0);
+}
+
+	char *
+telnet_getenv(val)
+	char *val;
+{
+	extern char *getenv();
+	return(getenv(val));
+}
+
+	char *
+telnet_gets(prompt, result, length, echo)
+	char *prompt;
+	char *result;
+	int length;
+	int echo;
+{
+	return((char *)0);
+}
+#endif	/* defined(AUTHENTICATION) || defined(ENCRYPTION) */
diff --git a/krb5-1-6/src/appl/telnet/telnetd/defs.h b/krb5-1-6/src/appl/telnet/telnetd/defs.h
new file mode 100644
index 000000000..ab653a35f
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/defs.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)defs.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Telnet server defines
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifndef	BSD
+# define	BSD 43
+#endif
+
+#if	defined(CRAY) && !defined(LINEMODE)
+# define SYSV_TERMIO
+# define LINEMODE
+# define KLUDGELINEMODE
+# define DIAGNOSTICS
+# if defined(UNICOS50) && !defined(UNICOS5)
+#  define UNICOS5
+# endif
+# if !defined(UNICOS5)
+#  define BFTPDAEMON
+#  define HAS_IP_TOS
+# endif
+#endif /* CRAY */
+#if defined(UNICOS5) && !defined(NO_SETSID)
+# define NO_SETSID
+#endif
+
+#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS)
+#define TELOPTS
+#define TELCMDS
+#define	SLC_NAMES
+#endif
+
+#if	defined(SYSV_TERMIO) && !defined(USE_TERMIO)
+# define	USE_TERMIO
+#endif
+
+#include <sys/socket.h>
+#ifndef	CRAY
+#include <sys/wait.h>
+#endif	/* CRAY */
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <sys/ioctl.h>
+#ifdef	HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#include <netinet/in.h>
+
+#include <arpa/telnet.h>
+
+/* for socklen() */
+#include "socket-utils.h"
+
+#include <stdio.h>
+#ifdef	__STDC__
+#include <stdlib.h>
+#endif
+#include <signal.h>
+#include <errno.h>
+#include <netdb.h>
+#include <syslog.h>
+#ifndef	LOG_DAEMON
+#define	LOG_DAEMON	0
+#endif
+#ifndef	LOG_ODELAY
+#define	LOG_ODELAY	0
+#endif
+#include <ctype.h>
+#ifndef HAVE_STRING_H
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+
+#ifndef	USE_TERMIO
+#include <sgtty.h>
+#else
+# ifdef	SYSV_TERMIO
+# include <termio.h>
+# else
+# include <termios.h>
+# endif
+#endif
+#if !defined(USE_TERMIO) || defined(NO_CC_T)
+typedef unsigned char cc_t;
+#endif
+
+#ifdef	__STDC__
+#include <unistd.h>
+#endif
+
+#ifndef _POSIX_VDISABLE
+# ifdef VDISABLE
+#  define _POSIX_VDISABLE VDISABLE
+# else
+#  define _POSIX_VDISABLE ((unsigned char)'\377')
+# endif
+#endif
+
+
+#ifdef	CRAY
+# ifdef	CRAY1
+# include <sys/pty.h>
+#  ifndef FD_ZERO
+# include <sys/select.h>
+#  endif /* FD_ZERO */
+# endif	/* CRAY1 */
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#endif	/* CRAY */
+
+#ifdef __hpux
+#include <sys/ptyio.h>
+#endif
+
+#if defined(__alpha) && defined(STREAMSPTY)
+#undef STREAMSPTY
+#endif
+
+#if	!defined(TIOCSCTTY) && defined(TCSETCTTY)
+# define	TIOCSCTTY TCSETCTTY
+#endif
+
+#ifndef	FD_SET
+#ifndef	HAVE_fd_set
+typedef struct fd_set { int fds_bits[1]; } fd_set;
+#endif
+
+#define	FD_SET(n, p)	((p)->fds_bits[0] |= (1<<(n)))
+#define	FD_CLR(n, p)	((p)->fds_bits[0] &= ~(1<<(n)))
+#define	FD_ISSET(n, p)	((p)->fds_bits[0] & (1<<(n)))
+#define FD_ZERO(p)	((p)->fds_bits[0] = 0)
+#endif	/* FD_SET */
+
+/*
+ * I/O data buffers defines
+ */
+#define	NETSLOP	64
+#ifdef CRAY
+#undef BUFSIZ
+#define BUFSIZ  2048
+#endif
+
+#define	NIACCUM(c)	{   *netip++ = c; \
+			    ncc++; \
+			}
+
+/* clock manipulations */
+#define	settimer(x)	(clocks.x = ++clocks.system)
+#define	sequenceIs(x,y)	(clocks.x < clocks.y)
+
+/*
+ * Linemode support states, in decreasing order of importance
+ */
+#define REAL_LINEMODE	0x04
+#define KLUDGE_OK	0x03
+#define	NO_AUTOKLUDGE	0x02
+#define KLUDGE_LINEMODE	0x01
+#define NO_LINEMODE	0x00
+
+/*
+ * Structures of information for each special character function.
+ */
+typedef struct {
+	unsigned char	flag;		/* the flags for this function */
+	cc_t		val;		/* the value of the special character */
+} slcent, *Slcent;
+
+typedef struct {
+	slcent		defset;		/* the default settings */
+	slcent		current;	/* the current settings */
+	cc_t		*sptr;		/* a pointer to the char in */
+					/* system data structures */
+} slcfun, *Slcfun;
+
+#ifdef DIAGNOSTICS
+/*
+ * Diagnostics capabilities
+ */
+#define	TD_REPORT	0x01	/* Report operations to client */
+#define TD_EXERCISE	0x02	/* Exercise client's implementation */
+#define TD_NETDATA	0x04	/* Display received data stream */
+#define TD_PTYDATA	0x08	/* Display data passed to pty */
+#define	TD_OPTIONS	0x10	/* Report just telnet options */
+#endif /* DIAGNOSTICS */
+
+/*
+ * We keep track of each side of the option negotiation.
+ */
+
+#define	MY_STATE_WILL		0x01
+#define	MY_WANT_STATE_WILL	0x02
+#define	MY_STATE_DO		0x04
+#define	MY_WANT_STATE_DO	0x08
+
+/*
+ * Macros to check the current state of things
+ */
+
+#define	my_state_is_do(opt)		(options[opt]&MY_STATE_DO)
+#define	my_state_is_will(opt)		(options[opt]&MY_STATE_WILL)
+#define my_want_state_is_do(opt)	(options[opt]&MY_WANT_STATE_DO)
+#define my_want_state_is_will(opt)	(options[opt]&MY_WANT_STATE_WILL)
+
+#define	my_state_is_dont(opt)		(!my_state_is_do(opt))
+#define	my_state_is_wont(opt)		(!my_state_is_will(opt))
+#define my_want_state_is_dont(opt)	(!my_want_state_is_do(opt))
+#define my_want_state_is_wont(opt)	(!my_want_state_is_will(opt))
+
+#define	set_my_state_do(opt)		(options[opt] |= MY_STATE_DO)
+#define	set_my_state_will(opt)		(options[opt] |= MY_STATE_WILL)
+#define	set_my_want_state_do(opt)	(options[opt] |= MY_WANT_STATE_DO)
+#define	set_my_want_state_will(opt)	(options[opt] |= MY_WANT_STATE_WILL)
+
+#define	set_my_state_dont(opt)		(options[opt] &= ~MY_STATE_DO)
+#define	set_my_state_wont(opt)		(options[opt] &= ~MY_STATE_WILL)
+#define	set_my_want_state_dont(opt)	(options[opt] &= ~MY_WANT_STATE_DO)
+#define	set_my_want_state_wont(opt)	(options[opt] &= ~MY_WANT_STATE_WILL)
+
+/*
+ * Tricky code here.  What we want to know is if the MY_STATE_WILL
+ * and MY_WANT_STATE_WILL bits have the same value.  Since the two
+ * bits are adjacent, a little arithmatic will show that by adding
+ * in the lower bit, the upper bit will be set if the two bits were
+ * different, and clear if they were the same.
+ */
+#define my_will_wont_is_changing(opt) \
+			((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL)
+
+#define my_do_dont_is_changing(opt) \
+			((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO)
+
+/*
+ * Make everything symetrical
+ */
+
+#define	HIS_STATE_WILL			MY_STATE_DO
+#define	HIS_WANT_STATE_WILL		MY_WANT_STATE_DO
+#define HIS_STATE_DO			MY_STATE_WILL
+#define HIS_WANT_STATE_DO		MY_WANT_STATE_WILL
+
+#define	his_state_is_do			my_state_is_will
+#define	his_state_is_will		my_state_is_do
+#define his_want_state_is_do		my_want_state_is_will
+#define his_want_state_is_will		my_want_state_is_do
+
+#define	his_state_is_dont		my_state_is_wont
+#define	his_state_is_wont		my_state_is_dont
+#define his_want_state_is_dont		my_want_state_is_wont
+#define his_want_state_is_wont		my_want_state_is_dont
+
+#define	set_his_state_do		set_my_state_will
+#define	set_his_state_will		set_my_state_do
+#define	set_his_want_state_do		set_my_want_state_will
+#define	set_his_want_state_will		set_my_want_state_do
+
+#define	set_his_state_dont		set_my_state_wont
+#define	set_his_state_wont		set_my_state_dont
+#define	set_his_want_state_dont		set_my_want_state_wont
+#define	set_his_want_state_wont		set_my_want_state_dont
+
+#define his_will_wont_is_changing	my_do_dont_is_changing
+#define his_do_dont_is_changing		my_will_wont_is_changing
+
+extern char	*line;
+
+#ifdef	ENCRYPTION
+extern void	(*encrypt_output) (unsigned char *, int);
+extern int	(*decrypt_input) (int);
+#endif	/* ENCRYPTION */
diff --git a/krb5-1-6/src/appl/telnet/telnetd/ext.h b/krb5-1-6/src/appl/telnet/telnetd/ext.h
new file mode 100644
index 000000000..5d4f8e159
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/ext.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ext.h	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Telnet server variable declarations
+ */
+extern char	options[256];
+extern char	do_dont_resp[256];
+extern char	will_wont_resp[256];
+extern int	linemode;	/* linemode on/off */
+#ifdef	LINEMODE
+extern int	uselinemode;	/* what linemode to use (on/off) */
+extern int	editmode;	/* edit modes in use */
+extern int	useeditmode;	/* edit modes to use */
+extern int	alwayslinemode;	/* command line option */
+# ifdef	KLUDGELINEMODE
+extern int	lmodetype;	/* Client support for linemode */
+# endif	/* KLUDGELINEMODE */
+#endif	/* LINEMODE */
+extern int	flowmode;	/* current flow control state */
+extern int	restartany;	/* restart output on any character state */
+#ifdef DIAGNOSTICS
+extern int	diagnostic;	/* telnet diagnostic capabilities */
+#endif /* DIAGNOSTICS */
+#ifdef BFTPDAEMON
+extern int	bftpd;		/* behave as bftp daemon */
+#endif /* BFTPDAEMON */
+#if	defined(SecurID)
+extern int	require_SecurID;
+#endif
+#if	defined(AUTHENTICATION)
+extern int	auth_level;
+#endif
+extern int auth_negotiated; /* Have we finished all authentication negotiation we plan to finish?*/
+extern slcfun	slctab[NSLC + 1];	/* slc mapping table */
+
+extern char	terminaltype[41];
+
+/*
+ * I/O data buffers, pointers, and counters.
+ */
+extern char	ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
+
+extern char	netibuf[BUFSIZ], *netip;
+
+extern char	netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
+extern char	*neturg;		/* one past last bye of urgent data */
+
+extern int	pcc, ncc;
+
+#if defined(CRAY2) && defined(UNICOS5)
+extern int unpcc;  /* characters left unprocessed by CRAY-2 terminal routine */
+extern char *unptyip;  /* pointer to remaining characters in buffer */
+#endif
+
+extern int	pty, net;
+extern int	SYNCHing;		/* we are in TELNET SYNCH mode */
+
+#ifdef ENCRYPTION
+extern int	must_encrypt;
+#endif
+
+extern void
+	_termstat (void),
+	add_slc (int, int, int),
+	check_slc (void),
+	change_slc (int, int, int),
+	cleanup (int),
+	clientstat (int, int, int),
+	copy_termbuf (char *, int),
+	deferslc (void),
+	defer_terminit (void),
+	do_opt_slc (unsigned char *, int),
+	doeof (void),
+	dooption (int),
+	dontoption (int),
+	edithost (char *, char *),
+	fatal (int, const char *),
+	fatalperror (int, const char *),
+	get_slc_defaults (void),
+	init_env (void),
+	init_termbuf (void),
+	interrupt (void),
+	localstat (void),
+	flowstat (void),
+	netclear (void),
+	netflush (void),
+#ifdef DIAGNOSTICS
+	printoption (char *, int),
+	printdata (char *, char *, int),
+	printsub (int, unsigned char *, int),
+#endif
+	ptyflush (void),
+	putchr (int),
+	putf (char *, char *),
+	recv_ayt (void),
+	send_do (int, int),
+	send_dont (int, int),
+	send_slc (void),
+	send_status (void),
+	send_will (int, int),
+	send_wont (int, int),
+	sendbrk (void),
+	sendsusp (void),
+	set_termbuf (void),
+	start_login (char *, int, char *),
+	start_slc (int),
+	startslave (char *, int, char *),
+	suboption (void),
+	telrcv (void),
+	ttloop (void),
+#if	defined(AUTHENTICATION)
+        ttsuck (void),
+#endif
+	tty_binaryin (int),
+	tty_binaryout (int);
+
+extern int
+	end_slc (unsigned char **),
+	getnpty (void),
+#ifndef convex
+	getpty (int *),
+#endif
+	login_tty (int),
+	spcset (int, cc_t *, cc_t **),
+	stilloob (int),
+	terminit (void),
+	termstat (void),
+	tty_flowmode (void),
+	tty_restartany (void),
+	tty_isbinaryin (void),
+	tty_isbinaryout (void),
+	tty_iscrnl (void),
+	tty_isecho (void),
+	tty_isediting (void),
+	tty_islitecho (void),
+	tty_isnewmap (void),
+	tty_israw (void),
+	tty_issofttab (void),
+	tty_istrapsig (void),
+	tty_linemode (void);
+
+extern void
+	tty_rspeed (int),
+	tty_setecho (int),
+	tty_setedit (int),
+	tty_setlinemode (int),
+	tty_setlitecho (int),
+	tty_setsig (int),
+	tty_setsofttab (int),
+	tty_tspeed (int),
+	willoption (int),
+	wontoption (int);
+
+extern void netprintf (const char *, ...);
+extern void netprintf_urg (const char *fmt, ...);
+extern void netprintf_noflush (const char *fmt, ...);
+extern int netwrite (const unsigned char *, size_t);
+extern void netputs (const char *);
+
+#ifdef	ENCRYPTION
+extern char	*nclearto;
+#endif	/* ENCRYPTION */
+
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+extern struct {
+    int
+	system,			/* what the current time is */
+	echotoggle,		/* last time user entered echo character */
+	modenegotiated,		/* last time operating mode negotiated */
+	didnetreceive,		/* last time we read data from network */
+	ttypesubopt,		/* ttype subopt is received */
+	tspeedsubopt,		/* tspeed subopt is received */
+	environsubopt,		/* environ subopt is received */
+	oenvironsubopt,		/* old environ subopt is received */
+	xdisplocsubopt,		/* xdisploc subopt is received */
+	baseline,		/* time started to do timed action */
+	gotDM;			/* when did we last see a data mark */
+} clocks;
+
+
+#if	defined(CRAY2) && defined(UNICOS5)
+extern int	needtermstat;
+#endif
+
+#ifdef NEED_UNSETENV_PROTO
+extern void unsetenv(const char *);
+#endif
+#ifdef NEED_SETENV_PROTO
+extern void setenv(const char *, const char *, int);
+#endif
diff --git a/krb5-1-6/src/appl/telnet/telnetd/global.c b/krb5-1-6/src/appl/telnet/telnetd/global.c
new file mode 100644
index 000000000..c1412834e
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/global.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)global.c	8.1 (Berkeley) 6/4/93 */
+
+/*
+ * Allocate global variables.  We do this
+ * by including the header file that defines
+ * them all as externs, but first we define
+ * the keyword "extern" to be nothing, so that
+ * we will actually allocate the space.
+ */
+
+#include "defs.h"
+#define extern
+#include "ext.h"
diff --git a/krb5-1-6/src/appl/telnet/telnetd/pathnames.h b/krb5-1-6/src/appl/telnet/telnetd/pathnames.h
new file mode 100644
index 000000000..c8b0806e7
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/pathnames.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)pathnames.h	8.1 (Berkeley) 6/4/93
+ */
+
+#if BSD > 43
+
+# include <paths.h>
+
+# ifndef _PATH_LOGIN
+#  define	_PATH_LOGIN	"/usr/bin/login"
+# endif
+
+#else
+ 
+# define	_PATH_TTY	"/dev/tty"
+# ifndef _PATH_LOGIN
+#  define	_PATH_LOGIN	"/bin/login"
+# endif
+
+#endif
+
+#ifdef BFTPDAEMON
+#define		BFTPPATH	"/usr/ucb/bftp"
+#endif  /* BFTPDAEMON */
diff --git a/krb5-1-6/src/appl/telnet/telnetd/slc.c b/krb5-1-6/src/appl/telnet/telnetd/slc.c
new file mode 100644
index 000000000..613674b01
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/slc.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)slc.c	8.1 (Berkeley) 6/4/93 */
+
+#include "telnetd.h"
+
+#ifdef	LINEMODE
+/*
+ * local varibles
+ */
+static unsigned char	*def_slcbuf = (unsigned char *)0;
+static int		def_slclen = 0;
+static int		slcchange;	/* change to slc is requested */
+static unsigned char	*slcptr;	/* pointer into slc buffer */
+static unsigned char	slcbuf[NSLC*6];	/* buffer for slc negotiation */
+
+/*
+ * send_slc
+ *
+ * Write out the current special characters to the client.
+ */
+	void
+send_slc()
+{
+	register int i;
+
+	/*
+	 * Send out list of triplets of special characters
+	 * to client.  We only send info on the characters
+	 * that are currently supported.
+	 */
+	for (i = 1; i <= NSLC; i++) {
+		if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT)
+			continue;
+		add_slc((unsigned char)i, slctab[i].current.flag,
+							slctab[i].current.val);
+	}
+
+}  /* end of send_slc */
+
+/*
+ * default_slc
+ *
+ * Set pty special characters to all the defaults.
+ */
+	void
+default_slc()
+{
+	register int i;
+
+	for (i = 1; i <= NSLC; i++) {
+		slctab[i].current.val = slctab[i].defset.val;
+		if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE))
+			slctab[i].current.flag = SLC_NOSUPPORT;
+		else
+			slctab[i].current.flag = slctab[i].defset.flag;
+		if (slctab[i].sptr) {
+			*(slctab[i].sptr) = slctab[i].defset.val;
+		}
+	}
+	slcchange = 1;
+
+}  /* end of default_slc */
+#endif	/* LINEMODE */
+
+/*
+ * get_slc_defaults
+ *
+ * Initialize the slc mapping table.
+ */
+	void
+get_slc_defaults()
+{
+	register int i;
+
+	init_termbuf();
+
+	for (i = 1; i <= NSLC; i++) {
+		slctab[i].defset.flag = 
+			spcset(i, &slctab[i].defset.val, &slctab[i].sptr);
+		slctab[i].current.flag = SLC_NOSUPPORT; 
+		slctab[i].current.val = 0; 
+	}
+
+}  /* end of get_slc_defaults */
+
+#ifdef	LINEMODE
+/*
+ * add_slc
+ *
+ * Add an slc triplet to the slc buffer.
+ */
+	void
+add_slc(func, flag, val)
+	register char func, flag;
+	register cc_t val;
+{
+
+	if ((*slcptr++ = (unsigned char)func) == 0xff)
+		*slcptr++ = 0xff;
+
+	if ((*slcptr++ = (unsigned char)flag) == 0xff)
+		*slcptr++ = 0xff;
+
+	if ((*slcptr++ = (unsigned char)val) == 0xff)
+		*slcptr++ = 0xff;
+
+}  /* end of add_slc */
+
+/*
+ * start_slc
+ *
+ * Get ready to process incoming slc's and respond to them.
+ *
+ * The parameter getit is non-zero if it is necessary to grab a copy
+ * of the terminal control structures.
+ */
+	void
+start_slc(getit)
+	register int getit;
+{
+
+	slcchange = 0;
+	if (getit)
+		init_termbuf();
+	(void) sprintf((char *)slcbuf, "%c%c%c%c",
+					IAC, SB, TELOPT_LINEMODE, LM_SLC);
+	slcptr = slcbuf + 4;
+
+}  /* end of start_slc */
+
+/*
+ * end_slc
+ *
+ * Finish up the slc negotiation.  If something to send, then send it.
+ */
+	int
+end_slc(bufp)
+	register unsigned char **bufp;
+{
+	register int len;
+	void netflush();
+
+	/*
+	 * If a change has occured, store the new terminal control
+	 * structures back to the terminal driver.
+	 */
+	if (slcchange) {
+		set_termbuf();
+	}
+
+	/*
+	 * If the pty state has not yet been fully processed and there is a
+	 * deferred slc request from the client, then do not send any
+	 * sort of slc negotiation now.  We will respond to the client's
+	 * request very soon.
+	 */
+	if (def_slcbuf && (terminit() == 0)) {
+		return(0);
+	}
+
+	if (slcptr > (slcbuf + 4)) {
+		if (bufp) {
+			*bufp = &slcbuf[4];
+			return(slcptr - slcbuf - 4);
+		} else {
+			(void) sprintf((char *)slcptr, "%c%c", IAC, SE);
+			slcptr += 2;
+			len = slcptr - slcbuf;
+			netwrite(slcbuf, len);
+			netflush();  /* force it out immediately */
+			DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2););
+		}
+	}
+	return (0);
+
+}  /* end of end_slc */
+
+/*
+ * process_slc
+ *
+ * Figure out what to do about the client's slc
+ */
+	void
+process_slc(func, flag, val)
+	register unsigned char func, flag;
+	register cc_t val;
+{
+	register int hislevel, mylevel, ack;
+
+	/*
+	 * Ensure that we know something about this function
+	 */
+	if (func > NSLC) {
+		add_slc(func, SLC_NOSUPPORT, 0);
+		return;
+	}
+
+	/*
+	 * Process the special case requests of 0 SLC_DEFAULT 0
+	 * and 0 SLC_VARIABLE 0.  Be a little forgiving here, don't
+	 * worry about whether the value is actually 0 or not.
+	 */
+	if (func == 0) {
+		if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) {
+			default_slc();
+			send_slc();
+		} else if (flag == SLC_VARIABLE) {
+			send_slc();
+		}
+		return;
+	}
+
+	/*
+	 * Appears to be a function that we know something about.  So
+	 * get on with it and see what we know.
+	 */
+
+	hislevel = flag & SLC_LEVELBITS;
+	mylevel = slctab[func].current.flag & SLC_LEVELBITS;
+	ack = flag & SLC_ACK;
+	/*
+	 * ignore the command if:
+	 * the function value and level are the same as what we already have;
+	 * or the level is the same and the ack bit is set
+	 */
+	if (hislevel == mylevel && (val == slctab[func].current.val || ack)) {
+		return;
+	} else if (ack) {
+		/*
+		 * If we get here, we got an ack, but the levels don't match.
+		 * This shouldn't happen.  If it does, it is probably because
+		 * we have sent two requests to set a variable without getting
+		 * a response between them, and this is the first response.
+		 * So, ignore it, and wait for the next response.
+		 */
+		return;
+	} else {
+		change_slc(func, flag, val);
+	}
+
+}  /* end of process_slc */
+
+/*
+ * change_slc
+ *
+ * Process a request to change one of our special characters.
+ * Compare client's request with what we are capable of supporting.
+ */
+	void
+change_slc(func, flag, val)
+	register char func, flag;
+	register cc_t val;
+{
+	register int hislevel, mylevel;
+	
+	hislevel = flag & SLC_LEVELBITS;
+	mylevel = slctab[func].defset.flag & SLC_LEVELBITS;
+	/*
+	 * If client is setting a function to NOSUPPORT
+	 * or DEFAULT, then we can easily and directly
+	 * accomodate the request.
+	 */
+	if (hislevel == SLC_NOSUPPORT) {
+		slctab[func].current.flag = flag;
+		slctab[func].current.val = (cc_t)_POSIX_VDISABLE;
+		flag |= SLC_ACK;
+		add_slc(func, flag, val);
+		return;
+	}
+	if (hislevel == SLC_DEFAULT) {
+		/*
+		 * Special case here.  If client tells us to use
+		 * the default on a function we don't support, then
+		 * return NOSUPPORT instead of what we may have as a
+		 * default level of DEFAULT.
+		 */
+		if (mylevel == SLC_DEFAULT) {
+			slctab[func].current.flag = SLC_NOSUPPORT;
+		} else {
+			slctab[func].current.flag = slctab[func].defset.flag;
+		}
+		slctab[func].current.val = slctab[func].defset.val;
+		add_slc(func, slctab[func].current.flag,
+						slctab[func].current.val);
+		return;
+	}
+
+	/*
+	 * Client wants us to change to a new value or he
+	 * is telling us that he can't change to our value.
+	 * Some of the slc's we support and can change,
+	 * some we do support but can't change,
+	 * and others we don't support at all.
+	 * If we can change it then we have a pointer to
+	 * the place to put the new value, so change it,
+	 * otherwise, continue the negotiation.
+	 */
+	if (slctab[func].sptr) {
+		/*
+		 * We can change this one.
+		 */
+		slctab[func].current.val = val;
+		*(slctab[func].sptr) = val;
+		slctab[func].current.flag = flag;
+		flag |= SLC_ACK;
+		slcchange = 1;
+		add_slc(func, flag, val);
+	} else {
+		/*
+		* It is not possible for us to support this
+		* request as he asks.
+		*
+		* If our level is DEFAULT, then just ack whatever was
+		* sent. 
+		*
+		* If he can't change and we can't change,
+		* then degenerate to NOSUPPORT.
+		*
+		* Otherwise we send our level back to him, (CANTCHANGE
+		* or NOSUPPORT) and if CANTCHANGE, send
+		* our value as well.
+		*/
+		if (mylevel == SLC_DEFAULT) {
+			slctab[func].current.flag = flag;
+			slctab[func].current.val = val;
+			flag |= SLC_ACK;
+		} else if (hislevel == SLC_CANTCHANGE &&
+				    mylevel == SLC_CANTCHANGE) {
+			flag &= ~SLC_LEVELBITS;
+			flag |= SLC_NOSUPPORT;
+			slctab[func].current.flag = flag;
+		} else {
+			flag &= ~SLC_LEVELBITS;
+			flag |= mylevel;
+			slctab[func].current.flag = flag;
+			if (mylevel == SLC_CANTCHANGE) {
+				slctab[func].current.val =
+					slctab[func].defset.val;
+				val = slctab[func].current.val;
+			}
+			
+		}
+		add_slc(func, flag, val);
+	}
+
+}  /* end of change_slc */
+
+#if	defined(USE_TERMIO) && (VEOF == VMIN)
+cc_t oldeofc = '\004';
+#endif
+
+/*
+ * check_slc
+ *
+ * Check the special characters in use and notify the client if any have
+ * changed.  Only those characters that are capable of being changed are
+ * likely to have changed.  If a local change occurs, kick the support level
+ * and flags up to the defaults.
+ */
+	void
+check_slc()
+{
+	register int i;
+
+	for (i = 1; i <= NSLC; i++) {
+#if	defined(USE_TERMIO) && (VEOF == VMIN)
+		/*
+		 * In a perfect world this would be a neat little
+		 * function.  But in this world, we should not notify
+		 * client of changes to the VEOF char when
+		 * ICANON is off, because it is not representing
+		 * a special character.
+		 */
+		if (i == SLC_EOF) {
+			if (!tty_isediting())
+				continue;
+			else if (slctab[i].sptr)
+				oldeofc = *(slctab[i].sptr);
+		}
+#endif	/* defined(USE_TERMIO) && defined(SYSV_TERMIO) */
+		if (slctab[i].sptr &&
+				(*(slctab[i].sptr) != slctab[i].current.val)) {
+			slctab[i].current.val = *(slctab[i].sptr);
+			if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE)
+				slctab[i].current.flag = SLC_NOSUPPORT;
+			else
+				slctab[i].current.flag = slctab[i].defset.flag;
+			add_slc((unsigned char)i, slctab[i].current.flag,
+						slctab[i].current.val);
+		}
+	}
+			
+}  /* check_slc */
+
+/*
+ * do_opt_slc
+ *
+ * Process an slc option buffer.  Defer processing of incoming slc's
+ * until after the terminal state has been processed.  Save the first slc
+ * request that comes along, but discard all others.
+ *
+ * ptr points to the beginning of the buffer, len is the length.
+ */
+	void
+do_opt_slc(ptr, len)
+	register unsigned char *ptr;
+	register int len;
+{
+	register unsigned char func, flag;
+	cc_t val;
+	register unsigned char *end = ptr + len;
+
+	if (terminit()) {  /* go ahead */
+		while (ptr < end) {
+			func = *ptr++;
+			if (ptr >= end) break;
+			flag = *ptr++;
+			if (ptr >= end) break;
+			val = (cc_t)*ptr++;
+
+			process_slc(func, flag, val);
+
+		}
+	} else {
+		/*
+		 * save this slc buffer if it is the first, otherwise dump
+		 * it.
+		 */
+		if (def_slcbuf == (unsigned char *)0) {
+			def_slclen = len;
+			def_slcbuf = (unsigned char *)malloc((unsigned)len);
+			if (def_slcbuf == (unsigned char *)0)
+				return;  /* too bad */
+			memcpy(def_slcbuf, ptr, len);
+		}
+	}
+
+}  /* end of do_opt_slc */
+
+/*
+ * deferslc
+ *
+ * Do slc stuff that was deferred.
+ */
+	void
+deferslc()
+{
+	if (def_slcbuf) {
+		start_slc(1);
+		do_opt_slc(def_slcbuf, def_slclen);
+		(void) end_slc(0);
+		free(def_slcbuf);
+		def_slcbuf = (unsigned char *)0;
+		def_slclen = 0;
+	}
+
+}  /* end of deferslc */
+
+#endif	/* LINEMODE */
diff --git a/krb5-1-6/src/appl/telnet/telnetd/state.c b/krb5-1-6/src/appl/telnet/telnetd/state.c
new file mode 100644
index 000000000..4693fc912
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/state.c
@@ -0,0 +1,1676 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)state.c	8.1 (Berkeley) 6/4/93 */
+
+#include "telnetd.h"
+#if	defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+#endif
+#if defined(ENCRYPTION)
+#include <libtelnet/encrypt.h>
+#endif
+
+unsigned char	doopt[] = { IAC, DO, '%', 'c', 0 };
+unsigned char	dont[] = { IAC, DONT, '%', 'c', 0 };
+unsigned char	will[] = { IAC, WILL, '%', 'c', 0 };
+unsigned char	wont[] = { IAC, WONT, '%', 'c', 0 };
+int	not42 = 1;
+
+static int envvarok (char *);
+
+/*
+ * Buffer for sub-options, and macros
+ * for suboptions buffer manipulations
+ */
+unsigned char subbuffer[TELNET_BUFSIZE], *subpointer= subbuffer, *subend= subbuffer;
+
+#define	SB_CLEAR()	subpointer = subbuffer
+#define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
+#define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
+				*subpointer++ = (c); \
+			}
+#define	SB_GET()	((*subpointer++)&0xff)
+#define	SB_EOF()	(subpointer >= subend)
+#define	SB_LEN()	(subend - subpointer)
+
+#ifdef	ENV_HACK
+unsigned char *subsave;
+#define SB_SAVE()	subsave = subpointer;
+#define	SB_RESTORE()	subpointer = subsave;
+#endif
+
+
+/*
+ * State for recv fsm
+ */
+#define	TS_DATA		0	/* base state */
+#define	TS_IAC		1	/* look for double IAC's */
+#define	TS_CR		2	/* CR-LF ->'s CR */
+#define	TS_SB		3	/* throw away begin's... */
+#define	TS_SE		4	/* ...end's (suboption negotiation) */
+#define	TS_WILL		5	/* will option negotiation */
+#define	TS_WONT		6	/* wont " */
+#define	TS_DO		7	/* do " */
+#define	TS_DONT		8	/* dont " */
+
+static void sb_auth_complete()
+{
+  if (!auth_negotiated) {
+    static char *error =
+      "An environment option was sent before authentication negotiation completed.\r\nThis may create a security hazard. Connection dropped.\r\n";
+    netputs(error);
+    netflush();
+    exit(1);
+  }
+}
+
+	void
+telrcv()
+{
+	register int c;
+	static int state = TS_DATA;
+#if	defined(CRAY2) && defined(UNICOS5)
+	char *opfrontp = pfrontp;
+#endif
+
+	while (ncc > 0) {
+		if ((&ptyobuf[BUFSIZ] - pfrontp) < 1)
+			break;
+		c = *netip++ & 0377, ncc--;
+#ifdef	ENCRYPTION
+		if (decrypt_input)
+			c = (*decrypt_input)(c);
+#endif	/* ENCRYPTION */
+		switch (state) {
+
+		case TS_CR:
+			state = TS_DATA;
+			/* Strip off \n or \0 after a \r */
+			if ((c == 0) || (c == '\n')) {
+				break;
+			}
+			/* FALL THROUGH */
+
+		case TS_DATA:
+			if (c == IAC) {
+				state = TS_IAC;
+				break;
+			}
+			/*
+			 * We now map \r\n ==> \r for pragmatic reasons.
+			 * Many client implementations send \r\n when
+			 * the user hits the CarriageReturn key.
+			 *
+			 * We USED to map \r\n ==> \n, since \r\n says
+			 * that we want to be in column 1 of the next
+			 * printable line, and \n is the standard
+			 * unix way of saying that (\r is only good
+			 * if CRMOD is set, which it normally is).
+			 */
+			if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
+				int nc = *netip;
+#ifdef	ENCRYPTION
+				if (decrypt_input)
+					nc = (*decrypt_input)(nc & 0xff);
+#endif	/* ENCRYPTION */
+#ifdef	LINEMODE
+				/*
+				 * If we are operating in linemode,
+				 * convert to local end-of-line.
+				 */
+				if (linemode && (ncc > 0) && (('\n' == nc) ||
+					 ((0 == nc) && tty_iscrnl())) ) {
+					netip++; ncc--;
+					c = '\n';
+				} else
+#endif
+				{
+#ifdef	ENCRYPTION
+					if (decrypt_input)
+						(void)(*decrypt_input)(-1);
+#endif	/* ENCRYPTION */
+					state = TS_CR;
+				}
+			}
+			*pfrontp++ = c;
+			break;
+
+		case TS_IAC:
+gotiac:			switch (c) {
+
+			/*
+			 * Send the process on the pty side an
+			 * interrupt.  Do this with a NULL or
+			 * interrupt char; depending on the tty mode.
+			 */
+			case IP:
+				DIAG(TD_OPTIONS,
+					printoption("td: recv IAC", c));
+				interrupt();
+				break;
+
+			case BREAK:
+				DIAG(TD_OPTIONS,
+					printoption("td: recv IAC", c));
+				sendbrk();
+				break;
+
+			/*
+			 * Are You There?
+			 */
+			case AYT:
+				DIAG(TD_OPTIONS,
+					printoption("td: recv IAC", c));
+				recv_ayt();
+				break;
+
+			/*
+			 * Abort Output
+			 */
+			case AO:
+			    {
+				DIAG(TD_OPTIONS,
+					printoption("td: recv IAC", c));
+				ptyflush();	/* half-hearted */
+				init_termbuf();
+
+				if (slctab[SLC_AO].sptr &&
+				    *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
+				    *pfrontp++ =
+					(unsigned char)*slctab[SLC_AO].sptr;
+				}
+
+				netclear();	/* clear buffer back */
+				netprintf_urg("%c%c", IAC, DM);
+				DIAG(TD_OPTIONS,
+					printoption("td: send IAC", DM));
+				break;
+			    }
+
+			/*
+			 * Erase Character and
+			 * Erase Line
+			 */
+			case EC:
+			case EL:
+			    {
+				cc_t ch;
+
+				DIAG(TD_OPTIONS,
+					printoption("td: recv IAC", c));
+				ptyflush();	/* half-hearted */
+				init_termbuf();
+				if (c == EC)
+					ch = *slctab[SLC_EC].sptr;
+				else
+					ch = *slctab[SLC_EL].sptr;
+				if (ch != (cc_t)(_POSIX_VDISABLE))
+					*pfrontp++ = (unsigned char)ch;
+				break;
+			    }
+
+			/*
+			 * Check for urgent data...
+			 */
+			case DM:
+				DIAG(TD_OPTIONS,
+					printoption("td: recv IAC", c));
+				SYNCHing = stilloob(net);
+				settimer(gotDM);
+				break;
+
+
+			/*
+			 * Begin option subnegotiation...
+			 */
+			case SB:
+				state = TS_SB;
+				SB_CLEAR();
+				continue;
+
+			case WILL:
+				state = TS_WILL;
+				continue;
+
+			case WONT:
+				state = TS_WONT;
+				continue;
+
+			case DO:
+				state = TS_DO;
+				continue;
+
+			case DONT:
+				state = TS_DONT;
+				continue;
+			case EOR:
+				if (his_state_is_will(TELOPT_EOR))
+					doeof();
+				break;
+
+			/*
+			 * Handle RFC 10xx Telnet linemode option additions
+			 * to command stream (EOF, SUSP, ABORT).
+			 */
+			case xEOF:
+				doeof();
+				break;
+
+			case SUSP:
+				sendsusp();
+				break;
+
+			case ABORT:
+				sendbrk();
+				break;
+
+			case IAC:
+				*pfrontp++ = c;
+				break;
+			}
+			state = TS_DATA;
+			break;
+
+		case TS_SB:
+			if (c == IAC) {
+				state = TS_SE;
+			} else {
+				SB_ACCUM(c);
+			}
+			break;
+
+		case TS_SE:
+			if (c != SE) {
+				if (c != IAC) {
+					/*
+					 * bad form of suboption negotiation.
+					 * handle it in such a way as to avoid
+					 * damage to local state.  Parse
+					 * suboption buffer found so far,
+					 * then treat remaining stream as
+					 * another command sequence.
+					 */
+
+					/* for DIAGNOSTICS */
+					SB_ACCUM(IAC);
+					SB_ACCUM(c);
+					subpointer -= 2;
+
+					SB_TERM();
+					suboption();
+					state = TS_IAC;
+					goto gotiac;
+				}
+				SB_ACCUM(c);
+				state = TS_SB;
+			} else {
+				/* for DIAGNOSTICS */
+				SB_ACCUM(IAC);
+				SB_ACCUM(SE);
+				subpointer -= 2;
+
+				SB_TERM();
+				suboption();	/* handle sub-option */
+				state = TS_DATA;
+			}
+			break;
+
+		case TS_WILL:
+			willoption(c);
+			state = TS_DATA;
+			continue;
+
+		case TS_WONT:
+			wontoption(c);
+			state = TS_DATA;
+			continue;
+
+		case TS_DO:
+			dooption(c);
+			state = TS_DATA;
+			continue;
+
+		case TS_DONT:
+			dontoption(c);
+			state = TS_DATA;
+			continue;
+
+		default:
+			syslog(LOG_ERR, "telnetd: panic state=%d", state);
+			printf("telnetd: panic state=%d\n", state);
+			exit(1);
+		}
+	}
+#if	defined(CRAY2) && defined(UNICOS5)
+	if (!linemode) {
+		char	xptyobuf[BUFSIZ+NETSLOP];
+		char	xbuf2[BUFSIZ];
+		register char *cp;
+		int n = pfrontp - opfrontp, oc;
+		memcpy(xptyobuf, opfrontp, n);
+		pfrontp = opfrontp;
+		pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP,
+					xbuf2, &oc, BUFSIZ);
+		for (cp = xbuf2; oc > 0; --oc) {
+			if (*cp == IAC)
+				netprintf("%c%c", *cp++, IAC);
+			else
+				netprintf("%c", *cp++);
+		}
+	}
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+}  /* end of telrcv */
+
+/*
+ * The will/wont/do/dont state machines are based on Dave Borman's
+ * Telnet option processing state machine.
+ *
+ * These correspond to the following states:
+ *	my_state = the last negotiated state
+ *	want_state = what I want the state to go to
+ *	want_resp = how many requests I have sent
+ * All state defaults are negative, and resp defaults to 0.
+ *
+ * When initiating a request to change state to new_state:
+ * 
+ * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
+ *	do nothing;
+ * } else {
+ *	want_state = new_state;
+ *	send new_state;
+ *	want_resp++;
+ * }
+ *
+ * When receiving new_state:
+ *
+ * if (want_resp) {
+ *	want_resp--;
+ *	if (want_resp && (new_state == my_state))
+ *		want_resp--;
+ * }
+ * if ((want_resp == 0) && (new_state != want_state)) {
+ *	if (ok_to_switch_to new_state)
+ *		want_state = new_state;
+ *	else
+ *		want_resp++;
+ *	send want_state;
+ * }
+ * my_state = new_state;
+ *
+ * Note that new_state is implied in these functions by the function itself.
+ * will and do imply positive new_state, wont and dont imply negative.
+ *
+ * Finally, there is one catch.  If we send a negative response to a
+ * positive request, my_state will be the positive while want_state will
+ * remain negative.  my_state will revert to negative when the negative
+ * acknowlegment arrives from the peer.  Thus, my_state generally tells
+ * us not only the last negotiated state, but also tells us what the peer
+ * wants to be doing as well.  It is important to understand this difference
+ * as we may wish to be processing data streams based on our desired state
+ * (want_state) or based on what the peer thinks the state is (my_state).
+ *
+ * This all works fine because if the peer sends a positive request, the data
+ * that we receive prior to negative acknowlegment will probably be affected
+ * by the positive state, and we can process it as such (if we can; if we
+ * can't then it really doesn't matter).  If it is that important, then the
+ * peer probably should be buffering until this option state negotiation
+ * is complete.
+ *
+ */
+	void
+send_do(option, init)
+	int option, init;
+{
+	if (init) {
+		if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
+		    his_want_state_is_will(option))
+			return;
+		/*
+		 * Special case for TELOPT_TM:  We send a DO, but pretend
+		 * that we sent a DONT, so that we can send more DOs if
+		 * we want to.
+		 */
+		if (option == TELOPT_TM)
+			set_his_want_state_wont(option);
+		else
+			set_his_want_state_will(option);
+		do_dont_resp[option]++;
+	}
+	netprintf((char *)doopt, option);
+
+	DIAG(TD_OPTIONS, printoption("td: send do", option));
+}
+
+#ifdef	AUTHENTICATION
+extern void auth_request();
+#endif
+#ifdef	LINEMODE
+static void doclientstat(void);
+#endif
+#ifdef	ENCRYPTION
+extern void encrypt_send_support();
+#endif	/* ENCRYPTION */
+
+	void
+willoption(option)
+	int option;
+{
+	int changeok = 0;
+	void (*func)() = 0;
+
+	/*
+	 * process input from peer.
+	 */
+
+	DIAG(TD_OPTIONS, printoption("td: recv will", option));
+
+	if (do_dont_resp[option]) {
+		do_dont_resp[option]--;
+		if (do_dont_resp[option] && his_state_is_will(option))
+			do_dont_resp[option]--;
+	}
+	if (do_dont_resp[option] == 0) {
+	    if (his_want_state_is_wont(option)) {
+		switch (option) {
+
+		case TELOPT_BINARY:
+			init_termbuf();
+			tty_binaryin(1);
+			set_termbuf();
+			changeok++;
+			break;
+
+		case TELOPT_ECHO:
+			/*
+			 * See comments below for more info.
+			 */
+			not42 = 0;	/* looks like a 4.2 system */
+			break;
+
+		case TELOPT_TM:
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+			/*
+			 * This telnetd implementation does not really
+			 * support timing marks, it just uses them to
+			 * support the kludge linemode stuff.  If we
+			 * receive a will or wont TM in response to our
+			 * do TM request that may have been sent to
+			 * determine kludge linemode support, process
+			 * it, otherwise TM should get a negative
+			 * response back.
+			 */
+			/*
+			 * Handle the linemode kludge stuff.
+			 * If we are not currently supporting any
+			 * linemode at all, then we assume that this
+			 * is the client telling us to use kludge
+			 * linemode in response to our query.  Set the
+			 * linemode type that is to be supported, note
+			 * that the client wishes to use linemode, and
+			 * eat the will TM as though it never arrived.
+			 */
+			if (lmodetype < KLUDGE_LINEMODE) {
+				lmodetype = KLUDGE_LINEMODE;
+				clientstat(TELOPT_LINEMODE, WILL, 0);
+				send_wont(TELOPT_SGA, 1);
+			} else if (lmodetype == NO_AUTOKLUDGE) {
+				lmodetype = KLUDGE_OK;
+			}
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+			/*
+			 * We never respond to a WILL TM, and
+			 * we leave the state WONT.
+			 */
+			return;
+
+		case TELOPT_LFLOW:
+			/*
+			 * If we are going to support flow control
+			 * option, then don't worry peer that we can't
+			 * change the flow control characters.
+			 */
+			slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
+			slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
+			slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
+			slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
+		case TELOPT_TTYPE:
+		case TELOPT_SGA:
+		case TELOPT_NAWS:
+		case TELOPT_TSPEED:
+		case TELOPT_XDISPLOC:
+		case TELOPT_NEW_ENVIRON:
+		case TELOPT_OLD_ENVIRON:
+			changeok++;
+			break;
+
+#ifdef	LINEMODE
+		case TELOPT_LINEMODE:
+# ifdef	KLUDGELINEMODE
+			/*
+			 * Note client's desire to use linemode.
+			 */
+			lmodetype = REAL_LINEMODE;
+# endif	/* KLUDGELINEMODE */
+			func = doclientstat;
+			changeok++;
+			break;
+#endif	/* LINEMODE */
+
+#ifdef	AUTHENTICATION
+		case TELOPT_AUTHENTICATION:
+			func = auth_request;
+			changeok++;
+			break;
+#endif
+
+#ifdef	ENCRYPTION
+		case TELOPT_ENCRYPT:
+			func = encrypt_send_support;
+			changeok++;
+			break;
+#endif	/* ENCRYPTION */
+
+		default:
+			break;
+		}
+		if (changeok) {
+			set_his_want_state_will(option);
+			send_do(option, 0);
+		} else {
+			do_dont_resp[option]++;
+			send_dont(option, 0);
+		}
+	    } else {
+		/*
+		 * Option processing that should happen when
+		 * we receive conformation of a change in
+		 * state that we had requested.
+		 */
+		switch (option) {
+		case TELOPT_ECHO:
+			not42 = 0;	/* looks like a 4.2 system */
+			/*
+			 * Egads, he responded "WILL ECHO".  Turn
+			 * it off right now!
+			 */
+			send_dont(option, 1);
+			/*
+			 * "WILL ECHO".  Kludge upon kludge!
+			 * A 4.2 client is now echoing user input at
+			 * the tty.  This is probably undesireable and
+			 * it should be stopped.  The client will
+			 * respond WONT TM to the DO TM that we send to
+			 * check for kludge linemode.  When the WONT TM
+			 * arrives, linemode will be turned off and a
+			 * change propogated to the pty.  This change
+			 * will cause us to process the new pty state
+			 * in localstat(), which will notice that
+			 * linemode is off and send a WILL ECHO
+			 * so that we are properly in character mode and
+			 * all is well.
+			 */
+			break;
+#ifdef	LINEMODE
+		case TELOPT_LINEMODE:
+# ifdef	KLUDGELINEMODE
+			/*
+			 * Note client's desire to use linemode.
+			 */
+			lmodetype = REAL_LINEMODE;
+# endif	/* KLUDGELINEMODE */
+			func = doclientstat;
+			break;
+#endif	/* LINEMODE */
+
+#ifdef	AUTHENTICATION
+		case TELOPT_AUTHENTICATION:
+			func = auth_request;
+			break;
+#endif
+
+#ifdef	ENCRYPTION
+		case TELOPT_ENCRYPT:
+			func = encrypt_send_support;
+			break;
+#endif	/* ENCRYPTION */
+		case TELOPT_LFLOW:
+			func = flowstat;
+			break;
+		}
+	    }
+	}
+	set_his_state_will(option);
+	if (func)
+		(*func)();
+}  /* end of willoption */
+
+	void
+send_dont(option, init)
+	int option, init;
+{
+	if (init) {
+		if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) ||
+		    his_want_state_is_wont(option))
+			return;
+		set_his_want_state_wont(option);
+		do_dont_resp[option]++;
+	}
+	netprintf((char *)dont, option);
+
+	DIAG(TD_OPTIONS, printoption("td: send dont", option));
+}
+
+	void
+wontoption(option)
+	int option;
+{
+	/*
+	 * Process client input.
+	 */
+
+	DIAG(TD_OPTIONS, printoption("td: recv wont", option));
+
+	if (do_dont_resp[option]) {
+		do_dont_resp[option]--;
+		if (do_dont_resp[option] && his_state_is_wont(option))
+			do_dont_resp[option]--;
+	}
+	if (do_dont_resp[option] == 0) {
+	    if (his_want_state_is_will(option)) {
+		/* it is always ok to change to negative state */
+		switch (option) {
+		case TELOPT_ECHO:
+			not42 = 1; /* doesn't seem to be a 4.2 system */
+			break;
+
+		case TELOPT_BINARY:
+			init_termbuf();
+			tty_binaryin(0);
+			set_termbuf();
+			break;
+
+#ifdef	LINEMODE
+		case TELOPT_LINEMODE:
+# ifdef	KLUDGELINEMODE
+			/*
+			 * If real linemode is supported, then client is
+			 * asking to turn linemode off.
+			 */
+			if (lmodetype != REAL_LINEMODE)
+				break;
+			lmodetype = KLUDGE_LINEMODE;
+# endif	/* KLUDGELINEMODE */
+			clientstat(TELOPT_LINEMODE, WONT, 0);
+			break;
+#endif	/* LINEMODE */
+
+		case TELOPT_TM:
+			/*
+			 * If we get a WONT TM, and had sent a DO TM,
+			 * don't respond with a DONT TM, just leave it
+			 * as is.  Short circut the state machine to
+			 * achive this.
+			 */
+			set_his_want_state_wont(TELOPT_TM);
+			return;
+
+		case TELOPT_LFLOW:
+			/*
+			 * If we are not going to support flow control
+			 * option, then let peer know that we can't
+			 * change the flow control characters.
+			 */
+			slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
+			slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
+			slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
+			slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
+			break;
+
+#if	defined(AUTHENTICATION)
+		case TELOPT_AUTHENTICATION:
+			auth_finished(0, AUTH_REJECT);
+			break;
+#endif
+
+		/*
+		 * For options that we might spin waiting for
+		 * sub-negotiation, if the client turns off the
+		 * option rather than responding to the request,
+		 * we have to treat it here as if we got a response
+		 * to the sub-negotiation, (by updating the timers)
+		 * so that we'll break out of the loop.
+		 */
+		case TELOPT_TTYPE:
+			settimer(ttypesubopt);
+			break;
+
+		case TELOPT_TSPEED:
+			settimer(tspeedsubopt);
+			break;
+
+		case TELOPT_XDISPLOC:
+			settimer(xdisplocsubopt);
+			break;
+
+		case TELOPT_OLD_ENVIRON:
+			settimer(oenvironsubopt);
+			break;
+
+		case TELOPT_NEW_ENVIRON:
+			settimer(environsubopt);
+			break;
+
+		default:
+			break;
+		}
+		set_his_want_state_wont(option);
+		if (his_state_is_will(option))
+			send_dont(option, 0);
+	    } else {
+		switch (option) {
+		case TELOPT_TM:
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+			if (lmodetype < NO_AUTOKLUDGE) {
+				lmodetype = NO_LINEMODE;
+				clientstat(TELOPT_LINEMODE, WONT, 0);
+				send_will(TELOPT_SGA, 1);
+				send_will(TELOPT_ECHO, 1);
+			}
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+			break;
+
+#if	defined(AUTHENTICATION)
+		case TELOPT_AUTHENTICATION:
+			auth_finished(0, AUTH_REJECT);
+			break;
+#endif
+		default:
+			break;
+		}
+	    }
+	}
+	set_his_state_wont(option);
+
+}  /* end of wontoption */
+
+	void
+send_will(option, init)
+	int option, init;
+{
+	if (init) {
+		if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
+		    my_want_state_is_will(option))
+			return;
+		set_my_want_state_will(option);
+		will_wont_resp[option]++;
+	}
+	netprintf((char *)will, option);
+
+	DIAG(TD_OPTIONS, printoption("td: send will", option));
+}
+
+#if	!defined(LINEMODE) || !defined(KLUDGELINEMODE)
+/*
+ * When we get a DONT SGA, we will try once to turn it
+ * back on.  If the other side responds DONT SGA, we
+ * leave it at that.  This is so that when we talk to
+ * clients that understand KLUDGELINEMODE but not LINEMODE,
+ * we'll keep them in char-at-a-time mode.
+ */
+int turn_on_sga = 0;
+#endif
+
+	void
+dooption(option)
+	int option;
+{
+	int changeok = 0;
+
+	/*
+	 * Process client input.
+	 */
+
+	DIAG(TD_OPTIONS, printoption("td: recv do", option));
+
+	if (will_wont_resp[option]) {
+		will_wont_resp[option]--;
+		if (will_wont_resp[option] && my_state_is_will(option))
+			will_wont_resp[option]--;
+	}
+	if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
+		switch (option) {
+		case TELOPT_ECHO:
+#ifdef	LINEMODE
+# ifdef	KLUDGELINEMODE
+			if (lmodetype == NO_LINEMODE)
+# else
+			if (his_state_is_wont(TELOPT_LINEMODE))
+# endif
+#endif
+			{
+				init_termbuf();
+				tty_setecho(1);
+				set_termbuf();
+			}
+			changeok++;
+			break;
+
+		case TELOPT_BINARY:
+			init_termbuf();
+			tty_binaryout(1);
+			set_termbuf();
+			changeok++;
+			break;
+
+		case TELOPT_SGA:
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+			/*
+			 * If kludge linemode is in use, then we must
+			 * process an incoming do SGA for linemode
+			 * purposes.
+			 */
+			if (lmodetype == KLUDGE_LINEMODE) {
+				/*
+				 * Receipt of "do SGA" in kludge
+				 * linemode is the peer asking us to
+				 * turn off linemode.  Make note of
+				 * the request.
+				 */
+				clientstat(TELOPT_LINEMODE, WONT, 0);
+				/*
+				 * If linemode did not get turned off
+				 * then don't tell peer that we did.
+				 * Breaking here forces a wont SGA to
+				 * be returned.
+				 */
+				if (linemode)
+					break;
+			}
+#else
+			turn_on_sga = 0;
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+			changeok++;
+			break;
+
+		case TELOPT_STATUS:
+			changeok++;
+			break;
+
+		case TELOPT_TM:
+			/*
+			 * Special case for TM.  We send a WILL, but
+			 * pretend we sent a WONT.
+			 */
+			send_will(option, 0);
+			set_my_want_state_wont(option);
+			set_my_state_wont(option);
+			return;
+
+		case TELOPT_LOGOUT:
+			/*
+			 * When we get a LOGOUT option, respond
+			 * with a WILL LOGOUT, make sure that
+			 * it gets written out to the network,
+			 * and then just go away...
+			 */
+			set_my_want_state_will(TELOPT_LOGOUT);
+			send_will(TELOPT_LOGOUT, 0);
+			set_my_state_will(TELOPT_LOGOUT);
+			(void)netflush();
+			(void)signal(SIGCHLD, SIG_DFL);
+			cleanup(0);
+			/* NOT REACHED */
+			break;
+
+#ifdef	ENCRYPTION
+		case TELOPT_ENCRYPT:
+			changeok++;
+			break;
+#endif	/* ENCRYPTION */
+		case TELOPT_LINEMODE:
+		case TELOPT_TTYPE:
+		case TELOPT_NAWS:
+		case TELOPT_TSPEED:
+		case TELOPT_LFLOW:
+		case TELOPT_XDISPLOC:
+#ifdef	TELOPT_ENVIRON
+		case TELOPT_NEW_ENVIRON:
+#endif
+		case TELOPT_OLD_ENVIRON:
+		default:
+			break;
+		}
+		if (changeok) {
+			set_my_want_state_will(option);
+			send_will(option, 0);
+		} else {
+			will_wont_resp[option]++;
+			send_wont(option, 0);
+		}
+	}
+	set_my_state_will(option);
+
+}  /* end of dooption */
+
+	void
+send_wont(option, init)
+	int option, init;
+{
+	if (init) {
+		if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
+		    my_want_state_is_wont(option))
+			return;
+		set_my_want_state_wont(option);
+		will_wont_resp[option]++;
+	}
+	netprintf((char *)wont, option);
+
+	DIAG(TD_OPTIONS, printoption("td: send wont", option));
+}
+
+	void
+dontoption(option)
+	int option;
+{
+	/*
+	 * Process client input.
+	 */
+
+
+	DIAG(TD_OPTIONS, printoption("td: recv dont", option));
+
+	if (will_wont_resp[option]) {
+		will_wont_resp[option]--;
+		if (will_wont_resp[option] && my_state_is_wont(option))
+			will_wont_resp[option]--;
+	}
+	if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
+		switch (option) {
+		case TELOPT_BINARY:
+			init_termbuf();
+			tty_binaryout(0);
+			set_termbuf();
+			break;
+
+		case TELOPT_ECHO:	/* we should stop echoing */
+#ifdef	LINEMODE
+# ifdef	KLUDGELINEMODE
+			if ((lmodetype != REAL_LINEMODE) &&
+			    (lmodetype != KLUDGE_LINEMODE))
+# else
+			if (his_state_is_wont(TELOPT_LINEMODE))
+# endif
+#endif
+			{
+				init_termbuf();
+				tty_setecho(0);
+				set_termbuf();
+			}
+			break;
+
+		case TELOPT_SGA:
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+			/*
+			 * If kludge linemode is in use, then we
+			 * must process an incoming do SGA for
+			 * linemode purposes.
+			 */
+			if ((lmodetype == KLUDGE_LINEMODE) ||
+			    (lmodetype == KLUDGE_OK)) {
+				/*
+				 * The client is asking us to turn
+				 * linemode on.
+				 */
+				lmodetype = KLUDGE_LINEMODE;
+				clientstat(TELOPT_LINEMODE, WILL, 0);
+				/*
+				 * If we did not turn line mode on,
+				 * then what do we say?  Will SGA?
+				 * This violates design of telnet.
+				 * Gross.  Very Gross.
+				 */
+			}
+			break;
+#else
+			set_my_want_state_wont(option);
+			if (my_state_is_will(option))
+				send_wont(option, 0);
+			set_my_state_wont(option);
+			if (turn_on_sga ^= 1)
+				send_will(option, 1);
+			return;
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+
+		default:
+			break;
+		}
+
+		set_my_want_state_wont(option);
+		if (my_state_is_will(option))
+			send_wont(option, 0);
+	}
+	set_my_state_wont(option);
+
+}  /* end of dontoption */
+
+#ifdef	ENV_HACK
+int env_ovar = -1;
+int env_ovalue = -1;
+#else	/* ENV_HACK */
+# define env_ovar OLD_ENV_VAR
+# define env_ovalue OLD_ENV_VALUE
+#endif	/* ENV_HACK */
+
+/*
+ * suboption()
+ *
+ *	Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ *
+ *	Currently we recognize:
+ *
+ *	Terminal type is
+ *	Linemode
+ *	Window size
+ *	Terminal speed
+ */
+	void
+suboption()
+{
+    register int subchar;
+
+    DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
+
+    subchar = SB_GET();
+    switch (subchar) {
+    case TELOPT_TSPEED: {
+	register int xspeed, rspeed;
+
+	if (his_state_is_wont(TELOPT_TSPEED))	/* Ignore if option disabled */
+		break;
+
+	sb_auth_complete();
+	
+	settimer(tspeedsubopt);
+
+	if (SB_EOF() || SB_GET() != TELQUAL_IS)
+		return;
+
+	xspeed = atoi((char *)subpointer);
+
+	while (SB_GET() != ',' && !SB_EOF());
+	if (SB_EOF())
+		return;
+
+	rspeed = atoi((char *)subpointer);
+	clientstat(TELOPT_TSPEED, xspeed, rspeed);
+
+	break;
+
+    }  /* end of case TELOPT_TSPEED */
+
+    case TELOPT_TTYPE: {		/* Yaaaay! */
+	char *tt;
+
+	if (his_state_is_wont(TELOPT_TTYPE))	/* Ignore if option disabled */
+		break;
+	sb_auth_complete();
+	settimer(ttypesubopt);
+
+	if (SB_EOF() || SB_GET() != TELQUAL_IS) {
+	    return;		/* ??? XXX but, this is the most robust */
+	}
+
+	tt = terminaltype;
+
+	while ((tt < (terminaltype + sizeof(terminaltype) - 1)) && !SB_EOF()) {
+	    register int c;
+
+	    c = SB_GET();
+	    if (isupper(c)) {
+		c = tolower(c);
+	    }
+	    *tt++ = c;    /* accumulate name */
+	}
+	*tt = 0;
+	break;
+    }  /* end of case TELOPT_TTYPE */
+
+    case TELOPT_NAWS: {
+	register int xwinsize, ywinsize;
+
+	if (his_state_is_wont(TELOPT_NAWS))	/* Ignore if option disabled */
+		break;
+
+	if (SB_EOF())
+		return;
+	xwinsize = SB_GET() << 8;
+	if (SB_EOF())
+		return;
+	xwinsize |= SB_GET();
+	if (SB_EOF())
+		return;
+	ywinsize = SB_GET() << 8;
+	if (SB_EOF())
+		return;
+	ywinsize |= SB_GET();
+	clientstat(TELOPT_NAWS, xwinsize, ywinsize);
+
+	break;
+
+    }  /* end of case TELOPT_NAWS */
+
+#ifdef	LINEMODE
+    case TELOPT_LINEMODE: {
+	register int request;
+
+	if (his_state_is_wont(TELOPT_LINEMODE))	/* Ignore if option disabled */
+		break;
+	/*
+	 * Process linemode suboptions.
+	 */
+	if (SB_EOF())
+	    break;		/* garbage was sent */
+	request = SB_GET();	/* get will/wont */
+
+	if (SB_EOF())
+	    break;		/* another garbage check */
+
+	if (request == LM_SLC) {  /* SLC is not preceeded by WILL or WONT */
+		/*
+		 * Process suboption buffer of slc's
+		 */
+		start_slc(1);
+		do_opt_slc(subpointer, subend - subpointer);
+		(void) end_slc(0);
+		break;
+	} else if (request == LM_MODE) {
+		if (SB_EOF())
+		    return;
+		useeditmode = SB_GET();  /* get mode flag */
+		clientstat(LM_MODE, 0, 0);
+		break;
+	}
+
+	if (SB_EOF())
+	    break;
+	switch (SB_GET()) {  /* what suboption? */
+	case LM_FORWARDMASK:
+		/*
+		 * According to spec, only server can send request for
+		 * forwardmask, and client can only return a positive response.
+		 * So don't worry about it.
+		 */
+
+	default:
+		break;
+	}
+	break;
+    }  /* end of case TELOPT_LINEMODE */
+#endif
+    case TELOPT_STATUS: {
+	int mode;
+
+	if (SB_EOF())
+	    break;
+	mode = SB_GET();
+	switch (mode) {
+	case TELQUAL_SEND:
+	    if (my_state_is_will(TELOPT_STATUS))
+		send_status();
+	    break;
+
+	case TELQUAL_IS:
+	    break;
+
+	default:
+	    break;
+	}
+	break;
+    }  /* end of case TELOPT_STATUS */
+
+    case TELOPT_XDISPLOC: {
+	if (SB_EOF() || SB_GET() != TELQUAL_IS)
+		return;
+	sb_auth_complete();
+	settimer(xdisplocsubopt);
+	subpointer[SB_LEN()] = '\0';
+	(void)setenv("DISPLAY", (char *)subpointer, 1);
+	break;
+    }  /* end of case TELOPT_XDISPLOC */
+
+#ifdef	TELOPT_NEW_ENVIRON
+    case TELOPT_NEW_ENVIRON:
+#endif
+    case TELOPT_OLD_ENVIRON: {
+	register int c;
+	register char *cp, *varp, *valp;
+
+	if (SB_EOF())
+		return;
+	sb_auth_complete();
+	c = SB_GET();
+	if (c == TELQUAL_IS) {
+		if (subchar == TELOPT_OLD_ENVIRON)
+			settimer(oenvironsubopt);
+		else
+			settimer(environsubopt);
+	} else if (c != TELQUAL_INFO) {
+		return;
+	}
+
+#ifdef	TELOPT_NEW_ENVIRON
+	if (subchar == TELOPT_NEW_ENVIRON) {
+	    while (!SB_EOF()) {
+		c = SB_GET();
+		if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
+			break;
+	    }
+	} else
+#endif
+	{
+#ifdef	ENV_HACK
+	    /*
+	     * We only want to do this if we haven't already decided
+	     * whether or not the other side has its VALUE and VAR
+	     * reversed.
+	     */
+	    if (env_ovar < 0) {
+		register int last = -1;		/* invalid value */
+		int empty = 0;
+		int got_var = 0, got_value = 0, got_uservar = 0;
+
+		/*
+		 * The other side might have its VALUE and VAR values
+		 * reversed.  To be interoperable, we need to determine
+		 * which way it is.  If the first recognized character
+		 * is a VAR or VALUE, then that will tell us what
+		 * type of client it is.  If the fist recognized
+		 * character is a USERVAR, then we continue scanning
+		 * the suboption looking for two consecutive
+		 * VAR or VALUE fields.  We should not get two
+		 * consecutive VALUE fields, so finding two
+		 * consecutive VALUE or VAR fields will tell us
+		 * what the client is.
+		 */
+		SB_SAVE();
+		while (!SB_EOF()) {
+			c = SB_GET();
+			switch(c) {
+			case OLD_ENV_VAR:
+				if (last < 0 || last == OLD_ENV_VAR
+				    || (empty && (last == OLD_ENV_VALUE)))
+					goto env_ovar_ok;
+				got_var++;
+				last = OLD_ENV_VAR;
+				break;
+			case OLD_ENV_VALUE:
+				if (last < 0 || last == OLD_ENV_VALUE
+				    || (empty && (last == OLD_ENV_VAR)))
+					goto env_ovar_wrong;
+				got_value++;
+				last = OLD_ENV_VALUE;
+				break;
+			case ENV_USERVAR:
+				/* count strings of USERVAR as one */
+				if (last != ENV_USERVAR)
+					got_uservar++;
+				if (empty) {
+					if (last == OLD_ENV_VALUE)
+						goto env_ovar_ok;
+					if (last == OLD_ENV_VAR)
+						goto env_ovar_wrong;
+				}
+				last = ENV_USERVAR;
+				break;
+			case ENV_ESC:
+				if (!SB_EOF())
+					c = SB_GET();
+				/* FALL THROUGH */
+			default:
+				empty = 0;
+				continue;
+			}
+			empty = 1;
+		}
+		if (empty) {
+			if (last == OLD_ENV_VALUE)
+				goto env_ovar_ok;
+			if (last == OLD_ENV_VAR)
+				goto env_ovar_wrong;
+		}
+		/*
+		 * Ok, the first thing was a USERVAR, and there
+		 * are not two consecutive VAR or VALUE commands,
+		 * and none of the VAR or VALUE commands are empty.
+		 * If the client has sent us a well-formed option,
+		 * then the number of VALUEs received should always
+		 * be less than or equal to the number of VARs and
+		 * USERVARs received.
+		 *
+		 * If we got exactly as many VALUEs as VARs and
+		 * USERVARs, the client has the same definitions.
+		 *
+		 * If we got exactly as many VARs as VALUEs and
+		 * USERVARS, the client has reversed definitions.
+		 */
+		if (got_uservar + got_var == got_value) {
+	    env_ovar_ok:
+			env_ovar = OLD_ENV_VAR;
+			env_ovalue = OLD_ENV_VALUE;
+		} else if (got_uservar + got_value == got_var) {
+	    env_ovar_wrong:
+			env_ovar = OLD_ENV_VALUE;
+			env_ovalue = OLD_ENV_VAR;
+			DIAG(TD_OPTIONS,
+			     netputs("ENVIRON VALUE and VAR are reversed!\r\n"));
+		}
+	    }
+	    SB_RESTORE();
+#endif
+
+	    while (!SB_EOF()) {
+		c = SB_GET();
+		if ((c == env_ovar) || (c == ENV_USERVAR))
+			break;
+	    }
+	}
+
+	if (SB_EOF())
+		return;
+
+	cp = varp = (char *)subpointer;
+	valp = 0;
+
+	while (!SB_EOF()) {
+		c = SB_GET();
+		if (subchar == TELOPT_OLD_ENVIRON) {
+			if (c == env_ovar)
+				c = NEW_ENV_VAR;
+			else if (c == env_ovalue)
+				c = NEW_ENV_VALUE;
+		}
+		switch (c) {
+
+		case NEW_ENV_VALUE:
+			*cp = '\0';
+			cp = valp = (char *)subpointer;
+			break;
+
+		case NEW_ENV_VAR:
+		case ENV_USERVAR:
+			*cp = '\0';
+			if (envvarok(varp)) {
+				if (valp)
+					(void)setenv(varp, valp, 1);
+				else
+					unsetenv(varp);
+			}
+			cp = varp = (char *)subpointer;
+			valp = 0;
+			break;
+
+		case ENV_ESC:
+			if (SB_EOF())
+				break;
+			c = SB_GET();
+			/* FALL THROUGH */
+		default:
+			*cp++ = c;
+			break;
+		}
+	}
+	*cp = '\0';
+	if (envvarok(varp)) {
+		if (valp)
+			(void)setenv(varp, valp, 1);
+		else
+			unsetenv(varp);
+	}
+	break;
+    }  /* end of case TELOPT_NEW_ENVIRON */
+#if	defined(AUTHENTICATION)
+    case TELOPT_AUTHENTICATION:
+	if (SB_EOF())
+		break;
+	switch(SB_GET()) {
+	case TELQUAL_SEND:
+	case TELQUAL_REPLY:
+		/*
+		 * These are sent by us and cannot be sent by
+		 * the client.
+		 */
+		break;
+	case TELQUAL_IS:
+		if (!auth_negotiated)
+			auth_is(subpointer, SB_LEN());
+		break;
+	case TELQUAL_NAME:
+		if (!auth_negotiated)
+			auth_name(subpointer, SB_LEN());
+		break;
+	}
+	break;
+#endif
+#ifdef	ENCRYPTION
+    case TELOPT_ENCRYPT:
+	if (SB_EOF())
+		break;
+	switch(SB_GET()) {
+	case ENCRYPT_SUPPORT:
+		encrypt_support(subpointer, SB_LEN());
+		break;
+	case ENCRYPT_IS:
+		encrypt_is(subpointer, SB_LEN());
+		break;
+	case ENCRYPT_REPLY:
+		encrypt_reply(subpointer, SB_LEN());
+		break;
+	case ENCRYPT_START:
+		encrypt_start(subpointer, SB_LEN());
+		break;
+	case ENCRYPT_END:
+		encrypt_end();
+		break;
+	case ENCRYPT_REQSTART:
+		encrypt_request_start(subpointer, SB_LEN());
+		break;
+	case ENCRYPT_REQEND:
+		/*
+		 * We can always send an REQEND so that we cannot
+		 * get stuck encrypting.  We should only get this
+		 * if we have been able to get in the correct mode
+		 * anyhow.
+		 */
+		encrypt_request_end();
+		break;
+	case ENCRYPT_ENC_KEYID:
+		encrypt_enc_keyid(subpointer, SB_LEN());
+		break;
+	case ENCRYPT_DEC_KEYID:
+		encrypt_dec_keyid(subpointer, SB_LEN());
+		break;
+	default:
+		break;
+	}
+	break;
+#endif	/* ENCRYPTION */
+
+    default:
+	break;
+    }  /* end of switch */
+
+}  /* end of suboption */
+
+#ifdef	LINEMODE
+static	void
+doclientstat()
+{
+	clientstat(TELOPT_LINEMODE, WILL, 0);
+}
+#endif
+
+#define	ADD(c)	 *ncp++ = c;
+#define	ADD_DATA(c) { *ncp++ = c; if (c == SE) *ncp++ = c; }
+	void
+send_status()
+{
+	unsigned char statusbuf[256];
+	register unsigned char *ncp;
+	register unsigned char i;
+
+	ncp = statusbuf;
+
+	netflush();	/* get rid of anything waiting to go out */
+
+	ADD(IAC);
+	ADD(SB);
+	ADD(TELOPT_STATUS);
+	ADD(TELQUAL_IS);
+
+	/*
+	 * We check the want_state rather than the current state,
+	 * because if we received a DO/WILL for an option that we
+	 * don't support, and the other side didn't send a DONT/WONT
+	 * in response to our WONT/DONT, then the "state" will be
+	 * WILL/DO, and the "want_state" will be WONT/DONT.  We
+	 * need to go by the latter.
+	 */
+	for (i = 0; i < (unsigned char)NTELOPTS; i++) {
+		if (my_want_state_is_will(i)) {
+			ADD(WILL);
+			ADD_DATA(i);
+			if (i == IAC)
+				ADD(IAC);
+		}
+		if (his_want_state_is_will(i)) {
+			ADD(DO);
+			ADD_DATA(i);
+			if (i == IAC)
+				ADD(IAC);
+		}
+	}
+
+	if (his_want_state_is_will(TELOPT_LFLOW)) {
+		ADD(SB);
+		ADD(TELOPT_LFLOW);
+		if (flowmode) {
+			ADD(LFLOW_ON);
+		} else {
+			ADD(LFLOW_OFF);
+		}
+		ADD(SE);
+
+		if (restartany >= 0) {
+			ADD(SB)
+			ADD(TELOPT_LFLOW);
+			if (restartany) {
+				ADD(LFLOW_RESTART_ANY);
+			} else {
+				ADD(LFLOW_RESTART_XON);
+			}
+			ADD(SE)
+			ADD(SB);
+		}
+	}
+
+#ifdef	LINEMODE
+	if (his_want_state_is_will(TELOPT_LINEMODE)) {
+		unsigned char *cp, *cpe;
+		int len;
+
+		ADD(SB);
+		ADD(TELOPT_LINEMODE);
+		ADD(LM_MODE);
+		ADD_DATA(editmode);
+		if (editmode == IAC)
+			ADD(IAC);
+		ADD(SE);
+
+		ADD(SB);
+		ADD(TELOPT_LINEMODE);
+		ADD(LM_SLC);
+		start_slc(0);
+		send_slc();
+		len = end_slc(&cp);
+		for (cpe = cp + len; cp < cpe; cp++)
+			ADD_DATA(*cp);
+		ADD(SE);
+	}
+#endif	/* LINEMODE */
+
+	ADD(IAC);
+	ADD(SE);
+
+	netwrite(statusbuf, (unsigned) (ncp - statusbuf));
+	netflush();	/* Send it on its way */
+
+	DIAG(TD_OPTIONS,
+		{printsub('>', statusbuf, ncp - statusbuf); netflush();});
+}
+
+static int envvarok(varp)
+	char *varp;
+{
+	if (!strchr(varp, '=') &&
+	    strcmp(varp, "TERMCAP") && /* to prevent a security hole  */
+	    strcmp(varp, "TERMINFO") &&	/* with tgetent */
+	    strcmp(varp, "TERMPATH") &&
+	    strcmp(varp, "HOME") && /* to prevent the tegetent bug  */
+	    strncmp(varp, "LD_", strlen("LD_")) && /* most systems */
+	    strncmp(varp, "_RLD_", strlen("_RLD_")) && /* irix */
+	    strncmp(varp, "KRB5", strlen("KRB5")) && /* v5 */
+	    /* The above is a catch-all for now.  Here are some of the
+	       specific ones we must avoid passing, at least until we
+	       can prove it can be done safely.  Keep this list around
+	       in case someone wants to remove the catch-all.  */
+	    strcmp(varp, "KRB5_CONFIG") && /* v5 */
+	    strcmp(varp, "KRB5CCNAME") &&  /* v5 */
+	    strcmp(varp, "KRB5_KTNAME") && /* v5 */
+	    strcmp(varp, "KRBTKFILE") &&   /* v4 */
+	    strcmp(varp, "KRB_CONF") &&	   /* cns v4 */
+	    strcmp(varp, "KRB_REALMS") &&  /* cns v4 */
+	    strcmp(varp, "LIBPATH") &&     /* AIX */
+	    strcmp(varp, "RESOLV_HOST_CONF") && /* linux */
+	    strcmp(varp, "NLSPATH") && /* locale stuff */
+	    strncmp(varp, "LC_", strlen("LC_")) && /* locale stuff */
+	    strcmp(varp, "IFS") &&
+	    (varp[0] != '-')) {
+		return 1;
+	} else {
+		syslog(LOG_INFO, "Rejected the attempt to modify the environment variable \"%s\"", varp);
+		return 0;
+	}
+
+}
diff --git a/krb5-1-6/src/appl/telnet/telnetd/sys_term.c b/krb5-1-6/src/appl/telnet/telnetd/sys_term.c
new file mode 100644
index 000000000..d78c2e83d
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/sys_term.c
@@ -0,0 +1,1498 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* baesd on @(#)sys_term.c	8.1 (Berkeley) 6/4/93 */
+
+#include "telnetd.h"
+#include "pathnames.h"
+#include <com_err.h>
+
+#ifndef LOGIN_PROGRAM
+#define LOGIN_PROGRAM _PATH_LOGIN
+#endif
+
+#include <libpty.h>
+#if	defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+#endif
+
+#if	defined(KRB5)
+#include "k5-int.h"
+#endif
+
+char *login_program = LOGIN_PROGRAM;
+
+#ifdef	NEWINIT
+#include <initreq.h>
+int	utmp_len = MAXHOSTNAMELEN;	/* sizeof(init_request.host) */
+#else	/* NEWINIT*/
+
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+
+#ifdef _PATH_WTMP
+char	wtmpf[] = _PATH_WTMP;
+#else
+char	wtmpf[]	= "/usr/adm/wtmp";
+#endif
+
+#ifdef _PATH_UTMP
+char 	utmpf[] = _PATH_UTMP;
+#else
+char	utmpf[] = "/etc/utmp";
+#endif
+  
+# ifdef CRAY
+#include <tmpdir.h>
+#include <sys/wait.h>
+#  if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY)
+   /*
+    * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can
+    * use it to tell us to turn off all the socket security code,
+    * since that is only used in UNICOS 7.0 and later.
+    */
+#   undef _SC_CRAY_SECURE_SYS
+#  endif
+
+#  if defined(_SC_CRAY_SECURE_SYS)
+#include <sys/sysv.h>
+#include <sys/secstat.h>
+extern int secflag;
+extern struct sysv sysv;
+#  endif /* _SC_CRAY_SECURE_SYS */
+# endif	/* CRAY */
+#endif	/* NEWINIT */
+
+#ifdef	STREAMSPTY
+#ifdef HAVE_SAC_H
+#include <sac.h> 
+#endif
+#include <sys/stropts.h>
+#endif
+
+#define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
+#define SCMPN(a, b)	strncmp(a, b, sizeof(a))
+
+#ifdef	HAVE_SYS_STREAM_H
+#include <sys/stream.h>
+#endif
+#ifdef __hpux
+#include <sys/resource.h>
+#include <sys/proc.h>
+#endif
+	/* For what platforms do we really need sys/tty.h? */
+#ifdef HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif
+	
+#ifdef	t_erase
+#undef	t_erase
+#undef	t_kill
+#undef	t_intrc
+#undef	t_quitc
+#undef	t_startc
+#undef	t_stopc
+#undef	t_eofc
+#undef	t_brkc
+#undef	t_suspc
+#undef	t_dsuspc
+#undef	t_rprntc
+#undef	t_flushc
+#undef	t_werasc
+#undef	t_lnextc
+#endif
+
+#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
+# define EXTPROC 0400
+#endif
+
+#ifndef	USE_TERMIO
+struct termbuf {
+	struct sgttyb sg;
+	struct tchars tc;
+	struct ltchars ltc;
+	int state;
+	int lflags;
+} termbuf, termbuf2;
+# define	cfsetospeed(tp, val)	(tp)->sg.sg_ospeed = (val)
+# define	cfsetispeed(tp, val)	(tp)->sg.sg_ispeed = (val)
+# define	cfgetospeed(tp)		(tp)->sg.sg_ospeed
+# define	cfgetispeed(tp)		(tp)->sg.sg_ispeed
+#else	/* USE_TERMIO */
+# ifdef	SYSV_TERMIO
+#	define termios termio
+# endif
+# ifndef	TCSANOW
+#  ifdef TCSETS
+#   define	TCSANOW		TCSETS
+#   define	TCSADRAIN	TCSETSW
+#   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
+#  else
+#   ifdef TCSETA
+#    define	TCSANOW		TCSETA
+#    define	TCSADRAIN	TCSETAW
+#    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
+#   else
+#    define	TCSANOW		TIOCSETA
+#    define	TCSADRAIN	TIOCSETAW
+#    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
+#   endif
+#  endif
+#  define	tcsetattr(f, a, t)	ioctl(f, a, t)
+#  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
+					(tp)->c_cflag |= (val)
+#  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
+#  ifdef CIBAUD
+#   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
+					(tp)->c_cflag |= ((val)<<IBSHIFT)
+#   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
+#  else
+#   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
+					(tp)->c_cflag |= (val)
+#   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
+#  endif
+# endif /* TCSANOW */
+struct termios termbuf, termbuf2;	/* pty control structure */
+# ifdef  STREAMSPTY
+int ttyfd = -1;
+# endif
+#endif	/* USE_TERMIO */
+
+#ifndef SETPGRP_TWOARG
+#define setpgrp(a,b) setpgrp()
+#endif
+
+int dup_tty(int);
+static char **addarg(char **, char *);
+
+/*
+ * init_termbuf()
+ * copy_termbuf(cp)
+ * set_termbuf()
+ *
+ * These three routines are used to get and set the "termbuf" structure
+ * to and from the kernel.  init_termbuf() gets the current settings.
+ * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
+ * set_termbuf() writes the structure into the kernel.
+ */
+
+	void
+init_termbuf()
+{
+#ifndef	USE_TERMIO
+	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
+	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
+	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
+# ifdef	TIOCGSTATE
+	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
+# endif
+#else
+# ifdef  STREAMSPTY
+	(void) tcgetattr(ttyfd, &termbuf);
+# else
+	(void) tcgetattr(pty, &termbuf);
+# endif
+#endif
+	termbuf2 = termbuf;
+}
+
+#if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
+	void
+copy_termbuf(cp, len)
+	char *cp;
+	int len;
+{
+	if (len > sizeof(termbuf))
+		len = sizeof(termbuf);
+	memcpy((char *)&termbuf, cp, len);
+	termbuf2 = termbuf;
+}
+#endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
+
+	void
+set_termbuf()
+{
+	/*
+	 * Only make the necessary changes.
+	 */
+#ifndef	USE_TERMIO
+	if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
+		(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
+	if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
+		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
+	if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
+							sizeof(termbuf.ltc)))
+		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
+	if (termbuf.lflags != termbuf2.lflags)
+		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
+#else	/* USE_TERMIO */
+	if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
+# ifdef  STREAMSPTY
+		(void) tcsetattr(ttyfd, TCSANOW, &termbuf);
+# else
+		(void) tcsetattr(pty, TCSANOW, &termbuf);
+# endif
+# if	defined(CRAY2) && defined(UNICOS5)
+	needtermstat = 1;
+# endif
+#endif	/* USE_TERMIO */
+}
+
+
+/*
+ * spcset(func, valp, valpp)
+ *
+ * This function takes various special characters (func), and
+ * sets *valp to the current value of that character, and
+ * *valpp to point to where in the "termbuf" structure that
+ * value is kept.
+ *
+ * It returns the SLC_ level of support for this function.
+ */
+
+#ifndef	USE_TERMIO
+	int
+spcset(func, valp, valpp)
+	int func;
+	cc_t *valp;
+	cc_t **valpp;
+{
+	switch(func) {
+	case SLC_EOF:
+		*valp = termbuf.tc.t_eofc;
+		*valpp = (cc_t *)&termbuf.tc.t_eofc;
+		return(SLC_VARIABLE);
+	case SLC_EC:
+		*valp = termbuf.sg.sg_erase;
+		*valpp = (cc_t *)&termbuf.sg.sg_erase;
+		return(SLC_VARIABLE);
+	case SLC_EL:
+		*valp = termbuf.sg.sg_kill;
+		*valpp = (cc_t *)&termbuf.sg.sg_kill;
+		return(SLC_VARIABLE);
+	case SLC_IP:
+		*valp = termbuf.tc.t_intrc;
+		*valpp = (cc_t *)&termbuf.tc.t_intrc;
+		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+	case SLC_ABORT:
+		*valp = termbuf.tc.t_quitc;
+		*valpp = (cc_t *)&termbuf.tc.t_quitc;
+		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+	case SLC_XON:
+		*valp = termbuf.tc.t_startc;
+		*valpp = (cc_t *)&termbuf.tc.t_startc;
+		return(SLC_VARIABLE);
+	case SLC_XOFF:
+		*valp = termbuf.tc.t_stopc;
+		*valpp = (cc_t *)&termbuf.tc.t_stopc;
+		return(SLC_VARIABLE);
+	case SLC_AO:
+		*valp = termbuf.ltc.t_flushc;
+		*valpp = (cc_t *)&termbuf.ltc.t_flushc;
+		return(SLC_VARIABLE);
+	case SLC_SUSP:
+		*valp = termbuf.ltc.t_suspc;
+		*valpp = (cc_t *)&termbuf.ltc.t_suspc;
+		return(SLC_VARIABLE);
+	case SLC_EW:
+		*valp = termbuf.ltc.t_werasc;
+		*valpp = (cc_t *)&termbuf.ltc.t_werasc;
+		return(SLC_VARIABLE);
+	case SLC_RP:
+		*valp = termbuf.ltc.t_rprntc;
+		*valpp = (cc_t *)&termbuf.ltc.t_rprntc;
+		return(SLC_VARIABLE);
+	case SLC_LNEXT:
+		*valp = termbuf.ltc.t_lnextc;
+		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
+		return(SLC_VARIABLE);
+	case SLC_FORW1:
+		*valp = termbuf.tc.t_brkc;
+		*valpp = (cc_t *)&termbuf.ltc.t_lnextc;
+		return(SLC_VARIABLE);
+	case SLC_BRK:
+	case SLC_SYNCH:
+	case SLC_AYT:
+	case SLC_EOR:
+		*valp = (cc_t)0;
+		*valpp = (cc_t *)0;
+		return(SLC_DEFAULT);
+	default:
+		*valp = (cc_t)0;
+		*valpp = (cc_t *)0;
+		return(SLC_NOSUPPORT);
+	}
+}
+
+#else	/* USE_TERMIO */
+
+	int
+spcset(func, valp, valpp)
+	int func;
+	cc_t *valp;
+	cc_t **valpp;
+{
+
+#define	setval(a, b)	*valp = termbuf.c_cc[a]; \
+			*valpp = &termbuf.c_cc[a]; \
+			return(b);
+#define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
+
+	switch(func) {
+	case SLC_EOF:
+		setval(VEOF, SLC_VARIABLE);
+	case SLC_EC:
+		setval(VERASE, SLC_VARIABLE);
+	case SLC_EL:
+		setval(VKILL, SLC_VARIABLE);
+	case SLC_IP:
+		setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+	case SLC_ABORT:
+		setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+	case SLC_XON:
+#ifdef	VSTART
+		setval(VSTART, SLC_VARIABLE);
+#else
+		defval(0x13);
+#endif
+	case SLC_XOFF:
+#ifdef	VSTOP
+		setval(VSTOP, SLC_VARIABLE);
+#else
+		defval(0x11);
+#endif
+	case SLC_EW:
+#ifdef	VWERASE
+		setval(VWERASE, SLC_VARIABLE);
+#else
+		defval(0);
+#endif
+	case SLC_RP:
+#ifdef	VREPRINT
+		setval(VREPRINT, SLC_VARIABLE);
+#else
+		defval(0);
+#endif
+	case SLC_LNEXT:
+#ifdef	VLNEXT
+		setval(VLNEXT, SLC_VARIABLE);
+#else
+		defval(0);
+#endif
+	case SLC_AO:
+#if	!defined(VDISCARD) && defined(VFLUSHO)
+# define VDISCARD VFLUSHO
+#endif
+#ifdef	VDISCARD
+		setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
+#else
+		defval(0);
+#endif
+	case SLC_SUSP:
+#ifdef	VSUSP
+		setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
+#else
+		defval(0);
+#endif
+#ifdef	VEOL
+	case SLC_FORW1:
+		setval(VEOL, SLC_VARIABLE);
+#endif
+#ifdef	VEOL2
+	case SLC_FORW2:
+		setval(VEOL2, SLC_VARIABLE);
+#endif
+	case SLC_AYT:
+#ifdef	VSTATUS
+		setval(VSTATUS, SLC_VARIABLE);
+#else
+		defval(0);
+#endif
+
+	case SLC_BRK:
+	case SLC_SYNCH:
+	case SLC_EOR:
+		defval(0);
+
+	default:
+		*valp = 0;
+		*valpp = 0;
+		return(SLC_NOSUPPORT);
+	}
+}
+#endif	/* USE_TERMIO */
+
+#ifdef CRAY
+/*
+ * getnpty()
+ *
+ * Return the number of pty's configured into the system.
+ */
+	int
+getnpty()
+{
+#ifdef _SC_CRAY_NPTY
+	int numptys;
+
+	if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
+		return numptys;
+	else
+#endif /* _SC_CRAY_NPTY */
+		return 128;
+}
+#endif /* CRAY */
+
+#ifndef	convex
+/*
+ * getpty()
+ *
+ * Allocate a pty.  As a side effect, the external character
+ * array "line" contains the name of the slave side.
+ *
+ * Returns the file descriptor of the opened pty.
+ */
+static char Xline[17];
+char *line = Xline;
+
+#ifdef	CRAY
+char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+#endif	/* CRAY */
+
+
+#endif	/* convex */
+
+static pid_t slavepid = 0;
+
+#ifdef	LINEMODE
+/*
+ * tty_flowmode()	Find out if flow control is enabled or disabled.
+ * tty_linemode()	Find out if linemode (external processing) is enabled.
+ * tty_setlinemod(on)	Turn on/off linemode.
+ * tty_isecho()		Find out if echoing is turned on.
+ * tty_setecho(on)	Enable/disable character echoing.
+ * tty_israw()		Find out if terminal is in RAW mode.
+ * tty_binaryin(on)	Turn on/off BINARY on input.
+ * tty_binaryout(on)	Turn on/off BINARY on output.
+ * tty_isediting()	Find out if line editing is enabled.
+ * tty_istrapsig()	Find out if signal trapping is enabled.
+ * tty_setedit(on)	Turn on/off line editing.
+ * tty_setsig(on)	Turn on/off signal trapping.
+ * tty_issofttab()	Find out if tab expansion is enabled.
+ * tty_setsofttab(on)	Turn on/off soft tab expansion.
+ * tty_islitecho()	Find out if typed control chars are echoed literally
+ * tty_setlitecho()	Turn on/off literal echo of control chars
+ * tty_tspeed(val)	Set transmit speed to val.
+ * tty_rspeed(val)	Set receive speed to val.
+ */
+
+#ifdef convex
+static int linestate;
+#endif
+
+	int
+tty_linemode()
+{
+#ifndef convex
+#ifndef	USE_TERMIO
+	return(termbuf.state & TS_EXTPROC);
+#else
+	return(termbuf.c_lflag & EXTPROC);
+#endif
+#else
+	return(linestate);
+#endif
+}
+
+	void
+tty_setlinemode(on)
+	int on;
+{
+#ifdef	TIOCEXT
+# ifndef convex
+	set_termbuf();
+# else
+	linestate = on;
+# endif
+	(void) ioctl(pty, TIOCEXT, (char *)&on);
+# ifndef convex
+	init_termbuf();
+# endif
+#else	/* !TIOCEXT */
+# ifdef	EXTPROC
+	if (on)
+		termbuf.c_lflag |= EXTPROC;
+	else
+		termbuf.c_lflag &= ~EXTPROC;
+# endif
+#endif	/* TIOCEXT */
+}
+#endif	/* LINEMODE */
+
+	int
+tty_isecho()
+{
+#ifndef USE_TERMIO
+	return (termbuf.sg.sg_flags & ECHO);
+#else
+	return (termbuf.c_lflag & ECHO);
+#endif
+}
+
+	int
+tty_flowmode()
+{
+#ifndef USE_TERMIO
+	return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
+#else
+	return((termbuf.c_iflag & IXON) ? 1 : 0);
+#endif
+}
+
+	int
+tty_restartany()
+{
+#ifndef USE_TERMIO
+# ifdef	DECCTQ
+	return((termbuf.lflags & DECCTQ) ? 0 : 1);
+# else
+	return(-1);
+# endif
+#else
+	return((termbuf.c_iflag & IXANY) ? 1 : 0);
+#endif
+}
+
+	void
+tty_setecho(on)
+	int on;
+{
+#ifndef	USE_TERMIO
+	if (on)
+		termbuf.sg.sg_flags |= ECHO|CRMOD;
+	else
+		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
+#else
+	if (on)
+		termbuf.c_lflag |= ECHO;
+	else
+		termbuf.c_lflag &= ~ECHO;
+#endif
+}
+
+	int
+tty_israw()
+{
+#ifndef USE_TERMIO
+	return(termbuf.sg.sg_flags & RAW);
+#else
+	return(!(termbuf.c_lflag & ICANON));
+#endif
+}
+
+#if	defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+	int
+tty_setraw(on)
+{
+#  ifndef USE_TERMIO
+	if (on)
+		termbuf.sg.sg_flags |= RAW;
+	else
+		termbuf.sg.sg_flags &= ~RAW;
+#  else
+	if (on)
+		termbuf.c_lflag &= ~ICANON;
+	else
+		termbuf.c_lflag |= ICANON;
+#  endif
+}
+#endif
+
+	void
+tty_binaryin(on)
+	int on;
+{
+#ifndef	USE_TERMIO
+	if (on)
+		termbuf.lflags |= LPASS8;
+	else
+		termbuf.lflags &= ~LPASS8;
+#else
+	if (on) {
+		termbuf.c_iflag &= ~ISTRIP;
+	} else {
+		termbuf.c_iflag |= ISTRIP;
+	}
+#endif
+}
+
+	void
+tty_binaryout(on)
+	int on;
+{
+#ifndef	USE_TERMIO
+	if (on)
+		termbuf.lflags |= LLITOUT;
+	else
+		termbuf.lflags &= ~LLITOUT;
+#else
+	if (on) {
+		termbuf.c_cflag &= ~(CSIZE|PARENB);
+		termbuf.c_cflag |= CS8;
+		termbuf.c_oflag &= ~OPOST;
+	} else {
+		termbuf.c_cflag &= ~CSIZE;
+		termbuf.c_cflag |= CS7|PARENB;
+		termbuf.c_oflag |= OPOST;
+	}
+#endif
+}
+
+	int
+tty_isbinaryin()
+{
+#ifndef	USE_TERMIO
+	return(termbuf.lflags & LPASS8);
+#else
+	return(!(termbuf.c_iflag & ISTRIP));
+#endif
+}
+
+	int
+tty_isbinaryout()
+{
+#ifndef	USE_TERMIO
+	return(termbuf.lflags & LLITOUT);
+#else
+	return(!(termbuf.c_oflag&OPOST));
+#endif
+}
+
+#ifdef	LINEMODE
+	int
+tty_isediting()
+{
+#ifndef USE_TERMIO
+	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
+#else
+	return(termbuf.c_lflag & ICANON);
+#endif
+}
+
+	int
+tty_istrapsig()
+{
+#ifndef USE_TERMIO
+	return(!(termbuf.sg.sg_flags&RAW));
+#else
+	return(termbuf.c_lflag & ISIG);
+#endif
+}
+
+	void
+tty_setedit(on)
+	int on;
+{
+#ifndef USE_TERMIO
+	if (on)
+		termbuf.sg.sg_flags &= ~CBREAK;
+	else
+		termbuf.sg.sg_flags |= CBREAK;
+#else
+	if (on)
+		termbuf.c_lflag |= ICANON;
+	else
+		termbuf.c_lflag &= ~ICANON;
+#endif
+}
+
+	void
+tty_setsig(on)
+	int on;
+{
+#ifndef	USE_TERMIO
+	if (on)
+		;
+#else
+	if (on)
+		termbuf.c_lflag |= ISIG;
+	else
+		termbuf.c_lflag &= ~ISIG;
+#endif
+}
+#endif	/* LINEMODE */
+
+	int
+tty_issofttab()
+{
+#ifndef	USE_TERMIO
+	return (termbuf.sg.sg_flags & XTABS);
+#else
+# ifdef	OXTABS
+	return (termbuf.c_oflag & OXTABS);
+# endif
+# ifdef	TABDLY
+	return ((termbuf.c_oflag & TABDLY) == TAB3);
+# endif
+#endif
+}
+
+	void
+tty_setsofttab(on)
+	int on;
+{
+#ifndef	USE_TERMIO
+	if (on)
+		termbuf.sg.sg_flags |= XTABS;
+	else
+		termbuf.sg.sg_flags &= ~XTABS;
+#else
+	if (on) {
+# ifdef	OXTABS
+		termbuf.c_oflag |= OXTABS;
+# endif
+# ifdef	TABDLY
+		termbuf.c_oflag &= ~TABDLY;
+		termbuf.c_oflag |= TAB3;
+# endif
+	} else {
+# ifdef	OXTABS
+		termbuf.c_oflag &= ~OXTABS;
+# endif
+# ifdef	TABDLY
+		termbuf.c_oflag &= ~TABDLY;
+		termbuf.c_oflag |= TAB0;
+# endif
+	}
+#endif
+}
+
+	int
+tty_islitecho()
+{
+#ifndef	USE_TERMIO
+	return (!(termbuf.lflags & LCTLECH));
+#else
+# ifdef	ECHOCTL
+	return (!(termbuf.c_lflag & ECHOCTL));
+# endif
+# ifdef	TCTLECH
+	return (!(termbuf.c_lflag & TCTLECH));
+# endif
+# if	!defined(ECHOCTL) && !defined(TCTLECH)
+	return (0);	/* assumes ctl chars are echoed '^x' */
+# endif
+#endif
+}
+
+	void
+tty_setlitecho(on)
+	int on;
+{
+#ifndef	USE_TERMIO
+	if (on)
+		termbuf.lflags &= ~LCTLECH;
+	else
+		termbuf.lflags |= LCTLECH;
+#else
+# ifdef	ECHOCTL
+	if (on)
+		termbuf.c_lflag &= ~ECHOCTL;
+	else
+		termbuf.c_lflag |= ECHOCTL;
+# endif
+# ifdef	TCTLECH
+	if (on)
+		termbuf.c_lflag &= ~TCTLECH;
+	else
+		termbuf.c_lflag |= TCTLECH;
+# endif
+#endif
+}
+
+	int
+tty_iscrnl()
+{
+#ifndef	USE_TERMIO
+	return (termbuf.sg.sg_flags & CRMOD);
+#else
+	return (termbuf.c_iflag & ICRNL);
+#endif
+}
+
+/*
+ * A table of available terminal speeds
+ */
+struct termspeeds {
+	int	speed;
+	speed_t	value;
+} termspeeds[] = {
+	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
+	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
+	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
+	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
+	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
+	{ 38400, B9600 }, { -1,    B9600 }
+};
+
+	void
+tty_tspeed(val)
+	int val;
+{
+	register struct termspeeds *tp;
+
+	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
+		;
+	cfsetospeed(&termbuf, tp->value);
+}
+
+	void
+tty_rspeed(val)
+	int val;
+{
+	register struct termspeeds *tp;
+
+	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
+		;
+	cfsetispeed(&termbuf, tp->value);
+}
+
+#if	defined(CRAY2) && defined(UNICOS5)
+	int
+tty_isnewmap()
+{
+	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
+			!(termbuf.c_oflag & ONLRET));
+}
+#endif
+
+
+#ifndef	NEWINIT
+#endif
+
+/*
+ * getptyslave()
+ *
+ * Open the slave side of the pty, and do any initialization
+ * that is necessary.  The return value is a file descriptor
+ * for the slave side.
+ */
+static void
+getptyslave()
+{
+     int t = -1;
+     long retval;
+
+#if	!defined(CRAY) || !defined(NEWINIT)
+# ifdef	LINEMODE
+	int waslm;
+# endif
+# ifdef	TIOCGWINSZ
+	struct winsize ws;
+	extern int def_row, def_col;
+# endif
+	extern int def_tspeed, def_rspeed;
+	/*
+	 * Opening the slave side may cause initilization of the
+	 * kernel tty structure.  We need remember the state of
+	 * 	if linemode was turned on
+	 *	terminal window size
+	 *	terminal speed
+	 * so that we can re-set them if we need to.
+	 */
+# ifdef	LINEMODE
+	waslm = tty_linemode();
+# endif
+
+	if ( (retval = pty_open_slave (line, &t)) != 0 )
+	    {
+		fatalperror(net,  error_message(retval));
+	    }
+
+#ifdef  STREAMSPTY
+#ifdef	USE_TERMIO
+	ttyfd = t;
+#endif
+	if (ioctl(pty, I_PUSH, "pckt") < 0) {
+#ifndef _AIX
+		fatal(net, "I_PUSH pckt");
+#endif
+	}
+#endif
+
+	/*
+	 * set up the tty modes as we like them to be.
+	 */
+	init_termbuf();
+# ifdef	TIOCGWINSZ
+	if (def_row || def_col) {
+		memset((char *)&ws, 0, sizeof(ws));
+		ws.ws_col = def_col;
+		ws.ws_row = def_row;
+		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
+	}
+# endif
+
+	/*
+	 * Settings for sgtty based systems
+	 */
+# ifndef	USE_TERMIO
+	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
+# endif	/* USE_TERMIO */
+
+	/*
+	 * Settings for UNICOS (and HPUX)
+	 */
+# if defined(CRAY) || defined(__hpux)
+	termbuf.c_oflag = OPOST|ONLCR|TAB3;
+	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
+	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
+	termbuf.c_cflag = EXTB|HUPCL|CS8;
+# endif
+
+	/*
+	 * Settings for all other termios/termio based
+	 * systems, other than 4.4BSD.  In 4.4BSD the
+	 * kernel does the initial terminal setup.
+	 */
+# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
+#  ifndef	OXTABS
+#   define OXTABS	0
+#  endif
+	termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
+	termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
+	termbuf.c_iflag |= ICRNL|IGNPAR;
+termbuf.c_cflag |= HUPCL;
+	termbuf.c_iflag &= ~IXOFF;
+# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
+	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
+	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
+# ifdef	LINEMODE
+	if (waslm)
+		tty_setlinemode(1);
+# endif	/* LINEMODE */
+
+	/*
+	 * Set the tty modes, and make this our controlling tty.
+	 */
+	set_termbuf();
+	if (dup_tty(t) == -1)
+		fatalperror(net, "dup_tty");
+#endif	/* !defined(CRAY) || !defined(NEWINIT) */
+	if (net > 2)
+		(void) close(net);
+#if	defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+	/*
+	 * Leave the pty open so that we can write out the rlogin
+	 * protocol for /bin/login, if the authentication works.
+	 */
+#else
+	if (pty > 2) {
+		(void) close(pty);
+		pty = -1;
+	}
+#endif
+}
+
+#if	!defined(CRAY) || !defined(NEWINIT)
+#ifndef	O_NOCTTY
+#define	O_NOCTTY	0
+#endif
+#endif	/* !defined(CRAY) || !defined(NEWINIT) */
+
+
+
+	int
+dup_tty(t)
+	int t;
+{
+	if (t != 0)
+		(void) dup2(t, 0);
+	if (t != 1)
+		(void) dup2(t, 1);
+	if (t != 2)
+		(void) dup2(t, 2);
+	if (t > 2)
+		close(t);
+	return(0);
+}
+
+
+#ifdef	NEWINIT
+char *gen_id = "fe";
+#endif
+
+/*
+ * startslave(host)
+ *
+ * Given a hostname, do whatever
+ * is necessary to startup the login process on the slave side of the pty.
+ */
+
+
+/* ARGSUSED */
+	void
+startslave(host, autologin, autoname)
+	char *host;
+	int autologin;
+	char *autoname;
+{
+	int syncpipe[2];
+	register int i;
+#ifdef	NEWINIT
+	extern char *ptyip;
+	struct init_request request;
+	void nologinproc();
+	register int n;
+#endif	/* NEWINIT */
+
+	if ( pipe(syncpipe) < 0 ) 
+		fatal(net, "failed getting synchronization pipe");
+    
+#if	defined(AUTHENTICATION)
+	if (!autoname || !autoname[0])
+		autologin = 0;
+
+	if (autologin < auth_level) {
+		fatal(net, "Authorization failed");
+		exit(1);
+	}
+#endif
+
+#ifndef	NEWINIT
+
+	if ((i = fork()) < 0)
+		fatalperror(net, "fork");
+	if (i) {
+		char c;
+
+		void sigjob (int);
+		slavepid = i; /* So we can clean it up later */
+#ifdef	CRAY
+		(void) signal(WJSIGNAL, sigjob);
+#endif
+
+		/* Wait for child before writing to parent side of pty.*/
+		(void) close(syncpipe[1]);
+		if ( read(syncpipe[0], &c, 1) == 0 ) {
+			/* Slave side died */
+			fatal ( net, "Slave failed to initialize");
+		}
+
+		close(syncpipe[0]);
+		
+	} else {
+		
+		pty_update_utmp (PTY_LOGIN_PROCESS, getpid(), "LOGIN", line,
+				 host, PTY_TTYSLOT_USABLE);
+		getptyslave();
+
+		/* Notify our parent we're ready to continue.*/
+		write(syncpipe[1],"y",1);
+		close(syncpipe[0]);
+		close(syncpipe[1]);
+		
+		start_login(host, autologin, autoname);
+		/*NOTREACHED*/
+	}
+#else	/* NEWINIT */
+
+	/*
+	 * Init will start up login process if we ask nicely.  We only wait
+	 * for it to start up and begin normal telnet operation.
+	 */
+	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
+		char tbuf[128];
+		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
+		fatalperror(net, tbuf);
+	}
+	memset((char *)&request, 0, sizeof(request));
+	request.magic = INIT_MAGIC;
+	SCPYN(request.gen_id, gen_id);
+	SCPYN(request.tty_id, &line[8]);
+	SCPYN(request.host, host);
+	SCPYN(request.term_type, *terminaltype ? terminaltype : "network");
+#if	!defined(UNICOS5)
+	request.signal = SIGCLD;
+	request.pid = getpid();
+#endif
+#ifdef BFTPDAEMON
+	/*
+	 * Are we working as the bftp daemon?
+	 */
+	if (bftpd) {
+		SCPYN(request.exec_name, BFTPPATH);
+	}
+#endif /* BFTPDAEMON */
+	if (write(i, (char *)&request, sizeof(request)) < 0) {
+		char tbuf[128];
+		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
+		fatalperror(net, tbuf);
+	}
+	(void) close(i);
+	(void) signal(SIGALRM, nologinproc);
+	for (i = 0; ; i++) {
+		char tbuf[128];
+		alarm(15);
+		n = read(pty, ptyip, BUFSIZ);
+		if (i == 3 || n >= 0 || !gotalarm)
+			break;
+		gotalarm = 0;
+		sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
+		(void) write(net, tbuf, strlen(tbuf));
+	}
+	if (n < 0 && gotalarm)
+		fatal(net, "/etc/init didn't start login process");
+	pcc += n;
+	alarm(0);
+	(void) signal(SIGALRM, SIG_DFL);
+
+	return;
+#endif	/* NEWINIT */
+}
+
+char	*envinit[3];
+extern char **environ;
+
+	void
+init_env()
+{
+	extern char *getenv();
+	char **envp;
+
+	envp = envinit;
+	if ((*envp = getenv("TZ")))
+		*envp++ -= 3;
+#if	defined(CRAY) || defined(__hpux)
+	else
+		*envp++ = "TZ=GMT0";
+#endif
+	*envp = 0;
+	environ = envinit;
+}
+
+#ifndef	NEWINIT
+
+/*
+ * start_login(host)
+ *
+ * Assuming that we are now running as a child processes, this
+ * function will turn us into the login process.
+ */
+
+	void
+start_login(host, autologin, name)
+	char *host;
+	int autologin;
+	char *name;
+{
+	register char **argv;
+	extern char *getenv();
+
+#ifdef SOLARIS
+	char *term;
+	char termbuf[64];
+#endif
+
+
+	/*
+	 * -h : pass on name of host.
+	 *		WARNING:  -h is accepted by login if and only if
+	 *			getuid() == 0.
+	 * -p : don't clobber the environment (so terminal type stays set).
+	 *
+	 * -f : force this login, he has already been authenticated
+	 */
+	argv = addarg(0, "login");
+
+#if	!defined(NO_LOGIN_H)
+
+# if	defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+	/*
+	 * Don't add the "-h host" option if we are going
+	 * to be adding the "-r host" option down below...
+	 */
+	if ((auth_level < 0) || (autologin != AUTH_VALID))
+# endif
+	{
+		argv = addarg(argv, "-h");
+		argv = addarg(argv, host);
+#ifdef	SOLARIS
+		/*
+		 * SVR4 version of -h takes TERM= as second arg, or -
+		 */
+		term = getenv("TERM");
+		if (term == NULL || term[0] == 0) {
+			term = "-";
+		} else {
+			strcpy(termbuf, "TERM=");
+			strncat(termbuf, term, sizeof(termbuf) - 6);
+			termbuf[sizeof(termbuf) - 1] = '\0';
+			term = termbuf;
+		}
+		argv = addarg(argv, term);
+#endif
+	}
+#endif
+#if	!defined(NO_LOGIN_P)
+	argv = addarg(argv, "-p");
+#endif
+#ifdef	BFTPDAEMON
+	/*
+	 * Are we working as the bftp daemon?  If so, then ask login
+	 * to start bftp instead of shell.
+	 */
+	if (bftpd) {
+		argv = addarg(argv, "-e");
+		argv = addarg(argv, BFTPPATH);
+	} else 
+#endif
+#if	defined (SecurID)
+	/*
+	 * don't worry about the -f that might get sent.
+	 * A -s is supposed to override it anyhow.
+	 */
+	if (require_SecurID)
+		argv = addarg(argv, "-s");
+#endif
+#if	defined (AUTHENTICATION)
+	if (auth_level >= 0 && autologin == AUTH_VALID) {
+		if (name[0] == '-') {
+		    /*
+		     * Authenticated and authorized to log in to an
+		     * account starting with '-'?  Even if that
+		     * unlikely case comes to pass, the current login
+		     * program will not parse the resulting command
+		     * line properly.
+		     */
+		    syslog(LOG_ERR, "user name cannot start with '-'");
+		    fatal(net, "user name cannot start with '-'");
+		    exit(1);
+		}
+# if	!defined(NO_LOGIN_F)
+#if	defined(LOGIN_CAP_F)
+		argv = addarg(argv, "-F");
+#else
+		argv = addarg(argv, "-f");
+#endif
+		argv = addarg(argv, "--");
+		argv = addarg(argv, name);
+# else
+#  if defined(LOGIN_R)
+		/*
+		 * We don't have support for "login -f", but we
+		 * can fool /bin/login into thinking that we are
+		 * rlogind, and allow us to log in without a
+		 * password.  The rlogin protocol expects
+		 *	local-user\0remote-user\0term/speed\0
+		 */
+
+		if (pty > 2) {
+			register char *cp;
+			char speed[1024];
+			int isecho, israw, xpty, len;
+			extern int def_rspeed;
+#  ifndef LOGIN_HOST
+			/*
+			 * Tell login that we are coming from "localhost".
+			 * If we passed in the real host name, then the
+			 * user would have to allow .rhost access from
+			 * every machine that they want authenticated
+			 * access to work from, which sort of defeats
+			 * the purpose of an authenticated login...
+			 * So, we tell login that the session is coming
+			 * from "localhost", and the user will only have
+			 * to have "localhost" in their .rhost file.
+			 */
+#			define LOGIN_HOST "localhost"
+#  endif
+			argv = addarg(argv, "-r");
+			argv = addarg(argv, LOGIN_HOST);
+
+			xpty = pty;
+# ifndef  STREAMSPTY
+			pty = 0;
+# else
+			ttyfd = 0;
+# endif
+			init_termbuf();
+			isecho = tty_isecho();
+			israw = tty_israw();
+			if (isecho || !israw) {
+				tty_setecho(0);		/* Turn off echo */
+				tty_setraw(1);		/* Turn on raw */
+				set_termbuf();
+			}
+			len = strlen(name)+1;
+			write(xpty, name, len);
+			write(xpty, name, len);
+			memset(speed, 0, sizeof(speed));
+			strncpy(speed,
+				(cp = getenv("TERM")) ? cp : "",
+				sizeof(speed)-1-(10*sizeof(def_rspeed)/4)-1);
+			/* 1 for /, () for the number, 1 for trailing 0. */
+			sprintf(speed + strlen(speed),
+				"/%d",
+				(def_rspeed > 0) ? def_rspeed : 9600);
+			len = strlen(speed)+1;
+			write(xpty, speed, len);
+
+			if (isecho || !israw) {
+				init_termbuf();
+				tty_setecho(isecho);
+				tty_setraw(israw);
+				set_termbuf();
+				if (!israw) {
+					/*
+					 * Write a newline to ensure
+					 * that login will be able to
+					 * read the line...
+					 */
+					write(xpty, "\n", 1);
+				}
+			}
+			pty = xpty;
+		}
+#  else
+		argv = addarg(argv, "--");
+		argv = addarg(argv, name);
+#  endif
+# endif
+	} else
+#endif
+	if (getenv("USER")) {
+		char *user = getenv("USER");
+		if (user[0] == '-') {
+		    /* "telnet -l-x ..." */
+		    syslog(LOG_ERR, "user name cannot start with '-'");
+		    fatal(net, "user name cannot start with '-'");
+		    exit(1);
+		}
+		argv = addarg(argv, "--");
+		argv = addarg(argv, user);
+#if	defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
+		{
+			register char **cpp;
+			for (cpp = environ; *cpp; cpp++)
+			    if ((*cpp)[0] != '-')
+				argv = addarg(argv, *cpp);
+		}
+#endif
+		/*
+		 * Assume that login will set the USER variable
+		 * correctly.  For SysV systems, this means that
+		 * USER will no longer be set, just LOGNAME by
+		 * login.  (The problem is that if the auto-login
+		 * fails, and the user then specifies a different
+		 * account name, he can get logged in with both
+		 * LOGNAME and USER in his environment, but the
+		 * USER value will be wrong.
+		 */
+		unsetenv("USER");
+	}
+#if	defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+	if (pty > 2)
+		close(pty);
+#endif
+	closelog();
+	execv(login_program, argv);
+
+	syslog(LOG_ERR, "%s: %m", login_program);
+	fatalperror(net, login_program);
+	/*NOTREACHED*/
+}
+
+/*
+ * This code returns a pointer to the first element of the array and
+ * expects the same to be called with.
+ * Therefore the -1 reference is legal. 
+ */
+
+static char **
+addarg(argv, val)
+	register char **argv;
+	register char *val;
+{
+	register char **cpp;
+
+	if (argv == NULL) {
+		/*
+		 * 10 entries, a leading length, and a null
+		 */
+		argv = (char **)malloc(sizeof(*argv) * 12);
+		if (argv == NULL)
+			return(NULL);
+		*argv++ = (char *)10;
+		*argv = (char *)0;
+	}
+	for (cpp = argv; *cpp; cpp++)
+		;
+	if (cpp == &argv[(long)argv[-1]]) {
+		--argv;
+		*argv = (char *)((long)(*argv) + 10);
+		argv = (char **)realloc(argv, sizeof(*argv) * ((long)(*argv) + 2));
+		if (argv == NULL)
+			return(NULL);
+		argv++;
+		cpp = &argv[(long)argv[-1] - 10];
+	}
+	*cpp++ = val;
+	*cpp = 0;
+	return(argv);
+}
+#endif	/* NEWINIT */
+
+/*
+ * cleanup()
+ *
+ * This is the routine to call when we are all through, to
+ * clean up anything that needs to be cleaned up.
+ */
+	/* ARGSUSED */
+	void
+cleanup(sig)
+	int sig;
+{
+	pty_cleanup(line,slavepid,1);
+#ifdef KRB5
+	kerberos5_cleanup();
+#endif
+    
+	(void) shutdown(net, 2);
+	exit(1);
+}
+
+
+
+
+
diff --git a/krb5-1-6/src/appl/telnet/telnetd/telnetd-ktd.c b/krb5-1-6/src/appl/telnet/telnetd/telnetd-ktd.c
new file mode 100644
index 000000000..295f19580
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/telnetd-ktd.c
@@ -0,0 +1,1462 @@
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1989 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)telnetd.c	5.51 (Berkeley) 1/21/93 */
+
+#include "telnetd.h"
+#include "pathnames.h"
+
+#if	defined(_SC_CRAY_SECURE_SYS)
+#include <sys/sysv.h>
+#include <libpty.h>
+#include <sys/secdev.h>
+int	secflag;
+char	tty_dev[16];
+struct	secdev dv;
+struct	sysv sysv;
+struct	socket_security ss;
+#endif	/* _SC_CRAY_SECURE_SYS */
+
+#if	defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+int	auth_level = 0;
+#endif
+#if	defined(SecurID)
+int	require_SecurID = 0;
+#endif
+
+extern	int utmp_len;
+int	registerd_host_only = 0;
+
+#ifdef	STREAMSPTY
+# include <stropts.h>
+# include <termio.h>
+/* make sure we don't get the bsd version */
+# include "/usr/include/sys/tty.h"
+# include <sys/ptyvar.h>
+
+/*
+ * Because of the way ptyibuf is used with streams messages, we need
+ * ptyibuf+1 to be on a full-word boundary.  The following wierdness
+ * is simply to make that happen.
+ */
+char	ptyibufbuf[BUFSIZ+4];
+char	*ptyibuf = ptyibufbuf+3;
+char	*ptyip = ptyibufbuf+3;
+char	ptyibuf2[BUFSIZ];
+unsigned char ctlbuf[BUFSIZ];
+struct	strbuf strbufc, strbufd;
+
+int readstream();
+
+#else	/* ! STREAMPTY */
+
+/*
+ * I/O data buffers,
+ * pointers, and counters.
+ */
+char	ptyibuf[BUFSIZ], *ptyip = ptyibuf;
+char	ptyibuf2[BUFSIZ];
+
+#endif /* ! STREAMPTY */
+
+int	hostinfo = 1;			/* do we print login banner? */
+
+#ifdef	CRAY
+extern int      newmap; /* nonzero if \n maps to ^M^J */
+int	lowpty = 0, highpty;	/* low, high pty numbers */
+#endif /* CRAY */
+
+int debug = 0;
+int keepalive = 1;
+char *progname;
+
+extern void usage (void);
+
+main(argc, argv)
+	char *argv[];
+{
+	struct sockaddr_in from;
+	int on = 1, fromlen;
+	register int ch;
+	extern char *optarg;
+	extern int optind;
+#if	defined(IPPROTO_IP) && defined(IP_TOS)
+	int tos = -1;
+#endif
+
+	pfrontp = pbackp = ptyobuf;
+	netip = netibuf;
+	nfrontp = nbackp = netobuf;
+#if	defined(ENCRYPTION)
+	nclearto = 0;
+#endif
+
+	progname = *argv;
+
+#ifdef CRAY
+	/*
+	 * Get number of pty's before trying to process options,
+	 * which may include changing pty range.
+	 */
+	highpty = getnpty();
+#endif /* CRAY */
+
+	while ((ch = getopt(argc, argv, "d:a:e:klhnr:u:UI:D:B:sS:a:X:")) != -1) {
+		switch(ch) {
+
+#ifdef	AUTHENTICATION
+		case 'a':
+			/*
+			 * Check for required authentication level
+			 */
+			if (strcmp(optarg, "debug") == 0) {
+				extern int auth_debug_mode;
+				auth_debug_mode = 1;
+			} else if (strcasecmp(optarg, "none") == 0) {
+				auth_level = 0;
+			} else if (strcasecmp(optarg, "other") == 0) {
+				auth_level = AUTH_OTHER;
+			} else if (strcasecmp(optarg, "user") == 0) {
+				auth_level = AUTH_USER;
+			} else if (strcasecmp(optarg, "valid") == 0) {
+				auth_level = AUTH_VALID;
+			} else if (strcasecmp(optarg, "off") == 0) {
+				/*
+				 * This hack turns off authentication
+				 */
+				auth_level = -1;
+			} else {
+				fprintf(stderr,
+			    "telnetd: unknown authorization level for -a\n");
+			}
+			break;
+#endif	/* AUTHENTICATION */
+
+#ifdef BFTPDAEMON
+		case 'B':
+			bftpd++;
+			break;
+#endif /* BFTPDAEMON */
+
+		case 'd':
+			if (strcmp(optarg, "ebug") == 0) {
+				debug++;
+				break;
+			}
+			usage();
+			/* NOTREACHED */
+			break;
+
+#ifdef DIAGNOSTICS
+		case 'D':
+			/*
+			 * Check for desired diagnostics capabilities.
+			 */
+			if (!strcmp(optarg, "report")) {
+				diagnostic |= TD_REPORT|TD_OPTIONS;
+			} else if (!strcmp(optarg, "exercise")) {
+				diagnostic |= TD_EXERCISE;
+			} else if (!strcmp(optarg, "netdata")) {
+				diagnostic |= TD_NETDATA;
+			} else if (!strcmp(optarg, "ptydata")) {
+				diagnostic |= TD_PTYDATA;
+			} else if (!strcmp(optarg, "options")) {
+				diagnostic |= TD_OPTIONS;
+			} else {
+				usage();
+				/* NOT REACHED */
+			}
+			break;
+#endif /* DIAGNOSTICS */
+
+#ifdef	ENCRYPTION
+		case 'e':
+			if (strcmp(optarg, "debug") == 0) {
+				extern int encrypt_debug_mode;
+				encrypt_debug_mode = 1;
+				break;
+			}
+			usage();
+			/* NOTREACHED */
+			break;
+#endif	/* ENCRYPTION */
+
+		case 'h':
+			hostinfo = 0;
+			break;
+
+#if	defined(CRAY) && defined(NEWINIT)
+		case 'I':
+		    {
+			extern char *gen_id;
+			gen_id = optarg;
+			break;
+		    }
+#endif	/* defined(CRAY) && defined(NEWINIT) */
+
+#ifdef	LINEMODE
+		case 'l':
+			alwayslinemode = 1;
+			break;
+#endif	/* LINEMODE */
+
+		case 'k':
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+			lmodetype = NO_AUTOKLUDGE;
+#else
+			/* ignore -k option if built without kludge linemode */
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+			break;
+
+		case 'n':
+			keepalive = 0;
+			break;
+
+#ifdef CRAY
+		case 'r':
+		    {
+			char *strchr();
+			char *c;
+
+			/*
+			 * Allow the specification of alterations
+			 * to the pty search range.  It is legal to
+			 * specify only one, and not change the
+			 * other from its default.
+			 */
+			c = strchr(optarg, '-');
+			if (c) {
+				*c++ = '\0';
+				highpty = atoi(c);
+			}
+			if (*optarg != '\0')
+				lowpty = atoi(optarg);
+			if ((lowpty > highpty) || (lowpty < 0) ||
+							(highpty > 32767)) {
+				usage();
+				/* NOT REACHED */
+			}
+			break;
+		    }
+#endif	/* CRAY */
+
+#ifdef	SecurID
+		case 's':
+			/* SecurID required */
+			require_SecurID = 1;
+			break;
+#endif	/* SecurID */
+		case 'S':
+#ifdef	HAVE_GETTOSBYNAME
+			if ((tos = parsetos(optarg, "tcp")) < 0)
+				fprintf(stderr, "%s%s%s\n",
+					"telnetd: Bad TOS argument '", optarg,
+					"'; will try to use default TOS");
+#else
+			fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
+						"-S flag not supported\n");
+#endif
+			break;
+
+		case 'u':
+			utmp_len = atoi(optarg);
+			break;
+
+		case 'U':
+			registerd_host_only = 1;
+			break;
+
+#ifdef	AUTHENTICATION
+		case 'X':
+			/*
+			 * Check for invalid authentication types
+			 */
+			auth_disable_name(optarg);
+			break;
+#endif	/* AUTHENTICATION */
+
+		default:
+			fprintf(stderr, "telnetd: %s: unknown option\n", ch);
+			/* FALLTHROUGH */
+		case '?':
+			usage();
+			/* NOTREACHED */
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (debug) {
+	    int s, ns, foo;
+	    struct servent *sp;
+	    static struct sockaddr_in sin = { AF_INET };
+
+	    if (argc > 1) {
+		usage();
+		/* NOT REACHED */
+	    } else if (argc == 1) {
+		    if (sp = getservbyname(*argv, "tcp")) {
+			sin.sin_port = sp->s_port;
+		    } else {
+			sin.sin_port = atoi(*argv);
+			if ((int)sin.sin_port <= 0) {
+			    fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
+			    usage();
+			    /* NOT REACHED */
+			}
+			sin.sin_port = htons((u_short)sin.sin_port);
+		   }
+	    } else {
+		sp = getservbyname("ktelnet", "tcp");
+		if (sp == 0) {
+		    fprintf(stderr, "telnetd: tcp/ktelnet: unknown service\n");
+		    exit(1);
+		}
+		sin.sin_port = sp->s_port;
+	    }
+
+	    s = socket(AF_INET, SOCK_STREAM, 0);
+	    if (s < 0) {
+		    perror("telnetd: socket");;
+		    exit(1);
+	    }
+	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+				(char *)&on, sizeof(on));
+	    if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+		perror("bind");
+		exit(1);
+	    }
+	    if (listen(s, 1) < 0) {
+		perror("listen");
+		exit(1);
+	    }
+	    foo = sizeof(sin);
+	    ns = accept(s, (struct sockaddr *)&sin, &foo);
+	    if (ns < 0) {
+		perror("accept");
+		exit(1);
+	    }
+	    (void) dup2(ns, 0);
+	    (void) close(ns);
+	    (void) close(s);
+#ifdef convex
+	} else if (argc == 1) {
+		; /* VOID*/		/* Just ignore the host/port name */
+#endif
+	} else if (argc > 0) {
+		usage();
+		/* NOT REACHED */
+	}
+
+#if	defined(_SC_CRAY_SECURE_SYS)
+	secflag = sysconf(_SC_CRAY_SECURE_SYS);
+
+	/*
+	 *      Get socket's security label 
+	 */
+	if (secflag)  {
+		int sz = sizeof(ss);
+
+		memset((char *)&dv, 0, sizeof(dv));
+
+		if (getsysv(&sysv, sizeof(struct sysv)) != 0) {
+			perror("getsysv");
+			exit(1);
+		}
+
+		/*
+		 *      Get socket security label and set device values
+		 *         {security label to be set on ttyp device}
+		 */
+		if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
+				(char *)&ss, &sz) >= 0) {
+
+			dv.dv_actlvl = ss.ss_slevel;
+			dv.dv_actcmp = ss.ss_compart;
+			dv.dv_minlvl = ss.ss_minlvl;
+			dv.dv_maxlvl = ss.ss_maxlvl;
+			dv.dv_valcmp = ss.ss_maxcmp;
+		}
+	}
+#endif	/* _SC_CRAY_SECURE_SYS */
+
+	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+	fromlen = sizeof (from);
+	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+		fprintf(stderr, "%s: ", progname);
+		perror("getpeername");
+		_exit(1);
+	}
+	if (keepalive &&
+	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
+			(char *)&on, sizeof (on)) < 0) {
+		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+	}
+
+#if	defined(IPPROTO_IP) && defined(IP_TOS)
+	{
+# if	defined(HAVE_GETTOSBYNAME)
+		struct tosent *tp;
+		if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+			tos = tp->t_tos;
+# endif
+		if (tos < 0)
+			tos = 020;	/* Low Delay bit */
+		if (tos
+		   && (setsockopt(0, IPPROTO_IP, IP_TOS,
+				  (char *)&tos, sizeof(tos)) < 0)
+		   && (errno != ENOPROTOOPT) )
+			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+	}
+#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
+	net = 0;
+	doit(&from);
+	/* NOTREACHED */
+}  /* end of main */
+
+	void
+usage()
+{
+	fprintf(stderr, "Usage: telnetd");
+#ifdef	AUTHENTICATION
+	fprintf(stderr, " [-a (debug|other|user|valid|off)]\n\t");
+#endif
+#ifdef BFTPDAEMON
+	fprintf(stderr, " [-B]");
+#endif
+	fprintf(stderr, " [-debug]");
+#ifdef DIAGNOSTICS
+	fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
+#endif
+#ifdef	AUTHENTICATION
+	fprintf(stderr, " [-edebug]");
+#endif
+	fprintf(stderr, " [-h]");
+#if	defined(CRAY) && defined(NEWINIT)
+	fprintf(stderr, " [-Iinitid]");
+#endif
+#ifdef LINEMODE
+	fprintf(stderr, " [-l]");
+#endif
+	fprintf(stderr, " [-n]");
+#ifdef	CRAY
+	fprintf(stderr, " [-r[lowpty]-[highpty]]");
+#endif
+#ifdef	SecurID
+	fprintf(stderr, " [-s]");
+#endif
+#ifdef	AUTHENTICATION
+	fprintf(stderr, " [-X auth-type]");
+#endif
+	fprintf(stderr, " [-u utmp_hostname_length] [-U]");
+	fprintf(stderr, " [port]\n");
+	exit(1);
+}
+
+/*
+ * getterminaltype
+ *
+ *	Ask the other end to send along its terminal type and speed.
+ * Output is the variable terminaltype filled in.
+ */
+static char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE };
+
+    int
+getterminaltype(name)
+    char *name;
+{
+    int retval = -1;
+    void _gettermname();
+
+    settimer(baseline);
+#if	defined(AUTHENTICATION)
+    /*
+     * Handle the Authentication option before we do anything else.
+     */
+    send_do(TELOPT_AUTHENTICATION, 1);
+    while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
+	ttloop();
+    if (his_state_is_will(TELOPT_AUTHENTICATION)) {
+	retval = auth_wait(name);
+    }
+#endif
+
+#if	defined(ENCRYPTION)
+    send_will(TELOPT_ENCRYPT, 1);
+#endif
+    send_do(TELOPT_TTYPE, 1);
+    send_do(TELOPT_TSPEED, 1);
+    send_do(TELOPT_XDISPLOC, 1);
+    send_do(TELOPT_ENVIRON, 1);
+    while (
+#if	defined(ENCRYPTION)
+	   his_do_dont_is_changing(TELOPT_ENCRYPT) ||
+#endif
+	   his_will_wont_is_changing(TELOPT_TTYPE) ||
+	   his_will_wont_is_changing(TELOPT_TSPEED) ||
+	   his_will_wont_is_changing(TELOPT_XDISPLOC) ||
+	   his_will_wont_is_changing(TELOPT_ENVIRON)) {
+	ttloop();
+    }
+#if	defined(ENCRYPTION)
+    /*
+     * Wait for the negotiation of what type of encryption we can
+     * send with.  If autoencrypt is not set, this will just return.
+     */
+    if (his_state_is_will(TELOPT_ENCRYPT)) {
+	encrypt_wait();
+    }
+#endif
+    if (his_state_is_will(TELOPT_TSPEED)) {
+	static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
+
+	if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+		memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+		nfrontp += sizeof(sbbuf);
+	}
+    }
+    if (his_state_is_will(TELOPT_XDISPLOC)) {
+	static char sbbuf[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
+
+	if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+		memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+		nfrontp += sizeof(sbbuf);
+	}
+    }
+    if (his_state_is_will(TELOPT_ENVIRON)) {
+	static char sbbuf[] = { IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE };
+
+	if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+		memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+		nfrontp += sizeof(sbbuf);
+	}
+    }
+    if (his_state_is_will(TELOPT_TTYPE)) {
+
+	if(nfrontp - netobuf + sizeof(ttytype_sbbuf) < sizeof(netobuf)) {
+		memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+		nfrontp += sizeof(ttytype_sbbuf);
+	}
+    }
+    if (his_state_is_will(TELOPT_TSPEED)) {
+	while (sequenceIs(tspeedsubopt, baseline))
+	    ttloop();
+    }
+    if (his_state_is_will(TELOPT_XDISPLOC)) {
+	while (sequenceIs(xdisplocsubopt, baseline))
+	    ttloop();
+    }
+    if (his_state_is_will(TELOPT_ENVIRON)) {
+	while (sequenceIs(environsubopt, baseline))
+	    ttloop();
+    }
+    if (his_state_is_will(TELOPT_TTYPE)) {
+	char first[256], last[256];
+
+	while (sequenceIs(ttypesubopt, baseline))
+	    ttloop();
+
+	/*
+	 * If the other side has already disabled the option, then
+	 * we have to just go with what we (might) have already gotten.
+	 */
+	if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
+	    (void) strncpy(first, terminaltype, sizeof(first) - 1);
+	    first[sizeof(first) - 1] = '\0';
+	    for(;;) {
+		/*
+		 * Save the unknown name, and request the next name.
+		 */
+		(void) strncpy(last, terminaltype, sizeof(last) - 1);
+	    	last[sizeof(last) - 1] = '\0';
+		_gettermname();
+		if (terminaltypeok(terminaltype))
+		    break;
+		if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
+		    his_state_is_wont(TELOPT_TTYPE)) {
+		    /*
+		     * We've hit the end.  If this is the same as
+		     * the first name, just go with it.
+		     */
+		    if (strncmp(first, terminaltype, sizeof(first)) == 0)
+			break;
+		    /*
+		     * Get the terminal name one more time, so that
+		     * RFC1091 compliant telnets will cycle back to
+		     * the start of the list.
+		     */
+		     _gettermname();
+		    if (strncmp(first, terminaltype, sizeof(first)) != 0)
+			(void) strncpy(terminaltype, first, sizeof(terminaltype) - 1);
+		    terminaltype[sizeof(terminaltype) - 1] = '\0';
+		    break;
+		}
+	    }
+	}
+    }
+    return(retval);
+}  /* end of getterminaltype */
+
+    void
+_gettermname()
+{
+    /*
+     * If the client turned off the option,
+     * we can't send another request, so we
+     * just return.
+     */
+    if (his_state_is_wont(TELOPT_TTYPE))
+	return;
+    settimer(baseline);
+    memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+    nfrontp += sizeof(ttytype_sbbuf);
+    while (sequenceIs(ttypesubopt, baseline))
+	ttloop();
+}
+
+    int
+terminaltypeok(s)
+    char *s;
+{
+    char buf[1024];
+
+    if (terminaltype == NULL)
+	return(1);
+
+    /*
+     * tgetent() will return 1 if the type is known, and
+     * 0 if it is not known.  If it returns -1, it couldn't
+     * open the database.  But if we can't open the database,
+     * it won't help to say we failed, because we won't be
+     * able to verify anything else.  So, we treat -1 like 1.
+     */
+    if (tgetent(buf, s) == 0)
+	return(0);
+    return(1);
+}
+
+#ifndef	MAXHOSTNAMELEN
+#define	MAXHOSTNAMELEN 64
+#endif	/* MAXHOSTNAMELEN */
+
+char *hostname;
+char host_name[MAXHOSTNAMELEN];
+char remote_host_name[MAXHOSTNAMELEN];
+
+#ifndef	convex
+extern void telnet (int, int);
+#else
+extern void telnet (int, int, char *);
+#endif
+
+/*
+ * Get a pty, scan input lines.
+ */
+doit(who)
+	struct sockaddr_in *who;
+{
+	char *host, *inet_ntoa();
+	int t;
+	struct hostent *hp;
+	int level;
+	char user_name[256];
+
+	/*
+	 * Find an available pty to use.
+	 */
+	if ( (retval = pty_getpty(&pty, line, sizeof(line)) < 0 ) {
+	    com_err(retval, "telnetd", "");
+	    
+	if (pty < 0)
+		fatal(net, "All network ports in use");
+
+#if	defined(_SC_CRAY_SECURE_SYS)
+	/*
+	 *	set ttyp line security label 
+	 */
+	if (secflag) {
+		extern char *myline;
+		if (setdevs(myline, &dv) < 0)
+			fatal(net, "cannot set pty security");
+	}
+#endif	/* _SC_CRAY_SECURE_SYS */
+
+	/* get name of connected client */
+	hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
+		who->sin_family);
+
+	if (hp == NULL && registerd_host_only) {
+		fatal(net, "Couldn't resolve your address into a host name.\r\n\
+         Please contact your net administrator");
+	} else if (hp &&
+	    (strlen(hp->h_name) <= ((utmp_len < 0) ? -utmp_len : utmp_len))) {
+		host = hp->h_name;
+	} else {
+		host = inet_ntoa(who->sin_addr);
+	}
+	/*
+	 * We must make a copy because Kerberos is probably going
+	 * to also do a gethost* and overwrite the static data...
+	 */
+	strncpy(remote_host_name, host, sizeof(remote_host_name)-1);
+	remote_host_name[sizeof(remote_host_name)-1] = 0;
+	host = remote_host_name;
+
+	(void) gethostname(host_name, sizeof (host_name));
+	hostname = host_name;
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+	auth_encrypt_init(hostname, host, "TELNETD", 1);
+#endif
+
+	init_env();
+	/*
+	 * get terminal type.
+	 */
+	*user_name = 0;
+	level = getterminaltype(user_name);
+	setenv("TERM", terminaltype ? terminaltype : "network", 1);
+
+	/*
+	 * Start up the login process on the slave side of the terminal
+	 */
+
+	startslave(host, level, user_name);
+	telnet(net, pty);  /* begin server processing */
+	/*NOTREACHED*/
+}  /* end of doit */
+
+#if	defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50)
+	int
+Xterm_output(ibufp, obuf, icountp, ocount)
+	char **ibufp, *obuf;
+	int *icountp, ocount;
+{
+	int ret;
+	ret = term_output(*ibufp, obuf, *icountp, ocount);
+	*ibufp += *icountp;
+	*icountp = 0;
+	return(ret);
+}
+#define	term_output	Xterm_output
+#endif	/* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */
+
+/*
+ * Main loop.  Select from pty and network, and
+ * hand data to telnet receiver finite state machine.
+ */
+	void
+#ifndef	convex
+telnet(f, p)
+#else
+telnet(f, p, host)
+#endif
+	int f, p;
+#ifdef convex
+	char *host;
+#endif
+{
+	int on = 1;
+#define	TABBUFSIZ	512
+	char	defent[TABBUFSIZ];
+	char	defstrs[TABBUFSIZ];
+#undef	TABBUFSIZ
+	char *HE;
+	char *HN;
+	char *IM;
+	void netflush();
+
+	/*
+	 * Initialize the slc mapping table.
+	 */
+	get_slc_defaults();
+
+	/*
+	 * Do some tests where it is desireable to wait for a response.
+	 * Rather than doing them slowly, one at a time, do them all
+	 * at once.
+	 */
+	if (my_state_is_wont(TELOPT_SGA))
+		send_will(TELOPT_SGA, 1);
+	/*
+	 * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
+	 * because 4.2 clients are unable to deal with TCP urgent data.
+	 *
+	 * To find out, we send out a "DO ECHO".  If the remote system
+	 * answers "WILL ECHO" it is probably a 4.2 client, and we note
+	 * that fact ("WILL ECHO" ==> that the client will echo what
+	 * WE, the server, sends it; it does NOT mean that the client will
+	 * echo the terminal input).
+	 */
+	send_do(TELOPT_ECHO, 1);
+
+#ifdef	LINEMODE
+	if (his_state_is_wont(TELOPT_LINEMODE)) {
+		/* Query the peer for linemode support by trying to negotiate
+		 * the linemode option.
+		 */
+		linemode = 0;
+		editmode = 0;
+		send_do(TELOPT_LINEMODE, 1);  /* send do linemode */
+	}
+#endif	/* LINEMODE */
+
+	/*
+	 * Send along a couple of other options that we wish to negotiate.
+	 */
+	send_do(TELOPT_NAWS, 1);
+	send_will(TELOPT_STATUS, 1);
+	flowmode = 1;		/* default flow control state */
+	restartany = -1;	/* uninitialized... */
+	send_do(TELOPT_LFLOW, 1);
+
+	/*
+	 * Spin, waiting for a response from the DO ECHO.  However,
+	 * some REALLY DUMB telnets out there might not respond
+	 * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
+	 * telnets so far seem to respond with WONT for a DO that
+	 * they don't understand...) because by the time we get the
+	 * response, it will already have processed the DO ECHO.
+	 * Kludge upon kludge.
+	 */
+	while (his_will_wont_is_changing(TELOPT_NAWS))
+		ttloop();
+
+	/*
+	 * But...
+	 * The client might have sent a WILL NAWS as part of its
+	 * startup code; if so, we'll be here before we get the
+	 * response to the DO ECHO.  We'll make the assumption
+	 * that any implementation that understands about NAWS
+	 * is a modern enough implementation that it will respond
+	 * to our DO ECHO request; hence we'll do another spin
+	 * waiting for the ECHO option to settle down, which is
+	 * what we wanted to do in the first place...
+	 */
+	if (his_want_state_is_will(TELOPT_ECHO) &&
+	    his_state_is_will(TELOPT_NAWS)) {
+		while (his_will_wont_is_changing(TELOPT_ECHO))
+			ttloop();
+	}
+	/*
+	 * On the off chance that the telnet client is broken and does not
+	 * respond to the DO ECHO we sent, (after all, we did send the
+	 * DO NAWS negotiation after the DO ECHO, and we won't get here
+	 * until a response to the DO NAWS comes back) simulate the
+	 * receipt of a will echo.  This will also send a WONT ECHO
+	 * to the client, since we assume that the client failed to
+	 * respond because it believes that it is already in DO ECHO
+	 * mode, which we do not want.
+	 */
+	if (his_want_state_is_will(TELOPT_ECHO)) {
+		DIAG(TD_OPTIONS,
+			{sprintf(nfrontp, "td: simulating recv\r\n");
+			 nfrontp += strlen(nfrontp);});
+		willoption(TELOPT_ECHO);
+	}
+
+	/*
+	 * Finally, to clean things up, we turn on our echo.  This
+	 * will break stupid 4.2 telnets out of local terminal echo.
+	 */
+
+	if (my_state_is_wont(TELOPT_ECHO))
+		send_will(TELOPT_ECHO, 1);
+
+#ifndef	STREAMSPTY
+	/*
+	 * Turn on packet mode
+	 */
+	(void) ioctl(p, TIOCPKT, (char *)&on);
+#endif
+
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+	/*
+	 * Continuing line mode support.  If client does not support
+	 * real linemode, attempt to negotiate kludge linemode by sending
+	 * the do timing mark sequence.
+	 */
+	if (lmodetype < REAL_LINEMODE)
+		send_do(TELOPT_TM, 1);
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+
+	/*
+	 * Call telrcv() once to pick up anything received during
+	 * terminal type negotiation, 4.2/4.3 determination, and
+	 * linemode negotiation.
+	 */
+	telrcv();
+
+	(void) ioctl(f, FIONBIO, (char *)&on);
+	(void) ioctl(p, FIONBIO, (char *)&on);
+#if	defined(CRAY2) && defined(UNICOS5)
+	init_termdriver(f, p, interrupt, sendbrk);
+#endif
+
+#if	defined(SO_OOBINLINE)
+	(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
+				(char *)&on, sizeof(on));
+#endif	/* defined(SO_OOBINLINE) */
+
+#ifdef	SIGTSTP
+	(void) signal(SIGTSTP, SIG_IGN);
+#endif
+#ifdef	SIGTTOU
+	/*
+	 * Ignoring SIGTTOU keeps the kernel from blocking us
+	 * in ttioct() in /sys/tty.c.
+	 */
+	(void) signal(SIGTTOU, SIG_IGN);
+#endif
+
+	(void) signal(SIGCHLD, cleanup);
+
+#if	defined(CRAY2) && defined(UNICOS5)
+	/*
+	 * Cray-2 will send a signal when pty modes are changed by slave
+	 * side.  Set up signal handler now.
+	 */
+	if ((int)signal(SIGUSR1, termstat) < 0)
+		perror("signal");
+	else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0)
+		perror("ioctl:TCSIGME");
+	/*
+	 * Make processing loop check terminal characteristics early on.
+	 */
+	termstat();
+#endif
+
+#ifdef  TIOCNOTTY
+	{
+		register int t;
+		t = open(_PATH_TTY, O_RDWR);
+		if (t >= 0) {
+			(void) ioctl(t, TIOCNOTTY, (char *)0);
+			(void) close(t);
+		}
+	}
+#endif
+
+#if	defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY)
+	(void) setsid();
+	ioctl(p, TIOCSCTTY, 0);
+#endif
+
+	/*
+	 * Show banner that getty never gave.
+	 *
+	 * We put the banner in the pty input buffer.  This way, it
+	 * gets carriage return null processing, etc., just like all
+	 * other pty --> client data.
+	 */
+
+#if	!defined(CRAY) || !defined(NEWINIT)
+	if (getenv("USER"))
+		hostinfo = 0;
+#endif
+
+	if (getent(defent, "default") == 1) {
+		char *getstr();
+		char *cp=defstrs;
+
+		HE = getstr("he", &cp);
+		HN = getstr("hn", &cp);
+		IM = getstr("im", &cp);
+		if (HN && *HN) {
+			(void) strncpy(host_name, HN, sizeof(host_name) - 1);
+			host_name[sizeof(host_name) - 1] = '\0';
+		}
+		if (IM == 0)
+			IM = "";
+	} else {
+		IM = DEFAULT_IM;
+		HE = 0;
+	}
+	edithost(HE, host_name);
+	if (hostinfo && *IM)
+		putf(IM, ptyibuf2);
+
+	if (pcc)
+		(void) strncat(ptyibuf2, ptyip, pcc+1);
+	ptyip = ptyibuf2;
+	pcc = strlen(ptyip);
+#ifdef	LINEMODE
+	/*
+	 * Last check to make sure all our states are correct.
+	 */
+	init_termbuf();
+	localstat();
+#endif	/* LINEMODE */
+
+	DIAG(TD_REPORT,
+		{sprintf(nfrontp, "td: Entering processing loop\r\n");
+		 nfrontp += strlen(nfrontp);});
+
+#ifdef	convex
+	startslave(host);
+#endif
+
+	for (;;) {
+		fd_set ibits, obits, xbits;
+		register int c;
+
+		if (ncc < 0 && pcc < 0)
+			break;
+
+#if	defined(CRAY2) && defined(UNICOS5)
+		if (needtermstat)
+			_termstat();
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+		FD_ZERO(&ibits);
+		FD_ZERO(&obits);
+		FD_ZERO(&xbits);
+		/*
+		 * Never look for input if there's still
+		 * stuff in the corresponding output buffer
+		 */
+		if (nfrontp - nbackp || pcc > 0) {
+			FD_SET(f, &obits);
+		} else {
+			FD_SET(p, &ibits);
+		}
+		if (pfrontp - pbackp || ncc > 0) {
+			FD_SET(p, &obits);
+		} else {
+			FD_SET(f, &ibits);
+		}
+		if (!SYNCHing) {
+			FD_SET(f, &xbits);
+		}
+		if ((c = select(16, &ibits, &obits, &xbits,
+						(struct timeval *)0)) < 1) {
+			if (c == -1) {
+				if (errno == EINTR) {
+					continue;
+				}
+			}
+			sleep(5);
+			continue;
+		}
+
+		/*
+		 * Any urgent data?
+		 */
+		if (FD_ISSET(net, &xbits)) {
+		    SYNCHing = 1;
+		}
+
+		/*
+		 * Something to read from the network...
+		 */
+		if (FD_ISSET(net, &ibits)) {
+#if	!defined(SO_OOBINLINE)
+			/*
+			 * In 4.2 (and 4.3 beta) systems, the
+			 * OOB indication and data handling in the kernel
+			 * is such that if two separate TCP Urgent requests
+			 * come in, one byte of TCP data will be overlaid.
+			 * This is fatal for Telnet, but we try to live
+			 * with it.
+			 *
+			 * In addition, in 4.2 (and...), a special protocol
+			 * is needed to pick up the TCP Urgent data in
+			 * the correct sequence.
+			 *
+			 * What we do is:  if we think we are in urgent
+			 * mode, we look to see if we are "at the mark".
+			 * If we are, we do an OOB receive.  If we run
+			 * this twice, we will do the OOB receive twice,
+			 * but the second will fail, since the second
+			 * time we were "at the mark", but there wasn't
+			 * any data there (the kernel doesn't reset
+			 * "at the mark" until we do a normal read).
+			 * Once we've read the OOB data, we go ahead
+			 * and do normal reads.
+			 *
+			 * There is also another problem, which is that
+			 * since the OOB byte we read doesn't put us
+			 * out of OOB state, and since that byte is most
+			 * likely the TELNET DM (data mark), we would
+			 * stay in the TELNET SYNCH (SYNCHing) state.
+			 * So, clocks to the rescue.  If we've "just"
+			 * received a DM, then we test for the
+			 * presence of OOB data when the receive OOB
+			 * fails (and AFTER we did the normal mode read
+			 * to clear "at the mark").
+			 */
+		    if (SYNCHing) {
+			int atmark;
+
+			(void) ioctl(net, SIOCATMARK, (char *)&atmark);
+			if (atmark) {
+			    ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
+			    if ((ncc == -1) && (errno == EINVAL)) {
+				ncc = read(net, netibuf, sizeof (netibuf));
+				if (sequenceIs(didnetreceive, gotDM)) {
+				    SYNCHing = stilloob(net);
+				}
+			    }
+			} else {
+			    ncc = read(net, netibuf, sizeof (netibuf));
+			}
+		    } else {
+			ncc = read(net, netibuf, sizeof (netibuf));
+		    }
+		    settimer(didnetreceive);
+#else	/* !defined(SO_OOBINLINE)) */
+		    ncc = read(net, netibuf, sizeof (netibuf));
+#endif	/* !defined(SO_OOBINLINE)) */
+		    if (ncc < 0 && errno == EWOULDBLOCK)
+			ncc = 0;
+		    else {
+			if (ncc <= 0) {
+			    break;
+			}
+			netip = netibuf;
+		    }
+		    DIAG((TD_REPORT | TD_NETDATA),
+			    {sprintf(nfrontp, "td: netread %d chars\r\n", ncc);
+			     nfrontp += strlen(nfrontp);});
+		    DIAG(TD_NETDATA, printdata("nd", netip, ncc));
+		}
+
+		/*
+		 * Something to read from the pty...
+		 */
+		if (FD_ISSET(p, &ibits)) {
+#ifndef	STREAMSPTY
+			pcc = read(p, ptyibuf, BUFSIZ);
+#else
+			pcc = readstream(p, ptyibuf, BUFSIZ);
+#endif
+			/*
+			 * On some systems, if we try to read something
+			 * off the master side before the slave side is
+			 * opened, we get EIO.
+			 */
+			if (pcc < 0 && (errno == EWOULDBLOCK ||
+#ifdef	EAGAIN
+					errno == EAGAIN ||
+#endif
+					errno == EIO)) {
+				pcc = 0;
+			} else {
+				if (pcc <= 0)
+					break;
+#if	!defined(CRAY2) || !defined(UNICOS5)
+#ifdef	LINEMODE
+				/*
+				 * If ioctl from pty, pass it through net
+				 */
+				if (ptyibuf[0] & TIOCPKT_IOCTL) {
+					copy_termbuf(ptyibuf+1, pcc-1);
+					localstat();
+					pcc = 1;
+				}
+#endif	/* LINEMODE */
+				if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
+					netclear();	/* clear buffer back */
+#ifndef	NO_URGENT
+					/*
+					 * There are client telnets on some
+					 * operating systems get screwed up
+					 * royally if we send them urgent
+					 * mode data.
+					 */
+					*nfrontp++ = IAC;
+					*nfrontp++ = DM;
+					neturg = nfrontp-1; /* off by one XXX */
+#endif
+				}
+				if (his_state_is_will(TELOPT_LFLOW) &&
+				    (ptyibuf[0] &
+				     (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
+					int newflow =
+					    ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
+					if (newflow != flowmode) {
+						flowmode = newflow;
+						(void) sprintf(nfrontp,
+							"%c%c%c%c%c%c",
+							IAC, SB, TELOPT_LFLOW,
+							flowmode ? LFLOW_ON
+								 : LFLOW_OFF,
+							IAC, SE);
+						nfrontp += 6;
+					}
+				}
+				pcc--;
+				ptyip = ptyibuf+1;
+#else	/* defined(CRAY2) && defined(UNICOS5) */
+				if (!uselinemode) {
+					unpcc = pcc;
+					unptyip = ptyibuf;
+					pcc = term_output(&unptyip, ptyibuf2,
+								&unpcc, BUFSIZ);
+					ptyip = ptyibuf2;
+				} else
+					ptyip = ptyibuf;
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+			}
+		}
+
+		while (pcc > 0) {
+			if ((&netobuf[BUFSIZ] - nfrontp) < 2)
+				break;
+			c = *ptyip++ & 0377, pcc--;
+			if (c == IAC)
+				*nfrontp++ = c;
+#if	defined(CRAY2) && defined(UNICOS5)
+			else if (c == '\n' &&
+				     my_state_is_wont(TELOPT_BINARY) && newmap)
+				*nfrontp++ = '\r';
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+			*nfrontp++ = c;
+			if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
+				if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
+					*nfrontp++ = *ptyip++ & 0377;
+					pcc--;
+				} else
+					*nfrontp++ = '\0';
+			}
+		}
+#if	defined(CRAY2) && defined(UNICOS5)
+		/*
+		 * If chars were left over from the terminal driver,
+		 * note their existence.
+		 */
+		if (!uselinemode && unpcc) {
+			pcc = unpcc;
+			unpcc = 0;
+			ptyip = unptyip;
+		}
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+
+		if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
+			netflush();
+		if (ncc > 0)
+			telrcv();
+		if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
+			ptyflush();
+	}
+	cleanup(0);
+}  /* end of telnet */
+	
+#ifndef	TCSIG
+# ifdef	TIOCSIG
+#  define TCSIG TIOCSIG
+# endif
+#endif
+
+#ifdef	STREAMSPTY
+
+int flowison = -1;  /* current state of flow: -1 is unknown */
+
+int readstream(p, ibuf, bufsize)
+	int p;
+	char *ibuf;
+	int bufsize;
+{
+	int flags = 0;
+	int ret = 0;
+	struct termios *tsp;
+	struct termio *tp;
+	struct iocblk *ip;
+	char vstop, vstart;
+	int ixon;
+	int newflow;
+
+	strbufc.maxlen = BUFSIZ;
+	strbufc.buf = ctlbuf;
+	strbufd.maxlen = bufsize-1;
+	strbufd.len = 0;
+	strbufd.buf = ibuf+1;
+	ibuf[0] = 0;
+
+	ret = getmsg(p, &strbufc, &strbufd, &flags);
+	if (ret < 0)  /* error of some sort -- probably EAGAIN */
+		return(-1);
+
+	if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
+		/* data message */
+		if (strbufd.len > 0) {			/* real data */
+			return(strbufd.len + 1);	/* count header char */
+		} else {
+			/* nothing there */
+			errno = EAGAIN;
+			return(-1);
+		}
+	}
+
+	/*
+	 * It's a control message.  Return 1, to look at the flag we set
+	 */
+
+	switch (ctlbuf[0]) {
+	case M_FLUSH:
+		if (ibuf[1] & FLUSHW)
+			ibuf[0] = TIOCPKT_FLUSHWRITE;
+		return(1);
+
+	case M_IOCTL:
+		ip = (struct iocblk *) (ibuf+1);
+
+		switch (ip->ioc_cmd) {
+		case TCSETS:
+		case TCSETSW:
+		case TCSETSF:
+			tsp = (struct termios *)
+					(ibuf+1 + sizeof(struct iocblk));
+			vstop = tsp->c_cc[VSTOP];
+			vstart = tsp->c_cc[VSTART];
+			ixon = tsp->c_iflag & IXON;
+			break;
+		case TCSETA:
+		case TCSETAW:
+		case TCSETAF:
+			tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));
+			vstop = tp->c_cc[VSTOP];
+			vstart = tp->c_cc[VSTART];
+			ixon = tp->c_iflag & IXON;      
+			break;
+		default:
+			errno = EAGAIN;
+			return(-1);
+		}
+
+		newflow =  (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
+		if (newflow != flowison) {  /* it's a change */
+			flowison = newflow;
+			ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
+			return(1);
+		}
+	}
+
+	/* nothing worth doing anything about */
+	errno = EAGAIN;
+	return(-1);
+}
+#endif /* STREAMSPTY */
+
+/*
+ * Send interrupt to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write intr char.
+ */
+	void
+interrupt()
+{
+	ptyflush();	/* half-hearted */
+
+#ifdef	TCSIG
+	(void) ioctl(pty, TCSIG, (char *)SIGINT);
+#else	/* TCSIG */
+	init_termbuf();
+	*pfrontp++ = slctab[SLC_IP].sptr ?
+			(unsigned char)*slctab[SLC_IP].sptr : '\177';
+#endif	/* TCSIG */
+}
+
+/*
+ * Send quit to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write quit char.
+ */
+	void
+sendbrk()
+{
+	ptyflush();	/* half-hearted */
+#ifdef	TCSIG
+	(void) ioctl(pty, TCSIG, (char *)SIGQUIT);
+#else	/* TCSIG */
+	init_termbuf();
+	*pfrontp++ = slctab[SLC_ABORT].sptr ?
+			(unsigned char)*slctab[SLC_ABORT].sptr : '\034';
+#endif	/* TCSIG */
+}
+
+	void
+sendsusp()
+{
+#ifdef	SIGTSTP
+	ptyflush();	/* half-hearted */
+# ifdef	TCSIG
+	(void) ioctl(pty, TCSIG, (char *)SIGTSTP);
+# else	/* TCSIG */
+	*pfrontp++ = slctab[SLC_SUSP].sptr ?
+			(unsigned char)*slctab[SLC_SUSP].sptr : '\032';
+# endif	/* TCSIG */
+#endif	/* SIGTSTP */
+}
+
+/*
+ * When we get an AYT, if ^T is enabled, use that.  Otherwise,
+ * just send back "[Yes]".
+ */
+	void
+recv_ayt()
+{
+#if	defined(SIGINFO) && defined(TCSIG)
+	if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
+		(void) ioctl(pty, TCSIG, (char *)SIGINFO);
+		return;
+	}
+#endif
+	(void) strncpy(nfrontp, "\r\n[Yes]\r\n",
+		       sizeof(netobuf) - 1 - (nfrontp - netobuf));
+	nfrontp += 9;
+	*nfrontp = '\0';
+}
+
+	void
+doeof()
+{
+	init_termbuf();
+
+#if	defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN)
+	if (!tty_isediting()) {
+		extern char oldeofc;
+		*pfrontp++ = oldeofc;
+		return;
+	}
+#endif
+	*pfrontp++ = slctab[SLC_EOF].sptr ?
+			(unsigned char)*slctab[SLC_EOF].sptr : '\004';
+}
diff --git a/krb5-1-6/src/appl/telnet/telnetd/telnetd.0.ps b/krb5-1-6/src/appl/telnet/telnetd/telnetd.0.ps
new file mode 100644
index 000000000..bbbdbd002
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/telnetd.0.ps
@@ -0,0 +1,555 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Courier-Bold
+%%+ font Courier-Oblique
+%%+ font Courier
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 5
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier-Oblique
+%%IncludeResource: font Courier
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Courier@0 ENC0/Courier RE
+/Courier-Oblique@0 ENC0/Courier-Oblique RE/Courier-Bold@0 ENC0/Courier-Bold RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNETD \( 8 \))72 48 R(BSD System Manager')
+241.42 48 Q 2.5(sM)-.55 G 105.272(anual TELNETD)348.92 48 R 1.666(\(8\))1.666 G
+/F1 10/Times-Bold@0 SF -.2(NA)72 108 S(ME).2 E/F2 10/Courier-Bold@0 SF(telnetd)
+102 120 Q F0 2.5<ad44>2.5 G(ARP)161.46 120 Q(A)-.92 E/F3 9/Times-Roman@0 SF
+(TELNET)2.5 E F0(protocol serv)2.5 E(er)-.15 E F1(SYNOPSIS)72 144 Q F2
+(/usr/libexec/telnetd)102 156 Q F0([)3.333 E F2<ad61>2.499 E/F4 10
+/Courier-Oblique@0 SF(authmode)6 E F0 3.333(][).833 G F2<ad42>-.834 E F0 3.333
+(][).833 G F2<ad44>-.834 E F4(debugmode)6 E F0 3.333(][).833 G F2(\255edebug)
+-.834 E F0 3.333(][).833 G F2<ad68>-.834 E F0(]).833 E([)228.833 168 Q F2<ad49>
+2.499 E F4(initid)A F0 3.333(][).833 G F2<ad6c>-.834 E F0 3.333(][).833 G F2
+<ad6b>-.834 E F0 3.333(][).833 G F2<ad6e>-.834 E F0 3.333(][).833 G F2<ad72>
+-.834 E F4(lowpty-highpty)A F0 3.333(][).833 G F2<ad73>-.834 E F0 3.333(][).833
+G F2<ad53>-.834 E F4(tos)228 180 Q F0 3.333(][).833 G F2<ad75>-.834 E F4(len)6
+E F0 3.333(][).833 G F2<ad55>-.834 E F0 3.333(][).833 G F2<ad58>-.834 E F4
+(authtype)6 E F0 3.333(][).833 G F2(\255debug)-.834 E F0([)6.833 E F4(port).833
+E F0 .833(]]).833 G F1(DESCRIPTION)72 204 Q F0(The)102 216 Q F2(telnetd)3.044 E
+F0 .544(command is a serv)3.044 F .544(er which supports the)-.15 F F3 -.36(DA)
+3.044 G(RP).36 E(A)-.828 E F0(standard)3.044 E F3(TELNET)3.044 E F0 .543
+(virtual terminal protocol.)3.044 F F2(Telnetd)102 228 Q F0 .221
+(is normally in)2.721 F -.2(vo)-.4 G -.1(ke).2 G 2.721(db).1 G 2.721(yt)234.184
+228 S .221(he internet serv)244.685 228 R .221(er \(see)-.15 F/F5 10/Courier@0
+SF(inetd)2.721 E F0 2.942(\(8\)\) for)B .221(requests to connect to the)2.721 F
+F3(TELNET)2.721 E F0 .673(port as indicated by the)102 240 R F5(/etc/services)
+3.173 E F0 .673(\214le \(see)3.173 F F5(services)3.173 E F0 3.846(\(5\)\). The)
+B F2(\255debug)4.839 E F0 .672(option may be used to)3.173 F .145(start up)102
+252 R F2(telnetd)2.645 E F0(manually)2.645 E 2.645(,i)-.65 G .145
+(nstead of through)223.65 252 R F5(inetd)2.645 E F0 2.79(\(8\). If)B .145
+(started up this w)2.645 F(ay)-.1 E(,)-.65 E F4(port)2.645 E F0 .145
+(may be speci\214ed to)2.645 F(run)102 264 Q F2(telnetd)2.5 E F0
+(on an alternate)2.5 E F3(TCP)2.5 E F0(port number)2.5 E(.)-.55 E(The)102 282 Q
+F2(telnetd)2.5 E F0(command accepts the follo)2.5 E(wing options:)-.25 E F2
+<ad61>103.666 300 Q F4(authmode)6 E F0 .106(This option may be used for specif\
+ying what mode should be used for authentication.)173 312 R(Note)5.106 E 2.778
+(that this option is only useful if)173 324 R F2(telnetd)5.279 E F0 2.779
+(has been compiled with support for the)5.279 F F5(AUTHENTICATION)173 336 Q F0
+2.5(option. There)2.5 F(are se)2.5 E -.15(ve)-.25 G(ral v).15 E(alid v)-.25 E
+(alues for)-.25 E F4(authmode:)2.5 E F0(deb)173 354 Q 8.26(ug T)-.2 F
+(urns on authentication deb)-.45 E(ugging code.)-.2 E 15.84(user Only)173 372 R
+(allo)2.923 E 2.923(wc)-.25 G .423(onnections when the remote user can pro)
+260.256 372 R .422(vide v)-.15 F .422(alid authentication in-)-.25 F 1.277
+(formation to identify the remote user)208 384 R 3.777(,a)-.4 G 1.277
+(nd is allo)372.181 384 R 1.277(wed access to the speci\214ed ac-)-.25 F
+(count without pro)208 396 Q(viding a passw)-.15 E(ord.)-.1 E -.25(va)173 414 S
+12.75(lid Only).25 F(allo)2.923 E 2.923(wc)-.25 G .423
+(onnections when the remote user can pro)260.256 414 R .422(vide v)-.15 F .422
+(alid authentication in-)-.25 F .742(formation to identify the remote user)208
+426 R 5.743(.T)-.55 G(he)372.995 426 Q F5(login)3.243 E F0 .743
+(\(1\) command will pro)B .743(vide an)-.15 F(y)-.15 E .53(additional user v)
+208 438 R .529(eri\214cation needed if the remote user is not allo)-.15 F .529
+(wed automatic ac-)-.25 F(cess to the speci\214ed account.)208 450 Q 11.95
+(other Only)173 468 R(allo)3.028 E 3.029(wc)-.25 G .529
+(onnections that supply some authentication information.)260.467 468 R .529
+(This option)5.529 F .079(is currently not supported by an)208 480 R 2.578(yo)
+-.15 G 2.578(ft)347.752 480 S .078(he e)356.44 480 R .078
+(xisting authentication mechanisms, and is)-.15 F(thus the same as specifying)
+208 492 Q F2 -3.5(\255a valid)4.166 F F0(.)A 13.06(none This)173 510 R .869
+(is the def)3.369 F .869(ault state.)-.1 F .869
+(Authentication information is not required.)5.869 F .87(If no or in-)5.869 F
+(suf)208 522 Q .394(\214cient authentication information is pro)-.25 F .393
+(vided, then the)-.15 F F5(login)2.893 E F0 .393(\(1\) program will)B(pro)208
+534 Q(vide the necessary user v)-.15 E(eri\214cation.)-.15 E(of)173 552 Q 23.59
+(fT)-.25 G 1.385(his disables the authentication code.)214.11 552 R 1.385
+(All user v)6.385 F 1.385(eri\214cation will happen through)-.15 F(the)208 564
+Q F5(login)2.5 E F0(\(1\) program.)A F2<ad42>103.666 582 Q F0 .82
+(Speci\214es bftp serv)173 582 R .82(er mode.)-.15 F .819(In this mode,)5.82 F
+F2(telnetd)3.319 E F0 .819(causes login to start a)3.319 F F5(bftp)3.319 E F0
+.819(\(1\) ses-)B .747(sion rather than the user')173 594 R 3.247(sn)-.55 G
+.747(ormal shell.)286.995 594 R .748
+(In bftp daemon mode normal logins are not sup-)5.747 F
+(ported, and it must be used on a port other than the normal)173 606 Q F3
+(TELNET)2.5 E F0(port.)2.5 E F2<ad44>103.666 624 Q F4(debugmode)6 E F0 .827
+(This option may be used for deb)173 636 R .827(ugging purposes.)-.2 F .827
+(This allo)5.827 F(ws)-.25 E F2(telnetd)3.327 E F0 .827(to print out de-)3.327
+F -.2(bu)173 648 S .827(gging information to the connection, allo).2 F .827
+(wing the user to see what)-.25 F F2(telnetd)3.327 E F0 .827(is doing.)3.327 F
+(There are se)173 660 Q -.15(ve)-.25 G(ral possible v).15 E(alues for)-.25 E F4
+(debugmode:)2.5 E F2(options)173 678 Q F0(Prints information about the ne)226
+678 Q(gotiation of)-.15 E F3(TELNET)2.5 E F0(options.)2.5 E(4.2 Berk)72 750 Q
+(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71(ution February)-.2 F
+(3, 1994)2.5 E(1)535 750 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNETD \( 8 \))72 48 R(BSD System Manager')
+241.42 48 Q 2.5(sM)-.55 G 105.272(anual TELNETD)348.92 48 R 1.666(\(8\))1.666 G
+/F1 10/Courier-Bold@0 SF(report)173 96 Q F0 2.438(Prints the)226 96 R F1
+(options)4.938 E F0 2.437(information, plus some additional information about)
+4.938 F(what processing is going on.)226 108 Q F1(netdata)173 126 Q F0
+(Displays the data stream recei)226 126 Q -.15(ve)-.25 G 2.5(db).15 G(y)367.51
+126 Q F1(telnetd.)2.5 E(ptydata)173 144 Q F0(Displays data written to the pty)
+226 144 Q(.)-.65 E F1(exercise)173 162 Q F0(Has not been implemented yet.)5 E
+F1(\255debug)103.666 180 Q F0(Enables deb)173 180 Q(ugging on each sock)-.2 E
+(et created by)-.1 E F1(telnetd)2.5 E F0(\(see)2.5 E/F2 10/Courier@0 SF
+(SO_DEBUG)2.5 E F0(in)2.5 E F2(socket)2.5 E F0(\(2\)\).)A F1(\255edebug)103.666
+198 Q F0(If)173 198 Q F1(telnetd)3.161 E F0 .662
+(has been compiled with support for data encryption, then the)3.161 F F1
+(\255edebug)4.828 E F0(op-)3.162 E(tion may be used to enable encryption deb)
+173 210 Q(ugging code.)-.2 E F1<ad68>103.666 228 Q F0(Disables the printing of\
+ host-speci\214c information before login has been completed.)173 228 Q F1
+<ad49>103.666 246 Q/F3 10/Courier-Oblique@0 SF(initid)7.171 E F0 1.171
+(This option is only applicable to)174.171 246 R/F4 9/Times-Roman@0 SF(UNICOS)
+3.671 E F0 1.171(systems prior to 7.0.)3.671 F 1.17(It speci\214es the)6.171 F
+F2(ID)3.67 E F0(from)3.67 E F2(/etc/inittab)173 258 Q F0
+(to use when init starts login sessions.)2.5 E(The def)5 E(ault)-.1 E F2(ID)2.5
+E F0(is)2.5 E F2(fe.)2.5 E F1<ad6b>103.666 276 Q F0 .556
+(This option is only useful if)173 276 R F1(telnetd)3.056 E F0 .557
+(has been compiled with both linemode and kludge)3.056 F .521
+(linemode support.)173 288 R .521(If the)5.521 F F1<ad6b>4.687 E F0 .52
+(option is speci\214ed, then if the remote client does not support)3.02 F(the)
+173 300 Q F2(LINEMODE)3.697 E F0 1.197(option, then)3.697 F F1(telnetd)3.697 E
+F0 1.197(will operate in character at a time mode.)3.697 F 1.198(It will)6.198
+F .148(still support kludge linemode, b)173 312 R .147
+(ut will only go into kludge linemode if the remote client re-)-.2 F 2.06
+(quests it.)173 324 R 2.061(\(This is done by by the client sending)7.06 F F2
+2.061(DONT SUPPRESS-GO-AHEAD)4.561 F F0(and)4.561 E F2 .1(DONT ECHO)173 336 R
+F0 .1(.\) The)B F1<ad6b>4.266 E F0 .1
+(option is most useful when there are remote clients that do not sup-)2.6 F .67
+(port kludge linemode, b)173 348 R .67(ut pass the heuristic \(if the)-.2 F
+3.17(yr)-.15 G .67(espond with)390.88 348 R F2 .67(WILL TIMING-MARK)3.17 F F0
+(in response to a)173 360 Q F2(DO TIMING-MARK\))2.5 E F0
+(for kludge linemode support.)2.5 E F1<ad6c>103.666 378 Q F0 .672
+(Speci\214es line mode.)173 378 R -.35(Tr)5.672 G .671
+(ies to force clients to use line- at-a-time mode.).35 F .671(If the)5.671 F F2
+(LINEMODE)3.171 E F0(option is not supported, it will go into kludge linemode.)
+173 390 Q F1<ad6e>103.666 408 Q F0(Disable)173 408 Q F2(TCP)3.488 E F0 -.1(ke)
+3.488 G(ep-ali).1 E -.15(ve)-.25 G 3.488(s. Normally).15 F F1(telnetd)3.488 E
+F0 .988(enables the)3.488 F F4(TCP)3.489 E F0 -.1(ke)3.489 G(ep-ali).1 E 1.289
+-.15(ve m)-.25 H .989(echanism to).15 F .602(probe connections that ha)173 420
+R .902 -.15(ve b)-.2 H .602
+(een idle for some period of time to determine if the client is).15 F 1.124
+(still there, so that idle connections from machines that ha)173 432 R 1.424
+-.15(ve c)-.2 H 1.124(rashed or can no longer be).15 F
+(reached may be cleaned up.)173 444 Q F1<ad72>103.666 462 Q F3(lowpty-highpty)6
+E F0 .772(This option is only enabled when)173 474 R F1(telnetd)3.272 E F0 .771
+(is compiled for)3.271 F F2(UNICOS.)3.271 E F0 .771(It speci\214es an in-)3.271
+F(clusi)173 486 Q 3.232 -.15(ve r)-.25 H 2.932(ange of pseudo-terminal de).15 F
+2.932(vices to use.)-.25 F 2.933(If the system has sysconf v)7.933 F(ariable)
+-.25 E F2(_SC_CRAY_NPTY)173 498 Q F0 1.486(con\214gured, the def)3.986 F 1.486
+(ault pty search range is 0 to)-.1 F F2(_SC_CRAY_NPTY;)3.986 E F0 .72
+(otherwise, the def)173 510 R .72(ault range is 0 to 128.)-.1 F(Either)5.72 E
+F3(lowpty)3.22 E F0(or)3.22 E F3(highpty)3.22 E F0 .72(may be omitted to)3.22 F
+(allo)173 522 Q 2.6(wc)-.25 G .1(hanging either end of the search range.)202.01
+522 R(If)5.1 E F3(lowpty)2.6 E F0 .1(is omitted, the - character is still)2.6 F
+(required so that)173 534 Q F1(telnetd)2.5 E F0(can dif)2.5 E(ferentiate)-.25 E
+F3(highpty)2.5 E F0(from)2.5 E F3(lowpty)2.5 E F0(.)A F1<ad73>103.666 552 Q F0
+1.391(This option is only enabled if)173 552 R F1(telnetd)3.891 E F0 1.391
+(is compiled with support for)3.891 F F4(SecurID)3.891 E F0 3.891(cards. It)
+3.891 F .787(causes the)173 564 R F1<ad73>4.953 E F0 .786
+(option to be passed on to)3.286 F F2(login)3.286 E F0 4.072(\(1\), and)B .786
+(thus is only useful if)3.286 F F2(login)3.286 E F0(\(1\))A .48(supports the)
+173 576 R F1<ad73>4.646 E F0 .48(\215ag to indicate that only)2.98 F F4
+(SecurID)2.98 E F0 -.25(va)2.98 G .481(lidated logins are allo).25 F .481
+(wed, and is usu-)-.25 F
+(ally useful for controlling remote logins from outside of a \214re)173 588 Q
+-.1(wa)-.25 G(ll.).1 E F1<ad53>103.666 606 Q F3(tos)6 E F1<ad75>103.666 624 Q
+F3(len)6.628 E F0 .628
+(This option is used to specify the size of the \214eld in the)173.628 624 R F2
+(utmp)3.127 E F0 .627(structure that holds the re-)3.127 F 1(mote host name.)
+173 636 R 1(If the resolv)6 F 1(ed host name is longer than)-.15 F F3(len)3.5 E
+F0 3.5(,t)C 1(he dotted decimal v)441.99 636 R(alue)-.25 E .046
+(will be used instead.)173 648 R .046(This allo)5.046 F .046(ws hosts with v)
+-.25 F .045(ery long host names that o)-.15 F -.15(ve)-.15 G(r\215o).15 E 2.545
+(wt)-.25 G .045(his \214eld to)497.68 648 R .996
+(still be uniquely identi\214ed.)173 660 R(Specifying)5.997 E F1(\255u0)5.163 E
+F0 .997(indicates that only dotted decimal addresses)3.497 F
+(should be put into the)173 672 Q F2(utmp)2.5 E F0(\214le.)2.5 E F1<ad55>
+103.666 690 Q F0 .422(This option causes)173 690 R F1(telnetd)2.922 E F0 .422
+(to refuse connections from addresses that cannot be mapped)2.922 F(4.2 Berk)72
+750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71(ution February)-.2 F
+(3, 1994)2.5 E(2)535 750 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNETD \( 8 \))72 48 R(BSD System Manager')
+241.42 48 Q 2.5(sM)-.55 G 105.272(anual TELNETD)348.92 48 R 1.666(\(8\))1.666 G
+(back into a symbolic name via the)173 96 Q/F1 10/Courier@0 SF(gethostbyaddr)
+2.5 E F0(\(3\) routine.)A/F2 10/Courier-Bold@0 SF<ad58>103.666 114 Q/F3 10
+/Courier-Oblique@0 SF(authtype)6 E F0 .123(This option is only v)173 126 R .123
+(alid if)-.25 F F2(telnetd)2.623 E F0 .123(has been b)2.623 F .124
+(uilt with support for the authentication op-)-.2 F 2.968(tion. It)173 138 R
+.467(disables the use of)2.968 F F3(authtype)2.967 E F0 .467
+(authentication, and can be used to temporarily dis-)2.967 F
+(able a speci\214c authentication type without ha)173 150 Q(ving to recompile)
+-.2 E F2(telnetd)2.5 E F0(.)A F2(Telnetd)102 168 Q F0 .851
+(operates by allocating a pseudo-terminal de)3.351 F .851(vice \(see)-.25 F F1
+(pty)3.351 E F0 4.202(\(4\)\) for)B 3.351(ac)3.351 G .852
+(lient, then creating a login)431.882 168 R .757(process which has the sla)102
+180 R 1.057 -.15(ve s)-.2 H .757(ide of the pseudo-terminal as).15 F F1(stdin)
+3.257 E F0(,)A F1(stdout)3.256 E F0(and)3.256 E F1(stderr)3.256 E F0(.)A F2
+(Telnetd)3.256 E F0(ma-)3.256 E .483
+(nipulates the master side of the pseudo-terminal, implementing the)102 192 R
+/F4 9/Times-Roman@0 SF(TELNET)2.984 E F0 .484(protocol and passing characters)
+2.984 F(between the remote client and the login process.)102 204 Q .538(When a)
+102 222 R F4(TELNET)3.038 E F0 .538(session is started up,)3.038 F F2(telnetd)
+3.038 E F0(sends)3.038 E F4(TELNET)3.038 E F0 .538
+(options to the client side indicating a will-)3.038 F(ingness to do the follo)
+102 234 Q(wing)-.25 E F4(TELNET)2.5 E F0
+(options, which are described in more detail belo)2.5 E(w:)-.25 E F1
+(DO AUTHENTICATION)132 252 Q(WILL ENCRYPT)132 264 Q(DO TERMINAL TYPE)132 276 Q
+(DO TSPEED)132 288 Q(DO XDISPLOC)132 300 Q(DO NEW-ENVIRON)132 312 Q(DO ENVIRON)
+132 324 Q(WILL SUPPRESS GO AHEAD)132 336 Q(DO ECHO)132 348 Q(DO LINEMODE)132
+360 Q(DO NAWS)132 372 Q(WILL STATUS)132 384 Q(DO LFLOW)132 396 Q
+(DO TIMING-MARK)132 408 Q F0 .468(The pseudo-terminal allocated to the client \
+is con\214gured to operate in cook)102 426 R .468(ed mode, and with)-.1 F F1
+.469(XTABS and)2.969 F(CRMOD)102 438 Q F0(enabled \(see)2.5 E F1(tty)2.5 E F0
+(\(4\)\).)A F2(Telnetd)102 456 Q F0(has support for enabling locally the follo)
+2.5 E(wing)-.25 E F4(TELNET)2.5 E F0(options:)2.5 E .558(WILL ECHO)102 474 R
+.558(When the)209.558 474 R F1(LINEMODE)3.057 E F0 .557(option is enabled, a)
+3.057 F F1 .557(WILL ECHO)3.057 F F0(or)3.057 E F1 .557(WONT ECHO)3.057 F F0
+.557(will be)3.057 F .487
+(sent to the client to indicate the current state of terminal echoing.)209 486
+R .487(When terminal)5.487 F .409(echo is not desired, a)209 498 R F1 .408
+(WILL ECHO)2.908 F F0 .408(is sent to indicate that)2.908 F F4(telnetd)2.908 E
+F0 .408(will tak)2.908 F 2.908(ec)-.1 G .408(are of)516.552 498 R 1.811
+(echoing an)209 510 R 4.311(yd)-.15 G 1.811
+(ata that needs to be echoed to the terminal, and then nothing is)268.572 510 R
+3.876(echoed. When)209 522 R 1.376(terminal echo is desired, a)3.876 F F1 1.375
+(WONT ECHO)3.875 F F0 1.375(is sent to indicate that)3.875 F F4(telnetd)209 534
+Q F0 .11(will not be doing an)2.61 F 2.61(yt)-.15 G .11
+(erminal echoing, so the client should do an)326.788 534 R 2.611(yt)-.15 G
+(erminal)509.45 534 Q(echoing that is needed.)209 546 Q .243(WILL BIN)102 564 R
+(AR)-.35 E 42.18(YI)-.65 G .243(ndicates that the client is willing to send a \
+8 bits of data, rather than the normal 7)212.573 564 R(bits of the Netw)209 576
+Q(ork V)-.1 E(irtual T)-.6 E(erminal.)-.7 E(WILL SGA)102 594 Q
+(Indicates that it will not be sending)209 594 Q F1(IAC GA,)2.5 E F0
+(go ahead, commands.)2.5 E .366(WILL ST)102 612 R -1.11(AT)-.93 G 41.27
+(US Indicates)1.11 F 2.866(aw)2.866 G .366
+(illingness to send the client, upon request, of the current status of all)
+262.858 612 R F4(TELNET)209 624 Q F0(options.)2.5 E .51(WILL TIMING-MARK)102
+642 R(Whene)209.51 642 Q -.15(ve)-.25 G 3.01(ra).15 G F1 .509(DO TIMING-MARK)
+-.001 F F0 .509(command is recei)3.009 F -.15(ve)-.25 G .509(d, it is al).15 F
+-.1(wa)-.1 G .509(ys responded to).1 F(with a)209 654 Q F1(WILL TIMING-MARK)2.5
+E F0 .726(WILL LOGOUT)102 672 R .726(When a)209.726 672 R F1 .726(DO LOGOUT)
+3.226 F F0 .726(is recei)3.226 F -.15(ve)-.25 G .726(d, a).15 F F1 .726
+(WILL LOGOUT)3.226 F F0 .726(is sent in response, and the)3.226 F(4.2 Berk)72
+750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71(ution February)-.2 F
+(3, 1994)2.5 E(3)535 750 Q EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNETD \( 8 \))72 48 R(BSD System Manager')
+241.42 48 Q 2.5(sM)-.55 G 105.272(anual TELNETD)348.92 48 R 1.666(\(8\))1.666 G
+/F1 9/Times-Roman@0 SF(TELNET)209 96 Q F0(session is shut do)2.5 E(wn.)-.25 E
+.118(WILL ENCR)102 114 R 32.1(YPT Only)-.65 F .118(sent if)2.618 F/F2 10
+/Courier-Bold@0 SF(telnetd)2.618 E F0 .118
+(is compiled with support for data encryption, and indicates)2.618 F 2.5(aw)209
+126 S(illingness to decrypt the data stream.)223.16 126 Q F2(Telnetd)102 144 Q
+F0(has support for enabling remotely the follo)2.5 E(wing)-.25 E F1(TELNET)2.5
+E F0(options:)2.5 E(DO BIN)102 162 Q(AR)-.35 E 52.73(YS)-.65 G
+(ent to indicate that)214.56 162 Q F1(telnetd)2.5 E F0(is willing to recei)2.5
+E .3 -.15(ve a)-.25 H 2.5(n8b).15 G(it data stream.)423.918 162 Q(DO LFLO)102
+180 Q 55.97(WR)-.35 G(equests that the client handle \215o)215.67 180 Q 2.5(wc)
+-.25 G(ontrol characters remotely)358.18 180 Q(.)-.65 E .967(DO ECHO)102 198 R
+.967(This is not really supported, b)209.967 198 R .967
+(ut is sent to identify a 4.2BSD)-.2 F/F3 10/Courier@0 SF(telnet)3.468 E F0
+.968(\(1\) client,)B .365(which will improperly respond with)209 210 R F3 .365
+(WILL ECHO.)2.865 F F0 .365(If a)2.865 F F3 .365(WILL ECHO)2.865 F F0 .365
+(is recei)2.865 F -.15(ve)-.25 G(d,).15 E(a)209 222 Q F3(DONT ECHO)2.5 E F0
+(will be sent in response.)2.5 E .445(DO TERMIN)102 240 R 7.92
+(AL-TYPE Indicates)-.35 F 2.945(ad)2.945 G .445
+(esire to be able to request the name of the type of terminal that is at-)
+260.875 240 R(tached to the client side of the connection.)209 252 Q(DO SGA)102
+270 Q(Indicates that it does not need to recei)209 270 Q -.15(ve)-.25 G F3
+(IAC GA,)2.65 E F0(the go ahead command.)2.5 E .006(DO N)102 288 R -.9(AW)-.35
+G 61.87(SR).9 G .006(equests that the client inform the serv)215.676 288 R .005
+(er when the windo)-.15 F 2.505(w\()-.25 G .005(display\) size changes.)452.51
+288 R(DO TERMIN)102 306 Q(AL-SPEED)-.35 E 1.029(Indicates a desire to be able \
+to request information about the speed of the serial)209 318 R
+(line to which the client is attached.)209 330 Q .469(DO XDISPLOC)102 348 R
+.469(Indicates a desire to be able to request the name of the X windo)209.469
+348 R .468(ws display that is)-.25 F(associated with the telnet client.)209 360
+Q 1.008(DO NEW)102 378 R(-ENVIR)-.65 E 17.52(ON Indicates)-.4 F 3.508(ad)3.508
+G 1.008(esire to be able to request en)262.564 378 R 1.009(vironment v)-.4 F
+1.009(ariable information, as de-)-.25 F(scribed in RFC 1572.)209 390 Q 1.009
+(DO ENVIR)102 408 R 42.97(ON Indicates)-.4 F 3.509(ad)3.509 G 1.009
+(esire to be able to request en)262.567 408 R 1.008(vironment v)-.4 F 1.008
+(ariable information, as de-)-.25 F(scribed in RFC 1408.)209 420 Q .886
+(DO LINEMODE)102 438 R .886(Only sent if)209.886 438 R F2(telnetd)3.386 E F0
+.886(is compiled with support for linemode, and requests that)3.386 F
+(the client do line by line processing.)209 450 Q 1.292(DO TIMING-MARK)102 468
+R 1.292(Only sent if)210.292 468 R F2(telnetd)3.792 E F0 1.291
+(is compiled with support for both linemode and kludge)3.792 F 2.029
+(linemode, and the client responded with)209 480 R F3 2.029(WONT LINEMODE.)
+4.529 F F0 2.029(If the client re-)4.529 F 3.375(sponds with)209 492 R F3 3.375
+(WILL TM,)5.875 F F0 3.375(the it is assumed that the client supports kludge)
+5.875 F 2.5(linemode. Note)209 504 R(that the)2.5 E([)3.333 E F2<ad6b>2.499 E
+F0 2.5(]o).833 G(ption can be used to disable this.)338.205 504 Q(DO A)102 522
+Q(UTHENTICA)-.55 E(TION)-1.11 E .618(Only sent if)209 534 R F2(telnetd)3.118 E
+F0 .618(is compiled with support for authentication, and indicates)3.118 F 2.5
+(aw)209 546 S(illingness to recei)223.16 546 Q .3 -.15(ve a)-.25 H
+(uthentication information for automatic login.).15 E .118(DO ENCR)102 564 R
+42.65(YPT Only)-.65 F .118(sent if)2.618 F F2(telnetd)2.618 E F0 .118
+(is compiled with support for data encryption, and indicates)2.618 F 2.5(aw)209
+576 S(illingness to decrypt the data stream.)223.16 576 Q/F4 10/Times-Bold@0 SF
+(ENVIR)72 600 Q(ONMENT)-.3 E(FILES)72 612 Q F3(/etc/services)102 624 Q
+(/etc/inittab)102 636 Q F0(\(UNICOS systems only\))2.5 E F3(/etc/iptos)102 648
+Q F0(\(if supported\))2.5 E F3(/usr/ucb/bftp)102 660 Q F0(\(if supported\))2.5
+E(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71
+(ution February)-.2 F(3, 1994)2.5 E(4)535 750 Q EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.834(TELNETD \( 8 \))72 48 R(BSD System Manager')
+241.42 48 Q 2.5(sM)-.55 G 105.272(anual TELNETD)348.92 48 R 1.666(\(8\))1.666 G
+/F1 10/Times-Bold@0 SF(SEE ALSO)72 96 Q/F2 10/Courier@0 SF(telnet)102 108 Q F0
+(\(1\),)A F2(login)5 E F0(\(1\),)A F2(bftp)5 E F0(\(1\) \(if supported\))A F1
+(ST)72 132 Q(AND)-.9 E(ARDS)-.35 E/F3 10/Courier-Bold@0 SF(RFC-854)102 144 Q/F4
+9/Times-Roman@0 SF(TELNET)155 144 Q F0(PR)2.5 E -1.88 -.4(OT O)-.4 H
+(COL SPECIFICA).4 E(TION)-1.11 E F3(RFC-855)102 156 Q F0
+(TELNET OPTION SPECIFICA)155 156 Q(TIONS)-1.11 E F3(RFC-856)102 168 Q F0
+(TELNET BIN)155 168 Q(AR)-.35 E 2.5(YT)-.65 G(RANSMISSION)241.21 168 Q F3
+(RFC-857)102 180 Q F0(TELNET ECHO OPTION)155 180 Q F3(RFC-858)102 192 Q F0
+(TELNET SUPPRESS GO AHEAD OPTION)155 192 Q F3(RFC-859)102 204 Q F0(TELNET ST)
+155 204 Q -1.11(AT)-.93 G(US OPTION)1.11 E F3(RFC-860)102 216 Q F0
+(TELNET TIMING MARK OPTION)155 216 Q F3(RFC-861)102 228 Q F0
+(TELNET EXTENDED OPTIONS - LIST OPTION)155 228 Q F3(RFC-885)102 240 Q F0
+(TELNET END OF RECORD OPTION)155 240 Q F3(RFC-1073)102 252 Q F0 -.7(Te)5 G
+(lnet W).7 E(indo)-.4 E 2.5(wS)-.25 G(ize Option)224.2 252 Q F3(RFC-1079)102
+264 Q F0 -.7(Te)5 G(lnet T).7 E(erminal Speed Option)-.7 E F3(RFC-1091)102 276
+Q F0 -.7(Te)5 G(lnet T).7 E(erminal-T)-.7 E(ype Option)-.8 E F3(RFC-1096)102
+288 Q F0 -.7(Te)5 G(lnet X Display Location Option).7 E F3(RFC-1123)102 300 Q
+F0(Requirements for Internet Hosts -- Application and Support)5 E F3(RFC-1184)
+102 312 Q F0 -.7(Te)5 G(lnet Linemode Option).7 E F3(RFC-1372)102 324 Q F0 -.7
+(Te)5 G(lnet Remote Flo).7 E 2.5(wC)-.25 G(ontrol Option)245.44 324 Q F3
+(RFC-1416)102 336 Q F0 -.7(Te)5 G(lnet Authentication Option).7 E F3(RFC-1411)
+102 348 Q F0 -.7(Te)5 G(lnet Authentication: K).7 E(erberos V)-.25 E(ersion 4)
+-1.11 E F3(RFC-1412)102 360 Q F0 -.7(Te)5 G(lnet Authentication: SPX).7 E F3
+(RFC-1571)102 372 Q F0 -.7(Te)5 G(lnet En).7 E
+(vironment Option Interoperability Issues)-.4 E F3(RFC-1572)102 384 Q F0 -.7
+(Te)5 G(lnet En).7 E(vironment Option)-.4 E F1 -.1(BU)72 408 S(GS).1 E F0(Some)
+102 420 Q F4(TELNET)2.5 E F0(commands are only partially implemented.)2.5 E
+.082(Because of b)102 438 R .082(ugs in the original 4.2 BSD)-.2 F F2(telnet)
+2.582 E F0(\(1\),)A F3(telnetd)5.164 E F0 .082
+(performs some dubious protocol e)2.582 F(xchanges)-.15 E(to try to disco)102
+450 Q -.15(ve)-.15 G 2.5(ri).15 G 2.5(ft)175.03 450 S
+(he remote client is, in f)183.64 450 Q(act, a 4.2 BSD)-.1 E F2(telnet)2.5 E F0
+(\(1\).)A(Binary mode has no common interpretation e)102 468 Q
+(xcept between similar operating systems \(Unix in this case\).)-.15 E
+(The terminal type name recei)102 486 Q -.15(ve)-.25 G 2.5(df).15 G
+(rom the remote client is con)239.06 486 Q -.15(ve)-.4 G(rted to lo).15 E
+(wer case.)-.25 E F3(Telnetd)102 504 Q F0(ne)2.5 E -.15(ve)-.25 G 2.5(rs).15 G
+(ends)174.7 504 Q F4(TELNET)2.5 E F2(IAC GA)2.5 E F0(\(go ahead\) commands.)2.5
+E(4.2 Berk)72 750 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 750 Q 95.71
+(ution February)-.2 F(3, 1994)2.5 E(5)535 750 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/appl/telnet/telnetd/telnetd.0.txt b/krb5-1-6/src/appl/telnet/telnetd/telnetd.0.txt
new file mode 100644
index 000000000..f13b6994c
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/telnetd.0.txt
@@ -0,0 +1,322 @@
+TELNETD(8)                BSD System Manager's Manual               TELNETD(8)
+
+NNAAMMEE
+     tteellnneettdd - DARPA TELNET protocol server
+
+SSYYNNOOPPSSIISS
+     //uussrr//lliibbeexxeecc//tteellnneettdd [--aa _a_u_t_h_m_o_d_e] [--BB] [--DD _d_e_b_u_g_m_o_d_e] [--eeddeebbuugg] [--hh]
+                          [--II_i_n_i_t_i_d] [--ll] [--kk] [--nn] [--rr_l_o_w_p_t_y_-_h_i_g_h_p_t_y] [--ss]
+                          [--SS _t_o_s] [--uu _l_e_n] [--UU] [--XX _a_u_t_h_t_y_p_e] [--ddeebbuugg [_p_o_r_t]]
+
+DDEESSCCRRIIPPTTIIOONN
+     The tteellnneettdd command is a server which supports the DARPA standard TELNET
+     virtual terminal protocol.  TTeellnneettdd is normally invoked by the internet
+     server (see inetd(8))  for requests to connect to the TELNET port as in-
+     dicated by the _/_e_t_c_/_s_e_r_v_i_c_e_s file (see services(5)).  The --ddeebbuugg option
+     may be used to start up tteellnneettdd manually, instead of through inetd(8).
+     If started up this way, _p_o_r_t may be specified to run tteellnneettdd on an alter-
+     nate TCP port number.
+
+     The tteellnneettdd command accepts the following options:
+
+     --aa _a_u_t_h_m_o_d_e  This option may be used for specifying what mode should be
+                  used for authentication.  Note that this option is only use-
+                  ful if tteellnneettdd has been compiled with support for the
+                  AUTHENTICATION option.  There are several valid values for
+                  _a_u_t_h_m_o_d_e_:
+
+                  debug  Turns on authentication debugging code.
+
+                  user   Only allow connections when the remote user can pro-
+                         vide valid authentication information to identify the
+                         remote user, and is allowed access to the specified
+                         account without providing a password.
+
+                  valid  Only allow connections when the remote user can pro-
+                         vide valid authentication information to identify the
+                         remote user.  The login(1) command will provide any
+                         additional user verification needed if the remote us-
+                         er is not allowed automatic access to the specified
+                         account.
+
+                  other  Only allow connections that supply some authentica-
+                         tion information.  This option is currently not sup-
+                         ported by any of the existing authentication mecha-
+                         nisms, and is thus the same as specifying --aa vvaalliidd.
+
+                  none   This is the default state.  Authentication informa-
+                         tion is not required.  If no or insufficient authen-
+                         tication information is provided, then the login(1)
+                         program will provide the necessary user verification.
+
+                  off    This disables the authentication code.  All user ver-
+                         ification will happen through the login(1) program.
+
+     --BB           Specifies bftp server mode.  In this mode, tteellnneettdd causes
+                  login to start a bftp(1) session rather than the user's nor-
+                  mal shell.  In bftp daemon mode normal logins are not sup-
+                  ported, and it must be used on a port other than the normal
+                  TELNET port.
+
+     --DD _d_e_b_u_g_m_o_d_e
+                  This option may be used for debugging purposes.  This allows
+                  tteellnneettdd to print out debugging information to the connec-
+                  tion, allowing the user to see what tteellnneettdd is doing.  There
+
+                  are several possible values for _d_e_b_u_g_m_o_d_e_:
+
+                  ooppttiioonnss   Prints information about the negotiation of TELNET
+                            options.
+
+                  rreeppoorrtt    Prints the ooppttiioonnss information, plus some addi-
+                            tional information about what processing is going
+                            on.
+
+                  nneettddaattaa   Displays the data stream received by tteellnneettdd..
+
+                  ppttyyddaattaa   Displays data written to the pty.
+
+                  eexxeerrcciissee  Has not been implemented yet.
+
+     --ddeebbuugg       Enables debugging on each socket created by tteellnneettdd (see
+                  SO_DEBUG in socket(2)).
+
+     --eeddeebbuugg      If tteellnneettdd has been compiled with support for data encryp-
+                  tion, then the --eeddeebbuugg option may be used to enable encryp-
+                  tion debugging code.
+
+     --hh           Disables the printing of host-specific information before
+                  login has been completed.
+
+     --II _i_n_i_t_i_d    This option is only applicable to UNICOS systems prior to
+                  7.0.  It specifies the ID from _/_e_t_c_/_i_n_i_t_t_a_b to use when init
+                  starts login sessions.  The default ID is fe.
+
+     --kk           This option is only useful if tteellnneettdd has been compiled with
+                  both linemode and kludge linemode support.  If the --kk option
+                  is specified, then if the remote client does not support the
+                  LINEMODE option, then tteellnneettdd will operate in character at a
+                  time mode.  It will still support kludge linemode, but will
+                  only go into kludge linemode if the remote client requests
+                  it.  (This is done by by the client sending DONT SUPPRESS-
+                  GO-AHEAD and DONT ECHO.) The --kk option is most useful when
+                  there are remote clients that do not support kludge
+                  linemode, but pass the heuristic (if they respond with WILL
+                  TIMING-MARK in response to a DO TIMING-MARK) for kludge
+                  linemode support.
+
+     --ll           Specifies line mode.  Tries to force clients to use line-
+                  at-a-time mode.  If the LINEMODE option is not supported, it
+                  will go into kludge linemode.
+
+     --nn           Disable TCP keep-alives.  Normally tteellnneettdd enables the TCP
+                  keep-alive mechanism to probe connections that have been
+                  idle for some period of time to determine if the client is
+                  still there, so that idle connections from machines that
+                  have crashed or can no longer be reached may be cleaned up.
+
+     --rr _l_o_w_p_t_y_-_h_i_g_h_p_t_y
+                  This option is only enabled when tteellnneettdd is compiled for
+                  UNICOS. It specifies an inclusive range of pseudo-terminal
+                  devices to use.  If the system has sysconf variable
+                  _SC_CRAY_NPTY configured, the default pty search range is 0
+                  to _SC_CRAY_NPTY; otherwise, the default range is 0 to 128.
+                  Either _l_o_w_p_t_y or _h_i_g_h_p_t_y may be omitted to allow changing
+                  either end of the search range.  If _l_o_w_p_t_y is omitted, the -
+                  character is still required so that tteellnneettdd can differenti-
+                  ate _h_i_g_h_p_t_y from _l_o_w_p_t_y.
+
+     --ss           This option is only enabled if tteellnneettdd is compiled with sup-
+                  port for SecurID cards.  It causes the --ss option to be
+                  passed on to login(1),  and thus is only useful if login(1)
+                  supports the --ss flag to indicate that only SecurID validated
+                  logins are allowed, and is usually useful for controlling
+                  remote logins from outside of a firewall.
+
+     --SS _t_o_s
+
+     --uu _l_e_n       This option is used to specify the size of the field in the
+                  utmp structure that holds the remote host name.  If the re-
+                  solved host name is longer than _l_e_n, the dotted decimal val-
+                  ue will be used instead.  This allows hosts with very long
+                  host names that overflow this field to still be uniquely
+                  identified.  Specifying --uu00 indicates that only dotted deci-
+                  mal addresses should be put into the _u_t_m_p file.
+
+     --UU           This option causes tteellnneettdd to refuse connections from ad-
+                  dresses that cannot be mapped back into a symbolic name via
+                  the gethostbyaddr(3) routine.
+
+     --XX _a_u_t_h_t_y_p_e  This option is only valid if tteellnneettdd has been built with
+                  support for the authentication option.  It disables the use
+                  of _a_u_t_h_t_y_p_e authentication, and can be used to temporarily
+                  disable a specific authentication type without having to re-
+                  compile tteellnneettdd.
+
+     TTeellnneettdd operates by allocating a pseudo-terminal device (see pty(4))  for
+     a client, then creating a login process which has the slave side of the
+     pseudo-terminal as stdin, stdout and stderr. TTeellnneettdd manipulates the mas-
+     ter side of the pseudo-terminal, implementing the TELNET protocol and
+     passing characters between the remote client and the login process.
+
+     When a TELNET session is started up, tteellnneettdd sends TELNET options to the
+     client side indicating a willingness to do the following TELNET options,
+     which are described in more detail below:
+
+           DO AUTHENTICATION
+           WILL ENCRYPT
+           DO TERMINAL TYPE
+           DO TSPEED
+           DO XDISPLOC
+           DO NEW-ENVIRON
+           DO ENVIRON
+           WILL SUPPRESS GO AHEAD
+           DO ECHO
+           DO LINEMODE
+           DO NAWS
+           WILL STATUS
+           DO LFLOW
+           DO TIMING-MARK
+
+     The pseudo-terminal allocated to the client is configured to operate in
+     cooked mode, and with XTABS and CRMOD enabled (see tty(4)).
+
+     TTeellnneettdd has support for enabling locally the following TELNET options:
+
+     WILL ECHO          When the LINEMODE option is enabled, a WILL ECHO or
+                        WONT ECHO will be sent to the client to indicate the
+                        current state of terminal echoing.  When terminal echo
+                        is not desired, a WILL ECHO is sent to indicate that
+                        telnetd will take care of echoing any data that needs
+                        to be echoed to the terminal, and then nothing is
+                        echoed.  When terminal echo is desired, a WONT ECHO is
+                        sent to indicate that telnetd will not be doing any
+                        terminal echoing, so the client should do any terminal
+                        echoing that is needed.
+
+     WILL BINARY        Indicates that the client is willing to send a 8 bits
+                        of data, rather than the normal 7 bits of the Network
+                        Virtual Terminal.
+
+     WILL SGA           Indicates that it will not be sending IAC GA, go
+                        ahead, commands.
+
+     WILL STATUS        Indicates a willingness to send the client, upon re-
+                        quest, of the current status of all TELNET options.
+
+     WILL TIMING-MARK   Whenever a DO TIMING-MARK command is received, it is
+                        always responded to with a WILL TIMING-MARK
+
+     WILL LOGOUT        When a DO LOGOUT is received, a WILL LOGOUT is sent in
+                        response, and the TELNET session is shut down.
+
+     WILL ENCRYPT       Only sent if tteellnneettdd is compiled with support for data
+                        encryption, and indicates a willingness to decrypt the
+                        data stream.
+
+     TTeellnneettdd has support for enabling remotely the following TELNET options:
+
+     DO BINARY          Sent to indicate that telnetd is willing to receive an
+                        8 bit data stream.
+
+     DO LFLOW           Requests that the client handle flow control charac-
+                        ters remotely.
+
+     DO ECHO            This is not really supported, but is sent to identify
+                        a 4.2BSD telnet(1) client, which will improperly re-
+                        spond with WILL ECHO. If a WILL ECHO is received, a
+                        DONT ECHO will be sent in response.
+
+     DO TERMINAL-TYPE   Indicates a desire to be able to request the name of
+                        the type of terminal that is attached to the client
+                        side of the connection.
+
+     DO SGA             Indicates that it does not need to receive IAC GA, the
+                        go ahead command.
+
+     DO NAWS            Requests that the client inform the server when the
+                        window (display) size changes.
+
+     DO TERMINAL-SPEED  Indicates a desire to be able to request information
+                        about the speed of the serial line to which the client
+                        is attached.
+
+     DO XDISPLOC        Indicates a desire to be able to request the name of
+                        the X windows display that is associated with the tel-
+                        net client.
+
+     DO NEW-ENVIRON     Indicates a desire to be able to request environment
+                        variable information, as described in RFC 1572.
+
+     DO ENVIRON         Indicates a desire to be able to request environment
+                        variable information, as described in RFC 1408.
+
+     DO LINEMODE        Only sent if tteellnneettdd is compiled with support for
+                        linemode, and requests that the client do line by line
+                        processing.
+
+     DO TIMING-MARK     Only sent if tteellnneettdd is compiled with support for both
+                        linemode and kludge linemode, and the client responded
+                        with WONT LINEMODE. If the client responds with WILL
+                        TM, the it is assumed that the client supports kludge
+                        linemode.  Note that the [--kk] option can be used to
+
+                        disable this.
+
+     DO AUTHENTICATION  Only sent if tteellnneettdd is compiled with support for au-
+                        thentication, and indicates a willingness to receive
+                        authentication information for automatic login.
+
+     DO ENCRYPT         Only sent if tteellnneettdd is compiled with support for data
+                        encryption, and indicates a willingness to decrypt the
+                        data stream.
+
+EENNVVIIRROONNMMEENNTT
+FFIILLEESS
+     _/_e_t_c_/_s_e_r_v_i_c_e_s
+     _/_e_t_c_/_i_n_i_t_t_a_b (UNICOS systems only)
+     _/_e_t_c_/_i_p_t_o_s (if supported)
+     _/_u_s_r_/_u_c_b_/_b_f_t_p (if supported)
+
+SSEEEE AALLSSOO
+     telnet(1),  login(1),  bftp(1) (if supported)
+
+SSTTAANNDDAARRDDSS
+     RRFFCC--885544   TELNET PROTOCOL SPECIFICATION
+     RRFFCC--885555   TELNET OPTION SPECIFICATIONS
+     RRFFCC--885566   TELNET BINARY TRANSMISSION
+     RRFFCC--885577   TELNET ECHO OPTION
+     RRFFCC--885588   TELNET SUPPRESS GO AHEAD OPTION
+     RRFFCC--885599   TELNET STATUS OPTION
+     RRFFCC--886600   TELNET TIMING MARK OPTION
+     RRFFCC--886611   TELNET EXTENDED OPTIONS - LIST OPTION
+     RRFFCC--888855   TELNET END OF RECORD OPTION
+     RRFFCC--11007733  Telnet Window Size Option
+     RRFFCC--11007799  Telnet Terminal Speed Option
+     RRFFCC--11009911  Telnet Terminal-Type Option
+     RRFFCC--11009966  Telnet X Display Location Option
+     RRFFCC--11112233  Requirements for Internet Hosts -- Application and Support
+     RRFFCC--11118844  Telnet Linemode Option
+     RRFFCC--11337722  Telnet Remote Flow Control Option
+     RRFFCC--11441166  Telnet Authentication Option
+     RRFFCC--11441111  Telnet Authentication: Kerberos Version 4
+     RRFFCC--11441122  Telnet Authentication: SPX
+     RRFFCC--11557711  Telnet Environment Option Interoperability Issues
+     RRFFCC--11557722  Telnet Environment Option
+
+BBUUGGSS
+     Some TELNET commands are only partially implemented.
+
+     Because of bugs in the original 4.2 BSD telnet(1),  tteellnneettdd performs some
+     dubious protocol exchanges to try to discover if the remote client is, in
+     fact, a 4.2 BSD telnet(1).
+
+     Binary mode has no common interpretation except between similar operating
+     systems (Unix in this case).
+
+     The terminal type name received from the remote client is converted to
+     lower case.
+
+     TTeellnneettdd never sends TELNET IAC GA (go ahead) commands.
+
+4.2 Berkeley Distribution      February 3, 1994                              5
diff --git a/krb5-1-6/src/appl/telnet/telnetd/telnetd.8 b/krb5-1-6/src/appl/telnet/telnetd/telnetd.8
new file mode 100644
index 000000000..78700cbed
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/telnetd.8
@@ -0,0 +1,631 @@
+.\" Copyright (c) 1983, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)telnetd.8	8.2 (Berkeley) 2/3/94
+.\" "
+.TH TELNETD 8
+.SH NAME
+telnetd \-
+.SM DARPA TELNET
+protocol server
+.SH SYNOPSIS
+.B /usr/libexec/telnetd
+[\fB\-a\fP \fIauthmode\fP] [\fB\-B\fP] [\fB\-D\fP] [\fIdebugmode\fP]
+[\fB\-e\fP] [\fB\-h\fP] [\fB\-I\fP\fIinitid\fP] [\fB\-l\fP]
+[\fB\-k\fP] [\fB\-n\fP] [\fB\-r\fP\fIlowpty-highpty\fP] [\fB\-s\fP]
+[\fB\-S\fP \fItos\fP] [\fB\-U\fP] [\fB\-X\fP \fIauthtype\fP]
+[\fB\-w\fP [\fBip\fP|\fImaxhostlen\fP[\fB,\fP[\fBno\fP]\fBstriplocal\fP]]]
+[\fB\-debug\fP [\fIport\fP]]
+.SH DESCRIPTION
+The
+.B telnetd
+command is a server which supports the
+.SM DARPA
+standard
+.SM TELNET
+virtual terminal protocol.
+.B Telnetd
+is normally invoked by the internet server (see
+.BR inetd (8)
+for requests to connect to the
+.SM TELNET
+port as indicated by the
+.I /etc/services
+file (see
+.BR services (5)).
+The
+.B \-debug
+option may be used to start up
+.B telnetd
+manually, instead of through
+.IR inetd (8).
+If started up this way, 
+.I port
+may be specified to run
+.B telnetd
+on an alternate
+.SM TCP
+port number.
+.PP
+The
+.B telnetd
+command accepts the following options:
+.TP
+\fB\-a\fP \fIauthmode\fP
+This option may be used for specifying what mode should be used for
+authentication.  Note that this option is only useful if
+.B telnetd
+has been compiled with support for the
+.SM AUTHENTICATION
+option.  There are several valid values for
+.IR authmode :
+.RS
+.TP
+.B debug
+Turns on authentication debugging code.
+.TP
+.B valid
+Only allow connections when the remote user can provide valid
+authentication information to identify the remote user, and is allowed
+access to the specified account without providing a password.
+.TP
+.B user
+Only allow connections when the remote user can provide valid
+authentication information to identify the remote user.  The
+.IR login (1)
+command will provide any additional user verification needed if the
+remote user is not allowed automatic access to the specified account.
+.TP
+.B other
+Only allow connections that supply some authentication information.
+This option is currently not supported by any of the existing
+authentication mechanisms, and is thus the same as specifying
+.B \-a
+.BR valid .
+.TP
+.B none
+This is the default state.  Authentication information is not required.
+If no or insufficient authentication information is provided, then the
+.IR login (1)
+program will provide the necessary user verification.
+.TP
+.B off
+This disables the authentication code.  All user verification will
+happen through the
+.IR login (1)
+program.
+.RE
+.TP
+.B \-B
+Specifies bftp server mode.  In this mode,
+.B telnetd
+causes login to start a
+.IR bftp (1)
+session rather than the user's normal shell.  In bftp daemon mode,
+normal logins are not supported, and it must be used on a port other
+than the normal
+.SM TELNET
+port.
+.TP
+\fB\-D\fP \fIdebugmode\fP
+This option may be used for debugging purposes.  This allows
+.B telnetd
+to print out debugging information to the connection, allowing the user
+to see what
+.B telnetd
+is doing.  There are several possible values for
+.IR debugmode :
+.RS
+.TP
+.B options
+Prints information about the negotiation of
+.SM TELNET
+options.
+.TP
+.B report
+Prints the
+.B options
+information, plus some additional information about what processing is
+going on.
+.TP
+.B netdata
+Displays the data stream received by
+.B telnetd.
+.TP
+.B ptydata
+Displays data written to the pty.
+.TP
+.B encrypt
+Enables	encryption debugging code.
+.TP
+.B exercise
+Has not been implemented yet.
+.RE
+.TP
+.B \-debug
+Enables debugging on each socket created by
+.B telnetd
+(see
+.SM SO_DEBUG
+in
+.IR socket (2)).
+.TP
+.B \-e
+This option causes
+.B telnetd
+to refuse unencrypted connections.
+.TP
+.B \-h
+Disables the printing of host-specific information before login has been
+completed.
+.TP
+\fB\-I\fP \fIinitid\fP
+This option is only applicable to
+.SM UNICOS
+systems prior to 7.0.  It specifies the
+.SM ID
+from
+.I /etc/inittab
+to use when init starts login sessions.  The default
+.SM ID
+is fe.
+.TP
+.B \-k
+This option is only useful if
+.B telnetd
+has been compiled with both linemode and kludge linemode support.  If
+the
+.B \-k
+option is specified, then if the remote client does not support the
+.SM LINEMODE
+option, then
+.B telnetd
+will operate in character at a time mode.  It will still support kludge
+linemode, but will only go into kludge linemode if the remote client
+requests it.  (This is done by by the client sending
+.SM DONT SUPPRESS-GO-AHEAD
+and
+.SM DONT ECHO.)
+The
+.B \-k
+option is most useful when there are remote clients that do not support
+kludge linemode, but pass the heuristic (if they respond with
+.SM WILL TIMING-MARK
+in response to a
+.SM DO TIMING-MARK)
+for kludge linemode support.
+.TP
+.B \-l
+Specifies line mode.  Tries to force clients to use line-at-a-time
+mode.  If the
+.SM LINEMODE
+option is not supported, it will go into kludge linemode.
+.TP
+.B \-n
+Disable
+.SM TCP
+keep-alives.  Normally
+.B telnetd
+enables the
+.SM TCP
+keep-alive mechanism to probe connections that have been idle for some
+period of time to determine if the client is still there, so that idle
+connections from machines that have crashed or can no longer be reached
+may be cleaned up.
+.TP
+\fB\-r\fP \fIlowpty-highpty\fP
+This option is only enabled when
+.B telnetd
+is compiled for
+.SM UNICOS.
+It specifies an inclusive range of pseudo-terminal devices to use.  If
+the system has sysconf variable
+.SM _SC_CRAY_NPTY
+configured, the default pty search range is 0 to
+.SM _SC_CRAY_NPTY;
+otherwise, the default range is 0 to 128.  Either
+.I lowpty
+or
+.I highpty
+may be omitted to allow changing either end of the search range.  If
+.I lowpty
+is omitted, the - character is still required so that
+.B telnetd
+can differentiate
+.I highpty
+from
+.IR lowpty .
+.TP
+.B \-s
+This option is only enabled if
+.B telnetd
+is compiled with support for SecurID cards.  It causes the
+.B \-s
+option to be passed on to
+.IR login (1),
+and thus is only useful if
+.IR login (1)
+supports the
+.B \-s
+flag to indicate that only SecurID validated logins are allowed, and is
+usually useful for controlling remote logins from outside of a firewall.
+.TP
+\fB\-S\fP \fItos\fP
+.TP
+.B \-U
+This option causes
+.B telnetd
+to refuse connections from addresses that cannot be mapped back into a
+symbolic name via the
+.IR gethostbyaddr (3)
+routine.
+.TP
+.B \-w \fP[\fBip\fP|\fImaxhostlen\fP[\fB,\fP[\fBno\fP]\fBstriplocal\fP]]
+Controls the form of the remote hostname passed to login(1).
+Specifying \fBip\fP results in the numeric IP address always being
+passed to login(1).  Specifying a number, \fImaxhostlen\fP, sets the
+maximum length of the hostname passed to login(1) before it will be
+passed as a numeric IP address.  If \fImaxhostlen\fP is 0, then the
+system default, as determined by the utmp or utmpx structures, is
+used.  The \fBnostriplocal\fP and \fBstriplocal\fP options, which must
+be preceded by a comma, control whether or not the local host domain
+is stripped from the remote hostname.  By default, the equivalent of
+\fBstriplocal\fP is in effect.
+.TP
+\fB\-X\fP \fIauthtype\fP
+This option is only valid if
+.B telnetd
+has been built with support for the authentication option.  It disables
+the use of
+.I authtype
+authentication, and can be used to temporarily disable a specific
+authentication type without having to recompile
+.BR telnetd .
+.PP
+.B Telnetd
+operates by allocating a pseudo-terminal device (see
+.IR pty (4))
+for a client, then creating a login process which has the slave side of
+the pseudo-terminal as
+.IR stdin ,
+.I stdout
+and
+.IR stderr .
+.B Telnetd
+manipulates the master side of the pseudo-terminal, implementing the
+.SM TELNET
+protocol and passing characters between the remote client and the login
+process.
+.PP
+When a
+.SM TELNET
+session is started up, 
+.B telnetd
+sends
+.SM TELNET
+options to the client side indicating a willingness to do the following
+.SM TELNET
+options, which are described in more detail below:
+.sp
+.nf
+.in +0.5i
+DO AUTHENTICATION
+WILL ENCRYPT
+DO TERMINAL TYPE
+DO TSPEED
+DO XDISPLOC
+DO NEW-ENVIRON
+DO ENVIRON
+WILL SUPPRESS GO AHEAD
+DO ECHO
+DO LINEMODE
+DO NAWS
+WILL STATUS
+DO LFLOW
+DO TIMING-MARK
+.in 
+.fi
+.PP
+The pseudo-terminal allocated to the client is configured
+to operate in \*(lqcooked\*(rq mode, and with
+.SM XTABS
+and
+.SM CRMOD
+enabled (see
+.IR tty (4)).
+.PP
+.B Telnetd
+has support for enabling locally the following
+.SM TELNET
+options:
+.TP "\w'.SM WILL TIMING-MARK\ 'u"
+.SM WILL ECHO
+When the
+.SM LINEMODE
+option is enabled, a
+.SM WILL ECHO
+or
+.SM WONT ECHO
+will be sent to the client to indicate the current state of terminal
+echoing.  When terminal echo is not desired, a
+.SM WILL ECHO
+is sent to indicate that
+.B telnetd
+will take care of echoing any data that needs to be echoed to the
+terminal, and then nothing is echoed.  When terminal echo is desired, a
+.SM WONT ECHO
+is sent to indicate that
+.B telnetd
+will not be doing any terminal echoing, so the
+client should do any terminal echoing that is needed.
+.TP
+.SM WILL BINARY
+Indicates that the client is willing to send a 8 bits of data, rather
+than the normal 7 bits of the Network Virtual Terminal.
+.TP
+.SM WILL SGA
+Indicates that it will not be sending
+.SM IAC GA,
+go ahead, commands.
+.TP
+.SM WILL STATUS 
+Indicates a willingness to send the client, upon request, of the current
+status of all
+.SM TELNET
+options.
+.TP
+.SM WILL TIMING-MARK
+Whenever a
+.SM DO TIMING-MARK
+command is received, it is always responded to with a
+.SM WILL TIMING-MARK
+.TP
+.SM WILL LOGOUT
+When a
+.SM DO LOGOUT
+is received, a
+.SM WILL LOGOUT
+is sent in response, and the
+.SM TELNET
+session is shut down.
+.TP
+.SM WILL ENCRYPT
+Only sent if
+.B telnetd
+is compiled with support for data encryption, and indicates a
+willingness to decrypt the data stream.
+.PP
+.B Telnetd
+has support for enabling remotely the following
+.SM TELNET
+options:
+.TP "\w'.SM DO TERMINAL-SPEED\ 'u"
+.SM DO BINARY
+Sent to indicate that
+.B telnetd
+is willing to receive an 8 bit data stream.
+.TP
+.SM DO LFLOW
+Requests that the client handle flow control characters remotely.
+.TP
+.SM DO ECHO
+This is not really supported, but is sent to identify a 4.2BSD
+.IR telnet (1)
+client, which will improperly respond with
+.SM WILL ECHO.
+If a
+.SM WILL ECHO
+is received, a
+.SM DONT ECHO
+will be sent in response.
+.TP
+.SM DO TERMINAL-TYPE
+Indicates a desire to be able to request the name of the type of
+terminal that is attached to the client side of the connection.
+.TP
+.SM DO SGA
+Indicates that it does not need to receive
+.SM IAC GA,
+the go ahead command.
+.TP
+.SM DO NAWS
+Requests that the client inform the server when the window (display)
+size changes.
+.TP
+.SM DO TERMINAL-SPEED
+Indicates a desire to be able to request information about the speed of
+the serial line to which the client is attached.
+.TP
+.SM DO XDISPLOC
+Indicates a desire to be able to request the name of the X windows
+display that is associated with the telnet client.
+.TP
+.SM DO NEW-ENVIRON
+Indicates a desire to be able to request environment variable
+information, as described in RFC 1572.
+.TP
+.SM DO ENVIRON
+Indicates a desire to be able to request environment variable
+information, as described in RFC 1408.
+.TP
+.SM DO LINEMODE
+Only sent if
+.B telnetd
+is compiled with support for linemode, and requests that the client do
+line by line processing.
+.TP
+.SM DO TIMING-MARK
+Only sent if
+.B telnetd
+is compiled with support for both linemode and kludge linemode, and the
+client responded with
+.SM WONT LINEMODE.
+If the client responds with
+.SM WILL TM,
+the it is assumed that the client supports kludge linemode.  Note that
+the
+.B \-k
+option can be used to disable this.
+.TP
+.SM DO AUTHENTICATION
+Only sent if
+.B telnetd
+is compiled with support for authentication, and indicates a willingness
+to receive authentication information for automatic login.
+.TP
+.SM DO ENCRYPT
+Only sent if
+.B telnetd
+is compiled with support for data encryption, and indicates a
+willingness to decrypt the data stream.
+.SH FILES
+.I /etc/services
+.br
+.I /etc/inittab
+(UNICOS systems only)
+.br
+.I /etc/iptos
+(if supported)
+.br
+.I /usr/ucb/bftp
+(if supported)
+.SH "SEE ALSO"
+.IR telnet (1),
+.IR login (1),
+.IR bftp (1)
+(if supported)
+.SH STANDARDS
+.TP "\w'.B RFC-2000\ 'u"
+.B RFC-854
+TELNET PROTOCOL SPECIFICATION
+.sp -1
+.TP
+.B RFC-855
+TELNET OPTION SPECIFICATIONS
+.sp -1
+.TP
+.B RFC-856
+TELNET BINARY TRANSMISSION
+.sp -1
+.TP
+.B RFC-857
+TELNET ECHO OPTION
+.sp -1
+.TP
+.B RFC-858
+TELNET SUPPRESS GO AHEAD OPTION
+.sp -1
+.TP
+.B RFC-859
+TELNET STATUS OPTION
+.sp -1
+.TP
+.B RFC-860
+TELNET TIMING MARK OPTION
+.sp -1
+.TP
+.B RFC-861
+TELNET EXTENDED OPTIONS - LIST OPTION
+.sp -1
+.TP
+.B RFC-885
+TELNET END OF RECORD OPTION
+.sp -1
+.TP
+.B RFC-1073
+Telnet Window Size Option
+.sp -1
+.TP
+.B RFC-1079
+Telnet Terminal Speed Option
+.sp -1
+.TP
+.B RFC-1091
+Telnet Terminal-Type Option
+.sp -1
+.TP
+.B RFC-1096
+Telnet X Display Location Option
+.sp -1
+.TP
+.B RFC-1123
+Requirements for Internet Hosts -- Application and Support
+.sp -1
+.TP
+.B RFC-1184
+Telnet Linemode Option
+.sp -1
+.TP
+.B RFC-1372
+Telnet Remote Flow Control Option
+.sp -1
+.TP
+.B RFC-1416
+Telnet Authentication Option
+.sp -1
+.TP
+.B RFC-1411
+Telnet Authentication: Kerberos Version 4
+.sp -1
+.TP
+.B RFC-1412
+Telnet Authentication: SPX
+.sp -1
+.TP
+.B RFC-1571
+Telnet Environment Option Interoperability Issues
+.sp -1
+.TP
+.B RFC-1572
+Telnet Environment Option
+.SH BUGS
+Some
+.SM TELNET
+commands are only partially implemented.
+.PP
+Because of bugs in the original 4.2 BSD
+.IR telnet (1),
+.B telnetd
+performs some dubious protocol exchanges to try to discover if the
+remote client is, in fact, a 4.2 BSD
+.IR telnet (1).
+.PP
+Binary mode has no common interpretation except between similar
+operating systems (Unix in this case).
+.PP
+The terminal type name received from the remote client is converted to
+lower case.
+.PP
+.B Telnetd
+never sends
+.SM TELNET
+.SM IAC GA
+(go ahead) commands.
diff --git a/krb5-1-6/src/appl/telnet/telnetd/telnetd.c b/krb5-1-6/src/appl/telnet/telnetd/telnetd.c
new file mode 100644
index 000000000..725075d37
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/telnetd.c
@@ -0,0 +1,1712 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+/* based on @(#)telnetd.c	8.1 (Berkeley) 6/4/93 */
+
+#include "telnetd.h"
+#include "pathnames.h"
+
+extern int getent(char *, char *);
+extern int tgetent(char *, char *);
+
+#if	defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY)
+/*
+ * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can
+ * use it to tell us to turn off all the socket security code,
+ * since that is only used in UNICOS 7.0 and later.
+ */
+# undef _SC_CRAY_SECURE_SYS
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libpty.h>
+#include <com_err.h>
+#if	defined(_SC_CRAY_SECURE_SYS)
+#include <sys/sysv.h>
+#include <sys/secdev.h>
+# ifdef SO_SEC_MULTI		/* 8.0 code */
+#include <sys/secparm.h>
+#include <sys/usrv.h>
+# endif /* SO_SEC_MULTI */
+int	secflag;
+char	tty_dev[16];
+struct	secdev dv;
+struct	sysv sysv;
+# ifdef SO_SEC_MULTI		/* 8.0 code */
+struct	socksec ss;
+# else /* SO_SEC_MULTI */	/* 7.0 code */
+struct	socket_security ss;
+# endif /* SO_SEC_MULTI */
+#endif	/* _SC_CRAY_SECURE_SYS */
+
+#include "fake-addrinfo.h"
+
+#ifdef KRB5
+#include "krb5.h"
+#endif
+
+#if	defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+#include <libtelnet/auth-proto.h>
+#endif
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#include <libtelnet/enc-proto.h>
+#endif
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+#include <libtelnet/misc-proto.h>
+#endif
+
+int	registerd_host_only = 0;
+
+#ifdef	STREAMSPTY
+#include <sys/stream.h>
+# include <stropts.h>
+# include <termio.h>
+/* make sure we don't get the bsd version */
+#ifdef HAVE_SYS_TTY_H
+# include "/usr/include/sys/tty.h"
+#endif
+#ifdef  HAVE_SYS_PTYVAR_H
+# include <sys/ptyvar.h>
+#endif
+
+/*
+ * Because of the way ptyibuf is used with streams messages, we need
+ * ptyibuf+1 to be on a full-word boundary.  The following wierdness
+ * is simply to make that happen.
+ */
+long	ptyibufbuf[BUFSIZ/sizeof(long)+1];
+char	*ptyibuf = ((char *)&ptyibufbuf[1])-1;
+char	*ptyip = ((char *)&ptyibufbuf[1])-1;
+char	ptyibuf2[BUFSIZ];
+unsigned char ctlbuf[BUFSIZ];
+struct	strbuf strbufc, strbufd;
+
+int readstream();
+
+#else	/* ! STREAMPTY */
+
+/*
+ * I/O data buffers,
+ * pointers, and counters.
+ */
+char	ptyibuf[BUFSIZ], *ptyip = ptyibuf;
+char	ptyibuf2[BUFSIZ];
+
+#endif /* ! STREAMPTY */
+
+static void doit (struct sockaddr *);
+int terminaltypeok (char *);
+static void _gettermname(void);
+
+int	hostinfo = 1;			/* do we print login banner? */
+
+#ifdef	CRAY
+extern int      newmap; /* nonzero if \n maps to ^M^J */
+int	lowpty = 0, highpty;	/* low, high pty numbers */
+#endif /* CRAY */
+
+int debug = 0;
+int keepalive = 1;
+char *progname;
+
+int maxhostlen = 0;
+int always_ip = 0;
+int stripdomain = 1;
+
+extern void usage (void);
+
+/*
+ * The string to pass to getopt().  We do it this way so
+ * that only the actual options that we support will be
+ * passed off to getopt().
+ */
+char valid_opts[] = {
+	'd', ':', 'h', 'k', 'L', ':', 'n', 'S', ':', 'U',
+	'w', ':',
+#ifdef	AUTHENTICATION
+	'a', ':', 'X', ':',
+#endif
+#ifdef BFTPDAEMON
+	'B',
+#endif
+#ifdef DIAGNOSTICS
+	'D', ':',
+#endif
+#ifdef	ENCRYPTION
+	'e',
+#endif
+#if	defined(CRAY) && defined(NEWINIT)
+	'I', ':',
+#endif
+#ifdef	LINEMODE
+	'l',
+#endif
+#ifdef CRAY
+	'r', ':',
+#endif
+#ifdef	SecurID
+	's',
+#endif
+#ifdef KRB5
+	'R', ':', 't', ':',
+#endif
+	'\0'
+};
+
+#include <sys/utsname.h>
+static char *
+get_default_IM()
+{
+	struct utsname name;
+	static char banner[1024];
+	
+	if (uname(&name) < 0)
+		sprintf(banner, "\r\nError getting hostname: %s\r\n",
+		    strerror(errno));
+        else {
+#if defined(_AIX)
+		sprintf(banner, "\r\n    %%h (%s release %s.%s) (%%t)\r\n\r\n",
+		    name.sysname, name.version, name.release);
+#else
+		sprintf(banner, "\r\n    %%h (%s release %s %s) (%%t)\r\n\r\n",
+		    name.sysname, name.release, name.version);
+#endif
+	}
+	return banner;
+}
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	struct sockaddr_storage from;
+	int on = 1;
+	socklen_t fromlen;
+	register int ch;
+	extern char *optarg;
+	extern int optind;
+#if	defined(IPPROTO_IP) && defined(IP_TOS)
+	int tos = -1;
+#endif
+
+	pfrontp = pbackp = ptyobuf;
+	netip = netibuf;
+	nfrontp = nbackp = netobuf;
+#ifdef	ENCRYPTION
+	nclearto = 0;
+#endif	/* ENCRYPTION */
+
+	progname = *argv;
+
+#ifdef CRAY
+	/*
+	 * Get number of pty's before trying to process options,
+	 * which may include changing pty range.
+	 */
+	highpty = getnpty();
+#endif /* CRAY */
+
+	while ((ch = getopt(argc, argv, valid_opts)) != -1) {
+		switch(ch) {
+
+#ifdef	AUTHENTICATION
+		case 'a':
+			/*
+			 * Check for required authentication level
+			 */
+			if (strcmp(optarg, "debug") == 0) {
+				extern int auth_debug_mode;
+				auth_debug_mode = 1;
+			} else if (strcasecmp(optarg, "none") == 0) {
+				auth_level = 0;
+			} else if (strcasecmp(optarg, "other") == 0) {
+				auth_level = AUTH_OTHER;
+			} else if (strcasecmp(optarg, "user") == 0) {
+				auth_level = AUTH_USER;
+			} else if (strcasecmp(optarg, "valid") == 0) {
+				auth_level = AUTH_VALID;
+			} else if (strcasecmp(optarg, "off") == 0) {
+				/*
+				 * This hack turns off authentication
+				 */
+				auth_level = -1;
+			} else {
+				fprintf(stderr,
+			    "telnetd: unknown authorization level for -a\n");
+			}
+			break;
+#endif	/* AUTHENTICATION */
+
+#ifdef BFTPDAEMON
+		case 'B':
+			bftpd++;
+			break;
+#endif /* BFTPDAEMON */
+
+		case 'd':
+			if (strcmp(optarg, "ebug") == 0) {
+				debug++;
+				break;
+			}
+			usage();
+			/* NOTREACHED */
+			break;
+
+#ifdef DIAGNOSTICS
+		case 'D':
+			/*
+			 * Check for desired diagnostics capabilities.
+			 */
+			if (!strcmp(optarg, "report")) {
+				diagnostic |= TD_REPORT|TD_OPTIONS;
+			} else if (!strcmp(optarg, "exercise")) {
+				diagnostic |= TD_EXERCISE;
+			} else if (!strcmp(optarg, "netdata")) {
+				diagnostic |= TD_NETDATA;
+			} else if (!strcmp(optarg, "ptydata")) {
+				diagnostic |= TD_PTYDATA;
+			} else if (!strcmp(optarg, "options")) {
+				diagnostic |= TD_OPTIONS;
+			} else if (!strcmp(optarg, "encrypt")) {
+				extern int encrypt_debug_mode;
+				encrypt_debug_mode = 1;
+			} else {
+				usage();
+				/* NOT REACHED */
+			}
+			break;
+#endif /* DIAGNOSTICS */
+
+#ifdef	ENCRYPTION
+		case 'e':
+			must_encrypt = 1;
+			break;
+#endif	/* ENCRYPTION */
+
+		case 'h':
+			hostinfo = 0;
+			break;
+
+#if	defined(CRAY) && defined(NEWINIT)
+		case 'I':
+		    {
+			extern char *gen_id;
+			gen_id = optarg;
+			break;
+		    }
+#endif	/* defined(CRAY) && defined(NEWINIT) */
+
+#ifdef	LINEMODE
+		case 'l':
+			alwayslinemode = 1;
+			break;
+#endif	/* LINEMODE */
+
+		case 'k':
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+			lmodetype = NO_AUTOKLUDGE;
+#else
+			/* ignore -k option if built without kludge linemode */
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+			break;
+
+		case 'L':
+		    {
+		        extern char *login_program;
+
+			login_program = optarg;
+			break;
+		    }
+
+		case 'n':
+			keepalive = 0;
+			break;
+
+#ifdef CRAY
+		case 'r':
+		    {
+			char *strchr();
+			char *c;
+
+			/*
+			 * Allow the specification of alterations
+			 * to the pty search range.  It is legal to
+			 * specify only one, and not change the
+			 * other from its default.
+			 */
+			c = strchr(optarg, '-');
+			if (c) {
+				*c++ = '\0';
+				highpty = atoi(c);
+			}
+			if (*optarg != '\0')
+				lowpty = atoi(optarg);
+			if ((lowpty > highpty) || (lowpty < 0) ||
+							(highpty > 32767)) {
+				usage();
+				/* NOT REACHED */
+			}
+			break;
+		    }
+#endif	/* CRAY */
+
+#ifdef KRB5
+		case 'R':
+		    {
+			extern krb5_context telnet_context;
+			krb5_error_code retval;
+			
+			if (telnet_context == 0) {
+				retval = krb5_init_context(&telnet_context);
+				if (retval) {
+					com_err("telnetd", retval,
+						"while initializing krb5");
+					exit(1);
+				}
+			}
+			krb5_set_default_realm(telnet_context, optarg);
+			break;
+		    }
+#endif	/* KRB5 */
+
+#ifdef	SecurID
+		case 's':
+			/* SecurID required */
+			require_SecurID = 1;
+			break;
+#endif	/* SecurID */
+		case 'S':
+#ifdef	HAVE_GETTOSBYNAME
+			if ((tos = parsetos(optarg, "tcp")) < 0)
+				fprintf(stderr, "%s%s%s\n",
+					"telnetd: Bad TOS argument '", optarg,
+					"'; will try to use default TOS");
+#else
+			fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
+						"-S flag not supported\n");
+#endif
+			break;
+
+#ifdef KRB5
+		case 't':
+		    {
+			extern char *telnet_srvtab;
+
+			telnet_srvtab = optarg;
+			break;
+		    }
+#endif	/* KRB5 */
+
+
+		case 'U':
+			registerd_host_only = 1;
+			break;
+
+#ifdef	AUTHENTICATION
+		case 'X':
+			/*
+			 * Check for invalid authentication types
+			 */
+			auth_disable_name(optarg);
+			break;
+#endif	/* AUTHENTICATION */
+		case 'w':
+			if (!strcmp(optarg, "ip"))
+				always_ip = 1;
+			else {
+				char *cp;
+				cp = strchr(optarg, ',');
+				if (cp == NULL)
+					maxhostlen = atoi(optarg);
+				else if (*(++cp)) {
+					if (!strcmp(cp, "striplocal"))
+						stripdomain = 1;
+					else if (!strcmp(cp, "nostriplocal"))
+						stripdomain = 0;
+					else {
+						usage();
+					}
+					*(--cp) = '\0';
+					maxhostlen = atoi(optarg);
+				}
+			}
+			break;
+		default:
+			fprintf(stderr, "telnetd: %c: unknown option\n", ch);
+			/* FALLTHROUGH */
+		case '?':
+			usage();
+			/* NOTREACHED */
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	/* XXX Convert this to support getaddrinfo, ipv6, etc.  */
+	if (debug) {
+	    int s, ns;
+	    socklen_t foo;
+	    struct servent *sp;
+	    static struct sockaddr_in sin4 = { AF_INET };
+
+	    if (argc > 1) {
+		usage();
+		/* NOT REACHED */
+	    } else if (argc == 1) {
+		    if ((sp = getservbyname(*argv, "tcp"))) {
+			sin4.sin_port = sp->s_port;
+		    } else {
+			sin4.sin_port = atoi(*argv);
+			if ((int)sin4.sin_port <= 0) {
+			    fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
+			    usage();
+			    /* NOT REACHED */
+			}
+			sin4.sin_port = htons((u_short)sin4.sin_port);
+		   }
+	    } else {
+		sp = getservbyname("telnet", "tcp");
+		if (sp == 0) {
+		    fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
+		    exit(1);
+		}
+		sin4.sin_port = sp->s_port;
+	    }
+
+	    s = socket(AF_INET, SOCK_STREAM, 0);
+	    if (s < 0) {
+		    perror("telnetd: socket");;
+		    exit(1);
+	    }
+	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+				(char *)&on, sizeof(on));
+	    if (bind(s, (struct sockaddr *)&sin4, sizeof(sin4)) < 0) {
+		perror("bind");
+		exit(1);
+	    }
+	    if (listen(s, 1) < 0) {
+		perror("listen");
+		exit(1);
+	    }
+	    foo = sizeof(sin4);
+	    ns = accept(s, (struct sockaddr *)&sin4, &foo);
+	    if (ns < 0) {
+		perror("accept");
+		exit(1);
+	    }
+	    (void) dup2(ns, 0);
+	    (void) close(ns);
+	    (void) close(s);
+#ifdef convex
+	} else if (argc == 1) {
+		; /* VOID*/		/* Just ignore the host/port name */
+#endif
+	} else if (argc > 0) {
+		usage();
+		/* NOT REACHED */
+	}
+
+#if	defined(_SC_CRAY_SECURE_SYS)
+	secflag = sysconf(_SC_CRAY_SECURE_SYS);
+
+	/*
+	 *	Get socket's security label
+	 */
+	if (secflag)  {
+		int szss = sizeof(ss);
+#ifdef SO_SEC_MULTI			/* 8.0 code */
+		int sock_multi;
+		int szi = sizeof(int);
+#endif /* SO_SEC_MULTI */
+
+		memset((char *)&dv, 0, sizeof(dv));
+
+		if (getsysv(&sysv, sizeof(struct sysv)) != 0) {
+			perror("getsysv");
+			exit(1);
+		}
+
+		/*
+		 *	Get socket security label and set device values
+		 *	   {security label to be set on ttyp device}
+		 */
+#ifdef SO_SEC_MULTI			/* 8.0 code */
+		if ((getsockopt(0, SOL_SOCKET, SO_SECURITY,
+			       (char *)&ss, &szss) < 0) ||
+		    (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI,
+				(char *)&sock_multi, &szi) < 0)) {
+			perror("getsockopt");
+			exit(1);
+		} else {
+			dv.dv_actlvl = ss.ss_actlabel.lt_level;
+			dv.dv_actcmp = ss.ss_actlabel.lt_compart;
+			if (!sock_multi) {
+				dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl;
+				dv.dv_valcmp = dv.dv_actcmp;
+			} else {
+				dv.dv_minlvl = ss.ss_minlabel.lt_level;
+				dv.dv_maxlvl = ss.ss_maxlabel.lt_level;
+				dv.dv_valcmp = ss.ss_maxlabel.lt_compart;
+			}
+			dv.dv_devflg = 0;
+		}
+#else /* SO_SEC_MULTI */		/* 7.0 code */
+		if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
+				(char *)&ss, &szss) >= 0) {
+			dv.dv_actlvl = ss.ss_slevel;
+			dv.dv_actcmp = ss.ss_compart;
+			dv.dv_minlvl = ss.ss_minlvl;
+			dv.dv_maxlvl = ss.ss_maxlvl;
+			dv.dv_valcmp = ss.ss_maxcmp;
+		}
+#endif /* SO_SEC_MULTI */
+	}
+#endif	/* _SC_CRAY_SECURE_SYS */
+
+	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+	fromlen = sizeof (from);
+	memset(&from, 0, sizeof(from));
+	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+		fprintf(stderr, "%s: ", progname);
+		perror("getpeername");
+		_exit(1);
+	}
+	if (keepalive &&
+	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
+			(char *)&on, sizeof (on)) < 0) {
+		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+	}
+
+#if	defined(IPPROTO_IP) && defined(IP_TOS)
+	if (fromlen == sizeof (struct in_addr)) {
+# if	defined(HAVE_GETTOSBYNAME)
+		struct tosent *tp;
+		if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+			tos = tp->t_tos;
+# endif
+		if (tos < 0)
+			tos = 020;	/* Low Delay bit */
+		if (tos
+		   && (setsockopt(0, IPPROTO_IP, IP_TOS,
+				  (char *)&tos, sizeof(tos)) < 0)
+		   && (errno != ENOPROTOOPT) )
+			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+	}
+#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
+	net = 0;
+	doit((struct sockaddr *)&from);
+	
+	/* NOTREACHED */
+	return 0;
+}  /* end of main */
+
+	void
+usage()
+{
+	fprintf(stderr, "Usage: telnetd");
+#ifdef	AUTHENTICATION
+	fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t");
+#endif
+#ifdef BFTPDAEMON
+	fprintf(stderr, " [-B]");
+#endif
+	fprintf(stderr, " [-debug]");
+#ifdef DIAGNOSTICS
+	fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
+#endif
+#ifdef	AUTHENTICATION
+	fprintf(stderr, " [-edebug]");
+#endif
+	fprintf(stderr, " [-h]");
+#if	defined(CRAY) && defined(NEWINIT)
+	fprintf(stderr, " [-Iinitid]");
+#endif
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+	fprintf(stderr, " [-k]");
+#endif
+#ifdef LINEMODE
+	fprintf(stderr, " [-l]");
+#endif
+	fprintf(stderr, " [-n]");
+#ifdef	CRAY
+	fprintf(stderr, " [-r[lowpty]-[highpty]]");
+#endif
+	fprintf(stderr, "\n\t");
+#ifdef	SecurID
+	fprintf(stderr, " [-s]");
+#endif
+#ifdef	HAVE_GETTOSBYNAME
+	fprintf(stderr, " [-S tos]");
+#endif
+#ifdef	AUTHENTICATION
+	fprintf(stderr, " [-X auth-type]");
+#endif
+	fprintf(stderr, " [-U]\n\t");
+	fprintf(stderr, " [-w [ip|maxhostlen[,[no]striplocal]]]\n\t");
+	fprintf(stderr, " [port]\n");
+	exit(1);
+}
+
+static void encrypt_failure()
+{
+    char *lerror_message;
+
+    if (auth_must_encrypt())
+	lerror_message = "Encryption was not successfully negotiated.  Goodbye.\r\n\r\n";
+    else
+	lerror_message = "Unencrypted connection refused. Goodbye.\r\n\r\n";
+
+    netputs(lerror_message);
+    netflush();
+    exit(1);
+}
+
+/*
+ * getterminaltype
+ *
+ *	Ask the other end to send along its terminal type and speed.
+ * Output is the variable terminaltype filled in.
+ */
+static unsigned char ttytype_sbbuf[] = {
+	IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
+};
+
+static int
+getterminaltype(name)
+    char *name;
+{
+    settimer(baseline);
+#if	defined(AUTHENTICATION)
+    ttsuck();
+    /*
+     * Handle the Authentication option before we do anything else.
+     */
+    send_do(TELOPT_AUTHENTICATION, 1);
+    while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
+	ttloop();
+    if (his_state_is_will(TELOPT_AUTHENTICATION)) {
+	auth_wait(name);
+    }
+#endif
+
+#ifdef	ENCRYPTION
+    send_will(TELOPT_ENCRYPT, 1);
+    send_do(TELOPT_ENCRYPT, 1);
+#endif	/* ENCRYPTION */
+    send_do(TELOPT_TTYPE, 1);
+    send_do(TELOPT_TSPEED, 1);
+    send_do(TELOPT_XDISPLOC, 1);
+    send_do(TELOPT_NEW_ENVIRON, 1);
+    send_do(TELOPT_OLD_ENVIRON, 1);
+    while (
+#ifdef	ENCRYPTION
+	   his_do_dont_is_changing(TELOPT_ENCRYPT) ||
+	   his_will_wont_is_changing(TELOPT_ENCRYPT) ||
+#endif	/* ENCRYPTION */
+	   his_will_wont_is_changing(TELOPT_TTYPE) ||
+	   his_will_wont_is_changing(TELOPT_TSPEED) ||
+	   his_will_wont_is_changing(TELOPT_XDISPLOC) ||
+	   his_will_wont_is_changing(TELOPT_NEW_ENVIRON) ||
+	   his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) {
+	ttloop();
+    }
+#ifdef	ENCRYPTION
+    /*
+     * Wait for the negotiation of what type of encryption we can
+     * send with.  If autoencrypt is not set, this will just return.
+     */
+    if (his_state_is_will(TELOPT_ENCRYPT)) {
+	encrypt_wait();
+    }
+    if (must_encrypt || auth_must_encrypt()) {
+	time_t timeout = time(0) + 60;
+	
+	if (my_state_is_dont(TELOPT_ENCRYPT) ||
+	    my_state_is_wont(TELOPT_ENCRYPT) ||
+	    his_state_is_wont(TELOPT_AUTHENTICATION))
+	    encrypt_failure();
+
+	while (!EncryptStartInput()) {
+	    if (time (0) > timeout)
+		encrypt_failure();
+	    ttloop();
+	}
+
+	while (!EncryptStartOutput()) {
+	    if (time (0) > timeout)
+		encrypt_failure();
+	    ttloop();
+	}
+
+	while (!encrypt_is_encrypting()) {
+	    if (time(0) > timeout)
+		encrypt_failure();
+	    ttloop();
+	}
+    }
+#endif	/* ENCRYPTION */
+    /* Options like environment require authentication and encryption
+       negotiation to be completed.*/
+    auth_negotiated = 1;
+    if (his_state_is_will(TELOPT_TSPEED)) {
+	static unsigned char sb[] =
+			{ IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
+	netwrite(sb, sizeof(sb));
+    }
+    if (his_state_is_will(TELOPT_XDISPLOC)) {
+	static unsigned char sb[] =
+			{ IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
+	netwrite(sb, sizeof(sb));
+    }
+    if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
+	static unsigned char sb[] =
+			{ IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
+	netwrite(sb, sizeof(sb));
+    }
+    else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
+	static unsigned char sb[] =
+			{ IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
+	netwrite(sb, sizeof(sb));
+    }
+    if (his_state_is_will(TELOPT_TTYPE))
+	netwrite(ttytype_sbbuf, sizeof(ttytype_sbbuf));
+
+    if (his_state_is_will(TELOPT_TSPEED)) {
+	while (sequenceIs(tspeedsubopt, baseline))
+	    ttloop();
+    }
+    if (his_state_is_will(TELOPT_XDISPLOC)) {
+	while (sequenceIs(xdisplocsubopt, baseline))
+	    ttloop();
+    }
+    if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
+	while (sequenceIs(environsubopt, baseline))
+	    ttloop();
+    }
+    if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
+	while (sequenceIs(oenvironsubopt, baseline))
+	    ttloop();
+    }
+    if (his_state_is_will(TELOPT_TTYPE)) {
+	char first[256], last[256];
+
+	while (sequenceIs(ttypesubopt, baseline))
+	    ttloop();
+
+	/*
+	 * If the other side has already disabled the option, then
+	 * we have to just go with what we (might) have already gotten.
+	 */
+	if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
+	    (void) strncpy(first, terminaltype, sizeof(first) - 1);
+	    first[sizeof(first) - 1] = '\0';
+	    for(;;) {
+		/*
+		 * Save the unknown name, and request the next name.
+		 */
+		(void) strncpy(last, terminaltype, sizeof(last) - 1);
+		last[sizeof(last) - 1] = '\0';
+		_gettermname();
+		if (terminaltypeok(terminaltype))
+		    break;
+		if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
+		    his_state_is_wont(TELOPT_TTYPE)) {
+		    /*
+		     * We've hit the end.  If this is the same as
+		     * the first name, just go with it.
+		     */
+		    if (strncmp(first, terminaltype, sizeof(first)) == 0)
+			break;
+		    /*
+		     * Get the terminal name one more time, so that
+		     * RFC1091 compliant telnets will cycle back to
+		     * the start of the list.
+		     */
+		    _gettermname();
+		    if (strncmp(first, terminaltype, sizeof(first)) != 0) {
+			(void) strncpy(terminaltype, first,
+				       sizeof(terminaltype) - 1);
+			terminaltype[sizeof(terminaltype) - 1] = '\0';
+		    }
+		    break;
+		}
+	    }
+	}
+    }
+#ifdef AUTHENTICATION
+    return(auth_check(name));
+#else
+    return(-1);
+#endif
+}  /* end of getterminaltype */
+
+static void
+_gettermname()
+{
+    /*
+     * If the client turned off the option,
+     * we can't send another request, so we
+     * just return.
+     */
+    if (his_state_is_wont(TELOPT_TTYPE))
+	return;
+    settimer(baseline);
+    netwrite(ttytype_sbbuf, sizeof(ttytype_sbbuf));
+    while (sequenceIs(ttypesubopt, baseline))
+	ttloop();
+}
+
+    int
+terminaltypeok(s)
+    char *s;
+{
+    char buf[1024];
+
+    if (!*s)
+	return(1);
+
+    /*
+     * tgetent() will return 1 if the type is known, and
+     * 0 if it is not known.  If it returns -1, it couldn't
+     * open the database.  But if we can't open the database,
+     * it won't help to say we failed, because we won't be
+     * able to verify anything else.  So, we treat -1 like 1.
+     */
+    if (tgetent(buf, s) == 0)
+	return(0);
+    return(1);
+}
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+
+#ifndef MAXDNAME
+#define MAXDNAME 256 /*per the rfc*/
+#endif
+
+char *hostname;
+char host_name[MAXDNAME];
+char remote_host_name[MAXDNAME];
+char *rhost_sane;
+
+#ifndef	convex
+extern void telnet (int, int);
+#else
+extern void telnet (int, int, char *);
+#endif
+
+/*
+ * Get a pty, scan input lines.
+ */
+static void doit(who)
+	struct sockaddr *who;
+{
+	int level;
+#if	defined(_SC_CRAY_SECURE_SYS)
+	int ptynum;
+#endif
+	char user_name[256];
+	long retval;
+	/*
+	 * Find an available pty to use.
+	 */
+	pty_init();
+	
+
+	if ((retval = pty_getpty(&pty, line, 17)) != 0) {
+		fatal(net, error_message(retval));
+	}
+
+#if	defined(_SC_CRAY_SECURE_SYS)
+	/*
+	 *	set ttyp line security label 
+	 */
+	if (secflag) {
+		char slave_dev[16];
+/*xxx This code needs to be fixed to work without ptynum; I don't understand why they don't currently use line, so I don't really know how to fix.*/
+		sprintf(tty_dev, "/dev/pty/%03d", ptynum);
+		if (setdevs(tty_dev, &dv) < 0)
+		 	fatal(net, "cannot set pty security");
+		sprintf(slave_dev, "/dev/ttyp%03d", ptynum);
+		if (setdevs(slave_dev, &dv) < 0)
+		 	fatal(net, "cannot set tty security");
+	}
+#endif	/* _SC_CRAY_SECURE_SYS */
+
+	retval = pty_make_sane_hostname((struct sockaddr *) who, maxhostlen,
+					stripdomain, always_ip,
+					&rhost_sane);
+	if (retval) {
+		fatal(net, error_message(retval));
+	}
+	if (registerd_host_only) {
+	    /* Get name of connected client -- but we don't actually
+	       use it.  Just confirm that we can get it.  */
+	    int aierror;
+	    char hostnamebuf[NI_MAXHOST];
+	    aierror = getnameinfo (who, socklen (who),
+				   hostnamebuf, sizeof (hostnamebuf), 0, 0,
+				   NI_NAMEREQD);
+	    if (aierror != 0) {
+		fatal(net,
+		      "Couldn't resolve your address into a host name.\r\n"
+		      "Please contact your net administrator");
+	    }
+	}
+
+	(void) gethostname(host_name, sizeof (host_name));
+	hostname = host_name;
+
+#if	defined(AUTHENTICATION) || defined(ENCRYPTION)
+	auth_encrypt_init(hostname, rhost_sane, "TELNETD", 1);
+#endif
+
+	init_env();
+
+#ifdef	SIGTTOU
+	/*
+	 * Ignoring SIGTTOU keeps the kernel from blocking us.
+	 * we tweak the tty with an ioctl()
+	 * (in ttioct() in /sys/tty.c in a BSD kernel)
+	 */
+	(void) signal(SIGTTOU, SIG_IGN);
+#endif
+	/*
+	 * get terminal type.
+	 */
+	*user_name = 0;
+	level = getterminaltype(user_name);
+	setenv("TERM", *terminaltype ? terminaltype : "network", 1);
+
+#if defined (AUTHENTICATION)
+	if (level < 0 && auth_level > 0) {
+		fatal (net, "No authentication provided");
+		exit (-1);
+	}
+#endif
+	/*
+	 * Start up the login process on the slave side of the terminal
+	 */
+#ifndef	convex
+	startslave(rhost_sane, level, user_name);
+
+#if	defined(_SC_CRAY_SECURE_SYS)
+	if (secflag) {
+		if (setulvl(dv.dv_actlvl) < 0)
+			fatal(net,"cannot setulvl()");
+		if (setucmp(dv.dv_actcmp) < 0)
+			fatal(net, "cannot setucmp()");
+	}
+#endif	/* _SC_CRAY_SECURE_SYS */
+
+	telnet(net, pty);  /* begin server processing */
+#else
+	telnet(net, pty, rhost_sane);
+#endif
+	/*NOTREACHED*/
+}  /* end of doit */
+
+#if	defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50)
+	int
+Xterm_output(ibufp, obuf, icountp, ocount)
+	char **ibufp, *obuf;
+	int *icountp, ocount;
+{
+	int ret;
+	ret = term_output(*ibufp, obuf, *icountp, ocount);
+	*ibufp += *icountp;
+	*icountp = 0;
+	return(ret);
+}
+#define	term_output	Xterm_output
+#endif	/* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */
+
+/*
+ * Main loop.  Select from pty and network, and
+ * hand data to telnet receiver finite state machine.
+ */
+	void
+#ifndef	convex
+telnet(f, p)
+#else
+telnet(f, p, host)
+#endif
+	int f, p;
+#ifdef convex
+	char *host;
+#endif
+{
+	int on = 1;
+#define	TABBUFSIZ	512
+	char	defent[TABBUFSIZ];
+	char	defstrs[TABBUFSIZ];
+#undef	TABBUFSIZ
+	char *HEstr;
+	char *HN;
+	char *IM;
+	void netflush();
+
+	/*
+	 * Initialize the slc mapping table.
+	 */
+	get_slc_defaults();
+
+	/*
+	 * Do some tests where it is desireable to wait for a response.
+	 * Rather than doing them slowly, one at a time, do them all
+	 * at once.
+	 */
+	if (my_state_is_wont(TELOPT_SGA))
+		send_will(TELOPT_SGA, 1);
+	/*
+	 * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
+	 * because 4.2 clients are unable to deal with TCP urgent data.
+	 *
+	 * To find out, we send out a "DO ECHO".  If the remote system
+	 * answers "WILL ECHO" it is probably a 4.2 client, and we note
+	 * that fact ("WILL ECHO" ==> that the client will echo what
+	 * WE, the server, sends it; it does NOT mean that the client will
+	 * echo the terminal input).
+	 */
+	send_do(TELOPT_ECHO, 1);
+
+#ifdef	LINEMODE
+	if (his_state_is_wont(TELOPT_LINEMODE)) {
+		/* Query the peer for linemode support by trying to negotiate
+		 * the linemode option.
+		 */
+		linemode = 0;
+		editmode = 0;
+		send_do(TELOPT_LINEMODE, 1);  /* send do linemode */
+	}
+#endif	/* LINEMODE */
+
+	/*
+	 * Send along a couple of other options that we wish to negotiate.
+	 */
+	send_do(TELOPT_NAWS, 1);
+	send_will(TELOPT_STATUS, 1);
+	flowmode = 1;		/* default flow control state */
+	restartany = -1;	/* uninitialized... */
+	send_do(TELOPT_LFLOW, 1);
+
+	/*
+	 * Spin, waiting for a response from the DO ECHO.  However,
+	 * some REALLY DUMB telnets out there might not respond
+	 * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
+	 * telnets so far seem to respond with WONT for a DO that
+	 * they don't understand...) because by the time we get the
+	 * response, it will already have processed the DO ECHO.
+	 * Kludge upon kludge.
+	 */
+	while (his_will_wont_is_changing(TELOPT_NAWS))
+		ttloop();
+
+	/*
+	 * But...
+	 * The client might have sent a WILL NAWS as part of its
+	 * startup code; if so, we'll be here before we get the
+	 * response to the DO ECHO.  We'll make the assumption
+	 * that any implementation that understands about NAWS
+	 * is a modern enough implementation that it will respond
+	 * to our DO ECHO request; hence we'll do another spin
+	 * waiting for the ECHO option to settle down, which is
+	 * what we wanted to do in the first place...
+	 */
+	if (his_want_state_is_will(TELOPT_ECHO) &&
+	    his_state_is_will(TELOPT_NAWS)) {
+		while (his_will_wont_is_changing(TELOPT_ECHO))
+			ttloop();
+	}
+	/*
+	 * On the off chance that the telnet client is broken and does not
+	 * respond to the DO ECHO we sent, (after all, we did send the
+	 * DO NAWS negotiation after the DO ECHO, and we won't get here
+	 * until a response to the DO NAWS comes back) simulate the
+	 * receipt of a will echo.  This will also send a WONT ECHO
+	 * to the client, since we assume that the client failed to
+	 * respond because it believes that it is already in DO ECHO
+	 * mode, which we do not want.
+	 */
+	if (his_want_state_is_will(TELOPT_ECHO)) {
+		DIAG(TD_OPTIONS, netputs("td: simulating recv\r\n"));
+		willoption(TELOPT_ECHO);
+	}
+
+	/*
+	 * Finally, to clean things up, we turn on our echo.  This
+	 * will break stupid 4.2 telnets out of local terminal echo.
+	 */
+
+	if (my_state_is_wont(TELOPT_ECHO))
+		send_will(TELOPT_ECHO, 1);
+
+#ifndef	STREAMSPTY
+	/*
+	 * Turn on packet mode
+	 */
+	(void) ioctl(p, TIOCPKT, (char *)&on);
+#endif
+
+#if	defined(LINEMODE) && defined(KLUDGELINEMODE)
+	/*
+	 * Continuing line mode support.  If client does not support
+	 * real linemode, attempt to negotiate kludge linemode by sending
+	 * the do timing mark sequence.
+	 */
+	if (lmodetype < REAL_LINEMODE)
+		send_do(TELOPT_TM, 1);
+#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+
+	/*
+	 * Call telrcv() once to pick up anything received during
+	 * terminal type negotiation, 4.2/4.3 determination, and
+	 * linemode negotiation.
+	 */
+	telrcv();
+
+	(void) ioctl(f, FIONBIO, (char *)&on);
+	(void) ioctl(p, FIONBIO, (char *)&on);
+#if	defined(CRAY2) && defined(UNICOS5)
+	init_termdriver(f, p, interrupt, sendbrk);
+#endif
+
+#if	defined(SO_OOBINLINE)
+	(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
+				(char *)&on, sizeof(on));
+#endif	/* defined(SO_OOBINLINE) */
+
+#ifdef	SIGTSTP
+	(void) signal(SIGTSTP, SIG_IGN);
+#endif
+
+	(void) signal(SIGCHLD, cleanup);
+
+#if	defined(CRAY2) && defined(UNICOS5)
+	/*
+	 * Cray-2 will send a signal when pty modes are changed by slave
+	 * side.  Set up signal handler now.
+	 */
+	if ((int)signal(SIGUSR1, termstat) < 0)
+		perror("signal");
+	else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0)
+		perror("ioctl:TCSIGME");
+	/*
+	 * Make processing loop check terminal characteristics early on.
+	 */
+	termstat();
+#endif
+
+#ifdef  TIOCNOTTY
+	{
+		register int t;
+		t = open(_PATH_TTY, O_RDWR);
+		if (t >= 0) {
+			(void) ioctl(t, TIOCNOTTY, (char *)0);
+			(void) close(t);
+		}
+	}
+#endif
+
+#if	defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY)
+	(void) setsid();
+	ioctl(p, TIOCSCTTY, 0);
+#endif
+
+	/*
+	 * Show banner that getty never gave.
+	 *
+	 * We put the banner in the pty input buffer.  This way, it
+	 * gets carriage return null processing, etc., just like all
+	 * other pty --> client data.
+	 */
+
+#if	!defined(CRAY) || !defined(NEWINIT)
+	if (getenv("USER"))
+		hostinfo = 0;
+#endif
+
+	if (getent(defent, "default") == 1) {
+		char *getstr();
+		char *cp=defstrs;
+
+		HEstr = getstr("he", &cp);
+		HN = getstr("hn", &cp);
+		IM = getstr("im", &cp);
+		if (HN && *HN)
+			(void) strncpy(host_name, HN, sizeof(host_name) - 1);
+		host_name[sizeof(host_name) - 1] = '\0';
+		if (IM == 0)
+			IM = "";
+	} else {
+		IM = get_default_IM();
+		HEstr = 0;
+	}
+	edithost(HEstr, host_name);
+	if (hostinfo && *IM)
+		putf(IM, ptyibuf2);
+
+	if (pcc)
+		(void) strncat(ptyibuf2, ptyip, pcc+1);
+	ptyip = ptyibuf2;
+	pcc = strlen(ptyip);
+#ifdef	LINEMODE
+	/*
+	 * Last check to make sure all our states are correct.
+	 */
+	init_termbuf();
+	localstat();
+#endif	/* LINEMODE */
+
+	DIAG(TD_REPORT, netputs("td: Entering processing loop\r\n"));
+
+#ifdef	convex
+	startslave(host);
+#endif
+
+	for (;;) {
+		fd_set ibits, obits, xbits;
+		register int c;
+
+		if (ncc < 0 && pcc < 0)
+			break;
+
+#if	defined(CRAY2) && defined(UNICOS5)
+		if (needtermstat)
+			_termstat();
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+		FD_ZERO(&ibits);
+		FD_ZERO(&obits);
+		FD_ZERO(&xbits);
+		/*
+		 * Never look for input if there's still
+		 * stuff in the corresponding output buffer
+		 */
+		if (nfrontp - nbackp || pcc > 0) {
+			FD_SET(f, &obits);
+		} else {
+			FD_SET(p, &ibits);
+		}
+		if (pfrontp - pbackp || ncc > 0) {
+			FD_SET(p, &obits);
+		} else {
+			FD_SET(f, &ibits);
+		}
+		if (!SYNCHing) {
+			FD_SET(f, &xbits);
+		}
+		if ((c = select(16, &ibits, &obits, &xbits,
+						(struct timeval *)0)) < 1) {
+			if (c == -1) {
+				if (errno == EINTR) {
+					continue;
+				}
+			}
+			sleep(5);
+			continue;
+		}
+
+		/*
+		 * Any urgent data?
+		 */
+		if (FD_ISSET(net, &xbits)) {
+		    SYNCHing = 1;
+		}
+
+		/*
+		 * Something to read from the network...
+		 */
+		if (FD_ISSET(net, &ibits)) {
+#if	!defined(SO_OOBINLINE)
+			/*
+			 * In 4.2 (and 4.3 beta) systems, the
+			 * OOB indication and data handling in the kernel
+			 * is such that if two separate TCP Urgent requests
+			 * come in, one byte of TCP data will be overlaid.
+			 * This is fatal for Telnet, but we try to live
+			 * with it.
+			 *
+			 * In addition, in 4.2 (and...), a special protocol
+			 * is needed to pick up the TCP Urgent data in
+			 * the correct sequence.
+			 *
+			 * What we do is:  if we think we are in urgent
+			 * mode, we look to see if we are "at the mark".
+			 * If we are, we do an OOB receive.  If we run
+			 * this twice, we will do the OOB receive twice,
+			 * but the second will fail, since the second
+			 * time we were "at the mark", but there wasn't
+			 * any data there (the kernel doesn't reset
+			 * "at the mark" until we do a normal read).
+			 * Once we've read the OOB data, we go ahead
+			 * and do normal reads.
+			 *
+			 * There is also another problem, which is that
+			 * since the OOB byte we read doesn't put us
+			 * out of OOB state, and since that byte is most
+			 * likely the TELNET DM (data mark), we would
+			 * stay in the TELNET SYNCH (SYNCHing) state.
+			 * So, clocks to the rescue.  If we've "just"
+			 * received a DM, then we test for the
+			 * presence of OOB data when the receive OOB
+			 * fails (and AFTER we did the normal mode read
+			 * to clear "at the mark").
+			 */
+		    if (SYNCHing) {
+			int atmark;
+
+			(void) ioctl(net, SIOCATMARK, (char *)&atmark);
+			if (atmark) {
+			    ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
+			    if ((ncc == -1) && (errno == EINVAL)) {
+				ncc = read(net, netibuf, sizeof (netibuf));
+				if (sequenceIs(didnetreceive, gotDM)) {
+				    SYNCHing = stilloob(net);
+				}
+			    }
+			} else {
+			    ncc = read(net, netibuf, sizeof (netibuf));
+			}
+		    } else {
+			ncc = read(net, netibuf, sizeof (netibuf));
+		    }
+		    settimer(didnetreceive);
+#else	/* !defined(SO_OOBINLINE)) */
+		    ncc = read(net, netibuf, sizeof (netibuf));
+#endif	/* !defined(SO_OOBINLINE)) */
+		    if (ncc < 0 && errno == EWOULDBLOCK)
+			ncc = 0;
+		    else {
+			if (ncc <= 0) {
+			    break;
+			}
+			netip = netibuf;
+		    }
+		    DIAG((TD_REPORT | TD_NETDATA),
+			 netprintf("td: netread %d chars\r\n", ncc));
+		    DIAG(TD_NETDATA, printdata("nd", netip, ncc));
+		}
+
+		/*
+		 * Something to read from the pty...
+		 */
+		if (FD_ISSET(p, &ibits)) {
+#ifndef	STREAMSPTY
+			pcc = read(p, ptyibuf, BUFSIZ);
+#else
+			pcc = readstream(p, ptyibuf, BUFSIZ);
+#endif
+			/*
+			 * On some systems, if we try to read something
+			 * off the master side before the slave side is
+			 * opened, we get EIO.
+			 */
+			if (pcc < 0 && (errno == EWOULDBLOCK ||
+#ifdef	EAGAIN
+					errno == EAGAIN ||
+#endif
+					errno == EIO)) {
+				pcc = 0;
+			} else {
+				if (pcc <= 0)
+					break;
+#if	!defined(CRAY2) || !defined(UNICOS5)
+#ifdef	LINEMODE
+				/*
+				 * If ioctl from pty, pass it through net
+				 */
+				if (ptyibuf[0] & TIOCPKT_IOCTL) {
+					copy_termbuf(ptyibuf+1, pcc-1);
+					localstat();
+					pcc = 1;
+				}
+#endif	/* LINEMODE */
+				if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
+					netclear();	/* clear buffer back */
+#ifndef	NO_URGENT
+					/*
+					 * There are client telnets on some
+					 * operating systems get screwed up
+					 * royally if we send them urgent
+					 * mode data.
+					 */
+					netprintf_urg("%c%c", IAC, DM);
+#endif
+				}
+				if (his_state_is_will(TELOPT_LFLOW) &&
+				    (ptyibuf[0] &
+				     (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
+					int newflow =
+					    ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
+					if (newflow != flowmode) {
+						flowmode = newflow;
+						netprintf("%c%c%c%c%c%c",
+							IAC, SB, TELOPT_LFLOW,
+							flowmode ? LFLOW_ON
+								 : LFLOW_OFF,
+							IAC, SE);
+					}
+				}
+				pcc--;
+				ptyip = ptyibuf+1;
+#else	/* defined(CRAY2) && defined(UNICOS5) */
+				if (!uselinemode) {
+					unpcc = pcc;
+					unptyip = ptyibuf;
+					pcc = term_output(&unptyip, ptyibuf2,
+								&unpcc, BUFSIZ);
+					ptyip = ptyibuf2;
+				} else
+					ptyip = ptyibuf;
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+			}
+		}
+
+		while (pcc > 0) {
+			if ((&netobuf[BUFSIZ] - nfrontp) < 2)
+				break;
+			c = *ptyip++ & 0377, pcc--;
+			if (c == IAC)
+				netprintf("%c", c);
+#if	defined(CRAY2) && defined(UNICOS5)
+			else if (c == '\n' &&
+				     my_state_is_wont(TELOPT_BINARY) && newmap)
+				netputs("\r");
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+			netprintf("%c", c);
+			if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
+				if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
+					netprintf("%c", *ptyip++ & 0377);
+					pcc--;
+				} else
+					netprintf("%c", '\0');
+			}
+		}
+#if	defined(CRAY2) && defined(UNICOS5)
+		/*
+		 * If chars were left over from the terminal driver,
+		 * note their existence.
+		 */
+		if (!uselinemode && unpcc) {
+			pcc = unpcc;
+			unpcc = 0;
+			ptyip = unptyip;
+		}
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+
+		if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
+			netflush();
+		if (ncc > 0)
+			telrcv();
+		if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
+			ptyflush();
+	}
+	(void) signal(SIGCHLD, SIG_DFL);
+	cleanup(0);
+}  /* end of telnet */
+	
+#ifndef	TCSIG
+# ifdef	TIOCSIG
+#  define TCSIG TIOCSIG
+# endif
+#endif
+
+#ifdef	STREAMSPTY
+
+int flowison = -1;  /* current state of flow: -1 is unknown */
+
+int readstream(p, ibuf, bufsize)
+	int p;
+	char *ibuf;
+	int bufsize;
+{
+	int flags = 0;
+	int ret = 0;
+	struct termios *tsp;
+	struct termio *tp;
+	struct iocblk *ip;
+	char vstop, vstart;
+	int ixon;
+	int newflow;
+
+	strbufc.maxlen = BUFSIZ;
+	strbufc.buf = (char *)ctlbuf;
+	strbufd.maxlen = bufsize-1;
+	strbufd.len = 0;
+	strbufd.buf = ibuf+1;
+	ibuf[0] = 0;
+
+	ret = getmsg(p, &strbufc, &strbufd, &flags);
+	if (ret < 0)  /* error of some sort -- probably EAGAIN */
+		return(-1);
+
+	if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
+		/* data message */
+		if (strbufd.len > 0) {			/* real data */
+			return(strbufd.len + 1);	/* count header char */
+		} else {
+			/* nothing there */
+			errno = EAGAIN;
+			return(-1);
+		}
+	}
+
+	/*
+	 * It's a control message.  Return 1, to look at the flag we set
+	 */
+
+	switch (ctlbuf[0]) {
+	case M_FLUSH:
+		if (ibuf[1] & FLUSHW)
+			ibuf[0] = TIOCPKT_FLUSHWRITE;
+		return(1);
+
+	case M_IOCTL:
+		ip = (struct iocblk *) (ibuf+1);
+		if (readstream_termio(ip->ioc_cmd, ibuf, 
+				      &vstop, &vstart, &ixon)) {
+		  if (readstream_termios(ip->ioc_cmd, ibuf, 
+					 &vstop, &vstart, &ixon)) {
+		    errno = EAGAIN;
+		    return(-1);
+		  }
+		}
+
+		newflow =  (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
+		if (newflow != flowison) {  /* it's a change */
+			flowison = newflow;
+			ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
+			return(1);
+		}
+	}
+
+	/* nothing worth doing anything about */
+	errno = EAGAIN;
+	return(-1);
+}
+#endif /* STREAMSPTY */
+
+/*
+ * Send interrupt to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write intr char.
+ */
+	void
+interrupt()
+{
+	ptyflush();	/* half-hearted */
+
+#ifdef	TCSIG
+	(void) ioctl(pty, TCSIG, (char *)SIGINT);
+#else	/* TCSIG */
+	init_termbuf();
+	*pfrontp++ = slctab[SLC_IP].sptr ?
+			(unsigned char)*slctab[SLC_IP].sptr : '\177';
+#endif	/* TCSIG */
+}
+
+/*
+ * Send quit to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write quit char.
+ */
+	void
+sendbrk()
+{
+	ptyflush();	/* half-hearted */
+#ifdef	TCSIG
+	(void) ioctl(pty, TCSIG, (char *)SIGQUIT);
+#else	/* TCSIG */
+	init_termbuf();
+	*pfrontp++ = slctab[SLC_ABORT].sptr ?
+			(unsigned char)*slctab[SLC_ABORT].sptr : '\034';
+#endif	/* TCSIG */
+}
+
+	void
+sendsusp()
+{
+#ifdef	SIGTSTP
+	ptyflush();	/* half-hearted */
+# ifdef	TCSIG
+	(void) ioctl(pty, TCSIG, (char *)SIGTSTP);
+# else	/* TCSIG */
+	*pfrontp++ = slctab[SLC_SUSP].sptr ?
+			(unsigned char)*slctab[SLC_SUSP].sptr : '\032';
+# endif	/* TCSIG */
+#endif	/* SIGTSTP */
+}
+
+/*
+ * When we get an AYT, if ^T is enabled, use that.  Otherwise,
+ * just send back "[Yes]".
+ */
+void
+recv_ayt()
+{
+#if	defined(SIGINFO) && defined(TCSIG)
+	if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
+		(void) ioctl(pty, TCSIG, (char *)SIGINFO);
+		return;
+	}
+#endif
+	netputs("\r\n[Yes]\r\n");
+}
+
+	void
+doeof()
+{
+	init_termbuf();
+
+#if	defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN)
+	if (!tty_isediting()) {
+		extern char oldeofc;
+		*pfrontp++ = oldeofc;
+		return;
+	}
+#endif
+	*pfrontp++ = slctab[SLC_EOF].sptr ?
+			(unsigned char)*slctab[SLC_EOF].sptr : '\004';
+}
diff --git a/krb5-1-6/src/appl/telnet/telnetd/telnetd.h b/krb5-1-6/src/appl/telnet/telnetd/telnetd.h
new file mode 100644
index 000000000..f21f617e5
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/telnetd.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)telnetd.h	8.1 (Berkeley) 6/4/93
+ */
+
+
+#include "defs.h"
+#include "ext.h"
+
+#ifdef	DIAGNOSTICS
+#define	DIAG(a,b)	if (diagnostic & (a)) b
+#else
+#define	DIAG(a,b)
+#endif
+
+/* other external variables */
+extern	char **environ;
+
diff --git a/krb5-1-6/src/appl/telnet/telnetd/termio-tn.c b/krb5-1-6/src/appl/telnet/telnetd/termio-tn.c
new file mode 100644
index 000000000..c34f5eb16
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/termio-tn.c
@@ -0,0 +1,33 @@
+/* handle having mutually exclusive termio vs. termios */
+/* return 0 if handled */
+#ifdef	STREAMSPTY
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/ioctl.h>
+#include <termio.h>
+
+int readstream_termio(cmd, ibuf, vstop, vstart, ixon)
+     int cmd;
+     char *ibuf;
+     char *vstop, *vstart;
+     int *ixon;
+{
+  struct termio *tp;
+  switch (cmd) {
+  case TCSETA:
+  case TCSETAW:
+  case TCSETAF:
+    tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));
+#if 0				/* VSTOP/VSTART only in termios!? */
+    *vstop = tp->c_cc[VSTOP];
+    *vstart = tp->c_cc[VSTART];
+#endif
+    *ixon = tp->c_iflag & IXON;      
+    return 0;
+  }
+  return -1;
+}
+
+#else
+int silence_warnings_about_empty_source_file_termio = 42;
+#endif /* STREAMSPTY */
diff --git a/krb5-1-6/src/appl/telnet/telnetd/termios-tn.c b/krb5-1-6/src/appl/telnet/telnetd/termios-tn.c
new file mode 100644
index 000000000..3e5488371
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/termios-tn.c
@@ -0,0 +1,35 @@
+/* handle having mutually exclusive termio vs. termios */
+/* return 0 if handled */
+#ifdef	STREAMSPTY
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#if !defined(TCSETS) && defined(_AIX) /* kludge for AIX */
+#include <termio.h>
+#endif
+
+int readstream_termios(cmd, ibuf, vstop, vstart, ixon)
+     int cmd;
+     char *ibuf;
+     char *vstop, *vstart;
+     int *ixon;
+{
+  struct termios *tsp;
+  switch (cmd) {
+  case TCSETS:
+  case TCSETSW:
+  case TCSETSF:
+    tsp = (struct termios *)
+      (ibuf+1 + sizeof(struct iocblk));
+    *vstop = tsp->c_cc[VSTOP];
+    *vstart = tsp->c_cc[VSTART];
+    *ixon = tsp->c_iflag & IXON;
+    return 0;
+  }
+  return -1;
+}
+
+#else
+int silence_warnings_about_empty_source_file_termios = 42;
+#endif /* STREAMSPTY */
diff --git a/krb5-1-6/src/appl/telnet/telnetd/termstat.c b/krb5-1-6/src/appl/telnet/telnetd/termstat.c
new file mode 100644
index 000000000..531e16783
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/termstat.c
@@ -0,0 +1,652 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)termstat.c	8.1 (Berkeley) 6/4/93 */
+
+#include "telnetd.h"
+
+/*
+ * local variables
+ */
+int def_tspeed = -1, def_rspeed = -1;
+#ifdef	TIOCSWINSZ
+int def_row = 0, def_col = 0;
+#endif
+#ifdef	LINEMODE
+static int _terminit = 0;
+#endif	/* LINEMODE */
+
+#if	defined(CRAY2) && defined(UNICOS5)
+int	newmap = 1;	/* nonzero if \n maps to ^M^J */
+#endif
+
+#ifdef	LINEMODE
+/*
+ * localstat
+ *
+ * This function handles all management of linemode.
+ *
+ * Linemode allows the client to do the local editing of data
+ * and send only complete lines to the server.  Linemode state is
+ * based on the state of the pty driver.  If the pty is set for
+ * external processing, then we can use linemode.  Further, if we
+ * can use real linemode, then we can look at the edit control bits
+ * in the pty to determine what editing the client should do.
+ *
+ * Linemode support uses the following state flags to keep track of
+ * current and desired linemode state.
+ *	alwayslinemode : true if -l was specified on the telnetd
+ * 	command line.  It means to have linemode on as much as
+ *	possible.
+ *
+ * 	lmodetype: signifies whether the client can
+ *	handle real linemode, or if use of kludgeomatic linemode
+ *	is preferred.  It will be set to one of the following:
+ *		REAL_LINEMODE : use linemode option
+ *		NO_KLUDGE : don't initiate kludge linemode.
+ *		KLUDGE_LINEMODE : use kludge linemode
+ *		NO_LINEMODE : client is ignorant of linemode
+ *
+ *	linemode, uselinemode : linemode is true if linemode
+ *	is currently on, uselinemode is the state that we wish
+ *	to be in.  If another function wishes to turn linemode
+ *	on or off, it sets or clears uselinemode.
+ *
+ *	editmode, useeditmode : like linemode/uselinemode, but
+ *	these contain the edit mode states (edit and trapsig).
+ *
+ * The state variables correspond to some of the state information
+ * in the pty.
+ *	linemode:
+ *		In real linemode, this corresponds to whether the pty
+ *		expects external processing of incoming data.
+ *		In kludge linemode, this more closely corresponds to the
+ *		whether normal processing is on or not.  (ICANON in
+ *		system V, or COOKED mode in BSD.)
+ *		If the -l option was specified (alwayslinemode), then
+ *		an attempt is made to force external processing on at
+ *		all times.
+ *
+ * The following heuristics are applied to determine linemode
+ * handling within the server.
+ *	1) Early on in starting up the server, an attempt is made
+ *	   to negotiate the linemode option.  If this succeeds
+ *	   then lmodetype is set to REAL_LINEMODE and all linemode
+ *	   processing occurs in the context of the linemode option.
+ *	2) If the attempt to negotiate the linemode option failed,
+ *	   and the "-k" (don't initiate kludge linemode) isn't set,
+ *	   then we try to use kludge linemode.  We test for this
+ *	   capability by sending "do Timing Mark".  If a positive
+ *	   response comes back, then we assume that the client
+ *	   understands kludge linemode (ech!) and the
+ *	   lmodetype flag is set to KLUDGE_LINEMODE.
+ *	3) Otherwise, linemode is not supported at all and
+ *	   lmodetype remains set to NO_LINEMODE (which happens
+ *	   to be 0 for convenience).
+ *	4) At any time a command arrives that implies a higher
+ *	   state of linemode support in the client, we move to that
+ *	   linemode support.
+ *
+ * A short explanation of kludge linemode is in order here.
+ *	1) The heuristic to determine support for kludge linemode
+ *	   is to send a do timing mark.  We assume that a client
+ *	   that supports timing marks also supports kludge linemode.
+ *	   A risky proposition at best.
+ *	2) Further negotiation of linemode is done by changing the
+ *	   the server's state regarding SGA.  If server will SGA,
+ *	   then linemode is off, if server won't SGA, then linemode
+ *	   is on.
+ */
+	void
+localstat()
+{
+	void netflush();
+	int need_will_echo = 0;
+
+#if	defined(CRAY2) && defined(UNICOS5)
+	/*
+	 * Keep track of that ol' CR/NL mapping while we're in the
+	 * neighborhood.
+	 */
+	newmap = tty_isnewmap();
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+
+	/*
+	 * Check for state of BINARY options.
+	 */
+	if (tty_isbinaryin()) {
+		if (his_want_state_is_wont(TELOPT_BINARY))
+			send_do(TELOPT_BINARY, 1);
+	} else {
+		if (his_want_state_is_will(TELOPT_BINARY))
+			send_dont(TELOPT_BINARY, 1);
+	}
+
+	if (tty_isbinaryout()) {
+		if (my_want_state_is_wont(TELOPT_BINARY))
+			send_will(TELOPT_BINARY, 1);
+	} else {
+		if (my_want_state_is_will(TELOPT_BINARY))
+			send_wont(TELOPT_BINARY, 1);
+	}
+
+	/*
+	 * Check for changes to flow control if client supports it.
+	 */
+	flowstat();
+
+	/*
+	 * Check linemode on/off state
+	 */
+	uselinemode = tty_linemode();
+
+	/*
+	 * If alwayslinemode is on, and pty is changing to turn it off, then
+	 * force linemode back on.
+	 */
+	if (alwayslinemode && linemode && !uselinemode) {
+		uselinemode = 1;
+		tty_setlinemode(uselinemode);
+	}
+
+#ifdef	ENCRYPTION
+	/*
+	 * If the terminal is not echoing, but editing is enabled,
+	 * something like password input is going to happen, so
+	 * if we the other side is not currently sending encrypted
+	 * data, ask the other side to start encrypting.
+	 */
+	if (his_state_is_will(TELOPT_ENCRYPT)) {
+		static int enc_passwd = 0;
+		if (uselinemode && !tty_isecho() && tty_isediting()
+		    && (enc_passwd == 0) && !decrypt_input) {
+			encrypt_send_request_start();
+			enc_passwd = 1;
+		} else if (enc_passwd) {
+			encrypt_send_request_end();
+			enc_passwd = 0;
+		}
+	}
+#endif	/* ENCRYPTION */
+
+	/*
+	 * Do echo mode handling as soon as we know what the
+	 * linemode is going to be.
+	 * If the pty has echo turned off, then tell the client that
+	 * the server will echo.  If echo is on, then the server
+	 * will echo if in character mode, but in linemode the
+	 * client should do local echoing.  The state machine will
+	 * not send anything if it is unnecessary, so don't worry
+	 * about that here.
+	 *
+	 * If we need to send the WILL ECHO (because echo is off),
+	 * then delay that until after we have changed the MODE.
+	 * This way, when the user is turning off both editing
+	 * and echo, the client will get editing turned off first.
+	 * This keeps the client from going into encryption mode
+	 * and then right back out if it is doing auto-encryption
+	 * when passwords are being typed.
+	 */
+	if (uselinemode) {
+		if (tty_isecho())
+			send_wont(TELOPT_ECHO, 1);
+		else
+			need_will_echo = 1;
+#ifdef	KLUDGELINEMODE
+		if (lmodetype == KLUDGE_OK)
+			lmodetype = KLUDGE_LINEMODE;
+#endif
+	}
+
+	/*
+	 * If linemode is being turned off, send appropriate
+	 * command and then we're all done.
+	 */
+	 if (!uselinemode && linemode) {
+# ifdef	KLUDGELINEMODE
+		if (lmodetype == REAL_LINEMODE) {
+# endif	/* KLUDGELINEMODE */
+			send_dont(TELOPT_LINEMODE, 1);
+# ifdef	KLUDGELINEMODE
+		} else if (lmodetype == KLUDGE_LINEMODE)
+			send_will(TELOPT_SGA, 1);
+# endif	/* KLUDGELINEMODE */
+		send_will(TELOPT_ECHO, 1);
+		linemode = uselinemode;
+		goto done;
+	}
+
+# ifdef	KLUDGELINEMODE
+	/*
+	 * If using real linemode check edit modes for possible later use.
+	 * If we are in kludge linemode, do the SGA negotiation.
+	 */
+	if (lmodetype == REAL_LINEMODE) {
+# endif	/* KLUDGELINEMODE */
+		useeditmode = 0;
+		if (tty_isediting())
+			useeditmode |= MODE_EDIT;
+		if (tty_istrapsig())
+			useeditmode |= MODE_TRAPSIG;
+		if (tty_issofttab())
+			useeditmode |= MODE_SOFT_TAB;
+		if (tty_islitecho())
+			useeditmode |= MODE_LIT_ECHO;
+# ifdef	KLUDGELINEMODE
+	} else if (lmodetype == KLUDGE_LINEMODE) {
+		if (tty_isediting() && uselinemode)
+			send_wont(TELOPT_SGA, 1);
+		else
+			send_will(TELOPT_SGA, 1);
+	}
+# endif	/* KLUDGELINEMODE */
+
+	/*
+	 * Negotiate linemode on if pty state has changed to turn it on.
+	 * Send appropriate command and send along edit mode, then all done.
+	 */
+	if (uselinemode && !linemode) {
+# ifdef	KLUDGELINEMODE
+		if (lmodetype == KLUDGE_LINEMODE) {
+			send_wont(TELOPT_SGA, 1);
+		} else if (lmodetype == REAL_LINEMODE) {
+# endif	/* KLUDGELINEMODE */
+			send_do(TELOPT_LINEMODE, 1);
+			/* send along edit modes */
+			netprintf("%c%c%c%c%c%c%c", IAC, SB,
+				TELOPT_LINEMODE, LM_MODE, useeditmode,
+				IAC, SE);
+			editmode = useeditmode;
+# ifdef	KLUDGELINEMODE
+		}
+# endif	/* KLUDGELINEMODE */
+		linemode = uselinemode;
+		goto done;
+	}
+
+# ifdef	KLUDGELINEMODE
+	/*
+	 * None of what follows is of any value if not using
+	 * real linemode.
+	 */
+	if (lmodetype < REAL_LINEMODE)
+		goto done;
+# endif	/* KLUDGELINEMODE */
+
+	if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
+		/*
+		 * If edit mode changed, send edit mode.
+		 */
+		 if (useeditmode != editmode) {
+			/*
+			 * Send along appropriate edit mode mask.
+			 */
+			(void) netprintf("%c%c%c%c%c%c%c", IAC, SB,
+				TELOPT_LINEMODE, LM_MODE, useeditmode,
+				IAC, SE);
+			editmode = useeditmode;
+		}
+							
+
+		/*
+		 * Check for changes to special characters in use.
+		 */
+		start_slc(0);
+		check_slc();
+		(void) end_slc(0);
+	}
+
+done:
+	if (need_will_echo)
+		send_will(TELOPT_ECHO, 1);
+	/*
+	 * Some things should be deferred until after the pty state has
+	 * been set by the local process.  Do those things that have been
+	 * deferred now.  This only happens once.
+	 */
+	if (_terminit == 0) {
+		_terminit = 1;
+		defer_terminit();
+	}
+
+	netflush();
+	set_termbuf();
+	return;
+
+}  /* end of localstat */
+#endif	/* LINEMODE */
+
+/*
+ * flowstat
+ *
+ * Check for changes to flow control
+ */
+	void
+flowstat()
+{
+	if (his_state_is_will(TELOPT_LFLOW)) {
+		if (tty_flowmode() != flowmode) {
+			flowmode = tty_flowmode();
+			netprintf("%c%c%c%c%c%c",
+					IAC, SB, TELOPT_LFLOW,
+					flowmode ? LFLOW_ON : LFLOW_OFF,
+					IAC, SE);
+		}
+		if (tty_restartany() != restartany) {
+			restartany = tty_restartany();
+			netprintf("%c%c%c%c%c%c",
+					IAC, SB, TELOPT_LFLOW,
+					restartany ? LFLOW_RESTART_ANY
+						   : LFLOW_RESTART_XON,
+					IAC, SE);
+		}
+	}
+}
+
+/*
+ * clientstat
+ *
+ * Process linemode related requests from the client.
+ * Client can request a change to only one of linemode, editmode or slc's
+ * at a time, and if using kludge linemode, then only linemode may be
+ * affected.
+ */
+	void
+clientstat(code, parm1, parm2)
+	register int code, parm1, parm2;
+{
+	void netflush();
+
+	/*
+	 * Get a copy of terminal characteristics.
+	 */
+	init_termbuf();
+
+	/*
+	 * Process request from client. code tells what it is.
+	 */
+	switch (code) {
+#ifdef	LINEMODE
+	case TELOPT_LINEMODE:
+		/*
+		 * Don't do anything unless client is asking us to change
+		 * modes.
+		 */
+		uselinemode = (parm1 == WILL);
+		if (uselinemode != linemode) {
+# ifdef	KLUDGELINEMODE
+			/*
+			 * If using kludge linemode, make sure that
+			 * we can do what the client asks.
+			 * We can not turn off linemode if alwayslinemode
+			 * and the ICANON bit is set.
+			 */
+			if (lmodetype == KLUDGE_LINEMODE) {
+				if (alwayslinemode && tty_isediting()) {
+					uselinemode = 1;
+				}
+			}
+		
+			/*
+			 * Quit now if we can't do it.
+			 */
+			if (uselinemode == linemode)
+				return;
+
+			/*
+			 * If using real linemode and linemode is being
+			 * turned on, send along the edit mode mask.
+			 */
+			if (lmodetype == REAL_LINEMODE && uselinemode)
+# else	/* KLUDGELINEMODE */
+			if (uselinemode)
+# endif	/* KLUDGELINEMODE */
+			{
+				useeditmode = 0;
+				if (tty_isediting())
+					useeditmode |= MODE_EDIT;
+				if (tty_istrapsig)
+					useeditmode |= MODE_TRAPSIG;
+				if (tty_issofttab())
+					useeditmode |= MODE_SOFT_TAB;
+				if (tty_islitecho())
+					useeditmode |= MODE_LIT_ECHO;
+				netprintf("%c%c%c%c%c%c%c", IAC,
+					SB, TELOPT_LINEMODE, LM_MODE,
+					useeditmode, IAC, SE);
+				editmode = useeditmode;
+			}
+
+
+			tty_setlinemode(uselinemode);
+
+			linemode = uselinemode;
+
+			if (!linemode)
+				send_will(TELOPT_ECHO, 1);
+		}
+		break;
+	
+	case LM_MODE:
+	    {
+		register int ack, changed;
+
+		/*
+		 * Client has sent along a mode mask.  If it agrees with
+		 * what we are currently doing, ignore it; if not, it could
+		 * be viewed as a request to change.  Note that the server
+		 * will change to the modes in an ack if it is different from
+		 * what we currently have, but we will not ack the ack.
+		 */
+		 useeditmode &= MODE_MASK;
+		 ack = (useeditmode & MODE_ACK);
+		 useeditmode &= ~MODE_ACK;
+
+		 if (changed = (useeditmode ^ editmode)) {
+			/*
+			 * This check is for a timing problem.  If the
+			 * state of the tty has changed (due to the user
+			 * application) we need to process that info
+			 * before we write in the state contained in the
+			 * ack!!!  This gets out the new MODE request,
+			 * and when the ack to that command comes back
+			 * we'll set it and be in the right mode.
+			 */
+			if (ack)
+				localstat();
+			if (changed & MODE_EDIT)
+				tty_setedit(useeditmode & MODE_EDIT);
+
+			if (changed & MODE_TRAPSIG)
+				tty_setsig(useeditmode & MODE_TRAPSIG);
+
+			if (changed & MODE_SOFT_TAB)
+				tty_setsofttab(useeditmode & MODE_SOFT_TAB);
+
+			if (changed & MODE_LIT_ECHO)
+				tty_setlitecho(useeditmode & MODE_LIT_ECHO);
+
+			set_termbuf();
+
+ 			if (!ack) {
+ 				netprintf("%c%c%c%c%c%c%c", IAC,
+					SB, TELOPT_LINEMODE, LM_MODE,
+ 					useeditmode|MODE_ACK,
+ 					IAC, SE);
+ 			}
+ 		
+			editmode = useeditmode;
+		}
+
+		break;
+
+	    }  /* end of case LM_MODE */
+#endif	/* LINEMODE */
+
+	case TELOPT_NAWS:
+#ifdef	TIOCSWINSZ
+	    {
+		struct winsize ws;
+
+		def_col = parm1;
+		def_row = parm2;
+#ifdef	LINEMODE
+		/*
+		 * Defer changing window size until after terminal is
+		 * initialized.
+		 */
+		if (terminit() == 0)
+			return;
+#endif	/* LINEMODE */
+
+		/*
+		 * Change window size as requested by client.
+		 */
+
+		ws.ws_col = parm1;
+		ws.ws_row = parm2;
+		(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
+	    }
+#endif	/* TIOCSWINSZ */
+		
+		break;
+	
+	case TELOPT_TSPEED:
+	    {
+		def_tspeed = parm1;
+		def_rspeed = parm2;
+#ifdef	LINEMODE
+		/*
+		 * Defer changing the terminal speed.
+		 */
+		if (terminit() == 0)
+			return;
+#endif	/* LINEMODE */
+		/*
+		 * Change terminal speed as requested by client.
+		 * We set the receive speed first, so that if we can't
+		 * store seperate receive and transmit speeds, the transmit
+		 * speed will take precedence.
+		 */
+		tty_rspeed(parm2);
+		tty_tspeed(parm1);
+		set_termbuf();
+
+		break;
+
+	    }  /* end of case TELOPT_TSPEED */
+
+	default:
+		/* What? */
+		break;
+	}  /* end of switch */
+
+#if	defined(CRAY2) && defined(UNICOS5)
+	/*
+	 * Just in case of the likely event that we changed the pty state.
+	 */
+	rcv_ioctl();
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+
+	netflush();
+
+}  /* end of clientstat */
+
+#if	defined(CRAY2) && defined(UNICOS5)
+	void
+termstat()
+{
+	needtermstat = 1;
+}
+
+	void
+_termstat()
+{
+	needtermstat = 0;
+	init_termbuf();
+	localstat();
+	rcv_ioctl();
+}
+#endif	/* defined(CRAY2) && defined(UNICOS5) */
+
+#ifdef	LINEMODE
+/*
+ * defer_terminit
+ *
+ * Some things should not be done until after the login process has started
+ * and all the pty modes are set to what they are supposed to be.  This
+ * function is called when the pty state has been processed for the first time. 
+ * It calls other functions that do things that were deferred in each module.
+ */
+	void
+defer_terminit()
+{
+
+	/*
+	 * local stuff that got deferred.
+	 */
+	if (def_tspeed != -1) {
+		clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed);
+		def_tspeed = def_rspeed = 0;
+	}
+
+#ifdef	TIOCSWINSZ
+	if (def_col || def_row) {
+		struct winsize ws;
+
+		memset((char *)&ws, 0, sizeof(ws));
+		ws.ws_col = def_col;
+		ws.ws_row = def_row;
+		(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
+	}
+#endif
+
+	/*
+	 * The only other module that currently defers anything.
+	 */
+	deferslc();
+
+}  /* end of defer_terminit */
+
+/*
+ * terminit
+ *
+ * Returns true if the pty state has been processed yet.
+ */
+	int
+terminit()
+{
+	return(_terminit);
+
+}  /* end of terminit */
+#endif	/* LINEMODE */
diff --git a/krb5-1-6/src/appl/telnet/telnetd/utility.c b/krb5-1-6/src/appl/telnet/telnetd/utility.c
new file mode 100644
index 000000000..f4568ec28
--- /dev/null
+++ b/krb5-1-6/src/appl/telnet/telnetd/utility.c
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* based on @(#)utility.c	8.1 (Berkeley) 6/4/93 */
+
+#include <stdarg.h>
+#define PRINTOPTIONS
+#include "telnetd.h"
+
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
+#if	defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+#endif
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+/*
+ * utility functions performing io related tasks
+ */
+
+/*
+ * ttloop
+ *
+ *	A small subroutine to flush the network output buffer, get some data
+ * from the network, and pass it through the telnet state machine.  We
+ * also flush the pty input buffer (by dropping its data) if it becomes
+ * too full.
+ */
+
+    void
+ttloop()
+{
+    void netflush();
+
+    DIAG(TD_REPORT, netputs("td: ttloop\r\n"));
+    if (nfrontp-nbackp) {
+	netflush();
+    }
+read_again:
+    ncc = read(net, netibuf, sizeof netibuf);
+    if (ncc < 0) {
+	if (errno == EINTR)
+	    goto read_again;
+	syslog(LOG_INFO, "ttloop:  read: %m");
+	exit(1);
+    } else if (ncc == 0) {
+	syslog(LOG_INFO, "ttloop:  peer died: %m");
+	exit(1);
+    }
+    DIAG(TD_REPORT, netprintf("td: ttloop read %d chars\r\n", ncc));
+    netip = netibuf;
+    telrcv();			/* state machine */
+    if (ncc > 0) {
+	pfrontp = pbackp = ptyobuf;
+	telrcv();
+    }
+}  /* end of ttloop */
+
+/* 
+ * ttsuck - This is a horrible kludge to deal with a bug in
+ * HostExplorer. HostExplorer thinks it knows how to do krb5 auth, but
+ * it doesn't really. So if you offer it krb5 as an auth choice before
+ * krb4, it will sabotage the connection. So we peek ahead into the
+ * input stream to see if the client is a UNIX client, and then
+ * (later) offer krb5 first only if it is. Since no Mac/PC telnet
+ * clients do auto switching between krb4 and krb5 like the UNIX
+ * client does, it doesn't matter what order they see the choices in
+ * (except for HostExplorer).
+ *
+ * It is actually not possible to do this without looking ahead into
+ * the input stream: the client and server both try to begin
+ * auth/encryption negotiation as soon as possible, so if we let the
+ * server process things normally, it will already have sent the list
+ * of supported auth types before seeing the NEW-ENVIRON option. If
+ * you change the code to hold off sending the list of supported auth
+ * types until after it knows whether or not the remote side supports
+ * NEW-ENVIRON, then the auth negotiation and encryption negotiation
+ * race conditions won't interact properly, and encryption negotiation
+ * will reliably fail.
+ */
+
+    void
+ttsuck()
+{
+    extern int auth_client_non_unix;
+    int nread;
+    struct timeval tv;
+    fd_set fds;
+    char *p, match[] = {IAC, WILL, TELOPT_NEW_ENVIRON};
+
+    if (nfrontp-nbackp) {
+	netflush();
+    }
+    tv.tv_sec = 1;
+    tv.tv_usec = 0;
+    FD_SET(net, &fds);
+
+    while (select(net + 1, &fds, NULL, NULL, &tv) == 1)
+      {
+	nread = read(net, netibuf + ncc, sizeof(netibuf) - ncc);
+	if (nread <= 0)
+	  break;
+	ncc += nread;
+      }
+
+    auth_client_non_unix = 1;
+    for (p = netibuf; p < netibuf + ncc; p++)
+      {
+	if (!memcmp(p, match, sizeof(match)))
+	  {
+	    auth_client_non_unix = 0;
+	    break;
+	  }
+      }
+
+    if (ncc > 0)
+      telrcv();
+}
+
+/*
+ * Check a descriptor to see if out of band data exists on it.
+ */
+    int
+stilloob(s)
+    int	s;		/* socket number */
+{
+    static struct timeval timeout = { 0 };
+    fd_set	excepts;
+    int value;
+
+    do {
+	FD_ZERO(&excepts);
+	FD_SET(s, &excepts);
+	value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
+    } while ((value == -1) && (errno == EINTR));
+
+    if (value < 0) {
+	fatalperror(pty, "select");
+    }
+    if (FD_ISSET(s, &excepts)) {
+	return 1;
+    } else {
+	return 0;
+    }
+}
+
+	void
+ptyflush()
+{
+	int n;
+
+	if ((n = pfrontp - pbackp) > 0) {
+		DIAG((TD_REPORT | TD_PTYDATA),
+		     netprintf("td: ptyflush %d chars\r\n", n));
+		DIAG(TD_PTYDATA, printdata("pd", pbackp, n));
+		n = write(pty, pbackp, (unsigned) n);
+	}
+	if (n < 0) {
+		if (errno == EWOULDBLOCK || errno == EINTR)
+			return;
+		(void)signal(SIGCHLD, SIG_DFL);
+		cleanup(0);
+	}
+	pbackp += n;
+	if (pbackp == pfrontp)
+		pbackp = pfrontp = ptyobuf;
+}
+
+/*
+ * nextitem()
+ *
+ *	Return the address of the next "item" in the TELNET data
+ * stream.  This will be the address of the next character if
+ * the current address is a user data character, or it will
+ * be the address of the character following the TELNET command
+ * if the current address is a TELNET IAC ("I Am a Command")
+ * character.
+ */
+static char *
+nextitem(current)
+    char	*current;
+{
+    if ((*current&0xff) != IAC) {
+	return current+1;
+    }
+    switch (*(current+1)&0xff) {
+    case DO:
+    case DONT:
+    case WILL:
+    case WONT:
+	return current+3;
+    case SB:		/* loop forever looking for the SE */
+	{
+	    register char *look = current+2;
+
+	    for (;;) {
+		if ((*look++&0xff) == IAC) {
+		    if ((*look++&0xff) == SE) {
+			return look;
+		    }
+		}
+	    }
+	}
+    default:
+	return current+2;
+    }
+}  /* end of nextitem */
+
+
+/*
+ * netclear()
+ *
+ *	We are about to do a TELNET SYNCH operation.  Clear
+ * the path to the network.
+ *
+ *	Things are a bit tricky since we may have sent the first
+ * byte or so of a previous TELNET command into the network.
+ * So, we have to scan the network buffer from the beginning
+ * until we are up to where we want to be.
+ *
+ *	A side effect of what we do, just to keep things
+ * simple, is to clear the urgent data pointer.  The principal
+ * caller should be setting the urgent data pointer AFTER calling
+ * us in any case.
+ */
+    void
+netclear()
+{
+    register char *thisitem, *next;
+    char *good;
+#define	wewant(p)	((nfrontp > p) && ((*p&0xff) == IAC) && \
+				((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+
+#ifdef	ENCRYPTION
+    thisitem = nclearto > netobuf ? nclearto : netobuf;
+#else	/* ENCRYPTION */
+    thisitem = netobuf;
+#endif	/* ENCRYPTION */
+
+    while ((next = nextitem(thisitem)) <= nbackp) {
+	thisitem = next;
+    }
+
+    /* Now, thisitem is first before/at boundary. */
+
+#ifdef	ENCRYPTION
+    good = nclearto > netobuf ? nclearto : netobuf;
+#else	/* ENCRYPTION */
+    good = netobuf;	/* where the good bytes go */
+#endif	/* ENCRYPTION */
+
+    while (nfrontp > thisitem) {
+	if (wewant(thisitem)) {
+	    unsigned int length;
+
+	    next = thisitem;
+	    do {
+		next = nextitem(next);
+	    } while (wewant(next) && (nfrontp > next));
+	    length = next-thisitem;
+	    memcpy(good, thisitem, length);
+	    good += length;
+	    thisitem = next;
+	} else {
+	    thisitem = nextitem(thisitem);
+	}
+    }
+
+    nbackp = netobuf;
+    nfrontp = good;		/* next byte to be sent */
+    neturg = 0;
+}  /* end of netclear */
+
+/*
+ *  netflush
+ *		Send as much data as possible to the network,
+ *	handling requests for urgent data.
+ */
+void
+netflush()
+{
+    int n;
+    extern int not42;
+
+    if ((n = nfrontp - nbackp) > 0) {
+	DIAG(TD_REPORT, {netprintf_noflush("td: netflush %d chars\r\n", n);
+			 n = nfrontp - nbackp;});
+#ifdef	ENCRYPTION
+	if (encrypt_output) {
+		char *s = nclearto ? nclearto : nbackp;
+		if (nfrontp - s > 0) {
+			(*encrypt_output)((unsigned char *)s, nfrontp-s);
+			nclearto = nfrontp;
+		}
+	}
+#endif	/* ENCRYPTION */
+	/*
+	 * if no urgent data, or if the other side appears to be an
+	 * old 4.2 client (and thus unable to survive TCP urgent data),
+	 * write the entire buffer in non-OOB mode.
+	 */
+	if ((neturg == 0) || (not42 == 0)) {
+	    n = write(net, nbackp, (unsigned) n);	/* normal write */
+	} else {
+	    n = neturg - nbackp;
+	    /*
+	     * In 4.2 (and 4.3) systems, there is some question about
+	     * what byte in a sendOOB operation is the "OOB" data.
+	     * To make ourselves compatible, we only send ONE byte
+	     * out of band, the one WE THINK should be OOB (though
+	     * we really have more the TCP philosophy of urgent data
+	     * rather than the Unix philosophy of OOB data).
+	     */
+	    if (n > 1) {
+		n = send(net, nbackp, n-1, 0);	/* send URGENT all by itself */
+	    } else {
+		n = send(net, nbackp, n, MSG_OOB);	/* URGENT data */
+	    }
+	}
+    }
+    if (n < 0) {
+	if (errno == EWOULDBLOCK || errno == EINTR)
+		return;
+	(void)signal(SIGCHLD, SIG_DFL);
+	cleanup(0);
+    }
+    nbackp += n;
+#ifdef	ENCRYPTION
+    if (nbackp > nclearto)
+	nclearto = 0;
+#endif	/* ENCRYPTION */
+    if (nbackp >= neturg) {
+	neturg = 0;
+    }
+    if (nbackp == nfrontp) {
+	nbackp = nfrontp = netobuf;
+#ifdef	ENCRYPTION
+	nclearto = 0;
+#endif	/* ENCRYPTION */
+    }
+    return;
+}  /* end of netflush */
+
+/*
+ * L8_256(x) = log8(256**x), rounded up, including sign (for decimal
+ * strings too).  log8(256) = 8/3, but we use integer math to round
+ * up.
+ */
+#define L8_256(x) (((x * 8 + 2) / 3) + 1)
+
+/*
+ * netprintf
+ *
+ * Do the equivalent of printf() to the NETOBUF "ring buffer",
+ * possibly calling netflush() if needed.
+ *
+ * Thou shalt not call this with a "%s" format; use netputs instead.
+ * We also don't deal with floating point widths in here.
+ */
+static void
+netprintf_ext(int noflush, int seturg, const char *fmt, va_list args)
+{
+	size_t remain;
+	size_t maxoutlen;
+	char buf[BUFSIZ];
+	const char *cp;
+	int len;
+
+	buf[0] = '\0';		/* nul-terminate */
+	remain = sizeof(netobuf) - (nfrontp - netobuf);
+	for (maxoutlen = 0, cp = fmt; *cp; cp++) {
+		if (*cp == '%')
+			/* Ok so this is slightly overkill... */
+			maxoutlen += L8_256(sizeof(long));
+		else
+			maxoutlen++;
+	}
+	if (maxoutlen >= sizeof(buf))
+		return;		/* highly unlikely */
+
+#ifdef HAVE_VSNPRINTF
+	len = vsnprintf(buf, sizeof(buf), fmt, args);
+#else
+	len = vsprintf(buf, fmt, args);	/* XXX need to fix for SunOS? */
+#endif
+
+	/*
+	 * The return value from sprintf()-like functions may be the
+	 * number of characters that *would* have been output, not the
+	 * number actually output.
+	 */
+	if (len <= 0 || len > sizeof(buf))
+		return;
+	if (remain < len && !noflush) {
+		netflush();
+		remain = sizeof(netobuf) - (nfrontp - netobuf);
+	}
+	if (remain < len)
+		return;		/* still not enough space? */
+	memcpy(nfrontp, buf, (size_t)len);
+	nfrontp += len;
+	if (seturg)
+		neturg = nfrontp - 1;
+}
+
+void
+netprintf(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	netprintf_ext(0, 0, fmt, args);
+	va_end(args);
+}
+
+void
+netprintf_urg(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	netprintf_ext(0, 1, fmt, args);
+	va_end(args);
+}
+
+void
+netprintf_noflush(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	netprintf_ext(1, 0, fmt, args);
+	va_end(args);
+}
+
+/*
+ * netwrite
+ *
+ * Copy BUF into the NETOBUF "ring buffer", possibly calling
+ * netflush() if needed.
+ */
+int
+netwrite(const unsigned char *buf, size_t len)
+{
+	size_t remain;
+
+	remain = sizeof(netobuf) - (nfrontp - netobuf);
+	if (remain < len) {
+		netflush();
+		remain = sizeof(netobuf) - (nfrontp - netobuf);
+	}
+	if (remain < len)
+		return 0;
+	memcpy(nfrontp, buf, len);
+	nfrontp += len;
+	return len;
+}
+
+/*
+ * netputs
+ *
+ * Write S to the NETOBUF "ring buffer".  Does not write a '\n'.
+ */
+void
+netputs(const char *s)
+{
+	netwrite((const unsigned char *) s, strlen(s));
+}
+
+/*
+ * miscellaneous functions doing a variety of little jobs follow ...
+ */
+
+
+	void
+fatal(f, msg)
+	int f;
+	const char *msg;
+{
+	char buf[BUFSIZ];
+
+	(void) sprintf(buf, "telnetd: %s.\r\n", msg);
+#ifdef	ENCRYPTION
+	if (encrypt_output) {
+		/*
+		 * Better turn off encryption first....
+		 * Hope it flushes...
+		 */
+		encrypt_send_end();
+		netflush();
+	}
+#endif	/* ENCRYPTION */
+	(void) write(f, buf, strlen(buf));
+	sleep(1);	/*XXX*/
+	exit(1);
+}
+
+	void
+fatalperror(f, msg)
+	int f;
+	const char *msg;
+{
+	char buf[BUFSIZ], *strerror();
+
+	(void) sprintf(buf, "%s: %s\r\n", msg, strerror(errno));
+	fatal(f, buf);
+}
+
+char editedhost[32];
+
+	void
+edithost(pat, host)
+	register char *pat;
+	register char *host;
+{
+	register char *res = editedhost;
+
+	if (!pat)
+		pat = "";
+	while (*pat) {
+		switch (*pat) {
+
+		case '#':
+			if (*host)
+				host++;
+			break;
+
+		case '@':
+			if (*host)
+				*res++ = *host++;
+			break;
+
+		default:
+			*res++ = *pat;
+			break;
+		}
+		if (res == &editedhost[sizeof editedhost - 1]) {
+			*res = '\0';
+			return;
+		}
+		pat++;
+	}
+	if (*host)
+		(void) strncpy(res, host,
+				sizeof editedhost - (res - editedhost) -1);
+	else
+		*res = '\0';
+	editedhost[sizeof editedhost - 1] = '\0';
+}
+
+static char *putlocation;
+
+static	void
+putstr(s)
+	register char *s;
+{
+
+	while (*s)
+		putchr(*s++);
+}
+
+	void
+putchr(cc)
+	int cc;
+{
+	*putlocation++ = cc;
+}
+
+/*
+ * This is split on two lines so that SCCS will not see the M
+ * between two % signs and expand it...
+ */
+static char fmtstr[] = { "%l:%M\
+%P on %A, %d %B %Y" };
+
+	void
+putf(cp, where)
+	register char *cp;
+	char *where;
+{
+	char *slash;
+	time_t t;
+	char db[100];
+#ifdef HAVE_SYS_UTSNAME_H
+	struct utsname utsinfo;
+
+	(void) uname(&utsinfo);
+#endif
+
+	putlocation = where;
+
+	while (*cp) {
+		if (*cp != '%') {
+			putchr(*cp++);
+			continue;
+		}
+		switch (*++cp) {
+
+		case 't':
+#ifdef	STREAMSPTY
+			/* names are like /dev/pts/2 -- we want pts/2 */
+			slash = strchr(line+1, '/');
+#else
+			slash = strrchr(line, '/');
+#endif
+			if (slash == (char *) 0)
+				putstr(line);
+			else
+				putstr(&slash[1]);
+			break;
+
+		case 'h':
+			putstr(editedhost);
+			break;
+
+		case 'd':
+			(void)time(&t);
+			(void)strftime(db, sizeof(db), fmtstr, localtime(&t));
+			putstr(db);
+			break;
+
+#ifdef HAVE_SYS_UTSNAME_H
+		case 's':
+			putstr(utsinfo.sysname);
+			break;
+
+		case 'm':
+			putstr(utsinfo.machine);
+			break;
+
+		case 'r':
+			putstr(utsinfo.release);
+			break;
+
+		case 'v':
+			putstr(utsinfo.version);
+			break;
+#endif
+
+		case '%':
+			putchr('%');
+			break;
+		}
+		cp++;
+	}
+}
+
+#ifdef DIAGNOSTICS
+/*
+ * Print telnet options and commands in plain text, if possible.
+ */
+void
+printoption(fmt, option)
+	register char *fmt;
+	register int option;
+{
+	netputs(fmt);
+	netputs(" ");
+	if (TELOPT_OK(option)) {
+		netputs(TELOPT(option));
+		netputs("\r\n");
+	} else if (TELCMD_OK(option)) {
+		netputs(TELCMD(option));
+		netputs("\r\n");
+	} else {
+		netprintf("%d\r\n", option);
+	}
+	return;
+}
+
+void
+printsub(direction, pointer, length)
+    char		direction;	/* '<' or '>' */
+    unsigned char	*pointer;	/* where suboption data sits */
+    int			length;		/* length of suboption data */
+{
+    register int i = 0;
+    char buf[512];
+
+        if (!(diagnostic & TD_OPTIONS))
+		return;
+
+	if (direction) {
+	    netputs("td: ");
+	    netputs(direction == '<' ? "recv" : "send");
+	    netputs(" suboption ");
+	    if (length >= 3) {
+		register int j;
+
+		i = pointer[length-2];
+		j = pointer[length-1];
+
+		if (i != IAC || j != SE) {
+		    netputs("(terminated by ");
+		    if (TELOPT_OK(i))
+			netputs(TELOPT(i));
+		    else if (TELCMD_OK(i))
+			netputs(TELCMD(i));
+		    else
+			netprintf("%d", i);
+		    netputs(" ");
+		    if (TELOPT_OK(j))
+			netputs(TELOPT(j));
+		    else if (TELCMD_OK(j))
+			netputs(TELCMD(j));
+		    else
+			netprintf("%d", j);
+		    netputs(", not IAC SE!) ");
+		}
+	    }
+	    length -= 2;
+	}
+	if (length < 1) {
+	    netputs("(Empty suboption??\?)");
+	    return;
+	}
+	switch (pointer[0]) {
+	case TELOPT_TTYPE:
+	    netputs("TERMINAL-TYPE ");
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		netputs("IS \"");
+		netwrite(pointer + 2, (size_t)(length - 2));
+		netputs("\"");
+		break;
+	    case TELQUAL_SEND:
+		netputs("SEND");
+		break;
+	    default:
+		netprintf("- unknown qualifier %d (0x%x).",
+			  pointer[1], pointer[1]);
+	    }
+	    break;
+	case TELOPT_TSPEED:
+	    netputs("TERMINAL-SPEED ");
+	    if (length < 2) {
+		netputs("(empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		netputs("IS ");
+		netwrite(pointer + 2, (size_t)(length - 2));
+		break;
+	    default:
+		if (pointer[1] == 1)
+		    netputs("SEND");
+		else
+		    netprintf("%d (unknown)", pointer[1]);
+		for (i = 2; i < length; i++)
+		    netprintf(" ?%d?", pointer[i]);
+		break;
+	    }
+	    break;
+
+	case TELOPT_LFLOW:
+	    netputs("TOGGLE-FLOW-CONTROL ");
+	    if (length < 2) {
+		netputs("(empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case LFLOW_OFF:
+		netputs("OFF"); break;
+	    case LFLOW_ON:
+		netputs("ON"); break;
+	    case LFLOW_RESTART_ANY:
+		netputs("RESTART-ANY"); break;
+	    case LFLOW_RESTART_XON:
+		netputs("RESTART-XON"); break;
+	    default:
+		netprintf("%d (unknown)", pointer[1]);
+	    }
+	    for (i = 2; i < length; i++)
+		netprintf(" ?%d?", pointer[i]);
+	    break;
+
+	case TELOPT_NAWS:
+	    netputs("NAWS");
+	    if (length < 2) {
+		netputs(" (empty suboption??\?)");
+		break;
+	    }
+	    if (length == 2) {
+		netprintf(" ?%d?", pointer[1]);
+		break;
+	    }
+	    netprintf(" %d %d (%d)",
+		pointer[1], pointer[2],
+		(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
+	    if (length == 4) {
+		netprintf(" ?%d?", pointer[3]);
+		break;
+	    }
+	    netprintf(" %d %d (%d)",
+		pointer[3], pointer[4],
+		(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
+	    for (i = 5; i < length; i++)
+		netprintf(" ?%d?", pointer[i]);
+	    break;
+
+	case TELOPT_LINEMODE:
+	    netputs("LINEMODE ");
+	    if (length < 2) {
+		netputs("(empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case WILL:
+		netputs("WILL ");
+		goto common;
+	    case WONT:
+		netputs("WONT ");
+		goto common;
+	    case DO:
+		netputs("DO ");
+		goto common;
+	    case DONT:
+		netputs("DONT ");
+	    common:
+		if (length < 3) {
+		    netputs("(no option??\?)");
+		    break;
+		}
+		switch (pointer[2]) {
+		case LM_FORWARDMASK:
+		    netputs("Forward Mask");
+		    for (i = 3; i < length; i++)
+			netprintf(" %x", pointer[i]);
+		    break;
+		default:
+		    netprintf("%d (unknown)", pointer[2]);
+		    for (i = 3; i < length; i++)
+			netprintf(" %d", pointer[i]);
+		    break;
+		}
+		break;
+		
+	    case LM_SLC:
+		netputs("SLC");
+		for (i = 2; i < length - 2; i += 3) {
+		    if (SLC_NAME_OK(pointer[i+SLC_FUNC])) {
+			netputs(" ");
+			netputs(SLC_NAME(pointer[i+SLC_FUNC]));
+		    } else
+			netprintf(" %d", pointer[i+SLC_FUNC]);
+		    switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
+		    case SLC_NOSUPPORT:
+			netputs(" NOSUPPORT"); break;
+		    case SLC_CANTCHANGE:
+			netputs(" CANTCHANGE"); break;
+		    case SLC_VARIABLE:
+			netputs(" VARIABLE"); break;
+		    case SLC_DEFAULT:
+			netputs(" DEFAULT"); break;
+		    }
+		    netputs(pointer[i+SLC_FLAGS]&SLC_ACK
+			    ? "|ACK" : "");
+		    netputs(pointer[i+SLC_FLAGS]&SLC_FLUSHIN
+			    ? "|FLUSHIN" : "");
+		    netputs(pointer[i+SLC_FLAGS]&SLC_FLUSHOUT
+			    ? "|FLUSHOUT" : "");
+		    if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
+						SLC_FLUSHOUT| SLC_LEVELBITS)) {
+			netprintf("(0x%x)", pointer[i+SLC_FLAGS]);
+		    }
+		    netprintf(" %d;", pointer[i+SLC_VALUE]);
+		    if ((pointer[i+SLC_VALUE] == IAC) &&
+			(pointer[i+SLC_VALUE+1] == IAC))
+				i++;
+		}
+		for (; i < length; i++)
+		    netprintf(" ?%d?", pointer[i]);
+		break;
+
+	    case LM_MODE:
+		netputs("MODE ");
+		if (length < 3) {
+		    netputs("(no mode??\?)");
+		    break;
+		}
+		{
+		    int wrotemode = 0;
+
+#define NETPUTS_MODE(x)				\
+do {						\
+	if (pointer[2] & (MODE_##x)) {		\
+		if (wrotemode) netputs("|");	\
+		netputs(#x);			\
+		wrotemode++;			\
+	}					\
+} while (0)
+		    NETPUTS_MODE(EDIT);
+		    NETPUTS_MODE(TRAPSIG);
+		    NETPUTS_MODE(SOFT_TAB);
+		    NETPUTS_MODE(LIT_ECHO);
+		    NETPUTS_MODE(ACK);
+#undef NETPUTS_MODE
+		    if (!wrotemode)
+			netputs("0");
+		}
+		if (pointer[2] & ~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
+		    netprintf(" (0x%x)", pointer[2]);
+		for (i = 3; i < length; i++)
+		    netprintf(" ?0x%x?", pointer[i]);
+		break;
+	    default:
+		netprintf("%d (unknown)", pointer[1]);
+		for (i = 2; i < length; i++)
+		    netprintf(" %d", pointer[i]);
+	    }
+	    break;
+
+	case TELOPT_STATUS: {
+	    register char *cp;
+	    register int j, k;
+
+	    netputs("STATUS");
+
+	    switch (pointer[1]) {
+	    default:
+		if (pointer[1] == TELQUAL_SEND)
+		    netputs(" SEND");
+		else
+		    netprintf(" %d (unknown)", pointer[1]);
+		for (i = 2; i < length; i++)
+		    netprintf(" ?%d?", pointer[i]);
+		break;
+	    case TELQUAL_IS:
+		netputs(" IS\r\n");
+
+		for (i = 2; i < length; i++) {
+		    switch(pointer[i]) {
+		    case DO:	cp = "DO"; goto common2;
+		    case DONT:	cp = "DONT"; goto common2;
+		    case WILL:	cp = "WILL"; goto common2;
+		    case WONT:	cp = "WONT"; goto common2;
+		    common2:
+			i++;
+			netputs(" ");
+			netputs(cp);
+			netputs(" ");
+			if (TELOPT_OK(pointer[i]))
+			    netputs(TELOPT(pointer[i]));
+			else
+			    netprintf("%d", pointer[i]);
+
+			netputs("\r\n");
+			break;
+
+		    case SB:
+			netputs(" SB ");
+			i++;
+			j = k = i;
+			while (j < length) {
+			    if (pointer[j] == SE) {
+				if (j+1 == length)
+				    break;
+				if (pointer[j+1] == SE)
+				    j++;
+				else
+				    break;
+			    }
+			    pointer[k++] = pointer[j++];
+			}
+			printsub(0, &pointer[i], k - i);
+			if (i < length) {
+			    netputs(" SE");
+			    i = j;
+			} else
+			    i = j - 1;
+
+			netputs("\r\n");
+
+			break;
+				
+		    default:
+			netprintf(" %d", pointer[i]);
+			break;
+		    }
+		}
+		break;
+	    }
+	    break;
+	  }
+
+	case TELOPT_XDISPLOC:
+	    netputs("X-DISPLAY-LOCATION ");
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		netputs("IS \"");
+		netwrite(pointer + 2, (size_t)(length - 2));
+		netputs("\"");
+		break;
+	    case TELQUAL_SEND:
+		netputs("SEND");
+		break;
+	    default:
+		netprintf("- unknown qualifier %d (0x%x).",
+			  pointer[1], pointer[1]);
+	    }
+	    break;
+
+	case TELOPT_NEW_ENVIRON:
+	    netputs("NEW-ENVIRON ");
+	    goto env_common1;
+	case TELOPT_OLD_ENVIRON:
+	    netputs("OLD-ENVIRON ");
+	env_common1:
+	    switch (pointer[1]) {
+	    case TELQUAL_IS:
+		netputs("IS ");
+		goto env_common;
+	    case TELQUAL_SEND:
+		netputs("SEND ");
+		goto env_common;
+	    case TELQUAL_INFO:
+		netputs("INFO ");
+	    env_common:
+		{
+		    register int noquote = 2;
+		    for (i = 2; i < length; i++ ) {
+			switch (pointer[i]) {
+			case NEW_ENV_VAR:
+			    netputs("\" VAR " + noquote);
+			    noquote = 2;
+			    break;
+
+			case NEW_ENV_VALUE:
+			    netputs("\" VALUE " + noquote);
+			    noquote = 2;
+			    break;
+
+			case ENV_ESC:
+			    netputs("\" ESC " + noquote);
+			    noquote = 2;
+			    break;
+
+			case ENV_USERVAR:
+			    netputs("\" USERVAR " + noquote);
+			    noquote = 2;
+			    break;
+
+			default:
+			    if (isprint(pointer[i]) && pointer[i] != '"') {
+				if (noquote) {
+				    netputs("\"");
+				    noquote = 0;
+				}
+				netprintf("%c", pointer[i]);
+			    } else {
+				netprintf("\" %03o " + noquote,
+					  pointer[i]);
+				noquote = 2;
+			    }
+			    break;
+			}
+		    }
+		    if (!noquote)
+			netputs("\"");
+		    break;
+		}
+	    }
+	    break;
+
+#if	defined(AUTHENTICATION)
+	case TELOPT_AUTHENTICATION:
+	    netputs("AUTHENTICATION");
+	
+	    if (length < 2) {
+		netputs(" (empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case TELQUAL_REPLY:
+	    case TELQUAL_IS:
+		netputs((pointer[1] == TELQUAL_IS) ? " IS " : " REPLY ");
+		if (AUTHTYPE_NAME_OK(pointer[2]))
+		    netputs(AUTHTYPE_NAME(pointer[2]));
+		else
+		    netprintf(" %d ", pointer[2]);
+		if (length < 3) {
+		    netputs("(partial suboption??\?)");
+		    break;
+		}
+		netputs(((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT)
+			? "CLIENT|" : "SERVER|");
+		netputs(((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+			? "MUTUAL" : "ONE-WAY");
+		netputs(((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON)
+			? "|ENCRYPT" : "");
+
+		auth_printsub(&pointer[1], length - 1, (unsigned char *)buf, 
+			      sizeof(buf));
+		netputs(buf);
+		break;
+
+	    case TELQUAL_SEND:
+		i = 2;
+		netputs(" SEND ");
+		while (i < length) {
+		    if (AUTHTYPE_NAME_OK(pointer[i]))
+			netputs(AUTHTYPE_NAME(pointer[i]));
+		    else
+			netprintf("%d", pointer[i]);
+		    netputs(" ");
+		    if (++i >= length) {
+			netputs("(partial suboption??\?)");
+			break;
+		    }
+		    netputs(((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT)
+			    ? "CLIENT|" : "SERVER|");
+		    netputs(((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+			    ? "MUTUAL" : "ONE-WAY");
+		    if ((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON)
+			netputs("|ENCRYPT");
+		    ++i;
+		}
+		break;
+
+	    case TELQUAL_NAME:
+		i = 2;
+		netputs(" NAME \"");
+		while (i < length) {
+		    if (isprint(pointer[i]))
+			netprintf("%c", pointer[i++]);
+		    else {
+			netprintf("\\%03o", pointer[i++]);
+		    }
+		}
+		netputs("\"");
+		break;
+
+	    default:
+		    for (i = 2; i < length; i++)
+			netprintf(" ?%d?", pointer[i]);
+		    break;
+	    }
+	    break;
+#endif
+
+#ifdef	ENCRYPTION
+	case TELOPT_ENCRYPT:
+	    netputs("ENCRYPT");
+	    if (length < 2) {
+		netputs(" (empty suboption??\?)");
+		break;
+	    }
+	    switch (pointer[1]) {
+	    case ENCRYPT_START:
+		netputs(" START");
+		break;
+
+	    case ENCRYPT_END:
+		netputs(" END");
+		break;
+
+	    case ENCRYPT_REQSTART:
+		netputs(" REQUEST-START");
+		break;
+
+	    case ENCRYPT_REQEND:
+		netputs(" REQUEST-END");
+		break;
+
+	    case ENCRYPT_IS:
+	    case ENCRYPT_REPLY:
+		netputs((pointer[1] == ENCRYPT_IS)
+			? " IS " : " REPLY ");
+		if (length < 3) {
+		    netputs(" (partial suboption??\?)");
+		    nfrontp += strlen(nfrontp);
+		    break;
+		}
+		if (ENCTYPE_NAME_OK(pointer[2]))
+		    netputs(ENCTYPE_NAME(pointer[2]));
+		else
+		    netprintf("%d (unknown)", pointer[2]);
+		netputs(" ");
+
+		encrypt_printsub(&pointer[1], length - 1, 
+				 (unsigned char *) buf, sizeof(buf));
+		netputs(buf);
+		break;
+
+	    case ENCRYPT_SUPPORT:
+		i = 2;
+		netputs(" SUPPORT ");
+		nfrontp += strlen(nfrontp);
+		while (i < length) {
+		    if (ENCTYPE_NAME_OK(pointer[i]))
+			netputs(ENCTYPE_NAME(pointer[i]));
+		    else
+			netprintf("%d", pointer[i]);
+		    netputs(" ");
+		    i++;
+		}
+		break;
+
+	    case ENCRYPT_ENC_KEYID:
+		netputs(" ENC_KEYID");
+		goto encommon;
+
+	    case ENCRYPT_DEC_KEYID:
+		netputs(" DEC_KEYID");
+		goto encommon;
+
+	    default:
+		netprintf(" %d (unknown)", pointer[1]);
+	    encommon:
+		for (i = 2; i < length; i++)
+		    netprintf(" %d", pointer[i]);
+		break;
+	    }
+	    break;
+#endif	/* ENCRYPTION */
+
+	default:
+	    if (TELOPT_OK(pointer[0]))
+	        netputs(TELOPT(pointer[0]));
+	    else
+	        netprintf("%d", pointer[0]);
+	    netputs(" (unknown)");
+	    for (i = 1; i < length; i++)
+		netprintf(" %d", pointer[i]);
+	    break;
+	}
+	netputs("\r\n");
+}
+
+/*
+ * Dump a data buffer in hex and ascii to the output data stream.
+ */
+	void
+printdata(tag, ptr, cnt)
+	register char *tag;
+	register char *ptr;
+	register int cnt;
+{
+	register int i;
+	char xbuf[30];
+
+	while (cnt) {
+		/* add a line of output */
+		netputs(tag);
+		netputs(": ");
+		for (i = 0; i < 20 && cnt; i++) {
+			netprintf(nfrontp, "%02x", *ptr);
+			nfrontp += strlen(nfrontp); 
+			if (isprint((int) *ptr)) {
+				xbuf[i] = *ptr;
+			} else {
+				xbuf[i] = '.';
+			}
+			if (i % 2)
+				netputs(" ");
+			cnt--;
+			ptr++;
+		}
+		xbuf[i] = '\0';
+		netputs(" ");
+		netputs(xbuf);
+		netputs("\r\n");
+	} 
+}
+#endif /* DIAGNOSTICS */
diff --git a/krb5-1-6/src/appl/user_user/Makefile.in b/krb5-1-6/src/appl/user_user/Makefile.in
new file mode 100644
index 000000000..e55eda8a2
--- /dev/null
+++ b/krb5-1-6/src/appl/user_user/Makefile.in
@@ -0,0 +1,25 @@
+thisconfigdir=./..
+myfulldir=appl/user_user
+mydir=user_user
+BUILDTOP=$(REL)..$(S)..
+DEFINES = -DDEBUG
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+all:: uuclient uuserver
+
+uuclient: client.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o uuclient client.o $(KRB5_BASE_LIBS)
+
+clean::
+	$(RM) client.o uuclient
+
+uuserver: server.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o uuserver server.o $(KRB5_BASE_LIBS)
+
+install::
+	$(INSTALL_PROGRAM) uuclient $(DESTDIR)$(CLIENT_BINDIR)/uuclient
+	$(INSTALL_PROGRAM) uuserver $(DESTDIR)$(SERVER_BINDIR)/uuserver
+
+clean::
+	$(RM) server.o uuserver
diff --git a/krb5-1-6/src/appl/user_user/client.c b/krb5-1-6/src/appl/user_user/client.c
new file mode 100644
index 000000000..3bcb84b95
--- /dev/null
+++ b/krb5-1-6/src/appl/user_user/client.c
@@ -0,0 +1,278 @@
+/*
+ * appl/user_user/client.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Other end of user-user client/server pair.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "krb5.h"
+#include "com_err.h"
+
+int main (argc, argv)
+int argc;
+char *argv[];
+{
+  int s;
+  register int retval, i;
+  char *hname;		/* full name of server */
+  char **srealms;	/* realm(s) of server */
+  char *princ;		/* principal in credentials cache */
+  struct servent *serv;
+  struct hostent *host;
+  struct sockaddr_in serv_net_addr, cli_net_addr;
+  krb5_ccache cc;
+  krb5_creds creds, *new_creds;
+  krb5_data reply, msg, princ_data;
+  krb5_auth_context auth_context = NULL;
+  krb5_ticket * ticket = NULL;
+  krb5_context context;
+  unsigned short port;
+
+  if (argc < 2 || argc > 4) {
+      fputs ("usage: uu-client <hostname> [message [port]]\n", stderr);
+      return 1;
+  }
+
+  retval = krb5_init_context(&context);
+  if (retval) {
+      com_err(argv[0], retval, "while initializing krb5");
+      exit(1);
+  }
+
+  if (argc == 4) {
+      port = htons(atoi(argv[3]));
+  }
+  else if ((serv = getservbyname ("uu-sample", "tcp")) == NULL)
+  {
+      fputs ("uu-client: unknown service \"uu-sample/tcp\"\n", stderr);
+      return 2;
+  } else {
+      port = serv->s_port;
+  }
+
+  if ((host = gethostbyname (argv[1])) == NULL) {
+      fprintf (stderr, "uu-client: can't get address of host \"%s\".\n", 
+	       argv[1]);
+      return 3;
+  }
+  
+  if (host->h_addrtype != AF_INET) {
+      fprintf (stderr, "uu-client: bad address type %d for \"%s\".\n",
+	       host->h_addrtype, argv[1]);
+      return 3;
+  }
+
+  hname = strdup (host->h_name);
+
+#ifndef USE_STDOUT
+  if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+      com_err ("uu-client", errno, "creating socket");
+      return 4;
+  } else {
+      cli_net_addr.sin_family = AF_INET;
+      cli_net_addr.sin_port = 0;
+      cli_net_addr.sin_addr.s_addr = 0;
+      if (bind (s, (struct sockaddr *)&cli_net_addr, 
+		sizeof (cli_net_addr)) < 0) {
+	  com_err ("uu-client", errno, "binding socket");
+	  return 4;
+      }
+  }
+  
+  serv_net_addr.sin_family = AF_INET;
+  serv_net_addr.sin_port = port;
+
+  i = 0;
+  while (1) {
+      if (host->h_addr_list[i] == 0) {
+	  fprintf (stderr, "uu-client: unable to connect to \"%s\"\n", hname);
+	  return 5;
+      }
+
+      memcpy ((char *)&serv_net_addr.sin_addr, host->h_addr_list[i++], 
+	      sizeof(serv_net_addr.sin_addr));
+
+      if (connect(s, (struct sockaddr *)&serv_net_addr, 
+		  sizeof (serv_net_addr)) == 0)
+	  break;
+      com_err ("uu-client", errno, "connecting to \"%s\" (%s).",
+	       hname, inet_ntoa(serv_net_addr.sin_addr));
+  }
+#else
+  s = 1;
+#endif
+
+  retval = krb5_cc_default(context, &cc);
+  if (retval) {
+      com_err("uu-client", retval, "getting credentials cache");
+      return 6;
+  }
+
+  memset ((char*)&creds, 0, sizeof(creds));
+
+  retval = krb5_cc_get_principal(context, cc, &creds.client);
+  if (retval) {
+      com_err("uu-client", retval, "getting principal name");
+      return 6;
+  }
+  
+  retval = krb5_unparse_name(context, creds.client, &princ);
+  if (retval) {
+      com_err("uu-client", retval, "printing principal name");
+      return 7;
+  } 
+  else
+      fprintf(stderr, "uu-client: client principal is \"%s\".\n", princ);
+
+  retval = krb5_get_host_realm(context, hname, &srealms);
+  if (retval) {
+      com_err("uu-client", retval, "getting realms for \"%s\"", hname);
+      return 7;
+  }
+
+  retval = 
+      krb5_build_principal_ext(context, &creds.server,
+			       krb5_princ_realm(context, creds.client)->length,
+			       krb5_princ_realm(context, creds.client)->data,
+			       6, "krbtgt",
+			       krb5_princ_realm(context, creds.client)->length,
+			       krb5_princ_realm(context, creds.client)->data,
+			       0);
+  if (retval) {
+      com_err("uu-client", retval, "setting up tgt server name");
+      return 7;
+  }
+  
+  /* Get TGT from credentials cache */
+  retval = krb5_get_credentials(context, KRB5_GC_CACHED, cc, 
+				&creds, &new_creds);
+  if (retval) {
+      com_err("uu-client", retval, "getting TGT");
+      return 6;
+  }
+
+  i = strlen(princ) + 1;
+
+  fprintf(stderr, "uu-client: sending %d bytes\n",new_creds->ticket.length + i);
+  princ_data.data = princ;
+  princ_data.length = i;		/* include null terminator for
+					   server's convenience */
+  retval = krb5_write_message(context, (krb5_pointer) &s, &princ_data);
+  if (retval) {
+      com_err("uu-client", retval, "sending principal name to server");
+      return 8;
+  }
+  
+  free(princ);
+  
+  retval = krb5_write_message(context, (krb5_pointer) &s, &new_creds->ticket);
+  if (retval) {
+      com_err("uu-client", retval, "sending ticket to server");
+      return 8;
+  }
+
+  retval = krb5_read_message(context, (krb5_pointer) &s, &reply);
+  if (retval) {
+      com_err("uu-client", retval, "reading reply from server");
+      return 9;
+  }
+
+  retval = krb5_auth_con_init(context, &auth_context);
+  if (retval) {
+      com_err("uu-client", retval, "initializing the auth_context");
+      return 9;
+  }
+  
+  retval = 
+      krb5_auth_con_genaddrs(context, auth_context, s,
+			     KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
+			     KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
+  if (retval) {
+      com_err("uu-client", retval, "generating addrs for auth_context");
+      	return 9;
+    }
+
+  retval = krb5_auth_con_setflags(context, auth_context,
+				  KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+  if (retval) {
+      com_err("uu-client", retval, "initializing the auth_context flags");
+      return 9;
+  }
+  
+  retval = krb5_auth_con_setuseruserkey(context, auth_context, 
+					&new_creds->keyblock);
+  if (retval) {
+      com_err("uu-client", retval, "setting useruserkey for authcontext");
+      return 9;
+  }
+  
+#if 1
+  /* read the ap_req to get the session key */
+  retval = krb5_rd_req(context, &auth_context, &reply,
+		       NULL, NULL, NULL, &ticket);
+  free(reply.data);
+#else
+  retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&s, "???",
+			 0, /* server */, 0, NULL, &ticket);
+#endif
+  
+  if (retval) {
+      com_err("uu-client", retval, "reading AP_REQ from server");
+      return 9;
+  }
+
+  retval = krb5_unparse_name(context, ticket->enc_part2->client, &princ);
+  if (retval)
+      com_err("uu-client", retval, "while unparsing client name");
+  else {
+      printf("server is named \"%s\"\n", princ);
+      free(princ);
+  }
+
+  retval = krb5_read_message(context, (krb5_pointer) &s, &reply);
+  if (retval) {
+      com_err("uu-client", retval, "reading reply from server");
+      return 9;
+  }
+  
+  retval = krb5_rd_safe(context, auth_context, &reply, &msg, NULL);
+  if (retval) {
+      com_err("uu-client", retval, "decoding reply from server");
+      return 10;
+  }
+
+  printf ("uu-client: server says \"%s\".\n", msg.data);
+  return 0;
+}
+
diff --git a/krb5-1-6/src/appl/user_user/server.c b/krb5-1-6/src/appl/user_user/server.c
new file mode 100644
index 000000000..292bacf6d
--- /dev/null
+++ b/krb5-1-6/src/appl/user_user/server.c
@@ -0,0 +1,231 @@
+/*
+ * appl/user_user/server.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * One end of the user-user client-server pair.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "port-sockets.h"
+#include "krb5.h"
+#include "com_err.h"
+
+/* fd 0 is a tcp socket used to talk to the client */
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+  krb5_data pname_data, tkt_data;
+  int sock = 0;
+  socklen_t l;
+  int retval;
+  struct sockaddr_in l_inaddr, f_inaddr;	/* local, foreign address */
+  krb5_creds creds, *new_creds;
+  krb5_ccache cc;
+  krb5_data msgtext, msg;
+  krb5_context context;
+    krb5_auth_context auth_context = NULL;
+
+#ifndef DEBUG
+  freopen("/tmp/uu-server.log", "w", stderr);
+#endif
+
+  retval = krb5_init_context(&context);
+  if (retval) {
+	  com_err(argv[0], retval, "while initializing krb5");
+	  exit(1);
+  }
+
+#ifdef DEBUG
+  {
+      int one = 1;
+      int acc;
+      struct servent *sp;
+      socklen_t namelen = sizeof(f_inaddr);
+      
+      if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+	  com_err("uu-server", errno, "creating socket");
+	  exit(3);
+      }
+      
+      l_inaddr.sin_family = AF_INET;
+      l_inaddr.sin_addr.s_addr = 0;
+      if (!(sp = getservbyname("uu-sample", "tcp"))) {
+	  com_err("uu-server", 0, "can't find uu-sample/tcp service");
+	  exit(3);
+      }
+      (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (one));
+      l_inaddr.sin_port = sp->s_port;
+      if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) {
+	  com_err("uu-server", errno, "binding socket");
+	  exit(3);
+      }
+      if (listen(sock, 1) == -1) {
+	  com_err("uu-server", errno, "listening");
+	  exit(3);
+      }
+      if ((acc = accept(sock, (struct sockaddr *)&f_inaddr, &namelen)) == -1) {
+	  com_err("uu-server", errno, "accepting");
+	  exit(3);
+      }
+      dup2(acc, 0);
+      close(sock);
+      sock = 0;
+  }
+#endif
+
+  retval = krb5_read_message(context, (krb5_pointer) &sock, &pname_data);
+  if (retval) {
+      com_err ("uu-server", retval, "reading pname");
+      return 2;
+  }
+
+  retval = krb5_read_message(context, (krb5_pointer) &sock, &tkt_data);
+  if (retval) {
+      com_err ("uu-server", retval, "reading ticket data");
+      return 2;
+  }
+
+  retval = krb5_cc_default(context, &cc);
+  if (retval) {
+      com_err("uu-server", retval, "getting credentials cache");
+      return 4;
+  }
+
+  memset ((char*)&creds, 0, sizeof(creds));
+  retval = krb5_cc_get_principal(context, cc, &creds.client);
+  if (retval) {
+      com_err("uu-client", retval, "getting principal name");
+      return 6;
+  }
+
+  /* client sends it already null-terminated. */
+  printf ("uu-server: client principal is \"%s\".\n", pname_data.data);
+
+  retval = krb5_parse_name(context, pname_data.data, &creds.server);
+  if (retval) {
+      com_err("uu-server", retval, "parsing client name");
+      return 3;
+  }
+
+  creds.second_ticket = tkt_data;
+  printf ("uu-server: client ticket is %d bytes.\n",
+	  creds.second_ticket.length);
+
+  retval = krb5_get_credentials(context, KRB5_GC_USER_USER, cc, 
+				&creds, &new_creds);
+  if (retval) {
+      com_err("uu-server", retval, "getting user-user ticket");
+      return 5;
+  }
+
+#ifndef DEBUG
+  l = sizeof(f_inaddr);
+  if (getpeername(0, (struct sockaddr *)&f_inaddr, &l) == -1)
+    {
+      com_err("uu-server", errno, "getting client address");
+      return 6;
+    }
+#endif
+  l = sizeof(l_inaddr);
+  if (getsockname(0, (struct sockaddr *)&l_inaddr, &l) == -1)
+    {
+      com_err("uu-server", errno, "getting local address");
+      return 6;
+    }
+
+  /* send a ticket/authenticator to the other side, so it can get the key
+     we're using for the krb_safe below. */
+
+  retval = krb5_auth_con_init(context, &auth_context);
+  if (retval) {
+      com_err("uu-server", retval, "making auth_context");
+      return 8;
+  }
+
+  retval = krb5_auth_con_setflags(context, auth_context,
+				  KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+  if (retval) {
+      com_err("uu-server", retval, "initializing the auth_context flags");
+      return 8;
+  }
+  
+  retval = 
+      krb5_auth_con_genaddrs(context, auth_context, sock,
+			     KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
+			     KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
+  if (retval) {
+      com_err("uu-server", retval, "generating addrs for auth_context");
+      return 9;
+  }
+  
+#if 1
+  retval = krb5_mk_req_extended(context, &auth_context, 
+				AP_OPTS_USE_SESSION_KEY, 
+				NULL, new_creds, &msg);
+  if (retval) {
+      com_err("uu-server", retval, "making AP_REQ");
+      return 8;
+  }
+  retval = krb5_write_message(context, (krb5_pointer) &sock, &msg);
+#else
+  retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sock,"???", 0,
+			 0, AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SESSION_KEY,
+			 NULL, &creds, cc, NULL, NULL, NULL);
+#endif
+  if (retval)
+      goto cl_short_wrt;
+  
+  free(msg.data);
+  
+  msgtext.length = 32;
+  msgtext.data = "Hello, other end of connection.";
+  
+  retval = krb5_mk_safe(context, auth_context, &msgtext, &msg, NULL);
+  if (retval) {
+      com_err("uu-server", retval, "encoding message to client");
+      return 6;
+  }
+
+  retval = krb5_write_message(context, (krb5_pointer) &sock, &msg);
+  if (retval) {
+  cl_short_wrt:
+      com_err("uu-server", retval, "writing message to client");
+      return 7;
+  }
+
+  return 0;
+}
diff --git a/krb5-1-6/src/clients/Makefile.in b/krb5-1-6/src/clients/Makefile.in
new file mode 100644
index 000000000..007e363d6
--- /dev/null
+++ b/krb5-1-6/src/clients/Makefile.in
@@ -0,0 +1,55 @@
+thisconfigdir=..
+myfulldir=clients
+mydir=clients
+BUILDTOP=$(REL)..
+
+LOCAL_SUBDIRS= klist kinit kdestroy kpasswd ksu kvno kcpytkt kdeltkt
+
+NO_OUTPRE=1
+all-windows::
+	@echo Making all in clients\klist
+	cd klist
+	$(MAKE) -$(MFLAGS)
+	@echo Making all in clients\kdestroy
+	cd ..\kdestroy
+	$(MAKE) -$(MFLAGS)
+	@echo Making all in clients\kinit
+	cd ..\kinit
+	$(MAKE) -$(MFLAGS)
+	@echo Making all in clients\kpasswd
+	cd ..\kpasswd
+	$(MAKE) -$(MFLAGS)
+	@echo Making all in clients\kvno
+	cd ..\kvno
+	$(MAKE) -$(MFLAGS)
+	@echo Making all in clients\kcpytkt
+	cd ..\kcpytkt
+	$(MAKE) -$(MFLAGS)
+	@echo Making all in clients\kdeltkt
+	cd ..\kdeltkt
+	$(MAKE) -$(MFLAGS)
+	cd ..
+
+clean-windows::
+	@echo Making clean in clients\klist
+	cd klist
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in clients\kdestroy
+	cd ..\kdestroy
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in clients\kinit
+	cd ..\kinit
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in clients\kpasswd
+	cd ..\kpasswd
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in clients\kvno
+	cd ..\kvno
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in clients\kcpytkt
+	cd ..\kcpytkt
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in clients\kdeltkt
+	cd ..\kdeltkt
+	$(MAKE) -$(MFLAGS) clean
+	cd ..
diff --git a/krb5-1-6/src/clients/kcpytkt/Makefile.in b/krb5-1-6/src/clients/kcpytkt/Makefile.in
new file mode 100644
index 000000000..a47ac5f8f
--- /dev/null
+++ b/krb5-1-6/src/clients/kcpytkt/Makefile.in
@@ -0,0 +1,39 @@
+thisconfigdir=./..
+myfulldir=clients/kcpytkt
+mydir=kcpytkt
+BUILDTOP=$(REL)..$(S)..
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KCPYTKT=$(OUTPRE)kcpytkt.exe
+
+##WIN32##EXERES=$(KCPYTKT:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKCPYTKT_APP -fo $@ -r $**
+
+all-unix:: kcpytkt
+##WIN32##all-windows:: $(KCPYTKT)
+all-mac::
+
+kcpytkt: kcpytkt.o $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $@ kcpytkt.o $(KRB4COMPAT_LIBS)
+
+##WIN32##$(KCPYTKT): $(OUTPRE)kcpytkt.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32##	link $(EXE_LINKOPTS) /out:$@ $**
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) kcpytkt.o kcpytkt
+
+install-unix::
+	for f in kcpytkt; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
diff --git a/krb5-1-6/src/clients/kcpytkt/kcpytkt.M b/krb5-1-6/src/clients/kcpytkt/kcpytkt.M
new file mode 100644
index 000000000..11ed93929
--- /dev/null
+++ b/krb5-1-6/src/clients/kcpytkt/kcpytkt.M
@@ -0,0 +1,37 @@
+.\"
+.\" clients/kvnol/kcpytkt.M
+.\" "
+.TH KCPYTKT 1
+.SH NAME
+kcpytkt \- copies one or more service tickets between credentials caches
+.SH SYNOPSIS
+\fBkcpytkt\fP [\fB\-h\fP] [\fB\-c source_ccache\fP] [\fB\-e etype\fP] [\fB\-f flags\fP] 
+\fBdest_ccache\fP \fBservice1\fP \fBservice2\fP \fB...\fP
+.br
+.SH DESCRIPTION
+.I kcpytkt
+copies the specified service tickets to the destination credentials cache
+.SH OPTIONS
+.TP
+.B \-c
+specifies the source credentials cache from which service tickets will be.
+copied.  if no ccache is specified, the default ccache is used.
+.TP
+.B \-e
+specifies the session key enctype of the service tickets you wish to delete.
+.TP
+.B \-h
+prints a usage statement and exits
+.SH ENVIRONMENT
+.B kcpytkt
+uses the following environment variable:
+.TP "\w'.SM KRB5CCNAME\ \ 'u"
+.SM KRB5CCNAME
+Location of the credentials (ticket) cache.
+.SH FILES
+.TP "\w'/tmp/krb5cc_[uid]\ \ 'u"
+/tmp/krb5cc_[uid]
+default location of the credentials cache ([uid] is the decimal UID of
+the user).
+.SH SEE ALSO
+kinit(1), kdestroy(1), krb5(3)
diff --git a/krb5-1-6/src/clients/kcpytkt/kcpytkt.c b/krb5-1-6/src/clients/kcpytkt/kcpytkt.c
new file mode 100644
index 000000000..8efddb413
--- /dev/null
+++ b/krb5-1-6/src/clients/kcpytkt/kcpytkt.c
@@ -0,0 +1,182 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <krb5.h>
+
+extern int optind;
+extern char *optarg;
+
+static char *prog;
+
+static void xusage()
+{
+    fprintf(stderr, "xusage: %s [-c from_ccache] [-e etype] [-f flags] dest_ccache service1 service2 ...\n", prog);
+    exit(1);
+}
+
+int quiet = 0;
+
+static void do_kcpytkt (int argc, char *argv[], char *fromccachestr, char *etypestr, int flags);
+
+int main(int argc, char *argv[])
+{
+    int option;
+    char *etypestr = 0;
+    char *fromccachestr = 0;
+    int flags = 0;
+
+    prog = strrchr(argv[0], '/');
+    prog = prog ? (prog + 1) : argv[0];
+
+    while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) {
+	switch (option) {
+        case 'c':
+            fromccachestr = optarg;
+            break;
+	case 'e':
+	    etypestr = optarg;
+	    break;
+        case 'f':
+            flags = atoi(optarg);
+            break;
+	case 'q':
+	    quiet = 1;
+	    break;
+	case 'h':
+	default:
+	    xusage();
+	    break;
+	}
+    }
+
+    if ((argc - optind) < 2)
+	xusage();
+
+    do_kcpytkt(argc - optind, argv + optind, fromccachestr, etypestr, flags);
+    return 0;
+}
+
+static void do_kcpytkt (int count, char *names[], 
+                        char *fromccachestr, char *etypestr, int flags)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    int i, errors;
+    krb5_enctype etype;
+    krb5_ccache fromccache;
+    krb5_ccache destccache;
+    krb5_principal me;
+    krb5_creds in_creds, out_creds;
+    int retflags;
+    char *princ;
+
+    ret = krb5_init_context(&context);
+    if (ret) {
+	com_err(prog, ret, "while initializing krb5 library");
+	exit(1);
+    }
+
+    if (etypestr) {
+        ret = krb5_string_to_enctype(etypestr, &etype);
+	if (ret) {
+	    com_err(prog, ret, "while converting etype");
+	    exit(1);
+	}
+        retflags = KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES;
+    } else {
+	etype = 0;
+        retflags = KRB5_TC_MATCH_SRV_NAMEONLY;
+    }
+
+    if (fromccachestr)
+        ret = krb5_cc_resolve(context, fromccachestr, &fromccache);
+    else
+        ret = krb5_cc_default(context, &fromccache);
+    if (ret) {
+	com_err(prog, ret, "while opening source ccache");
+	exit(1);
+    }
+
+    ret = krb5_cc_get_principal(context, fromccache, &me);
+    if (ret) {
+	com_err(prog, ret, "while getting client principal name");
+	exit(1);
+    }
+
+    ret = krb5_cc_resolve(context, names[0], &destccache);
+    if (ret) {
+	com_err(prog, ret, "while opening destination cache");
+	exit(1);
+    }
+
+    errors = 0;
+
+    for (i = 1; i < count; i++) {
+	memset(&in_creds, 0, sizeof(in_creds));
+
+	in_creds.client = me;
+
+	ret = krb5_parse_name(context, names[i], &in_creds.server);
+	if (ret) {
+	    if (!quiet)
+		fprintf(stderr, "%s: %s while parsing principal name\n",
+			names[i], error_message(ret));
+	    errors++;
+	    continue;
+	}
+
+	ret = krb5_unparse_name(context, in_creds.server, &princ);
+	if (ret) {
+	    fprintf(stderr, "%s: %s while printing principal name\n",
+		    names[i], error_message(ret));
+	    errors++;
+	    continue;
+	}
+
+	in_creds.keyblock.enctype = etype;
+
+        ret = krb5_cc_retrieve_cred(context, fromccache, retflags,
+                                    &in_creds, &out_creds);  
+	if (ret) {
+	    fprintf(stderr, "%s: %s while retrieving credentials\n",
+		    princ, error_message(ret));
+
+	    krb5_free_unparsed_name(context, princ);
+
+	    errors++;
+	    continue;
+	}
+
+	ret = krb5_cc_store_cred(context, destccache, &out_creds);
+
+	krb5_free_principal(context, in_creds.server);
+
+	if (ret) {
+	    fprintf(stderr, "%s: %s while removing credentials\n",
+		    princ, error_message(ret));
+
+            krb5_free_cred_contents(context, &out_creds);
+	    krb5_free_unparsed_name(context, princ);
+
+	    errors++;
+	    continue;
+	}
+
+	krb5_free_unparsed_name(context, princ);
+        krb5_free_cred_contents(context, &out_creds);
+    }
+
+    krb5_free_principal(context, me);
+    krb5_cc_close(context, fromccache);
+    krb5_cc_close(context, destccache);
+    krb5_free_context(context);
+
+    if (errors)
+	exit(1);
+
+    exit(0);
+}
diff --git a/krb5-1-6/src/clients/kdeltkt/Makefile.in b/krb5-1-6/src/clients/kdeltkt/Makefile.in
new file mode 100644
index 000000000..dbd4b7116
--- /dev/null
+++ b/krb5-1-6/src/clients/kdeltkt/Makefile.in
@@ -0,0 +1,39 @@
+thisconfigdir=./..
+myfulldir=clients/kdeltkt
+mydir=kvno
+BUILDTOP=$(REL)..$(S)..
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KDELTKT=$(OUTPRE)kdeltkt.exe
+
+##WIN32##EXERES=$(KDELTKT:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKDELTKT_APP -fo $@ -r $**
+
+all-unix:: kdeltkt
+##WIN32##all-windows:: $(KDELTKT)
+all-mac::
+
+kdeltkt: kdeltkt.o $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $@ kdeltkt.o $(KRB4COMPAT_LIBS)
+
+##WIN32##$(KDELTKT): $(OUTPRE)kdeltkt.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32##	link $(EXE_LINKOPTS) /out:$@ $**
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) kdeltkt.o kdeltkt
+
+install-unix::
+	for f in kdeltkt; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
diff --git a/krb5-1-6/src/clients/kdeltkt/kdeltkt.M b/krb5-1-6/src/clients/kdeltkt/kdeltkt.M
new file mode 100644
index 000000000..a9f369418
--- /dev/null
+++ b/krb5-1-6/src/clients/kdeltkt/kdeltkt.M
@@ -0,0 +1,37 @@
+.\"
+.\" clients/kvnol/kdeltkt.M
+.\" "
+.TH KDELTKT 1
+.SH NAME
+kdeltkt \- delete one or more service tickets from the credentials cache
+.SH SYNOPSIS
+\fBkdeltkt\fP [\fB\-h\fP] [\fB\-c ccache\fP] [\fB\-e etype\fP] [\fB\-f flags\fP] 
+\fBservice1\fP \fBservice2\fP \fB...\fP
+.br
+.SH DESCRIPTION
+.I kdeltkt
+deletes the specified service tickets from the credentials cache
+.SH OPTIONS
+.TP
+.B \-c
+specifies the credentials cache from which service tickets will be deleted.
+if no cache is specified, the default cache is used.
+.TP
+.B \-e
+specifies the session key enctype of the service tickets you wish to delete.
+.TP
+.B \-h
+prints a usage statement and exits
+.SH ENVIRONMENT
+.B kdeltkt
+uses the following environment variable:
+.TP "\w'.SM KRB5CCNAME\ \ 'u"
+.SM KRB5CCNAME
+Location of the credentials (ticket) cache.
+.SH FILES
+.TP "\w'/tmp/krb5cc_[uid]\ \ 'u"
+/tmp/krb5cc_[uid]
+default location of the credentials cache ([uid] is the decimal UID of
+the user).
+.SH SEE ALSO
+kinit(1), kdestroy(1), krb5(3)
diff --git a/krb5-1-6/src/clients/kdeltkt/kdeltkt.c b/krb5-1-6/src/clients/kdeltkt/kdeltkt.c
new file mode 100644
index 000000000..832a07075
--- /dev/null
+++ b/krb5-1-6/src/clients/kdeltkt/kdeltkt.c
@@ -0,0 +1,174 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <krb5.h>
+
+extern int optind;
+extern char *optarg;
+
+static char *prog;
+
+static void xusage()
+{
+    fprintf(stderr, "xusage: %s [-c ccache] [-e etype] [-f flags] service1 service2 ...\n", prog);
+    exit(1);
+}
+
+int quiet = 0;
+
+static void do_kdeltkt (int argc, char *argv[], char *ccachestr, char *etypestr, int flags);
+
+int main(int argc, char *argv[])
+{
+    int option;
+    char *etypestr = 0;
+    char *ccachestr = 0;
+    int flags = 0;
+
+    prog = strrchr(argv[0], '/');
+    prog = prog ? (prog + 1) : argv[0];
+
+    while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) {
+	switch (option) {
+        case 'c':
+            ccachestr = optarg;
+            break;
+	case 'e':
+	    etypestr = optarg;
+	    break;
+        case 'f':
+            flags = atoi(optarg);
+            break;
+	case 'q':
+	    quiet = 1;
+	    break;
+	case 'h':
+	default:
+	    xusage();
+	    break;
+	}
+    }
+
+    if ((argc - optind) < 1)
+	xusage();
+
+    do_kdeltkt(argc - optind, argv + optind, ccachestr, etypestr, flags);
+    return 0;
+}
+
+static void do_kdeltkt (int count, char *names[], 
+                        char *ccachestr, char *etypestr, int flags)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    int i, errors;
+    krb5_enctype etype;
+    krb5_ccache ccache;
+    krb5_principal me;
+    krb5_creds in_creds, out_creds;
+    int retflags;
+    char *princ;
+
+    ret = krb5_init_context(&context);
+    if (ret) {
+	com_err(prog, ret, "while initializing krb5 library");
+	exit(1);
+    }
+
+    if (etypestr) {
+        ret = krb5_string_to_enctype(etypestr, &etype);
+	if (ret) {
+	    com_err(prog, ret, "while converting etype");
+	    exit(1);
+	}
+        retflags = KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES;
+    } else {
+	etype = 0;
+        retflags = KRB5_TC_MATCH_SRV_NAMEONLY;
+    }
+
+    if (ccachestr)
+        ret = krb5_cc_resolve(context, ccachestr, &ccache);
+    else
+        ret = krb5_cc_default(context, &ccache);
+    if (ret) {
+	com_err(prog, ret, "while opening ccache");
+	exit(1);
+    }
+
+    ret = krb5_cc_get_principal(context, ccache, &me);
+    if (ret) {
+	com_err(prog, ret, "while getting client principal name");
+	exit(1);
+    }
+
+    errors = 0;
+
+    for (i = 0; i < count; i++) {
+	memset(&in_creds, 0, sizeof(in_creds));
+
+	in_creds.client = me;
+
+	ret = krb5_parse_name(context, names[i], &in_creds.server);
+	if (ret) {
+	    if (!quiet)
+		fprintf(stderr, "%s: %s while parsing principal name\n",
+			names[i], error_message(ret));
+	    errors++;
+	    continue;
+	}
+
+	ret = krb5_unparse_name(context, in_creds.server, &princ);
+	if (ret) {
+	    fprintf(stderr, "%s: %s while printing principal name\n",
+		    names[i], error_message(ret));
+	    errors++;
+	    continue;
+	}
+
+	in_creds.keyblock.enctype = etype;
+
+        ret = krb5_cc_retrieve_cred(context, ccache, retflags,
+                                    &in_creds, &out_creds);  
+	if (ret) {
+	    fprintf(stderr, "%s: %s while retrieving credentials\n",
+		    princ, error_message(ret));
+
+	    krb5_free_unparsed_name(context, princ);
+
+	    errors++;
+	    continue;
+	}
+
+	ret = krb5_cc_remove_cred(context, ccache, flags, &out_creds);
+
+	krb5_free_principal(context, in_creds.server);
+
+	if (ret) {
+	    fprintf(stderr, "%s: %s while removing credentials\n",
+		    princ, error_message(ret));
+
+            krb5_free_cred_contents(context, &out_creds);
+	    krb5_free_unparsed_name(context, princ);
+
+	    errors++;
+	    continue;
+	}
+
+	krb5_free_unparsed_name(context, princ);
+    krb5_free_cred_contents(context, &out_creds);
+    }
+
+    krb5_free_principal(context, me);
+    krb5_cc_close(context, ccache);
+    krb5_free_context(context);
+
+    if (errors)
+	exit(1);
+
+    exit(0);
+}
diff --git a/krb5-1-6/src/clients/kdestroy/Makefile.in b/krb5-1-6/src/clients/kdestroy/Makefile.in
new file mode 100644
index 000000000..51cf5cf5d
--- /dev/null
+++ b/krb5-1-6/src/clients/kdestroy/Makefile.in
@@ -0,0 +1,51 @@
+thisconfigdir=../..
+myfulldir=clients/kdestroy
+mydir=clients/kdestroy
+BUILDTOP=$(REL)..$(S)..
+DEFS=
+
+SRCS=kdestroy.c
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KDESTROY=$(OUTPRE)kdestroy.exe
+
+##WIN32##EXERES=$(KDESTROY:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKDESTROY_APP -fo $@ -r $**
+
+all-unix:: kdestroy
+##WIN32##all-windows:: $(KDESTROY)
+
+kdestroy: kdestroy.o $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $@ kdestroy.o $(KRB4COMPAT_LIBS)
+
+##WIN32##$(KDESTROY): $(OUTPRE)kdestroy.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32##	link $(EXE_LINKOPTS) -out:$@ $**
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) kdestroy.o kdestroy
+
+install-unix::
+	for f in kdestroy; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kdestroy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  kdestroy.c
diff --git a/krb5-1-6/src/clients/kdestroy/kdestroy.M b/krb5-1-6/src/clients/kdestroy/kdestroy.M
new file mode 100644
index 000000000..c7d0135b7
--- /dev/null
+++ b/krb5-1-6/src/clients/kdestroy/kdestroy.M
@@ -0,0 +1,104 @@
+.\" clients/kdestroy/kdestroy.M
+.\"
+.\" Copyright 1992 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KDESTROY 1
+.SH NAME
+kdestroy \- destroy Kerberos tickets
+.SH SYNOPSIS
+.B kdestroy
+[\fB\-5\fP] [\fB\-4\fP] [\fB\-q\fP] [\fB\-c\fP \fIcache_name]
+.br
+.SH DESCRIPTION
+The
+.I kdestroy
+utility destroys the user's active Kerberos authorization tickets by
+writing zeros to the specified credentials cache that contains them.  If
+the credentials cache is not specified, the default credentials cache is
+destroyed.
+If kdestroy was built with Kerberos 4 support, the default behavior is to
+destroy both Kerberos 5 and Kerberos 4 credentials.  Otherwise, kdestroy 
+will default to destroying only Kerberos 5 credentials.
+.SH OPTIONS
+.TP
+.B \-5
+destroy Kerberos 5 credentials.  This overrides whatever the default built-in
+behavior may be.  This option may be used with
+.B \-4
+.
+.TP
+.B \-4
+destroy Kerberos 4 credentials.  This overrides whatever the default built-in
+behavior may be.  This option is only available if kinit was built
+with Kerberos 4 compatibility.  This option may be used with 
+.B \-5
+.
+.TP
+.B \-q
+Run quietly.  Normally
+.B kdestroy
+beeps if it fails to destroy the user's tickets.  The
+.B \-q
+flag suppresses this behavior.
+.TP
+\fB\-c\fP \fIcache_name\fP
+use
+.I cache_name
+as the credentials (ticket) cache name and location; if this option is
+not used, the default cache name and location are used.
+.sp
+The default credentials cache may vary between systems.  If the
+.SM KRB5CCNAME
+environment variable is set, its value is used to name the default
+ticket cache.
+.PP
+Most installations recommend that you place the
+.I kdestroy
+command in your
+.I .logout
+file, so that your tickets are destroyed automatically when you log out.
+.SH ENVIRONMENT
+.B Kdestroy
+uses the following environment variables:
+.TP "\w'.SM KRB5CCNAME\ \ 'u"
+.SM KRB5CCNAME
+Location of the Kerberos 5 credentials (ticket) cache.
+.TP "\w'.SM KRBTKFILE\ \ 'u"
+.SM KRBTKFILE
+Filename of the Kerberos 4 credentials (ticket) cache.
+.SH FILES
+.TP "\w'/tmp/krb5cc_[uid]\ \ 'u"
+/tmp/krb5cc_[uid]
+default location of Kerberos 5 credentials cache 
+([uid] is the decimal UID of the user).
+.TP "\w'/tmp/tkt[uid]\ \ 'u"
+/tmp/tkt[uid]
+default location of Kerberos 4 credentials cache 
+([uid] is the decimal UID of the user).
+.SH SEE ALSO
+kinit(1), klist(1), krb5(3)
+.SH BUGS
+.PP
+Only the tickets in the specified credentials cache are destroyed.
+Separate ticket caches are used to hold root instance and password
+changing tickets.  These should probably be destroyed too, or all of a
+user's tickets kept in a single credentials cache.
diff --git a/krb5-1-6/src/clients/kdestroy/kdestroy.c b/krb5-1-6/src/clients/kdestroy/kdestroy.c
new file mode 100644
index 000000000..f7bcef7cd
--- /dev/null
+++ b/krb5-1-6/src/clients/kdestroy/kdestroy.c
@@ -0,0 +1,228 @@
+/*
+ * clients/kdestroy/kdestroy.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Destroy the contents of your credential cache.
+ */
+
+#include "autoconf.h"
+#include <krb5.h>
+#include <com_err.h>
+#include <string.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+
+#ifdef __STDC__
+#define BELL_CHAR '\a'
+#else
+#define BELL_CHAR '\007'
+#endif
+
+extern int optind;
+extern char *optarg;
+
+#ifndef _WIN32
+#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x))
+#else
+#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
+#endif
+
+char *progname;
+
+int got_k5 = 0;
+int got_k4 = 0;
+
+int default_k5 = 1;
+#ifdef KRB5_KRB4_COMPAT
+int default_k4 = 1;
+#else
+int default_k4 = 0;
+#endif
+
+
+static void usage()
+{
+#define KRB_AVAIL_STRING(x) ((x)?"available":"not available")
+
+    fprintf(stderr, "Usage: %s [-5] [-4] [-q] [-c cache_name]\n", progname);
+    fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
+    fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
+    fprintf(stderr, "\t   (Default is %s%s%s%s)\n",
+	    default_k5?"Kerberos 5":"",
+	    (default_k5 && default_k4)?" and ":"",
+	    default_k4?"Kerberos 4":"",
+	    (!default_k5 && !default_k4)?"neither":"");
+    fprintf(stderr, "\t-q quiet mode\n");
+    fprintf(stderr, "\t-c specify name of credentials cache\n");
+    exit(2);
+}
+
+int
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    krb5_context kcontext;
+    krb5_error_code retval;
+    int c;
+    krb5_ccache cache = NULL;
+    char *cache_name = NULL;
+    int code = 0;
+#ifdef KRB5_KRB4_COMPAT
+    int v4code = 0;
+    int v4 = 1;
+#endif
+    int errflg = 0;
+    int quiet = 0;
+
+    int use_k5 = 0;
+    int use_k4 = 0;
+
+    progname = GET_PROGNAME(argv[0]);
+
+    got_k5 = 1;
+#ifdef KRB5_KRB4_COMPAT
+    got_k4 = 1;
+#endif
+
+    while ((c = getopt(argc, argv, "54qc:")) != -1) {
+	switch (c) {
+	case 'q':
+	    quiet = 1;
+	    break;	
+	case 'c':
+	    if (cache_name) {
+		fprintf(stderr, "Only one -c option allowed\n");
+		errflg++;
+	    } else {
+		cache_name = optarg;
+	    }
+	    break;
+	case '4':
+	    if (!got_k4)
+	    {
+#ifdef KRB5_KRB4_COMPAT
+		fprintf(stderr, "Kerberos 4 support could not be loaded\n");
+#else
+		fprintf(stderr, "This was not built with Kerberos 4 support\n");
+#endif
+		exit(3);
+	    }
+	    use_k4 = 1;
+	    break;
+	case '5':
+	    if (!got_k5)
+	    {
+		fprintf(stderr, "Kerberos 5 support could not be loaded\n");
+		exit(3);
+	    }
+	    use_k5 = 1;
+	    break;
+	case '?':
+	default:
+	    errflg++;
+	    break;
+	}
+    }
+
+    if (optind != argc)
+	errflg++;
+    
+    if (errflg) {
+	usage();
+    }
+
+    if (!use_k5 && !use_k4)
+    {
+	use_k5 = default_k5;
+	use_k4 = default_k4;
+    }
+
+    if (!use_k5)
+	got_k5 = 0;
+    if (!use_k4)
+	got_k4 = 0;
+
+    if (got_k5) {
+	retval = krb5_init_context(&kcontext);
+	if (retval) {
+	    com_err(progname, retval, "while initializing krb5");
+	    exit(1);
+	}
+
+	if (cache_name) {
+#ifdef KRB5_KRB4_COMPAT
+	    v4 = 0;	/* Don't do v4 if doing v5 and cache name given. */
+#endif
+	    code = krb5_cc_resolve (kcontext, cache_name, &cache);
+	    if (code != 0) {
+		com_err (progname, code, "while resolving %s", cache_name);
+		exit(1);
+	    }
+	} else {
+	    code = krb5_cc_default(kcontext, &cache);
+	    if (code) {
+		com_err(progname, code, "while getting default ccache");
+		exit(1);
+	    }
+	}
+
+	code = krb5_cc_destroy (kcontext, cache);
+	if (code != 0) {
+	    com_err (progname, code, "while destroying cache");
+	    if (code != KRB5_FCC_NOFILE) {
+		if (quiet)
+		    fprintf(stderr, "Ticket cache NOT destroyed!\n");
+		else {
+		    fprintf(stderr, "Ticket cache %cNOT%c destroyed!\n", 
+			    BELL_CHAR, BELL_CHAR);
+		}
+		errflg = 1;
+	    }
+	}
+    }
+#ifdef KRB5_KRB4_COMPAT
+    if (got_k4 && v4) {
+	v4code = dest_tkt();
+	if (v4code == KSUCCESS && code != 0)
+	    fprintf(stderr, "Kerberos 4 ticket cache destroyed.\n");
+	if (v4code != KSUCCESS && v4code != RET_TKFIL) {
+	    if (quiet)
+		fprintf(stderr, "Kerberos 4 ticket cache NOT destroyed!\n");
+	    else
+		fprintf(stderr, "Kerberos 4 ticket cache %cNOT%c destroyed!\n",
+			BELL_CHAR, BELL_CHAR);
+	    errflg = 1;
+	}
+    }
+#endif
+    return errflg;
+}
diff --git a/krb5-1-6/src/clients/kinit/Makefile.in b/krb5-1-6/src/clients/kinit/Makefile.in
new file mode 100644
index 000000000..ead20cf12
--- /dev/null
+++ b/krb5-1-6/src/clients/kinit/Makefile.in
@@ -0,0 +1,54 @@
+thisconfigdir=../..
+myfulldir=clients/kinit
+mydir=clients/kinit
+BUILDTOP=$(REL)..$(S)..
+DEFS=
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SRCS=kinit.c
+
+##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows
+##WIN32##DEFINES=-DGETOPT_LONG
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KINIT=$(OUTPRE)kinit.exe
+
+##WIN32##EXERES=$(KINIT:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKINIT_APP -fo $@ -r $**
+
+all-unix:: kinit
+##WIN32##all-windows:: $(KINIT)
+
+kinit: kinit.o $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $@ kinit.o $(KRB4COMPAT_LIBS)
+
+##WIN32##$(KINIT): $(OUTPRE)kinit.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib $(KLIB) $(CLIB) $(EXERES)
+##WIN32##	link $(EXE_LINKOPTS) -out:$@ $** advapi32.lib
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) kinit.o kinit
+
+install-unix::
+	for f in kinit; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kinit.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  kinit.c
diff --git a/krb5-1-6/src/clients/kinit/kinit.M b/krb5-1-6/src/clients/kinit/kinit.M
new file mode 100644
index 000000000..eca8be341
--- /dev/null
+++ b/krb5-1-6/src/clients/kinit/kinit.M
@@ -0,0 +1,225 @@
+.\" clients/kinit/kinit.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KINIT 1
+.SH NAME
+kinit \- obtain and cache Kerberos ticket-granting ticket
+.SH SYNOPSIS
+.TP
+.B kinit
+.ad l
+[\fB\-5\fP]
+[\fB\-4\fP]
+[\fB\-V\fP]
+[\fB\-l\fP \fIlifetime\fP] [\fB\-s\fP \fIstart_time\fP]
+[\fB\-r\fP \fIrenewable_life\fP]
+[\fB\-p\fP | \fB\-P\fP]
+[\fB\-f\fP | \fB\-F\fP]
+[\fB\-a\fP]
+[\fB\-A\fP]
+[\fB\-v\fP] [\fB\-R\fP]
+[\fB\-k\fP [\fB\-t\fP \fIkeytab_file\fP]] [\fB\-c\fP \fIcache_name\fP]
+[\fB\-S\fP \fIservice_name\fP]
+[\fB\-X\fP \fIattribute\fP[=\fIvalue\fP]]
+[\fIprincipal\fP]
+.ad b
+.br
+.SH DESCRIPTION
+.I kinit
+obtains and caches an initial ticket-granting ticket for
+.IR principal .  
+The typical default behavior is to acquire only
+Kerberos 5 tickets.  However, if kinit was built with both 
+Kerberos 4 support and with the default behavior of acquiring both
+types of tickets, it will try to acquire both Kerberos 5 and Kerberos 4
+by default.
+Any documentation particular to Kerberos 4 does not apply if Kerberos 4
+support was not built into kinit.
+.SH OPTIONS
+.TP
+.B \-5
+get Kerberos 5 tickets.  This overrides whatever the default built-in
+behavior may be.  This option may be used with
+.B \-4
+.
+.TP
+.B \-4
+get Kerberos 4 tickets.  This overrides whatever the default built-in
+behavior may be.  This option is only available if kinit was built
+with Kerberos 4 compatibility.  This option may be used with 
+.B \-5
+.
+.TP
+.B \-V
+display verbose output.
+.TP
+\fB\-l\fP \fIlifetime\fP
+requests a ticket with the lifetime
+.IR lifetime .
+The value for
+.I lifetime
+must be followed immediately by one of the following delimiters:
+.sp
+.nf
+.in +.3i
+\fBs\fP  seconds
+\fBm\fP  minutes
+\fBh\fP  hours
+\fBd\fP  days
+.in -.3i
+.fi
+.sp
+as in "kinit -l 90m".  You cannot mix units; a value of `3h30m' will
+result in an error.
+.sp
+If the
+.B \-l
+option is not specified, the default ticket lifetime (configured by each
+site) is used.  Specifying a ticket lifetime longer than the maximum
+ticket lifetime (configured by each site) results in a ticket with the
+maximum lifetime.
+.TP
+\fB\-s\fP \fIstart_time\fP
+requests a postdated ticket, valid starting at
+.IR start_time .
+Postdated tickets are issued with the
+.I invalid
+flag set, and need to be fed back to the kdc before use.
+(Not applicable to Kerberos 4.)
+.TP
+\fB\-r\fP \fIrenewable_life\fP
+requests renewable tickets, with a total lifetime of
+.IR renewable_life .
+The duration is in the same format as the
+.B \-l
+option, with the same delimiters.  (Not applicable to Kerberos 4.)
+.TP
+.B \-f
+request forwardable tickets.  (Not applicable to Kerberos 4.)
+.TP
+.B \-F
+do not request forwardable tickets.  (Not applicable to Kerberos 4.)
+.TP
+.B \-p
+request proxiable tickets.  (Not applicable to Kerberos 4.)
+.TP
+.B \-P
+do not request proxiable tickets.  (Not applicable to Kerberos 4.)
+.TP
+.B \-a
+request tickets with the local address[es].  (Not applicable to Kerberos 4.)
+.TP
+.B \-A
+request address-less tickets.  (Not applicable to Kerberos 4.)
+.TP
+.B \-v
+requests that the ticket granting ticket in the cache (with the 
+.I invalid
+flag set) be passed to the kdc for validation.  If the ticket is within
+its requested time range, the cache is replaced with the validated
+ticket.  (Not applicable to Kerberos 4.)
+.TP
+.B \-R
+requests renewal of the ticket-granting ticket.  Note that an expired
+ticket cannot be renewed, even if the ticket is still within its
+renewable life.  When using this option with Kerberos 4, the kdc must
+support Kerberos 5 to Kerberos 4 ticket conversion.
+.TP
+\fB\-k\fP [\fB\-t\fP \fIkeytab_file\fP]
+requests a host ticket, obtained from a key in the local host's
+.I keytab
+file.  The name and location of the keytab file may be specified with
+the
+.B \-t
+.I keytab_file
+option; otherwise the default name and location will be used.  When using
+this option with Kerberos 4, the kdc must support Kerberos 5 to Kerberos 4
+ticket conversion.
+.TP
+\fB\-c\fP \fIcache_name\fP
+use
+.I cache_name
+as the Kerberos 5 credentials (ticket) cache name and location; if this 
+option is not used, the default cache name and location are used.
+.sp
+The default credentials cache may vary between systems.  If the
+.B KRB5CCNAME
+environment variable is set, its value is used to name the default
+ticket cache.  Any existing contents of the cache are destroyed by
+.IR kinit .
+(Note: The default name for Kerberos 4 comes from the
+.B KRBTKFILE
+environment variable.  This option does not apply to Kerberos 4.)
+.TP
+\fB\-S\fP \fIservice_name\fP
+specify an alternate service name to use when
+getting initial tickets.  (Applicable to Kerberos 5 or if using both
+Kerberos 5 and Kerberos 4 with a kdc that supports Kerberos 5 to Kerberos 4
+ticket conversion.)
+.TP
+\fB\-X\fP \fIattribute\fP[=\fIvalue\fP]
+specify a pre\-authentication attribute and value to be passed to
+pre\-authentication plugins.  The acceptable \fIattribute\fP and
+\fIvalue\fP values vary from pre\-authentication plugin to plugin.
+This option may be specified multiple times to specify multiple
+attributes.  If no \fIvalue\fP is specified, it is assumed to be
+"yes".
+.sp
+.nf
+The following attributes are recognized by the OpenSSL pkinit
+pre-authentication mechanism:
+.in +.3i
+\fBX509_user_identity\fP=\fIvalue\fP
+   specify where to find user's X509 identity information
+\fBX509_anchors\fP=\fIvalue\fP
+   specify where to find trusted X509 anchor information
+\fBflag_RSA_PROTOCOL\fP[=yes]
+   specify use of RSA, rather than the default Diffie-Hellman protocol
+.in -.3i
+.fi
+.sp
+.SH ENVIRONMENT
+.B Kinit
+uses the following environment variables:
+.TP "\w'.SM KRB5CCNAME\ \ 'u"
+.SM KRB5CCNAME
+Location of the Kerberos 5 credentials (ticket) cache.
+.TP "\w'.SM KRBTKFILE\ \ 'u"
+.SM KRBTKFILE
+Filename of the Kerberos 4 credentials (ticket) cache.
+.SH FILES
+.TP "\w'/tmp/krb5cc_[uid]\ \ 'u"
+/tmp/krb5cc_[uid]
+default location of Kerberos 5 credentials cache 
+([uid] is the decimal UID of the user).
+.TP "\w'/tmp/tkt[uid]\ \ 'u"
+/tmp/tkt[uid]
+default location of Kerberos 4 credentials cache 
+([uid] is the decimal UID of the user).
+.TP
+/etc/krb5.keytab
+default location for the local host's
+.B keytab
+file.
+.SH SEE ALSO
+klist(1), kdestroy(1), kerberos(1)
diff --git a/krb5-1-6/src/clients/kinit/kinit.c b/krb5-1-6/src/clients/kinit/kinit.c
new file mode 100644
index 000000000..1add7d9b4
--- /dev/null
+++ b/krb5-1-6/src/clients/kinit/kinit.c
@@ -0,0 +1,1213 @@
+/*
+ * clients/kinit/kinit.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Initialize a credentials cache.
+ */
+
+#include "autoconf.h"
+#include <krb5.h>
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#define HAVE_KRB524
+#else
+#undef HAVE_KRB524
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+#include <com_err.h>
+
+#ifdef GETOPT_LONG
+#include <getopt.h>
+#else
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#ifdef sun
+/* SunOS4 unistd didn't declare these; okay to make unconditional?  */
+extern int optind;
+extern char *optarg;
+#endif /* sun */
+#else
+extern int optind;
+extern char *optarg;
+extern int getopt();
+#endif /* HAVE_UNISTD_H */
+#endif /* GETOPT_LONG */
+
+#ifndef _WIN32
+#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x))
+#else
+#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+static 
+char * get_name_from_os()
+{
+    struct passwd *pw;
+    if ((pw = getpwuid((int) getuid())))
+	return pw->pw_name;
+    return 0;
+}
+#else /* HAVE_PWD_H */
+#ifdef _WIN32
+static
+char * get_name_from_os()
+{
+    static char name[1024];
+    DWORD name_size = sizeof(name);
+    if (GetUserName(name, &name_size)) {
+	name[sizeof(name)-1] = 0; /* Just to be extra safe */
+	return name;
+    } else {
+	return 0;
+    }
+}
+#else /* _WIN32 */
+static
+char * get_name_from_os()
+{
+    return 0;
+}
+#endif /* _WIN32 */
+#endif /* HAVE_PWD_H */
+
+static char* progname_v5 = 0;
+#ifdef KRB5_KRB4_COMPAT
+static char* progname_v4 = 0;
+static char* progname_v524 = 0;
+#endif
+
+static int got_k5 = 0;
+static int got_k4 = 0;
+
+static int default_k5 = 1;
+#if defined(KRB5_KRB4_COMPAT) && defined(KINIT_DEFAULT_BOTH)
+static int default_k4 = 1;
+#else
+static int default_k4 = 0;
+#endif
+
+static int authed_k5 = 0;
+static int authed_k4 = 0;
+
+#define KRB4_BACKUP_DEFAULT_LIFE_SECS 24*60*60 /* 1 day */
+
+typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
+
+struct k_opts
+{
+    /* in seconds */
+    krb5_deltat starttime;
+    krb5_deltat lifetime;
+    krb5_deltat rlife;
+
+    int forwardable;
+    int proxiable;
+    int addresses;
+
+    int not_forwardable;
+    int not_proxiable;
+    int no_addresses;
+
+    int verbose;
+
+    char* principal_name;
+    char* service_name;
+    char* keytab_name;
+    char* k5_cache_name;
+    char* k4_cache_name;
+
+    action_type action;
+
+    int num_pa_opts;
+    krb5_gic_opt_pa_data *pa_opts;
+};
+
+struct k5_data
+{
+    krb5_context ctx;
+    krb5_ccache cc;
+    krb5_principal me;
+    char* name;
+};
+
+struct k4_data
+{
+    krb5_deltat lifetime;
+#ifdef KRB5_KRB4_COMPAT
+    char aname[ANAME_SZ + 1];
+    char inst[INST_SZ + 1];
+    char realm[REALM_SZ + 1];
+    char name[ANAME_SZ + 1 + INST_SZ + 1 + REALM_SZ + 1];
+#endif
+};
+
+#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' },
+    { "noproxiable", 0, NULL, 'P' },
+    { "addresses", 0, NULL, 'a'},
+    { "forwardable", 0, NULL, 'f' },
+    { "proxiable", 0, NULL, 'p' },
+    { "noaddresses", 0, NULL, 'A' },
+    { NULL, 0, NULL, 0 }
+};
+
+#define GETOPT(argc, argv, str) getopt_long(argc, argv, str, long_options, 0)
+#else
+#define GETOPT(argc, argv, str) getopt(argc, argv, str)
+#endif
+
+static void
+usage(progname)
+     char *progname;
+{
+#define USAGE_BREAK "\n\t"
+
+#ifdef GETOPT_LONG
+#define USAGE_LONG_FORWARDABLE " | --forwardable | --noforwardable"
+#define USAGE_LONG_PROXIABLE   " | --proxiable | --noproxiable"
+#define USAGE_LONG_ADDRESSES   " | --addresses | --noaddresses"
+#define USAGE_BREAK_LONG       USAGE_BREAK
+#else
+#define USAGE_LONG_FORWARDABLE ""
+#define USAGE_LONG_PROXIABLE   ""
+#define USAGE_LONG_ADDRESSES   ""
+#define USAGE_BREAK_LONG       ""
+#endif
+
+    fprintf(stderr, "Usage: %s [-5] [-4] [-V] "
+	    "[-l lifetime] [-s start_time] "
+	    USAGE_BREAK
+	    "[-r renewable_life] "
+	    "[-f | -F" USAGE_LONG_FORWARDABLE "] "
+	    USAGE_BREAK_LONG
+	    "[-p | -P" USAGE_LONG_PROXIABLE "] "
+	    USAGE_BREAK_LONG
+	    "[-a | -A" USAGE_LONG_ADDRESSES "] "
+	    USAGE_BREAK
+	    "[-v] [-R] "
+	    "[-k [-t keytab_file]] "
+	    "[-c cachename] "
+	    USAGE_BREAK
+	    "[-S service_name]"
+	    "[-X <attribute>[=<value>]] [principal]"
+	    "\n\n", 
+	    progname);
+
+#define KRB_AVAIL_STRING(x) ((x)?"available":"not available")
+
+#define OPTTYPE_KRB5   "5"
+#define OPTTYPE_KRB4   "4"
+#define OPTTYPE_EITHER "Either 4 or 5"
+#ifdef HAVE_KRB524
+#define OPTTYPE_BOTH "5, or both 5 and 4"
+#else
+#define OPTTYPE_BOTH "5"
+#endif
+
+#ifdef KRB5_KRB4_COMPAT
+#define USAGE_OPT_FMT "%s%-50s%s\n"
+#define ULINE(indent, col1, col2) \
+fprintf(stderr, USAGE_OPT_FMT, indent, col1, col2)
+#else
+#define USAGE_OPT_FMT "%s%s\n"
+#define ULINE(indent, col1, col2) \
+fprintf(stderr, USAGE_OPT_FMT, indent, col1)
+#endif
+
+    ULINE("    ", "options:", "valid with Kerberos:");
+    fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
+    fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
+    fprintf(stderr, "\t   (Default behavior is to try %s%s%s%s)\n",
+	    default_k5?"Kerberos 5":"",
+	    (default_k5 && default_k4)?" and ":"",
+	    default_k4?"Kerberos 4":"",
+	    (!default_k5 && !default_k4)?"neither":"");
+    ULINE("\t", "-V verbose",                   OPTTYPE_EITHER);
+    ULINE("\t", "-l lifetime",                  OPTTYPE_EITHER);
+    ULINE("\t", "-s start time",                OPTTYPE_KRB5);
+    ULINE("\t", "-r renewable lifetime",        OPTTYPE_KRB5);
+    ULINE("\t", "-f forwardable",               OPTTYPE_KRB5);
+    ULINE("\t", "-F not forwardable",           OPTTYPE_KRB5);
+    ULINE("\t", "-p proxiable",                 OPTTYPE_KRB5);
+    ULINE("\t", "-P not proxiable",             OPTTYPE_KRB5);
+    ULINE("\t", "-a include addresses",         OPTTYPE_KRB5);
+    ULINE("\t", "-A do not include addresses",  OPTTYPE_KRB5);
+    ULINE("\t", "-v validate",                  OPTTYPE_KRB5);
+    ULINE("\t", "-R renew",                     OPTTYPE_BOTH);
+    ULINE("\t", "-k use keytab",                OPTTYPE_BOTH);
+    ULINE("\t", "-t filename of keytab to use", OPTTYPE_BOTH);
+    ULINE("\t", "-c Kerberos 5 cache name",     OPTTYPE_KRB5);
+    /* This options is not yet available: */
+    /* ULINE("\t", "-C Kerberos 4 cache name",     OPTTYPE_KRB4); */
+    ULINE("\t", "-S service",                   OPTTYPE_BOTH);
+    ULINE("\t", "-X <attribute>[=<value>]",     OPTTYPE_KRB5);
+    exit(2);
+}
+
+static krb5_context errctx;
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+				 const char *fmt, va_list args)
+{
+    const char *emsg;
+    emsg = krb5_get_error_message (errctx, code);
+    fprintf (stderr, "%s: %s ", myprog, emsg);
+    krb5_free_error_message (errctx, emsg);
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+}
+
+static int
+add_preauth_opt(struct k_opts *opts, char *av)
+{
+    char *sep, *v;
+    krb5_gic_opt_pa_data *p, *x;
+
+    if (opts->num_pa_opts == 0) {
+	opts->pa_opts = malloc(sizeof(krb5_gic_opt_pa_data));
+	if (opts->pa_opts == NULL)
+	    return ENOMEM;
+    } else {
+	size_t newsize = (opts->num_pa_opts + 1) * sizeof(krb5_gic_opt_pa_data);
+	x = realloc(opts->pa_opts, newsize);
+	if (x == NULL)
+	    return ENOMEM;
+	opts->pa_opts = x;
+    }
+    p = &opts->pa_opts[opts->num_pa_opts];
+    sep = strchr(av, '=');
+    if (sep) {
+	*sep = '\0';
+	v = ++sep;
+	p->value = v;
+    } else {
+	p->value = "yes";
+    }
+    p->attr = av;
+    opts->num_pa_opts++;
+    return 0;
+}
+
+static char *
+parse_options(argc, argv, opts, progname)
+    int argc;
+    char **argv;
+    struct k_opts* opts;
+    char *progname;
+{
+    krb5_error_code code;
+    int errflg = 0;
+    int use_k4 = 0;
+    int use_k5 = 0;
+    int i;
+
+    while ((i = GETOPT(argc, argv, "r:fpFP54aAVl:s:c:kt:RS:vX:"))
+	   != -1) {
+	switch (i) {
+	case 'V':
+	    opts->verbose = 1;
+	    break;
+	case 'l':
+	    /* Lifetime */
+	    code = krb5_string_to_deltat(optarg, &opts->lifetime);
+	    if (code != 0 || opts->lifetime == 0) {
+		fprintf(stderr, "Bad lifetime value %s\n", optarg);
+		errflg++;
+	    }
+	    break;
+	case 'r':
+	    /* Renewable Time */
+	    code = krb5_string_to_deltat(optarg, &opts->rlife);
+	    if (code != 0 || opts->rlife == 0) {
+		fprintf(stderr, "Bad lifetime value %s\n", optarg);
+		errflg++;
+	    }
+	    break;
+	case 'f':
+	    opts->forwardable = 1;
+	    break;
+	case 'F':
+	    opts->not_forwardable = 1;
+	    break;
+	case 'p':
+	    opts->proxiable = 1;
+	    break;
+	case 'P':
+	    opts->not_proxiable = 1;
+	    break;
+	case 'a':
+	    opts->addresses = 1;
+	    break;
+	case 'A':
+	    opts->no_addresses = 1;
+	    break;
+       	case 's':
+	    code = krb5_string_to_deltat(optarg, &opts->starttime);
+	    if (code != 0 || opts->starttime == 0) {
+		krb5_timestamp abs_starttime;
+
+		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 {
+		    opts->starttime = abs_starttime - time(0);
+		}
+	    }
+	    break;
+	case 'S':
+	    opts->service_name = optarg;
+	    break;
+	case 'k':
+	    opts->action = INIT_KT;
+	    break;
+	case 't':
+	    if (opts->keytab_name)
+	    {
+		fprintf(stderr, "Only one -t option allowed.\n");
+		errflg++;
+	    } else {
+		opts->keytab_name = optarg;
+	    }
+	    break;
+	case 'R':
+	    opts->action = RENEW;
+	    break;
+	case 'v':
+	    opts->action = VALIDATE;
+	    break;
+       	case 'c':
+	    if (opts->k5_cache_name)
+	    {
+		fprintf(stderr, "Only one -c option allowed\n");
+		errflg++;
+	    } else {
+		opts->k5_cache_name = optarg;
+	    }
+	    break;
+	case 'X':
+	    code = add_preauth_opt(opts, optarg);
+	    if (code)
+	    {
+		com_err(progname, code, "while adding preauth option");
+		errflg++;
+	    }
+	    break;
+#if 0
+	    /*
+	      A little more work is needed before we can enable this
+	      option.
+	    */
+	case 'C':
+	    if (opts->k4_cache_name)
+	    {
+		fprintf(stderr, "Only one -C option allowed\n");
+		errflg++;
+	    } else {
+		opts->k4_cache_name = optarg;
+	    }
+	    break;
+#endif
+	case '4':
+	    if (!got_k4)
+	    {
+#ifdef KRB5_KRB4_COMPAT
+		fprintf(stderr, "Kerberos 4 support could not be loaded\n");
+#else
+		fprintf(stderr, "This was not built with Kerberos 4 support\n");
+#endif
+		exit(3);
+	    }
+	    use_k4 = 1;
+	    break;
+	case '5':
+	    if (!got_k5)
+	    {
+		fprintf(stderr, "Kerberos 5 support could not be loaded\n");
+		exit(3);
+	    }
+	    use_k5 = 1;
+	    break;
+	default:
+	    errflg++;
+	    break;
+	}
+    }
+
+    if (opts->forwardable && opts->not_forwardable)
+    {
+	fprintf(stderr, "Only one of -f and -F allowed\n");
+	errflg++;
+    }
+    if (opts->proxiable && opts->not_proxiable)
+    {
+	fprintf(stderr, "Only one of -p and -P allowed\n");
+	errflg++;
+    }
+    if (opts->addresses && opts->no_addresses)
+    {
+	fprintf(stderr, "Only one of -a and -A allowed\n");
+	errflg++;
+    }
+
+    if (argc - optind > 1) {
+	fprintf(stderr, "Extra arguments (starting with \"%s\").\n",
+		argv[optind+1]);
+	errflg++;
+    }
+
+    /* At this point, if errorless, we know we only have one option
+       selection */
+    if (!use_k5 && !use_k4) {
+	use_k5 = default_k5;
+	use_k4 = default_k4;
+    }
+
+    /* Now, we encode the OPTTYPE stuff here... */
+    if (!use_k5 &&
+	(opts->starttime || opts->rlife || opts->forwardable || 
+	 opts->proxiable || opts->addresses || opts->not_forwardable || 
+	 opts->not_proxiable || opts->no_addresses || 
+	 (opts->action == VALIDATE) || opts->k5_cache_name))
+    {
+	fprintf(stderr, "Specified option that requires Kerberos 5\n");
+	errflg++;
+    }
+    if (!use_k4 &&
+	opts->k4_cache_name)
+    {
+	fprintf(stderr, "Specified option that require Kerberos 4\n");
+	errflg++;
+    }
+    if (
+#ifdef HAVE_KRB524
+	!use_k5
+#else
+	use_k4
+#endif
+	&& (opts->service_name || opts->keytab_name || 
+	    (opts->action == INIT_KT) || (opts->action == RENEW))
+	)
+    {
+	fprintf(stderr, "Specified option that requires Kerberos 5\n");
+	errflg++;
+    }
+
+    if (errflg) {
+	usage(progname);
+    }
+
+    got_k5 = got_k5 && use_k5;
+    got_k4 = got_k4 && use_k4;
+
+    opts->principal_name = (optind == argc-1) ? argv[optind] : 0;
+    return opts->principal_name;
+}
+
+static int
+k5_begin(opts, k5, k4)
+    struct k_opts* opts;
+struct k5_data* k5;
+struct k4_data* k4;
+{
+    char* progname = progname_v5;
+    krb5_error_code code = 0;
+
+    if (!got_k5)
+	return 0;
+
+    code = krb5_init_context(&k5->ctx);
+    if (code) {
+	com_err(progname, code, "while initializing Kerberos 5 library");
+	return 0;
+    }
+    errctx = k5->ctx;
+    if (opts->k5_cache_name)
+    {
+	code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc);
+	if (code != 0) {
+	    com_err(progname, code, "resolving ccache %s",
+		    opts->k5_cache_name);
+	    return 0;
+	}
+    } 
+    else
+    {
+	if ((code = krb5_cc_default(k5->ctx, &k5->cc))) {
+	    com_err(progname, code, "while getting default ccache");
+	    return 0;
+	}
+    }
+
+    if (opts->principal_name)
+    {
+	/* Use specified name */
+	if ((code = krb5_parse_name(k5->ctx, opts->principal_name, 
+				    &k5->me))) {
+	    com_err(progname, code, "when parsing name %s", 
+		    opts->principal_name);
+	    return 0;
+	}
+    }
+    else
+    {
+	/* No principal name specified */
+	if (opts->action == INIT_KT) {
+	    /* Use the default host/service name */
+	  code = krb5_sname_to_principal(k5->ctx, NULL, NULL,
+					 KRB5_NT_SRV_HST, &k5->me);
+	  if (code) {
+	    com_err(progname, code,
+		    "when creating default server principal name");
+	    return 0;
+	  }
+	} else {
+	  /* Get default principal from cache if one exists */
+	  code = krb5_cc_get_principal(k5->ctx, k5->cc, 
+				       &k5->me);
+	  if (code)
+	    {
+	      char *name = get_name_from_os();
+	      if (!name)
+		{
+		  fprintf(stderr, "Unable to identify user\n");
+		  return 0;
+		}
+	      if ((code = krb5_parse_name(k5->ctx, name, 
+					  &k5->me)))
+		{
+		  com_err(progname, code, "when parsing name %s", 
+			  name);
+		  return 0;
+		}
+	    }
+	}
+    }
+
+    code = krb5_unparse_name(k5->ctx, k5->me, &k5->name);
+    if (code) {
+	com_err(progname, code, "when unparsing name");
+	return 0;
+    }
+    opts->principal_name = k5->name;
+
+#ifdef KRB5_KRB4_COMPAT
+    if (got_k4)
+    {
+	/* Translate to a Kerberos 4 principal */
+	code = krb5_524_conv_principal(k5->ctx, k5->me,
+				       k4->aname, k4->inst, k4->realm);
+	if (code) {
+	    k4->aname[0] = 0;
+	    k4->inst[0] = 0;
+	    k4->realm[0] = 0;
+	}
+    }
+#endif
+    return 1;
+}
+
+static void
+k5_end(k5)
+    struct k5_data* k5;
+{
+    if (k5->name)
+	krb5_free_unparsed_name(k5->ctx, k5->name);
+    if (k5->me)
+	krb5_free_principal(k5->ctx, k5->me);
+    if (k5->cc)
+	krb5_cc_close(k5->ctx, k5->cc);
+    if (k5->ctx)
+	krb5_free_context(k5->ctx);
+    errctx = NULL;
+    memset(k5, 0, sizeof(*k5));
+}
+
+static int
+k4_begin(opts, k4)
+    struct k_opts* opts;
+    struct k4_data* k4;
+{
+#ifdef KRB5_KRB4_COMPAT
+    char* progname = progname_v4;
+    int k_errno = 0;
+#endif
+
+    if (!got_k4)
+	return 0;
+
+#ifdef KRB5_KRB4_COMPAT
+    if (k4->aname[0])
+	goto skip;
+
+    if (opts->principal_name)
+    {
+	/* Use specified name */
+        k_errno = kname_parse(k4->aname, k4->inst, k4->realm, 
+			      opts->principal_name);
+	if (k_errno)
+	{
+	    fprintf(stderr, "%s: %s\n", progname, 
+		    krb_get_err_text(k_errno));
+	    return 0;
+	}
+    } else {
+	/* No principal name specified */
+	if (opts->action == INIT_KT) {
+	    /* Use the default host/service name */
+	    /* XXX - need to add this functionality */
+	    fprintf(stderr, "%s: Kerberos 4 srvtab support is not "
+		    "implemented\n", progname);
+	    return 0;
+	} else {
+	    /* Get default principal from cache if one exists */
+	    k_errno = krb_get_tf_fullname(tkt_string(), k4->aname, 
+					  k4->inst, k4->realm);
+	    if (k_errno)
+	    {
+		char *name = get_name_from_os();
+		if (!name)
+		{
+		    fprintf(stderr, "Unable to identify user\n");
+		    return 0;
+		}
+		k_errno = kname_parse(k4->aname, k4->inst, k4->realm,
+				      name);
+		if (k_errno)
+		{
+		    fprintf(stderr, "%s: %s\n", progname, 
+			    krb_get_err_text(k_errno));
+		    return 0;
+		}
+	    }
+	}
+    }
+
+    if (!k4->realm[0])
+	krb_get_lrealm(k4->realm, 1);
+
+    if (k4->inst[0])
+	sprintf(k4->name, "%s.%s@%s", k4->aname, k4->inst, k4->realm);
+    else
+	sprintf(k4->name, "%s@%s", k4->aname, k4->realm);
+    opts->principal_name = k4->name;
+
+ skip:
+    if (k4->aname[0] && !k_isname(k4->aname))
+    {
+	fprintf(stderr, "%s: bad Kerberos 4 name format\n", progname);
+	return 0;
+    }
+
+    if (k4->inst[0] && !k_isinst(k4->inst))
+    {
+	fprintf(stderr, "%s: bad Kerberos 4 instance format\n", progname);
+	return 0;
+    }
+
+    if (k4->realm[0] && !k_isrealm(k4->realm))
+    {
+	fprintf(stderr, "%s: bad Kerberos 4 realm format\n", progname);
+	return 0;
+    }
+#endif /* KRB5_KRB4_COMPAT */
+    return 1;
+}
+
+static void
+k4_end(k4)
+    struct k4_data* k4;
+{
+    memset(k4, 0, sizeof(*k4));
+}
+
+#ifdef KRB5_KRB4_COMPAT
+static char stash_password[1024];
+static int got_password = 0;
+#endif /* KRB5_KRB4_COMPAT */
+
+static krb5_error_code
+KRB5_CALLCONV
+kinit_prompter(
+    krb5_context ctx,
+    void *data,
+    const char *name,
+    const char *banner,
+    int num_prompts,
+    krb5_prompt prompts[]
+    )
+{
+    int i;
+    krb5_prompt_type *types;
+    krb5_error_code rc =
+	krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts);
+    if (!rc && (types = krb5_get_prompt_types(ctx)))
+	for (i = 0; i < num_prompts; i++)
+	    if ((types[i] == KRB5_PROMPT_TYPE_PASSWORD) ||
+		(types[i] == KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN))
+	    {
+#ifdef KRB5_KRB4_COMPAT
+		strncpy(stash_password, prompts[i].reply->data,
+			sizeof(stash_password));
+		got_password = 1;
+#endif
+	    }
+    return rc;
+}
+
+static int
+k5_kinit(opts, k5)
+    struct k_opts* opts;
+    struct k5_data* k5;
+{
+    char* progname = progname_v5;
+    int notix = 1;
+    krb5_keytab keytab = 0;
+    krb5_creds my_creds;
+    krb5_error_code code = 0;
+    krb5_get_init_creds_opt *options = NULL;
+    int i;
+
+    if (!got_k5)
+	return 0;
+
+    code = krb5_get_init_creds_opt_alloc(k5->ctx, &options);
+    if (code)
+	goto cleanup;
+    memset(&my_creds, 0, sizeof(my_creds));
+
+    /*
+      From this point on, we can goto cleanup because my_creds is
+      initialized.
+    */
+
+    if (opts->lifetime)
+	krb5_get_init_creds_opt_set_tkt_life(options, opts->lifetime);
+    if (opts->rlife)
+	krb5_get_init_creds_opt_set_renew_life(options, opts->rlife);
+    if (opts->forwardable)
+	krb5_get_init_creds_opt_set_forwardable(options, 1);
+    if (opts->not_forwardable)
+	krb5_get_init_creds_opt_set_forwardable(options, 0);
+    if (opts->proxiable)
+	krb5_get_init_creds_opt_set_proxiable(options, 1);
+    if (opts->not_proxiable)
+	krb5_get_init_creds_opt_set_proxiable(options, 0);
+    if (opts->addresses)
+    {
+	krb5_address **addresses = NULL;
+	code = krb5_os_localaddr(k5->ctx, &addresses);
+	if (code != 0) {
+	    com_err(progname, code, "getting local addresses");
+	    goto cleanup;
+	}
+	krb5_get_init_creds_opt_set_address_list(options, addresses);
+    }
+    if (opts->no_addresses)
+	krb5_get_init_creds_opt_set_address_list(options, NULL);
+
+    if ((opts->action == INIT_KT) && opts->keytab_name)
+    {
+	code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab);
+	if (code != 0) {
+	    com_err(progname, code, "resolving keytab %s", 
+		    opts->keytab_name);
+	    goto cleanup;
+	}
+    }
+
+    for (i = 0; i < opts->num_pa_opts; i++) {
+	code = krb5_get_init_creds_opt_set_pa(k5->ctx, options,
+					      opts->pa_opts[i].attr,
+					      opts->pa_opts[i].value);
+	if (code != 0) {
+	    com_err(progname, code, "while setting '%s'='%s'",
+		    opts->pa_opts[i].attr, opts->pa_opts[i].value);
+	    goto cleanup;
+	}
+    }
+
+    switch (opts->action) {
+    case INIT_PW:
+	code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me,
+					    0, kinit_prompter, 0,
+					    opts->starttime, 
+					    opts->service_name,
+					    options);
+	break;
+    case INIT_KT:
+	code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me,
+					  keytab,
+					  opts->starttime, 
+					  opts->service_name,
+					  options);
+	break;
+    case VALIDATE:
+	code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc,
+					opts->service_name);
+	break;
+    case RENEW:
+	code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc,
+				      opts->service_name);
+	break;
+    }
+
+    if (code) {
+	char *doing = 0;
+	switch (opts->action) {
+	case INIT_PW:
+	case INIT_KT:
+	    doing = "getting initial credentials";
+	    break;
+	case VALIDATE:
+	    doing = "validating credentials";
+	    break;
+	case RENEW:
+	    doing = "renewing credentials";
+	    break;
+	}
+
+	/* If got code == KRB5_AP_ERR_V4_REPLY && got_k4, we should
+	   let the user know that maybe he/she wants -4. */
+	if (code == KRB5KRB_AP_ERR_V4_REPLY && got_k4)
+	    com_err(progname, code, "while %s\n"
+		    "The KDC doesn't support v5.  "
+		    "You may want the -4 option in the future",
+		    doing);
+	else if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+	    fprintf(stderr, "%s: Password incorrect while %s\n", progname,
+		    doing);
+	else
+	    com_err(progname, code, "while %s", doing);
+	goto cleanup;
+    }
+
+    if (!opts->lifetime) {
+	/* We need to figure out what lifetime to use for Kerberos 4. */
+	opts->lifetime = my_creds.times.endtime - my_creds.times.authtime;
+    }
+
+    code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me);
+    if (code) {
+	com_err(progname, code, "when initializing cache %s",
+		opts->k5_cache_name?opts->k5_cache_name:"");
+	goto cleanup;
+    }
+
+    code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds);
+    if (code) {
+	com_err(progname, code, "while storing credentials");
+	goto cleanup;
+    }
+
+    notix = 0;
+
+ cleanup:
+    if (options)
+	krb5_get_init_creds_opt_free(k5->ctx, options);
+    if (my_creds.client == k5->me) {
+	my_creds.client = 0;
+    }
+    if (opts->pa_opts) {
+	free(opts->pa_opts);
+	opts->pa_opts = NULL;
+	opts->num_pa_opts = 0;
+    }
+    krb5_free_cred_contents(k5->ctx, &my_creds);
+    if (keytab)
+	krb5_kt_close(k5->ctx, keytab);
+    return notix?0:1;
+}
+
+static int
+k4_kinit(opts, k4, ctx)
+    struct k_opts* opts;
+    struct k4_data* k4;
+    krb5_context ctx;
+{
+#ifdef KRB5_KRB4_COMPAT
+    char* progname = progname_v4;
+    int k_errno = 0;
+#endif
+
+    if (!got_k4)
+	return 0;
+
+    if (opts->starttime)
+	return 0;
+
+#ifdef KRB5_KRB4_COMPAT
+    if (!k4->lifetime)
+	k4->lifetime = opts->lifetime;
+    if (!k4->lifetime)
+	k4->lifetime = KRB4_BACKUP_DEFAULT_LIFE_SECS;
+
+    k4->lifetime = krb_time_to_life(0, k4->lifetime);
+
+    switch (opts->action)
+    {
+    case INIT_PW:
+	if (!got_password) {
+	    unsigned int pwsize = sizeof(stash_password);
+	    krb5_error_code code;
+	    char prompt[1024];
+
+	    sprintf(prompt, "Password for %s", opts->principal_name);
+	    stash_password[0] = 0;
+	    /*
+	      Note: krb5_read_password does not actually look at the
+	      context, so we're ok even if we don't have a context.  If
+	      we cannot dynamically load krb5, we can substitute any
+	      decent read password function instead of the krb5 one.
+	    */
+	    code = krb5_read_password(ctx, prompt, 0, stash_password, &pwsize);
+	    if (code || pwsize == 0)
+	    {
+		fprintf(stderr, "Error while reading password for '%s'\n",
+			opts->principal_name);
+		memset(stash_password, 0, sizeof(stash_password));
+		return 0;
+	    }
+	    got_password = 1;
+	}
+	k_errno = krb_get_pw_in_tkt(k4->aname, k4->inst, k4->realm, "krbtgt", 
+				    k4->realm, k4->lifetime, stash_password);
+
+	if (k_errno) {
+	    fprintf(stderr, "%s: %s\n", progname, 
+		    krb_get_err_text(k_errno));
+	    if (authed_k5)
+	        fprintf(stderr, "Maybe your KDC does not support v4.  "
+			"Try the -5 option next time.\n");
+	    return 0;
+	}
+	return 1;
+#ifndef HAVE_KRB524
+    case INIT_KT:
+	fprintf(stderr, "%s: srvtabs are not supported\n", progname);
+	return 0;
+    case RENEW:
+	fprintf(stderr, "%s: renewal of krb4 tickets is not supported\n",
+		progname);
+	return 0;
+#else
+    /* These cases are handled by the 524 code - this prevents the compiler 
+       warnings of not using all the enumerated types.
+    */ 
+    case INIT_KT:
+    case RENEW:
+    case VALIDATE:
+        return 0;
+#endif
+    }
+#endif
+    return 0;
+}
+
+static char*
+getvprogname(v, progname)
+    char *v, *progname;
+{
+    unsigned int len = strlen(progname) + 2 + strlen(v) + 2;
+    char *ret = malloc(len);
+    if (ret)
+	sprintf(ret, "%s(v%s)", progname, v);
+    else
+	ret = progname;
+    return ret;
+}
+
+#ifdef HAVE_KRB524
+/* Convert krb5 tickets to krb4. */
+static int try_convert524(k5)
+    struct k5_data* k5;
+{
+    char * progname = progname_v524;
+    krb5_error_code code = 0;
+    int icode = 0;
+    krb5_principal kpcserver = 0;
+    krb5_creds *v5creds = 0;
+    krb5_creds increds;
+    CREDENTIALS v4creds;
+
+    if (!got_k4 || !got_k5)
+	return 0;
+
+    memset((char *) &increds, 0, sizeof(increds));
+    /*
+      From this point on, we can goto cleanup because increds is
+      initialized.
+    */
+
+    if ((code = krb5_build_principal(k5->ctx,
+				     &kpcserver, 
+				     krb5_princ_realm(k5->ctx, k5->me)->length,
+				     krb5_princ_realm(k5->ctx, k5->me)->data,
+				     "krbtgt",
+				     krb5_princ_realm(k5->ctx, k5->me)->data,
+				     NULL))) {
+	com_err(progname, code,
+		"while creating service principal name");
+	goto cleanup;
+    }
+
+    increds.client = k5->me;
+    increds.server = kpcserver;
+    /* Prevent duplicate free calls.  */
+    kpcserver = 0;
+
+    increds.times.endtime = 0;
+    increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+    if ((code = krb5_get_credentials(k5->ctx, 0, 
+				     k5->cc,
+				     &increds, 
+				     &v5creds))) {
+	com_err(progname, code,
+		"getting V5 credentials");
+	goto cleanup;
+    }
+    if ((icode = krb524_convert_creds_kdc(k5->ctx,
+					  v5creds,
+					  &v4creds))) {
+	com_err(progname, icode, 
+		"converting to V4 credentials");
+	goto cleanup;
+    }
+    /* this is stolen from the v4 kinit */
+    /* initialize ticket cache */
+    if ((icode = in_tkt(v4creds.pname, v4creds.pinst)
+	 != KSUCCESS)) {
+	com_err(progname, icode,
+		"trying to create the V4 ticket file");
+	goto cleanup;
+    }
+    /* stash ticket, session key, etc. for future use */
+    if ((icode = krb_save_credentials(v4creds.service,
+				      v4creds.instance,
+				      v4creds.realm, 
+				      v4creds.session,
+				      v4creds.lifetime,
+				      v4creds.kvno,
+				      &(v4creds.ticket_st), 
+				      v4creds.issue_date))) {
+	com_err(progname, icode,
+		"trying to save the V4 ticket");
+	goto cleanup;
+    }
+
+ cleanup:
+    memset(&v4creds, 0, sizeof(v4creds));
+    if (v5creds)
+	krb5_free_creds(k5->ctx, v5creds);
+    increds.client = 0;
+    krb5_free_cred_contents(k5->ctx, &increds);
+    if (kpcserver)
+	krb5_free_principal(k5->ctx, kpcserver);
+    return !(code || icode);
+}
+#endif /* HAVE_KRB524 */
+
+int
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    struct k_opts opts;
+    struct k5_data k5;
+    struct k4_data k4;
+    char *progname;
+
+
+    progname = GET_PROGNAME(argv[0]);
+    progname_v5 = getvprogname("5", progname);
+#ifdef KRB5_KRB4_COMPAT
+    progname_v4 = getvprogname("4", progname);
+    progname_v524 = getvprogname("524", progname);
+#endif
+
+    /* 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);
+
+    /*
+      This is where we would put in code to dynamically load Kerberos
+      libraries.  Currenlty, we just get them implicitly.
+    */
+    got_k5 = 1;
+#ifdef KRB5_KRB4_COMPAT
+    got_k4 = 1;
+#endif
+
+    memset(&opts, 0, sizeof(opts));
+    opts.action = INIT_PW;
+
+    memset(&k5, 0, sizeof(k5));
+    memset(&k4, 0, sizeof(k4));
+
+    set_com_err_hook (extended_com_err_fn);
+
+    parse_options(argc, argv, &opts, progname);
+
+    got_k5 = k5_begin(&opts, &k5, &k4);
+    got_k4 = k4_begin(&opts, &k4);
+
+    authed_k5 = k5_kinit(&opts, &k5);
+#ifdef HAVE_KRB524
+    if (authed_k5)
+	authed_k4 = try_convert524(&k5);
+#endif
+    if (!authed_k4)
+	authed_k4 = k4_kinit(&opts, &k4, k5.ctx);
+#ifdef KRB5_KRB4_COMPAT
+    memset(stash_password, 0, sizeof(stash_password));
+#endif
+
+    if (authed_k5 && opts.verbose)
+	fprintf(stderr, "Authenticated to Kerberos v5\n");
+    if (authed_k4 && opts.verbose)
+	fprintf(stderr, "Authenticated to Kerberos v4\n");
+
+    k5_end(&k5);
+    k4_end(&k4);
+
+    if ((got_k5 && !authed_k5) || (got_k4 && !authed_k4) ||
+	(!got_k5 && !got_k4))
+	exit(1);
+    return 0;
+}
diff --git a/krb5-1-6/src/clients/klist/Makefile.in b/krb5-1-6/src/clients/klist/Makefile.in
new file mode 100644
index 000000000..66d0c4acd
--- /dev/null
+++ b/krb5-1-6/src/clients/klist/Makefile.in
@@ -0,0 +1,54 @@
+thisconfigdir=../..
+myfulldir=clients/klist
+mydir=clients/klist
+BUILDTOP=$(REL)..$(S)..
+DEFS=
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SRCS = klist.c
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KLIST=$(OUTPRE)klist.exe
+
+##WIN32##EXERES=$(KLIST:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKLIST_APP -fo $@ -r $**
+
+all-unix:: klist
+##WIN32##all-windows:: $(KLIST)
+
+klist: klist.o $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $@ klist.o $(KRB4COMPAT_LIBS)
+
+##WIN32##$(KLIST): $(OUTPRE)klist.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib $(SLIB) $(KLIB) $(CLIB) $(EXERES)
+##WIN32##	link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(SCLIB)
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) klist.o klist
+
+install-unix::
+	for f in klist; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)klist.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  klist.c
diff --git a/krb5-1-6/src/clients/klist/klist.M b/krb5-1-6/src/clients/klist/klist.M
new file mode 100644
index 000000000..c5f66d525
--- /dev/null
+++ b/krb5-1-6/src/clients/klist/klist.M
@@ -0,0 +1,154 @@
+.\" clients/klist/klist.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KLIST 1
+.SH NAME
+klist \- list cached Kerberos tickets
+.SH SYNOPSIS
+\fBklist\fP [\fB\-5\fP] [\fB\-4\fP] [\fB\-e\fP] [[\fB\-c\fP] [\fB\-f\fP] 
+[\fB\-s\fP] [\fB\-a\fP  [\fB\-n\fP]]]
+[\fB\-k\fP [\fB\-t\fP] [\fB\-K\fP]]
+[\fIcache_name\fP | \fIkeytab_name\fP]
+.br
+.SH DESCRIPTION
+.I Klist
+lists the Kerberos principal and Kerberos tickets held in a credentials
+cache, or the keys held in a
+.B keytab
+file.
+If klist was built with Kerberos 4 support, the default behavior is to list
+both Kerberos 5 and Kerberos 4 credentials.  Otherwise, klist will default
+to listing only Kerberos 5 credentials.
+.SH OPTIONS
+.TP
+.B \-5
+list Kerberos 5 credentials.  This overrides whatever the default built-in
+behavior may be.  This option may be used with
+.B \-4
+.
+.TP
+.B \-4
+list Kerberos 4 credentials.  This overrides whatever the default built-in
+behavior may be.  This option is only available if kinit was built
+with Kerberos 4 compatibility.  This option may be used with 
+.B \-5
+.
+.TP
+.B \-e
+displays the encryption types of the session key and the ticket for each
+credential in the credential cache, or each key in the keytab file.
+.TP
+.B \-c
+List tickets held in a credentials cache.  This is the default if
+neither
+.B \-c
+nor
+.B \-k
+is specified.
+.TP
+.B \-f
+shows the flags present in the credentials, using the following
+abbreviations:
+.sp
+.nf
+.in +.5i
+F	\fBF\fPorwardable
+f	\fBf\fPorwarded
+P	\fBP\fProxiable
+p	\fBp\fProxy
+D	post\fBD\fPateable
+d	post\fBd\fPated
+R	\fBR\fPenewable
+I	\fBI\fPnitial
+i	\fBi\fPnvalid
+H	\fBH\fPardware authenticated
+A	pre\fBA\fPuthenticated
+T	\fBT\fPransit policy checked
+O	\fBO\fPkay as delegate
+a	\fBa\fPnonymous
+.in -.5i
+.fi
+.TP
+.B \-s
+causes
+.B klist
+to run silently (produce no output), but to still set the exit status
+according to whether it finds the credentials cache.  The exit status is
+`0' if
+.B klist
+finds a credentials cache, and `1' if it does not or if the tickets are
+ expired.
+.TP
+.B \-a
+display list of addresses in credentials.
+.TP
+.B \-n
+show numeric addresses instead of reverse-resolving addresses.
+.TP
+\fB\-k\fP
+List keys held in a
+.B keytab
+file.  
+.TP
+.B \-t
+display the time entry timestamps for each keytab entry in the keytab
+file.
+.TP
+.B \-K
+display the value of the encryption key in each keytab entry in the
+keytab file.
+.PP
+If
+.I cache_name
+or
+.I keytab_name
+is not specified, klist will display the credentials in the default
+credentials cache or keytab file as appropriate.  If the
+.B KRB5CCNAME
+environment variable is set, its value is used to name the default
+ticket cache.
+.SH ENVIRONMENT
+.B Klist
+uses the following environment variables:
+.TP "\w'.SM KRB5CCNAME\ \ 'u"
+.SM KRB5CCNAME
+Location of the Kerberos 5 credentials (ticket) cache.
+.TP "\w'.SM KRBTKFILE\ \ 'u"
+.SM KRBTKFILE
+Filename of the Kerberos 4 credentials (ticket) cache.
+.SH FILES
+.TP "\w'/tmp/krb5cc_[uid]\ \ 'u"
+/tmp/krb5cc_[uid]
+default location of Kerberos 5 credentials cache 
+([uid] is the decimal UID of the user).
+.TP "\w'/tmp/tkt[uid]\ \ 'u"
+/tmp/tkt[uid]
+default location of Kerberos 4 credentials cache 
+([uid] is the decimal UID of the user).
+.TP
+/etc/krb5.keytab
+default location for the local host's
+.B keytab
+file.
+.SH SEE ALSO
+kinit(1), kdestroy(1), krb5(3)
diff --git a/krb5-1-6/src/clients/klist/klist.c b/krb5-1-6/src/clients/klist/klist.c
new file mode 100644
index 000000000..6cf7ce16a
--- /dev/null
+++ b/krb5-1-6/src/clients/klist/klist.c
@@ -0,0 +1,837 @@
+/*
+ * clients/klist/klist.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * List out the contents of your credential cache or keytab.
+ */
+
+#include "autoconf.h"
+#include <krb5.h>
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+#include <com_err.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+/* Need definition of INET6 before network headers, for IRIX.  */
+#if defined(HAVE_ARPA_INET_H)
+#include <arpa/inet.h>
+#endif
+
+#ifndef _WIN32
+#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x))
+#else
+#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
+#endif
+
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+
+extern int optind;
+
+int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
+int show_etype = 0, show_addresses = 0, no_resolve = 0;
+char *defname;
+char *progname;
+krb5_int32 now;
+unsigned int timestamp_width;
+
+krb5_context kcontext;
+
+char * etype_string (krb5_enctype );
+void show_credential (krb5_creds *);
+	
+void do_ccache (char *);
+void do_keytab (char *);
+void printtime (time_t);
+void one_addr (krb5_address *);
+void fillit (FILE *, unsigned int, int);
+
+#ifdef KRB5_KRB4_COMPAT
+void do_v4_ccache (char *);
+#endif /* KRB5_KRB4_COMPAT */
+
+#define DEFAULT 0
+#define CCACHE 1
+#define KEYTAB 2
+
+/*
+ * The reason we start out with got_k4 and got_k5 as zero (false) is
+ * so that we can easily add dynamic loading support for determining
+ * whether Kerberos 4 and Keberos 5 libraries are available
+ */
+
+static int got_k5 = 0; 
+static int got_k4 = 0;
+
+static int default_k5 = 1;
+#ifdef KRB5_KRB4_COMPAT
+static int default_k4 = 1;
+#else
+static int default_k4 = 0;
+#endif
+
+static void usage()
+{
+#define KRB_AVAIL_STRING(x) ((x)?"available":"not available")
+
+    fprintf(stderr, "Usage: %s [-5] [-4] [-e] [[-c] [-f] [-s] [-a [-n]]] %s",
+	     progname, "[-k [-t] [-K]] [name]\n"); 
+    fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
+    fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
+    fprintf(stderr, "\t   (Default is %s%s%s%s)\n",
+	    default_k5?"Kerberos 5":"",
+	    (default_k5 && default_k4)?" and ":"",
+	    default_k4?"Kerberos 4":"",
+	    (!default_k5 && !default_k4)?"neither":"");
+    fprintf(stderr, "\t-c specifies credentials cache\n");
+    fprintf(stderr, "\t-k specifies keytab\n");
+    fprintf(stderr, "\t   (Default is credentials cache)\n");
+    fprintf(stderr, "\t-e shows the encryption type\n");
+    fprintf(stderr, "\toptions for credential caches:\n");
+    fprintf(stderr, "\t\t-f shows credentials flags\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");
+    exit(1);
+}
+
+int
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    int c;
+    char *name;
+    int mode;
+    int use_k5 = 0, use_k4 = 0;
+
+    got_k5 = 1;
+#ifdef KRB5_KRB4_COMPAT
+    got_k4 = 1;
+#endif
+
+    progname = GET_PROGNAME(argv[0]);
+
+    name = NULL;
+    mode = DEFAULT;
+    while ((c = getopt(argc, argv, "fetKsnack45")) != -1) {
+	switch (c) {
+	case 'f':
+	    show_flags = 1;
+	    break;
+	case 'e':
+	    show_etype = 1;
+	    break;
+	case 't':
+	    show_time = 1;
+	    break;
+	case 'K':
+	    show_keys = 1;
+	    break;
+	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;
+	    break;
+	case 'k':
+	    if (mode != DEFAULT) usage();
+	    mode = KEYTAB;
+	    break;
+	case '4':
+	    if (!got_k4)
+	    {
+#ifdef KRB5_KRB4_COMPAT
+		fprintf(stderr, "Kerberos 4 support could not be loaded\n");
+#else
+		fprintf(stderr, "This was not built with Kerberos 4 support\n");
+#endif
+		exit(3);
+	    }
+	    use_k4 = 1;
+	    break;
+	case '5':
+	    if (!got_k5)
+	    {
+		fprintf(stderr, "Kerberos 5 support could not be loaded\n");
+		exit(3);
+	    }
+	    use_k5 = 1;
+	    break;
+	default:
+	    usage();
+	    break;
+	}
+    }
+
+    if (no_resolve && !show_addresses) {
+	usage();
+    }
+
+    if (mode == DEFAULT || mode == CCACHE) {
+	if (show_time || show_keys)
+	    usage();
+    } else {
+	if (show_flags || status_only || show_addresses)
+	    usage();
+    }
+
+    if (argc - optind > 1) {
+	fprintf(stderr, "Extra arguments (starting with \"%s\").\n",
+		argv[optind+1]);
+	usage();
+    }
+
+    name = (optind == argc-1) ? argv[optind] : 0;
+
+    if (!use_k5 && !use_k4)
+    {
+	use_k5 = default_k5;
+	use_k4 = default_k4;
+    }
+
+    if (!use_k5)
+	got_k5 = 0;
+    if (!use_k4)
+	got_k4 = 0;
+
+    now = time(0);
+    {
+	char tmp[BUFSIZ];
+
+	if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
+	    !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), 
+					(char *) NULL))
+	    timestamp_width = (int) strlen(tmp);
+	else
+	    timestamp_width = 15;
+    }
+
+    if (got_k5)
+    {
+	krb5_error_code retval;
+	retval = krb5_init_context(&kcontext);
+	if (retval) {
+	    com_err(progname, retval, "while initializing krb5");
+	    exit(1);
+	}
+
+	if (mode == DEFAULT || mode == CCACHE)
+	    do_ccache(name);
+	else
+	    do_keytab(name);
+    } else {
+#ifdef KRB5_KRB4_COMPAT
+	if (mode == DEFAULT || mode == CCACHE)
+	    do_v4_ccache(name);
+	else {
+	    /* We may want to add v4 srvtab support */
+	    fprintf(stderr, 
+		    "%s: srvtab option not supported for Kerberos 4\n", 
+		    progname);
+	    exit(1);
+	}
+#endif /* KRB4_KRB5_COMPAT */
+    }
+
+    return 0;
+}    
+
+void do_keytab(name)
+   char *name;
+{
+     krb5_keytab kt;
+     krb5_keytab_entry entry;
+     krb5_kt_cursor cursor;
+     char buf[BUFSIZ]; /* hopefully large enough for any type */
+     char *pname;
+     int code;
+     
+     if (name == NULL) {
+	  if ((code = krb5_kt_default(kcontext, &kt))) {
+	       com_err(progname, code, "while getting default keytab");
+	       exit(1);
+	  }
+     } else {
+	  if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
+	       com_err(progname, code, "while resolving keytab %s",
+		       name);
+	       exit(1);
+	  }
+     }
+
+     if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
+	  com_err(progname, code, "while getting keytab name");
+	  exit(1);
+     }
+
+     printf("Keytab name: %s\n", buf);
+     
+     if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
+	  com_err(progname, code, "while starting keytab scan");
+	  exit(1);
+     }
+
+     if (show_time) {
+	  printf("KVNO Timestamp");
+	  fillit(stdout, timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
+	  printf("Principal\n");
+	  printf("---- ");
+	  fillit(stdout, timestamp_width, (int) '-');
+	  printf(" ");
+	  fillit(stdout, 78 - timestamp_width - sizeof("KVNO"), (int) '-');
+	  printf("\n");
+     } else {
+	  printf("KVNO Principal\n");
+	  printf("---- --------------------------------------------------------------------------\n");
+     }
+     
+     while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
+	  if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
+	       com_err(progname, code, "while unparsing principal name");
+	       exit(1);
+	  }
+	  printf("%4d ", entry.vno);
+	  if (show_time) {
+	       printtime(entry.timestamp);
+	       printf(" ");
+	  }
+	  printf("%s", pname);
+	  if (show_etype)
+	      printf(" (%s) " , etype_string(entry.key.enctype));
+	  if (show_keys) {
+	       printf(" (0x");
+	       {
+		    int i;
+		    for (i = 0; i < entry.key.length; i++)
+			 printf("%02x", entry.key.contents[i]);
+	       }
+	       printf(")");
+	  }
+	  printf("\n");
+	  krb5_free_unparsed_name(kcontext, pname);
+     }
+     if (code && code != KRB5_KT_END) {
+	  com_err(progname, code, "while scanning keytab");
+	  exit(1);
+     }
+     if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
+	  com_err(progname, code, "while ending keytab scan");
+	  exit(1);
+     }
+     exit(0);
+}
+void do_ccache(name)
+   char *name;
+{
+    krb5_ccache cache = NULL;
+    krb5_cc_cursor cur;
+    krb5_creds creds;
+    krb5_principal princ;
+    krb5_flags flags;
+    krb5_error_code code;
+    int	exit_status = 0;
+	    
+    if (status_only)
+	/* exit_status is set back to 0 if a valid tgt is found */
+	exit_status = 1;
+
+    if (name == NULL) {
+	if ((code = krb5_cc_default(kcontext, &cache))) {
+	    if (!status_only)
+		com_err(progname, code, "while getting default ccache");
+	    exit(1);
+	    }
+    } else {
+	if ((code = krb5_cc_resolve(kcontext, name, &cache))) {
+	    if (!status_only)
+		com_err(progname, code, "while resolving ccache %s",
+			name);
+	    exit(1);
+	}
+    }
+ 
+    flags = 0;				/* turns off OPENCLOSE mode */
+    if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
+	if (code == KRB5_FCC_NOFILE) {
+	    if (!status_only) {
+		com_err(progname, code, "(ticket cache %s:%s)",
+			krb5_cc_get_type(kcontext, cache),
+			krb5_cc_get_name(kcontext, cache));
+#ifdef KRB5_KRB4_COMPAT
+		if (name == NULL)
+		    do_v4_ccache(0);
+#endif
+	    }
+	} else {
+	    if (!status_only)
+		com_err(progname, code,
+			"while setting cache flags (ticket cache %s:%s)",
+			krb5_cc_get_type(kcontext, cache),
+			krb5_cc_get_name(kcontext, cache));
+	}
+	exit(1);
+    }
+    if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
+	if (!status_only)
+	    com_err(progname, code, "while retrieving principal name");
+	exit(1);
+    }
+    if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
+	if (!status_only)
+	    com_err(progname, code, "while unparsing principal name");
+	exit(1);
+    }
+    if (!status_only) {
+	printf("Ticket cache: %s:%s\nDefault principal: %s\n\n",
+	       krb5_cc_get_type(kcontext, cache),
+	       krb5_cc_get_name(kcontext, cache), defname);
+	fputs("Valid starting", stdout);
+	fillit(stdout, timestamp_width - sizeof("Valid starting") + 3,
+	       (int) ' ');
+	fputs("Expires", stdout);
+	fillit(stdout, timestamp_width - sizeof("Expires") + 3,
+	       (int) ' ');
+	fputs("Service principal\n", stdout);
+    }
+    if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
+	if (!status_only)
+	    com_err(progname, code, "while starting to retrieve tickets");
+	exit(1);
+    }
+    while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
+	if (status_only) {
+	    if (exit_status && creds.server->length == 2 &&
+		strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
+		strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
+		strcmp((char *)creds.server->data[1].data,
+		       princ->realm.data) == 0 && 
+		creds.times.endtime > now)
+		exit_status = 0;
+	} else {
+	    show_credential(&creds);
+	}
+	krb5_free_cred_contents(kcontext, &creds);
+    }
+    if (code == KRB5_CC_END) {
+	if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
+	    if (!status_only)
+		com_err(progname, code, "while finishing ticket retrieval");
+	    exit(1);
+	}
+	flags = KRB5_TC_OPENCLOSE;	/* turns on OPENCLOSE mode */
+	if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
+	    if (!status_only)
+		com_err(progname, code, "while closing ccache");
+	    exit(1);
+	}
+#ifdef KRB5_KRB4_COMPAT
+	if (name == NULL && !status_only)
+	    do_v4_ccache(0);
+#endif
+	exit(exit_status);
+    } else {
+	if (!status_only)
+	    com_err(progname, code, "while retrieving a ticket");
+	exit(1);
+    }	
+}
+
+char *
+etype_string(enctype)
+    krb5_enctype enctype;
+{
+    static char buf[100];
+    krb5_error_code retval;
+    
+    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;
+}
+
+static char *
+flags_string(cred)
+    register krb5_creds *cred;
+{
+    static char buf[32];
+    int i = 0;
+	
+    if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
+	buf[i++] = 'F';
+    if (cred->ticket_flags & TKT_FLG_FORWARDED)
+	buf[i++] = 'f';
+    if (cred->ticket_flags & TKT_FLG_PROXIABLE)
+	buf[i++] = 'P';
+    if (cred->ticket_flags & TKT_FLG_PROXY)
+	buf[i++] = 'p';
+    if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
+	buf[i++] = 'D';
+    if (cred->ticket_flags & TKT_FLG_POSTDATED)
+	buf[i++] = 'd';
+    if (cred->ticket_flags & TKT_FLG_INVALID)
+	buf[i++] = 'i';
+    if (cred->ticket_flags & TKT_FLG_RENEWABLE)
+	buf[i++] = 'R';
+    if (cred->ticket_flags & TKT_FLG_INITIAL)
+	buf[i++] = 'I';
+    if (cred->ticket_flags & TKT_FLG_HW_AUTH)
+	buf[i++] = 'H';
+    if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
+	buf[i++] = 'A';
+    if (cred->ticket_flags & TKT_FLG_TRANSIT_POLICY_CHECKED)
+	buf[i++] = 'T';
+    if (cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE)
+	buf[i++] = 'O';		/* D/d are taken.  Use short strings?  */
+    if (cred->ticket_flags & TKT_FLG_ANONYMOUS)
+	buf[i++] = 'a';
+    buf[i] = '\0';
+    return(buf);
+}
+
+void 
+printtime(tv)
+    time_t tv;
+{
+    char timestring[BUFSIZ];
+    char fill;
+
+    fill = ' ';
+    if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
+				    timestring,
+				    timestamp_width+1,
+				    &fill)) {
+	printf(timestring);
+    }
+}
+
+void
+show_credential(cred)
+    register krb5_creds * cred;
+{
+    krb5_error_code retval;
+    krb5_ticket *tkt;
+    char *name, *sname, *flags;
+    int	extra_field = 0;
+
+    retval = krb5_unparse_name(kcontext, cred->client, &name);
+    if (retval) {
+	com_err(progname, retval, "while unparsing client name");
+	return;
+    }
+    retval = krb5_unparse_name(kcontext, cred->server, &sname);
+    if (retval) {
+	com_err(progname, retval, "while unparsing server name");
+	krb5_free_unparsed_name(kcontext, name);
+	return;
+    }
+    if (!cred->times.starttime)
+	cred->times.starttime = cred->times.authtime;
+
+    printtime(cred->times.starttime);
+    putchar(' '); putchar(' ');
+    printtime(cred->times.endtime);
+    putchar(' '); putchar(' ');
+
+    printf("%s\n", sname);
+
+    if (strcmp(name, defname)) {
+	    printf("\tfor client %s", name);
+	    extra_field++;
+    }
+    
+    if (cred->times.renew_till) {
+	if (!extra_field)
+		fputs("\t",stdout);
+	else
+		fputs(", ",stdout);
+	fputs("renew until ", stdout);
+	printtime(cred->times.renew_till);
+	extra_field += 2;
+    }
+
+    if (extra_field > 3) {
+	fputs("\n", stdout);
+	extra_field = 0;
+    }
+
+    if (show_flags) {
+	flags = flags_string(cred);
+	if (flags && *flags) {
+	    if (!extra_field)
+		fputs("\t",stdout);
+	    else
+		fputs(", ",stdout);
+	    printf("Flags: %s", flags);
+	    extra_field++;
+	}
+    }
+
+    if (extra_field > 2) {
+	fputs("\n", stdout);
+	extra_field = 0;
+    }
+
+    if (show_etype) {
+	retval = krb5_decode_ticket(&cred->ticket, &tkt);
+	if (retval)
+	    goto err_tkt;
+
+	if (!extra_field)
+	    fputs("\t",stdout);
+	else
+	    fputs(", ",stdout);
+	printf("Etype (skey, tkt): %s, ",
+	       etype_string(cred->keyblock.enctype));
+	printf("%s ",
+	       etype_string(tkt->enc_part.enctype));
+	extra_field++;
+
+    err_tkt:
+	if (tkt != NULL)
+	    krb5_free_ticket(kcontext, tkt);
+    }
+
+    /* 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[i]);
+	    }
+
+	    printf("\n");
+	}
+    }
+
+    krb5_free_unparsed_name(kcontext, name);
+    krb5_free_unparsed_name(kcontext, sname);
+}
+
+#include "port-sockets.h"
+#include "socket-utils.h" /* for ss2sin etc */
+#include "fake-addrinfo.h"
+
+void one_addr(a)
+    krb5_address *a;
+{
+    struct sockaddr_storage ss;
+    int err;
+    char namebuf[NI_MAXHOST];
+
+    memset (&ss, 0, sizeof (ss));
+
+    switch (a->addrtype) {
+    case ADDRTYPE_INET:
+	if (a->length != 4) {
+	broken:
+	    printf ("broken address (type %d length %d)",
+		    a->addrtype, a->length);
+	    return;
+	}
+	{
+	    struct sockaddr_in *sinp = ss2sin (&ss);
+	    sinp->sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+	    sinp->sin_len = sizeof (struct sockaddr_in);
+#endif
+	    memcpy (&sinp->sin_addr, a->contents, 4);
+	}
+	break;
+#ifdef KRB5_USE_INET6
+    case ADDRTYPE_INET6:
+	if (a->length != 16)
+	    goto broken;
+	{
+	    struct sockaddr_in6 *sin6p = ss2sin6 (&ss);
+	    sin6p->sin6_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+	    sin6p->sin6_len = sizeof (struct sockaddr_in6);
+#endif
+	    memcpy (&sin6p->sin6_addr, a->contents, 16);
+	}
+	break;
+#endif
+    default:
+	printf ("unknown addrtype %d", a->addrtype);
+	return;
+    }
+
+    namebuf[0] = 0;
+    err = getnameinfo (ss2sa (&ss), socklen (ss2sa (&ss)),
+		       namebuf, sizeof (namebuf), 0, 0,
+		       no_resolve ? NI_NUMERICHOST : 0U);
+    if (err) {
+	printf ("unprintable address (type %d, error %d %s)", a->addrtype, err,
+		gai_strerror (err));
+	return;
+    }
+    printf ("%s", namebuf);
+}
+
+void
+fillit(f, num, c)
+    FILE		*f;
+    unsigned int	num;
+    int			c;
+{
+    int i;
+
+    for (i=0; i<num; i++)
+	fputc(c, f);
+}
+
+#ifdef KRB5_KRB4_COMPAT
+void
+do_v4_ccache(name)
+    char * name;
+{
+    char    pname[ANAME_SZ];
+    char    pinst[INST_SZ];
+    char    prealm[REALM_SZ];
+    char    *file;
+    int     k_errno;
+    CREDENTIALS c;
+    int     header = 1;
+
+    if (!got_k4)
+	return;
+
+    file = name?name:tkt_string();
+
+    if (status_only) {
+	fprintf(stderr, 
+		"%s: exit status option not supported for Kerberos 4\n",
+		progname);
+	exit(1);
+    }
+
+    if (got_k5)
+	printf("\n\n");
+
+    printf("Kerberos 4 ticket cache: %s\n", file);
+
+    /* 
+     * Since krb_get_tf_realm will return a ticket_file error, 
+     * we will call tf_init and tf_close first to filter out
+     * things like no ticket file.  Otherwise, the error that 
+     * the user would see would be 
+     * klist: can't find realm of ticket file: No ticket file (tf_util)
+     * instead of
+     * klist: No ticket file (tf_util)
+     */
+
+    /* Open ticket file */
+    k_errno = tf_init(file, R_TKT_FIL);
+    if (k_errno) {
+	fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
+	exit(1);
+    }
+    /* Close ticket file */
+    (void) tf_close();
+
+    /* 
+     * We must find the realm of the ticket file here before calling
+     * tf_init because since the realm of the ticket file is not
+     * really stored in the principal section of the file, the
+     * routine we use must itself call tf_init and tf_close.
+     */
+    if ((k_errno = krb_get_tf_realm(file, prealm)) != KSUCCESS) {
+	fprintf(stderr, "%s: can't find realm of ticket file: %s\n",
+		progname, krb_get_err_text (k_errno));
+	exit(1);
+    }
+
+    /* Open ticket file */
+    if ((k_errno = tf_init(file, R_TKT_FIL))) {
+	fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
+	exit(1);
+    }
+    /* Get principal name and instance */
+    if ((k_errno = tf_get_pname(pname)) ||
+	(k_errno = tf_get_pinst(pinst))) {
+	fprintf(stderr, "%s: %s\n", progname, krb_get_err_text (k_errno));
+	exit(1);
+    }
+
+    /* 
+     * You may think that this is the obvious place to get the
+     * realm of the ticket file, but it can't be done here as the
+     * routine to do this must open the ticket file.  This is why 
+     * it was done before tf_init.
+     */
+       
+    printf("Principal: %s%s%s%s%s\n\n", pname,
+	   (pinst[0] ? "." : ""), pinst,
+	   (prealm[0] ? "@" : ""), prealm);
+    while ((k_errno = tf_get_cred(&c)) == KSUCCESS) {
+	if (header) {
+	    printf("%-18s  %-18s  %s\n",
+		   "  Issued", "  Expires", "  Principal");
+	    header = 0;
+	}
+	printtime(c.issue_date);
+	fputs("  ", stdout);
+	printtime(krb_life_to_time(c.issue_date, c.lifetime));
+	printf("  %s%s%s%s%s\n",
+	       c.service, (c.instance[0] ? "." : ""), c.instance,
+	       (c.realm[0] ? "@" : ""), c.realm);
+    }
+    if (header && k_errno == EOF) {
+	printf("No tickets in file.\n");
+    }
+}
+#endif /* KRB4_KRB5_COMPAT */
diff --git a/krb5-1-6/src/clients/kpasswd/Makefile.in b/krb5-1-6/src/clients/kpasswd/Makefile.in
new file mode 100644
index 000000000..bfa26f730
--- /dev/null
+++ b/krb5-1-6/src/clients/kpasswd/Makefile.in
@@ -0,0 +1,54 @@
+thisconfigdir=../..
+myfulldir=clients/kpasswd
+mydir=clients/kpasswd
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS=
+
+SRCS=kpasswd.c ksetpwd.c
+
+kpasswd: kpasswd.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o kpasswd kpasswd.o $(KRB5_BASE_LIBS)
+
+ksetpwd: ksetpwd.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o ksetpwd ksetpwd.o $(KRB5_BASE_LIBS)
+
+kpasswd.o:	$(srcdir)/kpasswd.c
+ksetpwd.o:	$(srcdir)/ksetpwd.c
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KPWD=$(OUTPRE)kpasswd.exe
+
+##WIN32##EXERES=$(KPWD:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKPASSWD_APP -fo $@ -r $**
+
+all-unix:: kpasswd ksetpwd
+
+clean-unix::
+	$(RM) kpasswd.o kpasswd ksetpwd.o ksetpwd
+
+install-all install-kdc install-server install-client install-unix::
+	$(INSTALL_PROGRAM) kpasswd $(DESTDIR)$(CLIENT_BINDIR)/`echo kpasswd|sed '$(transform)'`
+	$(INSTALL_DATA) $(srcdir)/kpasswd.M $(DESTDIR)$(CLIENT_MANDIR)/`echo kpasswd|sed '$(transform)'`.1;
+
+##WIN32##all-windows:: $(KPWD)
+
+##WIN32##$(KPWD): $(OUTPRE)kpasswd.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32##	link $(EXE_LINKOPTS) -out:$@ $** $(SCLIB)
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kpasswd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \
+  kpasswd.c
+$(OUTPRE)ksetpwd.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h ksetpwd.c
diff --git a/krb5-1-6/src/clients/kpasswd/kpasswd.M b/krb5-1-6/src/clients/kpasswd/kpasswd.M
new file mode 100644
index 000000000..d3cacbbaa
--- /dev/null
+++ b/krb5-1-6/src/clients/kpasswd/kpasswd.M
@@ -0,0 +1,75 @@
+.\" clients/kpasswd/kpasswd.M
+.\" 
+.\" Copyright 1995 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.\.so man1/header.doc
+.TH KPASSWD 1 \*h
+.SH NAME
+kpasswd \- change a user's Kerberos password
+.SH SYNOPSIS
+.B kpasswd
+[\fIprincipal\fP]
+.SH DESCRIPTION
+.PP
+The
+.I kpasswd
+command is used to change a Kerberos principal's password.
+.I Kpasswd
+prompts for the current Kerberos password, which is used to obtain a 
+.B changepw
+ticket from the
+.SM KDC
+for the user's Kerberos realm.  If
+.B kpasswd
+successfully obtains the
+.B changepw
+ticket, the user is prompted twice for the new password, and the
+password is changed.
+.PP
+If the principal is governed by a policy that specifies the length and/or
+number of character classes required in the new password, the new
+password must conform to the policy.  (The five character classes are
+lower case, upper case, numbers, punctuation, and all other characters.)
+.SH OPTIONS
+.TP
+.I principal
+change the password for the Kerberos principal
+.IR principal .
+Otherwise, 
+.I kpasswd
+uses the principal name from an existing ccache if there is one; if
+not, the principal is derived from the identity of the user
+invoking the
+.I kpasswd
+command.
+.SH PORTS
+.B kpasswd 
+looks first for kpasswd_server = host:port in the [realms] section of
+the krb5.conf file under the current realm.  If that is missing,
+.B kpasswd
+looks for the admin_server entry, but substitutes 464 for the port.
+.SH SEE ALSO
+kadmin(8), kadmind(8)
+.SH BUGS
+.PP
+.B kpasswd
+may not work with multi-homed hosts running on the Solaris platform.
diff --git a/krb5-1-6/src/clients/kpasswd/kpasswd.c b/krb5-1-6/src/clients/kpasswd/kpasswd.c
new file mode 100644
index 000000000..204a8bfdb
--- /dev/null
+++ b/krb5-1-6/src/clients/kpasswd/kpasswd.c
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include "autoconf.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <krb5.h>
+
+#define P1 "Enter new password"
+#define P2 "Enter it again"
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+
+static
+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(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 */
+
+int main(int argc, char *argv[])
+{
+   krb5_error_code ret;
+   krb5_context context;
+   krb5_principal princ;
+   char *pname;
+   krb5_ccache ccache;
+   krb5_get_init_creds_opt *opts = NULL;
+   krb5_creds creds;
+
+   char pw[1024];
+   unsigned int pwlen;
+   int result_code;
+   krb5_data result_code_string, result_string;
+
+   if (argc > 2) {
+      fprintf(stderr, "usage: %s [principal]\n", argv[0]);
+      exit(1);
+   }
+
+   pname = argv[1];
+
+   ret = krb5_init_context(&context);
+   if (ret) {
+      com_err(argv[0], ret, "initializing kerberos library");
+      exit(1);
+   }
+
+   /* in order, use the first of:
+      - a name specified on the command line
+      - the principal name from an existing ccache
+      - the name corresponding to the ruid of the process
+
+      otherwise, it's an error.
+      */
+
+   if (pname) {
+      if ((ret = krb5_parse_name(context, pname, &princ))) {
+	 com_err(argv[0], ret, "parsing client name");
+	 exit(1);
+      }
+   } else if ((ret = krb5_cc_default(context, &ccache)) != KRB5_CC_NOTFOUND) {
+      if (ret) {
+	 com_err(argv[0], ret, "opening default ccache");
+	 exit(1);
+      }
+
+      if ((ret = krb5_cc_get_principal(context, ccache, &princ))) {
+	 com_err(argv[0], ret, "getting principal from ccache");
+	 exit(1);
+      }
+
+      if ((ret = krb5_cc_close(context, ccache))) {
+	 com_err(argv[0], ret, "closing ccache");
+	 exit(1);
+      }
+   } else {
+       get_name_from_passwd_file(argv[0], context, &princ);
+   }
+
+   if ((ret = krb5_get_init_creds_opt_alloc(context, &opts))) {
+	 com_err(argv[0], ret, "allocating krb5_get_init_creds_opt");
+	 exit(1);
+   }
+   krb5_get_init_creds_opt_set_tkt_life(opts, 5*60);
+   krb5_get_init_creds_opt_set_renew_life(opts, 0);
+   krb5_get_init_creds_opt_set_forwardable(opts, 0);
+   krb5_get_init_creds_opt_set_proxiable(opts, 0);
+
+   if ((ret = krb5_get_init_creds_password(context, &creds, princ, NULL,
+					   krb5_prompter_posix, NULL, 
+					   0, "kadmin/changepw", opts))) {
+      if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+	 com_err(argv[0], 0,
+		 "Password incorrect while getting initial ticket");
+      else
+	 com_err(argv[0], ret, "getting initial ticket");
+      krb5_get_init_creds_opt_free(context, opts);
+      exit(1);
+   }
+
+   pwlen = sizeof(pw);
+   if ((ret = krb5_read_password(context, P1, P2, pw, &pwlen))) {
+      com_err(argv[0], ret, "while reading password");
+      krb5_get_init_creds_opt_free(context, opts);
+      exit(1);
+   }
+
+   if ((ret = krb5_change_password(context, &creds, pw,
+				   &result_code, &result_code_string,
+				   &result_string))) {
+      com_err(argv[0], ret, "changing password");
+      krb5_get_init_creds_opt_free(context, opts);
+      exit(1);
+   }
+
+   if (result_code) {
+      printf("%.*s%s%.*s\n",
+	     (int) result_code_string.length, result_code_string.data,
+	     result_string.length?": ":"",
+	     (int) result_string.length,
+	     result_string.data ? result_string.data : "");
+      krb5_get_init_creds_opt_free(context, opts);
+      exit(2);
+   }
+
+   if (result_string.data != NULL) 
+       free(result_string.data);
+   if (result_code_string.data != NULL)
+       free(result_code_string.data);
+   krb5_get_init_creds_opt_free(context, opts);
+
+   printf("Password changed.\n");
+   exit(0);
+}
diff --git a/krb5-1-6/src/clients/kpasswd/ksetpwd.c b/krb5-1-6/src/clients/kpasswd/ksetpwd.c
new file mode 100644
index 000000000..2eec39794
--- /dev/null
+++ b/krb5-1-6/src/clients/kpasswd/ksetpwd.c
@@ -0,0 +1,316 @@
+#include <krb5.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+
+#define TKTTIMELEFT     60*10   /* ten minutes */
+
+static int verify_creds()
+{
+	krb5_context	kcontext;
+	krb5_ccache		ccache;
+	krb5_error_code	kres;
+
+	kres = krb5_init_context(&kcontext);
+	if( kres == 0 )
+	{
+		kres = krb5_cc_default( kcontext, &ccache );
+		if( kres == 0 )
+		{
+			krb5_principal	user_princ;
+
+			kres = krb5_cc_get_principal( kcontext, ccache, &user_princ );
+			if( kres == 0 )
+				krb5_free_principal( kcontext, user_princ );
+			krb5_cc_close( kcontext, ccache );
+		}
+		krb5_free_context(kcontext);
+	}
+	return kres;
+}
+
+static void get_init_creds_opt_init( krb5_get_init_creds_opt *outOptions )
+{
+    krb5_preauthtype    preauth[] = { KRB5_PADATA_ENC_TIMESTAMP };
+    krb5_enctype        etypes[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC};
+    krb5_get_init_creds_opt_set_address_list(outOptions, NULL);
+    krb5_get_init_creds_opt_set_etype_list( outOptions, etypes, sizeof(etypes)/sizeof(krb5_enctype) );
+    krb5_get_init_creds_opt_set_preauth_list(outOptions, preauth, sizeof(preauth)/sizeof(krb5_preauthtype) );
+}
+
+typedef void * kbrccache_t;
+#define CCACHE_PREFIX_DEFAULT "MEMORY:C_"
+
+static kbrccache_t userinitcontext(
+	const char * user, const char * domain, const char * passwd, const char * cachename, int initialize,
+	int * outError )
+{
+	krb5_context	kcontext = 0;
+	krb5_ccache		kcache = 0;
+	krb5_creds		kcreds;
+	krb5_principal	kme = 0;
+	krb5_error_code	kres;
+	char *			pPass = strdup( passwd );
+	char *			pName = NULL;
+	char *			pCacheName = NULL;
+	int				numCreds = 0;
+
+	memset( &kcreds, 0, sizeof(kcreds) );
+	kres = krb5_init_context( &kcontext );
+	if( kres )
+		goto return_error;
+	if( domain )
+		kres = krb5_build_principal( kcontext, &kme, strlen(domain), domain, user, 0 );
+	else
+		kres = krb5_parse_name( kcontext, user, &kme );
+	if( kres )
+		goto fail;
+	krb5_unparse_name( kcontext, kme, &pName );
+	if( cachename )
+	{
+		pCacheName = malloc( strlen( pName ) + strlen( cachename ) + 1 );
+		if( pCacheName == NULL )
+		{
+			kres = KRB5_CC_NOMEM;
+			goto fail;
+		}
+		strcpy( pCacheName, cachename );
+		strcat( pCacheName, pName );
+		kres = krb5_cc_resolve( kcontext, pCacheName, &kcache );
+		if( kres )
+		{
+			kres = krb5_cc_resolve( kcontext, CCACHE_PREFIX_DEFAULT, &kcache );
+			if( kres == 0 )
+				pCacheName = strdup(CCACHE_PREFIX_DEFAULT);
+		}
+	}
+	else
+	{
+		kres = krb5_cc_default( kcontext, &kcache );
+		pCacheName = strdup( krb5_cc_get_name( kcontext, kcache ) );
+	}
+	if( kres )
+	{
+		krb5_free_context(kcontext);
+		goto return_error;
+	}
+	if( initialize )
+		krb5_cc_initialize( kcontext, kcache, kme );
+	if( kres == 0 && user && passwd )
+	{
+		long timeneeded = time(0L) +TKTTIMELEFT;
+		int have_credentials = 0;
+		krb5_cc_cursor cc_curs = NULL;
+		numCreds = 0;
+		if( (kres=krb5_cc_start_seq_get(kcontext, kcache, &cc_curs)) >= 0 )
+		{
+			while( (kres=krb5_cc_next_cred(kcontext, kcache, &cc_curs, &kcreds))== 0)
+			{
+				numCreds++;
+				if( krb5_principal_compare( kcontext, kme, kcreds.client ) )
+				{
+					if( kcreds.ticket_flags & TKT_FLG_INITIAL && kcreds.times.endtime>timeneeded )
+						have_credentials = 1;
+				}
+				krb5_free_cred_contents( kcontext, &kcreds );
+				if( have_credentials )
+					break;
+			}
+			krb5_cc_end_seq_get( kcontext, kcache, &cc_curs );
+		}
+		else
+		{
+			const char * errmsg = error_message(kres);
+			fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
+		}
+		if( kres != 0 || have_credentials == 0 )
+		{
+			krb5_get_init_creds_opt *options = NULL;
+			kres = krb5_get_init_creds_opt_alloc(kcontext, &options);
+			if ( kres == 0 )
+			{
+				get_init_creds_opt_init(options);
+/*
+** no valid credentials - get new ones
+*/
+				kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass,
+						NULL /*prompter*/, 
+						NULL /*data*/,
+						0 /*starttime*/,
+						0 /*in_tkt_service*/,
+						options /*options*/ );
+			}
+			if( kres == 0 )
+			{
+				if( numCreds <= 0 )
+					kres = krb5_cc_initialize( kcontext, kcache, kme );
+				if( kres == 0 )
+					kres = krb5_cc_store_cred( kcontext, kcache, &kcreds );
+				if( kres == 0 )
+					have_credentials = 1;
+			}
+			krb5_get_init_creds_opt_free(kcontext, options);
+		}
+#ifdef NOTUSED
+		if( have_credentials )
+		{
+			int mstat;
+			kres = gss_krb5_ccache_name( &mstat, pCacheName, NULL );
+			if( getenv( ENV_DEBUG_LDAPKERB ) )
+				fprintf( stderr, "gss credentials cache set to %s(%d)\n", pCacheName, kres );
+		}
+#endif
+		krb5_cc_close( kcontext, kcache );
+	}
+fail:
+	if( kres )
+	{
+			const char * errmsg = error_message(kres);
+			fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
+	}
+	krb5_free_principal( kcontext, kme );
+	krb5_free_cred_contents( kcontext, &kcreds );
+	if( pName )
+		free( pName );
+	free(pPass);
+	krb5_free_context(kcontext);
+
+return_error:
+	if( kres )
+	{
+		if( pCacheName )
+		{
+			free(pCacheName);
+			pCacheName = NULL;
+		}
+	}
+	if( outError )
+		*outError = kres;
+	return pCacheName;
+}
+
+static int init_creds()
+{
+	char user[512];
+	char * password = NULL;
+	int result;
+
+	user[0] = 0;
+	result = -1;
+
+	for(;;)
+	{
+		while( user[0] == 0 )
+		{
+			int userlen;
+			printf( "Username: ");
+			fflush(stdout);
+			if( fgets( user, sizeof(user), stdin ) == NULL )
+				return -1;
+			userlen = strlen( user);
+			if( userlen < 2 )
+				continue;
+			user[userlen-1] = 0;	/* get rid of the newline */
+			break;
+		}
+		{
+			kbrccache_t usercontext;
+			password = getpass( "Password: ");
+			if( ! password )
+				return -1;
+			result = 0;
+			usercontext = userinitcontext( user, NULL, password, NULL, 1, &result );
+			if( usercontext )
+				break;
+		}
+	}
+	return result;
+}
+
+int main( int argc, char ** argv )
+{
+	char * new_password = NULL;
+	char * new_password2;
+	krb5_context	kcontext;
+	krb5_error_code	kerr;
+	krb5_principal	target_principal;
+
+
+	if( argc < 2 )
+	{
+		fprintf( stderr, "Usage: setpass user@REALM\n");
+		exit(1);
+	}
+
+/*
+** verify credentials -
+*/
+	if( verify_creds() )
+		init_creds();
+	if( verify_creds() )
+	{
+		fprintf( stderr, "No user credentials available\n");
+		exit(1);
+	}
+/*
+** check the principal name -
+*/
+	krb5_init_context(&kcontext);
+	kerr = krb5_parse_name( kcontext, argv[1], &target_principal );
+
+	{
+		char * pname = NULL;
+		kerr = krb5_unparse_name( kcontext, target_principal, &pname );
+		printf( "Changing password for %s:\n", pname);
+		fflush( stdout );
+		free( pname );
+	}
+/*
+** get the new password -
+*/
+	while( !new_password )
+	{
+		new_password = getpass("Enter new password: ");
+		new_password2 = getpass("Verify new password: ");
+		if( strcmp( new_password, new_password2 ) )
+		{
+			printf("Passwords do not match\n");
+			free( new_password );
+			free( new_password2 );
+			continue;
+		}
+	}
+/*
+** change the password -
+*/
+	fprintf( stderr, "the password is %s\n", new_password );
+
+	{
+		int pw_result;
+		krb5_ccache ccache;
+		krb5_data	pw_res_string, res_string;
+
+		kerr = krb5_cc_default( kcontext, &ccache );
+		if( kerr == 0 )
+		{
+			kerr = krb5_set_password_using_ccache(kcontext, ccache, new_password, target_principal,
+						&pw_result, &pw_res_string, &res_string );
+			if( kerr )
+				fprintf( stderr, "Failed: %s\n", error_message(kerr) );
+			else
+			{
+				if( pw_result )
+				{
+					fprintf( stderr, "Failed(%d)", pw_result );
+					if( pw_res_string.length > 0 )
+						fprintf( stderr, ": %s", pw_res_string.data);
+					if( res_string.length > 0 )
+						fprintf( stderr, " %s", res_string.data);
+					fprintf( stderr, "\n");
+				}
+			}
+		}
+	}
+	return(0);
+}
diff --git a/krb5-1-6/src/clients/ksu/Makefile.in b/krb5-1-6/src/clients/ksu/Makefile.in
new file mode 100644
index 000000000..3b907404e
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/Makefile.in
@@ -0,0 +1,110 @@
+thisconfigdir=../..
+myfulldir=clients/ksu
+mydir=clients/ksu
+BUILDTOP=$(REL)..$(S)..
+DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
+DEFS=
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+KSU_LIBS=@KSU_LIBS@
+
+SRCS = \
+	$(srcdir)/krb_auth_su.c \
+	$(srcdir)/ccache.c \
+	$(srcdir)/authorization.c \
+	$(srcdir)/main.c \
+	$(srcdir)/heuristic.c \
+	$(srcdir)/xmalloc.c \
+	$(srcdir)/setenv.c
+OBJS = \
+	krb_auth_su.o \
+	ccache.o \
+	authorization.o \
+	main.o \
+	heuristic.o \
+	xmalloc.o @SETENVOBJ@
+
+all:: ksu
+
+ksu: $(OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS)
+
+clean::
+	$(RM) ksu
+
+install::
+	-for f in ksu; do \
+	  $(INSTALL_SETUID) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		${DESTDIR}$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)krb_auth_su.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/k5-util.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  krb_auth_su.c ksu.h
+$(OUTPRE)ccache.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h ccache.c ksu.h
+$(OUTPRE)authorization.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/k5-util.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  authorization.c ksu.h
+$(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h ksu.h main.c
+$(OUTPRE)heuristic.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/k5-util.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  heuristic.c ksu.h
+$(OUTPRE)xmalloc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/k5-util.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  ksu.h xmalloc.c
+$(OUTPRE)setenv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  setenv.c
diff --git a/krb5-1-6/src/clients/ksu/authorization.c b/krb5-1-6/src/clients/ksu/authorization.c
new file mode 100644
index 000000000..09a67b976
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/authorization.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (c) 1994 by the University of Southern California
+ *
+ * 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 copy, modify, and distribute
+ *     this software and its documentation in source and binary forms is
+ *     hereby granted, provided that any documentation or other materials
+ *     related to such distribution or use acknowledge that the software
+ *     was developed by the University of Southern California.
+ *
+ * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
+ *     University of Southern California MAKES NO REPRESENTATIONS OR
+ *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
+ *     limitation, the University of Southern California MAKES NO
+ *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+ *     PARTICULAR PURPOSE. The University of Southern
+ *     California shall not be held liable for any liability nor for any
+ *     direct, indirect, or consequential damages with respect to any
+ *     claim by the user or distributor of the ksu software.
+ *
+ * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+ */
+
+#include "ksu.h"
+
+static void auth_cleanup (FILE *, FILE *, char *);
+
+krb5_boolean fowner(fp, uid)
+    FILE *fp;
+    uid_t uid;
+{
+    struct stat sbuf;
+
+    /*
+     * For security reasons, file must be owned either by
+     * the user himself, or by root.  Otherwise, don't grant access.
+     */
+    if (fstat(fileno(fp), &sbuf)) {
+	return(FALSE);
+    }
+
+    if ((sbuf.st_uid != uid) && sbuf.st_uid) {
+	return(FALSE);
+    }
+
+    return(TRUE);
+}
+
+/*
+ * Given a Kerberos principal "principal", and a local username "luser",
+ * determine whether user is authorized to login according to the
+ * authorization files ~luser/.k5login" and ~luser/.k5users.  Returns TRUE
+ * if authorized, FALSE if not authorized.
+ *
+ */
+
+krb5_error_code krb5_authorization(context, principal, luser,
+				   cmd, ok, out_fcmd)
+    /* IN */
+    krb5_context context;
+    krb5_principal principal;
+    const char *luser;
+    char *cmd;
+    /* OUT */
+    krb5_boolean *ok;
+    char **out_fcmd;
+{
+    struct passwd *pwd;
+    char *princname;
+    int k5login_flag =0;
+    int k5users_flag =0;
+    krb5_boolean retbool =FALSE;
+    FILE * login_fp = 0, * users_fp = 0;
+    krb5_error_code retval = 0;
+    struct stat st_temp;
+
+    *ok =FALSE;
+
+    /* no account => no access */
+    if ((pwd = getpwnam(luser)) == NULL)
+	return 0;
+
+    retval = krb5_unparse_name(context, principal, &princname);
+    if (retval)
+	return retval;
+
+#ifdef DEBUG
+    printf("principal to be authorized %s\n", princname);
+    printf("login file: %s\n", k5login_path);
+    printf("users file: %s\n", k5users_path);
+#endif
+
+    k5login_flag = stat(k5login_path, &st_temp);
+    k5users_flag = stat(k5users_path, &st_temp);
+
+    /* k5login and k5users must be owned by target user or root */
+    if (!k5login_flag){
+    	if ((login_fp = fopen(k5login_path, "r")) == NULL)
+	    return 0;
+	if ( fowner(login_fp, pwd->pw_uid) == FALSE) {
+	    fclose(login_fp);
+	    return 0;
+	}
+    }
+
+    if (!k5users_flag){
+    	if ((users_fp = fopen(k5users_path, "r")) == NULL) {
+	    return 0;
+    	}
+	if ( fowner(users_fp, pwd->pw_uid) == FALSE){
+	    fclose(users_fp);
+	    return 0;
+    	}
+    }
+
+    if (auth_debug){
+	fprintf(stderr,
+		"In krb5_authorization: if auth files exist -> can access\n");
+    }
+
+#if 0
+    if (cmd){
+	if(k5users_flag){
+	    return 0; /* if  kusers does not exist -> done */
+	}else{
+	    if(retval = k5users_lookup(users_fp,princname,
+				       cmd,&retbool,out_fcmd)){
+		auth_cleanup(users_fp, login_fp, princname);
+		return retval;
+	    }else{
+		*ok =retbool;
+		return retval;
+	    }
+	}
+    }
+#endif
+
+    /* if either file exists,
+       first see if the principal is in the login in file,
+       if it's not there check the k5users file */
+
+    if (!k5login_flag){
+	if (auth_debug)
+	    fprintf(stderr,
+		    "In krb5_authorization: principal to be authorized %s\n",
+		    princname);
+
+	retval = k5login_lookup(login_fp,  princname, &retbool);
+	if (retval) {
+	    auth_cleanup(users_fp, login_fp, princname);
+	    return retval;
+	}
+	if (retbool) {
+	    if (cmd)
+		*out_fcmd = xstrdup(cmd);
+	}
+    }
+
+    if ((!k5users_flag) && (retbool == FALSE) ){
+	retval = k5users_lookup (users_fp, princname,
+				 cmd, &retbool, out_fcmd);
+	if(retval) {
+	    auth_cleanup(users_fp, login_fp, princname);
+	    return retval;
+	}
+    }
+
+    if (k5login_flag && k5users_flag){
+
+	char * kuser =  (char *) xcalloc (strlen(princname), sizeof(char));
+	if (!(krb5_aname_to_localname(context, principal,
+				      strlen(princname), kuser))
+	    && (strcmp(kuser, luser) == 0)) {
+	    retbool = TRUE;
+	}
+
+	free(kuser);
+    }
+
+    *ok =retbool;
+    auth_cleanup(users_fp, login_fp, princname);
+    return 0;
+}
+
+/***********************************************************
+k5login_lookup looks for princname in file fp. Spaces
+before the princaname (in the file ) are not ignored
+spaces after the princname are ignored. If there are
+any tokens after the principal name  FALSE is returned.
+
+***********************************************************/
+
+krb5_error_code k5login_lookup (fp, princname, found)
+    FILE *fp;
+    char *princname;
+    krb5_boolean *found;
+{
+
+    krb5_error_code retval;
+    char * line;
+    char * fprinc;
+    char * lp;
+    krb5_boolean loc_found = FALSE;
+
+    retval = get_line(fp, &line);
+    if (retval)
+	return retval;
+
+    while (line){
+	fprinc = get_first_token (line, &lp);
+
+	if (fprinc && (!strcmp(princname, fprinc))){
+	    if( get_next_token (&lp) ){
+		free (line);
+		break;  /* nothing should follow princname*/
+	    }
+	    else{
+		loc_found = TRUE;
+		free (line);
+		break;
+	    }
+	}
+
+	free (line);
+
+	retval = get_line(fp, &line);
+	if (retval)
+	    return retval;
+    }
+
+
+    *found = loc_found;
+    return 0;
+
+}
+
+/***********************************************************
+k5users_lookup looks for princname in file fp. Spaces
+before the princaname (in the file ) are not ignored
+spaces after the princname are ignored.
+
+authorization alg:
+
+if princname is not found return false.
+
+if princname is found{
+	 if cmd == NULL then the file entry after principal
+			name must be nothing or *
+
+	 if cmd !=NULL  then entry must be matched (* is ok)
+}
+
+
+***********************************************************/
+krb5_error_code k5users_lookup (fp, princname, cmd, found, out_fcmd)
+    FILE *fp;
+    char *princname;
+    char *cmd;
+    krb5_boolean *found;
+    char **out_fcmd;
+{
+    krb5_error_code retval;
+    char * line;
+    char * fprinc, *fcmd;
+    char * lp;
+    char * loc_fcmd = NULL;
+    krb5_boolean loc_found = FALSE;
+
+    retval = get_line(fp, &line);
+    if (retval)
+	return retval;
+
+    while (line){
+	fprinc = get_first_token (line, &lp);
+
+	if (fprinc && (!strcmp(princname, fprinc))){
+	    fcmd = get_next_token (&lp);
+
+	    if ((fcmd) && (!strcmp(fcmd, PERMIT_ALL_COMMANDS))){
+		if (get_next_token(&lp) == NULL){
+		    loc_fcmd =cmd ? xstrdup(cmd): NULL;
+		    loc_found = TRUE;
+		}
+		free (line);
+		break;
+	    }
+
+	    if (cmd == NULL){
+		if (fcmd == NULL)
+		    loc_found = TRUE;
+		free (line);
+		break;
+
+	    }else{
+		if (fcmd != NULL) {
+		    char * temp_rfcmd, *err;
+		    krb5_boolean match;
+		    do {
+			if(match_commands(fcmd,cmd,&match,
+					  &temp_rfcmd, &err)){
+			    if (auth_debug){
+				fprintf(stderr,"%s",err);
+			    }
+			    loc_fcmd = err;
+			    break;
+			}else{
+			    if (match == TRUE){
+				loc_fcmd = temp_rfcmd;
+				loc_found = TRUE;
+				break;
+			    }
+			}
+
+		    }while ((fcmd = get_next_token( &lp)));
+		}
+		free (line);
+		break;
+	    }
+	}
+
+	free (line);
+
+	retval = get_line(fp, &line);
+	if (retval) { 
+	    return retval;
+	}
+    }
+
+    *out_fcmd = loc_fcmd;
+    *found = loc_found;
+    return 0;
+
+}
+
+
+/***********************************************
+fcmd_resolve -
+takes a command specified .k5users file and
+resolves it into a full path name.
+
+************************************************/
+
+krb5_boolean fcmd_resolve(fcmd, out_fcmd, out_err)
+    char *fcmd;
+    char ***out_fcmd;
+    char **out_err;
+{
+    char * out_path;
+    char * err;
+    char ** tmp_fcmd;
+    char * path_ptr, *path;
+    char * lp, * tc;
+    int i=0;
+
+    tmp_fcmd = (char **) xcalloc (MAX_CMD, sizeof(char *));
+
+    if (*fcmd == '/'){  /* must be full path */
+	tmp_fcmd[0] = xstrdup(fcmd);
+	tmp_fcmd[1] = NULL;
+	*out_fcmd = tmp_fcmd;
+	return TRUE;
+    }else{
+	/* must be either full path or just the cmd name */
+	if (strchr(fcmd, '/')){
+	    err = (char *) xcalloc((strlen(fcmd) +200) ,sizeof(char));
+	    sprintf(err,"Error: bad entry - %s in %s file, must be either full path or just the cmd name\n", fcmd, KRB5_USERS_NAME);
+	    *out_err = err;
+	    return FALSE;
+	}
+
+#ifndef CMD_PATH
+	err = (char *) xcalloc(2*(strlen(fcmd) +200) ,sizeof(char));
+	sprintf(err,"Error: bad entry - %s in %s file, since %s is just the cmd name, CMD_PATH must be defined \n", fcmd, KRB5_USERS_NAME, fcmd);
+	*out_err = err;
+	return FALSE;
+#else
+
+	path = xstrdup (CMD_PATH);
+	path_ptr = path;
+
+	while ((*path_ptr == ' ') || (*path_ptr == '\t')) path_ptr ++;
+
+	tc = get_first_token (path_ptr, &lp);
+
+	if (! tc){
+	    err = (char *) xcalloc((strlen(fcmd) +200) ,sizeof(char));
+	    sprintf(err,"Error: bad entry - %s in %s file, CMD_PATH contains no paths \n",  fcmd, KRB5_USERS_NAME);
+	    *out_err = err;
+	    return FALSE;
+	}
+
+	i=0;
+	do{
+	    if (*tc != '/'){  /* must be full path */
+		err = (char *) xcalloc((strlen(tc) +200) ,sizeof(char));
+		sprintf(err,"Error: bad path %s in CMD_PATH for %s must start with '/' \n",tc, KRB5_USERS_NAME );
+		*out_err = err;
+		return FALSE;
+	    }
+
+	    out_path = (char *) xmalloc(strlen(tc) + strlen(fcmd) + 2);
+	    sprintf(out_path,"%s/%s",tc, fcmd );
+
+	    tmp_fcmd[i] = out_path;
+
+	    i++;
+
+	} while((tc = get_next_token (&lp)));
+
+	tmp_fcmd[i] = NULL;
+	*out_fcmd = tmp_fcmd;
+	return TRUE;
+
+#endif /* CMD_PATH */
+    }
+}
+
+/********************************************
+cmd_single - checks if cmd consists of a path
+	     or a single token
+
+********************************************/
+
+krb5_boolean cmd_single(cmd)
+    char * cmd;
+{
+
+    if ( ( strrchr( cmd, '/')) ==  NULL){
+	return TRUE;
+    }else{
+	return FALSE;
+    }
+}
+
+/********************************************
+cmd_arr_cmp_postfix - compares a command with the postfix
+         of fcmd
+********************************************/
+
+int cmd_arr_cmp_postfix(fcmd_arr, cmd)
+    char **fcmd_arr;
+    char *cmd;
+{
+    char  * temp_fcmd;
+    char *ptr;
+    int result =1;
+    int i = 0;
+
+    while(fcmd_arr[i]){
+	if ( (ptr = strrchr( fcmd_arr[i], '/')) ==  NULL){
+	    temp_fcmd = fcmd_arr[i];
+	}else {
+	    temp_fcmd = ptr + 1;
+	}
+
+	result = strcmp (temp_fcmd, cmd);
+	if (result == 0){
+	    break;
+	}
+	i++;
+    }
+
+    return result;
+
+
+}
+
+/**********************************************
+cmd_arr_cmp - checks if cmd matches any
+              of the fcmd entries.
+
+**********************************************/
+
+int cmd_arr_cmp (fcmd_arr, cmd)
+    char **fcmd_arr;
+    char *cmd;
+{
+    int result =1;
+    int i = 0;
+
+    while(fcmd_arr[i]){
+	result = strcmp (fcmd_arr[i], cmd);
+	if (result == 0){
+	    break;
+	}
+	i++;
+    }
+    return result;
+}
+
+
+krb5_boolean find_first_cmd_that_exists(fcmd_arr, cmd_out, err_out)
+    char **fcmd_arr;
+    char **cmd_out;
+    char **err_out;
+{
+    struct stat st_temp;
+    int i = 0;
+    krb5_boolean retbool= FALSE;
+    int j =0;
+    char * err;
+    unsigned int max_ln=0;
+    unsigned int tln=0;
+
+    while(fcmd_arr[i]){
+	tln = strlen(fcmd_arr[i]);
+	if ( tln > max_ln) max_ln = tln;
+	if (!stat (fcmd_arr[i], &st_temp )){
+	    *cmd_out = xstrdup(fcmd_arr[i]);
+	    retbool = TRUE;
+	    break;
+	}
+	i++;
+    }
+
+    if (retbool == FALSE ){
+	err = (char *) xcalloc((80 + (max_ln+2)*i) ,sizeof(char));
+	strcpy(err,"Error: not found -> ");
+	for(j= 0; j < i; j ++){
+	    strcat(err, " ");
+	    strcat(err, fcmd_arr[j]);
+	    strcat(err, " ");
+	}
+	strcat(err, "\n");
+	*err_out = err;
+    }
+
+
+    return retbool;
+}
+
+/***************************************************************
+returns 1 if there is an error, 0 if no error.
+
+***************************************************************/
+
+int match_commands (fcmd, cmd, match, cmd_out, err_out)
+    char *fcmd;
+    char *cmd;
+    krb5_boolean *match;
+    char **cmd_out;
+    char **err_out;
+{
+    char ** fcmd_arr;
+    char * err;
+    char * cmd_temp;
+
+    if(fcmd_resolve(fcmd, &fcmd_arr, &err )== FALSE ){
+	*err_out = err;
+	return 1;
+    }
+
+    if (cmd_single( cmd ) == TRUE){
+	if (!cmd_arr_cmp_postfix(fcmd_arr, cmd)){ /* found */
+
+	    if(find_first_cmd_that_exists( fcmd_arr,&cmd_temp,&err)== TRUE){
+		*match = TRUE;
+		*cmd_out = cmd_temp;
+		return 0;
+	    }else{
+		*err_out = err;
+		return 1;
+	    }
+	}else{
+	    *match = FALSE;
+	    return 0;
+	}
+    }else{
+	if (!cmd_arr_cmp(fcmd_arr, cmd)){  /* found */
+	    *match = TRUE;
+	    *cmd_out = xstrdup(cmd);
+	    return 0;
+	} else{
+	    *match = FALSE;
+	    return 0;
+	}
+    }
+
+}
+
+/*********************************************************
+   get_line - returns a line of any length.  out_line
+	      is set to null if eof.
+*********************************************************/
+
+krb5_error_code get_line (fp, out_line)
+    /* IN */
+    FILE *fp;
+    /* OUT */
+    char **out_line;
+{
+    char * line, *r, *newline , *line_ptr;
+    int chunk_count = 1;
+
+    line = (char *) xcalloc (BUFSIZ, sizeof (char ));
+    line_ptr = line;
+    line[0] = '\0';
+
+    while (( r = fgets(line_ptr, BUFSIZ , fp)) != NULL){
+	newline = strchr(line_ptr, '\n');
+	if (newline) {
+	    *newline = '\0';
+	    break;
+	}
+	else {
+	    chunk_count ++;
+	    if(!( line = (char *) realloc( line,
+					   chunk_count * sizeof(char) * BUFSIZ))){
+		return  ENOMEM;
+	    }
+
+	    line_ptr = line + (BUFSIZ -1) *( chunk_count -1) ;
+	}
+    }
+
+    if ((r == NULL) && (strlen(line) == 0)) {
+	*out_line = NULL;
+    }
+    else{
+	*out_line = line;
+    }
+
+    return 0;
+}
+
+/*******************************************************
+get_first_token -
+Expects a '\0' terminated input line .
+If there are any spaces before the first token, they
+will be returned as part of the first token.
+
+Note: this routine reuses the space pointed to by line
+******************************************************/
+
+char *  get_first_token (line, lnext)
+    char *line;
+    char **lnext;
+{
+
+    char * lptr, * out_ptr;
+
+
+    out_ptr = line;
+    lptr = line;
+    
+    while (( *lptr == ' ') || (*lptr == '\t')) lptr ++;
+    
+    if (strlen(lptr) == 0) return NULL;
+    
+    while (( *lptr != ' ') && (*lptr != '\t') && (*lptr != '\0')) lptr ++;
+    
+    if (*lptr == '\0'){
+	*lnext = lptr;
+    } else{
+	*lptr = '\0';
+	*lnext = lptr + 1;
+    }
+    
+    return out_ptr;
+}
+/**********************************************************
+get_next_token -
+returns the next token pointed to by *lnext.
+returns NULL if there is no more tokens.
+Note: that this function modifies the stream
+      pointed to by *lnext and does not allocate
+      space for the returned tocken. It also advances
+      lnext to the next tocken.
+**********************************************************/
+
+char *  get_next_token (lnext)
+    char **lnext;
+{
+    char * lptr, * out_ptr;
+
+
+    lptr = *lnext;
+
+    while (( *lptr == ' ') || (*lptr == '\t')) lptr ++;
+
+    if (strlen(lptr) == 0) return NULL;
+
+    out_ptr = lptr;
+
+    while (( *lptr != ' ') && (*lptr != '\t') && (*lptr != '\0')) lptr ++;
+
+    if (*lptr == '\0'){
+	*lnext = lptr;
+    } else{
+	*lptr = '\0';
+	*lnext = lptr + 1;
+    }
+
+    return out_ptr;
+}
+
+static void auth_cleanup(users_fp, login_fp, princname)
+    FILE *users_fp;
+    FILE *login_fp;
+    char *princname;
+{
+
+    free (princname);
+    if (users_fp)
+	fclose(users_fp);
+    if (login_fp)
+	fclose(login_fp);
+}
+
+void init_auth_names(pw_dir)
+    char *pw_dir;
+{
+    if (strlen (k5login_path) + 2 + strlen (KRB5_LOGIN_NAME) >= MAXPATHLEN) {
+	fprintf (stderr,
+		 "home directory name `%s' too long, can't search for .k5login\n",
+		 pw_dir);
+	exit (1);
+    }
+    if ((strlen(pw_dir) == 1) && (*pw_dir == '/')){
+	sprintf(k5login_path,"%s%s", pw_dir, KRB5_LOGIN_NAME);
+	sprintf(k5users_path,"%s%s", pw_dir, KRB5_USERS_NAME);
+    } else {
+	sprintf(k5login_path,"%s/%s", pw_dir, KRB5_LOGIN_NAME);
+	sprintf(k5users_path,"%s/%s", pw_dir, KRB5_USERS_NAME);
+    }
+}
diff --git a/krb5-1-6/src/clients/ksu/ccache.c b/krb5-1-6/src/clients/ksu/ccache.c
new file mode 100644
index 000000000..5e9c5ec51
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/ccache.c
@@ -0,0 +1,819 @@
+/* 
+ * Copyright (c) 1994 by the University of Southern California
+ *
+ * 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 copy, modify, and distribute
+ *     this software and its documentation in source and binary forms is
+ *     hereby granted, provided that any documentation or other materials
+ *     related to such distribution or use acknowledge that the software
+ *     was developed by the University of Southern California. 
+ *
+ * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
+ *     University of Southern California MAKES NO REPRESENTATIONS OR
+ *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
+ *     limitation, the University of Southern California MAKES NO
+ *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+ *     PARTICULAR PURPOSE. The University of Southern
+ *     California shall not be held liable for any liability nor for any
+ *     direct, indirect, or consequential damages with respect to any
+ *     claim by the user or distributor of the ksu software.
+ *
+ * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+ */
+
+#include "ksu.h" 
+#include "adm_proto.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/******************************************************************
+krb5_cache_copy
+
+gets rid of any expired tickets in the secondary cache,
+copies the default cache into the secondary cache, 
+
+************************************************************************/
+
+void show_credential();
+
+/* modifies only the cc_other, the algorithm may look a bit funny,
+   but I had to do it this way, since remove function did not come 
+   with k5 beta 3 release.                                          
+*/
+
+krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag, 
+				  primary_principal, cc_out, stored, target_uid)
+    /* IN */
+    krb5_context context;
+    krb5_ccache cc_def;
+    char *cc_other_tag;
+    krb5_principal primary_principal;
+uid_t target_uid;
+    /* OUT */
+    krb5_ccache *cc_out;
+    krb5_boolean *stored;
+{
+int i=0; 
+krb5_ccache  * cc_other;
+const char * cc_def_name;
+const char * cc_other_name; 
+krb5_error_code retval=0;
+krb5_creds ** cc_def_creds_arr = NULL;
+krb5_creds ** cc_other_creds_arr = NULL;
+struct stat st_temp;
+
+    cc_other = (krb5_ccache *)  xcalloc(1, sizeof (krb5_ccache));  	
+
+    if ((retval = krb5_cc_resolve(context, cc_other_tag, cc_other))){
+               com_err (prog_name, retval, "resolving ccache %s",
+                        cc_other_tag);
+		return retval;
+    }
+
+    cc_def_name = krb5_cc_get_name(context, cc_def);    
+    cc_other_name = krb5_cc_get_name(context, *cc_other);    
+
+    if ( ! stat(cc_def_name, &st_temp)){
+	if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){
+		return retval;
+	}
+    }
+
+    *stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr,
+					   primary_principal);
+
+#ifdef HAVE_LSTAT
+    if (!lstat( cc_other_name, &st_temp))
+#else /*HAVE_LSTAT*/
+    if (!stat( cc_other_name, &st_temp))
+#endif
+      return EINVAL;
+    
+      if (krb5_seteuid(0)||krb5_seteuid(target_uid)) {
+	return errno;
+      }
+      
+      
+    if ((retval = krb5_cc_initialize(context, *cc_other, primary_principal))){
+	return retval; 
+    }
+
+    retval = krb5_store_all_creds(context, * cc_other, cc_def_creds_arr, 
+				  cc_other_creds_arr); 
+
+    if (cc_def_creds_arr){ 	
+ 	   while (cc_def_creds_arr[i]){
+    		krb5_free_creds(context, cc_def_creds_arr[i]);	
+		i++;
+    	   }
+    }	
+
+    i=0;
+
+    if(cc_other_creds_arr){	
+    	while (cc_other_creds_arr[i]){
+    		krb5_free_creds(context, cc_other_creds_arr[i]);	
+		i++;
+	}
+    }
+
+    *cc_out = *cc_other; 	
+    return retval;	
+}
+
+
+krb5_error_code krb5_store_all_creds(context, cc, creds_def, creds_other)
+    krb5_context context;
+    krb5_ccache cc;
+    krb5_creds **creds_def;
+    krb5_creds **creds_other;
+{
+
+int i = 0; 
+krb5_error_code retval = 0;  
+krb5_creds ** temp_creds= NULL;   
+
+	
+	if ((creds_def == NULL) && (creds_other == NULL)) 
+		return 0;	
+
+	if ((creds_def == NULL) && (creds_other != NULL)) 
+		temp_creds = creds_other; 		
+
+	if ((creds_def != NULL) && (creds_other == NULL)) 
+		temp_creds = creds_def; 		
+
+
+	if (temp_creds){	
+		while(temp_creds[i]){ 
+			if ((retval= krb5_cc_store_cred(context, cc, 
+							temp_creds[i]))){
+				return retval; 
+			}
+			i++;	
+		}
+	}	
+	else { /* both arrays have elements in them */       
+
+		return  KRB5KRB_ERR_GENERIC;
+
+/************	while(creds_other[i]){ 
+			cmp = FALSE;	
+			j = 0;			
+			while(creds_def[j]){ 
+			   cmp = compare_creds(creds_other[i],creds_def[j]);
+
+			   if( cmp == TRUE) break;    		
+
+			   j++; 	
+			}
+			if (cmp == FALSE){
+				if (retval= krb5_cc_store_cred(context, cc,
+							 creds_other[i])){
+						return retval; 
+				}
+			}
+			i ++;
+		}
+
+		i=0;	
+		while(creds_def[i]){ 
+			if (retval= krb5_cc_store_cred(context, cc, 
+						       creds_def[i])){
+				return retval; 
+			}
+			i++;	
+		}
+
+**************/
+	}
+	return 0;
+}
+
+krb5_boolean compare_creds(context, cred1, cred2)
+    krb5_context context;
+    krb5_creds *cred1;
+    krb5_creds *cred2;
+{
+krb5_boolean retval; 
+
+	retval = krb5_principal_compare (context, cred1->client, cred2->client);
+
+	if (retval == TRUE) 
+		retval = krb5_principal_compare (context, cred1->server, 							 cred2->server);
+
+	return retval;
+}
+
+
+
+ 
+krb5_error_code krb5_get_nonexp_tkts(context, cc, creds_array)
+    krb5_context context;
+    krb5_ccache cc;
+    krb5_creds ***creds_array;
+{
+
+krb5_creds creds, temp_tktq, temp_tkt;
+krb5_creds **temp_creds; 
+krb5_error_code retval=0;
+krb5_cc_cursor cur; 
+int count = 0;
+int chunk_count = 1; 
+	
+  if ( ! ( temp_creds = (krb5_creds **) malloc( CHUNK * sizeof(krb5_creds *)))){
+                return errno;
+        }
+
+
+   memset((char *) &temp_tktq, 0, sizeof(temp_tktq));
+   memset((char *) &temp_tkt, 0, sizeof(temp_tkt));
+   memset((char *) &creds, 0, sizeof(creds));
+
+	/* initialize the cursor */    	
+    if ((retval = krb5_cc_start_seq_get(context, cc, &cur))) {
+	return retval; 
+    }
+
+    while (!(retval = krb5_cc_next_cred(context, cc, &cur, &creds))){
+
+	if ((retval = krb5_check_exp(context, creds.times))){
+		if (retval != KRB5KRB_AP_ERR_TKT_EXPIRED){ 
+			return retval;
+		} 
+		if (auth_debug){ 
+			fprintf(stderr,"krb5_ccache_copy: CREDS EXPIRED:\n");  
+			fputs("  Valid starting		Expires		Service principal\n",stdout);
+			show_credential(context, &creds, cc); 
+			fprintf(stderr,"\n");  
+		}
+	}
+	else {   /* these credentials didn't expire */      
+	
+			if ((retval = krb5_copy_creds(context, &creds, 
+						      &temp_creds[count]))){
+			return retval;				
+		}
+		count ++;
+
+	 	if (count == (chunk_count * CHUNK -1)){
+               		  chunk_count ++;
+                	 if (!(temp_creds = (krb5_creds **) realloc(temp_creds,
+                       	       chunk_count * CHUNK * sizeof(krb5_creds *)))){
+                       	       return errno;
+                 	}
+         	}
+	}
+		
+    }
+
+    temp_creds[count] = NULL;	
+    *creds_array   = temp_creds; 	
+
+    if (retval == KRB5_CC_END) {
+		retval = krb5_cc_end_seq_get(context, cc, &cur);
+    }	
+
+    return retval;	
+
+}
+
+
+krb5_error_code krb5_check_exp(context, tkt_time)
+    krb5_context context;
+    krb5_ticket_times tkt_time;
+{
+krb5_error_code retval =0;
+krb5_timestamp currenttime;
+
+	if ((retval = krb5_timeofday (context, ¤ttime))){ 
+		return retval;		
+	}	
+	if (auth_debug){
+		fprintf(stderr,"krb5_check_exp: the krb5_clockskew is %d \n",
+			context->clockskew);
+
+		fprintf(stderr,"krb5_check_exp: currenttime - endtime %d \n",
+	(currenttime - tkt_time.endtime )); 
+		
+	}
+
+	if (currenttime - tkt_time.endtime > context->clockskew){ 
+		retval = KRB5KRB_AP_ERR_TKT_EXPIRED ;
+		return retval;
+	}
+
+	return 0;
+}
+
+
+char *flags_string(cred)
+    krb5_creds *cred;
+{
+    static char buf[32];
+    int i = 0;
+	
+    if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
+        buf[i++] = 'F';
+    if (cred->ticket_flags & TKT_FLG_FORWARDED)
+        buf[i++] = 'f';
+    if (cred->ticket_flags & TKT_FLG_PROXIABLE)
+        buf[i++] = 'P';
+    if (cred->ticket_flags & TKT_FLG_PROXY)
+        buf[i++] = 'p';
+    if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
+        buf[i++] = 'D';
+    if (cred->ticket_flags & TKT_FLG_POSTDATED)
+        buf[i++] = 'd';
+    if (cred->ticket_flags & TKT_FLG_INVALID)
+        buf[i++] = 'i';
+    if (cred->ticket_flags & TKT_FLG_RENEWABLE)
+        buf[i++] = 'R';
+    if (cred->ticket_flags & TKT_FLG_INITIAL)
+        buf[i++] = 'I';
+    if (cred->ticket_flags & TKT_FLG_HW_AUTH)
+        buf[i++] = 'H';
+    if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
+        buf[i++] = 'A';
+    buf[i] = '\0';
+    return(buf);
+}
+
+void printtime(tv)
+    time_t tv;
+{
+    char fmtbuf[18];
+    char fill;
+    krb5_timestamp tstamp;
+
+    /* XXXX ASSUMES sizeof(krb5_timestamp) >= sizeof(time_t) */
+    (void) localtime((time_t *)&tv);
+    tstamp = tv;
+    fill = ' ';
+    if (!krb5_timestamp_to_sfstring(tstamp,
+				    fmtbuf,
+				    sizeof(fmtbuf),
+				    &fill))
+	printf(fmtbuf);
+}
+
+
+krb5_error_code
+krb5_get_login_princ(luser, princ_list)
+    const char *luser;
+    char ***princ_list;
+{
+    struct stat sbuf;
+    struct passwd *pwd;
+    char pbuf[MAXPATHLEN];
+    FILE *fp;
+    char * linebuf;
+    char *newline;
+    int gobble;
+    char ** buf_out;
+    struct stat st_temp;
+    int count = 0, chunk_count = 1; 
+
+    /* no account => no access */
+
+    if ((pwd = getpwnam(luser)) == NULL) {
+	return 0;
+    }
+    if (strlen(pwd->pw_dir) + sizeof("/.k5login") > MAXPATHLEN) {
+	fprintf (stderr, "home directory path for %s too long\n", luser);
+	exit (1);
+    }
+    (void) strcpy(pbuf, pwd->pw_dir);
+    (void) strcat(pbuf, "/.k5login");
+
+    if (stat(pbuf, &st_temp)) {	 /* not accessible */
+	return 0;
+    }
+
+
+    /* open ~/.k5login */
+    if ((fp = fopen(pbuf, "r")) == NULL) {
+	return 0;
+    }
+    /*
+     * For security reasons, the .k5login file must be owned either by
+     * the user himself, or by root.  Otherwise, don't grant access.
+     */
+    if (fstat(fileno(fp), &sbuf)) {
+	fclose(fp);
+	return 0;
+    }
+    if ((sbuf.st_uid != pwd->pw_uid) && sbuf.st_uid) {
+	fclose(fp);
+	return 0;
+    }
+
+    /* check each line */
+
+
+    if( !(linebuf = (char *) calloc (BUFSIZ, sizeof(char)))) return errno; 
+
+    if (!(buf_out = (char **) malloc( CHUNK * sizeof(char *)))) return errno;
+
+    while ( fgets(linebuf, BUFSIZ, fp) != NULL) {
+	/* null-terminate the input string */
+	linebuf[BUFSIZ-1] = '\0';
+	newline = NULL;
+	/* nuke the newline if it exists */
+	if ((newline = strchr(linebuf, '\n')))
+	    *newline = '\0';
+
+	buf_out[count] = linebuf;
+        count ++;
+
+        if (count == (chunk_count * CHUNK -1)){
+            chunk_count ++;
+            if (!(buf_out = (char **) realloc(buf_out,
+                            chunk_count * CHUNK * sizeof(char *)))){
+                            return errno;
+            }
+        }
+
+	/* clean up the rest of the line if necessary */
+	if (!newline)
+	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
+
+    	if( !(linebuf = (char *) calloc (BUFSIZ, sizeof(char)))) return errno; 
+    }
+
+    buf_out[count] = NULL;
+    *princ_list = buf_out; 	
+    fclose(fp);
+    return 0;
+}
+
+
+
+void
+show_credential(context, cred, cc)
+    krb5_context context;
+    krb5_creds *cred;
+    krb5_ccache cc;
+{
+    krb5_error_code retval;
+    char *name, *sname, *flags;
+    int	first = 1;
+    krb5_principal princ;
+    char * defname;	
+    int show_flags =1;
+
+    retval = krb5_unparse_name(context, cred->client, &name);
+    if (retval) {
+	com_err(prog_name, retval, "while unparsing client name");
+	return;
+    }
+    retval = krb5_unparse_name(context, cred->server, &sname);
+    if (retval) {
+	com_err(prog_name, retval, "while unparsing server name");
+	free(name);
+	return;
+    }
+
+    if ((retval = krb5_cc_get_principal(context, cc, &princ))) {
+        com_err(prog_name, retval, "while retrieving principal name");
+	return;
+    }
+    if ((retval = krb5_unparse_name(context, princ, &defname))) {
+        com_err(prog_name, retval, "while unparsing principal name");
+	return;
+    }	
+
+    if (!cred->times.starttime)
+	cred->times.starttime = cred->times.authtime;
+
+    printtime(cred->times.starttime);
+    putchar(' '); putchar(' ');
+    printtime(cred->times.endtime);
+    putchar(' '); putchar(' ');
+
+    printf("%s\n", sname);
+
+    if (strcmp(name, defname)) {
+	    printf("\tfor client %s", name);
+	    first = 0;
+    }
+    
+    if (cred->times.renew_till) {
+	if (first)
+		fputs("\t",stdout);
+	else
+		fputs(", ",stdout);
+	fputs("renew until ", stdout);
+        printtime(cred->times.renew_till);
+    }
+    if (show_flags) {
+	flags = flags_string(cred);
+	if (flags && *flags) {
+	    if (first)
+		fputs("\t",stdout);
+	    else
+		fputs(", ",stdout);
+	    printf("Flags: %s", flags);
+	    first = 0;
+        }
+    }
+    putchar('\n');
+    free(name);
+    free(sname);
+}
+
+int gen_sym(){
+	static int i = 0; 
+	i ++;
+	return i;
+}
+
+krb5_error_code krb5_ccache_overwrite(context, ccs, cct, primary_principal)
+    krb5_context context;
+    krb5_ccache ccs;
+    krb5_ccache cct;
+    krb5_principal primary_principal;
+{
+const char * cct_name;
+const char * ccs_name; 
+krb5_error_code retval=0;
+krb5_principal temp_principal;
+krb5_creds ** ccs_creds_arr = NULL;
+int i=0; 
+struct stat st_temp;
+
+    ccs_name = krb5_cc_get_name(context, ccs);    
+    cct_name = krb5_cc_get_name(context, cct);    
+
+    if ( ! stat(ccs_name, &st_temp)){
+	if ((retval = krb5_get_nonexp_tkts(context,  ccs, &ccs_creds_arr))){
+		return retval;
+	}
+    }	
+
+    if ( ! stat(cct_name, &st_temp)){
+	if ((retval = krb5_cc_get_principal(context, cct, &temp_principal))){ 
+		return retval;
+	}
+    }else{
+	temp_principal = primary_principal; 
+    }
+
+    if ((retval = krb5_cc_initialize(context, cct, temp_principal))){
+	return retval; 
+    }
+
+    retval = krb5_store_all_creds(context, cct, ccs_creds_arr, NULL); 
+
+    if (ccs_creds_arr){ 	
+ 	   while (ccs_creds_arr[i]){
+    		krb5_free_creds(context, ccs_creds_arr[i]);	
+		i++;
+    	   }
+    }	
+
+    return retval;	
+}
+
+krb5_error_code krb5_store_some_creds(context, cc, creds_def, creds_other, prst,
+				      stored)
+    krb5_context context;
+    krb5_ccache cc;
+    krb5_creds **creds_def;
+    krb5_creds **creds_other;
+    krb5_principal prst;
+    krb5_boolean *stored;
+{
+
+int i = 0; 
+krb5_error_code retval = 0;  
+krb5_creds ** temp_creds= NULL;   
+krb5_boolean temp_stored = FALSE; 
+
+	
+	if ((creds_def == NULL) && (creds_other == NULL)) 
+		return 0;	
+
+	if ((creds_def == NULL) && (creds_other != NULL)) 
+		temp_creds = creds_other; 		
+
+	if ((creds_def != NULL) && (creds_other == NULL)) 
+		temp_creds = creds_def; 		
+
+
+	if (temp_creds){	
+		while(temp_creds[i]){ 
+			if (krb5_principal_compare(context, 
+						   temp_creds[i]->client,
+						   prst)== TRUE) {
+
+				if ((retval = krb5_cc_store_cred(context, 
+							cc,temp_creds[i]))){
+					return retval; 
+				}
+				temp_stored = TRUE;
+			}
+
+			i++;	
+		}
+	}	
+	else { /* both arrays have elements in them */       
+		return KRB5KRB_ERR_GENERIC;
+	}
+
+*stored = temp_stored;
+return 0;
+}
+/******************************************************************
+krb5_cache_copy_restricted
+
+gets rid of any expired tickets in the secondary cache,
+copies the default cache into the secondary cache,  
+only credentials that are for prst are copied.            
+
+the algorithm may look a bit funny,
+but I had to do it this way, since cc_remove function did not come 
+with k5 beta 3 release.                                          
+************************************************************************/
+
+krb5_error_code krb5_ccache_copy_restricted (context, cc_def, cc_other_tag, 
+					     prst, cc_out, stored, target_uid)
+    krb5_context context;
+    krb5_ccache cc_def;
+    char *cc_other_tag;
+    krb5_principal prst;
+uid_t target_uid;
+    /* OUT */
+    krb5_ccache *cc_out;
+    krb5_boolean *stored;
+{
+
+int i=0; 
+krb5_ccache  * cc_other;
+const char * cc_def_name;
+const char * cc_other_name; 
+krb5_error_code retval=0;
+krb5_creds ** cc_def_creds_arr = NULL;
+krb5_creds ** cc_other_creds_arr = NULL;
+struct stat st_temp;
+
+    cc_other = (krb5_ccache *)  xcalloc(1, sizeof (krb5_ccache));  	
+
+    if ((retval = krb5_cc_resolve(context, cc_other_tag, cc_other))){
+               com_err (prog_name, retval, "resolving ccache %s",
+                        cc_other_tag);
+		return retval;
+    }
+
+    cc_def_name = krb5_cc_get_name(context, cc_def);    
+    cc_other_name = krb5_cc_get_name(context, *cc_other);    
+
+    if ( ! stat(cc_def_name, &st_temp)){
+	if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){
+		return retval;
+	}
+
+    }
+
+#ifdef HAVE_LSTAT
+    if (!lstat( cc_other_name, &st_temp)) {
+#else /*HAVE_LSTAT*/
+    if (!stat( cc_other_name, &st_temp)) {
+#endif
+      return EINVAL;
+    }
+    
+      if (krb5_seteuid(0)||krb5_seteuid(target_uid)) {
+	return errno;
+      }
+      
+    
+    if ((retval = krb5_cc_initialize(context, *cc_other, prst))){
+	return retval; 
+    }
+
+    retval = krb5_store_some_creds(context, * cc_other, 
+			cc_def_creds_arr, cc_other_creds_arr, prst, stored); 
+
+
+
+    if (cc_def_creds_arr){ 	
+ 	   while (cc_def_creds_arr[i]){
+    		krb5_free_creds(context, cc_def_creds_arr[i]);	
+		i++;
+    	   }
+    }	
+
+    i=0;
+
+    if(cc_other_creds_arr){	
+    	while (cc_other_creds_arr[i]){
+    		krb5_free_creds(context, cc_other_creds_arr[i]);	
+		i++;
+	}
+    }
+
+    *cc_out = *cc_other; 	
+    return retval;	
+}
+
+krb5_error_code krb5_ccache_filter (context, cc, prst)
+    krb5_context context;
+    krb5_ccache cc;
+    krb5_principal prst;
+{
+
+int i=0; 
+krb5_error_code retval=0;
+krb5_principal temp_principal;
+krb5_creds ** cc_creds_arr = NULL;
+const char * cc_name;
+krb5_boolean stored;
+struct stat st_temp;
+
+    cc_name = krb5_cc_get_name(context, cc);    
+
+    if ( ! stat(cc_name, &st_temp)){
+
+	if (auth_debug) {  
+	      fprintf(stderr,"putting cache %s through a filter for -z option\n", 		      cc_name);
+	}
+
+	if ((retval = krb5_get_nonexp_tkts(context, cc, &cc_creds_arr))){
+		return retval;
+	}
+
+	if ((retval = krb5_cc_get_principal(context, cc, &temp_principal))){ 
+		return retval;
+	}
+
+    	if ((retval = krb5_cc_initialize(context, cc, temp_principal))){
+		return retval; 
+    	}
+
+	if ((retval = krb5_store_some_creds(context, cc, cc_creds_arr,
+					    NULL, prst, &stored))){ 
+		return retval; 
+    	}
+
+   	if (cc_creds_arr){ 	
+ 	  	 while (cc_creds_arr[i]){
+    			krb5_free_creds(context, cc_creds_arr[i]);	
+			i++;
+    	   	}
+    	}	
+    }
+    return 0;	
+}
+
+krb5_boolean  krb5_find_princ_in_cred_list (context, creds_list, princ)
+    krb5_context context;
+    krb5_creds **creds_list;
+    krb5_principal princ;
+{
+
+int i = 0; 
+krb5_boolean temp_stored = FALSE; 
+
+	if (creds_list){	
+		while(creds_list[i]){ 
+			if (krb5_principal_compare(context, 
+						   creds_list[i]->client,
+						   princ)== TRUE){
+				temp_stored = TRUE;
+				break;
+			}
+
+			i++;	
+		}
+	}	
+
+return temp_stored;
+}
+
+krb5_error_code  krb5_find_princ_in_cache (context, cc, princ, found)
+    krb5_context context;
+    krb5_ccache cc;
+    krb5_principal princ;
+    krb5_boolean *found;
+{
+krb5_error_code retval;
+krb5_creds ** creds_list = NULL;
+const char * cc_name;
+struct stat st_temp;
+
+    cc_name = krb5_cc_get_name(context, cc);    
+
+    if ( ! stat(cc_name, &st_temp)){
+	if ((retval = krb5_get_nonexp_tkts(context, cc, &creds_list))){
+		return retval;
+	}
+    }
+
+    *found = krb5_find_princ_in_cred_list(context, creds_list, princ); 
+return 0;
+}
diff --git a/krb5-1-6/src/clients/ksu/heuristic.c b/krb5-1-6/src/clients/ksu/heuristic.c
new file mode 100644
index 000000000..85b94b5e2
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/heuristic.c
@@ -0,0 +1,769 @@
+/*
+ * Copyright (c) 1994 by the University of Southern California
+ *
+ * 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 copy, modify, and distribute
+ *     this software and its documentation in source and binary forms is
+ *     hereby granted, provided that any documentation or other materials
+ *     related to such distribution or use acknowledge that the software
+ *     was developed by the University of Southern California.
+ *
+ * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
+ *     University of Southern California MAKES NO REPRESENTATIONS OR
+ *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
+ *     limitation, the University of Southern California MAKES NO
+ *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+ *     PARTICULAR PURPOSE. The University of Southern
+ *     California shall not be held liable for any liability nor for any
+ *     direct, indirect, or consequential damages with respect to any
+ *     claim by the user or distributor of the ksu software.
+ *
+ * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+ */
+
+#include "ksu.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+
+/*******************************************************************
+get_all_princ_from_file - retrieves all principal names
+			from file pointed to by fp.
+
+*******************************************************************/
+static void close_time (int, FILE *, int, FILE *);
+static krb5_boolean find_str_in_list (char **, char *);
+
+krb5_error_code get_all_princ_from_file (fp, plist)
+    FILE *fp;
+    char ***plist;
+{
+
+    krb5_error_code retval;
+    char * line, * fprinc, * lp, ** temp_list = NULL;
+    int count = 0, chunk_count = 1;
+
+    if (!(temp_list = (char **) malloc( CHUNK * sizeof(char *))))
+	return errno;
+
+    retval = get_line(fp, &line);
+    if (retval)
+	return retval;	
+
+    while (line){
+	fprinc = get_first_token (line, &lp);
+		
+	if (fprinc ){
+	    temp_list[count] = xstrdup(fprinc);
+	    count ++;
+	}
+
+	if(count == (chunk_count * CHUNK -1)){
+	    chunk_count ++;
+	    if (!(temp_list = (char **) realloc(temp_list,
+						chunk_count * CHUNK * sizeof(char *)))){
+		return errno;
+	    }
+	}
+
+
+	free (line);
+	retval = get_line(fp, &line);
+	if (retval)
+	    return retval;
+    }
+
+    temp_list[count] = NULL;
+
+    *plist = temp_list;
+    return 0;
+}
+
+/*************************************************************
+list_union - combines list1 and list2 into combined_list.
+	     the  space for list1 and list2 is either freed
+	     or used by combined_list.
+**************************************************************/
+
+krb5_error_code list_union(list1, list2, combined_list)
+    char **list1;
+    char **list2;
+    char ***combined_list;
+{
+
+    unsigned int c1 =0, c2 = 0, i=0, j=0;
+    char ** tlist;
+
+    if (! list1){   	
+	*combined_list = list2;   	
+	return 0;
+    }
+
+    if (! list2){   	
+	*combined_list = list1;   	
+	return 0;
+    }
+
+    while (list1[c1]) c1++;
+    while (list2[c2]) c2++;
+	
+    if (!(tlist = (char **) calloc( c1 + c2 + 1, sizeof ( char *))))
+	return errno;
+
+    i = 0;
+    while(list1[i]) {
+	tlist[i] = list1[i];
+	i++;
+    }
+    j = 0;
+    while(list2[j]){
+	if(find_str_in_list(list1, list2[j])==FALSE){   	
+	    tlist[i] = list2[j];
+	    i++;
+	}
+	j++;
+    }
+
+    free (list1); 	
+    free (list2); 	
+	
+    tlist[i]= NULL;
+
+    *combined_list = tlist;
+    return 0;
+}
+
+krb5_error_code
+filter(fp, cmd, k5users_list, k5users_filt_list)
+    FILE *fp;
+    char *cmd;
+    char **k5users_list;
+    char ***k5users_filt_list;
+{
+
+    krb5_error_code retval =0;
+    krb5_boolean found = FALSE;
+    char * out_cmd = NULL;
+    unsigned int i=0, j=0, found_count = 0, k=0;	
+    char ** temp_filt_list;
+
+    *k5users_filt_list = NULL;
+
+    if (! k5users_list){		
+	return 0;
+    }
+
+    while(k5users_list[i]){	
+
+	retval= k5users_lookup(fp, k5users_list[i], cmd, &found, &out_cmd);
+	if (retval)
+	    return retval;
+
+	if (found == FALSE){ 		
+	    free (k5users_list[i]);
+	    k5users_list[i] = NULL;
+	    if (out_cmd) gb_err = out_cmd;
+	} else
+	    found_count ++;	
+
+	i++;
+    }
+
+    if (! (temp_filt_list = (char **) calloc(found_count +1, sizeof (char*))))
+	return errno;
+
+    for(j= 0, k=0; j < i; j++ ) {	
+	if (k5users_list[j]){
+	    temp_filt_list[k] = k5users_list[j]; 		
+	    k++;
+	}
+    }
+
+    temp_filt_list[k] = NULL;
+
+    free (k5users_list);	
+
+    *k5users_filt_list = temp_filt_list;
+    return 0;
+}
+
+krb5_error_code
+get_authorized_princ_names(luser, cmd, princ_list)
+    const char *luser;
+    char *cmd;
+    char ***princ_list;
+{
+
+    struct passwd *pwd;
+    int k5login_flag =0;
+    int k5users_flag =0;
+    FILE * login_fp = NULL , * users_fp = NULL;
+    char **  k5login_list = NULL, ** k5users_list = NULL;
+    char ** k5users_filt_list = NULL;
+    char ** combined_list = NULL;
+    struct stat tb;
+    krb5_error_code retval;	
+
+    *princ_list = NULL; 	
+
+    /* no account => no access */
+
+    if ((pwd = getpwnam(luser)) == NULL)
+	return 0;
+
+    k5login_flag = stat(k5login_path, &tb);
+    k5users_flag = stat(k5users_path, &tb);
+
+    if (!k5login_flag){
+        if ((login_fp = fopen(k5login_path, "r")) == NULL)
+	    return 0;
+        if ( fowner(login_fp, pwd->pw_uid) == FALSE){
+	    close_time(1 /*k5users_flag*/, (FILE *) 0 /*users_fp*/, 
+		       k5login_flag,login_fp);
+	    return 0;
+        }
+    }
+    if (!k5users_flag){
+        if ((users_fp = fopen(k5users_path, "r")) == NULL)
+	    return 0;
+
+        if ( fowner(users_fp, pwd->pw_uid) == FALSE){
+	    close_time(k5users_flag,users_fp, k5login_flag,login_fp);
+	    return 0;
+        }
+
+	retval = get_all_princ_from_file (users_fp, &k5users_list);
+   	if(retval) {
+	    close_time(k5users_flag,users_fp, k5login_flag,login_fp);
+	    return retval;
+   	}
+
+	rewind(users_fp);	
+	
+	retval = filter(users_fp,cmd, k5users_list, &k5users_filt_list);
+	if(retval) {
+	    close_time(k5users_flag,users_fp, k5login_flag, login_fp);
+	    return retval;
+	}
+    }
+ 	
+    if (!k5login_flag){
+	retval = get_all_princ_from_file (login_fp, &k5login_list);
+   	if(retval) {
+	    close_time(k5users_flag,users_fp, k5login_flag,login_fp);
+	    return retval;
+   	}
+    }	
+
+    close_time(k5users_flag,users_fp, k5login_flag, login_fp);
+
+    if (cmd) {
+      retval = list_union(k5login_list, k5users_filt_list, &combined_list);
+      if (retval){
+	  close_time(k5users_flag,users_fp, k5login_flag,login_fp);
+	  return retval;
+      }
+      *princ_list = combined_list;
+      return 0;
+    } else {
+	if (k5users_filt_list != NULL)
+	    free(k5users_filt_list);
+	*princ_list = k5login_list;
+	return 0;
+    }
+}
+
+static void close_time(k5users_flag, users_fp, k5login_flag, login_fp)
+    int k5users_flag;
+    FILE *users_fp;
+    int k5login_flag;
+    FILE *login_fp;
+{
+
+    if (!k5users_flag) fclose(users_fp);
+    if (!k5login_flag) fclose(login_fp);
+
+}
+
+static krb5_boolean find_str_in_list(list , elm)
+    char **list;
+    char *elm;
+{
+
+    int i=0;
+    krb5_boolean found = FALSE;
+
+    if (!list) return found;
+
+    while (list[i] ){
+        if (!strcmp(list[i], elm)){
+	    found = TRUE;
+	    break;
+        }
+        i++;
+    }
+
+    return found;
+}
+
+/**********************************************************************
+returns the principal that is closes to client (can be the the client
+himself). plist contains
+a principal list obtained from .k5login and .k5users file.
+A principal is picked that has the best chance of getting in.
+
+**********************************************************************/
+
+
+krb5_error_code get_closest_principal(context, plist, client, found)
+    krb5_context context;
+    char **plist;
+    krb5_principal *client;
+    krb5_boolean *found;
+{
+    krb5_error_code retval =0;
+    krb5_principal temp_client, best_client = NULL;
+    int i = 0, j=0, cnelem, pnelem;
+    krb5_boolean got_one;
+	
+    *found = FALSE;
+
+    if (! plist ) return 0;
+
+    cnelem = krb5_princ_size(context, *client);
+
+    while(plist[i]){
+
+	retval = krb5_parse_name(context, plist[i], &temp_client);
+	if (retval)
+	    return retval;
+	
+	pnelem = krb5_princ_size(context, temp_client);
+	
+	if ( cnelem > pnelem){	
+	    i++;
+	    continue;
+	}
+	
+	if (krb5_princ_realm(context, *client)->length ==
+	    krb5_princ_realm(context, temp_client)->length
+	    && (!memcmp (krb5_princ_realm(context, *client)->data,
+			 krb5_princ_realm(context, temp_client)->data,
+			 krb5_princ_realm(context, temp_client)->length))){
+	    
+	    got_one = TRUE;
+	    for(j =0; j < cnelem; j ++){
+		krb5_data *p1 =
+		    krb5_princ_component(context, *client, j);
+		krb5_data *p2 =
+		    krb5_princ_component(context, temp_client, j);
+		
+		if (!p1 || !p2 || (p1->length != p2->length) ||
+		    memcmp(p1->data,p2->data,p1->length)){
+		    got_one = FALSE;
+		    break;
+		}
+	    }
+	    if (got_one == TRUE){		
+		if(best_client){
+		    if(krb5_princ_size(context, best_client) >
+		       krb5_princ_size(context, temp_client)){
+			best_client = temp_client;
+		    }
+		}else
+		    best_client = temp_client;
+	    }
+	}
+	i++;
+    }
+    
+    if (best_client) {
+	*found = TRUE;
+	*client = best_client;
+    }
+
+    return 0;
+}
+
+/****************************************************************
+find_either_ticket checks to see whether there is a ticket for the
+   end server or tgt, if neither is there the return FALSE,
+*****************************************************************/
+
+krb5_error_code find_either_ticket (context, cc, client, end_server, found)
+    krb5_context context;
+    krb5_ccache cc;
+    krb5_principal client;
+    krb5_principal end_server;
+    krb5_boolean *found;
+{
+
+    krb5_principal kdc_server;
+    krb5_error_code retval;
+    krb5_boolean temp_found = FALSE;
+    const char * cc_source_name;
+    struct stat st_temp;
+
+    cc_source_name = krb5_cc_get_name(context, cc);
+
+    if ( ! stat(cc_source_name, &st_temp)){
+
+	retval = find_ticket(context, cc, client, end_server, &temp_found);
+	if (retval)
+	    return retval;
+ 	
+	if (temp_found == FALSE){
+	    retval = ksu_tgtname(context,
+				  krb5_princ_realm(context, client),
+				  krb5_princ_realm(context, client),
+				  &kdc_server);
+	    if (retval)
+		return retval;
+
+	    retval = find_ticket(context, cc,client, kdc_server, &temp_found);
+	    if(retval)
+		return retval;
+	}
+	else if (auth_debug)
+	    printf("find_either_ticket: found end server ticket\n");
+    }
+
+    *found = temp_found;
+
+    return 0;
+}
+
+
+krb5_error_code find_ticket (context, cc, client, server, found)
+    krb5_context context;
+    krb5_ccache cc;
+    krb5_principal client;
+    krb5_principal server;
+    krb5_boolean *found;
+{
+
+    krb5_creds tgt, tgtq;
+    krb5_error_code retval;
+	
+    *found = FALSE;
+
+    memset((char *) &tgtq, 0, sizeof(tgtq));
+    memset((char *) &tgt, 0, sizeof(tgt));
+
+    retval= krb5_copy_principal(context,  client, &tgtq.client);
+    if (retval)
+	return retval; 	
+
+    retval= krb5_copy_principal(context,  server, &tgtq.server);
+    if (retval)
+	return retval ; 	
+
+    retval = krb5_cc_retrieve_cred(context, cc, KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES,
+				   &tgtq, &tgt);
+
+    if (! retval) retval = krb5_check_exp(context, tgt.times);
+
+    if (retval){
+	if ((retval != KRB5_CC_NOTFOUND) &&
+	    (retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){
+	    return retval ;
+	}
+    } else{
+	*found = TRUE;
+	return 0;	
+    }
+
+    free(tgtq.server);
+    free(tgtq.client);
+
+    return 0;
+}
+
+
+
+krb5_error_code find_princ_in_list (context, princ, plist, found)
+    krb5_context context;
+    krb5_principal princ;
+    char **plist;
+    krb5_boolean *found;
+{
+
+    int i=0;
+    char * princname;
+    krb5_error_code retval;
+
+    *found = FALSE;
+
+    if (!plist) return 0;
+
+    retval = krb5_unparse_name(context, princ, &princname);
+    if (retval)
+	return retval;
+
+    while (plist[i] ){
+	if (!strcmp(plist[i], princname)){
+	    *found = TRUE;
+	    break;
+	}
+	i++;
+    }
+
+    return 0;
+
+}
+
+typedef struct princ_info {
+	krb5_principal p;
+	krb5_boolean found;
+}princ_info;
+
+/**********************************************************************
+get_best_princ_for_target -
+
+sets the client name, path_out gets set, if authorization is not possible
+path_out gets set to ...
+
+***********************************************************************/
+
+krb5_error_code get_best_princ_for_target(context, source_uid, target_uid,
+					  source_user, target_user,
+					  cc_source, options, cmd,
+					  hostname, client, path_out)
+    krb5_context context;
+    uid_t source_uid;
+    uid_t target_uid;
+    char *source_user;
+    char *target_user;
+    krb5_ccache cc_source;
+    opt_info *options;
+    char *cmd;
+    char *hostname;
+    krb5_principal *client;
+    int *path_out;
+{
+
+    princ_info princ_trials[10];
+    const char * cc_source_name;
+    krb5_principal cc_def_princ = NULL;
+    krb5_principal temp_client;
+    krb5_principal target_client;
+    krb5_principal source_client;
+    krb5_principal end_server;
+    krb5_error_code retval;
+    char ** aplist =NULL;
+    krb5_boolean found = FALSE;
+    struct stat tb;
+    int count =0;
+    int i;
+    struct stat st_temp;
+
+    *path_out = 0;
+
+    /* -n option was specified client is set we are done */
+    if (options->princ)
+	return 0;
+
+    cc_source_name = krb5_cc_get_name(context, cc_source);
+
+	
+    if (! stat(cc_source_name, &st_temp)) {
+	retval = krb5_cc_get_principal(context, cc_source, &cc_def_princ);
+	if (retval)
+	    return retval;
+    }
+
+    retval=krb5_parse_name(context, target_user, &target_client);
+    if (retval)
+	return retval;
+
+    retval=krb5_parse_name(context, source_user, &source_client);
+    if (retval)
+	return retval;
+
+    if (source_uid == 0){
+	if (target_uid != 0)
+	    *client = target_client; /* this will be used to restrict
+					the cache copty */   	
+	else {
+	    if(cc_def_princ)
+		*client = cc_def_princ;
+	    else
+		*client = target_client;
+	}
+
+	if (auth_debug)
+	    printf(" GET_best_princ_for_target: via source_uid == 0\n");
+
+	return 0;
+    }
+
+    /* from here on, the code is for source_uid !=  0 */
+
+    if (source_uid && (source_uid == target_uid)){
+	if(cc_def_princ)
+	    *client = cc_def_princ;
+	else
+	    *client = target_client;
+	if (auth_debug)
+	    printf("GET_best_princ_for_target: via source_uid == target_uid\n");
+	return 0;
+    }
+
+    /* Become root, then target for looking at .k5login.*/
+    if (krb5_seteuid(0) || krb5_seteuid(target_uid) ) {
+      return errno;
+    }
+    
+    /* if .k5users and .k5login do not exist */  	
+    if (stat(k5login_path, &tb) && stat(k5users_path, &tb) ){
+	*client = target_client;
+
+	if (cmd)
+	    *path_out = NOT_AUTHORIZED;
+
+	if (auth_debug)
+	    printf(" GET_best_princ_for_target: via no auth files path\n");
+
+	return 0;	
+    }else{
+	retval = get_authorized_princ_names(target_user, cmd, &aplist);
+	if (retval)
+	    return retval;
+
+	/* .k5users or .k5login exist, but no authorization */
+	if ((!aplist) || (!aplist[0])) {
+	    *path_out = NOT_AUTHORIZED;
+	    if (auth_debug)
+		printf("GET_best_princ_for_target: via empty auth files path\n");
+	    return 0;	
+	}
+    }
+
+    retval = krb5_sname_to_principal(context, hostname, NULL,
+				     KRB5_NT_SRV_HST, &end_server);
+    if (retval)
+	return retval;
+
+
+    /* first see if default principal of the source cache
+     * can get us in, then the target_user@realm, then the
+     * source_user@realm. If all of them fail, try any
+     * other ticket in the cache. */
+
+    if (cc_def_princ)
+	princ_trials[count ++].p = cc_def_princ;
+    else
+	princ_trials[count ++].p = NULL;
+
+    princ_trials[count ++].p = target_client;
+    princ_trials[count ++].p = source_client;
+
+    for (i= 0; i < count; i ++)
+	princ_trials[i].found = FALSE;
+
+    for (i= 0; i < count; i ++){
+	if(princ_trials[i].p) {	
+	    retval= find_princ_in_list(context, princ_trials[i].p, aplist, 
+				       &found);
+	    if (retval)
+		return retval;	
+	
+	    if (found == TRUE){
+		princ_trials[i].found = TRUE;
+
+		retval = find_either_ticket (context, cc_source, 
+					     princ_trials[i].p,
+					     end_server, &found);
+ 		if (retval)
+		    return retval;
+		if (found == TRUE){
+		    *client = princ_trials[i].p;
+		    if (auth_debug)
+			printf("GET_best_princ_for_target: via ticket file, choice #%d\n", i);
+		    return 0;	
+		}
+	    }	
+	}
+    }
+
+    /* out of preferred principals, see if there is any ticket that will
+       get us in */
+
+    i=0;
+    while (aplist[i]){
+	retval = krb5_parse_name(context, aplist[i], &temp_client);
+ 	if (retval)
+	    return retval;
+
+	retval = find_either_ticket (context, cc_source, temp_client,
+				     end_server, &found);
+	if (retval)
+	    return retval;
+
+	if (found == TRUE){
+	    if (auth_debug)
+		printf("GET_best_princ_for_target: via ticket file, choice: any ok ticket \n" );
+	    *client = temp_client;
+	    return 0;	
+	}
+
+	krb5_free_principal(context, temp_client);
+
+	i++;
+    }
+
+    /* no tickets qualified, select a principal, that may be used
+       for password promting */
+
+
+    for (i=0; i < count; i ++){
+	if (princ_trials[i].found == TRUE){
+	    *client = princ_trials[i].p;
+
+	    if (auth_debug)
+		printf("GET_best_princ_for_target: via prompt passwd list choice #%d \n",i);
+	    return  0;	
+	}
+    }
+
+#ifdef PRINC_LOOK_AHEAD
+    for (i=0; i < count; i ++){
+	if (princ_trials[i].p){
+	    retval=krb5_copy_principal(context, princ_trials[i].p,
+				       &temp_client);
+	    if(retval)
+		return retval; 	
+
+	    /* get the client name that is the closest
+	       to the three princ in trials */
+
+	    retval=get_closest_principal(context, aplist, &temp_client, 
+					 &found);
+	    if(retval)
+		return retval; 	
+
+	    if (found == TRUE){
+		*client = temp_client; 	
+		if (auth_debug)
+		    printf("GET_best_princ_for_target: via prompt passwd list choice: approximation of princ in trials # %d \n",i);
+		return 0;
+	    }
+	    krb5_free_principal(context, temp_client);
+	}
+    }
+
+#endif /* PRINC_LOOK_AHEAD */
+
+
+    if(auth_debug)
+	printf( "GET_best_princ_for_target: out of luck, can't get appropriate default principal\n");
+
+    *path_out = NOT_AUTHORIZED;
+    return 0;
+}
diff --git a/krb5-1-6/src/clients/ksu/krb_auth_su.c b/krb5-1-6/src/clients/ksu/krb_auth_su.c
new file mode 100644
index 000000000..8e1834240
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/krb_auth_su.c
@@ -0,0 +1,584 @@
+/* 
+ * Copyright (c) 1994 by the University of Southern California
+ *
+ * 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 copy, modify, and distribute
+ *     this software and its documentation in source and binary forms is
+ *     hereby granted, provided that any documentation or other materials
+ *     related to such distribution or use acknowledge that the software
+ *     was developed by the University of Southern California. 
+ *
+ * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
+ *     University of Southern California MAKES NO REPRESENTATIONS OR
+ *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
+ *     limitation, the University of Southern California MAKES NO
+ *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+ *     PARTICULAR PURPOSE. The University of Southern
+ *     California shall not be held liable for any liability nor for any
+ *     direct, indirect, or consequential damages with respect to any
+ *     claim by the user or distributor of the ksu software.
+ *
+ * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+ */
+
+#include "ksu.h"
+    
+static krb5_error_code krb5_verify_tkt_def
+		  (krb5_context,
+    		   krb5_principal,
+    		   krb5_principal,
+    		   krb5_keyblock *,
+    		   krb5_data *,
+    		   krb5_ticket **);
+
+void plain_dump_principal ();
+
+/*
+ * Try no preauthentication first; then try the encrypted timestamp
+ */
+krb5_preauthtype * preauth_ptr = NULL;
+
+
+
+krb5_boolean krb5_auth_check(context, client_pname, hostname, options,
+			     target_user, cc, path_passwd, target_uid)
+    krb5_context context;
+    krb5_principal client_pname;
+    char *hostname;
+    opt_info *options;
+    char *target_user;
+    uid_t target_uid;
+    krb5_ccache cc;
+    int *path_passwd;
+{
+    krb5_principal client, server;
+    krb5_creds tgt, tgtq, in_creds, * out_creds;
+    krb5_creds **tgts = NULL; /* list of ticket granting tickets */       
+    
+    krb5_ticket * target_tkt; /* decrypted ticket for server */                
+    krb5_error_code retval =0;
+    int got_it = 0; 
+    krb5_boolean zero_password;
+    
+    *path_passwd = 0;
+    memset((char *) &tgtq, 0, sizeof(tgtq)); 
+    memset((char *) &tgt, 0, sizeof(tgt)); 
+    memset((char *) &in_creds, 0, sizeof(krb5_creds)); 
+    
+	
+    if ((retval= krb5_copy_principal(context,  client_pname, &client))){
+	com_err(prog_name, retval,"while copying client principal");   
+	return (FALSE) ; 	
+    }
+    
+    if (auth_debug) {
+	dump_principal(context, "krb5_auth_check: Client principal name", 
+		       client); 
+    }
+    
+    if ((retval = krb5_sname_to_principal(context, hostname, NULL,
+					  KRB5_NT_SRV_HST, &server))){
+	com_err(prog_name, retval, 
+		"while creating server %s principal name", hostname);  
+	krb5_free_principal(context, client);
+	return (FALSE) ; 	
+    }
+    
+    if (auth_debug) {
+	dump_principal(context, "krb5_auth_check: Server principal name", 
+		       server); 
+    }
+    
+    
+    
+    /* check if ticket is already in the cache, if it is
+       then use it.    
+       */
+    if( krb5_fast_auth(context, client, server, target_user, cc) == TRUE){
+	if (auth_debug ){ 	
+	    fprintf (stderr,"Authenticated via fast_auth \n");
+	}
+	return TRUE;
+    }
+    
+    /* check to see if the local tgt is in the cache */         
+    
+    if ((retval= krb5_copy_principal(context,  client, &tgtq.client))){
+	com_err(prog_name, retval,"while copying client principal");   
+	return (FALSE) ; 	
+    }
+    
+    if ((retval = ksu_tgtname(context,  krb5_princ_realm(context, client),
+			       krb5_princ_realm(context, client),
+			       &tgtq.server))){ 		
+	com_err(prog_name, retval, "while creating tgt for local realm");  
+	krb5_free_principal(context, client);
+	krb5_free_principal(context, server);
+	return (FALSE) ; 	
+    }	
+
+    if (auth_debug){ dump_principal(context, "local tgt principal name", tgtq.server ); } 	
+    retval = krb5_cc_retrieve_cred(context, cc,
+				   KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES,
+				   &tgtq, &tgt); 
+    
+    if (! retval) retval = krb5_check_exp(context, tgt.times);
+    
+    if (retval){	
+	if ((retval != KRB5_CC_NOTFOUND) &&  
+	    (retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){
+	    com_err(prog_name, retval, 
+		    "while retrieving creds from cache");
+	    return (FALSE) ; 	
+	}
+    } else{
+	got_it = 1;	
+    }
+    
+    if (! got_it){
+	
+#ifdef GET_TGT_VIA_PASSWD
+	if (krb5_seteuid(0)||krb5_seteuid(target_uid)) {
+	    com_err("ksu", errno, "while switching to target uid");
+	    return FALSE;
+	}
+	
+
+	fprintf(stderr,"WARNING: Your password may be exposed if you enter it here and are logged \n");
+	fprintf(stderr,"         in remotely using an unsecure (non-encrypted) channel. \n");
+	
+	/*get the ticket granting ticket, via passwd(promt for passwd)*/
+	if (krb5_get_tkt_via_passwd (context, &cc, client, tgtq.server,
+				     options, & zero_password) == FALSE){ 
+	    krb5_seteuid(0);
+	    
+	    return FALSE;
+	}
+	*path_passwd = 1;
+	if (krb5_seteuid(0)) {
+	    com_err("ksu", errno, "while reclaiming root uid");
+	    return FALSE;
+	}
+	
+#else
+	plain_dump_principal (context, client);
+	fprintf(stderr,"does not have any appropriate tickets in the cache.\n");
+	return FALSE;
+	
+#endif /* GET_TGT_VIA_PASSWD */ 
+
+    }
+    
+    if ((retval= krb5_copy_principal(context, client, &in_creds.client))){
+	com_err(prog_name, retval,"while copying client principal");   
+	return (FALSE) ; 	
+    }
+    
+    if ((retval= krb5_copy_principal(context, server, &in_creds.server))){
+	com_err(prog_name, retval,"while copying client principal");   
+	return (FALSE) ; 	
+    }
+    
+    if ((retval = krb5_get_cred_from_kdc(context, cc, &in_creds, 
+					 &out_creds, &tgts))){
+	com_err(prog_name, retval, "while geting credentials from kdc");  
+	return (FALSE);
+    }
+    
+
+    if (auth_debug){ 
+	fprintf(stderr,"krb5_auth_check: got ticket for end server \n"); 
+	dump_principal(context, "out_creds->server", out_creds->server ); 
+    } 	
+    
+    
+    if (tgts){   
+	register int i =0;
+	
+	if (auth_debug){	
+	    fprintf(stderr, "krb5_auth_check: went via multiple realms");
+	}
+	while (tgts[i]){
+	    if ((retval=krb5_cc_store_cred(context,cc,tgts[i]))) {
+		com_err(prog_name, retval,
+			"while storing credentials from cross-realm walk");
+		return (FALSE);
+	    }
+	    i++;
+	}
+	krb5_free_tgt_creds(context, tgts);
+    }
+    
+    retval = krb5_verify_tkt_def(context, client, server, 
+				 &out_creds->keyblock, &out_creds->ticket,
+				 &target_tkt);
+    if (retval) {
+	com_err(prog_name, retval, "while verifying ticket for server");
+	return (FALSE);
+    }
+    
+    if ((retval = krb5_cc_store_cred(context,  cc, out_creds))){
+	com_err(prog_name, retval,
+		"While storing credentials");
+	return (FALSE);
+    }
+
+    return (TRUE);
+}
+
+/* krb5_fast_auth checks if ticket for the end server is already in
+   the cache, if it is, we don't need a tgt */     
+
+krb5_boolean krb5_fast_auth(context, client, server, target_user, cc)
+    krb5_context context;
+    krb5_principal client;
+    krb5_principal server;
+    char *target_user;
+    krb5_ccache cc;
+{
+				 
+    krb5_creds tgt, tgtq;
+    krb5_ticket * target_tkt;                 
+    krb5_error_code retval;
+    
+    memset((char *) &tgtq, 0, sizeof(tgtq)); 
+    memset((char *) &tgt, 0, sizeof(tgt)); 
+    
+    if ((retval= krb5_copy_principal(context, client, &tgtq.client))){
+	com_err(prog_name, retval,"while copying client principal");   
+	return (FALSE) ; 	
+    }
+    
+    if ((retval= krb5_copy_principal(context, server, &tgtq.server))){
+	com_err(prog_name, retval,"while copying client principal");   
+	return (FALSE) ; 	
+    }
+    
+    if ((retval = krb5_cc_retrieve_cred(context, cc,
+					KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES,
+					&tgtq, &tgt))){ 
+	if (auth_debug)
+	    com_err(prog_name, retval,"While Retrieving credentials"); 
+	return (FALSE) ; 	
+	
+    }
+    
+    if ((retval = krb5_verify_tkt_def(context, client, server, &tgt.keyblock, 
+				      &tgt.ticket, &target_tkt))){
+	com_err(prog_name, retval, "while verifing ticket for server"); 
+	return (FALSE);
+    }
+    
+    return TRUE;
+}
+
+static krb5_error_code 
+krb5_verify_tkt_def(context, client, server, cred_ses_key, 
+		    scr_ticket, clear_ticket)
+    /* IN */
+    krb5_context context;
+    krb5_principal client;
+    krb5_principal server;
+    krb5_keyblock *cred_ses_key;
+    krb5_data *scr_ticket;
+    /* OUT */
+    krb5_ticket **clear_ticket;
+{
+    krb5_keytab keytabid;
+    krb5_enctype enctype;
+    krb5_keytab_entry ktentry;
+    krb5_keyblock *tkt_key = NULL;
+    krb5_ticket * tkt = NULL;
+    krb5_error_code retval =0;
+    krb5_keyblock *	tkt_ses_key;
+    
+    if ((retval = decode_krb5_ticket(scr_ticket, &tkt))){
+	return retval;
+    }
+    
+    if (server && !krb5_principal_compare(context, server, tkt->server)){
+	return KRB5KRB_AP_WRONG_PRINC;
+    }
+    
+    if (auth_debug){ 
+	fprintf(stderr,"krb5_verify_tkt_def: verified target server\n");
+	dump_principal(context, "server", server); 
+	dump_principal(context, "tkt->server", tkt->server); 
+    } 	
+    
+    /* get the default keytab */
+    if ((retval = krb5_kt_default(context, &keytabid))){
+	krb5_free_ticket(context, tkt);	
+	return retval;
+    }
+
+    enctype = tkt->enc_part.enctype;
+    
+    if ((retval = krb5_kt_get_entry(context, keytabid, server,
+				    tkt->enc_part.kvno, enctype, &ktentry))){
+	krb5_free_ticket(context, tkt);	
+	return retval;
+    }
+    
+    krb5_kt_close(context, keytabid);
+    
+    if ((retval = krb5_copy_keyblock(context, &ktentry.key, &tkt_key))){
+	krb5_free_ticket(context, tkt);	
+	krb5_kt_free_entry(context, &ktentry);
+	return retval;
+    }
+    
+    /* decrypt the ticket */  
+    if ((retval = krb5_decrypt_tkt_part(context, tkt_key, tkt))) {
+	krb5_free_ticket(context, tkt);	
+	krb5_kt_free_entry(context, &ktentry);
+	krb5_free_keyblock(context, tkt_key);
+	return(retval);
+    }
+
+    /* Check to make sure ticket hasn't expired */
+    retval = krb5_check_exp(context, tkt->enc_part2->times);
+    if (retval) {
+	if (auth_debug && (retval == KRB5KRB_AP_ERR_TKT_EXPIRED)) {
+	    fprintf(stderr,
+		    "krb5_verify_tkt_def: ticket has expired");
+	}
+	krb5_free_ticket(context, tkt);	
+	krb5_kt_free_entry(context, &ktentry);
+	krb5_free_keyblock(context, tkt_key);
+	return KRB5KRB_AP_ERR_TKT_EXPIRED;
+    }
+    
+    if (!krb5_principal_compare(context, client, tkt->enc_part2->client)) {
+	krb5_free_ticket(context, tkt);	
+	krb5_kt_free_entry(context, &ktentry);
+	krb5_free_keyblock(context, tkt_key);
+	return KRB5KRB_AP_ERR_BADMATCH;
+    }
+    
+    if (auth_debug){ 
+	fprintf(stderr,
+		"krb5_verify_tkt_def: verified client's identity\n");
+	dump_principal(context, "client", client);
+	dump_principal(context, "tkt->enc_part2->client",tkt->enc_part2->client);
+    } 	
+    
+    tkt_ses_key = tkt->enc_part2->session;	
+    
+    if (cred_ses_key->enctype != tkt_ses_key->enctype ||
+	cred_ses_key->length != tkt_ses_key->length ||
+	memcmp((char *)cred_ses_key->contents,
+	       (char *)tkt_ses_key->contents, cred_ses_key->length)) {
+	
+	krb5_free_ticket(context, tkt);	
+	krb5_kt_free_entry(context, &ktentry);
+	krb5_free_keyblock(context, tkt_key);
+	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    }
+    
+    if (auth_debug){ 
+	fprintf(stderr,
+		"krb5_verify_tkt_def: session keys match \n");
+    } 	
+    
+    *clear_ticket = tkt; 
+    krb5_kt_free_entry(context, &ktentry);
+    krb5_free_keyblock(context, tkt_key);
+    return 0; 	
+    
+}
+
+
+krb5_boolean krb5_get_tkt_via_passwd (context, ccache, client, server,
+				      options, zero_password)
+    krb5_context context;
+    krb5_ccache *ccache;
+    krb5_principal client;
+    krb5_principal server;
+    opt_info *options;
+    krb5_boolean *zero_password;
+{
+    krb5_error_code code;
+    krb5_creds my_creds;
+    krb5_timestamp now;
+    unsigned int pwsize;
+    char password[255], *client_name, prompt[255];
+
+
+    *zero_password = FALSE;	
+    
+    if ((code = krb5_unparse_name(context, client, &client_name))) {
+        com_err (prog_name, code, "when unparsing name");
+        return (FALSE);
+    }
+
+    memset((char *)&my_creds, 0, sizeof(my_creds));
+    
+    if ((code = krb5_copy_principal(context, client, &my_creds.client))){ 
+        com_err (prog_name, code, "while copying principal");
+	return (FALSE);	
+    }	
+
+    if ((code = krb5_copy_principal(context, server, &my_creds.server))){ 
+        com_err (prog_name, code, "while copying principal");
+	return (FALSE);	
+    }	
+
+    if ((code = krb5_timeofday(context, &now))) {
+	com_err(prog_name, code, "while getting time of day");
+	return (FALSE);	
+    }
+
+    my_creds.times.starttime = 0;	/* start timer when request
+					   gets to KDC */
+    
+    my_creds.times.endtime = now + options->lifetime;
+    if (options->opt & KDC_OPT_RENEWABLE) {
+	my_creds.times.renew_till = now + options->rlife;
+    } else
+	my_creds.times.renew_till = 0;
+
+    if (strlen (client_name) + 80 > sizeof (prompt)) {
+	fprintf (stderr,
+		 "principal name %s too long for internal buffer space\n",
+		 client_name);
+	return FALSE;
+    }
+    (void) sprintf(prompt,"Kerberos password for %s: ", client_name);
+    
+    pwsize = sizeof(password);
+    
+    code = krb5_read_password(context, prompt, 0, password, &pwsize);
+    if (code ) {
+	com_err(prog_name, code, "while reading password for '%s'\n",
+		client_name);
+	memset(password, 0, sizeof(password));
+	return (FALSE); 
+    }
+    
+    if ( pwsize == 0) {
+	fprintf(stderr, "No password given\n");
+	*zero_password = TRUE;
+	memset(password, 0, sizeof(password));
+	return (FALSE); 
+    }
+    
+    code = krb5_get_in_tkt_with_password(context, options->opt, 
+					 0, NULL, preauth_ptr,
+					 password, *ccache, &my_creds, 0);
+    memset(password, 0, sizeof(password));
+    
+    
+    if (code) {
+	if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+	    fprintf (stderr, "%s: Password incorrect\n", prog_name);
+	else
+	    com_err (prog_name, code, "while getting initial credentials");
+	return (FALSE);
+    }
+    return (TRUE);
+}
+
+
+void dump_principal (context, str, p)
+    krb5_context context;
+    char *str;
+    krb5_principal p;
+{
+    char * stname;
+    krb5_error_code retval; 
+
+    if ((retval = krb5_unparse_name(context, p, &stname))) {
+	fprintf(stderr, " %s while unparsing name\n", error_message(retval));
+    }
+    fprintf(stderr, " %s: %s\n", str, stname);
+}
+
+void plain_dump_principal (context, p)
+    krb5_context context;
+    krb5_principal p;
+{    
+    char * stname;
+    krb5_error_code retval; 
+
+    if ((retval = krb5_unparse_name(context, p, &stname)))
+	fprintf(stderr, " %s while unparsing name\n", error_message(retval));
+    fprintf(stderr, "%s ", stname);
+}
+
+
+/**********************************************************************
+returns the principal that is closest to client. plist contains
+a principal list obtained from .k5login and parhaps .k5users file.   
+This routine gets called before getting the password for a tgt.             
+A principal is picked that has the best chance of getting in.          
+
+**********************************************************************/
+
+
+krb5_error_code get_best_principal(context, plist, client)
+    krb5_context context;
+    char **plist;
+    krb5_principal *client;
+{
+    krb5_error_code retval =0; 
+    krb5_principal temp_client, best_client = NULL;
+    
+    int i = 0, nelem;
+    
+    if (! plist ) return 0;
+    
+    nelem = krb5_princ_size(context, *client);
+    
+    while(plist[i]){
+	
+	if ((retval = krb5_parse_name(context, plist[i], &temp_client))){
+	    return retval;
+	}
+	
+	if (krb5_princ_realm(context, *client)->length ==
+	    krb5_princ_realm(context, temp_client)->length  
+	    && (!memcmp (krb5_princ_realm(context, *client)->data,
+			 krb5_princ_realm(context, temp_client)->data,
+			 krb5_princ_realm(context, temp_client)->length))){
+	    
+	    
+	    if (nelem &&
+		krb5_princ_size(context, *client) > 0 &&
+		krb5_princ_size(context, temp_client) > 0) {
+		krb5_data *p1 =
+		    krb5_princ_component(context, *client, 0);
+		krb5_data *p2 = 
+		    krb5_princ_component(context, temp_client, 0);
+		
+		if ((p1->length == p2->length) &&
+		    (!memcmp(p1->data,p2->data,p1->length))){
+		    
+		    if (auth_debug){
+			fprintf(stderr,
+				"get_best_principal: compare with %s\n",
+				plist[i]);
+		    }
+		    
+		    if(best_client){
+			if(krb5_princ_size(context, best_client) >
+			   krb5_princ_size(context, temp_client)){
+			    best_client = temp_client;
+			}
+		    }else{
+			best_client = temp_client;
+		    }
+		}
+	    }
+	    
+	}
+	i++;
+    }
+    
+    if (best_client) *client = best_client;
+    return 0;
+}
diff --git a/krb5-1-6/src/clients/ksu/ksu.M b/krb5-1-6/src/clients/ksu/ksu.M
new file mode 100644
index 000000000..aeceaad30
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/ksu.M
@@ -0,0 +1,481 @@
+.\" Copyright (c) 1994 by the University of Southern California
+.\"
+.\" 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 copy, modify, and distribute
+.\"     this software and its documentation in source and binary forms is
+.\"     hereby granted, provided that any documentation or other materials
+.\"     related to such distribution or use acknowledge that the software
+.\"     was developed by the University of Southern California. 
+.\"
+.\" DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
+.\"     University of Southern California MAKES NO REPRESENTATIONS OR
+.\"     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
+.\"     limitation, the University of Southern California MAKES NO
+.\"     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+.\"     PARTICULAR PURPOSE. The University of Southern
+.\"     California shall not be held liable for any liability nor for any
+.\"     direct, indirect, or consequential damages with respect to any
+.\"     claim by the user or distributor of the ksu software.
+.\"
+.\" KSU was writen by:  Ari Medvinsky, ari@isi.edu
+.\" "
+.TH KSU 1
+.SH NAME
+ksu \- Kerberized super-user    	
+.SH SYNOPSIS
+.B ksu 
+[
+.I target_user
+] [
+.B \-n
+.I target_principal_name 
+] [
+.B \-c
+.I source_cache_name
+] [
+.B \-k
+] [
+.B \-D
+] [
+.B \-r
+.I time
+] [
+.B \-pf
+] [
+.B \-l 
+.I lifetime
+] [
+.B \-zZ
+] [
+.B \-q
+] [
+.B \-e
+.I command
+[
+.I args ...
+] ] [
+.B \-a 
+[
+.I args ...
+] ] 
+.br
+.SH REQUIREMENTS
+Must have Kerberos version 5 installed to compile ksu.
+Must have a Kerberos version 5 server running to use ksu.
+.br
+.SH DESCRIPTION
+.I ksu
+is a Kerberized version of the su program that has two missions:
+one is to securely change the real and effective user ID to that
+of the target user, and the other is to create a new security context.
+For the sake of clarity, all references to and attributes of
+the user invoking the program will start with 'source' (e.g.
+source user, source cache, etc.).  Likewise, all references
+to and attributes of the target account will start with 'target'.
+.br
+.SH AUTHENTICATION
+To fulfill the first mission, ksu operates in two phases: authentication
+and authorization.  Resolving the target principal name is the
+first step in authentication.  The user
+can either specify his principal name with the
+.B \-n
+option
+(e.g.
+.B \-n
+jqpublic@USC.EDU) or a default principal name will be assigned
+using a heuristic described in the OPTIONS section (see
+.B \-n
+option).
+The target user name must be the first argument to ksu; if not specified
+root is the default.  If '.' is specified then the target user will be
+the source user (e.g. ksu .). 
+If the source user is root or the target user is the source user, no 
+authentication or authorization takes place.  Otherwise, ksu looks
+for an appropriate Kerberos ticket in the source cache.
+.PP
+The ticket can either be for
+the end-server
+or a ticket granting ticket (TGT) for the target principal's realm.  If the
+ticket for the end-server is already in the cache, it's decrypted and
+verified.  If it's not in the cache but the TGT is, the TGT is used to
+obtain the ticket for the end-server.   The end-server ticket is then
+verified.  If neither ticket is in the cache, but ksu is compiled
+with the GET_TGT_VIA_PASSWD define, the user will be prompted
+for a Kerberos password which will then be used to get a TGT.
+If the user is logged in remotely and
+does not have a secure channel, the password may be exposed.
+If neither ticket is in the cache and GET_TGT_VIA_PASSWD is not defined,
+authentication fails.
+.br
+.SH AUTHORIZATION
+This section describes authorization of the source user when ksu
+is invoked without the
+.B \-e
+option.
+For a description of the
+.B \-e
+option, see the OPTIONS section.
+.PP
+Upon successful authentication, ksu checks whether the target principal
+is authorized to access the target account.
+In the target user's home directory, ksu attempts to access
+two authorization files: .k5login and .k5users.  In the .k5login  
+file each line contains the name of a
+principal that is authorized to access the account.
+.TP 12
+For example:
+jqpublic@USC.EDU
+.br
+jqpublic/secure@USC.EDU
+.br
+jqpublic/admin@USC.EDU
+.PP
+The format of .k5users is the same, except the
+principal name may be followed by a list of commands that
+the principal is authorized to execute. (see the
+.B \-e
+option in the OPTIONS section for details).
+.PP
+Thus if the target principal
+name is found in the .k5login file the source user is authorized to access
+the target account. Otherwise ksu looks in the .k5users file.
+If the target principal name is found without any trailing commands
+or followed only by '*' then the source user is authorized.  
+If either .k5login or .k5users exist but an appropriate entry for the target
+principal does not exist then access is denied. If neither
+file exists then the principal will be granted access 
+to the account according to the aname\->lname mapping rules (see
+.IR krb5_anadd(8) 
+for more details).
+Otherwise, authorization fails.
+.br
+.SH EXECUTION OF THE TARGET SHELL
+Upon successful authentication and authorization, ksu
+proceeds in a similar fashion to su.  The environment
+is unmodified with the exception of USER, HOME and SHELL variables.
+If the target user is not root, USER gets set to the target user
+name. Otherwise USER remains unchanged. Both HOME and SHELL are
+set to the target login's default values.
+In addition, the environment variable KRB5CCNAME gets set to the
+name of the target cache.
+The real and effective user ID are changed to that of the
+target user.  The target user's shell is then invoked
+(the shell name is specified in the password file).
+Upon termination of the shell, ksu deletes the target cache (unless
+ksu is invoked with the
+.B \-k option).
+This is implemented by first doing a fork and then an exec, instead
+of just exec, as done by su.
+.br
+.SH CREATING A NEW SECURITY CONTEXT
+.PP
+Ksu can be used to create a new security context for the
+target program (either the target
+shell, or command specified via the -e option).
+The target program inherits a set
+of credentials from the source user.
+By default, this set includes all of the credentials
+in the source cache plus any
+additional credentials obtained during authentication.
+The source user is able to limit the credentials in this set
+by using -z or -Z option.
+-z restricts the copy of tickets from the source cache
+to the target cache to only the tickets where client ==
+the target principal name.  The -Z option
+provides the target user with a fresh target cache
+(no creds in the cache). Note that for security reasons,
+when the source user is root and target user is non-root,
+-z option is the default mode of operation. 
+
+While no authentication takes place if the source user
+is root or is the same as the target user, additional
+tickets can still be obtained for the target cache.
+If -n is specified and no credentials can be copied to the target
+cache,  the  source user is prompted for a Kerberos password
+(unless -Z specified or GET_TGT_VIA_PASSWD is undefined). If
+successful,  a  TGT is obtained from the Kerberos server and
+stored in the target cache.  Otherwise,
+if a password is not provided (user hit return)
+ksu continues  in  a
+normal  mode  of  operation (the target cache will
+not contain the desired TGT).
+If the wrong password is typed in, ksu fails.
+.PP
+\fISide Note:\fP during authentication, only the tickets that could be
+obtained without providing a password are cached in
+in the source cache.
+.SH OPTIONS
+.TP 10
+\fB\-n \fItarget_principal_name
+Specify a Kerberos target principal name.
+Used in authentication and authorization
+phases of ksu.
+
+If ksu is invoked without
+.B \-n,
+a default principal name is
+assigned via the following heuristic:
+
+\fICase 1:\fP source user is non-root.
+.br
+If the target user is the source user the default principal name
+is set to the default principal of the source cache. If the
+cache does not exist then the default principal name is set to
+target_user@local_realm.
+If the source and target users are different and
+neither ~target_user/.k5users
+nor ~target_user/.k5login exist then
+the default principal name is
+target_user_login_name@local_realm. Otherwise,
+starting with the first principal listed below,
+ksu checks if the principal is authorized
+to  access the target account and whether
+there is a legitimate ticket for that principal
+in the source cache. If both conditions are met
+that principal becomes the default target principal,
+otherwise go to the next principal.
+
+a) default principal of the source cache
+.br
+b) target_user@local_realm
+.br
+c) source_user@local_realm
+
+If a-c fails try any principal for which there is
+a ticket in the source cache and that is
+authorized to access the target account.
+If that fails select the first principal that
+is authorized to access the target account from
+the above list.
+If none are authorized and ksu is configured with PRINC_LOOK_AHEAD
+turned on, select the default principal as follows:
+
+For each candidate in the above list,
+select an authorized principal that has
+the same realm name and first part
+of the principal name equal to the prefix of the candidate.
+For example if candidate a) is jqpublic@ISI.EDU and jqpublic/secure@ISI.EDU
+is authorized to access the target account then the default principal
+is set to jqpublic/secure@ISI.EDU.
+
+\fICase 2:\fP source user is root.
+.br
+If the target user is non-root then the
+default principal name is target_user@local_realm.
+Else, if the source cache exists the default
+principal name is set to the default principal
+of the source cache. If the source cache does not
+exist, default principal name is set to
+root@local_realm.
+.TP 10
+\fB\-c \fIsource_cache_name
+Specify source cache name (e.g.
+.B \-c
+FILE:/tmp/my_cache).
+If
+.B \-c
+option is not used then the
+name is obtained from KRB5CCNAME environment variable.
+If KRB5CCNAME is not defined the source cache name
+is set to krb5cc_<source uid>.
+The target cache name is automatically
+set to krb5cc_<target uid>.(gen_sym()),
+where gen_sym generates a new number such that
+the resulting cache does not already exist.
+.br
+For example: krb5cc_1984.2
+.TP 10
+\fB\-k
+Do not delete the target cache upon termination of the
+target shell or a command (
+.B \-e
+command).
+Without
+.B \-k,
+ksu deletes the target cache.
+.TP 10
+\fB\-D
+turn on debug mode.
+.TP 10
+\fITicket granting ticket options: -l lifetime -r time -pf\fP
+The ticket granting ticket options only apply to the
+case where there are no appropriate tickets in
+the cache to authenticate the source user. In this case
+if ksu is configured to prompt users for a
+Kerberos password (GET_TGT_VIA_PASSWD is defined),
+the ticket granting
+ticket options that are specified will be used
+when getting a ticket granting ticket from the Kerberos
+server.
+.TP 10
+\fB\-l \fIlifetime
+option specifies the lifetime to be
+requested for the ticket; if this option is not
+specified, the  default ticket lifetime
+(configured by each site) is used instead.
+.TP 10
+\fB\-r \fItime
+option  specifies  that  the  RENEWABLE  option
+should be requested for the ticket, and specifies
+the desired total lifetime of the ticket.
+.TP 10
+\fB\-p
+option specifies that the PROXIABLE option should  be
+requested for the ticket.
+.TP 10
+\fB\-f
+option specifies that the FORWARDABLE  option  should
+be requested for the ticket.
+.TP 10
+\fB\-z
+restrict the copy of tickets from the source cache
+to the target cache to only the tickets where client ==
+the target principal name. Use the
+.B \-n
+option
+if you want the tickets for other then the default
+principal. Note that the
+.B \-z 
+option is mutually
+exclusive with the -Z option.
+.TP 10
+\fB\-Z
+Don't copy any tickets from the source cache to the
+target cache. Just create a fresh target cache,
+where the default principal name of the cache is
+initialized to the target principal name.  Note that
+.B \-Z
+option is mutually
+exclusive with the -z option.
+.TP 10
+\fB\-q
+suppress the printing of status messages.
+.TP 10
+\fB\-e \fIcommand [args ...]
+ksu proceeds exactly the same as if it was invoked without the
+.B \-e
+option,
+except instead of executing the target shell, ksu executes the
+specified command (Example of usage: ksu bob
+.B \-e
+ls
+.B \-lag).
+
+\fIThe authorization algorithm for -e is as follows:\fP
+
+If the source user is root or source user == target user,
+no authorization takes place and             
+the command is executed.  If source user id != 0, and ~target_user/.k5users
+file does not exist, authorization fails.
+Otherwise, ~target_user/.k5users file must have an
+appropriate entry for target principal
+to get authorized.
+
+\fIThe .k5users file format:\fP
+
+A single principal entry on each line
+that may be followed by a list of commands that
+the principal is authorized to execute.
+A principal name followed by a '*' means
+that the user is authorized to execute
+any command. Thus, in the following example:
+
+jqpublic@USC.EDU ls mail /local/kerberos/klist
+.br
+jqpublic/secure@USC.EDU *
+.br
+jqpublic/admin@USC.EDU
+
+jqpublic@USC.EDU is only authorized to execute ls, mail
+and klist commands. jqpublic/secure@USC.EDU is authorized
+to execute any command. jqpublic/admin@USC.EDU is not
+authorized to execute any command.  Note, that
+jqpublic/admin@USC.EDU is authorized to execute
+the target shell (regular ksu, without the
+.B \-e
+option) but jqpublic@USC.EDU is not.
+
+The commands listed after the principal name must
+be either a full path names or just the program name.
+In the second case, CMD_PATH specifying the location
+of authorized programs must be defined at the
+compilation time of ksu.               
+
+\fIWhich command gets executed ?\fP
+
+If the source user is root or
+the target user is the source user or 
+the user
+is authorized to execute any command ('*' entry)
+then command can be either a full or a relative
+path leading to the target program.
+Otherwise, the user must specify either a full
+path or just the program name.
+.TP 10
+\fB\-a \fIargs
+specify arguments to be passed to the target shell.
+Note: that all flags and parameters following -a
+will be passed to the shell, thus all options
+intended for ksu must precede
+.B \-a.
+The
+.B \-a
+option can be used to simulate the
+.B \-e
+option if used as follows:
+.B \-a
+.B \-c
+[command [arguments]].
+.B \-c
+is interpreted by the c-shell to execute the command.
+.PP
+.SH INSTALLATION INSTRUCTIONS
+ksu can be compiled with the following 4 flags (see the Imakefile):
+.TP 10
+\fIGET_TGT_VIA_PASSWD\fP 
+in case no appropriate tickets are found in the source
+cache, the user will be prompted for a Kerberos
+password.  The password is then used to get a
+ticket granting ticket from the Kerberos server.
+The danger of configuring ksu with this macro is
+if the source user is loged in remotely and does not
+have a secure channel, the password may get exposed.
+.TP 10
+\fIPRINC_LOOK_AHEAD\fP
+during the resolution of the default principal name,
+PRINC_LOOK_AHEAD enables ksu to find principal names          
+in the .k5users file as described in the OPTIONS section
+(see -n option).      
+.TP 10
+\fICMD_PATH\fP
+specifies a list of directories containing programs
+that users are authorized to execute (via .k5users file). 
+.TP 10
+\fIHAS_GETUSERSHELL\fP
+If the source user is non-root, ksu insists that
+the target user's shell to be invoked
+is a "legal shell". getusershell(3) is called to obtain
+the names of "legal shells".  Note that the target user's    
+shell is obtained from the passwd file.
+.TP 10
+SAMPLE CONFIGURATION:
+KSU_OPTS = -DGET_TGT_VIA_PASSWD 
+-DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /usr/ucb /local/bin"
+.TP 10
+PERMISSIONS FOR KSU
+ksu should be owned by root and have the set user id  bit turned on.   
+.TP 10
+END-SERVER ENTRY     
+
+ksu attempts to get a ticket for the end server just as Kerberized
+telnet and rlogin.  Thus, there must be an entry for the server in the
+Kerberos database (e.g. host/nii.isi.edu@ISI.EDU).  The keytab file must
+be in an appropriate location.
+
+.SH SIDE EFFECTS
+ksu deletes all expired tickets from the source cache. 
+.SH AUTHOR OF KSU:	GENNADY (ARI) MEDVINSKY
diff --git a/krb5-1-6/src/clients/ksu/ksu.h b/krb5-1-6/src/clients/ksu/ksu.h
new file mode 100644
index 000000000..7b6bbebbe
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/ksu.h
@@ -0,0 +1,254 @@
+/* 
+ * Copyright (c) 1994 by the University of Southern California
+ *
+ * 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 copy, modify, and distribute
+ *     this software and its documentation in source and binary forms is
+ *     hereby granted, provided that any documentation or other materials
+ *     related to such distribution or use acknowledge that the software
+ *     was developed by the University of Southern California. 
+ *
+ * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
+ *     University of Southern California MAKES NO REPRESENTATIONS OR
+ *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
+ *     limitation, the University of Southern California MAKES NO
+ *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+ *     PARTICULAR PURPOSE. The University of Southern
+ *     California shall not be held liable for any liability nor for any
+ *     direct, indirect, or consequential damages with respect to any
+ *     claim by the user or distributor of the ksu software.
+ *
+ * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+ */
+
+#include "k5-int.h"
+#include "k5-util.h"
+#include <stdio.h>
+#include "com_err.h"
+#include <sys/types.h> 
+#include <sys/param.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+/* <stdarg.h> or <varargs.h> is already included by com_err.h.  */
+
+#define NO_TARGET_FILE '.'
+#define SOURCE_USER_LOGIN "."
+
+#define KRB5_DEFAULT_OPTIONS 0
+#define KRB5_DEFAULT_TKT_LIFE 60*60*12 /* 12 hours */
+
+#define KRB5_SECONDARY_CACHE "FILE:/tmp/krb5cc_"
+
+#define KRB5_LOGIN_NAME ".k5login"
+#define KRB5_USERS_NAME ".k5users"
+#define USE_DEFAULT_REALM_NAME "."
+#define PERMIT_ALL_COMMANDS "*" 
+#define KRB5_SEC_BUFFSIZE 80
+#define NOT_AUTHORIZED 1
+
+#define CHUNK 3
+#define CACHE_MODE 0600
+#define MAX_CMD 2048 /* this is temp, should use realloc instead,          
+			as done in most of the code */       
+		      
+
+extern int optind;
+extern char * optarg;
+
+/* globals */
+extern char * prog_name;
+extern int auth_debug;
+extern int quiet;
+extern char k5login_path[MAXPATHLEN];
+extern char k5users_path[MAXPATHLEN];
+extern char * gb_err;
+/***********/
+
+typedef struct opt_info{
+	int opt;
+	krb5_deltat lifetime;
+	krb5_deltat rlife;
+	int princ;
+}opt_info;
+
+/* krb_auth_su.c */
+extern krb5_boolean krb5_auth_check
+        (krb5_context, krb5_principal, char *, opt_info *,
+		   char *, krb5_ccache, int *, uid_t);
+
+extern krb5_boolean krb5_fast_auth
+        (krb5_context, krb5_principal, krb5_principal, char *,
+		   krb5_ccache);
+
+extern krb5_boolean krb5_get_tkt_via_passwd 
+	(krb5_context, krb5_ccache *, krb5_principal,
+		   krb5_principal, opt_info *, krb5_boolean *);
+
+extern void dump_principal 
+	(krb5_context, char *, krb5_principal);
+
+extern void plain_dump_principal 
+	(krb5_context, krb5_principal);
+
+
+extern krb5_error_code krb5_parse_lifetime
+	(char *, long *);
+
+extern krb5_error_code get_best_principal
+	(krb5_context, char **, krb5_principal *);
+
+/* ccache.c */
+extern krb5_error_code krb5_ccache_copy
+	(krb5_context, krb5_ccache, char *, krb5_principal, 
+		   krb5_ccache *, krb5_boolean *, uid_t);
+
+extern krb5_error_code krb5_store_all_creds
+	(krb5_context, krb5_ccache, krb5_creds **, krb5_creds **);
+
+extern krb5_error_code krb5_store_all_creds
+	(krb5_context, krb5_ccache, krb5_creds **, krb5_creds **);
+
+extern krb5_boolean compare_creds
+	(krb5_context, krb5_creds *, krb5_creds *);
+
+extern krb5_error_code krb5_get_nonexp_tkts
+	(krb5_context, krb5_ccache, krb5_creds ***);
+
+extern krb5_error_code krb5_check_exp
+	(krb5_context, krb5_ticket_times);
+
+extern char *flags_string (krb5_creds *);
+
+extern krb5_error_code krb5_get_login_princ
+	(const char *, char ***);
+
+extern void show_credential
+	(krb5_context, krb5_creds *, krb5_ccache);
+
+extern int gen_sym (void);
+
+extern krb5_error_code krb5_ccache_overwrite
+	(krb5_context, krb5_ccache, krb5_ccache, krb5_principal);
+
+extern krb5_error_code krb5_store_some_creds
+	(krb5_context, krb5_ccache, krb5_creds **, krb5_creds **,
+		   krb5_principal, krb5_boolean *);
+
+extern krb5_error_code krb5_ccache_copy_restricted
+	(krb5_context, krb5_ccache, char *, krb5_principal, 
+		   krb5_ccache *, krb5_boolean *, uid_t);
+
+extern krb5_error_code krb5_ccache_refresh
+	(krb5_context, krb5_ccache);
+
+extern krb5_error_code krb5_ccache_filter
+	(krb5_context, krb5_ccache, krb5_principal);
+
+extern krb5_boolean krb5_find_princ_in_cred_list
+	(krb5_context, krb5_creds **, krb5_principal);
+
+extern krb5_error_code krb5_find_princ_in_cache
+	(krb5_context, krb5_ccache, krb5_principal, krb5_boolean *);
+
+extern void printtime (time_t);
+
+/* authorization.c */
+extern krb5_boolean fowner (FILE *, uid_t);
+
+extern krb5_error_code krb5_authorization
+	(krb5_context, krb5_principal, const char *, char *, 
+		   krb5_boolean *, char **);
+
+extern krb5_error_code k5login_lookup (FILE *, char *,
+						 krb5_boolean *);
+
+extern krb5_error_code k5users_lookup 
+	(FILE *, char *, char *, krb5_boolean *, char **);
+
+extern krb5_boolean fcmd_resolve
+	(char *, char ***, char **);
+
+extern krb5_boolean cmd_single (char *);
+
+extern int cmd_arr_cmp_postfix (char **, char *);
+
+extern int cmd_arr_cmp (char **, char *);
+
+extern krb5_boolean find_first_cmd_that_exists 
+	(char **, char **, char **);
+
+extern int match_commands 
+	(char *, char *, krb5_boolean *, char **, char **);
+
+extern krb5_error_code get_line (FILE *, char **);
+
+extern char *  get_first_token (char *, char **);
+
+extern char *  get_next_token (char **);
+
+extern void init_auth_names (char *);
+
+/* main.c */
+extern void usage (void);
+
+extern int standard_shell (char *);
+
+extern krb5_error_code get_params (int *, int, char **, char ***);
+
+extern char *get_dir_of_file (const char *);
+
+/* heuristic.c */
+extern krb5_error_code get_all_princ_from_file (FILE *, char ***);
+
+extern krb5_error_code list_union (char **, char **, char ***);
+
+extern krb5_error_code filter (FILE *, char *, char **, char ***);
+
+extern krb5_error_code get_authorized_princ_names
+	(const char *, char *, char ***);
+
+extern krb5_error_code get_closest_principal 
+	(krb5_context, char **, krb5_principal *, krb5_boolean *);
+
+extern krb5_error_code find_either_ticket 
+	(krb5_context, krb5_ccache, krb5_principal,
+		krb5_principal, krb5_boolean *);
+
+extern krb5_error_code find_ticket 
+	(krb5_context, krb5_ccache, krb5_principal,
+		krb5_principal, krb5_boolean *);
+
+
+extern krb5_error_code find_princ_in_list
+	(krb5_context, krb5_principal, char **, krb5_boolean *);
+
+extern krb5_error_code get_best_princ_for_target
+	(krb5_context, uid_t, uid_t, char *, char *, krb5_ccache, 
+		opt_info *, char *, char *, krb5_principal *, int *);
+
+extern krb5_error_code ksu_tgtname (krb5_context, const krb5_data *,
+					      const krb5_data *, 
+					      krb5_principal *tgtprinc);
+
+#ifndef min
+#define min(a,b) ((a) > (b) ? (b) : (a))
+#endif /* min */
+
+
+extern char *krb5_lname_file;  /* Note: print this out just be sure
+				  that it gets set */   	    
+
+extern void *xmalloc (size_t), 
+    *xrealloc (void *, size_t), 
+    *xcalloc (size_t, size_t);
+extern char *xstrdup (const char *);
+
+#ifndef HAVE_UNSETENV
+void unsetenv (char *);
+#endif
diff --git a/krb5-1-6/src/clients/ksu/main.c b/krb5-1-6/src/clients/ksu/main.c
new file mode 100644
index 000000000..f3d844069
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/main.c
@@ -0,0 +1,1001 @@
+/* 
+ * Copyright (c) 1994 by the University of Southern California
+ *
+ * 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 copy, modify, and distribute
+ *     this software and its documentation in source and binary forms is
+ *     hereby granted, provided that any documentation or other materials
+ *     related to such distribution or use acknowledge that the software
+ *     was developed by the University of Southern California. 
+ *
+ * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
+ *     University of Southern California MAKES NO REPRESENTATIONS OR
+ *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
+ *     limitation, the University of Southern California MAKES NO
+ *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
+ *     PARTICULAR PURPOSE. The University of Southern
+ *     California shall not be held liable for any liability nor for any
+ *     direct, indirect, or consequential damages with respect to any
+ *     claim by the user or distributor of the ksu software.
+ *
+ * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+ */
+
+#include "ksu.h"
+#include "adm_proto.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <grp.h>
+
+/* globals */
+char * prog_name;
+int auth_debug =0;     
+char k5login_path[MAXPATHLEN];
+char k5users_path[MAXPATHLEN];
+char * gb_err = NULL;
+int quiet = 0;
+/***********/
+
+#define _DEF_CSH "/bin/csh" 
+static int set_env_var (char *, char *);
+static void sweep_up (krb5_context, krb5_ccache);
+static char * ontty (void);
+#ifdef HAVE_STDARG_H
+static void print_status( const char *fmt, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+     __attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+     ;
+#else
+static void print_status();
+#endif
+char * get_dir_of_file();     
+
+/* Note -e and -a options are mutually exclusive */
+/* insure the proper specification of target user as well as catching         
+   ill specified arguments to commands */        
+
+void usage (){
+    fprintf(stderr, "Usage: %s [target user] [-n principal] [-c source cachename] [-k] [-D] [-r time] [-pf] [-l lifetime] [-zZ] [-q] [-e command [args... ] ] [-a [args... ] ]\n", prog_name);
+}
+
+/* for Ultrix and friends ... */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+/* These are file static so sweep_up can get to them*/
+static uid_t source_uid, target_uid;
+
+int
+main (argc, argv)
+    int argc;
+    char ** argv;
+{ 
+    int hp =0;
+    int some_rest_copy = 0;	
+    int all_rest_copy = 0;	
+    char *localhostname = NULL;
+    opt_info options;
+    int option=0;
+    int statusp=0;
+    krb5_error_code retval = 0; 
+    krb5_principal client = NULL;
+    krb5_ccache cc_target = NULL;
+    krb5_context ksu_context;
+    char * cc_target_tag = NULL; 
+    char * target_user = NULL;
+    char * source_user;
+    
+    krb5_ccache cc_source = NULL;
+    const char * cc_source_tag = NULL; 
+    uid_t source_gid, target_gid;
+    const char * cc_source_tag_tmp = NULL;
+    char * cc_target_tag_tmp=NULL; 
+    char * cmd = NULL, * exec_cmd = NULL;
+    int errflg = 0;
+    krb5_boolean auth_val; 
+    krb5_boolean authorization_val = FALSE; 
+    int path_passwd = 0;
+    int done =0,i,j;
+    uid_t ruid = getuid ();
+    struct passwd *pwd=NULL,  *target_pwd ;
+    char * shell;
+    char ** params;
+    int keep_target_cache = 0;
+    int child_pid, child_pgrp, ret_pid;
+    extern char * getpass(), *crypt();
+    int pargc;
+    char ** pargv;
+    struct stat  st_temp;
+    krb5_boolean stored = FALSE;
+    krb5_principal  kdc_server;
+    krb5_boolean zero_password;
+    char * dir_of_cc_target;     
+    
+    options.opt = KRB5_DEFAULT_OPTIONS;
+    options.lifetime = KRB5_DEFAULT_TKT_LIFE;
+    options.rlife =0; 
+    options.princ =0;	
+
+    params = (char **) xcalloc (2, sizeof (char *));
+    params[1] = NULL;
+
+
+    unsetenv ("KRB5_CONFIG");
+
+    retval = krb5_init_secure_context(&ksu_context);
+    if (retval) {
+        com_err(argv[0], retval, "while initializing krb5");
+	exit(1);
+    }
+
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+    prog_name = argv[0];
+    if (strlen (prog_name) > 50) {
+	/* this many chars *after* last / ?? */
+	com_err(prog_name, 0, "program name too long - quitting to avoid triggering system logging bugs");
+	exit (1);
+    }
+
+
+#ifndef LOG_NDELAY
+#define LOG_NDELAY 0
+#endif
+    
+#ifndef LOG_AUTH /* 4.2 syslog */
+    openlog(prog_name, LOG_PID|LOG_NDELAY);
+#else
+    openlog(prog_name, LOG_PID | LOG_NDELAY, LOG_AUTH);
+#endif /* 4.2 syslog */
+    
+      
+    if (( argc == 1) || (argv[1][0] == '-')){
+	target_user = xstrdup("root");
+	pargc = argc;
+	pargv = argv;
+    } else {
+	target_user = xstrdup(argv[1]);
+	pargc = argc -1;
+	
+	if ((pargv =(char **) calloc(pargc +1,sizeof(char *)))==NULL){
+	    com_err(prog_name, errno, "while allocating memory");
+	    exit(1);
+	}
+	
+	pargv[pargc] = NULL;
+	pargv[0] = argv[0];
+	
+	for(i =1; i< pargc; i ++){
+	    pargv[i] = argv[i + 1];
+	}
+    }
+    
+    if (krb5_seteuid (ruid)) {
+	com_err (prog_name, errno, "while setting euid to source user");
+	exit (1);
+    }
+    while(!done && ((option = getopt(pargc, pargv,"n:c:r:a:zZDfpkql:e:")) != -1)){
+	switch (option) {
+	case 'r':
+	    options.opt |= KDC_OPT_RENEWABLE;
+	    if (strlen (optarg) >= 14)
+		optarg = "bad-time";
+	    retval = krb5_string_to_deltat(optarg, &options.rlife);
+	    if (retval != 0 || options.rlife == 0) {
+		fprintf(stderr, "Bad lifetime value (%s hours?)\n", optarg);
+		errflg++;
+	    }
+	    break;
+	case 'a':
+            /* when integrating this remember to pass in pargc, pargv and
+               take care of params argument */
+	    optind --;	
+	    if (auth_debug){printf("Before get_params optind=%d\n", optind);}
+	    
+            if ((retval = get_params( & optind, pargc, pargv, ¶ms))){
+                com_err(prog_name, retval, "when gathering parameters");
+                errflg++;
+            }
+            if(auth_debug){ printf("After get_params optind=%d\n", optind);}
+	    done = 1;
+            break;
+	case 'p':
+	    options.opt |= KDC_OPT_PROXIABLE;
+	    break;
+	case 'f':
+	    options.opt |= KDC_OPT_FORWARDABLE;
+	    break;
+	case 'k':
+	    keep_target_cache =1;
+	    break;
+	case 'q':
+	    quiet =1;
+	    break;
+        case 'l':
+	    if (strlen (optarg) >= 14)
+		optarg = "bad-time";
+	    retval = krb5_string_to_deltat(optarg, &options.lifetime);
+	    if (retval != 0 || options.lifetime == 0) {
+		fprintf(stderr, "Bad lifetime value (%s hours?)\n", optarg);
+		errflg++;
+	    }
+	    break;
+	case 'n': 
+	    if ((retval = krb5_parse_name(ksu_context, optarg, &client))){
+		com_err(prog_name, retval, "when parsing name %s", optarg); 
+		errflg++;
+	    }	
+	    
+    	    options.princ = 1;
+	    
+	    break;
+#ifdef DEBUG
+	case 'D':
+	    auth_debug = 1;	
+	    break;
+#endif
+	case 'z':
+	    some_rest_copy = 1;	
+	    if(all_rest_copy) {  	
+		fprintf(stderr, 
+			"-z option is mutually exclusive with -Z.\n"); 
+		errflg++;
+	    }	
+	    break;	
+	case 'Z':
+	    all_rest_copy = 1;	
+	    if(some_rest_copy) {  	
+		fprintf(stderr, 
+			"-Z option is mutually exclusive with -z.\n"); 
+		errflg++;
+	    } 	
+	    break;	
+	case 'c':
+	    if (cc_source_tag == NULL) {
+		cc_source_tag = xstrdup(optarg);
+		if ( strchr(cc_source_tag, ':')){
+		    cc_source_tag_tmp = strchr(cc_source_tag, ':') + 1;
+		    
+		    if( stat( cc_source_tag_tmp, &st_temp)){
+			com_err (prog_name, errno,
+				 "while looking for credentials file %s",
+				 cc_source_tag_tmp);
+			exit (1);
+		    }
+		}
+		else { 
+		    fprintf(stderr,"malformed credential cache name %s\n",
+			    cc_source_tag); 
+		    errflg++;
+		}
+		
+	    } else {
+		fprintf(stderr, "Only one -c option allowed\n");
+		errflg++;
+	    }
+	    break;
+	case 'e': 
+	    cmd = xstrdup(optarg);
+            if(auth_debug){printf("Before get_params optind=%d\n", optind);}
+            if ((retval = get_params( & optind, pargc, pargv, ¶ms))){
+                com_err(prog_name, retval, "when gathering parameters");
+                errflg++;
+            }
+            if(auth_debug){printf("After get_params optind=%d\n", optind);}
+            done = 1;
+
+            if (auth_debug){
+                fprintf(stderr,"Command to be executed: %s\n", cmd);
+            }
+            break;
+	case '?':
+	default:
+	    errflg++;
+	    break;
+	}
+    }
+
+    if (errflg) {
+	usage();
+	exit(2);
+    }
+
+    if (optind != pargc ){
+        usage();
+        exit(2);
+    }
+
+    if (auth_debug){	
+	for(j=1; params[j] != NULL; j++){
+	    fprintf (stderr,"params[%d]= %s\n", j,params[j]);
+	}
+    }	
+
+    /***********************************/
+    source_user = getlogin(); /*checks for the the login name in /etc/utmp*/
+    
+    /* verify that that the user exists and get his passwd structure */
+    
+    if (source_user == NULL ||(pwd = getpwnam(source_user)) == NULL ||
+	pwd->pw_uid != ruid){
+	pwd = getpwuid(ruid);
+    }
+    
+    if (pwd == NULL) {
+	fprintf(stderr, "ksu: who are you?\n");
+	exit(1);
+    }
+    if (pwd->pw_uid != ruid) {
+	fprintf (stderr, "Your uid doesn't match your passwd entry?!\n");
+	exit (1);
+    }
+    /* Okay, now we have *some* passwd entry that matches the
+       current real uid.  */
+    
+    /* allocate space and copy the usernamane there */        
+    source_user = xstrdup(pwd->pw_name);
+    source_uid = pwd->pw_uid;
+    source_gid = pwd->pw_gid;
+    
+    
+    if (!strcmp(SOURCE_USER_LOGIN, target_user)){
+	target_user = xstrdup (source_user);			
+    }
+    
+    if ((target_pwd = getpwnam(target_user)) == NULL){ 
+	fprintf(stderr, "ksu: unknown login %s\n", target_user); 
+	exit(1);
+    }
+    target_uid = target_pwd->pw_uid;
+    target_gid = target_pwd->pw_gid;
+    
+    init_auth_names(target_pwd->pw_dir);
+    
+    /***********************************/
+    
+    if (cc_source_tag == NULL){
+	cc_source_tag = krb5_cc_default_name(ksu_context);
+	cc_source_tag_tmp = strchr(cc_source_tag, ':');
+	if (cc_source_tag_tmp == 0)
+	    cc_source_tag_tmp = cc_source_tag;
+	else
+	    cc_source_tag_tmp++;
+    }
+    
+    /* get a handle for the cache */      
+    if ((retval = krb5_cc_resolve(ksu_context, cc_source_tag, &cc_source))){
+	com_err(prog_name, retval,"while getting source cache");    
+	exit(1);
+    }
+    
+    if (((retval = krb5_cc_set_flags(ksu_context,  cc_source, 0x0)) != 0)
+	&& (retval != KRB5_FCC_NOFILE)) {
+	    com_err(prog_name, retval, "while opening ccache");
+	    exit(1);
+    }
+    if ((retval = get_best_princ_for_target(ksu_context, source_uid,
+					    target_uid, source_user, 
+					    target_user, cc_source, 
+					    &options, cmd, localhostname, 
+					    &client, &hp))){
+	com_err(prog_name,retval, "while selecting the best principal"); 
+	exit(1);
+    }
+    
+    /* We may be running as either source or target, depending on
+       what happened; become source.*/
+    if ( geteuid() != source_uid) {
+	if (krb5_seteuid(0) || krb5_seteuid(source_uid) ) {
+	    com_err(prog_name, errno, "while returning to source uid after finding best principal");
+	    exit(1);
+	}
+    }
+    
+    if (auth_debug){
+	if (hp){	
+	    fprintf(stderr,
+		    "GET_best_princ_for_target result: NOT AUTHORIZED\n");
+	}else{
+	    fprintf(stderr,
+		    "GET_best_princ_for_target result-best principal ");
+	    plain_dump_principal (ksu_context, client);
+	    fprintf(stderr,"\n");
+	}
+    }
+    
+    if (hp){	
+	if (gb_err) fprintf(stderr, "%s", gb_err);
+	fprintf(stderr,"account %s: authorization failed\n",target_user);
+	exit(1);
+    }
+    
+    if (cc_target_tag == NULL) {
+	
+	cc_target_tag = (char *)xcalloc(KRB5_SEC_BUFFSIZE ,sizeof(char));
+	/* make sure that the new ticket file does not already exist
+	   This is run as source_uid because it is reasonable to
+	   require the source user to have write to where the target
+	   cache will be created.*/
+	
+	do {
+	    sprintf(cc_target_tag, "%s%ld.%d",
+		    KRB5_SECONDARY_CACHE,
+		    (long) target_uid, gen_sym());
+	    cc_target_tag_tmp = strchr(cc_target_tag, ':') + 1;
+	    
+	}while ( !stat ( cc_target_tag_tmp, &st_temp)); 
+    }
+    
+    
+    dir_of_cc_target = get_dir_of_file(cc_target_tag_tmp);
+    
+    if (access(dir_of_cc_target, R_OK | W_OK )){
+	fprintf(stderr,
+		"%s does not have correct permissions for %s\n", 
+		source_user, cc_target_tag); 
+	exit(1); 	
+    }
+    
+    if (auth_debug){	
+	fprintf(stderr, " source cache =  %s\n", cc_source_tag); 
+	fprintf(stderr, " target cache =  %s\n", cc_target_tag); 
+    }
+    
+    /* 
+       Only when proper authentication and authorization
+       takes place, the target user becomes the owner of the cache.         
+       */           
+    
+    /* we continue to run as source uid until
+       the middle of the copy, when becomewe become the target user
+       The cache is owned by the target user.*/
+    
+	
+    /* if root ksu's to a regular user, then      
+       then only the credentials for that particular user 
+       should be copied */            
+    
+    if ((source_uid == 0) && (target_uid != 0)) {
+	
+	if ((retval = krb5_ccache_copy_restricted(ksu_context,  cc_source,
+						  cc_target_tag, client, 
+						  &cc_target, &stored, 
+						  target_uid))){
+	    com_err (prog_name, retval, 
+		     "while copying cache %s to %s",
+		     krb5_cc_get_name(ksu_context, cc_source),cc_target_tag);
+	    exit(1);
+	}
+	
+    } else {
+	if ((retval = krb5_ccache_copy(ksu_context, cc_source, cc_target_tag,
+				       client,&cc_target, &stored, target_uid))) {
+	    com_err (prog_name, retval, 
+		     "while copying cache %s to %s",
+		     krb5_cc_get_name(ksu_context, cc_source),
+		     cc_target_tag);
+	    exit(1);
+	}
+	
+    }
+    
+    /* Become root for authentication*/
+    
+    if (krb5_seteuid(0)) {
+	com_err(prog_name, errno, "while reclaiming root uid");
+	exit(1);
+    }
+    
+    if ((source_uid == 0) || (target_uid == source_uid)){
+#ifdef GET_TGT_VIA_PASSWD
+	if ((!all_rest_copy) && options.princ && (stored == FALSE)){
+	    if ((retval = ksu_tgtname(ksu_context, 
+				       krb5_princ_realm (ksu_context, client),
+				       krb5_princ_realm(ksu_context, client),
+				       &kdc_server))){
+		com_err(prog_name, retval,
+			"while creating tgt for local realm");
+		sweep_up(ksu_context, cc_target);
+		exit(1);
+	    }
+	    
+	    fprintf(stderr,"WARNING: Your password may be exposed if you enter it here and are logged\n");
+	    fprintf(stderr,"         in remotely using an unsecure (non-encrypted) channel.\n");
+	    if (krb5_get_tkt_via_passwd (ksu_context, &cc_target, client,
+					 kdc_server, &options, 
+					 &zero_password) == FALSE){
+		
+		if (zero_password == FALSE){  
+		    fprintf(stderr,"Goodbye\n");
+		    sweep_up(ksu_context, cc_target);
+		    exit(1);
+		}
+		
+		fprintf(stderr,
+			"Could not get a tgt for ");    
+		plain_dump_principal (ksu_context, client);
+		fprintf(stderr, "\n");    
+		
+	    }
+	}
+#endif /* GET_TGT_VIA_PASSWD */
+    }
+    
+    /* if the user is root or same uid then authentication is not neccesary,
+       root gets in automatically */   	
+    
+    if (source_uid && (source_uid != target_uid)) {
+	char * client_name;
+	
+	auth_val = krb5_auth_check(ksu_context, client, localhostname, &options,
+				   target_user,cc_target, &path_passwd, target_uid); 
+	
+	/* if Kerberos authentication failed then exit */     
+	if (auth_val ==FALSE){
+	    fprintf(stderr, "Authentication failed.\n");
+	    syslog(LOG_WARNING,
+		   "'%s %s' authentication failed for %s%s",
+		   prog_name,target_user,source_user,ontty());
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	}
+	
+#if 0
+	/* At best, this avoids a single kdc request
+	   It is hard to implement dealing with file permissions and
+	   is unnecessary.  It is important
+	   to properly handle races in chown if this code is ever re-enabled.
+	   */
+	/* cache the tickets if possible in the source cache */ 
+	if (!path_passwd){ 	
+	    
+	    if ((retval = krb5_ccache_overwrite(ksu_context, cc_target, cc_source,
+						client))){
+		com_err (prog_name, retval,
+			 "while copying cache %s to %s",
+			 krb5_cc_get_name(ksu_context, cc_target),
+			 krb5_cc_get_name(ksu_context, cc_source));
+		sweep_up(ksu_context, cc_target);
+		exit(1);
+	    }
+	    if (chown(cc_source_tag_tmp, source_uid, source_gid)){  
+		com_err(prog_name, errno, 
+			"while changing owner for %s",
+			cc_source_tag_tmp);   
+		exit(1);
+	    }
+	}
+#endif /*0*/
+
+	if ((retval = krb5_unparse_name(ksu_context, client, &client_name))) {
+	    com_err (prog_name, retval, "When unparsing name");
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	}     
+	
+	print_status("Authenticated %s\n", client_name);
+	syslog(LOG_NOTICE,"'%s %s' authenticated %s for %s%s",
+	       prog_name,target_user,client_name,
+	       source_user,ontty());
+	
+	/* Run authorization as target.*/
+	if (krb5_seteuid(target_uid)) {
+	    com_err(prog_name, errno, "while switching to target for authorization check");
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	}
+	
+	if ((retval = krb5_authorization(ksu_context, client,target_user,
+					 cmd, &authorization_val, &exec_cmd))){
+	    com_err(prog_name,retval,"while checking authorization");
+	    krb5_seteuid(0); /*So we have some chance of sweeping up*/
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	}
+	
+	if (krb5_seteuid(0)) {
+	    com_err(prog_name, errno, "while switching back from  target after authorization check");
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	}
+	if (authorization_val == TRUE){
+
+	    if (cmd) {	
+		print_status(
+		    "Account %s: authorization for %s for execution of\n",
+		    target_user, client_name);
+		print_status("               %s successful\n",exec_cmd);
+		syslog(LOG_NOTICE,
+		       "Account %s: authorization for %s for execution of %s successful",
+		       target_user, client_name, exec_cmd);
+		
+	    }else{
+		print_status(
+		    "Account %s: authorization for %s successful\n",
+			  	target_user, client_name);
+		syslog(LOG_NOTICE,
+		       "Account %s: authorization for %s successful",
+		       target_user, client_name);
+	    }
+	}else {
+	    if (cmd){ 	
+		if (exec_cmd){ /* was used to pass back the error msg */
+		    fprintf(stderr, "%s", exec_cmd );
+		    syslog(LOG_WARNING, "%s",exec_cmd);
+		}
+		fprintf(stderr,
+			"Account %s: authorization for %s for execution of %s failed\n",
+			target_user, client_name, cmd );
+		syslog(LOG_WARNING,
+		       "Account %s: authorization for %s for execution of %s failed",
+		       target_user, client_name, cmd );
+		
+	    }else{
+		fprintf(stderr,
+			"Account %s: authorization of %s failed\n",
+			target_user, client_name);
+		syslog(LOG_WARNING,
+		       "Account %s: authorization of %s failed",
+		       target_user, client_name);
+		
+	    }
+	    
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	}
+    }
+    
+    if( some_rest_copy){ 
+	if ((retval = krb5_ccache_filter(ksu_context, cc_target, client))){ 	
+	    com_err(prog_name,retval,"while calling cc_filter");
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	}
+    }
+    
+    if (all_rest_copy){
+	if ((retval = krb5_cc_initialize(ksu_context, cc_target, client))){  
+	    com_err(prog_name, retval,
+		    "while erasing target cache");    
+	    exit(1);
+	}
+	
+    }
+    
+    /* get the shell of the user, this will be the shell used by su */      
+    target_pwd = getpwnam(target_user);
+    
+    if (target_pwd->pw_shell)
+	shell = xstrdup(target_pwd->pw_shell);
+    else {
+	shell = _DEF_CSH;  /* default is cshell */   
+    }
+    
+#ifdef HAVE_GETUSERSHELL
+    
+    /* insist that the target login uses a standard shell (root is omited) */ 
+    
+    if (!standard_shell(target_pwd->pw_shell) && source_uid) {
+	fprintf(stderr, "ksu: permission denied (shell).\n");
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    }
+#endif /* HAVE_GETUSERSHELL */
+    
+    if (target_pwd->pw_uid){
+	
+	if(set_env_var("USER", target_pwd->pw_name)){
+	    fprintf(stderr,"ksu: couldn't set environment variable USER\n");
+	    sweep_up(ksu_context, cc_target);
+	    exit(1);
+	} 			
+    }	
+    
+    if(set_env_var( "HOME", target_pwd->pw_dir)){
+	fprintf(stderr,"ksu: couldn't set environment variable USER\n");
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    } 			
+    
+    if(set_env_var( "SHELL", shell)){
+	fprintf(stderr,"ksu: couldn't set environment variable USER\n");
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    } 			
+    
+    /* set the cc env name to target */         	
+    
+    if(set_env_var( KRB5_ENV_CCNAME, cc_target_tag)){
+	fprintf(stderr,"ksu: couldn't set environment variable %s\n",
+		KRB5_ENV_CCNAME);
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    } 			
+    
+    /* set permissions */
+    if (setgid(target_pwd->pw_gid) < 0) {
+	perror("ksu: setgid");
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    }
+    
+    
+    if (initgroups(target_user, target_pwd->pw_gid)) {
+	fprintf(stderr, "ksu: initgroups failed.\n");
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    }
+    
+    if ( ! strcmp(target_user, source_user)){ 			
+	print_status("Leaving uid as %s (%ld)\n",
+		     target_user, (long) target_pwd->pw_uid); 
+    }else{
+	print_status("Changing uid to %s (%ld)\n", 
+		     target_user, (long) target_pwd->pw_uid); 
+    }
+    
+#ifdef	HAVE_SETLUID
+    /*
+     * If we're on a system which keeps track of login uids, then
+     * set the login uid. If this fails this opens up a problem on DEC OSF
+     * with C2 enabled.
+     */
+    if (setluid((uid_t) pwd->pw_uid) < 0) {
+	perror("setluid");
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    }
+#endif	/* HAVE_SETLUID */
+    
+    if (setuid(target_pwd->pw_uid) < 0) {
+	perror("ksu: setuid");
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    }   
+    
+    if (access( cc_target_tag_tmp, R_OK | W_OK )){
+	com_err(prog_name, errno,
+		"%s does not have correct permissions for %s, %s aborted",
+		target_user, cc_target_tag_tmp, prog_name);
+	exit(1);
+    }
+    
+    if ( cc_source)
+	krb5_cc_close(ksu_context, cc_source);
+    
+    if (cmd){
+	if ((source_uid == 0) || (source_uid == target_uid )){
+	    exec_cmd = cmd;
+	}
+	
+	if( !exec_cmd){ 
+	    fprintf(stderr,
+		    "Internal error: command %s did not get resolved\n",cmd);
+	    exit(1);	
+	}
+	
+	params[0] = exec_cmd;
+    }
+    else{
+	params[0] = shell;
+    }
+    
+    if (auth_debug){		
+	fprintf(stderr, "program to be execed %s\n",params[0]);
+    }
+    
+    if( keep_target_cache ) {
+	execv(params[0], params);
+	com_err(prog_name, errno, "while trying to execv %s",
+		params[0]);
+	sweep_up(ksu_context, cc_target);
+	exit(1);
+    }else{
+	statusp = 1;
+	switch ((child_pid = fork())) {
+	default:
+	    if (auth_debug){
+	 	printf(" The child pid is %ld\n", (long) child_pid);
+        	printf(" The parent pid is %ld\n", (long) getpid());
+	    }
+            while ((ret_pid = waitpid(child_pid, &statusp, WUNTRACED)) != -1) {
+		if (WIFSTOPPED(statusp)) {
+		    child_pgrp = tcgetpgrp(1);
+		    kill(getpid(), SIGSTOP);
+		    tcsetpgrp(1, child_pgrp);
+		    kill(child_pid, SIGCONT); 
+		    statusp = 1;
+		    continue;
+		}
+		break;
+            }
+	    if (auth_debug){
+		printf("The exit status of the child is %d\n", statusp); 
+	    }
+	    if (ret_pid == -1) {
+	    	com_err(prog_name, errno, "while calling waitpid");
+	    }
+	    sweep_up(ksu_context, cc_target);
+	    exit (statusp);
+	case -1:
+	    com_err(prog_name, errno, "while trying to fork.");
+	    sweep_up(ksu_context, cc_target);
+	    exit (1);
+	case 0:
+	    execv(params[0], params);
+	    com_err(prog_name, errno, "while trying to execv %s", params[0]);
+	    exit (1);
+	}
+    }
+}
+
+#ifdef HAVE_GETUSERSHELL
+
+int standard_shell(sh)
+char *sh;
+{
+    register char *cp;
+    char *getusershell();
+    
+    while ((cp = getusershell()) != NULL)
+	if (!strcmp(cp, sh))
+	    return (1);
+    return (0);    
+}
+						  
+#endif /* HAVE_GETUSERSHELL */
+
+static char * ontty()
+{
+    char *p, *ttyname();
+    static char buf[MAXPATHLEN + 4];
+    
+    buf[0] = 0;
+    if ((p = ttyname(STDERR_FILENO))) {
+	if (strlen (p) > MAXPATHLEN) {
+	    fprintf (stderr, "terminal name %s too long\n", p);
+	    exit (1);
+	}
+	sprintf(buf, " on %s", p);
+    }
+    return (buf);
+}
+
+
+static int set_env_var(name, value)
+    char *name;
+    char *value;
+{
+    char * env_var_buf;
+    
+    /* allocate extra two spaces, one for the = and one for the \0 */  
+    env_var_buf = (char *) xcalloc(2 + strlen(name) + strlen(value),
+				   sizeof(char)); 
+    
+    sprintf(env_var_buf,"%s=%s",name, value);  
+    return putenv(env_var_buf);
+    
+}
+
+static void sweep_up(context, cc)
+    krb5_context context;
+    krb5_ccache cc;
+{
+    krb5_error_code retval; 
+    const char * cc_name;
+    struct stat  st_temp;
+
+    krb5_seteuid(0);
+    if (krb5_seteuid(target_uid) < 0) {
+	com_err(prog_name, errno,
+		"while changing to target uid for destroying ccache");
+	exit(1);
+    }
+
+    cc_name = krb5_cc_get_name(context, cc);
+    if ( ! stat(cc_name, &st_temp)){
+	if ((retval = krb5_cc_destroy(context, cc))){
+	    com_err(prog_name, retval, 
+		    "while destroying cache");   
+	}
+    }
+}
+
+/*****************************************************************
+get_params is to be called for the -a option or -e option to
+           collect all params passed in for the shell or for
+           cmd.  An aray is returned containing all params.
+           optindex is incremented accordingly and the first
+           element in the returned array is reserved for the
+           name of the command to be executed or the name of the
+           shell.
+*****************************************************************/
+
+krb5_error_code
+get_params(optindex, pargc, pargv, params)
+    int *optindex;
+    int pargc;
+    char **pargv;
+    char ***params;
+{
+
+    int i,j;
+    char ** ret_params;
+    int size = pargc - *optindex + 2;
+    
+    if ((ret_params = (char **) calloc(size, sizeof (char *)))== NULL ){
+	return errno;
+    }
+    
+    for (i = *optindex, j=1; i < pargc; i++,j++){
+	ret_params[j] = pargv[i];
+	*optindex = *optindex + 1;
+    }
+    
+    ret_params[size-1] = NULL;
+    *params = ret_params;
+    return 0;
+}
+
+static
+#ifdef HAVE_STDARG_H
+void print_status( const char *fmt, ...)
+#else
+void print_status (va_alist)
+     va_dcl
+#endif
+{
+    va_list ap;
+#ifndef HAVE_STDARG_H
+    char *fmt;
+    va_start (ap);
+    fmt = va_arg (ap, char*);
+    if (!quiet) vfprintf(stderr, fmt, ap);
+    va_end(ap);
+#else
+    if (! quiet){
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+    }
+#endif
+}
+
+
+char *get_dir_of_file(path)
+    const char *path;
+{
+    char * temp_path;      
+    char * ptr;
+
+    temp_path =  xstrdup(path);
+    
+    if ((ptr = strrchr( temp_path, '/'))) {
+	*ptr = '\0';  
+    } else {
+	free (temp_path);
+	temp_path = xmalloc(MAXPATHLEN);
+	if (temp_path)
+	    getcwd(temp_path, MAXPATHLEN);
+    }
+    return temp_path;  
+}
+
+krb5_error_code
+ksu_tgtname(context, server, client, tgtprinc)
+    krb5_context context;
+    const krb5_data *server, *client;
+    krb5_principal *tgtprinc;
+{
+    return krb5_build_principal_ext(context, tgtprinc, client->length, client->data,
+				    KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, 
+				    server->length, server->data,
+				    0);
+}
diff --git a/krb5-1-6/src/clients/ksu/setenv.c b/krb5-1-6/src/clients/ksu/setenv.c
new file mode 100644
index 000000000..056a478e5
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/setenv.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)setenv.c	5.2 (Berkeley) 6/27/88 */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "autoconf.h"
+
+static char *_findenv(char *, int *);
+
+#ifndef HAVE_SETENV
+extern int setenv(char *, char *, int);
+#endif
+#ifndef HAVE_UNSETENV
+extern void unsetenv(char *);
+#endif
+
+/*
+ * setenv --
+ *	Set the value of the environmental variable "name" to be
+ *	"value".  If rewrite is set, replace any current value.
+ */
+#ifndef HAVE_SETENV
+int
+setenv(name, value, rewrite)
+	register char *name, *value;
+	int rewrite;
+{
+	extern char **environ;
+	static int alloced;			/* if allocated space before */
+	register char *C;
+	int l_value, offset;
+
+	if (*value == '=')			/* no `=' in value */
+		++value;
+	l_value = strlen(value);
+	if ((C = _findenv(name, &offset))) {	/* find if already exists */
+		if (!rewrite)
+			return(0);
+		if (strlen(C) >= l_value) {	/* old larger; copy over */
+			while ((*C++ = *value++));
+			return(0);
+		}
+	}
+	else {					/* create new slot */
+		register int	cnt;
+		register char	**P;
+
+		for (P = environ, cnt = 0; *P; ++P, ++cnt);
+		if (alloced) {			/* just increase size */
+			environ = (char **)realloc((char *)environ,
+			    (u_int)(sizeof(char *) * (cnt + 2)));
+			if (!environ)
+				return(-1);
+		}
+		else {				/* get new space */
+			alloced = 1;		/* copy old entries into it */
+			P = (char **)malloc((u_int)(sizeof(char *) *
+			    (cnt + 2)));
+			if (!P)
+				return(-1);
+			memcpy(P, environ, cnt * sizeof(char *));
+			environ = P;
+		}
+		environ[cnt + 1] = NULL;
+		offset = cnt;
+	}
+	for (C = name; *C && *C != '='; ++C);	/* no `=' in name */
+	if (!(environ[offset] =			/* name + `=' + value */
+	    malloc((u_int)((int)(C - name) + l_value + 2))))
+		return(-1);
+	for (C = environ[offset]; (*C = *name++) &&( *C != '='); ++C);
+	for (*C++ = '='; (*C++ = *value++) != NULL;);
+	return(0);
+}
+#endif
+
+/*
+ * unsetenv(name) --
+ *	Delete environmental variable "name".
+ */
+#ifndef HAVE_UNSETENV
+void
+unsetenv(name)
+	char	*name;
+{
+	extern	char	**environ;
+	register char	**P;
+	int	offset;
+
+	while (_findenv(name, &offset))		/* if set multiple times */
+		for (P = &environ[offset];; ++P)
+			if (!(*P = *(P + 1)))
+				break;
+}
+#endif
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)getenv.c	5.5 (Berkeley) 6/27/88 */
+
+/*
+ * getenv --
+ *	Returns ptr to value associated with name, if any, else NULL.
+ */
+#ifndef HAVE_GETENV
+char *
+getenv(name)
+	char *name;
+{
+	int offset;
+
+	return(_findenv(name, &offset));
+}
+#endif
+
+/*
+ * _findenv --
+ *	Returns pointer to value associated with name, if any, else NULL.
+ *	Sets offset to be the offset of the name/value combination in the
+ *	environmental array, for use by setenv(3) and unsetenv(3).
+ *	Explicitly removes '=' in argument name.
+ *
+ */
+static char *
+_findenv(name, offset)
+	register char *name;
+	int *offset;
+{
+	extern char **environ;
+	register int len;
+	register char **P, *C;
+
+	for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+	for (P = environ; *P; ++P)
+		if (!strncmp(*P, name, len))
+			if (*(C = *P + len) == '=') {
+				*offset = P - environ;
+				return(++C);
+			}
+	return(NULL);
+}
diff --git a/krb5-1-6/src/clients/ksu/xmalloc.c b/krb5-1-6/src/clients/ksu/xmalloc.c
new file mode 100644
index 000000000..425b44f0e
--- /dev/null
+++ b/krb5-1-6/src/clients/ksu/xmalloc.c
@@ -0,0 +1,68 @@
+/*
+ * clients/ksu/xmalloc.c
+ *
+ * Copyright 1999 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Perform simple allocation/copy operations, exiting on failure.
+ */
+
+#include "ksu.h"
+
+void *xmalloc (size_t sz)
+{
+    void *ret = malloc (sz);
+    if (ret == 0 && sz != 0) {
+	perror (prog_name);
+	exit (1);
+    }
+    return ret;
+}
+
+void *xrealloc (void *old, size_t newsz)
+{
+    void *ret = realloc (old, newsz);
+    if (ret == 0 && newsz != 0) {
+	perror (prog_name);
+	exit (1);
+    }
+    return ret;
+}
+
+void *xcalloc (size_t nelts, size_t eltsz)
+{
+    void *ret = calloc (nelts, eltsz);
+    if (ret == 0 && nelts != 0 && eltsz != 0) {
+	perror (prog_name);
+	exit (1);
+    }
+    return ret;
+}
+
+char *xstrdup (const char *src)
+{
+    size_t len = strlen (src) + 1;
+    char *dst = xmalloc (len);
+    memcpy (dst, src, len);
+    return dst;
+}
diff --git a/krb5-1-6/src/clients/kvno/Makefile.in b/krb5-1-6/src/clients/kvno/Makefile.in
new file mode 100644
index 000000000..047c25b34
--- /dev/null
+++ b/krb5-1-6/src/clients/kvno/Makefile.in
@@ -0,0 +1,52 @@
+thisconfigdir=../..
+myfulldir=clients/kvno
+mydir=clients/kvno
+BUILDTOP=$(REL)..$(S)..
+DEFS=
+
+SRCS=kvno.c
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##KVNO=$(OUTPRE)kvno.exe
+
+##WIN32##EXERES=$(KVNO:.exe=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKVNO_APP -fo $@ -r $**
+
+all-unix:: kvno
+
+##WIN32##all-windows:: $(KVNO)
+
+kvno: kvno.o $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $@ kvno.o $(KRB4COMPAT_LIBS)
+
+##WIN32##$(KVNO): $(OUTPRE)kvno.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj $(KLIB) $(CLIB) $(EXERES)
+##WIN32##	link $(EXE_LINKOPTS) /out:$@ $**
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+clean-unix::
+	$(RM) kvno.o kvno
+
+install-unix::
+	for f in kvno; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
+	done
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kvno.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  kvno.c
diff --git a/krb5-1-6/src/clients/kvno/kvno.M b/krb5-1-6/src/clients/kvno/kvno.M
new file mode 100644
index 000000000..ad2cb4818
--- /dev/null
+++ b/krb5-1-6/src/clients/kvno/kvno.M
@@ -0,0 +1,85 @@
+.\" 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.
+.\"
+.\" clients/kvnol/kvno.M
+.\" "
+.TH KVNO 1
+.SH NAME
+kvno \- print key version numbers of Kerberos principals
+.SH SYNOPSIS
+\fBkvno\fP [\fB\-q\fP] [\fB\-h\fP] [\fB\-4\fP\ |\ [\fB-c ccache\fP]\ [\fB\-e etype\fP]]
+\fBservice1\fP \fBservice2\fP \fB...\fP
+.br
+.SH DESCRIPTION
+.I Kvno
+acquires a service ticket for the specified Kerberos principals and
+prints out the key version numbers of each.  
+.SH OPTIONS
+.TP
+.B \-c ccache
+specifies the name of a credentials cache to use (if not the default)
+.TP
+.B \-e etype
+specifies the enctype which will be requested for the session key of
+all the services named on the command line.  This is useful in certain
+backward compatibility situations.
+.TP
+.B \-q
+suppress printing
+.TP
+.B \-h
+prints a usage statement and exits
+.TP
+.B \-4
+specifies that Kerberos version 4 tickets should be acquired and
+described.  This option is only available if Kerberos 4 support was
+enabled at compilation time.
+.TP
+.B \-S sname
+specifies that krb5_sname_to_principal() will be used to build
+principal names.  If this flag is specified, the
+.B service1 service2 ...
+arguments are interpreted as hostnames (rather than principal names),
+and
+.B sname
+is interpreted as the service name.
+.SH ENVIRONMENT
+.B Kvno
+uses the following environment variable:
+.TP "\w'.SM KRB5CCNAME\ \ 'u"
+.SM KRB5CCNAME
+Location of the credentials (ticket) cache.
+.TP
+.SM KRBTKFILE
+Location of the v4 ticket file.
+.SH FILES
+.TP "\w'/tmp/krb5cc_[uid]\ \ 'u"
+/tmp/krb5cc_[uid]
+default location of the credentials cache ([uid] is the decimal UID of
+the user).
+.TP
+/tmp/tkt[uid]
+default location of the v4 ticket file.
+.SH SEE ALSO
+kinit(1), kdestroy(1), krb5(3)
diff --git a/krb5-1-6/src/clients/kvno/kvno.c b/krb5-1-6/src/clients/kvno/kvno.c
new file mode 100644
index 000000000..1598bf58f
--- /dev/null
+++ b/krb5-1-6/src/clients/kvno/kvno.c
@@ -0,0 +1,326 @@
+/*
+ * 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 "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+
+extern int optind;
+extern char *optarg;
+
+static char *prog;
+
+static void xusage()
+{
+#ifdef KRB5_KRB4_COMPAT
+    fprintf(stderr, 
+            "usage: %s [-4 | [-c ccache] [-e etype] [-k keytab] [-S sname]] service1 service2 ...\n", 
+            prog);
+#else
+    fprintf(stderr, "usage: %s [-c ccache] [-e etype] [-k keytab] [-S sname] service1 service2 ...\n",
+            prog);
+#endif
+    exit(1);
+}
+
+int quiet = 0;
+
+static void do_v4_kvno (int argc, char *argv[]);
+static void do_v5_kvno (int argc, char *argv[], 
+                        char *ccachestr, char *etypestr, char *keytab_name,
+			char *sname);
+
+#include <com_err.h>
+static void extended_com_err_fn (const char *, errcode_t, const char *,
+				 va_list);
+
+int main(int argc, char *argv[])
+{
+    int option;
+    char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL;
+    char *sname = NULL;
+    int v4 = 0;
+
+    set_com_err_hook (extended_com_err_fn);
+
+    prog = strrchr(argv[0], '/');
+    prog = prog ? (prog + 1) : argv[0];
+
+    while ((option = getopt(argc, argv, "c:e:hk:q4S:")) != -1) {
+	switch (option) {
+	case 'c':
+	    ccachestr = optarg;
+	    break;
+	case 'e':
+	    etypestr = optarg;
+	    break;
+	case 'h':
+	    xusage();
+	    break;
+	case 'k':
+	    keytab_name = optarg;
+	    break;
+	case 'q':
+	    quiet = 1;
+	    break;
+	case '4':
+	    v4 = 1;
+	    break;
+	case 'S':
+	    sname = optarg;
+	    break;
+	default:
+	    xusage();
+	    break;
+	}
+    }
+
+    if ((argc - optind) < 1)
+	xusage();
+
+    if ((ccachestr != NULL || etypestr != NULL || keytab_name != NULL) && v4)
+	xusage();
+
+    if (sname != NULL && v4)
+	xusage();
+
+    if (v4)
+	do_v4_kvno(argc - optind, argv + optind);
+    else
+	do_v5_kvno(argc - optind, argv + optind,
+		   ccachestr, etypestr, keytab_name, sname);
+    return 0;
+}
+
+#ifdef KRB5_KRB4_COMPAT
+#include <kerberosIV/krb.h>
+#endif
+static void do_v4_kvno (int count, char *names[])
+{
+#ifdef KRB5_KRB4_COMPAT
+    int i;
+
+    for (i = 0; i < count; i++) {
+	int err;
+	char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+	KTEXT_ST req;
+	CREDENTIALS creds;
+	*name = *inst = *realm = '\0';
+	err = kname_parse (name, inst, realm, names[i]);
+	if (err) {
+	    fprintf(stderr, "%s: error parsing name '%s': %s\n",
+		    prog, names[i], krb_get_err_text(err));
+	    exit(1);
+	}
+	if (realm[0] == 0) {
+	    err = krb_get_lrealm(realm, 1);
+	    if (err) {
+		fprintf(stderr, "%s: error looking up local realm: %s\n",
+			prog, krb_get_err_text(err));
+		exit(1);
+	    }
+	}
+	err = krb_mk_req(&req, name, inst, realm, 0);
+	if (err) {
+	    fprintf(stderr, "%s: krb_mk_req error: %s\n", prog,
+		    krb_get_err_text(err));
+	    exit(1);
+	}
+	err = krb_get_cred(name, inst, realm, &creds);
+	if (err) {
+	    fprintf(stderr, "%s: krb_get_cred error: %s\n", prog,
+		    krb_get_err_text(err));
+	    exit(1);
+	}
+	if (!quiet)
+	    printf("%s: kvno = %d\n", names[i], creds.kvno);
+    }
+#else
+    xusage();
+#endif
+}
+
+#include <krb5.h>
+static krb5_context context;
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+				 const char *fmt, va_list args)
+{
+    const char *emsg;
+    emsg = krb5_get_error_message (context, code);
+    fprintf (stderr, "%s: %s ", myprog, emsg);
+    krb5_free_error_message (context, emsg);
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+}
+
+static void do_v5_kvno (int count, char *names[], 
+                        char * ccachestr, char *etypestr, char *keytab_name,
+			char *sname)
+{
+    krb5_error_code ret;
+    int i, errors;
+    krb5_enctype etype;
+    krb5_ccache ccache;
+    krb5_principal me;
+    krb5_creds in_creds, *out_creds;
+    krb5_ticket *ticket;
+    char *princ;
+    krb5_keytab keytab = NULL;
+
+    ret = krb5_init_context(&context);
+    if (ret) {
+	com_err(prog, ret, "while initializing krb5 library");
+	exit(1);
+    }
+
+    if (etypestr) {
+        ret = krb5_string_to_enctype(etypestr, &etype);
+	if (ret) {
+	    com_err(prog, ret, "while converting etype");
+	    exit(1);
+	}
+    } else {
+	etype = 0;
+    }
+
+    if (ccachestr)
+        ret = krb5_cc_resolve(context, ccachestr, &ccache);
+    else
+        ret = krb5_cc_default(context, &ccache);
+    if (ret) {
+	com_err(prog, ret, "while opening ccache");
+	exit(1);
+    }
+
+    if (keytab_name) {
+	ret = krb5_kt_resolve(context, keytab_name, &keytab);
+	if (ret) {
+	    com_err(prog, ret, "resolving keytab %s", keytab_name);
+	    exit(1);
+	}
+    }
+
+    ret = krb5_cc_get_principal(context, ccache, &me);
+    if (ret) {
+	com_err(prog, ret, "while getting client principal name");
+	exit(1);
+    }
+
+    errors = 0;
+
+    for (i = 0; i < count; i++) {
+	memset(&in_creds, 0, sizeof(in_creds));
+
+	in_creds.client = me;
+
+	if (sname != NULL) {
+	    ret = krb5_sname_to_principal(context, names[i],
+					  sname, KRB5_NT_SRV_HST,
+					  &in_creds.server);
+	} else {
+	    ret = krb5_parse_name(context, names[i], &in_creds.server);
+	}
+	if (ret) {
+	    if (!quiet)
+		com_err(prog, ret, "while parsing principal name %s", names[i]);
+	    errors++;
+	    continue;
+	}
+
+	ret = krb5_unparse_name(context, in_creds.server, &princ);
+	if (ret) {
+	    com_err(prog, ret,
+		    "while formatting parsed principal name for '%s'",
+		    names[i]);
+	    errors++;
+	    continue;
+	}
+
+	in_creds.keyblock.enctype = etype;
+
+	ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds);
+
+	krb5_free_principal(context, in_creds.server);
+
+	if (ret) {
+	    com_err(prog, ret, "while getting credentials for %s", princ);
+
+	    krb5_free_unparsed_name(context, princ);
+
+	    errors++;
+	    continue;
+	}
+
+	/* we need a native ticket */
+	ret = krb5_decode_ticket(&out_creds->ticket, &ticket);
+	if (ret) {
+	    com_err(prog, ret, "while decoding ticket for %s", princ);
+	    krb5_free_creds(context, out_creds);
+	    krb5_free_unparsed_name(context, princ);
+
+	    errors++;
+	    continue;
+	}
+	    
+	if (keytab) {
+	    ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket);
+	    if (ret) {
+		if (!quiet)
+		    printf("%s: kvno = %d, keytab entry invalid", princ, ticket->enc_part.kvno);
+		com_err(prog, ret, "while decrypting ticket for %s", princ);
+		krb5_free_ticket(context, ticket);
+		krb5_free_creds(context, out_creds);
+		krb5_free_unparsed_name(context, princ);
+
+		errors++;
+		continue;
+	    }
+	    if (!quiet)
+		printf("%s: kvno = %d, keytab entry valid\n", princ, ticket->enc_part.kvno);
+	} else {
+	    if (!quiet)
+		printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno);
+	}
+
+	krb5_free_creds(context, out_creds);
+	krb5_free_unparsed_name(context, princ);
+    }
+
+    if (keytab)
+	krb5_kt_close(context, keytab);
+    krb5_free_principal(context, me);
+    krb5_cc_close(context, ccache);
+    krb5_free_context(context);
+
+    if (errors)
+	exit(1);
+
+    exit(0);
+}
diff --git a/krb5-1-6/src/config-files/Makefile.in b/krb5-1-6/src/config-files/Makefile.in
new file mode 100644
index 000000000..ad2b999d9
--- /dev/null
+++ b/krb5-1-6/src/config-files/Makefile.in
@@ -0,0 +1,12 @@
+thisconfigdir=./..
+myfulldir=config-files
+mydir=config-files
+BUILDTOP=$(REL)..
+all::
+
+install::
+	$(INSTALL_DATA) $(srcdir)/kdc.conf.M ${DESTDIR}$(FILE_MANDIR)/kdc.conf.5
+	$(INSTALL_DATA) $(srcdir)/krb5.conf.M ${DESTDIR}$(FILE_MANDIR)/krb5.conf.5
+	$(INSTALL_DATA) $(srcdir)/kdc.conf ${DESTDIR}$(EXAMPLEDIR)/kdc.conf
+	$(INSTALL_DATA) $(srcdir)/krb5.conf ${DESTDIR}$(EXAMPLEDIR)/krb5.conf
+	$(INSTALL_DATA) $(srcdir)/services.append ${DESTDIR}$(EXAMPLEDIR)/services.append
diff --git a/krb5-1-6/src/config-files/convert-config-files b/krb5-1-6/src/config-files/convert-config-files
new file mode 100644
index 000000000..53ddefff1
--- /dev/null
+++ b/krb5-1-6/src/config-files/convert-config-files
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+#
+# This program converts the old-style krb.conf and krb.realms files into the
+# new-format krb5.conf file.  It takes two arguments; the first is the krb.conf
+# file, and the second is the krb.realms file.  The krb5.conf file is output
+# to stdout.
+#
+# Written by Theodore Ts'o, 4/25/95
+#
+
+if ($#ARGV >= 0) {
+	$krb_conf_file = $ARGV[0];
+} else {
+	$krb_conf_file = "/etc/krb.conf";
+}
+
+if ($#ARGV >= 1) {
+	$krb_realms_file = $ARGV[1];
+} else {
+	$krb_realms_file = "/etc/krb.realms";
+}
+
+open(FILE, "<$krb_conf_file") || die "Couldn't open the krb.conf file\n";
+
+$_ = <FILE>;
+strip;
+$default_realm = $_;
+
+while(<FILE>) {
+	strip;
+	($realm, $host, $admin) = split;
+	if (!defined($realmpt{$realm})) {
+		$realmpt{$realm} = 1;
+	}
+	$realmkdc{$realm . "##" . $realmpt{$realm}} = $host;
+	$realmpt{$realm}++;
+	if ($admin eq "admin") {	
+		$realmadmin{$realm} = $host;
+	}
+}
+
+close(FILE);
+
+open(FILE, "<$krb_realms_file") || die "Couldn't open krb.realms file";
+
+while (<FILE>) {
+	strip;
+	($domain, $realm) = split;
+	$domain =~ s/\.$//;
+	$domain =~ tr/[A-Z]/[a-z]/;
+	$dom_realm{$domain} = $realm;
+	if ($domain =~ /^\./) {
+		$domain =~ s/^\.//;
+		$def_realm{$realm} = $domain;
+	}
+}
+
+print "[libdefaults]\n\tdefault_realm = $default_realm\n";
+
+print "[realms]\n";
+
+foreach $realm (sort(keys(%realmpt))) {
+	print "\t$realm = {\n";
+	for ($i = 1; $i < $realmpt{$realm}; $i++) {
+		printf("\t\tkdc = %s\n", $realmkdc{$realm . "##" . $i});
+		
+	}
+	if (defined($realmadmin{$realm})) {
+		print "\t\tadmin_server = $realmadmin{$realm}\n";
+	}
+	if (defined($def_realm{$realm})) {
+		print "\t\tdefault_domain = $def_realm{$realm}\n";
+	}
+	print "\t}\n";
+}
+
+print "\n[domain_realm]\n";
+
+foreach $domain (keys(%dom_realm)) {
+	print "\t$domain = $dom_realm{$domain}\n";
+}
+
+
+
diff --git a/krb5-1-6/src/config-files/kdc.conf b/krb5-1-6/src/config-files/kdc.conf
new file mode 100644
index 000000000..3355699ff
--- /dev/null
+++ b/krb5-1-6/src/config-files/kdc.conf
@@ -0,0 +1,13 @@
+[kdcdefaults]
+	kdc_ports = 750,88
+
+[realms]
+	ATHENA.MIT.EDU = {
+		database_name = /usr/local/var/krb5kdc/principal
+		admin_keytab = FILE:/usr/local/var/krb5kdc/kadm5.keytab
+		acl_file = /usr/local/var/krb5kdc/kadm5.acl
+		key_stash_file = /usr/local/var/krb5kdc/.k5.ATHENA.MIT.EDU
+		kdc_ports = 750,88
+		max_life = 10h 0m 0s
+		max_renewable_life = 7d 0h 0m 0s
+	}
diff --git a/krb5-1-6/src/config-files/kdc.conf.M b/krb5-1-6/src/config-files/kdc.conf.M
new file mode 100644
index 000000000..f19c6e008
--- /dev/null
+++ b/krb5-1-6/src/config-files/kdc.conf.M
@@ -0,0 +1,245 @@
+.\" Copyright 1995 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\"
+.TH KDC.CONF 5
+.SH NAME
+kdc.conf \- Kerberos V5 KDC configuration file
+.SH DESCRIPTION
+.I kdc.conf
+specifies per-realm configuration data to be used by the Kerberos V5
+Authentication Service and Key Distribution Center (AS/KDC).  This
+includes database, key and per-realm defaults.
+.PP
+The 
+.I kdc.conf
+file uses the same format as the
+.I krb5.conf
+file.  For a basic description of the syntax, please refer to the
+.I krb5.conf
+description.
+.PP
+The following sections are currently used in the
+.I kdc.conf
+file:
+.IP [kdcdefaults]
+Contains parameters which control the overall behaviour of the KDC.
+.IP [realms]
+Contains subsections keyed by Kerberos realm names which describe per-realm
+KDC parameters.
+.SH KDCDEFAULTS SECTION
+The following relations are defined in the
+.I [kdcdefaults]
+section:
+.IP kdc_ports
+This relation lists the ports which the Kerberos server should listen
+on, by default.  This list is a comma separated list of integers.  If
+this relation is not specified, the compiled-in default is usually
+port 88 and port 750.
+
+.IP v4_mode
+This 
+.B string
+specifies how the KDC should respond to Kerberos IV packets. Valid
+values for this relation are the same as the valid arguments to the
+.B -4
+flag to
+.BR krb5kdc .
+If this relation is not specified, the compiled-in default of
+.I none
+is used.
+
+.SH REALMS SECTION
+Each tag in the
+.I [realms]
+section of the file names a Kerberos realm.  The value of the tag is a
+subsection where the relations in that subsection define KDC parameters for
+that particular realm.
+.PP
+For each realm, the following tags may be specified in the
+.I [realms]
+subsection:
+
+.IP acl_file
+This
+.B string
+specifies the location of the access control list (acl) file that
+kadmin uses to determine which principals are allowed which permissions
+on the database. The default value is /usr/local/var/krb5kdc/kadm5.acl.
+
+.IP admin_keytab
+This
+.B string
+Specifies the location of the keytab file that kadmin uses to
+authenticate to the database.  The default value is
+/usr/local/var/krb5kdc/kadm5.keytab.
+
+.IP database_name
+This
+.B string
+specifies the location of the Kerberos database for this realm.
+
+.IP default_principal_expiration
+This
+.B absolute time string
+specifies the default expiration date of principals created in this realm.
+
+.IP default_principal_flags
+This
+.B flag string
+specifies the default attributes of principals created in this realm.
+The format for the string is a comma-separated list of flags, with '+'
+before each flag to be enabled and '-' before each flag to be
+disabled.  The default is for postdateable, forwardable, tgt-based,
+renewable, proxiable, dup-skey, allow-tickets, and service to be
+enabled, and all others to be disabled.
+
+There are a number of possible flags: 
+.RS
+.TP
+.B postdateable
+Enabling this flag allows the principal to obtain postdateable tickets.
+.TP
+.B forwardable
+Enabling this flag allows the principal to obtain forwardable tickets.
+.TP
+.B tgt-based
+Enabling this flag allows a principal to obtain tickets based on a
+ticket-granting-ticket, rather than repeating the authentication
+process that was used to obtain the TGT.
+.TP
+.B renewable
+Enabling this flag allows the principal to obtain renewable tickets.
+.TP
+.B proxiable
+Enabling this flag allows the principal to obtain proxy tickets.
+.TP
+.B dup-skey
+Enabling this flag allows the principal to obtain a session key for
+another user, permitting user-to-user authentication for this principal.
+.TP
+.B allow-tickets
+Enabling this flag means that the KDC will issue tickets for this
+principal.  Disabling this flag essentially deactivates the principal
+within this realm.
+.TP
+.B preauth
+If this flag is enabled on a client principal, then that principal is
+required to preauthenticate to the KDC before receiving any tickets.
+On a service principal, enabling this flag means that service tickets
+for this principal will only be issued to clients with a TGT that has
+the preauthenticated ticket set.
+.TP
+.B hwauth
+If this flag is enabled, then the principal is required to
+preauthenticate using a hardware device before receiving any tickets.
+.TP
+.B pwchange
+Enabling this flag forces a password change for this principal.
+.TP
+.B service
+Enabling this flag allows the the KDC to issue service tickets for this
+principal.
+.TP
+.B pwservice
+If this flag is enabled, it marks this principal as a password change
+service.  This should only be used in special cases, for example, if a
+user's password has expired, the user has to get tickets for that
+principal to be able to change it without going through the normal
+password authentication.
+.RE
+
+.IP dict_file
+This
+.B string
+location of the dictionary file containing strings that are not allowed
+as passwords.  If this tag is not set or if there is no policy assigned
+to the principal, then no check will be done.
+
+.IP kadmind_port
+This
+.B port number
+specifies the port on which the kadmind daemon is to listen for this
+realm.
+
+.IP kpasswd_port
+This
+.B port number
+specifies the port on which the kadmind daemon is to listen for this
+realm.
+
+.IP key_stash_file
+This
+.B string
+specifies the location where the master key has been stored with
+.I kdb5_stash.
+
+.IP kdc_ports
+This
+.B string
+specifies the list of ports that the KDC is to listen to for this realm.  
+By default, the value of 
+.I kdc_ports
+as specified in the 
+.I [kdcdefaults] 
+section is used.
+
+.IP master_key_name
+This
+.B string
+specifies the name of the principal associated with the master key.
+The default value is K/M.
+
+.IP master_key_type
+This
+.B key type string
+represents the master key's key type.
+
+.IP max_life
+This
+.B delta time string
+specifes the maximum time period that a ticket may be valid for in
+this realm.  
+
+.IP max_renewable_life
+This
+.B delta time string
+specifies the maximum time period that a ticket may be renewed for in
+this realm. 
+
+.IP supported_enctypes
+list of key:salt strings that specifies the default key/salt
+combinations of principals for this realm
+
+.IP kdc_supported_enctypes
+specifies the permitted key-salt combinations of principals for this realm
+
+.IP reject_bad_transit
+this
+.B boolean
+specifies whether or not the list of transited realms for cross-realm
+tickets should be checked against the transit path computed from the
+realm names and the [capaths] section of its krb5.conf file
+
+.SH FILES 
+/usr/local/var/krb5kdc/kdc.conf
+
+.SH SEE ALSO
+krb5.conf(5), krb5kdc(8)
diff --git a/krb5-1-6/src/config-files/krb5.conf b/krb5-1-6/src/config-files/krb5.conf
new file mode 100644
index 000000000..efc19e45d
--- /dev/null
+++ b/krb5-1-6/src/config-files/krb5.conf
@@ -0,0 +1,33 @@
+[libdefaults]
+	default_realm = ATHENA.MIT.EDU
+	krb4_config = /usr/kerberos/lib/krb.conf
+	krb4_realms = /usr/kerberos/lib/krb.realms
+
+[realms]
+	ATHENA.MIT.EDU = {
+		admin_server = KERBEROS.MIT.EDU
+		default_domain = MIT.EDU
+		v4_instance_convert = {
+			mit = mit.edu
+			lithium = lithium.lcs.mit.edu
+		}
+	}
+	ANDREW.CMU.EDU = {
+		admin_server = vice28.fs.andrew.cmu.edu
+	}
+# use "kdc =" if realm admins haven't put SRV records into DNS
+        GNU.ORG = {
+                kdc = kerberos.gnu.org
+                kdc = kerberos-2.gnu.org
+                admin_server = kerberos.gnu.org
+        }
+
+[domain_realm]
+	.mit.edu = ATHENA.MIT.EDU
+	mit.edu = ATHENA.MIT.EDU
+	.media.mit.edu = MEDIA-LAB.MIT.EDU
+	media.mit.edu = MEDIA-LAB.MIT.EDU
+	.ucsc.edu = CATS.UCSC.EDU
+
+[logging]
+#	kdc = CONSOLE
diff --git a/krb5-1-6/src/config-files/krb5.conf.M b/krb5-1-6/src/config-files/krb5.conf.M
new file mode 100644
index 000000000..92460a79b
--- /dev/null
+++ b/krb5-1-6/src/config-files/krb5.conf.M
@@ -0,0 +1,654 @@
+.\" Copyright 1995 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KRB5.CONF 5
+.SH NAME
+krb5.conf \- Kerberos configuration file
+.SH DESCRIPTION
+.I krb5.conf
+contains configuration information needed by the Kerberos V5 library.
+This includes information describing the default Kerberos realm, and the
+location of the Kerberos key distribution centers for known realms.
+.PP
+The 
+.I krb5.conf
+file uses an INI-style format.  Sections are delimited by square braces;
+within each section, there are relations where tags can be assigned to
+have specific values.  Tags can also contain a subsection, which
+contains further relations or subsections.  A tag can be assigned to
+multiple values.  Here is an example of the INI-style format used by
+.IR krb5.conf :
+
+.sp
+.nf
+.in +1i
+[section1]
+	tag1 = value_a
+	tag1 = value_b
+	tag2 = value_c
+
+[section 2]
+	tag3 = {
+		subtag1 = subtag_value_a
+		subtag1 = subtag_value_b
+		subtag2 = subtag_value_c
+	}
+	tag4 = {
+		subtag1 = subtag_value_d
+		subtag2 = subtag_value_e
+	}
+.in -1i
+.fi
+.sp
+
+.PP
+The following sections are currently used in the 
+.I krb5.conf
+file:
+.IP [libdefaults]
+Contains various default values used by the Kerberos V5 library.
+
+.IP [login]
+Contains default values used by the Kerberos V5 login program,
+.IR login.krb5 (8).
+
+.IP [appdefaults]
+Contains default values that can be used by Kerberos V5 applications.
+
+.IP [realms]
+Contains subsections keyed by Kerberos realm names which describe where
+to find the Kerberos servers for a particular realm, and other
+realm-specific information.
+
+.IP [domain_realm]
+Contains relations which map subdomains and domain names to Kerberos
+realm names.  This is used by programs to determine what realm a host
+should be in, given its fully qualified domain name.
+
+.IP [logging]
+Contains relations which determine how Kerberos entities are to perform
+their logging.
+
+.IP [capaths]
+Contains the authentication paths used with non-hierarchical
+cross-realm. Entries in the section are used by the client to determine
+the intermediate realms which may be used in cross-realm
+authentication. It is also used by the end-service when checking the
+transited field for trusted intermediate realms.
+
+.IP [dbdefaults]
+Contains default values for database specific parameters.
+
+.IP [dbmodules]
+Contains database specific parameters used by the database library.
+.PP 
+Each of these sections will be covered in more details in the following
+sections.
+.SH LIBDEFAULTS SECTION
+The following relations are defined in the [libdefaults] section:
+
+.IP default_keytab_name
+This relation specifies the default keytab name to be used by
+application severs such as telnetd and rlogind.  The default is
+"/etc/krb5.keytab".  This formerly defaulted to "/etc/v5srvtab", but
+was changed to the current value.
+
+.IP default_realm
+This relation identifies the default realm to be used in a client host's
+Kerberos activity.
+
+.IP default_tgs_enctypes
+This relation identifies the supported list of session key encryption
+types that should be returned by the KDC. The list may be delimited with
+commas or whitespace.
+
+.IP default_tkt_enctypes
+This relation identifies the supported list of session key encryption
+types that should be requested by the client, in the same format.
+
+.IP permitted_enctypes
+This relation identifies the permitted list of session key encryption
+types.
+
+.IP clockskew 
+This relation sets the maximum allowable amount of clockskew in seconds
+that the library will tolerate before assuming that a Kerberos message
+is invalid.  The default value is 300 seconds, or five minutes.
+
+.IP kdc_timesync 
+If the value of this relation is non-zero (the default), the library
+will compute the difference between the system clock and the time
+returned by the KDC and in order to correct for an inaccurate system
+clock.  This corrective factor is only used by the Kerberos library.
+
+.IP kdc_req_checksum_type
+For compatability with DCE security servers which do not support the
+default CKSUMTYPE_RSA_MD5 used by this version of Kerberos. Use a value
+of 2 to use the CKSUMTYPE_RSA_MD4 instead. This applies to DCE 1.1 and
+earlier.
+
+.IP ap_req_checksum_type 
+This allows you to set the checksum type used in the authenticator of
+KRB_AP_REQ messages.  The default value for this type is
+CKSUMTYPE_RSA_MD5.  For compatibility with applications linked against
+DCE version 1.1 or earlier Kerberos libraries, use a value of 2 to use
+the CKSUMTYPE_RSA_MD4
+instead.
+
+.IP safe_checksum_type 
+This allows you to set the preferred keyed-checksum type for use in KRB_SAFE
+messages.  The default value for this type is CKSUMTYPE_RSA_MD5_DES.
+For compatibility with applications linked against DCE version 1.1 or
+earlier Kerberos
+libraries, use a value of 3 to use the CKSUMTYPE_RSA_MD4_DES
+instead.  This field is ignored when its value is incompatible with
+the session key type.
+
+.IP preferred_preauth_types
+This allows you to set the preferred preauthentication types which the
+client will attempt before others which may be advertised by a KDC.  The
+default value for this setting is "17, 16, 15, 14", which forces libkrb5
+to attempt to use PKINIT if it is supported.
+
+.IP ccache_type
+User this parameter on systems which are DCE clients, to specify the
+type of cache to be created by kinit, or when forwarded tickets are
+received. DCE and Kerberos can share the cache, but some versions of DCE
+do not support the default cache as created by this version of
+Kerberos. Use a value of 1 on DCE 1.0.3a systems, and a value of 2 on
+DCE 1.1 systems.
+
+.IP krb4_srvtab 
+Specifies the location of the Kerberos V4 srvtab file.  Default is
+"/etc/srvtab".
+
+.IP krb4_config
+Specifies the location of the Kerberos V4 configuration file.  Default
+is "/etc/krb.conf".
+
+.IP krb4_realms
+Specifies the location of the Kerberos V4 domain/realm translation
+file.  Default is "/etc/krb.realms".
+
+.IP dns_lookup_kdc
+Indicate whether DNS SRV records shoud be used to locate the KDCs and 
+other servers for a realm, if they are not listed in the information 
+for the realm.  The default is to use these records.
+
+.IP dns_lookup_realm
+Indicate whether DNS TXT records should be used to determine the Kerberos
+realm of a host.  The default is not to use these records.
+
+.IP dns_fallback
+General flag controlling the use of DNS for Kerberos information.  If both
+of the preceding options are specified, this option has no effect.
+
+.IP extra_addresses
+This allows a computer to use multiple local addresses, in order to
+allow Kerberos to work in a network that uses NATs.  The addresses should
+be in a comma-separated list.
+
+.IP udp_preference_limit
+When sending a message to the KDC, the library will try using TCP
+before UDP if the size of the message is above "udp_preference_limit".
+If the message is smaller than "udp_preference_limit", then UDP will be
+tried before TCP.  Regardless of the size, both protocols will be
+tried if the first attempt fails.
+
+.IP verify_ap_req_nofail
+If this flag is set, then an attempt to get initial credentials will
+fail if the client machine does not have a keytab.  The default for the
+flag is false.
+
+.IP renew_lifetime
+The value of this tag is the default renewable lifetime for initial
+tickets.  The default value for the tag is 0.
+
+.IP noaddresses
+Setting this flag causes the initial Kerberos ticket to be addressless.
+The default for the flag is true.
+
+.IP forwardable
+If this flag is set, initial tickets by default will be forwardable.
+The default value for this flag is false.
+
+.IP proxiable
+If this flag is set, initial tickets by default will be proxiable.
+The default value for this flag is false.
+
+.SH APPDEFAULTS SECTION
+
+Each tag in the [appdefaults] section names a Kerberos V5 application
+or an option that is used by some Kerberos V5 application[s].  The
+four ways that you can set values for options are as follows, in
+decreasing order of precedence:
+
+.sp
+.nf
+.in +1i
+#1) 	
+	application = {
+		realm1 = {
+			option = value
+		}
+		realm2 = {
+			option = value
+		}
+	}
+#2) 	
+	application = {
+		option1 = value
+		option2 = value
+	}
+#3)	
+	realm = {
+		option = value
+	}
+#4)	
+	option = value
+.in -1in
+.fi
+.sp
+
+.SH LOGIN SECTION
+The [login] section is used to configure the behavior of the Kerberos V5
+login program,
+.IR login.krb5 (8).
+Refer to the manual entry for
+.I login.krb5
+for a description of the relations allowed in this section.
+.SH REALMS SECTION
+Each tag in the [realms] section of the file names a Kerberos realm.
+The value of the tag is a subsection where the relations in that
+subsection define the properties of that particular realm.  For example:
+
+.sp
+.nf
+.in +1i
+[realms]
+	ATHENA.MIT.EDU = {
+		admin_server = KERBEROS.MIT.EDU
+		default_domain = MIT.EDU
+		database_module = ldapconf
+		v4_instance_convert = {
+			mit = mit.edu
+			lithium = lithium.lcs.mit.edu
+		}
+		v4_realm = LCS.MIT.EDU
+	}
+.in -1i
+.fi
+.sp
+
+For each realm, the following tags may be specified in the realm's
+subsection:
+
+.IP kdc
+The value of this relation is the name of a host running a KDC for that
+realm.  An optional port number (preceded by a colon) may be appended to
+the hostname.  This tag should generally be used only if the realm
+administrator has not made the information available through DNS.
+
+.IP admin_server
+This relation identifies the host where the administration server is
+running.  Typically this is the Master Kerberos server.
+
+.IP database_module
+This relation indicates the name of the configuration section under dbmodules
+for database specific parameters used by the loadable database library.
+
+.IP default_domain
+This relation identifies the default domain for which hosts in this
+realm are assumed to be in.  This is needed for translating V4 principal
+names (which do not contain a domain name) to V5 principal names (which
+do).
+
+.IP v4_instance_convert
+This subsection allows the administrator to configure exceptions to the
+default_domain mapping rule.  It contains V4 instances (the tag name)
+which should be translated to some specific hostname (the tag value) as
+the second component in a Kerberos V5 principal name.
+
+.IP v4_realm
+This relation is used by the krb524 library routines when converting 
+a V5 principal name to a V4 principal name. It is used when V4 realm
+name and the V5 realm are not the same, but still share the same 
+principal names and passwords. The tag value is the Kerberos V4 realm 
+name. 
+
+.IP auth_to_local_names
+This subsection allows you to set explicit mappings from principal
+names to local user names.  The tag is the mapping name, and the value
+is the corresponding local user name.
+
+.IP auth_to_local
+This tag allows you to set a general rule for mapping principal names
+to local user names.  It will be used if there is not an explicit
+mapping for the principal name that is being translated.  The possible
+values are:
+
+.in +.5i
+DB:<filename>
+.in +.5i
+The principal will be looked up in the database <filename>.
+Support for this is not currently compiled in by default.
+.in -.5in
+RULE:<exp>
+.in +.5i
+The local name will be formulated from <exp>.
+.in -.5i
+DEFAULT
+.in +.5i
+The principal name will be used as the local name.  If the
+principal has more than one component or is not in the default
+realm, this rule is not applicable and the conversion will fail.
+.in -1i
+
+.SH DOMAIN_REALM SECTION
+
+The [domain_realm] section provides a translation from a hostname to the
+Kerberos realm name for the services provided by that host.
+.PP
+The tag name can be a hostname, or a domain name, where domain names are
+indicated by a prefix of a period ('.') character.  The value of the
+relation is the Kerberos realm name for that particular host or domain.
+Host names and domain names should be in lower case.
+.PP
+If no translation entry applies, the host's realm is considered to be
+the hostname's domain portion converted to upper case.  For example, the
+following [domain_realm] section:
+
+.sp
+.nf
+.in +1i
+[domain_realm]
+	.mit.edu = ATHENA.MIT.EDU
+	mit.edu = ATHENA.MIT.EDU 
+	dodo.mit.edu = SMS_TEST.MIT.EDU
+	.ucsc.edu = CATS.UCSC.EDU
+.in -1i
+.fi
+.sp
+maps dodo.mit.edu into the SMS_TEST.MIT.EDU realm, all other hosts in
+the MIT.EDU domain to the ATHENA.MIT.EDU realm, and all hosts in the
+UCSC.EDU domain into the CATS.UCSC.EDU realm.  ucbvax.berkeley.edu would
+be mapped by the default rules to the BERKELEY.EDU realm, while
+sage.lcs.mit.edu would be mapped to the LCS.MIT.EDU realm.
+
+.SH LOGGING SECTION
+
+The [logging] section indicates how a particular entity is to perform
+its logging.  The relations specified in this section assign one or more
+values to the entity name.
+.PP
+Currently, the following entities are used:
+.IP kdc
+These entries specify how the KDC is to perform its logging.
+.IP admin_server
+These entries specify how the administrative server is to perform its logging.
+.IP default
+These entries specify how to perform logging in the absence of explicit
+specifications otherwise.
+.PP
+Values are of the following forms:
+.IP FILE=<filename>
+.IP FILE:<filename>
+This value causes the entity's logging messages to go to the specified
+file.  If the
+.B =
+form is used, then the file is overwritten.  Otherwise, the file is
+appended to.
+.IP STDERR
+This value causes the entity's logging messages to go to its standard
+error stream.
+.IP CONSOLE
+This value causes the entity's logging messages to go to the console, if
+the system supports it.
+.IP DEVICE=<devicename>
+This causes the entity's logging messages to go to the specified device.
+.IP SYSLOG[:<severity>[:<facility>]]
+This causes the entity's logging messages to go to the system log.
+
+The
+.B severity
+argument specifies the default severity of system log messages.  This
+may be any of the following severities supported by the
+.I syslog(3)
+call minus the LOG_ prefix: LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
+LOG_WARNING, LOG_NOTICE, LOG_INFO, and LOG_DEBUG.  For example, to
+specify LOG_CRIT severity, one would use CRIT for
+.B severity.
+
+The
+.B facility
+argument specifies the facility under which the messages are logged.
+This may be any of the following facilities supported by the
+.I syslog(3)
+call minus the LOG_ prefix: LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON,
+LOG_AUTH, LOG_LPR, LOG_NEWS, LOG_UUCP, LOG_CRON, and LOG_LOCAL0 through
+LOG_LOCAL7.
+
+If no
+.B severity
+is specified, the default is ERR, and if no
+.B facility
+is specified, the default is AUTH.
+.PP
+In the following example, the logging messages from the KDC will go to
+the console and to the system log under the facility LOG_DAEMON with
+default severity of LOG_INFO; and the logging messages from the
+administrative server will be appended to the file /var/adm/kadmin.log
+and sent to the device /dev/tty04.
+.sp
+.nf
+.in +1i
+[logging]
+	kdc = CONSOLE
+	kdc = SYSLOG:INFO:DAEMON
+	admin_server = FILE:/var/adm/kadmin.log
+	admin_server = DEVICE=/dev/tty04
+.in -1i
+.fi
+.sp
+
+.SH CAPATHS SECTION
+
+Cross-realm authentication is typically organized hierarchically.  This
+hierarchy is based on the name of the realm, which thus imposes
+restrictions on the choice of realm names, and on who may participate in
+a cross-realm authentication. A non hierarchical orgization may be used,
+but requires a database to construct the authentication paths between
+the realms. This section defines that database.
+.PP
+A client will use this section to find the authentication path between
+its realm and the realm of the server. The server will use this section
+to verify the authentication path used be the client, by checking the
+transited field of the received ticket.
+.PP
+There is a tag name for each participating realm, and each tag has
+subtags for each of the realms. The value of the subtags is an
+intermediate realm which may participate in the cross-realm
+authentication. The subtags may be repeated if there is more then one
+intermediate realm. A value of "." means that the two realms share keys
+directly, and no intermediate realms should be allowed to participate.
+.PP
+There are n**2 possible entries in this table, but only those entries
+which will be needed on the client or the server need to be present. The
+client needs a tag for its local realm, with subtags for all the realms
+of servers it will need to authenticate with.  A server needs a tag for
+each realm of the clients it will serve.
+.PP
+For example, ANL.GOV, PNL.GOV, and NERSC.GOV all wish to use the ES.NET
+realm as an intermediate realm. ANL has a sub realm of TEST.ANL.GOV
+which will authenticate with NERSC.GOV but not PNL.GOV.  The [capath]
+section for ANL.GOV systems would look like this:
+.sp
+.nf
+.in +1i
+[capaths]
+	ANL.GOV = {
+		TEST.ANL.GOV = .
+		PNL.GOV = ES.NET
+		NERSC.GOV = ES.NET
+		ES.NET = .
+	}
+	TEST.ANL.GOV = {
+		ANL.GOV = .
+	}
+	PNL.GOV = {
+		ANL.GOV = ES.NET
+	}
+	NERSC.GOV = {
+		ANL.GOV = ES.NET
+	}
+	ES.NET = {
+		ANL.GOV = .
+	}
+.in -1i
+.fi
+.sp
+The [capath] section of the configuration file used on NERSC.GOV systems
+would look like this:
+.sp
+.nf
+.in +1i
+[capaths]
+	NERSC.GOV = {
+		ANL.GOV = ES.NET
+		TEST.ANL.GOV = ES.NET
+		TEST.ANL.GOV = ANL.GOV
+		PNL.GOV = ES.NET
+		ES.NET = .
+	}
+	ANL.GOV = {
+		NERSC.GOV = ES.NET
+	}
+	PNL.GOV = {
+		NERSC.GOV = ES.NET
+	}
+	ES.NET = {
+		NERSC.GOV = .
+	}
+	TEST.ANL.GOV = {
+		NERSC.GOV = ANL.GOV
+		NERSC.GOV = ES.NET
+	}
+.in -1i
+.fi
+.sp
+In the above examples, the ordering is not important, except when the
+same subtag name is used more then once. The client will use this to
+determing the path. (It is not important to the server, since the
+transited field is not sorted.)
+.PP
+If this section is not present, or if the client or server cannot find a
+client/server path, then normal hierarchical orginization is assumed.
+.PP
+This feature is not currently supported by DCE. DCE security servers can
+be used with Kerberized clients and servers, but versions prior to DCE
+1.1 did not fill in the transited field, and should be used with
+caution.
+
+.SH DATABASE DEFAULT SECTION
+
+The [dbdefaults] section indicates default values for the database specific parameters.
+It can also specify the configuration section under dbmodules for database
+specific parameters used by the loadable database library.  
+
+.PP
+The following tags are used in this section:
+.IP database_module
+This relation indicates the name of the configuration section under dbmodules
+for database specific parameters used by the loadable database library.
+
+.IP ldap_kerberos_container_dn 
+This LDAP specific tag indicates the DN of the container object where the realm
+objects will be located. This value is used if no object DN is mentioned in the
+configuration section under dbmodules.
+
+.IP ldap_kdc_dn
+This LDAP specific tag indicates the default bind DN for the KDC server.
+The KDC server does a login to the directory as this object. This value is used if
+no object DN is mentioned in the configuration section under dbmodules.
+
+.IP ldap_kadmind_dn
+This LDAP specific tag indicates the default bind DN for the
+Administration server. The Administration server does a login to the directory
+as this object. This value is used if no object DN is mentioned in
+the configuration section under dbmodules.
+
+.IP ldap_service_password_file
+This LDAP specific tag indicates the file containing the stashed passwords for the
+objects used for starting the Kerberos servers. This value is used if no
+service password file is mentioned in the configuration section under dbmodules.
+
+.IP ldap_server
+This LDAP specific tag indicates the list of LDAP servers. The list of LDAP servers
+is whitespace-separated. The LDAP server is specified by a LDAP URI.
+This value is used if no LDAP servers are mentioned in the configuration
+section under dbmodules.
+
+.IP ldap_conns_per_server
+This LDAP specific tag indicates the number of connections to be maintained per
+LDAP server. This value is used if the number of connections per LDAP server are not 
+mentioned in the configuration section under dbmodules. The default value is 5.
+
+.SH DATABASE MODULE SECTION
+Each tag in the [dbmodules] section of the file names a configuration section
+for database specific parameters that can be referred to by a realm. 
+The value of the tag is a subsection where the relations in that subsection
+define the database specific parameters.
+
+.PP
+For each section, the following tags may be specified in the subsection:
+
+.IP db_library
+This tag indicates the name of the loadable database library.
+The value should be db2 for db2 database and kldap for LDAP database.
+
+.IP ldap_kerberos_container_dn 
+This LDAP specific tag indicates the DN of the container object where the realm
+objects will be located.
+
+.IP ldap_kdc_dn
+This LDAP specific tag indicates the bind DN for the KDC server.
+The KDC does a login to the directory as this object.
+
+.IP ldap_kadmind_dn
+This LDAP specific tag indicates the bind DN for the Administration server.
+The Administration server does a login to the directory
+as this object.
+
+.IP ldap_service_password_file
+This LDAP specific tag indicates the file containing the stashed passwords for the
+objects used for starting the Kerberos servers.
+
+.IP ldap_server
+This LDAP specific tag indicates the list of LDAP servers. The list of LDAP servers
+is whitespace-separated. The LDAP server is specified by a LDAP URI.
+
+.IP ldap_conns_per_server
+This LDAP specific tag indicates the number of connections to be maintained per
+LDAP server.
+.SH FILES 
+/etc/krb5.conf
+.SH SEE ALSO
+syslog(3)
diff --git a/krb5-1-6/src/config-files/services.append b/krb5-1-6/src/config-files/services.append
new file mode 100644
index 000000000..bd1010f5c
--- /dev/null
+++ b/krb5-1-6/src/config-files/services.append
@@ -0,0 +1,32 @@
+#
+# Note --- if you are using Kerberos V4 clients and you either (a)
+# haven't converted all your KDC's over to use V5, or (b) are worried
+# about inter-realm interoperability with other KDC's that are still
+# using V4, then you will have to switch the definition of kerberos and
+# kerberos-sec.
+#
+# The issue is that the official port assignement for the "kerberos"
+# port is port 88, yet the unofficial port that has been used for
+# Kerberos V4 is port 750.  The V5 KDC will respond to requests made on
+# either port, and if V4 compatibility is turned on, it will respond to
+# V4 requests on either port as well.
+#
+#
+# Hence, it is safe to switch the definitions of kerberos and
+# kerberos-sec; both should be defined, though, and one should be port
+# 88 and one should be port 750.
+#
+kerberos	88/udp 		kdc		# Kerberos authentication--udp
+kerberos	88/tcp 		kdc		# Kerberos authentication--tcp
+kerberos-sec	750/udp 			# Kerberos authentication--udp
+kerberos-sec	750/tcp 			# Kerberos authentication--tcp
+kerberos_master	751/udp 			# Kerberos authentication
+kerberos_master	751/tcp 			# Kerberos authentication
+kerberos-adm	749/tcp				# Kerberos 5 admin/changepw
+kerberos-adm	749/udp				# Kerberos 5 admin/changepw
+kpop		1109/tcp			# Pop with Kerberos
+kshell		544/tcp		cmd		# and remote shell
+klogin		543/tcp				# Kerberos authenticated rlogin
+eklogin		2105/tcp			# Kerberos encrypted rlogin
+krb5_prop	754/tcp				# Kerberos slave propagation
+krb524		4444/tcp			# Kerberos 5 to 4 ticket xlator
diff --git a/krb5-1-6/src/config/ac-archive/README b/krb5-1-6/src/config/ac-archive/README
new file mode 100644
index 000000000..7bc626eb5
--- /dev/null
+++ b/krb5-1-6/src/config/ac-archive/README
@@ -0,0 +1,51 @@
+-*- text -*-
+
+These macros are taken from the autoconf archive at
+ac-archive.sourceforge.net.  Unless otherwise noted, they are under
+this modified version of the GNU General Public License version 2
+(also copied from ac-archive.sourceforge.net):
+
+    Every Autoconf macro presented on this web site is free software;
+    you can redistribute it and/or modify it under the terms of the
+    GNU General Public License as published by the Free Software
+    Foundation; either version 2, or (at your option) any later
+    version.
+
+    They are distributed in the hope that they will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    General Public License for more details. (You should have received
+    a copy of the GNU General Public License along with this program;
+    if not, write to the Free Software Foundation, Inc., 59 Temple
+    Place -- Suite 330, Boston, MA 02111-1307, USA.)
+
+    As a special exception, the Free Software Foundation gives
+    unlimited permission to copy, distribute and modify the configure
+    scripts that are the output of Autoconf. You need not follow the
+    terms of the GNU General Public License when using or distributing
+    such scripts, even though portions of the text of Autoconf appear
+    in them. The GNU General Public License (GPL) does govern all
+    other use of the material that constitutes the Autoconf program.
+
+    Certain portions of the Autoconf source text are designed to be
+    copied (in certain cases, depending on the input) into the output
+    of Autoconf. We call these the "data" portions. The rest of the
+    Autoconf source text consists of comments plus executable code
+    that decides which of the data portions to output in any given
+    case. We call these comments and executable code the "non-data"
+    portions. Autoconf never copies any of the non-data portions into
+    its output.
+
+    This special exception to the GPL applies to versions of Autoconf
+    released by the Free Software Foundation. When you make and
+    distribute a modified version of Autoconf, you may extend this
+    special exception to the GPL to apply to your modified version as
+    well, *unless* your modified version has the potential to copy
+    into its output some of the text that was the non-data portion of
+    the version that you started with. (In other words, unless your
+    change moves or copies text from the non-data portions to the data
+    portions.) If your modification has such potential, you must
+    delete any notice of this special exception to the GPL from your
+    modified version.
+
+acx_pthread.m4 version 1.5 2004/03/01
diff --git a/krb5-1-6/src/config/ac-archive/acx_pthread.m4 b/krb5-1-6/src/config/ac-archive/acx_pthread.m4
new file mode 100644
index 000000000..6a1537d47
--- /dev/null
+++ b/krb5-1-6/src/config/ac-archive/acx_pthread.m4
@@ -0,0 +1,239 @@
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro figures out how to build C programs using POSIX
+dnl threads.  It sets the PTHREAD_LIBS output variable to the threads
+dnl library and linker flags, and the PTHREAD_CFLAGS output variable
+dnl to any special C compiler flags that are needed.  (The user can also
+dnl force certain compiler flags/libs to be tested by setting these
+dnl environment variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well.  e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to
+dnl use these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl        LIBS="$PTHREAD_LIBS $LIBS"
+dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl        CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE
+dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands
+dnl to run it if it is not found.  If ACTION-IF-FOUND is not specified,
+dnl the default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform,
+dnl or if you have any other suggestions or comments.  This macro was
+dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org)
+dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread
+dnl macros posted by AFC to the autoconf macro repository.  We are also
+dnl grateful for the helpful feedback of numerous users.
+dnl
+dnl @version $Id: acx_pthread.m4,v 1.5 2004/03/01 19:28:29 guidod Exp $
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu> and Alejandro Forero Cuervo <bachue@bachue.com>
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthread or
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+		pthread-config)
+		AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+		if test x"$acx_pthread_config" = xno; then continue; fi
+		PTHREAD_CFLAGS="`pthread-config --cflags`"
+		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+		;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: threads are created detached by default
+        # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+        AC_MSG_CHECKING([for joinable pthread attribute])
+        AC_TRY_LINK([#include <pthread.h>],
+                    [int attr=PTHREAD_CREATE_JOINABLE;],
+                    ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+        if test x"$ok" = xunknown; then
+                AC_TRY_LINK([#include <pthread.h>],
+                            [int attr=PTHREAD_CREATE_UNDETACHED;],
+                            ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+        fi
+        if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+                AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+                          [Define to the necessary symbol if this constant
+                           uses a non-standard name on your system.])
+        fi
+        AC_MSG_RESULT(${ok})
+        if test x"$ok" = xunknown; then
+                AC_MSG_WARN([we do not know how to create joinable pthreads])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+                *-aix* | *-freebsd*)     flag="-D_THREAD_SAFE";;
+                *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+                PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        # More AIX lossage: must compile with cc_r
+        AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/krb5-1-6/src/config/config.guess b/krb5-1-6/src/config/config.guess
new file mode 100755
index 000000000..7924ac077
--- /dev/null
+++ b/krb5-1-6/src/config/config.guess
@@ -0,0 +1,1500 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2006-06-06'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    x86:Interix*:[345]*)
+	echo i586-pc-interix${UNAME_RELEASE}
+	exit ;;
+    EM64T:Interix*:[345]*)
+	echo x86_64-unknown-interix${UNAME_RELEASE}
+	exit ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-gnu
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
+	test x"${LIBC}" != x && {
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+		exit
+	}
+	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/krb5-1-6/src/config/config.sub b/krb5-1-6/src/config/config.sub
new file mode 100755
index 000000000..70584b007
--- /dev/null
+++ b/krb5-1-6/src/config/config.sub
@@ -0,0 +1,1608 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2006-06-06'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16c)
+		basic_machine=cr16c-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/krb5-1-6/src/config/install-sh b/krb5-1-6/src/config/install-sh
new file mode 100755
index 000000000..f5061e7e2
--- /dev/null
+++ b/krb5-1-6/src/config/install-sh
@@ -0,0 +1,295 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2003-09-24.23
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=
+transform_arg=
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+
+usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
+   or: $0 -d DIR1 DIR2...
+
+In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
+In the second, create the directory path DIR.
+
+Options:
+-b=TRANSFORMBASENAME
+-c         copy source (using $cpprog) instead of moving (using $mvprog).
+-d         create directories instead of installing files.
+-g GROUP   $chgrp installed files to GROUP.
+-m MODE    $chmod installed files to MODE.
+-o USER    $chown installed files to USER.
+-s         strip installed files (using $stripprog).
+-t=TRANSFORM
+--help     display this help and exit.
+--version  display version info and exit.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test -n "$1"; do
+  case $1 in
+    -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+        shift
+        continue;;
+
+    -c) instcmd=$cpprog
+        shift
+        continue;;
+
+    -d) dir_arg=true
+        shift
+        continue;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift
+        shift
+        continue;;
+
+    --help) echo "$usage"; exit 0;;
+
+    -m) chmodcmd="$chmodprog $2"
+        shift
+        shift
+        continue;;
+
+    -o) chowncmd="$chownprog $2"
+        shift
+        shift
+        continue;;
+
+    -s) stripcmd=$stripprog
+        shift
+        continue;;
+
+    -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+        shift
+        continue;;
+
+    --version) echo "$0 $scriptversion"; exit 0;;
+
+    *)  if test -z "$src"; then
+          src=$1
+        else
+          # this colon is to work around a 386BSD /bin/sh bug
+          :
+          dst=$1
+        fi
+        shift
+        continue;;
+  esac
+done
+
+if test -z "$src"; then
+  echo "$0: no input file specified." >&2
+  exit 1
+fi
+
+# Protect names starting with `-'.
+case $src in
+  -*) src=./$src ;;
+esac
+
+if test -n "$dir_arg"; then
+  dst=$src
+  src=
+
+  if test -d "$dst"; then
+    instcmd=:
+    chmodcmd=
+  else
+    instcmd=$mkdirprog
+  fi
+else
+  # Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+  # might cause directories to be created, which would be especially bad
+  # if $src (and thus $dsttmp) contains '*'.
+  if test ! -f "$src" && test ! -d "$src"; then
+    echo "$0: $src does not exist." >&2
+    exit 1
+  fi
+
+  if test -z "$dst"; then
+    echo "$0: no destination specified." >&2
+    exit 1
+  fi
+
+  # Protect names starting with `-'.
+  case $dst in
+    -*) dst=./$dst ;;
+  esac
+
+  # If destination is a directory, append the input filename; won't work
+  # if double slashes aren't ignored.
+  if test -d "$dst"; then
+    dst=$dst/`basename "$src"`
+  fi
+fi
+
+# This sed command emulates the dirname command.
+dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+
+# Skip lots of stat calls in the usual case.
+if test ! -d "$dstdir"; then
+  defaultIFS='
+	'
+  IFS="${IFS-$defaultIFS}"
+
+  oIFS=$IFS
+  # Some sh's can't handle IFS=/ for some reason.
+  IFS='%'
+  set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+  IFS=$oIFS
+
+  pathcomp=
+
+  while test $# -ne 0 ; do
+    pathcomp=$pathcomp$1
+    shift
+    test -d "$pathcomp" || $mkdirprog "$pathcomp"
+    pathcomp=$pathcomp/
+  done
+fi
+
+if test -n "$dir_arg"; then
+  $doit $instcmd "$dst" \
+    && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
+    && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
+    && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
+    && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
+
+else
+  # If we're going to rename the final executable, determine the name now.
+  if test -z "$transformarg"; then
+    dstfile=`basename "$dst"`
+  else
+    dstfile=`basename "$dst" $transformbasename \
+             | sed $transformarg`$transformbasename
+  fi
+
+  # don't allow the sed command to completely eliminate the filename.
+  test -z "$dstfile" && dstfile=`basename "$dst"`
+
+  # Make a couple of temp file names in the proper directory.
+  dsttmp=$dstdir/_inst.$$_
+  rmtmp=$dstdir/_rm.$$_
+
+  # Trap to clean up those temp files at exit.
+  trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Move or copy the file name to the temp name
+  $doit $instcmd "$src" "$dsttmp" &&
+
+  # and set any options; do chmod last to preserve setuid bits.
+  #
+  # If any of these fail, we abort the whole thing.  If we want to
+  # ignore errors from any of these, just make sure not to ignore
+  # errors from the above "$doit $instcmd $src $dsttmp" command.
+  #
+  { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+    && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+    && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+    && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
+
+  # Now remove or move aside any old file at destination location.  We
+  # try this two ways since rm can't unlink itself on some systems and
+  # the destination file might be busy for other reasons.  In this case,
+  # the final cleanup might fail but the new file should still install
+  # successfully.
+  {
+    if test -f "$dstdir/$dstfile"; then
+      $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
+      || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
+      || {
+	  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+	  (exit 1); exit
+      }
+    else
+      :
+    fi
+  } &&
+
+  # Now rename the file to the real destination.
+  $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+fi &&
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+{
+  (exit 0); exit
+}
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/krb5-1-6/src/config/lib.in b/krb5-1-6/src/config/lib.in
new file mode 100644
index 000000000..5d362743d
--- /dev/null
+++ b/krb5-1-6/src/config/lib.in
@@ -0,0 +1,170 @@
+### config/lib.in
+# *** keep this in sync with libnover.in
+#
+# Makefile fragment that creates static, shared, and profiled libraries.
+#
+# The following variables must be set in the Makefile.in:
+#
+# LIBBASE	library name without "lib" or extension
+# LIBMAJOR	library major version
+# LIBMINOR	library minor version
+# STOBJLISTS	list of files, each of which is an OBJS.ST created by
+#			libobj.in; *DO NOT* use ./OBJS.ST for the current
+#			directory as that will cause some makes to lose.
+# SHLIB_EXPDEPS	list of libraries that this one has explicit
+#			dependencies on, pref. in the form libfoo$(SHLIBEXT)
+# SHLIB_EXPLIBS	list of libraries that this one has explicit
+#			dependencies on, in "-lfoo" form.
+# SHLIB_DIRS	list of directories where $(SHLIB_EXPLIBS) can be
+#			found, in the form -Ldir1 -Ldir2 ...
+#			since there are very few systems where -L is the
+#			wrong thing (notable exception of SunOS but we
+#			deal with it...)
+# SHLIB_RDIRS	rpath directories to search; given in the
+#			form dir1:dir2 ...
+# RELDIR	path to this directory relative to $(TOPLIBD)
+
+LIBPREFIX=lib
+
+# STOBJLISTS=dir1/OBJS.ST dir2/OBJS.ST etc...
+SHOBJLISTS=$(STOBJLISTS:.ST=.SH)
+PFOBJLISTS=$(STOBJLISTS:.ST=.PF)
+
+dummy-target-1 $(SUBDIROBJLISTS) $(SUBDIROBJLISTS:.ST=.SH) $(SUBDIROBJLISTS:.ST=.PF): all-recurse
+
+# Gets invoked as $(PARSE_OBJLISTS) list-of-OBJS.*-files
+PARSE_OBJLISTS= set -x && $(PERL) -p -e 'BEGIN { $$SIG{__WARN__} = sub {die @_} }; $$e=$$ARGV; $$e =~ s/OBJS\...$$//; s/^/ /; s/ $$//; s/ / $$e/g;'
+
+lib$(LIBBASE)$(STLIBEXT): $(STOBJLISTS)
+	$(RM) $@
+	@echo "building static $(LIBBASE) library"
+	set -x; objlist=`$(PARSE_OBJLISTS) $(STOBJLISTS)` && $(AR) cq $@ $$objlist
+	$(RANLIB) $@
+
+lib$(LIBBASE)$(SHLIBVEXT): $(SHOBJLISTS) $(SHLIB_EXPDEPS) $(SHLIB_EXPORT_FILE_DEP)
+	$(RM) $@
+	@echo "building shared $(LIBBASE) library ($(LIBMAJOR).$(LIBMINOR))"
+	set -x; objlist=`$(PARSE_OBJLISTS) $(SHOBJLISTS)` && $(MAKE_SHLIB_COMMAND)
+
+lib$(LIBBASE)$(SHLIBSEXT): lib$(LIBBASE)$(SHLIBVEXT)
+	$(RM) $@
+	$(LN_S) lib$(LIBBASE)$(SHLIBVEXT) $@
+lib$(LIBBASE)$(SHLIBEXT): lib$(LIBBASE)$(SHLIBVEXT)
+	$(RM) $@
+	$(LN_S) lib$(LIBBASE)$(SHLIBVEXT) $@
+
+binutils.versions: $(SHLIB_EXPORT_FILE) Makefile
+	echo >  binutils.versions "$(LIBBASE)_$(LIBMAJOR)_MIT {"
+	sed  >> binutils.versions < $(SHLIB_EXPORT_FILE) "s/$$/;/"
+	echo >> binutils.versions "};"
+	echo >> binutils.versions "HIDDEN { local: __*; _rest*; _save*; *; };"
+
+darwin.exports: $(SHLIB_EXPORT_FILE) Makefile
+	sed > darwin-exports.tmp < $(SHLIB_EXPORT_FILE) "s/^/_/"
+	$(MV) darwin-exports.tmp darwin.exports
+
+osf1.exports: $(SHLIB_EXPORT_FILE) Makefile
+	$(RM) osf1.tmp osf1.exports
+	sed "s/^/-exported_symbol /" < $(SHLIB_EXPORT_FILE) > osf1.tmp
+	for f in . $(LIBINITFUNC); do \
+	  if test "$$f" != "." ; then \
+	    echo " -init $$f"__auxinit >> osf1.tmp; \
+	  else :; fi; \
+	done
+	a=""; \
+	for f in . $(LIBFINIFUNC); do \
+	  if test "$$f" != "." ; then \
+	    a="-fini $$f $$a"; \
+	  else :; fi; \
+	done; echo " $$a" >> osf1.tmp
+	mv -f osf1.tmp osf1.exports
+
+hpux10.exports: $(SHLIB_EXPORT_FILE) Makefile
+	$(RM) hpux10.tmp hpux10.exports
+	sed "s/^/+e /" < $(SHLIB_EXPORT_FILE) > hpux10.tmp
+	a=""; \
+	for f in . $(LIBFINIFUNC); do \
+	  if test "$$f" != .; then \
+	    a="+I $${f}__auxfini $$a"; \
+	  else :; fi; \
+	done; echo "$$a" >> hpux10.tmp
+	echo "+e errno" >> hpux10.tmp
+	echo "+e _GLOBAL__FD_lib$(LIBBASE)_$(LIBMAJOR)_$(LIBMINOR)" >> hpux10.tmp
+	echo "+e _GLOBAL__FI_lib$(LIBBASE)_$(LIBMAJOR)_$(LIBMINOR)" >> hpux10.tmp
+	mv -f hpux10.tmp hpux10.exports
+
+lib$(LIBBASE)$(PFLIBEXT): $(PFOBJLISTS)
+	$(RM) $@
+	@echo "building profiled $(LIBBASE) library"
+	set -x; objlist=`$(PARSE_OBJLISTS) $(PFOBJLISTS)` && $(AR) cq $@ $$objlist
+	$(RANLIB) $@
+
+$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT): lib$(LIBBASE)$(STLIBEXT)
+	$(RM) $@
+	(cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(STLIBEXT) .)
+$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT): lib$(LIBBASE)$(SHLIBEXT)
+	$(RM) $@
+	(cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(SHLIBEXT) .)
+$(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT): lib$(LIBBASE)$(SHLIBSEXT)
+	$(RM) $@
+	(cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(SHLIBSEXT) .)
+$(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT): lib$(LIBBASE)$(SHLIBVEXT)
+	$(RM) $@
+	(cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(SHLIBVEXT) .)
+$(TOPLIBD)/lib$(LIBBASE)$(PFLIBEXT): lib$(LIBBASE)$(PFLIBEXT)
+	$(RM) $@
+	(cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(PFLIBEXT) .)
+
+all-libs: $(LIBLIST)
+all-liblinks: $(LIBLINKS)
+
+clean-libs:
+	$(RM) lib$(LIBBASE)$(STLIBEXT)
+	$(RM) lib$(LIBBASE)$(SHLIBVEXT)
+	$(RM) lib$(LIBBASE)$(SHLIBSEXT)
+	$(RM) lib$(LIBBASE)$(SHLIBEXT)
+	$(RM) lib$(LIBBASE)$(PFLIBEXT)
+	$(RM) binutils.versions osf1.exports
+
+clean-liblinks:
+	$(RM) $(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT)
+	$(RM) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)
+	$(RM) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)
+	$(RM) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT)
+	$(RM) $(TOPLIBD)/lib$(LIBBASE)$(PFLIBEXT)
+
+install-libs: $(LIBINSTLIST)
+install-static:
+	$(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(STLIBEXT)
+	$(INSTALL_DATA) lib$(LIBBASE)$(STLIBEXT) $(DESTDIR)$(KRB5_LIBDIR)
+	$(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(STLIBEXT)
+install-shared:
+	$(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(SHLIBVEXT)
+	$(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(SHLIBEXT)
+	$(INSTALL_SHLIB) lib$(LIBBASE)$(SHLIBVEXT) $(DESTDIR)$(KRB5_LIBDIR)
+	(cd $(DESTDIR)$(KRB5_LIBDIR) && $(LN_S) lib$(LIBBASE)$(SHLIBVEXT) \
+		lib$(LIBBASE)$(SHLIBEXT))
+install-shlib-soname: install-shared
+	$(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(SHLIBSEXT)
+	(cd $(DESTDIR)$(KRB5_LIBDIR) && $(LN_S) lib$(LIBBASE)$(SHLIBVEXT) \
+		lib$(LIBBASE)$(SHLIBSEXT))
+install-profiled:
+	$(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(PFLIBEXT)
+	$(INSTALL_DATA) lib$(LIBBASE)$(PFLIBEXT) $(DESTDIR)$(KRB5_LIBDIR)
+	$(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(PFLIBEXT)
+
+Makefile: $(SRCTOP)/config/lib.in
+$(thisconfigdir)/config.status: $(SRCTOP)/config/shlib.conf
+
+# Use the following if links need to be made to $(TOPLIBD):
+# all-unix:: all-liblinks
+# install-unix:: install-libs
+# clean-unix:: clean-liblinks clean-libs
+
+# Use the following if links need not be made:
+# all-unix:: all-libs
+# install-unix:: install-libs
+# clean-unix:: clean-libs
+
+###
+### end config/lib.in
diff --git a/krb5-1-6/src/config/libnover.in b/krb5-1-6/src/config/libnover.in
new file mode 100644
index 000000000..09c42dcc8
--- /dev/null
+++ b/krb5-1-6/src/config/libnover.in
@@ -0,0 +1,112 @@
+### config/libnover.in
+# *** keep this in sync with lib.in
+#
+# Makefile fragment that creates shared libraries sans version
+# info (plugin modules).
+#
+# The following variables must be set in the Makefile.in:
+#
+# LIBBASE	library name without "lib" or extension
+# STOBJLISTS	list of files, each of which is an OBJS.ST created by
+#			libobj.in; *DO NOT* use ./OBJS.ST for the current
+#			directory as that will cause some makes to lose.
+# SHLIB_EXPDEPS	list of libraries that this one has explicit
+#			dependencies on, pref. in the form libfoo$(SHLIBEXT)
+# SHLIB_EXPLIBS	list of libraries that this one has explicit
+#			dependencies on, in "-lfoo" form.
+# SHLIB_DIRS	list of directories where $(SHLIB_EXPLIBS) can be
+#			found, in the form -Ldir1 -Ldir2 ...
+#			since there are very few systems where -L is the
+#			wrong thing (notable exception of SunOS but we
+#			deal with it...)
+# SHLIB_RDIRS	rpath directories to search; given in the
+#			form dir1:dir2 ...
+# RELDIR	path to this directory relative to $(TOPLIBD)
+
+LIBPREFIX=
+
+# STOBJLISTS=dir1/OBJS.ST dir2/OBJS.ST etc...
+SHOBJLISTS=$(STOBJLISTS:.ST=.SH)
+
+dummy-target-1 $(SUBDIROBJLISTS) $(SUBDIROBJLISTS:.ST=.SH) $(SUBDIROBJLISTS:.ST=.PF): all-recurse
+
+# Gets invoked as $(PARSE_OBJLISTS) list-of-OBJS.*-files
+PARSE_OBJLISTS= set -x && $(PERL) -p -e 'BEGIN { $$SIG{__WARN__} = sub {die @_} }; $$e=$$ARGV; $$e =~ s/OBJS\...$$//; s/^/ /; s/ $$//; s/ / $$e/g;'
+
+SHLIBVEXT=$(SHLIBEXT)
+LIBLIST=$(LIBBASE)$(DYNOBJEXT)
+LIBINSTLIST=install-shared
+
+$(LIBBASE)$(DYNOBJEXT): $(SHOBJLISTS) $(DYNOBJ_EXPDEPS) $(SHLIB_EXPORT_FILE_DEP)
+	$(RM) $@
+	@echo "building dynamic $(LIBBASE) object"
+	set -x; objlist=`$(PARSE_OBJLISTS) $(SHOBJLISTS)` && $(MAKE_DYNOBJ_COMMAND)
+
+binutils.versions: $(SHLIB_EXPORT_FILE) Makefile
+	echo >  binutils.versions "HIDDEN { local: __*; _rest*; _save*; *; };"
+	echo >> binutils.versions "$(LIBBASE)_$(LIBMAJOR)_MIT {"
+	sed  >> binutils.versions < $(SHLIB_EXPORT_FILE) "s/$$/;/"
+	echo >> binutils.versions "};"
+
+osf1.exports: $(SHLIB_EXPORT_FILE) Makefile
+	$(RM) osf1.tmp osf1.exports
+	sed "s/^/-exported_symbol /" < $(SHLIB_EXPORT_FILE) > osf1.tmp
+	for f in . $(LIBINITFUNC); do \
+	  if test "$$f" != "." ; then \
+	    echo " -init $$f"__auxinit >> osf1.tmp; \
+	  else :; fi; \
+	done
+	a=""; \
+	for f in . $(LIBFINIFUNC); do \
+	  if test "$$f" != "." ; then \
+	    a="-fini $$f $$a"; \
+	  else :; fi; \
+	done; echo " $$a" >> osf1.tmp; \
+	mv -f osf1.tmp osf1.exports
+
+hpux10.exports: $(SHLIB_EXPORT_FILE) Makefile
+	$(RM) hpux10.tmp hpux10.exports
+	sed "s/^/+e /" < $(SHLIB_EXPORT_FILE) > hpux10.tmp
+	a=""; \
+	for f in . $(LIBFINIFUNC); do \
+	  if test "$$f" != .; then \
+	    a="+I $${f}__auxfini $$a"; \
+	  else :; fi; \
+	done; echo "$$a" >> hpux10.tmp
+	echo "+e errno" >> hpux10.tmp
+	mv -f hpux10.tmp hpux10.exports
+
+darwin.exports: $(SHLIB_EXPORT_FILE) Makefile
+	$(RM) darwin.exports
+	sed "s/^/_/" < $(SHLIB_EXPORT_FILE) > darwin.exports
+
+$(TOPLIBD)/$(LIBBASE)$(SHLIBEXT): $(LIBBASE)$(SHLIBEXT)
+	$(RM) $@
+	(cd $(TOPLIBD) && $(LN_S) $(RELDIR)/$(LIBBASE)$(SHLIBEXT) .)
+
+all-libs: $(LIBBASE)$(DYNOBJEXT) # $(LIBLIST)
+
+clean-libs:
+	$(RM) $(LIBBASE)$(SHLIBEXT)
+	$(RM) binutils.versions osf1.exports
+
+install-libs: $(LIBINSTLIST)
+install-shared:
+	$(RM) $(DESTDIR)$(MODULE_INSTALL_DIR)/$(LIBBASE)$(DYNOBJEXT)
+	$(INSTALL_SHLIB) $(LIBBASE)$(DYNOBJEXT) $(DESTDIR)$(MODULE_INSTALL_DIR)
+
+Makefile: $(SRCTOP)/config/libnover.in
+$(thisconfigdir)/config.status: $(SRCTOP)/config/shlib.conf
+
+# Use the following if links need to be made to $(TOPLIBD):
+# all-unix:: all-liblinks
+# install-unix:: install-libs
+# clean-unix:: clean-liblinks clean-libs
+
+# Use the following if links need not be made:
+# all-unix:: all-libs
+# install-unix:: install-libs
+# clean-unix:: clean-libs
+
+###
+### end config/libnovers.in
diff --git a/krb5-1-6/src/config/libobj.in b/krb5-1-6/src/config/libobj.in
new file mode 100644
index 000000000..19cf2546e
--- /dev/null
+++ b/krb5-1-6/src/config/libobj.in
@@ -0,0 +1,39 @@
+### config/libobj.in
+#
+# Makefile fragment that builds object files for libraries.
+#
+# The following variables must be set in Makefile.in:
+#
+# STLIBOBJS	list of .o objects; this must not contain variable
+#		references.
+
+.SUFFIXES: .c .so .po
+.c.so:
+	$(CC) $(PICFLAGS) -DSHARED $(ALL_CFLAGS) -c $< -o $*.so.o && $(MV) $*.so.o $*.so
+.c.po:
+	$(CC) $(PROFFLAGS) $(ALL_CFLAGS) -c $< -o $*.po.o && $(MV) $*.po.o $*.po
+
+# rules to generate object file lists
+
+OBJS.ST: $(STLIBOBJS) Makefile
+	@echo $(STLIBOBJS) > $@
+
+OBJS.SH: $(SHLIBOBJS) Makefile
+	@echo $(SHLIBOBJS) > $@
+
+OBJS.PF: $(PFLIBOBJS) Makefile
+	@echo $(PFLIBOBJS) > $@
+
+all-libobjs: $(OBJLISTS)
+
+clean-libobjs:
+	$(RM) OBJS.ST OBJS.SH OBJS.PF $(STLIBOBJS) $(SHLIBOBJS) $(PFLIBOBJS)
+
+Makefile: $(SRCTOP)/config/libobj.in
+config.status: $(SRCTOP)/config/shlib.conf
+
+# clean-unix:: clean-libobjs
+# all-unix:: all-libobjs
+
+###
+### end config/libobj.in
diff --git a/krb5-1-6/src/config/mkinstalldirs b/krb5-1-6/src/config/mkinstalldirs
new file mode 100755
index 000000000..6b3b5fc5d
--- /dev/null
+++ b/krb5-1-6/src/config/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id$
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp"
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+  	  errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/krb5-1-6/src/config/move-if-changed b/krb5-1-6/src/config/move-if-changed
new file mode 100755
index 000000000..21403e129
--- /dev/null
+++ b/krb5-1-6/src/config/move-if-changed
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Move file 1 to file 2 if they don't already match.
+# Good for "make depend" for example, where it'd be nice to keep the
+# old datestamp.
+if [ $# != 2 ]; then
+  echo 2>&1 usage: $0 newfile oldfilename
+  exit 1
+fi
+#
+if [ ! -r "$2" ]; then
+  exec mv -f "$1" "$2"
+fi
+if cmp "$1" "$2" >/dev/null; then
+  echo "$2 is unchanged"
+  exec rm -f "$1"
+fi
+exec mv -f "$1" "$2"
diff --git a/krb5-1-6/src/config/post.in b/krb5-1-6/src/config/post.in
new file mode 100644
index 000000000..e997c5591
--- /dev/null
+++ b/krb5-1-6/src/config/post.in
@@ -0,0 +1,192 @@
+############################################################
+## config/post.in
+##
+
+# in case there is no default target (very unlikely)
+all::
+
+check-windows::
+
+##############################
+# dependency generation
+#
+
+depend:: depend-postrecurse
+depend-postrecurse: depend-recurse
+depend-recurse: depend-prerecurse
+
+depend-prerecurse:
+depend-postrecurse:
+
+depend-postrecurse: depend-update-makefile
+
+ALL_DEP_SRCS= $(SRCS) $(EXTRADEPSRCS)
+
+# be sure to check ALL_DEP_SRCS against *what it would be if SRCS and
+# EXTRADEPSRCS are both empty*
+$(BUILDTOP)/.depend-verify-srcdir:
+	@if test "$(srcdir)" = "." ; then \
+		echo 1>&2 error: cannot build dependencies with srcdir=. ; \
+		echo 1>&2 "(can't distinguish generated files from source files)" ; \
+		exit 1 ; \
+	else \
+		if test -r $(BUILDTOP)/.depend-verify-srcdir; then :; \
+			else (set -x; touch $(BUILDTOP)/.depend-verify-srcdir); fi \
+	fi
+$(BUILDTOP)/.depend-verify-et: depend-verify-et-$(COM_ERR_VERSION)
+depend-verify-et-k5:
+	@if test -r $(BUILDTOP)/.depend-verify-et; then :; \
+		else (set -x; touch $(BUILDTOP)/.depend-verify-et); fi
+depend-verify-et-sys:
+	@echo 1>&2 error: cannot build dependencies using system et package
+	@exit 1
+$(BUILDTOP)/.depend-verify-ss: depend-verify-ss-$(SS_VERSION)
+depend-verify-ss-k5:
+	@if test -r $(BUILDTOP)/.depend-verify-ss; then :; \
+		else (set -x; touch $(BUILDTOP)/.depend-verify-ss); fi
+depend-verify-ss-sys:
+	@echo 1>&2 error: cannot build dependencies using system ss package
+	@exit 1
+$(BUILDTOP)/.depend-verify-gcc: depend-verify-gcc-@HAVE_GCC@
+depend-verify-gcc-yes:
+	@if test -r $(BUILDTOP)/.depend-verify-gcc; then :; \
+		else (set -x; touch $(BUILDTOP)/.depend-verify-gcc); fi
+depend-verify-gcc-no:
+	@echo 1>&2 error: The '"depend"' rules are written for gcc.
+	@echo 1>&2 Please use gcc, or update the rules to handle your compiler.
+	@exit 1
+
+DEP_CFG_VERIFY = $(BUILDTOP)/.depend-verify-srcdir \
+	$(BUILDTOP)/.depend-verify-et $(BUILDTOP)/.depend-verify-ss
+DEP_VERIFY = $(DEP_CFG_VERIFY) $(BUILDTOP)/.depend-verify-gcc
+
+.d: $(ALL_DEP_SRCS) $(DEP_CFG_VERIFY) depend-dependencies
+	if test "$(ALL_DEP_SRCS)" != " " ; then \
+		$(RM) .dtmp && $(MAKE) .dtmp && mv -f .dtmp .d ; \
+	else \
+		touch .d ; \
+	fi
+
+# These are dependencies of the depend target that do not get fed to
+# the compiler.  Examples include generated header files.
+depend-dependencies:
+
+# .dtmp must *always* be out of date so that $? can be used to perform
+# VPATH searches on the sources.
+#
+# NOTE: This will fail when using Make programs whose VPATH support is
+# broken.
+.dtmp: $(ALL_DEP_SRCS)
+	$(CC) -M -DDEPEND $(ALL_CFLAGS) $? > .dtmp
+
+# NOTE: This will also generate spurious $(OUTPRE) and $(OBJEXT)
+# references in rules for non-library objects in a directory where
+# library objects happen to be built.  It's mostly harmless.
+.depend: .d $(SRCTOP)/util/depfix.pl
+	x=`$(CC) -print-libgcc-file-name` ; \
+	perl $(SRCTOP)/util/depfix.pl \
+		'$(SRCTOP)' '$(myfulldir)' '$(srcdir)' '$(BUILDTOP)' "$$x" '$(STLIBOBJS)' \
+		< .d > .depend
+
+depend-update-makefile: .depend depend-recurse
+	if test -n "$(SRCS)" ; then \
+		sed -e '/^# +++ Dependency line eater +++/,$$d' \
+			< $(srcdir)/Makefile.in | cat - .depend \
+			> $(srcdir)/Makefile.in.new; \
+	$(SRCTOP)/config/move-if-changed $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in ; \
+	else :; fi
+
+DEPTARGETS = .depend .d .dtmp $(DEP_VERIFY)
+DEPTARGETS_CLEAN = .depend .d .dtmp $(DEPTARGETS_@srcdir@_@CONFIG_RELTOPDIR@)
+DEPTARGETS_@top_srcdir@_. = $(DEP_VERIFY)
+
+#
+# end dependency generation
+##############################
+
+clean:: clean-$(WHAT)
+
+clean-unix::
+	$(RM) $(OBJS) $(DEPTARGETS_CLEAN) $(EXTRA_FILES)
+	-$(RM) -r $(srcdir)/$(thisconfigdir)/autom4te.cache
+
+clean-windows::
+	$(RM) *.$(OBJEXT)
+	$(RM) msvc.pdb *.err
+
+distclean:: distclean-$(WHAT)
+
+distclean-normal-clean:
+	$(MAKE) NORECURSE=true clean
+distclean-prerecurse: distclean-normal-clean
+distclean-nuke-configure-state:
+	$(RM) config.log config.cache config.status Makefile
+distclean-postrecurse: distclean-nuke-configure-state
+
+Makefiles-prerecurse: Makefile
+
+# thisconfigdir = relative path from this Makefile to config.status
+# mydir = relative path from config.status to this Makefile
+Makefile: $(srcdir)/Makefile.in $(thisconfigdir)/config.status \
+		$(SRCTOP)/config/pre.in $(SRCTOP)/config/post.in
+	cd $(thisconfigdir) && $(SHELL) config.status $(mydir)/Makefile
+$(thisconfigdir)/config.status: $(srcdir)/$(thisconfigdir)/configure
+	cd $(thisconfigdir) && $(SHELL) config.status --recheck
+# autom4te.cache supposedly improves performance with multiple runs, but
+# it breaks across versions, and around MIT we've got plenty of version
+# mixing.  So nuke it.
+$(srcdir)/$(thisconfigdir)/configure: @MAINT@ \
+		$(srcdir)/$(thisconfigdir)/configure.in \
+		$(SRCTOP)/patchlevel.h \
+		$(AUTOCONF_HEADER) \
+		$(SRCTOP)/aclocal.m4
+	-$(RM) -r $(srcdir)/$(thisconfigdir)/autom4te.cache
+	case "$(myfulldir)" in \
+	"" ) echo myfulldir not set in makefile ; exit 1 ;; \
+	. | appl* | tests* ) echo skipping ac syms check here ;; \
+	*) $(SRCTOP)/util/check-ac-syms $(top_srcdir) $(mydir)/$(BUILDTOP) $(AUTOCONF_HEADER) ;; \
+	esac
+	cd $(srcdir)/$(thisconfigdir) && \
+		$(AUTOCONF) --include=$(CONFIG_RELTOPDIR) $(AUTOCONFFLAGS)
+	-$(RM) -r $(srcdir)/$(thisconfigdir)/autom4te.cache
+
+RECURSE_TARGETS=all-recurse clean-recurse distclean-recurse install-recurse \
+	generate-files-mac-recurse \
+	check-recurse depend-recurse Makefiles-recurse install-headers-recurse
+
+# MY_SUBDIRS overrides any setting of SUBDIRS generated by the
+# configure script that generated this Makefile.  This is needed when
+# the configure script that produced this Makefile creates multiple
+# Makefiles in different directories; the setting of SUBDIRS will be
+# the same in each.
+#
+# LOCAL_SUBDIRS seems to account for the case where the configure
+# script doesn't call any other subsidiary configure scripts, but
+# generates multiple Makefiles.
+$(RECURSE_TARGETS):
+	@case "`echo 'x$(MFLAGS)'|sed -e 's/^x//' -e 's/ --.*$$//'`" \
+		in *[ik]*) e="status=1" ;; *) e="exit 1";; esac; \
+	do_subdirs="$(SUBDIRS)" ; \
+	status=0; \
+	if test -n "$$do_subdirs" && test -z "$(NORECURSE)"; then \
+	for i in $$do_subdirs ; do \
+		if test -d $$i && test -r $$i/Makefile ; then \
+		case $$i in .);; *) \
+			target=`echo $@|sed s/-recurse//`; \
+			echo "making $$target in $(CURRENT_DIR)$$i..."; \
+			if (cd $$i ; $(MAKE) \
+			    CURRENT_DIR=$(CURRENT_DIR)$$i/ $$target) then :; \
+			else eval $$e; fi; \
+			;; \
+		esac; \
+		else \
+			echo "Skipping missing directory $(CURRENT_DIR)$$i" ; \
+		fi; \
+	done; \
+	else :; \
+	fi;\
+	exit $$status
+
+##
+## end of post.in
+############################################################
diff --git a/krb5-1-6/src/config/pre.in b/krb5-1-6/src/config/pre.in
new file mode 100644
index 000000000..1a8185bc7
--- /dev/null
+++ b/krb5-1-6/src/config/pre.in
@@ -0,0 +1,564 @@
+############################################################
+## config/pre.in
+## common prefix for all Makefile.in in the Kerberos V5 tree.
+##
+
+# These are set per-directory by autoconf 2.52 and 2.53:
+#  srcdir=@srcdir@
+#  top_srcdir=@top_srcdir@
+# but these are only set by autoconf 2.53, and thus not useful to us on
+# Mac OS X yet (as of 10.2):
+#  abs_srcdir=@abs_srcdir@
+#  abs_top_srcdir=@abs_top_srcdir@
+#  builddir=@builddir@
+#  abs_builddir=@abs_builddir@
+#  top_builddir=@top_builddir@
+#  abs_top_builddir=@abs_top_builddir@
+# The "top" variables refer to the directory with the configure (or
+# config.status) script.
+
+WHAT = unix
+SHELL=/bin/sh
+
+all:: all-$(WHAT)
+
+clean:: clean-$(WHAT)
+
+distclean:: distclean-$(WHAT)
+
+install:: install-$(WHAT)
+
+check:: check-$(WHAT)
+
+install-headers:: install-headers-$(WHAT)
+
+##############################
+# Recursion rule support
+#
+
+# The commands for the recursion targets live in config/post.in.
+#
+# General form of recursion rules:
+#
+# Each recursive target foo-unix has related targets: foo-prerecurse,
+# foo-recurse, and foo-postrecurse
+#
+# The foo-recurse rule is in post.in.  It is what actually recursively
+# calls make.
+#
+# foo-recurse depends on foo-prerecurse, so any targets that must be
+# built before descending into subdirectories must be dependencies of
+# foo-prerecurse.
+#
+# foo-postrecurse depends on foo-recurse, but targets that must be
+# built after descending into subdirectories should be have
+# foo-recurse as dependencies in addition to being listed under
+# foo-postrecurse, to avoid ordering issues.
+#
+# The foo-prerecurse, foo-recurse, and foo-postrecurse rules are all
+# single-colon rules, to avoid nasty ordering problems with
+# double-colon rules.
+#
+# e.g.
+# all:: includes foo
+# foo:
+#	echo foo
+# includes::
+#	echo bar
+# includes::
+#	echo baz
+#
+# will result in "bar", "foo", "baz" on AIX, and possibly others.
+all-unix:: all-postrecurse
+all-postrecurse: all-recurse
+all-recurse: all-prerecurse
+
+all-prerecurse:
+all-postrecurse:
+
+clean-unix:: clean-postrecurse
+clean-postrecurse: clean-recurse
+clean-recurse: clean-prerecurse
+
+clean-prerecurse:
+clean-postrecurse:
+
+distclean-unix: distclean-postrecurse
+distclean-postrecurse: distclean-recurse
+distclean-recurse: distclean-prerecurse
+
+distclean-prerecurse:
+distclean-postrecurse:
+
+install-unix:: install-postrecurse
+install-postrecurse: install-recurse
+install-recurse: install-prerecurse
+
+install-prerecurse:
+install-postrecurse:
+
+install-headers-unix:: install-headers-postrecurse
+install-headers-postrecurse: install-headers-recurse
+install-headers-recurse: install-headers-prerecurse
+
+install-headers-prerecurse:
+install-headers-postrecurse:
+
+check-unix:: check-postrecurse
+check-postrecurse: check-recurse
+check-recurse: check-prerecurse
+
+check-prerecurse:
+check-postrecurse:
+
+Makefiles: Makefiles-postrecurse
+Makefiles-postrecurse: Makefiles-recurse
+Makefiles-recurse: Makefiles-prerecurse
+
+Makefiles-prerecurse:
+Makefiles-postrecurse:
+
+generate-files-mac: generate-files-mac-postrecurse
+generate-files-mac-postrecurse: generate-files-mac-recurse
+generate-files-mac-recurse: generate-files-mac-prerecurse
+generate-files-mac-prerecurse:
+
+#
+# end recursion rule support
+##############################
+
+# Directory syntax:
+#
+# begin relative path
+REL=
+# this is magic... should only be used for preceding a program invocation
+C=./
+# "/" for UNIX, "\" for Windows; *sigh*
+S=/
+
+#SUBDIRS = @subdirs@ $(LOCAL_SUBDIRS)
+SUBDIRS_@top_srcdir@ = @subdirs@
+SUBDIRS = $(SUBDIRS_@srcdir@) $(LOCAL_SUBDIRS)
+#
+srcdir = @srcdir@
+SRCTOP = @srcdir@/$(BUILDTOP)
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+CONFIG_RELTOPDIR = @CONFIG_RELTOPDIR@
+
+FAKEDEST=$(BUILDTOP)/util/fakedest
+FAKEPREFIX=$(FAKEDEST)/$(prefix)
+FAKELIBDIR=$(FAKEPREFIX)/lib
+
+# DEFS		set by configure
+# DEFINES	set by local Makefile.in
+# LOCALINCLUDES	set by local Makefile.in
+# CPPFLAGS	user override
+# CFLAGS	user override but starts off set by configure
+# PTHREAD_CFLAGS set by configure, not included in CFLAGS so that we
+#		don't pull the pthreads library into shared libraries
+ALL_CFLAGS = $(DEFS) $(DEFINES) $(KRB_INCLUDES) $(LOCALINCLUDES) \
+	-DKRB5_DEPRECATED=1 -DKRB5_PRIVATE=1 \
+	$(CPPFLAGS) $(CFLAGS) $(PTHREAD_CFLAGS)
+
+CFLAGS = @CFLAGS@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+THREAD_LINKOPTS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+CPPFLAGS = @CPPFLAGS@
+DEFS = @DEFS@
+CC = @CC@
+LD = $(PURE) @LD@
+DEPLIBS = @DEPLIBS@
+KRB_INCLUDES = -I$(BUILDTOP)/include -I$(SRCTOP)/include
+LDFLAGS = @LDFLAGS@
+LD_UNRESOLVED_PREFIX = @LD_UNRESOLVED_PREFIX@
+LD_SHLIBDIR_PREFIX = @LD_SHLIBDIR_PREFIX@
+LDARGS = @LDARGS@
+LIBS = @LIBS@
+SRVLIBS = @SRVLIBS@
+SRVDEPLIBS = @SRVDEPLIBS@
+CLNTLIBS = @CLNTLIBS@
+CLNTDEPLIBS = @CLNTDEPLIBS@
+
+INSTALL=@INSTALL@
+INSTALL_STRIP=
+INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP)
+INSTALL_SCRIPT=@INSTALL_PROGRAM@
+INSTALL_DATA=@INSTALL_DATA@
+INSTALL_SHLIB=@INSTALL_SHLIB@
+INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root
+## This is needed because autoconf will sometimes define @exec_prefix@ to be
+## ${prefix}.
+prefix=@prefix@
+INSTALL_PREFIX=$(prefix)
+INSTALL_EXEC_PREFIX=@exec_prefix@
+exec_prefix=@exec_prefix@
+datarootdir=@datarootdir@
+SHLIB_TAIL_COMP=@SHLIB_TAIL_COMP@
+
+datadir = @datadir@
+EXAMPLEDIR = $(datadir)/examples/krb5
+
+KRB5MANROOT = @mandir@
+ADMIN_BINDIR = @sbindir@
+SERVER_BINDIR = @sbindir@
+CLIENT_BINDIR =@bindir@
+ADMIN_MANDIR = $(KRB5MANROOT)/man8
+SERVER_MANDIR = $(KRB5MANROOT)/man8
+CLIENT_MANDIR = $(KRB5MANROOT)/man1
+FILE_MANDIR = $(KRB5MANROOT)/man5
+KRB5_LIBDIR = @libdir@
+KRB5_SHLIBDIR = @libdir@$(SHLIB_TAIL_COMP)
+KRB5_INCDIR = @includedir@
+MODULE_DIR = @libdir@/krb5/plugins
+KRB5_DB_MODULE_DIR = $(MODULE_DIR)/kdb
+KRB5_PA_MODULE_DIR = $(MODULE_DIR)/preauth
+KRB5_LIBKRB5_MODULE_DIR = $(MODULE_DIR)/libkrb5
+KRB5_INCSUBDIRS = \
+	$(KRB5_INCDIR)/krb5 \
+	$(KRB5_INCDIR)/gssapi \
+	$(KRB5_INCDIR)/kerberosIV \
+	$(KRB5_INCDIR)/gssrpc
+
+#
+# Macros used by the KADM5 (OV-based) unit test system.
+# XXX check which of these are actually used!
+#
+TESTDIR		= $(BUILDTOP)/kadmin/testing
+STESTDIR	= $(SRCTOP)/kadmin/testing
+COMPARE_DUMP	= $(TESTDIR)/scripts/compare_dump.pl
+FIX_CONF_FILES	= $(TESTDIR)/scripts/fixup-conf-files.pl
+INITDB		= $(STESTDIR)/scripts/init_db
+MAKE_KEYTAB	= $(TESTDIR)/scripts/make-host-keytab.pl
+LOCAL_MAKE_KEYTAB= $(TESTDIR)/scripts/make-host-keytab.pl
+RESTORE_FILES	= $(STESTDIR)/scripts/restore_files.sh
+SAVE_FILES	= $(STESTDIR)/scripts/save_files.sh
+ENV_SETUP	= $(TESTDIR)/scripts/env-setup.sh
+CLNTTCL		= $(TESTDIR)/util/ovsec_kadm_clnt_tcl
+SRVTCL		= $(TESTDIR)/util/ovsec_kadm_srv_tcl
+# Dejagnu variables.
+# We have to set the host with --host so that setup_xfail will work.
+# If we don't set it, then the host type used is "native", which
+# doesn't match "*-*-*".
+host=@krb5_cv_host@
+DEJAFLAGS	= $(DEJALFLAGS) $(CLFLAGS) --debug --srcdir $(srcdir) --host \
+		   $(host)
+RUNTEST		= runtest $(DEJAFLAGS)
+
+START_SERVERS	= $(STESTDIR)/scripts/start_servers $(TEST_SERVER) $(TEST_PATH)
+START_SERVERS_LOCAL = $(STESTDIR)/scripts/start_servers_local
+
+STOP_SERVERS	= $(STESTDIR)/scripts/stop_servers $(TEST_SERVER) $(TEST_PATH)
+STOP_SERVERS_LOCAL = $(STESTDIR)/scripts/stop_servers_local
+#
+# End of macros for the KADM5 unit test system.
+#
+
+transform = @program_transform_name@
+
+RM = rm -f
+CP  = cp
+MV = mv -f
+CHMOD=chmod
+RANLIB = @RANLIB@
+ARCHIVE = @ARCHIVE@
+ARADD = @ARADD@
+LN = @LN_S@
+AWK = @AWK@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+YACC = @YACC@
+PERL = @PERL@
+AUTOCONF = autoconf
+AUTOCONFFLAGS =
+AUTOHEADER = autoheader
+AUTOHEADERFLAGS =
+
+HOST_TYPE = @HOST_TYPE@
+SHEXT = @SHEXT@
+STEXT=@STEXT@
+VEXT=@VEXT@
+
+TOPLIBD = $(BUILDTOP)/lib
+
+OBJEXT = o
+LIBEXT = a
+EXEEXT =
+
+#
+# variables for libraries, for use in linking programs
+# -- this may want to get broken out into a separate frag later
+#
+#
+# Note: the following variables must be set in any Makefile.in that
+# uses KRB5_BUILD_PROGRAM
+#
+# PROG_LIBPATH	list of dirs, in -Ldir form, to search for libraries at link
+# PROG_RPATH	list of dirs, in dir1:dir2 form, for rpath purposes
+#
+# invocation is like:
+# prog: foo.o bar.o $(KRB5_BASE_DEPLIBS)
+# 	$(CC_LINK) -o $@ foo.o bar.o $(KRB5_BASE_LIBS)
+
+
+CC_LINK=@CC_LINK@
+
+# prefix (with no spaces after) for rpath flag to cc
+RPATH_FLAG=@RPATH_FLAG@
+
+# this gets set by configure to either $(STLIBEXT) or $(SHLIBEXT),
+# depending on whether we're building with shared libraries.
+DEPLIBEXT=@DEPLIBEXT@
+
+KADMCLNT_DEPLIB	= $(TOPLIBD)/libkadm5clnt$(DEPLIBEXT)
+KADMSRV_DEPLIB	= $(TOPLIBD)/libkadm5srv$(DEPLIBEXT)
+KDB5_DEPLIB	= $(TOPLIBD)/libkdb5$(DEPLIBEXT)
+GSSRPC_DEPLIB	= $(TOPLIBD)/libgssrpc$(DEPLIBEXT)
+GSS_DEPLIB	= $(TOPLIBD)/libgssapi_krb5$(DEPLIBEXT)
+KRB4_DEPLIB	= @KRB4_DEPLIB@		# $(TOPLIBD)/libkrb4$(DEPLIBEXT)
+DES425_DEPLIB	= @DES425_DEPLIB@	# $(TOPLIBD)/libdes425$(DEPLIBEXT)
+KRB5_DEPLIB	= $(TOPLIBD)/libkrb5$(DEPLIBEXT)
+CRYPTO_DEPLIB	= $(TOPLIBD)/libk5crypto$(DEPLIBEXT)
+COM_ERR_DEPLIB	= $(COM_ERR_DEPLIB-@COM_ERR_VERSION@)
+COM_ERR_DEPLIB-sys = # empty
+COM_ERR_DEPLIB-k5 = $(TOPLIBD)/libcom_err$(DEPLIBEXT)
+SUPPORT_LIBNAME=krb5support
+SUPPORT_DEPLIB	= $(TOPLIBD)/lib$(SUPPORT_LIBNAME)$(DEPLIBEXT)
+
+# These are forced to use ".a" as an extension because they're never
+# built shared.
+SS_DEPLIB	= $(SS_DEPLIB-@SS_VERSION@)
+SS_DEPLIB-k5	= $(TOPLIBD)/libss.a
+SS_DEPLIB-sys	=
+PTY_DEPLIB	= $(TOPLIBD)/libpty.a
+APPUTILS_DEPLIB	= $(TOPLIBD)/libapputils.a
+
+KRB5_BASE_DEPLIBS	= $(KRB5_DEPLIB) $(CRYPTO_DEPLIB) $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+KRB4COMPAT_DEPLIBS	= $(KRB4_DEPLIB) $(DES425_DEPLIB) $(KRB5_BASE_DEPLIBS)
+KDB5_DEPLIBS		= $(KDB5_DEPLIB)
+GSS_DEPLIBS		= $(GSS_DEPLIB)
+GSSRPC_DEPLIBS		= $(GSSRPC_DEPLIB) $(GSS_DEPLIBS)
+KADM_COMM_DEPLIBS	= $(GSSRPC_DEPLIBS) $(KDB5_DEPLIBS) $(GSSRPC_DEPLIBS)
+KADMSRV_DEPLIBS		= $(KADMSRV_DEPLIB) $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS)
+KADMCLNT_DEPLIBS	= $(KADMCLNT_DEPLIB) $(KADM_COMM_DEPLIBS)
+
+# Header file dependencies we might override.
+# See util/depfix.sed.
+# Also see depend-verify-* in post.in, which wants to confirm that we're using
+# the in-tree versions.
+COM_ERR_VERSION = @COM_ERR_VERSION@
+COM_ERR_DEPS	= $(COM_ERR_DEPS-@COM_ERR_VERSION@)
+COM_ERR_DEPS-sys =
+COM_ERR_DEPS-k5	= $(BUILDTOP)/include/com_err.h
+SS_VERSION	= @SS_VERSION@
+SS_DEPS		= $(SS_DEPS-@SS_VERSION@)
+SS_DEPS-sys	=
+SS_DEPS-k5	= $(BUILDTOP)/include/ss/ss.h $(BUILDTOP)/include/ss/ss_err.h
+
+# Header file dependencies that might depend on whether krb4 support
+# is compiled.
+
+KRB_ERR_H_DEP	= @KRB_ERR_H_DEP@
+
+# LIBS gets substituted in... e.g. -lnsl -lsocket
+
+# GEN_LIB is -lgen if needed for regexp
+GEN_LIB		= @GEN_LIB@
+
+SS_LIB		= $(SS_LIB-@SS_VERSION@)
+SS_LIB-sys	= @SS_LIB@
+SS_LIB-k5	= $(TOPLIBD)/libss.a
+KDB5_LIB	= -lkdb5
+
+DL_LIB		= @DL_LIB@
+
+KRB5_LIB			= -lkrb5
+K5CRYPTO_LIB			= -lk5crypto
+COM_ERR_LIB			= -lcom_err
+GSS_KRB5_LIB			= -lgssapi_krb5
+SUPPORT_LIB			= -l$(SUPPORT_LIBNAME)
+
+# KRB4_LIB is -lkrb4 if building --with-krb4
+# needs fixing if ever used on Mac OS X!
+KRB4_LIB	= @KRB4_LIB@
+
+# DES425_LIB is -ldes425 if building --with-krb4
+# needs fixing if ever used on Mac OS X!
+DES425_LIB	= @DES425_LIB@
+
+# HESIOD_LIBS is -lhesiod...
+HESIOD_LIBS	= @HESIOD_LIBS@
+
+KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
+KRB4COMPAT_LIBS	= $(KRB4_LIB) $(DES425_LIB) $(KRB5_BASE_LIBS)
+KDB5_LIBS	= $(KDB5_LIB)
+GSS_LIBS	= $(GSS_KRB5_LIB)
+# needs fixing if ever used on Mac OS X!
+GSSRPC_LIBS	= -lgssrpc $(GSS_LIBS)
+KADM_COMM_LIBS	= $(GSSRPC_LIBS)
+# need fixing if ever used on Mac OS X!
+KADMSRV_LIBS	= -lkadm5srv $(HESIOD_LIBS) $(KDB5_LIBS) $(KADM_COMM_LIBS)
+KADMCLNT_LIBS	= -lkadm5clnt $(KADM_COMM_LIBS)
+
+# need fixing if ever used on Mac OS X!
+PTY_LIB		= -lpty
+
+# libutil for NetBSD, et al. for openpty(), etc.
+UTIL_LIB	= @UTIL_LIB@
+
+# Misc stuff for linking server programs (and maybe some others,
+# eventually) but which we don't want to install.
+APPUTILS_LIB	= -lapputils
+
+#
+# some more stuff for --with-krb4
+KRB4_LIBPATH	= @KRB4_LIBPATH@
+KRB4_INCLUDES	= @KRB4_INCLUDES@
+
+#
+# variables for --with-tcl=
+TCL_LIBS	= @TCL_LIBS@
+TCL_LIBPATH	= @TCL_LIBPATH@
+TCL_RPATH	= @TCL_RPATH@
+TCL_MAYBE_RPATH = @TCL_MAYBE_RPATH@
+TCL_INCLUDES	= @TCL_INCLUDES@
+
+# error table rules
+#
+### /* these are invoked as $(...) foo.et, which works, but could be better */
+COMPILE_ET= $(COMPILE_ET-@COM_ERR_VERSION@)
+COMPILE_ET-sys= compile_et
+COMPILE_ET-k5= $(BUILDTOP)/util/et/compile_et -d $(SRCTOP)/util/et
+
+.SUFFIXES:  .h .c .et .ct
+
+# These versions cause both .c and .h files to be generated at once.
+# But GNU make doesn't understand this, and parallel builds can trigger
+# both of them at once, causing them to stomp on each other.  The versions
+# below only update one of the files, so compile_et has to get run twice,
+# but it won't break parallel builds.
+#.et.h: ; $(COMPILE_ET) $<
+#.et.c: ; $(COMPILE_ET) $<
+
+.et.h:
+	d=ettmp$$$$ ; (cp $< $$d.et && $(COMPILE_ET) $$d.et && mv $$d.h $*.h) ; \
+		e=$$? ; rm -f $$d.* ; exit $$e
+
+.et.c:
+	d=ettmp$$$$ ; (cp $< $$d.et && $(COMPILE_ET) $$d.et && mv $$d.c $*.c) ; \
+		e=$$? ; rm -f $$d.* ; exit $$e
+
+# rule to make object files
+#
+.SUFFIXES: .c .o
+.c.o:
+	$(CC) $(ALL_CFLAGS) -c $<
+
+# ss command table rules
+#
+MAKE_COMMANDS= $(MAKE_COMMANDS-@SS_VERSION@)
+MAKE_COMMANDS-sys= mk_cmds
+MAKE_COMMANDS-k5= $(BUILDTOP)/util/ss/mk_cmds
+
+.ct.c:
+	$(MAKE_COMMANDS) $<
+
+## Parameters to be set by configure for use in lib.in:
+##
+
+LN_S=@LN_S@
+AR=@AR@
+
+# Set to "lib$(LIBBASE)$(STEXT) lib$(LIBBASE)$(SHEXT) lib$(LIBBASE)$(PFEXT)" or
+# some subset thereof by configure; determines which types of libs get
+# built.
+LIBLIST=@LIBLIST@
+
+# Set by configure; list of library symlinks to make to $(TOPLIBD)
+LIBLINKS=@LIBLINKS@
+
+# Set by configure; list of install targets
+LIBINSTLIST=@LIBINSTLIST@
+
+# Some of these should really move to pre.in, since programs will need
+# it too. (e.g. stuff that has dependencies on the libraries)
+
+# usually .a
+STLIBEXT=@STLIBEXT@
+
+# usually .so.$(LIBMAJOR).$(LIBMINOR)
+SHLIBVEXT=@SHLIBVEXT@
+
+# usually .so.$(LIBMAJOR) (to allow for major-version compat)
+SHLIBSEXT=@SHLIBSEXT@
+
+# usually .so
+SHLIBEXT=@SHLIBEXT@
+
+# usually _p.a
+PFLIBEXT=@PFLIBEXT@
+
+#
+DYNOBJEXT=@DYNOBJEXT@
+MAKE_DYNOBJ_COMMAND=@MAKE_DYNOBJ_COMMAND@
+DYNOBJ_EXPDEPS=@DYNOBJ_EXPDEPS@
+DYNOBJ_EXPFLAGS=@DYNOBJ_EXPFLAGS@
+
+# File with symbol names to be exported, both functions and data,
+# currently not distinguished.
+SHLIB_EXPORT_FILE=$(srcdir)/$(LIBPREFIX)$(LIBBASE).exports
+
+# File that needs to be current for building the shared library,
+# usually SHLIB_EXPORT_FILE, but not always, if we have to convert
+# it to another, intermediate form for the linker.
+SHLIB_EXPORT_FILE_DEP=@SHLIB_EXPORT_FILE_DEP@
+
+# Command to run to build a shared library.
+# In systems that require multiple commands, like AIX, it may need
+# to change to rearrange where the various parameters fit in.
+MAKE_SHLIB_COMMAND=@MAKE_SHLIB_COMMAND@
+
+# flags for explicit libraries depending on this one,
+# e.g. "-R$(SHLIB_RPATH) $(SHLIB_SHLIB_DIRFLAGS) $(SHLIB_EXPLIBS)"
+SHLIB_EXPFLAGS=@SHLIB_EXPFLAGS@
+
+## Parameters to be set by configure for use in libobj.in:
+
+# Set to "OBJS.ST OBJS.SH OBJS.PF" or some subset thereof by
+# configure; determines which types of object files get built.
+OBJLISTS=@OBJLISTS@
+
+# Note that $(LIBSRCS) *cannot* contain any variable references, or
+# the suffix substitution will break on some platforms!
+SHLIBOBJS=$(STLIBOBJS:.o=@SHOBJEXT@)
+PFLIBOBJS=$(STLIBOBJS:.o=@PFOBJEXT@)
+
+# "$(CC) -G", "$(LD) -Bshareable", etc.
+LDCOMBINE=@LDCOMBINE@
+
+# "-h $@", "-h lib$(LIBNAME).$(LIBMAJOR)", etc.
+SONAME=@SONAME@
+
+
+#
+# rules to make various types of object files
+#
+PICFLAGS=@PICFLAGS@
+PROFFLAGS=@PROFFLAGS@
+
+# platform-dependent temporary files that should get cleaned up
+EXTRA_FILES=@EXTRA_FILES@
+
+VALGRIND=
+# Need absolute paths here because under kshd or ftpd we may run programs
+# while in other directories.
+VALGRIND_LOGDIR = `cd $(BUILDTOP)&&pwd`
+VALGRIND1 = valgrind --tool=memcheck --log-file=$(VALGRIND_LOGDIR)/vg --trace-children=yes -v --leak-check=yes --suppressions=`cd $(SRCTOP)&&pwd`/util/valgrind-suppressions
+
+#
+AUTOCONF_HEADER=$(SRCTOP)/include/autoconf.h.in
+
+##
+## end of pre.in
+############################################################
diff --git a/krb5-1-6/src/config/ren2long b/krb5-1-6/src/config/ren2long
new file mode 100755
index 000000000..e44dc8d5f
--- /dev/null
+++ b/krb5-1-6/src/config/ren2long
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Shell script that changes names that have been truncated to 8.3 format
+# back to their original longer name. The awk script produces a script with
+# lines of the following format:
+#     if [ -f <short> ]; then echo ::mv <short> <long> ; mv <short> <long> ; fi
+# These lines then get executed in bin/sh.
+#
+find . -type f -print | gawk -f $0.awk | sh -x 2> /dev/null
diff --git a/krb5-1-6/src/config/ren2long.awk b/krb5-1-6/src/config/ren2long.awk
new file mode 100644
index 000000000..fcf0177ea
--- /dev/null
+++ b/krb5-1-6/src/config/ren2long.awk
@@ -0,0 +1,75 @@
+#
+# Awk script to convert filenames shortened down to 8.3 
+# back to their larger size. 
+#
+# Works by looking at every filename and seeing if it's shortened
+# 8.3 version exists, and if so then mv the short name to the long
+# name.
+#
+# Usage: find . -type f -print | gawk -f ren2long.awk | sh -x [ 2> /dev/null ]
+#
+
+
+# Parse_path
+#
+# Takes the whole path and converts the basename part to 8.3. If it
+# changed in the process we emit a sh command to mv it if the shortened
+# name exists.
+# 
+function parse_path(p,P2,N,NEW) {
+
+     P2 = tolower(p)
+
+     NEW = ""
+     while(1) {
+	  N = index(P2,"/")			# Go until all / are parsed
+	  if (N == 0) break
+
+	  NEW = NEW name83(substr(P2,1,N-1)) "/"; # More of the path
+	  P2 = substr(P2,N+1)
+     }
+
+     if (bad[P2] == 1) {
+	  print "echo skipping " p
+	  return
+     }
+     NEW = NEW name83(P2)			# Append path and 8.3 name
+
+     if (bad[P2] == 2) {
+	  print "if [ -f " NEW " ]; then echo ::rm " NEW " ; rm " NEW " ; fi"
+	  return
+     }
+     if (NEW != p) 
+	  print "if [ -f " NEW " ]; then echo ::mv " NEW " " p " ; mv " NEW " " p " ; fi"
+}
+#
+# Name83
+# 
+# Converts the a single component part of a file name into 8.3 format
+#
+function name83(fname,P,B,E) {
+     P = index(fname,".");			# Find the extension
+
+     if (P == 0) {				# No extension
+	  B = substr(fname,1,8);		# Just truncate at 8 chars
+	  return B;
+    }
+
+    B = substr(fname, 1, P <= 8 ? P-1 : 8);	# At most 8 chars in name
+    E = substr(fname, P+1, 3)			# And 3 in extension
+    P = index(E, ".")				# 2 dot problem
+    if (P)
+	 E = substr(E, 1, P-1)
+
+     B = B "." E				# Put name together
+     return B
+}
+BEGIN {
+     bad["krb5-types-aux.h"] = 1
+     bad["autoconf.h.in"] = 1
+     bad["conv_tkt_skey.c"] = 1
+     ##bad["makefile"] = 2 -- windows have legitimate files with this name
+}
+{
+     parse_path($1)				# Do it
+}
diff --git a/krb5-1-6/src/config/rm.bat b/krb5-1-6/src/config/rm.bat
new file mode 100644
index 000000000..4cb1c8822
--- /dev/null
+++ b/krb5-1-6/src/config/rm.bat
@@ -0,0 +1,32 @@
+@echo off
+:loop
+if exist %1 del %1
+shift
+if not %1.==. goto loop
+exit
+
+Rem
+Rem rm.bat
+Rem
+Rem Copyright 1995 by the Massachusetts Institute of Technology.
+Rem All Rights Reserved.
+Rem
+Rem Export of this software from the United States of America may
+Rem   require a specific license from the United States Government.
+Rem   It is the responsibility of any person or organization contemplating
+Rem   export to obtain such a license before exporting.
+Rem 
+Rem WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+Rem distribute this software and its documentation for any purpose and
+Rem without fee is hereby granted, provided that the above copyright
+Rem notice appear in all copies and that both that copyright notice and
+Rem this permission notice appear in supporting documentation, and that
+Rem the name of M.I.T. not be used in advertising or publicity pertaining
+Rem to distribution of the software without specific, written prior
+Rem permission.  M.I.T. makes no representations about the suitability of
+Rem this software for any purpose.  It is provided "as is" without express
+Rem or implied warranty.
+Rem 
+Rem
+Rem Batch file to mimic the functionality of the Unix rm command
+Rem
diff --git a/krb5-1-6/src/config/shlib.conf b/krb5-1-6/src/config/shlib.conf
new file mode 100644
index 000000000..b26566a30
--- /dev/null
+++ b/krb5-1-6/src/config/shlib.conf
@@ -0,0 +1,478 @@
+# This shell script fragment should set a bunch of variables:
+#
+# CC_LINK_STATIC: How to link a program if we're only building static
+#  libraries for krb5 (but may use other shared libs, and there may
+#  be a shared krb5 lib already installed that we shouldn't use).
+# CC_LINK_SHARED: How to link a program if we're building shared
+#  libraries.
+# STLIBEXT: Static library extension.
+# SHLIBEXT: Shared library extension.
+# SHLIBVEXT: Shared library extension, with major version.
+# SHLIBSEXT: Shared library extension, with full version.
+# (... finish documenting these ...)
+
+#
+# Set up some defaults.
+#
+STLIBEXT=.a
+# Default to being unable to build shared libraries.
+SHLIBEXT=.so-nobuild
+SHLIBVEXT=.so.v-nobuild
+SHLIBSEXT=.so.s-nobuild
+# Most systems support profiled libraries.
+PFLIBEXT=_p.a
+# Most systems install shared libs as mode 644, etc. while hpux wants 755
+INSTALL_SHLIB='$(INSTALL_DATA)'
+# Most systems use the same objects for shared libraries and dynamically
+# loadable objects.
+DYNOBJEXT='$(SHLIBEXT)'
+MAKE_DYNOBJ_COMMAND='$(MAKE_SHLIB_COMMAND)'
+DYNOBJ_EXPDEPS='$(SHLIB_EXPDEPS)'
+DYNOBJ_EXPFLAGS='$(SHLIB_EXPFLAGS)'
+#
+use_linker_init_option=no
+use_linker_fini_option=no
+
+STOBJEXT=.o
+SHOBJEXT=.so
+PFOBJEXT=.po
+# Default for systems w/o shared libraries
+CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+#
+SHLIB_EXPORT_FILE_DEP='$(SHLIB_EXPORT_FILE)'
+# This will do for most platforms, and we'll substitute for
+# LDCOMBINE, SHLIB_EXPFLAGS, and LDCOMBINE_TAIL below.
+MAKE_SHLIB_COMMAND=x
+INIT_FINI_PREP=:
+
+# Default to static or shared libraries?
+default_static=no
+default_shared=yes
+
+# Set up architecture-specific variables.
+case $krb5_cv_host in
+alpha*-dec-osf*)
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.so.$(LIBMAJOR)'
+	SHLIBEXT=.so
+	# Alpha OSF/1 doesn't need separate PIC objects
+	SHOBJEXT=.o
+	INIT_FINI_PREP=initfini=
+	LDCOMBINE='$(CC) $(CFLAGS) $(PTHREAD_CFLAGS) -shared -Wl,-expect_unresolved -Wl,\* -Wl,-update_registry -Wl,$(BUILDTOP)/so_locations -Wl,-soname -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -Wl,-hidden -Wl,-input,osf1.exports $$initfini'
+	SHLIB_EXPORT_FILE_DEP=osf1.exports
+	use_linker_init_option=yes
+	use_linker_fini_option=yes
+	EXTRA_FILES="$EXTRA_FILES export"
+	SHLIB_EXPFLAGS='-rpath $(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	PROFFLAGS=-pg
+	RPATH_FLAG='-Wl,-rpath -Wl,'
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)'
+	if test "$krb5_cv_prog_gcc" = yes \
+		&& test "$krb5_cv_prog_gnu_ld" = yes; then
+		# Really should check for gnu ld vs system ld, too.
+		CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)'
+	else
+		# Need -oldstyle_liblookup to avoid picking up shared libs from
+		# other builds.  OSF/1 / Tru64 ld programs look through the entire
+		# library path for shared libs prior to looking through the
+		# entire library path for static libs.
+		CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) -Wl,-oldstyle_liblookup $(CFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)'
+	fi
+	# _RLD_ROOT hack needed to repoint "root" directory for purposes
+	# of searching for shared libs, since RPATHs take precedence over
+	# LD_LIBRARY_PATH.
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`$${LD_LIBRARY_PATH+:$$LD_LIBRARY_PATH}; export LD_LIBRARY_PATH; _RLD_ROOT=$(FAKEDEST):$${_RLD_ROOT+$$_RLD_ROOT}$${_RLD_ROOT-/}; export _RLD_ROOT;'
+	;;
+
+# HPUX *seems* to work under 10.20.
+# 
+# Note: "-Wl,+s" when building executables enables the use of the
+# SHLIB_PATH environment variable for finding shared libraries 
+# in non-standard directories.  If a non-standard search-path for
+#  shared libraries is compiled into the executable (using 
+# -Wl,+b,$KRB5_SHLIBDIR), then the order of "-Wl,+b,..." and "-Wl,+s" 
+# on the commandline of the linker will determine which path
+# (compiled-in or SHLIB_PATH) will be searched first.
+#
+# +I initproc routine gets called at load and unload time for
+#    shl_load calls, but appears to never be called for link-time
+#    specified libraries.
+# +e sym exports symbol and supposedly prevents other symbols
+#    from being exported, according to the man page, but the
+#    latter bit doesn't actually seem to work
+# -O +dpv should display any routines eliminated as unused, but -b
+#	  apparently turns that off
+*-*-hpux*)
+	INSTALL_SHLIB='$(INSTALL)'
+	SHLIBEXT=.sl
+	SHLIBVEXT='.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.$(LIBMAJOR)'
+	RPATH_FLAG='-Wl,+b,'
+	if test "$krb5_cv_prog_gcc" = yes; then
+		PICFLAGS=-fPIC
+		SHLIB_EXPFLAGS='-Wl,+s -Wl,+b,$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+		LDCOMBINE='gcc -fPIC -shared -Wl,+h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -Wl,-c,hpux10.exports'
+	else
+		PICFLAGS=+z
+		SHLIB_EXPFLAGS='+s +b $(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+		LDCOMBINE='ld -b +h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -c hpux10.exports'
+	fi
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -Wl,+s $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='SHLIB_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export SHLIB_PATH;'
+	SHLIB_EXPORT_FILE_DEP=hpux10.exports
+	# Do *not* set use_linker_init_option=yes here, because in the
+	# case where the library is specified at program link time, the
+	# initialization function appears not to get called, only for
+	# shl_load.  But for finalization functions, the shl_load case
+	# is the one we care about.
+	#
+	# Not setting use_linker_init_option here should cause compilation
+	# failures if the user tries to disable delayed initialization.
+	use_linker_fini_option=yes
+	;;
+
+mips-sgi-irix6.3)	# This is a Kludge; see below
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.so.$(LIBMAJOR)'
+	SHLIBEXT=.so
+	SHOBJEXT=.o
+	# Kludge follows: (gcc makes n32 object files but ld expects o32, so we reeducate ld)
+	if test "$krb5_cv_prog_gcc" = yes; then
+		LDCOMBINE='ld -n32 -shared -ignore_unresolved -update_registry $(BUILDTOP)/so_locations -soname $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)'
+	else
+		LDCOMBINE='ld -shared -ignore_unresolved -update_registry $(BUILDTOP)/so_locations -soname $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)'
+	fi
+	SHLIB_EXPFLAGS='-rpath $(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	# no gprof for Irix...
+	PROFFLAGS=-p
+	RPATH_FLAG='-Wl,-rpath -Wl,'
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	# This grossness is necessary due to the presence of *three*
+	# supported ABIs on Irix, and the precedence of the rpath over
+	# LD_LIBRARY*_PATH.  Like OSF/1, _RLD*_ROOT needs to be set to
+	# work around this lossage.
+	#
+	# Set the N32 and 64 variables first because the unqualified
+	# variables affect all three and can cause the sed command to fail.
+	#
+	# This loop is to reduce the clutter a slight bit.
+	add='`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`'
+	RUN_ENV=
+	for i in N32 64 ''; do
+		RUN_ENV="${RUN_ENV+ $RUN_ENV}LD_LIBRARY${i}_PATH=$add\$\${LD_LIBRARY${i}_PATH+:\$\$LD_LIBRARY${i}_PATH}; export LD_LIBRARY${i}_PATH;"
+		RUN_ENV="${RUN_ENV} _RLD${i}_ROOT=\$(FAKEDEST):\$\${_RLD${i}_ROOT+\$\${_RLD${i}_ROOT}}\$\${_RLD${i}_ROOT-/}; export _RLD${i}_ROOT;"
+	done
+	;;
+
+mips-sgi-irix*)
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.so.$(LIBMAJOR)'
+	SHLIBEXT=.so
+	SHOBJEXT=.o
+	if test "$krb5_cv_prog_gcc" = yes; then
+		LDCOMBINE_TAIL=""
+		INIT_FINI_PREP="initfini="
+	else
+		use_linker_init_option=yes
+		use_linker_fini_option=yes
+		INIT_FINI_PREP='initfini=; for f in . $(LIBINITFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-init,$${f}__auxinit"; fi; done; for f in . $(LIBFINIFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-fini,$${f}"; fi; done'
+		LDCOMBINE_TAIL='-Wl,-exports_file -Wl,$(SHLIB_EXPORT_FILE)'
+	fi
+	opts='-Wl,-ignore_unresolved -Wl,-update_registry -Wl,$(BUILDTOP)/so_locations'
+
+	if test "$krb5_cv_prog_gcc" = yes \
+		&& test "$krb5_cv_prog_gnu_ld" = yes; then
+		opts=''
+	fi
+	LDCOMBINE='$(CC) -shared '$opts' -Wl,-soname -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $$initfini'
+	SHLIB_EXPFLAGS='-rpath $(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	# no gprof for Irix...
+	PROFFLAGS=-p
+	RPATH_FLAG='-Wl,-rpath -Wl,'
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	# This grossness is necessary due to the presence of *three*
+	# supported ABIs on Irix, and the precedence of the rpath over
+	# LD_LIBRARY*_PATH.  Like OSF/1, _RLD*_ROOT needs to be set to
+	# work around this lossage.
+	#
+	# Set the N32 and 64 variables first because the unqualified
+	# variables affect all three and can cause the sed command to fail.
+	#
+	# This loop is to reduce the clutter a slight bit.
+	add='`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`'
+	RUN_ENV=
+	for i in N32 64 ''; do
+		RUN_ENV="${RUN_ENV+ $RUN_ENV}LD_LIBRARY${i}_PATH=$add\$\${LD_LIBRARY${i}_PATH+:\$\$LD_LIBRARY${i}_PATH}; export LD_LIBRARY${i}_PATH;"
+		RUN_ENV="${RUN_ENV} _RLD${i}_ROOT=\$(FAKEDEST):\$\${_RLD${i}_ROOT+\$\${_RLD${i}_ROOT}}\$\${_RLD${i}_ROOT-/}; export _RLD${i}_ROOT;"
+	done
+	;;
+
+# untested...
+mips-sni-sysv4)
+	if test "$krb5_cv_prog_gcc" = yes; then
+		PICFLAGS=-fpic
+		LDCOMBINE='$(CC) -G -Wl,-h -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)'
+	else
+		PICFLAGS=-Kpic
+		LDCOMBINE='$(CC) -G -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)'
+	fi
+	SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	SHLIBEXT=.so
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.so.$(LIBMAJOR)'
+	RPATH_FLAG=-R
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH;'
+	PROFFLAGS=-pg
+	;;
+
+mips-*-netbsd*)
+	PICFLAGS=-fPIC
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.so.$(LIBMAJOR)'
+	SHLIBEXT=.so
+	LDCOMBINE='ld -shared -soname $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)'
+	SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	RPATH_FLAG='-Wl,-rpath -Wl,'
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH;'
+	PROFFLAGS=-pg
+	;;
+
+*-*-netbsd*)
+	PICFLAGS=-fPIC
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBEXT=.so
+	LDCOMBINE='$(CC) -shared $(LDFLAGS)'
+	SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	RPATH_FLAG=-R
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH;'
+	PROFFLAGS=-pg
+	;;
+
+*-*-freebsd*)
+	if test -x /usr/bin/objformat ; then
+		objformat=`/usr/bin/objformat`
+	else
+		objformat="aout"
+	fi
+	PICFLAGS=-fpic
+	if test "x$objformat" = "xelf" ; then
+		SHLIBVEXT='.so.$(LIBMAJOR)'
+		RPATH_FLAG='-Wl,-rpath -Wl,'
+	else
+		RPATH_FLAG=-R
+		SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	fi
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	SHLIBEXT=.so
+	LDCOMBINE='ld -Bshareable'
+	SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH;'
+	PROFFLAGS=-pg
+	;;
+
+*-*-openbsd*)
+	PICFLAGS=-fpic
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBEXT=.so
+	LDCOMBINE='ld -Bshareable'
+	SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	RPATH_FLAG=-R
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH;'
+	PROFFLAGS=-pg
+	;;
+
+*-*-darwin* | *-*-rhapsody*)
+	SHLIBVEXT='.$(LIBMAJOR).$(LIBMINOR).dylib'
+	SHLIBSEXT='.$(LIBMAJOR).dylib'
+	SHLIB_EXPFLAGS='$(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	SHLIBEXT=.dylib
+	DYNOBJEXT=.so
+	SHLIB_EXPORT_FILE_DEP=darwin.exports
+	MAKE_DYNOBJ_COMMAND='$(CC) -bundle $(CFLAGS) $(LDFLAGS) -o $@ $$objlist $(DYNOBJ_EXPFLAGS) -exported_symbols_list darwin.exports'
+	LDCOMBINE='$(CC) -undefined error -dynamiclib -compatibility_version $(LIBMAJOR) -current_version $(LIBMAJOR).$(LIBMINOR) -install_name "$(KRB5_LIBDIR)/$(LIBPREFIX)$(LIBBASE)$(SHLIBVEXT)" $(CFLAGS) $(LDFLAGS)'
+	# The -dylib_file option tells the linker where to find indirect dependent
+	# libraries, without adding them to the dependency list.  We need this because
+	# the direct dependent libraries contain the pathname where the indirect
+	# dependent libraries will be installed (but haven't been yet).
+	LDCOMBINE_TAIL='-dylib_file "$(KRB5_LIBDIR)/libkrb5support.1.1.dylib":$(TOPLIBD)/libkrb5support.1.1.dylib'
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -dynamic $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='DYLD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export DYLD_LIBRARY_PATH;'
+	;;
+
+*-*-solaris*)
+	if test "$krb5_cv_prog_gcc" = yes; then
+		PICFLAGS=-fPIC
+		LDCOMBINE='$(CC) $(CFLAGS) -shared -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)'
+	else
+		PICFLAGS=-KPIC
+		# Solaris cc doesn't default to stuffing the SONAME field...
+		LDCOMBINE='$(CC) $(CFLAGS) -dy -G -z text -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $$initfini'
+		#
+		case $krb5_cv_host in
+		*-*-solaris2.[1-7] | *-*-solaris2.[1-7].*)
+		    # Did Solaris 7 and earlier have a linker option for this?
+		    ;;
+		*)
+		    INIT_FINI_PREP='initfini=; for f in . $(LIBINITFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-z,initarray=$${f}__auxinit"; fi; done; for f in . $(LIBFINIFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-z,finiarray=$$f"; fi; done'
+		    use_linker_init_option=yes
+		    use_linker_fini_option=yes
+		    ;;
+		esac
+	fi
+	LDCOMBINE_TAIL='$(LDFLAGS)'
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.so.$(LIBMAJOR)'
+	SHLIBEXT=.so
+	SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	PROFFLAGS=-pg
+	RPATH_FLAG=-R
+	CC_LINK_SHARED='$(PURE) $(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(PURE) $(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH;'
+	;;
+
+*-*-sunos*)
+	PICFLAGS=-fpic
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBEXT=.so
+	# The following grossness is to prevent relative paths from
+	# creeping into the RPATH of an executable or library built
+	# under SunOS; the explicit setting of LD_LIBRARY_PATH does
+	# does not make it into the output file, while directories
+	# passed by "-Ldirname" do.
+	LDCOMBINE='LD_LIBRARY_PATH=`echo $(SHLIB_DIRS) | sed -e "s/-L//g" -e "s/ /:/g"` ld -dp -assert pure-text'
+	SHLIB_EXPFLAGS='-L$(SHLIB_RDIRS) $(SHLIB_EXPLIBS)'
+	PROFFLAGS=-pg
+	# ick.
+	RPATH_FLAG=-L
+	CC_LINK_SHARED='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"` $(PURE) $(CC) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g` $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH;'
+	;;
+*-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu)
+	PICFLAGS=-fPIC
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBSEXT='.so.$(LIBMAJOR)'
+	SHLIBEXT=.so
+	# Linux ld doesn't default to stuffing the SONAME field...
+	# Use objdump -x to examine the fields of the library
+	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(LDFLAGS)'
+	# 
+	LDCOMBINE_TAIL='-Wl,--version-script binutils.versions && $(PERL) -w $(SRCTOP)/util/export-check.pl $(SHLIB_EXPORT_FILE) $@'
+	SHLIB_EXPORT_FILE_DEP=binutils.versions
+	# For cases where we do have dependencies on other libraries
+	# built in this tree...
+	SHLIB_EXPFLAGS='-Wl,-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	PROFFLAGS=-pg
+	RPATH_FLAG='-Wl,-rpath -Wl,'
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH) $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`; export LD_LIBRARY_PATH; '
+
+	## old version:
+	# Linux libc does weird stuff at shlib link time, must be
+	# explicitly listed here.  This also makes it get used even
+	# for the libraries marked as not having any dependencies; while
+	# that's not strictly correct, the resulting behavior -- not adding
+	# extra -R directories -- is still what we want.
+	#LDCOMBINE='ld -shared -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)'
+	#LDCOMBINE_TAIL="-lc"
+	#SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+
+	;;
+
+*-*-bsdi4*)
+	PICFLAGS=-fpic
+	SHLIBVEXT='.so.$(LIBMAJOR)'
+	SHLIBEXT=.so
+	LDCOMBINE='ld -Bshareable'
+	SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -Wl,-rpath,$(PROG_RPATH)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH)'
+	RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/
+/:/g"`; export LD_LIBRARY_PATH;'
+	PROFFLAGS=-pg
+	;;
+
+*-*-aix5*)
+	SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBEXT=.so
+	# AIX doesn't need separate PIC objects
+	SHOBJEXT=.o
+	SHLIB_EXPFLAGS='  $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	PROFFLAGS=-pg
+	if test "$krb5_cv_prog_gcc" = "yes" ; then
+	  wl_prefix=-Wl,
+	  RPATH_FLAG='-Wl,-blibpath:'
+	  LDCOMBINE='$(CC) -shared -v -o $@ $$objlist -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:$(SHLIB_EXPORT_FILE) -Xlinker -bernotok -Xlinker -brtl $(SHLIB_EXPFLAGS) -lc $$initfini'
+	else
+	  wl_prefix=
+	  RPATH_FLAG=-blibpath:
+	  LDCOMBINE='/bin/ld -o $@ $$objlist -H512 -T512 -bnoentry -bgcbypass:1 -bnodelcsect -bfilelist -bM:SRE -bE:$(SHLIB_EXPORT_FILE) -bernotok -brtl $(SHLIB_EXPFLAGS) -lc $$initfini'
+	fi
+	# Assume initialization always delayed.
+	INIT_FINI_PREP="wl=${wl_prefix}; "'i=1; initfini=; for f in . $(LIBFINIFUNC); do if test $$f != .; then initfini="$$initfini $${wl}-binitfini::$$f:$$i"; else :; fi; i=`expr $$i + 1`; done'
+	use_linker_fini_option=yes
+	MAKE_SHLIB_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE}"
+	RPATH_TAIL=:/usr/lib:/lib
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH):'"$RPATH_TAIL"' $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	# $(PROG_RPATH) is here to handle things like a shared tcl library
+	RUN_ENV='LIBPATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`:$(PROG_RPATH):/usr/lib:/usr/local/lib; export LIBPATH; '
+	;;
+
+*-*-aix4.*)
+	SHLIBVEXT='.a.$(LIBMAJOR).$(LIBMINOR)'
+	SHLIBEXT=.a
+	# AIX doesn't need separate PIC objects
+	SHOBJEXT=.o
+	SHLIB_EXPFLAGS='  $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+	PROFFLAGS=-pg
+	# Dynamically loaded object can have whatever suffix, but don't
+	# make archives like for shared libraries.
+	DYNOBJEXT=.so
+	#
+	if test "$krb5_cv_prog_gcc" = "yes" ; then
+	  wl_prefix=-Wl,
+	  RPATH_FLAG='-Wl,-blibpath:'
+	  LDCOMBINE='$(CC) -shared -v -o shr.o.$(LIBMAJOR).$(LIBMINOR) $$objlist -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:$(SHLIB_EXPORT_FILE) -Xlinker -bernotok $(SHLIB_EXPFLAGS) -lc $$initfini'
+	  LDCOMBINE_DYN='$(CC) -shared -v -o $@ $$objlist -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:$(SHLIB_EXPORT_FILE) -Xlinker -bernotok $(SHLIB_EXPFLAGS) -lc $$initfini'
+	else
+	  wl_prefix=
+	  RPATH_FLAG=-blibpath:
+	  LDCOMBINE='/bin/ld -o shr.o.$(LIBMAJOR).$(LIBMINOR) $$objlist -H512 -T512 -bnoentry -bgcbypass:1 -bnodelcsect -bfilelist -bM:SRE -bE:$(SHLIB_EXPORT_FILE) -bernotok $(SHLIB_EXPFLAGS) -lc $$initfini'
+	  LDCOMBINE_DYN='/bin/ld -o $@ $$objlist -H512 -T512 -bnoentry -bgcbypass:1 -bnodelcsect -bfilelist -bM:SRE -bE:$(SHLIB_EXPORT_FILE) -bernotok $(SHLIB_EXPFLAGS) -lc $$initfini'
+	fi
+	# Assume initialization always delayed.
+	INIT_FINI_PREP="wl=${wl_prefix}; "'i=1; initfini=; for f in . $(LIBFINIFUNC); do if test $$f != .; then initfini="$$initfini $${wl}-binitfini::$$f:$$i"; else :; fi; i=`expr $$i + 1`; done'
+	use_linker_fini_option=yes
+	MAKE_SHLIB_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE}"' && ar cq $@ shr.o.$(LIBMAJOR).$(LIBMINOR) && chmod +x $@ && rm -f shr.o.$(LIBMAJOR).$(LIBMINOR)'
+	MAKE_DYNOBJ_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE_DYN}"
+	RPATH_TAIL=:/usr/lib:/lib
+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(RPATH_FLAG)$(PROG_RPATH):'"$RPATH_TAIL"' $(CFLAGS) $(LDFLAGS)'
+	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+	# $(PROG_RPATH) is here to handle things like a shared tcl library
+	RUN_ENV='LIBPATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`:$(PROG_RPATH):/usr/lib:/usr/local/lib; export LIBPATH; '
+	;;
+esac
+
+if test "${MAKE_SHLIB_COMMAND}" = "x" ; then
+  if test "${INIT_FINI_PREP}" != ":"; then
+    MAKE_SHLIB_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE} -o \$@ \$\$objlist \$(SHLIB_EXPFLAGS) ${LDCOMBINE_TAIL}"
+  else
+    MAKE_SHLIB_COMMAND="${LDCOMBINE} -o \$@ \$\$objlist \$(SHLIB_EXPFLAGS) ${LDCOMBINE_TAIL}"
+  fi
+fi
diff --git a/krb5-1-6/src/config/wconfig.pl b/krb5-1-6/src/config/wconfig.pl
new file mode 100755
index 000000000..8a9d19f72
--- /dev/null
+++ b/krb5-1-6/src/config/wconfig.pl
@@ -0,0 +1,77 @@
+#! perl
+$win_flag = "WIN32##";
+@wflags = ();
+$mit_specific = 0;
+@ignore_list = ( "DOS#?#?" );
+
+foreach $arg (@ARGV) {
+    if ($arg =~ /^-/) { push @wflags, $arg; }
+    if ("--mit" eq $arg) {
+	$mit_specific = 1;
+    } elsif ("--win16" eq $arg) {
+	$win_flag = "WIN16##";
+    } elsif ("--win32" eq $arg) {
+	$win_flag = "WIN32##";
+    } elsif ($arg =~ /^--enable-/) {
+	my($a) = $arg . "##";
+	$a =~ s/^--enable-//;
+	$a =~ tr/a-z/A-Z/;
+	push @ignore_list, $a;
+    } elsif ($arg =~ /^--ignore=/) {
+	my($a) = $arg;
+	$a =~ s/--ignore=//;
+	push @ignore_list, $a;
+    } elsif ($arg =~ /^-/) {
+	print STDERR "Invalid option '$arg'\n";
+	exit 1;
+    } else {
+	if (! defined $dir) {
+	    $dir = $arg;
+	}
+    }
+}
+push @ignore_list, $win_flag;
+push @ignore_list, "MIT##" if $mit_specific;
+
+if ($#wflags >= 0) { printf "WCONFIG_FLAGS=%s\n", join (" ", @wflags); }
+
+# This has a couple variations from the old wconfig.c.
+#
+# The old script wouldn't treat the input strings as regular expressions.
+# This one does, and actually it builds one regexp, so the strict order of
+# checks done by wconfig.c no longer applies.
+#
+# And the old script would change "##DOS#" to "#", whereas this
+# version (with the regexp given above) will accept and discard 0, 1
+# or 2 "#" marks.
+$sub = "sub do_subst { my (\$a) = shift; \$a =~ s/^##(" . join("|", @ignore_list) . ")//; return \$a; }";
+#print STDERR $sub, "\n";
+eval $sub;
+
+sub process {
+    my $fh = shift;
+    while (<$fh>) {
+	if (/^@/) {
+	    # This branch isn't actually used as far as I can tell.
+	    print "\n";
+	    next;
+	}
+	# Do we want to do any autoconf-style @FOO@ substitutions?
+	# s/@MAINT@/#/g;
+	# Are there any options we might want to set at configure time?
+	print &do_subst($_);
+    }
+}
+
+if (defined $dir) {
+    open AUX, "<$dir/win-pre.in" || die "Couldn't open win-pre.in: $!\n";
+    &process(\*AUX);
+    close AUX;
+}
+&process(\*STDIN);
+if (defined $dir) {
+    open AUX, "<$dir/win-post.in" || die "Couldn't open win-post.in: $!\n";
+    &process(\*AUX);
+    close AUX;
+}
+exit 0;
diff --git a/krb5-1-6/src/config/win-post.in b/krb5-1-6/src/config/win-post.in
new file mode 100644
index 000000000..fd874aebe
--- /dev/null
+++ b/krb5-1-6/src/config/win-post.in
@@ -0,0 +1,111 @@
+#
+# Start of Win32 post-config lines (config/win-post.in)
+#
+
+setup-msg::
+	@set C_RULE_PRINT=	$(C_RULE_PRINT)
+	@set DO_C_RULE_PRINT=1
+
+!if defined(NO_OUTPRE) || defined(NO_OUTDIR)
+outpre-dir::
+!else
+outpre-dir:: $(OUTPRE3)$(DIRNUL)
+!endif
+
+#
+# put all:: first just in case no other rules occur here
+#
+all::
+
+#
+# Set the #define to indicate that we are compiling a DLL.  We default to 
+# compiling the Kerberos library
+#
+!if defined(DLL_EXP_TYPE)
+DLL_FILE_DEF=/D$(DLL_EXP_TYPE)_DLL_FILE
+!else
+DLL_FILE_DEF=/DKRB5_DLL_FILE
+!endif
+
+# Build the Makefile unless we are in the top-level
+#(where there is already an explicit rule).
+!if !defined(ZIP) && !defined(WINFILES)
+Makefile: Makefile.in $(BUILDTOP)\config\win-pre.in $(BUILDTOP)\config\win-post.in
+	$(WCONFIG) $(BUILDTOP)\config < Makefile.in > Makefile
+!endif
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+!if defined(WIN64LIBNAME)
+LIBNAME=$(WIN64LIBNAME)
+!endif
+!if defined(WIN64OBJFILE)
+OBJFILE=$(WIN64OBJFILE)
+!endif
+!endif
+
+!if defined(LIBNAME)
+
+!if !defined(OBJFILELIST)
+OBJFILELIST=@$(OBJFILE)
+!endif
+!if !defined(OBJFILEDEP)
+OBJFILEDEP=$(OBJFILE)
+!endif
+
+all-windows:: $(LIBNAME)
+$(LIBNAME): $(OBJFILEDEP)
+	$(LIBCMD) /out:$(LIBNAME) /nologo $(OBJFILELIST)
+
+!endif # LIBNAME
+
+
+!if defined(OBJFILE)
+all-windows:: $(OBJFILE)
+!if defined(LIBOBJS)
+$(OBJFILE): $(LIBOBJS)
+	if exist $(OBJFILE) del $(OBJFILE)
+!if defined(PREFIXDIR)
+	$(LIBECHO) -p $(PREFIXDIR)\ $** > $(OBJFILE)
+!else
+	$(LIBECHO) $** > $(OBJFILE)
+!endif # !PREFIXDIR
+!endif # LIBOBJS
+!endif # OBJFILE
+
+
+check::
+check-windows::
+
+!if defined(LIBNAME)
+clean-windows::
+# NO LONGER NEEDED BECAUSE WE CLEAN OUT THE DIR...
+#	if exist $(LIBNAME) del $(LIBNAME)
+!endif
+!if defined(OBJFILE)
+clean-windows::
+# NO LONGER NEEDED BECAUSE WE CLEAN OUT THE DIR...
+#	if exist $(OBJFILE) del $(OBJFILE)
+!endif
+
+clean-windows:: clean-windows-files clean-windows-dir
+
+
+# This needs to be in the post because we need RM to be defined in terms
+# of BUILDTOP
+clean-windows-files::
+!if "$(OUTPRE3)" == ""
+!error ASSERTION FAILURE: OUTPRE3 must be defined!!!
+!endif
+!if "$(OS)" == "Windows_NT"
+	@if exist $(OUTPRE3)$(DIRNUL) rd /s/q $(OUTPRE3)
+!else
+	@if exist $(OUTPRE3)$(DIRNUL) deltree /y $(OUTPRE3)
+!endif
+!if 0
+	$(RM) .\$(OUTPRE)*.obj .\$(OUTPRE)*.res
+	$(RM) .\$(OUTPRE)*.exe .\$(OUTPRE)*.dll
+	$(RM) .\$(OUTPRE)*.lib .\$(OUTPRE)*.pdb
+	$(RM) .\$(OUTPRE)*.exp .\$(OUTPRE)*.map
+	$(RM) .\$(OUTPRE)*.idb .\$(OUTPRE)*.ilk
+	$(RM) .\$(OUTPRE)*.manifest
+!endif
diff --git a/krb5-1-6/src/config/win-pre.in b/krb5-1-6/src/config/win-pre.in
new file mode 100644
index 000000000..7cadbe903
--- /dev/null
+++ b/krb5-1-6/src/config/win-pre.in
@@ -0,0 +1,258 @@
+WHAT=windows
+
+all:: setup-msg outpre-dir
+
+all:: all-$(WHAT)
+clean:: clean-$(WHAT)
+install:: install-$(WHAT)
+check:: check-$(WHAT)
+
+all-windows::
+clean-windows::
+install-windows::
+check-windows::
+
+all-windows:: Makefile
+clean-windows:: Makefile
+
+#
+# Figure out the CPU
+#
+!if !defined(CPU) || "$(CPU)" == ""
+CPU=$(PROCESSOR_ARCHITECTURE)
+!endif # CPU
+
+!if "$(CPU)" == ""
+CPU=i386
+!endif
+
+# Change x86 or X86 to i386
+!if ( "$(CPU)" == "X86" ) || ( "$(CPU)" == "x86" )
+CPU=i386
+!endif # CPU == X86
+
+!if ( "$(CPU)" != "i386" ) && ( "$(CPU)" != "ALPHA" ) && ( "$(CPU)" != "ALPHA64" ) && ( "$(CPU)" != "IA64" ) && ( "$(CPU)" != "AMD64" )
+!error Must specify CPU environment variable ( CPU=i386, CPU=ALPHA, CPU=ALPHA64,CPU=IA64, CPU=AMD64)
+!endif
+#
+# End of figuring out CPU
+#
+
+!if "$(OS)" == "Windows_NT"
+DIRNUL=
+!else 
+DIRNUL=\nul
+!endif
+
+# NOTE: ^ is an escape char for NMAKE.
+!ifdef NODEBUG
+OUTPRE_DBG=rel
+!else
+OUTPRE_DBG=dbg
+!endif
+OUTPRE1=obj
+OUTPRE2=$(OUTPRE1)\$(CPU)
+OUTPRE3=$(OUTPRE2)\$(OUTPRE_DBG)
+OUTPRE=$(OUTPRE3)^\
+
+$(OUTPRE3)$(DIRNUL):
+	-@if not exist $(OUTPRE1)$(DIRNUL) mkdir $(OUTPRE1)
+	-@if not exist $(OUTPRE2)$(DIRNUL) mkdir $(OUTPRE2)
+	-@if not exist $(OUTPRE3)$(DIRNUL) mkdir $(OUTPRE3)
+	@if exist $(OUTPRE3)$(DIRNUL) echo Output going into $(OUTPRE3)
+	@if not exist $(OUTPRE1)$(DIRNUL) echo The directory $(OUTPRE1) could not be created.
+	@if exist $(OUTPRE1)$(DIRNUL) if not exist $(OUTPRE2)$(DIRNUL) echo The directory $(OUTPRE2) could not be created.
+	@if exist $(OUTPRE2)$(DIRNUL) if not exist $(OUTPRE3)$(DIRNUL) echo The directory $(OUTPRE3) could not be created.
+
+
+clean-windows-dir::
+	-@if exist $(OUTPRE3)$(DIRNUL) rmdir $(OUTPRE3)
+	-@if exist $(OUTPRE2)$(DIRNUL) rmdir $(OUTPRE2)
+	-@if exist $(OUTPRE1)$(DIRNUL) rmdir $(OUTPRE1)
+	@if exist $(OUTPRE2)$(DIRNUL) echo The directory $(OUTPRE2) is not empty.
+	@if not exist $(OUTPRE2)$(DIRNUL) if exist $(OUTPRE1)$(DIRNUL) echo The directory $(OUTPRE1) is not empty.
+
+# Directory syntax:
+#
+# begin absolute path
+ABS=^\
+# begin relative path
+REL=
+# up-directory
+U=..
+# path separator
+S=^\
+# this is magic... should only be used for preceding a program invocation
+C=.^\
+
+srcdir = .
+SRCTOP = $(srcdir)\$(BUILDTOP)
+
+!if defined(KRB5_USE_DNS) || defined(KRB5_USE_DNS_KDC) || defined(KRB5_USE_DNS_REALMS)
+!if defined(KRB5_NO_WSHELPER)
+DNSMSG=resolver
+!else
+DNSMSG=wshelper
+DNSFLAGS=-DWSHELPER=1
+!endif
+!if !defined(DNS_INC)
+!message Must define DNS_INC to point to $(DNSMSG) includes dir!
+!error
+!endif
+!if !defined(DNS_LIB)
+!message Must define DNS_LIB to point to $(DNSMSG) library!
+!error
+!endif
+DNSLIBS=$(DNS_LIB)
+DNSFLAGS=-I$(DNS_INC) $(DNSFLAGS) -DKRB5_DNS_LOOKUP=1
+!if defined(KRB5_USE_DNS_KDC)
+DNSFLAGS=$(DNSFLAGS) -DKRB5_DNS_LOOKUP_KDC=1
+!endif
+!if defined(KRB5_USE_DNS_REALMS)
+DNSFLAGS=$(DNSFLAGS) -DKRB5_DNS_LOOKUP_REALM=1
+!endif
+!else
+DNSLIBS=
+DNSFLAGS=
+!endif
+
+!if ("$(CPU)" == "i386")
+TIME_T_FLAGS=-D_USE_32BIT_TIME_T
+!endif
+
+!if defined(KRB5_KFW_COMPILE)
+KFWFLAGS=-DUSE_LEASH=1
+!endif
+
+#
+# The name of the C compiler for the target
+#
+CC=cl
+
+PDB_OPTS=-Fd$(OUTPRE)\ -FD
+CPPFLAGS=-I$(SRCTOP)\include -I$(SRCTOP)\include\krb5 $(DNSFLAGS) -DKRB5_PRIVATE=1 -DWIN32_LEAN_AND_MEAN -DKRB5_DEPRECATED=1 -D_CRT_SECURE_NO_DEPRECATE $(KFWFLAGS) $(TIME_T_FLAGS)
+CCOPTS=-nologo /W3 $(PDB_OPTS) $(DLL_FILE_DEF)
+LOPTS=-nologo -incremental:no
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+CCLINKOPTION=/link bufferoverflowu.lib
+SCLIB=bufferoverflowu.lib
+DEBUGOPT=/Zi
+!else
+CCLINKOPTION=
+SCLIB=
+DEBUGOPT=/ZI
+!endif
+
+#if the compiler is vstudio 8, generate manifest
+!if exists("$(VCINSTALLDIR)\..\..\MICROSOFT VISUAL STUDIO 8")
+CCLINKOPTION = $(CCLINKOPTION) /MANIFEST
+_VC_MANIFEST_EMBED_EXE = if exist $*.exe.manifest mt.exe -manifest $*.exe.manifest -outputresource:$*.exe;1
+_VC_MANIFEST_EMBED_DLL = if exist $*.dll.manifest mt.exe -manifest $*.dll.manifest -outputresource:$*.dll;2
+!endif 
+
+# /ZI gives better debug info in each object file (MSVC 6.0 or higher).
+# /Zi gives debug info in each object file.
+# /Gs Avoid stack probes (they don't seem to work anyway)
+# /Os optimize for space.  FIXME:  Do not use /Ox; it miscompiles the DES lib!
+# /Od disable optimization (for debugging)
+# /MD (Win32) thread safe, ML would be single threaded, don't build with ML
+
+#
+# CCOPTS  was for DLL compiles
+# CCOPTS2 was for non-DLL compiles (EXEs, for example)
+#
+!ifdef NODEBUG
+!ifdef DEBUG_SYMBOL
+CCOPTS=$(DEBUGOPT) $(CCOPTS)
+LOPTS=$(LOPTS) -debug
+!endif
+CCOPTS=/Os /MD $(CCOPTS)
+LOPTS=$(LOPTS)
+!else
+CCOPTS=/Od $(DEBUGOPT) /MDd $(CCOPTS)
+LOPTS=$(LOPTS) -debug
+!endif
+
+# XXX - NOTE: We should probably use DllMainCRTStartup
+DLL_LINKOPTS=$(LOPTS) -dll -entry:DllMain
+EXE_LINKOPTS=$(LOPTS)
+
+RM=$(BUILDTOP)\config\rm.bat
+LIBECHO=$(BUILDTOP)\util\windows\$(OUTPRE)libecho
+CP=copy/b nul:+
+MV=ren
+LN=copy
+LIBCMD=lib
+AWK=rem
+RC = rc
+CVTRES = cvtres
+
+WCONFIG_EXE=$(BUILDTOP)\$(OUTPRE)wconfig.exe
+WCONFIG=$(WCONFIG_EXE:.exe=) $(WCONFIG_FLAGS)
+
+CLIB=$(BUILDTOP)\lib\$(OUTPRE)comerr32.lib
+PLIB=$(BUILDTOP)\lib\$(OUTPRE)xpprof32.lib
+KLIB=$(BUILDTOP)\lib\$(OUTPRE)krb5_32.lib
+K4LIB=$(BUILDTOP)\lib\$(OUTPRE)krb4_32.lib
+SLIB=$(BUILDTOP)\lib\$(OUTPRE)k5sprt32.lib
+GLIB=$(BUILDTOP)\lib\$(OUTPRE)gssapi32.lib
+WLIB=
+
+!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+CLIB=$(BUILDTOP)\lib\$(OUTPRE)comerr64.lib
+PLIB=$(BUILDTOP)\lib\$(OUTPRE)xpprof64.lib
+KLIB=$(BUILDTOP)\lib\$(OUTPRE)krb5_64.lib
+K4LIB=$(BUILDTOP)\lib\$(OUTPRE)krb4_64.lib
+SLIB=$(BUILDTOP)\lib\$(OUTPRE)k5sprt64.lib
+GLIB=$(BUILDTOP)\lib\$(OUTPRE)gssapi64.lib
+WLIB=
+
+!endif
+
+KRB4_INCLUDES=-I$(BUILDTOP)/include/kerberosIV
+
+COM_ERR_DEPS	= $(BUILDTOP)/include/com_err.h
+
+ARADD=rem
+RANLIB=rem
+ARCHIVE=rem
+
+LIBEXT=lib
+OBJEXT=obj
+EXEEXT=.exe
+
+MFLAGS=$(MAKEFLAGS)
+!ifdef MIGNORE
+MAKE=-$(MAKE)
+!endif
+
+CFLAGS = $(CCOPTS)
+ALL_CFLAGS = $(DEFS) $(DEFINES) $(LOCALINCLUDES) $(CPPFLAGS) $(CFLAGS)
+
+C_RULE_STUFF=$(CC) $(ALL_CFLAGS) -Fo$(OUTPRE)\ -c
+C_RULE_PRINT=$(C_RULE_STUFF)
+C_RULE=$(C_RULE_STUFF) $<
+
+{}.rc{$(OUTPRE)}.res:
+	$(RC) $(RCFLAGS) -fo $@ -r $<
+
+{}.c{$(OUTPRE)}.obj:
+	@if "%DO_C_RULE_PRINT%"=="1" echo %C_RULE_PRINT% ...
+	@set DO_C_RULE_PRINT=
+	@$(C_RULE)
+
+{}.cxx{$(OUTPRE)}.obj:
+	@if "%DO_C_RULE_PRINT%"=="1" echo %C_RULE_PRINT% ...
+	@set DO_C_RULE_PRINT=
+	@$(C_RULE)
+
+{}.cpp{$(OUTPRE)}.obj:
+	@if "%DO_C_RULE_PRINT%"=="1" echo %C_RULE_PRINT% ...
+	@set DO_C_RULE_PRINT=
+	@$(C_RULE)
+
+#
+# End of Win32 pre-config lines (config/win-pre.in)
+#
+
diff --git a/krb5-1-6/src/config/winexclude.sed b/krb5-1-6/src/config/winexclude.sed
new file mode 100644
index 000000000..fd76486ac
--- /dev/null
+++ b/krb5-1-6/src/config/winexclude.sed
@@ -0,0 +1,20 @@
+/krb5\.saber/d
+/autoconf.h$/d
+/t_mddriver$/d
+/test_parse$/d
+/test_profile$/d
+/\.orig$/d
+/\.rej/d
+/\.ico$/d
+/\.doc$/d
+/\.hlp$/d
+/\.hpj$/d
+/\.o$/d
+/\.a$/d
+/\.zip$/d
+/\.tar$/d
+/\.lib$/d
+/\.dll$/d
+/~$/d
+/winfile.list$/d
+/macfile.list$/d
diff --git a/krb5-1-6/src/configure.in b/krb5-1-6/src/configure.in
new file mode 100644
index 000000000..589781a97
--- /dev/null
+++ b/krb5-1-6/src/configure.in
@@ -0,0 +1,979 @@
+K5_AC_INIT([aclocal.m4])
+dnl
+dnl autoconf 2.49 defaults to a /dev/null cache file, which is what we
+dnl do not want for performance reasons. 
+if test "x$cache_file" = "x/dev/null"; then
+  cache_file=./config.cache
+  AC_CACHE_LOAD
+fi
+dnl
+CONFIG_RULES
+KRB5_VERSION=K5_VERSION
+AC_SUBST(KRB5_VERSION)
+dnl
+dnl
+AC_REQUIRE_CPP
+dnl
+dnl The following lines are so that configure --help gives some global 
+dnl configuration options.
+dnl
+KRB5_LIB_AUX
+AC_KRB5_TCL
+AC_ARG_ENABLE([athena],
+[  --enable-athena         build with MIT Project Athena configuration],,)
+dnl
+if test -z "$KRB4_LIB"; then
+kadminv4=""
+krb524=""
+libkrb4=""
+KRB4=""
+else
+kadminv4=kadmin.v4
+krb524=krb524
+libkrb4=lib/krb4
+KRB4=krb4
+fi
+AC_SUBST(KRB4)
+AC_SUBST(krb524)
+dnl
+dnl Begin autoconf tests for the Makefiles generated out of the top-level
+dnl configure.in...
+dnl
+AC_CHECK_FUNCS(memmove)
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+KRB5_BUILD_PROGRAM
+dnl for slave
+AC_TYPE_MODE_T
+AC_PROG_INSTALL
+KRB5_AC_NEED_DAEMON
+KRB5_GETSOCKNAME_ARGS
+KRB5_GETPEERNAME_ARGS
+LIBUTIL=
+AC_CHECK_LIB(util,main,[AC_DEFINE(HAVE_LIBUTIL,1,[Define if the util library is available])
+LIBUTIL=-lutil
+])
+AC_SUBST(LIBUTIL)
+dnl for kdc
+AC_CHECK_HEADERS(syslog.h stdarg.h sys/select.h sys/sockio.h ifaddrs.h unistd.h)
+AC_CHECK_FUNCS(openlog syslog closelog strftime vsprintf vasprintf vsnprintf)
+KRB5_NEED_PROTO([#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+/* Solaris 8 declares swab in stdlib.h.  */
+#include <stdlib.h>
+],swab,1)
+dnl
+AC_PROG_AWK
+KRB5_AC_INET6
+KRB5_SOCKADDR_SA_LEN
+CHECK_SIGNALS
+dnl
+dnl --with-vague-errors disables useful error messages.
+dnl
+AC_ARG_WITH([vague-errors],
+AC_HELP_STRING([--with-vague-errors],[Do not @<:@do@:>@ send helpful errors to client]), , withval=no)dnl
+if test "$withval" = yes; then
+	AC_MSG_RESULT(Supplying vague error messages to KDC clients)
+	AC_DEFINE(KRBCONF_VAGUE_ERRORS,1,[Define if the KDC should return only vague error codes to clients])
+fi
+dnl
+dnl --with-kdc-kdb-update makes the KDC update the database with last request
+dnl information and failure information.
+dnl
+AC_ARG_WITH([kdc-kdb-update],
+AC_HELP_STRING([--with-kdc-kdb-update],[Update the database @<:@don't update@:>@]), , withval=no)dnl
+if test "$withval" = yes; then
+	AC_MSG_RESULT(Updating KDC database with each request)
+	AC_DEFINE(KRBCONF_KDC_MODIFIES_KDB,1,[Define if KDC should update database with each request])
+fi
+dnl
+dnl Needed for hw-preauth replay detection on KDC.
+dnl
+dnl USE_RCACHE enables the replay cache
+dnl NOCACHE disables the lookaside cache
+dnl
+dnl The lookaside cache is checked first; if *exactly* the same message
+dnl comes in twice, e.g., because the (legitimate) client resent it,
+dnl the previous response will be resent.  Otherwise, the replay cache
+dnl is used to check for attempts to fake out the KDC.  Some hardware
+dnl preauth methods are weak enough that we *really* want to have this
+dnl checking turned on.
+dnl
+AC_ARG_ENABLE([kdc-replay-cache],
+AC_HELP_STRING([--enable-kdc-replay-cache],[check for replayed/retransmitted KDC requests (recommended when hardware preauthentication is in use) @<:@disabled@:>@]), , enableval=yes)dnl
+if test "$enableval" = yes ; then
+	AC_DEFINE(USE_RCACHE,1,[Define if the KDC should use a replay cache])
+else
+	AC_DEFINE(NOCACHE,1,[Define if the KDC should use no replay cache])
+fi
+AC_ARG_ENABLE([fakeka],
+AC_HELP_STRING([--enable-fakeka],[build the Fake KA server (emulates an AFS kaserver) @<:@default: don't build@:>@]), , enableval=no)dnl
+if test "$enableval" = yes; then
+	FAKEKA=fakeka
+else
+	FAKEKA=
+fi
+AC_SUBST(FAKEKA)
+KRB5_RUN_FLAGS
+dnl
+dnl for krb524
+AC_TYPE_SIGNAL
+dnl
+dnl from old include/configure.in
+AH_TEMPLATE([HAVE_STRUCT_SOCKADDR_STORAGE], 
+[Define if "struct sockaddr_storage" is available.])
+dnl
+AC_CONFIG_HEADER(include/autoconf.h)
+AC_PROG_INSTALL
+AC_PROG_AWK
+AC_PROG_LEX
+AC_C_CONST
+AC_HEADER_DIRENT
+AC_CHECK_FUNCS(strdup setvbuf inet_ntoa inet_aton seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strftime strptime geteuid setenv unsetenv getenv gethostbyname2 getifaddrs gmtime_r localtime_r pthread_mutex_lock sched_yield bswap16 bswap64 mkstemp getusershell lstat access ftime getcwd srand48 srand srandom stat strchr strerror strerror_r strstr timezone umask waitpid sem_init sem_trywait daemon)
+AC_HEADER_STDARG
+DECLARE_SYS_ERRLIST
+AC_CHECK_HEADERS(unistd.h paths.h regex.h regexpr.h fcntl.h memory.h ifaddrs.h sys/filio.h sched.h byteswap.h machine/endian.h machine/byte_order.h sys/bswap.h endian.h pwd.h arpa/inet.h alloca.h dlfcn.h limits.h pthread.h semaphore.h krb_db.h kdc.h)
+AC_CHECK_HEADER(regexp.h, [], [],
+[#define INIT char *sp = instring;
+#define GETC() (*sp++)
+#define PEEKC() (*sp)
+#define UNGETC(c) (--sp)
+#define RETURN(c) return(c)
+#define ERROR(c)
+])
+AC_CHECK_MEMBERS([struct sockaddr_in.sin_len, struct sockaddr.sa_len], , ,
+  [#include <sys/types.h>
+#include <netinet/in.h>])
+AC_CHECK_MEMBERS([struct stat.st_mtimensec,struct stat.st_mtimespec.tv_nsec,struct stat.st_mtim.tv_nsec],,,[#include <sys/types.h>
+#include <sys/stat.h>])
+KRB5_AC_REGEX_FUNCS
+AC_TYPE_OFF_T
+dnl
+dnl Fancy caching of perror result...
+AC_MSG_CHECKING(for perror declaration)
+AC_CACHE_VAL(krb5_cv_decl_perror,
+[AC_EGREP_HEADER(perror, errno.h, 
+  krb5_cv_decl_perror=yes, krb5_cv_decl_perror=no)])dnl
+AC_MSG_RESULT($krb5_cv_decl_perror)
+if test $krb5_cv_decl_perror = yes; then
+	AC_DEFINE(HDR_HAS_PERROR,1,[Define if errno.h declares perror])
+fi
+dnl
+KRB5_NEED_PROTO([#include <time.h>],strptime)
+CHECK_WAIT_TYPE
+CHECK_SIGPROCMASK
+AC_TYPE_GETGROUPS
+CHECK_SETJMP
+dnl
+dnl *rpcent return types needed for lib/rpc
+dnl
+AC_MSG_CHECKING([return type of setrpcent])
+AC_CACHE_VAL(k5_cv_type_setrpcent,
+[AC_TRY_COMPILE([#include <netdb.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+extern void setrpcent();],
+[int i;], k5_cv_type_setrpcent=void, k5_cv_type_setrpcent=int)])dnl
+AC_MSG_RESULT($k5_cv_type_setrpcent)
+AC_DEFINE_UNQUOTED(SETRPCENT_TYPE, $k5_cv_type_setrpcent, [Define as return type of setrpcent])
+dnl
+AC_MSG_CHECKING([return type of endrpcent])
+AC_CACHE_VAL(k5_cv_type_endrpcent,
+[AC_TRY_COMPILE([#include <netdb.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+extern void endrpcent();],
+[int i;], k5_cv_type_endrpcent=void, k5_cv_type_endrpcent=int)])dnl
+AC_MSG_RESULT($k5_cv_type_endrpcent)
+AC_DEFINE_UNQUOTED(ENDRPCENT_TYPE, $k5_cv_type_endrpcent, [Define as return type of endrpcent])
+dnl
+dnl
+dnl bswap_16 is a macro in byteswap.h under GNU libc
+AC_MSG_CHECKING(for bswap_16)
+AC_CACHE_VAL(krb5_cv_bswap_16,[
+AC_TRY_LINK([#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif],[bswap_16(37);],krb5_cv_bswap_16=yes,krb5_cv_bswap_16=no)])
+AC_MSG_RESULT($krb5_cv_bswap_16)
+if test "$krb5_cv_bswap_16" = yes; then
+  AC_DEFINE(HAVE_BSWAP_16,1,[Define to 1 if bswap_16 is available via byteswap.h])
+fi
+AC_MSG_CHECKING(for bswap_64)
+AC_CACHE_VAL(krb5_cv_bswap_64,[
+AC_TRY_LINK([#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif],[bswap_64(37);],krb5_cv_bswap_64=yes,krb5_cv_bswap_64=no)])
+AC_MSG_RESULT($krb5_cv_bswap_64)
+if test "$krb5_cv_bswap_64" = yes; then
+  AC_DEFINE(HAVE_BSWAP_64,1,[Define to 1 if bswap_64 is available via byteswap.h])
+fi
+dnl
+dnl Needed for ksu and some appl stuff.
+dnl
+case $krb5_cv_host in
+alpha*-dec-osf*)
+	AC_CHECK_LIB(security,setluid,
+		AC_DEFINE(HAVE_SETLUID,1,[Define if setluid provided in OSF/1 security library])
+		KSU_LIBS="-lsecurity"
+	)
+	;;
+esac
+AC_SUBST(KSU_LIBS)
+dnl
+if test $ac_cv_func_setenv = no || test $ac_cv_func_unsetenv = no \
+  || test $ac_cv_func_getenv = no; then
+  SETENVOBJ=setenv.o
+else
+  SETENVOBJ=
+fi
+AC_SUBST(SETENVOBJ)
+dnl
+dnl Check what the return types for gethostbyname_r and getservbyname_r are.
+dnl
+AC_CHECK_FUNC(gethostbyname_r,[
+ac_cv_func_gethostbyname_r=yes
+if test "$ac_cv_func_gethostbyname_r" = yes; then
+  AC_MSG_CHECKING([if gethostbyname_r returns an int])
+  AC_CACHE_VAL(krb5_cv_gethostbyname_r_returns_int,
+  [AC_TRY_COMPILE([#include <netdb.h>
+  extern int gethostbyname_r ();], [1;],
+  krb5_cv_gethostbyname_r_returns_int=yes,
+  krb5_cv_gethostbyname_r_returns_int=no)])
+  AC_MSG_RESULT($krb5_cv_gethostbyname_r_returns_int)
+
+  AC_MSG_CHECKING([if gethostbyname_r returns a pointer])
+  AC_CACHE_VAL(krb5_cv_gethostbyname_r_returns_ptr,
+  [AC_TRY_COMPILE([#include <netdb.h>
+  extern struct hostent *gethostbyname_r ();], [1;],
+  krb5_cv_gethostbyname_r_returns_ptr=yes,
+  krb5_cv_gethostbyname_r_returns_ptr=no)])
+  AC_MSG_RESULT($krb5_cv_gethostbyname_r_returns_ptr)
+
+  if test "$krb5_cv_gethostbyname_r_returns_int" = "$krb5_cv_gethostbyname_r_returns_ptr"; then
+    AC_MSG_WARN(cannot determine return type of gethostbyname_r -- disabling)
+    ac_cv_func_gethostbyname_r=no
+  fi
+  if test "$krb5_cv_gethostbyname_r_returns_int" = yes; then
+    AC_DEFINE(GETHOSTBYNAME_R_RETURNS_INT, 1, [Define if gethostbyname_r returns int rather than struct hostent * ])
+  fi
+fi
+if test "$ac_cv_func_gethostbyname_r" = yes; then
+  AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, [Define if gethostbyname_r exists and its return type is known])
+  AC_CHECK_FUNC(gethostbyaddr_r)
+fi
+])
+dnl
+
+AC_CHECK_FUNC(getpwnam_r,ac_cv_func_getpwnam_r=yes,ac_cv_func_getpwnam_r=no)
+AC_CHECK_FUNC(getpwuid_r,ac_cv_func_getpwuid_r=yes,ac_cv_func_getpwuid_r=no)
+if test "$ac_cv_func_getpwnam_r" = yes; then
+  AC_MSG_CHECKING([return type of getpwnam_r])
+  AC_CACHE_VAL(krb5_cv_getpwnam_r_return_type,
+  [AC_TRY_COMPILE([#include <pwd.h>
+   extern int getpwnam_r();], [1;],
+   getpwnam_r_returns_int=yes,getpwnam_r_returns_int=no)
+   AC_TRY_COMPILE([#include <pwd.h>
+   extern struct passwd *getpwnam_r();], [1;],
+   getpwnam_r_returns_ptr=yes,getpwnam_r_returns_ptr=no)
+   case "$getpwnam_r_returns_int/$getpwnam_r_returns_ptr" in
+     yes/no) krb5_cv_getpwnam_r_return_type=int ;;
+     no/yes) krb5_cv_getpwnam_r_return_type=ptr ;;
+     *) krb5_cv_getpwnam_r_return_type=unknown ;;
+   esac])
+  AC_MSG_RESULT($krb5_cv_getpwnam_r_return_type)
+  if test $krb5_cv_getpwnam_r_return_type = int; then
+    AC_DEFINE(GETPWNAM_R_RETURNS_INT, 1, [Define if getpwnam_r returns an int])
+  elif test $krb5_cv_getpwnam_r_return_type = unknown; then
+    AC_MSG_WARN([Cannot determine getpwnam_r return type, disabling getpwnam_r])
+    ac_cv_func_getpwnam_r=no
+  fi
+fi
+if test "$ac_cv_func_getpwnam_r" = yes; then
+  AC_MSG_CHECKING([number of arguments to getpwnam_r])
+  AC_CACHE_VAL(krb5_cv_getpwnam_r_args,
+  [AC_TRY_COMPILE([#include <pwd.h>
+   struct passwd pwx; char buf[1024];],
+   [getpwnam_r("", &pwx, buf, sizeof(buf));], args4=yes, args4=no)
+   AC_TRY_COMPILE([#include <pwd.h>
+   struct passwd pwx, *p; char buf[1024];],
+   [getpwnam_r("", &pwx, buf, sizeof(buf), &p);], args5=yes, args5=no)
+   case $args4/$args5 in
+     yes/no) krb5_cv_getpwnam_r_args=4 ;;
+     no/yes) krb5_cv_getpwnam_r_args=5 ;;
+     *) krb5_cv_getpwnam_r_args=unknown ;;
+   esac])
+  AC_MSG_RESULT($krb5_cv_getpwnam_r_args)
+  if test "$krb5_cv_getpwnam_r_args" = unknown; then
+    AC_MSG_WARN([Cannot determine number of arguments to getpwnam_r, disabling its use.])
+    ac_cv_func_getpwnam_r=no
+  else
+    AC_DEFINE(HAVE_GETPWNAM_R,1,[Define if getpwnam_r is available and useful.])
+    if test "$krb5_cv_getpwnam_r_args" = 4; then
+      AC_DEFINE(GETPWNAM_R_4_ARGS,1,[Define if getpwnam_r exists but takes only 4 arguments (e.g., POSIX draft 6 implementations like some Solaris releases).])
+    fi
+  fi
+fi
+
+if test "$ac_cv_func_getpwnam_r" = no && test "$ac_cv_func_getpwuid_r" = yes; then
+  # Actually, we could do this check, and the corresponding checks
+  # for return type and number of arguments, but I doubt we'll run
+  # into a system where we'd get to use getpwuid_r but not getpwnam_r.
+  AC_MSG_NOTICE([getpwnam_r not useful, so disabling getpwuid_r too])
+  ac_cv_func_getpwuid_r=no
+fi
+if test "$ac_cv_func_getpwuid_r" = yes; then
+  AC_DEFINE(HAVE_GETPWUID_R,1,[Define if getpwuid_r is available and useful.])
+  # Hack: Assume getpwuid_r is the shorter form if getpwnam_r is.
+  if test "$krb5_cv_getpwnam_r_args" = 4; then
+    AC_DEFINE(GETPWUID_R_4_ARGS,1,[Define if getpwuid_r exists but takes only 4 arguments (e.g., POSIX draft 6 implementations like some Solaris releases).])
+  fi
+fi
+
+if test "$ac_cv_func_gmtime_r" = yes; then
+  AC_MSG_CHECKING([whether gmtime_r returns int])
+  AC_CACHE_VAL(krb5_cv_gmtime_r_returns_int,
+  [AC_TRY_COMPILE([#include <time.h>
+   extern int gmtime_r ();], [1;], return_int=yes, return_int=no)
+   AC_TRY_COMPILE([#include <time.h>
+   extern struct tm *gmtime_r ();], [1;], return_ptr=yes, return_ptr=no)
+   case $return_int/$return_ptr in
+     yes/no) krb5_cv_gmtime_r_returns_int=yes ;;
+     no/yes) krb5_cv_gmtime_r_returns_int=no ;;
+     *)      # Can't figure it out, punt the function.
+             ac_cv_func_gmtime_r=no ;;
+   esac])
+  if test "$ac_cv_func_gmtime_r" = no; then
+    AC_MSG_RESULT(unknown -- ignoring gmtime_r)
+  else
+    AC_MSG_RESULT($krb5_cv_gmtime_r_returns_int)
+    if test "$krb5_cv_gmtime_r_returns_int" = yes; then
+      AC_DEFINE(GMTIME_R_RETURNS_INT,1,[Define if gmtime_r returns int instead of struct tm pointer, as on old HP-UX systems.])
+    fi
+  fi
+fi
+
+AC_CHECK_FUNC(getservbyname_r,[
+ac_cv_func_getservbyname_r=yes
+if test "$ac_cv_func_getservbyname_r" = yes; then
+  AC_MSG_CHECKING([if getservbyname_r returns an int])
+  AC_CACHE_VAL(krb5_cv_getservbyname_r_returns_int,
+  [AC_TRY_COMPILE([#include <netdb.h>
+  extern int getservbyname_r ();], [1;],
+  krb5_cv_getservbyname_r_returns_int=yes,
+  krb5_cv_getservbyname_r_returns_int=no)])
+  AC_MSG_RESULT($krb5_cv_getservbyname_r_returns_int)
+
+  AC_MSG_CHECKING([if getservbyname_r returns a pointer])
+  AC_CACHE_VAL(krb5_cv_getservbyname_r_returns_ptr,
+  [AC_TRY_COMPILE([#include <netdb.h>
+  extern struct servent *getservbyname_r ();], [1;],
+  krb5_cv_getservbyname_r_returns_ptr=yes,
+  krb5_cv_getservbyname_r_returns_ptr=no)])
+  AC_MSG_RESULT($krb5_cv_getservbyname_r_returns_ptr)
+
+  if test "$krb5_cv_getservbyname_r_returns_int" = "$krb5_cv_getservbyname_r_returns_ptr"; then
+    AC_MSG_WARN(cannot determine return type of getservbyname_r -- disabling)
+    ac_cv_func_getservbyname_r=no
+  fi
+  if test "$krb5_cv_getservbyname_r_returns_int" = yes; then
+    AC_DEFINE(GETSERVBYNAME_R_RETURNS_INT, 1, [Define if getservbyname_r returns int rather than struct servent * ])
+  fi
+fi
+if test "$ac_cv_func_getservbyname_r" = yes; then
+  AC_DEFINE(HAVE_GETSERVBYNAME_R, 1, [Define if getservbyname_r exists and its return type is known])
+  AC_CHECK_FUNC(getservbyport_r)
+fi
+])
+dnl
+HAVE_YYLINENO
+CHECK_DIRENT
+AC_TYPE_UID_T
+AC_TYPE_MODE_T
+dnl
+AC_CHECK_HEADER(termios.h,dnl
+[AC_CHECK_FUNC([tcsetattr],dnl
+  AC_DEFINE(POSIX_TERMIOS,1,[Define if termios.h exists and tcsetattr exists]))])
+dnl
+KRB5_SIGTYPE
+AC_CHECK_HEADERS(stdlib.h string.h stddef.h sys/types.h sys/file.h sys/param.h sys/stat.h sys/time.h netinet/in.h sys/uio.h sys/filio.h sys/select.h time.h paths.h)
+AC_HEADER_STDARG
+KRB5_AC_INET6
+dnl
+dnl If compiling with IPv6 support, test if in6addr_any functions.
+dnl Irix 6.5.16 defines it, but lacks support in the C library.
+if test $krb5_cv_inet6 = yes || test "$krb5_cv_inet6_with_dinet6" = yes ; then
+AC_CACHE_CHECK([for in6addr_any definition in library], 
+  krb5_cv_var_in6addr_any,
+[AC_TRY_LINK([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+],[
+  struct sockaddr_in6 in;
+  in.sin6_addr = in6addr_any;
+  printf("%x", &in);
+],krb5_cv_var_in6addr_any=yes, krb5_cv_var_in6addr_any=no)])
+  if test $krb5_cv_var_in6addr_any = no; then
+    AC_DEFINE(NEED_INSIXADDR_ANY,1,[Define if in6addr_any is not defined in libc])
+  fi
+fi
+
+dnl
+dnl
+dnl check for ANSI stdio, esp "b" option to fopen().  This (unfortunately)
+dnl requires a run check...
+dnl
+AC_MSG_CHECKING([for ANSI stdio])
+AC_CACHE_VAL(krb5_cv_has_ansi_stdio,
+[AC_TRY_RUN(
+[#include <stdio.h>
+int main()
+{
+  FILE *conftest;
+  if ((conftest = fopen("conftest.dat", "w")) == NULL) exit(1);
+  if (fclose(conftest)) exit(1);
+  if ((conftest = fopen("conftest.dat", "rb+")) == NULL) exit(1);
+  if (fputs("testing ANSI for stdio\n", conftest) == EOF) exit(1);
+  exit(0);
+}],
+krb5_cv_has_ansi_stdio=yes, krb5_cv_has_ansi_stdio=no,
+krb5_cv_has_ansi_stdio=yes)])dnl assume ANSI in cross environment
+AC_MSG_RESULT($krb5_cv_has_ansi_stdio)
+if test $krb5_cv_has_ansi_stdio = yes; then
+AC_DEFINE(ANSI_STDIO,1,[Define if ANSI stdio is present (in particular "b" option to fopen)])
+fi
+dnl
+dnl then from osconf.h, we have
+dnl
+AC_HEADER_TIME
+AC_CHECK_TYPE(time_t, long)
+dnl
+dnl Determine where to put the replay cache.
+dnl
+AC_MSG_CHECKING([for replay cache directory])
+AC_CACHE_VAL(krb5_cv_sys_rcdir,
+[
+for t_dir in /var/tmp /usr/tmp /var/usr/tmp /tmp ; do
+	test -d $t_dir || continue
+	krb5_cv_sys_rcdir=$t_dir
+	break
+done])dnl
+AC_MSG_RESULT($krb5_cv_sys_rcdir)
+KRB5_RCTMPDIR=$krb5_cv_sys_rcdir
+AC_SUBST(KRB5_RCTMPDIR)
+dnl
+dnl
+AC_MSG_CHECKING(for socklen_t)
+AC_CACHE_VAL(krb5_cv_has_type_socklen_t,
+[AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <sys/socket.h>
+],[sizeof (socklen_t);],
+krb5_cv_has_type_socklen_t=yes,krb5_cv_has_type_socklen_t=no)])
+AC_MSG_RESULT($krb5_cv_has_type_socklen_t)
+if test $krb5_cv_has_type_socklen_t = yes; then
+    AC_DEFINE(HAVE_SOCKLEN_T,1,[Define if there is a socklen_t type. If not, probably use size_t])
+fi
+dnl
+AC_MSG_CHECKING(for struct lifconf)
+AC_CACHE_VAL(krb5_cv_has_struct_lifconf,
+[AC_TRY_COMPILE(
+[#include <sys/socket.h>
+#include <net/if.h>
+],[sizeof (struct lifconf);],
+krb5_cv_has_struct_lifconf=yes,krb5_cv_has_struct_lifconf=no)])
+AC_MSG_RESULT($krb5_cv_has_struct_lifconf)
+if test $krb5_cv_has_struct_lifconf = yes; then
+    AC_DEFINE(HAVE_STRUCT_LIFCONF,1,[Define if there is a struct lifconf.])
+fi
+dnl HP-UX 11 uses stuct if_laddrconf
+AC_MSG_CHECKING(for struct if_laddrconf)
+AC_CACHE_VAL(krb5_cv_has_struct_if_laddrconf,
+[AC_TRY_COMPILE(
+[#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if6.h>
+],[sizeof (struct if_laddrconf);],
+krb5_cv_has_struct_if_laddrconf=yes,krb5_cv_has_struct_if_laddrconf=no)])
+AC_MSG_RESULT($krb5_cv_has_struct_if_laddrconf)
+if test $krb5_cv_has_struct_if_laddrconf = yes; then
+    AC_DEFINE(HAVE_STRUCT_IF_LADDRCONF,1,[Define if there is a struct if_laddrconf.])
+fi
+dnl
+dnl
+AC_MSG_CHECKING([for h_errno in netdb.h])
+AC_CACHE_VAL(krb5_cv_header_netdb_h_h_errno,
+[AC_TRY_COMPILE(
+	[#include <netdb.h>],
+	[int x = h_errno;], krb5_cv_header_netdb_h_h_errno=yes,
+	krb5_cv_header_netdb_h_h_errno=no)])
+AC_MSG_RESULT($krb5_cv_header_netdb_h_h_errno)
+if test $krb5_cv_header_netdb_h_h_errno = yes; then
+    AC_DEFINE([HAVE_NETDB_H_H_ERRNO], 1,
+	[Define if netdb.h declares h_errno])
+fi
+dnl
+dnl
+AC_ARG_ENABLE([athena],
+[  --enable-athena         build with MIT Project Athena configuration],
+AC_DEFINE(KRB5_ATHENA_COMPAT,1,[Define if MIT Project Athena default configuration should be used]),)
+
+if test "$KRB4_LIB" = ''; then
+	AC_MSG_NOTICE(No Kerberos 4 compatibility)
+	maybe_kerberosIV=
+else
+	AC_MSG_NOTICE(Kerberos 4 compatibility enabled)
+	maybe_kerberosIV=kerberosIV
+	AC_DEFINE(KRB5_KRB4_COMPAT,1,[Define if Kerberos V4 backwards compatibility should be supported])
+fi
+AC_SUBST(maybe_kerberosIV)
+dnl
+AC_C_INLINE
+AH_TOP([
+#ifndef KRB5_AUTOCONF_H
+#define KRB5_AUTOCONF_H
+])
+AH_BOTTOM([
+#if defined(__GNUC__) && !defined(inline)
+/* Silence gcc pedantic warnings about ANSI C.  */
+# define inline __inline__
+#endif
+#endif /* KRB5_AUTOCONF_H */
+])
+dnl
+dnl Not used yet, but let's find out what we've got on the platforms
+dnl we're working with....
+AC_CHECK_HEADERS(inttypes.h stdint.h)
+AC_CHECK_TYPES([uint32_t, int32_t, uint64_t, int64_t, uint_least32_t, uintptr_t, uintmax_t, long long], , , [
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+])
+dnl
+dnl stuff for util/profile
+dnl
+dnl AC_KRB5_TCL already done
+DO_TCL=
+test "$TCL_LIBS" != "" && DO_TCL=ok
+AC_SUBST(DO_TCL)
+dnl
+dnl Test for POSIX 2001 *printf support (X/Open System Interfaces extension
+dnl to ANSI/ISO C 1999 specification).  Specifically, positional
+dnl specifications; not checking for other features like %zx at present.
+AC_MSG_CHECKING(for POSIX printf positional specification support)
+AC_CACHE_VAL(ac_cv_printf_positional,[
+AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+const char expected[] = "200 100";
+int main () {
+    char buf[30];
+    sprintf(buf, "%2\$x %1\$d", 100, 512);
+    if (strcmp(expected, buf)) {
+	fprintf(stderr,"bad result: <%s> wanted: <%s>\n", buf, expected);
+	return 1;
+    }
+    return 0;
+}],
+  ac_cv_printf_positional=yes,
+  ac_cv_printf_positional=no,
+  AC_MSG_ERROR([Cannot test for printf positional argument support when cross compiling]))])
+dnl Nothing for autoconf.h for now.
+AC_MSG_RESULT($ac_cv_printf_positional)
+dnl
+dnl
+dnl for kadmin
+dnl
+AC_PROG_YACC
+ath_compat=
+AC_ARG_ENABLE([athena],
+[  --enable-athena         build with MIT Project Athena configuration],
+ath_compat=compat,)
+dnl The following are tests for the presence of programs required for
+dnl kadmin testing.
+AC_CHECK_PROG(have_RUNTEST,runtest,runtest)
+AC_CHECK_PROG(have_PERL,perl,perl)
+AC_KRB5_TCL	
+if test "$have_PERL" = perl -a "$have_RUNTEST" = runtest -a "$TCL_LIBS" != ""; then
+ 	DO_TEST=ok
+fi
+AC_SUBST(DO_TEST) 
+dnl
+DO_V4_TEST=
+if test "$have_PERL" = perl -a "$have_RUNTEST" = runtest -a "$TCL_LIBS" != "" -a "$ath_compat" != ""; then
+ 	DO_V4_TEST=ok
+fi
+AC_SUBST(DO_V4_TEST)
+dnl The following are substituted into kadmin/testing/scripts/env-setup.sh
+RBUILD=`pwd`
+AC_SUBST(RBUILD)
+case "$srcdir" in
+/*)	S_TOP=$srcdir ;;
+*)	S_TOP=`pwd`/$srcdir ;;
+esac
+AC_SUBST(S_TOP)
+AC_PATH_PROG(PERL_PATH,perl)
+AC_PATH_PROG(EXPECT,expect)
+dnl For kadmin/testing/util/Makefile.in
+if test "$TCL_LIBS" != "" ;  then
+	DO_ALL=tcl
+fi
+AC_SUBST(DO_ALL)
+KRB5_AC_PRIOCNTL_HACK
+K5_GEN_FILE(kadmin/testing/scripts/env-setup.sh:kadmin/testing/scripts/env-setup.shin)
+dnl for lib/kadm5
+AC_CHECK_PROG(RUNTEST,runtest,runtest)
+AC_CHECK_PROG(PERL,perl,perl)
+dnl
+dnl
+dnl for lib/krb4
+case $krb5_cv_host in
+     *-apple-darwin*)
+     KRB_ERR_TXT=
+     KRB_ERR=
+     KRB_ERR_C=krb_err.c
+     ;;
+     *)
+     KRB_ERR='$(OUTPRE)krb_err.$(OBJEXT)'
+     KRB_ERR_TXT=krb_err_txt.c
+     KRB_ERR_C=
+     ;;
+esac
+AC_SUBST([KRB_ERR_TXT])
+AC_SUBST([KRB_ERR])
+AC_SUBST([KRB_ERR_C])
+dnl
+dnl
+dnl lib/gssapi
+AC_CHECK_HEADER(stdint.h,[
+	include_stdint='awk '\''END{printf("%cinclude <stdint.h>\n", 35);}'\'' < /dev/null'],
+	include_stdint='echo "/* no stdint.h */"')
+AC_SUBST(include_stdint)
+AC_CHECK_HEADER(inttypes.h,[
+	include_inttypes='awk '\''END{printf("%cinclude <inttypes.h>\n", 35);}'\'' < /dev/null'],
+	include_inttypes='echo "/* no inttypes.h */"')
+AC_SUBST(include_inttypes)
+AC_CHECK_HEADER(xom.h,[
+	include_xom='awk '\''END{printf("%cinclude <xom.h>\n", 35);}'\'' < /dev/null'], [
+	include_xom='echo "/* no xom.h */"'])
+AC_SUBST(include_xom)
+dnl
+dnl
+dnl lib/rpc
+### Check where struct rpcent is declared.
+#
+# This is necessary to determine:
+# 1. If /usr/include/netdb.h declares struct rpcent
+# 2. If /usr/include/rpc/netdb.h declares struct rpcent
+#
+# We have our own rpc/netdb.h, and if /usr/include/netdb.h includes
+# rpc/netdb.h, then nastiness could happen.
+#
+# Logic: If /usr/include/netdb.h declares struct rpcent, then check
+# rpc/netdb.h.  If /usr/include/rpc/netdb.h declares struct rpcent,
+# then define STRUCT_RPCENT_IN_RPC_NETDB_H, otherwise do not.  If
+# neither netdb.h nor rpc/netdb.h declares struct rpcent, then define
+# STRUCT_RPCENT_IN_RPC_NETDB_H anyway.
+#
+AC_MSG_CHECKING([where struct rpcent is declared])
+AC_TRY_COMPILE([#include <netdb.h>],
+[struct rpcent e;
+char c = e.r_name[0];
+int i = e.r_number;],
+[AC_TRY_COMPILE([#include <rpc/netdb.h>],
+[struct rpcent e;
+char c = e.r_name[0];
+int i = e.r_number;],
+[AC_MSG_RESULT([rpc/netdb.h])
+rpcent_define='#define STRUCT_RPCENT_IN_RPC_NETDB_H'],
+[AC_MSG_RESULT([netdb.h])])],
+[AC_MSG_RESULT([nowhere])
+rpcent_define='#define STRUCT_RPCENT_IN_RPC_NETDB_H'])
+AC_SUBST(rpcent_define)
+
+AC_CHECK_HEADERS(sys/select.h sys/time.h unistd.h)
+if test $ac_cv_header_sys_select_h = yes; then
+  GSSRPC__SYS_SELECT_H='#include <sys/select.h>'
+else
+  GSSRPC__SYS_SELECT_H='/* #include <sys/select.h> */'
+fi
+AC_SUBST(GSSRPC__SYS_SELECT_H)
+if test $ac_cv_header_sys_time_h = yes; then
+  GSSRPC__SYS_TIME_H='#include <sys/time.h>'
+else
+  GSSRPC__SYS_TIME_H='/* #include <sys/time.h> */'
+fi
+AC_SUBST(GSSRPC__SYS_TIME_H)
+if test $ac_cv_header_unistd_h = yes; then
+  GSSRPC__UNISTD_H='#include <unistd.h>'
+else
+  GSSRPC__UNISTD_H='/* #include <unistd.h> */'
+fi
+AC_SUBST(GSSRPC__UNISTD_H)
+
+AC_CACHE_CHECK([for MAXHOSTNAMELEN in sys/param.h],
+  [krb5_cv_header_sys_param_h_maxhostnamelen],
+  [AC_TRY_COMPILE([#include <sys/param.h>],
+    [int i = MAXHOSTNAMELEN;],
+    [krb5_cv_header_sys_param_h_maxhostnamelen=yes],
+    [krb5_cv_header_sys_param_h_maxhostnamelen=no])])
+AC_CACHE_CHECK([for MAXHOSTNAMELEN in netdb.h],
+  [krb5_cv_header_netdb_h_maxhostnamelen],
+  [AC_TRY_COMPILE([#include <netdb.h>],
+    [int i = MAXHOSTNAMELEN;],
+    [krb5_cv_header_netdb_h_maxhostnamelen=yes],
+    [krb5_cv_header_netdb_h_maxhostnamelen=no])])
+
+GSSRPC__SYS_PARAM_H='/* #include <sys/param.h> */'
+GSSRPC__NETDB_H='/* #include <netdb.h> */'
+if test $krb5_cv_header_sys_param_h_maxhostnamelen = yes; then
+  GSSRPC__SYS_PARAM_H='#include <sys/param.h>'
+else
+  if test $krb5_cv_header_netdb_h_maxhostnamelen = yes; then
+    GSSRPC__NETDB_H='#include <netdb.h>'
+  else
+    AC_MSG_WARN([can't find MAXHOSTNAMELEN definition; faking it])
+  fi
+fi
+AC_SUBST(GSSRPC__SYS_PARAM_H)
+AC_SUBST(GSSRPC__NETDB_H)
+
+AC_CACHE_CHECK([for uint32_t in sys/types.h],
+  [krb5_cv_header_sys_types_h_uint32_t],
+  [AC_TRY_COMPILE([#include <sys/types.h>],
+      [uint32_t i = 0;],
+      [krb5_cv_header_sys_types_h_uint32_t=yes],
+      [krb5_cv_header_sys_types_h_uint32_t=no])])
+AC_CACHE_CHECK([for uint32_t in stdint.h],
+  [krb5_cv_header_stdint_h_uint32_t],
+  [AC_TRY_COMPILE([#include <stdint.h>],
+      [uint32_t i = 0;],
+      [krb5_cv_header_stdint_h_uint32_t=yes],
+      [krb5_cv_header_stdint_h_uint32_t=no])])
+AC_CACHE_CHECK([for uint32_t in inttypes.h],
+  [krb5_cv_header_inttypes_h_uint32_t],
+  [AC_TRY_COMPILE([#include <inttypes.h>],
+      [uint32_t i = 0;],
+      [krb5_cv_header_inttypes_h_uint32_t=yes],
+      [krb5_cv_header_inttypes_h_uint32_t=no])])
+GSSRPC__STDINT_H='/* #include <stdint.h> */'
+GSSRPC__INTTYPES_H='/* #include <inttypes.h> */'
+GSSRPC__FAKE_UINT32='/* #undef GSSRPC__FAKE_INT32 */'
+if test $krb5_cv_header_sys_types_h_uint32_t = yes; then
+  : # already included sys/types.h
+else
+  if test $krb5_cv_header_stdint_h_uint32_t = yes; then
+    GSSRPC__STDINT_H='#include <stdint.h>'
+  else
+    if test $krb5_cv_header_inttypes_h_uint32_t = yes; then
+      GSSRPC__INTTYPES_H='#include <inttypes.h>'
+    else
+      AC_MSG_WARN([can't find a fixed-width 32-bit type anywhere; faking it])
+      GSSRPC__FAKE_UINT32='#define GSSRPC__FAKE_UINT32 1'
+    fi
+  fi
+fi
+AC_SUBST(GSSRPC__STDINT_H)
+AC_SUBST(GSSRPC__INTTYPES_H)
+AC_SUBST(GSSRPC__FAKE_UINT32)
+
+AC_CACHE_CHECK([for BSD type aliases], [krb5_cv_type_bsdaliases],
+  [AC_TRY_COMPILE(
+    [#include <sys/types.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif],
+    [u_char c;
+u_int i;
+u_long l;], [krb5_cv_type_bsdaliases=yes], [krb5_cv_type_bsdaliases=no])])
+if test $krb5_cv_type_bsdaliases = yes; then
+  GSSRPC__BSD_TYPEALIASES='/* #undef GSSRPC__BSD_TYPEALIASES */'
+else
+  GSSRPC__BSD_TYPEALIASES='#define GSSRPC__BSD_TYPEALIASES 1'
+fi
+AC_SUBST(GSSRPC__BSD_TYPEALIASES)
+#
+# sockaddr length field checks
+#
+AC_CHECK_MEMBERS([struct sockaddr_in.sin_len], , ,
+  [#include <sys/types.h>
+@%:@include <netinet/in.h>])
+AC_CHECK_MEMBERS([struct sockaddr.sa_len], , ,
+  [#include <sys/types.h>
+@%:@include <sys/socket.h>])
+
+AC_MSG_CHECKING([return type of setrpcent])
+AC_CACHE_VAL(k5_cv_type_setrpcent,
+[AC_TRY_COMPILE([#include <netdb.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+extern void setrpcent();],
+[int i;], k5_cv_type_setrpcent=void, k5_cv_type_setrpcent=int)])dnl
+AC_MSG_RESULT($k5_cv_type_setrpcent)
+AC_DEFINE_UNQUOTED(SETRPCENT_TYPE, $k5_cv_type_setrpcent, [Define as return type of setrpcent])
+dnl
+AC_MSG_CHECKING([return type of endrpcent])
+AC_CACHE_VAL(k5_cv_type_endrpcent,
+[AC_TRY_COMPILE([#include <netdb.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+extern void endrpcent();],
+[int i;], k5_cv_type_endrpcent=void, k5_cv_type_endrpcent=int)])dnl
+AC_MSG_RESULT($k5_cv_type_endrpcent)
+AC_DEFINE_UNQUOTED(ENDRPCENT_TYPE, $k5_cv_type_endrpcent, [Define as return type of endrpcent])
+K5_GEN_FILE(include/gssrpc/types.h:include/gssrpc/types.hin)
+changequote(<<, >>)
+case "$krb5_cv_host" in
+*-*-solaris2.[012345]*)
+	PASS=tcp
+	;;
+*)
+	PASS="tcp udp"
+	;;
+esac
+changequote([, ])
+AC_SUBST(PASS)
+
+dnl for pkinit
+AC_CACHE_CHECK(for a recent enough OpenSSL, k5_cv_openssl_version_okay,
+[AC_COMPILE_IFELSE([#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x00908000L
+# error openssl is too old, need 0.9.8
+#endif
+int i = 1;
+], k5_cv_openssl_version_okay=yes, k5_cv_openssl_version_okay=no)])
+old_LIBS="$LIBS"
+AC_CHECK_LIB(crypto, PKCS7_get_signer_info)
+LIBS="$old_LIBS"
+if test "$k5_cv_openssl_version_okay" = yes; then
+  AC_CONFIG_SUBDIRS(plugins/preauth/pkinit)
+fi
+
+dnl
+dnl
+dnl Check for thread safety issues.
+dnl (Is there a better place for this?)
+dnl tsfuncs="getpwnam_r getpwuid_r gethostbyname_r getservbyname_r gmtime_r localtime_r"
+dnl Removed getpwnam_r and getpwuid_r because include/configure.in has some
+dnl more careful checks, and may decide to pretend that they're not found if
+dnl the function signatures can't be figured out.
+tsfuncs="gethostbyname_r getservbyname_r gmtime_r localtime_r"
+AC_CHECK_FUNCS($tsfuncs)
+if test "$enable_thread_support" = yes; then
+  tsmissing=""
+  for ts in $tsfuncs; do
+    if eval "test \"\${ac_cv_func_$ts}\" != yes"; then
+      tsmissing="$tsmissing $ts"
+    fi
+  done
+  if test "$ac_cv_func_res_nsearch/$ac_cv_lib_resolv_res_nsearch" = "no/no"; then
+    tsmissing="$tsmissing res_nsearch"
+  fi
+  if test "$tsmissing" != ""; then
+    AC_MSG_WARN([Some functions that are needed for library thread])
+    AC_MSG_WARN([safety appear to be missing.])
+    for ts in $tsmissing; do
+      AC_MSG_WARN([  missing thread-safe function: $ts])
+    done
+    AC_MSG_WARN([Without these functions, the installed libraries])
+    AC_MSG_WARN([may not be thread-safe.])
+  fi # tsmissing not empty
+fi # enable_thread_support
+dnl
+HOST_TYPE=$krb5_cv_host
+AC_SUBST(HOST_TYPE)
+dnl
+dnl Sadly, we seem to have accidentally committed ourselves in 1.4 to
+dnl an ABI that includes the existence of libkrb5support.0 even
+dnl though random apps should never use anything from it.  And on
+dnl the Mac, to which that didn't apply, we can't use major version 0.
+dnl
+case $krb5_cv_host in
+*-*-darwin* | *-*-rhapsody*) SUPPORTLIB_MAJOR=1 ;;
+*)			     SUPPORTLIB_MAJOR=0 ;;
+esac
+AC_SUBST(SUPPORTLIB_MAJOR)
+dnl
+dnl
+if test "$COM_ERR_VERSION" = k5 ; then
+dnl  AC_CONFIG_SUBDIRS(util/et)
+  K5_GEN_MAKEFILE(util/et)
+fi
+if test "$SS_VERSION" = k5 ; then
+  AC_CONFIG_SUBDIRS(util/ss)
+fi
+if test -n "$KRB4_LIB"; then
+  K5_GEN_MAKEFILE(lib/krb4)
+fi
+dnl
+dnl
+ldap_plugin_dir=""
+ldap_lib=""
+if test -n "$OPENLDAP_PLUGIN"; then
+  AC_CHECK_HEADERS(ldap.h lber.h)
+  if test $ac_cv_header_ldap_h = no || test $ac_cv_header_lber_h = no; then
+    AC_ERROR(OpenLDAP headers missing)
+  fi
+  old_LIBS="$LIBS"
+  LIBS="$LIBS -lldap"
+  AC_CHECK_FUNCS(ldap_initialize ldap_url_parse_nodn ldap_unbind_ext_s ldap_str2dn ldap_explode_dn)
+  LIBS="$old_LIBS"
+  AC_CONFIG_SUBDIRS(plugins/kdb/ldap/libkdb_ldap)
+  K5_GEN_MAKEFILE(plugins/kdb/ldap)
+  K5_GEN_MAKEFILE(plugins/kdb/ldap/ldap_util)
+  ldap_plugin_dir=plugins/kdb/ldap
+fi
+AC_SUBST(ldap_plugin_dir)
+
+AC_CONFIG_SUBDIRS(lib/apputils plugins/kdb/db2 plugins/preauth/wpse plugins/preauth/cksum_body appl tests)
+dnl
+if false; then
+  AC_CHECK_HEADERS(Python.h python2.3/Python.h)
+  AC_CONFIG_SUBDIRS(plugins/locate/python)
+fi
+
+AC_CONFIG_FILES(krb5-config, [chmod +x krb5-config])
+V5_AC_OUTPUT_MAKEFILE(.
+
+	util util/support util/profile util/send-pr
+
+	lib lib/des425 lib/kdb
+
+	lib/crypto lib/crypto/crc32 lib/crypto/des lib/crypto/dk
+	lib/crypto/enc_provider lib/crypto/hash_provider
+	lib/crypto/keyhash_provider lib/crypto/md4 lib/crypto/md5
+	lib/crypto/old lib/crypto/raw lib/crypto/sha1
+	lib/crypto/arcfour lib/crypto/yarrow lib/crypto/aes
+
+	lib/krb5 lib/krb5/error_tables lib/krb5/asn.1 lib/krb5/ccache
+	lib/krb5/keytab lib/krb5/krb lib/krb5/rcache lib/krb5/os
+
+	lib/gssapi lib/gssapi/generic lib/gssapi/krb5
+	lib/gssapi/mechglue lib/gssapi/spnego
+
+	lib/rpc lib/rpc/unit-test
+
+	lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/unit-test
+
+	kdc slave krb524 config-files gen-manpages include
+	include/kerberosIV
+
+	clients clients/klist clients/kinit clients/kvno
+	clients/kdestroy clients/kpasswd clients/ksu
+
+	kadmin kadmin/cli kadmin/dbutil kadmin/passwd
+	kadmin/passwd/unit-test kadmin/ktutil kadmin/server
+	kadmin/testing kadmin/testing/scripts kadmin/testing/util
+
+)
diff --git a/krb5-1-6/src/gen-manpages/Makefile.in b/krb5-1-6/src/gen-manpages/Makefile.in
new file mode 100644
index 000000000..a005278b5
--- /dev/null
+++ b/krb5-1-6/src/gen-manpages/Makefile.in
@@ -0,0 +1,9 @@
+thisconfigdir=./..
+myfulldir=gen-manpages
+mydir=gen-manpages
+BUILDTOP=$(REL)..
+all::
+
+install::
+	$(INSTALL_DATA) $(srcdir)/kerberos.M ${DESTDIR}$(CLIENT_MANDIR)/kerberos.1
+	$(INSTALL_DATA) $(srcdir)/k5login.M ${DESTDIR}$(FILE_MANDIR)/.k5login.5
diff --git a/krb5-1-6/src/gen-manpages/header.doc b/krb5-1-6/src/gen-manpages/header.doc
new file mode 100644
index 000000000..d11228786
--- /dev/null
+++ b/krb5-1-6/src/gen-manpages/header.doc
@@ -0,0 +1 @@
+.ds h ""Kerberos V5 release Beta 7" "MIT Project Athena"
diff --git a/krb5-1-6/src/gen-manpages/k5login.M b/krb5-1-6/src/gen-manpages/k5login.M
new file mode 100644
index 000000000..d6b30ae57
--- /dev/null
+++ b/krb5-1-6/src/gen-manpages/k5login.M
@@ -0,0 +1,55 @@
+.TH .K5LOGIN 5
+.SH NAME
+.k5login \- Kerberos V5 acl file for host access.
+.SH DESCRIPTION
+The
+.B .k5login
+file, which resides in a user's home directory, contains a list of the
+Kerberos principals.  Anyone with valid tickets for a principal in the
+file is allowed host access with the UID of the user in whose home
+directory the file resides.  One common use is to place a
+.B .k5login
+file in root's home directory, thereby granting system administrators
+remote root access to the host via Kerberos.
+.SH EXAMPLES
+Suppose the user "janedoe" had a 
+.B .k5login
+file in her home directory containing the following line:
+.sp
+.nf
+.in +1i
+johndoe@FUBAR.ORG
+.in -1i
+.fi
+.sp
+This would allow her husband "johndoe" to use any of the Kerberos
+network applications, such as
+.IR telnet (1),
+.IR rlogin (1),
+.IR rsh (1),
+and
+.IR rcp (1),
+to access her account, using his own Kerberos tickets.
+.PP
+Let us further suppose that "janedoe" is a system administrator.  She
+and the other system administrators would have their principals in
+root's
+.B .k5login
+file on each host:
+.sp
+.nf
+.in +1i
+janedoe@BLEEP.COM
+joeadmin/root@BLEEP.COM
+.in -1i
+.fi
+.sp
+This would allow either system administrator to log in to these hosts
+using their Kerberos tickets instead of having to type the root
+password.  Note that because "janedoe"'s husband retains the Kerberos
+tickets for his own principal, "johndoe@FUBAR.ORG", he would not have
+any of the privileges that require his wife's tickets, such as root
+access to any of her site's hosts, or the ability to change her
+password.
+.SH SEE ALSO
+telnet(1), rlogin(1), rsh(1), rcp(1), ksu(1), telnetd(8), klogind(8)
diff --git a/krb5-1-6/src/gen-manpages/kerberos.M b/krb5-1-6/src/gen-manpages/kerberos.M
new file mode 100644
index 000000000..b412be570
--- /dev/null
+++ b/krb5-1-6/src/gen-manpages/kerberos.M
@@ -0,0 +1,143 @@
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\" "
+.TH KERBEROS 1
+.SH NAME
+kerberos \- introduction to the Kerberos system
+.SH DESCRIPTION
+The Kerberos system authenticates individual users in a network
+environment.  After authenticating yourself to Kerberos, you can use
+network utilities such as
+.IR rlogin ,
+.IR rcp ,
+and
+.IR rsh
+without having to present passwords to remote hosts and without having
+to bother with
+.I \.rhosts
+files.  Note that these utilities will work without passwords only if
+the remote machines you deal with support the Kerberos system.
+.PP
+If you enter your username and
+.I kinit
+responds with this message:
+.PP
+kinit(v5): Client not found in Kerberos database while getting initial
+credentials
+.PP
+you haven't been registered as a Kerberos user.  See your system
+administrator.
+.PP
+A Kerberos name usually contains three parts.  The first is the
+.IR primary ,
+which is usually a user's or service's name.  The second is the
+.IR instance ,
+which in the case of a user is usually null.  Some users may have
+privileged instances, however, such as ``root'' or ``admin''.  In the
+case of a service, the instance is the fully qualified name of the
+machine on which it runs; i.e. there can be an
+.I rlogin
+service running on the machine ABC, which is different from the rlogin
+service running on the machine XYZ.  The third part of a Kerberos name
+is the
+.IR realm .
+The realm corresponds to the Kerberos service providing authentication
+for the principal.
+.PP
+When writing a Kerberos name, the principal name is separated from the
+instance (if not null) by a slash, and the realm (if not the local
+realm) follows, preceded by an ``@'' sign.  The following are examples
+of valid Kerberos names:
+.sp
+.nf
+.in +8
+david
+jennifer/admin
+joeuser@BLEEP.COM
+cbrown/root@FUBAR.ORG
+.in -8
+.fi
+.PP
+When you authenticate yourself with Kerberos you get an initial Kerberos
+.IR ticket .
+(A Kerberos ticket is an encrypted protocol message that provides
+authentication.)  Kerberos uses this ticket for network utilities such
+as
+.I rlogin
+and
+.IR rcp .
+The ticket transactions are done transparently, so you don't have to
+worry about their management.
+.PP
+Note, however, that tickets expire.  Privileged tickets, such as those
+with the instance ``root'', expire in a few minutes, while tickets that
+carry more ordinary privileges may be good for several hours or a day,
+depending on the installation's policy.  If your login session extends
+beyond the time limit, you will have to re-authenticate yourself to
+Kerberos to get new tickets.  Use the
+.IR kinit
+command to re-authenticate yourself.
+.PP
+If you use the
+.I kinit
+command to get your tickets, make sure you use the
+.I kdestroy
+command to destroy your tickets before you end your login session.  You
+should put the
+.I kdestroy
+command in your
+.I \.logout
+file so that your tickets will be destroyed automatically when you
+logout.  For more information about the
+.I kinit
+and
+.I kdestroy
+commands, see the
+.IR kinit (1)
+and
+.IR kdestroy (1)
+manual pages.
+.PP
+Kerberos tickets can be forwarded.  In order to forward tickets, you
+must request
+.I forwardable
+tickets when you
+.IR kinit .
+Once you have forwardable tickets, most Kerberos programs have a command
+line option to forward them to the remote host.
+.PP
+Currently, Kerberos support is available for the following network
+services:
+.IR rlogin ,
+.IR rsh ,
+.IR rcp ,
+.IR telnet ,
+.IR ftp ,
+.I krdist
+(a Kerberized version of
+.IR rdist ),
+.I ksu
+(a Kerberized version of
+.IR su ),
+.IR login ,
+and
+.IR Xdm .
+.SH "SEE ALSO"
+kdestroy(1), kinit(1), klist(1), kpasswd(1), rsh (1), rcp(1), rlogin(1),
+telnet(1), ftp(1), krdist(1), ksu(1), sclient(1), xdm(1), des_crypt(3),
+hash(3), krb5strings(3), krb5.conf(5), kdc.conf(5), kadmin(8),
+kadmind(8), kdb5_util(8), telnetd(8), ftpd(8), rdistd(8), sserver(8),
+klogind(8c), kshd(8c), login(8c)
+.SH BUGS
+.SH AUTHORS
+Steve Miller, MIT Project Athena/Digital Equipment Corporation
+.br
+Clifford Neuman, MIT Project Athena
+.SH HISTORY
+Kerberos was developed at MIT.  OpenVision rewrote and donated the
+administration server, which is used in the current version of Kerberos
+5.
+.SH RESTRICTIONS
+Copyright 1985,1986,1989-1996,2002 Massachusetts Institute of Technology
diff --git a/krb5-1-6/src/include/Makefile.in b/krb5-1-6/src/include/Makefile.in
new file mode 100644
index 000000000..4229c0ff5
--- /dev/null
+++ b/krb5-1-6/src/include/Makefile.in
@@ -0,0 +1,134 @@
+thisconfigdir=..
+myfulldir=include
+mydir=include
+LOCAL_SUBDIRS=@maybe_kerberosIV@
+BUILDTOP=$(REL)..
+KRB5RCTMPDIR= @KRB5_RCTMPDIR@
+##DOSBUILDTOP = ..
+NO_OUTPRE=1
+
+all-unix:: krb5/krb5.h
+
+all-unix:: maybe-make-db.h-@DB_HEADER_VERSION@
+
+generate-files-mac: krb5/krb5.h
+
+maybe-make-db.h-k5:
+	: db.h will be installed by util/db2
+maybe-make-db.h-sys:
+	: fall back to system db.h 
+maybe-make-db.h-redirect:
+	test -r db.h || echo '#include <@DB_HEADER@>' > db.h
+
+ET_HEADERS = adm_err.h asn1_err.h kdb5_err.h krb5_err.h
+BUILT_HEADERS = osconf.h
+
+all-unix:: autoconf.h $(BUILT_HEADERS)
+all-windows:: autoconf.h $(BUILT_HEADERS)
+
+all-unix:: @MAINT@ verify-calling-conventions-krb5
+
+$(srcdir)/autoconf.h.in: @MAINT@ $(srcdir)/autoconf.stmp
+$(srcdir)/autoconf.stmp: $(srcdir)/$(thisconfigdir)/configure.in $(SRCTOP)/aclocal.m4
+	$(RM) -r $(srcdir)/$(thisconfigdir)/autom4te.cache
+	cd $(srcdir)/$(thisconfigdir) && $(AUTOHEADER) --include=$(CONFIG_RELTOPDIR) $(AUTOHEADERFLAGS)
+	touch $(srcdir)/autoconf.stmp
+	$(RM) -r $(srcdir)/$(thisconfigdir)/autom4te.cache
+
+##DOS##autoconf.h: win-mac.h
+##DOS##	$(CP) win-mac.h $@
+##DOS##osconf.h: stock\osconf.h
+##DOS##	$(CP) stock\osconf.h $@
+
+###############################################################################
+##DOS##!if 0
+autoconf.h: autoconf.stamp
+autoconf.stamp: $(srcdir)/autoconf.h.in $(thisconfigdir)/config.status
+	(cd $(thisconfigdir) && $(SHELL) config.status $(mydir)/autoconf.h)
+	touch autoconf.stamp
+
+SYSCONFDIR = @sysconfdir@
+LOCALSTATEDIR = @localstatedir@
+BINDIR = @bindir@
+SBINDIR = @sbindir@
+LIBDIR  = @libdir@
+
+PROCESS_REPLACE = -e "s+@KRB5RCTMPDIR+$(KRB5RCTMPDIR)+" \
+		  -e "s+@PREFIX+$(INSTALL_PREFIX)+" \
+		  -e "s+@EXEC_PREFIX+$(INSTALL_EXEC_PREFIX)+" \
+		  -e "s+@BINDIR+$(BINDIR)+" \
+		  -e "s+@LIBDIR+$(LIBDIR)+" \
+		  -e "s+@SBINDIR+$(SBINDIR)+" \
+		  -e "s+@MODULEDIR+$(MODULE_DIR)+" \
+	-e 's+@LOCALSTATEDIR+$(LOCALSTATEDIR)+' \
+	-e 's+@SYSCONFDIR+$(SYSCONFDIR)+' 
+
+OSCONFSRC = $(srcdir)/stock/osconf.h
+
+osconf.h: $(OSCONFSRC) Makefile
+	cat $(OSCONFSRC) | sed $(PROCESS_REPLACE) > osconf.new
+	@set -x ; if cmp -s osconf.new osconf.h ; then : osconf.h is current ; \
+	else ($(RM) osconf.h ; $(CP) osconf.new osconf.h) fi
+	$(RM) osconf.new
+##DOS##!endif
+###############################################################################
+
+krb5/krb5.h: $(srcdir)/krb5/krb5.hin krb5_err.h kdb5_err.h kv5m_err.h krb524_err.h asn1_err.h
+	test -d krb5 || mkdir krb5
+	if test -r krb5.h; then \
+	  if cmp -s krb5.h $(srcdir)/krb5.h; then :; else rm -f krb5.h; fi; \
+	else :; fi
+	echo "/* This file is generated, please don't edit it directly.  */" > krb5/krb5.h
+	echo "#ifndef KRB5_KRB5_H_INCLUDED" >> krb5/krb5.h
+	echo "#define KRB5_KRB5_H_INCLUDED" >> krb5/krb5.h
+	cat $(srcdir)/krb5/krb5.hin krb5_err.h kdb5_err.h kv5m_err.h krb524_err.h \
+		asn1_err.h >> krb5/krb5.h
+	echo "#endif /* KRB5_KRB5_H_INCLUDED */" >> krb5/krb5.h
+
+verify-calling-conventions-krb5: private-and-public-decls
+	$(PERL) -w $(SRCTOP)/util/def-check.pl private-and-public-decls $(SRCTOP)/lib/krb5_32.def
+
+HEADERS_TO_CHECK = krb5/krb5.h $(srcdir)/k5-int.h $(srcdir)/krb5/preauth_plugin.h
+
+private-and-public-decls: $(HEADERS_TO_CHECK)
+	cat $(HEADERS_TO_CHECK) > $@
+
+#
+# Build the error table include files:
+# asn1_err.h kdb5_err.h krb5_err.h kv5m_err.h krb524_err.h
+
+asn1_err.h kdb5_err.h krb5_err.h kv5m_err.h krb524_err.h: rebuild-error-tables
+	: $@
+rebuild-error-tables:
+	(cd ../lib/krb5/error_tables && $(MAKE) includes)
+
+.PHONY: force rebuild-error-tables
+force:
+
+asn1_err.h: $(SRCTOP)/lib/krb5/error_tables/asn1_err.et
+kdb5_err.h: $(SRCTOP)/lib/krb5/error_tables/kdb5_err.et
+krb5_err.h: $(SRCTOP)/lib/krb5/error_tables/krb5_err.et	
+kv5m_err.h: $(SRCTOP)/lib/krb5/error_tables/kv5m_err.et
+krb524_err.h: $(SRCTOP)/lib/krb5/error_tables/krb524_err.et
+
+clean-unix::
+	$(RM) krb5/krb5.h krb5_err.h kdb5_err.h kv5m_err.h krb524_err.h \
+		asn1_err.h
+	$(RM) $(ET_HEADERS) autoconf.stamp
+
+clean-windows::
+	$(RM) com_err.h profile.h
+	$(RM) gssapi\gssapi.h gssapi\gssapi_generic.h gssapi\gssapi_krb5.h gssapi\timestamp
+	if exist gssapi\nul rmdir gssapi
+	$(RM) osconf.h autoconf.h autoconf.stamp
+	@echo Making clean in include
+
+clean::
+	$(RM) osconf.new $(BUILT_HEADERS)
+
+install-headers-unix install:: krb5/krb5.h profile.h
+	$(INSTALL_DATA) $(srcdir)/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5.h
+	$(INSTALL_DATA) krb5/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)krb5.h
+	$(INSTALL_DATA) $(srcdir)/krb5/locate_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)locate_plugin.h
+	$(INSTALL_DATA) profile.h $(DESTDIR)$(KRB5_INCDIR)$(S)profile.h
+	$(INSTALL_DATA) $(srcdir)/gssapi.h $(DESTDIR)$(KRB5_INCDIR)$(S)gssapi.h
diff --git a/krb5-1-6/src/include/adm.h b/krb5-1-6/src/include/adm.h
new file mode 100644
index 000000000..34c195fa2
--- /dev/null
+++ b/krb5-1-6/src/include/adm.h
@@ -0,0 +1,220 @@
+/*
+ * include/krb5/adm.h
+ *
+ * Copyright 1995,2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+#ifndef	KRB5_ADM_H__
+#define	KRB5_ADM_H__
+
+/*
+ * Kerberos V5 Change Password service name
+ */
+#define	KRB5_ADM_SERVICE_NAME	"kpasswd"
+#define	KRB5_ADM_DEFAULT_PORT	464
+
+#define KRB5_ADM_SERVICE_INSTANCE "changepw"
+
+/*
+ * Maximum password length.
+ */
+#define	KRB5_ADM_MAX_PASSWORD_LEN	512
+
+/*
+ * Protocol command strings.
+ */
+#define	KRB5_ADM_QUIT_CMD	"QUIT"
+#define	KRB5_ADM_CHECKPW_CMD	"CHECKPW"
+#define	KRB5_ADM_CHANGEPW_CMD	"CHANGEPW"
+#define	KRB5_ADM_MOTD_CMD	"MOTD"
+#define	KRB5_ADM_MIME_CMD	"MIME"
+#define	KRB5_ADM_LANGUAGE_CMD	"LANGUAGE"
+
+#define	KRB5_ADM_ADD_PRINC_CMD	"ADD-PRINCIPAL"
+#define	KRB5_ADM_DEL_PRINC_CMD	"DELETE-PRINCIPAL"
+#define	KRB5_ADM_REN_PRINC_CMD	"RENAME-PRINCIPAL"
+#define	KRB5_ADM_MOD_PRINC_CMD	"MODIFY-PRINCIPAL"
+#define	KRB5_ADM_INQ_PRINC_CMD	"INQUIRE-PRINCIPAL"
+#define	KRB5_ADM_EXT_KEY_CMD	"EXTRACT-KEY"
+
+/*
+ * Protocol command strings for the current version of the admin
+ * server.  (Chris had removed them in the version he was working
+ * with.)
+ *
+ * XXX I'm adding them back so the tree works.  We need to take care
+ * of this eventually.
+ */
+#define       KRB5_ADM_CHG_OPW_CMD    "OTHER-CHANGEPW"
+#define       KRB5_ADM_CHG_ORPW_CMD   "OTHER-RANDOM-CHANGEPW"
+#define       KRB5_ADM_ADD_KEY_CMD    "ADD-KEY"
+#define       KRB5_ADM_DEL_KEY_CMD    "DELETE-KEY"
+
+/*
+ * Reply status values.
+ */
+#define	KRB5_ADM_SUCCESS		0
+#define	KRB5_ADM_CMD_UNKNOWN		1
+#define	KRB5_ADM_PW_UNACCEPT		2
+#define	KRB5_ADM_BAD_PW			3
+#define	KRB5_ADM_NOT_IN_TKT		4
+#define	KRB5_ADM_CANT_CHANGE		5
+#define	KRB5_ADM_LANG_NOT_SUPPORTED	6
+
+#define	KRB5_ADM_P_ALREADY_EXISTS	64
+#define	KRB5_ADM_P_DOES_NOT_EXIST	65
+#define	KRB5_ADM_NOT_AUTHORIZED		66
+#define	KRB5_ADM_BAD_OPTION		67
+#define	KRB5_ADM_VALUE_REQUIRED		68
+#define	KRB5_ADM_SYSTEM_ERROR		69
+#define	KRB5_ADM_KEY_DOES_NOT_EXIST	70
+#define	KRB5_ADM_KEY_ALREADY_EXISTS	71
+
+/*
+ * Principal flag keywords.
+ */
+/* Settable only */
+#define	KRB5_ADM_KW_PASSWORD		"PASSWORD"
+#define	KRB5_ADM_KW_APASSWORD		"APASSWORD"
+#define	KRB5_ADM_KW_RANDOMKEY		"RANDOMKEY"
+#define	KRB5_ADM_KW_ARANDOMKEY		"ARANDOMKEY"
+#define	KRB5_ADM_KW_SETFLAGS		"SETFLAGS"
+#define	KRB5_ADM_KW_UNSETFLAGS		"UNSETFLAGS"
+/* Settable and retrievable */
+#define	KRB5_ADM_KW_MAXLIFE		"MAXLIFE"
+#define	KRB5_ADM_KW_MAXRENEWLIFE	"MAXRENEWLIFE"
+#define	KRB5_ADM_KW_EXPIRATION		"EXPIRATION"
+#define	KRB5_ADM_KW_PWEXPIRATION	"PWEXPIRATION"
+#define	KRB5_ADM_KW_FLAGS		"FLAGS"
+#define	KRB5_ADM_KW_AUXDATA		"AUXDATA"
+#define	KRB5_ADM_KW_EXTRADATA		"EXTRADATA"
+/* Retrievable only */
+#define	KRB5_ADM_KW_LASTPWCHANGE	"LASTPWCHANGE"
+#define	KRB5_ADM_KW_LASTSUCCESS		"LASTSUCCESS"
+#define	KRB5_ADM_KW_LASTFAILED		"LASTFAILED"
+#define	KRB5_ADM_KW_FAILCOUNT		"FAILCOUNT"
+#define	KRB5_ADM_KW_KEYDATA		"KEYDATA"
+
+/* Valid mask */
+#define	KRB5_ADM_M_PASSWORD		0x00000001
+#define	KRB5_ADM_M_MAXLIFE		0x00000002
+#define	KRB5_ADM_M_MAXRENEWLIFE		0x00000004
+#define	KRB5_ADM_M_EXPIRATION		0x00000008
+#define	KRB5_ADM_M_PWEXPIRATION		0x00000010
+#define	KRB5_ADM_M_RANDOMKEY		0x00000020
+#define	KRB5_ADM_M_FLAGS		0x00000040
+#define	KRB5_ADM_M_LASTPWCHANGE		0x00000080
+#define	KRB5_ADM_M_LASTSUCCESS		0x00000100
+#define	KRB5_ADM_M_LASTFAILED		0x00000200
+#define	KRB5_ADM_M_FAILCOUNT		0x00000400
+#define	KRB5_ADM_M_AUXDATA		0x00000800
+#define	KRB5_ADM_M_KEYDATA		0x00001000
+#define	KRB5_ADM_M_APASSWORD		0x00002000
+#define	KRB5_ADM_M_ARANDOMKEY		0x00004000
+#define	KRB5_ADM_M_UNUSED_15		0x00008000
+#define	KRB5_ADM_M_UNUSED_16		0x00010000
+#define KRB5_ADM_M_UNUSED_17		0x00020000
+#define	KRB5_ADM_M_UNUSED_18		0x00040000
+#define	KRB5_ADM_M_UNUSED_19		0x00080000
+#define	KRB5_ADM_M_UNUSED_20		0x00100000
+#define	KRB5_ADM_M_UNUSED_21		0x00200000
+#define	KRB5_ADM_M_UNUSED_22		0x00400000
+#define	KRB5_ADM_M_UNUSED_23		0x00800000
+#define	KRB5_ADM_M_UNUSED_24		0x01000000
+#define	KRB5_ADM_M_UNUSED_25		0x02000000
+#define	KRB5_ADM_M_UNUSED_26		0x04000000
+#define	KRB5_ADM_M_UNUSED_27		0x08000000
+#define	KRB5_ADM_M_UNUSED_28		0x10000000
+#define	KRB5_ADM_M_UNUSED_29		0x20000000
+#define	KRB5_ADM_M_GET			0x40000000
+#define	KRB5_ADM_M_SET			0x80000000
+
+#define KRB5_ADM_M_EXTRADATA		0x00000000 /* Hack to get */
+						   /* libkadm to compile */
+
+#define	KRB5_ADM_M_SET_VALID		(KRB5_ADM_M_SET		+ \
+					 KRB5_ADM_M_PASSWORD	+ \
+					 KRB5_ADM_M_APASSWORD	+ \
+					 KRB5_ADM_M_MAXLIFE	+ \
+					 KRB5_ADM_M_MAXRENEWLIFE+ \
+					 KRB5_ADM_M_EXPIRATION	+ \
+					 KRB5_ADM_M_PWEXPIRATION+ \
+					 KRB5_ADM_M_RANDOMKEY	+ \
+					 KRB5_ADM_M_ARANDOMKEY	+ \
+					 KRB5_ADM_M_FLAGS	+ \
+					 KRB5_ADM_M_AUXDATA)
+#define	KRB5_ADM_M_GET_VALID		(KRB5_ADM_M_GET		+ \
+					 KRB5_ADM_M_MAXLIFE	+ \
+					 KRB5_ADM_M_MAXRENEWLIFE+ \
+					 KRB5_ADM_M_EXPIRATION	+ \
+					 KRB5_ADM_M_PWEXPIRATION+ \
+					 KRB5_ADM_M_FLAGS	+ \
+					 KRB5_ADM_M_LASTPWCHANGE+ \
+					 KRB5_ADM_M_LASTSUCCESS	+ \
+					 KRB5_ADM_M_LASTFAILED	+ \
+					 KRB5_ADM_M_FAILCOUNT	+ \
+					 KRB5_ADM_M_AUXDATA	+ \
+					 KRB5_ADM_M_KEYDATA)
+
+/*
+ * Keytab reply components.
+ */
+#define	KRB5_ADM_KT_PRINCIPAL	0
+#define	KRB5_ADM_KT_TIMESTAMP	1
+#define	KRB5_ADM_KT_VNO		2
+#define	KRB5_ADM_KT_KEY_ENCTYPE	3
+#define	KRB5_ADM_KT_KEY_KEY	4
+#define	KRB5_ADM_KT_NCOMPS	5
+
+/* for krb5_key_salt_tuple */
+#include "kdb.h"
+
+/*
+ * Data structure returned by krb5_read_realm_params()
+ */
+typedef struct __krb5_realm_params {
+    char *		realm_profile;
+    char *		realm_dbname;
+    char *		realm_mkey_name;
+    char *		realm_stash_file;
+    char *		realm_kdc_ports;
+    char *		realm_kdc_tcp_ports;
+    char *		realm_acl_file;
+    krb5_int32		realm_kadmind_port;
+    krb5_enctype	realm_enctype;
+    krb5_deltat		realm_max_life;
+    krb5_deltat		realm_max_rlife;
+    krb5_timestamp	realm_expiration;
+    krb5_flags		realm_flags;
+    krb5_key_salt_tuple	*realm_keysalts;
+    unsigned int	realm_reject_bad_transit:1;
+    unsigned int	realm_kadmind_port_valid:1;
+    unsigned int	realm_enctype_valid:1;
+    unsigned int	realm_max_life_valid:1;
+    unsigned int	realm_max_rlife_valid:1;
+    unsigned int	realm_expiration_valid:1;
+    unsigned int	realm_flags_valid:1;
+    unsigned int	realm_reject_bad_transit_valid:1;
+    krb5_int32		realm_num_keysalts;
+} krb5_realm_params;
+#endif	/* KRB5_ADM_H__ */
diff --git a/krb5-1-6/src/include/adm_defs.h b/krb5-1-6/src/include/adm_defs.h
new file mode 100644
index 000000000..b2b747446
--- /dev/null
+++ b/krb5-1-6/src/include/adm_defs.h
@@ -0,0 +1,209 @@
+/*
+ * include/krb5/adm_defs.h
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * <<< Description >>>
+ */
+
+
+#ifndef __ADM_DEFINES__
+#define __ADM_DEFINES__
+
+#define ADM5_VERSTR		"ADM5VER1"
+#define ADM5_VERSIZE		strlen(ADM5_VERSTR)
+/* This used to be kerberos_master */
+#define ADM5_PORTNAME		"kerberos-adm"
+#define ADM5_DEFAULT_PORT	752
+#define ADM5_CPW_VERSION	"V5CPWS01"
+#define ADM5_ADM_VERSION	"V5ADMS01"
+#define CPWNAME			"kadmin"
+#define ADMINSTANCE		"admin"
+
+#define ADM_CPW_VERSION         "V5CPWS01"
+#define ADM_MAX_PW_ITERATIONS	5
+#define ADM_MAX_PW_CHOICES	5
+
+#ifdef MACH_PASS
+#define ADM_MAX_PW_LENGTH       8
+#define ADM_MAX_PHRASE_LENGTH	101
+#else
+#define ADM_MAX_PW_LENGTH       255
+#endif
+
+#define CPW_SNAME               ADM5_PORTNAME
+
+#define MAXCPWBUFSIZE 4096
+
+#ifdef unicos61
+#define SIZEOF_INADDR  SIZEOF_in_addr
+#else
+#define SIZEOF_INADDR sizeof(struct in_addr)
+#endif
+
+/* Server */
+#define KADMIND		0x01
+
+/* Applications */
+#define KPASSWD		0x01
+#define KSRVUTIL	0x02
+#define KADMIN		0x03
+
+/* Operations */
+#define ADDOPER		0x01    /* Add Principal */
+#define CHGOPER		0x02    /* Change Password */
+#define ADROPER         0x03    /* Add principal with random password */
+#define CHROPER         0x04    /* Change to random password */
+#define DELOPER		0x05    /* Delete Principal */
+#define MODOPER		0x06    /* Modify Principal attributes */
+#define INQOPER		0x07    /* Display Principal info */
+#define AD4OPER         0x08    /* Add Principal using v4 string-to-key */
+#define CH4OPER         0x09    /* Change password using v4 string-to-key */
+#define COMPLETE	0x0f
+
+/* Extra Message Types */
+#define SENDDATA1	0x00
+#define SENDDATA2	0x01
+#define SENDDATA3	0x02
+
+/* Unknowns */
+#define KUNKNOWNAPPL	0xff
+#define KUNKNOWNOPER	0xff
+#define KUNKNOWNERR	0xff
+
+typedef struct {
+    char appl_code;
+    char oper_code;
+    char retn_code;
+    char *message;
+} kadmin_requests;
+
+#if 0
+static char *oper_type[] = {
+	"complete",					/* 0 */
+	"addition",					/* 1 */
+	"deletion",					/* 2 */
+	"change",					/* 3 */
+	"modification",					/* 4 */
+	"inquiry"					/* 5 */
+};
+#endif
+
+#define SKYCHANGED	0x00
+#define NSKYRCVD	0x01
+
+
+#if 0
+static char *ksrvutil_message[] = {
+	"Service Key Changed",				/* 0 */
+	"New Key and Version Received"			/* 1 */
+};
+#endif
+
+#define KADMGOOD	0x00
+#define KADMSAG		0x01
+
+#if 0
+static char *kadmind_general_response[] = {
+	"Success",					/* 0 */
+	"Service Access Granted"			/* 1 */
+};
+#endif
+
+
+#define KPASSGOOD	0x00
+#define KPASSBAD	0x01
+
+#if 0
+static char *kadmind_kpasswd_response[] = {
+	"Password Changed",				/* 0 */
+	"Password NOT Changed!"				/* 1 */
+};
+#endif
+
+#define KSRVGOOD	0x00
+#define KSRVBAD		0x01
+#define KSRVCATASTROPHE	0x02
+
+#if 0
+static char *kadmind_ksrvutil_response[] = {
+	"Service Password Change Complete",		/* 0 */
+	"One or More Service Password Change(s) Failed!",	/* 1 */
+	"Database Update Failure - Possible Catastrophe!!"	/* 2 */
+};
+#endif
+
+#define KADMGOOD	0x00
+#define KADMBAD		0x01
+
+#if 0
+static char *kadmind_kadmin_response[] = {
+	"Administrative Service Completed",		/* 0 */
+	"Principal Unknown!",				/* 1 */
+	"Principal Already Exists!",			/* 2 */
+	"Allocation Failure!",				/* 3 */
+	"Password Failure!",				/* 4 */
+	"Protocol Failure!",				/* 5 */
+	"Security Failure!",				/* 6 */
+	"Admin Client Not in ACL List!",			/* 7 */
+	"Database Update Failure - Possible Catastrophe!!"	/* 8 */
+};
+#endif
+
+#define KMODVNO		0x00
+#define KMODATTR	0x01
+
+#ifdef SANDIA
+#define KMODFCNT	0x02
+#endif
+
+#define ATTRPOST	0x00
+#define ATTRNOPOST	0x01
+#define ATTRFOR		0x02
+#define ATTRNOFOR	0x03
+#define ATTRTGT		0x04
+#define ATTRNOTGT	0x05
+#define ATTRREN		0x06
+#define ATTRNOREN	0x07
+#define ATTRPROXY	0x08
+#define ATTRNOPROXY	0x09
+#define ATTRDSKEY	0x0a
+#define ATTRNODSKEY	0x0b
+#define ATTRLOCK	0x0c
+#define ATTRUNLOCK	0x0d
+
+#ifdef SANDIA
+#define ATTRPRE		0x0e
+#define ATTRNOPRE	0x0f
+#define ATTRPWOK	0x10
+#define ATTRPWCHG	0x11
+#define ATTRSID		0x12
+#define ATTRNOSID	0x13
+#endif
+
+#define ATTRNOSVR       0x14
+#define ATTRSVR         0x15
+
+#define BADATTR		0x3f
+
+#endif /* __ADM_DEFINES__ */
diff --git a/krb5-1-6/src/include/adm_proto.h b/krb5-1-6/src/include/adm_proto.h
new file mode 100644
index 000000000..f2bd465f7
--- /dev/null
+++ b/krb5-1-6/src/include/adm_proto.h
@@ -0,0 +1,132 @@
+/*
+ * include/krb5/adm_proto.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+#ifndef	KRB5_ADM_PROTO_H__
+#define	KRB5_ADM_PROTO_H__
+
+/*
+ * This is ugly, but avoids having to include k5-int or kdb.h for this.
+ */
+#ifndef	KRB5_KDB5__
+struct _krb5_db_entry;
+typedef struct _krb5_db_entry krb5_db_entry;
+#endif	/* KRB5_KDB5__ */
+
+/* Ditto for adm.h */
+
+/*
+ * XXXX krb5_realm params is defined in two header files!!!!
+ * This really needs to be fixed!!!
+ */
+#if !defined(KRB5_ADM_H__) && !defined(__KADM5_ADMIN_H__)
+struct ___krb5_realm_params;
+typedef struct ___krb5_realm_params krb5_realm_params;
+#endif	/* KRB5_ADM_H__ */
+
+#ifndef KRB5_KDB5__
+struct ___krb5_key_salt_tuple;
+typedef struct ___krb5_key_salt_tuple krb5_key_salt_tuple;
+#endif	/* KRB5_KDB5__ */
+
+/*
+ * Function prototypes.
+ */
+
+/* logger.c */
+krb5_error_code krb5_klog_init
+	(krb5_context,
+	 char *,
+	 char *,
+	 krb5_boolean);
+void krb5_klog_close (krb5_context);
+int krb5_klog_syslog (int, const char *, ...);
+void krb5_klog_reopen (krb5_context);
+
+/* alt_prof.c */
+krb5_error_code krb5_aprof_init
+	(char *, char *, krb5_pointer *);
+krb5_error_code krb5_aprof_getvals
+	(krb5_pointer, const char **, char ***);
+krb5_error_code krb5_aprof_get_boolean
+        (krb5_pointer, const char **, int, krb5_boolean *);
+krb5_error_code krb5_aprof_get_deltat
+	(krb5_pointer,
+	 const char **,
+	 krb5_boolean,
+	 krb5_deltat *);
+krb5_error_code krb5_aprof_get_string
+	(krb5_pointer, const char **, krb5_boolean, char **);
+krb5_error_code krb5_aprof_get_int32
+	(krb5_pointer,
+	 const char **,
+	 krb5_boolean,
+	 krb5_int32 *);
+krb5_error_code krb5_aprof_finish (krb5_pointer);
+
+krb5_error_code krb5_read_realm_params (krb5_context,
+					char *,
+					krb5_realm_params **);
+krb5_error_code krb5_free_realm_params (krb5_context,
+					krb5_realm_params *);
+
+/* str_conv.c */
+krb5_error_code
+krb5_string_to_flags (char *,
+		      const char *,
+		      const char *,
+		      krb5_flags *);
+krb5_error_code
+krb5_flags_to_string (krb5_flags,
+		      const char *,
+		      char *,
+		      size_t);
+krb5_error_code
+krb5_input_flag_to_string (int, 
+			   char *,
+			   size_t);
+
+/* keysalt.c */
+krb5_boolean
+krb5_keysalt_is_present (krb5_key_salt_tuple *,
+			 krb5_int32,
+			 krb5_enctype,
+			 krb5_int32);
+krb5_error_code
+krb5_keysalt_iterate (krb5_key_salt_tuple *,
+		      krb5_int32,
+		      krb5_boolean,
+		      krb5_error_code (*) (krb5_key_salt_tuple *,
+					   krb5_pointer),
+		      krb5_pointer);
+				     
+krb5_error_code
+krb5_string_to_keysalts (char *,
+			 const char *,
+			 const char *,
+			 krb5_boolean,
+			 krb5_key_salt_tuple **,
+			 krb5_int32 *);
+#endif	/* KRB5_ADM_PROTO_H__ */
diff --git a/krb5-1-6/src/include/cm.h b/krb5-1-6/src/include/cm.h
new file mode 100644
index 000000000..716e6cb59
--- /dev/null
+++ b/krb5-1-6/src/include/cm.h
@@ -0,0 +1,83 @@
+/*
+ * include/cm.h
+ *
+ * Copyright 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* Since fd_set is large on some platforms (8K on AIX 5.2), this
+   probably shouldn't be allocated in automatic storage.  */
+struct select_state {
+    int max, nfds;
+    fd_set rfds, wfds, xfds;
+    struct timeval end_time;	/* magic: tv_sec==0 => never time out */
+};
+
+
+/* Select state flags.  */
+#define SSF_READ	0x01
+#define SSF_WRITE	0x02
+#define SSF_EXCEPTION	0x04
+
+
+static const char *const state_strings[] = {
+    "INITIALIZING", "CONNECTING", "WRITING", "READING", "FAILED"
+};
+
+
+/* connection states */
+enum conn_states { INITIALIZING, CONNECTING, WRITING, READING, FAILED };
+struct incoming_krb5_message {
+    size_t bufsizebytes_read;
+    size_t bufsize;
+    char *buf;
+    char *pos;
+    unsigned char bufsizebytes[4];
+    size_t n_left;
+};
+struct conn_state {
+    SOCKET fd;
+    krb5_error_code err;
+    enum conn_states state;
+    unsigned int is_udp : 1;
+    int (*service)(struct conn_state *, struct select_state *, int);
+    struct addrinfo *addr;
+    struct {
+	struct {
+	    sg_buf sgbuf[2];
+	    sg_buf *sgp;
+	    int sg_count;
+	    unsigned char msg_len_buf[4];
+	} out;
+	struct incoming_krb5_message in;
+    } x;
+};
+
+struct sendto_callback_info {
+    int  (*pfn_callback) (struct conn_state *, void *, krb5_data *);
+    void (*pfn_cleanup)  (void *, krb5_data *);
+    void  *context;	
+};
+
+
+krb5_error_code krb5int_cm_call_select (const struct select_state *,
+					struct select_state *, int *);
diff --git a/krb5-1-6/src/include/copyright.h b/krb5-1-6/src/include/copyright.h
new file mode 100644
index 000000000..b1740ce3c
--- /dev/null
+++ b/krb5-1-6/src/include/copyright.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1989-1994 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
diff --git a/krb5-1-6/src/include/fake-addrinfo.h b/krb5-1-6/src/include/fake-addrinfo.h
new file mode 100644
index 000000000..952b43f0b
--- /dev/null
+++ b/krb5-1-6/src/include/fake-addrinfo.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2001,2002,2003,2004 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+/* Approach overview:
+
+   If a system version is available but buggy, save handles to it (via
+   inline functions in a support library), redefine the names to refer
+   to library functions, and in those functions, call the system
+   versions and fix up the returned data.  Use the native data
+   structures and flag values.
+
+   If no system version exists, use gethostby* and fake it.  Define
+   the data structures and flag values locally.
+
+
+   On Mac OS X, getaddrinfo results aren't cached (though
+   gethostbyname results are), so we need to build a cache here.  Now
+   things are getting really messy.  Because the cache is in use, we
+   use getservbyname, and throw away thread safety.  (Not that the
+   cache is thread safe, but when we get locking support, that'll be
+   dealt with.)  This code needs tearing down and rebuilding, soon.
+
+
+   Note that recent Windows developers' code has an interesting hack:
+   When you include the right header files, with the right set of
+   macros indicating system versions, you'll get an inline function
+   that looks for getaddrinfo (or whatever) in the system library, and
+   calls it if it's there.  If it's not there, it fakes it with
+   gethostby* calls.
+
+   We're taking a simpler approach: A system provides these routines or
+   it does not.
+
+   Someday, we may want to take into account different versions (say,
+   different revs of GNU libc) where some are broken in one way, and
+   some work or are broken in another way.  Cross that bridge when we
+   come to it.  */
+
+/* To do, maybe:
+
+   + For AIX 4.3.3, using the RFC 2133 definition: Implement
+     AI_NUMERICHOST.  It's not defined in the header file.
+
+     For certain (old?) versions of GNU libc, AI_NUMERICHOST is
+     defined but not implemented.
+
+   + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
+     functions if available.  But, see
+     http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
+     gethostbyname2 problem on Linux.  And besides, if a platform is
+     supporting IPv6 at all, they really should be doing getaddrinfo
+     by now.
+
+   + inet_ntop, inet_pton
+
+   + Conditionally export/import the function definitions, so a
+     library can have a single copy instead of multiple.
+
+   + Upgrade host requirements to include working implementations of
+     these functions, and throw all this away.  Pleeease?  :-)  */
+
+#ifndef FAI_DEFINED
+#define FAI_DEFINED
+#include "port-sockets.h"
+#include "socket-utils.h"
+
+#if !defined (HAVE_GETADDRINFO)
+
+#undef  addrinfo
+#define addrinfo	my_fake_addrinfo
+
+struct addrinfo {
+    int ai_family;		/* PF_foo */
+    int ai_socktype;		/* SOCK_foo */
+    int ai_protocol;		/* 0, IPPROTO_foo */
+    int ai_flags;		/* AI_PASSIVE etc */
+    size_t ai_addrlen;		/* real length of socket address */
+    char *ai_canonname;		/* canonical name of host */
+    struct sockaddr *ai_addr;	/* pointer to variable-size address */
+    struct addrinfo *ai_next;	/* next in linked list */
+};
+
+#undef	AI_PASSIVE
+#define	AI_PASSIVE	0x01
+#undef	AI_CANONNAME
+#define	AI_CANONNAME	0x02
+#undef	AI_NUMERICHOST
+#define	AI_NUMERICHOST	0x04
+/* RFC 2553 says these are part of the interface for getipnodebyname,
+   not for getaddrinfo.  RFC 3493 says they're part of the interface
+   for getaddrinfo, and getipnodeby* are deprecated.  Our fake
+   getaddrinfo implementation here does IPv4 only anyways.  */
+#undef	AI_V4MAPPED
+#define	AI_V4MAPPED	0
+#undef	AI_ADDRCONFIG
+#define	AI_ADDRCONFIG	0
+#undef	AI_ALL
+#define	AI_ALL		0
+#undef	AI_DEFAULT
+#define	AI_DEFAULT	(AI_V4MAPPED|AI_ADDRCONFIG)
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+#undef	NI_NUMERICHOST
+#define NI_NUMERICHOST	0x01
+#undef	NI_NUMERICSERV
+#define NI_NUMERICSERV	0x02
+#undef	NI_NAMEREQD
+#define NI_NAMEREQD	0x04
+#undef	NI_DGRAM
+#define NI_DGRAM	0x08
+#undef	NI_NOFQDN
+#define NI_NOFQDN	0x10
+
+
+#undef  EAI_ADDRFAMILY
+#define EAI_ADDRFAMILY	1
+#undef  EAI_AGAIN
+#define EAI_AGAIN	2
+#undef  EAI_BADFLAGS
+#define EAI_BADFLAGS	3
+#undef  EAI_FAIL
+#define EAI_FAIL	4
+#undef  EAI_FAMILY
+#define EAI_FAMILY	5
+#undef  EAI_MEMORY
+#define EAI_MEMORY	6
+#undef  EAI_NODATA
+#define EAI_NODATA	7
+#undef  EAI_NONAME
+#define EAI_NONAME	8
+#undef  EAI_SERVICE
+#define EAI_SERVICE	9
+#undef  EAI_SOCKTYPE
+#define EAI_SOCKTYPE	10
+#undef  EAI_SYSTEM
+#define EAI_SYSTEM	11
+
+#endif /* ! HAVE_GETADDRINFO */
+
+/* Fudge things on older gai implementations.  */
+/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST.  */
+#ifndef AI_NUMERICHOST
+# define AI_NUMERICHOST 0
+#endif
+/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
+   friends, which RFC 3493 says are now part of the getaddrinfo
+   interface, and we'll want to use.  */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+#ifndef AI_V4MAPPED
+# define AI_V4MAPPED 0
+#endif
+#ifndef AI_ALL
+# define AI_ALL 0
+#endif
+#ifndef AI_DEFAULT
+# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
+#endif
+
+#if defined(KRB5_USE_INET6) && defined(NEED_INSIXADDR_ANY) 
+/* If compiling with IPv6 support and C library does not define in6addr_any */
+extern const struct in6_addr krb5int_in6addr_any;
+#undef in6addr_any
+#define in6addr_any krb5int_in6addr_any
+#endif
+
+/* Call out to stuff defined in libkrb5support.  */
+extern int krb5int_getaddrinfo (const char *node, const char *service,
+				const struct addrinfo *hints,
+				struct addrinfo **aip);
+extern void krb5int_freeaddrinfo (struct addrinfo *ai);
+extern const char *krb5int_gai_strerror(int err);
+extern int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+				char *hbuf, size_t hbuflen,
+				char *sbuf, size_t sbuflen,
+				int flags);
+#ifndef IMPLEMENT_FAKE_GETADDRINFO
+#undef	getaddrinfo
+#define getaddrinfo krb5int_getaddrinfo
+#undef  freeaddrinfo
+#define freeaddrinfo krb5int_freeaddrinfo
+#undef  gai_strerror
+#define gai_strerror krb5int_gai_strerror
+#undef  getnameinfo
+#define getnameinfo krb5int_getnameinfo
+#endif
+
+#endif /* FAI_DEFINED */
diff --git a/krb5-1-6/src/include/foreachaddr.h b/krb5-1-6/src/include/foreachaddr.h
new file mode 100644
index 000000000..57591f596
--- /dev/null
+++ b/krb5-1-6/src/include/foreachaddr.h
@@ -0,0 +1,64 @@
+/*
+ * include/foreachaddr.c
+ *
+ * Copyright 1990,1991,2000,2001,2002,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Iterate over the protocol addresses supported by this host, invoking
+ * a callback function or three supplied by the caller.
+ *
+ * XNS support is untested, but "should just work".  (Hah!)
+ */
+
+/* This function iterates over all the addresses it can find for the
+   local system, in one or two passes.  In each pass, and between the
+   two, it can invoke callback functions supplied by the caller.  The
+   two passes should operate on the same information, though not
+   necessarily in the same order each time.  Duplicate and local
+   addresses should be eliminated.  Storage passed to callback
+   functions should not be assumed to be valid after foreach_localaddr
+   returns.
+
+   The int return value is an errno value (XXX or krb5_error_code
+   returned for a socket error) if something internal to
+   foreach_localaddr fails.  If one of the callback functions wants to
+   indicate an error, it should store something via the 'data' handle.
+   If any callback function returns a non-zero value,
+   foreach_localaddr will clean up and return immediately.
+
+   Multiple definitions are provided below, dependent on various
+   system facilities for extracting the necessary information.  */
+
+extern int
+krb5int_foreach_localaddr (/*@null@*/ void *data,
+			   int (*pass1fn) (/*@null@*/ void *,
+					   struct sockaddr *) /*@*/,
+			   /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+			   /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+						      struct sockaddr *) /*@*/)
+#if defined(DEBUG) || defined(TEST)
+     /*@modifies fileSystem@*/
+#endif
+    ;
+
+#define foreach_localaddr krb5int_foreach_localaddr
diff --git a/krb5-1-6/src/include/gssapi.h b/krb5-1-6/src/include/gssapi.h
new file mode 100644
index 000000000..f55768144
--- /dev/null
+++ b/krb5-1-6/src/include/gssapi.h
@@ -0,0 +1,5 @@
+/* 
+ * Wrapper so that #include <gssapi.h> will work without special include
+ * paths.
+ */
+#include <gssapi/gssapi.h>
diff --git a/krb5-1-6/src/include/gssrpc/auth.h b/krb5-1-6/src/include/gssrpc/auth.h
new file mode 100644
index 000000000..cc3de9764
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/auth.h
@@ -0,0 +1,219 @@
+/* @(#)auth.h	2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The data structures are completely opaque to the client.  The client
+ * is required to pass a AUTH * to routines that create rpc
+ * "sessions".
+ */
+#ifndef GSSRPC_AUTH_H
+#define GSSRPC_AUTH_H
+
+#include <gssrpc/xdr.h>
+
+GSSRPC__BEGIN_DECLS
+
+#define MAX_AUTH_BYTES	400
+#define MAXNETNAMELEN	255	/* maximum length of network user's name */
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+	AUTH_OK=0,
+	/*
+	 * failed at remote end
+	 */
+	AUTH_BADCRED=1,			/* bogus credentials (seal broken) */
+	AUTH_REJECTEDCRED=2,		/* client should begin new session */
+	AUTH_BADVERF=3,			/* bogus verifier (seal broken) */
+	AUTH_REJECTEDVERF=4,		/* verifier expired or was replayed */
+	AUTH_TOOWEAK=5,			/* rejected due to security reasons */
+	/*
+	 * failed locally
+	*/
+	AUTH_INVALIDRESP=6,		/* bogus response verifier */
+	AUTH_FAILED=7,			/* some unknown reason */
+	/*
+	 * RPCSEC_GSS errors
+	 */
+	RPCSEC_GSS_CREDPROBLEM = 13,
+	RPCSEC_GSS_CTXPROBLEM = 14
+};
+
+union des_block {
+#if 0 /* XXX nothing uses this, anyway */
+	struct {
+		uint32_t high;
+		uint32_t low;
+	} key;
+#endif
+	char c[8];
+};
+typedef union des_block des_block;
+extern bool_t	xdr_des_block(XDR *, des_block *);
+
+/*
+ * Authentication info.  Opaque to client.
+ */
+struct opaque_auth {
+	enum_t	oa_flavor;		/* flavor of auth */
+	caddr_t	oa_base;		/* address of more auth stuff */
+	u_int	oa_length;		/* not to exceed MAX_AUTH_BYTES */
+};
+
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+struct rpc_msg;
+
+typedef struct AUTH {
+	struct	opaque_auth	ah_cred;
+	struct	opaque_auth	ah_verf;
+	union	des_block	ah_key;
+	struct auth_ops {
+		void	(*ah_nextverf)(struct AUTH *);
+	        /* nextverf & serialize */
+		int	(*ah_marshal)(struct AUTH *, XDR *);
+	        /* validate varifier */
+		int	(*ah_validate)(struct AUTH *,
+				       struct opaque_auth *);
+	        /* refresh credentials */
+		int	(*ah_refresh)(struct AUTH *, struct rpc_msg *);
+	        /* destroy this structure */
+		void	(*ah_destroy)(struct AUTH *);
+		/* encode data for wire */
+		int     (*ah_wrap)(struct AUTH *, XDR *, 
+				   xdrproc_t, caddr_t);
+	        /* decode data from wire */
+  	        int	(*ah_unwrap)(struct AUTH *, XDR *, 
+				     xdrproc_t, caddr_t);	
+	} *ah_ops;
+	void *ah_private;
+} AUTH;
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH	*auth;
+ * XDR	*xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth)		\
+		((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth)		\
+		((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs)	\
+		((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs)	\
+		((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp)	\
+		((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp)	\
+		((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth, msg)		\
+		((*((auth)->ah_ops->ah_refresh))(auth, msg))
+#define auth_refresh(auth, msg)		\
+		((*((auth)->ah_ops->ah_refresh))(auth, msg))
+
+#define AUTH_WRAP(auth, xdrs, xfunc, xwhere)		\
+		((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+					      xfunc, xwhere))
+#define auth_wrap(auth, xdrs, xfunc, xwhere)		\
+		((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+					      xfunc, xwhere))
+#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere)		\
+		((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+					      xfunc, xwhere))
+#define auth_unwrap(auth, xdrs, xfunc, xwhere)		\
+		((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+					      xfunc, xwhere))
+
+#define AUTH_DESTROY(auth)		\
+		((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth)		\
+		((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+#ifdef GSSRPC__IMPL
+/* RENAMED: should be _null_auth if we can use reserved namespace. */
+extern struct opaque_auth gssrpc__null_auth;
+#endif
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ *	char *machname;
+ *	int uid;
+ *	int gid;
+ *	int len;
+ *	int *aup_gids;
+ */
+extern AUTH *authunix_create(char *machname, int uid, int gid, int len,
+			     int *aup_gids);
+extern AUTH *authunix_create_default(void);	/* takes no parameters */
+extern AUTH *authnone_create(void);		/* takes no parameters */
+extern AUTH *authdes_create();
+extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
+
+#define AUTH_NONE	0		/* no authentication */
+#define	AUTH_NULL	0		/* backward compatibility */
+#define	AUTH_UNIX	1		/* unix style (uid, gids) */
+#define	AUTH_SHORT	2		/* short hand unix style */
+#define AUTH_DES	3		/* des style (encrypted timestamps) */
+#define AUTH_GSSAPI	300001		/* GSS-API style */
+#define RPCSEC_GSS	6		/* RPCSEC_GSS */
+
+#if 0
+/*
+ * BACKWARDS COMPATIBILIY!  OpenV*Secure 1.0 had AUTH_GSSAPI == 4.  We
+ * need to accept this value until 1.0 is dead.
+ */
+/* This conflicts with AUTH_KERB (Solaris). */
+#define AUTH_GSSAPI_COMPAT		4
+#endif
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_AUTH_H) */
diff --git a/krb5-1-6/src/include/gssrpc/auth_gss.h b/krb5-1-6/src/include/gssrpc/auth_gss.h
new file mode 100644
index 000000000..ea5db92b9
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/auth_gss.h
@@ -0,0 +1,149 @@
+/*
+  auth_gssapi.h
+  
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+  
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of the University nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Id: auth_gss.h,v 1.13 2002/05/08 16:54:33 andros Exp
+*/
+
+#ifndef GSSRPC_AUTH_GSS_H
+#define GSSRPC_AUTH_GSS_H
+
+#include <gssrpc/rpc.h>
+#include <gssrpc/clnt.h>
+#ifdef HAVE_HEIMDAL
+#include <gssapi.h>
+#else
+#include <gssapi/gssapi.h>
+#endif
+
+GSSRPC__BEGIN_DECLS
+
+/* RPCSEC_GSS control procedures. */
+typedef enum {
+	RPCSEC_GSS_DATA = 0,
+	RPCSEC_GSS_INIT = 1,
+	RPCSEC_GSS_CONTINUE_INIT = 2,
+	RPCSEC_GSS_DESTROY = 3
+} rpc_gss_proc_t;
+
+/* RPCSEC_GSS services. */
+typedef enum {
+	RPCSEC_GSS_SVC_NONE = 1,
+	RPCSEC_GSS_SVC_INTEGRITY = 2,
+	RPCSEC_GSS_SVC_PRIVACY = 3
+} rpc_gss_svc_t;
+
+#define RPCSEC_GSS_VERSION	1
+
+/* RPCSEC_GSS security triple. */
+struct rpc_gss_sec {
+	gss_OID		mech;		/* mechanism */
+	gss_qop_t	qop;		/* quality of protection */
+	rpc_gss_svc_t	svc;		/* service */
+	gss_cred_id_t   cred;		/* cred handle */
+	uint32_t	req_flags;	/* req flags for init_sec_context */
+};
+
+/* Private data required for kernel implementation */
+struct authgss_private_data {
+	gss_ctx_id_t	pd_ctx;		/* Session context handle */
+	gss_buffer_desc	pd_ctx_hndl;	/* Credentials context handle */
+	uint32_t	pd_seq_win;	/* Sequence window */
+};
+
+/* Krb 5 default mechanism 
+#define KRB5OID  "1.2.840.113554.1.2.2"
+
+gss_OID_desc krb5oid = {
+	20, KRB5OID 
+};
+ */
+
+/*
+struct rpc_gss_sec krb5mech = { 
+	(gss_OID)&krb5oid,
+	GSS_QOP_DEFAULT,
+	RPCSEC_GSS_SVC_NONE
+}; 
+*/
+
+/* Credentials. */
+struct rpc_gss_cred {
+	u_int		gc_v;		/* version */
+	rpc_gss_proc_t	gc_proc;	/* control procedure */
+	uint32_t	gc_seq;		/* sequence number */
+	rpc_gss_svc_t	gc_svc;		/* service */
+	gss_buffer_desc	gc_ctx;		/* context handle */
+};
+
+/* Context creation response. */
+struct rpc_gss_init_res {
+	gss_buffer_desc		gr_ctx;		/* context handle */
+	uint32_t		gr_major;	/* major status */
+	uint32_t		gr_minor;	/* minor status */
+	uint32_t		gr_win;		/* sequence window */
+	gss_buffer_desc		gr_token;	/* token */
+};
+
+/* Maximum sequence number value. */
+#define MAXSEQ		0x80000000
+
+/* Prototypes. */
+bool_t	xdr_rpc_gss_buf		(XDR *xdrs, gss_buffer_t, u_int maxsize);
+bool_t	xdr_rpc_gss_cred	(XDR *xdrs, struct rpc_gss_cred *p);
+bool_t	xdr_rpc_gss_init_args	(XDR *xdrs, gss_buffer_desc *p);
+bool_t	xdr_rpc_gss_init_res	(XDR *xdrs, struct rpc_gss_init_res *p);
+bool_t	xdr_rpc_gss_data	(XDR *xdrs, xdrproc_t xdr_func,
+				 caddr_t xdr_ptr, gss_ctx_id_t ctx,
+				 gss_qop_t qop, rpc_gss_svc_t svc,
+				 uint32_t seq);
+bool_t	xdr_rpc_gss_wrap_data	(XDR *xdrs, xdrproc_t xdr_func, caddr_t
+				 xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop,
+				 rpc_gss_svc_t svc, uint32_t seq);
+bool_t	xdr_rpc_gss_unwrap_data	(XDR *xdrs, xdrproc_t xdr_func, caddr_t
+				 xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop,
+				 rpc_gss_svc_t svc, uint32_t seq);
+
+AUTH   *authgss_create		(CLIENT *, gss_name_t, struct rpc_gss_sec *);
+AUTH   *authgss_create_default	(CLIENT *, char *, struct rpc_gss_sec *);
+bool_t authgss_service		(AUTH *auth, int svc);
+bool_t authgss_get_private_data (AUTH *auth, struct authgss_private_data *);
+
+#ifdef GSSRPC__IMPL
+void	log_debug		(const char *fmt, ...);
+void	log_status		(char *m, OM_uint32 major, OM_uint32 minor);
+void	log_hexdump		(const u_char *buf, int len, int offset);
+#endif
+
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_AUTH_GSS_H) */
diff --git a/krb5-1-6/src/include/gssrpc/auth_gssapi.h b/krb5-1-6/src/include/gssrpc/auth_gssapi.h
new file mode 100644
index 000000000..73a2f0b16
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/auth_gssapi.h
@@ -0,0 +1,153 @@
+/*
+ * auth_gssapi.h, Protocol for GSS-API style authentication parameters for RPC
+ * 
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef GSSRPC_AUTH_GSSAPI_H
+#define GSSRPC_AUTH_GSSAPI_H
+
+GSSRPC__BEGIN_DECLS
+
+#define AUTH_GSSAPI_EXIT		0
+#define AUTH_GSSAPI_INIT 		1
+#define AUTH_GSSAPI_CONTINUE_INIT 	2
+#define AUTH_GSSAPI_MSG 		3
+#define AUTH_GSSAPI_DESTROY 		4
+
+/*
+ * Yuck.  Some sys/types.h files leak symbols
+ */
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+
+typedef struct _auth_gssapi_name {
+     char *name;
+     gss_OID type;
+} auth_gssapi_name;
+
+typedef struct _auth_gssapi_creds {
+     uint32_t version;
+     bool_t auth_msg;
+     gss_buffer_desc client_handle;
+} auth_gssapi_creds;
+
+typedef struct _auth_gssapi_init_arg {
+     uint32_t version;
+     gss_buffer_desc token;
+} auth_gssapi_init_arg;
+
+typedef struct _auth_gssapi_init_res {
+     uint32_t version;
+     gss_buffer_desc client_handle;
+     OM_uint32 gss_major, gss_minor;
+     gss_buffer_desc token;
+     gss_buffer_desc signed_isn;
+} auth_gssapi_init_res;
+
+typedef void (*auth_gssapi_log_badauth_func)
+     (OM_uint32 major,
+		OM_uint32 minor,
+		struct sockaddr_in *raddr,
+		caddr_t data);
+   
+typedef void (*auth_gssapi_log_badverf_func)
+     (gss_name_t client,
+		gss_name_t server,
+		struct svc_req *rqst,
+		struct rpc_msg *msg,
+		caddr_t data);
+
+typedef void (*auth_gssapi_log_miscerr_func)
+     (struct svc_req *rqst,
+		struct rpc_msg *msg,
+		char *error,
+		caddr_t data);
+
+bool_t xdr_gss_buf(XDR *, gss_buffer_t);
+bool_t xdr_authgssapi_creds(XDR *, auth_gssapi_creds *);
+bool_t xdr_authgssapi_init_arg(XDR *, auth_gssapi_init_arg *);
+bool_t xdr_authgssapi_init_res(XDR *, auth_gssapi_init_res *);
+
+bool_t auth_gssapi_wrap_data
+(OM_uint32 *major, OM_uint32 *minor,
+	   gss_ctx_id_t context, uint32_t seq_num, XDR
+	   *out_xdrs, bool_t (*xdr_func)(), caddr_t
+	   xdr_ptr);
+bool_t auth_gssapi_unwrap_data
+(OM_uint32 *major, OM_uint32 *minor,
+	   gss_ctx_id_t context, uint32_t seq_num, XDR
+	   *in_xdrs, bool_t (*xdr_func)(), caddr_t
+	   xdr_ptr);
+
+AUTH *auth_gssapi_create
+(CLIENT *clnt,
+	   OM_uint32 *major_status,
+	   OM_uint32 *minor_status,
+	   gss_cred_id_t claimant_cred_handle,
+	   gss_name_t target_name,
+	   gss_OID mech_type,
+	   OM_uint32 req_flags,
+	   OM_uint32 time_req,
+	   gss_OID *actual_mech_type,
+	   OM_uint32 *ret_flags,
+	   OM_uint32 *time_rec);
+
+AUTH *auth_gssapi_create_default
+(CLIENT *clnt, char *service_name);
+
+void auth_gssapi_display_status
+(char *msg, OM_uint32 major,
+	   OM_uint32 minor); 
+
+bool_t auth_gssapi_seal_seq
+(gss_ctx_id_t context, uint32_t seq_num, gss_buffer_t out_buf);
+
+bool_t auth_gssapi_unseal_seq
+(gss_ctx_id_t context, gss_buffer_t in_buf, uint32_t *seq_num);
+
+bool_t svcauth_gssapi_set_names
+(auth_gssapi_name *names, int num);
+void svcauth_gssapi_unset_names
+(void);
+
+void svcauth_gssapi_set_log_badauth_func
+(auth_gssapi_log_badauth_func func,
+	   caddr_t data);
+void svcauth_gssapi_set_log_badverf_func
+(auth_gssapi_log_badverf_func func,
+	   caddr_t data);
+void svcauth_gssapi_set_log_miscerr_func
+(auth_gssapi_log_miscerr_func func,
+	   caddr_t data);
+
+void svcauth_gss_set_log_badauth_func(auth_gssapi_log_badauth_func,
+				      caddr_t);
+void svcauth_gss_set_log_badverf_func(auth_gssapi_log_badverf_func,
+				      caddr_t);
+void svcauth_gss_set_log_miscerr_func(auth_gssapi_log_miscerr_func,
+				      caddr_t data);
+
+#define GSS_COPY_BUFFER(dest, src) { \
+     (dest).length = (src).length; \
+     (dest).value = (src).value; }
+
+#define GSS_DUP_BUFFER(dest, src) { \
+     (dest).length = (src).length; \
+     (dest).value = (void *) malloc((dest).length); \
+     memcpy((dest).value, (src).value, (dest).length); }
+
+#define GSS_BUFFERS_EQUAL(b1, b2) (((b1).length == (b2).length) && \
+				   !memcmp((b1).value,(b2).value,(b1.length)))
+
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_AUTH_GSSAPI_H) */
diff --git a/krb5-1-6/src/include/gssrpc/auth_unix.h b/krb5-1-6/src/include/gssrpc/auth_unix.h
new file mode 100644
index 000000000..9be442278
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/auth_unix.h
@@ -0,0 +1,80 @@
+/* @(#)auth_unix.h	2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)auth_unix.h 1.5 86/07/16 SMI      */
+
+/*
+ * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef GSSRPC_AUTH_UNIX_H
+#define GSSRPC_AUTH_UNIX_H
+
+GSSRPC__BEGIN_DECLS
+/*
+ * The system is very weak.  The client uses no encryption for  it
+ * credentials and only sends null verifiers.  The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ */
+
+/* The machine name is part of a credential; it may not exceed 255 bytes */
+#define MAX_MACHINE_NAME 255
+
+/* gids compose part of a credential; there may not be more than 16 of them */
+#define NGRPS 16
+
+/*
+ * Unix style credentials.
+ */
+struct authunix_parms {
+	uint32_t	 aup_time;
+	char	*aup_machname;
+	int	 aup_uid;
+	int	 aup_gid;
+	u_int	 aup_len;
+	int	*aup_gids;
+};
+
+extern bool_t xdr_authunix_parms(XDR *, struct authunix_parms *);
+
+/* 
+ * If a response verifier has flavor AUTH_SHORT, 
+ * then the body of the response verifier encapsulates the following structure;
+ * again it is serialized in the obvious fashion.
+ */
+struct short_hand_verf {
+	struct opaque_auth new_cred;
+};
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_AUTH_UNIX_H) */
diff --git a/krb5-1-6/src/include/gssrpc/clnt.h b/krb5-1-6/src/include/gssrpc/clnt.h
new file mode 100644
index 000000000..95450a241
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/clnt.h
@@ -0,0 +1,344 @@
+/* @(#)clnt.h	2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef GSSRPC_CLNT_H
+#define GSSRPC_CLNT_H
+
+GSSRPC__BEGIN_DECLS
+/*
+ * Rpc calls return an enum clnt_stat.  This should be looked at more,
+ * since each implementation is required to live with this (implementation
+ * independent) list of errors.
+ */
+enum clnt_stat {
+	RPC_SUCCESS=0,			/* call succeeded */
+	/*
+	 * local errors
+	 */
+	RPC_CANTENCODEARGS=1,		/* can't encode arguments */
+	RPC_CANTDECODERES=2,		/* can't decode results */
+	RPC_CANTSEND=3,			/* failure in sending call */
+	RPC_CANTRECV=4,			/* failure in receiving result */
+	RPC_TIMEDOUT=5,			/* call timed out */
+	/*
+	 * remote errors
+	 */
+	RPC_VERSMISMATCH=6,		/* rpc versions not compatible */
+	RPC_AUTHERROR=7,		/* authentication error */
+	RPC_PROGUNAVAIL=8,		/* program not available */
+	RPC_PROGVERSMISMATCH=9,		/* program version mismatched */
+	RPC_PROCUNAVAIL=10,		/* procedure unavailable */
+	RPC_CANTDECODEARGS=11,		/* decode arguments error */
+	RPC_SYSTEMERROR=12,		/* generic "other problem" */
+
+	/*
+	 * callrpc & clnt_create errors
+	 */
+	RPC_UNKNOWNHOST=13,		/* unknown host name */
+	RPC_UNKNOWNPROTO=17,		/* unkown protocol */
+
+	/*
+	 * _ create errors
+	 */
+	RPC_PMAPFAILURE=14,		/* the pmapper failed in its call */
+	RPC_PROGNOTREGISTERED=15,	/* remote program is not registered */
+	/*
+	 * unspecified error
+	 */
+	RPC_FAILED=16
+};
+
+
+/*
+ * Error info.
+ */
+struct rpc_err {
+	enum clnt_stat re_status;
+	union {
+		int RE_errno;		/* realated system error */
+		enum auth_stat RE_why;	/* why the auth error occurred */
+		struct {
+			rpcvers_t low;	/* lowest verion supported */
+			rpcvers_t high;	/* highest verion supported */
+		} RE_vers;
+		struct {		/* maybe meaningful if RPC_FAILED */
+			int32_t s1;
+			int32_t s2;
+		} RE_lb;		/* life boot & debugging only */
+	} ru;
+#define	re_errno	ru.RE_errno
+#define	re_why		ru.RE_why
+#define	re_vers		ru.RE_vers
+#define	re_lb		ru.RE_lb
+};
+
+
+/*
+ * Client rpc handle.
+ * Created by individual implementations, see e.g. rpc_udp.c.
+ * Client is responsible for initializing auth, see e.g. auth_none.c.
+ */
+typedef struct CLIENT {
+	AUTH	*cl_auth;			/* authenticator */
+	struct clnt_ops {
+	        /* call remote procedure */
+	        enum clnt_stat	(*cl_call)(struct CLIENT *,
+					   rpcproc_t, xdrproc_t, void *,
+					   xdrproc_t, void *, 
+					   struct timeval);	
+                /* abort a call */
+		void		(*cl_abort)(struct CLIENT *);	
+                /* get specific error code */
+		void		(*cl_geterr)(struct CLIENT *, 
+					     struct rpc_err *);	
+                /* frees results */
+		bool_t		(*cl_freeres)(struct CLIENT *,
+					      xdrproc_t, void *);
+                /* destroy this structure */
+		void		(*cl_destroy)(struct CLIENT *);
+                /* the ioctl() of rpc */
+		/* XXX CITI makes 2nd arg take u_int */
+		bool_t          (*cl_control)(struct CLIENT *, int,
+					      void *);
+	} *cl_ops;
+	void			*cl_private;	/* private stuff */
+} CLIENT;
+
+
+/*
+ * client side rpc interface ops
+ *
+ * Parameter types are:
+ *
+ */
+
+/*
+ * enum clnt_stat
+ * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
+ * 	CLIENT *rh;
+ *	rpcproc_t proc;
+ *	xdrproc_t xargs;
+ *	caddr_t argsp;
+ *	xdrproc_t xres;
+ *	caddr_t resp;
+ *	struct timeval timeout;
+ */
+#define	CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs)	\
+	((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+#define	clnt_call(rh, proc, xargs, argsp, xres, resp, secs)	\
+	((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+
+/*
+ * void
+ * CLNT_ABORT(rh);
+ * 	CLIENT *rh;
+ */
+#define	CLNT_ABORT(rh)	((*(rh)->cl_ops->cl_abort)(rh))
+#define	clnt_abort(rh)	((*(rh)->cl_ops->cl_abort)(rh))
+
+/*
+ * struct rpc_err
+ * CLNT_GETERR(rh);
+ * 	CLIENT *rh;
+ */
+#define	CLNT_GETERR(rh,errp)	((*(rh)->cl_ops->cl_geterr)(rh, errp))
+#define	clnt_geterr(rh,errp)	((*(rh)->cl_ops->cl_geterr)(rh, errp))
+
+
+/*
+ * bool_t
+ * CLNT_FREERES(rh, xres, resp);
+ * 	CLIENT *rh;
+ *	xdrproc_t xres;
+ *	caddr_t resp;
+ */
+#define	CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+#define	clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+
+/*
+ * bool_t
+ * CLNT_CONTROL(cl, request, info)
+ *      CLIENT *cl;
+ *      u_int request;
+ *      char *info;
+ */
+#define	CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+#define	clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+
+/*
+ * control operations that apply to both udp and tcp transports
+ */
+#define CLSET_TIMEOUT       1   /* set timeout (timeval) */
+#define CLGET_TIMEOUT       2   /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR   3   /* get server's address (sockaddr) */
+/*
+ * udp only control operations
+ */
+#define CLSET_RETRY_TIMEOUT 4   /* set retry timeout (timeval) */
+#define CLGET_RETRY_TIMEOUT 5   /* get retry timeout (timeval) */
+/*
+ * new control operations
+ */
+#define CLGET_LOCAL_ADDR    6	/* get local address (sockaddr, getsockname)*/
+
+/*
+ * void
+ * CLNT_DESTROY(rh);
+ * 	CLIENT *rh;
+ */
+#define	CLNT_DESTROY(rh)	((*(rh)->cl_ops->cl_destroy)(rh))
+#define	clnt_destroy(rh)	((*(rh)->cl_ops->cl_destroy)(rh))
+
+
+/*
+ * RPCTEST is a test program which is accessable on every rpc
+ * transport/port.  It is used for testing, performance evaluation,
+ * and network administration.
+ */
+
+#define RPCTEST_PROGRAM		((rpcprog_t)1)
+#define RPCTEST_VERSION		((rpcvers_t)1)
+#define RPCTEST_NULL_PROC	((rpcproc_t)2)
+#define RPCTEST_NULL_BATCH_PROC	((rpcproc_t)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((rpcproc_t)0)
+
+/*
+ * Below are the client handle creation routines for the various
+ * implementations of client side rpc.  They can return NULL if a 
+ * creation failure occurs.
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ * CLIENT *
+ * clntraw_create(prog, vers)
+ *	rpcprog_t prog;
+ *	rpcvers_t vers;
+ */
+extern CLIENT *clntraw_create(rpcprog_t, rpcvers_t);
+
+/*
+ * Generic client creation routine. Supported protocols are "udp" and "tcp"
+ */
+extern CLIENT *clnt_create(char *, rpcprog_t, rpcvers_t, char *);
+
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ *	struct sockaddr_in *raddr;
+ *	rpcprog_t prog;
+ *	rpcvers_t version;
+ *	register int *sockp;
+ *	u_int sendsz;
+ *	u_int recvsz;
+ */
+extern CLIENT *clnttcp_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
+			      int *, u_int, u_int);
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ *	struct sockaddr_in *raddr;
+ *	rpcprog_t program;
+ *	rpcvers_t version;
+ *	struct timeval wait;
+ *	int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ *	struct sockaddr_in *raddr;
+ *	rpcprog_t program;
+ *	rpcvers_t version;
+ *	struct timeval wait;
+ *	int *sockp;
+ *	u_int sendsz;
+ *	u_int recvsz;
+ */
+extern CLIENT *clntudp_create(struct sockaddr_in *, rpcprog_t,
+			      rpcvers_t, struct timeval, int *);
+extern CLIENT *clntudp_bufcreate(struct sockaddr_in *, rpcprog_t,
+				 rpcvers_t, struct timeval, int *,
+				 u_int, u_int);
+
+/*
+ * Print why creation failed
+ */
+void clnt_pcreateerror(char *);	/* stderr */
+char *clnt_spcreateerror(char *);	/* string */
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */ 
+void clnt_perrno(enum clnt_stat);	/* stderr */
+
+/*
+ * Print an English error message, given the client error code
+ */
+void clnt_perror(CLIENT *, char *); 	/* stderr */
+char *clnt_sperror(CLIENT *, char *);	/* string */
+
+/* 
+ * If a creation fails, the following allows the user to figure out why.
+ */
+struct rpc_createerr {
+	enum clnt_stat cf_stat;
+	struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
+};
+
+extern struct rpc_createerr rpc_createerr;
+
+
+
+/*
+ * Copy error message to buffer.
+ */
+char *clnt_sperrno(enum clnt_stat num);	/* string */
+
+#define UDPMSGSIZE	8800	/* rpc imposed limit on udp msg size */
+#define RPCSMALLMSGSIZE	400	/* a more reasonable packet size */
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_CLNT_H) */
diff --git a/krb5-1-6/src/include/gssrpc/netdb.h b/krb5-1-6/src/include/gssrpc/netdb.h
new file mode 100644
index 000000000..69267874e
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/netdb.h
@@ -0,0 +1,51 @@
+#ifndef RPC_NETDB_H
+#define RPC_NETDB_H
+
+/* @(#)netdb.h	2.1 88/07/29 3.9 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*	@(#)rpc.h 1.8 87/07/24 SMI	*/
+#include <gssrpc/types.h>
+/* since the gssrpc library requires that any application using it be
+built with these header files, I am making the decision that any app
+which uses the rpcent routines must use this header file, or something
+compatible (which most <netdb.h> are) --marc */
+
+/* Really belongs in <netdb.h> */
+#ifdef STRUCT_RPCENT_IN_RPC_NETDB_H
+struct rpcent {
+      char    *r_name;        /* name of server for this rpc program */
+      char    **r_aliases;    /* alias list */
+      int     r_number;       /* rpc program number */
+};
+#endif /*STRUCT_RPCENT_IN_RPC_NETDB_H*/
+
+struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent();
+
+#endif
diff --git a/krb5-1-6/src/include/gssrpc/pmap_clnt.h b/krb5-1-6/src/include/gssrpc/pmap_clnt.h
new file mode 100644
index 000000000..808306865
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/pmap_clnt.h
@@ -0,0 +1,81 @@
+/* @(#)pmap_clnt.h	2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * pmap_clnt.h
+ * Supplies C routines to get to portmap services.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef GSSRPC_PMAP_CLNT_H
+#define GSSRPC_PMAP_CLNT_H
+
+/*
+ * Usage:
+ *	success = pmap_set(program, version, protocol, port);
+ *	success = pmap_unset(program, version);
+ *	port = pmap_getport(address, program, version, protocol);
+ *	head = pmap_getmaps(address);
+ *	clnt_stat = pmap_rmtcall(address, program, version, procedure,
+ *		xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ *		(works for udp only.) 
+ * 	clnt_stat = clnt_broadcast(program, version, procedure,
+ *		xdrargs, argsp,	xdrres, resp, eachresult)
+ *		(like pmap_rmtcall, except the call is broadcasted to all
+ *		locally connected nets.  For each valid response received,
+ *		the procedure eachresult is called.  Its form is:
+ *	done = eachresult(resp, raddr)
+ *		bool_t done;
+ *		caddr_t resp;
+ *		struct sockaddr_in raddr;
+ *		where resp points to the results of the call and raddr is the
+ *		address if the responder to the broadcast.
+ */
+
+GSSRPC__BEGIN_DECLS
+extern bool_t		pmap_set(rpcprog_t, rpcvers_t, rpcprot_t, u_int);
+extern bool_t		pmap_unset(rpcprog_t, rpcvers_t);
+extern struct pmaplist	*pmap_getmaps(struct sockaddr_in *);
+enum clnt_stat		pmap_rmtcall(struct sockaddr_in *, rpcprog_t, 
+				     rpcvers_t, rpcproc_t, xdrproc_t, 
+				     caddr_t, xdrproc_t, caddr_t, 
+				     struct timeval, rpcport_t *);
+
+typedef bool_t (*resultproc_t)(caddr_t, struct sockaddr_in *);
+
+enum clnt_stat		clnt_broadcast(rpcprog_t, rpcvers_t, rpcproc_t,
+				       xdrproc_t, caddr_t, xdrproc_t,
+				       caddr_t, resultproc_t);
+extern u_short		pmap_getport(struct sockaddr_in *, 
+				     rpcprog_t, 
+				     rpcvers_t, rpcprot_t);
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_PMAP_CLNT_H) */
diff --git a/krb5-1-6/src/include/gssrpc/pmap_prot.h b/krb5-1-6/src/include/gssrpc/pmap_prot.h
new file mode 100644
index 000000000..8a8802b05
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/pmap_prot.h
@@ -0,0 +1,101 @@
+/* @(#)pmap_prot.h	2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * pmap_prot.h
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The following procedures are supported by the protocol:
+ *
+ * PMAPPROC_NULL() returns ()
+ * 	takes nothing, returns nothing
+ *
+ * PMAPPROC_SET(struct pmap) returns (bool_t)
+ * 	TRUE is success, FALSE is failure.  Registers the tuple
+ *	[prog, vers, prot, port].
+ *
+ * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+ *	TRUE is success, FALSE is failure.  Un-registers pair
+ *	[prog, vers].  prot and port are ignored.
+ *
+ * PMAPPROC_GETPORT(struct pmap) returns (u_short).
+ *	0 is failure.  Otherwise returns the port number where the pair
+ *	[prog, vers] is registered.  It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(rpcprog_t, rpcvers_t, rpcproc_t, string<>)
+ * 	RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * 	Calls the procedure on the local machine.  If it is not registered,
+ *	this procedure is quite; ie it does not return error information!!!
+ *	This procedure only is supported on rpc/udp and calls via
+ *	rpc/udp.  This routine only passes null authentication parameters.
+ *	This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#ifndef GSSRPC_PMAP_PROT_H
+#define GSSRPC_PMAP_PROT_H
+GSSRPC__BEGIN_DECLS
+
+#define PMAPPORT		((u_short)111)
+#define PMAPPROG		((rpcprog_t)100000)
+#define PMAPVERS		((rpcvers_t)2)
+#define PMAPVERS_PROTO		((rpcprot_t)2)
+#define PMAPVERS_ORIG		((rpcvers_t)1)
+#define PMAPPROC_NULL		((rpcproc_t)0)
+#define PMAPPROC_SET		((rpcproc_t)1)
+#define PMAPPROC_UNSET		((rpcproc_t)2)
+#define PMAPPROC_GETPORT	((rpcproc_t)3)
+#define PMAPPROC_DUMP		((rpcproc_t)4)
+#define PMAPPROC_CALLIT		((rpcproc_t)5)
+
+struct pmap {
+	rpcprog_t pm_prog;
+	rpcvers_t pm_vers;
+	rpcprot_t pm_prot;
+	rpcport_t pm_port;
+};
+
+extern bool_t xdr_pmap(XDR *, struct pmap *);
+
+struct pmaplist {
+	struct pmap	pml_map;
+	struct pmaplist *pml_next;
+};
+
+extern bool_t xdr_pmaplist(XDR *, struct pmaplist **);
+
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_PMAP_PROT_H) */
diff --git a/krb5-1-6/src/include/gssrpc/pmap_rmt.h b/krb5-1-6/src/include/gssrpc/pmap_rmt.h
new file mode 100644
index 000000000..48789b453
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/pmap_rmt.h
@@ -0,0 +1,63 @@
+/* @(#)pmap_rmt.h	2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Structures and XDR routines for parameters to and replies from
+ * the portmapper remote-call-service.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#ifndef GSSRPC_PMAP_RMT_H
+#define GSSRPC_PMAP_RMT_H
+GSSRPC__BEGIN_DECLS
+
+struct rmtcallargs {
+	rpcprog_t prog;
+	rpcvers_t vers;
+	rpcproc_t proc;
+	uint32_t arglen;
+	caddr_t args_ptr;
+	xdrproc_t xdr_args;
+};
+
+bool_t xdr_rmtcall_args(XDR *, struct rmtcallargs *);
+
+struct rmtcallres {
+	rpcport_t *port_ptr;
+	uint32_t resultslen;
+	caddr_t results_ptr;
+	xdrproc_t xdr_results;
+};
+
+bool_t xdr_rmtcallres(XDR *, struct rmtcallres *);
+
+GSSRPC__END_DECLS
+#endif /* !defined(GSSRPC_PMAP_RMT_H) */
diff --git a/krb5-1-6/src/include/gssrpc/rename.h b/krb5-1-6/src/include/gssrpc/rename.h
new file mode 100644
index 000000000..b28ae9145
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/rename.h
@@ -0,0 +1,307 @@
+/*
+ * lib/rpc/rename.h
+ *
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * Namespace mangling for various purposes.
+ *
+ * Symbols in the object code need to be renamed to not conflict with
+ * an OS-provided RPC implementation.  Without renaming, the conflicts
+ * can cause problems with things like RPC-enabled NSS
+ * implementations.
+ *
+ * Symbols in headers should not conflict with implementation-reserved
+ * namespace (prefixes "_[A-Z_]" for any purpose; prefix "_"
+ * for file scope identifiers and tag names), or unnecessarily impinge
+ * on user namespace.
+ *
+ * The renaming of the header directory is done to avoid problems when
+ * the OS header files include <rpc/foo.h> and might get ours instead.
+ * OS vendors should replace all the <gssrpc/foo.h> inclusions with
+ * <rpc/foo.h> inclusions, as appropriate.  Additionally, vendors
+ * should probably put some symbols into the implementation namespace.
+ *
+ * For example, inclusion protection should change from "GSSRPC_*_H"
+ * to "_RPC_*_H", struct tags should get "__" prefixes, etc.
+ *
+ * This implementation reserves the object code prefix "gssrpc_".
+ * External names in the RPC API not beginning with "_" get renamed
+ * with the prefix "gssrpc_" via #define, e.g., "foo" -> "gssrpc_foo".
+ * External names in the RPC API beginning with "_" get textually
+ * rewritten, with "#if 0"-disabled #defines mapping them back to
+ * their original forms, e.g., "_foo" is rewrittten to "gssrpc__foo"
+ * in the original files, with an unused "#define gssrpc__foo _foo"
+ * here.
+ */
+
+#ifndef GSSRPC_RENAME_H
+#define GSSRPC_RENAME_H
+
+/* auth.h */
+
+#define xdr_des_block		gssrpc_xdr_des_block
+
+#define authany_wrap		gssrpc_authany_wrap
+#define authany_unwrap		gssrpc_authany_unwrap
+
+#define authunix_create		gssrpc_authunix_create
+#define authunix_create_default	gssrpc_authunix_create_default
+#define authnone_create		gssrpc_authnone_create
+#define authdes_create		gssrpc_authdes_create
+#define xdr_opaque_auth		gssrpc_xdr_opaque_auth
+
+#if 0
+#define gssrpc__null_auth	_null_auth
+#endif
+
+/* auth_gss.c */
+
+#define auth_debug_gss		gssrpc_auth_debug_gss
+#define misc_debug_gss		gssrpc_misc_debug_gss
+
+/* auth_gss.h */
+
+#define xdr_rpc_gss_buf		gssrpc_xdr_rpc_gss_buf
+#define xdr_rpc_gss_cred	gssrpc_xdr_rpc_gss_cred
+#define xdr_rpc_gss_init_args	gssrpc_xdr_rpc_gss_init_args
+#define xdr_rpc_gss_init_res	gssrpc_xdr_rpc_gss_init_res
+#define xdr_rpc_gss_data	gssrpc_xdr_rpc_gss_data
+#define xdr_rpc_gss_wrap_data	gssrpc_xdr_rpc_gss_wrap_data
+#define xdr_rpc_gss_unwrap_data	gssrpc_xdr_rpc_gss_unwrap_data
+
+#define authgss_create		gssrpc_authgss_create
+#define authgss_create_default	gssrpc_authgss_create_default
+#define authgss_get_private_data	gssrpc_authgss_get_private_data
+#define authgss_service		gssrpc_authgss_service
+
+#ifdef GSSRPC__IMPL
+#define log_debug		gssrpc_log_debug
+#define log_status		gssrpc_log_status
+#define	log_hexdump		gssrpc_log_hexdump
+#endif
+
+/* auth_gssapi.c */
+
+#define auth_debug_gssapi	gssrpc_auth_debug_gssapi
+#define misc_debug_gssapi	gssrpc_misc_debug_gssapi
+
+/* auth_gssapi.h */
+
+#define xdr_gss_buf		gssrpc_xdr_gss_buf
+#define xdr_authgssapi_creds	gssrpc_xdr_authgssapi_creds
+#define xdr_authgssapi_init_arg	gssrpc_xdr_authgssapi_init_arg
+#define xdr_authgssapi_init_res	gssrpc_xdr_authgssapi_init_res
+
+#define auth_gssapi_wrap_data	gssrpc_auth_gssapi_wrap_data
+#define auth_gssapi_unwrap_data	gssrpc_auth_gssapi_unwrap_data
+#define auth_gssapi_create	gssrpc_auth_gssapi_create
+#define auth_gssapi_create_default	gssrpc_auth_gssapi_create_default
+#define auth_gssapi_display_status	gssrpc_auth_gssapi_display_status
+#define auth_gssapi_seal_seq	gssrpc_auth_gssapi_seal_seq
+#define auth_gssapi_unseal_seq	gssrpc_auth_gssapi_unseal_seq
+
+#define svcauth_gssapi_set_names	gssrpc_svcauth_gssapi_set_names
+#define svcauth_gssapi_unset_names	gssrpc_svcauth_gssapi_unset_names
+#define svcauth_gssapi_set_log_badauth_func	gssrpc_svcauth_gssapi_set_log_badauth_func
+#define svcauth_gssapi_set_log_badverf_func	gssrpc_svcauth_gssapi_set_log_badverf_func
+#define svcauth_gssapi_set_log_miscerr_func	gssrpc_svcauth_gssapi_set_log_miscerr_func
+
+#define svcauth_gss_set_log_badauth_func	gssrpc_svcauth_gss_set_log_badauth_func
+#define svcauth_gss_set_log_badverf_func	gssrpc_svcauth_gss_set_log_badverf_func
+#define svcauth_gss_set_log_miscerr_func	gssrpc_svcauth_gss_set_log_miscerr_func
+
+/* auth_unix.h */
+
+#define xdr_authunix_parms	gssrpc_xdr_authunix_parms
+
+/* clnt.h */
+
+#define clntraw_create		gssrpc_clntraw_create
+#define clnt_create		gssrpc_clnt_create
+#define clnttcp_create		gssrpc_clnttcp_create
+#define clntudp_create		gssrpc_clntudp_create
+#define clntudp_bufcreate	gssrpc_clntudp_bufcreate
+#define clnt_pcreateerror	gssrpc_clnt_pcreateerror
+#define clnt_spcreateerror	gssrpc_clnt_spcreateerror
+#define clnt_perrno		gssrpc_clnt_perrno
+#define clnt_perror		gssrpc_clnt_perror
+#define clnt_sperror		gssrpc_clnt_sperror
+/* XXX do we need to rename the struct? */
+#define rpc_createerr		gssrpc_rpc_createrr
+#define clnt_sperrno		gssrpc_clnt_sperrno
+
+/* pmap_clnt.h */
+
+#define pmap_set		gssrpc_pmap_set
+#define pmap_unset		gssrpc_pmap_unset
+#define pmap_getmaps		gssrpc_pmap_getmaps
+#define pmap_rmtcall		gssrpc_pmap_rmtcall
+#define clnt_broadcast		gssrpc_clnt_broadcast
+#define pmap_getport		gssrpc_pmap_getport
+
+/* pmap_prot.h */
+
+#define xdr_pmap		gssrpc_xdr_pmap
+#define xdr_pmaplist		gssrpc_xdr_pmaplist
+
+/* pmap_rmt.h */
+
+#define xdr_rmtcall_args	gssrpc_xdr_rmtcall_args
+#define xdr_rmtcallres		gssrpc_xdr_rmtcallres
+
+/* rpc.h */
+
+#define get_myaddress		gssrpc_get_myaddress
+#define bindresvport		gssrpc_bindresvport
+#define callrpc			gssrpc_callrpc
+#define getrpcport		gssrpc_getrpcport
+
+#if 0
+#define gssrpc__rpc_getdtablesize	_rpc_getdtablesize
+#endif
+
+/* rpc_msg.h */
+
+#define xdr_callmsg		gssrpc_xdr_callmsg
+#define xdr_callhdr		gssrpc_xdr_callhdr
+#define xdr_replymsg		gssrpc_xdr_replymsg
+#define xdr_accepted_reply	gssrpc_xdr_accepted_reply
+#define xdr_rejected_reply	gssrpc_xdr_rejected_reply
+
+#if 0
+#define gssrpc__seterr_reply	_seterr_reply
+#endif
+
+/* svc.h */
+
+#define svc_register		gssrpc_svc_register
+#define registerrpc             gssrpc_registerrpc
+#define svc_unregister		gssrpc_svc_unregister
+#define xprt_register		gssrpc_xprt_register
+#define xprt_unregister		gssrpc_xprt_unregister
+
+#define svc_sendreply		gssrpc_svc_sendreply
+#define svcerr_decode		gssrpc_svcerr_decode
+#define svcerr_weakauth		gssrpc_svcerr_weakauth
+#define svcerr_noproc		gssrpc_svcerr_noproc
+#define svcerr_progvers		gssrpc_svcerr_progvers
+#define svcerr_auth		gssrpc_svcerr_auth
+#define svcerr_noprog		gssrpc_svcerr_noprog
+#define svcerr_systemerr	gssrpc_svcerr_systemerr
+
+#define svc_maxfd		gssrpc_svc_maxfd
+#define svc_fdset		gssrpc_svc_fdset
+#define svc_fds			gssrpc_svc_fds
+
+#define rpctest_service		gssrpc_rpctest_service
+
+#define svc_getreq		gssrpc_svc_getreq
+#define svc_getreqset		gssrpc_svc_getreqset
+#define svc_getreqset2		gssrpc_svc_getreqset2
+#define svc_run			gssrpc_svc_run
+
+#define svcraw_create		gssrpc_svcraw_create
+
+#define svcudp_create		gssrpc_svcudp_create
+#define svcudp_bufcreate	gssrpc_svcudp_bufcreate
+#define svcudp_enablecache	gssrpc_svcudp_enablecache
+
+#define svctcp_create		gssrpc_svctcp_create
+
+#define svcfd_create            gssrpc_svcfd_create
+
+/* svc_auth.h */
+
+#define svc_auth_none_ops	gssrpc_svc_auth_none_ops
+#define svc_auth_gssapi_ops	gssrpc_svc_auth_gssapi_ops
+#define svc_auth_gss_ops	gssrpc_svc_auth_gss_ops
+
+#define svcauth_gss_set_svc_name	gssrpc_svcauth_gss_set_svc_name
+#define svcauth_gss_get_principal	gssrpc_svcauth_gss_get_principal
+
+#if 0
+#define gssrpc__authenticate	_authenticate
+#define gssrpc__svcauth_none	_svcauth_none
+#define gssrpc__svcauth_unix	_svcauth_unix
+#define gssrpc__svcauth_short	_svcauth_short
+#define gssrpc__svcauth_gssapi	_svcauth_gssapi
+#define gssrpc__svcauth_gss	_svcauth_gss
+#endif
+
+/* svc_auth_gss.c */
+
+#define svc_debug_gss		gssrpc_svc_debug_gss
+
+#define svcauth_gss_creds	gssrpc_svc_auth_gss_creds
+
+/* svc_auth_gssapi.c */
+
+#define svc_debug_gssapi	gssrpc_svc_debug_gssapi
+
+/* svc_auth_none.c */
+
+#define svc_auth_none		gssrpc_svc_auth_none
+
+/* xdr.h */
+
+#define xdr_void	gssrpc_xdr_void
+#define xdr_int		gssrpc_xdr_int
+#define xdr_u_int	gssrpc_xdr_u_int
+#define xdr_long	gssrpc_xdr_long
+#define xdr_u_long	gssrpc_xdr_u_long
+#define xdr_short	gssrpc_xdr_short
+#define xdr_u_short	gssrpc_xdr_u_short
+#define xdr_bool	gssrpc_xdr_bool
+#define xdr_enum	gssrpc_xdr_enum
+#define xdr_array	gssrpc_xdr_array
+#define xdr_bytes	gssrpc_xdr_bytes
+#define xdr_opaque	gssrpc_xdr_opaque
+#define xdr_string	gssrpc_xdr_string
+#define xdr_union	gssrpc_xdr_union
+#define xdr_char	gssrpc_xdr_char
+#define xdr_u_char	gssrpc_xdr_u_char
+#define xdr_vector	gssrpc_xdr_vector
+#define xdr_float	gssrpc_xdr_float
+#define xdr_double	gssrpc_xdr_double
+#define xdr_reference	gssrpc_xdr_reference
+#define xdr_pointer	gssrpc_xdr_pointer
+#define xdr_wrapstring	gssrpc_xdr_wrapstring
+#define xdr_free	gssrpc_xdr_free
+
+#define xdr_netobj	gssrpc_xdr_netobj
+#define xdr_int32	gssrpc_xdr_int32
+#define xdr_u_int32	gssrpc_xdr_u_int32
+
+#define xdralloc_create		gssrpc_xdralloc_create
+#define xdralloc_release	gssrpc_xdralloc_release
+#define xdralloc_getdata	gssrpc_xdralloc_getdata
+
+#define xdrmem_create		gssrpc_xdrmem_create
+#define xdrstdio_create		gssrpc_xdrstdio_create
+#define xdrrec_create		gssrpc_xdrrec_create
+#define xdrrec_endofrecord	gssrpc_xdrrec_endofrecord
+#define xdrrec_skiprecord	gssrpc_xdrrec_skiprecord
+#define xdrrec_eof		gssrpc_xdrrec_eof
+
+#endif /* !defined(GSSRPC_RENAME_H) */
diff --git a/krb5-1-6/src/include/gssrpc/rpc.h b/krb5-1-6/src/include/gssrpc/rpc.h
new file mode 100644
index 000000000..0f1730d18
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/rpc.h
@@ -0,0 +1,99 @@
+/* @(#)rpc.h	2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+#ifndef GSSRPC_RPC_H
+#define GSSRPC_RPC_H
+
+#include <gssrpc/types.h>		/* some typedefs */
+#include <netinet/in.h>
+
+/* external data representation interfaces */
+#include <gssrpc/xdr.h>		/* generic (de)serializer */
+
+/* Client side only authentication */
+#include <gssrpc/auth.h>		/* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include <gssrpc/clnt.h>		/* generic rpc stuff */
+
+/* semi-private protocol headers */
+#include <gssrpc/rpc_msg.h>	/* protocol for rpc messages */
+#include <gssrpc/auth_unix.h>	/* protocol for unix style cred */
+#include <gssrpc/auth_gss.h>	/* RPCSEC_GSS */
+/*
+ *  Uncomment-out the next line if you are building the rpc library with    
+ *  DES Authentication (see the README file in the secure_rpc/ directory).
+ */
+#if 0
+#include <gssrpc/auth_des.h>	protocol for des style cred
+#endif
+
+/* Server side only remote procedure callee */
+#include <gssrpc/svc_auth.h>	/* service side authenticator */
+#include <gssrpc/svc.h>		/* service manager and multiplexer */
+
+/*
+ * Punt the rpc/netdb.h everywhere because it just makes things much more
+ * difficult.  We don't use the *rpcent functions anyway.
+ */
+#if 0
+/*
+ * COMMENT OUT THE NEXT INCLUDE IF RUNNING ON SUN OS OR ON A VERSION
+ * OF UNIX BASED ON NFSSRC.  These systems will already have the structures
+ * defined by <rpc/netdb.h> included in <netdb.h>.
+ */
+/* routines for parsing /etc/rpc */
+#if 0 /* netdb.h already included in rpc/types.h */
+#include <netdb.h>
+#endif
+
+#include <gssrpc/netdb.h>	/* structures and routines to parse /etc/rpc */
+#endif
+
+/*
+ * get the local host's IP address without consulting
+ * name service library functions
+ */
+GSSRPC__BEGIN_DECLS
+extern int get_myaddress(struct sockaddr_in *);
+extern int bindresvport(int, struct sockaddr_in *);
+extern int callrpc(char *, rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t,
+		   char *, xdrproc_t , char *);
+extern int getrpcport(char *, rpcprog_t, rpcvers_t, rpcprot_t);
+extern int gssrpc__rpc_dtablesize(void);
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_RPC_H) */
diff --git a/krb5-1-6/src/include/gssrpc/rpc_msg.h b/krb5-1-6/src/include/gssrpc/rpc_msg.h
new file mode 100644
index 000000000..62d632967
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/rpc_msg.h
@@ -0,0 +1,205 @@
+/* @(#)rpc_msg.h	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)rpc_msg.h 1.7 86/07/16 SMI      */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef GSSRPC_RPC_MSG_H
+#define GSSRPC_RPC_MSG_H
+
+GSSRPC__BEGIN_DECLS
+
+#define RPC_MSG_VERSION		((uint32_t) 2)
+#define RPC_SERVICE_PORT	((u_short) 2048)
+
+/*
+ * Bottom up definition of an rpc message.
+ * NOTE: call and reply use the same overall stuct but
+ * different parts of unions within it.
+ */
+
+enum msg_type {
+	CALL=0,
+	REPLY=1
+};
+
+enum reply_stat {
+	MSG_ACCEPTED=0,
+	MSG_DENIED=1
+};
+
+enum accept_stat {
+	SUCCESS=0,
+	PROG_UNAVAIL=1,
+	PROG_MISMATCH=2,
+	PROC_UNAVAIL=3,
+	GARBAGE_ARGS=4,
+	SYSTEM_ERR=5
+};
+
+enum reject_stat {
+	RPC_MISMATCH=0,
+	AUTH_ERROR=1
+};
+
+/*
+ * Reply part of an rpc exchange
+ */
+
+/*
+ * Reply to an rpc request that was accepted by the server.
+ * Note: there could be an error even though the request was
+ * accepted.
+ */
+struct accepted_reply {
+	struct opaque_auth	ar_verf;
+	enum accept_stat	ar_stat;
+	union {
+		struct {
+			rpcvers_t	low;
+			rpcvers_t	high;
+		} AR_versions;
+		struct {
+			caddr_t	where;
+			xdrproc_t proc;
+		} AR_results;
+		/* and many other null cases */
+	} ru;
+#define	ar_results	ru.AR_results
+#define	ar_vers		ru.AR_versions
+};
+
+/*
+ * Reply to an rpc request that was rejected by the server.
+ */
+struct rejected_reply {
+	enum reject_stat rj_stat;
+	union {
+		struct {
+			rpcvers_t low;
+			rpcvers_t high;
+		} RJ_versions;
+		enum auth_stat RJ_why;  /* why authentication did not work */
+	} ru;
+#define	rj_vers	ru.RJ_versions
+#define	rj_why	ru.RJ_why
+};
+
+/*
+ * Body of a reply to an rpc request.
+ */
+struct reply_body {
+	enum reply_stat rp_stat;
+	union {
+		struct accepted_reply RP_ar;
+		struct rejected_reply RP_dr;
+	} ru;
+#define	rp_acpt	ru.RP_ar
+#define	rp_rjct	ru.RP_dr
+};
+
+/*
+ * Body of an rpc request call.
+ */
+struct call_body {
+	rpcvers_t cb_rpcvers;	/* must be equal to two */
+	rpcprog_t cb_prog;
+	rpcvers_t cb_vers;
+	rpcproc_t cb_proc;
+	struct opaque_auth cb_cred;
+	struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+	uint32_t		rm_xid;
+	enum msg_type		rm_direction;
+	union {
+		struct call_body RM_cmb;
+		struct reply_body RM_rmb;
+	} ru;
+#define	rm_call		ru.RM_cmb
+#define	rm_reply	ru.RM_rmb
+};
+#define	acpted_rply	ru.RM_rmb.ru.RP_ar
+#define	rjcted_rply	ru.RM_rmb.ru.RP_dr
+
+
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * 	XDR *xdrs;
+ * 	struct rpc_msg *cmsg;
+ */
+extern bool_t	xdr_callmsg(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * 	XDR *xdrs;
+ * 	struct rpc_msg *cmsg;
+ */
+extern bool_t	xdr_callhdr(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * 	XDR *xdrs;
+ * 	struct rpc_msg *rmsg;
+ */
+extern bool_t	xdr_replymsg(XDR *, struct rpc_msg *);
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * 	struct rpc_msg *msg;
+ * 	struct rpc_err *error;
+ */
+/*
+ * RENAMED: should be _seterr_reply or __seterr_reply if we can use
+ * reserved namespace.
+ */
+extern void	gssrpc__seterr_reply(struct rpc_msg *, struct rpc_err *);
+
+/* XDR the MSG_ACCEPTED part of a reply message union */
+extern bool_t	xdr_accepted_reply(XDR *, struct accepted_reply *);
+
+/* XDR the MSG_DENIED part of a reply message union */
+extern bool_t	xdr_rejected_reply(XDR *, struct rejected_reply *);
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_RPC_MSG_H) */
diff --git a/krb5-1-6/src/include/gssrpc/svc.h b/krb5-1-6/src/include/gssrpc/svc.h
new file mode 100644
index 000000000..b66353540
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/svc.h
@@ -0,0 +1,337 @@
+/* @(#)svc.h	2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef GSSRPC_SVC_H
+#define GSSRPC_SVC_H
+
+#include <gssrpc/svc_auth.h>
+
+GSSRPC__BEGIN_DECLS
+/*
+ * This interface must manage two items concerning remote procedure calling:
+ *
+ * 1) An arbitrary number of transport connections upon which rpc requests
+ * are received.  The two most notable transports are TCP and UDP;  they are
+ * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
+ * they in turn call xprt_register and xprt_unregister.
+ *
+ * 2) An arbitrary number of locally registered services.  Services are
+ * described by the following four data: program number, version number,
+ * "service dispatch" function, a transport handle, and a boolean that
+ * indicates whether or not the exported program should be registered with a
+ * local binder service;  if true the program's number and version and the
+ * port number from the transport handle are registered with the binder.
+ * These data are registered with the rpc svc system via svc_register.
+ *
+ * A service's dispatch function is called whenever an rpc request comes in
+ * on a transport.  The request's program and version numbers must match
+ * those of the registered service.  The dispatch function is passed two
+ * parameters, struct svc_req * and SVCXPRT *, defined below.
+ */
+
+enum xprt_stat {
+	XPRT_DIED,
+	XPRT_MOREREQS,
+	XPRT_IDLE
+};
+
+/*
+ * Server side transport handle
+ */
+typedef struct SVCXPRT {
+	int		xp_sock;
+	u_short		xp_port;	 /* associated port number */
+	struct xp_ops {
+	    /* receive incomming requests */
+	    bool_t	(*xp_recv)(struct SVCXPRT *, struct rpc_msg *);
+	    /* get transport status */
+	    enum xprt_stat (*xp_stat)(struct SVCXPRT *); 
+	    /* get arguments */
+	    bool_t	(*xp_getargs)(struct SVCXPRT *, xdrproc_t,
+				      void *);
+	    /* send reply */
+	    bool_t	(*xp_reply)(struct SVCXPRT *,
+				    struct rpc_msg *);	 
+            /* free mem allocated for args */
+	    bool_t	(*xp_freeargs)(struct SVCXPRT *, xdrproc_t,
+				       void *);
+	    /* destroy this struct */
+	    void	(*xp_destroy)(struct SVCXPRT *); 
+	} *xp_ops;
+	int		xp_addrlen;	 /* length of remote address */
+	struct sockaddr_in xp_raddr;	 /* remote address */
+	struct opaque_auth xp_verf;	 /* raw response verifier */
+	SVCAUTH		*xp_auth;	 /* auth flavor of current req */
+	void		*xp_p1;		 /* private */
+	void		*xp_p2;		 /* private */
+	int		xp_laddrlen;	 /* lenght of local address */
+	struct sockaddr_in xp_laddr;	 /* local address */
+} SVCXPRT;
+
+/*
+ *  Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Operations defined on an SVCXPRT handle
+ *
+ * SVCXPRT		*xprt;
+ * struct rpc_msg	*msg;
+ * xdrproc_t		 xargs;
+ * caddr_t		 argsp;
+ */
+#define SVC_RECV(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+#define svc_recv(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+
+#define SVC_STAT(xprt)					\
+	(*(xprt)->xp_ops->xp_stat)(xprt)
+#define svc_stat(xprt)					\
+	(*(xprt)->xp_ops->xp_stat)(xprt)
+
+#define SVC_GETARGS(xprt, xargs, argsp)			\
+	(*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+#define svc_getargs(xprt, xargs, argsp)			\
+	(*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+
+#define SVC_GETARGS_REQ(xprt, req, xargs, argsp)	\
+	(*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp))
+#define svc_getargs_req(xprt, req, xargs, argsp)	\
+	(*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp))
+
+#define SVC_REPLY(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+#define svc_reply(xprt, msg)				\
+	(*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+
+#define SVC_REPLY_REQ(xprt, req, msg)			\
+	(*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg))
+#define svc_reply_req(xprt, msg)			\
+	(*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg))
+
+#define SVC_FREEARGS(xprt, xargs, argsp)		\
+	(*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+#define svc_freeargs(xprt, xargs, argsp)		\
+	(*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+
+#define SVC_DESTROY(xprt)				\
+	(*(xprt)->xp_ops->xp_destroy)(xprt)
+#define svc_destroy(xprt)				\
+	(*(xprt)->xp_ops->xp_destroy)(xprt)
+
+
+/*
+ * Service request
+ */
+struct svc_req {
+	rpcprog_t		rq_prog;	/* service program number */
+	rpcvers_t		rq_vers;	/* service protocol version */
+	rpcproc_t		rq_proc;	/* the desired procedure */
+	struct opaque_auth rq_cred;	/* raw creds from the wire */
+	void *		rq_clntcred;	/* read only cooked client cred */
+	void *		rq_svccred;	/* read only svc cred/context */
+	void *		rq_clntname;	/* read only client name */
+	SVCXPRT		*rq_xprt;	/* associated transport */
+	/* The request's auth flavor *should* be here, but the svc_req 	*/
+	/* isn't passed around everywhere it is necessary.  The 	*/
+	/* transport *is* passed around, so the auth flavor it stored 	*/
+	/* there.  This means that the transport must be single 	*/
+	/* threaded, but other parts of SunRPC already require that. 	*/
+	/*SVCAUTH		*rq_auth;	 associated auth flavor */
+};
+
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ *	SVCXPRT *xprt;
+ *	rpcprog_t prog;
+ *	rpcvers_t vers;
+ *	void (*dispatch)();
+ *	int protocol;  like TCP or UDP, zero means do not register 
+ *
+ * registerrpc(prog, vers, proc, routine, inproc, outproc)
+ * 	returns 0 upon success, -1 if error.
+ */
+extern bool_t	svc_register(SVCXPRT *, rpcprog_t, rpcvers_t,
+			     void (*)(struct svc_req *, SVCXPRT *), int);
+
+extern int registerrpc(rpcprog_t, rpcvers_t, rpcproc_t,
+		       char *(*)(void *),
+		       xdrproc_t, xdrproc_t);
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ *	rpcprog_t prog;
+ *	rpcvers_t vers;
+ */
+extern void	svc_unregister(rpcprog_t, rpcvers_t);
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ *	SVCXPRT *xprt;
+ */
+extern void	xprt_register(SVCXPRT *);
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ *	SVCXPRT *xprt;
+ */
+extern void	xprt_unregister(SVCXPRT *);
+
+
+/*
+ * When the service routine is called, it must first check to see if
+ * it knows about the procedure; if not, it should call svcerr_noproc
+ * and return.  If so, it should deserialize its arguments via
+ * SVC_GETARGS or the new SVC_GETARGS_REQ (both defined above).  If
+ * the deserialization does not work, svcerr_decode should be called
+ * followed by a return.  Successful decoding of the arguments should
+ * be followed the execution of the procedure's code and a call to
+ * svc_sendreply or the new svc_sendreply_req.
+ *
+ * Also, if the service refuses to execute the procedure due to too-
+ * weak authentication parameters, svcerr_weakauth should be called.
+ * Note: do not confuse access-control failure with weak authentication!
+ *
+ * NB: In pure implementations of rpc, the caller always waits for a reply
+ * msg.  This message is sent when svc_sendreply is called.  
+ * Therefore pure service implementations should always call
+ * svc_sendreply even if the function logically returns void;  use
+ * xdr.h - xdr_void for the xdr routine.  HOWEVER, tcp based rpc allows
+ * for the abuse of pure rpc via batched calling or pipelining.  In the
+ * case of a batched call, svc_sendreply should NOT be called since
+ * this would send a return message, which is what batching tries to avoid.
+ * It is the service/protocol writer's responsibility to know which calls are
+ * batched and which are not.  Warning: responding to batch calls may
+ * deadlock the caller and server processes!
+ */
+
+extern bool_t	svc_sendreply(SVCXPRT *, xdrproc_t, caddr_t);
+extern void	svcerr_decode(SVCXPRT *);
+extern void	svcerr_weakauth(SVCXPRT *);
+extern void	svcerr_noproc(SVCXPRT *);
+extern void	svcerr_progvers(SVCXPRT *, rpcvers_t, rpcvers_t);
+extern void	svcerr_auth(SVCXPRT *, enum auth_stat);
+extern void	svcerr_noprog(SVCXPRT *);
+extern void	svcerr_systemerr(SVCXPRT *);
+
+/*
+ * Lowest level dispatching -OR- who owns this process anyway.
+ * Somebody has to wait for incoming requests and then call the correct
+ * service routine.  The routine svc_run does infinite waiting; i.e.,
+ * svc_run never returns.
+ * Since another (co-existant) package may wish to selectively wait for
+ * incoming calls or other events outside of the rpc architecture, the
+ * routine svc_getreq is provided.  It must be passed readfds, the
+ * "in-place" results of a select system call (see select, section 2).
+ */
+
+/*
+ * Global keeper of rpc service descriptors in use
+ * dynamic; must be inspected before each call to select 
+ */
+extern int svc_maxfd;
+#ifdef FD_SETSIZE
+extern fd_set svc_fdset;
+/* RENAMED */
+#define gssrpc_svc_fds gsssrpc_svc_fdset.fds_bits[0]	/* compatibility */
+#else
+extern int svc_fds;
+#endif /* def FD_SETSIZE */
+extern int svc_maxfd;
+
+/*
+ * a small program implemented by the svc_rpc implementation itself;
+ * also see clnt.h for protocol numbers.
+ */
+extern void rpctest_service();
+
+extern void	svc_getreq(int);
+#ifdef FD_SETSIZE
+extern void	svc_getreqset(fd_set *);/* takes fdset instead of int */
+extern void	svc_getreqset2(fd_set *, int);
+#else
+extern void	svc_getreqset(int *);
+#endif
+extern void	svc_run(void); 	 /* never returns */
+
+/*
+ * Socket to use on svcxxx_create call to get default socket
+ */
+#define	RPC_ANYSOCK	-1
+
+/*
+ * These are the existing service side transport implementations
+ */
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+extern SVCXPRT *svcraw_create(void);
+
+/*
+ * Udp based rpc.
+ */
+extern SVCXPRT *svcudp_create(int);
+extern SVCXPRT *svcudp_bufcreate(int, u_int, u_int);
+extern int svcudp_enablecache(SVCXPRT *, uint32_t);
+
+/*
+ * Tcp based rpc.
+ */
+extern SVCXPRT *svctcp_create(int, u_int, u_int);
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+extern SVCXPRT *svcfd_create(int, u_int, u_int);
+
+/* XXX add auth_gsapi_log_*? */
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_SVC_H) */
diff --git a/krb5-1-6/src/include/gssrpc/svc_auth.h b/krb5-1-6/src/include/gssrpc/svc_auth.h
new file mode 100644
index 000000000..541aa4514
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/svc_auth.h
@@ -0,0 +1,117 @@
+/* @(#)svc_auth.h	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)svc_auth.h 1.6 86/07/16 SMI      */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ * 
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Interface to server-side authentication flavors.
+ */
+
+#ifndef GSSRPC_SVC_AUTH_H
+#define GSSRPC_SVC_AUTH_H
+
+#include <gssapi/gssapi.h>
+
+GSSRPC__BEGIN_DECLS
+
+struct svc_req;
+
+typedef struct SVCAUTH {
+	struct svc_auth_ops {
+		int	(*svc_ah_wrap)(struct SVCAUTH *, XDR *, xdrproc_t,
+				       caddr_t);
+		int	(*svc_ah_unwrap)(struct SVCAUTH *, XDR *, xdrproc_t,
+					 caddr_t);
+		int	(*svc_ah_destroy)(struct SVCAUTH *);
+	} *svc_ah_ops;
+	void * svc_ah_private;
+} SVCAUTH;
+
+#ifdef GSSRPC__IMPL
+
+extern SVCAUTH svc_auth_none;
+
+extern struct svc_auth_ops svc_auth_none_ops;
+extern struct svc_auth_ops svc_auth_gssapi_ops;
+extern struct svc_auth_ops svc_auth_gss_ops;
+
+/*
+ * Server side authenticator
+ */
+/* RENAMED: should be _authenticate. */
+extern enum auth_stat gssrpc__authenticate(struct svc_req *rqst,
+	struct rpc_msg *msg, bool_t *no_dispatch);
+
+#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+     ((*((auth)->svc_ah_ops->svc_ah_wrap))(auth, xdrs, xfunc, xwhere))
+#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+     ((*((auth)->svc_ah_ops->svc_ah_unwrap))(auth, xdrs, xfunc, xwhere))
+#define SVCAUTH_DESTROY(auth) \
+     ((*((auth)->svc_ah_ops->svc_ah_destroy))(auth))
+
+/* no authentication */
+/* RENAMED: should be _svcauth_none. */
+enum auth_stat gssrpc__svcauth_none(struct svc_req *,
+	struct rpc_msg *, bool_t *);
+/* unix style (uid, gids) */
+/* RENAMED: shoudl be _svcauth_unix. */
+enum auth_stat gssrpc__svcauth_unix(struct svc_req *,
+	struct rpc_msg *, bool_t *);
+/* short hand unix style */
+/* RENAMED: should be _svcauth_short. */
+enum auth_stat gssrpc__svcauth_short(struct svc_req *,
+	struct rpc_msg *, bool_t *);
+/* GSS-API style */
+/* RENAMED: should be _svcauth_gssapi. */
+enum auth_stat gssrpc__svcauth_gssapi(struct svc_req *,
+	struct rpc_msg *, bool_t *);
+/* RPCSEC_GSS */
+enum auth_stat gssrpc__svcauth_gss(struct svc_req *,
+	struct rpc_msg *, bool_t *);
+
+#endif /* defined(GSSRPC__IMPL) */
+
+/*
+ * Approved way of getting principal of caller
+ */
+char *svcauth_gss_get_principal(SVCAUTH *auth);
+/*
+ * Approved way of setting server principal
+ */
+bool_t svcauth_gss_set_svc_name(gss_name_t name);
+
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_SVC_AUTH_H) */
diff --git a/krb5-1-6/src/include/gssrpc/types.hin b/krb5-1-6/src/include/gssrpc/types.hin
new file mode 100644
index 000000000..ed612f1f5
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/types.hin
@@ -0,0 +1,175 @@
+/* @(#)types.h	2.3 88/08/15 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)types.h 1.18 87/07/24 SMI      */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef GSSRPC_TYPES_H
+#define GSSRPC_TYPES_H
+
+#include <sys/types.h>
+
+@GSSRPC__SYS_SELECT_H@
+@GSSRPC__SYS_TIME_H@
+@GSSRPC__UNISTD_H@
+
+/*
+ * Try to get MAXHOSTNAMELEN from somewhere.
+ */
+@GSSRPC__SYS_PARAM_H@
+@GSSRPC__NETDB_H@
+
+/* Get htonl(), ntohl(), etc. */
+#include <netinet/in.h>
+
+#include <stdlib.h>
+
+/*
+ * Pull in typedefs for fixed-width integers somehow, if they weren't
+ * in sys/types.h.
+ */
+@GSSRPC__STDINT_H@
+@GSSRPC__INTTYPES_H@
+/* Define if there is no uint32_t in system headers. */
+@GSSRPC__FAKE_UINT32@
+
+#include <limits.h>
+
+#ifndef GSSRPC__BEGIN_DECLS
+#ifdef __cplusplus
+#define GSSRPC__BEGIN_DECLS	extern "C" {
+#define GSSRPC__END_DECLS	}
+#else
+#define GSSRPC__BEGIN_DECLS
+#define GSSRPC__END_DECLS
+#endif
+#endif
+
+GSSRPC__BEGIN_DECLS
+
+#if defined(CHAR_BIT) && CHAR_BIT != 8
+#error "Bytes must be exactly 8 bits."
+#endif
+
+/*
+ * If no uint32_t in system headers, fake it by looking for a 32-bit
+ * two's-complement type.  Yes, this stomps on POSIX namespace, but if
+ * we get here, we're on a system that's far from being
+ * POSIX-compliant anyway.
+ */
+#if GSSRPC__FAKE_UINT32
+#if (UINT_MAX == 0xffffffffUL) && (INT_MAX == 0x7fffffffL) \
+	&& (INT_MIN == -INT_MAX-1)
+typedef int		int32_t;
+typedef unsigned int	uint32_t;
+#else
+#if (ULONG_MAX == 0xffffffffUL) && (LONG_MAX == 0x7fffffffL) \
+	&& (LONG_MIN == -LONG_MAX-1)
+typedef long		int32_t;
+typedef unsigned long	uint32_t;
+#else
+#if (USHRT_MAX == 0xffffffffUL) && (SHRT_MAX == 0x7fffffffL) \
+	&& (SHRT_MIN == -SHRT_MAX-1)
+typedef short		int32_t;
+typedef unsigned short	uint32_t;
+#else
+#error "Can't fake up uint32_t."
+#endif
+#endif
+#endif
+#endif /* GSSRPC__FAKE_UINT32 */
+
+#if (LONG_MIN != -LONG_MAX-1) || (INT_MIN != -INT_MAX-1) \
+	|| (SHRT_MIN != -SHRT_MAX-1)
+#error "Integer types must be two's-complement."
+#endif
+
+/* Define if we need to fake up some BSD type aliases. */
+#ifndef GSSRPC__BSD_TYPEALIASES	/* Allow application to override. */
+@GSSRPC__BSD_TYPEALIASES@
+#endif
+#if GSSRPC__BSD_TYPEALIASES
+typedef unsigned char	u_char;
+typedef unsigned short	u_short;
+typedef unsigned int	u_int;
+typedef unsigned long	u_long;
+#endif
+
+typedef uint32_t	rpcprog_t;
+typedef uint32_t	rpcvers_t;
+typedef uint32_t	rpcprot_t;
+typedef uint32_t	rpcproc_t;
+typedef uint32_t	rpcport_t;
+typedef int32_t		rpc_inline_t;
+
+/* This is for rpc/netdb.h */
+@rpcent_define@
+
+#define	bool_t	int
+#define	enum_t	int
+#ifndef FALSE
+#	define	FALSE	(0)
+#endif
+#ifndef TRUE
+#	define	TRUE	(1)
+#endif
+/* XXX namespace */
+#define __dontcare__	-1
+#ifndef NULL
+#	define NULL 0
+#endif
+
+/*
+ * The below should probably be internal-only, but seem to be
+ * traditionally exported in RPC implementations.
+ */
+#define mem_alloc(bsize)	malloc(bsize)
+#define mem_free(ptr, bsize)	free(ptr)
+
+#if 0
+#include <netdb.h> /* XXX This should not have to be here.
+		    * I got sick of seeing the warnings for MAXHOSTNAMELEN
+		    * and the two values were different. -- shanzer 
+		    */
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define       INADDR_LOOPBACK         (uint32_t)0x7F000001
+#endif
+#ifndef MAXHOSTNAMELEN
+#define        MAXHOSTNAMELEN  64
+#endif
+
+GSSRPC__END_DECLS
+
+#include <gssrpc/rename.h>
+
+#endif /* !defined(GSSRPC_TYPES_H) */
diff --git a/krb5-1-6/src/include/gssrpc/xdr.h b/krb5-1-6/src/include/gssrpc/xdr.h
new file mode 100644
index 000000000..943e39e2a
--- /dev/null
+++ b/krb5-1-6/src/include/gssrpc/xdr.h
@@ -0,0 +1,334 @@
+/* @(#)xdr.h	2.2 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*      @(#)xdr.h 1.19 87/04/22 SMI      */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef GSSRPC_XDR_H
+#define GSSRPC_XDR_H
+
+#include <stdio.h>		/* for FILE */
+
+GSSRPC__BEGIN_DECLS
+/*
+ * XDR provides a conventional way for converting between C data
+ * types and an external bit-string representation.  Library supplied
+ * routines provide for the conversion on built-in C data types.  These
+ * routines and utility routines defined here are used to help implement
+ * a type encode/decode routine for each user-defined type.
+ *
+ * Each data type provides a single procedure which takes two arguments:
+ *
+ *	bool_t
+ *	xdrproc(xdrs, argresp)
+ *		XDR *xdrs;
+ *		<type> *argresp;
+ *
+ * xdrs is an instance of a XDR handle, to which or from which the data
+ * type is to be converted.  argresp is a pointer to the structure to be
+ * converted.  The XDR handle contains an operation field which indicates
+ * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
+ *
+ * XDR_DECODE may allocate space if the pointer argresp is null.  This
+ * data can be freed with the XDR_FREE operation.
+ *
+ * We write only one procedure per data type to make it easy
+ * to keep the encode and decode procedures for a data type consistent.
+ * In many cases the same code performs all operations on a user defined type,
+ * because all the hard work is done in the component type routines.
+ * decode as a series of calls on the nested data types.
+ */
+
+/*
+ * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
+ * stream.  XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+	XDR_ENCODE=0,
+	XDR_DECODE=1,
+	XDR_FREE=2
+};
+
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT	(4)
+#define RNDUP(x)  ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
+		    * BYTES_PER_XDR_UNIT)
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or decoded.
+ *
+ * The second argument to the xdrproc_t is a pointer to an opaque pointer.
+ * The opaque pointer generally points to a structure of the data type
+ * to be decoded.  If this pointer is 0, then the type routines should
+ * allocate dynamic storage of the appropriate size and return it.
+ * bool_t	(*xdrproc_t)(XDR *, caddr_t *);
+ *
+ * XXX can't actually prototype it, because some take three args!!!
+ */
+typedef	bool_t (*xdrproc_t)();
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
+ * and two private fields for the use of the particular impelementation.
+ */
+typedef struct XDR {
+	enum xdr_op	x_op;		/* operation; fast additional param */
+	struct xdr_ops {
+		/* get a long from underlying stream */
+		bool_t	(*x_getlong)(struct XDR *, long *);
+
+		/* put a long to underlying stream */
+		bool_t	(*x_putlong)(struct XDR *, long *);
+
+		/* get some bytes from underlying stream */
+		bool_t	(*x_getbytes)(struct XDR *, caddr_t, u_int);
+
+		/* put some bytes to underlying stream */
+		bool_t	(*x_putbytes)(struct XDR *, caddr_t, u_int);
+
+		/* returns bytes off from beginning */
+		u_int	(*x_getpostn)(struct XDR *);
+
+		/* lets you reposition the stream */
+		bool_t	(*x_setpostn)(struct XDR *, u_int);
+
+		/* buf quick ptr to buffered data */
+		rpc_inline_t *(*x_inline)(struct XDR *, int);
+
+		/* free privates of this xdr_stream */
+		void	(*x_destroy)(struct XDR *);
+	} *x_ops;
+	caddr_t 	x_public;	/* users' data */
+	void *		x_private;	/* pointer to private data */
+	caddr_t 	x_base;		/* private used for position info */
+	int		x_handy;	/* extra private word */
+} XDR;
+
+/*
+ * Operations defined on a XDR handle
+ *
+ * XDR		*xdrs;
+ * int32_t	*longp;
+ * caddr_t	 addr;
+ * u_int	 len;
+ * u_int	 pos;
+ */
+#define XDR_GETLONG(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+#define xdr_getlong(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+
+#define XDR_PUTLONG(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+#define xdr_putlong(xdrs, longp)			\
+	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+
+#define XDR_GETBYTES(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+#define xdr_getbytes(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+
+#define XDR_PUTBYTES(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+#define xdr_putbytes(xdrs, addr, len)			\
+	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+
+#define XDR_GETPOS(xdrs)				\
+	(*(xdrs)->x_ops->x_getpostn)(xdrs)
+#define xdr_getpos(xdrs)				\
+	(*(xdrs)->x_ops->x_getpostn)(xdrs)
+
+#define XDR_SETPOS(xdrs, pos)				\
+	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+#define xdr_setpos(xdrs, pos)				\
+	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+
+#define	XDR_INLINE(xdrs, len)				\
+	(*(xdrs)->x_ops->x_inline)(xdrs, len)
+#define	xdr_inline(xdrs, len)				\
+	(*(xdrs)->x_ops->x_inline)(xdrs, len)
+
+#define	XDR_DESTROY(xdrs)				\
+	if ((xdrs)->x_ops->x_destroy) 			\
+		(*(xdrs)->x_ops->x_destroy)(xdrs)
+#define	xdr_destroy(xdrs)				\
+	if ((xdrs)->x_ops->x_destroy) 			\
+		(*(xdrs)->x_ops->x_destroy)(xdrs)
+
+/*
+ * Support struct for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * a entry with a null procedure pointer.  The xdr_union routine gets
+ * the discriminant value and then searches the array of structures
+ * for a matching value.  If a match is found the associated xdr routine
+ * is called to handle that part of the union.  If there is
+ * no match, then a default routine may be called.
+ * If there is no match and no default routine it is an error.
+ */
+#define NULL_xdrproc_t ((xdrproc_t)0)
+struct xdr_discrim {
+	int	value;
+	xdrproc_t proc;
+};
+
+/*
+ * In-line routines for fast encode/decode of primitve data types.
+ * Caveat emptor: these use single memory cycles to get the
+ * data from the underlying buffer, and will fail to operate
+ * properly if the data is not aligned.  The standard way to use these
+ * is to say:
+ *	if ((buf = XDR_INLINE(xdrs, count)) == NULL)
+ *		return (FALSE);
+ *	<<< macro calls >>>
+ * where ``count'' is the number of bytes of data occupied
+ * by the primitive data types.
+ *
+ * N.B. and frozen for all time: each data type here uses 4 bytes
+ * of external representation.
+ */
+#define IXDR_GET_INT32(buf)		((int32_t)IXDR_GET_U_INT32(buf))
+#define IXDR_PUT_INT32(buf, v)		IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+#define IXDR_GET_U_INT32(buf)		(ntohl((uint32_t)*(buf)++))
+#define IXDR_PUT_U_INT32(buf, v)	(*(buf)++ = (int32_t)htonl((v)))
+
+#define IXDR_GET_LONG(buf)		((long)IXDR_GET_INT32(buf))
+#define IXDR_PUT_LONG(buf, v)		IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+
+#define IXDR_GET_BOOL(buf)		((bool_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_ENUM(buf, t)		((t)IXDR_GET_INT32(buf))
+#define IXDR_GET_U_LONG(buf)		((u_long)IXDR_GET_U_INT32(buf))
+#define IXDR_GET_SHORT(buf)		((short)IXDR_GET_INT32(buf))
+#define IXDR_GET_U_SHORT(buf)		((u_short)IXDR_GET_U_INT32(buf))
+
+#define IXDR_PUT_BOOL(buf, v)		IXDR_PUT_INT32((buf),((int32_t)(v)))
+#define IXDR_PUT_ENUM(buf, v)		IXDR_PUT_INT32((buf),((int32_t)(v)))
+#define IXDR_PUT_U_LONG(buf, v)		IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+#define IXDR_PUT_SHORT(buf, v)		IXDR_PUT_INT32((buf),((int32_t)(v)))
+#define IXDR_PUT_U_SHORT(buf, v)	IXDR_PUT_U_INT32((buf),((uint32_t)(v)))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+extern bool_t	xdr_void(XDR *, void *);
+extern bool_t	xdr_int(XDR *, int *);
+extern bool_t	xdr_u_int(XDR *, u_int *);
+extern bool_t	xdr_long(XDR *, long *);
+extern bool_t	xdr_u_long(XDR *, u_long *);
+extern bool_t	xdr_short(XDR *, short *);
+extern bool_t	xdr_u_short(XDR *, u_short *);
+extern bool_t	xdr_bool(XDR *, bool_t *);
+extern bool_t	xdr_enum(XDR *, enum_t *);
+extern bool_t	xdr_array(XDR *, caddr_t *, u_int *,
+			u_int, u_int, xdrproc_t);
+extern bool_t	xdr_bytes(XDR *, char **, u_int *, u_int);
+extern bool_t	xdr_opaque(XDR *, caddr_t, u_int);
+extern bool_t	xdr_string(XDR *, char **, u_int);
+extern bool_t	xdr_union(XDR *, enum_t *, char *, struct xdr_discrim *,
+			xdrproc_t);
+extern bool_t	xdr_char(XDR *, char *);
+extern bool_t	xdr_u_char(XDR *, u_char *);
+extern bool_t	xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t);
+extern bool_t	xdr_float(XDR *, float *);
+extern bool_t	xdr_double(XDR *, double *);
+extern bool_t	xdr_reference(XDR *, caddr_t *, u_int, xdrproc_t);
+extern bool_t	xdr_pointer(XDR *, char **, u_int, xdrproc_t);
+extern bool_t	xdr_wrapstring(XDR *, char **);
+
+#define xdr_rpcprog	xdr_u_int32
+#define xdr_rpcvers	xdr_u_int32
+#define xdr_rpcprot	xdr_u_int32
+#define xdr_rpcproc	xdr_u_int32
+#define xdr_rpcport	xdr_u_int32
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 2048
+struct netobj {
+	u_int	n_len;
+	char	*n_bytes;
+};
+typedef struct netobj netobj;
+
+extern bool_t   xdr_netobj(XDR *, struct netobj *);
+
+extern bool_t	xdr_int32(XDR *, int32_t *);
+extern bool_t	xdr_u_int32(XDR *, uint32_t *);
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+
+/* XDR allocating memory buffer */
+extern void	xdralloc_create(XDR *, enum xdr_op);
+
+/* destroy xdralloc, save buf */
+extern void	xdralloc_release(XDR *);
+
+/* get buffer from xdralloc */
+extern caddr_t	xdralloc_getdata(XDR *);
+
+/* XDR using memory buffers */
+extern void	xdrmem_create(XDR *, caddr_t, u_int, enum xdr_op);
+
+/* XDR using stdio library */
+extern void	xdrstdio_create(XDR *, FILE *, enum xdr_op);
+
+/* XDR pseudo records for tcp */
+extern void	xdrrec_create(XDR *xdrs, u_int, u_int, caddr_t,
+			int (*) (caddr_t, caddr_t, int),
+			int (*) (caddr_t, caddr_t, int));
+
+/* make end of xdr record */
+extern bool_t	xdrrec_endofrecord(XDR *, bool_t);
+
+/* move to beginning of next record */
+extern bool_t	xdrrec_skiprecord (XDR *xdrs);
+
+/* true if no more input */
+extern bool_t	xdrrec_eof (XDR *xdrs);
+
+/* free memory buffers for xdr */
+extern void	xdr_free (xdrproc_t, void *);
+GSSRPC__END_DECLS
+
+#endif /* !defined(GSSRPC_XDR_H) */
diff --git a/krb5-1-6/src/include/k5-err.h b/krb5-1-6/src/include/k5-err.h
new file mode 100644
index 000000000..c2cc52cee
--- /dev/null
+++ b/krb5-1-6/src/include/k5-err.h
@@ -0,0 +1,69 @@
+/*
+ * include/k5-err.h
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.	Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Error-message handling
+ */
+
+#ifndef K5_ERR_H
+#define K5_ERR_H
+
+#ifndef _
+#define _(X) (X)
+#endif
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include <win-mac.h>
+#endif
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+#include <stdarg.h>
+
+struct errinfo {
+    long code;
+    const char *msg;
+    char scratch_buf[1024];
+};
+
+void
+krb5int_set_error (struct errinfo *ep,
+		   long code,
+		   const char *fmt, ...);
+void
+krb5int_vset_error (struct errinfo *ep, long code,
+		    const char *fmt, va_list args);
+const char *
+krb5int_get_error (struct errinfo *ep, long code);
+void
+krb5int_free_error (struct errinfo *ep, const char *msg);
+void
+krb5int_clear_error (struct errinfo *ep);
+void
+krb5int_set_error_info_callout_fn (const char *(KRB5_CALLCONV *f)(long));
+
+#endif /* K5_ERR_H */
diff --git a/krb5-1-6/src/include/k5-int-pkinit.h b/krb5-1-6/src/include/k5-int-pkinit.h
new file mode 100644
index 000000000..e75c8031f
--- /dev/null
+++ b/krb5-1-6/src/include/k5-int-pkinit.h
@@ -0,0 +1,270 @@
+/*
+ * COPYRIGHT (C) 2006
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ * 
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ * 
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _KRB5_INT_PKINIT_H
+#define _KRB5_INT_PKINIT_H
+
+/*
+ * pkinit structures
+ */
+
+/* PKAuthenticator */
+typedef struct _krb5_pk_authenticator {
+	krb5_int32	cusec;	/* (0..999999) */
+	krb5_timestamp	ctime;
+	krb5_int32	nonce;	/* (0..4294967295) */
+	krb5_checksum	paChecksum;
+} krb5_pk_authenticator;
+
+/* PKAuthenticator draft9 */
+typedef struct _krb5_pk_authenticator_draft9 {
+	krb5_principal  kdcName;
+	krb5_octet_data	kdcRealm;
+	krb5_int32	cusec;	/* (0..999999) */
+	krb5_timestamp	ctime;
+	krb5_int32	nonce;	/* (0..4294967295) */
+} krb5_pk_authenticator_draft9;
+
+/* AlgorithmIdentifier */
+typedef struct _krb5_algorithm_identifier {
+	krb5_octet_data	algorithm;	/* OID */
+	krb5_octet_data	parameters; /* Optional */
+} krb5_algorithm_identifier;
+
+/* SubjectPublicKeyInfo */
+typedef struct _krb5_subject_pk_info {
+	krb5_algorithm_identifier   algorithm;
+	krb5_octet_data		    subjectPublicKey; /* BIT STRING */
+} krb5_subject_pk_info;
+
+/* AuthPack */
+typedef struct _krb5_auth_pack {
+	krb5_pk_authenticator	    pkAuthenticator;
+	krb5_subject_pk_info	    *clientPublicValue; /* Optional */
+	krb5_algorithm_identifier   **supportedCMSTypes; /* Optional */
+	krb5_octet_data		    clientDHNonce; /* Optional */
+} krb5_auth_pack;
+
+/* AuthPack draft9 */
+typedef struct _krb5_auth_pack_draft9 {
+	krb5_pk_authenticator_draft9 pkAuthenticator;
+	krb5_subject_pk_info	    *clientPublicValue; /* Optional */
+} krb5_auth_pack_draft9;
+
+/* ExternalPrincipalIdentifier */
+typedef struct _krb5_external_principal_identifier {
+	krb5_octet_data	subjectName; /* Optional */
+	krb5_octet_data	issuerAndSerialNumber; /* Optional */
+	krb5_octet_data	subjectKeyIdentifier; /* Optional */
+} krb5_external_principal_identifier;
+
+/* TrustedCas */
+typedef struct _krb5_trusted_ca {
+	enum {
+		choice_trusted_cas_UNKNOWN = -1,
+		choice_trusted_cas_principalName = 0,
+		choice_trusted_cas_caName = 1,
+		choice_trusted_cas_issuerAndSerial = 2
+	} choice;
+	union {
+		krb5_principal	principalName;
+		krb5_octet_data	caName;	/* fully-qualified X.500 "Name" as defined by X.509 (der-encoded) */
+		krb5_octet_data	issuerAndSerial; /* Optional -- IssuerAndSerialNumber (der-encoded) */
+	} u;
+} krb5_trusted_ca;
+
+/* typed data */
+typedef struct _krb5_typed_data {
+    krb5_magic magic;
+    krb5_int32  type;
+    unsigned int length;
+    krb5_octet *data;
+} krb5_typed_data;
+
+/* PA-PK-AS-REQ (Draft 9 -- PA TYPE 14) */
+typedef struct _krb5_pa_pk_as_req_draft9 {
+	krb5_octet_data	signedAuthPack;
+	krb5_trusted_ca **trustedCertifiers; /* Optional array */
+	krb5_octet_data kdcCert; /* Optional */
+	krb5_octet_data encryptionCert;
+} krb5_pa_pk_as_req_draft9;
+
+/* PA-PK-AS-REQ (rfc4556 -- PA TYPE 16) */
+typedef struct _krb5_pa_pk_as_req {
+	krb5_octet_data	signedAuthPack;
+	krb5_external_principal_identifier **trustedCertifiers; /* Optional array */
+	krb5_octet_data	kdcPkId; /* Optional */
+} krb5_pa_pk_as_req;
+
+/* DHRepInfo */
+typedef struct _krb5_dh_rep_info {
+	krb5_octet_data	dhSignedData;
+	krb5_octet_data	serverDHNonce; /* Optional */
+} krb5_dh_rep_info;
+
+/* KDCDHKeyInfo */
+typedef struct _krb5_kdc_dh_key_info {
+	krb5_octet_data	subjectPublicKey; /* BIT STRING */
+	krb5_int32	nonce;	/* (0..4294967295) */
+	krb5_timestamp	dhKeyExpiration; /* Optional */
+} krb5_kdc_dh_key_info;
+
+/* KDCDHKeyInfo draft9*/
+typedef struct _krb5_kdc_dh_key_info_draft9 {
+	krb5_octet_data	subjectPublicKey; /* BIT STRING */
+	krb5_int32	nonce;	/* (0..4294967295) */
+} krb5_kdc_dh_key_info_draft9;
+
+/* ReplyKeyPack */
+typedef struct _krb5_reply_key_pack {
+	krb5_keyblock	replyKey;
+	krb5_checksum	asChecksum;
+} krb5_reply_key_pack;
+
+/* ReplyKeyPack */
+typedef struct _krb5_reply_key_pack_draft9 {
+	krb5_keyblock	replyKey;
+	krb5_int32	nonce;
+} krb5_reply_key_pack_draft9;
+
+/* PA-PK-AS-REP (Draft 9 -- PA TYPE 15) */
+typedef struct _krb5_pa_pk_as_rep_draft9 {
+	enum {
+		choice_pa_pk_as_rep_draft9_UNKNOWN = -1,
+		choice_pa_pk_as_rep_draft9_dhSignedData = 0,
+		choice_pa_pk_as_rep_draft9_encKeyPack = 1
+	} choice;
+	union {
+		krb5_octet_data dhSignedData;
+		krb5_octet_data encKeyPack;
+	} u;
+} krb5_pa_pk_as_rep_draft9;
+
+/* PA-PK-AS-REP (rfc4556 -- PA TYPE 17) */
+typedef struct _krb5_pa_pk_as_rep {
+	enum {
+		choice_pa_pk_as_rep_UNKNOWN = -1,
+		choice_pa_pk_as_rep_dhInfo = 0,
+		choice_pa_pk_as_rep_encKeyPack = 1
+	} choice;
+	union {
+		krb5_dh_rep_info    dh_Info;
+		krb5_octet_data	    encKeyPack;
+	} u;
+} krb5_pa_pk_as_rep;
+
+/*
+ * Begin "asn1.h"
+ */
+
+/*************************************************************************
+ * Prototypes for pkinit asn.1 encode routines
+ *************************************************************************/
+
+krb5_error_code encode_krb5_pa_pk_as_req
+	(const krb5_pa_pk_as_req *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pa_pk_as_req_draft9
+	(const krb5_pa_pk_as_req_draft9 *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pa_pk_as_rep
+	(const krb5_pa_pk_as_rep *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pa_pk_as_rep_draft9
+	(const krb5_pa_pk_as_rep_draft9 *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_auth_pack
+	(const krb5_auth_pack *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_auth_pack_draft9
+	(const krb5_auth_pack_draft9 *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_kdc_dh_key_info
+	(const krb5_kdc_dh_key_info *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_reply_key_pack
+	(const krb5_reply_key_pack *, krb5_data **code);
+
+krb5_error_code encode_krb5_reply_key_pack_draft9
+	(const krb5_reply_key_pack_draft9 *, krb5_data **code);
+
+krb5_error_code encode_krb5_typed_data
+	(const krb5_typed_data **, krb5_data **code);
+
+krb5_error_code encode_krb5_td_trusted_certifiers
+	(const krb5_external_principal_identifier **, krb5_data **code);
+
+krb5_error_code encode_krb5_td_dh_parameters
+	(const krb5_algorithm_identifier **, krb5_data **code);
+
+/*************************************************************************
+ * Prototypes for pkinit asn.1 decode routines
+ *************************************************************************/
+
+krb5_error_code decode_krb5_pa_pk_as_req
+	(const krb5_data *, krb5_pa_pk_as_req **);
+
+krb5_error_code decode_krb5_pa_pk_as_req_draft9
+	(const krb5_data *, krb5_pa_pk_as_req_draft9 **);
+
+krb5_error_code decode_krb5_pa_pk_as_rep
+	(const krb5_data *, krb5_pa_pk_as_rep **);
+
+krb5_error_code decode_krb5_pa_pk_as_rep_draft9
+	(const krb5_data *, krb5_pa_pk_as_rep_draft9 **);
+
+krb5_error_code decode_krb5_auth_pack
+	(const krb5_data *, krb5_auth_pack **);
+
+krb5_error_code decode_krb5_auth_pack_draft9
+	(const krb5_data *, krb5_auth_pack_draft9 **);
+
+krb5_error_code decode_krb5_kdc_dh_key_info 
+	(const krb5_data *, krb5_kdc_dh_key_info **);
+
+krb5_error_code decode_krb5_principal_name
+	(const krb5_data *, krb5_principal_data **);
+
+krb5_error_code decode_krb5_reply_key_pack
+	(const krb5_data *, krb5_reply_key_pack **);
+
+krb5_error_code decode_krb5_reply_key_pack_draft9
+	(const krb5_data *, krb5_reply_key_pack_draft9 **);
+
+krb5_error_code decode_krb5_typed_data
+	(const krb5_data *, krb5_typed_data ***);
+
+krb5_error_code decode_krb5_td_trusted_certifiers
+	(const krb5_data *, krb5_external_principal_identifier ***);
+
+krb5_error_code decode_krb5_td_dh_parameters
+	(const krb5_data *, krb5_algorithm_identifier ***);
+
+#endif /* _KRB5_INT_PKINIT_H */
diff --git a/krb5-1-6/src/include/k5-int.h b/krb5-1-6/src/include/k5-int.h
new file mode 100644
index 000000000..02395816e
--- /dev/null
+++ b/krb5-1-6/src/include/k5-int.h
@@ -0,0 +1,2241 @@
+/*
+ * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, 2003,2006 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+/*
+ * 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
+ * includes other definitions that are not user-visible but are
+ * required for compiling Kerberos internal routines.
+ *
+ * John Gilmore, Cygnus Support, Sat Jan 21 22:45:52 PST 1995
+ */
+
+#ifndef _KRB5_INT_H
+#define _KRB5_INT_H
+
+#ifdef KRB5_GENERAL__
+#error krb5.h included before k5-int.h
+#endif /* KRB5_GENERAL__ */
+
+#include "osconf.h"
+
+/*
+ * Begin "k5-config.h"
+ */
+#ifndef KRB5_CONFIG__
+#define KRB5_CONFIG__
+
+/* 
+ * Machine-type definitions: PC Clone 386 running Microloss Windows
+ */
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include "win-mac.h"
+
+/* Kerberos Windows initialization file */
+#define KERBEROS_INI	"kerberos.ini"
+#define INI_FILES	"Files"
+#define INI_KRB_CCACHE	"krb5cc"	/* Location of the ccache */
+#define INI_KRB5_CONF	"krb5.ini"	/* Location of krb5.conf file */
+#define ANSI_STDIO
+#endif
+
+#ifndef KRB5_AUTOCONF__
+#define KRB5_AUTOCONF__
+#include "autoconf.h"
+#endif
+
+#ifndef KRB5_SYSTYPES__
+#define KRB5_SYSTYPES__
+
+#ifdef HAVE_SYS_TYPES_H		/* From autoconf.h */
+#include <sys/types.h>
+#else /* HAVE_SYS_TYPES_H */
+typedef unsigned long 	u_long;
+typedef unsigned int	u_int;
+typedef unsigned short	u_short;
+typedef unsigned char	u_char;
+#endif /* HAVE_SYS_TYPES_H */
+#endif /* KRB5_SYSTYPES__ */
+
+
+#include "k5-platform.h"
+/* not used in krb5.h (yet) */
+typedef UINT64_TYPE krb5_ui_8;
+typedef INT64_TYPE krb5_int64;
+
+
+#define DEFAULT_PWD_STRING1 "Enter password"
+#define DEFAULT_PWD_STRING2 "Re-enter password for verification"
+
+#define	KRB5_KDB_MAX_LIFE	(60*60*24) /* one day */
+#define	KRB5_KDB_MAX_RLIFE	(60*60*24*7) /* one week */
+#define	KRB5_KDB_EXPIRATION	2145830400 /* Thu Jan  1 00:00:00 2038 UTC */
+
+/* 
+ * Windows requires a different api interface to each function. Here
+ * just define it as NULL.
+ */
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* #define KRB5_OLD_CRYPTO is done in krb5.h */
+
+#endif /* KRB5_CONFIG__ */
+
+/*
+ * End "k5-config.h"
+ */
+
+/*
+ * After loading the configuration definitions, load the Kerberos definitions.
+ */
+#include <errno.h>
+#include "krb5.h"
+#include "profile.h"
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+
+/* Get mutex support; currently used only for the replay cache.  */
+#include "k5-thread.h"
+
+/* Get error info support.  */
+#include "k5-err.h"
+
+/* krb5/krb5.h includes many other .h files in the krb5 subdirectory.
+   The ones that it doesn't include, we include below.  */
+
+/*
+ * Begin "k5-errors.h"
+ */
+#ifndef KRB5_ERRORS__
+#define KRB5_ERRORS__
+
+
+/* Error codes used in KRB_ERROR protocol messages.
+   Return values of library routines are based on a different error table
+   (which allows non-ambiguous error codes between subsystems) */
+
+/* KDC errors */
+#define	KDC_ERR_NONE			0 /* No error */
+#define	KDC_ERR_NAME_EXP		1 /* Client's entry in DB expired */
+#define	KDC_ERR_SERVICE_EXP		2 /* Server's entry in DB expired */
+#define	KDC_ERR_BAD_PVNO		3 /* Requested pvno not supported */
+#define	KDC_ERR_C_OLD_MAST_KVNO		4 /* C's key encrypted in old master */
+#define	KDC_ERR_S_OLD_MAST_KVNO		5 /* S's key encrypted in old master */
+#define	KDC_ERR_C_PRINCIPAL_UNKNOWN	6 /* Client not found in Kerberos DB */
+#define	KDC_ERR_S_PRINCIPAL_UNKNOWN	7 /* Server not found in Kerberos DB */
+#define	KDC_ERR_PRINCIPAL_NOT_UNIQUE	8 /* Multiple entries in Kerberos DB */
+#define	KDC_ERR_NULL_KEY		9 /* The C or S has a null key */
+#define	KDC_ERR_CANNOT_POSTDATE		10 /* Tkt ineligible for postdating */
+#define	KDC_ERR_NEVER_VALID		11 /* Requested starttime > endtime */
+#define	KDC_ERR_POLICY			12 /* KDC policy rejects request */
+#define	KDC_ERR_BADOPTION		13 /* KDC can't do requested opt. */
+#define	KDC_ERR_ENCTYPE_NOSUPP		14 /* No support for encryption type */
+#define KDC_ERR_SUMTYPE_NOSUPP		15 /* No support for checksum type */
+#define KDC_ERR_PADATA_TYPE_NOSUPP	16 /* No support for padata type */
+#define KDC_ERR_TRTYPE_NOSUPP		17 /* No support for transited type */
+#define KDC_ERR_CLIENT_REVOKED		18 /* C's creds have been revoked */
+#define KDC_ERR_SERVICE_REVOKED		19 /* S's creds have been revoked */
+#define KDC_ERR_TGT_REVOKED		20 /* TGT has been revoked */
+#define KDC_ERR_CLIENT_NOTYET		21 /* C not yet valid */
+#define KDC_ERR_SERVICE_NOTYET		22 /* S not yet valid */
+#define KDC_ERR_KEY_EXP			23 /* Password has expired */
+#define KDC_ERR_PREAUTH_FAILED		24 /* Preauthentication failed */
+#define KDC_ERR_PREAUTH_REQUIRED	25 /* Additional preauthentication */
+					   /* required */
+#define KDC_ERR_SERVER_NOMATCH		26 /* Requested server and */
+					   /* ticket don't match*/
+#define KDC_ERR_SVC_UNAVAILABLE		29 /* A service is not
+					    * available that is
+					    * required to process the
+					    * request */
+/* Application errors */
+#define	KRB_AP_ERR_BAD_INTEGRITY 31	/* Decrypt integrity check failed */
+#define	KRB_AP_ERR_TKT_EXPIRED	32	/* Ticket expired */
+#define	KRB_AP_ERR_TKT_NYV	33	/* Ticket not yet valid */
+#define	KRB_AP_ERR_REPEAT	34	/* Request is a replay */
+#define	KRB_AP_ERR_NOT_US	35	/* The ticket isn't for us */
+#define	KRB_AP_ERR_BADMATCH	36	/* Ticket/authenticator don't match */
+#define	KRB_AP_ERR_SKEW		37	/* Clock skew too great */
+#define	KRB_AP_ERR_BADADDR	38	/* Incorrect net address */
+#define	KRB_AP_ERR_BADVERSION	39	/* Protocol version mismatch */
+#define	KRB_AP_ERR_MSG_TYPE	40	/* Invalid message type */
+#define	KRB_AP_ERR_MODIFIED	41	/* Message stream modified */
+#define	KRB_AP_ERR_BADORDER	42	/* Message out of order */
+#define	KRB_AP_ERR_BADKEYVER	44	/* Key version is not available */
+#define	KRB_AP_ERR_NOKEY	45	/* Service key not available */
+#define	KRB_AP_ERR_MUT_FAIL	46	/* Mutual authentication failed */
+#define KRB_AP_ERR_BADDIRECTION	47 	/* Incorrect message direction */
+#define KRB_AP_ERR_METHOD	48 	/* Alternative authentication */
+					/* method required */
+#define KRB_AP_ERR_BADSEQ	49 	/* Incorrect sequence numnber */
+					/* in message */
+#define KRB_AP_ERR_INAPP_CKSUM	50	/* Inappropriate type of */
+					/* checksum in message */
+#define KRB_AP_PATH_NOT_ACCEPTED 51	/* Policy rejects transited path */
+#define KRB_ERR_RESPONSE_TOO_BIG 52	/* Response too big for UDP, */
+					/*   retry with TCP */
+
+/* other errors */
+#define KRB_ERR_GENERIC		60 	/* Generic error (description */
+					/* in e-text) */
+#define	KRB_ERR_FIELD_TOOLONG	61	/* Field is too long for impl. */
+
+/* PKINIT server-reported errors */
+#define KDC_ERR_CLIENT_NOT_TRUSTED		62 /* client cert not trusted */
+#define KDC_ERR_INVALID_SIG			64 /* client signature verify failed */
+#define KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED	65 /* invalid Diffie-Hellman parameters */
+#define KDC_ERR_CANT_VERIFY_CERTIFICATE		70 /* client cert not verifiable to */
+						   /* trusted root cert */
+#define KDC_ERR_INVALID_CERTIFICATE		71 /* client cert had invalid signature */
+#define KDC_ERR_REVOKED_CERTIFICATE		72 /* client cert was revoked */
+#define KDC_ERR_REVOCATION_STATUS_UNKNOWN	73 /* client cert revoked, reason unknown */
+#define KDC_ERR_CLIENT_NAME_MISMATCH		75 /* mismatch between client cert and */
+						   /* principal name */
+#define KDC_ERR_INCONSISTENT_KEY_PURPOSE	77 /* bad extended key use */
+#define KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED	78 /* bad digest algorithm in client cert */
+#define KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED	79 /* missing paChecksum in PA-PK-AS-REQ */
+#define KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED 80 /* bad digest algorithm in SignedData */
+#define KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED 81
+
+#endif /* KRB5_ERRORS__ */
+/*
+ * End "k5-errors.h"
+ */
+
+/*
+ * This structure is returned in the e-data field of the KRB-ERROR
+ * message when the error calling for an alternative form of
+ * authentication is returned, KRB_AP_METHOD.
+ */
+typedef struct _krb5_alt_method {
+	krb5_magic	magic;
+	krb5_int32	method;
+	unsigned int	length;
+	krb5_octet	*data;
+} krb5_alt_method;
+
+/*
+ * A null-terminated array of this structure is returned by the KDC as
+ * the data part of the ETYPE_INFO preauth type.  It informs the
+ * client which encryption types are supported.
+ * The  same data structure is used by both etype-info and etype-info2
+ * but s2kparams must be null when encoding etype-info.
+ */
+typedef struct _krb5_etype_info_entry {
+	krb5_magic	magic;
+	krb5_enctype	etype;
+	unsigned int	length;
+	krb5_octet	*salt;
+    krb5_data s2kparams;
+} krb5_etype_info_entry;
+
+/* 
+ *  This is essentially -1 without sign extension which can screw up
+ *  comparisons on 64 bit machines. If the length is this value, then
+ *  the salt data is not present. This is to distinguish between not
+ *  being set and being of 0 length. 
+ */
+#define KRB5_ETYPE_NO_SALT VALID_UINT_BITS
+
+typedef krb5_etype_info_entry ** krb5_etype_info;
+
+/*
+ * a sam_challenge is returned for alternate preauth 
+ */
+/*
+          SAMFlags ::= BIT STRING {
+              use-sad-as-key[0],
+              send-encrypted-sad[1],
+              must-pk-encrypt-sad[2]
+          }
+ */
+/*
+          PA-SAM-CHALLENGE ::= SEQUENCE {
+              sam-type[0]                 INTEGER,
+              sam-flags[1]                SAMFlags,
+              sam-type-name[2]            GeneralString OPTIONAL,
+              sam-track-id[3]             GeneralString OPTIONAL,
+              sam-challenge-label[4]      GeneralString OPTIONAL,
+              sam-challenge[5]            GeneralString OPTIONAL,
+              sam-response-prompt[6]      GeneralString OPTIONAL,
+              sam-pk-for-sad[7]           EncryptionKey OPTIONAL,
+              sam-nonce[8]                INTEGER OPTIONAL,
+              sam-cksum[9]                Checksum OPTIONAL
+          }
+*/
+/* sam_type values -- informational only */
+#define PA_SAM_TYPE_ENIGMA     1   /*  Enigma Logic */
+#define PA_SAM_TYPE_DIGI_PATH  2   /*  Digital Pathways */
+#define PA_SAM_TYPE_SKEY_K0    3   /*  S/key where  KDC has key 0 */
+#define PA_SAM_TYPE_SKEY       4   /*  Traditional S/Key */
+#define PA_SAM_TYPE_SECURID    5   /*  Security Dynamics */
+#define PA_SAM_TYPE_CRYPTOCARD 6   /*  CRYPTOCard */
+#if 1 /* XXX need to figure out who has which numbers assigned */
+#define PA_SAM_TYPE_ACTIVCARD_DEC  6   /*  ActivCard decimal mode */
+#define PA_SAM_TYPE_ACTIVCARD_HEX  7   /*  ActivCard hex mode */
+#define PA_SAM_TYPE_DIGI_PATH_HEX  8   /*  Digital Pathways hex mode */
+#endif
+#define PA_SAM_TYPE_EXP_BASE    128 /* experimental */
+#define PA_SAM_TYPE_GRAIL		(PA_SAM_TYPE_EXP_BASE+0) /* testing */
+#define PA_SAM_TYPE_SECURID_PREDICT	(PA_SAM_TYPE_EXP_BASE+1) /* special */
+
+typedef struct _krb5_predicted_sam_response {
+	krb5_magic	magic;
+	krb5_keyblock	sam_key;
+	krb5_flags	sam_flags; /* Makes key munging easier */
+	krb5_timestamp  stime;	/* time on server, for replay detection */
+	krb5_int32      susec;
+	krb5_principal  client;
+	krb5_data       msd;	/* mechanism specific data */
+} krb5_predicted_sam_response;
+
+typedef struct _krb5_sam_challenge {
+	krb5_magic	magic;
+	krb5_int32	sam_type; /* information */
+	krb5_flags	sam_flags; /* KRB5_SAM_* values */
+	krb5_data	sam_type_name;
+	krb5_data	sam_track_id;
+	krb5_data	sam_challenge_label;
+	krb5_data	sam_challenge;
+	krb5_data	sam_response_prompt;
+	krb5_data	sam_pk_for_sad;
+	krb5_int32	sam_nonce;
+	krb5_checksum	sam_cksum;
+} krb5_sam_challenge;
+
+typedef struct _krb5_sam_key {	/* reserved for future use */
+	krb5_magic	magic;
+	krb5_keyblock	sam_key;
+} krb5_sam_key;
+
+typedef struct _krb5_enc_sam_response_enc {
+	krb5_magic	magic;
+	krb5_int32	sam_nonce;
+	krb5_timestamp	sam_timestamp;
+	krb5_int32	sam_usec;
+	krb5_data	sam_sad;
+} krb5_enc_sam_response_enc;
+
+typedef struct _krb5_sam_response {
+	krb5_magic	magic;
+	krb5_int32	sam_type; /* informational */
+	krb5_flags	sam_flags; /* KRB5_SAM_* values */
+	krb5_data	sam_track_id; /* copied */
+	krb5_enc_data	sam_enc_key; /* krb5_sam_key - future use */
+	krb5_enc_data	sam_enc_nonce_or_ts; /* krb5_enc_sam_response_enc */
+	krb5_int32	sam_nonce;
+	krb5_timestamp	sam_patimestamp;
+} krb5_sam_response;
+
+typedef struct _krb5_sam_challenge_2 {
+	krb5_data	sam_challenge_2_body;
+	krb5_checksum	**sam_cksum;		/* Array of checksums */
+} krb5_sam_challenge_2;
+
+typedef struct _krb5_sam_challenge_2_body {
+	krb5_magic	magic;
+	krb5_int32	sam_type; /* information */
+	krb5_flags	sam_flags; /* KRB5_SAM_* values */
+	krb5_data	sam_type_name;
+	krb5_data	sam_track_id;
+	krb5_data	sam_challenge_label;
+	krb5_data	sam_challenge;
+	krb5_data	sam_response_prompt;
+	krb5_data	sam_pk_for_sad;
+	krb5_int32	sam_nonce;
+	krb5_enctype	sam_etype;
+} krb5_sam_challenge_2_body;
+
+typedef struct _krb5_sam_response_2 {
+	krb5_magic	magic;
+	krb5_int32	sam_type; /* informational */
+	krb5_flags	sam_flags; /* KRB5_SAM_* values */
+	krb5_data	sam_track_id; /* copied */
+	krb5_enc_data	sam_enc_nonce_or_sad; /* krb5_enc_sam_response_enc */
+	krb5_int32	sam_nonce;
+} krb5_sam_response_2;
+
+typedef struct _krb5_enc_sam_response_enc_2 {
+	krb5_magic	magic;
+	krb5_int32	sam_nonce;
+	krb5_data	sam_sad;
+} krb5_enc_sam_response_enc_2;
+
+/*
+ * Keep the pkinit definitions in a separate file so that the plugin
+ * only has to include k5-int-pkinit.h rather than k5-int.h
+ */
+
+#include "k5-int-pkinit.h"
+
+/*
+ * Begin "ext-proto.h"
+ */
+#ifndef KRB5_EXT_PROTO__
+#define KRB5_EXT_PROTO__
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef HAVE_STRDUP
+extern char *strdup (const char *);
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#endif /* KRB5_EXT_PROTO__ */
+/*
+ * End "ext-proto.h"
+ */
+
+/*
+ * Begin "sysincl.h"
+ */
+#ifndef KRB5_SYSINCL__
+#define KRB5_SYSINCL__
+
+#ifndef KRB5_SYSTYPES__
+#define KRB5_SYSTYPES__
+/* needed for much of the rest -- but already handled in krb5.h? */
+/* #include <sys/types.h> */
+#endif /* KRB5_SYSTYPES__ */
+
+#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_SYS_STAT_H
+#include <sys/stat.h>			/* struct stat, stat() */
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>			/* MAXPATHLEN */
+#endif
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>			/* prototypes for file-related
+					   syscalls; flags for open &
+					   friends */
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#endif /* KRB5_SYSINCL__ */
+/*
+ * End "sysincl.h"
+ */
+
+/*
+ * Begin "los-proto.h"
+ */
+#ifndef KRB5_LIBOS_PROTO__
+#define KRB5_LIBOS_PROTO__
+
+#include <stdio.h>
+
+struct addrlist;
+struct sendto_callback_info;
+
+/* libos.spec */
+krb5_error_code krb5_lock_file (krb5_context, int, int);
+krb5_error_code krb5_unlock_file (krb5_context, int);
+krb5_error_code krb5_sendto_kdc (krb5_context, const krb5_data *,
+				 const krb5_data *, krb5_data *, int *, int);
+
+krb5_error_code krb5int_sendto (krb5_context context, const krb5_data *message,
+                const struct addrlist *addrs, struct sendto_callback_info* callback_info,
+				krb5_data *reply, struct sockaddr *localaddr, socklen_t *localaddrlen,
+                struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *addr_used,
+		int (*msg_handler)(krb5_context, const krb5_data *, void *),
+		void *msg_handler_data);
+
+krb5_error_code krb5_get_krbhst (krb5_context, const krb5_data *, char *** );
+krb5_error_code krb5_free_krbhst (krb5_context, char * const * );
+krb5_error_code krb5_create_secure_file (krb5_context, const char * pathname);
+krb5_error_code krb5_sync_disk_file (krb5_context, FILE *fp);
+
+krb5_error_code krb5int_get_fq_local_hostname (char *, size_t);
+
+krb5_error_code krb5int_init_context_kdc(krb5_context *);
+
+krb5_error_code krb5_os_init_context (krb5_context, krb5_boolean);
+
+void krb5_os_free_context (krb5_context);
+
+/* This function is needed by KfM's KerberosPreferences API 
+ * because it needs to be able to specify "secure" */
+krb5_error_code os_get_default_config_files 
+    (profile_filespec_t **pfiles, krb5_boolean secure);
+
+krb5_error_code krb5_os_hostaddr
+	(krb5_context, const char *, krb5_address ***);
+
+/* N.B.: You need to include fake-addrinfo.h *before* k5-int.h if you're
+   going to use this structure.  */
+struct addrlist {
+    struct {
+#ifdef FAI_DEFINED
+	struct addrinfo *ai;
+#else
+	struct undefined_addrinfo *ai;
+#endif
+	void (*freefn)(void *);
+	void *data;
+    } *addrs;
+    int naddrs;
+    int space;
+};
+#define ADDRLIST_INIT { 0, 0, 0 }
+extern void krb5int_free_addrlist (struct addrlist *);
+extern int krb5int_grow_addrlist (struct addrlist *, int);
+extern int krb5int_add_host_to_list (struct addrlist *, const char *,
+				     int, int, int, int);
+
+#include <krb5/locate_plugin.h>
+krb5_error_code
+krb5int_locate_server (krb5_context, const krb5_data *realm,
+		       struct addrlist *, enum locate_service_type svc,
+		       int sockettype, int family);
+
+#endif /* KRB5_LIBOS_PROTO__ */
+
+/* new encryption provider api */
+
+struct krb5_enc_provider {
+    /* keybytes is the input size to make_key; 
+       keylength is the output size */
+    size_t block_size, keybytes, keylength;
+
+    /* cipher-state == 0 fresh state thrown away at end */
+    krb5_error_code (*encrypt) (const krb5_keyblock *key,
+				const krb5_data *cipher_state,
+				const krb5_data *input,
+				krb5_data *output);
+
+    krb5_error_code (*decrypt) (const krb5_keyblock *key,
+				const krb5_data *ivec,
+				const krb5_data *input,
+				krb5_data *output);
+
+    krb5_error_code (*make_key) (const krb5_data *randombits,
+				 krb5_keyblock *key);
+
+  krb5_error_code (*init_state) (const krb5_keyblock *key,
+				 krb5_keyusage keyusage, krb5_data *out_state);
+  krb5_error_code (*free_state) (krb5_data *state);
+  
+};
+
+struct krb5_hash_provider {
+    size_t hashsize, blocksize;
+
+    /* this takes multiple inputs to avoid lots of copying. */
+    krb5_error_code (*hash) (unsigned int icount, const krb5_data *input,
+			     krb5_data *output);
+};
+
+struct krb5_keyhash_provider {
+    size_t hashsize;
+
+    krb5_error_code (*hash) (const krb5_keyblock *key,
+			     krb5_keyusage keyusage,
+			     const krb5_data *ivec,
+			     const krb5_data *input,
+			     krb5_data *output);
+
+    krb5_error_code (*verify) (const krb5_keyblock *key,
+			       krb5_keyusage keyusage,
+			       const krb5_data *ivec,
+			       const krb5_data *input,
+			       const krb5_data *hash,
+			       krb5_boolean *valid);
+};
+
+typedef void (*krb5_encrypt_length_func) (const struct krb5_enc_provider *enc,
+  const struct krb5_hash_provider *hash,
+  size_t inputlen, size_t *length);
+
+typedef krb5_error_code (*krb5_crypt_func) (const struct krb5_enc_provider *enc,
+  const struct krb5_hash_provider *hash,
+  const krb5_keyblock *key, krb5_keyusage keyusage,
+  const krb5_data *ivec, 
+  const krb5_data *input, krb5_data *output);
+
+typedef krb5_error_code (*krb5_str2key_func) (const struct krb5_enc_provider *enc, const krb5_data *string,
+  const krb5_data *salt, const krb5_data *parm, krb5_keyblock *key);
+
+typedef krb5_error_code (*krb5_prf_func)(
+					 const struct krb5_enc_provider *enc,
+					 const struct krb5_hash_provider *hash,
+					 const krb5_keyblock *key,
+					 const krb5_data *in, krb5_data *out);
+
+struct krb5_keytypes {
+    krb5_enctype etype;
+    char *in_string;
+    char *out_string;
+    const struct krb5_enc_provider *enc;
+    const struct krb5_hash_provider *hash;
+  size_t prf_length;
+    krb5_encrypt_length_func encrypt_len;
+    krb5_crypt_func encrypt;
+    krb5_crypt_func decrypt;
+    krb5_str2key_func str2key;
+  krb5_prf_func prf;
+    krb5_cksumtype required_ctype;
+};
+
+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. */
+    const struct krb5_keyhash_provider *keyhash;
+    const struct krb5_hash_provider *hash;
+    /* This just gets uglier and uglier.  In the key derivation case,
+       we produce an hmac.  To make the hmac code work, we can't hack
+       the output size indicated by the hash provider, but we may want
+       a truncated hmac.  If we want truncation, this is the number of
+       bytes we truncate to; it should be 0 otherwise.  */
+    unsigned int trunc_size;
+};
+
+#define KRB5_CKSUMFLAG_DERIVE		0x0001
+#define KRB5_CKSUMFLAG_NOT_COLL_PROOF	0x0002
+
+/*
+ * in here to deal with stuff from lib/crypto
+ */
+
+void krb5_nfold
+(unsigned int inbits, const unsigned char *in,
+		unsigned int outbits, unsigned char *out);
+
+krb5_error_code krb5_hmac
+(const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, unsigned int icount,
+		const krb5_data *input, krb5_data *output);
+
+krb5_error_code krb5int_pbkdf2_hmac_sha1 (const krb5_data *, unsigned long,
+					  const krb5_data *,
+					  const krb5_data *);
+
+/* Make this a function eventually?  */
+#ifdef _WIN32
+# define krb5int_zap_data(ptr, len) SecureZeroMemory(ptr, len)
+#elif defined(__palmos__) && !defined(__GNUC__)
+/* CodeWarrior 8.3 complains about passing a pointer to volatile in to
+   memset.  On the other hand, we probably want it for gcc.  */
+# define krb5int_zap_data(ptr, len) memset(ptr, 0, len)
+#else
+# define krb5int_zap_data(ptr, len) memset((volatile void *)ptr, 0, len)
+# if defined(__GNUC__) && defined(__GLIBC__)
+/* GNU libc generates multiple bogus initialization warnings if we
+   pass memset a volatile pointer.  The compiler should do well enough
+   with memset even without GNU libc's attempt at optimization.  */
+# undef memset
+# endif
+#endif /* WIN32 */
+#define zap(p,l) krb5int_zap_data(p,l)
+
+/* A definition of init_state for DES based encryption systems.
+ * sets up an 8-byte IV of all zeros
+ */
+
+krb5_error_code krb5int_des_init_state
+(const krb5_keyblock *key, krb5_keyusage keyusage, krb5_data *new_state);
+
+/* 
+ * normally to free a cipher_state you can just memset the length to zero and
+ * free it.
+ */
+krb5_error_code krb5int_default_free_state
+(krb5_data *state);
+
+
+/*
+ * Combine two keys (normally used by the hardware preauth mechanism)
+ */
+krb5_error_code krb5int_c_combine_keys
+(krb5_context context, krb5_keyblock *key1, krb5_keyblock *key2,
+		krb5_keyblock *outkey);
+
+void  krb5int_c_free_keyblock
+(krb5_context, krb5_keyblock *key);
+void  krb5int_c_free_keyblock_contents
+	(krb5_context, krb5_keyblock *);
+krb5_error_code   krb5int_c_init_keyblock
+		(krb5_context, krb5_enctype enctype,
+		size_t length, krb5_keyblock **out); 
+
+/*
+ * Internal - for cleanup.
+ */
+extern void krb5int_prng_cleanup (void);
+
+
+/* 
+ * These declarations are here, so both krb5 and k5crypto
+ * can get to them.
+ * krb5 needs to get to them so it can  make them available to libgssapi.
+ */
+extern const struct krb5_enc_provider krb5int_enc_arcfour;
+extern const struct krb5_hash_provider krb5int_hash_md5;
+
+
+#ifdef KRB5_OLD_CRYPTO
+/* old provider api */
+
+krb5_error_code krb5_crypto_os_localaddr
+	(krb5_address ***);
+
+krb5_error_code krb5_crypto_us_timeofday
+	(krb5_int32 *,
+		krb5_int32 *);
+
+time_t krb5int_gmt_mktime (struct tm *);
+
+#endif /* KRB5_OLD_CRYPTO */
+
+/* this helper fct is in libkrb5, but it makes sense declared here. */
+
+krb5_error_code krb5_encrypt_helper
+(krb5_context context, const krb5_keyblock *key,
+		krb5_keyusage keyusage, const krb5_data *plain,
+		krb5_enc_data *cipher);
+
+/*
+ * End "los-proto.h"
+ */
+
+/*
+ * Begin "libos.h"
+ */
+#ifndef KRB5_LIBOS__
+#define KRB5_LIBOS__
+
+typedef struct _krb5_os_context {
+	krb5_magic		magic;
+	krb5_int32		time_offset;
+	krb5_int32		usec_offset;
+	krb5_int32		os_flags;
+	char *			default_ccname;
+} *krb5_os_context;
+
+/*
+ * Flags for the os_flags field
+ *
+ * KRB5_OS_TOFFSET_VALID means that the time offset fields are valid.
+ * The intention is that this facility to correct the system clocks so
+ * that they reflect the "real" time, for systems where for some
+ * reason we can't set the system clock.  Instead we calculate the
+ * offset between the system time and real time, and store the offset
+ * in the os context so that we can correct the system clock as necessary.
+ *
+ * KRB5_OS_TOFFSET_TIME means that the time offset fields should be
+ * returned as the time by the krb5 time routines.  This should only
+ * be used for testing purposes (obviously!)
+ */
+#define KRB5_OS_TOFFSET_VALID	1
+#define KRB5_OS_TOFFSET_TIME	2
+
+/* lock mode flags */
+#define	KRB5_LOCKMODE_SHARED	0x0001
+#define	KRB5_LOCKMODE_EXCLUSIVE	0x0002
+#define	KRB5_LOCKMODE_DONTBLOCK	0x0004
+#define	KRB5_LOCKMODE_UNLOCK	0x0008
+
+#endif /* KRB5_LIBOS__ */
+/*
+ * End "libos.h"
+ */
+
+/*
+ * Define our view of the size of a DES key.
+ */
+#define	KRB5_MIT_DES_KEYSIZE		8
+/*
+ * Check if des_int.h has been included before us.  If so, then check to see
+ * that our view of the DES key size is the same as des_int.h's.
+ */
+#ifdef	MIT_DES_KEYSIZE
+#if	MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE
+error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE)
+#endif	/* MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE */
+#endif	/* MIT_DES_KEYSIZE */
+
+/*
+ * Begin "preauth.h"
+ *
+ * (Originally written by Glen Machin at Sandia Labs.)
+ */
+/*
+ * Sandia National Laboratories also makes no representations about the 
+ * suitability of the modifications, or additions to this software for 
+ * any purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ */
+#ifndef KRB5_PREAUTH__
+#define KRB5_PREAUTH__
+
+#include <krb5/preauth_plugin.h>
+
+#define CLIENT_ROCK_MAGIC 0x4352434b
+/* This structure is passed into the client preauth functions and passed
+ * back to the "get_data_proc" function so that it can locate the
+ * requested information.  It is opaque to the plugin code and can be
+ * expanded in the future as new types of requests are defined which
+ * may require other things to be passed through. */
+typedef struct _krb5_preauth_client_rock {
+	krb5_magic	magic;
+	krb5_kdc_rep	*as_reply;
+} krb5_preauth_client_rock;
+
+/* This structure lets us keep track of all of the modules which are loaded,
+ * turning the list of modules and their lists of implemented preauth types
+ * into a single list which we can walk easily. */
+typedef struct _krb5_preauth_context {
+    int n_modules;
+    struct _krb5_preauth_context_module {
+	/* Which of the possibly more than one preauth types which the
+	 * module supports we're using at this point in the list. */
+	krb5_preauthtype pa_type;
+	/* Encryption types which the client claims to support -- we
+	 * copy them directly into the krb5_kdc_req structure during
+	 * krb5_preauth_prepare_request(). */
+	krb5_enctype *enctypes;
+	/* The plugin's per-plugin context and a function to clear it. */
+	void *plugin_context;
+	preauth_client_plugin_fini_proc client_fini;
+	/* The module's table, and some of its members, copied here for
+	 * convenience when we populated the list. */
+	struct krb5plugin_preauth_client_ftable_v1 *ftable;
+	const char *name;
+	int flags, use_count;
+	preauth_client_process_proc client_process;
+	preauth_client_tryagain_proc client_tryagain;
+	preauth_client_supply_gic_opts_proc client_supply_gic_opts;
+	preauth_client_request_init_proc client_req_init;
+	preauth_client_request_fini_proc client_req_fini;
+	/* The per-request context which the client_req_init() function
+	 * might allocate, which we'll need to clean up later by
+	 * calling the client_req_fini() function. */
+	void *request_context;
+	/* A pointer to the request_context pointer.  All modules within
+	 * a plugin will point at the request_context of the first
+	 * module within the plugin. */
+	void **request_context_pp;
+    } *modules;
+} krb5_preauth_context;
+
+typedef struct _krb5_pa_enc_ts {
+    krb5_timestamp	patimestamp;
+    krb5_int32		pausec;
+} krb5_pa_enc_ts;
+
+typedef krb5_error_code (*krb5_preauth_obtain_proc)
+    (krb5_context,
+		    krb5_pa_data *,
+		    krb5_etype_info,
+		    krb5_keyblock *, 
+		    krb5_error_code ( * )(krb5_context,
+					  const krb5_enctype,
+					  krb5_data *,
+					  krb5_const_pointer,
+					  krb5_keyblock **),
+		    krb5_const_pointer,
+		    krb5_creds *,
+		    krb5_kdc_req *,
+		    krb5_pa_data **);
+
+typedef krb5_error_code (*krb5_preauth_process_proc)
+    (krb5_context,
+		    krb5_pa_data *,
+		    krb5_kdc_req *,
+		    krb5_kdc_rep *,
+		    krb5_error_code ( * )(krb5_context,
+					  const krb5_enctype,
+					  krb5_data *,
+					  krb5_const_pointer,
+					  krb5_keyblock **),
+		    krb5_const_pointer,
+		    krb5_error_code ( * )(krb5_context,
+					  const krb5_keyblock *,
+					  krb5_const_pointer,
+					  krb5_kdc_rep * ),
+		    krb5_keyblock **,
+		    krb5_creds *, 
+		    krb5_int32 *,
+		    krb5_int32 *);
+
+typedef struct _krb5_preauth_ops {
+    krb5_magic magic;
+    int     type;
+    int	flags;
+    krb5_preauth_obtain_proc	obtain;
+    krb5_preauth_process_proc	process;
+} krb5_preauth_ops;
+
+krb5_error_code krb5_obtain_padata
+    	(krb5_context,
+		krb5_pa_data **,
+		krb5_error_code ( * )(krb5_context,
+						      const krb5_enctype,
+						      krb5_data *,
+						      krb5_const_pointer,
+						      krb5_keyblock **),
+		krb5_const_pointer, 
+		krb5_creds *,
+		krb5_kdc_req *);
+
+krb5_error_code krb5_process_padata
+	(krb5_context,
+		krb5_kdc_req *,
+		krb5_kdc_rep *,
+		krb5_error_code ( * )(krb5_context,
+						      const krb5_enctype,
+						      krb5_data *,
+						      krb5_const_pointer,
+						      krb5_keyblock **),
+		krb5_const_pointer,
+		krb5_error_code ( * )(krb5_context,
+						      const krb5_keyblock *,
+						      krb5_const_pointer,
+						      krb5_kdc_rep * ),
+		krb5_keyblock **, 	
+		krb5_creds *, 
+		krb5_int32 *);		
+
+void krb5_free_etype_info
+    (krb5_context, krb5_etype_info);
+
+/*
+ * Preauthentication property flags
+ */
+#define KRB5_PREAUTH_FLAGS_ENCRYPT	0x00000001
+#define KRB5_PREAUTH_FLAGS_HARDWARE	0x00000002
+
+#endif /* KRB5_PREAUTH__ */
+/*
+ * End "preauth.h"
+ */
+
+/*
+ * Extending the krb5_get_init_creds_opt structure.  The original
+ * krb5_get_init_creds_opt structure is defined publicly.  The
+ * new extended version is private.  The original interface
+ * assumed a pre-allocated structure which was passed to
+ * krb5_get_init_creds_init().  The new interface assumes that
+ * the caller will call krb5_get_init_creds_alloc() and
+ * krb5_get_init_creds_free().
+ *
+ * Callers MUST NOT call krb5_get_init_creds_init() after allocating an
+ * opts structure using krb5_get_init_creds_alloc().  To do so will
+ * introduce memory leaks.  Unfortunately, there is no way to enforce
+ * this behavior.
+ *
+ * Two private flags are added for backward compatibility.
+ * KRB5_GET_INIT_CREDS_OPT_EXTENDED says that the structure was allocated
+ * with the new krb5_get_init_creds_opt_alloc() function.
+ * KRB5_GET_INIT_CREDS_OPT_SHADOWED is set to indicate that the extended
+ * structure is a shadow copy of an original krb5_get_init_creds_opt
+ * structure.  
+ * If KRB5_GET_INIT_CREDS_OPT_SHADOWED is set after a call to
+ * krb5int_gic_opt_to_opte(), the resulting extended structure should be
+ * freed (using krb5_get_init_creds_free).  Otherwise, the original
+ * structure was already extended and there is no need to free it.
+ */
+
+#define KRB5_GET_INIT_CREDS_OPT_EXTENDED 0x80000000
+#define KRB5_GET_INIT_CREDS_OPT_SHADOWED 0x40000000
+
+#define krb5_gic_opt_is_extended(s) \
+    ((s) && ((s)->flags & KRB5_GET_INIT_CREDS_OPT_EXTENDED) ? 1 : 0)
+#define krb5_gic_opt_is_shadowed(s) \
+    ((s) && ((s)->flags & KRB5_GET_INIT_CREDS_OPT_SHADOWED) ? 1 : 0)
+
+
+typedef struct _krb5_gic_opt_private {
+    int num_preauth_data;
+    krb5_gic_opt_pa_data *preauth_data;
+} krb5_gic_opt_private;
+
+typedef struct _krb5_gic_opt_ext {
+    krb5_flags flags;
+    krb5_deltat tkt_life;
+    krb5_deltat renew_life;
+    int forwardable;
+    int proxiable;
+    krb5_enctype *etype_list;
+    int etype_list_length;
+    krb5_address **address_list;
+    krb5_preauthtype *preauth_list;
+    int preauth_list_length;
+    krb5_data *salt;
+    /*
+     * Do not change anything above this point in this structure.
+     * It is identical to the public krb5_get_init_creds_opt structure.
+     * New members must be added below.
+     */
+    krb5_gic_opt_private *opt_private;
+} krb5_gic_opt_ext;
+
+krb5_error_code
+krb5int_gic_opt_to_opte(krb5_context context,
+                        krb5_get_init_creds_opt *opt,
+                        krb5_gic_opt_ext **opte,
+                        unsigned int force,
+                        const char *where);
+
+krb5_error_code
+krb5int_copy_data_contents (krb5_context, const krb5_data *, krb5_data *);
+
+typedef krb5_error_code (*krb5_gic_get_as_key_fct)
+    (krb5_context,
+		     krb5_principal,
+		     krb5_enctype,
+		     krb5_prompter_fct,
+		     void *prompter_data,
+		     krb5_data *salt,
+     krb5_data *s2kparams,
+		     krb5_keyblock *as_key,
+		     void *gak_data);
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds
+(krb5_context context,
+		krb5_creds *creds,
+		krb5_principal client,
+		krb5_prompter_fct prompter,
+		void *prompter_data,
+		krb5_deltat start_time,
+		char *in_tkt_service,
+		krb5_gic_opt_ext *gic_options,
+		krb5_gic_get_as_key_fct gak,
+		void *gak_data,
+		int *master,
+		krb5_kdc_rep **as_reply);
+
+krb5_error_code krb5int_populate_gic_opt (
+    krb5_context, krb5_gic_opt_ext **,
+    krb5_flags options, krb5_address * const *addrs, krb5_enctype *ktypes,
+    krb5_preauthtype *pre_auth_types, krb5_creds *creds);
+
+
+krb5_error_code KRB5_CALLCONV krb5_do_preauth
+	(krb5_context context,
+	 krb5_kdc_req *request,
+	 krb5_data *encoded_request_body,
+	 krb5_data *encoded_previous_request,
+	 krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
+	 krb5_data *salt, krb5_data *s2kparams,
+	 krb5_enctype *etype, krb5_keyblock *as_key,
+	 krb5_prompter_fct prompter, void *prompter_data,
+	 krb5_gic_get_as_key_fct gak_fct, void *gak_data,
+	 krb5_preauth_client_rock *get_data_rock,
+	 krb5_gic_opt_ext *opte);
+krb5_error_code KRB5_CALLCONV krb5_do_preauth_tryagain
+	(krb5_context context,
+	 krb5_kdc_req *request,
+	 krb5_data *encoded_request_body,
+	 krb5_data *encoded_previous_request,
+	 krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
+	 krb5_error *err_reply,
+	 krb5_data *salt, krb5_data *s2kparams,
+	 krb5_enctype *etype, krb5_keyblock *as_key,
+	 krb5_prompter_fct prompter, void *prompter_data,
+	 krb5_gic_get_as_key_fct gak_fct, void *gak_data,
+	 krb5_preauth_client_rock *get_data_rock,
+	 krb5_gic_opt_ext *opte);
+void KRB5_CALLCONV krb5_init_preauth_context
+	(krb5_context);
+void KRB5_CALLCONV krb5_free_preauth_context
+	(krb5_context);
+void KRB5_CALLCONV krb5_clear_preauth_context_use_counts
+	(krb5_context);
+void KRB5_CALLCONV krb5_preauth_prepare_request
+	(krb5_context, krb5_gic_opt_ext *, krb5_kdc_req *);
+void KRB5_CALLCONV krb5_preauth_request_context_init
+	(krb5_context);
+void KRB5_CALLCONV krb5_preauth_request_context_fini
+	(krb5_context);
+
+void KRB5_CALLCONV krb5_free_sam_challenge
+	(krb5_context, krb5_sam_challenge * );
+void KRB5_CALLCONV krb5_free_sam_challenge_2
+	(krb5_context, krb5_sam_challenge_2 * );
+void KRB5_CALLCONV krb5_free_sam_challenge_2_body
+	(krb5_context, krb5_sam_challenge_2_body *);
+void KRB5_CALLCONV krb5_free_sam_response
+	(krb5_context, krb5_sam_response * );
+void KRB5_CALLCONV krb5_free_sam_response_2
+	(krb5_context, krb5_sam_response_2 * );
+void KRB5_CALLCONV krb5_free_predicted_sam_response
+	(krb5_context, krb5_predicted_sam_response * );
+void KRB5_CALLCONV krb5_free_enc_sam_response_enc
+	(krb5_context, krb5_enc_sam_response_enc * );
+void KRB5_CALLCONV krb5_free_enc_sam_response_enc_2
+	(krb5_context, krb5_enc_sam_response_enc_2 * );
+void KRB5_CALLCONV krb5_free_sam_challenge_contents
+	(krb5_context, krb5_sam_challenge * );
+void KRB5_CALLCONV krb5_free_sam_challenge_2_contents
+	(krb5_context, krb5_sam_challenge_2 * );
+void KRB5_CALLCONV krb5_free_sam_challenge_2_body_contents
+	(krb5_context, krb5_sam_challenge_2_body * );
+void KRB5_CALLCONV krb5_free_sam_response_contents
+	(krb5_context, krb5_sam_response * );
+void KRB5_CALLCONV krb5_free_sam_response_2_contents
+	(krb5_context, krb5_sam_response_2 *);
+void KRB5_CALLCONV krb5_free_predicted_sam_response_contents
+	(krb5_context, krb5_predicted_sam_response * );
+void KRB5_CALLCONV krb5_free_enc_sam_response_enc_contents
+	(krb5_context, krb5_enc_sam_response_enc * );
+void KRB5_CALLCONV krb5_free_enc_sam_response_enc_2_contents
+	(krb5_context, krb5_enc_sam_response_enc_2 * );
+ 
+void KRB5_CALLCONV krb5_free_pa_enc_ts
+	(krb5_context, krb5_pa_enc_ts *);
+
+/* #include "krb5/wordsize.h" -- comes in through base-defs.h. */
+#include "com_err.h"
+#include "k5-plugin.h"
+
+struct _krb5_context {
+	krb5_magic	magic;
+	krb5_enctype	*in_tkt_ktypes;
+	unsigned int	in_tkt_ktype_count;
+	krb5_enctype	*tgs_ktypes;
+	unsigned int	tgs_ktype_count;
+	/* This used to be a void*, but since we always allocate them
+	   together (though in different source files), and the types
+	   are declared in the same header, might as well just combine
+	   them.
+
+	   The array[1] is so the existing code treating the field as
+	   a pointer will still work.  For cleanliness, it should
+	   eventually get changed to a single element instead of an
+	   array.  */
+	struct _krb5_os_context	os_context[1];
+	char		*default_realm;
+	profile_t	profile;
+	void		*db_context;
+	int		ser_ctx_count;
+	void		*ser_ctx;
+	/* allowable clock skew */
+	krb5_deltat 	clockskew;
+	krb5_cksumtype	kdc_req_sumtype;
+	krb5_cksumtype	default_ap_req_sumtype;
+	krb5_cksumtype	default_safe_sumtype;
+	krb5_flags 	kdc_default_options;
+	krb5_flags	library_options;
+	krb5_boolean	profile_secure;
+	int		fcc_default_format;
+	int		scc_default_format;
+	krb5_prompt_type *prompt_types;
+	/* Message size above which we'll try TCP first in send-to-kdc
+	   type code.  Aside from the 2**16 size limit, we put no
+	   absolute limit on the UDP packet size.  */
+	int		udp_pref_limit;
+
+	/* Use the config-file ktypes instead of app-specified?  */
+	krb5_boolean	use_conf_ktypes;
+
+#ifdef KRB5_DNS_LOOKUP
+        krb5_boolean    profile_in_memory;
+#endif /* KRB5_DNS_LOOKUP */
+
+    /* locate_kdc module stuff */
+    struct plugin_dir_handle libkrb5_plugins;
+    struct krb5plugin_service_locate_ftable *vtbl;
+    void (**locate_fptrs)(void);
+
+    /* preauth module stuff */
+    struct plugin_dir_handle preauth_plugins;
+    krb5_preauth_context *preauth_context;
+
+    /* error detail info */
+    struct errinfo err;
+};
+
+/* could be used in a table to find an etype and initialize a block */
+
+
+#define KRB5_LIBOPT_SYNC_KDCTIME	0x0001
+
+/* internal message representations */
+
+typedef struct _krb5_safe {
+    krb5_magic magic;
+    krb5_data user_data;		/* user data */
+    krb5_timestamp timestamp;		/* client time, optional */
+    krb5_int32 usec;			/* microsecond portion of time,
+					   optional */
+    krb5_ui_4 seq_number;		/* sequence #, optional */
+    krb5_address *s_address;	/* sender address */
+    krb5_address *r_address;	/* recipient address, optional */
+    krb5_checksum *checksum;	/* data integrity checksum */
+} krb5_safe;
+
+typedef struct _krb5_priv {
+    krb5_magic magic;
+    krb5_enc_data enc_part;		/* encrypted part */
+} krb5_priv;
+
+typedef struct _krb5_priv_enc_part {
+    krb5_magic magic;
+    krb5_data user_data;		/* user data */
+    krb5_timestamp timestamp;		/* client time, optional */
+    krb5_int32 usec;			/* microsecond portion of time, opt. */
+    krb5_ui_4 seq_number;		/* sequence #, optional */
+    krb5_address *s_address;	/* sender address */
+    krb5_address *r_address;	/* recipient address, optional */
+} krb5_priv_enc_part;
+
+void KRB5_CALLCONV krb5_free_safe
+	(krb5_context, krb5_safe * );
+void KRB5_CALLCONV krb5_free_priv
+	(krb5_context, krb5_priv * );
+void KRB5_CALLCONV krb5_free_priv_enc_part
+	(krb5_context, krb5_priv_enc_part * );
+
+/*
+ * Begin "asn1.h"
+ */
+#ifndef KRB5_ASN1__
+#define KRB5_ASN1__
+
+/* ASN.1 encoding knowledge; KEEP IN SYNC WITH ASN.1 defs! */
+/* here we use some knowledge of ASN.1 encodings */
+/* 
+  Ticket is APPLICATION 1.
+  Authenticator is APPLICATION 2.
+  AS_REQ is APPLICATION 10.
+  AS_REP is APPLICATION 11.
+  TGS_REQ is APPLICATION 12.
+  TGS_REP is APPLICATION 13.
+  AP_REQ is APPLICATION 14.
+  AP_REP is APPLICATION 15.
+  KRB_SAFE is APPLICATION 20.
+  KRB_PRIV is APPLICATION 21.
+  KRB_CRED is APPLICATION 22.
+  EncASRepPart is APPLICATION 25.
+  EncTGSRepPart is APPLICATION 26.
+  EncAPRepPart is APPLICATION 27.
+  EncKrbPrivPart is APPLICATION 28.
+  EncKrbCredPart is APPLICATION 29.
+  KRB_ERROR is APPLICATION 30.
+ */
+/* allow either constructed or primitive encoding, so check for bit 6
+   set or reset */
+#define krb5_is_krb_ticket(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x61 ||\
+				    (dat)->data[0] == 0x41))
+#define krb5_is_krb_authenticator(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x62 ||\
+				    (dat)->data[0] == 0x42))
+#define krb5_is_as_req(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x6a ||\
+				    (dat)->data[0] == 0x4a))
+#define krb5_is_as_rep(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x6b ||\
+				    (dat)->data[0] == 0x4b))
+#define krb5_is_tgs_req(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x6c ||\
+				    (dat)->data[0] == 0x4c))
+#define krb5_is_tgs_rep(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x6d ||\
+				    (dat)->data[0] == 0x4d))
+#define krb5_is_ap_req(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x6e ||\
+				    (dat)->data[0] == 0x4e))
+#define krb5_is_ap_rep(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x6f ||\
+				    (dat)->data[0] == 0x4f))
+#define krb5_is_krb_safe(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x74 ||\
+				    (dat)->data[0] == 0x54))
+#define krb5_is_krb_priv(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x75 ||\
+				    (dat)->data[0] == 0x55))
+#define krb5_is_krb_cred(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x76 ||\
+				    (dat)->data[0] == 0x56))
+#define krb5_is_krb_enc_as_rep_part(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x79 ||\
+				    (dat)->data[0] == 0x59))
+#define krb5_is_krb_enc_tgs_rep_part(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x7a ||\
+				    (dat)->data[0] == 0x5a))
+#define krb5_is_krb_enc_ap_rep_part(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x7b ||\
+				    (dat)->data[0] == 0x5b))
+#define krb5_is_krb_enc_krb_priv_part(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x7c ||\
+				    (dat)->data[0] == 0x5c))
+#define krb5_is_krb_enc_krb_cred_part(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x7d ||\
+				    (dat)->data[0] == 0x5d))
+#define krb5_is_krb_error(dat)\
+	((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
+				    (dat)->data[0] == 0x5e))
+
+/*************************************************************************
+ * Prototypes for krb5_encode.c
+ *************************************************************************/
+
+/*
+   krb5_error_code encode_krb5_structure(const krb5_structure *rep,
+					 krb5_data **code);
+   modifies  *code
+   effects   Returns the ASN.1 encoding of *rep in **code.
+             Returns ASN1_MISSING_FIELD if a required field is emtpy in *rep.
+             Returns ENOMEM if memory runs out.
+*/
+
+krb5_error_code encode_krb5_authenticator
+	(const krb5_authenticator *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_ticket
+	(const krb5_ticket *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_encryption_key
+	(const krb5_keyblock *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_enc_tkt_part
+	(const krb5_enc_tkt_part *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_enc_kdc_rep_part
+	(const krb5_enc_kdc_rep_part *rep, krb5_data **code);
+
+/* yes, the translation is identical to that used for KDC__REP */ 
+krb5_error_code encode_krb5_as_rep
+	(const krb5_kdc_rep *rep, krb5_data **code);
+
+/* yes, the translation is identical to that used for KDC__REP */ 
+krb5_error_code encode_krb5_tgs_rep
+	(const krb5_kdc_rep *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_ap_req
+	(const krb5_ap_req *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_ap_rep
+	(const krb5_ap_rep *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_ap_rep_enc_part
+	(const krb5_ap_rep_enc_part *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_as_req
+	(const krb5_kdc_req *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_tgs_req
+	(const krb5_kdc_req *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_kdc_req_body
+	(const krb5_kdc_req *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_safe
+	(const krb5_safe *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_safe_with_body
+	(const krb5_safe *rep, const krb5_data *body, krb5_data **code);
+
+krb5_error_code encode_krb5_priv
+	(const krb5_priv *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_enc_priv_part
+	(const krb5_priv_enc_part *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_cred
+	(const krb5_cred *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_enc_cred_part
+	(const krb5_cred_enc_part *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_error
+	(const krb5_error *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_authdata
+	(const krb5_authdata **rep, krb5_data **code);
+
+krb5_error_code encode_krb5_authdata_elt
+	(const krb5_authdata *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pwd_sequence
+	(const passwd_phrase_element *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pwd_data
+	(const krb5_pwd_data *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_padata_sequence
+	(const krb5_pa_data ** rep, krb5_data **code);
+
+krb5_error_code encode_krb5_alt_method
+	(const krb5_alt_method *, krb5_data **code);
+
+krb5_error_code encode_krb5_etype_info
+	(const krb5_etype_info_entry **, krb5_data **code);
+krb5_error_code encode_krb5_etype_info2
+	(const krb5_etype_info_entry **, krb5_data **code);
+
+krb5_error_code encode_krb5_enc_data
+    	(const krb5_enc_data *, krb5_data **);
+
+krb5_error_code encode_krb5_pa_enc_ts
+    	(const krb5_pa_enc_ts *, krb5_data **);
+
+krb5_error_code encode_krb5_sam_challenge
+	(const krb5_sam_challenge * , krb5_data **);
+
+krb5_error_code encode_krb5_sam_key
+	(const krb5_sam_key * , krb5_data **);
+
+krb5_error_code encode_krb5_enc_sam_response_enc
+	(const krb5_enc_sam_response_enc * , krb5_data **);
+
+krb5_error_code encode_krb5_sam_response
+	(const krb5_sam_response * , krb5_data **);
+
+krb5_error_code encode_krb5_sam_challenge_2
+	(const krb5_sam_challenge_2 * , krb5_data **);
+
+krb5_error_code encode_krb5_sam_challenge_2_body
+	(const krb5_sam_challenge_2_body * , krb5_data **);
+
+krb5_error_code encode_krb5_enc_sam_response_enc_2
+	(const krb5_enc_sam_response_enc_2 * , krb5_data **);
+
+krb5_error_code encode_krb5_sam_response_2
+	(const krb5_sam_response_2 * , krb5_data **);
+
+krb5_error_code encode_krb5_predicted_sam_response
+	(const krb5_predicted_sam_response * , krb5_data **);
+
+krb5_error_code encode_krb5_setpw_req
+(const krb5_principal target, char *password, krb5_data **code);
+
+/*************************************************************************
+ * End of prototypes for krb5_encode.c
+ *************************************************************************/
+
+krb5_error_code decode_krb5_sam_challenge
+       (const krb5_data *, krb5_sam_challenge **);
+
+krb5_error_code decode_krb5_enc_sam_key
+       (const krb5_data *, krb5_sam_key **);
+
+krb5_error_code decode_krb5_enc_sam_response_enc
+       (const krb5_data *, krb5_enc_sam_response_enc **);
+
+krb5_error_code decode_krb5_sam_response
+       (const krb5_data *, krb5_sam_response **);
+
+krb5_error_code decode_krb5_predicted_sam_response
+       (const krb5_data *, krb5_predicted_sam_response **);
+
+krb5_error_code decode_krb5_sam_challenge_2
+	(const krb5_data *, krb5_sam_challenge_2 **);
+
+krb5_error_code decode_krb5_sam_challenge_2_body
+	(const krb5_data *, krb5_sam_challenge_2_body **);
+
+krb5_error_code decode_krb5_enc_sam_response_enc_2
+	(const krb5_data *, krb5_enc_sam_response_enc_2 **);
+
+krb5_error_code decode_krb5_sam_response_2
+	(const krb5_data *, krb5_sam_response_2 **);
+
+
+/*************************************************************************
+ * Prototypes for krb5_decode.c
+ *************************************************************************/
+
+krb5_error_code krb5_validate_times
+       (krb5_context, 
+		       krb5_ticket_times *);
+
+/*
+   krb5_error_code decode_krb5_structure(const krb5_data *code,
+                                         krb5_structure **rep);
+                                         
+   requires  Expects **rep to not have been allocated;
+              a new *rep is allocated regardless of the old value.
+   effects   Decodes *code into **rep.
+	     Returns ENOMEM if memory is exhausted.
+             Returns asn1 and krb5 errors.
+*/
+
+krb5_error_code decode_krb5_authenticator
+	(const krb5_data *code, krb5_authenticator **rep);
+
+krb5_error_code decode_krb5_ticket
+	(const krb5_data *code, krb5_ticket **rep);
+
+krb5_error_code decode_krb5_encryption_key
+	(const krb5_data *output, krb5_keyblock **rep);
+
+krb5_error_code decode_krb5_enc_tkt_part
+	(const krb5_data *output, krb5_enc_tkt_part **rep);
+
+krb5_error_code decode_krb5_enc_kdc_rep_part
+	(const krb5_data *output, krb5_enc_kdc_rep_part **rep);
+
+krb5_error_code decode_krb5_as_rep
+	(const krb5_data *output, krb5_kdc_rep **rep);
+
+krb5_error_code decode_krb5_tgs_rep
+	(const krb5_data *output, krb5_kdc_rep **rep);
+
+krb5_error_code decode_krb5_ap_req
+	(const krb5_data *output, krb5_ap_req **rep);
+
+krb5_error_code decode_krb5_ap_rep
+	(const krb5_data *output, krb5_ap_rep **rep);
+
+krb5_error_code decode_krb5_ap_rep_enc_part
+	(const krb5_data *output, krb5_ap_rep_enc_part **rep);
+
+krb5_error_code decode_krb5_as_req
+	(const krb5_data *output, krb5_kdc_req **rep);
+
+krb5_error_code decode_krb5_tgs_req
+	(const krb5_data *output, krb5_kdc_req **rep);
+
+krb5_error_code decode_krb5_kdc_req_body
+	(const krb5_data *output, krb5_kdc_req **rep);
+
+krb5_error_code decode_krb5_safe
+	(const krb5_data *output, krb5_safe **rep);
+
+krb5_error_code decode_krb5_safe_with_body
+	(const krb5_data *output, krb5_safe **rep, krb5_data *body);
+
+krb5_error_code decode_krb5_priv
+	(const krb5_data *output, krb5_priv **rep);
+
+krb5_error_code decode_krb5_enc_priv_part
+	(const krb5_data *output, krb5_priv_enc_part **rep);
+
+krb5_error_code decode_krb5_cred
+	(const krb5_data *output, krb5_cred **rep);
+
+krb5_error_code decode_krb5_enc_cred_part
+	(const krb5_data *output, krb5_cred_enc_part **rep);
+
+krb5_error_code decode_krb5_error
+	(const krb5_data *output, krb5_error **rep);
+
+krb5_error_code decode_krb5_authdata
+	(const krb5_data *output, krb5_authdata ***rep);
+
+krb5_error_code decode_krb5_pwd_sequence
+	(const krb5_data *output, passwd_phrase_element **rep);
+
+krb5_error_code decode_krb5_pwd_data
+	(const krb5_data *output, krb5_pwd_data **rep);
+
+krb5_error_code decode_krb5_padata_sequence
+	(const krb5_data *output, krb5_pa_data ***rep);
+
+krb5_error_code decode_krb5_alt_method
+	(const krb5_data *output, krb5_alt_method **rep);
+
+krb5_error_code decode_krb5_etype_info
+	(const krb5_data *output, krb5_etype_info_entry ***rep);
+
+krb5_error_code decode_krb5_etype_info2
+	(const krb5_data *output, krb5_etype_info_entry ***rep);
+
+krb5_error_code decode_krb5_enc_data
+	(const krb5_data *output, krb5_enc_data **rep);
+
+krb5_error_code decode_krb5_pa_enc_ts
+	(const krb5_data *output, krb5_pa_enc_ts **rep);
+
+krb5_error_code decode_krb5_sam_key
+	(const krb5_data *, krb5_sam_key **);
+
+struct _krb5_key_data;		/* kdb.h */
+krb5_error_code
+krb5int_ldap_encode_sequence_of_keys (struct _krb5_key_data *key_data,
+				      krb5_int16 n_key_data,
+				      krb5_int32 mkvno,
+				      krb5_data **code);
+
+krb5_error_code
+krb5int_ldap_decode_sequence_of_keys (krb5_data *in,
+				      struct _krb5_key_data **out,
+				      krb5_int16 *n_key_data,
+				      int *mkvno);
+
+/*************************************************************************
+ * End of prototypes for krb5_decode.c
+ *************************************************************************/
+
+#endif /* KRB5_ASN1__ */
+/*
+ * End "asn1.h"
+ */
+
+
+/*
+ * Internal krb5 library routines
+ */
+krb5_error_code krb5_encrypt_tkt_part
+	(krb5_context,
+		const krb5_keyblock *,
+		krb5_ticket * );
+
+
+krb5_error_code krb5_encode_kdc_rep
+	(krb5_context,
+		const krb5_msgtype,
+		const krb5_enc_kdc_rep_part *,
+		int using_subkey,
+		const krb5_keyblock *,
+		krb5_kdc_rep *,
+		krb5_data ** );
+
+krb5_boolean krb5int_auth_con_chkseqnum
+	(krb5_context ctx, krb5_auth_context ac, krb5_ui_4 in_seq);
+/*
+ * [De]Serialization Handle and operations.
+ */
+struct __krb5_serializer {
+    krb5_magic		odtype;
+    krb5_error_code	(*sizer) (krb5_context,
+						  krb5_pointer,
+						  size_t *);
+    krb5_error_code	(*externalizer) (krb5_context,
+							 krb5_pointer,
+							 krb5_octet **,
+							 size_t *);
+    krb5_error_code	(*internalizer) (krb5_context,
+							 krb5_pointer *,
+							 krb5_octet **,
+							 size_t *);
+};
+typedef const struct __krb5_serializer * krb5_ser_handle;
+typedef struct __krb5_serializer krb5_ser_entry;
+
+krb5_ser_handle krb5_find_serializer
+	(krb5_context,
+		krb5_magic);
+krb5_error_code krb5_register_serializer
+	(krb5_context,
+			const krb5_ser_entry *);
+
+/* Determine the external size of a particular opaque structure */
+krb5_error_code KRB5_CALLCONV krb5_size_opaque
+	(krb5_context,
+		krb5_magic,
+		krb5_pointer,
+		size_t *);
+
+/* Serialize the structure into a buffer */
+krb5_error_code KRB5_CALLCONV krb5_externalize_opaque
+	(krb5_context,
+		krb5_magic,
+		krb5_pointer,
+		krb5_octet **,
+		size_t *);
+
+/* Deserialize the structure from a buffer */
+krb5_error_code KRB5_CALLCONV krb5_internalize_opaque
+	(krb5_context,
+		krb5_magic,
+		krb5_pointer *,
+		krb5_octet **,
+		size_t *);
+
+/* Serialize data into a buffer */
+krb5_error_code krb5_externalize_data
+	(krb5_context,
+		krb5_pointer,
+		krb5_octet **,
+		size_t *);
+/*
+ * Initialization routines.
+ */
+
+/* Initialize serialization for krb5_[os_]context */
+krb5_error_code KRB5_CALLCONV krb5_ser_context_init
+	(krb5_context);
+
+/* Initialize serialization for krb5_auth_context */
+krb5_error_code KRB5_CALLCONV krb5_ser_auth_context_init
+	(krb5_context);
+
+/* Initialize serialization for krb5_keytab */
+krb5_error_code KRB5_CALLCONV krb5_ser_keytab_init
+	(krb5_context);
+
+/* Initialize serialization for krb5_ccache */
+krb5_error_code KRB5_CALLCONV krb5_ser_ccache_init
+	(krb5_context);
+
+/* Initialize serialization for krb5_rcache */
+krb5_error_code KRB5_CALLCONV krb5_ser_rcache_init
+	(krb5_context);
+
+/* [De]serialize 4-byte integer */
+krb5_error_code KRB5_CALLCONV krb5_ser_pack_int32
+	(krb5_int32,
+		krb5_octet **,
+		size_t *);
+krb5_error_code KRB5_CALLCONV krb5_ser_unpack_int32
+	(krb5_int32 *,
+		krb5_octet **,
+		size_t *);
+/* [De]serialize 8-byte integer */
+krb5_error_code KRB5_CALLCONV krb5_ser_pack_int64
+	(krb5_int64, krb5_octet **, size_t *);
+krb5_error_code KRB5_CALLCONV krb5_ser_unpack_int64
+	(krb5_int64 *, krb5_octet **, size_t *);
+/* [De]serialize byte string */
+krb5_error_code KRB5_CALLCONV krb5_ser_pack_bytes
+	(krb5_octet *,
+		size_t,
+		krb5_octet **,
+		size_t *);
+krb5_error_code KRB5_CALLCONV krb5_ser_unpack_bytes
+	(krb5_octet *,
+		size_t,
+		krb5_octet **,
+		size_t *);
+
+krb5_error_code KRB5_CALLCONV krb5int_cc_default
+	(krb5_context, krb5_ccache *);
+
+krb5_error_code KRB5_CALLCONV krb5_cc_retrieve_cred_default
+	(krb5_context, krb5_ccache, krb5_flags,
+			krb5_creds *, krb5_creds *);
+
+krb5_boolean KRB5_CALLCONV
+krb5_creds_compare (krb5_context in_context,
+                    krb5_creds *in_creds,
+                    krb5_creds *in_compare_creds);
+
+void krb5int_set_prompt_types
+	(krb5_context, krb5_prompt_type *);
+
+krb5_error_code
+krb5int_generate_and_save_subkey (krb5_context, krb5_auth_context,
+				  krb5_keyblock * /* Old keyblock, not new!  */);
+
+/* set and change password helpers */
+
+krb5_error_code krb5int_mk_chpw_req
+	(krb5_context context, krb5_auth_context auth_context, 
+ 			krb5_data *ap_req, char *passwd, krb5_data *packet);
+krb5_error_code krb5int_rd_chpw_rep
+	(krb5_context context, krb5_auth_context auth_context,
+		       krb5_data *packet, int *result_code,
+		       krb5_data *result_data);
+krb5_error_code KRB5_CALLCONV krb5_chpw_result_code_string
+	(krb5_context context, int result_code,
+			char **result_codestr);
+krb5_error_code  krb5int_mk_setpw_req
+	(krb5_context context, krb5_auth_context auth_context,
+ 			krb5_data *ap_req, krb5_principal targetprinc, char *passwd, krb5_data *packet);
+krb5_error_code krb5int_rd_setpw_rep
+	(krb5_context context, krb5_auth_context auth_context,
+		       krb5_data *packet, int *result_code,
+		       krb5_data *result_data);
+krb5_error_code krb5int_setpw_result_code_string
+	(krb5_context context, int result_code,
+			const char **result_codestr);
+
+struct srv_dns_entry {
+    struct srv_dns_entry *next;
+    int priority;
+    int weight;
+    unsigned short port;
+    char *host;
+};
+#ifdef KRB5_DNS_LOOKUP
+krb5_error_code
+krb5int_make_srv_query_realm(const krb5_data *realm,
+			     const char *service,
+			     const char *protocol,
+			     struct srv_dns_entry **answers);
+void krb5int_free_srv_dns_data(struct srv_dns_entry *);
+#endif
+
+/*
+ * Convenience function for structure magic number
+ */
+#define KRB5_VERIFY_MAGIC(structure,magic_number) \
+    if ((structure)->magic != (magic_number)) return (magic_number);
+
+/* to keep lint happy */
+#define krb5_xfree(val) free((char *)(val))
+
+/* To keep happy libraries which are (for now) accessing internal stuff */
+
+/* Make sure to increment by one when changing the struct */
+#define KRB5INT_ACCESS_STRUCT_VERSION 12
+
+#ifndef ANAME_SZ
+struct ktext;			/* from krb.h, for krb524 support */
+#endif
+typedef struct _krb5int_access {
+    /* crypto stuff */
+    const struct krb5_hash_provider *md5_hash_provider;
+    const struct krb5_enc_provider *arcfour_enc_provider;
+    krb5_error_code (* krb5_hmac) (const struct krb5_hash_provider *hash,
+				   const krb5_keyblock *key,
+				   unsigned int icount, const krb5_data *input,
+				   krb5_data *output);
+    /* service location and communication */
+    krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg,
+				   const struct addrlist *, struct sendto_callback_info*, krb5_data *reply,
+				   struct sockaddr *, socklen_t *,struct sockaddr *,
+				   socklen_t *, int *,
+				   int (*msg_handler)(krb5_context, const krb5_data *, void *),
+				   void *msg_handler_data);
+    krb5_error_code (*add_host_to_list)(struct addrlist *lp,
+					const char *hostname,
+					int port, int secport,
+					int socktype, int family);
+    void (*free_addrlist) (struct addrlist *);
+
+    krb5_error_code (*make_srv_query_realm)(const krb5_data *realm,
+					    const char *service,
+					    const char *protocol,
+					    struct srv_dns_entry **answers);
+    void (*free_srv_dns_data)(struct srv_dns_entry *);
+    int (*use_dns_kdc)(krb5_context);
+
+    /* krb4 compatibility stuff -- may be null if not enabled */
+    krb5_int32 (*krb_life_to_time)(krb5_int32, int);
+    int (*krb_time_to_life)(krb5_int32, krb5_int32);
+    int (*krb524_encode_v4tkt)(struct ktext *, char *, unsigned int *);
+    krb5_error_code (*krb5int_c_mandatory_cksumtype)
+        (krb5_context, krb5_enctype, krb5_cksumtype *);
+    krb5_error_code (KRB5_CALLCONV *krb5_ser_pack_int64)
+        (krb5_int64, krb5_octet **, size_t *);
+    krb5_error_code (KRB5_CALLCONV *krb5_ser_unpack_int64)
+        (krb5_int64 *, krb5_octet **, size_t *);
+
+    /* Used for KDB LDAP back end.  */
+    krb5_error_code
+    (*asn1_ldap_encode_sequence_of_keys) (struct _krb5_key_data *key_data,
+					  krb5_int16 n_key_data,
+					  krb5_int32 mkvno,
+					  krb5_data **code);
+
+    krb5_error_code
+    (*asn1_ldap_decode_sequence_of_keys) (krb5_data *in,
+					  struct _krb5_key_data **out,
+					  krb5_int16 *n_key_data,
+					  int *mkvno);
+
+    /*
+     * pkinit asn.1 encode/decode functions
+     */
+    krb5_error_code (*encode_krb5_auth_pack)
+        (const krb5_auth_pack *rep, krb5_data **code);
+    krb5_error_code (*encode_krb5_auth_pack_draft9)
+        (const krb5_auth_pack_draft9 *rep, krb5_data **code);
+    krb5_error_code (*encode_krb5_kdc_dh_key_info)
+        (const krb5_kdc_dh_key_info *rep, krb5_data **code);
+    krb5_error_code (*encode_krb5_pa_pk_as_rep)
+        (const krb5_pa_pk_as_rep *rep, krb5_data **code);
+    krb5_error_code (*encode_krb5_pa_pk_as_rep_draft9)
+        (const krb5_pa_pk_as_rep_draft9 *rep, krb5_data **code);
+    krb5_error_code (*encode_krb5_pa_pk_as_req)
+	(const krb5_pa_pk_as_req *rep, krb5_data **code);
+    krb5_error_code (*encode_krb5_pa_pk_as_req_draft9)
+	(const krb5_pa_pk_as_req_draft9 *rep, krb5_data **code);
+    krb5_error_code (*encode_krb5_reply_key_pack)
+        (const krb5_reply_key_pack *, krb5_data **code);
+    krb5_error_code (*encode_krb5_reply_key_pack_draft9)
+        (const krb5_reply_key_pack_draft9 *, krb5_data **code);
+    krb5_error_code (*encode_krb5_td_dh_parameters)
+        (const krb5_algorithm_identifier **, krb5_data **code);
+    krb5_error_code (*encode_krb5_td_trusted_certifiers)
+        (const krb5_external_principal_identifier **, krb5_data **code);
+    krb5_error_code (*encode_krb5_typed_data)
+        (const krb5_typed_data **, krb5_data **code);
+
+    krb5_error_code (*decode_krb5_auth_pack)
+        (const krb5_data *, krb5_auth_pack **);
+    krb5_error_code (*decode_krb5_auth_pack_draft9)
+        (const krb5_data *, krb5_auth_pack_draft9 **);
+    krb5_error_code (*decode_krb5_pa_pk_as_req)
+        (const krb5_data *, krb5_pa_pk_as_req **);
+    krb5_error_code (*decode_krb5_pa_pk_as_req_draft9)
+        (const krb5_data *, krb5_pa_pk_as_req_draft9 **);
+    krb5_error_code (*decode_krb5_pa_pk_as_rep)
+        (const krb5_data *, krb5_pa_pk_as_rep **);
+    krb5_error_code (*decode_krb5_pa_pk_as_rep_draft9)
+        (const krb5_data *, krb5_pa_pk_as_rep_draft9 **);
+    krb5_error_code (*decode_krb5_kdc_dh_key_info)
+        (const krb5_data *, krb5_kdc_dh_key_info **);
+    krb5_error_code (*decode_krb5_principal_name)
+        (const krb5_data *, krb5_principal_data **);
+    krb5_error_code (*decode_krb5_reply_key_pack)
+        (const krb5_data *, krb5_reply_key_pack **);
+    krb5_error_code (*decode_krb5_reply_key_pack_draft9)
+        (const krb5_data *, krb5_reply_key_pack_draft9 **);
+    krb5_error_code (*decode_krb5_td_dh_parameters)
+        (const krb5_data *, krb5_algorithm_identifier ***);
+    krb5_error_code (*decode_krb5_td_trusted_certifiers)
+        (const krb5_data *, krb5_external_principal_identifier ***);
+    krb5_error_code (*decode_krb5_typed_data)
+        (const krb5_data *, krb5_typed_data ***);
+
+    krb5_error_code (*decode_krb5_as_req)
+	(const krb5_data *output, krb5_kdc_req **rep);
+    krb5_error_code (*encode_krb5_kdc_req_body)
+	(const krb5_kdc_req *rep, krb5_data **code);
+    void (KRB5_CALLCONV *krb5_free_kdc_req)
+	(krb5_context, krb5_kdc_req * );
+    void (*krb5int_set_prompt_types)
+	(krb5_context, krb5_prompt_type *);
+    krb5_error_code (*encode_krb5_authdata_elt)
+	(const krb5_authdata *rep, krb5_data **code);
+
+} krb5int_access;
+
+#define KRB5INT_ACCESS_VERSION \
+    (((krb5_int32)((sizeof(krb5int_access) & 0xFFFF) | \
+		   (KRB5INT_ACCESS_STRUCT_VERSION << 16))) & 0xFFFFFFFF)
+
+krb5_error_code KRB5_CALLCONV krb5int_accessor
+	(krb5int_access*, krb5_int32);
+
+/* Ick -- some krb524 and krb4 support placed in the krb5 library,
+   because AFS (and potentially other applications?) use the krb4
+   object as an opaque token, which (in some implementations) is not
+   in fact a krb4 ticket, so we don't want to drag in the krb4 support
+   just to enable this.  */
+
+#define KRB524_SERVICE "krb524"
+#define KRB524_PORT 4444
+
+/* v4lifetime.c */
+extern krb5_int32 krb5int_krb_life_to_time(krb5_int32, int);
+extern int krb5int_krb_time_to_life(krb5_int32, krb5_int32);
+
+/* conv_creds.c */
+int krb5int_encode_v4tkt
+	(struct ktext *v4tkt, char *buf, unsigned int *encoded_len);
+
+/* send524.c */
+int krb5int_524_sendto_kdc
+        (krb5_context context, const krb5_data * message, 
+	 const krb5_data * realm, krb5_data * reply,
+	 struct sockaddr *, socklen_t *);
+
+/* temporary -- this should be under lib/krb5/ccache somewhere */
+
+struct _krb5_ccache {
+    krb5_magic magic;
+    const struct _krb5_cc_ops *ops;
+    krb5_pointer data;
+};
+
+/*
+ * Per-type ccache cursor.
+ */
+struct krb5_cc_ptcursor {
+    const struct _krb5_cc_ops *ops;
+    krb5_pointer data;
+};
+typedef struct krb5_cc_ptcursor *krb5_cc_ptcursor;
+
+struct _krb5_cc_ops {
+    krb5_magic magic;
+    char *prefix;
+    const char * (KRB5_CALLCONV *get_name) (krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV *resolve) (krb5_context, krb5_ccache *,
+					    const char *);
+    krb5_error_code (KRB5_CALLCONV *gen_new) (krb5_context, krb5_ccache *);
+    krb5_error_code (KRB5_CALLCONV *init) (krb5_context, krb5_ccache,
+					    krb5_principal);
+    krb5_error_code (KRB5_CALLCONV *destroy) (krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV *close) (krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV *store) (krb5_context, krb5_ccache,
+					    krb5_creds *);
+    krb5_error_code (KRB5_CALLCONV *retrieve) (krb5_context, krb5_ccache,
+					    krb5_flags, krb5_creds *,
+					    krb5_creds *);
+    krb5_error_code (KRB5_CALLCONV *get_princ) (krb5_context, krb5_ccache,
+					    krb5_principal *);
+    krb5_error_code (KRB5_CALLCONV *get_first) (krb5_context, krb5_ccache,
+					    krb5_cc_cursor *);
+    krb5_error_code (KRB5_CALLCONV *get_next) (krb5_context, krb5_ccache,
+					    krb5_cc_cursor *, krb5_creds *);
+    krb5_error_code (KRB5_CALLCONV *end_get) (krb5_context, krb5_ccache,
+					    krb5_cc_cursor *);
+    krb5_error_code (KRB5_CALLCONV *remove_cred) (krb5_context, krb5_ccache,
+					    krb5_flags, krb5_creds *);
+    krb5_error_code (KRB5_CALLCONV *set_flags) (krb5_context, krb5_ccache,
+					    krb5_flags);
+    krb5_error_code (KRB5_CALLCONV *get_flags) (krb5_context, krb5_ccache,
+						krb5_flags *);
+    krb5_error_code (KRB5_CALLCONV *ptcursor_new)(krb5_context,
+						  krb5_cc_ptcursor *);
+    krb5_error_code (KRB5_CALLCONV *ptcursor_next)(krb5_context,
+						   krb5_cc_ptcursor,
+						   krb5_ccache *);
+    krb5_error_code (KRB5_CALLCONV *ptcursor_free)(krb5_context,
+						   krb5_cc_ptcursor *);
+    krb5_error_code (KRB5_CALLCONV *move)(krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV *lastchange)(krb5_context,
+						krb5_ccache, krb5_timestamp *);
+    krb5_error_code (KRB5_CALLCONV *wasdefault)(krb5_context, krb5_ccache,
+						krb5_timestamp *);
+};
+
+extern const krb5_cc_ops *krb5_cc_dfl_ops;
+
+krb5_error_code
+krb5int_cc_os_default_name(krb5_context context, char **name);
+
+/*
+ * Cursor for iterating over ccache types
+ */
+struct krb5_cc_typecursor;
+typedef struct krb5_cc_typecursor *krb5_cc_typecursor;
+
+krb5_error_code
+krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *cursor);
+
+krb5_error_code
+krb5int_cc_typecursor_next(
+    krb5_context context,
+    krb5_cc_typecursor cursor,
+    const struct _krb5_cc_ops **ops);
+
+krb5_error_code
+krb5int_cc_typecursor_free(
+    krb5_context context,
+    krb5_cc_typecursor *cursor);
+
+typedef struct _krb5_donot_replay {
+    krb5_magic magic;
+    krb5_ui_4 hash;
+    char *server;			/* null-terminated */
+    char *client;			/* null-terminated */
+    krb5_int32 cusec;
+    krb5_timestamp ctime;
+} krb5_donot_replay;
+
+krb5_error_code krb5_rc_default 
+	(krb5_context,
+		krb5_rcache *);
+krb5_error_code krb5_rc_resolve_type 
+	(krb5_context,
+		krb5_rcache *,char *);
+krb5_error_code krb5_rc_resolve_full 
+	(krb5_context,
+		krb5_rcache *,char *);
+char * krb5_rc_get_type 
+	(krb5_context,
+		krb5_rcache);
+char * krb5_rc_default_type 
+	(krb5_context);
+char * krb5_rc_default_name 
+	(krb5_context);
+krb5_error_code krb5_auth_to_rep 
+	(krb5_context,
+		krb5_tkt_authent *,
+		krb5_donot_replay *);
+
+
+krb5_error_code KRB5_CALLCONV krb5_rc_initialize
+	(krb5_context, krb5_rcache,krb5_deltat);
+krb5_error_code KRB5_CALLCONV krb5_rc_recover_or_initialize
+	(krb5_context, krb5_rcache,krb5_deltat);
+krb5_error_code KRB5_CALLCONV krb5_rc_recover
+	(krb5_context, krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_destroy
+	(krb5_context, krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_close
+	(krb5_context, krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_store
+	(krb5_context, krb5_rcache,krb5_donot_replay *);
+krb5_error_code KRB5_CALLCONV krb5_rc_expunge
+	(krb5_context, krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_get_lifespan
+	(krb5_context, krb5_rcache,krb5_deltat *);
+char *KRB5_CALLCONV krb5_rc_get_name
+	(krb5_context, krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_resolve
+	(krb5_context, krb5_rcache, char *);
+
+typedef struct _krb5_kt_ops {
+    krb5_magic magic;
+    char *prefix;
+    /* routines always present */
+    krb5_error_code (KRB5_CALLCONV *resolve) 
+	(krb5_context,
+		 const char *,
+		 krb5_keytab *);
+    krb5_error_code (KRB5_CALLCONV *get_name) 
+	(krb5_context,
+		 krb5_keytab,
+		 char *,
+		 unsigned int);
+    krb5_error_code (KRB5_CALLCONV *close) 
+	(krb5_context,
+		 krb5_keytab);
+    krb5_error_code (KRB5_CALLCONV *get) 
+	(krb5_context,
+		 krb5_keytab,
+		 krb5_const_principal,
+		 krb5_kvno,
+		 krb5_enctype,
+		 krb5_keytab_entry *);
+    krb5_error_code (KRB5_CALLCONV *start_seq_get) 
+	(krb5_context,
+		 krb5_keytab,
+		 krb5_kt_cursor *);	
+    krb5_error_code (KRB5_CALLCONV *get_next) 
+	(krb5_context,
+		 krb5_keytab,
+		 krb5_keytab_entry *,
+		 krb5_kt_cursor *);
+    krb5_error_code (KRB5_CALLCONV *end_get) 
+	(krb5_context,
+		 krb5_keytab,
+		 krb5_kt_cursor *);
+    /* routines to be included on extended version (write routines) */
+    krb5_error_code (KRB5_CALLCONV *add) 
+	(krb5_context,
+		 krb5_keytab,
+		 krb5_keytab_entry *);
+    krb5_error_code (KRB5_CALLCONV *remove) 
+	(krb5_context,
+		 krb5_keytab,
+		  krb5_keytab_entry *);
+
+    /* Handle for serializer */
+    const krb5_ser_entry *serializer;
+} krb5_kt_ops;
+
+extern const krb5_kt_ops krb5_kt_dfl_ops;
+
+extern krb5_error_code krb5int_translate_gai_error (int);
+
+/* Not sure it's ready for exposure just yet.  */
+extern krb5_error_code
+krb5int_c_mandatory_cksumtype (krb5_context, krb5_enctype, krb5_cksumtype *);
+
+extern int krb5int_crypto_init (void);
+extern int krb5int_prng_init(void);
+
+#define krb5_copy_error_state(CTX, OCTX) \
+	krb5int_set_error(&(CTX)->errinfo, (OCTX)->errinfo.code, "%s", (OCTX)->errinfo.msg)
+
+/*
+ * Referral definitions, debugging hooks, and subfunctions.
+ */
+#define        KRB5_REFERRAL_MAXHOPS	5
+/* #define DEBUG_REFERRALS */
+
+#ifdef DEBUG_REFERRALS
+void krb5int_dbgref_dump_principal(char *, krb5_principal);
+#endif
+
+/* Common hostname-parsing code. */
+krb5_error_code KRB5_CALLCONV krb5int_clean_hostname
+	(krb5_context,
+		const char *,
+		char *,
+		size_t);
+
+#endif /* _KRB5_INT_H */
diff --git a/krb5-1-6/src/include/k5-platform.h b/krb5-1-6/src/include/k5-platform.h
new file mode 100644
index 000000000..876335f94
--- /dev/null
+++ b/krb5-1-6/src/include/k5-platform.h
@@ -0,0 +1,715 @@
+/*
+ * k5-platform.h
+ *
+ * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.	Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Some platform-dependent definitions to sync up the C support level.
+ * Some to a C99-ish level, some related utility code.
+ *
+ * Currently:
+ * + make "static inline" work
+ * + 64-bit types and load/store code
+ * + SIZE_MAX
+ * + shared library init/fini hooks
+ * + consistent getpwnam/getpwuid interfaces
+ */
+
+#ifndef K5_PLATFORM_H
+#define K5_PLATFORM_H
+
+#include "autoconf.h"
+
+/* Initialization and finalization function support for libraries.
+
+   At top level, before the functions are defined or even declared:
+   MAKE_INIT_FUNCTION(init_fn);
+   MAKE_FINI_FUNCTION(fini_fn);
+   Then:
+   int init_fn(void) { ... }
+   void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... }
+   In code, in the same file:
+   err = CALL_INIT_FUNCTION(init_fn);
+
+   To trigger or verify the initializer invocation from another file,
+   a helper function must be created.
+
+   This model handles both the load-time execution (Windows) and
+   delayed execution (pthread_once) approaches, and should be able to
+   guarantee in both cases that the init function is run once, in one
+   thread, before other stuff in the library is done; furthermore, the
+   finalization code should only run if the initialization code did.
+   (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via
+   another function hidden in macros, but this is hairy enough
+   already.)
+
+   The init_fn and fini_fn names should be chosen such that any
+   exported names staring with those names, and optionally followed by
+   additional characters, fits in with any namespace constraints on
+   the library in question.
+
+
+   There's also PROGRAM_EXITING() currently always defined as zero.
+   If there's some trivial way to find out if the fini function is
+   being called because the program that the library is linked into is
+   exiting, we can just skip all the work because the resources are
+   about to be freed up anyways.  Generally this is likely to be the
+   same as distinguishing whether the library was loaded dynamically
+   while the program was running, or loaded as part of program
+   startup.  On most platforms, I don't think we can distinguish these
+   cases easily, and it's probably not worth expending any significant
+   effort.  (Note in particular that atexit() won't do, because if the
+   library is explicitly loaded and unloaded, it would have to be able
+   to deregister the atexit callback function.  Also, the system limit
+   on atexit callbacks may be small.)
+
+
+   Implementation outline:
+
+   Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that
+   is sought at library build time, and code is added to invoke the
+   function when the library is unloaded.  MAKE_INIT_FUNCTION does
+   likewise, but the function is invoked when the library is loaded,
+   and an extra variable is declared to hold an error code and a "yes
+   the initializer ran" flag.  CALL_INIT_FUNCTION blows up if the flag
+   isn't set, otherwise returns the error code.
+
+   UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a
+   name derived from the function name, containing a k5_once_t
+   (pthread_once_t or int), an error code, and a pointer to the
+   function.  The function itself is declared static, but the
+   associated variable has external linkage.  CALL_INIT_FUNCTION
+   ensures thath the function is called exactly once (pthread_once or
+   just check the flag) and returns the stored error code (or the
+   pthread_once error).
+
+   (That's the basic idea.  With some debugging assert() calls and
+   such, it's a bit more complicated.  And we also need to handle
+   doing the pthread test at run time on systems where that works, so
+   we use the k5_once_t stuff instead.)
+
+   UNIX, with compiler support: MAKE_FINI_FUNCTION declares the
+   function as a destructor, and the run time linker support or
+   whatever will cause it to be invoked when the library is unloaded,
+   the program ends, etc.
+
+   UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with
+   a magic name that is sought at library build time, and linker
+   options are used to mark it as a finalization function for the
+   library.  The symbol must be exported.
+
+   UNIX, no library finalization support: The finalization function
+   never runs, and we leak memory.  Tough.
+
+   DELAY_INITIALIZER will be defined by the configure script if we
+   want to use k5_once instead of load-time initialization.  That'll
+   be the preferred method on most systems except Windows, where we
+   have to initialize some mutexes.
+
+
+
+
+   For maximum flexibility in defining the macros, the function name
+   parameter should be a simple name, not even a macro defined as
+   another name.  The function should have a unique name, and should
+   conform to whatever namespace is used by the library in question.
+   (We do have export lists, but (1) they're not used for all
+   platforms, and (2) they're not used for static libraries.)
+
+   If the macro expansion needs the function to have been declared, it
+   must include a declaration.  If it is not necessary for the symbol
+   name to be exported from the object file, the macro should declare
+   it as "static".  Hence the signature must exactly match "void
+   foo(void)".  (ANSI C allows a static declaration followed by a
+   non-static one; the result is internal linkage.)  The macro
+   expansion has to come before the function, because gcc apparently
+   won't act on "__attribute__((constructor))" if it comes after the
+   function definition.
+
+   This is going to be compiler- and environment-specific, and may
+   require some support at library build time, and/or "asm"
+   statements.  But through macro expansion and auxiliary functions,
+   we should be able to handle most things except #pragma.
+
+   It's okay for this code to require that the library be built
+   with the same compiler and compiler options throughout, but
+   we shouldn't require that the library and application use the
+   same compiler.
+
+   For static libraries, we don't really care about cleanup too much,
+   since it's all memory handling and mutex allocation which will all
+   be cleaned up when the program exits.  Thus, it's okay if gcc-built
+   static libraries don't play nicely with cc-built executables when
+   it comes to static constructors, just as long as it doesn't cause
+   linking to fail.
+
+   For dynamic libraries on UNIX, we'll use pthread_once-type support
+   to do delayed initialization, so if finalization can't be made to
+   work, we'll only have memory leaks in a load/use/unload cycle.  If
+   anyone (like, say, the OS vendor) complains about this, they can
+   tell us how to get a shared library finalization function invoked
+   automatically.
+
+   Currently there's --disable-delayed-initialization for preventing
+   the initialization from being delayed on UNIX, but that's mainly
+   just for testing the linker options for initialization, and will
+   probably be removed at some point.  */
+
+/* Helper macros.  */
+
+# define JOIN__2_2(A,B) A ## _ ## _ ## B
+# define JOIN__2(A,B) JOIN__2_2(A,B)
+
+/* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set,
+   always provide a function by the expected name, even if we're
+   delaying initialization.  */
+
+#if defined(DELAY_INITIALIZER)
+
+/* Run the initialization code during program execution, at the latest
+   possible moment.  This means multiple threads may be active.  */
+# include "k5-thread.h"
+typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t;
+# ifdef USE_LINKER_INIT_OPTION
+#  define MAYBE_DUMMY_INIT(NAME)		\
+	void JOIN__2(NAME, auxinit) () { }
+# else
+#  define MAYBE_DUMMY_INIT(NAME)
+# endif
+# ifdef __GNUC__
+/* Do it in macro form so we get the file/line of the invocation if
+   the assertion fails.  */
+#  define k5_call_init_function(I)					\
+	(__extension__ ({						\
+		k5_init_t *k5int_i = (I);				\
+		int k5int_err = k5_once(&k5int_i->once, k5int_i->fn);	\
+		(k5int_err						\
+		 ? k5int_err						\
+		 : (assert(k5int_i->did_run != 0), k5int_i->error));	\
+	    }))
+#  define MAYBE_DEFINE_CALLINIT_FUNCTION
+# else
+#  define MAYBE_DEFINE_CALLINIT_FUNCTION			\
+	static inline int k5_call_init_function(k5_init_t *i)	\
+	{							\
+	    int err;						\
+	    err = k5_once(&i->once, i->fn);			\
+	    if (err)						\
+		return err;					\
+	    assert (i->did_run != 0);				\
+	    return i->error;					\
+	}
+# endif
+# define MAKE_INIT_FUNCTION(NAME)				\
+	static int NAME(void);					\
+	MAYBE_DUMMY_INIT(NAME)					\
+	/* forward declaration for use in initializer */	\
+	static void JOIN__2(NAME, aux) (void);			\
+	static k5_init_t JOIN__2(NAME, once) =			\
+		{ K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) };	\
+	MAYBE_DEFINE_CALLINIT_FUNCTION				\
+	static void JOIN__2(NAME, aux) (void)			\
+	{							\
+	    JOIN__2(NAME, once).did_run = 1;			\
+	    JOIN__2(NAME, once).error = NAME();			\
+	}							\
+	/* so ';' following macro use won't get error */	\
+	static int NAME(void)
+# define CALL_INIT_FUNCTION(NAME)	\
+	k5_call_init_function(& JOIN__2(NAME, once))
+/* This should be called in finalization only, so we shouldn't have
+   multiple active threads mucking around in our library at this
+   point.  So ignore the once_t object and just look at the flag.
+
+   XXX Could we have problems with memory coherence between processors
+   if we don't invoke mutex/once routines?  Probably not, the
+   application code should already be coordinating things such that
+   the library code is not in use by this point, and memory
+   synchronization will be needed there.  */
+# define INITIALIZER_RAN(NAME)	\
+	(JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0)
+
+# define PROGRAM_EXITING()		(0)
+
+#elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS)
+
+/* Run initializer at load time, via GCC/C++ hook magic.  */
+
+# ifdef USE_LINKER_INIT_OPTION
+     /* Both gcc and linker option??  Favor gcc.  */
+#  define MAYBE_DUMMY_INIT(NAME)		\
+	void JOIN__2(NAME, auxinit) () { }
+# else
+#  define MAYBE_DUMMY_INIT(NAME)
+# endif
+
+typedef struct { int error; unsigned char did_run; } k5_init_t;
+# define MAKE_INIT_FUNCTION(NAME)		\
+	MAYBE_DUMMY_INIT(NAME)			\
+	static k5_init_t JOIN__2(NAME, ran)	\
+		= { 0, 2 };			\
+	static void JOIN__2(NAME, aux)(void)	\
+	    __attribute__((constructor));	\
+	static int NAME(void);			\
+	static void JOIN__2(NAME, aux)(void)	\
+	{					\
+	    JOIN__2(NAME, ran).error = NAME();	\
+	    JOIN__2(NAME, ran).did_run = 3;	\
+	}					\
+	static int NAME(void)
+# define CALL_INIT_FUNCTION(NAME)		\
+	(JOIN__2(NAME, ran).did_run == 3	\
+	 ? JOIN__2(NAME, ran).error		\
+	 : (abort(),0))
+# define INITIALIZER_RAN(NAME)	(JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0)
+
+# define PROGRAM_EXITING()		(0)
+
+#elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32)
+
+/* Run initializer at load time, via linker magic, or in the
+   case of WIN32, win_glue.c hard-coded knowledge.  */
+typedef struct { int error; unsigned char did_run; } k5_init_t;
+# define MAKE_INIT_FUNCTION(NAME)		\
+	static k5_init_t JOIN__2(NAME, ran)	\
+		= { 0, 2 };			\
+	static int NAME(void);			\
+	void JOIN__2(NAME, auxinit)()		\
+	{					\
+	    JOIN__2(NAME, ran).error = NAME();	\
+	    JOIN__2(NAME, ran).did_run = 3;	\
+	}					\
+	static int NAME(void)
+# define CALL_INIT_FUNCTION(NAME)		\
+	(JOIN__2(NAME, ran).did_run == 3	\
+	 ? JOIN__2(NAME, ran).error		\
+	 : (abort(),0))
+# define INITIALIZER_RAN(NAME)	\
+	(JOIN__2(NAME, ran).error == 0)
+
+# define PROGRAM_EXITING()		(0)
+
+#else
+
+# error "Don't know how to do load-time initializers for this configuration."
+
+# define PROGRAM_EXITING()		(0)
+
+#endif
+
+
+
+#if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32)
+/* If we're told the linker option will be used, it doesn't really
+   matter what compiler we're using.  Do it the same way
+   regardless.  */
+
+# ifdef __hpux
+
+     /* On HP-UX, we need this auxiliary function.  At dynamic load or
+	unload time (but *not* program startup and termination for
+	link-time specified libraries), the linker-indicated function
+	is called with a handle on the library and a flag indicating
+	whether it's being loaded or unloaded.
+
+	The "real" fini function doesn't need to be exported, so
+	declare it static.
+
+	As usual, the final declaration is just for syntactic
+	convenience, so the top-level invocation of this macro can be
+	followed by a semicolon.  */
+
+#  include <dl.h>
+#  define MAKE_FINI_FUNCTION(NAME)					    \
+	static void NAME(void);						    \
+	void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \
+	void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); }	    \
+	static void NAME(void)
+
+# else /* not hpux */
+
+#  define MAKE_FINI_FUNCTION(NAME)	\
+	void NAME(void)
+
+# endif
+
+#elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS)
+/* If we're using gcc, if the C++ support works, the compiler should
+   build executables and shared libraries that support the use of
+   static constructors and destructors.  The C compiler supports a
+   function attribute that makes use of the same facility as C++.
+
+   XXX How do we know if the C++ support actually works?  */
+# define MAKE_FINI_FUNCTION(NAME)	\
+	static void NAME(void) __attribute__((destructor))
+
+#elif !defined(SHARED)
+
+/* In this case, we just don't care about finalization.
+
+   The code will still define the function, but we won't do anything
+   with it.  Annoying: This may generate unused-function warnings.  */
+
+# define MAKE_FINI_FUNCTION(NAME)	\
+	static void NAME(void)
+
+#else
+
+# error "Don't know how to do unload-time finalization for this configuration."
+
+#endif
+
+
+/* 64-bit support: krb5_ui_8 and krb5_int64.
+
+   This should move to krb5.h eventually, but without the namespace
+   pollution from the autoconf macros.  */
+#if defined(HAVE_STDINT_H) || defined(HAVE_INTTYPES_H)
+# ifdef HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+# ifdef HAVE_INTTYPES_H
+#  include <inttypes.h>
+# endif
+# define INT64_TYPE int64_t
+# define UINT64_TYPE uint64_t
+#elif defined(_WIN32)
+# define INT64_TYPE signed __int64
+# define UINT64_TYPE unsigned __int64
+#else /* not Windows, and neither stdint.h nor inttypes.h */
+# define INT64_TYPE signed long long
+# define UINT64_TYPE unsigned long long
+#endif
+
+#include <limits.h>
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t)((size_t)0 - 1))
+#endif
+
+/* Read and write integer values as (unaligned) octet strings in
+   specific byte orders.  Add per-platform optimizations as
+   needed.  */
+
+#if HAVE_ENDIAN_H
+# include <endian.h>
+#elif HAVE_MACHINE_ENDIAN_H
+# include <machine/endian.h>
+#endif
+/* Check for BIG/LITTLE_ENDIAN macros.  If exactly one is defined, use
+   it.  If both are defined, then BYTE_ORDER should be defined and
+   match one of them.  Try those symbols, then try again with an
+   underscore prefix.  */
+#if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
+# if BYTE_ORDER == BIG_ENDIAN
+#  define K5_BE
+# endif
+# if BYTE_ORDER == LITTLE_ENDIAN
+#  define K5_LE
+# endif
+#elif defined(BIG_ENDIAN)
+# define K5_BE
+#elif defined(LITTLE_ENDIAN)
+# define K5_LE
+#elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
+# if _BYTE_ORDER == _BIG_ENDIAN
+#  define K5_BE
+# endif
+# if _BYTE_ORDER == _LITTLE_ENDIAN
+#  define K5_LE
+# endif
+#elif defined(_BIG_ENDIAN)
+# define K5_BE
+#elif defined(_LITTLE_ENDIAN)
+# define K5_LE
+#endif
+#if !defined(K5_BE) && !defined(K5_LE)
+/* Look for some architectures we know about.
+
+   MIPS can use either byte order, but the preprocessor tells us which
+   mode we're compiling for.  The GCC config files indicate that
+   variants of Alpha and IA64 might be out there with both byte
+   orders, but until we encounter the "wrong" ones in the real world,
+   just go with the default (unless there are cpp predefines to help
+   us there too).
+
+   As far as I know, only PDP11 and ARM (which we don't handle here)
+   have strange byte orders where an 8-byte value isn't laid out as
+   either 12345678 or 87654321.  */
+# if defined(__i386__) || defined(_MIPSEL) || defined(__alpha__) || defined(__ia64__)
+#  define K5_LE
+# endif
+# if defined(__hppa__) || defined(__rs6000__) || defined(__sparc__) || defined(_MIPSEB) || defined(__m68k__) || defined(__sparc64__) || defined(__ppc__) || defined(__ppc64__)
+#  define K5_BE
+# endif
+#endif
+#if defined(K5_BE) && defined(K5_LE)
+# error "oops, check the byte order macros"
+#endif
+
+/* Optimize for GCC on platforms with known byte orders.
+
+   GCC's packed structures can be written to with any alignment; the
+   compiler will use byte operations, unaligned-word operations, or
+   normal memory ops as appropriate for the architecture.
+
+   This assumes the availability of uint##_t types, which should work
+   on most of our platforms except Windows, where we're not using
+   GCC.  */
+#ifdef __GNUC__
+# define PUT(SIZE,PTR,VAL)	(((struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i = (VAL))
+# define GET(SIZE,PTR)		(((const struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i)
+# define PUTSWAPPED(SIZE,PTR,VAL)	PUT(SIZE,PTR,SWAP##SIZE(VAL))
+# define GETSWAPPED(SIZE,PTR)		SWAP##SIZE(GET(SIZE,PTR))
+#endif
+/* To do: Define SWAP16, SWAP32, SWAP64 macros to byte-swap values
+   with the indicated numbers of bits.
+
+   Linux: byteswap.h, bswap_16 etc.
+   Solaris 10: none
+   Mac OS X: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong}
+   NetBSD: sys/bswap.h, bswap16 etc.  */
+
+#if defined(HAVE_BYTESWAP_H) && defined(HAVE_BSWAP_16)
+# include <byteswap.h>
+# define SWAP16			bswap_16
+# define SWAP32			bswap_32
+# ifdef HAVE_BSWAP_64
+#  define SWAP64		bswap_64
+# endif
+#endif
+
+static inline void
+store_16_be (unsigned int val, unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_BE)
+    PUT(16,p,val);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16)
+    PUTSWAPPED(16,p,val);
+#else
+    p[0] = (val >>  8) & 0xff;
+    p[1] = (val      ) & 0xff;
+#endif
+}
+static inline void
+store_32_be (unsigned int val, unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_BE)
+    PUT(32,p,val);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32)
+    PUTSWAPPED(32,p,val);
+#else
+    p[0] = (val >> 24) & 0xff;
+    p[1] = (val >> 16) & 0xff;
+    p[2] = (val >>  8) & 0xff;
+    p[3] = (val      ) & 0xff;
+#endif
+}
+static inline void
+store_64_be (UINT64_TYPE val, unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_BE)
+    PUT(64,p,val);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64)
+    PUTSWAPPED(64,p,val);
+#else
+    p[0] = (unsigned char)((val >> 56) & 0xff);
+    p[1] = (unsigned char)((val >> 48) & 0xff);
+    p[2] = (unsigned char)((val >> 40) & 0xff);
+    p[3] = (unsigned char)((val >> 32) & 0xff);
+    p[4] = (unsigned char)((val >> 24) & 0xff);
+    p[5] = (unsigned char)((val >> 16) & 0xff);
+    p[6] = (unsigned char)((val >>  8) & 0xff);
+    p[7] = (unsigned char)((val      ) & 0xff);
+#endif
+}
+static inline unsigned short
+load_16_be (const unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_BE)
+    return GET(16,p);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16)
+    return GETSWAPPED(16,p);
+#else
+    return (p[1] | (p[0] << 8));
+#endif
+}
+static inline unsigned int
+load_32_be (const unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_BE)
+    return GET(32,p);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32)
+    return GETSWAPPED(32,p);
+#else
+    return (p[3] | (p[2] << 8)
+	    | ((uint32_t) p[1] << 16)
+	    | ((uint32_t) p[0] << 24));
+#endif
+}
+static inline UINT64_TYPE
+load_64_be (const unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_BE)
+    return GET(64,p);
+#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64)
+    return GETSWAPPED(64,p);
+#else
+    return ((UINT64_TYPE)load_32_be(p) << 32) | load_32_be(p+4);
+#endif
+}
+static inline void
+store_16_le (unsigned int val, unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_LE)
+    PUT(16,p,val);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16)
+    PUTSWAPPED(16,p,val);
+#else
+    p[1] = (val >>  8) & 0xff;
+    p[0] = (val      ) & 0xff;
+#endif
+}
+static inline void
+store_32_le (unsigned int val, unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_LE)
+    PUT(32,p,val);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32)
+    PUTSWAPPED(32,p,val);
+#else
+    p[3] = (val >> 24) & 0xff;
+    p[2] = (val >> 16) & 0xff;
+    p[1] = (val >>  8) & 0xff;
+    p[0] = (val      ) & 0xff;
+#endif
+}
+static inline void
+store_64_le (UINT64_TYPE val, unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_LE)
+    PUT(64,p,val);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64)
+    PUTSWAPPED(64,p,val);
+#else
+    p[7] = (unsigned char)((val >> 56) & 0xff);
+    p[6] = (unsigned char)((val >> 48) & 0xff);
+    p[5] = (unsigned char)((val >> 40) & 0xff);
+    p[4] = (unsigned char)((val >> 32) & 0xff);
+    p[3] = (unsigned char)((val >> 24) & 0xff);
+    p[2] = (unsigned char)((val >> 16) & 0xff);
+    p[1] = (unsigned char)((val >>  8) & 0xff);
+    p[0] = (unsigned char)((val      ) & 0xff);
+#endif
+}
+static inline unsigned short
+load_16_le (const unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_LE)
+    return GET(16,p);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16)
+    return GETSWAPPED(16,p);
+#else
+    return (p[0] | (p[1] << 8));
+#endif
+}
+static inline unsigned int
+load_32_le (const unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_LE)
+    return GET(32,p);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32)
+    return GETSWAPPED(32,p);
+#else
+    return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
+#endif
+}
+static inline UINT64_TYPE
+load_64_le (const unsigned char *p)
+{
+#if defined(__GNUC__) && defined(K5_LE)
+    return GET(64,p);
+#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64)
+    return GETSWAPPED(64,p);
+#else
+    return ((UINT64_TYPE)load_32_le(p+4) << 32) | load_32_le(p);
+#endif
+}
+
+/* Make the interfaces to getpwnam and getpwuid consistent.
+   Model the wrappers on the POSIX thread-safe versions, but
+   use the unsafe system versions if the safe ones don't exist
+   or we can't figure out their interfaces.  */
+
+/* int k5_getpwnam_r(const char *, blah blah) */
+#ifdef HAVE_GETPWNAM_R
+# ifndef GETPWNAM_R_4_ARGS
+/* POSIX */
+#  define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT)	\
+	(getpwnam_r(NAME,REC,BUF,BUFSIZE,OUT) == 0	\
+	 ? (*(OUT) == NULL ? -1 : 0) : -1)
+# else
+/* POSIX drafts? */
+#  ifdef GETPWNAM_R_RETURNS_INT
+#   define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT)	\
+	(getpwnam_r(NAME,REC,BUF,BUFSIZE) == 0		\
+	 ? (*(OUT) = REC, 0)				\
+	 : (*(OUT) = NULL, -1))
+#  else
+#   define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT)  \
+	(*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
+#  endif
+# endif
+#else /* no getpwnam_r, or can't figure out #args or return type */
+/* Will get warnings about unused variables.  */
+# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \
+	(*(OUT) = getpwnam(NAME), *(OUT) == NULL ? -1 : 0)
+#endif
+
+/* int k5_getpwuid_r(uid_t, blah blah) */
+#ifdef HAVE_GETPWUID_R
+# ifndef GETPWUID_R_4_ARGS
+/* POSIX */
+#  define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT)	\
+	(getpwuid_r(UID,REC,BUF,BUFSIZE,OUT) == 0	\
+	 ? (*(OUT) == NULL ? -1 : 0) : -1)
+# else
+/* POSIX drafts?  Yes, I mean to test GETPWNAM... here.  Less junk to
+   do at configure time.  */
+#  ifdef GETPWNAM_R_RETURNS_INT
+#   define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT)	\
+	(getpwuid_r(UID,REC,BUF,BUFSIZE) == 0		\
+	 ? (*(OUT) = REC, 0)				\
+	 : (*(OUT) = NULL, -1))
+#  else
+#   define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT)  \
+	(*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0)
+#  endif
+# endif
+#else /* no getpwuid_r, or can't figure out #args or return type */
+/* Will get warnings about unused variables.  */
+# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \
+	(*(OUT) = getpwuid(UID), *(OUT) == NULL ? -1 : 0)
+#endif
+
+
+#endif /* K5_PLATFORM_H */
diff --git a/krb5-1-6/src/include/k5-plugin.h b/krb5-1-6/src/include/k5-plugin.h
new file mode 100644
index 000000000..5bb9be7a0
--- /dev/null
+++ b/krb5-1-6/src/include/k5-plugin.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+/* Just those definitions which are needed by util/support/plugins.c,
+   which gets compiled before util/et is built, which happens before
+   we can construct krb5.h, which is included by k5-int.h.
+
+   So, no krb5 types.  */
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include "win-mac.h"
+#endif
+#include "autoconf.h"
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include "k5-err.h"
+
+struct plugin_file_handle;	/* opaque */
+
+struct plugin_dir_handle {
+    /* This points to a NULL-terminated list of pointers to plugin_file_handle structs */
+    struct plugin_file_handle **files;
+};
+#define PLUGIN_DIR_INIT(P) ((P)->files = NULL)
+#define PLUGIN_DIR_OPEN(P) ((P)->files != NULL)
+
+long KRB5_CALLCONV
+krb5int_open_plugin (const char *, struct plugin_file_handle **, struct errinfo *);
+void KRB5_CALLCONV
+krb5int_close_plugin (struct plugin_file_handle *);
+
+long KRB5_CALLCONV
+krb5int_get_plugin_data (struct plugin_file_handle *, const char *, void **,
+			 struct errinfo *);
+
+long KRB5_CALLCONV
+krb5int_get_plugin_func (struct plugin_file_handle *, const char *,
+			 void (**)(), struct errinfo *);
+
+
+long KRB5_CALLCONV
+krb5int_open_plugin_dirs (const char * const *, const char * const *,
+			  struct plugin_dir_handle *, struct errinfo *);
+void KRB5_CALLCONV 
+krb5int_close_plugin_dirs (struct plugin_dir_handle *);
+
+long KRB5_CALLCONV 
+krb5int_get_plugin_dir_data (struct plugin_dir_handle *, const char *, 
+			     void ***, struct errinfo *);
+void KRB5_CALLCONV 
+krb5int_free_plugin_dir_data (void **);
+
+long KRB5_CALLCONV 
+krb5int_get_plugin_dir_func (struct plugin_dir_handle *, const char *, 
+			     void (***)(void), struct errinfo *);
+void KRB5_CALLCONV 
+krb5int_free_plugin_dir_func (void (**)(void));
diff --git a/krb5-1-6/src/include/k5-thread.h b/krb5-1-6/src/include/k5-thread.h
new file mode 100644
index 000000000..13c2391fb
--- /dev/null
+++ b/krb5-1-6/src/include/k5-thread.h
@@ -0,0 +1,797 @@
+/*
+ * include/k5-thread.h
+ *
+ * Copyright 2004,2005,2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Preliminary thread support.
+ */
+
+#ifndef K5_THREAD_H
+#define K5_THREAD_H
+
+#include "autoconf.h"
+#ifndef KRB5_CALLCONV
+# define KRB5_CALLCONV
+#endif
+#ifndef KRB5_CALLCONV_C
+# define KRB5_CALLCONV_C
+#endif
+
+/* Interface (tentative):
+
+   Mutex support:
+
+   // Between these two, we should be able to do pure compile-time
+   // and pure run-time initialization.
+   //   POSIX:   partial initializer is PTHREAD_MUTEX_INITIALIZER,
+   //            finish does nothing
+   //   Windows: partial initializer is an invalid handle,
+   //            finish does the real initialization work
+   //   debug:   partial initializer sets one magic value,
+   //            finish verifies and sets a new magic value for
+   //              lock/unlock to check
+   k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+   int k5_mutex_finish_init(k5_mutex_t *);
+   // for dynamic allocation
+   int k5_mutex_init(k5_mutex_t *);
+   // Must work for both kinds of alloc, even if it means adding flags.
+   int k5_mutex_destroy(k5_mutex_t *);
+
+   // As before.
+   int k5_mutex_lock(k5_mutex_t *);
+   int k5_mutex_unlock(k5_mutex_t *);
+
+   In each library, one new function to finish the static mutex init,
+   and any other library-wide initialization that might be desired.
+   On POSIX, this function would be called via the second support
+   function (see below).  On Windows, it would be called at library
+   load time.  These functions, or functions they calls, should be the
+   only places that k5_mutex_finish_init gets called.
+
+   A second function or macro called at various possible "first" entry
+   points which either calls pthread_once on the first function
+   (POSIX), or checks some flag set by the first function (Windows,
+   debug support), and possibly returns an error.  (In the
+   non-threaded case, a simple flag can be used to avoid multiple
+   invocations, and the mutexes don't need run-time initialization
+   anyways.)
+
+   A third function for library termination calls mutex_destroy on
+   each mutex for the library.  This function would be called
+   automatically at library unload time.  If it turns out to be needed
+   at exit time for libraries that don't get unloaded, perhaps we
+   should also use atexit().  Any static mutexes should be cleaned up
+   with k5_mutex_destroy here.
+
+   How does that second support function invoke the first support
+   function only once?  Through something modelled on pthread_once
+   that I haven't written up yet.  Probably:
+
+   k5_once_t foo_once = K5_ONCE_INIT;
+   k5_once(k5_once_t *, void (*)(void));
+
+   For POSIX: Map onto pthread_once facility.
+   For non-threaded case: A simple flag.
+   For Windows: Not needed; library init code takes care of it.
+
+   XXX: A general k5_once mechanism isn't possible for Windows,
+   without faking it through named mutexes or mutexes initialized at
+   startup.  I was only using it in one place outside these headers,
+   so I'm dropping the general scheme.  Eventually the existing uses
+   in k5-thread.h and k5-platform.h will be converted to pthread_once
+   or static variables.
+
+
+   Thread-specific data:
+
+   // TSD keys are limited in number in gssapi/krb5/com_err; enumerate
+   // them all.  This allows support code init to allocate the
+   // necessary storage for pointers all at once, and avoids any
+   // possible error in key creation.
+   enum { ... } k5_key_t;
+   // Register destructor function.  Called in library init code.
+   int k5_key_register(k5_key_t, void (*destructor)(void *));
+   // Returns NULL or data.
+   void *k5_getspecific(k5_key_t);
+   // Returns error if key out of bounds, or the pointer table can't
+   // be allocated.  A call to k5_key_register must have happened first.
+   // This may trigger the calling of pthread_setspecific on POSIX.
+   int k5_setspecific(k5_key_t, void *);
+   // Called in library termination code.
+   // Trashes data in all threads, calling the registered destructor
+   // (but calling it from the current thread).
+   int k5_key_delete(k5_key_t);
+
+   For the non-threaded version, the support code will have a static
+   array indexed by k5_key_t values, and get/setspecific simply access
+   the array elements.
+
+   The TSD destructor table is global state, protected by a mutex if
+   threads are enabled.
+
+   Debug support: Not much.  Might check if k5_key_register has been
+   called and abort if not.
+
+
+   Any actual external symbols will use the krb5int_ prefix.  The k5_
+   names will be simple macros or inline functions to rename the
+   external symbols, or slightly more complex ones to expand the
+   implementation inline (e.g., map to POSIX versions and/or debug
+   code using __FILE__ and the like).
+
+
+   More to be added, perhaps.  */
+
+#define DEBUG_THREADS
+#define DEBUG_THREADS_LOC
+#undef DEBUG_THREADS_SLOW /* debugging stuff that'll slow things down? */
+#undef DEBUG_THREADS_STATS
+
+#include <assert.h>
+
+/* For tracking locations, of (e.g.) last lock or unlock of mutex.  */
+#ifdef DEBUG_THREADS_LOC
+typedef struct {
+    const char *filename;
+    int lineno;
+} k5_debug_loc;
+#define K5_DEBUG_LOC_INIT	{ __FILE__, __LINE__ }
+#if __GNUC__ >= 2
+#define K5_DEBUG_LOC		(__extension__ (k5_debug_loc)K5_DEBUG_LOC_INIT)
+#else
+static inline k5_debug_loc k5_debug_make_loc(const char *file, int line)
+{
+    k5_debug_loc l;
+    l.filename = file;
+    l.lineno = line;
+    return l;
+}
+#define K5_DEBUG_LOC		(k5_debug_make_loc(__FILE__,__LINE__))
+#endif
+#else /* ! DEBUG_THREADS_LOC */
+typedef char k5_debug_loc;
+#define K5_DEBUG_LOC_INIT	0
+#define K5_DEBUG_LOC		0
+#endif
+
+#define k5_debug_update_loc(L)	((L) = K5_DEBUG_LOC)
+
+
+
+/* Statistics gathering:
+
+   Currently incomplete, don't try enabling it.
+
+   Eventually: Report number of times locked, total and standard
+   deviation of the time the lock was held, total and std dev time
+   spent waiting for the lock.  "Report" will probably mean "write a
+   line to a file if a magic environment variable is set."  */
+
+#ifdef DEBUG_THREADS_STATS
+
+#if HAVE_TIME_H && (!defined(HAVE_SYS_TIME_H) || defined(TIME_WITH_SYS_TIME))
+# include <time.h>
+#endif
+#if HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+/* for memset */
+#include <string.h>
+/* for uint64_t */
+#include <inttypes.h>
+typedef uint64_t k5_debug_timediff_t; /* or long double */
+typedef struct timeval k5_debug_time_t;
+static inline k5_debug_timediff_t
+timediff(k5_debug_time_t t2, k5_debug_time_t t1)
+{
+    return (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
+}
+static inline k5_debug_time_t get_current_time(void)
+{
+    struct timeval tv;
+    if (gettimeofday(&tv,0) < 0) { tv.tv_sec = tv.tv_usec = 0; }
+    return tv;
+}
+struct k5_timediff_stats {
+    k5_debug_timediff_t valmin, valmax, valsum, valsqsum;
+};
+typedef struct {
+    int count;
+    k5_debug_time_t time_acquired, time_created;
+    struct k5_timediff_stats lockwait, lockheld;
+} k5_debug_mutex_stats;
+#define k5_mutex_init_stats(S)					\
+	(memset((S), 0, sizeof(k5_debug_mutex_stats)),	\
+	 (S)->time_created = get_current_time(),		\
+	 0)
+#define k5_mutex_finish_init_stats(S) 	(0)
+#define K5_MUTEX_STATS_INIT	{ 0, {0}, {0}, {0}, {0} }
+typedef k5_debug_time_t k5_mutex_stats_tmp;
+#define k5_mutex_stats_start()	get_current_time()
+void KRB5_CALLCONV krb5int_mutex_lock_update_stats(k5_debug_mutex_stats *m,
+						   k5_mutex_stats_tmp start);
+void KRB5_CALLCONV krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m);
+#define k5_mutex_lock_update_stats	krb5int_mutex_lock_update_stats
+#define k5_mutex_unlock_update_stats	krb5int_mutex_unlock_update_stats
+void KRB5_CALLCONV krb5int_mutex_report_stats(/* k5_mutex_t *m */);
+
+#else
+
+typedef char k5_debug_mutex_stats;
+#define k5_mutex_init_stats(S)		(*(S) = 's', 0)
+#define k5_mutex_finish_init_stats(S)	(0)
+#define K5_MUTEX_STATS_INIT		's'
+typedef int k5_mutex_stats_tmp;
+#define k5_mutex_stats_start()		(0)
+#ifdef __GNUC__
+static inline void
+k5_mutex_lock_update_stats(k5_debug_mutex_stats *m, k5_mutex_stats_tmp t)
+{
+}
+#else
+# define k5_mutex_lock_update_stats(M,S)	(S)
+#endif
+#define k5_mutex_unlock_update_stats(M)	(*(M) = 's')
+
+/* If statistics tracking isn't enabled, these functions don't actually
+   do anything.  Declare anyways so we can do type checking etc.  */
+void KRB5_CALLCONV krb5int_mutex_lock_update_stats(k5_debug_mutex_stats *m,
+						   k5_mutex_stats_tmp start);
+void KRB5_CALLCONV krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m);
+void KRB5_CALLCONV krb5int_mutex_report_stats(/* k5_mutex_t *m */);
+
+#define krb5int_mutex_report_stats(M)	((M)->stats = 'd')
+
+#endif
+
+
+
+/* Define the OS mutex bit.  */
+
+/* First, if we're not actually doing multiple threads, do we
+   want the debug support or not?  */
+
+#ifdef DEBUG_THREADS
+
+enum k5_mutex_init_states {
+    K5_MUTEX_DEBUG_PARTLY_INITIALIZED = 0x12,
+    K5_MUTEX_DEBUG_INITIALIZED,
+    K5_MUTEX_DEBUG_DESTROYED
+};
+enum k5_mutex_flag_states {
+    K5_MUTEX_DEBUG_UNLOCKED = 0x23,
+    K5_MUTEX_DEBUG_LOCKED
+};
+
+typedef struct {
+    enum k5_mutex_init_states initialized;
+    enum k5_mutex_flag_states locked;
+} k5_os_nothread_mutex;
+
+# define K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER \
+	{ K5_MUTEX_DEBUG_PARTLY_INITIALIZED, K5_MUTEX_DEBUG_UNLOCKED }
+
+# define k5_os_nothread_mutex_finish_init(M)				\
+	(assert((M)->initialized != K5_MUTEX_DEBUG_INITIALIZED),	\
+	 assert((M)->initialized == K5_MUTEX_DEBUG_PARTLY_INITIALIZED),	\
+	 assert((M)->locked == K5_MUTEX_DEBUG_UNLOCKED),		\
+	 (M)->initialized = K5_MUTEX_DEBUG_INITIALIZED, 0)
+# define k5_os_nothread_mutex_init(M)			\
+	((M)->initialized = K5_MUTEX_DEBUG_INITIALIZED,	\
+	 (M)->locked = K5_MUTEX_DEBUG_UNLOCKED, 0)
+# define k5_os_nothread_mutex_destroy(M)				\
+	(assert((M)->initialized == K5_MUTEX_DEBUG_INITIALIZED),	\
+	 (M)->initialized = K5_MUTEX_DEBUG_DESTROYED, 0)
+
+# define k5_os_nothread_mutex_lock(M)			\
+	(k5_os_nothread_mutex_assert_unlocked(M),	\
+	 (M)->locked = K5_MUTEX_DEBUG_LOCKED, 0)
+# define k5_os_nothread_mutex_unlock(M)			\
+	(k5_os_nothread_mutex_assert_locked(M),		\
+	 (M)->locked = K5_MUTEX_DEBUG_UNLOCKED, 0)
+
+# define k5_os_nothread_mutex_assert_locked(M)				\
+	(assert((M)->initialized == K5_MUTEX_DEBUG_INITIALIZED),	\
+	 assert((M)->locked != K5_MUTEX_DEBUG_UNLOCKED),		\
+	 assert((M)->locked == K5_MUTEX_DEBUG_LOCKED))
+# define k5_os_nothread_mutex_assert_unlocked(M)			\
+	(assert((M)->initialized == K5_MUTEX_DEBUG_INITIALIZED),	\
+	 assert((M)->locked != K5_MUTEX_DEBUG_LOCKED),			\
+	 assert((M)->locked == K5_MUTEX_DEBUG_UNLOCKED))
+
+#else /* threads disabled and not debugging */
+
+typedef char k5_os_nothread_mutex;
+# define K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER	0
+/* Empty inline functions avoid the "statement with no effect"
+   warnings, and do better type-checking than functions that don't use
+   their arguments.  */
+static inline int k5_os_nothread_mutex_finish_init(k5_os_nothread_mutex *m) {
+    return 0;
+}
+static inline int k5_os_nothread_mutex_init(k5_os_nothread_mutex *m) {
+    return 0;
+}
+static inline int k5_os_nothread_mutex_destroy(k5_os_nothread_mutex *m) {
+    return 0;
+}
+static inline int k5_os_nothread_mutex_lock(k5_os_nothread_mutex *m) {
+    return 0;
+}
+static inline int k5_os_nothread_mutex_unlock(k5_os_nothread_mutex *m) {
+    return 0;
+}
+# define k5_os_nothread_mutex_assert_locked(M)		((void)0)
+# define k5_os_nothread_mutex_assert_unlocked(M)	((void)0)
+
+#endif
+
+/* Values:
+   2 - function has not been run
+   3 - function has been run
+   4 - function is being run -- deadlock detected */
+typedef unsigned char k5_os_nothread_once_t;
+# define K5_OS_NOTHREAD_ONCE_INIT	2
+# define k5_os_nothread_once(O,F)					\
+	(*(O) == 3 ? 0							\
+	 : *(O) == 2 ? (*(O) = 4, (F)(), *(O) = 3, 0)			\
+	 : (assert(*(O) != 4), assert(*(O) == 2 || *(O) == 3), 0))
+
+
+
+#ifndef ENABLE_THREADS
+
+typedef k5_os_nothread_mutex k5_os_mutex;
+# define K5_OS_MUTEX_PARTIAL_INITIALIZER	\
+		K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER
+# define k5_os_mutex_finish_init	k5_os_nothread_mutex_finish_init
+# define k5_os_mutex_init		k5_os_nothread_mutex_init
+# define k5_os_mutex_destroy		k5_os_nothread_mutex_destroy
+# define k5_os_mutex_lock		k5_os_nothread_mutex_lock
+# define k5_os_mutex_unlock		k5_os_nothread_mutex_unlock
+# define k5_os_mutex_assert_locked	k5_os_nothread_mutex_assert_locked
+# define k5_os_mutex_assert_unlocked	k5_os_nothread_mutex_assert_unlocked
+
+# define k5_once_t			k5_os_nothread_once_t
+# define K5_ONCE_INIT			K5_OS_NOTHREAD_ONCE_INIT
+# define k5_once			k5_os_nothread_once
+
+#elif HAVE_PTHREAD
+
+# include <pthread.h>
+
+/* Weak reference support, etc.
+
+   Linux: Stub mutex routines exist, but pthread_once does not.
+
+   Solaris: In libc there's a pthread_once that doesn't seem to do
+   anything.  Bleah.  But pthread_mutexattr_setrobust_np is defined
+   only in libpthread.  However, some version of GNU libc (Red Hat's
+   Fedora Core 5, reportedly) seems to have that function, but no
+   declaration, so we'd have to declare it in order to test for its
+   address.  We now have tests to see if pthread_once actually works,
+   so stick with that for now.
+
+   IRIX 6.5 stub pthread support in libc is really annoying.  The
+   pthread_mutex_lock function returns ENOSYS for a program not linked
+   against -lpthread.  No link-time failure, no weak symbols, etc.
+   The C library doesn't provide pthread_once; we can use weak
+   reference support for that.
+
+   If weak references are not available, then for now, we assume that
+   the pthread support routines will always be available -- either the
+   real thing, or functional stubs that merely prohibit creating
+   threads.
+
+   If we find a platform with non-functional stubs and no weak
+   references, we may have to resort to some hack like dlsym on the
+   symbol tables of the current process.  */
+#ifdef HAVE_PRAGMA_WEAK_REF
+# pragma weak pthread_once
+# pragma weak pthread_mutex_lock
+# pragma weak pthread_mutex_unlock
+# pragma weak pthread_mutex_destroy
+# pragma weak pthread_mutex_init
+# pragma weak pthread_self
+# pragma weak pthread_equal
+extern int krb5int_pthread_loaded(void);
+# define K5_PTHREADS_LOADED	(krb5int_pthread_loaded())
+#else
+/* no pragma weak support */
+# define K5_PTHREADS_LOADED	(1)
+#endif
+
+#if defined(__mips) && defined(__sgi) && (defined(_SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__))
+/* IRIX 6.5 stub pthread support in libc is really annoying.  The
+   pthread_mutex_lock function returns ENOSYS for a program not linked
+   against -lpthread.  No link-time failure, no weak reference tests,
+   etc.
+
+   The C library doesn't provide pthread_once; we can use weak
+   reference support for that.  */
+# ifndef HAVE_PRAGMA_WEAK_REF
+#  if defined(__GNUC__) && __GNUC__ < 3
+#   error "Please update to a newer gcc with weak symbol support, or switch to native cc, reconfigure and recompile."
+#  else
+#   error "Weak reference support is required"
+#  endif
+# endif
+#endif
+
+#ifdef HAVE_PRAGMA_WEAK_REF
+# define USE_PTHREAD_LOCK_ONLY_IF_LOADED
+#endif
+
+#ifdef HAVE_PRAGMA_WEAK_REF
+/* Can't rely on useful stubs -- see above regarding Solaris.  */
+typedef struct {
+    pthread_once_t o;
+    k5_os_nothread_once_t n;
+} k5_once_t;
+# define K5_ONCE_INIT	{ PTHREAD_ONCE_INIT, K5_OS_NOTHREAD_ONCE_INIT }
+# define k5_once(O,F)	(K5_PTHREADS_LOADED			\
+			 ? pthread_once(&(O)->o,F)		\
+			 : k5_os_nothread_once(&(O)->n,F))
+#else
+typedef pthread_once_t k5_once_t;
+# define K5_ONCE_INIT	PTHREAD_ONCE_INIT
+# define k5_once	pthread_once
+#endif
+
+typedef struct {
+    pthread_mutex_t p;
+#ifdef DEBUG_THREADS
+    pthread_t owner;
+#endif
+#ifdef USE_PTHREAD_LOCK_ONLY_IF_LOADED
+    k5_os_nothread_mutex n;
+#endif
+} k5_os_mutex;
+
+#ifdef DEBUG_THREADS
+# ifdef __GNUC__
+#  define k5_pthread_mutex_lock(M)			\
+	({						\
+	    k5_os_mutex *_m2 = (M);			\
+	    int _r2 = pthread_mutex_lock(&_m2->p);	\
+	    if (_r2 == 0) _m2->owner = pthread_self();	\
+	    _r2;					\
+	})
+# else
+static inline int
+k5_pthread_mutex_lock(k5_os_mutex *m)
+{
+    int r = pthread_mutex_lock(&m->p);
+    if (r)
+	return r;
+    m->owner = pthread_self();
+    return 0;
+}
+# endif
+# define k5_pthread_assert_locked(M)				\
+	(K5_PTHREADS_LOADED					\
+	 ? assert(pthread_equal((M)->owner, pthread_self()))	\
+	 : (void)0)
+# define k5_pthread_mutex_unlock(M)	\
+	(k5_pthread_assert_locked(M),	\
+	 (M)->owner = (pthread_t) 0,	\
+	 pthread_mutex_unlock(&(M)->p))
+#else
+# define k5_pthread_mutex_lock(M) pthread_mutex_lock(&(M)->p)
+static inline void k5_pthread_assert_locked(k5_os_mutex *m) { }
+# define k5_pthread_mutex_unlock(M) pthread_mutex_unlock(&(M)->p)
+#endif
+
+/* Define as functions to:
+   (1) eliminate "statement with no effect" warnings for "0"
+   (2) encourage type-checking in calling code  */
+
+static inline void k5_pthread_assert_unlocked(pthread_mutex_t *m) { }
+
+#if defined(DEBUG_THREADS_SLOW) && HAVE_SCHED_H && (HAVE_SCHED_YIELD || HAVE_PRAGMA_WEAK_REF)
+# include <sched.h>
+# if !HAVE_SCHED_YIELD
+#  pragma weak sched_yield
+#  define MAYBE_SCHED_YIELD()	((void)((&sched_yield != NULL) ? sched_yield() : 0))
+# else
+#  define MAYBE_SCHED_YIELD()	((void)sched_yield())
+# endif
+#else
+# define MAYBE_SCHED_YIELD()	((void)0)
+#endif
+
+/* It may not be obvious why this function is desirable.
+
+   I want to call pthread_mutex_lock, then sched_yield, then look at
+   the return code from pthread_mutex_lock.  That can't be implemented
+   in a macro without a temporary variable, or GNU C extensions.
+
+   There used to be an inline function which did it, with both
+   functions called from the inline function.  But that messes with
+   the debug information on a lot of configurations, and you can't
+   tell where the inline function was called from.  (Typically, gdb
+   gives you the name of the function from which the inline function
+   was called, and a line number within the inline function itself.)
+
+   With this auxiliary function, pthread_mutex_lock can be called at
+   the invoking site via a macro; once it returns, the inline function
+   is called (with messed-up line-number info for gdb hopefully
+   localized to just that call).  */
+#ifdef __GNUC__
+#define return_after_yield(R)			\
+	__extension__ ({			\
+	    int _r = (R);			\
+	    MAYBE_SCHED_YIELD();		\
+	    _r;					\
+	})
+#else
+static inline int return_after_yield(int r)
+{
+    MAYBE_SCHED_YIELD();
+    return r;
+}
+#endif
+
+#ifdef USE_PTHREAD_LOCK_ONLY_IF_LOADED
+
+# if defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) && defined(DEBUG_THREADS)
+#  define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+	{ PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, (pthread_t) 0, \
+	  K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER }
+# elif defined(DEBUG_THREADS)
+#  define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+	{ PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, \
+	  K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER }
+# else
+#  define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+	{ PTHREAD_MUTEX_INITIALIZER, K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER }
+# endif
+
+# define k5_os_mutex_finish_init(M)		\
+	k5_os_nothread_mutex_finish_init(&(M)->n)
+# define k5_os_mutex_init(M)			\
+	(k5_os_nothread_mutex_init(&(M)->n),	\
+	 (K5_PTHREADS_LOADED			\
+	  ? pthread_mutex_init(&(M)->p, 0)	\
+	  : 0))
+# define k5_os_mutex_destroy(M)			\
+	(k5_os_nothread_mutex_destroy(&(M)->n),	\
+	 (K5_PTHREADS_LOADED			\
+	  ? pthread_mutex_destroy(&(M)->p)	\
+	  : 0))
+
+# define k5_os_mutex_lock(M)						\
+	return_after_yield(K5_PTHREADS_LOADED				\
+			   ? k5_pthread_mutex_lock(M)			\
+			   : k5_os_nothread_mutex_lock(&(M)->n))
+# define k5_os_mutex_unlock(M)				\
+	(MAYBE_SCHED_YIELD(),				\
+	 (K5_PTHREADS_LOADED				\
+	  ? k5_pthread_mutex_unlock(M)			\
+	  : k5_os_nothread_mutex_unlock(&(M)->n)))
+
+# define k5_os_mutex_assert_unlocked(M)			\
+	(K5_PTHREADS_LOADED				\
+	 ? k5_pthread_assert_unlocked(&(M)->p)		\
+	 : k5_os_nothread_mutex_assert_unlocked(&(M)->n))
+# define k5_os_mutex_assert_locked(M)			\
+	(K5_PTHREADS_LOADED				\
+	 ? k5_pthread_assert_locked(M)			\
+	 : k5_os_nothread_mutex_assert_locked(&(M)->n))
+
+#else
+
+# ifdef DEBUG_THREADS
+#  ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+#   define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+	{ PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, (pthread_t) 0 }
+#  else
+#   define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+	{ PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0 }
+#  endif
+# else
+#  define K5_OS_MUTEX_PARTIAL_INITIALIZER \
+	{ PTHREAD_MUTEX_INITIALIZER }
+# endif
+
+static inline int k5_os_mutex_finish_init(k5_os_mutex *m) { return 0; }
+# define k5_os_mutex_init(M)		pthread_mutex_init(&(M)->p, 0)
+# define k5_os_mutex_destroy(M)		pthread_mutex_destroy(&(M)->p)
+# define k5_os_mutex_lock(M)	return_after_yield(k5_pthread_mutex_lock(M))
+# define k5_os_mutex_unlock(M)		(MAYBE_SCHED_YIELD(),k5_pthread_mutex_unlock(M))
+
+# define k5_os_mutex_assert_unlocked(M)	k5_pthread_assert_unlocked(&(M)->p)
+# define k5_os_mutex_assert_locked(M)	k5_pthread_assert_locked(M)
+
+#endif /* is pthreads always available? */
+
+#elif defined _WIN32
+
+typedef struct {
+    HANDLE h;
+    int is_locked;
+} k5_os_mutex;
+
+# define K5_OS_MUTEX_PARTIAL_INITIALIZER { INVALID_HANDLE_VALUE, 0 }
+
+# define k5_os_mutex_finish_init(M)					 \
+	(assert((M)->h == INVALID_HANDLE_VALUE),			 \
+	 ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError())
+# define k5_os_mutex_init(M)						 \
+	((M)->is_locked = 0,						 \
+	 ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError())
+# define k5_os_mutex_destroy(M)		\
+	(CloseHandle((M)->h) ? ((M)->h = 0, 0) : GetLastError())
+
+static inline int k5_os_mutex_lock(k5_os_mutex *m)
+{
+    DWORD res;
+    res = WaitForSingleObject(m->h, INFINITE);
+    if (res == WAIT_FAILED)
+	return GetLastError();
+    /* Eventually these should be turned into some reasonable error
+       code.  */
+    assert(res != WAIT_TIMEOUT);
+    assert(res != WAIT_ABANDONED);
+    assert(res == WAIT_OBJECT_0);
+    /* Avoid locking twice.  */
+    assert(m->is_locked == 0);
+    m->is_locked = 1;
+    return 0;
+}
+
+# define k5_os_mutex_unlock(M)				\
+	(assert((M)->is_locked == 1),			\
+	 (M)->is_locked = 0,				\
+	 ReleaseMutex((M)->h) ? 0 : GetLastError())
+
+# define k5_os_mutex_assert_unlocked(M)	((void)0)
+# define k5_os_mutex_assert_locked(M)	((void)0)
+
+#else
+
+# error "Thread support enabled, but thread system unknown"
+
+#endif
+
+
+
+
+typedef struct {
+    k5_debug_loc loc_last, loc_created;
+    k5_os_mutex os;
+    k5_debug_mutex_stats stats;
+} k5_mutex_t;
+#define K5_MUTEX_PARTIAL_INITIALIZER		\
+	{ K5_DEBUG_LOC_INIT, K5_DEBUG_LOC_INIT,	\
+	  K5_OS_MUTEX_PARTIAL_INITIALIZER, K5_MUTEX_STATS_INIT }
+static inline int k5_mutex_init_1(k5_mutex_t *m, k5_debug_loc l)
+{
+    int err = k5_os_mutex_init(&m->os);
+    if (err) return err;
+    m->loc_created = m->loc_last = l;
+    err = k5_mutex_init_stats(&m->stats);
+    assert(err == 0);
+    return 0;
+}
+#define k5_mutex_init(M)	k5_mutex_init_1((M), K5_DEBUG_LOC)
+static inline int k5_mutex_finish_init_1(k5_mutex_t *m, k5_debug_loc l)
+{
+    int err = k5_os_mutex_finish_init(&m->os);
+    if (err) return err;
+    m->loc_created = m->loc_last = l;
+    err = k5_mutex_finish_init_stats(&m->stats);
+    assert(err == 0);
+    return 0;
+}
+#define k5_mutex_finish_init(M)	k5_mutex_finish_init_1((M), K5_DEBUG_LOC)
+#define k5_mutex_destroy(M)			\
+	(k5_os_mutex_assert_unlocked(&(M)->os),	\
+	 krb5int_mutex_report_stats(M),		\
+	 k5_mutex_lock(M), (M)->loc_last = K5_DEBUG_LOC, k5_mutex_unlock(M), \
+	 k5_os_mutex_destroy(&(M)->os))
+#ifdef __GNUC__
+#define k5_mutex_lock(M)						 \
+	__extension__ ({						 \
+	    int _err = 0;						 \
+	    k5_mutex_stats_tmp _stats = k5_mutex_stats_start();		 \
+	    k5_mutex_t *_m = (M);					 \
+	    _err = k5_os_mutex_lock(&_m->os);				 \
+	    if (_err == 0) _m->loc_last = K5_DEBUG_LOC;			 \
+	    if (_err == 0) k5_mutex_lock_update_stats(&_m->stats, _stats); \
+	    _err;							 \
+	})
+#else
+static inline int k5_mutex_lock_1(k5_mutex_t *m, k5_debug_loc l)
+{
+    int err = 0;
+    k5_mutex_stats_tmp stats = k5_mutex_stats_start();
+    err = k5_os_mutex_lock(&m->os);
+    if (err)
+	return err;
+    m->loc_last = l;
+    k5_mutex_lock_update_stats(&m->stats, stats);
+    return err;
+}
+#define k5_mutex_lock(M)	k5_mutex_lock_1(M, K5_DEBUG_LOC)
+#endif
+#define k5_mutex_unlock(M)				\
+	(k5_mutex_assert_locked(M),			\
+	 k5_mutex_unlock_update_stats(&(M)->stats),	\
+	 (M)->loc_last = K5_DEBUG_LOC,			\
+	 k5_os_mutex_unlock(&(M)->os))
+
+#define k5_mutex_assert_locked(M)	k5_os_mutex_assert_locked(&(M)->os)
+#define k5_mutex_assert_unlocked(M)	k5_os_mutex_assert_unlocked(&(M)->os)
+
+#define k5_assert_locked	k5_mutex_assert_locked
+#define k5_assert_unlocked	k5_mutex_assert_unlocked
+
+
+/* Thread-specific data; implemented in a support file, because we'll
+   need to keep track of some global data for cleanup purposes.
+
+   Note that the callback function type is such that the C library
+   routine free() is a valid callback.  */
+typedef enum {
+    K5_KEY_COM_ERR,
+    K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME,
+    K5_KEY_GSS_KRB5_CCACHE_NAME,
+    K5_KEY_MAX
+} k5_key_t;
+/* rename shorthand symbols for export */
+#define k5_key_register	krb5int_key_register
+#define k5_getspecific	krb5int_getspecific
+#define k5_setspecific	krb5int_setspecific
+#define k5_key_delete	krb5int_key_delete
+extern int k5_key_register(k5_key_t, void (*)(void *));
+extern void *k5_getspecific(k5_key_t);
+extern int k5_setspecific(k5_key_t, void *);
+extern int k5_key_delete(k5_key_t);
+
+extern int  KRB5_CALLCONV krb5int_mutex_alloc  (k5_mutex_t **);
+extern void KRB5_CALLCONV krb5int_mutex_free   (k5_mutex_t *);
+extern int  KRB5_CALLCONV krb5int_mutex_lock   (k5_mutex_t *);
+extern int  KRB5_CALLCONV krb5int_mutex_unlock (k5_mutex_t *);
+
+/* In time, many of the definitions above should move into the support
+   library, and this file should be greatly simplified.  For type
+   definitions, that'll take some work, since other data structures
+   incorporate mutexes directly, and our mutex type is dependent on
+   configuration options and system attributes.  For most functions,
+   though, it should be relatively easy.
+
+   For now, plugins should use the exported functions, and not the
+   above macros, and use krb5int_mutex_alloc for allocations.  */
+#ifdef PLUGIN
+#undef k5_mutex_lock
+#define k5_mutex_lock krb5int_mutex_lock
+#undef k5_mutex_unlock
+#define k5_mutex_unlock krb5int_mutex_unlock
+#endif
+
+#endif /* multiple inclusion? */
diff --git a/krb5-1-6/src/include/k5-util.h b/krb5-1-6/src/include/k5-util.h
new file mode 100644
index 000000000..7bb8cfbe9
--- /dev/null
+++ b/krb5-1-6/src/include/k5-util.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 1989-1998,2002 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+/*
+ * "internal" utility functions used by various applications.
+ * They live in libkrb5util.
+ */
+
+#include "autoconf.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <errno.h>
+
+#ifndef krb5_seteuid
+
+#if defined(HAVE_SETEUID)
+#  define krb5_seteuid(EUID)	(seteuid((uid_t)(EUID)))
+#elif defined(HAVE_SETRESUID)
+#  define krb5_seteuid(EUID)	setresuid(getuid(), (uid_t)(EUID), geteuid())
+#elif defined(HAVE_SETREUID)
+#  define krb5_seteuid(EUID)	setreuid(geteuid(), (uid_t)(EUID))
+#else
+   /* You need to add a case to deal with this operating system.*/
+#  define krb5_seteuid(EUID)	(errno = EPERM, -1)
+#endif
+
+#ifdef HAVE_SETEGID
+#  define krb5_setegid(EGID)	(setegid((gid_t)(EGID)))
+#elif defined(HAVE_SETRESGID)
+#  define krb5_setegid(EGID)	(setresgid(getgid(), (gid_t)(EGID), getegid()))
+#elif defined(HAVE_SETREGID)
+#  define krb5_setegid(EGID)	(setregid(getegid(), (gid_t)(EGID)))
+#else
+   /* You need to add a case to deal with this operating system.*/
+#  define krb5_setegid(EGID)	(errno = EPERM, -1)
+#endif
+
+#endif
diff --git a/krb5-1-6/src/include/kdb.h b/krb5-1-6/src/include/kdb.h
new file mode 100644
index 000000000..e8a58787c
--- /dev/null
+++ b/krb5-1-6/src/include/kdb.h
@@ -0,0 +1,500 @@
+/*
+ * include/krb5/kdb.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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__
+
+/* Salt types */
+#define KRB5_KDB_SALTTYPE_NORMAL	0
+#define KRB5_KDB_SALTTYPE_V4		1
+#define KRB5_KDB_SALTTYPE_NOREALM	2
+#define KRB5_KDB_SALTTYPE_ONLYREALM	3
+#define KRB5_KDB_SALTTYPE_SPECIAL	4
+#define KRB5_KDB_SALTTYPE_AFS3		5
+
+/* Attributes */
+#define	KRB5_KDB_DISALLOW_POSTDATED	0x00000001
+#define	KRB5_KDB_DISALLOW_FORWARDABLE	0x00000002
+#define	KRB5_KDB_DISALLOW_TGT_BASED	0x00000004
+#define	KRB5_KDB_DISALLOW_RENEWABLE	0x00000008
+#define	KRB5_KDB_DISALLOW_PROXIABLE	0x00000010
+#define	KRB5_KDB_DISALLOW_DUP_SKEY	0x00000020
+#define	KRB5_KDB_DISALLOW_ALL_TIX	0x00000040
+#define	KRB5_KDB_REQUIRES_PRE_AUTH	0x00000080
+#define KRB5_KDB_REQUIRES_HW_AUTH	0x00000100
+#define	KRB5_KDB_REQUIRES_PWCHANGE	0x00000200
+#define KRB5_KDB_DISALLOW_SVR		0x00001000
+#define KRB5_KDB_PWCHANGE_SERVICE	0x00002000
+#define KRB5_KDB_SUPPORT_DESMD5         0x00004000
+#define	KRB5_KDB_NEW_PRINC		0x00008000
+
+/* Creation flags */
+#define KRB5_KDB_CREATE_BTREE		0x00000001
+#define KRB5_KDB_CREATE_HASH		0x00000002
+
+/*
+ * Note --- these structures cannot be modified without changing the
+ * database version number in libkdb.a, but should be expandable by
+ * adding new tl_data types.
+ */
+typedef struct _krb5_tl_data {
+    struct _krb5_tl_data* tl_data_next;		/* NOT saved */
+    krb5_int16 		  tl_data_type;		
+    krb5_ui_2		  tl_data_length;	
+    krb5_octet 	        * tl_data_contents;	
+} krb5_tl_data;
+
+/* 
+ * If this ever changes up the version number and make the arrays be as
+ * big as necessary.
+ *
+ * Currently the first type is the enctype and the second is the salt type.
+ */
+typedef struct _krb5_key_data {
+    krb5_int16 		  key_data_ver;		/* Version */
+    krb5_int16		  key_data_kvno;	/* Key Version */
+    krb5_int16		  key_data_type[2];	/* Array of types */
+    krb5_ui_2		  key_data_length[2];	/* Array of lengths */
+    krb5_octet 	        * key_data_contents[2];	/* Array of pointers */
+} krb5_key_data;
+
+#define KRB5_KDB_V1_KEY_DATA_ARRAY	2	/* # of array elements */
+
+typedef struct _krb5_keysalt {
+    krb5_int16		  type;	
+    krb5_data		  data;			/* Length, data */
+} krb5_keysalt;
+
+typedef struct _krb5_db_entry_new {
+    krb5_magic 		  magic;		/* NOT saved */
+    krb5_ui_2		  len;			
+    krb5_ui_4             mask;                 /* members currently changed/set */	
+    krb5_flags 		  attributes;
+    krb5_deltat		  max_life;
+    krb5_deltat		  max_renewable_life;
+    krb5_timestamp 	  expiration;	  	/* When the client expires */
+    krb5_timestamp 	  pw_expiration;  	/* When its passwd expires */
+    krb5_timestamp 	  last_success;		/* Last successful passwd */
+    krb5_timestamp 	  last_failed;		/* Last failed passwd attempt */
+    krb5_kvno 	 	  fail_auth_count; 	/* # of failed passwd attempt */
+    krb5_int16 		  n_tl_data;
+    krb5_int16 		  n_key_data;
+    krb5_ui_2		  e_length;		/* Length of extra data */
+    krb5_octet		* e_data;		/* Extra data to be saved */
+
+    krb5_principal 	  princ;		/* Length, data */	
+    krb5_tl_data	* tl_data;		/* Linked list */
+    krb5_key_data       * key_data;		/* Array */
+} krb5_db_entry;
+
+typedef struct _osa_policy_ent_t {
+    int               version;
+    char      *name;
+    krb5_ui_4       pw_min_life;
+    krb5_ui_4       pw_max_life;
+    krb5_ui_4       pw_min_length;
+    krb5_ui_4       pw_min_classes;
+    krb5_ui_4       pw_history_num;
+    krb5_ui_4       policy_refcnt;
+} osa_policy_ent_rec, *osa_policy_ent_t;
+
+typedef       void    (*osa_adb_iter_policy_func) (void *, osa_policy_ent_t);
+
+typedef struct __krb5_key_salt_tuple {
+    krb5_enctype	ks_enctype;
+    krb5_int32		ks_salttype;
+} krb5_key_salt_tuple;
+
+#define	KRB5_KDB_MAGIC_NUMBER		0xdbdbdbdb
+#define KRB5_KDB_V1_BASE_LENGTH		38
+  
+#define KRB5_TL_LAST_PWD_CHANGE		0x0001
+#define KRB5_TL_MOD_PRINC		0x0002
+#define KRB5_TL_KADM_DATA		0x0003
+#define KRB5_TL_KADM5_E_DATA		0x0004
+#define KRB5_TL_RB1_CHALLENGE		0x0005
+#ifdef SECURID
+#define KRB5_TL_SECURID_STATE           0x0006
+#define KRB5_TL_DB_ARGS                 0x7fff
+#endif /* SECURID */
+#define KRB5_TL_USER_CERTIFICATE        0x0007
+    
+/*
+ * Determines the number of failed KDC requests before DISALLOW_ALL_TIX is set
+ * on the principal.
+ */
+#define KRB5_MAX_FAIL_COUNT		5
+
+/* XXX depends on knowledge of krb5_parse_name() formats */
+#define KRB5_KDB_M_NAME		"K/M"	/* Kerberos/Master */
+
+/* prompts used by default when reading the KDC password from the keyboard. */
+#define KRB5_KDC_MKEY_1	"Enter KDC database master key"
+#define KRB5_KDC_MKEY_2	"Re-enter KDC database master key to verify"
+
+
+extern char *krb5_mkey_pwd_prompt1;
+extern char *krb5_mkey_pwd_prompt2;
+
+/*
+ * These macros specify the encoding of data within the database.
+ *
+ * Data encoding is little-endian.
+ */
+#include "k5-platform.h"
+#define	krb5_kdb_decode_int16(cp, i16)	\
+	*((krb5_int16 *) &(i16)) = load_16_le(cp)
+#define	krb5_kdb_decode_int32(cp, i32)	\
+	*((krb5_int32 *) &(i32)) = load_32_le(cp)
+#define krb5_kdb_encode_int16(i16, cp)	store_16_le(i16, cp)
+#define	krb5_kdb_encode_int32(i32, cp)	store_32_le(i32, cp)
+
+#define KRB5_KDB_OPEN_RW                0
+#define KRB5_KDB_OPEN_RO                1
+
+#ifndef KRB5_KDB_SRV_TYPE_KDC
+#define KRB5_KDB_SRV_TYPE_KDC           0x0100        
+#endif
+
+#ifndef KRB5_KDB_SRV_TYPE_ADMIN
+#define KRB5_KDB_SRV_TYPE_ADMIN         0x0200  
+#endif
+
+#ifndef KRB5_KDB_SRV_TYPE_PASSWD
+#define KRB5_KDB_SRV_TYPE_PASSWD        0x0300
+#endif
+
+#ifndef KRB5_KDB_SRV_TYPE_OTHER
+#define KRB5_KDB_SRV_TYPE_OTHER         0x0400  
+#endif
+
+#define KRB5_KDB_OPT_SET_DB_NAME        0
+#define KRB5_KDB_OPT_SET_LOCK_MODE      1
+
+#define KRB5_DB_LOCKMODE_SHARED       0x0001
+#define KRB5_DB_LOCKMODE_EXCLUSIVE    0x0002
+#define KRB5_DB_LOCKMODE_DONTBLOCK    0x0004
+#define KRB5_DB_LOCKMODE_PERMANENT    0x0008
+
+/* libkdb.spec */
+krb5_error_code krb5_db_open( krb5_context kcontext, char **db_args, int mode );
+krb5_error_code krb5_db_init  ( krb5_context kcontext );
+krb5_error_code krb5_db_create ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_inited  ( krb5_context kcontext );
+krb5_error_code kdb5_db_create ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_fini ( krb5_context kcontext );
+const char * krb5_db_errcode2string ( krb5_context kcontext, long err_code );
+krb5_error_code krb5_db_destroy ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_promote ( krb5_context kcontext, char **db_args );
+krb5_error_code krb5_db_get_age ( krb5_context kcontext, char *db_name, time_t *t );
+krb5_error_code krb5_db_set_option ( krb5_context kcontext, int option, void *value );
+krb5_error_code krb5_db_lock ( krb5_context kcontext, int lock_mode );
+krb5_error_code krb5_db_unlock ( krb5_context kcontext );
+krb5_error_code krb5_db_get_principal ( krb5_context kcontext,
+					krb5_const_principal search_for,
+					krb5_db_entry *entries,
+					int *nentries,
+					krb5_boolean *more );
+krb5_error_code krb5_db_free_principal ( krb5_context kcontext,
+					 krb5_db_entry *entry,
+					 int count );
+krb5_error_code krb5_db_put_principal ( krb5_context kcontext,
+					krb5_db_entry *entries,
+					int *nentries);
+krb5_error_code krb5_db_delete_principal ( krb5_context kcontext,
+					   krb5_principal search_for,
+					   int *nentries );
+krb5_error_code krb5_db_iterate ( krb5_context kcontext,
+				  char *match_entry,
+				  int (*func) (krb5_pointer, krb5_db_entry *),
+				  krb5_pointer func_arg );
+krb5_error_code krb5_supported_realms ( krb5_context kcontext,
+					char **realms );
+krb5_error_code krb5_free_supported_realms ( krb5_context kcontext,
+					     char **realms );
+krb5_error_code krb5_db_set_master_key_ext ( krb5_context kcontext,
+					     char *pwd,
+					     krb5_keyblock *key );
+krb5_error_code krb5_db_set_mkey ( krb5_context context, 
+				   krb5_keyblock *key);
+krb5_error_code krb5_db_get_mkey ( krb5_context kcontext,
+				   krb5_keyblock **key );
+krb5_error_code krb5_db_free_master_key ( krb5_context kcontext,
+					  krb5_keyblock *key );
+krb5_error_code krb5_db_store_master_key  ( krb5_context kcontext, 
+					    char *db_arg, 
+					    krb5_principal mname,
+					    krb5_keyblock *key,
+					    char *master_pwd);
+krb5_error_code krb5_db_fetch_mkey  ( krb5_context   context,
+				      krb5_principal mname,
+				      krb5_enctype   etype,
+				      krb5_boolean   fromkeyboard,
+				      krb5_boolean   twice,
+				      char          *db_args,
+				      krb5_data     *salt,
+				      krb5_keyblock *key);
+krb5_error_code krb5_db_verify_master_key ( krb5_context kcontext,
+					    krb5_principal mprinc,
+					    krb5_keyblock *mkey );
+krb5_error_code
+krb5_dbe_find_enctype( krb5_context	kcontext,
+		       krb5_db_entry	*dbentp,
+		       krb5_int32		ktype,
+		       krb5_int32		stype,
+		       krb5_int32		kvno,
+		       krb5_key_data	**kdatap);
+
+
+krb5_error_code krb5_dbe_search_enctype ( krb5_context kcontext, 
+					  krb5_db_entry *dbentp, 
+					  krb5_int32 *start, 
+					  krb5_int32 ktype, 
+					  krb5_int32 stype, 
+					  krb5_int32 kvno, 
+					  krb5_key_data **kdatap);
+
+krb5_error_code
+krb5_db_setup_mkey_name ( krb5_context context,
+			  const char *keyname,
+			  const char *realm,
+			  char **fullname,
+			  krb5_principal *principal);
+
+krb5_error_code
+krb5_dbekd_decrypt_key_data( krb5_context 	  context,
+			     const krb5_keyblock	* mkey,
+			     const krb5_key_data	* key_data,
+			     krb5_keyblock 	* dbkey,
+			     krb5_keysalt 	* keysalt);
+
+krb5_error_code
+krb5_dbekd_encrypt_key_data( krb5_context 		  context,
+			     const krb5_keyblock	* mkey,
+			     const krb5_keyblock 	* dbkey,
+			     const krb5_keysalt		* keysalt,
+			     int			  keyver,
+			     krb5_key_data	        * key_data);
+
+krb5_error_code
+krb5_dbe_lookup_mod_princ_data( krb5_context          context,
+				krb5_db_entry       * entry,
+				krb5_timestamp      * mod_time,
+				krb5_principal      * mod_princ);
+ 
+
+krb5_error_code
+krb5_dbe_update_last_pwd_change( krb5_context          context,
+				 krb5_db_entry       * entry,
+				 krb5_timestamp	  stamp);
+
+krb5_error_code
+krb5_dbe_lookup_tl_data( krb5_context          context,
+			 krb5_db_entry       * entry,
+			 krb5_tl_data        * ret_tl_data);
+
+krb5_error_code
+krb5_dbe_create_key_data( krb5_context          context,
+			  krb5_db_entry       * entry);
+
+
+krb5_error_code
+krb5_dbe_update_mod_princ_data( krb5_context          context,
+				krb5_db_entry       * entry,
+				krb5_timestamp        mod_date,
+				krb5_const_principal  mod_princ);
+
+krb5_error_code
+krb5_dbe_update_last_pwd_change( krb5_context          context,
+				 krb5_db_entry       * entry,
+				 krb5_timestamp	  stamp);
+
+void *krb5_db_alloc( krb5_context kcontext,
+		     void *ptr,
+		     size_t size );
+
+void krb5_db_free( krb5_context kcontext,
+		   void *ptr);
+
+
+krb5_error_code
+krb5_dbe_lookup_last_pwd_change( krb5_context          context,
+				 krb5_db_entry       * entry,
+				 krb5_timestamp      * stamp);
+
+krb5_error_code
+krb5_dbe_update_tl_data( krb5_context          context,
+			 krb5_db_entry       * entry,
+			 krb5_tl_data        * new_tl_data);
+
+krb5_error_code
+krb5_dbe_cpw( krb5_context	  kcontext,
+	      krb5_keyblock       * master_key,
+	      krb5_key_salt_tuple	* ks_tuple,
+	      int			  ks_tuple_count,
+	      char 		* passwd,
+	      int			  new_kvno,
+	      krb5_boolean	  keepold,
+	      krb5_db_entry	* db_entry);
+
+
+krb5_error_code
+krb5_dbe_ark( krb5_context	  context,
+	      krb5_keyblock       * master_key,
+	      krb5_key_salt_tuple	* ks_tuple,
+	      int			  ks_tuple_count,
+	      krb5_db_entry	* db_entry);
+
+krb5_error_code
+krb5_dbe_crk( krb5_context	  context,
+	      krb5_keyblock       * master_key,
+	      krb5_key_salt_tuple	* ks_tuple,
+	      int			  ks_tuple_count,
+	      krb5_boolean	  keepold,
+	      krb5_db_entry	* db_entry);
+
+krb5_error_code
+krb5_dbe_apw( krb5_context	  context,
+	      krb5_keyblock       * master_key,
+	      krb5_key_salt_tuple	* ks_tuple,
+	      int			  ks_tuple_count,
+	      char 		* passwd,
+	      krb5_db_entry	* db_entry);
+
+/* default functions. Should not be directly called */
+/*
+ *   Default functions prototype
+ */
+
+krb5_error_code
+krb5_dbe_def_search_enctype( krb5_context kcontext, 
+			     krb5_db_entry *dbentp, 
+			     krb5_int32 *start, 
+			     krb5_int32 ktype, 
+			     krb5_int32 stype, 
+			     krb5_int32 kvno, 
+			     krb5_key_data **kdatap);
+
+krb5_error_code
+krb5_def_store_mkey( krb5_context context,
+		     char *keyfile,
+		     krb5_principal mname,
+		     krb5_keyblock *key,
+		     char *master_pwd);
+
+
+krb5_error_code
+krb5_db_def_fetch_mkey( krb5_context   context,
+			krb5_principal mname,
+			krb5_keyblock *key,
+			int           *kvno,
+			char          *db_args);
+
+krb5_error_code
+krb5_def_verify_master_key( krb5_context context,
+			    krb5_principal mprinc,
+			    krb5_keyblock *mkey);
+
+krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,
+				   char *pwd,
+				   krb5_keyblock *key );
+
+krb5_error_code kdb_def_get_mkey ( krb5_context kcontext,
+				   krb5_keyblock **key );
+
+krb5_error_code
+krb5_dbe_def_cpw( krb5_context	  context,
+		  krb5_keyblock       * master_key,
+		  krb5_key_salt_tuple	* ks_tuple,
+		  int			  ks_tuple_count,
+		  char 		* passwd,
+		  int			  new_kvno,
+		  krb5_boolean	  keepold,
+		  krb5_db_entry	* db_entry);
+
+krb5_error_code
+krb5_def_promote_db(krb5_context, char *, char **);
+
+krb5_error_code 
+krb5_db_create_policy( krb5_context kcontext, 
+		       osa_policy_ent_t policy);
+
+krb5_error_code 
+krb5_db_get_policy ( krb5_context kcontext, 
+		     char *name, 
+		     osa_policy_ent_t *policy,
+		     int *nentries);
+
+krb5_error_code 
+krb5_db_put_policy( krb5_context kcontext, 
+		    osa_policy_ent_t policy);
+
+krb5_error_code 
+krb5_db_iter_policy( krb5_context kcontext,
+		     char *match_entry,
+		     osa_adb_iter_policy_func func,
+		     void *data);
+
+krb5_error_code 
+krb5_db_delete_policy( krb5_context kcontext, 
+		       char *policy);
+
+void 
+krb5_db_free_policy( krb5_context kcontext, 
+		     osa_policy_ent_t policy);
+
+#define KRB5_KDB_DEF_FLAGS	0
+
+#endif /* KRB5_KDB5__ */
diff --git a/krb5-1-6/src/include/kdb_dbc.h b/krb5-1-6/src/include/kdb_dbc.h
new file mode 100644
index 000000000..e2b300288
--- /dev/null
+++ b/krb5-1-6/src/include/kdb_dbc.h
@@ -0,0 +1,86 @@
+/*
+ * include/krb5/kdb_dbc.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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__
+
+#include "kdb.h"
+	
+/* Per-database context. */
+typedef struct __krb5_db_context {
+    krb5_boolean        db_inited;      /* Context initialized          */
+    char *              db_name;        /* Name of database             */
+    DBM *               db_dbm_ctx;     /* DBM context for database     */
+    char *              db_lf_name;     /* Name of lock file            */
+    int                 db_lf_file;     /* File descriptor of lock file */
+    time_t              db_lf_time;     /* Time last updated            */
+    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_keyblock      *db_master_key;  /* Master key of database       */
+    kdb5_dispatch_table *db_dispatch;   /* Dispatch table               */
+} krb5_db_context;
+
+krb5_error_code krb5_ktkdb_resolve
+        (krb5_context, krb5_db_context *, krb5_keytab *);
+
+krb5_error_code krb5_dbm_db_set_mkey
+        (krb5_context,krb5_db_context *,krb5_encrypt_block *);
+
+krb5_error_code krb5_dbm_db_get_mkey
+        (krb5_context,krb5_db_context *,krb5_encrypt_block **);
+
+#endif /* KRB5_KDB5_DBM__ */
diff --git a/krb5-1-6/src/include/kdb_kt.h b/krb5-1-6/src/include/kdb_kt.h
new file mode 100644
index 000000000..1dbd7f30d
--- /dev/null
+++ b/krb5-1-6/src/include/kdb_kt.h
@@ -0,0 +1,42 @@
+/*
+ * include/krb5/kdb_kt.h
+ *
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * KDC keytab definitions.
+ */
+
+
+#ifndef KRB5_KDB5_KT_H
+#define KRB5_KDB5_KT_H
+
+#include "kdb.h"
+
+extern struct _krb5_kt_ops krb5_kt_kdb_ops;
+
+krb5_error_code krb5_ktkdb_resolve (krb5_context, const char *, krb5_keytab *);
+
+krb5_error_code krb5_ktkdb_set_context(krb5_context);
+
+#endif /* KRB5_KDB5_DBM__ */
diff --git a/krb5-1-6/src/include/kerberosIV/Makefile.in b/krb5-1-6/src/include/kerberosIV/Makefile.in
new file mode 100644
index 000000000..dc410e885
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/Makefile.in
@@ -0,0 +1,22 @@
+thisconfigdir=./../..
+myfulldir=include/kerberosIV
+mydir=include/kerberosIV
+BUILDTOP=$(REL)..$(S)..
+KRB4_HEADERS=krb.h des.h mit-copyright.h
+
+all-unix:: krb_err.h kadm_err.h
+
+krb_err.h: $(SRCTOP)/lib/krb4/krb_err.et
+kadm_err.h: $(SRCTOP)/lib/krb4/kadm_err.et
+krb_err.h kadm_err.h:
+	(cd $(BUILDTOP)/lib/krb4 && $(MAKE) includes)
+
+clean-unix::
+	$(RM) krb_err.h kadm_err.h
+
+install-headers-unix install:: krb_err.h kadm_err.h
+	@set -x; for f in $(KRB4_HEADERS) ; \
+	do $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(KRB5_INCDIR)/kerberosIV/$$f ; \
+	done
+	$(INSTALL_DATA) krb_err.h $(DESTDIR)$(KRB5_INCDIR)$(S)kerberosIV$(S)krb_err.h
+	$(INSTALL_DATA) kadm_err.h $(DESTDIR)$(KRB5_INCDIR)$(S)kerberosIV$(S)kadm_err.h
diff --git a/krb5-1-6/src/include/kerberosIV/addr_comp.h b/krb5-1-6/src/include/kerberosIV/addr_comp.h
new file mode 100644
index 000000000..ccf3a8d05
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/addr_comp.h
@@ -0,0 +1,52 @@
+/*
+ * include/kerberosIV/addr_comp.h
+ *
+ * Copyright 1987-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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Include file for address comparison macros.
+ */
+
+#ifndef ADDR_COMP_DEFS
+#define ADDR_COMP_DEFS
+
+/*
+** Look boys and girls, a big kludge
+** We need to compare the two internet addresses in network byte order, not
+**   local byte order.  This is a *really really slow way of doing that*
+** But.....
+**         .....it works
+** so we run with it
+**
+** long_less_than gets fed two (u_char *)'s....
+*/
+
+#define u_char_comp(x,y) \
+        (((x)>(y))?(1):(((x)==(y))?(0):(-1)))
+
+#define long_less_than(x,y) \
+        (u_char_comp((x)[0],(y)[0])?u_char_comp((x)[0],(y)[0]): \
+	 (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+	  (u_char_comp((x)[2],(y)[2])?u_char_comp((x)[2],(y)[2]): \
+	   (u_char_comp((x)[3],(y)[3])))))
+
+#endif /* ADDR_COMP_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/admin_server.h b/krb5-1-6/src/include/kerberosIV/admin_server.h
new file mode 100644
index 000000000..3da415518
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/admin_server.h
@@ -0,0 +1,58 @@
+/*
+ * include/kerberosIV/admin_server.h
+ *
+ * Copyright 1987-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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#ifndef ADMIN_SERVER_DEFS
+#define ADMIN_SERVER_DEFS
+
+#define PW_SRV_VERSION		 2	/* version number */
+
+#define INSTALL_NEW_PW		(1<<0)	/*
+					 * ver, cmd, name, password,
+					 * old_pass, crypt_pass, uid
+					 */
+
+#define ADMIN_NEW_PW		(2<<1)	/*
+					 * ver, cmd, name, passwd,
+					 * old_pass
+					 * (grot), crypt_pass (grot)
+					 */
+
+#define ADMIN_SET_KDC_PASSWORD	(3<<1)	/* ditto */
+#define ADMIN_ADD_NEW_KEY	(4<<1)	/* ditto */
+#define ADMIN_ADD_NEW_KEY_ATTR	(5<<1)  /*
+					 * ver, cmd, name, passwd,
+					 * inst, attr (grot)
+					 */
+#define INSTALL_REPLY		(1<<1)	/* ver, cmd, name, password */
+#define	RETRY_LIMIT		 1
+#define	TIME_OUT		30
+#define USER_TIMEOUT		90
+#define MAX_KPW_LEN		40
+
+#define KADM	"changepw"		/* service name */
+
+#endif /* ADMIN_SERVER_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/des.h b/krb5-1-6/src/include/kerberosIV/des.h
new file mode 100644
index 000000000..083522405
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/des.h
@@ -0,0 +1,237 @@
+/*
+ * include/kerberosIV/des.h
+ *
+ * Copyright 1987, 1988, 1994, 2002 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Include file for the Data Encryption Standard library.
+ */
+
+#if defined(__MACH__) && defined(__APPLE__)
+#include <TargetConditionals.h>
+#include <AvailabilityMacros.h>
+#if TARGET_RT_MAC_CFM
+#error "Use KfM 4.0 SDK headers for CFM compilation."
+#endif
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5
+#define KRB5INT_DES_DEPRECATED AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5
+#endif
+#endif /* defined(__MACH__) && defined(__APPLE__) */
+
+/* Macro to add deprecated attribute to DES types and functions */
+/* Currently only defined on Mac OS X 10.5 and later.           */
+#ifndef KRB5INT_DES_DEPRECATED
+#define KRB5INT_DES_DEPRECATED
+#endif
+
+#ifdef __cplusplus
+#ifndef KRBINT_BEGIN_DECLS
+#define KRBINT_BEGIN_DECLS	extern "C" {
+#define KRBINT_END_DECLS	}
+#endif
+#else
+#define KRBINT_BEGIN_DECLS
+#define KRBINT_END_DECLS
+#endif
+
+#ifndef KRB5INT_DES_TYPES_DEFINED
+#define KRB5INT_DES_TYPES_DEFINED
+
+#include <limits.h>
+
+KRBINT_BEGIN_DECLS
+
+#if TARGET_OS_MAC
+#	pragma pack(push,2)
+#endif
+
+#if UINT_MAX >= 0xFFFFFFFFUL
+#define DES_INT32 int
+#define DES_UINT32 unsigned int
+#else
+#define DES_INT32 long
+#define DES_UINT32 unsigned long
+#endif
+
+typedef unsigned char des_cblock[8] 	/* crypto-block size */
+KRB5INT_DES_DEPRECATED;
+
+/*
+ * Key schedule.
+ *
+ * This used to be
+ *
+ * typedef struct des_ks_struct {
+ *     union { DES_INT32 pad; des_cblock _;} __;
+ * } des_key_schedule[16];
+ *
+ * but it would cause trouble if DES_INT32 were ever more than 4
+ * bytes.  The reason is that all the encryption functions cast it to
+ * (DES_INT32 *), and treat it as if it were DES_INT32[32].  If
+ * 2*sizeof(DES_INT32) is ever more than sizeof(des_cblock), the
+ * caller-allocated des_key_schedule will be overflowed by the key
+ * scheduling functions.  We can't assume that every platform will
+ * have an exact 32-bit int, and nothing should be looking inside a
+ * des_key_schedule anyway.
+ */
+typedef struct des_ks_struct {  DES_INT32 _[2]; } des_key_schedule[16] 
+KRB5INT_DES_DEPRECATED;
+
+#if TARGET_OS_MAC
+#	pragma pack(pop)
+#endif
+
+KRBINT_END_DECLS
+
+#endif /* KRB5INT_DES_TYPES_DEFINED */
+
+/* only do the whole thing once	 */
+#ifndef DES_DEFS
+/*
+ * lib/crypto/des/des_int.h defines KRB5INT_CRYPTO_DES_INT temporarily
+ * to avoid including the defintions and declarations below.  The
+ * reason that the crypto library needs to include this file is that
+ * it needs to have its types aligned with krb4's types.
+ */
+#ifndef KRB5INT_CRYPTO_DES_INT
+#define DES_DEFS
+
+#if defined(_WIN32)
+#ifndef KRB4
+#define KRB4 1
+#endif
+#include <win-mac.h>
+#endif
+#include <stdio.h> /* need FILE for des_cblock_print_file */
+
+KRBINT_BEGIN_DECLS
+
+#if TARGET_OS_MAC
+#	pragma pack(push,2)
+#endif
+
+/* Windows declarations */
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+#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 Prototypes
+ */
+
+int KRB5_CALLCONV des_key_sched (C_Block, Key_schedule) 
+KRB5INT_DES_DEPRECATED;
+
+int KRB5_CALLCONV
+des_pcbc_encrypt (C_Block *in, C_Block *out, long length,
+		  const des_key_schedule schedule, C_Block *ivec,
+		  int enc) 
+KRB5INT_DES_DEPRECATED;
+
+unsigned long KRB5_CALLCONV
+des_quad_cksum (const unsigned char *in, unsigned DES_INT32 *out,
+		long length, int out_count, C_Block *seed) 
+KRB5INT_DES_DEPRECATED;
+
+/*
+ * XXX ABI change: used to return void; also, cns/kfm have signed long
+ * instead of unsigned long length.
+ */
+unsigned long KRB5_CALLCONV
+des_cbc_cksum(const des_cblock *, des_cblock *, unsigned long,
+	      const des_key_schedule, const des_cblock *) 
+KRB5INT_DES_DEPRECATED;
+
+int KRB5_CALLCONV des_string_to_key (const char *, C_Block) 
+KRB5INT_DES_DEPRECATED;
+
+void afs_string_to_key(char *, char *, des_cblock) 
+KRB5INT_DES_DEPRECATED;
+
+/* XXX ABI change: used to return krb5_error_code */
+int KRB5_CALLCONV des_read_password(des_cblock *, char *, int) 
+KRB5INT_DES_DEPRECATED;
+
+int KRB5_CALLCONV des_ecb_encrypt(des_cblock *, des_cblock *,
+				  const des_key_schedule, int) 
+KRB5INT_DES_DEPRECATED;
+
+/* XXX kfm/cns have signed long length */
+int des_cbc_encrypt(des_cblock *, des_cblock *, unsigned long,
+		    const des_key_schedule, const des_cblock *, int) 
+KRB5INT_DES_DEPRECATED;
+
+void des_fixup_key_parity(des_cblock) 
+KRB5INT_DES_DEPRECATED;
+
+int des_check_key_parity(des_cblock) 
+KRB5INT_DES_DEPRECATED;
+
+int KRB5_CALLCONV des_new_random_key(des_cblock) 
+KRB5INT_DES_DEPRECATED;
+
+void des_init_random_number_generator(des_cblock) 
+KRB5INT_DES_DEPRECATED;
+
+int des_random_key(des_cblock *) 
+KRB5INT_DES_DEPRECATED;
+
+int des_is_weak_key(des_cblock) 
+KRB5INT_DES_DEPRECATED;
+
+void des_cblock_print_file(des_cblock *, FILE *fp) 
+KRB5INT_DES_DEPRECATED;
+
+
+#if TARGET_OS_MAC
+#	pragma pack(pop)
+#endif
+
+KRBINT_END_DECLS
+
+#endif /* KRB5INT_CRYPTO_DES_INT */
+#endif	/* DES_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/kadm.h b/krb5-1-6/src/include/kerberosIV/kadm.h
new file mode 100644
index 000000000..21bc60e5a
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/kadm.h
@@ -0,0 +1,194 @@
+/*
+ * include/kerberosIV/kadm.h
+ *
+ * Copyright 1988, 1994, 2002 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Definitions for Kerberos administration server & client.  These
+ * should be considered private; among other reasons, it leaks all
+ * over the namespace.
+ */
+
+#ifndef KADM_DEFS
+#define KADM_DEFS
+
+/*
+ * kadm.h
+ * Header file for the fourth attempt at an admin server
+ * Doug Church, December 28, 1989, MIT Project Athena
+ */
+
+#include <sys/types.h>
+#include "port-sockets.h"
+#include <kerberosIV/krb.h>
+#include <kerberosIV/des.h>
+
+/* for those broken Unixes without this defined... should be in sys/param.h */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+/* The global structures for the client and server */
+typedef struct {
+    struct sockaddr_in admin_addr;
+    struct sockaddr_in my_addr;
+    int my_addr_len;
+    int admin_fd;		/* file descriptor for link to admin server */
+    char sname[ANAME_SZ];	/* the service name */
+    char sinst[INST_SZ];	/* the services instance */
+    char krbrlm[REALM_SZ];
+    /* KfM additions... */
+    int  default_port;
+    CREDENTIALS creds; /* The client's credentials (from krb_get_pw_in_tkt_creds)*/
+} Kadm_Client;
+
+typedef struct {		/* status of the server, i.e the parameters */
+    int inter;			/* Space for command line flags */
+    char *sysfile;		/* filename of server */
+} admin_params;			/* Well... it's the admin's parameters */
+
+/* Largest password length to be supported */
+#define MAX_KPW_LEN	128
+
+/* Largest packet the admin server will ever allow itself to return */
+#define KADM_RET_MAX 2048
+
+/* That's right, versions are 8 byte strings */
+#define KADM_VERSTR	"KADM0.0A"
+#define KADM_ULOSE	"KYOULOSE"	/* sent back when server can't
+					   decrypt client's msg */
+#define KADM_VERSIZE strlen(KADM_VERSTR)
+
+/* the lookups for the server instances */
+#define PWSERV_NAME  "changepw"
+#define KADM_SNAME   "kerberos_master"
+#define KADM_SINST   "kerberos"
+
+/* Attributes fields constants and macros */
+#define ALLOC        2
+#define RESERVED     3
+#define DEALLOC      4
+#define DEACTIVATED  5
+#define ACTIVE       6
+
+/* Kadm_vals structure for passing db fields into the server routines */
+#define FLDSZ        4
+
+typedef struct {
+    u_char         fields[FLDSZ];     /* The active fields in this struct */
+    char           name[ANAME_SZ];
+    char           instance[INST_SZ];
+    KRB_UINT32     key_low;
+    KRB_UINT32     key_high;
+    KRB_UINT32     exp_date;
+    unsigned short attributes;
+    unsigned char  max_life;
+} Kadm_vals;                    /* The basic values structure in Kadm */
+
+/* Kadm_vals structure for passing db fields into the server routines */
+#define FLDSZ        4
+
+/* Need to define fields types here */
+#define KADM_NAME       31
+#define KADM_INST       30
+#define KADM_EXPDATE    29
+#define KADM_ATTR       28
+#define KADM_MAXLIFE    27
+#define KADM_DESKEY     26
+
+/* To set a field entry f in a fields structure d */
+#define SET_FIELD(f,d)  (d[3-(f/8)]|=(1<<(f%8)))
+
+/* To set a field entry f in a fields structure d */
+#define CLEAR_FIELD(f,d)  (d[3-(f/8)]&=(~(1<<(f%8))))
+
+/* Is field f in fields structure d */
+#define IS_FIELD(f,d)   (d[3-(f/8)]&(1<<(f%8)))
+
+/* Various return codes */
+#define KADM_SUCCESS    0
+
+#define WILDCARD_STR "*"
+
+enum acl_types {
+ADDACL,
+GETACL,
+MODACL,
+STABACL,
+DELACL
+};
+
+/* Various opcodes for the admin server's functions */
+#define CHANGE_PW    2
+#define ADD_ENT      3
+#define MOD_ENT      4
+#define GET_ENT      5
+#define CHECK_PW     6
+#define CHG_STAB     7
+/* Cygnus principal-deletion support */
+#define KADM_CYGNUS_EXT_BASE 64
+#define DEL_ENT              (KADM_CYGNUS_EXT_BASE+1)
+
+#ifdef POSIX
+typedef void sigtype;
+#else
+typedef int sigtype;
+#endif
+
+/* Avoid stomping on namespace... */
+
+#define vals_to_stream		kadm_vals_to_stream
+#define build_field_header	kadm_build_field_header
+#define vts_string		kadm_vts_string
+#define vts_short		kadm_vts_short
+#define vts_long		kadm_vts_long
+#define vts_char		kadm_vts_char
+
+#define stream_to_vals		kadm_stream_to_vals
+#define check_field_header	kadm_check_field_header
+#define stv_string		kadm_stv_string
+#define stv_short		kadm_stv_short
+#define stv_long		kadm_stv_long
+#define stv_char		kadm_stv_char
+
+int vals_to_stream(Kadm_vals *, u_char **);
+int build_field_header(u_char *, u_char **);
+int vts_string(char *, u_char **, int);
+int vts_short(KRB_UINT32, u_char **, int);
+int vts_long(KRB_UINT32, u_char **, int);
+int vts_char(KRB_UINT32, u_char **, int);
+
+int stream_to_vals(u_char *, Kadm_vals *, int);
+int check_field_header(u_char *, u_char *, int);
+int stv_string(u_char *, char *, int, int, int);
+int stv_short(u_char *, u_short *, int, int);
+int stv_long(u_char *, KRB_UINT32 *, int, int);
+int stv_char(u_char *, u_char *, int, int);
+
+int kadm_init_link(char *, char *, char *, Kadm_Client *, int);
+int kadm_cli_send(Kadm_Client *, u_char *, size_t, u_char **, size_t *);
+int kadm_cli_conn(Kadm_Client *);
+void kadm_cli_disconn(Kadm_Client *);
+int kadm_cli_out(Kadm_Client *, u_char *, int, u_char **, size_t *);
+int kadm_cli_keyd(Kadm_Client *, des_cblock, des_key_schedule);
+
+#endif /* KADM_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/kdc.h b/krb5-1-6/src/include/kerberosIV/kdc.h
new file mode 100644
index 000000000..095420c28
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/kdc.h
@@ -0,0 +1,55 @@
+/*
+ * include/kerberosIV/kdc.h
+ *
+ * Copyright 1987, 1988, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Include file for the Kerberos Key Distribution Center. 
+ */
+
+#ifndef KDC_DEFS
+#define KDC_DEFS
+
+#define S_AD_SZ		sizeof(struct sockaddr_in)
+
+#ifdef notdef
+#define max(a,b)	(a>b ? a : b)
+#define min(a,b)	(a<b ? a : b)
+#endif
+
+#define TRUE		1
+#define FALSE		0
+
+#define MKEYFILE	"/.k"
+#define K_LOGFIL	"/kerberos/kpropd.log"
+#define KS_LOGFIL	"/kerberos/kerberos_slave.log"
+#define KRB_ACL		"/kerberos/kerberos.acl"
+#define KRB_PROG	"./kerberos"
+
+#define ONE_MINUTE	60
+#define FIVE_MINUTES	(5 * ONE_MINUTE)
+#define ONE_HOUR	(60 * ONE_MINUTE)
+#define ONE_DAY		(24 * ONE_HOUR)
+#define THREE_DAYS	(3 * ONE_DAY)
+
+#endif /* KDC_DEFS */
+
diff --git a/krb5-1-6/src/include/kerberosIV/klog.h b/krb5-1-6/src/include/kerberosIV/klog.h
new file mode 100644
index 000000000..360fcfbee
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/klog.h
@@ -0,0 +1,57 @@
+/*
+ * include/kerberosIV/klog.h
+ *
+ * Copyright 1988, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * This file defines the types of log messages logged by klog.  Each
+ * type of message may be selectively turned on or off. 
+ */
+
+#ifndef KLOG_DEFS
+#define KLOG_DEFS
+
+#define KRBLOG 		"/kerberos/kerberos.log"  /* master server  */
+#define KRBSLAVELOG	"/kerberos/kerberos_slave.log"  /* master server  */
+#define	NLOGTYPE	100	/* Maximum number of log msg types  */
+
+#define L_NET_ERR	  1	/* Error in network code	    */
+#define L_NET_INFO	  2	/* Info on network activity	    */
+#define L_KRB_PERR	  3	/* Kerberos protocol errors	    */
+#define L_KRB_PINFO	  4	/* Kerberos protocol info	    */
+#define L_INI_REQ	  5	/* Request for initial ticket	    */
+#define L_NTGT_INTK       6	/* Initial request not for TGT	    */
+#define L_DEATH_REQ       7	/* Request for server death	    */
+#define L_TKT_REQ	  8	/* All ticket requests using a tgt  */
+#define L_ERR_SEXP	  9	/* Service expired		    */
+#define L_ERR_MKV	 10	/* Master key version incorrect     */
+#define L_ERR_NKY	 11	/* User's key is null		    */
+#define L_ERR_NUN	 12	/* Principal not unique		    */
+#define L_ERR_UNK	 13	/* Principal Unknown		    */
+#define L_ALL_REQ	 14	/* All requests			    */
+#define L_APPL_REQ	 15	/* Application requests (using tgt) */
+#define L_KRB_PWARN      16	/* Protocol warning messages	    */
+
+char   *klog(int, char *, char *, char *, char *, char *, char *, char *, 
+	     char *, char *, char *, char *);
+
+#endif /* KLOG_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/kparse.h b/krb5-1-6/src/include/kerberosIV/kparse.h
new file mode 100644
index 000000000..6cc890f65
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/kparse.h
@@ -0,0 +1,106 @@
+/*
+ * include/kerberosIV/kparse.h
+ *
+ * Copyright 1988, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Include file for kparse routines.
+ */
+
+#ifndef KPARSE_DEFS
+#define KPARSE_DEFS
+
+/*
+ * values returned by fGetParameterSet() 
+ */
+
+#define PS_BAD_KEYWORD	  -2	/* unknown or duplicate keyword */
+#define PS_SYNTAX	  -1	/* syntax error */
+#define PS_OKAY		   0	/* got a complete parameter set */
+#define PS_EOF		   1	/* nothing more in the file */
+
+/*
+ * values returned by fGetKeywordValue() 
+ */
+
+#define KV_SYNTAX	 -2	/* syntax error */
+#define KV_EOF		 -1	/* nothing more in the file */
+#define KV_OKAY		  0	/* got a keyword/value pair */
+#define KV_EOL		  1	/* nothing more on this line */
+
+/*
+ * values returned by fGetToken() 
+ */
+
+#define GTOK_BAD_QSTRING -1	/* newline found in quoted string */
+#define GTOK_EOF	  0	/* end of file encountered */
+#define GTOK_QSTRING	  1	/* quoted string */
+#define GTOK_STRING	  2	/* unquoted string */
+#define GTOK_NUMBER	  3	/* one or more digits */
+#define GTOK_PUNK	  4	/* punks are punctuation, newline,
+				 * etc. */
+#define GTOK_WHITE	  5	/* one or more whitespace chars */
+
+/*
+ * extended character classification macros 
+ */
+
+#define ISOCTAL(CH) 	( (CH>='0')  && (CH<='7') )
+#define ISQUOTE(CH) 	( (CH=='\"') || (CH=='\'') || (CH=='`') )
+#define ISWHITESPACE(C) ( (C==' ')   || (C=='\t') )
+#define ISLINEFEED(C) 	( (C=='\n')  || (C=='\r')  || (C=='\f') )
+
+/*
+ * tokens consist of any printable charcacter except comma, equal, or
+ * whitespace 
+ */
+
+#define ISTOKENCHAR(C) ((C>040) && (C<0177) && (C != ',') && (C != '='))
+
+/*
+ * the parameter table defines the keywords that will be recognized by
+ * fGetParameterSet, and their default values if not specified. 
+ */
+
+typedef struct {
+    char *keyword;
+    char *defvalue;
+    char *value;
+}       parmtable;
+
+#define PARMCOUNT(P) (sizeof(P)/sizeof(P[0]))
+
+int fGetChar (FILE *fp);
+int fGetParameterSet (FILE *fp, parmtable parm[], int parmcount);
+int ParmCompare (parmtable parm[], int parmcount, char *keyword, char *value);
+
+void FreeParameterSet (parmtable parm[], int parmcount);
+
+int fGetKeywordValue (FILE *fp, char *keyword, int klen, char *value, int vlen);
+
+int fGetToken (FILE *fp, char *dest, int maxlen);
+
+int fGetLiteral (FILE *fp);
+
+int fUngetChar (int ch, FILE *fp);
+
+#endif /* KPARSE_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/krb.h b/krb5-1-6/src/include/kerberosIV/krb.h
new file mode 100644
index 000000000..054acc5da
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/krb.h
@@ -0,0 +1,924 @@
+/*
+ * include/kerberosIV/krb.h
+ *
+ * Copyright 1987, 1988, 1994, 2001, 2002 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Include file for the Kerberos V4 library. 
+ */
+
+/* Only one time, please */
+#ifndef	KRB_DEFS
+#define KRB_DEFS
+
+/*
+ * For MacOS, don't expose prototypes of various private functions.
+ * Unfortuantely, they've leaked out everywhere else.
+ */
+#if defined(__MACH__) && defined(__APPLE__)
+#include <TargetConditionals.h>
+#include <AvailabilityMacros.h>
+#if TARGET_RT_MAC_CFM
+#error "Use KfM 4.0 SDK headers for CFM compilation."
+#endif
+#ifndef KRB_PRIVATE
+#define KRB_PRIVATE 0
+#endif
+#ifdef DEPRECATED_IN_MAC_OS_X_VERSION_10_5
+#define KRB5INT_KRB4_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5
+#endif
+#else
+#ifndef KRB_PRIVATE
+#define KRB_PRIVATE 1
+#endif
+#endif /* defined(__MACH__) && defined(__APPLE__) */
+
+/* Macro to add deprecated attribute to KRB4 types and functions */
+/* Currently only defined on Mac OS X 10.5 and later.            */
+#ifndef KRB5INT_KRB4_DEPRECATED
+#define KRB5INT_KRB4_DEPRECATED
+#endif
+
+/* Define u_char, u_short, u_int, and u_long. */
+/* XXX these typdef names are not standardized! */
+#include <sys/types.h>
+
+/* Need some defs from des.h	 */
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb_err.h>
+#include <profile.h>
+
+#ifdef _WIN32
+#include <time.h>
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+#ifndef KRBINT_BEGIN_DECLS
+#define KRBINT_BEGIN_DECLS	extern "C" {
+#define KRBINT_END_DECLS	}
+#endif
+#else
+#define KRBINT_BEGIN_DECLS
+#define KRBINT_END_DECLS
+#endif
+KRBINT_BEGIN_DECLS
+
+#if TARGET_OS_MAC
+#	pragma pack(push,2)
+#endif
+
+#define KRB4_32		DES_INT32
+#define KRB_INT32	DES_INT32
+#define KRB_UINT32	DES_UINT32
+
+#define		MAX_KRB_ERRORS	256
+
+#if TARGET_OS_MAC
+/* ABI divergence on Mac for backwards compatibility. */
+extern const char * const * const krb_err_txt 
+KRB5INT_KRB4_DEPRECATED;
+#else
+extern const char * const krb_err_txt[MAX_KRB_ERRORS] 
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+/* General definitions */
+#define		KSUCCESS	0
+#define		KFAILURE	255
+
+/*
+ * Kerberos specific definitions 
+ *
+ * KRBLOG is the log file for the kerberos master server. KRB_CONF is
+ * the configuration file where different host machines running master
+ * and slave servers can be found. KRB_MASTER is the name of the
+ * machine with the master database.  The admin_server runs on this
+ * machine, and all changes to the db (as opposed to read-only
+ * requests, which can go to slaves) must go to it. KRB_HOST is the
+ * default machine * when looking for a kerberos slave server.  Other
+ * possibilities are * in the KRB_CONF file. KRB_REALM is the name of
+ * the realm. 
+ */
+
+#define		KRB_CONF	"/etc/krb.conf"
+#define		KRB_RLM_TRANS	"/etc/krb.realms"
+#define		KRB_MASTER	"kerberos"
+#define		KRB_HOST	 KRB_MASTER
+#define		KRB_REALM	"ATHENA.MIT.EDU"
+
+/* The maximum sizes for aname, realm, sname, and instance +1 */
+#define 	ANAME_SZ	40
+#define		REALM_SZ	40
+#define		SNAME_SZ	40
+#define		INST_SZ		40
+#define     ADDR_SZ     40
+/*
+ * NB: This overcounts due to NULs.
+ */
+/* include space for '.' and '@' */
+#define		MAX_K_NAME_SZ	(ANAME_SZ + INST_SZ + REALM_SZ + 2)
+#define		KKEY_SZ		100
+#define		VERSION_SZ	1
+#define		MSG_TYPE_SZ	1
+#define		DATE_SZ		26	/* RTI date output */
+
+#define		MAX_HSTNM	100
+
+#ifndef DEFAULT_TKT_LIFE		/* allow compile-time override */
+#define DEFAULT_TKT_LIFE	120	/* default lifetime for krb_mk_req */
+#endif
+
+#define		KRB_TICKET_GRANTING_TICKET	"krbtgt"
+
+/* Definition of text structure used to pass text around */
+#define		MAX_KTXT_LEN	1250
+
+struct ktext {
+    int     length;		/* Length of the text */
+    unsigned char dat[MAX_KTXT_LEN];	/* The data itself */
+    unsigned long mbz;		/* zero to catch runaway strings */
+} KRB5INT_KRB4_DEPRECATED;
+
+typedef struct ktext *KTEXT KRB5INT_KRB4_DEPRECATED;
+typedef struct ktext KTEXT_ST KRB5INT_KRB4_DEPRECATED;
+
+
+/* Definitions for send_to_kdc */
+#define	CLIENT_KRB_TIMEOUT	4	/* time between retries */
+#define CLIENT_KRB_RETRY	5	/* retry this many times */
+#define	CLIENT_KRB_BUFLEN	512	/* max unfragmented packet */
+
+/* Definitions for ticket file utilities */
+#define	R_TKT_FIL	0
+#define	W_TKT_FIL	1
+
+/* Definitions for cl_get_tgt */
+#ifdef PC
+#define CL_GTGT_INIT_FILE		"\\kerberos\\k_in_tkts"
+#else
+#define CL_GTGT_INIT_FILE		"/etc/k_in_tkts"
+#endif /* PC */
+
+/* Parameters for rd_ap_req */
+/* Maximum allowable clock skew in seconds */
+#define 	CLOCK_SKEW	5*60
+/* Filename for readservkey */
+#define		KEYFILE		((char*)krb__get_srvtabname("/etc/srvtab"))
+
+/* Structure definition for rd_ap_req */
+
+struct auth_dat {
+    unsigned char k_flags;	/* Flags from ticket */
+    char    pname[ANAME_SZ];	/* Principal's name */
+    char    pinst[INST_SZ];	/* His Instance */
+    char    prealm[REALM_SZ];	/* His Realm */
+    unsigned KRB4_32 checksum;	/* Data checksum (opt) */
+    C_Block session;		/* Session Key */
+    int     life;		/* Life of ticket */
+    unsigned KRB4_32 time_sec;	/* Time ticket issued */
+    unsigned KRB4_32 address;	/* Address in ticket */
+    KTEXT_ST reply;		/* Auth reply (opt) */
+} KRB5INT_KRB4_DEPRECATED;
+
+typedef struct auth_dat AUTH_DAT KRB5INT_KRB4_DEPRECATED;
+
+/* Structure definition for credentials returned by get_cred */
+
+struct credentials {
+    char    service[ANAME_SZ];	/* Service name */
+    char    instance[INST_SZ];	/* Instance */
+    char    realm[REALM_SZ];	/* Auth domain */
+    C_Block session;		/* Session key */
+    int     lifetime;		/* Lifetime */
+    int     kvno;		/* Key version number */
+    KTEXT_ST ticket_st;		/* The ticket itself */
+    KRB4_32 issue_date;		/* The issue time */
+    char    pname[ANAME_SZ];	/* Principal's name */
+    char    pinst[INST_SZ];	/* Principal's instance */
+#if TARGET_OS_MAC
+    KRB_UINT32 address;			/* Address in ticket */
+    KRB_UINT32 stk_type;		/* string_to_key function needed */
+#endif
+#ifdef _WIN32
+    char    address[ADDR_SZ];   /* Address in ticket */
+#endif
+} KRB5INT_KRB4_DEPRECATED;
+
+typedef struct credentials CREDENTIALS KRB5INT_KRB4_DEPRECATED;
+
+/* Structure definition for rd_private_msg and rd_safe_msg */
+
+struct msg_dat {
+    unsigned char *app_data;	/* pointer to appl data */
+    unsigned KRB4_32 app_length;	/* length of appl data */
+    unsigned KRB4_32 hash;		/* hash to lookup replay */
+    int     swap;			/* swap bytes? */
+    KRB4_32  time_sec;			/* msg timestamp seconds */
+    unsigned char time_5ms;		/* msg timestamp 5ms units */
+} KRB5INT_KRB4_DEPRECATED;
+
+typedef struct msg_dat MSG_DAT KRB5INT_KRB4_DEPRECATED;
+
+
+/* Location of ticket file for save_cred and get_cred */
+#ifdef _WIN32
+#define TKT_FILE        "\\kerberos\\ticket.ses"
+#else
+#define TKT_FILE        tkt_string()
+#define TKT_ROOT        "/tmp/tkt"
+#endif /* _WIN32 */
+
+/*
+ * Error codes are now defined as offsets from com_err (krb_err.et)
+ * values.
+ */
+#define KRB_ET(x)	((KRBET_ ## x) - ERROR_TABLE_BASE_krb)
+
+/* Error codes returned from the KDC */
+#define	KDC_OK		KRB_ET(KSUCCESS)	/*  0 - Request OK */
+#define	KDC_NAME_EXP	KRB_ET(KDC_NAME_EXP)	/*  1 - Principal expired */
+#define	KDC_SERVICE_EXP	KRB_ET(KDC_SERVICE_EXP)	/*  2 - Service expired */
+#define	KDC_AUTH_EXP	KRB_ET(KDC_AUTH_EXP)	/*  3 - Auth expired */
+#define	KDC_PKT_VER	KRB_ET(KDC_PKT_VER)	/*  4 - Prot version unknown */
+#define	KDC_P_MKEY_VER	KRB_ET(KDC_P_MKEY_VER)	/*  5 - Wrong mkey version */
+#define	KDC_S_MKEY_VER 	KRB_ET(KDC_S_MKEY_VER)	/*  6 - Wrong mkey version */
+#define	KDC_BYTE_ORDER	KRB_ET(KDC_BYTE_ORDER)	/*  7 - Byte order unknown */
+#define	KDC_PR_UNKNOWN	KRB_ET(KDC_PR_UNKNOWN)	/*  8 - Princ unknown */
+#define	KDC_PR_N_UNIQUE KRB_ET(KDC_PR_N_UNIQUE)	/*  9 - Princ not unique */
+#define	KDC_NULL_KEY	KRB_ET(KDC_NULL_KEY)	/* 10 - Princ has null key */
+#define	KDC_GEN_ERR	KRB_ET(KDC_GEN_ERR)	/* 20 - Generic err frm KDC */
+
+/* Values returned by get_credentials */
+#define	GC_OK		KRB_ET(KSUCCESS)	/*  0 - Retrieve OK */
+#define	RET_OK		KRB_ET(KSUCCESS)	/*  0 - Retrieve OK */
+#define	GC_TKFIL	KRB_ET(GC_TKFIL)	/* 21 - Can't rd tkt file */
+#define	RET_TKFIL	KRB_ET(GC_TKFIL)	/* 21 - Can't rd tkt file */
+#define	GC_NOTKT	KRB_ET(GC_NOTKT)	/* 22 - Can't find tkt|TGT */
+#define	RET_NOTKT	KRB_ET(GC_NOTKT)	/* 22 - Can't find tkt|TGT */
+
+/* Values returned by mk_ap_req	 */
+#define	MK_AP_OK	KRB_ET(KSUCCESS)	/*  0 - Success */
+#define	MK_AP_TGTEXP	KRB_ET(MK_AP_TGTEXP)	/* 26 - TGT Expired */
+
+/* Values returned by rd_ap_req */
+#define	RD_AP_OK	KRB_ET(KSUCCESS)	/*  0 - Request authentic */
+#define	RD_AP_UNDEC	KRB_ET(RD_AP_UNDEC)	/* 31 - Can't decode authent */
+#define	RD_AP_EXP	KRB_ET(RD_AP_EXP)	/* 32 - Ticket expired */
+#define	RD_AP_NYV	KRB_ET(RD_AP_NYV)	/* 33 - Ticket not yet valid */
+#define	RD_AP_REPEAT	KRB_ET(RD_AP_REPEAT)	/* 34 - Repeated request */
+#define	RD_AP_NOT_US	KRB_ET(RD_AP_NOT_US)	/* 35 - Ticket isn't for us */
+#define	RD_AP_INCON	KRB_ET(RD_AP_INCON)	/* 36 - Request inconsistent */
+#define	RD_AP_TIME	KRB_ET(RD_AP_TIME)	/* 37 - delta_t too big */
+#define	RD_AP_BADD	KRB_ET(RD_AP_BADD)	/* 38 - Incorrect net addr */
+#define	RD_AP_VERSION	KRB_ET(RD_AP_VERSION)	/* 39 - prot vers mismatch */
+#define	RD_AP_MSG_TYPE	KRB_ET(RD_AP_MSG_TYPE)	/* 40 - invalid msg type */
+#define	RD_AP_MODIFIED	KRB_ET(RD_AP_MODIFIED)	/* 41 - msg stream modified */
+#define	RD_AP_ORDER	KRB_ET(RD_AP_ORDER)	/* 42 - message out of order */
+#define	RD_AP_UNAUTHOR	KRB_ET(RD_AP_UNAUTHOR)	/* 43 - unauthorized request */
+
+/* Values returned by get_pw_tkt */
+#define	GT_PW_OK	KRB_ET(KSUCCESS)	/*  0 - Got passwd chg tkt */
+#define	GT_PW_NULL	KRB_ET(GT_PW_NULL)	/* 51 - Current PW is null */
+#define	GT_PW_BADPW	KRB_ET(GT_PW_BADPW)	/* 52 - Wrong passwd */
+#define	GT_PW_PROT	KRB_ET(GT_PW_PROT)	/* 53 - Protocol Error */
+#define	GT_PW_KDCERR	KRB_ET(GT_PW_KDCERR)	/* 54 - Error ret by KDC */
+#define	GT_PW_NULLTKT	KRB_ET(GT_PW_NULLTKT)	/* 55 - Null tkt ret by KDC */
+
+/* Values returned by send_to_kdc */
+#define	SKDC_OK		KRB_ET(KSUCCESS)	/*  0 - Response received */
+#define	SKDC_RETRY	KRB_ET(SKDC_RETRY)	/* 56 - Retry count exceeded */
+#define	SKDC_CANT	KRB_ET(SKDC_CANT)	/* 57 - Can't send request */
+
+/*
+ * Values returned by get_intkt
+ * (can also return SKDC_* and KDC errors)
+ */
+
+#define	INTK_OK		KRB_ET(KSUCCESS)	/*  0 - Ticket obtained */
+#define	INTK_PW_NULL	KRB_ET(GT_PW_NULL)	/* 51 - Current PW is null */
+#define	INTK_W_NOTALL	KRB_ET(INTK_W_NOTALL)	/* 61 - Not ALL tkts retd */
+#define	INTK_BADPW	KRB_ET(INTK_BADPW)	/* 62 - Incorrect password */
+#define	INTK_PROT	KRB_ET(INTK_PROT)	/* 63 - Protocol Error */
+#define	INTK_ERR	KRB_ET(INTK_ERR)	/* 70 - Other error */
+
+/* Values returned by get_adtkt */
+#define AD_OK		KRB_ET(KSUCCESS)	/*  0 - Ticket Obtained */
+#define AD_NOTGT	KRB_ET(AD_NOTGT)	/* 71 - Don't have tgt */
+
+/* Error codes returned by ticket file utilities */
+#define	NO_TKT_FIL	KRB_ET(NO_TKT_FIL)	/* 76 - No ticket file found */
+#define	TKT_FIL_ACC	KRB_ET(TKT_FIL_ACC)	/* 77 - Can't acc tktfile */
+#define	TKT_FIL_LCK	KRB_ET(TKT_FIL_LCK)	/* 78 - Can't lck tkt file */
+#define	TKT_FIL_FMT	KRB_ET(TKT_FIL_FMT)	/* 79 - Bad tkt file format */
+#define	TKT_FIL_INI	KRB_ET(TKT_FIL_INI)	/* 80 - tf_init not called */
+
+/* Error code returned by kparse_name */
+#define	KNAME_FMT	KRB_ET(KNAME_FMT)	/* 81 - Bad krb name fmt */
+
+/* Error code returned by krb_mk_safe */
+#define	SAFE_PRIV_ERROR	(-1)			/* syscall error */
+
+/* Kerberos ticket flag field bit definitions */
+#define K_FLAG_ORDER    0       /* bit 0 --> lsb */
+#define K_FLAG_1                /* reserved */
+#define K_FLAG_2                /* reserved */
+#define K_FLAG_3                /* reserved */
+#define K_FLAG_4                /* reserved */
+#define K_FLAG_5                /* reserved */
+#define K_FLAG_6                /* reserved */
+#define K_FLAG_7                /* reserved, bit 7 --> msb */
+
+/* Are these needed anymore? */
+#ifdef	OLDNAMES
+#define krb_mk_req	mk_ap_req
+#define krb_rd_req	rd_ap_req
+#define krb_kntoln	an_to_ln
+#define krb_set_key	set_serv_key
+#define krb_get_cred	get_credentials
+#define krb_mk_priv	mk_private_msg
+#define krb_rd_priv	rd_private_msg
+#define krb_mk_safe	mk_safe_msg
+#define krb_rd_safe	rd_safe_msg
+#define krb_mk_err	mk_appl_err_msg
+#define krb_rd_err	rd_appl_err_msg
+#define krb_ck_repl	check_replay
+#define	krb_get_pw_in_tkt	get_in_tkt
+#define krb_get_svc_in_tkt	get_svc_in_tkt
+#define krb_get_pw_tkt		get_pw_tkt
+#define krb_realmofhost		krb_getrealm
+#define krb_get_phost		get_phost
+#define krb_get_krbhst		get_krbhst
+#define krb_get_lrealm		get_krbrlm
+#endif	/* OLDNAMES */
+
+/* Defines for krb_sendauth and krb_recvauth */
+
+#define	KOPT_DONT_MK_REQ 0x00000001 /* don't call krb_mk_req */
+#define	KOPT_DO_MUTUAL   0x00000002 /* do mutual auth */
+#define	KOPT_DONT_CANON  0x00000004 /* don't canonicalize inst as a host */
+
+#define	KRB_SENDAUTH_VLEN 8	    /* length for version strings */
+
+#ifdef ATHENA_COMPAT
+#define	KOPT_DO_OLDSTYLE 0x00000008 /* use the old-style protocol */
+#endif /* ATHENA_COMPAT */
+
+
+#ifdef _WIN32
+#define	TIME_GMT_UNIXSEC	win_time_gmt_unixsec((unsigned KRB4_32 *)0)
+#define	TIME_GMT_UNIXSEC_US(us)	win_time_gmt_unixsec((us))
+#define	CONVERT_TIME_EPOCH	win_time_get_epoch()
+#else
+/* until we do V4 compat under DOS, just turn this off */
+#define	_fmemcpy	memcpy
+#define	_fstrncpy	strncpy
+#define	far_fputs	fputs
+/* and likewise, just drag in the unix time interface */
+#define	TIME_GMT_UNIXSEC	unix_time_gmt_unixsec((unsigned KRB4_32 *)0)
+#define	TIME_GMT_UNIXSEC_US(us)	unix_time_gmt_unixsec((us))
+#define	CONVERT_TIME_EPOCH	((long)0)	/* Unix epoch is Krb epoch */
+#endif /* _WIN32 */
+
+/* Constants for KerberosProfileLib */
+#define	REALMS_V4_PROF_REALMS_SECTION		"v4 realms"
+#define	REALMS_V4_PROF_KDC			"kdc"
+#define	REALMS_V4_PROF_ADMIN_KDC		"admin_server"
+#define	REALMS_V4_PROF_KPASSWD_KDC		"kpasswd_server"
+#define	REALMS_V4_PROF_DOMAIN_SECTION		"v4 domain_realm"
+#define	REALMS_V4_PROF_LIBDEFAULTS_SECTION	"libdefaults"
+#define	REALMS_V4_PROF_LOCAL_REALM		"default_realm"
+#define	REALMS_V4_PROF_STK			"string_to_key_type"
+#define	REALMS_V4_MIT_STK			"mit_string_to_key"
+#define	REALMS_V4_AFS_STK			"afs_string_to_key"
+#define	REALMS_V4_COLUMBIA_STK			"columbia_string_to_key"
+#define	REALMS_V4_DEFAULT_REALM			"default_realm"
+#define	REALMS_V4_NO_ADDRESSES			"noaddresses"
+
+/* ask to disable IP address checking in the library */
+extern int krb_ignore_ip_address;
+
+/* Debugging printfs shouldn't even be compiled on many systems that don't
+   support printf!  Use it like  DEB (("Oops - %s\n", string));  */
+
+#ifdef DEBUG
+#define	DEB(x)	if (krb_debug) printf x
+extern int krb_debug;
+#else
+#define	DEB(x)	/* nothing */
+#endif
+
+/* Define a couple of function types including parameters.  These
+   are needed on MS-Windows to convert arguments of the function pointers
+   to the proper types during calls.  */
+
+typedef int (KRB5_CALLCONV *key_proc_type)
+	(char *, char *, char *,
+		    char *, C_Block)
+KRB5INT_KRB4_DEPRECATED;
+
+#define KEY_PROC_TYPE_DEFINED
+
+typedef int (KRB5_CALLCONV *decrypt_tkt_type)
+	(char *, char *, char *,
+		    char *, key_proc_type, KTEXT *)
+KRB5INT_KRB4_DEPRECATED;
+
+#define DECRYPT_TKT_TYPE_DEFINED
+
+extern struct _krb5_context * krb5__krb4_context;
+
+/*
+ * Function Prototypes for Kerberos V4.
+ */
+
+struct sockaddr_in;
+
+/* dest_tkt.c */
+int KRB5_CALLCONV dest_tkt
+	(void)
+KRB5INT_KRB4_DEPRECATED;
+
+/* err_txt.c */
+const char * KRB5_CALLCONV krb_get_err_text
+	(int errnum)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_ad_tkt.c */
+/* Previously not KRB5_CALLCONV */
+int KRB5_CALLCONV get_ad_tkt
+	(char *service, char *sinst, char *realm, int lifetime)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_admhst.c */
+int KRB5_CALLCONV krb_get_admhst
+	(char *host, char *realm, int idx)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_cred.c */
+int KRB5_CALLCONV krb_get_cred
+	(char *service, char *instance, char *realm,
+		   CREDENTIALS *c)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_in_tkt.c */
+/* Previously not KRB5_CALLCONV */
+int KRB5_CALLCONV krb_get_in_tkt
+	(char *k_user, char *instance, char *realm,
+		   char *service, char *sinst, int life,
+		   key_proc_type, decrypt_tkt_type, char *arg)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+/* Previously not KRB5_CALLCONV */
+int KRB5_CALLCONV krb_get_in_tkt_preauth
+	(char *k_user, char *instance, char *realm,
+		   char *service, char *sinst, int life,
+		   key_proc_type, decrypt_tkt_type, char *arg,
+		   char *preauth_p, int preauth_len)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+/* From KfM */
+int KRB5_CALLCONV krb_get_in_tkt_creds(char *, char *, char *, char *, char *,
+    int, key_proc_type, decrypt_tkt_type, char *, CREDENTIALS *)
+KRB5INT_KRB4_DEPRECATED;
+
+
+/* g_krbhst.c */
+int KRB5_CALLCONV krb_get_krbhst
+	(char *host, const char *realm, int idx)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_krbrlm.c */
+int KRB5_CALLCONV krb_get_lrealm
+	(char *realm, int idx)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_phost.c */
+char * KRB5_CALLCONV krb_get_phost
+	(char * alias)
+KRB5INT_KRB4_DEPRECATED;
+
+/* get_pw_tkt */
+int KRB5_CALLCONV get_pw_tkt 
+        (char *, char *, char *, char *)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_pw_in_tkt.c */
+int KRB5_CALLCONV krb_get_pw_in_tkt
+	(char *k_user, char *instance, char *realm,
+		   char *service, char *sinstance,
+		   int life, char *password)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+int KRB5_CALLCONV krb_get_pw_in_tkt_preauth
+	(char *k_user, char *instance, char *realm,
+		   char *service, char *sinstance,
+		   int life, char *password)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+int KRB5_CALLCONV
+krb_get_pw_in_tkt_creds(char *, char *, char *,
+	char *, char *, int, char *, CREDENTIALS *)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_svc_in_tkt.c */
+int KRB5_CALLCONV krb_get_svc_in_tkt
+	(char *k_user, char *instance, char *realm,
+		   char *service, char *sinstance,
+		   int life, char *srvtab)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_tf_fname.c */
+int KRB5_CALLCONV krb_get_tf_fullname
+	(const char *ticket_file, char *name, char *inst, char *realm)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_tf_realm.c */
+int KRB5_CALLCONV krb_get_tf_realm
+	(const char *ticket_file, char *realm)
+KRB5INT_KRB4_DEPRECATED;
+
+/* g_tkt_svc.c */
+int KRB5_CALLCONV krb_get_ticket_for_service
+	(char *serviceName,
+		   char *buf, unsigned KRB4_32 *buflen,
+		   int checksum, des_cblock, Key_schedule,
+		   char *version, int includeVersion)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+/* in_tkt.c */
+int KRB5_CALLCONV in_tkt
+	(char *name, char *inst)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV krb_in_tkt
+        (char *pname, char *pinst, char *realm)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+/* kname_parse.c */
+int KRB5_CALLCONV kname_parse
+	(char *name, char *inst, char *realm,
+		   char *fullname)
+KRB5INT_KRB4_DEPRECATED;
+
+/* Merged from KfM */
+int KRB5_CALLCONV kname_unparse
+	(char *, const char *, const char *, const char *)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV k_isname
+        (char *)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV k_isinst
+        (char *)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV k_isrealm
+        (char *)
+KRB5INT_KRB4_DEPRECATED;
+
+
+/* kuserok.c */
+int KRB5_CALLCONV kuserok
+	(AUTH_DAT *kdata, char *luser)
+KRB5INT_KRB4_DEPRECATED;
+
+/* lifetime.c */
+KRB4_32 KRB5_CALLCONV krb_life_to_time
+	(KRB4_32 start, int life)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV krb_time_to_life
+	(KRB4_32 start, KRB4_32 end)
+KRB5INT_KRB4_DEPRECATED;
+
+/* mk_auth.c */
+int KRB5_CALLCONV krb_check_auth
+	(KTEXT, unsigned KRB4_32 cksum, MSG_DAT *,
+		   C_Block, Key_schedule,
+		   struct sockaddr_in * local_addr,
+		   struct sockaddr_in * foreign_addr)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV krb_mk_auth
+	(long k4_options, KTEXT ticket,
+		   char *service, char *inst, char *realm,
+		   unsigned KRB4_32 checksum, char *version, KTEXT buf)
+KRB5INT_KRB4_DEPRECATED;
+
+/* mk_err.c */
+long KRB5_CALLCONV krb_mk_err
+	(u_char *out, KRB4_32 k4_code, char *text)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+/* mk_preauth.c */
+int krb_mk_preauth
+	(char **preauth_p, int *preauth_len, key_proc_type,
+		   char *name, char *inst, char *realm, char *password,
+		   C_Block)
+KRB5INT_KRB4_DEPRECATED;
+
+void krb_free_preauth
+	(char * preauth_p, int len)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+/* mk_priv.c */
+long KRB5_CALLCONV krb_mk_priv
+	(u_char *in, u_char *out,
+		   unsigned KRB4_32 length,
+		   Key_schedule, C_Block *,
+		   struct sockaddr_in * sender,
+		   struct sockaddr_in * receiver)
+KRB5INT_KRB4_DEPRECATED;
+
+/* mk_req.c */
+int KRB5_CALLCONV krb_mk_req
+	(KTEXT authent,
+		   char *service, char *instance, char *realm,
+		   KRB4_32 checksum)
+KRB5INT_KRB4_DEPRECATED;
+
+/* Merged from KfM */
+int KRB5_CALLCONV krb_mk_req_creds(KTEXT, CREDENTIALS *, KRB_INT32)
+KRB5INT_KRB4_DEPRECATED;
+
+/* Added CALLCONV (KfM exports w/o INTERFACE, but KfW doesn't export?) */
+int KRB5_CALLCONV krb_set_lifetime(int newval)
+KRB5INT_KRB4_DEPRECATED;
+
+/* mk_safe.c */
+long KRB5_CALLCONV krb_mk_safe
+	(u_char *in, u_char *out, unsigned KRB4_32 length,
+		   C_Block *,
+		   struct sockaddr_in *sender,
+		   struct sockaddr_in *receiver)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+/* netread.c */
+int krb_net_read
+	(int fd, char *buf, int len)
+KRB5INT_KRB4_DEPRECATED;
+
+/* netwrite.c */
+int krb_net_write
+	(int fd, char *buf, int len)
+KRB5INT_KRB4_DEPRECATED;
+
+/* pkt_clen.c */
+int pkt_clen
+	(KTEXT)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+/* put_svc_key.c */
+int KRB5_CALLCONV put_svc_key
+	(char *sfile,
+		   char *name, char *inst, char *realm,
+		   int newvno, char *key)
+KRB5INT_KRB4_DEPRECATED;
+
+/* rd_err.c */
+int KRB5_CALLCONV krb_rd_err
+	(u_char *in, u_long in_length,
+		   long *k4_code, MSG_DAT *m_data)
+KRB5INT_KRB4_DEPRECATED;
+
+/* rd_priv.c */
+long KRB5_CALLCONV krb_rd_priv
+	(u_char *in,unsigned KRB4_32 in_length,
+		   Key_schedule, C_Block *,
+		   struct sockaddr_in *sender,
+		   struct sockaddr_in *receiver,
+		   MSG_DAT *m_data)
+KRB5INT_KRB4_DEPRECATED;
+
+/* rd_req.c */
+int KRB5_CALLCONV krb_rd_req
+	(KTEXT, char *service, char *inst,
+		   unsigned KRB4_32 from_addr, AUTH_DAT *,
+		   char *srvtab)
+KRB5INT_KRB4_DEPRECATED;
+
+/* Merged from KfM */
+int KRB5_CALLCONV
+krb_rd_req_int(KTEXT, char *, char *, KRB_UINT32, AUTH_DAT *, C_Block)
+KRB5INT_KRB4_DEPRECATED;
+
+/* rd_safe.c */
+long KRB5_CALLCONV krb_rd_safe
+	(u_char *in, unsigned KRB4_32 in_length,
+		   C_Block *,
+		   struct sockaddr_in *sender,
+		   struct sockaddr_in *receiver,
+		   MSG_DAT *m_data)
+KRB5INT_KRB4_DEPRECATED;
+
+/* rd_svc_key.c */
+int KRB5_CALLCONV read_service_key
+	(char *service, char *instance, char *realm,
+		   int kvno, char *file, char *key)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV get_service_key
+	(char *service, char *instance, char *realm,
+		   int *kvno, char *file, char *key)
+KRB5INT_KRB4_DEPRECATED;
+
+/* realmofhost.c */
+char * KRB5_CALLCONV krb_realmofhost
+	(char *host)
+KRB5INT_KRB4_DEPRECATED;
+
+/* recvauth.c */
+int KRB5_CALLCONV krb_recvauth
+	(long k4_options, int fd, KTEXT ticket,
+		   char *service, char *instance,
+		   struct sockaddr_in *foreign_addr,
+		   struct sockaddr_in *local_addr,
+		   AUTH_DAT *kdata, char *srvtab,
+		   Key_schedule schedule, char *version)
+KRB5INT_KRB4_DEPRECATED;
+
+/* sendauth.c */
+int KRB5_CALLCONV krb_sendauth
+        (long k4_options, int fd, KTEXT ticket,
+	 char *service, char *inst, char *realm,
+	 unsigned KRB4_32 checksum, MSG_DAT *msg_data,
+	 CREDENTIALS *cred, Key_schedule schedule, 
+	 struct sockaddr_in *laddr, struct sockaddr_in *faddr, 
+	 char *version)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+/* save_creds.c */
+int KRB5_CALLCONV krb_save_credentials
+	(char *service, char *instance, char *realm,
+		   C_Block session, int lifetime, int kvno,
+		   KTEXT ticket, long issue_date)
+KRB5INT_KRB4_DEPRECATED;
+
+/* send_to_kdc.c */
+/* XXX PRIVATE? KfM doesn't export. */
+int send_to_kdc
+	(KTEXT pkt, KTEXT rpkt, char *realm)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+/* tkt_string.c */
+/* Used to return pointer to non-const char */
+const char * KRB5_CALLCONV tkt_string
+	(void)
+KRB5INT_KRB4_DEPRECATED;
+
+/* Previously not KRB5_CALLCONV, and previously took pointer to non-const. */
+void KRB5_CALLCONV krb_set_tkt_string
+	(const char *)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+/* tf_util.c */
+int KRB5_CALLCONV tf_init (const char *tf_name, int rw)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV tf_get_pname (char *p)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV tf_get_pinst (char *p)
+KRB5INT_KRB4_DEPRECATED;
+
+int KRB5_CALLCONV tf_get_cred (CREDENTIALS *c)
+KRB5INT_KRB4_DEPRECATED;
+
+void KRB5_CALLCONV tf_close (void)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+#if KRB_PRIVATE
+/* unix_time.c */
+unsigned KRB4_32 KRB5_CALLCONV unix_time_gmt_unixsec 
+        (unsigned KRB4_32 *)
+KRB5INT_KRB4_DEPRECATED;
+
+/*
+ * Internal prototypes
+ */
+extern int krb_set_key
+	(char *key, int cvt)
+KRB5INT_KRB4_DEPRECATED;
+
+/* This is exported by KfM.  It was previously not KRB5_CALLCONV. */
+extern int KRB5_CALLCONV decomp_ticket
+	(KTEXT tkt, unsigned char *flags, char *pname,
+		   char *pinstance, char *prealm, unsigned KRB4_32 *paddress,
+		   C_Block session, int *life, unsigned KRB4_32 *time_sec,
+		   char *sname, char *sinstance, C_Block,
+		   Key_schedule key_s)
+KRB5INT_KRB4_DEPRECATED;
+
+
+extern void cr_err_reply(KTEXT pkt, char *pname, char *pinst, char *prealm,
+			 u_long time_ws, u_long e, char *e_string)
+KRB5INT_KRB4_DEPRECATED;
+
+extern int create_ciph(KTEXT c, C_Block session, char *service, 
+		       char *instance, char *realm, unsigned long life,
+		       int kvno, KTEXT tkt, unsigned long kdc_time, 
+		       C_Block key)
+KRB5INT_KRB4_DEPRECATED;
+
+
+extern int krb_create_ticket(KTEXT tkt, unsigned int flags, char *pname,
+			     char *pinstance, char *prealm, long paddress,
+			     char *session, int life, long time_sec, 
+			     char *sname, char *sinstance, C_Block key)
+KRB5INT_KRB4_DEPRECATED;
+
+#endif /* KRB_PRIVATE */
+
+/* This function is used by KEYFILE above.  Do not call it directly */
+extern char * krb__get_srvtabname(const char *)
+KRB5INT_KRB4_DEPRECATED;
+
+#if KRB_PRIVATE
+
+extern int krb_kntoln(AUTH_DAT *, char *)
+KRB5INT_KRB4_DEPRECATED;
+
+#ifdef KRB5_GENERAL__
+extern int krb_cr_tkt_krb5(KTEXT tkt, unsigned int flags, char *pname,
+			   char *pinstance, char *prealm, long paddress,
+			   char *session, int life, long time_sec, 
+			   char *sname, char *sinstance,  
+			   krb5_keyblock *k5key)
+KRB5INT_KRB4_DEPRECATED;
+
+extern int krb_set_key_krb5(krb5_context ctx, krb5_keyblock *key)
+KRB5INT_KRB4_DEPRECATED;
+
+#endif
+
+#endif /* KRB_PRIVATE */
+
+/*
+ * krb_change_password -- merged from KfM
+ */
+/* change_password.c */
+int KRB5_CALLCONV krb_change_password(char *, char *, char *, char *, char *)
+KRB5INT_KRB4_DEPRECATED;
+
+/*
+ * RealmsConfig-glue.c -- merged from KfM
+ */
+int KRB5_CALLCONV krb_get_profile(profile_t *)
+KRB5INT_KRB4_DEPRECATED;
+
+#ifdef _WIN32
+HINSTANCE get_lib_instance(void)
+KRB5INT_KRB4_DEPRECATED;
+unsigned int krb_get_notification_message(void)
+KRB5INT_KRB4_DEPRECATED;
+char * KRB5_CALLCONV krb_get_default_user(void)
+KRB5INT_KRB4_DEPRECATED;
+int KRB5_CALLCONV krb_set_default_user(char *)
+KRB5INT_KRB4_DEPRECATED;
+unsigned KRB4_32 win_time_gmt_unixsec(unsigned KRB4_32 *)
+KRB5INT_KRB4_DEPRECATED;
+long win_time_get_epoch(void)
+KRB5INT_KRB4_DEPRECATED;
+#endif
+
+#if TARGET_OS_MAC
+#	pragma pack(pop)
+#endif
+
+KRBINT_END_DECLS
+
+#endif	/* KRB_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/krb_db.h b/krb5-1-6/src/include/kerberosIV/krb_db.h
new file mode 100644
index 000000000..3e3b1dda6
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/krb_db.h
@@ -0,0 +1,119 @@
+/*
+ * include/kerberosIV/krb_db.h
+ *
+ * Copyright 1987, 1988, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * spm		Project Athena  8/85 
+ *
+ * This file defines data structures for the kerberos
+ * authentication/authorization database. 
+ *
+ * They MUST correspond to those defined in *.rel 
+ */
+
+#ifndef KRB_DB_DEFS
+#define KRB_DB_DEFS
+
+#define KERB_M_NAME		"K"	/* Kerberos */
+#define KERB_M_INST		"M"	/* Master */
+#define KERB_DEFAULT_NAME	"default"
+#define KERB_DEFAULT_INST	""
+#define	DBM_FILE		"/kerberos/principal"
+
+/* this also defines the number of queue headers */
+#define KERB_DB_HASH_MODULO 64
+
+
+/* Arguments to kerb_dbl_lock() */
+
+#define KERB_DBL_EXCLUSIVE 1
+#define KERB_DBL_SHARED 0
+
+/* arguments to kerb_db_set_lockmode() */
+
+#define KERB_DBL_BLOCKING 0
+#define KERB_DBL_NONBLOCKING 1
+
+/* Principal defines the structure of a principal's name */
+
+typedef struct {
+    char    name[ANAME_SZ];
+    char    instance[INST_SZ];
+
+    unsigned long key_low;
+    unsigned long key_high;
+    unsigned long exp_date;
+    char    exp_date_txt[DATE_SZ];
+    unsigned long mod_date;
+    char    mod_date_txt[DATE_SZ];
+    unsigned short attributes;
+    unsigned char max_life;
+    unsigned char kdc_key_ver;
+    unsigned char key_version;
+
+    char    mod_name[ANAME_SZ];
+    char    mod_instance[INST_SZ];
+    char   *old;		/* cast to (Principal *); not in db,
+				 * ptr to old vals */
+}
+        Principal;
+
+typedef struct {
+    long    cpu;
+    long    elapsed;
+    long    dio;
+    long    pfault;
+    long    t_stamp;
+    long    n_retrieve;
+    long    n_replace;
+    long    n_append;
+    long    n_get_stat;
+    long    n_put_stat;
+}
+        DB_stat;
+
+/* Dba defines the structure of a database administrator */
+
+typedef struct {
+    char    name[ANAME_SZ];
+    char    instance[INST_SZ];
+    unsigned short attributes;
+    unsigned long exp_date;
+    char    exp_date_txt[DATE_SZ];
+    char   *old;	/*
+			 * cast to (Dba *); not in db, ptr to
+			 * old vals
+			 */
+}
+        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/krb5-1-6/src/include/kerberosIV/krbports.h b/krb5-1-6/src/include/kerberosIV/krbports.h
new file mode 100644
index 000000000..5b4dc5641
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/krbports.h
@@ -0,0 +1,27 @@
+/* krbports.h -- fallback port numbers in case /etc/services isn't changed */
+/* used by: appl/bsd/rcp.c, rlogin.c, rsh.c, knetd.c
+            kadmin/kadm_ser_wrap.c, lib/kadm/kadm_cli_wrap.c
+	    lib/krb/send_to_kdc.c
+	    movemail/movemail.c, pfrom/popmail.c
+	    server/kerberos.c, slave/kprop.c, kpropd.c
+*/
+
+#define KRB_SHELL_PORT 544
+#define UCB_SHELL_PORT 514
+
+#define KLOGIN_PORT 543
+#define EKLOGIN_PORT 2105
+#define UCB_LOGIN_PORT 513
+
+#define KADM_PORT 751
+#define KERBEROS_PORT 750
+#define KERBEROS_SEC_PORT 88
+#define KRB_PROP_PORT 754
+
+#define KPOP_PORT 1109
+#define POP3_PORT 110
+
+#define KNETD_PORT 2053
+
+/* already in rkinit_private.h */
+#define RKINIT_PORT 2108
diff --git a/krb5-1-6/src/include/kerberosIV/lsb_addr_cmp.h b/krb5-1-6/src/include/kerberosIV/lsb_addr_cmp.h
new file mode 100644
index 000000000..573f2b46c
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/lsb_addr_cmp.h
@@ -0,0 +1,47 @@
+/*
+ * include/kerberosIV/lsb_addr_cmp.h
+ *
+ * Copyright 1988, 1995 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Comparison macros to emulate LSBFIRST comparison results of network
+ * byte-order quantities
+ */
+
+#include "mit-copyright.h"
+#ifndef LSB_ADDR_COMP_DEFS
+#define LSB_ADDR_COMP_DEFS
+
+/* #include "osconf.h" */
+
+/* note that if we don't explicitly know if we're LSBFIRST, the 
+   alternate code is byte order independent and will give the
+   right answer. */
+#ifdef LSBFIRST
+#define lsb_net_ulong_less(x,y) ((x < y) ? -1 : ((x > y) ? 1 : 0))
+#define lsb_net_ushort_less(x,y) ((x < y) ? -1 : ((x > y) ? 1 : 0))
+#else
+/* MSBFIRST */
+#define u_char_comp(x,y) \
+        (((x)>(y))?(1):(((x)==(y))?(0):(-1)))
+/* This is gross, but... */
+#define lsb_net_ulong_less(x, y) long_less_than((u_char *)&x, (u_char *)&y)
+#define lsb_net_ushort_less(x, y) short_less_than((u_char *)&x, (u_char *)&y)
+
+#define long_less_than(x,y) \
+        (u_char_comp((x)[3],(y)[3])?u_char_comp((x)[3],(y)[3]): \
+	 (u_char_comp((x)[2],(y)[2])?u_char_comp((x)[2],(y)[2]): \
+	  (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+	   (u_char_comp((x)[0],(y)[0])))))
+#define short_less_than(x,y) \
+	  (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+	   (u_char_comp((x)[0],(y)[0])))
+
+#endif /* LSBFIRST */
+
+/* For krb4 library internal use only.  */
+extern int krb4int_address_less (struct sockaddr_in *, struct sockaddr_in *);
+
+#endif /*  LSB_ADDR_COMP_DEFS */
diff --git a/krb5-1-6/src/include/kerberosIV/mit-copyright.h b/krb5-1-6/src/include/kerberosIV/mit-copyright.h
new file mode 100644
index 000000000..e00865769
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/mit-copyright.h
@@ -0,0 +1,23 @@
+/* 
+  Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+   Export of this software from the United States of America may
+   require a specific license from the United States Government.
+   It is the responsibility of any person or organization contemplating
+   export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, Permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.  Furthermore if you modify this software you must label
+your software as modified software and not distribute it in such a
+fashion that it might be confused with the original M.I.T. software.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is" without express
+or implied warranty.
+
+  */
diff --git a/krb5-1-6/src/include/kerberosIV/prot.h b/krb5-1-6/src/include/kerberosIV/prot.h
new file mode 100644
index 000000000..ccb028bd7
--- /dev/null
+++ b/krb5-1-6/src/include/kerberosIV/prot.h
@@ -0,0 +1,277 @@
+/*
+ * include/kerberosIV/prot.h
+ *
+ * Copyright 1985-1994, 2001 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Prototypes for internal functions, mostly related to protocol
+ * encoding and decoding.
+ */
+
+#ifndef PROT_DEFS
+#define PROT_DEFS
+
+#define		KRB_PORT		750	/* PC's don't have
+						 * /etc/services */
+#define		KRB_PROT_VERSION 	4
+#define 	MAX_PKT_LEN		1000
+#define		MAX_TXT_LEN		1000
+
+/* Macro's to obtain various fields from a packet */
+
+#define pkt_version(packet)  (unsigned int) *(packet->dat)
+#define pkt_msg_type(packet) (unsigned int) *(packet->dat+1)
+#define pkt_a_name(packet)   (packet->dat+2)
+#define pkt_a_inst(packet)   \
+	(packet->dat+3+strlen((char *)pkt_a_name(packet)))
+#define pkt_a_realm(packet)  \
+	(pkt_a_inst(packet)+1+strlen((char *)pkt_a_inst(packet)))
+
+/* Macro to obtain realm from application request */
+#define apreq_realm(auth)     (auth->dat + 3)
+
+#define pkt_time_ws(packet) (char *) \
+        (packet->dat+5+strlen((char *)pkt_a_name(packet)) + \
+	 strlen((char *)pkt_a_inst(packet)) + \
+	 strlen((char *)pkt_a_realm(packet)))
+
+#define pkt_no_req(packet) (unsigned short) \
+        *(packet->dat+9+strlen((char *)pkt_a_name(packet)) + \
+	  strlen((char *)pkt_a_inst(packet)) + \
+	  strlen((char *)pkt_a_realm(packet)))
+#define pkt_x_date(packet) (char *) \
+        (packet->dat+10+strlen((char *)pkt_a_name(packet)) + \
+	 strlen((char *)pkt_a_inst(packet)) + \
+	 strlen((char *)pkt_a_realm(packet)))
+#define pkt_err_code(packet) ( (char *) \
+        (packet->dat+9+strlen((char *)pkt_a_name(packet)) + \
+	 strlen((char *)pkt_a_inst(packet)) + \
+	 strlen((char *)pkt_a_realm(packet))))
+#define pkt_err_text(packet) \
+        (packet->dat+13+strlen((char *)pkt_a_name(packet)) + \
+	 strlen((char *)pkt_a_inst(packet)) + \
+	 strlen((char *)pkt_a_realm(packet)))
+
+/*
+ * This remains here for the KDC to use for now, but will go away
+ * soon.
+ */
+
+#define     swap_u_long(x) {\
+ unsigned KRB4_32   _krb_swap_tmp[4];\
+ swab((char *)  &x,    ((char *)  _krb_swap_tmp) +2 ,2); \
+ swab(((char *) &x) +2,((char *)  _krb_swap_tmp),2); \
+ x = _krb_swap_tmp[0];   \
+                           }
+
+/*
+ * New byte swapping routines, much cleaner.
+ *
+ * Should also go away soon though.
+ */
+#include "k5-platform.h"
+
+#ifdef SWAP16
+#define krb4_swab16(val)	SWAP16(val)
+#else
+#define krb4_swab16(val)	((((val) >> 8)&0xFF) | ((val) << 8))
+#endif
+#ifdef SWAP32
+#define krb4_swap32(val)	SWAP32(val)
+#else
+#define krb4_swab32(val)	((((val)>>24)&0xFF) | (((val)>>8)&0xFF00) | \
+				  (((val)<<8)&0xFF0000) | ((val)<<24))
+#endif
+
+/*
+ * Macros to encode integers into buffers.  These take a parameter
+ * that is a moving pointer of type (unsigned char *) into the buffer,
+ * and assume that the caller has already bounds-checked.
+ */
+#define KRB4_PUT32BE(p, val)	(store_32_be(val, p), (p) += 4)
+#define KRB4_PUT32LE(p, val)	(store_32_le(val, p), (p) += 4)
+#define KRB4_PUT32(p, val, le)			\
+do {						\
+    if (le)					\
+	KRB4_PUT32LE((p), (val));		\
+    else					\
+	KRB4_PUT32BE((p), (val));		\
+} while (0)
+
+#define KRB4_PUT16BE(p, val)	(store_16_be(val, p), (p) += 2)
+#define KRB4_PUT16LE(p, val)	(store_16_le(val, p), (p) += 2)
+#define KRB4_PUT16(p, val, le)			\
+do {						\
+    if (le)					\
+	KRB4_PUT16LE((p), (val));		\
+    else					\
+	KRB4_PUT16BE((p), (val));		\
+} while (0)
+
+/*
+ * Macros to get integers from a buffer.  These take a parameter that
+ * is a moving pointer of type (unsigned char *) into the buffer, and
+ * assume that the caller has already bounds-checked.  In addition,
+ * they assume that val is an unsigned type; ANSI leaves the semantics
+ * of unsigned -> signed conversion as implementation-defined, so it's
+ * unwise to depend on such.
+ */
+#define KRB4_GET32BE(val, p)	((val) = load_32_be(p), (p) += 4)
+#define KRB4_GET32LE(val, p)	((val) = load_32_le(p), (p) += 4)
+#define KRB4_GET32(val, p, le)			\
+do {						\
+    if (le)					\
+	KRB4_GET32LE((val), (p));		\
+    else					\
+	KRB4_GET32BE((val), (p));		\
+} while (0)
+
+#define KRB4_GET16BE(val, p)	((val) = load_16_be(p), (p) += 2)
+#define KRB4_GET16LE(val, p)	((val) = load_16_le(p), (p) += 2)
+#define KRB4_GET16(val, p, le)			\
+do {						\
+    if (le)					\
+	KRB4_GET16LE((val), (p));		\
+    else					\
+	KRB4_GET16BE((val), (p));		\
+} while (0)
+
+/* Routines to create and read packets may be found in prot.c */
+
+KTEXT create_auth_reply(char *, char *, char *, long, int, 
+			unsigned long, int, KTEXT);
+KTEXT create_death_packet(char *);
+KTEXT pkt_cipher(KTEXT);
+
+/* getst.c */
+int krb4int_getst(int, char *, int);
+
+/* strnlen.c */
+extern int KRB5_CALLCONV krb4int_strnlen(const char *, int);
+
+/* prot_client.c */
+extern int KRB5_CALLCONV krb4prot_encode_kdc_request(
+    char *, char *, char *,
+    KRB4_32, int,
+    char *, char *,
+    char *, int, int, int,
+    KTEXT);
+extern int KRB5_CALLCONV krb4prot_decode_kdc_reply(
+    KTEXT,
+    int *,
+    char *, char *, char *,
+    long *, int *, unsigned long *, int *, KTEXT);
+extern int KRB5_CALLCONV krb4prot_decode_ciph(
+    KTEXT, int,
+    C_Block,
+    char *, char *, char *,
+    int *, int *, KTEXT, unsigned long *);
+extern int KRB5_CALLCONV krb4prot_encode_apreq(
+    int, char *,
+    KTEXT, KTEXT,
+    int, int, KTEXT);
+extern int KRB5_CALLCONV krb4prot_encode_authent(
+    char *, char *, char *,
+    KRB4_32,
+    int, long,
+    int, int le,
+    KTEXT pkt);
+extern int KRB5_CALLCONV krb4prot_decode_error(
+    KTEXT, int *,
+    char *, char *, char *,
+    unsigned long *, unsigned long *, char *);
+
+/* prot_common.c */
+extern int KRB5_CALLCONV krb4prot_encode_naminstrlm(
+    char *, char *, char *,
+    int, KTEXT, unsigned char **);
+extern int KRB5_CALLCONV krb4prot_decode_naminstrlm(
+    KTEXT, unsigned char **,
+    char *, char *, char *);
+extern int KRB5_CALLCONV krb4prot_decode_header(
+    KTEXT, int *, int *, int *);
+
+/* prot_kdc.c */
+extern int KRB5_CALLCONV krb4prot_encode_kdc_reply(
+    char *, char *, char *,
+    long, int, unsigned long,
+    int, KTEXT, int, int, KTEXT);
+extern int KRB5_CALLCONV krb4prot_encode_ciph(
+    C_Block,
+    char *, char *, char *,
+    unsigned long, int, KTEXT, unsigned long,
+    int, int, KTEXT);
+extern int KRB5_CALLCONV krb4prot_encode_tkt(
+    unsigned int,
+    char *, char *, char *,
+    unsigned long,
+    char *, int, long,
+    char *, char *,
+    int, int, KTEXT tkt);
+extern int KRB5_CALLCONV krb4prot_encode_err_reply(
+    char *, char *, char *,
+    unsigned long, unsigned long, char *,
+    int, int, KTEXT);
+extern int KRB5_CALLCONV krb4prot_decode_kdc_request(
+    KTEXT,
+    int *, char *, char *, char *,
+    long *, int *, char *sname, char *sinst);
+
+/* Message types , always leave lsb for byte order */
+
+#define		AUTH_MSG_KDC_REQUEST			 1<<1
+#define 	AUTH_MSG_KDC_REPLY			 2<<1
+#define		AUTH_MSG_APPL_REQUEST			 3<<1
+#define		AUTH_MSG_APPL_REQUEST_MUTUAL		 4<<1
+#define		AUTH_MSG_ERR_REPLY			 5<<1
+#define		AUTH_MSG_PRIVATE			 6<<1
+#define		AUTH_MSG_SAFE				 7<<1
+#define		AUTH_MSG_APPL_ERR			 8<<1
+#define 	AUTH_MSG_DIE				63<<1
+
+/* values for kerb error codes */
+
+#define		KERB_ERR_OK				 0
+#define		KERB_ERR_NAME_EXP			 1
+#define		KERB_ERR_SERVICE_EXP			 2
+#define		KERB_ERR_AUTH_EXP			 3
+#define		KERB_ERR_PKT_VER			 4
+#define		KERB_ERR_NAME_MAST_KEY_VER		 5
+#define		KERB_ERR_SERV_MAST_KEY_VER		 6
+#define		KERB_ERR_BYTE_ORDER			 7
+#define		KERB_ERR_PRINCIPAL_UNKNOWN		 8
+#define		KERB_ERR_PRINCIPAL_NOT_UNIQUE		 9
+#define		KERB_ERR_NULL_KEY			10
+/* Cygnus extensions for Preauthentication */
+#define         KERB_ERR_PREAUTH_SHORT			11
+#define		KERB_ERR_PREAUTH_MISMATCH		12
+
+/* Return codes from krb4prot_ encoders/decoders */
+
+#define		KRB4PROT_OK				0
+#define		KRB4PROT_ERR_UNDERRUN			1
+#define		KRB4PROT_ERR_OVERRUN			2
+#define		KRB4PROT_ERR_PROT_VERS			3
+#define		KRB4PROT_ERR_MSG_TYPE			4
+#define		KRB4PROT_ERR_GENERIC			255
+
+#endif /* PROT_DEFS */
diff --git a/krb5-1-6/src/include/krb5.h b/krb5-1-6/src/include/krb5.h
new file mode 100644
index 000000000..d68965155
--- /dev/null
+++ b/krb5-1-6/src/include/krb5.h
@@ -0,0 +1,7 @@
+/* The MIT Kerberos header file krb5.h used to live here.
+
+   As of the 1.5 release, we're installing multiple Kerberos headers,
+   so they're all moving to a krb5/ subdirectory.  This file is
+   present just to keep old software still compiling.  Please update
+   your code to use the new path for the header.  */
+#include <krb5/krb5.h>
diff --git a/krb5-1-6/src/include/krb5/krb5.hin b/krb5-1-6/src/include/krb5/krb5.hin
new file mode 100644
index 000000000..dd6ab9e0e
--- /dev/null
+++ b/krb5-1-6/src/include/krb5/krb5.hin
@@ -0,0 +1,2692 @@
+/*
+ * include/krb5.h
+ *
+ * Copyright 1989,1990,1995,2001, 2003  by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.	Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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__
+
+/* By default, do not expose deprecated interfaces. */
+#ifndef KRB5_DEPRECATED
+#define KRB5_DEPRECATED 0
+#endif
+/* Do not expose private interfaces.  Build system will override. */
+#ifndef KRB5_PRIVATE
+#define KRB5_PRIVATE 0
+#endif
+
+#if defined(__MACH__) && defined(__APPLE__)
+#	include <TargetConditionals.h>
+#    if TARGET_RT_MAC_CFM
+#	error "Use KfM 4.0 SDK headers for CFM compilation."
+#    endif
+#endif
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include <win-mac.h>
+#endif
+
+#ifndef KRB5_CONFIG__
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif /* !KRB5_CALLCONV */
+#endif /* !KRB5_CONFIG__ */
+
+#ifndef KRB5_CALLCONV_WRONG
+#define KRB5_CALLCONV_WRONG
+#endif
+
+#ifndef THREEPARAMOPEN
+#define THREEPARAMOPEN(x,y,z) open(x,y,z)
+#endif
+
+#define KRB5_OLD_CRYPTO
+
+#include <stdlib.h>
+#include <limits.h>		/* for *_MAX */
+
+#ifndef KRB5INT_BEGIN_DECLS
+#if defined(__cplusplus)
+#define KRB5INT_BEGIN_DECLS	extern "C" {
+#define KRB5INT_END_DECLS	}
+#else
+#define KRB5INT_BEGIN_DECLS
+#define KRB5INT_END_DECLS
+#endif
+#endif
+
+KRB5INT_BEGIN_DECLS
+
+#if TARGET_OS_MAC
+#    pragma pack(push,2)
+#endif
+
+/* from profile.h */
+struct _profile_t;
+/* typedef struct _profile_t *profile_t; */
+
+/*
+ * begin wordsize.h
+ */
+
+/*
+ * Word-size related definition.
+ */
+
+typedef	unsigned char	krb5_octet;
+
+#if INT_MAX == 0x7fff
+typedef	int	krb5_int16;
+typedef	unsigned int	krb5_ui_2;
+#elif SHRT_MAX == 0x7fff
+typedef	short	krb5_int16;
+typedef	unsigned short	krb5_ui_2;
+#else
+#error undefined 16 bit type
+#endif
+
+#if INT_MAX == 0x7fffffffL
+typedef	int	krb5_int32;
+typedef	unsigned int	krb5_ui_4;
+#elif LONG_MAX == 0x7fffffffL
+typedef	long	krb5_int32;
+typedef	unsigned long	krb5_ui_4;
+#elif SHRT_MAX == 0x7fffffffL
+typedef	short	krb5_int32;
+typedef	unsigned short	krb5_ui_4;
+#else
+#error: undefined 32 bit type
+#endif
+
+#define VALID_INT_BITS	  INT_MAX
+#define VALID_UINT_BITS	  UINT_MAX
+
+#define KRB5_INT32_MAX	2147483647
+/* this strange form is necessary since - is a unary operator, not a sign
+   indicator */
+#define KRB5_INT32_MIN	(-KRB5_INT32_MAX-1)
+
+#define KRB5_INT16_MAX 65535	
+/* this strange form is necessary since - is a unary operator, not a sign
+   indicator */
+#define KRB5_INT16_MIN	(-KRB5_INT16_MAX-1)
+
+/*
+ * end wordsize.h
+ */
+
+/*
+ * begin "base-defs.h"
+ */
+
+/*
+ * Basic definitions for Kerberos V5 library
+ */
+
+#ifndef FALSE
+#define	FALSE	0
+#endif
+#ifndef TRUE
+#define	TRUE	1
+#endif
+
+typedef	unsigned int krb5_boolean;
+typedef	unsigned int krb5_msgtype;	
+typedef	unsigned int krb5_kvno;	
+
+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;
+typedef krb5_int32	krb5_timestamp;
+typedef	krb5_int32	krb5_error_code;
+typedef krb5_int32	krb5_deltat;
+
+typedef krb5_error_code	krb5_magic;
+
+typedef struct _krb5_data {
+	krb5_magic magic;
+	unsigned int length;
+	char *data;
+} krb5_data;
+
+typedef struct _krb5_octet_data {
+	krb5_magic magic;
+	unsigned int length;
+	krb5_octet *data;
+} krb5_octet_data;
+
+/* 
+ * Hack length for crypto library to use the afs_string_to_key It is
+ * equivalent to -1 without possible sign extension 
+ * We also overload for an unset salt type length - which is also -1, but
+ * hey, why not....
+*/
+#define SALT_TYPE_AFS_LENGTH UINT_MAX
+#define SALT_TYPE_NO_LENGTH  UINT_MAX
+
+typedef	void * krb5_pointer;
+typedef void const * krb5_const_pointer;
+
+typedef struct krb5_principal_data {
+    krb5_magic magic;
+    krb5_data realm;
+    krb5_data *data;		/* An array of strings */
+    krb5_int32 length;
+    krb5_int32 type;
+} krb5_principal_data;
+
+typedef	krb5_principal_data * krb5_principal;
+
+/*
+ * Per V5 spec on definition of principal types
+ */
+
+/* Name type not known */
+#define KRB5_NT_UNKNOWN		0
+/* Just the name of the principal as in DCE, or for users */
+#define KRB5_NT_PRINCIPAL	1
+/* Service and other unique instance (krbtgt) */
+#define KRB5_NT_SRV_INST	2
+/* Service with host name as instance (telnet, rcommands) */
+#define KRB5_NT_SRV_HST		3
+/* Service with host as remaining components */
+#define KRB5_NT_SRV_XHST	4
+/* Unique ID */
+#define KRB5_NT_UID		5
+
+/* constant version thereof: */
+typedef const krb5_principal_data *krb5_const_principal;
+
+#define krb5_princ_realm(context, princ) (&(princ)->realm)
+#define krb5_princ_set_realm(context, princ,value) ((princ)->realm = *(value))
+#define krb5_princ_set_realm_length(context, princ,value) (princ)->realm.length = (value)
+#define krb5_princ_set_realm_data(context, princ,value) (princ)->realm.data = (value)
+#define	krb5_princ_size(context, princ) (princ)->length
+#define	krb5_princ_type(context, princ) (princ)->type
+#define	krb5_princ_name(context, princ) (princ)->data
+#define	krb5_princ_component(context, princ,i)		\
+	    (((i) < krb5_princ_size(context, princ))	\
+	     ? (princ)->data + (i)			\
+	     : NULL)
+
+/*
+ * Constants for realm referrals.
+ */
+#define        KRB5_REFERRAL_REALM	""
+
+/*
+ * Referral-specific functions.
+ */
+krb5_boolean KRB5_CALLCONV krb5_is_referral_realm(const krb5_data *);
+
+/*
+ * end "base-defs.h"
+ */
+
+/*
+ * begin "hostaddr.h"
+ */
+
+/* structure for address */
+typedef struct _krb5_address {
+    krb5_magic magic;
+    krb5_addrtype addrtype;
+    unsigned int length;
+    krb5_octet *contents;
+} krb5_address;
+
+/* per Kerberos v5 protocol spec */
+#define	ADDRTYPE_INET		0x0002
+#define	ADDRTYPE_CHAOS		0x0005
+#define	ADDRTYPE_XNS		0x0006
+#define	ADDRTYPE_ISO		0x0007
+#define ADDRTYPE_DDP		0x0010
+#define ADDRTYPE_INET6		0x0018
+/* not yet in the spec... */
+#define ADDRTYPE_ADDRPORT	0x0100
+#define ADDRTYPE_IPPORT		0x0101
+
+/* macros to determine if a type is a local type */
+#define ADDRTYPE_IS_LOCAL(addrtype) (addrtype & 0x8000)
+
+/*
+ * end "hostaddr.h"
+ */
+
+
+struct _krb5_context;
+typedef struct _krb5_context * krb5_context;
+
+struct _krb5_auth_context;
+typedef struct _krb5_auth_context * krb5_auth_context;
+
+struct _krb5_cryptosystem_entry;
+
+/*
+ * begin "encryption.h"
+ */
+
+typedef struct _krb5_keyblock {
+    krb5_magic magic;
+    krb5_enctype enctype;
+    unsigned int length;
+    krb5_octet *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 *key;
+} krb5_encrypt_block;
+#endif
+
+typedef struct _krb5_checksum {
+    krb5_magic magic;
+    krb5_cksumtype checksum_type;	/* checksum type */
+    unsigned int length;
+    krb5_octet *contents;
+} krb5_checksum;
+
+typedef struct _krb5_enc_data {
+    krb5_magic magic;
+    krb5_enctype enctype;
+    krb5_kvno kvno;
+    krb5_data ciphertext;
+} krb5_enc_data;
+
+/* per Kerberos v5 protocol spec */
+#define	ENCTYPE_NULL		0x0000
+#define	ENCTYPE_DES_CBC_CRC	0x0001	/* DES cbc mode with CRC-32 */
+#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_DES_HMAC_SHA1	0x0008
+#define ENCTYPE_DES3_CBC_SHA1	0x0010
+#define ENCTYPE_AES128_CTS_HMAC_SHA1_96	0x0011
+#define ENCTYPE_AES256_CTS_HMAC_SHA1_96	0x0012
+#define ENCTYPE_ARCFOUR_HMAC	0x0017
+#define ENCTYPE_ARCFOUR_HMAC_EXP 0x0018
+#define ENCTYPE_UNKNOWN		0x01ff
+
+#define	CKSUMTYPE_CRC32		0x0001
+#define	CKSUMTYPE_RSA_MD4	0x0002
+#define	CKSUMTYPE_RSA_MD4_DES	0x0003
+#define	CKSUMTYPE_DESCBC	0x0004
+/* des-mac-k */
+/* rsa-md4-des-k */
+#define	CKSUMTYPE_RSA_MD5	0x0007
+#define	CKSUMTYPE_RSA_MD5_DES	0x0008
+#define CKSUMTYPE_NIST_SHA	0x0009
+#define CKSUMTYPE_HMAC_SHA1_DES3	0x000c
+#define CKSUMTYPE_HMAC_SHA1_96_AES128	0x000f
+#define CKSUMTYPE_HMAC_SHA1_96_AES256	0x0010
+#define CKSUMTYPE_HMAC_MD5_ARCFOUR -138 /*Microsoft md5 hmac cksumtype*/
+
+/* The following are entropy source designations. Whenever
+ * krb5_C_random_add_entropy is called, one of these source  ids is passed
+ * in.  This  allows the library  to better estimate bits of
+ * entropy in the sample and to keep track of what sources of entropy have
+ * contributed enough entropy.  Sources marked internal MUST NOT be
+ * used by applications outside the Kerberos library
+*/
+
+enum {
+  KRB5_C_RANDSOURCE_OLDAPI = 0, /*calls to krb5_C_RANDOM_SEED (INTERNAL)*/
+  KRB5_C_RANDSOURCE_OSRAND = 1, /* /dev/random or equivalent (internal)*/
+  KRB5_C_RANDSOURCE_TRUSTEDPARTY = 2, /* From KDC or other trusted party*/
+  /*This source should be used carefully; data in this category
+   * should be from a third party trusted to give random bits
+   * For example keys issued by the KDC in the application server.
+   */
+  KRB5_C_RANDSOURCE_TIMING = 3, /* Timing of operations*/
+  KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL = 4, /*Protocol data possibly from attacker*/
+  KRB5_C_RANDSOURCE_MAX = 5 /*Do not use; maximum source ID*/
+};
+
+#ifndef krb5_roundup
+/* round x up to nearest multiple of y */
+#define krb5_roundup(x, y) ((((x) + (y) - 1)/(y))*(y))
+#endif /* roundup */
+
+/* macro function definitions to help clean up code */
+
+#if 1
+#define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1))
+#define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0))
+#else
+#define krb5_x(ptr,args) ((*(ptr)) args)
+#define krb5_xc(ptr,args) ((*(ptr)) args)
+#endif
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_encrypt
+    (krb5_context context, const krb5_keyblock *key,
+		    krb5_keyusage usage, const krb5_data *cipher_state,
+		    const krb5_data *input, krb5_enc_data *output);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_decrypt
+    (krb5_context context, const krb5_keyblock *key,
+		    krb5_keyusage usage, const krb5_data *cipher_state,
+		    const krb5_enc_data *input, krb5_data *output);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_encrypt_length
+    (krb5_context context, krb5_enctype enctype,
+		    size_t inputlen, size_t *length);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_block_size
+    (krb5_context context, krb5_enctype enctype,
+		    size_t *blocksize);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_keylengths
+    (krb5_context context, krb5_enctype enctype,
+		    size_t *keybytes, size_t *keylength);
+
+krb5_error_code KRB5_CALLCONV
+	krb5_c_init_state
+(krb5_context context,
+const krb5_keyblock *key, krb5_keyusage usage,
+krb5_data *new_state);
+
+krb5_error_code KRB5_CALLCONV
+	krb5_c_free_state
+(krb5_context context, const krb5_keyblock *key, krb5_data *state);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_prf (krb5_context, const krb5_keyblock *,
+		krb5_data *in, krb5_data *out);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_prf_length (krb5_context, krb5_enctype, size_t *outlen);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_make_random_key
+    (krb5_context context, krb5_enctype enctype,
+		    krb5_keyblock *k5_random_key);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_random_to_key
+    (krb5_context context, krb5_enctype enctype,
+		    krb5_data *random_data, krb5_keyblock *k5_random_key);
+
+/* Register a new entropy sample  with the PRNG. may cause
+* the PRNG to be reseeded, although this is not guaranteed.  See previous randsource definitions
+* for information on how each source should be used.
+*/
+krb5_error_code KRB5_CALLCONV
+	krb5_c_random_add_entropy
+(krb5_context context, unsigned int  randsource_id, const krb5_data *data);
+
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_random_make_octets
+    (krb5_context context, krb5_data *data);
+
+/*
+* Collect entropy from the OS if possible. strong requests that as strong 
+* of a source of entropy  as available be used.  Setting strong may 
+* increase the probability of blocking and should not  be used for normal 
+* applications.  Good uses include seeding the PRNG for kadmind
+* and realm setup.
+* If successful is non-null, then successful is set to 1 if the OS provided
+* entropy else zero.
+*/
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_os_entropy
+(krb5_context context, int strong, int *success);
+
+/*deprecated*/ krb5_error_code KRB5_CALLCONV
+    krb5_c_random_seed
+    (krb5_context context, krb5_data *data);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_string_to_key
+    (krb5_context context, krb5_enctype enctype,
+		    const krb5_data *string, const krb5_data *salt,
+		    krb5_keyblock *key);
+krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key_with_params(krb5_context context,
+				 krb5_enctype enctype,
+				 const krb5_data *string,
+				 const krb5_data *salt,
+				 const krb5_data *params,
+				 krb5_keyblock *key);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_enctype_compare
+    (krb5_context context, krb5_enctype e1, krb5_enctype e2,
+		    krb5_boolean *similar);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_make_checksum
+    (krb5_context context, krb5_cksumtype cksumtype,
+		    const krb5_keyblock *key, krb5_keyusage usage,
+		    const krb5_data *input, krb5_checksum *cksum);
+    
+krb5_error_code KRB5_CALLCONV
+    krb5_c_verify_checksum
+    (krb5_context context, 
+		    const krb5_keyblock *key, krb5_keyusage usage,
+		    const krb5_data *data,
+		    const krb5_checksum *cksum,
+		    krb5_boolean *valid);
+    
+krb5_error_code KRB5_CALLCONV
+    krb5_c_checksum_length
+    (krb5_context context, krb5_cksumtype cksumtype,
+		    size_t *length);
+
+krb5_error_code KRB5_CALLCONV
+    krb5_c_keyed_checksum_types
+    (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
+
+/* Defined in hardware preauth draft */
+
+#define KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM	25
+#define KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID	26
+#define KRB5_KEYUSAGE_PA_SAM_RESPONSE		27
+
+/* Defined in KDC referrals draft */
+#define KRB5_KEYUSAGE_PA_REFERRAL		26 /* XXX note conflict with above */
+
+krb5_boolean KRB5_CALLCONV krb5_c_valid_enctype
+	(krb5_enctype ktype);
+krb5_boolean KRB5_CALLCONV krb5_c_valid_cksumtype
+	(krb5_cksumtype ctype);
+krb5_boolean KRB5_CALLCONV krb5_c_is_coll_proof_cksum
+	(krb5_cksumtype ctype);
+krb5_boolean KRB5_CALLCONV krb5_c_is_keyed_cksum
+	(krb5_cksumtype ctype);
+
+#if KRB5_PRIVATE
+/* Use the above four instead.  */
+krb5_boolean KRB5_CALLCONV valid_enctype
+	(krb5_enctype ktype);
+krb5_boolean KRB5_CALLCONV valid_cksumtype
+	(krb5_cksumtype ctype);
+krb5_boolean KRB5_CALLCONV is_coll_proof_cksum
+	(krb5_cksumtype ctype);
+krb5_boolean KRB5_CALLCONV is_keyed_cksum
+	(krb5_cksumtype ctype);
+#endif
+
+#ifdef KRB5_OLD_CRYPTO
+/*
+ * old cryptosystem routine prototypes.  These are now layered
+ * on top of the functions above.
+ */
+krb5_error_code KRB5_CALLCONV krb5_encrypt
+	(krb5_context context,
+		krb5_const_pointer inptr,
+		krb5_pointer outptr,
+		size_t size,
+		krb5_encrypt_block * eblock,
+		krb5_pointer ivec);
+krb5_error_code KRB5_CALLCONV krb5_decrypt
+	(krb5_context context,
+		krb5_const_pointer inptr,
+		krb5_pointer outptr,
+		size_t size,
+		krb5_encrypt_block * eblock,
+		krb5_pointer ivec);
+krb5_error_code KRB5_CALLCONV krb5_process_key
+	(krb5_context context,
+		krb5_encrypt_block * eblock,
+		const krb5_keyblock * key);
+krb5_error_code KRB5_CALLCONV krb5_finish_key
+	(krb5_context context,
+		krb5_encrypt_block * eblock);
+krb5_error_code KRB5_CALLCONV krb5_string_to_key
+	(krb5_context context,
+		const krb5_encrypt_block * eblock,
+		krb5_keyblock * keyblock,
+		const krb5_data * data,
+		const krb5_data * salt);
+krb5_error_code KRB5_CALLCONV krb5_init_random_key
+	(krb5_context context,
+		const krb5_encrypt_block * eblock,
+		const krb5_keyblock * keyblock,
+		krb5_pointer * ptr);
+krb5_error_code KRB5_CALLCONV krb5_finish_random_key
+	(krb5_context context,
+		const krb5_encrypt_block * eblock,
+		krb5_pointer * ptr);
+krb5_error_code KRB5_CALLCONV krb5_random_key
+	(krb5_context context,
+		const krb5_encrypt_block * eblock,
+		krb5_pointer ptr,
+		krb5_keyblock ** keyblock);
+krb5_enctype KRB5_CALLCONV krb5_eblock_enctype
+	(krb5_context context,
+		const krb5_encrypt_block * eblock);
+krb5_error_code KRB5_CALLCONV krb5_use_enctype
+	(krb5_context context,
+		krb5_encrypt_block * eblock,
+		krb5_enctype enctype);
+size_t KRB5_CALLCONV krb5_encrypt_size
+	(size_t length,
+		krb5_enctype crypto);
+size_t KRB5_CALLCONV krb5_checksum_size
+	(krb5_context context,
+		krb5_cksumtype ctype);
+krb5_error_code KRB5_CALLCONV krb5_calculate_checksum
+	(krb5_context context,
+		krb5_cksumtype ctype,
+		krb5_const_pointer in, size_t in_length,
+		krb5_const_pointer seed, size_t seed_length,
+		krb5_checksum * outcksum);
+krb5_error_code KRB5_CALLCONV krb5_verify_checksum
+	(krb5_context context,
+		krb5_cksumtype ctype,
+		const krb5_checksum * cksum,
+		krb5_const_pointer in, size_t in_length,
+		krb5_const_pointer seed, size_t seed_length);
+
+#if KRB5_PRIVATE
+krb5_error_code KRB5_CALLCONV krb5_random_confounder
+	(size_t, krb5_pointer);
+
+krb5_error_code krb5_encrypt_data
+	(krb5_context context, krb5_keyblock *key, 
+		krb5_pointer ivec, krb5_data *data, 
+		krb5_enc_data *enc_data);
+
+krb5_error_code krb5_decrypt_data
+	(krb5_context context, krb5_keyblock *key, 
+		krb5_pointer ivec, krb5_enc_data *data, 
+		krb5_data *enc_data);
+#endif
+
+#endif /* KRB5_OLD_CRYPTO */
+
+/*
+ * end "encryption.h"
+ */
+
+/*
+ * begin "fieldbits.h"
+ */
+
+/* kdc_options for kdc_request */
+/* options is 32 bits; each host is responsible to put the 4 bytes
+   representing these bits into net order before transmission */
+/* #define	KDC_OPT_RESERVED	0x80000000 */
+#define	KDC_OPT_FORWARDABLE		0x40000000
+#define	KDC_OPT_FORWARDED		0x20000000
+#define	KDC_OPT_PROXIABLE		0x10000000
+#define	KDC_OPT_PROXY			0x08000000
+#define	KDC_OPT_ALLOW_POSTDATE		0x04000000
+#define	KDC_OPT_POSTDATED		0x02000000
+/* #define	KDC_OPT_UNUSED		0x01000000 */
+#define	KDC_OPT_RENEWABLE		0x00800000
+/* #define	KDC_OPT_UNUSED		0x00400000 */
+/* #define	KDC_OPT_RESERVED	0x00200000 */
+/* #define	KDC_OPT_RESERVED	0x00100000 */
+/* #define	KDC_OPT_RESERVED	0x00080000 */
+/* #define	KDC_OPT_RESERVED	0x00040000 */
+#define	KDC_OPT_REQUEST_ANONYMOUS	0x00020000
+#define	KDC_OPT_CANONICALIZE		0x00010000
+/* #define	KDC_OPT_RESERVED	0x00008000 */
+/* #define	KDC_OPT_RESERVED	0x00004000 */
+/* #define	KDC_OPT_RESERVED	0x00002000 */
+/* #define	KDC_OPT_RESERVED	0x00001000 */
+/* #define	KDC_OPT_RESERVED	0x00000800 */
+/* #define	KDC_OPT_RESERVED	0x00000400 */
+/* #define	KDC_OPT_RESERVED	0x00000200 */
+/* #define	KDC_OPT_RESERVED	0x00000100 */
+/* #define	KDC_OPT_RESERVED	0x00000080 */
+/* #define	KDC_OPT_RESERVED	0x00000040 */
+#define	KDC_OPT_DISABLE_TRANSITED_CHECK	0x00000020
+#define	KDC_OPT_RENEWABLE_OK		0x00000010
+#define	KDC_OPT_ENC_TKT_IN_SKEY		0x00000008
+/* #define	KDC_OPT_UNUSED		0x00000004 */
+#define	KDC_OPT_RENEW			0x00000002
+#define	KDC_OPT_VALIDATE		0x00000001
+
+/*
+ * Mask of ticket flags in the TGT which should be converted into KDC
+ * options when using the TGT to get derivitive tickets.
+ * 
+ *  New mask = KDC_OPT_FORWARDABLE | KDC_OPT_PROXIABLE |
+ *	       KDC_OPT_ALLOW_POSTDATE | KDC_OPT_RENEWABLE
+ */
+#define KDC_TKT_COMMON_MASK		0x54800000
+
+/* definitions for ap_options fields */
+/* ap_options are 32 bits; each host is responsible to put the 4 bytes
+   representing these bits into net order before transmission */
+#define	AP_OPTS_RESERVED		0x80000000
+#define	AP_OPTS_USE_SESSION_KEY		0x40000000
+#define	AP_OPTS_MUTUAL_REQUIRED		0x20000000
+/* #define	AP_OPTS_RESERVED	0x10000000 */
+/* #define	AP_OPTS_RESERVED	0x08000000 */
+/* #define	AP_OPTS_RESERVED	0x04000000 */
+/* #define	AP_OPTS_RESERVED	0x02000000 */
+/* #define	AP_OPTS_RESERVED	0x01000000 */
+/* #define	AP_OPTS_RESERVED	0x00800000 */
+/* #define	AP_OPTS_RESERVED	0x00400000 */
+/* #define	AP_OPTS_RESERVED	0x00200000 */
+/* #define	AP_OPTS_RESERVED	0x00100000 */
+/* #define	AP_OPTS_RESERVED	0x00080000 */
+/* #define	AP_OPTS_RESERVED	0x00040000 */
+/* #define	AP_OPTS_RESERVED	0x00020000 */
+/* #define	AP_OPTS_RESERVED	0x00010000 */
+/* #define	AP_OPTS_RESERVED	0x00008000 */
+/* #define	AP_OPTS_RESERVED	0x00004000 */
+/* #define	AP_OPTS_RESERVED	0x00002000 */
+/* #define	AP_OPTS_RESERVED	0x00001000 */
+/* #define	AP_OPTS_RESERVED	0x00000800 */
+/* #define	AP_OPTS_RESERVED	0x00000400 */
+/* #define	AP_OPTS_RESERVED	0x00000200 */
+/* #define	AP_OPTS_RESERVED	0x00000100 */
+/* #define	AP_OPTS_RESERVED	0x00000080 */
+/* #define	AP_OPTS_RESERVED	0x00000040 */
+/* #define	AP_OPTS_RESERVED	0x00000020 */
+/* #define	AP_OPTS_RESERVED	0x00000010 */
+/* #define	AP_OPTS_RESERVED	0x00000008 */
+/* #define	AP_OPTS_RESERVED	0x00000004 */
+/* #define	AP_OPTS_RESERVED	0x00000002 */
+#define AP_OPTS_USE_SUBKEY	0x00000001
+
+#define AP_OPTS_WIRE_MASK	0xfffffff0
+
+/* definitions for ad_type fields. */
+#define	AD_TYPE_RESERVED	0x8000
+#define	AD_TYPE_EXTERNAL	0x4000
+#define	AD_TYPE_REGISTERED	0x2000
+
+#define AD_TYPE_FIELD_TYPE_MASK	0x1fff
+
+/* Ticket flags */
+/* flags are 32 bits; each host is responsible to put the 4 bytes
+   representing these bits into net order before transmission */
+/* #define	TKT_FLG_RESERVED	0x80000000 */
+#define	TKT_FLG_FORWARDABLE		0x40000000
+#define	TKT_FLG_FORWARDED		0x20000000
+#define	TKT_FLG_PROXIABLE		0x10000000
+#define	TKT_FLG_PROXY			0x08000000
+#define	TKT_FLG_MAY_POSTDATE		0x04000000
+#define	TKT_FLG_POSTDATED		0x02000000
+#define	TKT_FLG_INVALID			0x01000000
+#define	TKT_FLG_RENEWABLE		0x00800000
+#define	TKT_FLG_INITIAL			0x00400000
+#define	TKT_FLG_PRE_AUTH		0x00200000
+#define	TKT_FLG_HW_AUTH			0x00100000
+#define	TKT_FLG_TRANSIT_POLICY_CHECKED	0x00080000
+#define	TKT_FLG_OK_AS_DELEGATE		0x00040000
+#define	TKT_FLG_ANONYMOUS		0x00020000
+/* #define	TKT_FLG_RESERVED	0x00010000 */
+/* #define	TKT_FLG_RESERVED	0x00008000 */
+/* #define	TKT_FLG_RESERVED	0x00004000 */
+/* #define	TKT_FLG_RESERVED	0x00002000 */
+/* #define	TKT_FLG_RESERVED	0x00001000 */
+/* #define	TKT_FLG_RESERVED	0x00000800 */
+/* #define	TKT_FLG_RESERVED	0x00000400 */
+/* #define	TKT_FLG_RESERVED	0x00000200 */
+/* #define	TKT_FLG_RESERVED	0x00000100 */
+/* #define	TKT_FLG_RESERVED	0x00000080 */
+/* #define	TKT_FLG_RESERVED	0x00000040 */
+/* #define	TKT_FLG_RESERVED	0x00000020 */
+/* #define	TKT_FLG_RESERVED	0x00000010 */
+/* #define	TKT_FLG_RESERVED	0x00000008 */
+/* #define	TKT_FLG_RESERVED	0x00000004 */
+/* #define	TKT_FLG_RESERVED	0x00000002 */
+/* #define	TKT_FLG_RESERVED	0x00000001 */
+
+/* definitions for lr_type fields. */
+#define	LR_TYPE_THIS_SERVER_ONLY	0x8000
+
+#define LR_TYPE_INTERPRETATION_MASK	0x7fff
+
+/* definitions for ad_type fields. */
+#define	AD_TYPE_EXTERNAL	0x4000
+#define	AD_TYPE_REGISTERED	0x2000
+
+#define AD_TYPE_FIELD_TYPE_MASK	0x1fff
+#define AD_TYPE_INTERNAL_MASK	0x3fff
+
+/* definitions for msec direction bit for KRB_SAFE, KRB_PRIV */
+#define	MSEC_DIRBIT		0x8000
+#define	MSEC_VAL_MASK		0x7fff
+
+/*
+ * end "fieldbits.h"
+ */
+
+/*
+ * begin "proto.h"
+ */
+
+/* Protocol version number */
+#define	KRB5_PVNO	5
+
+/* Message types */
+
+#define	KRB5_AS_REQ	((krb5_msgtype)10) /* Req for initial authentication */
+#define	KRB5_AS_REP	((krb5_msgtype)11) /* Response to KRB_AS_REQ request */
+#define	KRB5_TGS_REQ	((krb5_msgtype)12) /* TGS request to server */
+#define	KRB5_TGS_REP	((krb5_msgtype)13) /* Response to KRB_TGS_REQ req */
+#define	KRB5_AP_REQ	((krb5_msgtype)14) /* application request to server */
+#define	KRB5_AP_REP	((krb5_msgtype)15) /* Response to KRB_AP_REQ_MUTUAL */
+#define	KRB5_SAFE	((krb5_msgtype)20) /* Safe application message */
+#define	KRB5_PRIV	((krb5_msgtype)21) /* Private application message */
+#define	KRB5_CRED	((krb5_msgtype)22) /* Credential forwarding message */
+#define	KRB5_ERROR	((krb5_msgtype)30) /* Error response */
+
+/* LastReq types */
+#define KRB5_LRQ_NONE			0
+#define KRB5_LRQ_ALL_LAST_TGT		1
+#define KRB5_LRQ_ONE_LAST_TGT		(-1)
+#define KRB5_LRQ_ALL_LAST_INITIAL	2
+#define KRB5_LRQ_ONE_LAST_INITIAL	(-2)
+#define KRB5_LRQ_ALL_LAST_TGT_ISSUED	3
+#define KRB5_LRQ_ONE_LAST_TGT_ISSUED	(-3)
+#define KRB5_LRQ_ALL_LAST_RENEWAL	4
+#define KRB5_LRQ_ONE_LAST_RENEWAL	(-4)
+#define KRB5_LRQ_ALL_LAST_REQ		5
+#define KRB5_LRQ_ONE_LAST_REQ		(-5)
+#define KRB5_LRQ_ALL_PW_EXPTIME		6
+#define KRB5_LRQ_ONE_PW_EXPTIME		(-6)
+
+/* PADATA types */
+#define KRB5_PADATA_NONE		0
+#define	KRB5_PADATA_AP_REQ		1
+#define	KRB5_PADATA_TGS_REQ		KRB5_PADATA_AP_REQ
+#define KRB5_PADATA_ENC_TIMESTAMP	2
+#define	KRB5_PADATA_PW_SALT		3
+#if 0				/* Not used */
+#define KRB5_PADATA_ENC_ENCKEY		4  /* Key encrypted within itself */
+#endif
+#define KRB5_PADATA_ENC_UNIX_TIME	5  /* timestamp encrypted in key */
+#define KRB5_PADATA_ENC_SANDIA_SECURID	6  /* SecurId passcode */
+#define KRB5_PADATA_SESAME		7  /* Sesame project */
+#define KRB5_PADATA_OSF_DCE		8  /* OSF DCE */
+#define KRB5_CYBERSAFE_SECUREID		9  /* Cybersafe */
+#define	KRB5_PADATA_AFS3_SALT		10 /* Cygnus */
+#define KRB5_PADATA_ETYPE_INFO		11 /* Etype info for preauth */
+#define KRB5_PADATA_SAM_CHALLENGE	12 /* draft challenge system */
+#define KRB5_PADATA_SAM_RESPONSE	13 /* draft challenge system response */
+#define KRB5_PADATA_PK_AS_REQ_OLD	14 /* PKINIT */
+#define KRB5_PADATA_PK_AS_REP_OLD	15 /* PKINIT */
+#define KRB5_PADATA_PK_AS_REQ		16 /* PKINIT */
+#define KRB5_PADATA_PK_AS_REP		17 /* PKINIT */
+#define KRB5_PADATA_ETYPE_INFO2		19
+#define KRB5_PADATA_USE_SPECIFIED_KVNO	20
+#define KRB5_PADATA_SAM_REDIRECT	21
+#define KRB5_PADATA_GET_FROM_TYPED_DATA	22
+#define KRB5_PADATA_REFERRAL		25 /* draft referral system */
+#define KRB5_PADATA_SAM_CHALLENGE_2	30 /* draft challenge system, updated */
+#define KRB5_PADATA_SAM_RESPONSE_2	31 /* draft challenge system, updated */
+    
+#define	KRB5_SAM_USE_SAD_AS_KEY		0x80000000
+#define	KRB5_SAM_SEND_ENCRYPTED_SAD	0x40000000
+#define	KRB5_SAM_MUST_PK_ENCRYPT_SAD	0x20000000 /* currently must be zero */
+
+/* Reserved for SPX pre-authentication. */
+#define KRB5_PADATA_DASS		16
+
+/* Transited encoding types */
+#define	KRB5_DOMAIN_X500_COMPRESS	1
+
+/* alternate authentication types */
+#define	KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE	64
+
+/* authorization data types */
+#define KRB5_AUTHDATA_IF_RELEVANT   1
+#define KRB5_AUTHDATA_KDC_ISSUED    4
+#define KRB5_AUTHDATA_AND_OR	    5
+#define KRB5_AUTHDATA_MANDATORY_FOR_KDC	8
+#define KRB5_AUTHDATA_INITIAL_VERIFIED_CAS	9
+#define	KRB5_AUTHDATA_OSF_DCE	64
+#define KRB5_AUTHDATA_SESAME	65
+
+/* password change constants */
+
+#define KRB5_KPASSWD_SUCCESS		0
+#define KRB5_KPASSWD_MALFORMED		1
+#define KRB5_KPASSWD_HARDERROR		2
+#define KRB5_KPASSWD_AUTHERROR		3
+#define KRB5_KPASSWD_SOFTERROR		4
+/* These are Microsoft's extensions in RFC 3244, and it looks like
+   they'll become standardized, possibly with other additions.  */
+#define KRB5_KPASSWD_ACCESSDENIED	5	/* unused */
+#define KRB5_KPASSWD_BAD_VERSION	6
+#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7	/* unused */
+
+/*
+ * end "proto.h"
+ */
+
+/* Time set */
+typedef struct _krb5_ticket_times {
+    krb5_timestamp authtime; /* XXX ? should ktime in KDC_REP == authtime
+				in ticket? otherwise client can't get this */ 
+    krb5_timestamp starttime;		/* optional in ticket, if not present,
+					   use authtime */
+    krb5_timestamp endtime;
+    krb5_timestamp renew_till;
+} krb5_ticket_times;
+
+/* structure for auth data */
+typedef struct _krb5_authdata {
+    krb5_magic magic;
+    krb5_authdatatype ad_type;
+    unsigned int length;
+    krb5_octet *contents;
+} krb5_authdata;
+
+/* structure for transited encoding */
+typedef struct _krb5_transited {
+    krb5_magic magic;
+    krb5_octet tr_type;
+    krb5_data tr_contents;
+} krb5_transited;
+
+typedef struct _krb5_enc_tkt_part {
+    krb5_magic magic;
+    /* to-be-encrypted portion */
+    krb5_flags flags;			/* flags */
+    krb5_keyblock *session;		/* session key: includes enctype */
+    krb5_principal client;		/* client name/realm */
+    krb5_transited transited;		/* list of transited realms */
+    krb5_ticket_times times;		/* auth, start, end, renew_till */
+    krb5_address **caddrs;	/* array of ptrs to addresses */
+    krb5_authdata **authorization_data; /* auth data */
+} krb5_enc_tkt_part;
+
+typedef struct _krb5_ticket {
+    krb5_magic magic;
+    /* cleartext portion */
+    krb5_principal server;		/* server name/realm */
+    krb5_enc_data enc_part;		/* encryption type, kvno, encrypted
+					   encoding */
+    krb5_enc_tkt_part *enc_part2;	/* ptr to decrypted version, if
+					   available */
+} krb5_ticket;
+
+/* the unencrypted version */
+typedef struct _krb5_authenticator {
+    krb5_magic magic;
+    krb5_principal client;		/* client name/realm */
+    krb5_checksum *checksum;	/* checksum, includes type, optional */
+    krb5_int32 cusec;			/* client usec portion */
+    krb5_timestamp ctime;		/* client sec portion */
+    krb5_keyblock *subkey;		/* true session key, optional */
+    krb5_ui_4 seq_number;		/* sequence #, optional */
+    krb5_authdata **authorization_data; /* New add by Ari, auth data */
+} krb5_authenticator;
+
+typedef struct _krb5_tkt_authent {
+    krb5_magic magic;
+    krb5_ticket *ticket;
+    krb5_authenticator *authenticator;
+    krb5_flags ap_options;
+} krb5_tkt_authent;
+
+/* credentials:	 Ticket, session key, etc. */
+typedef struct _krb5_creds {
+    krb5_magic magic;
+    krb5_principal client;		/* client's principal identifier */
+    krb5_principal server;		/* server's principal identifier */
+    krb5_keyblock keyblock;		/* session encryption key info */
+    krb5_ticket_times times;		/* lifetime info */
+    krb5_boolean is_skey;		/* true if ticket is encrypted in
+					   another ticket's skey */
+    krb5_flags ticket_flags;		/* flags in ticket */
+    krb5_address **addresses;	/* addrs in ticket */
+    krb5_data ticket;			/* ticket string itself */
+    krb5_data second_ticket;		/* second ticket, if related to
+					   ticket (via DUPLICATE-SKEY or
+					   ENC-TKT-IN-SKEY) */
+    krb5_authdata **authdata;	/* authorization data */
+} krb5_creds;
+
+/* Last request fields */
+typedef struct _krb5_last_req_entry {
+    krb5_magic magic;
+    krb5_int32 lr_type;
+    krb5_timestamp value;
+} krb5_last_req_entry;
+
+/* pre-authentication data */
+typedef struct _krb5_pa_data {
+    krb5_magic magic;
+    krb5_preauthtype  pa_type;
+    unsigned int length;
+    krb5_octet *contents;
+} krb5_pa_data;
+
+typedef struct _krb5_kdc_req {
+    krb5_magic magic;
+    krb5_msgtype msg_type;		/* AS_REQ or TGS_REQ? */
+    krb5_pa_data **padata;	/* e.g. encoded AP_REQ */
+    /* real body */
+    krb5_flags kdc_options;		/* requested options */
+    krb5_principal client;		/* includes realm; optional */
+    krb5_principal server;		/* includes realm (only used if no
+					   client) */
+    krb5_timestamp from;		/* requested starttime */
+    krb5_timestamp till;		/* requested endtime */
+    krb5_timestamp rtime;		/* (optional) requested renew_till */
+    krb5_int32 nonce;			/* nonce to match request/response */
+    int nktypes;			/* # of ktypes, must be positive */
+    krb5_enctype *ktype;		/* requested enctype(s) */
+    krb5_address **addresses;	/* requested addresses, optional */
+    krb5_enc_data authorization_data;	/* encrypted auth data; OPTIONAL */
+    krb5_authdata **unenc_authdata; /* unencrypted auth data,
+					   if available */
+    krb5_ticket **second_ticket;/* second ticket array; OPTIONAL */
+} krb5_kdc_req;
+
+typedef struct _krb5_enc_kdc_rep_part {
+    krb5_magic magic;
+    /* encrypted part: */
+    krb5_msgtype msg_type;		/* krb5 message type */
+    krb5_keyblock *session;		/* session key */
+    krb5_last_req_entry **last_req; /* array of ptrs to entries */
+    krb5_int32 nonce;			/* nonce from request */
+    krb5_timestamp key_exp;		/* expiration date */
+    krb5_flags flags;			/* ticket flags */
+    krb5_ticket_times times;		/* lifetime info */
+    krb5_principal server;		/* server's principal identifier */
+    krb5_address **caddrs;	/* array of ptrs to addresses,
+					   optional */
+} krb5_enc_kdc_rep_part;
+
+typedef struct _krb5_kdc_rep {
+    krb5_magic magic;
+    /* cleartext part: */
+    krb5_msgtype msg_type;		/* AS_REP or KDC_REP? */
+    krb5_pa_data **padata;	/* preauthentication data from KDC */
+    krb5_principal client;		/* client's principal identifier */
+    krb5_ticket *ticket;		/* ticket */
+    krb5_enc_data enc_part;		/* encryption type, kvno, encrypted
+					   encoding */
+    krb5_enc_kdc_rep_part *enc_part2;/* unencrypted version, if available */
+} krb5_kdc_rep;
+
+/* error message structure */
+typedef struct _krb5_error {
+    krb5_magic magic;
+    /* some of these may be meaningless in certain contexts */
+    krb5_timestamp ctime;		/* client sec portion; optional */
+    krb5_int32 cusec;			/* client usec portion; optional */
+    krb5_int32 susec;			/* server usec portion */
+    krb5_timestamp stime;		/* server sec portion */
+    krb5_ui_4 error;			/* error code (protocol error #'s) */
+    krb5_principal client;		/* client's principal identifier;
+					   optional */
+    krb5_principal server;		/* server's principal identifier */
+    krb5_data text;			/* descriptive text */
+    krb5_data e_data;			/* additional error-describing data */
+} krb5_error;
+
+typedef struct _krb5_ap_req {
+    krb5_magic magic;
+    krb5_flags ap_options;		/* requested options */
+    krb5_ticket *ticket;		/* ticket */
+    krb5_enc_data authenticator;	/* authenticator (already encrypted) */
+} krb5_ap_req;
+
+typedef struct _krb5_ap_rep {
+    krb5_magic magic;
+    krb5_enc_data enc_part;
+} krb5_ap_rep;
+
+typedef struct _krb5_ap_rep_enc_part {
+    krb5_magic magic;
+    krb5_timestamp ctime;		/* client time, seconds portion */
+    krb5_int32 cusec;			/* client time, microseconds portion */
+    krb5_keyblock *subkey;		/* true session key, optional */
+    krb5_ui_4 seq_number;		/* sequence #, optional */
+} krb5_ap_rep_enc_part;
+
+typedef struct _krb5_response {
+    krb5_magic magic;
+    krb5_octet message_type;
+    krb5_data response;
+    krb5_int32 expected_nonce;	/* The expected nonce for KDC_REP messages */
+    krb5_timestamp request_time;   /* When we made the request */
+} krb5_response;
+
+typedef struct _krb5_cred_info {
+    krb5_magic magic;
+    krb5_keyblock *session;		/* session key used to encrypt */
+					/* ticket */
+    krb5_principal client;		/* client name/realm, optional */
+    krb5_principal server;		/* server name/realm, optional */
+    krb5_flags flags;			/* ticket flags, optional */
+    krb5_ticket_times times;		/* auth, start, end, renew_till, */
+					/* optional */
+    krb5_address **caddrs;	/* array of ptrs to addresses */
+} krb5_cred_info;
+
+typedef struct _krb5_cred_enc_part {
+    krb5_magic magic;
+    krb5_int32 nonce;			/* nonce, optional */
+    krb5_timestamp timestamp;		/* client time */
+    krb5_int32 usec;			/* microsecond portion of time */
+    krb5_address *s_address;	/* sender address, optional */
+    krb5_address *r_address;	/* recipient address, optional */
+    krb5_cred_info **ticket_info;
+} krb5_cred_enc_part;	 
+
+typedef struct _krb5_cred {
+    krb5_magic magic;
+    krb5_ticket **tickets;	/* tickets */
+    krb5_enc_data enc_part;		/* encrypted part */
+    krb5_cred_enc_part *enc_part2;	/* unencrypted version, if available*/
+} krb5_cred;
+
+/* Sandia password generation structures */
+typedef struct _passwd_phrase_element {
+    krb5_magic magic;
+    krb5_data *passwd;
+    krb5_data *phrase;
+} passwd_phrase_element;
+
+typedef struct _krb5_pwd_data {
+    krb5_magic magic;
+    int sequence_count;
+    passwd_phrase_element **element;
+} krb5_pwd_data;
+
+/* these need to be here so the typedefs are available for the prototypes */
+
+/*
+ * begin "safepriv.h"
+ */
+
+#define KRB5_AUTH_CONTEXT_DO_TIME	0x00000001
+#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
+#define KRB5_AUTH_CONTEXT_USE_SUBKEY	0x00000020
+ 
+typedef struct krb5_replay_data { 
+    krb5_timestamp	timestamp; 
+    krb5_int32		usec;
+    krb5_ui_4		seq; 
+} krb5_replay_data;
+
+/* flags for krb5_auth_con_genaddrs() */
+#define KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR		0x00000001
+#define KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR		0x00000002
+#define KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR	0x00000004
+#define KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR	0x00000008
+
+/* type of function used as a callback to generate checksum data for
+ * mk_req */
+
+typedef krb5_error_code 
+(KRB5_CALLCONV * krb5_mk_req_checksum_func) (krb5_context, krb5_auth_context , void *,
+			       krb5_data **);
+
+/*
+ * end "safepriv.h"
+ */
+
+
+/*
+ * begin "ccache.h"
+ */
+
+typedef	krb5_pointer	krb5_cc_cursor;	/* cursor for sequential lookup */
+
+struct _krb5_ccache;
+typedef struct _krb5_ccache *krb5_ccache;
+struct _krb5_cc_ops;
+typedef struct _krb5_cc_ops krb5_cc_ops;
+
+/*
+ * Cursor for iterating over all ccaches
+ */
+struct _krb5_cccol_cursor;
+typedef struct _krb5_cccol_cursor *krb5_cccol_cursor;
+
+/* for retrieve_cred */
+#define	KRB5_TC_MATCH_TIMES		0x00000001
+#define	KRB5_TC_MATCH_IS_SKEY		0x00000002
+#define	KRB5_TC_MATCH_FLAGS		0x00000004
+#define	KRB5_TC_MATCH_TIMES_EXACT	0x00000008
+#define	KRB5_TC_MATCH_FLAGS_EXACT	0x00000010
+#define	KRB5_TC_MATCH_AUTHDATA		0x00000020
+#define	KRB5_TC_MATCH_SRV_NAMEONLY	0x00000040
+#define	KRB5_TC_MATCH_2ND_TKT		0x00000080
+#define	KRB5_TC_MATCH_KTYPE		0x00000100
+#define KRB5_TC_SUPPORTED_KTYPES	0x00000200
+
+/* for set_flags and other functions */
+#define KRB5_TC_OPENCLOSE		0x00000001
+#define KRB5_TC_NOTICKET                0x00000002
+
+const char * KRB5_CALLCONV
+krb5_cc_get_name (krb5_context context, krb5_ccache cache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_gen_new (krb5_context context, krb5_ccache *cache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_initialize(krb5_context context, krb5_ccache cache,
+		   krb5_principal principal);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_destroy (krb5_context context, krb5_ccache cache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_close (krb5_context context, krb5_ccache cache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_store_cred (krb5_context context, krb5_ccache cache,
+		    krb5_creds *creds);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_retrieve_cred (krb5_context context, krb5_ccache cache,
+		       krb5_flags flags, krb5_creds *mcreds,
+		       krb5_creds *creds);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_get_principal (krb5_context context, krb5_ccache cache,
+		       krb5_principal *principal);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_start_seq_get (krb5_context context, krb5_ccache cache,
+		       krb5_cc_cursor *cursor);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_next_cred (krb5_context context, krb5_ccache cache,
+		   krb5_cc_cursor *cursor, krb5_creds *creds);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_end_seq_get (krb5_context context, krb5_ccache cache,
+		     krb5_cc_cursor *cursor);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_remove_cred (krb5_context context, krb5_ccache cache, krb5_flags flags,
+		     krb5_creds *creds);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_set_flags (krb5_context context, krb5_ccache cache, krb5_flags flags);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_get_flags (krb5_context context, krb5_ccache cache, krb5_flags *flags);
+
+const char * KRB5_CALLCONV
+krb5_cc_get_type (krb5_context context, krb5_ccache cache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor *cursor);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_cursor_next(
+    krb5_context context,
+    krb5_cccol_cursor cursor,
+    krb5_ccache *ccache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_cursor_free(krb5_context context, krb5_cccol_cursor *cursor);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_new_unique(
+    krb5_context context,
+    const char *type,
+    const char *hint,
+    krb5_ccache *id);
+
+/*
+ * end "ccache.h"
+ */
+
+/*
+ * begin "rcache.h"
+ */
+
+struct krb5_rc_st;
+typedef struct krb5_rc_st *krb5_rcache;
+
+/*
+ * end "rcache.h"
+ */
+
+/*
+ * begin "keytab.h"
+ */
+
+
+/* XXX */
+#define MAX_KEYTAB_NAME_LEN 1100 /* Long enough for MAXPATHLEN + some extra */
+
+typedef krb5_pointer krb5_kt_cursor;	/* XXX */
+
+typedef struct krb5_keytab_entry_st {
+    krb5_magic magic;
+    krb5_principal principal;	/* principal of this key */
+    krb5_timestamp timestamp;	/* time entry written to keytable */
+    krb5_kvno vno;		/* key version number */
+    krb5_keyblock key;		/* the secret key */
+} krb5_keytab_entry;
+
+#if KRB5_PRIVATE
+struct _krb5_kt_ops;
+typedef struct _krb5_kt {	/* should move into k5-int.h */
+    krb5_magic magic;
+    const struct _krb5_kt_ops *ops;
+    krb5_pointer data;
+} *krb5_keytab;
+#else
+struct _krb5_kt;
+typedef struct _krb5_kt *krb5_keytab;
+#endif
+
+char * KRB5_CALLCONV
+krb5_kt_get_type (krb5_context, krb5_keytab keytab);
+krb5_error_code KRB5_CALLCONV
+krb5_kt_get_name(krb5_context context, krb5_keytab keytab, char *name,
+		 unsigned int namelen);
+krb5_error_code KRB5_CALLCONV
+krb5_kt_close(krb5_context context, krb5_keytab keytab);
+krb5_error_code KRB5_CALLCONV
+krb5_kt_get_entry(krb5_context context, krb5_keytab keytab,
+		  krb5_const_principal principal, krb5_kvno vno,
+		  krb5_enctype enctype, krb5_keytab_entry *entry);
+krb5_error_code KRB5_CALLCONV
+krb5_kt_start_seq_get(krb5_context context, krb5_keytab keytab,
+		      krb5_kt_cursor *cursor);
+krb5_error_code KRB5_CALLCONV
+krb5_kt_next_entry(krb5_context context, krb5_keytab keytab,
+		   krb5_keytab_entry *entry, krb5_kt_cursor *cursor);
+krb5_error_code KRB5_CALLCONV
+krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab,
+		    krb5_kt_cursor *cursor);
+
+/*
+ * end "keytab.h"
+ */
+
+/*
+ * begin "func-proto.h"
+ */
+
+krb5_error_code KRB5_CALLCONV krb5_init_context
+	(krb5_context *);
+krb5_error_code KRB5_CALLCONV krb5_init_secure_context
+	(krb5_context *);
+void KRB5_CALLCONV krb5_free_context
+	(krb5_context);
+krb5_error_code KRB5_CALLCONV krb5_copy_context
+	(krb5_context, krb5_context *);
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_set_default_in_tkt_ktypes
+	(krb5_context,
+		const krb5_enctype *);
+krb5_error_code krb5_get_default_in_tkt_ktypes
+	(krb5_context,
+		krb5_enctype **);
+
+krb5_error_code krb5_set_default_tgs_ktypes
+	(krb5_context,
+		const krb5_enctype *);
+#endif
+
+krb5_error_code KRB5_CALLCONV 
+krb5_set_default_tgs_enctypes
+	(krb5_context,
+		const krb5_enctype *);
+#if KRB5_PRIVATE
+krb5_error_code KRB5_CALLCONV krb5_get_tgs_ktypes
+	(krb5_context,
+		krb5_const_principal,
+		krb5_enctype **);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_get_permitted_enctypes
+	(krb5_context, krb5_enctype **);
+
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_ktypes
+	(krb5_context, krb5_enctype *);
+
+krb5_boolean krb5_is_permitted_enctype
+	(krb5_context, krb5_enctype);
+#endif
+
+krb5_boolean KRB5_CALLCONV krb5_is_thread_safe(void);
+
+/* libkrb.spec */
+#if KRB5_PRIVATE
+krb5_error_code krb5_kdc_rep_decrypt_proc
+	(krb5_context,
+		const krb5_keyblock *,
+		krb5_const_pointer,
+		krb5_kdc_rep * );
+krb5_error_code KRB5_CALLCONV krb5_decrypt_tkt_part
+	(krb5_context,
+		const krb5_keyblock *,
+		krb5_ticket * );
+krb5_error_code krb5_get_cred_from_kdc
+	(krb5_context,
+		krb5_ccache,		/* not const, as reading may save
+					   state */
+		krb5_creds *,
+		krb5_creds **,
+		krb5_creds *** );
+krb5_error_code krb5_get_cred_from_kdc_validate
+	(krb5_context,
+		krb5_ccache,		/* not const, as reading may save
+					   state */
+		krb5_creds *,
+		krb5_creds **,
+		krb5_creds *** );
+krb5_error_code krb5_get_cred_from_kdc_renew
+	(krb5_context,
+		krb5_ccache,		/* not const, as reading may save
+					   state */
+		krb5_creds *,
+		krb5_creds **,
+		krb5_creds *** );
+
+krb5_error_code KRB5_CALLCONV
+krb5int_server_decrypt_ticket_keyblock
+  	(krb5_context context,
+                const krb5_keyblock *key,
+                krb5_ticket  *ticket);
+#endif
+
+krb5_error_code KRB5_CALLCONV
+krb5_server_decrypt_ticket_keytab
+  	(krb5_context context,
+                const krb5_keytab kt,
+                krb5_ticket  *ticket);
+
+void KRB5_CALLCONV krb5_free_tgt_creds
+	(krb5_context,
+	 krb5_creds **); /* XXX too hard to do with const */
+
+#define	KRB5_GC_USER_USER	1	/* want user-user ticket */
+#define	KRB5_GC_CACHED		2	/* want cached ticket only */
+
+krb5_error_code KRB5_CALLCONV krb5_get_credentials
+	(krb5_context,
+		krb5_flags,
+		krb5_ccache,
+		krb5_creds *,
+		krb5_creds **);
+krb5_error_code KRB5_CALLCONV krb5_get_credentials_validate
+	(krb5_context,
+		krb5_flags,
+		krb5_ccache,
+		krb5_creds *,
+		krb5_creds **);
+krb5_error_code KRB5_CALLCONV krb5_get_credentials_renew
+	(krb5_context,
+		krb5_flags,
+		krb5_ccache,
+		krb5_creds *,
+		krb5_creds **);
+#if KRB5_PRIVATE
+krb5_error_code krb5_get_cred_via_tkt
+	(krb5_context,
+		   krb5_creds *,
+		   krb5_flags,
+		   krb5_address * const *,
+		   krb5_creds *,
+		   krb5_creds **);
+#endif
+krb5_error_code KRB5_CALLCONV krb5_mk_req
+	(krb5_context,
+		krb5_auth_context *,
+		krb5_flags,
+		char *,
+		char *,
+		krb5_data *,
+		krb5_ccache,
+		krb5_data * );
+krb5_error_code KRB5_CALLCONV krb5_mk_req_extended
+	(krb5_context,
+		krb5_auth_context *,
+		krb5_flags,
+		krb5_data *,
+		krb5_creds *,
+		krb5_data * );
+krb5_error_code KRB5_CALLCONV krb5_mk_rep
+	(krb5_context,
+		krb5_auth_context,
+		krb5_data *);
+krb5_error_code KRB5_CALLCONV krb5_rd_rep
+	(krb5_context,
+		krb5_auth_context,
+		const krb5_data *,
+		krb5_ap_rep_enc_part **);
+krb5_error_code KRB5_CALLCONV krb5_mk_error
+	(krb5_context,
+		const krb5_error *,
+		krb5_data * );
+krb5_error_code KRB5_CALLCONV krb5_rd_error
+	(krb5_context,
+		const krb5_data *,
+		krb5_error ** );
+krb5_error_code KRB5_CALLCONV krb5_rd_safe
+	(krb5_context,
+		krb5_auth_context,
+		const krb5_data *,
+		krb5_data *,
+		krb5_replay_data *);
+krb5_error_code KRB5_CALLCONV krb5_rd_priv
+	(krb5_context,
+		krb5_auth_context,
+		const krb5_data *,
+		krb5_data *,
+		krb5_replay_data *);
+krb5_error_code KRB5_CALLCONV krb5_parse_name
+	(krb5_context,
+		const char *,
+		krb5_principal * );
+krb5_error_code KRB5_CALLCONV krb5_unparse_name
+	(krb5_context,
+		krb5_const_principal,
+		char ** );
+krb5_error_code KRB5_CALLCONV krb5_unparse_name_ext
+	(krb5_context,
+		krb5_const_principal,
+		char **,
+		unsigned int *);
+
+krb5_error_code KRB5_CALLCONV krb5_set_principal_realm
+	(krb5_context, krb5_principal, const char *);
+
+krb5_boolean KRB5_CALLCONV_WRONG krb5_address_search
+	(krb5_context,
+		const krb5_address *,
+		krb5_address * const *);
+krb5_boolean KRB5_CALLCONV krb5_address_compare
+	(krb5_context,
+		const krb5_address *,
+		const krb5_address *);
+int KRB5_CALLCONV krb5_address_order
+	(krb5_context,
+		const krb5_address *,
+		const krb5_address *);
+krb5_boolean KRB5_CALLCONV krb5_realm_compare
+	(krb5_context,
+		krb5_const_principal,
+		krb5_const_principal);
+krb5_boolean KRB5_CALLCONV krb5_principal_compare
+	(krb5_context,
+		krb5_const_principal,
+		krb5_const_principal);
+krb5_error_code KRB5_CALLCONV  krb5_init_keyblock
+		(krb5_context, krb5_enctype enctype,
+		size_t length, krb5_keyblock **out); 
+  		/* Initialize a new keyblock and allocate storage
+		 * for the contents of the key, which will be freed along
+		 * with the keyblock when krb5_free_keyblock is called.
+		 * It is legal to pass in a length of 0, in which
+		 * case contents are left unallocated.
+		 */
+krb5_error_code KRB5_CALLCONV krb5_copy_keyblock
+	(krb5_context,
+		const krb5_keyblock *,
+		krb5_keyblock **);
+krb5_error_code KRB5_CALLCONV krb5_copy_keyblock_contents
+	(krb5_context,
+		const krb5_keyblock *,
+		krb5_keyblock *);
+krb5_error_code KRB5_CALLCONV krb5_copy_creds
+	(krb5_context,
+		const krb5_creds *,
+		krb5_creds **);
+krb5_error_code KRB5_CALLCONV krb5_copy_data
+	(krb5_context,
+		const krb5_data *,
+		krb5_data **);
+krb5_error_code KRB5_CALLCONV krb5_copy_principal
+	(krb5_context,
+		krb5_const_principal,
+		krb5_principal *);
+#if KRB5_PRIVATE
+krb5_error_code KRB5_CALLCONV krb5_copy_addr
+	(krb5_context,
+		const krb5_address *,
+		krb5_address **);
+#endif
+krb5_error_code KRB5_CALLCONV krb5_copy_addresses
+	(krb5_context,
+		krb5_address * const *,
+		krb5_address ***);
+krb5_error_code KRB5_CALLCONV krb5_copy_ticket
+	(krb5_context,
+		const krb5_ticket *,
+		krb5_ticket **);
+krb5_error_code KRB5_CALLCONV krb5_copy_authdata
+	(krb5_context,
+		krb5_authdata * const *,
+		krb5_authdata ***);
+krb5_error_code KRB5_CALLCONV krb5_copy_authenticator
+	(krb5_context,
+		const krb5_authenticator *,
+		krb5_authenticator **);
+krb5_error_code KRB5_CALLCONV krb5_copy_checksum
+	(krb5_context,
+		const krb5_checksum *,
+		krb5_checksum **);
+#if KRB5_PRIVATE
+void krb5_init_ets
+	(krb5_context);
+void krb5_free_ets
+	(krb5_context);
+krb5_error_code krb5_generate_subkey
+	(krb5_context,
+		const krb5_keyblock *, krb5_keyblock **);
+krb5_error_code krb5_generate_seq_number
+	(krb5_context,
+		const krb5_keyblock *, krb5_ui_4 *);
+#endif
+krb5_error_code KRB5_CALLCONV krb5_get_server_rcache
+	(krb5_context,
+		const krb5_data *, krb5_rcache *);
+krb5_error_code KRB5_CALLCONV_C krb5_build_principal_ext
+	(krb5_context, krb5_principal *, unsigned int, const char *, ...);
+krb5_error_code KRB5_CALLCONV_C krb5_build_principal
+	(krb5_context, krb5_principal *, unsigned int, const char *, ...);
+#ifdef va_start
+/* XXX depending on varargs include file defining va_start... */
+krb5_error_code KRB5_CALLCONV krb5_build_principal_va
+	(krb5_context,
+		krb5_principal, unsigned int, const char *, va_list);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_425_conv_principal
+	(krb5_context,
+		const char *name,
+		const char *instance, const char *realm,
+		krb5_principal *princ);
+
+krb5_error_code KRB5_CALLCONV krb5_524_conv_principal
+	(krb5_context context, krb5_const_principal princ, 
+		char *name, char *inst, char *realm);
+
+struct credentials;
+int KRB5_CALLCONV krb5_524_convert_creds
+	(krb5_context context, krb5_creds *v5creds,
+	 struct credentials *v4creds);
+#if KRB5_DEPRECATED
+#define krb524_convert_creds_kdc krb5_524_convert_creds
+#define krb524_init_ets(x) (0)
+#endif
+
+/* libkt.spec */
+#if KRB5_PRIVATE
+krb5_error_code KRB5_CALLCONV krb5_kt_register
+	(krb5_context,
+		const struct _krb5_kt_ops * );
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_kt_resolve
+	(krb5_context,
+		const char *,
+		krb5_keytab * );
+krb5_error_code KRB5_CALLCONV krb5_kt_default_name
+	(krb5_context,
+		char *,
+		int );
+krb5_error_code KRB5_CALLCONV krb5_kt_default
+	(krb5_context,
+		krb5_keytab * );
+krb5_error_code KRB5_CALLCONV krb5_free_keytab_entry_contents
+	(krb5_context,
+		krb5_keytab_entry * );
+#if KRB5_PRIVATE
+/* use krb5_free_keytab_entry_contents instead */
+krb5_error_code KRB5_CALLCONV krb5_kt_free_entry
+	(krb5_context,
+		krb5_keytab_entry * );
+#endif
+/* remove and add are functions, so that they can return NOWRITE
+   if not a writable keytab */
+krb5_error_code KRB5_CALLCONV krb5_kt_remove_entry
+	(krb5_context,
+		krb5_keytab,
+		krb5_keytab_entry * );
+krb5_error_code KRB5_CALLCONV krb5_kt_add_entry
+	(krb5_context,
+		krb5_keytab,
+		krb5_keytab_entry * );
+krb5_error_code KRB5_CALLCONV_WRONG krb5_principal2salt
+	(krb5_context,
+		krb5_const_principal, krb5_data *);
+#if KRB5_PRIVATE
+krb5_error_code krb5_principal2salt_norealm
+	(krb5_context,
+		krb5_const_principal, krb5_data *);
+#endif
+/* librc.spec--see rcache.h */
+
+/* libcc.spec */
+krb5_error_code KRB5_CALLCONV krb5_cc_resolve
+	(krb5_context,
+		const char *,
+		krb5_ccache * );
+const char * KRB5_CALLCONV krb5_cc_default_name
+	(krb5_context);
+krb5_error_code KRB5_CALLCONV krb5_cc_set_default_name
+	(krb5_context, const char *);
+krb5_error_code KRB5_CALLCONV krb5_cc_default
+	(krb5_context,
+		krb5_ccache *);
+#if KRB5_PRIVATE
+unsigned int KRB5_CALLCONV krb5_get_notification_message
+	(void);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_cc_copy_creds
+	(krb5_context context,
+			krb5_ccache incc,
+			krb5_ccache outcc);
+
+
+/* chk_trans.c */
+#if KRB5_PRIVATE
+krb5_error_code krb5_check_transited_list
+	(krb5_context, const krb5_data *trans,
+	 const krb5_data *realm1, const krb5_data *realm2);
+#endif
+
+/* free_rtree.c */
+#if KRB5_PRIVATE
+void krb5_free_realm_tree
+	(krb5_context,
+		krb5_principal *);
+#endif
+
+/* krb5_free.c */
+void KRB5_CALLCONV krb5_free_principal
+	(krb5_context, krb5_principal );
+void KRB5_CALLCONV krb5_free_authenticator
+	(krb5_context, krb5_authenticator * );
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_authenticator_contents
+	(krb5_context, krb5_authenticator * );
+#endif
+void KRB5_CALLCONV krb5_free_addresses
+	(krb5_context, krb5_address ** );
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_address
+	(krb5_context, krb5_address * );
+#endif
+void KRB5_CALLCONV krb5_free_authdata
+	(krb5_context, krb5_authdata ** );
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_enc_tkt_part
+	(krb5_context, krb5_enc_tkt_part * );
+#endif
+void KRB5_CALLCONV krb5_free_ticket
+	(krb5_context, krb5_ticket * );
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_tickets
+	(krb5_context, krb5_ticket ** );
+void KRB5_CALLCONV krb5_free_kdc_req
+	(krb5_context, krb5_kdc_req * );
+void KRB5_CALLCONV krb5_free_kdc_rep
+	(krb5_context, krb5_kdc_rep * );
+void KRB5_CALLCONV krb5_free_last_req
+	(krb5_context, krb5_last_req_entry ** );
+void KRB5_CALLCONV krb5_free_enc_kdc_rep_part
+	(krb5_context, krb5_enc_kdc_rep_part * );
+#endif
+void KRB5_CALLCONV krb5_free_error
+	(krb5_context, krb5_error * );
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_ap_req
+	(krb5_context, krb5_ap_req * );
+void KRB5_CALLCONV krb5_free_ap_rep
+	(krb5_context, krb5_ap_rep * );
+void KRB5_CALLCONV krb5_free_cred
+	(krb5_context, krb5_cred *);
+#endif
+void KRB5_CALLCONV krb5_free_creds
+	(krb5_context, krb5_creds *);
+void KRB5_CALLCONV krb5_free_cred_contents
+	(krb5_context, krb5_creds *);
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_cred_enc_part
+	(krb5_context, krb5_cred_enc_part *);
+#endif
+void KRB5_CALLCONV krb5_free_checksum
+	(krb5_context, krb5_checksum *);
+void KRB5_CALLCONV krb5_free_checksum_contents
+	(krb5_context, krb5_checksum *);
+void KRB5_CALLCONV krb5_free_keyblock
+	(krb5_context, krb5_keyblock *);
+void KRB5_CALLCONV krb5_free_keyblock_contents
+	(krb5_context, krb5_keyblock *);
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_pa_data
+	(krb5_context, krb5_pa_data **);
+#endif
+void KRB5_CALLCONV krb5_free_ap_rep_enc_part
+	(krb5_context, krb5_ap_rep_enc_part *);
+#if KRB5_PRIVATE
+void KRB5_CALLCONV krb5_free_tkt_authent
+	(krb5_context, krb5_tkt_authent *);
+void KRB5_CALLCONV krb5_free_pwd_data
+	(krb5_context, krb5_pwd_data *);
+void KRB5_CALLCONV krb5_free_pwd_sequences
+	(krb5_context, passwd_phrase_element **);
+#endif
+void KRB5_CALLCONV krb5_free_data
+	(krb5_context, krb5_data *);
+void KRB5_CALLCONV krb5_free_data_contents
+	(krb5_context, krb5_data *);
+void KRB5_CALLCONV krb5_free_unparsed_name
+	(krb5_context, char *);
+void KRB5_CALLCONV krb5_free_cksumtypes
+	(krb5_context, krb5_cksumtype *);
+
+/* From krb5/os but needed but by the outside world */
+krb5_error_code KRB5_CALLCONV krb5_us_timeofday
+	(krb5_context,
+		krb5_timestamp *,
+		krb5_int32 * );
+krb5_error_code KRB5_CALLCONV krb5_timeofday
+	(krb5_context,
+		krb5_timestamp * );
+		 /* get all the addresses of this host */
+krb5_error_code KRB5_CALLCONV krb5_os_localaddr
+	(krb5_context,
+		krb5_address ***);
+krb5_error_code KRB5_CALLCONV krb5_get_default_realm
+	(krb5_context,
+		 char ** );
+krb5_error_code KRB5_CALLCONV krb5_set_default_realm
+	(krb5_context,
+		   const char * );
+void KRB5_CALLCONV krb5_free_default_realm
+	(krb5_context,
+		   char * );
+krb5_error_code KRB5_CALLCONV krb5_sname_to_principal
+	(krb5_context,
+		const char *,
+		   const char *,
+		   krb5_int32,
+		   krb5_principal *);
+krb5_error_code KRB5_CALLCONV
+krb5_change_password
+	(krb5_context context, krb5_creds *creds, char *newpw,
+			int *result_code, krb5_data *result_code_string,
+			krb5_data *result_string);
+krb5_error_code KRB5_CALLCONV
+krb5_set_password
+	(krb5_context context, krb5_creds *creds, char *newpw, krb5_principal change_password_for,
+			int *result_code, krb5_data *result_code_string, krb5_data *result_string);
+krb5_error_code KRB5_CALLCONV
+krb5_set_password_using_ccache
+	(krb5_context context, krb5_ccache ccache, char *newpw, krb5_principal change_password_for,
+			int *result_code, krb5_data *result_code_string, krb5_data *result_string);
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_set_config_files
+	(krb5_context, const char **);
+
+krb5_error_code KRB5_CALLCONV krb5_get_default_config_files
+	(char ***filenames);
+
+void KRB5_CALLCONV krb5_free_config_files
+	(char **filenames);
+#endif
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_profile
+	(krb5_context, struct _profile_t * /* profile_t */ *);
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_send_tgs
+	(krb5_context,
+		krb5_flags,
+		const krb5_ticket_times *,
+		const krb5_enctype *,
+		krb5_const_principal,
+		krb5_address * const *,
+		krb5_authdata * const *,
+		krb5_pa_data * const *,
+		const krb5_data *,
+		krb5_creds *,
+		krb5_response * );
+#endif
+
+#if KRB5_DEPRECATED
+krb5_error_code KRB5_CALLCONV krb5_get_in_tkt
+	(krb5_context,
+		krb5_flags,
+		krb5_address * const *,
+		krb5_enctype *,
+		krb5_preauthtype *,
+		krb5_error_code ( * )(krb5_context,
+					krb5_enctype,
+					krb5_data *,
+					krb5_const_pointer,
+					krb5_keyblock **),
+		krb5_const_pointer,
+		krb5_error_code ( * )(krb5_context,
+					const krb5_keyblock *,
+					krb5_const_pointer,
+					krb5_kdc_rep * ),
+		krb5_const_pointer,
+		krb5_creds *,
+		krb5_ccache,
+		krb5_kdc_rep ** );
+
+krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_password
+	(krb5_context,
+		krb5_flags,
+		krb5_address * const *,
+		krb5_enctype *,
+		krb5_preauthtype *,
+		const char *,
+		krb5_ccache,
+		krb5_creds *,
+		krb5_kdc_rep ** );
+
+krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_skey
+	(krb5_context,
+		krb5_flags,
+		krb5_address * const *,
+		krb5_enctype *,
+		krb5_preauthtype *,
+		const krb5_keyblock *,
+		krb5_ccache,
+		krb5_creds *,
+		krb5_kdc_rep ** );
+
+krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_keytab
+	(krb5_context,
+		krb5_flags,
+		krb5_address * const *,
+		krb5_enctype *,
+		krb5_preauthtype *,
+		krb5_keytab,
+		krb5_ccache,
+		krb5_creds *,
+		krb5_kdc_rep ** );
+#endif /* KRB5_DEPRECATED */
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_decode_kdc_rep
+	(krb5_context,
+		krb5_data *,
+		const krb5_keyblock *,
+		krb5_kdc_rep ** );
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_rd_req
+	(krb5_context,
+		krb5_auth_context *,
+		const krb5_data *,
+		krb5_const_principal,
+		krb5_keytab,
+		krb5_flags *,
+		krb5_ticket **);
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_rd_req_decoded
+	(krb5_context,
+		krb5_auth_context *,
+		const krb5_ap_req *,
+		krb5_const_principal,
+		krb5_keytab,
+		krb5_flags *,
+		krb5_ticket **);
+
+krb5_error_code krb5_rd_req_decoded_anyflag
+	(krb5_context,
+		krb5_auth_context *,
+		const krb5_ap_req *,
+		krb5_const_principal,
+		krb5_keytab,
+		krb5_flags *,
+		krb5_ticket **);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_kt_read_service_key
+	(krb5_context,
+		krb5_pointer,
+		krb5_principal,
+		krb5_kvno,
+		krb5_enctype,
+		krb5_keyblock **);
+krb5_error_code KRB5_CALLCONV krb5_mk_safe
+	(krb5_context,
+		krb5_auth_context,
+		const krb5_data *,
+		krb5_data *,
+		krb5_replay_data *);
+krb5_error_code KRB5_CALLCONV krb5_mk_priv
+	(krb5_context,
+		krb5_auth_context,
+		const krb5_data *,
+		krb5_data *,
+		krb5_replay_data *);
+#if KRB5_PRIVATE
+krb5_error_code KRB5_CALLCONV krb5_cc_register
+	(krb5_context,
+		krb5_cc_ops *,
+		krb5_boolean );
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_sendauth 
+	(krb5_context,
+		krb5_auth_context *,
+		krb5_pointer,
+		char *,
+		krb5_principal,
+		krb5_principal,
+		krb5_flags,
+		krb5_data *,
+		krb5_creds *,
+		krb5_ccache,
+		krb5_error **,
+		krb5_ap_rep_enc_part **,
+		krb5_creds **);
+	
+krb5_error_code KRB5_CALLCONV krb5_recvauth
+	(krb5_context,
+		krb5_auth_context *,
+		krb5_pointer,
+		char *,
+		krb5_principal,
+		krb5_int32, 
+		krb5_keytab,
+		krb5_ticket **);
+krb5_error_code KRB5_CALLCONV krb5_recvauth_version
+	(krb5_context,
+		krb5_auth_context *,
+		krb5_pointer,
+		krb5_principal,
+		krb5_int32, 
+		krb5_keytab,
+		krb5_ticket **,
+		krb5_data *);
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_walk_realm_tree
+	(krb5_context,
+		const krb5_data *,
+		const krb5_data *,
+		krb5_principal **,
+		int);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_mk_ncred
+	(krb5_context,
+		krb5_auth_context,
+		krb5_creds **,
+		krb5_data **,
+		krb5_replay_data *);
+
+krb5_error_code KRB5_CALLCONV krb5_mk_1cred
+	(krb5_context,
+		krb5_auth_context,
+		krb5_creds *,
+		krb5_data **,
+		krb5_replay_data *);
+
+krb5_error_code KRB5_CALLCONV krb5_rd_cred
+	(krb5_context,
+		krb5_auth_context,
+		krb5_data *,
+		krb5_creds ***,
+		krb5_replay_data *);
+
+krb5_error_code KRB5_CALLCONV krb5_fwd_tgt_creds
+	(krb5_context, 
+		krb5_auth_context,
+		char *,
+		krb5_principal, 
+		krb5_principal, 
+		krb5_ccache,
+		int forwardable,
+		krb5_data *);	
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_init
+	(krb5_context,
+		krb5_auth_context *);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_free
+	(krb5_context,
+		krb5_auth_context);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_setflags
+	(krb5_context,
+		krb5_auth_context,
+		krb5_int32);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getflags
+	(krb5_context,
+		krb5_auth_context,
+		krb5_int32 *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_set_checksum_func (krb5_context, krb5_auth_context,
+				 krb5_mk_req_checksum_func, void *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_get_checksum_func( krb5_context, krb5_auth_context,
+				 krb5_mk_req_checksum_func *, void **);
+
+krb5_error_code KRB5_CALLCONV_WRONG krb5_auth_con_setaddrs
+	(krb5_context,
+		krb5_auth_context,
+		krb5_address *,
+		krb5_address *);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getaddrs
+	(krb5_context,
+		krb5_auth_context,
+		krb5_address **,
+		krb5_address **);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_setports
+	(krb5_context,
+		krb5_auth_context,
+		krb5_address *,
+		krb5_address *);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_setuseruserkey
+	(krb5_context,
+		krb5_auth_context,
+		krb5_keyblock *);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getkey
+	(krb5_context,
+		krb5_auth_context,
+		krb5_keyblock **);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getsendsubkey(
+    krb5_context, krb5_auth_context, krb5_keyblock **);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getrecvsubkey(
+    krb5_context, krb5_auth_context, krb5_keyblock **);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_setsendsubkey(
+    krb5_context, krb5_auth_context, krb5_keyblock *);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_setrecvsubkey(
+    krb5_context, krb5_auth_context, krb5_keyblock *);
+
+#if KRB5_DEPRECATED
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getlocalsubkey
+	(krb5_context,
+		krb5_auth_context,
+		krb5_keyblock **);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getremotesubkey
+	(krb5_context,
+		krb5_auth_context,
+		krb5_keyblock **);
+#endif
+
+#if KRB5_PRIVATE
+krb5_error_code KRB5_CALLCONV krb5_auth_con_set_req_cksumtype
+	(krb5_context,
+		krb5_auth_context,
+		krb5_cksumtype);
+
+krb5_error_code krb5_auth_con_set_safe_cksumtype
+	(krb5_context,
+		krb5_auth_context,
+		krb5_cksumtype);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getlocalseqnumber
+	(krb5_context,
+		krb5_auth_context,
+		krb5_int32 *);
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getremoteseqnumber
+	(krb5_context,
+		krb5_auth_context,
+		krb5_int32 *);
+
+#if KRB5_DEPRECATED
+krb5_error_code KRB5_CALLCONV krb5_auth_con_initivector
+	(krb5_context,
+		krb5_auth_context);
+#endif
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_auth_con_setivector
+	(krb5_context,
+		krb5_auth_context,
+		krb5_pointer);
+
+krb5_error_code krb5_auth_con_getivector
+	(krb5_context,
+		krb5_auth_context,
+		krb5_pointer *);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_setrcache
+	(krb5_context,
+		krb5_auth_context,
+		krb5_rcache);
+
+krb5_error_code KRB5_CALLCONV_WRONG krb5_auth_con_getrcache
+	(krb5_context,
+		krb5_auth_context,
+		krb5_rcache *);
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_auth_con_setpermetypes
+	(krb5_context,
+	    krb5_auth_context,
+	    const krb5_enctype *);
+
+krb5_error_code krb5_auth_con_getpermetypes
+	(krb5_context,
+	    krb5_auth_context,
+	    krb5_enctype **);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_auth_con_getauthenticator
+	(krb5_context,
+		krb5_auth_context,
+		krb5_authenticator **);
+
+#define KRB5_REALM_BRANCH_CHAR '.'
+
+/*
+ * end "func-proto.h"
+ */
+
+/*
+ * begin stuff from libos.h
+ */
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_read_message (krb5_context, krb5_pointer, krb5_data *);
+krb5_error_code krb5_write_message (krb5_context, krb5_pointer, krb5_data *);
+int krb5_net_read (krb5_context, int , char *, int);
+int krb5_net_write (krb5_context, int , const char *, int);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_read_password
+	(krb5_context,
+		const char *,
+		const char *,
+		char *,
+		unsigned int * );
+krb5_error_code KRB5_CALLCONV krb5_aname_to_localname
+	(krb5_context,
+		krb5_const_principal,
+		int,
+		char * );
+krb5_error_code KRB5_CALLCONV krb5_get_host_realm
+	(krb5_context,
+		const char *,
+		char *** );
+krb5_error_code KRB5_CALLCONV krb5_get_fallback_host_realm
+	(krb5_context,
+		krb5_data *,
+		char *** );
+krb5_error_code KRB5_CALLCONV krb5_free_host_realm
+	(krb5_context,
+		char * const * );
+#if KRB5_PRIVATE
+krb5_error_code KRB5_CALLCONV krb5_get_realm_domain
+	(krb5_context,
+		const char *,
+		char ** );
+#endif
+krb5_boolean KRB5_CALLCONV krb5_kuserok
+	(krb5_context,
+		krb5_principal, const char *);
+krb5_error_code KRB5_CALLCONV krb5_auth_con_genaddrs
+	(krb5_context,
+		krb5_auth_context,
+		int, int);
+#if KRB5_PRIVATE
+krb5_error_code krb5_gen_portaddr
+	(krb5_context,
+		const krb5_address *,
+		krb5_const_pointer,
+		krb5_address **);
+krb5_error_code krb5_gen_replay_name
+	(krb5_context,
+		const krb5_address *,
+		const char *,
+		char **);
+krb5_error_code krb5_make_fulladdr
+	(krb5_context,
+		krb5_address *,
+		krb5_address *,
+		krb5_address *);
+#endif
+
+krb5_error_code KRB5_CALLCONV krb5_set_real_time
+	(krb5_context, krb5_timestamp, krb5_int32);
+
+#if KRB5_PRIVATE
+krb5_error_code krb5_set_debugging_time
+	(krb5_context, krb5_timestamp, krb5_int32);
+krb5_error_code krb5_use_natural_time
+	(krb5_context);
+#endif
+krb5_error_code KRB5_CALLCONV krb5_get_time_offsets
+	(krb5_context, krb5_timestamp *, krb5_int32 *);
+#if KRB5_PRIVATE
+krb5_error_code krb5_set_time_offsets
+	(krb5_context, krb5_timestamp, krb5_int32);
+#endif
+
+/* str_conv.c */
+krb5_error_code KRB5_CALLCONV krb5_string_to_enctype
+	(char *, krb5_enctype *);
+krb5_error_code KRB5_CALLCONV krb5_string_to_salttype
+	(char *, krb5_int32 *);
+krb5_error_code KRB5_CALLCONV krb5_string_to_cksumtype
+	(char *, krb5_cksumtype *);
+krb5_error_code KRB5_CALLCONV krb5_string_to_timestamp
+	(char *, krb5_timestamp *);
+krb5_error_code KRB5_CALLCONV krb5_string_to_deltat
+	(char *, krb5_deltat *);
+krb5_error_code KRB5_CALLCONV krb5_enctype_to_string
+	(krb5_enctype, char *, size_t);
+krb5_error_code KRB5_CALLCONV krb5_salttype_to_string
+	(krb5_int32, char *, size_t);
+krb5_error_code KRB5_CALLCONV krb5_cksumtype_to_string
+	(krb5_cksumtype, char *, size_t);
+krb5_error_code KRB5_CALLCONV krb5_timestamp_to_string
+	(krb5_timestamp, char *, size_t);
+krb5_error_code KRB5_CALLCONV krb5_timestamp_to_sfstring
+	(krb5_timestamp, char *, size_t, char *);
+krb5_error_code KRB5_CALLCONV krb5_deltat_to_string
+	(krb5_deltat, char *, size_t);
+
+
+
+/* The name of the Kerberos ticket granting service... and its size */
+#define	KRB5_TGS_NAME		"krbtgt"
+#define KRB5_TGS_NAME_SIZE	6
+
+/* flags for recvauth */
+#define KRB5_RECVAUTH_SKIP_VERSION	0x0001
+#define KRB5_RECVAUTH_BADAUTHVERS	0x0002
+/* initial ticket api functions */
+
+typedef struct _krb5_prompt {
+    char *prompt;
+    int hidden;
+    krb5_data *reply;
+} krb5_prompt;
+
+typedef krb5_error_code (KRB5_CALLCONV *krb5_prompter_fct)(krb5_context context,
+					     void *data,
+					     const char *name,
+					     const char *banner,
+					     int num_prompts,
+					     krb5_prompt prompts[]);
+
+
+krb5_error_code KRB5_CALLCONV
+krb5_prompter_posix (krb5_context context,
+		void *data,
+		const char *name,
+		const char *banner,
+		int num_prompts,
+		krb5_prompt prompts[]);
+
+typedef struct _krb5_get_init_creds_opt {
+    krb5_flags flags;
+    krb5_deltat tkt_life;
+    krb5_deltat renew_life;
+    int forwardable;
+    int proxiable;
+    krb5_enctype *etype_list;
+    int etype_list_length;
+    krb5_address **address_list;
+    krb5_preauthtype *preauth_list;
+    int preauth_list_length;
+    krb5_data *salt;
+} krb5_get_init_creds_opt;
+
+#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE	0x0001
+#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE	0x0002
+#define KRB5_GET_INIT_CREDS_OPT_FORWARDABLE	0x0004
+#define KRB5_GET_INIT_CREDS_OPT_PROXIABLE	0x0008
+#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST	0x0010
+#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST	0x0020
+#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST	0x0040
+#define KRB5_GET_INIT_CREDS_OPT_SALT		0x0080
+#define KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT	0x0100
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_alloc
+(krb5_context context,
+		krb5_get_init_creds_opt **opt);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free
+(krb5_context context,
+		krb5_get_init_creds_opt *opt);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_init
+(krb5_get_init_creds_opt *opt);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_tkt_life
+(krb5_get_init_creds_opt *opt,
+		krb5_deltat tkt_life);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_renew_life
+(krb5_get_init_creds_opt *opt,
+		krb5_deltat renew_life);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_forwardable
+(krb5_get_init_creds_opt *opt,
+		int forwardable);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_proxiable
+(krb5_get_init_creds_opt *opt,
+		int proxiable);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_etype_list
+(krb5_get_init_creds_opt *opt,
+		krb5_enctype *etype_list,
+		int etype_list_length);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_address_list
+(krb5_get_init_creds_opt *opt,
+		krb5_address **addresses);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_preauth_list
+(krb5_get_init_creds_opt *opt,
+		krb5_preauthtype *preauth_list,
+		int preauth_list_length);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_salt
+(krb5_get_init_creds_opt *opt,
+		krb5_data *salt);
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_change_password_prompt
+(krb5_get_init_creds_opt *opt,
+		int prompt);
+
+/* Generic preauth option attribute/value pairs */
+typedef struct _krb5_gic_opt_pa_data {
+    char *attr;
+    char *value;
+} krb5_gic_opt_pa_data;
+
+/*
+ * This function allows the caller to supply options to preauth
+ * plugins.  Preauth plugin modules are given a chance to look
+ * at each option at the time this function is called in ordre
+ * to check the validity of the option.
+ * The 'opt' pointer supplied to this function must have been
+ * obtained using krb5_get_init_creds_opt_alloc()
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_set_pa
+		(krb5_context context,
+		krb5_get_init_creds_opt *opt,
+		const char *attr,
+		const char *value);
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_password
+(krb5_context context,
+		krb5_creds *creds,
+		krb5_principal client,
+		char *password,
+		krb5_prompter_fct prompter,
+		void *data,
+		krb5_deltat start_time,
+		char *in_tkt_service,
+		krb5_get_init_creds_opt *k5_gic_options);
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_keytab
+(krb5_context context,
+		krb5_creds *creds,
+		krb5_principal client,
+		krb5_keytab arg_keytab,
+		krb5_deltat start_time,
+		char *in_tkt_service,
+		krb5_get_init_creds_opt *k5_gic_options);
+
+typedef struct _krb5_verify_init_creds_opt {
+    krb5_flags flags;
+    int ap_req_nofail;
+} krb5_verify_init_creds_opt;
+
+#define KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL	0x0001
+
+void KRB5_CALLCONV
+krb5_verify_init_creds_opt_init
+(krb5_verify_init_creds_opt *k5_vic_options);
+void KRB5_CALLCONV
+krb5_verify_init_creds_opt_set_ap_req_nofail
+(krb5_verify_init_creds_opt *k5_vic_options,
+		int ap_req_nofail);
+
+krb5_error_code KRB5_CALLCONV
+krb5_verify_init_creds
+(krb5_context context,
+		krb5_creds *creds,
+		krb5_principal ap_req_server,
+		krb5_keytab ap_req_keytab,
+		krb5_ccache *ccache,
+		krb5_verify_init_creds_opt *k5_vic_options);
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_validated_creds
+(krb5_context context,
+		krb5_creds *creds,
+		krb5_principal client,
+		krb5_ccache ccache,
+		char *in_tkt_service);
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_renewed_creds
+(krb5_context context,
+		krb5_creds *creds,
+		krb5_principal client,
+		krb5_ccache ccache,
+		char *in_tkt_service);
+
+krb5_error_code KRB5_CALLCONV
+krb5_decode_ticket
+(const krb5_data *code, 
+		krb5_ticket **rep);
+
+void KRB5_CALLCONV
+krb5_appdefault_string
+(krb5_context context,
+		const char *appname,  
+	        const krb5_data *realm,
+ 		const char *option,
+		const char *default_value,
+		char ** ret_value);
+
+void KRB5_CALLCONV
+krb5_appdefault_boolean
+(krb5_context context,
+		const char *appname,  
+	        const krb5_data *realm,
+ 		const char *option,
+		int default_value,
+		int *ret_value);
+
+#if KRB5_PRIVATE
+/*
+ * The realm iterator functions
+ */
+
+krb5_error_code KRB5_CALLCONV krb5_realm_iterator_create
+	(krb5_context context, void **iter_p);
+
+krb5_error_code KRB5_CALLCONV krb5_realm_iterator
+	(krb5_context context, void **iter_p, char **ret_realm);
+
+void KRB5_CALLCONV krb5_realm_iterator_free
+	(krb5_context context, void **iter_p);
+
+void KRB5_CALLCONV krb5_free_realm_string
+	(krb5_context context, char *str);
+#endif
+
+/*
+ * Prompter enhancements
+ */
+
+#define KRB5_PROMPT_TYPE_PASSWORD            0x1
+#define KRB5_PROMPT_TYPE_NEW_PASSWORD        0x2
+#define KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN  0x3
+#define KRB5_PROMPT_TYPE_PREAUTH             0x4
+
+typedef krb5_int32 krb5_prompt_type;
+
+krb5_prompt_type* KRB5_CALLCONV krb5_get_prompt_types
+	(krb5_context context);
+
+/* Error reporting */
+void KRB5_CALLCONV_C
+krb5_set_error_message (krb5_context, krb5_error_code, const char *, ...);
+#ifdef va_start
+void KRB5_CALLCONV
+krb5_vset_error_message (krb5_context, krb5_error_code, const char *, va_list);
+#endif
+/*
+ * The behavior of krb5_get_error_message is only defined the first
+ * time it is called after a failed call to a krb5 function using the
+ * same context, and only when the error code passed in is the same as
+ * that returned by the krb5 function.  Future versions may return the
+ * same string for the second and following calls.
+ *
+ * The string returned by this function must be freed using
+ * krb5_free_error_message.
+ */
+const char * KRB5_CALLCONV
+krb5_get_error_message (krb5_context, krb5_error_code);
+void KRB5_CALLCONV
+krb5_free_error_message (krb5_context, const char *);
+void KRB5_CALLCONV
+krb5_clear_error_message (krb5_context);
+
+
+#if TARGET_OS_MAC
+#    pragma pack(pop)
+#endif
+
+KRB5INT_END_DECLS
+
+/* Don't use this!  We're going to phase it out.  It's just here to keep
+   applications from breaking right away.  */
+#define krb5_const const
+
+#endif /* KRB5_GENERAL__ */
+
diff --git a/krb5-1-6/src/include/krb5/locate_plugin.h b/krb5-1-6/src/include/krb5/locate_plugin.h
new file mode 100644
index 000000000..f9f29baf7
--- /dev/null
+++ b/krb5-1-6/src/include/krb5/locate_plugin.h
@@ -0,0 +1,60 @@
+/*
+ * <krb5/locate_plugin.h>
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.	Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Service location plugin definitions for Kerberos 5.
+ */
+
+#ifndef KRB5_LOCATE_PLUGIN_H_INCLUDED
+#define KRB5_LOCATE_PLUGIN_H_INCLUDED
+#include <krb5/krb5.h>
+
+enum locate_service_type {
+    locate_service_kdc = 1,
+    locate_service_master_kdc,
+    locate_service_kadmin,
+    locate_service_krb524,
+    locate_service_kpasswd
+};
+
+typedef struct krb5plugin_service_locate_ftable {
+    int minor_version;		/* currently 0 */
+    /* Per-context setup and teardown.  Returned void* blob is
+       private to the plugin.  */
+    krb5_error_code (*init)(krb5_context, void **);
+    void (*fini)(void *);
+    /* Callback function returns non-zero if the plugin function
+       should quit and return; this may be because of an error, or may
+       indicate we've already contacted the service, whatever.  The
+       lookup function should only return an error if it detects a
+       problem, not if the callback function tells it to quit.  */
+    krb5_error_code (*lookup)(void *,
+			      enum locate_service_type svc, const char *realm,
+			      int socktype, int family,
+			      int (*cbfunc)(void *,int,struct sockaddr *),
+			      void *cbdata);
+} krb5plugin_service_locate_ftable;
+/* extern krb5plugin_service_locate_ftable service_locator; */
+#endif
diff --git a/krb5-1-6/src/include/krb5/preauth_plugin.h b/krb5-1-6/src/include/krb5/preauth_plugin.h
new file mode 100644
index 000000000..242956076
--- /dev/null
+++ b/krb5-1-6/src/include/krb5/preauth_plugin.h
@@ -0,0 +1,507 @@
+/*
+ * <krb5/preauth_plugin.h>
+ *
+ * Copyright (c) 2006 Red Hat, Inc.
+ * Portions copyright (c) 2006 Massachusetts Institute of Technology
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of Red Hat, Inc., nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Preauthentication plugin definitions for Kerberos 5.
+ */
+
+#ifndef KRB5_PREAUTH_PLUGIN_H_INCLUDED
+#define KRB5_PREAUTH_PLUGIN_H_INCLUDED
+#include <krb5/krb5.h>
+
+/*
+ * While arguments of these types are passed-in, for the most part a preauth
+ * module can treat them as opaque.  If we need keying data, we can ask for
+ * it directly.
+ */
+struct _krb5_db_entry_new;
+struct _krb5_key_data;
+struct _krb5_preauth_client_rock;
+
+/*
+ * Preauth mechanism property flags, unified from previous definitions in the
+ * KDC and libkrb5 sources.
+ */
+
+/* Provides a real answer which we can send back to the KDC (client-only).  The
+ * client assumes that one real answer will be enough. */
+#define PA_REAL		0x00000001
+
+/* Doesn't provide a real answer, but must be given a chance to run before any
+ * REAL mechanism callbacks (client-only). */
+#define PA_INFO		0x00000002
+
+/* Causes the KDC to include this mechanism in a list of supported preauth
+ * types if the user's DB entry flags the user as requiring hardware-based
+ * preauthentication (server-only). */
+#define PA_HARDWARE	0x00000004
+
+/* Causes the KDC to include this mechanism in a list of supported preauth
+ * types if the user's DB entry flags the user as requiring preauthentication,
+ * and to fail preauthentication if we can't verify the client data.  The
+ * flipside of PA_SUFFICIENT (server-only). */
+#define PA_REQUIRED	0x00000008
+
+/* Causes the KDC to include this mechanism in a list of supported preauth
+ * types if the user's DB entry flags the user as requiring preauthentication,
+ * and to mark preauthentication as successful if we can verify the client
+ * data.  The flipside of PA_REQUIRED (server-only). */
+#define PA_SUFFICIENT	0x00000010
+
+/* Marks this preauthentication mechanism as one which changes the key which is
+ * used for encrypting the response to the client.  Modules which have this
+ * flag have their server_return_proc called before modules which do not, and
+ * are passed over if a previously-called module has modified the encrypting
+ * key (server-only). */
+#define PA_REPLACES_KEY	0x00000020
+
+/* Causes the KDC to check with this preauthentication module even if the
+ * client has no entry in the realm database.  If the module returns a success
+ * code, continue processing and assume that its return_padata callback will
+ * supply us with a key for encrypting the AS reply (server-only). */
+/* #define PA_VIRTUAL	(0x00000040 | PA_REPLACES_KEY) */
+
+/* Not really a padata type, so don't include it in any list of preauth types
+ * which gets sent over the wire. */
+#define PA_PSEUDO	0x00000080
+
+
+/***************************************************************************
+ *
+ * Client-side preauthentication plugin interface definition.
+ *
+ ***************************************************************************/
+
+/*
+ * A callback which will obtain the user's long-term AS key by prompting the
+ * user for the password, then salting it properly, and so on.  For the moment,
+ * it's identical to the get_as_key callback used inside of libkrb5, but we
+ * define a new typedef here instead of making the existing one public to
+ * isolate ourselves from potential future changes.
+ */
+typedef krb5_error_code
+(*preauth_get_as_key_proc)(krb5_context,
+			   krb5_principal,
+			   krb5_enctype,
+			   krb5_prompter_fct,
+			   void *prompter_data,
+			   krb5_data *salt,
+			   krb5_data *s2kparams,
+			   krb5_keyblock *as_key,
+			   void *gak_data);
+
+/*
+ * A client module's callback functions are allowed to request various
+ * information to enable it to process a request.
+ */
+enum krb5plugin_preauth_client_request_type {
+    /* The returned krb5_data item holds the enctype used to encrypt the
+     * encrypted portion of the AS_REP packet. */
+    krb5plugin_preauth_client_get_etype = 1,
+    /* Free the data returned from krb5plugin_preauth_client_req_get_etype */
+    krb5plugin_preauth_client_free_etype = 2
+};
+typedef krb5_error_code
+(*preauth_get_client_data_proc)(krb5_context,
+				struct _krb5_preauth_client_rock *,
+				krb5_int32 request_type,
+				krb5_data **);
+
+/* Per-plugin initialization/cleanup.  The init function is called
+ * by libkrb5 when the plugin is loaded, and the fini function is
+ * called before the plugin is unloaded.  Both are optional and
+ * may be called multiple times in case the plugin is used in
+ * multiple contexts.  The returned context lives the lifetime of
+ * the krb5_context */
+typedef krb5_error_code
+(*preauth_client_plugin_init_proc)(krb5_context context,
+				   void **plugin_context);
+typedef void
+(*preauth_client_plugin_fini_proc)(krb5_context context,
+				   void *plugin_context);
+
+/* A callback which returns flags indicating if the module is a "real" or
+ * an "info" mechanism, and so on.  This function is called for each entry
+ * in the client_pa_type_list. */
+typedef int
+(*preauth_client_get_flags_proc)(krb5_context context,
+				 krb5_preauthtype pa_type);
+
+/* Per-request initialization/cleanup.  The request_init function is
+ * called when beginning to process a get_init_creds request and the
+ * request_fini function is called when processing of the request is
+ * complete.  This is optional.  It may be called multiple times in
+ * the lifetime of a krb5_context. */
+typedef void
+(*preauth_client_request_init_proc)(krb5_context context,
+				    void *plugin_context,
+				    void **request_context);
+typedef void
+(*preauth_client_request_fini_proc)(krb5_context context,
+				    void *plugin_context,
+				    void *request_context);
+
+/* Client function which processes server-supplied data in pa_data,
+ * returns created data in out_pa_data, storing any of its own state in
+ * client_context if data for the associated preauthentication type is
+ * needed.  It is also called after the AS-REP is received if the AS-REP
+ * includes preauthentication data of the associated type.
+ * NOTE! the encoded_previous_request will be NULL the first time this
+ * function is called, because it is expected to only ever contain the data
+ * obtained from a previous call to this function. */
+typedef krb5_error_code
+(*preauth_client_process_proc)(krb5_context context,
+			       void *plugin_context,
+			       void *request_context,
+			       krb5_get_init_creds_opt *opt,
+			       preauth_get_client_data_proc get_data_proc,
+			       struct _krb5_preauth_client_rock *rock,
+			       krb5_kdc_req *request,
+			       krb5_data *encoded_request_body,
+			       krb5_data *encoded_previous_request,
+			       krb5_pa_data *pa_data,
+			       krb5_prompter_fct prompter,
+			       void *prompter_data,
+			       preauth_get_as_key_proc gak_fct,
+			       void *gak_data,
+			       krb5_data *salt,
+			       krb5_data *s2kparams,
+			       krb5_keyblock *as_key,
+			       krb5_pa_data ***out_pa_data);
+
+/* Client function which can attempt to use e-data in the error response to
+ * try to recover from the given error.  If this function is not NULL, and
+ * it stores data in out_pa_data which is different data from the contents
+ * of in_pa_data, then the client library will retransmit the request. */
+typedef krb5_error_code
+(*preauth_client_tryagain_proc)(krb5_context context,
+				void *plugin_context,
+				void *request_context,
+				krb5_get_init_creds_opt *opt,
+				preauth_get_client_data_proc get_data_proc,
+				struct _krb5_preauth_client_rock *rock,
+				krb5_kdc_req *request,
+				krb5_data *encoded_request_body,
+				krb5_data *encoded_previous_request,
+				krb5_pa_data *in_pa_data,
+				krb5_error *error,
+				krb5_prompter_fct prompter,
+				void *prompter_data,
+				preauth_get_as_key_proc gak_fct,
+				void *gak_data,
+				krb5_data *salt,
+				krb5_data *s2kparams,
+				krb5_keyblock *as_key,
+				krb5_pa_data ***out_pa_data);
+
+/*
+ * Client function which receives krb5_get_init_creds_opt information.
+ * The attr and value information supplied should be copied locally by
+ * the module if it wishes to reference it after returning from this call.
+ */
+typedef krb5_error_code
+(*preauth_client_supply_gic_opts_proc)(krb5_context context,
+				       void *plugin_context,
+				       krb5_get_init_creds_opt *opt,
+				       const char *attr,
+				       const char *value);
+
+/*
+ * The function table / structure which a preauth client module must export as
+ * "preauthentication_client_0".  If the interfaces work correctly, future
+ * versions of the table will add either more callbacks or more arguments to
+ * callbacks, and in both cases we'll be able to wrap the v0 functions.
+ */
+typedef struct krb5plugin_preauth_client_ftable_v1 {
+    /* Not-usually-visible name. */
+    char *name;
+
+    /* Pointer to zero-terminated list of pa_types which this module can
+     * provide services for. */
+    krb5_preauthtype *pa_type_list;
+
+    /* Pointer to zero-terminated list of enc_types which this module claims
+     * to add support for. */
+    krb5_enctype *enctype_list;
+
+    /* Per-plugin initialization/cleanup.  The init function is called
+     * by libkrb5 when the plugin is loaded, and the fini function is
+     * called before the plugin is unloaded.  Both are optional and
+     * may be called multiple times in case the plugin is used in
+     * multiple contexts.  The returned context lives the lifetime of
+     * the krb5_context */
+    preauth_client_plugin_init_proc init;
+    preauth_client_plugin_fini_proc fini;
+
+    /* A callback which returns flags indicating if the module is a "real" or
+     * an "info" mechanism, and so on.  This function is called for each entry
+     * in the client_pa_type_list. */
+    preauth_client_get_flags_proc flags;
+
+    /* Per-request initialization/cleanup.  The request_init function is
+     * called when beginning to process a get_init_creds request and the
+     * request_fini function is called when processing of the request is
+     * complete.  This is optional.  It may be called multiple times in
+     * the lifetime of a krb5_context. */
+    preauth_client_request_init_proc request_init;
+    preauth_client_request_fini_proc request_fini;
+
+    /* Client function which processes server-supplied data in pa_data,
+     * returns created data in out_pa_data, storing any of its own state in
+     * client_context if data for the associated preauthentication type is
+     * needed.  It is also called after the AS-REP is received if the AS-REP
+     * includes preauthentication data of the associated type.
+     * NOTE! the encoded_previous_request will be NULL the first time this
+     * function is called, because it is expected to only ever contain the data
+     * obtained from a previous call to this function. */
+    preauth_client_process_proc process;
+
+    /* Client function which can attempt to use e-data in the error response to
+     * try to recover from the given error.  If this function is not NULL, and
+     * it stores data in out_pa_data which is different data from the contents
+     * of in_pa_data, then the client library will retransmit the request. */
+    preauth_client_tryagain_proc tryagain;
+
+    /*
+     * Client function which receives krb5_get_init_creds_opt information.
+     * The attr and value information supplied should be copied locally by
+     * the module if it wishes to reference it after returning from this call.
+     */
+    preauth_client_supply_gic_opts_proc gic_opts;
+
+} krb5plugin_preauth_client_ftable_v1;
+
+
+/***************************************************************************
+ *
+ * Server-side preauthentication plugin interface definition.
+ *
+ ***************************************************************************/
+
+/*
+ * A server module's callback functions are allowed to request specific types
+ * of information about the given client or server record or request, even
+ * though the database records themselves are opaque to the module.
+ */
+enum krb5plugin_preauth_entry_request_type {
+    /* The returned krb5_data item holds a DER-encoded X.509 certificate. */
+    krb5plugin_preauth_entry_request_certificate = 1,
+    /* The returned krb5_data_item holds a krb5_deltat. */
+    krb5plugin_preauth_entry_max_time_skew = 2,
+    /* The returned krb5_data_item holds an array of krb5_keyblock structures,
+     * terminated by an entry with key type = 0.
+     * Each keyblock should have its contents freed in turn, and then the data
+     * item itself should be freed. */
+    krb5plugin_preauth_keys = 3,
+    /* The returned krb5_data_item holds the request structure, re-encoded
+     * using DER.  Unless the client implementation is the same as the server
+     * implementation, there's a good chance that the result will not match
+     * what the client sent, so don't go creating any fatal errors if it
+     * doesn't match up. */
+    krb5plugin_preauth_request_body = 4
+};
+
+typedef krb5_error_code
+(*preauth_get_entry_data_proc)(krb5_context,
+			       krb5_kdc_req *,
+			       struct _krb5_db_entry_new *,
+			       krb5_int32 request_type,
+			       krb5_data **);
+
+/* Preauth plugin initialization function */
+typedef krb5_error_code
+(*preauth_server_init_proc)(krb5_context context,
+			    void **plugin_context,
+			    const char** realmnames);
+
+/* Preauth plugin cleanup function */
+typedef void
+(*preauth_server_fini_proc)(krb5_context context, void *plugin_context);
+
+/* Return the flags which the KDC should use for this module.  This is a
+ * callback instead of a static value because the module may or may not
+ * wish to count itself as a hardware preauthentication module (in other 
+ * words, the flags may be affected by the configuration, for example if a
+ * site administrator can force a particular preauthentication type to be
+ * supported using only hardware).  This function is called for each entry
+ * entry in the server_pa_type_list. */
+typedef int
+(*preauth_server_flags_proc)(krb5_context context, krb5_preauthtype patype);
+
+/* Get preauthentication data to send to the client as part of the "you
+ * need to use preauthentication" error.  The module doesn't need to
+ * actually provide data if the protocol doesn't require it, but it should
+ * return either zero or non-zero to control whether its padata type is
+ * included in the list which is sent back to the client.  Is not allowed
+ * to create a context because we have no guarantee that the client will
+ * ever call again (or that it will hit this server if it does), in which
+ * case a context might otherwise hang around forever. */
+typedef krb5_error_code
+(*preauth_server_edata_proc)(krb5_context,
+			     krb5_kdc_req *request,
+			     struct _krb5_db_entry_new *client,
+			     struct _krb5_db_entry_new *server,
+			     preauth_get_entry_data_proc,
+			     void *pa_module_context,
+			     krb5_pa_data *data);
+
+/* Verify preauthentication data sent by the client, setting the
+ * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
+ * field as appropriate, and returning nonzero on failure.  Can create
+ * context data for consumption by the return_proc or freepa_proc below. */
+typedef krb5_error_code
+(*preauth_server_verify_proc)(krb5_context context,
+			      struct _krb5_db_entry_new *client,
+			      krb5_data *req_pkt,
+			      krb5_kdc_req *request,
+			      krb5_enc_tkt_part *enc_tkt_reply,
+			      krb5_pa_data *data,
+			      preauth_get_entry_data_proc,
+			      void *pa_module_context,
+			      void **pa_request_context,
+			      krb5_data **e_data,
+			      krb5_authdata ***authz_data);
+
+/* Generate preauthentication response data to send to the client as part
+ * of the AS-REP.  If it needs to override the key which is used to encrypt
+ * the response, it can do so.  The module is expected (but not required,
+ * if a preauth_server_free_reqcontext_proc is also provided) to free any
+ * context data it saved in "pa_request_context". */
+typedef krb5_error_code
+(*preauth_server_return_proc)(krb5_context context,
+			      krb5_pa_data * padata,
+			      struct _krb5_db_entry_new *client,
+			      krb5_data *req_pkt,
+			      krb5_kdc_req *request,
+			      krb5_kdc_rep *reply,
+			      struct _krb5_key_data *client_keys,
+			      krb5_keyblock *encrypting_key,
+			      krb5_pa_data **send_pa,
+			      preauth_get_entry_data_proc,
+			      void *pa_module_context,
+			      void **pa_request_context);
+
+/* Free up the server-side per-request context, in cases where
+ * server_return_proc() didn't or for whatever reason was not called.
+ * Can be NULL. */
+typedef krb5_error_code
+(*preauth_server_free_reqcontext_proc)(krb5_context,
+				       void *pa_module_context,
+				       void **request_pa_context);
+
+/*
+ * The function table / structure which a preauth server module must export as
+ * "preauthentication_server_0".  NOTE: replace "0" with "1" for the type and
+ * variable names if this gets picked up by upstream.  If the interfaces work
+ * correctly, future versions of the table will add either more callbacks or
+ * more arguments to callbacks, and in both cases we'll be able to wrap the v0
+ * functions.
+ */
+typedef struct krb5plugin_preauth_server_ftable_v1 {
+    /* Not-usually-visible name. */
+    char *name;
+
+    /* Pointer to zero-terminated list of pa_types which this module can
+     * provide services for. */
+    krb5_preauthtype *pa_type_list;
+
+    /* Per-plugin initialization/cleanup.  The init function is called by the
+     * KDC when the plugin is loaded, and the fini function is called before
+     * the plugin is unloaded.  Both are optional. */
+    preauth_server_init_proc init_proc;
+    preauth_server_fini_proc fini_proc;
+
+    /* Return the flags which the KDC should use for this module.  This is a
+     * callback instead of a static value because the module may or may not
+     * wish to count itself as a hardware preauthentication module (in other
+     * words, the flags may be affected by the configuration, for example if a
+     * site administrator can force a particular preauthentication type to be
+     * supported using only hardware).  This function is called for each entry
+     * entry in the server_pa_type_list. */
+    preauth_server_flags_proc flags_proc;
+
+    /* Get preauthentication data to send to the client as part of the "you
+     * need to use preauthentication" error.  The module doesn't need to
+     * actually provide data if the protocol doesn't require it, but it should
+     * return either zero or non-zero to control whether its padata type is
+     * included in the list which is sent back to the client.  Is not allowed
+     * to create a context because we have no guarantee that the client will
+     * ever call again (or that it will hit this server if it does), in which
+     * case a context might otherwise hang around forever. */
+    preauth_server_edata_proc edata_proc;
+
+    /* Verify preauthentication data sent by the client, setting the
+     * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
+     * field as appropriate, and returning nonzero on failure.  Can create
+     * context data for consumption by the return_proc or freepa_proc below. */
+    preauth_server_verify_proc verify_proc;
+
+    /* Generate preauthentication response data to send to the client as part
+     * of the AS-REP.  If it needs to override the key which is used to encrypt
+     * the response, it can do so.  The module is expected (but not required,
+     * if a freepa_proc is also provided) to free any context data it saved in
+     * "request_pa_context". */
+    preauth_server_return_proc return_proc;
+
+    /* Free up the server-side per-request context, in cases where
+     * server_return_proc() didn't or for whatever reason was not called.
+     * Can be NULL. */
+    preauth_server_free_reqcontext_proc freepa_reqcontext_proc;
+
+} krb5plugin_preauth_server_ftable_v1;
+
+
+/*
+ * This function allows a preauth plugin to obtain preauth
+ * options.  The preauth_data returned from this function
+ * should be freed by calling krb5_get_init_creds_opt_free_pa().
+ *
+ * The 'opt' pointer supplied to this function must have been
+ * obtained using krb5_get_init_creds_opt_alloc()
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_get_pa
+		(krb5_context context,
+		krb5_get_init_creds_opt *opt,
+		int *num_preauth_data,
+		krb5_gic_opt_pa_data **preauth_data);
+
+/*
+ * This function frees the preauth_data that was returned by
+ * krb5_get_init_creds_opt_get_pa().
+ */
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free_pa
+		(krb5_context context,
+		 int num_preauth_data,
+		 krb5_gic_opt_pa_data *preauth_data);
+
+#endif /* KRB5_PREAUTH_PLUGIN_H_INCLUDED */
diff --git a/krb5-1-6/src/include/krb54proto.h b/krb5-1-6/src/include/krb54proto.h
new file mode 100644
index 000000000..d1d16e1ba
--- /dev/null
+++ b/krb5-1-6/src/include/krb54proto.h
@@ -0,0 +1,18 @@
+/*
+ * Kerberos V 5/4 prototypes
+ */
+
+extern krb5_error_code krb54_get_service_keyblock
+	(char *service, char *instance, char *realm,
+		   int kvno, char *file,
+		   krb5_keyblock * keyblock);
+extern int decomp_tkt_krb5
+	(KTEXT tkt, unsigned char *flags, char *pname,
+		   char *pinstance, char *prealm, unsigned KRB4_32 *paddress,
+		   des_cblock session, int *life, unsigned KRB4_32 *time_sec, 
+		   char *sname, char *sinstance, krb5_keyblock *k5key);
+extern int krb_set_key_krb5
+	(krb5_context ctx, krb5_keyblock *key);
+void krb_clear_key_krb5
+	(krb5_context ctx);
+
diff --git a/krb5-1-6/src/include/port-sockets.h b/krb5-1-6/src/include/port-sockets.h
new file mode 100644
index 000000000..35ed2b4c4
--- /dev/null
+++ b/krb5-1-6/src/include/port-sockets.h
@@ -0,0 +1,187 @@
+#ifndef _PORT_SOCKET_H
+#define _PORT_SOCKET_H
+#if defined(_WIN32)
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+/* Some of our own infrastructure where the WinSock stuff was too hairy
+   to dump into a clean Unix program...  */
+
+typedef WSABUF sg_buf;
+
+#define SG_ADVANCE(SG, N) \
+	((SG)->len < (N)				\
+	 ? (abort(), 0)					\
+	 : ((SG)->buf += (N), (SG)->len -= (N), 0))
+
+#define SG_LEN(SG)		((SG)->len + 0)
+#define SG_BUF(SG)		((SG)->buf + 0)
+#define SG_SET(SG, B, N)	((SG)->buf = (char *)(B),(SG)->len = (N))
+
+#define SOCKET_INITIALIZE()     0
+#define SOCKET_CLEANUP()
+#define SOCKET_ERRNO            (WSAGetLastError())
+#define SOCKET_SET_ERRNO(x)     (WSASetLastError (x))
+#define SOCKET_NFDS(f)          (0)     /* select()'s first arg is ignored */
+#define SOCKET_READ(fd, b, l)   (recv(fd, b, l, 0))
+#define SOCKET_WRITE(fd, b, l)  (send(fd, b, l, 0))
+#define SOCKET_CONNECT		connect	/* XXX */
+#define SOCKET_GETSOCKNAME	getsockname /* XXX */
+#define SOCKET_CLOSE		close /* XXX */
+#define SOCKET_EINTR            WSAEINTR
+
+/* Return -1 for error or number of bytes written.
+   TMP is a temporary variable; must be declared by the caller, and
+   must be used by this macro (to avoid compiler warnings).  */
+/* WSASend returns 0 or SOCKET_ERROR.  */
+#define SOCKET_WRITEV_TEMP DWORD
+#define SOCKET_WRITEV(FD, SG, LEN, TMP)	\
+	(WSASend((FD), (SG), (LEN), &(TMP), 0, 0, 0) ? -1 : (TMP))
+
+#define SHUTDOWN_READ	SD_RECEIVE
+#define SHUTDOWN_WRITE	SD_SEND
+#define SHUTDOWN_BOTH	SD_BOTH
+
+#ifndef EINPROGRESS
+#define EINPROGRESS WSAEINPROGRESS
+#endif
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+#ifndef ECONNRESET
+#define ECONNRESET  WSAECONNRESET
+#endif
+#ifndef ECONNABORTED
+#define ECONNABORTED WSAECONNABORTED
+#endif
+#ifndef ECONNREFUSED
+#define ECONNREFUSED WSAECONNREFUSED
+#endif
+#ifndef EHOSTUNREACH
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#endif
+#ifndef ETIMEDOUT
+#define ETIMEDOUT WSAETIMEDOUT
+#endif
+
+#elif defined(__palmos__)
+
+/* If this source file requires it, define struct sockaddr_in
+   (and possibly other things related to network I/O).  */
+
+#include "autoconf.h"
+#include <netdb.h>
+typedef int socklen_t;
+
+#else /* UNIX variants */
+
+#include "autoconf.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>		/* For struct sockaddr_in and in_addr */
+#include <arpa/inet.h>		/* For inet_ntoa */
+#include <netdb.h>
+
+#ifndef HAVE_NETDB_H_H_ERRNO
+extern int h_errno;		/* In case it's missing, e.g., HP-UX 10.20. */
+#endif
+
+#include <sys/param.h>		/* For MAXHOSTNAMELEN */
+#include <sys/socket.h>		/* For SOCK_*, AF_*, etc */
+#include <sys/time.h>		/* For struct timeval */
+#include <net/if.h>		/* For struct ifconf, for localaddr.c */
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>		/* For struct iovec, for sg_buf */
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>		/* For FIONBIO on Solaris.  */
+#endif
+
+/* Either size_t or int or unsigned int is probably right.  Under
+   SunOS 4, it looks like int is desired, according to the accept man
+   page.  */
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+/* XXX should only be done if sockaddr_storage not found */
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+struct krb5int_sockaddr_storage {
+    struct sockaddr_in s;
+    /* Plenty of slop just in case we get an ipv6 address anyways.  */
+    long extra[16];
+};
+#define sockaddr_storage krb5int_sockaddr_storage
+#endif
+
+/*
+ * Compatability with WinSock calls on MS-Windows...
+ */
+#define	SOCKET		int
+#define	INVALID_SOCKET	((SOCKET)~0)
+#define	closesocket	close
+#define	ioctlsocket	ioctl
+#define	SOCKET_ERROR	(-1)
+
+typedef struct iovec sg_buf;
+
+#define SG_ADVANCE(SG, N) \
+	((SG)->iov_len < (N)					\
+	 ? (abort(), 0)						\
+	 : ((SG)->iov_base = (char *) (SG)->iov_base + (N),	\
+	    (SG)->iov_len -= (N), 0))
+
+#define SG_LEN(SG)		((SG)->iov_len + 0)
+#define SG_BUF(SG)		((char*)(SG)->iov_base + 0)
+#define SG_SET(SG, B, L)	((SG)->iov_base = (char*)(B), (SG)->iov_len = (L))
+
+/* Some of our own infrastructure where the WinSock stuff was too hairy
+   to dump into a clean Unix program...  */
+
+#define	SOCKET_INITIALIZE()	(0)	/* No error (or anything else) */
+#define	SOCKET_CLEANUP()	/* nothing */
+#define	SOCKET_ERRNO		errno
+#define	SOCKET_SET_ERRNO(x)	(errno = (x))
+#define SOCKET_NFDS(f)		((f)+1)	/* select() arg for a single fd */
+#define SOCKET_READ		read
+#define SOCKET_WRITE		write
+#define SOCKET_CONNECT		connect
+#define SOCKET_GETSOCKNAME	getsockname
+#define SOCKET_CLOSE		close
+#define SOCKET_EINTR		EINTR
+#define SOCKET_WRITEV_TEMP int
+/* Use TMP to avoid compiler warnings and keep things consistent with
+   Windoze version.  */
+#define SOCKET_WRITEV(FD, SG, LEN, TMP) \
+	((TMP) = writev((FD), (SG), (LEN)), (TMP))
+
+#define SHUTDOWN_READ	0
+#define SHUTDOWN_WRITE	1
+#define SHUTDOWN_BOTH	2
+
+#ifndef HAVE_INET_NTOP
+#define inet_ntop(AF,SRC,DST,CNT)					    \
+    ((AF) == AF_INET							    \
+     ? ((CNT) < 16							    \
+	? (SOCKET_SET_ERRNO(ENOSPC), (const char *)NULL)		    \
+	: (sprintf((DST), "%d.%d.%d.%d",				    \
+		   ((const unsigned char *)(const void *)(SRC))[0] & 0xff,  \
+		   ((const unsigned char *)(const void *)(SRC))[1] & 0xff,  \
+		   ((const unsigned char *)(const void *)(SRC))[2] & 0xff,  \
+		   ((const unsigned char *)(const void *)(SRC))[3] & 0xff), \
+	   (DST)))							    \
+     : (SOCKET_SET_ERRNO(EAFNOSUPPORT), (const char *)NULL))
+#define HAVE_INET_NTOP
+#endif
+
+#endif /* _WIN32 */
+
+#if !defined(_WIN32)
+/* UNIX or ...?  */
+# ifdef S_SPLINT_S
+extern int socket (int, int, int) /*@*/;
+# endif
+#endif
+
+#endif /*_PORT_SOCKET_H*/
diff --git a/krb5-1-6/src/include/socket-utils.h b/krb5-1-6/src/include/socket-utils.h
new file mode 100644
index 000000000..070bb2ff1
--- /dev/null
+++ b/krb5-1-6/src/include/socket-utils.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2001,2005 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+#ifndef SOCKET_UTILS_H
+#define SOCKET_UTILS_H
+
+/* Some useful stuff cross-platform for manipulating socket addresses.
+   We assume at least ipv4 sockaddr_in support.  The sockaddr_storage
+   stuff comes from the ipv6 socket api enhancements; socklen_t is
+   provided on some systems; the rest is just convenience for internal
+   use in the krb5 tree.
+
+   Do NOT install this file.  */
+
+/* for HAVE_SOCKLEN_T, KRB5_USE_INET6, etc */
+#include "autoconf.h"
+/* for sockaddr_storage */
+#include "port-sockets.h"
+/* for "inline" if needed */
+#include "k5-platform.h"
+
+/*
+ * There's a lot of confusion between pointers to different sockaddr
+ * types, and pointers with different degrees of indirection, as in
+ * the locate_kdc type functions.  Use these function to ensure we
+ * don't do something silly like cast a "sockaddr **" to a
+ * "sockaddr_in *".
+ *
+ * The casts to (void *) are to get GCC to shut up about alignment
+ * increasing.
+ */
+static inline struct sockaddr_in *sa2sin (struct sockaddr *sa)
+{
+    return (struct sockaddr_in *) (void *) sa;
+}
+#ifdef KRB5_USE_INET6
+static inline struct sockaddr_in6 *sa2sin6 (struct sockaddr *sa)
+{
+    return (struct sockaddr_in6 *) (void *) sa;
+}
+#endif
+static inline struct sockaddr *ss2sa (struct sockaddr_storage *ss)
+{
+    return (struct sockaddr *) ss;
+}
+static inline struct sockaddr_in *ss2sin (struct sockaddr_storage *ss)
+{
+    return (struct sockaddr_in *) ss;
+}
+#ifdef KRB5_USE_INET6
+static inline struct sockaddr_in6 *ss2sin6 (struct sockaddr_storage *ss)
+{
+    return (struct sockaddr_in6 *) ss;
+}
+#endif
+
+#if !defined (socklen)
+/* socklen_t socklen (struct sockaddr *) */
+#  ifdef HAVE_SA_LEN
+#    define socklen(X) ((X)->sa_len)
+#  else
+#    ifdef KRB5_USE_INET6
+#      define socklen(X) ((X)->sa_family == AF_INET6 ? (socklen_t) sizeof (struct sockaddr_in6) : (X)->sa_family == AF_INET ? (socklen_t) sizeof (struct sockaddr_in) : (socklen_t) sizeof (struct sockaddr))
+#    else
+#      define socklen(X) ((X)->sa_family == AF_INET ? (socklen_t) sizeof (struct sockaddr_in) : (socklen_t) sizeof (struct sockaddr))
+#    endif
+#  endif
+#endif
+
+#endif /* SOCKET_UTILS_H */
diff --git a/krb5-1-6/src/include/spnego-asn1.h b/krb5-1-6/src/include/spnego-asn1.h
new file mode 100644
index 000000000..8070a9f99
--- /dev/null
+++ b/krb5-1-6/src/include/spnego-asn1.h
@@ -0,0 +1,89 @@
+/*
+ * spnego-asn1.h
+ *
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This file contains structure definitions 
+ * for the SPNEGO GSSAPI mechanism (RFC 2478).  This file is
+ *an internal interface between the GSSAPI library  and the ASN.1
+ *encoders/decoders for the SPNEGO structures in the krb5 library.
+ */
+
+
+#ifndef _KRB5_SPNEGO_ASN1_H_
+#define _KRB5_SPNEGO_ASN1_h_
+
+#include "k5-int.h"
+
+/* Context flags recognized by SPNEGO*/
+enum {
+  SPNEGO_DELEG_FLAG = 0x80,
+  SPNEGO_MUTUAL_FLAG = 0x40,
+  SPNEGO_ANON_FLAG=0x20,
+  SPNEGO_CONF_FLAG = 0x10
+};
+
+/* Results of a negotiation*/
+enum {
+  SPNEGO_ACCEPT_COMPLETED = 0,
+  SPNEGO_ACCEPT_INCOMPLETE = 1,
+  SPNEGO_REJECT = 2,
+  SPNEGO_UNSPEC_RESULT = 3
+};
+
+typedef krb5_data spnego_oid;
+
+typedef struct _spnego_initiator_token {
+    spnego_oid **mechanisms;
+    krb5_int32 requested_flags;
+    krb5_data mech_token;
+    krb5_data mechlist_mic;
+} spnego_initiator_token;
+
+typedef struct _spnego_acceptor_token {
+    int neg_result;
+    spnego_oid supported_mech;
+    krb5_data response_token;
+    krb5_data mechlist_mic;
+} spnego_acceptor_token;
+
+/*
+ * SPNEGO_PROTOTYPES should be defined in the modules implementing
+ * SPNEGO functions  and in the module implementing the accessor
+ * initializer.  All other modules should access these functions
+ * through the accessor interface.
+ */
+
+#ifdef SPNEGO_PROTOTYPES
+
+krb5_error_code krb5int_encode_spnego_acceptor_token
+(krb5_context , spnego_acceptor_token *,
+	 krb5_data **);
+
+krb5_error_code krb5int_encode_spnego_initiator_token
+(krb5_context, spnego_initiator_token *,
+ krb5_data **out);
+#endif /*SPNEGO_ASN1_PROTOTYPES*/
+
+#endif /*_KRB5_SPNEGO_ASN1_H_*/
diff --git a/krb5-1-6/src/include/stock/osconf.h b/krb5-1-6/src/include/stock/osconf.h
new file mode 100644
index 000000000..3a8ba4956
--- /dev/null
+++ b/krb5-1-6/src/include/stock/osconf.h
@@ -0,0 +1,139 @@
+/*
+ * include/krb5/stock/osconf.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Site- and OS- dependant configuration.
+ */
+
+#ifndef KRB5_OSCONF__
+#define KRB5_OSCONF__
+
+#if !defined(_WIN32)
+    /* Don't try to pull in autoconf.h for Windows, since it's not used */
+#ifndef KRB5_AUTOCONF__
+#define KRB5_AUTOCONF__
+#include "autoconf.h"
+#endif
+#endif
+
+#if defined(__MACH__) && defined(__APPLE__)
+# include <TargetConditionals.h>
+#endif
+
+#if defined(_WIN32)
+#define DEFAULT_PROFILE_FILENAME "krb5.ini"
+#define	DEFAULT_LNAME_FILENAME	"/aname"
+#define	DEFAULT_KEYTAB_NAME	"FILE:%s\\krb5kt"
+#else /* !_WINDOWS */
+#if TARGET_OS_MAC
+#define DEFAULT_SECURE_PROFILE_PATH "/Library/Preferences/edu.mit.Kerberos:/etc/krb5.conf:@SYSCONFDIR/krb5.conf"
+#define DEFAULT_PROFILE_PATH        ("~/Library/Preferences/edu.mit.Kerberos" ":" DEFAULT_SECURE_PROFILE_PATH)
+#define KRB5_PLUGIN_BUNDLE_DIR       "/System/Library/KerberosPlugins/KerberosFrameworkPlugins"
+#define KDB5_PLUGIN_BUNDLE_DIR       "/System/Library/KerberosPlugins/KerberosDatabasePlugins"
+#else
+#define DEFAULT_SECURE_PROFILE_PATH	"/etc/krb5.conf:@SYSCONFDIR/krb5.conf"
+#define DEFAULT_PROFILE_PATH        DEFAULT_SECURE_PROFILE_PATH
+#endif
+#define	DEFAULT_KEYTAB_NAME	"FILE:/etc/krb5.keytab"
+#define	DEFAULT_LNAME_FILENAME	"@PREFIX/lib/krb5.aname"
+#endif /* _WINDOWS  */
+
+#define DEFAULT_KDB_FILE        "@LOCALSTATEDIR/krb5kdc/principal"
+#define	DEFAULT_KEYFILE_STUB	"@LOCALSTATEDIR/krb5kdc/.k5."
+#define KRB5_DEFAULT_ADMIN_ACL	"@LOCALSTATEDIR/krb5kdc/krb5_adm.acl"
+/* Used by old admin server */
+#define	DEFAULT_ADMIN_ACL	"@LOCALSTATEDIR/krb5kdc/kadm_old.acl"
+
+/* Location of KDC profile */
+#define	DEFAULT_KDC_PROFILE	"@LOCALSTATEDIR/krb5kdc/kdc.conf"
+#define	KDC_PROFILE_ENV		"KRB5_KDC_PROFILE"
+
+#if TARGET_OS_MAC
+#define DEFAULT_KDB_LIB_PATH	{ KDB5_PLUGIN_BUNDLE_DIR, "@MODULEDIR/kdb", NULL }
+#else
+#define DEFAULT_KDB_LIB_PATH	{ "@MODULEDIR/kdb", NULL }
+#endif
+
+#define	DEFAULT_KDC_ENCTYPE	ENCTYPE_DES3_CBC_SHA1
+#define KDCRCACHE		"dfl:krb5kdc_rcache"
+
+#define KDC_PORTNAME		"kerberos" /* for /etc/services or equiv. */
+#define KDC_SECONDARY_PORTNAME	"kerberos-sec" /* For backwards */
+					    /* compatibility with */
+					    /* port 750 clients */
+
+#define KRB5_DEFAULT_PORT	88
+#define KRB5_DEFAULT_SEC_PORT	750
+
+#define DEFAULT_KPASSWD_PORT	464
+#define KPASSWD_PORTNAME "kpasswd"
+
+#define DEFAULT_KDC_UDP_PORTLIST "88,750"
+#define DEFAULT_KDC_TCP_PORTLIST ""
+
+/*
+ * Defaults for the KADM5 admin system.
+ */
+#define DEFAULT_KADM5_KEYTAB	"@LOCALSTATEDIR/krb5kdc/kadm5.keytab"
+#define DEFAULT_KADM5_ACL_FILE	"@LOCALSTATEDIR/krb5kdc/kadm5.acl"
+#define DEFAULT_KADM5_PORT	749 /* assigned by IANA */
+
+#define MAX_DGRAM_SIZE	4096
+#define MAX_SKDC_TIMEOUT 30
+#define SKDC_TIMEOUT_SHIFT 2		/* left shift of timeout for backoff */
+#define SKDC_TIMEOUT_1 1		/* seconds for first timeout */
+
+#define RCTMPDIR	"@KRB5RCTMPDIR"	/* directory to store replay caches */
+
+#define KRB5_PATH_TTY	"/dev/tty"
+#define KRB5_PATH_LOGIN	"@SBINDIR/login.krb5"
+#define KRB5_PATH_RLOGIN "@BINDIR/rlogin"
+
+#define KRB5_ENV_CCNAME	"KRB5CCNAME"
+
+/*
+ * krb4 kadmin stuff follows
+ */
+
+/* the default syslog file */
+#define KADM_SYSLOG  "@LOCALSTATEDIR/krb5kdc/admin_server.syslog"
+
+/* where to find the bad password table */
+#define PW_CHECK_FILE "@LOCALSTATEDIR/krb5kdc/bad_passwd"
+
+#define DEFAULT_ACL_DIR	"@LOCALSTATEDIR/krb5kdc"
+
+/*
+ * krb5 slave support follows
+ */
+
+#define KPROP_DEFAULT_FILE "@LOCALSTATEDIR/krb5kdc/slave_datatrans"
+#define KPROPD_DEFAULT_FILE "@LOCALSTATEDIR/krb5kdc/from_master"
+#define KPROPD_DEFAULT_KDB5_UTIL "@SBINDIR/kdb5_util"
+#define KPROPD_DEFAULT_KDB5_EDIT "@SBINDIR/kdb5_edit"
+#define KPROPD_DEFAULT_KRB_DB DEFAULT_KDB_FILE
+#define KPROPD_ACL_FILE "@LOCALSTATEDIR/krb5kdc/kpropd.acl"
+
+#endif /* KRB5_OSCONF__ */
diff --git a/krb5-1-6/src/include/syslog.h b/krb5-1-6/src/include/syslog.h
new file mode 100644
index 000000000..f587921e1
--- /dev/null
+++ b/krb5-1-6/src/include/syslog.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	@(#)syslog.h	7.10 (Berkeley) 6/27/88
+ */
+
+/*
+ *	include/syslog.h
+ */
+
+/*
+ *  Facility codes
+ */
+
+#define LOG_KERN	(0<<3)	/* kernel messages */
+#define LOG_USER	(1<<3)	/* random user-level messages */
+#define LOG_MAIL	(2<<3)	/* mail system */
+#define LOG_DAEMON	(3<<3)	/* system daemons */
+#define LOG_AUTH	(4<<3)	/* security/authorization messages */
+#define LOG_SYSLOG	(5<<3)	/* messages generated internally by syslogd */
+#define LOG_LPR		(6<<3)	/* line printer subsystem */
+#define LOG_NEWS	(7<<3)	/* network news subsystem */
+#define LOG_UUCP	(8<<3)	/* UUCP subsystem */
+	/* other codes through 15 reserved for system use */
+#define LOG_LOCAL0	(16<<3)	/* reserved for local use */
+#define LOG_LOCAL1	(17<<3)	/* reserved for local use */
+#define LOG_LOCAL2	(18<<3)	/* reserved for local use */
+#define LOG_LOCAL3	(19<<3)	/* reserved for local use */
+#define LOG_LOCAL4	(20<<3)	/* reserved for local use */
+#define LOG_LOCAL5	(21<<3)	/* reserved for local use */
+#define LOG_LOCAL6	(22<<3)	/* reserved for local use */
+#define LOG_LOCAL7	(23<<3)	/* reserved for local use */
+
+#define LOG_NFACILITIES	24	/* maximum number of facilities */
+#define LOG_FACMASK	0x03f8	/* mask to extract facility part */
+
+#define LOG_FAC(p)	(((p) & LOG_FACMASK) >> 3)	/* facility of pri */
+
+/*
+ *  Priorities (these are ordered)
+ */
+
+#define LOG_EMERG	0	/* system is unusable */
+#define LOG_ALERT	1	/* action must be taken immediately */
+#define LOG_CRIT	2	/* critical conditions */
+#define LOG_ERR		3	/* error conditions */
+#define LOG_WARNING	4	/* warning conditions */
+#define LOG_NOTICE	5	/* normal but signification condition */
+#define LOG_INFO	6	/* informational */
+#define LOG_DEBUG	7	/* debug-level messages */
+
+#define LOG_PRIMASK	0x0007	/* mask to extract priority part (internal) */
+#define LOG_PRI(p)	((p) & LOG_PRIMASK)	/* extract priority */
+
+#define	LOG_MAKEPRI(fac, pri)	(((fac) << 3) | (pri))
+
+#ifdef KERNEL
+#define LOG_PRINTF	-1	/* pseudo-priority to indicate use of printf */
+#endif
+
+/*
+ * arguments to setlogmask.
+ */
+#define	LOG_MASK(pri)	(1 << (pri))		/* mask for one priority */
+#define	LOG_UPTO(pri)	((1 << ((pri)+1)) - 1)	/* all priorities through pri */
+
+/*
+ *  Option flags for openlog.
+ *
+ *	LOG_ODELAY no longer does anything; LOG_NDELAY is the
+ *	inverse of what it used to be.
+ */
+#define	LOG_PID		0x01	/* log the pid with each message */
+#define	LOG_CONS	0x02	/* log on the console if errors in sending */
+#define	LOG_ODELAY	0x04	/* delay open until syslog() is called */
+#define LOG_NDELAY	0x08	/* don't delay open */
+#define LOG_NOWAIT	0x10	/* if forking to log on console, don't wait() */
+
+#ifndef KERNEL
+extern void syslog  (int , const char *, ... );
+#ifdef va_start				
+/* XXX depending on #define of va_start in <stdarg.h> */
+extern void vsyslog  (int , const char *, va_list );
+#endif
+extern void openlog  (const char *, int , int );
+extern void closelog  (void );
+extern int setlogmask  (int );
+
+#endif
diff --git a/krb5-1-6/src/include/win-mac.h b/krb5-1-6/src/include/win-mac.h
new file mode 100644
index 000000000..923fe6045
--- /dev/null
+++ b/krb5-1-6/src/include/win-mac.h
@@ -0,0 +1,224 @@
+/*
+ * This file is now only used on Windows
+ */
+
+/*
+ * type functions split out of here to make things look nicer in the
+ * various include files which need these definitions, as well as in
+ * the util/ directories.
+ */
+
+#ifndef _KRB5_WIN_MAC_H
+#define _KRB5_WIN_MAC_H
+
+#ifdef _WIN32
+
+#define ID_READ_PWD_DIALOG  10000
+#define ID_READ_PWD_PROMPT  10001
+#define ID_READ_PWD_PROMPT2 10002
+#define ID_READ_PWD_PWD     10003
+
+#ifdef RES_ONLY
+
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include <windows.h>
+
+#else /* ! RES_ONLY */
+
+/* To ensure backward compatibility of the ABI use 32-bit time_t on 
+ * 32-bit Windows. 
+ */
+#ifdef _KRB5_INT_H
+#ifdef KRB5_GENERAL__
+#error krb5.h included before k5-int.h
+#endif /* KRB5_GENERAL__ */
+#if _INTEGRAL_MAX_BITS >= 64 && _MSC_VER >= 1400 && !defined(_WIN64) && !defined(_USE_32BIT_TIME_T)
+#if defined(_TIME_T_DEFINED) || defined(_INC_IO) || defined(_INC_TIME) || defined(_INC_WCHAR)
+#error time_t has been defined as a 64-bit integer which is incompatible with Kerberos on this platform.
+#endif /* _TIME_T_DEFINED */
+#define _USE_32BIT_TIME_T
+#endif 
+#endif
+
+#define SIZEOF_INT      4
+#define SIZEOF_SHORT    2
+#define SIZEOF_LONG     4
+
+#include <windows.h>
+#include <limits.h>
+
+#ifndef SIZE_MAX    /* in case Microsoft defines max size of size_t */
+#ifdef  MAX_SIZE    /* Microsoft defines MAX_SIZE as max size of size_t */
+#define SIZE_MAX MAX_SIZE
+#else
+#define SIZE_MAX UINT_MAX
+#endif
+#endif
+
+#ifndef KRB5_CALLCONV
+#  define KRB5_CALLCONV __stdcall
+#  define KRB5_CALLCONV_C __cdecl
+
+/*
+ * Use this to mark an incorrect calling convention that has been
+ * "immortalized" because it was incorrectly exported in a previous
+ * release.
+ */
+
+#  define KRB5_CALLCONV_WRONG KRB5_CALLCONV_C
+
+#endif /* !KRB5_CALLCONV */
+
+#ifndef KRB5_SYSTYPES__
+#define KRB5_SYSTYPES__
+#include <sys/types.h>
+typedef unsigned long	 u_long;      /* Not part of sys/types.h on the pc */
+typedef unsigned int	 u_int;
+typedef unsigned short	 u_short;
+typedef unsigned char	 u_char;
+typedef unsigned int     uint32_t;
+typedef int              int32_t;
+#if _INTEGRAL_MAX_BITS >= 64
+typedef unsigned __int64 uint64_t;
+typedef __int64          int64_t;
+#endif
+#ifndef SSIZE_T_DEFINED
+#ifdef ssize_t
+#undef ssize_t
+#endif
+#ifdef _WIN64
+typedef __int64		 ssize_t;
+#else
+typedef _W64 int 	 ssize_t;
+#endif
+#define SSIZE_T_DEFINED
+#endif
+#endif /* KRB5_SYSTYPES__ */
+
+#define MAXHOSTNAMELEN  512
+#ifndef MAXPATHLEN
+#define MAXPATHLEN      256            /* Also for Windows temp files */
+#endif
+
+#define HAVE_NETINET_IN_H
+#define MSDOS_FILESYSTEM
+#define HAVE_STRING_H 
+#define HAVE_SRAND
+#define HAVE_ERRNO
+#define HAVE_STRDUP
+#define HAVE_GETADDRINFO
+#define HAVE_GETNAMEINFO
+#define NO_USERID
+#define NO_PASSWORD
+#define HAVE_STRERROR
+#define SYS_ERRLIST_DECLARED
+/* if __STDC_VERSION__ >= 199901L this shouldn't be needed */
+#define inline __inline
+#define KRB5_USE_INET6
+#define NEED_INSIXADDR_ANY
+#define ENABLE_THREADS
+
+#define WM_KERBEROS5_CHANGED "Kerberos5 Changed"
+#ifdef KRB4
+#define WM_KERBEROS_CHANGED "Kerberos Changed"
+#endif
+
+/* Kerberos Windows initialization file */
+#define KERBEROS_INI    "kerberos.ini"
+#ifdef CYGNUS
+#define KERBEROS_HLP    "kerbnet.hlp"
+#else
+#define KERBEROS_HLP	"krb5clnt.hlp"
+#endif
+#define INI_DEFAULTS    "Defaults"
+#define   INI_USER        "User"          /* Default user */
+#define   INI_INSTANCE    "Instance"      /* Default instance */
+#define   INI_REALM       "Realm"         /* Default realm */
+#define   INI_POSITION    "Position"
+#define   INI_OPTIONS     "Options"
+#define   INI_DURATION    "Duration"   /* Ticket duration in minutes */
+#define INI_EXPIRATION  "Expiration" /* Action on expiration (alert or beep) */
+#define   INI_ALERT       "Alert"
+#define   INI_BEEP        "Beep"
+#define   INI_FILES       "Files"
+#ifdef KRB4
+#define   INI_KRB_CONF    "krb.conf"     /* Location of krb.conf file */
+#define   DEF_KRB_CONF    "krb.conf"      /* Default name for krb.conf file */
+#else
+#define INI_KRB5_CONF   "krb5.ini"	/* From k5-config.h */
+#define INI_KRB_CONF    INI_KRB5_CONF	/* Location of krb.conf file */
+#define DEF_KRB_CONF    INI_KRB5_CONF	/* Default name for krb.conf file */
+#define INI_TICKETOPTS  "TicketOptions" /* Ticket options */
+#define   INI_FORWARDABLE  "Forwardable" /* get forwardable tickets */
+#define INI_KRB_CCACHE  "krb5cc"       	/* From k5-config.h */
+#endif
+#define INI_KRB_REALMS  "krb.realms"    /* Location of krb.realms file */
+#define DEF_KRB_REALMS  "krb.realms"    /* Default name for krb.realms file */
+#define INI_RECENT_LOGINS "Recent Logins"    
+#define INI_LOGIN       "Login"
+
+#define HAS_VOID_TYPE
+#define HAVE_STDARG_H
+#define HAVE_SYS_TYPES_H
+#define HAVE_STDLIB_H
+
+/* This controls which encryption routines libcrypto will provide */
+#define PROVIDE_DES_CBC_MD5
+#define PROVIDE_DES_CBC_CRC
+#define PROVIDE_DES_CBC_RAW
+#define PROVIDE_DES_CBC_CKSUM
+#define PROVIDE_CRC32
+#define PROVIDE_RSA_MD4
+#define PROVIDE_RSA_MD5
+/* #define PROVIDE_DES3_CBC_SHA */
+/* #define PROVIDE_DES3_CBC_RAW */
+/* #define PROVIDE_NIST_SHA */
+
+/* Ugly. Microsoft, in stdc mode, doesn't support the low-level i/o
+ * routines directly. Rather, they only export the _<function> version.
+ * The following defines works around this problem. 
+ */
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <fcntl.h>
+#include <io.h>
+#include <process.h>
+
+#ifdef NEED_SYSERROR
+/* Only needed by util/et/error_message.c but let's keep the source clean */
+#define sys_nerr        _sys_nerr
+#define sys_errlist     _sys_errlist
+#endif
+
+/*
+ * Functions with slightly different names on the PC
+ */
+#ifndef strcasecmp
+#define strcasecmp   stricmp
+#endif
+#ifndef strncasecmp
+#define strncasecmp  strnicmp
+#endif
+
+HINSTANCE get_lib_instance(void);
+
+#define GETSOCKNAME_ARG2_TYPE	struct sockaddr
+#define GETSOCKNAME_ARG3_TYPE	size_t
+#define GETPEERNAME_ARG2_TYPE	GETSOCKNAME_ARG2_TYPE
+#define GETPEERNAME_ARG3_TYPE	GETSOCKNAME_ARG3_TYPE
+
+#endif /* !RES_ONLY */
+
+#endif /* _WIN32 */
+
+#define THREEPARAMOPEN(x,y,z) open(x,y,z)
+
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#endif
+
+#ifndef KRB5_CALLCONV_C
+#define KRB5_CALLCONV_C
+#endif
+
+#endif /* _KRB5_WIN_MAC_H */
diff --git a/krb5-1-6/src/kadmin/Makefile.in b/krb5-1-6/src/kadmin/Makefile.in
new file mode 100644
index 000000000..5c83425bc
--- /dev/null
+++ b/krb5-1-6/src/kadmin/Makefile.in
@@ -0,0 +1,8 @@
+thisconfigdir=..
+myfulldir=kadmin
+mydir=kadmin
+BUILDTOP=$(REL)..
+LOCAL_SUBDIRS = cli dbutil passwd ktutil server testing
+
+all::
+
diff --git a/krb5-1-6/src/kadmin/cli/Makefile.in b/krb5-1-6/src/kadmin/cli/Makefile.in
new file mode 100644
index 000000000..0ffd29171
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/Makefile.in
@@ -0,0 +1,81 @@
+thisconfigdir=../..
+myfulldir=kadmin/cli
+mydir=kadmin/cli
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+DEFS=
+
+PROG = kadmin
+OBJS = kadmin.o kadmin_ct.o ss_wrapper.o getdate.o keytab.o
+
+SRCS = kadmin.c kadmin_ct.c ss_wrapper.c getdate.c keytab.c
+
+LOCALINCLUDES=-I$(srcdir)
+
+all:: $(PROG).local $(PROG)
+
+$(PROG).local: $(OBJS) $(SS_DEPLIB) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $(PROG).local $(OBJS) $(SS_LIB) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+
+$(PROG): $(OBJS) $(SS_DEPLIB) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $(PROG) $(OBJS) $(SS_LIB) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+
+kadmin_ct.o: kadmin_ct.c
+
+install::
+	$(INSTALL_PROGRAM) $(PROG).local ${DESTDIR}$(ADMIN_BINDIR)/$(PROG).local
+	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
+	$(INSTALL_SCRIPT) $(srcdir)/k5srvutil.sh ${DESTDIR}$(ADMIN_BINDIR)/k5srvutil
+	$(INSTALL_DATA) $(srcdir)/k5srvutil.M ${DESTDIR}$(ADMIN_MANDIR)/k5srvutil.8
+	$(INSTALL_DATA) $(srcdir)/$(PROG).M ${DESTDIR}$(ADMIN_MANDIR)/$(PROG).8
+	$(INSTALL_DATA) $(srcdir)/$(PROG).local.M ${DESTDIR}$(ADMIN_MANDIR)/$(PROG).local.8
+
+generate-files-mac: kadmin_ct.c getdate.c
+
+clean::
+	$(RM) $(PROG).local $(PROG) $(OBJS)
+clean-unix::
+	$(RM) getdate.c kadmin_ct.c
+
+# for testing getdate.y
+datetest: getdate.c
+	$(CC) -o datetest $(ALL_CFLAGS) $(LDFLAGS) $(LDARGS) -DTEST getdate.c
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kadmin.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h kadmin.c kadmin.h
+$(OUTPRE)kadmin_ct.$(OBJEXT): $(COM_ERR_DEPS) $(SS_DEPS) \
+  kadmin_ct.c
+$(OUTPRE)ss_wrapper.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \
+  $(SS_DEPS) kadmin.h ss_wrapper.c
+$(OUTPRE)getdate.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \
+  getdate.c kadmin.h
+$(OUTPRE)keytab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h kadmin.h keytab.c
diff --git a/krb5-1-6/src/kadmin/cli/getdate.y b/krb5-1-6/src/kadmin/cli/getdate.y
new file mode 100644
index 000000000..8b7fc5bae
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/getdate.y
@@ -0,0 +1,1027 @@
+%{
+/*
+**  Originally written by Steven M. Bellovin <smb@research.att.com> while
+**  at the University of North Carolina at Chapel Hill.  Later tweaked by
+**  a couple of people on Usenet.  Completely overhauled by Rich $alz
+**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**  send any email to Rich.
+**
+**  This grammar has nine shift/reduce conflicts.
+**
+**  This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#include "autoconf.h"
+#include <string.h>
+
+/* Since the code of getdate.y is not included in the Emacs executable
+   itself, there is no need to #define static in this file.  Even if
+   the code were included in the Emacs executable, it probably
+   wouldn't do any harm to #undef it here; this will only cause
+   problems if we try to write to a static variable, which I don't
+   think this code needs to do.  */
+#ifdef emacs
+#undef static
+#endif
+
+/* The following block of alloca-related preprocessor directives is here
+   solely to allow compilation by non GNU-C compilers of the C parser
+   produced from this file by old versions of bison.  Newer versions of
+   bison include a block similar to this one in bison.simple.  */
+
+#ifdef __GNUC__
+#undef alloca
+#define alloca __builtin_alloca
+#else
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX /* for Bison */
+ #pragma alloca
+#else
+void *alloca ();
+#endif
+#endif
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if defined(HAVE_STDLIB_H)
+#include <stdlib.h>
+#endif
+
+/* The code at the top of get_date which figures out the offset of the
+   current time zone checks various CPP symbols to see if special
+   tricks are need, but defaults to using the gettimeofday system call.
+   Include <sys/time.h> if that will be used.  */
+
+#if	defined(vms)
+
+#include <types.h>
+#include <time.h>
+
+#else
+
+#include <sys/types.h>
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef timezone
+#undef timezone /* needed for sgi */
+#endif
+
+/*
+** We use the obsolete `struct my_timeb' as part of our interface!
+** Since the system doesn't have it, we define it here;
+** our callers must do likewise.
+*/
+struct my_timeb {
+    time_t		time;		/* Seconds since the epoch	*/
+    unsigned short	millitm;	/* Field not used		*/
+    short		timezone;	/* Minutes west of GMT		*/
+    short		dstflag;	/* Field not used		*/
+};
+#endif	/* defined(vms) */
+
+#if defined (STDC_HEADERS) || defined (USG)
+#include <string.h>
+#endif
+
+/* Some old versions of bison generate parsers that use bcopy.
+   That loses on systems that don't provide the function, so we have
+   to redefine it here.  */
+#ifndef bcopy
+#define bcopy(from, to, len) memcpy ((to), (from), (len))
+#endif
+
+extern struct tm	*gmtime();
+extern struct tm	*localtime();
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+static int getdate_yylex (void);
+static int getdate_yyerror (char *);
+
+
+#define EPOCH		1970
+#define EPOCH_END	2038 /* assumes 32 bits */
+#define HOUR(x)		((time_t)(x) * 60)
+#define SECSPERDAY	(24L * 60L * 60L)
+
+
+/*
+**  An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+    char	*name;
+    int		type;
+    time_t	value;
+} TABLE;
+
+
+/*
+**  Daylight-savings mode:  on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+    DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+**  Meridian:  am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+    MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+**  Global variables.  We could get rid of most of these by using a good
+**  union as the yacc stack.  (This routine was originally written before
+**  yacc had the %union construct.)  Maybe someday; right now we only use
+**  the %union very rarely.
+*/
+static char	*yyInput;
+static DSTMODE	yyDSTmode;
+static time_t	yyDayOrdinal;
+static time_t	yyDayNumber;
+static int	yyHaveDate;
+static int	yyHaveDay;
+static int	yyHaveRel;
+static int	yyHaveTime;
+static int	yyHaveZone;
+static time_t	yyTimezone;
+static time_t	yyDay;
+static time_t	yyHour;
+static time_t	yyMinutes;
+static time_t	yyMonth;
+static time_t	yySeconds;
+static time_t	yyYear;
+static MERIDIAN	yyMeridian;
+static time_t	yyRelMonth;
+static time_t	yyRelSeconds;
+
+%}
+
+%union {
+    time_t		Number;
+    enum _MERIDIAN	Meridian;
+}
+
+%token	tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token	tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST tNEVER
+
+%type	<Number>	tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%type	<Number>	tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type	<Meridian>	tMERIDIAN o_merid
+
+%%
+
+spec	: /* NULL */
+	| spec item
+        | tNEVER {
+	    yyYear = 1970;
+	    yyMonth = 1;
+	    yyDay = 1;
+	    yyHour = yyMinutes = yySeconds = 0;
+	    yyDSTmode = DSToff;
+	    yyTimezone = 0; /* gmt */
+	    yyHaveDate++;
+        }
+	;
+
+item	: time {
+	    yyHaveTime++;
+	}
+	| zone {
+	    yyHaveZone++;
+	}
+	| date {
+	    yyHaveDate++;
+	}
+	| day {
+	    yyHaveDay++;
+	}
+	| rel {
+	    yyHaveRel++;
+	}
+	;
+
+time	: tUNUMBER tMERIDIAN {
+	    yyHour = $1;
+	    yyMinutes = 0;
+	    yySeconds = 0;
+	    yyMeridian = $2;
+	}
+	| tUNUMBER ':' tUNUMBER o_merid {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yySeconds = 0;
+	    yyMeridian = $4;
+	}
+	| tUNUMBER ':' tUNUMBER tSNUMBER {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yyMeridian = MER24;
+	    yyDSTmode = DSToff;
+	    yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+	}
+	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yySeconds = $5;
+	    yyMeridian = $6;
+	}
+	| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yySeconds = $5;
+	    yyMeridian = MER24;
+	    yyDSTmode = DSToff;
+	    yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+	}
+	;
+
+zone	: tZONE {
+	    yyTimezone = $1;
+	    yyDSTmode = DSToff;
+	}
+	| tDAYZONE {
+	    yyTimezone = $1;
+	    yyDSTmode = DSTon;
+	}
+	|
+	  tZONE tDST {
+	    yyTimezone = $1;
+	    yyDSTmode = DSTon;
+	}
+	;
+
+day	: tDAY {
+	    yyDayOrdinal = 1;
+	    yyDayNumber = $1;
+	}
+	| tDAY ',' {
+	    yyDayOrdinal = 1;
+	    yyDayNumber = $1;
+	}
+	| tUNUMBER tDAY {
+	    yyDayOrdinal = $1;
+	    yyDayNumber = $2;
+	}
+	;
+
+date	: tUNUMBER '/' tUNUMBER {
+	    yyMonth = $1;
+	    yyDay = $3;
+	}
+	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+	    yyMonth = $1;
+	    yyDay = $3;
+	    yyYear = $5;
+	}
+	| tUNUMBER tSNUMBER tSNUMBER {
+	    /* ISO 8601 format.  yyyy-mm-dd.  */
+	    yyYear = $1;
+	    yyMonth = -$2;
+	    yyDay = -$3;
+	}
+	| tUNUMBER tMONTH tSNUMBER {
+	    /* e.g. 17-JUN-1992.  */
+	    yyDay = $1;
+	    yyMonth = $2;
+	    yyYear = -$3;
+	}
+	| tMONTH tUNUMBER {
+	    yyMonth = $1;
+	    yyDay = $2;
+	}
+	| tMONTH tUNUMBER ',' tUNUMBER {
+	    yyMonth = $1;
+	    yyDay = $2;
+	    yyYear = $4;
+	}
+	| tUNUMBER tMONTH {
+	    yyMonth = $2;
+	    yyDay = $1;
+	}
+	| tUNUMBER tMONTH tUNUMBER {
+	    yyMonth = $2;
+	    yyDay = $1;
+	    yyYear = $3;
+	}
+	;
+
+rel	: relunit tAGO {
+	    yyRelSeconds = -yyRelSeconds;
+	    yyRelMonth = -yyRelMonth;
+	}
+	| relunit
+	;
+
+relunit	: tUNUMBER tMINUTE_UNIT {
+	    yyRelSeconds += $1 * $2 * 60L;
+	}
+	| tSNUMBER tMINUTE_UNIT {
+	    yyRelSeconds += $1 * $2 * 60L;
+	}
+	| tMINUTE_UNIT {
+	    yyRelSeconds += $1 * 60L;
+	}
+	| tSNUMBER tSEC_UNIT {
+	    yyRelSeconds += $1;
+	}
+	| tUNUMBER tSEC_UNIT {
+	    yyRelSeconds += $1;
+	}
+	| tSEC_UNIT {
+	    yyRelSeconds++;
+	}
+	| tSNUMBER tMONTH_UNIT {
+	    yyRelMonth += $1 * $2;
+	}
+	| tUNUMBER tMONTH_UNIT {
+	    yyRelMonth += $1 * $2;
+	}
+	| tMONTH_UNIT {
+	    yyRelMonth += $1;
+	}
+	;
+
+o_merid	: /* NULL */ {
+	    $$ = MER24;
+	}
+	| tMERIDIAN {
+	    $$ = $1;
+	}
+	;
+
+%%
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+    { "january",	tMONTH,  1 },
+    { "february",	tMONTH,  2 },
+    { "march",		tMONTH,  3 },
+    { "april",		tMONTH,  4 },
+    { "may",		tMONTH,  5 },
+    { "june",		tMONTH,  6 },
+    { "july",		tMONTH,  7 },
+    { "august",		tMONTH,  8 },
+    { "september",	tMONTH,  9 },
+    { "sept",		tMONTH,  9 },
+    { "october",	tMONTH, 10 },
+    { "november",	tMONTH, 11 },
+    { "december",	tMONTH, 12 },
+    { "sunday",		tDAY, 0 },
+    { "monday",		tDAY, 1 },
+    { "tuesday",	tDAY, 2 },
+    { "tues",		tDAY, 2 },
+    { "wednesday",	tDAY, 3 },
+    { "wednes",		tDAY, 3 },
+    { "thursday",	tDAY, 4 },
+    { "thur",		tDAY, 4 },
+    { "thurs",		tDAY, 4 },
+    { "friday",		tDAY, 5 },
+    { "saturday",	tDAY, 6 },
+    { NULL }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+    { "year",		tMONTH_UNIT,	12 },
+    { "month",		tMONTH_UNIT,	1 },
+    { "fortnight",	tMINUTE_UNIT,	14 * 24 * 60 },
+    { "week",		tMINUTE_UNIT,	7 * 24 * 60 },
+    { "day",		tMINUTE_UNIT,	1 * 24 * 60 },
+    { "hour",		tMINUTE_UNIT,	60 },
+    { "minute",		tMINUTE_UNIT,	1 },
+    { "min",		tMINUTE_UNIT,	1 },
+    { "second",		tSEC_UNIT,	1 },
+    { "sec",		tSEC_UNIT,	1 },
+    { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+    { "tomorrow",	tMINUTE_UNIT,	1 * 24 * 60 },
+    { "yesterday",	tMINUTE_UNIT,	-1 * 24 * 60 },
+    { "today",		tMINUTE_UNIT,	0 },
+    { "now",		tMINUTE_UNIT,	0 },
+    { "last",		tUNUMBER,	-1 },
+    { "this",		tMINUTE_UNIT,	0 },
+    { "next",		tUNUMBER,	2 },
+    { "first",		tUNUMBER,	1 },
+/*  { "second",		tUNUMBER,	2 }, */
+    { "third",		tUNUMBER,	3 },
+    { "fourth",		tUNUMBER,	4 },
+    { "fifth",		tUNUMBER,	5 },
+    { "sixth",		tUNUMBER,	6 },
+    { "seventh",	tUNUMBER,	7 },
+    { "eighth",		tUNUMBER,	8 },
+    { "ninth",		tUNUMBER,	9 },
+    { "tenth",		tUNUMBER,	10 },
+    { "eleventh",	tUNUMBER,	11 },
+    { "twelfth",	tUNUMBER,	12 },
+    { "ago",		tAGO,		1 },
+    { "never",		tNEVER,		0 },
+    { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+    { "gmt",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
+    { "ut",	tZONE,     HOUR( 0) },	/* Universal (Coordinated) */
+    { "utc",	tZONE,     HOUR( 0) },
+    { "wet",	tZONE,     HOUR( 0) },	/* Western European */
+    { "bst",	tDAYZONE,  HOUR( 0) },	/* British Summer */
+    { "wat",	tZONE,     HOUR( 1) },	/* West Africa */
+    { "at",	tZONE,     HOUR( 2) },	/* Azores */
+#if	0
+    /* For completeness.  BST is also British Summer, and GST is
+     * also Guam Standard. */
+    { "bst",	tZONE,     HOUR( 3) },	/* Brazil Standard */
+    { "gst",	tZONE,     HOUR( 3) },	/* Greenland Standard */
+#endif
+#if 0
+    { "nft",	tZONE,     HOUR(3.5) },	/* Newfoundland */
+    { "nst",	tZONE,     HOUR(3.5) },	/* Newfoundland Standard */
+    { "ndt",	tDAYZONE,  HOUR(3.5) },	/* Newfoundland Daylight */
+#endif
+    { "ast",	tZONE,     HOUR( 4) },	/* Atlantic Standard */
+    { "adt",	tDAYZONE,  HOUR( 4) },	/* Atlantic Daylight */
+    { "est",	tZONE,     HOUR( 5) },	/* Eastern Standard */
+    { "edt",	tDAYZONE,  HOUR( 5) },	/* Eastern Daylight */
+    { "cst",	tZONE,     HOUR( 6) },	/* Central Standard */
+    { "cdt",	tDAYZONE,  HOUR( 6) },	/* Central Daylight */
+    { "mst",	tZONE,     HOUR( 7) },	/* Mountain Standard */
+    { "mdt",	tDAYZONE,  HOUR( 7) },	/* Mountain Daylight */
+    { "pst",	tZONE,     HOUR( 8) },	/* Pacific Standard */
+    { "pdt",	tDAYZONE,  HOUR( 8) },	/* Pacific Daylight */
+    { "yst",	tZONE,     HOUR( 9) },	/* Yukon Standard */
+    { "ydt",	tDAYZONE,  HOUR( 9) },	/* Yukon Daylight */
+    { "hst",	tZONE,     HOUR(10) },	/* Hawaii Standard */
+    { "hdt",	tDAYZONE,  HOUR(10) },	/* Hawaii Daylight */
+    { "cat",	tZONE,     HOUR(10) },	/* Central Alaska */
+    { "ahst",	tZONE,     HOUR(10) },	/* Alaska-Hawaii Standard */
+    { "nt",	tZONE,     HOUR(11) },	/* Nome */
+    { "idlw",	tZONE,     HOUR(12) },	/* International Date Line West */
+    { "cet",	tZONE,     -HOUR(1) },	/* Central European */
+    { "met",	tZONE,     -HOUR(1) },	/* Middle European */
+    { "mewt",	tZONE,     -HOUR(1) },	/* Middle European Winter */
+    { "mest",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
+    { "swt",	tZONE,     -HOUR(1) },	/* Swedish Winter */
+    { "sst",	tDAYZONE,  -HOUR(1) },	/* Swedish Summer */
+    { "fwt",	tZONE,     -HOUR(1) },	/* French Winter */
+    { "fst",	tDAYZONE,  -HOUR(1) },	/* French Summer */
+    { "eet",	tZONE,     -HOUR(2) },	/* Eastern Europe, USSR Zone 1 */
+    { "bt",	tZONE,     -HOUR(3) },	/* Baghdad, USSR Zone 2 */
+#if 0
+    { "it",	tZONE,     -HOUR(3.5) },/* Iran */
+#endif
+    { "zp4",	tZONE,     -HOUR(4) },	/* USSR Zone 3 */
+    { "zp5",	tZONE,     -HOUR(5) },	/* USSR Zone 4 */
+#if 0
+    { "ist",	tZONE,     -HOUR(5.5) },/* Indian Standard */
+#endif
+    { "zp6",	tZONE,     -HOUR(6) },	/* USSR Zone 5 */
+#if	0
+    /* For completeness.  NST is also Newfoundland Stanard, and SST is
+     * also Swedish Summer. */
+    { "nst",	tZONE,     -HOUR(6.5) },/* North Sumatra */
+    { "sst",	tZONE,     -HOUR(7) },	/* South Sumatra, USSR Zone 6 */
+#endif	/* 0 */
+    { "wast",	tZONE,     -HOUR(7) },	/* West Australian Standard */
+    { "wadt",	tDAYZONE,  -HOUR(7) },	/* West Australian Daylight */
+#if 0
+    { "jt",	tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+    { "cct",	tZONE,     -HOUR(8) },	/* China Coast, USSR Zone 7 */
+    { "jst",	tZONE,     -HOUR(9) },	/* Japan Standard, USSR Zone 8 */
+    { "kst",	tZONE,     -HOUR(9) },	/* Korean Standard */
+#if 0
+    { "cast",	tZONE,     -HOUR(9.5) },/* Central Australian Standard */
+    { "cadt",	tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+    { "east",	tZONE,     -HOUR(10) },	/* Eastern Australian Standard */
+    { "eadt",	tDAYZONE,  -HOUR(10) },	/* Eastern Australian Daylight */
+    { "gst",	tZONE,     -HOUR(10) },	/* Guam Standard, USSR Zone 9 */
+    { "kdt",	tZONE,     -HOUR(10) },	/* Korean Daylight */
+    { "nzt",	tZONE,     -HOUR(12) },	/* New Zealand */
+    { "nzst",	tZONE,     -HOUR(12) },	/* New Zealand Standard */
+    { "nzdt",	tDAYZONE,  -HOUR(12) },	/* New Zealand Daylight */
+    { "idle",	tZONE,     -HOUR(12) },	/* International Date Line East */
+    {  NULL  }
+};
+
+/* ARGSUSED */
+static int
+yyerror(s)
+    char	*s;
+{
+  return 0;
+}
+
+
+static time_t
+ToSeconds(Hours, Minutes, Seconds, Meridian)
+    time_t	Hours;
+    time_t	Minutes;
+    time_t	Seconds;
+    MERIDIAN	Meridian;
+{
+    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+	return -1;
+    switch (Meridian) {
+    case MER24:
+	if (Hours < 0 || Hours > 23)
+	    return -1;
+	return (Hours * 60L + Minutes) * 60L + Seconds;
+    case MERam:
+	if (Hours < 1 || Hours > 12)
+	    return -1;
+	return (Hours * 60L + Minutes) * 60L + Seconds;
+    case MERpm:
+	if (Hours < 1 || Hours > 12)
+	    return -1;
+	return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+    default:
+	abort ();
+    }
+    /* NOTREACHED */
+}
+
+/*
+ * From hh:mm:ss [am|pm] mm/dd/yy [tz], compute and return the number
+ * of seconds since 00:00:00 1/1/70 GMT.
+ */
+static time_t
+Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
+    time_t	Month;
+    time_t	Day;
+    time_t	Year;
+    time_t	Hours;
+    time_t	Minutes;
+    time_t	Seconds;
+    MERIDIAN	Meridian;
+    DSTMODE	DSTmode;
+{
+    static int DaysInMonth[12] = {
+	31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    time_t	tod;
+    time_t	Julian;
+    int		i;
+
+    if (Year < 0)
+	Year = -Year;
+    if (Year < 1900)
+	Year += 1900;
+    DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+		    ? 29 : 28;
+    if (Year < EPOCH
+	|| Year > EPOCH_END
+	|| Month < 1 || Month > 12
+	/* Lint fluff:  "conversion from long may lose accuracy" */
+	|| Day < 1 || Day > DaysInMonth[(int)--Month])
+	 return -1;
+
+    for (Julian = Day - 1, i = 0; i < Month; i++)
+	Julian += DaysInMonth[i];
+    for (i = EPOCH; i < Year; i++)
+	 Julian += 365 + ((i % 4 == 0) && ((Year % 100 != 0) ||
+					   (Year % 400 == 0)));
+    Julian *= SECSPERDAY;
+    Julian += yyTimezone * 60L;
+    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+	return -1;
+    Julian += tod;
+    if (DSTmode == DSTon
+     || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+	Julian -= 60 * 60;
+    return Julian;
+}
+
+
+static time_t
+DSTcorrect(Start, Future)
+    time_t	Start;
+    time_t	Future;
+{
+    time_t	StartDay;
+    time_t	FutureDay;
+
+    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+    return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(Start, DayOrdinal, DayNumber)
+    time_t	Start;
+    time_t	DayOrdinal;
+    time_t	DayNumber;
+{
+    struct tm	*tm;
+    time_t	now;
+
+    now = Start;
+    tm = localtime(&now);
+    now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+    now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+    return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(Start, RelMonth)
+    time_t	Start;
+    time_t	RelMonth;
+{
+    struct tm	*tm;
+    time_t	Month;
+    time_t	Year;
+    time_t	ret;
+
+    if (RelMonth == 0)
+	return 0;
+    tm = localtime(&Start);
+    Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+    Year = Month / 12;
+    Month = Month % 12 + 1;
+    ret = Convert(Month, (time_t)tm->tm_mday, Year,
+		  (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+		  MER24, DSTmaybe);
+    if (ret == -1)
+      return ret;
+    return DSTcorrect(Start, ret);
+}
+
+
+static int
+LookupWord(buff)
+    char		*buff;
+{
+    register char	*p;
+    register char	*q;
+    register const TABLE	*tp;
+    int			i;
+    int			abbrev;
+
+    /* Make it lowercase. */
+    for (p = buff; *p; p++)
+	if (isupper((int) *p))
+	    *p = tolower((int) *p);
+
+    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+	yylval.Meridian = MERam;
+	return tMERIDIAN;
+    }
+    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+	yylval.Meridian = MERpm;
+	return tMERIDIAN;
+    }
+
+    /* See if we have an abbreviation for a month. */
+    if (strlen(buff) == 3)
+	abbrev = 1;
+    else if (strlen(buff) == 4 && buff[3] == '.') {
+	abbrev = 1;
+	buff[3] = '\0';
+    }
+    else
+	abbrev = 0;
+
+    for (tp = MonthDayTable; tp->name; tp++) {
+	if (abbrev) {
+	    if (strncmp(buff, tp->name, 3) == 0) {
+		yylval.Number = tp->value;
+		return tp->type;
+	    }
+	}
+	else if (strcmp(buff, tp->name) == 0) {
+	    yylval.Number = tp->value;
+	    return tp->type;
+	}
+    }
+
+    for (tp = TimezoneTable; tp->name; tp++)
+	if (strcmp(buff, tp->name) == 0) {
+	    yylval.Number = tp->value;
+	    return tp->type;
+	}
+
+    if (strcmp(buff, "dst") == 0) 
+	return tDST;
+
+    for (tp = UnitsTable; tp->name; tp++)
+	if (strcmp(buff, tp->name) == 0) {
+	    yylval.Number = tp->value;
+	    return tp->type;
+	}
+
+    /* Strip off any plural and try the units table again. */
+    i = strlen(buff) - 1;
+    if (buff[i] == 's') {
+	buff[i] = '\0';
+	for (tp = UnitsTable; tp->name; tp++)
+	    if (strcmp(buff, tp->name) == 0) {
+		yylval.Number = tp->value;
+		return tp->type;
+	    }
+	buff[i] = 's';		/* Put back for "this" in OtherTable. */
+    }
+
+    for (tp = OtherTable; tp->name; tp++)
+	if (strcmp(buff, tp->name) == 0) {
+	    yylval.Number = tp->value;
+	    return tp->type;
+	}
+
+    /* Drop out any periods and try the timezone table again. */
+    for (i = 0, p = q = buff; *q; q++)
+	if (*q != '.')
+	    *p++ = *q;
+	else
+	    i++;
+    *p = '\0';
+    if (i)
+	for (tp = TimezoneTable; tp->name; tp++)
+	    if (strcmp(buff, tp->name) == 0) {
+		yylval.Number = tp->value;
+		return tp->type;
+	    }
+
+    return tID;
+}
+
+
+static int
+yylex()
+{
+    register char	c;
+    register char	*p;
+    char		buff[20];
+    int			Count;
+    int			sign;
+
+    for ( ; ; ) {
+	while (isspace((int) *yyInput))
+	    yyInput++;
+
+	c = *yyInput;
+	if (isdigit((int) c) || c == '-' || c == '+') {
+	    if (c == '-' || c == '+') {
+		sign = c == '-' ? -1 : 1;
+		if (!isdigit((int) (*++yyInput)))
+		    /* skip the '-' sign */
+		    continue;
+	    }
+	    else
+		sign = 0;
+	    for (yylval.Number = 0; isdigit((int) (c = *yyInput++)); )
+		yylval.Number = 10 * yylval.Number + c - '0';
+	    yyInput--;
+	    if (sign < 0)
+		yylval.Number = -yylval.Number;
+	    return sign ? tSNUMBER : tUNUMBER;
+	}
+	if (isalpha((int) c)) {
+	    for (p = buff; isalpha((int) (c = *yyInput++)) || c == '.'; )
+		if (p < &buff[sizeof buff - 1])
+		    *p++ = c;
+	    *p = '\0';
+	    yyInput--;
+	    return LookupWord(buff);
+	}
+	if (c != '(')
+	    return *yyInput++;
+	Count = 0;
+	do {
+	    c = *yyInput++;
+	    if (c == '\0')
+		return c;
+	    if (c == '(')
+		Count++;
+	    else if (c == ')')
+		Count--;
+	} while (Count > 0);
+    }
+}
+
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds.  */
+static time_t
+difftm(a, b)
+     struct tm *a, *b;
+{
+  int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+  int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+  return
+    (
+     (
+      (
+       /* difference in day of year */
+       a->tm_yday - b->tm_yday
+       /* + intervening leap days */
+       +  ((ay >> 2) - (by >> 2))
+       -  (ay/100 - by/100)
+       +  ((ay/100 >> 2) - (by/100 >> 2))
+       /* + difference in years * 365 */
+       +  (time_t)(ay-by) * 365
+       )*24 + (a->tm_hour - b->tm_hour)
+      )*60 + (a->tm_min - b->tm_min)
+     )*60 + (a->tm_sec - b->tm_sec);
+}
+
+/* For get_date extern declaration compatibility check... yuck.  */
+#include <krb5.h>
+#include "kadmin.h"
+
+time_t
+get_date(p)
+    char		*p;
+{
+    struct my_timeb	*now = NULL;
+    struct tm		*tm, gmt;
+    struct my_timeb	ftz;
+    time_t		Start;
+    time_t		tod;
+    time_t		delta;
+
+    yyInput = p;
+    if (now == NULL) {
+        now = &ftz;
+
+	ftz.time = time((time_t *) 0);
+
+	if (! (tm = gmtime (&ftz.time)))
+	    return -1;
+	gmt = *tm;	/* Make a copy, in case localtime modifies *tm.  */
+	ftz.timezone = difftm (&gmt, localtime (&ftz.time)) / 60;
+    }
+
+    tm = localtime(&now->time);
+    yyYear = tm->tm_year;
+    yyMonth = tm->tm_mon + 1;
+    yyDay = tm->tm_mday;
+    yyTimezone = now->timezone;
+    yyDSTmode = DSTmaybe;
+    yyHour = 0;
+    yyMinutes = 0;
+    yySeconds = 0;
+    yyMeridian = MER24;
+    yyRelSeconds = 0;
+    yyRelMonth = 0;
+    yyHaveDate = 0;
+    yyHaveDay = 0;
+    yyHaveRel = 0;
+    yyHaveTime = 0;
+    yyHaveZone = 0;
+
+    /*
+     * When yyparse returns, zero or more of yyHave{Time,Zone,Date,Day,Rel} 
+     * will have been incremented.  The value is number of items of
+     * that type that were found; for all but Rel, more than one is
+     * illegal.
+     *
+     * For each yyHave indicator, the following values are set:
+     *
+     * yyHaveTime:
+     *	yyHour, yyMinutes, yySeconds: hh:mm:ss specified, initialized
+     *				      to zeros above
+     *	yyMeridian: MERam, MERpm, or MER24
+     *	yyTimeZone: time zone specified in minutes
+     *  yyDSTmode: DSToff if yyTimeZone is set, otherwise unchanged
+     *		   (initialized above to DSTmaybe)
+     *
+     * yyHaveZone:
+     *  yyTimezone: as above
+     *  yyDSTmode: DSToff if a non-DST zone is specified, otherwise DSTon
+     *	XXX don't understand interaction with yyHaveTime zone info
+     *
+     * yyHaveDay:
+     *	yyDayNumber: 0-6 for Sunday-Saturday
+     *  yyDayOrdinal: val specified with day ("second monday",
+     *		      Ordinal=2), otherwise 1
+     *
+     * yyHaveDate:
+     *	yyMonth, yyDay, yyYear: mm/dd/yy specified, initialized to
+     *				today above
+     *
+     * yyHaveRel:
+     *	yyRelSeconds: seconds specified with MINUTE_UNITs ("3 hours") or
+     *		      SEC_UNITs ("30 seconds")
+     *  yyRelMonth: months specified with MONTH_UNITs ("3 months", "1
+     *		     year")
+     *
+     * The code following yyparse turns these values into a single
+     * date stamp.
+     */
+    if (yyparse()
+     || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+	return -1;
+
+    /*
+     * If an absolute time specified, set Start to the equivalent Unix
+     * timestamp.  Otherwise, set Start to now, and if we do not have
+     * a relatime time (ie: only yyHaveZone), decrement Start to the
+     * beginning of today.
+     *
+     * By having yyHaveDay in the "absolute" list, "next Monday" means
+     * midnight next Monday.  Otherwise, "next Monday" would mean the
+     * time right now, next Monday.  It's not clear to me why the
+     * current behavior is preferred.
+     */
+    if (yyHaveDate || yyHaveTime || yyHaveDay) {
+	Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+		    yyMeridian, yyDSTmode);
+	if (Start < 0)
+	    return -1;
+    }
+    else {
+	Start = now->time;
+	if (!yyHaveRel)
+	    Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+    }
+
+    /*
+     * Add in the relative time specified.  RelativeMonth adds in the
+     * months, accounting for the fact that the actual length of "3
+     * months" depends on where you start counting.
+     *
+     * XXX By having this separate from the previous block, we are
+     * allowing dates like "10:00am 3 months", which means 3 months
+     * from 10:00am today, or even "1/1/99 two days" which means two
+     * days after 1/1/99.
+     *
+     * XXX Shouldn't this only be done if yyHaveRel, just for
+     * thoroughness?
+     */
+    Start += yyRelSeconds;
+    delta = RelativeMonth(Start, yyRelMonth);
+    if (delta == (time_t) -1)
+      return -1;
+    Start += delta;
+
+    /*
+     * Now, if you specified a day of week and counter, add it in.  By
+     * disallowing Date but allowing Time, you can say "5pm next
+     * monday".
+     *
+     * XXX The yyHaveDay && !yyHaveDate restriction should be enforced
+     * above and be able to cause failure.
+     */
+    if (yyHaveDay && !yyHaveDate) {
+	tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+	Start += tod;
+    }
+
+    /* Have to do *something* with a legitimate -1 so it's distinguishable
+     * from the error return value.  (Alternately could set errno on error.) */
+    return Start == -1 ? 0 : Start;
+}
+
+
+#if	defined(TEST)
+
+/* ARGSUSED */
+main(ac, av)
+    int		ac;
+    char	*av[];
+{
+    char	buff[128];
+    time_t	d;
+
+    (void)printf("Enter date, or blank line to exit.\n\t> ");
+    (void)fflush(stdout);
+    while (gets(buff) && buff[0]) {
+	d = get_date(buff, (struct my_timeb *)NULL);
+	if (d == -1)
+	    (void)printf("Bad format - couldn't convert.\n");
+	else
+	    (void)printf("%s", ctime(&d));
+	(void)printf("\t> ");
+	(void)fflush(stdout);
+    }
+    exit(0);
+    /* NOTREACHED */
+}
+#endif	/* defined(TEST) */
diff --git a/krb5-1-6/src/kadmin/cli/k5srvutil.M b/krb5-1-6/src/kadmin/cli/k5srvutil.M
new file mode 100644
index 000000000..b455b7c3c
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/k5srvutil.M
@@ -0,0 +1,58 @@
+.\" Copyright 1989, 2003 by the Massachusetts Institute of Technology.
+.\"
+.TH K5SRVUTIL 8
+.SH NAME
+k5srvutil \- host key table (keytab) manipulation utility
+.SH SYNOPSIS
+k5srvutil
+.B operation
+[
+.B \-i 
+] [ 
+.B \-f filename 
+]
+.SH DESCRIPTION
+.I k5srvutil
+allows a system manager to list or change keys currently in his
+keytab or to add new keys to the keytab.
+.PP
+
+Operation must be one of the following:
+.TP 10n
+.I list
+lists the keys in a keytab showing version number and principal
+name.  
+.TP 10n
+.I change
+changes all the keys in the keytab to new randomly-generated keys,
+updating the keys in the Kerberos server's database to match by using the
+kadmin protocol.  If a key's version number doesn't match the
+version number stored in the Kerberos server's database,  then the operation will fail.  The old keys are retained
+so that existing tickets continue to work.
+If the \-i flag is given, 
+.I k5srvutil
+will prompt for yes or no before changing each key.  If the \-k
+option is used, the old and new keys will be displayed.
+.TP 10n
+.I delold
+Deletes keys that are not the most recent version from the keytab.  This operation
+should be used some time after a change operation to  remove old keys.
+If the \-i flag is used, then the program prompts the user
+whether the old keys associated with each principal should be removed.
+.TP 10n
+.I delete
+deletes particular keys in the keytab, interactively prompting for 
+each key.
+
+.PP
+In all cases, the default file used is /etc/krb5.keytab file 
+ unless this is overridden by the \-f option.
+
+
+.I k5srvutil
+uses the kadmin program to edit the keytab in place.  However, old keys are retained, so
+they are available in case of failure.
+
+.SH SEE ALSO
+kadmin(8), ktutil(8)
+
diff --git a/krb5-1-6/src/kadmin/cli/k5srvutil.sh b/krb5-1-6/src/kadmin/cli/k5srvutil.sh
new file mode 100755
index 000000000..e1284e6af
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/k5srvutil.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+# list_princs keytab
+# returns a list of principals in the keytab
+# sorted and uniquified
+list_princs() {
+    klist -k $keytab | awk '(NR > 3) {print $2}' | sort | uniq
+}
+
+set_command() {
+    if [ x$command != x ] ; then
+	cmd_error Only one command can be specified
+	usage
+	exit 1
+    fi
+    command=$1
+}
+
+#interactive_prompt prompt princ
+# If in interactive mode  return  true if the principal  should be acted on
+# otherwise return true all the time
+interactive_prompt() {
+    if [ $interactive = 0 ] ; then
+	return 0
+    fi
+    printf "%s for %s? [yn]" "$1" "$2"
+    read ans
+    case $ans in
+    n*|N*)
+	return 1
+	;;
+    esac
+    return 0
+    }
+    
+cmd_error() {
+    echo $@ 2>&1
+    }
+
+usage() {
+    echo "Usage: $0 [-i] [-f file] list|change|delete|delold"
+}
+
+
+
+change_key() {
+    princs=`list_princs `
+    for princ in $princs; do
+	if interactive_prompt "Change key " $princ; then
+	    kadmin -k -t $keytab -p $princ -q "ktadd -k $keytab $princ"
+	fi
+    done
+    }
+
+delete_old_keys() {
+    princs=`list_princs `
+    for princ in $princs; do
+	if interactive_prompt "Delete old keys " $princ; then
+	    kadmin -k -t $keytab -p $princ -q "ktrem -k $keytab $princ old"
+	fi
+    done
+    }
+
+delete_keys() {
+    interactive=1
+    princs=`list_princs `
+    for princ in $princs; do
+	if interactive_prompt "Delete all keys " $princ; then
+	    kadmin -p $princ -k -t $keytab -q "ktrem -k $keytab $princ all"
+	fi
+    done
+    }
+
+
+keytab=/etc/krb5.keytab
+interactive=0
+
+while [ $# -gt 0 ] ; do
+    opt=$1
+    shift
+        case $opt in
+	"-f")
+	keytab=$1
+	shift
+	;;
+	"-i")
+	interactive=1
+	;;
+	change|delold|delete|list)
+	set_command $opt
+	;;
+	*)
+	cmd_error Illegal option: $opt
+	usage
+	exit 1
+	;;
+	esac
+done
+	
+
+case $command in
+    change)
+    change_key
+    ;;
+    delold)
+    delete_old_keys
+    ;;
+    delete)
+    delete_keys
+    ;;
+    list)
+    klist -k $keytab
+    ;;
+    *)
+        usage
+	;;
+    esac
diff --git a/krb5-1-6/src/kadmin/cli/kadmin.M b/krb5-1-6/src/kadmin/cli/kadmin.M
new file mode 100644
index 000000000..20958e88e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/kadmin.M
@@ -0,0 +1,869 @@
+.TH KADMIN 8
+.SH NAME
+kadmin \- Kerberos V5 database administration program
+.SH SYNOPSYS
+.TP
+.B kadmin
+.ad l
+[\fB\-O\fP | \fB\-N\fP]
+[\fB\-r\fP \fIrealm\fP] [\fB\-p\fP \fIprincipal\fP] [\fB\-q\fP \fIquery\fP]
+.br
+[[\fB-c\fP \fIcache_name\fP] | [\fB-k\fP [\fB-t\fP
+\fIkeytab\fP]]] [\fB\-w\fP \fIpassword\fP] [\fB\-s\fP
+\fIadmin_server\fP[\fI:port\fP]
+.TP "\w'.B kadmin.local\ 'u"
+.B kadmin.local
+[\fB\-r\fP \fIrealm\fP] [\fB\-p\fP \fIprincipal\fP] [\fB\-q\fP \fIquery\fP]
+.br
+[\fB\-d\fP \fIdbname\fP] [\fB\-e \fI"enc:salt ..."\fP] [\fB-m\fP] [\fB\-x\fP \fIdb_args\fP]
+.ad b
+.SH DESCRIPTION
+.B kadmin
+and
+.B kadmin.local
+are command-line interfaces to the Kerberos V5 KADM5 administration
+system.  Both
+.B kadmin
+and
+.B kadmin.local
+provide identical functionalities; the difference is that
+.B kadmin.local
+runs on the master KDC if the database is db2 and
+does not use Kerberos to authenticate to the
+database. Except as explicitly noted otherwise, 
+this man page will use
+.B kadmin
+to refer to both versions.
+.B kadmin
+provides for the maintenance of Kerberos principals, KADM5 policies, and
+service key tables (keytabs).  
+.PP
+The remote version uses Kerberos authentication and an encrypted RPC, to
+operate securely from anywhere on the network.  It authenticates to the
+KADM5 server using the service principal
+.IR kadmin/admin .
+If the credentials cache contains a ticket for the
+.I kadmin/admin
+principal, and the 
+.B \-c
+.I credentials_cache
+option is specified, that ticket is used to authenticate to KADM5.
+Otherwise, the
+.B -p
+and
+.B -k
+options are used to specify the client Kerberos principal name used to
+authenticate.  Once
+.B kadmin
+has determined the principal name, it requests a
+.I kadmin/admin
+Kerberos service ticket from the KDC, and uses that service ticket to
+authenticate to KADM5.
+.PP
+If the database is db2, the local client
+.BR kadmin.local ,
+is intended to run directly on the master KDC without Kerberos
+authentication.  The local version provides all of the functionality of
+the now obsolete
+.IR kdb5_edit (8),
+except for database dump and load, which is now provided by the
+.IR kdb5_util (8)
+utility.
+.PP
+If the database is LDAP, kadmin.local need not be run on the KDC. 
+.SH OPTIONS
+.TP
+\fB\-r\fP \fIrealm\fP
+Use
+.I realm
+as the default database realm.
+.TP
+\fB\-p\fP \fIprincipal\fP
+Use
+.I principal
+to authenticate.  Otherwise, kadmin will append "/admin" to the primary
+principal name of the default ccache, the value of the
+.SM USER
+environment variable, or the username as obtained with getpwuid, in
+order of preference.
+.TP
+\fB\-k\fP
+Use a keytab to decrypt the KDC response instead of prompting for a
+password on the TTY.  In this case, the default principal will be
+host/\fIhostname\fP.  If there is not a keytab specified with the
+.B \-t
+option, then the default keytab will be used.
+.TP
+\fB\-t\fP \fIkeytab\fP
+Use
+.I keytab
+to decrypt the KDC response.  This can only be used with the
+.B \-k
+option.
+.TP
+\fB\-c\fP \fIcredentials_cache\fP
+Use
+.I credentials_cache
+as the credentials cache.  The
+.I credentials_cache
+should contain a service ticket for the
+.I kadmin/admin
+service; it can be acquired with the
+.IR kinit (1)
+program.  If this option is not specified,
+.B kadmin
+requests a new service ticket from the KDC, and stores it in its own
+temporary ccache.
+.TP
+\fB\-w\fP \fIpassword\fP
+Use
+.I password
+instead of prompting for one on the TTY.  Note:  placing the password
+for a Kerberos principal with administration access into a shell script
+can be dangerous if unauthorized users gain read access to the script.
+.TP
+\fB\-q\fP \fIquery\fP
+pass
+.I query
+directly to
+.BR kadmin ,
+which will perform
+.I query
+and then exit.  This can be useful for writing scripts.
+.TP
+\fB\-d\fP \fIdbname\fP
+Specifies the name of the Kerberos database.
+This option does not apply to the LDAP database.
+.TP
+\fB\-s\fP \fIadmin_server[:port]\fP
+Specifies the admin server which kadmin should contact.
+.TP
+\fB\-m\fP
+Do not authenticate using a keytab.  This option will cause kadmin
+to prompt for the master database password.
+.TP
+\fB\-e\fP \fIenc:salt_list\fP
+Sets the list of encryption types and salt types to be used for any new
+keys created.
+.TP
+.B \-O
+Force use of old AUTH_GSSAPI authentication flavor.
+.TP
+.B \-N
+Prevent fallback to AUTH_GSSAPI authentication flavor.
+.TP
+\fB\-x\fP \fIdb_args\fP
+Specifies the database specific arguments.
+
+Options supported for LDAP database are:
+.RS
+.TP
+\-x host=<hostname>
+specifies the LDAP server to connect to by a LDAP URI.
+.TP
+\-x binddn=<bind_dn>
+.fi
+specifies the DN of the object used by the administration server to bind to the LDAP server.
+This object should have the read and write rights on the realm container, principal container
+and the subtree that is referenced by the realm.
+.TP
+\-x bindpwd=<bind_password>
+.fi
+specifies the password for the above mentioned binddn. It is recommended not to use this option.
+Instead, the password can be stashed using the stashsrvpw command of kdb5_ldap_util.
+.RE
+.SH DATE FORMAT 
+Various commands in kadmin can take a variety of date formats,
+specifying durations or absolute times.  Examples of valid formats are:
+.sp
+.nf
+.RS
+1 month ago
+2 hours ago
+400000 seconds ago
+last year
+this Monday
+next Monday
+yesterday
+tomorrow
+now
+second Monday
+a fortnight ago
+3/31/92 10:00:07 PST
+January 23, 1987 10:05pm
+22:00 GMT
+.RE
+.fi
+.PP
+Dates which do not have the "ago" specifier default to being absolute
+dates, unless they appear in a field where a duration is expected.  In
+that case the time specifier will be interpreted as relative.
+Specifying "ago" in a duration may result in unexpected behavior.
+.PP
+.SH COMMANDS
+.TP
+\fBadd_principal\fP [\fIoptions\fP] \fInewprinc\fP
+creates the principal
+.IR newprinc ,
+prompting twice for a password.  If no policy is specified with the
+-policy option, and the policy named "default" exists, then that
+policy is assigned to the principal; note that the assignment of the
+policy "default" only occurs automatically when a principal is first
+created, so the policy "default" must already exist for the assignment
+to occur.  This assignment of "default" can be suppressed with the
+-clearpolicy option.  This command requires the 
+.I add
+privilege.  This command has the aliases
+.B addprinc
+and
+.BR ank .
+The options are:
+.RS
+.TP
+\fB\-x\fP \fIdb_princ_args\fP
+Denotes the database specific options. The options for LDAP database are:
+.RS
+.TP
+\-x dn=<dn>
+Specifies the LDAP object that will contain the Kerberos principal being 
+created.
+.TP
+\-x linkdn=<dn>
+.fi
+Specifies the LDAP object to which the newly created Kerberos principal object
+will point to.
+.TP
+\-x containerdn=<container_dn>
+Specifies the container object under which the Kerberos principal is to be created. 
+.TP
+\-x tktpolicy=<policy>
+Associates a ticket policy to the Kerberos principal.
+.RE
+.TP
+\fB\-expire\fP \fIexpdate\fP
+expiration date of the principal
+.TP
+\fB\-pwexpire\fP \fIpwexpdate\fP
+password expiration date
+.TP
+\fB\-maxlife\fP \fImaxlife\fP
+maximum ticket life for the principal
+.TP
+\fB\-maxrenewlife\fP \fImaxrenewlife\fP
+maximum renewable life of tickets for the principal
+.TP
+\fB\-kvno\fP \fIkvno\fP
+explicity set the key version number.
+.TP
+\fB\-policy\fP \fIpolicy\fP
+policy used by this principal.  If no policy is supplied, then if the
+policy "default" exists and the -clearpolicy is not also specified,
+then the policy "default" is used; otherwise, the principal 
+will have no policy, and a warning message will be printed.
+.TP
+\fB\-clearpolicy\fP 
+.B -clearpolicy
+prevents the policy "default" from being assigned when 
+.B -policy
+is not specified.  This option has no effect if the policy "default"
+does not exist.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_postdated\fP
+.B -allow_postdated
+prohibits this principal from obtaining postdated tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_POSTDATED
+flag.)
+.B +allow_postdated
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_forwardable\fP
+.B -allow_forwardable
+prohibits this principal from obtaining forwardable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_FORWARDABLE
+flag.)
+.B +allow_forwardable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_renewable\fP
+.B -allow_renewable
+prohibits this principal from obtaining renewable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_RENEWABLE
+flag.)
+.B +allow_renewable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_proxiable\fP
+.B -allow_proxiable
+prohibits this principal from obtaining proxiable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_PROXIABLE
+flag.)
+.B +allow_proxiable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_dup_skey\fP
+.B -allow_dup_skey
+Disables user-to-user authentication for this principal by prohibiting
+this principal from obtaining a session key for another user.  (Sets the
+.SM KRB5_KDB_DISALLOW_DUP_SKEY
+flag.)
+.B +allow_dup_skey
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_preauth\fP
+.B +requires_preauth
+requires this principal to preauthenticate before being allowed to
+kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_PRE_AUTH
+flag.)
+.B -requires_preauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_hwauth\fP
+.B +requires_hwauth
+requires this principal to preauthenticate using a hardware device
+before being allowed to kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_HW_AUTH
+flag.)
+.B -requires_hwauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_svr\fP
+.B -allow_svr
+prohibits the issuance of service tickets for this principal.  (Sets the
+.SM KRB5_KDB_DISALLOW_SVR
+flag.)
+.B +allow_svr
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tgs_req\fP
+.B \-allow_tgs_req
+specifies that a Ticket-Granting Service (TGS) request for a service
+ticket for this principal is not permitted.  This option is useless for
+most things.
+.B +allow_tgs_req
+clears this flag.  The default is
+.BR +allow_tgs_req .
+In effect,
+.B \-allow_tgs_req
+sets the
+.SM KRB5_KDB_DISALLOW_TGT_BASED
+flag on the principal in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tix\fP
+.B \-allow_tix
+forbids the issuance of any tickets for this principal.
+.B +allow_tix
+clears this flag.  The default is
+.BR +allow_tix .
+In effect,
+.B \-allow_tix
+sets the
+.SM KRB5_KDB_DISALLOW_ALL_TIX
+flag on the principal in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBneedchange\fP
+.B +needchange
+sets a flag in attributes field to force a password change;
+.B \-needchange
+clears it.  The default is
+.BR \-needchange .
+In effect,
+.B +needchange
+sets the
+.SM KRB5_KDB_REQUIRES_PWCHANGE
+flag on the principal in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBpassword_changing_service\fP
+.B +password_changing_service
+sets a flag in the attributes field marking this as a password change
+service principal (useless for most things).
+.B \-password_changing_service
+clears the flag.  This flag intentionally has a long name.  The default
+is
+.BR \-password_changing_service .
+In effect,
+.B +password_changing_service
+sets the
+.SM KRB5_KDB_PWCHANGE_SERVICE
+flag on the principal in the database.
+.TP
+.B \-randkey
+sets the key of the principal to a random value
+.TP
+\fB\-pw\fP \fIpassword\fP
+sets the key of the principal to the specified string and does not
+prompt for a password.  Note:  using this option in a shell script can
+be dangerous if unauthorized users gain read access to the script.
+.TP
+\fB\-e\fP \fI"enc:salt ..."\fP
+uses the specified list of enctype\-salttype pairs for setting the key
+of the principal.  The quotes are necessary if there are multiple
+enctype\-salttype pairs.  This will not function against kadmin
+daemons earlier than krb5\-1.2.
+.nf
+.TP
+EXAMPLE:
+kadmin: addprinc tlyu/admin
+WARNING: no policy specified for "tlyu/admin@BLEEP.COM";
+defaulting to no policy.
+Enter password for principal tlyu/admin@BLEEP.COM:
+Re-enter password for principal tlyu/admin@BLEEP.COM:
+Principal "tlyu/admin@BLEEP.COM" created.
+kadmin:
+
+kadmin: addprinc -x dn=cn=mwm_user,o=org mwm_user
+WARNING: no policy specified for "mwm_user@BLEEP.COM";
+defaulting to no policy.
+Enter password for principal mwm_user@BLEEP.COM: 
+Re-enter password for principal mwm_user@BLEEP.COM: 
+Principal "mwm_user@BLEEP.COM" created.
+kadmin:
+
+.TP
+ERRORS:
+KADM5_AUTH_ADD (requires "add" privilege)
+KADM5_BAD_MASK (shouldn't happen)
+KADM5_DUP (principal exists already)
+KADM5_UNK_POLICY (policy does not exist)
+KADM5_PASS_Q_* (password quality violations)
+.fi
+.RE
+.TP
+\fBdelete_principal\fP [\fB-force\fP] \fIprincipal\fP
+deletes the specified principal from the database.  This command prompts
+for deletion, unless the
+.B -force
+option is given. This command requires the
+.I delete
+privilege.  Aliased
+to
+.BR delprinc.
+.sp
+.nf
+.RS
+.TP
+EXAMPLE:
+kadmin: delprinc mwm_user
+Are you sure you want to delete the principal
+"mwm_user@BLEEP.COM"? (yes/no): yes
+Principal "mwm_user@BLEEP.COM" deleted.
+Make sure that you have removed this principal from
+all ACLs before reusing.
+kadmin:
+.TP
+ERRORS:
+KADM5_AUTH_DELETE (reequires "delete" privilege)
+KADM5_UNK_PRINC (principal does not exist)
+.RE
+.fi
+.TP
+\fBmodify_principal\fP [\fIoptions\fP] \fIprincipal\fP
+modifies the specified principal, changing the fields as specified.  The
+options are as above for
+.BR add_principal ,
+except that password changing and flags related to password changing
+are forbidden by this command.  In addition, the option
+.B \-clearpolicy
+will clear the current policy of a principal.  This command requires the
+.I modify
+privilege.  Aliased to
+.BR modprinc .
+.RS
+.TP
+\fB\-x\fP \fIdb_princ_args\fP
+Denotes the database specific options. The options for LDAP database are:
+.RS
+.TP
+\-x tktpolicy=<policy>
+Associates a ticket policy to the Kerberos principal.
+.TP
+\-x linkdn=<dn>
+.fi
+Associates a Kerberos principal with a LDAP object. This option is honored only
+if the Kerberos principal is not already associated with a LDAP object. 
+.RE
+.TP
+ERRORS:
+KADM5_AUTH_MODIFY (requires "modify" privilege)
+KADM5_UNK_PRINC (principal does not exist)
+KADM5_UNK_POLICY (policy does not exist)
+KADM5_BAD_MASK (shouldn't happen)
+.RE
+.fi
+.TP
+\fBchange_password\fP [\fIoptions\fP] \fIprincipal\fP
+changes the password of
+.IR principal .
+Prompts for a new password if neither
+.B \-randkey
+or
+.B \-pw
+is specified.  Requires the
+.I changepw
+privilege, or that the principal that is running the program to be the
+same as the one changed.  Aliased to
+.BR cpw .
+The following options are available:
+.RS
+.TP
+.B \-randkey
+sets the key of the principal to a random value
+.TP
+\fB\-pw\fP \fIpassword\fP
+set the password to the specified string.  Not recommended.
+.TP
+\fB\-e\fP \fI"enc:salt ..."\fP
+uses the specified list of enctype\-salttype pairs for setting the key
+of the principal.  The quotes are necessary if there are multiple
+enctype\-salttype pairs.  This will not function against kadmin
+daemons earlier than krb5\-1.2.
+.TP
+\fB\-keepold \fP 
+Keeps the previous kvno's keys around.  There is no
+easy way to delete the old keys, and this flag is usually not
+necessary except perhaps for TGS keys.  Don't use this flag unless you
+know what you're doing. This option is not supported for the LDAP database.
+.nf
+.TP
+EXAMPLE:
+kadmin: cpw systest
+Enter password for principal systest@BLEEP.COM:
+Re-enter password for principal systest@BLEEP.COM:
+Password for systest@BLEEP.COM changed.
+kadmin:
+.TP
+ERRORS:
+KADM5_AUTH_MODIFY (requires the modify privilege)
+KADM5_UNK_PRINC (principal does not exist)
+KADM5_PASS_Q_* (password policy violation errors)
+KADM5_PADD_REUSE (password is in principal's password
+history)
+KADM5_PASS_TOOSOON (current password minimum life not
+expired)
+.RE
+.fi
+.TP
+\fBget_principal\fP [\fB-terse\fP] \fIprincipal\fP
+gets the attributes of
+.IR principal .
+Requires the
+.I inquire
+privilege, or that the principal that is running the the program to be
+the same as the one being listed.  With the
+.B \-terse
+option, outputs fields as quoted tab-separated strings.  Alias
+.BR getprinc .
+.sp
+.nf
+.RS
+.TP
+EXAMPLES:
+kadmin: getprinc tlyu/admin
+Principal: tlyu/admin@BLEEP.COM
+Expiration date: [never]
+Last password change: Mon Aug 12 14:16:47 EDT 1996
+Password expiration date: [none]
+Maximum ticket life: 0 days 10:00:00
+Maximum renewable life: 7 days 00:00:00
+Last modified: Mon Aug 12 14:16:47 EDT 1996 (bjaspan/admin@BLEEP.COM)
+Last successful authentication: [never]
+Last failed authentication: [never]
+Failed password attempts: 0
+Number of keys: 2
+Key: vno 1, DES cbc mode with CRC-32, no salt
+Key: vno 1, DES cbc mode with CRC-32, Version 4
+Attributes:
+Policy: [none]
+kadmin: getprinc -terse systest
+systest@BLEEP.COM	3	86400	604800	1
+785926535	753241234	785900000
+tlyu/admin@BLEEP.COM	786100034	0	0
+kadmin:
+.TP
+ERRORS:
+KADM5_AUTH_GET (requires the get (inquire) privilege)
+KADM5_UNK_PRINC (principal does not exist)
+.RE
+.fi
+.TP
+\fBlist_principals\fP [\fIexpression\fP]
+Retrieves all or some principal names.  
+.I Expression
+is a shell-style glob expression that can contain the wild-card
+characters \&?, *, and []'s.  All principal names matching the
+expression are printed.  If no expression is provided, all principal
+names are printed.  If the expression does not contain an "@" character,
+an "@" character followed by the local realm is appended to the
+expression.  Requires the
+.I list
+priviledge.  Alias
+.BR listprincs ,
+.BR get_principals ,
+.BR get_princs .
+.nf
+.RS
+.TP
+EXAMPLES:
+kadmin:  listprincs test*
+test3@SECURE-TEST.OV.COM
+test2@SECURE-TEST.OV.COM
+test1@SECURE-TEST.OV.COM
+testuser@SECURE-TEST.OV.COM
+kadmin:
+.RE
+.fi
+.TP
+\fBadd_policy\fP [\fIoptions\fP] \fIpolicy\fP
+adds the named policy to the policy database.  Requires the
+.I add
+privilege.  Aliased to
+.BR addpol .
+The following options are available:
+.RS
+.TP
+\fB\-maxlife\fP \fItime\fP
+sets the maximum lifetime of a password
+.TP
+\fB\-minlife\fP \fItime\fP
+sets the minimum lifetime of a password
+.TP
+\fB\-minlength\fP \fIlength\fP
+sets the minimum length of a password
+.TP
+\fB\-minclasses\fP \fInumber\fP
+sets the minimum number of character classes allowed in a password
+.TP
+\fB\-history\fP \fInumber\fP
+sets the number of past keys kept for a principal. This option is not supported for LDAP database
+.sp
+.nf
+.TP
+EXAMPLES:
+kadmin: add_policy -maxlife "2 days" -minlength 5 guests
+kadmin:
+.TP
+ERRORS:
+KADM5_AUTH_ADD (requires the add privilege)
+KADM5_DUP (policy already exists)
+.fi
+.RE
+.TP
+\fBdelete_policy [\-force]\fP \fIpolicy\fB
+deletes the named policy.  Prompts for confirmation before deletion.
+The command will fail if the policy is in use by any principals.
+Requires the
+.I delete
+privilege.  Alias
+.BR delpol .
+.sp
+.nf
+.RS
+.TP
+EXAMPLE:
+kadmin: del_policy guests
+Are you sure you want to delete the policy "guests"?
+(yes/no): yes
+kadmin:
+.TP
+ERRORS:
+KADM5_AUTH_DELETE (requires the delete privilege)
+KADM5_UNK_POLICY (policy does not exist)
+KADM5_POLICY_REF (reference count on policy is not zero)
+.RE
+.fi
+.TP
+\fBmodify_policy\fP [\fIoptions\fP] \fIpolicy\fP
+modifies the named policy.  Options are as above for
+.BR add_policy .
+Requires the
+.I modify
+privilege.  Alias
+.BR modpol .
+.sp
+.nf
+.RS
+.TP
+ERRORS:
+KADM5_AUTH_MODIFY (requires the modify privilege)
+KADM5_UNK_POLICY (policy does not exist)
+.RE
+.fi
+.TP
+\fBget_policy\fP [\fB\-terse\fP] \fIpolicy\fP
+displays the values of the named policy.  Requires the
+.I inquire
+privilege.  With the
+.B \-terse
+flag, outputs the fields as quoted strings separated by tabs.  Alias
+.BR getpol .
+.nf
+.RS
+.TP
+EXAMPLES:
+kadmin: get_policy admin
+Policy: admin
+Maximum password life: 180 days 00:00:00
+Minimum password life: 00:00:00
+Minimum password length: 6
+Minimum number of password character classes: 2
+Number of old keys kept: 5
+Reference count: 17
+kadmin: get_policy -terse admin
+admin	15552000	0	6	2	5	17
+kadmin:
+.TP
+ERRORS:
+KADM5_AUTH_GET (requires the get privilege)
+KADM5_UNK_POLICY (policy does not exist)
+.RE
+.fi
+.TP
+\fBlist_policies\fP [\fIexpression\fP]
+Retrieves all or some policy names.  
+.I Expression
+is a shell-style glob expression that can contain the wild-card
+characters \&?, *, and []'s.  All policy names matching the expression
+are printed.  If no expression is provided, all existing policy names
+are printed.  Requires the
+.I list
+priviledge.  Alias
+.BR listpols ,
+.BR get_policies ,
+.BR getpols .
+.sp
+.nf
+.RS
+.TP
+EXAMPLES:
+kadmin:  listpols
+test-pol
+dict-only
+once-a-min
+test-pol-nopw
+kadmin:  listpols t*
+test-pol
+test-pol-nopw
+kadmin:
+.RE
+.fi
+.TP
+\fBktadd\fP [\fB\-k\fP \fIkeytab\fP] [\fB\-q\fP] [\fB\-e\fP \fIkeysaltlist\fP]
+.br
+[\fIprincipal\fP | \fB\-glob\fP \fIprinc-exp\fP] [\fI...\fP]
+.br
+Adds a principal or all principals matching
+.I princ-exp
+to a keytab, randomizing each principal's key in the process.  Requires the
+.I inquire
+and 
+.I changepw
+privileges.  An entry for each of the principal's unique encryption types
+is added, ignoring multiple keys with the same encryption type but
+different salt types.  If the
+.B \-k
+argument is not specified, the default keytab
+.I /etc/krb5.keytab
+is used.  If the
+.B \-q
+option is specified, less verbose status information is displayed.
+.sp
+The
+.B -glob
+option requires the
+.I list
+privilege.
+.I princ-exp
+follows the same rules described for the
+.B list_principals
+command.  
+.sp
+.nf
+.RS
+.TP
+EXAMPLE:
+kadmin: ktadd -k /tmp/foo-new-keytab host/foo.mit.edu
+Entry for principal host/foo.mit.edu@ATHENA.MIT.EDU with
+	kvno 3, encryption type DES-CBC-CRC added to keytab
+	WRFILE:/tmp/foo-new-keytab
+kadmin:
+.RE
+.fi
+.TP
+\fBktremove\fP [\fB\-k\fP \fIkeytab\fP] [\fB\-q\fP] \fIprincipal\fP [\fIkvno\fP | \fBall\fP | \fBold\fP]
+Removes entries for the specified principal from a keytab.  Requires no
+permissions, since this does not require database access.  If the string
+"all" is specified, all entries for that principal are removed; if the
+string "old" is specified, all entries for that principal except those
+with the highest kvno are removed.  Otherwise, the value specified is
+parsed as an integer, and all entries whose kvno match that integer are
+removed.  If the
+.B \-k
+argument is not specifeid, the default keytab
+.I /etc/krb5.keytab
+is used.  If the
+.B \-q
+option is specified, less verbose status information is displayed.
+.sp
+.nf
+.RS
+.TP
+EXAMPLE:
+kadmin: ktremove -k /usr/local/var/krb5kdc/kadmind.keytab kadmin/admin
+Entry for principal kadmin/admin with kvno 3 removed
+	from keytab WRFILE:/usr/local/var/krb5kdc/kadmind.keytab.
+kadmin:
+.RE
+.fi
+.SH FILES
+.TP "\w'<dbname>.kadm5.lock\ \ 'u"
+principal.db
+default name for Kerberos principal database
+.TP
+<dbname>.kadm5
+KADM5 administrative database.  (This would be "principal.kadm5", if you
+use the default database name.)  Contains policy information.
+.TP
+<dbname>.kadm5.lock
+lock file for the KADM5 administrative database.  This file works
+backwards from most other lock files.  I.e.,
+.B kadmin
+will exit with an error if this file does
+.I not
+exist.
+.TP
+.B Note:
+The above three files are specific to db2 database.
+.TP 
+kadm5.acl
+file containing list of principals and their
+.B kadmin
+administrative privileges.  See
+.IR kadmind (8)
+for a description.
+.TP
+kadm5.keytab
+keytab file for
+.I kadmin/admin
+principal.
+.TP
+kadm5.dict
+file containing dictionary of strings explicitly disallowed as
+passwords.
+.SH HISTORY
+The
+.B kadmin
+prorgam was originally written by Tom Yu at MIT, as an interface to the
+OpenVision Kerberos administration program.
+.SH SEE ALSO
+.IR kerberos (1),
+.IR kpasswd (1),
+.IR kadmind (8)
+.SH BUGS
+.PP
+Command output needs to be cleaned up.
+
+There is no way to delete a key kept around from a "\-keepold" option
+to a password-changing command, other than to do a password change
+without the "\-keepold" option, which will of course cause problems if
+the key is a TGS key.  There will be more powerful key-manipulation
+commands in the future.
diff --git a/krb5-1-6/src/kadmin/cli/kadmin.c b/krb5-1-6/src/kadmin/cli/kadmin.c
new file mode 100644
index 000000000..ba0bd456b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/kadmin.c
@@ -0,0 +1,1760 @@
+/*
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * kadmin.c: base functions for a kadmin command line interface using
+ * the OVSecure library
+ */
+
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <math.h>
+#include <unistd.h>
+#include <pwd.h>
+/* #include <sys/timeb.h> */
+#include <time.h>
+#include "kadmin.h"
+
+#if defined(USE_LOGIN_LIBRARY)
+#include <Kerberos/KerberosLoginPrivate.h>
+#endif
+
+/* special struct to convert flag names for principals
+   to actual krb5_flags for a principal */
+struct pflag {
+    char *flagname;		/* name of flag as typed to CLI */
+    int flaglen;		/* length of string (not counting -,+) */
+    krb5_flags theflag;		/* actual principal flag to set/clear */
+    int set;			/* 0 means clear, 1 means set (on '-') */
+};
+
+static struct pflag flags[] = {
+{"allow_postdated",	15,	KRB5_KDB_DISALLOW_POSTDATED,	1},
+{"allow_forwardable",	17,	KRB5_KDB_DISALLOW_FORWARDABLE,	1},
+{"allow_tgs_req",	13,	KRB5_KDB_DISALLOW_TGT_BASED,	1},
+{"allow_renewable",	15,	KRB5_KDB_DISALLOW_RENEWABLE,	1},
+{"allow_proxiable",	15,	KRB5_KDB_DISALLOW_PROXIABLE,	1},
+{"allow_dup_skey",	14,	KRB5_KDB_DISALLOW_DUP_SKEY,	1},
+{"allow_tix", 9,	KRB5_KDB_DISALLOW_ALL_TIX,	1},
+{"requires_preauth",	16,	KRB5_KDB_REQUIRES_PRE_AUTH,	0},
+{"requires_hwauth",	15,	KRB5_KDB_REQUIRES_HW_AUTH,	0},
+{"needchange", 10,	KRB5_KDB_REQUIRES_PWCHANGE,	0},
+{"allow_svr", 9,	KRB5_KDB_DISALLOW_SVR, 1},
+{"password_changing_service",	25,	KRB5_KDB_PWCHANGE_SERVICE,	0 },
+{"support_desmd5",	14,	KRB5_KDB_SUPPORT_DESMD5,	0 }
+};
+
+static char *prflags[] = {
+    "DISALLOW_POSTDATED",	/* 0x00000001 */
+    "DISALLOW_FORWARDABLE",	/* 0x00000002 */
+    "DISALLOW_TGT_BASED",	/* 0x00000004 */
+    "DISALLOW_RENEWABLE",	/* 0x00000008 */
+    "DISALLOW_PROXIABLE",	/* 0x00000010 */
+    "DISALLOW_DUP_SKEY",	/* 0x00000020 */
+    "DISALLOW_ALL_TIX",		/* 0x00000040 */
+    "REQUIRES_PRE_AUTH",	/* 0x00000080 */
+    "REQUIRES_HW_AUTH",		/* 0x00000100 */
+    "REQUIRES_PWCHANGE",	/* 0x00000200 */
+    "UNKNOWN_0x00000400",	/* 0x00000400 */
+    "UNKNOWN_0x00000800",	/* 0x00000800 */
+    "DISALLOW_SVR",		/* 0x00001000 */
+    "PWCHANGE_SERVICE",		/* 0x00002000 */
+    "SUPPORT_DESMD5",		/* 0x00004000 */
+    "NEW_PRINC",		/* 0x00008000 */
+};
+
+char *getenv();
+int exit_status = 0;
+char *def_realm = NULL;
+char *whoami = NULL;
+
+void *handle = NULL;
+krb5_context context;
+char *ccache_name = NULL;
+
+int locked = 0;
+
+static void usage()
+{
+    fprintf(stderr,
+	    "Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args]\n"
+	    "\tclnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]\n"
+	    "\tlocal args: [-x db_args]* [-d dbname] [-e \"enc:salt ...\"] [-m]\n"
+	    "where,\n\t[-x db_args]* - any number of database specific arguments.\n"
+	    "\t\t\tLook at each database documentation for supported arguments\n",
+	    whoami);
+    exit(1);
+}
+
+static char *strdur(duration)
+    time_t duration;
+{
+    static char out[50];
+    int neg, days, hours, minutes, seconds;
+
+    if (duration < 0) {
+	duration *= -1;
+	neg = 1;
+    } else
+	neg = 0;
+    days = duration / (24 * 3600);
+    duration %= 24 * 3600;
+    hours = duration / 3600;
+    duration %= 3600;
+    minutes = duration / 60;
+    duration %= 60;
+    seconds = duration;
+    sprintf(out, "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
+	    days, days == 1 ? "day" : "days",
+	    hours, minutes, seconds);
+    return out;
+}
+
+static char *strdate(when)
+    krb5_timestamp when;
+{
+    struct tm *tm;
+    static char out[40];
+
+    time_t lcltim = when;
+    tm = localtime(&lcltim);
+    strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm);
+    return out;
+}
+
+/* this is a wrapper to go around krb5_parse_principal so we can set
+   the default realm up properly */
+static krb5_error_code
+kadmin_parse_name(name, principal)
+    char *name;
+    krb5_principal *principal;
+{
+    char *cp, *fullname;
+    krb5_error_code retval;
+
+    /* assumes def_realm is initialized! */
+    fullname = (char *)malloc(strlen(name) + 1 + strlen(def_realm) + 1);
+    if (fullname == NULL)
+	return ENOMEM;
+    strcpy(fullname, name);
+    cp = strchr(fullname, '@');
+    while (cp) {
+	if (cp - fullname && *(cp - 1) != '\\')
+	    break;
+	else
+	    cp = strchr(cp + 1, '@');
+    }
+    if (cp == NULL) {
+	strcat(fullname, "@");
+	strcat(fullname, def_realm);
+    }
+    retval = krb5_parse_name(context, fullname, principal);
+    free(fullname);
+    return retval;
+}
+
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+				 const char *fmt, va_list args)
+{
+    if (code) {
+	const char *emsg;
+	emsg = krb5_get_error_message (context, code);
+	fprintf (stderr, "%s: %s ", myprog, emsg);
+	krb5_free_error_message (context, emsg);
+    } else {
+	fprintf (stderr, "%s: ", myprog);
+    }
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+}
+
+char *kadmin_startup(argc, argv)
+    int argc;
+    char *argv[];
+{
+    extern char *optarg;
+    char *princstr = NULL, *keytab_name = NULL, *query = NULL;
+    char *password = NULL;
+    char *luser, *canon, *cp;
+    int optchar, freeprinc = 0, use_keytab = 0;
+    struct passwd *pw;
+    kadm5_ret_t retval;
+    krb5_ccache cc;
+    krb5_principal princ;
+    kadm5_config_params params;
+    char **db_args = NULL;
+    int db_args_size = 0;
+    char *db_name = NULL;
+    char *svcname;
+
+    memset((char *) ¶ms, 0, sizeof(params));
+
+#if defined(USE_LOGIN_LIBRARY)
+    /* Turn off all password prompting from the KLL */
+    retval = __KLSetPromptMechanism (klPromptMechanism_None);
+    if (retval) {
+	com_err(whoami, retval, "while calling __KLSetPromptMechanism()");
+	exit(1);
+    }
+#endif
+
+    if (strcmp (whoami, "kadmin.local") == 0)
+	set_com_err_hook(extended_com_err_fn);
+
+    retval = kadm5_init_krb5_context(&context);
+    if (retval) {
+	com_err(whoami, retval, "while initializing krb5 library");
+	exit(1);
+    }
+
+    while ((optchar = getopt(argc, argv, "x:r:p:kq:w:d:s:mc:t:e:ON")) != EOF) {
+	switch (optchar) {
+	case 'x':
+	    db_args_size++;
+	    {
+		char **temp = realloc(db_args, sizeof(char*) * (db_args_size+1));
+		if (temp == NULL) {
+		    fprintf(stderr,"%s: Cannot initialize. Not enough memory\n",
+			    argv[0]);
+		    exit(1);
+		}
+
+		db_args = temp;
+	    }
+	    db_args[db_args_size-1] = optarg;
+	    db_args[db_args_size]   = NULL;
+	    break;
+
+	case 'r':
+	    def_realm = optarg;
+	    break;
+	case 'p':
+	    princstr = optarg;
+	    break;
+	case 'c':
+	    ccache_name = optarg;
+	    break;
+	case 'k':
+	    use_keytab++;
+	    break;
+	case 't':
+	    keytab_name = optarg;
+	    break;
+	case 'w':
+	    password = optarg;
+	    break;
+	case 'q':
+	    query = optarg;
+	    break;
+	case 'd':
+	    /* now db_name is not a seperate argument. It has to be passed as part of the db_args */
+	    if (!db_name) {
+		db_name = malloc(strlen(optarg) + sizeof("dbname="));
+	    } else {
+		db_name = realloc(db_name, strlen(optarg) + sizeof("dbname="));
+	    }
+
+	    strcpy(db_name, "dbname=");
+	    strcat(db_name, optarg);
+
+	    db_args_size++;
+	    {
+		char **temp = realloc(db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
+		if (temp == NULL) {
+		    fprintf(stderr,
+			    "%s: Cannot initialize. Not enough memory\n",
+			    argv[0]);
+		    exit(1);
+		}
+
+		db_args = temp;
+	    }
+	    db_args[db_args_size-1] = db_name;
+	    db_args[db_args_size]   = NULL;
+	    break;
+	case 's':
+	    params.admin_server = optarg;
+	    params.mask |= KADM5_CONFIG_ADMIN_SERVER;
+	    break;
+	case 'm':
+	    params.mkey_from_kbd = 1;
+	    params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+	    break;
+	case 'e':
+	    retval = krb5_string_to_keysalts(optarg,
+					     ", \t",
+					     ":.-",
+					     0,
+					     ¶ms.keysalts,
+					     ¶ms.num_keysalts);
+	    if (retval) {
+		com_err(whoami, retval, "while parsing keysalts %s", optarg);
+		exit(1);
+	    }
+	    params.mask |= KADM5_CONFIG_ENCTYPES;
+	    break;
+	case 'O':
+	    params.mask |= KADM5_CONFIG_OLD_AUTH_GSSAPI;
+	    break;
+	case 'N':
+	    params.mask |= KADM5_CONFIG_AUTH_NOFALLBACK;
+	    break;
+	default:
+	    usage();
+	}
+    }
+    if ((ccache_name && use_keytab) ||
+	(keytab_name && !use_keytab))
+	usage();
+
+    if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) {
+	if (freeprinc)
+	    free(princstr);
+	fprintf(stderr, "%s: unable to get default realm\n", whoami);
+	exit(1);
+    }
+
+    params.mask |= KADM5_CONFIG_REALM;
+    params.realm = def_realm;
+
+    if (params.mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)
+	svcname = KADM5_ADMIN_SERVICE;
+    else
+	svcname = NULL;
+
+    /*
+     * Set cc to an open credentials cache, either specified by the -c
+     * argument or the default.
+     */
+    if (ccache_name == NULL) {
+	if ((retval = krb5_cc_default(context, &cc))) {
+	    com_err(whoami, retval,
+		    "while opening default credentials cache");
+	    exit(1);
+	}
+    } else {
+	if ((retval = krb5_cc_resolve(context, ccache_name, &cc))) {
+	    com_err(whoami, retval,
+		    "while opening credentials cache %s", ccache_name);
+	    exit(1);
+	}
+    }
+
+    /*
+     * If no principal name is specified: If a ccache was specified
+     * and its primary principal name can be read, it is used, else if
+     * a keytab was specified, the principal name is host/hostname,
+     * otherwise append "/admin" to the primary name of the default
+     * ccache, $USER, or pw_name.
+     *
+     * Gee, 100+ lines to figure out the client principal name.  This
+     * should be compressed...
+     */
+
+    if (princstr == NULL) {
+	if (ccache_name != NULL &&
+	    !krb5_cc_get_principal(context, cc, &princ)) {
+	    if ((retval = krb5_unparse_name(context, princ, &princstr))) {
+		com_err(whoami, retval,
+			"while canonicalizing principal name");
+		krb5_free_principal(context, princ);
+		exit(1);
+	    }
+	    krb5_free_principal(context, princ);
+	    freeprinc++;
+	} else if (use_keytab != 0) {
+	    if ((retval = krb5_sname_to_principal(context, NULL,
+						  "host",
+						  KRB5_NT_SRV_HST,
+						  &princ))) {
+		com_err(whoami, retval,
+			"creating host service principal");
+		exit(1);
+	    }
+	    if ((retval = krb5_unparse_name(context, princ, &princstr))) {
+		com_err(whoami, retval,
+			"while canonicalizing principal name");
+		krb5_free_principal(context, princ);
+		exit(1);
+	    }
+	    krb5_free_principal(context, princ);
+	    freeprinc++;
+	} else if (!krb5_cc_get_principal(context, cc, &princ)) {
+	    char *realm = NULL;
+	    if (krb5_unparse_name(context, princ, &canon)) {
+		fprintf(stderr,
+			"%s: unable to canonicalize principal\n", whoami);
+		krb5_free_principal(context, princ);
+		exit(1);
+	    }
+	    /* strip out realm of principal if it's there */
+	    realm = strchr(canon, '@');
+	    while (realm) {
+		if (realm - canon && *(realm - 1) != '\\')
+		    break;
+		else
+		    realm = strchr(realm+1, '@');
+	    }
+	    if (realm)
+		*realm++ = '\0';
+	    cp = strchr(canon, '/');
+	    while (cp) {
+		if (cp - canon && *(cp - 1) != '\\')
+		    break;
+		else
+		    cp = strchr(cp+1, '/');
+	    }
+	    if (cp != NULL)
+		*cp = '\0';
+	    princstr = (char*)malloc(strlen(canon) + 6 /* "/admin" */ +
+				     (realm ? 1 + strlen(realm) : 0) + 1);
+	    if (princstr == NULL) {
+		fprintf(stderr, "%s: out of memory\n", whoami);
+		exit(1);
+	    }
+	    strcpy(princstr, canon);
+	    strcat(princstr, "/admin");
+	    if (realm) {
+		strcat(princstr, "@");
+		strcat(princstr, realm);
+	    }
+	    free(canon);
+	    krb5_free_principal(context, princ);
+	    freeprinc++;
+	} else if ((luser = getenv("USER"))) {
+	    princstr = (char *) malloc(strlen(luser) + 7 /* "/admin@" */
+				       + strlen(def_realm) + 1);
+	    if (princstr == NULL) {
+		fprintf(stderr, "%s: out of memory\n", whoami);
+		exit(1);
+	    }
+	    strcpy(princstr, luser);
+	    strcat(princstr, "/admin");
+	    strcat(princstr, "@");
+	    strcat(princstr, def_realm);
+	    freeprinc++;
+	} else if ((pw = getpwuid(getuid()))) {
+	    princstr = (char *) malloc(strlen(pw->pw_name) + 7 /* "/admin@" */
+				       + strlen(def_realm) + 1);
+	    if (princstr == NULL) {
+		fprintf(stderr, "%s: out of memory\n", whoami);
+		exit(1);
+	    }
+	    strcpy(princstr, pw->pw_name);
+	    strcat(princstr, "/admin@");
+	    strcat(princstr, def_realm);
+	    freeprinc++;
+	} else {
+	    fprintf(stderr, "%s: unable to figure out a principal name\n",
+		    whoami);
+	    exit(1);
+	}
+    }
+
+    retval = krb5_klog_init(context, "admin_server", whoami, 0);
+    if (retval) {
+	com_err(whoami, retval, "while setting up logging");
+	exit(1);
+    }
+
+    /*
+     * Initialize the kadm5 connection.  If we were given a ccache,
+     * use it.  Otherwise, use/prompt for the password.
+     */
+    if (ccache_name) {
+	printf("Authenticating as principal %s with existing credentials.\n",
+	       princstr);
+	retval = kadm5_init_with_creds(princstr, cc,
+				       svcname,
+				       ¶ms,
+				       KADM5_STRUCT_VERSION,
+				       KADM5_API_VERSION_2,
+				       db_args,
+				       &handle);
+    } else if (use_keytab) {
+	if (keytab_name)
+	    printf("Authenticating as principal %s with keytab %s.\n",
+		   princstr, keytab_name);
+	else
+	    printf("Authenticating as principal %s with default keytab.\n",
+		   princstr);
+	retval = kadm5_init_with_skey(princstr, keytab_name,
+				      svcname,
+				      ¶ms,
+				      KADM5_STRUCT_VERSION,
+				      KADM5_API_VERSION_2,
+				      db_args,
+				      &handle);
+    } else {
+	printf("Authenticating as principal %s with password.\n",
+	       princstr);
+	retval = kadm5_init_with_password(princstr, password,
+					  svcname,
+					  ¶ms,
+					  KADM5_STRUCT_VERSION,
+					  KADM5_API_VERSION_2,
+					  db_args,
+					  &handle);
+    }
+    if (retval) {
+	com_err(whoami, retval, "while initializing %s interface", whoami);
+	if (retval == KADM5_BAD_CLIENT_PARAMS ||
+	    retval == KADM5_BAD_SERVER_PARAMS)
+	    usage();
+	exit(1);
+    }
+    if (freeprinc)
+	free(princstr);
+
+    if (db_name)
+	free(db_name), db_name=NULL;
+
+    if (db_args)
+	free(db_args), db_args=NULL;
+
+    if ((retval = krb5_cc_close(context, cc))) {
+	com_err(whoami, retval, "while closing ccache %s",
+		ccache_name);
+	exit(1);
+    }
+
+    /* register the WRFILE keytab type and set it as the default */
+    {
+#define DEFAULT_KEYTAB "WRFILE:/etc/krb5.keytab"
+	/* XXX krb5_defkeyname is an internal library global and
+	   should go away */
+	extern char *krb5_defkeyname;
+	krb5_defkeyname = DEFAULT_KEYTAB;
+    }
+
+    return query;
+}
+
+int quit()
+{
+    kadm5_ret_t retval;
+
+    if (locked) {
+	retval = kadm5_unlock(handle);
+	if (retval) {
+	    com_err("quit", retval, "while unlocking locked database");
+	    return 1;
+	}
+	locked = 0;
+    }
+
+    kadm5_destroy(handle);
+    if (ccache_name != NULL) {
+	fprintf(stderr,
+		"\n\a\a\aAdministration credentials NOT DESTROYED.\n");
+    }
+
+    /* insert more random cleanup here */
+    krb5_klog_close(context);
+    krb5_free_context(context);
+    return 0;
+}
+
+void kadmin_lock(argc, argv)
+    int argc;
+    char *argv[];
+{
+    kadm5_ret_t retval;
+
+    if (locked)
+	return;
+    retval = kadm5_lock(handle);
+    if (retval) {
+	com_err("lock", retval, "");
+	return;
+    }
+    locked = 1;
+}
+
+void kadmin_unlock(argc, argv)
+    int argc;
+    char *argv[];
+{
+    kadm5_ret_t retval;
+
+    if (!locked)
+	return;
+    retval = kadm5_unlock(handle);
+    if (retval) {
+	com_err("unlock", retval, "");
+	return;
+    }
+    locked = 0;
+}
+
+void kadmin_delprinc(argc, argv)
+    int argc;
+    char *argv[];
+{
+    kadm5_ret_t retval;
+    krb5_principal princ;
+    char *canon;
+    char reply[5];
+
+    if (! (argc == 2 ||
+	   (argc == 3 && !strcmp("-force", argv[1])))) {
+	fprintf(stderr, "usage: delete_principal [-force] principal\n");
+	return;
+    }
+    retval = kadmin_parse_name(argv[argc - 1], &princ);
+    if (retval) {
+	com_err("delete_principal", retval, "while parsing principal name");
+	return;
+    }
+    retval = krb5_unparse_name(context, princ, &canon);
+    if (retval) {
+	com_err("delete_principal", retval,
+		"while canonicalizing principal");
+	krb5_free_principal(context, princ);
+	return;
+    }
+    if (argc == 2) {
+	printf("Are you sure you want to delete the principal \"%s\"? (yes/no): ", canon);
+	fgets(reply, sizeof (reply), stdin);
+	if (strcmp("yes\n", reply)) {
+	    fprintf(stderr, "Principal \"%s\" not deleted\n", canon);
+	    free(canon);
+	    krb5_free_principal(context, princ);
+	    return;
+	}
+    }
+    retval = kadm5_delete_principal(handle, princ);
+    krb5_free_principal(context, princ);
+    if (retval) {
+	com_err("delete_principal", retval,
+		"while deleteing principal \"%s\"", canon);
+	free(canon);
+	return;
+    }
+    printf("Principal \"%s\" deleted.\nMake sure that you have removed this principal from all ACLs before reusing.\n", canon);
+    free(canon);
+    return;
+}
+
+void kadmin_cpw(argc, argv)
+    int argc;
+    char *argv[];
+{
+    kadm5_ret_t retval;
+    static char newpw[1024];
+    static char prompt1[1024], prompt2[1024];
+    char *canon;
+    char *pwarg = NULL;
+    int n_ks_tuple = 0, randkey = 0;
+    krb5_boolean keepold = FALSE;
+    krb5_key_salt_tuple *ks_tuple = NULL;
+    krb5_principal princ;
+    char **db_args = NULL;
+    int db_args_size = 0;
+
+
+    if (argc < 2) {
+	goto usage;
+    }
+    for (argv++, argc--; argc > 1; argc--, argv++) {
+	if (!strcmp("-x", *argv)) {
+	    argc--;
+	    if (argc < 1) {
+		fprintf(stderr, "change_password: missing db argument\n");
+		goto usage;
+	    }
+	    db_args_size++;
+	    {
+		char **temp = realloc(db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
+		if (temp == NULL) {
+		    fprintf(stderr,"change_password: Not enough memory\n");
+		    free(db_args), db_args = NULL;
+		    exit(1);
+		}
+
+		db_args = temp;
+	    }
+	    db_args[db_args_size-1] = *++argv;
+	    db_args[db_args_size]   = NULL;
+	    continue;
+	}
+	if (!strcmp("-pw", *argv)) {
+	    argc--;
+	    if (argc < 1) {
+		fprintf(stderr, "change_password: missing password arg\n");
+		goto usage;
+	    }
+	    pwarg = *++argv;
+	    continue;
+	}
+	if (!strcmp("-randkey", *argv)) {
+	    randkey++;
+	    continue;
+	}
+	if (!strcmp("-keepold", *argv)) {
+	    keepold = TRUE;
+	    continue;
+	}
+	if (!strcmp("-e", *argv)) {
+	    argc--;
+	    if (argc < 1) {
+		fprintf(stderr,
+			"change_password: missing keysaltlist arg\n");
+		goto usage;
+	    }
+	    retval = krb5_string_to_keysalts(*++argv, ", \t", ":.-", 0,
+					     &ks_tuple, &n_ks_tuple);
+	    if (retval) {
+		com_err("change_password", retval,
+			"while parsing keysalts %s", *argv);
+		return;
+	    }
+	    continue;
+	}
+	goto usage;
+    }
+    if (*argv == NULL) {
+	com_err("change_password", 0, "missing principal name");
+	goto usage;
+    }
+    retval = kadmin_parse_name(*argv, &princ);
+    if (retval) {
+	com_err("change_password", retval, "while parsing principal name");
+	if (ks_tuple != NULL)
+	    free(ks_tuple);
+	if (db_args) free(db_args);
+	return;
+    }
+    retval = krb5_unparse_name(context, princ, &canon);
+    if (retval) {
+	com_err("change_password", retval, "while canonicalizing principal");
+	krb5_free_principal(context, princ);
+	if (ks_tuple != NULL)
+	    free(ks_tuple);
+	if (db_args) free(db_args);
+	return;
+    }
+    if (pwarg != NULL) {
+	if (keepold || ks_tuple != NULL) {
+	    retval = kadm5_chpass_principal_3(handle, princ, keepold,
+					      n_ks_tuple, ks_tuple, pwarg);
+	    if (ks_tuple != NULL)
+		free(ks_tuple);
+	} else {
+	    retval = kadm5_chpass_principal(handle, princ, pwarg);
+	}
+	krb5_free_principal(context, princ);
+	if (retval) {
+	    com_err("change_password", retval,
+		    "while changing password for \"%s\".", canon);
+	    free(canon);
+	    if (db_args) free(db_args);
+	    return;
+	}
+	printf("Password for \"%s\" changed.\n", canon);
+	free(canon);
+	if (db_args) free(db_args);
+	return;
+    } else if (randkey) {
+	if (keepold || ks_tuple != NULL) {
+	    retval = kadm5_randkey_principal_3(handle, princ, keepold,
+					       n_ks_tuple, ks_tuple,
+					       NULL, NULL);
+	    if (ks_tuple != NULL)
+		free(ks_tuple);
+	} else {
+	    retval = kadm5_randkey_principal(handle, princ, NULL, NULL);
+	}
+	krb5_free_principal(context, princ);
+	if (retval) {
+	    com_err("change_password", retval,
+		    "while randomizing key for \"%s\".", canon);
+	    free(canon);
+	    if (db_args) free(db_args);
+	    return;
+	}
+	printf("Key for \"%s\" randomized.\n", canon);
+	free(canon);
+	if (db_args) free(db_args);
+	return;
+    } else if (argc == 1) {
+	unsigned int i = sizeof (newpw) - 1;
+
+	sprintf(prompt1, "Enter password for principal \"%.900s\"",
+		*argv);
+	sprintf(prompt2,
+		"Re-enter password for principal \"%.900s\"",
+		*argv);
+	retval = krb5_read_password(context, prompt1, prompt2,
+				    newpw, &i);
+	if (retval) {
+	    com_err("change_password", retval,
+		    "while reading password for \"%s\".", canon);
+	    free(canon);
+	    if (ks_tuple != NULL)
+		free(ks_tuple);
+	    krb5_free_principal(context, princ);
+	    if (db_args) free(db_args);
+	    return;
+	}
+	if (keepold || ks_tuple != NULL) {
+	    retval = kadm5_chpass_principal_3(handle, princ, keepold,
+					      n_ks_tuple, ks_tuple,
+					      newpw);
+	    if (ks_tuple != NULL)
+		free(ks_tuple);
+	} else {
+	    retval = kadm5_chpass_principal(handle, princ, newpw);
+	}
+	krb5_free_principal(context, princ);
+	memset(newpw, 0, sizeof (newpw));
+	if (retval) {
+	    com_err("change_password", retval,
+		    "while changing password for \"%s\".", canon);
+	    free(canon);
+	    if (db_args) free(db_args);
+	    return;
+	}
+	printf("Password for \"%s\" changed.\n", canon);
+	free(canon);
+	if (db_args) free(db_args);
+	return;
+    } else {
+	free(canon);
+	krb5_free_principal(context, princ);
+    usage:
+	if (db_args) free(db_args);
+	if (ks_tuple != NULL)
+	    free(ks_tuple);
+	fprintf(stderr,
+		"usage: change_password [-randkey] [-keepold] "
+		"[-e keysaltlist] [-pw password] "
+		"principal\n");
+	return;
+    }
+}
+
+static void
+kadmin_free_tl_data(kadm5_principal_ent_t princ)
+{
+    krb5_tl_data *tl_data = princ->tl_data;
+    int n_tl_data         = princ->n_tl_data;
+    int i;
+
+    princ->n_tl_data = 0;
+    princ->tl_data   = NULL;
+
+    for (i = 0; tl_data && (i < n_tl_data); i++) {
+	krb5_tl_data *next = tl_data->tl_data_next;
+	if (tl_data->tl_data_contents)
+	    free(tl_data->tl_data_contents);
+	free(tl_data);
+	tl_data = next;
+    }
+}
+
+#define KRB5_TL_DB_ARGS 0x7fff
+static int
+kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey,
+			ks_tuple, n_ks_tuple, caller)
+    int argc;
+    char *argv[];
+    kadm5_principal_ent_t oprinc;
+    long *mask;
+    char **pass;
+    int *randkey;
+    krb5_key_salt_tuple **ks_tuple;
+    int *n_ks_tuple;
+    char *caller;
+{
+    int i, j, attrib_set;
+    time_t date;
+    time_t now;
+    krb5_error_code retval;
+    krb5_tl_data *tl_data, *tail = NULL;
+
+    *mask = 0;
+    *pass = NULL;
+    *n_ks_tuple = 0;
+    *ks_tuple = NULL;
+    time(&now);
+    *randkey = 0;
+    for (i = 1; i < argc - 1; i++) {
+	attrib_set = 0;
+	if (strlen(argv[i]) == 2 &&
+	    !strcmp("-x",argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+
+	    tl_data = malloc(sizeof(krb5_tl_data));
+	    if (tl_data == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return ENOMEM;
+	    }
+
+	    memset(tl_data, 0, sizeof(krb5_tl_data));
+	    tl_data->tl_data_type = KRB5_TL_DB_ARGS;
+	    tl_data->tl_data_length  = strlen(argv[i])+1;
+	    tl_data->tl_data_contents = strdup(argv[i]);
+
+	    if (tail) {
+		tail->tl_data_next = tl_data;
+	    } else {
+		oprinc->tl_data = tl_data;
+	    }
+	    tail = tl_data;
+	    oprinc->n_tl_data++;
+
+	    if (tl_data->tl_data_contents == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return ENOMEM;
+	    }
+	    *mask |= KADM5_TL_DATA;
+	    continue;
+	}
+	if (strlen(argv[i]) == 7 &&
+	    !strcmp("-expire", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		date = get_date(argv[i]);
+		if (date == (time_t)-1) {
+		    fprintf(stderr, "Invalid date specification \"%s\".\n",
+			    argv[i]);
+		    return -1;
+		}
+		oprinc->princ_expire_time = date;
+		*mask |= KADM5_PRINC_EXPIRE_TIME;
+		continue;
+	    }
+	}
+	if (strlen(argv[i]) == 9 &&
+	    !strcmp("-pwexpire", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		date = get_date(argv[i]);
+		if (date == (time_t)-1) {
+		    fprintf(stderr, "Invalid date specification \"%s\".\n",
+			    argv[i]);
+		    return -1;
+		}
+		oprinc->pw_expiration = date;
+		*mask |= KADM5_PW_EXPIRATION;
+		continue;
+	    }
+	}
+	if (strlen(argv[i]) == 8 &&
+	    !strcmp("-maxlife", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		date = get_date(argv[i]);
+		if (date == (time_t)-1) {
+		    fprintf(stderr, "Invalid date specification \"%s\".\n",
+			    argv[i]);
+		    return -1;
+		}
+		oprinc->max_life = date - now;
+		*mask |= KADM5_MAX_LIFE;
+		continue;
+	    }
+	}
+	if (strlen(argv[i]) == 13 &&
+	    !strcmp("-maxrenewlife", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		date = get_date(argv[i]);
+		if (date == (time_t)-1) {
+		    fprintf(stderr, "Invalid date specification \"%s\".\n",
+			    argv[i]);
+		    return -1;
+		}
+		oprinc->max_renewable_life = date - now;
+		*mask |= KADM5_MAX_RLIFE;
+		continue;
+	    }
+	}
+	if (strlen(argv[i]) == 5 &&
+	    !strcmp("-kvno", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		oprinc->kvno = atoi(argv[i]);
+		*mask |= KADM5_KVNO;
+		continue;
+	    }
+	}
+	if (strlen(argv[i]) == 7 &&
+	    !strcmp("-policy", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		oprinc->policy = argv[i];
+		*mask |= KADM5_POLICY;
+		continue;
+	    }
+	}
+	if (strlen(argv[i]) == 12 &&
+	    !strcmp("-clearpolicy", argv[i])) {
+	    oprinc->policy = NULL;
+	    *mask |= KADM5_POLICY_CLR;
+	    continue;
+	}
+	if (strlen(argv[i]) == 3 &&
+	    !strcmp("-pw", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		*pass = argv[i];
+		continue;
+	    }
+	}
+	if (strlen(argv[i]) == 8 &&
+	    !strcmp("-randkey", argv[i])) {
+	    ++*randkey;
+	    continue;
+	}
+	if (!strcmp("-e", argv[i])) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		retval = krb5_string_to_keysalts(argv[i], ", \t", ":.-", 0,
+						 ks_tuple, n_ks_tuple);
+		if (retval) {
+		    com_err(caller, retval,
+			    "while parsing keysalts %s", argv[i]);
+		    return -1;
+		}
+	    }
+	    continue;
+	}
+	for (j = 0; j < sizeof (flags) / sizeof (struct pflag); j++) {
+	    if (strlen(argv[i]) == flags[j].flaglen + 1 &&
+		!strcmp(flags[j].flagname,
+			&argv[i][1] /* strip off leading + or - */)) {
+		if ((flags[j].set && argv[i][0] == '-') ||
+		    (!flags[j].set && argv[i][0] == '+')) {
+		    oprinc->attributes |= flags[j].theflag;
+		    *mask |= KADM5_ATTRIBUTES;
+		    attrib_set++;
+		    break;
+		} else if ((flags[j].set && argv[i][0] == '+') ||
+			   (!flags[j].set && argv[i][0] == '-')) {
+		    oprinc->attributes &= ~flags[j].theflag;
+		    *mask |= KADM5_ATTRIBUTES;
+		    attrib_set++;
+		    break;
+		} else {
+		    return -1;
+		}
+	    }
+	}
+	if (!attrib_set)
+	    return -1;		/* nothing was parsed */
+    }
+    if (i != argc - 1) {
+	return -1;
+    }
+    retval = kadmin_parse_name(argv[i], &oprinc->principal);
+    if (retval) {
+	com_err(caller, retval, "while parsing principal");
+	return -1;
+    }
+    return 0;
+}
+
+static void
+kadmin_addprinc_usage(func)
+    char *func;
+{
+    fprintf(stderr, "usage: %s [options] principal\n", func);
+    fprintf(stderr, "\toptions are:\n");
+    fprintf(stderr, "\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] [-clearpolicy] [-randkey]\n\t\t[-pw password] [-maxrenewlife maxrenewlife]\n\t\t[-e keysaltlist]\n\t\t[{+|-}attribute]\n");
+    fprintf(stderr, "\tattributes are:\n");
+    fprintf(stderr, "%s%s%s",
+	    "\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n",
+	    "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n",
+	    "\t\trequires_hwauth needchange allow_svr password_changing_service\n"
+	    "\nwhere,\n\t[-x db_princ_args]* - any number of database specific arguments.\n"
+	    "\t\t\tLook at each database documentation for supported arguments\n");
+}
+
+static void
+kadmin_modprinc_usage(func)
+    char *func;
+{
+    fprintf(stderr, "usage: %s [options] principal\n", func);
+    fprintf(stderr, "\toptions are:\n");
+    fprintf(stderr, "\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] [{+|-}attribute]\n");
+    fprintf(stderr, "\tattributes are:\n");
+    fprintf(stderr, "%s%s%s",
+	    "\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n",
+	    "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n",
+	    "\t\trequires_hwauth needchange allow_svr password_changing_service\n"
+	    "\nwhere,\n\t[-x db_princ_args]* - any number of database specific arguments.\n"
+	    "\t\t\tLook at each database documentation for supported arguments\n"
+	);
+}
+
+void kadmin_addprinc(argc, argv)
+    int argc;
+    char *argv[];
+{
+    kadm5_principal_ent_rec princ;
+    kadm5_policy_ent_rec defpol;
+    long mask;
+    int randkey = 0, i;
+    int n_ks_tuple;
+    krb5_key_salt_tuple *ks_tuple;
+    char *pass, *canon;
+    krb5_error_code retval;
+    static char newpw[1024], dummybuf[256];
+    static char prompt1[1024], prompt2[1024];
+
+    if (dummybuf[0] == 0) {
+	for (i = 0; i < 256; i++)
+	    dummybuf[i] = (i+1) % 256;
+    }
+
+    /* Zero all fields in request structure */
+    memset(&princ, 0, sizeof(princ));
+
+    princ.attributes = 0;
+    if (kadmin_parse_princ_args(argc, argv,
+				&princ, &mask, &pass, &randkey,
+				&ks_tuple, &n_ks_tuple,
+				"add_principal")) {
+	kadmin_addprinc_usage("add_principal");
+	kadmin_free_tl_data(&princ); /* need to free ks_tuple also??? */
+	return;
+    }
+
+    retval = krb5_unparse_name(context, princ.principal, &canon);
+    if (retval) {
+	com_err("add_principal",
+		retval, "while canonicalizing principal");
+	krb5_free_principal(context, princ.principal);
+	if (ks_tuple != NULL)
+	    free(ks_tuple);
+	kadmin_free_tl_data(&princ);
+	return;
+    }
+
+    /*
+     * If -policy was not specified, and -clearpolicy was not
+     * specified, and the policy "default" exists, assign it.  If
+     * -clearpolicy was specified, then KADM5_POLICY_CLR should be
+     * unset, since it is never valid for kadm5_create_principal.
+     */
+    if ((! (mask & KADM5_POLICY)) &&
+	(! (mask & KADM5_POLICY_CLR))) {
+	if (! kadm5_get_policy(handle, "default", &defpol)) {
+	    fprintf(stderr,
+		    "NOTICE: no policy specified for %s; assigning \"default\"\n",
+		    canon);
+	    princ.policy = "default";
+	    mask |= KADM5_POLICY;
+	    (void) kadm5_free_policy_ent(handle, &defpol);
+	} else
+	    fprintf(stderr,
+		    "WARNING: no policy specified for %s; defaulting to no policy\n",
+		    canon);
+    }
+    mask &= ~KADM5_POLICY_CLR;
+
+    if (randkey) {		/* do special stuff if -randkey specified */
+	princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; /* set notix */
+	mask |= KADM5_ATTRIBUTES;
+	pass = dummybuf;
+    } else if (pass == NULL) {
+	unsigned int sz = sizeof (newpw) - 1;
+
+	sprintf(prompt1, "Enter password for principal \"%.900s\"",
+		canon);
+	sprintf(prompt2,
+		"Re-enter password for principal \"%.900s\"",
+		canon);
+	retval = krb5_read_password(context, prompt1, prompt2,
+				    newpw, &sz);
+	if (retval) {
+	    com_err("add_principal", retval,
+		    "while reading password for \"%s\".", canon);
+	    free(canon);
+	    krb5_free_principal(context, princ.principal);
+	    kadmin_free_tl_data(&princ);
+	    return;
+	}
+	pass = newpw;
+    }
+    mask |= KADM5_PRINCIPAL;
+    if (ks_tuple != NULL) {
+	retval = kadm5_create_principal_3(handle, &princ, mask,
+					  n_ks_tuple, ks_tuple, pass);
+    } else {
+	retval = kadm5_create_principal(handle, &princ, mask, pass);
+    }
+    if (retval) {
+	com_err("add_principal", retval, "while creating \"%s\".",
+		canon);
+	krb5_free_principal(context, princ.principal);
+	free(canon);
+	if (ks_tuple != NULL)
+	    free(ks_tuple);
+	kadmin_free_tl_data(&princ);
+	return;
+    }
+    if (randkey) {		/* more special stuff for -randkey */
+	if (ks_tuple != NULL) {
+	    retval = kadm5_randkey_principal_3(handle, princ.principal,
+					       FALSE,
+					       n_ks_tuple, ks_tuple,
+					       NULL, NULL);
+	} else {
+	    retval = kadm5_randkey_principal(handle, princ.principal,
+					     NULL, NULL);
+	}
+	if (retval) {
+	    com_err("add_principal", retval,
+		    "while randomizing key for \"%s\".", canon);
+	    krb5_free_principal(context, princ.principal);
+	    free(canon);
+	    if (ks_tuple != NULL)
+		free(ks_tuple);
+	    kadmin_free_tl_data(&princ);
+	    return;
+	}
+	princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX;	/* clear notix */
+	mask = KADM5_ATTRIBUTES;
+	retval = kadm5_modify_principal(handle, &princ, mask);
+	if (retval) {
+	    com_err("add_principal", retval,
+		    "while clearing DISALLOW_ALL_TIX for \"%s\".", canon);
+	    krb5_free_principal(context, princ.principal);
+	    free(canon);
+	    if (ks_tuple != NULL)
+		free(ks_tuple);
+	    kadmin_free_tl_data(&princ);
+	    return;
+	}
+    }
+    krb5_free_principal(context, princ.principal);
+    printf("Principal \"%s\" created.\n", canon);
+    if (ks_tuple != NULL)
+	free(ks_tuple);
+    free(canon);
+    kadmin_free_tl_data(&princ);
+
+}
+
+void kadmin_modprinc(argc, argv)
+    int argc;
+    char *argv[];
+{
+    kadm5_principal_ent_rec princ, oldprinc;
+    krb5_principal kprinc;
+    long mask;
+    krb5_error_code retval;
+    char *pass, *canon;
+    int randkey = 0;
+    int n_ks_tuple = 0;
+    krb5_key_salt_tuple *ks_tuple;
+
+    if (argc < 2) {
+	kadmin_modprinc_usage("modify_principal");
+	return;
+    }
+
+    memset(&oldprinc, 0, sizeof(oldprinc));
+    memset(&princ, 0, sizeof(princ));
+
+    retval = kadmin_parse_name(argv[argc - 1], &kprinc);
+    if (retval) {
+	com_err("modify_principal", retval, "while parsing principal");
+	return;
+    }
+    retval = krb5_unparse_name(context, kprinc, &canon);
+    if (retval) {
+	com_err("modify_principal", retval,
+		"while canonicalizing principal");
+	krb5_free_principal(context, kprinc);
+	return;
+    }
+    retval = kadm5_get_principal(handle, kprinc, &oldprinc,
+				 KADM5_PRINCIPAL_NORMAL_MASK);
+    krb5_free_principal(context, kprinc);
+    if (retval) {
+	com_err("modify_principal", retval, "while getting \"%s\".",
+		canon);
+	free(canon);
+	return;
+    }
+    princ.attributes = oldprinc.attributes;
+    kadm5_free_principal_ent(handle, &oldprinc);
+    retval = kadmin_parse_princ_args(argc, argv,
+				     &princ, &mask,
+				     &pass, &randkey,
+				     &ks_tuple, &n_ks_tuple,
+				     "modify_principal");
+    if (ks_tuple != NULL) {
+	free(ks_tuple);
+	kadmin_modprinc_usage("modify_principal");
+	free(canon);
+	kadmin_free_tl_data(&princ);
+	return;
+    }
+    if (retval) {
+	kadmin_modprinc_usage("modify_principal");
+	free(canon);
+	kadmin_free_tl_data(&princ);
+	return;
+    }
+    if (randkey) {
+	fprintf(stderr, "modify_principal: -randkey not allowed\n");
+	krb5_free_principal(context, princ.principal);
+	free(canon);
+	kadmin_free_tl_data(&princ);
+	return;
+    }
+    if (pass) {
+	fprintf(stderr,
+		"modify_principal: -pw not allowed; use change_password\n");
+	krb5_free_principal(context, princ.principal);
+	free(canon);
+	kadmin_free_tl_data(&princ);
+	return;
+    }
+    retval = kadm5_modify_principal(handle, &princ, mask);
+    krb5_free_principal(context, princ.principal);
+    if (retval) {
+	com_err("modify_principal", retval,
+		"while modifying \"%s\".", canon);
+	free(canon);
+	kadmin_free_tl_data(&princ);
+	return;
+    }
+    printf("Principal \"%s\" modified.\n", canon);
+    kadmin_free_tl_data(&princ);
+    free(canon);
+}
+
+void kadmin_getprinc(argc, argv)
+    int argc;
+    char *argv[];
+{
+    kadm5_principal_ent_rec dprinc;
+    krb5_principal princ;
+    krb5_error_code retval;
+    char *canon, *modcanon;
+    int i;
+
+    if (! (argc == 2 ||
+	   (argc == 3 && !strcmp("-terse", argv[1])))) {
+	fprintf(stderr, "usage: get_principal [-terse] principal\n");
+	return;
+    }
+
+
+    memset(&dprinc, 0, sizeof(dprinc));
+    memset(&princ, 0, sizeof(princ));
+
+    retval = kadmin_parse_name(argv[argc - 1], &princ);
+    if (retval) {
+	com_err("get_principal", retval, "while parsing principal");
+	return;
+    }
+    retval = krb5_unparse_name(context, princ, &canon);
+    if (retval) {
+	com_err("get_principal", retval, "while canonicalizing principal");
+	krb5_free_principal(context, princ);
+	return;
+    }
+    retval = kadm5_get_principal(handle, princ, &dprinc,
+				 KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA);
+    krb5_free_principal(context, princ);
+    if (retval) {
+	com_err("get_principal", retval, "while retrieving \"%s\".", canon);
+	free(canon);
+	return;
+    }
+    retval = krb5_unparse_name(context, dprinc.mod_name, &modcanon);
+    if (retval) {
+	com_err("get_principal", retval, "while unparsing modname");
+	kadm5_free_principal_ent(handle, &dprinc);
+	free(canon);
+	return;
+    }
+    if (argc == 2) {
+	printf("Principal: %s\n", canon);
+	printf("Expiration date: %s\n", dprinc.princ_expire_time ?
+	       strdate(dprinc.princ_expire_time) : "[never]");
+	printf("Last password change: %s\n", dprinc.last_pwd_change ?
+	       strdate(dprinc.last_pwd_change) : "[never]");
+	printf("Password expiration date: %s\n",
+	       dprinc.pw_expiration ?
+	       strdate(dprinc.pw_expiration) : "[none]");
+	printf("Maximum ticket life: %s\n", strdur(dprinc.max_life));
+	printf("Maximum renewable life: %s\n", strdur(dprinc.max_renewable_life));
+	printf("Last modified: %s (%s)\n", strdate(dprinc.mod_date), modcanon);
+	printf("Last successful authentication: %s\n",
+	       dprinc.last_success ? strdate(dprinc.last_success) :
+	       "[never]");
+	printf("Last failed authentication: %s\n",
+	       dprinc.last_failed ? strdate(dprinc.last_failed) :
+	       "[never]");
+	printf("Failed password attempts: %d\n",
+	       dprinc.fail_auth_count);
+	printf("Number of keys: %d\n", dprinc.n_key_data);
+	for (i = 0; i < dprinc.n_key_data; i++) {
+	    krb5_key_data *key_data = &dprinc.key_data[i];
+	    char enctype[BUFSIZ], salttype[BUFSIZ];
+
+	    if (krb5_enctype_to_string(key_data->key_data_type[0],
+				       enctype, sizeof(enctype)))
+		sprintf(enctype, "<Encryption type 0x%x>",
+			key_data->key_data_type[0]);
+	    printf("Key: vno %d, %s, ", key_data->key_data_kvno, enctype);
+	    if (key_data->key_data_ver > 1) {
+		if (krb5_salttype_to_string(key_data->key_data_type[1],
+					    salttype, sizeof(salttype)))
+		    sprintf(salttype, "<Salt type 0x%x>",
+			    key_data->key_data_type[1]);
+		printf("%s\n", salttype);
+	    } else
+		printf("no salt\n");
+	}
+
+	printf("Attributes:");
+	for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) {
+	    if (dprinc.attributes & (krb5_flags) 1 << i)
+		printf(" %s", prflags[i]);
+	}
+	printf("\n");
+	printf("Policy: %s\n", dprinc.policy ? dprinc.policy : "[none]");
+    } else {
+	printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\""
+	       "\t%d\t%d\t%d\t%d\t%d",
+	       canon, dprinc.princ_expire_time, dprinc.last_pwd_change,
+	       dprinc.pw_expiration, dprinc.max_life, modcanon,
+	       dprinc.mod_date, dprinc.attributes, dprinc.kvno,
+	       dprinc.mkvno, dprinc.policy ? dprinc.policy : "[none]",
+	       dprinc.max_renewable_life, dprinc.last_success,
+	       dprinc.last_failed, dprinc.fail_auth_count,
+	       dprinc.n_key_data);
+	for (i = 0; i < dprinc.n_key_data; i++)
+	    printf("\t%d\t%d\t%d\t%d",
+		   dprinc.key_data[i].key_data_ver,
+		   dprinc.key_data[i].key_data_kvno,
+		   dprinc.key_data[i].key_data_type[0],
+		   dprinc.key_data[i].key_data_type[1]);
+	printf("\n");
+    }
+    free(modcanon);
+    kadm5_free_principal_ent(handle, &dprinc);
+    free(canon);
+}
+
+void kadmin_getprincs(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    char *expr, **names;
+    int i, count;
+
+    expr = NULL;
+    if (! (argc == 1 || (argc == 2 && (expr = argv[1])))) {
+	fprintf(stderr, "usage: get_principals [expression]\n");
+	return;
+    }
+    retval = kadm5_get_principals(handle, expr, &names, &count);
+    if (retval) {
+	com_err("get_principals", retval, "while retrieving list.");
+	return;
+    }
+    for (i = 0; i < count; i++)
+	printf("%s\n", names[i]);
+    kadm5_free_name_list(handle, names, count);
+}
+
+static int
+kadmin_parse_policy_args(argc, argv, policy, mask, caller)
+    int argc;
+    char *argv[];
+    kadm5_policy_ent_t policy;
+    long *mask;
+    char *caller;
+{
+    int i;
+    time_t now;
+    time_t date;
+
+    time(&now);
+    *mask = 0;
+    for (i = 1; i < argc - 1; i++) {
+	if (strlen(argv[i]) == 8 &&
+	    !strcmp(argv[i], "-maxlife")) {
+	    if (++i > argc -2)
+		return -1;
+	    else {
+		date = get_date(argv[i]);
+		if (date == (time_t)-1) {
+		    fprintf(stderr, "Invalid date specification \"%s\".\n",
+			    argv[i]);
+		    return -1;
+		}
+		policy->pw_max_life = date - now;
+		*mask |= KADM5_PW_MAX_LIFE;
+		continue;
+	    }
+	} else if (strlen(argv[i]) == 8 &&
+		   !strcmp(argv[i], "-minlife")) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		date = get_date(argv[i]);
+		if (date == (time_t)-1) {
+		    fprintf(stderr, "Invalid date specification \"%s\".\n",
+			    argv[i]);
+		    return -1;
+		}
+		policy->pw_min_life = date - now;
+		*mask |= KADM5_PW_MIN_LIFE;
+		continue;
+	    }
+	} else if (strlen(argv[i]) == 10 &&
+		   !strcmp(argv[i], "-minlength")) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		policy->pw_min_length = atoi(argv[i]);
+		*mask |= KADM5_PW_MIN_LENGTH;
+		continue;
+	    }
+	} else if (strlen(argv[i]) == 11 &&
+		   !strcmp(argv[i], "-minclasses")) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		policy->pw_min_classes = atoi(argv[i]);
+		*mask |= KADM5_PW_MIN_CLASSES;
+		continue;
+	    }
+	} else if (strlen(argv[i]) == 8 &&
+		   !strcmp(argv[i], "-history")) {
+	    if (++i > argc - 2)
+		return -1;
+	    else {
+		policy->pw_history_num = atoi(argv[i]);
+		*mask |= KADM5_PW_HISTORY_NUM;
+		continue;
+	    }
+	} else
+	    return -1;
+    }
+    if (i != argc -1) {
+	fprintf(stderr, "%s: parser lost count!\n", caller);
+	return -1;
+    } else
+	return 0;
+}
+
+static void
+kadmin_addmodpol_usage(func)
+    char *func;
+{
+    fprintf(stderr, "usage; %s [options] policy\n", func);
+    fprintf(stderr, "\toptions are:\n");
+    fprintf(stderr, "\t\t[-maxlife time] [-minlife time] [-minlength length]\n\t\t[-minclasses number] [-history number]\n");
+}
+
+void kadmin_addpol(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    long mask;
+    kadm5_policy_ent_rec policy;
+
+    memset(&policy, 0, sizeof(policy));
+    if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) {
+	kadmin_addmodpol_usage("add_policy");
+	return;
+    } else {
+	policy.policy = argv[argc - 1];
+	mask |= KADM5_POLICY;
+	retval = kadm5_create_policy(handle, &policy, mask);
+	if (retval) {
+	    com_err("add_policy", retval, "while creating policy \"%s\".",
+		    policy.policy);
+	    return;
+	}
+    }
+    return;
+}
+
+void kadmin_modpol(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    long mask;
+    kadm5_policy_ent_rec policy;
+
+    memset(&policy, 0, sizeof(policy));
+    if (kadmin_parse_policy_args(argc, argv, &policy, &mask,
+				 "modify_policy")) {
+	kadmin_addmodpol_usage("modify_policy");
+	return;
+    } else {
+	policy.policy = argv[argc - 1];
+	retval = kadm5_modify_policy(handle, &policy, mask);
+	if (retval) {
+	    com_err("modify_policy", retval, "while modifying policy \"%s\".",
+		    policy.policy);
+	    return;
+	}
+    }
+    return;
+}
+
+void kadmin_delpol(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    char reply[5];
+
+    if (! (argc == 2 ||
+	   (argc == 3 && !strcmp("-force", argv[1])))) {
+	fprintf(stderr, "usage: delete_policy [-force] policy\n");
+	return;
+    }
+    if (argc == 2) {
+	printf("Are you sure you want to delete the policy \"%s\"? (yes/no): ", argv[1]);
+	fgets(reply, sizeof (reply), stdin);
+	if (strcmp("yes\n", reply)) {
+	    fprintf(stderr, "Policy \"%s\" not deleted.\n", argv[1]);
+	    return;
+	}
+    }
+    retval = kadm5_delete_policy(handle, argv[argc - 1]);
+    if (retval) {
+	com_err("delete_policy:", retval, "while deleting policy \"%s\"",
+		argv[argc - 1]);
+	return;
+    }
+    return;
+}
+
+void kadmin_getpol(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    kadm5_policy_ent_rec policy;
+
+    if (! (argc == 2 ||
+	   (argc == 3 && !strcmp("-terse", argv[1])))) {
+	fprintf(stderr, "usage: get_policy [-terse] policy\n");
+	return;
+    }
+    retval = kadm5_get_policy(handle, argv[argc - 1], &policy);
+    if (retval) {
+	com_err("get_policy", retval, "while retrieving policy \"%s\".",
+		argv[argc - 1]);
+	return;
+    }
+    if (argc == 2) {
+	printf("Policy: %s\n", policy.policy);
+	printf("Maximum password life: %ld\n", policy.pw_max_life);
+	printf("Minimum password life: %ld\n", policy.pw_min_life);
+	printf("Minimum password length: %ld\n", policy.pw_min_length);
+	printf("Minimum number of password character classes: %ld\n",
+	       policy.pw_min_classes);
+	printf("Number of old keys kept: %ld\n", policy.pw_history_num);
+	printf("Reference count: %ld\n", policy.policy_refcnt);
+    } else {
+	printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\n",
+	       policy.policy, policy.pw_max_life, policy.pw_min_life,
+	       policy.pw_min_length, policy.pw_min_classes,
+	       policy.pw_history_num, policy.policy_refcnt);
+    }
+    kadm5_free_policy_ent(handle, &policy);
+    return;
+}
+
+void kadmin_getpols(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    char *expr, **names;
+    int i, count;
+
+    expr = NULL;
+    if (! (argc == 1 || (argc == 2 && (expr = argv[1])))) {
+	fprintf(stderr, "usage: get_policies [expression]\n");
+	return;
+    }
+    retval = kadm5_get_policies(handle, expr, &names, &count);
+    if (retval) {
+	com_err("get_policies", retval, "while retrieving list.");
+	return;
+    }
+    for (i = 0; i < count; i++)
+	printf("%s\n", names[i]);
+    kadm5_free_name_list(handle, names, count);
+}
+
+void kadmin_getprivs(argc, argv)
+    int argc;
+    char *argv[];
+{
+    static char *privs[] = {"GET", "ADD", "MODIFY", "DELETE"};
+    krb5_error_code retval;
+    int i;
+    long plist;
+
+    if (argc != 1) {
+	fprintf(stderr, "usage: get_privs\n");
+	return;
+    }
+    retval = kadm5_get_privs(handle, &plist);
+    if (retval) {
+	com_err("get_privs", retval, "while retrieving privileges");
+	return;
+    }
+    printf("current privileges:");
+    for (i = 0; i < sizeof (privs) / sizeof (char *); i++) {
+	if (plist & 1 << i)
+	    printf(" %s", privs[i]);
+    }
+    printf("\n");
+    return;
+}
diff --git a/krb5-1-6/src/kadmin/cli/kadmin.h b/krb5-1-6/src/kadmin/cli/kadmin.h
new file mode 100644
index 000000000..745ebcb2b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/kadmin.h
@@ -0,0 +1,75 @@
+/*
+ * kadmin/cli/kadmin.h
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Prototypes for kadmin functions called from SS library.
+ */
+
+#ifndef __KADMIN_H__
+#define __KADMIN_H__
+
+/* It would be nice if ss produced a header file we could reference */
+extern char *kadmin_startup(int argc, char *argv[]);
+extern int quit (void);
+extern void kadmin_lock(int argc, char *argv[]);
+extern void kadmin_unlock(int argc, char *argv[]);
+extern void kadmin_delprinc(int argc, char *argv[]);
+extern void kadmin_cpw(int argc, char *argv[]);
+extern void kadmin_addprinc(int argc, char *argv[]);
+extern void kadmin_modprinc(int argc, char *argv[]);
+extern void kadmin_getprinc(int argc, char *argv[]);
+extern void kadmin_getprincs(int argc, char *argv[]);
+extern void kadmin_addpol(int argc, char *argv[]);
+extern void kadmin_modpol(int argc, char *argv[]);
+extern void kadmin_delpol(int argc, char *argv[]);
+extern void kadmin_getpol(int argc, char *argv[]);
+extern void kadmin_getpols(int argc, char *argv[]);
+extern void kadmin_getprivs(int argc, char *argv[]);
+extern void kadmin_keytab_add(int argc, char *argv[]);
+extern void kadmin_keytab_remove(int argc, char *argv[]);
+
+#include "autoconf.h"
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+extern time_t get_date(char *);
+
+/* Yucky global variables */
+extern krb5_context context;
+extern char *krb5_defkeyname;	 
+extern char *whoami;
+extern void *handle;
+
+#endif /* __KADMIN_H__ */
+
diff --git a/krb5-1-6/src/kadmin/cli/kadmin.local.M b/krb5-1-6/src/kadmin/cli/kadmin.local.M
new file mode 100644
index 000000000..cf447d7e6
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/kadmin.local.M
@@ -0,0 +1 @@
+.so man8/kadmin.8
diff --git a/krb5-1-6/src/kadmin/cli/kadmin_ct.ct b/krb5-1-6/src/kadmin/cli/kadmin_ct.ct
new file mode 100644
index 000000000..05a4efb84
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/kadmin_ct.ct
@@ -0,0 +1,85 @@
+# 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.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+# 
+# Command table for kadmin CLI for OVSecure
+#
+
+command_table kadmin_cmds;
+
+request kadmin_addprinc, "Add principal",
+	add_principal, addprinc, ank;
+
+request kadmin_delprinc, "Delete principal",
+	delete_principal, delprinc;
+
+request kadmin_modprinc, "Modify principal",
+	modify_principal, modprinc;
+
+request kadmin_cpw, "Change password",
+	change_password, cpw;
+
+request kadmin_getprinc, "Get principal",
+	get_principal, getprinc;
+
+request kadmin_getprincs, "List principals",
+	list_principals, listprincs, get_principals, getprincs;
+
+request kadmin_addpol, "Add policy",
+	add_policy, addpol;
+
+request kadmin_modpol, "Modify policy",
+	modify_policy, modpol;
+
+request kadmin_delpol, "Delete policy",
+	delete_policy, delpol;
+
+request kadmin_getpol, "Get policy",
+	get_policy, getpol;
+
+request kadmin_getpols, "List policies",
+	list_policies, listpols, get_policies, getpols;
+
+request kadmin_getprivs, "Get privileges",
+	get_privs, getprivs;
+
+request kadmin_keytab_add, "Add entry(s) to a keytab",
+	ktadd, xst;
+
+request kadmin_keytab_remove, "Remove entry(s) from a keytab",
+	ktremove, ktrem;
+
+request kadmin_lock, "Lock database exclusively (use with extreme caution!)",
+	lock;
+
+request kadmin_unlock, "Release exclusive database lock",
+	unlock;
+
+# list_requests is generic -- unrelated to Kerberos
+request	ss_list_requests, "List available requests.",
+	list_requests, lr, "?";
+
+request	ss_quit, "Exit program.",
+	quit, exit, q;
+
+end;
+
diff --git a/krb5-1-6/src/kadmin/cli/keytab.c b/krb5-1-6/src/kadmin/cli/keytab.c
new file mode 100644
index 000000000..f6c167ce8
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/keytab.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $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
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#include "kadmin.h"
+
+static int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab,
+			 krb5_boolean keepold,
+			 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
+			 char *princ_str);
+static int remove_principal(char *keytab_str, krb5_keytab keytab, char
+			    *princ_str, char *kvno_str);
+static char *etype_string(krb5_enctype enctype);
+
+static int quiet;
+
+static void add_usage()
+{
+     fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob princ-exp] [...]\n");
+}
+     
+static void rem_usage()
+{
+     fprintf(stderr, "Usage: ktremove [-k[eytab] keytab] [-q] principal [kvno|\"all\"|\"old\"]\n");
+}
+
+static int process_keytab(krb5_context my_context, char **keytab_str,
+		   krb5_keytab *keytab) 
+{
+     int code;
+     
+     if (*keytab_str == NULL) {
+	  /* XXX krb5_defkeyname is an internal library global and
+             should go away */
+	  if (! (*keytab_str = strdup(krb5_defkeyname))) {
+	       com_err(whoami, ENOMEM, "while creating keytab name");
+	       return 1;
+	  }
+	  code = krb5_kt_default(my_context, keytab);
+	  if (code != 0) {
+	       com_err(whoami, code, "while opening default keytab");
+	       free(*keytab_str);
+	       return 1;
+	  }
+     } else {
+	  if (strchr(*keytab_str, ':') != NULL) {
+	       *keytab_str = strdup(*keytab_str);
+	       if (*keytab_str == NULL) {
+		    com_err(whoami, ENOMEM, "while creating keytab name");
+		    return 1;
+	       }
+	  } else {
+	       char *tmp = *keytab_str;
+
+	       *keytab_str = (char *)
+		    malloc(strlen("WRFILE:")+strlen(tmp)+1);
+	       if (*keytab_str == NULL) {
+		    com_err(whoami, ENOMEM, "while creating keytab name");
+		    return 1;
+	       }
+	       sprintf(*keytab_str, "WRFILE:%s", tmp);
+	  }
+	  
+	  code = krb5_kt_resolve(my_context, *keytab_str, keytab);
+	  if (code != 0) {
+	       com_err(whoami, code, "while resolving keytab %s", *keytab_str);
+	       free(keytab_str);
+	       return 1;
+	  }
+     }
+     
+     return 0;
+}
+
+     
+void kadmin_keytab_add(int argc, char **argv)
+{
+     krb5_keytab keytab = 0;
+     char *keytab_str = NULL, **princs;
+     int code, num, i;
+     krb5_error_code retval;
+     int n_ks_tuple = 0;
+     krb5_boolean keepold = FALSE;
+     krb5_key_salt_tuple *ks_tuple = NULL;
+
+     argc--; argv++;
+     quiet = 0;
+     while (argc) {
+	  if (strncmp(*argv, "-k", 2) == 0) {
+	       argc--; argv++;
+	       if (!argc || keytab_str) {
+		    add_usage();
+		    return;
+	       }
+	       keytab_str = *argv;
+	  } else if (strcmp(*argv, "-q") == 0) {
+	       quiet++;
+	  } else if (strcmp(*argv, "-e") == 0) {
+	       argc--;
+	       if (argc < 1) {
+		    add_usage();
+		    return;
+	       }
+	       retval = krb5_string_to_keysalts(*++argv, ", \t", ":.-", 0,
+						&ks_tuple, &n_ks_tuple);
+	       if (retval) {
+		    com_err("ktadd", retval, "while parsing keysalts %s",
+			    *argv);
+
+		    return;
+	       }
+	  } else
+	       break;
+	  argc--; argv++;
+     }
+
+     if (argc == 0) {
+	  add_usage();
+	  return;
+     }
+
+     if (process_keytab(context, &keytab_str, &keytab))
+	  return;
+     
+     while (*argv) {
+	  if (strcmp(*argv, "-glob") == 0) {
+	       if (*++argv == NULL) {
+		    add_usage();
+		    break;
+	       }
+	       
+	       code = kadm5_get_principals(handle, *argv, &princs, &num);
+	       if (code) {
+		    com_err(whoami, code, "while expanding expression \"%s\".",
+			    *argv);
+		    argv++;
+		    continue;
+	       }
+	       
+	       for (i = 0; i < num; i++) 
+		    (void) add_principal(handle, keytab_str, keytab,
+					 keepold, n_ks_tuple, ks_tuple,
+					 princs[i]); 
+	       kadm5_free_name_list(handle, princs, num);
+	  } else
+	       (void) add_principal(handle, keytab_str, keytab,
+				    keepold, n_ks_tuple, ks_tuple,
+				    *argv);
+	  argv++;
+     }
+	  
+     code = krb5_kt_close(context, keytab);
+     if (code != 0)
+	  com_err(whoami, code, "while closing keytab");
+
+     free(keytab_str);
+}
+
+void kadmin_keytab_remove(int argc, char **argv)
+{
+     krb5_keytab keytab = 0;
+     char *keytab_str = NULL;
+     int code;
+
+     argc--; argv++;
+     quiet = 0;
+     while (argc) {
+	  if (strncmp(*argv, "-k", 2) == 0) {
+	       argc--; argv++;
+	       if (!argc || keytab_str) {
+		    rem_usage();
+		    return;
+	       }
+	       keytab_str = *argv;
+	  } else if (strcmp(*argv, "-q") == 0) {
+	       quiet++;
+	  } else
+	       break;
+	  argc--; argv++;
+     }
+
+     if (argc != 1 && argc != 2) {
+	  rem_usage();
+	  return;
+     }
+     if (process_keytab(context, &keytab_str, &keytab))
+	  return;
+
+     (void) remove_principal(keytab_str, keytab, argv[0], argv[1]);
+
+     code = krb5_kt_close(context, keytab);
+     if (code != 0)
+	  com_err(whoami, code, "while closing keytab");
+
+     free(keytab_str);
+}
+
+static 
+int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab,
+		  krb5_boolean keepold, int n_ks_tuple,
+		  krb5_key_salt_tuple *ks_tuple,
+		  char *princ_str) 
+{
+     kadm5_principal_ent_rec princ_rec;
+     krb5_principal princ;
+     krb5_keytab_entry new_entry;
+     krb5_keyblock *keys;
+     int code, nkeys, i;
+
+     (void) memset((char *)&princ_rec, 0, sizeof(princ_rec));
+
+     princ = NULL;
+     keys = NULL;
+     nkeys = 0;
+
+     code = krb5_parse_name(context, princ_str, &princ);
+     if (code != 0) {
+	  com_err(whoami, code, "while parsing -add principal name %s",
+		  princ_str);
+	  goto cleanup;
+     }
+
+     if (keepold || ks_tuple != NULL) {
+	 code = kadm5_randkey_principal_3(lhandle, princ,
+					  keepold, n_ks_tuple, ks_tuple,
+					  &keys, &nkeys);
+     } else {
+	 code = kadm5_randkey_principal(lhandle, princ, &keys, &nkeys);
+     }
+     if (code != 0) {
+	  if (code == KADM5_UNK_PRINC) {
+	       fprintf(stderr, "%s: Principal %s does not exist.\n",
+		       whoami, princ_str);
+	  } else
+	       com_err(whoami, code, "while changing %s's key",
+		       princ_str);
+	  goto cleanup;
+     }
+
+     code = kadm5_get_principal(lhandle, princ, &princ_rec,
+				KADM5_PRINCIPAL_NORMAL_MASK);
+     if (code != 0) {
+	  com_err(whoami, code, "while retrieving principal");
+	  goto cleanup;
+     }
+
+     for (i = 0; i < nkeys; i++) {
+	  memset((char *) &new_entry, 0, sizeof(new_entry));
+	  new_entry.principal = princ;
+	  new_entry.key = keys[i];
+	  new_entry.vno = princ_rec.kvno;
+
+	  code = krb5_kt_add_entry(context, keytab, &new_entry);
+	  if (code != 0) {
+	       com_err(whoami, code, "while adding key to keytab");
+	       (void) kadm5_free_principal_ent(lhandle, &princ_rec);
+	       goto cleanup;
+	  }
+
+	  if (!quiet)
+	       printf("Entry for principal %s with kvno %d, "
+		      "encryption type %s added to keytab %s.\n",
+		      princ_str, princ_rec.kvno,
+		      etype_string(keys[i].enctype), keytab_str);
+     }
+
+     code = kadm5_free_principal_ent(lhandle, &princ_rec);
+     if (code != 0) {
+	  com_err(whoami, code, "while freeing principal entry");
+	  goto cleanup;
+     }
+
+cleanup:
+     if (nkeys) {
+	  for (i = 0; i < nkeys; i++)
+	       krb5_free_keyblock_contents(context, &keys[i]);
+	  free(keys);
+     }
+     if (princ)
+	  krb5_free_principal(context, princ);
+
+     return code;
+}
+
+int remove_principal(char *keytab_str, krb5_keytab keytab, char
+		     *princ_str, char *kvno_str) 
+{
+     krb5_principal princ;
+     krb5_keytab_entry entry;
+     krb5_kt_cursor cursor;
+     enum { UNDEF, SPEC, HIGH, ALL, OLD } mode;
+     int code, did_something;
+     krb5_kvno kvno;
+
+     code = krb5_parse_name(context, princ_str, &princ);
+     if (code != 0) {
+	  com_err(whoami, code, "while parsing principal name %s",
+		  princ_str);
+	  return code;
+     }
+
+     mode = UNDEF;
+     if (kvno_str == NULL) {
+	  mode = HIGH;
+	  kvno = 0;
+     } else if (strcmp(kvno_str, "all") == 0) {
+	  mode = ALL;
+	  kvno = 0;
+     } else if (strcmp(kvno_str, "old") == 0) {
+	  mode = OLD;
+	  kvno = 0;
+     } else {
+	  mode = SPEC;
+	  kvno = atoi(kvno_str);
+     }
+
+     /* kvno is set to specified value for SPEC, 0 otherwise */
+     code = krb5_kt_get_entry(context, keytab, princ, kvno, 0, &entry);
+     if (code != 0) {
+	  if (code == ENOENT) {
+	       fprintf(stderr, "%s: Keytab %s does not exist.\n",
+		       whoami, keytab_str);
+	  } else if (code == KRB5_KT_NOTFOUND) {
+	       if (mode != SPEC)
+		    fprintf(stderr, "%s: No entry for principal "
+			    "%s exists in keytab %s\n",
+			    whoami, princ_str, keytab_str);
+	       else
+		    fprintf(stderr, "%s: No entry for principal "
+			    "%s with kvno %d exists in keytab "
+			    "%s.\n", whoami, princ_str, kvno,
+			    keytab_str);
+	  } else {
+	       com_err(whoami, code, "while retrieving highest kvno "
+		       "from keytab");
+	  }
+	  return code;
+     }
+
+     /* set kvno to spec'ed value for SPEC, highest kvno otherwise */
+     kvno = entry.vno;
+     krb5_kt_free_entry(context, &entry);
+
+     code = krb5_kt_start_seq_get(context, keytab, &cursor);
+     if (code != 0) {
+	  com_err(whoami, code, "while starting keytab scan");
+	  return code;
+     }
+
+     did_something = 0;
+     while ((code = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
+	  if (krb5_principal_compare(context, princ, entry.principal) &&
+	      ((mode == ALL) ||
+	       (mode == SPEC && entry.vno == kvno) ||
+	       (mode == OLD && entry.vno != kvno) ||
+	       (mode == HIGH && entry.vno == kvno))) {
+
+	       /*
+		* Ack!  What a kludge... the scanning functions lock
+		* the keytab so entries cannot be removed while they
+		* are operating.
+		*/
+	       code = krb5_kt_end_seq_get(context, keytab, &cursor);
+	       if (code != 0) {
+		    com_err(whoami, code, "while temporarily ending "
+			    "keytab scan");
+		    return code;
+	       }
+	       code = krb5_kt_remove_entry(context, keytab, &entry);
+	       if (code != 0) {
+		    com_err(whoami, code, "while deleting entry from keytab");
+		    return code;
+	       }
+	       code = krb5_kt_start_seq_get(context, keytab, &cursor);
+	       if (code != 0) {
+		    com_err(whoami, code, "while restarting keytab scan");
+		    return code;
+	       }
+
+	       did_something++;
+	       if (!quiet)
+		    printf("Entry for principal %s with kvno %d "
+			   "removed from keytab %s.\n", 
+			   princ_str, entry.vno, keytab_str);
+	  }
+	  krb5_kt_free_entry(context, &entry);
+     }
+     if (code && code != KRB5_KT_END) {
+	  com_err(whoami, code, "while scanning keytab");
+	  return code;
+     }
+     if ((code = krb5_kt_end_seq_get(context, keytab, &cursor))) {
+	  com_err(whoami, code, "while ending keytab scan");
+	  return code;
+     }
+
+     /*
+      * If !did_someting then mode must be OLD or we would have
+      * already returned with an error.  But check it anyway just to
+      * prevent unexpected error messages...
+      */
+     if (!did_something && mode == OLD) {
+	  fprintf(stderr, "%s: There is only one entry for principal "
+		  "%s in keytab %s\n", whoami, princ_str, keytab_str);
+	  return 1;
+     }
+     
+     return 0;
+}
+
+/*
+ * etype_string(enctype): return a string representation of the
+ * encryption type.  XXX copied from klist.c; this should be a
+ * library function, or perhaps just #defines
+ */
+static char *etype_string(enctype)
+    krb5_enctype enctype;
+{
+    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;
+}
diff --git a/krb5-1-6/src/kadmin/cli/ss_wrapper.c b/krb5-1-6/src/kadmin/cli/ss_wrapper.c
new file mode 100644
index 000000000..f73ba8238
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/ss_wrapper.c
@@ -0,0 +1,64 @@
+/*
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * ss wrapper for kadmin
+ */
+
+#include <krb5.h>
+#include <ss/ss.h>
+#include <stdio.h>
+#include <string.h>
+#include "kadmin.h"
+
+extern ss_request_table kadmin_cmds;
+extern int exit_status;
+extern char *whoami;
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *request;
+    krb5_error_code retval;
+    int sci_idx, code = 0;
+
+    whoami = ((whoami = strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
+
+    request = kadmin_startup(argc, argv);
+    sci_idx = ss_create_invocation(whoami, "5.0", (char *) NULL,
+				   &kadmin_cmds, &retval);
+    if (retval) {
+	ss_perror(sci_idx, retval, "creating invocation");
+	exit(1);
+    }
+    if (request) {
+	    code = ss_execute_line(sci_idx, request);
+	    if (code != 0) {
+		    ss_perror(sci_idx, code, request);
+		    exit_status++;
+	    }
+    } else
+            retval = ss_listen(sci_idx);
+    return quit() ? 1 : exit_status;
+}
diff --git a/krb5-1-6/src/kadmin/cli/strftime.c b/krb5-1-6/src/kadmin/cli/strftime.c
new file mode 100644
index 000000000..6fb621e41
--- /dev/null
+++ b/krb5-1-6/src/kadmin/cli/strftime.c
@@ -0,0 +1,464 @@
+/*	$NetBSD: strftime.c,v 1.8 1999/02/07 17:33:30 augustss Exp $	*/
+
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char *sccsid = "@(#)strftime.c	5.11 (Berkeley) 2/24/91";
+#else
+__RCSID("$NetBSD: strftime.c,v 1.8 1999/02/07 17:33:30 augustss Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+#include <time.h>
+
+/* begin krb5 hack - replace stuff that would come from netbsd libc */
+#undef _CurrentTimeLocale
+#define _CurrentTimeLocale (&dummy_locale_info)
+
+struct dummy_locale_info_t {
+    char d_t_fmt[15];
+    char t_fmt_ampm[12];
+    char t_fmt[9];
+    char d_fmt[9];
+    char day[7][10];
+    char abday[7][4];
+    char mon[12][10];
+    char abmon[12][4];
+    char am_pm[2][3];
+};
+static const struct dummy_locale_info_t dummy_locale_info = {
+    "%a %b %d %X %Y",		/* %c */
+    "%I:%M:%S %p",		/* %r */
+    "%H:%M:%S",			/* %X */
+    "%m/%d/%y",			/* %x */
+    { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+      "Saturday" },
+    { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
+    { "January", "February", "March", "April", "May", "June",
+      "July", "August", "September", "October", "November", "December" },
+    { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
+    { "AM", "PM" },
+};
+#undef  TM_YEAR_BASE
+#define TM_YEAR_BASE 1900
+
+#undef  DAYSPERLYEAR
+#define DAYSPERLYEAR 366
+#undef  DAYSPERNYEAR
+#define DAYSPERNYEAR 365
+#undef  DAYSPERWEEK
+#define DAYSPERWEEK 7
+#undef  isleap
+#define isleap(N)	((N % 4) == 0 && (N % 100 != 0 || N % 400 == 0))
+#undef  tzname
+#define tzname my_tzname
+static const char *const tzname[2] = { 0, 0 };
+#undef  tzset
+#define tzset()
+#undef __P
+#define __P(X) X /* we already require ansi c in this tree */
+/* end krb5 hack */
+
+static	int _add __P((const char *, char **, const char *));
+static	int _conv __P((int, int, int, char **, const char *));
+static	int _secs __P((const struct tm *, char **, const char *));
+static	size_t _fmt __P((const char *, const struct tm *, char **,
+	    const char *));
+
+size_t
+strftime(s, maxsize, format, t)
+	char *s;
+	size_t maxsize;
+	const char *format;
+	const struct tm *t;
+{
+	char *pt;
+
+	tzset();
+	if (maxsize < 1)
+		return (0);
+
+	pt = s;
+	if (_fmt(format, t, &pt, s + maxsize)) {
+		*pt = '\0';
+		return (pt - s);
+	} else
+		return (0);
+}
+
+#define SUN_WEEK(t)	(((t)->tm_yday + 7 - \
+				((t)->tm_wday)) / 7)
+#define MON_WEEK(t)	(((t)->tm_yday + 7 - \
+				((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
+
+static size_t
+_fmt(format, t, pt, ptlim)
+	const char *format;
+	const struct tm *t;
+	char **pt;
+	const char * const ptlim;
+{
+	for (; *format; ++format) {
+		if (*format == '%') {
+			++format;
+			if (*format == 'E') {
+				/* Alternate Era */
+				++format;
+			} else if (*format == 'O') {
+				/* Alternate numeric symbols */
+				++format;
+			}
+			switch (*format) {
+			case '\0':
+				--format;
+				break;
+			case 'A':
+				if (t->tm_wday < 0 || t->tm_wday > 6)
+					return (0);
+				if (!_add(_CurrentTimeLocale->day[t->tm_wday],
+				    pt, ptlim))
+					return (0);
+				continue;
+
+			case 'a':
+				if (t->tm_wday < 0 || t->tm_wday > 6)
+					return (0);
+				if (!_add(_CurrentTimeLocale->abday[t->tm_wday],
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'B':
+				if (t->tm_mon < 0 || t->tm_mon > 11)
+					return (0);
+				if (!_add(_CurrentTimeLocale->mon[t->tm_mon],
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'b':
+			case 'h':
+				if (t->tm_mon < 0 || t->tm_mon > 11)
+					return (0);
+				if (!_add(_CurrentTimeLocale->abmon[t->tm_mon],
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'C':
+				if (!_conv((t->tm_year + TM_YEAR_BASE) / 100,
+				    2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'c':
+				if (!_fmt(_CurrentTimeLocale->d_t_fmt, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'D':
+				if (!_fmt("%m/%d/%y", t, pt, ptlim))
+					return (0);
+				continue;
+			case 'd':
+				if (!_conv(t->tm_mday, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'e':
+				if (!_conv(t->tm_mday, 2, ' ', pt, ptlim))
+					return (0);
+				continue;
+			case 'H':
+				if (!_conv(t->tm_hour, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'I':
+				if (!_conv(t->tm_hour % 12 ?
+				    t->tm_hour % 12 : 12, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'j':
+				if (!_conv(t->tm_yday + 1, 3, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'k':
+				if (!_conv(t->tm_hour, 2, ' ', pt, ptlim))
+					return (0);
+				continue;
+			case 'l':
+				if (!_conv(t->tm_hour % 12 ?
+				    t->tm_hour % 12: 12, 2, ' ', pt, ptlim))
+					return (0);
+				continue;
+			case 'M':
+				if (!_conv(t->tm_min, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'm':
+				if (!_conv(t->tm_mon + 1, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'n':
+				if (!_add("\n", pt, ptlim))
+					return (0);
+				continue;
+			case 'p':
+				if (!_add(_CurrentTimeLocale->am_pm[t->tm_hour
+				    >= 12], pt, ptlim))
+					return (0);
+				continue;
+			case 'R':
+				if (!_fmt("%H:%M", t, pt, ptlim))
+					return (0);
+				continue;
+			case 'r':
+				if (!_fmt(_CurrentTimeLocale->t_fmt_ampm, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'S':
+				if (!_conv(t->tm_sec, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 's':
+				if (!_secs(t, pt, ptlim))
+					return (0);
+				continue;
+			case 'T':
+				if (!_fmt("%H:%M:%S", t, pt, ptlim))
+					return (0);
+				continue;
+			case 't':
+				if (!_add("\t", pt, ptlim))
+					return (0);
+				continue;
+			case 'U':
+				if (!_conv(SUN_WEEK(t), 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'u':
+				if (!_conv(t->tm_wday ? t->tm_wday : 7, 1, '0',
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'V':	/* ISO 8601 week number */
+			case 'G':	/* ISO 8601 year (four digits) */
+			case 'g':	/* ISO 8601 year (two digits) */
+/*
+** From Arnold Robbins' strftime version 3.0:  "the week number of the
+** year (the first Monday as the first day of week 1) as a decimal number
+** (01-53)."
+** (ado, 1993-05-24)
+**
+** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** "Week 01 of a year is per definition the first week which has the
+** Thursday in this year, which is equivalent to the week which contains
+** the fourth day of January. In other words, the first week of a new year
+** is the week which has the majority of its days in the new year. Week 01
+** might also contain days from the previous year and the week before week
+** 01 of a year is the last week (52 or 53) of the previous year even if
+** it contains days from the new year. A week starts with Monday (day 1)
+** and ends with Sunday (day 7).  For example, the first week of the year
+** 1997 lasts from 1996-12-30 to 1997-01-05..."
+** (ado, 1996-01-02)
+*/
+				{
+					int	year;
+					int	yday;
+					int	wday;
+					int	w;
+
+					year = t->tm_year + TM_YEAR_BASE;
+					yday = t->tm_yday;
+					wday = t->tm_wday;
+					for ( ; ; ) {
+						int	len;
+						int	bot;
+						int	top;
+
+						len = isleap(year) ?
+							DAYSPERLYEAR :
+							DAYSPERNYEAR;
+						/*
+						** What yday (-3 ... 3) does
+						** the ISO year begin on?
+						*/
+						bot = ((yday + 11 - wday) %
+							DAYSPERWEEK) - 3;
+						/*
+						** What yday does the NEXT
+						** ISO year begin on?
+						*/
+						top = bot -
+							(len % DAYSPERWEEK);
+						if (top < -3)
+							top += DAYSPERWEEK;
+						top += len;
+						if (yday >= top) {
+							++year;
+							w = 1;
+							break;
+						}
+						if (yday >= bot) {
+							w = 1 + ((yday - bot) /
+								DAYSPERWEEK);
+							break;
+						}
+						--year;
+						yday += isleap(year) ?
+							DAYSPERLYEAR :
+							DAYSPERNYEAR;
+					}
+#ifdef XPG4_1994_04_09
+					if ((w == 52
+					     && t->tm_mon == TM_JANUARY)
+					    || (w == 1
+						&& t->tm_mon == TM_DECEMBER))
+						w = 53;
+#endif /* defined XPG4_1994_04_09 */
+					if (*format == 'V') {
+						if (!_conv(w, 2, '0',
+							pt, ptlim))
+							return (0);
+					} else if (*format == 'g') {
+						if (!_conv(year % 100, 2, '0',
+							pt, ptlim))
+							return (0);
+					} else	if (!_conv(year, 4, '0',
+							pt, ptlim))
+							return (0);
+				}
+				continue;
+			case 'W':
+				if (!_conv(MON_WEEK(t), 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'w':
+				if (!_conv(t->tm_wday, 1, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'x':
+				if (!_fmt(_CurrentTimeLocale->d_fmt, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'X':
+				if (!_fmt(_CurrentTimeLocale->t_fmt, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'y':
+				if (!_conv((t->tm_year + TM_YEAR_BASE) % 100,
+				    2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'Y':
+				if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0',
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'Z':
+				if (tzname[t->tm_isdst ? 1 : 0] &&
+				    !_add(tzname[t->tm_isdst ? 1 : 0], pt,
+				    ptlim))
+					return (0);
+				continue;
+			case '%':
+			/*
+			 * X311J/88-090 (4.12.3.5): if conversion char is
+			 * undefined, behavior is undefined.  Print out the
+			 * character itself as printf(3) does.
+			 */
+			default:
+				break;
+			}
+		}
+		if (*pt == ptlim)
+			return (0);
+		*(*pt)++ = *format;
+	}
+	return (ptlim - *pt);
+}
+
+static int
+_secs(t, pt, ptlim)
+	const struct tm *t;
+	char **pt;
+	const char * const ptlim;
+{
+	char buf[15];
+	time_t s;
+	char *p;
+	struct tm tmp;
+
+	buf[sizeof (buf) - 1] = '\0';
+	/* Make a copy, mktime(3) modifies the tm struct. */
+	tmp = *t;
+	s = mktime(&tmp);
+	for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
+		*p-- = (char)(s % 10 + '0');
+	return (_add(++p, pt, ptlim));
+}
+
+static int
+_conv(n, digits, pad, pt, ptlim)
+	int n, digits;
+	int pad;
+	char **pt;
+	const char * const ptlim;
+{
+	char buf[10];
+	char *p;
+
+	buf[sizeof (buf) - 1] = '\0';
+	for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
+		*p-- = n % 10 + '0';
+	while (p > buf && digits-- > 0)
+		*p-- = pad;
+	return (_add(++p, pt, ptlim));
+}
+
+static int
+_add(str, pt, ptlim)
+	const char *str;
+	char **pt;
+	const char * const ptlim;
+{
+
+	for (;; ++(*pt)) {
+		if (*pt == ptlim)
+			return (0);
+		if ((**pt = *str++) == '\0')
+			return (1);
+	}
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/Makefile.in b/krb5-1-6/src/kadmin/dbutil/Makefile.in
new file mode 100644
index 000000000..a7fa1778e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/Makefile.in
@@ -0,0 +1,165 @@
+thisconfigdir=../..
+myfulldir=kadmin/dbutil
+mydir=kadmin/dbutil
+BUILDTOP=$(REL)..$(S)..
+DEFINES = -DKDB4_DISABLE
+DEFS=
+LOCALINCLUDES = -I. @KRB4_INCLUDES@ 
+PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)
+KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+
+PROG = kdb5_util
+###OBJS	= kdb5_util.o dump.o dumpv4.o loadv4.o \
+###	kdb5_create.o kadm5_create.o string_table.o kdb5_stash.o \
+###	kdb5_destroy.o ovload.o import_err.o strtok.o
+###
+
+SRCS = kdb5_util.c kdb5_create.c kadm5_create.c string_table.c kdb5_destroy.c kdb5_stash.c import_err.c strtok.c dump.c ovload.c
+
+OBJS = kdb5_util.o kdb5_create.o kadm5_create.o string_table.o kdb5_destroy.o kdb5_stash.o import_err.o strtok.o dump.o ovload.o
+
+all:: $(PROG)
+
+$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o $(PROG) $(OBJS) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB4COMPAT_LIBS)
+
+import_err.c import_err.h: $(srcdir)/import_err.et
+
+$(OBJS): import_err.h
+
+install::
+	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
+	$(INSTALL_DATA) $(srcdir)/$(PROG).M ${DESTDIR}$(ADMIN_MANDIR)/$(PROG).8
+
+clean::
+	$(RM) $(PROG) $(OBJS) import_err.c import_err.h
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kdb5_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb5_util.c kdb5_util.h
+$(OUTPRE)kdb5_create.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb5_create.c kdb5_util.h
+$(OUTPRE)kadm5_create.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kadm5_create.c kdb5_util.h \
+  string_table.h
+$(OUTPRE)string_table.$(OBJEXT): string_table.c
+$(OUTPRE)kdb5_destroy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb5_destroy.c kdb5_util.h
+$(OUTPRE)kdb5_stash.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb5_stash.c kdb5_util.h
+$(OUTPRE)import_err.$(OBJEXT): $(COM_ERR_DEPS) import_err.c
+$(OUTPRE)strtok.$(OBJEXT): nstrtok.h strtok.c
+$(OUTPRE)dump.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h dump.c kdb5_util.h
+$(OUTPRE)ovload.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h import_err.h kdb5_util.h \
+  nstrtok.h ovload.c
diff --git a/krb5-1-6/src/kadmin/dbutil/dump.c b/krb5-1-6/src/kadmin/dbutil/dump.c
new file mode 100644
index 000000000..5c627d30c
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/dump.c
@@ -0,0 +1,2433 @@
+/*
+ * kadmin/dbutil/dump.c
+ *
+ * Copyright 1990,1991,2001,2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Dump a KDC database
+ */
+
+#include <stdio.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include <kadm5/server_internal.h>
+#include <kdb.h>
+#include <com_err.h>
+#include "kdb5_util.h"
+#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
+#include <regex.h>
+#endif	/* HAVE_REGEX_H */
+
+/*
+ * Needed for master key conversion.
+ */
+static int			mkey_convert;
+static krb5_keyblock		new_master_keyblock;
+
+static int	backwards;
+static int	recursive;
+
+/*
+ * Use compile(3) if no regcomp present.
+ */
+#if	!defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H)
+#define	INIT		char *sp = instring;
+#define	GETC()		(*sp++)
+#define	PEEKC()		(*sp)
+#define	UNGETC(c)	(--sp)
+#define	RETURN(c)	return(c)
+#define	ERROR(c)	
+#define	RE_BUF_SIZE	1024
+#include <regexp.h>
+#endif	/* !HAVE_REGCOMP && HAVE_REGEXP_H */
+
+struct dump_args {
+    char		*programname;
+    FILE		*ofile;
+    krb5_context	kcontext;
+    char		**names;
+    int			nnames;
+    int			verbose;
+};
+
+static krb5_error_code dump_k5beta_iterator (krb5_pointer,
+					     krb5_db_entry *);
+static krb5_error_code dump_k5beta6_iterator (krb5_pointer,
+					      krb5_db_entry *);
+static krb5_error_code dump_k5beta6_iterator_ext (krb5_pointer,
+						  krb5_db_entry *,
+						  int);
+static krb5_error_code dump_k5beta7_princ (krb5_pointer,
+					   krb5_db_entry *);
+static krb5_error_code dump_k5beta7_princ_ext (krb5_pointer,
+					       krb5_db_entry *,
+					       int);
+static krb5_error_code dump_k5beta7_princ_withpolicy
+			(krb5_pointer, krb5_db_entry *);
+static krb5_error_code dump_ov_princ (krb5_pointer,
+				      krb5_db_entry *);
+static void dump_k5beta7_policy (void *, osa_policy_ent_t);
+
+typedef krb5_error_code (*dump_func)(krb5_pointer,
+				     krb5_db_entry *);
+
+static int process_k5beta_record (char *, krb5_context,
+				  FILE *, int, int *);
+static int process_k5beta6_record (char *, krb5_context,
+				   FILE *, int, int *);
+static int process_k5beta7_record (char *, krb5_context,
+				   FILE *, int, int *);
+static int process_ov_record (char *, krb5_context,
+			      FILE *, int, int *);
+typedef krb5_error_code (*load_func)(char *, krb5_context,
+				     FILE *, int, int *);
+
+typedef struct _dump_version {
+     char *name;
+     char *header;
+     int updateonly;
+     int create_kadm5;
+     dump_func dump_princ;
+     osa_adb_iter_policy_func dump_policy;
+     load_func load_record;
+} dump_version;
+
+dump_version old_version = {
+     "Kerberos version 5 old format",
+     "kdb5_edit load_dump version 2.0\n",
+     0,
+     1,
+     dump_k5beta_iterator,
+     NULL,
+     process_k5beta_record,
+};
+dump_version beta6_version = {
+     "Kerberos version 5 beta 6 format",
+     "kdb5_edit load_dump version 3.0\n",
+     0,
+     1,
+     dump_k5beta6_iterator,
+     NULL,
+     process_k5beta6_record,
+};
+dump_version beta7_version = {
+     "Kerberos version 5",
+     "kdb5_util load_dump version 4\n",
+     0,
+     0,
+     dump_k5beta7_princ,
+     dump_k5beta7_policy,
+     process_k5beta7_record,
+};
+dump_version ov_version = {
+     "OpenV*Secure V1.0",
+     "OpenV*Secure V1.0\t",
+     1,
+     1,
+     dump_ov_princ,
+     dump_k5beta7_policy,
+     process_ov_record
+};
+
+dump_version r1_3_version = {
+     "Kerberos version 5 release 1.3",
+     "kdb5_util load_dump version 5\n",
+     0,
+     0,
+     dump_k5beta7_princ_withpolicy,
+     dump_k5beta7_policy,
+     process_k5beta7_record,
+};
+
+/* External data */
+extern char		*current_dbname;
+extern krb5_boolean	dbactive;
+extern int		exit_status;
+extern krb5_context	util_context;
+extern kadm5_config_params global_params;
+
+/* Strings */
+
+#define k5beta_dump_header	"kdb5_edit load_dump version 2.0\n"
+
+static const char null_mprinc_name[] = "kdb5_dump@MISSING";
+
+/* Message strings */
+#define regex_err		"%s: regular expression error - %s\n"
+#define regex_merr		"%s: regular expression match error - %s\n"
+#define pname_unp_err		"%s: cannot unparse principal name (%s)\n"
+#define mname_unp_err		"%s: cannot unparse modifier name (%s)\n"
+#define nokeys_err		"%s: cannot find any standard key for %s\n"
+#define sdump_tl_inc_err	"%s: tagged data list inconsistency for %s (counted %d, stored %d)\n"
+#define stand_fmt_name		"Kerberos version 5"
+#define old_fmt_name		"Kerberos version 5 old format"
+#define b6_fmt_name		"Kerberos version 5 beta 6 format"
+#define ofopen_error		"%s: cannot open %s for writing (%s)\n"
+#define oflock_error		"%s: cannot lock %s (%s)\n"
+#define dumprec_err		"%s: error performing %s dump (%s)\n"
+#define dumphdr_err		"%s: error dumping %s header (%s)\n"
+#define trash_end_fmt		"%s(%d): ignoring trash at end of line: "
+#define read_name_string	"name string"
+#define read_key_type		"key type"
+#define read_key_data		"key data"
+#define read_pr_data1		"first set of principal attributes"
+#define read_mod_name		"modifier name"
+#define read_pr_data2		"second set of principal attributes"
+#define read_salt_data		"salt data"
+#define read_akey_type		"alternate key type"
+#define read_akey_data		"alternate key data"
+#define read_asalt_type		"alternate salt type"
+#define read_asalt_data		"alternate salt data"
+#define read_exp_data		"expansion data"
+#define store_err_fmt		"%s(%d): cannot store %s(%s)\n"
+#define add_princ_fmt		"%s\n"
+#define parse_err_fmt		"%s(%d): cannot parse %s (%s)\n"
+#define read_err_fmt		"%s(%d): cannot read %s\n"
+#define no_mem_fmt		"%s(%d): no memory for buffers\n"
+#define rhead_err_fmt		"%s(%d): cannot match size tokens\n"
+#define err_line_fmt		"%s: error processing line %d of %s\n"
+#define head_bad_fmt		"%s: dump header bad in %s\n"
+#define read_bytecnt		"record byte count"
+#define read_encdata		"encoded data"
+#define n_name_unp_fmt		"%s(%s): cannot unparse name\n"
+#define n_dec_cont_fmt		"%s(%s): cannot decode contents\n"
+#define read_nint_data		"principal static attributes"
+#define read_tcontents		"tagged data contents"
+#define read_ttypelen		"tagged data type and length"
+#define read_kcontents		"key data contents"
+#define read_ktypelen		"key data type and length"
+#define read_econtents		"extra data contents"
+#define k5beta_fmt_name		"Kerberos version 5 old format"
+#define standard_fmt_name	"Kerberos version 5 format"
+#define no_name_mem_fmt		"%s: cannot get memory for temporary name\n"
+#define ctx_err_fmt		"%s: cannot initialize Kerberos context\n"
+#define stdin_name		"standard input"
+#define remaster_err_fmt	"while re-encoding keys for principal %s with new master key"
+#define restfail_fmt		"%s: %s restore failed\n"
+#define close_err_fmt		"%s: cannot close database (%s)\n"
+#define dbinit_err_fmt		"%s: cannot initialize database (%s)\n"
+#define dblock_err_fmt		"%s: cannot initialize database lock (%s)\n"
+#define dbname_err_fmt		"%s: cannot set database name to %s (%s)\n"
+#define dbdelerr_fmt		"%s: cannot delete bad database %s (%s)\n"
+#define dbunlockerr_fmt		"%s: cannot unlock database %s (%s)\n"
+#define dbrenerr_fmt		"%s: cannot rename database %s to %s (%s)\n"
+#define dbcreaterr_fmt		"%s: cannot create database %s (%s)\n"
+#define dfile_err_fmt		"%s: cannot open %s (%s)\n"
+
+static const char oldoption[] = "-old";
+static const char b6option[] = "-b6";
+static const char b7option[] = "-b7";
+static const char verboseoption[] = "-verbose";
+static const char updateoption[] = "-update";
+static const char hashoption[] = "-hash";
+static const char ovoption[] = "-ov";
+static const char dump_tmptrail[] = "~";
+
+/*
+ * Re-encrypt the key_data with the new master key...
+ */
+static krb5_error_code master_key_convert(context, db_entry)
+    krb5_context	  context;
+    krb5_db_entry	* db_entry;
+{
+    krb5_error_code	retval;
+    krb5_keyblock 	v5plainkey, *key_ptr;
+    krb5_keysalt 	keysalt;
+    int	      i, j;
+    krb5_key_data	new_key_data, *key_data;
+    krb5_boolean	is_mkey;
+
+    is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ);
+
+    if (is_mkey && db_entry->n_key_data != 1)
+	    fprintf(stderr,
+		    "Master key db entry has %d keys, expecting only 1!\n",
+		    db_entry->n_key_data);
+    for (i=0; i < db_entry->n_key_data; i++) {
+	key_data = &db_entry->key_data[i];
+	if (key_data->key_data_length == 0)
+	    continue;
+	retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock,
+					     key_data, &v5plainkey,
+					     &keysalt);
+	if (retval)
+		return retval;
+
+	memset(&new_key_data, 0, sizeof(new_key_data));
+	key_ptr = is_mkey ? &new_master_keyblock : &v5plainkey;
+	retval = krb5_dbekd_encrypt_key_data(context, &new_master_keyblock,
+					     key_ptr, &keysalt,
+					     key_data->key_data_kvno,
+					     &new_key_data);
+	if (retval)
+		return retval;
+	krb5_free_keyblock_contents(context, &v5plainkey);
+	for (j = 0; j < key_data->key_data_ver; j++) {
+	    if (key_data->key_data_length[j]) {
+		free(key_data->key_data_contents[j]);
+	    }
+	}
+	*key_data = new_key_data;
+    }
+    return 0;
+}
+
+/*
+ * Update the "ok" file.
+ */
+void update_ok_file (file_name)
+     char *file_name;
+{
+	/* handle slave locking/failure stuff */
+	char *file_ok;
+	int fd;
+	static char ok[]=".dump_ok";
+
+	if ((file_ok = (char *)malloc(strlen(file_name) + strlen(ok) + 1))
+	    == NULL) {
+		com_err(progname, ENOMEM,
+			"while allocating filename for update_ok_file");
+		exit_status++;
+		return;
+	}
+	strcpy(file_ok, file_name);
+	strcat(file_ok, ok);
+	if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
+		com_err(progname, errno, "while creating 'ok' file, '%s'",
+			file_ok);
+		exit_status++;
+		free(file_ok);
+		return;
+	}
+	if (write(fd, "", 1) != 1) {
+	    com_err(progname, errno, "while writing to 'ok' file, '%s'",
+		    file_ok);
+	     exit_status++;
+	     free(file_ok);
+	     return;
+	}
+
+	free(file_ok);
+	close(fd);
+	return;
+}
+
+/*
+ * name_matches()	- See if a principal name matches a regular expression
+ *			  or string.
+ */
+static int
+name_matches(name, arglist)
+    char		*name;
+    struct dump_args	*arglist;
+{
+#if	HAVE_REGCOMP
+    regex_t	match_exp;
+    regmatch_t	match_match;
+    int		match_error;
+    char	match_errmsg[BUFSIZ];
+    size_t	errmsg_size;
+#elif	HAVE_REGEXP_H
+    char	regexp_buffer[RE_BUF_SIZE];
+#elif	HAVE_RE_COMP
+    extern char	*re_comp();
+    char	*re_result;
+#endif	/* HAVE_RE_COMP */
+    int		i, match;
+
+    /*
+     * Plow, brute force, through the list of names/regular expressions.
+     */
+    match = (arglist->nnames) ? 0 : 1;
+    for (i=0; i<arglist->nnames; i++) {
+#if	HAVE_REGCOMP
+	/*
+	 * Compile the regular expression.
+	 */
+	match_error = regcomp(&match_exp, arglist->names[i], REG_EXTENDED);
+	if (match_error) {
+	    errmsg_size = regerror(match_error,
+				   &match_exp,
+				   match_errmsg,
+				   sizeof(match_errmsg));
+	    fprintf(stderr, regex_err, arglist->programname, match_errmsg);
+	    break;
+	}
+	/*
+	 * See if we have a match.
+	 */
+	match_error = regexec(&match_exp, name, 1, &match_match, 0);
+	if (match_error) {
+	    if (match_error != REG_NOMATCH) {
+		errmsg_size = regerror(match_error,
+				       &match_exp,
+				       match_errmsg,
+				       sizeof(match_errmsg));
+		fprintf(stderr, regex_merr,
+			arglist->programname, match_errmsg);
+		break;
+	    }
+	}
+	else {
+	    /*
+	     * We have a match.  See if it matches the whole
+	     * name.
+	     */
+	    if ((match_match.rm_so == 0) &&
+		(match_match.rm_eo == strlen(name)))
+		match = 1;
+	}
+	regfree(&match_exp);
+#elif	HAVE_REGEXP_H
+	/*
+	 * Compile the regular expression.
+	 */
+	compile(arglist->names[i],
+		regexp_buffer, 
+		®exp_buffer[RE_BUF_SIZE],
+		'\0');
+	if (step(name, regexp_buffer)) {
+	    if ((loc1 == name) &&
+		(loc2 == &name[strlen(name)]))
+		match = 1;
+	}
+#elif	HAVE_RE_COMP
+	/*
+	 * Compile the regular expression.
+	 */
+	if (re_result = re_comp(arglist->names[i])) {
+	    fprintf(stderr, regex_err, arglist->programname, re_result);
+	    break;
+	}
+	if (re_exec(name))
+	    match = 1;
+#else	/* HAVE_RE_COMP */
+	/*
+	 * If no regular expression support, then just compare the strings.
+	 */
+	if (!strcmp(arglist->names[i], name))
+	    match = 1;
+#endif	/* HAVE_REGCOMP */
+	if (match)
+	    break;
+    }
+    return(match);
+}
+
+static krb5_error_code
+find_enctype(dbentp, enctype, salttype, kentp)
+    krb5_db_entry	*dbentp;
+    krb5_enctype	enctype;
+    krb5_int32		salttype;
+    krb5_key_data	**kentp;
+{
+    int			i;
+    int			maxkvno;
+    krb5_key_data	*datap;
+
+    maxkvno = -1;
+    datap = (krb5_key_data *) NULL;
+    for (i=0; i<dbentp->n_key_data; i++) {
+	if (( (krb5_enctype)dbentp->key_data[i].key_data_type[0] == enctype) &&
+	    ((dbentp->key_data[i].key_data_type[1] == salttype) ||
+	     (salttype < 0))) {
+	    maxkvno = dbentp->key_data[i].key_data_kvno;
+	    datap = &dbentp->key_data[i];
+	}
+    }
+    if (maxkvno >= 0) {
+	*kentp = datap;
+	return(0);
+    }
+    return(ENOENT);    
+}
+
+#if 0
+/*
+ * dump_k5beta_header()	- Make a dump header that is recognizable by Kerberos
+ *			  Version 5 Beta 5 and previous releases.
+ */
+static krb5_error_code
+dump_k5beta_header(arglist)
+    struct dump_args *arglist;
+{
+    /* The old header consists of the leading string */
+    fprintf(arglist->ofile, k5beta_dump_header);
+    return(0);
+}
+#endif
+
+/*
+ * dump_k5beta_iterator()	- Dump an entry in a format that is usable
+ *				  by Kerberos Version 5 Beta 5 and previous
+ *				  releases.
+ */
+static krb5_error_code
+dump_k5beta_iterator(ptr, entry)
+    krb5_pointer	ptr;
+    krb5_db_entry	*entry;
+{
+    krb5_error_code	retval;
+    struct dump_args	*arg;
+    char		*name, *mod_name;
+    krb5_principal	mod_princ;
+    krb5_key_data	*pkey, *akey, nullkey;
+    krb5_timestamp	mod_date, last_pwd_change;
+    int			i;
+
+    /* Initialize */
+    arg = (struct dump_args *) ptr;
+    name = (char *) NULL;
+    mod_name = (char *) NULL;
+    memset(&nullkey, 0, sizeof(nullkey));
+
+    /*
+     * Flatten the principal name.
+     */
+    if ((retval = krb5_unparse_name(arg->kcontext,
+				    entry->princ,
+				    &name))) {
+	fprintf(stderr, pname_unp_err, 
+		arg->programname, error_message(retval));
+	return(retval);
+    }
+
+    /*
+     * Re-encode the keys in the new master key, if necessary.
+     */
+    if (mkey_convert) {
+	retval = master_key_convert(arg->kcontext, entry);
+	if (retval) {
+	    com_err(arg->programname, retval, remaster_err_fmt, name);
+	    return retval;
+	}
+    }
+    
+    /*
+     * If we don't have any match strings, or if our name matches, then
+     * proceed with the dump, otherwise, just forget about it.
+     */
+    if (!arg->nnames || name_matches(name, arg)) {
+	/*
+	 * Deserialize the modifier record.
+	 */
+	mod_name = (char *) NULL;
+	mod_princ = NULL;
+	last_pwd_change = mod_date = 0;
+	pkey = akey = (krb5_key_data *) NULL;
+	if (!(retval = krb5_dbe_lookup_mod_princ_data(arg->kcontext,
+						      entry,
+						      &mod_date,
+						      &mod_princ))) {
+	    if (mod_princ) {
+		/*
+		 * Flatten the modifier name.
+		 */
+		if ((retval = krb5_unparse_name(arg->kcontext,
+						mod_princ,
+						&mod_name)))
+		    fprintf(stderr, mname_unp_err, arg->programname,
+			    error_message(retval));
+		krb5_free_principal(arg->kcontext, mod_princ);
+	    }
+	}
+	if (!mod_name)
+	    mod_name = strdup(null_mprinc_name);
+
+	/*
+	 * Find the last password change record and set it straight.
+	 */
+	if ((retval =
+	     krb5_dbe_lookup_last_pwd_change(arg->kcontext, entry,
+					     &last_pwd_change))) {
+	    fprintf(stderr, nokeys_err, arg->programname, name);
+	    krb5_xfree(mod_name);
+	    krb5_xfree(name);
+	    return(retval);
+	}
+
+	/*
+	 * Find the 'primary' key and the 'alternate' key.
+	 */
+	if ((retval = find_enctype(entry,
+				   ENCTYPE_DES_CBC_CRC,
+				   KRB5_KDB_SALTTYPE_NORMAL,
+				   &pkey)) &&
+	    (retval = find_enctype(entry,
+				   ENCTYPE_DES_CBC_CRC,
+				   KRB5_KDB_SALTTYPE_V4,
+				   &akey))) {
+	    fprintf(stderr, nokeys_err, arg->programname, name);
+	    krb5_xfree(mod_name);
+	    krb5_xfree(name);
+	    return(retval);
+	}
+
+	/* If we only have one type, then ship it out as the primary. */
+	if (!pkey && akey) {
+	    pkey = akey;
+	    akey = &nullkey;
+	}
+	else {
+	    if (!akey)
+		akey = &nullkey;
+	}
+
+	/*
+	 * First put out strings representing the length of the variable
+	 * length data in this record, then the name and the primary key type.
+	 */
+	fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%s\t%d\t", strlen(name),
+		strlen(mod_name),
+		(krb5_int32) pkey->key_data_length[0],
+		(krb5_int32) akey->key_data_length[0],
+		(krb5_int32) pkey->key_data_length[1],
+		(krb5_int32) akey->key_data_length[1],
+		name,
+		(krb5_int32) pkey->key_data_type[0]);
+	for (i=0; i<pkey->key_data_length[0]; i++) {
+	    fprintf(arg->ofile, "%02x", pkey->key_data_contents[0][i]);
+	}
+	/*
+	 * Second, print out strings representing the standard integer
+	 * data in this record.
+	 */
+	fprintf(arg->ofile,
+		"\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%s\t%u\t%u\t%u\t",
+		(krb5_int32) pkey->key_data_kvno,
+		entry->max_life, entry->max_renewable_life,
+		1 /* Fake mkvno */, entry->expiration, entry->pw_expiration,
+		last_pwd_change, entry->last_success, entry->last_failed,
+		entry->fail_auth_count, mod_name, mod_date,
+		entry->attributes, pkey->key_data_type[1]);
+
+	/* Pound out the salt data, if present. */
+	for (i=0; i<pkey->key_data_length[1]; i++) {
+	    fprintf(arg->ofile, "%02x", pkey->key_data_contents[1][i]);
+	}
+	/* Pound out the alternate key type and contents */
+	fprintf(arg->ofile, "\t%u\t", akey->key_data_type[0]);
+	for (i=0; i<akey->key_data_length[0]; i++) {
+	    fprintf(arg->ofile, "%02x", akey->key_data_contents[0][i]);
+	}
+	/* Pound out the alternate salt type and contents */
+	fprintf(arg->ofile, "\t%u\t", akey->key_data_type[1]);
+	for (i=0; i<akey->key_data_length[1]; i++) {
+	    fprintf(arg->ofile, "%02x", akey->key_data_contents[1][i]);
+	}
+	/* Pound out the expansion data. (is null) */
+	for (i=0; i < 8; i++) {
+	    fprintf(arg->ofile, "\t%u", 0);
+	}
+	fprintf(arg->ofile, ";\n");
+	/* If we're blabbing, do it */
+	if (arg->verbose)
+	    fprintf(stderr, "%s\n", name);
+	krb5_xfree(mod_name);
+    }
+    krb5_xfree(name);
+    return(0);
+}
+
+/*
+ * dump_k5beta6_iterator()	- Output a dump record in krb5b6 format.
+ */
+static krb5_error_code
+dump_k5beta6_iterator(ptr, entry)
+    krb5_pointer	ptr;
+    krb5_db_entry	*entry;
+{
+    return dump_k5beta6_iterator_ext(ptr, entry, 0);
+}
+
+static krb5_error_code
+dump_k5beta6_iterator_ext(ptr, entry, kadm)
+    krb5_pointer	ptr;
+    krb5_db_entry	*entry;
+    int			kadm;
+{
+    krb5_error_code	retval;
+    struct dump_args	*arg;
+    char		*name;
+    krb5_tl_data	*tlp;
+    krb5_key_data	*kdata;
+    int			counter, skip, i, j;
+
+    /* Initialize */
+    arg = (struct dump_args *) ptr;
+    name = (char *) NULL;
+
+    /*
+     * Flatten the principal name.
+     */
+    if ((retval = krb5_unparse_name(arg->kcontext,
+				    entry->princ,
+				    &name))) {
+	fprintf(stderr, pname_unp_err, 
+		arg->programname, error_message(retval));
+	return(retval);
+    }
+
+    /*
+     * Re-encode the keys in the new master key, if necessary.
+     */
+    if (mkey_convert) {
+	retval = master_key_convert(arg->kcontext, entry);
+	if (retval) {
+	    com_err(arg->programname, retval, remaster_err_fmt, name);
+	    return retval;
+	}
+    }
+    
+    /*
+     * If we don't have any match strings, or if our name matches, then
+     * proceed with the dump, otherwise, just forget about it.
+     */
+    if (!arg->nnames || name_matches(name, arg)) {
+	/*
+	 * We'd like to just blast out the contents as they would appear in
+	 * the database so that we can just suck it back in, but it doesn't
+	 * lend itself to easy editing.
+	 */
+
+	/*
+	 * The dump format is as follows:
+	 *	len strlen(name) n_tl_data n_key_data e_length
+	 *	name
+	 *	attributes max_life max_renewable_life expiration
+	 *	pw_expiration last_success last_failed fail_auth_count
+	 *	n_tl_data*[type length <contents>]
+	 *	n_key_data*[ver kvno ver*(type length <contents>)]
+	 *	<e_data>
+	 * Fields which are not encapsulated by angle-brackets are to appear
+	 * verbatim.  A bracketed field's absence is indicated by a -1 in its
+	 * place
+	 */
+
+	/*
+	 * Make sure that the tagged list is reasonably correct.
+	 */
+	counter = skip = 0;
+	for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) {
+	     /*
+	      * don't dump tl data types we know aren't understood by
+	      * earlier revisions [krb5-admin/89]
+	      */
+	     switch (tlp->tl_data_type) {
+	     case KRB5_TL_KADM_DATA:
+		  if (kadm)
+		      counter++;
+		  else
+		      skip++;
+		  break;
+	     default:
+		  counter++;
+		  break;
+	     }
+	}
+	
+	if (counter + skip == entry->n_tl_data) {
+	    /* Pound out header */
+	    fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%s\t",
+		    (int) entry->len,
+		    strlen(name),
+		    counter,
+		    (int) entry->n_key_data,
+		    (int) entry->e_length,
+		    name);
+	    fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",
+		    entry->attributes,
+		    entry->max_life,
+		    entry->max_renewable_life,
+		    entry->expiration,
+		    entry->pw_expiration,
+		    entry->last_success,
+		    entry->last_failed,
+		    entry->fail_auth_count);
+	    /* Pound out tagged data. */
+	    for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) {
+		if (tlp->tl_data_type == KRB5_TL_KADM_DATA && !kadm)
+		     continue; /* see above, [krb5-admin/89] */
+
+		fprintf(arg->ofile, "%d\t%d\t",
+			(int) tlp->tl_data_type,
+			(int) tlp->tl_data_length);
+		if (tlp->tl_data_length)
+		    for (i=0; i<tlp->tl_data_length; i++)
+			fprintf(arg->ofile, "%02x", tlp->tl_data_contents[i]);
+		else
+		    fprintf(arg->ofile, "%d", -1);
+		fprintf(arg->ofile, "\t");
+	    }
+
+	    /* Pound out key data */
+	    for (counter=0; counter<entry->n_key_data; counter++) {
+		kdata = &entry->key_data[counter];
+		fprintf(arg->ofile, "%d\t%d\t",
+			(int) kdata->key_data_ver,
+			(int) kdata->key_data_kvno);
+		for (i=0; i<kdata->key_data_ver; i++) {
+		    fprintf(arg->ofile, "%d\t%d\t",
+			    kdata->key_data_type[i],
+			    kdata->key_data_length[i]);
+		    if (kdata->key_data_length[i])
+			for (j=0; j<kdata->key_data_length[i]; j++)
+			    fprintf(arg->ofile, "%02x",
+				    kdata->key_data_contents[i][j]);
+		    else
+			fprintf(arg->ofile, "%d", -1);
+		    fprintf(arg->ofile, "\t");
+		}
+	    }
+
+	    /* Pound out extra data */
+	    if (entry->e_length)
+		for (i=0; i<entry->e_length; i++)
+		    fprintf(arg->ofile, "%02x", entry->e_data[i]);
+	    else
+		fprintf(arg->ofile, "%d", -1);
+
+	    /* Print trailer */
+	    fprintf(arg->ofile, ";\n");
+
+	    if (arg->verbose)
+		fprintf(stderr, "%s\n", name);
+	}
+	else {
+	    fprintf(stderr, sdump_tl_inc_err,
+		    arg->programname, name, counter+skip,
+		    (int) entry->n_tl_data); 
+	    retval = EINVAL;
+	}
+    }
+    krb5_xfree(name);
+    return(retval);
+}
+
+/*
+ * dump_k5beta7_iterator()	- Output a dump record in krb5b7 format.
+ */
+static krb5_error_code
+dump_k5beta7_princ(ptr, entry)
+    krb5_pointer	ptr;
+    krb5_db_entry	*entry;
+{
+    return dump_k5beta7_princ_ext(ptr, entry, 0);
+}
+
+static krb5_error_code
+dump_k5beta7_princ_ext(ptr, entry, kadm)
+    krb5_pointer	ptr;
+    krb5_db_entry	*entry;
+    int			kadm;
+{
+     krb5_error_code retval;
+     struct dump_args *arg;
+     char *name;
+     int tmp_nnames;
+
+     /* Initialize */
+     arg = (struct dump_args *) ptr;
+     name = (char *) NULL;
+
+     /*
+      * Flatten the principal name.
+      */
+     if ((retval = krb5_unparse_name(arg->kcontext,
+				     entry->princ,
+				     &name))) {
+	  fprintf(stderr, pname_unp_err, 
+		  arg->programname, error_message(retval));
+	  return(retval);
+     }
+     /*
+      * If we don't have any match strings, or if our name matches, then
+      * proceed with the dump, otherwise, just forget about it.
+      */
+     if (!arg->nnames || name_matches(name, arg)) {
+	  fprintf(arg->ofile, "princ\t");
+	  
+	  /* save the callee from matching the name again */
+	  tmp_nnames = arg->nnames;
+	  arg->nnames = 0;
+	  retval = dump_k5beta6_iterator_ext(ptr, entry, kadm);
+	  arg->nnames = tmp_nnames;
+     }
+
+     free(name);
+     return retval;
+}
+
+static krb5_error_code
+dump_k5beta7_princ_withpolicy(ptr, entry)
+    krb5_pointer	ptr;
+    krb5_db_entry	*entry;
+{
+    return dump_k5beta7_princ_ext(ptr, entry, 1);
+}
+
+void dump_k5beta7_policy(void *data, osa_policy_ent_t entry)
+{
+     struct dump_args *arg;
+
+     arg = (struct dump_args *) data;
+     fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", entry->name,
+	     entry->pw_min_life, entry->pw_max_life, entry->pw_min_length,
+	     entry->pw_min_classes, entry->pw_history_num,
+	     entry->policy_refcnt);
+}
+
+static void print_key_data(FILE *f, krb5_key_data *key_data)
+{
+     int c;
+     
+     fprintf(f, "%d\t%d\t", key_data->key_data_type[0],
+	     key_data->key_data_length[0]);
+     for(c = 0; c < key_data->key_data_length[0]; c++) 
+	  fprintf(f, "%02x ",
+		  key_data->key_data_contents[0][c]);
+}
+
+/*
+ * Function: print_princ
+ * 
+ * Purpose: output osa_adb_princ_ent data in a human
+ *	    readable format (which is a format suitable for
+ *	    ovsec_adm_import consumption)
+ *
+ * Arguments:
+ *	data		(input) pointer to a structure containing a FILE *
+ *			        and a record counter.
+ *	entry		(input) entry to get dumped.
+ * 	<return value>	void
+ *
+ * Requires:
+ *	nuttin
+ * 
+ * Effects:
+ *	writes data to the specified file pointerp.
+ *
+ * Modifies:
+ *	nuttin
+ * 
+ */
+static krb5_error_code dump_ov_princ(krb5_pointer ptr, krb5_db_entry *kdb)
+{
+    char *princstr;
+    int	x, y, foundcrc;
+    struct dump_args *arg;
+    krb5_tl_data tl_data;
+    osa_princ_ent_rec adb;
+    XDR xdrs;
+
+    arg = (struct dump_args *) ptr;
+    /*
+     * XXX Currently, lookup_tl_data always returns zero; it sets
+     * tl_data->tl_data_length to zero if the type isn't found.
+     * This should be fixed...
+     */
+    /*
+     * XXX Should this function do nothing for a principal with no
+     * admin data, or print a record of "default" values?   See
+     * comment in server_kdb.c to help decide.
+     */
+    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+    if (krb5_dbe_lookup_tl_data(arg->kcontext, kdb, &tl_data)
+	|| (tl_data.tl_data_length == 0))
+	 return 0;
+
+    memset(&adb, 0, sizeof(adb));
+    xdrmem_create(&xdrs, tl_data.tl_data_contents,
+		  tl_data.tl_data_length, XDR_DECODE);
+    if (! xdr_osa_princ_ent_rec(&xdrs, &adb)) {
+	 xdr_destroy(&xdrs);
+	 return(KADM5_XDR_FAILURE);
+    }
+    xdr_destroy(&xdrs);
+    
+    krb5_unparse_name(arg->kcontext, kdb->princ, &princstr);
+    fprintf(arg->ofile, "princ\t%s\t", princstr);
+    if(adb.policy == NULL)
+	fputc('\t', arg->ofile);
+    else
+	fprintf(arg->ofile, "%s\t", adb.policy);
+    fprintf(arg->ofile, "%lx\t%d\t%d\t%d", adb.aux_attributes,
+	    adb.old_key_len,adb.old_key_next, adb.admin_history_kvno);
+
+    for (x = 0; x < adb.old_key_len; x++) {
+	 foundcrc = 0;
+	 for (y = 0; y < adb.old_keys[x].n_key_data; y++) {
+	      krb5_key_data *key_data = &adb.old_keys[x].key_data[y];
+
+	      if (key_data->key_data_type[0] != ENCTYPE_DES_CBC_CRC)
+		   continue;
+	      if (foundcrc) {
+		   fprintf(stderr, "Warning!  Multiple DES-CBC-CRC keys "
+			   "for principal %s; skipping duplicates.\n",
+			   princstr);
+		   continue;
+	      }
+	      foundcrc++;
+
+	      fputc('\t', arg->ofile);
+	      print_key_data(arg->ofile, key_data);
+	 }
+	 if (!foundcrc)
+	      fprintf(stderr, "Warning!  No DES-CBC-CRC key for principal "
+		      "%s, cannot generate OV-compatible record; skipping\n",
+		      princstr);
+    }
+
+    fputc('\n', arg->ofile);
+    free(princstr);
+    return 0;
+}
+
+/*
+ * usage is:
+ *	dump_db [-old] [-b6] [-b7] [-ov] [-verbose] [-mkey_convert]
+ *		[-new_mkey_file mkey_file] [-rev] [-recurse]
+ *		[filename [principals...]]
+ */
+void
+dump_db(argc, argv)
+    int		argc;
+    char	**argv;
+{
+    FILE		*f;
+    struct dump_args	arglist;
+    char		*programname;
+    char		*ofile;
+    krb5_error_code	kret, retval;
+    dump_version	*dump;
+    int			aindex;
+    krb5_boolean	locked;
+    char		*new_mkey_file = 0;
+	
+    /*
+     * Parse the arguments.
+     */
+    programname = argv[0];
+    if (strrchr(programname, (int) '/'))
+	programname = strrchr(argv[0], (int) '/') + 1;
+    ofile = (char *) NULL;
+    dump = &r1_3_version;
+    arglist.verbose = 0;
+    new_mkey_file = 0;
+    mkey_convert = 0;
+    backwards = 0;
+    recursive = 0;
+
+    /*
+     * Parse the qualifiers.
+     */
+    for (aindex = 1; aindex < argc; aindex++) {
+	if (!strcmp(argv[aindex], oldoption))
+	     dump = &old_version;
+	else if (!strcmp(argv[aindex], b6option))
+	     dump = &beta6_version;
+	else if (!strcmp(argv[aindex], b7option))
+	     dump = &beta7_version;
+	else if (!strcmp(argv[aindex], ovoption))
+	     dump = &ov_version;
+	else if (!strcmp(argv[aindex], verboseoption))
+	    arglist.verbose++;
+	else if (!strcmp(argv[aindex], "-mkey_convert"))
+	    mkey_convert = 1;
+	else if (!strcmp(argv[aindex], "-new_mkey_file")) {
+	    new_mkey_file = argv[++aindex];
+	    mkey_convert = 1;
+        } else if (!strcmp(argv[aindex], "-rev"))
+	    backwards = 1;
+	else if (!strcmp(argv[aindex], "-recurse"))
+	    recursive = 1;
+	else
+	    break;
+    }
+
+    arglist.names = (char **) NULL;
+    arglist.nnames = 0;
+    if (aindex < argc) {
+	ofile = argv[aindex];
+	aindex++;
+	if (aindex < argc) {
+	    arglist.names = &argv[aindex];
+	    arglist.nnames = argc - aindex;
+	}
+    }
+
+    /*
+     * Make sure the database is open.  The policy database only has
+     * to be opened if we try a dump that uses it.
+     */
+    if (!dbactive) {
+	com_err(argv[0], 0, Err_no_database);
+	exit_status++;
+	return;
+    }
+
+    /*
+     * If we're doing a master key conversion, set up for it.
+     */
+    if (mkey_convert) {
+	    if (!valid_master_key) {
+		    /* TRUE here means read the keyboard, but only once */
+		    retval = krb5_db_fetch_mkey(util_context,
+						master_princ,
+						master_keyblock.enctype,
+						TRUE, FALSE,
+						(char *) NULL, 0,
+						&master_keyblock);
+		    if (retval) {
+			    com_err(argv[0], retval,
+				    "while reading master key");
+			    exit(1);
+		    }
+		    retval = krb5_db_verify_master_key(util_context,
+						       master_princ,
+						       &master_keyblock);
+		    if (retval) {
+			    com_err(argv[0], retval,
+				    "while verifying master key");
+			    exit(1);
+		    }
+	    }
+	    new_master_keyblock.enctype = global_params.enctype;
+	    if (new_master_keyblock.enctype == ENCTYPE_UNKNOWN)
+		    new_master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
+	    if (!new_mkey_file)
+		    printf("Please enter new master key....\n");
+	    if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 
+					     new_master_keyblock.enctype,
+					     (new_mkey_file == 0) ? 
+					        (krb5_boolean) 1 : 0, 
+					     TRUE, 
+					     new_mkey_file, 0,
+					     &new_master_keyblock))) { 
+		    com_err(argv[0], retval, "while reading new master key");
+		    exit(1);
+	    }
+    }
+
+    kret = 0;
+    locked = 0;
+    if (ofile && strcmp(ofile, "-")) {
+	/*
+	 * Discourage accidental dumping to filenames beginning with '-'.
+	 */
+	if (ofile[0] == '-')
+	    usage();
+	/*
+	 * Make sure that we don't open and truncate on the fopen,
+	 * since that may hose an on-going kprop process.
+	 * 
+	 * We could also control this by opening for read and
+	 * write, doing an flock with LOCK_EX, and then
+	 * truncating the file once we have gotten the lock,
+	 * but that would involve more OS dependencies than I
+	 * want to get into.
+	 */
+	unlink(ofile);
+	if (!(f = fopen(ofile, "w"))) {
+	    fprintf(stderr, ofopen_error,
+		    programname, ofile, error_message(errno));
+	    exit_status++;
+	    return;
+       }
+	if ((kret = krb5_lock_file(util_context,
+				   fileno(f),
+				   KRB5_LOCKMODE_EXCLUSIVE))) {
+	    fprintf(stderr, oflock_error,
+		    programname, ofile, error_message(kret));
+	    exit_status++;
+	}
+	else
+	    locked = 1;
+    } else {
+	f = stdout;
+    }
+    if (f && !(kret)) {
+	arglist.programname = programname;
+	arglist.ofile = f;
+	arglist.kcontext = util_context;
+	fprintf(arglist.ofile, "%s", dump->header);
+	if (dump->header[strlen(dump->header)-1] != '\n')
+	     fputc('\n', arglist.ofile);
+	
+	if ((kret = krb5_db_iterate(util_context,
+				    NULL,
+				    dump->dump_princ,
+				    (krb5_pointer) &arglist))) { /* TBD: backwards and recursive not supported */
+	     fprintf(stderr, dumprec_err,
+		     programname, dump->name, error_message(kret));
+	     exit_status++;
+	}
+	if (dump->dump_policy &&
+	    (kret = krb5_db_iter_policy( util_context, "*", dump->dump_policy,
+					 &arglist))) { 
+	     fprintf(stderr, dumprec_err, programname, dump->name,
+		     error_message(kret));
+	     exit_status++;
+	}
+	if (ofile && f != stdout && !exit_status) {
+	    if (locked) {
+		(void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK);
+		locked = 0;
+	    }
+	    fclose(f);
+	    update_ok_file(ofile);
+	}
+    }
+    if (locked)
+	(void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK);
+}
+
+/*
+ * Read a string of bytes while counting the number of lines passed.
+ */
+static int
+read_string(f, buf, len, lp)
+    FILE	*f;
+    char	*buf;
+    int		len;
+    int		*lp;
+{
+    int c;
+    int i, retval;
+
+    retval = 0;
+    for (i=0; i<len; i++) {
+	c = fgetc(f);
+	if (c < 0) {
+	    retval = 1;
+	    break;
+	}
+	if (c == '\n')
+	    (*lp)++;
+	buf[i] = (char) c;
+    }
+    buf[len] = '\0';
+    return(retval);
+}
+
+/*
+ * Read a string of two character representations of bytes.
+ */
+static int
+read_octet_string(f, buf, len)
+    FILE	*f;
+    krb5_octet	*buf;
+    int		len;
+{
+    int c;
+    int i, retval;
+
+    retval = 0;
+    for (i=0; i<len; i++) {
+	if (fscanf(f, "%02x", &c) != 1) {
+	    retval = 1;
+	    break;
+	}
+	buf[i] = (krb5_octet) c;
+    }
+    return(retval);
+}
+
+/*
+ * Find the end of an old format record.
+ */
+static void
+find_record_end(f, fn, lineno)
+    FILE	*f;
+    char	*fn;
+    int		lineno;
+{
+    int	ch;
+
+    if (((ch = fgetc(f)) != ';') || ((ch = fgetc(f)) != '\n')) {
+	fprintf(stderr, trash_end_fmt, fn, lineno);
+	while (ch != '\n') {
+	    putc(ch, stderr);
+	    ch = fgetc(f);
+	}
+	putc(ch, stderr);
+    }
+}
+
+#if 0
+/*
+ * update_tl_data()	- Generate the tl_data entries.
+ */
+static krb5_error_code
+update_tl_data(kcontext, dbentp, mod_name, mod_date, last_pwd_change)
+    krb5_context	kcontext;
+    krb5_db_entry	*dbentp;
+    krb5_principal	mod_name;
+    krb5_timestamp	mod_date;
+    krb5_timestamp	last_pwd_change;
+{
+    krb5_error_code	kret;
+
+    kret = 0 ;
+
+    /*
+     * Handle modification principal.
+     */
+    if (mod_name) {
+	krb5_tl_mod_princ	mprinc;
+
+	memset(&mprinc, 0, sizeof(mprinc));
+	if (!(kret = krb5_copy_principal(kcontext,
+					 mod_name,
+					 &mprinc.mod_princ))) {
+	    mprinc.mod_date = mod_date;
+	    kret = krb5_dbe_encode_mod_princ_data(kcontext,
+						  &mprinc,
+						  dbentp);
+	}
+	if (mprinc.mod_princ)
+	    krb5_free_principal(kcontext, mprinc.mod_princ);
+    }
+
+    /*
+     * Handle last password change.
+     */
+    if (!kret) {
+	krb5_tl_data	*pwchg;
+	krb5_boolean	linked;
+
+	/* Find a previously existing entry */
+	for (pwchg = dbentp->tl_data;
+	     (pwchg) && (pwchg->tl_data_type != KRB5_TL_LAST_PWD_CHANGE);
+	     pwchg = pwchg->tl_data_next);
+
+	/* Check to see if we found one. */
+	linked = 0;
+	if (!pwchg) {
+	    /* No, allocate a new one */
+	    if ((pwchg = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) {
+		memset(pwchg, 0, sizeof(krb5_tl_data));
+		if (!(pwchg->tl_data_contents =
+		      (krb5_octet *) malloc(sizeof(krb5_timestamp)))) {
+		    free(pwchg);
+		    pwchg = (krb5_tl_data *) NULL;
+		}
+		else {
+		    pwchg->tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+		    pwchg->tl_data_length =
+			(krb5_int16) sizeof(krb5_timestamp);
+		}
+	    }
+	}
+	else
+	    linked = 1;
+
+	/* Do we have an entry? */
+	if (pwchg && pwchg->tl_data_contents) {
+	    /* Encode it */
+	    krb5_kdb_encode_int32(last_pwd_change, pwchg->tl_data_contents);
+	    /* Link it in if necessary */
+	    if (!linked) {
+		pwchg->tl_data_next = dbentp->tl_data;
+		dbentp->tl_data = pwchg;
+		dbentp->n_tl_data++;
+	    }
+	}
+	else
+	    kret = ENOMEM;
+    }
+
+    return(kret);
+}
+#endif
+
+/*
+ * process_k5beta_record()	- Handle a dump record in old format.
+ *
+ * Returns -1 for end of file, 0 for success and 1 for failure.
+ */
+static int
+process_k5beta_record(fname, kcontext, filep, verbose, linenop)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			verbose;
+    int			*linenop;
+{
+    int			nmatched;
+    int			retval;
+    krb5_db_entry	dbent;
+    int			name_len, mod_name_len, key_len;
+    int			alt_key_len, salt_len, alt_salt_len;
+    char		*name;
+    char		*mod_name;
+    int			tmpint1, tmpint2, tmpint3;
+    int			error;
+    const char		*try2read;
+    int			i;
+    krb5_key_data	*pkey, *akey;
+    krb5_timestamp	last_pwd_change, mod_date;
+    krb5_principal	mod_princ;
+    krb5_error_code	kret;
+
+    try2read = (char *) NULL;
+    (*linenop)++;
+    retval = 1;
+    memset((char *)&dbent, 0, sizeof(dbent));
+
+    /* Make sure we've got key_data entries */
+    if (krb5_dbe_create_key_data(kcontext, &dbent) ||
+	krb5_dbe_create_key_data(kcontext, &dbent)) {
+	krb5_db_free_principal(kcontext, &dbent, 1);
+	return(1);
+    }
+    pkey = &dbent.key_data[0];
+    akey = &dbent.key_data[1];
+
+    /*
+     * Match the sizes.  6 tokens to match.
+     */
+    nmatched = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t",
+		      &name_len, &mod_name_len, &key_len,
+		      &alt_key_len, &salt_len, &alt_salt_len);
+    if (nmatched == 6) {
+        pkey->key_data_length[0] = key_len;
+	akey->key_data_length[0] = alt_key_len;
+	pkey->key_data_length[1] = salt_len;
+	akey->key_data_length[1] = alt_salt_len;
+	name = (char *) NULL;
+	mod_name = (char *) NULL;
+	/*
+	 * Get the memory for the variable length fields.
+	 */
+	if ((name = (char *) malloc((size_t) (name_len + 1))) &&
+	    (mod_name = (char *) malloc((size_t) (mod_name_len + 1))) &&
+	    (!key_len ||
+	     (pkey->key_data_contents[0] = 
+	      (krb5_octet *) malloc((size_t) (key_len + 1)))) &&
+	    (!alt_key_len ||
+	     (akey->key_data_contents[0] = 
+	      (krb5_octet *) malloc((size_t) (alt_key_len + 1)))) &&
+	    (!salt_len ||
+	     (pkey->key_data_contents[1] = 
+	      (krb5_octet *) malloc((size_t) (salt_len + 1)))) &&
+	    (!alt_salt_len ||
+	     (akey->key_data_contents[1] = 
+	      (krb5_octet *) malloc((size_t) (alt_salt_len + 1))))
+	    ) {
+	    error = 0;
+
+	    /* Read the principal name */
+	    if (read_string(filep, name, name_len, linenop)) {
+		try2read = read_name_string;
+		error++;
+	    }
+	    /* Read the key type */
+	    if (!error && (fscanf(filep, "\t%d\t", &tmpint1) != 1)) {
+		try2read = read_key_type;
+		error++;
+	    }
+	    pkey->key_data_type[0] = tmpint1;
+	    /* Read the old format key */
+	    if (!error && read_octet_string(filep,
+					    pkey->key_data_contents[0],
+					    pkey->key_data_length[0])) {
+		try2read = read_key_data;
+		error++;
+	    }
+	    /* convert to a new format key */
+	    /* the encrypted version is stored as the unencrypted key length
+	       (4 bytes, MSB first) followed by the encrypted key. */
+	    if ((pkey->key_data_length[0] > 4)
+		&& (pkey->key_data_contents[0][0] == 0)
+		&& (pkey->key_data_contents[0][1] == 0)) {
+	      /* this really does look like an old key, so drop and swap */
+	      /* the *new* length is 2 bytes, LSB first, sigh. */
+	      size_t shortlen = pkey->key_data_length[0]-4+2;
+	      krb5_octet *shortcopy = (krb5_octet *) malloc(shortlen);
+	      krb5_octet *origdata = pkey->key_data_contents[0];
+	      shortcopy[0] = origdata[3];
+	      shortcopy[1] = origdata[2];
+	      memcpy(shortcopy+2,origdata+4,shortlen-2);
+	      free(origdata);
+	      pkey->key_data_length[0] = shortlen;
+	      pkey->key_data_contents[0] = shortcopy;
+	    }
+	      
+	    /* Read principal attributes */
+	    if (!error && (fscanf(filep,
+				  "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+				  &tmpint1, &dbent.max_life,
+				  &dbent.max_renewable_life,
+				  &tmpint2, &dbent.expiration,
+				  &dbent.pw_expiration, &last_pwd_change,
+				  &dbent.last_success, &dbent.last_failed,
+				  &tmpint3) != 10)) {
+		try2read = read_pr_data1;
+		error++;
+	    }
+	    pkey->key_data_kvno = tmpint1;
+	    dbent.fail_auth_count = tmpint3;
+	    /* Read modifier name */
+	    if (!error && read_string(filep,
+				      mod_name,
+				      mod_name_len,
+				      linenop)) {
+		try2read = read_mod_name;
+		error++;
+	    }
+	    /* Read second set of attributes */
+	    if (!error && (fscanf(filep, "\t%u\t%u\t%u\t",
+				  &mod_date, &dbent.attributes,
+				  &tmpint1) != 3)) {
+		try2read = read_pr_data2;
+		error++;
+	    }
+	    pkey->key_data_type[1] = tmpint1;
+	    /* Read salt data */
+	    if (!error && read_octet_string(filep,
+					    pkey->key_data_contents[1],
+					    pkey->key_data_length[1])) {
+		try2read = read_salt_data;
+		error++;
+	    }
+	    /* Read alternate key type */
+	    if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) {
+		try2read = read_akey_type;
+		error++;
+	    }
+	    akey->key_data_type[0] = tmpint1;
+	    /* Read alternate key */
+	    if (!error && read_octet_string(filep,
+					    akey->key_data_contents[0],
+					    akey->key_data_length[0])) {
+		try2read = read_akey_data;
+		error++;
+	    }
+
+	    /* convert to a new format key */
+	    /* the encrypted version is stored as the unencrypted key length
+	       (4 bytes, MSB first) followed by the encrypted key. */
+	    if ((akey->key_data_length[0] > 4)
+		&& (akey->key_data_contents[0][0] == 0)
+		&& (akey->key_data_contents[0][1] == 0)) {
+	      /* this really does look like an old key, so drop and swap */
+	      /* the *new* length is 2 bytes, LSB first, sigh. */
+	      size_t shortlen = akey->key_data_length[0]-4+2;
+	      krb5_octet *shortcopy = (krb5_octet *) malloc(shortlen);
+	      krb5_octet *origdata = akey->key_data_contents[0];
+	      shortcopy[0] = origdata[3];
+	      shortcopy[1] = origdata[2];
+	      memcpy(shortcopy+2,origdata+4,shortlen-2);
+	      free(origdata);
+	      akey->key_data_length[0] = shortlen;
+	      akey->key_data_contents[0] = shortcopy;
+	    }
+	      
+	    /* Read alternate salt type */
+	    if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) {
+		try2read = read_asalt_type;
+		error++;
+	    }
+	    akey->key_data_type[1] = tmpint1;
+	    /* Read alternate salt data */
+	    if (!error && read_octet_string(filep,
+					    akey->key_data_contents[1],
+					    akey->key_data_length[1])) {
+		try2read = read_asalt_data;
+		error++;
+	    }
+	    /* Read expansion data - discard it */
+	    if (!error) {
+		for (i=0; i<8; i++) {
+		    if (fscanf(filep, "\t%u", &tmpint1) != 1) {
+			try2read = read_exp_data;
+			error++;
+			break;
+		    }
+		}
+		if (!error)
+		    find_record_end(filep, fname, *linenop);
+	    }
+	
+	    /*
+	     * If no error, then we're done reading.  Now parse the names
+	     * and store the database dbent.
+	     */
+	    if (!error) {
+		if (!(kret = krb5_parse_name(kcontext,
+					     name,
+					     &dbent.princ))) {
+		    if (!(kret = krb5_parse_name(kcontext,
+						 mod_name,
+						 &mod_princ))) {
+			if (!(kret =
+			      krb5_dbe_update_mod_princ_data(kcontext,
+							     &dbent,
+							     mod_date,
+							     mod_princ)) &&
+			    !(kret =
+			      krb5_dbe_update_last_pwd_change(kcontext,
+							      &dbent,
+							      last_pwd_change))) {
+			    int one = 1;
+
+			    dbent.len = KRB5_KDB_V1_BASE_LENGTH;
+			    pkey->key_data_ver = (pkey->key_data_type[1] || pkey->key_data_length[1]) ?
+				2 : 1;
+			    akey->key_data_ver = (akey->key_data_type[1] || akey->key_data_length[1]) ?
+				2 : 1;
+			    if ((pkey->key_data_type[0] ==
+				 akey->key_data_type[0]) &&
+				(pkey->key_data_type[1] ==
+				 akey->key_data_type[1]))
+				dbent.n_key_data--;
+			    else if ((akey->key_data_type[0] == 0)
+				     && (akey->key_data_length[0] == 0)
+				     && (akey->key_data_type[1] == 0)
+				     && (akey->key_data_length[1] == 0))
+			        dbent.n_key_data--;
+
+			    dbent.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
+				KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_KEY_DATA |
+				KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS |
+				KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT;
+
+			    if ((kret = krb5_db_put_principal(kcontext,
+							      &dbent,
+							      &one)) ||
+				(one != 1)) {
+				fprintf(stderr, store_err_fmt,
+					fname, *linenop, name,
+					error_message(kret));
+				error++;
+			    }
+			    else {
+				if (verbose)
+				    fprintf(stderr, add_princ_fmt, name);
+				retval = 0;
+			    }
+			    dbent.n_key_data = 2;
+			}
+			krb5_free_principal(kcontext, mod_princ);
+		    }
+		    else {
+			fprintf(stderr, parse_err_fmt, 
+				fname, *linenop, mod_name, 
+				error_message(kret));
+			error++;
+		    }
+		}
+		else {
+		    fprintf(stderr, parse_err_fmt,
+			    fname, *linenop, name, error_message(kret));
+		    error++;
+		}
+	    }
+	    else {
+		fprintf(stderr, read_err_fmt, fname, *linenop, try2read);
+	    }
+	}
+	else {
+	    fprintf(stderr, no_mem_fmt, fname, *linenop);
+	}
+
+	krb5_db_free_principal(kcontext, &dbent, 1);
+	if (mod_name)
+	    free(mod_name);
+	if (name)
+	    free(name);
+    }
+    else {
+	if (nmatched != EOF)
+	    fprintf(stderr, rhead_err_fmt, fname, *linenop);
+	else
+	    retval = -1;
+    }
+    return(retval);
+}
+
+/*
+ * process_k5beta6_record()	- Handle a dump record in krb5b6 format.
+ *
+ * Returns -1 for end of file, 0 for success and 1 for failure.
+ */
+static int
+process_k5beta6_record(fname, kcontext, filep, verbose, linenop)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			verbose;
+    int			*linenop;
+{
+    int			retval;
+    krb5_db_entry	dbentry;
+    krb5_int32		t1, t2, t3, t4, t5, t6, t7, t8, t9;
+    int			nread;
+    int			error;
+    int			i, j, one;
+    char		*name;
+    krb5_key_data	*kp, *kdatap;
+    krb5_tl_data	**tlp, *tl;
+    krb5_octet 		*op;
+    krb5_error_code	kret;
+    const char		*try2read;
+
+    try2read = (char *) NULL;
+    memset((char *) &dbentry, 0, sizeof(dbentry));
+    (*linenop)++;
+    retval = 1;
+    name = (char *) NULL;
+    kp = (krb5_key_data *) NULL;
+    op = (krb5_octet *) NULL;
+    error = 0;
+    kret = 0;
+    nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t", &t1, &t2, &t3, &t4, &t5);
+    if (nread == 5) {
+	/* Get memory for flattened principal name */
+	if (!(name = (char *) malloc((size_t) t2 + 1)))
+	    error++;
+
+	/* Get memory for and form tagged data linked list */
+	tlp = &dbentry.tl_data;
+	for (i=0; i<t3; i++) {
+	    if ((*tlp = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) {
+		memset(*tlp, 0, sizeof(krb5_tl_data));
+		tlp = &((*tlp)->tl_data_next);
+		dbentry.n_tl_data++;
+	    }
+	    else {
+		error++;
+		break;
+	    }
+	}
+
+	/* Get memory for key list */
+	if (t4 && !(kp = (krb5_key_data *) malloc((size_t)
+						  (t4*sizeof(krb5_key_data)))))
+	    error++;
+
+	/* Get memory for extra data */
+	if (t5 && !(op = (krb5_octet *) malloc((size_t) t5)))
+	    error++;
+
+	if (!error) {
+	    dbentry.len = t1;
+	    dbentry.n_key_data = t4;
+	    dbentry.e_length = t5;
+	    if (kp) {
+		memset(kp, 0, (size_t) (t4*sizeof(krb5_key_data)));
+		dbentry.key_data = kp;
+		kp = (krb5_key_data *) NULL;
+	    }
+	    if (op) {
+		memset(op, 0, (size_t) t5);
+		dbentry.e_data = op;
+		op = (krb5_octet *) NULL;
+	    }
+
+	    /* Read in and parse the principal name */
+	    if (!read_string(filep, name, t2, linenop) &&
+		!(kret = krb5_parse_name(kcontext, name, &dbentry.princ))) {
+
+		/* Get the fixed principal attributes */
+		nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",
+			       &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9);
+		if (nread == 8) {
+		    dbentry.attributes = (krb5_flags) t2;
+		    dbentry.max_life = (krb5_deltat) t3;
+		    dbentry.max_renewable_life = (krb5_deltat) t4;
+		    dbentry.expiration = (krb5_timestamp) t5;
+		    dbentry.pw_expiration = (krb5_timestamp) t6;
+		    dbentry.last_success = (krb5_timestamp) t7;
+		    dbentry.last_failed = (krb5_timestamp) t8;
+		    dbentry.fail_auth_count = (krb5_kvno) t9;
+		    dbentry.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
+			KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
+			KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS |
+			KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT;
+		} else {
+		    try2read = read_nint_data;
+		    error++;
+		}
+
+		/*
+		 * Get the tagged data.
+		 *
+		 * Really, this code ought to discard tl data types
+		 * that it knows are special to the current version
+		 * and were not supported in the previous version.
+		 * But it's a pain to implement that here, and doing
+		 * it at dump time has almost as good an effect, so
+		 * that's what I did.  [krb5-admin/89]
+		 */
+		if (!error && dbentry.n_tl_data) {
+		    for (tl = dbentry.tl_data; tl; tl = tl->tl_data_next) {
+			nread = fscanf(filep, "%d\t%d\t", &t1, &t2);
+			if (nread == 2) {
+			    tl->tl_data_type = (krb5_int16) t1;
+			    tl->tl_data_length = (krb5_int16) t2;
+			    if (tl->tl_data_length) {
+				if (!(tl->tl_data_contents =
+				      (krb5_octet *) malloc((size_t) t2+1)) ||
+				    read_octet_string(filep,
+						      tl->tl_data_contents,
+						      t2)) {
+				    try2read = read_tcontents;
+				    error++;
+				    break;
+				}
+				/* test to set mask fields */
+				if (t1 == KRB5_TL_KADM_DATA) {
+				    XDR xdrs;
+				    osa_princ_ent_rec osa_princ_ent;
+
+				    /* 
+				     * Assuming aux_attributes will always be
+				     * there
+				     */
+				    dbentry.mask |= KADM5_AUX_ATTRIBUTES;
+
+				    /* test for an actual policy reference */
+				    memset(&osa_princ_ent, 0, sizeof(osa_princ_ent));
+				    xdrmem_create(&xdrs, (char *)tl->tl_data_contents,
+					    tl->tl_data_length, XDR_DECODE);
+				    if (xdr_osa_princ_ent_rec(&xdrs, &osa_princ_ent) &&
+					    (osa_princ_ent.aux_attributes & KADM5_POLICY) &&
+					    osa_princ_ent.policy != NULL) {
+
+					dbentry.mask |= KADM5_POLICY;
+					kdb_free_entry(NULL, NULL, &osa_princ_ent);
+				    }
+				    xdr_destroy(&xdrs);
+				}
+			    }
+			    else {
+				/* Should be a null field */
+				nread = fscanf(filep, "%d", &t9);
+				if ((nread != 1) || (t9 != -1)) {
+				    error++;
+				    try2read = read_tcontents;
+				    break;
+				}
+			    }
+			}
+			else {
+			    try2read = read_ttypelen;
+			    error++;
+			    break;
+			}
+		    }
+		    if (!error)
+			dbentry.mask |= KADM5_TL_DATA;
+		}
+
+		/* Get the key data */
+		if (!error && dbentry.n_key_data) {
+		    for (i=0; !error && (i<dbentry.n_key_data); i++) {
+			kdatap = &dbentry.key_data[i];
+			nread = fscanf(filep, "%d\t%d\t", &t1, &t2);
+			if (nread == 2) {
+			    kdatap->key_data_ver = (krb5_int16) t1;
+			    kdatap->key_data_kvno = (krb5_int16) t2;
+
+			    for (j=0; j<t1; j++) {
+				nread = fscanf(filep, "%d\t%d\t", &t3, &t4);
+				if (nread == 2) {
+				    kdatap->key_data_type[j] = t3;
+				    kdatap->key_data_length[j] = t4;
+				    if (t4) {
+					if (!(kdatap->key_data_contents[j] =
+					      (krb5_octet *)
+					      malloc((size_t) t4+1)) ||
+					    read_octet_string(filep,
+							      kdatap->key_data_contents[j],
+							      t4)) {
+					    try2read = read_kcontents;
+					    error++;
+					    break;
+					}
+				    }
+				    else {
+					/* Should be a null field */
+					nread = fscanf(filep, "%d", &t9);
+					if ((nread != 1) || (t9 != -1)) {
+					    error++;
+					    try2read = read_kcontents;
+					    break;
+					}
+				    }
+				}
+				else {
+				    try2read = read_ktypelen;
+				    error++;
+				    break;
+				}
+			    }
+			}
+		    }
+		    if (!error)
+			dbentry.mask |= KADM5_KEY_DATA;
+		}
+
+		/* Get the extra data */
+		if (!error && dbentry.e_length) {
+		    if (read_octet_string(filep,
+					  dbentry.e_data,
+					  (int) dbentry.e_length)) {
+			try2read = read_econtents;
+			error++;
+		    }
+		}
+		else {
+		    nread = fscanf(filep, "%d", &t9);
+		    if ((nread != 1) || (t9 != -1)) {
+			error++;
+			try2read = read_econtents;
+		    }
+		}
+
+		/* Finally, find the end of the record. */
+		if (!error)
+		    find_record_end(filep, fname, *linenop);
+
+		/*
+		 * We have either read in all the data or choked.
+		 */
+		if (!error) {
+		    one = 1;
+		    if ((kret = krb5_db_put_principal(kcontext,
+						      &dbentry,
+						      &one))) {
+			fprintf(stderr, store_err_fmt,
+				fname, *linenop,
+				name, error_message(kret));
+		    }
+		    else {
+			if (verbose)
+			    fprintf(stderr, add_princ_fmt, name);
+			retval = 0;
+		    }
+		}
+		else {
+		    fprintf(stderr, read_err_fmt, fname, *linenop, try2read);
+		}
+	    }
+	    else {
+		if (kret)
+		    fprintf(stderr, parse_err_fmt,
+			    fname, *linenop, name, error_message(kret));
+		else
+		    fprintf(stderr, no_mem_fmt, fname, *linenop);
+	    }
+	}
+	else {
+	    fprintf(stderr, rhead_err_fmt, fname, *linenop);
+	}
+
+	if (op)
+	    free(op);
+	if (kp)
+	    free(kp);
+	if (name)
+	    free(name);
+	krb5_db_free_principal(kcontext, &dbentry, 1);
+    }
+    else {
+	if (nread == EOF)
+	    retval = -1;
+    }
+    return(retval);
+}
+
+static int 
+process_k5beta7_policy(fname, kcontext, filep, verbose, linenop, pol_db)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			verbose;
+    int			*linenop;
+    void *pol_db;
+{
+    osa_policy_ent_rec rec;
+    char namebuf[1024];
+    int nread, ret;
+
+    (*linenop)++;
+    rec.name = namebuf;
+
+    nread = fscanf(filep, "%1024s\t%d\t%d\t%d\t%d\t%d\t%d", rec.name,
+		   &rec.pw_min_life, &rec.pw_max_life,
+		   &rec.pw_min_length, &rec.pw_min_classes,
+		   &rec.pw_history_num, &rec.policy_refcnt);
+    if (nread == EOF)
+	 return -1;
+    else if (nread != 7) {
+	 fprintf(stderr, "cannot parse policy on line %d (%d read)\n",
+		 *linenop, nread);
+	 return 1;
+    }
+
+    if ((ret = krb5_db_create_policy(kcontext, &rec))) {
+	 if (ret &&
+	     ((ret = krb5_db_put_policy(kcontext, &rec)))) {
+	      fprintf(stderr, "cannot create policy on line %d: %s\n",
+		      *linenop, error_message(ret));
+	      return 1;
+	 }
+    }
+    if (verbose)
+	 fprintf(stderr, "created policy %s\n", rec.name);
+    
+    return 0;
+}
+
+/*
+ * process_k5beta7_record()	- Handle a dump record in krb5b7 format.
+ *
+ * Returns -1 for end of file, 0 for success and 1 for failure.
+ */
+static int
+process_k5beta7_record(fname, kcontext, filep, verbose, linenop)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			verbose;
+    int			*linenop;
+{
+     int nread;
+     char rectype[100];
+
+     nread = fscanf(filep, "%100s\t", rectype);
+     if (nread == EOF)
+	  return -1;
+     else if (nread != 1)
+	  return 1;
+     if (strcmp(rectype, "princ") == 0)
+	  process_k5beta6_record(fname, kcontext, filep, verbose,
+				 linenop);
+     else if (strcmp(rectype, "policy") == 0)
+	  process_k5beta7_policy(fname, kcontext, filep, verbose,
+				 linenop);
+     else {
+	  fprintf(stderr, "unknown record type \"%s\" on line %d\n",
+		  rectype, *linenop);
+	  return 1;
+     }
+
+     return 0;
+}
+
+/*
+ * process_ov_record()	- Handle a dump record in OpenV*Secure 1.0 format.
+ *
+ * Returns -1 for end of file, 0 for success and 1 for failure.
+ */
+static int
+process_ov_record(fname, kcontext, filep, verbose, linenop)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			verbose;
+    int			*linenop;
+{
+     int nread;
+     char rectype[100];
+
+     nread = fscanf(filep, "%100s\t", rectype);
+     if (nread == EOF)
+	  return -1;
+     else if (nread != 1)
+	  return 1;
+     if (strcmp(rectype, "princ") == 0)
+	  process_ov_principal(fname, kcontext, filep, verbose,
+			       linenop);
+     else if (strcmp(rectype, "policy") == 0)
+	  process_k5beta7_policy(fname, kcontext, filep, verbose,
+				 linenop);
+     else if (strcmp(rectype, "End") == 0)
+	  return -1;
+     else {
+	  fprintf(stderr, "unknown record type \"%s\" on line %d\n",
+		  rectype, *linenop);
+	  return 1;
+     }
+
+     return 0;
+}
+
+/*
+ * restore_dump()	- Restore the database from any version dump file.
+ */
+static int
+restore_dump(programname, kcontext, dumpfile, f, verbose, dump)
+    char		*programname;
+    krb5_context	kcontext;
+    char		*dumpfile;
+    FILE		*f;
+    int			verbose;
+    dump_version	*dump;
+{
+    int		error;	
+    int		lineno;
+
+    error = 0;
+    lineno = 1;
+
+    /*
+     * Process the records.
+     */
+    while (!(error = (*dump->load_record)(dumpfile,
+					  kcontext, 
+					  f,
+					  verbose,
+					  &lineno)))
+	 ;
+    if (error != -1)
+	 fprintf(stderr, err_line_fmt, programname, lineno, dumpfile);
+    else
+	 error = 0;
+
+    return(error);
+}
+
+/*
+ * Usage: load_db [-old] [-ov] [-b6] [-b7] [-verbose] [-update] [-hash]
+ *		filename
+ */
+void
+load_db(argc, argv)
+    int		argc;
+    char	**argv;
+{
+    kadm5_config_params newparams;
+    krb5_error_code	kret;
+    krb5_context	kcontext;
+    FILE		*f;
+    extern char		*optarg;
+    extern int		optind;
+    char		*programname;
+    char		*dumpfile;
+    char		*dbname;
+    char		*dbname_tmp;
+    char		buf[BUFSIZ];
+    dump_version	*load;
+    int			update, verbose;
+    krb5_int32		crflags;
+    int			aindex;
+    int			db_locked = 0;
+
+    /*
+     * Parse the arguments.
+     */
+    programname = argv[0];
+    if (strrchr(programname, (int) '/'))
+	programname = strrchr(argv[0], (int) '/') + 1;
+    dumpfile = (char *) NULL;
+    dbname = global_params.dbname;
+    load = NULL;
+    update = 0;
+    verbose = 0;
+    crflags = KRB5_KDB_CREATE_BTREE;
+    exit_status = 0;
+    dbname_tmp = (char *) NULL;
+    for (aindex = 1; aindex < argc; aindex++) {
+	if (!strcmp(argv[aindex], oldoption))
+	     load = &old_version;
+	else if (!strcmp(argv[aindex], b6option))
+	     load = &beta6_version;
+	else if (!strcmp(argv[aindex], b7option))
+	     load = &beta7_version;
+	else if (!strcmp(argv[aindex], ovoption))
+	     load = &ov_version;
+	else if (!strcmp(argv[aindex], verboseoption))
+	    verbose = 1;
+	else if (!strcmp(argv[aindex], updateoption))
+	    update = 1;
+	else if (!strcmp(argv[aindex], hashoption)) {
+	    if (!add_db_arg("hash=true")) {
+		com_err(progname, ENOMEM, "while parsing command arguments\n");
+		exit(1);
+	    }
+	} else
+	    break;
+    }
+    if ((argc - aindex) != 1) {
+	usage();
+	return;
+    }
+    dumpfile = argv[aindex];
+
+    if (!(dbname_tmp = (char *) malloc(strlen(dbname)+
+				       strlen(dump_tmptrail)+1))) {
+	fprintf(stderr, no_name_mem_fmt, argv[0]);
+	exit_status++;
+	return;
+    }
+    strcpy(dbname_tmp, dbname);
+    strcat(dbname_tmp, dump_tmptrail);
+
+    /*
+     * Initialize the Kerberos context and error tables.
+     */
+    if ((kret = kadm5_init_krb5_context(&kcontext))) {
+	fprintf(stderr, ctx_err_fmt, programname);
+	free(dbname_tmp);
+	exit_status++;
+	return;
+    }
+
+    if( (kret = krb5_set_default_realm(kcontext, util_context->default_realm)) )
+    {
+	fprintf(stderr, "%s: Unable to set the default realm\n", programname);
+	free(dbname_tmp);
+	exit_status++;
+	return;
+    }
+
+    /*
+     * Open the dumpfile
+     */
+    if (dumpfile) {
+	if ((f = fopen(dumpfile, "r")) == NULL) {
+	     fprintf(stderr, dfile_err_fmt, programname, dumpfile,
+		     error_message(errno)); 
+	     exit_status++;
+	     return;
+	}
+	if ((kret = krb5_lock_file(kcontext, fileno(f),
+				   KRB5_LOCKMODE_SHARED))) {
+	     fprintf(stderr, "%s: Cannot lock %s: %s\n", programname,
+		     dumpfile, error_message(errno));
+	     exit_status++;
+	     return;
+	}
+    } else
+	f = stdin;
+
+    /*
+     * Auto-detect dump version if we weren't told, verify if we
+     * were told.
+     */
+    fgets(buf, sizeof(buf), f);
+    if (load) {
+	 /* only check what we know; some headers only contain a prefix */
+	 if (strncmp(buf, load->header, strlen(load->header)) != 0) {
+	      fprintf(stderr, head_bad_fmt, programname, dumpfile);
+	      exit_status++;
+	      if (dumpfile) fclose(f);
+	      return;
+	 }
+    } else {
+	 /* perhaps this should be in an array, but so what? */
+	 if (strcmp(buf, old_version.header) == 0)
+	      load = &old_version;
+	 else if (strcmp(buf, beta6_version.header) == 0)
+	      load = &beta6_version;
+	 else if (strcmp(buf, beta7_version.header) == 0)
+	      load = &beta7_version;
+	 else if (strcmp(buf, r1_3_version.header) == 0)
+	      load = &r1_3_version;
+	 else if (strncmp(buf, ov_version.header,
+			  strlen(ov_version.header)) == 0)
+	      load = &ov_version;
+	 else {
+	      fprintf(stderr, head_bad_fmt, programname, dumpfile);
+	      exit_status++;
+	      if (dumpfile) fclose(f);
+	      return;
+	 }
+    }
+    if (load->updateonly && !update) {
+	 fprintf(stderr, "%s: dump version %s can only be loaded with the "
+		 "-update flag\n", programname, load->name);
+	 exit_status++;
+	 return;
+    }
+
+    /*
+     * Cons up params for the new databases.  If we are not in update
+     * mode, we create an alternate database and then promote it to
+     * be the live db.
+     */
+    newparams = global_params;
+    if (! update) {
+	 newparams.mask |= KADM5_CONFIG_DBNAME;
+	 newparams.dbname = dbname_tmp;
+
+	 if ((kret = kadm5_get_config_params(kcontext, 1,
+					     &newparams, &newparams))) {
+	      com_err(argv[0], kret,
+		      "while retreiving new configuration parameters");
+	      exit_status++;
+	      return;
+	 }
+
+	 if (!add_db_arg("temporary")) {
+	     com_err(progname, ENOMEM, "computing parameters for database");
+	     exit(1);
+	 }
+    }
+    
+    /*
+     * If not an update restoration, create the database. otherwise open
+     */
+    if (!update) {
+	if((kret = krb5_db_create(kcontext, db5util_db_args))) {
+	    const char *emsg = krb5_get_error_message(kcontext, kret);
+	    /* 
+	     * See if something (like DAL KDB plugin) has set a specific error
+	     * message and use that otherwise use default.
+	     */
+
+	    if (emsg != NULL) {
+		fprintf(stderr, "%s: %s\n", programname, emsg);
+		krb5_free_error_message (kcontext, emsg);
+	    } else {
+		fprintf(stderr, dbcreaterr_fmt,
+			programname, dbname, error_message(kret));
+	    }
+	    exit_status++;
+	    kadm5_free_config_params(kcontext, &newparams);
+	    if (dumpfile) fclose(f);
+	    return;
+	}
+    }
+    else {
+	    /*
+	     * Initialize the database.
+	     */
+	    if ((kret = krb5_db_open(kcontext, db5util_db_args, 
+				     KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) {
+		const char *emsg = krb5_get_error_message(kcontext, kret);
+		/* 
+		 * See if something (like DAL KDB plugin) has set a specific
+		 * error message and use that otherwise use default.
+		 */
+
+		if (emsg != NULL) {
+		    fprintf(stderr, "%s: %s\n", programname, emsg);
+		    krb5_free_error_message (kcontext, emsg);
+		} else {
+		    fprintf(stderr, dbinit_err_fmt,
+			    programname, error_message(kret));
+		}
+		exit_status++;
+		goto error;
+	    }
+    }
+
+
+    /*
+     * If an update restoration, make sure the db is left unusable if
+     * the update fails.
+     */
+    if ((kret = krb5_db_lock(kcontext, update?KRB5_DB_LOCKMODE_PERMANENT: KRB5_DB_LOCKMODE_EXCLUSIVE))) {
+	/* 
+	 * Ignore a not supported error since there is nothing to do about it
+	 * anyway.
+	 */
+	if (kret != KRB5_PLUGIN_OP_NOTSUPP) {
+	    fprintf(stderr, "%s: %s while permanently locking database\n",
+		    programname, error_message(kret));
+	    exit_status++;
+	    goto error;
+	}
+    }
+    else
+	db_locked = 1;
+    
+    if (restore_dump(programname, kcontext, (dumpfile) ? dumpfile : stdin_name,
+		     f, verbose, load)) {
+	 fprintf(stderr, restfail_fmt,
+		 programname, load->name);
+	 exit_status++;
+    }
+
+    if (!update && load->create_kadm5 &&
+	((kret = kadm5_create_magic_princs(&newparams, kcontext)))) {
+	 /* error message printed by create_magic_princs */
+	 exit_status++;
+    }
+    
+    if (db_locked && (kret = krb5_db_unlock(kcontext))) {
+	 /* change this error? */
+	 fprintf(stderr, dbunlockerr_fmt,
+		 programname, dbname, error_message(kret));
+	 exit_status++;
+    }
+
+#if 0
+    if ((kret = krb5_db_fini(kcontext))) {
+	 fprintf(stderr, close_err_fmt,
+		 programname, error_message(kret));
+	 exit_status++;
+    }
+#endif
+
+    /* close policy db below */
+
+    if (exit_status == 0 && !update) {
+	kret = krb5_db_promote(kcontext, db5util_db_args);
+	/* 
+	 * Ignore a not supported error since there is nothing to do about it
+	 * anyway.
+	 */
+	if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) {
+	    fprintf(stderr, "%s: cannot make newly loaded database live (%s)\n",
+		    programname, error_message(kret));
+	    exit_status++;
+	}
+    }
+
+error:
+    /*
+     * If not an update: if there was an error, destroy the temp database,
+     * otherwise rename it into place.
+     *
+     * If an update: if there was no error, unlock the database.
+     */
+    if (!update) {
+	 if (exit_status) {
+	      kret = krb5_db_destroy(kcontext, db5util_db_args);
+	      /* 
+	       * Ignore a not supported error since there is nothing to do about
+	       * it anyway.
+	       */
+	      if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) {
+		   fprintf(stderr, dbdelerr_fmt,
+			   programname, dbname, error_message(kret));
+		   exit_status++;
+	      }
+	 }
+    }
+
+    if (dumpfile) {
+	 (void) krb5_lock_file(kcontext, fileno(f), KRB5_LOCKMODE_UNLOCK);
+	 fclose(f);
+    }
+
+    if (dbname_tmp)
+	 free(dbname_tmp);
+    krb5_free_context(kcontext);
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/dumpv4.c b/krb5-1-6/src/kadmin/dbutil/dumpv4.c
new file mode 100644
index 000000000..e6bd1f407
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/dumpv4.c
@@ -0,0 +1,462 @@
+/*
+ * admin/edit/dumpv4.c
+ *
+ * Copyright 1990,1991, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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"
+#include "com_err.h"
+
+#include <des.h>
+#include <krb.h>
+#ifdef HAVE_KRB_DB_H
+#include <krb_db.h>
+#endif /*HAVE_KRB_DB_H*/
+#ifdef HAVE_KDC_H
+;/* MKEYFILE is now defined in kdc.h */
+#include <kdc.h>
+#endif /*HAVE_KDC_H*/
+#include <stdio.h>
+#include <kadm5/admin.h>
+#include "kdb5_util.h"
+
+struct dump_record {
+	char	*comerr_name;
+	FILE	*f;
+	krb5_keyblock *v5mkey;
+	C_Block		v4_master_key;
+	Key_schedule	v4_master_key_schedule;
+	long	master_key_version;
+	char	*realm;
+};
+
+
+void update_ok_file();
+
+#define ANAME_SZ 40
+#define INST_SZ 40
+
+static char *v4_mkeyfile = "/.k";
+static int shortlife;
+static krb5_error_code handle_one_key(struct dump_record *arg, 
+				      krb5_keyblock *v5mkey, 
+				      krb5_key_data *v5key, 
+				      des_cblock v4key);
+static int handle_keys(struct dump_record *arg);
+
+static int
+v4init(arg, manual)
+    struct dump_record *arg;
+    int manual;
+{
+    int fd;
+    int ok = 0;
+
+    if (!manual) {
+	fd = open(v4_mkeyfile, O_RDONLY, 0600);
+	if (fd >= 0) {
+	    if (read(fd,arg->v4_master_key,sizeof(C_Block)) == sizeof(C_Block))
+		ok = 1;
+	    close(fd);
+	}
+    }
+    if (!ok) {
+	des_read_password(&arg->v4_master_key, "V4 Kerberos master key", 1);
+	printf("\n");
+    }
+    arg->master_key_version = 1;
+    key_sched(arg->v4_master_key, arg->v4_master_key_schedule);
+
+    return 0;
+}
+
+static void
+v4_print_time(file, timeval)
+    FILE   *file;
+    unsigned long timeval;
+{
+    struct tm *tm;
+    struct tm *gmtime();
+    tm = gmtime((time_t *)&timeval);
+    fprintf(file, " %04d%02d%02d%02d%02d",
+            tm->tm_year < 1900 ? tm->tm_year + 1900: tm->tm_year,
+            tm->tm_mon + 1,
+            tm->tm_mday,
+            tm->tm_hour,
+            tm->tm_min);
+}
+
+
+
+static krb5_error_code
+dump_v4_iterator(ptr, entry)
+    krb5_pointer ptr;
+    krb5_db_entry *entry;
+{
+    struct dump_record *arg = (struct dump_record *) ptr;
+    krb5_principal mod_princ;
+    krb5_timestamp mod_time;
+    krb5_error_code retval;
+    int	i, max_kvno, ok_key;
+
+    struct v4princ {
+	char name[ANAME_SZ+1];
+	char instance[INST_SZ+1];
+	char realm[REALM_SZ+1];
+	int max_life;
+	int kdc_key_ver, key_version, attributes;
+	char mod_name[ANAME_SZ+1];
+	char mod_instance[INST_SZ+1];
+	char mod_realm[REALM_SZ+1];
+    } v4princ, *principal;
+    des_cblock v4key;
+    
+    principal = &v4princ;
+
+    if (strcmp(krb5_princ_realm(util_context, entry->princ)->data, arg->realm))
+	/* skip this because it's a key for a different realm, probably
+	 * a paired krbtgt key */
+	return 0;
+
+    retval = krb5_524_conv_principal(util_context, entry->princ,
+				     principal->name, principal->instance,
+				     principal->realm);
+    if (retval)
+	/* Skip invalid V4 principals */
+	return 0;
+
+    if (!strcmp(principal->name, "K") && !strcmp(principal->instance, "M"))
+	/* The V4 master key is handled specially */
+	return 0;
+
+    if (! principal->name[0])
+	return 0;
+    if (! principal->instance[0])
+	strcpy(principal->instance, "*");
+
+    /* Now move to mod princ */
+    if ((retval = krb5_dbe_lookup_mod_princ_data(util_context,entry,
+						 &mod_time, &mod_princ))){
+	com_err(arg->comerr_name, retval, "while unparsing db entry");
+	exit_status++;
+	return retval;
+    }
+    retval = krb5_524_conv_principal(util_context, mod_princ,
+				     principal->mod_name, principal->mod_instance,
+				     principal->mod_realm);
+    if (retval) {
+	/* Invalid V4 mod principal */
+	principal->mod_name[0] = '\0';
+	principal->mod_instance[0] = '\0';
+    }
+
+    if (! principal->mod_name[0])
+	strcpy(principal->mod_name, "*");
+    if (! principal->mod_instance[0])
+	strcpy(principal->mod_instance, "*");
+    
+    /* OK deal with the key now. */
+    for (max_kvno = i = 0; i < entry->n_key_data; i++) {
+	if (max_kvno < entry->key_data[i].key_data_kvno) {
+	     max_kvno = entry->key_data[i].key_data_kvno;
+	     ok_key = i;
+	}
+    }
+
+    i = ok_key;
+    while (ok_key < entry->n_key_data) {
+	if (max_kvno == entry->key_data[ok_key].key_data_kvno) {
+	    if (entry->key_data[ok_key].key_data_type[1]
+		== KRB5_KDB_SALTTYPE_V4) {
+		goto found_one;
+	    }
+	}
+	ok_key++;
+    }
+
+    /* See if there are any DES keys that may be suitable */
+    ok_key = i;
+    while (ok_key < entry->n_key_data) {
+	if (max_kvno == entry->key_data[ok_key].key_data_kvno) {
+	    krb5_enctype enctype = entry->key_data[ok_key].key_data_type[0];
+	    if ((enctype == ENCTYPE_DES_CBC_CRC) ||
+		(enctype == ENCTYPE_DES_CBC_MD5) ||
+		(enctype == ENCTYPE_DES_CBC_RAW))
+		goto found_one;
+	}
+	ok_key++;
+    }
+    /* skip this because it's a new style key and we can't help it */
+    return 0;
+
+found_one:;
+    principal->key_version = max_kvno;
+    if (!shortlife)
+	principal->max_life = krb_time_to_life(0, entry->max_life);
+    else {
+	principal->max_life = entry->max_life / (60 * 5);
+	if (principal->max_life > 255)
+	    principal->max_life = 255;
+    }
+
+    principal->kdc_key_ver = arg->master_key_version;
+    principal->attributes = 0;	/* ??? not preserved either */
+
+    fprintf(arg->f, "%s %s %d %d %d %d ",
+	    principal->name,
+	    principal->instance,
+	    principal->max_life,
+	    principal->kdc_key_ver,
+	    principal->key_version,
+	    principal->attributes);
+
+    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]);
+	if (i == 3) fputc(' ', arg->f);
+    }
+
+    if (entry->expiration == 0) {
+        /* 0 means "never" expire. V4 didn't support that, so rather than
+	   having everything appear to have expired in 1970, we nail in the
+	   Cygnus 96q1 default value.  The value quoted here is directly 
+	   from src/admin/kdb_init.c in Cygnus CNS V4 96q1, and is
+	   roughly 12/31/2009. */
+        v4_print_time(arg->f, 946702799+((365*10+3)*24*60*60));
+    } else {
+    v4_print_time(arg->f, entry->expiration);
+    }
+    v4_print_time(arg->f, mod_time);
+
+    fprintf(arg->f, " %s %s\n", principal->mod_name, principal->mod_instance);
+    return 0;
+}
+
+/*ARGSUSED*/
+void dump_v4db(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	int	i;
+	char	*outname = NULL;
+	FILE	*f;
+	struct dump_record	arg;
+
+	for (i = 1; i < argc; i++) {
+		if (!strcmp(argv[i], "-S")) {
+			shortlife++;
+			continue;
+		}
+		break;
+	}
+	if (argc - i > 1) {
+		com_err(argv[0], 0, "Usage: %s [-S] filename", argv[0]);
+		exit_status++;
+		return;
+	}
+	if (!dbactive) {
+		com_err(argv[0], 0, Err_no_database);
+		exit_status++;
+		return;
+	}
+	if (argc - i == 1) {
+		outname = argv[i];
+		/*
+		 * Make sure that we don't open and truncate on the fopen,
+		 * since that may hose an on-going kprop process.
+		 * 
+		 * We could also control this by opening for read and
+		 * write, doing an flock with LOCK_EX, and then
+		 * truncating the file once we have gotten the lock,
+		 * but that would involve more OS dependancies than I
+		 * want to get into.
+		 */
+		unlink(outname);
+		if (!(f = fopen(outname, "w"))) {
+			com_err(argv[0], errno,
+				"While opening file %s for writing", outname);
+			exit_status++;
+			return;
+		}
+	} else {
+		f = stdout;
+	}
+
+	arg.comerr_name = argv[0];
+	arg.f = f;
+	v4init(&arg, 0);
+	handle_keys(&arg);
+
+	/* special handling for K.M since it isn't preserved */
+	{
+	  des_cblock v4key;
+	  int i2;
+
+	  /* assume:
+	     max lifetime (255)
+	     key version == 1 (actually, should be whatever the v5 one is)
+	     master key version == key version
+	     args == 0 (none are preserved)
+	     expiration date is the default 2000
+	     last mod time is near zero (arbitrarily.)
+	     creator is db_creation *
+	     */
+
+	  fprintf(f,"K M 255 1 1 0 ");
+	  
+#ifndef	KDB4_DISABLE
+	  kdb_encrypt_key (arg.v4_master_key, v4key, 
+			   arg.v4_master_key, arg.v4_master_key_schedule, 
+			   ENCRYPT);
+#else	/* KDB4_DISABLE */
+	  pcbc_encrypt((C_Block *) arg.v4_master_key,
+		       (C_Block *) v4key,
+		       (long) sizeof(C_Block),
+		       arg.v4_master_key_schedule,
+		       (C_Block *) arg.v4_master_key,
+		       ENCRYPT);
+#endif	/* KDB4_DISABLE */
+
+	  for (i2=0; i2<8; i2++) {
+	    fprintf(f, "%02x", ((unsigned char*)v4key)[i2]);
+	    if (i2 == 3) fputc(' ', f);
+	  }
+	  fprintf(f," 200001010459 197001020000 db_creation *\n");
+	}
+
+	(void) krb5_db_iterate(util_context, dump_v4_iterator, 
+			       (krb5_pointer) &arg);
+	if (argc == 2)
+		fclose(f);
+	if (outname)
+		update_ok_file(outname);
+}
+
+static int handle_keys(arg)
+    struct dump_record *arg;
+{
+    krb5_error_code retval;
+    char *defrealm;
+    char *mkey_name = 0;
+    char *mkey_fullname;
+    krb5_principal l_master_princ;
+
+    if ((retval = krb5_get_default_realm(util_context, &defrealm))) {
+      com_err(arg->comerr_name, retval, 
+	      "while retrieving default realm name");
+      exit(1);
+    }	    
+    arg->realm = defrealm;
+
+    /* assemble & parse the master key name */
+
+    if ((retval = krb5_db_setup_mkey_name(util_context, mkey_name, arg->realm, 
+					  &mkey_fullname, &l_master_princ))) {
+	com_err(arg->comerr_name, retval, "while setting up master key name");
+	exit(1);
+    }
+
+    if ((retval = krb5_db_fetch_mkey(util_context, l_master_princ, 
+				     master_keyblock.enctype, 0,
+				     0, global_params.stash_file, 0,
+				     &master_keyblock))) { 
+	com_err(arg->comerr_name, retval, "while reading master key");
+	exit(1);
+    }
+    arg->v5mkey = &master_keyblock;
+    return(0);
+}
+
+static krb5_error_code
+handle_one_key(arg, v5mkey, v5key, v4key)
+    struct dump_record *arg;
+    krb5_keyblock *v5mkey;
+    krb5_key_data *v5key;
+    des_cblock v4key;
+{
+    krb5_error_code retval;
+
+    krb5_keyblock v5plainkey;
+    /* v4key is the actual v4 key from the file. */
+
+    retval = krb5_dbekd_decrypt_key_data(util_context, v5mkey, v5key, 
+					 &v5plainkey, NULL);
+    if (retval) 
+	return retval;
+
+    memcpy(v4key, v5plainkey.contents, sizeof(des_cblock));
+#ifndef	KDB4_DISABLE
+    kdb_encrypt_key (v4key, v4key, 
+		     arg->v4_master_key, arg->v4_master_key_schedule, 
+		     ENCRYPT);
+#else	/* KDB4_DISABLE */
+    pcbc_encrypt((C_Block *) v4key,
+		 (C_Block *) v4key,
+		 (long) sizeof(C_Block),
+		 arg->v4_master_key_schedule,
+		 (C_Block *) arg->v4_master_key,
+		 ENCRYPT);
+#endif	/* KDB4_DISABLE */
+    return 0;
+}
+
+#else /* KRB5_KRB4_COMPAT */
+void dump_v4db(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	printf("This version of krb5_edit does not support the V4 dump command.\n");
+}
+#endif /* KRB5_KRB4_COMPAT */
diff --git a/krb5-1-6/src/kadmin/dbutil/import_err.et b/krb5-1-6/src/kadmin/dbutil/import_err.et
new file mode 100644
index 000000000..e091fe33c
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/import_err.et
@@ -0,0 +1,26 @@
+error_table imp
+error_code IMPORT_NO_ERR,	    "Successfully imported %d record%s.\n"
+error_code IMPORT_BAD_FILE,	    "Input not recognized as database dump"
+error_code IMPORT_BAD_TOKEN,	    "Bad token in dump file."
+error_code IMPORT_BAD_VERSION,	    "Bad version in dump file"
+error_code IMPORT_BAD_RECORD,	    "Defective record encountered: "
+error_code IMPORT_BAD_FOOTER,	    "Truncated input file detected."
+error_code IMPORT_FAILED,	    "Import of dump failed"
+error_code IMPORT_COUNT_MESSAGE,    "Mismatched record count: %d record%s indicated, %d record%s scanned.\n"
+error_code IMPORT_MISMATCH_COUNT,   "Number of records imported does not match count"
+error_code IMPORT_UNK_OPTION,	    "Unknown command line option.\nUsage: ovsec_adm_import [filename]"
+error_code IMPORT_WARN_DB,	    "Warning -- continuing to import will overwrite existing databases!"
+error_code IMPORT_RENAME_FAILED,    "Database rename Failed!!"
+error_code IMPORT_EXTRA_DATA,	    "Extra data after footer is ignored."
+error_code IMPORT_CONFIRM,	    "Proceed <y|n>?"
+error_code IMPORT_OPEN_DUMP,	    "while opening input file"
+error_code IMPORT_IMPORT,	    "while importing databases"
+error_code IMPORT_TTY,		    "cannot open /dev/tty!!"
+error_code IMPORT_RENAME_OPEN,	    "while opening databases"
+error_code IMPORT_RENAME_LOCK,	    "while acquiring permanent lock"
+error_code IMPORT_RENAME_UNLOCK,    "while releasing permanent lock"
+error_code IMPORT_RENAME_CLOSE,	    "while closing databases"
+error_code IMPORT_SINGLE_RECORD,    ""
+error_code IMPORT_PLURAL_RECORDS,   "s"
+error_code IMPORT_GET_PARAMS,	    "while retrieving configuration parameters"
+end
diff --git a/krb5-1-6/src/kadmin/dbutil/kadm5_create.c b/krb5-1-6/src/kadmin/dbutil/kadm5_create.c
new file mode 100644
index 000000000..ff0d294c5
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kadm5_create.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $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.
+ */
+
+#include "string_table.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <k5-int.h>
+#include <kdb.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+
+#include "fake-addrinfo.h"
+
+
+#include <krb5.h>
+#include <kdb.h>
+#include "kdb5_util.h"
+
+static int add_admin_princ(void *handle, krb5_context context,
+		    char *name, char *realm, int attrs, int lifetime);
+static int add_admin_princs(void *handle, krb5_context context, char *realm);
+
+#define ERR 1
+#define OK 0
+
+#define ADMIN_LIFETIME 60*60*3 /* 3 hours */
+#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
+
+/*
+ * Function: kadm5_create
+ *
+ * Purpose: create admin principals in KDC database
+ *
+ * Arguments:	params	(r) configuration parameters to use
+ *      
+ * Effects:  Creates KADM5_ADMIN_SERVICE and KADM5_CHANGEPW_SERVICE
+ * principals in the KDC database and sets their attributes
+ * appropriately.
+ */
+int kadm5_create(kadm5_config_params *params)
+{
+     int retval;
+     krb5_context context;
+
+     kadm5_config_params lparams;
+
+     if ((retval = kadm5_init_krb5_context(&context)))
+	  exit(ERR);
+
+     /*
+      * The lock file has to exist before calling kadm5_init, but
+      * params->admin_lockfile may not be set yet...
+      */
+     if ((retval = kadm5_get_config_params(context, 1,
+					   params, &lparams))) {
+	  com_err(progname, retval, "while looking up the Kerberos configuration");
+	  return 1;
+     }
+
+     retval = kadm5_create_magic_princs(&lparams, context);
+
+     kadm5_free_config_params(context, &lparams);
+     krb5_free_context(context);
+
+     return retval;
+}
+
+int kadm5_create_magic_princs(kadm5_config_params *params,
+			      krb5_context context)
+{
+     int retval;
+     void *handle;
+     
+     retval = krb5_klog_init(context, "admin_server", progname, 0);
+     if (retval)
+	  return retval;
+     if ((retval = kadm5_init(progname, NULL, NULL, params,
+			      KADM5_STRUCT_VERSION,
+			      KADM5_API_VERSION_2,
+			      db5util_db_args,
+			      &handle))) {
+	  com_err(progname, retval, "while initializing the Kerberos admin interface");
+	  return retval;
+     }
+
+     retval = add_admin_princs(handle, context, params->realm);
+
+     kadm5_destroy(handle);
+
+     krb5_klog_close(context);
+
+     return retval;
+}
+
+/*
+ * Function: build_name_with_realm
+ *
+ * Purpose: concatenate a name and a realm to form a krb5 name
+ *
+ * Arguments:
+ *
+ * 	name	(input) the name
+ * 	realm	(input) the realm
+ *
+ * Returns:
+ *
+ * 	pointer to name@realm, in allocated memory, or NULL if it
+ * 	cannot be allocated
+ *
+ * Requires: both strings are null-terminated
+ */
+static char *build_name_with_realm(char *name, char *realm)
+{
+     char *n;
+
+     n = (char *) malloc(strlen(name) + strlen(realm) + 2);
+     sprintf(n, "%s@%s", name, realm);
+     return n;
+}
+
+/*
+ * Function: add_admin_princs
+ *
+ * Purpose: create admin principals
+ *
+ * Arguments:
+ *
+ * 	rseed		(input) random seed
+ * 	realm		(input) realm, or NULL for default realm
+ *      <return value>  (output) status, 0 for success, 1 for serious error
+ *      
+ * Requires:
+ *      
+ * Effects:
+ *      
+ * add_admin_princs creates KADM5_ADMIN_SERVICE,
+ * KADM5_CHANGEPW_SERVICE.  If any of these exist a message is
+ * printed.  If any of these existing principal do not have the proper
+ * attributes, a warning message is printed.
+ */
+static int add_admin_princs(void *handle, krb5_context context, char *realm)
+{
+  krb5_error_code ret = 0;
+  char service_name[MAXHOSTNAMELEN + 8];
+  char localname[MAXHOSTNAMELEN];
+  struct addrinfo *ai, ai_hints;
+  int gai_error;
+
+  if (gethostname(localname, MAXHOSTNAMELEN)) {
+      ret = errno;
+      perror("gethostname");
+      goto clean_and_exit;
+  }
+  memset(&ai_hints, 0, sizeof(ai_hints));
+  ai_hints.ai_flags = AI_CANONNAME;
+  gai_error = getaddrinfo(localname, (char *)NULL, &ai_hints, &ai);
+  if (gai_error) {
+      ret = EINVAL;
+      fprintf(stderr, "getaddrinfo(%s): %s\n", localname,
+	      gai_strerror(gai_error));
+      goto clean_and_exit;
+  }
+  if (ai->ai_canonname == NULL) {
+      ret = EINVAL;
+      fprintf(stderr,
+	      "getaddrinfo(%s): Cannot determine canonical hostname.\n",
+	      localname);
+      freeaddrinfo(ai);
+      goto clean_and_exit;
+  }
+  sprintf(service_name, "kadmin/%s", ai->ai_canonname);
+  freeaddrinfo(ai);
+
+  if ((ret = add_admin_princ(handle, context,
+			     service_name, realm,
+			     KRB5_KDB_DISALLOW_TGT_BASED,
+			     ADMIN_LIFETIME)))
+      goto clean_and_exit;
+
+  if ((ret = add_admin_princ(handle, context,
+			     KADM5_ADMIN_SERVICE, realm,
+			     KRB5_KDB_DISALLOW_TGT_BASED,
+			     ADMIN_LIFETIME)))
+       goto clean_and_exit;
+
+  if ((ret = add_admin_princ(handle, context, 
+			     KADM5_CHANGEPW_SERVICE, realm, 
+			     KRB5_KDB_DISALLOW_TGT_BASED |
+			     KRB5_KDB_PWCHANGE_SERVICE,
+			     CHANGEPW_LIFETIME)))
+       goto clean_and_exit;
+  
+clean_and_exit:
+
+  return ret;
+}
+
+/*
+ * Function: add_admin_princ
+ *
+ * Arguments:
+ *
+ * 	creator		(r) principal to use as "mod_by"
+ * 	rseed		(r) seed for random key generator
+ * 	name		(r) principal name
+ * 	realm		(r) realm name for principal
+ * 	attrs		(r) principal's attributes
+ * 	lifetime	(r) principal's max life, or 0
+ * 	not_unique	(r) error message for multiple entries, never used
+ * 	exists		(r) warning message for principal exists
+ * 	wrong_attrs	(r) warning message for wrong attributes
+ *
+ * Returns:
+ *
+ * 	OK on success
+ * 	ERR on serious errors
+ *
+ * Effects:
+ * 
+ * If the principal is not unique, not_unique is printed (but this
+ * never happens).  If the principal exists, then exists is printed
+ * and if the principals attributes != attrs, wrong_attrs is printed.
+ * Otherwise, the principal is created with mod_by creator and
+ * attributes attrs and max life of lifetime (if not zero).
+ */
+
+int add_admin_princ(void *handle, krb5_context context,
+		    char *name, char *realm, int attrs, int lifetime)
+{
+     char *fullname;
+     krb5_error_code ret;
+     kadm5_principal_ent_rec ent;
+
+     memset(&ent, 0, sizeof(ent));
+
+     fullname = build_name_with_realm(name, realm);
+     ret = krb5_parse_name(context, fullname, &ent.principal);
+     if (ret) {
+	  com_err(progname, ret, str_PARSE_NAME);
+	  return(ERR);
+     }
+     ent.max_life = lifetime;
+     ent.attributes = attrs | KRB5_KDB_DISALLOW_ALL_TIX;
+     
+     ret = kadm5_create_principal(handle, &ent,
+				  (KADM5_PRINCIPAL | KADM5_MAX_LIFE |
+				   KADM5_ATTRIBUTES),
+				  "to-be-random");
+     if (ret) {
+	  if (ret != KADM5_DUP) {
+	       com_err(progname, ret, str_PUT_PRINC, fullname);
+	       krb5_free_principal(context, ent.principal);
+	       free(fullname);
+	       return ERR;
+	  }
+     } else {
+	  /* only randomize key if we created the principal */
+	  ret = kadm5_randkey_principal(handle, ent.principal, NULL, NULL);
+	  if (ret) {
+	       com_err(progname, ret, str_RANDOM_KEY, fullname);
+	       krb5_free_principal(context, ent.principal);
+	       free(fullname);
+	       return ERR;
+	  }
+	  
+	  ent.attributes = attrs;
+	  ret = kadm5_modify_principal(handle, &ent, KADM5_ATTRIBUTES);
+	  if (ret) {
+	       com_err(progname, ret, str_PUT_PRINC, fullname);
+	       krb5_free_principal(context, ent.principal);
+	       free(fullname);
+	       return ERR;
+	  }
+     }
+     
+     krb5_free_principal(context, ent.principal);
+     free(fullname);
+
+     return OK;
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/kdb5_create.c b/krb5-1-6/src/kadmin/dbutil/kdb5_create.c
new file mode 100644
index 000000000..da192256e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kdb5_create.c
@@ -0,0 +1,437 @@
+/*
+ * kadmin/dbutil/kdb5_create.c
+ *
+ * Copyright 1990,1991,2001, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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 <kdb.h>
+#include <kadm5/server_internal.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#include "kdb5_util.h"
+
+enum ap_op {
+    NULL_KEY,				/* setup null keys */
+    MASTER_KEY,				/* use master key as new key */
+    TGT_KEY				/* special handling for tgt key */
+};
+
+krb5_key_salt_tuple def_kslist = { ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL };
+
+struct realm_info {
+    krb5_deltat max_life;
+    krb5_deltat max_rlife;
+    krb5_timestamp expiration;
+    krb5_flags flags;
+    krb5_keyblock *key;
+    krb5_int32 nkslist;
+    krb5_key_salt_tuple *kslist;
+} rblock = { /* XXX */
+    KRB5_KDB_MAX_LIFE,
+    KRB5_KDB_MAX_RLIFE,
+    KRB5_KDB_EXPIRATION,
+    KRB5_KDB_DEF_FLAGS,
+    (krb5_keyblock *) NULL,
+    1,
+    &def_kslist
+};
+
+struct iterate_args {
+    krb5_context	ctx;
+    struct realm_info	*rblock;
+    krb5_db_entry	*dbentp;
+};
+
+static krb5_error_code add_principal 
+	(krb5_context,
+	 krb5_principal,
+	 enum ap_op,
+	 struct realm_info *);
+
+/*
+ * Steps in creating a database:
+ *
+ * 1) use the db calls to open/create a new database
+ *
+ * 2) get a realm name for the new db
+ *
+ * 3) get a master password for the new db; convert to an encryption key.
+ *
+ * 4) create various required entries in the database
+ *
+ * 5) close & exit
+ */
+
+extern krb5_keyblock master_keyblock;
+extern krb5_principal master_princ;
+krb5_data master_salt;
+
+krb5_data tgt_princ_entries[] = {
+	{0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
+	{0, 0, 0} };
+
+krb5_data db_creator_entries[] = {
+	{0, sizeof("db_creation")-1, "db_creation"} };
+
+/* XXX knows about contents of krb5_principal, and that tgt names
+ are of form TGT/REALM@REALM */
+krb5_principal_data tgt_princ = {
+        0,					/* magic number */
+	{0, 0, 0},				/* krb5_data realm */
+	tgt_princ_entries,			/* krb5_data *data */
+	2,					/* int length */
+	KRB5_NT_SRV_INST			/* int type */
+};
+
+krb5_principal_data db_create_princ = {
+        0,					/* magic number */
+	{0, 0, 0},				/* krb5_data realm */
+	db_creator_entries,			/* krb5_data *data */
+	1,					/* int length */
+	KRB5_NT_SRV_INST			/* int type */
+};
+
+extern char *mkey_password;
+
+extern char *progname;
+extern int exit_status;
+extern kadm5_config_params global_params;
+extern krb5_context util_context;
+
+void kdb5_create(argc, argv)
+   int argc;
+   char *argv[];
+{
+    int optchar;
+
+    krb5_error_code retval;
+    char *mkey_fullname;
+    char *pw_str = 0;
+    unsigned int pw_size = 0;
+    int do_stash = 0;
+    krb5_data pwd, seed;
+	   
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+
+    while ((optchar = getopt(argc, argv, "s")) != -1) {
+	switch(optchar) {
+	case 's':
+	    do_stash++;
+	    break;
+	case 'h':
+	    if (!add_db_arg("hash=true")) {
+		com_err(progname, ENOMEM, "while parsing command arguments\n");
+		exit(1);
+	    }
+	    break;
+	case '?':
+	default:
+	    usage();
+	    return;
+	}
+    }
+
+    rblock.max_life = global_params.max_life;
+    rblock.max_rlife = global_params.max_rlife;
+    rblock.expiration = global_params.expiration;
+    rblock.flags = global_params.flags;
+    rblock.nkslist = global_params.num_keysalts;
+    rblock.kslist = global_params.keysalts;
+
+    printf ("Loading random data\n");
+    retval = krb5_c_random_os_entropy (util_context, 1, NULL);
+    if (retval) {
+      com_err (argv[0], retval, "Loading random data");
+      exit_status++; return;
+    }
+    
+    /* assemble & parse the master key name */
+
+    if ((retval = krb5_db_setup_mkey_name(util_context,
+					  global_params.mkey_name,
+					  global_params.realm,  
+					  &mkey_fullname, &master_princ))) {
+	com_err(argv[0], retval, "while setting up master key name");
+	exit_status++; return;
+    }
+
+    krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm);
+    krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm));
+    krb5_princ_set_realm_data(util_context, &tgt_princ, global_params.realm);
+    krb5_princ_set_realm_length(util_context, &tgt_princ, strlen(global_params.realm));
+    krb5_princ_component(util_context, &tgt_princ,1)->data = global_params.realm;
+    krb5_princ_component(util_context, &tgt_princ,1)->length = strlen(global_params.realm);
+
+    printf("Initializing database '%s' for realm '%s',\n\
+master key name '%s'\n",
+	   global_params.dbname, global_params.realm, mkey_fullname);
+
+    if (!mkey_password) {
+	printf("You will be prompted for the database Master Password.\n");
+	printf("It is important that you NOT FORGET this password.\n");
+	fflush(stdout);
+
+	pw_size = 1024;
+	pw_str = malloc(pw_size);
+	
+	retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2,
+				    pw_str, &pw_size);
+	if (retval) {
+	    com_err(argv[0], retval, "while reading master key from keyboard");
+	    exit_status++; return;
+	}
+	mkey_password = pw_str;
+    }
+
+    pwd.data = mkey_password;
+    pwd.length = strlen(mkey_password);
+    retval = krb5_principal2salt(util_context, master_princ, &master_salt);
+    if (retval) {
+	com_err(argv[0], retval, "while calculating master key salt");
+	exit_status++; return;
+    }
+
+    retval = krb5_c_string_to_key(util_context, master_keyblock.enctype, 
+				  &pwd, &master_salt, &master_keyblock);
+    if (retval) {
+	com_err(argv[0], retval, "while transforming master key from password");
+	exit_status++; return;
+    }
+
+    rblock.key = &master_keyblock;
+
+    seed.length = master_keyblock.length;
+    seed.data = master_keyblock.contents;
+
+    if ((retval = krb5_c_random_seed(util_context, &seed))) {
+	com_err(argv[0], retval, "while initializing random key generator");
+	exit_status++; return;
+    }
+    if ((retval = krb5_db_create(util_context,
+				 db5util_db_args))) {
+	com_err(argv[0], retval, "while creating database '%s'",
+		global_params.dbname);
+	exit_status++; return;
+    }
+/*     if ((retval = krb5_db_fini(util_context))) { */
+/*         com_err(argv[0], retval, "while closing current database"); */
+/*         exit_status++; return; */
+/*     } */
+/*     if ((retval = krb5_db_open(util_context, db5util_db_args, KRB5_KDB_OPEN_RW))) { */
+/* 	com_err(argv[0], retval, "while initializing the database '%s'", */
+/* 		global_params.dbname); */
+/* 	exit_status++; return; */
+/*     } */
+    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);
+	com_err(argv[0], retval, "while adding entries to the database");
+	exit_status++; return;
+    }
+    /*
+     * Always stash the master key so kadm5_create does not prompt for
+     * it; delete the file below if it was not requested.  DO NOT EXIT
+     * BEFORE DELETING THE KEYFILE if do_stash is not set.
+     */
+    retval = krb5_db_store_master_key(util_context,
+				      global_params.stash_file,
+				      master_princ,
+				      &master_keyblock,
+				      mkey_password);
+    if (retval) {
+	com_err(argv[0], errno, "while storing key");
+	printf("Warning: couldn't stash master key.\n");
+    }
+    /* clean up */
+    (void) krb5_db_fini(util_context);
+    memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+    free(master_keyblock.contents);
+    if (pw_str) {
+	memset(pw_str, 0, pw_size);
+	free(pw_str);
+    }
+    free(master_salt.data);
+
+    if (kadm5_create(&global_params)) {
+	 if (!do_stash) unlink(global_params.stash_file);
+	 exit_status++;
+	 return;
+    }
+    if (!do_stash) unlink(global_params.stash_file);
+
+    return;
+}
+
+static krb5_error_code
+tgt_keysalt_iterate(ksent, ptr)
+    krb5_key_salt_tuple	*ksent;
+    krb5_pointer	ptr;
+{
+    krb5_context	context;
+    krb5_error_code	kret;
+    struct iterate_args	*iargs;
+    krb5_keyblock	key;
+    krb5_int32		ind;
+    krb5_data	pwd;
+
+    iargs = (struct iterate_args *) ptr;
+    kret = 0;
+
+    context = iargs->ctx;
+
+    /*
+     * Convert the master key password into a key for this particular
+     * encryption system.
+     */
+    pwd.data = mkey_password;
+    pwd.length = strlen(mkey_password);
+    kret = krb5_c_random_seed(context, &pwd);
+    if (kret)
+	return kret;
+
+    if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {
+	ind = iargs->dbentp->n_key_data-1;
+	if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype,
+					    &key))) {
+	    kret = krb5_dbekd_encrypt_key_data(context,
+					       iargs->rblock->key,
+					       &key, 
+					       NULL,
+					       1,
+					       &iargs->dbentp->key_data[ind]);
+	    krb5_free_keyblock_contents(context, &key);
+	}
+    }
+
+    return(kret);
+}
+
+static krb5_error_code
+add_principal(context, princ, op, pblock)
+    krb5_context context;
+    krb5_principal princ;
+    enum ap_op op;
+    struct realm_info *pblock;
+{
+    krb5_error_code 	  retval;
+    krb5_db_entry 	  entry;
+
+    krb5_timestamp	  now;
+    struct iterate_args	  iargs;
+
+    int			  nentries = 1;
+
+    memset((char *) &entry, 0, sizeof(entry));
+
+    entry.len = KRB5_KDB_V1_BASE_LENGTH;
+    entry.attributes = pblock->flags;
+    entry.max_life = pblock->max_life;
+    entry.max_renewable_life = pblock->max_rlife;
+    entry.expiration = pblock->expiration;
+
+    if ((retval = krb5_copy_principal(context, princ, &entry.princ)))
+	goto error_out;
+
+    if ((retval = krb5_timeofday(context, &now)))
+	goto error_out;
+
+    if ((retval = krb5_dbe_update_mod_princ_data(context, &entry,
+						 now, &db_create_princ)))
+	goto error_out;
+
+    switch (op) {
+    case MASTER_KEY:
+	if ((entry.key_data=(krb5_key_data*)malloc(sizeof(krb5_key_data)))
+	    == NULL)
+	    goto error_out;
+	memset((char *) entry.key_data, 0, sizeof(krb5_key_data));
+	entry.n_key_data = 1;
+
+	entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+	if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
+						  &master_keyblock, NULL, 
+						  1, entry.key_data)))
+	    return retval;
+	break;
+    case TGT_KEY:
+	iargs.ctx = context;
+	iargs.rblock = pblock;
+	iargs.dbentp = &entry;
+	/*
+	 * Iterate through the key/salt list, ignoring salt types.
+	 */
+	if ((retval = krb5_keysalt_iterate(pblock->kslist,
+					   pblock->nkslist,
+					   1,
+					   tgt_keysalt_iterate,
+					   (krb5_pointer) &iargs)))
+	    return retval;
+	break;
+    case NULL_KEY:
+	return EOPNOTSUPP;
+    default:
+	break;
+    }
+
+    entry.mask = (KADM5_KEY_DATA | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
+	KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_TL_DATA |
+	KADM5_PRINC_EXPIRE_TIME);
+
+    retval = krb5_db_put_principal(context, &entry, &nentries);
+
+error_out:;
+    krb5_db_free_principal(context, &entry, 1);
+    return retval;
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/kdb5_destroy.c b/krb5-1-6/src/kadmin/dbutil/kdb5_destroy.c
new file mode 100644
index 000000000..22b75eef6
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kdb5_destroy.c
@@ -0,0 +1,112 @@
+/*
+ * admin/destroy/kdb5_destroy.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * kdb_dest(roy): destroy the named database.
+ *
+ * This version knows about DBM format databases.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include "com_err.h"
+#include <kadm5/admin.h>
+#include <kdb.h>
+#include "kdb5_util.h"
+
+extern int exit_status;
+extern krb5_boolean dbactive;
+extern kadm5_config_params global_params;
+
+char *yes = "yes\n";			/* \n to compare against result of
+					   fgets */
+
+void
+kdb5_destroy(argc, argv)
+    int argc;
+    char *argv[];
+{
+    extern char *optarg;
+    extern int optind;
+    int optchar;
+    char *dbname;
+    char buf[5];
+    krb5_error_code retval1;
+    krb5_context context;
+    int force = 0;
+
+    retval1 = kadm5_init_krb5_context(&context);
+    if( retval1 )
+    {
+	com_err(argv[0], retval1, "while initializing krb5_context");
+	exit(1);
+    }
+
+    if ((retval1 = krb5_set_default_realm(context,
+					  util_context->default_realm))) {
+	com_err(argv[0], retval1, "while setting default realm name");
+	exit(1);
+    }
+    
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+
+    dbname = global_params.dbname;
+
+    optind = 1;
+    while ((optchar = getopt(argc, argv, "f")) != -1) {
+	switch(optchar) {
+	case 'f':
+	    force++;
+	    break;
+	case '?':
+	default:
+	    usage();
+	    return;
+	    /*NOTREACHED*/
+	}
+    }
+    if (!force) {
+	printf("Deleting KDC database stored in '%s', are you sure?\n", dbname);
+	printf("(type 'yes' to confirm)? ");
+	if (fgets(buf, sizeof(buf), stdin) == NULL) {
+	    exit_status++; return;
+        }
+	if (strcmp(buf, yes)) {
+	    exit_status++; return;
+        }
+	printf("OK, deleting database '%s'...\n", dbname);
+    }
+
+    retval1 = krb5_db_destroy(context, db5util_db_args);
+    if (retval1) {
+	com_err(argv[0], retval1, "deleting database '%s'",dbname);
+	exit_status++; return;
+    }
+
+    dbactive = FALSE;
+    printf("** Database '%s' destroyed.\n", dbname);
+    return;
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/kdb5_edit.M b/krb5-1-6/src/kadmin/dbutil/kdb5_edit.M
new file mode 100644
index 000000000..217c266b1
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kdb5_edit.M
@@ -0,0 +1,182 @@
+.\" admin/edit/kdb5_edit.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" 
+.\"
+.TH KDB5_EDIT 8
+.SH NAME
+kdb5_edit \- edit a Kerberos V5 principal database
+.SH SYNOPSIS
+.B kdb5_edit
+[
+.B \-r
+.I realm
+] [
+.B \-d
+.I dbname
+] [
+.B \-k
+.I keytype
+] [
+.B \-M
+.I mkeyname
+] [
+.B \-e
+.I enctype
+] [
+.B \-m
+] [
+.B \-R
+.I command
+] [
+.B \-s
+.I script
+] [
+.B \-f
+.I stashfile
+]
+.br
+.SH DESCRIPTION
+.I kdb5_edit
+allows an administrator to add, delete, and edit entries in a Kerberos
+version 5 principal database.
+After themaster key is verified, commands are to
+.I kdb5_edit
+are issued using one of three mechanisms.  If a single command is supplied 
+using the
+.B \-R
+.I command
+argument, then that single command is processed and execution ceases.  If a
+script file is provided using the 
+.B \-s
+.I script
+argument, then commands are read from this file until either an error occurs
+or an end of file is detected.  Finally, if neither a command or a script is
+specified, the invoker is placed into a shell-like command loop, from which
+[s]he may issue commands to modify the
+database.  
+.PP
+The
+.B \-r
+.I realm
+option specifies the realm of the database;
+by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.PP
+The
+.B \-d
+.I dbname
+option specifies the name under which the principal database is stored;
+by default the database is in DEFAULT_DBM_FILE (defined in <krb5/osconf.h>).
+.PP
+The
+.B \-k
+.I keytype
+option specifies the key type of the master key in the database; the default is
+the string representation of DEFAULT_KDC_KEYTYPE (defined in <krb5/osconf.h>).
+.PP
+The
+.B \-f
+.I stashfile
+option specifies the filename of the stashed V5 master key. The default is
+defined as DEFAULT_KEYFILE_STUB in <krb5/osconf.h> and is 
+typically $(prefix)/lib/krb5kdc/.k5.REALMNAME. (In previous
+releases, this would have been /.k5.REALMNAME.)
+.PP
+The
+.B \-M
+.I mkeyname
+option specifies the principal name for the master key in the database;
+the default is KRB5_KDB_M_NAME (defined in <krb5/kdb.h>).
+.PP
+The
+.B \-e
+.I enctype
+option specifies the encryption type to be used when placing entries in
+the database; the default is the string representation of DEFAULT_KDC_ETYPE
+(defined in <krb5/osconf.h>).
+.PP
+The
+.B \-m
+option specifies that the master database password should be fetched
+from the keyboard rather than from a file on disk.
+.SH AVAILABLE COMMANDS
+
+The following is a list of commands and their aliases that the system
+administrator may use to manipulate the database:
+
+.IP add_new_key,ank
+Add new entry to Kerberos database (prompting for password)
+
+.IP change_pwd_key,cpw      
+Change key of an entry in the Kerberos database (prompting for password)
+
+.IP add_rnd_key,ark         
+Add new entry to Kerberos database, using a random key
+
+.IP change_rnd_key,crk      
+Change key of an entry in the Kerberos database (select a new random key)
+
+.IP delete_entry,delent,del
+Delete an entry from the database
+
+.IP extract_srvtab,xst,ex_st
+Extract service key table
+
+.IP extract_v4_srvtab,xst4  
+Extract service key table
+
+.IP modify_entry,modent
+Modify entry
+
+.IP list_db,ldb             
+List database entries
+
+.IP dump_db,ddb             
+Dump database entries to a file
+
+.IP load_db,lddb            
+Load database entries from a file
+
+.IP set_dbname,sdbn         
+Change database name
+
+.IP enter_master_key,emk    
+Enter the master key for a database
+
+.IP change_working_directory,cwd,cd
+Change working directory
+
+.IP print_working_direcotry,pwd
+Print working directory
+
+.IP list_requests,lr,?     
+List available requests.
+
+.IP quit,exit,q            
+Exit program.
+
+.SH SEE ALSO
+krb5(3), krb5kdc(8), ss(3)
+.SH BUGS
+
diff --git a/krb5-1-6/src/kadmin/dbutil/kdb5_stash.c b/krb5-1-6/src/kadmin/dbutil/kdb5_stash.c
new file mode 100644
index 000000000..7e8fd3e8b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kdb5_stash.c
@@ -0,0 +1,183 @@
+/*
+ * admin/stash/kdb5_stash.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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>
+#include <stdio.h>
+#include "kdb5_util.h"
+
+extern krb5_keyblock master_keyblock;
+extern krb5_principal master_princ;
+extern kadm5_config_params global_params;
+
+extern int exit_status;
+extern int close_policy_db;
+
+void
+kdb5_stash(argc, argv)
+    int argc;
+    char *argv[];
+{
+    extern char *optarg;
+    extern int optind;
+    int optchar;
+    krb5_error_code retval;
+    char *dbname = (char *) NULL;
+    char *realm = 0;
+    char *mkey_name = 0;
+    char *mkey_fullname;
+    char *keyfile = 0;
+    krb5_context context;
+
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+
+    retval = kadm5_init_krb5_context(&context);
+    if( retval )
+    {
+	com_err(argv[0], retval, "while initializing krb5_context");
+	exit(1);
+    }
+
+    if ((retval = krb5_set_default_realm(context,
+					  util_context->default_realm))) {
+	com_err(argv[0], retval, "while setting default realm name");
+	exit(1);
+    }
+
+    dbname = global_params.dbname;
+    realm = global_params.realm;
+    mkey_name = global_params.mkey_name;
+    keyfile = global_params.stash_file;
+
+    optind = 1;
+    while ((optchar = getopt(argc, argv, "f:")) != -1) {
+	switch(optchar) {
+	case 'f':
+	    keyfile = optarg;
+	    break;
+	case '?':
+	default:
+	    usage();
+	    return;
+	}
+    }
+
+    if (!krb5_c_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_status++; return; 
+    }
+
+    /* assemble & parse the master key name */
+    retval = krb5_db_setup_mkey_name(context, mkey_name, realm, 
+				     &mkey_fullname, &master_princ);
+    if (retval) {
+	com_err(argv[0], retval, "while setting up master key name");
+	exit_status++; return; 
+    }
+
+    retval = krb5_db_open(context, db5util_db_args, 
+			  KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_OTHER);
+    if (retval) {
+	com_err(argv[0], retval, "while initializing the database '%s'",
+		dbname);
+	exit_status++; return; 
+    }
+
+    /* TRUE here means read the keyboard, but only once */
+    retval = krb5_db_fetch_mkey(context, master_princ,
+				master_keyblock.enctype,
+				TRUE, FALSE, (char *) NULL,
+				0, &master_keyblock);
+    if (retval) {
+	com_err(argv[0], retval, "while reading master key");
+	(void) krb5_db_fini(context);
+	exit_status++; return; 
+    }
+
+    retval = krb5_db_verify_master_key(context, master_princ, 
+				       &master_keyblock);
+    if (retval) {
+	com_err(argv[0], retval, "while verifying master key");
+	(void) krb5_db_fini(context);
+	exit_status++; return; 
+    }	
+
+    retval = krb5_db_store_master_key(context, keyfile, master_princ, 
+				      &master_keyblock, NULL);
+    if (retval) {
+	com_err(argv[0], errno, "while storing key");
+	memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+	(void) krb5_db_fini(context);
+	exit_status++; return; 
+    }
+    memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+
+    retval = krb5_db_fini(context);
+    if (retval) {
+	com_err(argv[0], retval, "closing database '%s'", dbname);
+	exit_status++; return; 
+    }
+
+    krb5_free_context(context);
+    exit_status = 0;
+    return; 
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/kdb5_util.M b/krb5-1-6/src/kadmin/dbutil/kdb5_util.M
new file mode 100644
index 000000000..0c7cac400
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kdb5_util.M
@@ -0,0 +1,272 @@
+.TH KDB5_UTIL 8
+.SH NAME
+kdb5_util \- Kerberos database maintainance utility
+.SH SYNOPSIS
+.B kdb5_util
+[\fB\-r\fP\ \fIrealm\fP] [\fB\-d\fP\ \fIdbname\fP]
+[\fB\-k\fP\ \fImkeytype\fP] [\fB\-M\fP\ \fImkeyname\fP]
+[\fB\-sf\fP\ \fIstashfilename\fP]
+[\fB\-m\fP]
+.I command
+.I [command_options]
+.SH DESCRIPTION
+.B kdb5_util
+allows an administrator to perform low-level maintainance procedures on
+the Kerberos and KADM5 database.  Databases can be created, destroyed,
+and dumped to and loaded from
+.SM ASCII
+files.  Additionally,
+.B kdb5_util
+can create a Kerberos master key stash file.
+.B kdb5_util
+subsumes the functionality of and makes obsolete the previous database
+maintainance programs
+.BR kdb5_create ,
+.BR kdb5_edit ,
+.BR kdb5_destroy ,
+and
+.BR kdb5_stash .
+.PP
+When
+.B kdb5_util
+is run, it attempts to acquire the master key and open the database.
+However, execution continues regardless of whether or not
+.B kdb5_util
+successfully opens the database, because the database may not exist yet
+or the stash file may be corrupt.
+.PP
+Note that some KDB plugins may not support all
+.B kdb5_util
+commands.
+.SH COMMAND-LINE OPTIONS
+.TP
+\fB\-r\fP\ \fIrealm\fP
+specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+\fB\-d\fP\ \fIdbname\fP
+specifies the name under which the principal database is stored; by
+default the database is that listed in
+.IR kdc.conf (5).
+The KADM5 policy database and lock file are also derived from this
+value.
+.TP
+\fB\-k\fP\ \fImkeytype\fP
+specifies the key type of the master key in the database; the default is
+that given in
+.IR kdc.conf .
+.TP
+\fB\-M\fP\ \fImkeyname\fP
+principal name for the master key in the database; the default is
+that given in
+.IR kdc.conf .
+.TP
+.B \-m
+specifies that the master database password should be read from the TTY
+rather than fetched from a file on disk.
+.TP
+\fB\-sf\fP \fIstash_file\fP
+specifies the stash file of the master database password.
+.TP
+\fB\-P\fP \fIpassword\fP
+specifies the master database password.  This option is not recommended.
+.SH COMMANDS
+.TP
+\fBcreate\fP [\fB\-s\fP]
+Creates a new database.  If the
+.B \-s
+option is specified, the stash file is also created.  This command fails
+if the database already exists.  If the command is successful, the
+database is opened just as if it had already existed when the program
+was first run.
+.TP
+\fBdestroy\fP [\fB\-f\fP]
+Destroys the database, first overwriting the disk sectors and then
+unlinking the files, after prompting the user for confirmation.  With
+the
+.B \-f
+argument, does not prompt the user.
+.TP
+\fBstash\fP [\fB\-f\fP\ \fIkeyfile\fP]
+Stores the master principal's keys in a stash file.  The
+.B \-f
+argument can be used to override the keyfile specified at startup.
+.TP
+\fBdump\fP [\fB\-old\fP] [\fB\-b6\fP] [\fB\-b7\fP] [\fB\-ov\fP]
+[\fB\-verbose\fP] [\fB\-mkey_convert\fP]
+[\fB\-new_mkey_file\fP \fImkey_file\fP] [\fB\-rev\fP] [\fB\-recurse\fP]
+[\fIfilename\fP [\fIprincipals...\fP]]
+.br
+Dumps the current Kerberos and KADM5 database into an ASCII file.  By
+default, the database is dumped in current format, "kdb5_util
+load_dumpversion 5".  If
+.I filename
+is not specified, or is the string "\-", the dump is sent to standard
+output.  Options:
+.RS
+.TP
+.B \-old
+causes the dump to be in the Kerberos 5 Beta 5 and earlier dump format
+("kdb5_edit load_dump version 2.0").
+.TP
+.B \-b6
+causes the dump to be in the Kerberos 5 Beta 6 format ("kdb5_edit
+load_dump version 3.0").
+.TP
+.B \-b7
+causes the dump to be in the Kerberos 5 Beta 7 format ("kdb5_util load_dump version 4").  This was the dump format produced on releases prior to 1.2.2.
+.TP
+.B \-ov
+causes the dump to be in
+.I ovsec_adm_export
+format.
+.TP
+.B \-verbose
+causes the name of each principal and policy to be printed as it is
+dumped.
+.TP
+.B \-mkey_convert
+prompts for a new master key.  This new master key will be used to
+re-encrypt the key data in the dumpfile.  The key data in the database
+will not be changed.
+.TP
+.B \-new_mkey_file \fImkey_file\fP
+the filename of a stash file.  The master key in this stash file will
+be used to re-encrypt the key data in the dumpfile.  The key data in
+the database will not be changed.
+.TP
+.B \-rev
+dumps in reverse order.  This may recover principals that do not dump
+normally, in cases where database corruption has occured.
+.TP
+.B \-recurse
+causes the dump to walk the database recursively (btree only).  This
+may recover principals that do not dump normally, in cases where
+database corruption has occured.  In cases of such corruption, this
+option will probably retrieve more principals than the \fB\-rev\fP
+option will.
+.RE
+.TP
+\fBload\fP [\fB\-old\fP] [\fB\-b6\fP] [\fB\-b7\fP] [\fB\-ov\fP] [\fB\-hash\fP]
+[\fB\-verbose\fP] [\fB\-update\fP] \fIfilename dbname\fP [\fIadmin_dbname\fP]
+.br
+Loads a database dump from the named file into the named database.
+Unless the 
+.B \-old
+or 
+.B \-b6
+option is given, the format of the dump file is detected
+automatically and handled as appropriate.  Unless the
+.B \-update
+option is given, 
+.B load
+creates a new database containing only the principals in the dump file,
+overwriting the contents of any previously existing database.  Note that
+when using the LDAP KDB plugin the
+.B \-update
+must be given.  Options:
+.RS
+.TP
+.B \-old
+requires the database to be in the Kerberos 5 Beta 5 and earlier format
+("kdb5_edit load_dump version 2.0").
+.TP
+.B \-b6
+requires the database to be in the Kerberos 5 Beta 6 format ("kdb5_edit
+load_dump version 3.0").
+.TP
+.B \-b7
+requires the database to be in the Kerberos 5 Beta 7 format ("kdb5_util
+load_dump version 4").
+.TP
+.B \-ov
+requires the database to be in
+.I ovsec_adm_import
+format.  Must be used with the
+.B \-update
+option.
+.TP
+.B \-hash
+requires the database to be stored as a hash.  If this option is not
+specified, the database will be stored as a btree.  This option
+is not recommended, as databases stored in hash format are known to
+corrupt data and lose principals.
+.TP
+.B \-verbose
+causes the name of each principal and policy to be printed as it is
+dumped.
+.TP
+.B \-update
+records from the dump file are added to or updated in the existing
+database; otherwise, a new database is created containing only what is
+in the dump file and the old one destroyed upon successful completion.
+.TP
+.B dbname
+is required and overrides the value specified on the command line or the
+default.
+.TP
+.B admin_dbname
+is optional and is derived from
+.B dbname
+if not specified.
+.RE
+.TP
+\fBdump_v4\fP [\fB\-S\fP] [\fIfilename\fP]
+Dumps the current database into the Kerberos 4 database dump format.
+The \-S option specifies the short lifetime algorithm.
+.TP
+\fBload_v4\fP [\fB\-T\fP] [\fB\-v\fP] [\fB\-h\fP] [\fB\-S\fP]
+[\fB\-t\fP] [\fB-n\fP] [\fB\-K\fP] [\fB\-s\fP\ \fIstashfile\fP]
+\fIinputfile\fP
+.br
+Loads a Kerberos 4 database dump file.  Options:
+.RS
+.TP
+.B \-K
+prompts for the V5 master key instead of using the stashed version.
+.TP
+.B \-n
+prompts for the V4 master key, instead of reading from the stash file.
+.TP
+.B \-s \fIstashfile
+gets the V4 master key out of \fIstashfile\fP instead of /.k
+.TP
+.B \-T
+creates a new \fIkrbtgt\fP instead of converting the V4 one.  The V5 server
+will thus not recognize outstanding tickets, so this should be used 
+with caution.
+.TP
+.B \-v
+lists each principal as it is converted or ignored.
+.TP
+.B \-t
+uses a temporary database, then moves that into place, instead of adding 
+the keys to the current database.
+.TP
+.B \-S
+Uses the short lifetime algorithm for conversion.
+.TP
+.B \-h
+Stores the database as a hash instead of a btree.  This option is
+not recommended, as databases stored in hash format are known to
+corrupt data and lose principals.
+.PP
+Note: if the Kerberos 4 database had a default expiration date of 12/31/1999
+or 12/31/2009 (the compiled in defaults for older or newer Kerberos
+releases) then any entries which have the same expiration date will be
+converted to "never" expire in the version 5 database.  If the default
+did not match either value, all expiration dates will be preserved. 
+.PP
+Also, Kerberos 4 stored a single modification time for any change to a
+record; Version 5 stores a seperate modification time and last
+password change time.  In practice, Version 4 "modifications" were
+always password changes.  \fIload_v4\fP copies the value into both
+fields.
+.RE
+.TP
+\fBark\fP
+Adds a random key.
+.SH SEE ALSO
+kadmin(8)
diff --git a/krb5-1-6/src/kadmin/dbutil/kdb5_util.c b/krb5-1-6/src/kadmin/dbutil/kdb5_util.c
new file mode 100644
index 000000000..1807d1ad0
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kdb5_util.c
@@ -0,0 +1,613 @@
+/*
+ * admin/edit/kdb5_edit.c
+ *
+ * (C) Copyright 1990,1991, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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>
+#include <adm_proto.h>
+#include <time.h>
+#include "kdb5_util.h"
+
+char	*Err_no_master_msg = "Master key not entered!\n";
+char	*Err_no_database = "Database not currently opened!\n";
+
+/*
+ * XXX Ick, ick, ick.  These global variables shouldn't be global....
+ */
+char *mkey_password = 0;
+
+/*
+ * I can't figure out any way for this not to be global, given how ss
+ * works.
+ */
+
+int exit_status = 0;
+krb5_context util_context;
+kadm5_config_params global_params;
+
+void usage()
+{
+     fprintf(stderr, "Usage: "
+	   "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n"
+	     "\t        [-sf stashfilename] [-m] cmd [cmd_options]\n"
+	     "\tcreate	[-s]\n"
+	     "\tdestroy	[-f]\n"
+	     "\tstash	[-f keyfile]\n"
+	     "\tdump	[-old] [-ov] [-b6] [-verbose]\n"
+	     "\t	[-mkey_convert] [-new_mkey_file mkey_file]\n"
+	     "\t	[-rev] [-recurse] [filename [princs...]]\n"
+	     "\tload	[-old] [-ov] [-b6] [-verbose] [-update] filename\n"
+	     "\tark	[-e etype_list] principal\n"
+	     "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
+	     "\t\t\tLook at each database documentation for supported arguments\n");
+     exit(1);
+}
+
+extern krb5_keyblock master_keyblock;
+extern krb5_principal master_princ;
+krb5_db_entry master_entry;
+int	valid_master_key = 0;
+
+char *progname;
+krb5_boolean manual_mkey = FALSE;
+krb5_boolean dbactive = FALSE;
+
+static int open_db_and_mkey(void);
+
+static void add_random_key(int, char **);
+   
+typedef void (*cmd_func)(int, char **);
+
+struct _cmd_table {
+     char *name;
+     cmd_func func;
+     int opendb;
+} cmd_table[] = {
+     {"create", kdb5_create, 0},
+     {"destroy", kdb5_destroy, 1},
+     {"stash", kdb5_stash, 1},
+     {"dump", dump_db, 1},
+     {"load", load_db, 0},
+/*      {"dump_v4", dump_v4db, 1}, */
+/*      {"load_v4", load_v4db, 0}, */
+     {"ark", add_random_key, 1},
+     {NULL, NULL, 0},
+};
+
+static struct _cmd_table *cmd_lookup(name)
+   char *name;
+{
+     struct _cmd_table *cmd = cmd_table;
+     while (cmd->name) {
+	  if (strcmp(cmd->name, name) == 0)
+	       return cmd;
+	  else
+	       cmd++;
+     }
+     
+     return NULL;
+}
+
+#define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL))
+
+char **db5util_db_args = NULL;
+int    db5util_db_args_size = 0;
+     
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+				 const char *fmt, va_list args)
+{
+    const char *emsg;
+    if (code) {
+	emsg = krb5_get_error_message (util_context, code);
+	fprintf (stderr, "%s: %s ", myprog, emsg);
+	krb5_free_error_message (util_context, emsg);
+    } else {
+	fprintf (stderr, "%s: ", myprog);
+    }
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+}
+
+int add_db_arg(char *arg)
+{
+    char **temp;
+    db5util_db_args_size++;
+    temp = realloc(db5util_db_args,
+		   sizeof(char *) * (db5util_db_args_size + 1));
+    if (temp == NULL)
+	return 0;
+    db5util_db_args = temp;
+    db5util_db_args[db5util_db_args_size-1] = arg;
+    db5util_db_args[db5util_db_args_size]   = NULL;
+    return 1;
+}
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    struct _cmd_table *cmd = NULL;
+    char *koptarg, **cmd_argv;	
+    char *db_name_tmp = NULL;
+    int cmd_argc;
+    krb5_error_code retval;
+
+    set_com_err_hook(extended_com_err_fn);
+
+    retval = kadm5_init_krb5_context(&util_context);
+    if (retval) {
+	    com_err (progname, retval, "while initializing Kerberos code");
+	    exit(1);
+    }
+
+/*     initialize_adb_error_table(); */
+
+    progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+    cmd_argv = (char **) malloc(sizeof(char *)*argc);
+    if (cmd_argv == NULL) {
+	 com_err(progname, ENOMEM, "while creating sub-command arguments");
+	 exit(1);
+    }
+    memset(cmd_argv, 0, sizeof(char *)*argc);
+    cmd_argc = 1;
+	 
+    argv++; argc--;
+    while (*argv) {
+       if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
+	    mkey_password = koptarg;
+	    manual_mkey = TRUE;
+       } else if (strcmp(*argv, "-d") == 0 && ARG_VAL) {
+	    global_params.dbname = koptarg;
+	    global_params.mask |= KADM5_CONFIG_DBNAME;
+
+	    db_name_tmp = malloc( strlen(global_params.dbname) + sizeof("dbname="));
+	    if( db_name_tmp == NULL )
+	    {
+		com_err(progname, ENOMEM, "while parsing command arguments");
+		exit(1);
+	    }
+
+	    strcpy( db_name_tmp, "dbname=");
+	    strcat( db_name_tmp, global_params.dbname );
+
+	    if (!add_db_arg(db_name_tmp)) {
+		com_err(progname, ENOMEM, "while parsing command arguments\n");
+		exit(1);
+	    }
+
+       } else if (strcmp(*argv, "-x") == 0 && ARG_VAL) {
+	   if (!add_db_arg(koptarg)) {
+		com_err(progname, ENOMEM, "while parsing command arguments\n");
+		exit(1);
+	   }
+
+       } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
+	    global_params.realm = koptarg;
+	    global_params.mask |= KADM5_CONFIG_REALM;
+	    /* not sure this is really necessary */
+	    if ((retval = krb5_set_default_realm(util_context,
+						 global_params.realm))) {
+		 com_err(progname, retval, "while setting default realm name");
+		 exit(1);
+	    }
+       } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
+	    if (krb5_string_to_enctype(koptarg, &global_params.enctype))
+		 com_err(argv[0], 0, "%s is an invalid enctype", koptarg);
+	    else
+		 global_params.mask |= KADM5_CONFIG_ENCTYPE;
+       } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
+	    global_params.mkey_name = koptarg;
+	    global_params.mask |= KADM5_CONFIG_MKEY_NAME;
+       } else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) {
+	    global_params.stash_file = koptarg;
+	    global_params.mask |= KADM5_CONFIG_STASH_FILE;
+       } else if (strcmp(*argv, "-m") == 0) {
+	    manual_mkey = TRUE;
+	    global_params.mkey_from_kbd = 1;
+	    global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+       } else if (cmd_lookup(*argv) != NULL) {
+	    if (cmd_argv[0] == NULL)
+		 cmd_argv[0] = *argv;
+	    else
+		 usage();
+       } else {
+	    cmd_argv[cmd_argc++] = *argv;
+       }
+       argv++; argc--;
+    }
+
+    if (cmd_argv[0] == NULL)
+	 usage();
+    
+    if( !util_context->default_realm )
+    {
+	char *temp = NULL;
+	retval = krb5_get_default_realm(util_context, &temp);
+	if( retval )
+	{
+	    com_err (progname, retval, "while getting default realm");
+	    exit(1);
+	}
+	util_context->default_realm = temp;
+    }
+
+    retval = kadm5_get_config_params(util_context, 1,
+				     &global_params, &global_params);
+    if (retval) {
+	 com_err(argv[0], retval, "while retreiving configuration parameters");
+	 exit(1);
+    }
+
+    /*
+     * Dump creates files which should not be world-readable.  It is
+     * easiest to do a single umask call here.
+     */
+    (void) umask(077);
+
+    master_keyblock.enctype = global_params.enctype;
+    if ((master_keyblock.enctype != ENCTYPE_UNKNOWN) &&
+	(!krb5_c_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]);
+    if (cmd->opendb && open_db_and_mkey())
+	 return exit_status;
+
+    (*cmd->func)(cmd_argc, cmd_argv);
+
+    if( db_name_tmp )
+	free( db_name_tmp );
+
+    if( db5util_db_args )
+	free(db5util_db_args);
+
+    kadm5_free_config_params(util_context, &global_params);
+    krb5_free_context(util_context);
+    return exit_status;
+}
+
+#if 0
+/*
+ * This function is no longer used in kdb5_util (and it would no
+ * longer work, anyway).
+ */
+void set_dbname(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+
+    if (argc < 3) {
+	com_err(argv[0], 0, "Too few arguments");
+	com_err(argv[0], 0, "Usage: %s dbpathname realmname", argv[0]);
+	exit_status++;
+	return;
+    }
+    if (dbactive) {
+	if ((retval = krb5_db_fini(util_context)) && retval!= KRB5_KDB_DBNOTINITED) {
+	    com_err(argv[0], retval, "while closing previous database");
+	    exit_status++;
+	    return;
+	}
+	if (valid_master_key) {
+	    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;
+    }
+
+    (void) set_dbname_help(argv[0], argv[1]);
+    return;
+}
+#endif
+
+/*
+ * open_db_and_mkey: Opens the KDC and policy database, and sets the
+ * global master_* variables.  Sets dbactive to TRUE if the databases
+ * are opened, and valid_master_key to 1 if the global master
+ * variables are set properly.  Returns 0 on success, and 1 on
+ * failure, but it is not considered a failure if the master key
+ * cannot be fetched (the master key stash file may not exist when the
+ * program is run).
+ */
+static int open_db_and_mkey()
+{
+    krb5_error_code retval;
+    int nentries;
+    krb5_boolean more;
+    krb5_data scratch, pwd, seed;
+
+    dbactive = FALSE;
+    valid_master_key = 0;
+
+    if ((retval = krb5_db_open(util_context, db5util_db_args, 
+			       KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) {
+	com_err(progname, retval, "while initializing database");
+	exit_status++;
+	return(1);
+    }
+
+   /* assemble & parse the master key name */
+
+    if ((retval = krb5_db_setup_mkey_name(util_context,
+					  global_params.mkey_name,
+					  global_params.realm, 
+					  0, &master_princ))) {
+	com_err(progname, retval, "while setting up master key name");
+	exit_status++;
+	return(1);
+    }
+    nentries = 1;
+    if ((retval = krb5_db_get_principal(util_context, master_princ, 
+					&master_entry, &nentries, &more))) {
+	com_err(progname, retval, "while retrieving master entry");
+	exit_status++;
+	(void) krb5_db_fini(util_context);
+	return(1);
+    } else if (more) {
+	com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
+		"while retrieving master entry");
+	exit_status++;
+	(void) krb5_db_fini(util_context);
+	return(1);
+    } else if (!nentries) {
+	com_err(progname, KRB5_KDB_NOENTRY, "while retrieving master entry");
+	exit_status++;
+	(void) krb5_db_fini(util_context);
+	return(1);
+    }
+
+    krb5_db_free_principal(util_context, &master_entry, nentries);
+
+    /* the databases are now open, and the master principal exists */
+    dbactive = TRUE;
+    
+    if (mkey_password) {
+	pwd.data = mkey_password;
+	pwd.length = strlen(mkey_password);
+	retval = krb5_principal2salt(util_context, master_princ, &scratch);
+	if (retval) {
+	    com_err(progname, retval, "while calculated master key salt");
+	    return(1);
+	}
+
+	/* If no encryption type is set, use the default */
+	if (master_keyblock.enctype == ENCTYPE_UNKNOWN) {
+	    master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
+	    if (!krb5_c_valid_enctype(master_keyblock.enctype))
+		com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
+			"while setting up enctype %d",
+			master_keyblock.enctype);
+	}
+
+	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");
+	    return(1);
+	}
+	free(scratch.data);
+	mkey_password = 0;
+    } else if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 
+					    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");
+	exit_status++;
+	return(0);
+    }
+    if ((retval = krb5_db_verify_master_key(util_context, master_princ, 
+					    &master_keyblock))) {
+	com_err(progname, retval, "while verifying master key");
+	exit_status++;
+	krb5_free_keyblock_contents(util_context, &master_keyblock);
+	return(1);
+    }
+
+    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++;
+	memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+	krb5_free_keyblock_contents(util_context, &master_keyblock);
+	return(1);
+    }
+
+    valid_master_key = 1;
+    dbactive = TRUE;
+    return 0;
+}
+
+#ifdef HAVE_GETCWD
+#undef getwd
+#endif
+
+int 
+quit()
+{
+    krb5_error_code retval;
+    static krb5_boolean finished = 0;
+
+    if (finished)
+	return 0;
+    retval = krb5_db_fini(util_context);
+    memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+    finished = TRUE;
+    if (retval && retval != KRB5_KDB_DBNOTINITED) {
+	com_err(progname, retval, "while closing database");
+	exit_status++;
+	return 1;
+    }
+    return 0;
+}
+
+static void
+add_random_key(argc, argv)
+    int argc;
+    char **argv;
+{
+    krb5_error_code ret;
+    krb5_principal princ;
+    krb5_db_entry dbent;
+    int n;
+    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);
+	exit_status++;
+	return;
+    }
+    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);
+	exit_status++;
+	return;
+    }
+    if (n != 1) {
+	fprintf(stderr, "principal %s not found\n", pr_str);
+	exit_status++;
+	return;
+    }
+    if (more) {
+	fprintf(stderr, "principal %s not unique\n", pr_str);
+	krb5_db_free_principal(util_context, &dbent, 1);
+	exit_status++;
+	return;
+    }
+    ret = krb5_string_to_keysalts(ks_str,
+				  ", \t", ":.-", 0,
+				  &keysalts,
+				  &num_keysalts);
+    if (ret) {
+	com_err(me, ret, "while parsing keysalts %s", ks_str);
+	exit_status++;
+	return;
+    }
+    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_db_free_principal(util_context, &dbent, 1);
+	exit_status++;
+	return;
+    }
+    dbent.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+    ret = krb5_timeofday(util_context, &now);
+    if (ret) {
+	com_err(me, ret, "while getting time");
+	krb5_db_free_principal(util_context, &dbent, 1);
+	exit_status++;
+	return;
+    }
+    ret = krb5_dbe_update_last_pwd_change(util_context, &dbent, now);
+    if (ret) {
+	com_err(me, ret, "while setting changetime");
+	krb5_db_free_principal(util_context, &dbent, 1);
+	exit_status++;
+	return;
+    }
+    ret = krb5_db_put_principal(util_context, &dbent, &n);
+    krb5_db_free_principal(util_context, &dbent, 1);
+    if (ret) {
+	com_err(me, ret, "while saving principal %s", pr_str);
+	exit_status++;
+	return;
+    }
+    printf("%s changed\n", pr_str);
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/kdb5_util.h b/krb5-1-6/src/kadmin/dbutil/kdb5_util.h
new file mode 100644
index 000000000..90b7b43ef
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/kdb5_util.h
@@ -0,0 +1,88 @@
+/*
+ * admin/edit/kdb5_edit.h
+ *
+ * Copyright 1992 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#define REALM_SEP	'@'
+#define REALM_SEP_STR	"@"
+
+extern char *progname;
+extern char *Err_no_database;
+#ifndef V4_DECLARES_STATIC
+extern krb5_keyblock master_keyblock;
+extern krb5_principal master_princ;
+#endif
+extern krb5_boolean dbactive;
+extern int exit_status;
+extern krb5_context util_context;
+extern kadm5_config_params global_params;
+extern int valid_master_key;
+extern krb5_db_entry master_db;
+extern char **db5util_db_args;
+extern int    db5util_db_args_size;
+extern int add_db_arg(char *arg);
+
+extern void usage(void);
+
+extern void add_key 
+	(char const *, char const *, 
+		   krb5_const_principal, const krb5_keyblock *, 
+		   krb5_kvno, krb5_keysalt *);
+extern int set_dbname_help
+	(char *, char *);
+
+extern char *kdb5_util_Init (int, char **);
+
+extern int quit (void);
+
+extern int check_for_match
+	(char *, int, krb5_db_entry *, int, int);
+
+extern void parse_token
+	(char *, int *, int *, char *);
+
+extern int create_db_entry (krb5_principal, krb5_db_entry *);
+
+extern int kadm5_create_magic_princs (kadm5_config_params *params,
+						krb5_context context);
+
+extern int process_ov_principal (char *fname, krb5_context kcontext, 
+					   FILE *filep, int verbose, 
+					   int *linenop);
+
+extern void load_db (int argc, char **argv);
+extern void dump_db (int argc, char **argv);
+extern void load_v4db (int argc, char **argv);
+extern void dump_v4db (int argc, char **argv);
+extern void kdb5_create (int argc, char **argv);
+extern void kdb5_destroy (int argc, char **argv);
+extern void kdb5_stash (int argc, char **argv);
+
+extern void update_ok_file (char *file_name);
+
+extern int kadm5_create (kadm5_config_params *params);
+
+void usage (void);
+
diff --git a/krb5-1-6/src/kadmin/dbutil/loadv4.c b/krb5-1-6/src/kadmin/dbutil/loadv4.c
new file mode 100644
index 000000000..6149e81d8
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/loadv4.c
@@ -0,0 +1,981 @@
+/*
+ * kadmin/dbutil/loadv4.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Generate (from scratch) a Kerberos V5 KDC database, filling it in with the
+ * 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 "k5-int.h"
+#include "com_err.h"
+
+#include <des.h>
+#include <krb.h>
+#include <krb_db.h>
+/* MKEYFILE is now defined in kdc.h */
+#include <kdc.h>
+
+static C_Block master_key;
+static Key_schedule master_key_schedule;
+
+static char *v4_mkeyfile = "/.k";
+
+#include <kadm5/admin.h>
+#include <stdio.h>
+/* Define to make certain blocks private */
+#define V4_DECLARES_STATIC
+#include "kdb5_util.h"
+#include "kadm5/adb.h"                  /* osa_adb_create_policy_db */
+#include <netinet/in.h>			/* ntohl */
+
+#define PROGNAME argv[0]
+
+enum ap_op {
+    NULL_KEY,				/* setup null keys */
+    MASTER_KEY,				/* use master key as new key */
+    RANDOM_KEY				/* choose a random key */
+};
+
+struct realm_info {
+    krb5_deltat max_life;
+    krb5_deltat max_rlife;
+    krb5_timestamp expiration;
+    krb5_flags flags;
+    krb5_keyblock *key;
+};
+
+static struct realm_info rblock = { /* XXX */
+    KRB5_KDB_MAX_LIFE,
+    KRB5_KDB_MAX_RLIFE,
+    KRB5_KDB_EXPIRATION,
+    KRB5_KDB_DEF_FLAGS,
+    0
+};
+
+static int verbose = 0;
+
+static int shortlife = 0;
+
+static krb5_error_code add_principal 
+		  (krb5_context,
+		   krb5_principal, 
+		   enum ap_op,
+		   struct realm_info *);
+
+static int v4init (char *, int, char *);
+static krb5_error_code enter_in_v5_db (krb5_context,
+				       char *, Principal *);
+static krb5_error_code process_v4_dump (krb5_context, char *,
+					char *, long);
+static krb5_error_code v4_dump_find_default (krb5_context, char *,
+					     char *, long *);
+static krb5_error_code fixup_database (krb5_context, char *);
+	
+static int create_local_tgt = 0;
+
+static krb5_keyblock master_keyblock;
+static krb5_principal master_princ;
+
+static krb5_data tgt_princ_entries[] = {
+	{0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
+	{0, 0, 0} };
+
+static krb5_data db_creator_entries[] = {
+	{0, sizeof("db_creation")-1, "db_creation"} };
+
+/* XXX knows about contents of krb5_principal, and that tgt names
+ are of form TGT/REALM@REALM */
+static krb5_principal_data tgt_princ = {
+        0,					/* magic number */
+	{0, 0, 0},				/* krb5_data realm */
+	tgt_princ_entries,			/* krb5_data *data */
+	2,					/* int length */
+	KRB5_NT_SRV_INST			/* int type */
+};
+
+static krb5_principal_data db_create_princ = {
+        0,					/* magic number */
+	{0, 0, 0},				/* krb5_data realm */
+	db_creator_entries,			/* krb5_data *data */
+	1,					/* int length */
+	KRB5_NT_SRV_INST			/* int type */
+};
+
+
+void
+load_v4db(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    /* The kdb library will default to this, but it is convenient to
+       make it explicit (error reporting and temporary filename generation
+       use it).  */
+    char *dbname = DEFAULT_KDB_FILE;
+    char *v4dumpfile = 0;
+    char *realm = 0;
+    char *mkey_name = 0;
+    char *mkey_fullname;
+    char *defrealm;
+    int v4manual = 0;
+    krb5_boolean read_mkey = 0;
+    int tempdb = 0;
+    char *tempdbname;
+    krb5_context context;
+    char *stash_file = (char *) NULL;
+    int	persist, op_ind;
+    kadm5_config_params newparams;
+    extern kadm5_config_params global_params;
+    long exp_time = 0;
+    krb5_int32 crflags = KRB5_KDB_CREATE_BTREE;
+    krb5_data seed;
+
+    retval = kadm5_init_krb5_context(&context);
+    if (retval) {
+	fprintf(stderr, "%s: Could not initialize krb5 context.\n", PROGNAME);
+	return;
+    }
+
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+
+    persist = 1;
+    op_ind = 1;
+    while (persist && (op_ind < argc)) {
+	if (!strcmp(argv[op_ind], "-T")) {
+	    create_local_tgt = 1;
+	}
+	else if (!strcmp(argv[op_ind], "-t")) {
+	    tempdb = 1;
+	}
+	else if (!strcmp(argv[op_ind], "-K")) {
+	    read_mkey = 1;
+	}
+	else if (!strcmp(argv[op_ind], "-v")) {
+	    verbose = 1;
+	}
+	else if (!strcmp(argv[op_ind], "-n")) {
+	    v4manual++;
+	} 
+	else if (!strcmp(argv[op_ind], "-S")) {
+	    shortlife++;
+	}
+	else if (!strcmp(argv[op_ind], "-s")) {
+	    if ((argc - op_ind) >= 1) {
+	        v4_mkeyfile = argv[op_ind+1];
+		op_ind++;
+	    } else {
+		usage();
+	    }
+	}
+	else if (!strcmp(argv[op_ind], "-h")) {
+	    crflags = KRB5_KDB_CREATE_HASH;
+	}
+	else if ((argc - op_ind) >= 1) {
+	    v4dumpfile = argv[op_ind];
+	    op_ind++;
+	}
+	else
+	    usage();
+	op_ind++;
+    }
+
+    realm = global_params.realm;
+    dbname = global_params.dbname;
+    mkey_name = global_params.mkey_name;
+    master_keyblock.enctype = global_params.enctype;
+    if (global_params.stash_file)
+	    stash_file = strdup(global_params.stash_file);
+    rblock.max_life = global_params.max_life;
+    rblock.max_rlife = global_params.max_rlife;
+    rblock.expiration = global_params.expiration;
+    rblock.flags = global_params.flags;
+
+    if (!v4dumpfile) {
+	usage();
+	krb5_free_context(context);
+	return;
+    }
+
+    if (!krb5_c_valid_enctype(master_keyblock.enctype)) {
+	com_err(PROGNAME, KRB5_PROG_KEYTYPE_NOSUPP,
+		"while setting up enctype %d", master_keyblock.enctype);
+	krb5_free_context(context);
+	return;
+    }
+
+    /* If the user has not requested locking, don't modify an existing database. */
+    if (! tempdb) {
+	retval = krb5_db_set_name(context, dbname);
+	if (retval != ENOENT) {
+	    fprintf(stderr,
+		    "%s: The v5 database appears to already exist.\n",
+		    PROGNAME);
+	    krb5_free_context(context);
+	    return;
+	}
+	tempdbname = dbname;
+    } else {
+	size_t dbnamelen = strlen(dbname);
+	tempdbname = malloc(dbnamelen + 2);
+	if (tempdbname == 0) {
+	    com_err(PROGNAME, ENOMEM, "allocating temporary filename");
+	    krb5_free_context(context);
+	    return;
+	}
+	strcpy(tempdbname, dbname);
+	tempdbname[dbnamelen] = '~';
+	tempdbname[dbnamelen+1] = 0;
+	(void) krb5_db_destroy(context, tempdbname);
+    }
+	
+
+    if (!realm) {
+	retval = krb5_get_default_realm(context, &defrealm);
+	if (retval) {
+	    com_err(PROGNAME, retval, "while retrieving default realm name");
+	    krb5_free_context(context);
+	    return;
+	}	    
+	realm = defrealm;
+    }
+
+    /* assemble & parse the master key name */
+    
+    retval = krb5_db_setup_mkey_name(context, mkey_name, realm,
+				     &mkey_fullname, &master_princ);
+    if (retval) {
+	com_err(PROGNAME, retval, "while setting up master key name");
+	krb5_free_context(context);
+	return;
+    }
+
+    krb5_princ_set_realm_data(context, &db_create_princ, realm);
+    krb5_princ_set_realm_length(context, &db_create_princ, strlen(realm));
+    krb5_princ_set_realm_data(context, &tgt_princ, realm);
+    krb5_princ_set_realm_length(context, &tgt_princ, strlen(realm));
+    krb5_princ_component(context, &tgt_princ,1)->data = realm;
+    krb5_princ_component(context, &tgt_princ,1)->length = strlen(realm);
+
+    printf("Initializing database '%s' for realm '%s',\n\
+master key name '%s'\n",
+	   dbname, realm, mkey_fullname);
+
+    if (read_mkey) {
+	puts("You will be prompted for the version 5 database Master Password.");
+	puts("It is important that you NOT FORGET this password.");
+	fflush(stdout);
+    }
+
+
+    retval = krb5_db_fetch_mkey(context, master_princ,
+				master_keyblock.enctype,
+				read_mkey, read_mkey, stash_file, 0, 
+				&master_keyblock);
+    if (retval) {
+	com_err(PROGNAME, retval, "while reading master key");
+	krb5_free_context(context);
+	return;
+    }
+
+    rblock.key = &master_keyblock;
+
+    seed.length = master_keyblock.length;
+    seed.data = master_keyblock.contents;
+
+    retval = krb5_c_random_seed(context, &seed);
+    if (retval) {
+	com_err(PROGNAME, retval, "while initializing random key generator");
+	krb5_free_context(context);
+	return;
+    }
+
+    retval = krb5_db_create(context, tempdbname, crflags);
+    if (retval) {
+	com_err(PROGNAME, retval, "while creating %sdatabase '%s'",
+		tempdb ? "temporary " : "", tempdbname);
+	krb5_free_context(context);
+	return;
+    }
+
+    retval = krb5_db_set_name(context, tempdbname);
+    if (retval) {
+	(void) krb5_db_destroy(context, tempdbname);
+        com_err(PROGNAME, retval, "while setting active database to '%s'",
+                tempdbname);
+	krb5_free_context(context);
+        return;
+    }
+    if (v4init(PROGNAME, v4manual, v4dumpfile)) {
+	(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_db_destroy(context, tempdbname);
+	com_err(PROGNAME, retval, "while initializing the database '%s'",
+		tempdbname);
+	krb5_free_context(context);
+	return;
+    }
+
+    retval = add_principal(context, master_princ, MASTER_KEY, &rblock);
+    if (retval) {
+	(void) krb5_db_fini(context);
+	(void) krb5_db_destroy(context, tempdbname);
+	com_err(PROGNAME, retval, "while adding K/M to the database");
+	krb5_free_context(context);
+	return;
+    }
+
+    if (create_local_tgt &&
+	(retval = add_principal(context, &tgt_princ, RANDOM_KEY, &rblock))) {
+	(void) krb5_db_fini(context);
+	(void) krb5_db_destroy(context, tempdbname);
+	com_err(PROGNAME, retval, "while adding TGT service to the database");
+	krb5_free_context(context);
+	return;
+    }
+
+    retval = v4_dump_find_default(context, v4dumpfile, realm, &exp_time);
+    if (retval) {
+        com_err(PROGNAME, retval, "warning: default entry not found");
+    }
+
+    retval = process_v4_dump(context, v4dumpfile, realm, exp_time);
+    putchar('\n');
+    if (retval)
+	com_err(PROGNAME, retval, "while translating entries to the database");
+    else {
+	retval = fixup_database(context, realm);
+    }
+    
+    /* clean up; rename temporary database if there were no errors */
+    if (retval == 0) {
+	retval = krb5_db_fini (context);
+	if (retval)
+	    com_err(PROGNAME, retval, "while shutting down database");
+	else if (tempdb && (retval = krb5_db_rename(context, tempdbname,
+						    dbname)))
+	    com_err(PROGNAME, retval, "while renaming temporary database");
+    } else {
+	(void) krb5_db_fini (context);
+	if (tempdb)
+	    (void) krb5_db_destroy (context, tempdbname);
+    }
+    memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+
+    /*
+     * Cons up config params for new database; using the global_params
+     * is just fine.
+     */
+    newparams = global_params;
+
+    /*
+     * Always create the policy db, even if we are not loading a dump
+     * file with policy info.
+     */
+    if (!tempdb && (retval = osa_adb_create_policy_db(&newparams))) {
+	com_err(PROGNAME, retval, "while creating policy database");
+	kadm5_free_config_params(context, &newparams);
+	krb5_free_context(context);
+	return;
+    }
+    /*
+     * Create the magic principals in the database.
+     */
+    retval = kadm5_create_magic_princs(&newparams, context);
+    if (retval) {
+	com_err(PROGNAME, retval, "while creating KADM5 principals");
+	krb5_free_context(context);
+	return;
+    }
+    
+    krb5_free_context(context);
+    return;
+}
+
+static int
+v4init(pname, manual, dumpfile)
+char *pname;
+int manual;
+char *dumpfile;
+{
+    int fd;
+    int ok = 0;
+
+    if (!manual) {
+	fd = open(v4_mkeyfile, O_RDONLY, 0600);
+	if (fd >= 0) {
+	    if (read(fd, master_key, sizeof(master_key)) == sizeof(master_key))
+		ok = 1;
+	    close(fd);
+	}
+    }
+    if (!ok) {
+	des_read_password(&master_key, "V4 Kerberos master key", 0);
+	printf("\n");
+    }
+    key_sched(master_key, master_key_schedule);
+    return 0;
+}
+
+static krb5_error_code
+enter_in_v5_db(context, realm, princ)
+krb5_context context;
+char *realm;
+Principal *princ;
+{
+    krb5_db_entry entry;
+    krb5_error_code retval;
+    krb5_keyblock v4v5key;
+    int nentries = 1;
+    des_cblock v4key;
+    char *name;
+    krb5_timestamp	mod_time;
+    krb5_principal	mod_princ;
+    krb5_keysalt	keysalt;
+
+    /* don't convert local TGT if we created a TGT already.... */
+    if (create_local_tgt && !strcmp(princ->name, "krbtgt") &&
+	!strcmp(princ->instance, realm)) {
+	    if (verbose)
+		    printf("\nignoring local TGT: '%s.%s' ...",
+			   princ->name, princ->instance);
+	    return 0;
+    }
+    if (!strcmp(princ->name, KERB_M_NAME) &&
+	!strcmp(princ->instance, KERB_M_INST)) {
+	des_cblock key_from_db;
+	int val;
+
+	/* here's our chance to verify the master key */
+	/*
+	 * use the master key to decrypt the key in the db, had better
+	 * be the same! 
+	 */
+	memcpy(key_from_db, (char *)&princ->key_low, 4);
+	memcpy(((char *) key_from_db) + 4, (char *)&princ->key_high, 4);
+	pcbc_encrypt((C_Block *) &key_from_db,
+		     (C_Block *) &key_from_db,
+		     (long) sizeof(C_Block),
+		     master_key_schedule,
+		     (C_Block *) master_key,
+		     DECRYPT);
+	val = memcmp((char *) master_key, (char *) key_from_db,
+		     sizeof(master_key));
+	memset((char *)key_from_db, 0, sizeof(key_from_db));
+	if (val) {
+	    return KRB5_KDB_BADMASTERKEY;
+	}
+	if (verbose)
+	    printf("\nignoring '%s.%s' ...", princ->name, princ->instance);
+	return 0;
+    }
+    memset((char *) &entry, 0, sizeof(entry));
+    retval = krb5_425_conv_principal(context, princ->name, princ->instance,
+				     realm, &entry.princ);
+    if (retval)
+	return retval;
+    if (verbose) {
+	retval = krb5_unparse_name(context, entry.princ, &name);
+	if (retval)
+	   name = strdup("<not unparsable name!>");
+	if (verbose)
+	    printf("\ntranslating %s...", name);
+	free(name);
+    }
+
+    retval = krb5_build_principal(context, &mod_princ,
+				  strlen(realm), realm, princ->mod_name,
+				  princ->mod_instance[0] ? 
+				  princ->mod_instance : NULL,
+				  NULL);
+    if (retval) {
+	krb5_free_principal(context, entry.princ);
+	return retval;
+    }
+    mod_time = princ->mod_date;
+
+    if (!shortlife)
+	entry.max_life = krb_life_to_time(0, princ->max_life);
+    else
+	entry.max_life = princ->max_life * 60 * 5;
+    entry.max_renewable_life = rblock.max_rlife;
+    entry.len = KRB5_KDB_V1_BASE_LENGTH;
+    entry.expiration = princ->exp_date;
+    entry.attributes = rblock.flags;	/* XXX is there a way to convert
+					   the old attrs? */
+
+    memcpy((char *)v4key, (char *)&(princ->key_low), 4);
+    memcpy((char *) (((char *) v4key) + 4), (char *)&(princ->key_high), 4);
+    pcbc_encrypt((C_Block *) &v4key,
+		 (C_Block *) &v4key,
+		 (long) sizeof(C_Block),
+		 master_key_schedule,
+		 (C_Block *) master_key,
+		 DECRYPT);
+
+    v4v5key.magic = KV5M_KEYBLOCK;
+    v4v5key.contents = (krb5_octet *)v4key;
+    v4v5key.enctype = ENCTYPE_DES_CBC_CRC;
+    v4v5key.length = sizeof(v4key);
+
+    retval = krb5_dbe_create_key_data(context, &entry);
+    if (retval) {
+	krb5_free_principal(context, entry.princ);
+	krb5_free_principal(context, mod_princ);
+	return retval;
+    }
+
+    keysalt.type = KRB5_KDB_SALTTYPE_V4;
+    keysalt.data.length = 0;
+    keysalt.data.data = (char *) NULL;
+    retval = krb5_dbekd_encrypt_key_data(context, rblock.key,
+					 &v4v5key, &keysalt, 
+					 princ->key_version,
+					 &entry.key_data[0]);
+    if (!retval)
+	retval = krb5_dbe_update_mod_princ_data(context, &entry,
+						mod_time, mod_princ);
+    if (!retval)
+        retval = krb5_dbe_update_last_pwd_change(context, &entry, mod_time);
+
+    if (retval) {
+	krb5_db_free_principal(context, &entry, 1);
+	krb5_free_principal(context, mod_princ);
+	return retval;
+    }
+    memset((char *)v4key, 0, sizeof(v4key));
+
+    retval = krb5_db_put_principal(context, &entry, &nentries);
+
+    if (!retval && !strcmp(princ->name, "krbtgt") &&
+	strcmp(princ->instance, realm) && princ->instance[0]) {
+	    krb5_free_principal(context, entry.princ);
+	    retval = krb5_build_principal(context, &entry.princ,
+					  strlen(princ->instance),
+					  princ->instance,
+					  "krbtgt", realm, NULL);
+	    if (retval)
+		    return retval;
+	    retval = krb5_db_put_principal(context, &entry, &nentries);
+    }
+
+    krb5_db_free_principal(context, &entry, 1);
+    krb5_free_principal(context, mod_princ);
+
+    return retval;
+}
+
+static krb5_error_code
+add_principal(context, princ, op, pblock)
+krb5_context context;
+krb5_principal princ;
+enum ap_op op;
+struct realm_info *pblock;
+{
+    krb5_db_entry entry;
+    krb5_error_code retval;
+    krb5_keyblock rkey;
+    int nentries = 1;
+    krb5_timestamp mod_time;
+
+    memset((char *) &entry, 0, sizeof(entry));
+    retval = krb5_copy_principal(context, princ, &entry.princ);
+    if (retval)
+	return(retval);
+    entry.max_life = pblock->max_life;
+    entry.max_renewable_life = pblock->max_rlife;
+    entry.len = KRB5_KDB_V1_BASE_LENGTH;
+    entry.expiration = pblock->expiration;
+    
+    retval = krb5_timeofday(context, &mod_time);
+    if (retval) {
+	krb5_db_free_principal(context, &entry, 1);
+	return retval;
+    }
+    entry.attributes = pblock->flags;
+
+    retval = krb5_dbe_create_key_data(context, &entry);
+    if (retval) {
+	krb5_db_free_principal(context, &entry, 1);
+	return(retval);
+    }
+
+    switch (op) {
+    case MASTER_KEY:
+	entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+	retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
+					     &master_keyblock,
+					     (krb5_keysalt *) NULL, 1,
+					     &entry.key_data[0]);
+	if (retval) {
+	    krb5_db_free_principal(context, &entry, 1);
+	    return retval;
+	}
+	break;
+    case RANDOM_KEY:
+	retval = krb5_c_make_random_key(context, pblock->key->enctype,
+					&rkey);
+	if (retval) {
+	    krb5_db_free_principal(context, &entry, 1);
+	    return retval;
+	}
+	retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
+					     &rkey, (krb5_keysalt *) NULL, 
+					     1, &entry.key_data[0]);
+	if (retval) {
+	    krb5_db_free_principal(context, &entry, 1);
+	    return(retval);
+	}
+	krb5_free_keyblock_contents(context, &rkey);
+	break;
+    case NULL_KEY:
+	return EOPNOTSUPP;
+    default:
+	break;
+    }
+
+    retval = krb5_dbe_update_mod_princ_data(context, &entry,
+					    mod_time, &db_create_princ);
+    if (!retval)
+	retval = krb5_db_put_principal(context, &entry, &nentries);
+    krb5_db_free_principal(context, &entry, 1);
+    return retval;
+}
+
+/*
+ * Convert a struct tm * to a UNIX time.
+ */
+
+
+#define daysinyear(y) (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
+
+#define SECSPERDAY 24*60*60
+#define SECSPERHOUR 60*60
+#define SECSPERMIN 60
+
+static int cumdays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
+			     365};
+
+static int leapyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static int nonleapyear[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static long
+maketime(tp, local)
+register struct tm *tp;
+int local;
+{
+    register long retval;
+    int foo;
+    int *marray;
+
+    if (tp->tm_mon < 0 || tp->tm_mon > 11 ||
+	tp->tm_hour < 0 || tp->tm_hour > 23 ||
+	tp->tm_min < 0 || tp->tm_min > 59 ||
+	tp->tm_sec < 0 || tp->tm_sec > 59) /* out of range */
+	return 0;
+
+    retval = 0;
+    if (tp->tm_year < 1900)
+	foo = tp->tm_year + 1900;
+    else
+	foo = tp->tm_year;
+
+    if (foo < 1901 || foo > 2038)	/* year is too small/large */
+	return 0;
+
+    if (daysinyear(foo) == 366) {
+	if (tp->tm_mon > 1)
+	    retval+= SECSPERDAY;	/* add leap day */
+	marray = leapyear;
+    } else
+	marray = nonleapyear;
+
+    if (tp->tm_mday < 0 || tp->tm_mday > marray[tp->tm_mon])
+	return 0;			/* out of range */
+
+    while (--foo >= 1970)
+	retval += daysinyear(foo) * SECSPERDAY;
+
+    retval += cumdays[tp->tm_mon] * SECSPERDAY;
+    retval += (tp->tm_mday-1) * SECSPERDAY;
+    retval += tp->tm_hour * SECSPERHOUR + tp->tm_min * SECSPERMIN + tp->tm_sec;
+
+    if (local) {
+	/* need to use local time, so we retrieve timezone info */
+	struct timezone tz;
+	struct timeval tv;
+	if (gettimeofday(&tv, &tz) < 0) {
+	    /* some error--give up? */
+	    return(retval);
+	}
+	retval += tz.tz_minuteswest * SECSPERMIN;
+    }
+    return(retval);
+}
+
+static long
+time_explode(cp)
+register char *cp;
+{
+    char wbuf[5];
+    struct tm tp;
+    int local;
+
+    memset((char *)&tp, 0, sizeof(tp));
+    
+    if (strlen(cp) > 10) {		/* new format */
+	(void) strncpy(wbuf, cp, 4);
+	wbuf[4] = 0;
+	tp.tm_year = atoi(wbuf);
+	cp += 4;			/* step over the year */
+	local = 0;			/* GMT */
+    } else {				/* old format: local time, 
+					   year is 2 digits, assuming 19xx */
+	wbuf[0] = *cp++;
+	wbuf[1] = *cp++;
+	wbuf[2] = 0;
+	tp.tm_year = 1900 + atoi(wbuf);
+	local = 1;			/* local */
+    }
+
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    wbuf[2] = 0;
+    tp.tm_mon = atoi(wbuf)-1;
+
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    tp.tm_mday = atoi(wbuf);
+    
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    tp.tm_hour = atoi(wbuf);
+    
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    tp.tm_min = atoi(wbuf);
+
+
+    return(maketime(&tp, local));
+}
+
+static krb5_error_code
+process_v4_dump(context, dumpfile, realm, default_exp_time)
+krb5_context context;
+char *dumpfile;
+char *realm;
+long default_exp_time;
+{
+    krb5_error_code retval;
+    FILE *input_file;
+    Principal aprinc;
+    char    exp_date_str[50];
+    char    mod_date_str[50];
+    int     temp1, temp2, temp3;
+
+    input_file = fopen(dumpfile, "r");
+    if (!input_file)
+	return errno;
+
+    for (;;) {			/* explicit break on eof from fscanf */
+	int nread;
+
+	memset((char *)&aprinc, 0, sizeof(aprinc));
+	nread = fscanf(input_file,
+		       "%s %s %d %d %d %hd %lx %lx %s %s %s %s\n",
+		       aprinc.name,
+		       aprinc.instance,
+		       &temp1,
+		       &temp2,
+		       &temp3,
+		       &aprinc.attributes,
+		       &aprinc.key_low,
+		       &aprinc.key_high,
+		       exp_date_str,
+		       mod_date_str,
+		       aprinc.mod_name,
+		       aprinc.mod_instance);
+	if (nread != 12) {
+	    retval = nread == EOF ? 0 : KRB5_KDB_DB_CORRUPT;
+	    break;
+	}
+	aprinc.key_low = ntohl (aprinc.key_low);
+	aprinc.key_high = ntohl (aprinc.key_high);
+	aprinc.max_life = (unsigned char) temp1;
+	aprinc.kdc_key_ver = (unsigned char) temp2;
+	aprinc.key_version = (unsigned char) temp3;
+	aprinc.exp_date = time_explode(exp_date_str);
+	if (aprinc.exp_date == default_exp_time)
+	    aprinc.exp_date = 0;
+	aprinc.mod_date = time_explode(mod_date_str);
+	if (aprinc.instance[0] == '*')
+	    aprinc.instance[0] = '\0';
+	if (aprinc.mod_name[0] == '*')
+	    aprinc.mod_name[0] = '\0';
+	if (aprinc.mod_instance[0] == '*')
+	    aprinc.mod_instance[0] = '\0';
+	retval = enter_in_v5_db(context, realm, &aprinc);
+	if (retval)
+	    break;
+    }
+    (void) fclose(input_file);
+    return retval;
+}
+
+static krb5_error_code
+v4_dump_find_default(context, dumpfile, realm, exptime)
+krb5_context context;
+char *dumpfile;
+char *realm;
+long *exptime;
+{
+    krb5_error_code retval = 0;
+    FILE *input_file;
+    Principal aprinc;
+    char    exp_date_str[50];
+    char    mod_date_str[50];
+    int     temp1, temp2, temp3;
+    long foundtime, guess1, guess2;
+
+    /* kdb_init is usually the only thing to touch the time in the 
+       default entry, and everything else just copies that time.  If
+       the site hasn't changed it, we can assume that "never" is an
+       appropriate value for V5.  There have been two values compiled
+       in, typically:
+
+       MIT V4 had the code
+       principal.exp_date = 946702799;
+       strncpy(principal.exp_date_txt, "12/31/99", DATE_SZ);
+
+       Cygnus CNS V4 had the code
+       principal.exp_date = 946702799+((365*10+3)*24*60*60);
+       strncpy(principal.exp_date_txt, "12/31/2009", DATE_SZ);
+
+       However, the dump files only store minutes -- so these values
+       are 59 seconds high.
+
+       Other values could be added later, but in practice these are
+       likely to be the only ones. */
+
+    guess1 = 946702799-59;
+    guess2 = 946702799+((365*10+3)*24*60*60);
+
+    input_file = fopen(dumpfile, "r");
+    if (!input_file)
+	return errno;
+
+    for (;;) {			/* explicit break on eof from fscanf */
+	int nread;
+
+	memset((char *)&aprinc, 0, sizeof(aprinc));
+	nread = fscanf(input_file,
+		       "%s %s %d %d %d %hd %lx %lx %s %s %s %s\n",
+		       aprinc.name,
+		       aprinc.instance,
+		       &temp1,
+		       &temp2,
+		       &temp3,
+		       &aprinc.attributes,
+		       &aprinc.key_low,
+		       &aprinc.key_high,
+		       exp_date_str,
+		       mod_date_str,
+		       aprinc.mod_name,
+		       aprinc.mod_instance);
+	if (nread != 12) {
+	    retval = nread == EOF ? 0 : KRB5_KDB_DB_CORRUPT;
+	    break;
+	}
+	if (!strcmp(aprinc.name, "default")
+	    && !strcmp(aprinc.instance, "*")) {
+	    foundtime = time_explode(exp_date_str);
+	    if (foundtime == guess1 || foundtime == guess2)
+	        *exptime = foundtime;
+	    if (verbose) {
+	        printf("\ndefault expiration found: ");
+	        if (foundtime == guess1) {
+		    printf("MIT or pre96q1 value (1999)");
+		} else if (foundtime == guess2) {
+		    printf("Cygnus CNS post 96q1 value (2009)");
+		} else {
+		    printf("non-default start time (%ld,%s)",
+			   foundtime, exp_date_str);
+		}
+	    }
+	    break;
+	}
+    }
+    (void) fclose(input_file);
+    return retval;
+}
+
+static krb5_error_code fixup_database(context, realm)
+    krb5_context context;
+    char * realm;
+{
+    return 0;
+}
+    
+#else /* KRB5_KRB4_COMPAT */
+void
+load_v4db(argc, argv)
+	int argc;
+	char *argv[];
+{
+	printf("This version of kdb5_util does not support the V4 load command.\n");
+}
+#endif /* KRB5_KRB4_COMPAT */
diff --git a/krb5-1-6/src/kadmin/dbutil/nstrtok.h b/krb5-1-6/src/kadmin/dbutil/nstrtok.h
new file mode 100644
index 000000000..f7f0d4a69
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/nstrtok.h
@@ -0,0 +1,3 @@
+/* Prototype for nstrtok */
+char *nstrtok(char *, const char *delim);
+
diff --git a/krb5-1-6/src/kadmin/dbutil/ovload.c b/krb5-1-6/src/kadmin/dbutil/ovload.c
new file mode 100644
index 000000000..b5bff3062
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/ovload.c
@@ -0,0 +1,213 @@
+#include    <unistd.h>
+#include    <string.h>
+#include    <stdlib.h>
+#include    "autoconf.h"
+#ifdef HAVE_MEMORY_H
+#include    <memory.h>
+#endif
+
+#include    <k5-int.h>
+#include <kadm5/admin.h>
+#include <kadm5/server_internal.h>
+#include    <kdb.h>
+#include    "import_err.h"
+#include    "kdb5_util.h"
+#include    "nstrtok.h"
+
+#define LINESIZE	32768 /* XXX */
+#define PLURAL(count)	(((count) == 1) ? error_message(IMPORT_SINGLE_RECORD) : error_message(IMPORT_PLURAL_RECORDS))
+
+static int parse_pw_hist_ent(current, hist)
+   char *current;
+   osa_pw_hist_ent *hist;
+{
+     int tmp, i, j, ret;
+     char *cp;
+
+     ret = 0;
+     hist->n_key_data = 1;
+
+     hist->key_data = (krb5_key_data *) malloc(hist->n_key_data *
+					       sizeof(krb5_key_data));
+     if (hist->key_data == NULL)
+	  return ENOMEM;
+     memset(hist->key_data, 0, sizeof(krb5_key_data)*hist->n_key_data);
+
+     for (i = 0; i < hist->n_key_data; i++) {
+	  krb5_key_data *key_data = &hist->key_data[i];
+
+	  key_data->key_data_ver = 1;
+	  
+	  if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	       com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	       ret = IMPORT_FAILED;
+	       goto done;
+	  }
+	  key_data->key_data_type[0] = atoi(cp);
+
+	  if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	       com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	       ret =  IMPORT_FAILED;
+	       goto done;
+	  }
+	  key_data->key_data_length[0] = atoi(cp);
+	  
+	  if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	       com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	       ret = IMPORT_FAILED;
+	       goto done;
+	  }
+	  if(!(key_data->key_data_contents[0] =
+	       (krb5_octet *) malloc(key_data->key_data_length[0]+1))) {
+	       ret = ENOMEM;
+	       goto done;
+	  }
+	  for(j = 0; j < key_data->key_data_length[0]; j++) {
+	       if(sscanf(cp, "%02x", &tmp) != 1) {
+		    com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+		    ret = IMPORT_FAILED;
+		    goto done;
+	       }
+	       key_data->key_data_contents[0][j] = tmp;
+	       cp = strchr(cp, ' ') + 1;
+	  }
+     }
+     
+done:
+     return ret;
+}
+
+/*
+ * Function: parse_principal
+ * 
+ * Purpose: parse principal line in db dump file
+ *
+ * Arguments:
+ * 	<return value>	0 on success, error code on failure
+ *
+ * Requires:
+ *	principal database to be opened.
+ *	nstrtok(3) to have a valid buffer in memory.
+ * 
+ * Effects:
+ *	[effects]
+ *
+ * Modifies:
+ *	[modifies]
+ * 
+ */
+int process_ov_principal(fname, kcontext, filep, verbose, linenop)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			verbose;
+    int			*linenop;
+{
+    XDR			    xdrs;
+    osa_princ_ent_t	    rec;
+    krb5_error_code	    ret;
+    krb5_tl_data	    tl_data;
+    krb5_principal	    princ;
+    krb5_db_entry	    kdb;
+    char		    *current;
+    char		    *cp;
+    int			    x, one;
+    krb5_boolean	    more;
+    char		    line[LINESIZE];
+
+    if (fgets(line, LINESIZE, filep) == (char *) NULL) {
+	 return IMPORT_BAD_FILE;
+    }
+    if((cp = nstrtok(line, "\t")) == NULL)
+	return IMPORT_BAD_FILE;
+    if((rec = (osa_princ_ent_t) malloc(sizeof(osa_princ_ent_rec))) == NULL)
+	return ENOMEM;
+    memset(rec, 0, sizeof(osa_princ_ent_rec));
+    if((ret = krb5_parse_name(kcontext, cp, &princ))) 
+	goto done;
+    krb5_unparse_name(kcontext, princ, ¤t);
+    if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	ret =  IMPORT_FAILED;
+	goto done;
+    } else {
+	if(strcmp(cp, "")) {
+	    if((rec->policy = (char *) malloc(strlen(cp)+1)) == NULL)  {
+		ret = ENOMEM;
+		goto done;
+	    }
+	    strcpy(rec->policy, cp);
+	} else rec->policy = NULL;
+    }
+    if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	ret = IMPORT_FAILED;
+	goto done;
+    }
+    rec->aux_attributes = strtol(cp, (char  **)NULL, 16);
+    if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	ret = IMPORT_FAILED;
+	goto done;
+    }
+    rec->old_key_len = atoi(cp);
+    if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	ret = IMPORT_FAILED;
+	goto done;
+    }
+    rec->old_key_next = atoi(cp);
+    if((cp = nstrtok((char *) NULL, "\t")) == NULL) {
+	com_err(NULL, IMPORT_BAD_RECORD, "%s", current);
+	ret = IMPORT_FAILED;
+	goto done;
+    }
+    rec->admin_history_kvno = atoi(cp);
+    if (! rec->old_key_len) {
+       rec->old_keys = NULL;
+    } else {
+       if(!(rec->old_keys = (osa_pw_hist_ent *)
+	    malloc(sizeof(osa_pw_hist_ent) * rec->old_key_len))) {
+	  ret = ENOMEM;
+	  goto done;
+       }
+       memset(rec->old_keys,0,
+	      sizeof(osa_pw_hist_ent) * rec->old_key_len);
+       for(x = 0; x < rec->old_key_len; x++)
+	    parse_pw_hist_ent(current, &rec->old_keys[x]);
+    }
+
+    xdralloc_create(&xdrs, XDR_ENCODE);
+    if (! xdr_osa_princ_ent_rec(&xdrs, rec)) {
+	 xdr_destroy(&xdrs);
+	 ret = KADM5_XDR_FAILURE;
+	 goto done;
+    }
+
+    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+    tl_data.tl_data_length = xdr_getpos(&xdrs);
+    tl_data.tl_data_contents = (krb5_octet *) xdralloc_getdata(&xdrs);
+
+    one = 1;
+    ret = krb5_db_get_principal(kcontext, princ, &kdb, &one, &more);
+    if (ret)
+	 goto done;
+    
+    ret = krb5_dbe_update_tl_data(kcontext, &kdb, &tl_data);
+    if (ret)
+	 goto done;
+
+    ret = krb5_db_put_principal(kcontext, &kdb, &one);
+    if (ret)
+	 goto done;
+
+    xdr_destroy(&xdrs);
+
+    (*linenop)++;
+
+done:
+    free(current);
+    krb5_free_principal(kcontext, princ);
+    osa_free_princ_ent(rec);
+    return ret;
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/string_table.c b/krb5-1-6/src/kadmin/dbutil/string_table.c
new file mode 100644
index 000000000..1caa1402e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/string_table.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ * 
+ */
+
+/* String table of messages for kadm5_create */
+
+char *str_PARSE_NAME = "while parsing admin principal name.";
+
+char *str_HISTORY_PARSE_NAME = "while parsing admin history principal name.";
+
+char *str_ADMIN_PRINC_EXISTS = "Warning! Admin principal already exists.";
+
+char *str_CHANGEPW_PRINC_EXISTS = "Warning! Changepw principal already exists.";
+
+char *str_HISTORY_PRINC_EXISTS = "Warning! Admin history principal already exists.";
+
+char *str_ADMIN_PRINC_WRONG_ATTRS = 
+    "Warning! Admin principal has incorrect attributes.\n"
+    "\tDISALLOW_TGT should be set, and max_life should be three hours.\n"
+    "\tThis program will leave them as-is, but beware!.";
+
+char *str_CHANGEPW_PRINC_WRONG_ATTRS = 
+    "Warning! Changepw principal has incorrect attributes.\n"
+    "\tDISALLOW_TGT and PW_CHANGE_SERVICE should both be set, and "
+     "max_life should be five minutes.\n"
+    "\tThis program will leave them as-is, but beware!.";
+
+char *str_HISTORY_PRINC_WRONG_ATTRS = 
+    "Warning! Admin history principal has incorrect attributes.\n"
+    "\tDISALLOW_ALL_TIX should be set.\n" 
+    "\tThis program will leave it as-is, but beware!.";
+
+char *str_CREATED_PRINC_DB =
+	"%s: Admin principal database created (or it already existed).\n"; /* whoami */
+
+char *str_CREATED_POLICY_DB =
+	"%s: Admin policy database created (or it already existed).\n"; /* whoami */
+
+char *str_RANDOM_KEY =
+	"while calling random key for %s.";  /* principal name */
+
+char *str_ENCRYPT_KEY =
+	"while calling encrypt key for %s."; /* principal name */
+
+char *str_PUT_PRINC =
+	"while storing %s in Kerberos database.";  /* principal name */
+
+char *str_CREATING_POLICY_DB = "while creating/opening admin policy database.";
+
+char *str_CLOSING_POLICY_DB = "while closing admin policy database.";
+
+char *str_CREATING_PRINC_DB = "while creating/opening admin principal database.";
+
+char *str_CLOSING_PRINC_DB = "while closing admin principal database.";
+
+char *str_CREATING_PRINC_ENTRY =
+	"while creating admin principal database entry for %s."; /* princ_name */
+
+char *str_A_PRINC = "a principal";
+
+char *str_UNPARSE_PRINC = "while unparsing principal.";
+
+char *str_CREATED_PRINC = "%s: Created %s principal.\n"; /* whoami, princ_name */
+
+char *str_INIT_KDB = "while initializing kdb.";
+
+char *str_NO_KDB = 
+"while initializing kdb.\nThe Kerberos KDC database needs to exist in /krb5.\n\
+If you haven't run kdb5_create you need to do so before running this command.";
+
+
+char *str_INIT_RANDOM_KEY = "while initializing random key generator.";
+
+char *str_TOO_MANY_ADMIN_PRINC = 
+	"while fetching admin princ. Can only have one admin principal.";
+
+char *str_TOO_MANY_CHANGEPW_PRINC = 
+	"while fetching changepw princ. Can only have one changepw principal.";
+
+char *str_TOO_MANY_HIST_PRINC = 
+	"while fetching history princ. Can only have one history principal.";
+
+char *str_WHILE_DESTROYING_ADMIN_SESSION = "while closing session with admin server and destroying tickets.";
diff --git a/krb5-1-6/src/kadmin/dbutil/string_table.h b/krb5-1-6/src/kadmin/dbutil/string_table.h
new file mode 100644
index 000000000..b89b9f1fa
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/string_table.h
@@ -0,0 +1,39 @@
+/*
+  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+  * 
+  * $Header$
+  *
+  */
+ 
+#ifndef _OVSEC_ADM_STRINGS_
+ 
+extern char *str_PARSE_NAME;
+extern char *str_HISTORY_PARSE_NAME;
+extern char *str_ADMIN_PRINC_EXISTS;
+extern char *str_CHANGEPW_PRINC_EXISTS;
+extern char *str_HISTORY_PRINC_EXISTS;
+extern char *str_ADMIN_PRINC_WRONG_ATTRS;
+extern char *str_CHANGEPW_PRINC_WRONG_ATTRS;
+extern char *str_HISTORY_PRINC_WRONG_ATTRS;
+extern char *str_CREATED_PRINC_DB;
+extern char *str_CREATED_POLICY_DB;
+extern char *str_RANDOM_KEY;
+extern char *str_ENCRYPT_KEY;
+extern char *str_PUT_PRINC;
+extern char *str_CREATING_POLICY_DB;
+extern char *str_CLOSING_POLICY_DB;
+extern char *str_CREATING_PRINC_DB;
+extern char *str_CLOSING_PRINC_DB;
+extern char *str_CREATING_PRINC_ENTRY;
+extern char *str_A_PRINC;
+extern char *str_UNPARSE_PRINC;
+extern char *str_CREATED_PRINC;
+extern char *str_INIT_KDB;
+extern char *str_NO_KDB;
+extern char *str_INIT_RANDOM_KEY;
+extern char *str_TOO_MANY_ADMIN_PRINC;
+extern char *str_TOO_MANY_CHANGEPW_PRINC;
+extern char *str_TOO_MANY_HIST_PRINC;
+extern char *str_WHILE_DESTROYING_ADMIN_SESSION;
+ 
+#endif /* _OVSEC_ADM_STRINGS_ */
diff --git a/krb5-1-6/src/kadmin/dbutil/strtok.c b/krb5-1-6/src/kadmin/dbutil/strtok.c
new file mode 100644
index 000000000..80117a31b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/strtok.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ */
+
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include "nstrtok.h"
+
+/*
+ * Function: nstrtok
+ * 
+ * Purpose: the same as strtok ... just different. does not deal with
+ *	    multiple tokens in row.
+ *
+ * Arguments:
+ *	s	    (input) string to scan
+ *	delim	    (input) list of delimiters
+ * 	<return value> string or null on error.
+ *
+ * Requires:
+ *	nuttin
+ * 
+ * Effects:
+ *	sets last to string
+ *
+ * Modifies:
+ *	last
+ * 
+ */
+
+char *
+nstrtok(s, delim)
+	register char *s;
+	register const char *delim;
+{
+	register const char *spanp;
+	register int c, sc;
+	char *tok;
+	static char *last;
+
+
+	if (s == NULL && (s = last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+	 */
+#ifdef OLD	 
+cont:
+	c = *s++;
+	for (spanp = delim; (sc = *spanp++) != 0;) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == 0) {		/* no non-delimiter characters */
+		last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+#else
+	tok = s;
+#endif	
+
+	/*
+	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = 0;
+				last = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
+
diff --git a/krb5-1-6/src/kadmin/dbutil/tcl_wrapper.c b/krb5-1-6/src/kadmin/dbutil/tcl_wrapper.c
new file mode 100644
index 000000000..16721ae6a
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/tcl_wrapper.c
@@ -0,0 +1,241 @@
+/*
+ * admin/edit/tcl_wrapper.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Tcl wrapper for kdb5_edit
+ */
+
+#include "k5-int.h"
+#include "kdb5_edit.h"
+#ifdef HAVE_TCL_H
+#include <tcl.h>
+#elif defined(HAVE_TCL_TCL_H)
+#include <tcl/tcl.h>
+#endif
+
+#define CMDDECL(x) int x(clientData, interp, argc, argv)\
+    ClientData clientData;\
+    Tcl_Interp * interp;\
+    int argc;\
+    char ** argv;
+#define CMDPROTO(x) int x (ClientData, Tcl_Interp, int, char **)
+#define MKCMD(name,cmd) Tcl_CreateCommand(interp, name, cmd,\
+					 (ClientData)NULL,\
+					 (Tcl_CmdDeleteProc *)NULL)
+
+extern int main();
+int *tclDummyMainPtr = (int *) main; /* force ld to suck in main()
+					from libtcl.a */
+extern Tcl_Interp *interp;	/* XXX yes, this is gross,
+				   but we do need it for some things */
+extern int exit_status;
+
+void show_principal (int, char **);
+void add_new_key (int, char **);
+void change_pwd_key (int, char **);
+void add_rnd_key (int, char **);
+void change_rnd_key (int, char **);
+void delete_entry (int, char **);
+void extract_srvtab (krb5_context, int, char **);
+void extract_v4_srvtab (int, char **);
+void list_db (int, char **);
+void dump_db (int, char **);
+void load_db (int, char **);
+void set_dbname (krb5_context, int, char **);
+void enter_master_key (krb5_context, int, char **);
+
+/*
+ * this is mostly stolen from tcl_ExitCmd()
+ * we need to do a few extra things, though...
+ */
+int doquit(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    int value;
+
+    if ((argc != 1) && (argc != 2)) {
+	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+		" ?returnCode?\"", (char *) NULL);
+	return TCL_ERROR;
+    }
+    if (argc == 1) {
+	exit(quit() ? 1 : exit_status);
+    }
+    if (Tcl_GetInt(interp, argv[1], &value) != TCL_OK) {
+	return TCL_ERROR;
+    }
+    (void)quit();
+    exit(value);
+    /*NOTREACHED*/
+    return TCL_OK;			/* Better not ever reach this! */
+}
+
+int list_requests(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    Tcl_SetResult(interp, "show_principal, show: Show the Kerberos database entry for a principal\nadd_new_key, ank: Add new entry to the Kerberos database (prompting for password\nchange_pwd_key, cpw: Change key of an entry in the Kerberos database (prompting for password)\nadd_rnd_key, ark: Add new entry to Kerberos database, using a random key\nchange_rnd_key, crk: Change key of an entry in the Kerberos database (select a random key)\ndelete_entry, delent: Delete an entry from the database\nextract_srvtab, xst, ex_st: Extract service key table\nextract_v4_srvtab, xst4: Extract service key table\nlist_db, ldb: List database entries\nset_dbname, sdbn: Change database name\nenter_master_key, emk: Enter the master key for a database\nchange_working_directory, cwd, cd: Change working directory\nprint_working_directory, pwd: Print working directory\nlist_requests, lr: List available requests\nquit, exit: Exit program", TCL_STATIC);
+    return TCL_OK;
+}
+
+int wrapper(func, interp, argc, argv)
+    void (*func)();
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    (*func)(argc, argv);
+    return TCL_OK;
+}
+
+int Tcl_AppInit(interp)
+    Tcl_Interp *interp;
+{
+    int argc;
+    char **argv, **mostly_argv;
+    char *interp_argv, *interp_argv0, *request;
+    Tcl_CmdInfo cmdInfo;
+
+    if (Tcl_Init(interp) == TCL_ERROR)
+	return TCL_ERROR;
+    /*
+     * the following is, admittedly, sorta gross, but the only way
+     * to grab the original argc, argv once the interpreter is running
+     */
+    interp_argv = Tcl_GetVar(interp, "argv", 0);
+    if (interp_argv == NULL)
+	return TCL_ERROR;
+    else if (Tcl_SplitList(interp, interp_argv,
+			   &argc, &mostly_argv) != TCL_OK)
+	return TCL_ERROR;
+    interp_argv0 = Tcl_GetVar(interp, "argv0", 0);
+    if (interp_argv0 == NULL)
+	return TCL_ERROR;
+    if ((argv = (char **)malloc((argc + 1) * sizeof (char *))) == NULL)
+	return TCL_ERROR;
+    argv[0] = interp_argv0;
+    memcpy(argv + 1, mostly_argv, argc++ * sizeof (char *));
+    /*
+     * set up a prompt
+     */
+    if (Tcl_SetVar(interp, "tcl_prompt1",
+		   "puts -nonewline \"kdb5_edit: \"", 0) == NULL)
+	return TCL_ERROR;
+    /*
+     * we don't want arbitrary programs to get exec'd by accident
+     */
+    if (Tcl_SetVar(interp, "auto_noexec", "{}", 0) == NULL)
+	return TCL_ERROR;
+    request = kdb5_edit_Init(argc, argv);
+    Tcl_CallWhenDeleted(interp, doquit,
+			(ClientData)0);
+    Tcl_CreateCommand(interp, "quit", doquit,
+		      (ClientData)0,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "exit", doquit,
+		      (ClientData)0,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "list_requests", list_requests,
+		      (ClientData)0,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "lr", list_requests,
+		      (ClientData)0,
+		      (Tcl_CmdDeleteProc *)0);
+    if (Tcl_GetCommandInfo(interp, "cd", &cmdInfo)) {
+	Tcl_CreateCommand(interp, "cwd", cmdInfo.proc,
+			  (ClientData)0,
+			  (Tcl_CmdDeleteProc *)0);
+	Tcl_CreateCommand(interp, "change_working_directory", cmdInfo.proc,
+			  (ClientData)0,
+			  (Tcl_CmdDeleteProc *)0);
+    }
+    if (Tcl_GetCommandInfo(interp, "pwd", &cmdInfo)) {
+	Tcl_CreateCommand(interp, "print_working_directory", cmdInfo.proc,
+			  (ClientData)0,
+			  (Tcl_CmdDeleteProc *)0);
+    }
+    Tcl_CreateCommand(interp, "show_principal", wrapper, show_principal,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "show", wrapper, show_principal,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "add_new_key", wrapper, add_new_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "ank", wrapper, add_new_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "change_pwd_key", wrapper, change_pwd_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "cpw", wrapper, change_pwd_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "add_rnd_key", wrapper, add_rnd_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "ark", wrapper, add_rnd_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "change_rnd_key", wrapper, change_rnd_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "crk", wrapper, change_rnd_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "delete_entry", wrapper, delete_entry,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "delent", wrapper, delete_entry,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "extract_srvtab", wrapper, extract_srvtab,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "xst", wrapper, extract_srvtab,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "ex_st", wrapper, extract_srvtab,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "extract_v4_srvtab", wrapper, extract_v4_srvtab,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "xv4st", wrapper, extract_v4_srvtab,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "list_db", wrapper, list_db,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "ldb", wrapper, list_db,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "dump_db", wrapper, dump_db,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "ddb", wrapper, dump_db,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "load_db", wrapper, load_db,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "lddb", wrapper, load_db,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "set_dbname", wrapper, set_dbname,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "sdbn", wrapper, set_dbname,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "enter_master_key", wrapper, enter_master_key,
+		      (Tcl_CmdDeleteProc *)0);
+    Tcl_CreateCommand(interp, "emk", wrapper, enter_master_key,
+		      (Tcl_CmdDeleteProc *)0);
+    if (request && (Tcl_Eval(interp, request) == TCL_ERROR))
+	return TCL_ERROR;
+    return TCL_OK;
+}
diff --git a/krb5-1-6/src/kadmin/dbutil/util.c b/krb5-1-6/src/kadmin/dbutil/util.c
new file mode 100644
index 000000000..246a6cb74
--- /dev/null
+++ b/krb5-1-6/src/kadmin/dbutil/util.c
@@ -0,0 +1,158 @@
+/*
+ * admin/edit/util.c
+ *
+ * Copyright 1992 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Utilities for kdb5_edit.
+ * 
+ * Some routines derived from code contributed by the Sandia National
+ * Laboratories.  Sandia National Laboratories also makes no
+ * representations about the suitability of the modifications, or
+ * additions to this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+#include "./kdb5_edit.h"
+
+#ifndef HAVE_STRSTR
+char *
+strstr(s1, s2)
+char *s1;
+char *s2;
+{
+   int s2len;
+   int i;
+   char *temp_ptr;
+
+   temp_ptr = s1;
+   for ( i = 0; i < strlen(s1); i++) {
+        if (memcmp(temp_ptr, s2, strlen(s2)) == 0) return(temp_ptr);
+        temp_ptr += 1;
+   }
+   return ((char *) 0);
+}
+#endif	/* HAVE_STRSTR */
+
+void
+parse_token(token_in, must_be_first_char, num_tokens, tokens_out)
+char *token_in;
+int  *must_be_first_char;
+int  *num_tokens;
+char *tokens_out;
+{
+    int i, j;
+    int token_count = 0;
+
+    i = 0;
+    j = 0;
+
+	/* Eliminate Up Front Asterisks */
+    *must_be_first_char = 1;
+    for (i = 0; token_in[i] == '*'; i++) {
+	*must_be_first_char = 0;
+    }
+
+    if (i == strlen(token_in)) {
+	*num_tokens = 0;
+	return;
+    }
+
+	/* Fill first token_out */
+    token_count++;
+    while ((token_in[i] != '*') && (token_in[i] != '\0')) {
+	tokens_out[j] = token_in[i];
+        j++;
+	i++;
+    }
+
+    if (i == strlen(token_in)) {
+	tokens_out[j] = '\0';
+	*num_tokens = token_count;
+	return;
+    }
+
+	/* Then All Subsequent Tokens */
+    while (i < strlen(token_in)) {
+	if (token_in[i] == '*') {
+	   token_count++;
+	   tokens_out[j] = '\t';
+	} else {
+	   tokens_out[j] = token_in[i];
+	}
+	i++;
+	j++;
+    }
+    tokens_out[j] = '\0';
+
+    if (tokens_out[j - 1] == '\t') {
+	token_count--;
+	tokens_out[j - 1] = '\0';
+    }
+
+    *num_tokens = token_count;
+    return;
+}
+
+int
+check_for_match(search_field, must_be_first_character, chk_entry, 
+		num_tokens, type)
+int must_be_first_character;
+char *search_field;
+krb5_db_entry *chk_entry;
+int num_tokens;
+int type;
+{
+    char token1[256];
+    char *found1;
+    char token2[256];
+    char *found2;
+    char token3[256];
+    char *found3;
+    char *local_entry;
+
+    local_entry = chk_entry->princ->data[type].data;
+
+    token1[0] = token2[0] = token3[0] = '\0';
+
+    (void) sscanf(search_field, "%s\t%s\t%s", token1, token2, token3);
+
+    found1 = strstr(local_entry, token1);
+
+    if (must_be_first_character && (found1 != local_entry)) return(0);
+
+    if (found1 && (num_tokens == 1)) return(1);
+
+    if (found1 && (num_tokens > 1)) {
+	found2 = strstr(local_entry, token2);
+	if (found2 && (found2 > found1) && (num_tokens == 2)) return(1);
+    }
+
+    if ((found2 > found1) && (num_tokens == 3)) {
+	found3 = strstr(local_entry, token3);
+       	if (found3 && (found3 > found2) && (found2 > found1)) return(1);
+    }
+    return(0);
+}
+
diff --git a/krb5-1-6/src/kadmin/kdbkeys/Makefile.in b/krb5-1-6/src/kadmin/kdbkeys/Makefile.in
new file mode 100644
index 000000000..741a9a745
--- /dev/null
+++ b/krb5-1-6/src/kadmin/kdbkeys/Makefile.in
@@ -0,0 +1,18 @@
+thisconfigdir=.
+myfulldir=kadmin/kdbkeys
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+
+PROG = kdbkeys
+OBJS = kdbkeys.o
+
+all:: $(PROG)
+
+$(PROG): $(OBJS) $(DEPLIBS)
+	$(CC) $(LDFLAGS) $(LDARGS) -o $(PROG) $(OBJS) $(LIBS)
+
+install::
+	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
+
+clean::
+	$(RM) $(PROG) $(OBJS)
diff --git a/krb5-1-6/src/kadmin/kdbkeys/do-test.pl b/krb5-1-6/src/kadmin/kdbkeys/do-test.pl
new file mode 100755
index 000000000..7acb425f7
--- /dev/null
+++ b/krb5-1-6/src/kadmin/kdbkeys/do-test.pl
@@ -0,0 +1,56 @@
+#!/afs/athena/contrib/perl/p
+
+#
+# $Id$
+#
+
+$debug = $ARGV[1] || $ENV{'VERBOSE_TEST'};
+
+die "Need a number.\n" if !$ARGV[0];
+
+die "Neither \$TOP nor \$TESTDIR is set.\n" 
+    if (! ($ENV{'TOP'} || $ENV{'TESTDIR'}));
+
+$TESTDIR = ($ENV{'TESTDIR'} || "$ENV{'TOP'}/testing");
+$INITDB = ($ENV{'INITDB'} || "$TESTDIR/scripts/init_db");
+
+for ($i=0; $i<$ARGV[0]; $i++) {
+    print "Trial $i\n" if $debug;
+
+    system("$INITDB > /dev/null 2>&1") &&
+	die "Error in init_db\n";
+
+    open(KEYS,"../dbutil/kdb5_util -R dump_db|") ||
+	die "Couldn't run kdb5_util: $!\n";
+    chop($header = <KEYS>);
+    if ($header ne "kdb5_util load_dump version 4") {
+	die "Cannot operate on dump version \"$header\"; version 4 required.";
+    }
+    while(<KEYS>) {
+	next if ((!/^princ.*kadmin\//) && (!/^princ.*krbtgt/));
+
+	print if $debug > 1;
+
+	split;
+
+	$princ = $_[6];
+	$nkeys = $_[4];
+	$ntls = $_[3];
+	print "$princ: nkeys $nkeys, ntls $ntls\n" if $debug;
+	for ($j = 15 + $ntls*3; $nkeys > 0; $nkeys--) {
+	    $ver = $_[$j++];
+	    $kvno = $_[$j++];
+	    $keytype = $_[$j++];
+	    $keylen = $_[$j++];
+	    $keydata = $_[$j++];
+	    $j += 3 if ($ver > 1);
+
+	    print "$princ, ver $ver, kvno $kvno, type $keytype, len $keylen, "
+		. "data $keydata\n" if $debug;
+	    
+	    die "Duplicated key $princ = $keydata\n" if
+		$keys{$keydata}++;
+	}
+    }
+    close(KEYS);
+}
diff --git a/krb5-1-6/src/kadmin/ktutil/Makefile.in b/krb5-1-6/src/kadmin/ktutil/Makefile.in
new file mode 100644
index 000000000..70a5e878f
--- /dev/null
+++ b/krb5-1-6/src/kadmin/ktutil/Makefile.in
@@ -0,0 +1,67 @@
+thisconfigdir=../..
+myfulldir=kadmin/ktutil
+mydir=kadmin/ktutil
+BUILDTOP=$(REL)..$(S)..
+LOCALINCLUDES = $(KRB4_INCLUDES)
+PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS=
+
+OBJS= 	ktutil.o \
+	ktutil_ct.o \
+	ktutil_funcs.o
+
+SRCS= 	$(srcdir)/ktutil.c \
+	ktutil_ct.c \
+	$(srcdir)/ktutil_funcs.c
+
+all:: ktutil
+
+ktutil: ktutil.o $(OBJS) $(SS_DEPLIB) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o ktutil $(OBJS) $(SS_LIB) $(KRB5_BASE_LIBS)
+
+install::
+	$(INSTALL_PROGRAM) ktutil ${DESTDIR}$(ADMIN_BINDIR)/ktutil
+	$(INSTALL_DATA) $(srcdir)/ktutil.M ${DESTDIR}$(ADMIN_MANDIR)/ktutil.8
+
+generate-files-mac: ktutil_ct.c
+
+# needed until we run makedepend
+ktutil_ct.c: ktutil_ct.ct
+
+ktutil_ct.o: ktutil_ct.c
+
+clean::
+	$(RM) ktutil_ct.c
+
+depend:: ktutil_ct.c
+
+clean::
+	$(RM) ktutil
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)ktutil.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SS_DEPS) ktutil.c \
+  ktutil.h
+$(OUTPRE)ktutil_ct.$(OBJEXT): $(COM_ERR_DEPS) $(SS_DEPS) \
+  ktutil_ct.c
+$(OUTPRE)ktutil_funcs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ktutil.h ktutil_funcs.c
diff --git a/krb5-1-6/src/kadmin/ktutil/ktutil.M b/krb5-1-6/src/kadmin/ktutil/ktutil.M
new file mode 100644
index 000000000..9e6d46dfe
--- /dev/null
+++ b/krb5-1-6/src/kadmin/ktutil/ktutil.M
@@ -0,0 +1,67 @@
+.TH KTUTIL 8
+.SH NAME
+ktutil \- Kerberos keytab file maintenance utility
+.SH SYNOPSIS
+.B ktutil
+.SH DESCRIPTION
+The
+.B ktutil
+command invokes a subshell from which an administrator can read, write,
+or edit entries in a Kerberos V5 keytab or V4 srvtab file.
+.SH COMMANDS
+.TP
+.B list
+Displays the current keylist.  Alias:
+.BR l .
+.TP
+\fBread_kt\fP \fIkeytab\fP
+Read the Kerberos V5 keytab file
+.I keytab
+into the current keylist.  Alias: 
+.B rkt
+.TP
+\fBread_st\fP \fIsrvtab\fP
+Read the Kerberos V4 srvtab file
+.I srvtab
+into the current keylist.  Alias:
+.BR rst .
+.TP
+\fBwrite_kt\fP \fIkeytab\fP
+Write the current keylist into the Kerberos V5 keytab file
+.IR keytab .
+Alias:
+.BR wkt .
+.TP
+\fBwrite_st\fP \fIsrvtab\fP
+Write the current keylist into the Kerberos V4 srvtab file
+.IR srvtab .
+Alias:
+.BR wst .
+.TP
+.B clear_list
+Clear the current keylist.  Alias:
+.BR clear .
+.TP
+\fBdelete_entry\fP \fIslot\fP
+Delete the entry in slot number
+.I slot
+from the current keylist.  Alias:
+.BR delent .
+.TP
+\fBadd_entry\fP (\-key | \-password) \-p \fIprincipal\fP \-k \fIkvno\fP \-e \fIenctype\fP
+Add principal to keylist using key or password.  Alias:
+.BR addent .
+.TP
+.BR list_requests
+Displays a listing of available commands.  Aliases:
+.BR lr ,
+.BR ? .
+.TP
+.B quit
+Quits
+.BR ktutil .
+Aliases:
+.BR exit ,
+.BR q .
+.SH SEE ALSO
+kadmin(8), kdb5_util(8)
diff --git a/krb5-1-6/src/kadmin/ktutil/ktutil.c b/krb5-1-6/src/kadmin/ktutil/ktutil.c
new file mode 100644
index 000000000..e2464e853
--- /dev/null
+++ b/krb5-1-6/src/kadmin/ktutil/ktutil.c
@@ -0,0 +1,295 @@
+/*
+ * kadmin/ktutil/ktutil.c
+ *
+ * Copyright 1995, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * SS user interface for ktutil.
+ */
+
+#include "k5-int.h"
+#include "ktutil.h"
+#include <com_err.h>
+#include "adm_proto.h"
+#include <ss/ss.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+extern ss_request_table ktutil_cmds;
+krb5_context kcontext;
+krb5_kt_list ktlist = NULL;
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    int sci_idx;
+
+    retval = krb5_init_context(&kcontext);
+    if (retval) {
+        com_err(argv[0], retval, "while initializing krb5");
+	exit(1);
+    }
+    sci_idx = ss_create_invocation("ktutil", "5.0", (char *)NULL,
+				   &ktutil_cmds, &retval);
+    if (retval) {
+	ss_perror(sci_idx, retval, "creating invocation");
+	exit(1);
+    }
+    retval = ss_listen(sci_idx);
+    ktutil_free_kt_list(kcontext, ktlist);
+    exit(0);
+}
+
+void ktutil_clear_list(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+
+    if (argc != 1) {
+	fprintf(stderr, "%s: invalid arguments\n", argv[0]);
+	return;
+    }
+    retval = ktutil_free_kt_list(kcontext, ktlist);
+    if (retval)
+	com_err(argv[0], retval, "while freeing ktlist");
+    ktlist = NULL;
+}
+
+void ktutil_read_v5(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+
+    if (argc != 2) {
+	fprintf(stderr, "%s: must specify keytab to read\n", argv[0]);
+	return;
+    }
+    retval = ktutil_read_keytab(kcontext, argv[1], &ktlist);
+    if (retval)
+	com_err(argv[0], retval, "while reading keytab \"%s\"", argv[1]);
+}
+
+void ktutil_read_v4(argc, argv)
+    int argc;
+    char *argv[];
+{
+#ifdef KRB5_KRB4_COMPAT
+    krb5_error_code retval;
+
+    if (argc != 2) {
+	fprintf(stderr, "%s: must specify the srvtab to read\n", argv[0]);
+	return;
+    }
+    retval = ktutil_read_srvtab(kcontext, argv[1], &ktlist);
+    if (retval)
+	com_err(argv[0], retval, "while reading srvtab \"%s\"", argv[1]);
+#else
+    fprintf(stderr, "%s: krb4 support not configured\n", argv[0]);
+#endif
+}
+
+void ktutil_write_v5(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+
+    if (argc != 2) {
+	fprintf(stderr, "%s: must specify keytab to write\n", argv[0]);
+	return;
+    }
+    retval = ktutil_write_keytab(kcontext, ktlist, argv[1]);
+    if (retval)
+	com_err(argv[0], retval, "while writing keytab \"%s\"", argv[1]);
+}
+
+void ktutil_write_v4(argc, argv)
+    int argc;
+    char *argv[];
+{
+#ifdef KRB5_KRB4_COMPAT
+    krb5_error_code retval;
+
+    if (argc != 2) {
+	fprintf(stderr, "%s: must specify srvtab to write\n", argv[0]);
+	return;
+    }
+    retval = ktutil_write_srvtab(kcontext, ktlist, argv[1]);
+    if (retval)
+	com_err(argv[0], retval, "while writing srvtab \"%s\"", argv[1]);
+#else
+    fprintf(stderr, "%s: krb4 support not configured\n", argv[0]);
+#endif
+}
+
+void ktutil_add_entry(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    char *princ = NULL;
+    char *enctype = NULL;
+    krb5_kvno kvno = 0;
+    int use_pass = 0, use_key = 0, i;    
+
+    for (i = 1; i < argc; i++) {
+	if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-p", 2)) {
+	    princ = argv[++i];
+	    continue;
+	}
+	if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-k", 2)) {
+	    kvno = (krb5_kvno) atoi(argv[++i]);
+	    continue;
+	}
+	if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) {
+	    enctype = argv[++i];
+	    continue;
+	}
+	if ((strlen(argv[i]) == 9) && !strncmp(argv[i], "-password", 9)) {
+	    use_pass++;
+	    continue;
+	}
+	if ((strlen(argv[i]) == 4) && !strncmp(argv[i], "-key", 4)) {
+	    use_key++;
+	    continue;
+	}
+    }
+
+    if (argc != 8 || !(princ && kvno && enctype) || (use_pass+use_key != 1)) {
+        fprintf(stderr, "usage: %s (-key | -password) -p principal "
+		"-k kvno -e enctype\n", argv[0]);
+	return;
+    }
+
+    retval = ktutil_add(kcontext, &ktlist, princ, kvno, enctype, use_pass);
+    if (retval)
+        com_err(argv[0], retval, "while adding new entry");
+}
+
+void ktutil_delete_entry(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+
+    if (argc != 2) {
+	fprintf(stderr, "%s: must specify entry to delete\n", argv[0]);
+	return;
+    }
+    retval = ktutil_delete(kcontext, &ktlist, atoi(argv[1]));
+    if (retval)
+	com_err(argv[0], retval, "while deleting entry %d", atoi(argv[1]));
+}
+
+void ktutil_list(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval;
+    krb5_kt_list lp;
+    int show_time = 0, show_keys = 0, show_enctype = 0;
+    int i, j;
+    char *pname;
+
+    for (i = 1; i < argc; i++) {
+	if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-t", 2)) {
+	    show_time++;
+	    continue;
+	}
+	if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-k", 2)) {
+	    show_keys++;
+	    continue;
+	}
+	if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) {
+	    show_enctype++;
+	    continue;
+	}
+
+	fprintf(stderr, "%s: usage: %s [-t] [-k] [-e]\n", argv[0], argv[0]);
+	return;
+    }
+    if (show_time) {
+	printf("slot KVNO Timestamp         Principal\n");
+	printf("---- ---- ----------------- ---------------------------------------------------\n");
+    } else {
+	printf("slot KVNO Principal\n");
+	printf("---- ---- ---------------------------------------------------------------------\n");
+    }
+    for (i = 1, lp = ktlist; lp; i++, lp = lp->next) {
+	retval = krb5_unparse_name(kcontext, lp->entry->principal, &pname);
+	if (retval) {
+	    com_err(argv[0], retval, "while unparsing principal name");
+	    return;
+	}
+	printf("%4d %4d ", i, lp->entry->vno);
+	if (show_time) {
+	    char fmtbuf[18];
+	    char fill;
+	    time_t tstamp;
+
+	    (void) localtime(&tstamp);
+	    lp->entry->timestamp = tstamp;
+	    fill = ' ';
+	    if (!krb5_timestamp_to_sfstring((krb5_timestamp)lp->entry->
+					    	timestamp,
+					    fmtbuf,
+					    sizeof(fmtbuf),
+					    &fill))
+		printf("%s ", fmtbuf);
+	}
+	printf("%40s", pname);
+	if (show_enctype) {
+	    static char buf[256];
+		if ((retval = krb5_enctype_to_string(
+		    lp->entry->key.enctype, buf, 256))) {
+		    com_err(argv[0], retval, "While converting enctype to string");
+		    return;
+		}
+	    printf(" (%s) ", buf);
+	}
+	
+	if (show_keys) {
+	    printf(" (0x");
+	    for (j = 0; j < lp->entry->key.length; j++)
+		printf("%02x", lp->entry->key.contents[j]);
+	    printf(")");
+	}
+	printf("\n");
+	krb5_xfree(pname);
+    }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/krb5-1-6/src/kadmin/ktutil/ktutil.h b/krb5-1-6/src/kadmin/ktutil/ktutil.h
new file mode 100644
index 000000000..d25c8d998
--- /dev/null
+++ b/krb5-1-6/src/kadmin/ktutil/ktutil.h
@@ -0,0 +1,75 @@
+/*
+ * kadmin/ktutil/ktutil.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+typedef struct _krb5_kt_list {
+    struct _krb5_kt_list *next;
+    krb5_keytab_entry *entry;
+} *krb5_kt_list;
+
+krb5_error_code ktutil_free_kt_list (krb5_context, krb5_kt_list);
+
+krb5_error_code ktutil_delete (krb5_context, krb5_kt_list *, int);
+
+krb5_error_code ktutil_add (krb5_context,
+			    krb5_kt_list *,
+			    char *,
+			    krb5_kvno,
+			    char *,
+			    int);
+
+krb5_error_code ktutil_read_keytab (krb5_context,
+				    char *,
+				    krb5_kt_list *);
+
+krb5_error_code ktutil_write_keytab (krb5_context,
+				     krb5_kt_list,
+				     char *);
+
+#ifdef KRB5_KRB4_COMPAT
+krb5_error_code ktutil_read_srvtab (krb5_context,
+				    char *,
+				    krb5_kt_list *);
+krb5_error_code ktutil_write_srvtab (krb5_context,
+				     krb5_kt_list,
+				     char *);
+#endif
+
+void ktutil_add_entry (int, char *[]);
+
+void ktutil_clear_list (int, char *[]);
+
+void ktutil_read_v5 (int, char *[]);
+
+void ktutil_read_v4 (int, char *[]);
+
+void ktutil_write_v5 (int, char *[]);
+
+void ktutil_write_v4 (int, char *[]);
+
+void ktutil_delete_entry (int, char *[]);
+
+void ktutil_list (int, char *[]);
diff --git a/krb5-1-6/src/kadmin/ktutil/ktutil_ct.ct b/krb5-1-6/src/kadmin/ktutil/ktutil_ct.ct
new file mode 100644
index 000000000..0c7ccb689
--- /dev/null
+++ b/krb5-1-6/src/kadmin/ktutil/ktutil_ct.ct
@@ -0,0 +1,59 @@
+# 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.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+# 
+# Command table for ktutil
+#
+
+command_table ktutil_cmds;
+
+request ktutil_clear_list, "Clear the current keylist.",
+	clear_list, clear;
+
+request ktutil_read_v5, "Read a krb5 keytab into the current keylist.",
+	read_kt, rkt;
+
+request ktutil_read_v4, "Read a krb4 srvtab into the current keylist.",
+	read_st, rst;
+
+request ktutil_write_v5, "Write the current keylist to a krb5 keytab.",
+	write_kt, wkt;
+
+request ktutil_write_v4, "Write the current keylist to a krb4 srvtab.",
+	write_st, wst;
+
+request ktutil_add_entry, "Add an entry to the current keylist.",
+	add_entry, addent;
+
+request ktutil_delete_entry, "Delete an entry from the current keylist.",
+	delete_entry, delent;
+
+request ktutil_list, "List the current keylist.",
+	list, l;
+
+request ss_list_requests, "List available requests.",
+	list_requests, lr, "?";
+
+request ss_quit, "Exit program.",
+	quit, exit, q;
+
+end;
diff --git a/krb5-1-6/src/kadmin/ktutil/ktutil_funcs.c b/krb5-1-6/src/kadmin/ktutil/ktutil_funcs.c
new file mode 100644
index 000000000..649002e21
--- /dev/null
+++ b/krb5-1-6/src/kadmin/ktutil/ktutil_funcs.c
@@ -0,0 +1,556 @@
+/*
+ * kadmin/ktutil/ktutil_funcs.c
+ *
+ *(C) Copyright 1995, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Utility functions for ktutil.
+ */
+
+#include "k5-int.h"
+#include "ktutil.h"
+#ifdef KRB5_KRB4_COMPAT
+#include "kerberosIV/krb.h"
+#include <stdio.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+
+/*
+ * Free a kt_list
+ */
+krb5_error_code ktutil_free_kt_list(context, list)
+    krb5_context context;
+    krb5_kt_list list;
+{
+    krb5_kt_list lp, prev;
+    krb5_error_code retval = 0;
+
+    for (lp = list; lp;) {
+	retval = krb5_kt_free_entry(context, lp->entry);
+	free((char *)lp->entry);
+	if (retval)
+	    break;
+	prev = lp;
+	lp = lp->next;
+	free((char *)prev);
+    }
+    return retval;
+}
+
+/*
+ * Delete a numbered entry in a kt_list.  Takes a pointer to a kt_list
+ * in case head gets deleted.
+ */
+krb5_error_code ktutil_delete(context, list, idx)
+    krb5_context context;
+    krb5_kt_list *list;
+    int idx;
+{
+    krb5_kt_list lp, prev;
+    int i;
+
+    for (lp = *list, i = 1; lp; prev = lp, lp = lp->next, i++) {
+	if (i == idx) {
+	    if (i == 1)
+		*list = lp->next;
+	    else
+		prev->next = lp->next;
+	    lp->next = NULL;
+	    return ktutil_free_kt_list(context, lp);
+	}
+    }
+    return EINVAL;
+}
+
+/*
+ * Create a new keytab entry and add it to the keytab list.
+ * Based on the value of use_pass, either prompt the user for a
+ * password or key.  If the keytab list is NULL, allocate a new
+ * one first.
+ */
+krb5_error_code ktutil_add(context, list, princ_str, kvno,
+			   enctype_str, use_pass)
+    krb5_context context;
+    krb5_kt_list *list;
+    char *princ_str;
+    krb5_kvno kvno;
+    char *enctype_str;
+    int use_pass;
+{
+    krb5_keytab_entry *entry;
+    krb5_kt_list lp = NULL, prev = NULL;
+    krb5_principal princ;
+    krb5_enctype enctype;
+    krb5_timestamp now;
+    krb5_error_code retval;
+    krb5_data password, salt;
+    krb5_keyblock key;
+    char buf[BUFSIZ];
+    char promptstr[1024];
+
+    char *cp;
+    int i, tmp;
+    unsigned int pwsize = BUFSIZ;
+
+    retval = krb5_parse_name(context, princ_str, &princ);
+    if (retval)
+        return retval;
+    /* now unparse in order to get the default realm appended
+       to princ_str, if no realm was specified */
+    retval = krb5_unparse_name(context, princ, &princ_str);
+    if (retval)
+        return retval;
+    retval = krb5_string_to_enctype(enctype_str, &enctype);
+    if (retval) 
+        return KRB5_BAD_ENCTYPE;
+    retval = krb5_timeofday(context, &now);
+    if (retval)
+        return retval;
+
+    if (*list) {
+        /* point lp at the tail of the list */
+        for (lp = *list; lp->next; lp = lp->next);
+    }
+    entry = (krb5_keytab_entry *) malloc(sizeof(krb5_keytab_entry));
+    if (!entry) {
+        return ENOMEM;
+    }
+    memset((char *) entry, 0, sizeof(*entry));
+
+    if (!lp) {		/* if list is empty, start one */
+        lp = (krb5_kt_list) malloc(sizeof(*lp));
+	if (!lp) {
+	    return ENOMEM;
+	}
+    } else {
+        lp->next = (krb5_kt_list) malloc(sizeof(*lp));
+	if (!lp->next) {
+	    return ENOMEM;
+	}
+	prev = lp;
+	lp = lp->next;
+    }          
+    lp->next = NULL;
+    lp->entry = entry;
+
+    if (use_pass) {
+        password.length = pwsize;
+	password.data = (char *) malloc(pwsize);
+	if (!password.data) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+
+	sprintf(promptstr, "Password for %.1000s", princ_str);
+        retval = krb5_read_password(context, promptstr, NULL, password.data,
+				    &password.length);
+	if (retval)
+	    goto cleanup;
+	retval = krb5_principal2salt(context, princ, &salt);
+	if (retval)
+	    goto cleanup;
+	retval = krb5_c_string_to_key(context, enctype, &password,
+				      &salt, &key);
+	if (retval)
+	    goto cleanup;
+	memset(password.data, 0, password.length);
+	password.length = 0;
+	memcpy(&lp->entry->key, &key, sizeof(krb5_keyblock));
+    } else {
+        printf("Key for %s (hex): ", princ_str);
+	fgets(buf, BUFSIZ, stdin);
+	/*
+	 * We need to get rid of the trailing '\n' from fgets.
+	 * If we have an even number of hex digits (as we should),
+	 * write a '\0' over the '\n'.  If for some reason we have
+	 * an odd number of hex digits, force an even number of hex
+	 * digits by writing a '0' into the last position (the string
+	 * will still be null-terminated).
+	 */
+	buf[strlen(buf) - 1] = strlen(buf) % 2 ? '\0' : '0';
+	if (strlen(buf) == 0) {
+	    fprintf(stderr, "addent: Error reading key.\n");
+	    retval = 0;
+	    goto cleanup;
+	}
+	
+        lp->entry->key.enctype = enctype;
+	lp->entry->key.contents = (krb5_octet *) malloc((strlen(buf) + 1) / 2);
+	if (!lp->entry->key.contents) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+
+	i = 0;
+	for (cp = buf; *cp; cp += 2) {
+	    if (!isxdigit((int) cp[0]) || !isxdigit((int) cp[1])) {
+	        fprintf(stderr, "addent: Illegal character in key.\n");
+		retval = 0;
+		goto cleanup;
+	    }
+	    sscanf(cp, "%02x", &tmp);
+	    lp->entry->key.contents[i++] = (krb5_octet) tmp;
+	}
+	lp->entry->key.length = i;
+    }
+    lp->entry->principal = princ;
+    lp->entry->vno = kvno;
+    lp->entry->timestamp = now;
+
+    if (!*list)
+	*list = lp;
+
+    return 0;
+
+ cleanup:
+    if (prev)
+        prev->next = NULL;
+    ktutil_free_kt_list(context, lp);
+    return retval;
+}
+
+/*
+ * Read in a keytab and append it to list.  If list starts as NULL,
+ * allocate a new one if necessary.
+ */
+krb5_error_code ktutil_read_keytab(context, name, list)
+    krb5_context context;
+    char *name;
+    krb5_kt_list *list;
+{
+    krb5_kt_list lp = NULL, tail = NULL, back = NULL;
+    krb5_keytab kt;
+    krb5_keytab_entry *entry;
+    krb5_kt_cursor cursor;
+    krb5_error_code retval = 0;
+
+    if (*list) {
+	/* point lp at the tail of the list */
+	for (lp = *list; lp->next; lp = lp->next);
+	back = lp;
+    }
+    retval = krb5_kt_resolve(context, name, &kt);
+    if (retval)
+	return retval;
+    retval = krb5_kt_start_seq_get(context, kt, &cursor);
+    if (retval)
+	goto close_kt;
+    for (;;) {
+	entry = (krb5_keytab_entry *)malloc(sizeof (krb5_keytab_entry));
+	if (!entry) {
+	    retval = ENOMEM;
+	    break;
+	}
+	memset((char *)entry, 0, sizeof (*entry));
+	retval = krb5_kt_next_entry(context, kt, entry, &cursor);
+	if (retval)
+	    break;
+
+	if (!lp) {		/* if list is empty, start one */
+	    lp = (krb5_kt_list)malloc(sizeof (*lp));
+	    if (!lp) {
+		retval = ENOMEM;
+		break;
+	    }
+	} else {
+	    lp->next = (krb5_kt_list)malloc(sizeof (*lp));
+	    if (!lp->next) {
+		retval = ENOMEM;
+		break;
+	    }
+	    lp = lp->next;
+	}
+	if (!tail)
+	    tail = lp;
+	lp->next = NULL;
+	lp->entry = entry;
+    }
+    if (entry)
+	free((char *)entry);
+    if (retval) {
+	if (retval == KRB5_KT_END)
+	    retval = 0;
+	else {
+	    ktutil_free_kt_list(context, tail);
+	    tail = NULL;
+	    if (back)
+		back->next = NULL;
+	}
+    }
+    if (!*list)
+	*list = tail;
+    krb5_kt_end_seq_get(context, kt, &cursor);
+ close_kt:
+    krb5_kt_close(context, kt);
+    return retval;
+}
+
+/*
+ * Takes a kt_list and writes it to the named keytab.
+ */
+krb5_error_code ktutil_write_keytab(context, list, name)
+    krb5_context context;
+    krb5_kt_list list;
+    char *name;
+{
+    krb5_kt_list lp;
+    krb5_keytab kt;
+    char ktname[MAXPATHLEN+sizeof("WRFILE:")+1];
+    krb5_error_code retval = 0;
+
+    strcpy(ktname, "WRFILE:");
+    if (strlen (name) >= MAXPATHLEN)
+	return ENAMETOOLONG;
+    strncat (ktname, name, MAXPATHLEN);
+    retval = krb5_kt_resolve(context, ktname, &kt);
+    if (retval)
+	return retval;
+    for (lp = list; lp; lp = lp->next) {
+	retval = krb5_kt_add_entry(context, kt, lp->entry);
+	if (retval)
+	    break;
+    }
+    krb5_kt_close(context, kt);
+    return retval;
+}
+
+#ifdef KRB5_KRB4_COMPAT
+/*
+ * getstr() takes a file pointer, a string and a count.  It reads from
+ * the file until either it has read "count" characters, or until it
+ * reads a null byte.  When finished, what has been read exists in the
+ * given string "s".  If "count" characters were actually read, the
+ * last is changed to a null, so the returned string is always null-
+ * terminated.  getstr() returns the number of characters read,
+ * including the null terminator.
+ */
+
+static int getstr(fp, s, n)
+    FILE *fp;
+    register char *s;
+    int n;
+{
+    register int count = n;
+    while (fread(s, 1, 1, fp) > 0 && --count)
+        if (*s++ == '\0')
+            return (n - count);
+    *s = '\0';
+    return (n - count);
+}
+
+/*
+ * Read in a named krb4 srvtab and append to list.  Allocate new list
+ * if needed.
+ */
+krb5_error_code ktutil_read_srvtab(context, name, list)
+    krb5_context context;
+    char *name;
+    krb5_kt_list *list;
+{
+    krb5_kt_list lp = NULL, tail = NULL, back = NULL;
+    krb5_keytab_entry *entry;
+    krb5_error_code retval = 0;
+    char sname[SNAME_SZ];	/* name of service */
+    char sinst[INST_SZ];	/* instance of service */
+    char srealm[REALM_SZ];	/* realm of service */
+    unsigned char kvno;		/* key version number */
+    des_cblock key;
+    FILE *fp;
+
+    if (*list) {
+	/* point lp at the tail of the list */
+	for (lp = *list; lp->next; lp = lp->next);
+	back = lp;
+    }
+    fp = fopen(name, "r");
+    if (!fp)
+	return EIO;
+    for (;;) {
+	entry = (krb5_keytab_entry *)malloc(sizeof (krb5_keytab_entry));
+	if (!entry) {
+	    retval = ENOMEM;
+	    break;
+	}
+	memset((char *)entry, 0, sizeof (*entry));
+	memset(sname, 0, sizeof (sname));
+	memset(sinst, 0, sizeof (sinst));
+	memset(srealm, 0, sizeof (srealm));
+	if (!(getstr(fp, sname, SNAME_SZ) > 0 &&
+	      getstr(fp, sinst, INST_SZ) > 0 &&
+	      getstr(fp, srealm, REALM_SZ) > 0 &&
+	      fread(&kvno, 1, 1, fp) > 0 &&
+	      fread((char *)key, sizeof (key), 1, fp) > 0))
+	    break;
+	entry->magic = KV5M_KEYTAB_ENTRY;
+	entry->timestamp = 0;	/* XXX */
+	entry->vno = kvno;
+	retval = krb5_425_conv_principal(context,
+					 sname, sinst, srealm,
+					 &entry->principal);
+	if (retval)
+	    break;
+	entry->key.magic = KV5M_KEYBLOCK;
+	entry->key.enctype = ENCTYPE_DES_CBC_CRC;
+	entry->key.length = sizeof (key);
+	entry->key.contents = (krb5_octet *)malloc(sizeof (key));
+	if (!entry->key.contents) {
+	    retval = ENOMEM;
+	    break;
+	}
+	memcpy((char *)entry->key.contents, (char *)key, sizeof (key));
+	if (!lp) {		/* if list is empty, start one */
+	    lp = (krb5_kt_list)malloc(sizeof (*lp));
+	    if (!lp) {
+		retval = ENOMEM;
+		break;
+	    }
+	} else {
+	    lp->next = (krb5_kt_list)malloc(sizeof (*lp));
+	    if (!lp->next) {
+		retval = ENOMEM;
+		break;
+	    }
+	    lp = lp->next;
+	}
+	lp->next = NULL;
+	lp->entry = entry;
+	if (!tail)
+	    tail = lp;
+    }
+    if (entry) {
+	if (entry->magic == KV5M_KEYTAB_ENTRY)
+	    krb5_kt_free_entry(context, entry);
+	free((char *)entry);
+    }
+    if (retval) {
+	ktutil_free_kt_list(context, tail);
+	tail = NULL;
+	if (back)
+	    back->next = NULL;
+    }
+    if (!*list)
+	*list = tail;
+    fclose(fp);
+    return retval;
+}
+
+/*
+ * Writes a kt_list out to a krb4 srvtab file.  Note that it first
+ * prunes the kt_list so that it won't contain any keys that are not
+ * the most recent, and ignores keys that are not ENCTYPE_DES.
+ */
+krb5_error_code ktutil_write_srvtab(context, list, name)
+    krb5_context context;
+    krb5_kt_list list;
+    char *name;
+{
+    krb5_kt_list lp, lp1, prev, pruned = NULL;
+    krb5_error_code retval = 0;
+    FILE *fp;
+    char sname[SNAME_SZ];
+    char sinst[INST_SZ];
+    char srealm[REALM_SZ];
+
+    /* First do heinous stuff to prune the list. */
+    for (lp = list; lp; lp = lp->next) {
+	if ((lp->entry->key.enctype != ENCTYPE_DES_CBC_CRC) &&
+	    (lp->entry->key.enctype != ENCTYPE_DES_CBC_MD5) &&
+	    (lp->entry->key.enctype != ENCTYPE_DES_CBC_MD4) &&
+	    (lp->entry->key.enctype != ENCTYPE_DES_CBC_RAW))
+	    continue;
+
+	for (lp1 = pruned; lp1; prev = lp1, lp1 = lp1->next) {
+	    /* Hunt for the current principal in the pruned list */
+	    if (krb5_principal_compare(context,
+				       lp->entry->principal,
+				       lp1->entry->principal))
+		    break;
+	}
+	if (!lp1) {		/* need to add entry to tail of pruned list */
+	    if (!pruned) {
+		pruned = (krb5_kt_list) malloc(sizeof (*pruned));
+		if (!pruned)
+		    return ENOMEM;
+		memset((char *) pruned, 0, sizeof(*pruned));
+		lp1 = pruned;
+	    } else {
+		prev->next
+		    = (krb5_kt_list) malloc(sizeof (*pruned));
+		if (!prev->next) {
+		    retval = ENOMEM;
+		    goto free_pruned;
+		}
+		memset((char *) prev->next, 0, sizeof(*pruned));
+		lp1 = prev->next;
+	    }
+	    lp1->entry = lp->entry;
+	} else {
+	    /* This heuristic should be roughly the same as in the
+	       keytab-reading code in libkrb5.  */
+	    int offset = 0;
+	    if (lp1->entry->vno > 240 || lp->entry->vno > 240) {
+		offset = 128;
+	    }
+#define M(X) (((X) + offset) % 256)
+	    if (M(lp1->entry->vno) < M(lp->entry->vno))
+		/* Check if lp->entry is newer kvno; if so, update */
+		lp1->entry = lp->entry;
+	}
+    }
+    umask(0077); /*Changing umask for all of ktutil is OK
+		  * We don't ever write out anything that should use
+		  * default umask.*/
+    fp = fopen(name, "w");
+    if (!fp) {
+	retval = EIO;
+	goto free_pruned;
+    }
+    for (lp = pruned; lp; lp = lp->next) {
+	unsigned char  kvno;
+	kvno = (unsigned char) lp->entry->vno;
+	retval = krb5_524_conv_principal(context,
+					 lp->entry->principal,
+					 sname, sinst, srealm);
+	if (retval)
+	    break;
+	fwrite(sname, strlen(sname) + 1, 1, fp);
+	fwrite(sinst, strlen(sinst) + 1, 1, fp);
+	fwrite(srealm, strlen(srealm) + 1, 1, fp);
+	fwrite((char *)&kvno, 1, 1, fp);
+	fwrite((char *)lp->entry->key.contents,
+	       sizeof (des_cblock), 1, fp);
+    }
+    fclose(fp);
+ free_pruned:
+    /*
+     * Loop over and free the pruned list; don't use free_kt_list
+     * because that kills the entries.
+     */
+    for (lp = pruned; lp;) {
+	prev = lp;
+	lp = lp->next;
+	free((char *)prev);
+    }
+    return retval;
+}
+#endif /* KRB5_KRB4_COMPAT */
diff --git a/krb5-1-6/src/kadmin/passwd/Kpasswd b/krb5-1-6/src/kadmin/passwd/Kpasswd
new file mode 100644
index 000000000..a7ec03161
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/Kpasswd
@@ -0,0 +1,46 @@
+*xm_ovpasswd.title:		PW-CHG-GUI
+*form.shadowThickness:		2
+
+*foreground:			black
+*background:			grey80
+*topShadowColor:		grey95
+*bottomShadowColor:		grey20
+*fontList:			-*-helvetica-medium-r-*-*-14-*
+*main_lbl.fontList:		-*-helvetica-bold-r-*-*-14-*
+*XmForm.Spacing:		5
+
+*main_lbl.labelString:		Changing password.
+*old_lbl.labelString:		Old password:
+*new_lbl.labelString:		New password:
+*again_lbl.labelString:		New password (again):
+*sep.leftOffset:		0
+*sep.rightOffset:		0
+*Quit.labelString:		Quit
+*Help.labelString:		Help
+
+*main_lbl.alignment:		ALIGNMENT_CENTER
+*lbl_form*alignment:		ALIGNMENT_END
+*scroll_win.shadowThickness:	0
+
+*scroll_text.value:		\
+Enter your old password below, and press return.  You will not be able to see what you\n\
+are typing.  After correctly entering your old password, you will be prompted twice for\n\
+your new password.  Other messages and directions will appear in this space as necessary.
+*scroll_text.rows:			5
+*scroll_text.columns:			66
+*scroll_text.scrollHorizontal:		FALSE
+*scroll_text.cursorPositionVisible:	FALSE
+
+*help_dlg_popup.title:		PW-CHG-GUI Help
+*help_dlg.messageString:	\
+Welcome to the Kerberos password changing GUI.\n\
+\n\
+In the main window, enter your old password when prompted.  After verifying\n\
+your old password, the policy governing your password will be displayed, and\n\
+you will be prompted for a new password.  You will then be asked to enter it\n\
+a second time, to make sure you have not made any typos.  Assuming that\n\
+your new password complies with your password policy, you should receive\n\
+an acknowledgement that your password has been changed.\n\
+\n\
+If an error occurs, the process will start over from the beginning.  You may\n\
+exit the application at any time by pressing the "Quit" button.
diff --git a/krb5-1-6/src/kadmin/passwd/Makefile.in b/krb5-1-6/src/kadmin/passwd/Makefile.in
new file mode 100644
index 000000000..16e892d3d
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/Makefile.in
@@ -0,0 +1,57 @@
+thisconfigdir=../..
+myfulldir=kadmin/passwd
+mydir=kadmin/passwd
+BUILDTOP=$(REL)..$(S)..
+LOCALINCLUDES = -I.
+DEFINES = -DUSE_KADM5_API_VERSION=1
+DEFS=
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+LOCAL_SUBDIRS = unit-test
+
+PROG = kpasswd
+OBJS = tty_kpasswd.o kpasswd.o kpasswd_strings.o
+SRCS = tty_kpasswd.c kpasswd.c kpasswd_strings.c
+
+all:: $(PROG)
+
+kpasswd_strings.c kpasswd_strings.h: $(srcdir)/kpasswd_strings.et
+
+$(OBJS): kpasswd_strings.h
+
+$(PROG): $(OBJS) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $(PROG) $(OBJS) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+
+clean::
+	$(RM) kpasswd_strings.c kpasswd_strings.h $(PROG) $(OBJS)
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)tty_kpasswd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h kpasswd.h \
+  kpasswd_strings.h tty_kpasswd.c
+$(OUTPRE)kpasswd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h kpasswd.c \
+  kpasswd.h kpasswd_strings.h
+$(OUTPRE)kpasswd_strings.$(OBJEXT): $(COM_ERR_DEPS) \
+  kpasswd_strings.c
diff --git a/krb5-1-6/src/kadmin/passwd/kpasswd.M b/krb5-1-6/src/kadmin/passwd/kpasswd.M
new file mode 100644
index 000000000..185c1f595
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/kpasswd.M
@@ -0,0 +1,70 @@
+.\" kadmin/kpasswd/kpasswd.M
+.\" 
+.\" Copyright 1995 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KPASSWD 1
+.SH NAME
+kpasswd \- change a user's Kerberos password
+.SH SYNOPSIS
+.B kpasswd
+[\fIprincipal\fP]
+.SH DESCRIPTION
+.PP
+The
+.I kpasswd
+command is used to change a Kerberos principal's password.
+.I Kpasswd
+prompts for the current Kerberos password, which is used to obtain a 
+.B changepw
+ticket from the
+.SM KDC
+for the user's Kerberos realm.  If
+.B kpasswd
+successfully obtains the
+.B changepw
+ticket, the user is prompted twice for the new password, and the
+password is changed.
+.PP
+If the principal is governed by a policy that specifies the length and/or
+number of character classes required in the new password, the new
+password must conform to the policy.  (The five character classes are
+lower case, upper case, numbers, punctuation, and all other characters.)
+.SH OPTIONS
+.TP
+.I principal
+change the password for the Kerberos principal
+.IR principal .
+Otherwise, the principal is derived from the identity of the user
+invoking the
+.I kpasswd
+command.
+.SH FILES
+.TP "\w'/tmp/tkt_kadm_[pid]'u"
+/tmp/tkt_kadm_[pid]
+temporary credentials cache for the lifetime of the password changing
+operation.  ([pid] is the process-ID of the kpasswd process.)
+.SH SEE ALSO
+kadmin(8), kadmind(8)
+.SH BUGS
+If
+.B kpasswd
+is suspended, the changepw tickets may not be destroyed.
diff --git a/krb5-1-6/src/kadmin/passwd/kpasswd.c b/krb5-1-6/src/kadmin/passwd/kpasswd.c
new file mode 100644
index 000000000..ca47fca5b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/kpasswd.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright 1993-1994 OpenVision Technologies, Inc., All Rights Reserved.
+ * 
+ * $Header$
+ *
+ *
+ */
+
+static char rcsid[] = "$Id$";
+
+#include <kadm5/admin.h>
+#include <krb5.h>
+
+#include "kpasswd_strings.h"
+#define string_text error_message
+
+#include "kpasswd.h"
+
+#include <stdio.h>
+#include <pwd.h>
+#include <string.h>
+
+extern char *whoami;
+
+
+#define MISC_EXIT_STATUS 6
+
+/*
+ * Function: kpasswd
+ *
+ * Purpose: Initialize and call lower level routines to change a password
+ *
+ * Arguments:
+ *
+ *	context		(r) krb5_context to use
+ *	argc/argv	(r) principal name to use, optional
+ *	read_old_password (f) function to read old password
+ *	read_new_password (f) function to read new and change password
+ *	display_intro_message (f) function to display intro message
+ *	whoami		(extern) argv[0]
+ *	
+ * Returns:
+ *                      exit status of 0 for success
+ *			1 principal unknown
+ *			2 old password wrong
+ *			3 cannot initialize admin server session
+ *			4 new passwd mismatch or error trying to change pw
+ *                      5 password not typed
+ *                      6 misc error
+ *                      7 incorrect usage
+ *      
+ * Requires:
+ *	Passwords cannot be more than 255 characters long.
+ *      
+ * Effects:
+ *
+ * If argc is 2, the password for the principal specified in argv[1]
+ * is changed; otherwise, the principal of the default credential
+ * cache or username is used.  display_intro_message is called with
+ * the arguments KPW_STR_CHANGING_PW_FOR and the principal name.
+ * read_old_password is then called to prompt for the old password.
+ * The admin system is then initialized, the principal's policy
+ * retrieved and explained, if appropriate, and finally
+ * read_new_password is called to read the new password and change the
+ * principal's password (presumably ovsec_kadm_chpass_principal).
+ * admin system is de-initialized before the function returns.
+ *      
+ * Modifies:
+ *
+ * Changes the principal's password.
+ *
+ */
+int
+kpasswd(context, argc, argv)
+   krb5_context context;
+   int argc;
+   char *argv[];
+{
+  int code;
+  krb5_ccache ccache = NULL;
+  krb5_principal princ = 0;
+  char *princ_str;
+  struct passwd *pw = 0;
+  unsigned int pwsize;
+  char password[255];  /* I don't really like 255 but that's what kinit uses */
+  char msg_ret[1024], admin_realm[1024];
+  ovsec_kadm_principal_ent_t principal_entry = NULL;
+  ovsec_kadm_policy_ent_t policy_entry = NULL;
+  void *server_handle;
+
+  if (argc > 2) {
+      com_err(whoami, KPW_STR_USAGE, 0);
+      return(7);
+      /*NOTREACHED*/
+    }
+
+  /************************************
+   *  Get principal name to change    * 
+   ************************************/
+
+  /* Look on the command line first, followed by the default credential
+     cache, followed by defaulting to the Unix user name */
+
+  if (argc == 2)
+    princ_str = strdup(argv[1]);
+  else {
+    code = krb5_cc_default(context, &ccache);
+    /* If we succeed, find who is in the credential cache */
+    if (code == 0) {
+      /* Get default principal from cache if one exists */
+      code = krb5_cc_get_principal(context, ccache, &princ);
+      /* if we got a principal, unparse it, otherwise get out of the if
+	 with an error code */
+      (void) krb5_cc_close(context, ccache);
+      if (code == 0) {
+	code = krb5_unparse_name(context, princ, &princ_str);
+	if (code != 0) {
+	  com_err(whoami,  code, string_text(KPW_STR_UNPARSE_NAME));
+	  return(MISC_EXIT_STATUS);
+	}
+      }
+    }
+
+    /* this is a crock.. we want to compare against */
+    /* "KRB5_CC_DOESNOTEXIST" but there is no such error code, and */
+    /* both the file and stdio types return FCC_NOFILE.  If there is */
+    /* ever another ccache type (or if the error codes are ever */
+    /* fixed), this code will have to be updated. */
+    if (code && code != KRB5_FCC_NOFILE) {
+      com_err(whoami, code, string_text(KPW_STR_WHILE_LOOKING_AT_CC));
+      return(MISC_EXIT_STATUS);
+    }
+
+    /* if either krb5_cc failed check the passwd file */
+    if (code != 0) {
+      pw = getpwuid( getuid());
+      if (pw == NULL) {
+	com_err(whoami, 0, string_text(KPW_STR_NOT_IN_PASSWD_FILE));
+	return(MISC_EXIT_STATUS);
+      }
+      princ_str = strdup(pw->pw_name);
+    }
+  }    
+  
+  display_intro_message(string_text(KPW_STR_CHANGING_PW_FOR), princ_str);
+
+  /* Need to get a krb5_principal, unless we started from with one from
+     the credential cache */
+
+  if (! princ) {
+      code = krb5_parse_name (context, princ_str, &princ);
+      if (code != 0) {
+	  com_err(whoami, code, string_text(KPW_STR_PARSE_NAME), princ_str);
+	  free(princ_str);
+	  return(MISC_EXIT_STATUS);
+      }
+  }
+  
+  pwsize = sizeof(password);
+  code = read_old_password(context, password, &pwsize);
+
+  if (code != 0) {
+    memset(password, 0, sizeof(password));
+    com_err(whoami, code, string_text(KPW_STR_WHILE_READING_PASSWORD));
+    krb5_free_principal(context, princ);
+    free(princ_str);
+    return(MISC_EXIT_STATUS);
+  }
+  if (pwsize == 0) {
+    memset(password, 0, sizeof(password));
+    com_err(whoami, 0, string_text(KPW_STR_NO_PASSWORD_READ));
+    krb5_free_principal(context, princ);
+    free(princ_str);
+    return(5);
+  }
+
+  admin_realm[0] = '\0';
+  strncat(admin_realm, krb5_princ_realm(context, princ)->data, 
+	  krb5_princ_realm(context, princ)->length);
+
+  code = ovsec_kadm_init(princ_str, password, KADM5_CHANGEPW_SERVICE,
+			 admin_realm /* we probably should take a -r */
+			             /* someday */,
+			 OVSEC_KADM_STRUCT_VERSION,
+			 OVSEC_KADM_API_VERSION_1,
+			 NULL,
+			 &server_handle);
+  if (code != 0) {
+    if (code == OVSEC_KADM_BAD_PASSWORD)
+      com_err(whoami, 0, string_text(KPW_STR_OLD_PASSWORD_INCORRECT));
+    else 
+      com_err(whoami, 0, string_text(KPW_STR_CANT_OPEN_ADMIN_SERVER), admin_realm,
+	      error_message(code));
+    krb5_free_principal(context, princ);
+    free(princ_str);
+    return((code == OVSEC_KADM_BAD_PASSWORD)?2:3);
+  }
+
+  /* Explain policy restrictions on new password if any. */
+  /* Note: copy of this exists in login (kverify.c/get_verified_in_tkt). */
+
+  code = ovsec_kadm_get_principal(server_handle, princ, &principal_entry);
+  if (code != 0) {
+    com_err(whoami, 0,
+	    string_text((code == OVSEC_KADM_UNK_PRINC)
+			? KPW_STR_PRIN_UNKNOWN : KPW_STR_CANT_GET_POLICY_INFO),
+	    princ_str);
+    krb5_free_principal(context, princ);
+    free(princ_str);
+    (void) ovsec_kadm_destroy(server_handle);
+    return((code == OVSEC_KADM_UNK_PRINC) ? 1 : MISC_EXIT_STATUS);
+  }
+  if ((principal_entry->aux_attributes & OVSEC_KADM_POLICY) != 0) {
+    code = ovsec_kadm_get_policy(server_handle,
+				 principal_entry->policy, &policy_entry);
+    if (code != 0) {
+      /* doesn't matter which error comes back, there's no nice recovery
+	 or need to differentiate to the user */
+      com_err(whoami, 0,
+	      string_text(KPW_STR_CANT_GET_POLICY_INFO), princ_str);
+      (void) ovsec_kadm_free_principal_ent(server_handle, principal_entry);
+      krb5_free_principal(context, princ);
+      free(princ_str);
+      (void) ovsec_kadm_destroy(server_handle);
+      return(MISC_EXIT_STATUS);
+    }
+    com_err(whoami, 0, string_text(KPW_STR_POLICY_EXPLANATION),
+	    princ_str, principal_entry->policy,
+	    policy_entry->pw_min_length, policy_entry->pw_min_classes);
+
+    code = ovsec_kadm_free_principal_ent(server_handle, principal_entry);
+    if (code) {
+	(void) ovsec_kadm_free_policy_ent(server_handle, policy_entry);
+	krb5_free_principal(context, princ);
+	free(princ_str);
+	com_err(whoami, code, string_text(KPW_STR_WHILE_FREEING_PRINCIPAL));
+	(void) ovsec_kadm_destroy(server_handle);
+	return(MISC_EXIT_STATUS);
+    }
+
+    code = ovsec_kadm_free_policy_ent(server_handle, policy_entry);
+    if (code) {
+	krb5_free_principal(context, princ);
+	free(princ_str);
+	com_err(whoami, code, string_text(KPW_STR_WHILE_FREEING_POLICY));
+	(void) ovsec_kadm_destroy(server_handle);
+	return(MISC_EXIT_STATUS);
+    }
+  }
+  else {
+    /* kpasswd *COULD* output something here to encourage the choice
+       of good passwords, in the absence of an enforced policy. */
+      code = ovsec_kadm_free_principal_ent(server_handle, principal_entry);
+      if (code) {
+	  krb5_free_principal(context, princ);
+	  free(princ_str);
+	  com_err(whoami, code, string_text(KPW_STR_WHILE_FREEING_PRINCIPAL));
+	  (void) ovsec_kadm_destroy(server_handle);
+	  return(MISC_EXIT_STATUS);
+      }
+  }
+
+  pwsize = sizeof(password);
+  code = read_new_password(server_handle, password, &pwsize, msg_ret, princ);
+  memset(password, 0, sizeof(password));
+
+  if (code)
+    com_err(whoami, 0, msg_ret);
+
+  krb5_free_principal(context, princ);
+  free(princ_str);
+
+  (void) ovsec_kadm_destroy(server_handle);
+  
+  if (code == KRB5_LIBOS_CANTREADPWD)
+     return(5);
+  else if (code)
+     return(4);
+  else
+     return(0);
+}
diff --git a/krb5-1-6/src/kadmin/passwd/kpasswd.h b/krb5-1-6/src/kadmin/passwd/kpasswd.h
new file mode 100644
index 000000000..577ab386f
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/kpasswd.h
@@ -0,0 +1,46 @@
+/*
+ * kadmin/passwd/kpasswd.h
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Prototypes for the kpasswd program callback functions.
+ */
+
+#ifndef __KPASSWD_H__
+#define __KPASSWD_H__
+
+int kpasswd(krb5_context context, int argc, char *argv[]);
+
+long read_old_password(krb5_context context, char *password, 
+		       unsigned int *pwsize);
+
+long read_new_password(void *server_handle, char *password, 
+		       unsigned int *pwsize, char *msg_ret, 
+		       krb5_principal princ);
+
+void display_intro_message(const char *fmt_string, const char *arg_string);
+
+#endif /* __KPASSWD_H__ */
+
+
diff --git a/krb5-1-6/src/kadmin/passwd/kpasswd_strings.et b/krb5-1-6/src/kadmin/passwd/kpasswd_strings.et
new file mode 100644
index 000000000..7e826d270
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/kpasswd_strings.et
@@ -0,0 +1,76 @@
+#
+# Copyright 1993-1994 OpenVision Technologies, Inc., All Rights Reserved.
+#
+# String table of messages for kpasswd
+
+
+error_table kpws
+
+# /* M1 */
+error_code KPW_STR_USAGE, "Usage: kpasswd [principal_name]."
+
+error_code KPW_STR_PRIN_UNKNOWN,
+	"Kerberos principal name %s is not recognized."
+#       /* <name> */
+
+# /* M2 */
+error_code KPW_STR_WHILE_LOOKING_AT_CC,
+	"while reading principal name from credential cache."
+
+# /* M4 */ 
+error_code KPW_STR_OLD_PASSWORD_INCORRECT,
+	"Old Kerberos password is incorrect. Please try again."
+
+# /* M5 */
+error_code KPW_STR_CANT_OPEN_ADMIN_SERVER,
+"Cannot establish a session with the Kerberos administrative server for\n\
+realm %s. %s."
+# /* <realm-name>, <Specific error message from admin server library>. */
+
+# /* M6 */
+error_code KPW_STR_NEW_PASSWORD_MISMATCH,
+	"New passwords do not match - password not changed.\n"
+
+# /* M7 */
+error_code KPW_STR_PASSWORD_CHANGED, "Kerberos password changed.\n"
+
+# /* M13 */
+error_code KPW_STR_PASSWORD_NOT_CHANGED, "Password not changed."
+
+error_code KPW_STR_PARSE_NAME, "when parsing name %s."
+error_code KPW_STR_UNPARSE_NAME, "when unparsing name."
+error_code KPW_STR_NOT_IN_PASSWD_FILE,	"Unable to identify user from password file."
+
+# /* M3 */
+error_code KPW_STR_CHANGING_PW_FOR, "Changing password for %s."
+# /* principal@realm */
+
+error_code KPW_STR_OLD_PASSWORD_PROMPT, "Old password"
+error_code KPW_STR_WHILE_READING_PASSWORD, "while reading new password."
+
+# /* M4 */
+error_code KPW_STR_NO_PASSWORD_READ,
+"You must type a password. Passwords must be at least one character long."
+
+# /* M14 */
+error_code KPW_STR_WHILE_TRYING_TO_CHANGE, "while trying to change password."
+
+error_code KPW_STR_WHILE_DESTROYING_ADMIN_SESSION,
+"while closing session with admin server and destroying tickets."
+
+error_code KPW_STR_WHILE_FREEING_PRINCIPAL,
+"while freeing admin principal entry"
+
+error_code KPW_STR_WHILE_FREEING_POLICY,
+"while freeing admin policy entry"
+
+error_code KPW_STR_CANT_GET_POLICY_INFO,
+"Could not get password policy information for principal %s."
+# /* principal@realm */
+
+error_code KPW_STR_POLICY_EXPLANATION,
+"%s's password is controlled by the policy %s, which\nrequires a minimum of %u characters from at least %u classes (the five classes\nare lowercase, uppercase, numbers, punctuation, and all other characters)."
+# /* principal_name policy_name min_length min_classes */
+
+end
+
diff --git a/krb5-1-6/src/kadmin/passwd/tty_kpasswd.c b/krb5-1-6/src/kadmin/passwd/tty_kpasswd.c
new file mode 100644
index 000000000..189409140
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/tty_kpasswd.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 1993-1994 OpenVision Technologies, Inc., All Rights Reserved.
+ * 
+ * $Header$
+ *
+ *
+ */
+
+static char rcsid[] = "$Id$";
+
+#include <kadm5/admin.h>
+#include <krb5.h>
+
+#include "kpasswd_strings.h"
+#define string_text error_message
+
+#include "kpasswd.h"
+#include <stdio.h>
+#include <pwd.h>
+#include <string.h>
+
+char *whoami;
+
+void display_intro_message(fmt_string, arg_string)
+     const char *fmt_string;
+     const char *arg_string;
+{
+  com_err(whoami, 0, fmt_string, arg_string);
+}
+
+long read_old_password(context, password, pwsize)
+     krb5_context context;
+     char *password;
+     unsigned int *pwsize;
+{
+  long code = krb5_read_password(context,
+			 string_text(KPW_STR_OLD_PASSWORD_PROMPT),  
+			 0, password, pwsize);
+  return code;
+}
+
+long read_new_password(server_handle, password, pwsize, msg_ret, princ)
+     void *server_handle;
+     char *password;
+     unsigned int *pwsize;
+     char *msg_ret;
+     krb5_principal princ;
+{
+  return (ovsec_kadm_chpass_principal_util(server_handle, princ, NULL, 
+					   NULL /* don't need new pw back */,
+					   msg_ret));
+}
+
+
+/*
+ * main() for tty version of kpasswd.c
+ */
+int
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+  krb5_context context;
+  int retval;
+
+  whoami = (whoami = strrchr(argv[0], '/')) ? whoami + 1 : argv[0];
+
+  retval = krb5_init_context(&context);
+  if (retval) {
+       com_err(whoami, retval, "initializing krb5 context");
+       exit(retval);
+  }
+  initialize_kpws_error_table();
+
+  retval = kpasswd(context, argc, argv);
+
+  if (!retval)
+    printf(string_text(KPW_STR_PASSWORD_CHANGED));
+
+  exit(retval);
+}
diff --git a/krb5-1-6/src/kadmin/passwd/unit-test/Makefile.in b/krb5-1-6/src/kadmin/passwd/unit-test/Makefile.in
new file mode 100644
index 000000000..969ee8207
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/unit-test/Makefile.in
@@ -0,0 +1,27 @@
+thisconfigdir=../../..
+myfulldir=kadmin/passwd/unit-test
+mydir=kadmin/passwd/unit-test
+BUILDTOP=$(REL)..$(S)..$(S)..
+check unit-test:: unit-test-@DO_TEST@
+
+unit-test-:
+	@echo "+++"
+	@echo "+++ WARNING: kpasswd unit tests not run."
+	@echo "+++ Either tcl, runtest, or Perl is unavailable."
+	@echo "+++"
+
+unit-test-ok:: unit-test-setup unit-test-body unit-test-cleanup
+
+unit-test-body::	
+	$(ENV_SETUP) $(RUNTEST) --tool kpasswd KPASSWD=../kpasswd \
+		KINIT=$(BUILDTOP)/clients/kinit/kinit \
+		KDESTROY=$(BUILDTOP)/clients/kdestroy/kdestroy \
+		PRIOCNTL_HACK=@PRIOCNTL_HACK@
+
+unit-test-setup::
+	$(ENV_SETUP) $(START_SERVERS)
+
+unit-test-cleanup::
+	$(ENV_SETUP) $(STOP_SERVERS)
+clean::
+	$(RM) dbg.log kpasswd.sum kpasswd.log
diff --git a/krb5-1-6/src/kadmin/passwd/unit-test/config/unix.exp b/krb5-1-6/src/kadmin/passwd/unit-test/config/unix.exp
new file mode 100644
index 000000000..bd8382e19
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/unit-test/config/unix.exp
@@ -0,0 +1,74 @@
+# Hack around Solaris 9 kernel race condition that causes last output
+# from a pty to get dropped.
+if { $PRIOCNTL_HACK } {
+    catch {exec priocntl -s -c FX -m 30 -p 30 -i pid [getpid]}
+    rename spawn oldspawn
+    proc spawn { args } {
+	upvar 1 spawn_id spawn_id
+	set newargs {}
+	set inflags 1
+	set eatnext 0
+	foreach arg $args {
+	    if { $arg == "-ignore" \
+		     || $arg == "-open" \
+		     || $arg == "-leaveopen" } {
+		lappend newargs $arg
+		set eatnext 1
+		continue
+	    }
+	    if [string match "-*" $arg] {
+		lappend newargs $arg
+		continue
+	    }
+	    if { $eatnext } {
+		set eatnext 0
+		lappend newargs $arg
+		continue
+	    }
+	    if { $inflags } {
+		set inflags 0
+		set newargs [concat $newargs {priocntl -e -c FX -p 0}]
+	    }
+	    lappend newargs $arg
+	}
+	set pid [eval oldspawn $newargs]
+	return $pid
+    }
+}
+
+#
+# kpasswd_version -- extract and print the version number of kpasswd
+#
+
+proc kpasswd_version {} {
+	global KPASSWD
+	catch "exec ident $KPASSWD" tmp
+	if [regexp {Id: kpasswd.c,v ([0-9]+\.[0-9]+)} $tmp \
+		dummy version] then {
+		clone_output "$KPASSWD version $version\n"
+	} else {
+		clone_output "$KPASSWD version <unknown>\n"
+	}
+}
+#
+# kpasswd_load -- loads the program
+#
+proc kpasswd_load {} {
+	#
+}
+
+# kpasswd_exit -- clean up and exit
+proc kpasswd_exit {} {
+	#
+}
+
+#
+# kpasswd_start -- start kpasswd running
+#
+proc kpasswd_start { args } {
+	global KPASSWD
+	global spawn_id
+
+	verbose "% $KPASSWD $args" 1
+	eval spawn $KPASSWD $args
+}
diff --git a/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp
new file mode 100644
index 000000000..740d7e62b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/changing.exp
@@ -0,0 +1,105 @@
+#
+# $Id$
+#
+
+set timeout 15
+
+load_lib "helpers.exp"
+
+if [info exist env(DEBUG)] { debug 1 }
+
+#
+# Here are the tests
+#
+
+test_3pass {test2} {D.5: different new passwords} test2 test2 test2 foobar \
+	4 {New passwords do not match - password not changed.}
+
+test_3pass {test2} {D.7.5: empty/empty} test2 test2 {} {} \
+	5 {You must type a password.  Passwords must be at least one character long.}
+
+test_3pass {test2} {D.6: empty/non-empty} test2 test2 {} test2 \
+	4 {New passwords do not match - password not changed.}
+
+test_3pass {test2} {D.7: non-empty/empty} test2 test2 test2 {} \
+	4 {New passwords do not match - password not changed.}
+
+
+test_win {test1} {D.8: change password} test1 test1 newpass
+
+test_win {test1} {D.9: test changed password} test1 newpass test1
+
+mytest "D.22: No policy description was shown" test1 4 {
+	-re "Changing password for test1.*\\.$s+Old password:\[^\n\]*$"
+		{ send "test1\n" }
+} {
+	-re "$s+.*$s+.*$s+.*char.*classes.*"
+		{ myfail "policy description displayed" }
+	timeout { mypass }
+} {
+	-re "^$s+New password:\[^\n\]*$"
+		{ send "newpass\n" }
+} {
+	-re "^$s+New password \\(again\\):\[^\n\]*\$"
+		{ send "ssapwen\n" }
+} {
+	-re "$s+New passwords do not match - password not changed."
+		{ mypass }
+}
+
+test_3pass {pol1} {D.10: new password too short} pol1 pol111111 que que \
+	4 {New password is too short.  Please choose a password which is at least [0-9]+ characters long.}
+
+test_3pass {pol1} {D.13: too few char classes in new password} pol1 \
+	pol111111 123456789 123456789 \
+	4 {New password does not have enough character classes.  The character classes are: - lower-case letters, - upper-case letters, - digits, - punctuation, and - all other characters \(e.g., control characters\). Please choose a password with at least [0-9]+ character classes.}
+
+test_3pass {pol1} {D.14: new password in dictionary} pol1 \
+	pol111111 Discordianism Discordianism \
+	4 {New password was found in a dictionary of possible passwords and therefore may be easily guessed.  Please choose another password.  See the kpasswd man page for help in choosing a good password.}
+
+test_win {pol1} {successful change} pol1 pol111111 polAAAAAA
+# fail "successful change: XXXX password history is majorly broken"
+
+test_3pass {pol1} {D.11: new password same as old} pol1 \
+	polAAAAAA polAAAAAA polAAAAAA \
+	4 {New password was used previously.  Please choose a different password.}
+
+test_3pass {pol1} {D.12: new password in history} pol1 \
+	polAAAAAA pol111111 pol111111 \
+	4 {New password was used previously.  Please choose a different password.}
+
+mytest "D.18: Policy description was shown" pol1 4 {
+	-re "Changing password for pol1.*\\.$s+Old password:\[^\n\]*$"
+		{ send "polAAAAAA\n" }
+} {
+	-re "$s+.*$s+.*$s+.*8 char.*2 classes.*$s+New password:\[^\n\]*$"
+		{ send "newpass1234\n" }
+} {
+	-re "^$s+New password \\(again\\):\[^\n\]*$"
+		{ send "newpass4321\n" }
+} {
+	-re "$s+New passwords do not match - password not changed."
+		{ mypass }
+}
+
+# restore pol1's password to its initial value; see discussion in 
+# secure-kpasswd/2204 about secure-releng/2191 if you are confused
+test_win {pol1} {successful change} pol1 polAAAAAA polBBBBBB
+test_win {pol1} {successful change} pol1 polBBBBBB polCCCCCC
+test_win {pol1} {successful change} pol1 polCCCCCC pol111111
+
+verbose "(sleeping 30 seconds)"
+catch "exec sleep 30"
+
+test_win {pol2} {successful change} pol2 pol222222 polbbbbbb
+
+test_3pass {pol2} {D.15: too soon to change password} pol2 \
+	polbbbbbb pol222222 pol222222 \
+	4 {Password cannot be changed because it was changed too recently.  Please wait until .*[12][0-9][0-9][0-9] before you change it.  If you need to change your password before then, contact your system security administrator.}
+
+verbose "(sleeping 30 seconds)"
+catch "exec sleep 30"
+
+test_win {pol2} {password min life passed} pol2 polbbbbbb pol222222
+
diff --git a/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/connecting.exp b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/connecting.exp
new file mode 100644
index 000000000..2cda17a6a
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/connecting.exp
@@ -0,0 +1,29 @@
+#
+# $Id$
+#
+
+set timeout 15
+
+load_lib "helpers.exp"
+
+if [info exist env(DEBUG)] { debug 1 }
+
+#
+# Here are the tests
+#
+
+test_initerr {test2} {C.4: empty old password (XXXX)} test2 {} \
+	5 {You must type a password.  Passwords must be at least one character long.}
+
+test_initerr {test2} {C.5: incorrect old password} test2 foobar \
+	2 "Old Kerberos password is incorrect. Please try again."
+
+# set timeout 60
+#
+#test_initerr {test2@SECURE-TEST-DEAD.OV.COM} {C.8: server up, daemon down} \
+#	test2 test2 \
+#	3 "" 
+#
+#test_initerr {test2@SECURE-TEST-DOWN.OV.COM} {C.8.5: server down} \
+#	test2 test2 \
+#	3 "${initerr_str}Cannot contact any KDC for requested realm"
diff --git a/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp
new file mode 100644
index 000000000..9cfff69f6
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/principal.exp
@@ -0,0 +1,60 @@
+#
+# $Id$
+#
+
+set timeout 15
+
+load_lib "helpers.exp"
+
+if [info exist env(DEBUG)] { debug 1 }
+
+#
+# Here are the tests
+#
+
+if {[info exists env(KRB5CCNAME)]} {
+	unset env(KRB5CCNAME)
+}
+kdestroy
+
+#### no principal specified
+
+if {[info exists env(USER)]} {
+    set whoami $env(USER)
+} else {
+    set whoami [exec whoami]
+}
+
+test_win {} {B.7: default nonexisting ccache(1)} $whoami $whoami newpass
+test_win {} {B.7: default nonexisting ccache(2)} $whoami newpass $whoami
+
+kinit test2 test2
+test_win {} {B.4: default existing cache containing existing principal} \
+	test2 test2 newpass
+kdestroy
+
+set env(KRB5CCNAME) FILE:/tmp/ovsec_adm_test_ccache
+kinit test2 newpass
+test_win {} {B.3: specified existing cache containing existing principal} \
+	test2 newpass test2
+kdestroy
+unset env(KRB5CCNAME)
+
+#### principal on command line
+
+#
+test_win {test2} {B.14: existing principal, no realm} test2 test2 newpass
+
+#
+test_initerr {bogus} {B.15, C.6: non-existent principal, no realm} bogus bogus \
+	3 "${initerr_str}Client not found in Kerberos database"
+
+#
+test_win {test2@SECURE-TEST.OV.COM} {B.16: existing principal, with realm} \
+	test2 newpass test2
+
+#
+test_initerr {bogus@SECURE-TEST.OV.COM} \
+	{B.17: non-existent principal, with realm} \
+	bogus bogus \
+	3 "${initerr_str}Client not found in Kerberos database"
diff --git a/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/usage.exp b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/usage.exp
new file mode 100644
index 000000000..e132bab2f
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/unit-test/kpasswd.0/usage.exp
@@ -0,0 +1,26 @@
+#
+# $Id$
+#
+
+set timeout 15
+
+load_lib "helpers.exp"
+
+#
+# Here are the tests
+#
+
+mytest {A.1: two args} {foo bar} 7 {
+	-re {[a-z./]+passwd: Usage: [a-z./]+passwd \[principal_name\]} { mypass }
+}
+
+mytest {A.2: three args} {foo bar baz} 7 {
+	-re {[a-z./]+passwd: Usage: [a-z./]+passwd \[principal_name\]} { mypass }
+}
+
+set env(KRB5CCNAME) bogus_type:bogus_ccname
+mytest {B.5: malformed ccache name} {} 6 {
+	-re {[a-z./]+passwd: Unknown credential cache type while reading principal name from credential cache} { mypass }
+}
+unset env(KRB5CCNAME)
+
diff --git a/krb5-1-6/src/kadmin/passwd/unit-test/lib/helpers.exp b/krb5-1-6/src/kadmin/passwd/unit-test/lib/helpers.exp
new file mode 100644
index 000000000..25b71a20e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/unit-test/lib/helpers.exp
@@ -0,0 +1,217 @@
+#
+# $Id$
+#
+
+global s
+set s "\[\r\n\t\ \]"
+
+if {[info commands exp_version] != {}} {
+	set exp_version_4 [regexp {^4} [exp_version]]
+} else {
+	set exp_version_4 [regexp {^4} [expect_version]]
+}
+
+# Backward compatibility until we're using expect 5 everywhere
+if {$exp_version_4} {
+	global wait_error_index wait_errno_index wait_status_index
+	set wait_error_index 0
+	set wait_errno_index 1
+	set wait_status_index 1
+} else {
+	set wait_error_index 2
+	set wait_errno_index 3
+	set wait_status_index 3
+}
+
+proc myfail { comment } {
+	global mytest_name
+	global mytest_status
+	wait
+	fail "$mytest_name: $comment"
+	set mytest_status 1
+}
+
+proc mypass {} {
+}
+
+##
+## When you expect on an id, and eof is detected, the spawn_id is closed.
+## It may be waited for, but calling expect or close on this id is an ERROR!
+##
+
+proc mytest { name kpargs status args } {
+	global spawn_id
+	global timeout
+	global mytest_name
+	global mytest_status
+	global wait_error_index wait_errno_index wait_status_index
+
+	verbose "starting test: $name"
+
+	set mytest_name "$name"
+
+	eval kpasswd_start $kpargs
+
+	# at the end, eof is success
+
+	lappend args { eof { if {[regexp "\[\r\n\]$" $expect_out(buffer)] == 0} { myfail "final status message not newline-terminated" } } }
+
+	# for each test argument....
+	# rep invariant:  when this foreach ends, the id is close'd, but
+	#   not wait'ed.
+
+	foreach test $args {
+		set mytest_status 0
+
+		# treat the arg as an expect parameter
+		# if failure, the process will be closed and waited.
+
+		uplevel 1 "expect {
+			$test
+			timeout { close; myfail \"timeout\"}
+			eof { myfail \"eof read before expected message string\" }
+		}"			
+
+		if {$mytest_status == 1} { return }
+	}
+
+	# at this point, the id is closed and we can wait on it.
+
+	set ret [wait]
+	verbose "% Exit $ret" 1
+	if {[lindex $ret $wait_error_index] == -1} {
+		fail "$name: wait returned error [lindex $ret $wait_errno_index]"
+	} else {
+		if { [lindex $ret $wait_status_index] == $status ||
+		     (($status<0) && ([lindex $ret $wait_status_index] == ($status+256))) } {
+			pass "$name"
+		} else {
+			fail "$name: unexpected return status [lindex $ret $wait_status_index], should be $status"
+		}
+	}
+}
+
+proc kinit { princ pass } {
+	global env;
+        global KINIT
+	spawn -noecho $KINIT -5 $princ;
+
+	expect {
+		-re "Password for .*:\[^\n\]*$"
+		    {send "$pass\n"}
+		timeout {puts "Timeout waiting for prompt" ; close }
+	}
+
+	# this necessary so close(1) in the child will not sleep waiting for
+	# the parent, which is us, to read pending data.
+
+	expect {
+		eof {}
+	}
+	wait
+}
+
+proc kdestroy {} {
+        global KDESTROY
+	global errorCode errorInfo
+	global env
+
+	if {[info exists errorCode]} {
+		set saveErrorCode $errorCode
+	}
+	if {[info exists errorInfo]} {
+		set saveErrorInfo $errorInfo
+	}
+	catch "system $KDESTROY -5 2>/dev/null"
+	if {[info exists saveErrorCode]} {
+		set errorCode $saveErrorCode
+	} elseif {[info exists errorCode]} {
+		unset errorCode
+	}
+	if {[info exists saveErrorInfo]} {
+		set errorInfo $saveErrorInfo
+	} elseif {[info exists errorInfo]} {
+		unset errorInfo
+	}
+}
+
+global initerr_str
+global initerr_regexp
+set initerr_str "Cannot establish a session with the Kerberos administrative server for realm \[^\r\n\]*\\. "
+set initerr_regexp "Cannot establish a session with the Kerberos administrative server for$s+realm \[^\r\n\]*\\.$s+"
+
+proc test_win { args name princ pass1 { pass2 "\001\001" } } {
+	global s
+	global initerr_regexp
+
+	if { $pass2 == "\001\001" } { set pass2 "$pass1" }
+
+	mytest "$name" $args 0 {
+		-re "Changing password for $princ.*\\.$s+Old password:\[^\n\]*$"
+			{ send "$pass1\n" }
+	} {
+		-re "Old Kerberos password is incorrect. Please try again."
+			{ close; myfail "Old password incorrect" }
+		-re "${initerr_regexp}(.+\[^\r\n\t\ \])\r\n"
+			{ close; myfail "init error: $expect_out(1,string)" }
+		-re "$s+New password:\[^\n\]*$"
+			{ send "$pass2\n" }
+		-re "$s+.*$s+.*$s+.*$s+New password:\[^\n\]*$"
+			{ send "$pass2\n" }
+	} {
+		-re "$s+New password \\(again\\):\[^\n\]*$"
+			{ send "$pass2\n" }
+	} {
+		-re "$s+Kerberos password changed."
+			{ mypass }
+		-re "$s+Password changed."
+			{ close; myfail "Wrong message on success." }
+	}
+}
+
+proc test_initerr { args name princ pass status err } {
+	global s
+	global initerr_regexp
+
+	regsub -all "$s+" $err "$s+" err2
+
+	mytest "$name" $args $status {
+		-re "Changing password for $princ.*\\.$s+Old password:\[^\n\]*$"
+			{ send "$pass\n" }
+	} {
+		-re "$err2"
+			{ mypass }
+		-re "Old Kerberos password is incorrect. Please try again."
+			{ close; myfail "Old password incorrect" }
+		-re "${initerr_regexp}(.+)\r\n"
+			{ close; myfail "init error: $expect_out(1,string)" }
+	}
+}
+
+proc test_3pass { args name princ pass1 pass2 pass3 status err } {
+	global s
+	global initerr_regexp
+
+	regsub -all "$s+" $err "$s+" err2
+
+	mytest "$name" $args $status {
+		-re "Changing password for $princ.*\\.$s+Old password:\[^\n\]*$"
+			{ send "$pass1\n" }
+	} {
+		-re "Old Kerberos password is incorrect. Please try again."
+			{ close; myfail "Old password incorrect" }
+		-re "${initerr_regexp}(.+)\r\n"
+			{ close; myfail "init error: $expect_out(1,string)" }
+		-re "$s+New password:\[^\n\]*$"
+			{ send "$pass2\n" }
+		-re "$s+.*$s+.*$s+.*$s+New password:\[^\n\]*$"
+			{ send "$pass2\n" }
+	} {
+		-re "$s+New password \\(again\\):\[^\n\]*$"
+			{ send "$pass3\n" }
+	} {
+		-re "$s+$err2"
+			{ mypass }
+	}
+}
+
diff --git a/krb5-1-6/src/kadmin/passwd/xm_kpasswd.c b/krb5-1-6/src/kadmin/passwd/xm_kpasswd.c
new file mode 100644
index 000000000..66976208a
--- /dev/null
+++ b/krb5-1-6/src/kadmin/passwd/xm_kpasswd.c
@@ -0,0 +1,452 @@
+/*
+ * Copyright 1993-1994 OpenVision Technologies, Inc., All Rights Reserved.
+ * 
+ * $Header$
+ *
+ *
+ */
+
+static char rcsid_2[] = "$Id$";
+
+#include <kadm5/admin.h>
+#include <krb5.h>
+
+#include "kpasswd_strings.h"
+#define string_text error_message
+#define initialize_kpasswd_strings initialize_kpws_error_table
+
+#include <stdio.h>
+#include <pwd.h>
+#include <string.h>
+
+char *whoami;
+
+#include <Xm/Xm.h>
+#include <Xm/MessageB.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/Form.h>
+#include <Xm/Text.h>
+#include <Xm/PushB.h>
+#include <Xm/Label.h>
+#include <Xm/Separator.h>
+#include <X11/cursorfont.h>
+#include <X11/Shell.h>
+
+Widget toplevel, scroll_text, prompt_text;
+Widget quit_btn, help_btn, old_lbl, new_lbl, again_lbl, main_lbl;
+XtAppContext app_con;
+int looping;
+int retval=0;
+
+
+/***************************************************************************
+ *
+ *  A few utility functions for setting/unsetting the busy cursor
+ *  (i.e. the watch cursor).
+ */
+static void
+SetCursor(w,c)
+     Widget w;
+     Cursor c;
+{
+  while (XtIsSubclass(w, shellWidgetClass) != True)
+    w = XtParent(w);
+
+  XDefineCursor(XtDisplay(w), XtWindow(w), c);
+  XFlush(XtDisplay(w));
+}
+
+ 
+static void
+SetStandardCursor()
+{
+  static Cursor ArrowCursor = (Cursor)NULL;
+ 
+  if (ArrowCursor == (Cursor)NULL)
+    ArrowCursor = XCreateFontCursor(XtDisplay(toplevel), XC_top_left_arrow);
+  SetCursor(toplevel, ArrowCursor);
+}
+
+ 
+static void
+SetWatchCursor()
+{
+  static Cursor WatchCursor = (Cursor)NULL;
+
+  if (WatchCursor == (Cursor)NULL)
+    WatchCursor = XCreateFontCursor(XtDisplay(toplevel), XC_watch);
+  SetCursor(toplevel, WatchCursor);
+}
+
+
+/***************************************************************************
+ *
+ *  Set up a com_err hook, for displaying to a motif scrolling widget.
+ */
+
+#if __STDC__
+#	include <stdarg.h>
+#else /* varargs: not STDC or no <stdarg> */
+	/* Non-ANSI, always take <varargs.h> path. */
+#	undef VARARGS
+#	define VARARGS 1
+#	include <varargs.h>
+#endif /* varargs */
+
+static void
+#ifdef __STDC__
+motif_com_err (const char *whoami, long code, const char *fmt, va_list args)
+#else
+motif_com_err (whoami, code, fmt, args)
+    const char *whoami;
+    long code;
+    const char *fmt;
+    va_list args;
+#endif
+{
+  XEvent event;
+  char buf[2048];
+
+  buf[0] = '\0';
+
+  if (whoami)
+    {
+      strncpy(buf, whoami, sizeof(buf) - 1);
+      buf[sizeof(buf) - 1] = '\0';
+      strncat(buf, ": ", sizeof(buf) - 1 - strlen(buf));
+    }
+  if (code)
+    {
+      buf[sizeof(buf) - 1] = '\0';
+      strncat(buf, error_message(code), sizeof(buf) - 1 - strlen(buf));
+      strncat(buf, " ", sizeof(buf) - 1 - strlen(buf));
+    }
+  if (fmt)
+    {
+      vsprintf(buf + strlen(buf), fmt, args);
+    }
+
+  XtVaSetValues(scroll_text, XmNvalue, buf, NULL);
+
+  for (; XtAppPending(app_con); )
+    {
+      XtAppNextEvent(app_con, &event);
+      XtDispatchEvent(&event);
+    }
+}
+
+
+/***************************************************************************
+ *
+ *  Function to display help widget.
+ */
+static void
+help()
+{
+  static Widget help_dlg = NULL;
+
+  if (!help_dlg)
+    {
+      help_dlg = XmCreateInformationDialog(toplevel, "help_dlg", NULL,
+					   0);
+      XtUnmanageChild(XmMessageBoxGetChild(help_dlg, XmDIALOG_CANCEL_BUTTON));
+      XtUnmanageChild(XmMessageBoxGetChild(help_dlg, XmDIALOG_HELP_BUTTON));
+    }
+  XtManageChild(help_dlg);
+}
+
+
+/***************************************************************************
+ *
+ *  Unset the global "looping" when we want to get out of reading a
+ *  password.
+ */
+static void
+unset_looping()
+{
+  looping = 0;
+}
+
+
+/***************************************************************************
+ *
+ *  Function to exit the gui.  Callback on the "Exit" button.
+ */
+static void
+quit()
+{
+  exit(retval);
+}
+
+
+/***************************************************************************
+ *
+ *  Set up motif widgets, callbacks, etc.
+ */
+static void
+create_widgets(argc, argv)
+     int *argc;
+     char *argv[];
+{
+  Widget form, lbl_form,
+  	sep,
+  	scroll_win;
+  Pixel bg;
+
+  toplevel = XtAppInitialize(&app_con, "Kpasswd", NULL, 0, argc, argv,
+			     NULL, NULL, 0);
+  form = XtCreateManagedWidget("form", xmFormWidgetClass, toplevel, NULL, 0);
+  quit_btn = XtVaCreateManagedWidget("Quit", xmPushButtonWidgetClass,
+				form,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_FORM,
+				NULL);
+  XtAddCallback(quit_btn, XmNactivateCallback, quit, 0);
+  help_btn = XtVaCreateManagedWidget("Help", xmPushButtonWidgetClass,
+				form,
+				XmNrightAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_FORM,
+				/* XmNshowAsDefault, TRUE, */
+				NULL);
+  XtAddCallback(help_btn, XmNactivateCallback, help, 0);
+  sep = XtVaCreateManagedWidget("sep", xmSeparatorWidgetClass,
+				form,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNrightAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_WIDGET,
+				XmNbottomWidget, quit_btn,
+				NULL);
+  lbl_form = XtVaCreateManagedWidget("lbl_form", xmFormWidgetClass,
+				form,
+				XmNspacing, 0,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_WIDGET,
+				XmNbottomWidget, sep,
+				NULL);
+  old_lbl = XtVaCreateManagedWidget("old_lbl", xmLabelWidgetClass,
+				lbl_form,
+				XmNtopAttachment, XmATTACH_FORM,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNrightAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_FORM,
+				NULL);
+  new_lbl = XtVaCreateManagedWidget("new_lbl", xmLabelWidgetClass,
+				lbl_form,
+				XmNtopAttachment, XmATTACH_FORM,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNrightAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_FORM,
+				NULL);
+  again_lbl = XtVaCreateManagedWidget("again_lbl", xmLabelWidgetClass,
+				lbl_form,
+				XmNtopAttachment, XmATTACH_FORM,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNrightAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_FORM,
+				NULL);
+  prompt_text = XtVaCreateManagedWidget("prompt_text", xmTextWidgetClass,
+				form,
+				XmNeditMode, XmSINGLE_LINE_EDIT,
+				XmNleftAttachment, XmATTACH_WIDGET,
+				XmNleftWidget, lbl_form,
+				XmNrightAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_WIDGET,
+				XmNbottomWidget, sep,
+				NULL);
+  XtAddCallback(prompt_text, XmNactivateCallback, unset_looping, 0);
+  XtVaGetValues(prompt_text, XmNbackground, &bg, NULL);
+  XtVaSetValues(prompt_text, XmNforeground, bg, NULL);
+
+  main_lbl = XtVaCreateWidget("main_lbl", xmLabelWidgetClass,
+				form,
+				XmNtopAttachment, XmATTACH_FORM,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNrightAttachment, XmATTACH_FORM,
+				NULL);
+  scroll_win = XtVaCreateManagedWidget("scroll_win",
+				xmScrolledWindowWidgetClass,
+				form,
+				XmNscrollingPolicy, XmAPPLICATION_DEFINED,
+				XmNscrollBarDisplayPolicy, XmSTATIC,
+				XmNtopAttachment, XmATTACH_WIDGET,
+				XmNtopWidget, main_lbl,
+				XmNleftAttachment, XmATTACH_FORM,
+				XmNrightAttachment, XmATTACH_FORM,
+				XmNbottomAttachment, XmATTACH_WIDGET,
+				XmNbottomWidget, prompt_text,
+				NULL);
+  scroll_text = XtVaCreateManagedWidget("scroll_text", xmTextWidgetClass,
+				scroll_win,
+				XmNeditMode, XmMULTI_LINE_EDIT,
+				XmNeditable, FALSE,
+				NULL);
+  XtRealizeWidget(toplevel);
+}
+
+
+/***************************************************************************
+ *
+ *  
+ */
+static long
+read_password(password, pwsize)
+     char *password;
+     int *pwsize;
+{
+  XEvent event;
+  char *text_val;
+
+  /* OK, this next part is gross...  but this is due to the fact that	*/
+  /* this is not your traditional X program, which would be event	*/
+  /* driven.  Instead, this program is more 'CLI' in nature, so we	*/
+  /* handle the dialogs synchronously... 				*/
+
+  XtVaSetValues(prompt_text, XmNmaxLength, *pwsize, XmNvalue, "", NULL);
+  for (looping=1; looping; )
+    {
+      XtAppNextEvent(app_con, &event);
+      XtDispatchEvent(&event);
+    }
+  XtVaGetValues(prompt_text, XmNvalue, &text_val, NULL);
+  *pwsize = strlen(text_val);
+  strcpy(password, text_val);
+  memset(text_val, 0, *pwsize);
+  XtVaSetValues(prompt_text, XmNvalue, text_val, NULL);
+  return(0);
+}
+  
+
+/***************************************************************************
+ *
+ *  
+ */
+void
+display_intro_message(fmt_string, arg_string)
+     const char *fmt_string;
+     const char *arg_string;
+{
+  XmString xmstr;
+  char buf[1024];
+
+  sprintf(buf, fmt_string, arg_string);
+
+  xmstr = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
+  XtVaSetValues(main_lbl, XmNlabelString, xmstr, NULL);
+  XmStringFree(xmstr);
+  XtManageChild(main_lbl);
+}
+
+
+long
+read_old_password(context, password, pwsize)
+     krb5_context context;
+     char *password;
+     unsigned int *pwsize;
+{
+  long code;
+
+  XtManageChild(old_lbl);
+  code = read_password(password, pwsize);
+  SetWatchCursor();
+  return code;
+}
+
+long
+read_new_password(server_handle, password, pwsize, msg_ret, princ)
+     void *server_handle;
+     char *password;
+     unsigned int *pwsize;
+     char *msg_ret;
+     krb5_principal princ;
+{
+  char *password2 = (char *) malloc(*pwsize * sizeof(char));
+  int pwsize2 = *pwsize;
+
+  SetStandardCursor();
+
+  if (password2 == NULL)
+    {
+      strcpy(msg_ret, error_message(ENOMEM));
+      SetWatchCursor();
+      return(ENOMEM);
+    }
+
+  XtManageChild(new_lbl); XtUnmanageChild(old_lbl);
+  read_password(password, pwsize);
+  XtManageChild(again_lbl); XtUnmanageChild(new_lbl);
+  read_password(password2, &pwsize2);
+
+  if (strcmp(password, password2))
+    {
+      memset(password, 0, *pwsize);
+
+      memset(password2, 0, pwsize2);
+      free(password2);
+      
+      strcpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH));
+      SetWatchCursor();
+      return(KRB5_LIBOS_BADPWDMATCH);
+    }
+
+  memset(password2, 0, pwsize2);
+  free(password2);
+
+  SetWatchCursor();
+  return (ovsec_kadm_chpass_principal_util(server_handle, princ, password,
+                                            NULL /* don't need new pw back */,
+                                            msg_ret));
+}
+  
+
+/***************************************************************************
+ *
+ *
+ */
+void
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+  krb5_context context;
+  int code;
+
+  initialize_kpasswd_strings();
+
+  whoami = (whoami = strrchr(argv[0], '/')) ? whoami + 1 : argv[0];
+
+  (void) set_com_err_hook(motif_com_err);
+
+  create_widgets(&argc, argv);
+  XmProcessTraversal(prompt_text, XmTRAVERSE_CURRENT);
+
+  if (retval = krb5_init_context(&context)) {
+       com_err(whoami, retval, "initializing krb5 context");
+       exit(retval);
+  }
+
+  while (1)
+    {
+      retval = kpasswd(context, argc, argv);
+      SetStandardCursor();
+
+      if (!retval)
+	com_err(0, 0, string_text(KPW_STR_PASSWORD_CHANGED));
+
+      if (retval == 0)		/* 0 is success, so presumably the user */
+				/* is done. */
+	XmProcessTraversal(quit_btn, XmTRAVERSE_CURRENT);
+
+      if ((retval == 1) ||	/* the rest are "fatal", so we should */
+	  (retval == 3) ||	/* "force" the user to quit... */
+	  (retval == 6) ||
+	  (retval == 7))
+	{
+	  XtSetSensitive(prompt_text, FALSE);
+	  XmProcessTraversal(quit_btn, XmTRAVERSE_CURRENT);
+	  XtAppMainLoop(app_con);
+	}
+    }
+
+  /* NOTREACHED */
+  exit(retval);
+}
diff --git a/krb5-1-6/src/kadmin/scripts/inst-hdrs.sh b/krb5-1-6/src/kadmin/scripts/inst-hdrs.sh
new file mode 100755
index 000000000..242be89e9
--- /dev/null
+++ b/krb5-1-6/src/kadmin/scripts/inst-hdrs.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+dir=$1; shift
+while [ $# -gt 0 ]; do
+	file=$1
+	cmp -s $file $dir/$file
+	if [ $? != 0 ]; then
+		echo "+ rm $dir/$file"
+		rm -f $dir/$file
+		echo "+ cp $file $dir/$file"
+		cp $file $dir/$file
+	fi
+	shift
+done
diff --git a/krb5-1-6/src/kadmin/server/Makefile.in b/krb5-1-6/src/kadmin/server/Makefile.in
new file mode 100644
index 000000000..6a1334c53
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/Makefile.in
@@ -0,0 +1,134 @@
+thisconfigdir=../..
+myfulldir=kadmin/server
+mydir=kadmin/server
+BUILDTOP=$(REL)..$(S)..
+KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+DEFS=
+
+LOCALINCLUDES = -I$(SRCTOP)/lib/gssapi/generic -I$(SRCTOP)/lib/gssapi/krb5 \
+	-I$(BUILDTOP)/lib/gssapi/generic -I$(BUILDTOP)/lib/gssapi/krb5
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+PROG = kadmind
+OBJS = kadm_rpc_svc.o server_stubs.o ovsec_kadmd.o schpw.o misc.o server_glue_v1.o
+SRCS = kadm_rpc_svc.c server_stubs.c ovsec_kadmd.c schpw.c misc.c server_glue_v1.c
+
+all:: $(PROG)
+
+$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o $(PROG) $(OBJS) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS) $(APPUTILS_LIB)
+
+install::
+	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(SERVER_BINDIR)/$(PROG)
+	$(INSTALL_DATA) $(srcdir)/$(PROG).M ${DESTDIR}$(SERVER_MANDIR)/$(PROG).8
+
+clean::
+	$(RM) $(PROG) $(OBJS)
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kadm_rpc_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/syslog.h \
+  kadm_rpc_svc.c misc.h
+$(OUTPRE)server_stubs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \
+  $(BUILDTOP)/include/kadm5/server_acl.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/syslog.h \
+  misc.h server_stubs.c
+$(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_acl.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \
+  $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.h $(BUILDTOP)/lib/gssapi/krb5/gssapi_krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_gssapi.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/kdb_kt.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  $(SRCTOP)/lib/gssapi/generic/gssapiP_generic.h $(SRCTOP)/lib/gssapi/generic/gssapi_generic.h \
+  $(SRCTOP)/lib/gssapi/krb5/gssapiP_krb5.h misc.h ovsec_kadmd.c
+$(OUTPRE)schpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  misc.h schpw.c
+$(OUTPRE)misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h misc.c misc.h
+$(OUTPRE)server_glue_v1.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h misc.h \
+  server_glue_v1.c
diff --git a/krb5-1-6/src/kadmin/server/acls.l b/krb5-1-6/src/kadmin/server/acls.l
new file mode 100644
index 000000000..aee4801e9
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/acls.l
@@ -0,0 +1,190 @@
+%{
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ * 
+ * $Log$
+ * Revision 1.3  1996/07/22 20:28:49  marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches.  This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964.  before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.2.4.1  1996/07/18 03:03:31  marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.2.2.1  1996/06/20  21:56:31  marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.2  1993/11/05  07:47:46  bjaspan
+ * add and use cmp_gss_names, fix regexp bug
+ *
+ * Revision 1.1  1993/11/05  07:08:48  bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+enum tokens {
+     NEWLINE = 257,
+     COMMA,
+     SEMI,
+
+     GET = 300,
+     ADD,
+     MODIFY,
+     DELETE,
+
+     ID = 350,
+};
+
+typedef union {
+     char *s;
+} toktype;
+
+toktype tokval;
+int acl_lineno = 0;
+
+%}
+
+%%
+
+\n		acl_lineno++; 
+[ \t]*		;
+[ ]*#.*		;
+","		return (COMMA);
+";"		return (SEMI);
+"get"		return (GET);
+"add"		return (ADD);
+"modify"	return (MODIFY);
+"delete"	return (DELETE);
+^[^ \t\n]+		{ tokval.s = yytext; return (ID); }
+
+%%
+     
+#include <string.h>
+#include <syslog.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <ovsec_admin/admin.h>
+
+typedef struct _entry {
+     gss_name_t gss_name;
+     char *name;
+     u_int privs;
+     struct _entry *next;
+} acl_entry;
+
+static acl_entry *acl_head = NULL;
+
+static void error(char *msg);
+
+int parse_aclfile(FILE *acl_file)
+{
+     OM_uint32 gssstat, minor_stat;
+     gss_buffer_desc in_buf;
+     acl_entry *entry;
+     enum tokens tok;
+
+     yyin = acl_file;
+
+     acl_lineno = 1;
+     while ((tok = yylex()) != 0) {
+	  if (tok != ID) {
+	       error("expected identifier");
+	       goto error;
+	  }
+
+	  entry = (acl_entry *) malloc(sizeof(acl_entry));
+	  if (entry == NULL) {
+	       error("out of memory");
+	       goto error;
+	  }
+	  entry->name = strdup(tokval.s);
+	  entry->privs = 0;
+	  while (1) {
+	       switch (tok = yylex()) {
+	       case GET:
+		    entry->privs |= OVSEC_KADM_PRIV_GET;
+		    break;
+	       case ADD:
+		    entry->privs |= OVSEC_KADM_PRIV_ADD;
+		    break;
+	       case MODIFY:
+		    entry->privs |= OVSEC_KADM_PRIV_MODIFY;
+		    break;
+	       case DELETE:
+		    entry->privs |= OVSEC_KADM_PRIV_DELETE;
+		    break;
+	       default:
+		    error("expected privilege");
+		    goto error;
+	       }
+	       tok = yylex();
+	       if (tok == COMMA)
+		    continue;
+	       else if (tok == SEMI)
+		    break;
+	       else {
+		    error("expected comma or semicolon");
+		    goto error;
+	       }
+	  }
+
+	  in_buf.value = entry->name;
+	  in_buf.length = strlen(entry->name) + 1;
+	  gssstat = gss_import_name(&minor_stat, &in_buf,
+				    gss_nt_krb5_name, &entry->gss_name);
+	  if (gssstat != GSS_S_COMPLETE) {
+	       error("invalid name");
+	       goto error;
+	  }
+	  
+	  if (acl_head == NULL) {
+	       entry->next = NULL;
+	       acl_head = entry;
+	  } else {
+	       entry->next = acl_head;
+	       acl_head = entry;
+	  }
+     }
+     return 0;
+
+error:
+     return 1;
+}
+
+int acl_check(gss_name_t caller, int priv)
+{
+     acl_entry *entry;
+     
+     entry = acl_head;
+     while (entry) {
+	  if (cmp_gss_names(entry->gss_name, caller) && entry->privs & priv)
+	       return 1;
+	  entry = entry->next;
+     }
+     return 0;
+}
+
+int cmp_gss_names(gss_name_t name1, gss_name_t name2)
+{
+     OM_uint32 minor_stat;
+     int eq;
+     (void) gss_compare_name(&minor_stat, name1, name2, &eq);
+     return eq;
+}
+
+static void error(char *msg)
+{
+     syslog(LOG_ERR, "Error while parsing acl file, line %d: %s\n",
+	    acl_lineno, msg);
+}
+
+yywrap() { return(1); }
diff --git a/krb5-1-6/src/kadmin/server/kadm_rpc_svc.c b/krb5-1-6/src/kadmin/server/kadm_rpc_svc.c
new file mode 100644
index 000000000..cd1f0d2f1
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/kadm_rpc_svc.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ */
+
+#include <stdio.h>
+#include <gssrpc/rpc.h>
+#include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */
+#include <syslog.h>
+#include "autoconf.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <kadm5/kadm_rpc.h>
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#include "misc.h"
+#include "kadm5/server_internal.h"
+
+extern void *global_server_handle;
+
+static int check_rpcsec_auth(struct svc_req *);
+static int gss_to_krb5_name(struct svc_req *, krb5_context, gss_name_t, krb5_principal *, gss_buffer_t);
+
+void log_badauth(OM_uint32 major, OM_uint32 minor,
+		 struct sockaddr_in *addr, char *data);
+/*
+ * Function: kadm_1
+ * 
+ * Purpose: RPC proccessing procedure.
+ *	    originally generated from rpcgen
+ *
+ * Arguments:
+ *	rqstp		    (input) rpc request structure
+ *	transp		    (input) rpc transport structure
+ *	(input/output)
+ * 	<return value>
+ *
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+
+void kadm_1(rqstp, transp)
+   struct svc_req *rqstp;
+   register SVCXPRT *transp;
+{
+     union {
+	  cprinc_arg create_principal_2_arg;
+	  dprinc_arg delete_principal_2_arg;
+	  mprinc_arg modify_principal_2_arg;
+	  rprinc_arg rename_principal_2_arg;
+	  gprinc_arg get_principal_2_arg;
+	  chpass_arg chpass_principal_2_arg;
+	  chrand_arg chrand_principal_2_arg;
+	  cpol_arg create_policy_2_arg;
+	  dpol_arg delete_policy_2_arg;
+	  mpol_arg modify_policy_2_arg;
+	  gpol_arg get_policy_2_arg;
+	  setkey_arg setkey_principal_2_arg;
+	  setv4key_arg setv4key_principal_2_arg;
+	  cprinc3_arg create_principal3_2_arg;
+	  chpass3_arg chpass_principal3_2_arg;
+	  chrand3_arg chrand_principal3_2_arg;
+	  setkey3_arg setkey_principal3_2_arg;
+     } argument;
+     char *result;
+     bool_t (*xdr_argument)(), (*xdr_result)();
+     char *(*local)();
+
+     if (rqstp->rq_cred.oa_flavor != AUTH_GSSAPI &&
+	 !check_rpcsec_auth(rqstp)) {
+	  krb5_klog_syslog(LOG_ERR, "Authentication attempt failed: %s, "
+		 "RPC authentication flavor %d",
+		 inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
+		 rqstp->rq_cred.oa_flavor);
+	  svcerr_weakauth(transp);
+	  return;
+     }
+     
+     switch (rqstp->rq_proc) {
+     case NULLPROC:
+	  (void) svc_sendreply(transp, xdr_void, (char *)NULL);
+	  return;
+	  
+     case CREATE_PRINCIPAL:
+	  xdr_argument = xdr_cprinc_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) create_principal_2_svc;
+	  break;
+	  
+     case DELETE_PRINCIPAL:
+	  xdr_argument = xdr_dprinc_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) delete_principal_2_svc;
+	  break;
+	  
+     case MODIFY_PRINCIPAL:
+	  xdr_argument = xdr_mprinc_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) modify_principal_2_svc;
+	  break;
+	  
+     case RENAME_PRINCIPAL:
+	  xdr_argument = xdr_rprinc_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) rename_principal_2_svc;
+	  break;
+	  
+     case GET_PRINCIPAL:
+	  xdr_argument = xdr_gprinc_arg;
+	  xdr_result = xdr_gprinc_ret;
+	  local = (char *(*)()) get_principal_2_svc;
+	  break;
+
+     case GET_PRINCS:
+	  xdr_argument = xdr_gprincs_arg;
+	  xdr_result = xdr_gprincs_ret;
+	  local = (char *(*)()) get_princs_2_svc;
+	  break;
+	  
+     case CHPASS_PRINCIPAL:
+	  xdr_argument = xdr_chpass_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) chpass_principal_2_svc;
+	  break;
+
+     case SETV4KEY_PRINCIPAL:
+	  xdr_argument = xdr_setv4key_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) setv4key_principal_2_svc;
+	  break;
+
+     case SETKEY_PRINCIPAL:
+	  xdr_argument = xdr_setkey_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) setkey_principal_2_svc;
+	  break;
+	  
+     case CHRAND_PRINCIPAL:
+	  xdr_argument = xdr_chrand_arg;
+	  xdr_result = xdr_chrand_ret;
+	  local = (char *(*)()) chrand_principal_2_svc;
+	  break;
+	  
+     case CREATE_POLICY:
+	  xdr_argument = xdr_cpol_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) create_policy_2_svc;
+	  break;
+	  
+     case DELETE_POLICY:
+	  xdr_argument = xdr_dpol_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) delete_policy_2_svc;
+	  break;
+	  
+     case MODIFY_POLICY:
+	  xdr_argument = xdr_mpol_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) modify_policy_2_svc;
+	  break;
+	  
+     case GET_POLICY:
+	  xdr_argument = xdr_gpol_arg;
+	  xdr_result = xdr_gpol_ret;
+	  local = (char *(*)()) get_policy_2_svc;
+	  break;
+
+     case GET_POLS:
+	  xdr_argument = xdr_gpols_arg;
+	  xdr_result = xdr_gpols_ret;
+	  local = (char *(*)()) get_pols_2_svc;
+	  break;
+	  
+     case GET_PRIVS:
+	  xdr_argument = xdr_u_int32;
+	  xdr_result = xdr_getprivs_ret;
+	  local = (char *(*)()) get_privs_2_svc;
+	  break;
+
+     case INIT:
+	  xdr_argument = xdr_u_int32;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) init_2_svc;
+	  break;
+
+     case CREATE_PRINCIPAL3:
+	  xdr_argument = xdr_cprinc3_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) create_principal3_2_svc;
+	  break;
+
+     case CHPASS_PRINCIPAL3:
+	  xdr_argument = xdr_chpass3_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) chpass_principal3_2_svc;
+	  break;
+
+     case CHRAND_PRINCIPAL3:
+	  xdr_argument = xdr_chrand3_arg;
+	  xdr_result = xdr_chrand_ret;
+	  local = (char *(*)()) chrand_principal3_2_svc;
+	  break;
+
+     case SETKEY_PRINCIPAL3:
+	  xdr_argument = xdr_setkey3_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) setkey_principal3_2_svc;
+	  break;
+
+     default:
+	  krb5_klog_syslog(LOG_ERR, "Invalid KADM5 procedure number: %s, %d",
+		 inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
+		 rqstp->rq_proc);
+	  svcerr_noproc(transp);
+	  return;
+     }
+     memset((char *)&argument, 0, sizeof(argument));
+     if (!svc_getargs(transp, xdr_argument, &argument)) {
+	  svcerr_decode(transp);
+	  return;
+     }
+     result = (*local)(&argument, rqstp);
+     if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+	  krb5_klog_syslog(LOG_ERR, "WARNING! Unable to send function results, "
+		 "continuing.");
+	  svcerr_systemerr(transp);
+     }
+     if (!svc_freeargs(transp, xdr_argument, &argument)) {
+	  krb5_klog_syslog(LOG_ERR, "WARNING! Unable to free arguments, "
+		 "continuing.");
+     }
+     return;
+}
+
+static int
+check_rpcsec_auth(struct svc_req *rqstp)
+{
+     gss_ctx_id_t ctx;
+     krb5_context kctx;
+     OM_uint32 maj_stat, min_stat;
+     gss_name_t name;
+     krb5_principal princ;
+     int ret, success;
+     krb5_data *c1, *c2, *realm;
+     gss_buffer_desc gss_str;
+     kadm5_server_handle_t handle;
+     size_t slen;
+     char *sdots;
+
+     success = 0;
+     handle = (kadm5_server_handle_t)global_server_handle;
+
+     if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS)
+	  return 0;
+
+     ctx = rqstp->rq_svccred;
+
+     maj_stat = gss_inquire_context(&min_stat, ctx, NULL, &name,
+				    NULL, NULL, NULL, NULL, NULL);
+     if (maj_stat != GSS_S_COMPLETE) {
+	  krb5_klog_syslog(LOG_ERR, "check_rpcsec_auth: "
+			   "failed inquire_context, stat=%u", maj_stat);
+	  log_badauth(maj_stat, min_stat,
+		      &rqstp->rq_xprt->xp_raddr, NULL);
+	  goto fail_name;
+     }
+
+     kctx = handle->context;
+     ret = gss_to_krb5_name(rqstp, kctx, name, &princ, &gss_str);
+     if (ret == 0)
+	  goto fail_name;
+
+     slen = gss_str.length;
+     trunc_name(&slen, &sdots);
+     /*
+      * Since we accept with GSS_C_NO_NAME, the client can authenticate
+      * against the entire kdb.  Therefore, ensure that the service
+      * name is something reasonable.
+      */
+     if (krb5_princ_size(kctx, princ) != 2)
+	  goto fail_princ;
+
+     c1 = krb5_princ_component(kctx, princ, 0);
+     c2 = krb5_princ_component(kctx, princ, 1);
+     realm = krb5_princ_realm(kctx, princ);
+     if (strncmp(handle->params.realm, realm->data, realm->length) == 0
+	 && strncmp("kadmin", c1->data, c1->length) == 0) {
+
+	  if (strncmp("history", c2->data, c2->length) == 0)
+	       goto fail_princ;
+	  else
+	       success = 1;
+     }
+
+fail_princ:
+     if (!success) {
+	 krb5_klog_syslog(LOG_ERR, "bad service principal %.*s%s",
+			  slen, gss_str.value, sdots);
+     }
+     gss_release_buffer(&min_stat, &gss_str);
+     krb5_free_principal(kctx, princ);
+fail_name:
+     gss_release_name(&min_stat, &name);
+     return success;
+}
+
+static int
+gss_to_krb5_name(struct svc_req *rqstp, krb5_context ctx, gss_name_t gss_name,
+		 krb5_principal *princ, gss_buffer_t gss_str)
+{
+     OM_uint32 status, minor_stat;
+     gss_OID gss_type;
+     char *str;
+     int success;
+
+     status = gss_display_name(&minor_stat, gss_name, gss_str, &gss_type);
+     if ((status != GSS_S_COMPLETE) || (gss_type != gss_nt_krb5_name)) {
+	  krb5_klog_syslog(LOG_ERR,
+			   "gss_to_krb5_name: "
+			   "failed display_name status %d", status);
+	  log_badauth(status, minor_stat,
+		      &rqstp->rq_xprt->xp_raddr, NULL);
+	  return 0;
+     }
+     str = malloc(gss_str->length +1);
+     if (str == NULL)
+	  return 0;
+     *str = '\0';
+
+     strncat(str, gss_str->value, gss_str->length);
+     success = (krb5_parse_name(ctx, str, princ) == 0);
+     free(str);
+     return success;
+}
diff --git a/krb5-1-6/src/kadmin/server/kadmind.M b/krb5-1-6/src/kadmin/server/kadmind.M
new file mode 100644
index 000000000..ad810e6f2
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/kadmind.M
@@ -0,0 +1,277 @@
+.TH KADMIND 8
+.SH NAME
+kadmind \- KADM5 administration server
+.SH SYNOPSIS
+.B kadmind
+[\fB\-x\fP \fIdb_args\fP] [\fB-r\fP \fIrealm\fP] [\fB\-m\fP] [\fB\-nofork\fP] [\fB\-port\fP
+\fIport-number\fP]
+.SH DESCRIPTION
+This command starts the KADM5 administration server.  If the database is db2, 
+the administration server runs on the master Kerberos server, which stores the KDC
+prinicpal database and the KADM5 policy database. If the database is LDAP,
+the administration server and the KDC server need not run on the same machine.  
+.B Kadmind
+accepts remote requests to administer the information in these
+databases.  Remote requests are sent, for example, by
+.IR kadmin (8)
+and the
+.IR kpasswd (1)
+command, both of which are clients of
+.BR kadmind .
+.PP
+.B kadmind
+requires a number of configuration files to be set up in order
+for it to work:
+.TP "\w'kdc.conf\ \ 'u"
+kdc.conf
+The KDC configuration file contains configuration informatin for the KDC
+and the KADM5 system.  
+.B Kadmind
+understands a number of variable settings in this file, some of whch are
+mandatory and some of which are optional.  See the CONFIGURATION VALUES
+section below.
+.TP
+keytab
+.B Kadmind
+requires a keytab containing correct entries for the 
+.I kadmin/admin
+and
+.I kadmin/changepw
+principals for every realm that kadmind will answer requests for.  The
+keytab can be created with the
+.IR kadmin (8)
+client.  The location of the keytab is determined by the
+.I admin_keytab
+configuration variable (see CONFIGURATION VALUES).
+.TP
+ACL file
+.BR Kadmind 's
+ACL (access control list) tells it which principals are allowed to
+perform KADM5 administration actions.  The path of the ACL file is
+specified via the acl_file configuration variable (see CONFIGURATION
+VALUES).  The syntax of the ACL file is specified in the ACL FILE SYNTAX
+section below.
+.PP
+After the server begins running, it puts itself in the background and
+disassociates itself from its controlling terminal.
+.SH OPTIONS
+.TP 
+\fB\-x\fP \fIdb_args\fP
+specifies the database specific arguments.
+
+Options supported for LDAP database are:
+.sp 
+.nf 
+.RS 12
+\-x nconns=<number_of_connections>
+.fi
+specifies the number of connections to be maintained per LDAP server.
+
+.nf
+\-x host=<ldapuri>
+specifies the LDAP server to connect to by a LDAP URI.
+
+\-x binddn=<binddn>
+.fi
+specifies the DN of the object used by the administration server to bind to the LDAP server. 
+This object should have the read and write rights on the realm container, principal container
+and the subtree that is referenced by the realm.
+
+\-x bindpwd=<bind_password>
+.fi
+specifies the password for the above mentioned binddn. It is recommended not to use this option.
+Instead, the password can be stashed using the stashsrvpw command of kdb5_ldap_util.
+.RE
+.fi
+.TP
+\fB\-r\fP \fIrealm\fP
+specifies the default realm that kadmind will serve; if it is not
+specified, the default realm of the host is used.  
+.B kadmind
+will answer requests for any realm that exists in the local KDC database
+and for which the appropriate principals are in its keytab.
+.TP
+.B \-m
+specifies that the master database password should be fetched from the
+keyboard rather than from a file on disk.  Note that the server gets the
+password prior to putting itself in the background; in combination with
+the -nofork option, you must place it in the background by hand.
+.TP
+.B \-nofork
+specifies that the server does not put itself in the background and does
+not disassociate itself from the terminal.  In normal operation, you
+should always allow the server place itself in the background.
+.TP
+\fB\-port\fP \fIport-number\fB
+specifies the port on which the administration server listens for
+connections.  The default is is controlled by the 
+.I kadmind_port
+configuration variable (see below).
+.SH CONFIGURATION VALUES
+.PP
+In addition to the relations defined in kdc.conf(5), kadmind
+understands the following relations, all of which should
+appear in the [realms] section:
+.TP
+acl_file
+The path of kadmind's ACL file.  Mandatory.  No default.
+.TP
+dict_file
+The path of kadmind's password dictionary.  A principal with any
+password policy will not be allowed to select any password in the
+dictionary.  Optional.  No default.
+.TP
+admin_keytab
+The name of the keytab containing entries for the principals
+.I kadmin/admin
+and
+.I kadmin/changepw
+in each realm that
+.B kadmind
+will serve.  The default is the value of the 
+.SM KRB5_KTNAME
+environment variable, if defined.  Mandatory.
+.TP
+kadmind_port
+The
+.SM TCP
+port on which
+.B kadmind
+will listen.  The default is 749.
+.SH ACL FILE SYNTAX
+.PP
+The ACL file controls which principals can or cannot perform which
+administrative functions.  For operations that affect principals, the
+ACL file also controls which principals can operate on which other
+principals.  This file can contain comment lines, null lines or lines
+which contain ACL entries.  Comment lines start with the sharp sign
+(\fB\&#\fP) and continue until the end of the line.  Lines containing ACL
+entries have the format of
+.B principal
+.I whitespace
+.B operation-mask
+[\fIwhitespace\fP \fBoperation-target\fP]
+.PP
+Ordering is important.  The first matching entry is the one which will
+control access for a particular principal on a particular principal.
+.PP
+.IP principal
+may specify a partially or fully qualified Kerberos version 5
+principal name.  Each component of the name may be wildcarded using
+the asterisk (
+.B *
+) character.
+.IP operation-target
+[Optional] may specify a partially or fully qualified Kerberos version 5
+principal name.  Each component of the name may be wildcarded using the
+asterisk (
+.B *
+) character.
+.IP operation-mask
+Specifies what operations may or may not be peformed by a principal
+matching a particular entry.  This is a string of one or more of the
+following list of characters or their upper-case counterparts.  If the
+character is upper-case, then the operation is disallowed.  If the
+character is lower-case, then the operation is permitted.
+.RS
+.TP 5
+.B a
+[Dis]allows the addition of principals or policies in the database.
+.sp -1v
+.TP
+.B d
+[Dis]allows the deletion of principals or policies in the database.
+.sp -1v
+.TP
+.B m
+[Dis]allows the modification of principals or policies in the database.
+.sp -1v
+.TP
+.B c
+[Dis]allows the changing of passwords for principals in the database.
+.sp -1v
+.TP
+.B i
+[Dis]allows inquiries to the database.
+.sp -1v
+.TP
+.B l
+[Dis]allows the listing of principals or policies in the database.
+.sp -1v
+.TP
+.B x
+Short for
+.IR admcil .
+.sp -1v
+.TP
+.B \&*
+Same as
+.BR x .
+.RE
+Some examples of valid entries here are:
+.TP
+.I user/instance@realm adm
+A standard fully qualified name.  The
+.B operation-mask
+only applies to this principal and specifies that [s]he may add,
+delete or modify principals and policies, but not change anybody
+else's password.
+.TP
+.I user/instance@realm cim service/instance@realm
+A standard fully qualified name and a standard fully qualified target.  The
+.B operation-mask
+only applies to this principal operating on this target and specifies that
+[s]he may change the target's password, request information about the
+target and modify it.
+.TP
+.I user/*@realm ac
+A wildcarded name.  The
+.B operation-mask
+applies to all principals in realm "realm" whose first component is
+"user" and specifies that [s]he may add principals and change
+anybody's password.
+.TP
+.I user/*@realm i */instance@realm
+A wildcarded name and target.  The
+.B operation-mask
+applies to all principals in realm "realm" whose first component is
+"user" and specifies that [s]he may perform
+inquiries on principals whose second component is "instance" and realm
+is "realm".
+.SH FILES
+.TP "\w'<dbname>.kadm5.lock\ 'u"
+principal.db
+default name for Kerberos principal database
+.TP
+<dbname>.kadm5
+KADM5 administrative database.  (This would be "principal.kadm5", if you
+use the default database name.)  Contains policy information.
+.TP
+<dbname>.kadm5.lock
+lock file for the KADM5 administrative database.  This file works
+backwards from most other lock files.  I.e.,
+.B kadmin
+will exit with an error if this file does
+.I not
+exist.
+.TP
+.B Note:
+The above three files are specific to db2 database.
+.TP
+kadm5.acl
+file containing list of principals and their
+.B kadmin
+administrative privileges.  See above for a description.
+.TP
+kadm5.keytab
+keytab file for
+.I kadmin/admin
+principal.
+.TP
+kadm5.dict
+file containing dictionary of strings explicitly disallowed as
+passwords.
+.SH SEE ALSO
+kpasswd(1), kadmin(8), kdb5_util(8), kadm5_export(8), kadm5_import(8),
+kdb5_ldap_util(8)
+
diff --git a/krb5-1-6/src/kadmin/server/misc.c b/krb5-1-6/src/kadmin/server/misc.c
new file mode 100644
index 000000000..ed5110048
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/misc.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ */
+
+#include    <k5-int.h>
+#include    <kdb.h>
+#include    <kadm5/server_internal.h>
+#include    "misc.h"
+
+/*
+ * Function: chpass_principal_wrapper_3
+ * 
+ * Purpose: wrapper to kadm5_chpass_principal that checks to see if
+ *	    pw_min_life has been reached. if not it returns an error.
+ *	    otherwise it calls kadm5_chpass_principal
+ *
+ * Arguments:
+ *	principal	(input) krb5_principals whose password we are
+ *				changing
+ *	keepold 	(input) whether to preserve old keys
+ *	n_ks_tuple	(input) the number of key-salt tuples in ks_tuple
+ *	ks_tuple	(input) array of tuples indicating the caller's
+ *				requested enctypes/salttypes
+ *	password	(input) password we are going to change to.
+ * 	<return value>	0 on success error code on failure.
+ *
+ * Requires:
+ *	kadm5_init to have been run.
+ * 
+ * Effects:
+ *	calls kadm5_chpass_principal which changes the kdb and the
+ *	the admin db.
+ *
+ */
+kadm5_ret_t
+chpass_principal_wrapper_3(void *server_handle,
+			   krb5_principal principal,
+			   krb5_boolean keepold,
+			   int n_ks_tuple,
+			   krb5_key_salt_tuple *ks_tuple,
+			   char *password)
+{
+    kadm5_ret_t			ret;
+
+    ret = check_min_life(server_handle, principal, NULL, 0);
+    if (ret)
+	 return ret;
+
+    return kadm5_chpass_principal_3(server_handle, principal,
+				    keepold, n_ks_tuple, ks_tuple,
+				    password);
+}
+
+
+/*
+ * Function: randkey_principal_wrapper_3
+ * 
+ * Purpose: wrapper to kadm5_randkey_principal which checks the
+ *	    password's min. life.
+ *
+ * Arguments:
+ *	principal	    (input) krb5_principal whose password we are
+ *				    changing
+ *	keepold 	(input) whether to preserve old keys
+ *	n_ks_tuple	(input) the number of key-salt tuples in ks_tuple
+ *	ks_tuple	(input) array of tuples indicating the caller's
+ *				requested enctypes/salttypes
+ *	key		    (output) new random key
+ * 	<return value>	    0, error code on error.
+ *
+ * Requires:
+ *	kadm5_init	 needs to be run
+ * 
+ * Effects:
+ *	calls kadm5_randkey_principal
+ *
+ */
+kadm5_ret_t
+randkey_principal_wrapper_3(void *server_handle,
+			    krb5_principal principal,
+			    krb5_boolean keepold,
+			    int n_ks_tuple,
+			    krb5_key_salt_tuple *ks_tuple,
+			    krb5_keyblock **keys, int *n_keys)
+{
+    kadm5_ret_t			ret;
+
+    ret = check_min_life(server_handle, principal, NULL, 0);
+    if (ret)
+	 return ret;
+    return kadm5_randkey_principal_3(server_handle, principal,
+				     keepold, n_ks_tuple, ks_tuple,
+				     keys, n_keys);
+}
+
+kadm5_ret_t
+schpw_util_wrapper(void *server_handle, krb5_principal princ,
+		   char *new_pw, char **ret_pw,
+		   char *msg_ret, unsigned int msg_len)
+{
+    kadm5_ret_t ret;
+
+    ret = check_min_life(server_handle, princ, msg_ret, msg_len);
+    if (ret)
+	return ret;
+
+    return kadm5_chpass_principal_util(server_handle, princ,
+				       new_pw, ret_pw,
+				       msg_ret, msg_len);
+}
+
+kadm5_ret_t
+check_min_life(void *server_handle, krb5_principal principal,
+	       char *msg_ret, unsigned int msg_len)
+{
+    krb5_int32			now;
+    kadm5_ret_t			ret;
+    kadm5_policy_ent_rec	pol;
+    kadm5_principal_ent_rec	princ;
+    kadm5_server_handle_t	handle = server_handle;
+
+    if (msg_ret != NULL)
+	*msg_ret = '\0';
+
+    ret = krb5_timeofday(handle->context, &now);
+    if (ret)
+	return ret;
+
+    ret = kadm5_get_principal(handle->lhandle, principal, 
+			      &princ, KADM5_PRINCIPAL_NORMAL_MASK);
+    if(ret) 
+	 return ret;
+    if(princ.aux_attributes & KADM5_POLICY) {
+	if((ret=kadm5_get_policy(handle->lhandle,
+				 princ.policy, &pol)) != KADM5_OK) {
+	    (void) kadm5_free_principal_ent(handle->lhandle, &princ);
+	    return ret;
+	}
+	if((now - princ.last_pwd_change) < pol.pw_min_life &&
+	   !(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+	    if (msg_ret != NULL) {
+		time_t until;
+		char *time_string, *ptr, *errstr;
+
+		until = princ.last_pwd_change + pol.pw_min_life;
+
+		time_string = ctime(&until);
+		errstr = error_message(CHPASS_UTIL_PASSWORD_TOO_SOON);
+
+		if (strlen(errstr) + strlen(time_string) >= msg_len) {
+		    *errstr = '\0';
+		} else {
+		    if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
+			*ptr = '\0';
+		    sprintf(msg_ret, errstr, time_string);
+		}
+	    }
+
+	    (void) kadm5_free_policy_ent(handle->lhandle, &pol);
+	    (void) kadm5_free_principal_ent(handle->lhandle, &princ);
+	    return KADM5_PASS_TOOSOON;
+	}
+
+	ret = kadm5_free_policy_ent(handle->lhandle, &pol);
+	if (ret) {
+	    (void) kadm5_free_principal_ent(handle->lhandle, &princ);
+	    return ret;
+        }
+    }
+
+    return kadm5_free_principal_ent(handle->lhandle, &princ);
+}
+
+#define MAXPRINCLEN 125
+
+void
+trunc_name(size_t *len, char **dots)
+{
+    *dots = *len > MAXPRINCLEN ? "..." : "";
+    *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len;
+}
diff --git a/krb5-1-6/src/kadmin/server/misc.h b/krb5-1-6/src/kadmin/server/misc.h
new file mode 100644
index 000000000..a020874fd
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/misc.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 1994 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ */
+
+kadm5_ret_t
+chpass_principal_wrapper_3(void *server_handle,
+			   krb5_principal principal,
+			   krb5_boolean keepold,
+			   int n_ks_tuple,
+			   krb5_key_salt_tuple *ks_tuple,
+			   char *password);
+
+kadm5_ret_t
+randkey_principal_wrapper_3(void *server_handle,
+			    krb5_principal principal,
+			    krb5_boolean keepold,
+			    int n_ks_tuple,
+			    krb5_key_salt_tuple *ks_tuple,
+			    krb5_keyblock **keys, int *n_keys);
+
+kadm5_ret_t
+schpw_util_wrapper(void *server_handle, krb5_principal princ,
+		   char *new_pw, char **ret_pw,
+		   char *msg_ret, unsigned int msg_len);
+
+kadm5_ret_t check_min_life(void *server_handle, krb5_principal principal,
+			   char *msg_ret, unsigned int msg_len);
+
+kadm5_ret_t kadm5_get_principal_v1(void *server_handle,
+				   krb5_principal principal, 
+				   kadm5_principal_ent_t_v1 *ent);
+
+kadm5_ret_t kadm5_get_policy_v1(void *server_handle, kadm5_policy_t name,
+				kadm5_policy_ent_t *ent);
+
+
+krb5_error_code process_chpw_request(krb5_context context, 
+				     void *server_handle, 
+				     char *realm, int s, 
+				     krb5_keytab keytab, 
+				     struct sockaddr_in *sockin, 
+				     krb5_data *req, krb5_data *rep);
+
+#ifdef SVC_GETARGS
+void  kadm_1(struct svc_req *, SVCXPRT *);
+#endif
+
+void trunc_name(size_t *len, char **dots);
diff --git a/krb5-1-6/src/kadmin/server/ovsec_kadmd.c b/krb5-1-6/src/kadmin/server/ovsec_kadmd.c
new file mode 100644
index 000000000..a3ce42189
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/ovsec_kadmd.c
@@ -0,0 +1,1235 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ */
+
+/*
+ * 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>
+#include    <sys/types.h>
+#ifdef _AIX
+#include    <sys/select.h>
+#endif
+#include    <sys/time.h>
+#include    <sys/socket.h>
+#include    <unistd.h>
+#include    <netinet/in.h>
+#include    <arpa/inet.h>  /* inet_ntoa */
+#include    <netdb.h>
+#include    <gssrpc/rpc.h>
+#include    <gssapi/gssapi.h>
+#include    "gssapiP_krb5.h" /* for kg_get_context */
+#include    <gssrpc/auth_gssapi.h>
+#include    <kadm5/admin.h>
+#include    <kadm5/kadm_rpc.h>
+#include    <kadm5/server_acl.h>
+#include    <adm_proto.h>
+#include    "kdb_kt.h"	/* for krb5_ktkdb_set_context */
+#include    <string.h>
+#include    "kadm5/server_internal.h" /* XXX for kadm5_server_handle_t */
+
+#include    "misc.h"
+
+#ifdef PURIFY
+#include    "purify.h"
+
+int	signal_pure_report = 0;
+int	signal_pure_clear = 0;
+void	request_pure_report(int);
+void	request_pure_clear(int);
+#endif /* PURIFY */
+
+#if defined(NEED_DAEMON_PROTO)
+extern int daemon(int, int);
+#endif
+
+volatile int	signal_request_exit = 0;
+volatile int	signal_request_hup = 0;
+void    setup_signal_handlers(void);
+void	request_exit(int);
+void	request_hup(int);
+void	reset_db(void);
+void	sig_pipe(int);
+void	kadm_svc_run(kadm5_config_params *params);
+
+#ifdef POSIX_SIGNALS
+static struct sigaction s_action;
+#endif /* POSIX_SIGNALS */
+
+
+#define	TIMEOUT	15
+
+gss_name_t gss_changepw_name = NULL, gss_oldchangepw_name = NULL;
+gss_name_t gss_kadmin_name = NULL;
+void *global_server_handle;
+
+/*
+ * This is a kludge, but the server needs these constants to be
+ * compatible with old clients.  They are defined in <kadm5/admin.h>,
+ * but only if USE_KADM5_API_VERSION == 1.
+ */
+#define OVSEC_KADM_ADMIN_SERVICE	"ovsec_adm/admin"
+#define OVSEC_KADM_CHANGEPW_SERVICE	"ovsec_adm/changepw"
+
+extern krb5_keyblock master_keyblock;
+
+char *build_princ_name(char *name, char *realm);
+void log_badauth(OM_uint32 major, OM_uint32 minor,
+		 struct sockaddr_in *addr, char *data);
+void log_badverf(gss_name_t client_name, gss_name_t server_name,
+		 struct svc_req *rqst, struct rpc_msg *msg,
+		 char *data);
+void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char
+		 *error, char *data);
+void log_badauth_display_status(char *msg, OM_uint32 major, OM_uint32 minor);
+void log_badauth_display_status_1(char *m, OM_uint32 code, int type,
+				  int rec);
+	
+int schpw;
+void do_schpw(int s, kadm5_config_params *params);
+
+#ifdef USE_PASSWORD_SERVER
+void kadm5_set_use_password_server (void);
+#endif
+
+/*
+ * Function: usage
+ * 
+ * Purpose: print out the server usage message
+ *
+ * Arguments:
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+
+static void usage()
+{
+     fprintf(stderr, "Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] "
+#ifdef USE_PASSWORD_SERVER
+             "[-passwordserver] "
+#endif
+	     "[-port port-number]\n"
+	     "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
+	     "\t\t\tLook at each database documentation for supported arguments\n"
+	     );
+     exit(1);
+}
+
+/*
+ * Function: display_status
+ *
+ * Purpose: displays GSS-API messages
+ *
+ * Arguments:
+ *
+ * 	msg		a string to be displayed with the message
+ * 	maj_stat	the GSS-API major status code
+ * 	min_stat	the GSS-API minor status code
+ *
+ * Effects:
+ *
+ * The GSS-API messages associated with maj_stat and min_stat are
+ * displayed on stderr, each preceeded by "GSS-API error <msg>: " and
+ * followed by a newline.
+ */
+static void display_status_1(char *, OM_uint32, int);
+
+static void display_status(msg, maj_stat, min_stat)
+     char *msg;
+     OM_uint32 maj_stat;
+     OM_uint32 min_stat;
+{
+     display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
+     display_status_1(msg, min_stat, GSS_C_MECH_CODE);
+}
+
+static void display_status_1(m, code, type)
+     char *m;
+     OM_uint32 code;
+     int type;
+{
+	OM_uint32 maj_stat, min_stat;
+	gss_buffer_desc msg;
+	OM_uint32 msg_ctx;
+     
+	msg_ctx = 0;
+	while (1) {
+		maj_stat = gss_display_status(&min_stat, code,
+					      type, GSS_C_NULL_OID,
+					      &msg_ctx, &msg);
+		fprintf(stderr, "GSS-API error %s: %s\n", m,
+			(char *)msg.value); 
+		(void) gss_release_buffer(&min_stat, &msg);
+	  
+		if (!msg_ctx)
+			break;
+	}
+}
+
+
+/* XXX yuck.  the signal handlers need this */
+static krb5_context context;
+
+static krb5_context hctx;
+
+int main(int argc, char *argv[])
+{
+     register	SVCXPRT *transp;
+     extern	char *optarg;
+     extern	int optind, opterr;
+     int ret, nofork, oldnames = 0;
+     OM_uint32 OMret, major_status, minor_status;
+     char *whoami;
+     gss_buffer_desc in_buf;
+     struct sockaddr_in addr;
+     int s;
+     auth_gssapi_name names[4];
+     gss_buffer_desc gssbuf;
+     gss_OID nt_krb5_name_oid;
+     kadm5_config_params params;
+     char **db_args      = NULL;
+     int    db_args_size = 0;
+     char *errmsg;
+
+     setvbuf(stderr, NULL, _IONBF, 0);
+
+     /* This is OID value the Krb5_Name NameType */
+     gssbuf.value = "{1 2 840 113554 1 2 2 1}";
+     gssbuf.length = strlen(gssbuf.value);
+     major_status = gss_str_to_oid(&minor_status, &gssbuf, &nt_krb5_name_oid);
+     if (major_status != GSS_S_COMPLETE) {
+	     fprintf(stderr, "Couldn't create KRB5 Name NameType OID\n");
+	     display_status("str_to_oid", major_status, minor_status);
+	     exit(1);
+     }
+
+     names[0].name = names[1].name = names[2].name = names[3].name = NULL;
+     names[0].type = names[1].type = names[2].type = names[3].type =
+	     nt_krb5_name_oid;
+
+#ifdef PURIFY
+     purify_start_batch();
+#endif /* PURIFY */
+     whoami = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+     nofork = 0;
+
+     memset((char *) ¶ms, 0, sizeof(params));
+     
+     argc--; argv++;
+     while (argc) {
+          if (strcmp(*argv, "-x") == 0) {
+	       argc--; argv++;
+	       if (!argc)
+		    usage();
+	       db_args_size++;
+	       {
+		   char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
+		   if( temp == NULL )
+		   {
+		       fprintf(stderr,"%s: cannot initialize. Not enough memory\n",
+			       whoami);
+		       exit(1);
+		   }
+		   db_args = temp;
+	       }
+	       db_args[db_args_size-1] = *argv;
+	       db_args[db_args_size]   = NULL;
+	  }else if (strcmp(*argv, "-r") == 0) {
+	       argc--; argv++;
+	       if (!argc)
+		    usage();
+	       params.realm = *argv;
+	       params.mask |= KADM5_CONFIG_REALM;
+	       argc--; argv++;
+	       continue;
+	  } else if (strcmp(*argv, "-m") == 0) {
+	       params.mkey_from_kbd = 1;
+	       params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+	  } else if (strcmp(*argv, "-nofork") == 0) {
+	       nofork = 1;
+#ifdef USE_PASSWORD_SERVER
+          } else if (strcmp(*argv, "-passwordserver") == 0) {
+              kadm5_set_use_password_server ();
+#endif              
+	  } else if(strcmp(*argv, "-port") == 0) {
+	    argc--; argv++;
+	    if(!argc)
+	      usage();
+	    params.kadmind_port = atoi(*argv);
+	    params.mask |= KADM5_CONFIG_KADMIND_PORT;
+	  } else
+	       break;
+	  argc--; argv++;
+     }
+     
+     if (argc != 0)
+	  usage();
+
+     if ((ret = kadm5_init_krb5_context(&context))) {
+	  fprintf(stderr, "%s: %s while initializing context, aborting\n",
+		  whoami, error_message(ret));
+	  exit(1);
+     }
+
+     krb5_klog_init(context, "admin_server", whoami, 1);
+
+     if((ret = kadm5_init("kadmind", NULL,
+			  NULL, ¶ms,
+			  KADM5_STRUCT_VERSION,
+			  KADM5_API_VERSION_2,
+			  db_args,
+		     &global_server_handle)) != KADM5_OK) {
+	  const char *e_txt = krb5_get_error_message (context, ret);
+	  krb5_klog_syslog(LOG_ERR, "%s while initializing, aborting",
+			   e_txt);
+	  fprintf(stderr, "%s: %s while initializing, aborting\n",
+		  whoami, e_txt);
+	  krb5_klog_close(context);
+	  exit(1);
+     }
+
+     if( db_args )
+     {
+	 free(db_args), db_args=NULL;
+     }
+     
+     if ((ret = kadm5_get_config_params(context, 1, ¶ms,
+					¶ms))) {
+	  const char *e_txt = krb5_get_error_message (context, ret);
+	  krb5_klog_syslog(LOG_ERR, "%s: %s while initializing, aborting",
+			   whoami, e_txt);
+	  fprintf(stderr, "%s: %s while initializing, aborting\n",
+		  whoami, e_txt);
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);
+	  exit(1);
+     }
+
+#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_ACL_FILE)
+
+     if ((params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
+	  krb5_klog_syslog(LOG_ERR, "%s: Missing required configuration values "
+			   "while initializing, aborting", whoami,
+			   (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS);
+	  fprintf(stderr, "%s: Missing required configuration values "
+		  "(%lx) while initializing, aborting\n", whoami,
+		  (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS);
+	  krb5_klog_close(context);
+	  kadm5_destroy(global_server_handle);
+	  exit(1);
+     }
+
+     memset(&addr, 0, sizeof(addr));
+     addr.sin_family = AF_INET;
+     addr.sin_addr.s_addr = INADDR_ANY;
+     addr.sin_port = htons(params.kadmind_port);
+
+     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	  const char *e_txt = krb5_get_error_message (context, ret);
+	  krb5_klog_syslog(LOG_ERR, "Cannot create TCP socket: %s",
+			   e_txt);
+	  fprintf(stderr, "Cannot create TCP socket: %s",
+		  e_txt);
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);	  
+	  exit(1);
+     }
+
+     if ((schpw = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	 const char *e_txt = krb5_get_error_message (context, ret);
+	 krb5_klog_syslog(LOG_ERR,
+			  "cannot create simple chpw socket: %s",
+			  e_txt);
+	 fprintf(stderr, "Cannot create simple chpw socket: %s",
+		 e_txt);
+	 kadm5_destroy(global_server_handle);
+	 krb5_klog_close(context);
+	 exit(1);
+     }
+
+#ifdef SO_REUSEADDR
+     /* the old admin server turned on SO_REUSEADDR for non-default
+	port numbers.  this was necessary, on solaris, for the tests
+	to work.  jhawk argues that the debug and production modes
+	should be the same.  I think I agree, so I'm always going to set
+	SO_REUSEADDR.  The other option is to have the unit tests wait
+	until the port is useable, or use a different port each time.  
+	--marc */
+
+     {
+	 int	allowed;
+
+	 allowed = 1;
+	 if (setsockopt(s,
+			SOL_SOCKET,
+			SO_REUSEADDR,
+			(char *) &allowed,
+			sizeof(allowed)) < 0) {
+	     const char *e_txt = krb5_get_error_message (context, ret);
+	     krb5_klog_syslog(LOG_ERR, "Cannot set SO_REUSEADDR: %s",
+			      e_txt);
+	     fprintf(stderr, "Cannot set SO_REUSEADDR: %s", e_txt);
+	     kadm5_destroy(global_server_handle);
+	     krb5_klog_close(context);	  
+	     exit(1);
+	 }
+	 if (setsockopt(schpw, SOL_SOCKET, SO_REUSEADDR,
+			(char *) &allowed, sizeof(allowed)) < 0) {
+	     const char *e_txt = krb5_get_error_message (context, ret);
+	     krb5_klog_syslog(LOG_ERR, "main",
+			      "cannot set SO_REUSEADDR on simple chpw socket: %s", 
+			      e_txt);
+	     fprintf(stderr,
+		     "Cannot set SO_REUSEADDR on simple chpw socket: %s",
+ 		     e_txt);
+ 	     kadm5_destroy(global_server_handle);
+ 	     krb5_klog_close(context);
+	 }
+
+     }
+#endif /* SO_REUSEADDR */
+     memset(&addr, 0, sizeof(addr));
+     addr.sin_family = AF_INET;
+     addr.sin_addr.s_addr = INADDR_ANY;
+     addr.sin_port = htons(params.kadmind_port);
+
+     if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+	  int oerrno = errno;
+	  const char *e_txt = krb5_get_error_message (context, errno);
+	  fprintf(stderr, "%s: Cannot bind socket.\n", whoami);
+	  fprintf(stderr, "bind: %s\n", e_txt);
+	  errno = oerrno;
+	  krb5_klog_syslog(LOG_ERR, "Cannot bind socket: %s", e_txt);
+	  if(oerrno == EADDRINUSE) {
+	       char *w = strrchr(whoami, '/');
+	       if (w) {
+		    w++;
+	       }
+	       else {
+		    w = whoami;
+	       }
+	       fprintf(stderr,
+"This probably means that another %s process is already\n"
+"running, or that another program is using the server port (number %d)\n"
+"after being assigned it by the RPC portmap daemon.  If another\n"
+"%s is already running, you should kill it before\n"
+"restarting the server.  If, on the other hand, another program is\n"
+"using the server port, you should kill it before running\n"
+"%s, and ensure that the conflict does not occur in the\n"
+"future by making sure that %s is started on reboot\n"
+		       "before portmap.\n", w, ntohs(addr.sin_port), w, w, w);
+	       krb5_klog_syslog(LOG_ERR, "Check for already-running %s or for "
+		      "another process using port %d", w,
+		      htons(addr.sin_port));
+	  }
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);
+	  exit(1);
+     }
+     memset(&addr, 0, sizeof(addr));
+     addr.sin_family = AF_INET;
+     addr.sin_addr.s_addr = INADDR_ANY;
+     /* XXX */
+     addr.sin_port = htons(params.kpasswd_port);
+
+     if (bind(schpw, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+	  char portbuf[32];
+	  int oerrno = errno;
+	  const char *e_txt = krb5_get_error_message (context, errno);
+	  fprintf(stderr, "%s: Cannot bind socket.\n", whoami);
+	  fprintf(stderr, "bind: %s\n", e_txt);
+	  errno = oerrno;
+	  sprintf(portbuf, "%d", ntohs(addr.sin_port));
+	  krb5_klog_syslog(LOG_ERR, "cannot bind simple chpw socket: %s",
+			   e_txt);
+	  if(oerrno == EADDRINUSE) {
+	       char *w = strrchr(whoami, '/');
+	       if (w) {
+		    w++;
+	       }
+	       else {
+		    w = whoami;
+	       }
+	       fprintf(stderr,
+"This probably means that another %s process is already\n"
+"running, or that another program is using the server port (number %d).\n"
+"If another %s is already running, you should kill it before\n"
+"restarting the server.\n",
+		       w, ntohs(addr.sin_port), w);
+ 	  }
+ 	  kadm5_destroy(global_server_handle);
+ 	  krb5_klog_close(context);
+	  exit(1);
+     }
+     
+     transp = svctcp_create(s, 0, 0);
+     if(transp == NULL) {
+	  fprintf(stderr, "%s: Cannot create RPC service.\n", whoami);
+	  krb5_klog_syslog(LOG_ERR, "Cannot create RPC service: %m");
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);	  
+	  exit(1);
+     }
+     if(!svc_register(transp, KADM, KADMVERS, kadm_1, 0)) {
+	  fprintf(stderr, "%s: Cannot register RPC service.\n", whoami);
+	  krb5_klog_syslog(LOG_ERR, "Cannot register RPC service, failing.");
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);	  
+	  exit(1);
+     }
+
+     names[0].name = build_princ_name(KADM5_ADMIN_SERVICE, params.realm);
+     names[1].name = build_princ_name(KADM5_CHANGEPW_SERVICE, params.realm);
+     names[2].name = build_princ_name(OVSEC_KADM_ADMIN_SERVICE, params.realm);
+     names[3].name = build_princ_name(OVSEC_KADM_CHANGEPW_SERVICE,
+				      params.realm); 
+     if (names[0].name == NULL || names[1].name == NULL ||
+	 names[2].name == NULL || names[3].name == NULL) {
+	  krb5_klog_syslog(LOG_ERR,
+			   "Cannot build GSS-API authentication names, "
+			   "failing.");
+	  fprintf(stderr, "%s: Cannot build GSS-API authentication names.\n",
+		  whoami);
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);	  
+	  exit(1);
+     }
+
+     /*
+      * Go through some contortions to point gssapi at a kdb keytab.
+      * This prevents kadmind from needing to use an actual file-based
+      * keytab.
+      */
+     /* XXX extract kadm5's krb5_context */
+     hctx = ((kadm5_server_handle_t)global_server_handle)->context;
+     /* Set ktkdb's internal krb5_context. */
+     ret = krb5_ktkdb_set_context(hctx);
+     if (ret) {
+	  krb5_klog_syslog(LOG_ERR, "Can't set kdb keytab's internal context.");
+	  goto kterr;
+     }
+     /* XXX master_keyblock is in guts of lib/kadm5/server_kdb.c */
+     ret = krb5_db_set_mkey(hctx, &master_keyblock);
+     if (ret) {
+	  krb5_klog_syslog(LOG_ERR, "Can't set master key for kdb keytab.");
+	  goto kterr;
+     }
+     ret = krb5_kt_register(context, &krb5_kt_kdb_ops);
+     if (ret) {
+	  krb5_klog_syslog(LOG_ERR, "Can't register kdb keytab.");
+	  goto kterr;
+     }
+     /* Tell gssapi about the kdb keytab. */
+     ret = krb5_gss_register_acceptor_identity("KDB:");
+     if (ret) {
+	  krb5_klog_syslog(LOG_ERR, "Can't register acceptor keytab.");
+	  goto kterr;
+     }
+kterr:
+     if (ret) {
+	  krb5_klog_syslog(LOG_ERR, "%s", krb5_get_error_message (context, ret));
+	  fprintf(stderr, "%s: Can't set up keytab for RPC.\n", whoami);
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);
+	  exit(1);
+     }
+
+     /*
+      * Try to acquire creds for the old OV services as well as the
+      * new names, but if that fails just fall back on the new names.
+      */
+     if (svcauth_gssapi_set_names(names, 4) == TRUE)
+	  oldnames++;
+     if (!oldnames && svcauth_gssapi_set_names(names, 2) == FALSE) {
+	  krb5_klog_syslog(LOG_ERR,
+			   "Cannot set GSS-API authentication names (keytab not present?), "
+			   "failing.");
+	  fprintf(stderr, "%s: Cannot set GSS-API authentication names.\n",
+		  whoami);
+	  svcauth_gssapi_unset_names();
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);	  
+	  exit(1);
+     }
+
+     /* if set_names succeeded, this will too */
+     in_buf.value = names[1].name;
+     in_buf.length = strlen(names[1].name) + 1;
+     (void) gss_import_name(&OMret, &in_buf, nt_krb5_name_oid,
+			    &gss_changepw_name);
+     if (oldnames) {
+	  in_buf.value = names[3].name;
+	  in_buf.length = strlen(names[3].name) + 1;
+	  (void) gss_import_name(&OMret, &in_buf, nt_krb5_name_oid,
+				 &gss_oldchangepw_name);
+     }
+
+     svcauth_gssapi_set_log_badauth_func(log_badauth, NULL);
+     svcauth_gssapi_set_log_badverf_func(log_badverf, NULL);
+     svcauth_gssapi_set_log_miscerr_func(log_miscerr, NULL);
+     
+     svcauth_gss_set_log_badauth_func(log_badauth, NULL);
+     svcauth_gss_set_log_badverf_func(log_badverf, NULL);
+     svcauth_gss_set_log_miscerr_func(log_miscerr, NULL);
+     
+     if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE) {
+	 fprintf(stderr, "%s: Cannot initialize RPCSEC_GSS service name.\n",
+		 whoami);
+	 exit(1);
+     }
+
+     if ((ret = kadm5int_acl_init(context, 0, params.acl_file))) {
+	  errmsg = krb5_get_error_message (context, ret);
+	  krb5_klog_syslog(LOG_ERR, "Cannot initialize acl file: %s",
+		 errmsg);
+	  fprintf(stderr, "%s: Cannot initialize acl file: %s\n",
+		  whoami, errmsg);
+	  svcauth_gssapi_unset_names();
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);
+	  exit(1);
+     }
+
+     if (!nofork && (ret = daemon(0, 0))) {
+	  ret = errno;
+	  errmsg = krb5_get_error_message (context, ret);
+	  krb5_klog_syslog(LOG_ERR, "Cannot detach from tty: %s", errmsg);
+	  fprintf(stderr, "%s: Cannot detach from tty: %s\n",
+		  whoami, errmsg);
+	  svcauth_gssapi_unset_names();
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);
+	  exit(1);
+     }
+     
+     krb5_klog_syslog(LOG_INFO, "Seeding random number generator");
+     ret = krb5_c_random_os_entropy(context, 1, NULL);
+     if (ret) {
+	  krb5_klog_syslog(LOG_ERR, "Error getting random seed: %s, aborting",
+			   krb5_get_error_message(context, ret));
+	  svcauth_gssapi_unset_names();
+	  kadm5_destroy(global_server_handle);
+	  krb5_klog_close(context);
+	  exit(1);
+     }
+	  
+     setup_signal_handlers();
+     krb5_klog_syslog(LOG_INFO, "starting");
+     kadm_svc_run(¶ms);
+     krb5_klog_syslog(LOG_INFO, "finished, exiting");
+
+     /* Clean up memory, etc */
+     svcauth_gssapi_unset_names();
+     kadm5_destroy(global_server_handle);
+     close(s);
+     kadm5int_acl_finish(context, 0);
+     if(gss_changepw_name) {
+          (void) gss_release_name(&OMret, &gss_changepw_name);
+     }
+     if(gss_oldchangepw_name) {
+          (void) gss_release_name(&OMret, &gss_oldchangepw_name);
+     }
+     for(s = 0 ; s < 4; s++) {
+          if (names[s].name) {
+	        free(names[s].name);
+	  }
+     }
+
+     krb5_klog_close(context);
+     krb5_free_context(context);
+     exit(2);
+}
+
+/*
+ * Function: setup_signal_handlers
+ *
+ * Purpose: Setup signal handling functions using POSIX's sigaction()
+ * if possible, otherwise with System V's signal().
+ */
+
+void setup_signal_handlers(void) {
+#ifdef POSIX_SIGNALS
+     (void) sigemptyset(&s_action.sa_mask);
+     s_action.sa_handler = request_exit;
+     (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL);
+     (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL);
+     (void) sigaction(SIGQUIT, &s_action, (struct sigaction *) NULL);
+     s_action.sa_handler = request_hup;
+     (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL);
+     s_action.sa_handler = sig_pipe;
+     (void) sigaction(SIGPIPE, &s_action, (struct sigaction *) NULL);
+#ifdef PURIFY
+     s_action.sa_handler = request_pure_report;
+     (void) sigaction(SIGUSR1, &s_action, (struct sigaction *) NULL);
+     s_action.sa_handler = request_pure_clear;
+     (void) sigaction(SIGUSR2, &s_action, (struct sigaction *) NULL);
+#endif /* PURIFY */
+#else /* POSIX_SIGNALS */
+     signal(SIGINT, request_exit);
+     signal(SIGTERM, request_exit);
+     signal(SIGQUIT, request_exit);
+     signal(SIGHUP, request_hup);
+     signal(SIGPIPE, sig_pipe);
+#ifdef PURIFY
+     signal(SIGUSR1, request_pure_report);
+     signal(SIGUSR2, request_pure_clear);
+#endif /* PURIFY */
+#endif /* POSIX_SIGNALS */
+}
+
+/*
+ * Function: kadm_svc_run
+ * 
+ * Purpose: modified version of sunrpc svc_run.
+ *	    which closes the database every TIMEOUT seconds.
+ *
+ * Arguments:
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+
+void kadm_svc_run(params)
+kadm5_config_params *params;
+{
+     fd_set	rfd;
+     struct	timeval	    timeout;
+     
+     while(signal_request_exit == 0) {
+	  if (signal_request_hup) {
+	      reset_db();
+	      krb5_klog_reopen(context);
+	      signal_request_hup = 0;
+	  }
+#ifdef PURIFY
+	  if (signal_pure_report)	/* check to see if a report */
+					/* should be dumped... */
+	    {
+	      purify_new_reports();
+	      signal_pure_report = 0;
+	    }
+	  if (signal_pure_clear)	/* ...before checking whether */
+					/* the info should be cleared. */
+	    {
+	      purify_clear_new_reports();
+	      signal_pure_clear = 0;
+	    }
+#endif /* PURIFY */
+	  timeout.tv_sec = TIMEOUT;
+	  timeout.tv_usec = 0;
+	  rfd = svc_fdset;
+	  FD_SET(schpw, &rfd);
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+	  switch(select(max(schpw, svc_maxfd) + 1,
+			(fd_set *) &rfd, NULL, NULL, &timeout)) {
+	  case -1:
+	       if(errno == EINTR)
+		    continue;
+	       perror("select");
+	       return;
+	  case 0:
+	       reset_db();
+	       break;
+	  default:
+	      if (FD_ISSET(schpw, &rfd))
+		  do_schpw(schpw, params);
+	      else
+		  svc_getreqset(&rfd);
+	  }
+     }
+}
+
+#ifdef PURIFY
+/*
+ * Function: request_pure_report
+ * 
+ * Purpose: sets flag saying the server got a signal and that it should
+ *		dump a purify report when convenient.
+ *
+ * Arguments:
+ * Requires:
+ * Effects:
+ * Modifies:
+ *	sets signal_pure_report to one
+ */
+
+void request_pure_report(int signum)
+{
+     krb5_klog_syslog(LOG_DEBUG, "Got signal to request a Purify report");
+     signal_pure_report = 1;
+     return;
+}
+
+/*
+ * Function: request_pure_clear
+ * 
+ * Purpose: sets flag saying the server got a signal and that it should
+ *		dump a purify report when convenient, then clear the
+ *		purify tables.
+ *
+ * Arguments:
+ * Requires:
+ * Effects:
+ * Modifies:
+ *	sets signal_pure_report to one
+ *	sets signal_pure_clear to one
+ */
+
+void request_pure_clear(int signum)
+{
+     krb5_klog_syslog(LOG_DEBUG, "Got signal to request a Purify report and clear the old Purify info");
+     signal_pure_report = 1;
+     signal_pure_clear = 1;
+     return;
+}
+#endif /* PURIFY */
+
+/*
+ * Function: request_hup
+ * 
+ * Purpose: sets flag saying the server got a signal and that it should
+ *		reset the database files when convenient.
+ *
+ * Arguments:
+ * Requires:
+ * Effects:
+ * Modifies:
+ *	sets signal_request_hup to one
+ */
+
+void request_hup(int signum)
+{
+     signal_request_hup = 1;
+     return;
+}
+
+/*
+ * Function: reset_db
+ * 
+ * Purpose: flushes the currently opened database files to disk.
+ *
+ * Arguments:
+ * Requires:
+ * Effects:
+ * 
+ * Currently, just sets signal_request_reset to 0.  The kdb and adb
+ * libraries used to be sufficiently broken that it was prudent to
+ * close and reopen the databases periodically.  They are no longer
+ * that broken, so this function is not necessary.
+ */
+void reset_db(void)
+{
+#ifdef notdef
+     kadm5_ret_t ret;
+     char *errmsg;
+     
+     if (ret = kadm5_flush(global_server_handle)) {
+	  krb5_klog_syslog(LOG_ERR, "FATAL ERROR!  %s while flushing databases.  "
+		 "Databases may be corrupt!  Aborting.",
+		 krb5_get_error_message (context, ret));
+	  krb5_klog_close(context);
+	  exit(3);
+     }
+#endif
+
+     return;
+}
+
+/*
+ * Function: request_exit
+ * 
+ * Purpose: sets flags saying the server got a signal and that it
+ *	    should exit when convient.
+ *
+ * Arguments:
+ * Requires:
+ * Effects:
+ *	modifies signal_request_exit which ideally makes the server exit
+ *	at some point.
+ *
+ * Modifies:
+ *	signal_request_exit
+ */
+
+void request_exit(int signum)
+{
+     krb5_klog_syslog(LOG_DEBUG, "Got signal to request exit");
+     signal_request_exit = 1;
+     return;
+}
+
+/*
+ * Function: sig_pipe
+ *
+ * Purpose: SIGPIPE handler
+ *
+ * Effects: krb5_klog_syslogs a message that a SIGPIPE occurred and returns,
+ * thus causing the read() or write() to fail and, presumable, the RPC
+ * to recover.  Otherwise, the process aborts.
+ */
+void sig_pipe(int unused)
+{
+     krb5_klog_syslog(LOG_NOTICE, "Warning: Received a SIGPIPE; probably a "
+	    "client aborted.  Continuing.");
+     return;
+}
+
+/*
+ * Function: build_princ_name
+ * 
+ * Purpose: takes a name and a realm and builds a string that can be
+ *	    consumed by krb5_parse_name.
+ *
+ * Arguments:
+ *	name		    (input) name to be part of principal
+ *	realm		    (input) realm part of principal
+ * 	<return value>	    char * pointing to "name@realm"
+ *
+ * Requires:
+ *	name be non-null.
+ * 
+ * Effects:
+ * Modifies:
+ */
+
+char *build_princ_name(char *name, char *realm)
+{
+     char *fullname;
+
+     fullname = (char *) malloc(strlen(name) + 1 +
+				(realm ? strlen(realm) + 1 : 0));
+     if (fullname == NULL)
+	  return NULL;
+     if (realm)
+	  sprintf(fullname, "%s@%s", name, realm);
+     else
+	  strcpy(fullname, name);
+     return fullname;
+}
+
+/*
+ * Function: log_badverf
+ *
+ * Purpose: Call from GSS-API Sun RPC for garbled/forged/replayed/etc
+ * messages.
+ *
+ * Argiments:
+ * 	client_name	(r) GSS-API client name
+ * 	server_name	(r) GSS-API server name
+ * 	rqst		(r) RPC service request
+ * 	msg		(r) RPC message
+ * 	data		(r) arbitrary data (NULL), not used
+ *
+ * Effects:
+ *
+ * Logs the invalid request via krb5_klog_syslog(); see functional spec for
+ * format.
+ */
+void log_badverf(gss_name_t client_name, gss_name_t server_name,
+		 struct svc_req *rqst, struct rpc_msg *msg, char
+		 *data)
+{
+     struct procnames {
+	  rpcproc_t proc;
+	  const char *proc_name;
+     };
+     static const struct procnames proc_names[] = {
+	  {1, "CREATE_PRINCIPAL"},
+	  {2, "DELETE_PRINCIPAL"},
+	  {3, "MODIFY_PRINCIPAL"},
+	  {4, "RENAME_PRINCIPAL"},
+	  {5, "GET_PRINCIPAL"},
+	  {6, "CHPASS_PRINCIPAL"},
+	  {7, "CHRAND_PRINCIPAL"},
+	  {8, "CREATE_POLICY"},
+	  {9, "DELETE_POLICY"},
+	  {10, "MODIFY_POLICY"},
+	  {11, "GET_POLICY"},
+	  {12, "GET_PRIVS"},
+	  {13, "INIT"},
+	  {14, "GET_PRINCS"},
+	  {15, "GET_POLS"},
+	  {16, "SETKEY_PRINCIPAL"},
+	  {17, "SETV4KEY_PRINCIPAL"},
+	  {18, "CREATE_PRINCIPAL3"},
+	  {19, "CHPASS_PRINCIPAL3"},
+	  {20, "CHRAND_PRINCIPAL3"},
+	  {21, "SETKEY_PRINCIPAL3"}
+     };
+#define NPROCNAMES (sizeof (proc_names) / sizeof (struct procnames))
+     OM_uint32 minor;
+     gss_buffer_desc client, server;
+     gss_OID gss_type;
+     char *a;
+     rpcproc_t proc;
+     int i;
+     const char *procname;
+     size_t clen, slen;
+     char *cdots, *sdots;
+
+     client.length = 0;
+     client.value = NULL;
+     server.length = 0;
+     server.value = NULL;
+
+     (void) gss_display_name(&minor, client_name, &client, &gss_type);
+     (void) gss_display_name(&minor, server_name, &server, &gss_type);
+     if (client.value == NULL) {
+	 client.value = "(null)";
+	 clen = sizeof("(null)") -1;
+     } else {
+	 clen = client.length;
+     }
+     trunc_name(&clen, &cdots);
+     if (server.value == NULL) {
+	 server.value = "(null)";
+	 slen = sizeof("(null)") - 1;
+     } else {
+	 slen = server.length;
+     }
+     trunc_name(&slen, &sdots);
+     a = inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr);
+
+     proc = msg->rm_call.cb_proc;
+     procname = NULL;
+     for (i = 0; i < NPROCNAMES; i++) {
+	  if (proc_names[i].proc == proc) {
+	       procname = proc_names[i].proc_name;
+	       break;
+	  }
+     }
+     if (procname != NULL)
+	  krb5_klog_syslog(LOG_NOTICE, "WARNING! Forged/garbled request: %s, "
+			   "claimed client = %.*s%s, server = %.*s%s, addr = %s",
+			   procname, clen, client.value, cdots,
+			   slen, server.value, sdots, a);
+     else
+	  krb5_klog_syslog(LOG_NOTICE, "WARNING! Forged/garbled request: %d, "
+			   "claimed client = %.*s%s, server = %.*s%s, addr = %s",
+			   proc, clen, client.value, cdots,
+			   slen, server.value, sdots, a);
+
+     (void) gss_release_buffer(&minor, &client);
+     (void) gss_release_buffer(&minor, &server);
+}
+
+/*
+ * Function: log_miscerr
+ *
+ * Purpose: Callback from GSS-API Sun RPC for miscellaneous errors
+ *
+ * Arguments:
+ * 	rqst		(r) RPC service request
+ * 	msg		(r) RPC message
+ *	error		(r) error message from RPC
+ * 	data		(r) arbitrary data (NULL), not used
+ *
+ * Effects:
+ *
+ * Logs the error via krb5_klog_syslog(); see functional spec for
+ * format.
+ */
+void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg,
+		 char *error, char *data)
+{
+     char *a;
+     
+     a = inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr);
+     krb5_klog_syslog(LOG_NOTICE, "Miscellaneous RPC error: %s, %s", a, error);
+}
+
+
+
+/*
+ * Function: log_badauth
+ *
+ * Purpose: Callback from GSS-API Sun RPC for authentication
+ * failures/errors.
+ *
+ * Arguments:
+ * 	major 		(r) GSS-API major status
+ * 	minor		(r) GSS-API minor status
+ * 	addr		(r) originating address
+ * 	data		(r) arbitrary data (NULL), not used
+ *
+ * Effects:
+ *
+ * Logs the GSS-API error via krb5_klog_syslog(); see functional spec for
+ * format.
+ */
+void log_badauth(OM_uint32 major, OM_uint32 minor,
+		 struct sockaddr_in *addr, char *data)
+{
+     char *a;
+     
+     /* Authentication attempt failed: <IP address>, <GSS-API error */
+     /* strings> */
+
+     a = inet_ntoa(addr->sin_addr);
+
+     krb5_klog_syslog(LOG_NOTICE, "Authentication attempt failed: %s, GSS-API "
+	    "error strings are:", a);
+     log_badauth_display_status("   ", major, minor);
+     krb5_klog_syslog(LOG_NOTICE, "   GSS-API error strings complete.");
+}
+
+void log_badauth_display_status(char *msg, OM_uint32 major, OM_uint32 minor)
+{
+     log_badauth_display_status_1(msg, major, GSS_C_GSS_CODE, 0);
+     log_badauth_display_status_1(msg, minor, GSS_C_MECH_CODE, 0);
+}
+
+void log_badauth_display_status_1(char *m, OM_uint32 code, int type,
+				  int rec)
+{
+     OM_uint32 gssstat, minor_stat;
+     gss_buffer_desc msg;
+     OM_uint32 msg_ctx;
+
+     msg_ctx = 0;
+     while (1) {
+	  gssstat = gss_display_status(&minor_stat, code,
+				       type, GSS_C_NULL_OID,
+				       &msg_ctx, &msg);
+	  if (gssstat != GSS_S_COMPLETE) {
+ 	       if (!rec) {
+		    log_badauth_display_status_1(m,gssstat,GSS_C_GSS_CODE,1); 
+		    log_badauth_display_status_1(m, minor_stat,
+						 GSS_C_MECH_CODE, 1);
+	       } else
+		    krb5_klog_syslog(LOG_ERR, "GSS-API authentication error %s: "
+			   "recursive failure!", msg);
+	       return;
+	  }
+
+	  krb5_klog_syslog(LOG_NOTICE, "%s %s", m, (char *)msg.value); 
+	  (void) gss_release_buffer(&minor_stat, &msg);
+	  
+	  if (!msg_ctx)
+	       break;
+     }
+}
+
+void do_schpw(int s1, kadm5_config_params *params)
+{
+    krb5_error_code ret;
+    /* XXX buffer = ethernet mtu */
+    char req[1500];
+    int len;
+    struct sockaddr_in from;
+    socklen_t fromlen;
+    krb5_keytab kt;
+    krb5_data reqdata, repdata;
+    int s2;
+
+    fromlen = sizeof(from);
+    if ((len = recvfrom(s1, req, sizeof(req), 0, (struct sockaddr *)&from,
+			&fromlen)) < 0) {
+	krb5_klog_syslog(LOG_ERR, "chpw: Couldn't receive request: %s",
+			 krb5_get_error_message (context, errno));
+	return;
+    }
+
+    if ((ret = krb5_kt_resolve(context, "KDB:", &kt))) {
+	krb5_klog_syslog(LOG_ERR, "chpw: Couldn't open admin keytab %s",
+			 krb5_get_error_message (context, ret));
+	return;
+    }
+
+    reqdata.length = len;
+    reqdata.data = req;
+
+    /* this is really obscure.  s1 is used for all communications.  it
+       is left unconnected in case the server is multihomed and routes
+       are asymmetric.  s2 is connected to resolve routes and get
+       addresses.  this is the *only* way to get proper addresses for
+       multihomed hosts if routing is asymmetric.  
+
+       A related problem in the server, but not the client, is that
+       many os's have no way to disconnect a connected udp socket, so
+       the s2 socket needs to be closed and recreated for each
+       request.  The s1 socket must not be closed, or else queued
+       requests will be lost.
+
+       A "naive" client implementation (one socket, no connect,
+       hostname resolution to get the local ip addr) will work and
+       interoperate if the client is single-homed. */
+
+    if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	const char *errmsg = krb5_get_error_message (context, errno);
+	krb5_klog_syslog(LOG_ERR, "cannot create connecting socket: %s",
+			 errmsg);
+	fprintf(stderr, "Cannot create connecting socket: %s",
+		errmsg);
+	svcauth_gssapi_unset_names();
+	kadm5_destroy(global_server_handle);
+	krb5_klog_close(context);	  
+	exit(1);
+    }
+
+    if (connect(s2, (struct sockaddr *) &from, sizeof(from)) < 0) {
+	krb5_klog_syslog(LOG_ERR, "chpw: Couldn't connect to client: %s",
+			 krb5_get_error_message (context, errno));
+	goto cleanup;
+    }
+
+    if ((ret = process_chpw_request(context, global_server_handle,
+				    params->realm, s2, kt, &from,
+				    &reqdata, &repdata))) {
+	krb5_klog_syslog(LOG_ERR, "chpw: Error processing request: %s", 
+			 krb5_get_error_message (context, ret));
+    }
+
+    close(s2);
+
+    if (repdata.length == 0) {
+	/* just return.  This means something really bad happened */
+        goto cleanup;
+    }
+
+    len = sendto(s1, repdata.data, (int) repdata.length, 0,
+		 (struct sockaddr *) &from, sizeof(from));
+
+    if (len < (int) repdata.length) {
+	krb5_xfree(repdata.data);
+
+	krb5_klog_syslog(LOG_ERR, "chpw: Error sending reply: %s", 
+			 krb5_get_error_message (context, errno));
+	goto cleanup;
+    }
+
+    krb5_xfree(repdata.data);
+
+cleanup:
+    krb5_kt_close(context, kt);
+
+    return;
+}
diff --git a/krb5-1-6/src/kadmin/server/schpw.c b/krb5-1-6/src/kadmin/server/schpw.c
new file mode 100644
index 000000000..e974beb7b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/schpw.c
@@ -0,0 +1,411 @@
+#include "k5-int.h"
+#include <kadm5/admin.h>
+#include <syslog.h>
+#include <adm_proto.h>	/* krb5_klog_syslog */
+#include <stdio.h>
+#include <errno.h>
+
+#include "misc.h"
+
+#ifndef GETSOCKNAME_ARG3_TYPE
+#define GETSOCKNAME_ARG3_TYPE int
+#endif
+
+krb5_error_code
+process_chpw_request(context, server_handle, realm, s, keytab, sockin, 
+		     req, rep)
+     krb5_context context;
+     void *server_handle;
+     char *realm;
+     int s;
+     krb5_keytab keytab;
+     struct sockaddr_in *sockin;
+     krb5_data *req;
+     krb5_data *rep;
+{
+    krb5_error_code ret;
+    char *ptr;
+    int plen, vno;
+    krb5_address local_kaddr, remote_kaddr;
+    int allocated_mem = 0;  
+    krb5_data ap_req, ap_rep;
+    krb5_auth_context auth_context;
+    krb5_principal changepw;
+    krb5_ticket *ticket;
+    krb5_data cipher, clear;
+    struct sockaddr local_addr, remote_addr;
+    GETSOCKNAME_ARG3_TYPE addrlen;
+    krb5_replay_data replay;
+    krb5_error krberror;
+    int numresult;
+    char strresult[1024];
+    char *clientstr;
+    size_t clen;
+    char *cdots;
+
+    ret = 0;
+    rep->length = 0;
+
+    auth_context = NULL;
+    changepw = NULL;
+    ap_rep.length = 0;
+    ticket = NULL;
+    clear.length = 0;
+    cipher.length = 0;
+
+    if (req->length < 4) {
+	/* either this, or the server is printing bad messages,
+	   or the caller passed in garbage */
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	numresult = KRB5_KPASSWD_MALFORMED;
+	strcpy(strresult, "Request was truncated");
+	goto chpwfail;
+    }
+
+    ptr = req->data;
+
+    /* verify length */
+
+    plen = (*ptr++ & 0xff);
+    plen = (plen<<8) | (*ptr++ & 0xff);
+
+    if (plen != req->length)
+	return(KRB5KRB_AP_ERR_MODIFIED);
+
+    /* verify version number */
+
+    vno = (*ptr++ & 0xff) ;
+    vno = (vno<<8) | (*ptr++ & 0xff);
+
+    if (vno != 1) {
+	ret = KRB5KDC_ERR_BAD_PVNO;
+	numresult = KRB5_KPASSWD_BAD_VERSION;
+	sprintf(strresult,
+		"Request contained unknown protocol version number %d", vno);
+	goto chpwfail;
+    }
+
+    /* read, check ap-req length */
+
+    ap_req.length = (*ptr++ & 0xff);
+    ap_req.length = (ap_req.length<<8) | (*ptr++ & 0xff);
+
+    if (ptr + ap_req.length >= req->data + req->length) {
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	numresult = KRB5_KPASSWD_MALFORMED;
+	strcpy(strresult, "Request was truncated in AP-REQ");
+	goto chpwfail;
+    }
+
+    /* verify ap_req */
+
+    ap_req.data = ptr;
+    ptr += ap_req.length;
+
+    ret = krb5_auth_con_init(context, &auth_context);
+    if (ret) {
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed initializing auth context");
+	goto chpwfail;
+    }
+
+    ret = krb5_auth_con_setflags(context, auth_context,
+				 KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+    if (ret) {
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed initializing auth context");
+	goto chpwfail;
+    }
+	
+    ret = krb5_build_principal(context, &changepw, strlen(realm), realm,
+			       "kadmin", "changepw", NULL);
+    if (ret) {
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed building kadmin/changepw principal");
+	goto chpwfail;
+    }
+
+    ret = krb5_rd_req(context, &auth_context, &ap_req, changepw, keytab,
+		      NULL, &ticket);
+
+    if (ret) {
+	numresult = KRB5_KPASSWD_AUTHERROR;
+	strcpy(strresult, "Failed reading application request");
+	goto chpwfail;
+    }
+
+    /* set up address info */
+
+    addrlen = sizeof(local_addr);
+
+    if (getsockname(s, &local_addr, &addrlen) < 0) {
+	ret = errno;
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed getting server internet address");
+	goto chpwfail;
+    }
+
+    /* some brain-dead OS's don't return useful information from
+     * the getsockname call.  Namely, windows and solaris.  */
+
+    if (((struct sockaddr_in *)&local_addr)->sin_addr.s_addr != 0) {
+	local_kaddr.addrtype = ADDRTYPE_INET;
+	local_kaddr.length =
+	    sizeof(((struct sockaddr_in *) &local_addr)->sin_addr);
+	local_kaddr.contents = 
+	    (krb5_octet *) &(((struct sockaddr_in *) &local_addr)->sin_addr);
+    } else {
+	krb5_address **addrs;
+
+	krb5_os_localaddr(context, &addrs);
+	local_kaddr.magic = addrs[0]->magic;
+	local_kaddr.addrtype = addrs[0]->addrtype;
+	local_kaddr.length = addrs[0]->length;
+	local_kaddr.contents = malloc(addrs[0]->length);
+	memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
+	allocated_mem++;
+
+	krb5_free_addresses(context, addrs);
+    }
+
+    addrlen = sizeof(remote_addr);
+
+    if (getpeername(s, &remote_addr, &addrlen) < 0) {
+	ret = errno;
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed getting client internet address");
+	goto chpwfail;
+    }
+
+    remote_kaddr.addrtype = ADDRTYPE_INET;
+    remote_kaddr.length =
+	sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
+    remote_kaddr.contents = 
+	(krb5_octet *) &(((struct sockaddr_in *) &remote_addr)->sin_addr);
+    
+    remote_kaddr.addrtype = ADDRTYPE_INET;
+    remote_kaddr.length = sizeof(sockin->sin_addr);
+    remote_kaddr.contents = (krb5_octet *) &sockin->sin_addr;
+    
+    /* mk_priv requires that the local address be set.
+       getsockname is used for this.  rd_priv requires that the
+       remote address be set.  recvfrom is used for this.  If
+       rd_priv is given a local address, and the message has the
+       recipient addr in it, this will be checked.  However, there
+       is simply no way to know ahead of time what address the
+       message will be delivered *to*.  Therefore, it is important
+       that either no recipient address is in the messages when
+       mk_priv is called, or that no local address is passed to
+       rd_priv.  Both is a better idea, and I have done that.  In
+       summary, when mk_priv is called, *only* a local address is
+       specified.  when rd_priv is called, *only* a remote address
+       is specified.  Are we having fun yet?  */
+
+    ret = krb5_auth_con_setaddrs(context, auth_context, NULL,
+			     &remote_kaddr);
+    if (ret) {
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed storing client internet address");
+	goto chpwfail;
+    }
+
+    /* verify that this is an AS_REQ ticket */
+
+    if (!(ticket->enc_part2->flags & TKT_FLG_INITIAL)) {
+	numresult = KRB5_KPASSWD_AUTHERROR;
+	strcpy(strresult, "Ticket must be derived from a password");
+	goto chpwfail;
+    }
+
+    /* construct the ap-rep */
+
+    ret = krb5_mk_rep(context, auth_context, &ap_rep);
+    if (ret) {
+	numresult = KRB5_KPASSWD_AUTHERROR;
+	strcpy(strresult, "Failed replying to application request");
+	goto chpwfail;
+    }
+
+    /* decrypt the new password */
+
+    cipher.length = (req->data + req->length) - ptr;
+    cipher.data = ptr;
+
+    ret = krb5_rd_priv(context, auth_context, &cipher, &clear, &replay);
+    if (ret) {
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed decrypting request");
+	goto chpwfail;
+    }
+
+    ret = krb5_unparse_name(context, ticket->enc_part2->client, &clientstr);
+    if (ret) {
+	numresult = KRB5_KPASSWD_HARDERROR;
+	strcpy(strresult, "Failed unparsing client name for log");
+	goto chpwfail;
+    }
+    /* change the password */
+
+    ptr = (char *) malloc(clear.length+1);
+    memcpy(ptr, clear.data, clear.length);
+    ptr[clear.length] = '\0';
+
+    ret = schpw_util_wrapper(server_handle, ticket->enc_part2->client,
+			     ptr, NULL, strresult, sizeof(strresult));
+
+    /* zap the password */
+    memset(clear.data, 0, clear.length);
+    memset(ptr, 0, clear.length);
+    krb5_xfree(clear.data);
+    free(ptr);
+    clear.length = 0;
+
+    clen = strlen(clientstr);
+    trunc_name(&clen, &cdots);
+    krb5_klog_syslog(LOG_NOTICE, "chpw request from %s for %.*s%s: %s",
+		     inet_ntoa(((struct sockaddr_in *)&remote_addr)->sin_addr),
+		     clen, clientstr, cdots,
+		     ret ? krb5_get_error_message (context, ret) : "success");
+    krb5_free_unparsed_name(context, clientstr);
+
+    if (ret) {
+	if ((ret != KADM5_PASS_Q_TOOSHORT) && 
+	    (ret != KADM5_PASS_REUSE) && (ret != KADM5_PASS_Q_CLASS) && 
+	    (ret != KADM5_PASS_Q_DICT) && (ret != KADM5_PASS_TOOSOON))
+	    numresult = KRB5_KPASSWD_HARDERROR;
+	else
+	    numresult = KRB5_KPASSWD_SOFTERROR;
+	/* strresult set by kadb5_chpass_principal_util() */
+	goto chpwfail;
+    }
+
+    /* success! */
+
+    numresult = KRB5_KPASSWD_SUCCESS;
+    strcpy(strresult, "");
+
+chpwfail:
+
+    clear.length = 2 + strlen(strresult);
+    clear.data = (char *) malloc(clear.length);
+
+    ptr = clear.data;
+
+    *ptr++ = (numresult>>8) & 0xff;
+    *ptr++ = numresult & 0xff;
+
+    memcpy(ptr, strresult, strlen(strresult));
+
+    cipher.length = 0;
+
+    if (ap_rep.length) {
+	ret = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr,
+				     NULL);
+	if (ret) {
+	    numresult = KRB5_KPASSWD_HARDERROR;
+	    strcpy(strresult,
+		   "Failed storing client and server internet addresses");
+	} else {
+	    ret = krb5_mk_priv(context, auth_context, &clear, &cipher,
+			       &replay);
+	    if (ret) {
+		numresult = KRB5_KPASSWD_HARDERROR;
+		strcpy(strresult, "Failed encrypting reply");
+	    }
+	}
+    }
+
+    /* if no KRB-PRIV was constructed, then we need a KRB-ERROR.
+       if this fails, just bail.  there's nothing else we can do. */
+
+    if (cipher.length == 0) {
+	/* clear out ap_rep now, so that it won't be inserted in the
+           reply */
+
+	if (ap_rep.length) {
+	    krb5_xfree(ap_rep.data);
+	    ap_rep.length = 0;
+	}
+
+	krberror.ctime = 0;
+	krberror.cusec = 0;
+	krberror.susec = 0;
+	ret = krb5_timeofday(context, &krberror.stime);
+	if (ret)
+	    goto bailout;
+
+	/* this is really icky.  but it's what all the other callers
+	   to mk_error do. */
+	krberror.error = ret;
+	krberror.error -= ERROR_TABLE_BASE_krb5;
+	if (krberror.error < 0 || krberror.error > 128)
+	    krberror.error = KRB_ERR_GENERIC;
+
+	krberror.client = NULL;
+
+	ret = krb5_build_principal(context, &krberror.server,
+				   strlen(realm), realm,
+				   "kadmin", "changepw", NULL);
+	if (ret)
+	    goto bailout;
+	krberror.text.length = 0;
+	krberror.e_data = clear;
+
+	ret = krb5_mk_error(context, &krberror, &cipher);
+
+	krb5_free_principal(context, krberror.server);
+
+	if (ret)
+	    goto bailout;
+    }
+
+    /* construct the reply */
+
+    rep->length = 6 + ap_rep.length + cipher.length;
+    rep->data = (char *) malloc(rep->length);
+    ptr = rep->data;
+
+    /* length */
+
+    *ptr++ = (rep->length>>8) & 0xff;
+    *ptr++ = rep->length & 0xff;
+
+    /* version == 0x0001 big-endian */
+
+    *ptr++ = 0;
+    *ptr++ = 1;
+
+    /* ap_rep length, big-endian */
+
+    *ptr++ = (ap_rep.length>>8) & 0xff;
+    *ptr++ = ap_rep.length & 0xff;
+
+    /* ap-rep data */
+
+    if (ap_rep.length) {
+	memcpy(ptr, ap_rep.data, ap_rep.length);
+	ptr += ap_rep.length;
+    }
+
+    /* krb-priv or krb-error */
+
+    memcpy(ptr, cipher.data, cipher.length);
+
+bailout:
+    if (auth_context)
+	krb5_auth_con_free(context, auth_context);
+    if (changepw)
+	krb5_free_principal(context, changepw);
+    if (ap_rep.length)
+	krb5_xfree(ap_rep.data);
+    if (ticket)
+	krb5_free_ticket(context, ticket);
+    if (clear.length)
+	krb5_xfree(clear.data);
+    if (cipher.length)
+	krb5_xfree(cipher.data);
+    if (allocated_mem) 
+        krb5_xfree(local_kaddr.contents);
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/kadmin/server/server_glue_v1.c b/krb5-1-6/src/kadmin/server/server_glue_v1.c
new file mode 100644
index 000000000..dfd6430f1
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/server_glue_v1.c
@@ -0,0 +1,32 @@
+#define USE_KADM5_API_VERSION 1
+#include <kadm5/admin.h>
+#include "misc.h"
+
+/*
+ * In server_stubs.c, kadmind has to be able to call kadm5 functions
+ * with the arguments appropriate for any api version.  Because of the
+ * prototypes in admin.h, however, the compiler will only allow one
+ * set of arguments to be passed.  This file exports the old api
+ * definitions with a different name, so they can be called from
+ * server_stubs.c, and just passes on the call to the real api
+ * function; it uses the old api version, however, so it can actually
+ * call the real api functions whereas server_stubs.c cannot.
+ *
+ * This is most useful for functions like kadm5_get_principal that
+ * take a different number of arguments based on API version.  For
+ * kadm5_get_policy, the same thing could be accomplished with
+ * typecasts instead.
+ */
+
+kadm5_ret_t kadm5_get_principal_v1(void *server_handle,
+				  krb5_principal principal, 
+				  kadm5_principal_ent_t_v1 *ent)
+{
+     return kadm5_get_principal(server_handle, principal, ent);
+}
+
+kadm5_ret_t kadm5_get_policy_v1(void *server_handle, kadm5_policy_t name,
+				kadm5_policy_ent_t *ent)
+{
+     return kadm5_get_policy(server_handle, name, ent);
+}
diff --git a/krb5-1-6/src/kadmin/server/server_stubs.c b/krb5-1-6/src/kadmin/server/server_stubs.c
new file mode 100644
index 000000000..f09154045
--- /dev/null
+++ b/krb5-1-6/src/kadmin/server/server_stubs.c
@@ -0,0 +1,1663 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ */
+
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include <kadm5/server_internal.h>
+#include <kadm5/server_acl.h>
+#include <syslog.h>
+#include <arpa/inet.h>  /* inet_ntoa */
+#include <adm_proto.h>  /* krb5_klog_syslog */
+#include "misc.h"
+#include <string.h>
+
+#define LOG_UNAUTH  "Unauthorized request: %s, %s, client=%s, service=%s, addr=%s"
+#define	LOG_DONE    "Request: %s, %s, %s, client=%s, service=%s, addr=%s"
+
+extern gss_name_t 			gss_changepw_name;
+extern gss_name_t			gss_oldchangepw_name;
+extern void *				global_server_handle;
+
+#define CHANGEPW_SERVICE(rqstp) \
+	(cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), gss_changepw_name) |\
+	 (gss_oldchangepw_name && \
+	  cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), \
+			gss_oldchangepw_name)))
+
+
+static int gss_to_krb5_name(kadm5_server_handle_t handle,
+		     gss_name_t gss_name, krb5_principal *princ);
+
+static int gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str);
+
+static gss_name_t acceptor_name(gss_ctx_id_t context);
+
+static gss_name_t rqst2name(struct svc_req *rqstp);
+
+static int cmp_gss_names(gss_name_t n1, gss_name_t n2)
+{
+   OM_uint32 emaj, emin;
+   int equal;
+
+   if (GSS_ERROR(emaj = gss_compare_name(&emin, n1, n2, &equal)))
+      return(0);
+
+   return(equal);
+}
+
+/* Does a comparison of the names and then releases the first entity */
+/* For use above in CHANGEPW_SERVICE */
+static int cmp_gss_names_rel_1(gss_name_t n1, gss_name_t n2)
+{
+   OM_uint32 min_stat;
+   int ret;
+
+   ret = cmp_gss_names(n1, n2);
+   if (n1) (void) gss_release_name(&min_stat, &n1);
+   return ret;
+}
+
+/*
+ * Function check_handle
+ *
+ * Purpose: Check a server handle and return a com_err code if it is
+ * invalid or 0 if it is valid.
+ *
+ * Arguments:
+ *
+ * 	handle		The server handle.
+ */
+
+static int check_handle(void *handle)
+{
+     CHECK_HANDLE(handle);
+     return 0;
+}
+
+/*
+ * Function: new_server_handle
+ *
+ * Purpose: Constructs a server handle suitable for passing into the
+ * server library API functions, by folding the client's API version
+ * and calling principal into the server handle returned by
+ * kadm5_init.
+ *
+ * Arguments:
+ * 	api_version	(input) The API version specified by the client
+ * 	rqstp		(input) The RPC request
+ * 	handle		(output) The returned handle
+ *	<return value>	(output) An error code, or 0 if no error occurred
+ * 
+ * Effects:
+ * 	Returns a pointer to allocated storage containing the server
+ * 	handle.  If an error occurs, then no allocated storage is
+ *	returned, and the return value of the function will be a
+ * 	non-zero com_err code.
+ *      
+ *      The allocated storage for the handle should be freed with
+ * 	free_server_handle (see below) when it is no longer needed.
+ */
+
+static kadm5_ret_t new_server_handle(krb5_ui_4 api_version,
+					  struct svc_req *rqstp,
+					  kadm5_server_handle_t
+					  *out_handle)
+{
+     kadm5_server_handle_t handle;
+
+     if (! (handle = (kadm5_server_handle_t)
+	    malloc(sizeof(*handle))))
+	  return ENOMEM;
+
+     *handle = *(kadm5_server_handle_t)global_server_handle;
+     handle->api_version = api_version;
+
+     if (! gss_to_krb5_name(handle, rqst2name(rqstp),
+			    &handle->current_caller)) {
+	  free(handle);
+	  return KADM5_FAILURE;
+     }
+
+     *out_handle = handle;
+     return 0;
+}
+
+/*
+ * Function: free_server_handle
+ *
+ * Purpose: Free handle memory allocated by new_server_handle
+ *
+ * Arguments:
+ * 	handle		(input/output) The handle to free
+ */
+static void free_server_handle(kadm5_server_handle_t handle)
+{
+     krb5_free_principal(handle->context, handle->current_caller);
+     free(handle);
+}
+
+/*
+ * Function: setup_gss_names
+ *
+ * Purpose: Create printable representations of the client and server
+ * names.
+ *
+ * Arguments:
+ * 	rqstp		(r) the RPC request
+ * 	client_name	(w) the gss_buffer_t for the client name
+ * 	server_name	(w) the gss_buffer_t for the server name
+ *
+ * Effects:
+ *
+ * Unparses the client and server names into client_name and
+ * server_name, both of which must be freed by the caller.  Returns 0
+ * on success and -1 on failure.
+ */
+static 
+int setup_gss_names(struct svc_req *rqstp,
+		    gss_buffer_desc *client_name,
+		    gss_buffer_desc *server_name)
+{
+     OM_uint32 maj_stat, min_stat;
+     gss_name_t server_gss_name;
+
+     if (gss_name_to_string(rqst2name(rqstp), client_name) != 0)
+	  return -1;
+     maj_stat = gss_inquire_context(&min_stat, rqstp->rq_svccred, NULL,
+				    &server_gss_name, NULL, NULL, NULL,
+				    NULL, NULL);
+     if (maj_stat != GSS_S_COMPLETE) {
+	  gss_release_buffer(&min_stat, client_name);
+          gss_release_name(&min_stat, &server_gss_name);
+	  return -1;
+     }
+     if (gss_name_to_string(server_gss_name, server_name) != 0) {
+	  gss_release_buffer(&min_stat, client_name);
+          gss_release_name(&min_stat, &server_gss_name);
+	  return -1;
+     }
+     gss_release_name(&min_stat, &server_gss_name);
+     return 0;
+}
+
+static gss_name_t acceptor_name(gss_ctx_id_t context)
+{
+     OM_uint32 maj_stat, min_stat;
+     gss_name_t name;
+     
+     maj_stat = gss_inquire_context(&min_stat, context, NULL, &name,
+				    NULL, NULL, NULL, NULL, NULL);
+     if (maj_stat != GSS_S_COMPLETE)
+	  return NULL;
+     return name;
+}
+     
+static int cmp_gss_krb5_name(kadm5_server_handle_t handle,
+		      gss_name_t gss_name, krb5_principal princ)
+{
+     krb5_principal princ2;
+     int status;
+
+     if (! gss_to_krb5_name(handle, gss_name, &princ2))
+	  return 0;
+     status = krb5_principal_compare(handle->context, princ, princ2);
+     krb5_free_principal(handle->context, princ2);
+     return status;
+}
+
+static int gss_to_krb5_name(kadm5_server_handle_t handle,
+		     gss_name_t gss_name, krb5_principal *princ)
+{
+     OM_uint32 status, minor_stat;
+     gss_buffer_desc gss_str;
+     gss_OID gss_type;
+     int success;
+
+     status = gss_display_name(&minor_stat, gss_name, &gss_str, &gss_type);
+     if ((status != GSS_S_COMPLETE) || (gss_type != gss_nt_krb5_name))
+	  return 0;
+     success = (krb5_parse_name(handle->context, gss_str.value, princ) == 0);
+     gss_release_buffer(&minor_stat, &gss_str);
+     return success;
+}
+
+static int
+gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str)
+{
+     OM_uint32 status, minor_stat;
+     gss_OID gss_type;
+
+     status = gss_display_name(&minor_stat, gss_name, str, &gss_type);
+     if ((status != GSS_S_COMPLETE) || (gss_type != gss_nt_krb5_name))
+	  return 1;
+     return 0;
+}
+
+static int
+log_unauth(
+    char *op,
+    char *target,
+    gss_buffer_t client,
+    gss_buffer_t server,
+    struct svc_req *rqstp)
+{
+    size_t tlen, clen, slen;
+    char *tdots, *cdots, *sdots;
+
+    tlen = strlen(target);
+    trunc_name(&tlen, &tdots);
+    clen = client->length;
+    trunc_name(&clen, &cdots);
+    slen = server->length;
+    trunc_name(&slen, &sdots);
+
+    return krb5_klog_syslog(LOG_NOTICE,
+			    "Unauthorized request: %s, %.*s%s, "
+			    "client=%.*s%s, service=%.*s%s, addr=%s",
+			    op, tlen, target, tdots,
+			    clen, client->value, cdots,
+			    slen, server->value, sdots,
+			    inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+}
+
+static int
+log_done(
+    char *op,
+    char *target,
+    char *errmsg,
+    gss_buffer_t client,
+    gss_buffer_t server,
+    struct svc_req *rqstp)
+{
+    size_t tlen, clen, slen;
+    char *tdots, *cdots, *sdots;
+
+    tlen = strlen(target);
+    trunc_name(&tlen, &tdots);
+    clen = client->length;
+    trunc_name(&clen, &cdots);
+    slen = server->length;
+    trunc_name(&slen, &sdots);
+
+    return krb5_klog_syslog(LOG_NOTICE,
+			    "Request: %s, %.*s%s, %s, "
+			    "client=%.*s%s, service=%.*s%s, addr=%s",
+			    op, tlen, target, tdots, errmsg,
+			    clen, client->value, cdots,
+			    slen, server->value, sdots,
+			    inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+}
+
+generic_ret *
+create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		ret;
+    char			*prime_arg;
+    gss_buffer_desc		client_name, service_name;
+    OM_uint32			minor_stat;
+    kadm5_server_handle_t	handle;
+    restriction_t		*rp;
+    char			*errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (CHANGEPW_SERVICE(rqstp)
+	|| !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD,
+		      arg->rec.principal, &rp)
+	|| kadm5int_acl_impose_restrictions(handle->context,
+				   &arg->rec, &arg->mask, rp)) {
+	 ret.code = KADM5_AUTH_ADD;
+	 log_unauth("kadm5_create_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+    } else {
+	 ret.code = kadm5_create_principal((void *)handle,
+						&arg->rec, arg->mask,
+						arg->passwd);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_create_principal", prime_arg, errmsg,
+		  &client_name, &service_name, rqstp);
+
+	 /* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
+    }
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+
+ exit_func:
+    return &ret;
+}
+
+generic_ret *
+create_principal3_2_svc(cprinc3_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		ret;
+    char			*prime_arg;
+    gss_buffer_desc		client_name, service_name;
+    OM_uint32			minor_stat;
+    kadm5_server_handle_t	handle;
+    restriction_t		*rp;
+    char                        *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (CHANGEPW_SERVICE(rqstp)
+	|| !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD,
+		      arg->rec.principal, &rp)
+	|| kadm5int_acl_impose_restrictions(handle->context,
+				   &arg->rec, &arg->mask, rp)) {
+	 ret.code = KADM5_AUTH_ADD;
+	 log_unauth("kadm5_create_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+    } else {
+	 ret.code = kadm5_create_principal_3((void *)handle,
+					     &arg->rec, arg->mask,
+					     arg->n_ks_tuple,
+					     arg->ks_tuple,
+					     arg->passwd);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_create_principal", prime_arg, errmsg,
+		  &client_name, &service_name, rqstp);
+
+	 /* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
+    }
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+delete_principal_2_svc(dprinc_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+    
+    if (CHANGEPW_SERVICE(rqstp)
+	|| !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_DELETE,
+		      arg->princ, NULL)) {
+	 ret.code = KADM5_AUTH_DELETE;
+	 log_unauth("kadm5_delete_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+    } else {
+	 ret.code = kadm5_delete_principal((void *)handle, arg->princ);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_delete_principal", prime_arg, errmsg,
+		  &client_name, &service_name, rqstp);
+
+	 /* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
+    }
+    free(prime_arg);
+    free_server_handle(handle);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+ exit_func:
+
+    return &ret;
+}
+
+generic_ret *
+modify_principal_2_svc(mprinc_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    restriction_t		    *rp;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->rec.principal, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (CHANGEPW_SERVICE(rqstp)
+	|| !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY,
+		      arg->rec.principal, &rp)
+	|| kadm5int_acl_impose_restrictions(handle->context,
+				   &arg->rec, &arg->mask, rp)) {
+	 ret.code = KADM5_AUTH_MODIFY;
+	 log_unauth("kadm5_modify_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+    } else {
+	 ret.code = kadm5_modify_principal((void *)handle, &arg->rec,
+						arg->mask);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_modify_principal", prime_arg, errmsg,
+		  &client_name, &service_name, rqstp);
+
+	 /* no need to check for NULL. Even if it is NULL, atleast error_code will be returned */
+    }
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+rename_principal_2_svc(rprinc_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		ret;
+    char			*prime_arg1,
+				*prime_arg2;
+    gss_buffer_desc		client_name,
+				service_name;
+    OM_uint32			minor_stat;
+    kadm5_server_handle_t	handle;
+    restriction_t		*rp;
+    char                        *errmsg;
+    size_t			tlen1, tlen2, clen, slen;
+    char			*tdots1, *tdots2, *cdots, *sdots;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->src, &prime_arg1) ||
+        krb5_unparse_name(handle->context, arg->dest, &prime_arg2)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+    tlen1 = strlen(prime_arg1);
+    trunc_name(&tlen1, &tdots1);
+    tlen2 = strlen(prime_arg2);
+    trunc_name(&tlen2, &tdots2);
+    clen = client_name.length;
+    trunc_name(&clen, &cdots);
+    slen = service_name.length;
+    trunc_name(&slen, &sdots);
+
+    ret.code = KADM5_OK;
+    if (! CHANGEPW_SERVICE(rqstp)) {
+	 if (!kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			ACL_DELETE, arg->src, NULL))
+	      ret.code = KADM5_AUTH_DELETE;
+	 /* any restrictions at all on the ADD kills the RENAME */
+	 if (!kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			ACL_ADD, arg->dest, &rp) || rp) {
+	      if (ret.code == KADM5_AUTH_DELETE)
+		   ret.code = KADM5_AUTH_INSUFFICIENT;
+	      else
+		   ret.code = KADM5_AUTH_ADD;
+	 }
+    } else
+	 ret.code = KADM5_AUTH_INSUFFICIENT;
+    if (ret.code != KADM5_OK) {
+	 krb5_klog_syslog(LOG_NOTICE,
+			  "Unauthorized request: kadm5_rename_principal, "
+			  "%.*s%s to %.*s%s, "
+			  "client=%.*s%s, service=%.*s%s, addr=%s",
+			  tlen1, prime_arg1, tdots1,
+			  tlen2, prime_arg2, tdots2,
+			  clen, client_name.value, cdots,
+			  slen, service_name.value, sdots,
+			  inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+    } else {
+	 ret.code = kadm5_rename_principal((void *)handle, arg->src,
+						arg->dest);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 krb5_klog_syslog(LOG_NOTICE,
+			  "Request: kadm5_rename_principal, "
+			  "%.*s%s to %.*s%s, %s, "
+			  "client=%.*s%s, service=%.*s%s, addr=%s",
+			  tlen1, prime_arg1, tdots1,
+			  tlen2, prime_arg2, tdots2, errmsg,
+			  clen, client_name.value, cdots,
+			  slen, service_name.value, sdots,
+			  inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr));
+    }
+    free_server_handle(handle);
+    free(prime_arg1);
+    free(prime_arg2);    
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+gprinc_ret *
+get_principal_2_svc(gprinc_arg *arg, struct svc_req *rqstp)
+{
+    static gprinc_ret		    ret;
+    kadm5_principal_ent_t_v1	    e;
+    char			    *prime_arg, *funcname;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_gprinc_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    funcname = handle->api_version == KADM5_API_VERSION_1 ?
+	 "kadm5_get_principal (V1)" : "kadm5_get_principal";
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) &&
+	(CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+					       rqst2name(rqstp),
+					       ACL_INQUIRE,
+					       arg->princ,
+					       NULL))) {
+	 ret.code = KADM5_AUTH_GET;
+	 log_unauth(funcname, prime_arg,
+		    &client_name, &service_name, rqstp);
+    } else {
+	 if (handle->api_version == KADM5_API_VERSION_1) {
+	      ret.code  = kadm5_get_principal_v1((void *)handle,
+						 arg->princ, &e); 
+	      if(ret.code == KADM5_OK) {
+		   memcpy(&ret.rec, e, sizeof(kadm5_principal_ent_rec_v1));
+		   free(e);
+	      }
+	 } else {
+	      ret.code  = kadm5_get_principal((void *)handle,
+					      arg->princ, &ret.rec,
+					      arg->mask);
+	 }
+	 
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done(funcname, prime_arg, errmsg,
+		  &client_name, &service_name, rqstp);
+
+    }
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+gprincs_ret *
+get_princs_2_svc(gprincs_arg *arg, struct svc_req *rqstp)
+{
+    static gprincs_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_gprincs_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    prime_arg = arg->exp;
+    if (prime_arg == NULL)
+	 prime_arg = "*";
+
+    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+					      rqst2name(rqstp),
+					      ACL_LIST,
+					      NULL,
+					      NULL)) {
+	 ret.code = KADM5_AUTH_LIST;
+	 log_unauth("kadm5_get_principals", prime_arg,
+		    &client_name, &service_name, rqstp);
+    } else {
+	 ret.code  = kadm5_get_principals((void *)handle,
+					       arg->exp, &ret.princs,
+					       &ret.count);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_get_principals", prime_arg, errmsg,
+		  &client_name, &service_name, rqstp);
+
+    }
+    free_server_handle(handle);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+chpass_principal_2_svc(chpass_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
+	 ret.code = chpass_principal_wrapper_3((void *)handle, arg->princ,
+					       FALSE, 0, NULL, arg->pass);
+    } else if (!(CHANGEPW_SERVICE(rqstp)) &&
+	       kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			 ACL_CHANGEPW, arg->princ, NULL)) {
+	 ret.code = kadm5_chpass_principal((void *)handle, arg->princ,
+						arg->pass);
+    } else {
+	 log_unauth("kadm5_chpass_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_CHANGEPW;
+    }
+
+    if(ret.code != KADM5_AUTH_CHANGEPW) {
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	log_done("kadm5_chpass_principal", prime_arg, errmsg,
+		 &client_name, &service_name, rqstp);
+    }
+
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+chpass_principal3_2_svc(chpass3_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
+	 ret.code = chpass_principal_wrapper_3((void *)handle, arg->princ,
+					       arg->keepold,
+					       arg->n_ks_tuple,
+					       arg->ks_tuple,
+					       arg->pass);
+    } else if (!(CHANGEPW_SERVICE(rqstp)) &&
+	       kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			 ACL_CHANGEPW, arg->princ, NULL)) {
+	 ret.code = kadm5_chpass_principal_3((void *)handle, arg->princ,
+					     arg->keepold,
+					     arg->n_ks_tuple,
+					     arg->ks_tuple,
+					     arg->pass);
+    } else {
+	 log_unauth("kadm5_chpass_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_CHANGEPW;
+    }
+
+    if(ret.code != KADM5_AUTH_CHANGEPW) {
+	if( ret.code == 0 )
+	     errmsg = "success";
+	else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	log_done("kadm5_chpass_principal", prime_arg, errmsg,
+		 &client_name, &service_name, rqstp);
+    }
+
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+setv4key_principal_2_svc(setv4key_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (!(CHANGEPW_SERVICE(rqstp)) &&
+	       kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			 ACL_SETKEY, arg->princ, NULL)) {
+	 ret.code = kadm5_setv4key_principal((void *)handle, arg->princ,
+					     arg->keyblock);
+    } else {
+	 log_unauth("kadm5_setv4key_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_SETKEY;
+    }
+
+    if(ret.code != KADM5_AUTH_SETKEY) {
+	if( ret.code == 0 )
+	     errmsg = "success";
+	else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	log_done("kadm5_setv4key_principal", prime_arg, errmsg,
+		 &client_name, &service_name, rqstp);
+    }
+
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+setkey_principal_2_svc(setkey_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (!(CHANGEPW_SERVICE(rqstp)) &&
+	       kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			 ACL_SETKEY, arg->princ, NULL)) {
+	 ret.code = kadm5_setkey_principal((void *)handle, arg->princ,
+					   arg->keyblocks, arg->n_keys);
+    } else {
+	 log_unauth("kadm5_setkey_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_SETKEY;
+    }
+
+    if(ret.code != KADM5_AUTH_SETKEY) {
+	if( ret.code == 0 )
+	    errmsg = "success";
+	else
+	    errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	log_done("kadm5_setkey_principal", prime_arg, errmsg,
+		 &client_name, &service_name, rqstp);
+    }
+
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+setkey_principal3_2_svc(setkey3_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (!(CHANGEPW_SERVICE(rqstp)) &&
+	       kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			 ACL_SETKEY, arg->princ, NULL)) {
+	 ret.code = kadm5_setkey_principal_3((void *)handle, arg->princ,
+					     arg->keepold,
+					     arg->n_ks_tuple,
+					     arg->ks_tuple,
+					     arg->keyblocks, arg->n_keys);
+    } else {
+	 log_unauth("kadm5_setkey_principal", prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_SETKEY;
+    }
+
+    if(ret.code != KADM5_AUTH_SETKEY) {
+	if( ret.code == 0 )
+	    errmsg = "success";
+	else
+	    errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	log_done("kadm5_setkey_principal", prime_arg, errmsg,
+		 &client_name, &service_name, rqstp);
+    }
+
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+chrand_ret *
+chrand_principal_2_svc(chrand_arg *arg, struct svc_req *rqstp)
+{
+    static chrand_ret		ret;
+    krb5_keyblock		*k;
+    int				nkeys;
+    char			*prime_arg, *funcname;
+    gss_buffer_desc		client_name,
+	    			service_name;
+    OM_uint32			minor_stat;
+    kadm5_server_handle_t	handle;
+    char                        *errmsg;
+
+    xdr_free(xdr_chrand_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    funcname = handle->api_version == KADM5_API_VERSION_1 ?
+	 "kadm5_randkey_principal (V1)" : "kadm5_randkey_principal";
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
+	 ret.code = randkey_principal_wrapper_3((void *)handle, arg->princ,
+						FALSE, 0, NULL, &k, &nkeys);
+    } else if (!(CHANGEPW_SERVICE(rqstp)) &&
+	       kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			 ACL_CHANGEPW, arg->princ, NULL)) {
+	 ret.code = kadm5_randkey_principal((void *)handle, arg->princ,
+					    &k, &nkeys);
+    } else {
+	 log_unauth(funcname, prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_CHANGEPW;
+    }
+
+    if(ret.code == KADM5_OK) {
+	 if (handle->api_version == KADM5_API_VERSION_1) {
+	      krb5_copy_keyblock_contents(handle->context, k, &ret.key);
+	      krb5_free_keyblock(handle->context, k);
+	 } else {
+	      ret.keys = k;
+	      ret.n_keys = nkeys;
+	 }
+    }
+
+    if(ret.code != KADM5_AUTH_CHANGEPW) {
+	if( ret.code == 0 )
+	    errmsg = "success";
+	else
+	    errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	log_done(funcname, prime_arg, errmsg,
+		 &client_name, &service_name, rqstp);
+    }
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+chrand_ret *
+chrand_principal3_2_svc(chrand3_arg *arg, struct svc_req *rqstp)
+{
+    static chrand_ret		ret;
+    krb5_keyblock		*k;
+    int				nkeys;
+    char			*prime_arg, *funcname;
+    gss_buffer_desc		client_name,
+	    			service_name;
+    OM_uint32			minor_stat;
+    kadm5_server_handle_t	handle;
+    char                        *errmsg;
+
+    xdr_free(xdr_chrand_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    funcname = handle->api_version == KADM5_API_VERSION_1 ?
+	 "kadm5_randkey_principal (V1)" : "kadm5_randkey_principal";
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+	 ret.code = KADM5_BAD_PRINCIPAL;
+	 goto exit_func;
+    }
+
+    if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
+	 ret.code = randkey_principal_wrapper_3((void *)handle, arg->princ,
+						arg->keepold,
+						arg->n_ks_tuple,
+						arg->ks_tuple,
+						&k, &nkeys);
+    } else if (!(CHANGEPW_SERVICE(rqstp)) &&
+	       kadm5int_acl_check(handle->context, rqst2name(rqstp),
+			 ACL_CHANGEPW, arg->princ, NULL)) {
+	 ret.code = kadm5_randkey_principal_3((void *)handle, arg->princ,
+					      arg->keepold,
+					      arg->n_ks_tuple,
+					      arg->ks_tuple,
+					      &k, &nkeys);
+    } else {
+	 log_unauth(funcname, prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_CHANGEPW;
+    }
+
+    if(ret.code == KADM5_OK) {
+	 if (handle->api_version == KADM5_API_VERSION_1) {
+	      krb5_copy_keyblock_contents(handle->context, k, &ret.key);
+	      krb5_free_keyblock(handle->context, k);
+	 } else {
+	      ret.keys = k;
+	      ret.n_keys = nkeys;
+	 }
+    }
+
+    if(ret.code != KADM5_AUTH_CHANGEPW) {
+	if( ret.code == 0 )
+	    errmsg = "success";
+	else
+	    errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	log_done(funcname, prime_arg, errmsg,
+		 &client_name, &service_name, rqstp);
+    }
+    free_server_handle(handle);
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+create_policy_2_svc(cpol_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;    
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    prime_arg = arg->rec.policy;
+
+    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+					      rqst2name(rqstp),
+					      ACL_ADD, NULL, NULL)) {
+	 ret.code = KADM5_AUTH_ADD;
+	 log_unauth("kadm5_create_policy", prime_arg,
+		    &client_name, &service_name, rqstp);
+
+    } else {
+	 ret.code = kadm5_create_policy((void *)handle, &arg->rec,
+					     arg->mask);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_create_policy",
+		  ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+		  &client_name, &service_name, rqstp);
+    }
+    free_server_handle(handle);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+delete_policy_2_svc(dpol_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;    
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    prime_arg = arg->name;
+    
+    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+					      rqst2name(rqstp),
+					      ACL_DELETE, NULL, NULL)) {
+	 log_unauth("kadm5_delete_policy", prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_DELETE;
+    } else {
+	 ret.code = kadm5_delete_policy((void *)handle, arg->name);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_delete_policy",
+		  ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+		  &client_name, &service_name, rqstp);
+    }
+    free_server_handle(handle);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+generic_ret *
+modify_policy_2_svc(mpol_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;    
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    prime_arg = arg->rec.policy;
+
+    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+					      rqst2name(rqstp),
+					      ACL_MODIFY, NULL, NULL)) {
+	 log_unauth("kadm5_modify_policy", prime_arg,
+		    &client_name, &service_name, rqstp);
+	 ret.code = KADM5_AUTH_MODIFY;
+    } else {
+	 ret.code = kadm5_modify_policy((void *)handle, &arg->rec,
+					     arg->mask);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_modify_policy",
+		  ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+		  &client_name, &service_name, rqstp);
+    }
+    free_server_handle(handle);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+gpol_ret * 
+get_policy_2_svc(gpol_arg *arg, struct svc_req *rqstp)
+{
+    static gpol_ret		ret;
+    kadm5_ret_t		ret2;
+    char			*prime_arg, *funcname;
+    gss_buffer_desc		client_name,
+				service_name;
+    OM_uint32			minor_stat;    
+    kadm5_policy_ent_t	e;
+    kadm5_principal_ent_rec	caller_ent;
+    kadm5_server_handle_t	handle;
+    char                        *errmsg;
+
+    xdr_free(xdr_gpol_ret,  &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    funcname = handle->api_version == KADM5_API_VERSION_1 ?
+	 "kadm5_get_policy (V1)" : "kadm5_get_policy";
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    prime_arg = arg->name;
+
+    ret.code = KADM5_AUTH_GET;
+    if (!CHANGEPW_SERVICE(rqstp) && kadm5int_acl_check(handle->context,
+					      rqst2name(rqstp),
+					      ACL_INQUIRE, NULL, NULL))
+	 ret.code = KADM5_OK;
+    else {
+	 ret.code = kadm5_get_principal(handle->lhandle,
+					handle->current_caller,
+					&caller_ent,
+					KADM5_PRINCIPAL_NORMAL_MASK);
+	 if (ret.code == KADM5_OK) {
+	      if (caller_ent.aux_attributes & KADM5_POLICY &&
+		  strcmp(caller_ent.policy, arg->name) == 0) {
+		   ret.code = KADM5_OK;
+	      } else ret.code = KADM5_AUTH_GET;
+	      ret2 = kadm5_free_principal_ent(handle->lhandle,
+					      &caller_ent);
+	      ret.code = ret.code ? ret.code : ret2;
+	 }
+    }
+    
+    if (ret.code == KADM5_OK) {
+	 if (handle->api_version == KADM5_API_VERSION_1) {
+	      ret.code  = kadm5_get_policy_v1((void *)handle, arg->name, &e);
+	      if(ret.code == KADM5_OK) {
+		   memcpy(&ret.rec, e, sizeof(kadm5_policy_ent_rec));
+		   free(e);
+	      }
+	 } else {
+	      ret.code = kadm5_get_policy((void *)handle, arg->name,
+					  &ret.rec);
+	 }
+	 
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done(funcname,
+		  ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
+		  &client_name, &service_name, rqstp);
+    } else {
+	 log_unauth(funcname, prime_arg,
+		    &client_name, &service_name, rqstp);
+    }
+    free_server_handle(handle);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+
+}
+
+gpols_ret *
+get_pols_2_svc(gpols_arg *arg, struct svc_req *rqstp)
+{
+    static gpols_ret		    ret;
+    char			    *prime_arg;
+    gss_buffer_desc		    client_name,
+				    service_name;
+    OM_uint32			    minor_stat;
+    kadm5_server_handle_t	    handle;
+    char                            *errmsg;
+
+    xdr_free(xdr_gpols_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+	 goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle))) {
+	 free_server_handle(handle);
+	 goto exit_func;
+    }
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	 ret.code = KADM5_FAILURE;
+	 goto exit_func;
+    }
+    prime_arg = arg->exp;
+    if (prime_arg == NULL)
+	 prime_arg = "*";
+
+    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+					      rqst2name(rqstp),
+					      ACL_LIST, NULL, NULL)) {
+	 ret.code = KADM5_AUTH_LIST;
+	 log_unauth("kadm5_get_policies", prime_arg,
+		    &client_name, &service_name, rqstp);
+    } else {
+	 ret.code  = kadm5_get_policies((void *)handle,
+					       arg->exp, &ret.pols,
+					       &ret.count);
+	 if( ret.code == 0 )
+	     errmsg = "success";
+	 else
+	     errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+	 log_done("kadm5_get_policies", prime_arg, errmsg,
+		  &client_name, &service_name, rqstp);
+    }
+    free_server_handle(handle);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    return &ret;
+}
+
+getprivs_ret * get_privs_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
+{
+     static getprivs_ret	    ret;
+     gss_buffer_desc		    client_name, service_name;
+     OM_uint32			    minor_stat;
+     kadm5_server_handle_t	    handle;
+     char                           *errmsg;
+
+     xdr_free(xdr_getprivs_ret, &ret);
+
+     if ((ret.code = new_server_handle(*arg, rqstp, &handle)))
+	  goto exit_func;
+
+     if ((ret.code = check_handle((void *)handle))) {
+	  free_server_handle(handle);
+	  goto exit_func;
+     }
+
+     ret.api_version = handle->api_version;
+
+     if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	  ret.code = KADM5_FAILURE;
+	  goto exit_func;
+     }
+
+     ret.code = kadm5_get_privs((void *)handle, &ret.privs);
+     if( ret.code == 0 )
+	 errmsg = "success";
+     else
+	 errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+
+     log_done("kadm5_get_privs", client_name.value, errmsg,
+	      &client_name, &service_name, rqstp);
+
+     free_server_handle(handle);
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+     return &ret;
+}
+
+generic_ret *init_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
+{
+     static generic_ret		ret;
+     gss_buffer_desc		client_name,
+	 			service_name;
+     kadm5_server_handle_t	handle;
+     OM_uint32			minor_stat;
+     char                       *errmsg = 0;
+     size_t clen, slen;
+     char *cdots, *sdots;
+
+     xdr_free(xdr_generic_ret, &ret);
+
+     if ((ret.code = new_server_handle(*arg, rqstp, &handle)))
+	  goto exit_func;
+     if (! (ret.code = check_handle((void *)handle))) {
+	 ret.api_version = handle->api_version;
+     }
+
+     free_server_handle(handle);
+
+     if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+	  ret.code = KADM5_FAILURE;
+	  goto exit_func;
+     }
+
+     if (ret.code != 0)
+	 errmsg = krb5_get_error_message(handle ? handle->context : NULL, ret.code);
+     else
+	 errmsg = "success";
+
+     clen = client_name.length;
+     trunc_name(&clen, &cdots);
+     slen = service_name.length;
+     trunc_name(&slen, &sdots);
+     krb5_klog_syslog(LOG_NOTICE, "Request: %s, %.*s%s, %s, "
+		      "client=%.*s%s, service=%.*s%s, addr=%s, flavor=%d",
+		      (ret.api_version == KADM5_API_VERSION_1 ?
+		       "kadm5_init (V1)" : "kadm5_init"),
+		      clen, client_name.value, cdots, errmsg,
+		      clen, client_name.value, cdots,
+		      slen, service_name.value, sdots,
+		      inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
+		      rqstp->rq_cred.oa_flavor);
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+	    
+exit_func:
+     return(&ret);
+}
+
+static gss_name_t
+rqst2name(struct svc_req *rqstp)
+{
+
+     if (rqstp->rq_cred.oa_flavor == RPCSEC_GSS)
+	  return rqstp->rq_clntname;
+     else
+	  return rqstp->rq_clntcred;
+}
diff --git a/krb5-1-6/src/kadmin/testing/Makefile.in b/krb5-1-6/src/kadmin/testing/Makefile.in
new file mode 100644
index 000000000..74600d1c9
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/Makefile.in
@@ -0,0 +1,10 @@
+thisconfigdir=../..
+myfulldir=kadmin/testing
+mydir=kadmin/testing
+BUILDTOP=$(REL)..$(S)..
+LOCAL_SUBDIRS = scripts util
+
+all::
+
+clean::
+	-$(RM) -r krb5-test-root
diff --git a/krb5-1-6/src/kadmin/testing/proto/kdc.conf.proto b/krb5-1-6/src/kadmin/testing/proto/kdc.conf.proto
new file mode 100644
index 000000000..6f9edeb5b
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/proto/kdc.conf.proto
@@ -0,0 +1,16 @@
+[kdcdefaults]
+	kdc_ports = 1750 
+
+[realms]
+	__REALM__ = {
+		profile = __K5ROOT__/krb5.conf
+		database_name = __K5ROOT__/kdb5
+		admin_keytab = __K5ROOT__/ovsec_adm.srvtab
+		key_stash_file = __K5ROOT__/.k5.__REALM__
+		acl_file = __K5ROOT__/ovsec_adm.acl
+		dict_file = __K5ROOT__/ovsec_adm.dict
+		kadmind_port = 1751
+		kpasswd_port = 1752
+		master_key_type = des3-hmac-sha1
+		supported_enctypes = des3-hmac-sha1:normal des-cbc-crc:normal des-cbc-crc:v4 des-cbc-md5:normal des-cbc-raw:normal
+	}
diff --git a/krb5-1-6/src/kadmin/testing/proto/krb5.conf.proto b/krb5-1-6/src/kadmin/testing/proto/krb5.conf.proto
new file mode 100644
index 000000000..c2648d6c6
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/proto/krb5.conf.proto
@@ -0,0 +1,29 @@
+[libdefaults]
+	default_realm = __REALM__
+	default_keytab_name = FILE:__K5ROOT__/v5srvtab
+	dns_fallback = no
+
+[realms]
+	__REALM__ = {
+		kdc = __KDCHOST__:1750
+		admin_server = __KDCHOST__:1751
+		database_module = foobar_db2_module_blah
+	}
+
+[domain_realm]
+	__LOCALHOST__ = __REALM__
+	__KDCHOST__ = __REALM__
+
+[logging]
+	admin_server = FILE:__K5ROOT__/syslog
+	kdc = FILE:__K5ROOT__/syslog
+	default = FILE:__K5ROOT__/syslog
+
+
+# THIS SHOULD BE IN KDC.CONF INSTEAD!
+[dbmodules]
+	db_module_dir = __MODDIR__
+	foobar_db2_module_blah = {
+		db_library = db2
+		database_name = __K5ROOT__/kdb5
+	}
diff --git a/krb5-1-6/src/kadmin/testing/proto/ovsec_adm.dict b/krb5-1-6/src/kadmin/testing/proto/ovsec_adm.dict
new file mode 100644
index 000000000..b54e3a85e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/proto/ovsec_adm.dict
@@ -0,0 +1,3 @@
+Abyssinia
+Discordianism
+foo
diff --git a/krb5-1-6/src/kadmin/testing/scripts/Makefile.in b/krb5-1-6/src/kadmin/testing/scripts/Makefile.in
new file mode 100644
index 000000000..6161b1db8
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/Makefile.in
@@ -0,0 +1,37 @@
+thisconfigdir=../../..
+myfulldir=kadmin/testing/scripts
+mydir=kadmin/testing/scripts
+BUILDTOP=$(REL)..$(S)..$(S)..
+PERL_PATH=@PERL_PATH@
+
+.SUFFIXES: .plin .pl
+
+GEN_SCRIPTS = compare_dump.pl fixup-conf-files.pl make-host-keytab.pl \
+	simple_dump.pl verify_xrunner_report.pl qualname.pl
+
+all:: env-setup.sh $(GEN_SCRIPTS) restore_files.sh 
+
+# Should only rebuild env_setup.sh here (use CONFIG_FILES=), but the weird krb5
+# makefile post-processing is unconditional and would trash the makefile.
+env-setup.sh: env-setup.stamp
+env-setup.stamp: $(srcdir)/env-setup.shin $(thisconfigdir)/config.status \
+		Makefile 
+	cd $(thisconfigdir) && \
+		CONFIG_FILES=$(mydir)/env-setup.sh:$(mydir)/env-setup.shin $(SHELL) \
+		config.status
+	chmod +x env-setup.sh
+	touch env-setup.stamp
+
+restore_files.sh:
+	rm -f restore_files.sh
+	ln -s $(srcdir)/save_files.sh restore_files.sh
+
+.plin.pl: 
+	-rm -f $@.tmp
+	echo "#!$(PERL_PATH)" > $@.tmp
+	sed 1d $< >> $@.tmp
+	chmod +x $@.tmp
+	mv $@.tmp $@
+
+clean::
+	-rm -f $(GEN_SCRIPTS) *.tmp env-setup.sh env-setup.stamp restore_files.sh
diff --git a/krb5-1-6/src/kadmin/testing/scripts/compare_dump.plin b/krb5-1-6/src/kadmin/testing/scripts/compare_dump.plin
new file mode 100755
index 000000000..df93df4a0
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/compare_dump.plin
@@ -0,0 +1,242 @@
+#!/usr/local/bin/perl
+
+#
+# $Id$
+#
+
+# $debug = 1;
+
+sub usage { die "usage: $0 before after changes\n";}
+
+sub unique {
+    local(@list) = @_;
+    local(%ary);
+
+    print "unique? ",join(" ",@list),"\n" if $debug;
+
+    foreach (@list) {
+	return(0) if $ary{$_}++;
+    }
+
+    1;
+}
+
+$before = shift(@ARGV) || &usage;
+$debug++ if $before =~ /^-d/;
+$before = shift(@ARGV) || &usage if $debug;
+$after = shift(@ARGV) || &usage;
+$changes = shift(@ARGV) || &usage;
+@ARGV && &usage;
+
+%policy =
+    (
+     "FIRST",2,
+     "pw_min_life",2,
+     "pw_max_life",3,
+     "pw_min_length",4,
+     "pw_min_classes",5,
+     "pw_history_num",6,
+     "policy_refcnt",7,
+     "LAST",7,
+     );
+
+%princ =
+    (
+     "FIRST",2,
+     "kvno",2,
+     "mod_name",3,
+     "max_life",4,
+     "princ_expire_time",5,
+     "expiration",5,
+     "pw_expiration",6,
+     "attributes",7,
+     "policy",8,
+     "aux_attributes",9,
+     "LAST",9,
+     );
+
+%keytab =
+    (
+     "LAST",-1,
+     );
+
+sub re { # @_ = ($cnt, $line)
+    local($cnt, $line) = @_;
+    local(@fields) = split(' ',$line);
+
+    @list = ('\S+') x $cnt;
+    for $f (@fields[3..$#fields]) {
+	($f =~ /=/) || die "Bad field: $f in $_";
+	if (!defined($this{$`})) { die "Bad parameter $` in $_"; }
+
+        if (($list[$this{$`}] = $') eq '\S+') {
+	    $list[$this{$`}] = '[^\s]+';
+	}
+    }
+    
+    join('\s+',@list)."\$";
+}
+
+open(CHANGES, $changes) || die "Couldn't open $changes: $!\n";
+
+while(<CHANGES>) {
+    next if s/^\s*\#\#\!\s*\#//;
+    next if !s/^\s*\#\#\!\s*//;
+
+    split;
+
+    if ($_[1] =~ /princ/) {
+	%this = %princ;
+	$this = "princ";
+    } elsif ($_[1] =~ /policy/) {
+	%this = %policy;
+	$this = "policy";
+    } elsif ($_[1] =~ /keytab/) {
+	%this = %keytab;
+	$this = $_[1];
+    } else {
+	die "Bad line: $_";
+    }
+
+    $cnt = $this{"LAST"}+1;
+
+    if ($_[0] =~ /add/) {
+	$diff{"+$this\t$_[2]"} = &re($cnt,$_);
+    } elsif ($_[0] =~ /delete/) {
+	$diff{"-$this\t$_[2]"} = &re($cnt,$_);
+    } elsif ($_[0] =~ /changefrom/) {
+	$diff{"-$this\t$_[2]"} = &re($cnt,$_);
+    } elsif ($_[0] =~ /changeto/) {
+	$ndiff{"-$this\t$_[2]"} = &re($cnt,$_);
+    } else {
+	die "Bad line: $_";
+    }
+}
+
+close(CHANGES);
+
+if ($debug) {
+    for (keys %diff) {
+	print " %diff: \"$_\" /$diff{$_}/\n";
+    }
+
+    for (keys %ndiff) {
+	print "%ndiff: \"$_\" /$ndiff{$_}/\n";
+    }
+
+    print "\n";
+}
+
+open(DIFF,"gdiff -u0 $before $after|") || die "Couldn't diff: $!\n";
+
+$warnings = 0;
+
+while(<DIFF>) {
+    next if /^\+{3}/;
+    next if /^\-{3}/;
+    next if /^@@/;
+
+    print "LINE: $_" if $debug;
+
+    split;
+
+    $key = "$_[0]\t$_[1]";
+    $re = $diff{$key};
+
+    delete $diff{$key};
+
+    print "%diff: \"$key\" /$re/\n" if $debug;
+
+    if (!$re) {
+	warn "Unexpected: \"$key\"\n";
+	$warnings++;
+	next;
+    }
+
+    if (!/$re/) {
+	warn "Failed: $key\n";
+	$warnings++;
+	next;
+    }
+
+    if ($new = $ndiff{$key}) {
+	delete $ndiff{$key};
+
+	@new = split(/\\s\+/, $new);
+	for ($i=1;$i<@new;$i++) {
+	    print "NEW: $new[$i]\n" if $debug;
+
+	    if ($new[$i] ne '\S+') {
+		$_[$i] = $new[$i];
+	    }
+	}
+	$_[0] =~ s/^\-//;
+	$key =~ s/^\-/\+/;
+
+	$diff{$key} = join("\t",@_);
+    }
+}
+
+close(DIFF);
+
+open(BEFORE, $before) || die "Couldn't open $before: $!\n";
+
+while(<BEFORE>) {
+    next if !/^keytab/;
+
+    split;
+
+    if (!$seen{$key = $_[0]." ".$_[1]}++) {
+	$key =~ s/-\d+$//;
+	$ktkeys{$key} .= " ".$_[2];
+	$kttimes{$key} .= " ".$_[3];
+    }
+}
+
+close(BEFORE);
+
+open(AFTER, $after) || die "Couldn't open $after: $!\n";
+
+while(<AFTER>) {
+    next if !/^keytab/;
+
+    split;
+
+    if (!$seen{$key = $_[0]." ".$_[1]}++) {
+	$key =~ s/-\d+$//;
+	$ktkeys{$key} .= " ".$_[2];
+	$kttimes{$key} .= " ".$_[3];
+    }
+}
+
+close(AFTER);
+
+for (keys %diff) {
+    warn "Unseen: \"$_\" /$diff{$_}/\n";
+    $warnings++;
+}
+
+for (keys %ndiff) {
+    warn "Unseen changes: \"$_\" /$ndiff{$_}/\n";
+    $warnings++;
+}
+
+for (keys %ktkeys) {
+    if (!&unique(split(' ',$ktkeys{$_}))) {
+	warn "Some keys not unique for $_\n";
+	$warnings++;
+    }
+}
+
+for (keys %kttimes) {
+    if (!&unique(split(' ',$kttimes{$_}))) {
+	warn "Some timestamps not unique for $_\n";
+	$warnings++;
+    }
+}
+
+if ($warnings) {
+    warn "$warnings warnings.\n";
+}
+
+exit($warnings);
diff --git a/krb5-1-6/src/kadmin/testing/scripts/env-setup.shin b/krb5-1-6/src/kadmin/testing/scripts/env-setup.shin
new file mode 100755
index 000000000..03e6d065e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/env-setup.shin
@@ -0,0 +1,118 @@
+#!/bin/sh
+#
+# The KADM5 unit tests were developed to work under gmake.  As a
+# result, they expect to inherit a number of environment variables.
+# Rather than rewrite the tests, we simply use this script as an
+# execution wrapper that sets all the necessary environment variables
+# before running the program specified on its command line.
+#
+# The variable settings all came from OV's config.mk.
+#
+# Usage: env-setup.sh <command line>
+#
+
+TOP=@RBUILD@/kadmin
+STOP=@S_TOP@/kadmin
+export TOP
+export STOP
+# These two may be needed in case $libdir references them.
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@ ; eval "libdir=$libdir"; export libdir
+
+# The shared library run time setup
+TOPLIBD=@RBUILD@/lib
+PROG_LIBPATH=-L@RBUILD@/lib
+BUILDTOP=@RBUILD@
+# XXX kludge!
+PROG_RPATH=@RBUILD@/lib
+# XXX more kludge!
+FAKEDEST=@RBUILD@/util/fakedest
+# This converts $(TOPLIBD) to $TOPLIBD
+cat > /tmp/env_setup$$ <<\EOF
+@KRB5_RUN_ENV@
+EOF
+
+foo=`sed -e 's/(//g' -e 's/)//g' -e 's/\\\$\\\$/\$/g' /tmp/env_setup$$`
+eval $foo
+
+# This will get put in setup.csh for convenience
+KRB5_RUN_ENV_CSH=`eval echo "$foo" | \
+	sed -e 's/\([^=]*\)=\(.*\)/setenv \1 \2/g' \
+	-e 's/export [^ ;]*;//g'`
+export KRB5_RUN_ENV_CSH
+rm /tmp/env_setup$$
+
+TESTDIR=$TOP/testing; export TESTDIR
+STESTDIR=$STOP/testing; export STESTDIR
+if [ "$K5ROOT" = "" ]; then
+	K5ROOT="`cd $TESTDIR; pwd`/krb5-test-root"
+	export K5ROOT
+fi
+
+# If $VERBOSE_TEST is non-null, enter verbose mode.  Set $VERBOSE to
+# true or false so its exit status identifies the mode.
+if test x$VERBOSE_TEST = x; then
+	VERBOSE=false
+else
+	VERBOSE=true
+fi
+export VERBOSE
+
+REALM=SECURE-TEST.OV.COM; export REALM
+
+if test x$EXPECT = x; then
+    EXPECT=@EXPECT@; export EXPECT
+fi
+
+COMPARE_DUMP=$TESTDIR/scripts/compare_dump.pl; export COMPARE_DUMP
+FIX_CONF_FILES=$TESTDIR/scripts/fixup-conf-files.pl
+export FIX_CONF_FILES
+INITDB=$STESTDIR/scripts/init_db; export INITDB
+MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl; export MAKE_KEYTAB
+LOCAL_MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl
+export LOCAL_MAKE_KEYTAB
+RESTORE_FILES=$TESTDIR/scripts/restore_files.sh; export RESTORE_FILES
+SAVE_FILES=$STESTDIR/scripts/save_files.sh; export SAVE_FILES
+SIMPLE_DUMP=$TESTDIR/scripts/simple_dump.pl; export SIMPLE_DUMP
+QUALNAME=$TESTDIR/scripts/qualname.pl; export QUALNAME
+TCLUTIL=$STESTDIR/tcl/util.t; export TCLUTIL
+BSDDB_DUMP=$TESTDIR/util/bsddb_dump; export BSDDB_DUMP
+CLNTTCL=$TESTDIR/util/ovsec_kadm_clnt_tcl; export CLNTTCL
+SRVTCL=$TESTDIR/util/ovsec_kadm_srv_tcl; export SRVTCL
+
+KRB5_CONFIG=$K5ROOT/krb5.conf; export KRB5_CONFIG
+KRB5_KDC_PROFILE=$K5ROOT/kdc.conf; export KRB5_KDC_PROFILE
+KRB5_KTNAME=$K5ROOT/ovsec_adm.srvtab; export KRB5_KTNAME
+KRB5CCNAME=$K5ROOT/krb5cc_unit-test; export KRB5CCNAME
+
+if [ "$TEST_SERVER" != "" ]; then
+	MAKE_KEYTAB="$MAKE_KEYTAB -server $TEST_SERVER"
+fi
+if [ "$TEST_PATH" != "" ]; then
+	MAKE_KEYTAB="$MAKE_KEYTAB -top $TEST_PATH"
+fi
+
+if [ "x$PS_ALL" = "x" ]; then
+	ps -axwwu >/dev/null 2>&1
+	ps_bsd=$?
+
+	ps -ef >/dev/null 2>&1
+	ps_sysv=$?
+
+	if [ $ps_bsd = 0 -a $ps_sysv = 1 ]; then
+		PS_ALL="ps -auxww"
+		PS_PID="ps -auxww"
+	elif [ $ps_bsd = 1 -a $ps_sysv = 0 ]; then
+		PS_ALL="ps -ef"
+		PS_PID="ps -fp"
+	else
+		PS_ALL="ps -auxww"
+		PS_PID="ps -auxww"
+		echo "WARNING!  Cannot auto-detect ps type, assuming BSD."
+	fi
+
+	export PS_ALL PS_PID
+fi
+
+exec ${1+"$@"}
diff --git a/krb5-1-6/src/kadmin/testing/scripts/find-make.sh b/krb5-1-6/src/kadmin/testing/scripts/find-make.sh
new file mode 100755
index 000000000..904730dfa
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/find-make.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+POSSIBILITIES='
+/usr/local/bin/gmake
+/usr/local/bin/make
+'
+
+for file in $POSSIBILITIES; do
+	if [ -f $file ]; then
+		echo $file
+		exit 0
+	fi
+done
+
+echo gmake
+echo '$0 could not find make!' 1>&2
+exit 1
+
diff --git a/krb5-1-6/src/kadmin/testing/scripts/fixup-conf-files.plin b/krb5-1-6/src/kadmin/testing/scripts/fixup-conf-files.plin
new file mode 100755
index 000000000..d7834d1c7
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/fixup-conf-files.plin
@@ -0,0 +1,344 @@
+#!/usr/local/bin/perl
+#
+# Usage: fixup-conf-files.pl [-server hostname]
+
+$verbose = $ENV{'VERBOSE_TEST'};
+$archos = $ENV{'ARCH_OS'};
+
+$REALM = "SECURE-TEST.OV.COM";
+
+sub replace {
+    local($old, $new, $backup) = @_;
+    local($dev, $ino, $mode);
+
+    $new = $old.".new" if !$new;
+    $backup = $old.".bak" if !$backup;
+
+    chmod($mode,$new) if (($dev, $ino, $mode) = stat($old));
+
+    unlink($backup);
+    link($old, $backup) || die "couldn't make backup link: $backup: $!\n"
+	if -e $old;
+    rename($new, $old) || die "couldn't rename $old to $new: $!\n";
+}
+
+if (@ARGV == 2 && $ARGV[0] eq "-server") {
+    $servername = $ARGV[1];
+} elsif (@ARGV != 0) {
+    print STDERR "Usage: $0 fixup-conf-files.pl [-server hostname]\n";
+}
+
+sub canonicalize_name {
+    local($hostname) = @_;
+    local($d, $addr, $addrtype);
+    
+    ($host,$d,$addrtype,$d,$addr) = gethostbyname($hostname);
+    die "couldn't get hostname $hostname\n" if !$host;
+    ($host) = gethostbyaddr($addr,$addrtype);
+    die "couldn't reverse-resolve $hostname\n" if !$host;
+    return $host;
+}
+
+## Get server's canonical hostname.
+if ($servername) {
+    $serverhost = $servername;
+} else {
+    chop ($serverhost = `hostname`);
+}
+$serverhost = &canonicalize_name($serverhost);
+
+## Get local canonical hostname
+chop($localhost=`hostname`);
+$localhost = &canonicalize_name($localhost);
+
+## parse krb.conf
+
+if (open(KCONF, "/etc/athena/krb.conf")) {
+    chop($hrealm = <KCONF>);
+
+    $confok = 0;
+
+    while(<KCONF>) {
+	$confs .= $_ if !/^$REALM\s+/o;
+	$confok = 1 if /^$REALM\s+$serverhost\s+admin\s+server$/oi;
+    }
+
+    close(KCONF);
+}
+
+## rewrite krb.conf if necessary.
+
+if (($hrealm ne $REALM) || !$confok) {
+    print "Rewriting /etc/athena/krb.conf...\n" if $verbose;
+
+    open(KCONF, ">/etc/athena/krb.conf.new") ||
+	die "couldn't open /etc/athena/krb.conf.new: $!\n";
+
+    print KCONF "$REALM\n";
+    print KCONF "$REALM $serverhost admin server\n";
+    print KCONF $confs;
+
+    close(KCONF);
+
+    &replace("/etc/athena/krb.conf");
+}
+
+## parse krb.realms
+
+if (open(KREALMS, "/etc/athena/krb.realms")) {
+    $serverrealmok = 0;
+    $localrealmok = 0;
+
+    while(<KREALMS>) {
+	$realms .= $_
+	    if !/^$serverhost\s+$REALM$/oi && !/^$localhost\s+$REALM$/oi;
+	$serverrealmok = 1 if /^$serverhost\s+$REALM$/oi;
+	$localrealmok = 1 if /^$localhost\s+$REALM$/oi;
+    }
+
+    close(KREALMS);
+}
+
+## rewrite krb.realms if necessary.
+
+if (!$serverrealmok || !$localrealmok) {
+    print "Rewriting /etc/athean/krb.realms...\n" if $verbose;
+
+    open(KREALMS, ">/etc/athena/krb.realms.new") ||
+	die "couldn't open /etc/athena/krb.realms.new: $!\n";
+
+    print KREALMS "$serverhost $REALM\n";
+    print KREALMS "$localhost $REALM\n" if ($localhost ne $serverhost);
+    print KREALMS $realms;
+
+    close(KREALMS);
+
+    &replace("/etc/athena/krb.realms");
+}
+
+# ## read /etc/passwd
+# 
+# open(PASSWD, "/etc/passwd") || die "couldn't open /etc/passwd: $!\n";
+# 
+# $passok = 0;
+# 
+# if ($archos ne "solaris2.3") {
+#     %mypass =
+# 	(
+# 	 "root", crypt("testroot","St"),
+# 	 "testenc", crypt("notath","HJ"),
+# 	 "testuser", "KERBEROS5",
+# 	 "pol1", "KERBEROS5",
+# 	 "pol2", "KERBEROS5",
+# 	 "pol3", "KERBEROS5",
+# 	 );
+# } else {
+#     %mypass =
+# 	(
+# 	 "root", "x", 
+# 	 "testenc", "x",
+# 	 "testuser", "x",
+# 	 "pol1", "x",
+# 	 "pol2", "x", 
+# 	 "pol3", "x",
+# 	 );
+#     %myshadow =
+# 	(
+# 	 "root", crypt("testroot","St"),
+# 	 "testenc", crypt("notath","HJ"),
+# 	 "testuser", "KERBEROS5",
+# 	 "pol1", "KERBEROS5",
+# 	 "pol2", "KERBEROS5",
+# 	 "pol3", "KERBEROS5",
+# 	 );
+# }    
+# 
+# $chpw = 0;
+# 
+# while(<PASSWD>) {
+#     if (/^([^:]+):([^:]+):/ && $mypass{$1}) {
+# 	$users{$1}++;
+# 	if ($2 ne $mypass{$1}) {
+# 	    s/^([^:]+):([^:]+):/$1:$mypass{$1}:/;
+# 	    $chpw++;
+# 	}
+#     }
+#     $pass .= $_;
+# }
+# 
+# $passok = 1;
+# 
+# for (keys %mypass) {
+#     if (!$users{$_}) {
+# 	$pass .= "$_:$mypass{$_}:32765:101::/tmp:/bin/csh\n";
+# 	$passok = 0;
+#     }
+# }
+# close(PASSWD);
+# 
+# ## rewrite passwd if necessary.
+# 
+# if ($chpw || !$passok) {
+#     print "Rewriting /etc/passwd...\n" if $verbose;
+# 
+#     open(PASSWD, ">/etc/passwd.new") ||
+# 	die "couldn't open /etc/passwd.new: $!\n";
+# 
+#     print PASSWD $pass;
+# 
+#     close(PASSWD);
+# 
+#     &replace("/etc/passwd");
+# }
+# 
+# if ($archos eq "solaris2.3") {
+# 
+# ## read /etc/shadow
+# 
+#     open(SHADOW, "/etc/shadow") || die "couldn't open /etc/shadow: $!\n";
+# 
+#     $shadowok = 0;
+#     $chpw = 0;
+#     %users = ();
+# 
+#     while(<SHADOW>) {
+# 	if (/^([^:]+):([^:]+):/ && $myshadow{$1}) {
+# 	    $users{$1}++;
+# 	    if ($2 ne $myshadow{$1}) {
+# 		s/^([^:]+):([^:]+):/$1:$myshadow{$1}:/;
+# 		$chpw++;
+# 	    }
+# 	}
+# 	$shadow .= $_;
+#     }
+#     
+#     $shadowok = 1;
+#     
+#     for (keys %myshadow) {
+# 	if (!$users{$_}) {
+# 	    $shadow .= "$_:$myshadow{$_}:6445::::::\n";
+# 	    $shadowok = 0;
+# 	}
+#     }
+#     close(SHADOW);
+#     
+# ## rewrite shadow if necessary.
+#     
+#     if ($chpw || !$shadowok) {
+# 	print "Rewriting /etc/shadow...\n" if $verbose;
+# 	
+# 	open(SHADOW, ">/etc/shadow.new") ||
+# 	    die "couldn't open /etc/shadow.new: $!\n";
+# 	
+# 	print SHADOW $shadow;
+# 	
+# 	close(SHADOW);
+# 	
+# 	&replace("/etc/shadow");
+#     }
+# }
+# 
+# if ($archos eq "aix3.2") {
+# 
+# ## read /etc/security/passwd
+# 
+#     open(SHADOW, "/etc/security/passwd") || die "couldn't open /etc/security/passwd: $!\n";
+# 
+#     $shadowok = 0;
+#     %users = ();
+# 
+#     while(<SHADOW>) {
+# 	if (/^([^:]+):\s*$/ && $mypass{$1}) {
+# 	    $user = $1;
+# 	    $users{$user}++;
+# 	    # arrange for the user to have a password entry and none other
+# 	    while (<SHADOW>) {
+# 		last if (!/=/);
+# 	    }
+# 	    $shadow .= "$user:\n\tpassword = KERBEROS5\n\n";
+# 	} else {
+# 	    $shadow .= $_;
+# 	}
+#     }
+#     
+#     $shadowok = 1;
+#     
+#     for (keys %mypass) {
+# 	if (!$users{$_}) {
+# 	    $shadow .= "$_:\n\tpassword = KERBEROS5\n\n";
+# 	    $shadowok = 0;
+# 	}
+#     }
+#     close(SHADOW);
+#     
+# ## rewrite shadow if necessary.
+#     
+#     if (!$shadowok) {
+# 	print "Rewriting /etc/security/passwd...\n" if $verbose;
+# 	
+# 	open(SHADOW, ">/etc/security/passwd.new") ||
+# 	    die "couldn't open /etc/security/passwd.new: $!\n";
+# 	
+# 	print SHADOW $shadow;
+# 	
+# 	close(SHADOW);
+# 	
+# 	&replace("/etc/security/passwd");
+#     }
+# }
+# 
+# open(SERVICES, "/etc/services") || die "couldn't open /etc/services: $!\n";
+# open(NEW_SERVICES, ">/etc/services.new") ||
+#     die "couldn't open /etc/services.new: $!\n";
+# 
+# print "Rewriting /etc/services...\n" if $verbose;
+# 
+# @needed_services = ('klogin', 'kshell', 'kerberos', 'kerberos-sec',
+# 		    'kerberos5', 'kerberos4', 'kerberos_master', 
+# 		    'passwd_server', 'eklogin', 'krb5_prop',
+# 		    'kerberos_adm', 'kerberos-adm');
+# for (@needed_services) {
+#     $needed_services{$_}++;
+# }
+# 
+# while (<SERVICES>) {
+#     m/^\s*([^\#\s][^\s]+)/;
+#     if ($needed_services{$1}) {
+# 	print "+ Commenting out old entry: $1\n" if $verbose;
+# 	print NEW_SERVICES "# $_";
+#     } else {
+# 	print NEW_SERVICES $_;
+#     }
+# }
+# 
+# close(SERVICES);
+# 
+# print NEW_SERVICES <<EOF || die "writing to /etc/services.new: $!\n";
+# 
+# klogin		543/tcp				# Kerberos authenticated rlogin
+# kshell          544/tcp         cmd             # and remote shell
+# kerberos	88/udp 		kdc		# Kerberos authentication--udp
+# kerberos	88/tcp 		kdc		# Kerberos authentication--tcp
+# kerberos-sec	750/udp 			# Kerberos authentication--udp
+# kerberos-sec	750/tcp 			# Kerberos authentication--tcp
+# kerberos5	88/udp 		kdc		# Kerberos authentication--udp
+# kerberos5	88/tcp 		kdc		# Kerberos authentication--tcp
+# kerberos4	750/udp 			# Kerberos authentication--udp
+# kerberos4	750/tcp 			# Kerberos authentication--tcp
+# kerberos_master	751/udp 			# Kerberos authentication
+# kerberos_master	751/tcp 			# Kerberos authentication
+# passwd_server	752/udp				# Kerberos passwd server
+# eklogin		2105/tcp			# Kerberos encrypted rlogin
+# krb5_prop	754/tcp				# Kerberos slave propagation
+# kerberos_adm	752/tcp				# Kerberos 5 admin/changepw
+# kerberos-adm	752/tcp				# Kerberos 5 admin/changepw
+# EOF
+# 
+# close(NEW_SERVICES) || die "error closing /etc/services.new: $!\n";
+# 
+# rename("/etc/services", "/etc/services.old") ||
+#     die "couldn't rename /etc/services to /etc/services.old: $!\n";
+# rename("/etc/services.new", "/etc/services") ||
+#     die "couldn't rename /etc/services.new to /etc/services: $!\n";
+# unlink("/etc/services.old") || die "couldn't unlink /etc/services: $!\n";
+# 
diff --git a/krb5-1-6/src/kadmin/testing/scripts/init_db b/krb5-1-6/src/kadmin/testing/scripts/init_db
new file mode 100755
index 000000000..93b6fa16e
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/init_db
@@ -0,0 +1,227 @@
+#!/bin/sh
+
+if $VERBOSE; then
+	REDIRECT=
+else
+	REDIRECT='>/dev/null'
+fi
+
+# Requires that $K5ROOT, /etc/krb.conf, and .k5.$REALM be world-writeable.
+
+if [ "$TOP" = "" ]; then
+	echo "init_db: Environment variable \$TOP must point to top of build tree" 1>&2
+	exit 1
+fi
+
+if [ "$STOP" = "" ]; then
+	echo "init_db: Environment variable \$STOP must point to top of source tree" 1>&2
+	exit 1
+fi
+
+if [ "$libdir" = "" ]; then
+	echo "init_db: Environment variable \$libdir must point to library install directory" 1>&2
+	exit 1
+fi
+
+IROOT=$TOP/..
+ADMIN=$TOP/dbutil
+BIN=$IROOT/bin
+ETC=$IROOT/etc
+MODDIR=$TOP/../util/fakedest$libdir/krb5/plugins/kdb
+SBIN=$TOP/keytab:$TOP/server
+DUMMY=${REALM=SECURE-TEST.OV.COM}; export REALM
+
+if [ ! -d $MODDIR ]; then
+	echo "+++" 1>&2
+	echo "+++ Error!  $MODDIR does not exist!" 1>&2
+	echo "+++ The MODDIR variable should point to the directory in which" 1>&2
+	echo "+++ database modules have been installed for testing." 1>&2
+	echo "+++" 1>&2
+	exit 1
+fi
+
+DUMMY=${TESTDIR=$TOP/testing}; export TESTDIR
+DUMMY=${STESTDIR=$STOP/testing}
+DUMMY=${SRVTCL=$TESTDIR/util/ovsec_kadm_srv_tcl}; export SRVTCL
+DUMMY=${TCLUTIL=$STESTDIR/tcl/util.t}; export TCLUTIL
+DUMMY=${LOCAL_MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl}
+
+PATH=$ADMIN:$BIN:$ETC:$SBIN:$PATH; export PATH
+
+if [ ! -x $SRVTCL ]; then
+	echo "+++" 1>&2
+	echo "+++ Error!  $SRVTCL does not exist!" 1>&2
+	echo "+++ It was probably not compiled because TCL was not available.  If you" 1>&2
+	echo "+++ now have TCL installed, cd into that directory, re-run configure" 1>&2 
+	echo "+++ with the --with-tcl option, and then re-run make." 1>&2
+	echo "+++" 1>&2
+
+	exit 1
+fi
+
+rm -rf $K5ROOT/*
+if [ -d $K5ROOT ]; then
+	true
+else
+	mkdir $K5ROOT
+fi
+
+# touch $K5ROOT/syslog
+# for pid in `$PS_ALL | awk '/syslogd/ && !/awk/  {print $2}'` ; do
+# 	case "$pid" in
+# 		xxx) ;;
+# 		*)
+# 			if $VERBOSE; then $PS_PID$pid | grep -v COMMAND; fi
+# 			kill -1 $pid
+# 			;;
+# 	esac
+# done
+
+qualname=`$QUALNAME`
+
+sed -e "s/__REALM__/$REALM/g" -e "s#__K5ROOT__#$K5ROOT#g" \
+	-e "s/__KDCHOST__/$qualname/g" \
+	-e "s/__LOCALHOST__/$qualname/g" \
+	-e "s#__MODDIR__#$MODDIR#g" \
+	< $STESTDIR/proto/krb5.conf.proto > $K5ROOT/krb5.conf
+sed -e "s/__REALM__/$REALM/g" -e "s#__K5ROOT__#$K5ROOT#g" \
+	< $STESTDIR/proto/kdc.conf.proto > $K5ROOT/kdc.conf
+
+eval kdb5_util -r $REALM create -P mrroot -s $REDIRECT || exit 1
+
+cp $STESTDIR/proto/ovsec_adm.dict $K5ROOT/ovsec_adm.dict
+
+cat - > /tmp/init_db$$ <<\EOF
+source $env(TCLUTIL)
+set r $env(REALM)
+if {[info exists env(USER)]} {
+    set whoami $env(USER)
+} else {
+    set whoami [exec whoami]
+}
+
+set cmds {
+    {ovsec_kadm_init $env(SRVTCL) mrroot null $r $OVSEC_KADM_STRUCT_VERSION \
+	    $OVSEC_KADM_API_VERSION_1 server_handle}
+
+    {ovsec_kadm_create_policy $server_handle "test-pol 0 10000 8 2 3 0" \
+	    {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LENGTH OVSEC_KADM_PW_MIN_CLASSES OVSEC_KADM_PW_MAX_LIFE OVSEC_KADM_PW_HISTORY_NUM}}
+    {ovsec_kadm_create_policy $server_handle "once-a-min 30 0 0 0 0 0" \
+	    {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LIFE}}
+    {ovsec_kadm_create_policy $server_handle "dict-only 0 0 0 0 0 0" \
+	    {OVSEC_KADM_POLICY}}
+    {ovsec_kadm_create_policy $server_handle [simple_policy test-pol-nopw] \
+	    {OVSEC_KADM_POLICY}}
+
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal testuser@$r] {OVSEC_KADM_PRINCIPAL} notathena}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal test1@$r] {OVSEC_KADM_PRINCIPAL} test1}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal test2@$r] {OVSEC_KADM_PRINCIPAL} test2}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal test3@$r] {OVSEC_KADM_PRINCIPAL} test3}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/get@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/modify@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/delete@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/add@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/none@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/rename@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/mod-add@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/mod-delete@$r] {OVSEC_KADM_PRINCIPAL} \
+	    admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/get-add@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/get-delete@$r] {OVSEC_KADM_PRINCIPAL} \
+	    admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/get-mod@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/no-add@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal admin/no-delete@$r] {OVSEC_KADM_PRINCIPAL} admin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [princ_w_pol pol1@$r test-pol] {OVSEC_KADM_PRINCIPAL \
+	    OVSEC_KADM_POLICY} pol111111}
+    {ovsec_kadm_create_principal $server_handle \
+	    [princ_w_pol pol2@$r once-a-min] {OVSEC_KADM_PRINCIPAL \
+	    OVSEC_KADM_POLICY} pol222222}
+    {ovsec_kadm_create_principal $server_handle \
+	    [princ_w_pol pol3@$r dict-only] {OVSEC_KADM_PRINCIPAL \
+	    OVSEC_KADM_POLICY} pol333333}
+    {ovsec_kadm_create_principal $server_handle \
+	    [princ_w_pol admin/get-pol@$r test-pol-nopw] \
+	    {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} StupidAdmin}
+    {ovsec_kadm_create_principal $server_handle \
+	    [princ_w_pol admin/pol@$r test-pol-nopw] {OVSEC_KADM_PRINCIPAL \
+	    OVSEC_KADM_POLICY} StupidAdmin}
+
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal changepw/kerberos] \
+            {OVSEC_KADM_PRINCIPAL} {XXX THIS IS WRONG}}
+
+    {ovsec_kadm_create_principal $server_handle \
+	    [simple_principal $whoami] \
+	    {OVSEC_KADM_PRINCIPAL} $whoami}
+
+    {ovsec_kadm_destroy $server_handle}
+}
+
+foreach cmd $cmds {
+    if {[catch $cmd output]} {
+	puts stderr "Error!  Command: $cmd\nError: $output"
+	exit 1
+    } else {
+	puts stdout $output
+    }
+}
+EOF
+eval "$SRVTCL < /tmp/init_db$$ $REDIRECT"
+rm /tmp/init_db$$
+
+if [ $? -ne 0 ]; then
+	echo "Error in $SRVTCL!" 1>&2
+	exit 1
+fi
+
+cat > $K5ROOT/ovsec_adm.acl <<EOF
+admin@$REALM			admcil
+admin/get@$REALM		il
+admin/modify@$REALM		mc
+admin/delete@$REALM		d
+admin/add@$REALM		a
+admin/get-pol@$REALM		il
+admin/rename@$REALM		adil
+admin/mod-add@$REALM		amc
+admin/mod-delete@$REALM		mcd
+admin/get-add@$REALM		ail
+admin/get-delete@$REALM		ild
+admin/get-mod@$REALM		ilmc
+admin/no-add@$REALM		mcdil
+admin/no-delete@$REALM		amcil
+changepw/kerberos@$REALM	cil
+
+EOF
+
+eval $LOCAL_MAKE_KEYTAB -princ kadmin/admin -princ kadmin/changepw -princ ovsec_adm/admin -princ ovsec_adm/changepw $K5ROOT/ovsec_adm.srvtab $REDIRECT
+
+# Create $K5ROOT/setup.csh to make it easy to run other programs against
+# the test db
+cat > $K5ROOT/setup.csh <<EOF
+setenv KRB5_CONFIG $KRB5_CONFIG
+setenv KRB5_KDC_PROFILE $KRB5_KDC_PROFILE
+setenv KRB5_KTNAME $KRB5_KTNAME
+$KRB5_RUN_ENV_CSH
+EOF
+
diff --git a/krb5-1-6/src/kadmin/testing/scripts/make-host-keytab.plin b/krb5-1-6/src/kadmin/testing/scripts/make-host-keytab.plin
new file mode 100755
index 000000000..ad509c35c
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/make-host-keytab.plin
@@ -0,0 +1,144 @@
+#!/usr/local/bin/perl 
+
+$server = undef;
+@princs = ();
+$top = undef;
+
+($whoami = $0) =~ s,.*/,,;
+$usage = "Usage: $whoami [ -server server ] [ -princ principal ]
+		[ -top dirname ] [ -verbose ] filename
+	Server defaults to the local host.
+	Default principals are host/hostname\@SECURE-TEST.OV.COM and
+	  test/hostname\@SECURE-TEST.OV.COM.
+	If any principals are specified, the default principals are
+	  not added to the srvtab.
+	The string \"xCANONHOSTx\" in a principal specification will be
+	  replaced by the canonical host name of the local host.";
+
+@ORIG_ARGV = @ARGV;
+
+while (($_ = $ARGV[0]) && /^-/) {
+    shift;
+    if (/^-server$/) {
+	($server = shift) || die "Missing argument to $_ option.\n$usage\n";
+    }
+    elsif (/^-princ$/) {
+	($princ = shift) || die "Missing argument to $_ option.\n$usage\n";
+	push(@princs, $princ);
+    }
+    elsif (/^-top$/) {
+	($top = shift) || die "Missing argument to $_ option.\n$usage\n";
+    }
+    elsif (/^-verbose$/) {
+	$verbose++;
+    }
+    elsif (/^--$/) {
+	last;
+    }
+    else {
+	die "Unknown option $_.\n$usage\n";
+    }
+}
+
+@princs = ("host/xCANONHOSTx\@SECURE-TEST.OV.COM",
+	   "test/xCANONHOSTx\@SECURE-TEST.OV.COM")
+    if (! @princs);
+
+$ktfile = shift(@ARGV) || die "need a keytab file\n";
+
+$verbose++ if ($ENV{'VERBOSE_TEST'});
+
+print "In $0 @ORIG_ARGV...\n" if ($verbose);
+
+chop ($canonhost = `hostname`);
+
+($canonhost,$aliases,$addrtype,$length,@addrs) = gethostbyname($canonhost);
+die "couldn't get canonical hostname\n" if !($canonhost && @addrs);
+($canonhost) = gethostbyaddr($addrs[0],$addrtype);
+die "couldn't get canonical hostname\n" if (!$canonhost);
+
+for (@princs) {
+    s/xCANONHOSTx/$canonhost/g;
+}
+
+die "Neither \$TOP nor \$TESTDIR is set, and -top not specified.\n"
+    if (! ($top || $ENV{'TOP'} || $ENV{'TESTDIR'}));
+
+$top = $ENV{'TOP'} if (! $top);
+$TESTDIR = ($ENV{'TESTDIR'} || "$top/testing");
+$MAKE_KEYTAB = ($ENV{'MAKE_KEYTAB'} || "$TESTDIR/scripts/$whoami");
+$SRVTCL = ($ENV{'SRVTCL'} || "$TESTDIR/util/ovsec_kadm_srv_tcl");
+$TCLUTIL = ($ENV{'TCLUTIL'} || "$TESTDIR/tcl/util.t");
+# This'll be wrong sometimes
+$RSH_CMD = ($ENV{'RSH_CMD'} || '/usr/ucb/rsh');
+$KADMIN = ($ENV{'KADMIN'} || "$top/cli/kadmin.local");
+
+if ($server) {
+# XXX Using /usr/ucb/rsh for now.
+
+# Strip command line options because we're adding our own.
+
+    $MAKE_KEYTAB =~ s/ .*//;
+
+    if ($ENV{'TOP'} && ($top ne $ENV{'TOP'})) {
+# Replace the old TOP with the new one where necessary
+	for ('TESTDIR', 'SRVTCL', 'TCLUTIL', 'MAKE_KEYTAB') {
+	    eval "\$$_ =~ s/^\$ENV{'TOP'}/\$top/;";
+	}
+
+# Make the paths as short as possible so our command line isn't too long.
+#	for ('SRVTCL', 'TCLUTIL', 'MAKE_KEYTAB') {
+#	    eval "\$$_ =~ s/^\$TESTDIR/\\\\\\\$TESTDIR/;";
+#	}
+#	for ('TESTDIR', 'SRVTCL', 'TCLUTIL', 'MAKE_KEYTAB') {
+#	    eval "\$$_ =~ s/^\$top/\\\\\\\$TOP/;";
+#	}
+    }
+
+    $cmd = "cd $top; \\`testing/scripts/find-make.sh\\` execute TOP=$top ";
+    $cmd .= "VERBOSE_TEST=$verbose " if ($verbose);
+    $cmd .= "TESTDIR=$TESTDIR ";
+    $cmd .= "SRVTCL=$SRVTCL ";
+    $cmd .= "TCLUTIL=$TCLUTIL ";
+
+    $cmd .= "CMD='$MAKE_KEYTAB ";
+    for (@princs) {
+	$cmd .= "-princ $_ ";
+    }
+    $cmd .= " /tmp/make-keytab.$canonhost.$$'";#';
+
+    $cmd = "$RSH_CMD $server -l root -n \"$cmd\"";
+
+    $cmd2 = "$RSH_CMD $server -l root -n \"cat /tmp/make-keytab.$canonhost.$$\" > $ktfile";
+
+    $cmd3 = "$RSH_CMD $server -l root -n \"rm /tmp/make-keytab.$canonhost.$$\"";
+
+    for ($cmd, $cmd2, $cmd3) {
+	print "$_\n" if ($verbose);
+
+	system($_) && die "Couldn't run $_: $!.\n";
+    }
+}
+else {
+    $redirect = "> /dev/null" if (! $verbose);
+
+    # We can ignore errors here, because the ktadd below will fail if
+    # this fails for any reason other than "principal exists"
+    for (@princs) {
+	next if (/^kadmin/);
+	$cmd = "$KADMIN -q 'ank -randkey $_' $redirect 2>&1";
+	system($cmd);
+    }
+    
+    $cmd = "$KADMIN -q 'ktadd -k $ktfile ";
+    $cmd .= " -q " if (! $verbose);
+    $cmd .= "@princs' $redirect";
+    if (system "$cmd") {
+	sleep(1);
+	die "Error in system($cmd)\n";
+    }
+}
+
+if (! -f $ktfile) {
+    die "$ktfile not created.\n";
+}
diff --git a/krb5-1-6/src/kadmin/testing/scripts/qualname.plin b/krb5-1-6/src/kadmin/testing/scripts/qualname.plin
new file mode 100755
index 000000000..883b7dfc8
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/qualname.plin
@@ -0,0 +1,20 @@
+#!/afs/athena/contrib/perl/p
+
+if ($#ARGV == -1) {
+    chop($hostname = `hostname`);
+} else {
+    $hostname = $ARGV[0];
+}
+
+if (! (($type,$addr) = (gethostbyname($hostname))[2,4])) {
+    print STDERR "No such host: $hostname\n";
+    exit(1);
+}
+if (! ($qualname = (gethostbyaddr($addr,$type))[0])) {
+    print STDERR "No address information for host $hostname\n";
+    exit(1);
+}
+
+$qualname =~ tr/A-Z/a-z/;	# lowercase our name for keytab use.
+print "$qualname\n";
+
diff --git a/krb5-1-6/src/kadmin/testing/scripts/save_files.sh b/krb5-1-6/src/kadmin/testing/scripts/save_files.sh
new file mode 100755
index 000000000..72182036f
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/save_files.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+while [ $# -gt 0 ] ; do
+	case $1 in
+		-start_servers)
+			start_servers=$1
+			;;
+	esac
+	shift
+done
+
+# files="/etc/inetd.conf /etc/syslog.conf /etc/krb.conf \
+# 	/etc/krb.realms /etc/passwd /etc/services /etc/v5srvtab \
+# 	/etc/rc.local /etc/shadow /etc/security/passwd /.k5login \
+# 	/.secure/etc/passwd /etc/athena/inetd.conf"
+
+files="/etc/krb.conf /etc/krb.realms /etc/athena/krb.conf \
+	/etc/athena/krb.realms /etc/v5srvtab /etc/krb5.keytab"
+
+name=`basename $0`
+
+make_dne_name()
+{
+	dne_name="/tmp/"`echo $1 | sed -e 's,/,#,g'`".did-not-exist"
+}
+	
+for f in $files ; do
+	if [ "$name" = "save_files.sh" ]; then
+		if [ -f $f.pre-secure ]; then 
+			if $VERBOSE; then
+			     echo "Warning!  $f.pre-secure exists, not saving."
+			fi
+		elif [ ! -f $f ]; then
+			make_dne_name $f
+			cp /dev/null $dne_name
+		else
+			cp $f $f.pre-secure
+		fi
+	else
+		make_dne_name $f
+		if [ -f $dne_name ]; then
+			rm -f $f $dne_name
+		elif [ ! -f $f.pre-secure ]; then
+			if [ "x$start_servers" = "x" ]; then
+			  echo "Warning!  $f.pre-secure does not exist!" 1>&2
+			fi
+		else
+			if cp $f.pre-secure $f; then
+				rm $f.pre-secure
+			else
+				echo "Warning! cp failed!" 1>&2
+			fi
+		fi
+	fi
+done
+
+# DUMMY=${INETD:=/etc/inetd}
+# if $VERBOSE; then
+# 	echo "Killing and restarting $INETD"
+# fi
+# kill `$PS_ALL | awk '/inetd/ && !/awk/ {print $2}'`
+# $INETD
diff --git a/krb5-1-6/src/kadmin/testing/scripts/simple_dump.plin b/krb5-1-6/src/kadmin/testing/scripts/simple_dump.plin
new file mode 100755
index 000000000..ea94ab2d1
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/simple_dump.plin
@@ -0,0 +1,88 @@
+#!/usr/local/bin/perl
+
+#
+# $Id$
+#
+
+## ovsec_adm_export format
+## [0]"policy" [1]name [2]pw_min_life [3]pw_max_life [4]pw_min_length [5]pw_min_classes [6]pw_history_num [7]policy_refcnt
+## [0]"princ" [1]name [2]policy [3]aux_attributes [4]old_key_len [5]admin_history_kvno [6..]old_keys
+$oaevers = "1.0";
+
+open(SORT, "|sort") || die "Couldn't open pipe to sort for output: $!\n";
+
+open(OAE, "$ENV{'TOP'}/install/admin/ovsec_adm_export|") ||
+    die "Couldn't get oae: $!\n";
+
+$header = <OAE>;
+
+die "Not ovsec_adm_export output\n"
+    if ($header !~ /^OpenV\*Secure V(\d+\.\d+)/);
+
+$stdinvers = $1;
+
+die "Expected oae version $oaevers, got $stdinvers instead.\n"
+    if $stdinvers ne $oaevers;
+
+while(<OAE>) {
+    if (/^End of Database/) {
+	last;
+    } elsif (/^policy/) {
+	print SORT;
+    } elsif (/^princ/) {
+	split(/\t/);
+
+	$_[2] = "\"\"" if !$_[2];
+
+	$_[3] = hex("0x".$_[3]);
+
+	$princ{$_[1]} = sprintf("%s\t0x%04x",@_[2,3]);
+    }
+}
+
+## kdb_edit ddb format
+## [0]strlen(principal) [1]strlen(mod_name) [2]key.length [3]alt_key.length [4]salt_length [5]alt_salt_length [6]principal [7]key.key_type [8]key.contents [9]kvno [10]max_life [11]max_renewable_life [12]mkvno [13]expiration [14]pw_expiration [15]last_pwd_change [16]last_success [17]last_failed [18]fail_auth_count [19]mod_name [20]mod_date [21]attributes [22]salt_type [23]salt [24]alt_key.contents [25]alt_salt [26..33]expansion*8;
+$ddbvers = "2.0";
+
+open(DDB, "$ENV{'TOP'}/install/admin/kdb5_edit -r SECURE-TEST.OV.COM -R ddb|") ||
+    die "Couldn't get ddb: $!\n";
+
+$header = <DDB>;
+
+die "Not a kdb5_edit ddb\n"
+    if ($header !~ /^kdb5_edit load_dump version (\d+\.\d+)/);
+
+$stdinvers = $1;
+
+die "Expected ddb version $ddbvers, got $stdinvers instead.\n"
+    if $stdinvers ne $ddbvers;
+
+## [6]principal [9]kvno [19]mod_name [10]max_life [13]expiration [14]pw_expiration [21]attributes // [2]policy [3]aux_attributes
+
+while(<DDB>) {
+    split;
+
+    print SORT join("\t","princ",(@_)[6,9,19,10,13,14],
+		    sprintf("0x%04x",$_[21]),
+		    $princ{$_[6]}),"\n";
+}
+
+close(DDB);
+
+for $keytab (@ARGV) {
+    open(KLIST, "$ENV{'TOP'}/install/bin/klist -k -t -K FILE:$keytab|") ||
+	die "Couldn't list $keytab: $!\n";
+
+    $dummy = <KLIST>;
+    $dummy = <KLIST>;
+    $dummy = <KLIST>;
+
+    while(<KLIST>) {
+	s/^\s+//;
+	split;
+	printf(SORT "keytab:FILE:%s\t%s-%s\t%s\t%s,%s\n",$keytab,
+	       @_[3,0,4,1,2]);
+    }
+}
+
+close(SORT);
diff --git a/krb5-1-6/src/kadmin/testing/scripts/start_servers b/krb5-1-6/src/kadmin/testing/scripts/start_servers
new file mode 100755
index 000000000..b59d97b91
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/start_servers
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# Usage: start_servers [hostname [path]]
+#
+# This script turns a host into a OpenV*Secure primary server for the
+# realm SECURE-TEST.OV.COM.  If no arguments are specified,
+# the local host is affected.  Otherwise, the host hostname is
+# affected; the path argument is the top of the Secure install tree on
+# that host, and if it is not specified the current canonical value of
+# TOP is used.
+
+DUMMY=${TESTDIR=$TOP/testing}
+DUMMY=${STESTDIR=$STOP/testing}
+DUMMY=${SAVE_FILES=$STESTDIR/scripts/save_files.sh}
+DUMMY=${FIX_CONF_FILES=$TESTDIR/scripts/fixup-conf-files.pl}
+DUMMY=${START_SERVERS_LOCAL=$STESTDIR/scripts/start_servers_local}
+# This'll be wrong sometimes
+DUMMY=${RSH_CMD=rsh}
+
+local=1
+
+if [ $# -gt 0 ]; then
+	if [ $# != 1 -a $# != 2 ]; then
+		echo "Usage: $0 [hostname [path]]" 1>&2
+		exit 1
+	fi
+
+	local=0
+	hostname=$1
+	if [ $# = 1 ]; then
+		rempath=`sh -c "cd $TOP && pwd"`
+	else
+		rempath=$2
+	fi
+fi
+
+if [ $local = 0 ]; then
+
+	# Fix up the local krb5.conf to point to the remote 
+	localname=`$QUALNAME`
+	sed -e "s/__REALM__/$REALM/g" -e "s#__K5ROOT__#$K5ROOT#g" \
+		-e "s/__KDCHOST__/$hostname/g" \
+		-e "s/__LOCALHOST__/$localname/g" \
+		-e "s#__MODDIR__#$TOP/../util/fakedest$libdir/db-modules#g"\
+		< $STESTDIR/proto/krb5.conf.proto > $K5ROOT/krb5.conf
+
+# Using /usr/ucb/rsh and getting rid of "-k $REALM" until we get
+# around to fixing the fact that Kerberos rsh doesn't strip out "-k
+# REALM" when falling back.
+
+	START_SERVERS_LOCAL=`echo $START_SERVERS_LOCAL|sed "s%$TOP%$rempath%"`
+	CMD="$RSH_CMD $hostname -n \
+	  \"sh -c 'VERBOSE_TEST=$VERBOSE_TEST TOP=$rempath \
+	    $rempath/testing/scripts/env-setup.sh \
+		$START_SERVERS_LOCAL $rempath'\""
+
+	if $VERBOSE; then
+		echo "+++"
+		echo "+++ Begin execution of start_servers_local on $hostname"
+		echo "+++"
+		echo $CMD
+	fi
+	eval $CMD
+	if $VERBOSE; then
+		echo "+++"
+		echo "+++ End execution of start_servers_local on $hostname"
+		echo "+++"
+	fi
+else
+	$START_SERVERS_LOCAL
+fi
+
diff --git a/krb5-1-6/src/kadmin/testing/scripts/start_servers_local b/krb5-1-6/src/kadmin/testing/scripts/start_servers_local
new file mode 100755
index 000000000..b787b57e3
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/start_servers_local
@@ -0,0 +1,218 @@
+#!/bin/sh
+
+DUMMY=${TESTDIR=$TOP/testing}
+DUMMY=${STESTDIR=$STOP/testing}
+DUMMY=${SAVE_FILES=$STESTDIR/scripts/save_files.sh}
+DUMMY=${FIX_CONF_FILES=$TESTDIR/scripts/fixup-conf-files.pl}
+DUMMY=${INITDB=$STESTDIR/scripts/init_db}
+DUMMY=${SRVTCL=$TESTDIR/util/ovsec_kadm_srv_tcl}; export SRVTCL
+DUMMY=${LOCAL_MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl}
+DUMMY=${STOP_SERVERS_LOCAL=$STESTDIR/scripts/stop_servers_local}
+DUMMY=${KRB5RCACHEDIR=$TESTDIR} ; export KRB5RCACHEDIR
+
+if [ -d /usr/tmp ]; then
+	usrtmp=/usr/tmp
+else
+	usrtmp=/var/tmp
+fi
+
+$STOP_SERVERS_LOCAL -start_servers
+
+if $VERBOSE; then
+	REDIRECT=
+else
+	REDIRECT='>/dev/null'
+fi
+
+v4files=false
+while :; do
+	case $1 in
+	-keysalt)
+		shift
+		if [ $# -gt 0 ]; then
+			keysalts="$keysalts $1"
+		else
+			break
+		fi
+		;;
+	-kdcport)
+		shift
+		if [ $# -gt 0 ]; then
+			kdcport=$1
+		else
+			break
+		fi
+		;;
+	-v4files)
+		if [ "`whoami`" != "root" ]; then
+			echo "You must be root to use -v4files!" 1>&2
+			exit 1
+		fi
+		v4files=true
+		;;
+	*)
+		break
+		;;
+	esac
+	shift
+done
+
+if [ $# -gt 1 ]; then
+	echo "Usage: $0 [-kdcport port] [-keysalts tuple] ... [top]" 1>&2
+	exit 1
+elif [ $# = 1 ]; then
+	TOP=$1
+	export TOP
+fi
+
+# fixup the system config files
+if $v4files; then
+	$SAVE_FILES || exit 1
+	$FIX_CONF_FILES || exit 1
+fi
+
+# create a fresh db
+
+$INITDB "$keysalts" || exit 1
+
+# Post-process the config files based on our arguments
+if [ "$keysalts" != "" ]; then
+	sedcmd="s/\([ 	]*supported_enctypes =\).*/\1 $keysalts/"
+	sed -e "$sedcmd" < $K5ROOT/kdc.conf > $K5ROOT/kdc.conf.new
+	mv $K5ROOT/kdc.conf.new $K5ROOT/kdc.conf
+fi
+if [ "$kdcport" != "" ] ; then
+	sedcmd="s/\(kdc_ports = .*\)[ 	]*/\1, $kdcport/"
+	sed -e "$sedcmd" < $K5ROOT/kdc.conf > $K5ROOT/kdc.conf.new
+	mv $K5ROOT/kdc.conf.new $K5ROOT/kdc.conf
+fi
+
+# allow admin to krlogin as root (for cleanup)
+DUMMY=${REALM=SECURE-TEST.OV.COM}; export REALM
+hostname=`hostname`
+QUALNAME=`$TOP/testing/scripts/qualname.pl $hostname`; export QUALNAME
+
+cat - > /tmp/start_servers_local$$ <<\EOF
+if { [catch {
+	source $env(STOP)/testing/tcl/util.t
+	set r $env(REALM)
+	set q $env(QUALNAME)
+	puts stdout [ovsec_kadm_init $env(SRVTCL) mrroot null $r \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle]
+	puts stdout [ovsec_kadm_create_principal $server_handle \
+		[simple_principal host/$q@$r] {OVSEC_KADM_PRINCIPAL} notathena]
+	puts stdout [ovsec_kadm_destroy $server_handle]
+} err]} {
+	puts stderr "initialization error: $err"
+	exit 1
+}
+exit 0
+EOF
+eval "$SRVTCL < /tmp/start_servers_local$$ $REDIRECT"
+x=$?
+rm /tmp/start_servers_local$$
+if test $x != 0 ; then exit 1 ; fi
+
+# rm -f /etc/v5srvtab
+# eval $LOCAL_MAKE_KEYTAB -princ host/xCANONHOSTx /etc/v5srvtab $REDIRECT
+
+# run the servers (from the build tree)
+
+adm_start_file=/tmp/adm_server_start.$$
+kdc_start_file=/tmp/kdc_server_start.$$
+
+rm -f $kdc_start_file
+
+if test "x$USER" = x ; then
+  USER=$LOGNAME ; export USER
+fi
+
+kdc_args="-R dfl:kdc_rcache.$USER"
+
+(trap "" 2; cd $TOP/../kdc; ./krb5kdc $kdc_args; touch $kdc_start_file) \
+	< /dev/null > $usrtmp/kdc-log.$USER 2>&1 &
+
+s=10
+max_s=60
+sofar_s=0
+timewait_s=300
+
+while true; do
+	rm -f $adm_start_file
+
+	(sleep 5; cd $TOP/server; ./kadmind $ovadm_args; \
+		touch $adm_start_file) < /dev/null > $usrtmp/kadm-log.$USER 2>&1 &
+
+	# wait until they start
+
+	while [ $sofar_s -le $max_s ]; do
+		if $VERBOSE; then
+			echo "Sleeping for $s seconds to allow servers" \
+				"to start..."
+		fi
+
+		sofar_s=`expr $sofar_s + $s`
+
+		sleep $s
+
+		if [ -f $adm_start_file -a -f $kdc_start_file ]; then
+			break
+		fi
+
+	done
+
+	if [ $sofar_s -le $max_s ]; then
+		if $VERBOSE; then
+			LOG_USER='log_user 1'
+		else
+			LOG_USER='log_user 0'
+		fi
+		if $EXPECT <<EOF
+		$LOG_USER
+#		spawn telnet localhost 1751
+# Connect to 127.0.0.1 explicitly, so failure to connect to ::1 will not
+# cause bogus errors.
+		spawn telnet 127.0.0.1 1751
+		expect {
+			"Connection refused" {
+				close
+				wait
+				exit 1
+			}
+			"Connected" {
+				send "close\n"
+				close
+				wait
+				exit 0
+			}
+			default {
+				catch {close}
+				wait
+				exit 1
+			}
+		}
+EOF
+		then
+			rm -f $kdc_start_file $adm_start_file
+			break
+		else
+			if $VERBOSE; then
+				echo "Could not connect to Admin server;" \
+					"attempting restart ($sofar_s" \
+					"seconds so far)."
+			fi
+			max_s=$timewait_s
+			continue
+		fi
+	else
+		echo "Admin server or KDC failed to start after $sofar_s" \
+			"seconds." 1>&2
+		if [ ! -f $adm_start_file ]; then
+		    echo "  No admin server start file $adm_start_file." 1>&2
+		fi
+		if [ ! -f $kdc_start_file ]; then
+		    echo "  No KDC start file $adm_start_file." 1>&2
+		fi
+		exit 1
+	fi
+done
diff --git a/krb5-1-6/src/kadmin/testing/scripts/stop_servers b/krb5-1-6/src/kadmin/testing/scripts/stop_servers
new file mode 100755
index 000000000..9542fada8
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/stop_servers
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# Usage: stop_servers [hostname [path]]
+#
+# This script turns a host into a OpenV*Secure primary server for the
+# realm SECURE-TEST.OV.COM.  If no arguments are specified,
+# the local host is affected.  Otherwise, the host hostname is
+# affected; the path argument is the top of the Secure install tree on
+# that host, and if it is not specified the current canonical value of
+# TOP is used.
+
+DUMMY=${TESTDIR=$TOP/testing}
+DUMMY=${STESTDIR=$STOP/testing}
+DUMMY=${FIX_CONF_FILES=$TESTDIR/scripts/fixup-conf-files.pl}
+DUMMY=${STOP_SERVERS_LOCAL=$STESTDIR/scripts/stop_servers_local}
+# This'll be wrong sometimes
+DUMMY=${RSH_CMD=rsh}
+DUMMY=${RESTORE_FILES=$TESTDIR/scripts/restore_files.sh}
+
+local=1
+
+if [ $# -gt 0 ]; then
+	if [ $# != 1 -a $# != 2 ]; then
+		echo "Usage: $0 [hostname [path]]" 1>&2
+		exit 1
+	fi
+
+	local=0
+	hostname=$1
+	if [ $# = 1 ]; then
+		rempath=`sh -c "cd $TOP && pwd"`
+	else
+		rempath=$2
+	fi
+fi
+
+if [ $local = 0 ]; then
+	if $VERBOSE; then
+		echo "+++ Stopping servers on remote host $hostname..."
+	fi
+
+	STOP_SERVERS_LOCAL=`echo $STOP_SERVERS_LOCAL | sed "s%$TOP%$rempath%"`
+	CMD="$RSH_CMD $hostname -n \
+	      \"sh -c 'VERBOSE_TEST=$VERBOSE_TEST TOP=$rempath \
+		$rempath/testing/scripts/env-setup.sh \
+		   $STOP_SERVERS_LOCAL $rempath'\""
+
+	if $VERBOSE; then
+		echo "+++"
+		echo "+++ Begin execution of stop_servers_local on $hostname"
+		echo "+++"
+		echo $CMD
+	fi
+	eval $CMD
+	if $VERBOSE; then
+		echo "+++"
+		echo "+++ End execution of stop_servers_local on $hostname"
+		echo "+++"
+	fi
+else
+	$STOP_SERVERS_LOCAL
+fi
diff --git a/krb5-1-6/src/kadmin/testing/scripts/stop_servers_local b/krb5-1-6/src/kadmin/testing/scripts/stop_servers_local
new file mode 100755
index 000000000..15700f501
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/stop_servers_local
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+DUMMY=${TESTDIR=$TOP/testing}
+DUMMY=${RESTORE_FILES=$TESTDIR/scripts/restore_files.sh}
+DUMMY=${KRB5RCACHEDIR=$TESTDIR}
+
+v4files=false
+while [ $# -gt 0 ] ; do
+	case $1 in
+		-start_servers)
+			start_servers=$1
+			;;
+		-v4files)
+			v4files=true
+			;;
+		*) 
+			TOP=$1
+			export TOP
+			;;
+	esac
+	shift
+done
+
+# kill any running servers.
+
+if $VERBOSE; then echo "Killing servers:"; fi
+
+for pid in xxx \
+	`$PS_ALL | grep krb5kdc | grep -v grep | awk '{print $2}'` \
+	`$PS_ALL | grep kadmind | grep -v grep | awk '{print $2}'` \
+	; do
+	case "$pid" in
+		xxx)
+			;;
+		*)
+			if $VERBOSE; then $PS_PID$pid | grep -v COMMAND; fi
+			kill $pid
+			;;
+	esac
+done
+
+# Destroy the kdc replay cache so we don't lose if we try to run the
+# KDC as another unix user.
+if test "x$USER" = x ; then
+  USER=$LOGNAME
+fi
+rm -f $KRB5RCACHEDIR/krb5kdc_rcache.$USER
+
+# restore saved system config files
+if $v4files; then
+	$RESTORE_FILES $start_servers
+fi
+exit 0
diff --git a/krb5-1-6/src/kadmin/testing/scripts/verify_xrunner_report.plin b/krb5-1-6/src/kadmin/testing/scripts/verify_xrunner_report.plin
new file mode 100755
index 000000000..9d83c3ea2
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/scripts/verify_xrunner_report.plin
@@ -0,0 +1,38 @@
+#!/usr/local/bin/perl
+
+sub usage { die "usage: $0 reportfile\n"; }
+
+$report = shift(@ARGV) || die &usage;
+
+open(REPORT, $report) || die "Couldn't open $report: $!\n";
+
+while(<REPORT>) {
+    if (/Process termination:/ && !/\bOK\b/) {
+	warn "Process termination not OK\n";
+	$warnings++;
+    } elsif (/Number of detected mismatches:\s*(\d+)/ && ($1 ne "0")) {
+	warn "Number of detected mismatches = $1\n";
+	$warnings++;
+    } elsif (/Detailed Results Description/) {
+	break;
+    }
+}
+
+while(<REPORT>) {
+    next if !/^\d+\s+/;
+
+    split;
+
+    if (($_[2] ne "run") &&
+	($_[2] ne "OK") &&
+	($_[2] ne "end-of-test")) {
+	warn "Unexpected result code $_[2] from test $_[4]\n";
+	$warnings++;
+    }
+}
+
+if ($warnings) {
+    warn "$warnings warnings.\n";
+}
+
+exit($warnings);
diff --git a/krb5-1-6/src/kadmin/testing/tcl/util.t b/krb5-1-6/src/kadmin/testing/tcl/util.t
new file mode 100644
index 000000000..0e39061f7
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/tcl/util.t
@@ -0,0 +1,60 @@
+proc simple_principal {name} {
+    return "{$name} 0 0 0 0 {$name} 0 0 0 0 null 0"
+}
+
+proc princ_w_pol {name policy} {
+    return "{$name} 0 0 0 0 {$name} 0 0 0 0 {$policy} 0"
+}
+
+proc simple_policy {name} {
+    return "{$name} 0 0 0 0 0 0"
+}
+
+proc config_params {masks values} {
+    if {[llength $masks] != [llength $values]} {
+	error "config_params: length of mask and values differ"
+    }
+
+    set params [list $masks 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 {}]
+    for {set i 0} {$i < [llength $masks]} {incr i} {
+	set mask [lindex $masks $i]
+	set value [lindex $values $i]
+	switch -glob -- $mask {
+	    "KADM5_CONFIG_REALM" {set params [lreplace $params 1 1 $value]}
+	    "KADM5_CONFIG_KADMIND_PORT" {
+		set params [lreplace $params 2 2 $value]}
+	    "KADM5_CONFIG_ADMIN_SERVER" {
+		set params [lreplace $params 3 3 $value]}
+	    "KADM5_CONFIG_DBNAME" {set params [lreplace $params 4 4 $value]}
+	    "KADM5_CONFIG_ADBNAME" {set params [lreplace $params 5 5 $value]}
+	    "KADM5_CONFIG_ADB_LOCKFILE" {
+		set params [lreplace $params 6 6 $value]}
+	    "KADM5_CONFIG_ADMIN_KEYTAB" {
+		set params [lreplace $params 7 7 $value]}
+	    "KADM5_CONFIG_ACL_FILE" {set params [lreplace $params 8 8 $value]}
+	    "KADM5_CONFIG_DICT_FILE" {
+		set params [lreplace $params 9 9 $value]}
+	    "KADM5_CONFIG_MKEY_FROM_KBD" {
+		set params [lreplace $params 10 10 $value]}
+	    "KADM5_CONFIG_STASH_FILE" {
+		set params [lreplace $params 11 11 $value]}
+	    "KADM5_CONFIG_MKEY_NAME" {
+		set params [lreplace $params 12 12 $value]}
+	    "KADM5_CONFIG_ENCTYPE" {set params [lreplace $params 13 13 $value]}
+	    "KADM5_CONFIG_MAX_LIFE" {
+		set params [lreplace $params 14 14 $value]}
+	    "KADM5_CONFIG_MAX_RLIFE" {
+		set params [lreplace $params 15 15 $value]}
+	    "KADM5_CONFIG_EXPIRATION" {
+		set params [lreplace $params 16 16 $value]}
+	    "KADM5_CONFIG_FLAGS" {set params [lreplace $params 17 17 $value]}
+	    "KADM5_CONFIG_ENCTYPES" {
+		set params [lreplace $params 18 19 [llength $value] $value]}
+	    "*" {error "config_params: unknown mask $mask"}
+	}
+    }
+    return $params
+}
+
+	    
+
diff --git a/krb5-1-6/src/kadmin/testing/util/Makefile.in b/krb5-1-6/src/kadmin/testing/util/Makefile.in
new file mode 100644
index 000000000..2f5760dc5
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/Makefile.in
@@ -0,0 +1,75 @@
+thisconfigdir=../../..
+myfulldir=kadmin/testing/util
+mydir=kadmin/testing/util
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = $(TCL_INCLUDES) -I$(BUILDTOP)/lib/kdb/
+# Force Tcl headers to use stdarg.h, because krb5 does too, and if
+# Tcl uses varargs.h it'll just mess things up.
+DEFINES= -DHAS_STDARG
+DEFS=
+KRB5_PTHREAD_LIB=$(THREAD_LINKOPTS) 
+
+PROG_LIBPATH=-L$(TOPLIBD) $(TCL_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)$(TCL_RPATH)
+
+SRCS	=	$(srcdir)/tcl_ovsec_kadm.c $(srcdir)/tcl_kadm5.c $(srcdir)/test.c
+OBJS	=	tcl_ovsec_kadm.o tcl_kadm5.o test.o
+
+CLNTPROG=	ovsec_kadm_clnt_tcl
+SRVPROG	=	ovsec_kadm_srv_tcl
+
+DO_ALL=@DO_ALL@
+
+all:: all-$(DO_ALL)
+
+all-::
+	@echo "+++"
+	@echo "+++ WARNING: Tcl not available.  The kadm5 tests will not be run."
+	@echo "+++"
+
+all-tcl:: $(CLNTPROG) $(SRVPROG)
+
+$(SRVPROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $(SRVPROG) $(OBJS) $(TCL_MAYBE_RPATH) \
+		$(KADMSRV_LIBS) $(KRB5_PTHREAD_LIB) $(KRB5_BASE_LIBS) $(TCL_LIBS)
+
+$(CLNTPROG): $(OBJS) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $(CLNTPROG) $(OBJS) $(TCL_MAYBE_RPATH) \
+		$(KRB5_PTHREAD_LIB) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS) $(TCL_LIBS)
+
+bsddb_dump: bsddb_dump.o
+	$(CC_LINK) -o bsddb_dump bsddb_dump.o $(KADMSRV_LIBS)
+
+clean:: 
+	$(RM) $(CLNTPROG) $(SRVPROG)
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)tcl_ovsec_kadm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/lib/kdb/adb_err.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h tcl_kadm5.h tcl_ovsec_kadm.c
+$(OUTPRE)tcl_kadm5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/lib/kdb/adb_err.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h tcl_kadm5.c tcl_kadm5.h
+$(OUTPRE)test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  tcl_kadm5.h test.c
diff --git a/krb5-1-6/src/kadmin/testing/util/bsddb_dump.c b/krb5-1-6/src/kadmin/testing/util/bsddb_dump.c
new file mode 100644
index 000000000..ba69b8461
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/bsddb_dump.c
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ */
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include <db.h>
+#include <stdio.h>
+
+main(int argc, char *argv[])
+{
+   char *file;
+   DB *db;
+   DBT dbkey, dbdata;
+   int code, i;
+
+   HASHINFO	info;
+
+   info.hash = NULL;
+   info.bsize = 256;
+   info.ffactor = 8;
+   info.nelem = 25000;
+   info.lorder = 0;
+
+   if (argc != 2) {
+      fprintf(stderr, "usage: argv[0] dbfile\n");
+      exit(2);
+   }
+	      
+   file = argv[1];
+
+   if((db = dbopen(file, O_RDWR, 0666, DB_HASH, &info)) == NULL) {
+      perror("Opening db file");
+      exit(1);
+   }
+
+   if ((code = (*db->seq)(db, &dbkey, &dbdata, R_FIRST)) == -1) { 
+      perror("starting db iteration");
+      exit(1);
+   }
+
+   while (code == 0) {
+      for (i=0; i<dbkey.size; i++)
+	 printf("%02x", (int) ((unsigned char *) dbkey.data)[i]);
+      printf("\t");
+      for (i=0; i<dbdata.size; i++)
+	 printf("%02x", (int) ((unsigned char *) dbdata.data)[i]);
+      printf("\n");
+
+      code = (*db->seq)(db, &dbkey, &dbdata, R_NEXT);
+   }
+
+   if (code == -1) {
+      perror("during db iteration");
+      exit(1);
+   }
+
+   if ((*db->close)(db) == -1) {
+      perror("closing db");
+      exit(1);
+   }
+
+   exit(0);
+}
diff --git a/krb5-1-6/src/kadmin/testing/util/tcl_kadm5.c b/krb5-1-6/src/kadmin/testing/util/tcl_kadm5.c
new file mode 100644
index 000000000..fb6466db2
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/tcl_kadm5.c
@@ -0,0 +1,2549 @@
+#include "autoconf.h"
+#include <stdio.h>
+#include <string.h>
+#if HAVE_TCL_H
+#include <tcl.h>
+#elif HAVE_TCL_TCL_H
+#include <tcl/tcl.h>
+#endif
+#define USE_KADM5_API_VERSION 2
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <adb_err.h>
+#include "tcl_kadm5.h"
+
+struct flagval {
+     char *name;
+     krb5_flags val;
+};
+
+/* XXX This should probably be in the hash table like server_handle */
+static krb5_context context;
+
+static struct flagval krb5_flags_array[] = {
+     {"KRB5_KDB_DISALLOW_POSTDATED", KRB5_KDB_DISALLOW_POSTDATED},
+     {"KRB5_KDB_DISALLOW_FORWARDABLE", KRB5_KDB_DISALLOW_FORWARDABLE},
+     {"KRB5_KDB_DISALLOW_TGT_BASED", KRB5_KDB_DISALLOW_TGT_BASED},
+     {"KRB5_KDB_DISALLOW_RENEWABLE", KRB5_KDB_DISALLOW_RENEWABLE},
+     {"KRB5_KDB_DISALLOW_PROXIABLE", KRB5_KDB_DISALLOW_PROXIABLE},
+     {"KRB5_KDB_DISALLOW_DUP_SKEY", KRB5_KDB_DISALLOW_DUP_SKEY},
+     {"KRB5_KDB_DISALLOW_ALL_TIX", KRB5_KDB_DISALLOW_ALL_TIX},
+     {"KRB5_KDB_REQUIRES_PRE_AUTH", KRB5_KDB_REQUIRES_PRE_AUTH},
+     {"KRB5_KDB_REQUIRES_HW_AUTH", KRB5_KDB_REQUIRES_HW_AUTH},
+     {"KRB5_KDB_REQUIRES_PWCHANGE", KRB5_KDB_REQUIRES_PWCHANGE},
+     {"KRB5_KDB_DISALLOW_SVR", KRB5_KDB_DISALLOW_SVR},
+     {"KRB5_KDB_PWCHANGE_SERVICE", KRB5_KDB_PWCHANGE_SERVICE}
+};
+
+static struct flagval aux_attributes[] = {
+     {"KADM5_POLICY",   KADM5_POLICY}
+};
+
+static struct flagval principal_mask_flags[] = {
+     {"KADM5_PRINCIPAL", KADM5_PRINCIPAL},
+     {"KADM5_PRINC_EXPIRE_TIME", KADM5_PRINC_EXPIRE_TIME},
+     {"KADM5_PW_EXPIRATION", KADM5_PW_EXPIRATION},
+     {"KADM5_LAST_PWD_CHANGE", KADM5_LAST_PWD_CHANGE},
+     {"KADM5_ATTRIBUTES", KADM5_ATTRIBUTES},
+     {"KADM5_MAX_LIFE", KADM5_MAX_LIFE},
+     {"KADM5_MOD_TIME", KADM5_MOD_TIME},
+     {"KADM5_MOD_NAME", KADM5_MOD_NAME},
+     {"KADM5_KVNO", KADM5_KVNO},
+     {"KADM5_MKVNO", KADM5_MKVNO},
+     {"KADM5_AUX_ATTRIBUTES", KADM5_AUX_ATTRIBUTES},
+     {"KADM5_POLICY", KADM5_POLICY},
+     {"KADM5_POLICY_CLR", KADM5_POLICY_CLR},
+     {"KADM5_MAX_RLIFE", KADM5_MAX_RLIFE},
+     {"KADM5_LAST_SUCCESS", KADM5_LAST_SUCCESS},
+     {"KADM5_LAST_FAILED", KADM5_LAST_FAILED},
+     {"KADM5_FAIL_AUTH_COUNT", KADM5_FAIL_AUTH_COUNT},
+     {"KADM5_KEY_DATA", KADM5_KEY_DATA},
+     {"KADM5_TL_DATA", KADM5_TL_DATA},
+     {"KADM5_PRINCIPAL_NORMAL_MASK", KADM5_PRINCIPAL_NORMAL_MASK}
+};
+
+static struct flagval policy_mask_flags[] = {
+     {"KADM5_POLICY", KADM5_POLICY},
+     {"KADM5_PW_MAX_LIFE", KADM5_PW_MAX_LIFE},
+     {"KADM5_PW_MIN_LIFE", KADM5_PW_MIN_LIFE},
+     {"KADM5_PW_MIN_LENGTH", KADM5_PW_MIN_LENGTH},
+     {"KADM5_PW_MIN_CLASSES", KADM5_PW_MIN_CLASSES},
+     {"KADM5_PW_HISTORY_NUM", KADM5_PW_HISTORY_NUM},
+     {"KADM5_REF_COUNT", KADM5_REF_COUNT}
+};
+
+static struct flagval config_mask_flags[] = {
+     {"KADM5_CONFIG_REALM", KADM5_CONFIG_REALM},
+     {"KADM5_CONFIG_DBNAME", KADM5_CONFIG_DBNAME},
+     {"KADM5_CONFIG_MKEY_NAME", KADM5_CONFIG_MKEY_NAME},
+     {"KADM5_CONFIG_MAX_LIFE", KADM5_CONFIG_MAX_LIFE},
+     {"KADM5_CONFIG_MAX_RLIFE", KADM5_CONFIG_MAX_RLIFE},
+     {"KADM5_CONFIG_EXPIRATION", KADM5_CONFIG_EXPIRATION},
+     {"KADM5_CONFIG_FLAGS", KADM5_CONFIG_FLAGS},
+     {"KADM5_CONFIG_ADMIN_KEYTAB", KADM5_CONFIG_ADMIN_KEYTAB},
+     {"KADM5_CONFIG_STASH_FILE", KADM5_CONFIG_STASH_FILE},
+     {"KADM5_CONFIG_ENCTYPE", KADM5_CONFIG_ENCTYPE},
+     {"KADM5_CONFIG_ADBNAME", KADM5_CONFIG_ADBNAME},
+     {"KADM5_CONFIG_ADB_LOCKFILE", KADM5_CONFIG_ADB_LOCKFILE},
+     {"KADM5_CONFIG_ACL_FILE", KADM5_CONFIG_ACL_FILE},
+     {"KADM5_CONFIG_KADMIND_PORT", KADM5_CONFIG_KADMIND_PORT},
+     {"KADM5_CONFIG_ENCTYPES", KADM5_CONFIG_ENCTYPES},
+     {"KADM5_CONFIG_ADMIN_SERVER", KADM5_CONFIG_ADMIN_SERVER},
+     {"KADM5_CONFIG_DICT_FILE", KADM5_CONFIG_DICT_FILE},
+     {"KADM5_CONFIG_MKEY_FROM_KBD", KADM5_CONFIG_MKEY_FROM_KBD},
+};
+
+static struct flagval priv_flags[] = {
+     {"KADM5_PRIV_GET", KADM5_PRIV_GET},
+     {"KADM5_PRIV_ADD", KADM5_PRIV_ADD},
+     {"KADM5_PRIV_MODIFY", KADM5_PRIV_MODIFY},
+     {"KADM5_PRIV_DELETE", KADM5_PRIV_DELETE}
+};
+    
+
+static char *arg_error = "wrong # args";
+
+static Tcl_HashTable *struct_table = 0;
+
+static int put_server_handle(Tcl_Interp *interp, void *handle, char **name)
+{
+    int i = 1, newPtr = 0;
+    static char buf[20];
+    Tcl_HashEntry *entry;
+
+    if (! struct_table) {
+	if (! (struct_table =
+	       malloc(sizeof(*struct_table)))) {
+	    fprintf(stderr, "Out of memory!\n");
+	    exit(1); /* XXX */
+	}
+	Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+    }
+
+    do {
+	/*
+	 * Handles from ovsec_kadm_init() and kadm5_init() should not
+	 * be mixed during unit tests, but the API would happily
+	 * accept them.  Making the hash entry names different in
+	 * tcl_kadm.c and tcl_ovsec_kadm.c ensures that GET_HANDLE
+	 * will fail if presented a handle from the other API.
+	 */
+	sprintf(buf, "kadm5_handle%d", i);
+	entry = Tcl_CreateHashEntry(struct_table, buf, &newPtr);
+	i++;
+    } while (! newPtr);
+
+    Tcl_SetHashValue(entry, handle);
+
+    *name = buf;
+
+    return TCL_OK;
+}
+
+static int get_server_handle(Tcl_Interp *interp, char *name, void **handle) 
+{
+    Tcl_HashEntry *entry;
+
+    if(!strcasecmp(name, "null"))
+	*handle = 0;
+    else {
+	if (! (struct_table &&
+	       (entry = Tcl_FindHashEntry(struct_table, name)))) {
+	     if (strncmp(name, "ovsec_kadm_handle", 17) == 0)
+		  Tcl_AppendResult(interp, "ovsec_kadm handle "
+				   "specified for kadm5 api: ", name, 0);
+	     else 
+		  Tcl_AppendResult(interp, "unknown server handle ", name, 0);
+	    return TCL_ERROR;
+	}
+	*handle = (void *) Tcl_GetHashValue(entry);
+    }
+    return TCL_OK;
+}
+
+static int remove_server_handle(Tcl_Interp *interp, char *name) 
+{
+    Tcl_HashEntry *entry;
+
+    if (! (struct_table &&
+	   (entry = Tcl_FindHashEntry(struct_table, name)))) {
+	Tcl_AppendResult(interp, "unknown server handle ", name, 0);
+	return TCL_ERROR;
+    }
+
+    Tcl_SetHashValue(entry, NULL);
+    return TCL_OK;
+}
+
+#define GET_HANDLE(num_args, ignored) \
+    void *server_handle; \
+    char *whoami = argv[0]; \
+    argv++, argc--; \
+    if (argc != num_args + 1) { \
+	Tcl_AppendResult(interp, whoami, ": ", arg_error, 0); \
+	return TCL_ERROR; \
+    } \
+    { \
+	int ltcl_ret; \
+	if ((ltcl_ret = get_server_handle(interp, argv[0], &server_handle)) \
+	    != TCL_OK) { \
+	    return ltcl_ret; \
+	} \
+    } \
+    argv++, argc--;
+
+static Tcl_HashTable *create_flag_table(struct flagval *flags, int size)
+{
+     Tcl_HashTable *table;
+     Tcl_HashEntry *entry;
+     int i;
+
+     if (! (table = (Tcl_HashTable *) malloc(sizeof(Tcl_HashTable)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_InitHashTable(table, TCL_STRING_KEYS);
+
+     for (i = 0; i < size; i++) {
+	  int newPtr;
+	       
+	  if (! (entry = Tcl_CreateHashEntry(table, flags[i].name, &newPtr))) {
+	       fprintf(stderr, "Out of memory!\n");
+	       exit(1); /* XXX */
+	  }
+
+	  Tcl_SetHashValue(entry, &flags[i].val);
+     }
+
+     return table;
+}
+
+
+static Tcl_DString *unparse_str(char *in_str)
+{
+     Tcl_DString *str;
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     if (! in_str) {
+	  Tcl_DStringAppend(str, "null", -1);
+     }
+     else {
+	  Tcl_DStringAppend(str, in_str, -1);
+     }
+
+     return str;
+}
+
+
+	  
+static int parse_str(Tcl_Interp *interp, char *in_str, char **out_str)
+{
+     if (! in_str) {
+	  *out_str = 0;
+     }
+     else if (! strcasecmp(in_str, "null")) {
+	  *out_str = 0;
+     }
+     else {
+	  *out_str = in_str;
+     }
+     return TCL_OK;
+}
+
+
+static void set_ok(Tcl_Interp *interp, char *string)
+{
+     Tcl_SetResult(interp, "OK", TCL_STATIC);
+     Tcl_AppendElement(interp, "KADM5_OK");
+     Tcl_AppendElement(interp, string);
+}
+
+
+
+static Tcl_DString *unparse_err(kadm5_ret_t code)
+{
+     char *code_string;
+     const char *error_string;
+     Tcl_DString *dstring;
+
+     switch (code) {
+     case KADM5_FAILURE: code_string = "KADM5_FAILURE"; break;
+     case KADM5_AUTH_GET: code_string = "KADM5_AUTH_GET"; break;
+     case KADM5_AUTH_ADD: code_string = "KADM5_AUTH_ADD"; break;
+     case KADM5_AUTH_MODIFY:
+	  code_string = "KADM5_AUTH_MODIFY"; break;
+     case KADM5_AUTH_DELETE:
+	  code_string = "KADM5_AUTH_DELETE"; break;
+     case KADM5_AUTH_INSUFFICIENT:
+	  code_string = "KADM5_AUTH_INSUFFICIENT"; break;
+     case KADM5_BAD_DB: code_string = "KADM5_BAD_DB"; break;
+     case KADM5_DUP: code_string = "KADM5_DUP"; break;
+     case KADM5_RPC_ERROR: code_string = "KADM5_RPC_ERROR"; break;
+     case KADM5_NO_SRV: code_string = "KADM5_NO_SRV"; break;
+     case KADM5_BAD_HIST_KEY:
+	  code_string = "KADM5_BAD_HIST_KEY"; break;
+     case KADM5_NOT_INIT: code_string = "KADM5_NOT_INIT"; break;
+     case KADM5_INIT: code_string = "KADM5_INIT"; break;
+     case KADM5_BAD_PASSWORD:
+	  code_string = "KADM5_BAD_PASSWORD"; break;
+     case KADM5_UNK_PRINC: code_string = "KADM5_UNK_PRINC"; break;
+     case KADM5_UNK_POLICY: code_string = "KADM5_UNK_POLICY"; break;
+     case KADM5_BAD_MASK: code_string = "KADM5_BAD_MASK"; break;
+     case KADM5_BAD_CLASS: code_string = "KADM5_BAD_CLASS"; break;
+     case KADM5_BAD_LENGTH: code_string = "KADM5_BAD_LENGTH"; break;
+     case KADM5_BAD_POLICY: code_string = "KADM5_BAD_POLICY"; break;
+     case KADM5_BAD_HISTORY: code_string = "KADM5_BAD_HISTORY"; break;
+     case KADM5_BAD_PRINCIPAL:
+	  code_string = "KADM5_BAD_PRINCIPAL"; break;
+     case KADM5_BAD_AUX_ATTR:
+	  code_string = "KADM5_BAD_AUX_ATTR"; break;
+     case KADM5_PASS_Q_TOOSHORT:
+	  code_string = "KADM5_PASS_Q_TOOSHORT"; break;
+     case KADM5_PASS_Q_CLASS:
+	  code_string = "KADM5_PASS_Q_CLASS"; break;
+     case KADM5_PASS_Q_DICT:
+	  code_string = "KADM5_PASS_Q_DICT"; break;
+     case KADM5_PASS_REUSE: code_string = "KADM5_PASS_REUSE"; break;
+     case KADM5_PASS_TOOSOON:
+	  code_string = "KADM5_PASS_TOOSOON"; break;
+     case KADM5_POLICY_REF:
+	  code_string = "KADM5_POLICY_REF"; break;
+     case KADM5_PROTECT_PRINCIPAL:
+	  code_string = "KADM5_PROTECT_PRINCIPAL"; break;
+     case KADM5_BAD_SERVER_HANDLE:
+	  code_string = "KADM5_BAD_SERVER_HANDLE"; break;
+     case KADM5_BAD_STRUCT_VERSION:
+     	  code_string = "KADM5_BAD_STRUCT_VERSION"; break;
+     case KADM5_OLD_STRUCT_VERSION:
+	  code_string = "KADM5_OLD_STRUCT_VERSION"; break;
+     case KADM5_NEW_STRUCT_VERSION:
+	  code_string = "KADM5_NEW_STRUCT_VERSION"; break;
+     case KADM5_BAD_API_VERSION:
+	  code_string = "KADM5_BAD_API_VERSION"; break;
+     case KADM5_OLD_LIB_API_VERSION:
+     	  code_string = "KADM5_OLD_LIB_API_VERSION"; break;
+     case KADM5_OLD_SERVER_API_VERSION:
+     	  code_string = "KADM5_OLD_SERVER_API_VERSION"; break;
+     case KADM5_NEW_LIB_API_VERSION:
+     	  code_string = "KADM5_NEW_LIB_API_VERSION"; break;
+     case KADM5_NEW_SERVER_API_VERSION:
+	  code_string = "KADM5_NEW_SERVER_API_VERSION"; break;
+     case KADM5_SECURE_PRINC_MISSING:
+	  code_string = "KADM5_SECURE_PRINC_MISSING"; break;
+     case KADM5_NO_RENAME_SALT:
+	  code_string = "KADM5_NO_RENAME_SALT"; break;
+     case KADM5_BAD_CLIENT_PARAMS:
+	  code_string = "KADM5_BAD_CLIENT_PARAMS"; break;
+     case KADM5_BAD_SERVER_PARAMS:
+	  code_string = "KADM5_BAD_SERVER_PARAMS"; break;
+     case KADM5_AUTH_LIST:
+	  code_string = "KADM5_AUTH_LIST"; break;
+     case KADM5_AUTH_CHANGEPW:
+	  code_string = "KADM5_AUTH_CHANGEPW"; break;
+     case KADM5_GSS_ERROR: code_string = "KADM5_GSS_ERROR"; break;
+     case KADM5_BAD_TL_TYPE: code_string = "KADM5_BAD_TL_TYPE"; break; 
+     case KADM5_MISSING_CONF_PARAMS:
+	  code_string = "KADM5_MISSING_CONF_PARAMS"; break;
+     case KADM5_BAD_SERVER_NAME:
+	  code_string = "KADM5_BAD_SERVER_NAME"; break;
+     case KADM5_MISSING_KRB5_CONF_PARAMS:
+	  code_string = "KADM5_MISSING_KRB5_CONF_PARAMS"; break;
+
+
+     case OSA_ADB_DUP: code_string = "OSA_ADB_DUP"; break;
+     case OSA_ADB_NOENT: code_string = "ENOENT"; break;
+     case OSA_ADB_DBINIT: code_string = "OSA_ADB_DBINIT"; break;
+     case OSA_ADB_BAD_POLICY: code_string = "Bad policy name"; break;
+     case OSA_ADB_BAD_PRINC: code_string = "Bad principal name"; break;
+     case OSA_ADB_BAD_DB: code_string = "Invalid database."; break;
+     case OSA_ADB_XDR_FAILURE: code_string = "OSA_ADB_XDR_FAILURE"; break;
+     case OSA_ADB_BADLOCKMODE: code_string = "OSA_ADB_BADLOCKMODE"; break;
+     case OSA_ADB_CANTLOCK_DB: code_string = "OSA_ADB_CANTLOCK_DB"; break;
+     case OSA_ADB_NOTLOCKED: code_string = "OSA_ADB_NOTLOCKED"; break;
+     case OSA_ADB_NOLOCKFILE: code_string = "OSA_ADB_NOLOCKFILE"; break;
+     case OSA_ADB_NOEXCL_PERM: code_string = "OSA_ADB_NOEXCL_PERM"; break;
+
+     case KRB5_KDB_INUSE: code_string = "KRB5_KDB_INUSE"; break;
+     case KRB5_KDB_UK_SERROR: code_string = "KRB5_KDB_UK_SERROR"; break;
+     case KRB5_KDB_UK_RERROR: code_string = "KRB5_KDB_UK_RERROR"; break;
+     case KRB5_KDB_UNAUTH: code_string = "KRB5_KDB_UNAUTH"; break;
+     case KRB5_KDB_NOENTRY: code_string = "KRB5_KDB_NOENTRY"; break;
+     case KRB5_KDB_ILL_WILDCARD: code_string = "KRB5_KDB_ILL_WILDCARD"; break;
+     case KRB5_KDB_DB_INUSE: code_string = "KRB5_KDB_DB_INUSE"; break;
+     case KRB5_KDB_DB_CHANGED: code_string = "KRB5_KDB_DB_CHANGED"; break;
+     case KRB5_KDB_TRUNCATED_RECORD:
+	  code_string = "KRB5_KDB_TRUNCATED_RECORD"; break;
+     case KRB5_KDB_RECURSIVELOCK:
+	  code_string = "KRB5_KDB_RECURSIVELOCK"; break;
+     case KRB5_KDB_NOTLOCKED: code_string = "KRB5_KDB_NOTLOCKED"; break;
+     case KRB5_KDB_BADLOCKMODE: code_string = "KRB5_KDB_BADLOCKMODE"; break;
+     case KRB5_KDB_DBNOTINITED: code_string = "KRB5_KDB_DBNOTINITED"; break;
+     case KRB5_KDB_DBINITED: code_string = "KRB5_KDB_DBINITED"; break;
+     case KRB5_KDB_ILLDIRECTION: code_string = "KRB5_KDB_ILLDIRECTION"; break;
+     case KRB5_KDB_NOMASTERKEY: code_string = "KRB5_KDB_NOMASTERKEY"; break;
+     case KRB5_KDB_BADMASTERKEY: code_string = "KRB5_KDB_BADMASTERKEY"; break;
+     case KRB5_KDB_INVALIDKEYSIZE:
+	  code_string = "KRB5_KDB_INVALIDKEYSIZE"; break;
+     case KRB5_KDB_CANTREAD_STORED:
+	  code_string = "KRB5_KDB_CANTREAD_STORED"; break;
+     case KRB5_KDB_BADSTORED_MKEY:
+	  code_string = "KRB5_KDB_BADSTORED_MKEY"; break;
+     case KRB5_KDB_CANTLOCK_DB: code_string = "KRB5_KDB_CANTLOCK_DB"; break;
+     case KRB5_KDB_DB_CORRUPT: code_string = "KRB5_KDB_DB_CORRUPT"; break;
+
+     case KRB5_PARSE_ILLCHAR: code_string = "KRB5_PARSE_ILLCHAR"; break;
+     case KRB5_PARSE_MALFORMED: code_string = "KRB5_PARSE_MALFORMED"; break;
+     case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: code_string = "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN"; break;
+     case KRB5_REALM_UNKNOWN: code_string = "KRB5_REALM_UNKNOWN"; break;
+     case KRB5_KDC_UNREACH: code_string = "KRB5_KDC_UNREACH"; break;
+     case KRB5_KDCREP_MODIFIED: code_string = "KRB5_KDCREP_MODIFIED"; break;
+     case KRB5KRB_AP_ERR_BAD_INTEGRITY: code_string  = "KRB5KRB_AP_ERR_BAD_INTEGRITY"; break;
+     case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: code_string = "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN"; break;
+     case KRB5_CONFIG_BADFORMAT: code_string = "KRB5_CONFIG_BADFORMAT"; break;
+
+     case KRB5_CC_NOTFOUND: code_string = "KRB5_CC_NOTFOUND"; break;
+     case KRB5_FCC_NOFILE: code_string = "KRB5_FCC_NOFILE"; break;
+
+     case EINVAL: code_string = "EINVAL"; break;
+     case ENOENT: code_string = "ENOENT"; break;
+
+     default:
+	 fprintf(stderr, "**** CODE %d (%s) ***\n", code,
+		 error_message (code));
+	 code_string = "UNKNOWN";
+	 break;
+     }
+
+     error_string = error_message(code);
+
+     if (! (dstring = (Tcl_DString *) malloc(sizeof(Tcl_DString)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX Do we really want to exit?  Ok if this is */
+		   /* just a test program, but what about if it gets */
+		   /* used for other things later? */
+     }
+
+     Tcl_DStringInit(dstring);
+
+     if (! (Tcl_DStringAppendElement(dstring, "ERROR") &&
+	    Tcl_DStringAppendElement(dstring, code_string) &&
+	    Tcl_DStringAppendElement(dstring, error_string))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+     
+     return dstring;
+}
+
+
+
+static void stash_error(Tcl_Interp *interp, krb5_error_code code)
+{
+     Tcl_DString *dstring = unparse_err(code);
+     Tcl_DStringResult(interp, dstring);
+     Tcl_DStringFree(dstring);
+     free(dstring);
+}
+
+static Tcl_DString *unparse_key_data(krb5_key_data *key_data, int n_key_data)
+{
+     Tcl_DString *str;
+     char buf[2048];
+     int i, j;
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+     for (i = 0; i < n_key_data; i++) {
+	  krb5_key_data *key = &key_data[i];
+
+	  Tcl_DStringStartSublist(str);
+	  sprintf(buf, "%d", key->key_data_type[0]);
+	  Tcl_DStringAppendElement(str, buf);
+	  sprintf(buf, "%d", key->key_data_ver > 1 ?
+		  key->key_data_type[1] : -1);
+	  Tcl_DStringAppendElement(str, buf);
+	  if (key->key_data_contents[0]) {
+	       sprintf(buf, "0x");
+	       for (j = 0; j < key->key_data_length[0]; j++) {
+		    sprintf(buf + 2*(j+1), "%02x",
+			    key->key_data_contents[0][j]);
+	       }
+	  } else *buf = '\0';
+	  Tcl_DStringAppendElement(str, buf);
+	  Tcl_DStringEndSublist(str);
+     }
+     
+     return str;
+}
+
+static Tcl_DString *unparse_tl_data(krb5_tl_data *tl_data, int n_tl_data)
+{
+     Tcl_DString *str;
+     char buf[2048];
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+     Tcl_DStringStartSublist(str);
+     for (; tl_data; tl_data = tl_data->tl_data_next) {
+	  Tcl_DStringStartSublist(str);
+	  sprintf(buf, "%d", tl_data->tl_data_type);
+	  Tcl_DStringAppendElement(str, buf);
+	  sprintf(buf, "%d", tl_data->tl_data_length);
+	  Tcl_DStringAppendElement(str, buf);
+	  Tcl_DStringAppend(str, " ", 1);
+	  Tcl_DStringAppend(str, tl_data->tl_data_contents,
+			    tl_data->tl_data_length);
+	  Tcl_DStringEndSublist(str);
+     }
+     Tcl_DStringEndSublist(str);
+     
+     return str;
+}
+
+static Tcl_DString *unparse_flags(struct flagval *array, int size,
+				  krb5_int32 flags)
+{
+     int i;
+     Tcl_DString *str;
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     for (i = 0; i < size; i++) {
+	  if (flags & array[i].val) {
+	       Tcl_DStringAppendElement(str, array[i].name);
+	  }
+     }
+
+     return str;
+}
+
+
+static int parse_flags(Tcl_Interp *interp, Tcl_HashTable *table,
+		       struct flagval *array, int size, char *str,
+		       krb5_flags *flags)
+{
+     int tmp, argc, i, retcode = TCL_OK;
+     char **argv;
+     Tcl_HashEntry *entry;
+
+     if (Tcl_GetInt(interp, str, &tmp) == TCL_OK) {
+	  *flags = tmp;
+	  return TCL_OK;
+     }
+     Tcl_ResetResult(interp);
+
+     if (Tcl_SplitList(interp, str, &argc, &argv) != TCL_OK) {
+	  return TCL_ERROR;
+     }
+
+     if (! table) {
+	  table = create_flag_table(array, size);
+     }
+
+     *flags = 0;
+
+     for (i = 0; i < argc; i++) {
+	  if (! (entry = Tcl_FindHashEntry(table, argv[i]))) {
+	       Tcl_AppendResult(interp, "unknown krb5 flag ", argv[i], 0);
+	       retcode = TCL_ERROR;
+	       break;
+	  }
+	  *flags |= *(krb5_flags *) Tcl_GetHashValue(entry);
+     }
+  
+     Tcl_Free(argv);
+     return(retcode);
+}
+
+static Tcl_DString *unparse_privs(krb5_flags flags)
+{
+     return unparse_flags(priv_flags, sizeof(priv_flags) /
+			  sizeof(struct flagval), flags);
+}
+
+
+static Tcl_DString *unparse_krb5_flags(krb5_flags flags)
+{
+     return unparse_flags(krb5_flags_array, sizeof(krb5_flags_array) /
+			  sizeof(struct flagval), flags);
+}
+
+static int parse_krb5_flags(Tcl_Interp *interp, char *str, krb5_flags *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, krb5_flags_array,
+				sizeof(krb5_flags_array) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+static Tcl_DString *unparse_aux_attributes(krb5_int32 flags)
+{
+     return unparse_flags(aux_attributes, sizeof(aux_attributes) /
+			  sizeof(struct flagval), flags);
+}
+
+
+static int parse_aux_attributes(Tcl_Interp *interp, char *str, long *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, aux_attributes,
+				sizeof(aux_attributes) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+static int parse_principal_mask(Tcl_Interp *interp, char *str, krb5_int32 *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, principal_mask_flags,
+				sizeof(principal_mask_flags) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+static int parse_policy_mask(Tcl_Interp *interp, char *str, krb5_int32 *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, policy_mask_flags,
+				sizeof(policy_mask_flags) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+
+static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ,
+					  krb5_int32 mask)
+{
+     Tcl_DString *str, *tmp_dstring;
+     char *tmp;
+     char buf[20];
+     krb5_error_code krb5_ret;
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     tmp = 0; /* It looks to me from looking at the library source */
+	      /* code for krb5_parse_name that the pointer passed into */
+	      /* it should be initialized to 0 if I want it do be */
+	      /* allocated automatically. */
+     if (mask & KADM5_PRINCIPAL) {
+          krb5_ret = krb5_unparse_name(context, princ->principal, &tmp);
+	  if (krb5_ret) {
+	       /* XXX Do we want to return an error?  Not sure. */
+	       Tcl_DStringAppendElement(str, "[unparseable principal]");
+	  }
+	  else {
+	       Tcl_DStringAppendElement(str, tmp);
+	       free(tmp);
+	  }
+     } else
+	  Tcl_DStringAppendElement(str, "null");
+
+     sprintf(buf, "%d", princ->princ_expire_time);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->last_pwd_change);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->pw_expiration);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->max_life);
+     Tcl_DStringAppendElement(str, buf);
+
+     tmp = 0;
+     if (mask & KADM5_MOD_NAME) {
+	  if ((krb5_ret = krb5_unparse_name(context, princ->mod_name, &tmp))) {
+	       /* XXX */
+	       Tcl_DStringAppendElement(str, "[unparseable principal]");
+	  }
+	  else {
+	       Tcl_DStringAppendElement(str, tmp);
+	       free(tmp);
+	  }
+     } else
+	  Tcl_DStringAppendElement(str, "null");
+
+     sprintf(buf, "%d", princ->mod_date);
+     Tcl_DStringAppendElement(str, buf);
+
+     if (mask & KADM5_ATTRIBUTES) {
+	  tmp_dstring = unparse_krb5_flags(princ->attributes);
+	  Tcl_DStringAppendElement(str, tmp_dstring->string);
+	  Tcl_DStringFree(tmp_dstring);
+	  free(tmp_dstring);
+     } else
+	  Tcl_DStringAppendElement(str, "null");
+
+     sprintf(buf, "%d", princ->kvno);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->mkvno);
+     Tcl_DStringAppendElement(str, buf);
+
+     /* XXX This may be dangerous, because the contents of the policy */
+     /* field are undefined if the POLICY bit isn't set.  However, I */
+     /* think it's a bug for the field not to be null in that case */
+     /* anyway, so we should assume that it will be null so that we'll */
+     /* catch it if it isn't. */
+     
+     tmp_dstring = unparse_str(princ->policy);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+
+     tmp_dstring = unparse_aux_attributes(princ->aux_attributes);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+
+     sprintf(buf, "%d", princ->max_renewable_life);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->last_success);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->last_failed);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->fail_auth_count);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->n_key_data);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->n_tl_data);
+     Tcl_DStringAppendElement(str, buf);
+
+     tmp_dstring = unparse_key_data(princ->key_data, princ->n_key_data);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+
+     tmp_dstring = unparse_tl_data(princ->tl_data, princ->n_tl_data);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+     
+     return str;
+}
+
+static int parse_keysalts(Tcl_Interp *interp, char *list,
+			  krb5_key_salt_tuple **keysalts,
+			  int num_keysalts)
+{
+     char **argv, **argv1 = NULL;
+     int i, tmp, argc, argc1, retcode;
+
+     *keysalts = NULL;
+     if (list == NULL)
+	  return TCL_OK;
+     
+     if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return retcode;
+     }
+     if (argc != num_keysalts) {
+	  sprintf(interp->result, "%d keysalts specified, "
+		  "but num_keysalts is %d", argc, num_keysalts);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     *keysalts = (krb5_key_salt_tuple *)
+	  malloc(sizeof(krb5_key_salt_tuple)*num_keysalts);
+     for (i = 0; i < num_keysalts; i++) {
+	  if ((retcode = Tcl_SplitList(interp, argv[i], &argc1, &argv1)) !=
+	      TCL_OK) { 
+	       goto finished;
+	  }
+	  if (argc1 != 2) {
+	       sprintf(interp->result, "wrong # fields in keysalt "
+		       "(%d should be 2)", argc1);
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  /* XXX this used to be argv1[1] too! */
+	  if ((retcode = Tcl_GetInt(interp, argv1[0], &tmp))
+	      != TCL_OK) {
+	       Tcl_AppendElement(interp, "while parsing ks_enctype");
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  (*keysalts)[i].ks_enctype = tmp;
+	  if ((retcode = Tcl_GetInt(interp, argv1[1], &tmp))
+	      != TCL_OK) {
+	       Tcl_AppendElement(interp, "while parsing ks_salttype");
+	       goto finished;
+	  }
+	  (*keysalts)[i].ks_salttype = tmp;
+
+	  Tcl_Free(argv1);
+	  argv1 = NULL;
+     }
+
+finished:
+     if (argv1) {
+	  Tcl_Free(argv1);
+     }
+     Tcl_Free(argv);
+     return retcode;
+}
+
+static int parse_key_data(Tcl_Interp *interp, char *list,
+			  krb5_key_data **key_data,
+			  int n_key_data)
+{
+     char **argv;
+     int argc, retcode;
+
+     *key_data = NULL;
+     if (list == NULL) {
+	  if (n_key_data != 0) {
+	       sprintf(interp->result, "0 key_datas specified, "
+		       "but n_key_data is %d", n_key_data);
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  } else
+	       return TCL_OK;
+     }
+     
+     if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return retcode;
+     }
+     if (argc != n_key_data) {
+	  sprintf(interp->result, "%d key_datas specified, "
+		  "but n_key_data is %d", argc, n_key_data);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (argc != 0) {
+	  sprintf(interp->result, "cannot parse key_data yet");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+finished:
+     Tcl_Free(argv);
+     return retcode;
+}
+
+static int parse_tl_data(Tcl_Interp *interp, char *list,
+			 krb5_tl_data **tlp,
+			 int n_tl_data)
+{
+     krb5_tl_data *tl, *tl2;
+     char **argv, **argv1 = NULL;
+     int i, tmp, argc, argc1, retcode;
+
+     *tlp = NULL;
+     if (list == NULL) {
+	  if (n_tl_data != 0) {
+	       sprintf(interp->result, "0 tl_datas specified, "
+		       "but n_tl_data is %d", n_tl_data);
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  } else
+	       return TCL_OK;
+     }
+     
+     if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return retcode;
+     }
+     if (argc != n_tl_data) {
+	  sprintf(interp->result, "%d tl_datas specified, "
+		  "but n_tl_data is %d", argc, n_tl_data);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     tl = tl2 = NULL;
+     for (i = 0; i < n_tl_data; i++) {
+	  tl2 = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
+	  memset(tl2, 0, sizeof(krb5_tl_data));
+	  tl2->tl_data_next = tl;
+	  tl = tl2;
+     }
+     tl2 = tl;
+	  
+     for (i = 0; i < n_tl_data; i++) {
+	  if ((retcode = Tcl_SplitList(interp, argv[i], &argc1, &argv1)) !=
+	      TCL_OK) { 
+	       goto finished;
+	  }
+	  if (argc1 != 3) {
+	       sprintf(interp->result, "wrong # fields in tl_data "
+		       "(%d should be 3)", argc1);
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  if ((retcode = Tcl_GetInt(interp, argv1[0], &tmp))
+	      != TCL_OK) {
+	       Tcl_AppendElement(interp, "while parsing tl_data_type");
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  tl->tl_data_type = tmp;
+	  if ((retcode = Tcl_GetInt(interp, argv1[1], &tmp))
+	      != TCL_OK) {
+	       Tcl_AppendElement(interp, "while parsing tl_data_length");
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  tl->tl_data_length = tmp;
+	  if (tl->tl_data_length != strlen(argv1[2])) {
+	       sprintf(interp->result, "specified length %d does not "
+		       "match length %d of string \"%s\"", tmp,
+		       strlen(argv1[2]), argv1[2]);
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  tl->tl_data_contents = (krb5_octet *) malloc(tmp+1);
+	  strcpy((char *) tl->tl_data_contents, argv1[2]);
+
+	  Tcl_Free(argv1);
+	  argv1 = NULL;
+	  tl = tl->tl_data_next;
+     }
+     if (tl != NULL) {
+	  sprintf(interp->result, "tl is not NULL!");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     *tlp = tl2;
+
+finished:
+     if (argv1) {
+	  Tcl_Free(argv1);
+     }
+     Tcl_Free(argv);
+     return retcode;
+}
+
+static int parse_config_params(Tcl_Interp *interp, char *list,
+			       kadm5_config_params *params)
+{
+     static Tcl_HashTable *table = 0;
+     char **argv = NULL;
+     int tmp, argc, retcode;
+
+     memset(params, 0, sizeof(kadm5_config_params));
+     if (list == NULL)
+	  return TCL_OK;
+     
+     if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return retcode;
+     }
+
+     if (argc != 20) {
+	  sprintf(interp->result,
+		  "wrong # args in config params structure (%d should be 20)", 
+		  argc);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if ((retcode = parse_flags(interp, table, config_mask_flags,
+				sizeof(config_mask_flags) /
+				sizeof(struct flagval),
+				argv[0], &tmp)) != TCL_OK) {
+	  goto finished;
+     }
+     params->mask = tmp;
+
+     if ((retcode = parse_str(interp, argv[1], ¶ms->realm)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing realm name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = Tcl_GetInt(interp, argv[2], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing kadmind_port");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->kadmind_port = tmp;
+     if ((retcode = parse_str(interp, argv[3], ¶ms->admin_server))
+	 != TCL_OK) { 
+	  Tcl_AppendElement(interp, "while parsing profile name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = parse_str(interp, argv[4], ¶ms->dbname)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing profile name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = parse_str(interp, argv[5], ¶ms->admin_dbname)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing admin_dbname name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = parse_str(interp, argv[6], ¶ms->admin_lockfile)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing admin_lockfile name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = parse_str(interp, argv[7], ¶ms->admin_keytab)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing admin_keytab name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = parse_str(interp, argv[8], ¶ms->acl_file)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing acl_file name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = parse_str(interp, argv[9], ¶ms->dict_file)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing dict_file name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = Tcl_GetInt(interp, argv[10], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing mkey_from_kbd");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->mkey_from_kbd = tmp;
+     if ((retcode = parse_str(interp, argv[11], ¶ms->stash_file)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing stash_file name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = parse_str(interp, argv[12], ¶ms->mkey_name)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing mkey_name name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((retcode = Tcl_GetInt(interp, argv[13], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing enctype");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->enctype = tmp;
+     if ((retcode = Tcl_GetInt(interp, argv[14], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing max_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->max_life = tmp;
+     if ((retcode = Tcl_GetInt(interp, argv[15], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing max_rlife");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->max_rlife = tmp;
+     if ((retcode = Tcl_GetInt(interp, argv[16], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing expiration");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->expiration = tmp;
+     if ((retcode = parse_krb5_flags(interp, argv[17], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing flags");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->flags = tmp;
+     if ((retcode = Tcl_GetInt(interp, argv[18], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing num_keysalts");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     params->num_keysalts = tmp;
+     if ((retcode = parse_keysalts(interp, argv[19], ¶ms->keysalts,
+				   params->num_keysalts)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing keysalts");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+finished:
+     return retcode;
+}
+     
+static int parse_principal_ent(Tcl_Interp *interp, char *list,
+			       kadm5_principal_ent_t *out_princ)
+{
+     kadm5_principal_ent_t princ;
+     krb5_error_code krb5_ret;
+     int tcl_ret;
+     int argc;
+     char **argv;
+     int tmp;
+     int retcode = TCL_OK;
+
+     if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     if (argc != 12 && argc != 20) {
+	  sprintf(interp->result,
+             "wrong # args in principal structure (%d should be 12 or 20)",
+		  argc);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (! (princ = malloc(sizeof *princ))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+     memset(princ, 0, sizeof(*princ));
+     
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &princ->principal)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     /*
+      * All of the numerical values parsed here are parsed into an
+      * "int" and then assigned into the structure in case the actual
+      * width of the field in the Kerberos structure is different from
+      * the width of an integer.
+      */
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing princ_expire_time");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->princ_expire_time = tmp;
+     
+     if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing last_pwd_change");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->last_pwd_change = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_expiration");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->pw_expiration = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing max_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->max_life = tmp;
+
+     if ((krb5_ret = krb5_parse_name(context, argv[5], &princ->mod_name)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing mod_name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+	  
+     if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing mod_date");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->mod_date = tmp;
+
+     if ((tcl_ret = parse_krb5_flags(interp, argv[7], &princ->attributes))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing attributes");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[8], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing kvno");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->kvno = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[9], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing mkvno");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->mkvno = tmp;
+
+     if ((tcl_ret = parse_str(interp, argv[10], &princ->policy)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if(princ->policy != NULL) {
+	if(!(princ->policy = strdup(princ->policy))) {
+	    fprintf(stderr, "Out of memory!\n");
+	    exit(1);
+	}
+     }
+
+     if ((tcl_ret = parse_aux_attributes(interp, argv[11],
+					 &princ->aux_attributes)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing aux_attributes");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (argc == 12) goto finished;
+     
+     if ((tcl_ret = Tcl_GetInt(interp, argv[12], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing max_renewable_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->max_renewable_life = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[13], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing last_success");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->last_success = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[14], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing last_failed");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->last_failed = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[15], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing fail_auth_count");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->fail_auth_count = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[16], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing n_key_data");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->n_key_data = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[17], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing n_tl_data");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->n_tl_data = tmp;
+
+     if ((tcl_ret = parse_key_data(interp, argv[18],
+				   &princ->key_data,
+				   princ->n_key_data)) != TCL_OK) { 
+	  Tcl_AppendElement(interp, "while parsing key_data");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if ((tcl_ret = parse_tl_data(interp, argv[19],
+				  &princ->tl_data,
+				  princ->n_tl_data)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing tl_data");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+finished:
+     Tcl_Free(argv);
+     *out_princ = princ;
+     return retcode;
+}
+
+
+static void free_principal_ent(kadm5_principal_ent_t *princ)
+{
+     krb5_free_principal(context, (*princ)->principal);
+     krb5_free_principal(context, (*princ)->mod_name);
+     free(*princ);
+     *princ = 0;
+}
+
+static Tcl_DString *unparse_policy_ent(kadm5_policy_ent_t policy)
+{
+     Tcl_DString *str, *tmp_dstring;
+     char buf[20];
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     tmp_dstring = unparse_str(policy->policy);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+     
+     sprintf(buf, "%ld", policy->pw_min_life);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_max_life);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_min_length);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_min_classes);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_history_num);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->policy_refcnt);
+     Tcl_DStringAppendElement(str, buf);
+
+     return str;
+}
+
+     
+     
+static int parse_policy_ent(Tcl_Interp *interp, char *list,
+			    kadm5_policy_ent_t *out_policy)
+{
+     kadm5_policy_ent_t policy;
+     int tcl_ret;
+     int argc;
+     char **argv;
+     int tmp;
+     int retcode = TCL_OK;
+
+     if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     if (argc != 7) {
+	  sprintf(interp->result, "wrong # args in policy structure (%d should be 7)",
+		  argc);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (! (policy = malloc(sizeof *policy))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+  
+     if ((tcl_ret = parse_str(interp, argv[0], &policy->policy)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if(policy->policy != NULL) {
+	if (! (policy->policy = strdup(policy->policy))) {
+	    fprintf(stderr, "Out of memory!\n");
+	    exit(1); /* XXX */
+	}
+     }
+     
+     /*
+      * All of the numerical values parsed here are parsed into an
+      * "int" and then assigned into the structure in case the actual
+      * width of the field in the Kerberos structure is different from
+      * the width of an integer.
+      */
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_min_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_min_life = tmp;
+     
+     if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_max_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_max_life = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_min_length");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_min_length = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_min_classes");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_min_classes = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[5], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_history_num");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_history_num = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy_refcnt");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->policy_refcnt = tmp;
+
+finished:
+     Tcl_Free(argv);
+     *out_policy = policy;
+     return retcode;
+}
+
+
+static void free_policy_ent(kadm5_policy_ent_t *policy)
+{
+     free(*policy);
+     *policy = 0;
+}
+
+static Tcl_DString *unparse_keytype(krb5_enctype enctype)
+{
+     Tcl_DString *str;
+     char buf[50];
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     switch (enctype) {
+	  /* XXX is this right? */
+     case ENCTYPE_NULL: Tcl_DStringAppend(str, "ENCTYPE_NULL", -1); break;
+     case ENCTYPE_DES_CBC_CRC:
+	  Tcl_DStringAppend(str, "ENCTYPE_DES_CBC_CRC", -1); break;
+     default:
+	  sprintf(buf, "UNKNOWN KEYTYPE (0x%x)", enctype);
+	  Tcl_DStringAppend(str, buf, -1);
+	  break;
+     }
+
+     return str;
+}
+	  
+	  
+static Tcl_DString *unparse_keyblocks(krb5_keyblock *keyblocks, int num_keys)
+{
+     Tcl_DString *str;
+     Tcl_DString *keytype;
+     int i, j;
+     
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     for (j = 0; j < num_keys; j++) {
+	  krb5_keyblock *keyblock = &keyblocks[j];
+	  
+	  Tcl_DStringStartSublist(str);
+
+	  keytype = unparse_keytype(keyblock->enctype);
+	  Tcl_DStringAppendElement(str, keytype->string);
+	  Tcl_DStringFree(keytype);
+	  free(keytype);
+	  if (keyblock->length == 0) {
+	       Tcl_DStringAppendElement(str, "0x00");
+	  }
+	  else {
+	       Tcl_DStringAppendElement(str, "0x");
+	       for (i = 0; i < keyblock->length; i++) {
+		    char buf[3];
+		    sprintf(buf, "%02x", (int) keyblock->contents[i]);
+		    Tcl_DStringAppend(str, buf, -1);
+	       }
+	  }
+
+	  Tcl_DStringEndSublist(str);
+     }
+     
+
+     return str;
+}
+
+enum init_type { INIT_NONE, INIT_PASS, INIT_CREDS };
+     
+static int _tcl_kadm5_init_any(enum init_type init_type, ClientData clientData,
+			Tcl_Interp *interp, int argc, char *argv[])
+{
+     kadm5_ret_t ret;
+     char *client_name, *pass, *service_name;
+     int tcl_ret;
+     krb5_ui_4 struct_version, api_version;
+     char *handle_var;
+     void *server_handle;
+     char *handle_name, *params_str;
+     char *whoami = argv[0];
+     kadm5_config_params params;
+
+     argv++, argc--;
+
+     kadm5_init_krb5_context(&context);
+
+     if (argc != 7) {
+	  Tcl_AppendResult(interp, whoami, ": ", arg_error, 0);
+	  return TCL_ERROR;
+     }
+
+     if (((tcl_ret = parse_str(interp, argv[0], &client_name)) != TCL_OK) ||
+	 ((tcl_ret = parse_str(interp, argv[1], &pass)) != TCL_OK) ||
+	 ((tcl_ret = parse_str(interp, argv[2], &service_name)) != TCL_OK) ||
+	 ((tcl_ret = parse_str(interp, argv[3], ¶ms_str)) != TCL_OK) ||
+	 ((tcl_ret = parse_config_params(interp, params_str, ¶ms))
+	  != TCL_OK) ||
+	 ((tcl_ret = Tcl_GetInt(interp, argv[4], (int *) &struct_version)) !=
+	  TCL_OK) ||
+	 ((tcl_ret = Tcl_GetInt(interp, argv[5], (int *) &api_version)) !=
+	  TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     handle_var = argv[6];
+
+     if (! (handle_var && *handle_var)) {
+	 Tcl_SetResult(interp, "must specify server handle variable name",
+		       TCL_STATIC);
+	 return TCL_ERROR;
+     }
+
+     if (init_type == INIT_CREDS) {
+	  krb5_ccache cc;
+	  
+	  if (pass == NULL) {
+	       if ((ret = krb5_cc_default(context, &cc))) {
+		    stash_error(interp, ret);
+		    return TCL_ERROR;
+	       }
+	  } else {
+	       if ((ret = krb5_cc_resolve(context, pass, &cc))) {
+		    stash_error(interp, ret);
+		    return TCL_ERROR;
+	       }
+	  }
+
+	  ret = kadm5_init_with_creds(client_name, cc, service_name,
+				      ¶ms, struct_version,
+				      api_version, NULL, &server_handle); 
+	  
+	  (void) krb5_cc_close(context, cc);
+     } else
+	  ret = kadm5_init(client_name, pass, service_name, ¶ms,
+			   struct_version, api_version, NULL, &server_handle);
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+
+     if ((tcl_ret = put_server_handle(interp, server_handle, &handle_name))
+	 != TCL_OK) {
+	 return tcl_ret;
+     }
+     
+     if (! Tcl_SetVar(interp, handle_var, handle_name, TCL_LEAVE_ERR_MSG)) {
+	 return TCL_ERROR;
+     }
+     
+     set_ok(interp, "KADM5 API initialized.");
+     return TCL_OK;
+}
+
+static int tcl_kadm5_init(ClientData clientData, Tcl_Interp *interp,
+			  int argc, char *argv[])
+{
+     return _tcl_kadm5_init_any(INIT_PASS, clientData, interp, argc, argv);
+}
+
+static int tcl_kadm5_init_with_creds(ClientData clientData, Tcl_Interp *interp,
+				     int argc, char *argv[])
+{
+     return _tcl_kadm5_init_any(INIT_CREDS, clientData, interp, argc, argv);
+}
+
+static int tcl_kadm5_destroy(ClientData clientData, Tcl_Interp *interp,
+			     int argc, char *argv[])
+{
+     kadm5_ret_t ret;
+     int tcl_ret;
+
+     GET_HANDLE(0, 0);
+
+     ret = kadm5_destroy(server_handle);
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+
+     if ((tcl_ret = remove_server_handle(interp, argv[-1])) != TCL_OK) {
+	 return tcl_ret;
+     }
+     
+     set_ok(interp, "KADM5 API deinitialized.");
+     return TCL_OK;
+}	  
+
+static int tcl_kadm5_create_principal(ClientData clientData, 
+				      Tcl_Interp *interp,
+				      int argc, char *argv[])
+{
+     int tcl_ret;
+     kadm5_ret_t ret;
+     int retcode = TCL_OK;
+     char *princ_string;
+     kadm5_principal_ent_t princ = 0;
+     krb5_int32 mask;
+     char *pw;
+#ifdef OVERRIDE     
+     int override_qual;
+#endif     
+
+     GET_HANDLE(3, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing principal");
+	  return tcl_ret;
+     }
+
+     if (princ_string &&
+	 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+
+     if ((tcl_ret = parse_str(interp, argv[2], &pw)) != TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+#ifdef OVERRIDE
+     if ((tcl_ret = Tcl_GetBoolean(interp, argv[3], &override_qual)) !=
+	 TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+#endif     
+
+#ifdef OVERRIDE
+     ret = kadm5_create_principal(server_handle, princ, mask, pw,
+				       override_qual);
+#else
+     ret = kadm5_create_principal(server_handle, princ, mask, pw);
+#endif     
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     else {
+	  set_ok(interp, "Principal created.");
+     }
+
+finished:
+     if (princ) {
+	  free_principal_ent(&princ);
+     }
+     return retcode;
+}
+
+
+
+static int tcl_kadm5_delete_principal(ClientData clientData, 
+				      Tcl_Interp *interp,
+				      int argc, char *argv[])
+{
+     krb5_principal princ;
+     krb5_error_code krb5_ret;
+     kadm5_ret_t ret;
+     int tcl_ret;
+     char *name;
+     
+     GET_HANDLE(1, 0);
+
+     if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
+	return tcl_ret;
+     if(name != NULL) {
+	if ((krb5_ret = krb5_parse_name(context, name, &princ))) {
+	    stash_error(interp, krb5_ret);
+	    Tcl_AppendElement(interp, "while parsing principal");
+	    return TCL_ERROR;
+	}
+     } else princ = NULL;
+     ret = kadm5_delete_principal(server_handle, princ);
+
+     if(princ != NULL) 
+	krb5_free_principal(context, princ);
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Principal deleted.");
+	  return TCL_OK;
+     }
+}
+
+
+
+static int tcl_kadm5_modify_principal(ClientData clientData, 
+				      Tcl_Interp *interp,
+				      int argc, char *argv[])
+{
+     char *princ_string;
+     kadm5_principal_ent_t princ = 0;
+     int tcl_ret;
+     krb5_int32 mask;
+     int retcode = TCL_OK;
+     kadm5_ret_t ret;
+
+     GET_HANDLE(2, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing principal");
+	  return tcl_ret;
+     }
+
+     if (princ_string &&
+	 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+     
+     if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = kadm5_modify_principal(server_handle, princ, mask);
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Principal modified.");
+     }
+
+finished:
+     if (princ) {
+	  free_principal_ent(&princ);
+     }
+     return retcode;
+}
+
+
+static int tcl_kadm5_rename_principal(ClientData clientData, 
+				      Tcl_Interp *interp,
+				      int argc, char *argv[])
+{
+     krb5_principal source, target;
+     krb5_error_code krb5_ret;
+     kadm5_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(2, 0);
+
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &source)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing source");
+	  return TCL_ERROR;
+     }
+
+     if ((krb5_ret = krb5_parse_name(context, argv[1], &target)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing target");
+	  krb5_free_principal(context, source);
+	  return TCL_ERROR;
+     }
+
+     ret = kadm5_rename_principal(server_handle, source, target);
+
+     if (ret == KADM5_OK) {
+	  set_ok(interp, "Principal renamed.");
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+     krb5_free_principal(context, source);
+     krb5_free_principal(context, target);
+     return retcode;
+}
+
+
+	  
+static int tcl_kadm5_chpass_principal(ClientData clientData, 
+				      Tcl_Interp *interp,
+				      int argc, char *argv[])
+{
+     krb5_principal princ;
+     char *pw;
+#ifdef OVERRIDE     
+     int override_qual;
+#endif     
+     krb5_error_code krb5_ret;
+     int retcode = TCL_OK;
+     kadm5_ret_t ret;
+
+     GET_HANDLE(2, 0);
+
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal name");
+	  return TCL_ERROR;
+     }
+
+     if (parse_str(interp, argv[1], &pw) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing password");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+#ifdef OVERRIDE
+     if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing override_qual");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     
+     ret = kadm5_chpass_principal(server_handle,
+				       princ, pw, override_qual);
+#else
+     ret = kadm5_chpass_principal(server_handle, princ, pw);
+#endif     
+
+     if (ret == KADM5_OK) {
+	  set_ok(interp, "Password changed.");
+	  goto finished;
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     krb5_free_principal(context, princ);
+     return retcode;
+}
+
+
+
+static int tcl_kadm5_chpass_principal_util(ClientData clientData,
+					   Tcl_Interp *interp,
+					   int argc, char *argv[])
+{
+     krb5_principal princ;
+     char *new_pw;
+#ifdef OVERRIDE     
+     int override_qual;
+#endif     
+     char *pw_ret, *pw_ret_var;
+     char msg_ret[1024], *msg_ret_var;
+     krb5_error_code krb5_ret;
+     kadm5_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(4, 0);
+
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal name");
+	  return TCL_ERROR;
+     }
+
+     if (parse_str(interp, argv[1], &new_pw) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing new password");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+#ifdef OVERRIDE
+     if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing override_qual");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+#endif
+     if (parse_str(interp, argv[3], &pw_ret_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_ret variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (parse_str(interp, argv[4], &msg_ret_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing msg_ret variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = kadm5_chpass_principal_util(server_handle, princ, new_pw,
+#ifdef OVERRIDE     
+					    override_qual,
+#endif					    
+					    pw_ret_var ? &pw_ret : 0,
+					    msg_ret_var ? msg_ret : 0,
+				            msg_ret_var ? sizeof(msg_ret) : 0);
+
+     if (ret == KADM5_OK) {
+	  if (pw_ret_var &&
+	      (! Tcl_SetVar(interp, pw_ret_var, pw_ret,
+			    TCL_LEAVE_ERR_MSG))) {
+	       Tcl_AppendElement(interp, "while setting pw_ret variable");
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  if (msg_ret_var &&
+	      (! Tcl_SetVar(interp, msg_ret_var, msg_ret,
+			    TCL_LEAVE_ERR_MSG))) {
+	       Tcl_AppendElement(interp,
+				 "while setting msg_ret variable");
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  set_ok(interp, "Password changed.");
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     krb5_free_principal(context, princ);
+     return retcode;
+}
+
+
+
+static int tcl_kadm5_randkey_principal(ClientData clientData, 
+				       Tcl_Interp *interp,
+				       int argc, char *argv[])
+{
+     krb5_principal princ;
+     krb5_keyblock *keyblocks;
+     int num_keys;
+     char *keyblock_var, *num_var, buf[50];
+     Tcl_DString *keyblock_dstring = 0;
+     krb5_error_code krb5_ret;
+     kadm5_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(3, 0);
+
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal name");
+	  return TCL_ERROR;
+     }
+
+     if (parse_str(interp, argv[1], &keyblock_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing keyblock variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if (parse_str(interp, argv[2], &num_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing keyblock variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = kadm5_randkey_principal(server_handle,
+				   princ, keyblock_var ? &keyblocks : 0,
+				   num_var ? &num_keys : 0);
+
+     if (ret == KADM5_OK) {
+	  if (keyblock_var) {
+	       keyblock_dstring = unparse_keyblocks(keyblocks, num_keys);
+	       if (! Tcl_SetVar(interp, keyblock_var,
+				keyblock_dstring->string,
+				TCL_LEAVE_ERR_MSG)) {
+		    Tcl_AppendElement(interp,
+				      "while setting keyblock variable");
+		    retcode = TCL_ERROR;
+		    goto finished;
+	       }
+	  }
+	  if (num_var) {
+	       sprintf(buf, "%d", num_keys);
+	       if (! Tcl_SetVar(interp, num_var, buf,
+				TCL_LEAVE_ERR_MSG)) {
+		    Tcl_AppendElement(interp,
+				      "while setting num_keys variable");
+	       }
+	  }
+	  set_ok(interp, "Key randomized.");
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     krb5_free_principal(context, princ);
+     if (keyblock_dstring) {
+	  Tcl_DStringFree(keyblock_dstring);
+	  free(keyblock_dstring);
+     }
+     return retcode;
+}
+
+
+
+static int tcl_kadm5_get_principal(ClientData clientData, Tcl_Interp *interp,
+				   int argc, char *argv[])
+{
+     krb5_principal princ;
+     kadm5_principal_ent_rec ent;
+     Tcl_DString *ent_dstring = 0;
+     char *ent_var;
+     char *name;
+     krb5_error_code krb5_ret;
+     int tcl_ret;
+     kadm5_ret_t ret = -1;
+     krb5_int32 mask;
+     int retcode = TCL_OK;
+     
+     GET_HANDLE(3, 1);
+
+     if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
+	return tcl_ret;
+     if(name != NULL) {
+	if ((krb5_ret = krb5_parse_name(context, name, &princ)) != 0) {
+	    stash_error(interp, krb5_ret);
+	    Tcl_AppendElement(interp, "while parsing principal name");
+	    return TCL_ERROR;
+	}
+     } else princ = NULL;
+
+     if ((tcl_ret = parse_str(interp, argv[1], &ent_var)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if ((tcl_ret = parse_principal_mask(interp, argv[2], &mask)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing principal mask");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     
+     ret = kadm5_get_principal(server_handle, princ, ent_var ? &ent : 0,
+			       mask);
+
+     if (ret == KADM5_OK) {
+	  if (ent_var) {
+	       ent_dstring = unparse_principal_ent(&ent, mask);
+	       if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
+				TCL_LEAVE_ERR_MSG)) {
+		    Tcl_AppendElement(interp,
+				      "while setting entry variable");
+		    retcode = TCL_ERROR;
+		    goto finished;
+	       }
+	       set_ok(interp, "Principal retrieved.");
+	  }
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     if (ent_dstring) {
+	  Tcl_DStringFree(ent_dstring);
+	  free(ent_dstring);
+     }
+     if(princ != NULL)
+	krb5_free_principal(context, princ);
+     if (ret == KADM5_OK && ent_var &&
+	 (ret = kadm5_free_principal_ent(server_handle, &ent)) &&
+	 (retcode == TCL_OK)) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+     return retcode;
+}
+     
+static int tcl_kadm5_create_policy(ClientData clientData, Tcl_Interp *interp,
+				   int argc, char *argv[])
+{
+     int tcl_ret;
+     kadm5_ret_t ret;
+     int retcode = TCL_OK;
+     char *policy_string;
+     kadm5_policy_ent_t policy = 0;
+     krb5_int32 mask;
+
+     GET_HANDLE(2, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy");
+	  return tcl_ret;
+     }
+
+     if (policy_string &&
+	 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+
+     ret = kadm5_create_policy(server_handle, policy, mask);
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     else {
+	  set_ok(interp, "Policy created.");
+     }
+
+finished:
+     if (policy) {
+	  free_policy_ent(&policy);
+     }
+     return retcode;
+}
+
+
+
+static int tcl_kadm5_delete_policy(ClientData clientData, Tcl_Interp *interp,
+				   int argc, char *argv[])
+{
+     kadm5_ret_t ret;
+     char *policy;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &policy) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy name");
+	  return TCL_ERROR;
+     }
+     
+     ret = kadm5_delete_policy(server_handle, policy);
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Policy deleted.");
+	  return TCL_OK;
+     }
+}
+
+
+
+static int tcl_kadm5_modify_policy(ClientData clientData, Tcl_Interp *interp,
+				   int argc, char *argv[])
+{
+     char *policy_string;
+     kadm5_policy_ent_t policy = 0;
+     int tcl_ret;
+     krb5_int32 mask;
+     int retcode = TCL_OK;
+     kadm5_ret_t ret;
+
+     GET_HANDLE(2, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy");
+	  return tcl_ret;
+     }
+
+     if (policy_string &&
+	 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = kadm5_modify_policy(server_handle, policy, mask);
+
+     if (ret != KADM5_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Policy modified.");
+     }
+
+finished:
+     if (policy) {
+	  free_policy_ent(&policy);
+     }
+     return retcode;
+}
+
+
+static int tcl_kadm5_get_policy(ClientData clientData, Tcl_Interp *interp,
+				int argc, char *argv[])
+{
+     kadm5_policy_ent_rec ent;
+     Tcl_DString *ent_dstring = 0;
+     char *policy;
+     char *ent_var;
+     kadm5_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(2, 1);
+
+     if (parse_str(interp, argv[0], &policy) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy name");
+	  return TCL_ERROR;
+     }
+     
+     if (parse_str(interp, argv[1], &ent_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry variable name");
+	  return TCL_ERROR;
+     }
+     
+     ret = kadm5_get_policy(server_handle, policy, ent_var ? &ent : 0);
+
+     if (ret == KADM5_OK) {
+	  if (ent_var) {
+	       ent_dstring = unparse_policy_ent(&ent);
+	       if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
+				TCL_LEAVE_ERR_MSG)) {
+		    Tcl_AppendElement(interp,
+				      "while setting entry variable");
+		    retcode = TCL_ERROR;
+		    goto finished;
+	       }
+	       set_ok(interp, "Policy retrieved.");
+	  }
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     if (ent_dstring) {
+	  Tcl_DStringFree(ent_dstring);
+	  free(ent_dstring);
+     }
+     if (ent_var && ret == KADM5_OK &&
+	 (ret = kadm5_free_policy_ent(server_handle, &ent)) &&
+	 (retcode == TCL_OK)) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+     return retcode;
+}
+
+     
+     
+static int tcl_kadm5_free_principal_ent(ClientData clientData,
+					Tcl_Interp *interp,
+					int argc, char *argv[])
+{
+     char *ent_name;
+     kadm5_principal_ent_t ent;
+     kadm5_ret_t ret;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry name");
+	  return TCL_ERROR;
+     }
+
+     if ((! ent_name) &&
+	 (ret = kadm5_free_principal_ent(server_handle, 0))) {
+	 stash_error(interp, ret);
+	 return TCL_ERROR;
+     }
+     else {
+	  Tcl_HashEntry *entry;
+
+	  if (strncmp(ent_name, "principal", sizeof("principal")-1)) {
+	       Tcl_AppendResult(interp, "invalid principal handle \"",
+				ent_name, "\"", 0);
+	       return TCL_ERROR;
+	  }
+	  if (! struct_table) {
+	       if (! (struct_table = malloc(sizeof(*struct_table)))) {
+		    fprintf(stderr, "Out of memory!\n");
+		    exit(1); /* XXX */
+	       }
+	       Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+	  }
+	  
+	  if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
+	       Tcl_AppendResult(interp, "principal handle \"", ent_name,
+				"\" not found", 0);
+	       return TCL_ERROR;
+	  }
+
+	  ent = (kadm5_principal_ent_t) Tcl_GetHashValue(entry);
+
+	  ret = kadm5_free_principal_ent(server_handle, ent);
+	  if (ret != KADM5_OK) {
+	      stash_error(interp, ret);
+	      return TCL_ERROR;
+	  }
+	  Tcl_DeleteHashEntry(entry);
+     }
+     set_ok(interp, "Principal freed.");
+     return TCL_OK;
+}
+	  
+		    
+static int tcl_kadm5_free_policy_ent(ClientData clientData,
+				     Tcl_Interp *interp,
+				     int argc, char *argv[])
+{
+     char *ent_name;
+     kadm5_policy_ent_t ent;
+     kadm5_ret_t ret;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry name");
+	  return TCL_ERROR;
+     }
+
+     if ((! ent_name) &&
+	 (ret = kadm5_free_policy_ent(server_handle, 0))) {
+	 stash_error(interp, ret);
+	 return TCL_ERROR;
+     }
+     else {
+	  Tcl_HashEntry *entry;
+
+	  if (strncmp(ent_name, "policy", sizeof("policy")-1)) {
+	       Tcl_AppendResult(interp, "invalid principal handle \"",
+				ent_name, "\"", 0);
+	       return TCL_ERROR;
+	  }
+	  if (! struct_table) {
+	       if (! (struct_table = malloc(sizeof(*struct_table)))) {
+		    fprintf(stderr, "Out of memory!\n");
+		    exit(1); /* XXX */
+	       }
+	       Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+	  }
+	  
+	  if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
+	       Tcl_AppendResult(interp, "policy handle \"", ent_name,
+				"\" not found", 0);
+	       return TCL_ERROR;
+	  }
+
+	  ent = (kadm5_policy_ent_t) Tcl_GetHashValue(entry);
+
+	  if ((ret = kadm5_free_policy_ent(server_handle, ent)) != KADM5_OK) {
+	      stash_error(interp, ret);
+	      return TCL_ERROR;
+	  }
+	  Tcl_DeleteHashEntry(entry);
+     }
+     set_ok(interp, "Policy freed.");
+     return TCL_OK;
+}
+	  
+		    
+static int tcl_kadm5_get_privs(ClientData clientData, Tcl_Interp *interp,
+			       int argc, char *argv[])
+{
+     char *set_ret;
+     kadm5_ret_t ret;
+     char *priv_var;
+     long privs;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &priv_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing privs variable name");
+	  return TCL_ERROR;
+     }
+
+     ret = kadm5_get_privs(server_handle, priv_var ? &privs : 0);
+
+     if (ret == KADM5_OK) {
+	  if (priv_var) {
+	       Tcl_DString *str = unparse_privs(privs);
+	       set_ret = Tcl_SetVar(interp, priv_var, str->string,
+				    TCL_LEAVE_ERR_MSG);
+	       Tcl_DStringFree(str);
+	       free(str);
+	       if (! set_ret) {
+		    Tcl_AppendElement(interp, "while setting priv variable");
+		    return TCL_ERROR;
+	       }
+	  }
+	  set_ok(interp, "Privileges retrieved.");
+	  return TCL_OK;
+     }
+     else {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+}
+		    
+
+void Tcl_kadm5_init(Tcl_Interp *interp)
+{
+    char buf[20];
+
+     Tcl_SetVar(interp, "KADM5_ADMIN_SERVICE",
+		KADM5_ADMIN_SERVICE, TCL_GLOBAL_ONLY);
+     Tcl_SetVar(interp, "KADM5_CHANGEPW_SERVICE",
+		KADM5_CHANGEPW_SERVICE, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", KADM5_STRUCT_VERSION);
+     Tcl_SetVar(interp, "KADM5_STRUCT_VERSION", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", KADM5_API_VERSION_1);
+     Tcl_SetVar(interp, "KADM5_API_VERSION_1", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", KADM5_API_VERSION_2);
+     Tcl_SetVar(interp, "KADM5_API_VERSION_2", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", KADM5_API_VERSION_MASK);
+     Tcl_SetVar(interp, "KADM5_API_VERSION_MASK", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", KADM5_STRUCT_VERSION_MASK);
+     Tcl_SetVar(interp, "KADM5_STRUCT_VERSION_MASK", buf,
+		TCL_GLOBAL_ONLY);
+
+     Tcl_CreateCommand(interp, "kadm5_init", tcl_kadm5_init, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_init_with_creds",
+		       tcl_kadm5_init_with_creds, 0, 0); 
+     Tcl_CreateCommand(interp, "kadm5_destroy", tcl_kadm5_destroy, 0,
+		       0);
+     Tcl_CreateCommand(interp, "kadm5_create_principal",
+		       tcl_kadm5_create_principal, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_delete_principal",
+		       tcl_kadm5_delete_principal, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_modify_principal",
+		       tcl_kadm5_modify_principal, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_rename_principal",
+		       tcl_kadm5_rename_principal, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_chpass_principal",
+		       tcl_kadm5_chpass_principal, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_chpass_principal_util",
+		       tcl_kadm5_chpass_principal_util, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_randkey_principal",
+		       tcl_kadm5_randkey_principal, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_get_principal",
+		       tcl_kadm5_get_principal, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_create_policy",
+		       tcl_kadm5_create_policy, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_delete_policy",
+		       tcl_kadm5_delete_policy, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_modify_policy",
+		       tcl_kadm5_modify_policy, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_get_policy",
+		       tcl_kadm5_get_policy, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_free_principal_ent",
+		       tcl_kadm5_free_principal_ent, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_free_policy_ent",
+		       tcl_kadm5_free_policy_ent, 0, 0);
+     Tcl_CreateCommand(interp, "kadm5_get_privs",
+		       tcl_kadm5_get_privs, 0, 0);
+}
diff --git a/krb5-1-6/src/kadmin/testing/util/tcl_kadm5.h b/krb5-1-6/src/kadmin/testing/util/tcl_kadm5.h
new file mode 100644
index 000000000..7e237753a
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/tcl_kadm5.h
@@ -0,0 +1,4 @@
+
+void Tcl_kadm5_init(Tcl_Interp *interp);
+void Tcl_ovsec_kadm_init(Tcl_Interp *interp);
+
diff --git a/krb5-1-6/src/kadmin/testing/util/tcl_krb5_hash.c b/krb5-1-6/src/kadmin/testing/util/tcl_krb5_hash.c
new file mode 100644
index 000000000..7fe1b8f74
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/tcl_krb5_hash.c
@@ -0,0 +1,167 @@
+/*
+ * All of the TCL krb5 functions which return (or place into output
+ * variables) structures or pointers to structures that can't be
+ * represented as tcl native types, do so by returning a handle for
+ * the appropriate structure.  The handle is a string of the form
+ * "type$id", where "type" is the type of datum represented by the
+ * handle and "id" is a unique identifier for it.  This handle can
+ * then be used later by the caller to refer to the object, and
+ * internally to retrieve the actually datum from the appropriate hash
+ * table.
+ *
+ * The functions in this file do four things:
+ * 
+ * 1) Given a pointer to a datum and a string representing the type of
+ * datum to which the pointer refers, create a new handle for the
+ * datum, store the datum in the hash table using the new handle as
+ * its key, and return the new handle.
+ *
+ * 2) Given a handle, locate and return the appropriate hash table
+ * datum.
+ *
+ * 3) Given a handle, look through a table of types and unparse
+ * functions to figure out what function to call to get a string
+ * representation of the datum, call it with the appropriate pointer
+ * (obtained from the hash table) as an argument, and return the
+ * resulting string as the unparsed form of the datum.
+ *
+ * 4) Given a handle, remove that handle and its associated datum from
+ * the hash table (but don't free it -- it's assumed to have already
+ * been freed by the caller).
+ */
+
+#if HAVE_TCL_H
+#include <tcl.h>
+#elif HAVE_TCL_TCL_H
+#include <tcl/tcl.h>
+#endif
+#include <assert.h>
+
+#define SEP_STR "$"
+
+static char *memory_error = "out of memory";
+
+/*
+ * Right now, we're only using one hash table.  However, at some point
+ * in the future, we might decide to use a separate hash table for
+ * every type.  Therefore, I'm putting this function in as an
+ * abstraction so it's the only thing we'll have to change if we
+ * decide to do that.
+ *
+ * Also, this function allows us to put in just one place the code for
+ * checking to make sure that the hash table exists and initializing
+ * it if it doesn't.
+ */
+
+static TclHashTable *get_hash_table(Tcl_Interp *interp,
+				    char *type)
+{
+     static Tcl_HashTable *hash_table = 0;
+
+     if (! hash_table) {
+	  if (! (hash_table = malloc(sizeof(*hash_table)))) {
+	       Tcl_SetResult(interp, memory_error, TCL_STATIC);
+	       return 0;
+	  }
+	  Tcl_InitHashTable(hash_table, TCL_STRING_KEYS);
+     }
+     return hash_table;
+}
+
+#define MAX_ID 999999999
+#define ID_BUF_SIZE 10
+
+static Tcl_HashEntry *get_new_handle(Tcl_Interp *interp,
+				     char *type)
+{
+     static unsigned long int id_counter = 0;
+     Tcl_DString *handle;
+     char int_buf[ID_BUF_SIZE];
+     
+     if (! (handle = malloc(sizeof(*handle)))) {
+	  Tcl_SetResult(interp, memory_error, TCL_STATIC);
+	  return 0;
+     }
+     Tcl_DStringInit(handle);
+
+     assert(id_counter <= MAX_ID);
+
+     sprintf(int_buf, "%d", id_counter++);
+
+     Tcl_DStringAppend(handle, type, -1);
+     Tcl_DStringAppend(handle, SEP_STR, -1);
+     Tcl_DStringAppend(handle, int_buf, -1);
+
+     return handle;
+}
+     
+     
+Tcl_DString *tcl_krb5_create_object(Tcl_Interp *interp,
+				    char *type,
+				    ClientData datum)
+{
+     Tcl_HashTable *table;
+     Tcl_DString *handle;
+     Tcl_HashEntry *entry;
+     int entry_created = 0;
+
+     if (! (table = get_hash_table(interp, type))) {
+	  return 0;
+     }
+
+     if (! (handle = get_new_handle(interp, type))) {
+	  return 0;
+     }
+
+     if (! (entry = Tcl_CreateHashEntry(table, handle, &entry_created))) {
+	  Tcl_SetResult(interp, "error creating hash entry", TCL_STATIC);
+	  Tcl_DStringFree(handle);
+	  return TCL_ERROR;
+     }
+
+     assert(entry_created);
+
+     Tcl_SetHashValue(entry, datum);
+
+     return handle;
+}
+
+ClientData tcl_krb5_get_object(Tcl_Interp *interp,
+			       char *handle)
+{
+     char *myhandle, *id_ptr;
+     Tcl_HashTable *table;
+     Tcl_HashEntry *entry;
+
+     if (! (myhandle = strdup(handle))) {
+	  Tcl_SetResult(interp, memory_error, TCL_STATIC);
+	  return 0;
+     }
+
+     if (! (id_ptr = index(myhandle, *SEP_STR))) {
+	  free(myhandle);
+	  Tcl_ResetResult(interp);
+	  Tcl_AppendResult(interp, "malformatted handle \"", handle,
+			   "\"", 0);
+	  return 0;
+     }
+
+     *id_ptr = '\0';
+     
+     if (! (table = get_hash_table(interp, myhandle))) {
+	  free(myhandle);
+	  return 0;
+     }
+
+     free(myhandle);
+
+     if (! (entry = Tcl_FindHashEntry(table, handle))) {
+	  Tcl_ResetResult(interp);
+	  Tcl_AppendResult(interp, "no object corresponding to handle \"",
+			   handle, "\"", 0);
+	  return 0;
+     }
+
+     return(Tcl_GetHashValue(entry));
+}
+
diff --git a/krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm.c b/krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm.c
new file mode 100644
index 000000000..7e04f04e9
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm.c
@@ -0,0 +1,2030 @@
+#include "autoconf.h"
+#include <stdio.h>
+#include <string.h>
+#if HAVE_TCL_H
+#include <tcl.h>
+#elif HAVE_TCL_TCL_H
+#include <tcl/tcl.h>
+#endif
+#define USE_KADM5_API_VERSION 1
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "tcl_kadm5.h"
+#include <adb_err.h>
+
+struct flagval {
+     char *name;
+     krb5_flags val;
+};
+
+/* XXX This should probably be in the hash table like server_handle */
+static krb5_context context;
+
+struct flagval krb5_flags_array[] = {
+     {"KRB5_KDB_DISALLOW_POSTDATED", KRB5_KDB_DISALLOW_POSTDATED},
+     {"KRB5_KDB_DISALLOW_FORWARDABLE", KRB5_KDB_DISALLOW_FORWARDABLE},
+     {"KRB5_KDB_DISALLOW_TGT_BASED", KRB5_KDB_DISALLOW_TGT_BASED},
+     {"KRB5_KDB_DISALLOW_RENEWABLE", KRB5_KDB_DISALLOW_RENEWABLE},
+     {"KRB5_KDB_DISALLOW_PROXIABLE", KRB5_KDB_DISALLOW_PROXIABLE},
+     {"KRB5_KDB_DISALLOW_DUP_SKEY", KRB5_KDB_DISALLOW_DUP_SKEY},
+     {"KRB5_KDB_DISALLOW_ALL_TIX", KRB5_KDB_DISALLOW_ALL_TIX},
+     {"KRB5_KDB_REQUIRES_PRE_AUTH", KRB5_KDB_REQUIRES_PRE_AUTH},
+     {"KRB5_KDB_REQUIRES_HW_AUTH", KRB5_KDB_REQUIRES_HW_AUTH},
+     {"KRB5_KDB_REQUIRES_PWCHANGE", KRB5_KDB_REQUIRES_PWCHANGE},
+     {"KRB5_KDB_DISALLOW_SVR", KRB5_KDB_DISALLOW_SVR},
+     {"KRB5_KDB_PWCHANGE_SERVICE", KRB5_KDB_PWCHANGE_SERVICE}
+};
+
+struct flagval aux_attributes[] = {
+     {"OVSEC_KADM_POLICY",   OVSEC_KADM_POLICY}
+};
+
+struct flagval principal_mask_flags[] = {
+     {"OVSEC_KADM_PRINCIPAL", OVSEC_KADM_PRINCIPAL},
+     {"OVSEC_KADM_PRINC_EXPIRE_TIME", OVSEC_KADM_PRINC_EXPIRE_TIME},
+     {"OVSEC_KADM_PW_EXPIRATION", OVSEC_KADM_PW_EXPIRATION},
+     {"OVSEC_KADM_LAST_PWD_CHANGE", OVSEC_KADM_LAST_PWD_CHANGE},
+     {"OVSEC_KADM_ATTRIBUTES", OVSEC_KADM_ATTRIBUTES},
+     {"OVSEC_KADM_MAX_LIFE", OVSEC_KADM_MAX_LIFE},
+     {"OVSEC_KADM_MOD_TIME", OVSEC_KADM_MOD_TIME},
+     {"OVSEC_KADM_MOD_NAME", OVSEC_KADM_MOD_NAME},
+     {"OVSEC_KADM_KVNO", OVSEC_KADM_KVNO},
+     {"OVSEC_KADM_MKVNO", OVSEC_KADM_MKVNO},
+     {"OVSEC_KADM_AUX_ATTRIBUTES", OVSEC_KADM_AUX_ATTRIBUTES},
+     {"OVSEC_KADM_POLICY", OVSEC_KADM_POLICY},
+     {"OVSEC_KADM_POLICY_CLR", OVSEC_KADM_POLICY_CLR}
+};
+
+struct flagval policy_mask_flags[] = {
+     {"OVSEC_KADM_POLICY", OVSEC_KADM_POLICY},
+     {"OVSEC_KADM_PW_MAX_LIFE", OVSEC_KADM_PW_MAX_LIFE},
+     {"OVSEC_KADM_PW_MIN_LIFE", OVSEC_KADM_PW_MIN_LIFE},
+     {"OVSEC_KADM_PW_MIN_LENGTH", OVSEC_KADM_PW_MIN_LENGTH},
+     {"OVSEC_KADM_PW_MIN_CLASSES", OVSEC_KADM_PW_MIN_CLASSES},
+     {"OVSEC_KADM_PW_HISTORY_NUM", OVSEC_KADM_PW_HISTORY_NUM},
+     {"OVSEC_KADM_REF_COUNT", OVSEC_KADM_REF_COUNT}
+};
+
+struct flagval priv_flags[] = {
+     {"OVSEC_KADM_PRIV_GET", OVSEC_KADM_PRIV_GET},
+     {"OVSEC_KADM_PRIV_ADD", OVSEC_KADM_PRIV_ADD},
+     {"OVSEC_KADM_PRIV_MODIFY", OVSEC_KADM_PRIV_MODIFY},
+     {"OVSEC_KADM_PRIV_DELETE", OVSEC_KADM_PRIV_DELETE}
+};
+    
+
+static char *arg_error = "wrong # args";
+
+static Tcl_HashTable *struct_table = 0;
+
+static int put_server_handle(Tcl_Interp *interp, void *handle, char **name)
+{
+    int i = 1, newPtr = 0;
+    static char buf[20];
+    Tcl_HashEntry *entry;
+
+    if (! struct_table) {
+	if (! (struct_table =
+	       malloc(sizeof(*struct_table)))) {
+	    fprintf(stderr, "Out of memory!\n");
+	    exit(1); /* XXX */
+	}
+	Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+    }
+
+    do {
+	/*
+	 * Handles from ovsec_kadm_init() and kadm5_init() should not
+	 * be mixed during unit tests, but the API would happily
+	 * accept them.  Making the hash entry names different in
+	 * tcl_kadm.c and tcl_ovsec_kadm.c ensures that GET_HANDLE
+	 * will fail if presented a handle from the other API.
+	 */
+	sprintf(buf, "ovsec_kadm_handle%d", i);
+	entry = Tcl_CreateHashEntry(struct_table, buf, &newPtr);
+	i++;
+    } while (! newPtr);
+
+    Tcl_SetHashValue(entry, handle);
+
+    *name = buf;
+
+    return TCL_OK;
+}
+
+static int get_server_handle(Tcl_Interp *interp, char *name, void **handle) 
+{
+    Tcl_HashEntry *entry;
+
+    if(!strcasecmp(name, "null"))
+	*handle = 0;
+    else {
+	if (! (struct_table &&
+	       (entry = Tcl_FindHashEntry(struct_table, name)))) {
+	     if (strncmp(name, "kadm5_handle", 12) == 0)
+		  Tcl_AppendResult(interp, "kadm5 handle specified "
+				   "for ovsec_kadm api: ", name, 0);
+	     else 
+		  Tcl_AppendResult(interp, "unknown server handle ", name, 0);
+	    return TCL_ERROR;
+	}
+	*handle = (void *) Tcl_GetHashValue(entry);
+    }
+    return TCL_OK;
+}
+
+static int remove_server_handle(Tcl_Interp *interp, char *name) 
+{
+    Tcl_HashEntry *entry;
+
+    if (! (struct_table &&
+	   (entry = Tcl_FindHashEntry(struct_table, name)))) {
+	Tcl_AppendResult(interp, "unknown server handle ", name, 0);
+	return TCL_ERROR;
+    }
+
+    Tcl_DeleteHashEntry(entry);
+    return TCL_OK;
+}
+
+#define GET_HANDLE(num_args, do_dostruct) \
+    void *server_handle; \
+    int dostruct = 0; \
+    char *whoami = argv[0]; \
+    argv++, argc--; \
+    if ((argc > 0) && (! strcmp(argv[0], "-struct"))) { \
+	if (! do_dostruct) { \
+	    Tcl_AppendResult(interp, "-struct isn't a valid option for ", \
+			     whoami, 0); \
+	    return TCL_ERROR; \
+	} \
+	dostruct++; \
+	argv++, argc--; \
+    } \
+    if (argc != num_args + 1) { \
+	Tcl_AppendResult(interp, whoami, ": ", arg_error, 0); \
+	return TCL_ERROR; \
+    } \
+    { \
+	int htcl_ret; \
+	if ((htcl_ret = get_server_handle(interp, argv[0], &server_handle)) \
+	    != TCL_OK) { \
+	    return htcl_ret; \
+	} \
+    } \
+    argv++, argc--;
+
+static Tcl_HashTable *create_flag_table(struct flagval *flags, int size)
+{
+     Tcl_HashTable *table;
+     Tcl_HashEntry *entry;
+     int i;
+
+     if (! (table = (Tcl_HashTable *) malloc(sizeof(Tcl_HashTable)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_InitHashTable(table, TCL_STRING_KEYS);
+
+     for (i = 0; i < size; i++) {
+	  int newPtr;
+	       
+	  if (! (entry = Tcl_CreateHashEntry(table, flags[i].name, &newPtr))) {
+	       fprintf(stderr, "Out of memory!\n");
+	       exit(1); /* XXX */
+	  }
+
+	  Tcl_SetHashValue(entry, &flags[i].val);
+     }
+
+     return table;
+}
+
+
+static Tcl_DString *unparse_str(char *in_str)
+{
+     Tcl_DString *str;
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     if (! in_str) {
+	  Tcl_DStringAppend(str, "null", -1);
+     }
+     else {
+	  Tcl_DStringAppend(str, in_str, -1);
+     }
+
+     return str;
+}
+
+
+	  
+static int parse_str(Tcl_Interp *interp, char *in_str, char **out_str)
+{
+     if (! in_str) {
+	  *out_str = 0;
+     }
+     else if (! strcasecmp(in_str, "null")) {
+	  *out_str = 0;
+     }
+     else {
+	  *out_str = in_str;
+     }
+     return TCL_OK;
+}
+
+
+static void set_ok(Tcl_Interp *interp, char *string)
+{
+     Tcl_SetResult(interp, "OK", TCL_STATIC);
+     Tcl_AppendElement(interp, "OVSEC_KADM_OK");
+     Tcl_AppendElement(interp, string);
+}
+
+
+
+static Tcl_DString *unparse_err(ovsec_kadm_ret_t code)
+{
+     char *code_string;
+     const char *error_string;
+     Tcl_DString *dstring;
+
+     switch (code) {
+     case OVSEC_KADM_FAILURE: code_string = "OVSEC_KADM_FAILURE"; break;
+     case OVSEC_KADM_AUTH_GET: code_string = "OVSEC_KADM_AUTH_GET"; break;
+     case OVSEC_KADM_AUTH_ADD: code_string = "OVSEC_KADM_AUTH_ADD"; break;
+     case OVSEC_KADM_AUTH_MODIFY:
+	  code_string = "OVSEC_KADM_AUTH_MODIFY"; break;
+     case OVSEC_KADM_AUTH_DELETE:
+	  code_string = "OVSEC_KADM_AUTH_DELETE"; break;
+     case OVSEC_KADM_AUTH_INSUFFICIENT:
+	  code_string = "OVSEC_KADM_AUTH_INSUFFICIENT"; break;
+     case OVSEC_KADM_BAD_DB: code_string = "OVSEC_KADM_BAD_DB"; break;
+     case OVSEC_KADM_DUP: code_string = "OVSEC_KADM_DUP"; break;
+     case OVSEC_KADM_RPC_ERROR: code_string = "OVSEC_KADM_RPC_ERROR"; break;
+     case OVSEC_KADM_NO_SRV: code_string = "OVSEC_KADM_NO_SRV"; break;
+     case OVSEC_KADM_BAD_HIST_KEY:
+	  code_string = "OVSEC_KADM_BAD_HIST_KEY"; break;
+     case OVSEC_KADM_NOT_INIT: code_string = "OVSEC_KADM_NOT_INIT"; break;
+     case OVSEC_KADM_INIT: code_string = "OVSEC_KADM_INIT"; break;
+     case OVSEC_KADM_BAD_PASSWORD:
+	  code_string = "OVSEC_KADM_BAD_PASSWORD"; break;
+     case OVSEC_KADM_UNK_PRINC: code_string = "OVSEC_KADM_UNK_PRINC"; break;
+     case OVSEC_KADM_UNK_POLICY: code_string = "OVSEC_KADM_UNK_POLICY"; break;
+     case OVSEC_KADM_BAD_MASK: code_string = "OVSEC_KADM_BAD_MASK"; break;
+     case OVSEC_KADM_BAD_CLASS: code_string = "OVSEC_KADM_BAD_CLASS"; break;
+     case OVSEC_KADM_BAD_LENGTH: code_string = "OVSEC_KADM_BAD_LENGTH"; break;
+     case OVSEC_KADM_BAD_POLICY: code_string = "OVSEC_KADM_BAD_POLICY"; break;
+     case OVSEC_KADM_BAD_HISTORY: code_string = "OVSEC_KADM_BAD_HISTORY"; break;
+     case OVSEC_KADM_BAD_PRINCIPAL:
+	  code_string = "OVSEC_KADM_BAD_PRINCIPAL"; break;
+     case OVSEC_KADM_BAD_AUX_ATTR:
+	  code_string = "OVSEC_KADM_BAD_AUX_ATTR"; break;
+     case OVSEC_KADM_PASS_Q_TOOSHORT:
+	  code_string = "OVSEC_KADM_PASS_Q_TOOSHORT"; break;
+     case OVSEC_KADM_PASS_Q_CLASS:
+	  code_string = "OVSEC_KADM_PASS_Q_CLASS"; break;
+     case OVSEC_KADM_PASS_Q_DICT:
+	  code_string = "OVSEC_KADM_PASS_Q_DICT"; break;
+     case OVSEC_KADM_PASS_REUSE: code_string = "OVSEC_KADM_PASS_REUSE"; break;
+     case OVSEC_KADM_PASS_TOOSOON:
+	  code_string = "OVSEC_KADM_PASS_TOOSOON"; break;
+     case OVSEC_KADM_POLICY_REF:
+	  code_string = "OVSEC_KADM_POLICY_REF"; break;
+     case OVSEC_KADM_PROTECT_PRINCIPAL:
+	  code_string = "OVSEC_KADM_PROTECT_PRINCIPAL"; break;
+     case OVSEC_KADM_BAD_SERVER_HANDLE:
+	  code_string = "OVSEC_KADM_BAD_SERVER_HANDLE"; break;
+     case OVSEC_KADM_BAD_STRUCT_VERSION:
+     	  code_string = "OVSEC_KADM_BAD_STRUCT_VERSION"; break;
+     case OVSEC_KADM_OLD_STRUCT_VERSION:
+	  code_string = "OVSEC_KADM_OLD_STRUCT_VERSION"; break;
+     case OVSEC_KADM_NEW_STRUCT_VERSION:
+	  code_string = "OVSEC_KADM_NEW_STRUCT_VERSION"; break;
+     case OVSEC_KADM_BAD_API_VERSION:
+	  code_string = "OVSEC_KADM_BAD_API_VERSION"; break;
+     case OVSEC_KADM_OLD_LIB_API_VERSION:
+     	  code_string = "OVSEC_KADM_OLD_LIB_API_VERSION"; break;
+     case OVSEC_KADM_OLD_SERVER_API_VERSION:
+     	  code_string = "OVSEC_KADM_OLD_SERVER_API_VERSION"; break;
+     case OVSEC_KADM_NEW_LIB_API_VERSION:
+     	  code_string = "OVSEC_KADM_NEW_LIB_API_VERSION"; break;
+     case OVSEC_KADM_NEW_SERVER_API_VERSION:
+	  code_string = "OVSEC_KADM_NEW_SERVER_API_VERSION"; break;
+     case OVSEC_KADM_SECURE_PRINC_MISSING:
+	  code_string = "OVSEC_KADM_SECURE_PRINC_MISSING"; break;
+     case KADM5_NO_RENAME_SALT:
+	  code_string = "KADM5_NO_RENAME_SALT"; break;
+     case KADM5_BAD_CLIENT_PARAMS:
+	  code_string = "KADM5_BAD_CLIENT_PARAMS"; break;
+     case KADM5_BAD_SERVER_PARAMS:
+	  code_string = "KADM5_BAD_SERVER_PARAMS"; break;
+     case KADM5_AUTH_LIST:
+	  code_string = "KADM5_AUTH_LIST"; break;
+     case KADM5_AUTH_CHANGEPW:
+	  code_string = "KADM5_AUTH_CHANGEPW"; break;
+     case OSA_ADB_DUP: code_string = "OSA_ADB_DUP"; break;
+     case OSA_ADB_NOENT: code_string = "ENOENT"; break;
+     case OSA_ADB_DBINIT: code_string = "OSA_ADB_DBINIT"; break;
+     case OSA_ADB_BAD_POLICY: code_string = "Bad policy name"; break;
+     case OSA_ADB_BAD_PRINC: code_string = "Bad principal name"; break;
+     case OSA_ADB_BAD_DB: code_string = "Invalid database."; break;
+     case OSA_ADB_XDR_FAILURE: code_string = "OSA_ADB_XDR_FAILURE"; break;
+     case KRB5_KDB_INUSE: code_string = "KRB5_KDB_INUSE"; break;
+     case KRB5_KDB_UK_SERROR: code_string = "KRB5_KDB_UK_SERROR"; break;
+     case KRB5_KDB_UK_RERROR: code_string = "KRB5_KDB_UK_RERROR"; break;
+     case KRB5_KDB_UNAUTH: code_string = "KRB5_KDB_UNAUTH"; break;
+     case KRB5_KDB_NOENTRY: code_string = "KRB5_KDB_NOENTRY"; break;
+     case KRB5_KDB_ILL_WILDCARD: code_string = "KRB5_KDB_ILL_WILDCARD"; break;
+     case KRB5_KDB_DB_INUSE: code_string = "KRB5_KDB_DB_INUSE"; break;
+     case KRB5_KDB_DB_CHANGED: code_string = "KRB5_KDB_DB_CHANGED"; break;
+     case KRB5_KDB_TRUNCATED_RECORD:
+	  code_string = "KRB5_KDB_TRUNCATED_RECORD"; break;
+     case KRB5_KDB_RECURSIVELOCK:
+	  code_string = "KRB5_KDB_RECURSIVELOCK"; break;
+     case KRB5_KDB_NOTLOCKED: code_string = "KRB5_KDB_NOTLOCKED"; break;
+     case KRB5_KDB_BADLOCKMODE: code_string = "KRB5_KDB_BADLOCKMODE"; break;
+     case KRB5_KDB_DBNOTINITED: code_string = "KRB5_KDB_DBNOTINITED"; break;
+     case KRB5_KDB_DBINITED: code_string = "KRB5_KDB_DBINITED"; break;
+     case KRB5_KDB_ILLDIRECTION: code_string = "KRB5_KDB_ILLDIRECTION"; break;
+     case KRB5_KDB_NOMASTERKEY: code_string = "KRB5_KDB_NOMASTERKEY"; break;
+     case KRB5_KDB_BADMASTERKEY: code_string = "KRB5_KDB_BADMASTERKEY"; break;
+     case KRB5_KDB_INVALIDKEYSIZE:
+	  code_string = "KRB5_KDB_INVALIDKEYSIZE"; break;
+     case KRB5_KDB_CANTREAD_STORED:
+	  code_string = "KRB5_KDB_CANTREAD_STORED"; break;
+     case KRB5_KDB_BADSTORED_MKEY:
+	  code_string = "KRB5_KDB_BADSTORED_MKEY"; break;
+     case KRB5_KDB_CANTLOCK_DB: code_string = "KRB5_KDB_CANTLOCK_DB"; break;
+     case KRB5_KDB_DB_CORRUPT: code_string = "KRB5_KDB_DB_CORRUPT"; break;
+     case KRB5_PARSE_ILLCHAR: code_string = "KRB5_PARSE_ILLCHAR"; break;
+     case KRB5_PARSE_MALFORMED: code_string = "KRB5_PARSE_MALFORMED"; break;
+     case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: code_string = "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN"; break;
+     case KRB5_REALM_UNKNOWN: code_string = "KRB5_REALM_UNKNOWN"; break;
+     case KRB5_KDC_UNREACH: code_string = "KRB5_KDC_UNREACH"; break;
+     case KRB5_KDCREP_MODIFIED: code_string = "KRB5_KDCREP_MODIFIED"; break;
+     case KRB5KRB_AP_ERR_BAD_INTEGRITY: code_string  = "KRB5KRB_AP_ERR_BAD_INTEGRITY"; break;
+     case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: code_string = "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN"; break;
+     case EINVAL: code_string = "EINVAL"; break;
+     case ENOENT: code_string = "ENOENT"; break;
+     default:
+	 fprintf(stderr, "**** CODE %d (%s) ***\n", code,
+		 error_message (code));
+	 code_string = "UNKNOWN";
+	 break;
+     }
+
+     error_string = error_message(code);
+
+     if (! (dstring = (Tcl_DString *) malloc(sizeof(Tcl_DString)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX Do we really want to exit?  Ok if this is */
+		   /* just a test program, but what about if it gets */
+		   /* used for other things later? */
+     }
+
+     Tcl_DStringInit(dstring);
+
+     if (! (Tcl_DStringAppendElement(dstring, "ERROR") &&
+	    Tcl_DStringAppendElement(dstring, code_string) &&
+	    Tcl_DStringAppendElement(dstring, error_string))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+     
+     return dstring;
+}
+
+
+
+static void stash_error(Tcl_Interp *interp, krb5_error_code code)
+{
+     Tcl_DString *dstring = unparse_err(code);
+     Tcl_DStringResult(interp, dstring);
+     Tcl_DStringFree(dstring);
+     free(dstring);
+}
+
+
+
+static Tcl_DString *unparse_flags(struct flagval *array, int size,
+				  krb5_int32 flags)
+{
+     int i;
+     Tcl_DString *str;
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     for (i = 0; i < size; i++) {
+	  if (flags & array[i].val) {
+	       Tcl_DStringAppendElement(str, array[i].name);
+	  }
+     }
+
+     return str;
+}
+
+
+static int parse_flags(Tcl_Interp *interp, Tcl_HashTable *table,
+		       struct flagval *array, int size, char *str,
+		       krb5_flags *flags)
+{
+     int tmp, argc, i, retcode = TCL_OK;
+     char **argv;
+     Tcl_HashEntry *entry;
+
+     if (Tcl_GetInt(interp, str, &tmp) == TCL_OK) {
+	  *flags = tmp;
+	  return TCL_OK;
+     }
+     Tcl_ResetResult(interp);
+
+     if (Tcl_SplitList(interp, str, &argc, &argv) != TCL_OK) {
+	  return TCL_ERROR;
+     }
+
+     if (! table) {
+	  table = create_flag_table(array, size);
+     }
+
+     *flags = 0;
+
+     for (i = 0; i < argc; i++) {
+	  if (! (entry = Tcl_FindHashEntry(table, argv[i]))) {
+	       Tcl_AppendResult(interp, "unknown krb5 flag ", argv[i], 0);
+	       retcode = TCL_ERROR;
+	       break;
+	  }
+	  *flags |= *(krb5_flags *) Tcl_GetHashValue(entry);
+     }
+  
+     Tcl_Free(argv);
+     return(retcode);
+}
+
+static Tcl_DString *unparse_privs(krb5_flags flags)
+{
+     return unparse_flags(priv_flags, sizeof(priv_flags) /
+			  sizeof(struct flagval), flags);
+}
+
+
+static Tcl_DString *unparse_krb5_flags(krb5_flags flags)
+{
+     return unparse_flags(krb5_flags_array, sizeof(krb5_flags_array) /
+			  sizeof(struct flagval), flags);
+}
+
+static int parse_krb5_flags(Tcl_Interp *interp, char *str, krb5_flags *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, krb5_flags_array,
+				sizeof(krb5_flags_array) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+static Tcl_DString *unparse_aux_attributes(krb5_int32 flags)
+{
+     return unparse_flags(aux_attributes, sizeof(aux_attributes) /
+			  sizeof(struct flagval), flags);
+}
+
+
+static int parse_aux_attributes(Tcl_Interp *interp, char *str, long *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, aux_attributes,
+				sizeof(aux_attributes) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+static int parse_principal_mask(Tcl_Interp *interp, char *str, krb5_int32 *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, principal_mask_flags,
+				sizeof(principal_mask_flags) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+
+static int parse_policy_mask(Tcl_Interp *interp, char *str, krb5_int32 *flags)
+{
+     krb5_flags tmp;
+     static Tcl_HashTable *table = 0;
+     int tcl_ret;
+     
+     if ((tcl_ret = parse_flags(interp, table, policy_mask_flags,
+				sizeof(policy_mask_flags) /
+				sizeof(struct flagval),
+				str, &tmp)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     *flags = tmp;
+     return TCL_OK;
+}
+
+
+static Tcl_DString *unparse_principal_ent(ovsec_kadm_principal_ent_t princ)
+{
+     Tcl_DString *str, *tmp_dstring;
+     char *tmp;
+     char buf[20];
+     krb5_error_code krb5_ret;
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     tmp = 0; /* It looks to me from looking at the library source */
+	      /* code for krb5_parse_name that the pointer passed into */
+	      /* it should be initialized to 0 if I want it do be */
+	      /* allocated automatically. */
+     krb5_ret = krb5_unparse_name(context, princ->principal, &tmp);
+     if (krb5_ret) {
+	  /* XXX Do we want to return an error?  Not sure. */
+	  Tcl_DStringAppendElement(str, "[unparseable principal]");
+     }
+     else {
+	  Tcl_DStringAppendElement(str, tmp);
+	  free(tmp);
+     }
+
+     sprintf(buf, "%d", princ->princ_expire_time);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->last_pwd_change);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->pw_expiration);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->max_life);
+     Tcl_DStringAppendElement(str, buf);
+
+     tmp = 0;
+     krb5_ret = krb5_unparse_name(context, princ->mod_name, &tmp);
+     if (krb5_ret) {
+	  /* XXX */
+	  Tcl_DStringAppendElement(str, "[unparseable principal]");
+     }
+     else {
+	  Tcl_DStringAppendElement(str, tmp);
+	  free(tmp);
+     }
+
+     sprintf(buf, "%d", princ->mod_date);
+     Tcl_DStringAppendElement(str, buf);
+
+     tmp_dstring = unparse_krb5_flags(princ->attributes);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+
+     sprintf(buf, "%d", princ->kvno);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", princ->mkvno);
+     Tcl_DStringAppendElement(str, buf);
+
+     /* XXX This may be dangerous, because the contents of the policy */
+     /* field are undefined if the POLICY bit isn't set.  However, I */
+     /* think it's a bug for the field not to be null in that case */
+     /* anyway, so we should assume that it will be null so that we'll */
+     /* catch it if it isn't. */
+     
+     tmp_dstring = unparse_str(princ->policy);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+
+     tmp_dstring = unparse_aux_attributes(princ->aux_attributes);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+
+     return str;
+}
+
+     
+     
+static int parse_principal_ent(Tcl_Interp *interp, char *list,
+			       ovsec_kadm_principal_ent_t *out_princ)
+{
+     ovsec_kadm_principal_ent_t princ;
+     krb5_error_code krb5_ret;
+     int tcl_ret;
+     int argc;
+     char **argv;
+     int tmp;
+     int retcode = TCL_OK;
+
+     if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     if (argc != 12) {
+	  sprintf(interp->result, "wrong # args in principal structure (%d should be 12)",
+		  argc);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (! (princ = malloc(sizeof *princ))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+  
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &princ->principal)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     /*
+      * All of the numerical values parsed here are parsed into an
+      * "int" and then assigned into the structure in case the actual
+      * width of the field in the Kerberos structure is different from
+      * the width of an integer.
+      */
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing princ_expire_time");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->princ_expire_time = tmp;
+     
+     if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing last_pwd_change");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->last_pwd_change = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_expiration");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->pw_expiration = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing max_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->max_life = tmp;
+
+     if ((krb5_ret = krb5_parse_name(context, argv[5], &princ->mod_name)) != 0) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing mod_name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+	  
+     if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing mod_date");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->mod_date = tmp;
+
+     if ((tcl_ret = parse_krb5_flags(interp, argv[7], &princ->attributes))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing attributes");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[8], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing kvno");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->kvno = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[9], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing mkvno");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     princ->mkvno = tmp;
+
+     if ((tcl_ret = parse_str(interp, argv[10], &princ->policy)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     if(princ->policy != NULL) {
+	if(!(princ->policy = strdup(princ->policy))) {
+	    fprintf(stderr, "Out of memory!\n");
+	    exit(1);
+	}
+     }
+
+     if ((tcl_ret = parse_aux_attributes(interp, argv[11],
+					 &princ->aux_attributes)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing aux_attributes");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+finished:
+     Tcl_Free(argv);
+     *out_princ = princ;
+     return retcode;
+}
+
+
+static void free_principal_ent(ovsec_kadm_principal_ent_t *princ)
+{
+     krb5_free_principal(context, (*princ)->principal);
+     krb5_free_principal(context, (*princ)->mod_name);
+     free(*princ);
+     *princ = 0;
+}
+
+static Tcl_DString *unparse_policy_ent(ovsec_kadm_policy_ent_t policy)
+{
+     Tcl_DString *str, *tmp_dstring;
+     char buf[20];
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     tmp_dstring = unparse_str(policy->policy);
+     Tcl_DStringAppendElement(str, tmp_dstring->string);
+     Tcl_DStringFree(tmp_dstring);
+     free(tmp_dstring);
+     
+     sprintf(buf, "%ld", policy->pw_min_life);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_max_life);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_min_length);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_min_classes);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->pw_history_num);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%ld", policy->policy_refcnt);
+     Tcl_DStringAppendElement(str, buf);
+
+     return str;
+}
+
+     
+     
+static int parse_policy_ent(Tcl_Interp *interp, char *list,
+			    ovsec_kadm_policy_ent_t *out_policy)
+{
+     ovsec_kadm_policy_ent_t policy;
+     int tcl_ret;
+     int argc;
+     char **argv;
+     int tmp;
+     int retcode = TCL_OK;
+
+     if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
+	  return tcl_ret;
+     }
+
+     if (argc != 7) {
+	  sprintf(interp->result, "wrong # args in policy structure (%d should be 7)",
+		  argc);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (! (policy = malloc(sizeof *policy))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+  
+     if ((tcl_ret = parse_str(interp, argv[0], &policy->policy)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if(policy->policy != NULL) {
+	if (! (policy->policy = strdup(policy->policy))) {
+	    fprintf(stderr, "Out of memory!\n");
+	    exit(1); /* XXX */
+	}
+     }
+     
+     /*
+      * All of the numerical values parsed here are parsed into an
+      * "int" and then assigned into the structure in case the actual
+      * width of the field in the Kerberos structure is different from
+      * the width of an integer.
+      */
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_min_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_min_life = tmp;
+     
+     if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_max_life");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_max_life = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_min_length");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_min_length = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_min_classes");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_min_classes = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[5], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_history_num");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_history_num = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy_refcnt");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->policy_refcnt = tmp;
+
+finished:
+     Tcl_Free(argv);
+     *out_policy = policy;
+     return retcode;
+}
+
+
+static void free_policy_ent(ovsec_kadm_policy_ent_t *policy)
+{
+     free(*policy);
+     *policy = 0;
+}
+
+static Tcl_DString *unparse_keytype(krb5_enctype enctype)
+{
+     Tcl_DString *str;
+     char buf[50];
+
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     switch (enctype) {
+	  /* XXX is this right? */
+     case ENCTYPE_NULL: Tcl_DStringAppend(str, "ENCTYPE_NULL", -1); break;
+     case ENCTYPE_DES_CBC_CRC:
+	  Tcl_DStringAppend(str, "ENCTYPE_DES_CBC_CRC", -1); break;
+     default:
+	  sprintf(buf, "UNKNOWN KEYTYPE (0x%x)", enctype);
+	  Tcl_DStringAppend(str, buf, -1);
+	  break;
+     }
+
+     return str;
+}
+	  
+	  
+static Tcl_DString *unparse_keyblock(krb5_keyblock *keyblock)
+{
+     Tcl_DString *str;
+     Tcl_DString *keytype;
+     int i;
+     
+     if (! (str = malloc(sizeof(*str)))) {
+	  fprintf(stderr, "Out of memory!\n");
+	  exit(1); /* XXX */
+     }
+
+     Tcl_DStringInit(str);
+
+     keytype = unparse_keytype(keyblock->enctype);
+     Tcl_DStringAppendElement(str, keytype->string);
+     Tcl_DStringFree(keytype);
+     free(keytype);
+     if (keyblock->length == 0) {
+	  Tcl_DStringAppendElement(str, "0x00");
+     }
+     else {
+	  Tcl_DStringAppendElement(str, "0x");
+	  for (i = 0; i < keyblock->length; i++) {
+	       char buf[3];
+	       sprintf(buf, "%02x", (int) keyblock->contents[i]);
+	       Tcl_DStringAppend(str, buf, -1);
+	  }
+     }
+
+     return str;
+}
+
+
+
+static int tcl_ovsec_kadm_init(ClientData clientData, Tcl_Interp *interp,
+			       int argc, char *argv[])
+{
+     ovsec_kadm_ret_t ret;
+     char *client_name, *pass, *service_name, *realm;
+     int tcl_ret;
+     krb5_ui_4 struct_version, api_version;
+     char *handle_var;
+     void *server_handle;
+     char *handle_name;
+     char *whoami = argv[0];
+
+     argv++, argc--;
+
+     kadm5_init_krb5_context(&context);
+
+     if (argc != 7) {
+	  Tcl_AppendResult(interp, whoami, ": ", arg_error, 0);
+	  return TCL_ERROR;
+     }
+
+     if (((tcl_ret = parse_str(interp, argv[0], &client_name)) != TCL_OK) ||
+	 ((tcl_ret = parse_str(interp, argv[1], &pass)) != TCL_OK) ||
+	 ((tcl_ret = parse_str(interp, argv[2], &service_name)) != TCL_OK) ||
+	 ((tcl_ret = parse_str(interp, argv[3], &realm)) != TCL_OK) ||
+	 ((tcl_ret = Tcl_GetInt(interp, argv[4], (int *) &struct_version)) !=
+	  TCL_OK) ||
+	 ((tcl_ret = Tcl_GetInt(interp, argv[5], (int *) &api_version)) !=
+	  TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     handle_var = argv[6];
+
+     if (! (handle_var && *handle_var)) {
+	 Tcl_SetResult(interp, "must specify server handle variable name",
+		       TCL_STATIC);
+	 return TCL_ERROR;
+     }
+     
+     ret = ovsec_kadm_init(client_name, pass, service_name, realm,
+			   struct_version, api_version, NULL, &server_handle);
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+
+     if ((tcl_ret = put_server_handle(interp, server_handle, &handle_name))
+	 != TCL_OK) {
+	 return tcl_ret;
+     }
+     
+     if (! Tcl_SetVar(interp, handle_var, handle_name, TCL_LEAVE_ERR_MSG)) {
+	 return TCL_ERROR;
+     }
+     
+     set_ok(interp, "OV Admin system initialized.");
+     return TCL_OK;
+}
+
+
+
+static int tcl_ovsec_kadm_destroy(ClientData clientData, Tcl_Interp *interp,
+				  int argc, char *argv[])
+{
+     ovsec_kadm_ret_t ret;
+     int tcl_ret;
+
+     GET_HANDLE(0, 0);
+
+     ret = ovsec_kadm_destroy(server_handle);
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+
+     if ((tcl_ret = remove_server_handle(interp, argv[-1])) != TCL_OK) {
+	 return tcl_ret;
+     }
+     
+     set_ok(interp, "OV Admin system deinitialized.");
+     return TCL_OK;
+}	  
+
+static int tcl_ovsec_kadm_create_principal(ClientData clientData, 
+					   Tcl_Interp *interp,
+					   int argc, char *argv[])
+{
+     int tcl_ret;
+     ovsec_kadm_ret_t ret;
+     int retcode = TCL_OK;
+     char *princ_string;
+     ovsec_kadm_principal_ent_t princ = 0;
+     krb5_int32 mask;
+     char *pw;
+#ifdef OVERRIDE     
+     int override_qual;
+#endif     
+
+     GET_HANDLE(3, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing principal");
+	  return tcl_ret;
+     }
+
+     if (princ_string &&
+	 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+
+     if ((tcl_ret = parse_str(interp, argv[2], &pw)) != TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+#ifdef OVERRIDE
+     if ((tcl_ret = Tcl_GetBoolean(interp, argv[3], &override_qual)) !=
+	 TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+#endif     
+
+#ifdef OVERRIDE
+     ret = ovsec_kadm_create_principal(server_handle, princ, mask, pw,
+				       override_qual);
+#else
+     ret = ovsec_kadm_create_principal(server_handle, princ, mask, pw);
+#endif     
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     else {
+	  set_ok(interp, "Principal created.");
+     }
+
+finished:
+     if (princ) {
+	  free_principal_ent(&princ);
+     }
+     return retcode;
+}
+
+
+
+static int tcl_ovsec_kadm_delete_principal(ClientData clientData, 
+					   Tcl_Interp *interp,
+					   int argc, char *argv[])
+{
+     krb5_principal princ;
+     krb5_error_code krb5_ret;
+     ovsec_kadm_ret_t ret;
+     int tcl_ret;
+     char *name;
+     
+     GET_HANDLE(1, 0);
+
+     if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
+	return tcl_ret;
+     if(name != NULL) {
+        krb5_ret = krb5_parse_name(context, name, &princ);
+	if (krb5_ret) {
+	    stash_error(interp, krb5_ret);
+	    Tcl_AppendElement(interp, "while parsing principal");
+	    return TCL_ERROR;
+	}
+     } else princ = NULL;
+     ret = ovsec_kadm_delete_principal(server_handle, princ);
+
+     if(princ != NULL) 
+	krb5_free_principal(context, princ);
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Principal deleted.");
+	  return TCL_OK;
+     }
+}
+
+
+
+static int tcl_ovsec_kadm_modify_principal(ClientData clientData, 
+					   Tcl_Interp *interp,
+					   int argc, char *argv[])
+{
+     char *princ_string;
+     ovsec_kadm_principal_ent_t princ = 0;
+     int tcl_ret;
+     krb5_int32 mask;
+     int retcode = TCL_OK;
+     ovsec_kadm_ret_t ret;
+
+     GET_HANDLE(2, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing principal");
+	  return tcl_ret;
+     }
+
+     if (princ_string &&
+	 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+     
+     if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = ovsec_kadm_modify_principal(server_handle, princ, mask);
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Principal modified.");
+     }
+
+finished:
+     if (princ) {
+	  free_principal_ent(&princ);
+     }
+     return retcode;
+}
+
+
+static int tcl_ovsec_kadm_rename_principal(ClientData clientData,
+					   Tcl_Interp *interp,
+					   int argc, char *argv[])
+{
+     krb5_principal source, target;
+     krb5_error_code krb5_ret;
+     ovsec_kadm_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(2, 0);
+
+     krb5_ret = krb5_parse_name(context, argv[0], &source);
+     if (krb5_ret) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing source");
+	  return TCL_ERROR;
+     }
+
+     krb5_ret = krb5_parse_name(context, argv[1], &target);
+     if (krb5_ret) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing target");
+	  krb5_free_principal(context, source);
+	  return TCL_ERROR;
+     }
+
+     ret = ovsec_kadm_rename_principal(server_handle, source, target);
+
+     if (ret == OVSEC_KADM_OK) {
+	  set_ok(interp, "Principal renamed.");
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+     krb5_free_principal(context, source);
+     krb5_free_principal(context, target);
+     return retcode;
+}
+
+
+	  
+static int tcl_ovsec_kadm_chpass_principal(ClientData clientData, 
+					   Tcl_Interp *interp,
+					   int argc, char *argv[])
+{
+     krb5_principal princ;
+     char *pw;
+#ifdef OVERRIDE     
+     int override_qual;
+#endif     
+     krb5_error_code krb5_ret;
+     int retcode = TCL_OK;
+     ovsec_kadm_ret_t ret;
+
+     GET_HANDLE(2, 0);
+
+     krb5_ret = krb5_parse_name(context, argv[0], &princ);
+     if (krb5_ret) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal name");
+	  return TCL_ERROR;
+     }
+
+     if (parse_str(interp, argv[1], &pw) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing password");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+#ifdef OVERRIDE
+     if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing override_qual");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     
+     ret = ovsec_kadm_chpass_principal(server_handle,
+				       princ, pw, override_qual);
+#else
+     ret = ovsec_kadm_chpass_principal(server_handle, princ, pw);
+#endif     
+
+     if (ret == OVSEC_KADM_OK) {
+	  set_ok(interp, "Password changed.");
+	  goto finished;
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     krb5_free_principal(context, princ);
+     return retcode;
+}
+
+
+
+static int tcl_ovsec_kadm_chpass_principal_util(ClientData clientData,
+						Tcl_Interp *interp,
+						int argc, char *argv[])
+{
+     krb5_principal princ;
+     char *new_pw;
+#ifdef OVERRIDE     
+     int override_qual;
+#endif     
+     char *pw_ret, *pw_ret_var;
+     char msg_ret[1024], *msg_ret_var;
+     krb5_error_code krb5_ret;
+     ovsec_kadm_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(4, 0);
+
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &princ))) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal name");
+	  return TCL_ERROR;
+     }
+
+     if (parse_str(interp, argv[1], &new_pw) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing new password");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+#ifdef OVERRIDE
+     if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing override_qual");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+#endif
+     if (parse_str(interp, argv[3], &pw_ret_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_ret variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     if (parse_str(interp, argv[4], &msg_ret_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing msg_ret variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = ovsec_kadm_chpass_principal_util(server_handle, princ, new_pw,
+#ifdef OVERRIDE     
+					    override_qual,
+#endif					    
+					    pw_ret_var ? &pw_ret : 0,
+					    msg_ret_var ? msg_ret : 0);
+
+     if (ret == OVSEC_KADM_OK) {
+	  if (pw_ret_var &&
+	      (! Tcl_SetVar(interp, pw_ret_var, pw_ret,
+			    TCL_LEAVE_ERR_MSG))) {
+	       Tcl_AppendElement(interp, "while setting pw_ret variable");
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  if (msg_ret_var &&
+	      (! Tcl_SetVar(interp, msg_ret_var, msg_ret,
+			    TCL_LEAVE_ERR_MSG))) {
+	       Tcl_AppendElement(interp,
+				 "while setting msg_ret variable");
+	       retcode = TCL_ERROR;
+	       goto finished;
+	  }
+	  set_ok(interp, "Password changed.");
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     krb5_free_principal(context, princ);
+     return retcode;
+}
+
+
+
+static int tcl_ovsec_kadm_randkey_principal(ClientData clientData,
+					    Tcl_Interp *interp,
+					    int argc, char *argv[])
+{
+     krb5_principal princ;
+     krb5_keyblock *keyblock;
+     char *keyblock_var;
+     Tcl_DString *keyblock_dstring = 0;
+#ifdef OVERRIDE     
+     int override_qual;
+#endif     
+     krb5_error_code krb5_ret;
+     ovsec_kadm_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(2, 0);
+
+     if ((krb5_ret = krb5_parse_name(context, argv[0], &princ))) {
+	  stash_error(interp, krb5_ret);
+	  Tcl_AppendElement(interp, "while parsing principal name");
+	  return TCL_ERROR;
+     }
+
+     if (parse_str(interp, argv[1], &keyblock_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing keyblock variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+#ifdef OVERRIDE
+     if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing override_qual");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = ovsec_kadm_randkey_principal(server_handle,
+					princ, keyblock_var ? &keyblock : 0,
+					override_qual);
+#else
+     ret = ovsec_kadm_randkey_principal(server_handle,
+					princ, keyblock_var ? &keyblock : 0);
+#endif					
+
+     if (ret == OVSEC_KADM_OK) {
+	  if (keyblock_var) {
+	       keyblock_dstring = unparse_keyblock(keyblock);
+	       if (! Tcl_SetVar(interp, keyblock_var,
+				keyblock_dstring->string,
+				TCL_LEAVE_ERR_MSG)) {
+		    Tcl_AppendElement(interp,
+				      "while setting keyblock variable");
+		    retcode = TCL_ERROR;
+		    goto finished;
+	       }
+	  }
+	  set_ok(interp, "Key randomized.");
+	  
+     }
+     else {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     krb5_free_principal(context, princ);
+     if (keyblock_dstring) {
+	  Tcl_DStringFree(keyblock_dstring);
+	  free(keyblock_dstring);
+     }
+     return retcode;
+}
+
+
+
+static int tcl_ovsec_kadm_get_principal(ClientData clientData,
+					Tcl_Interp *interp,
+					int argc, char *argv[])
+{
+     krb5_principal princ;
+     ovsec_kadm_principal_ent_t ent;
+     Tcl_DString *ent_dstring = 0;
+     char *ent_var;
+     char *name;
+     krb5_error_code krb5_ret;
+     int tcl_ret;
+     ovsec_kadm_ret_t ret;
+     int retcode = TCL_OK;
+     
+     GET_HANDLE(2, 1);
+
+     if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
+	return tcl_ret;
+     if(name != NULL) {
+	if ((krb5_ret = krb5_parse_name(context, name, &princ))) {
+	    stash_error(interp, krb5_ret);
+	    Tcl_AppendElement(interp, "while parsing principal name");
+	    return TCL_ERROR;
+	}
+     } else princ = NULL;
+
+     if ((tcl_ret = parse_str(interp, argv[1], &ent_var)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry variable name");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     
+     ret = ovsec_kadm_get_principal(server_handle, princ, ent_var ? &ent : 0);
+
+     if (ret == OVSEC_KADM_OK) {
+	  if (ent_var) {
+	       if (dostruct) {
+		    char buf[20];
+		    int i = 1, newPtr = 0;
+		    Tcl_HashEntry *entry;
+		    
+		    if (! struct_table) {
+			 if (! (struct_table =
+				malloc(sizeof(*struct_table)))) {
+			      fprintf(stderr, "Out of memory!\n");
+			      exit(1); /* XXX */
+			 }
+			 Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+		    }
+
+		    do {
+			 sprintf(buf, "principal%d", i);
+			 entry = Tcl_CreateHashEntry(struct_table, buf,
+						     &newPtr);
+			 i++;
+		    } while (! newPtr);
+
+		    Tcl_SetHashValue(entry, ent);
+		    if (! Tcl_SetVar(interp, ent_var, buf,
+				     TCL_LEAVE_ERR_MSG)) {
+			 Tcl_AppendElement(interp,
+					   "while setting entry variable");
+			 Tcl_DeleteHashEntry(entry);
+			 retcode = TCL_ERROR;
+			 goto finished;
+		    }
+		    set_ok(interp, "Principal structure retrieved.");
+	       }
+	       else {
+		    ent_dstring = unparse_principal_ent(ent);
+		    if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
+				     TCL_LEAVE_ERR_MSG)) {
+			 Tcl_AppendElement(interp,
+					   "while setting entry variable");
+			 retcode = TCL_ERROR;
+			 goto finished;
+		    }
+		    set_ok(interp, "Principal retrieved.");
+	       }
+	  }
+     }
+     else {
+	  ent = 0;
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     if (ent_dstring) {
+	  Tcl_DStringFree(ent_dstring);
+	  free(ent_dstring);
+     }
+     if(princ != NULL)
+	krb5_free_principal(context, princ);
+     if (ent && ((! dostruct) || (retcode != TCL_OK))) {
+	 if ((ret = ovsec_kadm_free_principal_ent(server_handle, ent)) &&
+	     (retcode == TCL_OK)) {
+	     stash_error(interp, ret);
+	     retcode = TCL_ERROR;
+	 }
+     }
+     return retcode;
+}
+     
+static int tcl_ovsec_kadm_create_policy(ClientData clientData,
+					Tcl_Interp *interp,
+					int argc, char *argv[])
+{
+     int tcl_ret;
+     ovsec_kadm_ret_t ret;
+     int retcode = TCL_OK;
+     char *policy_string;
+     ovsec_kadm_policy_ent_t policy = 0;
+     krb5_int32 mask;
+
+     GET_HANDLE(2, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy");
+	  return tcl_ret;
+     }
+
+     if (policy_string &&
+	 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = tcl_ret;
+	  goto finished;
+     }
+
+     ret = ovsec_kadm_create_policy(server_handle, policy, mask);
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     else {
+	  set_ok(interp, "Policy created.");
+     }
+
+finished:
+     if (policy) {
+	  free_policy_ent(&policy);
+     }
+     return retcode;
+}
+
+
+
+static int tcl_ovsec_kadm_delete_policy(ClientData clientData,
+					Tcl_Interp *interp,
+					int argc, char *argv[])
+{
+     ovsec_kadm_ret_t ret;
+     char *policy;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &policy) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy name");
+	  return TCL_ERROR;
+     }
+     
+     ret = ovsec_kadm_delete_policy(server_handle, policy);
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Policy deleted.");
+	  return TCL_OK;
+     }
+}
+
+
+
+static int tcl_ovsec_kadm_modify_policy(ClientData clientData,
+					Tcl_Interp *interp,
+					int argc, char *argv[])
+{
+     char *policy_string;
+     ovsec_kadm_policy_ent_t policy = 0;
+     int tcl_ret;
+     krb5_int32 mask;
+     int retcode = TCL_OK;
+     ovsec_kadm_ret_t ret;
+
+     GET_HANDLE(2, 0);
+
+     if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy");
+	  return tcl_ret;
+     }
+
+     if (policy_string &&
+	 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
+	  != TCL_OK)) {
+	  return tcl_ret;
+     }
+
+     if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+
+     ret = ovsec_kadm_modify_policy(server_handle, policy, mask);
+
+     if (ret != OVSEC_KADM_OK) {
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+     else {
+	  set_ok(interp, "Policy modified.");
+     }
+
+finished:
+     if (policy) {
+	  free_policy_ent(&policy);
+     }
+     return retcode;
+}
+
+
+static int tcl_ovsec_kadm_get_policy(ClientData clientData,
+				     Tcl_Interp *interp,
+				     int argc, char *argv[])
+{
+     ovsec_kadm_policy_ent_t ent;
+     Tcl_DString *ent_dstring = 0;
+     char *policy;
+     char *ent_var;
+     ovsec_kadm_ret_t ret;
+     int retcode = TCL_OK;
+
+     GET_HANDLE(2, 1);
+
+     if (parse_str(interp, argv[0], &policy) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing policy name");
+	  return TCL_ERROR;
+     }
+     
+     if (parse_str(interp, argv[1], &ent_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry variable name");
+	  return TCL_ERROR;
+     }
+     
+     ret = ovsec_kadm_get_policy(server_handle, policy, ent_var ? &ent : 0);
+
+     if (ret == OVSEC_KADM_OK) {
+	  if (ent_var) {
+	       if (dostruct) {
+		    char buf[20];
+		    int i = 1, newPtr = 0;
+		    Tcl_HashEntry *entry;
+		    
+		    if (! struct_table) {
+			 if (! (struct_table =
+				malloc(sizeof(*struct_table)))) {
+			      fprintf(stderr, "Out of memory!\n");
+			      exit(1); /* XXX */
+			 }
+			 Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+		    }
+
+		    do {
+			 sprintf(buf, "policy%d", i);
+			 entry = Tcl_CreateHashEntry(struct_table, buf,
+						     &newPtr);
+			 i++;
+		    } while (! newPtr);
+
+		    Tcl_SetHashValue(entry, ent);
+		    if (! Tcl_SetVar(interp, ent_var, buf,
+				     TCL_LEAVE_ERR_MSG)) {
+			 Tcl_AppendElement(interp,
+					   "while setting entry variable");
+			 Tcl_DeleteHashEntry(entry);
+			 retcode = TCL_ERROR;
+			 goto finished;
+		    }
+		    set_ok(interp, "Policy structure retrieved.");
+	       }
+	       else {
+		    ent_dstring = unparse_policy_ent(ent);
+		    if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
+				     TCL_LEAVE_ERR_MSG)) {
+			 Tcl_AppendElement(interp,
+					   "while setting entry variable");
+			 retcode = TCL_ERROR;
+			 goto finished;
+		    }
+		    set_ok(interp, "Policy retrieved.");
+	       }
+	  }
+     }
+     else {
+	  ent = 0;
+	  stash_error(interp, ret);
+	  retcode = TCL_ERROR;
+     }
+
+finished:
+     if (ent_dstring) {
+	  Tcl_DStringFree(ent_dstring);
+	  free(ent_dstring);
+     }
+     if (ent && ((! dostruct) || (retcode != TCL_OK))) {
+	 if ((ret = ovsec_kadm_free_policy_ent(server_handle, ent)) &&
+	     (retcode == TCL_OK)) {
+	     stash_error(interp, ret);
+	     retcode = TCL_ERROR;
+	 }
+     }
+     return retcode;
+}
+
+     
+     
+static int tcl_ovsec_kadm_free_principal_ent(ClientData clientData,
+					     Tcl_Interp *interp,
+					     int argc, char *argv[])
+{
+     char *ent_name;
+     ovsec_kadm_principal_ent_t ent;
+     ovsec_kadm_ret_t ret;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry name");
+	  return TCL_ERROR;
+     }
+
+     if ((! ent_name) &&
+	 (ret = ovsec_kadm_free_principal_ent(server_handle, 0))) {
+	 stash_error(interp, ret);
+	 return TCL_ERROR;
+     }
+     else {
+	  Tcl_HashEntry *entry;
+
+	  if (strncmp(ent_name, "principal", sizeof("principal")-1)) {
+	       Tcl_AppendResult(interp, "invalid principal handle \"",
+				ent_name, "\"", 0);
+	       return TCL_ERROR;
+	  }
+	  if (! struct_table) {
+	       if (! (struct_table = malloc(sizeof(*struct_table)))) {
+		    fprintf(stderr, "Out of memory!\n");
+		    exit(1); /* XXX */
+	       }
+	       Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+	  }
+	  
+	  if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
+	       Tcl_AppendResult(interp, "principal handle \"", ent_name,
+				"\" not found", 0);
+	       return TCL_ERROR;
+	  }
+
+	  ent = (ovsec_kadm_principal_ent_t) Tcl_GetHashValue(entry);
+
+	  if ((ret = ovsec_kadm_free_principal_ent(server_handle, ent))) {
+	      stash_error(interp, ret);
+	      return TCL_ERROR;
+	  }
+	  Tcl_DeleteHashEntry(entry);
+     }
+     set_ok(interp, "Principal freed.");
+     return TCL_OK;
+}
+	  
+		    
+static int tcl_ovsec_kadm_free_policy_ent(ClientData clientData,
+					  Tcl_Interp *interp,
+					  int argc, char *argv[])
+{
+     char *ent_name;
+     ovsec_kadm_policy_ent_t ent;
+     ovsec_kadm_ret_t ret;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing entry name");
+	  return TCL_ERROR;
+     }
+
+     if ((! ent_name) &&
+	 (ret = ovsec_kadm_free_policy_ent(server_handle, 0))) {
+	 stash_error(interp, ret);
+	 return TCL_ERROR;
+     }
+     else {
+	  Tcl_HashEntry *entry;
+
+	  if (strncmp(ent_name, "policy", sizeof("policy")-1)) {
+	       Tcl_AppendResult(interp, "invalid principal handle \"",
+				ent_name, "\"", 0);
+	       return TCL_ERROR;
+	  }
+	  if (! struct_table) {
+	       if (! (struct_table = malloc(sizeof(*struct_table)))) {
+		    fprintf(stderr, "Out of memory!\n");
+		    exit(1); /* XXX */
+	       }
+	       Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
+	  }
+	  
+	  if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
+	       Tcl_AppendResult(interp, "policy handle \"", ent_name,
+				"\" not found", 0);
+	       return TCL_ERROR;
+	  }
+
+	  ent = (ovsec_kadm_policy_ent_t) Tcl_GetHashValue(entry);
+
+	  if ((ret = ovsec_kadm_free_policy_ent(server_handle, ent))) {
+	      stash_error(interp, ret);
+	      return TCL_ERROR;
+	  }
+	  Tcl_DeleteHashEntry(entry);
+     }
+     set_ok(interp, "Policy freed.");
+     return TCL_OK;
+}
+	  
+		    
+static int tcl_ovsec_kadm_get_privs(ClientData clientData, Tcl_Interp *interp,
+				    int argc, char *argv[])
+{
+     char *set_ret;
+     ovsec_kadm_ret_t ret;
+     char *priv_var;
+     long privs;
+
+     GET_HANDLE(1, 0);
+
+     if (parse_str(interp, argv[0], &priv_var) != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing privs variable name");
+	  return TCL_ERROR;
+     }
+
+     ret = ovsec_kadm_get_privs(server_handle, priv_var ? &privs : 0);
+
+     if (ret == OVSEC_KADM_OK) {
+	  if (priv_var) {
+	       Tcl_DString *str = unparse_privs(privs);
+	       set_ret = Tcl_SetVar(interp, priv_var, str->string,
+				    TCL_LEAVE_ERR_MSG);
+	       Tcl_DStringFree(str);
+	       free(str);
+	       if (! set_ret) {
+		    Tcl_AppendElement(interp, "while setting priv variable");
+		    return TCL_ERROR;
+	       }
+	  }
+	  set_ok(interp, "Privileges retrieved.");
+	  return TCL_OK;
+     }
+     else {
+	  stash_error(interp, ret);
+	  return TCL_ERROR;
+     }
+}
+		    
+
+void Tcl_ovsec_kadm_init(Tcl_Interp *interp)
+{
+    char buf[20];
+
+     Tcl_SetVar(interp, "OVSEC_KADM_ADMIN_SERVICE",
+		OVSEC_KADM_ADMIN_SERVICE, TCL_GLOBAL_ONLY);
+     Tcl_SetVar(interp, "OVSEC_KADM_CHANGEPW_SERVICE",
+		OVSEC_KADM_CHANGEPW_SERVICE, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", OVSEC_KADM_STRUCT_VERSION);
+     Tcl_SetVar(interp, "OVSEC_KADM_STRUCT_VERSION", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", OVSEC_KADM_API_VERSION_1);
+     Tcl_SetVar(interp, "OVSEC_KADM_API_VERSION_1", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", OVSEC_KADM_API_VERSION_MASK);
+     Tcl_SetVar(interp, "OVSEC_KADM_API_VERSION_MASK", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", OVSEC_KADM_STRUCT_VERSION_MASK);
+     Tcl_SetVar(interp, "OVSEC_KADM_STRUCT_VERSION_MASK", buf,
+		TCL_GLOBAL_ONLY);
+
+     Tcl_CreateCommand(interp, "ovsec_kadm_init", tcl_ovsec_kadm_init, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_destroy", tcl_ovsec_kadm_destroy, 0,
+		       0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_create_principal",
+		       tcl_ovsec_kadm_create_principal, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_delete_principal",
+		       tcl_ovsec_kadm_delete_principal, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_modify_principal",
+		       tcl_ovsec_kadm_modify_principal, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_rename_principal",
+		       tcl_ovsec_kadm_rename_principal, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_chpass_principal",
+		       tcl_ovsec_kadm_chpass_principal, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_chpass_principal_util",
+		       tcl_ovsec_kadm_chpass_principal_util, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_randkey_principal",
+		       tcl_ovsec_kadm_randkey_principal, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_get_principal",
+		       tcl_ovsec_kadm_get_principal, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_create_policy",
+		       tcl_ovsec_kadm_create_policy, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_delete_policy",
+		       tcl_ovsec_kadm_delete_policy, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_modify_policy",
+		       tcl_ovsec_kadm_modify_policy, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_get_policy",
+		       tcl_ovsec_kadm_get_policy, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_free_principal_ent",
+		       tcl_ovsec_kadm_free_principal_ent, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_free_policy_ent",
+		       tcl_ovsec_kadm_free_policy_ent, 0, 0);
+     Tcl_CreateCommand(interp, "ovsec_kadm_get_privs",
+		       tcl_ovsec_kadm_get_privs, 0, 0);
+}
diff --git a/krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm_syntax b/krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm_syntax
new file mode 100644
index 000000000..3fc77fbcb
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/tcl_ovsec_kadm_syntax
@@ -0,0 +1,57 @@
+Here's a brief summary of the syntax of the tcl versions of the
+ovsec_kadm commands:
+
+string		Can be a string or "null" which will turn into a null pointer
+principal_ent	A 12-field list in the order of the principal_ent
+		structure: {string number number number number string
+			    number mask number number string mask}
+		It can also be "null", like a string, to indicate that
+		a null structure pointer should be used.
+mask		Either a number, representing the actual value of the
+		mask, or a sequence of symbols in a list.  Example:
+		{PRINCIPAL ATTRIBUTES} is a valid principal mask.
+boolean		"1", "0", "true", "false", etc.
+varname		The name of a Tcl variable, or "null" to not assign.
+policy_ent	Similar to principal_ent, but with seven fields,
+		instead of 12.  The first is a string, and the rest
+		are numbers.
+
+init
+		client_name:string pass:string service_name:string
+		realm:string struct_version:int api_version:int
+		server_handle_ret:varname
+destroy
+		server_handle:string
+create_principal
+		server_handle:string principal:principal_ent
+		mask:principal_mask password:string
+delete_principal
+		server_handle:string name:string
+modify_principal
+		server_handle:string principal_principal_ent
+		mask:principal_mask
+rename_principal
+		server_handle:string source:string target:string
+chpass_principal
+		server_handle:string name:string password:string
+chpass_principal_util
+		server_handle:string name:string password:string
+		pw_ret:varname msg_ret:varname
+randkey_principal
+		server_handle:string name:string keyblock_var:varname
+get_principal [-struct]
+		server_handle:string name:string princ_var:varname
+create_policy
+		server_handle:string policy:policy_ent mask:policy_mask
+delete_policy
+		server_handle:string name:string
+modify_policy
+		server_handle:string policy:policy_ent mask:policy_mask
+get_policy [-struct]
+		server_handle:string name:string policy_var:varname
+free_principal_ent
+		server_handle:string handle:string
+free_policy_ent
+		server_handle:string handle:string
+get_privs
+		server_handle:string privs:priv_var
diff --git a/krb5-1-6/src/kadmin/testing/util/test.c b/krb5-1-6/src/kadmin/testing/util/test.c
new file mode 100644
index 000000000..ef8546deb
--- /dev/null
+++ b/krb5-1-6/src/kadmin/testing/util/test.c
@@ -0,0 +1,38 @@
+#include "autoconf.h"
+#if HAVE_TCL_H
+#include <tcl.h>
+#elif HAVE_TCL_TCL_H
+#include <tcl/tcl.h>
+#endif
+#include "tcl_kadm5.h"
+
+#define _TCL_MAIN ((TCL_MAJOR_VERSION * 100 + TCL_MINOR_VERSION) >= 704)
+
+#if _TCL_MAIN
+int
+main(argc, argv)
+    int argc;			/* Number of command-line arguments. */
+    char **argv;		/* Values of command-line arguments. */
+{
+    Tcl_Main(argc, argv, Tcl_AppInit);
+    return 0;			/* Needed only to prevent compiler warning. */
+}
+#else
+/*
+ * The following variable is a special hack that allows applications
+ * to be linked using the procedure "main" from the Tcl library.  The
+ * variable generates a reference to "main", which causes main to
+ * be brought in from the library (and all of Tcl with it).
+ */
+
+extern int main();
+int *tclDummyMainPtr = (int *) main;
+#endif
+
+int Tcl_AppInit(Tcl_Interp *interp)
+{
+     Tcl_ovsec_kadm_init(interp);
+     Tcl_kadm5_init(interp);
+
+     return(TCL_OK);
+}
diff --git a/krb5-1-6/src/kdc/.saberinit b/krb5-1-6/src/kdc/.saberinit
new file mode 100644
index 000000000..d79f57ed0
--- /dev/null
+++ b/krb5-1-6/src/kdc/.saberinit
@@ -0,0 +1,35 @@
+suppress 223
+suppress 285
+suppress 33 on v4_klog
+suppress 34 on v4_klog
+suppress 36 on sendto
+suppress 35
+suppress 287 on usage
+suppress 287 on sin
+suppress 349 on krb_err_txt
+suppress 349 on krbONE
+suppress 349 on _ctype_
+suppress 340
+suppress 341
+suppress 346
+suppress 226 on error
+load -G main.o kdc5_err.o kdc_util.o network.o policy.o	-I../include
+load -G do_as_req.o do_tgs_req.o extern.o	-I../include
+make SRCS=dispatch.c saber
+load -G kerberos_v4.c -DBACKWARD_COMPAT -DVARARGS -I../include/kerberosIV -I../include -I../include/stdc-incl
+cd  /site/Don/krb5/kdc
+load -G ../lib/kdb/libkdb.a ../lib/libkrb5.a
+load -G ../lib/des/libdes.a ../lib/os-4.3/libos.a ../lib/crc-32/libcrc32.a
+load -G /mit/isode/isode-6.0/@sys/lib/libisode.a
+load -G -lkrb -ldes -lcom_err
+setopt load_flags -I/mit/krb5/vax-cc/include
+link
+unload /site/Don/krb5/lib/kdb/libkdb.a(decrypt_key.o)
+cd     /site/Don/krb5/lib/kdb
+make SRCS=decrypt_key.c saber
+unload /site/Don/krb5/lib/des/libdes.a(enc_dec.o)
+unload /site/Don/krb5/lib/des/libdes.a(new_rn_key.o)
+cd     /site/Don/krb5/lib/des
+make SRCS=enc_dec.c saber
+make SRCS=new_rn_key.c saber
+run
diff --git a/krb5-1-6/src/kdc/Makefile.in b/krb5-1-6/src/kdc/Makefile.in
new file mode 100644
index 000000000..bdd4b7da3
--- /dev/null
+++ b/krb5-1-6/src/kdc/Makefile.in
@@ -0,0 +1,213 @@
+thisconfigdir=..
+myfulldir=kdc
+mydir=kdc
+BUILDTOP=$(REL)..
+# -DUSE_RCACHE - enable replay cache for KDC
+# -DNOCACHE    - disable lookaside cache, which is used to resend previous
+#                response to replay (i.e., *don't* define this if you
+#                define USE_RCACHE)
+# These are now set in configure.in.
+DEFINES = # -DNOCACHE
+RUN_SETUP = @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH)
+KDB5_LIB_DEPS=$(DL_LIB) $(THREAD_LINKOPTS)
+PROG_RPATH=$(KRB5_LIBDIR)
+FAKEKA=@FAKEKA@
+DEFS=-DLIBDIR=\"$(KRB5_LIBDIR)\"
+
+all:: krb5kdc rtest $(FAKEKA)
+
+# DEFINES = -DBACKWARD_COMPAT $(KRB4DEF)
+
+LOCALINCLUDES = @KRB4_INCLUDES@ -I.
+SRCS= \
+	kdc5_err.c \
+	$(srcdir)/dispatch.c \
+	$(srcdir)/do_as_req.c \
+	$(srcdir)/do_tgs_req.c \
+	$(srcdir)/kdc_util.c \
+	$(srcdir)/kdc_preauth.c \
+	$(srcdir)/main.c \
+	$(srcdir)/network.c \
+	$(srcdir)/policy.c \
+	$(srcdir)/extern.c \
+	$(srcdir)/replay.c \
+	$(srcdir)/kerberos_v4.c
+
+OBJS= \
+	kdc5_err.o \
+	dispatch.o \
+	do_as_req.o \
+	do_tgs_req.o \
+	kdc_util.o \
+	kdc_preauth.o \
+	main.o \
+	network.o \
+	policy.o \
+	extern.o \
+	replay.o \
+	kerberos_v4.o
+
+RT_OBJS= rtest.o \
+	kdc_util.o \
+	policy.o \
+	extern.o
+
+depend:: kdc5_err.c
+
+kdc5_err.c: kdc5_err.et
+
+kdc5_err.h: kdc5_err.et
+
+kdc5_err.o: kdc5_err.h
+
+krb5kdc: $(OBJS) $(KADMSRV_DEPLIBS) $(KRB4COMPAT_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o krb5kdc $(OBJS) $(KADMSRV_LIBS) $(KRB4COMPAT_LIBS) $(APPUTILS_LIB)
+
+rtest: $(RT_OBJS) $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o rtest $(RT_OBJS) $(KDB5_LIBS) $(KADM_COMM_LIBS) $(KRB5_BASE_LIBS)
+
+fakeka: fakeka.o $(KADMSRV_DEPLIBS) $(KRB4COMPAT_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o fakeka fakeka.o $(KADMSRV_LIBS) $(KRB4COMPAT_LIBS) $(APPUTILS_LIB)
+
+check-unix:: rtest
+	KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;\
+	$(RUN_SETUP) $(VALGRIND) $(srcdir)/rtscript > test.out
+	cmp test.out $(srcdir)/rtest.good
+	$(RM) test.out
+
+install::
+	$(INSTALL_PROGRAM) krb5kdc ${DESTDIR}$(SERVER_BINDIR)/krb5kdc
+	$(INSTALL_DATA) $(srcdir)/krb5kdc.M ${DESTDIR}$(SERVER_MANDIR)/krb5kdc.8
+	f=$(FAKEKA); \
+	if test -n "$$f" ; then \
+		$(INSTALL_PROGRAM) $$f ${DESTDIR}$(SERVER_BINDIR)/$$f; \
+		$(INSTALL_DATA) $(srcdir)/fakeka.M ${DESTDIR}$(SERVER_MANDIR)/fakeka.8; \
+	fi
+
+clean::
+	$(RM) kdc5_err.h kdc5_err.c krb5kdc rtest.o rtest
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kdc5_err.$(OBJEXT): $(COM_ERR_DEPS) kdc5_err.c
+$(OUTPRE)dispatch.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  dispatch.c extern.h kdc_util.h
+$(OUTPRE)do_as_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm.h \
+  $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  do_as_req.c extern.h kdc_util.h policy.h
+$(OUTPRE)do_tgs_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  do_tgs_req.c extern.h kdc_util.h policy.h
+$(OUTPRE)kdc_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm.h \
+  $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  extern.h kdc_util.c kdc_util.h
+$(OUTPRE)kdc_preauth.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  extern.h kdc_preauth.c kdc_util.h
+$(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm.h \
+  $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/kdb_kt.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  extern.h kdc5_err.h kdc_util.h main.c
+$(OUTPRE)network.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/cm.h $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/foreachaddr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  extern.h kdc5_err.h kdc_util.h network.c
+$(OUTPRE)policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdc_util.h policy.c
+$(OUTPRE)extern.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  extern.c extern.h
+$(OUTPRE)replay.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h extern.h kdc_util.h \
+  replay.c
+$(OUTPRE)kerberos_v4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/klog.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/krb_db.h $(SRCTOP)/include/kerberosIV/prot.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  extern.h kdc_util.h kerberos_v4.c
diff --git a/krb5-1-6/src/kdc/dispatch.c b/krb5-1-6/src/kdc/dispatch.c
new file mode 100644
index 000000000..1d7c3bed7
--- /dev/null
+++ b/krb5-1-6/src/kdc/dispatch.c
@@ -0,0 +1,115 @@
+/*
+ * kdc/dispatch.c
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Dispatch an incoming packet.
+ */
+
+#include "k5-int.h"
+#include <syslog.h>
+#include "kdc_util.h"
+#include "extern.h"
+#include "adm_proto.h"
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+static krb5_int32 last_usec = 0, last_os_random = 0;
+
+krb5_error_code
+dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_data **response)
+{
+
+    krb5_error_code retval;
+    krb5_kdc_req *as_req;
+    krb5_int32 now, now_usec;
+    
+    /* decode incoming packet, and dispatch */
+
+#ifndef NOCACHE
+    /* try the replay lookaside buffer */
+    if (kdc_check_lookaside(pkt, response)) {
+	/* a hit! */
+	const char *name = 0;
+	char buf[46];
+
+	name = inet_ntop (ADDRTYPE2FAMILY (from->address->addrtype),
+			  from->address->contents, buf, sizeof (buf));
+	if (name == 0)
+	    name = "[unknown address type]";
+	krb5_klog_syslog(LOG_INFO,
+			 "DISPATCH: repeated (retransmitted?) request from %s, resending previous response",
+			 name);
+	return 0;
+    }
+#endif
+    retval = krb5_crypto_us_timeofday(&now, &now_usec);
+    if (retval == 0) {
+      krb5_int32 usec_difference = now_usec-last_usec;
+      krb5_data data;
+      if(last_os_random == 0)
+	last_os_random = now;
+      /* Grab random data from OS every hour*/
+      if(now-last_os_random >= 60*60) {
+	krb5_c_random_os_entropy(kdc_context, 0, NULL);
+	last_os_random = now;
+      }
+      
+      data.length = sizeof(krb5_int32);
+      data.data = (void *) &usec_difference;
+      
+      krb5_c_random_add_entropy(kdc_context,
+				KRB5_C_RANDSOURCE_TIMING, &data);
+      last_usec = now_usec;
+    }
+    /* try TGS_REQ first; they are more common! */
+
+    if (krb5_is_tgs_req(pkt)) {
+	retval = process_tgs_req(pkt, from, response);
+    } else if (krb5_is_as_req(pkt)) {
+	if (!(retval = decode_krb5_as_req(pkt, &as_req))) {
+	    /*
+	     * setup_server_realm() sets up the global realm-specific data
+	     * pointer.
+	     */
+	    if (!(retval = setup_server_realm(as_req->server))) {
+		retval = process_as_req(as_req, pkt, from, response);
+	    }
+	    krb5_free_kdc_req(kdc_context, as_req);
+	}
+    }
+#ifdef KRB5_KRB4_COMPAT
+    else if (pkt->data[0] == 4)		/* old version */
+	retval = process_v4(pkt, from, response);
+#endif
+    else
+	retval = KRB5KRB_AP_ERR_MSG_TYPE;
+#ifndef NOCACHE
+    /* put the response into the lookaside buffer */
+    if (!retval)
+	kdc_insert_lookaside(pkt, *response);
+#endif
+
+    return retval;
+}
diff --git a/krb5-1-6/src/kdc/do_as_req.c b/krb5-1-6/src/kdc/do_as_req.c
new file mode 100644
index 000000000..afc7d5210
--- /dev/null
+++ b/krb5-1-6/src/kdc/do_as_req.c
@@ -0,0 +1,554 @@
+/*
+ * kdc/do_as_req.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * KDC Routines to deal with AS_REQ's
+ */
+
+#include "k5-int.h"
+#include "com_err.h"
+
+#include <syslog.h>
+#ifdef HAVE_NETINET_IN_H
+#include <sys/types.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif	/* hpux */
+#endif /* HAVE_NETINET_IN_H */
+
+#include "kdc_util.h"
+#include "policy.h"
+#include "adm.h"
+#include "adm_proto.h"
+#include "extern.h"
+
+static krb5_error_code prepare_error_as (krb5_kdc_req *, int, krb5_data *, 
+					 krb5_data **, const char *);
+
+/*ARGSUSED*/
+krb5_error_code
+process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
+	       const krb5_fulladdr *from, krb5_data **response)
+{
+    krb5_db_entry client, server;
+    krb5_kdc_rep reply;
+    krb5_enc_kdc_rep_part reply_encpart;
+    krb5_ticket ticket_reply;
+    krb5_enc_tkt_part enc_tkt_reply;
+    krb5_error_code errcode;
+    int c_nprincs = 0, s_nprincs = 0;
+    krb5_boolean more;
+    krb5_timestamp kdc_time, authtime;
+    krb5_keyblock session_key;
+    krb5_keyblock encrypting_key;
+    const char *status;
+    krb5_key_data  *server_key, *client_key;
+    krb5_enctype useenctype;
+#ifdef	KRBCONF_KDC_MODIFIES_KDB
+    krb5_boolean update_client = 0;
+#endif	/* KRBCONF_KDC_MODIFIES_KDB */
+    krb5_data e_data;
+    register int i;
+    krb5_timestamp until, rtime;
+    char *cname = 0, *sname = 0;
+    const char *fromstring = 0;
+    char ktypestr[128];
+    char rep_etypestr[128];
+    char fromstringbuf[70];
+    void *pa_context = NULL;
+
+    ticket_reply.enc_part.ciphertext.data = 0;
+    e_data.data = 0;
+    encrypting_key.contents = 0;
+    reply.padata = 0;
+    session_key.contents = 0;
+    enc_tkt_reply.authorization_data = NULL;
+
+    ktypes2str(ktypestr, sizeof(ktypestr),
+	       request->nktypes, request->ktype);
+
+    fromstring = inet_ntop(ADDRTYPE2FAMILY (from->address->addrtype),
+			   from->address->contents,
+			   fromstringbuf, sizeof(fromstringbuf));
+    if (!fromstring)
+	fromstring = "<unknown>";
+
+    if (!request->client) {
+	status = "NULL_CLIENT";
+	errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+	goto errout;
+    }
+    if ((errcode = krb5_unparse_name(kdc_context, request->client, &cname))) {
+	status = "UNPARSING_CLIENT";
+	goto errout;
+    }
+    limit_string(cname);
+    if (!request->server) {
+	status = "NULL_SERVER";
+	errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+	goto errout;
+    }
+    if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) {
+	status = "UNPARSING_SERVER";
+	goto errout;
+    }
+    limit_string(sname);
+    
+    c_nprincs = 1;
+    if ((errcode = krb5_db_get_principal(kdc_context, request->client,
+					 &client, &c_nprincs, &more))) {
+	status = "LOOKING_UP_CLIENT";
+	c_nprincs = 0;
+	goto errout;
+    }
+    if (more) {
+	status = "NON-UNIQUE_CLIENT";
+	errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
+	goto errout;
+    } else if (c_nprincs != 1) {
+	status = "CLIENT_NOT_FOUND";
+#ifdef KRBCONF_VAGUE_ERRORS
+	errcode = KRB5KRB_ERR_GENERIC;
+#else
+	errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+#endif
+	goto errout;
+    }
+    
+    s_nprincs = 1;
+    if ((errcode = krb5_db_get_principal(kdc_context, request->server, &server,
+					 &s_nprincs, &more))) {
+	status = "LOOKING_UP_SERVER";
+	goto errout;
+    }
+    if (more) {
+	status = "NON-UNIQUE_SERVER";
+	errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
+	goto errout;
+    } else if (s_nprincs != 1) {
+	status = "SERVER_NOT_FOUND";
+	errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+	goto errout;
+    }
+
+    if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) {
+	status = "TIMEOFDAY";
+	goto errout;
+    }
+
+    if ((errcode = validate_as_request(request, client, server,
+				      kdc_time, &status))) {
+	if (!status) 
+	    status = "UNKNOWN_REASON";
+	errcode += ERROR_TABLE_BASE_krb5;
+	goto errout;
+    }
+      
+    /*
+     * Select the keytype for the ticket session key.
+     */
+    if ((useenctype = select_session_keytype(kdc_context, &server,
+					     request->nktypes,
+					     request->ktype)) == 0) {
+	/* unsupported ktype */
+	status = "BAD_ENCRYPTION_TYPE";
+	errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+	goto errout;
+    }
+
+    if ((errcode = krb5_c_make_random_key(kdc_context, useenctype,
+					  &session_key))) {
+	status = "RANDOM_KEY_FAILED";
+	goto errout;
+    }
+
+    ticket_reply.server = request->server;
+
+    enc_tkt_reply.flags = 0;
+    setflag(enc_tkt_reply.flags, TKT_FLG_INITIAL);
+
+    	/* It should be noted that local policy may affect the  */
+        /* processing of any of these flags.  For example, some */
+        /* realms may refuse to issue renewable tickets         */
+
+    if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE))
+	setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
+
+    if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE))
+	    setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
+
+    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.client = request->client;
+    enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
+    enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */
+
+    enc_tkt_reply.times.authtime = kdc_time;
+
+    if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) {
+	setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED);
+	setflag(enc_tkt_reply.flags, TKT_FLG_INVALID);
+	enc_tkt_reply.times.starttime = request->from;
+    } else
+	enc_tkt_reply.times.starttime = kdc_time;
+    
+    until = (request->till == 0) ? kdc_infinity : request->till;
+
+    enc_tkt_reply.times.endtime =
+	min(until,
+	    min(enc_tkt_reply.times.starttime + client.max_life,
+		min(enc_tkt_reply.times.starttime + server.max_life,
+		    enc_tkt_reply.times.starttime + max_life_for_realm)));
+
+    if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
+	!isflagset(client.attributes, KRB5_KDB_DISALLOW_RENEWABLE) &&
+	(enc_tkt_reply.times.endtime < request->till)) {
+
+	/* we set the RENEWABLE option for later processing */
+
+	setflag(request->kdc_options, KDC_OPT_RENEWABLE);
+	request->rtime = request->till;
+    }
+    rtime = (request->rtime == 0) ? kdc_infinity : request->rtime;
+
+    if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) {
+	/*
+	 * XXX Should we squelch the output renew_till to be no
+	 * earlier than the endtime of the ticket? 
+	 */
+	setflag(enc_tkt_reply.flags, TKT_FLG_RENEWABLE);
+	enc_tkt_reply.times.renew_till =
+	    min(rtime, enc_tkt_reply.times.starttime +
+		       min(client.max_renewable_life,
+			   min(server.max_renewable_life,
+			       max_renewable_life_for_realm)));
+    } else
+	enc_tkt_reply.times.renew_till = 0; /* XXX */
+
+    /* starttime is optional, and treated as authtime if not present.
+       so we can nuke it if it matches */
+    if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime)
+	enc_tkt_reply.times.starttime = 0;
+
+    enc_tkt_reply.caddrs = request->addresses;
+    enc_tkt_reply.authorization_data = 0;
+
+    /* 
+     * Check the preauthentication if it is there.
+     */
+    if (request->padata) {
+	errcode = check_padata(kdc_context, &client, req_pkt, request,
+			       &enc_tkt_reply, &pa_context, &e_data);
+	if (errcode) {
+#ifdef KRBCONF_KDC_MODIFIES_KDB
+	    /*
+	     * Note: this doesn't work if you're using slave servers!!!
+	     * It also causes the database to be modified (and thus
+	     * need to be locked) frequently.
+	     */
+	    if (client.fail_auth_count < KRB5_MAX_FAIL_COUNT) {
+		client.fail_auth_count = client.fail_auth_count + 1;
+		if (client.fail_auth_count == KRB5_MAX_FAIL_COUNT) { 
+		    client.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+		}
+	    }
+	    client.last_failed = kdc_time;
+	    update_client = 1;
+#endif
+	    status = "PREAUTH_FAILED";
+#ifdef KRBCONF_VAGUE_ERRORS
+	    errcode = KRB5KRB_ERR_GENERIC;
+#endif
+	    goto errout;
+	} 
+    }
+
+    /*
+     * Final check before handing out ticket: If the client requires
+     * preauthentication, verify that the proper kind of
+     * preauthentication was carried out.
+     */
+    status = missing_required_preauth(&client, &server, &enc_tkt_reply);
+    if (status) {
+	errcode = KRB5KDC_ERR_PREAUTH_REQUIRED;
+	get_preauth_hint_list(request, &client, &server, &e_data);
+	goto errout;
+    }
+
+    ticket_reply.enc_part2 = &enc_tkt_reply;
+
+    /*
+     * Find the server key
+     */
+    if ((errcode = krb5_dbe_find_enctype(kdc_context, &server,
+					 -1, /* ignore keytype */
+					 -1,		/* Ignore salttype */
+					 0,		/* Get highest kvno */
+					 &server_key))) {
+	status = "FINDING_SERVER_KEY";
+	goto errout;
+    }
+
+    /* convert server.key into a real key (it may be encrypted
+       in the database) */
+    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, 
+					       server_key, &encrypting_key,
+					       NULL))) {
+	status = "DECRYPT_SERVER_KEY";
+	goto errout;
+    }
+	
+    errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key, &ticket_reply);
+    krb5_free_keyblock_contents(kdc_context, &encrypting_key);
+    encrypting_key.contents = 0;
+    if (errcode) {
+	status = "ENCRYPTING_TICKET";
+	goto errout;
+    }
+    ticket_reply.enc_part.kvno = server_key->key_data_kvno;
+
+    /*
+     * Find the appropriate client key.  We search in the order specified
+     * by request keytype list.
+     */
+    client_key = (krb5_key_data *) NULL;
+    for (i = 0; i < request->nktypes; i++) {
+	useenctype = request->ktype[i];
+	if (!krb5_c_valid_enctype(useenctype))
+	    continue;
+
+	if (!krb5_dbe_find_enctype(kdc_context, &client, useenctype, -1,
+				   0, &client_key))
+	    break;
+    }
+    if (!(client_key)) {
+	/* Cannot find an appropriate key */
+	status = "CANT_FIND_CLIENT_KEY";
+	errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+	goto errout;
+    }
+
+    /* convert client.key_data into a real key */
+    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, 
+					       client_key, &encrypting_key,
+					       NULL))) {
+	status = "DECRYPT_CLIENT_KEY";
+	goto errout;
+    }
+    encrypting_key.enctype = useenctype;
+
+    /* Start assembling the response */
+    reply.msg_type = KRB5_AS_REP;
+    reply.client = request->client;
+    reply.ticket = &ticket_reply;
+    reply_encpart.session = &session_key;
+    if ((errcode = fetch_last_req_info(&client, &reply_encpart.last_req))) {
+	status = "FETCH_LAST_REQ";
+	goto errout;
+    }
+    reply_encpart.nonce = request->nonce;
+    reply_encpart.key_exp = client.expiration;
+    reply_encpart.flags = enc_tkt_reply.flags;
+    reply_encpart.server = ticket_reply.server;
+
+    /* copy the time fields EXCEPT for authtime; it's location
+       is used for ktime */
+    reply_encpart.times = enc_tkt_reply.times;
+    reply_encpart.times.authtime = authtime = kdc_time;
+
+    reply_encpart.caddrs = enc_tkt_reply.caddrs;
+
+    /* Fetch the padata info to be returned */
+    errcode = return_padata(kdc_context, &client, req_pkt, request,
+			    &reply, client_key, &encrypting_key, &pa_context);
+    if (errcode) {
+	status = "KDC_RETURN_PADATA";
+	goto errout;
+    }
+
+    /* now encode/encrypt the response */
+
+    reply.enc_part.enctype = encrypting_key.enctype;
+
+    errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, 
+				  0, &encrypting_key,  &reply, response);
+    krb5_free_keyblock_contents(kdc_context, &encrypting_key);
+    encrypting_key.contents = 0;
+    reply.enc_part.kvno = client_key->key_data_kvno;
+
+    if (errcode) {
+	status = "ENCODE_KDC_REP";
+	goto errout;
+    }
+    
+    /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we
+       can use them in raw form if needed.  But, we don't... */
+    memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
+    free(reply.enc_part.ciphertext.data);
+
+    rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), &reply);
+    krb5_klog_syslog(LOG_INFO,
+		     "AS_REQ (%s) %s: ISSUE: authtime %d, "
+		     "%s, %s for %s",
+		     ktypestr,
+	             fromstring, authtime,
+		     rep_etypestr,
+		     cname, sname);
+
+#ifdef	KRBCONF_KDC_MODIFIES_KDB
+    /*
+     * If we get this far, we successfully did the AS_REQ.
+     */
+    client.last_success = kdc_time;
+    client.fail_auth_count = 0;
+    update_client = 1;
+#endif	/* KRBCONF_KDC_MODIFIES_KDB */
+
+errout:
+    if (pa_context)
+	free_padata_context(kdc_context, &pa_context);
+
+    if (status) {
+	const char * emsg = 0;
+	if (errcode) 
+	    emsg = krb5_get_error_message (kdc_context, errcode);
+
+        krb5_klog_syslog(LOG_INFO, "AS_REQ (%s) %s: %s: %s for %s%s%s",
+			 ktypestr,
+	       fromstring, status, 
+	       cname ? cname : "<unknown client>",
+	       sname ? sname : "<unknown server>",
+	       errcode ? ", " : "",
+	       errcode ? emsg : "");
+	if (errcode)
+	    krb5_free_error_message (kdc_context, emsg);
+    }
+    if (errcode) {
+        int got_err = 0;
+	if (status == 0) {
+	    status = krb5_get_error_message (kdc_context, errcode);
+	    got_err = 1;
+	}
+	errcode -= ERROR_TABLE_BASE_krb5;
+	if (errcode < 0 || errcode > 128)
+	    errcode = KRB_ERR_GENERIC;
+	    
+	errcode = prepare_error_as(request, errcode, &e_data, response,
+				   status);
+	if (got_err) {
+	    krb5_free_error_message (kdc_context, status);
+	    status = 0;
+	}
+    }
+
+    if (enc_tkt_reply.authorization_data != NULL)
+	krb5_free_authdata(kdc_context, enc_tkt_reply.authorization_data);
+    if (encrypting_key.contents)
+	krb5_free_keyblock_contents(kdc_context, &encrypting_key);
+    if (reply.padata)
+	krb5_free_pa_data(kdc_context, reply.padata);
+
+    if (cname)
+	    free(cname);
+    if (sname)
+	    free(sname);
+    if (c_nprincs) {
+#ifdef	KRBCONF_KDC_MODIFIES_KDB
+	if (update_client) {
+	    krb5_db_put_principal(kdc_context, &client, &c_nprincs);
+	    /*
+	     * ptooey.  We want krb5_db_sync() or something like that.
+	     */
+	    krb5_db_fini(kdc_context);
+	    if (kdc_active_realm->realm_dbname)
+		krb5_db_set_name(kdc_active_realm->realm_context,
+				 kdc_active_realm->realm_dbname);
+	    krb5_db_init(kdc_context);
+	    /* Reset master key */
+	    krb5_db_set_mkey(kdc_context, &kdc_active_realm->realm_mkey);
+	}
+#endif	/* KRBCONF_KDC_MODIFIES_KDB */
+	krb5_db_free_principal(kdc_context, &client, c_nprincs);
+    }
+    if (s_nprincs)
+	krb5_db_free_principal(kdc_context, &server, s_nprincs);
+    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);
+	free(ticket_reply.enc_part.ciphertext.data);
+    }
+
+    krb5_free_data_contents(kdc_context, &e_data);
+    
+    return errcode;
+}
+
+static krb5_error_code
+prepare_error_as (krb5_kdc_req *request, int error, krb5_data *e_data,
+		  krb5_data **response, const char *status)
+{
+    krb5_error errpkt;
+    krb5_error_code retval;
+    krb5_data *scratch;
+    
+    errpkt.ctime = request->nonce;
+    errpkt.cusec = 0;
+
+    if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime,
+				    &errpkt.susec)))
+	return(retval);
+    errpkt.error = error;
+    errpkt.server = request->server;
+    errpkt.client = request->client;
+    errpkt.text.length = strlen(status)+1;
+    if (!(errpkt.text.data = malloc(errpkt.text.length)))
+	return ENOMEM;
+    (void) strcpy(errpkt.text.data, status);
+
+    if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) {
+	free(errpkt.text.data);
+	return ENOMEM;
+    }
+    if (e_data && e_data->data) {
+	errpkt.e_data = *e_data;
+    } else {
+	errpkt.e_data.length = 0;
+	errpkt.e_data.data = 0;
+    }
+
+    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+    free(errpkt.text.data);
+    if (retval)
+	free(scratch);
+    else 
+	*response = scratch;
+
+    return retval;
+}
diff --git a/krb5-1-6/src/kdc/do_tgs_req.c b/krb5-1-6/src/kdc/do_tgs_req.c
new file mode 100644
index 000000000..8e960cb04
--- /dev/null
+++ b/krb5-1-6/src/kdc/do_tgs_req.c
@@ -0,0 +1,847 @@
+/*
+ * kdc/do_tgs_req.c
+ *
+ * Copyright 1990,1991,2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * KDC Routines to deal with TGS_REQ's
+ */
+
+#include "k5-int.h"
+#include "com_err.h"
+
+#include <syslog.h>
+#ifdef HAVE_NETINET_IN_H
+#include <sys/types.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+#endif
+
+#include "kdc_util.h"
+#include "policy.h"
+#include "extern.h"
+#include "adm_proto.h"
+
+
+static void find_alternate_tgs (krb5_kdc_req *, krb5_db_entry *,
+				krb5_boolean *, int *);
+
+static krb5_error_code prepare_error_tgs (krb5_kdc_req *, krb5_ticket *,
+					  int, const char *, krb5_data **,
+					  const char *);
+
+/*ARGSUSED*/
+krb5_error_code
+process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
+		krb5_data **response)
+{
+    krb5_keyblock * subkey;
+    krb5_kdc_req *request = 0;
+    krb5_db_entry server;
+    krb5_kdc_rep reply;
+    krb5_enc_kdc_rep_part reply_encpart;
+    krb5_ticket ticket_reply, *header_ticket = 0;
+    int st_idx = 0;
+    krb5_enc_tkt_part enc_tkt_reply;
+    krb5_transited enc_tkt_transited;
+    int newtransited = 0;
+    krb5_error_code retval = 0;
+    int nprincs = 0;
+    krb5_boolean more;
+    krb5_timestamp kdc_time, authtime=0;
+    krb5_keyblock session_key;
+    krb5_timestamp until, rtime;
+    krb5_keyblock encrypting_key;
+    krb5_key_data  *server_key;
+    char *cname = 0, *sname = 0, *tmp = 0;
+    const char *fromstring = 0;
+    krb5_last_req_entry *nolrarray[2], nolrentry;
+/*    krb5_address *noaddrarray[1]; */
+    krb5_enctype useenctype;
+    int	errcode, errcode2;
+    register int i;
+    int firstpass = 1;
+    const char	*status = 0;
+    char ktypestr[128];
+    char rep_etypestr[128];
+    char fromstringbuf[70];
+
+    session_key.contents = 0;
+    
+    retval = decode_krb5_tgs_req(pkt, &request);
+    if (retval)
+	return retval;
+
+    ktypes2str(ktypestr, sizeof(ktypestr),
+	       request->nktypes, request->ktype);
+    /*
+     * setup_server_realm() sets up the global realm-specific data pointer.
+     */
+    if ((retval = setup_server_realm(request->server)))
+	return retval;
+
+    fromstring = inet_ntop(ADDRTYPE2FAMILY(from->address->addrtype),
+			   from->address->contents,
+			   fromstringbuf, sizeof(fromstringbuf));
+    if (!fromstring)
+	fromstring = "<unknown>";
+
+    if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) {
+	status = "UNPARSING SERVER";
+	goto cleanup;
+    }
+    limit_string(sname);
+
+   /* errcode = kdc_process_tgs_req(request, from, pkt, &req_authdat); */
+    errcode = kdc_process_tgs_req(request, from, pkt, &header_ticket, &subkey);
+
+    if (header_ticket && header_ticket->enc_part2 &&
+	(errcode2 = krb5_unparse_name(kdc_context, 
+				      header_ticket->enc_part2->client,
+				      &cname))) {
+	status = "UNPARSING CLIENT";
+	errcode = errcode2;
+	goto cleanup;
+    }
+    limit_string(cname);
+    
+    if (errcode) {
+	status = "PROCESS_TGS";
+	goto cleanup;
+    }
+
+    if (!header_ticket) {
+	errcode = KRB5_NO_TKT_SUPPLIED;	/* XXX? */
+	status="UNEXPECTED NULL in header_ticket";
+	goto cleanup;
+    }
+    
+    /*
+     * We've already dealt with the AP_REQ authentication, so we can
+     * use header_ticket freely.  The encrypted part (if any) has been
+     * decrypted with the session key.
+     */
+
+    authtime = header_ticket->enc_part2->times.authtime;
+
+    /* XXX make sure server here has the proper realm...taken from AP_REQ
+       header? */
+
+    nprincs = 1;
+    if ((errcode = krb5_db_get_principal(kdc_context, request->server, &server,
+					&nprincs, &more))) {
+	status = "LOOKING_UP_SERVER";
+	nprincs = 0;
+	goto cleanup;
+    }
+tgt_again:
+    if (more) {
+	status = "NON_UNIQUE_PRINCIPAL";
+	errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
+	goto cleanup;
+    } else if (nprincs != 1) {
+	/*
+	 * might be a request for a TGT for some other realm; we
+	 * should do our best to find such a TGS in this db
+	 */
+	if (firstpass && krb5_is_tgs_principal(request->server) == TRUE) {
+	    if (krb5_princ_size(kdc_context, request->server) == 2) {
+		krb5_data *server_1 =
+		    krb5_princ_component(kdc_context, request->server, 1);
+		krb5_data *tgs_1 =
+		    krb5_princ_component(kdc_context, tgs_server, 1);
+
+		if (!tgs_1 || server_1->length != tgs_1->length ||
+		    memcmp(server_1->data, tgs_1->data, tgs_1->length)) {
+		    krb5_db_free_principal(kdc_context, &server, nprincs);
+		    find_alternate_tgs(request, &server, &more, &nprincs);
+		    firstpass = 0;
+		    goto tgt_again;
+		}
+	    }
+	}
+	krb5_db_free_principal(kdc_context, &server, nprincs);
+	status = "UNKNOWN_SERVER";
+	errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+	goto cleanup;
+    }
+
+    if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) {
+	status = "TIME_OF_DAY";
+	goto cleanup;
+    }
+    
+    if ((retval = validate_tgs_request(request, server, header_ticket,
+				      kdc_time, &status))) {
+	if (!status)
+	    status = "UNKNOWN_REASON";
+	errcode = retval + ERROR_TABLE_BASE_krb5;
+	goto cleanup;
+    }
+
+    /*
+     * We pick the session keytype here....
+     * 
+     * Some special care needs to be taken in the user-to-user
+     * case, since we don't know what keytypes the application server
+     * which is doing user-to-user authentication can support.  We
+     * know that it at least must be able to support the encryption
+     * type of the session key in the TGT, since otherwise it won't be
+     * able to decrypt the U2U ticket!  So we use that in preference
+     * to anything else.
+     */
+    useenctype = 0;
+    if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) {
+	krb5_keyblock *	st_sealing_key;
+	krb5_kvno 	st_srv_kvno;
+	krb5_enctype	etype;
+
+	/*
+	 * Get the key for the second ticket, and decrypt it.
+	 */
+	if ((errcode = kdc_get_server_key(request->second_ticket[st_idx],
+					 &st_sealing_key,
+					 &st_srv_kvno))) {
+	    status = "2ND_TKT_SERVER";
+	    goto cleanup;
+	}
+	errcode = krb5_decrypt_tkt_part(kdc_context, st_sealing_key,
+				       request->second_ticket[st_idx]);
+	krb5_free_keyblock(kdc_context, st_sealing_key);
+	if (errcode) {
+	    status = "2ND_TKT_DECRYPT";
+	    goto cleanup;
+	}
+	
+	etype = request->second_ticket[st_idx]->enc_part2->session->enctype;
+	if (!krb5_c_valid_enctype(etype)) {
+	    status = "BAD_ETYPE_IN_2ND_TKT";
+	    errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+	    goto cleanup;
+	}
+	
+	for (i = 0; i < request->nktypes; i++) {
+	    if (request->ktype[i] == etype) {
+		useenctype = etype;
+		break;
+	    }
+	}
+    }
+
+    /*
+     * Select the keytype for the ticket session key.
+     */
+    if ((useenctype == 0) &&
+	(useenctype = select_session_keytype(kdc_context, &server,
+					     request->nktypes,
+					     request->ktype)) == 0) {
+	/* unsupported ktype */
+	status = "BAD_ENCRYPTION_TYPE";
+	errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+	goto cleanup;
+    }
+    
+    errcode = krb5_c_make_random_key(kdc_context, useenctype, &session_key);
+
+    if (errcode) {
+	/* random key failed */
+	status = "RANDOM_KEY_FAILED";
+	goto cleanup;
+    }
+
+    ticket_reply.server = request->server; /* XXX careful for realm... */
+
+    enc_tkt_reply.flags = 0;
+    enc_tkt_reply.times.starttime = 0;
+
+    /*
+     * Fix header_ticket's starttime; if it's zero, fill in the
+     * authtime's value.
+     */
+    if (!(header_ticket->enc_part2->times.starttime))
+	header_ticket->enc_part2->times.starttime =
+	    header_ticket->enc_part2->times.authtime;
+
+    /* don't use new addresses unless forwarded, see below */
+
+    enc_tkt_reply.caddrs = header_ticket->enc_part2->caddrs;
+    /* noaddrarray[0] = 0; */
+    reply_encpart.caddrs = 0;		/* optional...don't put it in */
+
+    /* It should be noted that local policy may affect the  */
+    /* processing of any of these flags.  For example, some */
+    /* realms may refuse to issue renewable tickets         */
+
+    if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE))
+	setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
+
+    if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) {
+	setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED);
+
+	/* include new addresses in ticket & reply */
+
+	enc_tkt_reply.caddrs = request->addresses;
+	reply_encpart.caddrs = request->addresses;
+    }	
+    if (isflagset(header_ticket->enc_part2->flags, TKT_FLG_FORWARDED))
+	setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED);
+
+    if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE))
+	setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
+
+    if (isflagset(request->kdc_options, KDC_OPT_PROXY)) {
+	setflag(enc_tkt_reply.flags, TKT_FLG_PROXY);
+
+	/* include new addresses in ticket & reply */
+
+	enc_tkt_reply.caddrs = request->addresses;
+	reply_encpart.caddrs = request->addresses;
+    }
+
+    if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
+	setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
+
+    if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) {
+	setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED);
+	setflag(enc_tkt_reply.flags, TKT_FLG_INVALID);
+	enc_tkt_reply.times.starttime = request->from;
+    } else
+	enc_tkt_reply.times.starttime = kdc_time;
+
+    if (isflagset(request->kdc_options, KDC_OPT_VALIDATE)) {
+	/* BEWARE of allocation hanging off of ticket & enc_part2, it belongs
+	   to the caller */
+	ticket_reply = *(header_ticket);
+	enc_tkt_reply = *(header_ticket->enc_part2);
+	clear(enc_tkt_reply.flags, TKT_FLG_INVALID);
+    }
+
+    if (isflagset(request->kdc_options, KDC_OPT_RENEW)) {
+	krb5_deltat old_life;
+
+	/* BEWARE of allocation hanging off of ticket & enc_part2, it belongs
+	   to the caller */
+	ticket_reply = *(header_ticket);
+	enc_tkt_reply = *(header_ticket->enc_part2);
+
+	old_life = enc_tkt_reply.times.endtime - enc_tkt_reply.times.starttime;
+
+	enc_tkt_reply.times.starttime = kdc_time;
+	enc_tkt_reply.times.endtime =
+	    min(header_ticket->enc_part2->times.renew_till,
+		kdc_time + old_life);
+    } else {
+	/* not a renew request */
+	enc_tkt_reply.times.starttime = kdc_time;
+	until = (request->till == 0) ? kdc_infinity : request->till;
+	enc_tkt_reply.times.endtime =
+	    min(until, min(enc_tkt_reply.times.starttime + server.max_life,
+			   min(enc_tkt_reply.times.starttime + max_life_for_realm,
+			       header_ticket->enc_part2->times.endtime)));
+	if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
+	    (enc_tkt_reply.times.endtime < request->till) &&
+	    isflagset(header_ticket->enc_part2->flags,
+		  TKT_FLG_RENEWABLE)) {
+	    setflag(request->kdc_options, KDC_OPT_RENEWABLE);
+	    request->rtime =
+		min(request->till,
+		    header_ticket->enc_part2->times.renew_till);
+	}
+    }
+    rtime = (request->rtime == 0) ? kdc_infinity : request->rtime;
+
+    if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) {
+	/* already checked above in policy check to reject request for a
+	   renewable ticket using a non-renewable ticket */
+	setflag(enc_tkt_reply.flags, TKT_FLG_RENEWABLE);
+	enc_tkt_reply.times.renew_till =
+	    min(rtime,
+		min(header_ticket->enc_part2->times.renew_till,
+		    enc_tkt_reply.times.starttime +
+		    min(server.max_renewable_life,
+			max_renewable_life_for_realm)));
+    } else {
+	enc_tkt_reply.times.renew_till = 0;
+    }
+    
+    /*
+     * Set authtime to be the same as header_ticket's
+     */
+    enc_tkt_reply.times.authtime = header_ticket->enc_part2->times.authtime;
+    
+    /*
+     * Propagate the preauthentication flags through to the returned ticket.
+     */
+    if (isflagset(header_ticket->enc_part2->flags, TKT_FLG_PRE_AUTH))
+	setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH);
+
+    if (isflagset(header_ticket->enc_part2->flags, TKT_FLG_HW_AUTH))
+	setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH);
+    
+    /* starttime is optional, and treated as authtime if not present.
+       so we can nuke it if it matches */
+    if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime)
+	enc_tkt_reply.times.starttime = 0;
+
+    /* assemble any authorization data */
+    if (request->authorization_data.ciphertext.data) {
+	krb5_data scratch;
+
+	scratch.length = request->authorization_data.ciphertext.length;
+	if (!(scratch.data =
+	      malloc(request->authorization_data.ciphertext.length))) {
+	    status = "AUTH_NOMEM";
+	    errcode = ENOMEM;
+	    goto cleanup;
+	}
+
+	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";
+	    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);
+	if (errcode) {
+	    status = "AUTH_DECODE";
+	    goto cleanup;
+	}
+
+	if ((errcode =
+	     concat_authorization_data(request->unenc_authdata,
+				       header_ticket->enc_part2->authorization_data, 
+				       &enc_tkt_reply.authorization_data))) {
+	    status = "CONCAT_AUTH";
+	    goto cleanup;
+	}
+    } else
+	enc_tkt_reply.authorization_data =
+	    header_ticket->enc_part2->authorization_data;
+
+    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 "" */
+
+    /*
+     * Only add the realm of the presented tgt to the transited list if 
+     * it is different than the local realm (cross-realm) and it is different
+     * than the realm of the client (since the realm of the client is already
+     * implicitly part of the transited list and should not be explicitly
+     * listed).
+     */
+
+    /* realm compare is like strcmp, but knows how to deal with these args */
+    if (realm_compare(header_ticket->server, tgs_server) ||
+	realm_compare(header_ticket->server, enc_tkt_reply.client)) {
+	/* tgt issued by local realm or issued by realm of client */
+	enc_tkt_reply.transited = header_ticket->enc_part2->transited;
+    } else {
+	/* tgt issued by some other realm and not the realm of the client */
+	/* assemble new transited field into allocated storage */
+	if (header_ticket->enc_part2->transited.tr_type !=
+	    KRB5_DOMAIN_X500_COMPRESS) {
+	    status = "BAD_TRTYPE";
+	    errcode = KRB5KDC_ERR_TRTYPE_NOSUPP;
+	    goto cleanup;
+	}
+	enc_tkt_transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
+	enc_tkt_transited.magic = 0;
+	enc_tkt_transited.tr_contents.magic = 0;
+	enc_tkt_transited.tr_contents.data = 0;
+	enc_tkt_transited.tr_contents.length = 0;
+	enc_tkt_reply.transited = enc_tkt_transited;
+	if ((errcode =
+	     add_to_transited(&header_ticket->enc_part2->transited.tr_contents,
+			      &enc_tkt_reply.transited.tr_contents,
+			      header_ticket->server,
+			      enc_tkt_reply.client,
+			      request->server))) {
+	    status = "ADD_TR_FAIL";
+	    goto cleanup;
+	}
+	newtransited = 1;
+    }
+    if (!isflagset (request->kdc_options, KDC_OPT_DISABLE_TRANSITED_CHECK)) {
+	unsigned int tlen;
+	char *tdots;
+
+	errcode = krb5_check_transited_list (kdc_context,
+					     &enc_tkt_reply.transited.tr_contents,
+					     krb5_princ_realm (kdc_context, header_ticket->enc_part2->client),
+					     krb5_princ_realm (kdc_context, request->server));
+	tlen = enc_tkt_reply.transited.tr_contents.length;
+	tdots = tlen > 125 ? "..." : "";
+	tlen = tlen > 125 ? 125 : tlen;
+
+	if (errcode == 0) {
+	    setflag (enc_tkt_reply.flags, TKT_FLG_TRANSIT_POLICY_CHECKED);
+	} else if (errcode == KRB5KRB_AP_ERR_ILL_CR_TKT)
+	    krb5_klog_syslog (LOG_INFO,
+			      "bad realm transit path from '%s' to '%s' "
+			      "via '%.*s%s'",
+			      cname ? cname : "<unknown client>",
+			      sname ? sname : "<unknown server>",
+			      tlen,
+			      enc_tkt_reply.transited.tr_contents.data,
+			      tdots);
+	else {
+	    const char *emsg = krb5_get_error_message(kdc_context, errcode);
+	    krb5_klog_syslog (LOG_ERR,
+			      "unexpected error checking transit from "
+			      "'%s' to '%s' via '%.*s%s': %s",
+			      cname ? cname : "<unknown client>",
+			      sname ? sname : "<unknown server>",
+			      tlen,
+			      enc_tkt_reply.transited.tr_contents.data,
+			      tdots, emsg);
+	    krb5_free_error_message(kdc_context, emsg);
+	}
+    } else
+	krb5_klog_syslog (LOG_INFO, "not checking transit path");
+    if (reject_bad_transit
+	&& !isflagset (enc_tkt_reply.flags, TKT_FLG_TRANSIT_POLICY_CHECKED)) {
+	errcode = KRB5KDC_ERR_POLICY;
+	status = "BAD_TRANSIT";
+	goto cleanup;
+    }
+
+    ticket_reply.enc_part2 = &enc_tkt_reply;
+
+    /*
+     * If we are doing user-to-user authentication, then make sure
+     * that the client for the second ticket matches the request
+     * server, and then encrypt the ticket using the session key of
+     * the second ticket.
+     */
+    if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) {
+	/*
+	 * Make sure the client for the second ticket matches
+	 * requested server.
+	 */
+	krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2;
+	krb5_principal client2 = t2enc->client;
+	if (!krb5_principal_compare(kdc_context, request->server, client2)) {
+		if ((errcode = krb5_unparse_name(kdc_context, client2, &tmp)))
+			tmp = 0;
+		if (tmp != NULL)
+		    limit_string(tmp);
+
+		krb5_klog_syslog(LOG_INFO,
+				 "TGS_REQ %s: 2ND_TKT_MISMATCH: "
+				 "authtime %d, %s for %s, 2nd tkt client %s",
+				 fromstring, authtime,
+				 cname ? cname : "<unknown client>",
+				 sname ? sname : "<unknown server>",
+				 tmp ? tmp : "<unknown>");
+		errcode = KRB5KDC_ERR_SERVER_NOMATCH;
+		goto cleanup;
+	}
+	    
+	ticket_reply.enc_part.kvno = 0;
+	ticket_reply.enc_part.enctype = t2enc->session->enctype;
+	if ((errcode = krb5_encrypt_tkt_part(kdc_context, t2enc->session,
+					     &ticket_reply))) {
+	    status = "2ND_TKT_ENCRYPT";
+	    goto cleanup;
+	}
+	st_idx++;
+    } else {
+	/*
+	 * Find the server key
+	 */
+	if ((errcode = krb5_dbe_find_enctype(kdc_context, &server,
+					     -1, /* ignore keytype */
+					     -1, /* Ignore salttype */
+					     0,		/* Get highest kvno */
+					     &server_key))) {
+	    status = "FINDING_SERVER_KEY";
+	    goto cleanup;
+	}
+	/* convert server.key into a real key (it may be encrypted
+	 *        in the database) */
+	if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context,
+						   &master_keyblock, 
+						   server_key, &encrypting_key,
+						   NULL))) {
+	    status = "DECRYPT_SERVER_KEY";
+	    goto cleanup;
+	}
+	errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key,
+					&ticket_reply);
+	krb5_free_keyblock_contents(kdc_context, &encrypting_key);
+	if (errcode) {
+	    status = "TKT_ENCRYPT";
+	    goto cleanup;
+	}
+	ticket_reply.enc_part.kvno = server_key->key_data_kvno;
+    }
+
+    /* Start assembling the response */
+    reply.msg_type = KRB5_TGS_REP;
+    reply.padata = 0;		/* always */
+    reply.client = header_ticket->enc_part2->client;
+    reply.enc_part.kvno = 0;		/* We are using the session key */
+    reply.ticket = &ticket_reply;
+
+    reply_encpart.session = &session_key;
+    reply_encpart.nonce = request->nonce;
+
+    /* copy the time fields EXCEPT for authtime; its location
+       is used for ktime */
+    reply_encpart.times = enc_tkt_reply.times;
+    reply_encpart.times.authtime = header_ticket->enc_part2->times.authtime;
+
+    /* starttime is optional, and treated as authtime if not present.
+       so we can nuke it if it matches */
+    if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime)
+	enc_tkt_reply.times.starttime = 0;
+
+    nolrentry.lr_type = KRB5_LRQ_NONE;
+    nolrentry.value = 0;
+    nolrarray[0] = &nolrentry;
+    nolrarray[1] = 0;
+    reply_encpart.last_req = nolrarray;	/* not available for TGS reqs */
+    reply_encpart.key_exp = 0;		/* ditto */
+    reply_encpart.flags = enc_tkt_reply.flags;
+    reply_encpart.server = ticket_reply.server;
+    
+    /* use the session key in the ticket, unless there's a subsession key
+       in the AP_REQ */
+
+    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);
+    if (errcode) {
+	status = "ENCODE_KDC_REP";
+    } else {
+	status = "ISSUE";
+    }
+
+    memset(ticket_reply.enc_part.ciphertext.data, 0,
+	   ticket_reply.enc_part.ciphertext.length);
+    free(ticket_reply.enc_part.ciphertext.data);
+    /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we
+       can use them in raw form if needed.  But, we don't... */
+    memset(reply.enc_part.ciphertext.data, 0,
+	   reply.enc_part.ciphertext.length);
+    free(reply.enc_part.ciphertext.data);
+    
+cleanup:
+    if (status) {
+	const char * emsg = NULL;
+	if (!errcode)
+	    rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), &reply);
+	if (errcode) 
+	    emsg = krb5_get_error_message (kdc_context, errcode);
+	krb5_klog_syslog(LOG_INFO,
+			 "TGS_REQ (%s) %s: %s: authtime %d, "
+			 "%s%s %s for %s%s%s",
+			 ktypestr,
+			 fromstring, status, authtime,
+			 !errcode ? rep_etypestr : "",
+			 !errcode ? "," : "",
+			 cname ? cname : "<unknown client>",
+			 sname ? sname : "<unknown server>",
+			 errcode ? ", " : "",
+			 errcode ? emsg : "");
+	if (errcode)
+	    krb5_free_error_message (kdc_context, emsg);
+    }
+    
+    if (errcode) {
+        int got_err = 0;
+	if (status == 0) {
+	    status = krb5_get_error_message (kdc_context, errcode);
+	    got_err = 1;
+	}
+	errcode -= ERROR_TABLE_BASE_krb5;
+	if (errcode < 0 || errcode > 128)
+	    errcode = KRB_ERR_GENERIC;
+	    
+	retval = prepare_error_tgs(request, header_ticket, errcode,
+				   fromstring, response, status);
+	if (got_err) {
+	    krb5_free_error_message (kdc_context, status);
+	    status = 0;
+	}
+    }
+    
+    if (header_ticket)
+	krb5_free_ticket(kdc_context, header_ticket);
+    if (request)
+	krb5_free_kdc_req(kdc_context, request);
+    if (cname)
+	free(cname);
+    if (sname)
+	free(sname);
+    if (nprincs)
+	krb5_db_free_principal(kdc_context, &server, 1);
+    if (session_key.contents)
+	krb5_free_keyblock_contents(kdc_context, &session_key);
+    if (newtransited)
+	free(enc_tkt_reply.transited.tr_contents.data); 
+
+    return retval;
+}
+
+static krb5_error_code
+prepare_error_tgs (krb5_kdc_req *request, krb5_ticket *ticket, int error,
+		   const char *ident, krb5_data **response, const char *status)
+{
+    krb5_error errpkt;
+    krb5_error_code retval;
+    krb5_data *scratch;
+
+    errpkt.ctime = request->nonce;
+    errpkt.cusec = 0;
+
+    if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime,
+				    &errpkt.susec)))
+	return(retval);
+    errpkt.error = error;
+    errpkt.server = request->server;
+    if (ticket && ticket->enc_part2)
+	errpkt.client = ticket->enc_part2->client;
+    else
+	errpkt.client = 0;
+    errpkt.text.length = strlen(status) + 1;
+    if (!(errpkt.text.data = malloc(errpkt.text.length)))
+	return ENOMEM;
+    (void) strcpy(errpkt.text.data, status);
+
+    if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) {
+	free(errpkt.text.data);
+	return ENOMEM;
+    }
+    errpkt.e_data.length = 0;
+    errpkt.e_data.data = 0;
+
+    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+    free(errpkt.text.data);
+    if (retval)
+	free(scratch);
+    else
+	*response = scratch;
+
+    return retval;
+}
+
+/*
+ * The request seems to be for a ticket-granting service somewhere else,
+ * but we don't have a ticket for the final TGS.  Try to give the requestor
+ * some intermediate realm.
+ */
+static void
+find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server,
+		   krb5_boolean *more, int *nprincs)
+{
+    krb5_error_code retval;
+    krb5_principal *plist, *pl2;
+    krb5_data tmp;
+
+    *nprincs = 0;
+    *more = FALSE;
+
+    /*
+     * Call to krb5_princ_component is normally not safe but is so
+     * here only because find_alternate_tgs() is only called from
+     * somewhere that has already checked the number of components in
+     * the principal.
+     */
+    if ((retval = krb5_walk_realm_tree(kdc_context, 
+		      krb5_princ_realm(kdc_context, request->server),
+		      krb5_princ_component(kdc_context, request->server, 1),
+				      &plist, KRB5_REALM_BRANCH_CHAR)))
+	return;
+
+    /* move to the end */
+    for (pl2 = plist; *pl2; pl2++);
+
+    /* the first entry in this array is for krbtgt/local@local, so we
+       ignore it */
+    while (--pl2 > plist) {
+	*nprincs = 1;
+	tmp = *krb5_princ_realm(kdc_context, *pl2);
+	krb5_princ_set_realm(kdc_context, *pl2, 
+			     krb5_princ_realm(kdc_context, tgs_server));
+	retval = krb5_db_get_principal(kdc_context, *pl2, server, nprincs, more);
+	krb5_princ_set_realm(kdc_context, *pl2, &tmp);
+	if (retval) {
+	    *nprincs = 0;
+	    *more = FALSE;
+	    krb5_free_realm_tree(kdc_context, plist);
+	    return;
+	}
+	if (*more) {
+	    krb5_db_free_principal(kdc_context, server, *nprincs);
+	    continue;
+	} else if (*nprincs == 1) {
+	    /* Found it! */
+	    krb5_principal tmpprinc;
+	    char *sname;
+
+	    tmp = *krb5_princ_realm(kdc_context, *pl2);
+	    krb5_princ_set_realm(kdc_context, *pl2, 
+				 krb5_princ_realm(kdc_context, tgs_server));
+	    if ((retval = krb5_copy_principal(kdc_context, *pl2, &tmpprinc))) {
+		krb5_db_free_principal(kdc_context, server, *nprincs);
+		krb5_princ_set_realm(kdc_context, *pl2, &tmp);
+		continue;
+	    }
+	    krb5_princ_set_realm(kdc_context, *pl2, &tmp);
+
+	    krb5_free_principal(kdc_context, request->server);
+	    request->server = tmpprinc;
+	    if (krb5_unparse_name(kdc_context, request->server, &sname)) {
+		krb5_klog_syslog(LOG_INFO,
+		       "TGS_REQ: issuing alternate <un-unparseable> TGT");
+	    } else {
+		limit_string(sname);
+		krb5_klog_syslog(LOG_INFO,
+		       "TGS_REQ: issuing TGT %s", sname);
+		free(sname);
+	    }
+	    return;
+	}
+	krb5_db_free_principal(kdc_context, server, *nprincs);
+	continue;
+    }
+
+    *nprincs = 0;
+    *more = FALSE;
+    krb5_free_realm_tree(kdc_context, plist);
+    return;
+}
diff --git a/krb5-1-6/src/kdc/extern.c b/krb5-1-6/src/kdc/extern.c
new file mode 100644
index 000000000..fa3e0af43
--- /dev/null
+++ b/krb5-1-6/src/kdc/extern.c
@@ -0,0 +1,42 @@
+/*
+ * kdc/extern.c
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * allocations of extern stuff
+ */
+
+#include "k5-int.h"
+#include "extern.h"
+
+/* real declarations of KDC's externs */
+kdc_realm_t	**kdc_realmlist = (kdc_realm_t **) NULL;
+int		kdc_numrealms = 0;
+kdc_realm_t	*kdc_active_realm = (kdc_realm_t *) NULL;
+krb5_data empty_string = {0, 0, ""};
+krb5_timestamp kdc_infinity = KRB5_INT32_MAX; /* XXX */
+krb5_rcache	kdc_rcache = (krb5_rcache) NULL;
+krb5_keyblock	psr_key;
+
+volatile int signal_requests_exit = 0;	/* gets set when signal hits */
+volatile int signal_requests_hup = 0;   /* ditto */
diff --git a/krb5-1-6/src/kdc/extern.h b/krb5-1-6/src/kdc/extern.h
new file mode 100644
index 000000000..d4db86aac
--- /dev/null
+++ b/krb5-1-6/src/kdc/extern.h
@@ -0,0 +1,99 @@
+/*
+ * kdc/extern.h
+ *
+ * Copyright 1990,2001 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * <<< Description >>>
+ */
+
+#ifndef __KRB5_KDC_EXTERN__
+#define __KRB5_KDC_EXTERN__
+
+typedef struct __kdc_realm_data {
+    /*
+     * General Kerberos per-realm data.
+     */
+    char *		realm_name;	/* Realm name			    */
+/* XXX the real context should go away once the db_context is done. 
+ * The db_context is then associated with the realm keytab using 
+ * krb5_ktkdb_resolv(). There should be nothing in the context which 
+ * cannot span multiple realms -- proven */
+    krb5_context	realm_context;	/* Context to be used for realm	    */
+    krb5_keytab		realm_keytab; 	/* keytab to be used for this realm */
+    char *		realm_profile;	/* Profile file for this realm	    */
+    /*
+     * Database per-realm data.
+     */
+    char *		realm_dbname;	/* Database name for realm	    */
+    char *		realm_stash;	/* Stash file name for realm	    */
+    char *		realm_mpname;	/* Master principal name for realm  */
+    krb5_principal	realm_mprinc;	/* Master principal for realm	    */
+    krb5_keyblock	realm_mkey;	/* Master key for this realm	    */
+    /*
+     * TGS per-realm data.
+     */
+    krb5_principal	realm_tgsprinc;	/* TGS principal for this realm	    */
+    /*
+     * Other per-realm data.
+     */
+    char		*realm_ports;	/* Per-realm KDC UDP port */
+    char		*realm_tcp_ports; /* Per-realm KDC TCP port */
+    /*
+     * Per-realm parameters.
+     */
+    krb5_deltat		realm_maxlife;	/* Maximum ticket life for realm    */
+    krb5_deltat		realm_maxrlife;	/* Maximum renewable life for realm */
+    krb5_boolean	realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */
+} kdc_realm_t;
+
+extern kdc_realm_t	**kdc_realmlist;
+extern int		kdc_numrealms;
+extern kdc_realm_t	*kdc_active_realm;
+
+kdc_realm_t *find_realm_data (char *, krb5_ui_4);
+
+/*
+ * Replace previously used global variables with the active (e.g. request's)
+ * realm data.  This allows us to support multiple realms with minimal logic
+ * changes.
+ */
+#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_keyblock			kdc_active_realm->realm_mkey
+#define	master_princ			kdc_active_realm->realm_mprinc
+#define	tgs_server_struct		*(kdc_active_realm->realm_tgsprinc)
+#define	tgs_server			kdc_active_realm->realm_tgsprinc
+#define	dbm_db_name			kdc_active_realm->realm_dbname
+#define	primary_port			kdc_active_realm->realm_pport
+#define reject_bad_transit		kdc_active_realm->realm_reject_bad_transit
+
+/* various externs for KDC */
+extern krb5_data 	empty_string;	/* an empty string */
+extern krb5_timestamp 	kdc_infinity;	/* greater than all other timestamps */
+extern krb5_rcache	kdc_rcache;	/* replay cache */
+extern krb5_keyblock	psr_key;	/* key for predicted sam response */
+
+extern volatile int signal_requests_exit;
+extern volatile int signal_requests_hup;
+#endif /* __KRB5_KDC_EXTERN__ */
diff --git a/krb5-1-6/src/kdc/fakeka.M b/krb5-1-6/src/kdc/fakeka.M
new file mode 100644
index 000000000..80ea0153a
--- /dev/null
+++ b/krb5-1-6/src/kdc/fakeka.M
@@ -0,0 +1,111 @@
+.\" kdc/fakeka.M
+.\"
+.\" Copyright 2005 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\"
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH FAKEKA 8
+.SH NAME
+fakeka \- Fake kaserver for AFS clients
+.SH SYNOPSIS
+\fBfakeka\fP [\fB\-dm\fP] [\fB\-c\fP \fIcell\fP] [\fB\-f\fP \fIforwarder\fP]
+[\fB\-l\fP \fBfacility\fP] [\fB\-p\fP \fBport\fP] [\fB\-r\fP \fIrealm\fP]
+.br
+.SH DESCRIPTION
+.I fakeka
+is a fake kaserver that speaks just enough of the AFS RX protocol to make
+klog work.  It is used in conjunction with a Kerberos V5 KDC to support
+existing AFS clients, and is usually used with ka-forwarder.
+.I fakeka
+must run on the same host as your Kerberos V5 KDC, since it needs access
+to the KDC database.  ka-forwarder should run on each of your AFS database
+servers, pointing to your Kerberos V5 KDCs.
+.I fakeka
+should then be running on each of the KDCs, with the AFS database servers
+listed as arguments to the
+.B -f
+option.
+.PP
+Note that principals you wish to use
+.I fakeka
+with must have either a V4-style key (des:v4) or an AFS-style key
+(des:afs3).  V5 enctypes won't work.
+.SH OPTIONS
+.TP
+\fB\-c\fP \fIcell\fP
+The AFS cell for which
+.I fakeka
+will be handling requests.  If not given, this defaults to the same as the
+Kerberos V5 realm (see
+.B \-r
+below).
+.TP
+.B \-d
+Enables debugging.  When this flag is given,
+.I fakeka
+will run in the foreground and print debugging information to standard
+error.  Overrides
+.BR \-m .
+.TP
+\fB\-f\fP \fIforwarder\fP
+Allows forwarded requests from
+.IR forwarder ,
+which is generally an AFS database server running ka-forwarder.  This
+option can be given multiple times (up to 10).  Each system running
+ka-forwarder should be specified with the
+.B \-f
+flag or forwarded requests from that host will not be answered.  (The
+forwarders append their own address to the packet.
+.TP
+\fB\-l\fP \fIfacility\fP
+Log actions via syslog with the given
+.I facility
+rather than the default of LOG_DAEMON.
+.I facility
+must be one of KERN, USER, MAIL, DAEMON, AUTH, LPR, NEWS, UUCP, CRON,
+LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, or LOCAL7.  This
+option is case-sensitive.  Not all of these facilities may be available,
+depending on what pre-defined syslog facilities your system provides.
+.TP
+.B \-m
+Fork and background when starting.  You will usually always want to give
+this flag.
+.TP
+\fB\-p\fP \fIport\fP
+Listen on the specified port rather than the default of 7004 (which is
+what klog expects).
+.I port
+may be a number or a service name from
+.IR /etc/services .
+.TP
+\fB\-r\fP \fIrealm\fP
+The Kerberos V5 realm to which the requests are being translated.  The
+default is the local default realm.
+.SH EXAMPLES
+Handle requests for a local cell whose name matches the local realm,
+accepting forwarded queries from afs1.example.com and afs2.example.com:
+.IP "" 4
+fakeka -m -f afs1.example.com -f afs2.example.com
+.PP
+If the cell name doesn't match the realm name,
+.B \-c
+would need to be added, specifying the cell name.
+.SH SEE ALSO
+ka-forwarder(8)
diff --git a/krb5-1-6/src/kdc/fakeka.c b/krb5-1-6/src/kdc/fakeka.c
new file mode 100644
index 000000000..7a6adf535
--- /dev/null
+++ b/krb5-1-6/src/kdc/fakeka.c
@@ -0,0 +1,1395 @@
+/*
+ * COPYRIGHT NOTICE
+ * Copyright (c) 1994 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * Converted to Kerberos 5 by Ken Hornstein <kenh@cmf.nrl.navy.mil>
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <kerberosIV/krb.h>
+#include <kerberosIV/des.h>
+
+#ifndef LINT
+static char rcsid[]=
+	"$Id$";
+#endif
+
+/*
+ * Misc macros
+ */
+
+#define PAD_TO(x, a) (((u_long)(x) + (a) - 1) & ~((a) - 1))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define MAXFORWARDERS 10
+#define HEADER_LEN 8
+
+/*
+ * Error values from kautils.h
+ * 
+ * The security errors are:
+ * 	KABADTICKET, KABADSERVER, KABADUSER, and KACLOCKSKEW
+ */
+
+#define KADATABASEINCONSISTENT                   (180480L)
+#define KANOENT                                  (180484L)
+#define KABADREQUEST                             (180490L)     
+#define KABADTICKET                              (180504L)
+#define KABADSERVER                              (180507L)
+#define KABADUSER                                (180508L)
+#define KACLOCKSKEW                              (180514L)
+#define KAINTERNALERROR                          (180518L)
+
+
+/*
+ * Type definitions
+ */
+
+typedef struct packet {
+    char *base;
+    int len;
+    char data[1024];
+} *packet_t;
+
+typedef struct rx_header {
+    u_int rx_epoch;
+    u_int rx_cid;
+    u_int rx_callnum;
+    u_int rx_seq;
+    u_int rx_serial;
+    u_char rx_type;
+    u_char rx_flags;
+    u_char rx_userstatus;
+    u_char rx_securityindex;
+    u_short rx_spare;
+    u_short rx_service;
+    u_int rx_request;
+} *rx_t;
+
+
+/*
+ * Global vars
+ */
+
+char *progname = "fakeka";		/* needed by libkdb.a */
+char *localrealm = NULL;
+char *localcell = NULL;
+krb5_timestamp req_time;
+kadm5_config_params realm_params;
+int debug = 0;
+
+
+/*
+ * This is a table for the "infamous" CMU ticket lifetime conversion.  If
+ * the lifetime is greater than 128, use this table
+ */
+#define MAX_TICKET_LIFETIME 2592000
+static long cmu_seconds[] =
+{
+  38400,  41055,  43894,  46929,  50174,  53643,  57352,  61318,
+  65558,  70091,  74937,  80119,  85658,  91581,  97914,  104684,
+  111922,  119661,  127935,  136781,  146239,  156350,  167161,  178720,
+  191077,  204289,  218415,  233517,  249663,  266926,  285383,  305116,
+  326213,  348769,  372885,  398668,  426233,  455705,  487215,  520903,
+  556921,  595430,  636600,  680618,  727679,  777995,  831789,  889303,
+  950794,  1016536,  1086825,  1161973,  1242317,  1328217,  1420057,  1518246,
+  1623225,  1735463,  1855462,  1983757,  2120924,  2267575,  2424366, 2591999,
+  0
+};
+
+#if	__STDC__
+/*
+ * Prototypes for all the functions we define
+ */
+
+void perrorexit(char *);
+void pexit(char *);
+char *kaerror(int);
+int get_princ_key(krb5_context, void *, kadm5_principal_ent_t, des_cblock,
+		  des_key_schedule);
+int check_princ(krb5_context, void *, char *, char *, kadm5_principal_ent_t);
+
+int make_reply_packet(krb5_context, void *, packet_t, int, int, int,
+		      char *, char *, char *, char *,
+		      des_cblock, des_key_schedule, char *);
+
+int Authenticate(krb5_context, void *, char *, packet_t, packet_t);
+int GetTicket(krb5_context, void *, char *, packet_t, packet_t);
+void process(krb5_context, void *, char *, packet_t, packet_t);
+#endif
+
+
+/*
+ * Helpers for exiting with errors
+ */
+
+void perrorexit(str)
+char *str;
+{
+    perror(str);
+    exit(1);
+}
+
+void pexit(str)
+char *str;
+{
+    printf("%s\n", str);
+    exit(1);
+}
+
+
+/*
+ * Translate error codes into strings.
+ */
+
+char *kaerror(e)
+int e;
+{
+    static char buf[1024];
+
+    switch (e) {
+    case KADATABASEINCONSISTENT:
+	return "database is inconsistent";
+    case KANOENT:
+	return "principal does not exist";
+    case KABADREQUEST:
+	return "request was malformed (bad password)";
+    case KABADTICKET:
+	return "ticket was malformed, invalid, or expired";
+    case KABADSERVER:
+	return "cannot issue tickets for this service";
+    case KABADUSER:
+	return "principal expired";
+    case KACLOCKSKEW:
+	return "client time is too far skewed";
+    case KAINTERNALERROR:
+	return "internal error in fakeka, help!";
+    default:
+	sprintf(buf, "impossible error code %d, help!", e);
+	return buf;
+    }
+    /*NOTREACHED*/
+}
+
+/*
+ * Syslog facilities
+ */
+typedef struct {
+	int num;
+	char *string;
+} facility_mapping;
+
+static facility_mapping mappings[] = {
+#ifdef LOG_KERN   
+	{ LOG_KERN, "KERN" },
+#endif
+#ifdef LOG_USER
+	{ LOG_USER, "USER" },
+#endif
+#ifdef LOG_MAIL
+	{ LOG_MAIL, "MAIL" },
+#endif
+#ifdef LOG_DAEMON
+	{ LOG_DAEMON, "DAEMON" },
+#endif
+#ifdef LOG_AUTH
+	{ LOG_AUTH, "AUTH" },
+#endif
+#ifdef LOG_LPR
+	{ LOG_LPR, "LPR" },
+#endif
+#ifdef LOG_NEWS
+	{ LOG_NEWS, "NEWS" },
+#endif
+#ifdef LOG_UUCP
+	{ LOG_UUCP, "UUCP" },
+#endif
+#ifdef LOG_CRON
+	{ LOG_CRON, "CRON" },
+#endif
+#ifdef LOG_LOCAL0
+	{ LOG_LOCAL0, "LOCAL0" },
+#endif
+#ifdef LOG_LOCAL1
+	{ LOG_LOCAL1, "LOCAL1" },
+#endif
+#ifdef LOG_LOCAL2
+	{ LOG_LOCAL2, "LOCAL2" },
+#endif
+#ifdef LOG_LOCAL3
+	{ LOG_LOCAL3, "LOCAL3" },
+#endif
+#ifdef LOG_LOCAL4
+	{ LOG_LOCAL4, "LOCAL4" },
+#endif
+#ifdef LOG_LOCAL5
+	{ LOG_LOCAL5, "LOCAL5" },
+#endif
+#ifdef LOG_LOCAL6
+	{ LOG_LOCAL6, "LOCAL6" },
+#endif
+#ifdef LOG_LOCAL7
+	{ LOG_LOCAL7, "LOCAL7" },
+#endif
+	{ 0, NULL }
+};
+
+
+/*
+ * Get the principal's key and key schedule from the db record.
+ *
+ * Life is more complicated in the V5 world.  Since we can have different
+ * encryption types, we have to make sure that we get back a DES key.
+ * Also, we have to try to get back a AFS3 or V4 salted key, since AFS
+ * doesn't know about a V5 style salt.
+ */
+
+int get_princ_key(context, handle, p, k, s)
+krb5_context context;
+void *handle;
+kadm5_principal_ent_t p;
+des_cblock k;
+des_key_schedule s;
+{	
+    int rv;
+    krb5_keyblock kb;
+    kadm5_ret_t retval;
+
+    /*
+     * We need to call kadm5_decrypt_key to decrypt the key data
+     * from the principal record.  We _must_ have a encryption type
+     * of DES_CBC_CRC, and we prefer having a salt type of AFS 3 (but
+     * a V4 salt will work as well).  If that fails, then return any
+     * type of key we can find.
+     *
+     * Note that since this uses kadm5_decrypt_key, it means it has to
+     * be compiled with the kadm5srv library.
+     */
+
+    if ((retval = kadm5_decrypt_key(handle, p, ENCTYPE_DES_CBC_CRC,
+				    KRB5_KDB_SALTTYPE_AFS3, 0, &kb,
+				    NULL, NULL)))
+	if ((retval = kadm5_decrypt_key(handle, p, ENCTYPE_DES_CBC_CRC,
+					KRB5_KDB_SALTTYPE_V4, 0, &kb,
+					NULL, NULL)))
+		if ((retval = kadm5_decrypt_key(handle, p, ENCTYPE_DES_CBC_CRC,
+						-1, 0, &kb, NULL, NULL))) {
+			syslog(LOG_ERR, "Couldn't find any matching key: %s",
+			       error_message(retval));
+			return KAINTERNALERROR;
+		}
+
+    /*
+     * Copy the data from our krb5_keyblock to the des_cblock.  Make sure
+     * the size of our key matches the V4/AFS des_cblock.
+     */
+
+    if (kb.length != sizeof(des_cblock)) {
+	krb5_free_keyblock_contents(context, &kb);
+	syslog(LOG_ERR, "Principal key size of %d didn't match C_Block size"
+	       " %d", kb.length, sizeof(des_cblock));
+	return KAINTERNALERROR;
+    }
+
+    memcpy((char *) k, (char *) kb.contents, sizeof(des_cblock));
+
+    krb5_free_keyblock_contents(context, &kb);
+
+    /*
+     * Calculate the des key schedule
+     */
+
+    rv = des_key_sched(k, s);
+    if (rv) {
+	memset((void *) k, 0, sizeof(k));
+	memset((void *)s, 0, sizeof(s));
+	return KAINTERNALERROR;
+    }
+    return 0;
+}
+
+
+/*
+ * Fetch principal from db and validate it.
+ *
+ * Note that this always fetches the key data from the principal (but it
+ * doesn't decrypt it).
+ */
+
+int check_princ(context, handle, name, inst, p)
+krb5_context context;
+void *handle;
+char *name, *inst;
+kadm5_principal_ent_t p;
+{
+    krb5_principal princ;
+    krb5_error_code code;
+    kadm5_ret_t retcode;
+
+    /*
+     * Screen out null principals. They are causing crashes here
+     * under HPUX-10.20. - vwelch@ncsa.uiuc.edu 1/6/98
+     */
+    if (!name || (name[0] == '\0')) {
+	syslog(LOG_ERR, "screening out null principal");
+	return KANOENT;
+    }
+
+    /*
+     * Build a principal from the name and instance (the realm is always
+     * the same).
+     */
+
+    if ((code = krb5_build_principal_ext(context, &princ, strlen(localrealm),
+					 localrealm, strlen(name), name,
+					 strlen(inst), inst, 0))) {
+	syslog(LOG_ERR, "could not build principal: %s", error_message(code));
+	return KAINTERNALERROR;
+    }
+
+    /*
+     * Fetch the principal from the database -- also fetch the key data.
+     * Note that since this retrieves the key data, it has to be linked with
+     * the kadm5srv library.
+     */
+
+    if ((retcode = kadm5_get_principal(handle, princ, p,
+				       KADM5_PRINCIPAL_NORMAL_MASK |
+				       KADM5_KEY_DATA))) {
+	if (retcode == KADM5_UNK_PRINC) {
+	    krb5_free_principal(context, princ);
+	    syslog(LOG_INFO, "principal %s.%s does not exist", name, inst);
+	    return KANOENT;
+	} else {
+	    krb5_free_principal(context, princ);
+	    syslog(LOG_ERR, "kadm5_get_principal failed: %s",
+		   error_message(retcode));
+	    return KAINTERNALERROR;
+	}
+    }
+
+    krb5_free_principal(context, princ);
+
+    /*
+     * Check various things - taken from the KDC code.
+     *
+     * Since we're essentially bypassing the KDC, we need to make sure
+     * that we don't give out a ticket that we shouldn't.
+     */
+
+    /*
+     * Has the principal expired?
+     */
+
+    if (p->princ_expire_time && p->princ_expire_time < req_time) {
+	kadm5_free_principal_ent(handle, p);
+	return KABADUSER;
+    }
+
+    /*
+     * Has the principal's password expired?  Note that we don't
+     * check for the PWCHANGE_SERVICE flag here, since we don't
+     * support password changing.  We do support the REQUIRES_PWCHANGE
+     * flag, though.
+     */
+
+    if ((p->pw_expiration && p->pw_expiration < req_time) ||
+	(p->attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+	kadm5_free_principal_ent(handle, p);
+	return KABADUSER;
+    }
+
+    /*
+     * See if the principal is locked out
+     */
+
+    if (p->attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
+	kadm5_free_principal_ent(handle, p);
+	return KABADUSER;
+    }
+
+    /*
+     * There's no way we can handle hardware preauth, so
+     * disallow tickets with this flag set.
+     */
+
+    if (p->attributes & KRB5_KDB_REQUIRES_HW_AUTH) {
+	kadm5_free_principal_ent(handle, p);
+	return KABADUSER;
+    }
+
+    /*
+     * Must be okay, then
+     */
+
+    return 0;
+}
+
+
+/*
+ * Create an rx reply packet in "packet" using the provided data.
+ * The caller is responsible for zeroing key and sched.
+ */
+
+int make_reply_packet(context, handle, reply, challenge_response, start_time,
+		      end_time, cname, cinst, sname, sinst, key, sched, label)
+krb5_context context;
+void *handle;
+packet_t reply;
+int challenge_response, start_time, end_time;
+char *cname, *cinst, *sname, *sinst;
+des_cblock key;
+des_key_schedule sched;
+char *label;
+{
+    int rv, n, maxn, v4life, *enclenp, *ticklenp;
+    u_char *p, *enc, *ticket;
+    kadm5_principal_ent_rec cprinc, sprinc;
+    des_cblock skey, new_session_key;
+    des_key_schedule ssched;
+    krb5_deltat lifetime;
+
+    rv = 0;
+
+    rv = check_princ(context, handle, cname, cinst, &cprinc);
+    if (rv)
+	return rv;
+
+    rv = check_princ(context, handle, sname, sinst, &sprinc);
+    if (rv) {
+	kadm5_free_principal_ent(handle, &cprinc);
+	return rv;
+    }
+
+    /* 
+     * Bound ticket lifetime by max lifetimes of user and service.
+     *
+     * Since V5 already stores everything in Unix epoch timestamps like
+     * AFS, these calculations are much simpler.
+     */
+
+    lifetime = end_time - start_time;
+    lifetime = min(lifetime, cprinc.max_life);
+    lifetime = min(lifetime, sprinc.max_life);
+    lifetime = min(lifetime, realm_params.max_life);
+
+    end_time = start_time + lifetime;
+
+    /*
+     * But we have to convert back to V4-style lifetimes
+     */
+
+    v4life = lifetime / 300;
+    if (v4life > 127) {
+	/*
+	 * Use the CMU algorithm instead
+	 */
+	long *clist = cmu_seconds;
+	while (*clist && *clist < lifetime) clist++;
+	v4life = 128 + (clist - cmu_seconds);
+    }
+
+    /*
+     * If this is for afs and the instance is the local cell name
+     * then we assume we added the instance in GetTickets to
+     * identify the afs key in the kerberos database. This is for
+     * cases where the afs cell name is different from the kerberos
+     * realm name. We now want to remove the instance so it doesn't
+     * cause klog to barf.
+     */
+    if (!strcmp(sname, "afs") && (strcasecmp(sinst, localcell) == 0))
+	sinst[0] = '\0';
+
+    /*
+     * All the data needed to construct the ticket is ready, so do it.
+     */
+
+    p = (unsigned char *) reply->base;
+    maxn = reply->len;
+    n = 0;
+
+#define ERR(x) do { rv = x ; goto error; } while (0)
+#define ADVANCE(x) { if ((n += x) > maxn) ERR(KAINTERNALERROR); else p += x;}
+#define PUT_CHAR(x) { *p = (x); ADVANCE(1); }
+#define PUT_INT(x) { int q = ntohl(x); memcpy(p, (char *)&q, 4); ADVANCE(4); }
+#define PUT_STR(x) { strcpy((char *) p, x); ADVANCE(strlen(x) + 1); }
+
+    ADVANCE(28);
+    PUT_INT(0x2bc);
+
+    enclenp = (int *)p;
+    PUT_INT(0);		/* filled in later */
+
+    enc = p;
+    PUT_INT(0);
+    PUT_INT(challenge_response);
+
+    /*
+     * new_session_key is created here, and remains in the clear
+     * until just before we return.
+     */
+    des_new_random_key(new_session_key);
+    memcpy(p, new_session_key, 8);
+
+    ADVANCE(8);
+    PUT_INT(start_time);
+    PUT_INT(end_time);
+    PUT_INT(sprinc.kvno);
+
+    ticklenp = (int *)p;
+    PUT_INT(0);		/* filled in later */
+
+    PUT_STR(cname);
+    PUT_STR(cinst);
+    PUT_STR("");
+    PUT_STR(sname);
+    PUT_STR(sinst);
+
+    ticket = p;
+    PUT_CHAR(0);	/* flags, always 0 */
+    PUT_STR(cname);
+    PUT_STR(cinst);
+    PUT_STR("");
+    PUT_INT(0);		/* would be ip address */
+
+    memcpy(p, new_session_key, 8);
+
+    ADVANCE(8);
+
+    PUT_CHAR(v4life);
+    PUT_INT(start_time);
+    PUT_STR(sname);
+    PUT_STR(sinst);
+
+    ADVANCE(PAD_TO(p - ticket, 8) - (p - ticket));
+
+    *ticklenp = ntohl(p - ticket);
+
+    rv = get_princ_key(context, handle, &sprinc, skey, ssched);
+    if (rv)
+	return rv;
+    des_pcbc_encrypt((C_Block *) ticket, (C_Block *) ticket, p - ticket,
+		     ssched, (C_Block *) skey, ENCRYPT);
+    memset(skey, 0, sizeof(skey));
+    memset(ssched, 0, sizeof(ssched));
+
+    PUT_STR(label);	/* "tgsT" or "gtkt" */
+    ADVANCE(-1);	/* back up over string terminator */
+
+    ADVANCE(PAD_TO(p - enc, 8) - (p - enc));
+#undef	ERR
+#undef	ADVANCE
+#undef	PUT_CHAR
+#undef	PUT_INT
+#undef	PUT_STR
+
+    *enclenp = ntohl(p - enc);
+    des_pcbc_encrypt((C_Block *) enc, (C_Block *) enc, p - enc, sched,
+		     (C_Block *) key, ENCRYPT);
+    reply->len = n;
+
+  error:
+    memset(new_session_key, 0, sizeof(new_session_key));
+    kadm5_free_principal_ent(handle, &cprinc);
+    kadm5_free_principal_ent(handle, &sprinc);
+
+    return rv;
+}
+
+#define ERR(x) do { rv = x; goto error; } while (0)
+#define ADVANCE(x) { if ((n += x) > maxn) ERR(KABADREQUEST); else p += x; }
+#define GET_INT(x) { int q; memcpy((char *)&q, p, 4); x = ntohl(q); ADVANCE(4); }
+#define GET_CHAR(x) { x = *p; ADVANCE(1); }
+#define GET_PSTR(x) \
+    { \
+	GET_INT(len); \
+	if (len > sizeof(x) - 1) ERR(KABADREQUEST); \
+	memcpy(x, p, len); \
+	x[len] = 0; \
+	ADVANCE(PAD_TO(len, 4)); \
+    }
+
+#define GET_STR(x) \
+    { \
+	len = strlen(p); \
+	if (len > sizeof(x) - 1) ERR(KABADREQUEST); \
+	strcpy(x, p); \
+	ADVANCE(len + 1); \
+    }
+
+
+/*
+ * Process an Authenticate request.
+ */
+
+int Authenticate(context, handle, from, req, reply)
+krb5_context context;
+void *handle;
+char *from;
+packet_t req, reply;
+{
+    int rv, n, maxn;
+    int len, start_time, end_time, challenge;
+    char name[ANAME_SZ+1], inst[INST_SZ+1], *p;
+    kadm5_principal_ent_rec cprinc;
+    des_cblock ckey;
+    des_key_schedule csched;
+    int free_princ_ent = 0;
+
+    rv = 0;
+
+    p = req->base;
+    maxn = req->len;
+    n = 0;
+
+    ADVANCE(32);
+
+    GET_PSTR(name);
+    GET_PSTR(inst);
+
+    if (debug)
+	fprintf(stderr, "Authenticating %s.%s\n", name, inst);
+
+    rv = check_princ(context, handle, name, inst, &cprinc);
+    if (rv)
+	ERR(rv);
+
+    free_princ_ent = 1;
+
+    GET_INT(start_time);
+    GET_INT(end_time);
+
+    GET_INT(len);
+    if (len != 8)
+	ERR(KABADREQUEST);
+
+    /*
+     * ckey and csched are set here and remain in the clear
+     * until just before we return.
+     */
+
+    rv = get_princ_key(context, handle, &cprinc, ckey, csched);
+    if (rv)
+	ERR(rv);
+    des_pcbc_encrypt((C_Block *) p, (C_Block *) p, 8, csched,
+		     (C_Block *) ckey, DECRYPT);
+
+    GET_INT(challenge);
+
+    rv = memcmp(p, "gTGS", 4);
+    if (rv)
+	ERR(KABADREQUEST);
+    ADVANCE(4);
+
+    /* ignore the rest */
+    ADVANCE(8);
+
+    /*
+     * We have all the data from the request, now generate the reply.
+     */
+
+    rv =  make_reply_packet(context, handle, reply, challenge + 1, start_time,
+   			    end_time, name, inst, "krbtgt", localcell,
+			    ckey, csched, "tgsT");
+  error:
+    memset(ckey, 0, sizeof(ckey));
+    memset(csched, 0, sizeof(csched));
+
+    syslog(LOG_INFO, "authenticate: %s.%s from %s", name, inst, from);
+    if (rv) {
+	syslog(LOG_INFO, "... failed due to %s", kaerror(rv));
+    }
+    if (free_princ_ent)
+	kadm5_free_principal_ent(handle, &cprinc);
+    return rv;
+}
+
+
+/*
+ * Process a GetTicket rpc.
+ */
+
+int GetTicket(context, handle, from, req, reply)
+krb5_context context;
+void *handle;
+char *from;
+packet_t req, reply;
+{
+    int rv, n, maxn, len, ticketlen;
+    char *p;
+    u_int kvno, start_time, end_time, times[2], flags, ipaddr;
+    u_int tgt_start_time, tgt_end_time, lifetime;
+    char rname[ANAME_SZ+1], rinst[INST_SZ+1];	/* requested principal */
+    char sname[ANAME_SZ+1], sinst[INST_SZ+1];	/* service principal (TGT) */
+    char cname[ANAME_SZ+1], cinst[INST_SZ+1];	/* client principal */
+    char cell[REALM_SZ+1], realm[REALM_SZ+1];
+    char enctimes[8 + 1], ticket[1024];
+    u_char tgt_lifetime;
+    kadm5_principal_ent_rec cprinc;
+    des_cblock ckey, session_key;
+    des_key_schedule csched, session_sched;
+    int free_princ_ent = 0;
+
+    rv = 0;
+
+    /* 
+     * Initialize these so we don't crash trying to print them in
+     * case they don't get filled in.
+     */
+    strcpy(rname, "Unknown");
+    strcpy(rinst, "Unknown");
+    strcpy(sname, "Unknown");
+    strcpy(sinst, "Unknown");
+    strcpy(cname, "Unknown");
+    strcpy(cinst, "Unknown");
+    strcpy(cell, "Unknown");
+    strcpy(realm, "Unknown");
+    
+    p = req->base;
+    maxn = req->len;
+    n = 0;
+
+    ADVANCE(32);
+
+    GET_INT(kvno);
+
+    GET_PSTR(cell);
+    if (!cell[0])
+	strcpy(cell, localcell);
+
+    if (debug)
+	fprintf(stderr, "Cell is %s\n", cell);
+
+    memset(ticket, 0, sizeof(ticket));
+    GET_PSTR(ticket);
+    ticketlen = len;	/* hacky hack hack */
+    GET_PSTR(rname);
+    GET_PSTR(rinst);
+
+    if (debug)
+	fprintf(stderr, "Request for %s/%s\n", rname, rinst);
+
+    GET_PSTR(enctimes);	/* still encrypted */
+    if (len != 8)	/* hack and hack again */
+	ERR(KABADREQUEST);
+
+    /* ignore the rest */
+    ADVANCE(8);
+
+    /*
+     * That's it for the packet, now decode the embedded ticket.
+     */
+
+    rv = check_princ(context, handle, "krbtgt", cell, &cprinc);
+    if (rv)
+	ERR(rv);
+
+    free_princ_ent = 1;
+
+    rv = get_princ_key(context, handle, &cprinc, ckey, csched);
+    if (rv)
+	ERR(rv);
+    des_pcbc_encrypt((C_Block *) ticket, (C_Block *) ticket, ticketlen, csched,
+		     (C_Block *) ckey, DECRYPT);
+    memset(ckey, 0, sizeof(ckey));
+    memset(csched, 0, sizeof(csched));
+
+    /*
+     * The ticket's session key is now in the clear in the ticket buffer.
+     * We zero it just before returning.
+     */
+
+    p = ticket;
+    maxn = ticketlen;
+    n = 0;
+
+    GET_CHAR(flags);
+    GET_STR(cname);
+    GET_STR(cinst);
+    GET_STR(realm);
+    GET_INT(ipaddr);
+    memcpy(session_key, p, 8);
+    ADVANCE(8);
+
+    GET_CHAR(tgt_lifetime);
+    GET_INT(tgt_start_time);
+    GET_STR(sname);
+    GET_STR(sinst);
+
+    if (debug)
+	fprintf(stderr,
+		"ticket: %s.%s@%s for %s.%s\n",
+		cname, cinst, realm, sname, sinst);
+
+    /*
+     * ok, we've got the ticket unpacked.
+     * now decrypt the start and end times.
+     */
+
+    rv = des_key_sched(session_key, session_sched);
+    if (rv) 
+	ERR(KABADTICKET);
+
+    des_ecb_encrypt((C_Block *) enctimes, (C_Block *) times, session_sched,
+		    DECRYPT);
+    start_time = ntohl(times[0]);
+    end_time = ntohl(times[1]);
+
+    /*
+     * All the info we need is now available.
+     * Now validate the request.
+     */
+
+    /*
+     * This translator requires that the flags and IP address
+     * in the ticket be zero, because we always set them that way,
+     * and we want to accept only tickets that we generated.
+     * 
+     * Are the flags and IP address fields 0?
+     */
+    if (flags || ipaddr) {
+	if (debug)
+	    fprintf(stderr, "ERROR: flags or ipaddr field non-zero\n");
+	ERR(KABADTICKET);
+    }
+    /*
+     * Is the supplied ticket a tgt?
+     */
+    if (strcmp(sname, "krbtgt")) {
+	if (debug)
+	    fprintf(stderr, "ERROR: not for krbtgt service\n");
+	ERR(KABADTICKET);
+    }
+
+    /*
+     * This translator does not allow MIT-style cross-realm access.
+     * Is this a cross-realm ticket?
+     */
+    if (strcasecmp(sinst, localcell)) {
+	if (debug)
+	    fprintf(stderr,
+		    "ERROR: Service instance (%s) differs from local cell\n",
+		    sinst);
+	ERR(KABADTICKET);
+    }
+
+    /*
+     * This translator does not issue cross-realm tickets,
+     * since klog doesn't use this feature.
+     * Is the request for a cross-realm ticket?
+     */
+    if (strcasecmp(cell, localcell)) {
+	if (debug)
+	    fprintf(stderr, "ERROR: Cell %s != local cell", cell);
+	ERR(KABADTICKET);
+    }
+
+    /*
+     * Even if we later decide to issue cross-realm tickets,
+     * we should not permit "realm hopping".
+     * This means that the client's realm should match
+     * the realm of the tgt with whose key we are supposed
+     * to decrypt the ticket.  I think.
+     */
+    if (*realm && strcasecmp(realm, cell)) {
+	if (debug)
+	    fprintf(stderr, "ERROR: Realm %s != cell %s\n", realm, cell);
+	ERR(KABADTICKET);
+    }
+
+    /*
+     * This translator issues service tickets only for afs,
+     * since klog is the only client that should be using it.
+     * Is the requested service afs?
+     *
+     * Note: to make EMT work, we're allowing tickets for emt/admin and
+     * adm/admin.
+     */
+    if (! ((strcmp(rname, "afs") == 0 && ! *rinst) ||
+	   (strcmp(rname, "emt") == 0 && strcmp(rinst, "admin") == 0) ||
+	   (strcmp(rname, "adm") == 0 && strcmp(rinst, "admin") == 0)))
+	ERR(KABADSERVER);
+
+    /*
+     * If the local realm name and cell name differ and the user
+     * is in the local cell and has requested a ticket of afs. (no
+     * instance, then we actually want to get a ticket for
+     * afs/<cell name>@<realm name>
+     */
+    if ((strcmp(rname, "afs") == 0) && !*rinst &&
+	strcmp(localrealm, localcell) &&
+	(strcasecmp(cell, localcell) == 0)) {
+	char *c;
+
+	strcpy(rinst, localcell);
+
+	for (c = rinst; *c != NULL; c++)
+	    *c = (char) tolower( (int) *c);
+
+	if (debug)
+	    fprintf(stderr, "Getting ticket for afs/%s\n", localcell);
+    }
+   
+    /*
+     * Even if we later decide to issue service tickets for
+     * services other than afs, we should still disallow
+     * the "changepw" and "krbtgt" services.
+     */
+    if (!strcmp(rname, "changepw") || !strcmp(rname, "krbtgt"))
+	ERR(KABADSERVER);
+
+    /*
+     * Is the tgt valid yet?  (ie. is the start time in the future)
+     */
+    if (req_time < tgt_start_time - CLOCK_SKEW) {
+	if (debug)
+	    fprintf(stderr, "ERROR: Ticket not yet valid\n");
+	ERR(KABADTICKET);
+    }
+
+    /*
+     * Has the tgt expired?  (ie. is the end time in the past)
+     *
+     * Sigh, convert from V4 lifetimes back to Unix epoch times.
+     */
+
+    if (tgt_lifetime < 128)
+	tgt_end_time = tgt_start_time + tgt_lifetime * 300;
+    else if (tgt_lifetime < 192)
+	tgt_end_time = tgt_start_time + cmu_seconds[tgt_lifetime - 128];
+    else
+	tgt_end_time = tgt_start_time + MAX_TICKET_LIFETIME;
+
+    if (tgt_end_time < req_time) {
+	if (debug)
+	    fprintf(stderr, "ERROR: Ticket expired\n");
+	ERR(KABADTICKET);
+    }
+
+    /*
+     * This translator uses the requested start time as a cheesy
+     * authenticator, since the KA protocol does not have an
+     * explicit authenticator.  We can do this since klog always
+     * requests a start time equal to the current time.
+     * 
+     * Is the requested start time approximately now?
+     */
+    if (abs(req_time - start_time) > CLOCK_SKEW)
+	ERR(KACLOCKSKEW);
+
+    /*
+     * The new ticket's lifetime is the minimum of:
+     * 1.  remainder of tgt's lifetime
+     * 2.  requested lifetime
+     * 
+     * This is further limited by the client and service's max lifetime
+     * in make_reply_packet().
+     */
+
+    lifetime = tgt_end_time - req_time;
+    lifetime = min(lifetime, end_time - start_time);
+    end_time = req_time + lifetime;
+
+    /*
+     * We have all the data from the request, now generate the reply.
+     */
+
+    rv = make_reply_packet(context, handle, reply, 0, start_time, end_time,
+			   cname, cinst, rname, rinst,
+			   session_key, session_sched, "gtkt");
+  error:
+    memset(ticket, 0, sizeof(ticket));
+    memset(session_key, 0, sizeof(session_key));
+    memset(session_sched, 0, sizeof(session_sched));
+
+    if (free_princ_ent)
+	kadm5_free_principal_ent(handle, &cprinc);
+
+    syslog(LOG_INFO, "getticket: %s.%s from %s for %s.%s",
+	   cname, cinst, from, rname, rinst);
+    if (rv) {
+	syslog(LOG_INFO, "... failed due to %s", kaerror(rv));
+    }
+    return rv;
+}
+
+
+#undef	ERR
+#undef	ADVANCE
+#undef	GET_INT
+#undef	GET_PSTR
+#undef	GET_STR
+
+/*
+ * Convert the request into a reply.
+ * Returns 0 on success.
+ */
+
+void process(context, handle, from, req, reply)
+krb5_context context;
+void *handle;
+char *from;
+packet_t req, reply;
+{
+    int rv;
+    rx_t req_rx = (rx_t)req->base;
+    rx_t reply_rx = (rx_t)reply->base;
+    int service, request;
+
+    service = ntohs(req_rx->rx_service);
+    request = ntohl(req_rx->rx_request);
+
+    /* ignore everything but type 1 */
+    if (req_rx->rx_type != 1) {
+	reply->len = 0;
+	return;
+    }
+
+    /* copy the rx header and change the flags */
+    *reply_rx = *req_rx;
+    reply_rx->rx_flags = 4;
+
+    rv = -1;
+
+    if (service == 0x2db && (request == 0x15 || request == 0x16)) {
+	if (debug)
+	    fprintf(stderr, "Handling Authenticate request\n");
+	rv = Authenticate(context, handle, from, req, reply);
+    }
+    if (service == 0x2dc && request == 0x17) {
+	if (debug)
+	    fprintf(stderr, "Handling GetTicket request\n");
+	rv = GetTicket(context, handle, from, req, reply);
+    }
+/*
+    if (service == 0x2db && request == 0x1) {
+	rv = Authenticate_old(from, req, reply);
+    }
+    if (service == 0x2dc && request == 0x3) {
+	rv = GetTicket_old(from, req, reply);
+    }
+ */
+    if (rv == -1) {
+	syslog(LOG_INFO, "bogus request %d/%d", service, request);
+	rv = KABADREQUEST;
+    }
+
+    if (rv) {
+	/* send the error back to rx */
+	reply->len = sizeof (*reply_rx);
+
+	reply_rx->rx_type = 4;
+	reply_rx->rx_flags = 0;
+	reply_rx->rx_request = ntohl(rv);
+    }
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+    int s, rv, ch, mflag = 0;
+    u_short port;
+    struct sockaddr_in sin;
+    int forwarders[MAXFORWARDERS], num_forwarders;
+    krb5_context context;
+    krb5_error_code code;
+    krb5_keyblock mkey;
+    krb5_principal master_princ;
+    kadm5_principal_ent_rec master_princ_rec;
+    void *handle;
+    facility_mapping *mapping;
+    int facility = LOG_DAEMON;
+
+    extern char *optarg;
+
+    port = 7004;
+    num_forwarders = 0;
+
+    /*
+     * Parse args.
+     */
+    while ((ch = getopt(argc, argv, "c:df:l:mp:r:")) != -1) {
+	switch (ch) {
+	case 'c':
+	    localcell = optarg;
+	    break;
+	case 'd':
+	    debug++;
+	    break;
+	case 'f': {
+	    struct hostent *hp;
+
+	    if (num_forwarders++ >= MAXFORWARDERS)
+		pexit("too many forwarders\n");
+
+	    hp = gethostbyname(optarg);
+	    if (!hp) {
+		printf("unknown host %s\n", optarg);
+		exit(1);
+	    }
+	    forwarders[num_forwarders - 1] = *(int *)hp->h_addr;
+
+	    break;
+	}
+	case 'l':
+	    for (mapping = mappings; mapping->string != NULL; mapping++)
+		if (strcmp(mapping->string, optarg) == 0)
+		    break;
+
+		if (mapping->string == NULL) {
+		    printf("Unknown facility \"%s\"\n", optarg);
+		    exit(1);
+		}
+
+		facility = mapping->num;
+		break;
+	case 'm':
+	    mflag = 1;
+	    break;
+	case 'p':
+	    if (isdigit(*optarg)) {
+		port = atoi(optarg);
+	    }
+	    else {
+		struct servent *sp;
+
+		sp = getservbyname(optarg, "udp");
+		if (!sp) {
+		    printf("unknown service %s\n", optarg);
+		    exit(1);
+		}
+		port = sp->s_port;
+	    }
+	    break;
+	case 'r':
+	    localrealm = optarg;
+	    break;
+	default:
+	    printf("usage: %s [-c cell] [-d] [-f forwarder-host] [-l facility ] [-p port] [-r realm]\n",
+		   argv[0]);
+	    exit(1);
+	}
+    }
+
+    openlog("fakeka", LOG_PID, facility);
+
+    port = htons(port);
+
+    /*
+     * Set up the socket.
+     */
+
+    s = socket(AF_INET, SOCK_DGRAM, 0);
+    if (s < 0)
+	perrorexit("Couldn't create socket");
+
+    sin.sin_family = AF_INET;
+    sin.sin_addr.s_addr = 0;
+    sin.sin_port = port;
+
+    rv = bind(s, (struct sockaddr *)&sin, sizeof(sin));
+    if (rv < 0)
+	perrorexit("Couldn't bind socket");
+
+    /*
+     * Initialize kerberos stuff and kadm5 stuff.
+     */
+
+    if ((code = krb5int_init_context_kdc(&context))) {
+	com_err(argv[0], code, "while initializing Kerberos");
+	exit(1);
+    }
+
+    if (!localrealm && (code = krb5_get_default_realm(context, &localrealm))) {
+	com_err(argv[0], code, "while getting local realm");
+	exit(1);
+    }
+
+    if (!localcell)
+	localcell = localrealm;
+
+    if ((code = kadm5_init_with_password(progname, NULL, KADM5_ADMIN_SERVICE,
+					 NULL, KADM5_STRUCT_VERSION,
+					 KADM5_API_VERSION_2,
+					 (char **) NULL, /* db_args */
+					 &handle))) {
+	com_err(argv[0], code, "while initializing Kadm5");
+	exit(1);
+    }
+
+    if ((code = kadm5_get_config_params(context, 1, NULL,
+					&realm_params))) {
+	com_err(argv[0], code, "while getting realm parameters");
+	exit(1);
+    }
+
+    if (! (realm_params.mask & KADM5_CONFIG_MAX_LIFE)) {
+	fprintf(stderr, "Cannot determine maximum ticket lifetime\n");
+	exit(1);
+    }
+
+    /*
+     * We need to initialize the random number generator for DES.  Use
+     * the master key to do this.
+     */
+
+    if ((code = krb5_parse_name(context, realm_params.mask &
+				KADM5_CONFIG_MKEY_NAME ?
+				realm_params.mkey_name : "K/M",
+				&master_princ))) {
+	com_err(argv[0], code, "while parsing master key name");
+	exit(1);
+    }
+
+    if ((code = kadm5_get_principal(handle, master_princ, &master_princ_rec,
+				    KADM5_KEY_DATA))) {
+	com_err(argv[0], code, "while getting master key data");
+	exit(1);
+    }
+
+    if ((code = kadm5_decrypt_key(handle, &master_princ_rec,
+				  ENCTYPE_DES_CBC_CRC, -1, 0, &mkey, NULL,
+				  NULL))) {
+	com_err(argv[0], code, "while decrypting the master key");
+	exit(1);
+    }
+
+    des_init_random_number_generator(mkey.contents);
+
+    krb5_free_keyblock_contents(context, &mkey);
+
+    kadm5_free_principal_ent(handle, &master_princ_rec);
+
+    krb5_free_principal(context, master_princ);
+
+    /*
+     * Fork and go into the background, if requested
+     */
+
+    if (!debug && mflag && daemon(0, 0)) {
+	com_err(argv[0], errno, "while detaching from tty");
+    }
+
+    /*
+     * rpc server loop.
+     */
+
+    for (;;) {
+	struct packet req, reply;
+	int sinlen, packetlen, i, forwarded;
+	char *from;
+
+	sinlen = sizeof(sin);
+	forwarded = 0;
+
+	memset(req.data, 0, sizeof(req.data));
+	rv = recvfrom(s, req.data, sizeof(req.data),
+		      0, (struct sockaddr *)&sin, &sinlen);
+
+	if (rv < 0) {
+	    syslog(LOG_ERR, "recvfrom failed: %m");
+	    sleep(1);
+	    continue;
+	}
+	packetlen = rv;
+
+	for (i = 0; i < num_forwarders; i++) {
+	    if (sin.sin_addr.s_addr == forwarders[i]) {
+		forwarded = 1;
+		break;
+	    }
+	}
+
+	if ((code = krb5_timeofday(context, &req_time))) {
+		syslog(LOG_ERR, "krb5_timeofday failed: %s",
+		       error_message(code));
+		continue;
+	}
+
+	memset(reply.data, 0, sizeof(reply.data));
+	req.len = packetlen;
+	req.base = req.data;
+	reply.base = reply.data;
+	reply.len = sizeof(reply.data);
+
+	if (forwarded) {
+	    struct in_addr ia;
+
+	    memcpy(&ia.s_addr, req.data, 4);
+	    from = inet_ntoa(ia);
+	    /*
+	     * copy the forwarder header and adjust the bases and lengths.
+	     */
+	    memcpy(reply.data, req.data, HEADER_LEN);
+	    req.base += HEADER_LEN;
+	    req.len -= HEADER_LEN;
+	    reply.base += HEADER_LEN;
+	    reply.len -= HEADER_LEN;
+	}
+	else {
+	    from = inet_ntoa(sin.sin_addr);
+	}
+
+	process(context, handle, from, &req, &reply);
+
+	if (reply.len == 0)
+	    continue;
+
+	if (forwarded) {
+	    /* re-adjust the length to account for the forwarder header */
+	    reply.len += HEADER_LEN;
+	}
+
+	rv = sendto(s, reply.data, reply.len,
+		    0, (struct sockaddr *)&sin, sinlen);
+	if (rv < 0) {
+	    syslog(LOG_ERR, "sendto failed: %m");
+	    sleep(1);
+	}
+    }
+    /*NOTREACHED*/
+}
diff --git a/krb5-1-6/src/kdc/kdc5_err.et b/krb5-1-6/src/kdc/kdc5_err.et
new file mode 100644
index 000000000..9d0ce877c
--- /dev/null
+++ b/krb5-1-6/src/kdc/kdc5_err.et
@@ -0,0 +1,35 @@
+#
+# kdc/kdc5_err.et
+#
+# Copyright 1990 by the Massachusetts Institute of Technology.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+#
+# KDC internal error table.
+
+error_table	kdc5
+
+error_code KDC5_RCSID,		"$Id$"
+error_code KDC5_NOPORT,		"No server port found"
+error_code KDC5_NONET,		"Network not initialized"
+error_code KDC5_IO_RESPONSE,	"Short write while sending response"
+
+end
diff --git a/krb5-1-6/src/kdc/kdc_preauth.c b/krb5-1-6/src/kdc/kdc_preauth.c
new file mode 100644
index 000000000..13a450e43
--- /dev/null
+++ b/krb5-1-6/src/kdc/kdc_preauth.c
@@ -0,0 +1,2352 @@
+/*
+ * kdc/kdc_preauth.c
+ *
+ * Copyright 1995, 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 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"
+#include <stdio.h>
+#include "adm_proto.h"
+#include <syslog.h>
+
+#include <assert.h>
+#include "../include/krb5/preauth_plugin.h"
+
+#if TARGET_OS_MAC
+static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/preauth", NULL }; /* should be a list */
+#else
+static const char *objdirs[] = { LIBDIR "/krb5/plugins/preauth", NULL };
+#endif
+
+/* XXX This is ugly and should be in a header file somewhere */
+#ifndef KRB5INT_DES_TYPES_DEFINED
+#define KRB5INT_DES_TYPES_DEFINED
+typedef unsigned char des_cblock[8];	/* crypto-block size */
+#endif
+typedef des_cblock mit_des_cblock;
+extern void mit_des_fixup_key_parity (mit_des_cblock );
+extern int mit_des_is_weak_key (mit_des_cblock );
+
+typedef struct _krb5_preauth_systems {
+    const char *name;
+    int		type;
+    int		flags;
+    void       *plugin_context;
+    preauth_server_init_proc	init;
+    preauth_server_fini_proc	fini;
+    preauth_server_edata_proc	get_edata;
+    preauth_server_verify_proc	verify_padata;
+    preauth_server_return_proc	return_padata;
+    preauth_server_free_reqcontext_proc	free_pa_reqctx;
+} krb5_preauth_systems;
+
+static krb5_error_code verify_enc_timestamp
+    (krb5_context, krb5_db_entry *client,
+		    krb5_data *req_pkt,
+		    krb5_kdc_req *request,
+		    krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data,
+		    preauth_get_entry_data_proc get_entry_data,
+		    void *pa_system_context,
+		    void **pa_request_context,
+		    krb5_data **e_data,
+		    krb5_authdata ***authz_data);
+
+static krb5_error_code get_etype_info
+    (krb5_context, krb5_kdc_req *request,
+		    krb5_db_entry *client, krb5_db_entry *server,
+		    preauth_get_entry_data_proc get_entry_data,
+		    void *pa_system_context,
+		    krb5_pa_data *data);
+static krb5_error_code
+get_etype_info2(krb5_context context, krb5_kdc_req *request,
+	        krb5_db_entry *client, krb5_db_entry *server,
+		preauth_get_entry_data_proc get_entry_data,
+		void *pa_system_context,
+		krb5_pa_data *pa_data);
+static krb5_error_code
+etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, 
+			 krb5_db_entry *client,
+			 krb5_kdc_req *request, krb5_kdc_rep *reply,
+			 krb5_key_data *client_key,
+			 krb5_keyblock *encrypting_key,
+			 krb5_pa_data **send_pa,
+			 int etype_info2);
+
+static krb5_error_code
+return_etype_info(krb5_context, krb5_pa_data * padata, 
+		  krb5_db_entry *client,
+		  krb5_data *req_pkt,
+		  krb5_kdc_req *request, krb5_kdc_rep *reply,
+		  krb5_key_data *client_key,
+		  krb5_keyblock *encrypting_key,
+		  krb5_pa_data **send_pa,
+		  preauth_get_entry_data_proc get_entry_data,
+		  void *pa_system_context,
+		  void **pa_request_context);
+
+static krb5_error_code
+return_etype_info2(krb5_context, krb5_pa_data * padata, 
+		   krb5_db_entry *client,
+		   krb5_data *req_pkt,
+		   krb5_kdc_req *request, krb5_kdc_rep *reply,
+		   krb5_key_data *client_key,
+		   krb5_keyblock *encrypting_key,
+		   krb5_pa_data **send_pa,
+		   preauth_get_entry_data_proc get_entry_data,
+		   void *pa_system_context,
+		   void **pa_request_context);
+
+static krb5_error_code return_pw_salt
+    (krb5_context, krb5_pa_data * padata, 
+		    krb5_db_entry *client,
+		    krb5_data *req_pkt,
+		    krb5_kdc_req *request, krb5_kdc_rep *reply,
+		    krb5_key_data *client_key,
+		    krb5_keyblock *encrypting_key,
+		    krb5_pa_data **send_pa,
+		    preauth_get_entry_data_proc get_entry_data,
+		    void *pa_system_context,
+		    void **pa_request_context);
+
+/* SAM preauth support */
+static krb5_error_code verify_sam_response
+    (krb5_context, krb5_db_entry *client,
+		    krb5_data *req_pkt,
+		    krb5_kdc_req *request,
+		    krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data,
+		    preauth_get_entry_data_proc get_entry_data,
+		    void *pa_module_context,
+		    void **pa_request_context,
+		    krb5_data **e_data,
+		    krb5_authdata ***authz_data);
+
+static krb5_error_code get_sam_edata
+    (krb5_context, krb5_kdc_req *request,
+		    krb5_db_entry *client, krb5_db_entry *server,
+		    preauth_get_entry_data_proc get_entry_data,
+		    void *pa_module_context,
+		    krb5_pa_data *data);
+static krb5_error_code return_sam_data
+    (krb5_context, krb5_pa_data * padata, 
+		    krb5_db_entry *client,
+		    krb5_data *req_pkt,
+		    krb5_kdc_req *request, krb5_kdc_rep *reply,
+		    krb5_key_data *client_key,
+		    krb5_keyblock *encrypting_key,
+		    krb5_pa_data **send_pa,
+		    preauth_get_entry_data_proc get_entry_data,
+		    void *pa_module_context,
+		    void **pa_request_context);
+
+static krb5_preauth_systems static_preauth_systems[] = {
+    {
+	"timestamp",
+        KRB5_PADATA_ENC_TIMESTAMP,
+        0,
+	NULL,
+	NULL,
+	NULL,
+        0,
+	verify_enc_timestamp,
+	0
+    },
+    {
+	"etype-info",
+	KRB5_PADATA_ETYPE_INFO,
+	0,
+	NULL,
+	NULL,
+	NULL,
+	get_etype_info,
+	0,
+	return_etype_info
+    },
+    {
+	"etype-info2",
+	KRB5_PADATA_ETYPE_INFO2,
+	0,
+	NULL,
+	NULL,
+	NULL,
+	get_etype_info2,
+	0,
+	return_etype_info2
+    },
+    {
+	"pw-salt",
+	KRB5_PADATA_PW_SALT,
+	PA_PSEUDO,		/* Don't include this in the error list */
+	NULL,
+	NULL,
+	NULL,
+	0, 
+	0,
+	return_pw_salt
+    },
+    {
+	"sam-response",
+	KRB5_PADATA_SAM_RESPONSE,
+	0,
+	NULL,
+	NULL,
+	NULL,
+	0,
+	verify_sam_response,
+	return_sam_data
+    },
+    {
+	"sam-challenge",
+	KRB5_PADATA_SAM_CHALLENGE,
+	PA_HARDWARE,		/* causes get_preauth_hint_list to use this */
+	NULL,
+	NULL,
+	NULL,
+	get_sam_edata,
+	0,
+	0
+    },
+    { "[end]", -1,}
+};
+
+static krb5_preauth_systems *preauth_systems;
+static int n_preauth_systems;
+static struct plugin_dir_handle preauth_plugins;
+
+krb5_error_code
+load_preauth_plugins(krb5_context context)
+{
+    struct errinfo err;
+    void **preauth_plugins_ftables;
+    struct krb5plugin_preauth_server_ftable_v1 *ftable;
+    int module_count, i, j, k;
+    void *plugin_context;
+    preauth_server_init_proc server_init_proc = NULL;
+    char **kdc_realm_names = NULL;
+
+    memset(&err, 0, sizeof(err));
+
+    /* Attempt to load all of the preauth plugins we can find. */
+    PLUGIN_DIR_INIT(&preauth_plugins);
+    if (PLUGIN_DIR_OPEN(&preauth_plugins) == 0) {
+	if (krb5int_open_plugin_dirs(objdirs, NULL,
+				     &preauth_plugins, &err) != 0) {
+	    return KRB5_PLUGIN_NO_HANDLE;
+	}
+    }
+
+    /* Get the method tables provided by the loaded plugins. */
+    preauth_plugins_ftables = NULL;
+    if (krb5int_get_plugin_dir_data(&preauth_plugins,
+				    "preauthentication_server_1",
+				    &preauth_plugins_ftables, &err) != 0) {
+	return KRB5_PLUGIN_NO_HANDLE;
+    }
+
+    /* Count the valid modules. */
+    module_count = sizeof(static_preauth_systems)
+		   / sizeof(static_preauth_systems[0]);
+    if (preauth_plugins_ftables != NULL) {
+	for (i = 0; preauth_plugins_ftables[i] != NULL; i++) {
+	    ftable = preauth_plugins_ftables[i];
+	    if ((ftable->flags_proc == NULL) &&
+		(ftable->edata_proc == NULL) &&
+		(ftable->verify_proc == NULL) &&
+		(ftable->return_proc == NULL)) {
+		continue;
+	    }
+	    for (j = 0;
+		 ftable->pa_type_list != NULL &&
+		 ftable->pa_type_list[j] > 0;
+		 j++) {
+		module_count++;
+	    }
+	}
+    }
+
+    /* Build the complete list of supported preauthentication options, and
+     * leave room for a terminator entry. */
+    preauth_systems = malloc(sizeof(krb5_preauth_systems) * (module_count + 1));
+    if (preauth_systems == NULL) {
+	krb5int_free_plugin_dir_data(preauth_plugins_ftables);
+	return ENOMEM;
+    }
+
+    /* Build a list of the names of the supported realms for this KDC.
+     * The list of names is terminated with a NULL. */
+    kdc_realm_names = malloc(sizeof(char *) * (kdc_numrealms + 1));
+    if (kdc_realm_names == NULL) {
+	krb5int_free_plugin_dir_data(preauth_plugins_ftables);
+	return ENOMEM;
+    }
+    for (i = 0; i < kdc_numrealms; i++) {
+	kdc_realm_names[i] = kdc_realmlist[i]->realm_name;
+    }
+    kdc_realm_names[i] = NULL;
+
+    /* Add the locally-supplied mechanisms to the dynamic list first. */
+    for (i = 0, k = 0;
+	 i < sizeof(static_preauth_systems) / sizeof(static_preauth_systems[0]);
+	 i++) {
+	if (static_preauth_systems[i].type == -1)
+	    break;
+	preauth_systems[k] = static_preauth_systems[i];
+	/* Try to initialize the preauth system.  If it fails, we'll remove it
+	 * from the list of systems we'll be using. */
+	plugin_context = NULL;
+	server_init_proc = static_preauth_systems[i].init;
+	if ((server_init_proc != NULL) &&
+	    ((*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names) != 0)) {
+	    memset(&preauth_systems[k], 0, sizeof(preauth_systems[k]));
+	    continue;
+	}
+	preauth_systems[k].plugin_context = plugin_context;
+	k++;
+    }
+
+    /* Now add the dynamically-loaded mechanisms to the list. */
+    if (preauth_plugins_ftables != NULL) {
+	for (i = 0; preauth_plugins_ftables[i] != NULL; i++) {
+	    ftable = preauth_plugins_ftables[i];
+	    if ((ftable->flags_proc == NULL) &&
+		(ftable->edata_proc == NULL) &&
+		(ftable->verify_proc == NULL) &&
+		(ftable->return_proc == NULL)) {
+		continue;
+	    }
+	    plugin_context = NULL;
+	    for (j = 0;
+		 ftable->pa_type_list != NULL &&
+		 ftable->pa_type_list[j] > 0;
+		 j++) {
+		/* Try to initialize the plugin.  If it fails, we'll remove it
+		 * from the list of modules we'll be using. */
+		if (j == 0) {
+		    server_init_proc = ftable->init_proc;
+		    if (server_init_proc != NULL) {
+			krb5_error_code initerr;
+			initerr = (*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names);
+			if (initerr) {
+			    const char *emsg;
+			    emsg = krb5_get_error_message(context, initerr);
+			    if (emsg) {
+				krb5_klog_syslog(LOG_ERR,
+					"preauth %s failed to initialize: %s",
+					ftable->name, emsg);
+				krb5_free_error_message(context, emsg);
+			    }
+			    memset(&preauth_systems[k], 0, sizeof(preauth_systems[k]));
+
+			    break;	/* skip all modules in this plugin */
+			}
+		    }
+		}
+		preauth_systems[k].name = ftable->name;
+		preauth_systems[k].type = ftable->pa_type_list[j];
+		if (ftable->flags_proc != NULL)
+		    preauth_systems[k].flags = ftable->flags_proc(context, preauth_systems[k].type);
+		else
+		    preauth_systems[k].flags = 0;
+		preauth_systems[k].plugin_context = plugin_context;
+		preauth_systems[k].init = server_init_proc;
+		/* Only call fini once for each plugin */
+		if (j == 0)
+		    preauth_systems[k].fini = ftable->fini_proc;
+		else
+		    preauth_systems[k].fini = NULL;
+		preauth_systems[k].get_edata = ftable->edata_proc;
+		preauth_systems[k].verify_padata = ftable->verify_proc;
+		preauth_systems[k].return_padata = ftable->return_proc;
+		preauth_systems[k].free_pa_reqctx =
+		    ftable->freepa_reqcontext_proc;
+		k++;
+	    }
+	}
+	krb5int_free_plugin_dir_data(preauth_plugins_ftables);
+    }
+    free(kdc_realm_names);
+    n_preauth_systems = k;
+    /* Add the end-of-list marker. */
+    preauth_systems[k].name = "[end]";
+    preauth_systems[k].type = -1;
+    return 0;
+}
+
+krb5_error_code
+unload_preauth_plugins(krb5_context context)
+{
+    int i;
+    if (preauth_systems != NULL) {
+	for (i = 0; i < n_preauth_systems; i++) {
+	    if (preauth_systems[i].fini != NULL) {
+	        (*preauth_systems[i].fini)(context,
+					   preauth_systems[i].plugin_context);
+	    }
+	    memset(&preauth_systems[i], 0, sizeof(preauth_systems[i]));
+	}
+	free(preauth_systems);
+	preauth_systems = NULL;
+	n_preauth_systems = 0;
+	krb5int_close_plugin_dirs(&preauth_plugins);
+    }
+    return 0;
+}
+
+/*
+ * The make_padata_context() function creates a space for storing any context
+ * information which will be needed by return_padata() later.  Each preauth
+ * type gets a context storage location of its own.
+ */
+struct request_pa_context {
+    int n_contexts;
+    struct {
+	krb5_preauth_systems *pa_system;
+	void *pa_context;
+    } *contexts;
+};
+
+static krb5_error_code
+make_padata_context(krb5_context context, void **padata_context)
+{
+    int i;
+    struct request_pa_context *ret;
+
+    ret = malloc(sizeof(*ret));
+    if (ret == NULL) {
+	return ENOMEM;
+    }
+
+    ret->n_contexts = n_preauth_systems;
+    ret->contexts = malloc(sizeof(ret->contexts[0]) * ret->n_contexts);
+    if (ret->contexts == NULL) {
+	free(ret);
+	return ENOMEM;
+    }
+
+    memset(ret->contexts, 0, sizeof(ret->contexts[0]) * ret->n_contexts);
+
+    for (i = 0; i < ret->n_contexts; i++) {
+	ret->contexts[i].pa_system = &preauth_systems[i];
+	ret->contexts[i].pa_context = NULL;
+    }
+
+    *padata_context = ret;
+
+    return 0;
+}
+
+/*
+ * The free_padata_context function frees any context information pointers
+ * which the check_padata() function created but which weren't already cleaned
+ * up by return_padata().
+ */
+krb5_error_code
+free_padata_context(krb5_context kcontext, void **padata_context)
+{
+    struct request_pa_context *context;
+    krb5_preauth_systems *preauth_system;
+    void **pctx, *mctx;
+    int i;
+
+    if (padata_context == NULL)
+	return 0;
+
+    context = *padata_context;
+
+    for (i = 0; i < context->n_contexts; i++) {
+	if (context->contexts[i].pa_context != NULL) {
+	    preauth_system = context->contexts[i].pa_system;
+	    mctx = preauth_system->plugin_context;
+	    if (preauth_system->free_pa_reqctx != NULL) {
+		pctx = &context->contexts[i].pa_context;
+		(*preauth_system->free_pa_reqctx)(kcontext, mctx, pctx);
+	    }
+	    context->contexts[i].pa_context = NULL;
+	}
+    }
+
+    free(context->contexts);
+    free(context);
+
+    return 0;
+}
+
+/* Retrieve a specified tl_data item from the given entry, and return its
+ * contents in a new krb5_data, which must be freed by the caller. */
+static krb5_error_code
+get_entry_tl_data(krb5_context context, krb5_db_entry *entry,
+		  krb5_int16 tl_data_type, krb5_data **result)
+{
+    krb5_tl_data *tl;
+    for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) {
+	if (tl->tl_data_type == tl_data_type) {
+	    *result = malloc(sizeof(krb5_data));
+	    if (*result == NULL) {
+		return ENOMEM;
+	    }
+	    (*result)->magic = KV5M_DATA;
+	    (*result)->data = malloc(tl->tl_data_length);
+	    if ((*result)->data == NULL) {
+		free(*result);
+		*result = NULL;
+		return ENOMEM;
+	    }
+	    memcpy((*result)->data, tl->tl_data_contents, tl->tl_data_length);
+	    return 0;
+	}
+    }
+    return ENOENT;
+}
+
+/*
+ * Retrieve a specific piece of information pertaining to the entry or the
+ * request and return it in a new krb5_data item which the caller must free.
+ *
+ * This may require massaging data into a contrived format, but it will
+ * hopefully keep us from having to reveal library-internal functions to
+ * modules.
+ */
+static krb5_error_code
+get_entry_data(krb5_context context,
+	       krb5_kdc_req *request, krb5_db_entry *entry,
+	       krb5_int32  type,
+	       krb5_data **result)
+{
+    int i, k;
+    krb5_data *ret;
+    krb5_deltat *delta;
+    krb5_keyblock *keys;
+    krb5_key_data *entry_key;
+
+    switch (type) {
+    case krb5plugin_preauth_entry_request_certificate:
+	return get_entry_tl_data(context, entry,
+				 KRB5_TL_USER_CERTIFICATE, result);
+	break;
+    case krb5plugin_preauth_entry_max_time_skew:
+	ret = malloc(sizeof(krb5_data));
+	if (ret == NULL)
+	    return ENOMEM;
+	delta = malloc(sizeof(krb5_deltat));
+	if (delta == NULL) {
+	    free(ret);
+	    return ENOMEM;
+	}
+	*delta = context->clockskew;
+	ret->data = (char *) delta;
+	ret->length = sizeof(*delta);
+	*result = ret;
+	return 0;
+	break;
+    case krb5plugin_preauth_keys:
+	ret = malloc(sizeof(krb5_data));
+	if (ret == NULL)
+	    return ENOMEM;
+	keys = malloc(sizeof(krb5_keyblock) * (request->nktypes + 1));
+	if (keys == NULL) {
+	    free(ret);
+	    return ENOMEM;
+	}
+	ret->data = (char *) keys;
+	ret->length = sizeof(krb5_keyblock) * (request->nktypes + 1);
+	memset(ret->data, 0, ret->length);
+	k = 0;
+	for (i = 0; i < request->nktypes; i++) {
+	    entry_key = NULL;
+	    if (krb5_dbe_find_enctype(context, entry, request->ktype[i],
+				      -1, 0, &entry_key) != 0)
+		continue;
+	    if (krb5_dbekd_decrypt_key_data(context, &master_keyblock,
+					    entry_key, &keys[k], NULL) != 0) {
+		if (keys[k].contents != NULL)
+		    krb5_free_keyblock_contents(context, &keys[k]);
+		memset(&keys[k], 0, sizeof(keys[k]));
+		continue;
+	    }
+	    k++;
+	}
+	if (k > 0) {
+	    *result = ret;
+	    return 0;
+	} else {
+	    free(keys);
+	    free(ret);
+	}
+	break;
+    case krb5plugin_preauth_request_body:
+	ret = NULL;
+	encode_krb5_kdc_req_body(request, &ret);
+	if (ret != NULL) {
+	    *result = ret;
+	    return 0;
+	}
+	return ASN1_PARSE_ERROR;
+	break;
+    default:
+	break;
+    }
+    return ENOENT;
+}
+
+static krb5_error_code
+find_pa_system(int type, krb5_preauth_systems **preauth)
+{
+    krb5_preauth_systems *ap;
+
+    ap = preauth_systems ? preauth_systems : static_preauth_systems;
+    while ((ap->type != -1) && (ap->type != type))
+	ap++;
+    if (ap->type == -1)
+	return(KRB5_PREAUTH_BAD_TYPE);
+    *preauth = ap;
+    return 0;
+} 
+
+static krb5_error_code
+find_pa_context(krb5_preauth_systems *pa_sys,
+		struct request_pa_context *context,
+		void ***pa_context)
+{
+    int i;
+
+    *pa_context = 0;
+
+    if (context == NULL)
+	return KRB5KRB_ERR_GENERIC;
+
+    for (i = 0; i < context->n_contexts; i++) {
+	if (context->contexts[i].pa_system == pa_sys) {
+	    *pa_context = &context->contexts[i].pa_context;
+	    return 0;
+	}
+    }
+
+    return KRB5KRB_ERR_GENERIC;
+}
+
+/*
+ * Create a list of indices into the preauth_systems array, sorted by order of
+ * preference.
+ */
+static krb5_boolean
+pa_list_includes(krb5_pa_data **pa_data, krb5_preauthtype pa_type)
+{
+    while (*pa_data != NULL) {
+	if ((*pa_data)->pa_type == pa_type)
+	    return TRUE;
+	pa_data++;
+    }
+    return FALSE;
+}
+static void
+sort_pa_order(krb5_context context, krb5_kdc_req *request, int *pa_order)
+{
+    int i, j, k, n_repliers, n_key_replacers;
+
+    /* First, set up the default order. */
+    i = 0;
+    for (j = 0; j < n_preauth_systems; j++) {
+        if (preauth_systems[j].return_padata != NULL)
+	    pa_order[i++] = j;
+    }
+    n_repliers = i;
+    pa_order[n_repliers] = -1;
+
+    /* Reorder so that PA_REPLACES_KEY modules are listed first. */
+    for (i = 0; i < n_repliers; i++) {
+	/* If this module replaces the key, then it's okay to leave it where it
+	 * is in the order. */
+	if (preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY)
+	    continue;
+	/* If not, search for a module which does, and swap in the first one we
+	 * find. */
+        for (j = i + 1; j < n_repliers; j++) {
+	    if (preauth_systems[pa_order[j]].flags & PA_REPLACES_KEY) {
+                k = pa_order[j];
+		pa_order[j] = pa_order[i];
+		pa_order[i] = k;
+		break;
+	    }
+        }
+    }
+
+    if (request->padata != NULL) {
+	/* Now reorder the subset of modules which replace the key,
+	 * bubbling those which handle pa_data types provided by the
+	 * client ahead of the others. */
+	for (i = 0; preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY; i++) {
+	    continue;
+	}
+	n_key_replacers = i;
+	for (i = 0; i < n_key_replacers; i++) {
+	    if (pa_list_includes(request->padata,
+				preauth_systems[pa_order[i]].type))
+		continue;
+	    for (j = i + 1; j < n_key_replacers; j++) {
+		if (pa_list_includes(request->padata,
+				    preauth_systems[pa_order[j]].type)) {
+		    k = pa_order[j];
+		    pa_order[j] = pa_order[i];
+		    pa_order[i] = k;
+		    break;
+		}
+	    }
+	}
+    }
+#ifdef DEBUG
+    krb5_klog_syslog(LOG_DEBUG, "original preauth mechanism list:");
+    for (i = 0; i < n_preauth_systems; i++) {
+	if (preauth_systems[i].return_padata != NULL)
+            krb5_klog_syslog(LOG_DEBUG, "... %s(%d)", preauth_systems[i].name,
+			     preauth_systems[i].type);
+    }
+    krb5_klog_syslog(LOG_DEBUG, "sorted preauth mechanism list:");
+    for (i = 0; pa_order[i] != -1; i++) {
+        krb5_klog_syslog(LOG_DEBUG, "... %s(%d)",
+			 preauth_systems[pa_order[i]].name,
+			 preauth_systems[pa_order[i]].type);
+    }
+#endif
+}
+
+const char *missing_required_preauth(krb5_db_entry *client,
+				     krb5_db_entry *server,
+				     krb5_enc_tkt_part *enc_tkt_reply)
+{
+#if 0
+    /*
+     * If this is the pwchange service, and the pre-auth bit is set,
+     * allow it even if the HW preauth would normally be required.
+     * 
+     * Sandia national labs wanted this for some strange reason... we
+     * leave it disabled normally.
+     */
+    if (isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE) &&
+	isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH))
+	return 0;
+#endif
+    
+#ifdef DEBUG
+    krb5_klog_syslog (LOG_DEBUG,
+		      "client needs %spreauth, %shw preauth; request has %spreauth, %shw preauth",
+		      isflagset (client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) ? "" : "no ",
+		      isflagset (client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) ? "" : "no ",
+		      isflagset (enc_tkt_reply->flags, TKT_FLG_PRE_AUTH) ? "" : "no ",
+		      isflagset (enc_tkt_reply->flags, TKT_FLG_HW_AUTH) ? "" : "no ");
+#endif
+
+    if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) &&
+	 !isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH))
+	return "NEEDED_PREAUTH";
+
+    if (isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) &&
+	!isflagset(enc_tkt_reply->flags, TKT_FLG_HW_AUTH))
+	return "NEEDED_HW_PREAUTH";
+
+    return 0;
+}
+
+void get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client,
+			   krb5_db_entry *server, krb5_data *e_data)
+{
+    int hw_only;
+    krb5_preauth_systems *ap;
+    krb5_pa_data **pa_data, **pa;
+    krb5_data *edat;
+    krb5_error_code retval;
+    
+    /* Zero these out in case we need to abort */
+    e_data->length = 0;
+    e_data->data = 0;
+    
+    hw_only = isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH);
+    pa_data = malloc(sizeof(krb5_pa_data *) * (n_preauth_systems+1));
+    if (pa_data == 0)
+	return;
+    memset(pa_data, 0, sizeof(krb5_pa_data *) * (n_preauth_systems+1));
+    pa = pa_data;
+
+    for (ap = preauth_systems; ap->type != -1; ap++) {
+	if (hw_only && !(ap->flags & PA_HARDWARE))
+	    continue;
+	if (ap->flags & PA_PSEUDO)
+	    continue;
+	*pa = malloc(sizeof(krb5_pa_data));
+	if (*pa == 0)
+	    goto errout;
+	memset(*pa, 0, sizeof(krb5_pa_data));
+	(*pa)->magic = KV5M_PA_DATA;
+	(*pa)->pa_type = ap->type;
+	if (ap->get_edata) {
+	  retval = (ap->get_edata)(kdc_context, request, client, server,
+				   get_entry_data, ap->plugin_context, *pa);
+	  if (retval) {
+	    /* just failed on this type, continue */
+	    free(*pa);
+	    *pa = 0;
+	    continue;
+	  }
+	}
+	pa++;
+    }
+    if (pa_data[0] == 0) {
+	krb5_klog_syslog (LOG_INFO,
+			  "%spreauth required but hint list is empty",
+			  hw_only ? "hw" : "");
+    }
+    retval = encode_krb5_padata_sequence((const krb5_pa_data **) pa_data,
+					 &edat);
+    if (retval)
+	goto errout;
+    *e_data = *edat;
+    free(edat);
+
+errout:
+    krb5_free_pa_data(kdc_context, pa_data);
+    return;
+}
+
+/*
+ * Add authorization data returned from preauth modules to the ticket
+ * It is assumed that ad is a "null-terminated" array of krb5_authdata ptrs
+ */
+static krb5_error_code
+add_authorization_data(krb5_enc_tkt_part *enc_tkt_part, krb5_authdata **ad)
+{
+    krb5_authdata **newad;
+    int oldones, newones;
+    int i;
+
+    if (enc_tkt_part == NULL || ad == NULL)
+	return EINVAL;
+
+    for (newones = 0; ad[newones] != NULL; newones++);
+    if (newones == 0)
+	return 0;   /* nothing to add */
+
+    if (enc_tkt_part->authorization_data == NULL)
+	oldones = 0;
+    else
+	for (oldones = 0;
+	     enc_tkt_part->authorization_data[oldones] != NULL; oldones++);
+
+    newad = malloc((oldones + newones + 1) * sizeof(krb5_authdata *));
+    if (newad == NULL)
+	return ENOMEM;
+
+    /* Copy any existing pointers */
+    for (i = 0; i < oldones; i++)
+	newad[i] = enc_tkt_part->authorization_data[i];
+
+    /* Add the new ones */
+    for (i = 0; i < newones; i++)
+	newad[oldones+i] = ad[i];
+
+    /* Terminate the new list */
+    newad[oldones+i] = NULL;
+
+    /* Free any existing list */
+    if (enc_tkt_part->authorization_data != NULL)
+	free(enc_tkt_part->authorization_data);
+
+    /* Install our new list */
+    enc_tkt_part->authorization_data = newad;
+
+    return 0;
+}
+
+/*
+ * This routine is called to verify the preauthentication information
+ * for a V5 request.
+ *
+ * Returns 0 if the pre-authentication is valid, non-zero to indicate
+ * an error code of some sort.
+ */
+
+krb5_error_code
+check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
+	      krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
+	      void **padata_context, krb5_data *e_data)
+{
+    krb5_error_code retval = 0;
+    krb5_pa_data **padata;
+    krb5_preauth_systems *pa_sys;
+    void **pa_context;
+    krb5_data *pa_e_data = NULL, *tmp_e_data = NULL;
+    int	pa_ok = 0, pa_found = 0;
+    krb5_error_code saved_retval = 0;
+    int use_saved_retval = 0;
+    const char *emsg;
+    krb5_authdata **tmp_authz_data = NULL;
+
+    if (request->padata == 0)
+	return 0;
+
+    if (make_padata_context(context, padata_context) != 0) {
+	return KRB5KRB_ERR_GENERIC;
+    }
+
+#ifdef DEBUG
+    krb5_klog_syslog (LOG_DEBUG, "checking padata");
+#endif
+    for (padata = request->padata; *padata; padata++) {
+#ifdef DEBUG
+	krb5_klog_syslog (LOG_DEBUG, ".. pa_type 0x%x", (*padata)->pa_type);
+#endif
+	if (find_pa_system((*padata)->pa_type, &pa_sys))
+	    continue;
+	if (find_pa_context(pa_sys, *padata_context, &pa_context))
+	    continue;
+#ifdef DEBUG
+	krb5_klog_syslog (LOG_DEBUG, ".. pa_type %s", pa_sys->name);
+#endif
+	if (pa_sys->verify_padata == 0)
+	    continue;
+	pa_found++;
+	retval = pa_sys->verify_padata(context, client, req_pkt, request,
+				       enc_tkt_reply, *padata,
+				       get_entry_data, pa_sys->plugin_context,
+				       pa_context, &tmp_e_data, &tmp_authz_data);
+	if (retval) {
+	    emsg = krb5_get_error_message (context, retval);
+	    krb5_klog_syslog (LOG_INFO, "preauth (%s) verify failure: %s",
+			      pa_sys->name, emsg);
+	    krb5_free_error_message (context, emsg);
+	    /* Ignore authorization data returned from modules that fail */
+	    if (tmp_authz_data != NULL) {
+		krb5_free_authdata(context, tmp_authz_data);
+		tmp_authz_data = NULL;
+	    }
+	    if (pa_sys->flags & PA_REQUIRED) {
+		/* free up any previous edata we might have been saving */
+		if (pa_e_data != NULL)
+		    krb5_free_data(context, pa_e_data);
+		pa_e_data = tmp_e_data;
+		tmp_e_data = NULL;
+		use_saved_retval = 0; /* Make sure we use the current retval */
+		pa_ok = 0;
+		break;
+	    }
+	    /*
+	     * We'll return edata from either the first PA_REQUIRED module
+	     * that fails, or the first non-PA_REQUIRED module that fails.
+	     * Hang on to edata from the first non-PA_REQUIRED module.
+	     * If we've already got one saved, simply discard this one.
+	     */
+	    if (tmp_e_data != NULL) {
+		if (pa_e_data == NULL) {
+		    /* save the first error code and e-data */
+		    pa_e_data = tmp_e_data;
+		    tmp_e_data = NULL;
+		    saved_retval = retval;
+		    use_saved_retval = 1;
+		} else {
+		    /* discard this extra e-data from non-PA_REQUIRED module */
+		    krb5_free_data(context, tmp_e_data);
+		    tmp_e_data = NULL;
+		}
+	    }
+	} else {
+#ifdef DEBUG
+	    krb5_klog_syslog (LOG_DEBUG, ".. .. ok");
+#endif
+	    /* Ignore any edata returned on success */
+	    if (tmp_e_data != NULL) {
+	        krb5_free_data(context, tmp_e_data);
+		tmp_e_data = NULL;
+	    }
+	    /* Add any authorization data to the ticket */
+	    if (tmp_authz_data != NULL) {
+		add_authorization_data(enc_tkt_reply, tmp_authz_data);
+		free(tmp_authz_data);
+		tmp_authz_data = NULL;
+	    }
+	    pa_ok = 1;
+	    if (pa_sys->flags & PA_SUFFICIENT)
+		break;
+	}
+    }
+
+    /* Don't bother copying and returning e-data on success */
+    if (pa_ok && pa_e_data != NULL) {
+	krb5_free_data(context, pa_e_data);
+	pa_e_data = NULL;
+    }
+    /* Return any e-data from the preauth that caused us to exit the loop */
+    if (pa_e_data != NULL) {
+	e_data->data = malloc(pa_e_data->length);
+	if (e_data->data == NULL) {
+	    krb5_free_data(context, pa_e_data);
+	    return KRB5KRB_ERR_GENERIC;
+	}
+	memcpy(e_data->data, pa_e_data->data, pa_e_data->length);
+	e_data->length = pa_e_data->length;
+	krb5_free_data(context, pa_e_data);
+	pa_e_data = NULL;
+	if (use_saved_retval != 0)
+	    retval = saved_retval;
+    }
+
+    if (pa_ok)
+	return 0;
+
+    /* pa system was not found, but principal doesn't require preauth */
+    if (!pa_found &&
+	!isflagset(client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) &&
+	!isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH))
+       return 0;
+
+    if (!pa_found) {
+	emsg = krb5_get_error_message(context, retval);
+	krb5_klog_syslog (LOG_INFO, "no valid preauth type found: %s", emsg);
+	krb5_free_error_message(context, emsg);
+    }
+    /* The following switch statement allows us
+     * to return some preauth system errors back to the client.
+     */
+    switch(retval) {
+    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+    case KRB5KRB_AP_ERR_SKEW:
+    case KRB5KDC_ERR_ETYPE_NOSUPP:
+    /* rfc 4556 */
+    case KRB5KDC_ERR_CLIENT_NOT_TRUSTED:
+    case KRB5KDC_ERR_INVALID_SIG:
+    case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED:
+    case KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE:
+    case KRB5KDC_ERR_INVALID_CERTIFICATE:
+    case KRB5KDC_ERR_REVOKED_CERTIFICATE:
+    case KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN:
+    case KRB5KDC_ERR_CLIENT_NAME_MISMATCH:
+    case KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE:
+    case KRB5KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED:
+    case KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED:
+    case KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED:
+    case KRB5KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED:
+    /* earlier drafts of what became rfc 4556 */
+    case KRB5KDC_ERR_CERTIFICATE_MISMATCH:
+    case KRB5KDC_ERR_KDC_NOT_TRUSTED:
+    case KRB5KDC_ERR_REVOCATION_STATUS_UNAVAILABLE:
+    /* This value is shared with KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */
+    /* case KRB5KDC_ERR_KEY_TOO_WEAK: */
+	return retval;
+    default:
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+}
+
+/*
+ * return_padata creates any necessary preauthentication
+ * structures which should be returned by the KDC to the client
+ */
+krb5_error_code
+return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
+	      krb5_kdc_req *request, krb5_kdc_rep *reply,
+	      krb5_key_data *client_key, krb5_keyblock *encrypting_key,
+	      void **padata_context)
+{
+    krb5_error_code		retval;
+    krb5_pa_data **		padata;
+    krb5_pa_data **		send_pa_list;
+    krb5_pa_data **		send_pa;
+    krb5_pa_data *		pa = 0;
+    krb5_preauth_systems *	ap;
+    int *			pa_order;
+    int *			pa_type;
+    int 			size = 0;
+    void **			pa_context;
+    krb5_boolean		key_modified;
+    krb5_keyblock		original_key;
+    if ((!*padata_context)&& (make_padata_context(context, padata_context) != 0)) {
+	return KRB5KRB_ERR_GENERIC;
+    }
+
+    for (ap = preauth_systems; ap->type != -1; ap++) {
+	if (ap->return_padata)
+	    size++;
+    }
+
+    if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
+	return ENOMEM;
+    if ((pa_order = malloc((size+1) * sizeof(int))) == NULL) {
+	free(send_pa_list);
+	return ENOMEM;
+    }
+    sort_pa_order(context, request, pa_order);
+
+    retval = krb5_copy_keyblock_contents(context, encrypting_key,
+					 &original_key);
+    if (retval) {
+	free(send_pa_list);
+	free(pa_order);
+	return retval;
+    }
+    key_modified = FALSE;
+
+    send_pa = send_pa_list;
+    *send_pa = 0;
+
+    for (pa_type = pa_order; *pa_type != -1; pa_type++) {
+	ap = &preauth_systems[*pa_type];
+        if (!key_modified)
+	    if (original_key.enctype != encrypting_key->enctype)
+                key_modified = TRUE;
+        if (!key_modified)
+	    if (original_key.length != encrypting_key->length)
+                key_modified = TRUE;
+        if (!key_modified)
+	    if (memcmp(original_key.contents, encrypting_key->contents,
+		       original_key.length) != 0)
+                key_modified = TRUE;
+	if (key_modified && (ap->flags & PA_REPLACES_KEY))
+	    continue;
+	if (ap->return_padata == 0)
+	    continue;
+	if (find_pa_context(ap, *padata_context, &pa_context))
+	    continue;
+	pa = 0;
+	if (request->padata) {
+	    for (padata = request->padata; *padata; padata++) {
+		if ((*padata)->pa_type == ap->type) {
+		    pa = *padata;
+		    break;
+		}
+	    }
+	}
+	if ((retval = ap->return_padata(context, pa, client, req_pkt, request, reply,
+					client_key, encrypting_key, send_pa,
+					get_entry_data, ap->plugin_context,
+					pa_context))) {
+	    goto cleanup;
+	}
+
+	if (*send_pa)
+	    send_pa++;
+	*send_pa = 0;
+    }
+    
+    retval = 0;
+
+    if (send_pa_list[0]) {
+	reply->padata = send_pa_list;
+	send_pa_list = 0;
+    }
+    
+cleanup:
+    krb5_free_keyblock_contents(context, &original_key);
+    free(pa_order);
+    if (send_pa_list)
+	krb5_free_pa_data(context, send_pa_list);
+    return (retval);
+}
+
+static krb5_boolean
+enctype_requires_etype_info_2(krb5_enctype enctype)
+{
+    switch(enctype) {
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES3_CBC_SHA1:
+    case ENCTYPE_DES3_CBC_RAW:
+    case ENCTYPE_ARCFOUR_HMAC:
+    case ENCTYPE_ARCFOUR_HMAC_EXP :
+	return 0;
+    default:
+	if (krb5_c_valid_enctype(enctype))
+	    return 1;
+	else return 0;
+    }
+}
+
+static krb5_boolean
+request_contains_enctype (krb5_context context,  const krb5_kdc_req *request,
+			  krb5_enctype enctype)
+{
+    int i;
+    for (i =0; i < request->nktypes; i++)
+	if (request->ktype[i] == enctype)
+	    return 1;
+    return 0;
+}
+
+
+static krb5_error_code
+verify_enc_timestamp(krb5_context context, krb5_db_entry *client,
+		     krb5_data *req_pkt,
+		     krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
+		     krb5_pa_data *pa,
+		     preauth_get_entry_data_proc ets_get_entry_data,
+		     void *pa_system_context,
+		     void **pa_request_context,
+		     krb5_data **e_data,
+		     krb5_authdata ***authz_data)
+{
+    krb5_pa_enc_ts *		pa_enc = 0;
+    krb5_error_code		retval;
+    krb5_data			scratch;
+    krb5_data			enc_ts_data;
+    krb5_enc_data 		*enc_data = 0;
+    krb5_keyblock		key;
+    krb5_key_data *		client_key;
+    krb5_int32			start;
+    krb5_timestamp		timenow;
+    krb5_error_code		decrypt_err = 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;
+    decrypt_err = 0;
+    while (1) {
+	if ((retval = krb5_dbe_search_enctype(context, client,
+					      &start, enc_data->enctype,
+					      -1, 0, &client_key)))
+	    goto cleanup;
+
+	if ((retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock, 
+						  client_key, &key, NULL)))
+	    goto cleanup;
+
+	key.enctype = enc_data->enctype;
+
+	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;
+	else
+	    decrypt_err = retval;
+    }
+
+    if ((retval = decode_krb5_pa_enc_ts(&enc_ts_data, &pa_enc)) != 0)
+	goto cleanup;
+
+    if ((retval = krb5_timeofday(context, &timenow)) != 0)
+	goto cleanup;
+    
+    if (labs(timenow - pa_enc->patimestamp) > context->clockskew) {
+	retval = KRB5KRB_AP_ERR_SKEW;
+	goto cleanup;
+    }
+
+    setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH);
+
+    retval = 0;
+    
+cleanup:
+    if (enc_data) {
+	krb5_free_data_contents(context, &enc_data->ciphertext);
+	free(enc_data);
+    }
+    krb5_free_data_contents(context, &enc_ts_data);
+    if (pa_enc)
+	free(pa_enc);
+    /*
+     * If we get NO_MATCHING_KEY and decryption previously failed, and
+     * we failed to find any other keys of the correct enctype after
+     * that failed decryption, it probably means that the password was
+     * incorrect.
+     */
+    if (retval == KRB5_KDB_NO_MATCHING_KEY && decrypt_err != 0)
+	retval = decrypt_err;
+    return retval;
+}
+
+static krb5_error_code
+_make_etype_info_entry(krb5_context context,
+		       krb5_kdc_req *request, krb5_key_data *client_key,
+		       krb5_enctype etype, krb5_etype_info_entry **entry,
+		       int etype_info2)
+{
+    krb5_data			salt;
+    krb5_etype_info_entry *	tmp_entry; 
+    krb5_error_code		retval;
+
+    if ((tmp_entry = malloc(sizeof(krb5_etype_info_entry))) == NULL)
+       return ENOMEM;
+
+    salt.data = 0;
+
+    tmp_entry->magic = KV5M_ETYPE_INFO_ENTRY;
+    tmp_entry->etype = etype;
+    tmp_entry->length = KRB5_ETYPE_NO_SALT;
+    tmp_entry->salt = 0;
+    tmp_entry->s2kparams.data = NULL;
+    tmp_entry->s2kparams.length = 0;
+    retval = get_salt_from_key(context, request->client,
+			       client_key, &salt);
+    if (retval)
+	goto fail;
+    if (etype_info2 && client_key->key_data_ver > 1 &&
+	client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_AFS3) {
+	switch (etype) {
+	case ENCTYPE_DES_CBC_CRC:
+	case ENCTYPE_DES_CBC_MD4:
+	case ENCTYPE_DES_CBC_MD5:
+	    tmp_entry->s2kparams.data = malloc(1);
+	    if (tmp_entry->s2kparams.data == NULL) {
+		retval = ENOMEM;
+		goto fail;
+	    }
+	    tmp_entry->s2kparams.length = 1;
+	    tmp_entry->s2kparams.data[0] = 1;
+	    break;
+	default:
+	    break;
+	}
+    }
+
+    if (salt.length >= 0) {
+	tmp_entry->length = salt.length;
+	tmp_entry->salt = (unsigned char *) salt.data;
+	salt.data = 0;
+    }
+    *entry = tmp_entry;
+    return 0;
+
+fail:
+    if (tmp_entry) {
+	if (tmp_entry->s2kparams.data)
+	    free(tmp_entry->s2kparams.data);
+	free(tmp_entry);
+    }
+    if (salt.data)
+	free(salt.data);
+    return retval;
+}
+/*
+ * This function returns the etype information for a particular
+ * client, to be passed back in the preauth list in the KRB_ERROR
+ * message.  It supports generating both etype_info  and etype_info2
+ *  as most of the work is the same.   
+ */
+static krb5_error_code
+etype_info_helper(krb5_context context, krb5_kdc_req *request,
+	       krb5_db_entry *client, krb5_db_entry *server,
+	       krb5_pa_data *pa_data, int etype_info2)
+{
+    krb5_etype_info_entry **	entry = 0;
+    krb5_key_data		*client_key;
+    krb5_error_code		retval;
+    krb5_data *			scratch;
+    krb5_enctype		db_etype;
+    int 			i = 0;
+    int 			start = 0;
+    int				seen_des = 0;
+
+    entry = malloc((client->n_key_data * 2 + 1) * sizeof(krb5_etype_info_entry *));
+    if (entry == NULL)
+	return ENOMEM;
+    entry[0] = NULL;
+
+    while (1) {
+	retval = krb5_dbe_search_enctype(context, client, &start, -1,
+					 -1, 0, &client_key);
+	if (retval == KRB5_KDB_NO_MATCHING_KEY)
+	    break;
+	if (retval)
+	    goto cleanup;
+	db_etype = client_key->key_data_type[0];
+	if (db_etype == ENCTYPE_DES_CBC_MD4)
+	    db_etype = ENCTYPE_DES_CBC_MD5;
+	
+	if (request_contains_enctype(context, request, db_etype)) {
+	    assert(etype_info2 ||
+		   !enctype_requires_etype_info_2(db_etype));
+	    if ((retval = _make_etype_info_entry(context, request, client_key,
+			    db_etype, &entry[i], etype_info2)) != 0) {
+		goto cleanup;
+	    }
+	    entry[i+1] = 0;
+	    i++;
+	}
+
+	/* 
+	 * If there is a des key in the kdb, try the "similar" enctypes,
+	 * avoid duplicate entries. 
+	 */
+	if (!seen_des) {
+	    switch (db_etype) {
+	    case ENCTYPE_DES_CBC_MD5:
+		db_etype = ENCTYPE_DES_CBC_CRC;
+		break;
+	    case ENCTYPE_DES_CBC_CRC:
+		db_etype = ENCTYPE_DES_CBC_MD5;
+		break;
+	    default:
+		continue;
+
+	    }
+	    if (request_contains_enctype(context, request, db_etype)) {
+		if ((retval = _make_etype_info_entry(context, request,
+				client_key, db_etype, &entry[i], etype_info2)) != 0) {
+		    goto cleanup;
+		}
+		entry[i+1] = 0;
+		i++;
+	    }
+	    seen_des++;
+	}
+    }
+    if (etype_info2)
+	retval = encode_krb5_etype_info2((const krb5_etype_info_entry **) entry,
+				    &scratch);
+    else 	retval = encode_krb5_etype_info((const krb5_etype_info_entry **) entry,
+				    &scratch);
+    if (retval)
+	goto cleanup;
+    pa_data->contents = (unsigned char *)scratch->data;
+    pa_data->length = scratch->length;
+    free(scratch);
+
+    retval = 0;
+
+cleanup:
+    if (entry)
+	krb5_free_etype_info(context, entry);
+    return retval;
+}
+
+static krb5_error_code
+get_etype_info(krb5_context context, krb5_kdc_req *request,
+	       krb5_db_entry *client, krb5_db_entry *server,
+	       preauth_get_entry_data_proc etype_get_entry_data,
+	       void *pa_system_context,
+	       krb5_pa_data *pa_data)
+{
+  int i;
+    for (i=0;  i < request->nktypes; i++) {
+	if (enctype_requires_etype_info_2(request->ktype[i])) 
+	    return KRB5KDC_ERR_PADATA_TYPE_NOSUPP ;;;; /*Caller will
+							* skip this
+							* type*/
+    }
+    return etype_info_helper(context, request, client, server, pa_data, 0);
+}
+
+static krb5_error_code
+get_etype_info2(krb5_context context, krb5_kdc_req *request,
+	       krb5_db_entry *client, krb5_db_entry *server,
+	       preauth_get_entry_data_proc etype_get_entry_data,
+	       void *pa_system_context,
+	       krb5_pa_data *pa_data)
+{
+    return etype_info_helper( context, request, client, server, pa_data, 1);
+}
+
+static krb5_error_code
+etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, 
+			 krb5_db_entry *client,
+			 krb5_kdc_req *request, krb5_kdc_rep *reply,
+			 krb5_key_data *client_key,
+			 krb5_keyblock *encrypting_key,
+			 krb5_pa_data **send_pa,
+			 int etype_info2)
+{
+    int i;
+    krb5_error_code retval;
+    krb5_pa_data *tmp_padata;
+    krb5_etype_info_entry **entry = NULL;
+    krb5_data *scratch = NULL;
+
+    /*
+     * Skip PA-ETYPE-INFO completely if AS-REQ lists any "newer"
+     * enctypes.
+     */
+    if (!etype_info2) {
+	for (i = 0; i < request->nktypes; i++) {
+	    if (enctype_requires_etype_info_2(request->ktype[i])) {
+		*send_pa = NULL;
+		return 0;
+	    }
+	}
+    }
+
+    tmp_padata = malloc( sizeof(krb5_pa_data));
+    if (tmp_padata == NULL)
+	return ENOMEM;
+    if (etype_info2)
+	tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO2;
+    else
+	tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO;
+
+    entry = malloc(2 * sizeof(krb5_etype_info_entry *));
+    if (entry == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    entry[0] = NULL;
+    entry[1] = NULL;
+    retval = _make_etype_info_entry(context, request,
+				    client_key, encrypting_key->enctype,
+				    entry, etype_info2);
+    if (retval)
+	goto cleanup;
+
+    if (etype_info2)
+	retval = encode_krb5_etype_info2((const krb5_etype_info_entry **) entry, &scratch);
+    else
+	retval = encode_krb5_etype_info((const krb5_etype_info_entry **) entry, &scratch);
+
+    if (retval)
+	goto cleanup;
+    tmp_padata->contents = scratch->data;
+    tmp_padata->length = scratch->length;
+    *send_pa = tmp_padata;
+
+    /* For cleanup - we no longer own the contents of the krb5_data 
+     * only to pointer to the krb5_data
+     */
+    scratch->data = 0;
+
+ cleanup:
+    if (entry)
+	krb5_free_etype_info(context, entry);
+    if (retval) {
+	if (tmp_padata)
+	    free(tmp_padata);
+    }
+    if (scratch)
+	    krb5_free_data(context, scratch);
+    return retval;
+}
+
+static krb5_error_code
+return_etype_info2(krb5_context context, krb5_pa_data * padata, 
+		   krb5_db_entry *client,
+		   krb5_data *req_pkt,
+		   krb5_kdc_req *request, krb5_kdc_rep *reply,
+		   krb5_key_data *client_key,
+		   krb5_keyblock *encrypting_key,
+		   krb5_pa_data **send_pa,
+		   preauth_get_entry_data_proc etype_get_entry_data,
+	           void *pa_system_context,
+		   void **pa_request_context)
+{
+    return etype_info_as_rep_helper(context, padata, client, request, reply,
+				    client_key, encrypting_key, send_pa, 1);
+}
+
+
+static krb5_error_code
+return_etype_info(krb5_context context, krb5_pa_data * padata, 
+		  krb5_db_entry *client,
+		  krb5_data *req_pkt,
+		  krb5_kdc_req *request, krb5_kdc_rep *reply,
+		  krb5_key_data *client_key,
+		  krb5_keyblock *encrypting_key,
+		  krb5_pa_data **send_pa,
+		  preauth_get_entry_data_proc etypeget_entry_data,
+	          void *pa_system_context,
+		  void **pa_request_context)
+{
+    return etype_info_as_rep_helper(context, padata, client, request, reply,
+				    client_key, encrypting_key, send_pa, 0);
+}
+
+static krb5_error_code
+return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
+	       krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request,
+	       krb5_kdc_rep *reply, krb5_key_data *client_key,
+	       krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
+	       preauth_get_entry_data_proc etype_get_entry_data,
+	       void *pa_system_context,
+	       void **pa_request_context)
+{
+    krb5_error_code	retval;
+    krb5_pa_data *	padata;
+    krb5_data *		scratch;
+    krb5_data		salt_data;
+    int i;
+    
+    for (i = 0; i < request->nktypes; i++) {
+	if (enctype_requires_etype_info_2(request->ktype[i]))
+	    return 0;
+    }
+    if (client_key->key_data_ver == 1 ||
+	client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)
+	return 0;
+
+    if ((padata = malloc(sizeof(krb5_pa_data))) == NULL)
+	return ENOMEM;
+    padata->magic = KV5M_PA_DATA;
+    padata->pa_type = KRB5_PADATA_PW_SALT;
+    
+    switch (client_key->key_data_type[1]) {
+    case KRB5_KDB_SALTTYPE_V4:
+	/* send an empty (V4) salt */
+	padata->contents = 0;
+	padata->length = 0;
+	break;
+    case KRB5_KDB_SALTTYPE_NOREALM:
+	if ((retval = krb5_principal2salt_norealm(kdc_context, 
+						   request->client,
+						   &salt_data)))
+	    goto cleanup;
+	padata->contents = (krb5_octet *)salt_data.data;
+	padata->length = salt_data.length;
+	break;
+    case KRB5_KDB_SALTTYPE_AFS3:
+	/* send an AFS style realm-based salt */
+	/* for now, just pass the realm back and let the client
+	   do the work. In the future, add a kdc configuration
+	   variable that specifies the old cell name. */
+	padata->pa_type = KRB5_PADATA_AFS3_SALT;
+	/* it would be just like ONLYREALM, but we need to pass the 0 */
+	scratch = krb5_princ_realm(kdc_context, request->client);
+	if ((padata->contents = malloc(scratch->length+1)) == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	memcpy(padata->contents, scratch->data, scratch->length);
+	padata->length = scratch->length+1;
+	padata->contents[scratch->length] = 0;
+	break;
+    case KRB5_KDB_SALTTYPE_ONLYREALM:
+	scratch = krb5_princ_realm(kdc_context, request->client);
+	if ((padata->contents = malloc(scratch->length)) == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	memcpy(padata->contents, scratch->data, scratch->length);
+	padata->length = scratch->length;
+	break;
+    case KRB5_KDB_SALTTYPE_SPECIAL:
+	if ((padata->contents = malloc(client_key->key_data_length[1]))
+	    == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	memcpy(padata->contents, client_key->key_data_contents[1],
+	       client_key->key_data_length[1]);
+	padata->length = client_key->key_data_length[1];
+	break;
+    default:
+	free(padata);
+	return 0;
+    }
+
+    *send_pa = padata;
+    return 0;
+    
+cleanup:
+    free(padata);
+    return retval;
+}
+
+static krb5_error_code
+return_sam_data(krb5_context context, krb5_pa_data *in_padata,
+		krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request,
+		krb5_kdc_rep *reply, krb5_key_data *client_key,
+		krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
+		preauth_get_entry_data_proc sam_get_entry_data,
+		void *pa_system_context,
+		void **pa_request_context)
+{
+    krb5_error_code	retval;
+    krb5_data		scratch;
+    int			i;
+
+    krb5_sam_response		*sr = 0;
+    krb5_predicted_sam_response	*psr = 0;
+
+    if (in_padata == 0)
+	return 0;
+
+    /*
+     * We start by doing the same thing verify_sam_response() does:
+     * extract the psr from the padata (which is an sr). Nothing
+     * here should generate errors! We've already successfully done
+     * all this once.
+     */
+
+    scratch.data = in_padata->contents;
+    scratch.length = in_padata->length;
+    
+    if ((retval = decode_krb5_sam_response(&scratch, &sr))) {
+	com_err("krb5kdc", retval,
+		"return_sam_data(): decode_krb5_sam_response failed");
+	goto cleanup;
+    }
+
+    {
+	krb5_enc_data tmpdata;
+
+	tmpdata.enctype = ENCTYPE_UNKNOWN;
+	tmpdata.ciphertext = sr->sam_track_id;
+
+	scratch.length = tmpdata.ciphertext.length;
+	if ((scratch.data = (char *) malloc(scratch.length)) == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+
+	if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0,
+				     &tmpdata, &scratch))) {
+	    com_err("krb5kdc", retval,
+		    "return_sam_data(): decrypt track_id failed");
+	    free(scratch.data);
+	    goto cleanup;
+	}
+    }
+
+    if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) {
+	com_err("krb5kdc", retval,
+		"return_sam_data(): decode_krb5_predicted_sam_response failed");
+	free(scratch.data);
+	goto cleanup;
+    }
+
+    /* We could use sr->sam_flags, but it may be absent or altered. */
+    if (psr->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) {
+	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+		"Unsupported SAM flag must-pk-encrypt-sad");
+	goto cleanup;
+    }
+    if (psr->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
+	/* No key munging */
+	goto cleanup;
+    }
+    if (psr->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) {
+	/* Use sam_key instead of client key */
+	krb5_free_keyblock_contents(context, encrypting_key);
+	krb5_copy_keyblock_contents(context, &psr->sam_key, encrypting_key);
+	/* XXX Attach a useful pa_data */
+	goto cleanup;
+    }
+
+    /* Otherwise (no flags set), we XOR the keys */
+    /* XXX The passwords-04 draft is underspecified here wrt different
+	   key types. We will do what I hope to get into the -05 draft. */
+    {
+	krb5_octet *p = encrypting_key->contents;
+	krb5_octet *q = psr->sam_key.contents;
+	int length = ((encrypting_key->length < psr->sam_key.length)
+		      ? encrypting_key->length
+		      : psr->sam_key.length);
+
+	for (i = 0; i < length; i++)
+	    p[i] ^= q[i];
+    }
+
+    /* Post-mixing key correction */
+    switch (encrypting_key->enctype) {
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES_CBC_RAW:
+	mit_des_fixup_key_parity(encrypting_key->contents);
+	if (mit_des_is_weak_key(encrypting_key->contents))
+	    ((krb5_octet *) encrypting_key->contents)[7] ^= 0xf0;
+	break;
+
+    /* XXX case ENCTYPE_DES3_CBC_MD5: listed in 1510bis-04 draft */
+    case ENCTYPE_DES3_CBC_SHA: /* XXX deprecated? */
+    case ENCTYPE_DES3_CBC_RAW:
+    case ENCTYPE_DES3_CBC_SHA1:
+	for (i = 0; i < 3; i++) {
+	    mit_des_fixup_key_parity(encrypting_key->contents + i * 8);
+	    if (mit_des_is_weak_key(encrypting_key->contents + i * 8))
+		((krb5_octet *) encrypting_key->contents)[7 + i * 8] ^= 0xf0;
+	}
+	break;
+
+    default:
+	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+		"Unimplemented keytype for SAM key mixing");
+	goto cleanup;
+    }
+
+    /* XXX Attach a useful pa_data */
+cleanup:
+    if (sr)
+	krb5_free_sam_response(context, sr);
+    if (psr)
+	krb5_free_predicted_sam_response(context, psr);
+
+    return retval;
+}
+    
+static struct {
+  char* name;
+  int   sam_type;
+} *sam_ptr, sam_inst_map[] = {
+  { "SNK4", PA_SAM_TYPE_DIGI_PATH, },
+  { "SECURID", PA_SAM_TYPE_SECURID, },
+  { "GRAIL", PA_SAM_TYPE_GRAIL, },
+  { 0, 0 },
+};
+
+static krb5_error_code
+get_sam_edata(krb5_context context, krb5_kdc_req *request,
+	      krb5_db_entry *client, krb5_db_entry *server,
+	      preauth_get_entry_data_proc sam_get_entry_data,
+	      void *pa_system_context, krb5_pa_data *pa_data)
+{
+    krb5_error_code		retval;
+    krb5_sam_challenge		sc;
+    krb5_predicted_sam_response	psr;
+    krb5_data *			scratch;
+    krb5_keyblock encrypting_key;
+    char response[9];
+    char inputblock[8];
+    krb5_data predict_response;
+
+    memset(&sc, 0, sizeof(sc));
+    memset(&psr, 0, sizeof(psr));
+
+    /* Given the client name we can figure out what type of preauth
+       they need. The spec is currently for querying the database for
+       names that match the types of preauth used. Later we should
+       make this mapping show up in kdc.conf. In the meantime, we
+       hardcode the following:
+		/SNK4 -- Digital Pathways SNK/4 preauth.
+		/GRAIL -- experimental preauth
+       The first one found is used. See sam_inst_map above.
+
+       For SNK4 in particular, the key in the database is the key for
+       the device; kadmin needs a special interface for it.
+     */
+
+    {
+      int npr = 1;
+      krb5_boolean more;
+      krb5_db_entry assoc;
+      krb5_key_data  *assoc_key;
+      krb5_principal newp;
+      int probeslot;
+
+      sc.sam_type = 0;
+
+      retval = krb5_copy_principal(kdc_context, request->client, &newp);
+      if (retval) {
+	com_err("krb5kdc", retval, "copying client name for preauth probe");
+	return retval;
+      }
+
+      probeslot = krb5_princ_size(context, newp)++;
+      krb5_princ_name(kdc_context, newp) = 
+	realloc(krb5_princ_name(kdc_context, newp),
+		krb5_princ_size(context, newp) * sizeof(krb5_data));
+
+      for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) {
+	krb5_princ_component(kdc_context,newp,probeslot)->data = sam_ptr->name;
+	krb5_princ_component(kdc_context,newp,probeslot)->length = 
+	  strlen(sam_ptr->name);
+	npr = 1;
+	retval = krb5_db_get_principal(kdc_context, newp, &assoc, &npr, &more);
+	if(!retval && npr) {
+	  sc.sam_type = sam_ptr->sam_type;
+	  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! */
+	{
+	  /* here's what do_tgs_req does */
+	  retval = krb5_dbe_find_enctype(kdc_context, &assoc,
+					 ENCTYPE_DES_CBC_RAW,
+					 KRB5_KDB_SALTTYPE_NORMAL,
+					 0,		/* Get highest kvno */
+					 &assoc_key);
+	  if (retval) {
+	    char *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_keyblock, 
+					       assoc_key, &encrypting_key,
+					       NULL);
+	  if (retval) {
+	    com_err("krb5kdc", retval, 
+		    "snk4 pulling out key entry");
+	    return retval;
+	  }
+	  /* now we can use encrypting_key... */
+	}
+      } else {
+	/* SAM is not an option - so don't return as hint */
+	return KRB5_PREAUTH_BAD_TYPE;
+      }
+    }
+    sc.magic = KV5M_SAM_CHALLENGE;
+    psr.sam_flags = sc.sam_flags = KRB5_SAM_USE_SAD_AS_KEY;
+
+    /* Replay prevention */
+    if ((retval = krb5_copy_principal(context, request->client, &psr.client)))
+	return retval;
+#ifdef USE_RCACHE
+    if ((retval = krb5_us_timeofday(context, &psr.stime, &psr.susec)))
+	return retval;
+#endif /* USE_RCACHE */
+
+    switch (sc.sam_type) {
+    case PA_SAM_TYPE_GRAIL:
+      sc.sam_type_name.data = "Experimental System";
+      sc.sam_type_name.length = strlen(sc.sam_type_name.data);
+      sc.sam_challenge_label.data = "experimental challenge label";
+      sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
+      sc.sam_challenge.data = "12345";
+      sc.sam_challenge.length = strlen(sc.sam_challenge.data);
+
+#if 0 /* Enable this to test "normal" (no flags set) mode.  */
+      psr.sam_flags = sc.sam_flags = 0;
+#endif
+
+      psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
+      /* string2key on sc.sam_challenge goes in here */
+      /* eblock is just to set the enctype */
+      {
+	const krb5_enctype type = ENCTYPE_DES_CBC_MD5;
+
+	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;
+	
+	{
+	    size_t enclen;
+	    krb5_enc_data tmpdata;
+
+	    if ((retval = krb5_c_encrypt_length(context,
+						psr_key.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, &psr_key,
+					 /* XXX */ 0, 0, scratch, &tmpdata)))
+		goto cleanup;
+
+	    sc.sam_track_id = tmpdata.ciphertext;
+	}
+      }
+
+      sc.sam_response_prompt.data = "response prompt";
+      sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data);
+      sc.sam_pk_for_sad.length = 0;
+      sc.sam_nonce = 0;
+      /* Generate checksum */
+      /*krb5_checksum_size(context, ctype)*/
+      /*krb5_calculate_checksum(context,ctype,in,in_length,seed,
+	seed_length,outcksum) */
+      /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed,
+	seed_length) */
+#if 0 /* XXX a) glue appears broken; b) this gives up the SAD */
+      sc.sam_cksum.contents = (krb5_octet *)
+	malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES));
+      if (sc.sam_cksum.contents == NULL) return(ENOMEM);
+
+      retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES,
+				       sc.sam_challenge.data,
+				       sc.sam_challenge.length,
+				       psr.sam_key.contents, /* key */
+				       psr.sam_key.length, /* key length */
+				       &sc.sam_cksum);
+      if (retval) { free(sc.sam_cksum.contents); return(retval); }
+#endif /* 0 */
+      
+      retval = encode_krb5_sam_challenge(&sc, &scratch);
+      if (retval) goto cleanup;
+      pa_data->magic = KV5M_PA_DATA;
+      pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE;
+      pa_data->contents = scratch->data;
+      pa_data->length = scratch->length;
+      
+      retval = 0;
+      break;
+    case PA_SAM_TYPE_DIGI_PATH:
+      sc.sam_type_name.data = "Digital Pathways";
+      sc.sam_type_name.length = strlen(sc.sam_type_name.data);
+#if 1
+      sc.sam_challenge_label.data = "Enter the following on your keypad";
+      sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
+#endif
+      /* generate digit string, take it mod 1000000 (six digits.) */
+      {
+	int j;
+	krb5_keyblock session_key;
+	char outputblock[8];
+	int i;
+
+	session_key.contents = 0;
+
+	memset(inputblock, 0, 8);
+
+	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");
+	  return retval;
+	}
+	/* 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) {
+	  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);
+	}
+	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;
+
+	encrypting_key.enctype = ENCTYPE_DES_CBC_RAW;
+
+	if (retval) {
+	  com_err("krb5kdc", retval, "snk4 processing key");
+	}
+
+	{
+	    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++) {
+	  char n[2];
+	  int k;
+	  n[0] = outputblock[j] & 0xf;
+	  n[1] = (outputblock[j]>>4) & 0xf;
+	  for (k=0; k<2; k++) {
+	    if(n[k] > 9) n[k] = ((n[k]-1)>>2);
+	    /* This is equivalent to:
+	       if(n[k]>=0xa && n[k]<=0xc) n[k] = 2;
+	       if(n[k]>=0xd && n[k]<=0xf) n[k] = 3;
+	       */
+	  }
+	  /* for v4, we keygen: *(j+(char*)&key1) = (n[1]<<4) | n[0]; */
+	  /* for v5, we just generate a string */
+	  response[2*j+0] = '0' + n[1];
+	  response[2*j+1] = '0' + n[0];
+	  /* and now, response has what we work with. */
+	}
+	response[8] = 0;
+	predict_response.data = response;
+	predict_response.length = 8;
+#if 0				/* for debugging, hack the output too! */
+sc.sam_challenge_label.data = response;
+sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
+#endif
+      }
+
+      psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
+      /* string2key on sc.sam_challenge goes in here */
+      /* eblock is just to set the enctype */
+      {
+	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;
+	
+	{
+	    size_t enclen;
+	    krb5_enc_data tmpdata;
+
+	    if ((retval = krb5_c_encrypt_length(context,
+						psr_key.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, &psr_key,
+					 /* XXX */ 0, 0, scratch, &tmpdata)))
+		goto cleanup;
+
+	    sc.sam_track_id = tmpdata.ciphertext;
+	}
+	if (retval) goto cleanup;
+      }
+
+      sc.sam_response_prompt.data = "Enter the displayed response";
+      sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data);
+      sc.sam_pk_for_sad.length = 0;
+      sc.sam_nonce = 0;
+      /* Generate checksum */
+      /*krb5_checksum_size(context, ctype)*/
+      /*krb5_calculate_checksum(context,ctype,in,in_length,seed,
+	seed_length,outcksum) */
+      /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed,
+	seed_length) */
+#if 0 /* XXX a) glue appears broken; b) this gives up the SAD */
+      sc.sam_cksum.contents = (krb5_octet *)
+	malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES));
+      if (sc.sam_cksum.contents == NULL) return(ENOMEM);
+
+      retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES,
+				       sc.sam_challenge.data,
+				       sc.sam_challenge.length,
+				       psr.sam_key.contents, /* key */
+				       psr.sam_key.length, /* key length */
+				       &sc.sam_cksum);
+      if (retval) { free(sc.sam_cksum.contents); return(retval); }
+#endif /* 0 */
+      
+      retval = encode_krb5_sam_challenge(&sc, &scratch);
+      if (retval) goto cleanup;
+      pa_data->magic = KV5M_PA_DATA;
+      pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE;
+      pa_data->contents = scratch->data;
+      pa_data->length = scratch->length;
+      
+      retval = 0;
+      break;
+    }
+
+cleanup:
+    krb5_free_keyblock_contents(context, &encrypting_key);
+    return retval;
+}
+
+static krb5_error_code
+verify_sam_response(krb5_context context, krb5_db_entry *client,
+		    krb5_data *req_pkt,
+		    krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
+		    krb5_pa_data *pa,
+		    preauth_get_entry_data_proc sam_get_entry_data,
+		    void *pa_system_context,
+		    void **pa_request_context,
+		    krb5_data **e_data,
+		    krb5_authdata ***authz_data)
+{
+    krb5_error_code		retval;
+    krb5_data			scratch;
+    krb5_sam_response		*sr = 0;
+    krb5_predicted_sam_response	*psr = 0;
+    krb5_enc_sam_response_enc	*esre = 0;
+    krb5_timestamp		timenow;
+    char			*princ_req = 0, *princ_psr = 0;
+
+    scratch.data = pa->contents;
+    scratch.length = pa->length;
+    
+    if ((retval = decode_krb5_sam_response(&scratch, &sr))) {
+	scratch.data = 0;
+	com_err("krb5kdc", retval, "decode_krb5_sam_response failed");
+	goto cleanup;
+    }
+
+    /* XXX We can only handle the challenge/response model of SAM.
+	   See passwords-04, par 4.1, 4.2 */
+    {
+      krb5_enc_data tmpdata;
+
+      tmpdata.enctype = ENCTYPE_UNKNOWN;
+      tmpdata.ciphertext = sr->sam_track_id;
+
+      scratch.length = tmpdata.ciphertext.length;
+      if ((scratch.data = (char *) malloc(scratch.length)) == NULL) {
+	  retval = ENOMEM;
+	  goto cleanup;
+      }
+
+      if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0,
+				   &tmpdata, &scratch))) {
+	  com_err("krb5kdc", retval, "decrypt track_id failed");
+	  goto cleanup;
+      }
+    }
+
+    if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) {
+	com_err("krb5kdc", retval,
+		"decode_krb5_predicted_sam_response failed -- replay attack?");
+	goto cleanup;
+    }
+
+    /* Replay detection */
+    if ((retval = krb5_unparse_name(context, request->client, &princ_req)))
+	goto cleanup;
+    if ((retval = krb5_unparse_name(context, psr->client, &princ_psr)))
+	goto cleanup;
+    if (strcmp(princ_req, princ_psr) != 0) {
+	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+		"Principal mismatch in SAM psr! -- replay attack?");
+	goto cleanup;
+    }
+
+    if ((retval = krb5_timeofday(context, &timenow)))
+	goto cleanup;
+
+#ifdef USE_RCACHE
+    {
+	krb5_donot_replay rep;
+	extern krb5_deltat rc_lifetime;
+	/*
+	 * Verify this response came back in a timely manner.
+	 * We do this b/c otherwise very old (expunged from the rcache)
+	 * psr's would be able to be replayed.
+	 */
+	if (timenow - psr->stime > rc_lifetime) {
+	    com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+	    "SAM psr came back too late! -- replay attack?");
+	    goto cleanup;
+	}
+
+	/* Now check the replay cache. */
+	rep.client = princ_psr;
+	rep.server = "SAM/rc";  /* Should not match any principal name. */
+	rep.ctime = psr->stime;
+	rep.cusec = psr->susec;
+	retval = krb5_rc_store(kdc_context, kdc_rcache, &rep);
+	if (retval) {
+	    com_err("krb5kdc", retval, "SAM psr replay attack!");
+	    goto cleanup;
+	}
+    }
+#endif /* USE_RCACHE */
+
+
+    {
+	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 (esre->sam_timestamp != sr->sam_patimestamp) {
+      retval = KRB5KDC_ERR_PREAUTH_FAILED;
+      goto cleanup;
+    }
+    
+    if (labs(timenow - sr->sam_patimestamp) > context->clockskew) {
+	retval = KRB5KRB_AP_ERR_SKEW;
+	goto cleanup;
+    }
+
+    setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
+
+  cleanup:
+    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);
+    if (princ_psr) free(princ_psr);
+    if (princ_req) free(princ_req);
+
+    return retval;
+}
diff --git a/krb5-1-6/src/kdc/kdc_util.c b/krb5-1-6/src/kdc/kdc_util.c
new file mode 100644
index 000000000..aeabc5c65
--- /dev/null
+++ b/krb5-1-6/src/kdc/kdc_util.c
@@ -0,0 +1,1591 @@
+/*
+ * kdc/kdc_util.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Utility functions for the KDC implementation.
+ */
+
+#include "k5-int.h"
+#include "kdc_util.h"
+#include "extern.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <syslog.h>
+#include "adm.h"
+#include "adm_proto.h"
+#include <limits.h>
+
+#ifdef USE_RCACHE
+static char *kdc_current_rcname = (char *) NULL;
+krb5_deltat rc_lifetime; /* See kdc_initialize_rcache() */
+#endif
+
+#ifdef USE_RCACHE
+/*
+ * initialize the replay cache.
+ */
+krb5_error_code
+kdc_initialize_rcache(krb5_context kcontext, char *rcache_name)
+{
+    krb5_error_code	retval;
+    char		*rcname;
+    char		*sname;
+
+    rcname = (rcache_name) ? rcache_name : kdc_current_rcname;
+
+    /* rc_lifetime used elsewhere to verify we're not */
+    /*  replaying really old data                     */
+    rc_lifetime = kcontext->clockskew;
+
+    if (!rcname)
+	rcname = KDCRCACHE;
+    if (!(retval = krb5_rc_resolve_full(kcontext, &kdc_rcache, rcname))) {
+	/* Recover or initialize the replay cache */
+	if (!(retval = krb5_rc_recover(kcontext, kdc_rcache)) ||
+	    !(retval = krb5_rc_initialize(kcontext,
+					  kdc_rcache,
+					  kcontext->clockskew))
+	    ) {
+	    /* Expunge the replay cache */
+	    if (!(retval = krb5_rc_expunge(kcontext, kdc_rcache))) {
+		sname = kdc_current_rcname;
+		kdc_current_rcname = strdup(rcname);
+		if (sname)
+		    free(sname);
+	    }
+	}
+	if (retval)
+	    krb5_rc_close(kcontext, kdc_rcache);
+    }
+    return(retval);
+}
+#endif
+
+/*
+ * concatenate first two authdata arrays, returning an allocated replacement.
+ * The replacement should be freed with krb5_free_authdata().
+ */
+krb5_error_code
+concat_authorization_data(krb5_authdata **first, krb5_authdata **second,
+			  krb5_authdata ***output)
+{
+    register int i, j;
+    register krb5_authdata **ptr, **retdata;
+
+    /* count up the entries */
+    i = 0;
+    if (first)
+	for (ptr = first; *ptr; ptr++)
+	    i++;
+    if (second)
+	for (ptr = second; *ptr; ptr++)
+	    i++;
+    
+    retdata = (krb5_authdata **)malloc((i+1)*sizeof(*retdata));
+    if (!retdata)
+	return ENOMEM;
+    retdata[i] = 0;			/* null-terminated array */
+    for (i = 0, j = 0, ptr = first; j < 2 ; ptr = second, j++)
+	while (ptr && *ptr) {
+	    /* now walk & copy */
+	    retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i]));
+	    if (!retdata[i]) {
+		krb5_free_authdata(kdc_context, retdata);
+		return ENOMEM;
+	    }
+	    *retdata[i] = **ptr;
+	    if (!(retdata[i]->contents =
+		  (krb5_octet *)malloc(retdata[i]->length))) {
+		free((char *)retdata[i]);
+		retdata[i] = 0;
+		krb5_free_authdata(kdc_context, retdata);
+		return ENOMEM;
+	    }
+	    memcpy((char *) retdata[i]->contents,
+		   (char *)(*ptr)->contents,
+		   retdata[i]->length);
+
+	    ptr++;
+	    i++;
+	}
+    *output = retdata;
+    return 0;
+}
+
+krb5_boolean
+realm_compare(krb5_principal princ1, krb5_principal princ2)
+{
+  krb5_data *realm1 = krb5_princ_realm(kdc_context, princ1);
+  krb5_data *realm2 = krb5_princ_realm(kdc_context, princ2);
+
+  return((realm1->length == realm2->length) &&
+         !memcmp(realm1->data, realm2->data, realm1->length));
+}
+
+/*
+ * Returns TRUE if the kerberos principal is the name of a Kerberos ticket
+ * service.
+ */
+krb5_boolean krb5_is_tgs_principal(krb5_principal principal)
+{
+	if ((krb5_princ_size(kdc_context, principal) > 0) &&
+	    (krb5_princ_component(kdc_context, principal, 0)->length ==
+	     KRB5_TGS_NAME_SIZE) &&
+	    (!memcmp(krb5_princ_component(kdc_context, principal, 0)->data,
+		     KRB5_TGS_NAME, KRB5_TGS_NAME_SIZE)))
+		return TRUE;
+	return FALSE;
+}
+
+/*
+ * given authentication data (provides seed for checksum), verify checksum
+ * for source data.
+ */
+static krb5_error_code
+comp_cksum(krb5_context kcontext, krb5_data *source, krb5_ticket *ticket,
+	   krb5_checksum *his_cksum)
+{
+    krb5_error_code 	  retval;
+    krb5_boolean	  valid;
+
+    if (!krb5_c_valid_cksumtype(his_cksum->checksum_type)) 
+	return KRB5KDC_ERR_SUMTYPE_NOSUPP;
+
+    /* must be collision proof */
+    if (!krb5_c_is_coll_proof_cksum(his_cksum->checksum_type))
+	return KRB5KRB_AP_ERR_INAPP_CKSUM;
+
+    /* verify checksum */
+    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 
+kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from,
+		    krb5_data *pkt, krb5_ticket **ticket,
+		    krb5_keyblock **subkey)
+{
+    krb5_pa_data       ** tmppa;
+    krb5_ap_req 	* apreq;
+    krb5_error_code 	  retval;
+    krb5_data		  scratch1;
+    krb5_data 		* scratch = NULL;
+    krb5_boolean 	  foreign_server = FALSE;
+    krb5_auth_context 	  auth_context = NULL;
+    krb5_authenticator	* authenticator = NULL;
+    krb5_checksum 	* his_cksum = NULL;
+/*    krb5_keyblock 	* key = NULL;*/
+/*    krb5_kvno 		  kvno = 0;*/
+
+    if (!request->padata)
+	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
+    for (tmppa = request->padata; *tmppa; tmppa++) {
+	if ((*tmppa)->pa_type == KRB5_PADATA_AP_REQ)
+	    break;
+    }
+    if (!*tmppa)			/* cannot find any AP_REQ */
+	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
+
+    scratch1.length = (*tmppa)->length;
+    scratch1.data = (char *)(*tmppa)->contents;
+    if ((retval = decode_krb5_ap_req(&scratch1, &apreq)))
+	return retval;
+    
+    if (isflagset(apreq->ap_options, AP_OPTS_USE_SESSION_KEY) ||
+	isflagset(apreq->ap_options, AP_OPTS_MUTUAL_REQUIRED)) {
+	krb5_klog_syslog(LOG_INFO, "TGS_REQ: SESSION KEY or MUTUAL");
+	retval = KRB5KDC_ERR_POLICY;
+	goto cleanup;
+    }
+
+    /* If the "server" principal in the ticket is not something
+       in the local realm, then we must refuse to service the request
+       if the client claims to be from the local realm.
+       
+       If we don't do this, then some other realm's nasty KDC can
+       claim to be authenticating a client from our realm, and we'll
+       give out tickets concurring with it!
+       
+       we set a flag here for checking below.
+       */
+    if ((krb5_princ_realm(kdc_context, apreq->ticket->server)->length !=
+	 krb5_princ_realm(kdc_context, tgs_server)->length) ||
+	memcmp(krb5_princ_realm(kdc_context, apreq->ticket->server)->data,
+	       krb5_princ_realm(kdc_context, tgs_server)->data,
+	       krb5_princ_realm(kdc_context, tgs_server)->length))
+	foreign_server = TRUE;
+
+    if ((retval = krb5_auth_con_init(kdc_context, &auth_context)))
+	goto cleanup;
+
+    if ((retval = krb5_auth_con_setaddrs(kdc_context, auth_context, NULL,
+					 from->address)) )
+	goto cleanup_auth_context;
+#ifdef USE_RCACHE
+    if ((retval = krb5_auth_con_setrcache(kdc_context, auth_context,
+					  kdc_rcache)))
+	goto cleanup_auth_context;
+#endif
+
+/*
+    if ((retval = kdc_get_server_key(apreq->ticket, &key, &kvno)))
+	goto cleanup_auth_context;
+*/
+
+    /*
+     * XXX This is currently wrong but to fix it will require making a 
+     * new keytab for groveling over the kdb.
+     */
+/*
+    retval = krb5_auth_con_setuseruserkey(kdc_context, auth_context, key);
+    krb5_free_keyblock(kdc_context, key);
+    if (retval) 
+	goto cleanup_auth_context;
+*/
+
+    if ((retval = krb5_rd_req_decoded_anyflag(kdc_context, &auth_context, apreq, 
+				      apreq->ticket->server, 
+				      kdc_active_realm->realm_keytab,
+				      NULL, ticket))) {
+#ifdef USE_RCACHE
+	/*
+	 * I'm not so sure that this is right, but it's better than nothing
+	 * at all.
+	 *
+	 * If we choke in the rd_req because of the replay cache, then attempt
+	 * to reinitialize the replay cache because somebody could have deleted
+	 * it from underneath us (e.g. a cron job)
+	 */
+	if ((retval == KRB5_RC_IO_IO) ||
+	    (retval == KRB5_RC_IO_UNKNOWN)) {
+	    (void) krb5_rc_close(kdc_context, kdc_rcache);
+	    kdc_rcache = (krb5_rcache) NULL;
+	    if (!(retval = kdc_initialize_rcache(kdc_context, (char *) NULL))) {
+		if ((retval = krb5_auth_con_setrcache(kdc_context, auth_context,
+						      kdc_rcache)) ||
+		    (retval = krb5_rd_req_decoded_anyflag(kdc_context, &auth_context,
+						  apreq, apreq->ticket->server,
+				      		 kdc_active_realm->realm_keytab,
+						  NULL, ticket))
+		    )
+		    goto cleanup_auth_context;
+	    }
+	} else
+	    goto cleanup_auth_context; 
+#else
+	goto cleanup_auth_context; 
+#endif
+    }
+
+    /* "invalid flag" tickets can must be used to validate */
+    if (isflagset((*ticket)->enc_part2->flags, TKT_FLG_INVALID)
+	&& !isflagset(request->kdc_options, KDC_OPT_VALIDATE)) {
+        retval = KRB5KRB_AP_ERR_TKT_INVALID;
+	goto cleanup_auth_context;
+    }
+
+    if ((retval = krb5_auth_con_getrecvsubkey(kdc_context,
+					      auth_context, subkey)))
+	goto cleanup_auth_context;
+
+    if ((retval = krb5_auth_con_getauthenticator(kdc_context, auth_context,
+						 &authenticator)))
+	goto cleanup_auth_context;
+
+    /* Check for a checksum */
+    if (!(his_cksum = authenticator->checksum)) {
+	retval = KRB5KRB_AP_ERR_INAPP_CKSUM; 
+	goto cleanup_authenticator;
+    }
+
+    /* make sure the client is of proper lineage (see above) */
+    if (foreign_server) {
+	krb5_data *tkt_realm = krb5_princ_realm(kdc_context, 
+						(*ticket)->enc_part2->client);
+	krb5_data *tgs_realm = krb5_princ_realm(kdc_context, tgs_server);
+	if (tkt_realm->length == tgs_realm->length &&
+	    !memcmp(tkt_realm->data, tgs_realm->data, tgs_realm->length)) {
+	    /* someone in a foreign realm claiming to be local */
+	    krb5_klog_syslog(LOG_INFO, "PROCESS_TGS: failed lineage check");
+	    retval = KRB5KDC_ERR_POLICY;
+	    goto cleanup_authenticator;
+	}
+    }
+
+    /*
+     * Check application checksum vs. tgs request
+     * 	 
+     * We try checksumming the req-body two different ways: first we
+     * try reaching into the raw asn.1 stream (if available), and
+     * checksum that directly; if that fails, then we try encoding
+     * using our local asn.1 library.
+     */
+    if (pkt && (fetch_asn1_field((unsigned char *) pkt->data,
+				 1, 4, &scratch1) >= 0)) {
+	if (comp_cksum(kdc_context, &scratch1, *ticket, his_cksum)) {
+	    if (!(retval = encode_krb5_kdc_req_body(request, &scratch))) 
+	        retval = comp_cksum(kdc_context, scratch, *ticket, his_cksum);
+	    krb5_free_data(kdc_context, scratch);
+	}
+    }
+
+cleanup_authenticator:
+    krb5_free_authenticator(kdc_context, authenticator);
+
+cleanup_auth_context:
+    /* We do not want the free of the auth_context to close the rcache */
+#ifdef USE_RCACHE
+    (void)  krb5_auth_con_setrcache(kdc_context, auth_context, 0);
+#endif
+    krb5_auth_con_free(kdc_context, auth_context);
+
+cleanup:
+    krb5_free_ap_req(kdc_context, apreq);
+    return retval;
+}
+
+/* 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(krb5_ticket *ticket, krb5_keyblock **key, krb5_kvno *kvno)
+{
+    krb5_error_code 	  retval;
+    krb5_db_entry 	  server;
+    krb5_boolean 	  more;
+    int	nprincs;
+    krb5_key_data	* server_key;
+
+    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)) {
+	    limit_string(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 */
+
+static krb5_last_req_entry nolrentry = { KV5M_LAST_REQ_ENTRY, KRB5_LRQ_NONE, 0 };
+static krb5_last_req_entry *nolrarray[] = { &nolrentry, 0 };
+
+krb5_error_code
+fetch_last_req_info(krb5_db_entry *dbentry, krb5_last_req_entry ***lrentry)
+{
+    *lrentry = nolrarray;
+    return 0;
+}
+
+
+/* XXX!  This is a temporary place-holder */
+
+krb5_error_code
+check_hot_list(krb5_ticket *ticket)
+{
+    return 0;
+}
+
+
+#define MAX_REALM_LN 500
+
+
+/* 
+ * subrealm - determine if r2 is a subrealm of r1
+ *
+ *            SUBREALM takes two realms, r1 and r2, and 
+ *            determines if r2 is a subrealm of r1.   
+ *            r2 is a subrealm of r1 if (r1 is a prefix
+ *            of r2 AND r1 and r2 begin with a /) or if 
+ *            (r1 is a suffix of r2 and neither r1 nor r2
+ *            begin with a /).
+ *
+ * RETURNS:   If r2 is a subrealm, and r1 is a prefix, the number
+ *            of characters in the suffix of r2 is returned as a
+ *            negative number.
+ *
+ *            If r2 is a subrealm, and r1 is a suffix, the number
+ *            of characters in the prefix of r2 is returned as a
+ *            positive number.
+ *
+ *            If r2 is not a subrealm, SUBREALM returns 0.
+ */
+static  int
+subrealm(char *r1, char *r2)
+{
+    size_t l1,l2;
+    l1 = strlen(r1);
+    l2 = strlen(r2);
+    if(l2 <= l1) return(0);
+    if((*r1 == '/') && (*r2 == '/') && (strncmp(r1,r2,l1) == 0)) return(l1-l2);
+    if((*r1 != '/') && (*r2 != '/') && (strncmp(r1,r2+l2-l1,l1) == 0))
+	return(l2-l1);
+    return(0);
+}
+
+/*
+ * add_to_transited  Adds the name of the realm which issued the
+ *                   ticket granting ticket on which the new ticket to
+ *                   be issued is based (note that this is the same as
+ *                   the realm of the server listed in the ticket
+ *                   granting ticket. 
+ *
+ * ASSUMPTIONS:  This procedure assumes that the transited field from
+ *               the existing ticket granting ticket already appears
+ *               in compressed form.  It will add the new realm while
+ *               maintaining that form.   As long as each successive
+ *               realm is added using this (or a similar) routine, the
+ *               transited field will be in compressed form.  The
+ *               basis step is an empty transited field which is, by
+ *               its nature, in its most compressed form.
+ *
+ * ARGUMENTS: krb5_data *tgt_trans  Transited field from TGT
+ *            krb5_data *new_trans  The transited field for the new ticket
+ *            krb5_principal tgs    Name of ticket granting server
+ *                                  This includes the realm of the KDC
+ *                                  that issued the ticket granting
+ *                                  ticket.  This is the realm that is
+ *                                  to be added to the transited field.
+ *            krb5_principal client Name of the client
+ *            krb5_principal server The name of the requested server.
+ *                                  This may be the an intermediate
+ *                                  ticket granting server.
+ *
+ *            The last two argument are needed since they are
+ *            implicitly part of the transited field of the new ticket
+ *            even though they are not explicitly listed.
+ *
+ * RETURNS:   krb5_error_code - Success, or out of memory
+ *
+ * MODIFIES:  new_trans:  ->length will contain the length of the new
+ *                        transited field.
+ * 
+ *                        If ->data was not null when this procedure
+ *                        is called, the memory referenced by ->data
+ *                        will be deallocated. 
+ *
+ *                        Memory will be allocated for the new transited field
+ *                        ->data will be updated to point to the newly
+ *                        allocated memory.  
+ *
+ * BUGS:  The space allocated for the new transited field is the
+ *        maximum that might be needed given the old transited field,
+ *        and the realm to be added.  This length is calculated
+ *        assuming that no compression of the new realm is possible.
+ *        This has no adverse consequences other than the allocation
+ *        of more space than required.  
+ *
+ *        This procedure will not yet use the null subfield notation,
+ *        and it will get confused if it sees it.
+ *
+ *        This procedure does not check for quoted commas in realm
+ *        names.
+ */
+
+static char *
+data2string (krb5_data *d)
+{
+    char *s;
+    s = malloc(d->length + 1);
+    if (s) {
+	memcpy(s, d->data, d->length);
+	s[d->length] = 0;
+    }
+    return s;
+}
+
+krb5_error_code 
+add_to_transited(krb5_data *tgt_trans, krb5_data *new_trans,
+		 krb5_principal tgs, krb5_principal client,
+		 krb5_principal server)
+{
+  krb5_error_code retval;
+  char        *realm;
+  char        *trans;
+  char        *otrans, *otrans_ptr;
+
+  /* The following are for stepping through the transited field     */
+
+  char        prev[MAX_REALM_LN];
+  char        next[MAX_REALM_LN];
+  char        current[MAX_REALM_LN];
+  char        exp[MAX_REALM_LN];      /* Expanded current realm name     */
+
+  int	      i;
+  int         clst, nlst;    /* count of last character in current and next */
+  int         pl, pl1;       /* prefix length                               */
+  int         added;         /* TRUE = new realm has been added             */
+
+  realm = data2string(krb5_princ_realm(kdc_context, tgs));
+  if (realm == NULL)
+      return(ENOMEM);
+
+  otrans = data2string(tgt_trans);
+  if (otrans == NULL) {
+      free(realm);
+      return(ENOMEM);
+  }
+  /* Keep track of start so we can free */
+  otrans_ptr = otrans;
+
+  /* +1 for null, 
+     +1 for extra comma which may be added between
+     +1 for potential space when leading slash in realm */
+  if (!(trans = (char *) malloc(strlen(realm) + strlen(otrans) + 3))) {
+    retval = ENOMEM;
+    goto fail;
+  }
+
+  if (new_trans->data)  free(new_trans->data);
+  new_trans->data = trans;
+  new_trans->length = 0;
+
+  trans[0] = '\0';
+
+  /* For the purpose of appending, the realm preceding the first */
+  /* realm in the transited field is considered the null realm   */
+
+  prev[0] = '\0';
+
+  /* read field into current */
+  for (i = 0; *otrans != '\0';) {
+      if (*otrans == '\\') {
+	  if (*(++otrans) == '\0')
+	      break;
+	  else
+	      continue;
+      }
+      if (*otrans == ',') {
+	  otrans++;
+	  break;
+      }
+      current[i++] = *otrans++;
+      if (i >= MAX_REALM_LN) {
+	  retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	  goto fail;
+      }
+  }
+  current[i] = '\0';
+
+  added = (krb5_princ_realm(kdc_context, client)->length == strlen(realm) &&
+           !strncmp(krb5_princ_realm(kdc_context, client)->data, realm, strlen(realm))) ||
+          (krb5_princ_realm(kdc_context, server)->length == strlen(realm) &&
+           !strncmp(krb5_princ_realm(kdc_context, server)->data, realm, strlen(realm)));
+
+  while (current[0]) {
+
+    /* figure out expanded form of current name */
+
+    clst = strlen(current) - 1;
+    if (current[0] == ' ') {
+      strncpy(exp, current+1, sizeof(exp) - 1);
+      exp[sizeof(exp) - 1] = '\0';
+    }
+    else if ((current[0] == '/') && (prev[0] == '/')) {
+      strncpy(exp, prev, sizeof(exp) - 1);
+      exp[sizeof(exp) - 1] = '\0';
+      if (strlen(exp) + strlen(current) + 1 >= MAX_REALM_LN) {
+	retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	goto fail;
+      }
+      strncat(exp, current, sizeof(exp) - 1 - strlen(exp));
+    }
+    else if (current[clst] == '.') {
+      strncpy(exp, current, sizeof(exp) - 1);
+      exp[sizeof(exp) - 1] = '\0';
+      if (strlen(exp) + strlen(prev) + 1 >= MAX_REALM_LN) {
+	retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	goto fail;
+      }
+      strncat(exp, prev, sizeof(exp) - 1 - strlen(exp));
+    }
+    else {
+      strncpy(exp, current, sizeof(exp) - 1);
+      exp[sizeof(exp) - 1] = '\0';
+    }
+
+    /* read field into next */
+    for (i = 0; *otrans != '\0';) {
+	if (*otrans == '\\') {
+	    if (*(++otrans) == '\0')
+		break;
+	    else
+		continue;
+	}
+	if (*otrans == ',') {
+	    otrans++;
+	    break;
+	}
+	next[i++] = *otrans++;
+	if (i >= MAX_REALM_LN) {
+	    retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	    goto fail;
+	}
+    }
+    next[i] = '\0';
+    nlst = i - 1;
+
+    if (!strcmp(exp, realm))  added = TRUE;
+
+    /* If we still have to insert the new realm */
+
+    if (!added) {
+
+      /* Is the next field compressed?  If not, and if the new */
+      /* realm is a subrealm of the current realm, compress    */
+      /* the new realm, and insert immediately following the   */
+      /* current one.  Note that we can not do this if the next*/
+      /* field is already compressed since it would mess up    */
+      /* what has already been done.  In most cases, this is   */
+      /* not a problem because the realm to be added will be a */
+      /* subrealm of the next field too, and we will catch     */
+      /* it in a future iteration.                             */
+
+	/* Note that the second test here is an unsigned comparison,
+	   so the first half (or a cast) is also required.  */
+      assert(nlst < 0 || nlst < sizeof(next));
+      if ((nlst < 0 || next[nlst] != '.') &&
+	  (next[0] != '/') &&
+	  (pl = subrealm(exp, realm))) {
+        added = TRUE;
+	current[sizeof(current) - 1] = '\0';
+	if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) {
+	  retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	  goto fail;
+	}
+        strncat(current, ",", sizeof(current) - 1 - strlen(current));
+        if (pl > 0) {
+          strncat(current, realm, (unsigned) pl);
+        }
+        else {
+          strncat(current, realm+strlen(realm)+pl, (unsigned) (-pl));
+        }
+      }
+
+      /* Whether or not the next field is compressed, if the    */
+      /* realm to be added is a superrealm of the current realm,*/
+      /* then the current realm can be compressed.  First the   */
+      /* realm to be added must be compressed relative to the   */
+      /* previous realm (if possible), and then the current     */
+      /* realm compressed relative to the new realm.  Note that */
+      /* if the realm to be added is also a superrealm of the   */
+      /* previous realm, it would have been added earlier, and  */
+      /* we would not reach this step this time around.         */
+
+      else if ((pl = subrealm(realm, exp))) {
+        added      = TRUE;
+        current[0] = '\0';
+        if ((pl1 = subrealm(prev,realm))) {
+	  if (strlen(current) + (pl1>0?pl1:-pl1) + 1 >= MAX_REALM_LN) {
+	    retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	    goto fail;
+	  }
+          if (pl1 > 0) {
+            strncat(current, realm, (unsigned) pl1);
+          }
+          else {
+            strncat(current, realm+strlen(realm)+pl1, (unsigned) (-pl1));
+          }
+        }
+        else { /* If not a subrealm */
+          if ((realm[0] == '/') && prev[0]) {
+	    if (strlen(current) + 2 >= MAX_REALM_LN) {
+	      retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	      goto fail;
+	    }
+	    strncat(current, " ", sizeof(current) - 1 - strlen(current));
+	    current[sizeof(current) - 1] = '\0';
+          }
+	  if (strlen(current) + strlen(realm) + 1 >= MAX_REALM_LN) {
+	    retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	    goto fail;
+	  }
+          strncat(current, realm, sizeof(current) - 1 - strlen(current));
+	  current[sizeof(current) - 1] = '\0';
+        }
+	if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) {
+	  retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	  goto fail;
+	}
+        strncat(current,",", sizeof(current) - 1 - strlen(current));
+	current[sizeof(current) - 1] = '\0';
+        if (pl > 0) {
+          strncat(current, exp, (unsigned) pl);
+        }
+        else {
+          strncat(current, exp+strlen(exp)+pl, (unsigned)(-pl));
+        }
+      }
+    }
+
+    if (new_trans->length != 0) {
+      if (strlen(trans) + 2 >= MAX_REALM_LN) {
+	retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	goto fail;
+      }
+      strcat(trans, ",");
+    }
+    if (strlen(trans) + strlen(current) + 1 >= MAX_REALM_LN) {
+      retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+      goto fail;
+    }
+    strcat(trans, current);
+    new_trans->length = strlen(trans);
+
+    strncpy(prev, exp, sizeof(prev) - 1);
+    prev[sizeof(prev) - 1] = '\0';
+    strncpy(current, next, sizeof(current) - 1);
+    current[sizeof(current) - 1] = '\0';
+  }
+
+  if (!added) {
+    if (new_trans->length != 0) {
+      if (strlen(trans) + 2 >= MAX_REALM_LN) {
+	retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	goto fail;
+      }
+      strcat(trans, ",");
+    }
+    if((realm[0] == '/') && trans[0]) {
+      if (strlen(trans) + 2 >= MAX_REALM_LN) {
+	retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+	goto fail;
+      }
+      strcat(trans, " ");
+    }
+    if (strlen(trans) + strlen(realm) + 1 >= MAX_REALM_LN) {
+      retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+      goto fail;
+    }
+    strcat(trans, realm);
+    new_trans->length = strlen(trans);
+  }
+
+  retval = 0;
+fail:
+  free(realm);
+  free(otrans_ptr);
+  return (retval);
+}
+
+/*
+ * Routines that validate a AS request; checks a lot of things.  :-)
+ *
+ * Returns a Kerberos protocol error number, which is _not_ the same
+ * as a com_err error number!
+ */
+#define AS_INVALID_OPTIONS (KDC_OPT_FORWARDED | KDC_OPT_PROXY |\
+KDC_OPT_VALIDATE | KDC_OPT_RENEW | KDC_OPT_ENC_TKT_IN_SKEY)
+int
+validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
+		    krb5_db_entry server, krb5_timestamp kdc_time,
+		    const char **status)
+{
+    int		errcode;
+    
+    /*
+     * If an option is set that is only allowed in TGS requests, complain.
+     */
+    if (request->kdc_options & AS_INVALID_OPTIONS) {
+	*status = "INVALID AS OPTIONS";
+	return KDC_ERR_BADOPTION;
+    }
+
+    /* The client's password must not be expired, unless the server is
+      a KRB5_KDC_PWCHANGE_SERVICE. */
+    if (client.pw_expiration && client.pw_expiration < kdc_time &&
+	!isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
+	*status = "CLIENT KEY EXPIRED";
+#ifdef KRBCONF_VAGUE_ERRORS
+	return(KRB_ERR_GENERIC);
+#else
+	return(KDC_ERR_KEY_EXP);
+#endif
+    }
+
+    /* The client must not be expired */
+    if (client.expiration && client.expiration < kdc_time) {
+	*status = "CLIENT EXPIRED";
+#ifdef KRBCONF_VAGUE_ERRORS
+	return(KRB_ERR_GENERIC);
+#else
+	return(KDC_ERR_NAME_EXP);
+#endif
+    }
+
+    /* The server must not be expired */
+    if (server.expiration && server.expiration < kdc_time) {
+	*status = "SERVICE EXPIRED";
+	    return(KDC_ERR_SERVICE_EXP);
+    }
+
+    /*
+     * If the client requires password changing, then only allow the 
+     * pwchange service.
+     */
+    if (isflagset(client.attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
+	!isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
+	*status = "REQUIRED PWCHANGE";
+	return(KDC_ERR_KEY_EXP);
+    }
+
+    /* Client and server must allow postdating tickets */
+    if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
+	 isflagset(request->kdc_options, KDC_OPT_POSTDATED)) && 
+	(isflagset(client.attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
+	 isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
+	*status = "POSTDATE NOT ALLOWED";
+	return(KDC_ERR_CANNOT_POSTDATE);
+    }
+    
+    /* Client and server must allow forwardable tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE) &&
+	(isflagset(client.attributes, KRB5_KDB_DISALLOW_FORWARDABLE) ||
+	 isflagset(server.attributes, KRB5_KDB_DISALLOW_FORWARDABLE))) {
+	*status = "FORWARDABLE NOT ALLOWED";
+	return(KDC_ERR_POLICY);
+    }
+    
+    /* Client and server must allow renewable tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE) &&
+	(isflagset(client.attributes, KRB5_KDB_DISALLOW_RENEWABLE) ||
+	 isflagset(server.attributes, KRB5_KDB_DISALLOW_RENEWABLE))) {
+	*status = "RENEWABLE NOT ALLOWED";
+	return(KDC_ERR_POLICY);
+    }
+    
+    /* Client and server must allow proxiable tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE) &&
+	(isflagset(client.attributes, KRB5_KDB_DISALLOW_PROXIABLE) ||
+	 isflagset(server.attributes, KRB5_KDB_DISALLOW_PROXIABLE))) {
+	*status = "PROXIABLE NOT ALLOWED";
+	return(KDC_ERR_POLICY);
+    }
+    
+    /* Check to see if client is locked out */
+    if (isflagset(client.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+	*status = "CLIENT LOCKED OUT";
+	return(KDC_ERR_C_PRINCIPAL_UNKNOWN);
+    }
+
+    /* Check to see if server is locked out */
+    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+	*status = "SERVICE LOCKED OUT";
+	return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+    }
+	
+    /* Check to see if server is allowed to be a service */
+    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
+	*status = "SERVICE NOT ALLOWED";
+	return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+    }
+
+    /*
+     * Check against local policy
+     */
+    errcode = against_local_policy_as(request, server, client,
+				      kdc_time, status); 
+    if (errcode)
+	return errcode;
+
+    return 0;
+}
+
+#define ASN1_ID_CLASS	(0xc0)
+#define ASN1_ID_TYPE    (0x20)
+#define ASN1_ID_TAG	(0x1f)	
+#define ASN1_CLASS_UNIV	(0)
+#define ASN1_CLASS_APP	(1)
+#define ASN1_CLASS_CTX	(2)
+#define ASN1_CLASS_PRIV	(3)
+#define asn1_id_constructed(x) 	(x & ASN1_ID_TYPE)
+#define asn1_id_primitive(x) 	(!asn1_id_constructed(x))
+#define asn1_id_class(x)	((x & ASN1_ID_CLASS) >> 6)
+#define asn1_id_tag(x)		(x & ASN1_ID_TAG)
+
+/*
+ * asn1length - return encoded length of value.
+ *
+ * passed a pointer into the asn.1 stream, which is updated
+ * to point right after the length bits.
+ *
+ * returns -1 on failure.
+ */
+static int
+asn1length(unsigned char **astream)
+{
+    int length;		/* resulting length */
+    int sublen;		/* sublengths */
+    int blen;		/* bytes of length */ 
+    unsigned char *p;	/* substring searching */	
+
+    if (**astream & 0x80) {
+        blen = **astream & 0x7f;
+	if (blen > 3) {
+	   return(-1);
+	}
+	for (++*astream, length = 0; blen; ++*astream, blen--) {
+	    length = (length << 8) | **astream;
+	}
+	if (length == 0) {
+		/* indefinite length, figure out by hand */
+	    p = *astream;
+	    p++;
+	    while (1) {
+		/* compute value length. */
+		if ((sublen = asn1length(&p)) < 0) {
+		    return(-1);
+		}
+		p += sublen;
+                /* check for termination */
+		if ((!*p++) && (!*p)) {
+		    p++;
+		    break;
+		}
+	    }
+	    length = p - *astream;	 
+	}
+    } else {
+	length = **astream;
+	++*astream;
+    } 
+   return(length);
+}
+
+/*
+ * fetch_asn1_field - return raw asn.1 stream of subfield.
+ *
+ * this routine is passed a context-dependent tag number and "level" and returns
+ * the size and length of the corresponding level subfield.
+ *
+ * levels and are numbered starting from 1.  
+ *
+ * returns 0 on success, -1 otherwise.
+ */
+int
+fetch_asn1_field(unsigned char *astream, unsigned int level,
+		 unsigned int field, krb5_data *data)
+{
+    unsigned char *estream;	/* end of stream */
+    int classes;		/* # classes seen so far this level */
+    unsigned int levels = 0;		/* levels seen so far */
+    int lastlevel = 1000;       /* last level seen */
+    int length;			/* various lengths */
+    int tag;			/* tag number */
+    unsigned char savelen;      /* saved length of our field */
+
+    classes = -1;
+    /* we assume that the first identifier/length will tell us 
+       how long the entire stream is. */
+    astream++;
+    estream = astream;
+    if ((length = asn1length(&astream)) < 0) {
+	return(-1);
+    }
+    estream += length;
+    /* search down the stream, checking identifiers.  we process identifiers
+       until we hit the "level" we want, and then process that level for our
+       subfield, always making sure we don't go off the end of the stream.  */
+    while (astream < estream) {
+	if (!asn1_id_constructed(*astream)) {
+	    return(-1);
+	}
+        if (asn1_id_class(*astream) == ASN1_CLASS_CTX) {
+            if ((tag = (int)asn1_id_tag(*astream)) <= lastlevel) {
+                levels++;
+                classes = -1;
+            }
+            lastlevel = tag; 
+            if (levels == level) {
+	        /* in our context-dependent class, is this the one we're looking for ? */
+	        if (tag == field) {
+		    /* return length and data */ 
+		    astream++;
+		    savelen = *astream;
+		    if ((data->length = asn1length(&astream)) < 0) {
+		        return(-1);
+	 	    }
+		    /* if the field length is indefinite, we will have to subtract two
+                       (terminating octets) from the length returned since we don't want
+                       to pass any info from the "wrapper" back.  asn1length will always return
+                       the *total* length of the field, not just what's contained in it */ 
+		    if ((savelen & 0xff) == 0x80) {
+		      data->length -=2 ;
+		    }
+		    data->data = (char *)astream;
+		    return(0);
+	        } else if (tag <= classes) {
+		    /* we've seen this class before, something must be wrong */
+		    return(-1);
+	        } else {
+		    classes = tag;
+	        }
+	    }
+        }
+        /* if we're not on our level yet, process this value.  otherwise skip over it */
+	astream++;
+	if ((length = asn1length(&astream)) < 0) {
+	    return(-1);
+	}
+	if (levels == level) {
+	    astream += length;
+	}
+    }
+    return(-1);
+}	
+
+/*
+ * Routines that validate a TGS request; checks a lot of things.  :-)
+ *
+ * Returns a Kerberos protocol error number, which is _not_ the same
+ * as a com_err error number!
+ */
+#define TGS_OPTIONS_HANDLED (KDC_OPT_FORWARDABLE | KDC_OPT_FORWARDED | \
+			     KDC_OPT_PROXIABLE | KDC_OPT_PROXY | \
+			     KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED | \
+			     KDC_OPT_RENEWABLE | KDC_OPT_RENEWABLE_OK | \
+			     KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_RENEW | \
+			     KDC_OPT_VALIDATE)
+
+#define NO_TGT_OPTION (KDC_OPT_FORWARDED | KDC_OPT_PROXY | KDC_OPT_RENEW | \
+		       KDC_OPT_VALIDATE)
+
+int
+validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
+		     krb5_ticket *ticket, krb5_timestamp kdc_time,
+		     const char **status)
+{
+    int		errcode;
+    int		st_idx = 0;
+
+    /*
+     * If an illegal option is set, ignore it.
+     */
+    request->kdc_options &= TGS_OPTIONS_HANDLED;
+
+    /* Check to see if server has expired */
+    if (server.expiration && server.expiration < kdc_time) {
+	*status = "SERVICE EXPIRED";
+	return(KDC_ERR_SERVICE_EXP);
+    }
+
+    /*
+     * Verify that the server principal in authdat->ticket is correct
+     * (either the ticket granting service or the service that was
+     * originally requested)
+     */
+    if (request->kdc_options & NO_TGT_OPTION) {
+	if (!krb5_principal_compare(kdc_context, ticket->server, request->server)) {
+	    *status = "SERVER DIDN'T MATCH TICKET FOR RENEW/FORWARD/ETC";
+	    return(KDC_ERR_SERVER_NOMATCH);
+	}
+    } else {
+	/*
+	 * OK, we need to validate the krbtgt service in the ticket.
+	 *
+	 * The krbtgt service is of the form:
+	 * 		krbtgt/realm-A@realm-B
+	 *
+	 * Realm A is the "server realm"; the realm of the
+	 * server of the requested ticket must match this realm.
+	 * Of course, it should be a realm serviced by this KDC.
+	 *
+	 * Realm B is the "client realm"; this is what should be
+	 * added to the transited field.  (which is done elsewhere)
+	 */
+
+	/* Make sure there are two components... */
+	if (krb5_princ_size(kdc_context, ticket->server) != 2) {
+	    *status = "BAD TGS SERVER LENGTH";
+	    return KRB_AP_ERR_NOT_US;
+	}
+	/* ...that the first component is krbtgt... */
+	if (!krb5_is_tgs_principal(ticket->server)) {
+	    *status = "BAD TGS SERVER NAME";
+	    return KRB_AP_ERR_NOT_US;
+	}
+	/* ...and that the second component matches the server realm... */
+	if ((krb5_princ_size(kdc_context, ticket->server) <= 1) ||
+	    (krb5_princ_component(kdc_context, ticket->server, 1)->length !=
+	     krb5_princ_realm(kdc_context, request->server)->length) ||
+	    memcmp(krb5_princ_component(kdc_context, ticket->server, 1)->data,
+		   krb5_princ_realm(kdc_context, request->server)->data,
+		   krb5_princ_realm(kdc_context, request->server)->length)) {
+	    *status = "BAD TGS SERVER INSTANCE";
+	    return KRB_AP_ERR_NOT_US;
+	}
+	/* XXX add check that second component must match locally
+	 * supported realm?
+	 */
+
+	/* Server must allow TGS based issuances */
+	if (isflagset(server.attributes, KRB5_KDB_DISALLOW_TGT_BASED)) {
+	    *status = "TGT BASED NOT ALLOWED";
+	    return(KDC_ERR_POLICY);
+	}
+    }
+	    
+    /* TGS must be forwardable to get forwarded or forwardable ticket */
+    if ((isflagset(request->kdc_options, KDC_OPT_FORWARDED) ||
+	 isflagset(request->kdc_options, KDC_OPT_FORWARDABLE)) &&
+	!isflagset(ticket->enc_part2->flags, TKT_FLG_FORWARDABLE)) {
+	*status = "TGT NOT FORWARDABLE";
+
+	return KDC_ERR_BADOPTION;
+    }
+
+    /* TGS must be proxiable to get proxiable ticket */    
+    if ((isflagset(request->kdc_options, KDC_OPT_PROXY) ||
+	 isflagset(request->kdc_options, KDC_OPT_PROXIABLE)) &&
+	!isflagset(ticket->enc_part2->flags, TKT_FLG_PROXIABLE)) {
+	*status = "TGT NOT PROXIABLE";
+	return KDC_ERR_BADOPTION;
+    }
+
+    /* TGS must allow postdating to get postdated ticket */
+    if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
+	  isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
+	!isflagset(ticket->enc_part2->flags, TKT_FLG_MAY_POSTDATE)) {
+	*status = "TGT NOT POSTDATABLE";
+	return KDC_ERR_BADOPTION;
+    }
+
+    /* can only validate invalid tix */
+    if (isflagset(request->kdc_options, KDC_OPT_VALIDATE) &&
+	!isflagset(ticket->enc_part2->flags, TKT_FLG_INVALID)) {
+	*status = "VALIDATE VALID TICKET";
+	return KDC_ERR_BADOPTION;
+    }
+
+    /* can only renew renewable tix */
+    if ((isflagset(request->kdc_options, KDC_OPT_RENEW) ||
+	  isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) &&
+	!isflagset(ticket->enc_part2->flags, TKT_FLG_RENEWABLE)) {
+	*status = "TICKET NOT RENEWABLE";
+	return KDC_ERR_BADOPTION;
+    }
+
+    /* can not proxy ticket granting tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_PROXY) &&
+	(!request->server->data ||
+	 request->server->data[0].length != KRB5_TGS_NAME_SIZE ||
+	 memcmp(request->server->data[0].data, KRB5_TGS_NAME,
+		KRB5_TGS_NAME_SIZE))) {
+	*status = "CAN'T PROXY TGT";
+	return KDC_ERR_BADOPTION;
+    }
+    
+    /* Server must allow forwardable tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE) &&
+	isflagset(server.attributes, KRB5_KDB_DISALLOW_FORWARDABLE)) {
+	*status = "NON-FORWARDABLE TICKET";
+	return(KDC_ERR_POLICY);
+    }
+    
+    /* Server must allow renewable tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE) &&
+	isflagset(server.attributes, KRB5_KDB_DISALLOW_RENEWABLE)) {
+	*status = "NON-RENEWABLE TICKET";
+	return(KDC_ERR_POLICY);
+    }
+    
+    /* Server must allow proxiable tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE) &&
+	isflagset(server.attributes, KRB5_KDB_DISALLOW_PROXIABLE)) {
+	*status = "NON-PROXIABLE TICKET";
+	return(KDC_ERR_POLICY);
+    }
+    
+    /* Server must allow postdated tickets */
+    if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) &&
+	isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED)) {
+	*status = "NON-POSTDATABLE TICKET";
+	return(KDC_ERR_CANNOT_POSTDATE);
+    }
+    
+    /* Server must allow DUP SKEY requests */
+    if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) &&
+	isflagset(server.attributes, KRB5_KDB_DISALLOW_DUP_SKEY)) {
+	*status = "DUP_SKEY DISALLOWED";
+	return(KDC_ERR_POLICY);
+    }
+
+    /* Server must not be locked out */
+    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+	*status = "SERVER LOCKED OUT";
+	return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+    }
+	
+    /* Server must be allowed to be a service */
+    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
+	*status = "SERVER NOT ALLOWED";
+	return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+    }
+
+    /* Check the hot list */
+    if (check_hot_list(ticket)) {
+	*status = "HOT_LIST";
+	return(KRB_AP_ERR_REPEAT);
+    }
+    
+    /* Check the start time vs. the KDC time */
+    if (isflagset(request->kdc_options, KDC_OPT_VALIDATE)) {
+	if (ticket->enc_part2->times.starttime > kdc_time) {
+	    *status = "NOT_YET_VALID";
+	    return(KRB_AP_ERR_TKT_NYV);
+	}
+    }
+    
+    /*
+     * Check the renew_till time.  The endtime was already
+     * been checked in the initial authentication check.
+     */
+    if (isflagset(request->kdc_options, KDC_OPT_RENEW) &&
+	(ticket->enc_part2->times.renew_till < kdc_time)) {
+	*status = "TKT_EXPIRED";
+	return(KRB_AP_ERR_TKT_EXPIRED);
+    }
+    
+    /*
+     * Checks for ENC_TKT_IN_SKEY:
+     *
+     * (1) Make sure the second ticket exists
+     * (2) Make sure it is a ticket granting ticket
+     */
+    if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) {
+	if (!request->second_ticket ||
+	    !request->second_ticket[st_idx]) {
+	    *status = "NO_2ND_TKT";
+	    return(KDC_ERR_BADOPTION);
+	}
+	if (!krb5_principal_compare(kdc_context, request->second_ticket[st_idx]->server,
+				    tgs_server)) {
+		*status = "2ND_TKT_NOT_TGS";
+		return(KDC_ERR_POLICY);
+	}
+	st_idx++;
+    }
+
+    /* Check for hardware preauthentication */
+    if (isflagset(server.attributes, KRB5_KDB_REQUIRES_HW_AUTH) &&
+	!isflagset(ticket->enc_part2->flags,TKT_FLG_HW_AUTH)) {
+	*status = "NO HW PREAUTH";
+	return KRB_ERR_GENERIC;
+    }
+
+    /* Check for any kind of preauthentication */
+    if (isflagset(server.attributes, KRB5_KDB_REQUIRES_PRE_AUTH) &&
+	!isflagset(ticket->enc_part2->flags, TKT_FLG_PRE_AUTH)) {
+	*status = "NO PREAUTH";
+	return KRB_ERR_GENERIC;
+    }
+    
+    /*
+     * Check local policy
+     */
+    errcode = against_local_policy_tgs(request, server, ticket, status);
+    if (errcode)
+	return errcode;
+    
+    
+    return 0;
+}
+
+/*
+ * This function returns 1 if the dbentry has a key for a specified
+ * keytype, and 0 if not.
+ */
+int
+dbentry_has_key_for_enctype(krb5_context context, krb5_db_entry *client,
+			    krb5_enctype enctype)
+{
+    krb5_error_code	retval;
+    krb5_key_data	*datap;
+
+    retval = krb5_dbe_find_enctype(context, client, enctype,
+				   -1, 0, &datap);
+    if (retval)
+	return 0;
+    else
+	return 1;
+}
+
+/*
+ * This function returns 1 if the entity referenced by this
+ * structure can support the a particular encryption system, and 0 if
+ * not.
+ *
+ * XXX eventually this information should be looked up in the
+ * database.  Since it isn't, we use some hueristics and attribute
+ * options bits for now.
+ */
+int
+dbentry_supports_enctype(krb5_context context, krb5_db_entry *client,
+			 krb5_enctype enctype)
+{
+    /*
+     * If it's DES_CBC_MD5, there's a bit in the attribute mask which
+     * checks to see if we support it.  For now, treat it as always
+     * clear.
+     *
+     * In theory everything's supposed to support DES_CBC_MD5, but
+     * that's not the reality....
+     */
+    if (enctype == ENCTYPE_DES_CBC_MD5)
+	return 0;
+
+    /*
+     * XXX we assume everything can understand DES_CBC_CRC
+     */
+    if (enctype == ENCTYPE_DES_CBC_CRC)
+	return 1;
+    
+    /*
+     * If we have a key for the encryption system, we assume it's
+     * supported.
+     */
+    return dbentry_has_key_for_enctype(context, client, enctype);
+}
+
+/*
+ * This function returns the keytype which should be selected for the
+ * session key.  It is based on the ordered list which the user
+ * requested, and what the KDC and the application server can support.
+ */
+krb5_enctype
+select_session_keytype(krb5_context context, krb5_db_entry *server,
+		       int nktypes, krb5_enctype *ktype)
+{
+    int		i;
+    
+    for (i = 0; i < nktypes; i++) {
+	if (!krb5_c_valid_enctype(ktype[i]))
+	    continue;
+
+	if (!krb5_is_permitted_enctype(context, ktype[i]))
+	    continue;
+
+	if (dbentry_supports_enctype(context, server, ktype[i]))
+	    return ktype[i];
+    }
+    return 0;
+}
+
+/*
+ * This function returns salt information for a particular client_key
+ */
+krb5_error_code
+get_salt_from_key(krb5_context context, krb5_principal client,
+		  krb5_key_data *client_key, krb5_data *salt)
+{
+    krb5_error_code		retval;
+    krb5_data *			realm;
+    
+    salt->data = 0;
+    salt->length = SALT_TYPE_NO_LENGTH;
+    
+    if (client_key->key_data_ver == 1)
+	return 0;
+
+    switch (client_key->key_data_type[1]) {
+    case KRB5_KDB_SALTTYPE_NORMAL:
+	break;
+    case KRB5_KDB_SALTTYPE_V4:
+	/* send an empty (V4) salt */
+	salt->data = 0;
+	salt->length = 0;
+	break;
+    case KRB5_KDB_SALTTYPE_NOREALM:
+	if ((retval = krb5_principal2salt_norealm(context, client, salt)))
+	    return retval;
+	break;
+    case KRB5_KDB_SALTTYPE_AFS3:
+	/* send the same salt as with onlyrealm - but with no type info,
+	   we just hope they figure it out on the other end. */
+	/* fall through to onlyrealm: */
+    case KRB5_KDB_SALTTYPE_ONLYREALM:
+	realm = krb5_princ_realm(context, client);
+	salt->length = realm->length;
+	if ((salt->data = malloc(realm->length)) == NULL)
+	    return ENOMEM;
+	memcpy(salt->data, realm->data, realm->length);
+	break;
+    case KRB5_KDB_SALTTYPE_SPECIAL:
+	salt->length = client_key->key_data_length[1];
+	if ((salt->data = malloc(salt->length)) == NULL)
+	    return ENOMEM;
+	memcpy(salt->data, client_key->key_data_contents[1], salt->length);
+	break;
+    }
+    return 0;
+}
+
+/*
+ * Limit strings to a "reasonable" length to prevent crowding out of
+ * other useful information in the log entry
+ */
+#define NAME_LENGTH_LIMIT 128
+
+void limit_string(char *name)
+{
+	int	i;
+
+	if (!name)
+		return;
+
+	if (strlen(name) < NAME_LENGTH_LIMIT)
+		return;
+
+	i = NAME_LENGTH_LIMIT-4;
+	name[i++] = '.';
+	name[i++] = '.';
+	name[i++] = '.';
+	name[i] = '\0';
+	return;
+}
+
+/*
+ * L10_2 = log10(2**x), rounded up; log10(2) ~= 0.301.
+ */
+#define L10_2(x) ((int)(((x * 301) + 999) / 1000))
+
+/*
+ * Max length of sprintf("%ld") for an int of type T; includes leading
+ * minus sign and terminating NUL.
+ */
+#define D_LEN(t) (L10_2(sizeof(t) * CHAR_BIT) + 2)
+
+void
+ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype)
+{
+    int i;
+    char stmp[D_LEN(krb5_enctype) + 1];
+    char *p;
+
+    if (nktypes < 0
+	|| len < (sizeof(" etypes {...}") + D_LEN(int))) {
+	*s = '\0';
+	return;
+    }
+
+    sprintf(s, "%d etypes {", nktypes);
+    for (i = 0; i < nktypes; i++) {
+	sprintf(stmp, "%s%ld", i ? " " : "", (long)ktype[i]);
+	if (strlen(s) + strlen(stmp) + sizeof("}") > len)
+	    break;
+	strcat(s, stmp);
+    }
+    if (i < nktypes) {
+	/*
+	 * We broke out of the loop. Try to truncate the list.
+	 */
+	p = s + strlen(s);
+	while (p - s + sizeof("...}") > len) {
+	    while (p > s && *p != ' ' && *p != '{')
+		*p-- = '\0';
+	    if (p > s && *p == ' ') {
+		*p-- = '\0';
+		continue;
+	    }
+	}
+	strcat(s, "...");
+    }
+    strcat(s, "}");
+    return;
+}
+
+void
+rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep)
+{
+    char stmp[sizeof("ses=") + D_LEN(krb5_enctype)];
+
+    if (len < (3 * D_LEN(krb5_enctype)
+	       + sizeof("etypes {rep= tkt= ses=}"))) {
+	*s = '\0';
+	return;
+    }
+
+    sprintf(s, "etypes {rep=%ld", (long)rep->enc_part.enctype);
+
+    if (rep->ticket != NULL) {
+	sprintf(stmp, " tkt=%ld", (long)rep->ticket->enc_part.enctype);
+	strcat(s, stmp);
+    }
+
+    if (rep->ticket != NULL
+	&& rep->ticket->enc_part2 != NULL
+	&& rep->ticket->enc_part2->session != NULL) {
+	sprintf(stmp, " ses=%ld",
+		(long)rep->ticket->enc_part2->session->enctype);
+	strcat(s, stmp);
+    }
+    strcat(s, "}");
+    return;
+}
diff --git a/krb5-1-6/src/kdc/kdc_util.h b/krb5-1-6/src/kdc/kdc_util.h
new file mode 100644
index 000000000..7fefb964e
--- /dev/null
+++ b/krb5-1-6/src/kdc/kdc_util.h
@@ -0,0 +1,206 @@
+/*
+ * kdc/kdc_util.h
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Declarations for policy.c
+ */
+
+#ifndef __KRB5_KDC_UTIL__
+#define __KRB5_KDC_UTIL__
+
+#include "kdb.h"
+
+typedef struct _krb5_fulladdr {
+    krb5_address *	address;
+    krb5_ui_4		port;
+} krb5_fulladdr;
+
+krb5_error_code check_hot_list (krb5_ticket *);
+krb5_boolean realm_compare (krb5_principal, krb5_principal);
+krb5_boolean krb5_is_tgs_principal (krb5_principal);
+krb5_error_code add_to_transited (krb5_data *,
+					    krb5_data *,
+					    krb5_principal,
+					    krb5_principal,
+					    krb5_principal);
+krb5_error_code compress_transited (krb5_data *,
+					      krb5_principal,
+					      krb5_data *);
+krb5_error_code concat_authorization_data (krb5_authdata **,
+						     krb5_authdata **,
+						     krb5_authdata ***);
+krb5_error_code fetch_last_req_info (krb5_db_entry *,
+					       krb5_last_req_entry ***);
+
+krb5_error_code kdc_convert_key (krb5_keyblock *,
+					   krb5_keyblock *,
+					   int);
+krb5_error_code kdc_process_tgs_req 
+	(krb5_kdc_req *,
+	           const krb5_fulladdr *,
+	           krb5_data *,
+	           krb5_ticket **,
+	           krb5_keyblock **);
+
+krb5_error_code kdc_get_server_key (krb5_ticket *,
+					      krb5_keyblock **,
+					      krb5_kvno *);
+
+int validate_as_request (krb5_kdc_req *, krb5_db_entry, 
+					  krb5_db_entry, krb5_timestamp,
+					  const char **);
+
+int validate_tgs_request (krb5_kdc_req *, krb5_db_entry, 
+					  krb5_ticket *, krb5_timestamp,
+					  const char **);
+
+int fetch_asn1_field (unsigned char *, unsigned int, unsigned int,
+				 krb5_data *);
+
+int
+dbentry_has_key_for_enctype (krb5_context context,
+				       krb5_db_entry *client,
+				       krb5_enctype enctype);
+    
+int
+dbentry_supports_enctype (krb5_context context,
+				    krb5_db_entry *client,
+				    krb5_enctype enctype);
+
+krb5_enctype
+select_session_keytype (krb5_context context,
+				  krb5_db_entry *server,
+				  int nktypes,
+				  krb5_enctype *ktypes);
+
+krb5_error_code
+get_salt_from_key (krb5_context, krb5_principal,
+			     krb5_key_data *, krb5_data *);
+
+void limit_string (char *name);
+
+void
+ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype);
+
+void
+rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep);
+
+/* do_as_req.c */
+krb5_error_code process_as_req (krb5_kdc_req *, krb5_data *,
+					  const krb5_fulladdr *,
+					  krb5_data ** );
+
+/* do_tgs_req.c */
+krb5_error_code process_tgs_req (krb5_data *,
+					   const krb5_fulladdr *,
+					   krb5_data ** );
+/* dispatch.c */
+krb5_error_code dispatch (krb5_data *,
+				    const krb5_fulladdr *,
+				    krb5_data **);
+
+/* main.c */
+krb5_error_code kdc_initialize_rcache (krb5_context, char *);
+
+krb5_error_code setup_server_realm (krb5_principal);
+
+/* network.c */
+krb5_error_code listen_and_process (const char *);
+krb5_error_code setup_network (const char *);
+krb5_error_code closedown_network (const char *);
+
+/* policy.c */
+int against_local_policy_as (krb5_kdc_req *, krb5_db_entry,
+					krb5_db_entry, krb5_timestamp,
+					const char **);
+
+int against_local_policy_tgs (krb5_kdc_req *, krb5_db_entry,
+					krb5_ticket *, const char **);
+
+/* kdc_preauth.c */
+const char * missing_required_preauth
+    (krb5_db_entry *client, krb5_db_entry *server,
+	       krb5_enc_tkt_part *enc_tkt_reply);
+void get_preauth_hint_list (krb5_kdc_req * request,
+				      krb5_db_entry *client,
+				      krb5_db_entry *server,
+				      krb5_data *e_data);
+krb5_error_code load_preauth_plugins(krb5_context context);
+krb5_error_code unload_preauth_plugins(krb5_context context);
+
+krb5_error_code check_padata
+    (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
+	       krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
+	       void **padata_context, krb5_data *e_data);
+    
+krb5_error_code return_padata
+    (krb5_context context, krb5_db_entry *client,
+	       krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
+	       krb5_key_data *client_key, krb5_keyblock *encrypting_key,
+	       void **padata_context);
+    
+krb5_error_code free_padata_context
+    (krb5_context context, void **padata_context);
+
+/* replay.c */
+krb5_boolean kdc_check_lookaside (krb5_data *, krb5_data **);
+void kdc_insert_lookaside (krb5_data *, krb5_data *);
+void kdc_free_lookaside(krb5_context);
+
+/* which way to convert key? */
+#define CONVERT_INTO_DB	0
+#define CONVERT_OUTOF_DB 1
+
+#define isflagset(flagfield, flag) (flagfield & (flag))
+#define setflag(flagfield, flag) (flagfield |= (flag))
+#define clear(flagfield, flag) (flagfield &= ~(flag))
+
+#ifdef KRB5_KRB4_COMPAT
+krb5_error_code process_v4 (const krb5_data *,
+				      const krb5_fulladdr *,
+				      krb5_data **);
+void process_v4_mode (const char *, const char *);
+void enable_v4_crossrealm(char *);
+#else
+#define process_v4(foo,bar,quux,foobar)	KRB5KRB_AP_ERR_BADVERSION
+#endif
+
+#ifndef	min
+#define	min(a, b)	((a) < (b) ? (a) : (b))
+#define	max(a, b)	((a) > (b) ? (a) : (b))
+#endif
+
+#ifdef KRB5_USE_INET6
+#define ADDRTYPE2FAMILY(X) \
+  ((X) == ADDRTYPE_INET6 ? AF_INET6 : (X) == ADDRTYPE_INET ? AF_INET : -1)
+#else
+#define ADDRTYPE2FAMILY(X) \
+  ((X) == ADDRTYPE_INET ? AF_INET : -1)
+#endif
+
+/* RFC 4120: KRB5KDC_ERR_KEY_TOO_WEAK
+ * RFC 4556: KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED */
+#define KRB5KDC_ERR_KEY_TOO_WEAK KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
+
+#endif /* __KRB5_KDC_UTIL__ */
diff --git a/krb5-1-6/src/kdc/kerberos_v4.c b/krb5-1-6/src/kdc/kerberos_v4.c
new file mode 100644
index 000000000..9f93e451e
--- /dev/null
+++ b/krb5-1-6/src/kdc/kerberos_v4.c
@@ -0,0 +1,1198 @@
+/*
+ * kdc/kerberos_v4.c
+ *
+ * Copyright 1985, 1986, 1987, 1988,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "autoconf.h"
+#ifdef KRB5_KRB4_COMPAT
+#define BACKWARD_COMPAT
+
+#include "k5-int.h"
+#include "kdc_util.h"
+#include "adm_proto.h"
+
+#include <stdarg.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <signal.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#include <time.h>
+#endif
+#include <sys/file.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+
+/* v4 include files:
+ */
+#include <krb.h>
+#include <des.h>
+#include <klog.h>
+#include <prot.h>
+#include <krb_db.h>
+
+#ifdef NEED_SWAB_PROTO
+extern void swab(const void *, void *, size_t );
+#endif
+
+static int compat_decrypt_key (krb5_key_data *, C_Block,
+					 krb5_keyblock *, int);
+static int kerb_get_principal (char *, char *, Principal *,
+					 int *, krb5_keyblock *, krb5_kvno,
+					 int, krb5_deltat *);
+static int check_princ (char *, char *, int, Principal *,
+				  krb5_keyblock *, int, krb5_deltat *);
+
+char * v4_klog (int, const char *, ...);
+#define klog v4_klog
+
+/* take this out when we don't need it anymore */
+int krbONE = 1;
+/* XXX inline former contents of krb_conf.h for now */
+/* Byte ordering */
+extern int krbONE;
+#define		HOST_BYTE_ORDER	(* (char *) &krbONE)
+#define		MSB_FIRST		0	/* 68000, IBM RT/PC */
+#define		LSB_FIRST		1	/* Vax, PC8086 */
+
+int     f;
+
+/* XXX several files in libkdb know about this */
+char *progname;
+
+#ifndef BACKWARD_COMPAT
+static Key_schedule master_key_schedule;
+static C_Block master_key;
+#endif
+
+static struct timeval kerb_time;
+static Principal a_name_data;	/* for requesting user */
+static Principal s_name_data;	/* for services requested */
+static C_Block session_key;
+
+static char log_text[512];
+static char *lt;
+
+/* fields within the received request packet */
+static u_char req_msg_type;
+static u_char req_version;
+static char *req_name_ptr;
+static char *req_inst_ptr;
+static char *req_realm_ptr;
+
+static krb5_ui_4 req_time_ws;
+
+static char local_realm[REALM_SZ];
+
+static long n_auth_req;
+static long n_appl_req;
+
+static long pause_int = -1;
+
+static void hang(void);
+
+
+/* v4/v5 backwards-compatibility stub routines,
+ * which allow the v5 server to handle v4 packets
+ * by invoking substantially-unaltered v4 server code.
+ * this is only necessary during the installation's conversion to v5.
+ * process_v4() is invoked by v5's dispatch() routine;
+ * when the v4 server needs to access the v5 database,
+ * it calls the other stubs.
+ *
+ * until all kerberized application-programs are updated,
+ * this approach inflates the v5 server's code size,
+ * but it's easier to debug than a concurrent, subordinate v4 server would be.
+ */
+
+/*
+ * v5 include files:
+ */
+#include "com_err.h"
+#include "extern.h"		/* to pick up master_princ */
+
+static krb5_data *response;
+
+void kerberos_v4 (struct sockaddr_in *, KTEXT);
+void kerb_err_reply (struct sockaddr_in *, KTEXT, long, char *);
+static int set_tgtkey (char *, krb5_kvno, krb5_boolean);
+
+/* Attributes converted from V5 to V4 - internal representation */
+#define V4_KDB_REQUIRES_PREAUTH  0x1
+#define V4_KDB_DISALLOW_ALL_TIX  0x2
+#define V4_KDB_REQUIRES_PWCHANGE 0x4
+#define V4_KDB_DISALLOW_SVR      0x8
+
+/* v4 compatibitly mode switch */
+#define KDC_V4_NONE		0	/* Don't even respond to packets */
+#define KDC_V4_DISABLE		1	/* V4 requests return an error */
+#define	KDC_V4_FULL		2	/* Preauth required go through */
+#define KDC_V4_NOPREAUTH	3	/* Preauth required disallowed */
+
+#define KDC_V4_DEFAULT_MODE KDC_V4_NONE
+/* Flag on how to handle v4 */
+static int		kdc_v4;
+
+struct v4mode_lookup_entry {
+    int                 mode;                   /* Mode setting */
+    const char *	v4_specifier;		/* How to recognize it	*/
+};
+
+static const struct v4mode_lookup_entry  v4mode_table[] = {
+/*  mode                input specifier */
+{ KDC_V4_NONE,          "none"          },
+{ KDC_V4_DISABLE,       "disable"       }, 
+{ KDC_V4_FULL,          "full"          },
+{ KDC_V4_NOPREAUTH,     "nopreauth"     }
+};
+
+static const int v4mode_table_nents = sizeof(v4mode_table)/
+				      sizeof(v4mode_table[0]);
+
+static int allow_v4_crossrealm = 0;
+
+void process_v4_mode(const char *program_name, const char *string)
+{
+    int i, found;
+
+    found = 0;
+    kdc_v4 = KDC_V4_DEFAULT_MODE;
+
+    if(!string) return;  /* Set to default mode */
+    
+    for (i=0; i<v4mode_table_nents; i++) {
+	if (!strcasecmp(string, v4mode_table[i].v4_specifier)) {
+	    found = 1;
+	    kdc_v4 = v4mode_table[i].mode;
+	    break;
+	}
+    }
+
+    if(!found) {
+      /* It is considered fatal if we request a mode that is not found */
+	com_err(program_name, 0, "invalid v4_mode %s", string);
+	exit(1);
+    }
+    return;
+}
+
+void enable_v4_crossrealm ( char *programname) {
+    allow_v4_crossrealm = 1;
+    krb5_klog_syslog(LOG_ERR, "Enabling v4 cross-realm compatibility; this is a known security hole");
+}
+
+krb5_error_code
+process_v4(const krb5_data *pkt, const krb5_fulladdr *client_fulladdr,
+	   krb5_data **resp)
+{
+    struct sockaddr_in client_sockaddr;
+    krb5_address *addr = client_fulladdr->address;
+    krb5_error_code retval;
+    krb5_timestamp now;
+    KTEXT_ST v4_pkt;
+    char *lrealm;
+
+    /* Check if disabled completely */
+    if (kdc_v4 == KDC_V4_NONE) {
+	(void) klog(L_KRB_PERR, "Disabled KRB V4 request");
+	return KRB5KDC_ERR_BAD_PVNO;
+    }
+
+    
+    if ((retval = krb5_timeofday(kdc_context, &now)))
+        return(retval);
+    kerb_time.tv_sec = now;
+
+    if (!*local_realm) {		/* local-realm name already set up */
+	lrealm = master_princ->realm.data;
+	if (master_princ->realm.length < sizeof(local_realm)) {
+	    memcpy(local_realm, lrealm, master_princ->realm.length);
+	    local_realm[master_princ->realm.length] = '\0';
+	} else
+	    retval = KRB5_CONFIG_NOTENUFSPACE;
+    }
+    /* convert client_fulladdr to client_sockaddr:
+     */
+    client_sockaddr.sin_family	= AF_INET;
+    client_sockaddr.sin_port	= client_fulladdr->port;
+    if (client_fulladdr->address->addrtype != ADDRTYPE_INET) {
+	klog(L_KRB_PERR, "got krb4 request from non-ipv4 address");
+	client_sockaddr.sin_addr.s_addr = 0;
+    } else
+	memcpy(&client_sockaddr.sin_addr, addr->contents, 
+	       sizeof client_sockaddr.sin_addr);
+    memset( client_sockaddr.sin_zero, 0, sizeof client_sockaddr.sin_zero);
+
+    /* convert v5 packet structure to v4's.
+     * this copy is gross, but necessary:
+     */
+    if (pkt->length > MAX_KTXT_LEN) {
+	    (void) klog(L_KRB_PERR, "V4 request too long.");
+	    return KRB5KRB_ERR_FIELD_TOOLONG;
+    }
+    v4_pkt.length = pkt->length;
+    v4_pkt.mbz = 0;
+    memcpy( v4_pkt.dat, pkt->data, pkt->length);
+
+    kerberos_v4( &client_sockaddr, &v4_pkt);
+    *resp = response;
+    return(retval);
+}
+
+char * v4_klog( int type, const char *format, ...)
+{
+    int logpri = LOG_INFO;
+    va_list pvar;
+    va_start(pvar, format);
+
+    switch (type) {
+    case L_ERR_SEXP:
+    case L_ERR_NKY:
+    case L_ERR_NUN:
+    case L_ERR_UNK:
+    case L_KRB_PERR:
+	logpri = LOG_ERR;
+    case L_INI_REQ:
+    case L_NTGT_INTK:
+    case L_TKT_REQ:
+    case L_APPL_REQ:
+	strcpy(log_text, "PROCESS_V4:");
+	vsprintf(log_text+strlen(log_text), format, pvar);
+	krb5_klog_syslog(logpri, "%s", log_text);
+    default:
+	/* ignore the other types... */
+	;
+    }
+    va_end(pvar);
+    return(log_text);
+}
+
+static
+int krb4_sendto(int s, const char *msg, int len, int flags,
+		const struct sockaddr *to, int to_len)
+{
+    if (  !(response = (krb5_data *) malloc( sizeof *response))) {
+	return ENOMEM;
+    }
+    if ( !(response->data = (char *) malloc( len))) {
+	krb5_free_data(kdc_context,  response);
+	return ENOMEM;
+    }
+    response->length = len;
+    memcpy( response->data, msg, len);
+    return( 0);
+}
+static void
+hang(void)
+{
+    if (pause_int == -1) {
+        klog(L_KRB_PERR, "Kerberos will pause so as not to loop init");
+     /* for (;;)
+            pause(); */
+    } else {
+        char buf[256];
+        sprintf(buf,
+	   "Kerberos will wait %d seconds before dying so as not to loop init",
+		(int) pause_int);
+        klog(L_KRB_PERR, buf);
+        sleep((unsigned) pause_int);
+        klog(L_KRB_PERR, "Do svedania....\n");
+     /* exit(1); */
+    }
+}
+#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.
+ */
+static int
+compat_decrypt_key (krb5_key_data *in5, unsigned char *out4,
+		    krb5_keyblock *out5, int issrv)
+{
+    krb5_error_code retval;
+
+    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 (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_CBC_SHA1 )
+		out5->enctype = ENCTYPE_DES3_CBC_RAW;
+	}
+    }
+    return(retval);
+}
+
+/* array of name-components + NULL ptr
+ */
+
+/*
+ * Previously this code returned either a v4 key or a v5 key  and you
+ * could tell from the enctype of the v5 key whether the v4 key was
+ * useful.  Now we return both keys so the code can try both des3 and
+ * des decryption.  We fail if the ticket doesn't have a v4 key.
+ * Also, note as a side effect, the v5 key is basically useless  in
+ * the client case.  It is still returned so the caller can free it.
+ */
+static int
+kerb_get_principal(char *name, char *inst, /* could have wild cards */
+		   Principal *principal,
+		   int *more,	/* more tuples than room for */
+		   krb5_keyblock *k5key, krb5_kvno kvno,
+		   int issrv,	/* true if retrieving a service key */
+		   krb5_deltat *k5life)
+{
+    /* Note that this structure should not be passed to the
+       krb5_free* functions, because the pointers within it point
+       to data with other references.  */
+    krb5_principal search;
+
+    krb5_db_entry entries;	/* filled in by krb5_db_get_principal() */
+    int nprinc;			/* how many found */
+    krb5_boolean more5;		/* are there more? */
+    C_Block k;
+    short toggle = 0;
+    unsigned long *date;
+    char* text;
+    struct tm *tp;
+    krb5_key_data *pkey;
+    krb5_error_code retval;
+
+    *more = 0;
+    /* begin setting up the principal structure
+     * with the first info we have:
+     */
+    memcpy( principal->name,     name, 1 + strlen( name));
+    memcpy( principal->instance, inst, 1 + strlen( inst));
+
+    /* the principal-name format changed between v4 & v5:
+     *     v4: name.instance@realm
+     *     v5: realm/name/instance
+     *     in v5, null instance means the null-component doesn't exist.
+     */
+
+    if ((retval = krb5_425_conv_principal(kdc_context, name, inst, 
+					  local_realm, &search)))
+	return(0);
+
+    if ((retval = krb5_db_get_principal(kdc_context, search, &entries, 
+					&nprinc, &more5))) {
+        krb5_free_principal(kdc_context, search);
+        return(0);
+    }
+    principal->key_low = principal->key_high = 0;
+    krb5_free_principal(kdc_context, search);
+
+    if (nprinc < 1) {
+        *more = (int)more5 || (nprinc > 1);
+        return(nprinc);
+    } 
+
+    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 {
+	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: failed to find key for %s.%s #%d",
+		      name, inst, kvno);
+	    krb5_db_free_principal(kdc_context, &entries, nprinc);
+	    return(0);
+	}
+    }
+
+    if (!compat_decrypt_key(pkey, k, k5key, issrv)) {
+ 	memcpy( &principal->key_low, k, LONGLEN);
+       	memcpy( &principal->key_high, (krb5_ui_4 *) k + 1, LONGLEN);
+    }
+    memset(k, 0, sizeof k);
+    if (issrv) {
+	krb5_free_keyblock_contents (kdc_context, k5key);
+      	if (krb5_dbe_find_enctype(kdc_context, &entries,
+				  ENCTYPE_DES3_CBC_RAW,
+				  -1, kvno, &pkey) &&
+	    krb5_dbe_find_enctype(kdc_context, &entries,
+				  ENCTYPE_DES3_CBC_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 #%d (after having found it once)",
+		      name, inst, kvno);
+	    krb5_db_free_principal(kdc_context, &entries, nprinc);
+	    return(0);
+	}
+	compat_decrypt_key(pkey, k, k5key, issrv);
+	memset (k, 0, sizeof k);
+    }
+
+
+    /*
+     * Convert v5's entries struct to v4's Principal struct:
+     * v5's time-unit for lifetimes is 1 sec, while v4 uses 5 minutes,
+     * and gets weirder above (128 * 300) seconds.
+     */
+    principal->max_life = krb_time_to_life(0, entries.max_life);
+    if (k5life != NULL)
+	*k5life = entries.max_life;
+    /*
+     * This is weird, but the intent is that the expiration is the minimum
+     * of the principal expiration and key expiration
+     */
+    principal->exp_date = (unsigned long) 
+        entries.expiration && entries.pw_expiration ?
+        min(entries.expiration, entries.pw_expiration) :
+        (entries.pw_expiration ? entries.pw_expiration :
+        entries.expiration);
+/*    principal->mod_date = (unsigned long) entries.mod_date; */
+/* Set the master key version to 1. It's not really useful because all keys
+ * will be encrypted in the same master key version, and digging out the 
+ * actual key version will be harder than it's worth --proven */
+/*    principal->kdc_key_ver = entries.mkvno; */
+    principal->kdc_key_ver = 1;
+    principal->key_version = pkey->key_data_kvno;
+    /* We overload the attributes with the relevant v5 ones */
+    principal->attributes = 0;
+    if (isflagset(entries.attributes,  KRB5_KDB_REQUIRES_HW_AUTH) ||
+	isflagset(entries.attributes,  KRB5_KDB_REQUIRES_PRE_AUTH)) {
+          principal->attributes |= V4_KDB_REQUIRES_PREAUTH;
+    }
+    if (isflagset(entries.attributes,  KRB5_KDB_DISALLOW_ALL_TIX)) {
+          principal->attributes |= V4_KDB_DISALLOW_ALL_TIX;
+    }
+    if (issrv && isflagset(entries.attributes, KRB5_KDB_DISALLOW_SVR)) {
+	principal->attributes |= V4_KDB_DISALLOW_SVR;
+    }
+    if (isflagset(entries.attributes,  KRB5_KDB_REQUIRES_PWCHANGE)) {
+          principal->attributes |= V4_KDB_REQUIRES_PWCHANGE;
+    }
+
+    /* set up v4 format of each date's text: */
+    for ( date = &principal->exp_date, text = principal->exp_date_txt;
+	  toggle ^= 1;
+	  date = &principal->mod_date, text = principal->mod_date_txt) {
+	tp = localtime( (time_t *) date);
+	sprintf( text, "%4d-%02d-%02d",
+		 tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900,
+		 tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */
+    }
+    /*
+     * free the storage held by the v5 entry struct,
+     * which was allocated by krb5_db_get_principal().
+     * this routine clears the keyblock's contents for us.
+     */
+    krb5_db_free_principal(kdc_context, &entries, nprinc);
+    *more = (int) more5 || (nprinc > 1);
+    return( nprinc);
+}
+
+static void str_length_check(char *str, int max_size)
+{
+	int	i;
+	char	*cp;
+
+	for (i=0, cp = str; i < max_size-1; i++, cp++) {
+		if (*cp == 0)
+			return;
+	}
+	*cp = 0;
+}
+
+void
+kerberos_v4(struct sockaddr_in *client, KTEXT pkt)
+{
+    static KTEXT_ST rpkt_st;
+    KTEXT   rpkt = &rpkt_st;
+    static KTEXT_ST ciph_st;
+    KTEXT   ciph = &ciph_st;
+    static KTEXT_ST tk_st;
+    KTEXT   tk = &tk_st;
+    static KTEXT_ST auth_st;
+    KTEXT   auth = &auth_st;
+    AUTH_DAT ad_st;
+    AUTH_DAT *ad = &ad_st;
+
+
+    static struct in_addr client_host;
+    static int msg_byte_order;
+    static int swap_bytes;
+    static u_char k_flags;
+ /* char   *p_name, *instance; */
+    int     lifetime = 0;
+    int     i;
+    C_Block key;
+    Key_schedule key_s;
+    char   *ptr;
+
+    krb5_keyblock k5key;
+    krb5_kvno kvno;
+    krb5_deltat sk5life, ck5life;
+    KRB4_32 v4endtime, v4req_end;
+
+    k5key.contents = NULL;	/* in case we have to free it */
+
+    ciph->length = 0;
+
+    client_host = client->sin_addr;
+
+    /* eval macros and correct the byte order and alignment as needed */
+    req_version = pkt_version(pkt);	/* 1 byte, version */
+    req_msg_type = pkt_msg_type(pkt);	/* 1 byte, Kerberos msg type */
+
+    /* set these to point to something safe */
+    req_name_ptr = req_inst_ptr = req_realm_ptr = "";
+
+    /* check if disabled, but we tell client */
+    if (kdc_v4 == KDC_V4_DISABLE) {
+	lt = klog(L_KRB_PERR,
+	"KRB will not handle v4 request from %s",
+		  inet_ntoa(client_host));
+	/* send an error reply */
+	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
+	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
+	return;
+    }
+
+    /* check packet version */
+    if (req_version != KRB_PROT_VERSION) {
+	lt = klog(L_KRB_PERR,
+	"KRB prot version mismatch: KRB =%d request = %d",
+		  KRB_PROT_VERSION, req_version, 0);
+	/* send an error reply */
+	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
+	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
+	return;
+    }
+    msg_byte_order = req_msg_type & 1;
+
+    swap_bytes = 0;
+    if (msg_byte_order != HOST_BYTE_ORDER) {
+	swap_bytes++;
+    }
+    klog(L_KRB_PINFO,
+	"Prot version: %d, Byte order: %d, Message type: %d",
+	 (int) req_version, msg_byte_order, req_msg_type);
+
+    switch (req_msg_type & ~1) {
+
+    case AUTH_MSG_KDC_REQUEST:
+	{
+	    int    req_life;	/* Requested liftime */
+	    unsigned int request_backdate =  0; /*How far to backdate
+						  in seconds.*/
+	    char   *service;	/* Service name */
+	    char   *instance;	/* Service instance */
+#ifdef notdef
+	    int     kerno;	/* Kerberos error number */
+#endif
+	    n_auth_req++;
+	    tk->length = 0;
+	    k_flags = 0;	/* various kerberos flags */
+
+
+	    /* set up and correct for byte order and alignment */
+	    req_name_ptr = (char *) pkt_a_name(pkt);
+	    str_length_check(req_name_ptr, ANAME_SZ);
+	    req_inst_ptr = (char *) pkt_a_inst(pkt);
+	    str_length_check(req_inst_ptr, INST_SZ);
+	    req_realm_ptr = (char *) pkt_a_realm(pkt);
+	    str_length_check(req_realm_ptr, REALM_SZ);
+	    memcpy(&req_time_ws, pkt_time_ws(pkt), sizeof(req_time_ws));
+	    /* time has to be diddled */
+	    if (swap_bytes) {
+		swap_u_long(req_time_ws);
+	    }
+	    ptr = (char *) pkt_time_ws(pkt) + 4;
+
+	    req_life = (*ptr++) & 0xff;
+
+	    service = ptr;
+	    str_length_check(service, SNAME_SZ);
+	    instance = ptr + strlen(service) + 1;
+	    str_length_check(instance, INST_SZ);
+
+	    rpkt = &rpkt_st;
+
+	    klog(L_INI_REQ,
+	    "Initial ticket request Host: %s User: \"%s\" \"%s\"",
+	       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, &k5key, 0, &ck5life))) {
+		kerb_err_reply(client, pkt, i, "check_princ failed");
+		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,
+		    "INITIAL request from %s.%s for %s.%s", req_name_ptr,
+		    req_inst_ptr, service, instance, 0);
+	    /* this does all the checking */
+	    if ((i = check_princ(service, instance, lifetime,
+				 &s_name_data, &k5key, 1, &sk5life))) {
+		kerb_err_reply(client, pkt, i, "check_princ failed");
+		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 */
+	    v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
+	    v4req_end = min(v4req_end, kerb_time.tv_sec + ck5life);
+	    v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life);
+	    lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end);
+	    v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime);
+	    /*
+	     * Adjust issue time backwards if necessary, due to
+	     * roundup in krb_time_to_life().
+	     */
+	    if (v4endtime > v4req_end)
+		request_backdate = v4endtime - v4req_end;
+
+#ifdef NOENCRYPTION
+	    memset(session_key, 0, sizeof(C_Block));
+#else
+	    /* random session key */
+	    des_new_random_key(session_key);
+#endif
+
+	    /* unseal server's key from master key */
+	    memcpy( key,                &s_name_data.key_low,  4);
+	    memcpy( ((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4);
+
+	    s_name_data.key_low = s_name_data.key_high = 0;
+	    kdb_encrypt_key(key, key, master_key,
+			    master_key_schedule, DECRYPT);
+	    /* construct and seal the ticket */
+	    /* We always issue des tickets; the 3des tickets are a broken hack*/
+	    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 - request_backdate,
+			      s_name_data.name, s_name_data.instance,
+			      key);
+
+	    krb5_free_keyblock_contents(kdc_context, &k5key);
+	    memset(key, 0, sizeof(key));
+	    memset(key_s, 0, sizeof(key_s));
+
+	    /*
+	     * get the user's key, unseal it from the server's key, and
+	     * use it to seal the cipher 
+	     */
+
+	    /* a_name_data.key_low a_name_data.key_high */
+	    memcpy( key,                &a_name_data.key_low,  4);
+	    memcpy( ((krb5_ui_4 *) key) + 1, &a_name_data.key_high, 4);
+	    a_name_data.key_low= a_name_data.key_high = 0;
+
+	    /* unseal the a_name key from the master key */
+	    kdb_encrypt_key(key, key, master_key, 
+			    master_key_schedule, DECRYPT);
+
+	    create_ciph(ciph, session_key, s_name_data.name,
+			s_name_data.instance, local_realm, lifetime,
+		  s_name_data.key_version, tk, kerb_time.tv_sec, key);
+
+	    /* clear session key */
+	    memset(session_key, 0, sizeof(session_key));
+
+	    memset(key, 0, sizeof(key));
+
+
+
+	    /* always send a reply packet */
+	    rpkt = create_auth_reply(req_name_ptr, req_inst_ptr,
+		req_realm_ptr, req_time_ws, 0, a_name_data.exp_date,
+		a_name_data.key_version, ciph);
+	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
+		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
+	    memset(&a_name_data, 0, sizeof(a_name_data));
+	    memset(&s_name_data, 0, sizeof(s_name_data));
+	    break;
+	}
+    case AUTH_MSG_APPL_REQUEST:
+	{
+	    krb5_ui_4  time_ws;	/* Workstation time */
+	    int    req_life;	/* Requested liftime */
+	    char   *service;	/* Service name */
+	    char   *instance;	/* Service instance */
+	    int     kerno = 0;	/* Kerberos error number */
+	    unsigned int request_backdate =  0; /*How far to backdate
+						  in seconds.*/
+	    char    tktrlm[REALM_SZ];
+
+	    n_appl_req++;
+	    tk->length = 0;
+	    k_flags = 0;	/* various kerberos flags */
+
+	    auth->mbz = 0;	/* pkt->mbz already zeroed */
+	    auth->length = 4 + strlen((char *)pkt->dat + 3);
+	    if (auth->length + 1 > MAX_KTXT_LEN) {
+		lt = klog(L_KRB_PERR,
+			  "APPL request with realm length too long from %s",
+			  inet_ntoa(client_host));
+		kerb_err_reply(client, pkt, RD_AP_INCON,
+			       "realm length too long");
+		return;
+	    }
+
+	    auth->length += (int) *(pkt->dat + auth->length) +
+		(int) *(pkt->dat + auth->length + 1) + 2;
+	    if (auth->length > MAX_KTXT_LEN) {
+		lt = klog(L_KRB_PERR,
+			  "APPL request with funky tkt or req_id length from %s",
+			  inet_ntoa(client_host));
+		kerb_err_reply(client, pkt, RD_AP_INCON,
+			       "funky tkt or req_id length");
+		return;
+	    }
+
+	    memcpy(auth->dat, pkt->dat, auth->length);
+
+	    strncpy(tktrlm, (char *)auth->dat + 3, REALM_SZ);
+	    tktrlm[REALM_SZ-1] = '\0';
+	    kvno = (krb5_kvno)auth->dat[2];
+	    if ((!allow_v4_crossrealm)&&strcmp(tktrlm, local_realm) != 0) {
+	      lt = klog(L_ERR_UNK,
+			"Cross realm ticket from %s denied by policy,", tktrlm);
+	      kerb_err_reply(client, pkt,
+			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
+		return;
+	    }
+	    if (set_tgtkey(tktrlm, kvno, 0)) {
+	      lt = klog(L_ERR_UNK,
+			  "FAILED set_tgtkey realm %s, kvno %d. Host: %s ",
+			  tktrlm, kvno, inet_ntoa(client_host));
+		/* no better error code */
+		kerb_err_reply(client, pkt,
+			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
+		return;
+	    }
+	    kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
+		ad, 0);
+	    if (kerno) {
+		if (set_tgtkey(tktrlm, kvno, 1)) {
+		    lt = klog(L_ERR_UNK,
+			      "FAILED 3des set_tgtkey realm %s, kvno %d. Host: %s ",
+			      tktrlm, kvno, inet_ntoa(client_host));
+		    /* no better error code */
+		    kerb_err_reply(client, pkt,
+				   KERB_ERR_PRINCIPAL_UNKNOWN, lt);
+		    return;
+		}
+		kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
+				   ad, 0);
+	    }
+
+	    if (kerno) {
+		klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s",
+		     inet_ntoa(client_host), krb_get_err_text(kerno));
+		req_name_ptr = req_inst_ptr = req_realm_ptr = "";
+		kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
+		return;
+	    }
+	    ptr = (char *) pkt->dat + auth->length;
+
+	    memcpy(&time_ws, ptr, 4);
+	    ptr += 4;
+
+	    req_life = (*ptr++) & 0xff;
+
+	    service = ptr;
+	    str_length_check(service, SNAME_SZ);
+	    instance = ptr + strlen(service) + 1;
+	    str_length_check(instance, INST_SZ);
+
+	    klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s",
+	     ad->pname, ad->pinst, ad->prealm,
+	     inet_ntoa(client_host), service, instance, 0);
+	    req_name_ptr = ad->pname;
+	    req_inst_ptr = ad->pinst;
+	    req_realm_ptr = ad->prealm;
+
+	    if (strcmp(ad->prealm, tktrlm)) {
+		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
+		     "Can't hop realms");
+		return;
+	    }
+	    if (!strcmp(service, "changepw")) {
+		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
+		     "Can't authorize password changed based on TGT");
+		return;
+	    }
+	    kerno = check_princ(service, instance, req_life,
+				&s_name_data, &k5key, 1, &sk5life);
+	    if (kerno) {
+		kerb_err_reply(client, pkt, kerno, "check_princ failed");
+		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 */
+	    v4endtime = krb_life_to_time((KRB4_32)ad->time_sec, ad->life);
+	    v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
+	    v4req_end = min(v4endtime, v4req_end);
+	    v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life);
+
+	    lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end);
+	    v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime);
+	    /*
+	     * Adjust issue time backwards if necessary, due to
+	     * roundup in krb_time_to_life().
+	     */
+	    if (v4endtime > v4req_end)
+		request_backdate = v4endtime - v4req_end;
+
+	    /* unseal server's key from master key */
+	    memcpy(key,                &s_name_data.key_low,  4);
+	    memcpy(((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4);
+	    s_name_data.key_low = s_name_data.key_high = 0;
+	    kdb_encrypt_key(key, key, master_key,
+			    master_key_schedule, DECRYPT);
+	    /* construct and seal the ticket */
+
+#ifdef NOENCRYPTION
+	    memset(session_key, 0, sizeof(C_Block));
+#else
+	    /* random session key */
+	    des_new_random_key(session_key);
+#endif
+
+	    /* ALways issue des tickets*/
+	    krb_create_ticket(tk, k_flags, ad->pname, ad->pinst,
+			      ad->prealm, client_host.s_addr,
+			      (char *) session_key, lifetime,
+			      kerb_time.tv_sec - request_backdate,
+			      s_name_data.name, s_name_data.instance,
+			      key);
+	    krb5_free_keyblock_contents(kdc_context, &k5key);
+	    memset(key, 0, sizeof(key));
+	    memset(key_s, 0, sizeof(key_s));
+
+	    create_ciph(ciph, session_key, service, instance,
+			local_realm,
+			lifetime, s_name_data.key_version, tk,
+			kerb_time.tv_sec, ad->session);
+
+	    /* clear session key */
+	    memset(session_key, 0, sizeof(session_key));
+
+	    memset(ad->session, 0, sizeof(ad->session));
+
+	    rpkt = create_auth_reply(ad->pname, ad->pinst,
+				     ad->prealm, time_ws,
+				     0, 0, 0, ciph);
+	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
+		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
+	    memset(&s_name_data, 0, sizeof(s_name_data));
+	    break;
+	}
+
+
+#ifdef notdef_DIE
+    case AUTH_MSG_DIE:
+	{
+	    lt = klog(L_DEATH_REQ,
+	        "Host: %s User: \"%s\" \"%s\" Kerberos killed",
+	        inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
+	    exit(0);
+	}
+#endif /* notdef_DIE */
+
+    default:
+	{
+	    lt = klog(L_KRB_PERR,
+		"Unknown message type: %d from %s port %u",
+		req_msg_type, inet_ntoa(client_host),
+		ntohs(client->sin_port));
+	    break;
+	}
+    }
+}
+
+
+
+/*
+ * kerb_er_reply creates an error reply packet and sends it to the
+ * client. 
+ */
+
+void
+kerb_err_reply(struct sockaddr_in *client, KTEXT pkt, long int err, char *string)
+{
+    static KTEXT_ST e_pkt_st;
+    KTEXT   e_pkt = &e_pkt_st;
+    static char e_msg[128];
+
+    strcpy(e_msg, "\nKerberos error -- ");
+    strncat(e_msg, string, sizeof(e_msg) - 1 - 19);
+    cr_err_reply(e_pkt, req_name_ptr, req_inst_ptr, req_realm_ptr,
+		 req_time_ws, err, e_msg);
+    krb4_sendto(f, (char *) e_pkt->dat, e_pkt->length, 0,
+	   (struct sockaddr *) client, sizeof (struct sockaddr_in));
+
+}
+
+static int
+check_princ(char *p_name, char *instance, int lifetime, Principal *p,
+	    krb5_keyblock *k5key, int issrv, krb5_deltat *k5life)
+{
+    static int n;
+    static int more;
+ /* long trans; */
+
+    n = kerb_get_principal(p_name, instance, p, &more, k5key, 0,
+			   issrv, k5life);
+    klog(L_ALL_REQ,
+	 "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d",
+	 p_name, instance, lifetime, n, 0);
+    
+    if (n < 0) {
+	lt = klog(L_KRB_PERR, "Database unavailable!");
+	p->key_high = p->key_low = 0;    
+	hang();
+    }
+    
+    /*
+     * if more than one p_name, pick one, randomly create a session key,
+     * compute maximum lifetime, lookup authorizations if applicable,
+     * and stuff into cipher. 
+     */
+    if (n == 0) {
+	/* service unknown, log error, skip to next request */
+	lt = klog(L_ERR_UNK, "UNKNOWN \"%s\" \"%s\"", p_name,
+	    instance, 0);
+	return KERB_ERR_PRINCIPAL_UNKNOWN;
+    }
+    if (more) {
+	/* not unique, log error */
+	lt = klog(L_ERR_NUN, "Principal NOT UNIQUE \"%s\" \"%s\"",
+		  p_name, instance, 0);
+	return KERB_ERR_PRINCIPAL_NOT_UNIQUE;
+    }
+
+    /*
+     * Check our V5 stuff first.
+     */
+
+    /*
+     * Does the principal have REQUIRES_PWCHANGE set?
+     */
+    if (isflagset(p->attributes, V4_KDB_REQUIRES_PWCHANGE)) {
+	lt = klog(L_ERR_SEXP, "V5 REQUIRES_PWCHANGE set "
+		  "\"%s\" \"%s\"", p_name, instance);
+	return KERB_ERR_NAME_EXP;
+    }
+
+    /*
+     * Does the principal have DISALLOW_ALL_TIX set?
+     */
+    if (isflagset(p->attributes, V4_KDB_DISALLOW_ALL_TIX)) {
+	lt = klog(L_ERR_SEXP, "V5 DISALLOW_ALL_TIX set: "
+		  "\"%s\" \"%s\"", p_name, instance);
+	/* Not sure of a better error to return */
+	return KERB_ERR_NAME_EXP;
+    }
+
+    if (isflagset(p->attributes, V4_KDB_DISALLOW_SVR)) {
+	lt = klog(L_ERR_SEXP, "V5 DISALLOW_SVR set: "
+		  "\"%s\" \"%s\"", p_name, instance);
+	/* Not sure of a better error to return */
+	return KERB_ERR_NAME_EXP;
+    }
+
+    /*
+     * Does the principal require preauthentication?
+     */
+    if ((kdc_v4 == KDC_V4_NOPREAUTH) &&
+	isflagset(p->attributes, V4_KDB_REQUIRES_PREAUTH)) {
+        lt = klog(L_ERR_SEXP, "V5 REQUIRES_PREAUTH set: "
+		  "\"%s\" \"%s\"", p_name, instance);
+	/* Not sure of a better error to return */
+	return KERB_ERR_AUTH_EXP;
+/*	return KERB_ERR_NAME_EXP;*/
+    }
+
+    /* If the user's key is null, we want to return an error */
+    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)&&
+	((u_long) p->exp_date <(u_long) kerb_time.tv_sec)) {
+	/* service did expire, log it */
+	char timestr[40];
+	struct tm *tm;
+	time_t t = p->exp_date;
+
+	tm = localtime(&t);
+	if (!strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm))
+	    timestr[0] = '\0';
+	lt = klog(L_ERR_SEXP,
+		  "EXPIRED \"%s\" \"%s\"  %s", p->name, p->instance, timestr);
+	return KERB_ERR_NAME_EXP;
+    }
+    /* ok is zero */
+    return 0;
+}
+
+
+/* Set the key for krb_rd_req so we can check tgt */
+static int
+set_tgtkey(char *r, krb5_kvno kvno, krb5_boolean use_3des)
+{
+    int     n;
+    static char lastrealm[REALM_SZ] = "";
+    static int last_kvno = 0;
+    static krb5_boolean last_use_3des = 0;
+    static int more;
+    Principal p_st;
+    Principal *p = &p_st;
+    C_Block key;
+    krb5_keyblock k5key;
+
+    k5key.contents = NULL;
+    if (!strcmp(lastrealm, r) && last_kvno == kvno && last_use_3des == use_3des)
+	return (KSUCCESS);
+
+/*  log("Getting key for %s", r); */
+
+    n = kerb_get_principal("krbtgt", r, p, &more, &k5key, kvno, 1, NULL);
+    if (n == 0)
+	return (KFAILURE);
+
+    if (isflagset(p->attributes, V4_KDB_DISALLOW_ALL_TIX)) {
+	lt = klog(L_ERR_SEXP,
+		  "V5 DISALLOW_ALL_TIX set: \"krbtgt\" \"%s\"", r);
+	krb5_free_keyblock_contents(kdc_context, &k5key);
+	return KFAILURE;
+    }
+
+    if (isflagset(p->attributes, V4_KDB_DISALLOW_SVR)) {
+	lt = klog(L_ERR_SEXP, "V5 DISALLOW_SVR set: \"krbtgt\" \"%s\"", r);
+	krb5_free_keyblock_contents(kdc_context, &k5key);
+	return KFAILURE;
+    }
+
+    if (use_3des&&!K4KDC_ENCTYPE_OK(k5key.enctype)) {
+	krb_set_key_krb5(kdc_context, &k5key);
+	strncpy(lastrealm, r, sizeof(lastrealm) - 1);
+	lastrealm[sizeof(lastrealm) - 1] = '\0';
+	last_kvno = kvno;
+	last_use_3des = use_3des;
+    } 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);
+	strncpy(lastrealm, r, sizeof(lastrealm) - 1);
+	lastrealm[sizeof(lastrealm) - 1] = '\0';
+	last_kvno = kvno;
+    }
+    krb5_free_keyblock_contents(kdc_context, &k5key);
+    return (KSUCCESS);
+}
+
+#else	/* KRB5_KRB4_COMPAT */
+#include "k5-int.h"
+#endif /* KRB5_KRB4_COMPAT */
diff --git a/krb5-1-6/src/kdc/krb5kdc.M b/krb5-1-6/src/kdc/krb5kdc.M
new file mode 100644
index 000000000..2056eecd9
--- /dev/null
+++ b/krb5-1-6/src/kdc/krb5kdc.M
@@ -0,0 +1,188 @@
+.\" kdc/krb5kdc.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\"
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KRB5KDC 8
+.SH NAME
+krb5kdc \- Kerberos V5 KDC
+.SH SYNOPSIS
+.B krb5kdc
+[
+.B \-x
+.I db_args
+] [
+.B \-d
+.I dbname
+] [
+.B \-k
+.I keytype
+] [
+.B \-M
+.I mkeyname
+] [
+.B \-p
+.I portnum
+] [
+.B \-m
+] [
+.B \-r
+.I realm
+] [
+.B \-4
+.I v4mode
+] [
+.B \-n
+]
+.br
+.SH DESCRIPTION
+.I krb5kdc
+is the Kerberos version 5 Authentication Service and Key Distribution
+Center (AS/KDC).
+.PP
+The
+.B \-x
+.I db_args
+option specifies the database specific arguments.
+
+Options supported for LDAP database are:
+.sp 
+.nf 
+.RS 8
+\-x nconns=<number_of_connections>
+.fi
+specifies the number of connections to be maintained per LDAP server.
+
+.nf
+\-x host=<ldapuri>
+specifies the LDAP server to connect to by a LDAP URI.
+
+\-x binddn=<binddn>
+.fi
+specifies the DN of the object used by the KDC server to bind to the LDAP server.
+This object should have the rights to read the realm container, principal container
+and the subtree that is referenced by the realm.
+
+\-x bindpwd=<bind_password>
+.fi
+specifies the password for the above mentioned binddn. It is recommended not to use this option.
+Instead, the password can be stashed using the stashsrvpw command of kdb5_ldap_util.
+.RE
+.fi
+.PP
+The
+.B \-r
+.I realm
+option specifies the realm for which the server should provide service;
+by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.PP
+The
+.B \-d
+.I dbname
+option specifies the name under which the principal database can be found; by
+default the database is in DEFAULT_DBM_FILE.
+This option does not apply to the LDAP database.
+.PP
+The
+.B \-k
+.I keytype
+option specifies the key type of the master key in the database; the default
+is KEYTYPE_DES.
+.PP
+The
+.B \-M
+.I mkeyname
+option specifies the principal name for the master key in the database;
+the default is KRB5_KDB_M_NAME (usually "K/M" in the KDC's realm).
+.PP
+The
+.B \-p
+.I portnum
+option specifies the default UDP port number which the KDC should listen on for
+Kerberos version 5 requests.  This value is used when no port is specified in
+the KDC profile and when no port is specified in the Kerberos configuration
+file.
+If no value is available, then the value in /etc/services for service
+"kerberos" is used.
+.PP
+The
+.B \-m
+option specifies that the master database password should be fetched
+from the keyboard rather than from a file on disk.
+.PP
+The
+.B \-4
+option specifies how the KDC responds to kerberos IV requests for
+tickets.  The command line option overrides the value in the KDC
+profile.  The possible values are 
+.I none,
+.I disable,
+.I full
+or
+.I nopreauth.
+These instruct the KDC to not respond to V4 packets, to
+respond with a version skew error, to issue tickets for all database
+entries, and to issue tickets for all but preauthentication required
+database entries respectively. The default behaviour is as if 
+.I none
+was specified.
+.PP
+The
+.B \-n
+option specifies that the KDC does not put itself in the background
+and does not disassociate itself from the terminal.  In normal
+operation, you should always allow the KDC to place itself in
+the background.
+.PP
+The KDC may service requests for multiple realms (maximum 32 realms).  The
+realms are listed on the command line.  Per-realm options that can be
+specified on the command line pertain for each realm that follows it and are
+superceded by subsequent definitions of the same option.  For example, 
+.PP
+.B krb5kdc
+.B \-p
+.I 2001
+.B \-r
+.I REALM1
+.B \-p
+.I 2002
+.B \-r
+.I REALM2
+.B \-r
+.I REALM3
+.PP
+specifies that the KDC listen on port 2001 for REALM1 and on port 2002 for
+REALM2 and REALM3.  Additionally, per-realm parameters may be specified in the
+.I kdc.conf
+file.  The location of this file may be specified by the
+.I KRB5_KDC_PROFILE
+environment variable.  Parameters specified in this file take precedence over
+options specified on the command line.  See the
+.I kdc.conf(5)
+description for further details.
+.SH SEE ALSO
+krb5(3), kdb5_util(8), kdc.conf(5), kdb5_ldap_util(8)
+.SH BUGS
+
+It should fork and go into the background when it finishes reading the
+master password from the terminal.
diff --git a/krb5-1-6/src/kdc/main.c b/krb5-1-6/src/kdc/main.c
new file mode 100644
index 000000000..282d418af
--- /dev/null
+++ b/krb5-1-6/src/kdc/main.c
@@ -0,0 +1,764 @@
+/*
+ * kdc/main.c
+ *
+ * Copyright 1990,2001 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Main procedure body for the KDC server process.
+ */
+
+#include <stdio.h>
+#include <syslog.h>
+#include <signal.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include "k5-int.h"
+#include "com_err.h"
+#include "adm.h"
+#include "adm_proto.h"
+#include "kdc_util.h"
+#include "extern.h"
+#include "kdc5_err.h"
+#include "kdb_kt.h"
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef KRB5_KRB4_COMPAT
+#include <des.h>
+#endif
+
+#if defined(NEED_DAEMON_PROTO)
+extern int daemon(int, int);
+#endif
+
+void usage (char *);
+
+krb5_sigtype request_exit (int);
+krb5_sigtype request_hup  (int);
+
+void setup_signal_handlers (void);
+
+krb5_error_code setup_sam (void);
+
+void initialize_realms (krb5_context, int, char **);
+
+void finish_realms (char *);
+
+static int nofork = 0;
+static int rkey_init_done = 0;
+
+#ifdef POSIX_SIGNALS
+static struct sigaction s_action;
+#endif /* POSIX_SIGNALS */
+
+#define	KRB5_KDC_MAX_REALMS	32
+
+/*
+ * Find the realm entry for a given realm.
+ */
+kdc_realm_t *
+find_realm_data(char *rname, krb5_ui_4 rsize)
+{
+    int i;
+    for (i=0; i<kdc_numrealms; i++) {
+	if ((rsize == strlen(kdc_realmlist[i]->realm_name)) &&
+	    !strncmp(rname, kdc_realmlist[i]->realm_name, rsize))
+	    return(kdc_realmlist[i]);
+    }
+    return((kdc_realm_t *) NULL);
+}
+
+krb5_error_code
+setup_server_realm(krb5_principal sprinc)
+{
+    krb5_error_code	kret;
+    kdc_realm_t		*newrealm;
+
+    kret = 0;
+    if (kdc_numrealms > 1) {
+	if (!(newrealm = find_realm_data(sprinc->realm.data,
+					 (krb5_ui_4) sprinc->realm.length)))
+	    kret = ENOENT;
+	else
+	    kdc_active_realm = newrealm;
+    }
+    else
+	kdc_active_realm = kdc_realmlist[0];
+    return(kret);
+}
+
+static void
+finish_realm(kdc_realm_t *rdp)
+{
+    if (rdp->realm_dbname)
+	free(rdp->realm_dbname);
+    if (rdp->realm_mpname)
+	free(rdp->realm_mpname);
+    if (rdp->realm_stash)
+	free(rdp->realm_stash);
+    if (rdp->realm_ports)
+	free(rdp->realm_ports);
+    if (rdp->realm_tcp_ports)
+	free(rdp->realm_tcp_ports);
+    if (rdp->realm_keytab)
+	krb5_kt_close(rdp->realm_context, rdp->realm_keytab);
+    if (rdp->realm_context) {
+	if (rdp->realm_mprinc)
+	    krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
+	if (rdp->realm_mkey.length && rdp->realm_mkey.contents) {
+	    memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length);
+	    free(rdp->realm_mkey.contents);
+	}
+	krb5_db_fini(rdp->realm_context);
+	if (rdp->realm_tgsprinc)
+	    krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
+	krb5_free_context(rdp->realm_context);
+    }
+    memset((char *) rdp, 0, sizeof(*rdp));
+    free(rdp);
+}
+
+/*
+ * Initialize a realm control structure from the alternate profile or from
+ * the specified defaults.
+ *
+ * After we're complete here, the essence of the realm is embodied in the
+ * realm data and we should be all set to begin operation for that realm.
+ */
+static krb5_error_code
+init_realm(char *progname, kdc_realm_t *rdp, char *realm, 
+	   char *def_mpname, krb5_enctype def_enctype, char *def_udp_ports,
+	   char *def_tcp_ports, krb5_boolean def_manual, char **db_args)
+{
+    krb5_error_code	kret;
+    krb5_boolean	manual;
+    krb5_realm_params	*rparams;
+
+    memset((char *) rdp, 0, sizeof(kdc_realm_t));
+    if (!realm) {
+	kret = EINVAL;
+	goto whoops;
+    }
+	
+    rdp->realm_name = realm;
+    kret = krb5int_init_context_kdc(&rdp->realm_context);
+    if (kret) {
+	com_err(progname, kret, "while getting context for realm %s",
+		realm);
+	goto whoops;
+    }
+
+    kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name,
+				  &rparams);
+    if (kret) {
+	com_err(progname, kret, "while reading realm parameters");
+	goto whoops;
+    }
+    
+    /* Handle profile file name */
+    if (rparams && rparams->realm_profile)
+	rdp->realm_profile = strdup(rparams->realm_profile);
+
+    /* Handle master key name */
+    if (rparams && rparams->realm_mkey_name)
+	rdp->realm_mpname = strdup(rparams->realm_mkey_name);
+    else
+	rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) :
+	    strdup(KRB5_KDB_M_NAME);
+
+    /* Handle KDC ports */
+    if (rparams && rparams->realm_kdc_ports)
+	rdp->realm_ports = strdup(rparams->realm_kdc_ports);
+    else
+	rdp->realm_ports = strdup(def_udp_ports);
+    if (rparams && rparams->realm_kdc_tcp_ports)
+	rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports);
+    else
+	rdp->realm_tcp_ports = strdup(def_tcp_ports);
+
+    /* Handle stash file */
+    if (rparams && rparams->realm_stash_file) {
+	rdp->realm_stash = strdup(rparams->realm_stash_file);
+	manual = FALSE;
+    } else
+	manual = def_manual;
+
+    /* Handle master key type */
+    if (rparams && rparams->realm_enctype_valid)
+	rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype;
+    else
+	rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN;
+
+    /* Handle reject-bad-transit flag */
+    if (rparams && rparams->realm_reject_bad_transit_valid)
+	rdp->realm_reject_bad_transit = rparams->realm_reject_bad_transit;
+    else
+	rdp->realm_reject_bad_transit = 1;
+
+    /* Handle ticket maximum life */
+    rdp->realm_maxlife = (rparams && rparams->realm_max_life_valid) ?
+	rparams->realm_max_life : KRB5_KDB_MAX_LIFE;
+
+    /* Handle ticket renewable maximum life */
+    rdp->realm_maxrlife = (rparams && rparams->realm_max_rlife_valid) ?
+	rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE;
+
+    if (rparams)
+	krb5_free_realm_params(rdp->realm_context, rparams);
+
+    /*
+     * We've got our parameters, now go and setup our realm context.
+     */
+
+    /* Set the default realm of this context */
+    if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) {
+	com_err(progname, kret, "while setting default realm to %s",
+		realm);
+	goto whoops;
+    }
+
+    /* first open the database  before doing anything */
+#ifdef KRBCONF_KDC_MODIFIES_KDB    
+    if ((kret = krb5_db_open(rdp->realm_context, db_args, 
+			     KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC))) {
+#else
+    if ((kret = krb5_db_open(rdp->realm_context, db_args, 
+			     KRB5_KDB_OPEN_RO | KRB5_KDB_SRV_TYPE_KDC))) {
+#endif
+	com_err(progname, kret,
+		"while initializing database for realm %s", realm);
+	goto whoops;
+    }
+
+    /* Assemble and parse the master key name */
+    if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname,
+					rdp->realm_name, (char **) NULL,
+					&rdp->realm_mprinc))) {
+	com_err(progname, kret,
+		"while setting up master key name %s for realm %s",
+		rdp->realm_mpname, realm);
+	goto whoops;
+    }
+
+    /*
+     * Get the master key.
+     */
+    if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc,
+				   rdp->realm_mkey.enctype, manual,
+				   FALSE, rdp->realm_stash,
+				   0, &rdp->realm_mkey))) {
+	com_err(progname, kret,
+		"while fetching master key %s for realm %s",
+		rdp->realm_mpname, realm);
+	goto whoops;
+    }
+
+    /* Verify the master key */
+    if ((kret = krb5_db_verify_master_key(rdp->realm_context,
+					  rdp->realm_mprinc,
+					  &rdp->realm_mkey))) {
+	com_err(progname, kret,
+		"while verifying master key for realm %s", realm);
+	goto whoops;
+    }
+
+    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;
+    }
+
+    /* Set up the keytab */
+    if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL,
+				   &rdp->realm_keytab))) {
+	com_err(progname, kret,
+		"while resolving kdb keytab for realm %s", realm);
+	goto whoops;
+    }
+
+    /* Preformat the TGS name */
+    if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc,
+				     strlen(realm), realm, KRB5_TGS_NAME,
+				     realm, (char *) NULL))) {
+	com_err(progname, kret,
+		"while building TGS name for realm %s", realm);
+	goto whoops;
+    }
+
+    if (!rkey_init_done) {
+	krb5_data seed;
+#ifdef KRB5_KRB4_COMPAT
+	krb5_keyblock temp_key;
+#endif
+	/*
+	 * If all that worked, then initialize the random key
+	 * generators.
+	 */
+
+	seed.length = rdp->realm_mkey.length;
+	seed.data = rdp->realm_mkey.contents;
+
+	if ((kret = krb5_c_random_add_entropy(rdp->realm_context,
+					     KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
+	    goto whoops;
+
+#ifdef KRB5_KRB4_COMPAT
+	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:
+    /*
+     * If we choked, then clean up any dirt we may have dropped on the floor.
+     */
+    if (kret) {
+        
+	finish_realm(rdp);
+    }
+    return(kret);
+}
+
+krb5_sigtype
+request_exit(int signo)
+{
+    signal_requests_exit = 1;
+
+#ifdef POSIX_SIGTYPE
+    return;
+#else
+    return(0);
+#endif
+}
+
+krb5_sigtype
+request_hup(int signo)
+{
+    signal_requests_hup = 1;
+
+#ifdef POSIX_SIGTYPE
+    return;
+#else
+    return(0);
+#endif
+}
+
+void
+setup_signal_handlers(void)
+{
+#ifdef POSIX_SIGNALS
+    (void) sigemptyset(&s_action.sa_mask);
+    s_action.sa_flags = 0;
+    s_action.sa_handler = request_exit;
+    (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL);
+    (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL);
+    s_action.sa_handler = request_hup;
+    (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL);
+    s_action.sa_handler = SIG_IGN;
+    (void) sigaction(SIGPIPE, &s_action, (struct sigaction *) NULL);
+#else  /* POSIX_SIGNALS */
+    signal(SIGINT, request_exit);
+    signal(SIGTERM, request_exit);
+    signal(SIGHUP, request_hup);
+    signal(SIGPIPE, SIG_IGN);
+#endif /* POSIX_SIGNALS */
+
+    return;
+}
+
+krb5_error_code
+setup_sam(void)
+{
+    return krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_MD5, &psr_key);
+}
+
+void
+usage(char *name)
+{
+    fprintf(stderr, "usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname] [-R replaycachename ]\n\t[-m] [-k masterenctype] [-M masterkeyname] [-p port] [-4 v4mode] [-X] [-n]\n"
+	    "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
+	    "\t\t\tLook at each database documentation for supported arguments\n",
+	    name);
+    return;
+}
+
+void
+initialize_realms(krb5_context kcontext, int argc, char **argv)
+{
+    int 		c;
+    char		*db_name = (char *) NULL;
+    char		*mkey_name = (char *) NULL;
+    char		*rcname = KDCRCACHE;
+    char		*lrealm;
+    krb5_error_code	retval;
+    krb5_enctype	menctype = ENCTYPE_UNKNOWN;
+    kdc_realm_t		*rdatap;
+    krb5_boolean	manual = FALSE;
+    char		*default_udp_ports = 0;
+    char		*default_tcp_ports = 0;
+    krb5_pointer	aprof;
+    const char		*hierarchy[3];
+    char               **db_args      = NULL;
+    int                  db_args_size = 0;
+
+#ifdef KRB5_KRB4_COMPAT
+    char                *v4mode = 0;
+#endif
+    extern char *optarg;
+
+    if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) {
+	hierarchy[0] = "kdcdefaults";
+	hierarchy[1] = "kdc_ports";
+	hierarchy[2] = (char *) NULL;
+	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports))
+	    default_udp_ports = 0;
+	hierarchy[1] = "kdc_tcp_ports";
+	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports))
+	    default_tcp_ports = 0;
+#ifdef KRB5_KRB4_COMPAT
+	hierarchy[1] = "v4_mode";
+	if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode))
+	    v4mode = 0;
+#endif
+	/* aprof_init can return 0 with aprof == NULL */
+	if (aprof)
+	     krb5_aprof_finish(aprof);
+    }
+    if (default_udp_ports == 0)
+	default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST);
+    if (default_tcp_ports == 0)
+	default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST);
+    /*
+     * Loop through the option list.  Each time we encounter a realm name,
+     * use the previously scanned options to fill in for defaults.
+     */
+    while ((c = getopt(argc, argv, "x:r:d:mM:k:R:e:p:s:n4:X3")) != -1) {
+	switch(c) {
+	case 'x':
+	    db_args_size++;
+	    {
+		char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
+		if( temp == NULL )
+		{
+		    fprintf(stderr,"%s: KDC cannot initialize. Not enough memory\n",
+			    argv[0]);
+		    exit(1);
+		}
+
+		db_args = temp;
+	    }
+	    db_args[db_args_size-1] = optarg;
+	    db_args[db_args_size]   = NULL;
+	  break;
+
+	case 'r':			/* realm name for db */
+	    if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
+		if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
+		    if ((retval = init_realm(argv[0], rdatap, optarg, 
+					     mkey_name, menctype,
+					     default_udp_ports,
+					     default_tcp_ports, manual, db_args))) {
+			fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n",
+				argv[0], optarg);
+			exit(1);
+		    }
+		    kdc_realmlist[kdc_numrealms] = rdatap;
+		    kdc_numrealms++;
+		    free(db_args), db_args=NULL, db_args_size = 0;
+		}
+		else
+		{
+			fprintf(stderr,"%s: cannot initialize realm %s. Not enough memory\n",
+				argv[0], optarg);
+			exit(1);
+		}
+	    }
+	    break;
+	case 'd':			/* pathname for db */
+	    /* now db_name is not a seperate argument. It has to be passed as part of the db_args */
+	    if( db_name == NULL )
+	    {
+		db_name = malloc(sizeof("dbname=") + strlen(optarg));
+		if( db_name == NULL )
+		{
+			fprintf(stderr,"%s: KDC cannot initialize. Not enough memory\n",
+				argv[0] );
+			exit(1);
+		}
+
+		sprintf( db_name, "dbname=%s", optarg);
+	    }
+
+	    db_args_size++;
+	    {
+		char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
+		if( temp == NULL )
+		{
+		    fprintf(stderr,"%s: KDC cannot initialize. Not enough memory\n",
+			    argv[0]);
+		    exit(1);
+		}
+
+		db_args = temp;
+	    }
+	    db_args[db_args_size-1] = db_name;
+	    db_args[db_args_size]   = NULL;
+	    break;
+	case 'm':			/* manual type-in of master key */
+	    manual = TRUE;
+	    if (menctype == ENCTYPE_UNKNOWN)
+		menctype = ENCTYPE_DES_CBC_CRC;
+	    break;
+	case 'M':			/* master key name in DB */
+	    mkey_name = optarg;
+	    break;
+	case 'n':
+	    nofork++;			/* don't detach from terminal */
+	    break;
+	case 'k':			/* enctype for master key */
+	    if (krb5_string_to_enctype(optarg, &menctype))
+		com_err(argv[0], 0, "invalid enctype %s", optarg);
+	    break;
+	case 'R':
+	    rcname = optarg;
+	    break;
+	case 'p':
+	    if (default_udp_ports)
+		free(default_udp_ports);
+	    default_udp_ports = strdup(optarg);
+#if 0 /* not yet */
+	    if (default_tcp_ports)
+		free(default_tcp_ports);
+	    default_tcp_ports = strdup(optarg);
+#endif
+	    break;
+	case '4':
+#ifdef KRB5_KRB4_COMPAT
+	    if (v4mode)
+		free(v4mode);
+	    v4mode = strdup(optarg);
+#endif
+	    break;
+	case 'X':
+#ifdef KRB5_KRB4_COMPAT
+		enable_v4_crossrealm(argv[0]);
+#endif
+		break;
+	case '?':
+	default:
+	    usage(argv[0]);
+	    exit(1);
+	}
+    }
+
+#ifdef KRB5_KRB4_COMPAT
+    /*
+     * Setup the v4 mode 
+     */
+    process_v4_mode(argv[0], v4mode);
+    free(v4mode);
+#endif
+
+    /*
+     * Check to see if we processed any realms.
+     */
+    if (kdc_numrealms == 0) {
+	/* no realm specified, use default realm */
+	if ((retval = krb5_get_default_realm(kcontext, &lrealm))) {
+	    com_err(argv[0], retval,
+		    "while attempting to retrieve default realm");
+	    fprintf (stderr, "%s: %s, attempting to retrieve default realm\n",
+		     argv[0], krb5_get_error_message(kcontext, retval));
+	    exit(1);
+	}
+	if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
+	    if ((retval = init_realm(argv[0], rdatap, lrealm, 
+				     mkey_name, menctype, default_udp_ports,
+				     default_tcp_ports, manual, db_args))) {
+		fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n",
+			argv[0], lrealm);
+		exit(1);
+	    }
+	    kdc_realmlist[0] = rdatap;
+	    kdc_numrealms++;
+	}
+    }
+
+#ifdef USE_RCACHE
+    /*
+     * Now handle the replay cache.
+     */
+    if ((retval = kdc_initialize_rcache(kcontext, rcname))) {
+	com_err(argv[0], retval, "while initializing KDC replay cache '%s'",
+		rcname);
+	exit(1);
+    }
+#endif
+
+    /* Ensure that this is set for our first request. */
+    kdc_active_realm = kdc_realmlist[0];
+    if (default_udp_ports)
+	free(default_udp_ports);
+    if (default_tcp_ports)
+	free(default_tcp_ports);
+    if (db_args)
+	free(db_args);
+    if (db_name)
+	free(db_name);
+
+    return;
+}
+
+void
+finish_realms(char *prog)
+{
+    int i;
+
+    for (i = 0; i < kdc_numrealms; i++) {
+	finish_realm(kdc_realmlist[i]);
+	kdc_realmlist[i] = 0;
+    }
+}
+
+/*
+ outline:
+
+ process args & setup
+
+ initialize database access (fetch master key, open DB)
+
+ initialize network
+
+ loop:
+ 	listen for packet
+
+	determine packet type, dispatch to handling routine
+		(AS or TGS (or V4?))
+
+	reflect response
+
+	exit on signal
+
+ clean up secrets, close db
+
+ shut down network
+
+ exit
+ */
+
+int main(int argc, char **argv)
+{
+    krb5_error_code	retval;
+    krb5_context	kcontext;
+    int errout = 0;
+
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+
+    if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) * 
+						  KRB5_KDC_MAX_REALMS))) {
+	fprintf(stderr, "%s: cannot get memory for realm list\n", argv[0]);
+	exit(1);
+    }
+    memset((char *) kdc_realmlist, 0,
+	   (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS));
+
+    /*
+     * A note about Kerberos contexts: This context, "kcontext", is used
+     * for the KDC operations, i.e. setup, network connection and error
+     * reporting.  The per-realm operations use the "realm_context"
+     * associated with each realm.
+     */
+    retval = krb5int_init_context_kdc(&kcontext);
+    if (retval) {
+	    com_err(argv[0], retval, "while initializing krb5");
+	    exit(1);
+    }
+    krb5_klog_init(kcontext, "kdc", argv[0], 1);
+    /* N.B.: After this point, com_err sends output to the KDC log
+       file, and not to stderr.  */
+
+    initialize_kdc5_error_table();
+
+    /*
+     * Scan through the argument list
+     */
+    initialize_realms(kcontext, argc, argv);
+
+    setup_signal_handlers();
+
+    load_preauth_plugins(kcontext);
+
+    retval = setup_sam();
+    if (retval) {
+	com_err(argv[0], retval, "while initializing SAM");
+	finish_realms(argv[0]);
+	return 1;
+    }
+
+    if ((retval = setup_network(argv[0]))) {
+	com_err(argv[0], retval, "while initializing network");
+	finish_realms(argv[0]);
+	return 1;
+    }
+    if (!nofork && daemon(0, 0)) {
+	com_err(argv[0], errno, "while detaching from tty");
+	finish_realms(argv[0]);
+	return 1;
+    }
+    krb5_klog_syslog(LOG_INFO, "commencing operation");
+    if ((retval = listen_and_process(argv[0]))) {
+	com_err(argv[0], retval, "while processing network requests");
+	errout++;
+    }
+    if ((retval = closedown_network(argv[0]))) {
+	com_err(argv[0], retval, "while shutting down network");
+	errout++;
+    }
+    krb5_klog_syslog(LOG_INFO, "shutting down");
+    unload_preauth_plugins(kcontext);
+    krb5_klog_close(kdc_context);
+    finish_realms(argv[0]);
+    if (kdc_realmlist) 
+      free(kdc_realmlist);
+#ifdef USE_RCACHE
+    (void) krb5_rc_close(kcontext, kdc_rcache);
+#endif
+#ifndef NOCACHE
+    kdc_free_lookaside(kcontext);
+#endif
+    krb5_free_context(kcontext);
+    return errout;
+}
+
+
+
+
diff --git a/krb5-1-6/src/kdc/migration.doc b/krb5-1-6/src/kdc/migration.doc
new file mode 100644
index 000000000..d3613ac0d
--- /dev/null
+++ b/krb5-1-6/src/kdc/migration.doc
@@ -0,0 +1,59 @@
+This document describes the protocols & procedures necessary to allow
+a large krb4 site like MIT to migrate smoothly to krb5.
+
+The problem we have to solve is that v4 clients don't know about the v5
+string-to-key function, which incorporates the user's name, instance, and realm
+into his private key, along with his password.
+It happens that our solution also solves a related problem: the v5 str2key
+function prevents a site from changing its realm-name, as when the company gets
+bought by another.
+
+PROTOCOLS:
+
+The compatibilty kdc will mark v5-style entries with an attribute bit.
+
+the v5 get_in_tkt clients (kinit, login, etc) all will be able to perform
+v4 str2key; this will allow users with v4 passwords to gain v5 tickets.
+When a user's entry contains a v5-style password, and he uses v5 kinit,
+the kinit protocol will have the kdc send a cleartext realm-unique string
+(initially null) along with the (password+realm)-encrypted tgt.
+When such a user runs v4 kinit, he loses.
+
+Mapping the realm-name to a realm-id string happens in a kdc-configuration file,
+possibly in the first line of krb.conf .
+
+These things will not happen until we deploy a kpasswd that can replace
+v4-style passwords with v5-style ones.
+It would be nice to provide a "convert" flag, that allows you to upgrade
+without having to change your password's text.
+
+PROCEDURES:
+
+Initially, administrators should deploy the v5 kdc (with its built-in
+v4 compatibility), a v4 kadmin server, and a v5 kadmin server.
+The v5 kadmin server will at this time continue to use the v4 str2key function,
+so all of the passwords in the database will be v4 compatible.
+
+the compatibility versions of the get_in_tkt clients (kinit, login, etc)
+should be deployed when most of the campus' software can handle v5.
+When a v4 user runs v5 kinit, he gets v5 tickets unawares.
+Vice-versa, the user loses.
+
+The users are then weaned from v4 in three (two?) steps:
+   first, we change kpasswd to convert v4-style passwords to v5-style,
+   once the site converts most of its various clients and daemons to v5 krb.
+   the kdc now needs to be able to send a non-null realm-id string to kinit.
+
+   second, we turn off the v4 kadmin server (simultaneous with 1 or 3?).
+
+   third, but optionally, we turn off the v4-compatibility glue in the kdc.
+
+Every user who runs the converting kpasswd becomes unable to run v4 clients
+thereafter; we assume that a user who converts has continued access to
+other v5 clients. the conversion code can warn him.
+
+We continue to run the v4 kadmin because users of v4 kpasswd may not yet have
+ready access to v5 clients.
+
+Note that the database's conversion commences gradually with the deployment
+of the converting kpasswd, so this deployment doesn't have to be instantaneous.
diff --git a/krb5-1-6/src/kdc/network.c b/krb5-1-6/src/kdc/network.c
new file mode 100644
index 000000000..3cb4400df
--- /dev/null
+++ b/krb5-1-6/src/kdc/network.c
@@ -0,0 +1,1132 @@
+/*
+ * kdc/network.c
+ *
+ * Copyright 1990,2000 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Network code for Kerberos v5 KDC.
+ */
+
+#include "k5-int.h"
+#include "com_err.h"
+#include "kdc_util.h"
+#include "extern.h"
+#include "kdc5_err.h"
+#include "adm_proto.h"
+#include <sys/ioctl.h>
+#include <syslog.h>
+
+#include <stddef.h>
+#include <ctype.h>
+#include "port-sockets.h"
+#include "socket-utils.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+/* for SIOCGIFCONF, etc. */
+#include <sys/sockio.h>
+#endif
+#include <sys/time.h>
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <arpa/inet.h>
+
+#ifndef ARPHRD_ETHER /* OpenBSD breaks on multiple inclusions */
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>		/* FIONBIO */
+#endif
+
+#include "fake-addrinfo.h"
+
+/* Misc utility routines.  */
+static void
+set_sa_port(struct sockaddr *addr, int port)
+{
+    switch (addr->sa_family) {
+    case AF_INET:
+	sa2sin(addr)->sin_port = port;
+	break;
+#ifdef KRB5_USE_INET6
+    case AF_INET6:
+	sa2sin6(addr)->sin6_port = port;
+	break;
+#endif
+    default:
+	break;
+    }
+}
+
+static int ipv6_enabled()
+{
+#ifdef KRB5_USE_INET6
+    static int result = -1;
+    if (result == -1) {
+	int s;
+	s = socket(AF_INET6, SOCK_STREAM, 0);
+	if (s >= 0) {
+	    result = 1;
+	    close(s);
+	} else
+	    result = 0;
+    }
+    return result;
+#else
+    return 0;
+#endif
+}
+
+static int
+setreuseaddr(int sock, int value)
+{
+    return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
+}
+
+#if defined(KRB5_USE_INET6) && defined(IPV6_V6ONLY)
+static int
+setv6only(int sock, int value)
+{
+    return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value));
+}
+#endif
+
+
+static const char *paddr (struct sockaddr *sa)
+{
+    static char buf[100];
+    char portbuf[10];
+    if (getnameinfo(sa, socklen(sa),
+		    buf, sizeof(buf), portbuf, sizeof(portbuf),
+		    NI_NUMERICHOST|NI_NUMERICSERV))
+	strcpy(buf, "<unprintable>");
+    else {
+	unsigned int len = sizeof(buf) - strlen(buf);
+	char *p = buf + strlen(buf);
+	if (len > 2+strlen(portbuf)) {
+	    *p++ = '.';
+	    len--;
+	    strncpy(p, portbuf, len);
+	}
+    }
+    return buf;
+}
+
+/* KDC data.  */
+
+enum kdc_conn_type { CONN_UDP, CONN_TCP_LISTENER, CONN_TCP };
+
+/* Per-connection info.  */
+struct connection {
+    int fd;
+    enum kdc_conn_type type;
+    void (*service)(struct connection *, const char *, int);
+    union {
+	/* Type-specific information.  */
+	struct {
+	    int x;
+	} udp;
+	struct {
+	    int x;
+	} tcp_listener;
+	struct {
+	    /* connection */
+	    struct sockaddr_storage addr_s;
+	    socklen_t addrlen;
+	    char addrbuf[56];
+	    krb5_fulladdr faddr;
+	    krb5_address kaddr;
+	    /* incoming */
+	    size_t bufsiz;
+	    size_t offset;
+	    char *buffer;
+	    size_t msglen;
+	    /* outgoing */
+	    krb5_data *response;
+	    unsigned char lenbuf[4];
+	    sg_buf sgbuf[2];
+	    sg_buf *sgp;
+	    int sgnum;
+	    /* crude denial-of-service avoidance support */
+	    time_t start_time;
+	} tcp;
+    } u;
+};
+
+
+#define SET(TYPE) struct { TYPE *data; int n, max; }
+
+/* Start at the top and work down -- this should allow for deletions
+   without disrupting the iteration, since we delete by overwriting
+   the element to be removed with the last element.  */
+#define FOREACH_ELT(set,idx,vvar) \
+  for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--)
+
+#define GROW_SET(set, incr, tmpptr) \
+  (((int)(set.max + incr) < set.max					\
+    || (((size_t)((int)(set.max + incr) * sizeof(set.data[0]))		\
+	 / sizeof(set.data[0]))						\
+	!= (set.max + incr)))						\
+   ? 0				/* overflow */				\
+   : ((tmpptr = realloc(set.data,					\
+			(int)(set.max + incr) * sizeof(set.data[0])))	\
+      ? (set.data = tmpptr, set.max += incr, 1)				\
+      : 0))
+
+/* 1 = success, 0 = failure */
+#define ADD(set, val, tmpptr) \
+  ((set.n < set.max || GROW_SET(set, 10, tmpptr))			\
+   ? (set.data[set.n++] = val, 1)					\
+   : 0)
+
+#define DEL(set, idx) \
+  (set.data[idx] = set.data[--set.n], 0)
+
+#define FREE_SET_DATA(set) if(set.data) free(set.data);                 \
+   (set.data = 0, set.max = 0)
+
+
+/* Set<struct connection *> connections; */
+static SET(struct connection *) connections;
+#define n_sockets	connections.n
+#define conns		connections.data
+
+/* Set<u_short> udp_port_data, tcp_port_data; */
+static SET(u_short) udp_port_data, tcp_port_data;
+
+#include "cm.h"
+
+static struct select_state sstate;
+
+static krb5_error_code add_udp_port(int port)
+{
+    int	i;
+    void *tmp;
+    u_short val;
+    u_short s_port = port;
+
+    if (s_port != port)
+	return EINVAL;
+
+    FOREACH_ELT (udp_port_data, i, val)
+	if (s_port == val)
+	    return 0;
+    if (!ADD(udp_port_data, s_port, tmp))
+	return ENOMEM;
+    return 0;
+}
+
+static krb5_error_code add_tcp_port(int port)
+{
+    int	i;
+    void *tmp;
+    u_short val;
+    u_short s_port = port;
+
+    if (s_port != port)
+	return EINVAL;
+
+    FOREACH_ELT (tcp_port_data, i, val)
+	if (s_port == val)
+	    return 0;
+    if (!ADD(tcp_port_data, s_port, tmp))
+	return ENOMEM;
+    return 0;
+}
+
+
+#define USE_AF AF_INET
+#define USE_TYPE SOCK_DGRAM
+#define USE_PROTO 0
+#define SOCKET_ERRNO errno
+#include "foreachaddr.h"
+
+struct socksetup {
+    const char *prog;
+    krb5_error_code retval;
+};
+
+static struct connection *
+add_fd (struct socksetup *data, int sock, enum kdc_conn_type conntype,
+	void (*service)(struct connection *, const char *, int))
+{
+    struct connection *newconn;
+    void *tmp;
+
+    newconn = malloc(sizeof(*newconn));
+    if (newconn == 0) {
+	data->retval = errno;
+	com_err(data->prog, errno,
+		"cannot allocate storage for connection info");
+	return 0;
+    }
+    if (!ADD(connections, newconn, tmp)) {
+	data->retval = errno;
+	com_err(data->prog, data->retval, "cannot save socket info");
+	free(newconn);
+	return 0;
+    }
+
+    memset(newconn, 0, sizeof(*newconn));
+    newconn->type = conntype;
+    newconn->fd = sock;
+    newconn->service = service;
+    return newconn;
+}
+
+static void process_packet(struct connection *, const char *, int);
+static void accept_tcp_connection(struct connection *, const char *, int);
+static void process_tcp_connection(struct connection *, const char *, int);
+
+static struct connection *
+add_udp_fd (struct socksetup *data, int sock)
+{
+    return add_fd(data, sock, CONN_UDP, process_packet);
+}
+
+static struct connection *
+add_tcp_listener_fd (struct socksetup *data, int sock)
+{
+    return add_fd(data, sock, CONN_TCP_LISTENER, accept_tcp_connection);
+}
+
+static struct connection *
+add_tcp_data_fd (struct socksetup *data, int sock)
+{
+    return add_fd(data, sock, CONN_TCP, process_tcp_connection);
+}
+
+static void
+delete_fd (struct connection *xconn)
+{
+    struct connection *conn;
+    int i;
+
+    FOREACH_ELT(connections, i, conn)
+	if (conn == xconn) {
+	    DEL(connections, i);
+	    break;
+	}
+    free(xconn);
+}
+
+static int
+setnbio(int sock)
+{
+    static const int one = 1;
+    return ioctlsocket(sock, FIONBIO, (const void *)&one);
+}
+
+static int
+setnolinger(int s)
+{
+    static const struct linger ling = { 0, 0 };
+    return setsockopt(s, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
+}
+
+/* Returns -1 or socket fd.  */
+static int
+setup_a_tcp_listener(struct socksetup *data, struct sockaddr *addr)
+{
+    int sock;
+
+    sock = socket(addr->sa_family, SOCK_STREAM, 0);
+    if (sock == -1) {
+	com_err(data->prog, errno, "Cannot create TCP server socket on %s",
+		paddr(addr));
+	return -1;
+    }
+    if (setreuseaddr(sock, 1) < 0)
+	com_err(data->prog, errno,
+		"Cannot enable SO_REUSEADDR on fd %d", sock);
+#ifdef KRB5_USE_INET6
+    if (addr->sa_family == AF_INET6) {
+#ifdef IPV6_V6ONLY
+	if (setv6only(sock, 1))
+	    com_err(data->prog, errno, "setsockopt(IPV6_V6ONLY,1) failed");
+	else
+	    com_err(data->prog, 0, "setsockopt(IPV6_V6ONLY,1) worked");
+#else
+	krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support");
+#endif /* IPV6_V6ONLY */
+    }
+#endif /* KRB5_USE_INET6 */
+    if (bind(sock, addr, socklen(addr)) == -1) {
+	com_err(data->prog, errno,
+		"Cannot bind TCP server socket on %s", paddr(addr));
+	close(sock);
+	return -1;
+    }
+    if (listen(sock, 5) < 0) {
+	com_err(data->prog, errno, "Cannot listen on TCP server socket on %s",
+		paddr(addr));
+	close(sock);
+	return -1;
+    }
+    if (setnbio(sock)) {
+	com_err(data->prog, errno,
+		"cannot set listening tcp socket on %s non-blocking",
+		paddr(addr));
+	close(sock);
+	return -1;
+    }
+    if (setnolinger(sock)) {
+	com_err(data->prog, errno, "disabling SO_LINGER on TCP socket on %s",
+		paddr(addr));
+	close(sock);
+	return -1;
+    }
+    return sock;
+}
+
+static int
+setup_tcp_listener_ports(struct socksetup *data)
+{
+    struct sockaddr_in sin4;
+#ifdef KRB5_USE_INET6
+    struct sockaddr_in6 sin6;
+#endif
+    int i, port;
+
+    memset(&sin4, 0, sizeof(sin4));
+    sin4.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+    sin4.sin_len = sizeof(sin4);
+#endif
+    sin4.sin_addr.s_addr = INADDR_ANY;
+
+#ifdef KRB5_USE_INET6
+    memset(&sin6, 0, sizeof(sin6));
+    sin6.sin6_family = AF_INET6;
+#ifdef SIN6_LEN
+    sin6.sin6_len = sizeof(sin6);
+#endif
+    sin6.sin6_addr = in6addr_any;
+#endif
+
+    FOREACH_ELT (tcp_port_data, i, port) {
+	int s4, s6;
+
+	set_sa_port((struct sockaddr *)&sin4, htons(port));
+	if (!ipv6_enabled()) {
+	    s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
+	    if (s4 < 0)
+		return -1;
+	    s6 = -1;
+	} else {
+#ifndef KRB5_USE_INET6
+	    abort();
+#else
+	    s4 = s6 = -1;
+
+	    set_sa_port((struct sockaddr *)&sin6, htons(port));
+
+	    s6 = setup_a_tcp_listener(data, (struct sockaddr *)&sin6);
+	    if (s6 < 0)
+		return -1;
+
+	    s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
+#endif /* KRB5_USE_INET6 */
+	}
+
+	/* Sockets are created, prepare to listen on them.  */
+	if (s4 >= 0) {
+	    FD_SET(s4, &sstate.rfds);
+	    if (s4 >= sstate.max)
+		sstate.max = s4 + 1;
+	    if (add_tcp_listener_fd(data, s4) == 0)
+		close(s4);
+	    else
+		krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s",
+				 s4, paddr((struct sockaddr *)&sin4));
+	}
+#ifdef KRB5_USE_INET6
+	if (s6 >= 0) {
+	    FD_SET(s6, &sstate.rfds);
+	    if (s6 >= sstate.max)
+		sstate.max = s6 + 1;
+	    if (add_tcp_listener_fd(data, s6) == 0) {
+		close(s6);
+		s6 = -1;
+	    } else
+		krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s",
+				 s6, paddr((struct sockaddr *)&sin6));
+	    if (s4 < 0)
+		krb5_klog_syslog(LOG_INFO,
+				 "assuming IPv6 socket accepts IPv4");
+	}
+#endif
+    }
+    return 0;
+}
+
+static int
+setup_udp_port(void *P_data, struct sockaddr *addr)
+{
+    struct socksetup *data = P_data;
+    int sock = -1, i;
+    char haddrbuf[NI_MAXHOST];
+    int err;
+    u_short port;
+
+    err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf),
+		      0, 0, NI_NUMERICHOST);
+    if (err)
+	strcpy(haddrbuf, "<unprintable>");
+
+    switch (addr->sa_family) {
+    case AF_INET:
+	break;
+#ifdef AF_INET6
+    case AF_INET6:
+#ifdef KRB5_USE_INET6
+	break;
+#else
+	{
+	    static int first = 1;
+	    if (first) {
+		krb5_klog_syslog (LOG_INFO, "skipping local ipv6 addresses");
+		first = 0;
+	    }
+	    return 0;
+	}
+#endif
+#endif
+#ifdef AF_LINK /* some BSD systems, AIX */
+    case AF_LINK:
+	return 0;
+#endif
+#ifdef AF_DLI /* Direct Link Interface - DEC Ultrix/OSF1 link layer? */
+    case AF_DLI:
+	return 0;
+#endif
+    default:
+	krb5_klog_syslog (LOG_INFO,
+			  "skipping unrecognized local address family %d",
+			  addr->sa_family);
+	return 0;
+    }
+
+    FOREACH_ELT (udp_port_data, i, port) {
+	sock = socket (addr->sa_family, SOCK_DGRAM, 0);
+	if (sock == -1) {
+	    data->retval = errno;
+	    com_err(data->prog, data->retval,
+		    "Cannot create server socket for port %d address %s",
+		    port, haddrbuf);
+	    return 1;
+	}
+	set_sa_port(addr, htons(port));
+	if (bind (sock, (struct sockaddr *)addr, socklen (addr)) == -1) {
+	    data->retval = errno;
+	    com_err(data->prog, data->retval,
+		    "Cannot bind server socket to port %d address %s",
+		    port, haddrbuf);
+	    return 1;
+	}
+	FD_SET (sock, &sstate.rfds);
+	if (sock >= sstate.max)
+	    sstate.max = sock + 1;
+	krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s", sock,
+			  paddr((struct sockaddr *)addr));
+	if (add_udp_fd (data, sock) == 0)
+	    return 1;
+    }
+    return 0;
+}
+
+#if 1
+static void klog_handler(const void *data, size_t len)
+{
+    static char buf[BUFSIZ];
+    static int bufoffset;
+    void *p;
+
+#define flush_buf() \
+  (bufoffset						\
+   ? (((buf[0] == 0 || buf[0] == '\n')			\
+       ? (fork()==0?abort():(void)0)			\
+       : (void)0),					\
+      krb5_klog_syslog(LOG_INFO, "%s", buf),		\
+      memset(buf, 0, sizeof(buf)),			\
+      bufoffset = 0)					\
+   : 0)
+
+    p = memchr(data, 0, len);
+    if (p)
+	len = (const char *)p - (const char *)data;
+scan_for_newlines:
+    if (len == 0)
+	return;
+    p = memchr(data, '\n', len);
+    if (p) {
+	if (p != data)
+	    klog_handler(data, (size_t)((const char *)p - (const char *)data));
+	flush_buf();
+	len -= ((const char *)p - (const char *)data) + 1;
+	data = 1 + (const char *)p;
+	goto scan_for_newlines;
+    } else if (len > sizeof(buf) - 1 || len + bufoffset > sizeof(buf) - 1) {
+	size_t x = sizeof(buf) - len - 1;
+	klog_handler(data, x);
+	flush_buf();
+	len -= x;
+	data = (const char *)data + x;
+	goto scan_for_newlines;
+    } else {
+	memcpy(buf + bufoffset, data, len);
+	bufoffset += len;
+    }
+}
+#endif
+
+/* XXX */
+extern int krb5int_debug_sendto_kdc;
+extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t);
+
+krb5_error_code
+setup_network(const char *prog)
+{
+    struct socksetup setup_data;
+    krb5_error_code retval;
+    char *cp;
+    int i, port;
+
+    FD_ZERO(&sstate.rfds);
+    FD_ZERO(&sstate.wfds);
+    FD_ZERO(&sstate.xfds);
+    sstate.max = 0;
+
+/*    krb5int_debug_sendto_kdc = 1; */
+    krb5int_sendtokdc_debug_handler = klog_handler;
+
+    /* Handle each realm's ports */
+    for (i=0; i<kdc_numrealms; i++) {
+	cp = kdc_realmlist[i]->realm_ports;
+	while (cp && *cp) {
+	    if (*cp == ',' || isspace((int) *cp)) {
+		cp++;
+		continue;
+	    }
+	    port = strtol(cp, &cp, 10);
+	    if (cp == 0)
+		break;
+	    retval = add_udp_port(port);
+	    if (retval)
+		return retval;
+	}
+
+	cp = kdc_realmlist[i]->realm_tcp_ports;
+	while (cp && *cp) {
+	    if (*cp == ',' || isspace((int) *cp)) {
+		cp++;
+		continue;
+	    }
+	    port = strtol(cp, &cp, 10);
+	    if (cp == 0)
+		break;
+	    retval = add_tcp_port(port);
+	    if (retval)
+		return retval;
+	}
+    }
+
+    setup_data.prog = prog;
+    setup_data.retval = 0;
+    krb5_klog_syslog (LOG_INFO, "setting up network...");
+    /* To do: Use RFC 2292 interface (or follow-on) and IPV6_PKTINFO,
+       so we might need only one UDP socket; fall back to binding
+       sockets on each address only if IPV6_PKTINFO isn't
+       supported.  */
+    if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
+	return setup_data.retval;
+    }
+    setup_tcp_listener_ports(&setup_data);
+    krb5_klog_syslog (LOG_INFO, "set up %d sockets", n_sockets);
+    if (n_sockets == 0) {
+	com_err(prog, 0, "no sockets set up?");
+	exit (1);
+    }
+
+    return 0;
+}
+
+static void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
+{
+    switch (sa->sa_family) {
+    case AF_INET:
+	faddr->address->addrtype = ADDRTYPE_INET;
+	faddr->address->length = 4;
+	faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr;
+	faddr->port = ntohs(sa2sin(sa)->sin_port);
+	break;
+#ifdef KRB5_USE_INET6
+    case AF_INET6:
+	if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) {
+	    faddr->address->addrtype = ADDRTYPE_INET;
+	    faddr->address->length = 4;
+	    faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr;
+	} else {
+	    faddr->address->addrtype = ADDRTYPE_INET6;
+	    faddr->address->length = 16;
+	    faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr;
+	}
+	faddr->port = ntohs(sa2sin6(sa)->sin6_port);
+	break;
+#endif
+    default:
+	faddr->address->addrtype = -1;
+	faddr->address->length = 0;
+	faddr->address->contents = 0;
+	faddr->port = 0;
+	break;
+    }
+}
+
+static void process_packet(struct connection *conn, const char *prog,
+			   int selflags)
+{
+    int cc;
+    socklen_t saddr_len;
+    krb5_fulladdr faddr;
+    krb5_error_code retval;
+    struct sockaddr_storage saddr;
+    krb5_address addr;
+    krb5_data request;
+    krb5_data *response;
+    char pktbuf[MAX_DGRAM_SIZE];
+    int port_fd = conn->fd;
+
+    response = NULL;
+    saddr_len = sizeof(saddr);
+    cc = recvfrom(port_fd, pktbuf, sizeof(pktbuf), 0,
+		  (struct sockaddr *)&saddr, &saddr_len);
+    if (cc == -1) {
+	if (errno != EINTR
+	    /* This is how Linux indicates that a previous
+	       transmission was refused, e.g., if the client timed out
+	       before getting the response packet.  */
+	    && errno != ECONNREFUSED
+	    )
+	    com_err(prog, errno, "while receiving from network");
+	return;
+    }
+    if (!cc)
+	return;		/* zero-length packet? */
+
+    request.length = cc;
+    request.data = pktbuf;
+    faddr.address = &addr;
+    init_addr(&faddr, ss2sa(&saddr));
+    /* this address is in net order */
+    if ((retval = dispatch(&request, &faddr, &response))) {
+	com_err(prog, retval, "while dispatching (udp)");
+	return;
+    }
+    cc = sendto(port_fd, response->data, (socklen_t) response->length, 0,
+		(struct sockaddr *)&saddr, saddr_len);
+    if (cc == -1) {
+	char addrbuf[46];
+        krb5_free_data(kdc_context, response);
+	if (inet_ntop(((struct sockaddr *)&saddr)->sa_family,
+		      addr.contents, addrbuf, sizeof(addrbuf)) == 0) {
+	    strcpy(addrbuf, "?");
+	}
+	com_err(prog, errno, "while sending reply to %s/%d",
+		addrbuf, faddr.port);
+	return;
+    }
+    if (cc != response->length) {
+	krb5_free_data(kdc_context, response);
+	com_err(prog, 0, "short reply write %d vs %d\n",
+		response->length, cc);
+	return;
+    }
+    krb5_free_data(kdc_context, response);
+    return;
+}
+
+static int tcp_data_counter;
+static int max_tcp_data_connections = 30;
+
+static void kill_tcp_connection(struct connection *);
+
+static void accept_tcp_connection(struct connection *conn, const char *prog,
+				  int selflags)
+{
+    int s;
+    struct sockaddr_storage addr_s;
+    struct sockaddr *addr = (struct sockaddr *)&addr_s;
+    socklen_t addrlen = sizeof(addr_s);
+    struct socksetup sockdata;
+    struct connection *newconn;
+    char tmpbuf[10];
+
+    s = accept(conn->fd, addr, &addrlen);
+    if (s < 0)
+	return;
+    setnbio(s), setnolinger(s);
+
+    sockdata.prog = prog;
+    sockdata.retval = 0;
+
+    newconn = add_tcp_data_fd(&sockdata, s);
+    if (newconn == 0)
+	return;
+
+    if (getnameinfo((struct sockaddr *)&addr_s, addrlen,
+		    newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf),
+		    tmpbuf, sizeof(tmpbuf),
+		    NI_NUMERICHOST | NI_NUMERICSERV))
+	strcpy(newconn->u.tcp.addrbuf, "???");
+    else {
+	char *p, *end;
+	p = newconn->u.tcp.addrbuf;
+	end = p + sizeof(newconn->u.tcp.addrbuf);
+	p += strlen(p);
+	if (end - p > 2 + strlen(tmpbuf)) {
+	    *p++ = '.';
+	    strcpy(p, tmpbuf);
+	}
+    }
+#if 0
+    krb5_klog_syslog(LOG_INFO, "accepted TCP connection on socket %d from %s",
+		     s, newconn->u.tcp.addrbuf);
+#endif
+
+    newconn->u.tcp.addr_s = addr_s;
+    newconn->u.tcp.addrlen = addrlen;
+    newconn->u.tcp.bufsiz = 1024 * 1024;
+    newconn->u.tcp.buffer = malloc(newconn->u.tcp.bufsiz);
+    newconn->u.tcp.start_time = time(0);
+
+    if (++tcp_data_counter > max_tcp_data_connections) {
+	struct connection *oldest_tcp = NULL;
+	struct connection *c;
+	int i;
+
+	krb5_klog_syslog(LOG_INFO, "too many connections");
+
+	FOREACH_ELT (connections, i, c) {
+	    if (c->type != CONN_TCP)
+		continue;
+	    if (c == newconn)
+		continue;
+#if 0
+	    krb5_klog_syslog(LOG_INFO, "fd %d started at %ld", c->fd,
+			     c->u.tcp.start_time);
+#endif
+	    if (oldest_tcp == NULL
+		|| oldest_tcp->u.tcp.start_time > c->u.tcp.start_time)
+		oldest_tcp = c;
+	}
+	if (oldest_tcp != NULL) {
+	    krb5_klog_syslog(LOG_INFO, "dropping tcp fd %d from %s",
+			     oldest_tcp->fd, oldest_tcp->u.tcp.addrbuf);
+	    kill_tcp_connection(oldest_tcp);
+	}
+    }
+    if (newconn->u.tcp.buffer == 0) {
+	com_err(prog, errno, "allocating buffer for new TCP session from %s",
+		newconn->u.tcp.addrbuf);
+	delete_fd(newconn);
+	close(s);
+	tcp_data_counter--;
+	return;
+    }
+    newconn->u.tcp.offset = 0;
+    newconn->u.tcp.faddr.address = &newconn->u.tcp.kaddr;
+    init_addr(&newconn->u.tcp.faddr, ss2sa(&newconn->u.tcp.addr_s));
+    SG_SET(&newconn->u.tcp.sgbuf[0], newconn->u.tcp.lenbuf, 4);
+    SG_SET(&newconn->u.tcp.sgbuf[1], 0, 0);
+
+    FD_SET(s, &sstate.rfds);
+    if (sstate.max <= s)
+	sstate.max = s + 1;
+}
+
+static void
+kill_tcp_connection(struct connection *conn)
+{
+    if (conn->u.tcp.response)
+	krb5_free_data(kdc_context, conn->u.tcp.response);
+    if (conn->u.tcp.buffer)
+	free(conn->u.tcp.buffer);
+    FD_CLR(conn->fd, &sstate.rfds);
+    FD_CLR(conn->fd, &sstate.wfds);
+    if (sstate.max == conn->fd + 1)
+	while (sstate.max > 0
+	       && ! FD_ISSET(sstate.max-1, &sstate.rfds)
+	       && ! FD_ISSET(sstate.max-1, &sstate.wfds)
+	       /* && ! FD_ISSET(sstate.max-1, &sstate.xfds) */
+	    )
+	    sstate.max--;
+    close(conn->fd);
+    conn->fd = -1;
+    delete_fd(conn);
+    tcp_data_counter--;
+}
+
+static krb5_error_code
+make_toolong_error (krb5_data **out)
+{
+    krb5_error errpkt;
+    krb5_error_code retval;
+    krb5_data *scratch;
+
+    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
+    if (retval)
+	return retval;
+    errpkt.error = KRB_ERR_FIELD_TOOLONG;
+    errpkt.server = tgs_server;
+    errpkt.client = NULL;
+    errpkt.cusec = 0;
+    errpkt.ctime = 0;
+    errpkt.text.length = 0;
+    errpkt.text.data = 0;
+    errpkt.e_data.length = 0;
+    errpkt.e_data.data = 0;
+    scratch = malloc(sizeof(*scratch));
+    if (scratch == NULL)
+	return ENOMEM;
+    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+    if (retval) {
+	free(scratch);
+	return retval;
+    }
+
+    *out = scratch;
+    return 0;
+}
+
+static void
+process_tcp_connection(struct connection *conn, const char *prog, int selflags)
+{
+    if (selflags & SSF_WRITE) {
+	ssize_t nwrote;
+	SOCKET_WRITEV_TEMP tmp;
+
+	nwrote = SOCKET_WRITEV(conn->fd, conn->u.tcp.sgp, conn->u.tcp.sgnum,
+			       tmp);
+	if (nwrote < 0) {
+	    goto kill_tcp_connection;
+	}
+	if (nwrote == 0)
+	    /* eof */
+	    goto kill_tcp_connection;
+	while (nwrote) {
+	    sg_buf *sgp = conn->u.tcp.sgp;
+	    if (nwrote < SG_LEN(sgp)) {
+		SG_ADVANCE(sgp, nwrote);
+		nwrote = 0;
+	    } else {
+		nwrote -= SG_LEN(sgp);
+		conn->u.tcp.sgp++;
+		conn->u.tcp.sgnum--;
+		if (conn->u.tcp.sgnum == 0 && nwrote != 0)
+		    abort();
+	    }
+	}
+	if (conn->u.tcp.sgnum == 0) {
+	    /* finished sending */
+	    /* We should go back to reading, though if we sent a
+	       FIELD_TOOLONG error in reply to a length with the high
+	       bit set, RFC 4120 says we have to close the TCP
+	       stream.  */
+	    goto kill_tcp_connection;
+	}
+    } else if (selflags & SSF_READ) {
+	/* Read message length and data into one big buffer, already
+	   allocated at connect time.  If we have a complete message,
+	   we stop reading, so we should only be here if there is no
+	   data in the buffer, or only an incomplete message.  */
+	size_t len;
+	ssize_t nread;
+	if (conn->u.tcp.offset < 4) {
+	    /* msglen has not been computed */
+	    /* XXX Doing at least two reads here, letting the kernel
+	       worry about buffering.  It'll be faster when we add
+	       code to manage the buffer here.  */
+	    len = 4 - conn->u.tcp.offset;
+	    nread = SOCKET_READ(conn->fd,
+				conn->u.tcp.buffer + conn->u.tcp.offset, len);
+	    if (nread < 0)
+		/* error */
+		goto kill_tcp_connection;
+	    if (nread == 0)
+		/* eof */
+		goto kill_tcp_connection;
+	    conn->u.tcp.offset += nread;
+	    if (conn->u.tcp.offset == 4) {
+		unsigned char *p = (unsigned char *)conn->u.tcp.buffer;
+		conn->u.tcp.msglen = ((p[0] << 24)
+				      | (p[1] << 16)
+				      | (p[2] <<  8)
+				      | p[3]);
+		if (conn->u.tcp.msglen > conn->u.tcp.bufsiz - 4) {
+		    krb5_error_code err;
+		    /* message too big */
+		    krb5_klog_syslog(LOG_ERR, "TCP client %s wants %lu bytes, cap is %lu",
+				     conn->u.tcp.addrbuf, (unsigned long) conn->u.tcp.msglen,
+				     (unsigned long) conn->u.tcp.bufsiz - 4);
+		    /* XXX Should return an error.  */
+		    err = make_toolong_error (&conn->u.tcp.response);
+		    if (err) {
+			krb5_klog_syslog(LOG_ERR,
+					 "error constructing KRB_ERR_FIELD_TOOLONG error! %s",
+					 error_message(err));
+			goto kill_tcp_connection;
+		    }
+		    goto have_response;
+		}
+	    }
+	} else {
+	    /* msglen known */
+	    krb5_data request;
+	    krb5_error_code err;
+
+	    len = conn->u.tcp.msglen - (conn->u.tcp.offset - 4);
+	    nread = SOCKET_READ(conn->fd,
+				conn->u.tcp.buffer + conn->u.tcp.offset, len);
+	    if (nread < 0)
+		/* error */
+		goto kill_tcp_connection;
+	    if (nread == 0)
+		/* eof */
+		goto kill_tcp_connection;
+	    conn->u.tcp.offset += nread;
+	    if (conn->u.tcp.offset < conn->u.tcp.msglen + 4)
+		return;
+	    /* have a complete message, and exactly one message */
+	    request.length = conn->u.tcp.msglen;
+	    request.data = conn->u.tcp.buffer + 4;
+	    err = dispatch(&request, &conn->u.tcp.faddr,
+			   &conn->u.tcp.response);
+	    if (err) {
+		com_err(prog, err, "while dispatching (tcp)");
+		goto kill_tcp_connection;
+	    }
+	have_response:
+	    conn->u.tcp.lenbuf[0] = 0xff & (conn->u.tcp.response->length >> 24);
+	    conn->u.tcp.lenbuf[1] = 0xff & (conn->u.tcp.response->length >> 16);
+	    conn->u.tcp.lenbuf[2] = 0xff & (conn->u.tcp.response->length >> 8);
+	    conn->u.tcp.lenbuf[3] = 0xff & (conn->u.tcp.response->length >> 0);
+	    SG_SET(&conn->u.tcp.sgbuf[1], conn->u.tcp.response->data,
+		   conn->u.tcp.response->length);
+	    conn->u.tcp.sgp = conn->u.tcp.sgbuf;
+	    conn->u.tcp.sgnum = 2;
+	    FD_CLR(conn->fd, &sstate.rfds);
+	    FD_SET(conn->fd, &sstate.wfds);
+	}
+    } else
+	abort();
+
+    return;
+
+kill_tcp_connection:
+    kill_tcp_connection(conn);
+}
+
+static void service_conn(struct connection *conn, const char *prog,
+			 int selflags)
+{
+    conn->service(conn, prog, selflags);
+}
+
+krb5_error_code
+listen_and_process(const char *prog)
+{
+    int			nfound;
+    /* This struct contains 3 fd_set objects; on some platforms, they
+       can be rather large.  Making this static avoids putting all
+       that junk on the stack.  */
+    static struct select_state sout;
+    int			i, sret;
+    krb5_error_code	err;
+
+    if (conns == (struct connection **) NULL)
+	return KDC5_NONET;
+    
+    while (!signal_requests_exit) {
+	if (signal_requests_hup) {
+	    krb5_klog_reopen(kdc_context);
+	    signal_requests_hup = 0;
+	}
+	sstate.end_time.tv_sec = sstate.end_time.tv_usec = 0;
+	err = krb5int_cm_call_select(&sstate, &sout, &sret);
+	if (err) {
+	    com_err(prog, err, "while selecting for network input(1)");
+	    continue;
+	}
+	if (sret == -1) {
+	    if (errno != EINTR)
+		com_err(prog, errno, "while selecting for network input(2)");
+	    continue;
+	}
+	nfound = sret;
+	for (i=0; i<n_sockets && nfound > 0; i++) {
+	    int sflags = 0;
+	    if (conns[i]->fd < 0)
+		abort();
+	    if (FD_ISSET(conns[i]->fd, &sout.rfds))
+		sflags |= SSF_READ, nfound--;
+	    if (FD_ISSET(conns[i]->fd, &sout.wfds))
+		sflags |= SSF_WRITE, nfound--;
+	    if (sflags)
+		service_conn(conns[i], prog, sflags);
+	}
+    }
+    return 0;
+}
+
+krb5_error_code
+closedown_network(const char *prog)
+{
+    int i;
+    struct connection *conn;
+
+    if (conns == (struct connection **) NULL)
+	return KDC5_NONET;
+
+    FOREACH_ELT (connections, i, conn) {
+	if (conn->fd >= 0)
+	    (void) close(conn->fd);
+	DEL (connections, i);
+	/* There may also be per-connection data in the tcp structure
+	   (tcp.buffer, tcp.response) that we're not freeing here.
+	   That should only happen if we quit with a connection in
+	   progress.  */
+	free(conn);
+    }
+    FREE_SET_DATA(connections);
+    FREE_SET_DATA(udp_port_data);
+    FREE_SET_DATA(tcp_port_data);
+
+    return 0;
+}
+
+#endif /* INET */
diff --git a/krb5-1-6/src/kdc/policy.c b/krb5-1-6/src/kdc/policy.c
new file mode 100644
index 000000000..8c0b69272
--- /dev/null
+++ b/krb5-1-6/src/kdc/policy.c
@@ -0,0 +1,75 @@
+/*
+ * kdc/policy.c
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Policy decision routines for KDC.
+ */
+
+#include "k5-int.h"
+#include "kdc_util.h"
+
+int
+against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
+			krb5_db_entry server, krb5_timestamp kdc_time,
+			const char **status)
+{
+#if 0
+     /* An AS request must include the addresses field */
+    if (request->addresses == 0) {
+	*status = "NO ADDRESS";
+	return KRB5KDC_ERR_POLICY;
+    }
+#endif
+    
+    return 0;			/* not against policy */
+}
+
+/*
+ * This is where local policy restrictions for the TGS should placed.
+ */
+krb5_error_code
+against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
+			 krb5_ticket *ticket, const char **status)
+{
+#if 0
+    /*
+     * For example, if your site wants to disallow ticket forwarding,
+     * you might do something like this:
+     */
+    
+    if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) {
+	*status = "FORWARD POLICY";
+	return KRB5KDC_ERR_POLICY;
+    }
+#endif
+    
+    return 0;				/* not against policy */
+}
+
+
+
+
+
+
+
diff --git a/krb5-1-6/src/kdc/policy.h b/krb5-1-6/src/kdc/policy.h
new file mode 100644
index 000000000..fe8307625
--- /dev/null
+++ b/krb5-1-6/src/kdc/policy.h
@@ -0,0 +1,39 @@
+/*
+ * kdc/policy.h
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Declarations for policy.c
+ */
+
+#ifndef __KRB5_KDC_POLICY__
+#define __KRB5_KDC_POLICY__
+
+extern int against_postdate_policy (krb5_timestamp);
+
+extern int against_flag_policy_as (const krb5_kdc_req *);
+
+extern int against_flag_policy_tgs (const krb5_kdc_req *,
+					      const krb5_ticket *);
+
+#endif /* __KRB5_KDC_POLICY__ */
diff --git a/krb5-1-6/src/kdc/replay.c b/krb5-1-6/src/kdc/replay.c
new file mode 100644
index 000000000..e6c48a4ea
--- /dev/null
+++ b/krb5-1-6/src/kdc/replay.c
@@ -0,0 +1,175 @@
+/*
+ * kdc/replay.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Replay lookaside cache for the KDC, to avoid extra work.
+ *
+ */
+
+#include "k5-int.h"
+#include "kdc_util.h"
+#include "extern.h"
+
+#ifndef NOCACHE
+
+typedef struct _krb5_kdc_replay_ent {
+    struct _krb5_kdc_replay_ent *next;
+    int num_hits;
+    krb5_int32 timein;
+    time_t db_age;
+    krb5_data *req_packet;
+    krb5_data *reply_packet;
+} krb5_kdc_replay_ent;
+
+static krb5_kdc_replay_ent root_ptr = {0};
+
+static int hits = 0;
+static int calls = 0;
+static int max_hits_per_entry = 0;
+static int num_entries = 0;
+
+#define STALE_TIME	2*60		/* two minutes */
+#define STALE(ptr) ((abs((ptr)->timein - timenow) >= STALE_TIME) ||	\
+		    ((ptr)->db_age != db_age))
+
+#define MATCH(ptr) (((ptr)->req_packet->length == inpkt->length) &&	\
+		    !memcmp((ptr)->req_packet->data, inpkt->data,	\
+			    inpkt->length) &&				\
+		    ((ptr)->db_age == db_age))
+/* XXX
+   Todo:  quench the size of the queue...
+ */
+
+/* return TRUE if outpkt is filled in with a packet to reply with,
+   FALSE if the caller should do the work */
+
+krb5_boolean
+kdc_check_lookaside(krb5_data *inpkt, krb5_data **outpkt)
+{
+    krb5_int32 timenow;
+    register krb5_kdc_replay_ent *eptr, *last, *hold;
+    time_t db_age;
+
+    if (krb5_timeofday(kdc_context, &timenow) || 
+	krb5_db_get_age(kdc_context, 0, &db_age))
+	return FALSE;
+
+    calls++;
+
+    /* search for a replay entry in the queue, possibly removing
+       stale entries while we're here */
+
+    if (root_ptr.next) {
+	for (last = &root_ptr, eptr = root_ptr.next;
+	     eptr;
+	     eptr = eptr->next) {
+	    if (MATCH(eptr)) {
+		eptr->num_hits++;
+		hits++;
+
+		if (krb5_copy_data(kdc_context, eptr->reply_packet, outpkt))
+		    return FALSE;
+		else
+		    return TRUE;
+		/* return here, don't bother flushing even if it is stale.
+		   if we just matched, we may get another retransmit... */
+	    }
+	    if (STALE(eptr)) {
+		/* flush it and collect stats */
+		max_hits_per_entry = max(max_hits_per_entry, eptr->num_hits);
+		krb5_free_data(kdc_context, eptr->req_packet);
+		krb5_free_data(kdc_context, eptr->reply_packet);
+		hold = eptr;
+		last->next = eptr->next;
+		eptr = last;
+		free(hold);
+	    } else {
+		/* this isn't it, just move along */
+		last = eptr;
+	    }
+	}
+    }
+    return FALSE;
+}
+
+/* insert a request & reply into the lookaside queue.  assumes it's not
+   already there, and can fail softly due to other weird errors. */
+
+void
+kdc_insert_lookaside(krb5_data *inpkt, krb5_data *outpkt)
+{
+    register krb5_kdc_replay_ent *eptr;    
+    krb5_int32 timenow;
+    time_t db_age;
+
+    if (krb5_timeofday(kdc_context, &timenow) || 
+	krb5_db_get_age(kdc_context, 0, &db_age))
+	return;
+
+    /* this is a new entry */
+    eptr = (krb5_kdc_replay_ent *)calloc(1, sizeof(*eptr));
+    if (!eptr)
+	return;
+    eptr->timein = timenow;
+    eptr->db_age = db_age;
+    /*
+     * This is going to hurt a lot malloc()-wise due to the need to
+     * allocate memory for the krb5_data and krb5_address elements.
+     * ARGH!
+     */
+    if (krb5_copy_data(kdc_context, inpkt, &eptr->req_packet)) {
+	free(eptr);
+	return;
+    }
+    if (krb5_copy_data(kdc_context, outpkt, &eptr->reply_packet)) {
+	krb5_free_data(kdc_context, eptr->req_packet);
+	free(eptr);
+	return;
+    }
+    eptr->next = root_ptr.next;
+    root_ptr.next = eptr;
+    num_entries++;
+    return;
+}
+
+/* frees memory associated with the lookaside queue for memory profiling */
+void
+kdc_free_lookaside(krb5_context kcontext)
+{
+    register krb5_kdc_replay_ent *eptr, *last, *hold;
+    if (root_ptr.next) {
+        for (last = &root_ptr, eptr = root_ptr.next;
+	     eptr; eptr = eptr->next) {
+		krb5_free_data(kcontext, eptr->req_packet);
+		krb5_free_data(kcontext, eptr->reply_packet);
+		hold = eptr;
+		last->next = eptr->next;
+		eptr = last;
+		free(hold);
+	}
+    }
+}
+
+#endif /* NOCACHE */
diff --git a/krb5-1-6/src/kdc/rtest.c b/krb5-1-6/src/kdc/rtest.c
new file mode 100644
index 000000000..87f4a9652
--- /dev/null
+++ b/krb5-1-6/src/kdc/rtest.c
@@ -0,0 +1,116 @@
+/*
+ * kdc/rtest.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include "kdc_util.h"
+#include "extern.h"
+
+void krb5_klog_syslog(void);
+
+static krb5_principal 
+make_princ(krb5_context ctx, const char *str, const char *prog)
+{
+    krb5_principal ret;
+    char *dat;
+
+    if(!(ret = (krb5_principal) malloc(sizeof(krb5_principal_data)))) {
+	  com_err(prog, ENOMEM, "while allocating principal data");
+	  exit(3);
+    }
+    memset(ret, 0, sizeof(krb5_principal_data));
+
+    /* We do not include the null... */
+    if(!(dat = (char *) malloc(strlen(str)))) {
+	  com_err(prog, ENOMEM, "while allocating principal realm data");
+	  exit(3);
+    }
+    memcpy(dat, str, strlen(str));
+    krb5_princ_set_realm_data(ctx, ret, dat);
+    krb5_princ_set_realm_length(ctx, ret, strlen(str));
+    
+    return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+	krb5_data otrans;
+	krb5_data ntrans;
+	krb5_principal tgs, cl, sv;
+	krb5_error_code kret;
+	kdc_realm_t	kdc_realm;
+
+	if (argc < 4) {
+	    fprintf(stderr, "not enough args\n");
+	    exit(1);
+	}
+
+
+	/* Get a context */
+	kret = krb5int_init_context_kdc(&kdc_realm.realm_context);
+	if (kret) {
+	  com_err(argv[0], kret, "while getting krb5 context");
+	  exit(2);
+	}
+	/* Needed so kdc_context will work */
+	kdc_active_realm = &kdc_realm;
+
+	ntrans.length = 0;
+	ntrans.data = 0;
+
+	otrans.length = strlen(argv[1]);
+	if (otrans.length) 
+	  otrans.data = (char *) malloc(otrans.length);
+	else 
+	  otrans.data = 0;
+	memcpy(otrans.data,argv[1], otrans.length);
+
+	tgs = make_princ(kdc_context, argv[2], argv[0]);
+	cl  = make_princ(kdc_context, argv[3], argv[0]);
+	sv  = make_princ(kdc_context, argv[4], argv[0]);
+	
+	add_to_transited(&otrans,&ntrans,tgs,cl,sv);
+
+	printf("%s\n",ntrans.data);
+
+	/* Free up all memory so we can profile for leaks */
+	if (otrans.data)
+	  free(otrans.data);
+	free(ntrans.data);
+
+	krb5_free_principal(kdc_realm.realm_context, tgs);
+	krb5_free_principal(kdc_realm.realm_context, cl);
+	krb5_free_principal(kdc_realm.realm_context, sv);
+	krb5_free_context(kdc_realm.realm_context);
+
+	exit(0);
+    }
+
+void krb5_klog_syslog(void) {}
+kdc_realm_t *find_realm_data (char *rname, krb5_ui_4 rsize) { return 0; }
diff --git a/krb5-1-6/src/kdc/rtest.good b/krb5-1-6/src/kdc/rtest.good
new file mode 100644
index 000000000..4eecf6e30
--- /dev/null
+++ b/krb5-1-6/src/kdc/rtest.good
@@ -0,0 +1,26 @@
+ATHENA.MIT.EDU
+MIT.EDU,ATHENA.
+EDU,MIT.,ATHENA.
+EDU,MIT.,ATHENA.,WASHINGTON.EDU
+EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.
+EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W.
+EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W.,SUB3W.CS.WASHINGTON.EDU
+EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W.
+EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W.
+EDU,ATHENA.MIT.,SUB2M.,WASHINGTON.EDU,CS.
+/EDU/MIT/ATHENA
+/EDU/MIT,/ATHENA
+/EDU/MIT,/ATHENA
+/EDU,/MIT,/ATHENA
+/EDU,/MIT,/ATHENA, /EDU/WASHINGTON
+/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS
+/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W
+/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W, /EDU/WASHINGTON/CS/SUB3W
+/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W
+/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W
+/EDU,/MIT/ATHENA,/SUB2M, /EDU/WASHINGTON,/CS
+EDU,MIT.,ATHENA.,ATEST., /COM,/HP,/APOLLO
+EDU,MIT.,ATHENA., /COM,/HP,/APOLLO,/HTEST
+/COM,/HP,/APOLLO,EDU,MIT.,ATHENA.,ATEST.
+/COM,/HP,/APOLLO,ATHENA.MIT.EDU
+EDU,MIT.,ATHENA., /COM/HP/APOLLO/HTEST
diff --git a/krb5-1-6/src/kdc/rtscript b/krb5-1-6/src/kdc/rtscript
new file mode 100755
index 000000000..8803e3325
--- /dev/null
+++ b/krb5-1-6/src/kdc/rtscript
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+#
+#  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.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+# 
+# should print out contents of rtest.good
+#
+./rtest "" ATHENA.MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest ATHENA.MIT.EDU MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "MIT.EDU,ATHENA." EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "EDU,MIT.,ATHENA." WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU" CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS." SUB2W.CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W." SUB3W.CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W." SUB1W.CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W." SUB1M.ATHENA.MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "EDU,SUB2M.ATHENA.MIT.,WASHINGTON.EDU,CS." ATHENA.MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU
+./rtest "" /EDU/MIT/ATHENA /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest /EDU/MIT/ATHENA /EDU/MIT /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest " /EDU/MIT/ATHENA" /EDU/MIT /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU/MIT,/ATHENA" /EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU,/MIT,/ATHENA" /EDU/WASHINGTON /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON" /EDU/WASHINGTON/CS /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS" /EDU/WASHINGTON/CS/SUB2W /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W" /EDU/WASHINGTON/CS/SUB3W /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W" /EDU/WASHINGTON/CS/SUB1W /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W" /EDU/MIT/ATHENA/SUB1M /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/EDU,/MIT/ATHENA/SUB2M, /EDU/WASHINGTON,/CS" /EDU/MIT/ATHENA /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "EDU,MIT.,ATHENA., /COM,/HP,/APOLLO" ATEST.ATHENA.MIT.EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "EDU,MIT.,ATHENA., /COM,/HP,/APOLLO" /COM/HP/APOLLO/HTEST /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/COM,/HP,/APOLLO,EDU,MIT.,ATHENA." ATEST.ATHENA.MIT.EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "/COM,/HP,/APOLLO" ATHENA.MIT.EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
+./rtest "EDU,MIT.,ATHENA." /COM/HP/APOLLO/HTEST /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M
diff --git a/krb5-1-6/src/krb5-config.M b/krb5-1-6/src/krb5-config.M
new file mode 100644
index 000000000..c0a0fa140
--- /dev/null
+++ b/krb5-1-6/src/krb5-config.M
@@ -0,0 +1,74 @@
+.\" krb5-config.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\"
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KRB5-CONFIG 1
+.SH NAME
+krb5-config \- tool for linking against MIT Kerberos libraries
+.SH SYNOPSIS
+.B krb5-config
+[ \fB--help\fP | \fB--all\fP | \fB--version\fP | \fB--vendor\fP | \fB--prefix\fP | 
+\fB--exec-prefix\fP | \fB--cflags\fP | \fB--libs\fP libraries ]
+.br
+.SH DESCRIPTION
+.I krb5-config
+tells the application programmer what special flags to use to compile
+and link programs against the installed Kerberos libraries.
+.SH OPTIONS
+.TP
+\fB\--help\fP
+print usage message.  This is the default.
+.TP
+\fB\--all\fP
+prints version, vendor, prefix and exec-prefix.
+.TP
+\fB\--version\fP
+prints the version of the installed Kerberos implementation.
+.TP
+\fB\--vendor\fP
+prints the vendor of the installed Kerberos implementation.
+.TP
+\fB\--prefix\fP 
+prints the prefix with which Kerberos was built.
+.TP
+\fB\--exec-prefix\fP 
+prints the exec-prefix with which Kerberos was built.
+.TP
+\fB\--cflags\fP 
+prints the compiler flags with which Kerberos was built.
+.TP
+\fB\--libs\fP \fIlibraries\fP 
+list compiler options required to link with \fIlibraries\fP.  Possible 
+values for \fIlibraries\fP are:
+.sp
+.nf
+.in +.5i
+krb5         Kerberos 5 application
+gssapi       GSSAPI application with Kerberos 5 bindings
+krb4         Kerberos 4 application
+kadm-client  Kadmin client
+kadm-server  Kadmin server
+kdb          Application that accesses the kerberos database
+.in -.5i
+.fi
+.SH SEE ALSO
+kerberos(1), cc(1)
diff --git a/krb5-1-6/src/krb5-config.in b/krb5-1-6/src/krb5-config.in
new file mode 100755
index 000000000..341450cd2
--- /dev/null
+++ b/krb5-1-6/src/krb5-config.in
@@ -0,0 +1,226 @@
+#!/bin/sh
+
+# Copyright 2001, 2002, 2003 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+#
+
+# Configurable parameters set by autoconf
+version_string="Kerberos 5 release @KRB5_VERSION@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+includedir=@includedir@
+libdir=@libdir@
+CC_LINK='@CC_LINK@'
+KRB4_LIB=@KRB4_LIB@
+DES425_LIB=@DES425_LIB@
+KDB5_DB_LIB=@KDB5_DB_LIB@
+LDFLAGS='@LDFLAGS@'
+RPATH_FLAG='@RPATH_FLAG@'
+PTHREAD_CFLAGS='@PTHREAD_CFLAGS@'
+DL_LIB='@DL_LIB@'
+
+LIBS='@LIBS@'
+GEN_LIB=@GEN_LIB@
+
+# Defaults for program
+library=krb5
+
+# Some constants
+vendor_string="Massachusetts Institute of Technology"
+
+# Process arguments
+# Yes, we are sloppy, library specifications can come before options
+while test $# != 0; do
+    case $1 in
+	--all)
+	    do_all=1
+	    ;;
+	--cflags)
+	    do_cflags=1
+	    ;;
+	--deps)
+	    do_deps=1
+	    ;;
+	--exec-prefix)
+	    do_exec_prefix=1
+	    ;;
+	--help)
+	    do_help=1
+	    ;;
+	--libs)
+	    do_libs=1
+	    ;;
+	--prefix)
+	    do_prefix=1
+	    ;;
+	--vendor)
+	    do_vendor=1
+	    ;;
+	--version)
+	    do_version=1
+	    ;;
+	krb5)
+	    library=krb5
+	    ;;
+	gssapi)
+	    library=gssapi
+	    ;;
+	krb4)
+	    library=krb4
+	    ;;
+	kadm-client)
+	    library=kadm_client
+	    ;;
+	kadm-server)
+	    library=kadm_server
+	    ;;
+	kdb)
+	    library=kdb
+	    ;;
+	*)
+	    echo "$0: Unknown option \`$1' -- use \`--help' for usage"
+	    exit 1
+    esac
+    shift
+done
+
+# If required options - provide help
+if test -z "$do_all" -a -z "$do_version" -a -z "$do_vendor" -a -z "$do_prefix" -a -z "$do_vendor" -a -z "$do_exec_prefix" -a -z "$do_cflags" -a -z "$do_libs"; then
+    do_help=1
+fi
+
+
+if test -n "$do_help"; then
+    echo "Usage: $0 [OPTIONS] [LIBRARIES]"
+    echo "Options:"
+    echo "        [--help]          Help"
+    echo "        [--all]           Display version, vendor, and various values"
+    echo "        [--version]       Version information"
+    echo "        [--vendor]        Vendor information"
+    echo "        [--prefix]        Kerberos installed prefix"
+    echo "        [--exec-prefix]   Kerberos installed exec_prefix"
+    echo "        [--cflags]        Compile time CFLAGS"
+    echo "        [--libs]          List libraries required to link [LIBRARIES]"
+    echo "Libraries:"
+    echo "        krb5              Kerberos 5 application"
+    echo "        gssapi            GSSAPI application with Kerberos 5 bindings"
+    echo "        krb4              Kerberos 4 application"
+    echo "        kadm-client       Kadmin client"
+    echo "        kadm-server       Kadmin server"
+    echo "        kdb               Application that accesses the kerberos database"
+    exit 0
+fi
+
+if test -n "$do_all"; then
+    all_exit=
+    do_version=1
+    do_prefix=1
+    do_exec_prefix=1
+    do_vendor=1
+    title_version="Version:     "
+    title_prefix="Prefix:      "
+    title_exec_prefix="Exec_prefix: "
+    title_vendor="Vendor:      "
+else
+    all_exit="exit 0"
+fi
+
+if test -n "$do_version"; then
+    echo "$title_version$version_string"
+    $all_exit
+fi
+
+if test -n "$do_vendor"; then
+    echo "$title_vendor$vendor_string"
+    $all_exit
+fi
+
+if test -n "$do_prefix"; then
+    echo "$title_prefix$prefix"
+    $all_exit
+fi
+
+if test -n "$do_exec_prefix"; then
+    echo "$title_exec_prefix$exec_prefix"
+    $all_exit
+fi
+
+if test -n "$do_cflags"; then
+    if test x"$includedir" != x"/usr/include" ; then
+        echo "-I${includedir}"
+    else
+        echo ''
+    fi
+fi
+
+
+if test -n "$do_libs"; then
+    # Ugly gross hack for our build tree
+    lib_flags=`echo $CC_LINK | sed -e 's/\$(CC)//' \
+	    -e 's/\$(PURE)//' \
+	    -e 's#\$(PROG_RPATH)#'$libdir'#' \
+	    -e 's#\$(PROG_LIBPATH)#-L'$libdir'#' \
+	    -e 's#\$(RPATH_FLAG)#'"$RPATH_FLAG"'#' \
+	    -e 's#\$(LDFLAGS)#'"$LDFLAGS"'#' \
+	    -e 's#\$(PTHREAD_CFLAGS)#'"$PTHREAD_CFLAGS"'#' \
+	    -e 's#\$(CFLAGS)#'"$CFLAGS"'#'`
+
+    if test $library = 'kdb'; then
+	lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB"
+	library=krb5
+    fi
+
+    if test $library = 'kadm_server'; then
+	lib_flags="$lib_flags -lkadm5srv -lkdb5 $KDB5_DB_LIB"
+	library=kadm_common
+    fi
+
+    if test $library = 'kadm_client'; then
+	lib_flags="$lib_flags -lkadm5clnt"
+	library=kadm_common
+    fi
+
+    if test $library = 'kadm_common'; then
+	lib_flags="$lib_flags -lgssrpc"
+	library=gssapi
+    fi
+
+    if test $library = 'gssapi'; then
+	lib_flags="$lib_flags -lgssapi_krb5"
+	library=krb5
+    fi
+
+    if test $library = 'krb4'; then
+	lib_flags="$lib_flags $KRB4_LIB $DES425_LIB"
+	library=krb5
+    fi
+
+    if test $library = 'krb5'; then
+	lib_flags="$lib_flags -lkrb5 -lk5crypto -lcom_err $GEN_LIB $LIBS $DL_LIB"
+    fi
+
+    echo $lib_flags
+fi
+
+exit 0
diff --git a/krb5-1-6/src/krb524/Makefile.in b/krb5-1-6/src/krb524/Makefile.in
new file mode 100644
index 000000000..e5f6b6d44
--- /dev/null
+++ b/krb5-1-6/src/krb524/Makefile.in
@@ -0,0 +1,176 @@
+thisconfigdir=..
+myfulldir=krb524
+mydir=krb524
+BUILDTOP=$(REL)..
+KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+DEFS=
+
+# Copyright 1994 by OpenVision Technologies, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software
+# and its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appears in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of OpenVision not be used
+# in advertising or publicity pertaining to distribution of the software
+# without specific, written prior permission. OpenVision makes no
+# representations about the suitability of this software for any
+# purpose.  It is provided "as is" without express or implied warranty.
+# 
+# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+# 
+
+DEFINES = -DUSE_MASTER -DKRB524_PRIVATE=1
+PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+##WIN32##!if ("$(CPU)" == "i386") && defined(USE_ALTERNATE_KRB4_INCLUDES)
+##WIN32##KRB4_INCLUDES=-I$(USE_ALTERNATE_KRB4_INCLUDES)
+##WIN32##!endif
+
+##WIN32##!if ("$(CPU)" == "i386") && defined(USE_ALTERNATE_KRB4_LIB)
+##WIN32##K4LIB=$(USE_ALTERNATE_KRB4_LIB)
+##WIN32##!endif
+
+K524EXE = $(OUTPRE)k524init.exe
+K524LIB = $(OUTPRE)krb524.lib
+K524DEP = $(K524LIB)
+K524DEF = krb524.def
+WINLIBS = kernel32.lib ws2_32.lib user32.lib shell32.lib oldnames.lib \
+	version.lib advapi32.lib gdi32.lib
+
+LOCALINCLUDES= $(KRB4_INCLUDES) -I. -I$(srcdir)
+
+# Library sources
+SRCS	= \
+	$(srcdir)/conv_princ.c \
+	$(srcdir)/cnv_tkt_skey.c \
+	$(srcdir)/libinit.c	\
+    $(srcdir)/krb524.c
+
+EXTRADEPSRCS = \
+	$(srcdir)/test.c \
+	$(srcdir)/k524init.c \
+	$(srcdir)/krb524d.c
+
+##WIN32##!ifdef KRB524_STATIC_HACK
+##WIN32##LPREFIX=..\lib
+##WIN32##K5_GLUE=$(LPREFIX)\$(OUTPRE)k5_glue.obj
+##WIN32##KLIBS = $(LPREFIX)\krb5\$(OUTPRE)krb5.lib \
+##WIN32##	$(LPREFIX)\crypto\$(OUTPRE)crypto.lib \
+##WIN32##	$(BUILDTOP)\util\profile\$(OUTPRE)profile.lib \
+##WIN32##	$(LPREFIX)\des425\$(OUTPRE)des425.lib
+##WIN32##KLIB=$(KLIBS) $(DNSLIBS) $(K5_GLUE) $(CLIB)
+##WIN32##STLIBOBJS=$(STLIBOBJS:libinit=globals)
+##WIN32##K524DEP=$(STLIBOBJS)
+##WIN32##!endif
+
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##EXERES=$(K524EXE:.exe=.res)
+##WIN32##LIBRES=$(K524LIB:.lib=.res)
+
+##WIN32##$(EXERES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKRB524_INIT -fo $@ -r $**
+##WIN32##$(LIBRES): $(VERSIONRC)
+##WIN32##        $(RC) $(RCFLAGS) -DKRB524_LIB -fo $@ -r $**
+
+all-unix:: krb524d krb524test k524init
+
+##WIN32##all-windows:: $(K524EXE) $(K524LIB)
+
+krb524test: test.o $(KRB5_DEPLIB) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o krb524test test.o $(KRB5_LIB) $(KRB4COMPAT_LIBS)
+
+SERVER_OBJS= krb524d.o cnv_tkt_skey.o conv_princ.o
+CLIENT_OBJS= $(OUTPRE)k524init.$(OBJEXT)
+
+krb524d: $(SERVER_OBJS) $(KADMSRV_DEPLIBS) $(KRB5_DEPLIB) $(KRB4COMPAT_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o krb524d $(SERVER_OBJS) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_LIB) $(KRB4COMPAT_LIBS) $(APPUTILS_LIB)
+
+k524init: $(CLIENT_OBJS) $(KRB5_DEPLIB) $(KRB4COMPAT_DEPLIBS)
+	$(CC_LINK) -o k524init $(CLIENT_OBJS) $(KRB5_LIB) $(KRB4COMPAT_LIBS)
+
+##WIN32##$(K524LIB): $(OUTPRE)krb524.$(OBJEXT) $(OUTPRE)libinit.$(OBJEXT) $(KLIB) $(CLIB) $(LIBRES)
+##WIN32##	link $(DLL_LINKOPTS) -def:$(K524DEF) -out:$*.dll $** $(WINLIBS)
+##WIN32##	$(_VC_MANIFEST_EMBED_DLL)
+
+##WIN32##$(K524EXE): $(OUTPRE)k524init.$(OBJEXT) $(KLIB) $(K4LIB) $(CLIB) $(EXERES) $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib
+##WIN32##	link $(EXE_LINKOPTS) -out:$@ $** $(WINLIBS) $(SCLIB)
+##WIN32##	$(_VC_MANIFEST_EMBED_EXE)
+
+install-unix::
+	$(INSTALL_PROGRAM) krb524d $(DESTDIR)$(SERVER_BINDIR)/krb524d
+	$(INSTALL_PROGRAM) k524init $(DESTDIR)$(CLIENT_BINDIR)/krb524init
+	$(INSTALL_DATA) $(srcdir)/krb524d.M $(DESTDIR)$(SERVER_MANDIR)/krb524d.8
+	$(INSTALL_DATA) $(srcdir)/k524init.M \
+		$(DESTDIR)$(CLIENT_MANDIR)/krb524init.1
+
+clean-unix::
+	$(RM) $(OBJS) core *~ *.bak #*
+	$(RM) krb524test krb524d k524init test.o $(CLIENT_OBJS) $(SERVER_OBJS)
+
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)conv_princ.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h conv_princ.c krb524d.h
+$(OUTPRE)cnv_tkt_skey.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  cnv_tkt_skey.c krb524d.h
+$(OUTPRE)libinit.$(OBJEXT): libinit.c
+$(OUTPRE)krb524.$(OBJEXT): krb524.c
+$(OUTPRE)test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  test.c
+$(OUTPRE)k524init.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  k524init.c
+$(OUTPRE)krb524d.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(KRB_ERR_H_DEP) \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  krb524d.c krb524d.h
diff --git a/krb5-1-6/src/krb524/README b/krb5-1-6/src/krb524/README
new file mode 100644
index 000000000..dd7ca9c23
--- /dev/null
+++ b/krb5-1-6/src/krb524/README
@@ -0,0 +1,154 @@
+Copyright 1994 by OpenVision Technologies, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appears in all copies and
+that both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of OpenVision not be used
+in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. OpenVision makes no
+representations about the suitability of this software for any
+purpose.  It is provided "as is" without express or implied warranty.
+
+OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Kerberos V5 to Kerberos V4 Credentials Converting Service, ALPHA RELEASE
+========================================================================
+
+krb524 is a service that converts Kerberos V5 credentials into
+Kerberos V4 credentials suitable for use with applications that for
+whatever reason do not use V5 directly.  The service consists of a
+server that has access to the secret key of the Kerberos service for
+which credentials will be converted, and a library for use by client
+programs that wish to use the server.
+
+The protocol is simple.  Suppose that a client C wishes to obtain V4
+credentials for a V5 service S by using the krb524 server.  The
+notation {C,S}_n represents a Vn service ticket for S for use by C.
+
+(1) C obtains V5 credentials, including a ticket {C,S}_5, for S by the
+normal V5 means.
+
+(2) C transmits {C,S}_5 to KRB524.
+
+(3) KRB524 converts {C,S}_5 into {C,S}_4.
+
+(4) KRB524 transmits {C,S}_4 to C.
+
+(5) C creates a V4 credentials strucuture from the plaintext
+information in the V5 credential and {C,S}_4.
+
+Steps (2) through (4) are encapsulated in a single function call in
+the krb524 library.
+
+An alternate conversion is provided for AFS servers that support the
+encrypted part of a krb5 ticket as an AFS token.  If the krb524d is
+converting a principal whose first component is afs and if the
+encrypted part of the ticket fits in 344 bytes, then it will default
+to simply returning the encrypted part of the ticket as a token.  If
+it turns out that the AFS server does not support the ticket, then
+users will get an unknown key version error and the krb524d must be
+configured to use v4 tickets for this AFS service.
+
+
+Obviously, not all V5 credentials can be completely converted to V4
+credentials, since the former is a superset of the latter.  The
+precise semantics of the conversion function are still undecided.
+UTSL.
+
+Programs contained in this release
+======================================================================
+
+krb524d [-m[aster]] [-k[eytab]]
+
+The krb524 server.  It accepts UDP requests on the krb524 service
+port, specified in /etc/services, or on port 4444 by default.  (A
+request for an official port assignment is underway.)  The -m argument
+causes krb524d to access the KDC master database directly; the -k
+argument causes krb524d to use the default keytab (and therefore only
+be able to convert tickets for services in the keytab).  Only one of
+-m or -k can be specified.
+
+test -remote server client service
+
+A test program that obtains a V5 credential for {client,service},
+converts it to a V4 credential, and prints out the entire contents of
+both versions.  It prompts for service's secret key, which it needs to
+decrypt both tickets in order to print them out.  Enter it as an eight
+digit ASCII hex number.
+
+k524init [-n] [-p principal]
+
+Convert a V5 credential into a V4 credential and store it in a V4
+ticket file.  The client is 'principal', or krbtgt at the V5 ccache's
+default principal's realm if not specified.  The -n argument causes
+the new ticket to be added to the existing ticket file; otherwise, the
+ticket file is initialized.
+
+Configuring krb524d AFS Conversion
+======================================================================
+
+The krb524d looks in the appdefaults  section of krb5.conf for an
+application called afs_krb5 to determine whether  afs principals
+support encrypted ticket parts as tokens.  The following configuration
+fragment says that afs/sipb.mit.edu@ATHENA.MIT.EDU supports the new
+token format but afs@ATHENA.MIT.EDU and
+afs/athena.mit.edu@ATHENA.MIT.EDU do not.  Note that the default is to
+assume afs servers support the new format.
+
+[appdefaults]
+afs_krb5 = { 
+	ATHENA.MIT.EDU = {
+		# This stanza describes principals in the
+		#ATHENA.MIT.EDU realm
+		afs = false
+		afs/athena.mit.edu = false
+		afs/sipb.mit.edu = true
+	}
+}
+
+
+Using libkrb524.a
+======================================================================
+
+To use libkrb524.a, #include "krb524.h", link against libkrb524.a,
+call krb524_init_ets() at the beginning of your program, and call one
+of the following two functions:
+
+int krb524_convert_creds_addr(krb5_creds *v5creds, CREDENTIALS *v4creds,
+			 struct sockaddr *saddr)
+
+int krb524_convert_creds_kdc(krb5_creds *v5creds, CREDENTIALS *v4creds)
+
+Both convert the V5 credential in v5creds into a V4 credential in
+v4creds.  One assumes krb524d is running on the KDC, the other uses an
+explicit host.  You only need to specify the address for saddr; the
+port is filled in automatically.
+
+Unresolved issues / Bugs
+======================================================================
+
+o krb524d requires access to the secret key of any service to be
+converted.  Should krb524d run on the KDC or on individual server
+machines?  The latter is more paranoid, since it prevents bugs in
+krb524d from provided unauthorized access to the master database.
+However, it also requires the client to provide the address of the
+server to be used.  The client will usually have this information
+(since presumably it will be sending the converted V4 credentials to
+the same server) but it may not be in a convenient form.  It seems
+"cleaner" to have krb524d run on the KDC.
+
+o Even if krb524d uses keytabs on server machines, it needs to be more
+flexible.  You only want to run one krb524d per host, so it has to be
+able to scan multiple keytabs.  This might get logistically messy.
+
+o This code is of alpha quality.  Bugs, omissions, memory leaks, and
+perhaps security holes still remain.  Do not use it (yet) in a
+production environment.
diff --git a/krb5-1-6/src/krb524/cnv_tkt_skey.c b/krb5-1-6/src/krb524/cnv_tkt_skey.c
new file mode 100644
index 000000000..97d8bbfdd
--- /dev/null
+++ b/krb5-1-6/src/krb524/cnv_tkt_skey.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2003  by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.	Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "k5-int.h"		/* we need krb5_context::clockskew */
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include "port-sockets.h"
+#else
+#include <sys/time.h>
+#include <netinet/in.h>
+#endif
+#include <krb.h>
+#include "krb524d.h"
+
+static int krb524d_debug = 0;
+
+/*
+ * Convert a v5 ticket for server to a v4 ticket, using service key
+ * skey for both.
+ */
+int krb524_convert_tkt_skey(context, v5tkt, v4tkt, v5_skey, v4_skey,
+			    saddr)
+     krb5_context context;
+     krb5_ticket *v5tkt;
+     KTEXT_ST *v4tkt;
+     krb5_keyblock *v5_skey, *v4_skey;
+     struct sockaddr_in *saddr;
+{
+     char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+     char sname[ANAME_SZ], sinst[INST_SZ], srealm[REALM_SZ];
+     krb5_enc_tkt_part *v5etkt;
+     int ret, lifetime, v4endtime;
+     krb5_timestamp server_time;
+     struct sockaddr_in *sinp = (struct sockaddr_in *)saddr;
+     krb5_address kaddr;
+
+     v5tkt->enc_part2 = NULL;
+     if ((ret = krb5_decrypt_tkt_part(context, v5_skey, v5tkt))) {
+	  return ret;
+     }
+     v5etkt = v5tkt->enc_part2;
+
+     if (v5etkt->transited.tr_contents.length != 0) {
+	 /* Some intermediate realms transited -- do we accept them?
+
+	    Simple answer: No.
+
+	    More complicated answer: Check our local config file to
+	    see if the path is correct, and base the answer on that.
+	    This denies the krb4 application server any ability to do
+	    its own validation as krb5 servers can.
+
+	    Fast answer: Not right now.  */
+	  krb5_free_enc_tkt_part(context, v5etkt);
+	  v5tkt->enc_part2 = NULL;
+	  return KRB5KRB_AP_ERR_ILL_CR_TKT;
+     }
+     /* We could also encounter a case where luser@R1 gets a ticket
+	for krbtgt/R3@R2, and then tries to convert it.  But the
+	converted ticket would be one the v4 KDC code should reject
+	anyways.  So we don't need to worry about it here.  */
+
+     if ((ret = krb524_convert_princs(context, v5etkt->client, v5tkt->server,
+				     pname, pinst, prealm, sname,
+				     sinst, srealm))) {
+	  krb5_free_enc_tkt_part(context, v5etkt);
+	  v5tkt->enc_part2 = NULL;
+	  return ret;
+     }
+     if ((v5etkt->session->enctype != ENCTYPE_DES_CBC_CRC &&
+	  v5etkt->session->enctype != ENCTYPE_DES_CBC_MD4 &&
+	  v5etkt->session->enctype != ENCTYPE_DES_CBC_MD5) ||
+	 v5etkt->session->length != sizeof(C_Block)) {
+	  if (krb524d_debug)
+	       fprintf(stderr, "v5 session keyblock type %d length %d != C_Block size %d\n",
+		       v5etkt->session->enctype,
+		       v5etkt->session->length,
+		       (int) sizeof(C_Block));
+	  krb5_free_enc_tkt_part(context, v5etkt);
+	  v5tkt->enc_part2 = NULL;
+	  return KRB524_BADKEY;
+     }
+     
+     /* V4 has no concept of authtime or renew_till, so ignore them */
+     if (v5etkt->times.starttime == 0)
+	  v5etkt->times.starttime = v5etkt->times.authtime;
+     /* rather than apply fit an extended v5 lifetime into a v4 range,
+	give out a v4 ticket with as much of the v5 lifetime is available
+	"now" instead. */
+     if ((ret = krb5_timeofday(context, &server_time))) {
+         if (krb524d_debug)
+	      fprintf(stderr, "krb5_timeofday failed!\n");
+	 krb5_free_enc_tkt_part(context, v5etkt);
+	 v5tkt->enc_part2 = NULL;
+	 return ret;       
+     }
+     if ((server_time + context->clockskew >= v5etkt->times.starttime)
+	 && (server_time - context->clockskew <= v5etkt->times.endtime)) {
+	  lifetime = krb_time_to_life(server_time, v5etkt->times.endtime);
+	  v4endtime = krb_life_to_time(server_time, lifetime);
+	  /*
+	   * Adjust start time backwards if the lifetime value
+	   * returned by krb_time_to_life() maps to a longer lifetime
+	   * than that of the original krb5 ticket.
+	   */
+	  if (v4endtime > v5etkt->times.endtime)
+	      server_time -= v4endtime - v5etkt->times.endtime;
+     } else {
+          if (krb524d_debug)
+	       fprintf(stderr, "v5 ticket time out of bounds\n");
+	  krb5_free_enc_tkt_part(context, v5etkt);
+	  v5tkt->enc_part2 = NULL;
+	  if (server_time+context->clockskew < v5etkt->times.starttime)
+	       return KRB5KRB_AP_ERR_TKT_NYV;
+	  else if (server_time-context->clockskew > v5etkt->times.endtime)
+	       return KRB5KRB_AP_ERR_TKT_EXPIRED;
+	  else /* shouldn't happen, but just in case... */
+	    return KRB5KRB_AP_ERR_TKT_NYV;
+     }
+
+     kaddr.addrtype = ADDRTYPE_INET;
+     kaddr.length = sizeof(sinp->sin_addr);
+     kaddr.contents = (krb5_octet *)&sinp->sin_addr;
+
+     if (!krb5_address_search(context, &kaddr, v5etkt->caddrs)) {
+	 if (krb524d_debug)
+	     fprintf(stderr, "Invalid v5creds address information.\n");
+	 krb5_free_enc_tkt_part(context, v5etkt);
+	 v5tkt->enc_part2 = NULL;
+	 return KRB524_BADADDR;
+     }
+
+     if (krb524d_debug)
+	printf("startime = %ld, authtime = %ld, lifetime = %ld\n",
+	       (long) v5etkt->times.starttime,
+	       (long) v5etkt->times.authtime,
+	       (long) lifetime);
+
+     /* XXX are there V5 flags we should map to V4 equivalents? */
+     if (v4_skey->enctype == ENCTYPE_DES_CBC_CRC) {
+	 ret = krb_create_ticket(v4tkt,
+				 0, /* flags */			     
+				 pname,
+				 pinst,
+				 prealm,
+				 sinp->sin_addr.s_addr,
+				 (char *) v5etkt->session->contents,
+				 lifetime,
+				 /* issue_data */
+				 server_time,
+				 sname,
+				 sinst,
+				 v4_skey->contents);
+     }
+     else abort();
+     krb5_free_enc_tkt_part(context, v5etkt);
+     v5tkt->enc_part2 = NULL;
+     if (ret == KSUCCESS)
+	  return 0;
+     else
+	  return KRB524_V4ERR;
+}
diff --git a/krb5-1-6/src/krb524/conv_princ.c b/krb5-1-6/src/krb524/conv_princ.c
new file mode 100644
index 000000000..5ec2940d7
--- /dev/null
+++ b/krb5-1-6/src/krb524/conv_princ.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "krb5.h"
+#include <krb.h>
+#include "krb524d.h"
+
+int krb524_convert_princs(context, client, server, pname, pinst, prealm, 
+			  sname, sinst, srealm)
+     krb5_context context;
+     krb5_principal client, server;
+     char *pname, *pinst, *prealm, *sname, *sinst, *srealm;
+{
+     int ret;
+     
+     if ((ret = krb5_524_conv_principal(context, client, pname, pinst, 
+					prealm)))
+	  return ret;
+     
+     return krb5_524_conv_principal(context, server, sname, sinst, srealm);
+}
diff --git a/krb5-1-6/src/krb524/k524init.M b/krb5-1-6/src/krb524/k524init.M
new file mode 100644
index 000000000..f480767a0
--- /dev/null
+++ b/krb5-1-6/src/krb524/k524init.M
@@ -0,0 +1,47 @@
+.\" krb524/k524init.M
+.\"
+.\" Copyright 2005 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\"
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KRB524INIT 1
+.SH NAME
+krb524init \- Obtain Kerberos V4 tickets from Kerberos V5 tickets
+.SH SYNOPSIS
+\fBkrb524init\fP [\fB\-n\fP] [\fB\-p\fP \fIprincipal\fP]
+.SH DESCRIPTION
+.I krb524init
+converts a V5 credential to a V4 credential by querying a remote krb524d
+server and stores it in a V4 ticket cache.  The credential is
+.I principal
+or "krbtgt" at the V5 ticket cache's default principal's realm if not
+specified.
+.SH OPTIONS
+.TP
+.B \-n
+By default, the V4 ticket cache is initialized.  If this option is given,
+the converted credential is instead added to the existing ticket cache.
+.TP
+\fB\-p\fP \fIprincipal\fP
+Convert
+.I principal
+rather than krbtgt.
+.SH SEE ALSO
+kinit(1), krb524d(8)
diff --git a/krb5-1-6/src/krb524/k524init.c b/krb5-1-6/src/krb524/k524init.c
new file mode 100644
index 000000000..73f3650ed
--- /dev/null
+++ b/krb5-1-6/src/krb524/k524init.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "autoconf.h"
+#include <krb5.h>
+#include "com_err.h"
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#endif
+
+#include <krb.h>
+
+extern int optind;
+extern char *optarg;
+char *prog = "k524init";
+
+int main(argc, argv)
+     int argc;
+     char **argv;
+{
+     krb5_principal client, server;
+     krb5_ccache cc;
+     krb5_creds increds, *v5creds;
+     CREDENTIALS v4creds;
+     int code;
+     int option;
+     char *princ = NULL;
+     int nodelete = 0;
+     int lose = 0;
+     krb5_context context;
+     krb5_error_code retval;
+
+     if (argv[0]) {
+	 prog = strrchr (argv[0], '/');
+	 if (prog)
+	     prog++;
+	 else
+	     prog = argv[0];
+     }
+
+     retval = krb5_init_context(&context);
+     if (retval) {
+	     com_err(prog, retval, "while initializing krb5");
+	     exit(1);
+     }
+
+     while(((option =  getopt(argc, argv, "p:n")) != -1)) {
+	 switch(option) {
+	   case 'p':
+	     princ = optarg;
+	     break;
+	   case 'n':
+	     nodelete++;
+	     break;
+	   default:
+	     lose++;
+	     break;
+	 }
+     }
+
+     if (lose || (argc - optind > 1)) {
+	 fprintf(stderr, "Usage: %s [-p principal] [-n]\n", prog);
+	 exit(1);
+     }
+
+     if ((code = krb5_cc_default(context, &cc))) {
+	  com_err(prog, code, "opening default credentials cache");
+	  exit(1);
+     }
+
+     if ((code = krb5_cc_get_principal(context, cc, &client))) {
+	 com_err(prog, code, "while retrieving user principal name");
+	 exit(1);
+     }
+
+     if (princ) {
+	 if ((code = krb5_parse_name(context, princ, &server))) {
+	     com_err(prog, code, "while parsing service principal name");
+	     exit(1);
+	 }
+     } else {
+	 if ((code = krb5_build_principal(context, &server, 
+					  krb5_princ_realm(context, client)->length,
+					  krb5_princ_realm(context, client)->data,
+					  "krbtgt",
+					  krb5_princ_realm(context, client)->data,
+					  NULL))) {
+	     com_err(prog, code, "while creating service principal name");
+	     exit(1);
+	 }
+     }
+
+     if (!nodelete) {
+	 krb5_data *crealm = krb5_princ_realm (context, client);
+	 krb5_data *srealm = krb5_princ_realm (context, server);
+	 if (crealm->length != srealm->length
+	     || memcmp (crealm->data, srealm->data, crealm->length)) {
+	     /* Since krb4 ticket files don't store the realm name
+		separately, and the client realm is assumed to be the
+		realm of the first ticket, let's not store an initial
+		ticket with the wrong realm name, since it'll confuse
+		other programs.  */
+	     fprintf (stderr,
+		      "%s: Client and server principals' realm names are different;\n"
+		      "\tbecause of limitations in the krb4 ticket file implementation,\n"
+		      "\tthis doesn't work for an initial ticket.  Try `%s -n'\n"
+		      "\tif you already have other krb4 tickets, or convert the\n"
+		      "\tticket-granting ticket from your home realm.\n",
+		      prog, prog);
+	     exit (1);
+	 }
+     }
+
+     memset((char *) &increds, 0, sizeof(increds));
+     increds.client = client;
+     increds.server = server;
+     increds.times.endtime = 0;
+     increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+     if ((code = krb5_get_credentials(context, 0, cc, &increds, &v5creds))) {
+	  com_err(prog, code, "getting V5 credentials");
+	  exit(1);
+     }
+
+     if ((code = krb5_524_convert_creds(context, v5creds, &v4creds))) {
+	  com_err(prog, code, "converting to V4 credentials");
+	  exit(1);
+     }
+     
+     /* this is stolen from the v4 kinit */
+
+     if (!nodelete) {
+	 /* initialize ticket cache */
+	 code = krb_in_tkt(v4creds.pname,v4creds.pinst,v4creds.realm);
+	 if (code != KSUCCESS) {
+	     fprintf (stderr, "%s: %s trying to create the V4 ticket file",
+		      prog, krb_get_err_text (code));
+	     exit(1);
+	 }
+     }
+
+     /* stash ticket, session key, etc. for future use */
+     /* This routine does *NOT* return one of the usual com_err codes.  */
+     if ((code = krb_save_credentials(v4creds.service, v4creds.instance,
+				      v4creds.realm, v4creds.session,
+				      v4creds.lifetime, v4creds.kvno,
+				      &(v4creds.ticket_st), 
+				      v4creds.issue_date))) {
+	 fprintf (stderr, "%s: %s trying to save the V4 ticket\n",
+		  prog, krb_get_err_text (code));
+	 exit(1);
+     }
+
+     exit(0);
+}
diff --git a/krb5-1-6/src/krb524/krb524.c b/krb5-1-6/src/krb524/krb524.c
new file mode 100644
index 000000000..1eff72f00
--- /dev/null
+++ b/krb5-1-6/src/krb524/krb524.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2003 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#ifdef _WIN32
+#include "krb5.h"
+
+#ifdef krb524_convert_creds_kdc
+#undef krb524_convert_creds_kdc
+#endif
+#ifdef krb524_init_ets
+#undef krb524_init_ets
+#endif
+
+int KRB5_CALLCONV_WRONG
+krb524_convert_creds_kdc(krb5_context context, krb5_creds *v5creds, struct credentials *v4creds)
+{
+	return(krb5_524_convert_creds(context,v5creds,v4creds));
+}
+
+void KRB5_CALLCONV_WRONG
+krb524_init_ets(krb5_context context)
+{
+	/* no-op */
+}
+#endif /* _WIN32 */
diff --git a/krb5-1-6/src/krb524/krb524.def b/krb5-1-6/src/krb524/krb524.def
new file mode 100644
index 000000000..67d205045
--- /dev/null
+++ b/krb5-1-6/src/krb524/krb524.def
@@ -0,0 +1,13 @@
+;----------------------------------------------------
+;   KRB524.DEF - KRB524.DLL module definition file
+;----------------------------------------------------
+
+; ****************************************************************************
+; Do not add any function to this file until you make sure the calling
+; convention for the exported function is KRB5_CALLCONV
+; ****************************************************************************
+
+
+EXPORTS
+    krb524_convert_creds_kdc	@1
+    krb524_init_ets		@2
diff --git a/krb5-1-6/src/krb524/krb524_prot b/krb5-1-6/src/krb524/krb524_prot
new file mode 100644
index 000000000..f83854d77
--- /dev/null
+++ b/krb5-1-6/src/krb524/krb524_prot
@@ -0,0 +1,11 @@
+Protocol:
+
+	-> ASN.1 encoded V5 ticket
+	<- int status_code, [int kvno, encode_v4tkt encoded KTEXT_ST]
+
+kvno and V4 ticket are only included if status_code is zero.
+
+The kvno for the converted ticket is sent explicitly because the field
+is ASN.1 encoded in the krb5_creds structure; the client would have to
+decode (but not decrypt) the entire krb5_ticket structure to get it,
+which would be inefficient.
diff --git a/krb5-1-6/src/krb524/krb524d.M b/krb5-1-6/src/krb524/krb524d.M
new file mode 100644
index 000000000..dee00cf81
--- /dev/null
+++ b/krb5-1-6/src/krb524/krb524d.M
@@ -0,0 +1,74 @@
+.\" krb524/krb524d.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\"
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" "
+.TH KRB524D 8
+.SH NAME
+krb524d \- Version 5 to Version 4 Credentials Conversion Daemon
+.SH SYNOPSIS
+.B krb524d
+[
+.B \-m[aster]
+|
+.B \-k[eytab]
+] [
+.B \-r
+.I realm
+] [
+.B \-nofork
+] [
+.B \-p
+.I portnum
+]
+.br
+.SH DESCRIPTION
+.I krb524d
+is the Kerberos Version 5 to Version 4 Credentials Conversion daemon.  
+It works in conjuction with a krb5kdc to allow clients to acquire Kerberos 
+version 4 tickets from Kerberos version 5 tickets without specifying a password.
+.SH OPTIONS
+.TP
+\fB\-m[aster]\fP
+Use the KDC database to convert credentials.  This option cannot be combined with
+\fB\-k[eytab]\fP.
+.TP
+\fB\-k[eytab]\fP
+Use the default keytab to convert credentials. This option cannot be combined with
+\fB\-m[aster]\fP.  
+.TP
+\fB\-r\fP \fIrealm\fP
+Convert credentials for \fIrealm\fP; by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+\fB\-nofork\fP
+specifies that krb524d not fork on launch.  Useful for debugging purposes.
+.TP
+\fB\-p\fP \fIportnum\fP 
+specifies the default UDP port number which krb524d should listen on for
+Kerberos 524 requests.  This value is used when no port is specified in
+the KDC profile and when no port is specified in the Kerberos configuration
+file.
+If no value is available, then the value in /etc/services for service
+"krb524" is used.
+.SH SEE ALSO
+kerberos(1), krb5kdc(8), kdb5_util(8), kdc.conf(5)
diff --git a/krb5-1-6/src/krb524/krb524d.c b/krb5-1-6/src/krb524/krb524d.c
new file mode 100644
index 000000000..497e81301
--- /dev/null
+++ b/krb5-1-6/src/krb524/krb524d.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#include <com_err.h>
+#include <stdarg.h>
+
+#include <assert.h>
+#include <stdio.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+
+#include <krb.h>
+#include "krb524d.h"
+
+#if defined(NEED_DAEMON_PROTO)
+extern int daemon(int, int);
+#endif
+
+#define TIMEOUT 60
+#define TKT_BUFSIZ 2048
+#define MSGSIZE 8192
+
+char *whoami;
+int signalled = 0;
+static int debug = 0;
+void *handle = NULL;
+
+int use_keytab, use_master;
+int allow_v4_crossrealm = 0;
+char *keytab = NULL;
+krb5_keytab kt;
+
+void init_keytab(krb5_context),
+    init_master(krb5_context, kadm5_config_params *),
+    cleanup_and_exit(int, krb5_context);
+krb5_error_code do_connection(int, krb5_context);
+krb5_error_code lookup_service_key(krb5_context, krb5_principal,
+				   krb5_enctype, krb5_kvno,
+				   krb5_keyblock *, krb5_kvno *);
+krb5_error_code  kdc_get_server_key(krb5_context, krb5_principal,
+				    krb5_keyblock *, krb5_kvno *,
+				    krb5_enctype, krb5_kvno);
+
+static krb5_error_code
+handle_classic_v4 (krb5_context context, krb5_ticket *v5tkt,
+		   struct sockaddr_in *saddr,
+		   krb5_data *tktdata, krb5_kvno *v4kvno);
+static krb5_error_code
+afs_return_v4(krb5_context, const krb5_principal , int *use_v5);
+
+static void usage(context)
+    krb5_context context;
+{
+    fprintf(stderr, "Usage: %s [-k[eytab]] [-m[aster] [-r realm]] [-nofork] [-p portnum]\n", whoami);
+    cleanup_and_exit(1, context);
+}
+
+static RETSIGTYPE request_exit(signo)
+    int signo;
+{
+    signalled = 1;
+}
+
+int (*encode_v4tkt)(KTEXT, char *, unsigned int *) = 0;
+
+int main(argc, argv)
+    int argc;
+    char **argv;
+{
+    struct servent *serv;
+    struct sockaddr_in saddr;
+    struct timeval timeout;
+    int ret, s, nofork;
+    fd_set rfds;
+    krb5_context context;
+    krb5_error_code retval;
+    kadm5_config_params config_params;
+    unsigned long port = 0;
+
+    whoami = ((whoami = strrchr(argv[0], '/')) ? whoami + 1 : argv[0]);
+
+    retval = krb5int_init_context_kdc(&context);
+    if (retval) {
+	com_err(whoami, retval, "while initializing krb5");
+	exit(1);
+    }
+
+    {
+	krb5int_access k5int;
+	retval = krb5int_accessor(&k5int, KRB5INT_ACCESS_VERSION);
+	if (retval != 0) {
+	    com_err(whoami, retval,
+		    "while accessing krb5 library internal support");
+	    exit(1);
+	}
+	encode_v4tkt = k5int.krb524_encode_v4tkt;
+	if (encode_v4tkt == NULL) {
+	    com_err(whoami, 0,
+		    "krb4 support disabled in krb5 support library");
+	    exit(1);
+	}
+    }
+
+    argv++; argc--;
+    use_master = use_keytab = nofork = 0;
+    config_params.mask = 0;
+
+    while (argc) {
+	if (strncmp(*argv, "-X", 2) == 0) {
+	    allow_v4_crossrealm = 1;
+	}
+	else if (strncmp(*argv, "-k", 2) == 0)
+	    use_keytab = 1;
+	else if (strncmp(*argv, "-m", 2) == 0)
+	    use_master = 1;
+	else if (strcmp(*argv, "-nofork") == 0)
+	    nofork = 1;
+	else if (strcmp(*argv, "-r") == 0) {
+	    argv++; argc--;
+	    if (argc == 0 || !use_master)
+		usage(context);
+	    config_params.mask |= KADM5_CONFIG_REALM;
+	    config_params.realm = *argv;
+	}
+	else if (strcmp(*argv, "-p") == 0) {
+	    char *endptr = 0;
+	    argv++; argc--;
+	    if (argc == 0)
+		usage (context);
+	    if (port != 0) {
+		com_err (whoami, 0,
+			 "port number may only be specified once");
+		exit (1);
+	    }
+	    port = strtoul (*argv, &endptr, 0);
+	    if (*endptr != '\0' || port > 65535 || port == 0) {
+		com_err (whoami, 0,
+			 "invalid port number %s, must be 1..65535\n",
+			 *argv);
+		exit (1);
+	    }
+	}
+	else
+	    break;
+	argv++; argc--;
+    }
+    if (argc || use_keytab + use_master > 1 ||
+	use_keytab + use_master == 0) {
+	use_keytab = use_master = 0;
+	usage(context);
+    }
+
+    signal(SIGINT, request_exit);
+    signal(SIGHUP, SIG_IGN);
+    signal(SIGTERM, request_exit);
+
+    krb5_klog_init(context, "krb524d", whoami, !nofork);
+
+    if (use_keytab)
+	init_keytab(context);
+    if (use_master)
+	init_master(context, &config_params);
+
+    memset((char *) &saddr, 0, sizeof(struct sockaddr_in));
+    saddr.sin_family = AF_INET;
+    saddr.sin_addr.s_addr = INADDR_ANY;
+    if (port == 0) {
+	serv = getservbyname(KRB524_SERVICE, "udp");
+	if (serv == NULL) {
+	    com_err(whoami, 0, "service entry `%s' not found, using %d",
+		    KRB524_SERVICE, KRB524_PORT);
+	    saddr.sin_port = htons(KRB524_PORT);
+	} else
+	    saddr.sin_port = serv->s_port;
+    } else
+	saddr.sin_port = htons(port);
+
+    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	com_err(whoami, errno, "creating main socket");
+	cleanup_and_exit(1, context);
+    }
+    if ((ret = bind(s, (struct sockaddr *) &saddr,
+		    sizeof(struct sockaddr_in))) < 0) {
+	com_err(whoami, errno, "binding main socket");
+	cleanup_and_exit(1, context);
+    }
+    if (!nofork && daemon(0, 0)) {
+	com_err(whoami, errno, "while detaching from tty");
+	cleanup_and_exit(1, context);
+    }
+
+    while (1) {
+	FD_ZERO(&rfds);
+	FD_SET(s, &rfds);
+	timeout.tv_sec = TIMEOUT;
+	timeout.tv_usec = 0;
+
+	ret = select(s+1, &rfds, NULL, NULL, &timeout);
+	if (signalled)
+	    cleanup_and_exit(0, context);
+	else if (ret == 0) {
+	    if (use_master) {
+		ret = kadm5_flush(handle);
+		if (ret && ret != KRB5_KDB_DBNOTINITED) {
+		    com_err(whoami, ret, "closing kerberos database");
+		    cleanup_and_exit(1, context);
+		}
+	    }
+	} else if (ret < 0 && errno != EINTR) {
+	    com_err(whoami, errno, "in select");
+	    cleanup_and_exit(1, context);
+	} else if (FD_ISSET(s, &rfds)) {
+	    if (debug)
+		printf("received packet\n");
+	    if ((ret = do_connection(s, context))) {
+		com_err(whoami, ret, "handling packet");
+	    }
+	} else
+	    com_err(whoami, 0, "impossible situation occurred!");
+    }
+
+    cleanup_and_exit(0, context);
+}
+
+void cleanup_and_exit(ret, context)
+    int ret;
+    krb5_context context;
+{
+    if (use_master && handle) {
+	(void) kadm5_destroy(handle);
+    }
+    if (use_keytab && kt) krb5_kt_close(context, kt);
+    krb5_klog_close(context);
+    krb5_free_context(context);
+    exit(ret);
+}
+
+void init_keytab(context)
+    krb5_context context;
+{
+    int ret;
+    use_keytab = 0;
+    if (keytab == NULL) {
+	if ((ret = krb5_kt_default(context, &kt))) {
+	    com_err(whoami, ret, "while opening default keytab");
+	    cleanup_and_exit(1, context);
+	}
+    } else {
+	if ((ret = krb5_kt_resolve(context, keytab, &kt))) {
+	    com_err(whoami, ret, "while resolving keytab %s",
+		    keytab);
+	    cleanup_and_exit(1, context);
+	}
+    }
+    use_keytab = 1;		/* now safe to close keytab */
+}
+
+void init_master(context, params)
+    krb5_context context;
+    kadm5_config_params *params;
+{
+    int ret;
+
+    use_master = 0;
+    if ((ret = kadm5_init(whoami, NULL, KADM5_ADMIN_SERVICE, params,
+			  KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+			  &handle))) {
+	com_err(whoami, ret, "initializing kadm5 library");
+	cleanup_and_exit(1, context);
+    }
+    use_master = 1;		/* now safe to close kadm5 */
+}
+
+krb5_error_code do_connection(s, context)
+    int s;
+    krb5_context context;
+{
+    struct sockaddr saddr;
+    krb5_ticket *v5tkt = 0;
+    krb5_data msgdata, tktdata;
+    char msgbuf[MSGSIZE], tktbuf[TKT_BUFSIZ], *p;
+    int ret;
+    socklen_t saddrlen;
+    krb5_int32 n; /* Must be 4 bytes */
+    krb5_kvno v4kvno;
+
+    msgdata.data = msgbuf;
+    msgdata.length = MSGSIZE;
+    tktdata.data = tktbuf;
+    tktdata.length = TKT_BUFSIZ;
+    saddrlen = sizeof(struct sockaddr);
+    ret = recvfrom(s, msgdata.data, (int) msgdata.length, 0, &saddr, &saddrlen);
+    if (ret < 0) {
+	/* if recvfrom fails, we probably don't have a valid saddr to
+	   use for the reply, so don't even try to respond. */
+	return errno;
+    }
+    if (debug)
+	printf("message received\n");
+
+    if ((ret = decode_krb5_ticket(&msgdata, &v5tkt))) {
+	switch (ret) {
+	case KRB5KDC_ERR_BAD_PVNO:
+	case ASN1_MISPLACED_FIELD:
+	case ASN1_MISSING_FIELD:
+	case ASN1_BAD_ID:
+	case KRB5_BADMSGTYPE:
+	    /* don't even answer parse errors */
+	    return ret;
+	    break;
+	default:
+	    /* try and recognize our own error packet */
+	    if (msgdata.length == sizeof(krb5_int32))
+		return KRB5_BADMSGTYPE;
+	    else
+		goto error;
+	}
+    }
+    if (debug)
+	printf("V5 ticket decoded\n");
+
+    if (krb5_princ_size(context, v5tkt->server) >= 1
+	&& krb5_princ_component(context, v5tkt->server, 0)->length == 3
+	&& strncmp(krb5_princ_component(context, v5tkt->server, 0)->data,
+		   "afs", 3) == 0) {
+	krb5_data *enc_part;
+	int use_v5;
+	if ((ret = afs_return_v4(context, v5tkt->server,
+				 &use_v5)) != 0)
+	    goto error;
+	if ((ret = encode_krb5_enc_data(&v5tkt->enc_part, &enc_part)) != 0)
+	    goto error;
+	if (!(use_v5)|| enc_part->length >= 344) {
+	    krb5_free_data(context, enc_part);
+	    if ((ret = handle_classic_v4(context, v5tkt,
+					 (struct sockaddr_in *) &saddr, &tktdata,
+					 &v4kvno)) != 0)
+		goto error;
+	} else {
+	    KTEXT_ST fake_v4tkt;
+	    memset(&fake_v4tkt, 0x11, sizeof(fake_v4tkt));
+	    fake_v4tkt.mbz = 0;
+	    fake_v4tkt.length = enc_part->length;
+	    memcpy(fake_v4tkt.dat, enc_part->data, enc_part->length);
+	    v4kvno = (0x100-0x2b); /*protocol constant indicating  v5
+				    * enc part only*/
+	    krb5_free_data(context, enc_part);
+	    ret = encode_v4tkt(&fake_v4tkt, tktdata.data, &tktdata.length);
+	}
+    } else {
+	if ((ret = handle_classic_v4(context, v5tkt,
+				     (struct sockaddr_in *) &saddr, &tktdata,
+				     &v4kvno)) != 0)
+	    goto error;
+    }
+
+error:
+    /* create the reply */
+    p = msgdata.data;
+    msgdata.length = 0;
+
+    n = htonl(ret);
+    memcpy(p, (char *) &n, sizeof(krb5_int32));
+    p += sizeof(krb5_int32);
+    msgdata.length += sizeof(krb5_int32);
+
+    if (ret)
+	goto write_msg;
+
+    n = htonl(v4kvno);
+    memcpy(p, (char *) &n, sizeof(krb5_int32));
+    p += sizeof(krb5_int32);
+    msgdata.length += sizeof(krb5_int32);
+
+    memcpy(p, tktdata.data, tktdata.length);
+    p += tktdata.length;
+    msgdata.length += tktdata.length;
+
+write_msg:
+    if (ret)
+	(void) sendto(s, msgdata.data, (int) msgdata.length, 0, &saddr, saddrlen);
+    else
+	if (sendto(s, msgdata.data, msgdata.length, 0, &saddr, saddrlen)<0)
+	    ret = errno;
+    if (debug)
+	printf("reply written\n");
+    if (v5tkt)
+	krb5_free_ticket(context, v5tkt);
+
+
+    return ret;
+}
+
+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, kvno, ktype, &entry)))
+	    return ret;
+	*key = entry.key;
+	key->contents = malloc(key->length);
+	if (key->contents)
+	    memcpy(key->contents, entry.key.contents, key->length);
+	else if (key->length) {
+	    /* out of memory? */
+	    ret = errno;
+	    memset (key, 0, sizeof (*key));
+	    return ret;
+	}
+
+	krb5_kt_free_entry(context, &entry);
+	return 0;
+    } else if (use_master) {
+	return kdc_get_server_key(context, p, key, kvnop, ktype, kvno);
+    }
+    return 0;
+}
+
+krb5_error_code kdc_get_server_key(context, service, key, kvnop, ktype, kvno)
+    krb5_context context;
+    krb5_principal service;
+    krb5_keyblock *key;
+    krb5_kvno *kvnop;
+    krb5_enctype ktype;
+    krb5_kvno kvno;
+{
+    krb5_error_code ret;
+    kadm5_principal_ent_rec server;
+
+    if ((ret = kadm5_get_principal(handle, service, &server,
+				   KADM5_KEY_DATA|KADM5_ATTRIBUTES)))
+	return ret;
+
+    if (server.attributes & KRB5_KDB_DISALLOW_ALL_TIX
+	|| server.attributes & KRB5_KDB_DISALLOW_SVR) {
+	kadm5_free_principal_ent(handle, &server);
+	return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+    }
+
+    /*
+     * We try kadm5_decrypt_key twice because in the case of a
+     * ENCTYPE_DES_CBC_CRC key, we prefer to find a krb4 salt type
+     * over a normal key.  Note this may create a problem if the
+     * server key is passworded and has both a normal and v4 salt.
+     * There is no good solution to this.
+     */
+    if ((ret = kadm5_decrypt_key(handle,
+				 &server,
+				 ktype,
+				 (ktype == ENCTYPE_DES_CBC_CRC) ?
+				 KRB5_KDB_SALTTYPE_V4 : -1,
+				 kvno,
+				 key, NULL, kvnop)) &&
+	(ret = kadm5_decrypt_key(handle,
+				 &server,
+				 ktype,
+				 -1,
+				 kvno,
+				 key, NULL, kvnop))) {
+	kadm5_free_principal_ent(handle, &server);
+	return (KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
+    }
+
+    kadm5_free_principal_ent(handle, &server);
+    return ret;
+}
+
+/*
+ * We support two  kinds of v4 credentials.  There are real v4
+ *   credentials, and  a Kerberos v5 enc part masquerading as a krb4
+ *  credential to be used by modern AFS implementations; this function
+ *  handles the classic v4 case.
+ */
+
+static krb5_error_code
+handle_classic_v4 (krb5_context context, krb5_ticket *v5tkt,
+		   struct sockaddr_in *saddr,
+		   krb5_data *tktdata, krb5_kvno *v4kvno)
+{
+    krb5_error_code ret;
+    krb5_keyblock v5_service_key, v4_service_key;
+    KTEXT_ST v4tkt;
+
+    v5_service_key.contents = NULL;
+    v4_service_key.contents = NULL;
+
+    if ((ret = lookup_service_key(context, v5tkt->server,
+				  v5tkt->enc_part.enctype,
+				  v5tkt->enc_part.kvno,
+				  &v5_service_key, NULL)))
+	goto error;
+
+    if ((ret = lookup_service_key(context, v5tkt->server,
+				  ENCTYPE_DES_CBC_CRC,
+				  0,
+				  &v4_service_key, v4kvno)))
+	goto error;
+
+    if (debug)
+	printf("service key retrieved\n");
+    if ((ret = krb5_decrypt_tkt_part(context, &v5_service_key, v5tkt))) {
+	goto error;
+    }
+
+    if (!(allow_v4_crossrealm || krb5_realm_compare(context, v5tkt->server,
+						    v5tkt->enc_part2->client))) {
+	ret = KRB5KDC_ERR_POLICY;
+	goto error;
+    }
+    krb5_free_enc_tkt_part(context, v5tkt->enc_part2);
+    v5tkt->enc_part2= NULL;
+
+    memset(&v4tkt, 0x33, sizeof(v4tkt));
+    ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &v5_service_key,
+				  &v4_service_key,
+				  (struct sockaddr_in *)saddr);
+    if (ret)
+	goto error;
+
+    if (debug)
+	printf("credentials converted\n");
+
+    ret = encode_v4tkt(&v4tkt, tktdata->data, &tktdata->length);
+    if (ret)
+	goto error;
+    if (debug)
+	printf("v4 credentials encoded\n");
+
+error:
+    if (v5tkt->enc_part2) {
+	krb5_free_enc_tkt_part(context, v5tkt->enc_part2);
+	v5tkt->enc_part2 = NULL;
+    }
+
+    if (v5_service_key.contents)
+	krb5_free_keyblock_contents(context, &v5_service_key);
+    if (v4_service_key.contents)
+	krb5_free_keyblock_contents(context, &v4_service_key);
+    return ret;
+}
+
+/*
+ * afs_return_v4: a predicate to determine whether we want to try
+ * using the afs krb5 encrypted part encoding or whether we  just
+ * return krb4.  Takes a principal, and checks the configuration file.
+ */
+static krb5_error_code
+afs_return_v4 (krb5_context context, const krb5_principal princ,
+	       int *use_v5)
+{
+    krb5_error_code ret;
+    char *unparsed_name;
+    char *cp;
+    krb5_data realm;
+    assert(use_v5 != NULL);
+    ret = krb5_unparse_name(context, princ, &unparsed_name);
+    if (ret != 0)
+	return ret;
+/* Trim out trailing realm component into separate string.*/
+    for (cp = unparsed_name; *cp != '\0'; cp++) {
+	if (*cp == '\\') {
+	    cp++; /* We trust unparse_name not to leave a singleton
+		   * backslash*/
+	    continue;
+	}
+	if (*cp == '@') {
+	    *cp = '\0';
+	    realm.data = cp+1;
+	    realm.length = strlen((char *) realm.data);
+	    break;
+	}
+    }
+    krb5_appdefault_boolean(context, "afs_krb5",
+			    &realm, unparsed_name, 1,
+			    use_v5);
+    krb5_free_unparsed_name(context, unparsed_name);
+    return ret;
+}
diff --git a/krb5-1-6/src/krb524/krb524d.h b/krb5-1-6/src/krb524/krb524d.h
new file mode 100644
index 000000000..b40e3aec5
--- /dev/null
+++ b/krb5-1-6/src/krb524/krb524d.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef KRB524INT_H
+#define KRB524INT_H
+
+#include "port-sockets.h"
+#include "kerberosIV/krb.h"
+
+#ifndef KRB524INT_BEGIN_DECLS
+#ifdef __cplusplus
+#define KRB524INT_BEGIN_DECLS	extern "C" {
+#define KRB524INT_END_DECLS	}
+#else
+#define KRB524INT_BEGIN_DECLS
+#define KRB524INT_END_DECLS
+#endif
+#endif
+
+KRB524INT_BEGIN_DECLS
+
+int krb524_convert_tkt_skey
+	(krb5_context context, krb5_ticket *v5tkt, KTEXT_ST *v4tkt, 
+		   krb5_keyblock *v5_skey, krb5_keyblock *v4_skey,
+			struct sockaddr_in *saddr);
+
+KRB524INT_END_DECLS
+
+#endif /* KRB524INT_H */
diff --git a/krb5-1-6/src/krb524/libinit.c b/krb5-1-6/src/krb524/libinit.c
new file mode 100644
index 000000000..22aeea9f8
--- /dev/null
+++ b/krb5-1-6/src/krb524/libinit.c
@@ -0,0 +1,27 @@
+#ifdef _WIN32
+#include <windows.h>
+
+BOOL
+WINAPI
+DllMain(
+    HANDLE hModule,
+    DWORD fdwReason,
+    LPVOID lpReserved
+    )
+{
+    switch (fdwReason)
+    {
+	case DLL_PROCESS_ATTACH:
+	    break;
+	case DLL_THREAD_ATTACH:
+	    break;
+	case DLL_THREAD_DETACH:
+	    break;
+	case DLL_PROCESS_DETACH:
+	    break;
+	default:
+	    return FALSE;
+    }
+    return TRUE;
+}
+#endif
diff --git a/krb5-1-6/src/krb524/test.c b/krb5-1-6/src/krb524/test.c
new file mode 100644
index 000000000..d0cb92181
--- /dev/null
+++ b/krb5-1-6/src/krb524/test.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "k5-int.h"
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+
+#ifndef _WIN32
+#include <netinet/in.h>
+#endif
+
+#include <des.h>
+#include <krb.h>
+#include "com_err.h"
+
+#define KEYSIZE 8
+#define CRED_BUFSIZ 2048
+
+#define krb5_print_addrs
+
+void do_local (krb5_creds *, krb5_keyblock *),
+     do_remote (krb5_context, krb5_creds *, char *, krb5_keyblock *);
+
+static 
+void print_key(msg, key)
+     char *msg;
+     des_cblock *key;
+{
+     printf("%s: ", msg);
+     C_Block_print(key);
+     printf("\n");
+}
+
+static
+void print_time(msg, t)
+     char *msg;
+     int t;
+{
+     printf("%s: %d, %s", msg, t, ctime((time_t *) &t));
+}
+
+static
+void krb5_print_times(msg, t)
+     char *msg;
+     krb5_ticket_times *t;
+{
+     printf("%s: Start: %d, %s", msg, t->starttime, 
+	    ctime((time_t *) &t->starttime));
+     printf("%s: End: %d, %s", msg, t->endtime, 
+	    ctime((time_t *) &t->endtime));
+     printf("%s: Auth: %d, %s", msg, t->authtime, 
+	    ctime((time_t *) &t->authtime));
+     printf("%s: Renew: %d, %s", msg, t->renew_till, 
+	    ctime((time_t *) &t->renew_till));
+}
+
+static
+void krb5_print_keyblock(msg, key)
+     char *msg;
+     krb5_keyblock *key;
+{
+     printf("%s: Keytype: %d\n", msg, key->enctype);
+     printf("%s: Length: %d\n", msg, key->length);
+     printf("%s: Key: ", msg);
+     C_Block_print((des_cblock *) key->contents);
+     printf("\n");
+}
+
+static
+void krb5_print_ticket(context, ticket_data, key)
+     krb5_context context;
+     krb5_data *ticket_data;
+     krb5_keyblock *key;
+{
+     char *p;
+     krb5_ticket *tkt;
+     int ret;
+
+     if ((ret = decode_krb5_ticket(ticket_data, &tkt))) {
+	  com_err("test", ret, "decoding ticket");
+	  exit(1);
+     }
+     if ((ret = krb5_decrypt_tkt_part(context, key, tkt))) {
+	  com_err("test", ret, "decrypting V5 ticket for print");
+	  exit(1);
+     }
+     
+     krb5_unparse_name(context, tkt->server, &p);
+     printf("Ticket: Server: %s\n", p);
+     free(p);
+     printf("Ticket: kvno: %d\n", tkt->enc_part.kvno);
+     printf("Ticket: Flags: 0x%08x\n", tkt->enc_part2->flags);
+     krb5_print_keyblock("Ticket: Session Keyblock",
+			 tkt->enc_part2->session);
+     krb5_unparse_name(context, tkt->enc_part2->client, &p);
+     printf("Ticket: Client: %s\n", p);
+     free(p);
+     krb5_print_times("Ticket: Times", &tkt->enc_part2->times);
+     printf("Ticket: Address 0: %08lx\n",
+	    *((unsigned long *) tkt->enc_part2->caddrs[0]->contents));
+     
+     krb5_free_ticket(context, tkt);
+}
+
+static
+void krb5_print_creds(context, creds, secret_key)
+     krb5_context context;
+     krb5_creds *creds;
+     krb5_keyblock *secret_key;
+{
+     char *p;
+     
+     krb5_unparse_name(context, creds->client, &p);
+     printf("Client: %s\n", p);
+     free(p);
+     krb5_unparse_name(context, creds->server, &p);
+     printf("Server: %s\n", p);
+     free(p);
+     krb5_print_keyblock("Session key", &creds->keyblock);
+     krb5_print_times("Times", &creds->times);
+     printf("is_skey: %s\n", creds->is_skey ? "True" : "False");
+     printf("Flags: 0x%08x\n", creds->ticket_flags);
+#if 0
+     krb5_print_addrs(creds->addresses);
+#endif
+     krb5_print_ticket(context, &creds->ticket, secret_key);
+     /* krb5_print_ticket(context, &creds->second_ticket, secret_key); */
+}
+
+static
+void krb4_print_ticket(ticket, secret_key)
+     KTEXT ticket;
+     krb5_keyblock *secret_key;
+{
+     char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+     char sname[ANAME_SZ], sinst[INST_SZ];
+     unsigned char flags;
+     krb5_ui_4 addr;
+     krb5_ui_4 issue_time;
+     C_Block session_key;
+     int life;
+     Key_schedule keysched;
+     
+     int ret;
+     
+     if (des_key_sched(secret_key->contents, keysched)) {
+	  fprintf(stderr, "Bug in DES key somewhere.\n");
+	  exit(1);
+     }
+     
+     ret = decomp_ticket(ticket, &flags, pname, pinst, prealm, &addr,
+			 session_key, &life, &issue_time, sname,
+			 sinst,  secret_key->contents, keysched);
+     if (ret != KSUCCESS) {
+	  fprintf(stderr, "krb4 decomp_ticket failed\n");
+	  exit(1);
+     }
+     printf("Ticket: Client: %s.%s@%s\n", pname, pinst, prealm);
+     printf("Ticket: Service: %s.%s\n", sname, sinst);
+     printf("Ticket: Address: %08lx\n", (long) addr);
+     print_key("Ticket: Session Key", (char *) session_key);
+     printf("Ticket: Lifetime: %d\n", life);
+     printf("Ticket: Issue Date: %ld, %s", (long) issue_time, 
+	    ctime((time_t *) &issue_time));
+}
+
+static
+void krb4_print_creds(creds, secret_key)
+     CREDENTIALS *creds;
+     krb5_keyblock *secret_key;
+{
+     printf("Client: %s.%s@%s\n", creds->pname, creds->pinst,
+	    creds->realm);
+     printf("Service: %s.%s@%s\n", creds->service, creds->instance,
+	    creds->realm);
+     print_key("Session key", (char *) creds->session);
+     printf("Lifetime: %d\n", creds->lifetime);
+     printf("Key Version: %d\n", creds->kvno);
+     print_time("Issue Date", creds->issue_date);
+     krb4_print_ticket(&creds->ticket_st, secret_key);
+}
+
+static
+void usage()
+{
+     fprintf(stderr, "Usage: test [-remote server] client service\n");
+     exit(1);
+}
+
+int main(argc, argv)
+     int argc;
+     char **argv;
+{
+     krb5_principal client, server;
+     krb5_ccache cc;
+     krb5_creds increds, *v5creds;
+     krb5_keyblock key;
+     char keybuf[KEYSIZE], buf[BUFSIZ];
+     int i, ret, local;
+     char *remote;
+     krb5_context context;
+     krb5_error_code retval;
+
+#if 0
+     krb524_debug = 1;
+#endif
+
+     retval = krb5_init_context(&context);
+     if (retval) {
+	     com_err(argv[0], retval, "while initializing krb5");
+	     exit(1);
+     }
+
+     local = 0;
+     remote = NULL;
+     argc--; argv++;
+     while (argc) {
+	  if (strcmp(*argv, "-local") == 0)
+	       local++;
+#if 0
+	  else if (strcmp(*argv, "-remote") == 0) {
+	       argc--; argv++;
+	       if (!argc)
+		    usage();
+	       remote = *argv;
+	  }
+#endif
+	  else
+	       break;
+	  argc--; argv++;
+     }
+     if (argc != 2)
+	  usage();
+
+     if ((ret = krb5_parse_name(context, argv[0], &client))) {
+	  com_err("test", ret, "parsing client name");
+	  exit(1);
+     }
+     if ((ret = krb5_parse_name(context, argv[1], &server))) {
+	  com_err("test", ret, "parsing server name");
+	  exit(1);
+     }
+     if ((ret = krb5_cc_default(context, &cc))) {
+	  com_err("test", ret, "opening default credentials cache");
+	  exit(1);
+     }
+     
+     memset((char *) &increds, 0, sizeof(increds));
+     increds.client = client;
+     increds.server = server;
+     increds.times.endtime = 0;
+     increds.keyblock.enctype = ENCTYPE_DES_CBC_MD5;
+     if ((ret = krb5_get_credentials(context, 0, cc, &increds, &v5creds))) {
+	  com_err("test", ret, "getting V5 credentials");
+	  exit(1);
+     }
+
+     /* We need the service key in order to locally decrypt both */
+     /* tickets for testing */
+     printf("Service's key: ");
+     fflush(stdout);
+     fgets(buf, BUFSIZ, stdin);
+     for (i = 0; i < 8; i++) {
+	  unsigned char c;
+	  c = buf[2*i];
+	  if (c >= '0' && c <= '9')
+	       c -= '0';
+	  else if (c >= 'a' && c <= 'z')
+	       c = c - 'a' + 0xa;
+	  keybuf[i] = c << 4;
+	  c = buf[2*i+1];
+	  if (c >= '0' && c <= '9')
+	       c -= '0';
+	  else if (c >= 'a' && c <= 'z')
+	       c = c - 'a' + 0xa;
+	  keybuf[i] += c;
+     }
+     
+     key.enctype = ENCTYPE_DES_CBC_MD5;
+     key.length = KEYSIZE; /* presumably */
+     key.contents = (krb5_octet *) keybuf;
+
+     do_remote(context, v5creds, remote, &key);
+     exit(0);
+}
+
+void do_remote(context, v5creds, server, key)
+     krb5_context context;
+     krb5_creds *v5creds;
+     char *server;
+     krb5_keyblock *key;
+{
+#if 0
+     struct sockaddr_in saddr;
+     struct hostent *hp;
+#endif
+     CREDENTIALS v4creds;
+     int ret;
+
+     printf("\nV5 credentials:\n");
+     krb5_print_creds(context, v5creds, key);
+
+#if 0
+     if (strcmp(server, "kdc") != 0) {
+	  hp = gethostbyname(server);
+	  if (hp == NULL) {
+	       fprintf(stderr, "test: host %s does not exist.\n", server);
+	       exit(1);
+	  }
+	  memset((char *) &saddr, 0, sizeof(struct sockaddr_in));
+	  saddr.sin_family = AF_INET;
+	  memcpy((char *) &saddr.sin_addr.s_addr, hp->h_addr,
+		 sizeof(struct in_addr));
+	  
+	  if ((ret = krb524_convert_creds_addr(context, v5creds, &v4creds, 
+					      (struct sockaddr *) &saddr))) {
+	       com_err("test", ret, "converting credentials on %s",
+		       server);
+	       exit(1);
+	  }
+     } else
+#endif
+     {
+	  if ((ret = krb524_convert_creds_kdc(context, v5creds, &v4creds))) {
+	       com_err("test", ret, "converting credentials via kdc");
+	       exit(1);
+	  }
+     }
+     
+     printf("\nV4 credentials:\n");
+     krb4_print_creds(&v4creds, key);
+}
diff --git a/krb5-1-6/src/lib/Makefile.in b/krb5-1-6/src/lib/Makefile.in
new file mode 100644
index 000000000..b1590df71
--- /dev/null
+++ b/krb5-1-6/src/lib/Makefile.in
@@ -0,0 +1,195 @@
+thisconfigdir=./..
+myfulldir=lib
+mydir=lib
+LOCAL_SUBDIRS=crypto krb5 des425 @KRB4@ gssapi rpc kdb kadm5 apputils
+BUILDTOP=$(REL)..
+
+all-unix::
+
+CLEANLIBS = libkrb5.a libkdb5.a libcrypto.a libgssapi_krb5.a libdes425.a \
+	libkrb425.a libkadm.a libkrb4.a libcom_err.a libpty.a \
+	libss.a libgssapi.a libapputils.a \
+	libkrb5.so libcrypto.so libkrb4.so libdes425.so
+
+clean-unix::
+
+clean-windows::
+
+# Windows stuff to make krb5 and gssapi DLLs.
+
+##MIT##!if !defined(VS_INC)
+##MIT##!message Must define VS_INC to point to version server include dir!
+##MIT##!error
+##MIT##!endif
+##MIT##!if !defined(VS_LIB)
+##MIT##!message Must define VS_LIB to point to version server library!
+##MIT##!error
+##MIT##!endif
+##MIT##MITLIBS=$(VS_LIB)
+##MIT##MITFLAGS=-I$(VS_INC) /DVERSERV=1
+
+
+
+##WIN32##!if  ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+##WIN32##SLIBS = $(BUILDTOP)\util\support\$(OUTPRE)k5sprt64.lib
+##WIN32##!else
+##WIN32##SLIBS = $(BUILDTOP)\util\support\$(OUTPRE)k5sprt32.lib
+##WIN32##!endif
+##WIN32##CLIBS = $(BUILDTOP)\util\et\$(OUTPRE)comerr.lib
+##WIN32##PLIBS = $(BUILDTOP)\util\profile\$(OUTPRE)profile.lib
+##WIN32##KLIBS = krb5\$(OUTPRE)krb5.lib crypto\$(OUTPRE)crypto.lib \
+##WIN32##	$(BUILDTOP)\util\profile\$(OUTPRE)profile.lib \
+##WIN32##	des425\$(OUTPRE)des425.lib
+##WIN32##GLIBS = gssapi\$(OUTPRE)gssapi.lib
+##WIN32##K4LIBS = krb4\$(OUTPRE)krb4.lib
+
+
+##WIN32##SDEF = k5sprt32.def
+##WIN32##CDEF = comerr32.def
+##WIN32##PDEF = xpprof32.def
+##WIN32##KDEF = krb5_32.def
+##WIN32##GDEF = gssapi32.def
+##WIN32##K4DEF = krb4_32.def
+
+
+
+##WIN32##KRB5RC = krb5.rc
+##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
+
+##WIN32##WINLIBS = kernel32.lib ws2_32.lib user32.lib shell32.lib oldnames.lib \
+##WIN32##	version.lib secur32.lib advapi32.lib gdi32.lib delayimp.lib
+##WIN32##WINDLLFLAGS = $(DLL_LINKOPTS) -base:0x1c000000 /DELAYLOAD:secur32.dll \
+##WIN32##	/DELAYLOAD:advapi32.dll /DELAY:UNLOAD /DELAY:NOBIND
+
+##WIN32##S_GLUE=$(OUTPRE)support_glue.obj
+##WIN32##K5_GLUE=$(OUTPRE)k5_glue.obj
+##WIN32##K4_GLUE=$(OUTPRE)k4_glue.obj
+##WIN32##GSS_GLUE=$(OUTPRE)gss_glue.obj
+##WIN32##COMERR_GLUE=$(OUTPRE)comerr_glue.obj
+##WIN32##PROF_GLUE=$(OUTPRE)prof_glue.obj
+
+##WIN32##SGLUE=$(S_GLUE)
+##WIN32##CGLUE=$(COMERR_GLUE)
+##WIN32##PGLUE=$(PROF_GLUE)
+##WIN32##KGLUE=$(K5_GLUE)
+##WIN32##GGLUE=$(GSS_GLUE)
+##WIN32##K4GLUE=$(K4_GLUE)
+
+##WIN32##RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY
+
+##WIN32##SRES=$(SLIB:.lib=.res)
+##WIN32##CRES=$(CLIB:.lib=.res)
+##WIN32##PRES=$(PLIB:.lib=.res)
+##WIN32##KRES=$(KLIB:.lib=.res)
+##WIN32##GRES=$(GLIB:.lib=.res)
+##WIN32##K4RES=$(K4LIB:.lib=.res)
+
+##WIN32##$(SRES): $(VERSIONRC)
+##WIN32##	$(RC) $(RCFLAGS) -DSUPPORT_LIB -fo $@ -r $**
+##WIN32##$(CRES): $(VERSIONRC)
+##WIN32##	$(RC) $(RCFLAGS) -DCE_LIB -fo $@ -r $**
+##WIN32##$(PRES): $(VERSIONRC)
+##WIN32##	$(RC) $(RCFLAGS) -DPROF_LIB -fo $@ -r $**
+##WIN32##$(KRES): $(KRB5RC)
+##WIN32##	$(RC) $(RCFLAGS) -DKRB5_LIB -fo $@ -r $**
+##WIN32##$(K4RES): $(VERSIONRC)
+##WIN32##	$(RC) $(RCFLAGS) -DKRB4_LIB -fo $@ -r $**
+##WIN32##$(GRES): $(VERSIONRC)
+##WIN32##	$(RC) $(RCFLAGS) -DGSSAPI_LIB -fo $@ -r $**
+##WIN32##$(KRB5RC): $(VERSIONRC)
+
+##WIN32##$(SLIB): $(SDEF) $(SLIBS) $(SGLUE) $(SRES)
+##WIN32##	link $(WINDLLFLAGS) -def:$(SDEF) -out:$*.dll \
+##WIN32##	  $(SLIBS) $(SGLUE) $(SRES) $(WINLIBS) $(SCLIB)
+##WIN32##        $(_VC_MANIFEST_EMBED_DLL)
+##WIN32##$(SDEF): ..\util\support\libkrb5support.exports
+##WIN32##	echo EXPORTS > $(SDEF).new
+##WIN32##	type ..\util\support\libkrb5support.exports >> $(SDEF).new
+##WIN32##	-$(RM) $(SDEF)
+##WIN32##	ren $(SDEF).new $(SDEF)
+
+##WIN32##$(CLIB): $(CDEF) $(CLIBS) $(CGLUE) $(CRES) $(SLIB)
+##WIN32##	link $(WINDLLFLAGS) -def:$(CDEF) -out:$*.dll \
+##WIN32##	  $(CLIBS) $(CGLUE) $(CRES) $(SLIB) $(WINLIBS) $(SCLIB)
+##WIN32##	$(_VC_MANIFEST_EMBED_DLL)
+
+##WIN32##$(PLIB): $(PDEF) $(PLIBS) $(PGLUE) $(PRES) $(CLIB) $(SLIB)
+##WIN32##	link $(WINDLLFLAGS) -def:$(PDEF) -out:$*.dll \
+##WIN32##	  $(PLIBS) $(PGLUE) $(PRES) $(CLIB) $(SLIB) $(WINLIBS)
+##WIN32##	$(_VC_MANIFEST_EMBED_DLL)
+
+##WIN32##$(KLIB): $(KDEF) $(KLIBS) $(KGLUE) $(KRES) $(CLIB) $(SLIB) $(MITLIBS) $(DNSLIBS)
+##WIN32##	link $(WINDLLFLAGS) -def:$(KDEF) -out:$*.dll \
+##WIN32##	  $(KLIBS) $(KGLUE) $(KRES) $(CLIB) $(SLIB) $(MITLIBS) $(DNSLIBS) $(WINLIBS) $(SCLIB)
+##WIN32##	$(_VC_MANIFEST_EMBED_DLL)
+
+##WIN32##$(GLIB): $(GDEF) $(GLIBS) $(GGLUE) $(GRES) $(KLIB) $(CLIB) $(SLIB)
+##WIN32##	link $(WINDLLFLAGS) -def:$(GDEF) -out:$*.dll \
+##WIN32##	  $(GLIBS) $(GGLUE) $(GRES) $(KLIB) $(CLIB) $(SLIB) $(WINLIBS) $(SCLIB)
+##WIN32##		$(_VC_MANIFEST_EMBED_DLL)
+
+##WIN32##$(K4LIB): $(K4DEF) $(K4LIBS) $(K4GLUE) $(K4RES) $(KLIB) $(CLIB) $(PLIB)
+##WIN32##	link $(WINDLLFLAGS) -def:$(K4DEF) -out:$*.dll \
+##WIN32##	  $(K4LIBS) $(K4GLUE) $(K4RES) $(KLIB) $(CLIB) $(PLIB) $(WINLIBS) $(SCLIB)
+##WIN32##  	$(_VC_MANIFEST_EMBED_DLL)
+
+##WIN32##$(K5_GLUE): win_glue.c
+##WIN32##	$(CC) $(ALL_CFLAGS) $(MITFLAGS) /c /DKRB5=1 /Fo$@ $**
+##WIN32##$(K4_GLUE): win_glue.c
+##WIN32##	$(CC) $(ALL_CFLAGS) /c /DKRB4=1 /Fo$@ $**
+##WIN32##$(GSS_GLUE): win_glue.c
+##WIN32##	$(CC) $(ALL_CFLAGS) /c /DGSSAPI=1 /Fo$@ $**
+##WIN32##$(COMERR_GLUE): win_glue.c
+##WIN32##	$(CC) $(ALL_CFLAGS) /c /DCOMERR=1 /Fo$@ $**
+##WIN32##$(PROF_GLUE): win_glue.c
+##WIN32##	$(CC) $(ALL_CFLAGS) /c /DPROFILELIB=1 /Fo$@ $**
+##WIN32##$(S_GLUE): win_glue.c
+##WIN32##	$(CC) $(ALL_CFLAGS) /c /DSUPPORTLIB=1 /Fo$@ $**
+
+##WIN32### Build Convenience
+##WIN32##comerr.lib: $(CLIB)
+##WIN32##krb4.lib:   $(K4LIB)
+##WIN32##krb5.lib:   $(KLIB)
+##WIN32##gssapi.lib: $(GLIB)
+##WIN32##profile.lib: $(PLIB)
+
+##WIN32##all-windows:: 
+##WIN32##	@echo Making in lib\crypto
+##WIN32##	cd crypto
+##WIN32##	$(MAKE) -$(MFLAGS)
+##WIN32##	@echo Making in lib\krb5
+##WIN32##	cd ..\krb5
+##WIN32##	$(MAKE) -$(MFLAGS)
+##WIN32##	@echo Making in lib\des425
+##WIN32##	cd ..\des425
+##WIN32##	$(MAKE) -$(MFLAGS) 
+##WIN32##	@echo Making in lib\krb4
+##WIN32##	cd ..\krb4
+##WIN32##	$(MAKE) -$(MFLAGS) 
+##WIN32##	@echo Making in lib\gssapi
+##WIN32##	cd ..\gssapi
+##WIN32##	$(MAKE) -$(MFLAGS) 
+##WIN32##	@echo Making in lib
+##WIN32##	cd ..
+
+##WIN32##all-windows:: lib-windows
+##WIN32##lib-windows:: krb5.lib gssapi.lib krb4.lib 
+
+##WIN32##clean-windows::
+##WIN32##	@echo Making clean in lib\crypto
+##WIN32##	cd crypto
+##WIN32##	$(MAKE) -$(MFLAGS) clean
+##WIN32##	@echo Making clean in lib\krb5
+##WIN32##	cd ..\krb5
+##WIN32##	$(MAKE) -$(MFLAGS) clean
+##WIN32##	@echo Making clean in lib\des425
+##WIN32##	cd ..\des425
+##WIN32##	$(MAKE) -$(MFLAGS) clean
+##WIN32##	@echo Making clean in lib\krb4
+##WIN32##	cd ..\krb4
+##WIN32##	$(MAKE) -$(MFLAGS) clean
+##WIN32##	@echo Making clean in lib\gssapi
+##WIN32##	cd ..\gssapi
+##WIN32##	$(MAKE) -$(MFLAGS) clean
+##WIN32##	@echo Making clean in lib
+##WIN32##	cd ..
diff --git a/krb5-1-6/src/lib/apputils/Makefile.in b/krb5-1-6/src/lib/apputils/Makefile.in
new file mode 100644
index 000000000..a087728af
--- /dev/null
+++ b/krb5-1-6/src/lib/apputils/Makefile.in
@@ -0,0 +1,52 @@
+prefix=@prefix@
+bindir=@bindir@
+datadir=@datadir@
+mydatadir=$(datadir)/apputils
+thisconfigdir=.
+myfulldir=lib/apputils
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+RELDIR=../lib/apputils
+SED = sed
+DEFS=
+
+##DOS##BUILDTOP = ..\..
+##DOS##LIBNAME=$(OUTPRE)apputils.lib
+##DOS##XTRA=
+##DOS##OBJFILE=$(OUTPRE)apputils.lst
+
+# LIBOBJS may or may not contain daemon.o; dummy.o is just here to
+# avoid having an empty library.
+STLIBOBJS=dummy.o @LIBOBJS@
+STOBJLISTS=OBJS.ST
+LIBBASE=apputils
+
+all-unix:: all-liblinks
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+install-unix:: install-libs
+
+LINTFLAGS=-uhvb 
+LINTFILES= daemon.c
+LIBOBJS=$(OUTPRE)daemon.$(OBJEXT)
+
+SRCS=	$(srcdir)/daemon.c \
+	$(srcdir)/dummy.c
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+daemon.so daemon.po $(OUTPRE)daemon.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  daemon.c
+dummy.so dummy.po $(OUTPRE)dummy.$(OBJEXT): dummy.c
diff --git a/krb5-1-6/src/lib/apputils/configure.in b/krb5-1-6/src/lib/apputils/configure.in
new file mode 100644
index 000000000..73e9a87aa
--- /dev/null
+++ b/krb5-1-6/src/lib/apputils/configure.in
@@ -0,0 +1,6 @@
+K5_AC_INIT(daemon.c)
+CONFIG_RULES
+AC_REPLACE_FUNCS(daemon)
+KRB5_BUILD_LIBRARY_STATIC
+KRB5_BUILD_LIBOBJS
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/lib/apputils/daemon.c b/krb5-1-6/src/lib/apputils/daemon.c
new file mode 100644
index 000000000..00dde4882
--- /dev/null
+++ b/krb5-1-6/src/lib/apputils/daemon.c
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <unistd.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+int
+daemon(nochdir, noclose)
+	int nochdir, noclose;
+{
+	int cpid;
+
+	if ((cpid = fork()) == -1)
+		return (-1);
+	if (cpid)
+		exit(0);
+#ifdef HAVE_SETSID
+	(void) setsid();
+#else
+#ifndef TIOCNOTTY
+	setpgrp();
+#else
+	{
+		int n;
+	    
+		/*
+		 * The open below may hang on pseudo ttys if the person
+		 * who starts named logs out before this point.  Thus,
+		 * the need for the timer.
+		 */
+		alarm(120);
+		n = open("/dev/tty", O_RDWR);
+		alarm(0);
+		if (n > 0) {
+			(void) ioctl(n, TIOCNOTTY, (char *)NULL);
+			(void) close(n);
+		}
+	}
+#endif
+#endif
+	if (!nochdir)
+		(void) chdir("/");
+	if (!noclose) {
+		int devnull = open(_PATH_DEVNULL, O_RDWR, 0);
+
+		if (devnull != -1) {
+			(void) dup2(devnull, 0);
+			(void) dup2(devnull, 1);
+			(void) dup2(devnull, 2);
+			if (devnull > 2)
+				(void) close(devnull);
+		}
+	}
+	return (0);
+}
diff --git a/krb5-1-6/src/lib/apputils/dummy.c b/krb5-1-6/src/lib/apputils/dummy.c
new file mode 100644
index 000000000..d5b6cc08d
--- /dev/null
+++ b/krb5-1-6/src/lib/apputils/dummy.c
@@ -0,0 +1 @@
+int lib_server_dummy = 0;
diff --git a/krb5-1-6/src/lib/comerr32.def b/krb5-1-6/src/lib/comerr32.def
new file mode 100644
index 000000000..05e4f5d1f
--- /dev/null
+++ b/krb5-1-6/src/lib/comerr32.def
@@ -0,0 +1,12 @@
+;LIBRARY		COMERR32
+DESCRIPTION	'DLL for ComErr'
+HEAPSIZE	8192
+
+EXPORTS
+	com_err
+	com_err_va
+	error_message
+	add_error_table
+	remove_error_table
+	set_com_err_hook
+	reset_com_err_hook
diff --git a/krb5-1-6/src/lib/crypto/ISSUES b/krb5-1-6/src/lib/crypto/ISSUES
new file mode 100644
index 000000000..c2122805d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/ISSUES
@@ -0,0 +1,16 @@
+Issues to be addressed for src/lib/crypto: -*- text -*-
+
+Many files here and in subdirectories pollute the namespace.
+However, some applications wanting to directly use some of those
+routines will expect those names to be available.
+
+Workaround: Shared library export lists?  Define and export internal
+names, and provide wrapper library code or weak functions under the
+polluting names?
+
+Some routines assume "int" is big enough to describe all buffers that
+may be supplied.
+
+The prng here is poor.  It should not use n-fold as a mixing function,
+because it's possible that the input will be structured in some way
+that may interact poorly with the n-fold algorithm.
diff --git a/krb5-1-6/src/lib/crypto/Makefile.in b/krb5-1-6/src/lib/crypto/Makefile.in
new file mode 100644
index 000000000..12172f98a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/Makefile.in
@@ -0,0 +1,772 @@
+thisconfigdir=../..
+myfulldir=lib/crypto
+mydir=lib/crypto
+BUILDTOP=$(REL)..$(S)..
+LOCAL_SUBDIRS=crc32 des dk enc_provider hash_provider keyhash_provider \
+	md4 md5 old raw sha1 arcfour yarrow aes
+LOCALINCLUDES = -I$(srcdir)/enc_provider \
+	-I$(srcdir)/hash_provider -I$(srcdir)/keyhash_provider \
+	-I$(srcdir)/aes \
+	-I$(srcdir)/old -I$(srcdir)/raw -I$(srcdir)/dk -I$(srcdir)/arcfour \
+	-I$(srcdir)/yarrow -I$(srcdir)/sha1
+RUN_SETUP = @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS=
+
+EXTRADEPSRCS=\
+	$(srcdir)/t_nfold.c	\
+	$(srcdir)/t_encrypt.c	\
+	$(srcdir)/t_prf.c \
+	$(srcdir)/t_prng.c	\
+	$(srcdir)/t_hmac.c	\
+	$(srcdir)/t_pkcs5.c	\
+	$(srcdir)/t_cts.c	\
+	$(srcdir)/vectors.c
+
+##DOSBUILDTOP = ..\..
+##DOSLIBNAME=$(OUTPRE)crypto.lib
+##DOSOBJFILE=$(OUTPRE)crypto.lst
+##DOSOBJFILELIST=@$(OUTPRE)crypto.lst @$(OUTPRE)des.lst @$(OUTPRE)md4.lst @$(OUTPRE)md5.lst @$(OUTPRE)sha1.lst @$(OUTPRE)arcfour.lst @$(OUTPRE)crc32.lst @$(OUTPRE)dk.lst @$(OUTPRE)old.lst @$(OUTPRE)raw.lst @$(OUTPRE)enc_prov.lst @$(OUTPRE)hash_pro.lst @$(OUTPRE)kh_pro.lst @$(OUTPRE)yarrow.lst @$(OUTPRE)aes.lst
+##DOSOBJFILEDEP =$(OUTPRE)crypto.lst $(OUTPRE)des.lst $(OUTPRE)md4.lst $(OUTPRE)md5.lst $(OUTPRE)sha1.lst $(OUTPRE)arcfour.lst $(OUTPRE)crc32.lst $(OUTPRE)dk.lst $(OUTPRE)old.lst $(OUTPRE)raw.lst $(OUTPRE)enc_prov.lst $(OUTPRE)hash_pro.lst $(OUTPRE)kh_pro.lst $(OUTPRE)aes.lst
+
+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	\
+	combine_keys.o	\
+	crypto_libinit.o	\
+	default_state.o \
+	decrypt.o		\
+	encrypt.o		\
+	encrypt_length.o	\
+	enctype_compare.o	\
+	enctype_to_string.o	\
+	etypes.o		\
+	hmac.o			\
+	keyblocks.o \
+	keyed_cksum.o		\
+	keyed_checksum_types.o	\
+	keylengths.o		\
+	make_checksum.o		\
+	make_random_key.o	\
+	mandatory_sumtype.o	\
+	nfold.o			\
+	old_api_glue.o		\
+	pbkdf2.o		\
+	prf.o \
+	prng.o			\
+	random_to_key.o		\
+	state.o \
+	string_to_cksumtype.o	\
+	string_to_enctype.o	\
+	string_to_key.o		\
+	valid_cksumtype.o	\
+	valid_enctype.o		\
+	verify_checksum.o
+
+OBJS=\
+	$(OUTPRE)block_size.$(OBJEXT)		\
+	$(OUTPRE)checksum_length.$(OBJEXT)	\
+	$(OUTPRE)cksumtype_to_string.$(OBJEXT)	\
+	$(OUTPRE)cksumtypes.$(OBJEXT)		\
+	$(OUTPRE)coll_proof_cksum.$(OBJEXT)	\
+	$(OUTPRE)combine_keys.$(OBJEXT)	\
+	$(OUTPRE)crypto_libinit.$(OBJEXT)	\
+	$(OUTPRE)default_state.$(OBJEXT) \
+	$(OUTPRE)decrypt.$(OBJEXT)		\
+	$(OUTPRE)encrypt.$(OBJEXT)		\
+	$(OUTPRE)encrypt_length.$(OBJEXT)	\
+	$(OUTPRE)enctype_compare.$(OBJEXT)	\
+	$(OUTPRE)enctype_to_string.$(OBJEXT)	\
+	$(OUTPRE)etypes.$(OBJEXT)		\
+	$(OUTPRE)hmac.$(OBJEXT)			\
+	$(OUTPRE)keyblocks.$(OBJEXT) \
+	$(OUTPRE)keyed_cksum.$(OBJEXT)		\
+	$(OUTPRE)keyed_checksum_types.$(OBJEXT)	\
+	$(OUTPRE)keylengths.$(OBJEXT)	\
+	$(OUTPRE)make_checksum.$(OBJEXT)	\
+	$(OUTPRE)make_random_key.$(OBJEXT)	\
+	$(OUTPRE)mandatory_sumtype.$(OBJEXT)	\
+	$(OUTPRE)nfold.$(OBJEXT)		\
+	$(OUTPRE)old_api_glue.$(OBJEXT)		\
+	$(OUTPRE)pbkdf2.$(OBJEXT)		\
+	$(OUTPRE)prf.$(OBJEXT) \
+	$(OUTPRE)prng.$(OBJEXT)			\
+	$(OUTPRE)random_to_key.$(OBJEXT)	\
+	$(OUTPRE)state.$(OBJEXT) \
+	$(OUTPRE)string_to_cksumtype.$(OBJEXT)	\
+	$(OUTPRE)string_to_enctype.$(OBJEXT)	\
+	$(OUTPRE)string_to_key.$(OBJEXT)	\
+	$(OUTPRE)valid_cksumtype.$(OBJEXT)	\
+	$(OUTPRE)valid_enctype.$(OBJEXT)	\
+	$(OUTPRE)verify_checksum.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/block_size.c		\
+	$(srcdir)/checksum_length.c	\
+	$(srcdir)/cksumtype_to_string.c	\
+	$(srcdir)/cksumtypes.c		\
+	$(srcdir)/coll_proof_cksum.c	\
+	$(srcdir)/combine_keys.c	\
+	$(srcdir)/crypto_libinit.c	\
+	$(srcdir)/default_state.c \
+	$(srcdir)/decrypt.c		\
+	$(srcdir)/encrypt.c		\
+	$(srcdir)/encrypt_length.c	\
+	$(srcdir)/enctype_compare.c	\
+	$(srcdir)/enctype_to_string.c	\
+	$(srcdir)/etypes.c		\
+	$(srcdir)/hmac.c		\
+	$(srcdir)/keyblocks.c \
+	$(srcdir)/keyed_cksum.c		\
+	$(srcdir)/keyed_checksum_types.c\
+	$(srcdir)/keylengths.c		\
+	$(srcdir)/make_checksum.c	\
+	$(srcdir)/make_random_key.c	\
+	$(srcdir)/mandatory_sumtype.c	\
+	$(srcdir)/nfold.c		\
+	$(srcdir)/old_api_glue.c	\
+	$(srcdir)/pbkdf2.c	\
+	$(srcdir)/prf.c \
+	$(srcdir)/prng.c		\
+	$(srcdir)/random_to_key.c	\
+	$(srcdir)/state.c \
+	$(srcdir)/string_to_cksumtype.c	\
+	$(srcdir)/string_to_enctype.c	\
+	$(srcdir)/string_to_key.c	\
+	$(srcdir)/valid_cksumtype.c	\
+	$(srcdir)/valid_enctype.c	\
+	$(srcdir)/verify_checksum.c
+
+
+LIBBASE=k5crypto
+LIBMAJOR=3
+LIBMINOR=1
+LIBINITFUNC=cryptoint_initialize_library
+LIBFINIFUNC=cryptoint_cleanup_library
+RELDIR=crypto
+
+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 arcfour/OBJS.ST \
+	aes/OBJS.ST \
+	yarrow/OBJS.ST \
+	OBJS.ST
+SUBDIROBJLISTS=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 arcfour/OBJS.ST \
+	aes/OBJS.ST \
+	yarrow/OBJS.ST
+
+# No dependencies.  Record places to find this shared object if the target
+# link editor and loader support it.
+DEPLIBS=
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_EXPLIBS= $(SUPPORT_LIB) $(LIBS)
+SHLIB_EXPDEPLIBS= $(SUPPORT_DEPLIB)
+SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@
+SHLIB_LIBDIRS= @SHLIB_LIBDIRS@
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-liblinks
+install-unix:: install-libs
+
+libcrypto.lib:
+	libdir crypto.lib
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+check-unix:: t_nfold t_encrypt t_prf t_prng t_hmac t_pkcs5
+	$(RUN_SETUP) $(VALGRIND) ./t_nfold
+	$(RUN_SETUP) $(VALGRIND) ./t_encrypt
+	$(RUN_SETUP) $(VALGRIND) ./t_prng <$(srcdir)/t_prng.seed >t_prng.output && \
+	diff t_prng.output $(srcdir)/t_prng.expected
+	$(RUN_SETUP) $(VALGRIND) ./t_hmac
+
+#	$(RUN_SETUP) $(VALGRIND) ./t_pkcs5
+
+t_nfold$(EXEEXT): t_nfold.$(OBJEXT) nfold.$(OBJEXT) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_nfold.$(OBJEXT) nfold.$(OBJEXT) $(SUPPORT_LIB)
+
+t_encrypt$(EXEEXT): t_encrypt.$(OBJEXT) nfold.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_encrypt.$(OBJEXT)  -lkrb5 -lk5crypto -lcom_err $(SUPPORT_LIB)
+
+t_prf$(EXEEXT): t_prf.$(OBJEXT) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_prf.$(OBJEXT)  -lkrb5 -lk5crypto -lcom_err $(SUPPORT_LIB)
+
+t_prng$(EXEEXT): t_prng.$(OBJEXT) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_prng.$(OBJEXT)  -lk5crypto -lcom_err $(SUPPORT_LIB)
+
+t_hmac$(EXEEXT): t_hmac.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_hmac.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
+
+t_pkcs5$(EXEEXT): t_pkcs5.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_pkcs5.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
+
+vectors$(EXEEXT): vectors.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ vectors.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
+
+t_cts$(EXEEXT): t_cts.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_cts.$(OBJEXT) \
+		$(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
+
+
+clean::
+	$(RM) t_nfold.o t_nfold t_encrypt t_encrypt.o t_prng.o t_prng \
+		t_hmac.o t_hmac t_pkcs5.o t_pkcs5 pbkdf2.o t_prf t_prf.o
+	-$(RM) t_prng.output
+
+all-windows::
+	cd crc32
+	@echo Making in crypto\crc32
+	$(MAKE) -$(MFLAGS)
+	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 ..\md5
+	@echo Making in crypto\md5
+	$(MAKE) -$(MFLAGS)
+	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 ..\arcfour
+	@echo Making in crypto\arcfour
+	$(MAKE) -$(MFLAGS)
+	cd ..\yarrow
+	@echo Making in crypto\yarrow
+	$(MAKE) -$(MFLAGS)
+	cd ..\aes
+	@echo Making in crypto\aes
+	$(MAKE) -$(MFLAGS)
+	cd ..
+
+clean-windows::
+	cd 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 ..\old
+	@echo Making clean in crypto\old
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\raw
+	@echo Making clean in crypto\raw
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\sha1
+	@echo Making clean in crypto\sha1
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\arcfour
+	@echo Making clean in crypto\arcfour
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\yarrow
+	@echo Making clean in crypto\yarrow
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\aes
+	@echo Making clean in crypto\aes
+	$(MAKE) -$(MFLAGS) clean
+	cd ..
+
+check-windows::
+	cd 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 ..\old
+	@echo Making check in crypto\old
+	$(MAKE) -$(MFLAGS) check
+	cd ..\raw
+	@echo Making check in crypto\raw
+	$(MAKE) -$(MFLAGS) check
+	cd ..\sha1
+	@echo Making check in crypto\sha1
+	$(MAKE) -$(MFLAGS) check
+	cd ..\arcfour
+	@echo Making check in crypto\arcfour
+	$(MAKE) -$(MFLAGS) check
+	cd ..\yarrow
+	@echo Making check in crypto\yarrow
+	$(MAKE) -$(MFLAGS) check
+	cd ..\aes
+	@echo Making check in crypto\aes
+	$(MAKE) -$(MFLAGS) check
+	cd ..
+
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+block_size.so block_size.po $(OUTPRE)block_size.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h block_size.c etypes.h
+checksum_length.so checksum_length.po $(OUTPRE)checksum_length.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h checksum_length.c \
+  cksumtypes.h
+cksumtype_to_string.so cksumtype_to_string.po $(OUTPRE)cksumtype_to_string.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cksumtype_to_string.c \
+  cksumtypes.h
+cksumtypes.so cksumtypes.po $(OUTPRE)cksumtypes.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/hash_provider/hash_provider.h \
+  $(srcdir)/keyhash_provider/keyhash_provider.h cksumtypes.c \
+  cksumtypes.h
+coll_proof_cksum.so coll_proof_cksum.po $(OUTPRE)coll_proof_cksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cksumtypes.h coll_proof_cksum.c
+combine_keys.so combine_keys.po $(OUTPRE)combine_keys.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/dk/dk.h \
+  combine_keys.c etypes.h
+crypto_libinit.so crypto_libinit.po $(OUTPRE)crypto_libinit.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h crypto_libinit.c
+default_state.so default_state.po $(OUTPRE)default_state.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h default_state.c
+decrypt.so decrypt.po $(OUTPRE)decrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  decrypt.c etypes.h
+encrypt.so encrypt.po $(OUTPRE)encrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  encrypt.c etypes.h
+encrypt_length.so encrypt_length.po $(OUTPRE)encrypt_length.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h encrypt_length.c etypes.h
+enctype_compare.so enctype_compare.po $(OUTPRE)enctype_compare.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h enctype_compare.c \
+  etypes.h
+enctype_to_string.so enctype_to_string.po $(OUTPRE)enctype_to_string.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h enctype_to_string.c \
+  etypes.h
+etypes.so etypes.po $(OUTPRE)etypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/aes/aes_s2k.h $(srcdir)/arcfour/arcfour.h \
+  $(srcdir)/dk/dk.h $(srcdir)/enc_provider/enc_provider.h \
+  $(srcdir)/hash_provider/hash_provider.h $(srcdir)/old/old.h \
+  $(srcdir)/raw/raw.h etypes.c etypes.h
+hmac.so hmac.po $(OUTPRE)hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  hmac.c
+keyblocks.so keyblocks.po $(OUTPRE)keyblocks.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h keyblocks.c
+keyed_cksum.so keyed_cksum.po $(OUTPRE)keyed_cksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cksumtypes.h keyed_cksum.c
+keyed_checksum_types.so keyed_checksum_types.po $(OUTPRE)keyed_checksum_types.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cksumtypes.h etypes.h \
+  keyed_checksum_types.c
+keylengths.so keylengths.po $(OUTPRE)keylengths.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h keylengths.c
+make_checksum.so make_checksum.po $(OUTPRE)make_checksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/dk/dk.h \
+  cksumtypes.h etypes.h make_checksum.c
+make_random_key.so make_random_key.po $(OUTPRE)make_random_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h make_random_key.c
+mandatory_sumtype.so mandatory_sumtype.po $(OUTPRE)mandatory_sumtype.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h mandatory_sumtype.c
+nfold.so nfold.po $(OUTPRE)nfold.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  nfold.c
+old_api_glue.so old_api_glue.po $(OUTPRE)old_api_glue.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h old_api_glue.c
+pbkdf2.so pbkdf2.po $(OUTPRE)pbkdf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/hash_provider/hash_provider.h pbkdf2.c
+prf.so prf.po $(OUTPRE)prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  etypes.h prf.c
+prng.so prng.po $(OUTPRE)prng.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/enc_provider/enc_provider.h $(srcdir)/sha1/shs.h \
+  $(srcdir)/yarrow/yarrow.h $(srcdir)/yarrow/ycipher.h \
+  $(srcdir)/yarrow/yhash.h $(srcdir)/yarrow/ytypes.h \
+  prng.c
+random_to_key.so random_to_key.po $(OUTPRE)random_to_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h random_to_key.c
+state.so state.po $(OUTPRE)state.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  etypes.h state.c
+string_to_cksumtype.so string_to_cksumtype.po $(OUTPRE)string_to_cksumtype.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cksumtypes.h string_to_cksumtype.c
+string_to_enctype.so string_to_enctype.po $(OUTPRE)string_to_enctype.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h string_to_enctype.c
+string_to_key.so string_to_key.po $(OUTPRE)string_to_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h string_to_key.c
+valid_cksumtype.so valid_cksumtype.po $(OUTPRE)valid_cksumtype.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cksumtypes.h valid_cksumtype.c
+valid_enctype.so valid_enctype.po $(OUTPRE)valid_enctype.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h valid_enctype.c
+verify_checksum.so verify_checksum.po $(OUTPRE)verify_checksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cksumtypes.h verify_checksum.c
+t_nfold.so t_nfold.po $(OUTPRE)t_nfold.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  t_nfold.c
+t_encrypt.so t_encrypt.po $(OUTPRE)t_encrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h etypes.h t_encrypt.c
+t_prf.so t_prf.po $(OUTPRE)t_prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  t_prf.c
+t_prng.so t_prng.po $(OUTPRE)t_prng.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  t_prng.c
+t_hmac.so t_hmac.po $(OUTPRE)t_hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/hash_provider/hash_provider.h t_hmac.c
+t_pkcs5.so t_pkcs5.po $(OUTPRE)t_pkcs5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  t_pkcs5.c
+t_cts.so t_cts.po $(OUTPRE)t_cts.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/hash_provider/hash_provider.h t_cts.c
+vectors.so vectors.po $(OUTPRE)vectors.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/hash_provider/hash_provider.h vectors.c
diff --git a/krb5-1-6/src/lib/crypto/aes/Makefile.in b/krb5-1-6/src/lib/crypto/aes/Makefile.in
new file mode 100644
index 000000000..8a740cca6
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/Makefile.in
@@ -0,0 +1,93 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/aes
+mydir=lib/crypto/aes
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../dk
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=aes
+##DOS##OBJFILE=..\$(OUTPRE)aes.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS=\
+	aescrypt.o	\
+	aestab.o	\
+	aeskey.o	\
+	aes_s2k.o
+
+OBJS=\
+	$(OUTPRE)aescrypt.$(OBJEXT)	\
+	$(OUTPRE)aestab.$(OBJEXT)	\
+	$(OUTPRE)aeskey.$(OBJEXT)	\
+	$(OUTPRE)aes_s2k.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/aescrypt.c	\
+	$(srcdir)/aestab.c	\
+	$(srcdir)/aeskey.c	\
+	$(srcdir)/aes_s2k.c
+
+GEN_OBJS=\
+	$(OUTPRE)aescrypt.$(OBJEXT)	\
+	$(OUTPRE)aestab.$(OBJEXT)	\
+	$(OUTPRE)aeskey.$(OBJEXT)
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs # aes-gen
+
+includes:: depend
+
+depend:: $(SRCS)
+
+aes-gen: aes-gen.o $(GEN_OBJS)
+	$(CC_LINK) -o aes-gen aes-gen.o $(GEN_OBJS)
+
+run-aes-gen: aes-gen
+	./aes-gen > kresults.out
+
+check:: run-aes-gen
+
+aes-test: aes-test.$(OBJEXT) $(CRYPTO_DEPLIB)
+	$(CC_LINK) -o aes-test aes-test.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
+
+check:: run-aes-test
+run-aes-test: aes-test
+	$(RUN_SETUP) $(VALGRIND) ./aes-test -k > vk.txt
+	cmp vk.txt $(srcdir)/expect-vk.txt
+	$(RUN_SETUP) $(VALGRIND) ./aes-test > vt.txt
+	cmp vt.txt $(srcdir)/expect-vt.txt
+
+clean-unix:: clean-libobjs
+
+clean::
+	-$(RM) aes-gen aes-gen.o vt.txt vk.txt kresults.out aes-test aes-test.o
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+aescrypt.so aescrypt.po $(OUTPRE)aescrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h aes.h aescrypt.c aesopt.h \
+  uitypes.h
+aestab.so aestab.po $(OUTPRE)aestab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  aes.h aesopt.h aestab.c uitypes.h
+aeskey.so aeskey.po $(OUTPRE)aeskey.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  aes.h aeskey.c aesopt.h uitypes.h
+aes_s2k.so aes_s2k.po $(OUTPRE)aes_s2k.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../dk/dk.h aes_s2k.c aes_s2k.h
diff --git a/krb5-1-6/src/lib/crypto/aes/aes-gen.c b/krb5-1-6/src/lib/crypto/aes/aes-gen.c
new file mode 100644
index 000000000..855e6a470
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aes-gen.c
@@ -0,0 +1,326 @@
+/*
+ * To be compiled against the AES code from:
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/index.htm
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "aes.h"
+
+#define B 16U
+unsigned char key[16];
+unsigned char test_case_len[] = { B+1, 2*B-1, 2*B, 2*B+1, 3*B-1, 3*B, 4*B, };
+#define NTESTS (sizeof(test_case_len))
+struct {
+    unsigned char ivec[16];
+    unsigned char input[4*16];
+    unsigned char output[4*16];
+} test_case[NTESTS];
+aes_ctx ctx, dctx;
+
+static void init ()
+{
+    int i, j, r;
+
+    srand(42);
+    for (i = 0; i < 16; i++)
+	key[i] = 0xff & rand();
+    memset(test_case, 0, sizeof(test_case));
+    for (i = 0; i < NTESTS; i++)
+	for (j = 0; j < test_case_len[i]; j++) {
+	    test_case[i].input[j] = 0xff & rand();
+	}
+
+    r = aes_enc_key (key, sizeof(key), &ctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    r = aes_dec_key (key, sizeof(key), &dctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+}
+
+static void hexdump(const unsigned char *ptr, size_t len)
+{
+    int i;
+    for (i = 0; i < len; i++)
+	printf ("%s%02X", (i % 16 == 0) ? "\n    " : " ", ptr[i]);
+}
+
+static void fips_test ()
+{
+    static const unsigned char fipskey[16] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    };
+    static const unsigned char input[16] = {
+	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+    };
+    static const unsigned char expected[16] = {
+	0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+	0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a,
+    };
+    unsigned char output[16];
+    unsigned char tmp[16];
+    aes_ctx fipsctx;
+    int r;
+
+    printf ("FIPS test:\nkey:");
+    hexdump (fipskey, 16);
+    printf ("\ninput:");
+    hexdump (input, 16);
+    r = aes_enc_key (fipskey, sizeof(fipskey), &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    r = aes_enc_blk (input, output, &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    printf ("\noutput:");
+    hexdump (output, 16);
+    printf ("\n");
+    if (memcmp(expected, output, 16))
+	fprintf(stderr, "wrong results!!!\n"), exit (1);
+    r = aes_dec_key (fipskey, sizeof(fipskey), &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    r = aes_dec_blk (output, tmp, &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    if (memcmp(input, tmp, 16))
+	fprintf(stderr, "decryption failed!!\n"), exit(1);
+    printf ("ok.\n\n");
+}
+
+static void
+xor (unsigned char *out, const unsigned char *a, const unsigned char *b)
+{
+    int i;
+    for (i = 0; i < B; i++)
+	out[i] = a[i] ^ b[i];
+}
+
+static void
+ecb_enc (unsigned char *out, unsigned char *in, unsigned int len)
+{
+    int i, r;
+    for (i = 0; i < len; i += 16) {
+	r = aes_enc_blk (in + i, out + i, &ctx);
+	if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    }
+    if (i != len) abort ();
+}
+
+static void
+ecb_dec (unsigned char *out, unsigned char *in, unsigned int len)
+{
+    int i, r;
+    for (i = 0; i < len; i += 16) {
+	r = aes_dec_blk (in + i, out + i, &dctx);
+	if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    }
+    if (i != len) abort ();
+}
+
+#define D(X) (printf("%s %d: %s=",__FUNCTION__,__LINE__, #X),hexdump(X,B),printf("\n"))
+
+#undef D
+#define D(X)
+
+static void
+cbc_enc (unsigned char *out, unsigned char *in, unsigned char *iv,
+	 unsigned int len)
+{
+    int i, r;
+    unsigned char tmp[B];
+    D(iv);
+    memcpy (tmp, iv, B);
+    for (i = 0; i < len; i += B) {
+	D(in+i);
+	xor (tmp, tmp, in + i);
+	D(tmp);
+	r = aes_enc_blk (tmp, out + i, &ctx);
+	if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+	memcpy (tmp, out + i, B);
+	D(out+i);
+    }
+    if (i != len) abort ();
+}
+
+static void
+cbc_dec (unsigned char *out, unsigned char *in, unsigned char *iv,
+	 unsigned int len)
+{
+    int i, r;
+    unsigned char tmp[B];
+    memcpy (tmp, iv, B);
+    for (i = 0; i < len; i += B) {
+	r = aes_dec_blk (in + i, tmp, &dctx);
+	if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+	xor (tmp, tmp, iv);
+	iv = in + i;
+	memcpy (out + i, tmp, B);
+    }
+    if (i != len) abort ();
+}
+
+static void
+cts_enc (unsigned char *out, unsigned char *in, unsigned char *iv,
+	 unsigned int len)
+{
+    int r;
+    unsigned int len2;
+    unsigned char pn1[B], pn[B], cn[B], cn1[B];
+
+    if (len < B + 1) abort ();
+    len2 = (len - B - 1) & ~(B-1);
+    cbc_enc (out, in, iv, len2);
+    out += len2;
+    in += len2;
+    len -= len2;
+    if (len2)
+	iv = out - B;
+    if (len <= B || len > 2 * B)
+	abort ();
+    printf ("(did CBC mode for %d)\n", len2);
+
+    D(in);
+    xor (pn1, in, iv);
+    D(pn1);
+    r = aes_enc_blk (pn1, cn, &ctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    D(cn);
+    memset (pn, 0, sizeof(pn));
+    memcpy (pn, in+B, len-B);
+    D(pn);
+    xor (pn, pn, cn);
+    D(pn);
+    r = aes_enc_blk (pn, cn1, &ctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    D(cn1);
+    memcpy(out, cn1, B);
+    memcpy(out+B, cn, len-B);
+}
+
+static void
+cts_dec (unsigned char *out, unsigned char *in, unsigned char *iv,
+	 unsigned int len)
+{
+    int r;
+    unsigned int len2;
+    unsigned char pn1[B], pn[B], cn[B], cn1[B];
+
+    if (len < B + 1) abort ();
+    len2 = (len - B - 1) & ~(B-1);
+    cbc_dec (out, in, iv, len2);
+    out += len2;
+    in += len2;
+    len -= len2;
+    if (len2)
+	iv = in - B;
+    if (len <= B || len > 2 * B)
+	abort ();
+
+    memcpy (cn1, in, B);
+    r = aes_dec_blk (cn1, pn, &dctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    memset (cn, 0, sizeof(cn));
+    memcpy (cn, in+B, len-B);
+    xor (pn, pn, cn);
+    memcpy (cn+len-B, pn+len-B, 2*B-len);
+    r = aes_dec_blk (cn, pn1, &dctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    xor (pn1, pn1, iv);
+    memcpy(out, pn1, B);
+    memcpy(out+B, pn, len-B);
+}
+
+static void ecb_test ()
+{
+    int testno;
+    unsigned char tmp[4*B];
+
+    printf ("ECB tests:\n");
+    printf ("key:");
+    hexdump (key, sizeof(key));
+    for (testno = 0; testno < NTESTS; testno++) {
+	unsigned len = (test_case_len[testno] + 15) & ~15;
+	printf ("\ntest %d - %d bytes\n", testno, len);
+	printf ("input:");
+	hexdump (test_case[testno].input, len);
+	printf ("\n");
+	ecb_enc (test_case[testno].output, test_case[testno].input, len);
+	printf ("output:");
+	hexdump (test_case[testno].output, len);
+	printf ("\n");
+	ecb_dec (tmp, test_case[testno].output, len);
+	if (memcmp (tmp, test_case[testno].input, len)) {
+	    printf ("ecb decrypt failed!!");
+	    hexdump (tmp, len);
+	    printf ("\n");
+	    exit (1);
+	}
+    }
+    printf ("\n");
+}
+
+unsigned char ivec[16] = { 0 };
+
+static void cbc_test ()
+{
+    int testno;
+    unsigned char tmp[4*B];
+
+    printf ("CBC tests:\n");
+    printf ("initial vector:");
+    hexdump (ivec, sizeof(ivec));
+    for (testno = 0; testno < NTESTS; testno++) {
+	unsigned len = (test_case_len[testno] + 15) & ~15;
+	printf ("\ntest %d - %d bytes\n", testno, len);
+	printf ("input:");
+	hexdump (test_case[testno].input, len);
+	printf ("\n");
+	cbc_enc (test_case[testno].output, test_case[testno].input, ivec, len);
+	printf ("output:");
+	hexdump (test_case[testno].output, len);
+	printf ("\n");
+	cbc_dec (tmp, test_case[testno].output, ivec, len);
+	if (memcmp (tmp, test_case[testno].input, len)) {
+	    printf("cbc decrypt failed!!");
+	    hexdump (tmp, len);
+	    printf ("\n");
+	    exit(1);
+	}
+    }
+    printf ("\n");
+}
+
+static void cts_test ()
+{
+    int testno;
+    unsigned char tmp[4*B];
+
+    printf ("CTS tests:\n");
+    printf ("initial vector:");
+    hexdump (ivec, sizeof(ivec));
+    for (testno = 0; testno < NTESTS; testno++) {
+	unsigned int len = test_case_len[testno];
+	printf ("\ntest %d - %d bytes\n", testno, len);
+	printf ("input:");
+	hexdump (test_case[testno].input, len);
+	printf ("\n");
+	cts_enc (test_case[testno].output, test_case[testno].input, ivec, len);
+	printf ("output:");
+	hexdump (test_case[testno].output, len);
+	printf ("\n");
+	cts_dec (tmp, test_case[testno].output, ivec, len);
+	if (memcmp (tmp, test_case[testno].input, len))
+	    fprintf (stderr, "cts decrypt failed!!\n"), exit(1);
+    }
+    printf ("\n");
+}
+
+int main ()
+{
+    init ();
+    fips_test ();
+
+    ecb_test();
+    cbc_test();
+    cts_test();
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/aes/aes-test.c b/krb5-1-6/src/lib/crypto/aes/aes-test.c
new file mode 100644
index 000000000..c05fd26e3
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aes-test.c
@@ -0,0 +1,138 @@
+/*
+ * lib/crypto/aes/aes-test.c
+ *
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Subset of NIST tests for AES; specifically, the variable-key and
+ * variable-text tests for 128- and 256-bit keys.
+ */
+
+#include <stdio.h>
+#include "k5-int.h"
+
+static char key[32];
+static char plain[16], cipher[16], zero[16];
+
+static krb5_keyblock enc_key;
+static krb5_data ivec;
+static krb5_data in, out;
+static void init()
+{
+    enc_key.contents = key;
+    enc_key.length = 16;
+    ivec.data = zero;
+    ivec.length = 16;
+    in.data = plain;
+    in.length = 16;
+    out.data = cipher;
+    out.length = 16;
+}
+static void enc()
+{
+    krb5int_aes_encrypt(&enc_key, &ivec, &in, &out);
+}
+
+static void hexdump(const char *label, const char *cp, int len)
+{
+    printf("%s=", label);
+    while (len--) printf("%02X", 0xff & *cp++);
+    printf("\n");
+}
+
+static void set_bit(char *ptr, int bitnum)
+{
+    int bytenum;
+    bytenum = bitnum / 8;
+    bitnum %= 8;
+    /* First bit is the high bit! */
+    ptr[bytenum] = 1 << (7 - bitnum);
+}
+
+/* Variable-Key tests */
+static void vk_test_1(int len)
+{
+    int i;
+
+    enc_key.length = len;
+    printf("\nKEYSIZE=%d\n\n", len * 8);
+    memset(plain, 0, sizeof(plain));
+    hexdump("PT", plain, 16);
+    for (i = 0; i < len * 8; i++) {
+	memset(key, 0, len);
+	set_bit(key, i);
+	printf("\nI=%d\n", i+1);
+	hexdump("KEY", key, len);
+	enc();
+	hexdump("CT", cipher, 16);
+    }
+    printf("\n==========\n");
+}
+static void vk_test()
+{
+    vk_test_1(16);
+    vk_test_1(32);
+}
+
+/* Variable-Text tests */
+static void vt_test_1(int len)
+{
+    int i;
+
+    enc_key.length = len;
+    printf("\nKEYSIZE=%d\n\n", len * 8);
+    memset(key, 0, len);
+    hexdump("KEY", key, len);
+    for (i = 0; i < 16 * 8; i++) {
+	memset(plain, 0, sizeof(plain));
+	set_bit(plain, i);
+	printf("\nI=%d\n", i+1);
+	hexdump("PT", plain, 16);
+	enc();
+	hexdump("CT", cipher, 16);
+    }
+    printf("\n==========\n");
+}
+static void vt_test()
+{
+    vt_test_1(16);
+    vt_test_1(32);
+}
+
+
+int main (int argc, char *argv[])
+{
+    if (argc > 2 || (argc == 2 && strcmp(argv[1], "-k"))) {
+	fprintf(stderr,
+		"usage:\t%s -k\tfor variable-key tests\n"
+		"   or:\t%s   \tfor variable-plaintext tests\n",
+		argv[0], argv[0]);
+	return 1;
+    }
+    init();
+    if (argc == 2)
+	vk_test();
+    else
+	vt_test();
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/aes/aes.h b/krb5-1-6/src/lib/crypto/aes/aes.h
new file mode 100644
index 000000000..ac1c1b89e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aes.h
@@ -0,0 +1,97 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the definitions required to use AES (Rijndael) in C.
+*/
+
+#ifndef _AES_H
+#define _AES_H
+
+#include "uitypes.h"
+
+/*  BLOCK_SIZE is in BYTES: 16, 24, 32 or undefined for aes.c and 16, 20, 
+    24, 28, 32 or undefined for aespp.c.  When left undefined a slower 
+    version that provides variable block length is compiled.    
+*/
+
+#define BLOCK_SIZE  16
+
+/* key schedule length (in 32-bit words)    */
+
+#if !defined(BLOCK_SIZE)
+#define KS_LENGTH   128
+#else
+#define KS_LENGTH   4 * BLOCK_SIZE
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+typedef uint16_t    aes_fret;   /* type for function return value       */
+#define aes_bad     0           /* bad function return value            */
+#define aes_good    1           /* good function return value           */
+#ifndef AES_DLL                 /* implement normal or DLL functions    */
+#define aes_rval    aes_fret
+#else
+#define aes_rval    aes_fret __declspec(dllexport) _stdcall
+#endif
+
+typedef struct                      /* the AES context for encryption   */
+{   uint32_t    k_sch[KS_LENGTH];   /* the encryption key schedule      */
+    uint32_t    n_rnd;              /* the number of cipher rounds      */
+    uint32_t    n_blk;              /* the number of bytes in the state */
+} aes_ctx;
+
+/* for Kerberos 5 tree -- hide names!  */
+#define aes_blk_len	krb5int_aes_blk_len
+#define aes_enc_key	krb5int_aes_enc_key
+#define aes_enc_blk	krb5int_aes_enc_blk
+#define aes_dec_key	krb5int_aes_dec_key
+#define aes_dec_blk	krb5int_aes_dec_blk
+#define fl_tab		krb5int_fl_tab
+#define ft_tab		krb5int_ft_tab
+#define il_tab		krb5int_il_tab
+#define im_tab		krb5int_im_tab
+#define it_tab		krb5int_it_tab
+#define rcon_tab	krb5int_rcon_tab
+
+aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]);
+
+aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/aes.txt b/krb5-1-6/src/lib/crypto/aes/aes.txt
new file mode 100644
index 000000000..b644b5eb4
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aes.txt
@@ -0,0 +1,70 @@
+
+An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197)
+--------------------------------------------------------------------
+
+The source code files are as follows:
+
+1. aes.h:       the header file required to use AES in C
+2. aescpp.h     the header file required to use AES in C++
+3. aescrypt.c   the main C source code file for encryption and decryption
+4. aeskey.c     the main C source code file for the key schedule
+5. aestab.c     the main file for the AES tables
+6. aesopt.h     the file for common code and for setting build options
+7. aescrypt.asm a faster alternative to 3 above in assembler (using NASM)
+8. uitypes.h    a file for defining fixed length unsigned integer types
+9. aescrypp.c   an alternative to 3 for all Rijndael block and key sizes 
+10.aeskeypp.c   an alternative to 4 for all Rijndael block and key sizes 
+11.aesxam.c     an example of AES use
+
+Source files 9 and 10 are much slower than 4 and 5 for normal use and
+should not be used unless support for 20 and 28 byte blocks and keys
+is necessary.  Files 4 and 5 provide support for block and key sizes
+of 16, 24 and 32 bytes (fixed or variable) but the assemler code in 
+file 7 only supports the 16 byte AES block length. It does, however,
+offer the three key sizes when used with file 4. The use of files 4
+and 5 (or 9 and 10) with variable block size should be avoided since 
+the code is much faster when the block size is fixed.
+
+The VC++ AES Development Project
+--------------------------------
+
+The VC++ SOlution contains the following sub-projects
+
+1. aes_asm      this project tests the assembler code implementation
+2. aes_dll      this project builds the DLL version
+3. aes_gav      this project re-creates the test vector files and
+                optionally checks them against a reference set
+4. aes_rav      this project checks the values produced by the code
+                against the values in the test vector files
+5. aes_tmr      this project measures the speed of the code
+6. aes_tst      this project is set up to test the extended version
+                of Rijndael with block and key sizes of 16, 20, 24,
+                28 and 32 bytes
+7. aes_xam      this project builds the example of AES use in a 
+                simple file encryption program
+                
+Note that the paths for the various directories have to be set up in 
+aestst.h
+
+The AES and Rijndael Test Vector Files
+--------------------------------------
+
+These files fall in the following groups (where <nn> is a two digit
+number):
+
+1. ecbvk<nn>.txt  ECB vectors with variable key
+2. ecbvt<nn>.txt  ECB vectors with variable text
+3. ecbnk<nn>.txt  new ECB vectors with variable key 
+4. ecbnt<nn>.txt  new ECB vectors with variable text
+5. ecbme<nn>.txt  ECB monte carlo encryption test vectors
+6. ecbmd<nn>.txt  ECB monte carlo decryption test vectors
+7. cbcme<nn>.txt  CBC monte carlo encryption test vectors
+8. cbcmd<nn>.txt  CBC monte carlo decryption test vectors
+
+The first digit of the numeric suffix on the filename gives the 
+block size in 32bit units and the second numeric digit gives the
+key size.  For example, the file ecbvk44.txt provides the test 
+vectors for ECB encryption with a 128 bit block size and a 128 
+bit key size.
+
+   Brian Gladman <brg@gladman.uk.net>
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/aes_s2k.c b/krb5-1-6/src/lib/crypto/aes/aes_s2k.c
new file mode 100644
index 000000000..68d3111bf
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aes_s2k.c
@@ -0,0 +1,93 @@
+/*
+ * lib/crypto/aes/aes_s2k.c
+ *
+ * Copyright 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5int_aes_string_to_key
+ */
+
+#include "k5-int.h"
+#include "dk.h"
+#include "aes_s2k.h"
+
+#define DEFAULT_ITERATION_COUNT		4096 /* was 0xb000L in earlier drafts */
+#define MAX_ITERATION_COUNT		0x1000000L
+
+krb5_error_code
+krb5int_aes_string_to_key(const struct krb5_enc_provider *enc,
+			  const krb5_data *string,
+			  const krb5_data *salt,
+			  const krb5_data *params,
+			  krb5_keyblock *key)
+{
+    unsigned long iter_count;
+    krb5_data out;
+    static const krb5_data usage = { KV5M_DATA, 8, "kerberos" };
+    krb5_error_code err;
+
+    if (params) {
+	unsigned char *p = (unsigned char *) params->data;
+	if (params->length != 4)
+	    return KRB5_ERR_BAD_S2K_PARAMS;
+	/* The first two need casts in case 'int' is 16 bits.  */
+	iter_count = (((unsigned long)p[0] << 24)
+		      | ((unsigned long)p[1] << 16)
+		      | (p[2] <<  8)
+		      | (p[3]));
+	if (iter_count == 0) {
+	    iter_count = (1L << 16) << 16;
+	    if (((iter_count >> 16) >> 16) != 1)
+		return KRB5_ERR_BAD_S2K_PARAMS;
+	}
+    } else
+	iter_count = DEFAULT_ITERATION_COUNT;
+
+    /* This is not a protocol specification constraint; this is an
+       implementation limit, which should eventually be controlled by
+       a config file.  */
+    if (iter_count >= MAX_ITERATION_COUNT)
+	return KRB5_ERR_BAD_S2K_PARAMS;
+
+    /*
+     * Dense key space, no parity bits or anything, so take a shortcut
+     * and use the key contents buffer for the generated bytes.
+     */
+    out.data = (char *) key->contents;
+    out.length = key->length;
+    if (out.length != 16 && out.length != 32)
+	return KRB5_CRYPTO_INTERNAL;
+
+    err = krb5int_pbkdf2_hmac_sha1 (&out, iter_count, string, salt);
+    if (err) {
+	memset(out.data, 0, out.length);
+	return err;
+    }
+
+    err = krb5_derive_key (enc, key, key, &usage);
+    if (err) {
+	memset(out.data, 0, out.length);
+	return err;
+    }
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/aes/aes_s2k.h b/krb5-1-6/src/lib/crypto/aes/aes_s2k.h
new file mode 100644
index 000000000..b6804a991
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aes_s2k.h
@@ -0,0 +1,4 @@
+extern krb5_error_code
+krb5int_aes_string_to_key (const struct krb5_enc_provider *,
+			   const krb5_data *, const krb5_data *,
+			   const krb5_data *, krb5_keyblock *key);
diff --git a/krb5-1-6/src/lib/crypto/aes/aescpp.h b/krb5-1-6/src/lib/crypto/aes/aescpp.h
new file mode 100644
index 000000000..e685485e1
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aescpp.h
@@ -0,0 +1,55 @@
+
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ TERMS
+
+ Redistribution and use in source and binary forms, with or without 
+ modification, are permitted subject to the following conditions:
+
+  1. Redistributions of source code must retain the above copyright 
+     notice, this list of conditions and the following disclaimer. 
+
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the 
+     documentation and/or other materials provided with the distribution. 
+
+  3. The copyright holder's name must not be used to endorse or promote 
+     any products derived from this software without his specific prior 
+     written permission. 
+
+ This software is provided 'as is' with no express or implied warranties 
+ of correctness or fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the definitions required to use AES (Rijndael) in C++.
+*/
+
+#ifndef _AESCPP_H
+#define _AESCPP_H
+
+#include "aes.h"
+
+class AESclass
+{   aes_ctx cx[1];
+public:
+#if defined(BLOCK_SIZE)
+    AESclass()                          { cx->n_blk = BLOCK_SIZE; cx->n_rnd = 0; }
+#else
+    AESclass(unsigned int blen = 16)    { cx->n_blk = blen; cx->n_rnd = 0; }
+#endif
+    aes_rval blk_len(unsigned int blen) { return aes_blk_len(blen, cx); }
+    aes_rval enc_key(const unsigned char in_key[], unsigned int klen)
+            { return aes_enc_key(in_key, klen, cx); }
+    aes_rval dec_key(const unsigned char in_key[], unsigned int klen)
+            { return aes_dec_key(in_key, klen, cx); }
+    aes_rval enc_blk(const unsigned char in_blk[], unsigned char out_blk[])
+            { return aes_enc_blk(in_blk, out_blk, cx); }
+    aes_rval dec_blk(const unsigned char in_blk[], unsigned char out_blk[])
+            { return aes_dec_blk(in_blk, out_blk, cx); }
+};
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/aescrypp.c b/krb5-1-6/src/lib/crypto/aes/aescrypp.c
new file mode 100644
index 000000000..87b634179
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aescrypp.c
@@ -0,0 +1,487 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing encryption and decryption
+ for AES (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes.
+ It can optionally be replaced by code written in assembler using NASM.
+*/
+
+#include "aesopt.h"
+
+#define unused  77  /* Sunset Strip */
+
+#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c]
+#define so(y,x,c)   word_out(y + 4 * c, s(x,c))
+
+#if BLOCK_SIZE == 16
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[4],y[4]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
+ /* 
+   the following defines prevent the compiler requiring the declaration
+   of generated but unused variables in the fwd_var and inv_var macros
+ */
+#define b04 unused
+#define b05 unused
+#define b06 unused
+#define b07 unused
+#define b14 unused
+#define b15 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
+
+#elif BLOCK_SIZE == 20
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[5],y[5]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,y##0,y##1,y##2,y##3,y##4
+#define b05 unused
+#define b06 unused
+#define b07 unused
+#define b15 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); s(y,4) = s(x,4); 
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); si(y,x,k,4)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); so(y,x,4)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); rm(y,x,k,4)
+
+#elif BLOCK_SIZE == 24
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[6],y[6]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5, \
+                        y##0,y##1,y##2,y##3,y##4,y##5
+#define b06 unused
+#define b07 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
+                        s(y,4) = s(x,4); s(y,5) = s(x,5);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
+                        si(y,x,k,3); si(y,x,k,4); si(y,x,k,5)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); \
+                        so(y,x,3); so(y,x,4); so(y,x,5)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
+                        rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5)
+
+#elif BLOCK_SIZE == 28
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[7],y[7]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5,x##6 \
+                        y##0,y##1,y##2,y##3,y##4,y##5,y##6
+#define b07 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
+                        s(y,4) = s(x,4); s(y,5) = s(x,5);; s(y,6) = s(x,6);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
+                        si(y,x,k,3); si(y,x,k,4); si(y,x,k,5); si(y,x,k,6)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); \
+                        so(y,x,3); so(y,x,4); so(y,x,5); so(y,x,6)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
+                        rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6)
+#else
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[8],y[8]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \
+                        y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
+                        s(y,4) = s(x,4); s(y,5) = s(x,5); \
+                        s(y,6) = s(x,6); s(y,7) = s(x,7);
+
+#if BLOCK_SIZE == 32
+
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \
+                        si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \
+                        so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \
+                        rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7)
+#else
+
+#define state_in(y,x,k) \
+switch(nc) \
+{   case 8: si(y,x,k,7); \
+    case 7: si(y,x,k,6); \
+    case 6: si(y,x,k,5); \
+    case 5: si(y,x,k,4); \
+    case 4: si(y,x,k,3); si(y,x,k,2); \
+            si(y,x,k,1); si(y,x,k,0); \
+}
+
+#define state_out(y,x) \
+switch(nc) \
+{   case 8: so(y,x,7); \
+    case 7: so(y,x,6); \
+    case 6: so(y,x,5); \
+    case 5: so(y,x,4); \
+    case 4: so(y,x,3); so(y,x,2); \
+            so(y,x,1); so(y,x,0); \
+}
+
+#if defined(FAST_VARIABLE)
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
+            rm(y,x,k,5); rm(y,x,k,4); \
+            rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+    case 7: rm(y,x,k,6); rm(y,x,k,5); \
+            rm(y,x,k,4); rm(y,x,k,3); \
+            rm(y,x,k,2); rm(y,x,k,1); \
+            rm(y,x,k,0); \
+            break; \
+    case 6: rm(y,x,k,5); rm(y,x,k,4); \
+            rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+    case 5: rm(y,x,k,4); rm(y,x,k,3); \
+            rm(y,x,k,2); rm(y,x,k,1); \
+            rm(y,x,k,0); \
+            break; \
+    case 4: rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+}
+#else
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{   case 8: rm(y,x,k,7); \
+    case 7: rm(y,x,k,6); \
+    case 6: rm(y,x,k,5); \
+    case 5: rm(y,x,k,4); \
+    case 4: rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+}
+
+#endif
+
+#endif
+#endif
+
+#if defined(ENCRYPTION)
+
+/* I am grateful to Frank Yellin for the following construction
+   (and that for decryption) which, given the column (c) of the 
+   output state variable, gives the input state variables which 
+   are needed for each row (r) of the state.
+
+   For the fixed block size options, compilers should reduce these 
+   two expressions to fixed variable references. But for variable 
+   block size code conditional clauses will sometimes be returned.
+
+   y = output word, x = input word, r = row, c = column for r = 0, 
+   1, 2 and 3 = column accessed for row r.
+*/
+
+#define fwd_var(x,r,c) \
+ ( r==0 ?           \
+    ( c==0 ? s(x,0) \
+    : c==1 ? s(x,1) \
+    : c==2 ? s(x,2) \
+    : c==3 ? s(x,3) \
+    : c==4 ? s(x,4) \
+    : c==5 ? s(x,5) \
+    : c==6 ? s(x,6) \
+    : s(x,7))       \
+ : r==1 ?           \
+    ( c==0 ? s(x,1) \
+    : c==1 ? s(x,2) \
+    : c==2 ? s(x,3) \
+    : c==3 ? nc==4 ? s(x,0) : s(x,4) \
+    : c==4 ? nc==5 ? s(x,0) : s(x,5) \
+    : c==5 ? nc==6 ? s(x,0) : s(x,6) \
+    : c==6 ? nc==7 ? s(x,0) : s(x,7) \
+    : s(x,0))       \
+ : r==2 ?           \
+    ( c==0 ? nc==8 ? s(x,3) : s(x,2) \
+    : c==1 ? nc==8 ? s(x,4) : s(x,3) \
+    : c==2 ? nc==8 ? s(x,5) : nc==4 ? s(x,0) : s(x,4) \
+    : c==3 ? nc==8 ? s(x,6) : nc==5 ? s(x,0) : nc==4 ? s(x,1) : s(x,5) \
+    : c==4 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : nc==6 ? s(x,0) : s(x,1) \
+    : c==5 ? nc==6 ? s(x,1) : s(x,0) \
+    : c==6 ? s(x,1) \
+    : s(x,2))       \
+ :                  \
+    ( c==0 ? nc>6  ? s(x,4) : s(x,3) \
+    : c==1 ? nc>6  ? s(x,5) : nc==4 ? s(x,0) : s(x,4) \
+    : c==2 ? nc>6  ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,0) : s(x,1) \
+    : c==3 ? nc==8 ? s(x,7) : nc==5 ? s(x,1) : nc==4 ? s(x,2) : s(x,0) \
+    : c==4 ? nc==8 ? s(x,0) : nc==5 ? s(x,2) : s(x,1) \
+    : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==6 ? nc==8 ? s(x,2) : s(x,3) \
+    : s(x,3)))
+
+#if defined(FT4_SET)
+#undef  dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c)
+#elif defined(FT1_SET)
+#undef  dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c)
+#else
+#define fwd_rnd(y,x,k,c)    s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c]
+#endif
+
+#if defined(FL4_SET)
+#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c)
+#elif defined(FL1_SET)
+#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c)
+#else
+#define fwd_lrnd(y,x,k,c)   s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{   uint32_t        locals(b0, b1);
+    const uint32_t  *kp = cx->k_sch;
+    dec_fmvars  /* declare variables for fwd_mcol() if needed */
+
+    if(!(cx->n_blk & 1)) return aes_bad;
+
+#if (ENC_UNROLL == FULL)
+
+    state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); 
+    kp += (cx->n_rnd - 9) * nc;
+
+    switch(cx->n_rnd)
+    {
+    case 14:    round(fwd_rnd,  b1, b0, kp - 4 * nc);
+    case 13:    round(fwd_rnd,  b0, b1, kp - 3 * nc);
+    case 12:    round(fwd_rnd,  b1, b0, kp - 2 * nc);
+    case 11:    round(fwd_rnd,  b0, b1, kp -     nc);
+    case 10:    round(fwd_rnd,  b1, b0, kp         );             
+                round(fwd_rnd,  b0, b1, kp +     nc);
+                round(fwd_rnd,  b1, b0, kp + 2 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 3 * nc);
+                round(fwd_rnd,  b1, b0, kp + 4 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 5 * nc);
+                round(fwd_rnd,  b1, b0, kp + 6 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 7 * nc);
+                round(fwd_rnd,  b1, b0, kp + 8 * nc);
+                round(fwd_lrnd, b0, b1, kp + 9 * nc);
+    }
+#else
+    {   uint32_t    rnd;
+
+        state_in(b0, in_blk, kp); 
+
+#if (ENC_UNROLL == PARTIAL)
+
+        for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd)
+        {
+            kp += nc;
+            round(fwd_rnd, b1, b0, kp); 
+            kp += nc;
+            round(fwd_rnd, b0, b1, kp); 
+        }
+
+        if(cx->n_rnd & 1) 
+        {
+            l_copy(b1, b0);
+        }
+        else
+        {
+            kp += nc;
+            round(fwd_rnd,  b1, b0, kp); 
+        }
+#else
+        for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+        {
+            kp += nc;
+            round(fwd_rnd, b1, b0, kp); 
+            l_copy(b0, b1); 
+        }
+#endif
+        kp += nc;
+        round(fwd_lrnd, b0, b1, kp);
+    }
+#endif
+
+    state_out(out_blk, b0);
+    return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION)
+
+#define inv_var(x,r,c) \
+ ( r==0 ?           \
+    ( c==0 ? s(x,0) \
+    : c==1 ? s(x,1) \
+    : c==2 ? s(x,2) \
+    : c==3 ? s(x,3) \
+    : c==4 ? s(x,4) \
+    : c==5 ? s(x,5) \
+    : c==6 ? s(x,6) \
+    : s(x,7))       \
+ : r==1 ?           \
+    ( c==0 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,4) : s(x,3) \
+    : c==1 ? s(x,0) \
+    : c==2 ? s(x,1) \
+    : c==3 ? s(x,2) \
+    : c==4 ? s(x,3) \
+    : c==5 ? s(x,4) \
+    : c==6 ? s(x,5) \
+    : s(x,6))       \
+ : r==2 ?           \
+    ( c==0 ? nc>6  ? s(x,5) : nc==6 ? s(x,4) : nc==5 ? s(x,3) : s(x,2) \
+    : c==1 ? nc>6  ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,4) : s(x,3) \
+    : c==2 ? nc==8 ? s(x,7) : s(x,0) \
+    : c==3 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==4 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==5 ? nc==8 ? s(x,2) : s(x,3) \
+    : c==6 ? nc==8 ? s(x,3) : s(x,4) \
+    : s(x,4))       \
+ :                  \
+    ( c==0 ? nc==8 ? s(x,4) : nc==5 ? s(x,2) : nc==4 ? s(x,1) : s(x,3) \
+    : c==1 ? nc==8 ? s(x,5) : nc==5 ? s(x,3) : nc==4 ? s(x,2) : s(x,4) \
+    : c==2 ? nc==8 ? s(x,6) : nc==5 ? s(x,4) : nc==4 ? s(x,3) : s(x,5) \
+    : c==3 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : s(x,0) \
+    : c==4 ? nc>6  ? s(x,0) : s(x,1) \
+    : c==5 ? nc==6 ? s(x,2) : s(x,1) \
+    : c==6 ? s(x,2) \
+    : s(x,3)))
+
+#if defined(IT4_SET)
+#undef  dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c)
+#elif defined(IT1_SET)
+#undef  dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c)
+#else
+#define inv_rnd(y,x,k,c)    s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c])
+#endif
+
+#if defined(IL4_SET)
+#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c)
+#elif defined(IL1_SET)
+#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c)
+#else
+#define inv_lrnd(y,x,k,c)   s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{   uint32_t        locals(b0, b1);
+    const uint32_t  *kp = cx->k_sch + nc * cx->n_rnd;
+    dec_imvars  /* declare variables for inv_mcol() if needed */
+
+    if(!(cx->n_blk & 2)) return aes_bad;
+
+#if (DEC_UNROLL == FULL)
+
+    state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); 
+    kp = cx->k_sch + 9 * nc;
+
+    switch(cx->n_rnd)
+    {
+    case 14:    round(inv_rnd,  b1, b0, kp + 4 * nc);
+    case 13:    round(inv_rnd,  b0, b1, kp + 3 * nc);
+    case 12:    round(inv_rnd,  b1, b0, kp + 2 * nc);
+    case 11:    round(inv_rnd,  b0, b1, kp +     nc);
+    case 10:    round(inv_rnd,  b1, b0, kp         );             
+                round(inv_rnd,  b0, b1, kp -     nc);
+                round(inv_rnd,  b1, b0, kp - 2 * nc); 
+                round(inv_rnd,  b0, b1, kp - 3 * nc);
+                round(inv_rnd,  b1, b0, kp - 4 * nc); 
+                round(inv_rnd,  b0, b1, kp - 5 * nc);
+                round(inv_rnd,  b1, b0, kp - 6 * nc); 
+                round(inv_rnd,  b0, b1, kp - 7 * nc);
+                round(inv_rnd,  b1, b0, kp - 8 * nc);
+                round(inv_lrnd, b0, b1, kp - 9 * nc);
+    }
+#else
+    {   uint32_t    rnd;
+
+        state_in(b0, in_blk, kp); 
+
+#if (DEC_UNROLL == PARTIAL)
+
+        for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd)
+        {
+            kp -= nc;
+            round(inv_rnd, b1, b0, kp); 
+            kp -= nc;
+            round(inv_rnd, b0, b1, kp); 
+        }
+
+        if(cx->n_rnd & 1) 
+        {
+            l_copy(b1, b0);
+        }
+        else
+        {       
+            kp -= nc;
+            round(inv_rnd,  b1, b0, kp); 
+        }
+#else
+        for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+        {
+            kp -= nc;
+            round(inv_rnd, b1, b0, kp); 
+            l_copy(b0, b1); 
+        }
+#endif
+        kp -= nc;
+        round(inv_lrnd, b0, b1, kp);
+    }
+#endif
+
+    state_out(out_blk, b0);
+    return aes_good;
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/aescrypt.asm b/krb5-1-6/src/lib/crypto/aes/aescrypt.asm
new file mode 100644
index 000000000..35a6818b6
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aescrypt.asm
@@ -0,0 +1,402 @@
+
+; -------------------------------------------------------------------------
+; Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+; All rights reserved.
+;
+; LICENSE TERMS
+;
+; The free distribution and use of this software in both source and binary 
+; form is allowed (with or without changes) provided that:
+;
+;   1. distributions of this source code include the above copyright 
+;      notice, this list of conditions and the following disclaimer;
+;
+;   2. distributions in binary form include the above copyright
+;      notice, this list of conditions and the following disclaimer
+;      in the documentation and/or other associated materials;
+;
+;   3. the copyright holder's name is not used to endorse products 
+;      built using this software without specific written permission.
+;
+; DISCLAIMER
+;
+; This software is provided 'as is' with no explcit or implied warranties
+; in respect of any properties, including, but not limited to, correctness 
+; and fitness for purpose.
+; -------------------------------------------------------------------------
+; Issue Date: 15/01/2002
+
+; An AES (Rijndael) implementation for the Pentium MMX family using the NASM
+; assembler <http://www.web-sites.co.uk/nasm/>. This version only implements
+; the standard AES block length (128 bits, 16 bytes) with the same interface
+; as that used in my C/C++ implementation.   This code does not preserve the
+; eax, ecx or edx registers or the artihmetic status flags. However, the ebx, 
+; esi, edi, and ebp registers are preserved across calls.    Only encryption
+; and decryption are implemented here, the key schedule code being that from
+; compiling aes.c with USE_ASM defined.  This code uses VC++ register saving
+; conentions; if it is used with another compiler, its conventions for using
+; and saving registers will need to be checked.
+
+    section .text use32
+
+; aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+; aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+    global  _aes_enc_blk
+    global  _aes_dec_blk
+    
+    extern  _ft_tab
+    extern  _fl_tab
+    extern  _it_tab
+    extern  _il_tab
+
+;%define USE_MMX   ; include this to use MMX registers for temporary storage
+;%define USE_EMMS    ; include this if you make use of floating point operations
+
+%ifdef  USE_MMX
+%ifdef  USE_EMMS
+%define EMMS_ON
+%endif
+%endif
+
+tlen:   equ  1024   ; length of each of 4 'xor' arrays (256 32-bit words)
+
+; offsets to parameters with one register pushed onto stack
+
+in_blk: equ     8   ; input byte array address parameter
+out_blk:equ    12   ; output byte array address parameter
+ctx:    equ    16   ; AES context structure
+
+; offsets in context structure
+
+ksch:   equ     0   ; encryption key schedule base address
+nrnd:   equ   256   ; number of rounds
+nblk:   equ   260   ; number of rounds
+
+; register mapping for encrypt and decrypt subroutines
+
+%define r0  eax
+%define r1  ebx
+%define r2  ecx
+%define r3  edx
+%define r4  esi
+%define r5  edi
+%define r6  ebp
+
+%define eaxl  al
+%define eaxh  ah
+%define ebxl  bl
+%define ebxh  bh
+%define ecxl  cl
+%define ecxh  ch
+%define edxl  dl
+%define edxh  dh
+
+; This macro takes a 32-bit word representing a column and uses
+; each of its four bytes to index into four tables of 256 32-bit
+; words to obtain values that are then xored into the appropriate
+; output registers r0, r1, r4 or r5.  
+
+; Parameters:
+;   %1  out_state[0]
+;   %2  out_state[1]
+;   %3  out_state[2]
+;   %4  out_state[3]
+;   %5  table base address
+;   %6  input register for the round (destroyed)
+;   %7  scratch register for the round
+
+%macro do_col 7
+
+    movzx   %7,%6l
+    xor     %1,[4*%7+%5]
+    movzx   %7,%6h
+    shr     %6,16
+    xor     %2,[4*%7+%5+tlen]
+    movzx   %7,%6l
+    movzx   %6,%6h
+    xor     %3,[4*%7+%5+2*tlen] 
+    xor     %4,[4*%6+%5+3*tlen]
+
+%endmacro
+
+; initialise output registers from the key schedule
+
+%macro do_fcol 8
+
+    mov     %1,[%8]
+    movzx   %7,%6l
+    mov     %2,[%8+12]
+    xor     %1,[4*%7+%5]
+    mov     %4,[%8+ 4]
+    movzx   %7,%6h
+    shr     %6,16
+    xor     %2,[4*%7+%5+tlen]
+    movzx   %7,%6l
+    movzx   %6,%6h
+    xor     %4,[4*%6+%5+3*tlen]
+    mov     %6,%3
+    mov     %3,[%8+ 8]
+    xor     %3,[4*%7+%5+2*tlen] 
+
+%endmacro
+
+; initialise output registers from the key schedule
+
+%macro do_icol 8
+
+    mov     %1,[%8]
+    movzx   %7,%6l
+    mov     %2,[%8+ 4]
+    xor     %1,[4*%7+%5]
+    mov     %4,[%8+12]
+    movzx   %7,%6h
+    shr     %6,16
+    xor     %2,[4*%7+%5+tlen]
+    movzx   %7,%6l
+    movzx   %6,%6h
+    xor     %4,[4*%6+%5+3*tlen]
+    mov     %6,%3
+    mov     %3,[%8+ 8]
+    xor     %3,[4*%7+%5+2*tlen] 
+
+%endmacro
+
+; These macros implement either MMX or stack based local variables
+
+%ifdef  USE_MMX
+
+%macro  save 2
+    movd    mm%1,%2
+%endmacro
+
+%macro  restore 2
+    movd    %1,mm%2
+%endmacro
+
+%else
+
+%macro  save 2
+    mov     [esp+4*%1],%2
+%endmacro
+
+%macro  restore 2
+    mov     %1,[esp+4*%2]
+%endmacro
+
+%endif
+
+; This macro performs a forward encryption cycle. It is entered with
+; the first previous round column values in r0, r1, r4 and r5 and
+; exits with the final values in the same registers, using the MMX
+; registers mm0-mm1 for temporary storage
+
+%macro fwd_rnd 1-2 _ft_tab
+
+; mov current column values into the MMX registers
+
+    mov     r2,r0
+    save    0,r1
+    save    1,r5
+
+; compute new column values
+
+    do_fcol r0,r5,r4,r1, %2, r2,r3, %1
+    do_col  r4,r1,r0,r5, %2, r2,r3
+    restore r2,0
+    do_col  r1,r0,r5,r4, %2, r2,r3
+    restore r2,1
+    do_col  r5,r4,r1,r0, %2, r2,r3
+
+%endmacro
+
+; This macro performs an inverse encryption cycle. It is entered with
+; the first previous round column values in r0, r1, r4 and r5 and
+; exits with the final values in the same registers, using the MMX
+; registers mm0-mm1 for temporary storage
+
+%macro inv_rnd 1-2 _it_tab
+
+; mov current column values into the MMX registers
+
+    mov     r2,r0
+    save    0,r1
+    save    1,r5
+
+; compute new column values
+
+    do_icol r0,r1,r4,r5, %2, r2,r3, %1
+    do_col  r4,r5,r0,r1, %2, r2,r3
+    restore r2,0
+    do_col  r1,r4,r5,r0, %2, r2,r3
+    restore r2,1
+    do_col  r5,r0,r1,r4, %2, r2,r3
+
+%endmacro
+
+; AES (Rijndael) Encryption Subroutine
+
+_aes_enc_blk:
+    push    ebp
+    mov     ebp,[esp+ctx]       ; pointer to context
+    xor     eax,eax
+    test    [ebp+nblk],byte 1
+    je      .0
+    cmp     eax,[ebp+nrnd]      ; encryption/decryption flags
+    jne     short .1
+.0: pop     ebp
+    ret            
+
+; CAUTION: the order and the values used in these assigns 
+; rely on the register mappings
+
+.1: push    ebx
+    mov     r2,[esp+in_blk+4]
+    push    esi
+    mov     r3,[ebp+nrnd]   ; number of rounds
+    push    edi
+    lea     r6,[ebp+ksch]   ; key pointer
+
+; input four columns and xor in first round key
+
+    mov     r0,[r2]
+    mov     r1,[r2+4]
+    mov     r4,[r2+8]
+    mov     r5,[r2+12]
+    xor     r0,[r6]
+    xor     r1,[r6+4]
+    xor     r4,[r6+8]
+    xor     r5,[r6+12]
+
+%ifndef USE_MMX
+    sub     esp,8           ; space for register saves on stack
+%endif
+    add     r6,16           ; increment to next round key   
+    sub     r3,10          
+    je      .4              ; 10 rounds for 128-bit key
+    add     r6,32  
+    sub     r3,2
+    je      .3              ; 12 rounds for 128-bit key
+    add     r6,32  
+
+.2: fwd_rnd r6-64           ; 14 rounds for 128-bit key
+    fwd_rnd r6-48  
+.3: fwd_rnd r6-32           ; 12 rounds for 128-bit key
+    fwd_rnd r6-16  
+.4: fwd_rnd r6              ; 10 rounds for 128-bit key
+    fwd_rnd r6+ 16 
+    fwd_rnd r6+ 32
+    fwd_rnd r6+ 48
+    fwd_rnd r6+ 64
+    fwd_rnd r6+ 80
+    fwd_rnd r6+ 96
+    fwd_rnd r6+112
+    fwd_rnd r6+128
+    fwd_rnd r6+144,_fl_tab  ; last round uses a different table
+
+; move final values to the output array.  CAUTION: the 
+; order of these assigns rely on the register mappings
+
+%ifndef USE_MMX
+    add     esp,8
+%endif
+    mov     r6,[esp+out_blk+12]
+    mov     [r6+12],r5
+    pop     edi
+    mov     [r6+8],r4
+    pop     esi
+    mov     [r6+4],r1
+    pop     ebx
+    mov     [r6],r0
+    pop     ebp
+    mov     eax,1
+%ifdef  EMMS_ON
+    emms
+%endif
+    ret
+
+; AES (Rijndael) Decryption Subroutine
+
+_aes_dec_blk:
+    push    ebp
+    mov     ebp,[esp+ctx]       ; pointer to context
+    xor     eax,eax
+    test    [ebp+nblk],byte 2
+    je      .0
+    cmp     eax,[ebp+nrnd]      ; encryption/decryption flags
+    jne     short .1
+.0: pop     ebp
+    ret            
+
+; CAUTION: the order and the values used in these assigns 
+; rely on the register mappings
+
+.1: push    ebx
+    mov     r2,[esp+in_blk+4]
+    push    esi
+    mov     r3,[ebp+nrnd]   ; number of rounds
+    push    edi
+    lea     r6,[ebp+ksch]   ; key pointer
+    mov     r0,r3
+    shl     r0,4
+    add     r6,r0
+    
+; input four columns and xor in first round key
+
+    mov     r0,[r2]
+    mov     r1,[r2+4]
+    mov     r4,[r2+8]
+    mov     r5,[r2+12]
+    xor     r0,[r6]
+    xor     r1,[r6+4]
+    xor     r4,[r6+8]
+    xor     r5,[r6+12]
+
+%ifndef USE_MMX
+    sub     esp,8           ; space for register saves on stack
+%endif
+    sub     r6,16           ; increment to next round key   
+    sub     r3,10          
+    je      .4              ; 10 rounds for 128-bit key
+    sub     r6,32  
+    sub     r3,2
+    je      .3              ; 12 rounds for 128-bit key
+    sub     r6,32  
+
+.2: inv_rnd r6+64           ; 14 rounds for 128-bit key 
+    inv_rnd r6+48  
+.3: inv_rnd r6+32           ; 12 rounds for 128-bit key
+    inv_rnd r6+16  
+.4: inv_rnd r6              ; 10 rounds for 128-bit key
+    inv_rnd r6- 16 
+    inv_rnd r6- 32
+    inv_rnd r6- 48
+    inv_rnd r6- 64
+    inv_rnd r6- 80
+    inv_rnd r6- 96
+    inv_rnd r6-112
+    inv_rnd r6-128
+    inv_rnd r6-144,_il_tab  ; last round uses a different table
+
+; move final values to the output array.  CAUTION: the 
+; order of these assigns rely on the register mappings
+
+%ifndef USE_MMX
+    add     esp,8
+%endif
+    mov     r6,[esp+out_blk+12]
+    mov     [r6+12],r5
+    pop     edi
+    mov     [r6+8],r4
+    pop     esi
+    mov     [r6+4],r1
+    pop     ebx
+    mov     [r6],r0
+    pop     ebp
+    mov     eax,1
+%ifdef  EMMS_ON
+    emms
+%endif
+    ret
+
+    end
diff --git a/krb5-1-6/src/lib/crypto/aes/aescrypt.c b/krb5-1-6/src/lib/crypto/aes/aescrypt.c
new file mode 100644
index 000000000..9db66e284
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aescrypt.c
@@ -0,0 +1,421 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing encryption and decryption
+ for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It  
+ can optionally be replaced by code written in assembler using NASM.
+*/
+
+#include "aesopt.h"
+
+#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7)
+#error An illegal block size has been specified.
+#endif  
+
+#define unused  77  /* Sunset Strip */
+
+#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c]
+#define so(y,x,c)   word_out(y + 4 * c, s(x,c))
+
+#if BLOCK_SIZE == 16
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[4],y[4]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
+ /* 
+   the following defines prevent the compiler requiring the declaration
+   of generated but unused variables in the fwd_var and inv_var macros
+ */
+#define b04 unused
+#define b05 unused
+#define b06 unused
+#define b07 unused
+#define b14 unused
+#define b15 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
+
+#elif BLOCK_SIZE == 24
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[6],y[6]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5, \
+                        y##0,y##1,y##2,y##3,y##4,y##5
+#define b06 unused
+#define b07 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
+                        s(y,4) = s(x,4); s(y,5) = s(x,5);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
+                        si(y,x,k,3); si(y,x,k,4); si(y,x,k,5)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); \
+                        so(y,x,3); so(y,x,4); so(y,x,5)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
+                        rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5)
+#else
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[8],y[8]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \
+                        y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
+                        s(y,4) = s(x,4); s(y,5) = s(x,5); \
+                        s(y,6) = s(x,6); s(y,7) = s(x,7);
+
+#if BLOCK_SIZE == 32
+
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \
+                        si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \
+                        so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \
+                        rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7)
+#else
+
+#define state_in(y,x,k) \
+switch(nc) \
+{   case 8: si(y,x,k,7); si(y,x,k,6); \
+    case 6: si(y,x,k,5); si(y,x,k,4); \
+    case 4: si(y,x,k,3); si(y,x,k,2); \
+            si(y,x,k,1); si(y,x,k,0); \
+}
+
+#define state_out(y,x) \
+switch(nc) \
+{   case 8: so(y,x,7); so(y,x,6); \
+    case 6: so(y,x,5); so(y,x,4); \
+    case 4: so(y,x,3); so(y,x,2); \
+            so(y,x,1); so(y,x,0); \
+}
+
+#if defined(FAST_VARIABLE)
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
+            rm(y,x,k,5); rm(y,x,k,4); \
+            rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+    case 6: rm(y,x,k,5); rm(y,x,k,4); \
+            rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+    case 4: rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+}
+#else
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
+    case 6: rm(y,x,k,5); rm(y,x,k,4); \
+    case 4: rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+}
+
+#endif
+
+#endif
+#endif
+
+#if defined(ENCRYPTION)
+
+/* I am grateful to Frank Yellin for the following construction
+   (and that for decryption) which, given the column (c) of the 
+   output state variable, gives the input state variables which 
+   are needed in its computation for each row (r) of the state.
+
+   For the fixed block size options, compilers should be able to 
+   reduce this complex expression (and the equivalent one for 
+   decryption) to a static variable reference at compile time. 
+   But for variable block size code, there will be some limbs on
+   which conditional clauses will be returned.
+*/
+
+/* y = output word, x = input word, r = row, c = column for r = 0, 
+   1, 2 and 3 = column accessed for row r.
+*/
+
+#define fwd_var(x,r,c) \
+ ( r==0 ?           \
+    ( c==0 ? s(x,0) \
+    : c==1 ? s(x,1) \
+    : c==2 ? s(x,2) \
+    : c==3 ? s(x,3) \
+    : c==4 ? s(x,4) \
+    : c==5 ? s(x,5) \
+    : c==6 ? s(x,6) \
+    : s(x,7))       \
+ : r==1 ?           \
+    ( c==0 ? s(x,1) \
+    : c==1 ? s(x,2) \
+    : c==2 ? s(x,3) \
+    : c==3 ? nc==4 ? s(x,0) : s(x,4) \
+    : c==4 ? s(x,5) \
+    : c==5 ? nc==8 ? s(x,6) : s(x,0) \
+    : c==6 ? s(x,7) \
+    : s(x,0))       \
+ : r==2 ?           \
+    ( c==0 ? nc==8 ? s(x,3) : s(x,2) \
+    : c==1 ? nc==8 ? s(x,4) : s(x,3) \
+    : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
+    : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
+    : c==4 ? nc==8 ? s(x,7) : s(x,0) \
+    : c==5 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==6 ? s(x,1) \
+    : s(x,2))       \
+ :                  \
+    ( c==0 ? nc==8 ? s(x,4) : s(x,3) \
+    : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
+    : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
+    : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \
+    : c==4 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==6 ? s(x,2) \
+    : s(x,3)))
+
+#if defined(FT4_SET)
+#undef  dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c)
+#elif defined(FT1_SET)
+#undef  dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c)
+#else
+#define fwd_rnd(y,x,k,c)    s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c]
+#endif
+
+#if defined(FL4_SET)
+#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c)
+#elif defined(FL1_SET)
+#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c)
+#else
+#define fwd_lrnd(y,x,k,c)   s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{   uint32_t        locals(b0, b1);
+    const uint32_t  *kp = cx->k_sch;
+    dec_fmvars  /* declare variables for fwd_mcol() if needed */
+
+    if(!(cx->n_blk & 1)) return aes_bad;
+
+    state_in(b0, in_blk, kp); 
+
+#if (ENC_UNROLL == FULL)
+
+    kp += (cx->n_rnd - 9) * nc;
+
+    switch(cx->n_rnd)
+    {
+    case 14:    round(fwd_rnd,  b1, b0, kp - 4 * nc); 
+                round(fwd_rnd,  b0, b1, kp - 3 * nc);
+    case 12:    round(fwd_rnd,  b1, b0, kp - 2 * nc); 
+                round(fwd_rnd,  b0, b1, kp -     nc);
+    case 10:    round(fwd_rnd,  b1, b0, kp         );             
+                round(fwd_rnd,  b0, b1, kp +     nc);
+                round(fwd_rnd,  b1, b0, kp + 2 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 3 * nc);
+                round(fwd_rnd,  b1, b0, kp + 4 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 5 * nc);
+                round(fwd_rnd,  b1, b0, kp + 6 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 7 * nc);
+                round(fwd_rnd,  b1, b0, kp + 8 * nc);
+                round(fwd_lrnd, b0, b1, kp + 9 * nc);
+    }
+#else
+    
+#if (ENC_UNROLL == PARTIAL)
+    {   uint32_t    rnd;
+        for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd)
+        {
+            kp += nc;
+            round(fwd_rnd, b1, b0, kp); 
+            kp += nc;
+            round(fwd_rnd, b0, b1, kp); 
+        }
+        kp += nc;
+        round(fwd_rnd,  b1, b0, kp);
+#else
+    {   uint32_t    rnd, *p0 = b0, *p1 = b1, *pt;
+        for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+        {
+            kp += nc;
+            round(fwd_rnd, p1, p0, kp); 
+            pt = p0, p0 = p1, p1 = pt;
+        }
+#endif
+        kp += nc;
+        round(fwd_lrnd, b0, b1, kp);
+    }
+#endif
+
+    state_out(out_blk, b0);
+    return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION)
+
+#define inv_var(x,r,c) \
+ ( r==0 ?           \
+    ( c==0 ? s(x,0) \
+    : c==1 ? s(x,1) \
+    : c==2 ? s(x,2) \
+    : c==3 ? s(x,3) \
+    : c==4 ? s(x,4) \
+    : c==5 ? s(x,5) \
+    : c==6 ? s(x,6) \
+    : s(x,7))       \
+ : r==1 ?           \
+    ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \
+    : c==1 ? s(x,0) \
+    : c==2 ? s(x,1) \
+    : c==3 ? s(x,2) \
+    : c==4 ? s(x,3) \
+    : c==5 ? s(x,4) \
+    : c==6 ? s(x,5) \
+    : s(x,6))       \
+ : r==2 ?           \
+    ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
+    : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
+    : c==2 ? nc==8 ? s(x,7) : s(x,0) \
+    : c==3 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==4 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==5 ? nc==8 ? s(x,2) : s(x,3) \
+    : c==6 ? s(x,3) \
+    : s(x,4))       \
+ :                  \
+    ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \
+    : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
+    : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
+    : c==3 ? nc==8 ? s(x,7) : s(x,0) \
+    : c==4 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==6 ? s(x,2) \
+    : s(x,3)))
+
+#if defined(IT4_SET)
+#undef  dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c)
+#elif defined(IT1_SET)
+#undef  dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c)
+#else
+#define inv_rnd(y,x,k,c)    s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c])
+#endif
+
+#if defined(IL4_SET)
+#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c)
+#elif defined(IL1_SET)
+#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c)
+#else
+#define inv_lrnd(y,x,k,c)   s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{   uint32_t        locals(b0, b1);
+    const uint32_t  *kp = cx->k_sch + nc * cx->n_rnd;
+    dec_imvars  /* declare variables for inv_mcol() if needed */
+
+    if(!(cx->n_blk & 2)) return aes_bad;
+
+    state_in(b0, in_blk, kp);
+
+#if (DEC_UNROLL == FULL)
+
+    kp = cx->k_sch + 9 * nc;
+    switch(cx->n_rnd)
+    {
+    case 14:    round(inv_rnd,  b1, b0, kp + 4 * nc);
+                round(inv_rnd,  b0, b1, kp + 3 * nc);
+    case 12:    round(inv_rnd,  b1, b0, kp + 2 * nc);
+                round(inv_rnd,  b0, b1, kp + nc    );
+    case 10:    round(inv_rnd,  b1, b0, kp         );             
+                round(inv_rnd,  b0, b1, kp -     nc);
+                round(inv_rnd,  b1, b0, kp - 2 * nc); 
+                round(inv_rnd,  b0, b1, kp - 3 * nc);
+                round(inv_rnd,  b1, b0, kp - 4 * nc); 
+                round(inv_rnd,  b0, b1, kp - 5 * nc);
+                round(inv_rnd,  b1, b0, kp - 6 * nc); 
+                round(inv_rnd,  b0, b1, kp - 7 * nc);
+                round(inv_rnd,  b1, b0, kp - 8 * nc);
+                round(inv_lrnd, b0, b1, kp - 9 * nc);
+    }
+#else
+    
+#if (DEC_UNROLL == PARTIAL)
+    {   uint32_t    rnd;
+        for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd)
+        {
+            kp -= nc; 
+            round(inv_rnd, b1, b0, kp); 
+            kp -= nc; 
+            round(inv_rnd, b0, b1, kp); 
+        }
+        kp -= nc;
+        round(inv_rnd, b1, b0, kp);
+#else
+    {   uint32_t    rnd, *p0 = b0, *p1 = b1, *pt;
+        for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+        {
+            kp -= nc;
+            round(inv_rnd, p1, p0, kp); 
+            pt = p0, p0 = p1, p1 = pt;
+        }
+#endif
+        kp -= nc;
+        round(inv_lrnd, b0, b1, kp);
+    }
+#endif
+
+    state_out(out_blk, b0);
+    return aes_good;
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/aeskey.c b/krb5-1-6/src/lib/crypto/aes/aeskey.c
new file mode 100644
index 000000000..970a26fca
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aeskey.c
@@ -0,0 +1,363 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing the key schedule for AES 
+ (Rijndael) for block and key sizes of 16, 24, and 32 bytes.
+*/
+
+#include "aesopt.h"
+
+#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7)
+#error An illegal block size has been specified.
+#endif  
+
+/* Subroutine to set the block size (if variable) in bytes, legal
+   values being 16, 24 and 32. 
+*/
+
+#if !defined(BLOCK_SIZE) && defined(SET_BLOCK_LENGTH)
+
+aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1])
+{
+#if !defined(FIXED_TABLES)
+    if(!tab_init) gen_tabs();
+#endif
+
+    if((blen & 7) || blen < 16 || blen > 32) 
+    {     
+        cx->n_blk = 0; return aes_bad;
+    }
+
+    cx->n_blk = blen;
+    return aes_good;
+}
+
+#endif
+
+/* Initialise the key schedule from the user supplied key. The key
+   length is now specified in bytes - 16, 24 or 32 as appropriate.
+   This corresponds to bit lengths of 128, 192 and 256 bits, and
+   to Nk values of 4, 6 and 8 respectively.
+
+   The following macros implement a single cycle in the key 
+   schedule generation process. The number of cycles needed 
+   for each cx->n_col and nk value is:
+ 
+    nk =             4  5  6  7  8
+    ------------------------------
+    cx->n_col = 4   10  9  8  7  7
+    cx->n_col = 5   14 11 10  9  9
+    cx->n_col = 6   19 15 12 11 11
+    cx->n_col = 7   21 19 16 13 14
+    cx->n_col = 8   29 23 19 17 14
+*/
+
+#if defined(ENCRYPTION_KEY_SCHEDULE)
+
+#define ke4(k,i) \
+{   k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
+    k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
+}
+#define kel4(k,i) \
+{   k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
+    k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
+}
+
+#define ke6(k,i) \
+{   k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
+    k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
+    k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \
+}
+#define kel6(k,i) \
+{   k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
+    k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
+}
+
+#define ke8(k,i) \
+{   k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
+    k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
+    k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \
+    k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \
+}
+#define kel8(k,i) \
+{   k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
+    k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
+}
+
+aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{   uint32_t    ss[8]; 
+
+#if !defined(FIXED_TABLES)
+    if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+    if(!cx->n_blk) cx->n_blk = 16;
+#else
+    cx->n_blk = BLOCK_SIZE;
+#endif
+    
+    cx->n_blk = (cx->n_blk & ~3U) | 1;
+
+    cx->k_sch[0] = ss[0] = word_in(in_key     );
+    cx->k_sch[1] = ss[1] = word_in(in_key +  4);
+    cx->k_sch[2] = ss[2] = word_in(in_key +  8);
+    cx->k_sch[3] = ss[3] = word_in(in_key + 12);
+
+#if (BLOCK_SIZE == 16) && (ENC_UNROLL != NONE)
+
+    switch(klen)
+    {
+    case 16:    ke4(cx->k_sch, 0); ke4(cx->k_sch, 1); 
+                ke4(cx->k_sch, 2); ke4(cx->k_sch, 3);
+                ke4(cx->k_sch, 4); ke4(cx->k_sch, 5); 
+                ke4(cx->k_sch, 6); ke4(cx->k_sch, 7);
+                ke4(cx->k_sch, 8); kel4(cx->k_sch, 9); 
+                cx->n_rnd = 10; break;
+    case 24:    cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+                cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+                ke6(cx->k_sch, 0); ke6(cx->k_sch, 1); 
+                ke6(cx->k_sch, 2); ke6(cx->k_sch, 3);
+                ke6(cx->k_sch, 4); ke6(cx->k_sch, 5); 
+                ke6(cx->k_sch, 6); kel6(cx->k_sch, 7); 
+                cx->n_rnd = 12; break;
+    case 32:    cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+                cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+                cx->k_sch[6] = ss[6] = word_in(in_key + 24);
+                cx->k_sch[7] = ss[7] = word_in(in_key + 28);
+                ke8(cx->k_sch, 0); ke8(cx->k_sch, 1); 
+                ke8(cx->k_sch, 2); ke8(cx->k_sch, 3);
+                ke8(cx->k_sch, 4); ke8(cx->k_sch, 5); 
+                kel8(cx->k_sch, 6); 
+                cx->n_rnd = 14; break;
+    default:    cx->n_rnd = 0; return aes_bad; 
+    }
+#else
+    {   uint32_t i, l;
+        cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+        l = (nc * cx->n_rnd + nc - 1) / (klen >> 2);
+
+        switch(klen)
+        {
+        case 16:    for(i = 0; i < l; ++i)
+                        ke4(cx->k_sch, i);
+                    break;
+        case 24:    cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+                    cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+                    for(i = 0; i < l; ++i)
+                        ke6(cx->k_sch, i);
+                    break;
+        case 32:    cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+                    cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+                    cx->k_sch[6] = ss[6] = word_in(in_key + 24);
+                    cx->k_sch[7] = ss[7] = word_in(in_key + 28);
+                    for(i = 0; i < l; ++i)
+                        ke8(cx->k_sch,  i);
+                    break;
+        default:    cx->n_rnd = 0; return aes_bad; 
+        }
+    }
+#endif
+
+    return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION_KEY_SCHEDULE)
+
+#if (DEC_ROUND != NO_TABLES)
+#define d_vars  dec_imvars
+#define ff(x)   inv_mcol(x)
+#else
+#define ff(x)   (x)
+#define d_vars
+#endif
+
+#if 1
+#define kdf4(k,i) \
+{   ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \
+    ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \
+    ss[4] ^= k[4*(i)];   k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \
+    ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \
+}
+#define kd4(k,i) \
+{   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
+    k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \
+    k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \
+}
+#define kdl4(k,i) \
+{   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \
+    k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \
+    k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \
+}
+#else
+#define kdf4(k,i) \
+{   ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \
+    ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \
+}
+#define kd4(k,i) \
+{   ss[4] = ls_box(ss[3],3) ^ rcon_tab[i]; \
+    ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \
+    ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \
+    ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \
+    ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \
+}
+#define kdl4(k,i) \
+{   ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \
+    ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \
+}
+#endif
+
+#define kdf6(k,i) \
+{   ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \
+    ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \
+    ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \
+}
+#define kd6(k,i) \
+{   ss[6] = ls_box(ss[5],3) ^ rcon_tab[i]; \
+    ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \
+    ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \
+    ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \
+    ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \
+    ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \
+    ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \
+}
+#define kdl6(k,i) \
+{   ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \
+    ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \
+}
+
+#define kdf8(k,i) \
+{   ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \
+    ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \
+    ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \
+    ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \
+}
+#define kd8(k,i) \
+{   uint32_t g = ls_box(ss[7],3) ^ rcon_tab[i]; \
+    ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \
+    ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \
+    ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \
+    ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \
+    g = ls_box(ss[3],0); \
+    ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \
+    ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \
+    ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \
+    ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \
+}
+#define kdl8(k,i) \
+{   ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \
+    ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \
+}
+
+aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{   uint32_t    ss[8]; 
+    d_vars
+
+#if !defined(FIXED_TABLES)
+    if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+    if(!cx->n_blk) cx->n_blk = 16;
+#else
+    cx->n_blk = BLOCK_SIZE;
+#endif
+
+    cx->n_blk = (cx->n_blk & ~3U) | 2;
+
+    cx->k_sch[0] = ss[0] = word_in(in_key     );
+    cx->k_sch[1] = ss[1] = word_in(in_key +  4);
+    cx->k_sch[2] = ss[2] = word_in(in_key +  8);
+    cx->k_sch[3] = ss[3] = word_in(in_key + 12);
+
+#if (BLOCK_SIZE == 16) && (DEC_UNROLL != NONE)
+
+    switch(klen)
+    {
+    case 16:    kdf4(cx->k_sch, 0); kd4(cx->k_sch, 1); 
+                kd4(cx->k_sch, 2); kd4(cx->k_sch, 3);
+                kd4(cx->k_sch, 4); kd4(cx->k_sch, 5); 
+                kd4(cx->k_sch, 6); kd4(cx->k_sch, 7);
+                kd4(cx->k_sch, 8); kdl4(cx->k_sch, 9); 
+                cx->n_rnd = 10; break;
+    case 24:    cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16));
+                cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20));
+                kdf6(cx->k_sch, 0); kd6(cx->k_sch, 1); 
+                kd6(cx->k_sch, 2); kd6(cx->k_sch, 3);
+                kd6(cx->k_sch, 4); kd6(cx->k_sch, 5); 
+                kd6(cx->k_sch, 6); kdl6(cx->k_sch, 7); 
+                cx->n_rnd = 12; break;
+    case 32:    cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16));
+                cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20));
+                cx->k_sch[6] = ff(ss[6] = word_in(in_key + 24));
+                cx->k_sch[7] = ff(ss[7] = word_in(in_key + 28));
+                kdf8(cx->k_sch, 0); kd8(cx->k_sch, 1); 
+                kd8(cx->k_sch, 2); kd8(cx->k_sch, 3);
+                kd8(cx->k_sch, 4); kd8(cx->k_sch, 5); 
+                kdl8(cx->k_sch, 6); 
+                cx->n_rnd = 14; break;
+    default:    cx->n_rnd = 0; return aes_bad; 
+    }
+#else
+    {   uint32_t i, l;
+        cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+        l = (nc * cx->n_rnd + nc - 1) / (klen >> 2);
+
+        switch(klen)
+        {
+        case 16: 
+                    for(i = 0; i < l; ++i)
+                        ke4(cx->k_sch, i);
+                    break;
+        case 24:    cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+                    cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+                    for(i = 0; i < l; ++i)
+                        ke6(cx->k_sch, i);
+                    break;
+        case 32:    cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+                    cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+                    cx->k_sch[6] = ss[6] = word_in(in_key + 24);
+                    cx->k_sch[7] = ss[7] = word_in(in_key + 28);
+                    for(i = 0; i < l; ++i)
+                        ke8(cx->k_sch,  i);
+                    break;
+        default:    cx->n_rnd = 0; return aes_bad; 
+        }
+#if (DEC_ROUND != NO_TABLES)
+        for(i = nc; i < nc * cx->n_rnd; ++i)
+            cx->k_sch[i] = inv_mcol(cx->k_sch[i]);
+#endif
+    }
+#endif
+
+    return aes_good;
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/aeskeypp.c b/krb5-1-6/src/lib/crypto/aes/aeskeypp.c
new file mode 100644
index 000000000..89fd9006d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aeskeypp.c
@@ -0,0 +1,399 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing the key schedule for AES 
+ (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes.
+*/
+
+#include "aesopt.h"
+
+/* Subroutine to set the block size (if variable) in bytes, legal
+   values being 16, 24 and 32. 
+*/
+
+#if !defined(BLOCK_SIZE) && defined(SET_BLOCK_LENGTH)
+
+/* Subroutine to set the block size (if variable) in bytes, legal
+   values being 16, 24 and 32. 
+*/
+
+aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1])
+{
+#if !defined(FIXED_TABLES)
+    if(!tab_init) gen_tabs();
+#endif
+
+    if((blen & 3) || blen < 16 || blen > 32) 
+    {     
+        cx->n_blk = 0; return aes_bad;
+    }
+
+    cx->n_blk = blen;
+    return aes_good;
+}
+
+#endif
+
+/* Initialise the key schedule from the user supplied key. The key
+   length is now specified in bytes - 16, 24 or 32 as appropriate.
+   This corresponds to bit lengths of 128, 192 and 256 bits, and
+   to Nk values of 4, 6 and 8 respectively.
+
+   The following macros implement a single cycle in the key 
+   schedule generation process. The number of cycles needed 
+   for each cx->n_blk and nk value is:
+ 
+    nk =             4  5  6  7  8
+    ------------------------------
+    cx->n_blk = 4   10  9  8  7  7
+    cx->n_blk = 5   14 11 10  9  9
+    cx->n_blk = 6   19 15 12 11 11
+    cx->n_blk = 7   21 19 16 13 14
+    cx->n_blk = 8   29 23 19 17 14
+*/
+
+/* Initialise the key schedule from the user supplied key. The key
+   length is now specified in bytes - 16, 20, 24, 28 or 32 as 
+   appropriate. This corresponds to bit lengths of 128, 160, 192,
+   224 and 256 bits, and to Nk values of 4, 5, 6, 7 & 8 respectively.
+ */
+
+#define mx(t,f) (*t++ = inv_mcol(*f),f++)
+#define cp(t,f) *t++ = *f++
+
+#if   BLOCK_SIZE == 16
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s)
+#elif BLOCK_SIZE == 20
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+                    cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+                    mx(d,s)
+#elif BLOCK_SIZE == 24
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+                    cp(d,s); cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+                    mx(d,s); mx(d,s)
+#elif BLOCK_SIZE == 28
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+                    cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+                    mx(d,s); mx(d,s); mx(d,s)
+#elif BLOCK_SIZE == 32
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+                    cp(d,s); cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+                    mx(d,s); mx(d,s); mx(d,s); mx(d,s)
+#else
+
+#define cpy(d,s) \
+switch(nc) \
+{   case 8: cp(d,s); \
+    case 7: cp(d,s); \
+    case 6: cp(d,s); \
+    case 5: cp(d,s); \
+    case 4: cp(d,s); cp(d,s); \
+            cp(d,s); cp(d,s); \
+}
+
+#define mix(d,s) \
+switch(nc) \
+{   case 8: mx(d,s); \
+    case 7: mx(d,s); \
+    case 6: mx(d,s); \
+    case 5: mx(d,s); \
+    case 4: mx(d,s); mx(d,s); \
+            mx(d,s); mx(d,s); \
+}
+
+#endif
+
+/*  The following macros implement a single cycle in the key 
+    schedule generation process. The number of cycles needed 
+    for each cx->n_blk and nk value is:
+ 
+    nk =      4  5  6  7  8
+    -----------------------
+    cx->n_blk = 4   10  9  8  7  7
+    cx->n_blk = 5   14 11 10  9  9
+    cx->n_blk = 6   19 15 12 11 11
+    cx->n_blk = 7   21 19 16 13 14
+    cx->n_blk = 8   29 23 19 17 14
+*/
+
+#define ks4(i) \
+{   p ^= ls_box(s,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \
+    cx->k_sch[4*(i)+4] = p; \
+    cx->k_sch[4*(i)+5] = q; \
+    cx->k_sch[4*(i)+6] = r; \
+    cx->k_sch[4*(i)+7] = s; \
+}
+
+#define ks5(i) \
+{   p ^= ls_box(t,3) ^ rcon_tab[i]; q ^= p; \
+    r ^= q; s ^= r; t ^= s; \
+    cx->k_sch[5*(i)+ 5] = p; \
+    cx->k_sch[5*(i)+ 6] = q; \
+    cx->k_sch[5*(i)+ 7] = r; \
+    cx->k_sch[5*(i)+ 8] = s; \
+    cx->k_sch[5*(i)+ 9] = t; \
+}
+
+#define ks6(i) \
+{   p ^= ls_box(u,3) ^ rcon_tab[i]; q ^= p; \
+    r ^= q; s ^= r; t ^= s; u ^= t; \
+    cx->k_sch[6*(i)+ 6] = p; \
+    cx->k_sch[6*(i)+ 7] = q; \
+    cx->k_sch[6*(i)+ 8] = r; \
+    cx->k_sch[6*(i)+ 9] = s; \
+    cx->k_sch[6*(i)+10] = t; \
+    cx->k_sch[6*(i)+11] = u; \
+}
+
+#define ks7(i) \
+{   p ^= ls_box(v,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \
+    t ^= ls_box(s,0); u ^= t; v ^= u; \
+    cx->k_sch[7*(i)+ 7] = p; \
+    cx->k_sch[7*(i)+ 8] = q; \
+    cx->k_sch[7*(i)+ 9] = r; \
+    cx->k_sch[7*(i)+10] = s; \
+    cx->k_sch[7*(i)+11] = t; \
+    cx->k_sch[7*(i)+12] = u; \
+    cx->k_sch[7*(i)+13] = v; \
+}
+
+#define ks8(i) \
+{   p ^= ls_box(w,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \
+    t ^= ls_box(s,0); u ^= t; v ^= u; w ^= v; \
+    cx->k_sch[8*(i)+ 8] = p; \
+    cx->k_sch[8*(i)+ 9] = q; \
+    cx->k_sch[8*(i)+10] = r; \
+    cx->k_sch[8*(i)+11] = s; \
+    cx->k_sch[8*(i)+12] = t; \
+    cx->k_sch[8*(i)+13] = u; \
+    cx->k_sch[8*(i)+14] = v; \
+    cx->k_sch[8*(i)+15] = w; \
+}
+
+#if defined(ENCRYPTION_KEY_SCHEDULE)
+
+aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{   uint32_t    i,p,q,r,s,t,u,v,w;
+
+#if !defined(FIXED_TABLES)
+    if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+    if(!cx->n_blk) cx->n_blk = 16;
+#else
+    cx->n_blk = BLOCK_SIZE;
+#endif
+
+    cx->n_blk = (cx->n_blk & ~3) | 1;
+    cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+
+    cx->k_sch[0] = p = word_in(in_key     );
+    cx->k_sch[1] = q = word_in(in_key +  4);
+    cx->k_sch[2] = r = word_in(in_key +  8);
+    cx->k_sch[3] = s = word_in(in_key + 12);
+
+#if BLOCK_SIZE == 16 && defined(UNROLL)
+
+    switch(klen >> 2)
+    {
+    case 4: ks4(0); ks4(1); ks4(2); ks4(3);
+            ks4(4); ks4(5); ks4(6); ks4(7);
+            ks4(8); ks4(9); 
+            cx->n_rnd = 10; break;
+    case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+            ks5(0); ks5(1); ks5(2); ks5(3);
+            ks5(4); ks5(5); ks5(6); ks5(7); 
+            ks5(8);  
+            cx->n_rnd = 11; break;
+    case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+            cx->k_sch[5] = u = word_in(in_key + 20);
+            ks6(0); ks6(1); ks6(2); ks6(3);
+            ks6(4); ks6(5); ks6(6); ks6(7); 
+            cx->n_rnd = 12; break;
+    case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+            cx->k_sch[5] = u = word_in(in_key + 20);
+            cx->k_sch[6] = v = word_in(in_key + 24);
+            ks7(0); ks7(1); ks7(2); ks7(3);
+            ks7(4); ks7(5); ks7(6); 
+            cx->n_rnd = 13; break;
+    case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+            cx->k_sch[5] = u = word_in(in_key + 20);
+            cx->k_sch[6] = v = word_in(in_key + 24);
+            cx->k_sch[7] = w = word_in(in_key + 28);
+            ks8(0); ks8(1); ks8(2); ks8(3);
+            ks8(4); ks8(5); ks8(6); 
+            cx->n_rnd = 14; break;
+    default:cx->n_rnd = 0; return aes_bad;
+    }
+#else
+    cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+    {
+        uint32_t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2);
+        switch(klen >> 2)
+        {
+        case 4: for(i = 0; i < l; ++i)
+                    ks4(i);
+                break;
+        case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+                for(i = 0; i < l; ++i)
+                    ks5(i);
+                break;
+        case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+                cx->k_sch[5] = u = word_in(in_key + 20);
+                for(i = 0; i < l; ++i)
+                    ks6(i);
+                break;
+        case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+                cx->k_sch[5] = u = word_in(in_key + 20);
+                cx->k_sch[6] = v = word_in(in_key + 24);
+                for(i = 0; i < l; ++i)
+                    ks7(i);
+                break;
+        case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+                cx->k_sch[5] = u = word_in(in_key + 20);
+                cx->k_sch[6] = v = word_in(in_key + 24);
+                cx->k_sch[7] = w = word_in(in_key + 28);
+                for(i = 0; i < l; ++i)
+                    ks8(i);
+                break;
+        }
+    }
+#endif
+
+    return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION_KEY_SCHEDULE)
+
+aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{   uint32_t    i,p,q,r,s,t,u,v,w;
+    dec_imvars
+
+#if !defined(FIXED_TABLES)
+    if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+    if(!cx->n_blk) cx->n_blk = 16;
+#else
+    cx->n_blk = BLOCK_SIZE;
+#endif
+
+    cx->n_blk = (cx->n_blk & ~3) | 2;
+    cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+
+    cx->k_sch[0] = p = word_in(in_key     );
+    cx->k_sch[1] = q = word_in(in_key +  4);
+    cx->k_sch[2] = r = word_in(in_key +  8);
+    cx->k_sch[3] = s = word_in(in_key + 12);
+
+#if BLOCK_SIZE == 16 && defined(UNROLL)
+
+    switch(klen >> 2)
+    {
+    case 4: ks4(0); ks4(1); ks4(2); ks4(3);
+            ks4(4); ks4(5); ks4(6); ks4(7);
+            ks4(8); ks4(9); 
+            cx->n_rnd = 10; break;
+    case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+            ks5(0); ks5(1); ks5(2); ks5(3);
+            ks5(4); ks5(5); ks5(6); ks5(7); 
+            ks5(8);  
+            cx->n_rnd = 11; break;
+    case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+            cx->k_sch[5] = u = word_in(in_key + 20);
+            ks6(0); ks6(1); ks6(2); ks6(3);
+            ks6(4); ks6(5); ks6(6); ks6(7); 
+            cx->n_rnd = 12; break;
+    case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+            cx->k_sch[5] = u = word_in(in_key + 20);
+            cx->k_sch[6] = v = word_in(in_key + 24);
+            ks7(0); ks7(1); ks7(2); ks7(3);
+            ks7(4); ks7(5); ks7(6); 
+            cx->n_rnd = 13; break;
+    case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+            cx->k_sch[5] = u = word_in(in_key + 20);
+            cx->k_sch[6] = v = word_in(in_key + 24);
+            cx->k_sch[7] = w = word_in(in_key + 28);
+            ks8(0); ks8(1); ks8(2); ks8(3);
+            ks8(4); ks8(5); ks8(6); 
+            cx->n_rnd = 14; break;
+    default:cx->n_rnd = 0; return aes_bad;
+    }
+#else
+    cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+    {
+        uint32_t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2);
+        switch(klen >> 2)
+        {
+        case 4: for(i = 0; i < l; ++i)
+                    ks4(i);
+                break;
+        case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+                for(i = 0; i < l; ++i)
+                    ks5(i);
+                break;
+        case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+                cx->k_sch[5] = u = word_in(in_key + 20);
+                for(i = 0; i < l; ++i)
+                    ks6(i);
+                break;
+        case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+                cx->k_sch[5] = u = word_in(in_key + 20);
+                cx->k_sch[6] = v = word_in(in_key + 24);
+                for(i = 0; i < l; ++i)
+                    ks7(i);
+                break;
+        case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+                cx->k_sch[5] = u = word_in(in_key + 20);
+                cx->k_sch[6] = v = word_in(in_key + 24);
+                cx->k_sch[7] = w = word_in(in_key + 28);
+                for(i = 0; i < l; ++i)
+                    ks8(i);
+                break;
+        }
+    }
+#endif
+
+#if (DEC_ROUND != NO_TABLES)
+    for(i = nc; i < nc * cx->n_rnd; ++i)
+        cx->k_sch[i] = inv_mcol(cx->k_sch[i]);
+#endif
+
+    return aes_good;
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/aesopt.h b/krb5-1-6/src/lib/crypto/aes/aesopt.h
new file mode 100644
index 000000000..e7f3efa78
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aesopt.h
@@ -0,0 +1,851 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 07/02/2002
+
+ This file contains the compilation options for AES (Rijndael) and code 
+ that is common across encryption, key scheduling and table generation.
+
+
+    OPERATION
+ 
+    These source code files implement the AES algorithm Rijndael designed by
+    Joan Daemen and Vincent Rijmen. The version in aes.c is designed for 
+    block and key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes) while 
+    that in aespp.c provides for block and keys sizes of 128, 160, 192, 224 
+    and 256 bits (16, 20, 24, 28 and 32 bytes).  This file is a common header 
+    file for these two implementations and for aesref.c, which is a reference 
+    implementation.
+    
+    This version is designed for flexibility and speed using operations on
+    32-bit words rather than operations on bytes.  It provides aes_both fixed 
+    and  dynamic block and key lengths and can also run with either big or 
+    little endian internal byte order (see aes.h).  It inputs block and key 
+    lengths in bytes with the legal values being  16, 24 and 32 for aes.c and 
+    16, 20, 24, 28 and 32 for aespp.c
+ 
+    THE CIPHER INTERFACE
+
+    uint8_t         (an unsigned  8-bit type)
+    uint32_t        (an unsigned 32-bit type)
+    aes_fret        (a signed 16 bit type for function return values)
+    aes_good        (value != 0, a good return)
+    aes_bad         (value == 0, an error return)
+    struct aes_ctx  (structure for the cipher encryption context)
+    struct aes_ctx  (structure for the cipher decryption context)
+    aes_rval        the function return type (aes_fret if not DLL)
+
+    C subroutine calls:
+
+      aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]);
+      aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+      aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+      aes_rval aes_dec_len(unsigned int blen, aes_ctx cx[1]);
+      aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+      aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+    IMPORTANT NOTE: If you are using this C interface and your compiler does 
+    not set the memory used for objects to zero before use, you will need to 
+    ensure that cx.s_flg is set to zero before using these subroutine calls.
+
+    C++ aes class subroutines:
+
+      class AESclass    for encryption
+      class AESclass    for decryption
+
+      aes_rval len(unsigned int blen = 16);
+      aes_rval key(const unsigned char in_key[], unsigned int klen);
+      aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]);
+
+      aes_rval len(unsigned int blen = 16);
+      aes_rval key(const unsigned char in_key[], unsigned int klen);
+      aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]);
+
+    The block length inputs to set_block and set_key are in numbers of
+    BYTES, not bits.  The calls to subroutines must be made in the above 
+    order but multiple calls can be made without repeating earlier calls
+    if their parameters have not changed. If the cipher block length is
+    variable but set_blk has not been called before cipher operations a
+    value of 16 is assumed (that is, the AES block size). In contrast to 
+    earlier versions the block and key length parameters are now checked
+    for correctness and the encryption and decryption routines check to 
+    ensure that an appropriate key has been set before they are called.
+
+    COMPILATION 
+
+    The files used to provide AES (Rijndael) are
+
+    a. aes.h for the definitions needed for use in C.
+    b. aescpp.h for the definitions needed for use in C++. 
+    c. aesopt.h for setting compilation options (also includes common
+       code).
+    d. aescrypt.c for encryption and decrytpion, or
+    e. aescrypt.asm for encryption and decryption using assembler code.
+    f. aeskey.c for key scheduling.
+    g. aestab.c for table loading or generation.
+    h. uitypes.h for defining fixed length unsigned integers.
+
+    The assembler code uses the NASM assembler. The above files provice
+    block and key lengths of 16, 24 and 32 bytes (128, 192 and 256 bits).
+    If aescrypp.c and aeskeypp.c are used instead of aescrypt.c and
+    aeskey.c respectively, the block and key lengths can then be 16, 20,
+    24, 28 or 32 bytes. However this code has not been optimised to the 
+    same extent and is hence slower (esepcially for the AES block size
+    of 16 bytes).
+
+    To compile AES (Rijndael) for use in C code use aes.h and exclude
+    the AES_DLL define in aes.h
+
+    To compile AES (Rijndael) for use in in C++ code use aescpp.h and
+    exclude the AES_DLL define in aes.h
+
+    To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use
+    aes.h, include the AES_DLL define and compile the DLL.  If using 
+    the test files to test the DLL, exclude aes.c from the test build
+    project and compile it with the same defines as used for the DLL 
+    (ensure that the DLL path is correct)
+
+    CONFIGURATION OPTIONS (here and in aes.h)
+
+    a. define BLOCK_SIZE in aes.h to set the cipher block size (16, 24 
+       or 32 for the standard code, or 16, 20, 24, 28 or 32 for the 
+       extended code) or leave this undefined for dynamically variable 
+       block size (this will result in much slower code).
+    b. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL
+    c. You may need to set PLATFORM_BYTE_ORDER to define the byte order. 
+    d. If you want the code to run in a specific internal byte order, then
+       INTERNAL_BYTE_ORDER must be set accordingly.
+    e. set other configuration options decribed below.
+*/ 
+
+#ifndef _AESOPT_H
+#define _AESOPT_H
+
+/*  START OF CONFIGURATION OPTIONS
+
+    USE OF DEFINES
+  
+    Later in this section there are a number of defines that control
+    the operation of the code.  In each section, the purpose of each
+    define is explained so that the relevant form can be included or
+    excluded by setting either 1's or 0's respectively on the branches
+    of the related #if clauses.
+*/
+
+#include "autoconf.h"
+
+/*  1. PLATFORM SPECIFIC INCLUDES */
+
+#if /* defined(__GNUC__) || */ defined(__GNU_LIBRARY__)
+#  include <endian.h>
+#  include <byteswap.h>
+#elif defined(__CRYPTLIB__)
+#  if defined( INC_ALL )
+#    include "crypt.h"
+#  elif defined( INC_CHILD )
+#    include "../crypt.h"
+#  else
+#    include "crypt.h"
+#  endif
+#  if defined(DATA_LITTLEENDIAN)
+#    define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#  else
+#    define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#  endif
+#elif defined(_MSC_VER)
+#  include <stdlib.h>
+#elif defined(__m68k__) && defined(__palmos__)
+#  include <FloatMgr.h> /* defines BIG_ENDIAN */
+#elif defined(_MIPSEB)
+#  define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#elif defined(_MIPSEL)
+#  define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif defined(_WIN32)
+#  define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif !defined(_WIN32)
+#  include <stdlib.h>
+#  if defined(HAVE_ENDIAN_H)
+#    include <endian.h>
+#  elif defined(HAVE_MACHINE_ENDIAN_H)
+#    include <machine/endian.h>
+#  else
+#    include <sys/param.h>
+#  endif
+#endif
+
+/*  2. BYTE ORDER IN 32-BIT WORDS
+
+    To obtain the highest speed on processors with 32-bit words, this code 
+    needs to determine the order in which bytes are packed into such words.
+    The following block of code is an attempt to capture the most obvious 
+    ways in which various environemnts specify heir endian definitions. It 
+    may well fail, in which case the definitions will need to be set by 
+    editing at the points marked **** EDIT HERE IF NECESSARY **** below.
+*/
+#define AES_LITTLE_ENDIAN   1234 /* byte 0 is least significant (i386) */
+#define AES_BIG_ENDIAN      4321 /* byte 0 is most significant (mc68k) */
+
+#if !defined(PLATFORM_BYTE_ORDER)
+#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN)
+#  if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
+#    if defined(BYTE_ORDER)
+#      if   (BYTE_ORDER == LITTLE_ENDIAN)
+#        define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#      elif (BYTE_ORDER == BIG_ENDIAN)
+#        define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#      endif
+#    endif
+#  elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) 
+#    define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#  elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
+#    define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#  endif
+#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)
+#  if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
+#    if defined(_BYTE_ORDER)
+#      if   (_BYTE_ORDER == _LITTLE_ENDIAN)
+#        define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#      elif (_BYTE_ORDER == _BIG_ENDIAN)
+#        define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#      endif
+#    endif
+#  elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) 
+#    define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#  elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
+#    define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#  endif
+#elif 0     /* **** EDIT HERE IF NECESSARY **** */
+#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif 0     /* **** EDIT HERE IF NECESSARY **** */
+#define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#elif 1
+#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#define UNKNOWN_BYTE_ORDER	/* we're guessing */
+#endif
+#endif
+
+/*  3. ASSEMBLER SUPPORT
+    
+    If the assembler code is used for encryption and decryption this file only 
+    provides key scheduling so the following defines are used
+*/
+#ifdef  AES_ASM
+#define ENCRYPTION_KEY_SCHEDULE
+#define DECRYPTION_KEY_SCHEDULE
+#endif
+
+/*  4. FUNCTIONS REQUIRED
+
+    This implementation provides five main subroutines which provide for
+    setting block length, setting encryption and decryption keys and for
+    encryption and decryption. When the assembler code is not being used
+    the following definition blocks allow the selection of the routines
+    that are to be included in the compilation.
+*/
+#if 1
+#ifndef AES_ASM
+#define SET_BLOCK_LENGTH
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define ENCRYPTION_KEY_SCHEDULE
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define DECRYPTION_KEY_SCHEDULE
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define ENCRYPTION
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define DECRYPTION
+#endif
+#endif
+
+/*  5. BYTE ORDER WITHIN 32 BIT WORDS
+
+    The fundamental data processing units in Rijndael are 8-bit bytes. The 
+    input, output and key input are all enumerated arrays of bytes in which 
+    bytes are numbered starting at zero and increasing to one less than the 
+    number of bytes in the array in question. This enumeration is only used 
+    for naming bytes and does not imply any adjacency or order relationship 
+    from one byte to another. When these inputs and outputs are considered 
+    as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to 
+    byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. 
+    In this implementation bits are numbered from 0 to 7 starting at the 
+    numerically least significant end of each byte (bit n represents 2^n).
+
+    However, Rijndael can be implemented more efficiently using 32-bit 
+    words by packing bytes into words so that bytes 4*n to 4*n+3 are placed
+    into word[n]. While in principle these bytes can be assembled into words 
+    in any positions, this implementation only supports the two formats in 
+    which bytes in adjacent positions within words also have adjacent byte
+    numbers. This order is called big-endian if the lowest numbered bytes 
+    in words have the highest numeric significance and little-endian if the 
+    opposite applies. 
+    
+    This code can work in either order irrespective of the order used by the 
+    machine on which it runs. Normally the internal byte order will be set
+    to the order of the processor on which the code is to be run but this
+    define can be used to reverse this in special situations
+*/
+#if 1
+#define INTERNAL_BYTE_ORDER PLATFORM_BYTE_ORDER
+#elif defined(AES_LITTLE_ENDIAN)
+#define INTERNAL_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif defined(AES_BIG_ENDIAN)
+#define INTERNAL_BYTE_ORDER AES_BIG_ENDIAN
+#endif
+
+/*  6. FAST INPUT/OUTPUT OPERATIONS.  
+
+    On some machines it is possible to improve speed by transferring the 
+    bytes in the input and output arrays to and from the internal 32-bit 
+    variables by addressing these arrays as if they are arrays of 32-bit 
+    words.  On some machines this will always be possible but there may 
+    be a large performance penalty if the byte arrays are not aligned on 
+    the normal word boundaries. On other machines this technique will 
+    lead to memory access errors when such 32-bit word accesses are not
+    properly aligned. The option SAFE_IO avoids such problems but will 
+    often be slower on those machines that support misaligned access 
+    (especially so if care is taken to align the input  and output byte 
+    arrays on 32-bit word boundaries). If SAFE_IO is not defined it is 
+    assumed that access to byte arrays as if they are arrays of 32-bit 
+    words will not cause problems when such accesses are misaligned.
+*/
+#if 1
+#define SAFE_IO
+#endif
+
+/*
+ * If PLATFORM_BYTE_ORDER does not match the actual machine byte
+ * order, the fast word-access code will cause incorrect results.
+ * Therefore, SAFE_IO is required when the byte order is unknown.
+ */
+#if !defined(SAFE_IO) && defined(UNKNOWN_BYTE_ORDER)
+#  error "SAFE_IO must be defined if machine byte order is unknown."
+#endif
+
+/*  7. LOOP UNROLLING
+
+    The code for encryption and decrytpion cycles through a number of rounds
+    that can be implemented either in a loop or by expanding the code into a 
+    long sequence of instructions, the latter producing a larger program but
+    one that will often be much faster. The latter is called loop unrolling.
+    There are also potential speed advantages in expanding two iterations in
+    a loop with half the number of iterations, which is called partial loop
+    unrolling.  The following options allow partial or full loop unrolling 
+    to be set independently for encryption and decryption
+*/
+#if !defined(CONFIG_SMALL)
+#define ENC_UNROLL  FULL
+#elif 0
+#define ENC_UNROLL  PARTIAL
+#else
+#define ENC_UNROLL  NONE
+#endif
+
+#if !defined(CONFIG_SMALL)
+#define DEC_UNROLL  FULL
+#elif 0
+#define DEC_UNROLL  PARTIAL
+#else
+#define DEC_UNROLL  NONE
+#endif
+
+/*  8. FIXED OR DYNAMIC TABLES
+
+    When this section is included the tables used by the code are compiled 
+    statically into the binary file.  Otherwise they are computed once when 
+    the code is first used.
+*/
+#if 1
+#define FIXED_TABLES
+#endif
+
+/*  9. FAST FINITE FIELD OPERATIONS
+
+    If this section is included, tables are used to provide faster finite 
+    field arithmetic (this has no effect if FIXED_TABLES is defined).
+*/
+#if 1
+#define FF_TABLES
+#endif
+
+/*  10. INTERNAL STATE VARIABLE FORMAT
+
+    The internal state of Rijndael is stored in a number of local 32-bit 
+    word varaibles which can be defined either as an array or as individual 
+    names variables. Include this section if you want to store these local
+    varaibles in arrays. Otherwise individual local variables will be used.
+*/
+#if 1
+#define ARRAYS
+#endif
+
+/* In this implementation the columns of the state array are each held in
+   32-bit words. The state array can be held in various ways: in an array
+   of words, in a number of individual word variables or in a number of 
+   processor registers. The following define maps a variable name x and
+   a column number c to the way the state array variable is to be held.
+   The first define below maps the state into an array x[c] whereas the 
+   second form maps the state into a number of individual variables x0,
+   x1, etc.  Another form could map individual state colums to machine
+   register names.
+*/
+
+#if defined(ARRAYS)
+#define s(x,c) x[c]
+#else
+#define s(x,c) x##c
+#endif
+
+/*  11. VARIABLE BLOCK SIZE SPEED
+
+    This section is only relevant if you wish to use the variable block
+    length feature of the code.  Include this section if you place more
+    emphasis on speed rather than code size.
+*/
+#if 1
+#define FAST_VARIABLE
+#endif
+
+/*  12. INTERNAL TABLE CONFIGURATION
+
+    This cipher proceeds by repeating in a number of cycles known as 'rounds'
+    which are implemented by a round function which can optionally be speeded
+    up using tables.  The basic tables are each 256 32-bit words, with either 
+    one or four tables being required for each round function depending on
+    how much speed is required. The encryption and decryption round functions
+    are different and the last encryption and decrytpion round functions are
+    different again making four different round functions in all.
+
+    This means that:
+      1. Normal encryption and decryption rounds can each use either 0, 1 
+         or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
+      2. The last encryption and decryption rounds can also use either 0, 1 
+         or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
+
+    Include or exclude the appropriate definitions below to set the number
+    of tables used by this implementation.
+*/
+
+#if !defined(CONFIG_SMALL)   /* set tables for the normal encryption round */
+#define ENC_ROUND   FOUR_TABLES
+#elif 0
+#define ENC_ROUND   ONE_TABLE
+#else
+#define ENC_ROUND   NO_TABLES
+#endif
+
+#if !defined(CONFIG_SMALL)       /* set tables for the last encryption round */
+#define LAST_ENC_ROUND  FOUR_TABLES
+#elif 0
+#define LAST_ENC_ROUND  ONE_TABLE
+#else
+#define LAST_ENC_ROUND  NO_TABLES
+#endif
+
+#if !defined(CONFIG_SMALL)   /* set tables for the normal decryption round */
+#define DEC_ROUND   FOUR_TABLES
+#elif 0
+#define DEC_ROUND   ONE_TABLE
+#else
+#define DEC_ROUND   NO_TABLES
+#endif
+
+#if !defined(CONFIG_SMALL)       /* set tables for the last decryption round */
+#define LAST_DEC_ROUND  FOUR_TABLES
+#elif 0
+#define LAST_DEC_ROUND  ONE_TABLE
+#else
+#define LAST_DEC_ROUND  NO_TABLES
+#endif
+
+/*  The decryption key schedule can be speeded up with tables in the same
+    way that the round functions can.  Include or exclude the following 
+    defines to set this requirement.
+*/
+#if !defined(CONFIG_SMALL)
+#define KEY_SCHED   FOUR_TABLES
+#elif 0
+#define KEY_SCHED   ONE_TABLE
+#else
+#define KEY_SCHED   NO_TABLES
+#endif
+
+/* END OF CONFIGURATION OPTIONS */
+
+#define NO_TABLES   0   /* DO NOT CHANGE */
+#define ONE_TABLE   1   /* DO NOT CHANGE */
+#define FOUR_TABLES 4   /* DO NOT CHANGE */
+#define NONE        0   /* DO NOT CHANGE */
+#define PARTIAL     1   /* DO NOT CHANGE */
+#define FULL        2   /* DO NOT CHANGE */
+
+#if defined(BLOCK_SIZE) && ((BLOCK_SIZE & 3) || BLOCK_SIZE < 16 || BLOCK_SIZE > 32)
+#error An illegal block size has been specified.
+#endif  
+
+#if !defined(BLOCK_SIZE)
+#define RC_LENGTH    29
+#else
+#define RC_LENGTH   5 * BLOCK_SIZE / 4 - (BLOCK_SIZE == 16 ? 10 : 11)
+#endif
+
+/* Disable at least some poor combinations of options */
+
+#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES
+#undef  LAST_ENC_ROUND
+#define LAST_ENC_ROUND  NO_TABLES
+#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES
+#undef  LAST_ENC_ROUND
+#define LAST_ENC_ROUND  ONE_TABLE 
+#endif
+
+#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE
+#undef  ENC_UNROLL
+#define ENC_UNROLL  NONE
+#endif
+
+#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES
+#undef  LAST_DEC_ROUND
+#define LAST_DEC_ROUND  NO_TABLES
+#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES
+#undef  LAST_DEC_ROUND
+#define LAST_DEC_ROUND  ONE_TABLE 
+#endif
+
+#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE
+#undef  DEC_UNROLL
+#define DEC_UNROLL  NONE
+#endif
+
+#include "aes.h"
+
+ /*
+   upr(x,n):  rotates bytes within words by n positions, moving bytes to
+              higher index positions with wrap around into low positions
+   ups(x,n):  moves bytes by n positions to higher index positions in 
+              words but without wrap around
+   bval(x,n): extracts a byte from a word
+ */
+
+#if (INTERNAL_BYTE_ORDER == AES_LITTLE_ENDIAN)
+#if defined(_MSC_VER)
+#define upr(x,n)        _lrotl((x), 8 * (n))
+#else
+#define upr(x,n)        (((x) << (8 * (n))) | ((x) >> (32 - 8 * (n))))
+#endif
+#define ups(x,n)        ((x) << (8 * (n)))
+#define bval(x,n)       ((uint8_t)((x) >> (8 * (n))))
+#define bytes2word(b0, b1, b2, b3)  \
+        (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
+#endif
+
+#if (INTERNAL_BYTE_ORDER == AES_BIG_ENDIAN)
+#define upr(x,n)        (((x) >> (8 * (n))) | ((x) << (32 - 8 * (n))))
+#define ups(x,n)        ((x) >> (8 * (n))))
+#define bval(x,n)       ((uint8_t)((x) >> (24 - 8 * (n))))
+#define bytes2word(b0, b1, b2, b3)  \
+        (((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | ((uint32_t)(b2) << 8) | (b3))
+#endif
+
+#if defined(SAFE_IO)
+
+#define word_in(x)      bytes2word((x)[0], (x)[1], (x)[2], (x)[3])
+#define word_out(x,v)   { (x)[0] = bval(v,0); (x)[1] = bval(v,1);   \
+                          (x)[2] = bval(v,2); (x)[3] = bval(v,3);   }
+
+#elif (INTERNAL_BYTE_ORDER == PLATFORM_BYTE_ORDER)
+
+#define word_in(x)      *(uint32_t*)(x)
+#define word_out(x,v)   *(uint32_t*)(x) = (v)
+
+#else
+
+#if !defined(bswap_32)
+#if !defined(_MSC_VER)
+#define _lrotl(x,n)     (((x) <<  n) | ((x) >> (32 - n)))
+#endif
+#define bswap_32(x)     ((_lrotl((x),8) & 0x00ff00ff) | (_lrotl((x),24) & 0xff00ff00)) 
+#endif
+
+#define word_in(x)      bswap_32(*(uint32_t*)(x))
+#define word_out(x,v)   *(uint32_t*)(x) = bswap_32(v)
+
+#endif
+
+/* the finite field modular polynomial and elements */
+
+#define WPOLY   0x011b
+#define BPOLY     0x1b
+
+/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+#define m1  0x80808080
+#define m2  0x7f7f7f7f
+#define FFmulX(x)  ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY))
+
+/* The following defines provide alternative definitions of FFmulX that might
+   give improved performance if a fast 32-bit multiply is not available. Note
+   that a temporary variable u needs to be defined where FFmulX is used.
+
+#define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) 
+#define m4  (0x01010101 * BPOLY)
+#define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) 
+*/
+
+/* Work out which tables are needed for the different options   */
+
+#ifdef  AES_ASM
+#ifdef  ENC_ROUND
+#undef  ENC_ROUND
+#endif
+#define ENC_ROUND   FOUR_TABLES
+#ifdef  LAST_ENC_ROUND
+#undef  LAST_ENC_ROUND
+#endif
+#define LAST_ENC_ROUND  FOUR_TABLES
+#ifdef  DEC_ROUND
+#undef  DEC_ROUND
+#endif
+#define DEC_ROUND   FOUR_TABLES
+#ifdef  LAST_DEC_ROUND
+#undef  LAST_DEC_ROUND
+#endif
+#define LAST_DEC_ROUND  FOUR_TABLES
+#ifdef  KEY_SCHED
+#undef  KEY_SCHED
+#define KEY_SCHED   FOUR_TABLES
+#endif
+#endif
+
+#if defined(ENCRYPTION) || defined(AES_ASM)
+#if ENC_ROUND == ONE_TABLE
+#define FT1_SET
+#elif ENC_ROUND == FOUR_TABLES
+#define FT4_SET
+#else
+#define SBX_SET
+#endif
+#if LAST_ENC_ROUND == ONE_TABLE
+#define FL1_SET
+#elif LAST_ENC_ROUND == FOUR_TABLES
+#define FL4_SET
+#elif !defined(SBX_SET)
+#define SBX_SET
+#endif
+#endif
+
+#if defined(DECRYPTION) || defined(AES_ASM)
+#if DEC_ROUND == ONE_TABLE
+#define IT1_SET
+#elif DEC_ROUND == FOUR_TABLES
+#define IT4_SET
+#else
+#define ISB_SET
+#endif
+#if LAST_DEC_ROUND == ONE_TABLE
+#define IL1_SET
+#elif LAST_DEC_ROUND == FOUR_TABLES
+#define IL4_SET
+#elif !defined(ISB_SET)
+#define ISB_SET
+#endif
+#endif
+
+#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE)
+#if KEY_SCHED == ONE_TABLE
+#define LS1_SET
+#define IM1_SET
+#elif KEY_SCHED == FOUR_TABLES
+#define LS4_SET
+#define IM4_SET
+#elif !defined(SBX_SET)
+#define SBX_SET
+#endif
+#endif
+
+#ifdef  FIXED_TABLES
+#define prefx   extern const
+#else
+#define prefx   extern
+extern uint8_t  tab_init;
+void gen_tabs(void);
+#endif
+
+prefx uint32_t  rcon_tab[29];
+
+#ifdef  SBX_SET
+prefx uint8_t s_box[256];
+#endif
+
+#ifdef  ISB_SET
+prefx uint8_t inv_s_box[256];
+#endif
+
+#ifdef  FT1_SET
+prefx uint32_t ft_tab[256];
+#endif
+
+#ifdef  FT4_SET
+prefx uint32_t ft_tab[4][256];
+#endif
+
+#ifdef  FL1_SET
+prefx uint32_t fl_tab[256];
+#endif
+
+#ifdef  FL4_SET
+prefx uint32_t fl_tab[4][256];
+#endif
+
+#ifdef  IT1_SET
+prefx uint32_t it_tab[256];
+#endif
+
+#ifdef  IT4_SET
+prefx uint32_t it_tab[4][256];
+#endif
+
+#ifdef  IL1_SET
+prefx uint32_t il_tab[256];
+#endif
+
+#ifdef  IL4_SET
+prefx uint32_t il_tab[4][256];
+#endif
+
+#ifdef  LS1_SET
+#ifdef  FL1_SET
+#undef  LS1_SET
+#else
+prefx uint32_t ls_tab[256];
+#endif
+#endif
+
+#ifdef  LS4_SET
+#ifdef  FL4_SET
+#undef  LS4_SET
+#else
+prefx uint32_t ls_tab[4][256];
+#endif
+#endif
+
+#ifdef  IM1_SET
+prefx uint32_t im_tab[256];
+#endif
+
+#ifdef  IM4_SET
+prefx uint32_t im_tab[4][256];
+#endif
+
+/* Set the number of columns in nc.  Note that it is important  */
+/* that nc is a constant which is known at compile time if the  */
+/* highest speed version of the code is needed                  */
+
+#if defined(BLOCK_SIZE)
+#define nc  (BLOCK_SIZE >> 2)
+#else
+#define nc  (cx->n_blk >> 2)
+#endif
+
+/* generic definitions of Rijndael macros that use of tables    */
+
+#define no_table(x,box,vf,rf,c) bytes2word( \
+    box[bval(vf(x,0,c),rf(0,c))], \
+    box[bval(vf(x,1,c),rf(1,c))], \
+    box[bval(vf(x,2,c),rf(2,c))], \
+    box[bval(vf(x,3,c),rf(3,c))])
+
+#define one_table(x,op,tab,vf,rf,c) \
+ (     tab[bval(vf(x,0,c),rf(0,c))] \
+  ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
+  ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
+  ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
+
+#define four_tables(x,tab,vf,rf,c) \
+ (  tab[0][bval(vf(x,0,c),rf(0,c))] \
+  ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
+  ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
+  ^ tab[3][bval(vf(x,3,c),rf(3,c))])
+
+#define vf1(x,r,c)  (x)
+#define rf1(r,c)    (r)
+#define rf2(r,c)    ((r-c)&3)
+
+/* perform forward and inverse column mix operation on four bytes in long word x in */
+/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros.  */
+
+#define dec_fmvars
+#if defined(FM4_SET)    /* not currently used */
+#define fwd_mcol(x)     four_tables(x,fm_tab,vf1,rf1,0)
+#elif defined(FM1_SET)  /* not currently used */
+#define fwd_mcol(x)     one_table(x,upr,fm_tab,vf1,rf1,0)
+#else
+#undef  dec_fmvars
+#define dec_fmvars      uint32_t f1, f2;
+#define fwd_mcol(x)     (f1 = (x), f2 = FFmulX(f1), f2 ^ upr(f1 ^ f2, 3) ^ upr(f1, 2) ^ upr(f1, 1))
+#endif
+
+#define dec_imvars
+#if defined(IM4_SET)
+#define inv_mcol(x)     four_tables(x,im_tab,vf1,rf1,0)
+#elif defined(IM1_SET)
+#define inv_mcol(x)     one_table(x,upr,im_tab,vf1,rf1,0)
+#else
+#undef  dec_imvars
+#define dec_imvars      uint32_t    f2, f4, f8, f9;
+#define inv_mcol(x) \
+    (f9 = (x), f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \
+    f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1))
+#endif
+
+#if defined(FL4_SET)
+#define ls_box(x,c)     four_tables(x,fl_tab,vf1,rf2,c)
+#elif   defined(LS4_SET)
+#define ls_box(x,c)     four_tables(x,ls_tab,vf1,rf2,c)
+#elif defined(FL1_SET)
+#define ls_box(x,c)     one_table(x,upr,fl_tab,vf1,rf2,c)
+#elif defined(LS1_SET)
+#define ls_box(x,c)     one_table(x,upr,ls_tab,vf1,rf2,c)
+#else
+#define ls_box(x,c)     no_table(x,s_box,vf1,rf2,c)
+#endif
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/aessrc.url b/krb5-1-6/src/lib/crypto/aes/aessrc.url
new file mode 100644
index 000000000..0758737db
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aessrc.url
@@ -0,0 +1 @@
+http://fp.gladman.plus.com/cryptography_technology/rijndael/index.htm
diff --git a/krb5-1-6/src/lib/crypto/aes/aestab.c b/krb5-1-6/src/lib/crypto/aes/aestab.c
new file mode 100644
index 000000000..7a5d69f7d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/aestab.c
@@ -0,0 +1,494 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 07/02/2002
+*/
+
+#include "aesopt.h"
+
+#if defined(FIXED_TABLES) || !defined(FF_TABLES) 
+
+/*  finite field arithmetic operations */
+
+#define f2(x)   ((x<<1) ^ (((x>>7) & 1) * WPOLY))
+#define f4(x)   ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
+#define f8(x)   ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \
+                        ^ (((x>>5) & 4) * WPOLY))
+#define f3(x)   (f2(x) ^ x)
+#define f9(x)   (f8(x) ^ x)
+#define fb(x)   (f8(x) ^ f2(x) ^ x)
+#define fd(x)   (f8(x) ^ f4(x) ^ x)
+#define fe(x)   (f8(x) ^ f4(x) ^ f2(x))
+
+#endif
+
+#if defined(FIXED_TABLES)
+
+#define sb_data(w) \
+    w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+    w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+    w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+    w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+    w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+    w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+    w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+    w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+    w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+    w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+    w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+    w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+    w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+    w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+    w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+    w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+    w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+    w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+    w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+    w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+    w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+    w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+    w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+    w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+    w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+    w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+    w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+    w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+    w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+    w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+    w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+    w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16)
+
+#define isb_data(w) \
+    w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
+    w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
+    w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
+    w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
+    w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
+    w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
+    w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
+    w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
+    w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
+    w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
+    w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
+    w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
+    w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
+    w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
+    w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
+    w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
+    w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
+    w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
+    w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
+    w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
+    w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
+    w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
+    w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
+    w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
+    w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
+    w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
+    w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
+    w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
+    w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
+    w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
+    w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
+    w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d),
+
+#define mm_data(w) \
+    w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
+    w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
+    w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
+    w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
+    w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
+    w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
+    w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
+    w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
+    w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
+    w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
+    w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
+    w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
+    w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
+    w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
+    w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
+    w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
+    w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
+    w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
+    w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
+    w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
+    w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
+    w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
+    w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
+    w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
+    w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
+    w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
+    w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
+    w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
+    w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
+    w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
+    w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
+    w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff)
+
+#define h0(x)   (x)
+
+/*  These defines are used to ensure tables are generated in the 
+    right format depending on the internal byte order required
+*/
+
+#define w0(p)   bytes2word(p, 0, 0, 0)
+#define w1(p)   bytes2word(0, p, 0, 0)
+#define w2(p)   bytes2word(0, 0, p, 0)
+#define w3(p)   bytes2word(0, 0, 0, p)
+
+/*  Number of elements required in this table for different
+    block and key lengths is:
+
+    Rcon Table      key length (bytes)
+    Length          16  20  24  28  32
+                ---------------------
+    block     16 |  10   9   8   7   7
+    length    20 |  14  11  10   9   9
+    (bytes)   24 |  19  15  12  11  11
+              28 |  24  19  16  13  13
+              32 |  29  23  19  17  14
+
+    this table can be a table of bytes if the key schedule
+    code is adjusted accordingly
+*/
+
+#define u0(p)   bytes2word(f2(p), p, p, f3(p))
+#define u1(p)   bytes2word(f3(p), f2(p), p, p)
+#define u2(p)   bytes2word(p, f3(p), f2(p), p)
+#define u3(p)   bytes2word(p, p, f3(p), f2(p))
+
+#define v0(p)   bytes2word(fe(p), f9(p), fd(p), fb(p))
+#define v1(p)   bytes2word(fb(p), fe(p), f9(p), fd(p))
+#define v2(p)   bytes2word(fd(p), fb(p), fe(p), f9(p))
+#define v3(p)   bytes2word(f9(p), fd(p), fb(p), fe(p))
+
+const uint32_t rcon_tab[29] =
+{
+    w0(0x01), w0(0x02), w0(0x04), w0(0x08),
+    w0(0x10), w0(0x20), w0(0x40), w0(0x80),
+    w0(0x1b), w0(0x36), w0(0x6c), w0(0xd8),
+    w0(0xab), w0(0x4d), w0(0x9a), w0(0x2f),
+    w0(0x5e), w0(0xbc), w0(0x63), w0(0xc6),
+    w0(0x97), w0(0x35), w0(0x6a), w0(0xd4),
+    w0(0xb3), w0(0x7d), w0(0xfa), w0(0xef),
+    w0(0xc5)
+};
+
+#ifdef  SBX_SET
+const uint8_t s_box[256] = { sb_data(h0) };
+#endif
+#ifdef  ISB_SET
+const uint8_t inv_s_box[256] = { isb_data(h0) };
+#endif
+
+#ifdef  FT1_SET
+const uint32_t ft_tab[256] = { sb_data(u0) };
+#endif
+#ifdef  FT4_SET
+const uint32_t ft_tab[4][256] = 
+    { {  sb_data(u0) }, {  sb_data(u1) }, {  sb_data(u2) }, {  sb_data(u3) } };
+#endif
+
+#ifdef  FL1_SET
+const uint32_t fl_tab[256] = { sb_data(w0) };
+#endif
+#ifdef  FL4_SET
+const uint32_t fl_tab[4][256] = 
+    { {  sb_data(w0) }, {  sb_data(w1) }, {  sb_data(w2) }, {  sb_data(w3) } };
+#endif
+
+#ifdef  IT1_SET
+const uint32_t it_tab[256] = { isb_data(v0) };
+#endif
+#ifdef  IT4_SET
+const uint32_t it_tab[4][256] =
+    { { isb_data(v0) }, { isb_data(v1) }, { isb_data(v2) }, { isb_data(v3) } };
+#endif
+
+#ifdef  IL1_SET
+const uint32_t il_tab[256] = { isb_data(w0) };
+#endif
+#ifdef  IL4_SET
+const uint32_t il_tab[4][256] = 
+    { { isb_data(w0) }, { isb_data(w1) }, { isb_data(w2) }, { isb_data(w3) } };
+#endif
+
+#ifdef  LS1_SET
+const uint32_t ls_tab[256] = { sb_data(w0) };
+#endif
+#ifdef  LS4_SET
+const uint32_t ls_tab[4][256] =
+    { {  sb_data(w0) }, {  sb_data(w1) }, {  sb_data(w2) }, {  sb_data(w3) } };
+#endif
+
+#ifdef  IM1_SET
+const uint32_t im_tab[256] = { mm_data(v0) };
+#endif
+#ifdef  IM4_SET
+const uint32_t im_tab[4][256] = 
+    { {  mm_data(v0) }, {  mm_data(v1) }, {  mm_data(v2) }, {  mm_data(v3) } };
+#endif
+
+#else   /* dynamic table generation */
+
+uint8_t tab_init = 0;
+
+#define const
+
+uint32_t  rcon_tab[RC_LENGTH];
+
+#ifdef  SBX_SET
+uint8_t s_box[256];
+#endif
+#ifdef  ISB_SET
+uint8_t inv_s_box[256];
+#endif
+
+#ifdef  FT1_SET
+uint32_t ft_tab[256];
+#endif
+#ifdef  FT4_SET
+uint32_t ft_tab[4][256];
+#endif
+
+#ifdef  FL1_SET
+uint32_t fl_tab[256];
+#endif
+#ifdef  FL4_SET
+uint32_t fl_tab[4][256];
+#endif
+
+#ifdef  IT1_SET
+uint32_t it_tab[256];
+#endif
+#ifdef  IT4_SET
+uint32_t it_tab[4][256];
+#endif
+
+#ifdef  IL1_SET
+uint32_t il_tab[256];
+#endif
+#ifdef  IL4_SET
+uint32_t il_tab[4][256];
+#endif
+
+#ifdef  LS1_SET
+uint32_t ls_tab[256];
+#endif
+#ifdef  LS4_SET
+uint32_t ls_tab[4][256];
+#endif
+
+#ifdef  IM1_SET
+uint32_t im_tab[256];
+#endif
+#ifdef  IM4_SET
+uint32_t im_tab[4][256];
+#endif
+
+#if !defined(FF_TABLES)
+
+/*  Generate the tables for the dynamic table option
+
+    It will generally be sensible to use tables to compute finite 
+    field multiplies and inverses but where memory is scarse this 
+    code might sometimes be better. But it only has effect during
+    initialisation so its pretty unimportant in overall terms.
+*/
+
+/*  return 2 ^ (n - 1) where n is the bit number of the highest bit
+    set in x with x in the range 1 < x < 0x00000200.   This form is
+    used so that locals within fi can be bytes rather than words
+*/
+
+static uint8_t hibit(const uint32_t x)
+{   uint8_t r = (uint8_t)((x >> 1) | (x >> 2));
+    
+    r |= (r >> 2);
+    r |= (r >> 4);
+    return (r + 1) >> 1;
+}
+
+/* return the inverse of the finite field element x */
+
+static uint8_t fi(const uint8_t x)
+{   uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+    if(x < 2) return x;
+
+    for(;;)
+    {
+        if(!n1) return v1;
+
+        while(n2 >= n1)
+        {   
+            n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
+        }
+        
+        if(!n2) return v2;
+
+        while(n1 >= n2)
+        {   
+            n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
+        }
+    }
+}
+
+#else
+
+/* define the finite field multiplies required for Rijndael */
+
+#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
+#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
+#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
+#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
+#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
+#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
+#define fi(x) ((x) ?   pow[255 - log[x]]: 0)
+
+#endif
+
+/* The forward and inverse affine transformations used in the S-box */
+
+#define fwd_affine(x) \
+    (w = (uint32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(uint8_t)(w^(w>>8)))
+
+#define inv_affine(x) \
+    (w = (uint32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(uint8_t)(w^(w>>8)))
+
+void gen_tabs(void)
+{   uint32_t  i, w;
+
+#if defined(FF_TABLES)
+
+    uint8_t  pow[512], log[256];
+
+    /*  log and power tables for GF(2^8) finite field with
+        WPOLY as modular polynomial - the simplest primitive
+        root is 0x03, used here to generate the tables
+    */
+
+    i = 0; w = 1; 
+    do
+    {   
+        pow[i] = (uint8_t)w;
+        pow[i + 255] = (uint8_t)w;
+        log[w] = (uint8_t)i++;
+        w ^=  (w << 1) ^ (w & 0x80 ? WPOLY : 0);
+    }
+    while (w != 1);
+
+#endif
+
+    for(i = 0, w = 1; i < RC_LENGTH; ++i)
+    {
+        rcon_tab[i] = bytes2word(w, 0, 0, 0);
+        w = f2(w);
+    }
+
+    for(i = 0; i < 256; ++i)
+    {   uint8_t    b;
+
+        b = fwd_affine(fi((uint8_t)i));
+        w = bytes2word(f2(b), b, b, f3(b));
+
+#ifdef  SBX_SET
+        s_box[i] = b;
+#endif
+
+#ifdef  FT1_SET                 /* tables for a normal encryption round */
+        ft_tab[i] = w;
+#endif
+#ifdef  FT4_SET
+        ft_tab[0][i] = w;
+        ft_tab[1][i] = upr(w,1);
+        ft_tab[2][i] = upr(w,2);
+        ft_tab[3][i] = upr(w,3);
+#endif
+        w = bytes2word(b, 0, 0, 0);
+
+#ifdef  FL1_SET                 /* tables for last encryption round (may also   */
+        fl_tab[i] = w;          /* be used in the key schedule)                 */
+#endif
+#ifdef  FL4_SET
+        fl_tab[0][i] = w;
+        fl_tab[1][i] = upr(w,1);
+        fl_tab[2][i] = upr(w,2);
+        fl_tab[3][i] = upr(w,3);
+#endif
+
+#ifdef  LS1_SET                 /* table for key schedule if fl_tab above is    */
+        ls_tab[i] = w;          /* not of the required form                     */
+#endif
+#ifdef  LS4_SET
+        ls_tab[0][i] = w;
+        ls_tab[1][i] = upr(w,1);
+        ls_tab[2][i] = upr(w,2);
+        ls_tab[3][i] = upr(w,3);
+#endif
+
+        b = fi(inv_affine((uint8_t)i));
+        w = bytes2word(fe(b), f9(b), fd(b), fb(b));
+
+#ifdef  IM1_SET                 /* tables for the inverse mix column operation  */
+        im_tab[b] = w;
+#endif
+#ifdef  IM4_SET
+        im_tab[0][b] = w;
+        im_tab[1][b] = upr(w,1);
+        im_tab[2][b] = upr(w,2);
+        im_tab[3][b] = upr(w,3);
+#endif
+
+#ifdef  ISB_SET
+        inv_s_box[i] = b;
+#endif
+#ifdef  IT1_SET                 /* tables for a normal decryption round */
+        it_tab[i] = w;
+#endif
+#ifdef  IT4_SET
+        it_tab[0][i] = w;
+        it_tab[1][i] = upr(w,1);
+        it_tab[2][i] = upr(w,2);
+        it_tab[3][i] = upr(w,3);
+#endif
+        w = bytes2word(b, 0, 0, 0);
+#ifdef  IL1_SET                 /* tables for last decryption round */
+        il_tab[i] = w;
+#endif
+#ifdef  IL4_SET
+        il_tab[0][i] = w;
+        il_tab[1][i] = upr(w,1);
+        il_tab[2][i] = upr(w,2);
+        il_tab[3][i] = upr(w,3);
+#endif
+    }
+
+    tab_init = 1;
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/expect-vk.txt b/krb5-1-6/src/lib/crypto/aes/expect-vk.txt
new file mode 100644
index 000000000..bbd2c587b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/expect-vk.txt
@@ -0,0 +1,1548 @@
+
+KEYSIZE=128
+
+PT=00000000000000000000000000000000
+
+I=1
+KEY=80000000000000000000000000000000
+CT=0EDD33D3C621E546455BD8BA1418BEC8
+
+I=2
+KEY=40000000000000000000000000000000
+CT=C0CC0C5DA5BD63ACD44A80774FAD5222
+
+I=3
+KEY=20000000000000000000000000000000
+CT=2F0B4B71BC77851B9CA56D42EB8FF080
+
+I=4
+KEY=10000000000000000000000000000000
+CT=6B1E2FFFE8A114009D8FE22F6DB5F876
+
+I=5
+KEY=08000000000000000000000000000000
+CT=9AA042C315F94CBB97B62202F83358F5
+
+I=6
+KEY=04000000000000000000000000000000
+CT=DBE01DE67E346A800C4C4B4880311DE4
+
+I=7
+KEY=02000000000000000000000000000000
+CT=C117D2238D53836ACD92DDCDB85D6A21
+
+I=8
+KEY=01000000000000000000000000000000
+CT=DC0ED85DF9611ABB7249CDD168C5467E
+
+I=9
+KEY=00800000000000000000000000000000
+CT=807D678FFF1F56FA92DE3381904842F2
+
+I=10
+KEY=00400000000000000000000000000000
+CT=0E53B3FCAD8E4B130EF73AEB957FB402
+
+I=11
+KEY=00200000000000000000000000000000
+CT=969FFD3B7C35439417E7BDE923035D65
+
+I=12
+KEY=00100000000000000000000000000000
+CT=A99B512C19CA56070491166A1503BF15
+
+I=13
+KEY=00080000000000000000000000000000
+CT=6E9985252126EE344D26AE369D2327E3
+
+I=14
+KEY=00040000000000000000000000000000
+CT=B85F4809F904C275491FCDCD1610387E
+
+I=15
+KEY=00020000000000000000000000000000
+CT=ED365B8D7D20C1F5D53FB94DD211DF7B
+
+I=16
+KEY=00010000000000000000000000000000
+CT=B3A575E86A8DB4A7135D604C43304896
+
+I=17
+KEY=00008000000000000000000000000000
+CT=89704BCB8E69F846259EB0ACCBC7F8A2
+
+I=18
+KEY=00004000000000000000000000000000
+CT=C56EE7C92197861F10D7A92B90882055
+
+I=19
+KEY=00002000000000000000000000000000
+CT=92F296F6846E0EAF9422A5A24A08B069
+
+I=20
+KEY=00001000000000000000000000000000
+CT=E67E32BB8F11DEB8699318BEE9E91A60
+
+I=21
+KEY=00000800000000000000000000000000
+CT=B08EEF85EAF626DD91B65C4C3A97D92B
+
+I=22
+KEY=00000400000000000000000000000000
+CT=661083A6ADDCE79BB4E0859AB5538013
+
+I=23
+KEY=00000200000000000000000000000000
+CT=55DFE2941E0EB10AFC0B333BD34DE1FE
+
+I=24
+KEY=00000100000000000000000000000000
+CT=6BFE5945E715C9662609770F8846087A
+
+I=25
+KEY=00000080000000000000000000000000
+CT=79848E9C30C2F8CDA8B325F7FED2B139
+
+I=26
+KEY=00000040000000000000000000000000
+CT=7A713A53B99FEF34AC04DEEF80965BD0
+
+I=27
+KEY=00000020000000000000000000000000
+CT=18144A2B46620D32C3C32CE52D49257F
+
+I=28
+KEY=00000010000000000000000000000000
+CT=872E827C70887C80749F7B8BB1847C7E
+
+I=29
+KEY=00000008000000000000000000000000
+CT=6B86C6A4FE6A60C59B1A3102F8DE49F3
+
+I=30
+KEY=00000004000000000000000000000000
+CT=9848BB3DFDF6F532F094679A4C231A20
+
+I=31
+KEY=00000002000000000000000000000000
+CT=925AD528E852E329B2091CD3F1C2BCEE
+
+I=32
+KEY=00000001000000000000000000000000
+CT=80DF436544B0DD596722E46792A40CD8
+
+I=33
+KEY=00000000800000000000000000000000
+CT=525DAF18F93E83E1E74BBBDDE4263BBA
+
+I=34
+KEY=00000000400000000000000000000000
+CT=F65C9D2EE485D24701FFA3313B9D5BE6
+
+I=35
+KEY=00000000200000000000000000000000
+CT=E4FC8D8BCA06425BDF94AFA40FCC14BA
+
+I=36
+KEY=00000000100000000000000000000000
+CT=A53F0A5CA1E4E6440BB975FF320DE6F8
+
+I=37
+KEY=00000000080000000000000000000000
+CT=D55313B9394080462E87E02899B553F0
+
+I=38
+KEY=00000000040000000000000000000000
+CT=34A71D761F71BCD344384C7F97D27906
+
+I=39
+KEY=00000000020000000000000000000000
+CT=233F3D819599612EBC89580245C996A8
+
+I=40
+KEY=00000000010000000000000000000000
+CT=B4F1374E5268DBCB676E447529E53F89
+
+I=41
+KEY=00000000008000000000000000000000
+CT=0816BD27861D2BA891D1044E39951E96
+
+I=42
+KEY=00000000004000000000000000000000
+CT=F3BE9EA3F10C73CA64FDE5DB13A951D1
+
+I=43
+KEY=00000000002000000000000000000000
+CT=2448086A8106FBD03048DDF857D3F1C8
+
+I=44
+KEY=00000000001000000000000000000000
+CT=670756E65BEC8B68F03D77CDCDCE7B91
+
+I=45
+KEY=00000000000800000000000000000000
+CT=EF968CF0D36FD6C6EFFD225F6FB44CA9
+
+I=46
+KEY=00000000000400000000000000000000
+CT=2E8767157922E3826DDCEC1B0CC1E105
+
+I=47
+KEY=00000000000200000000000000000000
+CT=78CE7EEC670E45A967BAB17E26A1AD36
+
+I=48
+KEY=00000000000100000000000000000000
+CT=3C5CEE825655F098F6E81A2F417DA3FB
+
+I=49
+KEY=00000000000080000000000000000000
+CT=67BFDB431DCE1292200BC6F5207ADB12
+
+I=50
+KEY=00000000000040000000000000000000
+CT=7540FD38E447C0779228548747843A6F
+
+I=51
+KEY=00000000000020000000000000000000
+CT=B85E513301F8A936EA9EC8A21A85B5E6
+
+I=52
+KEY=00000000000010000000000000000000
+CT=04C67DBF16C11427D507A455DE2C9BC5
+
+I=53
+KEY=00000000000008000000000000000000
+CT=03F75EB8959E55079CFFB4FF149A37B6
+
+I=54
+KEY=00000000000004000000000000000000
+CT=74550287F666C63BB9BC7838433434B0
+
+I=55
+KEY=00000000000002000000000000000000
+CT=7D537200195EBC3AEFD1EAAB1C385221
+
+I=56
+KEY=00000000000001000000000000000000
+CT=CE24E4D40C68A82B535CBD3C8E21652A
+
+I=57
+KEY=00000000000000800000000000000000
+CT=AB20072405AA8FC40265C6F1F3DC8BC0
+
+I=58
+KEY=00000000000000400000000000000000
+CT=6CFD2CF688F566B093F67B9B3839E80A
+
+I=59
+KEY=00000000000000200000000000000000
+CT=BD95977E6B7239D407A012C5544BF584
+
+I=60
+KEY=00000000000000100000000000000000
+CT=DF9C0130AC77E7C72C997F587B46DBE0
+
+I=61
+KEY=00000000000000080000000000000000
+CT=E7F1B82CADC53A648798945B34EFEFF2
+
+I=62
+KEY=00000000000000040000000000000000
+CT=932C6DBF69255CF13EDCDB72233ACEA3
+
+I=63
+KEY=00000000000000020000000000000000
+CT=5C76002BC7206560EFE550C80B8F12CC
+
+I=64
+KEY=00000000000000010000000000000000
+CT=F6B7BDD1CAEEBAB574683893C4475484
+
+I=65
+KEY=00000000000000008000000000000000
+CT=A920E37CC6DC6B31DA8C0169569F5034
+
+I=66
+KEY=00000000000000004000000000000000
+CT=919380ECD9C778BC513148B0C28D65FD
+
+I=67
+KEY=00000000000000002000000000000000
+CT=EE67308DD3F2D9E6C2170755E5784BE1
+
+I=68
+KEY=00000000000000001000000000000000
+CT=3CC73E53B85609023A05E149B223AE09
+
+I=69
+KEY=00000000000000000800000000000000
+CT=983E8AF7CF05EBB28D71EB841C9406E6
+
+I=70
+KEY=00000000000000000400000000000000
+CT=0F3099B2D31FA5299EE5BF43193287FC
+
+I=71
+KEY=00000000000000000200000000000000
+CT=B763D84F38C27FE6931DCEB6715D4DB6
+
+I=72
+KEY=00000000000000000100000000000000
+CT=5AE3C9B0E3CC29C0C61565CD01F8A248
+
+I=73
+KEY=00000000000000000080000000000000
+CT=F58083572CD90981958565D48D2DEE25
+
+I=74
+KEY=00000000000000000040000000000000
+CT=7E6255EEF8F70C0EF10337AAB1CCCEF8
+
+I=75
+KEY=00000000000000000020000000000000
+CT=AAD4BAC34DB22821841CE2F631961902
+
+I=76
+KEY=00000000000000000010000000000000
+CT=D7431C0409BB1441BA9C6858DC7D4E81
+
+I=77
+KEY=00000000000000000008000000000000
+CT=EF9298C65E339F6E801A59C626456993
+
+I=78
+KEY=00000000000000000004000000000000
+CT=53FE29F68FF541ABC3F0EF3350B72F7E
+
+I=79
+KEY=00000000000000000002000000000000
+CT=F6BBA5C10DB02529E2C2DA3FB582CC14
+
+I=80
+KEY=00000000000000000001000000000000
+CT=E4239AA37FC531A386DAD1126FC0E9CD
+
+I=81
+KEY=00000000000000000000800000000000
+CT=8F7758F857D15BBE7BFD0E416404C365
+
+I=82
+KEY=00000000000000000000400000000000
+CT=D273EB57C687BCD1B4EA7218A509E7B8
+
+I=83
+KEY=00000000000000000000200000000000
+CT=65D64F8D76E8B3423FA25C4EB58A210A
+
+I=84
+KEY=00000000000000000000100000000000
+CT=623D802B4EC450D66A16625702FCDBE0
+
+I=85
+KEY=00000000000000000000080000000000
+CT=7496460CB28E5791BAEAF9B68FB00022
+
+I=86
+KEY=00000000000000000000040000000000
+CT=34EA600F18BB0694B41681A49D510C1D
+
+I=87
+KEY=00000000000000000000020000000000
+CT=5F8FF0D47D5766D29B5D6E8F46423BD8
+
+I=88
+KEY=00000000000000000000010000000000
+CT=225F9286C5928BF09F84D3F93F541959
+
+I=89
+KEY=00000000000000000000008000000000
+CT=B21E90D25DF383416A5F072CEBEB1FFB
+
+I=90
+KEY=00000000000000000000004000000000
+CT=4AEFCDA089318125453EB9E8EB5E492E
+
+I=91
+KEY=00000000000000000000002000000000
+CT=4D3E75C6CD40EC4869BC85158591ADB8
+
+I=92
+KEY=00000000000000000000001000000000
+CT=63A8B904405436A1B99D7751866771B7
+
+I=93
+KEY=00000000000000000000000800000000
+CT=64F0DAAE47529199792EAE172BA53293
+
+I=94
+KEY=00000000000000000000000400000000
+CT=C3EEF84BEA18225D515A8C852A9047EE
+
+I=95
+KEY=00000000000000000000000200000000
+CT=A44AC422B47D47B81AF73B3E9AC9596E
+
+I=96
+KEY=00000000000000000000000100000000
+CT=D16E04A8FBC435094F8D53ADF25F5084
+
+I=97
+KEY=00000000000000000000000080000000
+CT=EF13DC34BAB03E124EEAD8B6BF44B532
+
+I=98
+KEY=00000000000000000000000040000000
+CT=D94799075C24DCC067AF0D392049250D
+
+I=99
+KEY=00000000000000000000000020000000
+CT=14F431771EDDCE4764C21A2254B5E3C8
+
+I=100
+KEY=00000000000000000000000010000000
+CT=7039329F36F2ED682B02991F28D64679
+
+I=101
+KEY=00000000000000000000000008000000
+CT=124EE24EDE5551639DB8B8B941F6141D
+
+I=102
+KEY=00000000000000000000000004000000
+CT=C2852879A34D5184E478EC918B993FEE
+
+I=103
+KEY=00000000000000000000000002000000
+CT=86A806A3525B93E432053C9AB5ABBEDF
+
+I=104
+KEY=00000000000000000000000001000000
+CT=C1609BF5A4F07E37C17A36366EC23ECC
+
+I=105
+KEY=00000000000000000000000000800000
+CT=7E81E7CB92159A51FFCEA331B1E8EA53
+
+I=106
+KEY=00000000000000000000000000400000
+CT=37A7BE002856C5A59A6E03EAFCE7729A
+
+I=107
+KEY=00000000000000000000000000200000
+CT=BDF98A5A4F91E890C9A1D1E5FAAB138F
+
+I=108
+KEY=00000000000000000000000000100000
+CT=4E96ACB66E051F2BC739CC3D3E34A26B
+
+I=109
+KEY=00000000000000000000000000080000
+CT=EE996CDD120EB86E21ECFA49E8E1FCF1
+
+I=110
+KEY=00000000000000000000000000040000
+CT=61B9E6B579DBF6070C351A1440DD85FF
+
+I=111
+KEY=00000000000000000000000000020000
+CT=AC369E484316440B40DFC83AA96E28E7
+
+I=112
+KEY=00000000000000000000000000010000
+CT=0A2D16DE985C76D45C579C1159413BBE
+
+I=113
+KEY=00000000000000000000000000008000
+CT=DA3FDC38DA1D374FA4802CDA1A1C6B0F
+
+I=114
+KEY=00000000000000000000000000004000
+CT=B842523D4C41C2211AFE43A5800ADCE3
+
+I=115
+KEY=00000000000000000000000000002000
+CT=9E2CDA90D8E992DBA6C73D8229567192
+
+I=116
+KEY=00000000000000000000000000001000
+CT=D49583B781D9E20F5BE101415957FC49
+
+I=117
+KEY=00000000000000000000000000000800
+CT=EF09DA5C12B376E458B9B8670032498E
+
+I=118
+KEY=00000000000000000000000000000400
+CT=A96BE0463DA774461A5E1D5A9DD1AC10
+
+I=119
+KEY=00000000000000000000000000000200
+CT=32CEE3341060790D2D4B1362EF397090
+
+I=120
+KEY=00000000000000000000000000000100
+CT=21CEA416A3D3359D2C4D58FB6A035F06
+
+I=121
+KEY=00000000000000000000000000000080
+CT=172AEAB3D507678ECAF455C12587ADB7
+
+I=122
+KEY=00000000000000000000000000000040
+CT=B6F897941EF8EBFF9FE80A567EF38478
+
+I=123
+KEY=00000000000000000000000000000020
+CT=A9723259D94A7DC662FB0C782CA3F1DD
+
+I=124
+KEY=00000000000000000000000000000010
+CT=2F91C984B9A4839F30001B9F430493B4
+
+I=125
+KEY=00000000000000000000000000000008
+CT=0472406345A610B048CB99EE0EF3FA0F
+
+I=126
+KEY=00000000000000000000000000000004
+CT=F5F39086646F8C05ED16EFA4B617957C
+
+I=127
+KEY=00000000000000000000000000000002
+CT=26D50F485A30408D5AF47A5736292450
+
+I=128
+KEY=00000000000000000000000000000001
+CT=0545AAD56DA2A97C3663D1432A3D1C84
+
+==========
+
+KEYSIZE=256
+
+PT=00000000000000000000000000000000
+
+I=1
+KEY=8000000000000000000000000000000000000000000000000000000000000000
+CT=E35A6DCB19B201A01EBCFA8AA22B5759
+
+I=2
+KEY=4000000000000000000000000000000000000000000000000000000000000000
+CT=5075C2405B76F22F553488CAE47CE90B
+
+I=3
+KEY=2000000000000000000000000000000000000000000000000000000000000000
+CT=49DF95D844A0145A7DE01C91793302D3
+
+I=4
+KEY=1000000000000000000000000000000000000000000000000000000000000000
+CT=E7396D778E940B8418A86120E5F421FE
+
+I=5
+KEY=0800000000000000000000000000000000000000000000000000000000000000
+CT=05F535C36FCEDE4657BE37F4087DB1EF
+
+I=6
+KEY=0400000000000000000000000000000000000000000000000000000000000000
+CT=D0C1DDDD10DA777C68AB36AF51F2C204
+
+I=7
+KEY=0200000000000000000000000000000000000000000000000000000000000000
+CT=1C55FB811B5C6464C4E5DE1535A75514
+
+I=8
+KEY=0100000000000000000000000000000000000000000000000000000000000000
+CT=52917F3AE957D5230D3A2AF57C7B5A71
+
+I=9
+KEY=0080000000000000000000000000000000000000000000000000000000000000
+CT=C6E3D5501752DD5E9AEF086D6B45D705
+
+I=10
+KEY=0040000000000000000000000000000000000000000000000000000000000000
+CT=A24A9C7AF1D9B1E17E1C9A3E711B3FA7
+
+I=11
+KEY=0020000000000000000000000000000000000000000000000000000000000000
+CT=B881ECA724A6D43DBC6B96F6F59A0D20
+
+I=12
+KEY=0010000000000000000000000000000000000000000000000000000000000000
+CT=EC524D9A24DFFF2A9639879B83B8E137
+
+I=13
+KEY=0008000000000000000000000000000000000000000000000000000000000000
+CT=34C4F345F5466215A037F443635D6F75
+
+I=14
+KEY=0004000000000000000000000000000000000000000000000000000000000000
+CT=5BA5055BEDB8895F672E29F2EB5A355D
+
+I=15
+KEY=0002000000000000000000000000000000000000000000000000000000000000
+CT=B3F692AA3A435259EBBEF9B51AD1E08D
+
+I=16
+KEY=0001000000000000000000000000000000000000000000000000000000000000
+CT=414FEB4376F2C64A5D2FBB2ED531BA7D
+
+I=17
+KEY=0000800000000000000000000000000000000000000000000000000000000000
+CT=A20D519E3BCA3303F07E81719F61605E
+
+I=18
+KEY=0000400000000000000000000000000000000000000000000000000000000000
+CT=A08D10E520AF811F45BD60A2DC0DC4B1
+
+I=19
+KEY=0000200000000000000000000000000000000000000000000000000000000000
+CT=B06893A8C563C430E6F3858826EFBBE4
+
+I=20
+KEY=0000100000000000000000000000000000000000000000000000000000000000
+CT=0FFEE26AE2D3929C6BD9C6BEDFF84409
+
+I=21
+KEY=0000080000000000000000000000000000000000000000000000000000000000
+CT=4D0F5E906ED77801FC0EF53EDC5F9E2B
+
+I=22
+KEY=0000040000000000000000000000000000000000000000000000000000000000
+CT=8B6EC00119AD8B026DCE56EA7DEFE930
+
+I=23
+KEY=0000020000000000000000000000000000000000000000000000000000000000
+CT=69026591D43363EE9D83B5007F0B484E
+
+I=24
+KEY=0000010000000000000000000000000000000000000000000000000000000000
+CT=27135D86950C6A2F86872706279A4761
+
+I=25
+KEY=0000008000000000000000000000000000000000000000000000000000000000
+CT=35E6DB8723F281DA410C3AC8535ED77C
+
+I=26
+KEY=0000004000000000000000000000000000000000000000000000000000000000
+CT=57427CF214B8C28E4BBF487CCB8D0E09
+
+I=27
+KEY=0000002000000000000000000000000000000000000000000000000000000000
+CT=6DF01BF56E5131AC87F96E99CAB86367
+
+I=28
+KEY=0000001000000000000000000000000000000000000000000000000000000000
+CT=3856C5B55790B768BBF7D43031579BCF
+
+I=29
+KEY=0000000800000000000000000000000000000000000000000000000000000000
+CT=1E6ED8FB7C15BC4D2F63BA7037ED44D0
+
+I=30
+KEY=0000000400000000000000000000000000000000000000000000000000000000
+CT=E1B2ED6CD8D93D455534E401156D4BCF
+
+I=31
+KEY=0000000200000000000000000000000000000000000000000000000000000000
+CT=EFBCCA5BDFDAD10E875F02336212CE36
+
+I=32
+KEY=0000000100000000000000000000000000000000000000000000000000000000
+CT=0B777F02FD18DCE2646DCFE868DFAFAD
+
+I=33
+KEY=0000000080000000000000000000000000000000000000000000000000000000
+CT=C8A104B5693D1B14F5BF1F10100BF508
+
+I=34
+KEY=0000000040000000000000000000000000000000000000000000000000000000
+CT=4CCE6615244AFCB38408FECE219962EA
+
+I=35
+KEY=0000000020000000000000000000000000000000000000000000000000000000
+CT=F99E7845D3A255B394C9C050CBA258B1
+
+I=36
+KEY=0000000010000000000000000000000000000000000000000000000000000000
+CT=B4AFBB787F9BCFB7B55FDF447F611295
+
+I=37
+KEY=0000000008000000000000000000000000000000000000000000000000000000
+CT=AE1C426A697FAF2808B7EF6ADDB5C020
+
+I=38
+KEY=0000000004000000000000000000000000000000000000000000000000000000
+CT=7572F92811A85B9BDD38DEAD9945BCAE
+
+I=39
+KEY=0000000002000000000000000000000000000000000000000000000000000000
+CT=71BC7AA46E43FB95A181527D9F6A360F
+
+I=40
+KEY=0000000001000000000000000000000000000000000000000000000000000000
+CT=5542EF2923066F1EC8F546DD0D8E7CA8
+
+I=41
+KEY=0000000000800000000000000000000000000000000000000000000000000000
+CT=6B92317C7D623790B748FDD7EFC42422
+
+I=42
+KEY=0000000000400000000000000000000000000000000000000000000000000000
+CT=0FE7C097E899C71EF045360F8D6C25CF
+
+I=43
+KEY=0000000000200000000000000000000000000000000000000000000000000000
+CT=4ECE7EE107D0264D04693151C25B9DF6
+
+I=44
+KEY=0000000000100000000000000000000000000000000000000000000000000000
+CT=FD6AE687CBFCA9E301045888D3BB9605
+
+I=45
+KEY=0000000000080000000000000000000000000000000000000000000000000000
+CT=476B579C8556C7254424902CC1D6D36E
+
+I=46
+KEY=0000000000040000000000000000000000000000000000000000000000000000
+CT=4133CBCDFDD6B8860A1FC18665D6D71B
+
+I=47
+KEY=0000000000020000000000000000000000000000000000000000000000000000
+CT=3B36EC2664798C108B816812C65DFDC7
+
+I=48
+KEY=0000000000010000000000000000000000000000000000000000000000000000
+CT=364E20A234FEA385D48DC5A09C9E70CF
+
+I=49
+KEY=0000000000008000000000000000000000000000000000000000000000000000
+CT=4A4BA25969DE3F5EE5642C71AAD0EFD1
+
+I=50
+KEY=0000000000004000000000000000000000000000000000000000000000000000
+CT=E42CBAAE43297F67A76C1C501BB79E36
+
+I=51
+KEY=0000000000002000000000000000000000000000000000000000000000000000
+CT=23CEDEDA4C15B4C037E8C61492217937
+
+I=52
+KEY=0000000000001000000000000000000000000000000000000000000000000000
+CT=A1719147A1F4A1A1180BD16E8593DCDE
+
+I=53
+KEY=0000000000000800000000000000000000000000000000000000000000000000
+CT=AB82337E9FB0EC60D1F25A1D0014192C
+
+I=54
+KEY=0000000000000400000000000000000000000000000000000000000000000000
+CT=74BF2D8FC5A8388DF1A3A4D7D33FC164
+
+I=55
+KEY=0000000000000200000000000000000000000000000000000000000000000000
+CT=D5B493317E6FBC6FFFD664B3C491368A
+
+I=56
+KEY=0000000000000100000000000000000000000000000000000000000000000000
+CT=BA767381586DA56A2A8D503D5F7ADA0B
+
+I=57
+KEY=0000000000000080000000000000000000000000000000000000000000000000
+CT=E8E6BC57DFE9CCADB0DECABF4E5CF91F
+
+I=58
+KEY=0000000000000040000000000000000000000000000000000000000000000000
+CT=3C8E5A5CDC9CEED90815D1F84BB2998C
+
+I=59
+KEY=0000000000000020000000000000000000000000000000000000000000000000
+CT=283843020BA38F056001B2FD585F7CC9
+
+I=60
+KEY=0000000000000010000000000000000000000000000000000000000000000000
+CT=D8ADC7426F623ECE8741A70621D28870
+
+I=61
+KEY=0000000000000008000000000000000000000000000000000000000000000000
+CT=D7C5C215592D06F00E6A80DA69A28EA9
+
+I=62
+KEY=0000000000000004000000000000000000000000000000000000000000000000
+CT=52CF6FA433C3C870CAC70190358F7F16
+
+I=63
+KEY=0000000000000002000000000000000000000000000000000000000000000000
+CT=F63D442A584DA71786ADEC9F3346DF75
+
+I=64
+KEY=0000000000000001000000000000000000000000000000000000000000000000
+CT=549078F4B0CA7079B45F9A5ADAFAFD99
+
+I=65
+KEY=0000000000000000800000000000000000000000000000000000000000000000
+CT=F2A5986EE4E9984BE2BAFB79EA8152FA
+
+I=66
+KEY=0000000000000000400000000000000000000000000000000000000000000000
+CT=8A74535017B4DB2776668A1FAE64384C
+
+I=67
+KEY=0000000000000000200000000000000000000000000000000000000000000000
+CT=E613342F57A97FD95DC088711A5D0ECD
+
+I=68
+KEY=0000000000000000100000000000000000000000000000000000000000000000
+CT=3FFAEBF6B22CF1DC82AE17CD48175B01
+
+I=69
+KEY=0000000000000000080000000000000000000000000000000000000000000000
+CT=BAFD52EFA15C248CCBF9757735E6B1CE
+
+I=70
+KEY=0000000000000000040000000000000000000000000000000000000000000000
+CT=7AF94BC018D9DDD4539D2DD1C6F4000F
+
+I=71
+KEY=0000000000000000020000000000000000000000000000000000000000000000
+CT=FE177AD61CA0FDB281086FBA8FE76803
+
+I=72
+KEY=0000000000000000010000000000000000000000000000000000000000000000
+CT=74DBEA15E2E9285BAD163D7D534251B6
+
+I=73
+KEY=0000000000000000008000000000000000000000000000000000000000000000
+CT=23DD21331B3A92F200FE56FF050FFE74
+
+I=74
+KEY=0000000000000000004000000000000000000000000000000000000000000000
+CT=A69C5AA34AB20A858CAFA766EACED6D8
+
+I=75
+KEY=0000000000000000002000000000000000000000000000000000000000000000
+CT=3F72BB4DF2A4F941A4A09CB78F04B97A
+
+I=76
+KEY=0000000000000000001000000000000000000000000000000000000000000000
+CT=72CC43577E1FD5FD14622D24D97FCDCC
+
+I=77
+KEY=0000000000000000000800000000000000000000000000000000000000000000
+CT=D83AF8EBE93E0B6B99CAFADE224937D1
+
+I=78
+KEY=0000000000000000000400000000000000000000000000000000000000000000
+CT=44042329128D56CAA8D084C8BD769D1E
+
+I=79
+KEY=0000000000000000000200000000000000000000000000000000000000000000
+CT=14102D72290DE4F2C430ADD1ED64BA1D
+
+I=80
+KEY=0000000000000000000100000000000000000000000000000000000000000000
+CT=449124097B1ECD0AE7065206DF06F03C
+
+I=81
+KEY=0000000000000000000080000000000000000000000000000000000000000000
+CT=D060A99F8CC153A42E11E5F97BD7584A
+
+I=82
+KEY=0000000000000000000040000000000000000000000000000000000000000000
+CT=65605B3EA9261488D53E48602ADEA299
+
+I=83
+KEY=0000000000000000000020000000000000000000000000000000000000000000
+CT=C5E5CAD7A208DE8EA6BE049EFE5C7346
+
+I=84
+KEY=0000000000000000000010000000000000000000000000000000000000000000
+CT=4C280C46D2181646048DD5BC0C0831A5
+
+I=85
+KEY=0000000000000000000008000000000000000000000000000000000000000000
+CT=5DD65CF37F2A0929559AABAFDA08E730
+
+I=86
+KEY=0000000000000000000004000000000000000000000000000000000000000000
+CT=31F2335CAAF264172F69A693225E6D22
+
+I=87
+KEY=0000000000000000000002000000000000000000000000000000000000000000
+CT=3E28B35F99A72662590DA96426DD377F
+
+I=88
+KEY=0000000000000000000001000000000000000000000000000000000000000000
+CT=570F40F5D7B20441486578ED344343BE
+
+I=89
+KEY=0000000000000000000000800000000000000000000000000000000000000000
+CT=C54308AD1C9E3B19F8B7417873045A8C
+
+I=90
+KEY=0000000000000000000000400000000000000000000000000000000000000000
+CT=CBF335E39CE13ADE2B696179E8FD0CE1
+
+I=91
+KEY=0000000000000000000000200000000000000000000000000000000000000000
+CT=9C2FBF422355D8293083D51F4A3C18A9
+
+I=92
+KEY=0000000000000000000000100000000000000000000000000000000000000000
+CT=5ED8B5A31ECEFAB16C9AA6986DA67BCE
+
+I=93
+KEY=0000000000000000000000080000000000000000000000000000000000000000
+CT=627815DCFC814ABC75900041B1DD7B59
+
+I=94
+KEY=0000000000000000000000040000000000000000000000000000000000000000
+CT=9EF3E82A50A59F166260494F7A7F2CC3
+
+I=95
+KEY=0000000000000000000000020000000000000000000000000000000000000000
+CT=878CD0D8D920888B5935D6C351128737
+
+I=96
+KEY=0000000000000000000000010000000000000000000000000000000000000000
+CT=E44429474D6FC3084EB2A6B8B46AF754
+
+I=97
+KEY=0000000000000000000000008000000000000000000000000000000000000000
+CT=EBAACF9641D54E1FB18D0A2BE4F19BE5
+
+I=98
+KEY=0000000000000000000000004000000000000000000000000000000000000000
+CT=13B3BF497CEE780E123C7E193DEA3A01
+
+I=99
+KEY=0000000000000000000000002000000000000000000000000000000000000000
+CT=6E8F381DE00A41161F0DF03B4155BFD4
+
+I=100
+KEY=0000000000000000000000001000000000000000000000000000000000000000
+CT=35E4F29BBA2BAE01144910783C3FEF49
+
+I=101
+KEY=0000000000000000000000000800000000000000000000000000000000000000
+CT=55B17BD66788CEAC366398A31F289FFB
+
+I=102
+KEY=0000000000000000000000000400000000000000000000000000000000000000
+CT=11341F56C0D6D1008D28741DAA7679CE
+
+I=103
+KEY=0000000000000000000000000200000000000000000000000000000000000000
+CT=4DF7253DF421D83358BDBE924745D98C
+
+I=104
+KEY=0000000000000000000000000100000000000000000000000000000000000000
+CT=BAE2EE651116D93EDC8E83B5F3347BE1
+
+I=105
+KEY=0000000000000000000000000080000000000000000000000000000000000000
+CT=F9721ABD06709157183AF3965A659D9D
+
+I=106
+KEY=0000000000000000000000000040000000000000000000000000000000000000
+CT=19A1C252A613FE2860A4AE6D75CE6FA3
+
+I=107
+KEY=0000000000000000000000000020000000000000000000000000000000000000
+CT=B5DDB2F5D9752C949FBDE3FFF5556C6E
+
+I=108
+KEY=0000000000000000000000000010000000000000000000000000000000000000
+CT=81B044FCFFC78ECCFCD171AAD0405C66
+
+I=109
+KEY=0000000000000000000000000008000000000000000000000000000000000000
+CT=C640566D3C06020EB2C42F1D62E56A9B
+
+I=110
+KEY=0000000000000000000000000004000000000000000000000000000000000000
+CT=EA6C4BCF425291679FDFFD26A424FBCC
+
+I=111
+KEY=0000000000000000000000000002000000000000000000000000000000000000
+CT=57F6901465D9440D9F15EE2CBA5A4090
+
+I=112
+KEY=0000000000000000000000000001000000000000000000000000000000000000
+CT=FBCFA74CADC7406260F63D96C8AAB6B1
+
+I=113
+KEY=0000000000000000000000000000800000000000000000000000000000000000
+CT=DFF4F096CEA211D4BBDACA033D0EC7D1
+
+I=114
+KEY=0000000000000000000000000000400000000000000000000000000000000000
+CT=1EE5190D551F0F42F675227A381296A9
+
+I=115
+KEY=0000000000000000000000000000200000000000000000000000000000000000
+CT=F98E1905012E580F097623C10B93054F
+
+I=116
+KEY=0000000000000000000000000000100000000000000000000000000000000000
+CT=E7D43743D21DD3C9F168C86856558B9A
+
+I=117
+KEY=0000000000000000000000000000080000000000000000000000000000000000
+CT=632A9DDA730DAB67593C5D08D8AC1059
+
+I=118
+KEY=0000000000000000000000000000040000000000000000000000000000000000
+CT=E084317000715B9057BC9DE9F3AB6124
+
+I=119
+KEY=0000000000000000000000000000020000000000000000000000000000000000
+CT=61F9EF33A0BB4E666C2ED99101919FAB
+
+I=120
+KEY=0000000000000000000000000000010000000000000000000000000000000000
+CT=6DC1D68A11834657D46703C22578D59A
+
+I=121
+KEY=0000000000000000000000000000008000000000000000000000000000000000
+CT=53AC1548863D3D16F1D4DC7242E05F2C
+
+I=122
+KEY=0000000000000000000000000000004000000000000000000000000000000000
+CT=E82CD587A408306AD78CEAE0916B9F8C
+
+I=123
+KEY=0000000000000000000000000000002000000000000000000000000000000000
+CT=0FD2D40EA6AD17A3A767F0A8600D6295
+
+I=124
+KEY=0000000000000000000000000000001000000000000000000000000000000000
+CT=AD84CC8255ADB39DFCA23F92761AE7E9
+
+I=125
+KEY=0000000000000000000000000000000800000000000000000000000000000000
+CT=F4F20CF7D51BEE7DA024A2B11A7ECA0B
+
+I=126
+KEY=0000000000000000000000000000000400000000000000000000000000000000
+CT=5057691B85D9CE93A193214DB0A016B6
+
+I=127
+KEY=0000000000000000000000000000000200000000000000000000000000000000
+CT=0F58C960876390BDEF4BB6BE95CAA1EE
+
+I=128
+KEY=0000000000000000000000000000000100000000000000000000000000000000
+CT=9A3E66EEBC21BC0BD9430B341EF465FA
+
+I=129
+KEY=0000000000000000000000000000000080000000000000000000000000000000
+CT=20415035F34B8BCBCB28ABF07F78F0D4
+
+I=130
+KEY=0000000000000000000000000000000040000000000000000000000000000000
+CT=AC89FC7BA10479EBF10DE65BCEF89B3C
+
+I=131
+KEY=0000000000000000000000000000000020000000000000000000000000000000
+CT=068FA75A30BE443171AF3F6FEB1A20D2
+
+I=132
+KEY=0000000000000000000000000000000010000000000000000000000000000000
+CT=50E02F213246C525A8C27700CA34B502
+
+I=133
+KEY=0000000000000000000000000000000008000000000000000000000000000000
+CT=227DA47D5A0906DB3AB042BB0A695FB6
+
+I=134
+KEY=0000000000000000000000000000000004000000000000000000000000000000
+CT=8663AC30ED12514F1DE46777F4514BFC
+
+I=135
+KEY=0000000000000000000000000000000002000000000000000000000000000000
+CT=A987D4BC12E1DE9F4B6DF43567C34A8B
+
+I=136
+KEY=0000000000000000000000000000000001000000000000000000000000000000
+CT=6D5A0370F599ACA605F63B04E5143D0C
+
+I=137
+KEY=0000000000000000000000000000000000800000000000000000000000000000
+CT=9809266E378B07B7AFDB3BAA97B7E442
+
+I=138
+KEY=0000000000000000000000000000000000400000000000000000000000000000
+CT=8F753252B30CCCACE12D9A301F4D5090
+
+I=139
+KEY=0000000000000000000000000000000000200000000000000000000000000000
+CT=032465F6C0CE34D41962F561692A1AFF
+
+I=140
+KEY=0000000000000000000000000000000000100000000000000000000000000000
+CT=C50E9AD5BEB8F3B00821DD47FF8AC093
+
+I=141
+KEY=0000000000000000000000000000000000080000000000000000000000000000
+CT=9C6FEA3D46268D54A6829B2AD25BB276
+
+I=142
+KEY=0000000000000000000000000000000000040000000000000000000000000000
+CT=0FD8575E87706F561343D7B3A41E044A
+
+I=143
+KEY=0000000000000000000000000000000000020000000000000000000000000000
+CT=BEE9BEB3739540D88CBCE77925F0A114
+
+I=144
+KEY=0000000000000000000000000000000000010000000000000000000000000000
+CT=D24EAEE7FFFBAC3D6F26C2DCE0DCDE28
+
+I=145
+KEY=0000000000000000000000000000000000008000000000000000000000000000
+CT=47771A90398FF0F7FA821C2F8F5E1398
+
+I=146
+KEY=0000000000000000000000000000000000004000000000000000000000000000
+CT=4639741B6F84B135AD118C8249B64ED0
+
+I=147
+KEY=0000000000000000000000000000000000002000000000000000000000000000
+CT=8EE5505EC85567697A3306F250A27720
+
+I=148
+KEY=0000000000000000000000000000000000001000000000000000000000000000
+CT=7C8A19AC1AEFBC5E0119D91A5F05D4C2
+
+I=149
+KEY=0000000000000000000000000000000000000800000000000000000000000000
+CT=5141B9B672E54773B672E3A6C424887B
+
+I=150
+KEY=0000000000000000000000000000000000000400000000000000000000000000
+CT=B5A2D3CD206653C6402F34FB0AE3613D
+
+I=151
+KEY=0000000000000000000000000000000000000200000000000000000000000000
+CT=0F5BD9408738231D114B0A82753279A3
+
+I=152
+KEY=0000000000000000000000000000000000000100000000000000000000000000
+CT=FEF033FF4268EA487FC74C5E43A45338
+
+I=153
+KEY=0000000000000000000000000000000000000080000000000000000000000000
+CT=A3EDC09DCD529B113910D904AD855581
+
+I=154
+KEY=0000000000000000000000000000000000000040000000000000000000000000
+CT=AB8FBB6F27A0AC7C55B59FDD36B72F1C
+
+I=155
+KEY=0000000000000000000000000000000000000020000000000000000000000000
+CT=EEA44D5ED4D769CC930CD83D8999EC46
+
+I=156
+KEY=0000000000000000000000000000000000000010000000000000000000000000
+CT=6972276803AE9AA7C6F431AB10979C34
+
+I=157
+KEY=0000000000000000000000000000000000000008000000000000000000000000
+CT=86DEAA9F39244101818178474D7DBDE9
+
+I=158
+KEY=0000000000000000000000000000000000000004000000000000000000000000
+CT=88C6B466EA361D662D8D08CBF181F4FE
+
+I=159
+KEY=0000000000000000000000000000000000000002000000000000000000000000
+CT=91AB2C6B7C63FF59F7CBEEBF91B20B95
+
+I=160
+KEY=0000000000000000000000000000000000000001000000000000000000000000
+CT=2DFE6C146AD5B3D8C3C1718F13B48E01
+
+I=161
+KEY=0000000000000000000000000000000000000000800000000000000000000000
+CT=C7CFF1623451711391A302EEC3584AAA
+
+I=162
+KEY=0000000000000000000000000000000000000000400000000000000000000000
+CT=089FE845CC05011686C66019D18BE050
+
+I=163
+KEY=0000000000000000000000000000000000000000200000000000000000000000
+CT=08C8410B9B427211A67124B0DCCEAD48
+
+I=164
+KEY=0000000000000000000000000000000000000000100000000000000000000000
+CT=8D91592F5566085254784606334D7629
+
+I=165
+KEY=0000000000000000000000000000000000000000080000000000000000000000
+CT=3298FEAAF2E1201D6299FF8846639C97
+
+I=166
+KEY=0000000000000000000000000000000000000000040000000000000000000000
+CT=C497CB9F0BDFE0EFC8C2F3F90760AA72
+
+I=167
+KEY=0000000000000000000000000000000000000000020000000000000000000000
+CT=2788AFD046E0309CBE4424690DA2AB89
+
+I=168
+KEY=0000000000000000000000000000000000000000010000000000000000000000
+CT=E9891707F25EF29FEE372890D4258982
+
+I=169
+KEY=0000000000000000000000000000000000000000008000000000000000000000
+CT=DB041D94A23D45D4D4DCED5A030CAF61
+
+I=170
+KEY=0000000000000000000000000000000000000000004000000000000000000000
+CT=FFAFDBF0ECB18DF9EA02C27077448E6D
+
+I=171
+KEY=0000000000000000000000000000000000000000002000000000000000000000
+CT=2DAAA42A7D0A1D3B0E4761D99CF2150A
+
+I=172
+KEY=0000000000000000000000000000000000000000001000000000000000000000
+CT=3B7A54CB7CF30ABE263DD6ED5BFE8D63
+
+I=173
+KEY=0000000000000000000000000000000000000000000800000000000000000000
+CT=EEFA090174C590C448A55D43648F534A
+
+I=174
+KEY=0000000000000000000000000000000000000000000400000000000000000000
+CT=9E15798731ED42F43EA2740A691DA872
+
+I=175
+KEY=0000000000000000000000000000000000000000000200000000000000000000
+CT=31FBD661540A5DEAAD1017CFD3909EC8
+
+I=176
+KEY=0000000000000000000000000000000000000000000100000000000000000000
+CT=CDA9AE05F224140E28CB951721B44D6A
+
+I=177
+KEY=0000000000000000000000000000000000000000000080000000000000000000
+CT=0C5BC512C60A1EAC3434EFB1A8FBB182
+
+I=178
+KEY=0000000000000000000000000000000000000000000040000000000000000000
+CT=AA863610DEEEEB62D045E87EA30B59B5
+
+I=179
+KEY=0000000000000000000000000000000000000000000020000000000000000000
+CT=6AC2448DE568D279C7EEBE1DF403920C
+
+I=180
+KEY=0000000000000000000000000000000000000000000010000000000000000000
+CT=E2011E3D292B26888AE801215FD0CB40
+
+I=181
+KEY=0000000000000000000000000000000000000000000008000000000000000000
+CT=E06F3E15EE3A61672D1C99BADE5B9DBE
+
+I=182
+KEY=0000000000000000000000000000000000000000000004000000000000000000
+CT=BB7027F0548CF6712CEB4C7A4B28E178
+
+I=183
+KEY=0000000000000000000000000000000000000000000002000000000000000000
+CT=061EC21FB70FADBDF87C3BD2AE23825B
+
+I=184
+KEY=0000000000000000000000000000000000000000000001000000000000000000
+CT=4C21F26FE94ABBAC381352375314C3EB
+
+I=185
+KEY=0000000000000000000000000000000000000000000000800000000000000000
+CT=F7CEE6DD99909C2B569EEDA61ED8942E
+
+I=186
+KEY=0000000000000000000000000000000000000000000000400000000000000000
+CT=CE98C4A876C65E4CCB261EBB1D9DF7F5
+
+I=187
+KEY=0000000000000000000000000000000000000000000000200000000000000000
+CT=A5491881CF833C3604ABC08044F402AC
+
+I=188
+KEY=0000000000000000000000000000000000000000000000100000000000000000
+CT=A1BA16E64CCCB3087D57A768507B0BFC
+
+I=189
+KEY=0000000000000000000000000000000000000000000000080000000000000000
+CT=D55951E202D2949EBD3BE43120C738BF
+
+I=190
+KEY=0000000000000000000000000000000000000000000000040000000000000000
+CT=EBB8E43069E69F450EFEC65DCD52B7FD
+
+I=191
+KEY=0000000000000000000000000000000000000000000000020000000000000000
+CT=2B292135663B4AA5ABFE9423D57E7EE9
+
+I=192
+KEY=0000000000000000000000000000000000000000000000010000000000000000
+CT=E91BF974B3BE3AD966249D8655292A85
+
+I=193
+KEY=0000000000000000000000000000000000000000000000008000000000000000
+CT=384365998EAA9562236CC58F6ADF9610
+
+I=194
+KEY=0000000000000000000000000000000000000000000000004000000000000000
+CT=C2E997012AA3D4D8D359C9A947CBE69F
+
+I=195
+KEY=0000000000000000000000000000000000000000000000002000000000000000
+CT=F49421204148BA213BE87E2D5C22B0BF
+
+I=196
+KEY=0000000000000000000000000000000000000000000000001000000000000000
+CT=82ED0ED9953AA92E4DF30929CA65C00F
+
+I=197
+KEY=0000000000000000000000000000000000000000000000000800000000000000
+CT=291EB1D11653C8479437C74A977F5106
+
+I=198
+KEY=0000000000000000000000000000000000000000000000000400000000000000
+CT=BCB997B1939B8983ABD550D6025683E3
+
+I=199
+KEY=0000000000000000000000000000000000000000000000000200000000000000
+CT=1FBA2592C6F489775CAADA71F9B983E9
+
+I=200
+KEY=0000000000000000000000000000000000000000000000000100000000000000
+CT=969F66F217AF1A3DB9E41C1B29039824
+
+I=201
+KEY=0000000000000000000000000000000000000000000000000080000000000000
+CT=A54BB7D6B17E423AC0A7744C19073CB8
+
+I=202
+KEY=0000000000000000000000000000000000000000000000000040000000000000
+CT=B0AC6E6578D1021F47DCF9748A32EAD5
+
+I=203
+KEY=0000000000000000000000000000000000000000000000000020000000000000
+CT=B87B361C3B7B194C77A4358D4669153E
+
+I=204
+KEY=0000000000000000000000000000000000000000000000000010000000000000
+CT=46A133847F96EAA8282A799DC8899D58
+
+I=205
+KEY=0000000000000000000000000000000000000000000000000008000000000000
+CT=2265EC3A9F2D5C9547A091CC8CFB18EA
+
+I=206
+KEY=0000000000000000000000000000000000000000000000000004000000000000
+CT=54CBF3A6FC4FE56D426117AA1FFD1DDE
+
+I=207
+KEY=0000000000000000000000000000000000000000000000000002000000000000
+CT=5312877CCEAB6CFB0905394A370A8003
+
+I=208
+KEY=0000000000000000000000000000000000000000000000000001000000000000
+CT=7190BD6EC613FE38B84ECFE28F702FE4
+
+I=209
+KEY=0000000000000000000000000000000000000000000000000000800000000000
+CT=D1FA5B9CA89A43B04C05F0EF29EF68CD
+
+I=210
+KEY=0000000000000000000000000000000000000000000000000000400000000000
+CT=808285751548ED934FD1056D2D9AE8BA
+
+I=211
+KEY=0000000000000000000000000000000000000000000000000000200000000000
+CT=2758DEF3E7B95A9AE89777BE64D5A6CF
+
+I=212
+KEY=0000000000000000000000000000000000000000000000000000100000000000
+CT=07D81F87DB3E0ACC82B01E08FB22F3C1
+
+I=213
+KEY=0000000000000000000000000000000000000000000000000000080000000000
+CT=8DA250E5553D650711A75EE1CB4FD1C7
+
+I=214
+KEY=0000000000000000000000000000000000000000000000000000040000000000
+CT=A93D946BD0E87F32719DF5F158CEE669
+
+I=215
+KEY=0000000000000000000000000000000000000000000000000000020000000000
+CT=03945236EC2A4D4EAF30B8ABEB54330D
+
+I=216
+KEY=0000000000000000000000000000000000000000000000000000010000000000
+CT=11CC35301F24B79DDE31AEA2D1354F88
+
+I=217
+KEY=0000000000000000000000000000000000000000000000000000008000000000
+CT=E73715B3E8D9A290F44AE6FFBF247E5D
+
+I=218
+KEY=0000000000000000000000000000000000000000000000000000004000000000
+CT=7345E07732B71CB158BBF64CCA5C5B96
+
+I=219
+KEY=0000000000000000000000000000000000000000000000000000002000000000
+CT=6E128F296D24705A1924FD9B70C4ED04
+
+I=220
+KEY=0000000000000000000000000000000000000000000000000000001000000000
+CT=95A789776F036783FBD330947083F54F
+
+I=221
+KEY=0000000000000000000000000000000000000000000000000000000800000000
+CT=360DEC2533EA4AA2E3E54FD3DE2906EB
+
+I=222
+KEY=0000000000000000000000000000000000000000000000000000000400000000
+CT=E68EFD7FECF4D601EA22727BD764965B
+
+I=223
+KEY=0000000000000000000000000000000000000000000000000000000200000000
+CT=9065C64A8BFF44AC33EDBB611CF83D7B
+
+I=224
+KEY=0000000000000000000000000000000000000000000000000000000100000000
+CT=8F33C8DF2A7A51CE8090E8F123BC3723
+
+I=225
+KEY=0000000000000000000000000000000000000000000000000000000080000000
+CT=807F391FFBA8291BA625623210F99018
+
+I=226
+KEY=0000000000000000000000000000000000000000000000000000000040000000
+CT=5E8B3F3A701522CE5CAA761C929D6292
+
+I=227
+KEY=0000000000000000000000000000000000000000000000000000000020000000
+CT=3BA404DC38735A78289E3809E8364835
+
+I=228
+KEY=0000000000000000000000000000000000000000000000000000000010000000
+CT=D23BEDBAD229F8305DC425B6B759DCC9
+
+I=229
+KEY=0000000000000000000000000000000000000000000000000000000008000000
+CT=44880F21CF5913040AE376AEE2A10AD8
+
+I=230
+KEY=0000000000000000000000000000000000000000000000000000000004000000
+CT=9BC98E29D057C0E828C3B5CCE69256C1
+
+I=231
+KEY=0000000000000000000000000000000000000000000000000000000002000000
+CT=B293CC7A975DA141A68279368057CC41
+
+I=232
+KEY=0000000000000000000000000000000000000000000000000000000001000000
+CT=8D60FB87ACD91385B313BE5F1D7BD30F
+
+I=233
+KEY=0000000000000000000000000000000000000000000000000000000000800000
+CT=2C8E56132D70291B303C48FDF75543CD
+
+I=234
+KEY=0000000000000000000000000000000000000000000000000000000000400000
+CT=D1F80035B826791F6CE4E59B7DB1BB0D
+
+I=235
+KEY=0000000000000000000000000000000000000000000000000000000000200000
+CT=42CE6224FC36469339A133DD08173BD4
+
+I=236
+KEY=0000000000000000000000000000000000000000000000000000000000100000
+CT=61817155EA41BCBA2AF7F06AE7CBF585
+
+I=237
+KEY=0000000000000000000000000000000000000000000000000000000000080000
+CT=D1923A9866068D2EF5FB77D57C3315B6
+
+I=238
+KEY=0000000000000000000000000000000000000000000000000000000000040000
+CT=B37CBDB5D719F49691CA968EF2E84140
+
+I=239
+KEY=0000000000000000000000000000000000000000000000000000000000020000
+CT=EC974E653A055D7F8F22171030F68E1D
+
+I=240
+KEY=0000000000000000000000000000000000000000000000000000000000010000
+CT=DDE5D3B9AAD9C32213BB3675A822499C
+
+I=241
+KEY=0000000000000000000000000000000000000000000000000000000000008000
+CT=D3B6E9216EA1AE57EB1C628A3C38AB78
+
+I=242
+KEY=0000000000000000000000000000000000000000000000000000000000004000
+CT=82C99ECC69472B7E96324B042AE8B87A
+
+I=243
+KEY=0000000000000000000000000000000000000000000000000000000000002000
+CT=97144DC5338C43600F84439C0AA0D147
+
+I=244
+KEY=0000000000000000000000000000000000000000000000000000000000001000
+CT=400AC4A0BBADA1DB2121EB144C7E5209
+
+I=245
+KEY=0000000000000000000000000000000000000000000000000000000000000800
+CT=EFD9D550EB419ED278F4885A490AB54C
+
+I=246
+KEY=0000000000000000000000000000000000000000000000000000000000000400
+CT=2AB7816E149B7C0404C88A8857793670
+
+I=247
+KEY=0000000000000000000000000000000000000000000000000000000000000200
+CT=5B591DFF9E8DEE15BAD24C025DBCA481
+
+I=248
+KEY=0000000000000000000000000000000000000000000000000000000000000100
+CT=0C06633E30721C3749F49AD8CBF2B754
+
+I=249
+KEY=0000000000000000000000000000000000000000000000000000000000000080
+CT=96D6D31A41B5123B2035FD91A921D4CA
+
+I=250
+KEY=0000000000000000000000000000000000000000000000000000000000000040
+CT=E7F6C34D86668BC2805CA7793C5E86AD
+
+I=251
+KEY=0000000000000000000000000000000000000000000000000000000000000020
+CT=F46DFF5FF500D6879C4D3E45CF0CF0F3
+
+I=252
+KEY=0000000000000000000000000000000000000000000000000000000000000010
+CT=60D842D9C61DA7495C116197B7CECBBE
+
+I=253
+KEY=0000000000000000000000000000000000000000000000000000000000000008
+CT=D45B24EDB673353EBDF248B8FA06B67A
+
+I=254
+KEY=0000000000000000000000000000000000000000000000000000000000000004
+CT=119EAEBCC165D0BD02C0D35DC82EF992
+
+I=255
+KEY=0000000000000000000000000000000000000000000000000000000000000002
+CT=E673143680414ADA301D0ED34626B9FE
+
+I=256
+KEY=0000000000000000000000000000000000000000000000000000000000000001
+CT=6B6CFE160A6263631B292F879EEFF926
+
+==========
diff --git a/krb5-1-6/src/lib/crypto/aes/expect-vt.txt b/krb5-1-6/src/lib/crypto/aes/expect-vt.txt
new file mode 100644
index 000000000..02b238c04
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/expect-vt.txt
@@ -0,0 +1,1036 @@
+
+KEYSIZE=128
+
+KEY=00000000000000000000000000000000
+
+I=1
+PT=80000000000000000000000000000000
+CT=3AD78E726C1EC02B7EBFE92B23D9EC34
+
+I=2
+PT=40000000000000000000000000000000
+CT=45BC707D29E8204D88DFBA2F0B0CAD9B
+
+I=3
+PT=20000000000000000000000000000000
+CT=161556838018F52805CDBD6202002E3F
+
+I=4
+PT=10000000000000000000000000000000
+CT=F5569B3AB6A6D11EFDE1BF0A64C6854A
+
+I=5
+PT=08000000000000000000000000000000
+CT=64E82B50E501FBD7DD4116921159B83E
+
+I=6
+PT=04000000000000000000000000000000
+CT=BAAC12FB613A7DE11450375C74034041
+
+I=7
+PT=02000000000000000000000000000000
+CT=BCF176A7EAAD8085EBACEA362462A281
+
+I=8
+PT=01000000000000000000000000000000
+CT=47711816E91D6FF059BBBF2BF58E0FD3
+
+I=9
+PT=00800000000000000000000000000000
+CT=B970DFBE40698AF1638FE38BD3DF3B2F
+
+I=10
+PT=00400000000000000000000000000000
+CT=F95B59A44F391E14CF20B74BDC32FCFF
+
+I=11
+PT=00200000000000000000000000000000
+CT=720F74AE04A2A435B9A7256E49378F5B
+
+I=12
+PT=00100000000000000000000000000000
+CT=2A0445F61D36BFA7E277070730CF76DA
+
+I=13
+PT=00080000000000000000000000000000
+CT=8D0536B997AEFEC1D94011BAB6699A03
+
+I=14
+PT=00040000000000000000000000000000
+CT=674F002E19F6ED47EFF319E51FAD4498
+
+I=15
+PT=00020000000000000000000000000000
+CT=292C02C5CB9163C80AC0F6CF1DD8E92D
+
+I=16
+PT=00010000000000000000000000000000
+CT=FA321CF18EF5FE727DD82A5C1E945141
+
+I=17
+PT=00008000000000000000000000000000
+CT=A5A7AFE1034C39CCCEBE3C584BC0BE05
+
+I=18
+PT=00004000000000000000000000000000
+CT=4FF5A52E697E77D081205DBDB21CEA39
+
+I=19
+PT=00002000000000000000000000000000
+CT=209E88DC94C9003000CE0769AF7B7166
+
+I=20
+PT=00001000000000000000000000000000
+CT=5DEE41AF864CB4B650E5F51551824D38
+
+I=21
+PT=00000800000000000000000000000000
+CT=A79A63FA7E4503AE6D6E09F5F9053030
+
+I=22
+PT=00000400000000000000000000000000
+CT=A48316749FAE7FAC7002031A6AFD8BA7
+
+I=23
+PT=00000200000000000000000000000000
+CT=D6EEE8A7357A0E1D64262CA9C337AC42
+
+I=24
+PT=00000100000000000000000000000000
+CT=B013CA8A62A858053E9FB667ED39829E
+
+I=25
+PT=00000080000000000000000000000000
+CT=DF6EA9E4538A45A52D5C1A43C88F4B55
+
+I=26
+PT=00000040000000000000000000000000
+CT=7D03BA451371591D3FD5547D9165C73B
+
+I=27
+PT=00000020000000000000000000000000
+CT=0E0426281A6277E186499D365D5F49FF
+
+I=28
+PT=00000010000000000000000000000000
+CT=DBC02169DD2059E6CC4C57C1FEDF5AB4
+
+I=29
+PT=00000008000000000000000000000000
+CT=826590E05D167DA6F00DCC75E22788EB
+
+I=30
+PT=00000004000000000000000000000000
+CT=34A73F21A04421D9786335FAAB49423A
+
+I=31
+PT=00000002000000000000000000000000
+CT=ED347D0E0128EE1A7392A1D36AB78AA9
+
+I=32
+PT=00000001000000000000000000000000
+CT=EE944B2FE6E9FC888042608DA9615F75
+
+I=33
+PT=00000000800000000000000000000000
+CT=9E7C85A909EF7218BA7947CFB4718F46
+
+I=34
+PT=00000000400000000000000000000000
+CT=811AE07A0B2B1F816587FA73699AE77D
+
+I=35
+PT=00000000200000000000000000000000
+CT=68466FBF43C2FE13D4B18F7EC5EA745F
+
+I=36
+PT=00000000100000000000000000000000
+CT=D20B015C7191B219780956E6101F9354
+
+I=37
+PT=00000000080000000000000000000000
+CT=5939D5C1BBF54EE1B3E326D757BDDE25
+
+I=38
+PT=00000000040000000000000000000000
+CT=B1FDAFE9A0240E8FFEA19CE94B5105D3
+
+I=39
+PT=00000000020000000000000000000000
+CT=D62962ECE02CDD68C06BDFEFB2F9495B
+
+I=40
+PT=00000000010000000000000000000000
+CT=B3BB2DE6F3C26587BA8BAC4F7AD9499A
+
+I=41
+PT=00000000008000000000000000000000
+CT=E0B1072D6D9FF703D6FBEF77852B0A6B
+
+I=42
+PT=00000000004000000000000000000000
+CT=D8DD51C907F478DE0228E83E61FD1758
+
+I=43
+PT=00000000002000000000000000000000
+CT=A42DFFE6E7C1671C06A25236FDD10017
+
+I=44
+PT=00000000001000000000000000000000
+CT=25ACF141550BFAB9EF451B6C6A5B2163
+
+I=45
+PT=00000000000800000000000000000000
+CT=4DA7FCA3949B16E821DBC84F19581018
+
+I=46
+PT=00000000000400000000000000000000
+CT=7D49B6347CBCC8919C7FA96A37A7A215
+
+I=47
+PT=00000000000200000000000000000000
+CT=900024B29A08C6721B95BA3B753DDB4D
+
+I=48
+PT=00000000000100000000000000000000
+CT=6D2182FB283B6934D90BA7848CAB5E66
+
+I=49
+PT=00000000000080000000000000000000
+CT=F73EF01B448D23A4D90DE8B2F9666E7A
+
+I=50
+PT=00000000000040000000000000000000
+CT=4AD9CDA2418643E9A3D926AF5E6B0412
+
+I=51
+PT=00000000000020000000000000000000
+CT=7CAEC8E7E5953997D545B033201C8C5B
+
+I=52
+PT=00000000000010000000000000000000
+CT=3C43CA1F6B6864503E27B48D88230CF5
+
+I=53
+PT=00000000000008000000000000000000
+CT=44F779B93108FE9FEEC880D79BA74488
+
+I=54
+PT=00000000000004000000000000000000
+CT=9E50E8D9CFD3A682A78E527C9072A1CF
+
+I=55
+PT=00000000000002000000000000000000
+CT=68D000CBC838BBE3C505D6F814C01F28
+
+I=56
+PT=00000000000001000000000000000000
+CT=2CB2A9FEC1ACD1D9B0FA05205E304F57
+
+I=57
+PT=00000000000000800000000000000000
+CT=01EB2806606E46444520A5CC6180CD4B
+
+I=58
+PT=00000000000000400000000000000000
+CT=DAA9B25168CC702326F217F1A0C0B162
+
+I=59
+PT=00000000000000200000000000000000
+CT=3E07E648975D9578D03555B1755807ED
+
+I=60
+PT=00000000000000100000000000000000
+CT=0B45F52E802C8B8DE09579425B80B711
+
+I=61
+PT=00000000000000080000000000000000
+CT=659595DA0B68F6DF0DD6CA77202986E1
+
+I=62
+PT=00000000000000040000000000000000
+CT=05FF42873893536E58C8FA98A45C73C4
+
+I=63
+PT=00000000000000020000000000000000
+CT=B5B03421DE8BBFFC4EADEC767339A9BD
+
+I=64
+PT=00000000000000010000000000000000
+CT=788BCD111ECF73D4E78D2E21BEF55460
+
+I=65
+PT=00000000000000008000000000000000
+CT=909CD9EC6790359F982DC6F2393D5315
+
+I=66
+PT=00000000000000004000000000000000
+CT=332950F361535FF24EFAC8C76293F12C
+
+I=67
+PT=00000000000000002000000000000000
+CT=A68CCD4E330FFDA9D576DA436DB53D75
+
+I=68
+PT=00000000000000001000000000000000
+CT=27C8A1CCFDB0B015D1ED5B3E77143791
+
+I=69
+PT=00000000000000000800000000000000
+CT=D76A4B95887A77DF610DD3E1D3B20325
+
+I=70
+PT=00000000000000000400000000000000
+CT=C068AB0DE71C66DAE83C361EF4B2D989
+
+I=71
+PT=00000000000000000200000000000000
+CT=C2120BCD49EDA9A288B3B4BE79AC8158
+
+I=72
+PT=00000000000000000100000000000000
+CT=0C546F62BF2773CD0F564FCECA7BA688
+
+I=73
+PT=00000000000000000080000000000000
+CT=18F3462BEDE4920213CCB66DAB1640AA
+
+I=74
+PT=00000000000000000040000000000000
+CT=FE42F245EDD0E24B216AEBD8B392D690
+
+I=75
+PT=00000000000000000020000000000000
+CT=3D3EEBC8D3D1558A194C2D00C337FF2B
+
+I=76
+PT=00000000000000000010000000000000
+CT=29AAEDF043E785DB42836F79BE6CBA28
+
+I=77
+PT=00000000000000000008000000000000
+CT=215F90C6744E2944358E78619159A611
+
+I=78
+PT=00000000000000000004000000000000
+CT=8606B1AA9E1D548E5442B06551E2C6DC
+
+I=79
+PT=00000000000000000002000000000000
+CT=987BB4B8740EC0EDE7FEA97DF033B5B1
+
+I=80
+PT=00000000000000000001000000000000
+CT=C0A3500DA5B0AE07D2F450930BEEDF1B
+
+I=81
+PT=00000000000000000000800000000000
+CT=525FDF8312FE8F32C781481A8DAAAE37
+
+I=82
+PT=00000000000000000000400000000000
+CT=BFD2C56AE5FB9C9DE33A6944572A6487
+
+I=83
+PT=00000000000000000000200000000000
+CT=7975A57A425CDF5AA1FA929101F650B0
+
+I=84
+PT=00000000000000000000100000000000
+CT=BF174BC49609A8709B2CD8366DAA79FE
+
+I=85
+PT=00000000000000000000080000000000
+CT=06C50C43222F56C874B1704E9F44BF7D
+
+I=86
+PT=00000000000000000000040000000000
+CT=0CEC48CD34043EA29CA3B8ED5278721E
+
+I=87
+PT=00000000000000000000020000000000
+CT=9548EA34A1560197B304D0ACB8A1698D
+
+I=88
+PT=00000000000000000000010000000000
+CT=22F9E9B1BD73B6B5B7D3062C986272F3
+
+I=89
+PT=00000000000000000000008000000000
+CT=FEE8E934BD0873295059002230E298D4
+
+I=90
+PT=00000000000000000000004000000000
+CT=1B08E2E3EB820D139CB4ABBDBE81D00D
+
+I=91
+PT=00000000000000000000002000000000
+CT=0021177681E4D90CEAF69DCED0145125
+
+I=92
+PT=00000000000000000000001000000000
+CT=4A8E314452CA8A8A3619FC54BC423643
+
+I=93
+PT=00000000000000000000000800000000
+CT=65047474F7222C94C6965425FF1BFD0A
+
+I=94
+PT=00000000000000000000000400000000
+CT=E123F551A9C4A8489622B16F961A9AA4
+
+I=95
+PT=00000000000000000000000200000000
+CT=EF05530948B80915028BB2B6FE429380
+
+I=96
+PT=00000000000000000000000100000000
+CT=72535B7FE0F0F777CEDCD55CD77E2DDF
+
+I=97
+PT=00000000000000000000000080000000
+CT=3423D8EFC31FA2F4C365C77D8F3B5C63
+
+I=98
+PT=00000000000000000000000040000000
+CT=DE0E51C264663F3C5DBC59580A98D8E4
+
+I=99
+PT=00000000000000000000000020000000
+CT=B2D9391166680947AB09264156719679
+
+I=100
+PT=00000000000000000000000010000000
+CT=10DB79F23B06D263835C424AF749ADB7
+
+I=101
+PT=00000000000000000000000008000000
+CT=DDF72D27E6B01EC107EA3E005B59563B
+
+I=102
+PT=00000000000000000000000004000000
+CT=8266B57485A5954A4236751DE07F6694
+
+I=103
+PT=00000000000000000000000002000000
+CT=669A501E1F1ADE6E5523DE01D6DBC987
+
+I=104
+PT=00000000000000000000000001000000
+CT=C20C48F2989725D461D1DB589DC0896E
+
+I=105
+PT=00000000000000000000000000800000
+CT=DE35158E7810ED1191825D2AA98FA97D
+
+I=106
+PT=00000000000000000000000000400000
+CT=4FE294F2C0F34D0671B693A237EBDDC8
+
+I=107
+PT=00000000000000000000000000200000
+CT=087AE74B10CCBFDF6739FEB9559C01A4
+
+I=108
+PT=00000000000000000000000000100000
+CT=5DC278970B7DEF77A5536C77AB59C207
+
+I=109
+PT=00000000000000000000000000080000
+CT=7607F078C77085184EAA9B060C1FBFFF
+
+I=110
+PT=00000000000000000000000000040000
+CT=9DB841531BCBE7998DAD19993FB3CC00
+
+I=111
+PT=00000000000000000000000000020000
+CT=D6A089B654854A94560BAE13298835B8
+
+I=112
+PT=00000000000000000000000000010000
+CT=E1E223C4CF90CC5D195B370D65114622
+
+I=113
+PT=00000000000000000000000000008000
+CT=1CBED73C50D053BDAD372CEEE54836A1
+
+I=114
+PT=00000000000000000000000000004000
+CT=D309E69376D257ADF2BFDA152B26555F
+
+I=115
+PT=00000000000000000000000000002000
+CT=740F7649117F0DEE6EAA7789A9994C36
+
+I=116
+PT=00000000000000000000000000001000
+CT=76AE64417C297184D668C5FD908B3CE5
+
+I=117
+PT=00000000000000000000000000000800
+CT=6095FEA4AA8035591F1787A819C48787
+
+I=118
+PT=00000000000000000000000000000400
+CT=D1FF4E7ACD1C79967FEBAB0F7465D450
+
+I=119
+PT=00000000000000000000000000000200
+CT=5F5AD3C42B9489557BB63BF49ECF5F8A
+
+I=120
+PT=00000000000000000000000000000100
+CT=FB56CC09B680B1D07C5A52149E29F07C
+
+I=121
+PT=00000000000000000000000000000080
+CT=FF49B8DF4A97CBE03833E66197620DAD
+
+I=122
+PT=00000000000000000000000000000040
+CT=5E070ADE533D2E090ED0F5BE13BC0983
+
+I=123
+PT=00000000000000000000000000000020
+CT=3AB4FB1D2B7BA376590A2C241D1F508D
+
+I=124
+PT=00000000000000000000000000000010
+CT=58B2431BC0BEDE02550F40238969EC78
+
+I=125
+PT=00000000000000000000000000000008
+CT=0253786E126504F0DAB90C48A30321DE
+
+I=126
+PT=00000000000000000000000000000004
+CT=200211214E7394DA2089B6ACD093ABE0
+
+I=127
+PT=00000000000000000000000000000002
+CT=0388DACE60B6A392F328C2B971B2FE78
+
+I=128
+PT=00000000000000000000000000000001
+CT=58E2FCCEFA7E3061367F1D57A4E7455A
+
+==========
+
+KEYSIZE=256
+
+KEY=0000000000000000000000000000000000000000000000000000000000000000
+
+I=1
+PT=80000000000000000000000000000000
+CT=DDC6BF790C15760D8D9AEB6F9A75FD4E
+
+I=2
+PT=40000000000000000000000000000000
+CT=C7098C217C334D0C9BDF37EA13B0822C
+
+I=3
+PT=20000000000000000000000000000000
+CT=60F0FB0D4C56A8D4EEFEC5264204042D
+
+I=4
+PT=10000000000000000000000000000000
+CT=73376FBBF654D0686E0E84001477106B
+
+I=5
+PT=08000000000000000000000000000000
+CT=2F443B52BA5F0C6EA0602C7C4FD259B6
+
+I=6
+PT=04000000000000000000000000000000
+CT=75D11B0E3A68C4223D88DBF017977DD7
+
+I=7
+PT=02000000000000000000000000000000
+CT=779B38D15BFFB63D8D609D551A5CC98E
+
+I=8
+PT=01000000000000000000000000000000
+CT=5275F3D86B4FB8684593133EBFA53CD3
+
+I=9
+PT=00800000000000000000000000000000
+CT=1CEF2074B336CEC62F12DEA2F6AB1481
+
+I=10
+PT=00400000000000000000000000000000
+CT=1AEF5ABBAD9D7160874578DCD8BAE172
+
+I=11
+PT=00200000000000000000000000000000
+CT=46C525DB17E72F26BF03216846B6F609
+
+I=12
+PT=00100000000000000000000000000000
+CT=E24411F941BBE08788781E3EC52CBAA4
+
+I=13
+PT=00080000000000000000000000000000
+CT=83A3DEDD1DD27018F6A6477E40527581
+
+I=14
+PT=00040000000000000000000000000000
+CT=B68F8A2CDBAB0C923C67FC8F0F1087DE
+
+I=15
+PT=00020000000000000000000000000000
+CT=649944A70C32BF87A7409E7AE128FDE8
+
+I=16
+PT=00010000000000000000000000000000
+CT=2846526D67387539C89314DE9E0C2D02
+
+I=17
+PT=00008000000000000000000000000000
+CT=A9A0B8402E53C70DD1688054BA58DDFD
+
+I=18
+PT=00004000000000000000000000000000
+CT=4A72E6E1B79C83AC4BE3EBA5699EED48
+
+I=19
+PT=00002000000000000000000000000000
+CT=B0E36B867BA4FF2B77D0614B0E364E4C
+
+I=20
+PT=00001000000000000000000000000000
+CT=49B57DE141F6418E3090F24DDD4014B6
+
+I=21
+PT=00000800000000000000000000000000
+CT=A6C0D5B9797258E1987AC5F6CD20146D
+
+I=22
+PT=00000400000000000000000000000000
+CT=426CF4BDCAA369175965D26E7C71EEA2
+
+I=23
+PT=00000200000000000000000000000000
+CT=E27F484CE54BC99BC1A52BDA3B518A26
+
+I=24
+PT=00000100000000000000000000000000
+CT=D16D186284C7E6EE64B8104E0EF20BA5
+
+I=25
+PT=00000080000000000000000000000000
+CT=6431F8538AD54E1E044A9F71F8EF556B
+
+I=26
+PT=00000040000000000000000000000000
+CT=ECD57CEB451D27EB96C55B2042257E8E
+
+I=27
+PT=00000020000000000000000000000000
+CT=4F0F188DC911B1954AFBC734C9F68872
+
+I=28
+PT=00000010000000000000000000000000
+CT=B54DEF0337626B65614E81EDFDE620F3
+
+I=29
+PT=00000008000000000000000000000000
+CT=6655D8074CAE0B90B0D3A3FE72D4D9DB
+
+I=30
+PT=00000004000000000000000000000000
+CT=C6B74B6B9EB4FC0C9A237DB1B616D09A
+
+I=31
+PT=00000002000000000000000000000000
+CT=D7B5D076EA56EC2B20791D7AD51CCF8F
+
+I=32
+PT=00000001000000000000000000000000
+CT=FE160C224BF003CE3BDDC90CB52ED22C
+
+I=33
+PT=00000000800000000000000000000000
+CT=5E00DA9BA94B5EC0D258D8A8002E0F6A
+
+I=34
+PT=00000000400000000000000000000000
+CT=09AC6DCFF4DACFF1651E2BA212A292A3
+
+I=35
+PT=00000000200000000000000000000000
+CT=B283617E318D99AF83A05D9810BA89F7
+
+I=36
+PT=00000000100000000000000000000000
+CT=0B5F70CCB40B0EF2538AE9B4A9770B35
+
+I=37
+PT=00000000080000000000000000000000
+CT=43282BF180248FB517839B37F4DDAAE4
+
+I=38
+PT=00000000040000000000000000000000
+CT=DDBD534C8B2E6D30A268F88C55AD765B
+
+I=39
+PT=00000000020000000000000000000000
+CT=A41A164E50EC2D9F175E752B755E0B5C
+
+I=40
+PT=00000000010000000000000000000000
+CT=37BFF99FF2F7AA97779E4ADF6F13FB10
+
+I=41
+PT=00000000008000000000000000000000
+CT=9BA4F7BD298152903A683C4CEC669216
+
+I=42
+PT=00000000004000000000000000000000
+CT=5FB750C7CE10DE7B4504248914D0DA06
+
+I=43
+PT=00000000002000000000000000000000
+CT=3E748BFA108E086F51D56EC74A9E0FB9
+
+I=44
+PT=00000000001000000000000000000000
+CT=31D4E56B99F5B73C1B8437DF332AFB98
+
+I=45
+PT=00000000000800000000000000000000
+CT=9DC6717B84FC55D266E7B1D9B5C52A5F
+
+I=46
+PT=00000000000400000000000000000000
+CT=8EF8BA007F23C0A50FC120E07041BCCD
+
+I=47
+PT=00000000000200000000000000000000
+CT=C58F38E1839FC1918A12B8C9E88C66B6
+
+I=48
+PT=00000000000100000000000000000000
+CT=B695D72A3FCF508C4050E12E40061C2D
+
+I=49
+PT=00000000000080000000000000000000
+CT=5D2736AD478A50583BC8C11BEFF16D7A
+
+I=50
+PT=00000000000040000000000000000000
+CT=DF0EACA8F17847AD41F9578F14C7B56B
+
+I=51
+PT=00000000000020000000000000000000
+CT=E5AA14AD48AD0A3C47CC35D5F8020E51
+
+I=52
+PT=00000000000010000000000000000000
+CT=11BE6C8F58EBD8CEF1A53F591A68E8CE
+
+I=53
+PT=00000000000008000000000000000000
+CT=ECFE7BAFCBF42C1FEE015488770B3053
+
+I=54
+PT=00000000000004000000000000000000
+CT=E552649F8D8EC4A1E1CD6DF50B6E6777
+
+I=55
+PT=00000000000002000000000000000000
+CT=521C0629DE93B9119CDB1DDC5809DDEA
+
+I=56
+PT=00000000000001000000000000000000
+CT=CB38A62A0BAB1784156BA038CBA99BF6
+
+I=57
+PT=00000000000000800000000000000000
+CT=76CCEE8AAACD394DE1EEF3DDA10CB54B
+
+I=58
+PT=00000000000000400000000000000000
+CT=6AFF910FA1D5673140E2DB59B8416049
+
+I=59
+PT=00000000000000200000000000000000
+CT=064A12C0EF73FB386801BF4F35F3120D
+
+I=60
+PT=00000000000000100000000000000000
+CT=2240E374929D5B1BB8FF0FFDDDF640EC
+
+I=61
+PT=00000000000000080000000000000000
+CT=D4BA15C904C7692185DE85C02052E180
+
+I=62
+PT=00000000000000040000000000000000
+CT=1714A315AB0166728A44CD91D4AE9018
+
+I=63
+PT=00000000000000020000000000000000
+CT=6C970BDD9F0E222722EA31A1D12DD0AD
+
+I=64
+PT=00000000000000010000000000000000
+CT=F5956EDF02BD36A401BBB6CE77C3D3FB
+
+I=65
+PT=00000000000000008000000000000000
+CT=0CA11F122CCD7C259DC597EED3DF9BC4
+
+I=66
+PT=00000000000000004000000000000000
+CT=50109AB4912AD2560B206F331B62EB6C
+
+I=67
+PT=00000000000000002000000000000000
+CT=DBE7C91A4175614889A2D4BEFD64845E
+
+I=68
+PT=00000000000000001000000000000000
+CT=0D3322853A571A6B46B79C0228E0DD25
+
+I=69
+PT=00000000000000000800000000000000
+CT=96E4EE0BB9A11C6FB8522F285BADDEB6
+
+I=70
+PT=00000000000000000400000000000000
+CT=96705C52D2CFCE82E630C93477C79C49
+
+I=71
+PT=00000000000000000200000000000000
+CT=C50130AED6A126149D71F3888C83C232
+
+I=72
+PT=00000000000000000100000000000000
+CT=4816EFE3DEB380566EBA0C17BF582090
+
+I=73
+PT=00000000000000000080000000000000
+CT=0390857B4C8C98E4CF7A2B6F3394C507
+
+I=74
+PT=00000000000000000040000000000000
+CT=422E73A02025EBE8B8B5D6E0FA24FCB2
+
+I=75
+PT=00000000000000000020000000000000
+CT=3271AA7F4BF1D7C38050A43076D4FF76
+
+I=76
+PT=00000000000000000010000000000000
+CT=D2074946F0D37B8975607BFC2E70234C
+
+I=77
+PT=00000000000000000008000000000000
+CT=1A509194C1270AB92E5A42D3A9F8D98B
+
+I=78
+PT=00000000000000000004000000000000
+CT=512438946360CCC4A5C6D73F6EED7130
+
+I=79
+PT=00000000000000000002000000000000
+CT=98CFCDEC46EBEA1A286B3004F2746A0D
+
+I=80
+PT=00000000000000000001000000000000
+CT=A1CF369949677A3AF3D58E3EABF2741B
+
+I=81
+PT=00000000000000000000800000000000
+CT=D84C2E1A0E4A52166FA8FF6889D1E5E2
+
+I=82
+PT=00000000000000000000400000000000
+CT=4AD91CCEEF60119B5078FD162D2735DE
+
+I=83
+PT=00000000000000000000200000000000
+CT=2860793D818E97AAFF1D339D7702438D
+
+I=84
+PT=00000000000000000000100000000000
+CT=6F9068BE73364AE250D89D78A6C9CE6F
+
+I=85
+PT=00000000000000000000080000000000
+CT=024FC3FEF4883FEB1A8DD005305FECCE
+
+I=86
+PT=00000000000000000000040000000000
+CT=08A61FE0816D75EA15EB3C9FB9CCDED6
+
+I=87
+PT=00000000000000000000020000000000
+CT=449C86DFA13F260175CE39797686FFA4
+
+I=88
+PT=00000000000000000000010000000000
+CT=4FFFFC29A59858E1133F2BFB1A8A4817
+
+I=89
+PT=00000000000000000000008000000000
+CT=19425D1F6480B25096561295697DC2B7
+
+I=90
+PT=00000000000000000000004000000000
+CT=31974727ECDD2C77C3A428FC3A8CB3FC
+
+I=91
+PT=00000000000000000000002000000000
+CT=A57CD704B3C95E744D08DF443458F2F5
+
+I=92
+PT=00000000000000000000001000000000
+CT=486D8C193DB1ED73ACB17990442FC40B
+
+I=93
+PT=00000000000000000000000800000000
+CT=5E4DBF4E83AB3BC055B9FCC7A6B3A763
+
+I=94
+PT=00000000000000000000000400000000
+CT=ACF2E0A693FBBCBA4D41B861E0D89E37
+
+I=95
+PT=00000000000000000000000200000000
+CT=32A7CB2AE066A51D2B78FC4B4CFCB608
+
+I=96
+PT=00000000000000000000000100000000
+CT=677D494DBB73CAF55C1990158DA12F14
+
+I=97
+PT=00000000000000000000000080000000
+CT=082A0D2367512ADF0D75A151BFBE0A17
+
+I=98
+PT=00000000000000000000000040000000
+CT=5E5BB7337923C482CE8CBA249E6A8C7D
+
+I=99
+PT=00000000000000000000000020000000
+CT=D3001BA7C7026EE3E5003179530AFCFC
+
+I=100
+PT=00000000000000000000000010000000
+CT=46EC44F8931E629FE8FD8961312EDDE1
+
+I=101
+PT=00000000000000000000000008000000
+CT=C5F8ECD79C7B30E81D17E32079969310
+
+I=102
+PT=00000000000000000000000004000000
+CT=5B8AD6919E24CAEBCC55401AEE0C9802
+
+I=103
+PT=00000000000000000000000002000000
+CT=C2302B7E701B5CC7F8B29E3516DBBFA6
+
+I=104
+PT=00000000000000000000000001000000
+CT=A1D04D6A76F9F7A94D49FAA64A87F244
+
+I=105
+PT=00000000000000000000000000800000
+CT=7FB6F92D35B5CB6C631600EDB9E860BA
+
+I=106
+PT=00000000000000000000000000400000
+CT=B2EF7078BCFACE07AEEC3F9B48830EB3
+
+I=107
+PT=00000000000000000000000000200000
+CT=F475A7493D24C7036E53390374C378B3
+
+I=108
+PT=00000000000000000000000000100000
+CT=B36802AC987377A37BD8EADC97C57D60
+
+I=109
+PT=00000000000000000000000000080000
+CT=ADDCD3D19689C4DDC738CE5F69DC9505
+
+I=110
+PT=00000000000000000000000000040000
+CT=0DAF8CA22884915403C0F0BB1F4BD74F
+
+I=111
+PT=00000000000000000000000000020000
+CT=4AF36BAE2660503B3248E4685059FD05
+
+I=112
+PT=00000000000000000000000000010000
+CT=7D5631814DD8E917D97A0D514C743971
+
+I=113
+PT=00000000000000000000000000008000
+CT=BC3352500FC0CBB9DB5B5F6B491C1BE8
+
+I=114
+PT=00000000000000000000000000004000
+CT=6A4A30BA87E87AF65C90AEB7AFEDC76B
+
+I=115
+PT=00000000000000000000000000002000
+CT=77E6125897668AC8E73E8C79A6FF8336
+
+I=116
+PT=00000000000000000000000000001000
+CT=3FA9D39104EBB323C7AAAA248960DD1E
+
+I=117
+PT=00000000000000000000000000000800
+CT=FAD75AD76AB10ADC49036B250E229D39
+
+I=118
+PT=00000000000000000000000000000400
+CT=2FACAA5FE35B228A16AC74088D702EC4
+
+I=119
+PT=00000000000000000000000000000200
+CT=88B6CBCFDFEF8AD91720A1BB69A1F33E
+
+I=120
+PT=00000000000000000000000000000100
+CT=C7E9D250998632D444356242EF04058D
+
+I=121
+PT=00000000000000000000000000000080
+CT=B14DAD8D3D9153F46C0D3A1AD63C7A05
+
+I=122
+PT=00000000000000000000000000000040
+CT=60ABA678A506608D0845966D29B5F790
+
+I=123
+PT=00000000000000000000000000000020
+CT=482DC43F2388EF25D24144E144BD834E
+
+I=124
+PT=00000000000000000000000000000010
+CT=1490A05A7CEE43BDE98B56E309DC0126
+
+I=125
+PT=00000000000000000000000000000008
+CT=ABFA77CD6E85DA245FB0BDC5E52CFC29
+
+I=126
+PT=00000000000000000000000000000004
+CT=DD4AB1284D4AE17B41E85924470C36F7
+
+I=127
+PT=00000000000000000000000000000002
+CT=CEA7403D4D606B6E074EC5D3BAF39D18
+
+I=128
+PT=00000000000000000000000000000001
+CT=530F8AFBC74536B9A963B4F1C4CB738B
+
+==========
diff --git a/krb5-1-6/src/lib/crypto/aes/test/Readme.txt b/krb5-1-6/src/lib/crypto/aes/test/Readme.txt
new file mode 100644
index 000000000..69dbb5b9c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/Readme.txt
@@ -0,0 +1,22 @@
+README
+
+Algorithm:	Rijndael
+Submitter:	Joan Daemen and Vincent Rijmen
+
+Test values: Known Answer Tests and Monte Carlo Tests
+-----------------------------------------------------------
+
+This directory contains the following files:
+
+Readme.txt: 	This file.
+
+cbc_d_m.txt:	Test values for the CBC decryption MCT.
+cbc_e_m.txt:	Test values for the CBC encryption MCT.
+ecb_d_m.txt:	Test values for the ECB decryption MCT.
+ecb_e_m.txt:	Test values for the ECB encryption MCT.
+ecb_vk.txt: 	Test values for the Variable Key KAT.
+ecb_vt.txt:	      Test values for the Variable Text KAT.
+ecb_iv.txt:	      Test values for the Intermediate Values KAT.
+ecb_iv.readme:	Detailed information about the Intermediate Values KAT.
+ecb_tbl.txt:	Test values for the Table KAT.
+
diff --git a/krb5-1-6/src/lib/crypto/aes/test/cbc_d_m.txt b/krb5-1-6/src/lib/crypto/aes/test/cbc_d_m.txt
new file mode 100644
index 000000000..e216f3b87
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/cbc_d_m.txt
@@ -0,0 +1,7224 @@
+
+=========================
+
+FILENAME:  "cbc_d_m.txt"
+
+Cipher Block Chaining (CBC) Mode - DECRYPTION
+Monte Carlo Test
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+==========
+
+KEYSIZE=128
+
+I=0
+KEY=00000000000000000000000000000000
+IV=00000000000000000000000000000000
+CT=00000000000000000000000000000000
+PT=FACA37E0B0C85373DF706E73F7C9AF86
+
+I=1
+KEY=FACA37E0B0C85373DF706E73F7C9AF86
+IV=52D0C29FF8793A519BD6A8289FC80E6A
+CT=FACA37E0B0C85373DF706E73F7C9AF86
+PT=F5372F9735C5685F1DA362AF6ECB2940
+
+I=2
+KEY=0FFD1877850D3B2CC2D30CDC990286C6
+IV=DD74BB1AC6F0F866C7992C61F59D5594
+CT=F5372F9735C5685F1DA362AF6ECB2940
+PT=5496A4C29C7670F61B5D5DF6181F5947
+
+I=3
+KEY=5B6BBCB5197B4BDAD98E512A811DDF81
+IV=3795C88134F7C011433397D1443FEB3A
+CT=5496A4C29C7670F61B5D5DF6181F5947
+PT=940CC5A2AF4F1F8D1862B47BCF63E4CA
+
+I=4
+KEY=CF677917B6345457C1ECE5514E7E3B4B
+IV=0FC1413900225B47AF9E139E1650EA23
+CT=940CC5A2AF4F1F8D1862B47BCF63E4CA
+PT=08832415D97820DE305A58A9AD111A9E
+
+I=5
+KEY=C7E45D026F4C7489F1B6BDF8E36F21D5
+IV=3032F64674FA243D61DF8C16313D81F3
+CT=08832415D97820DE305A58A9AD111A9E
+PT=BD4089775FD1BDB0A6C4F36D1DDAA93E
+
+I=6
+KEY=7AA4D475309DC93957724E95FEB588EB
+IV=47D7F440B43888F173AE5A492F1A99F8
+CT=BD4089775FD1BDB0A6C4F36D1DDAA93E
+PT=AB9955F74612859267D61FEA85A75ADC
+
+I=7
+KEY=D13D8182768F4CAB30A4517F7B12D237
+IV=6D9E57242195D27771D1C7A748378AB0
+CT=AB9955F74612859267D61FEA85A75ADC
+PT=168F213FB678D8A46D0E55EFD1C49BB3
+
+I=8
+KEY=C7B2A0BDC0F7940F5DAA0490AAD64984
+IV=1B98968FB5ABD95930525C1257DEB364
+CT=168F213FB678D8A46D0E55EFD1C49BB3
+PT=3C4CEECFF9560501C5D8C901D87C8E7B
+
+I=9
+KEY=FBFE4E7239A1910E9872CD9172AAC7FF
+IV=35EB7B6D3F63AAE927C5346C9C2CB91D
+CT=3C4CEECFF9560501C5D8C901D87C8E7B
+PT=9D206BE0CC60296BF3A486A8C69778EF
+
+I=10
+KEY=66DE2592F5C1B8656BD64B39B43DBF10
+IV=226646B36D8E9B9279F94378CCBF8FBA
+CT=9D206BE0CC60296BF3A486A8C69778EF
+PT=9DA7B8094BD0F0BEA26848C84B8E083C
+
+I=11
+KEY=FB799D9BBE1148DBC9BE03F1FFB3B72C
+IV=3E3A2B0E1C70A19BCD7222708AA94F26
+CT=9DA7B8094BD0F0BEA26848C84B8E083C
+PT=6A93B2F318C14C2D3E58455B86A4F5D7
+
+I=12
+KEY=91EA2F68A6D004F6F7E646AA791742FB
+IV=1F256942B3CD691858A20664BB24545E
+CT=6A93B2F318C14C2D3E58455B86A4F5D7
+PT=4A19AC6C6FEB654D3675A2BE32E5A820
+
+I=13
+KEY=DBF38304C93B61BBC193E4144BF2EADB
+IV=631F2EDE05C1C950BCE67DF53BA53ED6
+CT=4A19AC6C6FEB654D3675A2BE32E5A820
+PT=799EAB8E9C864A13490FD6B089F764C5
+
+I=14
+KEY=A26D288A55BD2BA8889C32A4C2058E1E
+IV=F6AD064E0DBF4AF4AA5165E1FE0E86FA
+CT=799EAB8E9C864A13490FD6B089F764C5
+PT=2FA3F38CA1216C6D911C1779F333413E
+
+I=15
+KEY=8DCEDB06F49C47C5198025DD3136CF20
+IV=DA039AC5F4EDCD84472B23CFA1252EC3
+CT=2FA3F38CA1216C6D911C1779F333413E
+PT=2FC703AD6A7DAF8B0BDDD8586C1D67D0
+
+I=16
+KEY=A209D8AB9EE1E84E125DFD855D2BA8F0
+IV=341B5FDA8AB434461A7B7A87EF0C530C
+CT=2FC703AD6A7DAF8B0BDDD8586C1D67D0
+PT=54723CABFBE32DEEDFEBF4292A5710FA
+
+I=17
+KEY=F67BE4006502C5A0CDB609AC777CB80A
+IV=2C42AD577B0BE057555C3FCB6FC0089E
+CT=54723CABFBE32DEEDFEBF4292A5710FA
+PT=6B1E2A8C1A9CBB95D1B34AAFE15A78D3
+
+I=18
+KEY=9D65CE8C7F9E7E351C0543039626C0D9
+IV=E5E06583A834BF16118ED5FA401A2D6F
+CT=6B1E2A8C1A9CBB95D1B34AAFE15A78D3
+PT=F4E57BFAB65375B3AD49CD78814F0C16
+
+I=19
+KEY=6980B576C9CD0B86B14C8E7B1769CCCF
+IV=71E59389FF6F992225B32960593F9362
+CT=F4E57BFAB65375B3AD49CD78814F0C16
+PT=90A31B5934FCF6822526C973114BD953
+
+I=20
+KEY=F923AE2FFD31FD04946A47080622159C
+IV=2A4B31492B9BAEC402C255978BB96D40
+CT=90A31B5934FCF6822526C973114BD953
+PT=61F88BA8D438A0FD23F0101465C7FD4E
+
+I=21
+KEY=98DB258729095DF9B79A571C63E5E8D2
+IV=607640CEA12DCF7F188B2B65C7F4153D
+CT=61F88BA8D438A0FD23F0101465C7FD4E
+PT=F62D206DF53F41CA898F3A8EB6A843FF
+
+I=22
+KEY=6EF605EADC361C333E156D92D54DAB2D
+IV=D69C32E12303361B465BE9A484BCA723
+CT=F62D206DF53F41CA898F3A8EB6A843FF
+PT=364BC3F9FDA5FB1AEEA7691550A58320
+
+I=23
+KEY=58BDC6132193E729D0B2048785E8280D
+IV=C207B8347B8DB8BC6845827BB6986B0E
+CT=364BC3F9FDA5FB1AEEA7691550A58320
+PT=DAA6386A073CD1653E9A9DB0A97970BA
+
+I=24
+KEY=821BFE7926AF364CEE2899372C9158B7
+IV=6C5D2B186393280253D6922A8421C3A9
+CT=DAA6386A073CD1653E9A9DB0A97970BA
+PT=AAF74F0E0A0141A811853AE8B120BC00
+
+I=25
+KEY=28ECB1772CAE77E4FFADA3DF9DB1E4B7
+IV=3CB62EF0E649027DDDB76206D0F4D355
+CT=AAF74F0E0A0141A811853AE8B120BC00
+PT=22A0F9611447C1A85F397DD79E3206F9
+
+I=26
+KEY=0A4C481638E9B64CA094DE080383E24E
+IV=C4320FA90686AE0F9E979CBF1391F6D6
+CT=22A0F9611447C1A85F397DD79E3206F9
+PT=1871ABDEAA7E057E76D41ED9191FAC39
+
+I=27
+KEY=123DE3C89297B332D640C0D11A9C4E77
+IV=FBFD18AADF7C5E8E96EB976A535BF312
+CT=1871ABDEAA7E057E76D41ED9191FAC39
+PT=BF52994F41B1DEF78C6A057642C52D89
+
+I=28
+KEY=AD6F7A87D3266DC55A2AC5A7585963FE
+IV=C195141578ADF4C92113C8A9A63FF072
+CT=BF52994F41B1DEF78C6A057642C52D89
+PT=3EAFB00E3B4A0E6DF74743A7EDAD0FE4
+
+I=29
+KEY=93C0CA89E86C63A8AD6D8600B5F46C1A
+IV=D1C4E98C4A9AC79B7CCBC052ACF78913
+CT=3EAFB00E3B4A0E6DF74743A7EDAD0FE4
+PT=4393544AB2387A93496D683C2B8970C7
+
+I=30
+KEY=D0539EC35A54193BE400EE3C9E7D1CDD
+IV=80517C6341DAF4DCBCCAE452F3040147
+CT=4393544AB2387A93496D683C2B8970C7
+PT=51DAC594293708A918E9EFC04F7F2F1C
+
+I=31
+KEY=81895B5773631192FCE901FCD10233C1
+IV=69DE50406B4E3E8A94C1367E1E3D5464
+CT=51DAC594293708A918E9EFC04F7F2F1C
+PT=035B64F06C8166000C82BF15CC88446D
+
+I=32
+KEY=82D23FA71FE27792F06BBEE91D8A77AC
+IV=8EA2E38145BBD79881B7EB31B8818A21
+CT=035B64F06C8166000C82BF15CC88446D
+PT=F3EFFA770A21741551F309E1967CC2E4
+
+I=33
+KEY=713DC5D015C30387A198B7088BF6B548
+IV=0DCAA309668E11509828152553FF2306
+CT=F3EFFA770A21741551F309E1967CC2E4
+PT=62BA0548E7AD136BEB4E38AECD7942D9
+
+I=34
+KEY=1387C098F26E10EC4AD68FA6468FF791
+IV=D031FCA5F3C88926CC3BDDC448537B69
+CT=62BA0548E7AD136BEB4E38AECD7942D9
+PT=38E3D4C7AF0C3E494F1D580AC5430634
+
+I=35
+KEY=2B64145F5D622EA505CBD7AC83CCF1A5
+IV=6FFA5A45EDA60294B0224EEB8C36C455
+CT=38E3D4C7AF0C3E494F1D580AC5430634
+PT=2231EB6A6588CBCB56B930B7F1CF9E04
+
+I=36
+KEY=0955FF3538EAE56E5372E71B72036FA1
+IV=B5375674631ECC3334A318993CB81F9A
+CT=2231EB6A6588CBCB56B930B7F1CF9E04
+PT=59692274C130D6820287EA10F7E64602
+
+I=37
+KEY=503CDD41F9DA33EC51F50D0B85E529A3
+IV=A93D6E028B5C2BD17A29C6CA1617A0A2
+CT=59692274C130D6820287EA10F7E64602
+PT=5975A95327DE7749EA8DEDC580E5E8C7
+
+I=38
+KEY=09497412DE0444A5BB78E0CE0500C164
+IV=26E00CB161145FCD00C39BC4FB1E5CBB
+CT=5975A95327DE7749EA8DEDC580E5E8C7
+PT=D1F7E36BC8FF4439820CB617E745A9CC
+
+I=39
+KEY=D8BE977916FB009C397456D9E24568A8
+IV=72E78D9E15C8FBA864C6C40CEBB190B8
+CT=D1F7E36BC8FF4439820CB617E745A9CC
+PT=76FB4F20C902E9AA89854440631092B5
+
+I=40
+KEY=AE45D859DFF9E936B0F112998155FA1D
+IV=4B6C585FEF52490EA62BAAD08FAA3DCF
+CT=76FB4F20C902E9AA89854440631092B5
+PT=6D7D4487DCD624B2FC5002DFE7D2D347
+
+I=41
+KEY=C3389CDE032FCD844CA110466687295A
+IV=E94FD23A598DDE077CD1DAEE97FDADD9
+CT=6D7D4487DCD624B2FC5002DFE7D2D347
+PT=7297F8F85B21E1A5CB902DCC5F6738F9
+
+I=42
+KEY=B1AF6426580E2C2187313D8A39E011A3
+IV=86E495D31EEFCBC30064414FBD78FAE5
+CT=7297F8F85B21E1A5CB902DCC5F6738F9
+PT=4A6978AACC6968931FB1B83D53D31FEF
+
+I=43
+KEY=FBC61C8C946744B2988085B76A330E4C
+IV=6BA7664AB5ED4F7956D6C3FAA7C42961
+CT=4A6978AACC6968931FB1B83D53D31FEF
+PT=6B63FAAF9DB43A2B6025F29B1D6A331C
+
+I=44
+KEY=90A5E62309D37E99F8A5772C77593D50
+IV=37D17D1702EA34A3C75376AA0F9D24AD
+CT=6B63FAAF9DB43A2B6025F29B1D6A331C
+PT=8317A07BEE0BF16B88D7D197884AC6CF
+
+I=45
+KEY=13B24658E7D88FF27072A6BBFF13FB9F
+IV=29B89B238062495C260AF44C63AA809F
+CT=8317A07BEE0BF16B88D7D197884AC6CF
+PT=0443BFEBCA7C85CBD0CB66AB9D75425D
+
+I=46
+KEY=17F1F9B32DA40A39A0B9C0106266B9C2
+IV=08CF82854AE07429C4A866AA727CEA2E
+CT=0443BFEBCA7C85CBD0CB66AB9D75425D
+PT=6B1EB033CB844F9BDD96BA2C67D139C7
+
+I=47
+KEY=7CEF4980E62045A27D2F7A3C05B78005
+IV=05579F3E0017EBF6083756DC0A50A2E9
+CT=6B1EB033CB844F9BDD96BA2C67D139C7
+PT=E7904CBFB41EBE4178B4D633AFC9B311
+
+I=48
+KEY=9B7F053F523EFBE3059BAC0FAA7E3314
+IV=E6B2CB0CE57E02A230DCD16C08614823
+CT=E7904CBFB41EBE4178B4D633AFC9B311
+PT=96EAAA148F05FAD1F0FC06E135EC5DF8
+
+I=49
+KEY=0D95AF2BDD3B0132F567AAEE9F926EEC
+IV=4268294B10AD58BE9E570A9485963682
+CT=96EAAA148F05FAD1F0FC06E135EC5DF8
+PT=9F2F712F62DE747EE479A0A74384B196
+
+I=50
+KEY=92BADE04BFE5754C111E0A49DC16DF7A
+IV=A5C558F5D4658089CD9FB295EDAE64DB
+CT=9F2F712F62DE747EE479A0A74384B196
+PT=9CF7F00094C4E2D96D752C2312FC135E
+
+I=51
+KEY=0E4D2E042B2197957C6B266ACEEACC24
+IV=1CE301F294BDF4C906E5F0A6FA7C22BB
+CT=9CF7F00094C4E2D96D752C2312FC135E
+PT=ABA58D548DB6E9BE977FDDC85E16C2DE
+
+I=52
+KEY=A5E8A350A6977E2BEB14FBA290FC0EFA
+IV=66C1FF1E4B52A3542B48306EC33F171D
+CT=ABA58D548DB6E9BE977FDDC85E16C2DE
+PT=802948E1A5177FBE97ABA26B996FDF1B
+
+I=53
+KEY=25C1EBB1038001957CBF59C90993D1E1
+IV=197A546DEB2E19E17507276B9ED95135
+CT=802948E1A5177FBE97ABA26B996FDF1B
+PT=67D931C0946ECDF2F8E41000726D1A56
+
+I=54
+KEY=4218DA7197EECC67845B49C97BFECBB7
+IV=D11DA3CE92ADA0686F7BF12A4796D9F7
+CT=67D931C0946ECDF2F8E41000726D1A56
+PT=386C68821385E8CFCDD5678FE2AA89F8
+
+I=55
+KEY=7A74B2F3846B24A8498E2E469954424F
+IV=4DDE413EBC3F30E2F3A9F48DA1258DAF
+CT=386C68821385E8CFCDD5678FE2AA89F8
+PT=1638C741EFE3B1CC45C7754783350825
+
+I=56
+KEY=6C4C75B26B8895640C495B011A614A6A
+IV=5B4F013B085E3A04A16A409E8C3BB270
+CT=1638C741EFE3B1CC45C7754783350825
+PT=91AB00C3828D3DF72BEC487EF4652567
+
+I=57
+KEY=FDE77571E905A89327A5137FEE046F0D
+IV=98074F522144682FF1498C61581F8B0E
+CT=91AB00C3828D3DF72BEC487EF4652567
+PT=BC5BA874D2F3039837528993FB275EBA
+
+I=58
+KEY=41BCDD053BF6AB0B10F79AEC152331B7
+IV=B65C1A6F80CA024B92176D57061ECDFE
+CT=BC5BA874D2F3039837528993FB275EBA
+PT=B7DE1BEE1867F4DC3F974E0D8B416DB0
+
+I=59
+KEY=F662C6EB23915FD72F60D4E19E625C07
+IV=7268C08FA807D83C9830F54A59F32662
+CT=B7DE1BEE1867F4DC3F974E0D8B416DB0
+PT=19769B9EB30B8DE5FD640ACE78F01F0A
+
+I=60
+KEY=EF145D75909AD232D204DE2FE692430D
+IV=B260792BAB22BAAB6CCF3AE1DD3A0F85
+CT=19769B9EB30B8DE5FD640ACE78F01F0A
+PT=2079F2C0A0DE164CD41FCE29D8CE3178
+
+I=61
+KEY=CF6DAFB53044C47E061B10063E5C7275
+IV=6ABCE7B41E112B91B8E6BC0DBE37600C
+CT=2079F2C0A0DE164CD41FCE29D8CE3178
+PT=0D3A678FAB06E743A9134C103B39B61D
+
+I=62
+KEY=C257C83A9B42233DAF085C160565C468
+IV=CEB1E776DBEF46BF8B949C0AF0EBEAD2
+CT=0D3A678FAB06E743A9134C103B39B61D
+PT=80339ADB34BCDE3384D66170373AEEAC
+
+I=63
+KEY=426452E1AFFEFD0E2BDE3D66325F2AC4
+IV=EAAC373FCA05E610C1C5D4437AFD5631
+CT=80339ADB34BCDE3384D66170373AEEAC
+PT=38D52D75E5783A08FBFE622633D6CF47
+
+I=64
+KEY=7AB17F944A86C706D0205F400189E583
+IV=2A25ED6933CAAA95569ADA1AC7480942
+CT=38D52D75E5783A08FBFE622633D6CF47
+PT=3204F1EACBB520A69F0939F45BC82041
+
+I=65
+KEY=48B58E7E8133E7A04F2966B45A41C5C2
+IV=9C6819799DAF61111ACC3C0ECEB0F8BF
+CT=3204F1EACBB520A69F0939F45BC82041
+PT=16BD33EE541798BEE114E9D7F9141A9C
+
+I=66
+KEY=5E08BD90D5247F1EAE3D8F63A355DF5E
+IV=C181F4DF1EE0E13BF76044A3DA5E3BC4
+CT=16BD33EE541798BEE114E9D7F9141A9C
+PT=A0A68CF016C6AD8DAC4D5634EAADEBE5
+
+I=67
+KEY=FEAE3160C3E2D2930270D95749F834BB
+IV=2A4EE2CD011AF421616789DB790354FD
+CT=A0A68CF016C6AD8DAC4D5634EAADEBE5
+PT=FCE7D92FD0B3A1C7920558F653E1019B
+
+I=68
+KEY=0249E84F13517354907581A11A193520
+IV=A7F7E2B701F34F308C0F28514DFAA15F
+CT=FCE7D92FD0B3A1C7920558F653E1019B
+PT=F16A084B2DE16D5E3E5405665DE3C623
+
+I=69
+KEY=F323E0043EB01E0AAE2184C747FAF303
+IV=6D319828AAA75DFE99BEEDD21B983C7D
+CT=F16A084B2DE16D5E3E5405665DE3C623
+PT=CE20AE629887DF02064F2D9DB092E1DB
+
+I=70
+KEY=3D034E66A637C108A86EA95AF76812D8
+IV=9484E76149F41901AF8AFD3152C56506
+CT=CE20AE629887DF02064F2D9DB092E1DB
+PT=B457A655282213C1B7C5C2A206C7FCB9
+
+I=71
+KEY=8954E8338E15D2C91FAB6BF8F1AFEE61
+IV=329E089DC915BD71B1F8D0713BFC4F97
+CT=B457A655282213C1B7C5C2A206C7FCB9
+PT=A89B8F7541FFF719A3C7DE1577CE1C3F
+
+I=72
+KEY=21CF6746CFEA25D0BC6CB5ED8661F25E
+IV=FA381CAC5777234E6DF8A28A4E6671D8
+CT=A89B8F7541FFF719A3C7DE1577CE1C3F
+PT=C4E73D25647350527C1F93F6C1D90296
+
+I=73
+KEY=E5285A63AB997582C073261B47B8F0C8
+IV=082ACF3D2661514F0E00BDABC9015946
+CT=C4E73D25647350527C1F93F6C1D90296
+PT=34BF6DECECFE1C9AE3AA34B6DB3741EF
+
+I=74
+KEY=D197378F4767691823D912AD9C8FB127
+IV=3E56B658F899B6DBBA4EAF6E629F3555
+CT=34BF6DECECFE1C9AE3AA34B6DB3741EF
+PT=FD86C78538176DC5D48BE2EC6B89D581
+
+I=75
+KEY=2C11F00A7F7004DDF752F041F70664A6
+IV=765B823193F2738E6CACBB0154C941B1
+CT=FD86C78538176DC5D48BE2EC6B89D581
+PT=524E035AB9DEB29E467B9586A90F3A42
+
+I=76
+KEY=7E5FF350C6AEB643B12965C75E095EE4
+IV=DE2B3EC0A3FF29EC67BBE1B124E9451A
+CT=524E035AB9DEB29E467B9586A90F3A42
+PT=83DE1E768EED94BA09E623845A057834
+
+I=77
+KEY=FD81ED26484322F9B8CF4643040C26D0
+IV=A5CF4D996D8460E71DDA938461BB884B
+CT=83DE1E768EED94BA09E623845A057834
+PT=D8381D17B9BCF942F408DBB2B7B2D6B7
+
+I=78
+KEY=25B9F031F1FFDBBB4CC79DF1B3BEF067
+IV=899696B8EDC4E8B60489742A2559C909
+CT=D8381D17B9BCF942F408DBB2B7B2D6B7
+PT=BF1D8175015D0A0341427DE1F7DDE379
+
+I=79
+KEY=9AA47144F0A2D1B80D85E0104463131E
+IV=AD76D13B2F2A3F938F5C810A38A83D09
+CT=BF1D8175015D0A0341427DE1F7DDE379
+PT=58114DEFF8CFF10F06B390EB01B13394
+
+I=80
+KEY=C2B53CAB086D20B70B3670FB45D2208A
+IV=9EC540C144AB57D4E5A9185F55E71E50
+CT=58114DEFF8CFF10F06B390EB01B13394
+PT=53E72B9603CE221F0160791DF51F6B3E
+
+I=81
+KEY=9152173D0BA302A80A5609E6B0CD4BB4
+IV=B780257238CA60FD998819B2D04CEB92
+CT=53E72B9603CE221F0160791DF51F6B3E
+PT=AF0238554AAFFB0FB5DFAC35E3CE8F4C
+
+I=82
+KEY=3E502F68410CF9A7BF89A5D35303C4F8
+IV=3509BC884089ADEB90137A39AEA75CFC
+CT=AF0238554AAFFB0FB5DFAC35E3CE8F4C
+PT=20844D3F4F637B974D38B7E5F1C84205
+
+I=83
+KEY=1ED462570E6F8230F2B11236A2CB86FD
+IV=52BAB07EB72804630E4BD769F0172FDA
+CT=20844D3F4F637B974D38B7E5F1C84205
+PT=68404E006D2F16572EDFAE636A62C537
+
+I=84
+KEY=76942C5763409467DC6EBC55C8A943CA
+IV=E4B417D85F36F3A25CF04AB05157F247
+CT=68404E006D2F16572EDFAE636A62C537
+PT=13C8DF4117D4EA3645F1825700F8FFA5
+
+I=85
+KEY=655CF31674947E51999F3E02C851BC6F
+IV=3FE0683442B6B5DF515209DE16F8FD4B
+CT=13C8DF4117D4EA3645F1825700F8FFA5
+PT=42307D929439F2723202A5206D640431
+
+I=86
+KEY=276C8E84E0AD8C23AB9D9B22A535B85E
+IV=33FAD11D9D4057E7ED989F1520450C32
+CT=42307D929439F2723202A5206D640431
+PT=5ED8AF875ACF37BE8FAAC16D4AB8072B
+
+I=87
+KEY=79B42103BA62BB9D24375A4FEF8DBF75
+IV=807852E5AD0EB5E0C3A2AAF18DFB14F9
+CT=5ED8AF875ACF37BE8FAAC16D4AB8072B
+PT=79C950A45ECDC8B676A5CFF324A81DA8
+
+I=88
+KEY=007D71A7E4AF732B529295BCCB25A2DD
+IV=516BC35B52C26C99E21C0147CB7DD99E
+CT=79C950A45ECDC8B676A5CFF324A81DA8
+PT=595C3DDCFBD90661A3A70B94C470A26B
+
+I=89
+KEY=59214C7B1F76754AF1359E280F5500B6
+IV=FDABDD4BD60725F5E640629416F417D3
+CT=595C3DDCFBD90661A3A70B94C470A26B
+PT=7957CF3989083D25B54C6890EC58DB0C
+
+I=90
+KEY=20768342967E486F4479F6B8E30DDBBA
+IV=CADFADF417898DE3786D5DF869396611
+CT=7957CF3989083D25B54C6890EC58DB0C
+PT=6C1E8DF34FC80DD2ECA00A1EDC5FC239
+
+I=91
+KEY=4C680EB1D9B645BDA8D9FCA63F521983
+IV=A7DF9FA44AA2B49B9E26C6148CCAF36F
+CT=6C1E8DF34FC80DD2ECA00A1EDC5FC239
+PT=72B5A426C9DC3B336756FB10B00626CE
+
+I=92
+KEY=3EDDAA97106A7E8ECF8F07B68F543F4D
+IV=50FF574915D407A97A74CC399DE2D901
+CT=72B5A426C9DC3B336756FB10B00626CE
+PT=194826159D7FAB9166D64F1DD6F627B0
+
+I=93
+KEY=27958C828D15D51FA95948AB59A218FD
+IV=A1E3BC848C019B6FC3F7072F9A866C52
+CT=194826159D7FAB9166D64F1DD6F627B0
+PT=0186B2316FC29104D3549C49F92AE414
+
+I=94
+KEY=26133EB3E2D7441B7A0DD4E2A088FCE9
+IV=4DBA42F1031AE32016524C7F86781528
+CT=0186B2316FC29104D3549C49F92AE414
+PT=373384DB7383D3A4914C0141BB104B81
+
+I=95
+KEY=1120BA68915497BFEB41D5A31B98B768
+IV=FFCB87107AC596D71BA807902D524247
+CT=373384DB7383D3A4914C0141BB104B81
+PT=25465CE5FA2AD65D75586064A18516A8
+
+I=96
+KEY=3466E68D6B7E41E29E19B5C7BA1DA1C0
+IV=55879596C3F0A295FA00CFEF1B056248
+CT=25465CE5FA2AD65D75586064A18516A8
+PT=2311A52CEC4A16B5F4FCA613BC0BDB83
+
+I=97
+KEY=177743A1873457576AE513D406167A43
+IV=B1A7DABF3D2384BF8754B829659B3989
+CT=2311A52CEC4A16B5F4FCA613BC0BDB83
+PT=357F4BF62308CD5C48F34E9E644DD515
+
+I=98
+KEY=22080857A43C9A0B22165D4A625BAF56
+IV=72BF477FE8CF428CFA856323E18B3135
+CT=357F4BF62308CD5C48F34E9E644DD515
+PT=17758539D1896B92BFB811D30C9BA134
+
+I=99
+KEY=357D8D6E75B5F1999DAE4C996EC00E62
+IV=4CBA048DFA50910EC94FE5D6AA5DD502
+CT=17758539D1896B92BFB811D30C9BA134
+PT=372B6DCEE44D18D3791C4E8FB0A91971
+
+I=100
+KEY=0256E0A091F8E94AE4B20216DE691713
+IV=86F4F670CA3B191B860D6C8A9A35A872
+CT=372B6DCEE44D18D3791C4E8FB0A91971
+PT=66D3FABC4885C1F4897D9160C152D570
+
+I=101
+KEY=64851A1CD97D28BE6DCF93761F3BC263
+IV=08490B2E8588FE564F0112D76D6108E9
+CT=66D3FABC4885C1F4897D9160C152D570
+PT=926278E71894F32B5E2A5A1F5FA695E7
+
+I=102
+KEY=F6E762FBC1E9DB9533E5C969409D5784
+IV=D3A2E4AFFDD8A7CC1498EF0E812087B7
+CT=926278E71894F32B5E2A5A1F5FA695E7
+PT=A455F5D65D91563D9C15E6B745F29531
+
+I=103
+KEY=52B2972D9C788DA8AFF02FDE056FC2B5
+IV=6CB8822EA67C247A6A0CBAD830B3562C
+CT=A455F5D65D91563D9C15E6B745F29531
+PT=4544371A5E3A8E7AD9885AECD3868AF3
+
+I=104
+KEY=17F6A037C24203D276787532D6E94846
+IV=93E3CAD8BE023F6451ADAA525988A974
+CT=4544371A5E3A8E7AD9885AECD3868AF3
+PT=8473F4F1D77AC1F46706EBD108CB48A5
+
+I=105
+KEY=938554C61538C226117E9EE3DE2200E3
+IV=A7E7B354606EF4C1D00BF4F128CCE966
+CT=8473F4F1D77AC1F46706EBD108CB48A5
+PT=787ADE453DCE2FA7F6F24CD33C9A5CDC
+
+I=106
+KEY=EBFF8A8328F6ED81E78CD230E2B85C3F
+IV=97A2CF706C1871B502D15B028C5F0D80
+CT=787ADE453DCE2FA7F6F24CD33C9A5CDC
+PT=E6A7E5B65DC124FBE1C1FFFE18A34D8A
+
+I=107
+KEY=0D586F357537C97A064D2DCEFA1B11B5
+IV=9BBDCAF2A3CC7FC5BF6285631A4636FD
+CT=E6A7E5B65DC124FBE1C1FFFE18A34D8A
+PT=6A391E9F475546720836312BBEB0B3A9
+
+I=108
+KEY=676171AA32628F080E7B1CE544ABA21C
+IV=603EEDE91F925A2228537E8BDD26C96B
+CT=6A391E9F475546720836312BBEB0B3A9
+PT=D75086BA446563AAB1873FDEBE611D67
+
+I=109
+KEY=B031F7107607ECA2BFFC233BFACABF7B
+IV=546B8CA37AACE2BC2C85014F2ACD6315
+CT=D75086BA446563AAB1873FDEBE611D67
+PT=63A4D826625CBD9F10083E62330BCFBC
+
+I=110
+KEY=D3952F36145B513DAFF41D59C9C170C7
+IV=BC2E6E9DD10152C8281B798F711A9334
+CT=63A4D826625CBD9F10083E62330BCFBC
+PT=41275EFDFC86B5BDCCCDCA2BBFA5B90D
+
+I=111
+KEY=92B271CBE8DDE4806339D7727664C9CA
+IV=D940A8D1B3448AA9148C7F6DFC266B00
+CT=41275EFDFC86B5BDCCCDCA2BBFA5B90D
+PT=56AC1BCB285044710D26EFC42A0ABA56
+
+I=112
+KEY=C41E6A00C08DA0F16E1F38B65C6E739C
+IV=214238FF5F4D01F3A6694EC80E15BCF7
+CT=56AC1BCB285044710D26EFC42A0ABA56
+PT=5AF2877973AB9787E42202AC0C6E7538
+
+I=113
+KEY=9EECED79B32637768A3D3A1A500006A4
+IV=561B4934904E327F3B3639CED6C7A995
+CT=5AF2877973AB9787E42202AC0C6E7538
+PT=787F52F6D9CD9085D782B95FD68F70F8
+
+I=114
+KEY=E693BF8F6AEBA7F35DBF8345868F765C
+IV=06B93FB1A99BD387A091509B8C6D3482
+CT=787F52F6D9CD9085D782B95FD68F70F8
+PT=E7B1DB917C92E488C6B02AC4C42AFD79
+
+I=115
+KEY=0122641E1679437B9B0FA98142A58B25
+IV=1D57A61FED51218BD8C1357CE58F21EB
+CT=E7B1DB917C92E488C6B02AC4C42AFD79
+PT=2FBAB770D511EACA849F654DE429DE84
+
+I=116
+KEY=2E98D36EC368A9B11F90CCCCA68C55A1
+IV=CB311C43EC32D59941CEF81BB9CF4E57
+CT=2FBAB770D511EACA849F654DE429DE84
+PT=A8FE17AEA961C2A450DD5EAABAA19613
+
+I=117
+KEY=8666C4C06A096B154F4D92661C2DC3B2
+IV=B9D7B74D62DD89A01EE3093A5C2A0470
+CT=A8FE17AEA961C2A450DD5EAABAA19613
+PT=D9E598A4DBAF82BDF9474BE13B997FF5
+
+I=118
+KEY=5F835C64B1A6E9A8B60AD98727B4BC47
+IV=6398D8A38C38A9B54DCF18C0D76758BA
+CT=D9E598A4DBAF82BDF9474BE13B997FF5
+PT=291DB2BC325CD7A94032E7C1208921A5
+
+I=119
+KEY=769EEED883FA3E01F6383E46073D9DE2
+IV=4774C7E1BB97117BCA26A897B9302EFA
+CT=291DB2BC325CD7A94032E7C1208921A5
+PT=DFC55866F85055F06E752E04AAC4C36A
+
+I=120
+KEY=A95BB6BE7BAA6BF1984D1042ADF95E88
+IV=BDA0616700CD2817FE4425F6F541E8C1
+CT=DFC55866F85055F06E752E04AAC4C36A
+PT=7CACB3A88E7114F7737B05D0FB3AF7F3
+
+I=121
+KEY=D5F70516F5DB7F06EB36159256C3A97B
+IV=1EF4836BD363B89EE73911B14EBE9262
+CT=7CACB3A88E7114F7737B05D0FB3AF7F3
+PT=3282F1F6B3C04E325FB13E85D18CDBBC
+
+I=122
+KEY=E775F4E0461B3134B4872B17874F72C7
+IV=E35D47CEDBD30701A64FE504C6BC4199
+CT=3282F1F6B3C04E325FB13E85D18CDBBC
+PT=BFB9748A3C825CDA3EA5D001F6AD305F
+
+I=123
+KEY=58CC806A7A996DEE8A22FB1671E24298
+IV=7A3676377E0B4F815B4B8C9A98DCAB4D
+CT=BFB9748A3C825CDA3EA5D001F6AD305F
+PT=B33787380A4C3BD5B32EC335916F9229
+
+I=124
+KEY=EBFB075270D5563B390C3823E08DD0B1
+IV=B3E40B27DBF6D985D4F57BD4D2899DC8
+CT=B33787380A4C3BD5B32EC335916F9229
+PT=BCD5E40A3B4885ACA82BEC952BA8A973
+
+I=125
+KEY=572EE3584B9DD3979127D4B6CB2579C2
+IV=897608FE3238F80CD24192CC64F4F695
+CT=BCD5E40A3B4885ACA82BEC952BA8A973
+PT=793E22E0B01FFE63E89C84A0D0FE1216
+
+I=126
+KEY=2E10C1B8FB822DF479BB50161BDB6BD4
+IV=D84401CF83566FEA8FB859C446C22632
+CT=793E22E0B01FFE63E89C84A0D0FE1216
+PT=96858A96FEB19712B10A44FBF8E633D9
+
+I=127
+KEY=B8954B2E0533BAE6C8B114EDE33D580D
+IV=7210E127BFB706EF9CD24139C0927E01
+CT=96858A96FEB19712B10A44FBF8E633D9
+PT=28A34CC75A215117331D6B88387E16F8
+
+I=128
+KEY=903607E95F12EBF1FBAC7F65DB434EF5
+IV=744B8DD281919F79FC529DA15AA0F18F
+CT=28A34CC75A215117331D6B88387E16F8
+PT=43FE41DC9FFB88F93ADC43D41BA3E4B2
+
+I=129
+KEY=D3C84635C0E96308C1703CB1C0E0AA47
+IV=5C7379A90F1E47F88C7424E8CD31E55D
+CT=43FE41DC9FFB88F93ADC43D41BA3E4B2
+PT=66D6D0E84CEB8672D38DDE557CCCFFF6
+
+I=130
+KEY=B51E96DD8C02E57A12FDE2E4BC2C55B1
+IV=529B92CD068415627C4BE49874347F98
+CT=66D6D0E84CEB8672D38DDE557CCCFFF6
+PT=F817D013CB041CA41B6D611ED261FAE9
+
+I=131
+KEY=4D0946CE4706F9DE099083FA6E4DAF58
+IV=9B4452DD48C3EECEFDB6A6CFAE670117
+CT=F817D013CB041CA41B6D611ED261FAE9
+PT=56420C70CC459A131CD531EDC39ED6E9
+
+I=132
+KEY=1B4B4ABE8B4363CD1545B217ADD379B1
+IV=264ABBC30CC98DA3C06B935B1364A317
+CT=56420C70CC459A131CD531EDC39ED6E9
+PT=650DA8C4CB11E4ABFE8841D20443BB04
+
+I=133
+KEY=7E46E27A40528766EBCDF3C5A990C2B5
+IV=DBABF7B18568FED50C69DA0C9AA5395D
+CT=650DA8C4CB11E4ABFE8841D20443BB04
+PT=94E6CE02AE253F3BE4A59775CAB7B11B
+
+I=134
+KEY=EAA02C78EE77B85D0F6864B0632773AE
+IV=F0D2E456CE063CB68988C1C397038480
+CT=94E6CE02AE253F3BE4A59775CAB7B11B
+PT=124F09DAC6A45E6077DCECE971B24ED1
+
+I=135
+KEY=F8EF25A228D3E63D78B4885912953D7F
+IV=C19A6D2D35E606E552580B002023C966
+CT=124F09DAC6A45E6077DCECE971B24ED1
+PT=AAD649FD1168DFCB431A7216571ED4C1
+
+I=136
+KEY=52396C5F39BB39F63BAEFA4F458BE9BE
+IV=DF1A307B1D25BC2751ECDC791EC51B16
+CT=AAD649FD1168DFCB431A7216571ED4C1
+PT=992749C940CBBB0944F5248E8D65268C
+
+I=137
+KEY=CB1E2596797082FF7F5BDEC1C8EECF32
+IV=D8B0466FC4344C6BF4E57584E5F48A36
+CT=992749C940CBBB0944F5248E8D65268C
+PT=FF16B9246C325A3B96250875A9D5C4BE
+
+I=138
+KEY=34089CB21542D8C4E97ED6B4613B0B8C
+IV=B8C3E4ECF57631CE1EEA74AD99545BA2
+CT=FF16B9246C325A3B96250875A9D5C4BE
+PT=72EDB906165FE6A19E02435AC6457C9A
+
+I=139
+KEY=46E525B4031D3E65777C95EEA77E7716
+IV=9C4F78D05257C64D752C576B5BB16245
+CT=72EDB906165FE6A19E02435AC6457C9A
+PT=0C2F00362B8733D343DCAF884A6BFD46
+
+I=140
+KEY=4ACA2582289A0DB634A03A66ED158A50
+IV=C51122198D2FD566ACA1BD07C28BCC7A
+CT=0C2F00362B8733D343DCAF884A6BFD46
+PT=C7F5C00F42695CF7870240DA73D487F7
+
+I=141
+KEY=8D3FE58D6AF35141B3A27ABC9EC10DA7
+IV=14769B7962371925822C42F0411BDC65
+CT=C7F5C00F42695CF7870240DA73D487F7
+PT=F4BC8A4310A4CD2F396F43B81BD060EB
+
+I=142
+KEY=79836FCE7A579C6E8ACD390485116D4C
+IV=CDA4414DF23427B937D586C1A8164479
+CT=F4BC8A4310A4CD2F396F43B81BD060EB
+PT=1B996A525174C35466103BCBD53ECB9C
+
+I=143
+KEY=621A059C2B235F3AECDD02CF502FA6D0
+IV=1DA9E7C02BE868E118E4B9BF5928BFCF
+CT=1B996A525174C35466103BCBD53ECB9C
+PT=2B4EC5CB9DE50257B5901C6D49B5EB54
+
+I=144
+KEY=4954C057B6C65D6D594D1EA2199A4D84
+IV=55433149AA93215BF53CB8FE66CD683A
+CT=2B4EC5CB9DE50257B5901C6D49B5EB54
+PT=5A5B9ACA3BDA951DC4C4DFB7DD15AD18
+
+I=145
+KEY=130F5A9D8D1CC8709D89C115C48FE09C
+IV=695C69EA8C4257D2758364AFF6387DA0
+CT=5A5B9ACA3BDA951DC4C4DFB7DD15AD18
+PT=5BB08593BA52E94F07CB14FF564AF299
+
+I=146
+KEY=48BFDF0E374E213F9A42D5EA92C51205
+IV=665463164601CD0045C684729CDD5E7D
+CT=5BB08593BA52E94F07CB14FF564AF299
+PT=DB1840467889551150026A90E3FC272F
+
+I=147
+KEY=93A79F484FC7742ECA40BF7A7139352A
+IV=355C4B87A682712460C80ABA630F7BE8
+CT=DB1840467889551150026A90E3FC272F
+PT=9F7BD8EF96A1ECC75B4E3031E65FE8FC
+
+I=148
+KEY=0CDC47A7D96698E9910E8F4B9766DDD6
+IV=FBF20FEC0A9E9B530DD3745955A1960C
+CT=9F7BD8EF96A1ECC75B4E3031E65FE8FC
+PT=DCF003E1DDD4B52F5B680568B42EEECF
+
+I=149
+KEY=D02C444604B22DC6CA668A2323483319
+IV=04EADC638E309466B9500B1C3A308856
+CT=DCF003E1DDD4B52F5B680568B42EEECF
+PT=DDD2F2AEFEF4A4641747699170DF0129
+
+I=150
+KEY=0DFEB6E8FA4689A2DD21E3B253973230
+IV=FB521123E5BB45F1AC7083C382B95E10
+CT=DDD2F2AEFEF4A4641747699170DF0129
+PT=7D6C54E4369E965513DE1E95E8A37433
+
+I=151
+KEY=7092E20CCCD81FF7CEFFFD27BB344603
+IV=0E71300101915AEE97563493B4B2EFB9
+CT=7D6C54E4369E965513DE1E95E8A37433
+PT=B7F5C4275EF7D3A23E8E9A4BC2BCA700
+
+I=152
+KEY=C767262B922FCC55F071676C7988E103
+IV=8BBC970D4E24F6F1A92859BBAE70B757
+CT=B7F5C4275EF7D3A23E8E9A4BC2BCA700
+PT=679FA9A8AB3EE2F0663D4DC95FEC3847
+
+I=153
+KEY=A0F88F8339112EA5964C2AA52664D944
+IV=B8D28B6903859465F996A0DF491DDAAA
+CT=679FA9A8AB3EE2F0663D4DC95FEC3847
+PT=914DCEAC5B00940A415C2144DAA1EF03
+
+I=154
+KEY=31B5412F6211BAAFD7100BE1FCC53647
+IV=06E1FF99E63E0EDDA1D95682B541D026
+CT=914DCEAC5B00940A415C2144DAA1EF03
+PT=A718031A531395DA071B828A10A2B9DC
+
+I=155
+KEY=96AD423531022F75D00B896BEC678F9B
+IV=F18546028693CC0A72E218460AC932E9
+CT=A718031A531395DA071B828A10A2B9DC
+PT=19D996B9FF549029D800CF977C0E0A88
+
+I=156
+KEY=8F74D48CCE56BF5C080B46FC90698513
+IV=7E98DAFA8DE35537A0B0AA8FA32E01DF
+CT=19D996B9FF549029D800CF977C0E0A88
+PT=6A7D514FBE9963987E0EE5DD22FDC8BD
+
+I=157
+KEY=E50985C370CFDCC47605A321B2944DAE
+IV=071F44277D12AD6E653FB747C11BEFB7
+CT=6A7D514FBE9963987E0EE5DD22FDC8BD
+PT=AB07C464DF72DF58411A7CBF906F43A6
+
+I=158
+KEY=4E0E41A7AFBD039C371FDF9E22FB0E08
+IV=BDA8979A0DE78999AE0659D2744BC21B
+CT=AB07C464DF72DF58411A7CBF906F43A6
+PT=A8ABC34FF51FD998427A7837BB0F22BB
+
+I=159
+KEY=E6A582E85AA2DA047565A7A999F42CB3
+IV=3CA763C4375A6C70F072B52C42A02560
+CT=A8ABC34FF51FD998427A7837BB0F22BB
+PT=9E82A41AB2A2748695663075C5BF1C09
+
+I=160
+KEY=782726F2E800AE82E00397DC5C4B30BA
+IV=B1DD4DC8715CA0B8BA3426395B61ABA4
+CT=9E82A41AB2A2748695663075C5BF1C09
+PT=3C891AEFC6645F3C23A2E3A2E1A522EF
+
+I=161
+KEY=44AE3C1D2E64F1BEC3A1747EBDEE1255
+IV=932F28E3FC0F85A0E703AD6079A68CC0
+CT=3C891AEFC6645F3C23A2E3A2E1A522EF
+PT=D4FDD9C3D36E80E0AFA95ABEC2E62FB9
+
+I=162
+KEY=9053E5DEFD0A715E6C082EC07F083DEC
+IV=1AD1530DE6274BBA3A097004D85DF8FA
+CT=D4FDD9C3D36E80E0AFA95ABEC2E62FB9
+PT=9FACBB106FBF34D9B25A83AD4F45AA38
+
+I=163
+KEY=0FFF5ECE92B54587DE52AD6D304D97D4
+IV=8412EAA361AB8193AD529FA36944FE3D
+CT=9FACBB106FBF34D9B25A83AD4F45AA38
+PT=E95628B6A14326AC153B228C0DD25063
+
+I=164
+KEY=E6A9767833F6632BCB698FE13D9FC7B7
+IV=9F1D906FD25CCCA7565D82CDA44B4A57
+CT=E95628B6A14326AC153B228C0DD25063
+PT=7B1ECD07E452D593D00E326F8FD9F2B5
+
+I=165
+KEY=9DB7BB7FD7A4B6B81B67BD8EB2463502
+IV=9C91B12734A86451492400EE5759C190
+CT=7B1ECD07E452D593D00E326F8FD9F2B5
+PT=A99874C1ECA463D335B37179348AEF4F
+
+I=166
+KEY=342FCFBE3B00D56B2ED4CCF786CCDA4D
+IV=9060C6E8E2B51E5F1000860ECB5A608C
+CT=A99874C1ECA463D335B37179348AEF4F
+PT=F9296E658C3048C58FE6404AB6E0186C
+
+I=167
+KEY=CD06A1DBB7309DAEA1328CBD302CC221
+IV=ADCB427405EDF8078622AFC6C731D3EF
+CT=F9296E658C3048C58FE6404AB6E0186C
+PT=8D3A4ABFB8F57AEBB1284B78BFDD240D
+
+I=168
+KEY=403CEB640FC5E745101AC7C58FF1E62C
+IV=4CED30477756892A49FE6358700F5DE7
+CT=8D3A4ABFB8F57AEBB1284B78BFDD240D
+PT=7C71310D5241B8B461847FA7E2B4D506
+
+I=169
+KEY=3C4DDA695D845FF1719EB8626D45332A
+IV=52A3B8E21588368AA3AD2131B283B34C
+CT=7C71310D5241B8B461847FA7E2B4D506
+PT=380A1E2925FC8061FBC69B08B4C7C6C8
+
+I=170
+KEY=0447C4407878DF908A58236AD982F5E2
+IV=B7AD265DF50ABD77C1D1D02BAF06CEBD
+CT=380A1E2925FC8061FBC69B08B4C7C6C8
+PT=6931E262570F27732A75629A384492CA
+
+I=171
+KEY=6D7626222F77F8E3A02D41F0E1C66728
+IV=DD7D3CA7F6CE54775836734B10685A99
+CT=6931E262570F27732A75629A384492CA
+PT=336D0AB3F9A793469C544E98CFDC8AD6
+
+I=172
+KEY=5E1B2C91D6D06BA53C790F682E1AEDFE
+IV=54087C05437049FBAFC9BF6C56AD16CC
+CT=336D0AB3F9A793469C544E98CFDC8AD6
+PT=0098A640F1D04E5557F748B80215082A
+
+I=173
+KEY=5E838AD1270025F06B8E47D02C0FE5D4
+IV=DD13A93C7FAEF14820D6A168AF9969DB
+CT=0098A640F1D04E5557F748B80215082A
+PT=48660EDDC3ACAC1A814AE088650DE007
+
+I=174
+KEY=16E5840CE4AC89EAEAC4A758490205D3
+IV=589C43A680F7AE6E15DE25FD50F18BED
+CT=48660EDDC3ACAC1A814AE088650DE007
+PT=047740C48160A14563C0049316C7B78E
+
+I=175
+KEY=1292C4C865CC28AF8904A3CB5FC5B25D
+IV=22DB095AF8268D37AC536FDA3A81B7C2
+CT=047740C48160A14563C0049316C7B78E
+PT=D9679ABB1AED1524E8DA2ECA89172853
+
+I=176
+KEY=CBF55E737F213D8B61DE8D01D6D29A0E
+IV=77FDCCC9BAB3B7E81D7B9D14540ED3A7
+CT=D9679ABB1AED1524E8DA2ECA89172853
+PT=C774AD9EF683A59747AB41DA044471C4
+
+I=177
+KEY=0C81F3ED89A2981C2675CCDBD296EBCA
+IV=2E266970512C0F6D404367978C70B5C6
+CT=C774AD9EF683A59747AB41DA044471C4
+PT=927C98AFDE6F108268A306A1A818EE89
+
+I=178
+KEY=9EFD6B4257CD889E4ED6CA7A7A8E0543
+IV=E2B0A0F146E931136932D8188B7DC980
+CT=927C98AFDE6F108268A306A1A818EE89
+PT=D3C11AF1EF255D65EAAEE5B5C5BF3CD9
+
+I=179
+KEY=4D3C71B3B8E8D5FBA4782FCFBF31399A
+IV=ABA118A590A8A69D41D20ED13F7DA4C9
+CT=D3C11AF1EF255D65EAAEE5B5C5BF3CD9
+PT=760B1C47EB476A246CE41163B7425C7B
+
+I=180
+KEY=3B376DF453AFBFDFC89C3EAC087365E1
+IV=8A395FFEE93FF820FBC086932216324F
+CT=760B1C47EB476A246CE41163B7425C7B
+PT=4EEAE25D1654A461D6A56896EDFFEAB7
+
+I=181
+KEY=75DD8FA945FB1BBE1E39563AE58C8F56
+IV=82D68DE458D38127E2A17DA736BC1651
+CT=4EEAE25D1654A461D6A56896EDFFEAB7
+PT=BD7ABD27F3515B9FD337ADADBA5E9EC9
+
+I=182
+KEY=C8A7328EB6AA4021CD0EFB975FD2119F
+IV=95757C38F4CB26C29DF174FD8B1F35E8
+CT=BD7ABD27F3515B9FD337ADADBA5E9EC9
+PT=E32EF56DE91CC21C158822BDB841A02C
+
+I=183
+KEY=2B89C7E35FB6823DD886D92AE793B1B3
+IV=AFFB434005E300E99E815A8E5B46E159
+CT=E32EF56DE91CC21C158822BDB841A02C
+PT=578B7692D68BD4D65A159C9CCDC81F64
+
+I=184
+KEY=7C02B171893D56EB829345B62A5BAED7
+IV=15E783551969F275EF25A429F68BA0DB
+CT=578B7692D68BD4D65A159C9CCDC81F64
+PT=0F70D77F31DE8F0010628377C8E4A1C3
+
+I=185
+KEY=7372660EB8E3D9EB92F1C6C1E2BF0F14
+IV=078B6E3FC7C79D52A5C49847A7C5D0BB
+CT=0F70D77F31DE8F0010628377C8E4A1C3
+PT=A4F29F6A50A4A15789D4647774C96997
+
+I=186
+KEY=D780F964E84778BC1B25A2B696766683
+IV=C9B2C903F131856C0D8218146479513A
+CT=A4F29F6A50A4A15789D4647774C96997
+PT=7AD4F764911F8F1E8C9356F00B1468EE
+
+I=187
+KEY=AD540E007958F7A297B6F4469D620E6D
+IV=780DAD9DBA12DDC713ECF44057B8B56E
+CT=7AD4F764911F8F1E8C9356F00B1468EE
+PT=A00EAFD28A95C7F39137773F28F9A0D3
+
+I=188
+KEY=0D5AA1D2F3CD305106818379B59BAEBE
+IV=6643BF26488FB21BCDAA7D4FABAA5BC3
+CT=A00EAFD28A95C7F39137773F28F9A0D3
+PT=FC884EEEB73B2F66C97D742A441B0463
+
+I=189
+KEY=F1D2EF3C44F61F37CFFCF753F180AADD
+IV=7B707442550BF1FA4C1B74F0DC3237FC
+CT=FC884EEEB73B2F66C97D742A441B0463
+PT=9C260AA82C6902B068495B4844507F7D
+
+I=190
+KEY=6DF4E594689F1D87A7B5AC1BB5D0D5A0
+IV=8329E8DE2980225DA61158BF467B1D79
+CT=9C260AA82C6902B068495B4844507F7D
+PT=1C12FEAA35AD2DD21DE6411C3A3BB6D5
+
+I=191
+KEY=71E61B3E5D323055BA53ED078FEB6375
+IV=EFD514D7CF3FAC49DBB5BB3505B9B18F
+CT=1C12FEAA35AD2DD21DE6411C3A3BB6D5
+PT=15F26D34E8E1037A5A2393CEA5DB396B
+
+I=192
+KEY=6414760AB5D3332FE0707EC92A305A1E
+IV=9EFC37C295552B965B29A23AC2788D8B
+CT=15F26D34E8E1037A5A2393CEA5DB396B
+PT=76F0C79955566A0A091AA46E0C59455E
+
+I=193
+KEY=12E4B193E0855925E96ADAA726691F40
+IV=5BA54E33128A7526A9130E632BE00D65
+CT=76F0C79955566A0A091AA46E0C59455E
+PT=1EA06231EBEEB995E2F94B88A4004333
+
+I=194
+KEY=0C44D3A20B6BE0B00B93912F82695C73
+IV=9B1C6FA42510E530D2282BF8C5516DCE
+CT=1EA06231EBEEB995E2F94B88A4004333
+PT=16C36348884B32AC1CB1DE2D3C158981
+
+I=195
+KEY=1A87B0EA8320D21C17224F02BE7CD5F2
+IV=F755F641EED4C828DCBECC327D93F4AF
+CT=16C36348884B32AC1CB1DE2D3C158981
+PT=6581A3FB5F61C6C1904F35E787BF552D
+
+I=196
+KEY=7F061311DC4114DD876D7AE539C380DF
+IV=5D799F356C1672707716C47DA4384C01
+CT=6581A3FB5F61C6C1904F35E787BF552D
+PT=0BA11F8EE845E03641928825B3344994
+
+I=197
+KEY=74A70C9F3404F4EBC6FFF2C08AF7C94B
+IV=89A5592031795CEAECF1C1F274813818
+CT=0BA11F8EE845E03641928825B3344994
+PT=1CF907A6C8A33C7806819EB97B854588
+
+I=198
+KEY=685E0B39FCA7C893C07E6C79F1728CC3
+IV=BBE87558AF456066B9CE3EBB8729D554
+CT=1CF907A6C8A33C7806819EB97B854588
+PT=722BB2E53CE7846F40B5EA18AF1430B0
+
+I=199
+KEY=1A75B9DCC0404CFC80CB86615E66BC73
+IV=2CC42E6DA36883482ACB5D9D92823186
+CT=722BB2E53CE7846F40B5EA18AF1430B0
+PT=E667D6A95E9C56BB56E4436CC1B69874
+
+I=200
+KEY=FC126F759EDC1A47D62FC50D9FD02407
+IV=F18DD0388BF5692B7394BAFDC4854308
+CT=E667D6A95E9C56BB56E4436CC1B69874
+PT=3C9A76798C468470EEBC5F7B915879A3
+
+I=201
+KEY=C088190C129A9E3738939A760E885DA4
+IV=8262D8603FE0F4AE8BF5795690992F1C
+CT=3C9A76798C468470EEBC5F7B915879A3
+PT=3CAFB994BDEF76370D8A5129B63BECDB
+
+I=202
+KEY=FC27A098AF75E8003519CB5FB8B3B17F
+IV=AB090F7A86CFD9A7C1BD8869BBB4D27B
+CT=3CAFB994BDEF76370D8A5129B63BECDB
+PT=50D037733D2C3242024BD322ADDF01CB
+
+I=203
+KEY=ACF797EB9259DA423752187D156CB0B4
+IV=3581D6724722C3892C712B2AA1066824
+CT=50D037733D2C3242024BD322ADDF01CB
+PT=0D7CB755305EF09692FCED530CCC1336
+
+I=204
+KEY=A18B20BEA2072AD4A5AEF52E19A0A382
+IV=9D0DAD6448895ECBE05F8DC73E014E3C
+CT=0D7CB755305EF09692FCED530CCC1336
+PT=D66389E01F44C60B26BCF3F9B39DAB55
+
+I=205
+KEY=77E8A95EBD43ECDF831206D7AA3D08D7
+IV=7BDC3CD62CD79C7E6CB8FAE104175DE4
+CT=D66389E01F44C60B26BCF3F9B39DAB55
+PT=CC9F59409D636BE5C555AC2841650CD7
+
+I=206
+KEY=BB77F01E2020873A4647AAFFEB580400
+IV=A4FBE42983B236097E40C1E244B14748
+CT=CC9F59409D636BE5C555AC2841650CD7
+PT=34804672FCEF79481269B1D254DDCAF9
+
+I=207
+KEY=8FF7B66CDCCFFE72542E1B2DBF85CEF9
+IV=700B37E771E88E5DCD9C81D6FD16B995
+CT=34804672FCEF79481269B1D254DDCAF9
+PT=62FC00FDF1F6BF44FFBEB5BED5589A64
+
+I=208
+KEY=ED0BB6912D394136AB90AE936ADD549D
+IV=F3A9954079382ACD97C3EC198522AE69
+CT=62FC00FDF1F6BF44FFBEB5BED5589A64
+PT=F7901904A02544E064400A2625121C4C
+
+I=209
+KEY=1A9BAF958D1C05D6CFD0A4B54FCF48D1
+IV=3799F5DEF76C56F8B0A69889B85760AA
+CT=F7901904A02544E064400A2625121C4C
+PT=A915D55AE8E14497F2693A55F83041F5
+
+I=210
+KEY=B38E7ACF65FD41413DB99EE0B7FF0924
+IV=5421F3F4CDD3C6F9BF38184BC61904AA
+CT=A915D55AE8E14497F2693A55F83041F5
+PT=66EA0D0968631F3BDA46921078E495C1
+
+I=211
+KEY=D56477C60D9E5E7AE7FF0CF0CF1B9CE5
+IV=3B87243EE38BD474E4CBF34A7C592CFC
+CT=66EA0D0968631F3BDA46921078E495C1
+PT=283826367D00718849A6539EE8CAD8BF
+
+I=212
+KEY=FD5C51F0709E2FF2AE595F6E27D1445A
+IV=0FB53077D2BC27C544CD400A28212291
+CT=283826367D00718849A6539EE8CAD8BF
+PT=B15EA2718FB406D457C8B96530EDC014
+
+I=213
+KEY=4C02F381FF2A2926F991E60B173C844E
+IV=8BFE654E422E9BCCE7F1357053E1130C
+CT=B15EA2718FB406D457C8B96530EDC014
+PT=44238CE0F1765C7983BF408D5ECFA2BA
+
+I=214
+KEY=08217F610E5C755F7A2EA68649F326F4
+IV=86841D597FA91F54CBAD3C57FC1FC492
+CT=44238CE0F1765C7983BF408D5ECFA2BA
+PT=BB6408099CA64F1216D204865449E967
+
+I=215
+KEY=B345776892FA3A4D6CFCA2001DBACF93
+IV=849198CEA19F4AD76013D172867A0D20
+CT=BB6408099CA64F1216D204865449E967
+PT=B7E109C6813E686ADA396DDB277AD960
+
+I=216
+KEY=04A47EAE13C45227B6C5CFDB3AC016F3
+IV=9C5E0182124701DA958CF68E1B9F8CC1
+CT=B7E109C6813E686ADA396DDB277AD960
+PT=65C77CB822CA10AE1F95B91F0A3F6436
+
+I=217
+KEY=61630216310E4289A95076C430FF72C5
+IV=2BB9026F793A64A325E02B922E3A51DD
+CT=65C77CB822CA10AE1F95B91F0A3F6436
+PT=48E9DB9FC3F883AD28A0299561444197
+
+I=218
+KEY=298AD989F2F6C12481F05F5151BB3352
+IV=6BE0B03639C858D8F2CAE00EFE8FECCA
+CT=48E9DB9FC3F883AD28A0299561444197
+PT=02B277AB327BCB5C91831BD376DC5211
+
+I=219
+KEY=2B38AE22C08D0A781073448227676143
+IV=ADC033E3EEC3705031D2FB24205823A2
+CT=02B277AB327BCB5C91831BD376DC5211
+PT=FE288D6703CF6AB1635483305A82F192
+
+I=220
+KEY=D5102345C34260C97327C7B27DE590D1
+IV=F637C38CB5DF86458225143E157B9415
+CT=FE288D6703CF6AB1635483305A82F192
+PT=B07BF02F795D13D972D5D6E556E8BA37
+
+I=221
+KEY=656BD36ABA1F731001F211572B0D2AE6
+IV=824B7BBB3A339BF045C3CFEA9FD842B9
+CT=B07BF02F795D13D972D5D6E556E8BA37
+PT=D4661C2E102C6644724DA54BE291215D
+
+I=222
+KEY=B10DCF44AA33155473BFB41CC99C0BBB
+IV=21FA242B2B9FFF0C7DC6B712A38A333B
+CT=D4661C2E102C6644724DA54BE291215D
+PT=F7EDEE448559A6ACD68815B6EEAF6E38
+
+I=223
+KEY=46E021002F6AB3F8A537A1AA27336583
+IV=390906ECE51C92800D620E1CD1FD3574
+CT=F7EDEE448559A6ACD68815B6EEAF6E38
+PT=07257C91424F65E6752470A6960DF6D9
+
+I=224
+KEY=41C55D916D25D61ED013D10CB13E935A
+IV=918A010EC2B106DE32A220315999DF7D
+CT=07257C91424F65E6752470A6960DF6D9
+PT=CCB4F3FCFFDEE9E93DD3AB4CC2DB870E
+
+I=225
+KEY=8D71AE6D92FB3FF7EDC07A4073E51454
+IV=7CF6B4948C4E04ED235F2CC96B0A6B49
+CT=CCB4F3FCFFDEE9E93DD3AB4CC2DB870E
+PT=C455220E8C8847FF2592074A53104105
+
+I=226
+KEY=49248C631E737808C8527D0A20F55551
+IV=4839E74C868786D0A109603CF98F1100
+CT=C455220E8C8847FF2592074A53104105
+PT=B4D0F5B4C15D7AD556ED4964A94C898F
+
+I=227
+KEY=FDF479D7DF2E02DD9EBF346E89B9DCDE
+IV=5C6D9649E47FAA8A2DCAFB317B6BC0EA
+CT=B4D0F5B4C15D7AD556ED4964A94C898F
+PT=B515D2904555793DDC142618DCFF8464
+
+I=228
+KEY=48E1AB479A7B7BE042AB1276554658BA
+IV=E3573B4137C13BBA6CDD10D71042B8F6
+CT=B515D2904555793DDC142618DCFF8464
+PT=2C272D6589E2E6EE09067882795E9FB9
+
+I=229
+KEY=64C6862213999D0E4BAD6AF42C18C703
+IV=08E335104FC5D18E2C11EF34B805F060
+CT=2C272D6589E2E6EE09067882795E9FB9
+PT=B38E39322245C4A2E170EBF36D764AD5
+
+I=230
+KEY=D748BF1031DC59ACAADD8107416E8DD6
+IV=E134D0DEA38A23983766DA18DADA70E0
+CT=B38E39322245C4A2E170EBF36D764AD5
+PT=E7556255602B48D7CAC710A004FFFD2E
+
+I=231
+KEY=301DDD4551F7117B601A91A7459170F8
+IV=301C2808833418F45D5F97FB09A99504
+CT=E7556255602B48D7CAC710A004FFFD2E
+PT=D4356D51B1C486AAC8BCF2F65312758C
+
+I=232
+KEY=E428B014E03397D1A8A6635116830574
+IV=264D556FA9A9D73510F562BBF983A4F7
+CT=D4356D51B1C486AAC8BCF2F65312758C
+PT=B4D003D6C542B576A3EAEC8F1B017F5B
+
+I=233
+KEY=50F8B3C2257122A70B4C8FDE0D827A2F
+IV=8821647AD3E9E529909E60D0F75DA400
+CT=B4D003D6C542B576A3EAEC8F1B017F5B
+PT=10056819F314FF21114BE6209AB5508C
+
+I=234
+KEY=40FDDBDBD665DD861A0769FE97372AA3
+IV=CBD574F4DB1EFEE4E2EC9485D1192E04
+CT=10056819F314FF21114BE6209AB5508C
+PT=6E7AA061FE85B6F8972CB0E793BE0CB0
+
+I=235
+KEY=2E877BBA28E06B7E8D2BD91904892613
+IV=4F98EE1501681EC0E7834FE941DF6C6B
+CT=6E7AA061FE85B6F8972CB0E793BE0CB0
+PT=45E0C0014219D77686E82E74E60608CA
+
+I=236
+KEY=6B67BBBB6AF9BC080BC3F76DE28F2ED9
+IV=1D34CAB2FF836A7E6568823784519170
+CT=45E0C0014219D77686E82E74E60608CA
+PT=ACF686F9D6723EAFDBFE512AB3A8C6B1
+
+I=237
+KEY=C7913D42BC8B82A7D03DA6475127E868
+IV=BEA74B4435F9F79D39B8CCE1F090D4B8
+CT=ACF686F9D6723EAFDBFE512AB3A8C6B1
+PT=F11FE34D158D40DEA10033BCE0253F30
+
+I=238
+KEY=368EDE0FA906C279713D95FBB102D758
+IV=DF30EE5D8CA298BE630DDE4B6D8AD7AA
+CT=F11FE34D158D40DEA10033BCE0253F30
+PT=4E970ACAB8B19C942C85FAA7825C5E67
+
+I=239
+KEY=7819D4C511B75EED5DB86F5C335E893F
+IV=DC3CCC928C02710EE91391032A3B557D
+CT=4E970ACAB8B19C942C85FAA7825C5E67
+PT=0FF6C292507CF135036E04A391210466
+
+I=240
+KEY=77EF165741CBAFD85ED66BFFA27F8D59
+IV=7CC57A486E05E36F852278450C03D39F
+CT=0FF6C292507CF135036E04A391210466
+PT=BBEF94C8179E7A124492A252507D58E7
+
+I=241
+KEY=CC00829F5655D5CA1A44C9ADF202D5BE
+IV=BBB92F65197F8D6B388191E78E90A858
+CT=BBEF94C8179E7A124492A252507D58E7
+PT=BAF11150DD418ED7C28072A718815954
+
+I=242
+KEY=76F193CF8B145B1DD8C4BB0AEA838CEA
+IV=99DA5A29F934BE23EB74B6DE4E8CC740
+CT=BAF11150DD418ED7C28072A718815954
+PT=A935099B91A35655C850939D2FED1569
+
+I=243
+KEY=DFC49A541AB70D4810942897C56E9983
+IV=92401B7E92A49FA5A6905E51E49D51C2
+CT=A935099B91A35655C850939D2FED1569
+PT=F60E1B5D10CDA17FC762798B86B8708D
+
+I=244
+KEY=29CA81090A7AAC37D7F6511C43D6E90E
+IV=C2A57521674EB0FB3E46DE2CC1DCF419
+CT=F60E1B5D10CDA17FC762798B86B8708D
+PT=0B976079B61F46E7F3CCCD17E23D872F
+
+I=245
+KEY=225DE170BC65EAD0243A9C0BA1EB6E21
+IV=66970AE807FED1E3581496C9FBE5FF50
+CT=0B976079B61F46E7F3CCCD17E23D872F
+PT=FB44F0094A5FC03BD0A27391E58D0AA3
+
+I=246
+KEY=D9191179F63A2AEBF498EF9A44666482
+IV=ED7B2ED1AFF7DB9B514D6E4DFAEA484B
+CT=FB44F0094A5FC03BD0A27391E58D0AA3
+PT=41A534A69AD25FEB39BB9F754F15D8FE
+
+I=247
+KEY=98BC25DF6CE87500CD2370EF0B73BC7C
+IV=B7E8C7F08BCE1CF1CC2568E18C18C92B
+CT=41A534A69AD25FEB39BB9F754F15D8FE
+PT=022B28D4F7355E14F99F654B6C35BC16
+
+I=248
+KEY=9A970D0B9BDD2B1434BC15A46746006A
+IV=F2EF32464FC7E5F3D397C259CB963B7F
+CT=022B28D4F7355E14F99F654B6C35BC16
+PT=28F18EA03ADEB36C40FD8FBC590EC6C8
+
+I=249
+KEY=B26683ABA103987874419A183E48C6A2
+IV=687E822CCFC5800E88E59ED7DEC1409D
+CT=28F18EA03ADEB36C40FD8FBC590EC6C8
+PT=661F9AEA300100333D64FCDD1212C663
+
+I=250
+KEY=D47919419102984B492566C52C5A00C1
+IV=3922BB08EE1B4CC75881D1D6F66B8EE0
+CT=661F9AEA300100333D64FCDD1212C663
+PT=11C4D360F585EDF544D5479AE1ABDBE6
+
+I=251
+KEY=C5BDCA21648775BE0DF0215FCDF1DB27
+IV=9B7C0D7D0EA8CAD77B331F2E0CA1E639
+CT=11C4D360F585EDF544D5479AE1ABDBE6
+PT=2E4695733B01CC78993E6EB464784223
+
+I=252
+KEY=EBFB5F525F86B9C694CE4FEBA9899904
+IV=A2BF273F12FE1F4B2F56A86CAFD9C5BF
+CT=2E4695733B01CC78993E6EB464784223
+PT=1CC514E9F4B13FFEF3B076DAC8C62877
+
+I=253
+KEY=F73E4BBBAB378638677E3931614FB173
+IV=1D4960EBE667AC5DE5ED767183838846
+CT=1CC514E9F4B13FFEF3B076DAC8C62877
+PT=3B1A7D179DDED66A37F3053B8B231EEA
+
+I=254
+KEY=CC2436AC36E95052508D3C0AEA6CAF99
+IV=974643FDFDB695A44B7EF8676A2B87DD
+CT=3B1A7D179DDED66A37F3053B8B231EEA
+PT=620A4E7A25E8D05779C0FB8CEBA55A74
+
+I=255
+KEY=AE2E78D613018005294DC78601C9F5ED
+IV=C9A1D92DB7D553DCAEB3BB81B489257A
+CT=620A4E7A25E8D05779C0FB8CEBA55A74
+PT=93508503278ECECE65D67B5F50962C4E
+
+I=256
+KEY=3D7EFDD5348F4ECB4C9BBCD9515FD9A3
+IV=108E736F1DCD178A8648F6AA6D527732
+CT=93508503278ECECE65D67B5F50962C4E
+PT=EA9E953D8B62FFAFF9FAFB97F614D65C
+
+I=257
+KEY=D7E068E8BFEDB164B561474EA74B0FFF
+IV=B893A94302C0DAFB19D7B6656085DCA9
+CT=EA9E953D8B62FFAFF9FAFB97F614D65C
+PT=1452ED26E774029EF30D272F8548C2F8
+
+I=258
+KEY=C3B285CE5899B3FA466C60612203CD07
+IV=668FF6719E5A29A99876227EEDE5818F
+CT=1452ED26E774029EF30D272F8548C2F8
+PT=4083167E5ED1A1A449C1825B84F321E1
+
+I=259
+KEY=833193B00648125E0FADE23AA6F0ECE6
+IV=9F6375A022543AB8303368A235813F02
+CT=4083167E5ED1A1A449C1825B84F321E1
+PT=9206639D076685FD2078F9B984B7A03F
+
+I=260
+KEY=1137F02D012E97A32FD51B8322474CD9
+IV=1B95128E90B110AED9D543D2A996271F
+CT=9206639D076685FD2078F9B984B7A03F
+PT=AAA3F2BD0126DFD5007DD2835CCB0109
+
+I=261
+KEY=BB940290000848762FA8C9007E8C4DD0
+IV=BB2E26A9CDEF9D1B2940EFFBA1971A5D
+CT=AAA3F2BD0126DFD5007DD2835CCB0109
+PT=B58BB3761519C1726D75AE96313FB7DE
+
+I=262
+KEY=0E1FB1E61511890442DD67964FB3FA0E
+IV=68D3EC37EE43E3F24072F69F2DFA768D
+CT=B58BB3761519C1726D75AE96313FB7DE
+PT=4558CD47C012B7293396D7EDFE3CEA85
+
+I=263
+KEY=4B477CA1D5033E2D714BB07BB18F108B
+IV=F7E107DBF4DDBF7974B699536A4E2803
+CT=4558CD47C012B7293396D7EDFE3CEA85
+PT=6F43B6B28AEF5DD1B66279ACAAB9A589
+
+I=264
+KEY=2404CA135FEC63FCC729C9D71B36B502
+IV=B3E6DA8DE5DDF7ED6F832D1306A1C04A
+CT=6F43B6B28AEF5DD1B66279ACAAB9A589
+PT=1BA743E148BC164C4C8324D665B5A3BD
+
+I=265
+KEY=3FA389F2175075B08BAAED017E8316BF
+IV=8BBBB56B39893C8F286561EF6E47E66A
+CT=1BA743E148BC164C4C8324D665B5A3BD
+PT=49A40365092DD1360D916AAEAFD03FC1
+
+I=266
+KEY=76078A971E7DA486863B87AFD153297E
+IV=48BA08703A306F772E78F660173A26B3
+CT=49A40365092DD1360D916AAEAFD03FC1
+PT=DF7DEB5968D683AAA274B0D5D3F9AA03
+
+I=267
+KEY=A97A61CE76AB272C244F377A02AA837D
+IV=0C7832F9CDF65DADA7FA809B8DE709C3
+CT=DF7DEB5968D683AAA274B0D5D3F9AA03
+PT=69689E97E9B166DA53E25BDFBCAF4A97
+
+I=268
+KEY=C012FF599F1A41F677AD6CA5BE05C9EA
+IV=05BC03F59CD8C5FAE4A7240E6168CF41
+CT=69689E97E9B166DA53E25BDFBCAF4A97
+PT=5F87DC71EF2918F75A94E43007FF50E6
+
+I=269
+KEY=9F952328703359012D398895B9FA990C
+IV=4233E654802B55155E158B650B64718E
+CT=5F87DC71EF2918F75A94E43007FF50E6
+PT=4F170790775A6A147E99D251C401969A
+
+I=270
+KEY=D08224B80769331553A05AC47DFB0F96
+IV=4AEAE53003D5085F5963CC36C4589941
+CT=4F170790775A6A147E99D251C401969A
+PT=E566D46360EF38E5CFF0C2E7E7E0D679
+
+I=271
+KEY=35E4F0DB67860BF09C5098239A1BD9EF
+IV=F6CBFF51F6E59B7AAA9EB1261707429A
+CT=E566D46360EF38E5CFF0C2E7E7E0D679
+PT=F7189C4B9E1048ED66D9B7CCD089C5F9
+
+I=272
+KEY=C2FC6C90F996431DFA892FEF4A921C16
+IV=0A05A4BFBBCC8B3E218C123A95FFF475
+CT=F7189C4B9E1048ED66D9B7CCD089C5F9
+PT=68FB0909789DBFA672BEEF5DF0017B63
+
+I=273
+KEY=AA076599810BFCBB8837C0B2BA936775
+IV=DF1A3AF147E72C2CEAE5D8713D52F572
+CT=68FB0909789DBFA672BEEF5DF0017B63
+PT=AF2784590089186BED3A48ADC1B68562
+
+I=274
+KEY=0520E1C08182E4D0650D881F7B25E217
+IV=BFDC5ECF596F5F3CFFEAAF4B961209FA
+CT=AF2784590089186BED3A48ADC1B68562
+PT=E8C29D3C129AB8FA797EFDCE4CE4D4F2
+
+I=275
+KEY=EDE27CFC93185C2A1C7375D137C136E5
+IV=49195E71516D5117C26814F98FD94C31
+CT=E8C29D3C129AB8FA797EFDCE4CE4D4F2
+PT=6ACF2AE12C38DB520F49E6C90D4B8F03
+
+I=276
+KEY=872D561DBF208778133A93183A8AB9E6
+IV=E4FA7788D6E7AFBD08884BFCFA74D30C
+CT=6ACF2AE12C38DB520F49E6C90D4B8F03
+PT=78FEA3B57D6176C44CE753FB01416CA6
+
+I=277
+KEY=FFD3F5A8C241F1BC5FDDC0E33BCBD540
+IV=08E333F43615229D95E7C425A04EA2B7
+CT=78FEA3B57D6176C44CE753FB01416CA6
+PT=5030D7131ABBD7AC323BA31B602B776E
+
+I=278
+KEY=AFE322BBD8FA26106DE663F85BE0A22E
+IV=64BDE35106D9A66A4216EA20F6C52D06
+CT=5030D7131ABBD7AC323BA31B602B776E
+PT=14B32E8BD3BD9D82613E32536E6A9F91
+
+I=279
+KEY=BB500C300B47BB920CD851AB358A3DBF
+IV=8FB9E6BDCD50610E97CF731216CFE698
+CT=14B32E8BD3BD9D82613E32536E6A9F91
+PT=1F22542AFCE63AA92CCDAF45F8DAEEF0
+
+I=280
+KEY=A472581AF7A1813B2015FEEECD50D34F
+IV=E18B3C5EDA8CDA9E94A376CEEF687D9F
+CT=1F22542AFCE63AA92CCDAF45F8DAEEF0
+PT=FC986510E3ED40994D1C33201D0EDB27
+
+I=281
+KEY=58EA3D0A144CC1A26D09CDCED05E0868
+IV=D1828C9DDB263064AD259A2360B3DFBA
+CT=FC986510E3ED40994D1C33201D0EDB27
+PT=06C1CE557C9AC5D40560CF2D40DCC47C
+
+I=282
+KEY=5E2BF35F68D60476686902E39082CC14
+IV=3454FD0698CC8CD949970509C23E50F6
+CT=06C1CE557C9AC5D40560CF2D40DCC47C
+PT=4287FA420FD9AFCAB7E290273BDF4054
+
+I=283
+KEY=1CAC091D670FABBCDF8B92C4AB5D8C40
+IV=C2F0C044A975ADBD20DE56858A074886
+CT=4287FA420FD9AFCAB7E290273BDF4054
+PT=447AFDD3ACF0DEEB0385799789FBAFF0
+
+I=284
+KEY=58D6F4CECBFF7557DC0EEB5322A623B0
+IV=299C337821B0779A7ADC3A04316A6373
+CT=447AFDD3ACF0DEEB0385799789FBAFF0
+PT=BA0BBC980827E87EEA51E66C92C96B31
+
+I=285
+KEY=E2DD4856C3D89D29365F0D3FB06F4881
+IV=2368291AD179C3C143E636898EB3E104
+CT=BA0BBC980827E87EEA51E66C92C96B31
+PT=77A6131415B251049423FFFB1F3A8A3A
+
+I=286
+KEY=957B5B42D66ACC2DA27CF2C4AF55C2BB
+IV=14300EA81B57E102AEDD97CCD466E18A
+CT=77A6131415B251049423FFFB1F3A8A3A
+PT=A7AEC0CC599D56347A72D934DDAC7899
+
+I=287
+KEY=32D59B8E8FF79A19D80E2BF072F9BA22
+IV=FD62415C90DACCD22EC364877DB0CB24
+CT=A7AEC0CC599D56347A72D934DDAC7899
+PT=1B1100FCB9F85D8CCFDEC5865083B44D
+
+I=288
+KEY=29C49B72360FC79517D0EE76227A0E6F
+IV=6CB24892D26E43E63819C372D5EB4F6D
+CT=1B1100FCB9F85D8CCFDEC5865083B44D
+PT=33E9BBD018604F301C2543878FCCCA5C
+
+I=289
+KEY=1A2D20A22E6F88A50BF5ADF1ADB6C433
+IV=50D84A03998B897D1AE217FEA9A955C4
+CT=33E9BBD018604F301C2543878FCCCA5C
+PT=07163D652DB035C091830042D6047DF3
+
+I=290
+KEY=1D3B1DC703DFBD659A76ADB37BB2B9C0
+IV=092DF26C855F07690836203E3E1790D0
+CT=07163D652DB035C091830042D6047DF3
+PT=AD6647AF8EFCD4F3B2ECDB4D6FFFC1EB
+
+I=291
+KEY=B05D5A688D236996289A76FE144D782B
+IV=68634C941957E3F58F71BE37D7C5C78B
+CT=AD6647AF8EFCD4F3B2ECDB4D6FFFC1EB
+PT=D2B51122154D10F67D2C07BD75D5E8E2
+
+I=292
+KEY=62E84B4A986E796055B67143619890C9
+IV=3C85044F6438FAA021BB7985A63A959D
+CT=D2B51122154D10F67D2C07BD75D5E8E2
+PT=4131E9296FECD2DF35EDFBF0CBD0E54B
+
+I=293
+KEY=23D9A263F782ABBF605B8AB3AA487582
+IV=46D47F3F12B6ADD5580CE8CE7C7359CD
+CT=4131E9296FECD2DF35EDFBF0CBD0E54B
+PT=5AEA3E73A6EC0D9D683A3526AC1C0E58
+
+I=294
+KEY=79339C10516EA6220861BF9506547BDA
+IV=D3C58B190FDA0838C770C2185C553D97
+CT=5AEA3E73A6EC0D9D683A3526AC1C0E58
+PT=A21B17CB4588C30CAD6DF25A5E83E273
+
+I=295
+KEY=DB288BDB14E6652EA50C4DCF58D799A9
+IV=870E7F0E3109712E84C58BEC0E7032F6
+CT=A21B17CB4588C30CAD6DF25A5E83E273
+PT=0021FF3BB8336E607B8DE10117005230
+
+I=296
+KEY=DB0974E0ACD50B4EDE81ACCE4FD7CB99
+IV=2FC82B298A60FC40DA3EFD4E800DB063
+CT=0021FF3BB8336E607B8DE10117005230
+PT=2EFA32680ECD84891B447393F7C1AC88
+
+I=297
+KEY=F5F34688A2188FC7C5C5DF5DB8166711
+IV=E1B86C9FC466B72BE40F65973FC41FC4
+CT=2EFA32680ECD84891B447393F7C1AC88
+PT=722117C1EE83FBA840EFEE86A930579F
+
+I=298
+KEY=87D251494C9B746F852A31DB1126308E
+IV=48E347A705B6E322153BFE567931346F
+CT=722117C1EE83FBA840EFEE86A930579F
+PT=A684344231EC4C03726A0DC20EADA36D
+
+I=299
+KEY=2156650B7D77386CF7403C191F8B93E3
+IV=4CD618E5F959FC4C66602263F6C5C652
+CT=A684344231EC4C03726A0DC20EADA36D
+PT=F40BFBEAC1C1BD1621FBAE1B605BD092
+
+I=300
+KEY=D55D9EE1BCB6857AD6BB92027FD04371
+IV=5A41E8952E6B1C551C4691DE9C0A4B6D
+CT=F40BFBEAC1C1BD1621FBAE1B605BD092
+PT=6ECDBFB3947C7E81C7BD4BE93B603728
+
+I=301
+KEY=BB90215228CAFBFB1106D9EB44B07459
+IV=52E2726B0855F993E1075077B3AB1E77
+CT=6ECDBFB3947C7E81C7BD4BE93B603728
+PT=71E051375A3B974FE523DA47862E24AE
+
+I=302
+KEY=CA70706572F16CB4F42503ACC29E50F7
+IV=76B6637161FBE4760FCE90E9868B441A
+CT=71E051375A3B974FE523DA47862E24AE
+PT=CC6CFBCF9A62A3AE55F6B040673B25B3
+
+I=303
+KEY=061C8BAAE893CF1AA1D3B3ECA5A57544
+IV=5563B0C2350A4ED76EE0C322480884FB
+CT=CC6CFBCF9A62A3AE55F6B040673B25B3
+PT=DA71B26C4EE3FB1FD413FD0757B379E6
+
+I=304
+KEY=DC6D39C6A670340575C04EEBF2160CA2
+IV=45C1C5DAF8DE9170C01E554DD36C564E
+CT=DA71B26C4EE3FB1FD413FD0757B379E6
+PT=BCD4BC394FFB46207EF0A8EC9883BD55
+
+I=305
+KEY=60B985FFE98B72250B30E6076A95B1F7
+IV=38E5B69E6D82A760BFD65CBAACC56F8A
+CT=BCD4BC394FFB46207EF0A8EC9883BD55
+PT=FD997E7A7B77E5DF637182399779AF75
+
+I=306
+KEY=9D20FB8592FC97FA6841643EFDEC1E82
+IV=8EB39B261910419E43B178DCD6803572
+CT=FD997E7A7B77E5DF637182399779AF75
+PT=71749C51136457B604CD8B4C193928A8
+
+I=307
+KEY=EC5467D48198C04C6C8CEF72E4D5362A
+IV=6DFA447305215066A0B5671E5AB80951
+CT=71749C51136457B604CD8B4C193928A8
+PT=DF48D76E54B4264304B0EC036DFDADDE
+
+I=308
+KEY=331CB0BAD52CE60F683C037189289BF4
+IV=8C2B316ECA96DB57322853E07BE47AB3
+CT=DF48D76E54B4264304B0EC036DFDADDE
+PT=5E2BD374B9856C573A4DEBF1B8F453EC
+
+I=309
+KEY=6D3763CE6CA98A585271E88031DCC818
+IV=E541AC59CFDBEA97D1AE5221F849838E
+CT=5E2BD374B9856C573A4DEBF1B8F453EC
+PT=D7F97B76A8D3076D343A22459EC4765D
+
+I=310
+KEY=BACE18B8C47A8D35664BCAC5AF18BE45
+IV=B359889A22B9502571E4817C47BC5348
+CT=D7F97B76A8D3076D343A22459EC4765D
+PT=E24F05EEE812BD3389AC0AAC4172F5C6
+
+I=311
+KEY=58811D562C683006EFE7C069EE6A4B83
+IV=33F8D881A783051987103096B6C734C3
+CT=E24F05EEE812BD3389AC0AAC4172F5C6
+PT=A2AB44CC9C41A8748201DA6F9429AB39
+
+I=312
+KEY=FA2A599AB02998726DE61A067A43E0BA
+IV=2028704442AE252BCF1D081C5EE2D80B
+CT=A2AB44CC9C41A8748201DA6F9429AB39
+PT=E8FA100D1D28186196BAF990A80109AA
+
+I=313
+KEY=12D04997AD018013FB5CE396D242E910
+IV=6384E3612062BC6850C94C3B14934A6F
+CT=E8FA100D1D28186196BAF990A80109AA
+PT=683AEF47A8990E2F8AAD8813789069B1
+
+I=314
+KEY=7AEAA6D005988E3C71F16B85AAD280A1
+IV=12F78728F3B0EFAC7D304257E47ED5C8
+CT=683AEF47A8990E2F8AAD8813789069B1
+PT=F3121C95A5BACDEAEFA87C4EE40B6C6D
+
+I=315
+KEY=89F8BA45A02243D69E5917CB4ED9ECCC
+IV=FE654BC69677E13383C4206BFB7896A6
+CT=F3121C95A5BACDEAEFA87C4EE40B6C6D
+PT=AE9701378E128847A2669B516795D586
+
+I=316
+KEY=276FBB722E30CB913C3F8C9A294C394A
+IV=E79D5C468BCBA36A79B74F32F28FA635
+CT=AE9701378E128847A2669B516795D586
+PT=D97D988A40C5B323794F160FE8639262
+
+I=317
+KEY=FE1223F86EF578B245709A95C12FAB28
+IV=4F3055450C627AD4712E042666AC0812
+CT=D97D988A40C5B323794F160FE8639262
+PT=32381BA55D5C0C91D683D57593772496
+
+I=318
+KEY=CC2A385D33A9742393F34FE052588FBE
+IV=172165B468B83B62B41A2B4310461193
+CT=32381BA55D5C0C91D683D57593772496
+PT=4D555F31A60F1007B96FBB458B06A619
+
+I=319
+KEY=817F676C95A664242A9CF4A5D95E29A7
+IV=5D5EEBEA67DCD5F7851619F1BAA6414E
+CT=4D555F31A60F1007B96FBB458B06A619
+PT=23D1AC0F18C20FCE7E5CC4619F8376D5
+
+I=320
+KEY=A2AECB638D646BEA54C030C446DD5F72
+IV=54154B82B5820D5892DABD15B403345D
+CT=23D1AC0F18C20FCE7E5CC4619F8376D5
+PT=2E55905A38F818CC04D8A792D2007332
+
+I=321
+KEY=8CFB5B39B59C73265018975694DD2C40
+IV=AC47D7619A587DC8213B749918FCFEA8
+CT=2E55905A38F818CC04D8A792D2007332
+PT=010F3396885F8F6BF15170B8E6D221BD
+
+I=322
+KEY=8DF468AF3DC3FC4DA149E7EE720F0DFD
+IV=6CE249D2E89C61ACD029AA3C122427D1
+CT=010F3396885F8F6BF15170B8E6D221BD
+PT=4DB3972D9851B8A4B3150A43210D36F0
+
+I=323
+KEY=C047FF82A59244E9125CEDAD53023B0D
+IV=07A578889914E113C1C4DE01DC4B1DE4
+CT=4DB3972D9851B8A4B3150A43210D36F0
+PT=84F64CFFD705E82704FF3DA4FC074B34
+
+I=324
+KEY=44B1B37D7297ACCE16A3D009AF057039
+IV=CE73ADCD7BCF1807C084276EDD765256
+CT=84F64CFFD705E82704FF3DA4FC074B34
+PT=5964DF8E8D656846EE574635787F7B18
+
+I=325
+KEY=1DD56CF3FFF2C488F8F4963CD77A0B21
+IV=679903574013011E62CC5798B9633607
+CT=5964DF8E8D656846EE574635787F7B18
+PT=E28E7E3AA93802BEEFE258F38F5D2E5C
+
+I=326
+KEY=FF5B12C956CAC6361716CECF5827257D
+IV=678D8583A022C60BCE2C227627A548B2
+CT=E28E7E3AA93802BEEFE258F38F5D2E5C
+PT=D297684A7C50765C413BFA37B5E1E256
+
+I=327
+KEY=2DCC7A832A9AB06A562D34F8EDC6C72B
+IV=4EF9AACC21733B65B4DD0B1F105D4037
+CT=D297684A7C50765C413BFA37B5E1E256
+PT=9EF5F9A2B14B090A201DE74E4CF714C8
+
+I=328
+KEY=B33983219BD1B9607630D3B6A131D3E3
+IV=5CC41FCC9EC19619BA06D10BBC6E1F5F
+CT=9EF5F9A2B14B090A201DE74E4CF714C8
+PT=81EF000CF6CA737E0F449927E66F6392
+
+I=329
+KEY=32D6832D6D1BCA1E79744A91475EB071
+IV=6DE60CE2986CF80C5D588FA1F9A8C3A0
+CT=81EF000CF6CA737E0F449927E66F6392
+PT=3BE177EE9F8F7BE3BCE0FAA70C0A5025
+
+I=330
+KEY=0937F4C3F294B1FDC594B0364B54E054
+IV=BE2F86A52BEED4497790D6134CF0D64E
+CT=3BE177EE9F8F7BE3BCE0FAA70C0A5025
+PT=DD313134DB126529F349808B3E766795
+
+I=331
+KEY=D406C5F72986D4D436DD30BD752287C1
+IV=A89E52478FDEF91AF151097CED84579C
+CT=DD313134DB126529F349808B3E766795
+PT=330203EA36484C8E091F00CD2255E599
+
+I=332
+KEY=E704C61D1FCE985A3FC2307057776258
+IV=1AEF7BA63A3E3B6D2EB8EB1980D3E581
+CT=330203EA36484C8E091F00CD2255E599
+PT=E28A47CDB7DB0351006C1D9FB227FCEF
+
+I=333
+KEY=058E81D0A8159B0B3FAE2DEFE5509EB7
+IV=F67C7FCF8C5AA1574A165D8CBE694BF4
+CT=E28A47CDB7DB0351006C1D9FB227FCEF
+PT=ACF869797690853BE142BB7BAC735FC8
+
+I=334
+KEY=A976E8A9DE851E30DEEC96944923C17F
+IV=636F181C4735E700897928BFC60A43EB
+CT=ACF869797690853BE142BB7BAC735FC8
+PT=60FF9BF36809DAEB94F823FC6458B26A
+
+I=335
+KEY=C989735AB68CC4DB4A14B5682D7B7315
+IV=0829C0EE6B170C490C7A73401761CEAA
+CT=60FF9BF36809DAEB94F823FC6458B26A
+PT=17630CBEAB904F7996301515F24A1F27
+
+I=336
+KEY=DEEA7FE41D1C8BA2DC24A07DDF316C32
+IV=A4E0624D86F1098D2DD4D0408897ACED
+CT=17630CBEAB904F7996301515F24A1F27
+PT=A1E35C3E2FA1B1DB11DB96E7DD58AB37
+
+I=337
+KEY=7F0923DA32BD3A79CDFF369A0269C705
+IV=D3639A296FF168ED773785CFCACD1015
+CT=A1E35C3E2FA1B1DB11DB96E7DD58AB37
+PT=14F5408460708A69A22A2023B01969CE
+
+I=338
+KEY=6BFC635E52CDB0106FD516B9B270AECB
+IV=37CD0428A0C08CC6AABAAA05D8830557
+CT=14F5408460708A69A22A2023B01969CE
+PT=516991CA6530D20AB121394F51288880
+
+I=339
+KEY=3A95F29437FD621ADEF42FF6E358264B
+IV=FB52F5A95F2E3665D44F0AEACB88B108
+CT=516991CA6530D20AB121394F51288880
+PT=FB0C32B66729736F8E5EC8C92D80FDC5
+
+I=340
+KEY=C199C02250D4117550AAE73FCED8DB8E
+IV=403B43C740215D94E8FBAE22846D3B0A
+CT=FB0C32B66729736F8E5EC8C92D80FDC5
+PT=C243054D022E7E9EFC21F965C71D63EB
+
+I=341
+KEY=03DAC56F52FA6FEBAC8B1E5A09C5B865
+IV=663796B211E7F6E05B4A107B16A904B0
+CT=C243054D022E7E9EFC21F965C71D63EB
+PT=6CA56F6792355B2A7A60A4467A85F71E
+
+I=342
+KEY=6F7FAA08C0CF34C1D6EBBA1C73404F7B
+IV=A23B73DF1477EC98202135164C6EF1AB
+CT=6CA56F6792355B2A7A60A4467A85F71E
+PT=BC590C8B427B013F873B2F5F8D66D5D1
+
+I=343
+KEY=D326A68382B435FE51D09543FE269AAA
+IV=E84DF462C62D594AAD94C33C446E18FC
+CT=BC590C8B427B013F873B2F5F8D66D5D1
+PT=D37CAA9BEA300FF6219349DBA25DA0A6
+
+I=344
+KEY=005A0C1868843A087043DC985C7B3A0C
+IV=9AAD322884EBE93D0FA084E144600174
+CT=D37CAA9BEA300FF6219349DBA25DA0A6
+PT=AE50C328AFFC39A103C767C1FD337449
+
+I=345
+KEY=AE0ACF30C77803A97384BB59A1484E45
+IV=9CEE91362FB0D50ABCEB58EF49EC3614
+CT=AE50C328AFFC39A103C767C1FD337449
+PT=882939453C6E156CD023B468EDD16C95
+
+I=346
+KEY=2623F675FB1616C5A3A70F314C9922D0
+IV=5626126CC424BF26D92C822442E4221E
+CT=882939453C6E156CD023B468EDD16C95
+PT=B9A97FE0DEF66604F6CE928AAB532EC2
+
+I=347
+KEY=9F8A899525E070C155699DBBE7CA0C12
+IV=E5BB374C14E36FD0C2D5F9191C967EC7
+CT=B9A97FE0DEF66604F6CE928AAB532EC2
+PT=6ED0FF2FE8DA900A33AE20F7C1C2E457
+
+I=348
+KEY=F15A76BACD3AE0CB66C7BD4C2608E845
+IV=4493B9F0FF63D392273302B6932C8F77
+CT=6ED0FF2FE8DA900A33AE20F7C1C2E457
+PT=B7583A56BED55067A520B4F5E5C1528F
+
+I=349
+KEY=46024CEC73EFB0ACC3E709B9C3C9BACA
+IV=12E2BFD3EAB69E5132E3CDF8BAFBD45E
+CT=B7583A56BED55067A520B4F5E5C1528F
+PT=28874485575E292B0C83E1B568019BF0
+
+I=350
+KEY=6E85086924B19987CF64E80CABC8213A
+IV=3CEFDC726C919CA265CD6C28A05DE542
+CT=28874485575E292B0C83E1B568019BF0
+PT=A35D16BBB96BF3F9E06D96EDA9BB44BB
+
+I=351
+KEY=CDD81ED29DDA6A7E2F097EE102736581
+IV=4AE79901700F018D1E5D95A9FAD762F2
+CT=A35D16BBB96BF3F9E06D96EDA9BB44BB
+PT=367E6880D369D482E7E64CFCD1BCC870
+
+I=352
+KEY=FBA676524EB3BEFCC8EF321DD3CFADF1
+IV=52EEDB058A8E1FE7C651D484F86F941F
+CT=367E6880D369D482E7E64CFCD1BCC870
+PT=32B33E97C94953392A738A964DB121FC
+
+I=353
+KEY=C91548C587FAEDC5E29CB88B9E7E8C0D
+IV=B3704291187E9D55901DD237EC1E2F24
+CT=32B33E97C94953392A738A964DB121FC
+PT=965A9A0C0287AB8535436E95CC9BFB99
+
+I=354
+KEY=5F4FD2C9857D4640D7DFD61E52E57794
+IV=B3878FC256FA4F9ED0BA05FF51C0CE2A
+CT=965A9A0C0287AB8535436E95CC9BFB99
+PT=367A5C93099ACF72353DAC320A3B766E
+
+I=355
+KEY=69358E5A8CE78932E2E27A2C58DE01FA
+IV=774EA78AECAF5A1D7CC1785DE91CAB01
+CT=367A5C93099ACF72353DAC320A3B766E
+PT=116EDEB1D0E6F8D1BB58AF648429B792
+
+I=356
+KEY=785B50EB5C0171E359BAD548DCF7B668
+IV=FB1EC4218C5F733A54DEA7F753F45D68
+CT=116EDEB1D0E6F8D1BB58AF648429B792
+PT=EF3C679822E3A906F380CD07EBE65F09
+
+I=357
+KEY=976737737EE2D8E5AA3A184F3711E961
+IV=8BBE09AFE41C5A78EBA0524212AC570F
+CT=EF3C679822E3A906F380CD07EBE65F09
+PT=291B066A30A3B11681D414A4BB5311D5
+
+I=358
+KEY=BE7C31194E4169F32BEE0CEB8C42F8B4
+IV=4E8F651C06778A964AA7D43999E41FD6
+CT=291B066A30A3B11681D414A4BB5311D5
+PT=764F8FD22FE0BD98852F259EA6DC6F7C
+
+I=359
+KEY=C833BECB61A1D46BAEC129752A9E97C8
+IV=E90A35007EE7F001D1F5982BF2477C82
+CT=764F8FD22FE0BD98852F259EA6DC6F7C
+PT=66016373A6B1A3797A1B2D2B19B73126
+
+I=360
+KEY=AE32DDB8C7107712D4DA045E3329A6EE
+IV=46FF289808B1AF6B290CB5AF05747085
+CT=66016373A6B1A3797A1B2D2B19B73126
+PT=3367064ECF5CA978001887DBDE40DE5A
+
+I=361
+KEY=9D55DBF6084CDE6AD4C28385ED6978B4
+IV=9BAC8819E1CA613CFAA730FBC2034168
+CT=3367064ECF5CA978001887DBDE40DE5A
+PT=5C4F01D47C9DA94DE95FC26763CC1146
+
+I=362
+KEY=C11ADA2274D177273D9D41E28EA569F2
+IV=A5CE34A846E1D0A737963C49FAD6378E
+CT=5C4F01D47C9DA94DE95FC26763CC1146
+PT=D41D854E42863F161E76A2397020C321
+
+I=363
+KEY=15075F6C3657483123EBE3DBFE85AAD3
+IV=2CC823722DD3E8F15035875ED43513E2
+CT=D41D854E42863F161E76A2397020C321
+PT=1C542DC0B54A053471AF583C909AB3C4
+
+I=364
+KEY=095372AC831D4D055244BBE76E1F1917
+IV=9799D03B6AD46BECD981279B35DF707C
+CT=1C542DC0B54A053471AF583C909AB3C4
+PT=958D0254D7AFE1E678A9844DF4F4D18D
+
+I=365
+KEY=9CDE70F854B2ACE32AED3FAA9AEBC89A
+IV=E0E401C7BA5E319F0D60AB765CBEE176
+CT=958D0254D7AFE1E678A9844DF4F4D18D
+PT=C54888169B30587E732BD7213EE5B1A3
+
+I=366
+KEY=5996F8EECF82F49D59C6E88BA40E7939
+IV=711DA6521732E6868111DCC1C835F9DF
+CT=C54888169B30587E732BD7213EE5B1A3
+PT=446F234FCADA809A8B2E167A86C9EB36
+
+I=367
+KEY=1DF9DBA105587407D2E8FEF122C7920F
+IV=B7008BC907C546A56743C292185C2B02
+CT=446F234FCADA809A8B2E167A86C9EB36
+PT=6AD93BC7E18B48810664CD1C528BA6C4
+
+I=368
+KEY=7720E066E4D33C86D48C33ED704C34CB
+IV=4D7DD98183E56F71D72DB76187FC5F95
+CT=6AD93BC7E18B48810664CD1C528BA6C4
+PT=0D75BD2B8683FB819EB7F71E2E0836A7
+
+I=369
+KEY=7A555D4D6250C7074A3BC4F35E44026C
+IV=F4DCFB73BBE7EB5348D56F81BCBC0971
+CT=0D75BD2B8683FB819EB7F71E2E0836A7
+PT=8CBE14862E93FE011A4F45518C7258FA
+
+I=370
+KEY=F6EB49CB4CC33906507481A2D2365A96
+IV=5432FBF1480AA398F09CA5AF375FA394
+CT=8CBE14862E93FE011A4F45518C7258FA
+PT=4026D669905762F0790B6497646A2D4D
+
+I=371
+KEY=B6CD9FA2DC945BF6297FE535B65C77DB
+IV=CA462DC9F029A8311CA45A4116DADC1D
+CT=4026D669905762F0790B6497646A2D4D
+PT=A8CD2E187CF274756E5736D420853435
+
+I=372
+KEY=1E00B1BAA0662F834728D3E196D943EE
+IV=4FC9E7688352F4700C5F380BFD1F4FB2
+CT=A8CD2E187CF274756E5736D420853435
+PT=A99410B60322340E279C87D3D26793AA
+
+I=373
+KEY=B794A10CA3441B8D60B4543244BED044
+IV=4D90B1A30EB7E957FAE3DC8C132F4F42
+CT=A99410B60322340E279C87D3D26793AA
+PT=D136F990196C667EC35E3A0492C39968
+
+I=374
+KEY=66A2589CBA287DF3A3EA6E36D67D492C
+IV=6FAD87F358F0C702C5E9E599093219ED
+CT=D136F990196C667EC35E3A0492C39968
+PT=8CE49C1BAACAB69432DDA2FF4250C7B2
+
+I=375
+KEY=EA46C48710E2CB679137CCC9942D8E9E
+IV=2B6FF495B7E482360E31949C7C9B2E2B
+CT=8CE49C1BAACAB69432DDA2FF4250C7B2
+PT=7942B80F57EA24FA200451B37899F9E2
+
+I=376
+KEY=93047C884708EF9DB1339D7AECB4777C
+IV=21FDC4C9B03A1A9A3F87FF9AAC80FAAE
+CT=7942B80F57EA24FA200451B37899F9E2
+PT=DE156D56E199FDBB2600DBF9FC254003
+
+I=377
+KEY=4D1111DEA6911226973346831091377F
+IV=387612E399C62916B394A9FC6BC0F059
+CT=DE156D56E199FDBB2600DBF9FC254003
+PT=C302C494D910640271695324E64B0992
+
+I=378
+KEY=8E13D54A7F817624E65A15A7F6DA3EED
+IV=34BCABDE4646BCC05CAF7E61CBF1F8D2
+CT=C302C494D910640271695324E64B0992
+PT=110CE84E5B81867CE4FCCD1BBB5FD792
+
+I=379
+KEY=9F1F3D042400F05802A6D8BC4D85E97F
+IV=C7898DA9ABF2A3D364C228A83525B04F
+CT=110CE84E5B81867CE4FCCD1BBB5FD792
+PT=7B94C0E4849AD65291F0F7BD464C544C
+
+I=380
+KEY=E48BFDE0A09A260A93562F010BC9BD33
+IV=00E079EEBC47AF3ED3796DBF4A2B55FC
+CT=7B94C0E4849AD65291F0F7BD464C544C
+PT=D6518596BB53E44452393BD4440D805C
+
+I=381
+KEY=32DA78761BC9C24EC16F14D54FC43D6F
+IV=03E168F8AF2303593E0F936648D253DC
+CT=D6518596BB53E44452393BD4440D805C
+PT=0C4B51FB33380BB215F29F3FCE7CA0DA
+
+I=382
+KEY=3E91298D28F1C9FCD49D8BEA81B89DB5
+IV=15E1ECD59BC092C974FA4738C66D9604
+CT=0C4B51FB33380BB215F29F3FCE7CA0DA
+PT=3FC98D86A558B711807930AAA391C9BF
+
+I=383
+KEY=0158A40B8DA97EED54E4BB402229540A
+IV=303BD4A407015A9E899816E0FABF288D
+CT=3FC98D86A558B711807930AAA391C9BF
+PT=85D77D90C312FE938F6C1983014BD572
+
+I=384
+KEY=848FD99B4EBB807EDB88A2C323628178
+IV=E018FA96FD433CFD162E8E67D4F37015
+CT=85D77D90C312FE938F6C1983014BD572
+PT=4F49C1740EA88B5767CE36C95158DD63
+
+I=385
+KEY=CBC618EF40130B29BC46940A723A5C1B
+IV=84013D3E2AA0C77650644CD6862096A7
+CT=4F49C1740EA88B5767CE36C95158DD63
+PT=E6F1409ABA890AC3A50FC4AAD82E1872
+
+I=386
+KEY=2D375875FA9A01EA194950A0AA144469
+IV=8BFD137593BFF254414349F1147B9BFF
+CT=E6F1409ABA890AC3A50FC4AAD82E1872
+PT=66F6E29696CFDC72EE905636614D2A72
+
+I=387
+KEY=4BC1BAE36C55DD98F7D90696CB596E1B
+IV=8EC295602FB66C4A2DCA65F66B07E010
+CT=66F6E29696CFDC72EE905636614D2A72
+PT=553B45792AE0625B357C4B68A4BB767F
+
+I=388
+KEY=1EFAFF9A46B5BFC3C2A54DFE6FE21864
+IV=5999E221475D06295451E52FF88F9F97
+CT=553B45792AE0625B357C4B68A4BB767F
+PT=FAB6F53166BFDB89DF68D46D423C243E
+
+I=389
+KEY=E44C0AAB200A644A1DCD99932DDE3C5A
+IV=49D1944CBD7BE00C671B8E996F9A3EB9
+CT=FAB6F53166BFDB89DF68D46D423C243E
+PT=308DDB3FE0415C46AE450C78FC5F2558
+
+I=390
+KEY=D4C1D194C04B380CB38895EBD1811902
+IV=9785FEE180794318514967B4199CFB93
+CT=308DDB3FE0415C46AE450C78FC5F2558
+PT=6659969D1BD493A3851E75981BACCCB0
+
+I=391
+KEY=B2984709DB9FABAF3696E073CA2DD5B2
+IV=4FD1DAE14DB75AC0E6C94388805AC3B5
+CT=6659969D1BD493A3851E75981BACCCB0
+PT=B56B950D84DCA131FD8A5E2601037B36
+
+I=392
+KEY=07F3D2045F430A9ECB1CBE55CB2EAE84
+IV=3ED415E7DDDADD2DC7F0376E6CA42EFE
+CT=B56B950D84DCA131FD8A5E2601037B36
+PT=8648F40FA13018563E6F1A799D9FCD91
+
+I=393
+KEY=81BB260BFE7312C8F573A42C56B16315
+IV=FEAF76717C0905A601509BD68C6D08E5
+CT=8648F40FA13018563E6F1A799D9FCD91
+PT=66DE6D7A74B36C7EE2737DA526F5C8CD
+
+I=394
+KEY=E7654B718AC07EB61700D9897044ABD8
+IV=2B808C340320DD64AB9278A9D9A3E247
+CT=66DE6D7A74B36C7EE2737DA526F5C8CD
+PT=9BB0D29CDA21452F60B5897186F3FAFB
+
+I=395
+KEY=7CD599ED50E13B9977B550F8F6B75123
+IV=D2EB48117E2E9FB2058800DE1A442799
+CT=9BB0D29CDA21452F60B5897186F3FAFB
+PT=489CDC3A2C1AE7510E03AE36D5EAB0E5
+
+I=396
+KEY=344945D77CFBDCC879B6FECE235DE1C6
+IV=427765E0671AA6D32634447687E9B209
+CT=489CDC3A2C1AE7510E03AE36D5EAB0E5
+PT=1D65D0E1235AE47DBCC2C65B59892C4C
+
+I=397
+KEY=292C95365FA138B5C57438957AD4CD8A
+IV=D75E9F074D965FE902287B3BB1483315
+CT=1D65D0E1235AE47DBCC2C65B59892C4C
+PT=E75B7AE5A8C3B93F15D0E3EBD04E1B4B
+
+I=398
+KEY=CE77EFD3F762818AD0A4DB7EAA9AD6C1
+IV=5455FD9A01E04E48CA777CF8185697ED
+CT=E75B7AE5A8C3B93F15D0E3EBD04E1B4B
+PT=11F4A35F6C225A9DF1CA6BAF92E11B07
+
+I=399
+KEY=DF834C8C9B40DB17216EB0D1387BCDC6
+IV=3C608F664492626B2208DC92E819411A
+CT=11F4A35F6C225A9DF1CA6BAF92E11B07
+PT=9B8FB71E035CEFF9CBFA1346E5ACEFE0
+
+==========
+
+KEYSIZE=192
+
+I=0
+KEY=000000000000000000000000000000000000000000000000
+IV=00000000000000000000000000000000
+CT=00000000000000000000000000000000
+PT=5DF678DD17BA4E75B61768C6ADEF7C7B
+
+I=1
+KEY=8AB601AF30C47B225DF678DD17BA4E75B61768C6ADEF7C7B
+IV=3B243F1A9BA094EE8AB601AF30C47B22
+CT=5DF678DD17BA4E75B61768C6ADEF7C7B
+PT=F9604074F8FA45AC71959888DD056F9F
+
+I=2
+KEY=D443B8E25A882D05A49638A9EF400BD9C782F04E70EA13E4
+IV=467E32A79443B0735EF5B94D6A4C5627
+CT=F9604074F8FA45AC71959888DD056F9F
+PT=98A957EA6DBE623B7E08F919812A3898
+
+I=3
+KEY=5742DCD38C8FD46D3C3F6F4382FE69E2B98A0957F1C02B7C
+IV=B9E1062EEDD9A1ED83016431D607F968
+CT=98A957EA6DBE623B7E08F919812A3898
+PT=AD6D29D6482764BB4BC27A87AE5CD877
+
+I=4
+KEY=B33625F7872DE4A191524695CAD90D59F24873D05F9CF30B
+IV=BD1AAC94D2D39445E474F9240BA230CC
+CT=AD6D29D6482764BB4BC27A87AE5CD877
+PT=DA5EB591FDC48F0D9E4EBD373E5717A3
+
+I=5
+KEY=35DA9F0A5DB187964B0CF304371D82546C06CEE761CBE4A8
+IV=4782561ED717916986ECBAFDDA9C6337
+CT=DA5EB591FDC48F0D9E4EBD373E5717A3
+PT=3F6E771434E26D4FA5A57CEF9DEE05D6
+
+I=6
+KEY=A8182E4F8FD8C7987462841003FFEF1BC9A3B208FC25E17E
+IV=093273C6E96EA5399DC2B145D269400E
+CT=3F6E771434E26D4FA5A57CEF9DEE05D6
+PT=F8FBFC8CBDD4AA8E8DA58DEA7F2F344C
+
+I=7
+KEY=71A581F408C35DA48C99789CBE2B459544063FE2830AD532
+IV=3900E8650CA62A25D9BDAFBB871B9A3C
+CT=F8FBFC8CBDD4AA8E8DA58DEA7F2F344C
+PT=B969AA871D3B35C260D8B36C7E9E8913
+
+I=8
+KEY=BCD0E4B5F0B7FB5035F0D21BA310705724DE8C8EFD945C21
+IV=0E2BCF13C2A18FF5CD756541F874A6F4
+CT=B969AA871D3B35C260D8B36C7E9E8913
+PT=6205EECCDD965D45339A2DFE85F52AD7
+
+I=9
+KEY=A2796321044D9F5557F53CD77E862D121744A170786176F6
+IV=8B935AB4C17D24D21EA98794F4FA6405
+CT=6205EECCDD965D45339A2DFE85F52AD7
+PT=6BC27204DA1B9BC27E463D0E71557D99
+
+I=10
+KEY=AD4506295D5309603C374ED3A49DB6D069029C7E09340B6F
+IV=A9AF68AB4EFDB7770F3C6508591E9635
+CT=6BC27204DA1B9BC27E463D0E71557D99
+PT=DB1576A8F1BD88F73E6938E72F9C6DCD
+
+I=11
+KEY=61ECB6C8660E5E20E722387B55203E27576BA49926A866A2
+IV=DF83746D72419F65CCA9B0E13B5D5740
+CT=DB1576A8F1BD88F73E6938E72F9C6DCD
+PT=150D14977B15FD304890D7B9C4F8536E
+
+I=12
+KEY=03679C91B6C57828F22F2CEC2E35C3171FFB7320E25035CC
+IV=59D101131EA2FD7F628B2A59D0CB2608
+CT=150D14977B15FD304890D7B9C4F8536E
+PT=7AE22B73B412A81D0BCF422C68DA37F8
+
+I=13
+KEY=9A087B9DBC37B12988CD079F9A276B0A1434310C8A8A0234
+IV=F26F03A3C84A49F0996FE70C0AF2C901
+CT=7AE22B73B412A81D0BCF422C68DA37F8
+PT=2D1584CE9B85E7264228A8AFF8FAFF01
+
+I=14
+KEY=07489932E5335B38A5D8835101A28C2C561C99A37270FD35
+IV=E76AB1C798119F5D9D40E2AF5904EA11
+CT=2D1584CE9B85E7264228A8AFF8FAFF01
+PT=C1067030225453E808F1FF324C44BE7F
+
+I=15
+KEY=DC3726E33013BC9964DEF36123F6DFC45EED66913E34434A
+IV=55010D6199E792E3DB7FBFD1D520E7A1
+CT=C1067030225453E808F1FF324C44BE7F
+PT=3AD7DBD96BB69D63BE39B9A16574AC74
+
+I=16
+KEY=EDD4EC10B074A36C5E0928B8484042A7E0D4DF305B40EF3E
+IV=18C6FE6D0A2FDD7E31E3CAF380671FF5
+CT=3AD7DBD96BB69D63BE39B9A16574AC74
+PT=3D5D82A4C06B9DDCCC8A6B8BF228482F
+
+I=17
+KEY=23824573BD3CE30D6354AA1C882BDF7B2C5EB4BBA968A711
+IV=E1DEAECBCFC06BCCCE56A9630D484061
+CT=3D5D82A4C06B9DDCCC8A6B8BF228482F
+PT=C0E5F9618F2FAB97EA82F8164DC89860
+
+I=18
+KEY=AAA43BC528933502A3B1537D070474ECC6DC4CADE4A03F71
+IV=2CE22FDF7E87B7CC89267EB695AFD60F
+CT=C0E5F9618F2FAB97EA82F8164DC89860
+PT=6942155FC9EF8F7CFE37CD6FED03CECF
+
+I=19
+KEY=A2686C442D636D31CAF34622CEEBFB9038EB81C209A3F1BE
+IV=B7772CF7B44B856308CC578105F05833
+CT=6942155FC9EF8F7CFE37CD6FED03CECF
+PT=6BA4C261F5173862A6789FB026099571
+
+I=20
+KEY=29F645A446D84EACA15784433BFCC3F29E931E722FAA64CF
+IV=15CA23A60D99FFF68B9E29E06BBB239D
+CT=6BA4C261F5173862A6789FB026099571
+PT=AA9E8C6497CAC6B0C8CC92F8DFE7B455
+
+I=21
+KEY=5E9165527010387F0BC90827AC360542565F8C8AF04DD09A
+IV=53193227307BBE49776720F636C876D3
+CT=AA9E8C6497CAC6B0C8CC92F8DFE7B455
+PT=7DA426C712E7F2F35087D6AA31CF56AB
+
+I=22
+KEY=92DC0EEE09F5169E766D2EE0BED1F7B106D85A20C1828631
+IV=85A3D20949963F95CC4D6BBC79E52EE1
+CT=7DA426C712E7F2F35087D6AA31CF56AB
+PT=09B9FF5E5833B6CE0010C3D0C4A84C19
+
+I=23
+KEY=C45B938E7C18B4107FD4D1BEE6E2417F06C899F0052ACA28
+IV=292A007187D730B956879D6075EDA28E
+CT=09B9FF5E5833B6CE0010C3D0C4A84C19
+PT=178F7AC0FF63C33683A001F5C4171316
+
+I=24
+KEY=03D99546E931B761685BAB7E1981824985689805C13DD93E
+IV=A8D8CD3B96215FCDC78206C895290371
+CT=178F7AC0FF63C33683A001F5C4171316
+PT=C39B82763CF6901170902BE6DC1B9305
+
+I=25
+KEY=B52384CAC0B230F5ABC0290825771258F5F8B3E31D264A3B
+IV=451968C3AA8D0319B6FA118C29838794
+CT=C39B82763CF6901170902BE6DC1B9305
+PT=85D827F61EC17FD00B10356292C863E2
+
+I=26
+KEY=DCF617A990AC4CBB2E180EFE3BB66D88FEE886818FEE29D9
+IV=575103DAEFD233E269D59363501E7C4E
+CT=85D827F61EC17FD00B10356292C863E2
+PT=535BAC956D5CAB917E1A1BC28E82F28F
+
+I=27
+KEY=14D0FCAFFD961CFD7D43A26B56EAC61980F29D43016CDB56
+IV=7DE780ACCF9F1896C826EB066D3A5046
+CT=535BAC956D5CAB917E1A1BC28E82F28F
+PT=7E73E89F187EA6D5F5A3044A19C85941
+
+I=28
+KEY=AF5BFBC086F1392203304AF44E9460CC7551990918A48217
+IV=633F0251217DECEDBB8B076F7B6725DF
+CT=7E73E89F187EA6D5F5A3044A19C85941
+PT=B0976DFD4F0620203AC4ED89D395BAFF
+
+I=29
+KEY=79FFB93DCF243047B3A72709019240EC4F957480CB3138E8
+IV=C1AAE3E35613DAADD6A442FD49D50965
+CT=B0976DFD4F0620203AC4ED89D395BAFF
+PT=5ECB838EC7F9F2E7ADBD719599F829B9
+
+I=30
+KEY=681F54ADA7685555ED6CA487C66BB20BE228051552C91151
+IV=4F00D9CD31BE1CC611E0ED90684C6512
+CT=5ECB838EC7F9F2E7ADBD719599F829B9
+PT=8DDA96BD88D3D756306D249ABF99F5F9
+
+I=31
+KEY=8663BEBF11817A3060B6323A4EB8655DD245218FED50E4A8
+IV=7CC24DC4B003DE90EE7CEA12B6E92F65
+CT=8DDA96BD88D3D756306D249ABF99F5F9
+PT=479E96E558540B71508FEF3173A6FC68
+
+I=32
+KEY=831519BE48B0021A2728A4DF16EC6E2C82CACEBE9EF618C0
+IV=59FFA792DC8618070576A7015931782A
+CT=479E96E558540B71508FEF3173A6FC68
+PT=080EA053745BEEBDBC5F7D964EEBD2F7
+
+I=33
+KEY=AFC20AF72699543A2F26048C62B780913E95B328D01DCA37
+IV=4E5BDD875324CAC02CD713496E295620
+CT=080EA053745BEEBDBC5F7D964EEBD2F7
+PT=B5A58D345C0260A9E274E2E593B76C44
+
+I=34
+KEY=46AEAF002B9A297E9A8389B83EB5E038DCE151CD43AAA673
+IV=C67419FDA89E68B1E96CA5F70D037D44
+CT=B5A58D345C0260A9E274E2E593B76C44
+PT=5200F2D475CA388841CB0DD02C7EB7F6
+
+I=35
+KEY=1598E4DD7DA3D7B0C8837B6C4B7FD8B09D2A5C1D6FD41185
+IV=9F5C74A1FE2DFF2153364BDD5639FECE
+CT=5200F2D475CA388841CB0DD02C7EB7F6
+PT=B2639C2D26BF2CAF2371CA3A4F3D3476
+
+I=36
+KEY=FE63AA4A158B41AE7AE0E7416DC0F41FBE5B962720E925F3
+IV=2DC59704D531C890EBFB4E976828961E
+CT=B2639C2D26BF2CAF2371CA3A4F3D3476
+PT=C758ADC41E334CCBF34C40E2AEAA3852
+
+I=37
+KEY=86B214FA7F89CE06BDB84A8573F3B8D44D17D6C58E431DA1
+IV=D0982ADEECE45CCC78D1BEB06A028FA8
+CT=C758ADC41E334CCBF34C40E2AEAA3852
+PT=F8E0AA1E780F18A50371CBCB1B63E83F
+
+I=38
+KEY=C0C34A59DC653DCE4558E09B0BFCA0714E661D0E9520F59E
+IV=A252B0F29766A24B46715EA3A3ECF3C8
+CT=F8E0AA1E780F18A50371CBCB1B63E83F
+PT=554B524391A7A1679210CFC0152A65CE
+
+I=39
+KEY=3CF3D7DDFFF704231013B2D89A5B0116DC76D2CE800A9050
+IV=42EE716B821C18FCFC309D84239239ED
+CT=554B524391A7A1679210CFC0152A65CE
+PT=3273E6C51751407B7E4ECDED7970746D
+
+I=40
+KEY=7FCC684C43B958F02260541D8D0A416DA2381F23F97AE43D
+IV=A4FCB2B8AB7158B9433FBF91BC4E5CD3
+CT=3273E6C51751407B7E4ECDED7970746D
+PT=D90B75848AC14ACA3CAD9AF2A15F315F
+
+I=41
+KEY=240724B451241314FB6B219907CB0BA79E9585D15825D562
+IV=5C4FA1918B04D5F85BCB4CF8129D4BE4
+CT=D90B75848AC14ACA3CAD9AF2A15F315F
+PT=753C59B87C45B21D527527C6C2DDEB0D
+
+I=42
+KEY=F0BEECC2DB5D16F98E5778217B8EB9BACCE0A2179AF83E6F
+IV=4E41A4AB69AEE73FD4B9C8768A7905ED
+CT=753C59B87C45B21D527527C6C2DDEB0D
+PT=156E851810ADB0BF2D28B6150D32CAC7
+
+I=43
+KEY=C2FB954C95633B5B9B39FD396B230905E1C8140297CAF4A8
+IV=983906FA7F156CF33245798E4E3E2DA2
+CT=156E851810ADB0BF2D28B6150D32CAC7
+PT=26E671DACE32070A601796207BD045B5
+
+I=44
+KEY=BF0BD4C6DDBE22DABDDF8CE3A5110E0F81DF8222EC1AB11D
+IV=B3188D29356783AF7DF0418A48DD1981
+CT=26E671DACE32070A601796207BD045B5
+PT=ADAD9072859250A8590F6F54C24E5A77
+
+I=45
+KEY=2E4F07AD61768CC010721C9120835EA7D8D0ED762E54EB6A
+IV=639F27016A9D99B99144D36BBCC8AE1A
+CT=ADAD9072859250A8590F6F54C24E5A77
+PT=AC8AD3933D51D5D71CA90FB73A53F6AD
+
+I=46
+KEY=9963998A6F982462BCF8CF021DD28B70C479E2C114071DC7
+IV=B2A3ACB0CE942F13B72C9E270EEEA8A2
+CT=AC8AD3933D51D5D71CA90FB73A53F6AD
+PT=7319F2825648168F07D525618DA9979A
+
+I=47
+KEY=417FD42690AAE310CFE13D804B9A9DFFC3ACC7A099AE8A5D
+IV=EBB0EF7CE1ACF152D81C4DACFF32C772
+CT=7319F2825648168F07D525618DA9979A
+PT=4FC19392439D6CBE6699419355E0590B
+
+I=48
+KEY=30CD3A2A0910C7268020AE120807F141A5358633CC4ED356
+IV=4DCACE79E4C3ADFE71B2EE0C99BA2436
+CT=4FC19392439D6CBE6699419355E0590B
+PT=047FF92A523900A3C46D906163927DDD
+
+I=49
+KEY=F13EE3ACC9C19E4C845F57385A3EF1E261581652AFDCAE8B
+IV=E260680204844E6FC1F3D986C0D1596A
+CT=047FF92A523900A3C46D906163927DDD
+PT=2DAE78D178D069918CCC11D675E09655
+
+I=50
+KEY=91556C720DC982D5A9F12FE922EE9873ED940784DA3C38DE
+IV=A4E4973E74B61315606B8FDEC4081C99
+CT=2DAE78D178D069918CCC11D675E09655
+PT=6315A6A029ED7FC5AB3CD38D8DAE561A
+
+I=51
+KEY=9120A23E63AF3BC2CAE489490B03E7B646A8D40957926EC4
+IV=C02DA24531C794BD0075CE4C6E66B917
+CT=6315A6A029ED7FC5AB3CD38D8DAE561A
+PT=65A796C69B769E59D34AD19803F117C6
+
+I=52
+KEY=5C6847E25C66145DAF431F8F907579EF95E2059154637902
+IV=0D72A6B0F3959C89CD48E5DC3FC92F9F
+CT=65A796C69B769E59D34AD19803F117C6
+PT=70770D19D03DF488FB627F460A225F39
+
+I=53
+KEY=F5ECA4C905FF0EC2DF34129640488D676E807AD75E41263B
+IV=2F60424B5062D978A984E32B59991A9F
+CT=70770D19D03DF488FB627F460A225F39
+PT=C8A66A2CD18286D2148230BAB7D81E11
+
+I=54
+KEY=FF86E251C5EC6129179278BA91CA0BB57A024A6DE999382A
+IV=CC7330AE077936B10A6A4698C0136FEB
+CT=C8A66A2CD18286D2148230BAB7D81E11
+PT=FC0B47BA3E51927A632F457A919818DC
+
+I=55
+KEY=5C0A7344D6FD6983EB993F00AF9B99CF192D0F17780120F6
+IV=CA119AEE5576E06EA38C9115131108AA
+CT=FC0B47BA3E51927A632F457A919818DC
+PT=AEEDB360C58C4CDC7ACE87AA1A4B785B
+
+I=56
+KEY=426948BD499E8A9845748C606A17D51363E388BD624A58AD
+IV=920C491DE39D52501E633BF99F63E31B
+CT=AEEDB360C58C4CDC7ACE87AA1A4B785B
+PT=737ECC4294FF69495DC37DC795EC13CE
+
+I=57
+KEY=F8AD0E545AA212E6360A4022FEE8BC5A3E20F57AF7A64B63
+IV=B975B70450A41A2DBAC446E9133C987E
+CT=737ECC4294FF69495DC37DC795EC13CE
+PT=3E7CDC26CCC69E02D08248224A22961E
+
+I=58
+KEY=C2834233A26DCD8A08769C04322E2258EEA2BD58BD84DD7D
+IV=A88326DC57AB80FC3A2E4C67F8CFDF6C
+CT=3E7CDC26CCC69E02D08248224A22961E
+PT=88177B6502254344A364023BCAD29E79
+
+I=59
+KEY=962D892D6CDED6798061E761300B611C4DC6BF6377564304
+IV=D95CFF470B1796D754AECB1ECEB31BF3
+CT=88177B6502254344A364023BCAD29E79
+PT=A10FA825EB6DA0E242D9A381F607472D
+
+I=60
+KEY=3ADA98C76065214A216E4F44DB66C1FE0F1F1CE281510429
+IV=FBD25798351AF35DACF711EA0CBBF733
+CT=A10FA825EB6DA0E242D9A381F607472D
+PT=6B5EE3A222DF46560A12E91C006D303F
+
+I=61
+KEY=C6AB975CF71B6DDF4A30ACE6F9B987A8050DF5FE813C3416
+IV=6CDB3875008754DAFC710F9B977E4C95
+CT=6B5EE3A222DF46560A12E91C006D303F
+PT=A0047B92A93ACF32138A818B6E32B3EE
+
+I=62
+KEY=FFD0E16A5C955EBAEA34D7745083489A16877475EF0E87F8
+IV=F7061CA37B11E445397B7636AB8E3365
+CT=A0047B92A93ACF32138A818B6E32B3EE
+PT=1707FC063700E98FF5FDA98A07A8A1C7
+
+I=63
+KEY=AA71EC7061FA246CFD332B726783A115E37ADDFFE8A6263F
+IV=1853E27FC0689E6755A10D1A3D6F7AD6
+CT=1707FC063700E98FF5FDA98A07A8A1C7
+PT=06320FA4C0E2F42B364B991243FA053D
+
+I=64
+KEY=D8685685696CBF5CFB0124D6A761553ED53144EDAB5C2302
+IV=E19A3BEC7EBCA3C87219BAF508969B30
+CT=06320FA4C0E2F42B364B991243FA053D
+PT=BB70503E9715D653710C0630211755A7
+
+I=65
+KEY=28C2AFFA406EF763407174E83074836DA43D42DD8A4B76A5
+IV=5F3BCA36562AFA82F0AAF97F2902483F
+CT=BB70503E9715D653710C0630211755A7
+PT=D632FEF42560770DF318C570AFC85285
+
+I=66
+KEY=260B8E0723E9AF3D96438A1C1514F460572587AD25832420
+IV=328A42D3898A81C20EC921FD6387585E
+CT=D632FEF42560770DF318C570AFC85285
+PT=B1C847FFF455D002E55FCFAF4A4F69A4
+
+I=67
+KEY=F39D3CD6A68DC6BC278BCDE3E1412462B27A48026FCC4D84
+IV=C89E7B4C1BAED0FAD596B2D185646981
+CT=B1C847FFF455D002E55FCFAF4A4F69A4
+PT=9C484252E1FE52CD2DFCCAA3E0118F07
+
+I=68
+KEY=61A9714C87B94F27BBC38FB100BF76AF9F8682A18FDDC283
+IV=56B7D716EC6F9A6D92344D9A2134899B
+CT=9C484252E1FE52CD2DFCCAA3E0118F07
+PT=85A142323B9877E86F3A5874EA613E87
+
+I=69
+KEY=B504BE17C673E81F3E62CD833B270147F0BCDAD565BCFC04
+IV=BEF2C82884510475D4ADCF5B41CAA738
+CT=85A142323B9877E86F3A5874EA613E87
+PT=53D0EF74268F55C1B6CA84415E5A2F6F
+
+I=70
+KEY=1A63CC27BE45C5106DB222F71DA8548646765E943BE6D36B
+IV=CC958CC3874510F0AF67723078362D0F
+CT=53D0EF74268F55C1B6CA84415E5A2F6F
+PT=7B7DB0F3EFAD244FFCC6991452001DF6
+
+I=71
+KEY=4B17520C49F46EAF16CF9204F20570C9BAB0C78069E6CE9D
+IV=48D7C0690532AFCC51749E2BF7B1ABBF
+CT=7B7DB0F3EFAD244FFCC6991452001DF6
+PT=DD0661DCA2BE8C20E95B3A84CCACDB10
+
+I=72
+KEY=1ADE412393310021CBC9F3D850BBFCE953EBFD04A54A158D
+IV=4B96B2D0CCADFF7D51C9132FDAC56E8E
+CT=DD0661DCA2BE8C20E95B3A84CCACDB10
+PT=E505435777F3781121A4A374684E3268
+
+I=73
+KEY=493467065AE405B82ECCB08F274884F8724F5E70CD0427E5
+IV=1E8116EB95B94AFC53EA2625C9D50599
+CT=E505435777F3781121A4A374684E3268
+PT=EF4B4E997DA0DCCBDBB36C020D03E8B5
+
+I=74
+KEY=4C94816DF6EBDEF5C187FE165AE85833A9FC3272C007CF50
+IV=29094410F6017E5805A0E66BAC0FDB4D
+CT=EF4B4E997DA0DCCBDBB36C020D03E8B5
+PT=FA9BAB377C654ED894024BEBDCED2FA0
+
+I=75
+KEY=697A0BC179C07A633B1C5521268D16EB3DFE79991CEAE0F0
+IV=83DD12597A405FB725EE8AAC8F2BA496
+CT=FA9BAB377C654ED894024BEBDCED2FA0
+PT=DD1FDA63382552D007F6F8E995820640
+
+I=76
+KEY=D40786ED2A6C15E8E6038F421EA8443B3A0881708968E6B0
+IV=2F3AE5594D9CCEDCBD7D8D2C53AC6F8B
+CT=DD1FDA63382552D007F6F8E995820640
+PT=C5FF0EB50BA651F436D0566385860ADA
+
+I=77
+KEY=9D47680C0159F69A23FC81F7150E15CF0CD8D7130CEEEC6A
+IV=1BCFAD6802C41B9A4940EEE12B35E372
+CT=C5FF0EB50BA651F436D0566385860ADA
+PT=67AE61A77D77CBFD48C080B21313BBAB
+
+I=78
+KEY=86E61E031542D2DB4452E0506879DE32441857A11FFD57C1
+IV=3DF4DA1F65C739511BA1760F141B2441
+CT=67AE61A77D77CBFD48C080B21313BBAB
+PT=68C8512217CB9C3BBF28011FA5BED044
+
+I=79
+KEY=4F93757DE614CB1D2C9AB1727FB24209FB3056BEBA438785
+IV=B2C15424EF4E4637C9756B7EF35619C6
+CT=68C8512217CB9C3BBF28011FA5BED044
+PT=233898C850826172965695499748A1B0
+
+I=80
+KEY=C56E54BBB54B22CC0FA229BA2F30237B6D66C3F72D0B2635
+IV=DC2FF5992D9383EF8AFD21C6535FE9D1
+CT=233898C850826172965695499748A1B0
+PT=70069F5E963A820D640B40697BD24716
+
+I=81
+KEY=A1EF05CB5AAE7A977FA4B6E4B90AA176096D839E56D96123
+IV=EE8CB982124A394C64815170EFE5585B
+CT=70069F5E963A820D640B40697BD24716
+PT=B136CA2EF42A9CFF53410554B28A8F65
+
+I=82
+KEY=ACEC084A8CED2F4FCE927CCA4D203D895A2C86CAE453EE46
+IV=515D8B6C167EC8570D030D81D64355D8
+CT=B136CA2EF42A9CFF53410554B28A8F65
+PT=123600CD1B5A664430413021DDC8CBBE
+
+I=83
+KEY=8325A9391B4E106ADCA47C07567A5BCD6A6DB6EB399B25F8
+IV=5A55A24EC8154E532FC9A17397A33F25
+CT=123600CD1B5A664430413021DDC8CBBE
+PT=8ECCA03E10D415557C4E7D92DDBFD791
+
+I=84
+KEY=DB877966BE0E84575268DC3946AE4E981623CB79E424F269
+IV=659705F3774E141758A2D05FA540943D
+CT=8ECCA03E10D415557C4E7D92DDBFD791
+PT=CB70B675AC6BF92237F1C479516E7E6A
+
+I=85
+KEY=59027658DEC2B5DE99186A4CEAC5B7BA21D20F00B54A8C03
+IV=C9B803CE2D57D26F82850F3E60CC3189
+CT=CB70B675AC6BF92237F1C479516E7E6A
+PT=5D99D06E9BEB82AB1CE22201E8467DBC
+
+I=86
+KEY=652E430F984201E0C481BA22712E35113D302D015D0CF1BF
+IV=1838FACBEAC13CF73C2C35574680B43E
+CT=5D99D06E9BEB82AB1CE22201E8467DBC
+PT=11D7AED0B552D62677DEB874BF7CF8ED
+
+I=87
+KEY=8377A2C11B73082DD55614F2C47CE3374AEE9575E2700952
+IV=068170C7E11427DFE659E1CE833109CD
+CT=11D7AED0B552D62677DEB874BF7CF8ED
+PT=74B108D32ABE8401D22F2C3FB008F670
+
+I=88
+KEY=7B89A5C45B0A22BBA1E71C21EEC2673698C1B94A5278FF22
+IV=5283DAD6FA2B605DF8FE070540792A96
+CT=74B108D32ABE8401D22F2C3FB008F670
+PT=7883BD8C4DA81C21C4A5847AD801B7AE
+
+I=89
+KEY=101261A4D23FDA13D964A1ADA36A7B175C643D308A79488C
+IV=E2ED92DE4829CB526B9BC4608935F8A8
+CT=7883BD8C4DA81C21C4A5847AD801B7AE
+PT=C865B27C21F6F6E681759C318607D2B9
+
+I=90
+KEY=E6A6A13B7A64EB51110113D1829C8DF1DD11A1010C7E9A35
+IV=AB325AD4F1FF1C52F6B4C09FA85B3142
+CT=C865B27C21F6F6E681759C318607D2B9
+PT=E31D7AC0E8ADB302BC6C23A0B1D693ED
+
+I=91
+KEY=64D366C4F61E139BF21C69116A313EF3617D82A1BDA809D8
+IV=A5201D1770A12A898275C7FF8C7AF8CA
+CT=E31D7AC0E8ADB302BC6C23A0B1D693ED
+PT=CAE6A97EE64228EEEF02E135944C5C62
+
+I=92
+KEY=B006CEF05093DE2238FAC06F8C73161D8E7F639429E455BA
+IV=62BD7E3EA22E26BAD4D5A834A68DCDB9
+CT=CAE6A97EE64228EEEF02E135944C5C62
+PT=B7AEF117099F799BB0752C7260A2DFB5
+
+I=93
+KEY=160AFF18C06B6C4A8F54317885EC6F863E0A4FE649468A0F
+IV=AEBB967838133F64A60C31E890F8B268
+CT=B7AEF117099F799BB0752C7260A2DFB5
+PT=81CCC6EDAD41D9C7986D4E175C71551D
+
+I=94
+KEY=21112CBE896259CE0E98F79528ADB641A66701F11537DF12
+IV=B695BBE7FA331039371BD3A649093584
+CT=81CCC6EDAD41D9C7986D4E175C71551D
+PT=9039E01C6485040A2EDAF4C27FE93870
+
+I=95
+KEY=60272333C1B4CCC39EA117894C28B24B88BDF5336ADEE762
+IV=4EE830907337D60241360F8D48D6950D
+CT=9039E01C6485040A2EDAF4C27FE93870
+PT=44D359DBE4BE436D5133CD81B72DB5C7
+
+I=96
+KEY=25C676A781511A98DA724E52A896F126D98E38B2DDF352A5
+IV=38491C9FD517260445E1559440E5D65B
+CT=44D359DBE4BE436D5133CD81B72DB5C7
+PT=7B47F95ED30563BE218E40DB4EAAE836
+
+I=97
+KEY=59A7B7512B5DC429A135B70C7B939298F80078699359BA93
+IV=1FD8B8BA8B0492E67C61C1F6AA0CDEB1
+CT=7B47F95ED30563BE218E40DB4EAAE836
+PT=C417F6A6824B165D4C26D631F77E45AC
+
+I=98
+KEY=82E6CF234BC0AA10652241AAF9D884C5B426AE586427FF3F
+IV=5FB017B65FE4AF34DB417872609D6E39
+CT=C417F6A6824B165D4C26D631F77E45AC
+PT=41EC9A06B318A4D06636ED5403F46CB7
+
+I=99
+KEY=82D69A1D747CF6E024CEDBAC4AC02015D210430C67D39388
+IV=1CC1F56321366F420030553E3FBC5CF0
+CT=41EC9A06B318A4D06636ED5403F46CB7
+PT=38E467F81D919F0A1704E9F5CDF4D5FC
+
+I=100
+KEY=29EFCA26B9C67E141C2ABC545751BF1FC514AAF9AA274674
+IV=A83BDBF4326AE806AB39503BCDBA88F4
+CT=38E467F81D919F0A1704E9F5CDF4D5FC
+PT=A08359A20D6F405018F8180A3E8D0FD1
+
+I=101
+KEY=AB20AC8C3C5DA5BEBCA9E5F65A3EFF4FDDECB2F394AA49A5
+IV=A14B10E1A998B04E82CF66AA859BDBAA
+CT=A08359A20D6F405018F8180A3E8D0FD1
+PT=A16C303138057144A3ECA63E7398DC93
+
+I=102
+KEY=86C5E861B9CEAF041DC5D5C7623B8E0B7E0014CDE7329536
+IV=181D943EA950561D2DE544ED85930ABA
+CT=A16C303138057144A3ECA63E7398DC93
+PT=EA1A2E30D890D01979D2BCE1EBE6C922
+
+I=103
+KEY=90321C401E4B6B30F7DFFBF7BAAB5E1207D2A82C0CD45C14
+IV=12BDB944D898BC5A16F7F421A785C434
+CT=EA1A2E30D890D01979D2BCE1EBE6C922
+PT=C0D620FCF33031DAD617ADBE8F6D13AC
+
+I=104
+KEY=84964C3B41FE8E4F3709DB0B499B6FC8D1C5059283B94FB8
+IV=0615AD27B29C55F814A4507B5FB5E57F
+CT=C0D620FCF33031DAD617ADBE8F6D13AC
+PT=EC4B9AEDBE44C4B74B693D08AA1D175A
+
+I=105
+KEY=6C6361F2C87BC168DB4241E6F7DFAB7F9AAC389A29A458E2
+IV=E79F33FFCD79681CE8F52DC989854F27
+CT=EC4B9AEDBE44C4B74B693D08AA1D175A
+PT=F34D426225ADEC3BD2580BF21EF24B3E
+
+I=106
+KEY=FDA3FB79F1A16865280F0384D272474448F43368375613DC
+IV=1DFE18B10032D35F91C09A8B39DAA90D
+CT=F34D426225ADEC3BD2580BF21EF24B3E
+PT=E14841B0D0CC1E698DE8053B9F1621E1
+
+I=107
+KEY=562D3BF792909255C947423402BE592DC51C3653A840323D
+IV=247A46C43AE54F1FAB8EC08E6331FA30
+CT=E14841B0D0CC1E698DE8053B9F1621E1
+PT=D21381B5032426EC3582BBD23739E04E
+
+I=108
+KEY=9D375E6E32C30A801B54C381019A7FC1F09E8D819F79D273
+IV=E05018C26DC38BBDCB1A6599A05398D5
+CT=D21381B5032426EC3582BBD23739E04E
+PT=82034FF505FE67B94373770348A934E5
+
+I=109
+KEY=7D1A900B515478DB99578C7404641878B3EDFA82D7D0E696
+IV=498AEA38AB55250CE02DCE656397725B
+CT=82034FF505FE67B94373770348A934E5
+PT=018B5B1787138D222F6B39C1291ECD2C
+
+I=110
+KEY=E74B55A39F67C54298DCD7638377955A9C86C343FECE2BBA
+IV=DD89DF396236F9A59A51C5A8CE33BD99
+CT=018B5B1787138D222F6B39C1291ECD2C
+PT=CABCB7EA14E821726602272A46CEB825
+
+I=111
+KEY=D3FFFE0F27D9200352606089979FB428FA84E469B800939F
+IV=A707D154BAC28BDC34B4ABACB8BEE541
+CT=CABCB7EA14E821726602272A46CEB825
+PT=0840D09DF2B14ED4B340D32101D68A54
+
+I=112
+KEY=485EC313821A37095A20B014652EFAFC49C43748B9D619CB
+IV=ADEF6A8A49BF208B9BA13D1CA5C3170A
+CT=0840D09DF2B14ED4B340D32101D68A54
+PT=5EB0166FB04AF38F9EA60929FD641844
+
+I=113
+KEY=E841074638A154D90490A67BD5640973D7623E6144B2018F
+IV=B1956D86A4F79E40A01FC455BABB63D0
+CT=5EB0166FB04AF38F9EA60929FD641844
+PT=2ECBDAFBD0336A436D89FC12944750EC
+
+I=114
+KEY=17E86798DB7A64E42A5B7C8005576330BAEBC273D0F55163
+IV=0AFFE19CA1425218FFA960DEE3DB303D
+CT=2ECBDAFBD0336A436D89FC12944750EC
+PT=A326D8C07EF7A21302A3C6A9C67C371A
+
+I=115
+KEY=D1A6F2AB7C130A60897DA4407BA0C123B84804DA16896679
+IV=6F630069CD0333BDC64E9533A7696E84
+CT=A326D8C07EF7A21302A3C6A9C67C371A
+PT=6D06DDFB9B12A71298E32318F582EF72
+
+I=116
+KEY=C7D58104581CB5C5E47B79BBE0B2663120AB27C2E30B890B
+IV=80E47BA8410247C5167373AF240FBFA5
+CT=6D06DDFB9B12A71298E32318F582EF72
+PT=E1391A50F140E255A9B2E628F25B9B1D
+
+I=117
+KEY=00D8EEC433F7D68E054263EB11F284648919C1EA11501216
+IV=96F652822C5D4496C70D6FC06BEB634B
+CT=E1391A50F140E255A9B2E628F25B9B1D
+PT=1418A2DC8D6DBA4942932D6944011D8A
+
+I=118
+KEY=71D444358CCCF986115AC1379C9F3E2DCB8AEC8355510F9C
+IV=410374DE0D8A79FA710CAAF1BF3B2F08
+CT=1418A2DC8D6DBA4942932D6944011D8A
+PT=A70A2C48CF5786868844274B8C493C56
+
+I=119
+KEY=B9FD9626EC74A129B650ED7F53C8B8AB43CECBC8D91833CA
+IV=8362FAE290801C25C829D21360B858AF
+CT=A70A2C48CF5786868844274B8C493C56
+PT=3484BA42558B199E8477B8F8280CDE91
+
+I=120
+KEY=94CAEE912A7B443582D4573D0643A135C7B97330F114ED5B
+IV=F6ABE3F0A7FFC9E02D3778B7C60FE51C
+CT=3484BA42558B199E8477B8F8280CDE91
+PT=5D79433F85C7D4C258487080E340F049
+
+I=121
+KEY=1D2F762CF08FAE0ADFAD1402838475F79FF103B012541D12
+IV=A0C57652FBF9107C89E598BDDAF4EA3F
+CT=5D79433F85C7D4C258487080E340F049
+PT=C51891EA2E68BC60E84912A91F470201
+
+I=122
+KEY=9E691D03A3AEB6491AB585E8ADECC99777B811190D131F13
+IV=8426C338234DB9E183466B2F53211843
+CT=C51891EA2E68BC60E84912A91F470201
+PT=F946FD67DD7F92A7A6B93B4F71F70243
+
+I=123
+KEY=61EA6FD274C07ADDE3F3788F70935B30D1012A567CE41D50
+IV=2C2AF70B07E9E6F9FF8372D1D76ECC94
+CT=F946FD67DD7F92A7A6B93B4F71F70243
+PT=B4CB0EFF14F8CDC693CC8E7DCEE8E0B0
+
+I=124
+KEY=84F27E5BF8B55DA657387670646B96F642CDA42BB20CFDE0
+IV=693782638B439464E51811898C75277B
+CT=B4CB0EFF14F8CDC693CC8E7DCEE8E0B0
+PT=EF6DDB56AAE9CFFE128FB3776DD94D20
+
+I=125
+KEY=5B1111EADAECDD73B855AD26CE8259085042175CDFD5B0C0
+IV=A14AAEF7A1BF063BDFE36FB1225980D5
+CT=EF6DDB56AAE9CFFE128FB3776DD94D20
+PT=4ACC6AF28293A647093AE788BA778835
+
+I=126
+KEY=A924DC707FB16DF1F299C7D44C11FF4F5978F0D465A238F5
+IV=3F7E73BFA24B0C02F235CD9AA55DB082
+CT=4ACC6AF28293A647093AE788BA778835
+PT=5A7989DC61AD6B66B3E83A29168BEDB9
+
+I=127
+KEY=164FBEF9EBAEEF03A8E04E082DBC9429EA90CAFD7329D54C
+IV=2FB4F1A000B78156BF6B6289941F82F2
+CT=5A7989DC61AD6B66B3E83A29168BEDB9
+PT=246A94AB8488B39C52DE68E8CA5AE0D2
+
+I=128
+KEY=B1F4A368B64A78EC8C8ADAA3A93427B5B84EA215B973359E
+IV=5D178EC8305B804FA7BB1D915DE497EF
+CT=246A94AB8488B39C52DE68E8CA5AE0D2
+PT=F7C758F8DC8FC0891907EBBF299F70B8
+
+I=129
+KEY=9161A39C256814AA7B4D825B75BBE73CA14949AA90EC4526
+IV=C87E61A9434EB29F209500F493226C46
+CT=F7C758F8DC8FC0891907EBBF299F70B8
+PT=E2D82C5506BEFA7D7BF032E4C72141CF
+
+I=130
+KEY=0BFDA1B2CF4B15199995AE0E73051D41DAB97B4E57CD04E9
+IV=5D00992780D9832B9A9C022EEA2301B3
+CT=E2D82C5506BEFA7D7BF032E4C72141CF
+PT=F3A0DF1793FC88117E87478FD9E5A1A8
+
+I=131
+KEY=F8F5F6016FECDCAF6A357119E0F99550A43E3CC18E28A541
+IV=2800EECA83EB078CF30857B3A0A7C9B6
+CT=F3A0DF1793FC88117E87478FD9E5A1A8
+PT=BEB572C53E9985218ED9012BAB4A9F5B
+
+I=132
+KEY=84F3E0D153E140D6D48003DCDE6010712AE73DEA25623A1A
+IV=E2BEAF80F4A1DDA27C0616D03C0D9C79
+CT=BEB572C53E9985218ED9012BAB4A9F5B
+PT=7F4B21C4B7466149CB890B77AC538752
+
+I=133
+KEY=B69E5A72FE9B1B85ABCB221869267138E16E369D8931BD48
+IV=FE0A667B9B2BDD29326DBAA3AD7A5B53
+CT=7F4B21C4B7466149CB890B77AC538752
+PT=4B239C8F83F0A10DC6A3497CC3CF9C8E
+
+I=134
+KEY=0BCF87D2538E0EADE0E8BE97EAD6D03527CD7FE14AFE21C6
+IV=878250C5EA7834CFBD51DDA0AD151528
+CT=4B239C8F83F0A10DC6A3497CC3CF9C8E
+PT=89F2B4B8C5AB2988CDEA61F4D4A1BCD4
+
+I=135
+KEY=97A4FDCD2E0C993E691A0A2F2F7DF9BDEA271E159E5F9D12
+IV=95E34D44C3E2FE319C6B7A1F7D829793
+CT=89F2B4B8C5AB2988CDEA61F4D4A1BCD4
+PT=C622E28004842564F193C0E58AB40FCB
+
+I=136
+KEY=38F0A45980CEF0B9AF38E8AF2BF9DCD91BB4DEF014EB92D9
+IV=1BC195727D154539AF545994AEC26987
+CT=C622E28004842564F193C0E58AB40FCB
+PT=DF360FBC1607BCC1E6EE9088AEE62EC7
+
+I=137
+KEY=6638E0333D7A6765700EE7133DFE6018FD5A4E78BA0DBC1E
+IV=F0AB65A69AA4486A5EC8446ABDB497DC
+CT=DF360FBC1607BCC1E6EE9088AEE62EC7
+PT=9A8E5BFE223FA9D747164FC1C98B9CDC
+
+I=138
+KEY=5103611D32D7A1EFEA80BCED1FC1C9CFBA4C01B9738620C2
+IV=A6617B5DA41B2A32373B812E0FADC68A
+CT=9A8E5BFE223FA9D747164FC1C98B9CDC
+PT=F0143DD4EC3A85F9FA4D5579BD7268A1
+
+I=139
+KEY=64FD310AF27CF98C1A948139F3FB4C36400154C0CEF44863
+IV=EBCB744B477F25E635FE5017C0AB5863
+CT=F0143DD4EC3A85F9FA4D5579BD7268A1
+PT=C5C1FED629BF81EE343E4DAEE6BC4D44
+
+I=140
+KEY=9390B012FA7D48D9DF557FEFDA44CDD8743F196E28480527
+IV=7AF352D33C08F3FEF76D81180801B155
+CT=C5C1FED629BF81EE343E4DAEE6BC4D44
+PT=26C4460F0B79E16263C38C240C276E5C
+
+I=141
+KEY=F578E5DF6818CB58F99139E0D13D2CBA17FC954A246F6B7B
+IV=05DA148A4EB4D12966E855CD92658381
+CT=26C4460F0B79E16263C38C240C276E5C
+PT=E0E249ADB3A39EE2BB48959426874123
+
+I=142
+KEY=F23F67282BAFE10E1973704D629EB258ACB400DE02E82A58
+IV=7748B1652DE54EF9074782F743B72A56
+CT=E0E249ADB3A39EE2BB48959426874123
+PT=C2299AAE24C941DC44E5D492BC492FED
+
+I=143
+KEY=5CAC16BD99EC5067DB5AEAE34657F384E851D44CBEA105B5
+IV=4F599B9C20378305AE937195B243B169
+CT=C2299AAE24C941DC44E5D492BC492FED
+PT=780DA1D6FD961DA4756375A15B8BA620
+
+I=144
+KEY=9FF7C1766F7F6F9FA3574B35BBC1EE209D32A1EDE52AA395
+IV=044A8C7FFE220414C35BD7CBF6933FF8
+CT=780DA1D6FD961DA4756375A15B8BA620
+PT=E63FE8BE6566E9ECCCDBEC442BCCCBD5
+
+I=145
+KEY=3EA408C4CD15E6F24568A38BDEA707CC51E94DA9CEE66840
+IV=05DE81CD5892F1FEA153C9B2A26A896D
+CT=E63FE8BE6566E9ECCCDBEC442BCCCBD5
+PT=19F5E5DDDF0F6FABA9B16B732C6058B8
+
+I=146
+KEY=29FF0DD567A810385C9D465601A86867F85826DAE28630F8
+IV=0A2A8BF3BE53E2B5175B0511AABDF6CA
+CT=19F5E5DDDF0F6FABA9B16B732C6058B8
+PT=41FCD9F8972431F43669863F37B4A18C
+
+I=147
+KEY=842E4C2F46849E731D619FAE968C5993CE31A0E5D5329174
+IV=1EABD419CA4C0D0BADD141FA212C8E4B
+CT=41FCD9F8972431F43669863F37B4A18C
+PT=9857CFE1CFE1046F88DF3EB8ECC92E40
+
+I=148
+KEY=8EE3344CCB9DE2038536504F596D5DFC46EE9E5D39FBBF34
+IV=FA266CF1AF82A2250ACD78638D197C70
+CT=9857CFE1CFE1046F88DF3EB8ECC92E40
+PT=DE4C55865FB82BDA1FC0D024791C1B22
+
+I=149
+KEY=DEEEC86215A6098D5B7A05C906D57626592E4E7940E7A416
+IV=F9B4CFCA36A1B0AB500DFC2EDE3BEB8E
+CT=DE4C55865FB82BDA1FC0D024791C1B22
+PT=077F866BF30097D12650855C71B7DB9C
+
+I=150
+KEY=50872D11A2E463D65C0583A2F5D5E1F77F7ECB2531507F8A
+IV=53D4E4CE2C06FCC38E69E573B7426A5B
+CT=077F866BF30097D12650855C71B7DB9C
+PT=670BBCB81CDE03B883D9B784124F5851
+
+I=151
+KEY=7DE3AF7C8550901C3B0E3F1AE90BE24FFCA77CA1231F27DB
+IV=C26330B1219C4B4A2D64826D27B4F3CA
+CT=670BBCB81CDE03B883D9B784124F5851
+PT=D6141C300F5E5119E1B5F4BBF415A6DD
+
+I=152
+KEY=BB126D64220A8DB9ED1A232AE655B3561D12881AD70A8106
+IV=74D773D0F053239CC6F1C218A75A1DA5
+CT=D6141C300F5E5119E1B5F4BBF415A6DD
+PT=8F742130206F1047FE9CAAE4F2C31B19
+
+I=153
+KEY=9845C3A02214A55D626E021AC63AA311E38E22FE25C99A1F
+IV=7EC0B4E8BD4BD3EB2357AEC4001E28E4
+CT=8F742130206F1047FE9CAAE4F2C31B19
+PT=47D0D28AF3164CC77FBAB5C015CAC1C9
+
+I=154
+KEY=BBC47FAB874E0ED425BED090352CEFD69C34973E30035BD6
+IV=833EC00D894BD8502381BC0BA55AAB89
+CT=47D0D28AF3164CC77FBAB5C015CAC1C9
+PT=3202B04CFC260747BF839FF754A01E26
+
+I=155
+KEY=BCC028DA5F286DE017BC60DCC90AE89123B708C964A345F0
+IV=8BCC8079D2175F4407045771D8666334
+CT=3202B04CFC260747BF839FF754A01E26
+PT=75E9FBADAD8885FB2398427EE94C5899
+
+I=156
+KEY=352B0CD3E3BA0EB462559B7164826D6A002F4AB78DEF1D69
+IV=0B159F18C1F33EA389EB2409BC926354
+CT=75E9FBADAD8885FB2398427EE94C5899
+PT=90DA906982058C84D2E75B5DAE0EA756
+
+I=157
+KEY=6F32D4393B37EA77F28F0B18E687E1EED2C811EA23E1BA3F
+IV=2F5C35DA76038E4F5A19D8EAD88DE4C3
+CT=90DA906982058C84D2E75B5DAE0EA756
+PT=705C22072FDFB807A49BAE0FD4D254AF
+
+I=158
+KEY=5740616769DDF57482D3291FC95859E97653BFE5F733EE90
+IV=B276B0CE56828D683872B55E52EA1F03
+CT=705C22072FDFB807A49BAE0FD4D254AF
+PT=A966EE217CF2BDBC17A0BB55AE769FEB
+
+I=159
+KEY=C9E379BDBC05CC402BB5C73EB5AAE45561F304B05945717B
+IV=E1F41EF2147CB5CE9EA318DAD5D83934
+CT=A966EE217CF2BDBC17A0BB55AE769FEB
+PT=239D761F1F0437935464C4959546B6BB
+
+I=160
+KEY=7B2C4F503FCC91AE0828B121AAAED3C63597C025CC03C7C0
+IV=6F90097C7822030DB2CF36ED83C95DEE
+CT=239D761F1F0437935464C4959546B6BB
+PT=499477B6476BA58CAEF81290ABDD46C4
+
+I=161
+KEY=42BC1C4F29D1801D41BCC697EDC5764A9B6FD2B567DE8104
+IV=1571EE53AE1ACAEF3990531F161D11B3
+CT=499477B6476BA58CAEF81290ABDD46C4
+PT=ACC1FB947EB4C7F115871859CD254D96
+
+I=162
+KEY=9BE24C041BF4DEECED7D3D039371B1BB8EE8CAECAAFBCC92
+IV=E24F4DBEF2122A73D95E504B32255EF1
+CT=ACC1FB947EB4C7F115871859CD254D96
+PT=85DC9D7ADF342B0733CF9812CFD58F0A
+
+I=163
+KEY=83BEBEB5727649F268A1A0794C459ABCBD2752FE652E4398
+IV=AF0690E77B1F140B185CF2B16982971E
+CT=85DC9D7ADF342B0733CF9812CFD58F0A
+PT=7ED8B4DCBD1D13BEA5C819E99ECF75AA
+
+I=164
+KEY=7020802D561D88AD167914A5F158890218EF4B17FBE13632
+IV=F0AC93D8DDD31D5BF39E3E98246BC15F
+CT=7ED8B4DCBD1D13BEA5C819E99ECF75AA
+PT=C81F0464C2DE212229370C7A4ED2E890
+
+I=165
+KEY=39F8EA2D638410ABDE6610C13386A82031D8476DB533DEA2
+IV=FD6338FAE6F6B00B49D86A0035999806
+CT=C81F0464C2DE212229370C7A4ED2E890
+PT=23A0FA99C632BCC62A035A09514C3EBA
+
+I=166
+KEY=52FA33F30EFD8D0FFDC6EA58F5B414E61BDB1D64E47FE018
+IV=04C6E0136D8E04C16B02D9DE6D799DA4
+CT=23A0FA99C632BCC62A035A09514C3EBA
+PT=9F7F1081AE4B6AD51D395D764D2D5B68
+
+I=167
+KEY=95C21BD9257B233A62B9FAD95BFF7E3306E24012A952BB70
+IV=72410E03AAE65889C738282A2B86AE35
+CT=9F7F1081AE4B6AD51D395D764D2D5B68
+PT=5F088092968BF4AF04BF862A6721DF2B
+
+I=168
+KEY=058F749326AE1DD53DB17A4BCD748A9C025DC638CE73645B
+IV=D678325E266D12D7904D6F4A03D53EEF
+CT=5F088092968BF4AF04BF862A6721DF2B
+PT=15670F60D1D70E129418AC14A425DD70
+
+I=169
+KEY=23D2D59C5EF4AF3D28D6752B1CA3848E96456A2C6A56B92B
+IV=BB7B672A91E9A61A265DA10F785AB2E8
+CT=15670F60D1D70E129418AC14A425DD70
+PT=3273AC9D250F729AE790A941739C79BF
+
+I=170
+KEY=E11B1F94517914C81AA5D9B639ACF61471D5C36D19CAC094
+IV=AB84F623EFA11728C2C9CA080F8DBBF5
+CT=3273AC9D250F729AE790A941739C79BF
+PT=9B135880CB56A8E6CF3A364CC6E02175
+
+I=171
+KEY=66F867085DBE626581B68136F2FA5EF2BEEFF521DF2AE1E1
+IV=01ED899C8DC9C09E87E3789C0CC776AD
+CT=9B135880CB56A8E6CF3A364CC6E02175
+PT=681D6FC5447CCFE1152156CFF6172B6A
+
+I=172
+KEY=98505FCD27DAB39EE9ABEEF3B6869113ABCEA3EE293DCA8B
+IV=A58C8285C31035B1FEA838C57A64D1FB
+CT=681D6FC5447CCFE1152156CFF6172B6A
+PT=6E30DF3FBD67A5FD491E315EF3A268A0
+
+I=173
+KEY=9F904A41C19B57A9879B31CC0BE134EEE2D092B0DA9FA22B
+IV=6F46DCB3A84FD96907C0158CE641E437
+CT=6E30DF3FBD67A5FD491E315EF3A268A0
+PT=5B4980E24D8F9CABE017991326FBBE95
+
+I=174
+KEY=A330D5A6779731D6DCD2B12E466EA84502C70BA3FC641CBE
+IV=C5BDAB77E0CA95463CA09FE7B60C667F
+CT=5B4980E24D8F9CABE017991326FBBE95
+PT=7324530BF94BD80D286C9BE2FE4113D3
+
+I=175
+KEY=20F008DE76D7968AAFF6E225BF2570482AAB904102250F6D
+IV=32F5EC4AEBB997C583C0DD780140A75C
+CT=7324530BF94BD80D286C9BE2FE4113D3
+PT=B163425AB21DF6AFBD2C7000E777E902
+
+I=176
+KEY=0F48153B232E71F41E95A07F0D3886E79787E041E552E66F
+IV=3D1854E0C481B28E2FB81DE555F9E77E
+CT=B163425AB21DF6AFBD2C7000E777E902
+PT=EB1A6C86C3811E3081325F35BA7F2DCA
+
+I=177
+KEY=96EE2134FD40CA34F58FCCF9CEB998D716B5BF745F2DCBA5
+IV=8629366A8B8E266499A6340FDE6EBBC0
+CT=EB1A6C86C3811E3081325F35BA7F2DCA
+PT=E9675AF0035C3F8E9D5E58D0652BF5C7
+
+I=178
+KEY=BF754C828BFE309B1CE89609CDE5A7598BEBE7A43A063E62
+IV=566D5FCEC3FF7D43299B6DB676BEFAAF
+CT=E9675AF0035C3F8E9D5E58D0652BF5C7
+PT=24B4DA85EEFAA123948C6B5E0E07EB08
+
+I=179
+KEY=F0223B4AF5C885B4385C4C8C231F067A1F678CFA3401D56A
+IV=67B98EC651B057104F5777C87E36B52F
+CT=24B4DA85EEFAA123948C6B5E0E07EB08
+PT=753CFEBBB9E623453B8BB2976B8D7BD4
+
+I=180
+KEY=04665169E091DEF74D60B2379AF9253F24EC3E6D5F8CAEBE
+IV=BC3806A9E56A1DACF4446A2315595B43
+CT=753CFEBBB9E623453B8BB2976B8D7BD4
+PT=6949284723B4F795D530B366FAE70876
+
+I=181
+KEY=9CABB1CFD4E46F8324299A70B94DD2AAF1DC8D0BA56BA6C8
+IV=8C864563BB8D45A098CDE0A63475B174
+CT=6949284723B4F795D530B366FAE70876
+PT=D43FED9A25C62349787F0336BFFBBFEB
+
+I=182
+KEY=4407065E88AE79D9F01677EA9C8BF1E389A38E3D1A901923
+IV=539CC5888B34198FD8ACB7915C4A165A
+CT=D43FED9A25C62349787F0336BFFBBFEB
+PT=030733E175916579F582A778B261DA1C
+
+I=183
+KEY=84D1EE80E8FA54DEF311440BE91A949A7C212945A8F1C33F
+IV=78306F4F56DEF759C0D6E8DE60542D07
+CT=030733E175916579F582A778B261DA1C
+PT=F7B1ABE4B4AE3CB726F9A88B06D4552A
+
+I=184
+KEY=E885BEA6176A75D804A0EFEF5DB4A82D5AD881CEAE259615
+IV=3AC80B78F744208A6C545026FF902106
+CT=F7B1ABE4B4AE3CB726F9A88B06D4552A
+PT=DA984A2C346A4B758E066EB509079168
+
+I=185
+KEY=2E0317B2DB3F9893DE38A5C369DEE358D4DEEF7BA722077D
+IV=FC74E03B1068A6FEC686A914CC55ED4B
+CT=DA984A2C346A4B758E066EB509079168
+PT=21F473636EF27B91F29BB1CE67908763
+
+I=186
+KEY=850E1B37E1F7DD89FFCCD6A0072C98C926455EB5C0B2801E
+IV=7DFD76EE7EF97796AB0D0C853AC8451A
+CT=21F473636EF27B91F29BB1CE67908763
+PT=9EEF6E211CC8EDBD3C4FBE3E14B13C70
+
+I=187
+KEY=655D365D66CAA5C36123B8811BE475741A0AE08BD403BC6E
+IV=33318C04CC0B3CBDE0532D6A873D784A
+CT=9EEF6E211CC8EDBD3C4FBE3E14B13C70
+PT=8AB49333CA7B2E58E7B24536BB34DEE7
+
+I=188
+KEY=BE3C315647F981DCEB972BB2D19F5B2CFDB8A5BD6F376289
+IV=79D06A0D66B5C2B1DB61070B2133241F
+CT=8AB49333CA7B2E58E7B24536BB34DEE7
+PT=323D1E775FD729005DA7A2853A855ED4
+
+I=189
+KEY=3126E544A65724C4D9AA35C58E48722CA01F073855B23C5D
+IV=CC5C9D95685AF1228F1AD412E1AEA518
+CT=323D1E775FD729005DA7A2853A855ED4
+PT=E283016FEDADEBA2BEC7ADB5A8DEA8B9
+
+I=190
+KEY=BCF052AFAFA4852D3B2934AA63E5998E1ED8AA8DFD6C94E4
+IV=2753144E0A26D9FE8DD6B7EB09F3A1E9
+CT=E283016FEDADEBA2BEC7ADB5A8DEA8B9
+PT=9A9BB977D53BBD47550DC60A49AFA0FA
+
+I=191
+KEY=ECB724A85CBC7B58A1B28DDDB6DE24C94BD56C87B4C3341E
+IV=27F910046A94AA3B50477607F318FE75
+CT=9A9BB977D53BBD47550DC60A49AFA0FA
+PT=AF4C7AC3B02C1B077E8F97B59AE52A21
+
+I=192
+KEY=BCA9E9794F9004AB0EFEF71E06F23FCE355AFB322E261E3F
+IV=8AF06705FE272571501ECDD1132C7FF3
+CT=AF4C7AC3B02C1B077E8F97B59AE52A21
+PT=A97DEE2A64DFA7C198B6A4F21E80F7DF
+
+I=193
+KEY=10DCC14B9A309E25A7831934622D980FADEC5FC030A6E9E0
+IV=B04E1C6FC657B8AEAC752832D5A09A8E
+CT=A97DEE2A64DFA7C198B6A4F21E80F7DF
+PT=34E8228A24C7A16F9ED3F4B9A94AA70D
+
+I=194
+KEY=9CB6EE6AAEFAFBED936B3BBE46EA3960333FAB7999EC4EED
+IV=6A966EBB8F80A1608C6A2F2134CA65C8
+CT=34E8228A24C7A16F9ED3F4B9A94AA70D
+PT=99E6CA896906CBAA9B8D01155D1DB162
+
+I=195
+KEY=461916712E8BD6F10A8DF1372FECF2CAA8B2AA6CC4F1FF8F
+IV=EAF849974783FAA7DAAFF81B80712D1C
+CT=99E6CA896906CBAA9B8D01155D1DB162
+PT=6009B53EB4690C1F1F10639F1FD7640A
+
+I=196
+KEY=5B9B91A966F9CE146A8444099B85FED5B7A2C9F3DB269B85
+IV=3FB045D182F781EB1D8287D8487218E5
+CT=6009B53EB4690C1F1F10639F1FD7640A
+PT=88ED4BC34A27F4C4B480B99857EBF541
+
+I=197
+KEY=404F7D8B0E966F02E2690FCAD1A20A110322706B8CCD6EC4
+IV=49C0F4571BAEBE4C1BD4EC22686FA116
+CT=88ED4BC34A27F4C4B480B99857EBF541
+PT=B88F0E3E01FEDF97766AC6B762D2EBC3
+
+I=198
+KEY=CB2EA99F330A3A865AE601F4D05CD5867548B6DCEE1F8507
+IV=2518DA0D88C02EC38B61D4143D9C5584
+CT=B88F0E3E01FEDF97766AC6B762D2EBC3
+PT=C1C167FF37E89937DCB8D79C9BC9EC74
+
+I=199
+KEY=913C795CF72CD1219B27660BE7B44CB1A9F0614075D66973
+IV=37769A59390261FB5A12D0C3C426EBA7
+CT=C1C167FF37E89937DCB8D79C9BC9EC74
+PT=64D912270A1E60192CDAAD8168219E56
+
+I=200
+KEY=05F19DF919E44144FFFE742CEDAA2CA8852ACCC11DF7F725
+IV=63E9D4D1BDD7FEAD94CDE4A5EEC89065
+CT=64D912270A1E60192CDAAD8168219E56
+PT=C9AD2DBB1C686A67A3E21A5659576A2B
+
+I=201
+KEY=099D0DCE5E4E194236535997F1C246CF26C8D69744A09D0E
+IV=A01E3F917EF4652F0C6C903747AA5806
+CT=C9AD2DBB1C686A67A3E21A5659576A2B
+PT=244C740B4B136C6C480D0147163868D1
+
+I=202
+KEY=EA1F242E9C75C712121F2D9CBAD12AA36EC5D7D05298F5DF
+IV=C9D2288C473BCB3EE38229E0C23BDE50
+CT=244C740B4B136C6C480D0147163868D1
+PT=A6B125A9C570CC3ECBB5D302ADB96E34
+
+I=203
+KEY=CD5D7C91FBDC81A1B4AE08357FA1E69DA57004D2FF219BEB
+IV=871F525F8ED73B7F274258BF67A946B3
+CT=A6B125A9C570CC3ECBB5D302ADB96E34
+PT=0F9862A4A21E1FB365135C07577FB3EE
+
+I=204
+KEY=F7D9B8C22BDC8005BB366A91DDBFF92EC06358D5A85E2805
+IV=01BB0A9A8737C19D3A84C453D00001A4
+CT=0F9862A4A21E1FB365135C07577FB3EE
+PT=D833DB436E1751B882D03FADF683690B
+
+I=205
+KEY=83F81E3CED72F22F6305B1D2B3A8A89642B367785EDD410E
+IV=80E0E7001CCA60CA7421A6FEC6AE722A
+CT=D833DB436E1751B882D03FADF683690B
+PT=0AE2C64D2C577C420F26F2F48AA58D62
+
+I=206
+KEY=63310E5F2F8F0E0769E7779F9FFFD4D44D95958CD478CC6C
+IV=57E54995CDC9417DE0C91063C2FDFC28
+CT=0AE2C64D2C577C420F26F2F48AA58D62
+PT=B0E2976AA3891A2C71AFEB063E3C4383
+
+I=207
+KEY=F3AE2989B3980DC9D905E0F53C76CEF83C3A7E8AEA448FEF
+IV=999DD6C2B1C528E2909F27D69C1703CE
+CT=B0E2976AA3891A2C71AFEB063E3C4383
+PT=16F8A305177ECDBA15403FE5D8EEF60D
+
+I=208
+KEY=52CF17D8DEA4CE5ACFFD43F02B080342297A416F32AA79E2
+IV=C9F5BC961057F845A1613E516D3CC393
+CT=16F8A305177ECDBA15403FE5D8EEF60D
+PT=A607A3EE165E82711B30B44CF4E0C4CF
+
+I=209
+KEY=E22ADE79E75FE58E69FAE01E3D568133324AF523C64ABD2D
+IV=E153F25DD207351AB0E5C9A139FB2BD4
+CT=A607A3EE165E82711B30B44CF4E0C4CF
+PT=5191CDD0D077AD6BE956AF8E8E39FECA
+
+I=210
+KEY=38C58EA4EA1E8D4C386B2DCEED212C58DB1C5AAD487343E7
+IV=F55357187F06B142DAEF50DD0D4168C2
+CT=5191CDD0D077AD6BE956AF8E8E39FECA
+PT=F63A42508522E5F09C31F160298E8E6F
+
+I=211
+KEY=8C29CD4F1330EF25CE516F9E6803C9A8472DABCD61FDCD88
+IV=2CBD520E6F6F89C7B4EC43EBF92E6269
+CT=F63A42508522E5F09C31F160298E8E6F
+PT=E58ED2EA8671DC5D527CDE01C6D9655D
+
+I=212
+KEY=3650C9671F38CD752BDFBD74EE7215F5155175CCA724A8D5
+IV=73CA969AECA5574BBA7904280C082250
+CT=E58ED2EA8671DC5D527CDE01C6D9655D
+PT=5FFCACC68357B6709F5B10D48C65EA40
+
+I=213
+KEY=6F68A078A75FF5A1742311B26D25A3858A0A65182B414295
+IV=DEA2D7D8F9FE3E7D5938691FB86738D4
+CT=5FFCACC68357B6709F5B10D48C65EA40
+PT=10BBA695F25C1F9412DB80F59F937F84
+
+I=214
+KEY=9E08E5F9EEC5A7606498B7279F79BC1198D1E5EDB4D23D11
+IV=20E4DE61513233E5F1604581499A52C1
+CT=10BBA695F25C1F9412DB80F59F937F84
+PT=36CAF539734BCAF8250595E5E5DB3E94
+
+I=215
+KEY=F72A5636B3A2D23B5252421EEC3276E9BDD4700851090385
+IV=9DEBE05128A2A1A06922B3CF5D67755B
+CT=36CAF539734BCAF8250595E5E5DB3E94
+PT=C64074C9A34850C6FD1B12CD8AE9EF30
+
+I=216
+KEY=D74FABF587AB10AA941236D74F7A262F40CF62C5DBE0ECB5
+IV=DEF3A637247B78C02065FDC33409C291
+CT=C64074C9A34850C6FD1B12CD8AE9EF30
+PT=DF663CE4199BC64ACB9B6F99D69EC679
+
+I=217
+KEY=8D12BAEA80612A284B740A3356E1E0658B540D5C0D7E2ACC
+IV=7D9C0365E66F1A355A5D111F07CA3A82
+CT=DF663CE4199BC64ACB9B6F99D69EC679
+PT=CD1BCBDCE7F8C008177E25B83604EE83
+
+I=218
+KEY=57B4196767474175866FC1EFB119206D9C2A28E43B7AC44F
+IV=41846FA05FC28ABCDAA6A38DE7266B5D
+CT=CD1BCBDCE7F8C008177E25B83604EE83
+PT=CD7E96FE44368C4AD22E9D4F6BE3C2C2
+
+I=219
+KEY=CBA15BF34D728F0E4B115711F52FAC274E04B5AB5099068D
+IV=873A6522E20108C09C1542942A35CE7B
+CT=CD7E96FE44368C4AD22E9D4F6BE3C2C2
+PT=BCC88D6EAF2E41D9AA6E7C91DADCF92E
+
+I=220
+KEY=D3071140E7C7E244F7D9DA7F5A01EDFEE46AC93A8A45FFA3
+IV=A50F782EA949C2A718A64AB3AAB56D4A
+CT=BCC88D6EAF2E41D9AA6E7C91DADCF92E
+PT=1FFD3EC8E0D0AD8F3D23961703C0C445
+
+I=221
+KEY=3F44AB6E12394D24E824E4B7BAD14071D9495F2D89853BE6
+IV=501500DC8A97D00BEC43BA2EF5FEAF60
+CT=1FFD3EC8E0D0AD8F3D23961703C0C445
+PT=1D3D85A9A4BF101E12CC79640D716AC6
+
+I=222
+KEY=D6B97A7D0CEBEA71F519611E1E6E506FCB85264984F45120
+IV=84933D2D2F1F6C13E9FDD1131ED2A755
+CT=1D3D85A9A4BF101E12CC79640D716AC6
+PT=A2228D0483F9CF74CAA301FD30D7DB68
+
+I=223
+KEY=E86CCBF22BAF7B31573BEC1A9D979F1B012627B4B4238A48
+IV=4AE5BFEB7168981E3ED5B18F27449140
+CT=A2228D0483F9CF74CAA301FD30D7DB68
+PT=D43E1D2C7447B7C08BCA25F8371AEECF
+
+I=224
+KEY=0279786975DB97998305F136E9D028DB8AEC024C83396487
+IV=2FC19D77503C0296EA15B39B5E74ECA8
+CT=D43E1D2C7447B7C08BCA25F8371AEECF
+PT=4F97B6C0B7D10763CD5CE3A45855FEC0
+
+I=225
+KEY=7F842708B71AD43BCC9247F65E012FB847B0E1E8DB6C9A47
+IV=BAC3ED277430C4537DFD5F61C2C143A2
+CT=4F97B6C0B7D10763CD5CE3A45855FEC0
+PT=067B1521895AE654CA0C20492A9714B8
+
+I=226
+KEY=2FA21F709793A1C7CAE952D7D75BC9EC8DBCC1A1F1FB8EFF
+IV=66014BDC0AD70ABB50263878208975FC
+CT=067B1521895AE654CA0C20492A9714B8
+PT=E07E7A1D3F39E45E3A755A82EE3C2EBC
+
+I=227
+KEY=671468BAD93EDBD32A9728CAE8622DB2B7C99B231FC7A043
+IV=47BFF88E3EC2E8DC48B677CA4EAD7A14
+CT=E07E7A1D3F39E45E3A755A82EE3C2EBC
+PT=0933D51670E8918147A56816B838BC74
+
+I=228
+KEY=9749A2F6B448445023A4FDDC988ABC33F06CF335A7FF1C37
+IV=58F8C33F4725EED2F05DCA4C6D769F83
+CT=0933D51670E8918147A56816B838BC74
+PT=E90570CDFC2CDCC99826780CA7CD7A1C
+
+I=229
+KEY=C43D753C2489B403CAA18D1164A660FA684A8B390032662B
+IV=C4027E5BF29E96A65374D7CA90C1F053
+CT=E90570CDFC2CDCC99826780CA7CD7A1C
+PT=65B6C303491459554CDDA630AAB36C12
+
+I=230
+KEY=32F2C804DF89C908AF174E122DB239AF24972D09AA810A39
+IV=51DE94724DCE9B10F6CFBD38FB007D0B
+CT=65B6C303491459554CDDA630AAB36C12
+PT=A0B1694685785EFBDD6DB8E4FC312BC4
+
+I=231
+KEY=9431549183D690920FA62754A8CA6754F9FA95ED56B021FD
+IV=5CBDC9F06F45D2F5A6C39C955C5F599A
+CT=A0B1694685785EFBDD6DB8E4FC312BC4
+PT=C271A8F639D1A293F4B8899428F618C2
+
+I=232
+KEY=0AA1211F2A2134DACDD78FA2911BC5C70D421C797E46393F
+IV=E52D7ACAF5DFAF799E90758EA9F7A448
+CT=C271A8F639D1A293F4B8899428F618C2
+PT=AB7968C2A1859D5AEBFAEB201910B672
+
+I=233
+KEY=88BFBDDC6D21FC0E66AEE760309E589DE6B8F75967568F4D
+IV=15AF9C49191BF995821E9CC34700C8D4
+CT=AB7968C2A1859D5AEBFAEB201910B672
+PT=59D394BB9C41BE21C050A9DF2DD94C2B
+
+I=234
+KEY=05AB922FA8B6F5FF3F7D73DBACDFE6BC26E85E864A8FC366
+IV=0FB568270892E7A98D142FF3C59709F1
+CT=59D394BB9C41BE21C050A9DF2DD94C2B
+PT=43F89BAE0DCCB0EAF30411E6239A753C
+
+I=235
+KEY=7A7ED7932DED53767C85E875A1135656D5EC4F606915B65A
+IV=48F1E1DAEE9C16CD7FD545BC855BA689
+CT=43F89BAE0DCCB0EAF30411E6239A753C
+PT=8196A2F49E2508443F86B294D71A5D5E
+
+I=236
+KEY=8955F595C21BF3AAFD134A813F365E12EA6AFDF4BE0FEB04
+IV=B3DEB1ED557CB477F32B2206EFF6A0DC
+CT=8196A2F49E2508443F86B294D71A5D5E
+PT=5ED45F8741E7FC5C77CAACA9D3DFA26D
+
+I=237
+KEY=09205C9C2A528A5BA3C715067ED1A24E9DA0515D6DD04969
+IV=3742941BC0992AAC8075A909E84979F1
+CT=5ED45F8741E7FC5C77CAACA9D3DFA26D
+PT=F60C9F9616A03B40655CB733EE1C3B68
+
+I=238
+KEY=46DAA0A9A034745355CB8A906871990EF8FCE66E83CC7201
+IV=A3E1EA7D9E5BA6CE4FFAFC358A66FE08
+CT=F60C9F9616A03B40655CB733EE1C3B68
+PT=E73F7E14A3A245B1E594F659D996ED06
+
+I=239
+KEY=DA145A69C9D459E1B2F4F484CBD3DCBF1D6810375A5A9F07
+IV=F5D4EB0EAB3486D29CCEFAC069E02DB2
+CT=E73F7E14A3A245B1E594F659D996ED06
+PT=52651C2039168170765B235D85BF6CEC
+
+I=240
+KEY=61CD045E05969B9FE091E8A4F2C55DCF6B33336ADFE5F3EB
+IV=F7162437A85A186ABBD95E37CC42C27E
+CT=52651C2039168170765B235D85BF6CEC
+PT=665C920C4BB95B5C716D60AE9C30DB1B
+
+I=241
+KEY=BDF9F289D095660D86CD7AA8B97C06931A5E53C443D528F0
+IV=ADD7416105DB0CF0DC34F6D7D503FD92
+CT=665C920C4BB95B5C716D60AE9C30DB1B
+PT=F6E1D36CF7D41F70885587A85B897EA2
+
+I=242
+KEY=4CBAF7692571D8C5702CA9C44EA819E3920BD46C185C5652
+IV=9FBF3815905FCD9FF14305E0F5E4BEC8
+CT=F6E1D36CF7D41F70885587A85B897EA2
+PT=137DB7F20F98671E37F55E401D0482E2
+
+I=243
+KEY=CEBF572BB09CC72963511E3641307EFDA5FE8A2C0558D4B0
+IV=0C3951BDCA9582CA8205A04295ED1FEC
+CT=137DB7F20F98671E37F55E401D0482E2
+PT=72125C79A48573158496EFCC5CA552D4
+
+I=244
+KEY=0D8978CF8179CBBF1143424FE5B50DE8216865E059FD8664
+IV=898422AB0DB951B1C3362FE431E50C96
+CT=72125C79A48573158496EFCC5CA552D4
+PT=6B12016832DE435A963FFFA857824CF7
+
+I=245
+KEY=180D2DA794FEAF777A514327D76B4EB2B7579A480E7FCA93
+IV=0B47A508EAD8008015845568158764C8
+CT=6B12016832DE435A963FFFA857824CF7
+PT=18693A241FB5687CF3A793B9B7EE4B15
+
+I=246
+KEY=3D6C36453DCA611462387903C8DE26CE44F009F1B9918186
+IV=857CC19C3E72C1AD25611BE2A934CE63
+CT=18693A241FB5687CF3A793B9B7EE4B15
+PT=4E04BD363AFC26BDDD3D98892A7C705A
+
+I=247
+KEY=8B626E8D8E075BCE2C3CC435F222007399CD917893EDF1DC
+IV=6E4FCD034F6E2AF5B60E58C8B3CD3ADA
+CT=4E04BD363AFC26BDDD3D98892A7C705A
+PT=06FB2C371C3F54518AA0A2766CE1CCF3
+
+I=248
+KEY=A5ECEB5BAE22C2E72AC7E802EE1D5422136D330EFF0C3D2F
+IV=4A23E1EFBB43855E2E8E85D620259929
+CT=06FB2C371C3F54518AA0A2766CE1CCF3
+PT=D7DE2C298EB1EF273A6386986BDEC555
+
+I=249
+KEY=B25537EEFD5BDA7AFD19C42B60ACBB05290EB59694D2F87A
+IV=9034BBDBF74A369E17B9DCB55379189D
+CT=D7DE2C298EB1EF273A6386986BDEC555
+PT=0F4A1CEA83DA845DEC063ADFF173F424
+
+I=250
+KEY=39FEF1C45697DABCF253D8C1E3763F58C5088F4965A10C5E
+IV=2B5EF64E50A2CF5F8BABC62AABCC00C6
+CT=0F4A1CEA83DA845DEC063ADFF173F424
+PT=CE27F8AF55009D3658D166B960CA12D6
+
+I=251
+KEY=5657BBA1106032F13C74206EB676A26E9DD9E9F0056B1E88
+IV=CE96953F749BBFD66FA94A6546F7E84D
+CT=CE27F8AF55009D3658D166B960CA12D6
+PT=BF1458E052637EFC0EEF352621606029
+
+I=252
+KEY=A1BC53DEFD62921A8360788EE415DC929336DCD6240B7EA1
+IV=B944FC42142E4940F7EBE87FED02A0EB
+CT=BF1458E052637EFC0EEF352621606029
+PT=E4D96706DB5B0DA8FA429BB65BFBE4D8
+
+I=253
+KEY=DAC8C0328BA4104167B91F883F4ED13A697447607FF09A79
+IV=A8D8E3A3BB687ECC7B7493EC76C6825B
+CT=E4D96706DB5B0DA8FA429BB65BFBE4D8
+PT=1B11FF1367FE94F7759D1BEC40B8FDCC
+
+I=254
+KEY=03AE3AA5E62CA4927CA8E09B58B045CD1CE95C8C3F4867B5
+IV=35D7DB1466E14E3ED966FA976D88B4D3
+CT=1B11FF1367FE94F7759D1BEC40B8FDCC
+PT=0989D688C947C616AC13B63892E35E74
+
+I=255
+KEY=EAD5A60BB601C1147521361391F783DBB0FAEAB4ADAB39C1
+IV=59BA56CC11EFA9A2E97B9CAE502D6586
+CT=0989D688C947C616AC13B63892E35E74
+PT=978C150575871FB2C8847AA0CB092108
+
+I=256
+KEY=C608EE8A971A0383E2AD2316E4709C69787E901466A218C9
+IV=253A79448D79B0B72CDD4881211BC297
+CT=978C150575871FB2C8847AA0CB092108
+PT=D08629CCCF6B869B10768DE9E2984B2E
+
+I=257
+KEY=D8EB4FC4230D3E39322B0ADA2B1B1AF268081DFD843A53E7
+IV=E9A7FDB26A37B6601EE3A14EB4173DBA
+CT=D08629CCCF6B869B10768DE9E2984B2E
+PT=E320AECF3803401AB95E09EB50A6EDA5
+
+I=258
+KEY=E3F18E12233B5A30D10BA41513185AE8D1561416D49CBE42
+IV=4C6B62E3E6658BE73B1AC1D600366409
+CT=E320AECF3803401AB95E09EB50A6EDA5
+PT=D29E97683C9989C75D5D73EAADC23EE2
+
+I=259
+KEY=7D9DEAA58D97A2FC0395337D2F81D32F8C0B67FC795E80A0
+IV=414A2961119CE4D79E6C64B7AEACF8CC
+CT=D29E97683C9989C75D5D73EAADC23EE2
+PT=8D859D878DF32FDD26AF4984D48A1BD2
+
+I=260
+KEY=E4A19E3554E8D73B8E10AEFAA272FCF2AAA42E78ADD49B72
+IV=9DF8066FCF854065993C7490D97F75C7
+CT=8D859D878DF32FDD26AF4984D48A1BD2
+PT=7B524B71439722F0555D4681F7EEAAC9
+
+I=261
+KEY=0C93CDDA4435E903F542E58BE1E5DE02FFF968F95A3A31BB
+IV=9529BF1B1ACEEDA5E83253EF10DD3E38
+CT=7B524B71439722F0555D4681F7EEAAC9
+PT=8C8ECC9829F06F73497EA90D48CD7FC5
+
+I=262
+KEY=637747C6EF7B72B579CC2913C815B171B687C1F412F74E7E
+IV=ADC9666D259469516FE48A1CAB4E9BB6
+CT=8C8ECC9829F06F73497EA90D48CD7FC5
+PT=6E416C2563212821F0D8E7D75297B11F
+
+I=263
+KEY=7E4BB22E1A7C4E25178D4536AB349950465F26234060FF61
+IV=C3BE9A54FDDA99731D3CF5E8F5073C90
+CT=6E416C2563212821F0D8E7D75297B11F
+PT=EFC73DFA5FB87EA16284E25D22360C2F
+
+I=264
+KEY=62B7D329DC5EA208F84A78CCF48CE7F124DBC47E6256F34E
+IV=E2145312DF24CBDB1CFC6107C622EC2D
+CT=EFC73DFA5FB87EA16284E25D22360C2F
+PT=1191FC5E2EFA9F19004C7D00E1F4D8B1
+
+I=265
+KEY=039B0E1DE399831EE9DB8492DA7678E82497B97E83A22BFF
+IV=0931D0D100EEB87D612CDD343FC72116
+CT=1191FC5E2EFA9F19004C7D00E1F4D8B1
+PT=717B1B902086B97296B7E97BC01C259E
+
+I=266
+KEY=CB02B3C8CA4A0C9498A09F02FAF0C19AB220500543BE0E61
+IV=65D0C1DFC85C7FB9C899BDD529D38F8A
+CT=717B1B902086B97296B7E97BC01C259E
+PT=569097DA8C43871CC5A55AC150ABCD31
+
+I=267
+KEY=5FFAEE959D35C247CE3008D876B3468677850AC41315C350
+IV=7A4A448600ACA08994F85D5D577FCED3
+CT=569097DA8C43871CC5A55AC150ABCD31
+PT=4046F3DF53DFC1B56400501F08200FE0
+
+I=268
+KEY=0CA33FAAA4B25FEB8E76FB07256C873313855ADB1B35CCB0
+IV=C83E2121AA25A5295359D13F39879DAC
+CT=4046F3DF53DFC1B56400501F08200FE0
+PT=87C5362AAF3F31B05C92189E38FD9C66
+
+I=269
+KEY=5B782B675EE9A8A509B3CD2D8A53B6834F17424523C850D6
+IV=567E0CD5EAFC699457DB14CDFA5BF74E
+CT=87C5362AAF3F31B05C92189E38FD9C66
+PT=03A5CD79734810F4D9559FDC97A4B1A1
+
+I=270
+KEY=B069B5DCAADA727F0A160054F91BA6779642DD99B46CE177
+IV=5397ED8A6DF7641EEB119EBBF433DADA
+CT=03A5CD79734810F4D9559FDC97A4B1A1
+PT=1B1ECDDFD726C66594DF7B050F6758FF
+
+I=271
+KEY=52477DE5EFBAE2621108CD8B2E3D6012029DA69CBB0BB988
+IV=52151355DA4369C8E22EC8394560901D
+CT=1B1ECDDFD726C66594DF7B050F6758FF
+PT=26E9A7A560DD36D9767A51DA06301BBD
+
+I=272
+KEY=6E59FF11BED37F8837E16A2E4EE056CB74E7F746BD3BA235
+IV=FB1A5F8FA1C3D1F43C1E82F451699DEA
+CT=26E9A7A560DD36D9767A51DA06301BBD
+PT=C2FAB5CDDB329F2EA1E1459251A3CB1B
+
+I=273
+KEY=504DE2EC58CE17BBF51BDFE395D2C9E5D506B2D4EC98692E
+IV=6BCD90C4D648AB783E141DFDE61D6833
+CT=C2FAB5CDDB329F2EA1E1459251A3CB1B
+PT=4293D0A26E81DBE9FED6113B1954D59F
+
+I=274
+KEY=CC6C6C4150E763AAB7880F41FB53120C2BD0A3EFF5CCBCB1
+IV=0F61DAA62B7E95A79C218EAD08297411
+CT=4293D0A26E81DBE9FED6113B1954D59F
+PT=5DC81F054088DB9B3D1F8AD4BACC2039
+
+I=275
+KEY=BD3B4967A596578FEA401044BBDBC99716CF293B4F009C88
+IV=0C6435697122955071572526F5713425
+CT=5DC81F054088DB9B3D1F8AD4BACC2039
+PT=B6FB950586C671E968FFC709B79E8AF8
+
+I=276
+KEY=9A08B753E07CD6535CBB85413D1DB87E7E30EE32F89E1670
+IV=377A670B7487B3EB2733FE3445EA81DC
+CT=B6FB950586C671E968FFC709B79E8AF8
+PT=ED69B1E52F5F095EFF0AC73A76039B65
+
+I=277
+KEY=E5FAA83242346B4EB1D234A41242B120813A29088E9D8D15
+IV=DBEEED8784AD80B57FF21F61A248BD1D
+CT=ED69B1E52F5F095EFF0AC73A76039B65
+PT=FBC0C9A6FBC2CCD02BF5A009B43FE903
+
+I=278
+KEY=44770F6B1653E2754A12FD02E9807DF0AACF89013AA26416
+IV=7D9B061A6209E0FAA18DA7595467893B
+CT=FBC0C9A6FBC2CCD02BF5A009B43FE903
+PT=ADBE2B6C2C979C90E019991C5E81F69E
+
+I=279
+KEY=89A3B49BBE885D34E7ACD66EC517E1604AD6101D64239288
+IV=5495C29E4DDA4E26CDD4BBF0A8DBBF41
+CT=ADBE2B6C2C979C90E019991C5E81F69E
+PT=E382D6611C0B2591BE9B7B6BC66D479D
+
+I=280
+KEY=457D838277C2797B042E000FD91CC4F1F44D6B76A24ED515
+IV=0303BB8A65CCE419CCDE3719C94A244F
+CT=E382D6611C0B2591BE9B7B6BC66D479D
+PT=7A39D5BFC7ADB6B7539A1AA45A31A7E5
+
+I=281
+KEY=814AD70FBAF9D8AA7E17D5B01EB17246A7D771D2F87F72F0
+IV=550BD125E57ADE94C437548DCD3BA1D1
+CT=7A39D5BFC7ADB6B7539A1AA45A31A7E5
+PT=3CB8FF426FF48FA93EFAEDC559833C86
+
+I=282
+KEY=89599F584B46337342AF2AF27145FDEF992D9C17A1FC4E76
+IV=45800DE7659A8FD008134857F1BFEBD9
+CT=3CB8FF426FF48FA93EFAEDC559833C86
+PT=2F5C7660310DE65B1C5254E2176A15CA
+
+I=283
+KEY=8EF84BDE14C7412B6DF35C9240481BB4857FC8F5B6965BBC
+IV=5142FFEADEC300C107A1D4865F817258
+CT=2F5C7660310DE65B1C5254E2176A15CA
+PT=7A3056742CF8CFDE9CBEAE32607E8DE3
+
+I=284
+KEY=F076085EE3EA165617C30AE66CB0D46A19C166C7D6E8D65F
+IV=02FBB83EDCB092957E8E4380F72D577D
+CT=7A3056742CF8CFDE9CBEAE32607E8DE3
+PT=B2B7B7551B2A1D59601003C6EDD70A78
+
+I=285
+KEY=7D74D286D9CEC1C3A574BDB3779AC93379D165013B3FDC27
+IV=890E42EAA4C59B078D02DAD83A24D795
+CT=B2B7B7551B2A1D59601003C6EDD70A78
+PT=8B617CCD9B1289F485167DC13126795C
+
+I=286
+KEY=8BA3AA3C04001B9D2E15C17EEC8840C7FCC718C00A19A57B
+IV=F96182D81751ECCAF6D778BADDCEDA5E
+CT=8B617CCD9B1289F485167DC13126795C
+PT=D4800EE4A5E29A18C655AD5CE23063F9
+
+I=287
+KEY=E51B3BF1DF7B0D54FA95CF9A496ADADF3A92B59CE829C682
+IV=46297563D303DF226EB891CDDB7B16C9
+CT=D4800EE4A5E29A18C655AD5CE23063F9
+PT=4A6008072DCEB7602BF120F0984FF1D6
+
+I=288
+KEY=82091A039C558D36B0F5C79D64A46DBF1163956C70663754
+IV=28E82D15BAC860EA671221F2432E8062
+CT=4A6008072DCEB7602BF120F0984FF1D6
+PT=B05CD61BC646851726441B147FBB1AD3
+
+I=289
+KEY=C503B4B113DE349700A91186A2E2E8A837278E780FDD2D87
+IV=342F9FDEEEBE130A470AAEB28F8BB9A1
+CT=B05CD61BC646851726441B147FBB1AD3
+PT=33E1834199EE6CD5C6F950D4823B2337
+
+I=290
+KEY=4B06065B748AFB69334892C73B0C847DF1DEDEAC8DE60EB0
+IV=02928C43C0FF24968E05B2EA6754CFFE
+CT=33E1834199EE6CD5C6F950D4823B2337
+PT=BA0BD1FFA54258361D3A8BD9F3C689E4
+
+I=291
+KEY=AD0B10216B5D496B894343389E4EDC4BECE455757E208754
+IV=50DC56062E88C9CAE60D167A1FD7B202
+CT=BA0BD1FFA54258361D3A8BD9F3C689E4
+PT=4911046D8F1D2BCF54F22B5A83AF5AE1
+
+I=292
+KEY=AF6CC229A2618121C05247551153F784B8167E2FFD8FDDB5
+IV=A7CC6A2B280A9DE80267D208C93CC84A
+CT=4911046D8F1D2BCF54F22B5A83AF5AE1
+PT=254CA1983D7B794911B455E857CE902B
+
+I=293
+KEY=66413E8C7D11836FE51EE6CD2C288ECDA9A22BC7AA414D9E
+IV=D01066ADC643A032C92DFCA5DF70024E
+CT=254CA1983D7B794911B455E857CE902B
+PT=B0A100E60D0404D123D10AE78E9CFFCB
+
+I=294
+KEY=D13AF271F9C3337455BFE62B212C8A1C8A73212024DDB255
+IV=20D00A218F07ECEDB77BCCFD84D2B01B
+CT=B0A100E60D0404D123D10AE78E9CFFCB
+PT=D4CD0CC7D2EBAB050108E94365D34FAA
+
+I=295
+KEY=8B3C7094C3AD8B018172EAECF3C721198B7BC863410EFDFF
+IV=EC5F46869A00FFC25A0682E53A6EB875
+CT=D4CD0CC7D2EBAB050108E94365D34FAA
+PT=DF913CC34675469401CCA41DB50BFBA4
+
+I=296
+KEY=7DCF9D4559C3EA3A5EE3D62FB5B2678D8AB76C7EF405065B
+IV=8718728B7105A417F6F3EDD19A6E613B
+CT=DF913CC34675469401CCA41DB50BFBA4
+PT=5B09F0AF91EA41851A232543E97A6ED4
+
+I=297
+KEY=C3E6C2A9975117B605EA2680245826089094493D1D7F688F
+IV=21D001128A401EBFBE295FECCE92FD8C
+CT=5B09F0AF91EA41851A232543E97A6ED4
+PT=8544DFD1E46D14FF1B0E9CF43A7E9EB6
+
+I=298
+KEY=54C6D7971066FDD380AEF951C03532F78B9AD5C92701F639
+IV=F861E1C66C3F21779720153E8737EA65
+CT=8544DFD1E46D14FF1B0E9CF43A7E9EB6
+PT=586696A67E355CCDC41AD16D87786773
+
+I=299
+KEY=B47A128050D1FC84D8C86FF7BE006E3A4F8004A4A079914A
+IV=55A87D49D3640887E0BCC51740B70157
+CT=586696A67E355CCDC41AD16D87786773
+PT=6C7FF8D2F033B33C729C556E0731ACFF
+
+I=300
+KEY=C66EA18D75351D93B4B797254E33DD063D1C51CAA7483DB5
+IV=7224A11A5D122A607214B30D25E4E117
+CT=6C7FF8D2F033B33C729C556E0731ACFF
+PT=BC031D9B497C64B15EE143CF4D2130B1
+
+I=301
+KEY=00432A82295B2C6708B48ABE074FB9B763FD1205EA690D04
+IV=61D8239BE618CC39C62D8B0F5C6E31F4
+CT=BC031D9B497C64B15EE143CF4D2130B1
+PT=325D14CCDE09311A8069C5522FD050FD
+
+I=302
+KEY=E03B01935511FA7E3AE99E72D94688ADE394D757C5B95DF9
+IV=339B83266B282A96E0782B117C4AD619
+CT=325D14CCDE09311A8069C5522FD050FD
+PT=FA25D0913004A26A3232F743ACC7677E
+
+I=303
+KEY=47F79639F27D47E9C0CC4EE3E9422AC7D1A62014697E3A87
+IV=C5F60E2EC86A0971A7CC97AAA76CBD97
+CT=FA25D0913004A26A3232F743ACC7677E
+PT=61AA67B567F1CE94326B4711F8115727
+
+I=304
+KEY=EE86C028A3B01E7EA16629568EB3E453E3CD6705916F6DA0
+IV=4037462A5B08A27FA971561151CD5997
+CT=61AA67B567F1CE94326B4711F8115727
+PT=35D0FD8AFF6CBDF34065CED4796D9D27
+
+I=305
+KEY=EE88DBE9CCC930CB94B6D4DC71DF59A0A3A8A9D1E802F087
+IV=20CB619D26A05953000E1BC16F792EB5
+CT=35D0FD8AFF6CBDF34065CED4796D9D27
+PT=DD69B839EAE7D0DF79F5D06140D54325
+
+I=306
+KEY=C77ADB703861D01649DF6CE59B38897FDA5D79B0A8D7B3A2
+IV=16CFCF6A4F3272EA29F20099F4A8E0DD
+CT=DD69B839EAE7D0DF79F5D06140D54325
+PT=CA93E79E612893AA0D979ABDF5CA788A
+
+I=307
+KEY=3F486F048B5D9716834C8B7BFA101AD5D7CAE30D5D1DCB28
+IV=58332C3A8F187A96F832B474B33C4700
+CT=CA93E79E612893AA0D979ABDF5CA788A
+PT=39974A1C62DF12F62EC9F75704B0EFA8
+
+I=308
+KEY=B9022C8EA2C6FEF4BADBC16798CF0823F903145A59AD2480
+IV=3C09D97EFC480CD6864A438A299B69E2
+CT=39974A1C62DF12F62EC9F75704B0EFA8
+PT=B840EFC34BCD941BF551E437D633BB3A
+
+I=309
+KEY=D22317E3BB60B9FA029B2EA4D3029C380C52F06D8F9E9FBA
+IV=C755A4CF1FAD90046B213B6D19A6470E
+CT=B840EFC34BCD941BF551E437D633BB3A
+PT=979F6217FD73CAB73A1DE1FACF68542C
+
+I=310
+KEY=E196EBBFCDA64F7095044CB32E71568F364F119740F6CB96
+IV=D342A7B4EF6CB49F33B5FC5C76C6F68A
+CT=979F6217FD73CAB73A1DE1FACF68542C
+PT=A290A25CFBCB1BEE137AFB860BB2CF29
+
+I=311
+KEY=B756B878A99088B83794EEEFD5BA4D612535EA114B4404BF
+IV=D92C9835E799541056C053C76436C7C8
+CT=A290A25CFBCB1BEE137AFB860BB2CF29
+PT=7E99249836CA5167C88BD3431C78C2E0
+
+I=312
+KEY=2515F524203B507E490DCA77E3701C06EDBE3952573CC65F
+IV=FD7219F6C131C4BD92434D5C89ABD8C6
+CT=7E99249836CA5167C88BD3431C78C2E0
+PT=5B7DAB9C2148A2B7ACCE4723D1D63B3F
+
+I=313
+KEY=28A33899811FE9B7127061EBC238BEB141707E7186EAFD60
+IV=F6B29A78141D8F8A0DB6CDBDA124B9C9
+CT=5B7DAB9C2148A2B7ACCE4723D1D63B3F
+PT=12BAE3836257C52B88ECEEAAE8DE3B80
+
+I=314
+KEY=85C6089FEF19163500CA8268A06F7B9AC99C90DB6E34C6E0
+IV=AE11E9BE14B4ECB1AD6530066E06FF82
+CT=12BAE3836257C52B88ECEEAAE8DE3B80
+PT=71C5D9F8747D428DE30736C4DD33E3E5
+
+I=315
+KEY=86665ED5DA56FE90710F5B90D41239172A9BA61FB3072505
+IV=2CBAA91201D1980B03A0564A354FE8A5
+CT=71C5D9F8747D428DE30736C4DD33E3E5
+PT=D824A3FB80554CCD519D730D25EED2AF
+
+I=316
+KEY=F6D0840D75423D5CA92BF86B544775DA7B06D51296E9F7AA
+IV=66AA086063C3768C70B6DAD8AF14C3CC
+CT=D824A3FB80554CCD519D730D25EED2AF
+PT=C974BCBE88ACA9D29312192BE52885BD
+
+I=317
+KEY=56F2FDAAB52A8691605F44D5DCEBDC08E814CC3973C17217
+IV=14D16CCEDE70F435A02279A7C068BBCD
+CT=C974BCBE88ACA9D29312192BE52885BD
+PT=23B74C4B5E661FA157F571F4C13AA3AE
+
+I=318
+KEY=676109782F02525643E8089E828DC3A9BFE1BDCDB2FBD1B9
+IV=46BB517768227D1D3193F4D29A28D4C7
+CT=23B74C4B5E661FA157F571F4C13AA3AE
+PT=BDF2A1A79D553C85F5867B2BD5259A82
+
+I=319
+KEY=D21B20B085B317EDFE1AA9391FD8FF2C4A67C6E667DE4B3B
+IV=054B26F10A7F2D69B57A29C8AAB145BB
+CT=BDF2A1A79D553C85F5867B2BD5259A82
+PT=1E02970BE31FEE63C9BCCC79FB41F670
+
+I=320
+KEY=3CF3F93D44647FB7E0183E32FCC7114F83DB0A9F9C9FBD4B
+IV=C44342FC579F9083EEE8D98DC1D7685A
+CT=1E02970BE31FEE63C9BCCC79FB41F670
+PT=70F71372F64174D7C8757F043812439F
+
+I=321
+KEY=2C83CB76D99E054E90EF2D400A8665984BAE759BA48DFED4
+IV=884B46D9FBE7D99C1070324B9DFA7AF9
+CT=70F71372F64174D7C8757F043812439F
+PT=46B20E91579B5CC0ADE9327478DF25FA
+
+I=322
+KEY=0ADEA18FAA36E94BD65D23D15D1D3958E64747EFDC52DB2E
+IV=F256BC3206E11E9C265D6AF973A8EC05
+CT=46B20E91579B5CC0ADE9327478DF25FA
+PT=51FE245369F67740615E159E28C2D56C
+
+I=323
+KEY=E0C00F8BFD4ADCD087A3078234EB4E1887195271F4900E42
+IV=836F6756B9EC572DEA1EAE04577C359B
+CT=51FE245369F67740615E159E28C2D56C
+PT=58A1B407358C1F9783A05C0A43D5B4FB
+
+I=324
+KEY=EEA0B17E70A6FC53DF02B3850167518F04B90E7BB745BAB9
+IV=0E584BF6D72F08310E60BEF58DEC2083
+CT=58A1B407358C1F9783A05C0A43D5B4FB
+PT=6212DD8752996CC4D747790D5F2BC7E7
+
+I=325
+KEY=B6E49EEA07D03112BD106E0253FE3D4BD3FE7776E86E7D5E
+IV=2BA760FB0CC14D1858442F947776CD41
+CT=6212DD8752996CC4D747790D5F2BC7E7
+PT=DB16C25BDE0B95F4EC7B34FA2096E6A6
+
+I=326
+KEY=F64DCEBA5E71D73E6606AC598DF5A8BF3F85438CC8F89BF8
+IV=674AA4866EE9988E40A9505059A1E62C
+CT=DB16C25BDE0B95F4EC7B34FA2096E6A6
+PT=BB98BBB3289F3B5A96C5D3DA92F8CD0F
+
+I=327
+KEY=23CBCCA3D63DABB8DD9E17EAA56A93E5A94090565A0056F7
+IV=E3D676539CBD9676D5860219884C7C86
+CT=BB98BBB3289F3B5A96C5D3DA92F8CD0F
+PT=324C1661B1E289EA3DAC27AF14E026C5
+
+I=328
+KEY=D6F7C4A098C4E809EFD2018B14881A0F94ECB7F94EE07032
+IV=E7FB3F340E160FB5F53C08034EF943B1
+CT=324C1661B1E289EA3DAC27AF14E026C5
+PT=6EDA104789445C38F66EC2562F95FBDB
+
+I=329
+KEY=4B795FAB98879223810811CC9DCC4637628275AF61758BE9
+IV=C5E830814D72E9449D8E9B0B00437A2A
+CT=6EDA104789445C38F66EC2562F95FBDB
+PT=C834C54858181891C7D654A7502C0B60
+
+I=330
+KEY=AA317465E376BAF2493CD484C5D45EA6A554210831598089
+IV=2388FCCDB47CB5DBE1482BCE7BF128D1
+CT=C834C54858181891C7D654A7502C0B60
+PT=9C5F5599557D176050BBAC4258B87F66
+
+I=331
+KEY=B601C39C0E5F02DED563811D90A949C6F5EF8D4A69E1FFEF
+IV=10C2528D377387311C30B7F9ED29B82C
+CT=9C5F5599557D176050BBAC4258B87F66
+PT=ED5F51A6AFA843D467E21F6C68992273
+
+I=332
+KEY=44A1FE3F8349D500383CD0BB3F010A12920D92260178DD9C
+IV=9E73D9FB1D2471E8F2A03DA38D16D7DE
+CT=ED5F51A6AFA843D467E21F6C68992273
+PT=D7A5F18382F892264008F75707254D95
+
+I=333
+KEY=568F031D75B9B48FEF992138BDF99834D2056571065D9009
+IV=DEC9B60FA5A91887122EFD22F6F0618F
+CT=D7A5F18382F892264008F75707254D95
+PT=D13A34D9F57884ECEE2FA1A412584BE4
+
+I=334
+KEY=72CFCCE9FE5EB48A3EA315E148811CD83C2AC4D51405DBED
+IV=75C70261D0C49D692440CFF48BE70005
+CT=D13A34D9F57884ECEE2FA1A412584BE4
+PT=064D550098F0813D145A2AA296064CCF
+
+I=335
+KEY=58448186BD1ED1FC38EE40E1D0719DE52870EE7782039722
+IV=754A1B79A75BD3B32A8B4D6F43406576
+CT=064D550098F0813D145A2AA296064CCF
+PT=D7CD7D2B23E42F7A9808D48C28982743
+
+I=336
+KEY=6FF7BCC770079D57EF233DCAF395B29FB0783AFBAA9BB061
+IV=25EE1F4D8F257C6437B33D41CD194CAB
+CT=D7CD7D2B23E42F7A9808D48C28982743
+PT=6F55D4C7A13F08A1D936C5F0177040CA
+
+I=337
+KEY=7ECBB104AA3505E58076E90D52AABA3E694EFF0BBDEBF0AB
+IV=E21F1527B69B89C8113C0DC3DA3298B2
+CT=6F55D4C7A13F08A1D936C5F0177040CA
+PT=7F061908571CDDBC1F8F82A31A3AF1F9
+
+I=338
+KEY=135D99B5F2482FFAFF70F00505B6678276C17DA8A7D10152
+IV=5DA54CDB26A0DC2D6D9628B1587D2A1F
+CT=7F061908571CDDBC1F8F82A31A3AF1F9
+PT=30AB085953DE3E8027DE0C8A185A7D02
+
+I=339
+KEY=3C76458A987B66F0CFDBF85C56685902511F7122BF8B7C50
+IV=E0614E072D2563DD2F2BDC3F6A33490A
+CT=30AB085953DE3E8027DE0C8A185A7D02
+PT=92C915E98AEBF6265C43A66AC5B40787
+
+I=340
+KEY=EBD41B4484EA67A05D12EDB5DC83AF240D5CD7487A3F7BD7
+IV=6EA27DF02FA0A9A9D7A25ECE1C910150
+CT=92C915E98AEBF6265C43A66AC5B40787
+PT=E9AC0996F97FFBA0F7C860A089CDF99F
+
+I=341
+KEY=85B6BBBC8E2243D3B4BEE42325FC5484FA94B7E8F3F28248
+IV=46D915F802932C936E62A0F80AC82473
+CT=E9AC0996F97FFBA0F7C860A089CDF99F
+PT=BA1D082EDB28E255CB37AFEDB497D43A
+
+I=342
+KEY=BDA8736E56DDB34F0EA3EC0DFED4B6D131A3180547655672
+IV=0A7B9BCBE89E4CDE381EC8D2D8FFF09C
+CT=BA1D082EDB28E255CB37AFEDB497D43A
+PT=63298FE15A14C4A4E582C57772A0581E
+
+I=343
+KEY=9B5DC0C3B097B7CE6D8A63ECA4C07275D421DD7235C50E6C
+IV=81F4666446CB470526F5B3ADE64A0481
+CT=63298FE15A14C4A4E582C57772A0581E
+PT=AE79390C6789DFCF7110BA93281E9895
+
+I=344
+KEY=E64DDC6A55048E35C3F35AE0C349ADBAA53167E11DDB96F9
+IV=DB4439803A1ACA807D101CA9E59339FB
+CT=AE79390C6789DFCF7110BA93281E9895
+PT=2C9DF2ED511595756E5CF6D33442D3A3
+
+I=345
+KEY=9C75AC9CBA0918CDEF6EA80D925C38CFCB6D91322999455A
+IV=B73DBACA0C10AD0A7A3870F6EF0D96F8
+CT=2C9DF2ED511595756E5CF6D33442D3A3
+PT=90FDAEAEDC379128B73515CB2AAC9B7A
+
+I=346
+KEY=A045744F6BB9205F7F9306A34E6BA9E77C5884F90335DE20
+IV=356BBCDD4EBDA8F93C30D8D3D1B03892
+CT=90FDAEAEDC379128B73515CB2AAC9B7A
+PT=E66EA385E1F20791090CA24ADB250AFC
+
+I=347
+KEY=48E94FAC40CFC94B99FDA526AF99AE76755426B3D810D4DC
+IV=ABAF17EBE3658829E8AC3BE32B76E914
+CT=E66EA385E1F20791090CA24ADB250AFC
+PT=A17C6802F4322D97C6966B523B54CF88
+
+I=348
+KEY=3FC9CD7847FF49D73881CD245BAB83E1B3C24DE1E3441B54
+IV=7D25F4EE8B874E2D772082D40730809C
+CT=A17C6802F4322D97C6966B523B54CF88
+PT=CBEC825D143BF30C58B608B58ABFB618
+
+I=349
+KEY=D4464B5CD3CFAD06F36D4F794F9070EDEB74455469FBAD4C
+IV=93D0E88641960F8EEB8F86249430E4D1
+CT=CBEC825D143BF30C58B608B58ABFB618
+PT=D7A8E224DAA4DB7629790D3D4D5A8560
+
+I=350
+KEY=73DD2DA38114D0BD24C5AD5D9534AB9BC20D486924A1282C
+IV=3E6B8F8084BAA391A79B66FF52DB7DBB
+CT=D7A8E224DAA4DB7629790D3D4D5A8560
+PT=EB7EAD5CF27BA091DEF8D7839EFD7C90
+
+I=351
+KEY=CDA609EB23BB90EBCFBB0001674F0B0A1CF59FEABA5C54BC
+IV=8EEE61573B01F1E4BE7B2448A2AF4056
+CT=EB7EAD5CF27BA091DEF8D7839EFD7C90
+PT=2EFA41B666ECBBB1D699C1FB8CA9E175
+
+I=352
+KEY=768FCC098B8F48FFE14141B701A3B0BBCA6C5E1136F5B5C9
+IV=60BC671273707E17BB29C5E2A834D814
+CT=2EFA41B666ECBBB1D699C1FB8CA9E175
+PT=44D7245914CF3BF73831D4225BD32FDD
+
+I=353
+KEY=91F2FFA6BB520FD1A59665EE156C8B4CF25D8A336D269A14
+IV=21187FBCFC5E01BEE77D33AF30DD472E
+CT=44D7245914CF3BF73831D4225BD32FDD
+PT=E9FA049C77C326A4F03D2C9E740DE4A1
+
+I=354
+KEY=2FC9C39B5DBC560E4C6C617262AFADE80260A6AD192B7EB5
+IV=72912E59A0095846BE3B3C3DE6EE59DF
+CT=E9FA049C77C326A4F03D2C9E740DE4A1
+PT=9A62281465C72FDAA73E00E343A99BC3
+
+I=355
+KEY=F401ED3768BC72D4D60E496607688232A55EA64E5A82E576
+IV=88022668FE843060DBC82EAC350024DA
+CT=9A62281465C72FDAA73E00E343A99BC3
+PT=FAD9ADA4B98A4141A2857F93F6F71DEB
+
+I=356
+KEY=1AD741BDF8A18D8E2CD7E4C2BEE2C37307DBD9DDAC75F89D
+IV=F98FECC470C84631EED6AC8A901DFF5A
+CT=FAD9ADA4B98A4141A2857F93F6F71DEB
+PT=630453171FEE434834490229830E1C1A
+
+I=357
+KEY=24F7B99681335EAD4FD3B7D5A10C803B3392DBF42F7BE487
+IV=5D69B4D81847DABD3E20F82B7992D323
+CT=630453171FEE434834490229830E1C1A
+PT=DE613189001598BA6AE67F259F9FD349
+
+I=358
+KEY=60E401E96083FF2291B2865CA11918815974A4D1B0E437CE
+IV=AADE84AD4127FCDA4413B87FE1B0A18F
+CT=DE613189001598BA6AE67F259F9FD349
+PT=CA18925634072DEC80F2F724A0F24235
+
+I=359
+KEY=66831E7F4FC51DB95BAA140A951E356DD98653F5101675FB
+IV=1C1E2F698C5DD62006671F962F46E29B
+CT=CA18925634072DEC80F2F724A0F24235
+PT=B289F06551C56B77F5CDF7B321E0E8E3
+
+I=360
+KEY=48FB1A5B41F634D5E923E46FC4DB5E1A2C4BA44631F69D18
+IV=6A872620ED13A14B2E7804240E33296C
+CT=B289F06551C56B77F5CDF7B321E0E8E3
+PT=13B1F93DD388A192D6FB836C90E0E022
+
+I=361
+KEY=F13FA6E33170F596FA921D521753FF88FAB0272AA1167D3A
+IV=40BF714207DA180BB9C4BCB87086C143
+CT=13B1F93DD388A192D6FB836C90E0E022
+PT=298B7B19A27EA1BE9574588A5885F64B
+
+I=362
+KEY=CE171639A4DDA77DD319664BB52D5E366FC47FA0F9938B71
+IV=8FB32729166E154F3F28B0DA95AD52EB
+CT=298B7B19A27EA1BE9574588A5885F64B
+PT=11FA000C73485654A8918360DF3C1F5E
+
+I=363
+KEY=9322B0E9AE4D6B20C2E36647C6650862C755FCC026AF942F
+IV=809DE75B169C56BE5D35A6D00A90CC5D
+CT=11FA000C73485654A8918360DF3C1F5E
+PT=05533E642958E2F6F29BB1848BE225CB
+
+I=364
+KEY=21B86D89874D627FC7B05823EF3DEA9435CE4D44AD4DB1E4
+IV=81CF24C876471695B29ADD602900095F
+CT=05533E642958E2F6F29BB1848BE225CB
+PT=613DB485B9565B4889887282A3C8CFB5
+
+I=365
+KEY=6E5AD95BDDA04D12A68DECA6566BB1DCBC463FC60E857E51
+IV=7E3AC16D28733BD84FE2B4D25AED2F6D
+CT=613DB485B9565B4889887282A3C8CFB5
+PT=0CDDDA3B3375430B601BA1CCBD567284
+
+I=366
+KEY=807937B80E55E814AA50369D651EF2D7DC5D9E0AB3D30CD5
+IV=C49324EE3A928684EE23EEE3D3F5A506
+CT=0CDDDA3B3375430B601BA1CCBD567284
+PT=C47A6E22A123AB6397F9C2AFFA6D45AB
+
+I=367
+KEY=20B3595EFE3D3DA76E2A58BFC43D59B44BA45CA549BE497E
+IV=B188E4D3A2AC3F42A0CA6EE6F068D5B3
+CT=C47A6E22A123AB6397F9C2AFFA6D45AB
+PT=71592AFCA1FEEE8AB6D6CEF22C14A21D
+
+I=368
+KEY=A97EAD081EDF66D11F73724365C3B73EFD72925765AAEB63
+IV=0DFF90FA3722469289CDF456E0E25B76
+CT=71592AFCA1FEEE8AB6D6CEF22C14A21D
+PT=F4E0C4BCF8B386CF1BD457BD1FB65646
+
+I=369
+KEY=DA90448D67D59E3CEB93B6FF9D7031F1E6A6C5EA7A1CBD25
+IV=154DB6488872217073EEE985790AF8ED
+CT=F4E0C4BCF8B386CF1BD457BD1FB65646
+PT=9ED1119909322C280FE92B7840792605
+
+I=370
+KEY=CF62D3016C8507F17542A76694421DD9E94FEE923A659B20
+IV=ED45F0A7D33FC08515F2978C0B5099CD
+CT=9ED1119909322C280FE92B7840792605
+PT=F812615F1BE701E74FCEEFC288303C7C
+
+I=371
+KEY=C2681849C663E45A8D50C6398FA51C3EA6810150B255A75C
+IV=19E09027253115100D0ACB48AAE6E3AB
+CT=F812615F1BE701E74FCEEFC288303C7C
+PT=25897C51C5FEDBFDC630BF8E9F3B2875
+
+I=372
+KEY=F47C452077541CEEA8D9BA684A5BC7C360B1BEDE2D6E8F29
+IV=2C2EE28C518163DF36145D69B137F8B4
+CT=25897C51C5FEDBFDC630BF8E9F3B2875
+PT=9929E5E9F0CA00D0E02022E2FCFAFC3F
+
+I=373
+KEY=F7BF8679C8D86E2C31F05F81BA91C71380919C3CD1947316
+IV=FCF0C5D85049463103C3C359BF8C72C2
+CT=9929E5E9F0CA00D0E02022E2FCFAFC3F
+PT=3B603A3FDAA669E7C965708C9789E329
+
+I=374
+KEY=9312EDA0B14017910A9065BE6037AEF449F4ECB0461D903F
+IV=364CDACF5762B18864AD6BD9799879BD
+CT=3B603A3FDAA669E7C965708C9789E329
+PT=AC33F7B1A778C36617668C98E20B318A
+
+I=375
+KEY=D5BC989407D78D82A6A3920FC74F6D925E926028A416A1B5
+IV=5FB00506C71711D046AE7534B6979A13
+CT=AC33F7B1A778C36617668C98E20B318A
+PT=B408AF5509EF45E0AEDF12570FAE3651
+
+I=376
+KEY=6BBB14591C12578112AB3D5ACEA02872F04D727FABB897E4
+IV=D41F58F192CF60D6BE078CCD1BC5DA03
+CT=B408AF5509EF45E0AEDF12570FAE3651
+PT=39EB055E027AC0DEA5992B7BA3753AB5
+
+I=377
+KEY=3F71566EA7D07EBF2B403804CCDAE8AC55D4590408CDAD51
+IV=7E495DEC2224696554CA4237BBC2293E
+CT=39EB055E027AC0DEA5992B7BA3753AB5
+PT=832B01D2AD4F0EE077244CF9B6ABE31C
+
+I=378
+KEY=0BDC563CE47527D1A86B39D66195E64C22F015FDBE664E4D
+IV=4FE13E98163C3F7734AD005243A5596E
+CT=832B01D2AD4F0EE077244CF9B6ABE31C
+PT=926EB7E17FA4262D1D390D83CDAC6FB2
+
+I=379
+KEY=07D4D606747858B63A058E371E31C0613FC9187E73CA21FF
+IV=12D459160DCFFEFE0C08803A900D7F67
+CT=926EB7E17FA4262D1D390D83CDAC6FB2
+PT=DBFBC3313F86C26BA54B9F69BA93C665
+
+I=380
+KEY=84BE014D4BFA8ACCE1FE4D0621B7020A9A828717C959E79A
+IV=179322B7D19F3A38836AD74B3F82D27A
+CT=DBFBC3313F86C26BA54B9F69BA93C665
+PT=39B00A1A655B298F56271B2BDBA6B16B
+
+I=381
+KEY=A921F537F5F324CAD84E471C44EC2B85CCA59C3C12FF56F1
+IV=D4B03D3AB6FF79D22D9FF47ABE09AE06
+CT=39B00A1A655B298F56271B2BDBA6B16B
+PT=7C5DABBF7C7951808DCD35DB2617B763
+
+I=382
+KEY=3BB6AACEEEC21A9FA413ECA338957A054168A9E734E8E192
+IV=5C92A3C4C3C8567792975FF91B313E55
+CT=7C5DABBF7C7951808DCD35DB2617B763
+PT=BD88FB3B815415503D4F9264AFEA7887
+
+I=383
+KEY=008F402C3524BCA8199B1798B9C16F557C273B839B029915
+IV=08360D06E31B3AA43B39EAE2DBE6A637
+CT=BD88FB3B815415503D4F9264AFEA7887
+PT=B2813AFBC477618F4C6A436C97AA26F2
+
+I=384
+KEY=8AB9F9FC4EE8B2D4AB1A2D637DB60EDA304D78EF0CA8BFE7
+IV=DCF7EF19F68916268A36B9D07BCC0E7C
+CT=B2813AFBC477618F4C6A436C97AA26F2
+PT=1E96D52E46B1D73EB00778B203946F28
+
+I=385
+KEY=CA9D4CE917399619B58CF84D3B07D9E4804A005D0F3CD0CF
+IV=63A112DB63DDECB54024B51559D124CD
+CT=1E96D52E46B1D73EB00778B203946F28
+PT=C03D770FE4B1733C5E59DD68F0060D5A
+
+I=386
+KEY=1D8268F833FC772575B18F42DFB6AAD8DE13DD35FF3ADD95
+IV=8B7AC769F85BA650D71F241124C5E13C
+CT=C03D770FE4B1733C5E59DD68F0060D5A
+PT=6495A8A3667DEDE2CAB58BA3B2F7034E
+
+I=387
+KEY=CCCEE884786AF28A112427E1B9CB473A14A656964DCDDEDB
+IV=280C5BD88E3B88ACD14C807C4B9685AF
+CT=6495A8A3667DEDE2CAB58BA3B2F7034E
+PT=4CC3C2AC85EBD619E708988C9FEC60C6
+
+I=388
+KEY=8B85284B2B06874D5DE7E54D3C209123F3AECE1AD221BE1D
+IV=62E112946391FEFB474BC0CF536C75C7
+CT=4CC3C2AC85EBD619E708988C9FEC60C6
+PT=1522371FD5D53919F52CD97258CEBDA7
+
+I=389
+KEY=B2EBBE81CF234A7E48C5D252E9F5A83A068217688AEF03BA
+IV=8A936BAE971C0C9F396E96CAE425CD33
+CT=1522371FD5D53919F52CD97258CEBDA7
+PT=4AA882DCB39AA79E8439E9ECE9F4F3BD
+
+I=390
+KEY=043B9FDDEC299802026D508E5A6F0FA482BBFE84631BF007
+IV=6FA7FCDBA3B1BCA5B6D0215C230AD27C
+CT=4AA882DCB39AA79E8439E9ECE9F4F3BD
+PT=28C1E45D8D01AD148FA7D7C4F41ACE04
+
+I=391
+KEY=1074F9BD3FFD4EAF2AACB4D3D76EA2B00D1C294097013E03
+IV=1210BAF1D69B23FE144F6660D3D4D6AD
+CT=28C1E45D8D01AD148FA7D7C4F41ACE04
+PT=3ABE04FC59C3BDF9D7721902DEFCB439
+
+I=392
+KEY=D97F3440E3684D291012B02F8EAD1F49DA6E304249FD8A3A
+IV=C271800852E147D5C90BCDFDDC950386
+CT=3ABE04FC59C3BDF9D7721902DEFCB439
+PT=3A563A6A047E16123B289B047BB54C4E
+
+I=393
+KEY=49A10E68A38B02F42A448A458AD3095BE146AB463248C674
+IV=9DB6856C7E01CF3690DE3A2840E34FDD
+CT=3A563A6A047E16123B289B047BB54C4E
+PT=F8CB54B8D16274E9A20C0F026866E52F
+
+I=394
+KEY=9DD96DCFD4A1B11FD28FDEFD5BB17DB2434AA4445A2E235B
+IV=233C069312D97A03D47863A7772AB3EB
+CT=F8CB54B8D16274E9A20C0F026866E52F
+PT=0302D25C39BF21F67F1AF2E1951D40F9
+
+I=395
+KEY=746E55928D7E549DD18D0CA1620E5C443C5056A5CF3363A2
+IV=B6086C5FEEE9A078E9B7385D59DFE582
+CT=0302D25C39BF21F67F1AF2E1951D40F9
+PT=721192A3A5140DD63D93E0D6ACC4A4B8
+
+I=396
+KEY=7E6FC505EAAB07E4A39C9E02C71A519201C3B67363F7C71A
+IV=9828A03F0ADCE33E0A01909767D55379
+CT=721192A3A5140DD63D93E0D6ACC4A4B8
+PT=1C0F7440EF41FF18E263392741AD9D8B
+
+I=397
+KEY=D13AD442CAE026C3BF93EA42285BAE8AE3A08F54225A5A91
+IV=4FC707A846B4469AAF551147204B2127
+CT=1C0F7440EF41FF18E263392741AD9D8B
+PT=442F978615AC3983AA5ABEA81AD1ACA6
+
+I=398
+KEY=043A4EFFCD44EEB1FBBC7DC43DF7970949FA31FC388BF637
+IV=05D58B4A88A961AFD5009ABD07A4C872
+CT=442F978615AC3983AA5ABEA81AD1ACA6
+PT=E75C29413A33AA1210F36AADEC02FCEE
+
+I=399
+KEY=81492E2C6296C9341CE0548507C43D1B59095B51D4890AD9
+IV=D89794EAA1791507857360D3AFD22785
+CT=E75C29413A33AA1210F36AADEC02FCEE
+PT=6342BFDDD2F6610350458B6695463484
+
+==========
+
+KEYSIZE=256
+
+I=0
+KEY=0000000000000000000000000000000000000000000000000000000000000000
+IV=00000000000000000000000000000000
+CT=00000000000000000000000000000000
+PT=4804E1818FE6297519A3E88C57310413
+
+I=1
+KEY=098E3797788EA3BCD5477BF1660373944804E1818FE6297519A3E88C57310413
+IV=098E3797788EA3BCD5477BF166037394
+CT=4804E1818FE6297519A3E88C57310413
+PT=D36C27EBB8FA0BC9FA368DF850FD45FB
+
+I=2
+KEY=D949E143F98BDE24BD40A256F9E369339B68C66A371C22BCE395657407CC41E8
+IV=D0C7D6D481057D986807D9A79FE01AA7
+CT=D36C27EBB8FA0BC9FA368DF850FD45FB
+PT=EBCB4DC84155682856D94B442BC597EE
+
+I=3
+KEY=296352DA0158E197EBC80771EC1ECC7D70A38BA276494A94B54C2E302C09D606
+IV=F02AB399F8D33FB35688A52715FDA54E
+CT=EBCB4DC84155682856D94B442BC597EE
+PT=23AA6A6B4BE8C04E19707CA330804C4E
+
+I=4
+KEY=5D3E9E2EA4DEDDB65A58DADB5B9679BC5309E1C93DA18ADAAC3C52931C899A48
+IV=745DCCF4A5863C21B190DDAAB788B5C1
+CT=23AA6A6B4BE8C04E19707CA330804C4E
+PT=9B1AA0F33416484BA68740E821F95CD3
+
+I=5
+KEY=E35024184CCA14687DB19E13093D2A31C813413A09B7C2910ABB127B3D70C69B
+IV=BE6EBA36E814C9DE27E944C852AB538D
+CT=9B1AA0F33416484BA68740E821F95CD3
+PT=8A8C6ADF453CB7A2FC4F3690FF7C6F23
+
+I=6
+KEY=FDC6EB83FF93BA06DE2D09CB33F05406429F2BE54C8B7533F6F424EBC20CA9B8
+IV=1E96CF9BB359AE6EA39C97D83ACD7E37
+CT=8A8C6ADF453CB7A2FC4F3690FF7C6F23
+PT=B104182A3D85B857FB342BD06063E989
+
+I=7
+KEY=7177668BAC9407FB2835524D58F1311EF39B33CF710ECD640DC00F3BA26F4031
+IV=8CB18D085307BDFDF6185B866B016518
+CT=B104182A3D85B857FB342BD06063E989
+PT=68AD7EB507FAEE8FF54E5B7EB4314208
+
+I=8
+KEY=790AE8470B39A60E9F32F4025B2251849B364D7A76F423EBF88E5445165E0239
+IV=087D8ECCA7ADA1F5B707A64F03D3609A
+CT=68AD7EB507FAEE8FF54E5B7EB4314208
+PT=99736D55B2730FDBC4FCD9128A3E6F06
+
+I=9
+KEY=4EAF05AC15913059B6B0E43EFA7ADC1C0245202FC4872C303C728D579C606D3F
+IV=37A5EDEB1EA896572982103CA1588D98
+CT=99736D55B2730FDBC4FCD9128A3E6F06
+PT=DF326CEE98EE253C855D171D93AA9455
+
+I=10
+KEY=55EE1CCDBA5A04040F4212DFBF6ABC89DD774CC15C69090CB92F9A4A0FCAF96A
+IV=1B411961AFCB345DB9F2F6E145106095
+CT=DF326CEE98EE253C855D171D93AA9455
+PT=B4E41BD5257CD7AF0A6F020BEE5F4067
+
+I=11
+KEY=6190A91725B7D4E8DD42F3F3B4E42E14699357147915DEA3B3409841E195B90D
+IV=347EB5DA9FEDD0ECD200E12C0B8E929D
+CT=B4E41BD5257CD7AF0A6F020BEE5F4067
+PT=3608F41CA4C677E74F48B113D9B336B0
+
+I=12
+KEY=0A93E973CCBAC75C9C0AA05502A43E945F9BA308DDD3A944FC08295238268FBD
+IV=6B034064E90D13B4414853A6B6401080
+CT=3608F41CA4C677E74F48B113D9B336B0
+PT=FB54DBB9C0C7176C4C9E1E4E6688B570
+
+I=13
+KEY=584CCAEDD52F491A935D892AD132F75AA4CF78B11D14BE28B096371C5EAE3ACD
+IV=52DF239E19958E460F57297FD396C9CE
+CT=FB54DBB9C0C7176C4C9E1E4E6688B570
+PT=F40A6A6AE95E9D163D88AAE9A2D359BC
+
+I=14
+KEY=0DD784E96CAB96D702DD3972E95317FD50C512DBF44A233E8D1E9DF5FC7D6371
+IV=559B4E04B984DFCD9180B0583861E0A7
+CT=F40A6A6AE95E9D163D88AAE9A2D359BC
+PT=0FE04B8BB249E49E24FEB6FFE106121C
+
+I=15
+KEY=2BC3A4EBD80215F0130EC1F76821BC515F2559504603C7A0A9E02B0A1D7B716D
+IV=26142002B4A9832711D3F8858172ABAC
+CT=0FE04B8BB249E49E24FEB6FFE106121C
+PT=EBA4EF8D541919A0D0947359344D61C9
+
+I=16
+KEY=0B5856BE9A78457868F7CF9C9C58EF7AB481B6DD121ADE0079745853293610A4
+IV=209BF255427A50887BF90E6BF479532B
+CT=EBA4EF8D541919A0D0947359344D61C9
+PT=06484C36A29BD3CA7CBAB7FBEA47313B
+
+I=17
+KEY=C004F13C83AA1FD5C2A592D27B47C437B2C9FAEBB0810DCA05CEEFA8C371219F
+IV=CB5CA78219D25AADAA525D4EE71F2B4D
+CT=06484C36A29BD3CA7CBAB7FBEA47313B
+PT=376157B7DB3B027980C5EF0E88B3F9EF
+
+I=18
+KEY=AD89203CAD17908C4F44F3FD2D61505385A8AD5C6BBA0FB3850B00A64BC2D870
+IV=6D8DD1002EBD8F598DE1612F56269464
+CT=376157B7DB3B027980C5EF0E88B3F9EF
+PT=756783C2F0EE73BBD81B908F660AA6F7
+
+I=19
+KEY=FBE990A6247EABC0CD5090DF0C566E01F0CF2E9E9B547C085D1090292DC87E87
+IV=5660B09A89693B4C8214632221373E52
+CT=756783C2F0EE73BBD81B908F660AA6F7
+PT=6CC64B773ECDFA9749DB33197F7EA0AB
+
+I=20
+KEY=FEC46AD20DA3E667B26D79B11A82A40F9C0965E9A599869F14CBA33052B6DE2C
+IV=052DFA7429DD4DA77F3DE96E16D4CA0E
+CT=6CC64B773ECDFA9749DB33197F7EA0AB
+PT=9230E4DCA927E2F8E617A2EBC4F11477
+
+I=21
+KEY=F4396B035E4E1BD914877124D1CD4B370E3981350CBE6467F2DC01DB9647CA5B
+IV=0AFD01D153EDFDBEA6EA0895CB4FEF38
+CT=9230E4DCA927E2F8E617A2EBC4F11477
+PT=6ACD9F3939A86EE4236A3C060D2F5C3C
+
+I=22
+KEY=49C90E620094D6A85E75BD886FAFE79264F41E0C35160A83D1B63DDD9B689667
+IV=BDF065615EDACD714AF2CCACBE62ACA5
+CT=6ACD9F3939A86EE4236A3C060D2F5C3C
+PT=E5F4F050827F69B60B417063AC1060E4
+
+I=23
+KEY=1AED4D36938AB2D5D884EF2F106D2CEF8100EE5CB7696335DAF74DBE3778F683
+IV=53244354931E647D86F152A77FC2CB7D
+CT=E5F4F050827F69B60B417063AC1060E4
+PT=5CE4B0B3C32700B6B887E05A88EE0239
+
+I=24
+KEY=EF14B937F6E0F19AC8ADBD208DD60EE5DDE45EEF744E63836270ADE4BF96F4BA
+IV=F5F9F401656A434F1029520F9DBB220A
+CT=5CE4B0B3C32700B6B887E05A88EE0239
+PT=4794284E2BB56A47332E84AD7A2006A2
+
+I=25
+KEY=182581A233332DDCD43C25AF9AA3AD7F9A7076A15FFB09C4515E2949C5B6F218
+IV=F7313895C5D3DC461C91988F1775A39A
+CT=4794284E2BB56A47332E84AD7A2006A2
+PT=C8AE2CAA7C257508C3AB75BE28D2602F
+
+I=26
+KEY=ABE7FE236E28332AE7A74A9EA03B97A952DE5A0B23DE7CCC92F55CF7ED649237
+IV=B3C27F815D1B1EF6339B6F313A983AD6
+CT=C8AE2CAA7C257508C3AB75BE28D2602F
+PT=A9FD4B9D4833B647FF60F8013C3B5B9D
+
+I=27
+KEY=08248BDC5F9186DCD65DA6344A10C57EFB2311966BEDCA8B6D95A4F6D15FC9AA
+IV=A3C375FF31B9B5F631FAECAAEA2B52D7
+CT=A9FD4B9D4833B647FF60F8013C3B5B9D
+PT=C871D7B4C0167DCFDD79AF1DEAC49D4F
+
+I=28
+KEY=BF29FB1B11AA7DB8742FF06458C384853352C622ABFBB744B0EC0BEB3B9B54E5
+IV=B70D70C74E3BFB64A272565012D341FB
+CT=C871D7B4C0167DCFDD79AF1DEAC49D4F
+PT=E2DE7BAC726C404FC7BA5099E39409CA
+
+I=29
+KEY=1810253DDF0CC5ECE2381FB4C2BEEDCCD18CBD8ED997F70B77565B72D80F5D2F
+IV=A739DE26CEA6B8549617EFD09A7D6949
+CT=E2DE7BAC726C404FC7BA5099E39409CA
+PT=D4A8257110EF7FFE2A1F026B28D7483A
+
+I=30
+KEY=F343D1EC9AEB200B65DB4AA369F6A47E052498FFC97888F55D495919F0D81515
+IV=EB53F4D145E7E5E787E35517AB4849B2
+CT=D4A8257110EF7FFE2A1F026B28D7483A
+PT=9EA25895CFEAEAD224095C4687726D06
+
+I=31
+KEY=86A93B0F219E1FFEBC0E4BA0334046AA9B86C06A069262277940055F77AA7813
+IV=75EAEAE3BB753FF5D9D501035AB6E2D4
+CT=9EA25895CFEAEAD224095C4687726D06
+PT=5C5DD66E7AD197DA86844D53C8ACEA0E
+
+I=32
+KEY=2278C61356CB0A951DAE3B6DC76868C9C7DB16047C43F5FDFFC4480CBF06921D
+IV=A4D1FD1C7755156BA1A070CDF4282E63
+CT=5C5DD66E7AD197DA86844D53C8ACEA0E
+PT=011959D35C8FE620E1C49D1804912F26
+
+I=33
+KEY=E1972A31ACF850A22CBC592AF6CAF6F0C6C24FD720CC13DD1E00D514BB97BD3B
+IV=C3EFEC22FA335A373112624731A29E39
+CT=011959D35C8FE620E1C49D1804912F26
+PT=895DDA7BB43DC3060B41DA70CAE4D2ED
+
+I=34
+KEY=BB4A76B5E8FD3820CC5D4A44F527E6704F9F95AC94F1D0DB15410F6471736FD6
+IV=5ADD5C8444056882E0E1136E03ED1080
+CT=895DDA7BB43DC3060B41DA70CAE4D2ED
+PT=94E8BBC942B4127A0A8EBEC59319CF57
+
+I=35
+KEY=4D98C60F0FA316B2DA3D11CFB3B9FE0CDB772E65D645C2A11FCFB1A1E26AA081
+IV=F6D2B0BAE75E2E9216605B8B469E187C
+CT=94E8BBC942B4127A0A8EBEC59319CF57
+PT=274FE85E229321D4A6B2E9D4F0D3830F
+
+I=36
+KEY=A9FC5AC4A7B3550BC34E4BA94C0D328BFC38C63BF4D6E375B97D587512B9238E
+IV=E4649CCBA81043B919735A66FFB4CC87
+CT=274FE85E229321D4A6B2E9D4F0D3830F
+PT=256AC08E72D79B0CB7457B26769AC226
+
+I=37
+KEY=1C44DEF03398188AC1B2EF6A6E91A33FD95206B5860178790E3823536423E1A8
+IV=B5B88434942B4D8102FCA4C3229C91B4
+CT=256AC08E72D79B0CB7457B26769AC226
+PT=366D17A14CA0FC192DBB731C1C305874
+
+I=38
+KEY=3D80B92C01F9721032366B20D97DC097EF3F1114CAA184602383504F7813B9DC
+IV=21C467DC32616A9AF384844AB7EC63A8
+CT=366D17A14CA0FC192DBB731C1C305874
+PT=000B4A6054663874ECAE310144BA9377
+
+I=39
+KEY=48DD38DC16A4CE76338C95A866C1C795EF345B749EC7BC14CF2D614E3CA92AAB
+IV=755D81F0175DBC6601BAFE88BFBC0702
+CT=000B4A6054663874ECAE310144BA9377
+PT=32B32D65566626D794FB296CA816B0A8
+
+I=40
+KEY=C62EFA02F23FE796799BF9151FBFD8D7DD877611C8A19AC35BD6482294BF9A03
+IV=8EF3C2DEE49B29E04A176CBD797E1F42
+CT=32B32D65566626D794FB296CA816B0A8
+PT=D743A090101B1BAF5B83E8C06517E193
+
+I=41
+KEY=91400A96EEADA906ABD4C3F6863CE4750AC4D681D8BA816C0055A0E2F1A87B90
+IV=576EF0941C924E90D24F3AE399833CA2
+CT=D743A090101B1BAF5B83E8C06517E193
+PT=2DE61760BEE8F811B3FEB44D2C566DB0
+
+I=42
+KEY=9983EAD4BF987E39644D7D0963F93DB62722C1E16652797DB3AB14AFDDFE1620
+IV=08C3E0425135D73FCF99BEFFE5C5D9C3
+CT=2DE61760BEE8F811B3FEB44D2C566DB0
+PT=E97598EFFED4128DCCCDD7A04D8405E1
+
+I=43
+KEY=B72929D2D02A00D36E7C3BD11CDB9FA4CE57590E98866BF07F66C30F907A13C1
+IV=2EAAC3066FB27EEA0A3146D87F22A212
+CT=E97598EFFED4128DCCCDD7A04D8405E1
+PT=5983276B92B95898302385F5156B6201
+
+I=44
+KEY=CC9928E45F7885515986E0D431F3288E97D47E650A3F33684F4546FA851171C0
+IV=7BB001368F52858237FADB052D28B72A
+CT=5983276B92B95898302385F5156B6201
+PT=ABDEFF06E04995FD2C5472D05056A0A3
+
+I=45
+KEY=59A2D8FCED30176B73FF5642BCE4A9163C0A8163EA76A6956311342AD547D163
+IV=953BF018B248923A2A79B6968D178198
+CT=ABDEFF06E04995FD2C5472D05056A0A3
+PT=E4210D117B05F3EADC8AF75D1A80B823
+
+I=46
+KEY=FFCCE373B679DE040165054D9EECA460D82B8C729173557FBF9BC377CFC76940
+IV=A66E3B8F5B49C96F729A530F22080D76
+CT=E4210D117B05F3EADC8AF75D1A80B823
+PT=4786111E1B0F2CA78E43CC0D154BC1EA
+
+I=47
+KEY=36E29D3C942DBC6A12B53088632260649FAD9D6C8A7C79D831D80F7ADA8CA8AA
+IV=C92E7E4F2254626E13D035C5FDCEC404
+CT=4786111E1B0F2CA78E43CC0D154BC1EA
+PT=122DC3B40007BA36BC7E7EE808911DAE
+
+I=48
+KEY=3692660415E53226D2758E60FD6E3F5F8D805ED88A7BC3EE8DA67192D21DB504
+IV=0070FB3881C88E4CC0C0BEE89E4C5F3B
+CT=122DC3B40007BA36BC7E7EE808911DAE
+PT=5E443EC882C1B938C2A4C412D3A92FDF
+
+I=49
+KEY=E3C167B38A29EDFBDC37A50F434C7056D3C4601008BA7AD64F02B58001B49ADB
+IV=D55301B79FCCDFDD0E422B6FBE224F09
+CT=5E443EC882C1B938C2A4C412D3A92FDF
+PT=14A8F43BA8829B134D6BD110E6D43F92
+
+I=50
+KEY=8AD38A575E425D347C5B5BFB08A5173CC76C942BA038E1C502696490E760A549
+IV=6912EDE4D46BB0CFA06CFEF44BE9676A
+CT=14A8F43BA8829B134D6BD110E6D43F92
+PT=025982911796C2FE34C89157BF2959BD
+
+I=51
+KEY=AE4ABA37DD2C3C5109B13C3DD9FCB67EC53516BAB7AE233B36A1F5C75849FCF4
+IV=24993060836E616575EA67C6D159A142
+CT=025982911796C2FE34C89157BF2959BD
+PT=BC658642A8EEBEC6DBE2A76BCD70799B
+
+I=52
+KEY=31AC934C58BF87AD1EE4357BBE315175795090F81F409DFDED4352AC9539856F
+IV=9FE6297B8593BBFC1755094667CDE70B
+CT=BC658642A8EEBEC6DBE2A76BCD70799B
+PT=132CE1CC36EFE58A4A53534B962D2D70
+
+I=53
+KEY=79F7C18CA600203D404363908749B22F6A7C713429AF7877A71001E70314A81F
+IV=485B52C0FEBFA7905EA756EB3978E35A
+CT=132CE1CC36EFE58A4A53534B962D2D70
+PT=8D2BA39F08ED00BEB51543C0FCCFA57C
+
+I=54
+KEY=162A4089A1E46EAB5C9592BF1F98BCC2E757D2AB214278C912054227FFDB0D63
+IV=6FDD810507E44E961CD6F12F98D10EED
+CT=8D2BA39F08ED00BEB51543C0FCCFA57C
+PT=2E8D05A8A3066094025FE07F3A53A94E
+
+I=55
+KEY=DB5F33F93F2B795EDA54095937B79E4CC9DAD7038244185D105AA258C588A42D
+IV=CD7573709ECF17F586C19BE6282F228E
+CT=2E8D05A8A3066094025FE07F3A53A94E
+PT=D39EC2261C53AD45F91627E1B1F62D22
+
+I=56
+KEY=CCA770427DF8CF5350864D4E86E6D8891A4415259E17B518E94C85B9747E890F
+IV=17F843BB42D3B60D8AD24417B15146C5
+CT=D39EC2261C53AD45F91627E1B1F62D22
+PT=F517DC01890C3D300520B6CE343B7F94
+
+I=57
+KEY=25F53E7CC6590220E9426296568DE496EF53C924171B8828EC6C33774045F69B
+IV=E9524E3EBBA1CD73B9C42FD8D06B3C1F
+CT=F517DC01890C3D300520B6CE343B7F94
+PT=ECBCCBB21AC2D07E3ECACD26D42E4444
+
+I=58
+KEY=6D4A92C82C6C3D44CED65D76BB33B23E03EF02960DD95856D2A6FE51946BB2DF
+IV=48BFACB4EA353F6427943FE0EDBE56A8
+CT=ECBCCBB21AC2D07E3ECACD26D42E4444
+PT=6FF7C241A5FF025FAA8C4DAF5E0950AE
+
+I=59
+KEY=A3D0AB0A0F8EDF232D111458D3B8B1C66C18C0D7A8265A09782AB3FECA62E271
+IV=CE9A39C223E2E267E3C7492E688B03F8
+CT=6FF7C241A5FF025FAA8C4DAF5E0950AE
+PT=3B7E4B74F021F9E995627DE42B03D7D8
+
+I=60
+KEY=A8E2D59CF188CDA75C80FA49889F7EE357668BA35807A3E0ED48CE1AE16135A9
+IV=0B327E96FE0612847191EE115B27CF25
+CT=3B7E4B74F021F9E995627DE42B03D7D8
+PT=6759C15ED1049A51953E814C2445F3C6
+
+I=61
+KEY=092010B28BD3C8E59D09CE85169190BB303F4AFD890339B178764F56C524C66F
+IV=A1C2C52E7A5B0542C18934CC9E0EEE58
+CT=6759C15ED1049A51953E814C2445F3C6
+PT=05F681CB7984491E2CE5B1025F860BEB
+
+I=62
+KEY=538E3068E1059FE89C27D5F19405274835C9CB36F08770AF5493FE549AA2CD84
+IV=5AAE20DA6AD6570D012E1B748294B7F3
+CT=05F681CB7984491E2CE5B1025F860BEB
+PT=E046F5B143CEEAC44EF520F2C3BFA96E
+
+I=63
+KEY=78B5D2551099875910844A17ABBACD64D58F3E87B3499A6B1A66DEA6591D64EA
+IV=2B3BE23DF19C18B18CA39FE63FBFEA2C
+CT=E046F5B143CEEAC44EF520F2C3BFA96E
+PT=0F508DD1BCC6C520A81AE7EC75361179
+
+I=64
+KEY=8D6E7E66F496C358A369EF7C49D117A3DADFB3560F8F5F4BB27C394A2C2B7593
+IV=F5DBAC33E40F4401B3EDA56BE26BDAC7
+CT=0F508DD1BCC6C520A81AE7EC75361179
+PT=BAE114FFF19FD11336D454BF0FF6954D
+
+I=65
+KEY=781164DD6F90037E9896672FD24F1AF6603EA7A9FE108E5884A86DF523DDE0DE
+IV=F57F1ABB9B06C0263BFF88539B9E0D55
+CT=BAE114FFF19FD11336D454BF0FF6954D
+PT=FE73CE62C227459729E8FDC9116EC6BB
+
+I=66
+KEY=9268D6C0E8DE5AFBCCE137EADE6293E49E4D69CB3C37CBCFAD40903C32B32665
+IV=EA79B21D874E5985547750C50C2D8912
+CT=FE73CE62C227459729E8FDC9116EC6BB
+PT=B13971219C12C12A8308213759196B0D
+
+I=67
+KEY=701EB5AEF8262D8634B53AF1768ED68E2F7418EAA0250AE52E48B10B6BAA4D68
+IV=E276636E10F8777DF8540D1BA8EC456A
+CT=B13971219C12C12A8308213759196B0D
+PT=4F5A36173C16ED45F5D36B9D1AED84FF
+
+I=68
+KEY=40D027792516E1FE962F63B9C939677C602E2EFD9C33E7A0DB9BDA967147C997
+IV=30CE92D7DD30CC78A29A5948BFB7B1F2
+CT=4F5A36173C16ED45F5D36B9D1AED84FF
+PT=9FB89D6FEFE606058FE40B5492643596
+
+I=69
+KEY=CAAFC0DD2E4FC86AC19B40BC34F14630FF96B39273D5E1A5547FD1C2E323FC01
+IV=8A7FE7A40B59299457B42305FDC8214C
+CT=9FB89D6FEFE606058FE40B5492643596
+PT=F6D0717F197CBAE383B55117FCBE07AC
+
+I=70
+KEY=CE03D67B6DAB9CFAA0C20129475620230946C2ED6AA95B46D7CA80D51F9DFBAD
+IV=04AC16A643E454906159419573A76613
+CT=F6D0717F197CBAE383B55117FCBE07AC
+PT=7747114FF82F8C7568BE51912CFDB51A
+
+I=71
+KEY=DDCEDD32E5F0D26F7707DAE453288B537E01D3A29286D733BF74D14433604EB7
+IV=13CD0B49885B4E95D7C5DBCD147EAB70
+CT=7747114FF82F8C7568BE51912CFDB51A
+PT=E75313A8DFA7EB0AD1664B14D2DBE284
+
+I=72
+KEY=6B032958C3379BD4BEC22CD4271EB4589952C00A4D213C396E129A50E1BBAC33
+IV=B6CDF46A26C749BBC9C5F63074363F0B
+CT=E75313A8DFA7EB0AD1664B14D2DBE284
+PT=42FEDBDC4F0BD11DA42163D76E952DC7
+
+I=73
+KEY=1710F6CF86EDB5F1364F19CA676ED69BDBAC1BD6022AED24CA33F9878F2E81F4
+IV=7C13DF9745DA2E25888D351E407062C3
+CT=42FEDBDC4F0BD11DA42163D76E952DC7
+PT=6E0166BA404B3AEFACCA8E972F087EA5
+
+I=74
+KEY=9D9711F138D0C2D1003E2C99BB0F0447B5AD7D6C4261D7CB66F97710A026FF51
+IV=8A87E73EBE3D772036713553DC61D2DC
+CT=6E0166BA404B3AEFACCA8E972F087EA5
+PT=644A1DCFCA2EC01C3E8911768837D99E
+
+I=75
+KEY=1BD7E446FADA5507ECE26BBB635045E7D1E760A3884F17D758706666281126CF
+IV=8640F5B7C20A97D6ECDC4722D85F41A0
+CT=644A1DCFCA2EC01C3E8911768837D99E
+PT=4E69AE75BD37DB8024DBD1A11D6D414E
+
+I=76
+KEY=3454FD4B259FB4C086288ADAFF6464CD9F8ECED63578CC577CABB7C7357C6781
+IV=2F83190DDF45E1C76ACAE1619C34212A
+CT=4E69AE75BD37DB8024DBD1A11D6D414E
+PT=F63964784AD35374EAFC933AC11A48B6
+
+I=77
+KEY=97EFD593918FB16F2D6889C118C5ED4469B7AAAE7FAB9F23965724FDF4662F37
+IV=A3BB28D8B41005AFAB40031BE7A18989
+CT=F63964784AD35374EAFC933AC11A48B6
+PT=51CBF7F67A22DA909567D67F1919ECEF
+
+I=78
+KEY=481E90BC31903905C08D0E5AEF79A514387C5D58058945B30330F282ED7FC3D8
+IV=DFF1452FA01F886AEDE5879BF7BC4850
+CT=51CBF7F67A22DA909567D67F1919ECEF
+PT=9AE181DE8DB65E7E242926091A17D0B1
+
+I=79
+KEY=35A4F86146CED63BDCB485B0AE4C205AA29DDC86883F1BCD2719D48BF7681369
+IV=7DBA68DD775EEF3E1C398BEA4135854E
+CT=9AE181DE8DB65E7E242926091A17D0B1
+PT=47E15B5AC96A7FDB805F3B8862D9055F
+
+I=80
+KEY=5ECF20C5884FDF95C2B7C17D40CD6923E57C87DC41556416A746EF0395B11636
+IV=6B6BD8A4CE8109AE1E0344CDEE814979
+CT=47E15B5AC96A7FDB805F3B8862D9055F
+PT=1806C474A1ECE5D8183E725804FB92C3
+
+I=81
+KEY=AC473047ADF97E75C100CBBD73FA0892FD7A43A8E0B981CEBF789D5B914A84F5
+IV=F288108225B6A1E003B70AC0333761B1
+CT=1806C474A1ECE5D8183E725804FB92C3
+PT=0A0615424DAD4EFC25EC43B13C672727
+
+I=82
+KEY=6620AE39484EDD0EC21A3E3F659537DDF77C56EAAD14CF329A94DEEAAD2DA3D2
+IV=CA679E7EE5B7A37B031AF582166F3F4F
+CT=0A0615424DAD4EFC25EC43B13C672727
+PT=551639A520D0D043CAD42CB02900D5EF
+
+I=83
+KEY=04D696BB056CC59492B376CB3A0286EAA26A6F4F8DC41F715040F25A842D763D
+IV=62F638824D22189A50A948F45F97B137
+CT=551639A520D0D043CAD42CB02900D5EF
+PT=DF906B0E72FEACC9B45381B992E23A5A
+
+I=84
+KEY=0AED1F2A6660BDBA660E00137E38C1C97DFA0441FF3AB3B8E41373E316CF4C67
+IV=0E3B8991630C782EF4BD76D8443A4723
+CT=DF906B0E72FEACC9B45381B992E23A5A
+PT=D477C6287D05C0F83B27B1FD91F5F908
+
+I=85
+KEY=E0A51B848A913A860FD2C39941C8C3A1A98DC269823F7340DF34C21E873AB56F
+IV=EA4804AEECF1873C69DCC38A3FF00268
+CT=D477C6287D05C0F83B27B1FD91F5F908
+PT=6AB7E109C085B0BA7C8A8B76482F9C80
+
+I=86
+KEY=A8B0500EC0292EF668A03E8293E235BAC33A236042BAC3FAA3BE4968CF1529EF
+IV=48154B8A4AB814706772FD1BD22AF61B
+CT=6AB7E109C085B0BA7C8A8B76482F9C80
+PT=71A31000A5763A0C79B6353E39FFBE84
+
+I=87
+KEY=34C53C34901B693F4611F20F1DD5125EB2993360E7CCF9F6DA087C56F6EA976B
+IV=9C756C3A503247C92EB1CC8D8E3727E4
+CT=71A31000A5763A0C79B6353E39FFBE84
+PT=B5B377EBEBC0B32A5A0C7E2A2504C32A
+
+I=88
+KEY=A13850B9164EF60EB77E06819605AC01072A448B0C0C4ADC8004027CD3EE5441
+IV=95FD6C8D86559F31F16FF48E8BD0BE5F
+CT=B5B377EBEBC0B32A5A0C7E2A2504C32A
+PT=B74459D1E7C5CF9106C362572FE9C917
+
+I=89
+KEY=37261F6D588FF9028A23319CE02DDA71B06E1D5AEBC9854D86C7602BFC079D56
+IV=961E4FD44EC10F0C3D5D371D76287670
+CT=B74459D1E7C5CF9106C362572FE9C917
+PT=5777A0854A6E00DB0B6B199BDD35447A
+
+I=90
+KEY=085A7B276E58B9175204A87D74B9E78AE719BDDFA1A785968DAC79B02132D92C
+IV=3F7C644A36D74015D82799E194943DFB
+CT=5777A0854A6E00DB0B6B199BDD35447A
+PT=01CC73B6EE44403DFED2C91D6F0DC441
+
+I=91
+KEY=61DC99DD0C1470F511D79DCC2541002AE6D5CE694FE3C5AB737EB0AD4E3F1D6D
+IV=6986E2FA624CC9E243D335B151F8E7A0
+CT=01CC73B6EE44403DFED2C91D6F0DC441
+PT=8993161CF3E75DE836BB2C1955581DB6
+
+I=92
+KEY=AEB68207F1E4395794BA7E28CE9BF7996F46D875BC04984345C59CB41B6700DB
+IV=CF6A1BDAFDF049A2856DE3E4EBDAF7B3
+CT=8993161CF3E75DE836BB2C1955581DB6
+PT=2A4D6929ED3A66E71EFC40F1840CD649
+
+I=93
+KEY=DBF8A8AED7B6D7BCFD1B5BEEC3F01AC0450BB15C513EFEA45B39DC459F6BD692
+IV=754E2AA92652EEEB69A125C60D6BED59
+CT=2A4D6929ED3A66E71EFC40F1840CD649
+PT=596CE09B1176A9FB5A9973086A0E4C12
+
+I=94
+KEY=1A61C7F2FB652E256190C0896F800CD61C6751C74048575F01A0AF4DF5659A80
+IV=C1996F5C2CD3F9999C8B9B67AC701616
+CT=596CE09B1176A9FB5A9973086A0E4C12
+PT=B57AC41360C13F6831689C311BD0ED2C
+
+I=95
+KEY=FC3828E6A9487698231D11C10C353F2DA91D95D42089683730C8337CEEB577AC
+IV=E659EF14522D58BD428DD14863B533FB
+CT=B57AC41360C13F6831689C311BD0ED2C
+PT=F58AA69EEBF25943C728FA26524DE154
+
+I=96
+KEY=9D16CAD42D19D1A3B9CB12566745B2765C97334ACB7B3174F7E0C95ABCF896F8
+IV=612EE2328451A73B9AD603976B708D5B
+CT=F58AA69EEBF25943C728FA26524DE154
+PT=4A678FED6C5E5898A47F2DFE9DF71DF2
+
+I=97
+KEY=D9A8554717435E69EFD4A617CA70B0D216F0BCA7A72569EC539FE4A4210F8B0A
+IV=44BE9F933A5A8FCA561FB441AD3502A4
+CT=4A678FED6C5E5898A47F2DFE9DF71DF2
+PT=38011537A04E6C4A81510899741F2FFC
+
+I=98
+KEY=AA9D9A7B4E187F8D78AAEE11967A20A42EF1A990076B05A6D2CEEC3D5510A4F6
+IV=7335CF3C595B21E4977E48065C0A9076
+CT=38011537A04E6C4A81510899741F2FFC
+PT=6472060F536BC5F83A3C247F63C3580E
+
+I=99
+KEY=90A5D8CD93F0AE068E8DC72CA5DD6E184A83AF9F5400C05EE8F2C84236D3FCF8
+IV=3A3842B6DDE8D18BF627293D33A74EBC
+CT=6472060F536BC5F83A3C247F63C3580E
+PT=08B99B59D0584DAC0412796871FE3F27
+
+I=100
+KEY=489520777A18D5BF65B85AAEA29DB3D8423A34C684588DF2ECE0B12A472DC3DF
+IV=D830F8BAE9E87BB9EB359D820740DDC0
+CT=08B99B59D0584DAC0412796871FE3F27
+PT=E8B8579DF9E918B3D24C18E17068AD66
+
+I=101
+KEY=69542EE000ACEEFB5E0EB471F3CD0927AA82635B7DB195413EACA9CB37456EB9
+IV=21C10E977AB43B443BB6EEDF5150BAFF
+CT=E8B8579DF9E918B3D24C18E17068AD66
+PT=9B6C3234993F6900B3E572B5A43CA644
+
+I=102
+KEY=E88C863186548F35DF6EFB48743B7C1831EE516FE48EFC418D49DB7E9379C8FD
+IV=81D8A8D186F861CE81604F3987F6753F
+CT=9B6C3234993F6900B3E572B5A43CA644
+PT=E0A2962A02698489813292D33D02D0AB
+
+I=103
+KEY=C9DD7904D060B79B83F97A1FC93E50DED14CC745E6E778C80C7B49ADAE7B1856
+IV=2151FF35563438AE5C978157BD052CC6
+CT=E0A2962A02698489813292D33D02D0AB
+PT=10C80B22D8EC54B855E103D6B76C03BC
+
+I=104
+KEY=D208B7A87003A507561FA5C7422A85C5C184CC673E0B2C70599A4A7B19171BEA
+IV=1BD5CEACA063129CD5E6DFD88B14D51B
+CT=10C80B22D8EC54B855E103D6B76C03BC
+PT=CE88B76CC2223EB68BA9B5852C1921DB
+
+I=105
+KEY=27B0E1BF8EA57E8AD51BC3FA278369780F0C7B0BFC2912C6D233FFFE350E3A31
+IV=F5B85617FEA6DB8D8304663D65A9ECBD
+CT=CE88B76CC2223EB68BA9B5852C1921DB
+PT=00401EEE034A193C86A23152AF4B767E
+
+I=106
+KEY=45E37A710D9E754EE90B7C1DBB894DC20F4C65E5FF630BFA5491CEAC9A454C4F
+IV=62539BCE833B0BC43C10BFE79C0A24BA
+CT=00401EEE034A193C86A23152AF4B767E
+PT=CEF1DC8A618BF71C68720E6EEDE31EEF
+
+I=107
+KEY=B432E78F49D50B045C8B598EEA3D4142C1BDB96F9EE8FCE63CE3C0C277A652A0
+IV=F1D19DFE444B7E4AB580259351B40C80
+CT=CEF1DC8A618BF71C68720E6EEDE31EEF
+PT=EF8FB3790627F31E5CBF21B31FF942DE
+
+I=108
+KEY=F5CE9C0AF13DA60D32912620673AEE572E320A1698CF0FF8605CE171685F107E
+IV=41FC7B85B8E8AD096E1A7FAE8D07AF15
+CT=EF8FB3790627F31E5CBF21B31FF942DE
+PT=2EF1C697D948D712AA177855B0D56650
+
+I=109
+KEY=DA14D71084F47D87385EF58128C7517F00C3CC814187D8EACA4B9924D88A762E
+IV=2FDA4B1A75C9DB8A0ACFD3A14FFDBF28
+CT=2EF1C697D948D712AA177855B0D56650
+PT=0A20E82375680D134FE05AC74E3A0217
+
+I=110
+KEY=B68F8C980984E2508E9706117256A4A70AE324A234EFD5F985ABC3E396B07439
+IV=6C9B5B888D709FD7B6C9F3905A91F5D8
+CT=0A20E82375680D134FE05AC74E3A0217
+PT=46AF886AB871A3DABDEB32F1738E180B
+
+I=111
+KEY=078A8955ECB2F6ACB249E2DB36B660794C4CACC88C9E76233840F112E53E6C32
+IV=B10505CDE53614FC3CDEE4CA44E0C4DE
+CT=46AF886AB871A3DABDEB32F1738E180B
+PT=79949181E3D20A3042C1E7BDAE73330B
+
+I=112
+KEY=7CB2A8360EE65417A979D9B5D4A32D2935D83D496F4C7C137A8116AF4B4D5F39
+IV=7B382163E254A2BB1B303B6EE2154D50
+CT=79949181E3D20A3042C1E7BDAE73330B
+PT=12C5E55F6EA47BC44392AE9FB888C1FB
+
+I=113
+KEY=E5835F97C4FF1B007D695DD0E72324A9271DD81601E807D73913B830F3C59EC2
+IV=9931F7A1CA194F17D410846533800980
+CT=12C5E55F6EA47BC44392AE9FB888C1FB
+PT=FCA15AB64A01FA6E89FE41F72A67D9E8
+
+I=114
+KEY=50932FF04CCCE411AA0541726C1C4CD7DBBC82A04BE9FDB9B0EDF9C7D9A2472A
+IV=B51070678833FF11D76C1CA28B3F687E
+CT=FCA15AB64A01FA6E89FE41F72A67D9E8
+PT=7B75EC39F707C3C90691BE561AD5CAC6
+
+I=115
+KEY=ECAEC5FD6AF5F7DF2587C1A40CB046ADA0C96E99BCEE3E70B67C4791C3778DEC
+IV=BC3DEA0D263913CE8F8280D660AC0A7A
+CT=7B75EC39F707C3C90691BE561AD5CAC6
+PT=1D3D15FFA0B69EFA8E146301411DFA49
+
+I=116
+KEY=82F88C3850CC3D111C2125F34840A9A2BDF47B661C58A08A38682490826A77A5
+IV=6E5649C53A39CACE39A6E45744F0EF0F
+CT=1D3D15FFA0B69EFA8E146301411DFA49
+PT=34AFB3D6F0BD9ACB6954BB96B1067F9E
+
+I=117
+KEY=702FEC9E7F0D2369FF35D4B7A1269AD3895BC8B0ECE53A41513C9F06336C083B
+IV=F2D760A62FC11E78E314F144E9663371
+CT=34AFB3D6F0BD9ACB6954BB96B1067F9E
+PT=899E4C8192661CCA7C73CDFBC3DCA2F3
+
+I=118
+KEY=A1DF98E4585C1A4C15C42AD0782C925000C584317E83268B2D4F52FDF0B0AAC8
+IV=D1F0747A27513925EAF1FE67D90A0883
+CT=899E4C8192661CCA7C73CDFBC3DCA2F3
+PT=3097C0413291E217FB0E3A8A2D908C12
+
+I=119
+KEY=9F9082177BF33D8AF6131018E1EFD49F305244704C12C49CD6416877DD2026DA
+IV=3E4F1AF323AF27C6E3D73AC899C346CF
+CT=3097C0413291E217FB0E3A8A2D908C12
+PT=6C71968295905F881F95DC8BA481CA72
+
+I=120
+KEY=B7E5B267EDBFFD4DB4526BA2A1978C105C23D2F2D9829B14C9D4B4FC79A1ECA8
+IV=28753070964CC0C742417BBA4078588F
+CT=6C71968295905F881F95DC8BA481CA72
+PT=96D0AB98DBD0CB94A68FC41BEF0B418D
+
+I=121
+KEY=127FAA6C94663FA9008A1FB7A419C036CAF3796A025250806F5B70E796AAAD25
+IV=A59A180B79D9C2E4B4D87415058E4C26
+CT=96D0AB98DBD0CB94A68FC41BEF0B418D
+PT=9E3E4428A911FB328A9F89D7D5E527DB
+
+I=122
+KEY=1B9493F07E7E5F07473E6997AE15CCDC54CD3D42AB43ABB2E5C4F930434F8AFE
+IV=09EB399CEA1860AE47B476200A0C0CEA
+CT=9E3E4428A911FB328A9F89D7D5E527DB
+PT=0DB5EF3481A9945BAF2E499B5CDE8DDC
+
+I=123
+KEY=7B2B8201EEF1601C44006A6D7E06EE355978D2762AEA3FE94AEAB0AB1F910722
+IV=60BF11F1908F3F1B033E03FAD01322E9
+CT=0DB5EF3481A9945BAF2E499B5CDE8DDC
+PT=C0569DD7DCAE99859D3987B04FFD8CF0
+
+I=124
+KEY=B2D7FEE25A564FA00CEDC8E05BAC7F7D992E4FA1F644A66CD7D3371B506C8BD2
+IV=C9FC7CE3B4A72FBC48EDA28D25AA9148
+CT=C0569DD7DCAE99859D3987B04FFD8CF0
+PT=D8AF74B5BB8E632299D32E8DD4DDA012
+
+I=125
+KEY=5A06C176A290538BC549CAA8041539A941813B144DCAC54E4E00199684B12BC0
+IV=E8D13F94F8C61C2BC9A402485FB946D4
+CT=D8AF74B5BB8E632299D32E8DD4DDA012
+PT=0821FB911EDE8CDCD97DDAEDCCDB7B1C
+
+I=126
+KEY=1318D23A3A966D16FDEEE300571F3A8549A0C08553144992977DC37B486A50DC
+IV=491E134C98063E9D38A729A8530A032C
+CT=0821FB911EDE8CDCD97DDAEDCCDB7B1C
+PT=BCB2831AF3721C020FC1D683C19AEBEA
+
+I=127
+KEY=D6D24AA79B3CA4434CCE2B1470B4FE18F512439FA066559098BC15F889F0BB36
+IV=C5CA989DA1AAC955B120C81427ABC49D
+CT=BCB2831AF3721C020FC1D683C19AEBEA
+PT=BE869BB3C18EB622CCAC81B6F5B62CC4
+
+I=128
+KEY=5F62348BCD9ADB23A19E683400D968404B94D82C61E8E3B25410944E7C4697F2
+IV=89B07E2C56A67F60ED504320706D9658
+CT=BE869BB3C18EB622CCAC81B6F5B62CC4
+PT=C8D3EDD549FEA614B4F2348F82DE5531
+
+I=129
+KEY=A64795E417B7C9344185F6B0C66C096B834735F9281645A6E0E2A0C1FE98C2C3
+IV=F925A16FDA2D1217E01B9E84C6B5612B
+CT=C8D3EDD549FEA614B4F2348F82DE5531
+PT=4049BDBD9C302D8F2E06F10D34317784
+
+I=130
+KEY=CD1F9AB35436014B0CF7ECE9FF98C2BDC30E8844B4266829CEE451CCCAA9B547
+IV=6B580F574381C87F4D721A5939F4CBD6
+CT=4049BDBD9C302D8F2E06F10D34317784
+PT=E1338EA5C5462E8C458E5546FA60324D
+
+I=131
+KEY=78F7558C14BB5100CE93CD49C22BE2D9223D06E1716046A58B6A048A30C9870A
+IV=B5E8CF3F408D504BC26421A03DB32064
+CT=E1338EA5C5462E8C458E5546FA60324D
+PT=055984AA929F4D45F5812DC719D4EF24
+
+I=132
+KEY=2DBC5092C4C7AB427576EBA2855E00562764824BE3FF0BE07EEB294D291D682E
+IV=554B051ED07CFA42BBE526EB4775E28F
+CT=055984AA929F4D45F5812DC719D4EF24
+PT=ABC519C4290C69D98BF7AC2A56767202
+
+I=133
+KEY=68FA1D8FE36FC5B48A7486FBB34A7B598CA19B8FCAF36239F51C85677F6B1A2C
+IV=45464D1D27A86EF6FF026D5936147B0F
+CT=ABC519C4290C69D98BF7AC2A56767202
+PT=C825E44799B1739A1F4CB406BBEABEDD
+
+I=134
+KEY=A2302849850FD33D4048B898DB6C7B0244847FC8534211A3EA503161C481A4F1
+IV=CACA35C666601689CA3C3E636826005B
+CT=C825E44799B1739A1F4CB406BBEABEDD
+PT=D24EE8D56CE09AFE1061B4016ADD61F7
+
+I=135
+KEY=9B2E669EA4BB938072E6E97B0ACF834E96CA971D3FA28B5DFA318560AE5CC506
+IV=391E4ED721B440BD32AE51E3D1A3F84C
+CT=D24EE8D56CE09AFE1061B4016ADD61F7
+PT=50FECB118EABF93BB97102E9212C883D
+
+I=136
+KEY=A07C5EBAC9D0F862AD525C76460B4BA9C6345C0CB1097266434087898F704D3B
+IV=3B5238246D6B6BE2DFB4B50D4CC4C8E7
+CT=50FECB118EABF93BB97102E9212C883D
+PT=C370C26BD3805211A4679399DFA4DDCB
+
+I=137
+KEY=414C776222058D6285574741B2B4D11D05449E6762892077E727141050D490F0
+IV=E13029D8EBD5750028051B37F4BF9AB4
+CT=C370C26BD3805211A4679399DFA4DDCB
+PT=79715A04DF9216268C77A152CA96C2F6
+
+I=138
+KEY=5E54A416470FE8BA263C0FC88FD884297C35C463BD1B36516B50B5429A425206
+IV=1F18D374650A65D8A36B48893D6C5534
+CT=79715A04DF9216268C77A152CA96C2F6
+PT=06DF18B5FAF35F03FE22E39CAE430655
+
+I=139
+KEY=98C55CFFB53FA72345EF936283F64BB17AEADCD647E86952957256DE34015453
+IV=C691F8E9F2304F9963D39CAA0C2ECF98
+CT=06DF18B5FAF35F03FE22E39CAE430655
+PT=1AED42EB32C4BAEAF9946818AA00C324
+
+I=140
+KEY=B8332B1EE5D6A4E1BBFA20AEAE22330560079E3D752CD3B86CE63EC69E019777
+IV=20F677E150E903C2FE15B3CC2DD478B4
+CT=1AED42EB32C4BAEAF9946818AA00C324
+PT=D276B6A6D480165A944572EF76D4B3E8
+
+I=141
+KEY=6E50753A2A0814A778FA2BC773C6A7A2B271289BA1ACC5E2F8A34C29E8D5249F
+IV=D6635E24CFDEB046C3000B69DDE494A7
+CT=D276B6A6D480165A944572EF76D4B3E8
+PT=BA46F59DFADC6CA2CBB7D80E33D7B24B
+
+I=142
+KEY=D8E1763EAD728AB8AA2284964BE586880837DD065B70A94033149427DB0296D4
+IV=B6B10304877A9E1FD2D8AF513823212A
+CT=BA46F59DFADC6CA2CBB7D80E33D7B24B
+PT=FC9B9F7B5120E1D8B2DD58D211EFF053
+
+I=143
+KEY=458CB146C73342F9D5EE4364C400E8E5F4AC427D0A50489881C9CCF5CAED6687
+IV=9D6DC7786A41C8417FCCC7F28FE56E6D
+CT=FC9B9F7B5120E1D8B2DD58D211EFF053
+PT=6AD8BCAEFF6F0BF9F360FF601C9B7A43
+
+I=144
+KEY=F1FBE00DA1F634ACACB6E2F4F15C11179E74FED3F53F436172A93395D6761CC4
+IV=B477514B66C576557958A190355CF9F2
+CT=6AD8BCAEFF6F0BF9F360FF601C9B7A43
+PT=BB6E45D060E186323AC2B50CFB988856
+
+I=145
+KEY=3FBC35054FFF43657936BB676A5C5D1F251ABB0395DEC553486B86992DEE9492
+IV=CE47D508EE0977C9D58059939B004C08
+CT=BB6E45D060E186323AC2B50CFB988856
+PT=31B6157397933EE35DEE5B40FE7237BB
+
+I=146
+KEY=D49B4E96F8FC2D91FBED3985C53BEB8314ACAE70024DFBB01585DDD9D39CA329
+IV=EB277B93B7036EF482DB82E2AF67B69C
+CT=31B6157397933EE35DEE5B40FE7237BB
+PT=EFEB82ED91C5C60FB8F910542804B57B
+
+I=147
+KEY=8D4ABC926827F066B4391FF4B3D6EC99FB472C9D93883DBFAD7CCD8DFB981652
+IV=59D1F20490DBDDF74FD4267176ED071A
+CT=EFEB82ED91C5C60FB8F910542804B57B
+PT=E30D071737AB9991F000302502BE84A6
+
+I=148
+KEY=086A14365F781B2FAF533B1534F458D2184A2B8AA423A42E5D7CFDA8F92692F4
+IV=8520A8A4375FEB491B6A24E18722B44B
+CT=E30D071737AB9991F000302502BE84A6
+PT=856AF9DF9A9FE5038B75C98E0E1C720F
+
+I=149
+KEY=A64DE8CF2DF04ADB60E88C769F7025BC9D20D2553EBC412DD6093426F73AE0FB
+IV=AE27FCF9728851F4CFBBB763AB847D6E
+CT=856AF9DF9A9FE5038B75C98E0E1C720F
+PT=D84910F298F91E081480A912B1AF32D6
+
+I=150
+KEY=C52575277A0BD189E2F746FC51CA77844569C2A7A6455F25C2899D344695D22D
+IV=63689DE857FB9B52821FCA8ACEBA5238
+CT=D84910F298F91E081480A912B1AF32D6
+PT=57E4A4A2D639D414ED7F82583B4FFA52
+
+I=151
+KEY=CB9A5219490F7EE31B030ECE521C589B128D6605707C8B312FF61F6C7DDA287F
+IV=0EBF273E3304AF6AF9F4483203D62F1F
+CT=57E4A4A2D639D414ED7F82583B4FFA52
+PT=1CECC8218392F2047C0B70BEBFCC5846
+
+I=152
+KEY=AA6412AAC8FC309E6BCDFFD1DA01B6470E61AE24F3EE793553FD6FD2C2167039
+IV=61FE40B381F34E7D70CEF11F881DEEDC
+CT=1CECC8218392F2047C0B70BEBFCC5846
+PT=EC2B86A04DB2B4F41830E5EA035531E3
+
+I=153
+KEY=EFF5BC892E47F4C7EA859969255AC665E24A2884BE5CCDC14BCD8A38C14341DA
+IV=4591AE23E6BBC459814866B8FF5B7022
+CT=EC2B86A04DB2B4F41830E5EA035531E3
+PT=8A1A8EE6E08F61E99FC37AC177881C8A
+
+I=154
+KEY=D62E9405D7402765E30FDAD7A29B2E716850A6625ED3AC28D40EF0F9B6CB5D50
+IV=39DB288CF907D3A2098A43BE87C1E814
+CT=8A1A8EE6E08F61E99FC37AC177881C8A
+PT=F21583AC8C5F03C19A1A9B856C97D6E0
+
+I=155
+KEY=D49F229B7DB6973EDE6BD14AB20234379A4525CED28CAFE94E146B7CDA5C8BB0
+IV=02B1B69EAAF6B05B3D640B9D10991A46
+CT=F21583AC8C5F03C19A1A9B856C97D6E0
+PT=323191D5997CF0424B7F5501CBD55B17
+
+I=156
+KEY=08B1021CD316864EF5B370CBF891FD27A874B41B4BF05FAB056B3E7D1189D0A7
+IV=DC2E2087AEA011702BD8A1814A93C910
+CT=323191D5997CF0424B7F5501CBD55B17
+PT=B2BBCC6E54CB33319536A81174B0D73B
+
+I=157
+KEY=786AE1D89ECC32C8883D984E7DC5FD0A1ACF78751F3B6C9A905D966C6539079C
+IV=70DBE3C44DDAB4867D8EE8858554002D
+CT=B2BBCC6E54CB33319536A81174B0D73B
+PT=6E4ADDA6895734D891F328C6D0C71467
+
+I=158
+KEY=E6C7441B75AF8701E29376287A126CB07485A5D3966C584201AEBEAAB5FE13FB
+IV=9EADA5C3EB63B5C96AAEEE6607D791BA
+CT=6E4ADDA6895734D891F328C6D0C71467
+PT=8BED3D2AAB5271F90EE5335520E87AA2
+
+I=159
+KEY=22D515400072783951742ACDF2FA6DC8FF6898F93D3E29BB0F4B8DFF95166959
+IV=C412515B75DDFF38B3E75CE588E80178
+CT=8BED3D2AAB5271F90EE5335520E87AA2
+PT=D3059CA1B293AA1F52D459643C5FAB5C
+
+I=160
+KEY=D6E6A383AF38A1CD2889A5F79A23CE512C6D04588FAD83A45D9FD49BA949C205
+IV=F433B6C3AF4AD9F479FD8F3A68D9A399
+CT=D3059CA1B293AA1F52D459643C5FAB5C
+PT=C20D8580ACA043B0ED2F409EEA42C0F0
+
+I=161
+KEY=AA95A47ADECB61AAD1A05DA0CE6B17BDEE6081D8230DC014B0B09405430B02F5
+IV=7C7307F971F3C067F929F8575448D9EC
+CT=C20D8580ACA043B0ED2F409EEA42C0F0
+PT=61C0D0081F176C53DE83B70608201EE6
+
+I=162
+KEY=168A56A528A70354AD74C59A8AF33A508FA051D03C1AAC476E3323034B2B1C13
+IV=BC1FF2DFF66C62FE7CD4983A44982DED
+CT=61C0D0081F176C53DE83B70608201EE6
+PT=C016536FEFC08B69867AB2946FFBE011
+
+I=163
+KEY=92157F38953622D8C0E191DAC4179A6A4FB602BFD3DA272EE849919724D0FC02
+IV=849F299DBD91218C6D9554404EE4A03A
+CT=C016536FEFC08B69867AB2946FFBE011
+PT=6923FF03C812710270438F67EF2F42D1
+
+I=164
+KEY=CCB6779947D31DF17182FB54555B49422695FDBC1BC8562C980A1EF0CBFFBED3
+IV=5EA308A1D2E53F29B1636A8E914CD328
+CT=6923FF03C812710270438F67EF2F42D1
+PT=0D1674014AD9DC2150E073E2FCF006A8
+
+I=165
+KEY=22AA52C07B42CFEB5E75687D395D86092B8389BD51118A0DC8EA6D12370FB87B
+IV=EE1C25593C91D21A2FF793296C06CF4B
+CT=0D1674014AD9DC2150E073E2FCF006A8
+PT=6399A65CC66E9318F2CEE1103B8FFB90
+
+I=166
+KEY=527EF084271AC57F5D33F2E7C7BE1FF1481A2FE1977F19153A248C020C8043EB
+IV=70D4A2445C580A9403469A9AFEE399F8
+CT=6399A65CC66E9318F2CEE1103B8FFB90
+PT=511CBDD6CFA31788A43C765301D6BAAB
+
+I=167
+KEY=D826E762C9EA31B6F4415B3AE5ED888B1906923758DC0E9D9E18FA510D56F940
+IV=8A5817E6EEF0F4C9A972A9DD2253977A
+CT=511CBDD6CFA31788A43C765301D6BAAB
+PT=B04E78AB18AE3F5B825087D9D5794BD7
+
+I=168
+KEY=B4C2DEE60A738C428B187EC3A3A4A982A948EA9C407231C61C487D88D82FB297
+IV=6CE43984C399BDF47F5925F946492109
+CT=B04E78AB18AE3F5B825087D9D5794BD7
+PT=6B013F9A972D82BD5A87DA6C1DD5FD0F
+
+I=169
+KEY=C4A41F8C4B26391F6C0D629C6B052BD8C249D506D75FB37B46CFA7E4C5FA4F98
+IV=7066C16A4155B55DE7151C5FC8A1825A
+CT=6B013F9A972D82BD5A87DA6C1DD5FD0F
+PT=9005F8243C6486F63590E7508503719C
+
+I=170
+KEY=91A18F2681FCACE1C80DC772BD0F2628524C2D22EB3B358D735F40B440F93E04
+IV=550590AACADA95FEA400A5EED60A0DF0
+CT=9005F8243C6486F63590E7508503719C
+PT=39DEEEC3D3AEEBBF4B573462B375B5E4
+
+I=171
+KEY=E8FF0EE1269AFDCA213F69757C84704D6B92C3E13895DE32380874D6F38C8BE0
+IV=795E81C7A766512BE932AE07C18B5665
+CT=39DEEEC3D3AEEBBF4B573462B375B5E4
+PT=1910F8E7C3D863784058CB35D674AEEB
+
+I=172
+KEY=F00751EFCCECA0ECA3C252F396B4078E72823B06FB4DBD4A7850BFE325F8250B
+IV=18F85F0EEA765D2682FD3B86EA3077C3
+CT=1910F8E7C3D863784058CB35D674AEEB
+PT=4A71250E55629D3C5CC62B18B4B67653
+
+I=173
+KEY=383A1B81E82B8174A9B9F0AF9EA498A338F31E08AE2F2076249694FB914E5358
+IV=C83D4A6E24C721980A7BA25C08109F2D
+CT=4A71250E55629D3C5CC62B18B4B67653
+PT=19CBB63FBB92C7A10B676DBB5EB29060
+
+I=174
+KEY=A6695341053BD5B1E15A6CD73DEF84E12138A83715BDE7D72FF1F940CFFCC338
+IV=9E5348C0ED1054C548E39C78A34B1C42
+CT=19CBB63FBB92C7A10B676DBB5EB29060
+PT=18BA0A45E67D2CFEC691203FC2509837
+
+I=175
+KEY=71B4C384EF619E5D6CADBFC7D53564913982A272F3C0CB29E960D97F0DAC5B0F
+IV=D7DD90C5EA5A4BEC8DF7D310E8DAE070
+CT=18BA0A45E67D2CFEC691203FC2509837
+PT=7699C8550933C30D630AC16D8DA6F13D
+
+I=176
+KEY=7D0527970FD45C35817091A317A2EAB04F1B6A27FAF308248A6A1812800AAA32
+IV=0CB1E413E0B5C268EDDD2E64C2978E21
+CT=7699C8550933C30D630AC16D8DA6F13D
+PT=78FE8EEC14618ED34F63E8671434ADA7
+
+I=177
+KEY=204ECE43E91409C515077FACC37C4DF837E5E4CBEE9286F7C509F075943E0795
+IV=5D4BE9D4E6C055F09477EE0FD4DEA748
+CT=78FE8EEC14618ED34F63E8671434ADA7
+PT=0907F75149A74B49F302D2C08CF18AF5
+
+I=178
+KEY=8E80DC69B6CC0F0D7F1F0BE6E9F178AD3EE2139AA735CDBE360B22B518CF8D60
+IV=AECE122A5FD806C86A18744A2A8D3555
+CT=0907F75149A74B49F302D2C08CF18AF5
+PT=FE24023BCABCD83E6212FA53E7320D92
+
+I=179
+KEY=5152CCE87D9CCC930D7B376C4F1B334BC0C611A16D8915805419D8E6FFFD80F2
+IV=DFD21081CB50C39E72643C8AA6EA4BE6
+CT=FE24023BCABCD83E6212FA53E7320D92
+PT=9526CDED534CB3366306F8C731F87CD6
+
+I=180
+KEY=00C9D78F67F1B63181ADE21A02675C6755E0DC4C3EC5A6B6371F2021CE05FC24
+IV=519B1B671A6D7AA28CD6D5764D7C6F2C
+CT=9526CDED534CB3366306F8C731F87CD6
+PT=801F005EA2E9287FFD8D9B01BE8E2205
+
+I=181
+KEY=442603CF6A012BDB23086BD7EFD7396ED5FFDC129C2C8EC9CA92BB20708BDE21
+IV=44EFD4400DF09DEAA2A589CDEDB06509
+CT=801F005EA2E9287FFD8D9B01BE8E2205
+PT=7558994ACE0299E34EB586B832C98560
+
+I=182
+KEY=B153C7C49983077FB0C79C30266A487AA0A74558522E172A84273D9842425B41
+IV=F575C40BF3822CA493CFF7E7C9BD7114
+CT=7558994ACE0299E34EB586B832C98560
+PT=324273A52FFBFBCAC5401CFCD3075C98
+
+I=183
+KEY=0E038D82F7FAD738824EF9FEB6F6627692E536FD7DD5ECE041672164914507D9
+IV=BF504A466E79D047328965CE909C2A0C
+CT=324273A52FFBFBCAC5401CFCD3075C98
+PT=509E651E053E85340A5B545AA0E40A71
+
+I=184
+KEY=B2237D5D0E16B5F9A8FD7274F4CA1206C27B53E378EB69D44B3C753E31A10DA8
+IV=BC20F0DFF9EC62C12AB38B8A423C7070
+CT=509E651E053E85340A5B545AA0E40A71
+PT=1716AB4DCAB205D62EF356E4C565BA70
+
+I=185
+KEY=CBE25CF8F3CAB9849F44F330AD8B17E1D56DF8AEB2596C0265CF23DAF4C4B7D8
+IV=79C121A5FDDC0C7D37B98144594105E7
+CT=1716AB4DCAB205D62EF356E4C565BA70
+PT=093CA7764E7F6828EF210E89D3D01C73
+
+I=186
+KEY=2BF3C06B0CAE728C8A6134634D5DEAF1DC515FD8FC26042A8AEE2D532714ABAB
+IV=E0119C93FF64CB081525C753E0D6FD10
+CT=093CA7764E7F6828EF210E89D3D01C73
+PT=86F8B39DB10EB8B3CFED4C98BBBFFAE1
+
+I=187
+KEY=A2C742CFF575CA98D3261BE7DA99E3935AA9EC454D28BC99450361CB9CAB514A
+IV=893482A4F9DBB81459472F8497C40962
+CT=86F8B39DB10EB8B3CFED4C98BBBFFAE1
+PT=8BF9C14617B3CE1511ABBD484439D041
+
+I=188
+KEY=F8AB8BAD8F2C5A54ED4C80AD094A36D4D1502D035A9B728C54A8DC83D892810B
+IV=5A6CC9627A5990CC3E6A9B4AD3D3D547
+CT=8BF9C14617B3CE1511ABBD484439D041
+PT=C41B937B1D5E10D982C7850685997862
+
+I=189
+KEY=4DBA6859C8D681253E8F6278BE76D87D154BBE7847C56255D66F59855D0BF969
+IV=B511E3F447FADB71D3C3E2D5B73CEEA9
+CT=C41B937B1D5E10D982C7850685997862
+PT=467114F3F33C8BA65AA76C297E9DA11C
+
+I=190
+KEY=2738E652A9F41B48B443B487B2AF6D7C533AAA8BB4F9E9F38CC835AC23965875
+IV=6A828E0B61229A6D8ACCD6FF0CD9B501
+CT=467114F3F33C8BA65AA76C297E9DA11C
+PT=CB9D772C72BC5BB3E18087CABADDE5B2
+
+I=191
+KEY=A1C138E8AFAA19465AE9BD1968C19E8798A7DDA7C645B2406D48B266994BBDC7
+IV=86F9DEBA065E020EEEAA099EDA6EF3FB
+CT=CB9D772C72BC5BB3E18087CABADDE5B2
+PT=678837A26F65190F44107C19A01F97E6
+
+I=192
+KEY=CD73AF62C6130630324F71F35042BC9AFF2FEA05A920AB4F2958CE7F39542A21
+IV=6CB2978A69B91F7668A6CCEA3883221D
+CT=678837A26F65190F44107C19A01F97E6
+PT=E395804E9F2D61447B5207AA438F7D98
+
+I=193
+KEY=F076EAF59DAC3F3975E9CBED6697A21B1CBA6A4B360DCA0B520AC9D57ADB57B9
+IV=3D0545975BBF390947A6BA1E36D51E81
+CT=E395804E9F2D61447B5207AA438F7D98
+PT=CA6E3E780C170E950306FEE08CAB46D9
+
+I=194
+KEY=87DD7A9906E626E1AC55611A52EBC196D6D454333A1AC49E510C3735F6701160
+IV=77AB906C9B4A19D8D9BCAAF7347C638D
+CT=CA6E3E780C170E950306FEE08CAB46D9
+PT=419B7C538E827E431B2C2BA5AEB95373
+
+I=195
+KEY=C8D569C710030750FDA3A48E748BED26974F2860B498BADD4A201C9058C94213
+IV=4F08135E16E521B151F6C59426602CB0
+CT=419B7C538E827E431B2C2BA5AEB95373
+PT=1D6607B51B0DA629C62D00CB20870FEA
+
+I=196
+KEY=A3A22E3CED89316BC747E3326CB53C448A292FD5AF951CF48C0D1C5B784E4DF9
+IV=6B7747FBFD8A363B3AE447BC183ED162
+CT=1D6607B51B0DA629C62D00CB20870FEA
+PT=58169D0006C9031C7CCE502F086B0CD6
+
+I=197
+KEY=DDB2F456CFE201D5E1DD9EFC6593813FD23FB2D5A95C1FE8F0C34C747025412F
+IV=7E10DA6A226B30BE269A7DCE0926BD7B
+CT=58169D0006C9031C7CCE502F086B0CD6
+PT=8001E1BDAE24A2A9ABE102C2BEB4AD70
+
+I=198
+KEY=A990048427C8E19BABE1D0BB5D6A83CA523E53680778BD415B224EB6CE91EC5F
+IV=7422F0D2E82AE04E4A3C4E4738F902F5
+CT=8001E1BDAE24A2A9ABE102C2BEB4AD70
+PT=EA143E99846F5DF1C1A2AD0565D3AE45
+
+I=199
+KEY=5074E20E5B70B571A7155A3AAFE3AF2AB82A6DF18317E0B09A80E3B3AB42421A
+IV=F9E4E68A7CB854EA0CF48A81F2892CE0
+CT=EA143E99846F5DF1C1A2AD0565D3AE45
+PT=C1EBFE1B00D813BB5AC9E4B007977B19
+
+I=200
+KEY=50315F6BF520F26A044751215225348179C193EA83CFF30BC0490703ACD53903
+IV=0045BD65AE50471BA3520B1BFDC69BAB
+CT=C1EBFE1B00D813BB5AC9E4B007977B19
+PT=3476AA08CB11F13D8DD858CF10472D03
+
+I=201
+KEY=03D2536F9830D74A9B2AEDD1508CE4764DB739E248DE02364D915FCCBC921400
+IV=53E30C046D1025209F6DBCF002A9D0F7
+CT=3476AA08CB11F13D8DD858CF10472D03
+PT=C79BED3BB201F29B65CDF5709654317C
+
+I=202
+KEY=4AC2173AD99E09ECCB4A647AF96C26F98A2CD4D9FADFF0AD285CAABC2AC6257C
+IV=4910445541AEDEA6506089ABA9E0C28F
+CT=C79BED3BB201F29B65CDF5709654317C
+PT=E5E144D56A2FF95D644D51E73AEAE922
+
+I=203
+KEY=9F46778CA9C15CB9978C0DF359056F3D6FCD900C90F009F04C11FB5B102CCC5E
+IV=D58460B6705F55555CC66989A06949C4
+CT=E5E144D56A2FF95D644D51E73AEAE922
+PT=38582F30FDE74A162CCD85955C2E48FC
+
+I=204
+KEY=63038F8EA2934D0C65F181BE92B9664A5795BF3C6D1743E660DC7ECE4C0284A2
+IV=FC45F8020B5211B5F27D8C4DCBBC0977
+CT=38582F30FDE74A162CCD85955C2E48FC
+PT=266E808D7E9206C9294F0349D1CEF1DA
+
+I=205
+KEY=D43CC15DCAB5047B8C67D61F1735C6A471FB3FB11385452F49937D879DCC7578
+IV=B73F4ED368264977E99657A1858CA0EE
+CT=266E808D7E9206C9294F0349D1CEF1DA
+PT=8E3D1F7DC678C32352782D52E4CD44D5
+
+I=206
+KEY=9979232A388E0E6C766279CFE7E047B4FFC620CCD5FD860C1BEB50D5790131AD
+IV=4D45E277F23B0A17FA05AFD0F0D58110
+CT=8E3D1F7DC678C32352782D52E4CD44D5
+PT=DDC8075418E2A649D4E78144528682F9
+
+I=207
+KEY=43479EA72BF3B417CF224B15749043C5220E2798CD1F2045CF0CD1912B87B354
+IV=DA3EBD8D137DBA7BB94032DA93700471
+CT=DDC8075418E2A649D4E78144528682F9
+PT=4096B4F51C77C8A00A5308D8C3175B6A
+
+I=208
+KEY=7AE39630885C3ACDCF915625141DF45A6298936DD168E8E5C55FD949E890E83E
+IV=39A40897A3AF8EDA00B31D30608DB79F
+CT=4096B4F51C77C8A00A5308D8C3175B6A
+PT=60D0385ECE913BEC6760BAA0BCCDE853
+
+I=209
+KEY=82496ADB8A91DAE80C249D2BD8F00C990248AB331FF9D309A23F63E9545D006D
+IV=F8AAFCEB02CDE025C3B5CB0ECCEDF8C3
+CT=60D0385ECE913BEC6760BAA0BCCDE853
+PT=79A86909141C27366744FC614808705B
+
+I=210
+KEY=EF7FEE5E3FDAC015E8016A7A9D3EB8677BE0C23A0BE5F43FC57B9F881C557036
+IV=6D368485B54B1AFDE425F75145CEB4FE
+CT=79A86909141C27366744FC614808705B
+PT=9817CE82A9D821189878991B32360409
+
+I=211
+KEY=A400D423453A59F64968E8B80140AAF6E3F70CB8A23DD5275D0306932E63743F
+IV=4B7F3A7D7AE099E3A16982C29C7E1291
+CT=9817CE82A9D821189878991B32360409
+PT=C3259E5D4A3E82FDC862E862E4449DA2
+
+I=212
+KEY=B9280C8996C8BEC6888CB4D9D1E76B0620D292E5E80357DA9561EEF1CA27E99D
+IV=1D28D8AAD3F2E730C1E45C61D0A7C1F0
+CT=C3259E5D4A3E82FDC862E862E4449DA2
+PT=F035078B9A3E45B4ED561F001DB21E47
+
+I=213
+KEY=9686D9BB259CD14FA7D58C9789932385D0E7956E723D126E7837F1F1D795F7DA
+IV=2FAED532B3546F892F59384E58744883
+CT=F035078B9A3E45B4ED561F001DB21E47
+PT=596B9F7F2122A11C599626B16B6AC340
+
+I=214
+KEY=736E847DDC4C794A3AA2E22C1AF85EF1898C0A11531FB37221A1D740BCFF349A
+IV=E5E85DC6F9D0A8059D776EBB936B7D74
+CT=596B9F7F2122A11C599626B16B6AC340
+PT=800FCC5CE3B08CFFDD70FB5270DED220
+
+I=215
+KEY=728D3E35CD653621D41E591530770B370983C64DB0AF3F8DFCD12C12CC21E6BA
+IV=01E3BA4811294F6BEEBCBB392A8F55C6
+CT=800FCC5CE3B08CFFDD70FB5270DED220
+PT=5515A58EB0013D2EE561BD2826761209
+
+I=216
+KEY=929F6FD8250BAD33FAE4ED108843A2645C9663C300AE02A319B0913AEA57F4B3
+IV=E01251EDE86E9B122EFAB405B834A953
+CT=5515A58EB0013D2EE561BD2826761209
+PT=8B7B3AB73287CEAAA0098D41F0B3A28B
+
+I=217
+KEY=3F54C218B02F6097C3F31A05F5CCB8C4D7ED59743229CC09B9B91C7B1AE45638
+IV=ADCBADC09524CDA43917F7157D8F1AA0
+CT=8B7B3AB73287CEAAA0098D41F0B3A28B
+PT=90CDCF132600F622D1339197B441A4C0
+
+I=218
+KEY=2F60AEE4E6A6F7109193112BC756D7F24720966714293A2B688A8DECAEA5F2F8
+IV=10346CFC5689978752600B2E329A6F36
+CT=90CDCF132600F622D1339197B441A4C0
+PT=EA089BEC0DEE1305828522B8AD4F5A99
+
+I=219
+KEY=33623A9F86F3AF456D92076B132E46A3AD280D8B19C7292EEA0FAF5403EAA861
+IV=1C02947B60555855FC011640D4789151
+CT=EA089BEC0DEE1305828522B8AD4F5A99
+PT=339C14562AE38F84BE0FB1569C234287
+
+I=220
+KEY=6291ED0B63ED8C18A713DDCBFCA054E19EB419DD3324A6AA54001E029FC9EAE6
+IV=51F3D794E51E235DCA81DAA0EF8E1242
+CT=339C14562AE38F84BE0FB1569C234287
+PT=31050E95B1F08B9139EF7F8D42110978
+
+I=221
+KEY=7BEF1BE3E67AA478C5D9F50350D221CCAFB1174882D42D3B6DEF618FDDD8E39E
+IV=197EF6E88597286062CA28C8AC72752D
+CT=31050E95B1F08B9139EF7F8D42110978
+PT=18DE66E3B58C9ABAB99987826AF0D0AF
+
+I=222
+KEY=3DEB69283844069B400C2E7127B8CD2EB76F71AB3758B781D476E60DB7283331
+IV=460472CBDE3EA2E385D5DB72776AECE2
+CT=18DE66E3B58C9ABAB99987826AF0D0AF
+PT=B75D11E28C94DB969FE009B984DA956B
+
+I=223
+KEY=754C5BEC642540EC8BAD0778773CA8E700326049BBCC6C174B96EFB433F2A65A
+IV=48A732C45C614677CBA12909508465C9
+CT=B75D11E28C94DB969FE009B984DA956B
+PT=7CEEE835FC734108785B367A28C62058
+
+I=224
+KEY=01B0A659138DEE7CF1EFA11DD0A209247CDC887C47BF2D1F33CDD9CE1B348602
+IV=74FCFDB577A8AE907A42A665A79EA1C3
+CT=7CEEE835FC734108785B367A28C62058
+PT=F1E848F6C257D6D56B4FBCA36900614C
+
+I=225
+KEY=F9531CEDC3C5C76A90195BF1E5FB5ED98D34C08A85E8FBCA5882656D7234E74E
+IV=F8E3BAB4D048291661F6FAEC355957FD
+CT=F1E848F6C257D6D56B4FBCA36900614C
+PT=7B06A193C8B84977E56B382D424D2A78
+
+I=226
+KEY=D409DB9768430BCA0E2B68BA1CFE93A5F63261194D50B2BDBDE95D403079CD36
+IV=2D5AC77AAB86CCA09E32334BF905CD7C
+CT=7B06A193C8B84977E56B382D424D2A78
+PT=413356E3367ACBDD88ADA6DF5E09FFC6
+
+I=227
+KEY=8425B50A014625BA114ABAC1585C3F68B70137FA7B2A79603544FB9F6E7032F0
+IV=502C6E9D69052E701F61D27B44A2ACCD
+CT=413356E3367ACBDD88ADA6DF5E09FFC6
+PT=13B524E8AEBFE32CC9559B500D9E9A82
+
+I=228
+KEY=3ED2EEDFF8C12697C9CEB18B8DC86798A4B41312D5959A4CFC1160CF63EEA872
+IV=BAF75BD5F987032DD8840B4AD59458F0
+CT=13B524E8AEBFE32CC9559B500D9E9A82
+PT=91775D8DF510277669BC11697965AE99
+
+I=229
+KEY=B3C35FF0F6B2DDCF5522A35E75040BB135C34E9F2085BD3A95AD71A61A8B06EB
+IV=8D11B12F0E73FB589CEC12D5F8CC6C29
+CT=91775D8DF510277669BC11697965AE99
+PT=0AA5B5A593FED4CE1FD66736774649D2
+
+I=230
+KEY=5581EEED032A31D6F8077BEED79ABB1E3F66FB3AB37B69F48A7B16906DCD4F39
+IV=E642B11DF598EC19AD25D8B0A29EB0AF
+CT=0AA5B5A593FED4CE1FD66736774649D2
+PT=3DB595E23D32347092E5D94A8376DB5D
+
+I=231
+KEY=2337ABB014AD70D3E290033BD6FC75D702D36ED88E495D84189ECFDAEEBB9464
+IV=76B6455D178741051A9778D50166CEC9
+CT=3DB595E23D32347092E5D94A8376DB5D
+PT=2AF2DEC9D2D4F0BA81D1FC88E421C034
+
+I=232
+KEY=7C8A43D8CA68E782BBD49C18477683052821B0115C9DAD3E994F33520A9A5450
+IV=5FBDE868DEC5975159449F23918AF6D2
+CT=2AF2DEC9D2D4F0BA81D1FC88E421C034
+PT=8AF90FCCBEDCDF709AEE93FEF45C03EC
+
+I=233
+KEY=37FDC789E91F58F691931C86C4505926A2D8BFDDE241724E03A1A0ACFEC657BC
+IV=4B7784512377BF742A47809E8326DA23
+CT=8AF90FCCBEDCDF709AEE93FEF45C03EC
+PT=8E98DF785A601DF26465D9A0D163D650
+
+I=234
+KEY=57C30D92BD234BE693F15534768970FC2C4060A5B8216FBC67C4790C2FA581EC
+IV=603ECA1B543C1310026249B2B2D929DA
+CT=8E98DF785A601DF26465D9A0D163D650
+PT=21D3EAC95A088A548E5C0E56001BD103
+
+I=235
+KEY=1F9A07E73DB0530F84B6DB88C5EA0AFD0D938A6CE229E5E8E998775A2FBE50EF
+IV=48590A75809318E917478EBCB3637A01
+CT=21D3EAC95A088A548E5C0E56001BD103
+PT=48A8853D9E4E4A6351E5F5734911D569
+
+I=236
+KEY=219E87740C05905A3DAC677C78C5E6D4453B0F517C67AF8BB87D822966AF8586
+IV=3E04809331B5C355B91ABCF4BD2FEC29
+CT=48A8853D9E4E4A6351E5F5734911D569
+PT=C75ECB64A655DC6803FC976A1CAE78A9
+
+I=237
+KEY=D445B2CF4C6B8AF073FCDFF8907C4B278265C435DA3273E3BB8115437A01FD2F
+IV=F5DB35BB406E1AAA4E50B884E8B9ADF3
+CT=C75ECB64A655DC6803FC976A1CAE78A9
+PT=F063E6C6A62D07B1CA90594CB9041DE4
+
+I=238
+KEY=3DECAA3153A9658A2CAA5578AF2C55CD720622F37C1F745271114C0FC305E0CB
+IV=E9A918FE1FC2EF7A5F568A803F501EEA
+CT=F063E6C6A62D07B1CA90594CB9041DE4
+PT=45F375DDBA20D20CB6C5EAB28AA85D06
+
+I=239
+KEY=31766034845DF8A1AEDFC70CE3CD5B1D37F5572EC63FA65EC7D4A6BD49ADBDCD
+IV=0C9ACA05D7F49D2B827592744CE10ED0
+CT=45F375DDBA20D20CB6C5EAB28AA85D06
+PT=5D117AAC285D5A6948390FDAFBDACAD5
+
+I=240
+KEY=BF17727E1D5DCA94C9CCA8E11DFBF22A6AE42D82EE62FC378FEDA967B2777718
+IV=8E61124A9900323567136FEDFE36A937
+CT=5D117AAC285D5A6948390FDAFBDACAD5
+PT=C8B61B172D930641A88E9E13236E11F9
+
+I=241
+KEY=B82DB30F4271245293FC4CB6A0C10D4FA2523695C3F1FA7627633774911966E1
+IV=073AC1715F2CEEC65A30E457BD3AFF65
+CT=C8B61B172D930641A88E9E13236E11F9
+PT=FE05708E08F8568BB55175CEEF9E0433
+
+I=242
+KEY=28AE9BD5E181AC41CF2F9B4710DD160C5C57461BCB09ACFD923242BA7E8762D2
+IV=908328DAA3F088135CD3D7F1B01C1B43
+CT=FE05708E08F8568BB55175CEEF9E0433
+PT=D7DB71EAC2EF31AE105227E34134AD3C
+
+I=243
+KEY=437D385B59B4AB247A5BCFC0C0F8596F8B8C37F109E69D53826065593FB3CFEE
+IV=6BD3A38EB8350765B5745487D0254F63
+CT=D7DB71EAC2EF31AE105227E34134AD3C
+PT=ECD51D08C870983992708FC1FDFA9D15
+
+I=244
+KEY=4EF45D9C1FCA58D42D9E7E2E9C7D0B8F67592AF9C196056A1010EA98C24952FB
+IV=0D8965C7467EF3F057C5B1EE5C8552E0
+CT=ECD51D08C870983992708FC1FDFA9D15
+PT=F436BA32E9D089248AC47E40AA6B4BAC
+
+I=245
+KEY=D3F16D0CF75471A24F273B3E8EF0A3A0936F90CB28468C4E9AD494D868221957
+IV=9D053090E89E297662B94510128DA82F
+CT=F436BA32E9D089248AC47E40AA6B4BAC
+PT=F43E89C3DBD391B5778B30A36A9E42F3
+
+I=246
+KEY=953E7AB7369425A4F396D764F3EA047F67511908F3951DFBED5FA47B02BC5BA4
+IV=46CF17BBC1C05406BCB1EC5A7D1AA7DF
+CT=F43E89C3DBD391B5778B30A36A9E42F3
+PT=B12ABB428A29703B929EFDB0031694D1
+
+I=247
+KEY=C8DDFEFD3C72822B72C78757EE8EF856D67BA24A79BC6DC07FC159CB01AACF75
+IV=5DE3844A0AE6A78F815150331D64FC29
+CT=B12ABB428A29703B929EFDB0031694D1
+PT=79F19D2BD0A025D2D9822A28F5304446
+
+I=248
+KEY=870A25E9511D3F1BCFA941DA41FD00C0AF8A3F61A91C4812A64373E3F49A8B33
+IV=4FD7DB146D6FBD30BD6EC68DAF73F896
+CT=79F19D2BD0A025D2D9822A28F5304446
+PT=C52D5EF8D7A1353F5C1FF7BA33F9ED97
+
+I=249
+KEY=178B86564949AE1A0CE50E61F4D3F8776AA761997EBD7D2DFA5C8459C76366A4
+IV=9081A3BF18549101C34C4FBBB52EF8B7
+CT=C52D5EF8D7A1353F5C1FF7BA33F9ED97
+PT=82FAB7DF4BE409880B8F66210DE8D2E5
+
+I=250
+KEY=C3F845809E635052F94076E1F3026779E85DD646355974A5F1D3E278CA8BB441
+IV=D473C3D6D72AFE48F5A5788007D19F0E
+CT=82FAB7DF4BE409880B8F66210DE8D2E5
+PT=52C05722F125348666DFCF0F2D052530
+
+I=251
+KEY=34AE823E21F4C45784F2E125CF5039FCBA9D8164C47C4023970C2D77E78E9171
+IV=F756C7BEBF9794057DB297C43C525E85
+CT=52C05722F125348666DFCF0F2D052530
+PT=DE7FAAF4A10D4D5404847FA080C1DC1C
+
+I=252
+KEY=9D1EEFC6B62427F5A2CBB2047AB0E41B64E22B9065710D77938852D7674F4D6D
+IV=A9B06DF897D0E3A226395321B5E0DDE7
+CT=DE7FAAF4A10D4D5404847FA080C1DC1C
+PT=49327927599012EE87FF64F45AC9A9AE
+
+I=253
+KEY=2C7B21A79BE0B5B0E4DCC427DE8D91572DD052B73CE11F99147736233D86E4C3
+IV=B165CE612DC4924546177623A43D754C
+CT=49327927599012EE87FF64F45AC9A9AE
+PT=6E11B9F592DD99CD94F8999D9476F4CF
+
+I=254
+KEY=F4A72FB6D161B9E15A41576C5A7CBF3F43C1EB42AE3C8654808FAFBEA9F0100C
+IV=D8DC0E114A810C51BE9D934B84F12E68
+CT=6E11B9F592DD99CD94F8999D9476F4CF
+PT=108AC1FE3E008D1C3058917157003E2C
+
+I=255
+KEY=2E5FE97C58B060C9BACA9E9CC14CFC89534B2ABC903C0B48B0D73ECFFEF02E20
+IV=DAF8C6CA89D1D928E08BC9F09B3043B6
+CT=108AC1FE3E008D1C3058917157003E2C
+PT=B315EF45A3BD77688AD0976EF5DCA26B
+
+I=256
+KEY=9D763A80B96B112E1DAEA50A98C0B6F7E05EC5F933817C203A07A9A10B2C8C4B
+IV=B329D3FCE1DB71E7A7643B96598C4A7E
+CT=B315EF45A3BD77688AD0976EF5DCA26B
+PT=7BF8DABED803049DF8D1F34ED00536F7
+
+I=257
+KEY=DF5F07523E7E305B48AAD9C205AE826C9BA61F47EB8278BDC2D65AEFDB29BABC
+IV=42293DD28715217555047CC89D6E349B
+CT=7BF8DABED803049DF8D1F34ED00536F7
+PT=E55FE84DF3137D16E74DC01A1BFDA4A7
+
+I=258
+KEY=80CF537EC8836ADD0FB72F35B2EF703D7EF9F70A189105AB259B9AF5C0D41E1B
+IV=5F90542CF6FD5A86471DF6F7B741F251
+CT=E55FE84DF3137D16E74DC01A1BFDA4A7
+PT=6019F9DA2DFDCDCB14C2C6CE5B34432D
+
+I=259
+KEY=4469D3622A022CFB7614C9C9EB36E6031EE00ED0356CC86031595C3B9BE05D36
+IV=C4A6801CE281462679A3E6FC59D9963E
+CT=6019F9DA2DFDCDCB14C2C6CE5B34432D
+PT=6D2788861A8F9526D1EC8A6A8AFBA629
+
+I=260
+KEY=DED804546FA6B0BCD8C9FD9119616F9873C786562FE35D46E0B5D651111BFB1F
+IV=9AB1D73645A49C47AEDD3458F257899B
+CT=6D2788861A8F9526D1EC8A6A8AFBA629
+PT=81D5CDEA70E433A2A341FFB13ECCEC54
+
+I=261
+KEY=24FD3D900606EEF8F31156D30EA094ADF2124BBC5F076EE443F429E02FD7174B
+IV=FA2539C469A05E442BD8AB4217C1FB35
+CT=81D5CDEA70E433A2A341FFB13ECCEC54
+PT=F74B4869E92F918A95B508E382A83FA6
+
+I=262
+KEY=C24CA269EAADDFBA060AAF15C2265DE6055903D5B628FF6ED6412103AD7F28ED
+IV=E6B19FF9ECAB3142F51BF9C6CC86C94B
+CT=F74B4869E92F918A95B508E382A83FA6
+PT=EF3293511A17D0E089A8F88E396B4F31
+
+I=263
+KEY=789C94E8D2B6D6FD022ED678F42E796CEA6B9084AC3F2F8E5FE9D98D941467DC
+IV=BAD03681381B09470424796D3608248A
+CT=EF3293511A17D0E089A8F88E396B4F31
+PT=0D70FCE243309D716D8FA672A11EBCB8
+
+I=264
+KEY=B8DFB47D720C26AE22AD6C87785CCB97E71B6C66EF0FB2FF32667FFF350ADB64
+IV=C0432095A0BAF0532083BAFF8C72B2FB
+CT=0D70FCE243309D716D8FA672A11EBCB8
+PT=831365AB30D062F2B1C051A9EA03AEEB
+
+I=265
+KEY=938BCEFF0FD9AEC61CF2B0509A645A19640809CDDFDFD00D83A62E56DF09758F
+IV=2B547A827DD588683E5FDCD7E238918E
+CT=831365AB30D062F2B1C051A9EA03AEEB
+PT=EFE7E9DC254FF4AA70ABF327566A5448
+
+I=266
+KEY=BBF0C86D05BF543EC3B9A9240833187F8BEFE011FA9024A7F30DDD71896321C7
+IV=287B06920A66FAF8DF4B197492574266
+CT=EFE7E9DC254FF4AA70ABF327566A5448
+PT=2D41BEE483BD2BAD16026AD7AA5ABA07
+
+I=267
+KEY=B744A9326EC1D56CBFF51D969D075C7DA6AE5EF5792D0F0AE50FB7A623399BC0
+IV=0CB4615F6B7E81527C4CB4B295344402
+CT=2D41BEE483BD2BAD16026AD7AA5ABA07
+PT=079460C9B745A53999932C5ECFE6A37B
+
+I=268
+KEY=AE49C59DD393E9EC9030AEDAD7FC61FEA13A3E3CCE68AA337C9C9BF8ECDF38BB
+IV=190D6CAFBD523C802FC5B34C4AFB3D83
+CT=079460C9B745A53999932C5ECFE6A37B
+PT=CE7C5851D0437368FEDC7E39270A7430
+
+I=269
+KEY=8176855633B6FB2445BDDC2FD8D299576F46666D1E2BD95B8240E5C1CBD54C8B
+IV=2F3F40CBE02512C8D58D72F50F2EF8A9
+CT=CE7C5851D0437368FEDC7E39270A7430
+PT=A0C3F2D688E4370AD2F08C09B28DBCC1
+
+I=270
+KEY=050E71C47B278C5825DE84513A732D11CF8594BB96CFEE5150B069C87958F04A
+IV=8478F4924891777C6063587EE2A1B446
+CT=A0C3F2D688E4370AD2F08C09B28DBCC1
+PT=BE472E609ABB030B96739A959EDBDD21
+
+I=271
+KEY=502E4BDCF449E96CB16D5B6C097D20CC71C2BADB0C74ED5AC6C3F35DE7832D6B
+IV=55203A188F6E653494B3DF3D330E0DDD
+CT=BE472E609ABB030B96739A959EDBDD21
+PT=FE4227D6AC71519FA0F2078433DF69CA
+
+I=272
+KEY=C3DDDE6B2E80381010569BC093561F628F809D0DA005BCC56631F4D9D45C44A1
+IV=93F395B7DAC9D17CA13BC0AC9A2B3FAE
+CT=FE4227D6AC71519FA0F2078433DF69CA
+PT=3F8439C7648C5C2B5877643C536E14F9
+
+I=273
+KEY=1CC65CB104317D620D729EDEB4C4B512B004A4CAC489E0EE3E4690E587325058
+IV=DF1B82DA2AB145721D24051E2792AA70
+CT=3F8439C7648C5C2B5877643C536E14F9
+PT=E189B969BF38C8A2F38BF3F12267B5B4
+
+I=274
+KEY=D121C8556039F07E231F9E88DE60572B518D1DA37BB1284CCDCD6314A555E5EC
+IV=CDE794E464088D1C2E6D00566AA4E239
+CT=E189B969BF38C8A2F38BF3F12267B5B4
+PT=EF15CCEC56DCD62681FC7564A1095ECD
+
+I=275
+KEY=C87070F4AA767BE043B29FE3AF258C91BE98D14F2D6DFE6A4C311670045CBB21
+IV=1951B8A1CA4F8B9E60AD016B7145DBBA
+CT=EF15CCEC56DCD62681FC7564A1095ECD
+PT=BD38CD579A7124DD0814DB21FC0E7D96
+
+I=276
+KEY=08167C643CA7CAD8729B17EB91918AC103A01C18B71CDAB74425CD51F852C6B7
+IV=C0660C9096D1B138312988083EB40650
+CT=BD38CD579A7124DD0814DB21FC0E7D96
+PT=565F580B61E456544D8D553948AD95FD
+
+I=277
+KEY=55BB77ED49C419EEA418365F2750857355FF4413D6F88CE309A89868B0FF534A
+IV=5DAD0B897563D336D68321B4B6C10FB2
+CT=565F580B61E456544D8D553948AD95FD
+PT=1AA68EAC78C2B5BFF996F0B58C56432F
+
+I=278
+KEY=8FEC3C85819F24EE1DA186AB212A19D44F59CABFAE3A395CF03E68DD3CA91065
+IV=DA574B68C85B3D00B9B9B0F4067A9CA7
+CT=1AA68EAC78C2B5BFF996F0B58C56432F
+PT=65660FBF6C166604D9E717671488D734
+
+I=279
+KEY=D1D19B25C23EA5923D45493905B867D12A3FC500C22C5F5829D97FBA2821C751
+IV=5E3DA7A043A1817C20E4CF9224927E05
+CT=65660FBF6C166604D9E717671488D734
+PT=477CBD97B467AA1AAB738E294092FAA3
+
+I=280
+KEY=E1972BE045093EC4475DCE6351CDEDCB6D437897764BF54282AAF19368B33DF2
+IV=3046B0C587379B567A18875A54758A1A
+CT=477CBD97B467AA1AAB738E294092FAA3
+PT=C0ED90D90AE11390A275BD03BE00E1D5
+
+I=281
+KEY=6F622A270D77AE65084E2070343E8C7FADAEE84E7CAAE6D220DF4C90D6B3DC27
+IV=8EF501C7487E90A14F13EE1365F361B4
+CT=C0ED90D90AE11390A275BD03BE00E1D5
+PT=296FED9B8CF7C532721A2188DDB1A441
+
+I=282
+KEY=FF7209EA94C0401544991FDB57F77F2084C105D5F05D23E052C56D180B027866
+IV=901023CD99B7EE704CD73FAB63C9F35F
+CT=296FED9B8CF7C532721A2188DDB1A441
+PT=4AE1C2EB8D1CEB5804FA992708150590
+
+I=283
+KEY=73C6F94AD63DE39C289AE20179FDDDD7CE20C73E7D41C8B8563FF43F03177DF6
+IV=8CB4F0A042FDA3896C03FDDA2E0AA2F7
+CT=4AE1C2EB8D1CEB5804FA992708150590
+PT=A4EAC8940C12F9CEAC78DFDC99DF68B4
+
+I=284
+KEY=A7369886016682F6075678509FFB86ED6ACA0FAA71533176FA472BE39AC81542
+IV=D4F061CCD75B616A2FCC9A51E6065B3A
+CT=A4EAC8940C12F9CEAC78DFDC99DF68B4
+PT=70B05A9959E7C4E4545BB3AECCD8B33D
+
+I=285
+KEY=F01B9FF32CE9CA699F69ADBBC209BBD21A7A553328B4F592AE1C984D5610A67F
+IV=572D07752D8F489F983FD5EB5DF23D3F
+CT=70B05A9959E7C4E4545BB3AECCD8B33D
+PT=F4978960F1382713A5A7183B9694DE85
+
+I=286
+KEY=FF05A97961A5CA725CD2E1B2A9D58304EEEDDC53D98CD2810BBB8076C08478FA
+IV=0F1E368A4D4C001BC3BB4C096BDC38D6
+CT=F4978960F1382713A5A7183B9694DE85
+PT=EDCC3B8D26928086F1C6727833405424
+
+I=287
+KEY=AA4DB35CCBD936D13D1B7DB64638B99A0321E7DEFF1E5207FA7DF20EF3C42CDE
+IV=55481A25AA7CFCA361C99C04EFED3A9E
+CT=EDCC3B8D26928086F1C6727833405424
+PT=12A36AC1DA72345291CF206FA04F102F
+
+I=288
+KEY=611E32BF030B7B377AEC338C7FA6D88311828D1F256C66556BB2D261538B3CF1
+IV=CB5381E3C8D24DE647F74E3A399E6119
+CT=12A36AC1DA72345291CF206FA04F102F
+PT=8DA0003E090444453B932F0CDBBFA54E
+
+I=289
+KEY=43E230241EF150AC761C1307C43C3E209C228D212C6822105021FD6D883499BF
+IV=22FC029B1DFA2B9B0CF0208BBB9AE6A3
+CT=8DA0003E090444453B932F0CDBBFA54E
+PT=A3D9F2112895CEA937A2B18ABB589CC0
+
+I=290
+KEY=1FE38E9028DAC8A1E65A04C78BD0E7523FFB7F3004FDECB967834CE7336C057F
+IV=5C01BEB4362B980D904617C04FECD972
+CT=A3D9F2112895CEA937A2B18ABB589CC0
+PT=191EE02B9FED198599B5BC2F36271ABB
+
+I=291
+KEY=5FFD20799D7A7E7A328BD57B13F6E52F26E59F1B9B10F53CFE36F0C8054B1FC4
+IV=401EAEE9B5A0B6DBD4D1D1BC9826027D
+CT=191EE02B9FED198599B5BC2F36271ABB
+PT=EFC32006AE746D1E3F65E6C7ADF32804
+
+I=292
+KEY=EFEFD2A0F1917EB5BFD2337260E11023C926BF1D35649822C153160FA8B837C0
+IV=B012F2D96CEB00CF8D59E6097317F50C
+CT=EFC32006AE746D1E3F65E6C7ADF32804
+PT=F9C49B0BFFA354EEBBE3DE29BF9D2623
+
+I=293
+KEY=7676D792019D370A67526977EC5FDB5B30E22416CAC7CCCC7AB0C826172511E3
+IV=99990532F00C49BFD8805A058CBECB78
+CT=F9C49B0BFFA354EEBBE3DE29BF9D2623
+PT=EAEAE4BFF789E64D80D88CE5BC0E15CC
+
+I=294
+KEY=69202B4EB33EB35987DD82026714F603DA08C0A93D4E2A81FA6844C3AB2B042F
+IV=1F56FCDCB2A38453E08FEB758B4B2D58
+CT=EAEAE4BFF789E64D80D88CE5BC0E15CC
+PT=96C362F59FD2457A5ED68A116B4AA682
+
+I=295
+KEY=DE8B4CC7995B3E061E126157B0C2AF984CCBA25CA29C6FFBA4BECED2C061A2AD
+IV=B7AB67892A658D5F99CFE355D7D6599B
+CT=96C362F59FD2457A5ED68A116B4AA682
+PT=5498BE46DCE840F7B593BE2BC0D252CB
+
+I=296
+KEY=1BFE119E1B63BA06E9A590709A2985D218531C1A7E742F0C112D70F900B3F066
+IV=C5755D5982388400F7B7F1272AEB2A4A
+CT=5498BE46DCE840F7B593BE2BC0D252CB
+PT=697482966F491ACB46E7171A4813D916
+
+I=297
+KEY=9E6361F9775A88FAAD09711E9691798C71279E8C113D35C757CA67E348A02970
+IV=859D70676C3932FC44ACE16E0CB8FC5E
+CT=697482966F491ACB46E7171A4813D916
+PT=A799874DC7721D96DEEFAB5FE1A01A8E
+
+I=298
+KEY=7D1EF621D3ADC4BD4EC1861167FA5B0CD6BE19C1D64F28518925CCBCA90033FE
+IV=E37D97D8A4F74C47E3C8F70FF16B2280
+CT=A799874DC7721D96DEEFAB5FE1A01A8E
+PT=2D19344625CF5E6DE07EE960F4AEC5CF
+
+I=299
+KEY=7DFD0BE692B47C022DC789EF5291D2F5FBA72D87F380763C695B25DC5DAEF631
+IV=00E3FDC74119B8BF63060FFE356B89F9
+CT=2D19344625CF5E6DE07EE960F4AEC5CF
+PT=F80C5143F173AE672DA4DDC8272C13EF
+
+I=300
+KEY=A78C66D30475B93F0A87E6E4A8BFA3AE03AB7CC402F3D85B44FFF8147A82E5DE
+IV=DA716D3596C1C53D27406F0BFA2E715B
+CT=F80C5143F173AE672DA4DDC8272C13EF
+PT=76BDB7A63614A41C9D52718B3514E03C
+
+I=301
+KEY=9542E4B9D92DAF7B463C83DA257422B37516CB6234E77C47D9AD899F4F9605E2
+IV=32CE826ADD5816444CBB653E8DCB811D
+CT=76BDB7A63614A41C9D52718B3514E03C
+PT=93F65B7B961EE6B623A026576FF8890B
+
+I=302
+KEY=6932CD66A25D1DE274C7D5DF540917BFE6E09019A2F99AF1FA0DAFC8206E8CE9
+IV=FC7029DF7B70B29932FB5605717D350C
+CT=93F65B7B961EE6B623A026576FF8890B
+PT=FA5BEB508ABCBCB1B1D56C0E207A032D
+
+I=303
+KEY=595CCC3640445FF5BBF303FF7845AB821CBB7B49284526404BD8C3C600148FC4
+IV=306E0150E2194217CF34D6202C4CBC3D
+CT=FA5BEB508ABCBCB1B1D56C0E207A032D
+PT=BFAEA3EB7C617567EB302D571DBF2811
+
+I=304
+KEY=BF5382311BF88FC9E32D5BADC832BE48A315D8A254245327A0E8EE911DABA7D5
+IV=E60F4E075BBCD03C58DE5852B07715CA
+CT=BFAEA3EB7C617567EB302D571DBF2811
+PT=4B0E63933414184D43B0AA714AA31E02
+
+I=305
+KEY=B50A2FF8FAC6820638CCBA3A0CA6519CE81BBB3160304B6AE35844E05708B9D7
+IV=0A59ADC9E13E0DCFDBE1E197C494EFD4
+CT=4B0E63933414184D43B0AA714AA31E02
+PT=0073CA04B300003AF3C1035C664E0646
+
+I=306
+KEY=1A32AA7CA8B5D83C47F56C5D24EDBD38E8687135D3304B50109947BC3146BF91
+IV=AF38858452735A3A7F39D667284BECA4
+CT=0073CA04B300003AF3C1035C664E0646
+PT=75CFE6D4A4F05D8EBB5C614AC7FB48C8
+
+I=307
+KEY=C321C5381F5A334C8B82DD2F0E4C73AE9DA797E177C016DEABC526F6F6BDF759
+IV=D9136F44B7EFEB70CC77B1722AA1CE96
+CT=75CFE6D4A4F05D8EBB5C614AC7FB48C8
+PT=B0D8DB37DF5C3A87B9E5D562283E8FEE
+
+I=308
+KEY=40879EA19753F0F22B1C1BF438A446532D7F4CD6A89C2C591220F394DE8378B7
+IV=83A65B998809C3BEA09EC6DB36E835FD
+CT=B0D8DB37DF5C3A87B9E5D562283E8FEE
+PT=9C885637CC7666C04B424DD6EF1F3EDB
+
+I=309
+KEY=B6824C9F800B1E7825135F250DB99FC8B1F71AE164EA4A995962BE42319C466C
+IV=F605D23E1758EE8A0E0F44D1351DD99B
+CT=9C885637CC7666C04B424DD6EF1F3EDB
+PT=3E7F4437656E63E0ADC6C764B20FE92D
+
+I=310
+KEY=7FA3CDE5856B1F0D9AE33E9E6ED1532E8F885ED601842979F4A479268393AF41
+IV=C921817A05600175BFF061BB6368CCE6
+CT=3E7F4437656E63E0ADC6C764B20FE92D
+PT=B19CCFDAADEC54C8DD5F4FD53D3C5824
+
+I=311
+KEY=3E3ABA34DB005D9FF2CEF1321BCD018E3E14910CAC687DB129FB36F3BEAFF765
+IV=419977D15E6B4292682DCFAC751C52A0
+CT=B19CCFDAADEC54C8DD5F4FD53D3C5824
+PT=84F7D061322A4042913C0BD14F5F1391
+
+I=312
+KEY=FB474D499955CB1F37FBA309DD55E09DBAE3416D9E423DF3B8C73D22F1F0E4F4
+IV=C57DF77D42559680C535523BC698E113
+CT=84F7D061322A4042913C0BD14F5F1391
+PT=CBCD716DA9C53D7AFFFE65B780926660
+
+I=313
+KEY=7C1D07031362A7439F9DD5272DAD1D9B712E3000378700894739589571628294
+IV=875A4A4A8A376C5CA866762EF0F8FD06
+CT=CBCD716DA9C53D7AFFFE65B780926660
+PT=F605D205704496C5BFCEE88130920CDE
+
+I=314
+KEY=7E9E72A6032523643F0965E8BFCB0793872BE20547C3964CF8F7B01441F08E4A
+IV=028375A510478427A094B0CF92661A08
+CT=F605D205704496C5BFCEE88130920CDE
+PT=CFA8B47DEB5770925EA29484D82CDBB4
+
+I=315
+KEY=518CA0A8C81E9DDCE1060410C69F0ACE48835678AC94E6DEA655249099DC55FE
+IV=2F12D20ECB3BBEB8DE0F61F879540D5D
+CT=CFA8B47DEB5770925EA29484D82CDBB4
+PT=1065AD49D2DD48EB9540F23A69469B92
+
+I=316
+KEY=45E6A5A17D8D1AEA04CD8E184D0A1BF758E6FB317E49AE353315D6AAF09ACE6C
+IV=146A0509B5938736E5CB8A088B951139
+CT=1065AD49D2DD48EB9540F23A69469B92
+PT=DB12EE00C65069CFEA509BA5BD5BB6BC
+
+I=317
+KEY=FC8F8F7F8A440A6CEB920D4311851B3A83F41531B819C7FAD9454D0F4DC178D0
+IV=B9692ADEF7C91086EF5F835B5C8F00CD
+CT=DB12EE00C65069CFEA509BA5BD5BB6BC
+PT=B66316FB3CCC9B262A34C205AE43F42B
+
+I=318
+KEY=42D666DF2C1575E3B346FCBCD208AD9F359703CA84D55CDCF3718F0AE3828CFB
+IV=BE59E9A0A6517F8F58D4F1FFC38DB6A5
+CT=B66316FB3CCC9B262A34C205AE43F42B
+PT=4C851D9BDC164194A6D1FDE274C06D1B
+
+I=319
+KEY=786B9456901DFA9FF85C686DEEDCA02079121E5158C31D4855A072E89742E1E0
+IV=3ABDF289BC088F7C4B1A94D13CD40DBF
+CT=4C851D9BDC164194A6D1FDE274C06D1B
+PT=5507F1EB271BDBC0A6DD8BBAEC843A05
+
+I=320
+KEY=C79B5CD424E592D392FECD3233CEA70B2C15EFBA7FD8C688F37DF9527BC6DBE5
+IV=BFF0C882B4F8684C6AA2A55FDD12072B
+CT=5507F1EB271BDBC0A6DD8BBAEC843A05
+PT=BB10EF7C98DE0255C836D5319B94B166
+
+I=321
+KEY=10ABC5B835E6E6BD02E90B63D22EF9E7970500C6E706C4DD3B4B2C63E0526A83
+IV=D730996C1103746E9017C651E1E05EEC
+CT=BB10EF7C98DE0255C836D5319B94B166
+PT=E8B797AFDC378DB47F172260963A6E2C
+
+I=322
+KEY=75E05AAAB4E6981A20E4177D214B81EA7FB297693B314969445C0E03766804AF
+IV=654B9F1281007EA7220D1C1EF365780D
+CT=E8B797AFDC378DB47F172260963A6E2C
+PT=58ED1CC5A208A0E7340167E79F5DA7C2
+
+I=323
+KEY=A69FECC296D12216128BD1D2C48B373D275F8BAC9939E98E705D69E4E935A36D
+IV=D37FB6682237BA0C326FC6AFE5C0B6D7
+CT=58ED1CC5A208A0E7340167E79F5DA7C2
+PT=FEDA5FB215819B441BE18B0AED27A1FD
+
+I=324
+KEY=7EED1776E603DD6C20F08B4C6B121525D985D41E8CB872CA6BBCE2EE04120290
+IV=D872FBB470D2FF7A327B5A9EAF992218
+CT=FEDA5FB215819B441BE18B0AED27A1FD
+PT=7CD64E29A704F13688DB206F7F337685
+
+I=325
+KEY=D4479A0AF29AF7145EC3FB89FEF8BBA7A5539A372BBC83FCE367C2817B217415
+IV=AAAA8D7C14992A787E3370C595EAAE82
+CT=7CD64E29A704F13688DB206F7F337685
+PT=25D6728244F28F79D1BC707BE94ECA13
+
+I=326
+KEY=7FB45D09003B25EFEB5F68CCB7E09C008085E8B56F4E0C8532DBB2FA926FBE06
+IV=ABF3C703F2A1D2FBB59C9345491827A7
+CT=25D6728244F28F79D1BC707BE94ECA13
+PT=47AF03717893A10D7F40D5A3D9B82534
+
+I=327
+KEY=35EE9428D4EC49EC103EDF32F4FBEE16C72AEBC417DDAD884D9B67594BD79B32
+IV=4A5AC921D4D76C03FB61B7FE431B7216
+CT=47AF03717893A10D7F40D5A3D9B82534
+PT=B6C25C0E4CA560707588321AAF41119C
+
+I=328
+KEY=B12C0149A6EDD2DC3742D10822FEDDF771E8B7CA5B78CDF838135543E4968AAE
+IV=84C2956172019B30277C0E3AD60533E1
+CT=B6C25C0E4CA560707588321AAF41119C
+PT=09137DF5460434E863647B4B50E17A60
+
+I=329
+KEY=CFEC596CE216B14A955E7CBC095C198678FBCA3F1D7CF9105B772E08B477F0CE
+IV=7EC0582544FB6396A21CADB42BA2C471
+CT=09137DF5460434E863647B4B50E17A60
+PT=17A26688B271E9765F41C71CD8CF0C25
+
+I=330
+KEY=35903FF91CC199C048C6C031AA2F4FC96F59ACB7AF0D10660436E9146CB8FCEB
+IV=FA7C6695FED7288ADD98BC8DA373564F
+CT=17A26688B271E9765F41C71CD8CF0C25
+PT=62E3C4D53DECB83FCD5F57D1971D58FB
+
+I=331
+KEY=F262476804B79C1F85FEB875CCD5FC3E0DBA686292E1A859C969BEC5FBA5A410
+IV=C7F27891187605DFCD38784466FAB3F7
+CT=62E3C4D53DECB83FCD5F57D1971D58FB
+PT=3495C5855D819B6FF779FC7AC59BEB53
+
+I=332
+KEY=DC61E5CFC9BAE6B23B894486AD478ADD392FADE7CF6033363E1042BF3E3E4F43
+IV=2E03A2A7CD0D7AADBE77FCF3619276E3
+CT=3495C5855D819B6FF779FC7AC59BEB53
+PT=7440ABE9E1374208CFBCCC18ADC6089F
+
+I=333
+KEY=C9D2E747A1A6D594CCAE434B7605C8FB4D6F060E2E57713EF1AC8EA793F847DC
+IV=15B30288681C3326F72707CDDB424226
+CT=7440ABE9E1374208CFBCCC18ADC6089F
+PT=B6802F0F62A28AF7326CDB2144E8DE87
+
+I=334
+KEY=99FEF610CFFFACBE8C6AD0A2B0C8F8A7FBEF29014CF5FBC9C3C05586D710995B
+IV=502C11576E59792A40C493E9C6CD305C
+CT=B6802F0F62A28AF7326CDB2144E8DE87
+PT=B84D7D91E60C131F6F042D403D85C47B
+
+I=335
+KEY=91EB2713A930B6A53993029D5A056B4143A25490AAF9E8D6ACC478C6EA955D20
+IV=0815D10366CF1A1BB5F9D23FEACD93E6
+CT=B84D7D91E60C131F6F042D403D85C47B
+PT=4DDF64827A16F90B5E6B306E8F227DB7
+
+I=336
+KEY=C15019D3523304CC9231B33C53C7FE1E0E7D3012D0EF11DDF2AF48A865B72097
+IV=50BB3EC0FB03B269ABA2B1A109C2955F
+CT=4DDF64827A16F90B5E6B306E8F227DB7
+PT=FDF6E5B6486E11839EB3A7F5C3898F54
+
+I=337
+KEY=E24B749901384F48B2E740C51175E311F38BD5A49881005E6C1CEF5DA63EAFC3
+IV=231B6D4A530B4B8420D6F3F942B21D0F
+CT=FDF6E5B6486E11839EB3A7F5C3898F54
+PT=841EF37B4AF82CC5EB00E11775079D81
+
+I=338
+KEY=44B7FFFA042DCA1BF276D4911D4B0BE2779526DFD2792C9B871C0E4AD3393242
+IV=A6FC8B6305158553409194540C3EE8F3
+CT=841EF37B4AF82CC5EB00E11775079D81
+PT=1725AF7F70B65FBB060D29B3BCDF0A31
+
+I=339
+KEY=B724B2CD569E436B20594E10576934BF60B089A0A2CF7320811127F96FE63873
+IV=F3934D3752B38970D22F9A814A223F5D
+CT=1725AF7F70B65FBB060D29B3BCDF0A31
+PT=2CCC6D09954E5FE6C6A87E18950EED02
+
+I=340
+KEY=E9EB02E31CABD14DFF231F1F649294044C7CE4A937812CC647B959E1FAE8D571
+IV=5ECFB02E4A359226DF7A510F33FBA0BB
+CT=2CCC6D09954E5FE6C6A87E18950EED02
+PT=C82C82AF68EACE2AF22C3266F898F573
+
+I=341
+KEY=90C8F71B05BE122AFE5D58A7A1AAB666845066065F6BE2ECB5956B8702702002
+IV=7923F5F81915C367017E47B8C5382262
+CT=C82C82AF68EACE2AF22C3266F898F573
+PT=377F6966928959F2D68F3A2BD0EA3735
+
+I=342
+KEY=1BE70B607CF9A9E35DF916C4CC103FEBB32F0F60CDE2BB1E631A51ACD29A1737
+IV=8B2FFC7B7947BBC9A3A44E636DBA898D
+CT=377F6966928959F2D68F3A2BD0EA3735
+PT=3A8CCF4943B9866A9ABBEC0BA46F25DB
+
+I=343
+KEY=631B2C30FEA26433F0CBCD01B1CE974089A3C0298E5B3D74F9A1BDA776F532EC
+IV=78FC2750825BCDD0AD32DBC57DDEA8AB
+CT=3A8CCF4943B9866A9ABBEC0BA46F25DB
+PT=3B767EAB7F0C2D24BBE5565E93DC3E24
+
+I=344
+KEY=8785E70A8CD45A8FE1E4382DC62D563DB2D5BE82F15710504244EBF9E5290CC8
+IV=E49ECB3A72763EBC112FF52C77E3C17D
+CT=3B767EAB7F0C2D24BBE5565E93DC3E24
+PT=619610C6A4A8E9B196E65D2E5D463968
+
+I=345
+KEY=B49BAD1E8EB8B9CF7F32048A81E5BCD3D343AE4455FFF9E1D4A2B6D7B86F35A0
+IV=331E4A14026CE3409ED63CA747C8EAEE
+CT=619610C6A4A8E9B196E65D2E5D463968
+PT=F12AF66580B33C3113C45CF5EFD52F4F
+
+I=346
+KEY=3C92453C6342B6CDC18BFE05241EB5D922695821D54CC5D0C766EA2257BA1AEF
+IV=8809E822EDFA0F02BEB9FA8FA5FB090A
+CT=F12AF66580B33C3113C45CF5EFD52F4F
+PT=A427E0B2CD34285167999A9F18295D26
+
+I=347
+KEY=24A1F21CA68CF23F1674BF5328219987864EB8931878ED81A0FF70BD4F9347C9
+IV=1833B720C5CE44F2D7FF41560C3F2C5E
+CT=A427E0B2CD34285167999A9F18295D26
+PT=85F5855ACB2741070E1C89F904CBDBEA
+
+I=348
+KEY=B5479F4D4A0DBBFFBF86C576009F241403BB3DC9D35FAC86AEE3F9444B589C23
+IV=91E66D51EC8149C0A9F27A2528BEBD93
+CT=85F5855ACB2741070E1C89F904CBDBEA
+PT=295D7A02348A185F5C54113C734E9003
+
+I=349
+KEY=AA9CE82B0B649063C874699C71E8A94E2AE647CBE7D5B4D9F2B7E87838160C20
+IV=1FDB776641692B9C77F2ACEA71778D5A
+CT=295D7A02348A185F5C54113C734E9003
+PT=E466F369B840296AAB1A24ED32A19F51
+
+I=350
+KEY=A2BA72E2906E04C42C0047EF222FFFE6CE80B4A25F959DB359ADCC950AB79371
+IV=08269AC99B0A94A7E4742E7353C756A8
+CT=E466F369B840296AAB1A24ED32A19F51
+PT=099CEB8099DD025E4A57015168F75388
+
+I=351
+KEY=EA9B425CCD937976EB04693F16C4DAC4C71C5F22C6489FED13FACDC46240C0F9
+IV=482130BE5DFD7DB2C7042ED034EB2522
+CT=099CEB8099DD025E4A57015168F75388
+PT=E40CD2C0A7E7CB35C64AEB396338A801
+
+I=352
+KEY=D31BCE56BA19A7CB6057C5F2CCB3786223108DE261AF54D8D5B026FD017868F8
+IV=39808C0A778ADEBD8B53ACCDDA77A2A6
+CT=E40CD2C0A7E7CB35C64AEB396338A801
+PT=12E94732A52D15C624A8E554AB54C9A4
+
+I=353
+KEY=F0CD039C509E0EFF71B18AE3FEEB186D31F9CAD0C482411EF118C3A9AA2CA15C
+IV=23D6CDCAEA87A93411E64F113258600F
+CT=12E94732A52D15C624A8E554AB54C9A4
+PT=241C32C2C0C5C6CBE4BB354C054C68D7
+
+I=354
+KEY=0579BEABF73DD177C1F1F0827DA20BA115E5F812044787D515A3F6E5AF60C98B
+IV=F5B4BD37A7A3DF88B0407A61834913CC
+CT=241C32C2C0C5C6CBE4BB354C054C68D7
+PT=E4EA5643CF19EF64820A1B591DE1C378
+
+I=355
+KEY=99C7C61F7153FFA0F07380D052431667F10FAE51CB5E68B197A9EDBCB2810AF3
+IV=9CBE78B4866E2ED7318270522FE11DC6
+CT=E4EA5643CF19EF64820A1B591DE1C378
+PT=BC86D5465171B667CE837F874D933FF4
+
+I=356
+KEY=C2A65A0A2E71F6E7E2BD9FBB5049F7914D897B179A2FDED6592A923BFF123507
+IV=5B619C155F22094712CE1F6B020AE1F6
+CT=BC86D5465171B667CE837F874D933FF4
+PT=EEB9DC4EBD27720AD3527A1323D85413
+
+I=357
+KEY=B635E7EFD987991CD29414B3EBAB2EA4A330A7592708ACDC8A78E828DCCA6114
+IV=7493BDE5F7F66FFB30298B08BBE2D935
+CT=EEB9DC4EBD27720AD3527A1323D85413
+PT=78591E006B877AC6880834E3F98FD6B0
+
+I=358
+KEY=F5849125E52B6DF3CD8144DDB64178DDDB69B9594C8FD61A0270DCCB2545B7A4
+IV=43B176CA3CACF4EF1F15506E5DEA5679
+CT=78591E006B877AC6880834E3F98FD6B0
+PT=8F9A67CF96F4608D56923CB267855F3F
+
+I=359
+KEY=41885734A072249ADE0091A0AD87F47854F3DE96DA7BB69754E2E07942C0E89B
+IV=B40CC611455949691381D57D1BC68CA5
+CT=8F9A67CF96F4608D56923CB267855F3F
+PT=1B0B8D9118CBECBA2D5AD17A261F9D56
+
+I=360
+KEY=FF1A5B86E3545D9CB01A1222EC99A81C4FF85307C2B05A2D79B8310364DF75CD
+IV=BE920CB2432679066E1A8382411E5C64
+CT=1B0B8D9118CBECBA2D5AD17A261F9D56
+PT=6225E63F0C1A5DE00FD63032908A51F3
+
+I=361
+KEY=836FB4DC9C17E5AD70404B41CC4A043E2DDDB538CEAA07CD766E0131F455243E
+IV=7C75EF5A7F43B831C05A596320D3AC22
+CT=6225E63F0C1A5DE00FD63032908A51F3
+PT=7C66E540C016FB81A345E10331FCAFF3
+
+I=362
+KEY=63CA7D0E2675E43626B5311A7BA7131B51BB50780EBCFC4CD52BE032C5A98BCD
+IV=E0A5C9D2BA62019B56F57A5BB7ED1725
+CT=7C66E540C016FB81A345E10331FCAFF3
+PT=2F010053D3C59BB8ACB5B13B197A4204
+
+I=363
+KEY=6B5C4A2DD70FFF3023B2A775BECF05607EBA502BDD7967F4799E5109DCD3C9C9
+IV=08963723F17A1B060507966FC568167B
+CT=2F010053D3C59BB8ACB5B13B197A4204
+PT=8918E06B8619B43E859171A345E246AE
+
+I=364
+KEY=575661F811B8D8B50980A55848A48949F7A2B0405B60D3CAFC0F20AA99318F67
+IV=3C0A2BD5C6B727852A32022DF66B8C29
+CT=8918E06B8619B43E859171A345E246AE
+PT=60FF920A8495AD880459737525C109D6
+
+I=365
+KEY=5FACBE49DE8F64786918067E7E361681975D224ADFF57E42F85653DFBCF086B1
+IV=08FADFB1CF37BCCD6098A32636929FC8
+CT=60FF920A8495AD880459737525C109D6
+PT=03F09A2C18DB8BAE5CCC93B9165A1D16
+
+I=366
+KEY=9BFDA5803AC1C3004F0B138885DE59FE94ADB866C72EF5ECA49AC066AAAA9BA7
+IV=C4511BC9E44EA778261315F6FBE84F7F
+CT=03F09A2C18DB8BAE5CCC93B9165A1D16
+PT=52CB3AF36047F4D14C2EAEE3C3F8AF2A
+
+I=367
+KEY=614239035D7EF489DE2F88FDB6188EC3C6668295A769013DE8B46E856952348D
+IV=FABF9C8367BF378991249B7533C6D73D
+CT=52CB3AF36047F4D14C2EAEE3C3F8AF2A
+PT=249794B3822BB06708B5D5777D297C40
+
+I=368
+KEY=20BEFE90BA9C7EE9CFB1E569FE354258E2F116262542B15AE001BBF2147B48CD
+IV=41FCC793E7E28A60119E6D94482DCC9B
+CT=249794B3822BB06708B5D5777D297C40
+PT=1836AE59EAE452DAC108618DECD666BD
+
+I=369
+KEY=E11E8BF6DE253E4FBADEDFD44B34BE15FAC7B87FCFA6E3802109DA7FF8AD2E70
+IV=C1A0756664B940A6756F3ABDB501FC4D
+CT=1836AE59EAE452DAC108618DECD666BD
+PT=20EE84DEB0E7B0C83D74CE251AA1615C
+
+I=370
+KEY=D519038D457B4BCD9DD50C8F64FE2F2ADA293CA17F4153481C7D145AE20C4F2C
+IV=3407887B9B5E7582270BD35B2FCA913F
+CT=20EE84DEB0E7B0C83D74CE251AA1615C
+PT=6FA7D3584A2E4B803AC1AC07B09931A2
+
+I=371
+KEY=82F1611CFB9E7AF9F9274C6BF1B96BEBB58EEFF9356F18C826BCB85D52957E8E
+IV=57E86291BEE5313464F240E4954744C1
+CT=6FA7D3584A2E4B803AC1AC07B09931A2
+PT=A7B8F8AC07BAB843F4E7942A6E4A85D5
+
+I=372
+KEY=DFF5A6DE8ADE9AB78CF1E637F44FD3351236175532D5A08BD25B2C773CDFFB5B
+IV=5D04C7C27140E04E75D6AA5C05F6B8DE
+CT=A7B8F8AC07BAB843F4E7942A6E4A85D5
+PT=7F3C3702404E6E013474A0AA0EF85527
+
+I=373
+KEY=9C6A11136F64F462E7C5CB30049CDA056D0A2057729BCE8AE62F8CDD3227AE7C
+IV=439FB7CDE5BA6ED56B342D07F0D30930
+CT=7F3C3702404E6E013474A0AA0EF85527
+PT=7C0C44DC96872DEE0BAC71DDBDCC84E3
+
+I=374
+KEY=2C95624ADD9B1E09F13AE579333B22BB1106648BE41CE364ED83FD008FEB2A9F
+IV=B0FF7359B2FFEA6B16FF2E4937A7F8BE
+CT=7C0C44DC96872DEE0BAC71DDBDCC84E3
+PT=B9E4597C562E9B5C0E6815E64F767CE9
+
+I=375
+KEY=CBB3F14A21E49825990B89E7D07BC386A8E23DF7B2327838E3EBE8E6C09D5676
+IV=E7269300FC7F862C68316C9EE340E13D
+CT=B9E4597C562E9B5C0E6815E64F767CE9
+PT=4B37A1FD978F50BE9EA482CFBEACFA08
+
+I=376
+KEY=65B742FFD29D9B07F3956625AED7382EE3D59C0A25BD28867D4F6A297E31AC7E
+IV=AE04B3B5F37903226A9EEFC27EACFBA8
+CT=4B37A1FD978F50BE9EA482CFBEACFA08
+PT=D3406B71FFC847C364199666A808C43A
+
+I=377
+KEY=6C6A4DE74AF6C443B4F6A1C7DAB4A28E3095F77BDA756F451956FC4FD6396844
+IV=09DD0F18986B5F444763C7E274639AA0
+CT=D3406B71FFC847C364199666A808C43A
+PT=94744ECE39108CB8084DF8A17C49CDCC
+
+I=378
+KEY=AD09E82AFAA9F5168CD9B83F44C096A0A4E1B9B5E365E3FD111B04EEAA70A588
+IV=C163A5CDB05F3155382F19F89E74342E
+CT=94744ECE39108CB8084DF8A17C49CDCC
+PT=45EF43A20D7F174DA1463DDA678BBFFB
+
+I=379
+KEY=DC29CBF4E8B92311A9AA788C437A8EDDE10EFA17EE1AF4B0B05D3934CDFB1A73
+IV=712023DE1210D6072573C0B307BA187D
+CT=45EF43A20D7F174DA1463DDA678BBFFB
+PT=4480FB073AA197507E376C56B824C753
+
+I=380
+KEY=93308B36D3A2E1A952B96FE4687B2DF9A58E0110D4BB63E0CE6A556275DFDD20
+IV=4F1940C23B1BC2B8FB1317682B01A324
+CT=4480FB073AA197507E376C56B824C753
+PT=C8BBB77D206EF37C7C40DB175D105271
+
+I=381
+KEY=9682C995955D18471758C504201E93AC6D35B66DF4D5909CB22A8E7528CF8F51
+IV=05B242A346FFF9EE45E1AAE04865BE55
+CT=C8BBB77D206EF37C7C40DB175D105271
+PT=50C0B9001C716D53470FC9B011191402
+
+I=382
+KEY=60854B33BE79B0E631B1AF9046C46D153DF50F6DE8A4FDCFF52547C539D69B53
+IV=F60782A62B24A8A126E96A9466DAFEB9
+CT=50C0B9001C716D53470FC9B011191402
+PT=8DB5367A34C5E5B93486AB07CA8BB02E
+
+I=383
+KEY=7EE74E63D01F31D44B3860471B0BE50FB0403917DC611876C1A3ECC2F35D2B7D
+IV=1E6205506E6681327A89CFD75DCF881A
+CT=8DB5367A34C5E5B93486AB07CA8BB02E
+PT=4F9B922C88C1750829D9088F16EDB529
+
+I=384
+KEY=A65EE6CE576182F487D2C21C4F8539F3FFDBAB3B54A06D7EE87AE44DE5B09E54
+IV=D8B9A8AD877EB320CCEAA25B548EDCFC
+CT=4F9B922C88C1750829D9088F16EDB529
+PT=05A705F6B55D3ACF3E95E8264FEFFDCC
+
+I=385
+KEY=64F9A7DF5DA898C968746F96692F1892FA7CAECDE1FD57B1D6EF0C6BAA5F6398
+IV=C2A741110AC91A3DEFA6AD8A26AA2161
+CT=05A705F6B55D3ACF3E95E8264FEFFDCC
+PT=D1FB7C1A698990AC81068D08BE1CE91F
+
+I=386
+KEY=019663655974433AD5731BC4388A067D2B87D2D78874C71D57E9816314438A87
+IV=656FC4BA04DCDBF3BD07745251A51EEF
+CT=D1FB7C1A698990AC81068D08BE1CE91F
+PT=A1CD24AAFCEE3A60A025B983D10D8E54
+
+I=387
+KEY=16EF87A84F0627345CED6385A62374778A4AF67D749AFD7DF7CC38E0C54E04D3
+IV=1779E4CD1672640E899E78419EA9720A
+CT=A1CD24AAFCEE3A60A025B983D10D8E54
+PT=B9064D063D2C8D8D935B53CBEF3224E2
+
+I=388
+KEY=80931C61E23BA976FFC9288F74AD876D334CBB7B49B670F064976B2B2A7C2031
+IV=967C9BC9AD3D8E42A3244B0AD28EF31A
+CT=B9064D063D2C8D8D935B53CBEF3224E2
+PT=8AD3B2222D84A4B25DC1311378027207
+
+I=389
+KEY=227ACE0315678DEE433049D8CDFEE2D8B99F09596432D44239565A38527E5236
+IV=A2E9D262F75C2498BCF96157B95365B5
+CT=8AD3B2222D84A4B25DC1311378027207
+PT=3A7FC9D43F1F997FAF4931101C5B5FD4
+
+I=390
+KEY=11799A22D50C53A89EDF396B7C7565AD83E0C08D5B2D4D3D961F6B284E250DE2
+IV=33035421C06BDE46DDEF70B3B18B8775
+CT=3A7FC9D43F1F997FAF4931101C5B5FD4
+PT=930860056FE2FDDC10059D09385C0415
+
+I=391
+KEY=58DE85D9975D5F8A16C47C834568EF1D10E8A08834CFB0E1861AF621767909F7
+IV=49A71FFB42510C22881B45E8391D8AB0
+CT=930860056FE2FDDC10059D09385C0415
+PT=F41CCB823840FF7D16C6990A14E591D9
+
+I=392
+KEY=3C8567CD05AF33761FE05FBDC2596EBFE4F46B0A0C8F4F9C90DC6F2B629C982E
+IV=645BE21492F26CFC0924233E873181A2
+CT=F41CCB823840FF7D16C6990A14E591D9
+PT=82899B698456363C175791B845D5736F
+
+I=393
+KEY=F50F05CBDDFEBE7A656EE5C08CC24FF5667DF06388D979A0878BFE932749EB41
+IV=C98A6206D8518D0C7A8EBA7D4E9B214A
+CT=82899B698456363C175791B845D5736F
+PT=CF85BFDA1DFF5ADFFAF1B3E000B407F3
+
+I=394
+KEY=B44AA91A374D1C5A7BD00557CBD24962A9F84FB99526237F7D7A4D7327FDECB2
+IV=4145ACD1EAB3A2201EBEE09747100697
+CT=CF85BFDA1DFF5ADFFAF1B3E000B407F3
+PT=34EEA75CC20C6EDEE9A5379C3B5CF01A
+
+I=395
+KEY=4C401127C0AFABBEA4C93FD80BA009CC9D16E8E5572A4DA194DF7AEF1CA11CA8
+IV=F80AB83DF7E2B7E4DF193A8FC07240AE
+CT=34EEA75CC20C6EDEE9A5379C3B5CF01A
+PT=27C6392ABE790B448CC9216B3FCF5454
+
+I=396
+KEY=44D59CB8EBCC91362462D1D8FE193270BAD0D1CFE95346E518165B84236E48FC
+IV=08958D9F2B633A8880ABEE00F5B93BBC
+CT=27C6392ABE790B448CC9216B3FCF5454
+PT=2C39AC10C7D51B61D8F437D9BAA24A55
+
+I=397
+KEY=E42795DA2BF8FA7A3B0E83923A5E243196E97DDF2E865D84C0E26C5D99CC02A9
+IV=A0F20962C0346B4C1F6C524AC4471641
+CT=2C39AC10C7D51B61D8F437D9BAA24A55
+PT=F828BC735827C106E61F8FFFE9453A77
+
+I=398
+KEY=7F05DC0CD80178018D3A90E4A0CE63156EC1C1AC76A19C8226FDE3A2708938DE
+IV=9B2249D6F3F9827BB63413769A904724
+CT=F828BC735827C106E61F8FFFE9453A77
+PT=DF8129A79852FEE2A8015A2379A7215B
+
+I=399
+KEY=935560C6072D897477D71AC4C12188D0B140E80BEEF362608EFCB981092E1985
+IV=EC50BCCADF2CF175FAED8A2061EFEBC5
+CT=DF8129A79852FEE2A8015A2379A7215B
+PT=CD6429CF3F81F8B4F82BC627A8283096
+
+===========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/cbc_e_m.txt b/krb5-1-6/src/lib/crypto/aes/test/cbc_e_m.txt
new file mode 100644
index 000000000..cd344785f
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/cbc_e_m.txt
@@ -0,0 +1,7224 @@
+
+=========================
+
+FILENAME:  "cbc_e_m.txt"
+
+Cipher Block Chaining (CBC) Mode - ENCRYPTION
+Monte Carlo Test
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+==========
+
+KEYSIZE=128
+
+I=0
+KEY=00000000000000000000000000000000
+IV=00000000000000000000000000000000
+PT=00000000000000000000000000000000
+CT=8A05FC5E095AF4848A08D328D3688E3D
+
+I=1
+KEY=8A05FC5E095AF4848A08D328D3688E3D
+IV=8A05FC5E095AF4848A08D328D3688E3D
+PT=204F17E2444381F6114FF53934C0BCD3
+CT=192D9B3AA10BB2F7846CCBA0085C657A
+
+I=2
+KEY=93286764A85146730E641888DB34EB47
+IV=192D9B3AA10BB2F7846CCBA0085C657A
+PT=983BF6F5A6DFBCDAA19370666E83A99A
+CT=40D8DAF6D1FDA0A073B3BD18B7695D2E
+
+I=3
+KEY=D3F0BD9279ACE6D37DD7A5906C5DB669
+IV=40D8DAF6D1FDA0A073B3BD18B7695D2E
+PT=C48CD503A21C8AD0B2483EF15F79571D
+CT=3EDBE80D69A1D2248CA55FC17C4EF3C5
+
+I=4
+KEY=ED2B559F100D34F7F172FA51101345AC
+IV=3EDBE80D69A1D2248CA55FC17C4EF3C5
+PT=6A49A07B90CE830C20BC239646D936C0
+CT=D87891CF573C99EAE4349A70CA099415
+
+I=5
+KEY=3553C4504731AD1D15466021DA1AD1B9
+IV=D87891CF573C99EAE4349A70CA099415
+PT=0ACB9A969946F523317BB932CE1561A4
+CT=24E8F1013F479BBE655DF088C9316BC7
+
+I=6
+KEY=11BB3551787636A3701B90A9132BBA7E
+IV=24E8F1013F479BBE655DF088C9316BC7
+PT=3DFC8683C1D626A26E2513EB747E8B0F
+CT=2C92E80D8D1F70B411C28BD9FDABF21D
+
+I=7
+KEY=3D29DD5CF569461761D91B70EE804863
+IV=2C92E80D8D1F70B411C28BD9FDABF21D
+PT=FAE2D6A36DBD17199F257643C89EB608
+CT=A61810A2798A70A9D2B37E88DEF9AE0F
+
+I=8
+KEY=9B31CDFE8CE336BEB36A65F83079E66C
+IV=A61810A2798A70A9D2B37E88DEF9AE0F
+PT=CB97F090318A6B10F5044EB8333ECDD6
+CT=0034FA480DE6F65D98D30B026118718F
+
+I=9
+KEY=9B0537B68105C0E32BB96EFA516197E3
+IV=0034FA480DE6F65D98D30B026118718F
+PT=1B8030AC682BA677A7A3ACDC7FB33BB6
+CT=BEA24548CBC4A6630C9F1251F2C3DC51
+
+I=10
+KEY=25A772FE4AC1668027267CABA3A24BB2
+IV=BEA24548CBC4A6630C9F1251F2C3DC51
+PT=D0524282C9AC395508CB2991822E8F42
+CT=4F278DD0B06CBFBAA928635E7CA81B68
+
+I=11
+KEY=6A80FF2EFAADD93A8E0E1FF5DF0A50DA
+IV=4F278DD0B06CBFBAA928635E7CA81B68
+PT=49EA900E2F61DF8CDEA7D479F59C4C30
+CT=EDFF930BB183F8DAC2FC0BD01AD65882
+
+I=12
+KEY=877F6C254B2E21E04CF21425C5DC0858
+IV=EDFF930BB183F8DAC2FC0BD01AD65882
+PT=A1BBEB4E44EF725497B8C589192CC900
+CT=A6FE530E9509D48BAF30F601D04DB19D
+
+I=13
+KEY=21813F2BDE27F56BE3C2E2241591B9C5
+IV=A6FE530E9509D48BAF30F601D04DB19D
+PT=4AD71402771A83F41F7E3AC004150CB7
+CT=FF1148A2E07401F7291B418D62618B65
+
+I=14
+KEY=DE9077893E53F49CCAD9A3A977F032A0
+IV=FF1148A2E07401F7291B418D62618B65
+PT=AC47A1FD3490D6E809D40D4BEB8FF639
+CT=4420D4686F7A4D77A72810E89A5E0DF1
+
+I=15
+KEY=9AB0A3E15129B9EB6DF1B341EDAE3F51
+IV=4420D4686F7A4D77A72810E89A5E0DF1
+PT=F22E1865DD87A88238173FC693C382E7
+CT=A4C7DE5DF9E2B6A20A1E22F8D7496ACD
+
+I=16
+KEY=3E777DBCA8CB0F4967EF91B93AE7559C
+IV=A4C7DE5DF9E2B6A20A1E22F8D7496ACD
+PT=929EFB34B1C552221B648A3D2C678EC9
+CT=D93DBCCA25FA4D9D8C37B3F107FCFA3C
+
+I=17
+KEY=E74AC1768D3142D4EBD822483D1BAFA0
+IV=D93DBCCA25FA4D9D8C37B3F107FCFA3C
+PT=771C61ABB1E9BAB6F678336C8193307E
+CT=75F491C2EA85184ACA3C96B769FA9698
+
+I=18
+KEY=92BE50B467B45A9E21E4B4FF54E13938
+IV=75F491C2EA85184ACA3C96B769FA9698
+PT=55E42F98CCED821FE211D29674E77F48
+CT=A9C7536B77265ECBF7AC5ECD1EF5DDE2
+
+I=19
+KEY=3B7903DF10920455D648EA324A14E4DA
+IV=A9C7536B77265ECBF7AC5ECD1EF5DDE2
+PT=56BC0FA54F6F1E04A9A8893D3964EA68
+CT=3C749BF7EFA55CE924D1B33291C2B586
+
+I=20
+KEY=070D9828FF3758BCF2995900DBD6515C
+IV=3C749BF7EFA55CE924D1B33291C2B586
+PT=45D9BBBB1F3BB33EE182F09C90B1661C
+CT=C4708DBAEBD202CDD2054DDCB1AF7BAB
+
+I=21
+KEY=C37D159214E55A71209C14DC6A792AF7
+IV=C4708DBAEBD202CDD2054DDCB1AF7BAB
+PT=37765B154264AD781BBE5F5717DE7038
+CT=87457FD2EE747645576A27F46B00EC30
+
+I=22
+KEY=44386A40FA912C3477F633280179C6C7
+IV=87457FD2EE747645576A27F46B00EC30
+PT=A7150BBC7BE3837E145AB83E554B49DE
+CT=E25743DAD8E627803DA6C5E587C82384
+
+I=23
+KEY=A66F299A22770BB44A50F6CD86B1E543
+IV=E25743DAD8E627803DA6C5E587C82384
+PT=173343A8488146FC9E4B59C2DF42BAF3
+CT=0D0A78CD5E3EB40F92FB55351122E92B
+
+I=24
+KEY=AB6551577C49BFBBD8ABA3F897930C68
+IV=0D0A78CD5E3EB40F92FB55351122E92B
+PT=3B68CFE78B5DEA8F5165A2034D8C2823
+CT=1921B523A2F9B5F53C740D451C9FCE0C
+
+I=25
+KEY=B244E474DEB00A4EE4DFAEBD8B0CC264
+IV=1921B523A2F9B5F53C740D451C9FCE0C
+PT=FDDD484B52C7F3A32F4514BEF5A646E3
+CT=6EAC2BB6EDF35C1267FF4F10700F3CD7
+
+I=26
+KEY=DCE8CFC23343565C8320E1ADFB03FEB3
+IV=6EAC2BB6EDF35C1267FF4F10700F3CD7
+PT=CDAD592E5467AD1FA1B71D8AC050FCE0
+CT=D9624E40A8C9A2C58ABEDBAEB865DC1F
+
+I=27
+KEY=058A81829B8AF499099E3A03436622AC
+IV=D9624E40A8C9A2C58ABEDBAEB865DC1F
+PT=F9E90A4D7A9EF66818004CBC47C8C6EA
+CT=DE15C7322B32738BB493E7FA27AFE6E2
+
+I=28
+KEY=DB9F46B0B0B88712BD0DDDF964C9C44E
+IV=DE15C7322B32738BB493E7FA27AFE6E2
+PT=FE3CC4AE4A13AC8946407CEEE220290B
+CT=5822C79D627AD8A0C4975873D62C5E11
+
+I=29
+KEY=83BD812DD2C25FB2799A858AB2E59A5F
+IV=5822C79D627AD8A0C4975873D62C5E11
+PT=A5106EBD8888CC3A6884AC8E8EA9C97A
+CT=F5AD0473A4228662D9F76E7A5ED4DBDD
+
+I=30
+KEY=7610855E76E0D9D0A06DEBF0EC314182
+IV=F5AD0473A4228662D9F76E7A5ED4DBDD
+PT=4F30B073FB95CD0F0317E749F20E7A7D
+CT=4B39DA1FA331CFEB1D6713054C6E9474
+
+I=31
+KEY=3D295F41D5D1163BBD0AF8F5A05FD5F6
+IV=4B39DA1FA331CFEB1D6713054C6E9474
+PT=4850735E17F01A3B131E1B78B3A6EB96
+CT=32D1BE8640859CFAB16D64CE8795729B
+
+I=32
+KEY=0FF8E1C795548AC10C679C3B27CAA76D
+IV=32D1BE8640859CFAB16D64CE8795729B
+PT=A8C4B9E0069935CB046ACBB49C0B1205
+CT=47DC1150929AA9610938CB0CFE92995E
+
+I=33
+KEY=4824F09707CE23A0055F5737D9583E33
+IV=47DC1150929AA9610938CB0CFE92995E
+PT=13F5DA56D399A7DAA004D0BE76845E68
+CT=BCA6BD8971837B8A81B923E5B2ED0D83
+
+I=34
+KEY=F4824D1E764D582A84E674D26BB533B0
+IV=BCA6BD8971837B8A81B923E5B2ED0D83
+PT=8397C79E02FDFE6B7D47FA0181EA453A
+CT=23D991B7DA5E96966830E7B40B5A2D8A
+
+I=35
+KEY=D75BDCA9AC13CEBCECD6936660EF1E3A
+IV=23D991B7DA5E96966830E7B40B5A2D8A
+PT=18987E5504E23C0F862BCA8DFFC2B07F
+CT=17AA31C49F584DEF77C8E7891B11652B
+
+I=36
+KEY=C0F1ED6D334B83539B1E74EF7BFE7B11
+IV=17AA31C49F584DEF77C8E7891B11652B
+PT=A34D44CC1C6E171D7D48447F87E2F2C1
+CT=DD1F90F66D4062E6823F0F229562D110
+
+I=37
+KEY=1DEE7D9B5E0BE1B519217BCDEE9CAA01
+IV=DD1F90F66D4062E6823F0F229562D110
+PT=C9793582E22B8840BBAA3D7669208CCC
+CT=8F5B876777F7CA903B1D6346AA8BDAE7
+
+I=38
+KEY=92B5FAFC29FC2B25223C188B441770E6
+IV=8F5B876777F7CA903B1D6346AA8BDAE7
+PT=730EACFEE3817A94B88117ABB3F9CDE4
+CT=388780BA989C0A8BB5BD9E4086D91EF7
+
+I=39
+KEY=AA327A46B16021AE978186CBC2CE6E11
+IV=388780BA989C0A8BB5BD9E4086D91EF7
+PT=F004D3A14C6C94FA2D39BE0C71119658
+CT=7F4C33E4F5C055C05DB4B7691061B307
+
+I=40
+KEY=D57E49A244A0746ECA3531A2D2AFDD16
+IV=7F4C33E4F5C055C05DB4B7691061B307
+PT=575F86A5D1637CB86449F8BC0F1573D3
+CT=F6FE1919F174065AB31AC43E0D733A81
+
+I=41
+KEY=238050BBB5D47234792FF59CDFDCE797
+IV=F6FE1919F174065AB31AC43E0D733A81
+PT=14F8E2DB61B05E094CA4C0E9DA7800EE
+CT=4CB876F2DC169F955E639C6C916340A6
+
+I=42
+KEY=6F38264969C2EDA1274C69F04EBFA731
+IV=4CB876F2DC169F955E639C6C916340A6
+PT=F88BA2E4AA4ABDD381778DFD1DA1856F
+CT=AEEB80B469D89E45BC3426B6CCC50440
+
+I=43
+KEY=C1D3A6FD001A73E49B784F46827AA371
+IV=AEEB80B469D89E45BC3426B6CCC50440
+PT=195F74019B65C0F7D724491BDE8C8B88
+CT=2FD7CCDBDB2B2037C104F0A707A11EDA
+
+I=44
+KEY=EE046A26DB3153D35A7CBFE185DBBDAB
+IV=2FD7CCDBDB2B2037C104F0A707A11EDA
+PT=FF51887AB5FEC9C97CB61BB2DE9CDBC6
+CT=8DF7BB99B781C63F4F8B2A7D5DFF2960
+
+I=45
+KEY=63F3D1BF6CB095EC15F7959CD82494CB
+IV=8DF7BB99B781C63F4F8B2A7D5DFF2960
+PT=A35AAB0055E99FA980D59B242B8C6257
+CT=7D96ECC20571E9E85C16E3BDADA374CA
+
+I=46
+KEY=1E653D7D69C17C0449E176217587E001
+IV=7D96ECC20571E9E85C16E3BDADA374CA
+PT=02CC392194874CD531025588C96E2D22
+CT=AA1DC2E69CE582DFA9A1B435854FCBB1
+
+I=47
+KEY=B478FF9BF524FEDBE040C214F0C82BB0
+IV=AA1DC2E69CE582DFA9A1B435854FCBB1
+PT=94CC5DB118EF53C904B0EEC23AC650FD
+CT=DA0CA33BCCE4ABA1936833127D1F5E25
+
+I=48
+KEY=6E745CA039C0557A7328F1068DD77595
+IV=DA0CA33BCCE4ABA1936833127D1F5E25
+PT=52F009E929526E923BE4F43B66876725
+CT=B5E80FF4DADD69BB7493B9F72A752811
+
+I=49
+KEY=DB9C5354E31D3CC107BB48F1A7A25D84
+IV=B5E80FF4DADD69BB7493B9F72A752811
+PT=6B88B42E99E5B4F838064A711B71DE1F
+CT=5CDDCE45516C6D1654647A1A541AC435
+
+I=50
+KEY=87419D11B27151D753DF32EBF3B899B1
+IV=5CDDCE45516C6D1654647A1A541AC435
+PT=9E25CBDD8E2D7D68FF72932E35879175
+CT=3C7E88A9A6462D08ADA5910A3FCE611A
+
+I=51
+KEY=BB3F15B814377CDFFE7AA3E1CC76F8AB
+IV=3C7E88A9A6462D08ADA5910A3FCE611A
+PT=72A4EF1D82A3AC5C1DFDF8C4DCFB9F6E
+CT=E428200E1C3BE9A5141F73590B7473B8
+
+I=52
+KEY=5F1735B6080C957AEA65D0B8C7028B13
+IV=E428200E1C3BE9A5141F73590B7473B8
+PT=7CD8053F2FD743A44CC39F75C1E81075
+CT=AB3B8A79653E884053AFC8C14504AF77
+
+I=53
+KEY=F42CBFCF6D321D3AB9CA187982062464
+IV=AB3B8A79653E884053AFC8C14504AF77
+PT=0731077A8B6854CB90AFFAE3A3B199C4
+CT=53B7DFD6D12DDE7966C62FCC1946A4AC
+
+I=54
+KEY=A79B6019BC1FC343DF0C37B59B4080C8
+IV=53B7DFD6D12DDE7966C62FCC1946A4AC
+PT=E4E26CA1DA697F30E0542763313A79B7
+CT=6DEC201BBB90B66A3B2DFF4FA1DDF7C4
+
+I=55
+KEY=CA774002078F7529E421C8FA3A9D770C
+IV=6DEC201BBB90B66A3B2DFF4FA1DDF7C4
+PT=C2CF11681C4767A78B2F95AFB50CF155
+CT=F535B7CD4135A39E0E344BD2CFA14B83
+
+I=56
+KEY=3F42F7CF46BAD6B7EA158328F53C3C8F
+IV=F535B7CD4135A39E0E344BD2CFA14B83
+PT=606618948C1ED454B9B0F92435381D2D
+CT=209AC483682C48AA197BB64417127656
+
+I=57
+KEY=1FD8334C2E969E1DF36E356CE22E4AD9
+IV=209AC483682C48AA197BB64417127656
+PT=8F8A70AADF2F8BFB5E137F86AC83D32F
+CT=76F5F43A888D7F22D698A73810ED5B15
+
+I=58
+KEY=692DC776A61BE13F25F69254F2C311CC
+IV=76F5F43A888D7F22D698A73810ED5B15
+PT=E9E8AEBF16A5F4E1C26B4A385163E844
+CT=625C62F33C9548F2651FB0A08BF45286
+
+I=59
+KEY=0B71A5859A8EA9CD40E922F47937434A
+IV=625C62F33C9548F2651FB0A08BF45286
+PT=C69CFD36C50EBA06E3B3C4AB7C9B694E
+CT=3931CE6DF783063F26920D4048B00C82
+
+I=60
+KEY=32406BE86D0DAFF2667B2FB431874FC8
+IV=3931CE6DF783063F26920D4048B00C82
+PT=5DFE322DD692BA8DD9CD328A5AF9A3B7
+CT=A3CA3ECE725C84281144052A80EA5176
+
+I=61
+KEY=918A55261F512BDA773F2A9EB16D1EBE
+IV=A3CA3ECE725C84281144052A80EA5176
+PT=4BBD16BF74226F816767A7207C672C9A
+CT=94552690A231354F8F9BEF295E55F142
+
+I=62
+KEY=05DF73B6BD601E95F8A4C5B7EF38EFFC
+IV=94552690A231354F8F9BEF295E55F142
+PT=7055D0C535B2B0501FF6AAEE46E03818
+CT=771908987F00C2D822897E7EEA148F29
+
+I=63
+KEY=72C67B2EC260DC4DDA2DBBC9052C60D5
+IV=771908987F00C2D822897E7EEA148F29
+PT=7336B9D4977BDDA811C0C5EBEA539574
+CT=7AA84598115B181863081AFCC239EDD2
+
+I=64
+KEY=086E3EB6D33BC455B925A135C7158D07
+IV=7AA84598115B181863081AFCC239EDD2
+PT=5296C8546532BAEACBEC9F29916FB6B2
+CT=3D95967035AF639B2D2814DEB9B7F86A
+
+I=65
+KEY=35FBA8C6E694A7CE940DB5EB7EA2756D
+IV=3D95967035AF639B2D2814DEB9B7F86A
+PT=430880F5576C7783BC1336F900DDD037
+CT=4D70AAD2FC9EF403B463A72DB4CFE640
+
+I=66
+KEY=788B02141A0A53CD206E12C6CA6D932D
+IV=4D70AAD2FC9EF403B463A72DB4CFE640
+PT=E489B93778DE0C42FEFB6122ECA46BDC
+CT=165DDB405546934E81CB6B0B89B4A40E
+
+I=67
+KEY=6ED6D9544F4CC083A1A579CD43D93723
+IV=165DDB405546934E81CB6B0B89B4A40E
+PT=8E5481ACD58BFC5D141C1F71CDE91E37
+CT=693775A3661CE9D0E4CB4888431C64A5
+
+I=68
+KEY=07E1ACF729502953456E314500C55386
+IV=693775A3661CE9D0E4CB4888431C64A5
+PT=4AAA5E507EFB9FAD15E5F4C77F46AF89
+CT=C42391D50B1210C67B6AD642745A4DAC
+
+I=69
+KEY=C3C23D22224239953E04E707749F1E2A
+IV=C42391D50B1210C67B6AD642745A4DAC
+PT=4E0748F8716801B099494037485B8BA4
+CT=A4CB7F010AC42B4C3C14F02353F3644A
+
+I=70
+KEY=67094223288612D902101724276C7A60
+IV=A4CB7F010AC42B4C3C14F02353F3644A
+PT=0B7B41D57885DB37A2FC355C8D03FF3C
+CT=1BB0CBD24537B36EB555BE8C0FEC3A1F
+
+I=71
+KEY=7CB989F16DB1A1B7B745A9A82880407F
+IV=1BB0CBD24537B36EB555BE8C0FEC3A1F
+PT=4696F9A564354194142AB7B8630B4279
+CT=18B10BAE39D4FA58F586A067A8E38BC5
+
+I=72
+KEY=6408825F54655BEF42C309CF8063CBBA
+IV=18B10BAE39D4FA58F586A067A8E38BC5
+PT=0B59EBABAB994F2DDB3DE383454BECE8
+CT=C09C6670B93ECD303BA53DE58DD81A64
+
+I=73
+KEY=A494E42FED5B96DF7966342A0DBBD1DE
+IV=C09C6670B93ECD303BA53DE58DD81A64
+PT=2F897F3385E71133CEC8367411E830A3
+CT=45EA7CB9119DF7367294F9FE36D4A09F
+
+I=74
+KEY=E17E9896FCC661E90BF2CDD43B6F7141
+IV=45EA7CB9119DF7367294F9FE36D4A09F
+PT=8CDE9D975B51A098F4CAC93DC58C002F
+CT=02DDD735439A8AE03E976E629A6C992C
+
+I=75
+KEY=E3A34FA3BF5CEB093565A3B6A103E86D
+IV=02DDD735439A8AE03E976E629A6C992C
+PT=1E20571F82C2C6884A6F90A23FD3A925
+CT=B040686B866AE80A88B899031F2F0EE4
+
+I=76
+KEY=53E327C839360303BDDD3AB5BE2CE689
+IV=B040686B866AE80A88B899031F2F0EE4
+PT=0851624711970ADE2F456D5DAFB17E05
+CT=201756BC061706513264A3C489D95A0C
+
+I=77
+KEY=73F471743F2105528FB9997137F5BC85
+IV=201756BC061706513264A3C489D95A0C
+PT=E8B1410DE742136E71F54D31FEAA72EB
+CT=2EF27C31AA488648FCE0F1804D658092
+
+I=78
+KEY=5D060D459569831A735968F17A903C17
+IV=2EF27C31AA488648FCE0F1804D658092
+PT=97E0CA84C9B22C8942C7FC5088EAED04
+CT=7545F1D9C8F5F8B441EDCDAF00462344
+
+I=79
+KEY=2843FC9C5D9C7BAE32B4A55E7AD61F53
+IV=7545F1D9C8F5F8B441EDCDAF00462344
+PT=7B5572C09E998656B55C53748CF77C21
+CT=347875EFD6BD978CD1B2EA949F7E2358
+
+I=80
+KEY=1C3B89738B21EC22E3064FCAE5A83C0B
+IV=347875EFD6BD978CD1B2EA949F7E2358
+PT=A30001AA29D70B0A141B8FC8B9B2E210
+CT=9C956408BA335CCC9F02F31CC45FD5E6
+
+I=81
+KEY=80AEED7B3112B0EE7C04BCD621F7E9ED
+IV=9C956408BA335CCC9F02F31CC45FD5E6
+PT=839783D75859393B215010F63159FA45
+CT=B70E700F4A7ED08618754960B83BD0F2
+
+I=82
+KEY=37A09D747B6C60686471F5B699CC391F
+IV=B70E700F4A7ED08618754960B83BD0F2
+PT=1E3C630BC8C34BF8822686043D14E4D6
+CT=4721B6796F82D47D6EEB9CB11A19605E
+
+I=83
+KEY=70812B0D14EEB4150A9A690783D55941
+IV=4721B6796F82D47D6EEB9CB11A19605E
+PT=CEE1B977E8B75623CC4E2C4F4765FE2A
+CT=3382E1B076680BBBE7C451582016DD11
+
+I=84
+KEY=4303CABD6286BFAEED5E385FA3C38450
+IV=3382E1B076680BBBE7C451582016DD11
+PT=02365457AB60C892A0C34A7067AB7608
+CT=AB581732E06B90AA0C835C1C7B6D18B5
+
+I=85
+KEY=E85BDD8F82ED2F04E1DD6443D8AE9CE5
+IV=AB581732E06B90AA0C835C1C7B6D18B5
+PT=222B7ED84C648C12FFDD6E8E13EEC651
+CT=3E2E592CEEAD3B5E16860E80E406E882
+
+I=86
+KEY=D67584A36C40145AF75B6AC33CA87467
+IV=3E2E592CEEAD3B5E16860E80E406E882
+PT=7D24BD646EEBA44ED27B11DA42D72FF8
+CT=9163F6DBE0D8BB79A154D92E37A07E1C
+
+I=87
+KEY=471672788C98AF23560FB3ED0B080A7B
+IV=9163F6DBE0D8BB79A154D92E37A07E1C
+PT=42B571FFB3275F5A8E26616A3F0E3403
+CT=E1340E61513FE8146F29E111392E2C3A
+
+I=88
+KEY=A6227C19DDA74737392652FC32262641
+IV=E1340E61513FE8146F29E111392E2C3A
+PT=6EFD16D48E03B6E1CD74777ABC891DA8
+CT=3D703B4FD8A8A7F015D0FD47DE0C5A28
+
+I=89
+KEY=9B524756050FE0C72CF6AFBBEC2A7C69
+IV=3D703B4FD8A8A7F015D0FD47DE0C5A28
+PT=7956129687AC95397E14821A17F267DE
+CT=C5C6D2BAABDBE0B82CDFFFE7A92C8344
+
+I=90
+KEY=5E9495ECAED4007F0029505C4506FF2D
+IV=C5C6D2BAABDBE0B82CDFFFE7A92C8344
+PT=AC661770332FE0A45B80791C3A5D1241
+CT=6F7BDE1BD17C5B10064B52EB54EE90B0
+
+I=91
+KEY=31EF4BF77FA85B6F066202B711E86F9D
+IV=6F7BDE1BD17C5B10064B52EB54EE90B0
+PT=1DE0702C81667A979E5E3542DA95C5AD
+CT=DC7E35D5B02AFF4B92C190265E01C0F8
+
+I=92
+KEY=ED917E22CF82A42494A392914FE9AF65
+IV=DC7E35D5B02AFF4B92C190265E01C0F8
+PT=A491CB4321C757FD353B560C0B3EA4D0
+CT=D753F5A6C5D7E17F4024FD8675B23E7F
+
+I=93
+KEY=3AC28B840A55455BD4876F173A5B911A
+IV=D753F5A6C5D7E17F4024FD8675B23E7F
+PT=418FA3B3E9B4E463D04AC3A3361DCA57
+CT=B635529E8080B33E9AD6D79B8203112D
+
+I=94
+KEY=8CF7D91A8AD5F6654E51B88CB8588037
+IV=B635529E8080B33E9AD6D79B8203112D
+PT=C87E4ED505989807D1DBDA4769804EA3
+CT=43E763CD1B9EE4BC474B79C1E0DA2564
+
+I=95
+KEY=CF10BAD7914B12D9091AC14D5882A553
+IV=43E763CD1B9EE4BC474B79C1E0DA2564
+PT=042F084454D0EE01AB00D3921E1BCA06
+CT=C799956FF8A7A05B71123EBC4AA09C0C
+
+I=96
+KEY=08892FB869ECB2827808FFF11222395F
+IV=C799956FF8A7A05B71123EBC4AA09C0C
+PT=9A8E40400C51A438DCE498AD3455DE51
+CT=76679B0E26B1B6CA2A8D90944777C57F
+
+I=97
+KEY=7EEEB4B64F5D044852856F655555FC20
+IV=76679B0E26B1B6CA2A8D90944777C57F
+PT=227E122D3AF18A3CAA973B33B3356CE7
+CT=B2F52396F02D2DFFE36C5F9238AC1EBE
+
+I=98
+KEY=CC1B9720BF7029B7B1E930F76DF9E29E
+IV=B2F52396F02D2DFFE36C5F9238AC1EBE
+PT=0D9CDD97E2FE0E78CF16B1596DC20ABA
+CT=7C8EDD3A079835954238E0FE4872AAE1
+
+I=99
+KEY=B0954A1AB8E81C22F3D1D009258B487F
+IV=7C8EDD3A079835954238E0FE4872AAE1
+PT=925A7ECD233B3B3CCDE2221A03C5F720
+CT=D7C9FD3EF010C8577087591149D5640F
+
+I=100
+KEY=675CB72448F8D475835689186C5E2C70
+IV=D7C9FD3EF010C8577087591149D5640F
+PT=59FEFBE5179F0E7E48F3D97CDA314FF5
+CT=2608CCE6BA917551DEF84FA7BCA9B23C
+
+I=101
+KEY=41547BC2F269A1245DAEC6BFD0F79E4C
+IV=2608CCE6BA917551DEF84FA7BCA9B23C
+PT=7F24A1BA8762294194F76322A6B28A16
+CT=EFF1513B52D5D74D2202898AC99552C4
+
+I=102
+KEY=AEA52AF9A0BC76697FAC4F351962CC88
+IV=EFF1513B52D5D74D2202898AC99552C4
+PT=79B43F27F3E144C4EFBF383698A1EC90
+CT=B4B3B020D44D059666E86D22072916B5
+
+I=103
+KEY=1A169AD974F173FF194422171E4BDA3D
+IV=B4B3B020D44D059666E86D22072916B5
+PT=8BF20B60B4774354857BA2979CD396F9
+CT=6F1A3D43CC2171A808AE8D38396DE1D1
+
+I=104
+KEY=750CA79AB8D0025711EAAF2F27263BEC
+IV=6F1A3D43CC2171A808AE8D38396DE1D1
+PT=74955DDACFB8A5467D069F1EF341248B
+CT=47C23A68DA351C22EBF86FDBD8F723B4
+
+I=105
+KEY=32CE9DF262E51E75FA12C0F4FFD11858
+IV=47C23A68DA351C22EBF86FDBD8F723B4
+PT=25D7A186ED990020E10A23C5CFB1CEF9
+CT=D5F2E2C2CED730479D87E0AF0FEF8A73
+
+I=106
+KEY=E73C7F30AC322E326795205BF03E922B
+IV=D5F2E2C2CED730479D87E0AF0FEF8A73
+PT=13480F2EDCCB62B8F9A7DF98238571FC
+CT=F29A46A7F1B1D1D4F5FE30E569D7A801
+
+I=107
+KEY=15A639975D83FFE6926B10BE99E93A2A
+IV=F29A46A7F1B1D1D4F5FE30E569D7A801
+PT=75E138123B5A98596303ACF9DAEEA714
+CT=9F6E9A13913DF78AC67BD20303AF49B5
+
+I=108
+KEY=8AC8A384CCBE086C5410C2BD9A46739F
+IV=9F6E9A13913DF78AC67BD20303AF49B5
+PT=DBD0AE00FD06761626366EB251412A32
+CT=46AC9F42239B22A163CE0FDEAA103D44
+
+I=109
+KEY=CC643CC6EF252ACD37DECD6330564EDB
+IV=46AC9F42239B22A163CE0FDEAA103D44
+PT=B8768A8AF461C9547D1F982FE90E96B6
+CT=95D7C8F969B0EEB03FEC257043597315
+
+I=110
+KEY=59B3F43F8695C47D0832E813730F3DCE
+IV=95D7C8F969B0EEB03FEC257043597315
+PT=3D20CC8AD484048251C7A81C7E3CA59C
+CT=6B74AF42435BC640A826EC443207574E
+
+I=111
+KEY=32C75B7DC5CE023DA014045741086A80
+IV=6B74AF42435BC640A826EC443207574E
+PT=BF719F78B23BAFD4A50634BCD9361095
+CT=31E3919F36D79FBF61884227110C10FF
+
+I=112
+KEY=0324CAE2F3199D82C19C467050047A7F
+IV=31E3919F36D79FBF61884227110C10FF
+PT=E1D32740BB8B6D67AD3038887899F090
+CT=A1CD90683CE041D6CA20780176FDD5F4
+
+I=113
+KEY=A2E95A8ACFF9DC540BBC3E7126F9AF8B
+IV=A1CD90683CE041D6CA20780176FDD5F4
+PT=3069EA97F092ACDCF41649377B8FCBC8
+CT=7220F866A10DC711DC1D277B4C8F204D
+
+I=114
+KEY=D0C9A2EC6EF41B45D7A1190A6A768FC6
+IV=7220F866A10DC711DC1D277B4C8F204D
+PT=B0563A5E0EE1E2B96F3F7D04EE39EA7C
+CT=CF81CA348B98C532B172F032AE0A6FED
+
+I=115
+KEY=1F4868D8E56CDE7766D3E938C47CE02B
+IV=CF81CA348B98C532B172F032AE0A6FED
+PT=B1B78BD75C30DD4E1E198ACB98B498A6
+CT=99C990D64D27D47ED0C1E7F186AC6674
+
+I=116
+KEY=8681F80EA84B0A09B6120EC942D0865F
+IV=99C990D64D27D47ED0C1E7F186AC6674
+PT=D413E3CC66E9938E4E0CFC1975E38C8C
+CT=30C7DAD86FEF77C43A44A3EF8B116354
+
+I=117
+KEY=B64622D6C7A47DCD8C56AD26C9C1E50B
+IV=30C7DAD86FEF77C43A44A3EF8B116354
+PT=CD85D9334481AE85B8816233CA4AF7DB
+CT=9E717B45239DD908138837154B803654
+
+I=118
+KEY=28375993E439A4C59FDE9A338241D35F
+IV=9E717B45239DD908138837154B803654
+PT=925BA3760D655D5B788802DDE25732BB
+CT=4A6E32C01709EBCCC9BCA43FD5DFDFB3
+
+I=119
+KEY=62596B53F3304F0956623E0C579E0CEC
+IV=4A6E32C01709EBCCC9BCA43FD5DFDFB3
+PT=0AA6264BFCC7BD07FA8F94E1EF739633
+CT=7263392DC9DA868BC0317A6D4AD52553
+
+I=120
+KEY=103A527E3AEAC982965344611D4B29BF
+IV=7263392DC9DA868BC0317A6D4AD52553
+PT=FB385BD8ECE7C4DFE2351D851141888D
+CT=AA49B1DDA3AF4D05D861667E88AD61AB
+
+I=121
+KEY=BA73E3A3994584874E32221F95E64814
+IV=AA49B1DDA3AF4D05D861667E88AD61AB
+PT=510E13E20BB06EAD335F10F2C69831D3
+CT=3AC256A92F69AF35DB05DDCA61CF1EE4
+
+I=122
+KEY=80B1B50AB62C2BB29537FFD5F42956F0
+IV=3AC256A92F69AF35DB05DDCA61CF1EE4
+PT=0A07CAA0EC6CB726F1A38847253BECB6
+CT=037497736381429A5E5A139C44A6C64A
+
+I=123
+KEY=83C52279D5AD6928CB6DEC49B08F90BA
+IV=037497736381429A5E5A139C44A6C64A
+PT=864FEF67C8902757E2CFB28DA2EF3C8D
+CT=5393D7F9F37A5B9F1F82C1BE20435149
+
+I=124
+KEY=D056F58026D732B7D4EF2DF790CCC1F3
+IV=5393D7F9F37A5B9F1F82C1BE20435149
+PT=ED2D2A671677067B30540D4C9D86905F
+CT=2969AC5FB94EC76209C6DF58F6B8AA01
+
+I=125
+KEY=F93F59DF9F99F5D5DD29F2AF66746BF2
+IV=2969AC5FB94EC76209C6DF58F6B8AA01
+PT=67ED14454DAD764C1772BCB1E0527954
+CT=150F94E1940F9D2ACC735F79B0912A06
+
+I=126
+KEY=EC30CD3E0B9668FF115AADD6D6E541F4
+IV=150F94E1940F9D2ACC735F79B0912A06
+PT=517A4852F68370EDD879E32F52FD4D2B
+CT=6EFD8E4E4C096A2033B3DA8A1F0066AF
+
+I=127
+KEY=82CD4370479F02DF22E9775CC9E5275B
+IV=6EFD8E4E4C096A2033B3DA8A1F0066AF
+PT=DBF4CAD912437115658E5BA5E1724739
+CT=899D9126CD85D2D4053AD9EE7156041B
+
+I=128
+KEY=0B50D2568A1AD00B27D3AEB2B8B32340
+IV=899D9126CD85D2D4053AD9EE7156041B
+PT=69B302F96AFCF802AC639EBABC52ECFB
+CT=819E4B8319807088FF306E125E52DAD3
+
+I=129
+KEY=8ACE99D5939AA083D8E3C0A0E6E1F993
+IV=819E4B8319807088FF306E125E52DAD3
+PT=F5CA57371833F0AF98F0EC02DFE518ED
+CT=4DFA3739235D14660DF7D5FDE36F6567
+
+I=130
+KEY=C734AEECB0C7B4E5D514155D058E9CF4
+IV=4DFA3739235D14660DF7D5FDE36F6567
+PT=29BBD9264B9792BED8A8EFA43F943A7D
+CT=4EA36ECCBCCD9FAFD8FB588BD53826A7
+
+I=131
+KEY=8997C0200C0A2B4A0DEF4DD6D0B6BA53
+IV=4EA36ECCBCCD9FAFD8FB588BD53826A7
+PT=149120CFC3D7C671F287AA77A4A3EF97
+CT=0282357C78C8944A5520AF80506DE30D
+
+I=132
+KEY=8B15F55C74C2BF0058CFE25680DB595E
+IV=0282357C78C8944A5520AF80506DE30D
+PT=02C2E0CCB12F5216213D493325F38FC3
+CT=C827C36F654137A2BB127D1782285B10
+
+I=133
+KEY=43323633118388A2E3DD9F4102F3024E
+IV=C827C36F654137A2BB127D1782285B10
+PT=FA1693AD90401791FF9093A562EC66EB
+CT=3723A94BC91032BF8DB599ABEFB784D1
+
+I=134
+KEY=74119F78D893BA1D6E6806EAED44869F
+IV=3723A94BC91032BF8DB599ABEFB784D1
+PT=5410CBE33ABB58AB0B0E86F5817E6F2C
+CT=26A520B5B475632EE8806648BFC028AF
+
+I=135
+KEY=52B4BFCD6CE6D93386E860A25284AE30
+IV=26A520B5B475632EE8806648BFC028AF
+PT=B01A11D200C24F4333029DE3BFF49601
+CT=36D5E00E0A53D7CE1498215AFA686905
+
+I=136
+KEY=64615FC366B50EFD927041F8A8ECC735
+IV=36D5E00E0A53D7CE1498215AFA686905
+PT=252E4460E9A391D54CE9E516663E59AE
+CT=829F0B7B17ED5F2FB7A014A6CD9D8052
+
+I=137
+KEY=E6FE54B8715851D225D0555E65714767
+IV=829F0B7B17ED5F2FB7A014A6CD9D8052
+PT=BCC51A6493F6847BEA8219329F67308D
+CT=BAB1D358D08DA13BEC485051F2EBFE2E
+
+I=138
+KEY=5C4F87E0A1D5F0E9C998050F979AB949
+IV=BAB1D358D08DA13BEC485051F2EBFE2E
+PT=D89236011B3C2338E95322D4716AEE59
+CT=29BA99F8CF8B48134B1330E75BD7254E
+
+I=139
+KEY=75F51E186E5EB8FA828B35E8CC4D9C07
+IV=29BA99F8CF8B48134B1330E75BD7254E
+PT=21D0EB5857C93A0D4D75253E1020C00E
+CT=9D557274FE14AA69673441117A2D7DA2
+
+I=140
+KEY=E8A06C6C904A1293E5BF74F9B660E1A5
+IV=9D557274FE14AA69673441117A2D7DA2
+PT=3C3BB454584C4C7570089B6E631BA035
+CT=543EF50A024E77ACE685BD0BBB47232D
+
+I=141
+KEY=BC9E99669204653F033AC9F20D27C288
+IV=543EF50A024E77ACE685BD0BBB47232D
+PT=8ED890BC903AEAC7C3C685980EDB3370
+CT=884BD68868D89DE9DEDB2D95A8B992FB
+
+I=142
+KEY=34D54FEEFADCF8D6DDE1E467A59E5073
+IV=884BD68868D89DE9DEDB2D95A8B992FB
+PT=684DEBD6DEDE24BD0F4F8AFA47F08AEF
+CT=DB00984CAEB14CF5A1FDE8E8E9C03830
+
+I=143
+KEY=EFD5D7A2546DB4237C1C0C8F4C5E6843
+IV=DB00984CAEB14CF5A1FDE8E8E9C03830
+PT=C42B245443F2695F306455199C7C76FE
+CT=0CA808425E8EBDDD5519130F4900329F
+
+I=144
+KEY=E37DDFE00AE309FE29051F80055E5ADC
+IV=0CA808425E8EBDDD5519130F4900329F
+PT=1655F89334CCB6ED8E140088997BD2D1
+CT=0DAE2F85CD81874DCD7368277D0C386D
+
+I=145
+KEY=EED3F065C7628EB3E47677A7785262B1
+IV=0DAE2F85CD81874DCD7368277D0C386D
+PT=2B7A2DF6E0CAC83837AFDC8B2134E6A6
+CT=E3BF66A6784432E6CE61B769C3CFDB35
+
+I=146
+KEY=0D6C96C3BF26BC552A17C0CEBB9DB984
+IV=E3BF66A6784432E6CE61B769C3CFDB35
+PT=8FED19E77B9690EC8F70272364B4EB74
+CT=473925552401311F24EE4F40B5A3ECB5
+
+I=147
+KEY=4A55B3969B278D4A0EF98F8E0E3E5531
+IV=473925552401311F24EE4F40B5A3ECB5
+PT=032D9AF654037E2586B12CF031E4AB4C
+CT=E9E1E4ACF3F4E25CB8093F6B27665DFF
+
+I=148
+KEY=A3B4573A68D36F16B6F0B0E5295808CE
+IV=E9E1E4ACF3F4E25CB8093F6B27665DFF
+PT=E6EF26B3721F6C772D231584DD480441
+CT=2D9F85D63FED609876DF97F0E6B85564
+
+I=149
+KEY=8E2BD2EC573E0F8EC02F2715CFE05DAA
+IV=2D9F85D63FED609876DF97F0E6B85564
+PT=E641EBC4A734C71669D948F1BEEE675A
+CT=3A61F4BED09FD7A7AED71E9FD53D2EE3
+
+I=150
+KEY=B44A265287A1D8296EF8398A1ADD7349
+IV=3A61F4BED09FD7A7AED71E9FD53D2EE3
+PT=36DB43747CD9215857886A0DE2008509
+CT=6BE2AD95F4A642F3FD73D9543B53D479
+
+I=151
+KEY=DFA88BC773079ADA938BE0DE218EA730
+IV=6BE2AD95F4A642F3FD73D9543B53D479
+PT=58A73313B31B8C1EB3C144C9363EE94B
+CT=BF198D336DF857BFBA069634C25CF45B
+
+I=152
+KEY=60B106F41EFFCD65298D76EAE3D2536B
+IV=BF198D336DF857BFBA069634C25CF45B
+PT=E0974E1BBEFE21422ECED27858535F87
+CT=7945132F6F7EED6B61E1CF9C47E2AB2A
+
+I=153
+KEY=19F415DB7181200E486CB976A430F841
+IV=7945132F6F7EED6B61E1CF9C47E2AB2A
+PT=6F36B63A1A8B426282CA4E61B7E37B3A
+CT=AF441F330C8C199E9776D92A92B02216
+
+I=154
+KEY=B6B00AE87D0D3990DF1A605C3680DA57
+IV=AF441F330C8C199E9776D92A92B02216
+PT=99AD2B814D3A4C0E1C27D4251C55C74A
+CT=F34463A538E46E87B0F24EAA36B674A7
+
+I=155
+KEY=45F4694D45E957176FE82EF60036AEF0
+IV=F34463A538E46E87B0F24EAA36B674A7
+PT=6D05C19E42D0561C198A10FA55F4C870
+CT=5D54D3C72D55015D0149FA1591208824
+
+I=156
+KEY=18A0BA8A68BC564A6EA1D4E3911626D4
+IV=5D54D3C72D55015D0149FA1591208824
+PT=7AA7A04DE8CD21F59BA5369CA175CEC3
+CT=D2EBE35C33210B39CD4F443BB577DBD8
+
+I=157
+KEY=CA4B59D65B9D5D73A3EE90D82461FD0C
+IV=D2EBE35C33210B39CD4F443BB577DBD8
+PT=2DA2A48FE13FA4DD5271A02FB7F98AEC
+CT=2F4AD89C0D915DF978160E9E882AD28E
+
+I=158
+KEY=E501814A560C008ADBF89E46AC4B2F82
+IV=2F4AD89C0D915DF978160E9E882AD28E
+PT=82EB831B9FF9DA7D06553A456133766B
+CT=09A04C7CBED3D60ADB6CFDD012DEED17
+
+I=159
+KEY=ECA1CD36E8DFD68000946396BE95C295
+IV=09A04C7CBED3D60ADB6CFDD012DEED17
+PT=8D4FD1CE8CB9745E9E65182D94F8307A
+CT=193C6FAB40C87C7029983EDD52628400
+
+I=160
+KEY=F59DA29DA817AAF0290C5D4BECF74695
+IV=193C6FAB40C87C7029983EDD52628400
+PT=F06A061082E499E65A5DED0D22323F57
+CT=7166BD655D8128E7B09D37B38478B480
+
+I=161
+KEY=84FB1FF8F596821799916AF8688FF215
+IV=7166BD655D8128E7B09D37B38478B480
+PT=DCEC808551EA98534E1A9EDF457125DA
+CT=5DFAAFB695D34A7AF2D39CD2D01FD4BD
+
+I=162
+KEY=D901B04E6045C86D6B42F62AB89026A8
+IV=5DFAAFB695D34A7AF2D39CD2D01FD4BD
+PT=FAE59C96604D062F49C8C93FA7E4D5FC
+CT=85F63AFC88A1CED4E73B849C295692F2
+
+I=163
+KEY=5CF78AB2E8E406B98C7972B691C6B45A
+IV=85F63AFC88A1CED4E73B849C295692F2
+PT=7FE1EA6A7A525A7E0222D6269F7D6A40
+CT=DC60A8554BF9E783D0E92283EC0D00AF
+
+I=164
+KEY=809722E7A31DE13A5C9050357DCBB4F5
+IV=DC60A8554BF9E783D0E92283EC0D00AF
+PT=89C93828CE30D4CD7025D9F2CF864371
+CT=EF10720E8F10FBABC96BB5F4E5287D12
+
+I=165
+KEY=6F8750E92C0D1A9195FBE5C198E3C9E7
+IV=EF10720E8F10FBABC96BB5F4E5287D12
+PT=A8DEA35D4A712ACE8F38A2CA2CB6BCFB
+CT=EED271733DC7B81AD09C86C8F8D69255
+
+I=166
+KEY=8155219A11CAA28B4567630960355BB2
+IV=EED271733DC7B81AD09C86C8F8D69255
+PT=6720AD239EFECF5785B238D4DA39DD6A
+CT=DC47B1FAC154CB0C39ADF4C92F8C2902
+
+I=167
+KEY=5D129060D09E69877CCA97C04FB972B0
+IV=DC47B1FAC154CB0C39ADF4C92F8C2902
+PT=D41DEA3BC44CC552B5ACCFEEFAF225F5
+CT=AD4828834513730BF275C854D35BF09E
+
+I=168
+KEY=F05AB8E3958D1A8C8EBF5F949CE2822E
+IV=AD4828834513730BF275C854D35BF09E
+PT=5059DA9258A7DE12865E1E2173399BC9
+CT=82CA6B085A452CFDFFBDE5C7B738CDAB
+
+I=169
+KEY=7290D3EBCFC836717102BA532BDA4F85
+IV=82CA6B085A452CFDFFBDE5C7B738CDAB
+PT=9625B8A444C3E4D3554A8C6E33E1B810
+CT=4F44C38189E1011970690D0ED4BCB9C7
+
+I=170
+KEY=3DD4106A46293768016BB75DFF66F642
+IV=4F44C38189E1011970690D0ED4BCB9C7
+PT=373FBCA7529A9FA9AF77295FC55B0BEE
+CT=27BE0578B0F898C04133AA4D3C1A5A7C
+
+I=171
+KEY=1A6A1512F6D1AFA840581D10C37CAC3E
+IV=27BE0578B0F898C04133AA4D3C1A5A7C
+PT=37FC0A286DFFD5A76643D1D45C858F64
+CT=B9C70B34F78F3DA7796C32D0918474A5
+
+I=172
+KEY=A3AD1E26015E920F39342FC052F8D89B
+IV=B9C70B34F78F3DA7796C32D0918474A5
+PT=E1EAC69AA2A8F05B8747E2624D00F4BB
+CT=846985C471F10676E63BCD09C32506F3
+
+I=173
+KEY=27C49BE270AF9479DF0FE2C991DDDE68
+IV=846985C471F10676E63BCD09C32506F3
+PT=6EB0046D9C6854C63447296F4F6D3D21
+CT=F754559746C52113C29AF782E96B6105
+
+I=174
+KEY=D090CE75366AB56A1D95154B78B6BF6D
+IV=F754559746C52113C29AF782E96B6105
+PT=F65269422328F40D8A53F4F14DB88583
+CT=AE6B4EABF8DC479A1E3F8C3F30A4A797
+
+I=175
+KEY=7EFB80DECEB6F2F003AA9974481218FA
+IV=AE6B4EABF8DC479A1E3F8C3F30A4A797
+PT=765B38DC041DEC130A3A294D9F89A16D
+CT=87645926B9D85AC4AB023D2104CC3FA2
+
+I=176
+KEY=F99FD9F8776EA834A8A8A4554CDE2758
+IV=87645926B9D85AC4AB023D2104CC3FA2
+PT=8070950120E0FBE07C70B171364AD173
+CT=0125D51139CE00DB848B8A9AD3FEB90B
+
+I=177
+KEY=F8BA0CE94EA0A8EF2C232ECF9F209E53
+IV=0125D51139CE00DB848B8A9AD3FEB90B
+PT=1EF45DD2CD61667469569CFAD445341C
+CT=E1651756A2C0D132C671D74748244E49
+
+I=178
+KEY=19DF1BBFEC6079DDEA52F988D704D01A
+IV=E1651756A2C0D132C671D74748244E49
+PT=26BEF7E8A3D0AC50DC64B8215CCBC44F
+CT=94049FBD554A6CFFE7927D6EC07D6242
+
+I=179
+KEY=8DDB8402B92A15220DC084E61779B258
+IV=94049FBD554A6CFFE7927D6EC07D6242
+PT=803F34FA967583623D0CA4D76FC56787
+CT=974BBE04952D8F0DD70F4353FEB092EB
+
+I=180
+KEY=1A903A062C079A2FDACFC7B5E9C920B3
+IV=974BBE04952D8F0DD70F4353FEB092EB
+PT=023E5D307CE85244144D59A53DB504E7
+CT=2615B9F94F9024EA616648FF15E3B65F
+
+I=181
+KEY=3C8583FF6397BEC5BBA98F4AFC2A96EC
+IV=2615B9F94F9024EA616648FF15E3B65F
+PT=1A84130B09CE3E7AB1F400B9FE295BEB
+CT=39A2A3B6EFB5EBE805CBAD5817EAEEDA
+
+I=182
+KEY=052720498C22552DBE622212EBC07836
+IV=39A2A3B6EFB5EBE805CBAD5817EAEEDA
+PT=B83609055302D99DE46B7153AE3DFCE2
+CT=93F72B839E2AD731B5E894B56ADADCF4
+
+I=183
+KEY=96D00BCA1208821C0B8AB6A7811AA4C2
+IV=93F72B839E2AD731B5E894B56ADADCF4
+PT=85E69EBDE13C05526EA8AE1D24B487F3
+CT=D0ADA333801DFDBFC2420B73CD2B92A5
+
+I=184
+KEY=467DA8F992157FA3C9C8BDD44C313667
+IV=D0ADA333801DFDBFC2420B73CD2B92A5
+PT=F24782E953B9B1BBF3B925659C99415B
+CT=F59A3D0B65E8F16DC73CCD6C27E8C705
+
+I=185
+KEY=B3E795F2F7FD8ECE0EF470B86BD9F162
+IV=F59A3D0B65E8F16DC73CCD6C27E8C705
+PT=73BE517552E054D78583BEA03B84A245
+CT=7904DBE3A103D936EB4B960C180B0651
+
+I=186
+KEY=CAE34E1156FE57F8E5BFE6B473D2F733
+IV=7904DBE3A103D936EB4B960C180B0651
+PT=91998E9582D8357DD5D8B95A9D85912F
+CT=C2DE0D0145A45DEABD6DE1FD62161EB1
+
+I=187
+KEY=083D4310135A0A1258D2074911C4E982
+IV=C2DE0D0145A45DEABD6DE1FD62161EB1
+PT=2A5D4EC49712B9CF1E2D9C6C5EFACC2A
+CT=974264BDC574C738243DDC008EC4C15A
+
+I=188
+KEY=9F7F27ADD62ECD2A7CEFDB499F0028D8
+IV=974264BDC574C738243DDC008EC4C15A
+PT=F74520C3745B9B9F9D19642AA57451FB
+CT=F4EE51C2ECC32F4806F9C8588880525B
+
+I=189
+KEY=6B91766F3AEDE2627A16131117807A83
+IV=F4EE51C2ECC32F4806F9C8588880525B
+PT=4A7D6FC6712F451F58DF0AC2D517189E
+CT=F4978F5F53AA4C336BEE0C62F432B44F
+
+I=190
+KEY=9F06F9306947AE5111F81F73E3B2CECC
+IV=F4978F5F53AA4C336BEE0C62F432B44F
+PT=00DAD17491C973991FEC296972B691BC
+CT=09DAA53C2E394BF83113BE48E5D0CCA2
+
+I=191
+KEY=96DC5C0C477EE5A920EBA13B0662026E
+IV=09DAA53C2E394BF83113BE48E5D0CCA2
+PT=C00943704C1336F01A1D23FD98BE7E8B
+CT=D0DE529664BF241DBED3168DA5BC1B28
+
+I=192
+KEY=46020E9A23C1C1B49E38B7B6A3DE1946
+IV=D0DE529664BF241DBED3168DA5BC1B28
+PT=A07FAD9770CC32C5680F33A2D67044A4
+CT=F6A44922B3744BE96C46742A79A49CBB
+
+I=193
+KEY=B0A647B890B58A5DF27EC39CDA7A85FD
+IV=F6A44922B3744BE96C46742A79A49CBB
+PT=D5450C670BE84169AD1E62C5ECB8365F
+CT=47D229908D4C1EA34E429C34B7D635F5
+
+I=194
+KEY=F7746E281DF994FEBC3C5FA86DACB008
+IV=47D229908D4C1EA34E429C34B7D635F5
+PT=9E90D30BE92104667A16522237D645A6
+CT=6463AC2096842A0958ACF45370C0626F
+
+I=195
+KEY=9317C2088B7DBEF7E490ABFB1D6CD267
+IV=6463AC2096842A0958ACF45370C0626F
+PT=74382A7BF713DE8E8D17AE389E03C3AC
+CT=ECDCEF7613C362D288AC23D38722DC4C
+
+I=196
+KEY=7FCB2D7E98BEDC256C3C88289A4E0E2B
+IV=ECDCEF7613C362D288AC23D38722DC4C
+PT=DB2EC6F41A72F426D9F5DBC65CEC1C5C
+CT=DFE2DA423ACE2DFB053265E9E9B214E2
+
+I=197
+KEY=A029F73CA270F1DE690EEDC173FC1AC9
+IV=DFE2DA423ACE2DFB053265E9E9B214E2
+PT=35998CB9958DC9DE0550FC3EA722D571
+CT=5EBCA79BF99165D9FFE355D9B24ECB5D
+
+I=198
+KEY=FE9550A75BE1940796EDB818C1B2D194
+IV=5EBCA79BF99165D9FFE355D9B24ECB5D
+PT=9BDA7BC96736FE2140911C98E8E02E1C
+CT=782D3EFD5F599E8D3C85D06128677EC2
+
+I=199
+KEY=86B86E5A04B80A8AAA686879E9D5AF56
+IV=782D3EFD5F599E8D3C85D06128677EC2
+PT=8014C1F398E4DCC7F4E5E09E5FAFB080
+CT=E01AE2D961F31BBAE3DA7429627572AB
+
+I=200
+KEY=66A28C83654B113049B21C508BA0DDFD
+IV=E01AE2D961F31BBAE3DA7429627572AB
+PT=97D66D66D1731EEFF14519620616A10B
+CT=BC41ED9D568D6ED36212C92DEEB40A0E
+
+I=201
+KEY=DAE3611E33C67FE32BA0D57D6514D7F3
+IV=BC41ED9D568D6ED36212C92DEEB40A0E
+PT=F7646B60C237ED24F467141980EB4F00
+CT=CB8DF2D164E5B4AB3193D02E71959F63
+
+I=202
+KEY=116E93CF5723CB481A33055314814890
+IV=CB8DF2D164E5B4AB3193D02E71959F63
+PT=4A3A241B26AC7A1C88AA2FB750DF6E5A
+CT=E396FB47A686ABAA350B84C250E5EAE9
+
+I=203
+KEY=F2F86888F1A560E22F3881914464A279
+IV=E396FB47A686ABAA350B84C250E5EAE9
+PT=A71348309D176A072167C4B1B8A295C0
+CT=29AF21F96564EB591E9A60B1BE88DEC7
+
+I=204
+KEY=DB57497194C18BBB31A2E120FAEC7CBE
+IV=29AF21F96564EB591E9A60B1BE88DEC7
+PT=BC528364EF78D6432177FE0CF1CDECD1
+CT=34CD9D96D4455AE0C15B6B970F1EC905
+
+I=205
+KEY=EF9AD4E74084D15BF0F98AB7F5F2B5BB
+IV=34CD9D96D4455AE0C15B6B970F1EC905
+PT=18972F6992299533EE23AA5824C25892
+CT=2E05E3E2079A055310FD9318590A6F41
+
+I=206
+KEY=C19F3705471ED408E00419AFACF8DAFA
+IV=2E05E3E2079A055310FD9318590A6F41
+PT=5441FF0D0A4062D5D0DF29BF2FDA85B4
+CT=47D4EAECE59C733EEFCB7B9D5BE95A98
+
+I=207
+KEY=864BDDE9A282A7360FCF6232F7118062
+IV=47D4EAECE59C733EEFCB7B9D5BE95A98
+PT=ED3E19B5AB5389AA3A58D97F6604F4C0
+CT=00525B7D5BFC0651AEF6770F6281E6DC
+
+I=208
+KEY=86198694F97EA167A139153D959066BE
+IV=00525B7D5BFC0651AEF6770F6281E6DC
+PT=8BD4869C88A9BD3DCFE89B98B93F6EB3
+CT=AFB2215E6DC04E9467F44227FD4BDB98
+
+I=209
+KEY=29ABA7CA94BEEFF3C6CD571A68DBBD26
+IV=AFB2215E6DC04E9467F44227FD4BDB98
+PT=6E7269FC27BDCC42D64CEF41A612F771
+CT=7B769B90279C95E31D8B3D792FA27FA8
+
+I=210
+KEY=52DD3C5AB3227A10DB466A634779C28E
+IV=7B769B90279C95E31D8B3D792FA27FA8
+PT=E00316E79DC10D179002B1BACC146027
+CT=E3870CDE5CF99B7C4C489AF81153002F
+
+I=211
+KEY=B15A3084EFDBE16C970EF09B562AC2A1
+IV=E3870CDE5CF99B7C4C489AF81153002F
+PT=FB2FC78A79C33225E6EAAA06B76FA793
+CT=4DFC91F8971635348EF35141E8C291F7
+
+I=212
+KEY=FCA6A17C78CDD45819FDA1DABEE85356
+IV=4DFC91F8971635348EF35141E8C291F7
+PT=69C8EE14F21832BB077F1A5414851FFE
+CT=DA51BE36F96AA8C80DED9DB2A701D72F
+
+I=213
+KEY=26F71F4A81A77C9014103C6819E98479
+IV=DA51BE36F96AA8C80DED9DB2A701D72F
+PT=766EC1664D2194E0F89B69861A4A8501
+CT=2ACA6359CD935CA2294F9FB5A50F4993
+
+I=214
+KEY=0C3D7C134C3420323D5FA3DDBCE6CDEA
+IV=2ACA6359CD935CA2294F9FB5A50F4993
+PT=1D95E551169BD538836CC349BC6B1772
+CT=315518F0AC6C1DC9939CB802336DA968
+
+I=215
+KEY=3D6864E3E0583DFBAEC31BDF8F8B6482
+IV=315518F0AC6C1DC9939CB802336DA968
+PT=4F6BFE727AECDAB5A32DF8CFFC43D6A9
+CT=34C3ECD89376B4D771CA0669C2C3E26C
+
+I=216
+KEY=09AB883B732E892CDF091DB64D4886EE
+IV=34C3ECD89376B4D771CA0669C2C3E26C
+PT=AA8B1DA2E015D482EE08FA2B4A2B77B6
+CT=A3F4DD9DDC375C90579C274527612C6E
+
+I=217
+KEY=AA5F55A6AF19D5BC88953AF36A29AA80
+IV=A3F4DD9DDC375C90579C274527612C6E
+PT=2EE6982D9E0AA5FCB61F3E66E52A0D6D
+CT=C45C9E4DE76782E2599BD73B132BFE90
+
+I=218
+KEY=6E03CBEB487E575ED10EEDC879025410
+IV=C45C9E4DE76782E2599BD73B132BFE90
+PT=6E58E5B1EDF1BFABAD643D8223F0FA81
+CT=32221DA62DA2B441B5E66A197A5C69F1
+
+I=219
+KEY=5C21D64D65DCE31F64E887D1035E3DE1
+IV=32221DA62DA2B441B5E66A197A5C69F1
+PT=D5A81DF4B6BE17A531478961D78CAB46
+CT=E1FEB5C31B1671F15DC1F7713E5DD7FE
+
+I=220
+KEY=BDDF638E7ECA92EE392970A03D03EA1F
+IV=E1FEB5C31B1671F15DC1F7713E5DD7FE
+PT=D360948141A1D3ECFF5E8D6BDC022685
+CT=FF07F02135FB458D63EE68C4B1463A99
+
+I=221
+KEY=42D893AF4B31D7635AC718648C45D086
+IV=FF07F02135FB458D63EE68C4B1463A99
+PT=E3C1E44333C9307E90EE2FBA6A7708A5
+CT=1AE4E8466B84B59EECF5E6BEB6140DF2
+
+I=222
+KEY=583C7BE920B562FDB632FEDA3A51DD74
+IV=1AE4E8466B84B59EECF5E6BEB6140DF2
+PT=653AA343CE35F72E2ADB5FFCD2DFCBA8
+CT=3CB44BC123DDCD55B812D265CC5E974E
+
+I=223
+KEY=648830280368AFA80E202CBFF60F4A3A
+IV=3CB44BC123DDCD55B812D265CC5E974E
+PT=E96A66BFE5F0E8083A01664A47226672
+CT=BB6C54E118FA895F2AC4CC036166E390
+
+I=224
+KEY=DFE464C91B9226F724E4E0BC9769A9AA
+IV=BB6C54E118FA895F2AC4CC036166E390
+PT=A5B240D8E5731E1BFA7C4FDFB4EED81F
+CT=DA20870677A6214F26FDACBA81B41882
+
+I=225
+KEY=05C4E3CF6C3407B802194C0616DDB128
+IV=DA20870677A6214F26FDACBA81B41882
+PT=92FF6EAB4A6D1AD3941E6A91D8C9105B
+CT=F079AA86FC9FD361DBA0C21CCD4B0F6C
+
+I=226
+KEY=F5BD494990ABD4D9D9B98E1ADB96BE44
+IV=F079AA86FC9FD361DBA0C21CCD4B0F6C
+PT=DFF005175EF746B83CB00AC13337E248
+CT=B6021E0AA1A921C7BCC3FDAB1C3EA44A
+
+I=227
+KEY=43BF57433102F51E657A73B1C7A81A0E
+IV=B6021E0AA1A921C7BCC3FDAB1C3EA44A
+PT=DDDC1AA804AD13813C6AEA540557C097
+CT=41F0E4AB03801DCE585727B7C41F48BD
+
+I=228
+KEY=024FB3E83282E8D03D2D540603B752B3
+IV=41F0E4AB03801DCE585727B7C41F48BD
+PT=4C6421E5A487C9C452958CAB38AC7098
+CT=6EFDD855BAF2D13437C01097ABB633DE
+
+I=229
+KEY=6CB26BBD887039E40AED4491A801616D
+IV=6EFDD855BAF2D13437C01097ABB633DE
+PT=2A11519D5463F2B96A5E0FCE6E4710D7
+CT=5E8243E5C54A109CCC0BF622A299EF68
+
+I=230
+KEY=323028584D3A2978C6E6B2B30A988E05
+IV=5E8243E5C54A109CCC0BF622A299EF68
+PT=252145DACAD23E8B85AB7637B22C42F2
+CT=2C9A476418F01C589ADC0CA10BF4A183
+
+I=231
+KEY=1EAA6F3C55CA35205C3ABE12016C2F86
+IV=2C9A476418F01C589ADC0CA10BF4A183
+PT=A22C36DC7D00645FEFE8683EA4231787
+CT=DA3A4AC19EF6A0F950E26B00834AFE41
+
+I=232
+KEY=C49025FDCB3C95D90CD8D5128226D1C7
+IV=DA3A4AC19EF6A0F950E26B00834AFE41
+PT=B0DC92D3B4878156B768923286F0433F
+CT=10BBC2A8C8F650FD8EED7CC9F5EAD05D
+
+I=233
+KEY=D42BE75503CAC5248235A9DB77CC019A
+IV=10BBC2A8C8F650FD8EED7CC9F5EAD05D
+PT=83A9338157091D4AECAF60E887AE09F7
+CT=757993A70F78B25F02FA0355E04DE27B
+
+I=234
+KEY=A15274F20CB2777B80CFAA8E9781E3E1
+IV=757993A70F78B25F02FA0355E04DE27B
+PT=9D818ACA2C753E7314F51699D3062031
+CT=E2E74C76C09516135876D54AFC940D80
+
+I=235
+KEY=43B53884CC276168D8B97FC46B15EE61
+IV=E2E74C76C09516135876D54AFC940D80
+PT=BDD36F881F8D1FC56780E291D1359EE1
+CT=22F76A2DB98544549DEA21FFCDC2B943
+
+I=236
+KEY=614252A975A2253C45535E3BA6D75722
+IV=22F76A2DB98544549DEA21FFCDC2B943
+PT=4C9C16802A4BB1202D4FAC9E76C57A43
+CT=166B0FF778D72B6102D6ADF990A70A23
+
+I=237
+KEY=77295D5E0D750E5D4785F3C236705D01
+IV=166B0FF778D72B6102D6ADF990A70A23
+PT=0045ECDDAA51EE6FDB226E2D9471F46C
+CT=D7724DC8A1413BC1B9D6F305794426F0
+
+I=238
+KEY=A05B1096AC34359CFE5300C74F347BF1
+IV=D7724DC8A1413BC1B9D6F305794426F0
+PT=25C55C60290DF3D0DC3274CD2AE0ED21
+CT=41F0196DFE0B1F664A107D12A6FF3D79
+
+I=239
+KEY=E1AB09FB523F2AFAB4437DD5E9CB4688
+IV=41F0196DFE0B1F664A107D12A6FF3D79
+PT=9A44454F7A335C89BEFF1D94D3FDB320
+CT=3F37D7ADFB9933FFBAC1F7D07F31046E
+
+I=240
+KEY=DE9CDE56A9A619050E828A0596FA42E6
+IV=3F37D7ADFB9933FFBAC1F7D07F31046E
+PT=03D7F09054233696BEF84AB8D5B77091
+CT=02D226A748153C27A723F02461FFF913
+
+I=241
+KEY=DC4EF8F1E1B32522A9A17A21F705BBF5
+IV=02D226A748153C27A723F02461FFF913
+PT=D5C82A6F048A2AA0E5CF4F1EDADD68B3
+CT=4BD7486C212E7F78228478BBF0A7AD3D
+
+I=242
+KEY=9799B09DC09D5A5A8B25029A07A216C8
+IV=4BD7486C212E7F78228478BBF0A7AD3D
+PT=936431AD9F800606240C33EAF661D3DA
+CT=3EFE00CA0A96AF4425E683512DAC0164
+
+I=243
+KEY=A967B057CA0BF51EAEC381CB2A0E17AC
+IV=3EFE00CA0A96AF4425E683512DAC0164
+PT=280DC27864BED0D548B5B4F9A7FA38DE
+CT=7023640C8D6B02F6C4C7E007C169C592
+
+I=244
+KEY=D944D45B4760F7E86A0461CCEB67D23E
+IV=7023640C8D6B02F6C4C7E007C169C592
+PT=CD0F58962915E5A514E5D6DA8BB868E8
+CT=D08419A75363E9622FAA09DB589915F1
+
+I=245
+KEY=09C0CDFC14031E8A45AE6817B3FEC7CF
+IV=D08419A75363E9622FAA09DB589915F1
+PT=09A6099FDDDBBC15EE79224B01C49DF0
+CT=6CDD2B0279D9DB3C71329C1BB2C24C2F
+
+I=246
+KEY=651DE6FE6DDAC5B6349CF40C013C8BE0
+IV=6CDD2B0279D9DB3C71329C1BB2C24C2F
+PT=B24B11FD8A6FC6B2703FFBEBC85B6C44
+CT=CCB0F6F32BDE2339A1842A7EDC8C99C7
+
+I=247
+KEY=A9AD100D4604E68F9518DE72DDB01227
+IV=CCB0F6F32BDE2339A1842A7EDC8C99C7
+PT=2E471506C55D1762CDB9EAEF29E23C01
+CT=DAD62227A5F328CC33F054EEB346E3D3
+
+I=248
+KEY=737B322AE3F7CE43A6E88A9C6EF6F1F4
+IV=DAD62227A5F328CC33F054EEB346E3D3
+PT=5598344020E32F9B2C509D06F4E7804A
+CT=18DE226F7CAA4EF2712A223C4709C9E2
+
+I=249
+KEY=6BA510459F5D80B1D7C2A8A029FF3816
+IV=18DE226F7CAA4EF2712A223C4709C9E2
+PT=549A87BE74B62BAC3F0FDC2A878F5669
+CT=DB082C8D70948B6BF08D4848E4DB0231
+
+I=250
+KEY=B0AD3CC8EFC90BDA274FE0E8CD243A27
+IV=DB082C8D70948B6BF08D4848E4DB0231
+PT=08946428BF90FBF0951A35D6FB72A48A
+CT=29CBD3E3F2074514E63A7B2A651AB031
+
+I=251
+KEY=9966EF2B1DCE4ECEC1759BC2A83E8A16
+IV=29CBD3E3F2074514E63A7B2A651AB031
+PT=7EBEC38F7787EE1BDD6A648334FA3076
+CT=0037935821278E879BCBB2FBE4ECC23E
+
+I=252
+KEY=99517C733CE9C0495ABE29394CD24828
+IV=0037935821278E879BCBB2FBE4ECC23E
+PT=01D77828928164A830C249D96AC6F8B4
+CT=47501831F9DF42C234E9FE9169075888
+
+I=253
+KEY=DE016442C536828B6E57D7A825D510A0
+IV=47501831F9DF42C234E9FE9169075888
+PT=608349FF8FFC31B072CFA7DF649E15B8
+CT=BC10B1D412BC05404B2E38A1D75DA421
+
+I=254
+KEY=6211D596D78A87CB2579EF09F288B481
+IV=BC10B1D412BC05404B2E38A1D75DA421
+PT=B16325BD78FC0451216FF476D4CAE293
+CT=6ABD8010E9CBAE61E05A9E30C622B501
+
+I=255
+KEY=08AC55863E4129AAC523713934AA0180
+IV=6ABD8010E9CBAE61E05A9E30C622B501
+PT=E613C244F74C61B078C9E59E06E7AD85
+CT=E896B8BD539C30D9A58E5EF6629B279C
+
+I=256
+KEY=E03AED3B6DDD197360AD2FCF5631261C
+IV=E896B8BD539C30D9A58E5EF6629B279C
+PT=6CFF7A909AAB2C0DC61FB8F11B45E661
+CT=30D15AAA05F56FA2D21E9974FB3FF5DA
+
+I=257
+KEY=D0EBB791682876D1B2B3B6BBAD0ED3C6
+IV=30D15AAA05F56FA2D21E9974FB3FF5DA
+PT=6BFAC8E8FB9C3D5AF813B4DF90AD863B
+CT=43B99F3DA3C1BCCE9038118E2968EFA1
+
+I=258
+KEY=935228ACCBE9CA1F228BA73584663C67
+IV=43B99F3DA3C1BCCE9038118E2968EFA1
+PT=064D09E9F5104602E191DC39F18E6A1A
+CT=EBC5796519BE4E05262A10D56FA0F72D
+
+I=259
+KEY=789751C9D257841A04A1B7E0EBC6CB4A
+IV=EBC5796519BE4E05262A10D56FA0F72D
+PT=C2B528D69ED3028A359D4472D98807A7
+CT=5F2B51DD025E775A63DFE5B9FBF54986
+
+I=260
+KEY=27BC0014D009F340677E5259103382CC
+IV=5F2B51DD025E775A63DFE5B9FBF54986
+PT=D5CF62940967AF7225F79E87136751F5
+CT=F56D88E433CEA445C6E4D6298DFB6C27
+
+I=261
+KEY=D2D188F0E3C75705A19A84709DC8EEEB
+IV=F56D88E433CEA445C6E4D6298DFB6C27
+PT=3BE3171202E762846D2CA00FB2CB141A
+CT=4C168A0129F2D48E249777A366D1AEF1
+
+I=262
+KEY=9EC702F1CA35838B850DF3D3FB19401A
+IV=4C168A0129F2D48E249777A366D1AEF1
+PT=5B82A34141C236FAED7E1A78D3C426C4
+CT=E11FEBEF79E425480442D45A8C105B44
+
+I=263
+KEY=7FD8E91EB3D1A6C3814F278977091B5E
+IV=E11FEBEF79E425480442D45A8C105B44
+PT=86CFADD3F1B368B3A6E57148CA343D38
+CT=5F5F3548BDBB2A5337FBF07DF76526DD
+
+I=264
+KEY=2087DC560E6A8C90B6B4D7F4806C3D83
+IV=5F5F3548BDBB2A5337FBF07DF76526DD
+PT=A4474ACA97100C7A357A66119D678798
+CT=013ADA262021F88617773CF478067EC8
+
+I=265
+KEY=21BD06702E4B7416A1C3EB00F86A434B
+IV=013ADA262021F88617773CF478067EC8
+PT=6D66801C39DB803B5DA5A80E30DB0D89
+CT=F46BE70F65FC5641318292AE0C79E5C5
+
+I=266
+KEY=D5D6E17F4BB72257904179AEF413A68E
+IV=F46BE70F65FC5641318292AE0C79E5C5
+PT=C9499B32D8F47313EB351139DB81AB25
+CT=8573A25F86C7784BF7A0153DF812805C
+
+I=267
+KEY=50A54320CD705A1C67E16C930C0126D2
+IV=8573A25F86C7784BF7A0153DF812805C
+PT=4B09D37A4A57B320C34B1D70F74EB36A
+CT=036913128A2B71CE3D05D52D61E48E86
+
+I=268
+KEY=53CC5032475B2BD25AE4B9BE6DE5A854
+IV=036913128A2B71CE3D05D52D61E48E86
+PT=EA3A92794B204C0345765CEE2A04AF27
+CT=5A53E929182859CC28D4EB1CB9579B71
+
+I=269
+KEY=099FB91B5F73721E723052A2D4B23325
+IV=5A53E929182859CC28D4EB1CB9579B71
+PT=2714E38858426C5631BB2BB4FA289985
+CT=DF4BD734DEC60475D47FE40502439AAE
+
+I=270
+KEY=D6D46E2F81B5766BA64FB6A7D6F1A98B
+IV=DF4BD734DEC60475D47FE40502439AAE
+PT=69AC3FD2273926E2DAD3F5BED9F21491
+CT=EBCCD0B121C4009EA7F038F30F5B6B05
+
+I=271
+KEY=3D18BE9EA07176F501BF8E54D9AAC28E
+IV=EBCCD0B121C4009EA7F038F30F5B6B05
+PT=07520CD471E27BAC35387DB47E706784
+CT=299FE603BBA51BD1582CBD42BC9568EA
+
+I=272
+KEY=1487589D1BD46D2459933316653FAA64
+IV=299FE603BBA51BD1582CBD42BC9568EA
+PT=39598B70B8EB190049823472E3596E42
+CT=68DD98FE52B454F85D6F6A6C742223FA
+
+I=273
+KEY=7C5AC063496039DC04FC597A111D899E
+IV=68DD98FE52B454F85D6F6A6C742223FA
+PT=C7E13ABBBA75F527AB1320DD930B24F1
+CT=906B569E44263A4E6F41A52802D3FC59
+
+I=274
+KEY=EC3196FD0D4603926BBDFC5213CE75C7
+IV=906B569E44263A4E6F41A52802D3FC59
+PT=9F5D8E50F06895D5D7E6D1DAA247D45F
+CT=E5ECBDCC55A9D952BE0F93DFA0FE2C31
+
+I=275
+KEY=09DD2B3158EFDAC0D5B26F8DB33059F6
+IV=E5ECBDCC55A9D952BE0F93DFA0FE2C31
+PT=EC3F35C1E6371F106443BD1446D58A0A
+CT=4837A3D703E80BFE50D742E378956F3A
+
+I=276
+KEY=41EA88E65B07D13E85652D6ECBA536CC
+IV=4837A3D703E80BFE50D742E378956F3A
+PT=7998C3B7B5C94540DFC5BF777D700D48
+CT=DF1564E5E47503A779020D27394571E9
+
+I=277
+KEY=9EFFEC03BF72D299FC672049F2E04725
+IV=DF1564E5E47503A779020D27394571E9
+PT=63BEA75A2440C5D123F335F72137B0B6
+CT=5147239C3F6E4A158989BE96C0275D41
+
+I=278
+KEY=CFB8CF9F801C988C75EE9EDF32C71A64
+IV=5147239C3F6E4A158989BE96C0275D41
+PT=09C656A0DFCF893DDBE5E2B3D88E5F1F
+CT=7E4DEE30DED62EE15CD957530B62559D
+
+I=279
+KEY=B1F521AF5ECAB66D2937C98C39A54FF9
+IV=7E4DEE30DED62EE15CD957530B62559D
+PT=71DC22F489DD422CDE09F01DAA427567
+CT=6F62D6359F07F6BDBB4C02BBE50B273C
+
+I=280
+KEY=DE97F79AC1CD40D0927BCB37DCAE68C5
+IV=6F62D6359F07F6BDBB4C02BBE50B273C
+PT=C2A9BC94CAE48DBEB37B4B506AD4336A
+CT=902D9E9F82DE4E66E42B4FEA79AF4077
+
+I=281
+KEY=4EBA690543130EB6765084DDA50128B2
+IV=902D9E9F82DE4E66E42B4FEA79AF4077
+PT=69EE7E15EEC2EA953A32E1714961BA9E
+CT=72CB5DE8AF6CDC60A00A15CEAF249DBD
+
+I=282
+KEY=3C7134EDEC7FD2D6D65A91130A25B50F
+IV=72CB5DE8AF6CDC60A00A15CEAF249DBD
+PT=4C0A3B88FDFAEFEC38858A927C38AE6A
+CT=68C2BFA5DE837B927BD75C6DE6008595
+
+I=283
+KEY=54B38B4832FCA944AD8DCD7EEC25309A
+IV=68C2BFA5DE837B927BD75C6DE6008595
+PT=CE75CCA2D7B0199EB1DA7E33A0E50AB7
+CT=4FFCCBB31FB1FCC0FCB38F0B557BE67A
+
+I=284
+KEY=1B4F40FB2D4D5584513E4275B95ED6E0
+IV=4FFCCBB31FB1FCC0FCB38F0B557BE67A
+PT=E0ECA2ABC1F389B149E746CFB039539E
+CT=249FB11DF8C0ED1F346F6D69B8FD0470
+
+I=285
+KEY=3FD0F1E6D58DB89B65512F1C01A3D290
+IV=249FB11DF8C0ED1F346F6D69B8FD0470
+PT=BFA871CA5EC16C0B353679782BE04394
+CT=8127E6D8EEC1111518065EDC34CD4B4C
+
+I=286
+KEY=BEF7173E3B4CA98E7D5771C0356E99DC
+IV=8127E6D8EEC1111518065EDC34CD4B4C
+PT=1EF816C565B2F56E772C96AD5C92842D
+CT=C8DC75AE1E2DBD005D94E69D6776C498
+
+I=287
+KEY=762B62902561148E20C3975D52185D44
+IV=C8DC75AE1E2DBD005D94E69D6776C498
+PT=9F2B9873F88EBF21A3BB3DCD853C812E
+CT=861D4FF061E85D44173252244F143692
+
+I=288
+KEY=F0362D60448949CA37F1C5791D0C6BD6
+IV=861D4FF061E85D44173252244F143692
+PT=6CDEA8A806516A1A0E1CBB5AA123862A
+CT=16DA4EE5C5044F66EFCC313754FBCD9E
+
+I=289
+KEY=E6EC6385818D06ACD83DF44E49F7A648
+IV=16DA4EE5C5044F66EFCC313754FBCD9E
+PT=5B637BB469073B5E54EC006F47C4D546
+CT=C2C50037BBBEC252B7D5CF10C38BD665
+
+I=290
+KEY=242963B23A33C4FE6FE83B5E8A7C702D
+IV=C2C50037BBBEC252B7D5CF10C38BD665
+PT=38DADBF2BA4A80A6A190D9E2AA245167
+CT=721222A5A67E96246DA1B9C59B67DDD5
+
+I=291
+KEY=563B41179C4D52DA0249829B111BADF8
+IV=721222A5A67E96246DA1B9C59B67DDD5
+PT=CB52378F6E4E7FCB1891D3BB4D086B9F
+CT=D28B8F54E8BDA9A20965984D5DA27FC9
+
+I=292
+KEY=84B0CE4374F0FB780B2C1AD64CB9D231
+IV=D28B8F54E8BDA9A20965984D5DA27FC9
+PT=E66015A1B848EF190F981DEFEDB98C93
+CT=012C5D9B847C9583B0BE03999D24E277
+
+I=293
+KEY=859C93D8F08C6EFBBB92194FD19D3046
+IV=012C5D9B847C9583B0BE03999D24E277
+PT=F5B2BAD53323A52A2B99CC12782CD6F9
+CT=D1EFB7E7A34F75887038FC4827E894C1
+
+I=294
+KEY=5473243F53C31B73CBAAE507F675A487
+IV=D1EFB7E7A34F75887038FC4827E894C1
+PT=11C0C41C3F547B5D7FC94115327AB3D5
+CT=2CF97D8995AA8FDC4C05205D3D8B757F
+
+I=295
+KEY=788A59B6C66994AF87AFC55ACBFED1F8
+IV=2CF97D8995AA8FDC4C05205D3D8B757F
+PT=3F911029D8B69CA1A323A277090B9C07
+CT=44BB04C6253F3ADD454264EA97490475
+
+I=296
+KEY=3C315D70E356AE72C2EDA1B05CB7D58D
+IV=44BB04C6253F3ADD454264EA97490475
+PT=9D7724EFD1AE76904458EF1360953AA4
+CT=5D6F876E4FDD6921B243EB1F6EF50F82
+
+I=297
+KEY=615EDA1EAC8BC75370AE4AAF3242DA0F
+IV=5D6F876E4FDD6921B243EB1F6EF50F82
+PT=44A26554FE355D95706431B344701B03
+CT=5F3226B39DF230163D2C474F04BAD36E
+
+I=298
+KEY=3E6CFCAD3179F7454D820DE036F80961
+IV=5F3226B39DF230163D2C474F04BAD36E
+PT=5D8B62C8CD3B04451A599989F3165530
+CT=A247CF8E1D8F480DA4155DA846A2B64E
+
+I=299
+KEY=9C2B33232CF6BF48E9975048705ABF2F
+IV=A247CF8E1D8F480DA4155DA846A2B64E
+PT=610D3798E62E9338D5987BAC82D48CD7
+CT=2A92B5AAEA43CFBAA62842DEE7F43A19
+
+I=300
+KEY=B6B98689C6B570F24FBF129697AE8536
+IV=2A92B5AAEA43CFBAA62842DEE7F43A19
+PT=F77943AA429BCCC5253156474E719389
+CT=7D475AFF824080E9C95D4E49D4F5090D
+
+I=301
+KEY=CBFEDC7644F5F01B86E25CDF435B8C3B
+IV=7D475AFF824080E9C95D4E49D4F5090D
+PT=5E6269D157164B2C544D3052E9DB8553
+CT=AD4628B05F5A765E557015B4A41505EA
+
+I=302
+KEY=66B8F4C61BAF8645D392496BE74E89D1
+IV=AD4628B05F5A765E557015B4A41505EA
+PT=77126BD6C08A094981FEC9E2DE91B2BF
+CT=59C24F269E3884A4F8E3F9FB05BF448F
+
+I=303
+KEY=3F7ABBE0859702E12B71B090E2F1CD5E
+IV=59C24F269E3884A4F8E3F9FB05BF448F
+PT=7775F90D2189E91B75AB8AD93C0D44F2
+CT=B72873115D4761B8BAEB5B5892B79DF8
+
+I=304
+KEY=8852C8F1D8D06359919AEBC8704650A6
+IV=B72873115D4761B8BAEB5B5892B79DF8
+PT=03D9C45A2A152ADAA53E1D42AB33555B
+CT=FE0C3F22E6B467DC1C628C928D03DB5B
+
+I=305
+KEY=765EF7D33E6404858DF8675AFD458BFD
+IV=FE0C3F22E6B467DC1C628C928D03DB5B
+PT=279791AC4189634A6066BCDCAA2EF9B4
+CT=7F3ABBA943C8E3EF19C3BA2C98C9685F
+
+I=306
+KEY=09644C7A7DACE76A943BDD76658CE3A2
+IV=7F3ABBA943C8E3EF19C3BA2C98C9685F
+PT=E46E5FB6019BA52524A383A18A89583A
+CT=C96D250343B134241221490AB39931DB
+
+I=307
+KEY=C00969793E1DD34E861A947CD615D279
+IV=C96D250343B134241221490AB39931DB
+PT=A3A544B8982C2F9EA0CD0ABC4D6392E2
+CT=951D54AABDF6F5B70E700C4896EB2685
+
+I=308
+KEY=55143DD383EB26F9886A983440FEF4FC
+IV=951D54AABDF6F5B70E700C4896EB2685
+PT=43FEB2051478A02BA1F054C9E82F0209
+CT=1F90165BE29C6C86D09AD07B1C006CA6
+
+I=309
+KEY=4A842B8861774A7F58F0484F5CFE985A
+IV=1F90165BE29C6C86D09AD07B1C006CA6
+PT=558AD95B25BAB5205FB7E529C96E5B59
+CT=40C0A0427C12AB1F72A7ADF96F82D437
+
+I=310
+KEY=0A448BCA1D65E1602A57E5B6337C4C6D
+IV=40C0A0427C12AB1F72A7ADF96F82D437
+PT=BABA13A1244DEFF5E4A2AB8183775773
+CT=FB08FDF3BF4394BA1A92C45B7F5F3060
+
+I=311
+KEY=F14C7639A22675DA30C521ED4C237C0D
+IV=FB08FDF3BF4394BA1A92C45B7F5F3060
+PT=46E036ECCDBE88931E552E45CBBC2BDC
+CT=311AE8C2B7CB633178874BDEEEE0602F
+
+I=312
+KEY=C0569EFB15ED16EB48426A33A2C31C22
+IV=311AE8C2B7CB633178874BDEEEE0602F
+PT=4D5C919959478AD0D9862BA509233102
+CT=1DC85D9A8877C79698C7D1C1610CBAE9
+
+I=313
+KEY=DD9EC3619D9AD17DD085BBF2C3CFA6CB
+IV=1DC85D9A8877C79698C7D1C1610CBAE9
+PT=D423E31E9FD6E4F4373FA7AD31CC6011
+CT=FC55E7BEA15BD539EDACB202F0218D4A
+
+I=314
+KEY=21CB24DF3CC104443D2909F033EE2B81
+IV=FC55E7BEA15BD539EDACB202F0218D4A
+PT=52C2C696A4343C0F280A3BC8F6AA19EA
+CT=FFD9FECD3A4EC194568A96C5A899E8D2
+
+I=315
+KEY=DE12DA12068FC5D06BA39F359B77C353
+IV=FFD9FECD3A4EC194568A96C5A899E8D2
+PT=3B2266FAB514211E8E33AFA566898083
+CT=DC1A545F354365A0002180BACCE0AD25
+
+I=316
+KEY=02088E4D33CCA0706B821F8F57976E76
+IV=DC1A545F354365A0002180BACCE0AD25
+PT=DC20E6BD8B8AC822CF2B505E580E6A80
+CT=51CF4C11F15B8B565B875F769C2FD37F
+
+I=317
+KEY=53C7C25CC2972B26300540F9CBB8BD09
+IV=51CF4C11F15B8B565B875F769C2FD37F
+PT=67B4C3E2AFC3402901549265186303FB
+CT=A118B7E5B10DAB4DDB449877AB1E6897
+
+I=318
+KEY=F2DF75B9739A806BEB41D88E60A6D59E
+IV=A118B7E5B10DAB4DDB449877AB1E6897
+PT=971952EE322CD68462B4CE8B772BBA48
+CT=A2988AAC94D8A7EFB32B34CC07911F3E
+
+I=319
+KEY=5047FF15E7422784586AEC426737CAA0
+IV=A2988AAC94D8A7EFB32B34CC07911F3E
+PT=64C2665506EDDED98EC55D2CCED7762C
+CT=86AEB7B90565D05293A8D9146880C307
+
+I=320
+KEY=D6E948ACE227F7D6CBC235560FB709A7
+IV=86AEB7B90565D05293A8D9146880C307
+PT=A5E7E411209DD2A34AA8CDA3153A69E4
+CT=27746442FAC1DF26B11A55251AAFD865
+
+I=321
+KEY=F19D2CEE18E628F07AD860731518D1C2
+IV=27746442FAC1DF26B11A55251AAFD865
+PT=83A41EF5F664A909BC47939D7858C221
+CT=619A164C3F2119FFCA3832A5EA958E01
+
+I=322
+KEY=90073AA227C7310FB0E052D6FF8D5FC3
+IV=619A164C3F2119FFCA3832A5EA958E01
+PT=1F5A31EBB2C515728DB07EE3160D03CD
+CT=DEE1692D386EF5A8861BE5D8A4630906
+
+I=323
+KEY=4EE6538F1FA9C4A736FBB70E5BEE56C5
+IV=DEE1692D386EF5A8861BE5D8A4630906
+PT=297B343F5EE6221FB6CC40E0C836B387
+CT=B2BA45B0A776A950C32DD5F302201FC3
+
+I=324
+KEY=FC5C163FB8DF6DF7F5D662FD59CE4906
+IV=B2BA45B0A776A950C32DD5F302201FC3
+PT=CC3601DC94B13116DF3012860A522D2D
+CT=6D141746B23B4E1EF20DFE6C14D6ECE4
+
+I=325
+KEY=914801790AE423E907DB9C914D18A5E2
+IV=6D141746B23B4E1EF20DFE6C14D6ECE4
+PT=FE07DA9A6E8B712B1FDFC3C1CC87146D
+CT=0D80E8F5557A88A271133F8929125C72
+
+I=326
+KEY=9CC8E98C5F9EAB4B76C8A318640AF990
+IV=0D80E8F5557A88A271133F8929125C72
+PT=EBDC0192755A685D6275532E93D33890
+CT=B88A629A8E22A78BAF98C9E623F48134
+
+I=327
+KEY=24428B16D1BC0CC0D9506AFE47FE78A4
+IV=B88A629A8E22A78BAF98C9E623F48134
+PT=78AD3067BE2E9536ADB58DA49D7CA6DA
+CT=0A9C2D318240F4FA4FF91CC5D23A371F
+
+I=328
+KEY=2EDEA62753FCF83A96A9763B95C44FBB
+IV=0A9C2D318240F4FA4FF91CC5D23A371F
+PT=04C72A08CCC36B4211AFE98637C4CEFF
+CT=A42618A89B9E618DDD7A983081E086B9
+
+I=329
+KEY=8AF8BE8FC86299B74BD3EE0B1424C902
+IV=A42618A89B9E618DDD7A983081E086B9
+PT=22D4A346027B8E5FEE1C0C0C45CA7DCB
+CT=7CC4479AE05A295723F27545E1A46B7B
+
+I=330
+KEY=F63CF9152838B0E068219B4EF580A279
+IV=7CC4479AE05A295723F27545E1A46B7B
+PT=05090A5C8F3CD0E7F7EA11B33CDF3C1D
+CT=815BCEB2A29EA2A491C8E39B117790EC
+
+I=331
+KEY=776737A78AA61244F9E978D5E4F73295
+IV=815BCEB2A29EA2A491C8E39B117790EC
+PT=7B40F8A4AC0E4C6BD73A59FFC91CA77D
+CT=E4ED412F3ECDD4B7409BEEAEDC2C755F
+
+I=332
+KEY=938A7688B46BC6F3B972967B38DB47CA
+IV=E4ED412F3ECDD4B7409BEEAEDC2C755F
+PT=047E2E4681A97ED20308F1FE4B132F7B
+CT=10153209AED4115329587180D65A0B97
+
+I=333
+KEY=839F44811ABFD7A0902AE7FBEE814C5D
+IV=10153209AED4115329587180D65A0B97
+PT=32671E6C0D28744AB457587BBB6DD21E
+CT=847F781EDF77A870C4EA99CCC1721917
+
+I=334
+KEY=07E03C9FC5C87FD054C07E372FF3554A
+IV=847F781EDF77A870C4EA99CCC1721917
+PT=EC3159B002B95054F00D57049D91E32B
+CT=05CC06529764F6747FCB2B62569C428C
+
+I=335
+KEY=022C3ACD52AC89A42B0B5555796F17C6
+IV=05CC06529764F6747FCB2B62569C428C
+PT=9A930743113957D10EC643D8D8034C73
+CT=D1C7957073C2A44D9483DD11F3FA2B1E
+
+I=336
+KEY=D3EBAFBD216E2DE9BF8888448A953CD8
+IV=D1C7957073C2A44D9483DD11F3FA2B1E
+PT=2E061A5B483D0D834D3019954E54CF80
+CT=0AC3300C59DB7A76A1E16DC5BF167B70
+
+I=337
+KEY=D9289FB178B5579F1E69E581358347A8
+IV=0AC3300C59DB7A76A1E16DC5BF167B70
+PT=2A6E00DF7820913341D26EF611A7BEC1
+CT=5A5A1BE396D3C56DB0690B92A925D8D8
+
+I=338
+KEY=83728452EE6692F2AE00EE139CA69F70
+IV=5A5A1BE396D3C56DB0690B92A925D8D8
+PT=E871C79BA6132F15C80A85F4BC732E77
+CT=829ABA07496E1269437680257308029D
+
+I=339
+KEY=01E83E55A708809BED766E36EFAE9DED
+IV=829ABA07496E1269437680257308029D
+PT=5955643AB76251E6AF97BC2490D09A72
+CT=3FEDBF80B703D067126EF55B02A41175
+
+I=340
+KEY=3E0581D5100B50FCFF189B6DED0A8C98
+IV=3FEDBF80B703D067126EF55B02A41175
+PT=32BCF86ECA6CCE8F9C1C87AD9FDF8238
+CT=B59D6C5FCA91EDBFE75E795638CAD286
+
+I=341
+KEY=8B98ED8ADA9ABD431846E23BD5C05E1E
+IV=B59D6C5FCA91EDBFE75E795638CAD286
+PT=01A08051FC1D98C1BDAE4CA1D41D91E6
+CT=21CB8EF8BBE6C371A26BFF92701C3D1A
+
+I=342
+KEY=AA536372617C7E32BA2D1DA9A5DC6304
+IV=21CB8EF8BBE6C371A26BFF92701C3D1A
+PT=5F5D891DF8D595D3FEDAEF0174B0A1D1
+CT=23D0FB6489113D3D4AA6470210698391
+
+I=343
+KEY=89839816E86D430FF08B5AABB5B5E095
+IV=23D0FB6489113D3D4AA6470210698391
+PT=54FEAB37EFCD36D28E943DD85E803812
+CT=45F0556ED9A8ED0E1C8B0A0BA648E069
+
+I=344
+KEY=CC73CD7831C5AE01EC0050A013FD00FC
+IV=45F0556ED9A8ED0E1C8B0A0BA648E069
+PT=7AF4BC398ACAD37F526BDE12F3ED59ED
+CT=C41E115EE06FFE5DED10480A1BE5B720
+
+I=345
+KEY=086DDC26D1AA505C011018AA0818B7DC
+IV=C41E115EE06FFE5DED10480A1BE5B720
+PT=CF15E4B6DDF60A4EE0CB6CBFA8AD499B
+CT=1098A41E2C97C9D70626E4D1841F5CC1
+
+I=346
+KEY=18F57838FD3D998B0736FC7B8C07EB1D
+IV=1098A41E2C97C9D70626E4D1841F5CC1
+PT=BAD4050A0013AB8BC556F367AB634D94
+CT=D9B58211EB935246A5E04FCD3BE10B54
+
+I=347
+KEY=C140FA2916AECBCDA2D6B3B6B7E6E049
+IV=D9B58211EB935246A5E04FCD3BE10B54
+PT=CEFF0AF7EF4EA7EF3B0E8BF7FB756E77
+CT=50FAE8C770EF7F9D5FE93B090B9D5C66
+
+I=348
+KEY=91BA12EE6641B450FD3F88BFBC7BBC2F
+IV=50FAE8C770EF7F9D5FE93B090B9D5C66
+PT=3B8C412B4156B413AD06CB181B4C5EAA
+CT=E47249D4B5F24FF415B0E669EBF471B1
+
+I=349
+KEY=75C85B3AD3B3FBA4E88F6ED6578FCD9E
+IV=E47249D4B5F24FF415B0E669EBF471B1
+PT=56C612C5C594CAFB7B1CE8131E786DF0
+CT=6AF057199C217EECB886D940F61B91C5
+
+I=350
+KEY=1F380C234F9285485009B796A1945C5B
+IV=6AF057199C217EECB886D940F61B91C5
+PT=5629EF768743AB63D5B79B511C0A6BEF
+CT=A5A76C330984D34310D021A6C2BDE9BC
+
+I=351
+KEY=BA9F60104616560B40D996306329B5E7
+IV=A5A76C330984D34310D021A6C2BDE9BC
+PT=ED8DF427A02692C09D7AAEF2EDAA1249
+CT=8AAEFBA5DE0AAA41D947E3238B279913
+
+I=352
+KEY=30319BB5981CFC4A999E7513E80E2CF4
+IV=8AAEFBA5DE0AAA41D947E3238B279913
+PT=949339605F30310FC557F2CA4815B034
+CT=9408BCB67EA573E7B5359B67918C16B9
+
+I=353
+KEY=A4392703E6B98FAD2CABEE7479823A4D
+IV=9408BCB67EA573E7B5359B67918C16B9
+PT=03607642CBBCCA2134837AC4BB452682
+CT=90660AF3DD0EAC1B61BB60EB49408586
+
+I=354
+KEY=345F2DF03BB723B64D108E9F30C2BFCB
+IV=90660AF3DD0EAC1B61BB60EB49408586
+PT=DE00E32930E14BD4297F9D789D0C25A1
+CT=1C48AC020174C0D87443229C113E2838
+
+I=355
+KEY=281781F23AC3E36E3953AC0321FC97F3
+IV=1C48AC020174C0D87443229C113E2838
+PT=9CA7A04855F8404176D7D30B594B65AC
+CT=7ACCB3FD4F9C7A5BFB83A969EB6D211A
+
+I=356
+KEY=52DB320F755F9935C2D0056ACA91B6E9
+IV=7ACCB3FD4F9C7A5BFB83A969EB6D211A
+PT=DC0B392E998A347ECB789A51A09F1B1D
+CT=22BED79EF2CAFF83BE8CEE5D7001DE21
+
+I=357
+KEY=7065E591879566B67C5CEB37BA9068C8
+IV=22BED79EF2CAFF83BE8CEE5D7001DE21
+PT=07210334590A9314031D98F7DFBB84B9
+CT=44B16879886BC331407D1E7C7F247A04
+
+I=358
+KEY=34D48DE80FFEA5873C21F54BC5B412CC
+IV=44B16879886BC331407D1E7C7F247A04
+PT=27DDF18405E56989E59ED442C8825DD6
+CT=2787AD57159450916A45C72D0E074D53
+
+I=359
+KEY=135320BF1A6AF51656643266CBB35F9F
+IV=2787AD57159450916A45C72D0E074D53
+PT=4F43202A454BB0F3A9440DA558BEE228
+CT=3C1B83C66CEEEB27644BC66ACC3117E8
+
+I=360
+KEY=2F48A37976841E31322FF40C07824877
+IV=3C1B83C66CEEEB27644BC66ACC3117E8
+PT=28ED6A88BDE4ADEFDA5C0F629109A7A3
+CT=B6009481F8C5D3EE37C645CF238238A1
+
+I=361
+KEY=994837F88E41CDDF05E9B1C3240070D6
+IV=B6009481F8C5D3EE37C645CF238238A1
+PT=48DC5A3700CD4A7A9B066DC0E2667544
+CT=C1A20854601D7A81CAC51E9237BDC030
+
+I=362
+KEY=58EA3FACEE5CB75ECF2CAF5113BDB0E6
+IV=C1A20854601D7A81CAC51E9237BDC030
+PT=1F84C71120B50FDF715B60DB69DECBE0
+CT=663EDB4EFD3F6AC2259A43C926ACE66D
+
+I=363
+KEY=3ED4E4E21363DD9CEAB6EC983511568B
+IV=663EDB4EFD3F6AC2259A43C926ACE66D
+PT=D6F9C59367A57E1DBDC2F4627524BC9A
+CT=CA84A10F987212D75B744A7966ABBABA
+
+I=364
+KEY=F45045ED8B11CF4BB1C2A6E153BAEC31
+IV=CA84A10F987212D75B744A7966ABBABA
+PT=1D8BC84060844CE5C40C716F2190C2BB
+CT=ABAEEB339C4D150E894392444E021710
+
+I=365
+KEY=5FFEAEDE175CDA45388134A51DB8FB21
+IV=ABAEEB339C4D150E894392444E021710
+PT=1300843AABCFB110198F0F0102C0A4D5
+CT=DBA9A1F8EE9AB8300D0273F71EAC5D1C
+
+I=366
+KEY=84570F26F9C66275358347520314A63D
+IV=DBA9A1F8EE9AB8300D0273F71EAC5D1C
+PT=1EA11B05D7DA9D770BA9AB619267B7A3
+CT=4921F1CB4A9AA6594C205D8FF0B2DEC9
+
+I=367
+KEY=CD76FEEDB35CC42C79A31ADDF3A678F4
+IV=4921F1CB4A9AA6594C205D8FF0B2DEC9
+PT=9ABA414156563E88A8CCDB3BD226F66C
+CT=4CF623AC6E145E2D61CAD28BFBF1F1E5
+
+I=368
+KEY=8180DD41DD489A011869C85608578911
+IV=4CF623AC6E145E2D61CAD28BFBF1F1E5
+PT=FEF20625FA0C788DB8A20298F6933F6F
+CT=67C491A5CA1A065980BDECE44B7979F1
+
+I=369
+KEY=E6444CE417529C5898D424B2432EF0E0
+IV=67C491A5CA1A065980BDECE44B7979F1
+PT=79C4A475D0E064D72D48AF6357A0E6A0
+CT=529766CDD1223ED05C055108F91E6526
+
+I=370
+KEY=B4D32A29C670A288C4D175BABA3095C6
+IV=529766CDD1223ED05C055108F91E6526
+PT=0758AA9195AE8684B9FEEBEF8E1226AE
+CT=2AEC009219ECD0499DD729352C220E7D
+
+I=371
+KEY=9E3F2ABBDF9C72C159065C8F96129BBB
+IV=2AEC009219ECD0499DD729352C220E7D
+PT=886713433798AB16E87A8AD3A8CD0C87
+CT=0DE2A7554E343B6FFC6D1ECF4A8AF0DD
+
+I=372
+KEY=93DD8DEE91A849AEA56B4240DC986B66
+IV=0DE2A7554E343B6FFC6D1ECF4A8AF0DD
+PT=984E8BA3DFFB4E9A1244D65BEA7DC594
+CT=8111340B4AF2CD82FF15447143069276
+
+I=373
+KEY=12CCB9E5DB5A842C5A7E06319F9EF910
+IV=8111340B4AF2CD82FF15447143069276
+PT=A4F6C8ACF4F1050D11E42FEF1B6C8B68
+CT=BB4693FA1399583EACB21D2675E6D156
+
+I=374
+KEY=A98A2A1FC8C3DC12F6CC1B17EA782846
+IV=BB4693FA1399583EACB21D2675E6D156
+PT=C5DBE1A937D6EA2FDD9A1A2FD25217B9
+CT=BC01B078339637D796F822B7E58D968D
+
+I=375
+KEY=158B9A67FB55EBC5603439A00FF5BECB
+IV=BC01B078339637D796F822B7E58D968D
+PT=DBD0494B0FE3149F8BCB8A70D344E811
+CT=600C1EFBDCA314A6F9714DEE413B9BD2
+
+I=376
+KEY=7587849C27F6FF639945744E4ECE2519
+IV=600C1EFBDCA314A6F9714DEE413B9BD2
+PT=FCA88DCB484317D7F886E7437BC9E669
+CT=2E3788A647105DD0A286E2EFFD469C99
+
+I=377
+KEY=5BB00C3A60E6A2B33BC396A1B388B980
+IV=2E3788A647105DD0A286E2EFFD469C99
+PT=65AF28E41B3DA5ACE3B2CC9A25EAD28C
+CT=5411E48B57058A52C8560423BCFFBCD2
+
+I=378
+KEY=0FA1E8B137E328E1F39592820F770552
+IV=5411E48B57058A52C8560423BCFFBCD2
+PT=6DD82A9F1CF0A5134A76899B04BE37D5
+CT=C3F69C8ED682BF252D5119D1695126E1
+
+I=379
+KEY=CC57743FE16197C4DEC48B53662623B3
+IV=C3F69C8ED682BF252D5119D1695126E1
+PT=DE729AB3803144FD958D8597396BC8ED
+CT=0941B78975FD2945B4AA81E8C58E3CB2
+
+I=380
+KEY=C516C3B6949CBE816A6E0ABBA3A81F01
+IV=0941B78975FD2945B4AA81E8C58E3CB2
+PT=D8404E7A17254EB40683A8919A9563B4
+CT=BF647E0346C013E138A2F0B06E7BB142
+
+I=381
+KEY=7A72BDB5D25CAD6052CCFA0BCDD3AE43
+IV=BF647E0346C013E138A2F0B06E7BB142
+PT=214089EC2996CE9FA2BBFEFBCAC03509
+CT=AFDA67B9451FF758CC87BBD93C7D4BE4
+
+I=382
+KEY=D5A8DA0C97435A389E4B41D2F1AEE5A7
+IV=AFDA67B9451FF758CC87BBD93C7D4BE4
+PT=9406E9D4FB4592A609BBDB23CE5F9D7F
+CT=B18202E4CA510695540371A8B6523616
+
+I=383
+KEY=642AD8E85D125CADCA48307A47FCD3B1
+IV=B18202E4CA510695540371A8B6523616
+PT=FEE45BE0503B4093747AFCEA9881D30D
+CT=64E149A4A1840F93D675B041ED81D45A
+
+I=384
+KEY=00CB914CFC96533E1C3D803BAA7D07EB
+IV=64E149A4A1840F93D675B041ED81D45A
+PT=880368D5609350167C7826DA30DCFF59
+CT=65A363E9837DFBBDA2688E6F4FBE6C35
+
+I=385
+KEY=6568F2A57FEBA883BE550E54E5C36BDE
+IV=65A363E9837DFBBDA2688E6F4FBE6C35
+PT=29C5940D09A8723B441FC469C909813A
+CT=2A47FDF5BF600891DF4D9E8AA34748BA
+
+I=386
+KEY=4F2F0F50C08BA012611890DE46842364
+IV=2A47FDF5BF600891DF4D9E8AA34748BA
+PT=20AF0FF7BAC0F468C12BD2816A8B1620
+CT=68A637E4B94EC150C84A6EBB005BB79B
+
+I=387
+KEY=278938B479C56142A952FE6546DF94FF
+IV=68A637E4B94EC150C84A6EBB005BB79B
+PT=42906D013A3F0A426B01B489ECA6CAD7
+CT=A090CA02FCD40F01CA0D1A699E30C164
+
+I=388
+KEY=8719F2B685116E43635FE40CD8EF559B
+IV=A090CA02FCD40F01CA0D1A699E30C164
+PT=05A02D4D7D90BCA74ECE791CD865CB88
+CT=F70109F0EBBA56959B3013565E2BDFFC
+
+I=389
+KEY=7018FB466EAB38D6F86FF75A86C48A67
+IV=F70109F0EBBA56959B3013565E2BDFFC
+PT=C373AB7B8F770212F9D5CEF40099086C
+CT=67221CC1F104809B8A5D35431963812D
+
+I=390
+KEY=173AE7879FAFB84D7232C2199FA70B4A
+IV=67221CC1F104809B8A5D35431963812D
+PT=8C59B2A7FD50EC66ABACC0531BE33237
+CT=E06166175F68155DB86E268F3C5524AE
+
+I=391
+KEY=F75B8190C0C7AD10CA5CE496A3F22FE4
+IV=E06166175F68155DB86E268F3C5524AE
+PT=D39790AED2970355A6337AAD2CA4D501
+CT=85E89883242A3B68F4AAF922646EB385
+
+I=392
+KEY=72B31913E4ED96783EF61DB4C79C9C61
+IV=85E89883242A3B68F4AAF922646EB385
+PT=87D4160C7C97476D0884A22B5983AA65
+CT=038C79FDFAA0B4F4AD9DC336F46CACDF
+
+I=393
+KEY=713F60EE1E4D228C936BDE8233F030BE
+IV=038C79FDFAA0B4F4AD9DC336F46CACDF
+PT=3B59088B5ADC77E4B3FC31897C6389B5
+CT=F6C92ECB3332E5E93C9DE29F27F94BB3
+
+I=394
+KEY=87F64E252D7FC765AFF63C1D14097B0D
+IV=F6C92ECB3332E5E93C9DE29F27F94BB3
+PT=68BA9BEBB40B3E35D2E577A2831CF9DB
+CT=7B72342488233DAD5ACF0A8D54EA9E8B
+
+I=395
+KEY=FC847A01A55CFAC8F539369040E3E586
+IV=7B72342488233DAD5ACF0A8D54EA9E8B
+PT=7816251219B8C7F009ADD7A1898D02CF
+CT=45CBA66AD6045917C3E8257D3ECBECDB
+
+I=396
+KEY=B94FDC6B7358A3DF36D113ED7E28095D
+IV=45CBA66AD6045917C3E8257D3ECBECDB
+PT=F542FEAB12E2EA9AE761E58108784E37
+CT=82E289465F5838036B9880C33AEBCB83
+
+I=397
+KEY=3BAD552D2C009BDC5D49932E44C3C2DE
+IV=82E289465F5838036B9880C33AEBCB83
+PT=3B8208791DAE56383CC2BCB44097C9D3
+CT=F02F2B89DE46D01F46AD95C82AF0C20E
+
+I=398
+KEY=CB827EA4F2464BC31BE406E66E3300D0
+IV=F02F2B89DE46D01F46AD95C82AF0C20E
+PT=3F2C0F7A0AEAB04F318C661ABCFED153
+CT=8D4FAF6332578524301ACA22AD86965B
+
+I=399
+KEY=46CDD1C7C011CEE72BFECCC4C3B5968B
+IV=8D4FAF6332578524301ACA22AD86965B
+PT=A27200B51D69AAC22F1C567F8BCEABFA
+CT=2F844CBF78EBA70DA7A49601388F1AB6
+
+==========
+
+KEYSIZE=192
+
+I=0
+KEY=000000000000000000000000000000000000000000000000
+IV=00000000000000000000000000000000
+PT=00000000000000000000000000000000
+CT=7BD966D53AD8C1BB85D2ADFAE87BB104
+
+I=1
+KEY=506339DAE3B35BEB7BD966D53AD8C1BB85D2ADFAE87BB104
+IV=7BD966D53AD8C1BB85D2ADFAE87BB104
+PT=0555C410F44C7AA4506339DAE3B35BEB
+CT=869C061BE9CFEAB5D285B0724A9A8970
+
+I=2
+KEY=74D3414C2374367BFD4560CED3172B0E57571D88A2E13874
+IV=869C061BE9CFEAB5D285B0724A9A8970
+PT=C6FB25A188CF7F3F24B07896C0C76D90
+CT=9E58A52B3840DBE16E8063A18220FEE4
+
+I=3
+KEY=DDE2DF4EEC312FA3631DC5E5EB57F0EF39D77E2920C1C690
+IV=9E58A52B3840DBE16E8063A18220FEE4
+PT=84E3D4168A8469A6A9319E02CF4519D8
+CT=730A256C202B9D57F3C0D73AD4B6CBED
+
+I=4
+KEY=9D973AECAF19E9951017E089CB7C6DB8CA17A913F4770D7D
+IV=730A256C202B9D57F3C0D73AD4B6CBED
+PT=E000CE26CD3185B44075E5A24328C636
+CT=E79EF11C5C1FD1AB75280BCFFCFE89D4
+
+I=5
+KEY=7A52007B2C40C9F4F78911959763BC13BF3FA2DC088984A9
+IV=E79EF11C5C1FD1AB75280BCFFCFE89D4
+PT=19D79403BB238816E7C53A9783592061
+CT=65744444724F1052D0B8674EDC8083B5
+
+I=6
+KEY=40D50426A8D09F3292FD55D1E52CAC416F87C592D409071C
+IV=65744444724F1052D0B8674EDC8083B5
+PT=FDFA33685E2B5BBC3A87045D849056C6
+CT=23C6377D3D076491AD93E2B6112289C7
+
+I=7
+KEY=6FD062412FE1AE4EB13B62ACD82BC8D0C2142724C52B8EDB
+IV=23C6377D3D076491AD93E2B6112289C7
+PT=5056DDDEF15831502F0566678731317C
+CT=F13A83088536BF30E5E9018BE57D7D89
+
+I=8
+KEY=EB4DB5F469D0EE9B4001E1A45D1D77E027FD26AF2056F352
+IV=F13A83088536BF30E5E9018BE57D7D89
+PT=0EE535A4A524668F849DD7B5463140D5
+CT=3F496CB19B21C37159528BF345473E6D
+
+I=9
+KEY=AA6E5744B909D9A87F488D15C63CB4917EAFAD5C6511CD3F
+IV=3F496CB19B21C37159528BF345473E6D
+PT=3A11F90EB51C81ED4123E2B0D0D93733
+CT=CF79C1EDEE17A68DC7E673006AEC90D9
+
+I=10
+KEY=64AB0C0C9471B77FB0314CF8282B121CB949DE5C0FFD5DE6
+IV=CF79C1EDEE17A68DC7E673006AEC90D9
+PT=85187E7F91280A5BCEC55B482D786ED7
+CT=92D1757BEBCE6E0406407819AF82353F
+
+I=11
+KEY=9E5720C1DC2E285C22E03983C3E57C18BF09A645A07F68D9
+IV=92D1757BEBCE6E0406407819AF82353F
+PT=45147511BC08EC76FAFC2CCD485F9F23
+CT=8C0228F57523D746E67D27A8E6C426D9
+
+I=12
+KEY=EBBB8245582E4367AEE21176B6C6AB5E597481ED46BB4E00
+IV=8C0228F57523D746E67D27A8E6C426D9
+PT=73B9EEAC644CBB8875ECA28484006B3B
+CT=D0025BF1FC35DD9BDA20F42DF775AF71
+
+I=13
+KEY=5F938EE9CC63C9E87EE04A874AF376C5835475C0B1CEE171
+IV=D0025BF1FC35DD9BDA20F42DF775AF71
+PT=DE2507F01BC8B212B4280CAC944D8A8F
+CT=3FDDD3E04B2CBE79BB07D82182CD3787
+
+I=14
+KEY=B94E2EC5F6E86EDC413D996701DFC8BC3853ADE13303D6F6
+IV=3FDDD3E04B2CBE79BB07D82182CD3787
+PT=90CE32BCC16C20F7E6DDA02C3A8BA734
+CT=F7B491E4C40B60BE8ACF16D68E3ED60F
+
+I=15
+KEY=DE41ABD8C44F5DF6B6890883C5D4A802B29CBB37BD3D00F9
+IV=F7B491E4C40B60BE8ACF16D68E3ED60F
+PT=B7ACCA62BB9974BC670F851D32A7332A
+CT=7ED4055D367CB31A4CF1CC17132E00B5
+
+I=16
+KEY=E2A57C71F23BC4DEC85D0DDEF3A81B18FE6D7720AE13004C
+IV=7ED4055D367CB31A4CF1CC17132E00B5
+PT=1CA59C2384797B803CE4D7A936749928
+CT=8D50A87F14D466323929BB52FA60FA42
+
+I=17
+KEY=2FA1A78B8BCC301C450DA5A1E77C7D2AC744CC725473FA0E
+IV=8D50A87F14D466323929BB52FA60FA42
+PT=0A623319F2A051ACCD04DBFA79F7F4C2
+CT=7C02D378606FC33DFCEF8AA2A000383E
+
+I=18
+KEY=A949CE493892DF58390F76D98713BE173BAB46D0F473C230
+IV=7C02D378606FC33DFCEF8AA2A000383E
+PT=EE8F5FF6A7FF813386E869C2B35EEF44
+CT=CAE55B9CCBB5A68EBF0D2AB55E079FD4
+
+I=19
+KEY=E159445FE4201A6CF3EA2D454CA6189984A66C65AA745DE4
+IV=CAE55B9CCBB5A68EBF0D2AB55E079FD4
+PT=9699456986535C4648108A16DCB2C534
+CT=9056685FBFECC7A6143DB5AC314DAC88
+
+I=20
+KEY=EE4F7BF96BF1163E63BC451AF34ADF3F909BD9C99B39F16C
+IV=9056685FBFECC7A6143DB5AC314DAC88
+PT=16D6C34C3B57AC0A0F163FA68FD10C52
+CT=4D6A5542F0680CE37E88119141F321F5
+
+I=21
+KEY=27F8CEE0120E8A0F2ED610580322D3DCEE13C858DACAD099
+IV=4D6A5542F0680CE37E88119141F321F5
+PT=337839926E36EC77C9B7B51979FF9C31
+CT=78E16D6027F0D190E78825C2F52E5364
+
+I=22
+KEY=0AF4D3D8EB9FF18A56377D3824D2024C099BED9A2FE483FD
+IV=78E16D6027F0D190E78825C2F52E5364
+PT=8F96B66F934467C72D0C1D38F9917B85
+CT=82A81B33F80A105DD7D9CC6DDFECDB96
+
+I=23
+KEY=AD2AFC821170D967D49F660BDCD81211DE4221F7F008586B
+IV=82A81B33F80A105DD7D9CC6DDFECDB96
+PT=E2CB8E6E329C6660A7DE2F5AFAEF28ED
+CT=0BCD68A063BA3540B3E04C885DF45BD0
+
+I=24
+KEY=5B50EE72BD6CE837DF520EABBF6227516DA26D7FADFC03BB
+IV=0BCD68A063BA3540B3E04C885DF45BD0
+PT=31A14C64CD8BCC8FF67A12F0AC1C3150
+CT=DB27EA5834BF572EA50E03E0773C1010
+
+I=25
+KEY=BF4D8A58F54D47620475E4F38BDD707FC8AC6E9FDAC013AB
+IV=DB27EA5834BF572EA50E03E0773C1010
+PT=26755B5C0BE60998E41D642A4821AF55
+CT=655A896243B5E86B2F74299A317A2E4C
+
+I=26
+KEY=8DC190D88B17EAB9612F6D91C8689814E7D84705EBBA3DE7
+IV=655A896243B5E86B2F74299A317A2E4C
+PT=C6920ADCED82F661328C1A807E5AADDB
+CT=9F45472FDBB732C745AD228810392EA2
+
+I=27
+KEY=B44071C6F14CDA97FE6A2ABE13DFAAD3A275658DFB831345
+IV=9F45472FDBB732C745AD228810392EA2
+PT=2178DFA9784E563E3981E11E7A5B302E
+CT=9F985FBF08235845E396BFCE54BCE7C8
+
+I=28
+KEY=A3C12E42B53D829E61F275011BFCF29641E3DA43AF3FF48D
+IV=9F985FBF08235845E396BFCE54BCE7C8
+PT=44977E2274DA25AE17815F8444715809
+CT=033EAF4FAC934D123012279B1663C80B
+
+I=29
+KEY=8FD2B79E25E39C4A62CCDA4EB76FBF8471F1FDD8B95C3C86
+IV=033EAF4FAC934D123012279B1663C80B
+PT=425088D4626CD7972C1399DC90DE1ED4
+CT=A962CB4707B0048BB81F4225EFC85E48
+
+I=30
+KEY=3D68793EF46B8125CBAE1109B0DFBB0FC9EEBFFD569462CE
+IV=A962CB4707B0048BB81F4225EFC85E48
+PT=EF21ED587C272175B2BACEA0D1881D6F
+CT=6F3A0D63A22C003F7F65B09098F667DB
+
+I=31
+KEY=6A4FB651BE9D0BAFA4941C6A12F3BB30B68B0F6DCE620515
+IV=6F3A0D63A22C003F7F65B09098F667DB
+PT=16054E60B460B2D15727CF6F4AF68A8A
+CT=8BB46230FF03665765F2E5AAEA14104F
+
+I=32
+KEY=3F5991D63C15A1822F207E5AEDF0DD67D379EAC72476155A
+IV=8BB46230FF03665765F2E5AAEA14104F
+PT=82D0B12FEA88917F551627878288AA2D
+CT=8E1A664131FAB09E786E111C3C20A7BB
+
+I=33
+KEY=456F69D38929ED82A13A181BDC0A6DF9AB17FBDB1856B2E1
+IV=8E1A664131FAB09E786E111C3C20A7BB
+PT=1384D3B7CAEB528A7A36F805B53C4C00
+CT=92D99BF1D71026D2BF78E32421E34E52
+
+I=34
+KEY=658891F63379484C33E383EA0B1A4B2B146F18FF39B5FCB3
+IV=92D99BF1D71026D2BF78E32421E34E52
+PT=9F60C3117269E88920E7F825BA50A5CE
+CT=7DB6782C68EC5FC75A2A75E4EA7B4071
+
+I=35
+KEY=9193E2EACE8423F64E55FBC663F614EC4E456D1BD3CEBCC2
+IV=7DB6782C68EC5FC75A2A75E4EA7B4071
+PT=232ECA0370EBD920F41B731CFDFD6BBA
+CT=D76A1E73E977533E6D7C74277DAFEB48
+
+I=36
+KEY=F4C34FE273D0FCB5993FE5B58A8147D22339193CAE61578A
+IV=D76A1E73E977533E6D7C74277DAFEB48
+PT=5BCD8C6C4D14321F6550AD08BD54DF43
+CT=4A69E9081DDD43A6061700C7DA8F5E73
+
+I=37
+KEY=DC82C155896C5D5CD3560CBD975C0474252E19FB74EE09F9
+IV=4A69E9081DDD43A6061700C7DA8F5E73
+PT=C914BB961EA890D828418EB7FABCA1E9
+CT=91EE5BE28C27F055258BC3E1F37E2DEC
+
+I=38
+KEY=08F1655EA3656F1C42B8575F1B7BF42100A5DA1A87902415
+IV=91EE5BE28C27F055258BC3E1F37E2DEC
+PT=11804F73D788115CD473A40B2A093240
+CT=86B9BE5AFD2A8A49E2651C314CAE0918
+
+I=39
+KEY=59D7EFD92140A147C401E905E6517E68E2C0C62BCB3E2D0D
+IV=86B9BE5AFD2A8A49E2651C314CAE0918
+PT=6E2A1E436926174E51268A878225CE5B
+CT=C642F5ED78DB76738A89296B1C4A0932
+
+I=40
+KEY=F6E75E7867D0FB4A02431CE89E8A081B6849EF40D774243F
+IV=C642F5ED78DB76738A89296B1C4A0932
+PT=15896B8B864CF068AF30B1A146905A0D
+CT=24288AE027547E499EBADE9260C8F037
+
+I=41
+KEY=9A048C2BC98E15B2266B9608B9DE7652F6F331D2B7BCD408
+IV=24288AE027547E499EBADE9260C8F037
+PT=FF9A330C205DC3006CE3D253AE5EEEF8
+CT=BD9B3D670D24EDDA1EAD1DB06C8A83C7
+
+I=42
+KEY=97E8C017644E9FED9BF0AB6FB4FA9B88E85E2C62DB3657CF
+IV=BD9B3D670D24EDDA1EAD1DB06C8A83C7
+PT=C9A3916C34A7CCD90DEC4C3CADC08A5F
+CT=1FCCBC65C44E4680E1593EE0EEFEA9A9
+
+I=43
+KEY=3A2862113BD3312D843C170A70B4DD080907128235C8FE66
+IV=1FCCBC65C44E4680E1593EE0EEFEA9A9
+PT=EAF9C4A80EE93585ADC0A2065F9DAEC0
+CT=2C0004064936696B10D039D9795BABC7
+
+I=44
+KEY=33FAE356C0C96F17A83C130C3982B46319D72B5B4C9355A1
+IV=2C0004064936696B10D039D9795BABC7
+PT=4181525880CA468909D28147FB1A5E3A
+CT=79F193EB9A9A48464FF007D73E9B4106
+
+I=45
+KEY=2136A7940C9B9FAFD1CD80E7A318FC2556272C8C720814A7
+IV=79F193EB9A9A48464FF007D73E9B4106
+PT=2899D75DFB84950E12CC44C2CC52F0B8
+CT=DA12307CE9A6BA0FCE5A76AE1747E619
+
+I=46
+KEY=0C839679750274320BDFB09B4ABE462A987D5A22654FF2BE
+IV=DA12307CE9A6BA0FCE5A76AE1747E619
+PT=2C71B8623CA5BF292DB531ED7999EB9D
+CT=A59997FA19B58BC71CB05E7140386C94
+
+I=47
+KEY=4D3CDB92797645C1AE462761530BCDED84CD045325779E2A
+IV=A59997FA19B58BC71CB05E7140386C94
+PT=63F4FC202A1B921241BF4DEB0C7431F3
+CT=49E65D7422398035DD1E4EBAD37C699D
+
+I=48
+KEY=38082D7CC27EBABBE7A07A1571324DD859D34AE9F60BF7B7
+IV=49E65D7422398035DD1E4EBAD37C699D
+PT=7F0E2FD5D4B5A0CB7534F6EEBB08FF7A
+CT=64DF24483FC73174FB6482A6E2B895E0
+
+I=49
+KEY=1557398CFBFF31F8837F5E5D4EF57CACA2B7C84F14B36257
+IV=64DF24483FC73174FB6482A6E2B895E0
+PT=0F525FCF2A1E3D612D5F14F039818B43
+CT=028880CC8AA1B92CB807F1102663E658
+
+I=50
+KEY=229C31F1D34A529581F7DE91C454C5801AB0395F32D0840F
+IV=028880CC8AA1B92CB807F1102663E658
+PT=219604B99FF2BE7B37CB087D28B5636D
+CT=FAC8B66D1BA7849392CC235D0276110E
+
+I=51
+KEY=C75DE76D40D536277B3F68FCDFF34113887C1A0230A69501
+IV=FAC8B66D1BA7849392CC235D0276110E
+PT=3319C80C038E565FE5C1D69C939F64B2
+CT=79770F286419EEFD855868EC4ADF3775
+
+I=52
+KEY=5F0B08B451490B27024867D4BBEAAFEE0D2472EE7A79A274
+IV=79770F286419EEFD855868EC4ADF3775
+PT=E173A8580816CAFA9856EFD9119C3D00
+CT=FC0AA487B09DF657DB58DBF83E13E137
+
+I=53
+KEY=E86E8BFBF1D65541FE42C3530B7759B9D67CA916446A4343
+IV=FC0AA487B09DF657DB58DBF83E13E137
+PT=01274C45F202C22CB765834FA09F5E66
+CT=9691EA44FC67CA29E50E7FF7DBC4D0CA
+
+I=54
+KEY=7849550CA6CCD87268D32917F71093903372D6E19FAE9389
+IV=9691EA44FC67CA29E50E7FF7DBC4D0CA
+PT=026BD493499B7BA99027DEF7571A8D33
+CT=5206F7CF45A59FD6444CCBB6B034CF45
+
+I=55
+KEY=52D81D6104DBF6DF3AD5DED8B2B50C46773E1D572F9A5CCC
+IV=5206F7CF45A59FD6444CCBB6B034CF45
+PT=33CA15B3D921E7752A91486DA2172EAD
+CT=F4A41D18E3EF9DE46917BADB1B5EC613
+
+I=56
+KEY=36FB680165ABD632CE71C3C0515A91A21E29A78C34C49ADF
+IV=F4A41D18E3EF9DE46917BADB1B5EC613
+PT=65F3084285AA869464237560617020ED
+CT=6C4154D3245D2546979118A36120A911
+
+I=57
+KEY=6E7548B98AA0640AA23097137507B4E489B8BF2F55E433CE
+IV=6C4154D3245D2546979118A36120A911
+PT=6CF540F502D90886588E20B8EF0BB238
+CT=2A52376A7E494ADEDD53A416F73FE9C0
+
+I=58
+KEY=A0D840A0E3CC1EA58862A0790B4EFE3A54EB1B39A2DBDA0E
+IV=2A52376A7E494ADEDD53A416F73FE9C0
+PT=708AE2375F305572CEAD0819696C7AAF
+CT=7A0EF052184147EA279839380B3DBB32
+
+I=59
+KEY=153CF68E4A1C1FCEF26C502B130FB9D073732201A9E6613C
+IV=7A0EF052184147EA279839380B3DBB32
+PT=A8267215107D3DD0B5E4B62EA9D0016B
+CT=F193B80D57571F94A4F5373149163AA1
+
+I=60
+KEY=E0B0657A66C37D8703FFE8264458A644D7861530E0F05B9D
+IV=F193B80D57571F94A4F5373149163AA1
+PT=EE4B04302CB02990F58C93F42CDF6249
+CT=A28E99815C930AC05ADA4524A7E5968C
+
+I=61
+KEY=94760F8A93926E4DA17171A718CBAC848D5C50144715CD11
+IV=A28E99815C930AC05ADA4524A7E5968C
+PT=34D122B717CBA59174C66AF0F55113CA
+CT=6F9342E7915613450E823EC9A781DAA3
+
+I=62
+KEY=0B352460A1579376CEE23340899DBFC183DE6EDDE09417B2
+IV=6F9342E7915613450E823EC9A781DAA3
+PT=D8689ED21F3EA8E29F432BEA32C5FD3B
+CT=584BB944532A830F7F8DCDBE42E7DBFC
+
+I=63
+KEY=999A5CEB73DFCC1796A98A04DAB73CCEFC53A363A273CC4E
+IV=584BB944532A830F7F8DCDBE42E7DBFC
+PT=4E87F73D46D0C0AF92AF788BD2885F61
+CT=4AC372A4D3273C71F69D50168A9235A1
+
+I=64
+KEY=42C59FFD5AA69C11DC6AF8A0099000BF0ACEF37528E1F9EF
+IV=4AC372A4D3273C71F69D50168A9235A1
+PT=324DC9C2D34E95F9DB5FC31629795006
+CT=60E53CC2D5E4900D48A0C5F7EE3BC810
+
+I=65
+KEY=843EBDEF0CEEBA5BBC8FC462DC7490B2426E3682C6DA31FF
+IV=60E53CC2D5E4900D48A0C5F7EE3BC810
+PT=8B94F018A7115B3AC6FB22125648264A
+CT=4BD7DF7DFD03A24809B751F59FACF417
+
+I=66
+KEY=98E40853FA954FF5F7581B1F217732FA4BD967775976C5E8
+IV=4BD7DF7DFD03A24809B751F59FACF417
+PT=109C734AC21ED2631CDAB5BCF67BF5AE
+CT=B7A3CF7E58A413C5065E9CFD23C750F9
+
+I=67
+KEY=5419462C5329544A40FBD46179D3213F4D87FB8A7AB19511
+IV=B7A3CF7E58A413C5065E9CFD23C750F9
+PT=8CA507ACCDB3A793CCFD4E7FA9BC1BBF
+CT=6285C3D0FD2645192C5DD046D73414CE
+
+I=68
+KEY=B58628819840885D227E17B184F5642661DA2BCCAD8581DF
+IV=6285C3D0FD2645192C5DD046D73414CE
+PT=7DE48BAD03BB9F53E19F6EADCB69DC17
+CT=583FBCEB09646CEC19D00620E5455FD5
+
+I=69
+KEY=73F7F00EF22ED1B07A41AB5A8D9108CA780A2DEC48C0DE0A
+IV=583FBCEB09646CEC19D00620E5455FD5
+PT=126D3F2A0BC1B168C671D88F6A6E59ED
+CT=886A5273055AF7AE37EFB726DC90FD9E
+
+I=70
+KEY=69735F80F0B876DAF22BF92988CBFF644FE59ACA94502394
+IV=886A5273055AF7AE37EFB726DC90FD9E
+PT=0B4D3F58D83D866A1A84AF8E0296A76A
+CT=FD068F02BB6C2611EF78CD963EF2F78F
+
+I=71
+KEY=92E5FF32D46494880F2D762B33A7D975A09D575CAAA2D41B
+IV=FD068F02BB6C2611EF78CD963EF2F78F
+PT=705667CBCC87BF3DFB96A0B224DCE252
+CT=34713FD3FA07F0B3F94EC0FB17BB465F
+
+I=72
+KEY=A0DF9DCB873A1ADC3B5C49F8C9A029C659D397A7BD199244
+IV=34713FD3FA07F0B3F94EC0FB17BB465F
+PT=4BF66F55275D6CB3323A62F9535E8E54
+CT=82C8A179661207B7FE178A266C607074
+
+I=73
+KEY=2D1604ADAA49C3FBB994E881AFB22E71A7C41D81D179E230
+IV=82C8A179661207B7FE178A266C607074
+PT=167203BBB933707A8DC999662D73D927
+CT=DCDBCC8D11C632CB220C6E95B399A1CC
+
+I=74
+KEY=7D2C4B0C0D0B001A654F240CBE741CBA85C8731462E043FC
+IV=DCDBCC8D11C632CB220C6E95B399A1CC
+PT=668F998350BDA831503A4FA1A742C3E1
+CT=8827EBFCB24470266D5C0BA05D5974A4
+
+I=75
+KEY=BE3A4CF21186C2C7ED68CFF00C306C9CE89478B43FB93758
+IV=8827EBFCB24470266D5C0BA05D5974A4
+PT=B8D1D48F3C41094EC31607FE1C8DC2DD
+CT=61E59DECE1AEFFDEB9B216828953D70F
+
+I=76
+KEY=D0CE372842DC32508C8D521CED9E934251266E36B6EAE057
+IV=61E59DECE1AEFFDEB9B216828953D70F
+PT=49A4495257D08AA56EF47BDA535AF097
+CT=ECD04FFB385CCC1D13C312A5C31810DE
+
+I=77
+KEY=E7274C14C4163169605D1DE7D5C25F5F42E57C9375F2F089
+IV=ECD04FFB385CCC1D13C312A5C31810DE
+PT=3EED6F60FD9050A737E97B3C86CA0339
+CT=D9C90455AFBF5465F89752FB6F60BDFF
+
+I=78
+KEY=71E35A00CAFB898BB99419B27A7D0B3ABA722E681A924D76
+IV=D9C90455AFBF5465F89752FB6F60BDFF
+PT=5CE6E7F07945191396C416140EEDB8E2
+CT=F6E795B326CFD6CCC0E230E4FE770878
+
+I=79
+KEY=79DFA388989B29204F738C015CB2DDF67A901E8CE4E5450E
+IV=F6E795B326CFD6CCC0E230E4FE770878
+PT=314A5784B7909F89083CF9885260A0AB
+CT=6B3A00F05F79F25E4E9EDA81034A9B7B
+
+I=80
+KEY=75F6D5983AE6D7AC24498CF103CB2FA8340EC40DE7AFDE75
+IV=6B3A00F05F79F25E4E9EDA81034A9B7B
+PT=DEC42B1A6184FDF80C297610A27DFE8C
+CT=6A19BEA8826427E309BD55BCBBE246B4
+
+I=81
+KEY=E47EEE65549BF1634E50325981AF084B3DB391B15C4D98C1
+IV=6A19BEA8826427E309BD55BCBBE246B4
+PT=63C46CFF49FF13B291883BFD6E7D26CF
+CT=738C0B0E580C0B1ED488DDE8502CB754
+
+I=82
+KEY=E6DBE45547556F403DDC3957D9A30355E93B4C590C612F95
+IV=738C0B0E580C0B1ED488DDE8502CB754
+PT=E951F5C902BD351502A50A3013CE9E23
+CT=389E33F3DAB3FAB7B2ACB853C0150B8D
+
+I=83
+KEY=EBA5A1BDF9FC558905420AA40310F9E25B97F40ACC742418
+IV=389E33F3DAB3FAB7B2ACB853C0150B8D
+PT=54EFC45B4036B60D0D7E45E8BEA93AC9
+CT=EACAE8A4B5CCBDB28ED2162670DBD4B1
+
+I=84
+KEY=B570945030615F75EF88E200B6DC4450D545E22CBCAFF0A9
+IV=EACAE8A4B5CCBDB28ED2162670DBD4B1
+PT=7F3BA6FE23AE45665ED535EDC99D0AFC
+CT=535FEA61623ECD22FA1A95BF95320252
+
+I=85
+KEY=F332D3DE8556F82EBCD70861D4E289722F5F7793299DF2FB
+IV=535FEA61623ECD22FA1A95BF95320252
+PT=8FEB6943B22437D34642478EB537A75B
+CT=CD23D928E1D3221E4D3C51670C071276
+
+I=86
+KEY=1402D325D7EBA90871F4D1493531AB6C626326F4259AE08D
+IV=CD23D928E1D3221E4D3C51670C071276
+PT=8B01EE4509B58B49E73000FB52BD5126
+CT=56DC7F1BE2CC26A369B3BCA71BF8FAB8
+
+I=87
+KEY=389C95DC5BF411B62728AE52D7FD8DCF0BD09A533E621A35
+IV=56DC7F1BE2CC26A369B3BCA71BF8FAB8
+PT=9BFE561402B07B4C2C9E46F98C1FB8BE
+CT=A059CFB443009F0ACD8E5051BD16C837
+
+I=88
+KEY=89180FBFF0A12019877161E694FD12C5C65ECA028374D202
+IV=A059CFB443009F0ACD8E5051BD16C837
+PT=C8D55810C7A22E30B1849A63AB5531AF
+CT=62CEB7D9A6D23B40CFD75990D1040BA4
+
+I=89
+KEY=08BE01CF1E620DBEE5BFD63F322F2985098993925270D9A6
+IV=62CEB7D9A6D23B40CFD75990D1040BA4
+PT=F888764A970B03BC81A60E70EEC32DA7
+CT=F6D89003ABBF003AF013EB221AF17F99
+
+I=90
+KEY=5EB9AC53FC544ADE1367463C999029BFF99A78B04881A63F
+IV=F6D89003ABBF003AF013EB221AF17F99
+PT=26A25CFC1E699D8B5607AD9CE2364760
+CT=74C9E920DC16396E89774B82E7803EF5
+
+I=91
+KEY=D8FAD6E8CDC96CEF67AEAF1C458610D170ED3332AF0198CA
+IV=74C9E920DC16396E89774B82E7803EF5
+PT=76AFDD045A30FAA486437ABB319D2631
+CT=A5B997689B88AAC0611C2963C8C1B7CE
+
+I=92
+KEY=7E774E64A5F209B2C2173874DE0EBA1111F11A5167C02F04
+IV=A5B997689B88AAC0611C2963C8C1B7CE
+PT=ABF525144D3415DEA68D988C683B655D
+CT=7A2F39D97547C3CD336577E41C0483ED
+
+I=93
+KEY=0406C21AE6E015E0B83801ADAB4979DC22946DB57BC4ACE9
+IV=7A2F39D97547C3CD336577E41C0483ED
+PT=E0C2466426630D1B7A718C7E43121C52
+CT=67899F7D0890E90383C05A7984604241
+
+I=94
+KEY=D9249A4AFDF40BEADFB19ED0A3D990DFA15437CCFFA4EEA8
+IV=67899F7D0890E90383C05A7984604241
+PT=07E55341FCD016D7DD2258501B141E0A
+CT=7B1CBCD270B09E9A1D15714D8366D174
+
+I=95
+KEY=B2242464CD4D2448A4AD2202D3690E45BC4146817CC23FDC
+IV=7B1CBCD270B09E9A1D15714D8366D174
+PT=25C6E62F44ABFF406B00BE2E30B92FA2
+CT=C86E27E5CA4461CE656D893A16477966
+
+I=96
+KEY=602CDF824C043C836CC305E7192D6F8BD92CCFBB6A8546BA
+IV=C86E27E5CA4461CE656D893A16477966
+PT=3F9D262E375F057BD208FBE6814918CB
+CT=8129054CF746CB79112942AE35142E4D
+
+I=97
+KEY=73F82C9EE4B4D0E8EDEA00ABEE6BA4F2C8058D155F9168F7
+IV=8129054CF746CB79112942AE35142E4D
+PT=7BC798EAC4C17B2D13D4F31CA8B0EC6B
+CT=36F21910B1677AF19586E55E360FB8DD
+
+I=98
+KEY=E5FC538A60CC29A3DB1819BB5F0CDE035D83684B699ED02A
+IV=36F21910B1677AF19586E55E360FB8DD
+PT=D3E39037253E5BAA96047F148478F94B
+CT=BA7CE80E0853D264368EE61D8E71EEBE
+
+I=99
+KEY=D9381EF81441B6C16164F1B5575F0C676B0D8E56E7EF3E94
+IV=BA7CE80E0853D264368EE61D8E71EEBE
+PT=DE4FFDFADB81FABB3CC44D72748D9F62
+CT=971AD82D1F46F1087B37103B4BE5DD8C
+
+I=100
+KEY=A0BF8B4740D929C9F67E29984819FD6F103A9E6DAC0AE318
+IV=971AD82D1F46F1087B37103B4BE5DD8C
+PT=FE6355B5D860522B798795BF54989F08
+CT=D17268155EE586F352BB031929441700
+
+I=101
+KEY=477A0AB591FFEC5C270C418D16FC7B9C42819D74854EF418
+IV=D17268155EE586F352BB031929441700
+PT=166A50EEE05F4A39E7C581F2D126C595
+CT=2CD84FB5B587BE8B04638A9EDBA17AE2
+
+I=102
+KEY=50005B4C4B11BFB20BD40E38A37BC51746E217EA5EEF8EFA
+IV=2CD84FB5B587BE8B04638A9EDBA17AE2
+PT=1296DC2C1741EB2A177A51F9DAEE53EE
+CT=8C2A5A31951FB2D9E8D35CD3C007B8B3
+
+I=103
+KEY=E1E88DDBA5D849DF87FE5409366477CEAE314B399EE83649
+IV=8C2A5A31951FB2D9E8D35CD3C007B8B3
+PT=57C5E1A070E3C2AEB1E8D697EEC9F66D
+CT=AA9E935BA264C9FD0C07072AF8499CD7
+
+I=104
+KEY=D465F0FB195068CF2D60C7529400BE33A2364C1366A1AA9E
+IV=AA9E935BA264C9FD0C07072AF8499CD7
+PT=77D0522670E00BD7358D7D20BC882110
+CT=A22DF6CE12C75FB99F5159A1E3E4249F
+
+I=105
+KEY=4DEB1B5E6398E4AD8F4D319C86C7E18A3D6715B285458E01
+IV=A22DF6CE12C75FB99F5159A1E3E4249F
+PT=D6F96D22896A2574998EEBA57AC88C62
+CT=B356102A9158C569469E61093146B9F0
+
+I=106
+KEY=D73E5CA946860BDD3C1B21B6179F24E37BF974BBB40337F1
+IV=B356102A9158C569469E61093146B9F0
+PT=2E72F61FC21F57A09AD547F7251EEF70
+CT=AB2BABFB88D3C3ACE4CBA81E0E250AD3
+
+I=107
+KEY=6B592CE635873DE197308A4D9F4CE74F9F32DCA5BA263D22
+IV=AB2BABFB88D3C3ACE4CBA81E0E250AD3
+PT=39B02C01155705C9BC67704F7301363C
+CT=8A4AC90E9095479F3C02DE7B08C01F1C
+
+I=108
+KEY=1026EE98CAC684081D7A43430FD9A0D0A33002DEB2E6223E
+IV=8A4AC90E9095479F3C02DE7B08C01F1C
+PT=14F49DBECEE88DBB7B7FC27EFF41B9E9
+CT=62E4E3C43938D014D90C4A1D8CD09639
+
+I=109
+KEY=20972278E7C0FFC17F9EA08736E170C47A3C48C33E36B407
+IV=62E4E3C43938D014D90C4A1D8CD09639
+PT=56EFB0EA336A674930B1CCE02D067BC9
+CT=5E8EB865BFC1999D57A67280E37CA129
+
+I=110
+KEY=2BEE1A1965A7F17C211018E28920E9592D9A3A43DD4A152E
+IV=5E8EB865BFC1999D57A67280E37CA129
+PT=9CF6F073F2F0C7CB0B79386182670EBD
+CT=D3B98A4562FAB47ED3D09C55E75EE51B
+
+I=111
+KEY=EB85E491647FD6ACF2A992A7EBDA5D27FE4AA6163A14F035
+IV=D3B98A4562FAB47ED3D09C55E75EE51B
+PT=61964EF472752F21C06BFE8801D827D0
+CT=CF3D65AEEDD747416AF436A3B909828F
+
+I=112
+KEY=E94E6286941EC36D3D94F709060D1A6694BE90B5831D72BA
+IV=CF3D65AEEDD747416AF436A3B909828F
+PT=6C0B536EA1099A4202CB8617F06115C1
+CT=5DB0625B34C01C47490B5200E8A205FC
+
+I=113
+KEY=F5D756E568CA6BA06024955232CD0621DDB5C2B56BBF7746
+IV=5DB0625B34C01C47490B5200E8A205FC
+PT=08D5CD9945D190AB1C993463FCD4A8CD
+CT=771B5C66F79E262FAAC6F92F128669CB
+
+I=114
+KEY=462C74E6E222DE77173FC934C553200E77733B9A79391E8D
+IV=771B5C66F79E262FAAC6F92F128669CB
+PT=5628EC55D7AB7634B3FB22038AE8B5D7
+CT=31C436E7CA7343A93AA0B74A38CCDAC0
+
+I=115
+KEY=5062F2489F4C68FE26FBFFD30F2063A74DD38CD041F5C44D
+IV=31C436E7CA7343A93AA0B74A38CCDAC0
+PT=F279C45DBD75C458164E86AE7D6EB689
+CT=845320B41FD6F1D4DBB36D19D8A4A268
+
+I=116
+KEY=5A27EC509FED17B6A2A8DF6710F692739660E1C999516625
+IV=845320B41FD6F1D4DBB36D19D8A4A268
+PT=7C0CB5E4FFE703260A451E1800A17F48
+CT=D8F9FB52BE1B342D6FBBB8A7FCDEFD89
+
+I=117
+KEY=E925EC8E99BF11E97A512435AEEDA65EF9DB596E658F9BAC
+IV=D8F9FB52BE1B342D6FBBB8A7FCDEFD89
+PT=187F3648643AF8E6B30200DE0652065F
+CT=240647A32D765031C79D8893CC19EBA9
+
+I=118
+KEY=5574034BCE64FADD5E576396839BF66F3E46D1FDA9967005
+IV=240647A32D765031C79D8893CC19EBA9
+PT=AF808097E0C68C8FBC51EFC557DBEB34
+CT=2A3805A7D773F9C00635779752C9CCE7
+
+I=119
+KEY=D842A9983BBDAA5E746F663154E80FAF3873A66AFB5FBCE2
+IV=2A3805A7D773F9C00635779752C9CCE7
+PT=D44486CCC61C68588D36AAD3F5D95083
+CT=2219F0C7A805BEC4A4931F84CBFFC598
+
+I=120
+KEY=CD622302BD70E2CD567696F6FCEDB16B9CE0B9EE30A0797A
+IV=2219F0C7A805BEC4A4931F84CBFFC598
+PT=67DA1BC4F2BC2F3315208A9A86CD4893
+CT=8B1F4353CF6969888BBD6654AB65C2A8
+
+I=121
+KEY=80A1D0CA7667F291DD69D5A53384D8E3175DDFBA9BC5BBD2
+IV=8B1F4353CF6969888BBD6654AB65C2A8
+PT=D114FDA8E61BEAC44DC3F3C8CB17105C
+CT=B6F0C0F016A1FA033C37D1128D9B2EF3
+
+I=122
+KEY=2C9B755C3B8B44416B991555252522E02B6A0EA8165E9521
+IV=B6F0C0F016A1FA033C37D1128D9B2EF3
+PT=738DBCE3EE7E70EAAC3AA5964DECB6D0
+CT=14FB0A67CB0729CA25152581D8C3FEEF
+
+I=123
+KEY=5D05BDFBF482E4D37F621F32EE220B2A0E7F2B29CE9D6BCE
+IV=14FB0A67CB0729CA25152581D8C3FEEF
+PT=D3186497981F294B719EC8A7CF09A092
+CT=14C988C52C7ED50EBD10219F1F58C213
+
+I=124
+KEY=9E044D195FA8557C6BAB97F7C25CDE24B36F0AB6D1C5A9DD
+IV=14C988C52C7ED50EBD10219F1F58C213
+PT=C062585284FDE540C301F0E2AB2AB1AF
+CT=1FE7E153E69F95F102624ACEB9067FA1
+
+I=125
+KEY=2B116B6F1FD581C6744C76A424C34BD5B10D407868C3D67C
+IV=1FE7E153E69F95F102624ACEB9067FA1
+PT=F18294D40CAA674DB5152676407DD4BA
+CT=AB43B2C61C9F23B96EFE293C6730A98F
+
+I=126
+KEY=EAF1AFBDD2CEDB9ADF0FC462385C686CDFF369440FF37FF3
+IV=AB43B2C61C9F23B96EFE293C6730A98F
+PT=7D465730C5422413C1E0C4D2CD1B5A5C
+CT=B1413F447CA81C678287EE2366544547
+
+I=127
+KEY=4FA6C7DA7A84D4CB6E4EFB2644F4740B5D74876769A73AB4
+IV=B1413F447CA81C678287EE2366544547
+PT=C7BFA1BFA26828F7A5576867A84A0F51
+CT=7AE90F988557F3A41BBDB4B69C5FF56A
+
+I=128
+KEY=C9B0E3C7CEF4003014A7F4BEC1A387AF46C933D1F5F8CFDE
+IV=7AE90F988557F3A41BBDB4B69C5FF56A
+PT=5173C32806105AD18616241DB470D4FB
+CT=F2EF675645D284F042FAEBE87AE3ECAE
+
+I=129
+KEY=DB855274F6CC030BE64893E88471035F0433D8398F1B2370
+IV=F2EF675645D284F042FAEBE87AE3ECAE
+PT=6DF6B7F917B2F8431235B1B33838033B
+CT=30D4F068BC2FDEC79CF81A4FA641A495
+
+I=130
+KEY=F37DBF11472A4F87D69C6380385EDD9898CBC276295A87E5
+IV=30D4F068BC2FDEC79CF81A4FA641A495
+PT=F4C98D268B7D175728F8ED65B1E64C8C
+CT=0CEB234560B935E5B08C7EA2AA4A962D
+
+I=131
+KEY=1A2F5A0827B2F861DA7740C558E7E87D2847BCD4831011C8
+IV=0CEB234560B935E5B08C7EA2AA4A962D
+PT=9873E312B815DC81E952E5196098B7E6
+CT=7BED84EFC02836F6D165AD27DEEF2B21
+
+I=132
+KEY=9C815F2A4EC42D02A19AC42A98CFDE8BF92211F35DFF3AE9
+IV=7BED84EFC02836F6D165AD27DEEF2B21
+PT=D8765DE55131DC4186AE05226976D563
+CT=C36FEDCB97DA734243A20C49D5942DD1
+
+I=133
+KEY=9A12CC40F3C185AA62F529E10F15ADC9BA801DBA886B1738
+IV=C36FEDCB97DA734243A20C49D5942DD1
+PT=18B252CEB124BD110693936ABD05A8A8
+CT=94C9A6BDB97522FACEE2E869C3C48FB0
+
+I=134
+KEY=F08C23DDC110ED40F63C8F5CB6608F337462F5D34BAF9888
+IV=94C9A6BDB97522FACEE2E869C3C48FB0
+PT=154FF810E3F0CE586A9EEF9D32D168EA
+CT=AFC8D15F80F19F942FCA22DA0DF79937
+
+I=135
+KEY=B1224FF7293C5DC559F45E03369110A75BA8D709465801BF
+IV=AFC8D15F80F19F942FCA22DA0DF79937
+PT=259A6B069CA3273C41AE6C2AE82CB085
+CT=5AADC1716B2ED4FC7CA9825A32EA2FB1
+
+I=136
+KEY=D29A829813CC5B4103599F725DBFC45B2701555374B22E0E
+IV=5AADC1716B2ED4FC7CA9825A32EA2FB1
+PT=CB78C574D9B1B9EF63B8CD6F3AF00684
+CT=EACB8D3001640F340DFB459CD8D162BD
+
+I=137
+KEY=1049116DD39F7B30E99212425CDBCB6F2AFA10CFAC634CB3
+IV=EACB8D3001640F340DFB459CD8D162BD
+PT=DF461D135DE19FA2C2D393F5C0532071
+CT=9115EB33739C04AAE22765621A8852C5
+
+I=138
+KEY=A129CBBF89658D977887F9712F47CFC5C8DD75ADB6EB1E76
+IV=9115EB33739C04AAE22765621A8852C5
+PT=E32AF908A190B95FB160DAD25AFAF6A7
+CT=B171D8AC24C6873B54F42D5DAC51ED34
+
+I=139
+KEY=EE7226D88DFA48DFC9F621DD0B8148FE9C2958F01ABAF342
+IV=B171D8AC24C6873B54F42D5DAC51ED34
+PT=0A669BB00E2123B54F5BED67049FC548
+CT=CFFC81B70593A36D022248D1CBE7FC58
+
+I=140
+KEY=C907918503B2C1C0060AA06A0E12EB939E0B1021D15D0F1A
+IV=CFFC81B70593A36D022248D1CBE7FC58
+PT=E9B1E6FA006D4CEE2775B75D8E48891F
+CT=0B3B02FC8A8D677B8077D7FDF9EB0396
+
+I=141
+KEY=E468A0560DB602C10D31A296849F8CE81E7CC7DC28B60C8C
+IV=0B3B02FC8A8D677B8077D7FDF9EB0396
+PT=AA3626C69662AE442D6F31D30E04C301
+CT=2C78C31D4B2EBAEF54CB6D04C4375196
+
+I=142
+KEY=EB8BCD80D3E35CCB2149618BCFB136074AB7AAD8EC815D1A
+IV=2C78C31D4B2EBAEF54CB6D04C4375196
+PT=5017BD9EB52514180FE36DD6DE555E0A
+CT=67D2DD54A0881186DFA6A608C036CE61
+
+I=143
+KEY=7065D92686BA37E9469BBCDF6F39278195110CD02CB7937B
+IV=67D2DD54A0881186DFA6A608C036CE61
+PT=6CBC1C2DAA3A7F7B9BEE14A655596B22
+CT=62163C88A40E7CFF7522A3DC32F30BCF
+
+I=144
+KEY=E0B4AE9D6C9A5A92248D8057CB375B7EE033AF0C1E4498B4
+IV=62163C88A40E7CFF7522A3DC32F30BCF
+PT=0F6C44EE5E2587A790D177BBEA206D7B
+CT=B84A631DE451F109C48785DE3D4099C2
+
+I=145
+KEY=DDCDB4F73AA0C8789CC7E34A2F66AA7724B42AD223040176
+IV=B84A631DE451F109C48785DE3D4099C2
+PT=EE1EA5C5340C2F263D791A6A563A92EA
+CT=D438E983DB81DA9341CE1AC45F4E7E52
+
+I=146
+KEY=813604E941CBDF6448FF0AC9F4E770E4657A30167C4A7F24
+IV=D438E983DB81DA9341CE1AC45F4E7E52
+PT=08E1F94874432DBD5CFBB01E7B6B171C
+CT=0E1C069CB75D4EDF4243D1E6D7175425
+
+I=147
+KEY=D64EB9DE5A3B546B46E30C5543BA3E3B2739E1F0AB5D2B01
+IV=0E1C069CB75D4EDF4243D1E6D7175425
+PT=CFCDC1C0EFE678FB5778BD371BF08B0F
+CT=CBC0ED542E26A1943926EF7897A79E97
+
+I=148
+KEY=D1659785D1D551948D23E1016D9C9FAF1E1F0E883CFAB596
+IV=CBC0ED542E26A1943926EF7897A79E97
+PT=1FEA178A348CAE8B072B2E5B8BEE05FF
+CT=C743A7B60EB7C24867DA82AFF15ED18A
+
+I=149
+KEY=05786C3E1FBE51864A6046B7632B5DE779C58C27CDA4641C
+IV=C743A7B60EB7C24867DA82AFF15ED18A
+PT=3A4EF6696CD26875D41DFBBBCE6B0012
+CT=EA23014227CF7B563AEFF86DB947FAC4
+
+I=150
+KEY=CE1E5D5BF32BF0CAA04347F544E426B1432A744A74E39ED8
+IV=EA23014227CF7B563AEFF86DB947FAC4
+PT=DFDF9B4032986E90CB663165EC95A14C
+CT=EAF762B60A106C03B76742E69CEE385A
+
+I=151
+KEY=F8EAC01B3F7E925A4AB425434EF44AB2F44D36ACE80DA682
+IV=EAF762B60A106C03B76742E69CEE385A
+PT=2BDC6EAB1D86311D36F49D40CC556290
+CT=E6CC0491C3509240ED848AE304CC3385
+
+I=152
+KEY=BF5AE8B244244B4BAC7821D28DA4D8F219C9BC4FECC19507
+IV=E6CC0491C3509240ED848AE304CC3385
+PT=81D4E28E02717AB347B028A97B5AD911
+CT=11EE9D22AC798AB5FEF6C6188845F425
+
+I=153
+KEY=5C6538235111334FBD96BCF021DD5247E73F7A5764846122
+IV=11EE9D22AC798AB5FEF6C6188845F425
+PT=DDE402413BB09DFBE33FD09115357804
+CT=3F054911089500FD2CD0645DBFE2A8D3
+
+I=154
+KEY=FAC914FA6B6CA1AB8293F5E1294852BACBEF1E0ADB66C9F1
+IV=3F054911089500FD2CD0645DBFE2A8D3
+PT=345343E023AC39FFA6AC2CD93A7D92E4
+CT=7538E78DE8FC09D203010C61422E6B5A
+
+I=155
+KEY=1E62F54271EA4374F7AB126CC1B45B68C8EE126B9948A2AB
+IV=7538E78DE8FC09D203010C61422E6B5A
+PT=0EC4357C476EB76AE4ABE1B81A86E2DF
+CT=3A4D0093A2B7FF807BAA6A815538507E
+
+I=156
+KEY=5AD3B884BE5653BBCDE612FF6303A4E8B34478EACC70F2D5
+IV=3A4D0093A2B7FF807BAA6A815538507E
+PT=F59FD86893B7DF7244B14DC6CFBC10CF
+CT=2C2FD7DF94FDDC2CA1C05EF5878583FF
+
+I=157
+KEY=B9039E1678902ECCE1C9C520F7FE78C41284261F4BF5712A
+IV=2C2FD7DF94FDDC2CA1C05EF5878583FF
+PT=4600E6CCD65B575AE3D02692C6C67D77
+CT=59C9FA2E4A2227C3E5B831899A3CCBFD
+
+I=158
+KEY=394A8245256D72B8B8003F0EBDDC5F07F73C1796D1C9BAD7
+IV=59C9FA2E4A2227C3E5B831899A3CCBFD
+PT=3030D8E24F7BEA0580491C535DFD5C74
+CT=DEAFC4A07A3FB5D5AA09FF6A2515AB4A
+
+I=159
+KEY=2496931DFCFF2E7166AFFBAEC7E3EAD25D35E8FCF4DC119D
+IV=DEAFC4A07A3FB5D5AA09FF6A2515AB4A
+PT=63CD1CC241B267791DDC1158D9925CC9
+CT=B1B0AED275FCE241B5726E943B37C130
+
+I=160
+KEY=53CBA419E5CED1C8D71F557CB21F0893E8478668CFEBD0AD
+IV=B1B0AED275FCE241B5726E943B37C130
+PT=85F4E06A05C8704A775D37041931FFB9
+CT=B0DFD3EF3AF538791E69AF59CAA7B8CC
+
+I=161
+KEY=DFB0E5440EB582F667C0869388EA30EAF62E2931054C6861
+IV=B0DFD3EF3AF538791E69AF59CAA7B8CC
+PT=B7BDA6C504797C8B8C7B415DEB7B533E
+CT=220F810B0D5A9ED8794932D0BF6150D6
+
+I=162
+KEY=B26A70894070BC9B45CF079885B0AE328F671BE1BA2D38B7
+IV=220F810B0D5A9ED8794932D0BF6150D6
+PT=0113567BFAC19EB86DDA95CD4EC53E6D
+CT=56C77682CA1A041B312061F3FB9A1A59
+
+I=163
+KEY=36EDA74B7133D5871308711A4FAAAA29BE477A1241B722EE
+IV=56C77682CA1A041B312061F3FB9A1A59
+PT=4D39AD87258968FA8487D7C23143691C
+CT=4F18208E63B2D84CC7A0707617DD7B63
+
+I=164
+KEY=F7589312CE997AFE5C1051942C18726579E70A64566A598D
+IV=4F18208E63B2D84CC7A0707617DD7B63
+PT=1B82F5C849E0F965C1B53459BFAAAF79
+CT=85CE0310DEFB36474B38C4347D7EEE8B
+
+I=165
+KEY=F770FC7B1E183E31D9DE5284F2E3442232DFCE502B14B706
+IV=85CE0310DEFB36474B38C4347D7EEE8B
+PT=7B56EBC47E780FB000286F69D08144CF
+CT=CB5AE674DB1426618F577BBD63309EA4
+
+I=166
+KEY=79AD3040CCC9FD521284B4F029F76243BD88B5ED482429A2
+IV=CB5AE674DB1426618F577BBD63309EA4
+PT=47A5B213BC3DF61B8EDDCC3BD2D1C363
+CT=1E26AB2D8B156913995FCAC1ABD99D68
+
+I=167
+KEY=10BB9597F823B61F0CA21FDDA2E20B5024D77F2CE3FDB4CA
+IV=1E26AB2D8B156913995FCAC1ABD99D68
+PT=D31FC11C9FD6E7F86916A5D734EA4B4D
+CT=84E0E24F155E5EFCA9AE9C5F2F26BD25
+
+I=168
+KEY=E1264A2AD33800FF8842FD92B7BC55AC8D79E373CCDB09EF
+IV=84E0E24F155E5EFCA9AE9C5F2F26BD25
+PT=F77FE11AE4BEB403F19DDFBD2B1BB6E0
+CT=B41973B0D807A43A822EB57555B818D4
+
+I=169
+KEY=A19ABDD25ED272693C5B8E226FBBF1960F5756069963113B
+IV=B41973B0D807A43A822EB57555B818D4
+PT=FECAAA8EA9C1883640BCF7F88DEA7296
+CT=949634E68FB9086AE623EAF5E867D4A5
+
+I=170
+KEY=DD904ECCC94F64D0A8CDBAC4E002F9FCE974BCF37104C59E
+IV=949634E68FB9086AE623EAF5E867D4A5
+PT=E8A413C2ADB97D387C0AF31E979D16B9
+CT=96BE2B618F8A961E5DC892F429A8B6FC
+
+I=171
+KEY=1B83C20396D7D0D33E7391A56F886FE2B4BC2E0758AC7362
+IV=96BE2B618F8A961E5DC892F429A8B6FC
+PT=1408434BF0C3432BC6138CCF5F98B403
+CT=C0A9596F56E48F459D2C405F47DCA44C
+
+I=172
+KEY=B04C71DBEA60DB15FEDAC8CA396CE0A729906E581F70D72E
+IV=C0A9596F56E48F459D2C405F47DCA44C
+PT=5E7F070C7EE8A852ABCFB3D87CB70BC6
+CT=A4739C93911C72C959E89544500843BD
+
+I=173
+KEY=9BFC8026BC1D965B5AA95459A870926E7078FB1C4F789493
+IV=A4739C93911C72C959E89544500843BD
+PT=718C23D1F537A6E72BB0F1FD567D4D4E
+CT=4D581200B1E446CC3AD306138BF2898B
+
+I=174
+KEY=FEA9DF8F4FECB3ED17F146591994D4A24AABFD0FC48A1D18
+IV=4D581200B1E446CC3AD306138BF2898B
+PT=E4DD231D871795E065555FA9F3F125B6
+CT=E53EFC19D8048073167B1473C5EBA6D9
+
+I=175
+KEY=62DF036D6F96D937F2CFBA40C19054D15CD0E97C0161BBC1
+IV=E53EFC19D8048073167B1473C5EBA6D9
+PT=9AB809114F10C3FD9C76DCE2207A6ADA
+CT=BDB0C3D9732DE5813C4C72CF01FF5194
+
+I=176
+KEY=CFEF04F0343587004F7F7999B2BDB150609C9BB3009EEA55
+IV=BDB0C3D9732DE5813C4C72CF01FF5194
+PT=B4CFE094F8B4EEE5AD30079D5BA35E37
+CT=D00B5B980D8B10DF3D7D4C0BE5975C1C
+
+I=177
+KEY=CBF2C475C11FA6B89F742201BF36A18F5DE1D7B8E509B649
+IV=D00B5B980D8B10DF3D7D4C0BE5975C1C
+PT=34B39728291953DC041DC085F52A21B8
+CT=ADF5CDFDCC23AD8AD111454B2DB69013
+
+I=178
+KEY=C96820A08056F7C23281EFFC73150C058CF092F3C8BF265A
+IV=ADF5CDFDCC23AD8AD111454B2DB69013
+PT=4C8152CCAA0A23AC029AE4D54149517A
+CT=F070979F68BAEBBD6CE8CE8A549C0E12
+
+I=179
+KEY=61A6BBDB58B4C9D4C2F178631BAFE7B8E0185C799C232848
+IV=F070979F68BAEBBD6CE8CE8A549C0E12
+PT=0B6AF20EF8550A1BA8CE9B7BD8E23E16
+CT=8A75D276384A4F468B459466A304D418
+
+I=180
+KEY=D3EC560DE8B1BBEE4884AA1523E5A8FE6B5DC81F3F27FC50
+IV=8A75D276384A4F468B459466A304D418
+PT=259A18BABFD09145B24AEDD6B005723A
+CT=B7C04F66EB771CBD97F948098E23C655
+
+I=181
+KEY=16FE806749FDDF8CFF44E573C892B443FCA48016B1043A05
+IV=B7C04F66EB771CBD97F948098E23C655
+PT=E00B5E4B3D9E64D0C512D66AA14C6462
+CT=29FB08289BD19BCC0FEB0F433D5CACEE
+
+I=182
+KEY=9CC345922C8912D5D6BFED5B53432F8FF34F8F558C5896EB
+IV=29FB08289BD19BCC0FEB0F433D5CACEE
+PT=07BAA266554EAE0C8A3DC5F56574CD59
+CT=495C245E2F3CC52499B9C1AD7C4484BA
+
+I=183
+KEY=7DDDCF7DE759FDEC9FE3C9057C7FEAAB6AF64EF8F01C1251
+IV=495C245E2F3CC52499B9C1AD7C4484BA
+PT=2E5360D5563EB7D4E11E8AEFCBD0EF39
+CT=68267051421D3AFA19A2E43D501B940B
+
+I=184
+KEY=4BA2EAD4106DD4B7F7C5B9543E62D0517354AAC5A007865A
+IV=68267051421D3AFA19A2E43D501B940B
+PT=050EBC6942F92D95367F25A9F734295B
+CT=1781558A2A8B7C29AC82D6610B67E3CF
+
+I=185
+KEY=CFCCD4ECD20E051CE044ECDE14E9AC78DFD67CA4AB606595
+IV=1781558A2A8B7C29AC82D6610B67E3CF
+PT=1AC90B21EB197E26846E3E38C263D1AB
+CT=BF5FE87A2E882A64493850EC3A0E93A5
+
+I=186
+KEY=C9EA5F992C77DD9C5F1B04A43A61861C96EE2C48916EF630
+IV=BF5FE87A2E882A64493850EC3A0E93A5
+PT=58F997704D085DC506268B75FE79D880
+CT=8F43A961964E3452094E8E71295177CD
+
+I=187
+KEY=1136648F9E0A53C3D058ADC5AC2FB24E9FA0A239B83F81FD
+IV=8F43A961964E3452094E8E71295177CD
+PT=086041AB29E423EFD8DC3B16B27D8E5F
+CT=BF69230BAB6200B7828DC04A13B88E83
+
+I=188
+KEY=47040E2D6DFBE3006F318ECE074DB2F91D2D6273AB870F7E
+IV=BF69230BAB6200B7828DC04A13B88E83
+PT=57865A8650D3202056326AA2F3F1B0C3
+CT=A012FAEE65E2C4F0AC22CB63AB75E35D
+
+I=189
+KEY=868F8310E79C0473CF23742062AF7609B10FA91000F2EC23
+IV=A012FAEE65E2C4F0AC22CB63AB75E35D
+PT=F3ABB47DAE94B82EC18B8D3D8A67E773
+CT=F35BBD3C516F86384DA3BB6B5CCC8B37
+
+I=190
+KEY=5C71ADCE480714DA3C78C91C33C0F031FCAC127B5C3E6714
+IV=F35BBD3C516F86384DA3BB6B5CCC8B37
+PT=CDB3E57FA6DDFF9FDAFE2EDEAF9B10A9
+CT=627A15E65B37C2B9575E8A781271AE64
+
+I=191
+KEY=B603092BC5FD004F5E02DCFA68F73288ABF298034E4FC970
+IV=627A15E65B37C2B9575E8A781271AE64
+PT=7E04F9A0F723DF00EA72A4E58DFA1495
+CT=15427D27E783A5476345C83F3E8A3319
+
+I=192
+KEY=4DB5A9F825C5E8C24B40A1DD8F7497CFC8B7503C70C5FA69
+IV=15427D27E783A5476345C83F3E8A3319
+PT=842B94BE25E8747BFBB6A0D3E038E88D
+CT=35812AFD1A90B0B7D52B45EAD9CAF083
+
+I=193
+KEY=D4F2CCC0734F9ACD7EC18B2095E427781D9C15D6A90F0AEA
+IV=35812AFD1A90B0B7D52B45EAD9CAF083
+PT=3FAB7D4C741B8CD499476538568A720F
+CT=C1A59CD3D9E6650F0D16947D26BFC20D
+
+I=194
+KEY=CB28A8313E133469BF6417F34C024277108A81AB8FB0C8E7
+IV=C1A59CD3D9E6650F0D16947D26BFC20D
+PT=37AC888DCE5CDFD31FDA64F14D5CAEA4
+CT=CB0313E9A046711866CA65702A45CDB6
+
+I=195
+KEY=C5BFEB8246ABAF467467041AEC44336F7640E4DBA5F50551
+IV=CB0313E9A046711866CA65702A45CDB6
+PT=326C9E3EB49138ED0E9743B378B89B2F
+CT=ACE8FC6C6ABBC8124FE35C7976585DF6
+
+I=196
+KEY=110891F8FDF0F254D88FF87686FFFB7D39A3B8A2D3AD58A7
+IV=ACE8FC6C6ABBC8124FE35C7976585DF6
+PT=964239EB84C57F61D4B77A7ABB5B5D12
+CT=0762EF13B80A8B77D04AF797B67D5AA6
+
+I=197
+KEY=EFF558976586AC91DFED17653EF5700AE9E94F3565D00201
+IV=0762EF13B80A8B77D04AF797B67D5AA6
+PT=5ECA17ADFE3C2C21FEFDC96F98765EC5
+CT=B60CC9CD9DE93E2A6FB0B59369B1628E
+
+I=198
+KEY=4494A36EABE3555E69E1DEA8A31C4E208659FAA60C61608F
+IV=B60CC9CD9DE93E2A6FB0B59369B1628E
+PT=7A659E803888296BAB61FBF9CE65F9CF
+CT=73258A43C7DA66FFE4DC9384FC7A60C1
+
+I=199
+KEY=1780249B48B8F7561AC454EB64C628DF62856922F01B004E
+IV=73258A43C7DA66FFE4DC9384FC7A60C1
+PT=8D9C3DCF612320B4531487F5E35BA208
+CT=F0F5D51C06F2D900CC4BE8D3512CA4B6
+
+I=200
+KEY=9FF03D1E23BD9959EA3181F76234F1DFAECE81F1A137A4F8
+IV=F0F5D51C06F2D900CC4BE8D3512CA4B6
+PT=F002AEC878B80A0B887019856B056E0F
+CT=E1321C52A51D9345296A0EF2A9DC9CC5
+
+I=201
+KEY=6042967162EDA50B0B039DA5C729629A87A48F0308EB383D
+IV=E1321C52A51D9345296A0EF2A9DC9CC5
+PT=C5EA4A519D9BAF8FFFB2AB6F41503C52
+CT=ED79D8FC9C60B583E29D0A65A6A5F321
+
+I=202
+KEY=250C416206B9D0A9E67A45595B49D71965398566AE4ECB1C
+IV=ED79D8FC9C60B583E29D0A65A6A5F321
+PT=34D771B44B3943DE454ED713645475A2
+CT=7A08F9096109535C262407EB323EF7BC
+
+I=203
+KEY=6357BC1B7B12F1C09C72BC503A408445431D828D9C703CA0
+IV=7A08F9096109535C262407EB323EF7BC
+PT=60A1EEAE2B16841A465BFD797DAB2169
+CT=24C7F1A39F8B2F03C256F5C59B69C31A
+
+I=204
+KEY=18BF29D147A9675BB8B54DF3A5CBAB46814B77480719FFBA
+IV=24C7F1A39F8B2F03C256F5C59B69C31A
+PT=BFD7B314F959298B7BE895CA3CBB969B
+CT=7DDA5DF3CC7C69AA490FB597888396B2
+
+I=205
+KEY=E8B13C48FBABCD19C56F100069B7C2ECC844C2DF8F9A6908
+IV=7DDA5DF3CC7C69AA490FB597888396B2
+PT=23F8A60BD2354901F00E1599BC02AA42
+CT=04CEB4BE252293A822C77B9C4C27822B
+
+I=206
+KEY=BF275C4D9FC54BC0C1A1A4BE4C955144EA83B943C3BDEB23
+IV=04CEB4BE252293A822C77B9C4C27822B
+PT=2182C0577EAA3C2A57966005646E86D9
+CT=0F24034642E351984620BB2647F5D649
+
+I=207
+KEY=40B459144A6415C2CE85A7F80E7600DCACA3026584483D6A
+IV=0F24034642E351984620BB2647F5D649
+PT=F59318D1D3D9A9E0FF930559D5A15E02
+CT=DB98808C46668D79AB059C5554CEEB1A
+
+I=208
+KEY=D5A01AB42D709E6A151D277448108DA507A69E30D086D670
+IV=DB98808C46668D79AB059C5554CEEB1A
+PT=49CF142E621D1A8D951443A067148BA8
+CT=15C32FE5E9BCA5F8D09EA2E4D145FE3D
+
+I=209
+KEY=8191AB3C11B4B72700DE0891A1AC285DD7383CD401C3284D
+IV=15C32FE5E9BCA5F8D09EA2E4D145FE3D
+PT=5C1E9B721987B8BF5431B1883CC4294D
+CT=AA7CA217D0514CA4F20C50293121E8D8
+
+I=210
+KEY=69D24875B8A5B5D1AAA2AA8671FD64F925346CFD30E2C095
+IV=AA7CA217D0514CA4F20C50293121E8D8
+PT=8239553D8FB88E17E843E349A91102F6
+CT=C4068B901CB07904F843BF6F3CDC4FF8
+
+I=211
+KEY=12BAE3B5B2C03E746EA421166D4D1DFDDD77D3920C3E8F6D
+IV=C4068B901CB07904F843BF6F3CDC4FF8
+PT=80D797C671D3BFF67B68ABC00A658BA5
+CT=9F835417C4D622DB52651897DC23E1C3
+
+I=212
+KEY=1A0CFD7FA1284652F1277501A99B3F268F12CB05D01D6EAE
+IV=9F835417C4D622DB52651897DC23E1C3
+PT=C36513D78FBBFDCC08B61ECA13E87826
+CT=0156C998E85BE92F0EF998442204EB19
+
+I=213
+KEY=7829D1FE113103B0F071BC9941C0D60981EB5341F21985B7
+IV=0156C998E85BE92F0EF998442204EB19
+PT=000894F1AF39A67562252C81B01945E2
+CT=6A554057C0A3EB723B693258BC5E899D
+
+I=214
+KEY=D719D37FC9087D2F9A24FCCE81633D7BBA8261194E470C2A
+IV=6A554057C0A3EB723B693258BC5E899D
+PT=B92413276BF142D0AF300281D8397E9F
+CT=395F80E405813D97576954A23C77C2CA
+
+I=215
+KEY=39E173517A321A5AA37B7C2A84E200ECEDEB35BB7230CEE0
+IV=395F80E405813D97576954A23C77C2CA
+PT=AA95F2BD255DBE23EEF8A02EB33A6775
+CT=1B1BC5D3DABD536E91177EF1BF2B7E39
+
+I=216
+KEY=EE1FB67D907C597BB860B9F95E5F53827CFC4B4ACD1BB0D9
+IV=1B1BC5D3DABD536E91177EF1BF2B7E39
+PT=985E81E0BF5FF6EFD7FEC52CEA4E4321
+CT=20F42326749CC7CCD54188DEA46F4EC1
+
+I=217
+KEY=41D333EC5E537B8098949ADF2AC3944EA9BDC3946974FE18
+IV=20F42326749CC7CCD54188DEA46F4EC1
+PT=901FD7D22F220608AFCC8591CE2F22FB
+CT=AFFC6F2668097B58A0CFF619A3FDD1CB
+
+I=218
+KEY=F6E392EF75572C6A3768F5F942CAEF160972358DCA892FD3
+IV=AFFC6F2668097B58A0CFF619A3FDD1CB
+PT=45AEB51360C50AB1B730A1032B0457EA
+CT=1B75CF440CE8521069599B7889F21C1D
+
+I=219
+KEY=47C82CF46472D3732C1D3ABD4E22BD06602BAEF5437B33CE
+IV=1B75CF440CE8521069599B7889F21C1D
+PT=7E931056CC33D22CB12BBE1B1125FF19
+CT=F6079ADBAA8D28F371F0156B170FB7BD
+
+I=220
+KEY=DDA62A9922B04902DA1AA066E4AF95F511DBBB9E54748473
+IV=F6079ADBAA8D28F371F0156B170FB7BD
+PT=2BE3DA337C9187109A6E066D46C29A71
+CT=7D2FC16B26971DDC20C6F7510C47B352
+
+I=221
+KEY=570C8CA5236A2E65A735610DC2388829311D4CCF58333721
+IV=7D2FC16B26971DDC20C6F7510C47B352
+PT=43596064590570F88AAAA63C01DA6767
+CT=5FBA845FB25FE6AE015E4E8A228ED645
+
+I=222
+KEY=6CEA158ED663A4B7F88FE55270676E87304302457ABDE164
+IV=5FBA845FB25FE6AE015E4E8A228ED645
+PT=1E265F0AA9A20C603BE6992BF5098AD2
+CT=A729E250D736A43966DD0D9C461ECEC0
+
+I=223
+KEY=AACCE3387C0DF35D5FA60702A751CABE569E0FD93CA32FA4
+IV=A729E250D736A43966DD0D9C461ECEC0
+PT=B08AAE113CCE6226C626F6B6AA6E57EA
+CT=A8192E964A74A6ABDB463ECFA483A1E3
+
+I=224
+KEY=207F19ABDA13F728F7BF2994ED256C158DD8311698208E47
+IV=A8192E964A74A6ABDB463ECFA483A1E3
+PT=858CF92E6B1793448AB3FA93A61E0475
+CT=060C7CCCD58E6348518161C7878AA71B
+
+I=225
+KEY=AB05AD81CF07091AF1B3555838AB0F5DDC5950D11FAA295C
+IV=060C7CCCD58E6348518161C7878AA71B
+PT=424D175035503C728B7AB42A1514FE32
+CT=8ECAA12830B0C5B4C6950E69AFD31B66
+
+I=226
+KEY=3A8E1CC01464AF9B7F79F470081BCAE91ACC5EB8B079323A
+IV=8ECAA12830B0C5B4C6950E69AFD31B66
+PT=6E5A94391F1FE5A9918BB141DB63A681
+CT=65C3A891192324A7FA3C882B2C09CB8D
+
+I=227
+KEY=8004AB13CF38B3ED1ABA5CE11138EE4EE0F0D6939C70F9B7
+IV=65C3A891192324A7FA3C882B2C09CB8D
+PT=584E219335CA4642BA8AB7D3DB5C1C76
+CT=F29F8735A403414621F2100AF38A500C
+
+I=228
+KEY=D37BB962CFC53E77E825DBD4B53BAF08C102C6996FFAA9BB
+IV=F29F8735A403414621F2100AF38A500C
+PT=CCB996C23C627D4D537F127100FD8D9A
+CT=9C6A7655E25E9231E46C0D3B57C7FCAB
+
+I=229
+KEY=C23B3C983C79179A744FAD8157653D39256ECBA2383D5510
+IV=9C6A7655E25E9231E46C0D3B57C7FCAB
+PT=5D727E12D3932F56114085FAF3BC29ED
+CT=6C5AA7364755AF599AB6F86EC8B24C52
+
+I=230
+KEY=4462CD1DD817170C18150AB710309260BFD833CCF08F1942
+IV=6C5AA7364755AF599AB6F86EC8B24C52
+PT=D7A99C8F3BC37AD08659F185E46E0096
+CT=821D7EAC8FD041C0C8CF1011661FBB9E
+
+I=231
+KEY=1BA52BEF2B010D169A08741B9FE0D3A0771723DD9690A2DC
+IV=821D7EAC8FD041C0C8CF1011661FBB9E
+PT=704F3525510FCC745FC7E6F2F3161A1A
+CT=44591D71D64FC38010E402874853E9BC
+
+I=232
+KEY=C6A6818229CC65E6DE51696A49AF102067F3215ADEC34B60
+IV=44591D71D64FC38010E402874853E9BC
+PT=5D5769AE155C9F43DD03AA6D02CD68F0
+CT=E5647FF6C843543E484FC13B58A345B9
+
+I=233
+KEY=41F27DD5905B299C3B35169C81EC441E2FBCE06186600ED9
+IV=E5647FF6C843543E484FC13B58A345B9
+PT=ADF29030DFDFCCEE8754FC57B9974C7A
+CT=E6EA42E2F046D3ED75081A50770563D1
+
+I=234
+KEY=3A8018855EDC80D2DDDF547E71AA97F35AB4FA31F1656D08
+IV=E6EA42E2F046D3ED75081A50770563D1
+PT=096F74717D5583477B726550CE87A94E
+CT=D75682FE37396887659E87895F1C6441
+
+I=235
+KEY=6C94C2634142DA310A89D6804693FF743F2A7DB8AE790949
+IV=D75682FE37396887659E87895F1C6441
+PT=F1B527DD4935FBDE5614DAE61F9E5AE3
+CT=15755CFE84E113AA751E4D5BB098ABC7
+
+I=236
+KEY=4BA407D7C6426C641FFC8A7EC272ECDE4A3430E31EE1A28E
+IV=15755CFE84E113AA751E4D5BB098ABC7
+PT=7C4433DCC314DBD72730C5B48700B655
+CT=B048F209CE1B1FAEC33392D2D8F326A1
+
+I=237
+KEY=A56FD7BCEEA55474AFB478770C69F3708907A231C612842F
+IV=B048F209CE1B1FAEC33392D2D8F326A1
+PT=D40C7CD8D80C8C6CEECBD06B28E73810
+CT=8E1F4830F94004C286C39D0EC014A963
+
+I=238
+KEY=0730B7B664CFD1E321AB3047F529F7B20FC43F3F06062D4C
+IV=8E1F4830F94004C286C39D0EC014A963
+PT=B16772FE8C8A573FA25F600A8A6A8597
+CT=3FB92771D2BE2D33C40AB0409998B229
+
+I=239
+KEY=0A08E43B13C57EB41E1217362797DA81CBCE8F7F9F9E9F65
+IV=3FB92771D2BE2D33C40AB0409998B229
+PT=D4883476825EA2D30D38538D770AAF57
+CT=190106DE79836016C57A16BBBA6893D2
+
+I=240
+KEY=195B7E1B67872B0D071311E85E14BA970EB499C425F60CB7
+IV=190106DE79836016C57A16BBBA6893D2
+PT=3B8F4F140FDFFB6B13539A20744255B9
+CT=C06398537B4F534203D57184543E6516
+
+I=241
+KEY=BE0C4A8A9B581D16C77089BB255BE9D50D61E84071C869A1
+IV=C06398537B4F534203D57184543E6516
+PT=E50D127AE258061DA7573491FCDF361B
+CT=FF615CCC9F2D3DBB3074C835ECE4224E
+
+I=242
+KEY=662A224DAB1233C83811D577BA76D46E3D1520759D2C4BEF
+IV=FF615CCC9F2D3DBB3074C835ECE4224E
+PT=347C976D20470968D82668C7304A2EDE
+CT=B5FB1BCCBC838B87FDB10FEFE6CDC45B
+
+I=243
+KEY=F4F3B47D9CC8BA798DEACEBB06F55FE9C0A42F9A7BE18FB4
+IV=B5FB1BCCBC838B87FDB10FEFE6CDC45B
+PT=BC276D1002C5DD8292D9963037DA89B1
+CT=151F88A44A76568FAC756011B827778D
+
+I=244
+KEY=7EA3C03193B737DE98F5461F4C8309666CD14F8BC3C6F839
+IV=151F88A44A76568FAC756011B827778D
+PT=BCD9054596EE644E8A50744C0F7F8DA7
+CT=C1B0B6FDD717881442496794A2C890F2
+
+I=245
+KEY=C4D94D5C4169EE4B5945F0E29B9481722E98281F610E68CB
+IV=C1B0B6FDD717881442496794A2C890F2
+PT=3D7F68D3014F3BEDBA7A8D6DD2DED995
+CT=181100A04881DCF9813E4A22C6C1BB3B
+
+I=246
+KEY=A9A9483D9FC46DD34154F042D3155D8BAFA6623DA7CFD3F0
+IV=181100A04881DCF9813E4A22C6C1BB3B
+PT=0FE2E2A97DFFB4966D700561DEAD8398
+CT=AA4BEC4007C38C7B86B6F9EED33E5EB1
+
+I=247
+KEY=5F08A3C09F4AE90BEB1F1C02D4D6D1F029109BD374F18D41
+IV=AA4BEC4007C38C7B86B6F9EED33E5EB1
+PT=C2392264CE43C57AF6A1EBFD008E84D8
+CT=A0756CCDA72462CD89DF9990C0FE6676
+
+I=248
+KEY=6A1A4F2D25DFC9F94B6A70CF73F2B33DA0CF0243B40FEB37
+IV=A0756CCDA72462CD89DF9990C0FE6676
+PT=A6650A3432CCA74A3512ECEDBA9520F2
+CT=F5044AECC6F35C99FCDBA26DD15E1474
+
+I=249
+KEY=B475174A46D0CDC2BE6E3A23B501EFA45C14A02E6551FF43
+IV=F5044AECC6F35C99FCDBA26DD15E1474
+PT=07967DE17DEB720CDE6F5867630F043B
+CT=60645B559E7321D7FA8A3F925CFC0FA4
+
+I=250
+KEY=8DBB9D8A4A2E7E61DE0A61762B72CE73A69E9FBC39ADF0E7
+IV=60645B559E7321D7FA8A3F925CFC0FA4
+PT=D8D3FD2077545DD039CE8AC00CFEB3A3
+CT=C4C6FD53A2572D643AA631FB85B84D0B
+
+I=251
+KEY=97D34E4B3B9E081A1ACC9C258925E3179C38AE47BC15BDEC
+IV=C4C6FD53A2572D643AA631FB85B84D0B
+PT=F31D8F3C8AC67E081A68D3C171B0767B
+CT=E1A0E460E2D1483FE954F26F45CCE7A0
+
+I=252
+KEY=5372C72A4ABF72D9FB6C78456BF4AB28756C5C28F9D95A4C
+IV=E1A0E460E2D1483FE954F26F45CCE7A0
+PT=422C5429CE7BD811C4A1896171217AC3
+CT=2695923CFB2141F05A0F144FF021BD36
+
+I=253
+KEY=A8CA6DB8A8758322DDF9EA7990D5EAD82F63486709F8E77A
+IV=2695923CFB2141F05A0F144FF021BD36
+PT=780771C65FCB907BFBB8AA92E2CAF1FB
+CT=A9820B527F71E95CC1F53033149FB26F
+
+I=254
+KEY=62ABF1F4178F3C73747BE12BEFA40384EE9678541D675515
+IV=A9820B527F71E95CC1F53033149FB26F
+PT=CCC14BD8DF1CA8A4CA619C4CBFFABF51
+CT=2BAD4E8CD7D6420D36DC2F8E77DCA072
+
+I=255
+KEY=C79B767D31D9F0FC5FD6AFA738724189D84A57DA6ABBF567
+IV=2BAD4E8CD7D6420D36DC2F8E77DCA072
+PT=1EFF63C71B10DCC7A53087892656CC8F
+CT=C21303AAB04E2CAF1893396DD405B265
+
+I=256
+KEY=1F3C7FF71340DEEC9DC5AC0D883C6D26C0D96EB7BEBE4702
+IV=C21303AAB04E2CAF1893396DD405B265
+PT=209270B7768E5553D8A7098A22992E10
+CT=B220025B5307C9D5D1EEB4B427E7263F
+
+I=257
+KEY=867CB381E6D532B32FE5AE56DB3BA4F31137DA039959613D
+IV=B220025B5307C9D5D1EEB4B427E7263F
+PT=8546A6C9B4CEF0229940CC76F595EC5F
+CT=B925C660EBE409050DA369E58C601F4D
+
+I=258
+KEY=33B33F93622E509296C0683630DFADF61C94B3E615397E70
+IV=B925C660EBE409050DA369E58C601F4D
+PT=1F4930242C2951C4B5CF8C1284FB6221
+CT=67DA7B4BEAB2152D21C54F389F9282D4
+
+I=259
+KEY=E8EC3394AF44DD34F11A137DDA6DB8DB3D51FCDE8AABFCA4
+IV=67DA7B4BEAB2152D21C54F389F9282D4
+PT=41611AE93BE61306DB5F0C07CD6A8DA6
+CT=4C116D3ED0B021129CCD1764D132A72D
+
+I=260
+KEY=92F61F4CB5794268BD0B7E430ADD99C9A19CEBBA5B995B89
+IV=4C116D3ED0B021129CCD1764D132A72D
+PT=E7B1E63FBD5B4CA77A1A2CD81A3D9F5C
+CT=FE1C3096C14AF2A4DC840207BFFFC0AF
+
+I=261
+KEY=08DC826B4DDBAC4D43174ED5CB976B6D7D18E9BDE4669B26
+IV=FE1C3096C14AF2A4DC840207BFFFC0AF
+PT=9A0D034B1931FD599A2A9D27F8A2EE25
+CT=ED500812A10CC6C4EED0836871F85AA9
+
+I=262
+KEY=486EBC43A876FF2AAE4746C76A9BADA993C86AD5959EC18F
+IV=ED500812A10CC6C4EED0836871F85AA9
+PT=8237641B58069AFD40B23E28E5AD5367
+CT=0AD90C1C13E7C1318057A417C0B9B97C
+
+I=263
+KEY=F340D2CAC4645595A49E4ADB797C6C98139FCEC2552778F3
+IV=0AD90C1C13E7C1318057A417C0B9B97C
+PT=905119E1F11E4B04BB2E6E896C12AABF
+CT=B260FFA5806A4A6D8845FA6146A565ED
+
+I=264
+KEY=DF326741BD1EE2FF16FEB57EF91626F59BDA34A313821D1E
+IV=B260FFA5806A4A6D8845FA6146A565ED
+PT=4F639233904531162C72B58B797AB76A
+CT=2D27A1A3968E30EBCA463C8709D0FD83
+
+I=265
+KEY=D4C684692E05983C3BD914DD6F98161E519C08241A52E09D
+IV=2D27A1A3968E30EBCA463C8709D0FD83
+PT=428B700FB3CD18790BF4E328931B7AC3
+CT=D350CCF3B440006C9F18E99DD5B69920
+
+I=266
+KEY=9DD5275FFDCD5D2DE889D82EDBD81672CE84E1B9CFE479BD
+IV=D350CCF3B440006C9F18E99DD5B69920
+PT=97F4A6256A9E22FB4913A336D3C8C511
+CT=F5A0571EB7E4719B862EBC47141EA319
+
+I=267
+KEY=0A3B329A4973D7A21D298F306C3C67E948AA5DFEDBFADAA4
+IV=F5A0571EB7E4719B862EBC47141EA319
+PT=E355F7EBA4DAC16B97EE15C5B4BE8A8F
+CT=4F18730073D3E78CAD356441F1317B2D
+
+I=268
+KEY=3BB3A19EF4EB8A755231FC301FEF8065E59F39BF2ACBA189
+IV=4F18730073D3E78CAD356441F1317B2D
+PT=A20B3B6C41E88E9D31889304BD985DD7
+CT=AEAECB17B9009AAF1E4E9CC02653194B
+
+I=269
+KEY=4B9DDD2F821CE4D1FC9F3727A6EF1ACAFBD1A57F0C98B8C2
+IV=AEAECB17B9009AAF1E4E9CC02653194B
+PT=5D2E4A96F9BB4AD4702E7CB176F76EA4
+CT=26851709960A42D5711EBDC7D40535FC
+
+I=270
+KEY=D7273499C5BA2842DA1A202E30E5581F8ACF18B8D89D8D3E
+IV=26851709960A42D5711EBDC7D40535FC
+PT=202534EA0A1952A19CBAE9B647A6CC93
+CT=FF8BFFB98EDA7E54664AE879551B5497
+
+I=271
+KEY=7870FF6B66070AB02591DF97BE3F264BEC85F0C18D86D9A9
+IV=FF8BFFB98EDA7E54664AE879551B5497
+PT=365CFE282B9508CFAF57CBF2A3BD22F2
+CT=D0809C84A97221E6F8DCB483B38EC7E1
+
+I=272
+KEY=F4E6DFDF4A081200F5114313174D07AD145944423E081E48
+IV=D0809C84A97221E6F8DCB483B38EC7E1
+PT=915323F59134AB838C9620B42C0F18B0
+CT=DC8A24B8DECF81E0412DBF10127119EC
+
+I=273
+KEY=336A7C81A4BE3FE9299B67ABC982864D5574FB522C7907A4
+IV=DC8A24B8DECF81E0412DBF10127119EC
+PT=0FC4387E49F666B8C78CA35EEEB62DE9
+CT=84E370DF6CA478BA85FC0874393CE442
+
+I=274
+KEY=F8ADC39E17CDDEB0AD781774A526FEF7D088F3261545E3E6
+IV=84E370DF6CA478BA85FC0874393CE442
+PT=34BFEFD3E43D8EE0CBC7BF1FB373E159
+CT=2C109A8363D1D0FB69CA77ABFA922F05
+
+I=275
+KEY=2B26D271208BD64F81688DF7C6F72E0CB942848DEFD7CCE3
+IV=2C109A8363D1D0FB69CA77ABFA922F05
+PT=D28D86D5199E7E30D38B11EF374608FF
+CT=F1749EFE66D339BC99AE4D9F63C90490
+
+I=276
+KEY=ACB8D3E6F5A45F0C701C1309A02417B020ECC9128C1EC873
+IV=F1749EFE66D339BC99AE4D9F63C90490
+PT=2ADAFA1911C5E9BD879E0197D52F8943
+CT=3B2A7C4278E1F071BFA29A6B0BFF4A15
+
+I=277
+KEY=CCEE75264DD770C44B366F4BD8C5E7C19F4E537987E18266
+IV=3B2A7C4278E1F071BFA29A6B0BFF4A15
+PT=84E244B62DF08DC76056A6C0B8732FC8
+CT=A35F83A5EE0B1C3B9DAD76DEAED96D72
+
+I=278
+KEY=F8F9239CDB5CC963E869ECEE36CEFBFA02E325A72938EF14
+IV=A35F83A5EE0B1C3B9DAD76DEAED96D72
+PT=F0B652F296CF162B341756BA968BB9A7
+CT=D5867FFE2FB75E309D3345611B25E3B0
+
+I=279
+KEY=509A10ABA5EAF2963DEF93101979A5CA9FD060C6321D0CA4
+IV=D5867FFE2FB75E309D3345611B25E3B0
+PT=C47D42AE34131463A86333377EB63BF5
+CT=6E136F01638AFBE3554218431DF44E7E
+
+I=280
+KEY=9B52C39C38F16CCE53FCFC117AF35E29CA9278852FE942DA
+IV=6E136F01638AFBE3554218431DF44E7E
+PT=78E05783EAEBE1BDCBC8D3379D1B9E58
+CT=FB6ACD3D0CF805374AD07EF5C038EBF6
+
+I=281
+KEY=2044F086923D5E43A896312C760B5B1E80420670EFD1A92C
+IV=FB6ACD3D0CF805374AD07EF5C038EBF6
+PT=02415B8E4D915492BB16331AAACC328D
+CT=0086C26DA11540FF5F485D7B238FD98C
+
+I=282
+KEY=12CE4C4109606CD7A810F341D71E1BE1DF0A5B0BCC5E70A0
+IV=0086C26DA11540FF5F485D7B238FD98C
+PT=0A2988237132B0B3328ABCC79B5D3294
+CT=F2E94C71A2AE0FCB096D8259B931CF8D
+
+I=283
+KEY=21BBCDA7FBC5229C5AF9BF3075B0142AD667D952756FBF2D
+IV=F2E94C71A2AE0FCB096D8259B931CF8D
+PT=4234B6C7F1CE98A3337581E6F2A54E4B
+CT=3B52E7834263C6790763706943741FD8
+
+I=284
+KEY=BB451732881A996161AB58B337D3D253D104A93B361BA0F5
+IV=3B52E7834263C6790763706943741FD8
+PT=F8509FB57E14501F9AFEDA9573DFBBFD
+CT=93FCA9F122CB707213D0CD72D8E6BF74
+
+I=285
+KEY=857D076E9A127A84F257F1421518A221C2D46449EEFD1F81
+IV=93FCA9F122CB707213D0CD72D8E6BF74
+PT=AA4D07DFAD030BE03E38105C1208E3E5
+CT=50717568D21862AECFAA898337405C96
+
+I=286
+KEY=1BCFD020D63709E0A226842AC700C08F0D7EEDCAD9BD4317
+IV=50717568D21862AECFAA898337405C96
+PT=7B488D7BBB2D538E9EB2D74E4C257364
+CT=0338D74260CB6CBB1B220DE7E4CC0BCF
+
+I=287
+KEY=CCDDF5D0BBCE202DA11E5368A7CBAC34165CE02D3D7148D8
+IV=0338D74260CB6CBB1B220DE7E4CC0BCF
+PT=16E01F8B3E94AC26D71225F06DF929CD
+CT=698AD17BB2F5F06C0465BEE34A7DCEDD
+
+I=288
+KEY=B7F556BC9BB4DC49C8948213153E5C5812395ECE770C8605
+IV=698AD17BB2F5F06C0465BEE34A7DCEDD
+PT=3ED0C80AFDEFE8BF7B28A36C207AFC64
+CT=E20129557F795C2B1CC32A5494824A4B
+
+I=289
+KEY=4B00D75969C3549C2A95AB466A4700730EFA749AE38ECC4E
+IV=E20129557F795C2B1CC32A5494824A4B
+PT=20BE0CD6C2244384FCF581E5F27788D5
+CT=C2F9DD55E91F4796636FEC9745410087
+
+I=290
+KEY=5EDCC5155BA684A4E86C7613835847E56D95980DA6CFCCC9
+IV=C2F9DD55E91F4796636FEC9745410087
+PT=B2DF53DF1139FB9915DC124C3265D038
+CT=015D51CD3568EB4EC210B58FFA89A409
+
+I=291
+KEY=21BA26AC6880AACDE93127DEB630ACABAF852D825C4668C0
+IV=015D51CD3568EB4EC210B58FFA89A409
+PT=401094B8B47CBDC87F66E3B933262E69
+CT=2987D39C19E6997957BDD0CAF010F778
+
+I=292
+KEY=BBA7ABC0A20CCBDEC0B6F442AFD635D2F838FD48AC569FB8
+IV=2987D39C19E6997957BDD0CAF010F778
+PT=EFC30498827AAD9A9A1D8D6CCA8C6113
+CT=E01AA987C9520EF8EBF53E97371D056B
+
+I=293
+KEY=5322D81BAA29410320AC5DC566843B2A13CDC3DF9B4B9AD3
+IV=E01AA987C9520EF8EBF53E97371D056B
+PT=685D6F660D40105CE88573DB08258ADD
+CT=D1265ABFCFA75FC65E94983BFF75CD48
+
+I=294
+KEY=19DF73EBF1CEF669F18A077AA92364EC4D595BE4643E579B
+IV=D1265ABFCFA75FC65E94983BFF75CD48
+PT=DD6E090E9981E5F24AFDABF05BE7B76A
+CT=605FDD1CA95B8FE1A5E26DBA10241914
+
+I=295
+KEY=F7D1D0CA3DAA851891D5DA660078EB0DE8BB365E741A4E8F
+IV=605FDD1CA95B8FE1A5E26DBA10241914
+PT=9F8442EE8B5A325FEE0EA321CC647371
+CT=76D67121FDEAEB6B81DBB29565F71E8E
+
+I=296
+KEY=FFFF200EA04824E9E703AB47FD920066696084CB11ED5001
+IV=76D67121FDEAEB6B81DBB29565F71E8E
+PT=5AF386509F0C8BAA082EF0C49DE2A1F1
+CT=7E1D833DC8D73228B7DFDE918E31E5E7
+
+I=297
+KEY=2A7D40B689490FC7991E287A3545324EDEBF5A5A9FDCB5E6
+IV=7E1D833DC8D73228B7DFDE918E31E5E7
+PT=02AB05F508ACDD21D58260B829012B2E
+CT=D6CA06D415EA5D750B5D06C252645A43
+
+I=298
+KEY=134154161A39E2CF4FD42EAE20AF6F3BD5E25C98CDB8EFA5
+IV=D6CA06D415EA5D750B5D06C252645A43
+PT=E63873AE14DD3BA8393C14A09370ED08
+CT=BFEA32E77BC1607921C54027C01C3EDF
+
+I=299
+KEY=AD8AF90935A6B455F03E1C495B6E0F42F4271CBF0DA4D17A
+IV=BFEA32E77BC1607921C54027C01C3EDF
+PT=BAD47B1FBF949870BECBAD1F2F9F569A
+CT=A86FFC9A91C79AFE47899B3934F3E05E
+
+I=300
+KEY=D88A2E828514CEC25851E0D3CAA995BCB3AE878639573124
+IV=A86FFC9A91C79AFE47899B3934F3E05E
+PT=2A2115074A9767747500D78BB0B27A97
+CT=507ED155CC3ED3B1922BBC166812A7FE
+
+I=301
+KEY=2CDDF1A577A3C86C082F31860697460D21853B90514596DA
+IV=507ED155CC3ED3B1922BBC166812A7FE
+PT=308D27178ABA22BCF457DF27F2B706AE
+CT=87F4EEA7CD2438F3EDCB650824A2D638
+
+I=302
+KEY=2B9D006908018D648FDBDF21CBB37EFECC4E5E9875E740E2
+IV=87F4EEA7CD2438F3EDCB650824A2D638
+PT=28F6C452D061E3DB0740F1CC7FA24508
+CT=DBA57DDA73A4E987EA32EF113877E908
+
+I=303
+KEY=FC69838410D06425547EA2FBB8179779267CB1894D90A9EA
+IV=DBA57DDA73A4E987EA32EF113877E908
+PT=91CFB50FFBE97D8AD7F483ED18D1E941
+CT=1720ED3E3B685A19CDA66BD09BD4DA5F
+
+I=304
+KEY=541AAB6191E2C51F435E4FC5837FCD60EBDADA59D64473B5
+IV=1720ED3E3B685A19CDA66BD09BD4DA5F
+PT=78FF980C48FAEBA0A87328E58132A13A
+CT=ED2E260103CAA77598FD195D02B484C8
+
+I=305
+KEY=761B0A3F50E2ACC1AE7069C480B56A157327C304D4F0F77D
+IV=ED2E260103CAA77598FD195D02B484C8
+PT=8C01554039D8F8EE2201A15EC10069DE
+CT=A9F0E16716B3AC14E06F18F5AEECB541
+
+I=306
+KEY=70056CD35CF430D5078088A39606C6019348DBF17A1C423C
+IV=A9F0E16716B3AC14E06F18F5AEECB541
+PT=C139651464D1614B061E66EC0C169C14
+CT=A41DDF008E0D52B627982D4196C3069E
+
+I=307
+KEY=EE1932746487B7BEA39D57A3180B94B7B4D0F6B0ECDF44A2
+IV=A41DDF008E0D52B627982D4196C3069E
+PT=C617572884721A3D9E1C5EA73873876B
+CT=44E5304E35A21660C450FAF84D87B13B
+
+I=308
+KEY=13D43E4526F8243FE77867ED2DA982D770800C48A158F599
+IV=44E5304E35A21660C450FAF84D87B13B
+PT=9C72E08DD264D6B7FDCD0C31427F9381
+CT=173B2C7A54A1A3CF3D39DCB68DA1C539
+
+I=309
+KEY=7CB72DE2CAED4080F0434B97790821184DB9D0FE2CF930A0
+IV=173B2C7A54A1A3CF3D39DCB68DA1C539
+PT=4DF3764F679E29446F6313A7EC1564BF
+CT=F1A167A3EB8F3FAB9F9B1570475ED15A
+
+I=310
+KEY=A7E6340A1278A3E801E22C3492871EB3D222C58E6BA7E1FA
+IV=F1A167A3EB8F3FAB9F9B1570475ED15A
+PT=2ED419EA11AAF8F3DB5119E8D895E368
+CT=2C5C5B10E285FE6C7E4750D2F9C1BD23
+
+I=311
+KEY=4B535B4D088F09192DBE77247002E0DFAC65955C92665CD9
+IV=2C5C5B10E285FE6C7E4750D2F9C1BD23
+PT=A3E9EA99771D0C02ECB56F471AF7AAF1
+CT=A12B4A15DBFAE2E7D4A7A792CD3C121A
+
+I=312
+KEY=2F0E7BAD76DC0A718C953D31ABF8023878C232CE5F5A4EC3
+IV=A12B4A15DBFAE2E7D4A7A792CD3C121A
+PT=1CC105D2604628B7645D20E07E530368
+CT=65CE700B785D901C5E5E08F7E74BB296
+
+I=313
+KEY=6111C386DE35C954E95B4D3AD3A59224269C3A39B811FC55
+IV=65CE700B785D901C5E5E08F7E74BB296
+PT=F902717AF7F0794E4E1FB82BA8E9C325
+CT=E7F3BD1056C504285FFC7F65B395DCAE
+
+I=314
+KEY=3B8F85E6FD28C4610EA8F02A8560960C7960455C0B8420FB
+IV=E7F3BD1056C504285FFC7F65B395DCAE
+PT=20A5529420D6D4C35A9E4660231D0D35
+CT=6CC36458ADECCA8B7198FD272A8C76C8
+
+I=315
+KEY=D404C97E089F240B626B9472288C5C8708F8B87B21085633
+IV=6CC36458ADECCA8B7198FD272A8C76C8
+PT=1094639F6723C9B0EF8B4C98F5B7E06A
+CT=D01C3C1E036D804563F04926ED203146
+
+I=316
+KEY=4779B44770085E18B277A86C2BE1DCC26B08F15DCC286775
+IV=D01C3C1E036D804563F04926ED203146
+PT=A482437681DFE307937D7D3978977A13
+CT=319D579DE9E55C8A3B2097EE8C93375F
+
+I=317
+KEY=22362304D7417BB483EAFFF1C2048048502866B340BB502A
+IV=319D579DE9E55C8A3B2097EE8C93375F
+PT=7AF0C8274B5C243B654F9743A74925AC
+CT=5F722165B8B422E088814B77A6B4D8E4
+
+I=318
+KEY=06FDA49350C16FEADC98DE947AB0A2A8D8A92DC4E60F88CE
+IV=5F722165B8B422E088814B77A6B4D8E4
+PT=A37964FA3E8145EF24CB87978780145E
+CT=C0417773DFD3FC83C2CE12D388F5DD8F
+
+I=319
+KEY=366245F8CBC490611CD9A9E7A5635E2B1A673F176EFA5541
+IV=C0417773DFD3FC83C2CE12D388F5DD8F
+PT=5D7E1E14F7BD7DB6309FE16B9B05FF8B
+CT=2EAE64B58C18AC7ADD2EE62896AB708D
+
+I=320
+KEY=A1BB8A9F9BE8F1383277CD52297BF251C749D93FF85125CC
+IV=2EAE64B58C18AC7ADD2EE62896AB708D
+PT=3ADC6991BF15554F97D9CF67502C6159
+CT=069FC966F8A985AD41617CB0148D2B96
+
+I=321
+KEY=7AB228E4114C14AB34E80434D1D277FC8628A58FECDC0E5A
+IV=069FC966F8A985AD41617CB0148D2B96
+PT=4405B80CCE92FD71DB09A27B8AA4E593
+CT=13459A0239A33BC41424A5D03C6B2864
+
+I=322
+KEY=78D1BC27E5CBBB1D27AD9E36E8714C38920C005FD0B7263E
+IV=13459A0239A33BC41424A5D03C6B2864
+PT=B9BAA861988616CD026394C3F487AFB6
+CT=08DA968A2BAEB9B763EB42BF555A2BFA
+
+I=323
+KEY=F53B033A22EA1D7B2F7708BCC3DFF58FF1E742E085ED0DC4
+IV=08DA968A2BAEB9B763EB42BF555A2BFA
+PT=30654265AD0FB24E8DEABF1DC721A666
+CT=E8412BDC1E75AC8E2C28552E2195795E
+
+I=324
+KEY=4928B51AF5C2408CC7362360DDAA5901DDCF17CEA478749A
+IV=E8412BDC1E75AC8E2C28552E2195795E
+PT=EEB05E487EEB907FBC13B620D7285DF7
+CT=E01839F95680D27E048383236D59EE85
+
+I=325
+KEY=C4DB91EAFC4C26D7272E1A998B2A8B7FD94C94EDC9219A1F
+IV=E01839F95680D27E048383236D59EE85
+PT=BA0160229D7471FE8DF324F0098E665B
+CT=D41902E6BE946CEB1612CFEE2F33F7CD
+
+I=326
+KEY=B550731E659834A1F337187F35BEE794CF5E5B03E6126DD2
+IV=D41902E6BE946CEB1612CFEE2F33F7CD
+PT=7DC970AFAF99BA6C718BE2F499D41276
+CT=326C3523173D62E9E145592E7A774311
+
+I=327
+KEY=5F87F6C2402B2352C15B2D5C2283857D2E1B022D9C652EC3
+IV=326C3523173D62E9E145592E7A774311
+PT=24ED6DAE1B24CC2BEAD785DC25B317F3
+CT=DDAE8AFF94604FFA82AE4FFB06953C01
+
+I=328
+KEY=3636C04061996CD01CF5A7A3B6E3CA87ACB54DD69AF012C2
+IV=DDAE8AFF94604FFA82AE4FFB06953C01
+PT=98E262805B8D9FD169B1368221B24F82
+CT=0D75DCFA4941BCE658DB2C71CB270BE7
+
+I=329
+KEY=64B9A0DE7DDA73C011807B59FFA27661F46E61A751D71925
+IV=0D75DCFA4941BCE658DB2C71CB270BE7
+PT=2BC34C226D41D8CE528F609E1C431F10
+CT=D70ED1DCDB9420E4B4A0D2A7C5148DE3
+
+I=330
+KEY=F64196479D35F74BC68EAA852436568540CEB30094C394C6
+IV=D70ED1DCDB9420E4B4A0D2A7C5148DE3
+PT=1015CB1E4569986C92F83699E0EF848B
+CT=524314DCCF2ADE5F8C3D241824C2BA73
+
+I=331
+KEY=686AB32115A2884C94CDBE59EB1C88DACCF39718B0012EB5
+IV=524314DCCF2ADE5F8C3D241824C2BA73
+PT=FB8B49053F724B7D9E2B256688977F07
+CT=7C579324F7251EDF95BDE2320104ACA6
+
+I=332
+KEY=34DD68E6F442F6D9E89A2D7D1C399605594E752AB1058213
+IV=7C579324F7251EDF95BDE2320104ACA6
+PT=A3B71504A8DAA3515CB7DBC7E1E07E95
+CT=921A66278A6D1E61D4B509F199F8FE55
+
+I=333
+KEY=19C9F40A858DD9EA7A804B5A965488648DFB7CDB28FD7C46
+IV=921A66278A6D1E61D4B509F199F8FE55
+PT=B0B651905E1B38FB2D149CEC71CF2F33
+CT=F2C37CF94514C902A0E438159C2C9F5F
+
+I=334
+KEY=B68812FC7D4E40D6884337A3D34041662D1F44CEB4D1E319
+IV=F2C37CF94514C902A0E438159C2C9F5F
+PT=7DE03F498839F8DAAF41E6F6F8C3993C
+CT=4596A25A85D06BCC74F686F8F1E8C203
+
+I=335
+KEY=2836F982CA563379CDD595F956902AAA59E9C2364539211A
+IV=4596A25A85D06BCC74F686F8F1E8C203
+PT=D5425E42151014ED9EBEEB7EB71873AF
+CT=0BA46EFA61FB07430C51D7CE267E1F47
+
+I=336
+KEY=BC8C7F9051C98892C671FB03376B2DE955B815F863473E5D
+IV=0BA46EFA61FB07430C51D7CE267E1F47
+PT=5D060EEC179C1B9E94BA86129B9FBBEB
+CT=49F7D7D7BAB7795A4E74A854C8C1AC53
+
+I=337
+KEY=E661F49B22BC92358F862CD48DDC54B31BCCBDACAB86920E
+IV=49F7D7D7BAB7795A4E74A854C8C1AC53
+PT=C598926A437A27A45AED8B0B73751AA7
+CT=0EB97E32AEC4CE3959197C5B72C1ABC5
+
+I=338
+KEY=E625AB8664BCF057813F52E623189A8A42D5C1F7D94739CB
+IV=0EB97E32AEC4CE3959197C5B72C1ABC5
+PT=B7272C4D712F9CF500445F1D46006262
+CT=DA9F53564E69AED610BCCAD13C00A241
+
+I=339
+KEY=75FC1D46AFD886915BA001B06D71345C52690B26E5479B8A
+IV=DA9F53564E69AED610BCCAD13C00A241
+PT=FE7513CF9353BBF093D9B6C0CB6476C6
+CT=7F61B6F9B7C14EB6179F2DA597EC1183
+
+I=340
+KEY=F92D3201DA84422024C1B749DAB07AEA45F6268372AB8A09
+IV=7F61B6F9B7C14EB6179F2DA597EC1183
+PT=4E4D3DF58D7D9C338CD12F47755CC4B1
+CT=F9216373C300AA9BE96BD8C98F9716B7
+
+I=341
+KEY=680384A1E522C848DDE0D43A19B0D071AC9DFE4AFD3C9CBE
+IV=F9216373C300AA9BE96BD8C98F9716B7
+PT=1A7B30192D54142E912EB6A03FA68A68
+CT=8512BA1B57BC04EF3C021DB1EC3CA9C6
+
+I=342
+KEY=DE3B85BD09EC93B858F26E214E0CD49E909FE3FB11003578
+IV=8512BA1B57BC04EF3C021DB1EC3CA9C6
+PT=86587FF85D73F77FB638011CECCE5BF0
+CT=FA582C37D4063D61428C886A9FD54C84
+
+I=343
+KEY=C574CA7322F443FBA2AA42169A0AE9FFD2136B918ED579FC
+IV=FA582C37D4063D61428C886A9FD54C84
+PT=3A7425A8B7BC3A941B4F4FCE2B18D043
+CT=7571B4D46CBC671964AB5BDE9C843DCF
+
+I=344
+KEY=078109812EFBA9DBD7DBF6C2F6B68EE6B6B8304F12514433
+IV=7571B4D46CBC671964AB5BDE9C843DCF
+PT=5224060F0848F028C2F5C3F20C0FEA20
+CT=DA9EB72D65D492FE88B819674B8433C1
+
+I=345
+KEY=5BF7FA2E15A87C850D4541EF93621C183E00292859D577F2
+IV=DA9EB72D65D492FE88B819674B8433C1
+PT=2622B2A19CBBAD065C76F3AF3B53D55E
+CT=C66EF470CEDDD499AE6214E75DE9051B
+
+I=346
+KEY=ECBE2377CAF0C9E9CB2BB59F5DBFC88190623DCF043C72E9
+IV=C66EF470CEDDD499AE6214E75DE9051B
+PT=833F22A76D51E360B749D959DF58B56C
+CT=57407E3DEFFF753E879619424FCE5713
+
+I=347
+KEY=4EAB83DA78D60CB09C6BCBA2B240BDBF17F4248D4BF225FA
+IV=57407E3DEFFF753E879619424FCE5713
+PT=25781A534FB9192CA215A0ADB226C559
+CT=644D89381439E7BBED7DC344CBF4C886
+
+I=348
+KEY=C4977EF1F6271D6CF826429AA6795A04FA89E7C98006ED7C
+IV=644D89381439E7BBED7DC344CBF4C886
+PT=E8EDD9AA25A8C5B08A3CFD2B8EF111DC
+CT=CA4B2680D0EE8E28818BE8DE8D625ADC
+
+I=349
+KEY=80212F6D11C6DAE2326D641A7697D42C7B020F170D64B7A0
+IV=CA4B2680D0EE8E28818BE8DE8D625ADC
+PT=8F667EEDB79E930644B6519CE7E1C78E
+CT=5497F477AD5E65BB748A781533F1BCEF
+
+I=350
+KEY=A05DF1DF7E0393A566FA906DDBC9B1970F8877023E950B4F
+IV=5497F477AD5E65BB748A781533F1BCEF
+PT=099FDB76E6D21788207CDEB26FC54947
+CT=C8C541B359BF1B53441C4EFFFD2F65AF
+
+I=351
+KEY=3970F236F800D18BAE3FD1DE8276AAC44B9439FDC3BA6EE0
+IV=C8C541B359BF1B53441C4EFFFD2F65AF
+PT=C79FA2079ECCEBCD992D03E98603422E
+CT=E59765A861DE0168161EA1360B5966A9
+
+I=352
+KEY=8ED3BFA3E4C9453C4BA8B476E3A8ABAC5D8A98CBC8E30849
+IV=E59765A861DE0168161EA1360B5966A9
+PT=AFBCD48F06709730B7A34D951CC994B7
+CT=5A65435BD1B4DB742E8AFF8C402927FC
+
+I=353
+KEY=2A3F01E56E45895B11CDF72D321C70D87300674788CA2FB5
+IV=5A65435BD1B4DB742E8AFF8C402927FC
+PT=CF684F64B8CCD2EDA4ECBE468A8CCC67
+CT=551AF68D50D23408F47214C0B18E6C8A
+
+I=354
+KEY=CA12AC8D17941E6244D701A062CE44D0877273873944433F
+IV=551AF68D50D23408F47214C0B18E6C8A
+PT=561072AC144854C1E02DAD6879D19739
+CT=ADFF035C89E040A4C3CCE190D6CB7283
+
+I=355
+KEY=D1CA1B08A51B5086E92802FCEB2E047444BE9217EF8F31BC
+IV=ADFF035C89E040A4C3CCE190D6CB7283
+PT=827ADE7D0F329D9A1BD8B785B28F4EE4
+CT=425F5596D3FD37243EE59D6FC1F5ADCC
+
+I=356
+KEY=54EC325FE63AA470AB77576A38D333507A5B0F782E7A9C70
+IV=425F5596D3FD37243EE59D6FC1F5ADCC
+PT=4AAF21E64F8DBDB0852629574321F4F6
+CT=D85520FE860C9F320CDC8192A900F499
+
+I=357
+KEY=5B4612BC35BFC12473227794BEDFAC6276878EEA877A68E9
+IV=D85520FE860C9F320CDC8192A900F499
+PT=0D046A402A1860C70FAA20E3D3856554
+CT=11C20F3ACED79B37402B2F04886D4CC7
+
+I=358
+KEY=5052384CE705101562E078AE7008375536ACA1EE0F17242E
+IV=11C20F3ACED79B37402B2F04886D4CC7
+PT=7546E6521BBBFAFE0B142AF0D2BAD131
+CT=BCDA339266E3AFB779AF17CE34218BE5
+
+I=359
+KEY=F7ECFB2AA4FC6DE2DE3A4B3C16EB98E24F03B6203B36AFCB
+IV=BCDA339266E3AFB779AF17CE34218BE5
+PT=85DF7958789E9090A7BEC36643F97DF7
+CT=300D46EAB6466314BB00DBC869C77F4E
+
+I=360
+KEY=1E27229506EC9555EE370DD6A0ADFBF6F4036DE852F1D085
+IV=300D46EAB6466314BB00DBC869C77F4E
+PT=C6CED700614467A0E9CBD9BFA210F8B7
+CT=51735C075A14FE95D4A02F527A9474D3
+
+I=361
+KEY=857F653E1E811CABBF4451D1FAB9056320A342BA2865A456
+IV=51735C075A14FE95D4A02F527A9474D3
+PT=53D436401D6811B19B5847AB186D89FE
+CT=827017531E56980C4357549D0E70114F
+
+I=362
+KEY=1BCE612F3A5262223D344682E4EF9D6F63F416272615B519
+IV=827017531E56980C4357549D0E70114F
+PT=4C1BD17FFD65AB2C9EB1041124D37E89
+CT=751BCA9516123906561FB8AF2208CEE1
+
+I=363
+KEY=7C7034EC27524FC3482F8C17F2FDA46935EBAE88041D7BF8
+IV=751BCA9516123906561FB8AF2208CEE1
+PT=7C23D6E77039F35267BE55C31D002DE1
+CT=82CAFBBE859FA80B2A8E58CEC074B01A
+
+I=364
+KEY=7F31EEE0447BB53CCAE577A977620C621F65F646C469CBE2
+IV=82CAFBBE859FA80B2A8E58CEC074B01A
+PT=B91FF7759419BBB10341DA0C6329FAFF
+CT=B7614376C9BAFC92E17E39D2BDF1F2EF
+
+I=365
+KEY=E705144BCE40FC987D8434DFBED8F0F0FE1BCF947998390D
+IV=B7614376C9BAFC92E17E39D2BDF1F2EF
+PT=72B3472217AC80979834FAAB8A3B49A4
+CT=A63BA38FDDFE99D28BA447871BBA6211
+
+I=366
+KEY=15C813D2D9AD1494DBBF97506326692275BF881362225B1C
+IV=A63BA38FDDFE99D28BA447871BBA6211
+PT=349F8E5FAE004B51F2CD079917EDE80C
+CT=C87E448872E619419766CB46787F2581
+
+I=367
+KEY=B12B790C217821DA13C1D3D811C07063E2D943551A5D7E9D
+IV=C87E448872E619419766CB46787F2581
+PT=EC474C794E3C8322A4E36ADEF8D5354E
+CT=73DD478F7F41857F7A5DE7EDF3F1AF7B
+
+I=368
+KEY=1CFA6A54B3E572DC601C94576E81F51C9884A4B8E9ACD1E6
+IV=73DD478F7F41857F7A5DE7EDF3F1AF7B
+PT=48F8361EF11F94C1ADD11358929D5306
+CT=8B85DE2CBE5C96CBDFE16064079754D9
+
+I=369
+KEY=6718C10E683F4D73EB994A7BD0DD63D74765C4DCEE3B853F
+IV=8B85DE2CBE5C96CBDFE16064079754D9
+PT=59BFDA108542EDDB7BE2AB5ADBDA3FAF
+CT=56FF53384CED780F604F86EC0CE26B26
+
+I=370
+KEY=704ED4F1E96776A2BD6619439C301BD8272A4230E2D9EE19
+IV=56FF53384CED780F604F86EC0CE26B26
+PT=468FDBDB8BC26B5A175615FF81583BD1
+CT=7B0C2436262A262C5FAFC3A9B786DB00
+
+I=371
+KEY=67AFB86317B622B2C66A3D75BA1A3DF478858199555F3519
+IV=7B0C2436262A262C5FAFC3A9B786DB00
+PT=768BE978E5E8CA6E17E16C92FED15410
+CT=D32206D5D1521AB667516391810F5719
+
+I=372
+KEY=0BF4E0C32EA3D69615483BA06B4827421FD4E208D4506200
+IV=D32206D5D1521AB667516391810F5719
+PT=1943C5D93D10A0E36C5B58A03915F424
+CT=6BCE2BEC0D5A0DA9051AF2B34A873694
+
+I=373
+KEY=924D1C527572A2EF7E86104C66122AEB1ACE10BB9ED75494
+IV=6BCE2BEC0D5A0DA9051AF2B34A873694
+PT=E3020D099D0841C299B9FC915BD17479
+CT=3BEBA6BA0762BF5FAA4D26B70071B4A9
+
+I=374
+KEY=CFA41DB53F2F8766456DB6F6617095B4B083360C9EA6E03D
+IV=3BEBA6BA0762BF5FAA4D26B70071B4A9
+PT=31F7316F0D1012CD5DE901E74A5D2589
+CT=C4253CED7F88DF97596B08A15BAEF533
+
+I=375
+KEY=E2B9D43008C1537281488A1B1EF84A23E9E83EADC508150E
+IV=C4253CED7F88DF97596B08A15BAEF533
+PT=00365D6755A898E62D1DC98537EED414
+CT=2D4EB6BA84D1C0C978EA20C1693BB75C
+
+I=376
+KEY=43EA75DFD5B35CCBAC063CA19A298AEA91021E6CAC33A252
+IV=2D4EB6BA84D1C0C978EA20C1693BB75C
+PT=599279C68B67A988A153A1EFDD720FB9
+CT=03698CC5E133AD8855B847C124FD2778
+
+I=377
+KEY=8F2C76FCFBD8060DAF6FB0647B1A2762C4BA59AD88CE852A
+IV=03698CC5E133AD8855B847C124FD2778
+PT=47EFAF7E090B94B5CCC603232E6B5AC6
+CT=8D44C11C25ADE5631E05FAAECCA70AF7
+
+I=378
+KEY=E02084775A2E1A4E222B71785EB7C201DABFA30344698FDD
+IV=8D44C11C25ADE5631E05FAAECCA70AF7
+PT=394EC624EBC0D79E6F0CF28BA1F61C43
+CT=5EB407847213D5E950C66787B140BC35
+
+I=379
+KEY=D8208A70940589F47C9F76FC2CA417E88A79C484F52933E8
+IV=5EB407847213D5E950C66787B140BC35
+PT=F28816D227AC09F538000E07CE2B93BA
+CT=2D4FBD74A027526BADC8C2A433963C22
+
+I=380
+KEY=858193C76AFE48D951D0CB888C83458327B10620C6BF0FCA
+IV=2D4FBD74A027526BADC8C2A433963C22
+PT=FBAA6C644F8E08885DA119B7FEFBC12D
+CT=FA2DAE761EBBFDE4B77CBCD2381165DB
+
+I=381
+KEY=DA9A9F800056FC6EABFD65FE9238B86790CDBAF2FEAE6A11
+IV=FA2DAE761EBBFDE4B77CBCD2381165DB
+PT=F66A574C26D0F15C5F1B0C476AA8B4B7
+CT=DB18F5B16BF19C2BCCA36091A302BF38
+
+I=382
+KEY=BD2AB07F036032AB70E5904FF9C9244C5C6EDA635DACD529
+IV=DB18F5B16BF19C2BCCA36091A302BF38
+PT=04B0C1A19C6D38B467B02FFF0336CEC5
+CT=D3F01581B21DF4E470EE595CAB44912C
+
+I=383
+KEY=7EF57F6BDE41D79CA31585CE4BD4D0A82C80833FF6E84405
+IV=D3F01581B21DF4E470EE595CAB44912C
+PT=83BF32E0F3F3CEE7C3DFCF14DD21E537
+CT=10C69B9A04E0851B63D85D025BBACA29
+
+I=384
+KEY=22057A9912BB6B76B3D31E544F3455B34F58DE3DAD528E2C
+IV=10C69B9A04E0851B63D85D025BBACA29
+PT=150ACC96322893CC5CF005F2CCFABCEA
+CT=2743FE5769DDA5D591318E200AF672D0
+
+I=385
+KEY=742A2117B51176E69490E00326E9F066DE69501DA7A4FCFC
+IV=2743FE5769DDA5D591318E200AF672D0
+PT=93246C1A26F66DAF562F5B8EA7AA1D90
+CT=5CA8FC8DB4A20B2CA8AB86B1B40DA1A1
+
+I=386
+KEY=3C09F8C3B20BE749C8381C8E924BFB4A76C2D6AC13A95D5D
+IV=5CA8FC8DB4A20B2CA8AB86B1B40DA1A1
+PT=D91806E0F3451C374823D9D4071A91AF
+CT=25701E4C6685C98333566EB75498AEB7
+
+I=387
+KEY=DD0386F2D0D1E8FFED4802C2F4CE32C94594B81B4731F3EA
+IV=25701E4C6685C98333566EB75498AEB7
+PT=701A5D7027053688E10A7E3162DA0FB6
+CT=E4A5889FC49B62F767F61F1D2810801A
+
+I=388
+KEY=BB9A1FA7287B0D3D09ED8A5D3055503E2262A7066F2173F0
+IV=E4A5889FC49B62F767F61F1D2810801A
+PT=A110B0A38255279B66999955F8AAE5C2
+CT=F1A9BDA2045F3EAE2AB9CEE2AD352270
+
+I=389
+KEY=21B561DC3C44B5A5F84437FF340A6E9008DB69E4C2145180
+IV=F1A9BDA2045F3EAE2AB9CEE2AD352270
+PT=1562CF8420963B479A2F7E7B143FB898
+CT=E7E2BA657D3482A4825D643B8C01B52E
+
+I=390
+KEY=60A0FA1F5FA435401FA68D9A493EEC348A860DDF4E15E4AE
+IV=E7E2BA657D3482A4825D643B8C01B52E
+PT=930490633BC4EDC941159BC363E080E5
+CT=2FDBCD145EB8620594834B0D63BBD137
+
+I=391
+KEY=7DD1686F811E4017307D408E17868E311E0546D22DAE3599
+IV=2FDBCD145EB8620594834B0D63BBD137
+PT=4BB1C43F4ABC51CD1D719270DEBA7557
+CT=B703658AD9FFCDE05E2C7E252990402E
+
+I=392
+KEY=18203DC5AAA632F5877E2504CE7943D1402938F7043E75B7
+IV=B703658AD9FFCDE05E2C7E252990402E
+PT=47931942F275F05E65F155AA2BB872E2
+CT=5B79CB7FA90D3BB5A979A4588D4DE434
+
+I=393
+KEY=9F6D532CBAF42FCDDC07EE7B67747864E9509CAF89739183
+IV=5B79CB7FA90D3BB5A979A4588D4DE434
+PT=E3A36DF4EB896B4D874D6EE910521D38
+CT=61BF460521E67B3CAC638F3298EF9310
+
+I=394
+KEY=ED4F97BC99036E83BDB8A87E469203584533139D119C0293
+IV=61BF460521E67B3CAC638F3298EF9310
+PT=55EABDF72CCB5D737222C49023F7414E
+CT=8A27D87B53B2FB8BBAFF7851AF1D51F2
+
+I=395
+KEY=E1B9A7291D885F8E379F70051520F8D3FFCC6BCCBE815361
+IV=8A27D87B53B2FB8BBAFF7851AF1D51F2
+PT=D30271EA236E948F0CF63095848B310D
+CT=15075FDCBD2D6FC15B9A3841A2D58C34
+
+I=396
+KEY=976B101EE3E10E0822982FD9A80D9712A456538D1C54DF55
+IV=15075FDCBD2D6FC15B9A3841A2D58C34
+PT=879EED3434159D8076D2B737FE695186
+CT=6896582462983FAAE443078F9768B339
+
+I=397
+KEY=A7A3277BF5F605FC4A0E77FDCA95A8B8401554028B3C6C6C
+IV=6896582462983FAAE443078F9768B339
+PT=89DDABE96D1069ED30C8376516170BF4
+CT=96FE6B921416B667AA5B34D2D2E25747
+
+I=398
+KEY=DD57026B1D4E32A8DCF01C6FDE831EDFEA4E60D059DE3B2B
+IV=96FE6B921416B667AA5B34D2D2E25747
+PT=8144C8BB09FC72827AF42510E8B83754
+CT=EEDC3677AB7B57829F6D733F8090DA8A
+
+I=399
+KEY=B4D1BDF297DC0574322C2A1875F8495D752313EFD94EE1A1
+IV=EEDC3677AB7B57829F6D733F8090DA8A
+PT=510F7A55799B39786986BF998A9237DC
+CT=BA50C94440C04A8C0899D42658E25437
+
+==========
+
+KEYSIZE=256
+
+I=0
+KEY=0000000000000000000000000000000000000000000000000000000000000000
+IV=00000000000000000000000000000000
+PT=00000000000000000000000000000000
+CT=FE3C53653E2F45B56FCD88B2CC898FF0
+
+I=1
+KEY=B2493DE29713367D9FAA93469F8EF596FE3C53653E2F45B56FCD88B2CC898FF0
+IV=FE3C53653E2F45B56FCD88B2CC898FF0
+PT=B2493DE29713367D9FAA93469F8EF596
+CT=7CE2ABAF8BEF23C4816DC8CE842048A7
+
+I=2
+KEY=33A36646FE56F70DC0C51A3117E639F182DEF8CAB5C06671EEA0407C48A9C757
+IV=7CE2ABAF8BEF23C4816DC8CE842048A7
+PT=81EA5BA46945C1705F6F89778868CC67
+CT=50CD14A12C6852D39654C816BFAF9AC2
+
+I=3
+KEY=0D6A3DACE75B104CA8A303A32670BF3AD213EC6B99A834A278F4886AF7065D95
+IV=50CD14A12C6852D39654C816BFAF9AC2
+PT=3EC95BEA190DE74168661992319686CB
+CT=3F411DAD0E339FE281637133BF46BD13
+
+I=4
+KEY=A53BE0709BF686A7DB7C3848D81AB66BED52F1C6979BAB40F997F9594840E086
+IV=3F411DAD0E339FE281637133BF46BD13
+PT=A851DDDC7CAD96EB73DF3BEBFE6A0951
+CT=5BA2C7663A4061719A7CCC2AF2A3EE8A
+
+I=5
+KEY=ECF3490CB7717A5236A3A94811BEBF13B6F036A0ADDBCA3163EB3573BAE30E0C
+IV=5BA2C7663A4061719A7CCC2AF2A3EE8A
+PT=49C8A97C2C87FCF5EDDF9100C9A40978
+CT=F105031CE7E5111317745C64F4F6D150
+
+I=6
+KEY=CE8A062A2A9F9EDE2EFB43A8602BB47847F535BC4A3EDB22749F69174E15DF5C
+IV=F105031CE7E5111317745C64F4F6D150
+PT=22794F269DEEE48C1858EAE071950B6B
+CT=C8F030398A873550A34386D9A153D833
+
+I=7
+KEY=2BE39545B8FC27444178BF0004C7F1048F050585C0B9EE72D7DCEFCEEF46076F
+IV=C8F030398A873550A34386D9A153D833
+PT=E569936F9263B99A6F83FCA864EC457C
+CT=519CF42C0BBFCBD79679089BC5E963B4
+
+I=8
+KEY=80E9C0F78F99E309935C0A69B961D787DE99F1A9CB0625A541A5E7552AAF64DB
+IV=519CF42C0BBFCBD79679089BC5E963B4
+PT=AB0A55B23765C44DD224B569BDA62683
+CT=64AC8FEA3B83584E9B7379B48F88B7A4
+
+I=9
+KEY=48DDBDA704BA7702960820A0D2CA485CBA357E43F0857DEBDAD69EE1A527D37F
+IV=64AC8FEA3B83584E9B7379B48F88B7A4
+PT=C8347D508B23940B05542AC96BAB9FDB
+CT=2B1F53F35A308673E9B1E004C32B2080
+
+I=10
+KEY=D26C4C6BE601D63BDDE6F1A49B5124CB912A2DB0AAB5FB9833677EE5660CF3FF
+IV=2B1F53F35A308673E9B1E004C32B2080
+PT=9AB1F1CCE2BBA1394BEED104499B6C97
+CT=0DAE66B5741FE38E544D9EC4E90ABDAF
+
+I=11
+KEY=D241355DB8FC5F23D0D207F72E290F189C844B05DEAA1816672AE0218F064E50
+IV=0DAE66B5741FE38E544D9EC4E90ABDAF
+PT=002D79365EFD89180D34F653B5782BD3
+CT=D00122636CC0D9D62E614EAF0963C448
+
+I=12
+KEY=1BC3268A0B674A05B2FC6E18460231564C856966B26AC1C0494BAE8E86658A18
+IV=D00122636CC0D9D62E614EAF0963C448
+PT=C98213D7B39B1526622E69EF682B3E4E
+CT=30EF014D1766651C524B3CC82F0140C6
+
+I=13
+KEY=50BE5951A5C2403C52425897C442A8457C6A682BA50CA4DC1B009246A964CADE
+IV=30EF014D1766651C524B3CC82F0140C6
+PT=4B7D7FDBAEA50A39E0BE368F82409913
+CT=BAD488702B447FABEC2074E1DD37E631
+
+I=14
+KEY=C007EE52430FF98EDD206C94ED349DE6C6BEE05B8E48DB77F720E6A774532CEF
+IV=BAD488702B447FABEC2074E1DD37E631
+PT=90B9B703E6CDB9B28F623403297635A3
+CT=EC3862EB60E7D8D0827645BD690F71B8
+
+I=15
+KEY=AE37C1DBEBF9B269E8D10CC4F046F9FC2A8682B0EEAF03A77556A31A1D5C5D57
+IV=EC3862EB60E7D8D0827645BD690F71B8
+PT=6E302F89A8F64BE735F160501D72641A
+CT=6073D1F25F3697C1E07384C67D71D8AE
+
+I=16
+KEY=86E8B9050AB24200E3757B67F08761534AF55342B1999466952527DC602D85F9
+IV=6073D1F25F3697C1E07384C67D71D8AE
+PT=28DF78DEE14BF0690BA477A300C198AF
+CT=90EF55AB8837792F82CF0F002E36F8DB
+
+I=17
+KEY=DE93EA10BB6DC2B0A6D3919561CE5AE4DA1A06E939AEED4917EA28DC4E1B7D22
+IV=90EF55AB8837792F82CF0F002E36F8DB
+PT=587B5315B1DF80B045A6EAF291493BB7
+CT=063783CB1A2137732D10CA6233C5CE93
+
+I=18
+KEY=3D147E3727A1FEB2C6F36AB9DF772E97DC2D8522238FDA3A3AFAE2BE7DDEB3B1
+IV=063783CB1A2137732D10CA6233C5CE93
+PT=E38794279CCC3C026020FB2CBEB97473
+CT=79C5CEEE64BFD33948D2E08EBE25B7E9
+
+I=19
+KEY=34586C52923969647663A0D69436D7D1A5E84BCC4730090372280230C3FB0458
+IV=79C5CEEE64BFD33948D2E08EBE25B7E9
+PT=094C1265B59897D6B090CA6F4B41F946
+CT=87DFB65D575F56670DB739C988FD7DE5
+
+I=20
+KEY=53724BF79612A7F0237927604619DD592237FD91106F5F647F9F3BF94B0679BD
+IV=87DFB65D575F56670DB739C988FD7DE5
+PT=672A27A5042BCE94551A87B6D22F0A88
+CT=643F46BC77A5FE2434753B9C38142583
+
+I=21
+KEY=8FBC30746F29985FFFA43C8BD3C4FC664608BB2D67CAA1404BEA006573125C3E
+IV=643F46BC77A5FE2434753B9C38142583
+PT=DCCE7B83F93B3FAFDCDD1BEB95DD213F
+CT=FD774BD6874EA7C0D790A5015440B664
+
+I=22
+KEY=9A61A910701A4A42873549F78D3D9FD1BB7FF0FBE08406809C7AA5642752EA5A
+IV=FD774BD6874EA7C0D790A5015440B664
+PT=15DD99641F33D21D7891757C5EF963B7
+CT=BFCEF4403428F5C96C24C249962371D4
+
+I=23
+KEY=8D98738F6DF30113AF69A7A61C1582EE04B104BBD4ACF349F05E672DB1719B8E
+IV=BFCEF4403428F5C96C24C249962371D4
+PT=17F9DA9F1DE94B51285CEE5191281D3F
+CT=CC79F35C41F0E6C0EB03472B1D13029E
+
+I=24
+KEY=976C27F1A15FF6780043636FC4777090C8C8F7E7955C15891B5D2006AC629910
+IV=CC79F35C41F0E6C0EB03472B1D13029E
+PT=1AF4547ECCACF76BAF2AC4C9D862F27E
+CT=0629B80F94FBC2C1984985B9F3B85BDD
+
+I=25
+KEY=E8934C533DED166F58D65C9E60A906A5CEE14FE801A7D7488314A5BF5FDAC2CD
+IV=0629B80F94FBC2C1984985B9F3B85BDD
+PT=7FFF6BA29CB2E01758953FF1A4DE7635
+CT=F2A70F4ED1A836696841D523F2650B55
+
+I=26
+KEY=8116688C16D2C26D162C4D813FB267103C4640A6D00FE121EB55709CADBFC998
+IV=F2A70F4ED1A836696841D523F2650B55
+PT=698524DF2B3FD4024EFA111F5F1B61B5
+CT=A9B5565EB9B5D5DAC52BE0F449FBE11A
+
+I=27
+KEY=5A7062E77C6D20563AFD0BFDAAE04BE995F316F869BA34FB2E7E9068E4442882
+IV=A9B5565EB9B5D5DAC52BE0F449FBE11A
+PT=DB660A6B6ABFE23B2CD1467C95522CF9
+CT=E47F675379D4CE3DDABA0F906BE014B2
+
+I=28
+KEY=4DDC0A5938F4A3DC1AF8D3AFD3DF6198718C71AB106EFAC6F4C49FF88FA43C30
+IV=E47F675379D4CE3DDABA0F906BE014B2
+PT=17AC68BE4499838A2005D852793F2A71
+CT=7B95AB0E030C70B7940ECDAEFCA570A5
+
+I=29
+KEY=E287EFC66626600AF3453F68BE53E5250A19DAA513628A7160CA525673014C95
+IV=7B95AB0E030C70B7940ECDAEFCA570A5
+PT=AF5BE59F5ED2C3D6E9BDECC76D8C84BD
+CT=E854E5DE0C42D57B869C29FC8D5AFFF3
+
+I=30
+KEY=7F3415A538F60B24A58447E1D38805B3E24D3F7B1F205F0AE6567BAAFE5BB366
+IV=E854E5DE0C42D57B869C29FC8D5AFFF3
+PT=9DB3FA635ED06B2E56C178896DDBE096
+CT=4E55EDEDC35CDEAB3BFB2B5D39871625
+
+I=31
+KEY=59E5F5ECC5693DA07046636094970E8CAC18D296DC7C81A1DDAD50F7C7DCA543
+IV=4E55EDEDC35CDEAB3BFB2B5D39871625
+PT=26D1E049FD9F3684D5C22481471F0B3F
+CT=3355C2CC762E58FA941E0004209CA710
+
+I=32
+KEY=0B62CF7EA869036A529E9D184574CD609F4D105AAA52D95B49B350F3E7400253
+IV=3355C2CC762E58FA941E0004209CA710
+PT=52873A926D003ECA22D8FE78D1E3C3EC
+CT=9B86680D69D38870268D42E78EDA2B50
+
+I=33
+KEY=CEDC9CCC4DC42CB055EDC50597EE24DF04CB7857C381512B6F3E1214699A2903
+IV=9B86680D69D38870268D42E78EDA2B50
+PT=C5BE53B2E5AD2FDA0773581DD29AE9BF
+CT=05DD4896F08EEAA6A53FA7BCF183F538
+
+I=34
+KEY=CA30B422016C86247D75B618D19247AC011630C1330FBB8DCA01B5A89819DC3B
+IV=05DD4896F08EEAA6A53FA7BCF183F538
+PT=04EC28EE4CA8AA942898731D467C6373
+CT=F81E56F4390D65C7959348A6FBD8A94E
+
+I=35
+KEY=B7096A2EC0259DA21ACA6DBE637A9F15F90866350A02DE4A5F92FD0E63C17575
+IV=F81E56F4390D65C7959348A6FBD8A94E
+PT=7D39DE0CC1491B8667BFDBA6B2E8D8B9
+CT=4364CA2D90FA256084DF8E2FCDC62AB3
+
+I=36
+KEY=436C0894D4436149EE685F0061BDF3AEBA6CAC189AF8FB2ADB4D7321AE075FC6
+IV=4364CA2D90FA256084DF8E2FCDC62AB3
+PT=F46562BA1466FCEBF4A232BE02C76CBB
+CT=0991DE19A5ABE5F7E8AE24120789B9AB
+
+I=37
+KEY=44E1636AFF962EC4F1C446A89B9393C6B3FD72013F531EDD33E35733A98EE66D
+IV=0991DE19A5ABE5F7E8AE24120789B9AB
+PT=078D6BFE2BD54F8D1FAC19A8FA2E6068
+CT=0F4EF4FA608671AC5F71063CF6C1EBDE
+
+I=38
+KEY=44289918A9E99F859FC2F604FE38B86EBCB386FB5FD56F716C92510F5F4F0DB3
+IV=0F4EF4FA608671AC5F71063CF6C1EBDE
+PT=00C9FA72567FB1416E06B0AC65AB2BA8
+CT=2D6A2A1CC9D208C16236BBC9451EC5E1
+
+I=39
+KEY=BE5907C77B0939D20575F27427A2C3FE91D9ACE7960767B00EA4EAC61A51C852
+IV=2D6A2A1CC9D208C16236BBC9451EC5E1
+PT=FA719EDFD2E0A6579AB70470D99A7B90
+CT=237A8DFBA42708BBF7E540766F2059F1
+
+I=40
+KEY=CD97125720F2002207AC44C456CDDF0DB2A3211C32206F0BF941AAB0757191A3
+IV=237A8DFBA42708BBF7E540766F2059F1
+PT=73CE15905BFB39F002D9B6B0716F1CF3
+CT=2D1AB5CF3E9C27ADA9FB45F15007A7BB
+
+I=41
+KEY=123F64F2A28C80C2F6E000F69C8E5A639FB994D30CBC48A650BAEF4125763618
+IV=2D1AB5CF3E9C27ADA9FB45F15007A7BB
+PT=DFA876A5827E80E0F14C4432CA43856E
+CT=7039C9AF1E10FE99A91483EA578AE6DD
+
+I=42
+KEY=6CD69C4F5AD7CB5E9E4574F6A48FDB28EF805D7C12ACB63FF9AE6CAB72FCD0C5
+IV=7039C9AF1E10FE99A91483EA578AE6DD
+PT=7EE9F8BDF85B4B9C68A574003801814B
+CT=116DD8566366A19EEAF2F3E744B3EF9C
+
+I=43
+KEY=C73969C7D6D057003E2E215D94978792FEED852A71CA17A1135C9F4C364F3F59
+IV=116DD8566366A19EEAF2F3E744B3EF9C
+PT=ABEFF5888C079C5EA06B55AB30185CBA
+CT=648A801EF27E77D964BB751A32B8CFE8
+
+I=44
+KEY=E0960DD6E807F3D0B5DF057D0D1E6DCC9A67053483B4607877E7EA5604F7F0B1
+IV=648A801EF27E77D964BB751A32B8CFE8
+PT=27AF64113ED7A4D08BF124209989EA5E
+CT=D18AE728717C535049868FA6F1B4294E
+
+I=45
+KEY=466AE043435C6CCA67FF1C5D4B4175DA4BEDE21CF2C833283E6165F0F543D9FF
+IV=D18AE728717C535049868FA6F1B4294E
+PT=A6FCED95AB5B9F1AD2201920465F1816
+CT=169B55360728DA8F582C488F2569411F
+
+I=46
+KEY=27E1BC4931601D667CD807454D58B2BB5D76B72AF5E0E9A7664D2D7FD02A98E0
+IV=169B55360728DA8F582C488F2569411F
+PT=618B5C0A723C71AC1B271B180619C761
+CT=67DADCF7C31CA394F46F18AB1AEA022E
+
+I=47
+KEY=2D4EB1F3A709F0A4CA5E2CD47F8F10123AAC6BDD36FC4A33922235D4CAC09ACE
+IV=67DADCF7C31CA394F46F18AB1AEA022E
+PT=0AAF0DBA9669EDC2B6862B9132D7A2A9
+CT=A5D49BDF099335166BBFDCBE29C90B80
+
+I=48
+KEY=2A90CE470EB8C9400B056307D53452BE9F78F0023F6F7F25F99DE96AE309914E
+IV=A5D49BDF099335166BBFDCBE29C90B80
+PT=07DE7FB4A9B139E4C15B4FD3AABB42AC
+CT=5AFC238F19E369E77278593C6E20A946
+
+I=49
+KEY=90B696E9A0792BFF7BF21BE373731CB5C584D38D268C16C28BE5B0568D293808
+IV=5AFC238F19E369E77278593C6E20A946
+PT=BA2658AEAEC1E2BF70F778E4A6474E0B
+CT=2861A363922099D0F0B2A5AD2A5F421E
+
+I=50
+KEY=4FE5C563B7DB98C6B9CCA52F313FBAFCEDE570EEB4AC8F127B5715FBA7767A16
+IV=2861A363922099D0F0B2A5AD2A5F421E
+PT=DF53538A17A2B339C23EBECC424CA649
+CT=D76E51B6EA5F74D0116C4D16EDD0DFAC
+
+I=51
+KEY=EBF784D98E40372429819EE23BE85B723A8B21585EF3FBC26A3B58ED4AA6A5BA
+IV=D76E51B6EA5F74D0116C4D16EDD0DFAC
+PT=A41241BA399BAFE2904D3BCD0AD7E18E
+CT=6214F5E50EC99F40B86951CE395C8315
+
+I=52
+KEY=C01A5093C6A29CEED72D14D903BD17E8589FD4BD503A6482D252092373FA26AF
+IV=6214F5E50EC99F40B86951CE395C8315
+PT=2BEDD44A48E2ABCAFEAC8A3B38554C9A
+CT=6CFC2188E40E806BBE277988B924627E
+
+I=53
+KEY=A8C3A10380B6D4D1CEFABF57F3C695193463F535B434E4E96C7570ABCADE44D1
+IV=6CFC2188E40E806BBE277988B924627E
+PT=68D9F1904614483F19D7AB8EF07B82F1
+CT=B98E851902AEC129FD1607DECA9E0669
+
+I=54
+KEY=B828711ABA1D06408099944287112DE58DED702CB69A25C091637775004042B8
+IV=B98E851902AEC129FD1607DECA9E0669
+PT=10EBD0193AABD2914E632B1574D7B8FC
+CT=DBDA9DB56E6FF915D67D7DEE541DD6A3
+
+I=55
+KEY=3B0E9FE343D665ABB3706243EF023C765637ED99D8F5DCD5471E0A9B545D941B
+IV=DBDA9DB56E6FF915D67D7DEE541DD6A3
+PT=8326EEF9F9CB63EB33E9F60168131193
+CT=399802CE3FF3878A73C7D85E19FDD54B
+
+I=56
+KEY=9270D72D972B46C8E630FBD1AA67FBED6FAFEF57E7065B5F34D9D2C54DA04150
+IV=399802CE3FF3878A73C7D85E19FDD54B
+PT=A97E48CED4FD2363554099924565C79B
+CT=40FABA067414961FD964EC91196943E3
+
+I=57
+KEY=017211AC512541BFBDD0292385AA20862F5555519312CD40EDBD3E5454C902B3
+IV=40FABA067414961FD964EC91196943E3
+PT=9302C681C60E07775BE0D2F22FCDDB6B
+CT=6BF1125E581341510FD02B9450886B17
+
+I=58
+KEY=AC2652A877F924710178641D20B239B944A4470FCB018C11E26D15C0044169A4
+IV=6BF1125E581341510FD02B9450886B17
+PT=AD54430426DC65CEBCA84D3EA518193F
+CT=74871D2EF6D1F29181B0A2530885EEC8
+
+I=59
+KEY=0BF012A9F0CB194C1F00893D4803E10130235A213DD07E8063DDB7930CC4876C
+IV=74871D2EF6D1F29181B0A2530885EEC8
+PT=A7D6400187323D3D1E78ED2068B1D8B8
+CT=2A2DC9F5CB47C94D430ECAAAB1D0811E
+
+I=60
+KEY=8D22EEEA013E327509E84630166331DB1A0E93D4F697B7CD20D37D39BD140672
+IV=2A2DC9F5CB47C94D430ECAAAB1D0811E
+PT=86D2FC43F1F52B3916E8CF0D5E60D0DA
+CT=BC318E32957CE6577CD06E2D3166CD1F
+
+I=61
+KEY=1C4909D11840D978FD7232D0FBC0E6A3A63F1DE663EB519A5C0313148C72CB6D
+IV=BC318E32957CE6577CD06E2D3166CD1F
+PT=916BE73B197EEB0DF49A74E0EDA3D778
+CT=E9858DBB1B5145ABB598ADE882346DDB
+
+I=62
+KEY=DD2ED3C6FCE0034F19259D57A35B60CF4FBA905D78BA1431E99BBEFC0E46A6B6
+IV=E9858DBB1B5145ABB598ADE882346DDB
+PT=C167DA17E4A0DA37E457AF87589B866C
+CT=1E04B15BBF727BEAC33C0C26141636DD
+
+I=63
+KEY=81C434CDF7EABAA49252EC86DFE15FBA51BE2106C7C86FDB2AA7B2DA1A50906B
+IV=1E04B15BBF727BEAC33C0C26141636DD
+PT=5CEAE70B0B0AB9EB8B7771D17CBA3F75
+CT=EB21AED731D594017F5729262A1E23B4
+
+I=64
+KEY=AEF6BF8323CAE4C2270CC5E51B0A3BFFBA9F8FD1F61DFBDA55F09BFC304EB3DF
+IV=EB21AED731D594017F5729262A1E23B4
+PT=2F328B4ED4205E66B55E2963C4EB6445
+CT=EB73CFADA0ACB98B37091CB81489CC7C
+
+I=65
+KEY=BC3BD548867FA82FF80EF67B38016A1E51EC407C56B1425162F9874424C77FA3
+IV=EB73CFADA0ACB98B37091CB81489CC7C
+PT=12CD6ACBA5B54CEDDF02339E230B51E1
+CT=1FEEF226D6759E8813B98A5D43B2F22A
+
+I=66
+KEY=E1F5760C694DBE5688A0241B5517B4B14E02B25A80C4DCD971400D1967758D89
+IV=1FEEF226D6759E8813B98A5D43B2F22A
+PT=5DCEA344EF32167970AED2606D16DEAF
+CT=9C591D087F0F45C8AE3DEC9C455FE200
+
+I=67
+KEY=ABF2D79C472D0159FA9AE646D0C0FC9CD25BAF52FFCB9911DF7DE185222A6F89
+IV=9C591D087F0F45C8AE3DEC9C455FE200
+PT=4A07A1902E60BF0F723AC25D85D7482D
+CT=62C4F4D7E4AC5ABC03BECA3CA56DA4FD
+
+I=68
+KEY=E58A351A4DD79A2ED6D386E11A8563F2B09F5B851B67C3ADDCC32BB98747CB74
+IV=62C4F4D7E4AC5ABC03BECA3CA56DA4FD
+PT=4E78E2860AFA9B772C4960A7CA459F6E
+CT=AD8557C0D04675CC312C7A106D5C8B83
+
+I=69
+KEY=BCF7BB1010AF5CEB05E06339689067E31D1A0C45CB21B661EDEF51A9EA1B40F7
+IV=AD8557C0D04675CC312C7A106D5C8B83
+PT=597D8E0A5D78C6C5D333E5D872150411
+CT=80159F4F5E0C2DC07D3CD3C52A1A8E6D
+
+I=70
+KEY=328BB8EB86055D2BB52A02E40BB5D2C39D0F930A952D9BA190D3826CC001CE9A
+IV=80159F4F5E0C2DC07D3CD3C52A1A8E6D
+PT=8E7C03FB96AA01C0B0CA61DD6325B520
+CT=F58A2EE5A5BDE8CA0A96F4F4B64BE737
+
+I=71
+KEY=F192AE51D926A2B68C38EA4E48A0590F6885BDEF3090736B9A457698764A29AD
+IV=F58A2EE5A5BDE8CA0A96F4F4B64BE737
+PT=C31916BA5F23FF9D3912E8AA43158BCC
+CT=B4C0DD55013AEFE12D94F31B861134CC
+
+I=72
+KEY=5EE48E38C2C805E2AACC89AD8682E552DC4560BA31AA9C8AB7D18583F05B1D61
+IV=B4C0DD55013AEFE12D94F31B861134CC
+PT=AF7620691BEEA75426F463E3CE22BC5D
+CT=FD8B06AEF9B3C25D11B950A6648276BB
+
+I=73
+KEY=F425B9BF4D114251736EE7FCDB430B6721CE6614C8195ED7A668D52594D96BDA
+IV=FD8B06AEF9B3C25D11B950A6648276BB
+PT=AAC137878FD947B3D9A26E515DC1EE35
+CT=31BE8DF4A8A749FBF11AB07D8479A10B
+
+I=74
+KEY=61A2D5337BCB827887F884AD98C67BEA1070EBE060BE172C5772655810A0CAD1
+IV=31BE8DF4A8A749FBF11AB07D8479A10B
+PT=95876C8C36DAC029F49663514385708D
+CT=E9A2EF0C882781788D50033B79FE181F
+
+I=75
+KEY=E930B2277AC4475FB0A94519F60DE552F9D204ECE8999654DA226663695ED2CE
+IV=E9A2EF0C882781788D50033B79FE181F
+PT=88926714010FC5273751C1B46ECB9EB8
+CT=17FFCD5A010709A2737570E038D63B27
+
+I=76
+KEY=B944CE978DF68F8FBFF0A5EA62AAC299EE2DC9B6E99E9FF6A95716835188E9E9
+IV=17FFCD5A010709A2737570E038D63B27
+PT=50747CB0F732C8D00F59E0F394A727CB
+CT=E12B89FA1B1DD3B29F02219FD3D7D3D2
+
+I=77
+KEY=0E2D7FCEB557462267BED2CCA8B48CD70F06404CF2834C443655371C825F3A3B
+IV=E12B89FA1B1DD3B29F02219FD3D7D3D2
+PT=B769B15938A1C9ADD84E7726CA1E4E4E
+CT=75AE99B6022B08E36FB88A6F4D7698BF
+
+I=78
+KEY=8046D73D60912221694B2AFE703EDB167AA8D9FAF0A844A759EDBD73CF29A284
+IV=75AE99B6022B08E36FB88A6F4D7698BF
+PT=8E6BA8F3D5C664030EF5F832D88A57C1
+CT=CF32DCE11FDB098A6435315342796064
+
+I=79
+KEY=20716D6975C32231968BF76725144CBAB59A051BEF734D2D3DD88C208D50C2E0
+IV=CF32DCE11FDB098A6435315342796064
+PT=A037BA5415520010FFC0DD99552A97AC
+CT=80F12B261317C66F21AC811230848468
+
+I=80
+KEY=AD5A2011E425AFFD57E7191336D37D25356B2E3DFC648B421C740D32BDD44688
+IV=80F12B261317C66F21AC811230848468
+PT=8D2B4D7891E68DCCC16CEE7413C7319F
+CT=F2C6B70C19A5748C6D2B5DE41544854F
+
+I=81
+KEY=49D4228508C789105CF457D10FA56048C7AD9931E5C1FFCE715F50D6A890C3C7
+IV=F2C6B70C19A5748C6D2B5DE41544854F
+PT=E48E0294ECE226ED0B134EC239761D6D
+CT=A31FB3535978DAA555DD617FAB27A97A
+
+I=82
+KEY=67CE710A3E778CB4A37D1F2274D4462D64B22A62BCB9256B248231A903B76ABD
+IV=A31FB3535978DAA555DD617FAB27A97A
+PT=2E1A538F36B005A4FF8948F37B712665
+CT=97336ECFAE89015E0B5A7D1C154C71BF
+
+I=83
+KEY=A87C517EF43CACC6D41EEB661DD1142CF38144AD123024352FD84CB516FB1B02
+IV=97336ECFAE89015E0B5A7D1C154C71BF
+PT=CFB22074CA4B20727763F44469055201
+CT=466CD227A6A9D5FC3C0579064530FCE0
+
+I=84
+KEY=D73F926A5B5DD8F5B82DE8F77E0E0697B5ED968AB499F1C913DD35B353CBE7E2
+IV=466CD227A6A9D5FC3C0579064530FCE0
+PT=7F43C314AF6174336C33039163DF12BB
+CT=4F444B4554E965A113DC0097AA8FAD7A
+
+I=85
+KEY=7A19BE1C42A13B85B754834E9808DF4BFAA9DDCFE070946800013524F9444A98
+IV=4F444B4554E965A113DC0097AA8FAD7A
+PT=AD262C7619FCE3700F796BB9E606D9DC
+CT=F7078ABE7617867274CBBEDA1082B987
+
+I=86
+KEY=D256675EDBF987B5CA86C21DE177C6A00DAE57719667121A74CA8BFEE9C6F31F
+IV=F7078ABE7617867274CBBEDA1082B987
+PT=A84FD9429958BC307DD24153797F19EB
+CT=676ACAB66B04597F1A33FF462BD5E0EE
+
+I=87
+KEY=C025616AB6F89BB1B90AA0E8F63FF1CC6AC49DC7FD634B656EF974B8C21313F1
+IV=676ACAB66B04597F1A33FF462BD5E0EE
+PT=127306346D011C04738C62F51748376C
+CT=BF66B8DD1E540A4FED759FDB9A44B439
+
+I=88
+KEY=2A437D44D93C25B3233FB168D63751A5D5A2251AE337412A838CEB635857A7C8
+IV=BF66B8DD1E540A4FED759FDB9A44B439
+PT=EA661C2E6FC4BE029A3511802008A069
+CT=EC8DBB5B3FE245180856B312D3052A87
+
+I=89
+KEY=838278123F0261D1F287C9FF94CA4A55392F9E41DCD504328BDA58718B528D4F
+IV=EC8DBB5B3FE245180856B312D3052A87
+PT=A9C10556E63E4462D1B8789742FD1BF0
+CT=02E1E60312BB371912C35E3EBC6EA755
+
+I=90
+KEY=64F3A47C8C7CFA9FF2AC88637C598E6A3BCE7842CE6E332B9919064F373C2A1A
+IV=02E1E60312BB371912C35E3EBC6EA755
+PT=E771DC6EB37E9B4E002B419CE893C43F
+CT=73D7499EBB38716D71CCB737CFFFA3FB
+
+I=91
+KEY=585ABE6B779F22400FC2AC3B55B39E91481931DC75564246E8D5B178F8C389E1
+IV=73D7499EBB38716D71CCB737CFFFA3FB
+PT=3CA91A17FBE3D8DFFD6E245829EA10FB
+CT=CEE7721855B7381D369ECC1C9337BB02
+
+I=92
+KEY=7BC1E883465CBBB9BA624FF99308259386FE43C420E17A5BDE4B7D646BF432E3
+IV=CEE7721855B7381D369ECC1C9337BB02
+PT=239B56E831C399F9B5A0E3C2C6BBBB02
+CT=B6F48D369383974D163E4F17FDFC59EF
+
+I=93
+KEY=70032AF50BB5E080D4AA7722CEDC7DA9300ACEF2B362ED16C875327396086B0C
+IV=B6F48D369383974D163E4F17FDFC59EF
+PT=0BC2C2764DE95B396EC838DB5DD4583A
+CT=E8372DA404126C63190626D95583629D
+
+I=94
+KEY=5C61B59BDA2FF51D4F4F740578466EA9D83DE356B7708175D17314AAC38B0991
+IV=E8372DA404126C63190626D95583629D
+PT=2C629F6ED19A159D9BE50327B69A1300
+CT=F717B53E51665D0854C895EA1D1D7E77
+
+I=95
+KEY=59A35E82B9C8D8FF25CFC5BAD979A9052F2A5668E616DC7D85BB8140DE9677E6
+IV=F717B53E51665D0854C895EA1D1D7E77
+PT=05C2EB1963E72DE26A80B1BFA13FC7AC
+CT=7D3EE90EEF7C16872F98296977AA9557
+
+I=96
+KEY=5BC419836F7C4F57957E13E39B2181455214BF66096ACAFAAA23A829A93CE2B1
+IV=7D3EE90EEF7C16872F98296977AA9557
+PT=02674701D6B497A8B0B1D65942582840
+CT=6DCD0C4B5633078FDEA9AE24781CB212
+
+I=97
+KEY=E6D2BB67584AA2FAAE1D0DAD8C9C60253FD9B32D5F59CD75748A060DD12050A3
+IV=6DCD0C4B5633078FDEA9AE24781CB212
+PT=BD16A2E43736EDAD3B631E4E17BDE160
+CT=6515251260A73AE868E992B6D49579C5
+
+I=98
+KEY=57637851C3C08A2923EBD2FEA27472DC5ACC963F3FFEF79D1C6394BB05B52966
+IV=6515251260A73AE868E992B6D49579C5
+PT=B1B1C3369B8A28D38DF6DF532EE812F9
+CT=1A40C2C15F03867E81F951B545396BB4
+
+I=99
+KEY=E08E94110F1E64554848AB1966299B7D408C54FE60FD71E39D9AC50E408C42D2
+IV=1A40C2C15F03867E81F951B545396BB4
+PT=B7EDEC40CCDEEE7C6BA379E7C45DE9A1
+CT=DD331F336D669EFD37106099EA51010D
+
+I=100
+KEY=17F2544156745EC108BF97DA806752C39DBF4BCD0D9BEF1EAA8AA597AADD43DF
+IV=DD331F336D669EFD37106099EA51010D
+PT=F77CC050596A3A9440F73CC3E64EC9BE
+CT=0EF37EC0B6071874FF68926D98A0EEAB
+
+I=101
+KEY=C97ABFF115E20A6C72A6206DB63EC0FD934C350DBB9CF76A55E237FA327DAD74
+IV=0EF37EC0B6071874FF68926D98A0EEAB
+PT=DE88EBB0439654AD7A19B7B73659923E
+CT=DA1DAEB42178A7657A40BD72A06CEDDC
+
+I=102
+KEY=77AB469FBC999BB2922D460413E2012049519BB99AE4500F2FA28A88921140A8
+IV=DA1DAEB42178A7657A40BD72A06CEDDC
+PT=BED1F96EA97B91DEE08B6669A5DCC1DD
+CT=E78523134FC8EAA77CC85E0EEC60FCD3
+
+I=103
+KEY=4F88FA6F4053B3A15094ED532C2F47DCAED4B8AAD52CBAA8536AD4867E71BC7B
+IV=E78523134FC8EAA77CC85E0EEC60FCD3
+PT=3823BCF0FCCA2813C2B9AB573FCD46FC
+CT=BC540D1838D7AD8E8B1C44B96684DD31
+
+I=104
+KEY=D178E105443700CFEE007AB3BAA71E4C1280B5B2EDFB1726D876903F18F5614A
+IV=BC540D1838D7AD8E8B1C44B96684DD31
+PT=9EF01B6A0464B36EBE9497E096885990
+CT=6C6B95A5D8F4E7F1A5864DDBFCDCEED8
+
+I=105
+KEY=8F6A589BA0ED1A67FE426368A7E523047EEB2017350FF0D77DF0DDE4E4298F92
+IV=6C6B95A5D8F4E7F1A5864DDBFCDCEED8
+PT=5E12B99EE4DA1AA8104219DB1D423D48
+CT=B58C92AE19B332621E7A4E5512C88596
+
+I=106
+KEY=147895B157BF16B87C32AAA17480A886CB67B2B92CBCC2B5638A93B1F6E10A04
+IV=B58C92AE19B332621E7A4E5512C88596
+PT=9B12CD2AF7520CDF8270C9C9D3658B82
+CT=4D1D90F007BB5099C382E69C9CD1F7E5
+
+I=107
+KEY=4C8441FCEBBD595999864A6CC37F7EDB867A22492B07922CA008752D6A30FDE1
+IV=4D1D90F007BB5099C382E69C9CD1F7E5
+PT=58FCD44DBC024FE1E5B4E0CDB7FFD65D
+CT=7F59920056EC32FA48F8A9CCCFFE437A
+
+I=108
+KEY=CD922EEA60F0F136A799C650F5D4B030F923B0497DEBA0D6E8F0DCE1A5CEBE9B
+IV=7F59920056EC32FA48F8A9CCCFFE437A
+PT=81166F168B4DA86F3E1F8C3C36ABCEEB
+CT=A546F57E48A783694577D59F7FD01D9E
+
+I=109
+KEY=90DE3ECB26E68BDD3C4B7AB9B9CDE6195C654537354C23BFAD87097EDA1EA305
+IV=A546F57E48A783694577D59F7FD01D9E
+PT=5D4C102146167AEB9BD2BCE94C195629
+CT=6342B8CB1E493F916585FF1BBFC42AB3
+
+I=110
+KEY=ADF1869FEA15122394E1F6FF6B51E5DE3F27FDFC2B051C2EC802F66565DA89B6
+IV=6342B8CB1E493F916585FF1BBFC42AB3
+PT=3D2FB854CCF399FEA8AA8C46D29C03C7
+CT=052AEDF54016429320B04243E308ECFE
+
+I=111
+KEY=DF52D7982845CBAEB4E56592906B63943A0D10096B135EBDE8B2B42686D26548
+IV=052AEDF54016429320B04243E308ECFE
+PT=72A35107C250D98D2004936DFB3A864A
+CT=EE147A64DC2E31222A3A14B133769ACE
+
+I=112
+KEY=5D6B5899612FF15825029DEB0B37CB4ED4196A6DB73D6F9FC288A097B5A4FF86
+IV=EE147A64DC2E31222A3A14B133769ACE
+PT=82398F01496A3AF691E7F8799B5CA8DA
+CT=8330EF868E72D33172D7DEC7B440056C
+
+I=113
+KEY=FC23917C478894C9490A6585CCB8A716572985EB394FBCAEB05F7E5001E4FAEA
+IV=8330EF868E72D33172D7DEC7B440056C
+PT=A148C9E526A765916C08F86EC78F6C58
+CT=DC83E3727C4E9754A82BFCFFD924ACB3
+
+I=114
+KEY=BCD556FA7AFA27F9675F45922924DFA68BAA669945012BFA187482AFD8C05659
+IV=DC83E3727C4E9754A82BFCFFD924ACB3
+PT=40F6C7863D72B3302E552017E59C78B0
+CT=C0B97D9320DC3E893953E1D93859D3E4
+
+I=115
+KEY=A0F23A11C85F008CFEC20F76BD6751054B131B0A65DD157321276376E09985BD
+IV=C0B97D9320DC3E893953E1D93859D3E4
+PT=1C276CEBB2A52775999D4AE494438EA3
+CT=8C28875C39211D01A084A59BA71D0C31
+
+I=116
+KEY=2BB58C8FE9FE5BAEC5DB3F6A7EB98187C73B9C565CFC087281A3C6ED4784898C
+IV=8C28875C39211D01A084A59BA71D0C31
+PT=8B47B69E21A15B223B19301CC3DED082
+CT=7865E390E8019259A117669082ED5CCC
+
+I=117
+KEY=6035A1AC1F0C1871EA06773DEA40B5C5BF5E7FC6B4FD9A2B20B4A07DC569D540
+IV=7865E390E8019259A117669082ED5CCC
+PT=4B802D23F6F243DF2FDD485794F93442
+CT=DC7BA7C54217B8DEE966C0672DBE79CD
+
+I=118
+KEY=CCA70BB373BA65736D25078BB99980F66325D803F6EA22F5C9D2601AE8D7AC8D
+IV=DC7BA7C54217B8DEE966C0672DBE79CD
+PT=AC92AA1F6CB67D02872370B653D93533
+CT=CBB60FB6BE7240A2037CDA46DAAAC4E4
+
+I=119
+KEY=E6D9E4347ABCE875CDFB026A9B1CE767A893D7B548986257CAAEBA5C327D6869
+IV=CBB60FB6BE7240A2037CDA46DAAAC4E4
+PT=2A7EEF8709068D06A0DE05E122856791
+CT=3B0863884DCFFDAAE439E3BCFC2E0491
+
+I=120
+KEY=90C0678C9B9796FACBD3A9E8E40A46E6939BB43D05579FFD2E9759E0CE536CF8
+IV=3B0863884DCFFDAAE439E3BCFC2E0491
+PT=761983B8E12B7E8F0628AB827F16A181
+CT=1407CDBD04CA6450D15A276B0E45D500
+
+I=121
+KEY=A3505D86BF4B95AEC0F720B4CBDF4985879C7980019DFBADFFCD7E8BC016B9F8
+IV=1407CDBD04CA6450D15A276B0E45D500
+PT=33903A0A24DC03540B24895C2FD50F63
+CT=94B64DF8376EAF94F24EB0457DF81418
+
+I=122
+KEY=EAD741BA44D8637A4D49A089E4A122F2132A347836F354390D83CECEBDEEADE0
+IV=94B64DF8376EAF94F24EB0457DF81418
+PT=49871C3CFB93F6D48DBE803D2F7E6B77
+CT=6E2DE304D4A21A218291FD9B59FED9BF
+
+I=123
+KEY=278551B22B73239BF36E61370FFF43EA7D07D77CE2514E188F123355E410745F
+IV=6E2DE304D4A21A218291FD9B59FED9BF
+PT=CD5210086FAB40E1BE27C1BEEB5E6118
+CT=72A1E7B22D6B8B8C38C4CCD545466879
+
+I=124
+KEY=C7046CA82928EA5AE1E6998399A090BB0FA630CECF3AC594B7D6FF80A1561C26
+IV=72A1E7B22D6B8B8C38C4CCD545466879
+PT=E0813D1A025BC9C11288F8B4965FD351
+CT=F5F1B011C644D119625733433C3DBB40
+
+I=125
+KEY=82AF7079A309A3B1367E4DC8EE90B8C5FA5780DF097E148DD581CCC39D6BA766
+IV=F5F1B011C644D119625733433C3DBB40
+PT=45AB1CD18A2149EBD798D44B7730287E
+CT=FDD90319FC2878AE4E23CE63C6660D1A
+
+I=126
+KEY=EB439411E1412BA8D6DB9F3052753D3F078E83C6F5566C239BA202A05B0DAA7C
+IV=FDD90319FC2878AE4E23CE63C6660D1A
+PT=69ECE46842488819E0A5D2F8BCE585FA
+CT=0B3948AEFD674622289CB41E3F668A5C
+
+I=127
+KEY=C2FDF3EB8C01693C7FB990CE6D7F56E10CB7CB6808312A01B33EB6BE646B2020
+IV=0B3948AEFD674622289CB41E3F668A5C
+PT=29BE67FA6D404294A9620FFE3F0A6BDE
+CT=9F5BF60EB5CCF9D9F3A20DA569209636
+
+I=128
+KEY=ECF0B5C32A3163495086894AB263166D93EC3D66BDFDD3D8409CBB1B0D4BB616
+IV=9F5BF60EB5CCF9D9F3A20DA569209636
+PT=2E0D4628A6300A752F3F1984DF1C408C
+CT=3FED40A5796B3D1FF8805E5EF8922511
+
+I=129
+KEY=259CAA194EE9BE90B2B1E7654CBDCD03AC017DC3C496EEC7B81CE545F5D99307
+IV=3FED40A5796B3D1FF8805E5EF8922511
+PT=C96C1FDA64D8DDD9E2376E2FFEDEDB6E
+CT=2973A39E09EF5F4F42B29E6730ECC127
+
+I=130
+KEY=FAAB18CE5FA7895BAA9EC69A55F690208572DE5DCD79B188FAAE7B22C5355220
+IV=2973A39E09EF5F4F42B29E6730ECC127
+PT=DF37B2D7114E37CB182F21FF194B5D23
+CT=F8C4C1A86B0665E2124CFFA9128FFEFD
+
+I=131
+KEY=3806BAB3764E794DF526A17BCE0112877DB61FF5A67FD46AE8E2848BD7BAACDD
+IV=F8C4C1A86B0665E2124CFFA9128FFEFD
+PT=C2ADA27D29E9F0165FB867E19BF782A7
+CT=90996F6629A41FC86A9520DD33AE5B3F
+
+I=132
+KEY=B7F781357E024140C3797D01C286E72BED2F70938FDBCBA28277A456E414F7E2
+IV=90996F6629A41FC86A9520DD33AE5B3F
+PT=8FF13B86084C380D365FDC7A0C87F5AC
+CT=9DAFB2F259BFD18945A0A6EFF9A81A75
+
+I=133
+KEY=B67D37A8E281AFD015C38A72F5662BEE7080C261D6641A2BC7D702B91DBCED97
+IV=9DAFB2F259BFD18945A0A6EFF9A81A75
+PT=018AB69D9C83EE90D6BAF77337E0CCC5
+CT=C89F523289AE2A7C8F796C2252CB0597
+
+I=134
+KEY=A47B97F34FB4A8F219ED7A59EFE40080B81F90535FCA305748AE6E9B4F77E800
+IV=C89F523289AE2A7C8F796C2252CB0597
+PT=1206A05BAD3507220C2EF02B1A822B6E
+CT=3AACC4E5DE152BB1730C6D10C9A81A0A
+
+I=135
+KEY=E8EBBFDA61B6BC6735953F8E448B5E0282B354B681DF1BE63BA2038B86DFF20A
+IV=3AACC4E5DE152BB1730C6D10C9A81A0A
+PT=4C9028292E0214952C7845D7AB6F5E82
+CT=1E315BFFFDC3DA42438E683263B496DD
+
+I=136
+KEY=EE950FF3D603DECEE18F4ACF99A623589C820F497C1CC1A4782C6BB9E56B64D7
+IV=1E315BFFFDC3DA42438E683263B496DD
+PT=067EB029B7B562A9D41A7541DD2D7D5A
+CT=9B021A44CD9FF920DFE1EC97B3EE8AE4
+
+I=137
+KEY=E073E1149A4A605E041167F3739F17240780150DB1833884A7CD872E5685EE33
+IV=9B021A44CD9FF920DFE1EC97B3EE8AE4
+PT=0EE6EEE74C49BE90E59E2D3CEA39347C
+CT=4F62EE03D7A8337ECB3DCC0EA5444C2D
+
+I=138
+KEY=BF449E4B7DFA404D3F18C0266725F67248E2FB0E662B0BFA6CF04B20F3C1A21E
+IV=4F62EE03D7A8337ECB3DCC0EA5444C2D
+PT=5F377F5FE7B020133B09A7D514BAE156
+CT=AC8767B1E15D6D1ECACCCBF2D0FAB043
+
+I=139
+KEY=3AB2898399D0F8467B37A5C916D9117AE4659CBF877666E4A63C80D2233B125D
+IV=AC8767B1E15D6D1ECACCCBF2D0FAB043
+PT=85F617C8E42AB80B442F65EF71FCE708
+CT=9CA6E27F1966AE133CB7B98C2B13C1DA
+
+I=140
+KEY=06A09B6D5A6BCA82B26D0625F2A89FA178C37EC09E10C8F79A8B395E0828D387
+IV=9CA6E27F1966AE133CB7B98C2B13C1DA
+PT=3C1212EEC3BB32C4C95AA3ECE4718EDB
+CT=B7A6788E6D9886047D1450B093F5B6FE
+
+I=141
+KEY=79A26263675E11BE581DDEA79A20CAACCF65064EF3884EF3E79F69EE9BDD6579
+IV=B7A6788E6D9886047D1450B093F5B6FE
+PT=7F02F90E3D35DB3CEA70D8826888550D
+CT=5C1785DC27BC301DEAFAEF325A4CCBFD
+
+I=142
+KEY=21DEF781026D9ACB4108C6F9847C635F93728392D4347EEE0D6586DCC191AE84
+IV=5C1785DC27BC301DEAFAEF325A4CCBFD
+PT=587C95E265338B751915185E1E5CA9F3
+CT=9577E8F6DF5921C4B518974A2F1FCF07
+
+I=143
+KEY=EB000BAA170733EA4D077BDD7DA1623506056B640B6D5F2AB87D1196EE8E6183
+IV=9577E8F6DF5921C4B518974A2F1FCF07
+PT=CADEFC2B156AA9210C0FBD24F9DD016A
+CT=09F8E3DA7C5E39F2F13C2B72001D1D56
+
+I=144
+KEY=D56A1025AB5F7B5F943B3AECAF87A2800FFD88BE773366D849413AE4EE937CD5
+IV=09F8E3DA7C5E39F2F13C2B72001D1D56
+PT=3E6A1B8FBC5848B5D93C4131D226C0B5
+CT=7344F33968E177F3864908F02915739A
+
+I=145
+KEY=876077EA9BDB2134098B73CAD4411D997CB97B871FD2112BCF083214C7860F4F
+IV=7344F33968E177F3864908F02915739A
+PT=520A67CF30845A6B9DB049267BC6BF19
+CT=EC286360EF2A54CE894ED06ACF39970C
+
+I=146
+KEY=AA9943761AD545F47EBCF5CD4584C3B3909118E7F0F845E54646E27E08BF9843
+IV=EC286360EF2A54CE894ED06ACF39970C
+PT=2DF9349C810E64C07737860791C5DE2A
+CT=89F4BE70D36A05C84FD2124F6A69786B
+
+I=147
+KEY=5C285D3FD07EF5F6664B1F4C4CA771E31965A6972392402D0994F03162D6E028
+IV=89F4BE70D36A05C84FD2124F6A69786B
+PT=F6B11E49CAABB00218F7EA810923B250
+CT=9A65E99C06E0744056365C4A26CD001F
+
+I=148
+KEY=F28851656D77922A55655DBE4610993683004F0B2572346D5FA2AC7B441BE037
+IV=9A65E99C06E0744056365C4A26CD001F
+PT=AEA00C5ABD0967DC332E42F20AB7E8D5
+CT=566ECB7B317C81CF87BC483B4B6CF417
+
+I=149
+KEY=62428DD3F6B04C564CA6D9DA9A9A64B3D56E8470140EB5A2D81EE4400F771420
+IV=566ECB7B317C81CF87BC483B4B6CF417
+PT=90CADCB69BC7DE7C19C38464DC8AFD85
+CT=16E3F727D2D4CC2E88C2A4B0DFEF34AF
+
+I=150
+KEY=78A68A0EC33E2C0198538C1EA591AF46C38D7357C6DA798C50DC40F0D098208F
+IV=16E3F727D2D4CC2E88C2A4B0DFEF34AF
+PT=1AE407DD358E6057D4F555C43F0BCBF5
+CT=6F6606018F5491FC43864FC29B572551
+
+I=151
+KEY=4EFBCF71F7A0DA7564DAF1F0488AA933ACEB7556498EE870135A0F324BCF05DE
+IV=6F6606018F5491FC43864FC29B572551
+PT=365D457F349EF674FC897DEEED1B0675
+CT=BC07194E716B4D78F64E14B6E5762439
+
+I=152
+KEY=A4BBF15395604071DF929A4922A129DD10EC6C1838E5A508E5141B84AEB921E7
+IV=BC07194E716B4D78F64E14B6E5762439
+PT=EA403E2262C09A04BB486BB96A2B80EE
+CT=BF1994171481FB4F84AB092F437EA9C7
+
+I=153
+KEY=665F10926596E8F5691ACE10AA5075AEAFF5F80F2C645E4761BF12ABEDC78820
+IV=BF1994171481FB4F84AB092F437EA9C7
+PT=C2E4E1C1F0F6A884B688545988F15C73
+CT=254FE05D25B67D3BF6C2688F46A7FAD8
+
+I=154
+KEY=15F4BA29EBAAF160AC95507FDA03D7D58ABA185209D2237C977D7A24AB6072F8
+IV=254FE05D25B67D3BF6C2688F46A7FAD8
+PT=73ABAABB8E3C1995C58F9E6F7053A27B
+CT=A03B8DB2C1C9B6C574A8499C6E5869CF
+
+I=155
+KEY=96A760AB52E1D6A5ACFCA016E98D0BA12A8195E0C81B95B9E3D533B8C5381B37
+IV=A03B8DB2C1C9B6C574A8499C6E5869CF
+PT=8353DA82B94B27C50069F069338EDC74
+CT=088F141F097F659145DE8E1EDB2300B5
+
+I=156
+KEY=7C06F9EE0327C811CEE3CC3B2B492620220E81FFC164F028A60BBDA61E1B1B82
+IV=088F141F097F659145DE8E1EDB2300B5
+PT=EAA1994551C61EB4621F6C2DC2C42D81
+CT=43703327BFDAF109F6F9C5969D3C7649
+
+I=157
+KEY=0F8AC1E3014DD99D1A440A693CB73B51617EB2D87EBE012150F2783083276DCB
+IV=43703327BFDAF109F6F9C5969D3C7649
+PT=738C380D026A118CD4A7C65217FE1D71
+CT=BDAC873D0A674CDA98105DC3070F7BE4
+
+I=158
+KEY=E595998ABEF32CABDD4A441B4042BF8BDCD235E574D94DFBC8E225F38428162F
+IV=BDAC873D0A674CDA98105DC3070F7BE4
+PT=EA1F5869BFBEF536C70E4E727CF584DA
+CT=A1A89122CF532FBC69E74A70F1E7346F
+
+I=159
+KEY=FBA3999F7BF540184E9BE7715CA8C0497D7AA4C7BB8A6247A1056F8375CF2240
+IV=A1A89122CF532FBC69E74A70F1E7346F
+PT=1E360015C5066CB393D1A36A1CEA7FC2
+CT=68C2A6FF8EABE7EA05E5DD6093C00129
+
+I=160
+KEY=65AF7CB5F5CEF75FEF0BF5F746D7DD7D15B80238352185ADA4E0B2E3E60F2369
+IV=68C2A6FF8EABE7EA05E5DD6093C00129
+PT=9E0CE52A8E3BB747A19012861A7F1D34
+CT=1EA92E63C6926082B04F69E658CFA478
+
+I=161
+KEY=7D3BA807729873EB2021AC1817B2C7D30B112C5BF3B3E52F14AFDB05BEC08711
+IV=1EA92E63C6926082B04F69E658CFA478
+PT=1894D4B2875684B4CF2A59EF51651AAE
+CT=45A943F0B6430ABA20C562469AE98A6D
+
+I=162
+KEY=5ECAEF5BF4EC899C7BFAEE2F50B864924EB86FAB45F0EF95346AB94324290D7C
+IV=45A943F0B6430ABA20C562469AE98A6D
+PT=23F1475C8674FA775BDB4237470AA341
+CT=6CDF579A8429606CC9BC56D010845954
+
+I=163
+KEY=8D394BD1C8C1D1F8A67A3BA16530662A22673831C1D98FF9FDD6EF9334AD5428
+IV=6CDF579A8429606CC9BC56D010845954
+PT=D3F3A48A3C2D5864DD80D58E358802B8
+CT=96E9E19694DB9931AC09A7B6296FEAA8
+
+I=164
+KEY=9ABEC4725C717368463710CB2D45774DB48ED9A7550216C851DF48251DC2BE80
+IV=96E9E19694DB9931AC09A7B6296FEAA8
+PT=17878FA394B0A290E04D2B6A48751167
+CT=176C9B9B32A539F35BDFB21B38C42134
+
+I=165
+KEY=3CA1E23510949D81242F16DE0E9B2B3AA3E2423C67A72F3B0A00FA3E25069FB4
+IV=176C9B9B32A539F35BDFB21B38C42134
+PT=A61F26474CE5EEE96218061523DE5C77
+CT=06004480169FB7B6D4DBA7453A85E54D
+
+I=166
+KEY=2A72AA0C7EAA3113480EF57A83C272D7A5E206BC7138988DDEDB5D7B1F837AF9
+IV=06004480169FB7B6D4DBA7453A85E54D
+PT=16D348396E3EAC926C21E3A48D5959ED
+CT=FF2F4F6E32133CE8C70252937FE5BDA6
+
+I=167
+KEY=90C0C8FC5B65BE92E643956293A70AF35ACD49D2432BA46519D90FE86066C75F
+IV=FF2F4F6E32133CE8C70252937FE5BDA6
+PT=BAB262F025CF8F81AE4D601810657824
+CT=0972CCC79C412DB6FBC5918B8E6EAB7C
+
+I=168
+KEY=E0AF49BAC4BD146E83C884327FFB682353BF8515DF6A89D3E21C9E63EE086C23
+IV=0972CCC79C412DB6FBC5918B8E6EAB7C
+PT=706F81469FD8AAFC658B1150EC5C62D0
+CT=2D8C668310308FCF7B3E325F50AA89E5
+
+I=169
+KEY=E5C29451893B7B94249E89469E58DEAD7E33E396CF5A061C9922AC3CBEA2E5C6
+IV=2D8C668310308FCF7B3E325F50AA89E5
+PT=056DDDEB4D866FFAA7560D74E1A3B68E
+CT=8342DD95F1040E763C82E36F8F74822F
+
+I=170
+KEY=4A9AD7CAFA46AE63362069120B502D33FD713E033E5E086AA5A04F5331D667E9
+IV=8342DD95F1040E763C82E36F8F74822F
+PT=AF58439B737DD5F712BEE0549508F39E
+CT=8CA83627884D9B7A62F096BD37C14EFF
+
+I=171
+KEY=21AEFC00E7CC2942F319630702ECCC6B71D90824B6139310C750D9EE06172916
+IV=8CA83627884D9B7A62F096BD37C14EFF
+PT=6B342BCA1D8A8721C5390A1509BCE158
+CT=13073AB95C0C0587372564189A4C176F
+
+I=172
+KEY=7E615F002723795F6E37182ECC0C429E62DE329DEA1F9697F075BDF69C5B3E79
+IV=13073AB95C0C0587372564189A4C176F
+PT=5FCFA300C0EF501D9D2E7B29CEE08EF5
+CT=247A01C6A7072F64CB463E6580DA222E
+
+I=173
+KEY=C2A25232803E901B35080B5CA64DEC2646A4335B4D18B9F33B3383931C811C57
+IV=247A01C6A7072F64CB463E6580DA222E
+PT=BCC30D32A71DE9445B3F13726A41AEB8
+CT=562355D078402DA76B0CCAAC2BE63DAE
+
+I=174
+KEY=46C06B83AD1C5CD849C53A11C05137141087668B35589454503F493F376721F9
+IV=562355D078402DA76B0CCAAC2BE63DAE
+PT=846239B12D22CCC37CCD314D661CDB32
+CT=841B1644CCE1BF9DB0D537733047DB7F
+
+I=175
+KEY=CB3AD5FB9E07D380841D712E7A71FC15949C70CFF9B92BC9E0EA7E4C0720FA86
+IV=841B1644CCE1BF9DB0D537733047DB7F
+PT=8DFABE78331B8F58CDD84B3FBA20CB01
+CT=DE34C065627DB86A2D0AE89FB31BDA86
+
+I=176
+KEY=240CFC15D60F6AE4A53D2C25BD71DD6E4AA8B0AA9BC493A3CDE096D3B43B2000
+IV=DE34C065627DB86A2D0AE89FB31BDA86
+PT=EF3629EE4808B96421205D0BC700217B
+CT=38DD744B95756614261178685FBF097F
+
+I=177
+KEY=FAA7CBA4AAAD9576591C12233960F1C87275C4E10EB1F5B7EBF1EEBBEB84297F
+IV=38DD744B95756614261178685FBF097F
+PT=DEAB37B17CA2FF92FC213E0684112CA6
+CT=DC1CF4E4633355111AD09BE1C6BC1E39
+
+I=178
+KEY=29E0D33A81FFDCE220D1587C36C5EB09AE6930056D82A0A6F121755A2D383746
+IV=DC1CF4E4633355111AD09BE1C6BC1E39
+PT=D347189E2B52499479CD4A5F0FA51AC1
+CT=2A5DC4E8C16753D202B638E5003AF83D
+
+I=179
+KEY=956C5751C5B439990A006DB1B52336E78434F4EDACE5F374F3974DBF2D02CF7B
+IV=2A5DC4E8C16753D202B638E5003AF83D
+PT=BC8C846B444BE57B2AD135CD83E6DDEE
+CT=70F5676DC7646EA8F8A913AE6AD21949
+
+I=180
+KEY=8AD9D44BC9018FD05B103360575592FEF4C193806B819DDC0B3E5E1147D0D632
+IV=70F5676DC7646EA8F8A913AE6AD21949
+PT=1FB5831A0CB5B64951105ED1E276A419
+CT=C44DA6A603A1E9C02F18123D5CAD5291
+
+I=181
+KEY=DA77F2DA5CD7148B15FE8CA898C9A25E308C35266820741C24264C2C1B7D84A3
+IV=C44DA6A603A1E9C02F18123D5CAD5291
+PT=50AE269195D69B5B4EEEBFC8CF9C30A0
+CT=53C2D89EC4D5867DC79168D21C9B8755
+
+I=182
+KEY=4A4FD6AED6825A2A0C2114460F029EDA634EEDB8ACF5F261E3B724FE07E603F6
+IV=53C2D89EC4D5867DC79168D21C9B8755
+PT=903824748A554EA119DF98EE97CB3C84
+CT=79B9DABE5171A614CAFDEA11637A1800
+
+I=183
+KEY=29102930967275801BD019D6766FDA1A1AF73706FD845475294ACEEF649C1BF6
+IV=79B9DABE5171A614CAFDEA11637A1800
+PT=635FFF9E40F02FAA17F10D90796D44C0
+CT=8AB92FA5EA50F1185112FE4D8D2FCC21
+
+I=184
+KEY=F4ABA34B232C18EAD6D367320651C374904E18A317D4A56D785830A2E9B3D7D7
+IV=8AB92FA5EA50F1185112FE4D8D2FCC21
+PT=DDBB8A7BB55E6D6ACD037EE4703E196E
+CT=FB97C84040732D7B308C5959059D90A9
+
+I=185
+KEY=FB140F98A79F5D5D68B80301CB7B640E6BD9D0E357A7881648D469FBEC2E477E
+IV=FB97C84040732D7B308C5959059D90A9
+PT=0FBFACD384B345B7BE6B6433CD2AA77A
+CT=D0D0119D500519BF5B4770C494B41680
+
+I=186
+KEY=BC98221C0792D22B6EB258E57DB0D8B0BB09C17E07A291A91393193F789A51FE
+IV=D0D0119D500519BF5B4770C494B41680
+PT=478C2D84A00D8F76060A5BE4B6CBBCBE
+CT=94842399FC93828D30979DAD9210B827
+
+I=187
+KEY=C92F345AC3CB803EA91C123F97E7005A2F8DE2E7FB31132423048492EA8AE9D9
+IV=94842399FC93828D30979DAD9210B827
+PT=75B71646C4595215C7AE4ADAEA57D8EA
+CT=5BDB886E7A7DBBA8679704F13F44B981
+
+I=188
+KEY=3EACAF51FEA9A9886D0B9D1B6BA8436574566A89814CA88C44938063D5CE5058
+IV=5BDB886E7A7DBBA8679704F13F44B981
+PT=F7839B0B3D6229B6C4178F24FC4F433F
+CT=A2DA893257EE0F732A80FC52887A0788
+
+I=189
+KEY=72E26FEDC250C5FED59FE29C966B61FAD68CE3BBD6A2A7FF6E137C315DB457D0
+IV=A2DA893257EE0F732A80FC52887A0788
+PT=4C4EC0BC3CF96C76B8947F87FDC3229F
+CT=2F7877481B1162B01616C9F3268B4C44
+
+I=190
+KEY=901C1268AD3582E6A9FA4C5CBB99D07EF9F494F3CDB3C54F7805B5C27B3F1B94
+IV=2F7877481B1162B01616C9F3268B4C44
+PT=E2FE7D856F6547187C65AEC02DF2B184
+CT=9FFA4AF8D0F096CC40A9F879076211E0
+
+I=191
+KEY=EAF814EC49F2254E4933FAF977D7BEEC660EDE0B1D43538338AC4DBB7C5D0A74
+IV=9FFA4AF8D0F096CC40A9F879076211E0
+PT=7AE40684E4C7A7A8E0C9B6A5CC4E6E92
+CT=886097F5BC20C157A605CBEFCA5663D7
+
+I=192
+KEY=8ED70BBA192093A0C9AD62E86C27091FEE6E49FEA16392D49EA98654B60B69A3
+IV=886097F5BC20C157A605CBEFCA5663D7
+PT=642F1F5650D2B6EE809E98111BF0B7F3
+CT=00DBBB84F52B3C9B28325161072753B6
+
+I=193
+KEY=18280464C9E683CFFF9B75A5FD74EE96EEB5F27A5448AE4FB69BD735B12C3A15
+IV=00DBBB84F52B3C9B28325161072753B6
+PT=96FF0FDED0C6106F3636174D9153E789
+CT=714A27832B326F0A8FA745012DE4D936
+
+I=194
+KEY=F464EE1298B09059016082CCC5ABC0129FFFD5F97F7AC145393C92349CC8E323
+IV=714A27832B326F0A8FA745012DE4D936
+PT=EC4CEA7651561396FEFBF76938DF2E84
+CT=5DE8A5CDBA7A6111A646AA17CA5324D4
+
+I=195
+KEY=EE7301D63C482593ABB33CF4A57F1101C2177034C500A0549F7A3823569BC7F7
+IV=5DE8A5CDBA7A6111A646AA17CA5324D4
+PT=1A17EFC4A4F8B5CAAAD3BE3860D4D113
+CT=EA197ECF36E63616EBB0D9D7C1BD9A22
+
+I=196
+KEY=10528506D50D143EAC40D83731DD55F0280E0EFBF3E6964274CAE1F497265DD5
+IV=EA197ECF36E63616EBB0D9D7C1BD9A22
+PT=FE2184D0E94531AD07F3E4C394A244F1
+CT=798349D56EC37993B0E131F8E3F64860
+
+I=197
+KEY=438E1B672254504B972927644802ED36518D472E9D25EFD1C42BD00C74D015B5
+IV=798349D56EC37993B0E131F8E3F64860
+PT=53DC9E61F75944753B69FF5379DFB8C6
+CT=545E4CD72E74F5A91B29DDBA60BCEB5A
+
+I=198
+KEY=7E32F16A4E2E125A95FF9963C6F9796105D30BF9B3511A78DF020DB6146CFEEF
+IV=545E4CD72E74F5A91B29DDBA60BCEB5A
+PT=3DBCEA0D6C7A421102D6BE078EFB9457
+CT=084142F2C892DCF8A37A509DF0D669BC
+
+I=199
+KEY=B1BEC1C124A0941D0BA6C75239C17E250D92490B7BC3C6807C785D2BE4BA9753
+IV=084142F2C892DCF8A37A509DF0D669BC
+PT=CF8C30AB6A8E86479E595E31FF380744
+CT=0A96C326C9D642F1F84C8772BCF8EB4A
+
+I=200
+KEY=80D7A5A2AE29B42143046D45B6B6B36C07048A2DB21584718434DA5958427C19
+IV=0A96C326C9D642F1F84C8772BCF8EB4A
+PT=316964638A89203C48A2AA178F77CD49
+CT=273916ED09A517CE5C6A294D82E78980
+
+I=201
+KEY=4D1C892DF27868BBB0FE803145C1D731203D9CC0BBB093BFD85EF314DAA5F599
+IV=273916ED09A517CE5C6A294D82E78980
+PT=CDCB2C8F5C51DC9AF3FAED74F377645D
+CT=7183A7C83964ECFB2A1E44FFCFEBB7C1
+
+I=202
+KEY=8C9B28041ECD5149A51207ACE38F0D0351BE3B0882D47F44F240B7EB154E4258
+IV=7183A7C83964ECFB2A1E44FFCFEBB7C1
+PT=C187A129ECB539F215EC879DA64EDA32
+CT=6015DF395D795DECA0A2F833E3614000
+
+I=203
+KEY=FF175C7C745BB06E51EEDAA4F2C61E0F31ABE431DFAD22A852E24FD8F62F0258
+IV=6015DF395D795DECA0A2F833E3614000
+PT=738C74786A96E127F4FCDD081149130C
+CT=B6B466B56B0E994E672072C273BA067D
+
+I=204
+KEY=0C84C64E1BB3B86E9AF5A8405D950B3A871F8284B4A3BBE635C23D1A85950425
+IV=B6B466B56B0E994E672072C273BA067D
+PT=F3939A326FE80800CB1B72E4AF531535
+CT=C8566E37DF2E2958DDD5D2DB49889BA8
+
+I=205
+KEY=5FF4C2A08B85338172D2779BF789DA234F49ECB36B8D92BEE817EFC1CC1D9F8D
+IV=C8566E37DF2E2958DDD5D2DB49889BA8
+PT=537004EE90368BEFE827DFDBAA1CD119
+CT=C4A8D14DB86637E94AF515764BC7DF44
+
+I=206
+KEY=BD81DE1813AEC9BAFDDC90E4A563CB338BE13DFED3EBA557A2E2FAB787DA40C9
+IV=C4A8D14DB86637E94AF515764BC7DF44
+PT=E2751CB8982BFA3B8F0EE77F52EA1110
+CT=5707495E4CBA3727FBA5D7F4F61AF35C
+
+I=207
+KEY=AE1B09CB7D99BAC0A71B3E83815F10A2DCE674A09F51927059472D4371C0B395
+IV=5707495E4CBA3727FBA5D7F4F61AF35C
+PT=139AD7D36E37737A5AC7AE67243CDB91
+CT=C770CD182DFF66E4D6A7BFEFE2820AE1
+
+I=208
+KEY=4F7491F03447293C42DE8393E7AD91741B96B9B8B2AEF4948FE092AC9342B974
+IV=C770CD182DFF66E4D6A7BFEFE2820AE1
+PT=E16F983B49DE93FCE5C5BD1066F281D6
+CT=E2044134ACD21D5AD026671BDC0CB2E4
+
+I=209
+KEY=A747EF80608CED4309800CA0B1C73081F992F88C1E7CE9CE5FC6F5B74F4E0B90
+IV=E2044134ACD21D5AD026671BDC0CB2E4
+PT=E8337E7054CBC47F4B5E8F33566AA1F5
+CT=303CF7780126AD06B5272A8350639C93
+
+I=210
+KEY=E5EBF5E471F2CA9F38492F604438B9C0C9AE0FF41F5A44C8EAE1DF341F2D9703
+IV=303CF7780126AD06B5272A8350639C93
+PT=42AC1A64117E27DC31C923C0F5FF8941
+CT=DACCD42953603A1321CAD9C236454598
+
+I=211
+KEY=B5E5C9211A5C43F2267B4A2411FC2CC21362DBDD4C3A7EDBCB2B06F62968D29B
+IV=DACCD42953603A1321CAD9C236454598
+PT=500E3CC56BAE896D1E32654455C49502
+CT=F9AB4D1D8255E83B330031EBE2ECE5C6
+
+I=212
+KEY=8D78453D63A2DD8D08BF5F250F2581CFEAC996C0CE6F96E0F82B371DCB84375D
+IV=F9AB4D1D8255E83B330031EBE2ECE5C6
+PT=389D8C1C79FE9E7F2EC415011ED9AD0D
+CT=0F28E2D4CC948D36E18F80184A594841
+
+I=213
+KEY=2E921775036404FD9939EE83C9585481E5E1741402FB1BD619A4B70581DD7F1C
+IV=0F28E2D4CC948D36E18F80184A594841
+PT=A3EA524860C6D9709186B1A6C67DD54E
+CT=A4756EAB45BCF716A52038C729E420C6
+
+I=214
+KEY=9F86FEF42701B1D779BD46BE515680FC41941ABF4747ECC0BC848FC2A8395FDA
+IV=A4756EAB45BCF716A52038C729E420C6
+PT=B114E9812465B52AE084A83D980ED47D
+CT=9834425E009006673E777E3552E83D20
+
+I=215
+KEY=2212046FFD03BA552089FBF7B2F3EF32D9A058E147D7EAA782F3F1F7FAD162FA
+IV=9834425E009006673E777E3552E83D20
+PT=BD94FA9BDA020B825934BD49E3A56FCE
+CT=AEA572D530A3694EAFF6DFDE30B80D5A
+
+I=216
+KEY=F73BB21F916D8011751AFDDDCD130A6477052A34777483E92D052E29CA696FA0
+IV=AEA572D530A3694EAFF6DFDE30B80D5A
+PT=D529B6706C6E3A445593062A7FE0E556
+CT=86394E06B621147758CAB012852035A6
+
+I=217
+KEY=EE44A367A3CDDFED7DBD980BF731B4E5F13C6432C155979E75CF9E3B4F495A06
+IV=86394E06B621147758CAB012852035A6
+PT=197F117832A05FFC08A765D63A22BE81
+CT=3CBC18C1AC02C0A7595199E08F1F552B
+
+I=218
+KEY=1558BABB3DCD830F693E7950F736BCADCD807CF36D5757392C9E07DBC0560F2D
+IV=3CBC18C1AC02C0A7595199E08F1F552B
+PT=FB1C19DC9E005CE21483E15B00070848
+CT=5A9CFD8BFE10CF7FBD0F9A3FAF6C117B
+
+I=219
+KEY=D083F58141F5E5AF3D5479739D55780D971C81789347984691919DE46F3A1E56
+IV=5A9CFD8BFE10CF7FBD0F9A3FAF6C117B
+PT=C5DB4F3A7C3866A0546A00236A63C4A0
+CT=61A437D4E2F1C3779F1EBE906C5D2C12
+
+I=220
+KEY=C60824F2DDC67623D270974E9F87BD27F6B8B6AC71B65B310E8F237403673244
+IV=61A437D4E2F1C3779F1EBE906C5D2C12
+PT=168BD1739C33938CEF24EE3D02D2C52A
+CT=FC675EE1B12B47410A20CFAC23FD20EE
+
+I=221
+KEY=F73A715AD84DB0A6F55AD584922001920ADFE84DC09D1C7004AFECD8209A12AA
+IV=FC675EE1B12B47410A20CFAC23FD20EE
+PT=313255A8058BC685272A42CA0DA7BCB5
+CT=82E3FB6189716D94C8E9D30E1ECCABC4
+
+I=222
+KEY=6ABBDCE21E2ECECBCAA3473897A2E178883C132C49EC71E4CC463FD63E56B96E
+IV=82E3FB6189716D94C8E9D30E1ECCABC4
+PT=9D81ADB8C6637E6D3FF992BC0582E0EA
+CT=BD84DCE4994B505EED71596B454BDF85
+
+I=223
+KEY=0D4F68CDB9B53B08E22DDDFE4FD5FCC035B8CFC8D0A721BA213766BD7B1D66EB
+IV=BD84DCE4994B505EED71596B454BDF85
+PT=67F4B42FA79BF5C3288E9AC6D8771DB8
+CT=1B3AA490C6E874BA77CE55D71789616C
+
+I=224
+KEY=3D8E3121698DD7E9D1835EFF5FA02DB22E826B58164F550056F9336A6C940787
+IV=1B3AA490C6E874BA77CE55D71789616C
+PT=30C159ECD038ECE133AE83011075D172
+CT=D6EE171B39B5E40535FBF5A7CB4C6953
+
+I=225
+KEY=1A5B2249CA785F0DB58FF5B07CCCFCDEF86C7C432FFAB1056302C6CDA7D86ED4
+IV=D6EE171B39B5E40535FBF5A7CB4C6953
+PT=27D51368A3F588E4640CAB4F236CD16C
+CT=8691BE10D13B4C08246938750EE33643
+
+I=226
+KEY=48AD5DEF217F83DC5039ECD1191ABE3A7EFDC253FEC1FD0D476BFEB8A93B5897
+IV=8691BE10D13B4C08246938750EE33643
+PT=52F67FA6EB07DCD1E5B6196165D642E4
+CT=E40AD0EE818639E37349E1132B138D63
+
+I=227
+KEY=FEB84B0B264A8A6FB8D4DE065DA68A479AF712BD7F47C4EE34221FAB8228D5F4
+IV=E40AD0EE818639E37349E1132B138D63
+PT=B61516E4073509B3E8ED32D744BC347D
+CT=6E40A22767A39C978F279D40B447099D
+
+I=228
+KEY=2FE79FCC3C959901BAAEE8C55B71D01FF4B7B09A18E45879BB0582EB366FDC69
+IV=6E40A22767A39C978F279D40B447099D
+PT=D15FD4C71ADF136E027A36C306D75A58
+CT=C2DE8C5200F6FCBF1A4D6178909DF110
+
+I=229
+KEY=C3EB1424EFD0ACDF3670C4943CB2CF5936693CC81812A4C6A148E393A6F22D79
+IV=C2DE8C5200F6FCBF1A4D6178909DF110
+PT=EC0C8BE8D34535DE8CDE2C5167C31F46
+CT=104CBECB1134CAE09B2FE8C5CE2E0901
+
+I=230
+KEY=DF9F70702DA816906F3907575DF4D3032625820309266E263A670B5668DC2478
+IV=104CBECB1134CAE09B2FE8C5CE2E0901
+PT=1C746454C278BA4F5949C3C361461C5A
+CT=65287F66F01AC054B1051D700EDDBF2B
+
+I=231
+KEY=F6C4CE3006A43EFBE18C5FF305F32C37430DFD65F93CAE728B62162666019B53
+IV=65287F66F01AC054B1051D700EDDBF2B
+PT=295BBE402B0C286B8EB558A45807FF34
+CT=4933D44FD414225CB1E6951240D28150
+
+I=232
+KEY=3963CE7465D89FBE550649326262DB450A3E292A2D288C2E3A84833426D31A03
+IV=4933D44FD414225CB1E6951240D28150
+PT=CFA70044637CA145B48A16C16791F772
+CT=3733351F76DE0E07581F84600E38EFDD
+
+I=233
+KEY=42468662273D8CB3EFAB19DBC802888B3D0D1C355BF68229629B075428EBF5DE
+IV=3733351F76DE0E07581F84600E38EFDD
+PT=7B25481642E5130DBAAD50E9AA6053CE
+CT=F16F22EB9CCD854591AE2FC28E1D4B59
+
+I=234
+KEY=E2B3E5EA6573FC8ABE4E890FA4F5502DCC623EDEC73B076CF3352896A6F6BE87
+IV=F16F22EB9CCD854591AE2FC28E1D4B59
+PT=A0F56388424E703951E590D46CF7D8A6
+CT=1D607C6E9BAD454DD5DE785F2A78F990
+
+I=235
+KEY=FDB55AF96E09AF677AA4737992E13C9ED10242B05C96422126EB50C98C8E4717
+IV=1D607C6E9BAD454DD5DE785F2A78F990
+PT=1F06BF130B7A53EDC4EAFA7636146CB3
+CT=7B16B6A8F88E05F6A9A036A67CB8A2B6
+
+I=236
+KEY=E546D74518CF4AA64B399EA321C570CAAA14F418A41847D78F4B666FF036E5A1
+IV=7B16B6A8F88E05F6A9A036A67CB8A2B6
+PT=18F38DBC76C6E5C1319DEDDAB3244C54
+CT=63AD66FCF9D52195CD0339443F554311
+
+I=237
+KEY=2F9B91A24BEF0E503DC576E4F8D32C16C9B992E45DCD664242485F2BCF63A6B0
+IV=63AD66FCF9D52195CD0339443F554311
+PT=CADD46E7532044F676FCE847D9165CDC
+CT=6293FBB897D8F0C60171BEA3072CA512
+
+I=238
+KEY=97B7DF112EFFE9279D5EDF932889D84BAB2A695CCA1596844339E188C84F03A2
+IV=6293FBB897D8F0C60171BEA3072CA512
+PT=B82C4EB36510E777A09BA977D05AF45D
+CT=9555D7F244448C80E965CE6AB7EF0F7B
+
+I=239
+KEY=39F26B429FE4111DAA984F03112B339F3E7FBEAE8E511A04AA5C2FE27FA00CD9
+IV=9555D7F244448C80E965CE6AB7EF0F7B
+PT=AE45B453B11BF83A37C6909039A2EBD4
+CT=FA242C9DB2984E9EFA8CD98AE7C29D6F
+
+I=240
+KEY=64C6D001CB3C8AFC24A72DA11D172727C45B92333CC9549A50D0F668986291B6
+IV=FA242C9DB2984E9EFA8CD98AE7C29D6F
+PT=5D34BB4354D89BE18E3F62A20C3C14B8
+CT=2998B59B0441F068D7F3FCE7AEAA6FD9
+
+I=241
+KEY=FE56E2EB2434CA49D46A684DBCE2426CEDC327A83888A4F287230A8F36C8FE6F
+IV=2998B59B0441F068D7F3FCE7AEAA6FD9
+PT=9A9032EAEF0840B5F0CD45ECA1F5654B
+CT=A3F77BBA27BA88F33D4330EB2CC0EFBA
+
+I=242
+KEY=0F9B3CAD0EDFA9C429F3A005C78FE9F84E345C121F322C01BA603A641A0811D5
+IV=A3F77BBA27BA88F33D4330EB2CC0EFBA
+PT=F1CDDE462AEB638DFD99C8487B6DAB94
+CT=9C751C64BCB82229ABA5130353455CCB
+
+I=243
+KEY=1725A4C019FB909FB1DE2ACA00E9A33DD2414076A38A0E2811C52967494D4D1E
+IV=9C751C64BCB82229ABA5130353455CCB
+PT=18BE986D1724395B982D8ACFC7664AC5
+CT=540DE482B7170E925FA4B429F6BCD458
+
+I=244
+KEY=E2A619367235AA4611A72FD4FAF68FB3864CA4F4149D00BA4E619D4EBFF19946
+IV=540DE482B7170E925FA4B429F6BCD458
+PT=F583BDF66BCE3AD9A079051EFA1F2C8E
+CT=6AADE1E1A12F5C83AF434CAD95B29678
+
+I=245
+KEY=8629FB2CC8C06A07EC910681499E917FECE14515B5B25C39E122D1E32A430F3E
+IV=6AADE1E1A12F5C83AF434CAD95B29678
+PT=648FE21ABAF5C041FD362955B3681ECC
+CT=11308758A1C2075FEAECD260867CA343
+
+I=246
+KEY=5EDD76C395D2A0D3D547CFB394B439EAFDD1C24D14705B660BCE0383AC3FAC7D
+IV=11308758A1C2075FEAECD260867CA343
+PT=D8F48DEF5D12CAD439D6C932DD2AA895
+CT=14C9A904A3909A8FF44D88E22F8626DF
+
+I=247
+KEY=AF3FA8D6034564D7151C3933C7986CFCE9186B49B7E0C1E9FF838B6183B98AA2
+IV=14C9A904A3909A8FF44D88E22F8626DF
+PT=F1E2DE159697C404C05BF680532C5516
+CT=A042D7F391A37E5A3EDB3022400EC797
+
+I=248
+KEY=8ACC720216DBDBDB4C213FE65E575A09495ABCBA2643BFB3C158BB43C3B74D35
+IV=A042D7F391A37E5A3EDB3022400EC797
+PT=25F3DAD4159EBF0C593D06D599CF36F5
+CT=439FEF326223A65F7A555C6231178190
+
+I=249
+KEY=F2882A52603203A71895A5870CCF7EE40AC55388446019ECBB0DE721F2A0CCA5
+IV=439FEF326223A65F7A555C6231178190
+PT=7844585076E9D87C54B49A61529824ED
+CT=6FE1286C19AA3BC802F1C6C7B58DB4C4
+
+I=250
+KEY=57EFB10BFC21E28397A9D5E5A533D35B65247BE45DCA2224B9FC21E6472D7861
+IV=6FE1286C19AA3BC802F1C6C7B58DB4C4
+PT=A5679B599C13E1248F3C7062A9FCADBF
+CT=C38D763981392FF038573CA341DD8EA1
+
+I=251
+KEY=19328A5147BC2E7C5149DA257487D734A6A90DDDDCF30DD481AB1D4506F0F6C0
+IV=C38D763981392FF038573CA341DD8EA1
+PT=4EDD3B5ABB9DCCFFC6E00FC0D1B4046F
+CT=5FD553A2848C683B138D50F2741B124D
+
+I=252
+KEY=ED66DE43FE0F966850EF6754E21B69A0F97C5E7F587F65EF92264DB772EBE48D
+IV=5FD553A2848C683B138D50F2741B124D
+PT=F4545412B9B3B81401A6BD71969CBE94
+CT=910CDCBE38068A51185A879FF2B45B9C
+
+I=253
+KEY=E53D9016DE7DF4E2377968864B6F69F8687082C16079EFBE8A7CCA28805FBF11
+IV=910CDCBE38068A51185A879FF2B45B9C
+PT=085B4E552072628A67960FD2A9740058
+CT=E0A0E68A14893501D75BC42B8EFC6F96
+
+I=254
+KEY=C88C4383E2D16541765E5DB85957C59188D0644B74F0DABF5D270E030EA3D087
+IV=E0A0E68A14893501D75BC42B8EFC6F96
+PT=2DB1D3953CAC91A34127353E1238AC69
+CT=A66DD21DA627347F962A0AB7DCA887ED
+
+I=255
+KEY=6F01CC5C22DE71C7C2D5B429AA756A392EBDB656D2D7EEC0CB0D04B4D20B576A
+IV=A66DD21DA627347F962A0AB7DCA887ED
+PT=A78D8FDFC00F1486B48BE991F322AFA8
+CT=87551BC7A6B6D9B76239CB8A31FF1993
+
+I=256
+KEY=DAC405506CD3779FC2400B459B7C6B6EA9E8AD9174613777A934CF3EE3F44EF9
+IV=87551BC7A6B6D9B76239CB8A31FF1993
+PT=B5C5C90C4E0D06580095BF6C31090157
+CT=B909B206A041F33EB3AC7ED481DFBA21
+
+I=257
+KEY=E482333E6FBAA8427A2E30D56069E0B810E11F97D420C4491A98B1EA622BF4D8
+IV=B909B206A041F33EB3AC7ED481DFBA21
+PT=3E46366E0369DFDDB86E3B90FB158BD6
+CT=DE5E71F446794D3402400C96FBFEB93F
+
+I=258
+KEY=176CAD69CD20690B95DA40B95C43AC54CEBF6E639259897D18D8BD7C99D54DE7
+IV=DE5E71F446794D3402400C96FBFEB93F
+PT=F3EE9E57A29AC149EFF4706C3C2A4CEC
+CT=175A7C580A99E985A2FD2F185D9BAADB
+
+I=259
+KEY=FA4DD79A64960C8264624CDF215B54A1D9E5123B98C060F8BA259264C44EE73C
+IV=175A7C580A99E985A2FD2F185D9BAADB
+PT=ED217AF3A9B66589F1B80C667D18F8F5
+CT=413EB5D166C1D196F0239FF34D184013
+
+I=260
+KEY=49855C1008EAF59432518A9F3807A0B398DBA7EAFE01B16E4A060D978956A72F
+IV=413EB5D166C1D196F0239FF34D184013
+PT=B3C88B8A6C7CF9165633C640195CF412
+CT=69A3A63C580336296FF826600C754747
+
+I=261
+KEY=849D231AE9F90F233F328BE6EE0AC180F17801D6A602874725FE2BF78523E068
+IV=69A3A63C580336296FF826600C754747
+PT=CD187F0AE113FAB70D630179D60D6133
+CT=B9AF0CA2B502C2DEB66834BD729AA528
+
+I=262
+KEY=40E3F7EA3E7CFBDBF57935DBB124CF7F48D70D741300459993961F4AF7B94540
+IV=B9AF0CA2B502C2DEB66834BD729AA528
+PT=C47ED4F0D785F4F8CA4BBE3D5F2E0EFF
+CT=99E16968796AB521FC460A8DF6744FA8
+
+I=263
+KEY=4FDF8D16B85E527490FBE95EA34138D6D136641C6A6AF0B86FD015C701CD0AE8
+IV=99E16968796AB521FC460A8DF6744FA8
+PT=0F3C7AFC8622A9AF6582DC851265F7A9
+CT=7B871B0153657949D1FE7259E16791B7
+
+I=264
+KEY=6AD7099EA6DC50F5CC836C3EB934CF92AAB17F1D390F89F1BE2E679EE0AA9B5F
+IV=7B871B0153657949D1FE7259E16791B7
+PT=250884881E8202815C7885601A75F744
+CT=8D6B80EAC01BF7E204A79DD14BFDB71A
+
+I=265
+KEY=0860DD776AD2014ED90D0837A5A298B627DAFFF7F9147E13BA89FA4FAB572C45
+IV=8D6B80EAC01BF7E204A79DD14BFDB71A
+PT=62B7D4E9CC0E51BB158E64091C965724
+CT=DAD6A83408559AD3003C6995DC099303
+
+I=266
+KEY=9E8757199D96CA08B9C3CEF817E902B8FD0C57C3F141E4C0BAB593DA775EBF46
+IV=DAD6A83408559AD3003C6995DC099303
+PT=96E78A6EF744CB4660CEC6CFB24B9A0E
+CT=AA6EF32AFC8AA6ADCDE86D86CC59AFB4
+
+I=267
+KEY=483AD9696154B929F35016B648F5952B5762A4E90DCB426D775DFE5CBB0710F2
+IV=AA6EF32AFC8AA6ADCDE86D86CC59AFB4
+PT=D6BD8E70FCC273214A93D84E5F1C9793
+CT=713F9516A55FBFA4AE8155EC12A3AB5D
+
+I=268
+KEY=027B7F5F83B26099A4CE8FCC1AB84529265D31FFA894FDC9D9DCABB0A9A4BBAF
+IV=713F9516A55FBFA4AE8155EC12A3AB5D
+PT=4A41A636E2E6D9B0579E997A524DD002
+CT=B2E4BEAF6DB84214E379B89697191379
+
+I=269
+KEY=D7AEFAD28855BB04A9604527F8376CAF94B98F50C52CBFDD3AA513263EBDA8D6
+IV=B2E4BEAF6DB84214E379B89697191379
+PT=D5D5858D0BE7DB9D0DAECAEBE28F2986
+CT=9FE3B8941D9F85B1400CC45B7BDE8E9F
+
+I=270
+KEY=B5EBE7CB901F69E61EC6F011E6A46A2E0B5A37C4D8B33A6C7AA9D77D45632649
+IV=9FE3B8941D9F85B1400CC45B7BDE8E9F
+PT=62451D19184AD2E2B7A6B5361E930681
+CT=E9ABFC5563B4AD1718EF4A91F7D60913
+
+I=271
+KEY=571805B63BC20F5784AF56FDB71CBCD7E2F1CB91BB07977B62469DECB2B52F5A
+IV=E9ABFC5563B4AD1718EF4A91F7D60913
+PT=E2F3E27DABDD66B19A69A6EC51B8D6F9
+CT=D825DC1C8C73A84BDFEFD9799D9E3960
+
+I=272
+KEY=9EED79D9ABB11094FB4475ED2EC042133AD4178D37743F30BDA944952F2B163A
+IV=D825DC1C8C73A84BDFEFD9799D9E3960
+PT=C9F57C6F90731FC37FEB231099DCFEC4
+CT=7D0DC4C31259FD0A46D2D2282F1FE22E
+
+I=273
+KEY=EF905E20846E064A3B3281FD2BD59AB647D9D34E252DC23AFB7B96BD0034F414
+IV=7D0DC4C31259FD0A46D2D2282F1FE22E
+PT=717D27F92FDF16DEC076F4100515D8A5
+CT=93FAFC16EFF504A9D2B791A272A78135
+
+I=274
+KEY=8F219C67ACF0F1C745FA0ABBADE96015D4232F58CAD8C69329CC071F72937521
+IV=93FAFC16EFF504A9D2B791A272A78135
+PT=60B1C247289EF78D7EC88B46863CFAA3
+CT=EF387517F8C781A79700C8196DCA6F1A
+
+I=275
+KEY=48C6408FD8FA84D30DD53B83B31C425D3B1B5A4F321F4734BECCCF061F591A3B
+IV=EF387517F8C781A79700C8196DCA6F1A
+PT=C7E7DCE8740A7514482F31381EF52248
+CT=A6166002C7239645D55494BB64840B26
+
+I=276
+KEY=1C9EB0648715CA5738A4FD27A63693A09D0D3A4DF53CD1716B985BBD7BDD111D
+IV=A6166002C7239645D55494BB64840B26
+PT=5458F0EB5FEF4E843571C6A4152AD1FD
+CT=FB35646B2008AD29AFF508B94179F223
+
+I=277
+KEY=4AA2E4BAC74E8CD9AEA969550D27877866385E26D5347C58C46D53043AA4E33E
+IV=FB35646B2008AD29AFF508B94179F223
+PT=563C54DE405B468E960D9472AB1114D8
+CT=59C1692D4598AD622B6586A06892E11D
+
+I=278
+KEY=B9F5A3BAAA0C2F6EA5E835F6E6E5D50E3FF9370B90ACD13AEF08D5A452360223
+IV=59C1692D4598AD622B6586A06892E11D
+PT=F35747006D42A3B70B415CA3EBC25276
+CT=3131E251A6A4AC7226A1809553198AB8
+
+I=279
+KEY=EF46814F8656D3D8ABAF3B08EFEBC3150EC8D55A36087D48C9A95531012F889B
+IV=3131E251A6A4AC7226A1809553198AB8
+PT=56B322F52C5AFCB60E470EFE090E161B
+CT=2E30D8D5B7B636307A6D354FBED41A2D
+
+I=280
+KEY=3DFBE0FE20F0421CAABD62E2CDB0E60F20F80D8F81BE4B78B3C4607EBFFB92B6
+IV=2E30D8D5B7B636307A6D354FBED41A2D
+PT=D2BD61B1A6A691C4011259EA225B251A
+CT=6D791952F9416FC09B78517A2FFE986F
+
+I=281
+KEY=5197CF05753D155C5B08A5EB51B82F2D4D8114DD78FF24B828BC310490050AD9
+IV=6D791952F9416FC09B78517A2FFE986F
+PT=6C6C2FFB55CD5740F1B5C7099C08C922
+CT=37A8E0B9375AD5669A396D980D68D0F3
+
+I=282
+KEY=B3EFE2F914264AAAB7C7FD9C4843619E7A29F4644FA5F1DEB2855C9C9D6DDA2A
+IV=37A8E0B9375AD5669A396D980D68D0F3
+PT=E2782DFC611B5FF6ECCF587719FB4EB3
+CT=BC65630DB71EE8DA2194E5DFBC48360E
+
+I=283
+KEY=CAAB7758FF4AFF39A98C2202A26165CFC64C9769F8BB19049311B9432125EC24
+IV=BC65630DB71EE8DA2194E5DFBC48360E
+PT=794495A1EB6CB5931E4BDF9EEA220451
+CT=9C47136C1B510BFCEFA7F6659BDA08C2
+
+I=284
+KEY=CC38852E17544DB004372C4A3AA3DFDB5A0B8405E3EA12F87CB64F26BAFFE4E6
+IV=9C47136C1B510BFCEFA7F6659BDA08C2
+PT=0693F276E81EB289ADBB0E4898C2BA14
+CT=68AC57D13EC53C250FEBFC64B1992B1C
+
+I=285
+KEY=108FE55553F353DFABD421E15A18C9F532A7D3D4DD2F2EDD735DB3420B66CFFA
+IV=68AC57D13EC53C250FEBFC64B1992B1C
+PT=DCB7607B44A71E6FAFE30DAB60BB162E
+CT=9A8C11E031E57B77138A3637784D1D71
+
+I=286
+KEY=C432EA6E854DE8C191C6F0ED4A2BF1D7A82BC234ECCA55AA60D78575732BD28B
+IV=9A8C11E031E57B77138A3637784D1D71
+PT=D4BD0F3BD6BEBB1E3A12D10C10333822
+CT=3BBB1E76A491A5AA145ED931BB886333
+
+I=287
+KEY=980941D5FEFD458061B1B443E39818299390DC42485BF00074895C44C8A3B1B8
+IV=3BBB1E76A491A5AA145ED931BB886333
+PT=5C3BABBB7BB0AD41F07744AEA9B3E9FE
+CT=F79F1B46F57BDD36B58DDA33619D3920
+
+I=288
+KEY=B4FF33FB094612B6A3438A285C3AEA41640FC704BD202D36C1048677A93E8898
+IV=F79F1B46F57BDD36B58DDA33619D3920
+PT=2CF6722EF7BB5736C2F23E6BBFA2F268
+CT=F1C3ED72D0B6D917DD6F8AE86CFD8CBF
+
+I=289
+KEY=BC81027596771F9C591BE6C61762B1E795CC2A766D96F4211C6B0C9FC5C30427
+IV=F1C3ED72D0B6D917DD6F8AE86CFD8CBF
+PT=087E318E9F310D2AFA586CEE4B585BA6
+CT=EAF1AACEEB9F9BE0E880911BFEEAC2AC
+
+I=290
+KEY=D41458000DDED43B83DAA81B1D7FFB597F3D80B886096FC1F4EB9D843B29C68B
+IV=EAF1AACEEB9F9BE0E880911BFEEAC2AC
+PT=68955A759BA9CBA7DAC14EDD0A1D4ABE
+CT=7B35179E67E9B40346F7DE6356EDC98F
+
+I=291
+KEY=FACDC2B3BA9E125B2A734DE75F99F48C04089726E1E0DBC2B21C43E76DC40F04
+IV=7B35179E67E9B40346F7DE6356EDC98F
+PT=2ED99AB3B740C660A9A9E5FC42E60FD5
+CT=0EDE849D7E56B296B12C1EDF37436A8D
+
+I=292
+KEY=E73022253439EB4464CE0B205BBB0F1F0AD613BB9FB6695403305D385A876589
+IV=0EDE849D7E56B296B12C1EDF37436A8D
+PT=1DFDE0968EA7F91F4EBD46C70422FB93
+CT=D02F1EAF3CF6A6B681BAF8ECB921FFC4
+
+I=293
+KEY=9F3671205266DC4F7C771EBA74265F36DAF90D14A340CFE2828AA5D4E3A69A4D
+IV=D02F1EAF3CF6A6B681BAF8ECB921FFC4
+PT=78065305665F370B18B9159A2F9D5029
+CT=E365BE1A125C6930DFDCBB33E6937EC5
+
+I=294
+KEY=111A3E012C9D5CB2967E8BD22907D6F7399CB30EB11CA6D25D561EE70535E488
+IV=E365BE1A125C6930DFDCBB33E6937EC5
+PT=8E2C4F217EFB80FDEA0995685D2189C1
+CT=C5B24EEC5CDD17AA56838B09EC4AB725
+
+I=295
+KEY=15DA3EE4EE9A560B05493FFC971713A5FC2EFDE2EDC1B1780BD595EEE97F53AD
+IV=C5B24EEC5CDD17AA56838B09EC4AB725
+PT=04C000E5C2070AB99337B42EBE10C552
+CT=4D8A43CD28BBCB86953FA55A409BF130
+
+I=296
+KEY=2C8B30484D954192818342F3766C1415B1A4BE2FC57A7AFE9EEA30B4A9E4A29D
+IV=4D8A43CD28BBCB86953FA55A409BF130
+PT=39510EACA30F179984CA7D0FE17B07B0
+CT=A524A6329E6DCE041F72459234ECDE78
+
+I=297
+KEY=0F162BAD5F298EE0B0164CFED6A7AC271480181D5B17B4FA819875269D087CE5
+IV=A524A6329E6DCE041F72459234ECDE78
+PT=239D1BE512BCCF7231950E0DA0CBB832
+CT=90BBC5130D1C06182F737FE7F0FCD00D
+
+I=298
+KEY=62744CA02B6684D05A91F2049D403480843BDD0E560BB2E2AEEB0AC16DF4ACE8
+IV=90BBC5130D1C06182F737FE7F0FCD00D
+PT=6D62670D744F0A30EA87BEFA4BE798A7
+CT=35F293EDDEC8D9446A4ACD34602839B5
+
+I=299
+KEY=21F5373DA5D6BF15BC163383F62EA92FB1C94EE388C36BA6C4A1C7F50DDC955D
+IV=35F293EDDEC8D9446A4ACD34602839B5
+PT=43817B9D8EB03BC5E687C1876B6E9DAF
+CT=E45CF478D7C84325143165F58B041A13
+
+I=300
+KEY=4CF4A508B4DF37A831916353620DC1F45595BA9B5F0B2883D090A20086D88F4E
+IV=E45CF478D7C84325143165F58B041A13
+PT=6D019235110988BD8D8750D0942368DB
+CT=964983C30745D7EEA1BD5E287DAC466C
+
+I=301
+KEY=35C99C004D01E89F94A9B3BC79C492D7C3DC3958584EFF6D712DFC28FB74C922
+IV=964983C30745D7EEA1BD5E287DAC466C
+PT=793D3908F9DEDF37A538D0EF1BC95323
+CT=6834813D8403A963AD36C1A18CA605C0
+
+I=302
+KEY=F185723D6A2D2A6F9F4B9194A444AA2AABE8B865DC4D560EDC1B3D8977D2CCE2
+IV=6834813D8403A963AD36C1A18CA605C0
+PT=C44CEE3D272CC2F00BE22228DD8038FD
+CT=61F35AA76E1E0EC2D5E4F4F432B68260
+
+I=303
+KEY=B571B0BC6CFD2BA23611FB9A900A31FACA1BE2C2B25358CC09FFC97D45644E82
+IV=61F35AA76E1E0EC2D5E4F4F432B68260
+PT=44F4C28106D001CDA95A6A0E344E9BD0
+CT=DD081A96602E6665B860466B8D14050E
+
+I=304
+KEY=2A5757156C596DE633D0D8908011C3771713F854D27D3EA9B19F8F16C8704B8C
+IV=DD081A96602E6665B860466B8D14050E
+PT=9F26E7A900A4464405C1230A101BF28D
+CT=5BF18EA3D7F3ED1D941EA1B995313B98
+
+I=305
+KEY=DA008B517FA48E908A72B8525CC31AEF4CE276F7058ED3B425812EAF5D417014
+IV=5BF18EA3D7F3ED1D941EA1B995313B98
+PT=F057DC4413FDE376B9A260C2DCD2D998
+CT=74C361B6A13013E9ABF6841601513539
+
+I=306
+KEY=E313244DC22AC16C1D59AC494AA728D738211741A4BEC05D8E77AAB95C10452D
+IV=74C361B6A13013E9ABF6841601513539
+PT=3913AF1CBD8E4FFC972B141B16643238
+CT=9937614570FD404D5B39BA43D3A20602
+
+I=307
+KEY=92A7173E943CBA80AF56203552625E8AA1167604D4438010D54E10FA8FB2432F
+IV=9937614570FD404D5B39BA43D3A20602
+PT=71B4337356167BECB20F8C7C18C5765D
+CT=726FCDDF8E6738B51D767828EBDFC71E
+
+I=308
+KEY=242C75C141A58DC403020E52421BB347D379BBDB5A24B8A5C83868D2646D8431
+IV=726FCDDF8E6738B51D767828EBDFC71E
+PT=B68B62FFD5993744AC542E671079EDCD
+CT=78F735344BF10EED47969F1C02ECBF8C
+
+I=309
+KEY=5247008C3EB79AA67E5D2E0B95D0AC3AAB8E8EEF11D5B6488FAEF7CE66813BBD
+IV=78F735344BF10EED47969F1C02ECBF8C
+PT=766B754D7F1217627D5F2059D7CB1F7D
+CT=7D6A6CA54B084105DF6A778A4913BB04
+
+I=310
+KEY=06E7C1A6C8BC6A3355A86F61B41E70C6D6E4E24A5ADDF74D50C480442F9280B9
+IV=7D6A6CA54B084105DF6A778A4913BB04
+PT=54A0C12AF60BF0952BF5416A21CEDCFC
+CT=11F0A303D6C0ED5E18F40248AF1A794B
+
+I=311
+KEY=D7722746B58D494BE9B97F586CA4BB0AC71441498C1D1A134830820C8088F9F2
+IV=11F0A303D6C0ED5E18F40248AF1A794B
+PT=D195E6E07D312378BC111039D8BACBCC
+CT=2A715E8AC7101415E65EBF34CC4CD786
+
+I=312
+KEY=98B1E5954DE8000B6FFFE98D918B6237ED651FC34B0D0E06AE6E3D384CC42E74
+IV=2A715E8AC7101415E65EBF34CC4CD786
+PT=4FC3C2D3F8654940864696D5FD2FD93D
+CT=965E8AF93D390E424C9F4F1FBF9D98A5
+
+I=313
+KEY=74B910207ACD1D7C801724D53ED6BBC47B3B953A76340044E2F17227F359B6D1
+IV=965E8AF93D390E424C9F4F1FBF9D98A5
+PT=EC08F5B537251D77EFE8CD58AF5DD9F3
+CT=294782DD29C65B6C445C5D92F50E6D19
+
+I=314
+KEY=3E1AD36FDCC33F6B3425B5D52717845E527C17E75FF25B28A6AD2FB50657DBC8
+IV=294782DD29C65B6C445C5D92F50E6D19
+PT=4AA3C34FA60E2217B432910019C13F9A
+CT=E22098E7EDBEECC49FA8E31B76E925CA
+
+I=315
+KEY=BE9F93FE153DF61370F6709F8265DCCDB05C8F00B24CB7EC3905CCAE70BEFE02
+IV=E22098E7EDBEECC49FA8E31B76E925CA
+PT=80854091C9FEC97844D3C54AA5725893
+CT=24E80C1F59A4EA36044358E0C0D4F29D
+
+I=316
+KEY=A790F593CFA1643BD2EB3A1AAB8176A294B4831FEBE85DDA3D46944EB06A0C9F
+IV=24E80C1F59A4EA36044358E0C0D4F29D
+PT=190F666DDA9C9228A21D4A8529E4AA6F
+CT=63CF21803941B521532FF36F9FBFC7BD
+
+I=317
+KEY=0CF6F000352B4B583E4AEE707D111DC9F77BA29FD2A9E8FB6E6967212FD5CB22
+IV=63CF21803941B521532FF36F9FBFC7BD
+PT=AB660593FA8A2F63ECA1D46AD6906B6B
+CT=250941C1D45C82B0D9C381293CDD833A
+
+I=318
+KEY=1F875BCF1967857990EC97864B1EA9F8D272E35E06F56A4BB7AAE60813084818
+IV=250941C1D45C82B0D9C381293CDD833A
+PT=1371ABCF2C4CCE21AEA679F6360FB431
+CT=8303B962DAFC4A225C0FD6EA60D29CF4
+
+I=319
+KEY=42FE25BF51418FE7A7C7A1828219E1DB51715A3CDC092069EBA530E273DAD4EC
+IV=8303B962DAFC4A225C0FD6EA60D29CF4
+PT=5D797E7048260A9E372B3604C9074823
+CT=29E2DB359FAB42C0A83A4059A059CB51
+
+I=320
+KEY=6C821A4893FE0EAC88FC1F98BD44AD0A7893810943A262A9439F70BBD3831FBD
+IV=29E2DB359FAB42C0A83A4059A059CB51
+PT=2E7C3FF7C2BF814B2F3BBE1A3F5D4CD1
+CT=02BDB7EC18279FA9B7788D95FEB4000E
+
+I=321
+KEY=411670D389D0A04859FDC26DE5AAD1297A2E36E55B85FD00F4E7FD2E2D371FB3
+IV=02BDB7EC18279FA9B7788D95FEB4000E
+PT=2D946A9B1A2EAEE4D101DDF558EE7C23
+CT=3960A92A34967F13B754F2265A6F68C1
+
+I=322
+KEY=851BCD18F6043DE625BBEA33E1E860E3434E9FCF6F13821343B30F0877587772
+IV=3960A92A34967F13B754F2265A6F68C1
+PT=C40DBDCB7FD49DAE7C46285E0442B1CA
+CT=EF396AB8613AC6083932734D38869458
+
+I=323
+KEY=1944F363F3143A380F26BD4831A6BD9EAC77F5770E29441B7A817C454FDEE32A
+IV=EF396AB8613AC6083932734D38869458
+PT=9C5F3E7B051007DE2A9D577BD04EDD7D
+CT=CB73B8D257CC1A8235E48DA0E6AECC4E
+
+I=324
+KEY=C2F3C203F591C78914E31BA1E083AB9867044DA559E55E994F65F1E5A9702F64
+IV=CB73B8D257CC1A8235E48DA0E6AECC4E
+PT=DBB731600685FDB11BC5A6E9D1251606
+CT=3B0B12757B5D1B6E0130FCC306E9DBAA
+
+I=325
+KEY=0DCB66B972631AFBB1DA22F1418EE1C45C0F5FD022B845F74E550D26AF99F4CE
+IV=3B0B12757B5D1B6E0130FCC306E9DBAA
+PT=CF38A4BA87F2DD72A5393950A10D4A5C
+CT=CCEF4079CE8FAF0E6B8CD4C8751059E1
+
+I=326
+KEY=8FF976D3C735506D86A3540664F1C40590E01FA9EC37EAF925D9D9EEDA89AD2F
+IV=CCEF4079CE8FAF0E6B8CD4C8751059E1
+PT=8232106AB5564A96377976F7257F25C1
+CT=D835D2FA5583D9B2C16424960163DF7F
+
+I=327
+KEY=3499925B26E4F846CAA230EC069F127F48D5CD53B9B4334BE4BDFD78DBEA7250
+IV=D835D2FA5583D9B2C16424960163DF7F
+PT=BB60E488E1D1A82B4C0164EA626ED67A
+CT=4634485DB5D9C40FA2F6EF36E477F0B7
+
+I=328
+KEY=7A133EEC3DD747FE38A3370F8927A3C70EE1850E0C6DF744464B124E3F9D82E7
+IV=4634485DB5D9C40FA2F6EF36E477F0B7
+PT=4E8AACB71B33BFB8F20107E38FB8B1B8
+CT=AE30CD2A5D84CEF10B9C15EE1FE20CEB
+
+I=329
+KEY=F573665345317BAB5F14881777A0D789A0D1482451E939B54DD707A0207F8E0C
+IV=AE30CD2A5D84CEF10B9C15EE1FE20CEB
+PT=8F6058BF78E63C5567B7BF18FE87744E
+CT=B3926CDE5BFB1363DCCA28CDA2DC4CD8
+
+I=330
+KEY=FEFB661FA786BF2DA1B70FD7D06B86E8134324FA0A122AD6911D2F6D82A3C2D4
+IV=B3926CDE5BFB1363DCCA28CDA2DC4CD8
+PT=0B88004CE2B7C486FEA387C0A7CB5161
+CT=633388FA9EAE0DB2036F63CB2E21C266
+
+I=331
+KEY=BFC495DFBA60078708D992724C9201577070AC0094BC276492724CA6AC8200B2
+IV=633388FA9EAE0DB2036F63CB2E21C266
+PT=413FF3C01DE6B8AAA96E9DA59CF987BF
+CT=54ACB838D247D26A1544B2E42F18CF3F
+
+I=332
+KEY=EB0113E4FFE1201B59EAE94706B2571F24DC143846FBF50E8736FE42839ACF8D
+IV=54ACB838D247D26A1544B2E42F18CF3F
+PT=54C5863B4581279C51337B354A205648
+CT=B9210B8A8639CA5C94A1CF1169F89DDB
+
+I=333
+KEY=0E1D5F7873FD6440227C5529AEB4C7999DFD1FB2C0C23F5213973153EA625256
+IV=B9210B8A8639CA5C94A1CF1169F89DDB
+PT=E51C4C9C8C1C445B7B96BC6EA8069086
+CT=8990488561B43B03CF9FE631E2E7D5E7
+
+I=334
+KEY=8B2759471137DBF37906B394EFEF96D2146D5737A1760451DC08D762088587B1
+IV=8990488561B43B03CF9FE631E2E7D5E7
+PT=853A063F62CABFB35B7AE6BD415B514B
+CT=9DCE77D8CCC0F041FA717C28474E9A30
+
+I=335
+KEY=0D4B29E8D6F39CA01BC01CE73E2834C689A320EF6DB6F4102679AB4A4FCB1D81
+IV=9DCE77D8CCC0F041FA717C28474E9A30
+PT=866C70AFC7C4475362C6AF73D1C7A214
+CT=E1DA174FE5848D21735E55B91CA48A9B
+
+I=336
+KEY=55228F6FF93B7DE9304CD75991C133A5687937A0883279315527FEF3536F971A
+IV=E1DA174FE5848D21735E55B91CA48A9B
+PT=5869A6872FC8E1492B8CCBBEAFE90763
+CT=C578F53AD69AD508711E674F8DD2A843
+
+I=337
+KEY=35CA943437046860F72A1F8554127676AD01C29A5EA8AC39243999BCDEBD3F59
+IV=C578F53AD69AD508711E674F8DD2A843
+PT=60E81B5BCE3F1589C766C8DCC5D345D3
+CT=177A50196260D3F0A3F97423899EBEE2
+
+I=338
+KEY=B8C3B8414C112FC2E2E848733D5CF69CBA7B92833CC87FC987C0ED9F572381BB
+IV=177A50196260D3F0A3F97423899EBEE2
+PT=8D092C757B1547A215C257F6694E80EA
+CT=6B03A799C51C7D0A9D3C9929617E69B1
+
+I=339
+KEY=E82B651AE5740119104FE3284CE780E4D178351AF9D402C31AFC74B6365DE80A
+IV=6B03A799C51C7D0A9D3C9929617E69B1
+PT=50E8DD5BA9652EDBF2A7AB5B71BB7678
+CT=8D4C7C1157422E7B6DDA47C5C2C246F4
+
+I=340
+KEY=3C0B660F2B78F768812AC671D3107AD85C34490BAE962CB877263373F49FAEFE
+IV=8D4C7C1157422E7B6DDA47C5C2C246F4
+PT=D4200315CE0CF671916525599FF7FA3C
+CT=787B3C51094569BC1F139102964DF5AF
+
+I=341
+KEY=A197B59C700A4786E840733047964FD4244F755AA7D345046835A27162D25B51
+IV=787B3C51094569BC1F139102964DF5AF
+PT=9D9CD3935B72B0EE696AB5419486350C
+CT=AE02945B4E63AC35B6AC2DFA2DF3CEBA
+
+I=342
+KEY=00E75C4B909D44A94FA20EDA6C3628418A4DE101E9B0E931DE998F8B4F2195EB
+IV=AE02945B4E63AC35B6AC2DFA2DF3CEBA
+PT=A170E9D7E097032FA7E27DEA2BA06795
+CT=AC4AACD3597FE73F519F7CEDAFE6E000
+
+I=343
+KEY=4626BE31853C15DE412EF2A42328D47326074DD2B0CF0E0E8F06F366E0C775EB
+IV=AC4AACD3597FE73F519F7CEDAFE6E000
+PT=46C1E27A15A151770E8CFC7E4F1EFC32
+CT=5EB8B35708A135E041603BA323663F34
+
+I=344
+KEY=1733A037E76437411F49821D948A098978BFFE85B86E3BEECE66C8C5C3A14ADF
+IV=5EB8B35708A135E041603BA323663F34
+PT=51151E066258229F5E6770B9B7A2DDFA
+CT=6674FB922570377334A4F22D13E95BD8
+
+I=345
+KEY=8474275A2E4D5E5448EB8D34B65EE7081ECB05179D1E0C9DFAC23AE8D0481107
+IV=6674FB922570377334A4F22D13E95BD8
+PT=9347876DC929691557A20F2922D4EE81
+CT=F0E3F09C0350C0172E449A01F24AB828
+
+I=346
+KEY=765AA3F4014B8475CF832DE6128F7F2DEE28F58B9E4ECC8AD486A0E92202A92F
+IV=F0E3F09C0350C0172E449A01F24AB828
+PT=F22E84AE2F06DA218768A0D2A4D19825
+CT=CC156010299679ADEE9CC000FD5C90E5
+
+I=347
+KEY=DD3D3AFC83B7EEBC58CE35B35719B587223D959BB7D8B5273A1A60E9DF5E39CA
+IV=CC156010299679ADEE9CC000FD5C90E5
+PT=AB67990882FC6AC9974D18554596CAAA
+CT=80354EDEA10038E903C4896313236CE5
+
+I=348
+KEY=4764BB8C98BCF3FD4A21A370AE5432BBA208DB4516D88DCE39DEE98ACC7D552F
+IV=80354EDEA10038E903C4896313236CE5
+PT=9A5981701B0B1D4112EF96C3F94D873C
+CT=15140DC26F383EB99425FB51D445CC98
+
+I=349
+KEY=DF729AB7D09BC85489F8AD373EBDDA70B71CD68779E0B377ADFB12DB183899B7
+IV=15140DC26F383EB99425FB51D445CC98
+PT=9816213B48273BA9C3D90E4790E9E8CB
+CT=163465787010C97D3C2023D803F62556
+
+I=350
+KEY=A945B0C5997C596B5155A6BCA5055127A128B3FF09F07A0A91DB31031BCEBCE1
+IV=163465787010C97D3C2023D803F62556
+PT=76372A7249E7913FD8AD0B8B9BB88B57
+CT=23E861D557EE72534C8B729240E3A54F
+
+I=351
+KEY=0E1C166F2B947D14D0C7E6ABD280A31E82C0D22A5E1E0859DD5043915B2D19AE
+IV=23E861D557EE72534C8B729240E3A54F
+PT=A759A6AAB2E8247F819240177785F239
+CT=652CA6A199D7DBC37936FCD70636989F
+
+I=352
+KEY=208A37149072011877E3E85B3DC7F4A7E7EC748BC7C9D39AA466BF465D1B8131
+IV=652CA6A199D7DBC37936FCD70636989F
+PT=2E96217BBBE67C0CA7240EF0EF4757B9
+CT=7C29D6F4788553E3C50A48027478A98F
+
+I=353
+KEY=A8FFCB194C077EEED66632AEBE01652E9BC5A27FBF4C8079616CF744296328BE
+IV=7C29D6F4788553E3C50A48027478A98F
+PT=8875FC0DDC757FF6A185DAF583C69189
+CT=7B886FC819D625B224F2516901788E88
+
+I=354
+KEY=3716969BDDBF04FF4010D4667CCA994AE04DCDB7A69AA5CB459EA62D281BA636
+IV=7B886FC819D625B224F2516901788E88
+PT=9FE95D8291B87A119676E6C8C2CBFC64
+CT=3EAB925C025F379153CE2C7191026976
+
+I=355
+KEY=991D0D313717C7AC62537C8572DE094BDEE65FEBA4C5925A16508A5CB919CF40
+IV=3EAB925C025F379153CE2C7191026976
+PT=AE0B9BAAEAA8C3532243A8E30E149001
+CT=B9904B8BDF431FDDB9166086C9D3E24C
+
+I=356
+KEY=315772BB82A3DD286FE5891934B19434677614607B868D87AF46EADA70CA2D0C
+IV=B9904B8BDF431FDDB9166086C9D3E24C
+PT=A84A7F8AB5B41A840DB6F59C466F9D7F
+CT=3C7029336ECCA5D352DB9D0C060D3830
+
+I=357
+KEY=C99E4E6A8C1D42A9E431FF8B2A8ACA615B063D53154A2854FD9D77D676C7153C
+IV=3C7029336ECCA5D352DB9D0C060D3830
+PT=F8C93CD10EBE9F818BD476921E3B5E55
+CT=4AF4290AA79EB96435D2D3FC745033D7
+
+I=358
+KEY=55317B8B407B7D089ED2CEF7BE80E99111F21459B2D49130C84FA42A029726EB
+IV=4AF4290AA79EB96435D2D3FC745033D7
+PT=9CAF35E1CC663FA17AE3317C940A23F0
+CT=BFCA0B6B31AAD81F1BDC743B48B7CCA4
+
+I=359
+KEY=6EAE6D8B06AA25493BA3608357D71404AE381F32837E492FD393D0114A20EA4F
+IV=BFCA0B6B31AAD81F1BDC743B48B7CCA4
+PT=3B9F160046D15841A571AE74E957FD95
+CT=89C1D565569A12A68B2E808AB5CFA2E3
+
+I=360
+KEY=3245D7C1F5571A1329E1B2303F8A689D27F9CA57D5E45B8958BD509BFFEF48AC
+IV=89C1D565569A12A68B2E808AB5CFA2E3
+PT=5CEBBA4AF3FD3F5A1242D2B3685D7C99
+CT=EC8EEAED7894646B1D1A5E058ED41178
+
+I=361
+KEY=1DE05811428569D3F89CF1C01AF434AFCB7720BAAD703FE245A70E9E713B59D4
+IV=EC8EEAED7894646B1D1A5E058ED41178
+PT=2FA58FD0B7D273C0D17D43F0257E5C32
+CT=92802F392579C66AD72D2E85776720E8
+
+I=362
+KEY=0A8FB6D844AB0B73C05A121085E07FFE59F70F838809F988928A201B065C793C
+IV=92802F392579C66AD72D2E85776720E8
+PT=176FEEC9062E62A038C6E3D09F144B51
+CT=461DBCF9894F5319FE772F6529FBCEC0
+
+I=363
+KEY=4E6818B3BBEF69FA7ABEC1EBE2E54CDC1FEAB37A0146AA916CFD0F7E2FA7B7FC
+IV=461DBCF9894F5319FE772F6529FBCEC0
+PT=44E7AE6BFF446289BAE4D3FB67053322
+CT=794CA9DC41BAE95D415A6D1119582763
+
+I=364
+KEY=4A1EABB13924B188441724141F1C88A966A61AA640FC43CC2DA7626F36FF909F
+IV=794CA9DC41BAE95D415A6D1119582763
+PT=0476B30282CBD8723EA9E5FFFDF9C475
+CT=B761EAF5CC07651BD33D8BF93913EAE8
+
+I=365
+KEY=FFE4E48F8D96710A1BE7DBE36F4905CDD1C7F0538CFB26D7FE9AE9960FEC7A77
+IV=B761EAF5CC07651BD33D8BF93913EAE8
+PT=B5FA4F3EB4B2C0825FF0FFF770558D64
+CT=0B5146EB77161E60D6D1E2FAEAE80694
+
+I=366
+KEY=7A4F383AF4BB2DC6588E75EE82C7D9CFDA96B6B8FBED38B7284B0B6CE5047CE3
+IV=0B5146EB77161E60D6D1E2FAEAE80694
+PT=85ABDCB5792D5CCC4369AE0DED8EDC02
+CT=07635064CE85F6AE17961AF1F2B44469
+
+I=367
+KEY=EFFE7F8BBBEC8BEC83FA199102763BEDDDF5E6DC3568CE193FDD119D17B0388A
+IV=07635064CE85F6AE17961AF1F2B44469
+PT=95B147B14F57A62ADB746C7F80B1E222
+CT=3A9CD5F30C421FF333BA2C2F0A7AD07D
+
+I=368
+KEY=1DF51B7A35E11E2AF79E8C59094A1ECFE769332F392AD1EA0C673DB21DCAE8F7
+IV=3A9CD5F30C421FF333BA2C2F0A7AD07D
+PT=F20B64F18E0D95C6746495C80B3C2522
+CT=F60032C249CF561CB02421DA189A57D1
+
+I=369
+KEY=CC09FFE72A10AE27FE14934A6628AB83116901ED70E587F6BC431C680550BF26
+IV=F60032C249CF561CB02421DA189A57D1
+PT=D1FCE49D1FF1B00D098A1F136F62B54C
+CT=EAD5844B160C08F9CDAA15FD5936EF26
+
+I=370
+KEY=09C84CA0DA0B9FD79D3090E690BAB419FBBC85A666E98F0F71E909955C665000
+IV=EAD5844B160C08F9CDAA15FD5936EF26
+PT=C5C1B347F01B31F0632403ACF6921F9A
+CT=26AD72F011133FD4CED8F38A1ABE7D73
+
+I=371
+KEY=74FA53C172A2003EC5933F486FCC7BBFDD11F75677FAB0DBBF31FA1F46D82D73
+IV=26AD72F011133FD4CED8F38A1ABE7D73
+PT=7D321F61A8A99FE958A3AFAEFF76CFA6
+CT=F115FBC0D3F386527176D1DF6AD4B38A
+
+I=372
+KEY=0E5BA209B7BC28D184E73BD37F35C1312C040C96A4093689CE472BC02C0C9EF9
+IV=F115FBC0D3F386527176D1DF6AD4B38A
+PT=7AA1F1C8C51E28EF4174049B10F9BA8E
+CT=27ED0BA04734E70317BF58E11B0DD051
+
+I=373
+KEY=9404D9139B6597D1F7C7519713C6CBC80BE90736E33DD18AD9F8732137014EA8
+IV=27ED0BA04734E70317BF58E11B0DD051
+PT=9A5F7B1A2CD9BF0073206A446CF30AF9
+CT=24080A577426F8F270A13F3A5F3DB546
+
+I=374
+KEY=E72476BC679C8DCBAB92BBA5D48BF6D32FE10D61971B2978A9594C1B683CFBEE
+IV=24080A577426F8F270A13F3A5F3DB546
+PT=7320AFAFFCF91A1A5C55EA32C74D3D1B
+CT=A754CC0464E35B387435790505F2DCE5
+
+I=375
+KEY=4548DE389CCAD4A65B02A9B5FE90930188B5C165F3F87240DD6C351E6DCE270B
+IV=A754CC0464E35B387435790505F2DCE5
+PT=A26CA884FB56596DF09012102A1B65D2
+CT=D9AED2566884E97D081EADB45780AA7D
+
+I=376
+KEY=2E54365B503140D0EC9074DFA05F4B2C511B13339B7C9B3DD57298AA3A4E8D76
+IV=D9AED2566884E97D081EADB45780AA7D
+PT=6B1CE863CCFB9476B792DD6A5ECFD82D
+CT=9FA221E082CAD838AB4B210A8794BD8F
+
+I=377
+KEY=7C9FB092B8A96465076E14C575E9A8F0CEB932D319B643057E39B9A0BDDA30F9
+IV=9FA221E082CAD838AB4B210A8794BD8F
+PT=52CB86C9E89824B5EBFE601AD5B6E3DC
+CT=AAEA6DE5734CF14BED503512EB071C2A
+
+I=378
+KEY=90AB85A18F2B0255D4F43AF5E98DAA7E64535F366AFAB24E93698CB256DD2CD3
+IV=AAEA6DE5734CF14BED503512EB071C2A
+PT=EC34353337826630D39A2E309C64028E
+CT=1359A157B415EB63E038AB7354E6B0F2
+
+I=379
+KEY=9135D4D54A1CE6BBF4F23AFDE23F537C770AFE61DEEF592D735127C1023B9C21
+IV=1359A157B415EB63E038AB7354E6B0F2
+PT=019E5174C537E4EE200600080BB2F902
+CT=0764EBDBFAE8FD447244408A5153CC3B
+
+I=380
+KEY=4B5F1BC60EF5DCE83474A3970EB2ABA8706E15BA2407A4690115674B5368501A
+IV=0764EBDBFAE8FD447244408A5153CC3B
+PT=DA6ACF1344E93A53C086996AEC8DF8D4
+CT=A31F69E0055E8D4162AC06C088925FBA
+
+I=381
+KEY=9DD8E8D75BE2E4D1BC70B30DAE0B375FD3717C5A2159292863B9618BDBFA0FA0
+IV=A31F69E0055E8D4162AC06C088925FBA
+PT=D687F311551738398804109AA0B99CF7
+CT=EB84AC035534CDF1698E660F529E0EC7
+
+I=382
+KEY=4A2B2FC8446B4C2575CFE584A490680238F5D059746DE4D90A37078489640167
+IV=EB84AC035534CDF1698E660F529E0EC7
+PT=D7F3C71F1F89A8F4C9BF56890A9B5F5D
+CT=9236D37A28C2CF29237127173B93C5D5
+
+I=383
+KEY=9BE42576823EEAADB34657A5CBB44B21AAC303235CAF2BF029462093B2F7C4B2
+IV=9236D37A28C2CF29237127173B93C5D5
+PT=D1CF0ABEC655A688C689B2216F242323
+CT=86C122CFA62B1356FEE33FECF598ACC9
+
+I=384
+KEY=5DFC1838B052E95A948D0AC31736CBE62C0221ECFA8438A6D7A51F7F476F687B
+IV=86C122CFA62B1356FEE33FECF598ACC9
+PT=C6183D4E326C03F727CB5D66DC8280C7
+CT=8A9926125B1CA354B1D7A9FED0850FEE
+
+I=385
+KEY=2B12FA914EE7674EADED81C47A67A1B4A69B07FEA1989BF26672B68197EA6795
+IV=8A9926125B1CA354B1D7A9FED0850FEE
+PT=76EEE2A9FEB58E1439608B076D516A52
+CT=AD99A2A427BFF7A17C375DB38764EBFC
+
+I=386
+KEY=10607DE088CB92382089EF99B7C054280B02A55A86276C531A45EB32108E8C69
+IV=AD99A2A427BFF7A17C375DB38764EBFC
+PT=3B728771C62CF5768D646E5DCDA7F59C
+CT=0E141FD7D6928E7B7885638B6334947C
+
+I=387
+KEY=605ECCB38F9FFD9DAB2DB523313FFADB0516BA8D50B5E22862C088B973BA1815
+IV=0E141FD7D6928E7B7885638B6334947C
+PT=703EB15307546FA58BA45ABA86FFAEF3
+CT=996CB8723B08B99A4959072DC8A73292
+
+I=388
+KEY=C6371257BDA461F3A4D2F1ED5DD4B0B69C7A02FF6BBD5BB22B998F94BB1D2A87
+IV=996CB8723B08B99A4959072DC8A73292
+PT=A669DEE4323B9C6E0FFF44CE6CEB4A6D
+CT=72966BAA5E4D7FA9129088F2C072E301
+
+I=389
+KEY=DDD8877C25005F9B8336823CBF4D4B1DEEEC695535F0241B390907667B6FC986
+IV=72966BAA5E4D7FA9129088F2C072E301
+PT=1BEF952B98A43E6827E473D1E299FBAB
+CT=32C321C999A2D68EA4517D332C785FC4
+
+I=390
+KEY=00882DCBC6CFDED1A2ED7D9892F494A5DC2F489CAC52F2959D587A5557179642
+IV=32C321C999A2D68EA4517D332C785FC4
+PT=DD50AAB7E3CF814A21DBFFA42DB9DFB8
+CT=391D95DD63982E0A9AF3980A234DB5B9
+
+I=391
+KEY=234B9097BD6519EFE106103720AC937DE532DD41CFCADC9F07ABE25F745A23FB
+IV=391D95DD63982E0A9AF3980A234DB5B9
+PT=23C3BD5C7BAAC73E43EB6DAFB25807D8
+CT=D3A279EE1BABABA71DB01DC35EBA879D
+
+I=392
+KEY=AFF7D52D959CC7E41F1F3FF3CA2425053690A4AFD46177381A1BFF9C2AE0A466
+IV=D3A279EE1BABABA71DB01DC35EBA879D
+PT=8CBC45BA28F9DE0BFE192FC4EA88B678
+CT=B4696871EE3A9D035BC32308DA5A5DA7
+
+I=393
+KEY=B557440CEEB6E4EF54F6CD1B222246AC82F9CCDE3A5BEA3B41D8DC94F0BAF9C1
+IV=B4696871EE3A9D035BC32308DA5A5DA7
+PT=1AA091217B2A230B4BE9F2E8E80663A9
+CT=C5047AFD7884E0124928229AA6E72F67
+
+I=394
+KEY=BF64C071FAAD2C48CB269C03563FA06147FDB62342DF0A2908F0FE0E565DD6A6
+IV=C5047AFD7884E0124928229AA6E72F67
+PT=0A33847D141BC8A79FD05118741DE6CD
+CT=240D684E6BAD3FD4E41D58DB871E93CD
+
+I=395
+KEY=F6945509258A1584398F5438DFD679DB63F0DE6D297235FDECEDA6D5D143456B
+IV=240D684E6BAD3FD4E41D58DB871E93CD
+PT=49F09578DF2739CCF2A9C83B89E9D9BA
+CT=F66917F0C3C67774F9263062F918DDD5
+
+I=396
+KEY=A8E48107D59287ABBA374E7CE5BC28E89599C99DEAB4428915CB96B7285B98BE
+IV=F66917F0C3C67774F9263062F918DDD5
+PT=5E70D40EF018922F83B81A443A6A5133
+CT=85C42456F11D0191BC4B4DD4EA0406EE
+
+I=397
+KEY=E4F367569F4F9114AFE937A0190C9738105DEDCB1BA94318A980DB63C25F9E50
+IV=85C42456F11D0191BC4B4DD4EA0406EE
+PT=4C17E6514ADD16BF15DE79DCFCB0BFD0
+CT=D48B6C87A25C71113947569411C2186A
+
+I=398
+KEY=987ED2D586DA9AB08C584BBEA0478953C4D6814CB9F5320990C78DF7D39D863A
+IV=D48B6C87A25C71113947569411C2186A
+PT=7C8DB58319950BA423B17C1EB94B1E6B
+CT=AB6957C2F3D360593E9096F3A392A701
+
+I=399
+KEY=3DF2BF13B7FF97CA13567A890E11C9796FBFD68E4A265250AE571B04700F213B
+IV=AB6957C2F3D360593E9096F3A392A701
+PT=A58C6DC631250D7A9F0E3137AE56402A
+CT=C0FEFFF07506A0B4CD7B8B0CF25D3664
+
+===========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/ecb_d_m.txt b/krb5-1-6/src/lib/crypto/aes/test/ecb_d_m.txt
new file mode 100644
index 000000000..d99a69af3
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/ecb_d_m.txt
@@ -0,0 +1,6024 @@
+
+=========================
+
+FILENAME:  "ecb_d_m.txt"
+
+Electronic Codebook (ECB) Mode - DECRYPTION
+Monte Carlo Test
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+=========================
+
+KEYSIZE=128
+
+I=0
+KEY=00000000000000000000000000000000
+CT=00000000000000000000000000000000
+PT=44416AC2D1F53C583303917E6BE9EBE0
+
+I=1
+KEY=44416AC2D1F53C583303917E6BE9EBE0
+CT=44416AC2D1F53C583303917E6BE9EBE0
+PT=E3FD51123B48A2E2AB1DB29894202222
+
+I=2
+KEY=A7BC3BD0EABD9EBA981E23E6FFC9C9C2
+CT=E3FD51123B48A2E2AB1DB29894202222
+PT=877B88A77AEF04F05546539E17259F53
+
+I=3
+KEY=20C7B37790529A4ACD587078E8EC5691
+CT=877B88A77AEF04F05546539E17259F53
+PT=C7A71C1B46261602EB1EE48FDA8155A4
+
+I=4
+KEY=E760AF6CD6748C48264694F7326D0335
+CT=C7A71C1B46261602EB1EE48FDA8155A4
+PT=6B6AC8E00FAF7E045ECCFC426A137221
+
+I=5
+KEY=8C0A678CD9DBF24C788A68B5587E7114
+CT=6B6AC8E00FAF7E045ECCFC426A137221
+PT=3F252821FA79AFC3F1798B343AAD41EE
+
+I=6
+KEY=B32F4FAD23A25D8F89F3E38162D330FA
+CT=3F252821FA79AFC3F1798B343AAD41EE
+PT=0B55C691E1F97205D137FF34478E5BC9
+
+I=7
+KEY=B87A893CC25B2F8A58C41CB5255D6B33
+CT=0B55C691E1F97205D137FF34478E5BC9
+PT=F6CCC1CC18A3199D6427EDCA0BB2DF90
+
+I=8
+KEY=4EB648F0DAF836173CE3F17F2EEFB4A3
+CT=F6CCC1CC18A3199D6427EDCA0BB2DF90
+PT=0CDD7D9734B1515C73DDA60EFF28CD89
+
+I=9
+KEY=426B3567EE49674B4F3E5771D1C7792A
+CT=0CDD7D9734B1515C73DDA60EFF28CD89
+PT=3E813131EDD440D9054799CEA508FF6F
+
+I=10
+KEY=7CEA0456039D27924A79CEBF74CF8645
+CT=3E813131EDD440D9054799CEA508FF6F
+PT=8C6859BD0B6E078FAA6B686297653232
+
+I=11
+KEY=F0825DEB08F3201DE012A6DDE3AAB477
+CT=8C6859BD0B6E078FAA6B686297653232
+PT=C966A4106C1DCE062D1346EB5E5133BB
+
+I=12
+KEY=39E4F9FB64EEEE1BCD01E036BDFB87CC
+CT=C966A4106C1DCE062D1346EB5E5133BB
+PT=4F4AE38B53FD7800F0E9F5C214E16F2A
+
+I=13
+KEY=76AE1A703713961B3DE815F4A91AE8E6
+CT=4F4AE38B53FD7800F0E9F5C214E16F2A
+PT=C73A033491DC0B6A77FEA2FBCC9D305E
+
+I=14
+KEY=B1941944A6CF9D714A16B70F6587D8B8
+CT=C73A033491DC0B6A77FEA2FBCC9D305E
+PT=C928C2A05BB44816EFBE6B13E94BC70E
+
+I=15
+KEY=78BCDBE4FD7BD567A5A8DC1C8CCC1FB6
+CT=C928C2A05BB44816EFBE6B13E94BC70E
+PT=A7C1593E7B4BAEE5256D4081337E7CAF
+
+I=16
+KEY=DF7D82DA86307B8280C59C9DBFB26319
+CT=A7C1593E7B4BAEE5256D4081337E7CAF
+PT=7ECD305AC27AEBFA2B8F85F9AC312638
+
+I=17
+KEY=A1B0B280444A9078AB4A196413834521
+CT=7ECD305AC27AEBFA2B8F85F9AC312638
+PT=A24D1403A58B94798F5F3565ABFD3B44
+
+I=18
+KEY=03FDA683E1C1040124152C01B87E7E65
+CT=A24D1403A58B94798F5F3565ABFD3B44
+PT=5B6E097B3B0E21DCC9CE9970701C7BD5
+
+I=19
+KEY=5893AFF8DACF25DDEDDBB571C86205B0
+CT=5B6E097B3B0E21DCC9CE9970701C7BD5
+PT=4E21CEA52B3111AC8F6B204A1F5E65E2
+
+I=20
+KEY=16B2615DF1FE347162B0953BD73C6052
+CT=4E21CEA52B3111AC8F6B204A1F5E65E2
+PT=806DDC5C37ADEEBB6FCE4730939D7A99
+
+I=21
+KEY=96DFBD01C653DACA0D7ED20B44A11ACB
+CT=806DDC5C37ADEEBB6FCE4730939D7A99
+PT=3462F7C6D3E071A0D3ACE7FD79149776
+
+I=22
+KEY=A2BD4AC715B3AB6ADED235F63DB58DBD
+CT=3462F7C6D3E071A0D3ACE7FD79149776
+PT=AF0FFF307B72284E794C8A64C30299D2
+
+I=23
+KEY=0DB2B5F76EC18324A79EBF92FEB7146F
+CT=AF0FFF307B72284E794C8A64C30299D2
+PT=E482B613FBCF9C4422D85E3160B1FB0F
+
+I=24
+KEY=E93003E4950E1F608546E1A39E06EF60
+CT=E482B613FBCF9C4422D85E3160B1FB0F
+PT=FADC8EF9C95540AD69897DECAB2D50D5
+
+I=25
+KEY=13EC8D1D5C5B5FCDECCF9C4F352BBFB5
+CT=FADC8EF9C95540AD69897DECAB2D50D5
+PT=2A765E237FB5230D792D455596A17118
+
+I=26
+KEY=399AD33E23EE7CC095E2D91AA38ACEAD
+CT=2A765E237FB5230D792D455596A17118
+PT=0887DA8012C7F95BD6ADB18D1ED3C2DB
+
+I=27
+KEY=311D09BE3129859B434F6897BD590C76
+CT=0887DA8012C7F95BD6ADB18D1ED3C2DB
+PT=3BB831A7B6FAC3649176471012FAD1C1
+
+I=28
+KEY=0AA5381987D346FFD2392F87AFA3DDB7
+CT=3BB831A7B6FAC3649176471012FAD1C1
+PT=E4F8629AB3489A0945B8B7188B953DE5
+
+I=29
+KEY=EE5D5A83349BDCF69781989F2436E052
+CT=E4F8629AB3489A0945B8B7188B953DE5
+PT=1D4B0B5B321EB711939AB481239E2541
+
+I=30
+KEY=F31651D806856BE7041B2C1E07A8C513
+CT=1D4B0B5B321EB711939AB481239E2541
+PT=71A368D5A33665D6FF9F33FECAFC6884
+
+I=31
+KEY=82B5390DA5B30E31FB841FE0CD54AD97
+CT=71A368D5A33665D6FF9F33FECAFC6884
+PT=8ACF418080075BA23B05A52552773B84
+
+I=32
+KEY=087A788D25B45593C081BAC59F239613
+CT=8ACF418080075BA23B05A52552773B84
+PT=E0E6058735F4FE765E882521D769FB41
+
+I=33
+KEY=E89C7D0A1040ABE59E099FE4484A6D52
+CT=E0E6058735F4FE765E882521D769FB41
+PT=70DCE91F818DF2CDC4269F1B4EA0A465
+
+I=34
+KEY=9840941591CD59285A2F00FF06EAC937
+CT=70DCE91F818DF2CDC4269F1B4EA0A465
+PT=E2F809D6DD77D72EF6DB5A82C42BF1CF
+
+I=35
+KEY=7AB89DC34CBA8E06ACF45A7DC2C138F8
+CT=E2F809D6DD77D72EF6DB5A82C42BF1CF
+PT=0741D11DDD877957E753ECF8DB91C72B
+
+I=36
+KEY=7DF94CDE913DF7514BA7B6851950FFD3
+CT=0741D11DDD877957E753ECF8DB91C72B
+PT=03E411012CA3B5B3CC163677D4B52456
+
+I=37
+KEY=7E1D5DDFBD9E42E287B180F2CDE5DB85
+CT=03E411012CA3B5B3CC163677D4B52456
+PT=0270D90790EF8347ACFB87EB2FEC2710
+
+I=38
+KEY=7C6D84D82D71C1A52B4A0719E209FC95
+CT=0270D90790EF8347ACFB87EB2FEC2710
+PT=3AE40270512374AF4022638E0A7A6D8E
+
+I=39
+KEY=468986A87C52B50A6B686497E873911B
+CT=3AE40270512374AF4022638E0A7A6D8E
+PT=8008D87E928A980FECA08CAF1EC91DDA
+
+I=40
+KEY=C6815ED6EED82D0587C8E838F6BA8CC1
+CT=8008D87E928A980FECA08CAF1EC91DDA
+PT=1D479A54832FF1A81D30008EFDF16A34
+
+I=41
+KEY=DBC6C4826DF7DCAD9AF8E8B60B4BE6F5
+CT=1D479A54832FF1A81D30008EFDF16A34
+PT=9E731FECD9A767BDA0C84B4C4D552BD3
+
+I=42
+KEY=45B5DB6EB450BB103A30A3FA461ECD26
+CT=9E731FECD9A767BDA0C84B4C4D552BD3
+PT=C2211A6B16CD27C6C73A5C3C1A0132AC
+
+I=43
+KEY=8794C105A29D9CD6FD0AFFC65C1FFF8A
+CT=C2211A6B16CD27C6C73A5C3C1A0132AC
+PT=7E523DD6F25706F971F020F88FFA0CF7
+
+I=44
+KEY=F9C6FCD350CA9A2F8CFADF3ED3E5F37D
+CT=7E523DD6F25706F971F020F88FFA0CF7
+PT=0EDC01C6C1A8DA6A7C9EEE3587CB098E
+
+I=45
+KEY=F71AFD1591624045F064310B542EFAF3
+CT=0EDC01C6C1A8DA6A7C9EEE3587CB098E
+PT=EE479106871DA872632794633B1ACF0E
+
+I=46
+KEY=195D6C13167FE8379343A5686F3435FD
+CT=EE479106871DA872632794633B1ACF0E
+PT=7EC1A4578D911F336184DACCCA92D943
+
+I=47
+KEY=679CC8449BEEF704F2C77FA4A5A6ECBE
+CT=7EC1A4578D911F336184DACCCA92D943
+PT=53715F25AE02513F181E3DECBB007803
+
+I=48
+KEY=34ED976135ECA63BEAD942481EA694BD
+CT=53715F25AE02513F181E3DECBB007803
+PT=304D5764B5206F8204A69D1BED11FA62
+
+I=49
+KEY=04A0C00580CCC9B9EE7FDF53F3B76EDF
+CT=304D5764B5206F8204A69D1BED11FA62
+PT=5A7590ADEF208BFD808499A2BFE9B011
+
+I=50
+KEY=5ED550A86FEC42446EFB46F14C5EDECE
+CT=5A7590ADEF208BFD808499A2BFE9B011
+PT=2502C0F68A721A93ECE8D7B6C2097BA4
+
+I=51
+KEY=7BD7905EE59E58D7821391478E57A56A
+CT=2502C0F68A721A93ECE8D7B6C2097BA4
+PT=1C814E26A6464086D606C7B4C6DFD85B
+
+I=52
+KEY=6756DE7843D81851541556F348887D31
+CT=1C814E26A6464086D606C7B4C6DFD85B
+PT=9D55D6EA99BA391190068205DD9AE69C
+
+I=53
+KEY=FA030892DA622140C413D4F695129BAD
+CT=9D55D6EA99BA391190068205DD9AE69C
+PT=9D1212D0BD8C26422EEFF4DDB16B2EF3
+
+I=54
+KEY=67111A4267EE0702EAFC202B2479B55E
+CT=9D1212D0BD8C26422EEFF4DDB16B2EF3
+PT=54DF71E70141E1712449CDC1AC7D07F6
+
+I=55
+KEY=33CE6BA566AFE673CEB5EDEA8804B2A8
+CT=54DF71E70141E1712449CDC1AC7D07F6
+PT=AF3DE6F3510978928C129CFC19FB29B4
+
+I=56
+KEY=9CF38D5637A69EE142A7711691FF9B1C
+CT=AF3DE6F3510978928C129CFC19FB29B4
+PT=830DB7014774C7DF870C8456BC0162AB
+
+I=57
+KEY=1FFE3A5770D2593EC5ABF5402DFEF9B7
+CT=830DB7014774C7DF870C8456BC0162AB
+PT=6606C0A36A18BEFF33485F95B82C30E7
+
+I=58
+KEY=79F8FAF41ACAE7C1F6E3AAD595D2C950
+CT=6606C0A36A18BEFF33485F95B82C30E7
+PT=4B1E64672B89056DF693E73B419E786E
+
+I=59
+KEY=32E69E933143E2AC00704DEED44CB13E
+CT=4B1E64672B89056DF693E73B419E786E
+PT=1877DEEAFF10A5A3F5E9A811BF7595BA
+
+I=60
+KEY=2A914079CE53470FF599E5FF6B392484
+CT=1877DEEAFF10A5A3F5E9A811BF7595BA
+PT=A11A48215BF59CC53BC8A009DCA3973D
+
+I=61
+KEY=8B8B085895A6DBCACE5145F6B79AB3B9
+CT=A11A48215BF59CC53BC8A009DCA3973D
+PT=E80535676DE8898A3624B8127EC21024
+
+I=62
+KEY=638E3D3FF84E5240F875FDE4C958A39D
+CT=E80535676DE8898A3624B8127EC21024
+PT=E2977A804EC9A8B03C85234AD3A95B52
+
+I=63
+KEY=811947BFB687FAF0C4F0DEAE1AF1F8CF
+CT=E2977A804EC9A8B03C85234AD3A95B52
+PT=D776D8BF13F736483862328571C06C61
+
+I=64
+KEY=566F9F00A570CCB8FC92EC2B6B3194AE
+CT=D776D8BF13F736483862328571C06C61
+PT=3AF7969F3247A0914037209556997164
+
+I=65
+KEY=6C98099F97376C29BCA5CCBE3DA8E5CA
+CT=3AF7969F3247A0914037209556997164
+PT=4F87DDC715CEE3A9D67645AD920DF74A
+
+I=66
+KEY=231FD45882F98F806AD38913AFA51280
+CT=4F87DDC715CEE3A9D67645AD920DF74A
+PT=9E88CA52E6B0C160E52B23F36882DBA1
+
+I=67
+KEY=BD971E0A64494EE08FF8AAE0C727C921
+CT=9E88CA52E6B0C160E52B23F36882DBA1
+PT=CAD26E5881D9D4E52C7595C773E0FDAB
+
+I=68
+KEY=77457052E5909A05A38D3F27B4C7348A
+CT=CAD26E5881D9D4E52C7595C773E0FDAB
+PT=C2D0B3D713CFCA5ABB7B9DED14429F37
+
+I=69
+KEY=B595C385F65F505F18F6A2CAA085ABBD
+CT=C2D0B3D713CFCA5ABB7B9DED14429F37
+PT=DD7AADA7524A4878F7C598C4CBCD9CAB
+
+I=70
+KEY=68EF6E22A4151827EF333A0E6B483716
+CT=DD7AADA7524A4878F7C598C4CBCD9CAB
+PT=A0F33B1FCC3F4A4B0982F0823C4ED3C9
+
+I=71
+KEY=C81C553D682A526CE6B1CA8C5706E4DF
+CT=A0F33B1FCC3F4A4B0982F0823C4ED3C9
+PT=B22BB23CD68E8779A8C0FC9A350CB756
+
+I=72
+KEY=7A37E701BEA4D5154E713616620A5389
+CT=B22BB23CD68E8779A8C0FC9A350CB756
+PT=EA4D96AC54BD8387AD36AC8C855A9D44
+
+I=73
+KEY=907A71ADEA195692E3479A9AE750CECD
+CT=EA4D96AC54BD8387AD36AC8C855A9D44
+PT=A3B90CFDE355723BC94999784534FA74
+
+I=74
+KEY=33C37D50094C24A92A0E03E2A26434B9
+CT=A3B90CFDE355723BC94999784534FA74
+PT=55636C86A64383768CB948FF57B29322
+
+I=75
+KEY=66A011D6AF0FA7DFA6B74B1DF5D6A79B
+CT=55636C86A64383768CB948FF57B29322
+PT=B29CCDFD8E7BE50892F0D77DD969F97E
+
+I=76
+KEY=D43CDC2B217442D734479C602CBF5EE5
+CT=B29CCDFD8E7BE50892F0D77DD969F97E
+PT=9CF0432822EABDF489B57EDD9CEF7FEA
+
+I=77
+KEY=48CC9F03039EFF23BDF2E2BDB050210F
+CT=9CF0432822EABDF489B57EDD9CEF7FEA
+PT=AA753B7D38E807D691005899385DC6DA
+
+I=78
+KEY=E2B9A47E3B76F8F52CF2BA24880DE7D5
+CT=AA753B7D38E807D691005899385DC6DA
+PT=E4F0681527FA7AD3D1E7C78C03FB79FA
+
+I=79
+KEY=0649CC6B1C8C8226FD157DA88BF69E2F
+CT=E4F0681527FA7AD3D1E7C78C03FB79FA
+PT=7923AF8E50F378B9C97D2F162348025B
+
+I=80
+KEY=7F6A63E54C7FFA9F346852BEA8BE9C74
+CT=7923AF8E50F378B9C97D2F162348025B
+PT=3BEFAB920CA31A6B8B87E11DF97B42DE
+
+I=81
+KEY=4485C87740DCE0F4BFEFB3A351C5DEAA
+CT=3BEFAB920CA31A6B8B87E11DF97B42DE
+PT=4661D6B8004611976A21C69804D102C0
+
+I=82
+KEY=02E41ECF409AF163D5CE753B5514DC6A
+CT=4661D6B8004611976A21C69804D102C0
+PT=B861DF2279F2AEE4FCFD7D322AD0BE2B
+
+I=83
+KEY=BA85C1ED39685F87293308097FC46241
+CT=B861DF2279F2AEE4FCFD7D322AD0BE2B
+PT=1785745618A541F9454443FFB494F2E9
+
+I=84
+KEY=AD00B5BB21CD1E7E6C774BF6CB5090A8
+CT=1785745618A541F9454443FFB494F2E9
+PT=AA7507A80B4CCF33E8B4F09E2D7004F6
+
+I=85
+KEY=0775B2132A81D14D84C3BB68E620945E
+CT=AA7507A80B4CCF33E8B4F09E2D7004F6
+PT=433412B8F10F81A557AC461823097FC7
+
+I=86
+KEY=4441A0ABDB8E50E8D36FFD70C529EB99
+CT=433412B8F10F81A557AC461823097FC7
+PT=EC3206BDB3765876B74952C411D40373
+
+I=87
+KEY=A873A61668F8089E6426AFB4D4FDE8EA
+CT=EC3206BDB3765876B74952C411D40373
+PT=F7F994027D328FA3D70C9DEABD3BE733
+
+I=88
+KEY=5F8A321415CA873DB32A325E69C60FD9
+CT=F7F994027D328FA3D70C9DEABD3BE733
+PT=E2A8419BF86A2408ED8D0274A5CE0E10
+
+I=89
+KEY=BD22738FEDA0A3355EA7302ACC0801C9
+CT=E2A8419BF86A2408ED8D0274A5CE0E10
+PT=80FB8CD5243C89D77F503B2F16979F90
+
+I=90
+KEY=3DD9FF5AC99C2AE221F70B05DA9F9E59
+CT=80FB8CD5243C89D77F503B2F16979F90
+PT=F7773137F233AE2609C2C9AC36F58224
+
+I=91
+KEY=CAAECE6D3BAF84C42835C2A9EC6A1C7D
+CT=F7773137F233AE2609C2C9AC36F58224
+PT=F3D0A1DADA4A009E8E4C0EF717469BCD
+
+I=92
+KEY=397E6FB7E1E5845AA679CC5EFB2C87B0
+CT=F3D0A1DADA4A009E8E4C0EF717469BCD
+PT=0AC0FF22EB653A26A3F1F0CFE3808609
+
+I=93
+KEY=33BE90950A80BE7C05883C9118AC01B9
+CT=0AC0FF22EB653A26A3F1F0CFE3808609
+PT=28FF865CE11720BB1B56EF49D7D1840D
+
+I=94
+KEY=1B4116C9EB979EC71EDED3D8CF7D85B4
+CT=28FF865CE11720BB1B56EF49D7D1840D
+PT=001FAF58E22F5E8ED6BCC7FD581D7C2F
+
+I=95
+KEY=1B5EB99109B8C049C86214259760F99B
+CT=001FAF58E22F5E8ED6BCC7FD581D7C2F
+PT=32B41303A58AB49CB4CB2322B77383B3
+
+I=96
+KEY=29EAAA92AC3274D57CA9370720137A28
+CT=32B41303A58AB49CB4CB2322B77383B3
+PT=9C52020FCDE0306C8E19CDF68FEFDF50
+
+I=97
+KEY=B5B8A89D61D244B9F2B0FAF1AFFCA578
+CT=9C52020FCDE0306C8E19CDF68FEFDF50
+PT=2E3452997687D12E3A8C59B9178B09E2
+
+I=98
+KEY=9B8CFA0417559597C83CA348B877AC9A
+CT=2E3452997687D12E3A8C59B9178B09E2
+PT=872CF16DBB7CD6EA8EBB91A60BDE0C6F
+
+I=99
+KEY=1CA00B69AC29437D468732EEB3A9A0F5
+CT=872CF16DBB7CD6EA8EBB91A60BDE0C6F
+PT=7862C78E3B209535E6C6BE92F5EDF42B
+
+I=100
+KEY=64C2CCE79709D648A0418C7C464454DE
+CT=7862C78E3B209535E6C6BE92F5EDF42B
+PT=9185D8487C1D2DB679A52FDA2FE5FFCD
+
+I=101
+KEY=F54714AFEB14FBFED9E4A3A669A1AB13
+CT=9185D8487C1D2DB679A52FDA2FE5FFCD
+PT=77C3AF8C81CDB1CDEF5C0429CF3E5DA4
+
+I=102
+KEY=8284BB236AD94A3336B8A78FA69FF6B7
+CT=77C3AF8C81CDB1CDEF5C0429CF3E5DA4
+PT=6F36C74290EA6332E98CD23D08AEF7F9
+
+I=103
+KEY=EDB27C61FA332901DF3475B2AE31014E
+CT=6F36C74290EA6332E98CD23D08AEF7F9
+PT=4A7831538FA1D32E3F8631BEFD99AA73
+
+I=104
+KEY=A7CA4D327592FA2FE0B2440C53A8AB3D
+CT=4A7831538FA1D32E3F8631BEFD99AA73
+PT=5D2B599D9AF9054A99C25577C9286C9E
+
+I=105
+KEY=FAE114AFEF6BFF657970117B9A80C7A3
+CT=5D2B599D9AF9054A99C25577C9286C9E
+PT=65E4088200BCC01FCEE39C6E42082FD8
+
+I=106
+KEY=9F051C2DEFD73F7AB7938D15D888E87B
+CT=65E4088200BCC01FCEE39C6E42082FD8
+PT=4588E0D3AABBEFE611B9576391B903E9
+
+I=107
+KEY=DA8DFCFE456CD09CA62ADA764931EB92
+CT=4588E0D3AABBEFE611B9576391B903E9
+PT=A55622F833FF271DD8A8F01CF5828FCF
+
+I=108
+KEY=7FDBDE067693F7817E822A6ABCB3645D
+CT=A55622F833FF271DD8A8F01CF5828FCF
+PT=8C954010C870B2DB7FA44E1DEBFE6DE8
+
+I=109
+KEY=F34E9E16BEE3455A01266477574D09B5
+CT=8C954010C870B2DB7FA44E1DEBFE6DE8
+PT=58B7BD00ED18FC81E618807DE65305B8
+
+I=110
+KEY=ABF9231653FBB9DBE73EE40AB11E0C0D
+CT=58B7BD00ED18FC81E618807DE65305B8
+PT=EF82E5F4879039F2A1A4CC2F2044BD14
+
+I=111
+KEY=447BC6E2D46B8029469A2825915AB119
+CT=EF82E5F4879039F2A1A4CC2F2044BD14
+PT=2B6C12307F14FD50B41D8F972B19AC76
+
+I=112
+KEY=6F17D4D2AB7F7D79F287A7B2BA431D6F
+CT=2B6C12307F14FD50B41D8F972B19AC76
+PT=C9B6D042CE76892D17F70D4EE00A0D79
+
+I=113
+KEY=A6A104906509F454E570AAFC5A491016
+CT=C9B6D042CE76892D17F70D4EE00A0D79
+PT=1B08F9293BBFC44DDCF2C1D26A9DD00B
+
+I=114
+KEY=BDA9FDB95EB6301939826B2E30D4C01D
+CT=1B08F9293BBFC44DDCF2C1D26A9DD00B
+PT=4FD353B247048FAAA728E10C691C70CA
+
+I=115
+KEY=F27AAE0B19B2BFB39EAA8A2259C8B0D7
+CT=4FD353B247048FAAA728E10C691C70CA
+PT=0BBB6FDBC62C428B85111BC7C93AE994
+
+I=116
+KEY=F9C1C1D0DF9EFD381BBB91E590F25943
+CT=0BBB6FDBC62C428B85111BC7C93AE994
+PT=9C1A213A5772DE6C15CE7406F84BED03
+
+I=117
+KEY=65DBE0EA88EC23540E75E5E368B9B440
+CT=9C1A213A5772DE6C15CE7406F84BED03
+PT=AB3DE06BBDB213D64F735CA990DC373C
+
+I=118
+KEY=CEE60081355E30824106B94AF865837C
+CT=AB3DE06BBDB213D64F735CA990DC373C
+PT=6C004A1A114E90C7903AA4A0120A2B10
+
+I=119
+KEY=A2E64A9B2410A045D13C1DEAEA6FA86C
+CT=6C004A1A114E90C7903AA4A0120A2B10
+PT=6405A033C294E72119A8955712548121
+
+I=120
+KEY=C6E3EAA8E6844764C89488BDF83B294D
+CT=6405A033C294E72119A8955712548121
+PT=AE8A3BAC7279B1BC152A5AD8EBAC3EAD
+
+I=121
+KEY=6869D10494FDF6D8DDBED265139717E0
+CT=AE8A3BAC7279B1BC152A5AD8EBAC3EAD
+PT=4ADDA9999D2BE20D8925F39699563294
+
+I=122
+KEY=22B4789D09D614D5549B21F38AC12574
+CT=4ADDA9999D2BE20D8925F39699563294
+PT=BC5CA33CB2A1A580EB92946C77A63467
+
+I=123
+KEY=9EE8DBA1BB77B155BF09B59FFD671113
+CT=BC5CA33CB2A1A580EB92946C77A63467
+PT=F7ABEAD301264A3E59EABA0B9606DC92
+
+I=124
+KEY=69433172BA51FB6BE6E30F946B61CD81
+CT=F7ABEAD301264A3E59EABA0B9606DC92
+PT=2566114A10BE9BF19E0910486DAB6BE5
+
+I=125
+KEY=4C252038AAEF609A78EA1FDC06CAA664
+CT=2566114A10BE9BF19E0910486DAB6BE5
+PT=AF72E1B179660A1B833D9D4FC8473B6B
+
+I=126
+KEY=E357C189D3896A81FBD78293CE8D9D0F
+CT=AF72E1B179660A1B833D9D4FC8473B6B
+PT=DFF968B761D8E154B74C9D568C12008E
+
+I=127
+KEY=3CAEA93EB2518BD54C9B1FC5429F9D81
+CT=DFF968B761D8E154B74C9D568C12008E
+PT=42DF098BCB57D0D25269E29C9BC99DE6
+
+I=128
+KEY=7E71A0B579065B071EF2FD59D9560067
+CT=42DF098BCB57D0D25269E29C9BC99DE6
+PT=66C34CAAEFC2009B985D1E622FC61AB4
+
+I=129
+KEY=18B2EC1F96C45B9C86AFE33BF6901AD3
+CT=66C34CAAEFC2009B985D1E622FC61AB4
+PT=150C1BF943982C5EA1A6839D94F23288
+
+I=130
+KEY=0DBEF7E6D55C77C2270960A66262285B
+CT=150C1BF943982C5EA1A6839D94F23288
+PT=048BFBB28879206964C5F3B41264011A
+
+I=131
+KEY=09350C545D2557AB43CC931270062941
+CT=048BFBB28879206964C5F3B41264011A
+PT=54D2DC53B87EC949F0FA0E134EE26D50
+
+I=132
+KEY=5DE7D007E55B9EE2B3369D013EE44411
+CT=54D2DC53B87EC949F0FA0E134EE26D50
+PT=1BA46AFE1AE87C4F0254BF02DF3B6D37
+
+I=133
+KEY=4643BAF9FFB3E2ADB1622203E1DF2926
+CT=1BA46AFE1AE87C4F0254BF02DF3B6D37
+PT=7733E74E743C9E997AC2ED36B2E89CE8
+
+I=134
+KEY=31705DB78B8F7C34CBA0CF355337B5CE
+CT=7733E74E743C9E997AC2ED36B2E89CE8
+PT=670AEA160FAC67ABCECA140EB8195EB5
+
+I=135
+KEY=567AB7A184231B9F056ADB3BEB2EEB7B
+CT=670AEA160FAC67ABCECA140EB8195EB5
+PT=7CFD74D510AC894FF5B698280386F4FF
+
+I=136
+KEY=2A87C374948F92D0F0DC4313E8A81F84
+CT=7CFD74D510AC894FF5B698280386F4FF
+PT=10D03F32C0694E9FFF598E101998105E
+
+I=137
+KEY=3A57FC4654E6DC4F0F85CD03F1300FDA
+CT=10D03F32C0694E9FFF598E101998105E
+PT=351D6E8D1C26F36973356F6235B8ABAD
+
+I=138
+KEY=0F4A92CB48C02F267CB0A261C488A477
+CT=351D6E8D1C26F36973356F6235B8ABAD
+PT=0DDDA7AA09FBD986C0B9EA2B018FAE4F
+
+I=139
+KEY=02973561413BF6A0BC09484AC5070A38
+CT=0DDDA7AA09FBD986C0B9EA2B018FAE4F
+PT=31C5B68B7A08D1B7320FAB052CC3B0D1
+
+I=140
+KEY=335283EA3B3327178E06E34FE9C4BAE9
+CT=31C5B68B7A08D1B7320FAB052CC3B0D1
+PT=501B8D9EE91468522029020A39484DB5
+
+I=141
+KEY=63490E74D2274F45AE2FE145D08CF75C
+CT=501B8D9EE91468522029020A39484DB5
+PT=2714FBA566DFD4909B8ABF29B1D5A8E8
+
+I=142
+KEY=445DF5D1B4F89BD535A55E6C61595FB4
+CT=2714FBA566DFD4909B8ABF29B1D5A8E8
+PT=94485381E5088D67BC1335C89FA5C2B8
+
+I=143
+KEY=D015A65051F016B289B66BA4FEFC9D0C
+CT=94485381E5088D67BC1335C89FA5C2B8
+PT=BE5BEE26D6686A0EB5838C237FEF79B7
+
+I=144
+KEY=6E4E487687987CBC3C35E7878113E4BB
+CT=BE5BEE26D6686A0EB5838C237FEF79B7
+PT=417F73D46CFBE3C5C9AD513BCBC6D185
+
+I=145
+KEY=2F313BA2EB639F79F598B6BC4AD5353E
+CT=417F73D46CFBE3C5C9AD513BCBC6D185
+PT=AE3B07350B3BE7D4F9F6FE2F95622449
+
+I=146
+KEY=810A3C97E05878AD0C6E4893DFB71177
+CT=AE3B07350B3BE7D4F9F6FE2F95622449
+PT=7BD4231225A7B665953AB034E24A7C7A
+
+I=147
+KEY=FADE1F85C5FFCEC89954F8A73DFD6D0D
+CT=7BD4231225A7B665953AB034E24A7C7A
+PT=3C1FBE8F3CEB1438B4A64E59FAF291CF
+
+I=148
+KEY=C6C1A10AF914DAF02DF2B6FEC70FFCC2
+CT=3C1FBE8F3CEB1438B4A64E59FAF291CF
+PT=ACFF7F1E71AA952CF8ADB24FEE18A7BB
+
+I=149
+KEY=6A3EDE1488BE4FDCD55F04B129175B79
+CT=ACFF7F1E71AA952CF8ADB24FEE18A7BB
+PT=3C3A6D3FD73B36317417106A92E2B43E
+
+I=150
+KEY=5604B32B5F8579EDA14814DBBBF5EF47
+CT=3C3A6D3FD73B36317417106A92E2B43E
+PT=F34F8C719A4A74DD8F4FA4CBC520827A
+
+I=151
+KEY=A54B3F5AC5CF0D302E07B0107ED56D3D
+CT=F34F8C719A4A74DD8F4FA4CBC520827A
+PT=6A5D56FB6C7EBA15112AF8A093F3E1E1
+
+I=152
+KEY=CF1669A1A9B1B7253F2D48B0ED268CDC
+CT=6A5D56FB6C7EBA15112AF8A093F3E1E1
+PT=8BF39EE3B8ED0F6A6EA92319A81B10E6
+
+I=153
+KEY=44E5F742115CB84F51846BA9453D9C3A
+CT=8BF39EE3B8ED0F6A6EA92319A81B10E6
+PT=2BC796D320C444BBBAD466D686F460F6
+
+I=154
+KEY=6F2261913198FCF4EB500D7FC3C9FCCC
+CT=2BC796D320C444BBBAD466D686F460F6
+PT=2CF595F424ED50B1A146E387B128CBA3
+
+I=155
+KEY=43D7F4651575AC454A16EEF872E1376F
+CT=2CF595F424ED50B1A146E387B128CBA3
+PT=56F2E856045BAE66EA003A6C39205344
+
+I=156
+KEY=15251C33112E0223A016D4944BC1642B
+CT=56F2E856045BAE66EA003A6C39205344
+PT=31C83401BD83424BA6E94C0D6D453D9A
+
+I=157
+KEY=24ED2832ACAD406806FF9899268459B1
+CT=31C83401BD83424BA6E94C0D6D453D9A
+PT=A687F05992CCB57CDE61AFF8878913ED
+
+I=158
+KEY=826AD86B3E61F514D89E3761A10D4A5C
+CT=A687F05992CCB57CDE61AFF8878913ED
+PT=16E771193C2473502F415C27FB101D94
+
+I=159
+KEY=948DA97202458644F7DF6B465A1D57C8
+CT=16E771193C2473502F415C27FB101D94
+PT=C69CDBA29C9EDC3407C1C73A756A0B6E
+
+I=160
+KEY=521172D09EDB5A70F01EAC7C2F775CA6
+CT=C69CDBA29C9EDC3407C1C73A756A0B6E
+PT=566D82281F48E3217F3852115CF2E944
+
+I=161
+KEY=047CF0F88193B9518F26FE6D7385B5E2
+CT=566D82281F48E3217F3852115CF2E944
+PT=B3FEBC8F8F0F0B652C4358BCC9BF54DF
+
+I=162
+KEY=B7824C770E9CB234A365A6D1BA3AE13D
+CT=B3FEBC8F8F0F0B652C4358BCC9BF54DF
+PT=BBB84877094B3EB86203D17C92CF5168
+
+I=163
+KEY=0C3A040007D78C8CC16677AD28F5B055
+CT=BBB84877094B3EB86203D17C92CF5168
+PT=2C45E5A3F8C564862DA4D8AD428D3E67
+
+I=164
+KEY=207FE1A3FF12E80AECC2AF006A788E32
+CT=2C45E5A3F8C564862DA4D8AD428D3E67
+PT=10ADC2AF56600D95AD8BB579EF5170C9
+
+I=165
+KEY=30D2230CA972E59F41491A798529FEFB
+CT=10ADC2AF56600D95AD8BB579EF5170C9
+PT=1854BB8AC568F3599153BE1AC60BA78D
+
+I=166
+KEY=288698866C1A16C6D01AA46343225976
+CT=1854BB8AC568F3599153BE1AC60BA78D
+PT=E641765C80D8812A1A0F4606C639642E
+
+I=167
+KEY=CEC7EEDAECC297ECCA15E265851B3D58
+CT=E641765C80D8812A1A0F4606C639642E
+PT=317AC70CEAA87AE66A15C22BD5E534E5
+
+I=168
+KEY=FFBD29D6066AED0AA000204E50FE09BD
+CT=317AC70CEAA87AE66A15C22BD5E534E5
+PT=BFFB8D7B3D9F54727944ABC3F6474362
+
+I=169
+KEY=4046A4AD3BF5B978D9448B8DA6B94ADF
+CT=BFFB8D7B3D9F54727944ABC3F6474362
+PT=060765D1D9D289B862DA274CFDB4D7A0
+
+I=170
+KEY=4641C17CE22730C0BB9EACC15B0D9D7F
+CT=060765D1D9D289B862DA274CFDB4D7A0
+PT=FBAFA4C1D6CEF2A45E9E084311FDF858
+
+I=171
+KEY=BDEE65BD34E9C264E500A4824AF06527
+CT=FBAFA4C1D6CEF2A45E9E084311FDF858
+PT=F7F36BFDA77362B470B0B074241C58E9
+
+I=172
+KEY=4A1D0E40939AA0D095B014F66EEC3DCE
+CT=F7F36BFDA77362B470B0B074241C58E9
+PT=2FC236EDCD573A6DCFBA7930E9CF4698
+
+I=173
+KEY=65DF38AD5ECD9ABD5A0A6DC687237B56
+CT=2FC236EDCD573A6DCFBA7930E9CF4698
+PT=949A9994DC976595BFACA5F31116A165
+
+I=174
+KEY=F145A139825AFF28E5A6C8359635DA33
+CT=949A9994DC976595BFACA5F31116A165
+PT=19373CA9D519BF83EAA4C17E1EE8225C
+
+I=175
+KEY=E8729D90574340AB0F02094B88DDF86F
+CT=19373CA9D519BF83EAA4C17E1EE8225C
+PT=685C783918997A7572B0A09315F1F2DB
+
+I=176
+KEY=802EE5A94FDA3ADE7DB2A9D89D2C0AB4
+CT=685C783918997A7572B0A09315F1F2DB
+PT=FC0CB1792EADB7E8DECB021A435DE1E7
+
+I=177
+KEY=7C2254D061778D36A379ABC2DE71EB53
+CT=FC0CB1792EADB7E8DECB021A435DE1E7
+PT=797C5E5B4F3B38E7C72FF7AAAB270E86
+
+I=178
+KEY=055E0A8B2E4CB5D164565C687556E5D5
+CT=797C5E5B4F3B38E7C72FF7AAAB270E86
+PT=A5AB675262EA186F777681647B6AA1F9
+
+I=179
+KEY=A0F56DD94CA6ADBE1320DD0C0E3C442C
+CT=A5AB675262EA186F777681647B6AA1F9
+PT=08CDF6AF55BBB247D0DE1A69CD041A78
+
+I=180
+KEY=A8389B76191D1FF9C3FEC765C3385E54
+CT=08CDF6AF55BBB247D0DE1A69CD041A78
+PT=DED1F3C30AB5EC3455C7B6A756E5FF03
+
+I=181
+KEY=76E968B513A8F3CD963971C295DDA157
+CT=DED1F3C30AB5EC3455C7B6A756E5FF03
+PT=C759A17B354D668D1BA5541D16241D9F
+
+I=182
+KEY=B1B0C9CE26E595408D9C25DF83F9BCC8
+CT=C759A17B354D668D1BA5541D16241D9F
+PT=97E011FE7B327B8292270D4CD18BD9AC
+
+I=183
+KEY=2650D8305DD7EEC21FBB289352726564
+CT=97E011FE7B327B8292270D4CD18BD9AC
+PT=9F004E4282F790C06681F16262EF78CF
+
+I=184
+KEY=B9509672DF207E02793AD9F1309D1DAB
+CT=9F004E4282F790C06681F16262EF78CF
+PT=6B34AA95EFD874915DAE275CE34A04B9
+
+I=185
+KEY=D2643CE730F80A932494FEADD3D71912
+CT=6B34AA95EFD874915DAE275CE34A04B9
+PT=96966D118C50B67849F93B109492B5EB
+
+I=186
+KEY=44F251F6BCA8BCEB6D6DC5BD4745ACF9
+CT=96966D118C50B67849F93B109492B5EB
+PT=2CA6F85E4F29BE884392A0FEDD08D5A7
+
+I=187
+KEY=6854A9A8F38102632EFF65439A4D795E
+CT=2CA6F85E4F29BE884392A0FEDD08D5A7
+PT=21B71D4F23DDC002CAAFB7426009BD27
+
+I=188
+KEY=49E3B4E7D05CC261E450D201FA44C479
+CT=21B71D4F23DDC002CAAFB7426009BD27
+PT=BF059F1945E9E51B22B308849757B475
+
+I=189
+KEY=F6E62BFE95B5277AC6E3DA856D13700C
+CT=BF059F1945E9E51B22B308849757B475
+PT=434F4E756A3178472E12B80A1C2ED83E
+
+I=190
+KEY=B5A9658BFF845F3DE8F1628F713DA832
+CT=434F4E756A3178472E12B80A1C2ED83E
+PT=37DB2B0D5967700CDE348FB60661A6D4
+
+I=191
+KEY=82724E86A6E32F3136C5ED39775C0EE6
+CT=37DB2B0D5967700CDE348FB60661A6D4
+PT=D31C5130F8F217AC0014B5F37B9BB86B
+
+I=192
+KEY=516E1FB65E11389D36D158CA0CC7B68D
+CT=D31C5130F8F217AC0014B5F37B9BB86B
+PT=3B8CD15967907F9C617697EBEF395B16
+
+I=193
+KEY=6AE2CEEF3981470157A7CF21E3FEED9B
+CT=3B8CD15967907F9C617697EBEF395B16
+PT=AF17B5E5236BF46576379CD4E5AF8A34
+
+I=194
+KEY=C5F57B0A1AEAB364219053F5065167AF
+CT=AF17B5E5236BF46576379CD4E5AF8A34
+PT=88286D6FB237181EC239C1D70C0D6675
+
+I=195
+KEY=4DDD1665A8DDAB7AE3A992220A5C01DA
+CT=88286D6FB237181EC239C1D70C0D6675
+PT=8A5207BB1283343B3692045183451A7D
+
+I=196
+KEY=C78F11DEBA5E9F41D53B967389191BA7
+CT=8A5207BB1283343B3692045183451A7D
+PT=53C12FAC4B0185AA0CE067FC67EC5B9C
+
+I=197
+KEY=944E3E72F15F1AEBD9DBF18FEEF5403B
+CT=53C12FAC4B0185AA0CE067FC67EC5B9C
+PT=BBA2BB9B1CA48D2E97E0C39E500EB9C0
+
+I=198
+KEY=2FEC85E9EDFB97C54E3B3211BEFBF9FB
+CT=BBA2BB9B1CA48D2E97E0C39E500EB9C0
+PT=8BA2341064B7B5184CD7E7A40FA0358E
+
+I=199
+KEY=A44EB1F9894C22DD02ECD5B5B15BCC75
+CT=8BA2341064B7B5184CD7E7A40FA0358E
+PT=97121EEEA68CC6200FBC0B311849E625
+
+I=200
+KEY=335CAF172FC0E4FD0D50DE84A9122A50
+CT=97121EEEA68CC6200FBC0B311849E625
+PT=027FA370A9412B342043A15F19294961
+
+I=201
+KEY=31230C678681CFC92D137FDBB03B6331
+CT=027FA370A9412B342043A15F19294961
+PT=72CFBE6BA03AB28A53A6727717D1199A
+
+I=202
+KEY=43ECB20C26BB7D437EB50DACA7EA7AAB
+CT=72CFBE6BA03AB28A53A6727717D1199A
+PT=7A15B1B4B4ED35F9C208500FE7C4C1C7
+
+I=203
+KEY=39F903B8925648BABCBD5DA3402EBB6C
+CT=7A15B1B4B4ED35F9C208500FE7C4C1C7
+PT=AF46496D09254FAB5F381E93EEB4FBB0
+
+I=204
+KEY=96BF4AD59B730711E3854330AE9A40DC
+CT=AF46496D09254FAB5F381E93EEB4FBB0
+PT=ADA064E0F4324E8B0C062F6E33C7D016
+
+I=205
+KEY=3B1F2E356F41499AEF836C5E9D5D90CA
+CT=ADA064E0F4324E8B0C062F6E33C7D016
+PT=7723A61733BD5BBFAB8C559ED379B8B5
+
+I=206
+KEY=4C3C88225CFC1225440F39C04E24287F
+CT=7723A61733BD5BBFAB8C559ED379B8B5
+PT=5D210E8F35DD863316E89FADA70E8392
+
+I=207
+KEY=111D86AD6921941652E7A66DE92AABED
+CT=5D210E8F35DD863316E89FADA70E8392
+PT=92B1D20E7D87787950990052DE2ABA4F
+
+I=208
+KEY=83AC54A314A6EC6F027EA63F370011A2
+CT=92B1D20E7D87787950990052DE2ABA4F
+PT=178E494D23AA6AC13AC180727C47FD2A
+
+I=209
+KEY=94221DEE370C86AE38BF264D4B47EC88
+CT=178E494D23AA6AC13AC180727C47FD2A
+PT=CB9C10817C059D5BE4F123576FF459C6
+
+I=210
+KEY=5FBE0D6F4B091BF5DC4E051A24B3B54E
+CT=CB9C10817C059D5BE4F123576FF459C6
+PT=4934C56CC7BAF0A8DEBB62CFB2B0DEBF
+
+I=211
+KEY=168AC8038CB3EB5D02F567D596036BF1
+CT=4934C56CC7BAF0A8DEBB62CFB2B0DEBF
+PT=F6F2A4B90B357D88401702C968D9EC02
+
+I=212
+KEY=E0786CBA878696D542E2651CFEDA87F3
+CT=F6F2A4B90B357D88401702C968D9EC02
+PT=06A35CAD7B36751BEE345C33112EB6D1
+
+I=213
+KEY=E6DB3017FCB0E3CEACD6392FEFF43122
+CT=06A35CAD7B36751BEE345C33112EB6D1
+PT=3244CDE10DF48795DA702CD8C2F4CABD
+
+I=214
+KEY=D49FFDF6F144645B76A615F72D00FB9F
+CT=3244CDE10DF48795DA702CD8C2F4CABD
+PT=47C06F5BEA8C3503512E0E200966C546
+
+I=215
+KEY=935F92AD1BC8515827881BD724663ED9
+CT=47C06F5BEA8C3503512E0E200966C546
+PT=68A077D25CBEA7F76B88D8C6A414D0CE
+
+I=216
+KEY=FBFFE57F4776F6AF4C00C3118072EE17
+CT=68A077D25CBEA7F76B88D8C6A414D0CE
+PT=DDF110C2C79B46C5132CCEF654280D7E
+
+I=217
+KEY=260EF5BD80EDB06A5F2C0DE7D45AE369
+CT=DDF110C2C79B46C5132CCEF654280D7E
+PT=0AB610A0082813076D052011C12DC924
+
+I=218
+KEY=2CB8E51D88C5A36D32292DF615772A4D
+CT=0AB610A0082813076D052011C12DC924
+PT=8C42F49EDAE1BD6B631E74B68B1B8444
+
+I=219
+KEY=A0FA118352241E06513759409E6CAE09
+CT=8C42F49EDAE1BD6B631E74B68B1B8444
+PT=B5A5B6E50B3A066D16DF883F353019FE
+
+I=220
+KEY=155FA766591E186B47E8D17FAB5CB7F7
+CT=B5A5B6E50B3A066D16DF883F353019FE
+PT=70CFA25AFC9919937E2FC90900F0B398
+
+I=221
+KEY=6590053CA58701F839C71876ABAC046F
+CT=70CFA25AFC9919937E2FC90900F0B398
+PT=B927A5911AE33DEAB619DAFEE22CD0DF
+
+I=222
+KEY=DCB7A0ADBF643C128FDEC2884980D4B0
+CT=B927A5911AE33DEAB619DAFEE22CD0DF
+PT=10C548438C5B976EDD624129B2102D7A
+
+I=223
+KEY=CC72E8EE333FAB7C52BC83A1FB90F9CA
+CT=10C548438C5B976EDD624129B2102D7A
+PT=4549E45DA2F8FE82972DC7DF3548CAFF
+
+I=224
+KEY=893B0CB391C755FEC591447ECED83335
+CT=4549E45DA2F8FE82972DC7DF3548CAFF
+PT=2B85505E64089FEB6B5763011E778C96
+
+I=225
+KEY=A2BE5CEDF5CFCA15AEC6277FD0AFBFA3
+CT=2B85505E64089FEB6B5763011E778C96
+PT=4B157930F9A6EBE3D9D6AC9FADDEB35C
+
+I=226
+KEY=E9AB25DD0C6921F677108BE07D710CFF
+CT=4B157930F9A6EBE3D9D6AC9FADDEB35C
+PT=12341C0FE9EB6757BFFCC4BC1A8F2585
+
+I=227
+KEY=FB9F39D2E58246A1C8EC4F5C67FE297A
+CT=12341C0FE9EB6757BFFCC4BC1A8F2585
+PT=5422D62D794B02FC04BE01198EE23ACE
+
+I=228
+KEY=AFBDEFFF9CC9445DCC524E45E91C13B4
+CT=5422D62D794B02FC04BE01198EE23ACE
+PT=42D43022FD6DB571BCB2FDE653C9068C
+
+I=229
+KEY=ED69DFDD61A4F12C70E0B3A3BAD51538
+CT=42D43022FD6DB571BCB2FDE653C9068C
+PT=80BD3AAED5D519B75D22BF060EF1DFC6
+
+I=230
+KEY=6DD4E573B471E89B2DC20CA5B424CAFE
+CT=80BD3AAED5D519B75D22BF060EF1DFC6
+PT=B72973F9016A348CDDCCFFC2DD291B5A
+
+I=231
+KEY=DAFD968AB51BDC17F00EF367690DD1A4
+CT=B72973F9016A348CDDCCFFC2DD291B5A
+PT=5692E61C86A7B2C043ABBED712390361
+
+I=232
+KEY=8C6F709633BC6ED7B3A54DB07B34D2C5
+CT=5692E61C86A7B2C043ABBED712390361
+PT=75138737269AA27855C2CFD2DCEDEFC4
+
+I=233
+KEY=F97CF7A11526CCAFE6678262A7D93D01
+CT=75138737269AA27855C2CFD2DCEDEFC4
+PT=A022AA28CECC4BB5EB28BA5B7828AB6E
+
+I=234
+KEY=595E5D89DBEA871A0D4F3839DFF1966F
+CT=A022AA28CECC4BB5EB28BA5B7828AB6E
+PT=17B0BF87EE02AA44705B1B1B4DF7D3F4
+
+I=235
+KEY=4EEEE20E35E82D5E7D1423229206459B
+CT=17B0BF87EE02AA44705B1B1B4DF7D3F4
+PT=095A5A041C43DCFEB5D0DF3E7659344A
+
+I=236
+KEY=47B4B80A29ABF1A0C8C4FC1CE45F71D1
+CT=095A5A041C43DCFEB5D0DF3E7659344A
+PT=9DCE0D1C572509F3367EE952B89044E5
+
+I=237
+KEY=DA7AB5167E8EF853FEBA154E5CCF3534
+CT=9DCE0D1C572509F3367EE952B89044E5
+PT=E6075BCC82399A91E52034EA2F197058
+
+I=238
+KEY=3C7DEEDAFCB762C21B9A21A473D6456C
+CT=E6075BCC82399A91E52034EA2F197058
+PT=431D243CEE96B424B0FA4FEC5E707036
+
+I=239
+KEY=7F60CAE61221D6E6AB606E482DA6355A
+CT=431D243CEE96B424B0FA4FEC5E707036
+PT=5EF70106A2EA454CA9405A8AA1B54EF0
+
+I=240
+KEY=2197CBE0B0CB93AA022034C28C137BAA
+CT=5EF70106A2EA454CA9405A8AA1B54EF0
+PT=09B003CB7E2ADDD587A2ABCDD03D234F
+
+I=241
+KEY=2827C82BCEE14E7F85829F0F5C2E58E5
+CT=09B003CB7E2ADDD587A2ABCDD03D234F
+PT=3647FAC6EF758113DC768E7737098DE9
+
+I=242
+KEY=1E6032ED2194CF6C59F411786B27D50C
+CT=3647FAC6EF758113DC768E7737098DE9
+PT=C043BD96A88492C85431B72C708C3C60
+
+I=243
+KEY=DE238F7B89105DA40DC5A6541BABE96C
+CT=C043BD96A88492C85431B72C708C3C60
+PT=299A25142A6B5D334158D359DD9CD574
+
+I=244
+KEY=F7B9AA6FA37B00974C9D750DC6373C18
+CT=299A25142A6B5D334158D359DD9CD574
+PT=21E56C2202C8D6F81EDC63A8A1EA4B6A
+
+I=245
+KEY=D65CC64DA1B3D66F524116A567DD7772
+CT=21E56C2202C8D6F81EDC63A8A1EA4B6A
+PT=FD3565957E3845065B7AEF27A900FDD5
+
+I=246
+KEY=2B69A3D8DF8B9369093BF982CEDD8AA7
+CT=FD3565957E3845065B7AEF27A900FDD5
+PT=A4DB9120D1ED0419342AFC2CBF114647
+
+I=247
+KEY=8FB232F80E6697703D1105AE71CCCCE0
+CT=A4DB9120D1ED0419342AFC2CBF114647
+PT=27FDDEA1E746BD217CFB4CD7A511BACE
+
+I=248
+KEY=A84FEC59E9202A5141EA4979D4DD762E
+CT=27FDDEA1E746BD217CFB4CD7A511BACE
+PT=6A9189FD46E47B22F151A213D023442B
+
+I=249
+KEY=C2DE65A4AFC45173B0BBEB6A04FE3205
+CT=6A9189FD46E47B22F151A213D023442B
+PT=1C729701404C76D5D7A156C39CF52542
+
+I=250
+KEY=DEACF2A5EF8827A6671ABDA9980B1747
+CT=1C729701404C76D5D7A156C39CF52542
+PT=6F97CB4564E0783DFE962DCB13FEDF72
+
+I=251
+KEY=B13B39E08B685F9B998C90628BF5C835
+CT=6F97CB4564E0783DFE962DCB13FEDF72
+PT=F818140A280299B182CDA37CBE9B27AB
+
+I=252
+KEY=49232DEAA36AC62A1B41331E356EEF9E
+CT=F818140A280299B182CDA37CBE9B27AB
+PT=20E9F2BE7017C2945005FD8A420A5B7D
+
+I=253
+KEY=69CADF54D37D04BE4B44CE947764B4E3
+CT=20E9F2BE7017C2945005FD8A420A5B7D
+PT=60BB97C634161EF6A36056193B6EDDB0
+
+I=254
+KEY=09714892E76B1A48E824988D4C0A6953
+CT=60BB97C634161EF6A36056193B6EDDB0
+PT=E4B9777B7390EF430A93FF7DD0B68CD4
+
+I=255
+KEY=EDC83FE994FBF50BE2B767F09CBCE587
+CT=E4B9777B7390EF430A93FF7DD0B68CD4
+PT=E5E3BD960CF15BBDB8A6C08711A884CF
+
+I=256
+KEY=082B827F980AAEB65A11A7778D146148
+CT=E5E3BD960CF15BBDB8A6C08711A884CF
+PT=71A6AEFD0181DCE69A116585044C7F66
+
+I=257
+KEY=798D2C82998B7250C000C2F289581E2E
+CT=71A6AEFD0181DCE69A116585044C7F66
+PT=8E9C1CFFDB8972617D74DA0E9ED065D1
+
+I=258
+KEY=F711307D42020031BD7418FC17887BFF
+CT=8E9C1CFFDB8972617D74DA0E9ED065D1
+PT=CE7882AB901A199910FC463A4D1D626A
+
+I=259
+KEY=3969B2D6D21819A8AD885EC65A951995
+CT=CE7882AB901A199910FC463A4D1D626A
+PT=2334546032E850D0029CB1AD6AFCEA7A
+
+I=260
+KEY=1A5DE6B6E0F04978AF14EF6B3069F3EF
+CT=2334546032E850D0029CB1AD6AFCEA7A
+PT=88B4CF0D4AB7BD00BE98DA1626063A69
+
+I=261
+KEY=92E929BBAA47F478118C357D166FC986
+CT=88B4CF0D4AB7BD00BE98DA1626063A69
+PT=5A7FF831F28E5EC4A11DA524E2323925
+
+I=262
+KEY=C896D18A58C9AABCB0919059F45DF0A3
+CT=5A7FF831F28E5EC4A11DA524E2323925
+PT=DF000551EF9BBD914969BD1B353BDC8C
+
+I=263
+KEY=1796D4DBB752172DF9F82D42C1662C2F
+CT=DF000551EF9BBD914969BD1B353BDC8C
+PT=1EECBC47697208193C354E28D23E8CE9
+
+I=264
+KEY=097A689CDE201F34C5CD636A1358A0C6
+CT=1EECBC47697208193C354E28D23E8CE9
+PT=DF85CD4B3F821A7411F9F5D1FDF9DB85
+
+I=265
+KEY=D6FFA5D7E1A20540D43496BBEEA17B43
+CT=DF85CD4B3F821A7411F9F5D1FDF9DB85
+PT=038E765F1910D8C0C1251254605218F2
+
+I=266
+KEY=D571D388F8B2DD80151184EF8EF363B1
+CT=038E765F1910D8C0C1251254605218F2
+PT=FBA8FE850294EEAEE75F56C974BF7DE4
+
+I=267
+KEY=2ED92D0DFA26332EF24ED226FA4C1E55
+CT=FBA8FE850294EEAEE75F56C974BF7DE4
+PT=47F9D6F7A3E2A1BFA360EA1BA8B0450E
+
+I=268
+KEY=6920FBFA59C49291512E383D52FC5B5B
+CT=47F9D6F7A3E2A1BFA360EA1BA8B0450E
+PT=FD6F4A4825DE5E776BFD569223CB5A2C
+
+I=269
+KEY=944FB1B27C1ACCE63AD36EAF71370177
+CT=FD6F4A4825DE5E776BFD569223CB5A2C
+PT=10430ED7EE0FDB8FBC348F8E08286622
+
+I=270
+KEY=840CBF659215176986E7E121791F6755
+CT=10430ED7EE0FDB8FBC348F8E08286622
+PT=4B75D5C573185303B01EB649884758B1
+
+I=271
+KEY=CF796AA0E10D446A36F95768F1583FE4
+CT=4B75D5C573185303B01EB649884758B1
+PT=85CCA4271A941517D55D05B4F29527C3
+
+I=272
+KEY=4AB5CE87FB99517DE3A452DC03CD1827
+CT=85CCA4271A941517D55D05B4F29527C3
+PT=615EA2D44C52D639B6AD05D621B4A1A6
+
+I=273
+KEY=2BEB6C53B7CB87445509570A2279B981
+CT=615EA2D44C52D639B6AD05D621B4A1A6
+PT=1DFD1E93D34ABFE45BA6BF6BD3FBF30E
+
+I=274
+KEY=361672C0648138A00EAFE861F1824A8F
+CT=1DFD1E93D34ABFE45BA6BF6BD3FBF30E
+PT=B65C3F09FFFF752DEE2F8F2D441A51CA
+
+I=275
+KEY=804A4DC99B7E4D8DE080674CB5981B45
+CT=B65C3F09FFFF752DEE2F8F2D441A51CA
+PT=3B36D6FD4F7ACAD4681FF4398AC7AFB3
+
+I=276
+KEY=BB7C9B34D4048759889F93753F5FB4F6
+CT=3B36D6FD4F7ACAD4681FF4398AC7AFB3
+PT=F3CDEFABE450D887CD585C280BB22367
+
+I=277
+KEY=48B1749F30545FDE45C7CF5D34ED9791
+CT=F3CDEFABE450D887CD585C280BB22367
+PT=ECC49251BAD79981CA1B1F683A843531
+
+I=278
+KEY=A475E6CE8A83C65F8FDCD0350E69A2A0
+CT=ECC49251BAD79981CA1B1F683A843531
+PT=8BE43F0A30663108513A0E5F49F9152C
+
+I=279
+KEY=2F91D9C4BAE5F757DEE6DE6A4790B78C
+CT=8BE43F0A30663108513A0E5F49F9152C
+PT=DB3D559FCEBE0FAF3B218161BA6B3F07
+
+I=280
+KEY=F4AC8C5B745BF8F8E5C75F0BFDFB888B
+CT=DB3D559FCEBE0FAF3B218161BA6B3F07
+PT=8F0C3AE11B03433C07CABD26BF47A430
+
+I=281
+KEY=7BA0B6BA6F58BBC4E20DE22D42BC2CBB
+CT=8F0C3AE11B03433C07CABD26BF47A430
+PT=73578DC3464CE3EE0314B206E1E9504C
+
+I=282
+KEY=08F73B792914582AE119502BA3557CF7
+CT=73578DC3464CE3EE0314B206E1E9504C
+PT=60DA2C12B296804C608348A54EE1C60D
+
+I=283
+KEY=682D176B9B82D866819A188EEDB4BAFA
+CT=60DA2C12B296804C608348A54EE1C60D
+PT=A960934724BDC61E5429E59856FC1902
+
+I=284
+KEY=C14D842CBF3F1E78D5B3FD16BB48A3F8
+CT=A960934724BDC61E5429E59856FC1902
+PT=6B7E71535C6B7B09BDF19AF79CD58C95
+
+I=285
+KEY=AA33F57FE3546571684267E1279D2F6D
+CT=6B7E71535C6B7B09BDF19AF79CD58C95
+PT=B95E0126EF320F1E6F288366DB7F2773
+
+I=286
+KEY=136DF4590C666A6F076AE487FCE2081E
+CT=B95E0126EF320F1E6F288366DB7F2773
+PT=6403B99D6FE0F85128FDD1F05B81AA6E
+
+I=287
+KEY=776E4DC46386923E2F973577A763A270
+CT=6403B99D6FE0F85128FDD1F05B81AA6E
+PT=9EBA25F2D6CE5817F4317F3AFE6421E7
+
+I=288
+KEY=E9D46836B548CA29DBA64A4D59078397
+CT=9EBA25F2D6CE5817F4317F3AFE6421E7
+PT=5E77AAE8A3C5EEAF4732BB310DAC3771
+
+I=289
+KEY=B7A3C2DE168D24869C94F17C54ABB4E6
+CT=5E77AAE8A3C5EEAF4732BB310DAC3771
+PT=5FD00675371300B60C30EFCEE0171080
+
+I=290
+KEY=E873C4AB219E243090A41EB2B4BCA466
+CT=5FD00675371300B60C30EFCEE0171080
+PT=482D701DBCE3AE108F65836C12A41C2C
+
+I=291
+KEY=A05EB4B69D7D8A201FC19DDEA618B84A
+CT=482D701DBCE3AE108F65836C12A41C2C
+PT=2966D81642542925891D8F7409051E4A
+
+I=292
+KEY=89386CA0DF29A30596DC12AAAF1DA600
+CT=2966D81642542925891D8F7409051E4A
+PT=2FD6F3DB9DD1DEDED9F32D1806AE69D6
+
+I=293
+KEY=A6EE9F7B42F87DDB4F2F3FB2A9B3CFD6
+CT=2FD6F3DB9DD1DEDED9F32D1806AE69D6
+PT=9B59277165B792790E29ADB53ADE60DB
+
+I=294
+KEY=3DB7B80A274FEFA241069207936DAF0D
+CT=9B59277165B792790E29ADB53ADE60DB
+PT=A4873C5246044200B56C25FFADAB15D6
+
+I=295
+KEY=99308458614BADA2F46AB7F83EC6BADB
+CT=A4873C5246044200B56C25FFADAB15D6
+PT=9E2BBBD65649EB2A0CD974AD32BF382F
+
+I=296
+KEY=071B3F8E37024688F8B3C3550C7982F4
+CT=9E2BBBD65649EB2A0CD974AD32BF382F
+PT=F83F4408675892DADA4833A43F22FFC8
+
+I=297
+KEY=FF247B86505AD45222FBF0F1335B7D3C
+CT=F83F4408675892DADA4833A43F22FFC8
+PT=19C337CCBF8D06DC68D9A16DB294EF44
+
+I=298
+KEY=E6E74C4AEFD7D28E4A22519C81CF9278
+CT=19C337CCBF8D06DC68D9A16DB294EF44
+PT=433578E0901A4F4B134E6DCF68249FC7
+
+I=299
+KEY=A5D234AA7FCD9DC5596C3C53E9EB0DBF
+CT=433578E0901A4F4B134E6DCF68249FC7
+PT=7F317CB0B3279C894B8A08289797FFF1
+
+I=300
+KEY=DAE3481ACCEA014C12E6347B7E7CF24E
+CT=7F317CB0B3279C894B8A08289797FFF1
+PT=AFFB4CA21A2A36FD24BB18C5AED17789
+
+I=301
+KEY=751804B8D6C037B1365D2CBED0AD85C7
+CT=AFFB4CA21A2A36FD24BB18C5AED17789
+PT=394DA5EC353A68B844D1BC24A468DA5C
+
+I=302
+KEY=4C55A154E3FA5F09728C909A74C55F9B
+CT=394DA5EC353A68B844D1BC24A468DA5C
+PT=C649C174B98A06351F26C117D14FF290
+
+I=303
+KEY=8A1C60205A70593C6DAA518DA58AAD0B
+CT=C649C174B98A06351F26C117D14FF290
+PT=2E122AA7C90B57304A80C19480627DD7
+
+I=304
+KEY=A40E4A87937B0E0C272A901925E8D0DC
+CT=2E122AA7C90B57304A80C19480627DD7
+PT=9841ADE6A65834CE89959EFE8F059ED6
+
+I=305
+KEY=3C4FE76135233AC2AEBF0EE7AAED4E0A
+CT=9841ADE6A65834CE89959EFE8F059ED6
+PT=6B70D74762A4BEFBD15B9EC6835CB69B
+
+I=306
+KEY=573F3026578784397FE4902129B1F891
+CT=6B70D74762A4BEFBD15B9EC6835CB69B
+PT=2E8B5DEF53E2294C0C953A9B8BD9399D
+
+I=307
+KEY=79B46DC90465AD757371AABAA268C10C
+CT=2E8B5DEF53E2294C0C953A9B8BD9399D
+PT=D32D00F78BA00F6CEA792598B89779E4
+
+I=308
+KEY=AA996D3E8FC5A21999088F221AFFB8E8
+CT=D32D00F78BA00F6CEA792598B89779E4
+PT=7059DCC6CB8D295B95F2978F25927B31
+
+I=309
+KEY=DAC0B1F844488B420CFA18AD3F6DC3D9
+CT=7059DCC6CB8D295B95F2978F25927B31
+PT=833A1AFA7DC4CAF54F5B36981A98D7E3
+
+I=310
+KEY=59FAAB02398C41B743A12E3525F5143A
+CT=833A1AFA7DC4CAF54F5B36981A98D7E3
+PT=4CC5A526400B493AAA28909A2F4932BF
+
+I=311
+KEY=153F0E247987088DE989BEAF0ABC2685
+CT=4CC5A526400B493AAA28909A2F4932BF
+PT=D7134DEE2967104D161876A0802B3727
+
+I=312
+KEY=C22C43CA50E018C0FF91C80F8A9711A2
+CT=D7134DEE2967104D161876A0802B3727
+PT=C45DB7BC52D7A0D53399B91EFB686D32
+
+I=313
+KEY=0671F4760237B815CC08711171FF7C90
+CT=C45DB7BC52D7A0D53399B91EFB686D32
+PT=2F49EA2A8D7F44909BCF41C3640FD0AB
+
+I=314
+KEY=29381E5C8F48FC8557C730D215F0AC3B
+CT=2F49EA2A8D7F44909BCF41C3640FD0AB
+PT=6D416059758F4AC555A05D83E9CFC4DE
+
+I=315
+KEY=44797E05FAC7B64002676D51FC3F68E5
+CT=6D416059758F4AC555A05D83E9CFC4DE
+PT=2721015DDF85EC87ED8480A87705CD37
+
+I=316
+KEY=63587F5825425AC7EFE3EDF98B3AA5D2
+CT=2721015DDF85EC87ED8480A87705CD37
+PT=3B045F5DD5ADC6E5D341E2E6A5B919D3
+
+I=317
+KEY=585C2005F0EF9C223CA20F1F2E83BC01
+CT=3B045F5DD5ADC6E5D341E2E6A5B919D3
+PT=85DA9719FF16899B343BE56FDF9F86BF
+
+I=318
+KEY=DD86B71C0FF915B90899EA70F11C3ABE
+CT=85DA9719FF16899B343BE56FDF9F86BF
+PT=67FD32AC2783C381E77AE0BB8ACEECCD
+
+I=319
+KEY=BA7B85B0287AD638EFE30ACB7BD2D673
+CT=67FD32AC2783C381E77AE0BB8ACEECCD
+PT=D8BEC715849E6A2A164F0139B8EC038E
+
+I=320
+KEY=62C542A5ACE4BC12F9AC0BF2C33ED5FD
+CT=D8BEC715849E6A2A164F0139B8EC038E
+PT=6ECA9375A207148E36203C8BD885A520
+
+I=321
+KEY=0C0FD1D00EE3A89CCF8C37791BBB70DD
+CT=6ECA9375A207148E36203C8BD885A520
+PT=A96877A8369B7086EF76D8281C066068
+
+I=322
+KEY=A567A6783878D81A20FAEF5107BD10B5
+CT=A96877A8369B7086EF76D8281C066068
+PT=2D6DDF2C136F5ACDC12D33D52ECD6397
+
+I=323
+KEY=880A79542B1782D7E1D7DC8429707322
+CT=2D6DDF2C136F5ACDC12D33D52ECD6397
+PT=E2F3EFF780EEDAD7B820CF57F946AB21
+
+I=324
+KEY=6AF996A3ABF9580059F713D3D036D803
+CT=E2F3EFF780EEDAD7B820CF57F946AB21
+PT=D083829AB624DC46BF55F15C2ACA2CDC
+
+I=325
+KEY=BA7A14391DDD8446E6A2E28FFAFCF4DF
+CT=D083829AB624DC46BF55F15C2ACA2CDC
+PT=637A1328711A701F011B0D66953A11FC
+
+I=326
+KEY=D90007116CC7F459E7B9EFE96FC6E523
+CT=637A1328711A701F011B0D66953A11FC
+PT=9230F9E8C4AA7D697641B4E800AECE8B
+
+I=327
+KEY=4B30FEF9A86D893091F85B016F682BA8
+CT=9230F9E8C4AA7D697641B4E800AECE8B
+PT=CABC2F3EBCB87AEF4550060FB6F95C7D
+
+I=328
+KEY=818CD1C714D5F3DFD4A85D0ED99177D5
+CT=CABC2F3EBCB87AEF4550060FB6F95C7D
+PT=25C93DA609BEDFD48D88B7E005EA9D4D
+
+I=329
+KEY=A445EC611D6B2C0B5920EAEEDC7BEA98
+CT=25C93DA609BEDFD48D88B7E005EA9D4D
+PT=E445C1B43DC6AA0D47C766675676CA29
+
+I=330
+KEY=40002DD520AD86061EE78C898A0D20B1
+CT=E445C1B43DC6AA0D47C766675676CA29
+PT=3F8A99E9D556F0CE0B0F3B4FE89A7C15
+
+I=331
+KEY=7F8AB43CF5FB76C815E8B7C662975CA4
+CT=3F8A99E9D556F0CE0B0F3B4FE89A7C15
+PT=BE04197CADBDBC917AB288D85C554D4A
+
+I=332
+KEY=C18EAD405846CA596F5A3F1E3EC211EE
+CT=BE04197CADBDBC917AB288D85C554D4A
+PT=2CF8FE59EED67AF15BD6C09C8DA37882
+
+I=333
+KEY=ED765319B690B0A8348CFF82B361696C
+CT=2CF8FE59EED67AF15BD6C09C8DA37882
+PT=FF8CBF98D0B15198ACDC53D7247511C5
+
+I=334
+KEY=12FAEC816621E1309850AC55971478A9
+CT=FF8CBF98D0B15198ACDC53D7247511C5
+PT=27794678855BAE2BDE7EB75487813E28
+
+I=335
+KEY=3583AAF9E37A4F1B462E1B0110954681
+CT=27794678855BAE2BDE7EB75487813E28
+PT=5681B2CECDE71663A864D0288607D86B
+
+I=336
+KEY=630218372E9D5978EE4ACB2996929EEA
+CT=5681B2CECDE71663A864D0288607D86B
+PT=8936EB6E65F2CD2B3AFD1310B5B2D6C8
+
+I=337
+KEY=EA34F3594B6F9453D4B7D83923204822
+CT=8936EB6E65F2CD2B3AFD1310B5B2D6C8
+PT=16045490148187B05CC46B80099A4530
+
+I=338
+KEY=FC30A7C95FEE13E38873B3B92ABA0D12
+CT=16045490148187B05CC46B80099A4530
+PT=FE909FFB1D490B028867288FE682EEE9
+
+I=339
+KEY=02A0383242A718E100149B36CC38E3FB
+CT=FE909FFB1D490B028867288FE682EEE9
+PT=7B3E5C0017089A7842866ABA6364FFEA
+
+I=340
+KEY=799E643255AF82994292F18CAF5C1C11
+CT=7B3E5C0017089A7842866ABA6364FFEA
+PT=CC263F129618975F204AE499F115C69B
+
+I=341
+KEY=B5B85B20C3B715C662D815155E49DA8A
+CT=CC263F129618975F204AE499F115C69B
+PT=997ACE7EABF6EBF9CC7BBCC2670CF1A0
+
+I=342
+KEY=2CC2955E6841FE3FAEA3A9D739452B2A
+CT=997ACE7EABF6EBF9CC7BBCC2670CF1A0
+PT=88D4A74B19278ED442068D0954DFA8B2
+
+I=343
+KEY=A4163215716670EBECA524DE6D9A8398
+CT=88D4A74B19278ED442068D0954DFA8B2
+PT=F1CC6407AB254178DEFEF983112D6AC5
+
+I=344
+KEY=55DA5612DA433193325BDD5D7CB7E95D
+CT=F1CC6407AB254178DEFEF983112D6AC5
+PT=689A0E429CDAF1BD1197C160BF962544
+
+I=345
+KEY=3D4058504699C02E23CC1C3DC321CC19
+CT=689A0E429CDAF1BD1197C160BF962544
+PT=54CF618196D978C0460CF8051DF5BE18
+
+I=346
+KEY=698F39D1D040B8EE65C0E438DED47201
+CT=54CF618196D978C0460CF8051DF5BE18
+PT=4AA0EF106F23B43C3DD371C66404C602
+
+I=347
+KEY=232FD6C1BF630CD2581395FEBAD0B403
+CT=4AA0EF106F23B43C3DD371C66404C602
+PT=A5185CAE1718143FC6CC329D9F233E17
+
+I=348
+KEY=86378A6FA87B18ED9EDFA76325F38A14
+CT=A5185CAE1718143FC6CC329D9F233E17
+PT=A2A7E8855D25A0C475961E9B7ED7BE35
+
+I=349
+KEY=249062EAF55EB829EB49B9F85B243421
+CT=A2A7E8855D25A0C475961E9B7ED7BE35
+PT=E0B7536B335FB98F197F762B3B97CECE
+
+I=350
+KEY=C4273181C60101A6F236CFD360B3FAEF
+CT=E0B7536B335FB98F197F762B3B97CECE
+PT=C45C38164083871528D8B3BA7423BFEA
+
+I=351
+KEY=007B0997868286B3DAEE7C6914904505
+CT=C45C38164083871528D8B3BA7423BFEA
+PT=017AEBDEF43CF9664C582356A4A0C374
+
+I=352
+KEY=0101E24972BE7FD596B65F3FB0308671
+CT=017AEBDEF43CF9664C582356A4A0C374
+PT=BBB48EA21B5EDCCF5346A7B4E6796BED
+
+I=353
+KEY=BAB56CEB69E0A31AC5F0F88B5649ED9C
+CT=BBB48EA21B5EDCCF5346A7B4E6796BED
+PT=3A53DFCB6067F9E98653136A44A4B537
+
+I=354
+KEY=80E6B32009875AF343A3EBE112ED58AB
+CT=3A53DFCB6067F9E98653136A44A4B537
+PT=951BA0E2272E46FC8CC3990E002EEFF0
+
+I=355
+KEY=15FD13C22EA91C0FCF6072EF12C3B75B
+CT=951BA0E2272E46FC8CC3990E002EEFF0
+PT=249202E40BC5892B9CEE96279E69432A
+
+I=356
+KEY=316F1126256C9524538EE4C88CAAF471
+CT=249202E40BC5892B9CEE96279E69432A
+PT=B90CE5BF126163B37F75032A88AFD615
+
+I=357
+KEY=8863F499370DF6972CFBE7E204052264
+CT=B90CE5BF126163B37F75032A88AFD615
+PT=E0BDD9E1FF493D82777BD7FB4035D309
+
+I=358
+KEY=68DE2D78C844CB155B8030194430F16D
+CT=E0BDD9E1FF493D82777BD7FB4035D309
+PT=0A3A5E377CDB2D1F6CB09E200494F578
+
+I=359
+KEY=62E4734FB49FE60A3730AE3940A40415
+CT=0A3A5E377CDB2D1F6CB09E200494F578
+PT=483DF6E2936389D1FC09921497AF8AE7
+
+I=360
+KEY=2AD985AD27FC6FDBCB393C2DD70B8EF2
+CT=483DF6E2936389D1FC09921497AF8AE7
+PT=7A90B7B1E493109323A54AD285090EC6
+
+I=361
+KEY=5049321CC36F7F48E89C76FF52028034
+CT=7A90B7B1E493109323A54AD285090EC6
+PT=B6471BF36A24B5B0CAC19BDD4C83DC50
+
+I=362
+KEY=E60E29EFA94BCAF8225DED221E815C64
+CT=B6471BF36A24B5B0CAC19BDD4C83DC50
+PT=EFBDC6ECADCE6AA5DBD302E7A0647700
+
+I=363
+KEY=09B3EF030485A05DF98EEFC5BEE52B64
+CT=EFBDC6ECADCE6AA5DBD302E7A0647700
+PT=783A89B88CC875F743B645BA1449CEE7
+
+I=364
+KEY=718966BB884DD5AABA38AA7FAAACE583
+CT=783A89B88CC875F743B645BA1449CEE7
+PT=EAD61D2577852D4EA276F3699EFB2BDC
+
+I=365
+KEY=9B5F7B9EFFC8F8E4184E59163457CE5F
+CT=EAD61D2577852D4EA276F3699EFB2BDC
+PT=9E804D8814AF4FC67BA931D1C72774C7
+
+I=366
+KEY=05DF3616EB67B72263E768C7F370BA98
+CT=9E804D8814AF4FC67BA931D1C72774C7
+PT=7C383CC27D8C2B117AC72088EB334FD9
+
+I=367
+KEY=79E70AD496EB9C331920484F1843F541
+CT=7C383CC27D8C2B117AC72088EB334FD9
+PT=9D4BE61ECECB2E60EC621A6320C0E844
+
+I=368
+KEY=E4ACECCA5820B253F542522C38831D05
+CT=9D4BE61ECECB2E60EC621A6320C0E844
+PT=227992ADFC526D9AA99BA629E7523198
+
+I=369
+KEY=C6D57E67A472DFC95CD9F405DFD12C9D
+CT=227992ADFC526D9AA99BA629E7523198
+PT=93A265FB7650BE75CBDD8732F65F09A5
+
+I=370
+KEY=55771B9CD22261BC97047337298E2538
+CT=93A265FB7650BE75CBDD8732F65F09A5
+PT=5AB3354B8D28F041C5A7FDAB828996BC
+
+I=371
+KEY=0FC42ED75F0A91FD52A38E9CAB07B384
+CT=5AB3354B8D28F041C5A7FDAB828996BC
+PT=BA5C6566701BD3791C2DA51CDC5AB6DD
+
+I=372
+KEY=B5984BB12F1142844E8E2B80775D0559
+CT=BA5C6566701BD3791C2DA51CDC5AB6DD
+PT=2C96CE0653EFB1113C6E822DD4AE6200
+
+I=373
+KEY=990E85B77CFEF39572E0A9ADA3F36759
+CT=2C96CE0653EFB1113C6E822DD4AE6200
+PT=1065F5519472C78BADAB79EC00BBCABA
+
+I=374
+KEY=896B70E6E88C341EDF4BD041A348ADE3
+CT=1065F5519472C78BADAB79EC00BBCABA
+PT=049AA7D4B4C1A59C1A16E3E5D8B46515
+
+I=375
+KEY=8DF1D7325C4D9182C55D33A47BFCC8F6
+CT=049AA7D4B4C1A59C1A16E3E5D8B46515
+PT=C8F1C4179DD8FCD6942D07AF7392F481
+
+I=376
+KEY=45001325C1956D545170340B086E3C77
+CT=C8F1C4179DD8FCD6942D07AF7392F481
+PT=9C9AE90AFE18822197EA47FE2F48813F
+
+I=377
+KEY=D99AFA2F3F8DEF75C69A73F52726BD48
+CT=9C9AE90AFE18822197EA47FE2F48813F
+PT=DFBABE8688391CC868CDE134DDFFE1F0
+
+I=378
+KEY=062044A9B7B4F3BDAE5792C1FAD95CB8
+CT=DFBABE8688391CC868CDE134DDFFE1F0
+PT=72BE585F98DA4DC03998B5820D5230A9
+
+I=379
+KEY=749E1CF62F6EBE7D97CF2743F78B6C11
+CT=72BE585F98DA4DC03998B5820D5230A9
+PT=BCF3D47B888599A27AD63D6EFD8FB86F
+
+I=380
+KEY=C86DC88DA7EB27DFED191A2D0A04D47E
+CT=BCF3D47B888599A27AD63D6EFD8FB86F
+PT=62F7A2AD05BB46CB81B9601129100455
+
+I=381
+KEY=AA9A6A20A25061146CA07A3C2314D02B
+CT=62F7A2AD05BB46CB81B9601129100455
+PT=FA4D3B82232D19BE14A57422012C7751
+
+I=382
+KEY=50D751A2817D78AA78050E1E2238A77A
+CT=FA4D3B82232D19BE14A57422012C7751
+PT=40953AAA3D6C1BBE375A1E275754C98C
+
+I=383
+KEY=10426B08BC1163144F5F1039756C6EF6
+CT=40953AAA3D6C1BBE375A1E275754C98C
+PT=CE9123C6A5A66AF788A8515721D646A0
+
+I=384
+KEY=DED348CE19B709E3C7F7416E54BA2856
+CT=CE9123C6A5A66AF788A8515721D646A0
+PT=E45F3483E343F5C3C0AC77E955369AB3
+
+I=385
+KEY=3A8C7C4DFAF4FC20075B3687018CB2E5
+CT=E45F3483E343F5C3C0AC77E955369AB3
+PT=6E7CE5F4BE070EC870691CDD494A767E
+
+I=386
+KEY=54F099B944F3F2E877322A5A48C6C49B
+CT=6E7CE5F4BE070EC870691CDD494A767E
+PT=2BB1EE551920A632E90EB9E462280365
+
+I=387
+KEY=7F4177EC5DD354DA9E3C93BE2AEEC7FE
+CT=2BB1EE551920A632E90EB9E462280365
+PT=692E0FA8B1C39CB96A11E21EA1B3365E
+
+I=388
+KEY=166F7844EC10C863F42D71A08B5DF1A0
+CT=692E0FA8B1C39CB96A11E21EA1B3365E
+PT=345C0DE98A9F472B6BCBE241BB346590
+
+I=389
+KEY=223375AD668F8F489FE693E130699430
+CT=345C0DE98A9F472B6BCBE241BB346590
+PT=D9D9313DC80FB90608614ECCC962207F
+
+I=390
+KEY=FBEA4490AE80364E9787DD2DF90BB44F
+CT=D9D9313DC80FB90608614ECCC962207F
+PT=7AEE31C488D1DD54B9AD8EE3AEFE546C
+
+I=391
+KEY=810475542651EB1A2E2A53CE57F5E023
+CT=7AEE31C488D1DD54B9AD8EE3AEFE546C
+PT=9CF27E1202080D9F3A9B5E02290204EA
+
+I=392
+KEY=1DF60B462459E68514B10DCC7EF7E4C9
+CT=9CF27E1202080D9F3A9B5E02290204EA
+PT=670085C6D3B95C6017DB9163B9D2D565
+
+I=393
+KEY=7AF68E80F7E0BAE5036A9CAFC72531AC
+CT=670085C6D3B95C6017DB9163B9D2D565
+PT=2A36E88DF74BA4B24283FEE52DDE5AA4
+
+I=394
+KEY=50C0660D00AB1E5741E9624AEAFB6B08
+CT=2A36E88DF74BA4B24283FEE52DDE5AA4
+PT=81B75B31F130467F4A1FA6CA4A329E5E
+
+I=395
+KEY=D1773D3CF19B58280BF6C480A0C9F556
+CT=81B75B31F130467F4A1FA6CA4A329E5E
+PT=D0A0347102BD11F9E2BD8E8A72D53ADC
+
+I=396
+KEY=01D7094DF32649D1E94B4A0AD21CCF8A
+CT=D0A0347102BD11F9E2BD8E8A72D53ADC
+PT=97F0187509608DF1D9B27AB5D005E505
+
+I=397
+KEY=96271138FA46C42030F930BF02192A8F
+CT=97F0187509608DF1D9B27AB5D005E505
+PT=E60139E36ECD7B24C7C98772C92A1E87
+
+I=398
+KEY=702628DB948BBF04F730B7CDCB333408
+CT=E60139E36ECD7B24C7C98772C92A1E87
+PT=7E92E19E07A469E7D49D3D07EF719157
+
+I=399
+KEY=0EB4C945932FD6E323AD8ACA2442A55F
+CT=7E92E19E07A469E7D49D3D07EF719157
+PT=F5BF8B37136F2E1F6BEC6F572021E3BA
+
+=========================
+
+KEYSIZE=192
+
+I=0
+KEY=000000000000000000000000000000000000000000000000
+CT=00000000000000000000000000000000
+PT=48E31E9E256718F29229319C19F15BA4
+
+I=1
+KEY=9643D8334A63DF4D48E31E9E256718F29229319C19F15BA4
+CT=48E31E9E256718F29229319C19F15BA4
+PT=CC01684BE9B29ED01EA7923E7D2380AA
+
+I=2
+KEY=EF334C87288C43DE84E276D5CCD586228C8EA3A264D2DB0E
+CT=CC01684BE9B29ED01EA7923E7D2380AA
+PT=8726B4E66D6B8FBAA22D42981A5A40CC
+
+I=3
+KEY=0891A045BB044B9D03C4C233A1BE09982EA3E13A7E889BC2
+CT=8726B4E66D6B8FBAA22D42981A5A40CC
+PT=83B9A21A0710FDB9C603797613772ED6
+
+I=4
+KEY=A5233519DE914717807D6029A6AEF421E8A0984C6DFFB514
+CT=83B9A21A0710FDB9C603797613772ED6
+PT=F15479A2B2C250F7E5C11D333D867CBD
+
+I=5
+KEY=A1CB19726DB4C2C77129198B146CA4D60D61857F5079C9A9
+CT=F15479A2B2C250F7E5C11D333D867CBD
+PT=C1AF401BD4E62D8BA15BEC3690F2FB25
+
+I=6
+KEY=04B03C15DB8324B3B0865990C08A895DAC3A6949C08B328C
+CT=C1AF401BD4E62D8BA15BEC3690F2FB25
+PT=01E01E3B10470286035EBD7502EF11A0
+
+I=7
+KEY=A1CB0164AB1E88EDB16647ABD0CD8BDBAF64D43CC264232C
+CT=01E01E3B10470286035EBD7502EF11A0
+PT=A681127825B718411291106AB416779A
+
+I=8
+KEY=27BFD9CB824C525617E755D3F57A939ABDF5C456767254B6
+CT=A681127825B718411291106AB416779A
+PT=5C2EBA728589A9CAA15E28E7D8E59AA0
+
+I=9
+KEY=B308E0DCE108194C4BC9EFA170F33A501CABECB1AE97CE16
+CT=5C2EBA728589A9CAA15E28E7D8E59AA0
+PT=E738305279BE636648B6D5FFA3E97E4A
+
+I=10
+KEY=FE787701EE66664BACF1DFF3094D5936541D394E0D7EB05C
+CT=E738305279BE636648B6D5FFA3E97E4A
+PT=5AF7D4C9439C7412FD7236E7685659DF
+
+I=11
+KEY=DD93D742AFA0B19CF6060B3A4AD12D24A96F0FA96528E983
+CT=5AF7D4C9439C7412FD7236E7685659DF
+PT=30D0681D4060E24D1427D1AAC498DB1B
+
+I=12
+KEY=D5D19C2FEA9DC94BC6D663270AB1CF69BD48DE03A1B03298
+CT=30D0681D4060E24D1427D1AAC498DB1B
+PT=FC9B6752064B1CCE75EBFBE91AF8F2CD
+
+I=13
+KEY=EB0954ECE44620833A4D04750CFAD3A7C8A325EABB48C055
+CT=FC9B6752064B1CCE75EBFBE91AF8F2CD
+PT=61E6AE6E035BCC3C94EF00101216904A
+
+I=14
+KEY=E6E5AB38545B6DF75BABAA1B0FA11F9B5C4C25FAA95E501F
+CT=61E6AE6E035BCC3C94EF00101216904A
+PT=BF738A4E55F036126CC9B56DED530B8C
+
+I=15
+KEY=E8C670F71E5B62B6E4D820555A51298930859097440D5B93
+CT=BF738A4E55F036126CC9B56DED530B8C
+PT=6B9CD4C227FC30C14FD881B838D9F8F5
+
+I=16
+KEY=23FF647DD75770418F44F4977DAD19487F5D112F7CD4A366
+CT=6B9CD4C227FC30C14FD881B838D9F8F5
+PT=6173EF2B5C9B569A1BD4B62C7C913844
+
+I=17
+KEY=DB94124B11CC03D9EE371BBC21364FD26489A70300459B22
+CT=6173EF2B5C9B569A1BD4B62C7C913844
+PT=709EF90F853E55123A917FB258E900F9
+
+I=18
+KEY=4821CA96B50ACA049EA9E2B3A4081AC05E18D8B158AC9BDB
+CT=709EF90F853E55123A917FB258E900F9
+PT=5D73D99E47B1DB28E0ED9B9D1C212CFA
+
+I=19
+KEY=FA47C5BF5E688F8BC3DA3B2DE3B9C1E8BEF5432C448DB721
+CT=5D73D99E47B1DB28E0ED9B9D1C212CFA
+PT=32016FFCB2AA5EA6EA0C808F60613CA2
+
+I=20
+KEY=C66A73E0D1261C2CF1DB54D151139F4E54F9C3A324EC8B83
+CT=32016FFCB2AA5EA6EA0C808F60613CA2
+PT=CAA3704F7FD76EBACB1D2A266A0899FF
+
+I=21
+KEY=FAE8E04094E572A33B78249E2EC4F1F49FE4E9854EE4127C
+CT=CAA3704F7FD76EBACB1D2A266A0899FF
+PT=E32DBD027A1A36B2EC8D0A98C9293E7E
+
+I=22
+KEY=8F2FBF9E40182950D855999C54DEC7467369E31D87CD2C02
+CT=E32DBD027A1A36B2EC8D0A98C9293E7E
+PT=1C117311882C0D5159A9DFD5C3C68D95
+
+I=23
+KEY=F6FB8F6DFAA034BFC444EA8DDCF2CA172AC03CC8440BA197
+CT=1C117311882C0D5159A9DFD5C3C68D95
+PT=5E379C2471DB04582CD861E6F8A419D7
+
+I=24
+KEY=699DCA67F4EF50C49A7376A9AD29CE4F06185D2EBCAFB840
+CT=5E379C2471DB04582CD861E6F8A419D7
+PT=5932A84C6ACBD8452EE9AC47CE4B6BD8
+
+I=25
+KEY=F568B4F126486CE4C341DEE5C7E2160A28F1F16972E4D398
+CT=5932A84C6ACBD8452EE9AC47CE4B6BD8
+PT=00634EED1D18C84AE0A8198CF791DE81
+
+I=26
+KEY=C49E5E8D366B6FE7C3229008DAFADE40C859E8E585750D19
+CT=00634EED1D18C84AE0A8198CF791DE81
+PT=E10C93B1C466FFF0B6EB6DB50AF271EC
+
+I=27
+KEY=22B07DB9ED443A9D222E03B91E9C21B07EB285508F877CF5
+CT=E10C93B1C466FFF0B6EB6DB50AF271EC
+PT=58A0C680F565E63A7E41C6EAC50A3B01
+
+I=28
+KEY=2BDF4CCE2B4CAFDD7A8EC539EBF9C78A00F343BA4A8D47F4
+CT=58A0C680F565E63A7E41C6EAC50A3B01
+PT=92921B2AA7FC6367199A4C42FAE0E2A4
+
+I=29
+KEY=E2BE29F6905D41C5E81CDE134C05A4ED19690FF8B06DA550
+CT=92921B2AA7FC6367199A4C42FAE0E2A4
+PT=B6EC2A692D2657E5506F2C3BA1912799
+
+I=30
+KEY=E43634FD3DB719C75EF0F47A6123F308490623C311FC82C9
+CT=B6EC2A692D2657E5506F2C3BA1912799
+PT=23ECD0813B1A7090CF9BE874D6B0846C
+
+I=31
+KEY=ACA2F21EF46E30B57D1C24FB5A398398869DCBB7C74C06A5
+CT=23ECD0813B1A7090CF9BE874D6B0846C
+PT=04BD52F4C1AB8DF4816A6E11F8B54452
+
+I=32
+KEY=0130B37AFE24D66079A1760F9B920E6C07F7A5A63FF942F7
+CT=04BD52F4C1AB8DF4816A6E11F8B54452
+PT=DFA0074DEFEDB44D0D96AD6020D1A37D
+
+I=33
+KEY=00AC6BF5E3AD20FFA6017142747FBA210A6108C61F28E18A
+CT=DFA0074DEFEDB44D0D96AD6020D1A37D
+PT=5AB15057E05F73FAAF12C0EC26D3F02F
+
+I=34
+KEY=E3A70EBF3D9167AAFCB021159420C9DBA573C82A39FB11A5
+CT=5AB15057E05F73FAAF12C0EC26D3F02F
+PT=6ECC2F23AB7854E97F215C52EF1E62E0
+
+I=35
+KEY=CBCD9116DC78FA64927C0E363F589D32DA529478D6E57345
+CT=6ECC2F23AB7854E97F215C52EF1E62E0
+PT=930B3EBDE0989049056022E83FC9EF1E
+
+I=36
+KEY=FBB5E5462DE715180177308BDFC00D7BDF32B690E92C9C5B
+CT=930B3EBDE0989049056022E83FC9EF1E
+PT=1EE4ABB9ACD70B93A83BCD8751F858DE
+
+I=37
+KEY=E5D2B1ACD8BE6DF21F939B32731706E877097B17B8D4C485
+CT=1EE4ABB9ACD70B93A83BCD8751F858DE
+PT=FCAC610EA0D309C6D36EED5A4BC04036
+
+I=38
+KEY=54DD0B6CB083BDE8E33FFA3CD3C40F2EA467964DF31484B3
+CT=FCAC610EA0D309C6D36EED5A4BC04036
+PT=161D5EE8F50A3F69A11ADFEAF1A2A2AA
+
+I=39
+KEY=28309F7EB99AAEE1F522A4D426CE3047057D49A702B62619
+CT=161D5EE8F50A3F69A11ADFEAF1A2A2AA
+PT=D9D365B061D2F3BF9DF94181837621B4
+
+I=40
+KEY=E55ECDDFAE95A2C92CF1C164471CC3F89884082681C007AD
+CT=D9D365B061D2F3BF9DF94181837621B4
+PT=938647A6AAD455D89A6DFEFE60D62331
+
+I=41
+KEY=C9CEE1C9D89DF76ABF7786C2EDC8962002E9F6D8E116249C
+CT=938647A6AAD455D89A6DFEFE60D62331
+PT=06A002DDC7DC4F22F9B1D5734C312AAA
+
+I=42
+KEY=B26709109B66C916B9D7841F2A14D902FB5823ABAD270E36
+CT=06A002DDC7DC4F22F9B1D5734C312AAA
+PT=BB45E9BE2237E3288F56EDD0D9AD6734
+
+I=43
+KEY=2FAD2FF32E10680502926DA108233A2A740ECE7B748A6902
+CT=BB45E9BE2237E3288F56EDD0D9AD6734
+PT=CF5A1338F5FA7ED4C77F6EA3836F079A
+
+I=44
+KEY=63D3D62540C790D1CDC87E99FDD944FEB371A0D8F7E56E98
+CT=CF5A1338F5FA7ED4C77F6EA3836F079A
+PT=32F2D628117ADB46383FC101B58E95A6
+
+I=45
+KEY=0DF38CE71CF26A19FF3AA8B1ECA39FB88B4E61D9426BFB3E
+CT=32F2D628117ADB46383FC101B58E95A6
+PT=3A3CCEA99D43887AC64498AB4EFC87DD
+
+I=46
+KEY=7EEEB78A0C9BAA9FC506661871E017C24D0AF9720C977CE3
+CT=3A3CCEA99D43887AC64498AB4EFC87DD
+PT=787DC1C632C4AA77D42324338C510146
+
+I=47
+KEY=4DF02EE427AE29A1BD7BA7DE4324BDB59929DD4180C67DA5
+CT=787DC1C632C4AA77D42324338C510146
+PT=BB0635A471D26B80E5E387E4F14A1626
+
+I=48
+KEY=D6983F5E8BE728D9067D927A32F6D6357CCA5AA5718C6B83
+CT=BB0635A471D26B80E5E387E4F14A1626
+PT=14A9AA3EE6343C2D57E0F2ED7A05DC0D
+
+I=49
+KEY=BD84A7CD471613B512D43844D4C2EA182B2AA8480B89B78E
+CT=14A9AA3EE6343C2D57E0F2ED7A05DC0D
+PT=25E254AD6C33908BC07B3DEC4052F549
+
+I=50
+KEY=E54A2146242AADFB37366CE9B8F17A93EB5195A44BDB42C7
+CT=25E254AD6C33908BC07B3DEC4052F549
+PT=10E09F426E6F33CD21DF1EB748A46088
+
+I=51
+KEY=0517B745BCE24E0527D6F3ABD69E495ECA8E8B13037F224F
+CT=10E09F426E6F33CD21DF1EB748A46088
+PT=B65D2FFE83F9469AA2B1ABC559EAAB87
+
+I=52
+KEY=8297790C75E8931C918BDC5555670FC4683F20D65A9589C8
+CT=B65D2FFE83F9469AA2B1ABC559EAAB87
+PT=E743F6441CCF9703FF4B8E3F4921ACDF
+
+I=53
+KEY=7EC47C0C5663CD4C76C82A1149A898C79774AEE913B42517
+CT=E743F6441CCF9703FF4B8E3F4921ACDF
+PT=BECC5CF2F2C62A9E7D3CF979A9E96F94
+
+I=54
+KEY=FBB1F10529FABEB3C80476E3BB6EB259EA485790BA5D4A83
+CT=BECC5CF2F2C62A9E7D3CF979A9E96F94
+PT=3718199958EAA473B980B95F9C76E03F
+
+I=55
+KEY=EE4113D30720269DFF1C6F7AE384162A53C8EECF262BAABC
+CT=3718199958EAA473B980B95F9C76E03F
+PT=D15525B8BBB6D209E0BB3B6F5ACB2556
+
+I=56
+KEY=488286944DC6B0842E494AC25832C423B373D5A07CE08FEA
+CT=D15525B8BBB6D209E0BB3B6F5ACB2556
+PT=0270AF07DDA52DF7CA7B0EE7DF098A80
+
+I=57
+KEY=A32A880A84E7EDB82C39E5C58597E9D47908DB47A3E9056A
+CT=0270AF07DDA52DF7CA7B0EE7DF098A80
+PT=2D380F99A182CD14CFFEF5E88B93B416
+
+I=58
+KEY=DBD0FD5053BC52C60101EA5C241524C0B6F62EAF287AB17C
+CT=2D380F99A182CD14CFFEF5E88B93B416
+PT=47FE8C67DCBC616E4C984D323EA4A45B
+
+I=59
+KEY=D79F78A4726F5FCA46FF663BF8A945AEFA6E639D16DE1527
+CT=47FE8C67DCBC616E4C984D323EA4A45B
+PT=FA595C69C3286771FB8C921DFBBFFC2E
+
+I=60
+KEY=0C88AAD46F951FB6BCA63A523B8122DF01E2F180ED61E909
+CT=FA595C69C3286771FB8C921DFBBFFC2E
+PT=8FA64C511FCE6FC987B327D12EBDADAD
+
+I=61
+KEY=762EEA21D382067E33007603244F4D168651D651C3DC44A4
+CT=8FA64C511FCE6FC987B327D12EBDADAD
+PT=8F52C709508408B40C241FD38E515E76
+
+I=62
+KEY=EA05788C20FB364EBC52B10A74CB45A28A75C9824D8D1AD2
+CT=8F52C709508408B40C241FD38E515E76
+PT=7CFD332B306684AC92279CE06F1287D8
+
+I=63
+KEY=D4B2582B094D874DC0AF822144ADC10E18525562229F9D0A
+CT=7CFD332B306684AC92279CE06F1287D8
+PT=0DA14F6619665E0128044355481BD658
+
+I=64
+KEY=C080E7033FDF1BCFCD0ECD475DCB9F0F305616376A844B52
+CT=0DA14F6619665E0128044355481BD658
+PT=FEDEBE73AA4047AF27E86A8B9E8E2ED7
+
+I=65
+KEY=C5BA9667999CF2D633D07334F78BD8A017BE7CBCF40A6585
+CT=FEDEBE73AA4047AF27E86A8B9E8E2ED7
+PT=12CD6896129E376AAB9C0E980F3B7CD2
+
+I=66
+KEY=65FF092A539C4600211D1BA2E515EFCABC227224FB311957
+CT=12CD6896129E376AAB9C0E980F3B7CD2
+PT=04E7939B352F7B5C38B7EC5784EC78C2
+
+I=67
+KEY=F98E7062F9EBE61C25FA8839D03A949684959E737FDD6195
+CT=04E7939B352F7B5C38B7EC5784EC78C2
+PT=0184996278A57E36E608E95616C46964
+
+I=68
+KEY=306FBEFB3BF4E241247E115BA89FEAA0629D7725691908F1
+CT=0184996278A57E36E608E95616C46964
+PT=92179E392E05C8B96A0CFAC36109B09E
+
+I=69
+KEY=EE641F5DB58F9057B6698F62869A221908918DE60810B86F
+CT=92179E392E05C8B96A0CFAC36109B09E
+PT=7F197B01172C809635198E6B156D13BC
+
+I=70
+KEY=EADB8B255F98FD9DC970F46391B6A28F3D88038D1D7DABD3
+CT=7F197B01172C809635198E6B156D13BC
+PT=46F6DD79AD079DCFBC451B24ECDDA4FA
+
+I=71
+KEY=47225D75FE68FFA08F86291A3CB13F4081CD18A9F1A00F29
+CT=46F6DD79AD079DCFBC451B24ECDDA4FA
+PT=B5DAA09E3545F92FF44176187A1F9179
+
+I=72
+KEY=7CDECC21E72E54F43A5C898409F4C66F758C6EB18BBF9E50
+CT=B5DAA09E3545F92FF44176187A1F9179
+PT=F51A35F3DD410132EEC9E9F22A6F6FAB
+
+I=73
+KEY=75D1AAFDBFE72C94CF46BC77D4B5C75D9B458743A1D0F1FB
+CT=F51A35F3DD410132EEC9E9F22A6F6FAB
+PT=D1CC6D95B58793C342CF14AF250D5E40
+
+I=74
+KEY=41874C54BD58757A1E8AD1E26132549ED98A93EC84DDAFBB
+CT=D1CC6D95B58793C342CF14AF250D5E40
+PT=A1FAB3B352A887A829357528FED4B80E
+
+I=75
+KEY=1D94704F4A51A5CABF706251339AD336F0BFE6C47A0917B5
+CT=A1FAB3B352A887A829357528FED4B80E
+PT=CBC6473B3AA4DE2D64EED554CA241EAC
+
+I=76
+KEY=A41B52E0AE7E568074B6256A093E0D1B94513390B02D0919
+CT=CBC6473B3AA4DE2D64EED554CA241EAC
+PT=19DC6E89D71DCE5DCECD1A6F85C3FBD6
+
+I=77
+KEY=85F21BCD70691F596D6A4BE3DE23C3465A9C29FF35EEF2CF
+CT=19DC6E89D71DCE5DCECD1A6F85C3FBD6
+PT=EC6974E51B21F26A100E66183C68FD15
+
+I=78
+KEY=CAD0B254A88B669681033F06C502312C4A924FE709860FDA
+CT=EC6974E51B21F26A100E66183C68FD15
+PT=A16B6F78009B6E30CB758E87AD4D8034
+
+I=79
+KEY=8AC49B19582BFCF32068507EC5995F1C81E7C160A4CB8FEE
+CT=A16B6F78009B6E30CB758E87AD4D8034
+PT=CB5C20AAFA898193BC34FF3EE460B313
+
+I=80
+KEY=988F8D4F3A66AC99EB3470D43F10DE8F3DD33E5E40AB3CFD
+CT=CB5C20AAFA898193BC34FF3EE460B313
+PT=397F92C8E69E0916E30DC6889779799E
+
+I=81
+KEY=DE2D26C6130E006ED24BE21CD98ED799DEDEF8D6D7D24563
+CT=397F92C8E69E0916E30DC6889779799E
+PT=9A9CBD9380E2187855CAE5A73D58480F
+
+I=82
+KEY=BF6BE6D55C04977348D75F8F596CCFE18B141D71EA8A0D6C
+CT=9A9CBD9380E2187855CAE5A73D58480F
+PT=B67B360EE0FF297D3662F5B7CDB82CB9
+
+I=83
+KEY=6582BCA895FA1221FEAC6981B993E69CBD76E8C6273221D5
+CT=B67B360EE0FF297D3662F5B7CDB82CB9
+PT=2D146ED9236082D2D71810969A1AB1FB
+
+I=84
+KEY=6AC68BB8BBC7F520D3B807589AF3644E6A6EF850BD28902E
+CT=2D146ED9236082D2D71810969A1AB1FB
+PT=4B9F55652C40B6DA963A98D875ADACE4
+
+I=85
+KEY=180DAB1B14A92DB29827523DB6B3D294FC546088C8853CCA
+CT=4B9F55652C40B6DA963A98D875ADACE4
+PT=FC0A8A3D511F5FAFF0A3DD13B49E5A13
+
+I=86
+KEY=7ABD7440D5EE5FE2642DD800E7AC8D3B0CF7BD9B7C1B66D9
+CT=FC0A8A3D511F5FAFF0A3DD13B49E5A13
+PT=4231C02AD3231C3EB7AEB9135B95AC4B
+
+I=87
+KEY=54ACAE182B5FDACF261C182A348F9105BB590488278ECA92
+CT=4231C02AD3231C3EB7AEB9135B95AC4B
+PT=4C3A949ACCCBB55F9415C81B1413FD9D
+
+I=88
+KEY=015706F99E81CC026A268CB0F844245A2F4CCC93339D370F
+CT=4C3A949ACCCBB55F9415C81B1413FD9D
+PT=E9B1CEAF77B64A88CC3E020B16E1BF7E
+
+I=89
+KEY=929BD0A1CC6450E78397421F8FF26ED2E372CE98257C8871
+CT=E9B1CEAF77B64A88CC3E020B16E1BF7E
+PT=98FFEA0827068CB0B508CA520D8B43F7
+
+I=90
+KEY=9B81EC47D8442D311B68A817A8F4E262567A04CA28F7CB86
+CT=98FFEA0827068CB0B508CA520D8B43F7
+PT=BEDA572C3CA3FEF97F7071DA35414EA1
+
+I=91
+KEY=93B211B869CBECCBA5B2FF3B94571C9B290A75101DB68527
+CT=BEDA572C3CA3FEF97F7071DA35414EA1
+PT=35E8CB8302748C8623A09980909FB516
+
+I=92
+KEY=BC5320E4025EB960905A34B89623901D0AAAEC908D293031
+CT=35E8CB8302748C8623A09980909FB516
+PT=E136148B2FA5AF5CD3F8BC3883566CB8
+
+I=93
+KEY=C4EC937F948D0B5A716C2033B9863F41D95250A80E7F5C89
+CT=E136148B2FA5AF5CD3F8BC3883566CB8
+PT=B7CE40E3E3D30191CDF4AB5BE98F347A
+
+I=94
+KEY=6D381856C149D9DCC6A260D05A553ED014A6FBF3E7F068F3
+CT=B7CE40E3E3D30191CDF4AB5BE98F347A
+PT=A821E934DAAE37FF3136E769DAC315FB
+
+I=95
+KEY=A3679C5957C656DE6E8389E480FB092F25901C9A3D337D08
+CT=A821E934DAAE37FF3136E769DAC315FB
+PT=4227B96A0CC6CA1C21BCF8B1ADB3BDE1
+
+I=96
+KEY=BE7112453B1DF3EC2CA4308E8C3DC333042CE42B9080C0E9
+CT=4227B96A0CC6CA1C21BCF8B1ADB3BDE1
+PT=EE36BBFDDF19165F9E64AE79B4CF06A9
+
+I=97
+KEY=AEA4A2D5CD0A2FC7C2928B735324D56C9A484A52244FC640
+CT=EE36BBFDDF19165F9E64AE79B4CF06A9
+PT=C3DFE088C6767BC939F492C1FA9604CD
+
+I=98
+KEY=A16FC5F22F03984F014D6BFB9552AEA5A3BCD893DED9C28D
+CT=C3DFE088C6767BC939F492C1FA9604CD
+PT=DB1202E468119D977868F6E294E3CC3A
+
+I=99
+KEY=A4E0565DD419BDD1DA5F691FFD433332DBD42E714A3A0EB7
+CT=DB1202E468119D977868F6E294E3CC3A
+PT=6F2F682BA4F95EB8C5B883C7660B2653
+
+I=100
+KEY=3CAEE44D0E85058EB570013459BA6D8A1E6CADB62C3128E4
+CT=6F2F682BA4F95EB8C5B883C7660B2653
+PT=1036B4AA6C897D36DFE6658A953E5075
+
+I=101
+KEY=4E883A500CA89963A546B59E353310BCC18AC83CB90F7891
+CT=1036B4AA6C897D36DFE6658A953E5075
+PT=04FCB3A81E5319A16CCF212719906229
+
+I=102
+KEY=ADED5A405C5C095AA1BA06362B60091DAD45E91BA09F1AB8
+CT=04FCB3A81E5319A16CCF212719906229
+PT=CD79BAC069BB58605D43005B927816E5
+
+I=103
+KEY=5499B441405D16B06CC3BCF642DB517DF006E94032E70C5D
+CT=CD79BAC069BB58605D43005B927816E5
+PT=DB5B3C625D1F66CF28A86CC100472398
+
+I=104
+KEY=D31221246382CA8EB79880941FC437B2D8AE858132A02FC5
+CT=DB5B3C625D1F66CF28A86CC100472398
+PT=D8732A2C16EC6AE202371AF03A6F91E8
+
+I=105
+KEY=CDF928E97051F08B6FEBAAB809285D50DA999F7108CFBE2D
+CT=D8732A2C16EC6AE202371AF03A6F91E8
+PT=F0A1A353A8AB9A893F621F0BEA3B4F01
+
+I=106
+KEY=10CC2EED0ECBD1E69F4A09EBA183C7D9E5FB807AE2F4F12C
+CT=F0A1A353A8AB9A893F621F0BEA3B4F01
+PT=27E4451BD15E43F301E138713DC12E78
+
+I=107
+KEY=03C4F5E1FD3D34D1B8AE4CF070DD842AE41AB80BDF35DF54
+CT=27E4451BD15E43F301E138713DC12E78
+PT=C7FA931DA414CB37A9BDB6F128E082EE
+
+I=108
+KEY=CC5D7D36D085E3257F54DFEDD4C94F1D4DA70EFAF7D55DBA
+CT=C7FA931DA414CB37A9BDB6F128E082EE
+PT=A6777D51A0A1C94DD74A18795341015F
+
+I=109
+KEY=9F4EE4750FF3F53AD923A2BC746886509AED1683A4945CE5
+CT=A6777D51A0A1C94DD74A18795341015F
+PT=32A4D930A5597E02D7076E399D18D895
+
+I=110
+KEY=8525417BB6D8095BEB877B8CD131F8524DEA78BA398C8470
+CT=32A4D930A5597E02D7076E399D18D895
+PT=1B78FCF274EEB1E597998EE4EFFF9F8B
+
+I=111
+KEY=54EFA98071F1EF62F0FF877EA5DF49B7DA73F65ED6731BFB
+CT=1B78FCF274EEB1E597998EE4EFFF9F8B
+PT=2997FEE2823CC84DA14E8439449F5C7C
+
+I=112
+KEY=2505931CE4D41D16D968799C27E381FA7B3D726792EC4787
+CT=2997FEE2823CC84DA14E8439449F5C7C
+PT=810534A9E8DB2808FEE681B13C04411D
+
+I=113
+KEY=C2DF863BEB4F27AB586D4D35CF38A9F285DBF3D6AEE8069A
+CT=810534A9E8DB2808FEE681B13C04411D
+PT=BE2380994365F1D7FC8278E86C8B497D
+
+I=114
+KEY=036C0C95D0C26B66E64ECDAC8C5D582579598B3EC2634FE7
+CT=BE2380994365F1D7FC8278E86C8B497D
+PT=EFEC3977D5A21DC4AC786E786CA3ECE9
+
+I=115
+KEY=BD05AD63A0A9F1B509A2F4DB59FF45E1D521E546AEC0A30E
+CT=EFEC3977D5A21DC4AC786E786CA3ECE9
+PT=22A7280D8231895EA4F0B6A39AC583C3
+
+I=116
+KEY=A16DFA00981597B42B05DCD6DBCECCBF71D153E5340520CD
+CT=22A7280D8231895EA4F0B6A39AC583C3
+PT=0CC61E91B3CBCD0E190D52059E27647A
+
+I=117
+KEY=ABC1AD453235832727C3C247680501B168DC01E0AA2244B7
+CT=0CC61E91B3CBCD0E190D52059E27647A
+PT=5CE91F77F7C8F0AB1BBA802D2FFF0E9B
+
+I=118
+KEY=64D40ACA0F526EC67B2ADD309FCDF11A736681CD85DD4A2C
+CT=5CE91F77F7C8F0AB1BBA802D2FFF0E9B
+PT=255459BE5A27E08942A049F6EC44582E
+
+I=119
+KEY=8BB5C7D8B2B177855E7E848EC5EA119331C6C83B69991202
+CT=255459BE5A27E08942A049F6EC44582E
+PT=28E2E20115C3665D9D88CB74681301EA
+
+I=120
+KEY=4E30FCC4C182F471769C668FD02977CEAC4E034F018A13E8
+CT=28E2E20115C3665D9D88CB74681301EA
+PT=2E96E6BBCD999F4B1507C7EC9E4B8430
+
+I=121
+KEY=906B361E9D72E107580A80341DB0E885B949C4A39FC197D8
+CT=2E96E6BBCD999F4B1507C7EC9E4B8430
+PT=03DED0A95164E5FA215E9C49C433E95B
+
+I=122
+KEY=F656F5D9D973C02C5BD4509D4CD40D7F981758EA5BF27E83
+CT=03DED0A95164E5FA215E9C49C433E95B
+PT=AD9C16D2567B73FCA4866FE16CF09CDA
+
+I=123
+KEY=8811A4ACDF37A140F648464F1AAF7E833C91370B3702E259
+CT=AD9C16D2567B73FCA4866FE16CF09CDA
+PT=68539BFF0F8CC23A0A3267796A11B75C
+
+I=124
+KEY=E5AF2E8CDBAD01589E1BDDB01523BCB936A350725D135505
+CT=68539BFF0F8CC23A0A3267796A11B75C
+PT=B15F623E5A7D73452A419EB04AFCF72E
+
+I=125
+KEY=C9E743CAD731A62E2F44BF8E4F5ECFFC1CE2CEC217EFA22B
+CT=B15F623E5A7D73452A419EB04AFCF72E
+PT=520142AFDA69E9CFA98D8DD59CCB12BC
+
+I=126
+KEY=6CF6C656FFBB77807D45FD2195372633B56F43178B24B097
+CT=520142AFDA69E9CFA98D8DD59CCB12BC
+PT=7EC2A8430F23A5E183E0032DAB5232C5
+
+I=127
+KEY=772CEE9F934D57D4038755629A1483D2368F403A20768252
+CT=7EC2A8430F23A5E183E0032DAB5232C5
+PT=E5E3A5D968B1FF774B55CCA06BE3BD65
+
+I=128
+KEY=9A4DAB93F3C74EBBE664F0BBF2A57CA57DDA8C9A4B953F37
+CT=E5E3A5D968B1FF774B55CCA06BE3BD65
+PT=9608643D0A34DA28372A7E7E34427E1B
+
+I=129
+KEY=EF0F60BCBA3374E0706C9486F891A68D4AF0F2E47FD7412C
+CT=9608643D0A34DA28372A7E7E34427E1B
+PT=B22BD410584F29610801B18EDAB1BD19
+
+I=130
+KEY=DE013A6C3440AFF3C2474096A0DE8FEC42F1436AA566FC35
+CT=B22BD410584F29610801B18EDAB1BD19
+PT=ADEC4519F1A7AD74BCCECABEDCF20D73
+
+I=131
+KEY=2B5B547A934A5A376FAB058F51792298FE3F89D47994F146
+CT=ADEC4519F1A7AD74BCCECABEDCF20D73
+PT=E04D4FF54191BEEEF5B295A32DA2ADE5
+
+I=132
+KEY=BF356F2FFC2C538F8FE64A7A10E89C760B8D1C7754365CA3
+CT=E04D4FF54191BEEEF5B295A32DA2ADE5
+PT=3F9531EDD5072F7A9F2A62ECC2CCE50A
+
+I=133
+KEY=7CEBD7310CC4791AB0737B97C5EFB30C94A77E9B96FAB9A9
+CT=3F9531EDD5072F7A9F2A62ECC2CCE50A
+PT=C3DC95781FAE7BB6C02BD08B3617DDF1
+
+I=134
+KEY=192741D2AB9C887673AFEEEFDA41C8BA548CAE10A0ED6458
+CT=C3DC95781FAE7BB6C02BD08B3617DDF1
+PT=F69B837F168B9A9E637E7357B65F2B60
+
+I=135
+KEY=38552740A79FB5BF85346D90CCCA522437F2DD4716B24F38
+CT=F69B837F168B9A9E637E7357B65F2B60
+PT=40DCDF58E7EFDD62C114A83F8AC898BB
+
+I=136
+KEY=A0AED2C07C2168B6C5E8B2C82B258F46F6E675789C7AD783
+CT=40DCDF58E7EFDD62C114A83F8AC898BB
+PT=27F78F3BD8E04A8646EBF364155A71ED
+
+I=137
+KEY=2B4FAEBF17993E12E21F3DF3F3C5C5C0B00D861C8920A66E
+CT=27F78F3BD8E04A8646EBF364155A71ED
+PT=F305DFC8EAD44E786F59B0551C7104F5
+
+I=138
+KEY=96819F6E9738209F111AE23B19118BB8DF5436499551A29B
+CT=F305DFC8EAD44E786F59B0551C7104F5
+PT=2E47F833BE7C06ED1E42AC11366F4BEF
+
+I=139
+KEY=AAEA16BAC3E84DD73F5D1A08A76D8D55C1169A58A33EE974
+CT=2E47F833BE7C06ED1E42AC11366F4BEF
+PT=A9D3A511C3D76779B607AAB2556823AD
+
+I=140
+KEY=F66BA47C56AC5A36968EBF1964BAEA2C771130EAF656CAD9
+CT=A9D3A511C3D76779B607AAB2556823AD
+PT=153A7CC2387C05289F759C85076CDD88
+
+I=141
+KEY=1D892BCCFAF3DA1083B4C3DB5CC6EF04E864AC6FF13A1751
+CT=153A7CC2387C05289F759C85076CDD88
+PT=76B6089030D914F0F4C6078193207A7D
+
+I=142
+KEY=DAEBAF980095A397F502CB4B6C1FFBF41CA2ABEE621A6D2C
+CT=76B6089030D914F0F4C6078193207A7D
+PT=EB71D127848BA397451D45801830461E
+
+I=143
+KEY=85F86FADA92076AB1E731A6CE894586359BFEE6E7A2A2B32
+CT=EB71D127848BA397451D45801830461E
+PT=B79D9BE1B2DB808B412413C203C710DF
+
+I=144
+KEY=BEADDA5CE1E7F3D4A9EE818D5A4FD8E8189BFDAC79ED3BED
+CT=B79D9BE1B2DB808B412413C203C710DF
+PT=E6423467C3CA69D94C944FA2A97BB61F
+
+I=145
+KEY=D4664C8DCFA8304D4FACB5EA9985B131540FB20ED0968DF2
+CT=E6423467C3CA69D94C944FA2A97BB61F
+PT=18EFF53B7D62A9D9ED8AB9ABE67FC110
+
+I=146
+KEY=9CCF1EEAF55FEA5A574340D1E4E718E8B9850BA536E94CE2
+CT=18EFF53B7D62A9D9ED8AB9ABE67FC110
+PT=8E6A4AC577153D806ED71A07319CAB67
+
+I=147
+KEY=7D840184CB9D3A05D9290A1493F22568D75211A20775E785
+CT=8E6A4AC577153D806ED71A07319CAB67
+PT=B7B23D8E7D344F39B3EA0D67CCF37377
+
+I=148
+KEY=D72F35B6DD825B656E9B379AEEC66A5164B81CC5CB8694F2
+CT=B7B23D8E7D344F39B3EA0D67CCF37377
+PT=3385AD0503AF68BFBFBEAA89B1C87736
+
+I=149
+KEY=48335F06D7C27C955D1E9A9FED6902EEDB06B64C7A4EE3C4
+CT=3385AD0503AF68BFBFBEAA89B1C87736
+PT=9FC40A6B984BEEC182AB650B05CEF38C
+
+I=150
+KEY=A66149286535FD6EC2DA90F47522EC2F59ADD3477F801048
+CT=9FC40A6B984BEEC182AB650B05CEF38C
+PT=4CEC52C9DE143486DFC9D098637DFBB5
+
+I=151
+KEY=7EA78450FAEEF8BF8E36C23DAB36D8A9866403DF1CFDEBFD
+CT=4CEC52C9DE143486DFC9D098637DFBB5
+PT=EB8E40333ACD18EFB04DC0A857DDCD7A
+
+I=152
+KEY=197DDF842BAEF36E65B8820E91FBC0463629C3774B202687
+CT=EB8E40333ACD18EFB04DC0A857DDCD7A
+PT=F1AFF04058F819B0F191398C8022130F
+
+I=153
+KEY=D68841CF848B0F619417724EC903D9F6C7B8FAFBCB023588
+CT=F1AFF04058F819B0F191398C8022130F
+PT=6DF4A95D8D602C0E53F5A5C350D3EB64
+
+I=154
+KEY=6DFA0F7B01A2F011F9E3DB134463F5F8944D5F389BD1DEEC
+CT=6DF4A95D8D602C0E53F5A5C350D3EB64
+PT=057D8F9BE9260BB3A0382CD2EF7D1FCA
+
+I=155
+KEY=88227C4AD1CBC8F0FC9E5488AD45FE4B347573EA74ACC126
+CT=057D8F9BE9260BB3A0382CD2EF7D1FCA
+PT=D4EDACCB9B7B35F2A0690E22C91E25AE
+
+I=156
+KEY=848B8E3213D366B22873F843363ECBB9941C7DC8BDB2E488
+CT=D4EDACCB9B7B35F2A0690E22C91E25AE
+PT=A2F61B5BDD9F580B26C329B878BAFA3C
+
+I=157
+KEY=FA3A476D1C6E33FD8A85E318EBA193B2B2DF5470C5081EB4
+CT=A2F61B5BDD9F580B26C329B878BAFA3C
+PT=5A0616880CD40B72B58CF268EC8F934B
+
+I=158
+KEY=C9F77D58F58D5FEDD083F590E77598C00753A61829878DFF
+CT=5A0616880CD40B72B58CF268EC8F934B
+PT=0E42047D7EDE2A5FBB37767A69A45B9B
+
+I=159
+KEY=00A523C700FBB663DEC1F1ED99ABB29FBC64D0624023D664
+CT=0E42047D7EDE2A5FBB37767A69A45B9B
+PT=2AFA823A10BB436A7B00816C80A52711
+
+I=160
+KEY=660275323A59E807F43B73D78910F1F5C764510EC086F175
+CT=2AFA823A10BB436A7B00816C80A52711
+PT=B2406F3F9160E25DF7C9AA81AF6EB449
+
+I=161
+KEY=47A4FCDB97D4A383467B1CE8187013A830ADFB8F6FE8453C
+CT=B2406F3F9160E25DF7C9AA81AF6EB449
+PT=B1E01D2A401495F8DDAEAB7B04BEB23D
+
+I=162
+KEY=2BDD5B54D4EB236AF79B01C258648650ED0350F46B56F701
+CT=B1E01D2A401495F8DDAEAB7B04BEB23D
+PT=390572A9ECE28A0E0BBDC729DBE5F79A
+
+I=163
+KEY=328202460B65D004CE9E736BB4860C5EE6BE97DDB0B3009B
+CT=390572A9ECE28A0E0BBDC729DBE5F79A
+PT=5D41665811702124C597DB4E3BD950E1
+
+I=164
+KEY=94457C0A759DF4E993DF1533A5F62D7A23294C938B6A507A
+CT=5D41665811702124C597DB4E3BD950E1
+PT=689EB1CB1586D127696E8725DEE49E58
+
+I=165
+KEY=4E0226CA850DDC79FB41A4F8B070FC5D4A47CBB6558ECE22
+CT=689EB1CB1586D127696E8725DEE49E58
+PT=A2D9DF62AC8BF8A93E7A954416864052
+
+I=166
+KEY=659C817A1C10A24D59987B9A1CFB04F4743D5EF243088E70
+CT=A2D9DF62AC8BF8A93E7A954416864052
+PT=507835696F1920BD4A05797563DF5769
+
+I=167
+KEY=92192D9175187FB409E04EF373E224493E38278720D7D919
+CT=507835696F1920BD4A05797563DF5769
+PT=2070413F5103482B6C83129304E5AC87
+
+I=168
+KEY=6959063FBA59CCEC29900FCC22E16C6252BB35142432759E
+CT=2070413F5103482B6C83129304E5AC87
+PT=BF7FD1E21B41B1F1C2625C1097F1BCB8
+
+I=169
+KEY=5722993710D811B196EFDE2E39A0DD9390D96904B3C3C926
+CT=BF7FD1E21B41B1F1C2625C1097F1BCB8
+PT=6E2236654F2999545F50FA9CF63F9F2E
+
+I=170
+KEY=038FA98E7A226A9FF8CDE84B768944C7CF89939845FC5608
+CT=6E2236654F2999545F50FA9CF63F9F2E
+PT=3F370291CEDCB115C8EE409A8EEB46D6
+
+I=171
+KEY=CACF0199725D5466C7FAEADAB855F5D20767D302CB1710DE
+CT=3F370291CEDCB115C8EE409A8EEB46D6
+PT=84023DB96D373EC8315AE78A3B7E82FB
+
+I=172
+KEY=7B40321CB11520D143F8D763D562CB1A363D3488F0699225
+CT=84023DB96D373EC8315AE78A3B7E82FB
+PT=C35064D82A3016FE2C2E2CC0627E7B5C
+
+I=173
+KEY=F045CFEC2A6BC7E580A8B3BBFF52DDE41A1318489217E979
+CT=C35064D82A3016FE2C2E2CC0627E7B5C
+PT=D78DFFE87C0F95856C31A07BADA23084
+
+I=174
+KEY=86B3CA5F50CEF6C557254C53835D48617622B8333FB5D9FD
+CT=D78DFFE87C0F95856C31A07BADA23084
+PT=5B5B5D3CA5C6E5CF18F3E4EE802BE82B
+
+I=175
+KEY=E6D99DC0C58655B70C7E116F269BADAE6ED15CDDBF9E31D6
+CT=5B5B5D3CA5C6E5CF18F3E4EE802BE82B
+PT=DB65A82F6EB7A410A367165900E85117
+
+I=176
+KEY=B8F770CFBE47D070D71BB940482C09BECDB64A84BF7660C1
+CT=DB65A82F6EB7A410A367165900E85117
+PT=FE8BE8484D925043102238FF63FDAC57
+
+I=177
+KEY=FF09ADB06FE587192990510805BE59FDDD94727BDC8BCC96
+CT=FE8BE8484D925043102238FF63FDAC57
+PT=AC36E01A7AD482A8D89703D2A6528720
+
+I=178
+KEY=B5C937A4019CDAD185A6B1127F6ADB55050371A97AD94BB6
+CT=AC36E01A7AD482A8D89703D2A6528720
+PT=9F3698CE06C6497C89B58CA723F7ECAA
+
+I=179
+KEY=F60CAF8FB99B63B21A9029DC79AC92298CB6FD0E592EA71C
+CT=9F3698CE06C6497C89B58CA723F7ECAA
+PT=FB8CE2E1D332FE4557B6C5CF1676F2FB
+
+I=180
+KEY=B7CF2BABD58B5FDCE11CCB3DAA9E6C6CDB0038C14F5855E7
+CT=FB8CE2E1D332FE4557B6C5CF1676F2FB
+PT=A2631F612698318AD454E9DB10319DA6
+
+I=181
+KEY=FD99B4137CAFC47F437FD45C8C065DE60F54D11A5F69C841
+CT=A2631F612698318AD454E9DB10319DA6
+PT=FCA42B332B5974EE6DFA54B54EC89AC7
+
+I=182
+KEY=271CEEF189AD367DBFDBFF6FA75F290862AE85AF11A15286
+CT=FCA42B332B5974EE6DFA54B54EC89AC7
+PT=A70DBBDFCE54B8648C3FC4A8A58CCDF8
+
+I=183
+KEY=7B78F7ECC9B28EC718D644B0690B916CEE914107B42D9F7E
+CT=A70DBBDFCE54B8648C3FC4A8A58CCDF8
+PT=C90CE914F9310F9C3EE065DD95281A51
+
+I=184
+KEY=762F521ADF6C5F24D1DAADA4903A9EF0D07124DA2105852F
+CT=C90CE914F9310F9C3EE065DD95281A51
+PT=63E8430CE22F531E4A4D4583533F6FC4
+
+I=185
+KEY=A88A493EB3C28C49B232EEA87215CDEE9A3C6159723AEAEB
+CT=63E8430CE22F531E4A4D4583533F6FC4
+PT=E7562DC647910A052F4AFBF165A68A3A
+
+I=186
+KEY=1C97343A60EE05035564C36E3584C7EBB5769AA8179C60D1
+CT=E7562DC647910A052F4AFBF165A68A3A
+PT=3E070B3F65FD01B49849513B556DB199
+
+I=187
+KEY=C5110692100A332E6B63C8515079C65F2D3FCB9342F1D148
+CT=3E070B3F65FD01B49849513B556DB199
+PT=3DE5A45B2CAA4FAFAC3032F89F15195D
+
+I=188
+KEY=D94D8CAA9EBD67F056866C0A7CD389F0810FF96BDDE4C815
+CT=3DE5A45B2CAA4FAFAC3032F89F15195D
+PT=A36A163E8806B1E053EBE439B0D1302F
+
+I=189
+KEY=1C1D7A3E9358048CF5EC7A34F4D53810D2E41D526D35F83A
+CT=A36A163E8806B1E053EBE439B0D1302F
+PT=67CA4B988CCABA4E4DBEE6C387562762
+
+I=190
+KEY=9182E40D14973087922631AC781F825E9F5AFB91EA63DF58
+CT=67CA4B988CCABA4E4DBEE6C387562762
+PT=9F404F0E1A9FE5A988CE6E4A54FE9E23
+
+I=191
+KEY=7D89ECFC0DCFFE0A0D667EA2628067F7179495DBBE9D417B
+CT=9F404F0E1A9FE5A988CE6E4A54FE9E23
+PT=D71EFD794457C71614E4266C77193444
+
+I=192
+KEY=AC7A11D29CDA0FB6DA7883DB26D7A0E10370B3B7C984753F
+CT=D71EFD794457C71614E4266C77193444
+PT=185DBF418A6834CD118B16EAF381F3CB
+
+I=193
+KEY=1029D5FA3D38927EC2253C9AACBF942C12FBA55D3A0586F4
+CT=185DBF418A6834CD118B16EAF381F3CB
+PT=737A502DEE68DDFA3FEECD42ACE124EA
+
+I=194
+KEY=F261B484C642750CB15F6CB742D749D62D15681F96E4A21E
+CT=737A502DEE68DDFA3FEECD42ACE124EA
+PT=FD11B0F356455913E892928B5B16946B
+
+I=195
+KEY=BCCFAF05FF47A5EC4C4EDC44149210C5C587FA94CDF23675
+CT=FD11B0F356455913E892928B5B16946B
+PT=4B06F6D6D149BAF25D4C76E46EFF8571
+
+I=196
+KEY=1000A15983B73D6807482A92C5DBAA3798CB8C70A30DB304
+CT=4B06F6D6D149BAF25D4C76E46EFF8571
+PT=450713DA24492403C48CB16D2F39744E
+
+I=197
+KEY=306F097E64B634AC424F3948E1928E345C473D1D8C34C74A
+CT=450713DA24492403C48CB16D2F39744E
+PT=998CA5E3C80B66EB11EAD376FA358A92
+
+I=198
+KEY=13965208C3EF77E1DBC39CAB2999E8DF4DADEE6B76014DD8
+CT=998CA5E3C80B66EB11EAD376FA358A92
+PT=F54A34F6F0833CA808D60A8F75BB0585
+
+I=199
+KEY=1A6DC3FDD0D1F97C2E89A85DD91AD477457BE4E403BA485D
+CT=F54A34F6F0833CA808D60A8F75BB0585
+PT=8760D5CBD1DA48807BAEAF7F781680F2
+
+I=200
+KEY=228897B4E2F16967A9E97D9608C09CF73ED54B9B7BACC8AF
+CT=8760D5CBD1DA48807BAEAF7F781680F2
+PT=EF57DF7161E1BC0F7B466A50C576691A
+
+I=201
+KEY=D0E8190E72A305C946BEA2E7692120F8459321CBBEDAA1B5
+CT=EF57DF7161E1BC0F7B466A50C576691A
+PT=E01ECA338A93EA38E43B2F364314C121
+
+I=202
+KEY=087F0486B80659F0A6A068D4E3B2CAC0A1A80EFDFDCE6094
+CT=E01ECA338A93EA38E43B2F364314C121
+PT=A7683273638D02272FF6A311BB94256F
+
+I=203
+KEY=1D807E4730DDA3EB01C85AA7803FC8E78E5EADEC465A45FB
+CT=A7683273638D02272FF6A311BB94256F
+PT=1BCC3DF6B07BD2615C13E381F5F877C3
+
+I=204
+KEY=D4D4F2780D52D7521A04675130441A86D24D4E6DB3A23238
+CT=1BCC3DF6B07BD2615C13E381F5F877C3
+PT=D1B3B793D1377E82A2DE5D46E53791FB
+
+I=205
+KEY=86D08D85652DB662CBB7D0C2E17364047093132B5695A3C3
+CT=D1B3B793D1377E82A2DE5D46E53791FB
+PT=9AC7AF9B82621E18E4FF613EAA609F46
+
+I=206
+KEY=C03996907AC99A7A51707F5963117A1C946C7215FCF53C85
+CT=9AC7AF9B82621E18E4FF613EAA609F46
+PT=57F3FA35A42C29F33DEC4671140264A4
+
+I=207
+KEY=F8CA52D95C587EF80683856CC73D53EFA9803464E8F75821
+CT=57F3FA35A42C29F33DEC4671140264A4
+PT=A887ED8BF6C19F5012F317A4FCF3D7BF
+
+I=208
+KEY=DE99CC8F9756C1DCAE0468E731FCCCBFBB7323C014048F9E
+CT=A887ED8BF6C19F5012F317A4FCF3D7BF
+PT=A29C8D764BCF211C789158A9B8EB330C
+
+I=209
+KEY=9228DB1B61E0D8670C98E5917A33EDA3C3E27B69ACEFBC92
+CT=A29C8D764BCF211C789158A9B8EB330C
+PT=EB6AFD9B36315DB322EC8C4243043F50
+
+I=210
+KEY=24AFE14097C2A217E7F2180A4C02B010E10EF72BEFEB83C2
+CT=EB6AFD9B36315DB322EC8C4243043F50
+PT=05C8AC90CCD00E2A3809C68C11D6D65A
+
+I=211
+KEY=32810943F9313BD0E23AB49A80D2BE3AD90731A7FE3D5598
+CT=05C8AC90CCD00E2A3809C68C11D6D65A
+PT=E39991B58C52154166AD09367B04C67A
+
+I=212
+KEY=FBEC72A177254EA501A3252F0C80AB7BBFAA3891853993E2
+CT=E39991B58C52154166AD09367B04C67A
+PT=CBC8974F72F77A1821FC69B29FE2DB60
+
+I=213
+KEY=C706D206DE538439CA6BB2607E77D1639E5651231ADB4882
+CT=CBC8974F72F77A1821FC69B29FE2DB60
+PT=1D08F4E2B8DFED1032B6CA5211B3E34C
+
+I=214
+KEY=9A7EB0A4F8E67F87D7634682C6A83C73ACE09B710B68ABCE
+CT=1D08F4E2B8DFED1032B6CA5211B3E34C
+PT=1888CEC22449EFF96BDC2C7A242BBBDC
+
+I=215
+KEY=70CA2CAD6A50D22BCFEB8840E2E1D38AC73CB70B2F431012
+CT=1888CEC22449EFF96BDC2C7A242BBBDC
+PT=032E6155677B6A72D7F94C7A9A9AA53F
+
+I=216
+KEY=B16697FEA247CDB9CCC5E915859AB9F810C5FB71B5D9B52D
+CT=032E6155677B6A72D7F94C7A9A9AA53F
+PT=9B43BBD1C0CEBF7593E9BC0ABB626E96
+
+I=217
+KEY=7A3E844BEB897A63578652C44554068D832C477B0EBBDBBB
+CT=9B43BBD1C0CEBF7593E9BC0ABB626E96
+PT=8D661E03C61C28D5786EBCEBE0D5B63D
+
+I=218
+KEY=E7A1B96EFC4D5FB5DAE04CC783482E58FB42FB90EE6E6D86
+CT=8D661E03C61C28D5786EBCEBE0D5B63D
+PT=F61D5DCBF8F2F3F0EAB387149790E079
+
+I=219
+KEY=0EDA761C06FBA0A02CFD110C7BBADDA811F17C8479FE8DFF
+CT=F61D5DCBF8F2F3F0EAB387149790E079
+PT=1F03E0957B6892533BBEAB06EB35AD4F
+
+I=220
+KEY=E242AD5B7141916133FEF19900D24FFB2A4FD78292CB20B0
+CT=1F03E0957B6892533BBEAB06EB35AD4F
+PT=BB9E7343035F88764B229D506E7ADC7B
+
+I=221
+KEY=D901A6CF874A6A77886082DA038DC78D616D4AD2FCB1FCCB
+CT=BB9E7343035F88764B229D506E7ADC7B
+PT=3934EBF7AD2243C0D09734E30B41C0E4
+
+I=222
+KEY=0F488E86E7D92F29B154692DAEAF844DB1FA7E31F7F03C2F
+CT=3934EBF7AD2243C0D09734E30B41C0E4
+PT=B9CE1A1A9595E7235F5B10FBA29ACCD2
+
+I=223
+KEY=A7E2CF991692247A089A73373B3A636EEEA16ECA556AF0FD
+CT=B9CE1A1A9595E7235F5B10FBA29ACCD2
+PT=624EBA65EE9E3E1BDF8C5AA7E1283A65
+
+I=224
+KEY=1DE03E09395E56CE6AD4C952D5A45D75312D346DB442CA98
+CT=624EBA65EE9E3E1BDF8C5AA7E1283A65
+PT=375132E5F47DA19E80CC8652BE5A3692
+
+I=225
+KEY=51B6813629EFE53C5D85FBB721D9FCEBB1E1B23F0A18FC0A
+CT=375132E5F47DA19E80CC8652BE5A3692
+PT=8165A4126FE75EFC6AFF7BFD732F94A6
+
+I=226
+KEY=8DD50DFF93624339DCE05FA54E3EA217DB1EC9C2793768AC
+CT=8165A4126FE75EFC6AFF7BFD732F94A6
+PT=35012FABD289E6B7FB07946591D18F0D
+
+I=227
+KEY=C7A4F75CB74C7F3DE9E1700E9CB744A020195DA7E8E6E7A1
+CT=35012FABD289E6B7FB07946591D18F0D
+PT=C26F37D700677ED72F4FC2C8F6AEADE2
+
+I=228
+KEY=198B572CD0E711352B8E47D99CD03A770F569F6F1E484A43
+CT=C26F37D700677ED72F4FC2C8F6AEADE2
+PT=CB29ECE41596736B72AED2460AEEFBA2
+
+I=229
+KEY=0A1FB41CA720E357E0A7AB3D8946491C7DF84D2914A6B1E1
+CT=CB29ECE41596736B72AED2460AEEFBA2
+PT=7F7BD6FAF9C37D5522A3BF480CCEBF20
+
+I=230
+KEY=7E383601899DEA729FDC7DC7708534495F5BF26118680EC1
+CT=7F7BD6FAF9C37D5522A3BF480CCEBF20
+PT=C501E371005DF57E0037F41A744D026F
+
+I=231
+KEY=13ACF410865B41E15ADD9EB670D8C1375F6C067B6C250CAE
+CT=C501E371005DF57E0037F41A744D026F
+PT=624EF8749580108CDC7A020179F81D0F
+
+I=232
+KEY=75F025072AA2406F389366C2E558D1BB8316047A15DD11A1
+CT=624EF8749580108CDC7A020179F81D0F
+PT=40D72550603522C67180DE6EC3D30139
+
+I=233
+KEY=C5ED76F88EA65C3D78444392856DF37DF296DA14D60E1098
+CT=40D72550603522C67180DE6EC3D30139
+PT=96C6F647AFB90F804431F9E2F1780F29
+
+I=234
+KEY=E827DFF88D0B1A43EE82B5D52AD4FCFDB6A723F627761FB1
+CT=96C6F647AFB90F804431F9E2F1780F29
+PT=CCB934A501DDAD11E994938A214EB189
+
+I=235
+KEY=F0777D1BFF12EE42223B81702B0951EC5F33B07C0638AE38
+CT=CCB934A501DDAD11E994938A214EB189
+PT=07825F2D35E761C76893B697E30E4D08
+
+I=236
+KEY=6912B59C06C90D3725B9DE5D1EEE302B37A006EBE536E330
+CT=07825F2D35E761C76893B697E30E4D08
+PT=1F674E97F88EB1DA1DD24C0AB4321258
+
+I=237
+KEY=AE24933526FAE5F83ADE90CAE66081F12A724AE15104F168
+CT=1F674E97F88EB1DA1DD24C0AB4321258
+PT=B6DE499EBE0B3C30F1DAC8E40FE9F10C
+
+I=238
+KEY=F348F88852CF356C8C00D954586BBDC1DBA882055EED0064
+CT=B6DE499EBE0B3C30F1DAC8E40FE9F10C
+PT=105E31DBDE33764B098862AF6D0B6CD2
+
+I=239
+KEY=83B06CC00A17D3149C5EE88F8658CB8AD220E0AA33E66CB6
+CT=105E31DBDE33764B098862AF6D0B6CD2
+PT=697D6537677B20C188246FBF4997C7CB
+
+I=240
+KEY=A5381A9C91D61A01F5238DB8E123EB4B5A048F157A71AB7D
+CT=697D6537677B20C188246FBF4997C7CB
+PT=4FBFB0EFBA92C1E0189E2C3097AA35BA
+
+I=241
+KEY=FDF831A7D1345AFEBA9C3D575BB12AAB429AA325EDDB9EC7
+CT=4FBFB0EFBA92C1E0189E2C3097AA35BA
+PT=600288531DCEB99B69A7890CE804FA9F
+
+I=242
+KEY=A10ED54E7B2B2B2BDA9EB504467F93302B3D2A2905DF6458
+CT=600288531DCEB99B69A7890CE804FA9F
+PT=EE94D4376D9332C8DCD05C695EDB124F
+
+I=243
+KEY=2F69F01250D7745F340A61332BECA1F8F7ED76405B047617
+CT=EE94D4376D9332C8DCD05C695EDB124F
+PT=7EDC3182C36DC5A172B170A919524888
+
+I=244
+KEY=FCD5F8FAB347624E4AD650B1E8816459855C06E942563E9F
+CT=7EDC3182C36DC5A172B170A919524888
+PT=95FA03C96DFCB9ABCFF23B5ABFBABCDE
+
+I=245
+KEY=A9307E62197A747EDF2C5378857DDDF24AAE3DB3FDEC8241
+CT=95FA03C96DFCB9ABCFF23B5ABFBABCDE
+PT=6CE2C6CFC61667965C20B0BE11B55DDE
+
+I=246
+KEY=DA3B03896DDFDE08B3CE95B7436BBA64168E8D0DEC59DF9F
+CT=6CE2C6CFC61667965C20B0BE11B55DDE
+PT=3DBDFBE63A6FAE7572C778108A62A27C
+
+I=247
+KEY=7D766BAD6E536CE38E736E51790414116449F51D663B7DE3
+CT=3DBDFBE63A6FAE7572C778108A62A27C
+PT=1C197D3449FED6ED6924E14B43A17BF0
+
+I=248
+KEY=36F69C30B0272CAB926A136530FAC2FC0D6D1456259A0613
+CT=1C197D3449FED6ED6924E14B43A17BF0
+PT=0B0CCC6F508C18168284F7976AD81BEE
+
+I=249
+KEY=632661C312B2EB5D9966DF0A6076DAEA8FE9E3C14F421DFD
+CT=0B0CCC6F508C18168284F7976AD81BEE
+PT=F437B8FD92CE37D8D74550C5BE29BF99
+
+I=250
+KEY=5FB1BDFC29EFE2DA6D5167F7F2B8ED3258ACB304F16BA264
+CT=F437B8FD92CE37D8D74550C5BE29BF99
+PT=78F6E6F6480A04F5632EA112170F928C
+
+I=251
+KEY=2B24C5188F4A2E7B15A78101BAB2E9C73B821216E66430E8
+CT=78F6E6F6480A04F5632EA112170F928C
+PT=2FD38831EE4D09DD8DB9A84B5825B528
+
+I=252
+KEY=F816FB720A08828C3A74093054FFE01AB63BBA5DBE4185C0
+CT=2FD38831EE4D09DD8DB9A84B5825B528
+PT=ED307697B51CFAD7052A3A7B3A564990
+
+I=253
+KEY=776B08F4778FAB96D7447FA7E1E31ACDB31180268417CC50
+CT=ED307697B51CFAD7052A3A7B3A564990
+PT=DB9952A98F0D4B045C624EFA5619CAF9
+
+I=254
+KEY=C7A944C9BA2D5F740CDD2D0E6EEE51C9EF73CEDCD20E06A9
+CT=DB9952A98F0D4B045C624EFA5619CAF9
+PT=DADA40BF0E367AF50874BB2628251AA3
+
+I=255
+KEY=69B8688D9C1ECD95D6076DB160D82B3CE70775FAFA2B1C0A
+CT=DADA40BF0E367AF50874BB2628251AA3
+PT=35DFA85D3F2D7F47DD7865EA0BC73A5C
+
+I=256
+KEY=7E6C7E90EDE36F44E3D8C5EC5FF5547B3A7F1010F1EC2656
+CT=35DFA85D3F2D7F47DD7865EA0BC73A5C
+PT=EE0231F994C2DB6C7C04746170F03E54
+
+I=257
+KEY=0E56C8FD184AB5D40DDAF415CB378F17467B6471811C1802
+CT=EE0231F994C2DB6C7C04746170F03E54
+PT=D9F314FEAD11122CE8F532ED0C0B129C
+
+I=258
+KEY=267BC5325796002BD429E0EB66269D3BAE8E569C8D170A9E
+CT=D9F314FEAD11122CE8F532ED0C0B129C
+PT=74A32BDFF53A59F09AAFB328977E05B1
+
+I=259
+KEY=889B6087CAAD1B43A08ACB34931CC4CB3421E5B41A690F2F
+CT=74A32BDFF53A59F09AAFB328977E05B1
+PT=D4CCC3077C15EE470D5EFCF815A48410
+
+I=260
+KEY=F9AE78D077E3F98574460833EF092A8C397F194C0FCD8B3F
+CT=D4CCC3077C15EE470D5EFCF815A48410
+PT=29284B0E7776DFB8BB536B3C16399D62
+
+I=261
+KEY=71BBCD4B1F4B04265D6E433D987FF534822C727019F4165D
+CT=29284B0E7776DFB8BB536B3C16399D62
+PT=202326CEAD57A5C13592FFBFFD5BF508
+
+I=262
+KEY=F6F461C7931CF0317D4D65F3352850F5B7BE8DCFE4AFE355
+CT=202326CEAD57A5C13592FFBFFD5BF508
+PT=B9AFAD0658E1A4A1EECAA25B2863AD53
+
+I=263
+KEY=BC0D82D3B7909D54C4E2C8F56DC9F45459742F94CCCC4E06
+CT=B9AFAD0658E1A4A1EECAA25B2863AD53
+PT=DE7AC7F7381DD34F3148911F306F4161
+
+I=264
+KEY=339FFE2E01AB1D621A980F0255D4271B683CBE8BFCA30F67
+CT=DE7AC7F7381DD34F3148911F306F4161
+PT=F197DE9FED1EA08F6C17E631BF5449FE
+
+I=265
+KEY=EC908F9A4F266644EB0FD19DB8CA8794042B58BA43F74699
+CT=F197DE9FED1EA08F6C17E631BF5449FE
+PT=7E1416C06ED3F56782DB5CB536B9B56E
+
+I=266
+KEY=CFE36CCCC94F8A5B951BC75DD61972F386F0040F754EF3F7
+CT=7E1416C06ED3F56782DB5CB536B9B56E
+PT=BE1FE1F7B4CFF55D15BBCB6D9313729D
+
+I=267
+KEY=90690906407FB8AC2B0426AA62D687AE934BCF62E65D816A
+CT=BE1FE1F7B4CFF55D15BBCB6D9313729D
+PT=50E6818C06583D3D1C99C4A127D118CF
+
+I=268
+KEY=5D2A712578EC47217BE2A726648EBA938FD20BC3C18C99A5
+CT=50E6818C06583D3D1C99C4A127D118CF
+PT=E1BFD3ED18E9A6D7BF383D590DA23B59
+
+I=269
+KEY=3CA141EE57D7E0FC9A5D74CB7C671C4430EA369ACC2EA2FC
+CT=E1BFD3ED18E9A6D7BF383D590DA23B59
+PT=03961127347C141C01F5276CB9BB31F7
+
+I=270
+KEY=65E9B8AE22DC52A599CB65EC481B0858311F11F67595930B
+CT=03961127347C141C01F5276CB9BB31F7
+PT=E9A8336DC0B530A86988B2DE74EDFFA1
+
+I=271
+KEY=870A30E0F3B836FA7063568188AE38F05897A32801786CAA
+CT=E9A8336DC0B530A86988B2DE74EDFFA1
+PT=B5FA5E388CFFFE2BA33436CC39A73972
+
+I=272
+KEY=4B81E55C765F570CC59908B90451C6DBFBA395E438DF55D8
+CT=B5FA5E388CFFFE2BA33436CC39A73972
+PT=CEF4896BBC86F1E02312479C40D96DAE
+
+I=273
+KEY=0FAB0DCFB6E3E7940B6D81D2B8D7373BD8B1D27878063876
+CT=CEF4896BBC86F1E02312479C40D96DAE
+PT=F195F5321FCAA68B0B0CBA83978A8084
+
+I=274
+KEY=F860076D3847A80BFAF874E0A71D91B0D3BD68FBEF8CB8F2
+CT=F195F5321FCAA68B0B0CBA83978A8084
+PT=861575205386223EBC6B48B22C35A2A6
+
+I=275
+KEY=B2DB77DC3E18C3A77CED01C0F49BB38E6FD62049C3B91A54
+CT=861575205386223EBC6B48B22C35A2A6
+PT=DC074F3D41C62DA9D609A982DEB9E074
+
+I=276
+KEY=E632B0C6EE68910EA0EA4EFDB55D9E27B9DF89CB1D00FA20
+CT=DC074F3D41C62DA9D609A982DEB9E074
+PT=6933F4F193B028A22B913453B0B4C9A2
+
+I=277
+KEY=88AA3FEE5FDFA336C9D9BA0C26EDB685924EBD98ADB43382
+CT=6933F4F193B028A22B913453B0B4C9A2
+PT=56811E665DDFBEA07A7C2C762F0D5C73
+
+I=278
+KEY=2A0A1FE31ADFC64F9F58A46A7B320825E83291EE82B96FF1
+CT=56811E665DDFBEA07A7C2C762F0D5C73
+PT=CFF92E47C8C973ADA7B57D9FE320B356
+
+I=279
+KEY=7958F9D10B6DC91050A18A2DB3FB7B884F87EC716199DCA7
+CT=CFF92E47C8C973ADA7B57D9FE320B356
+PT=A55A4F827552761580DC27E0712051B1
+
+I=280
+KEY=ADDB73FE13D439CAF5FBC5AFC6A90D9DCF5BCB9110B98D16
+CT=A55A4F827552761580DC27E0712051B1
+PT=734B095C3C54FCDE26C33659C82CACCB
+
+I=281
+KEY=E979AF9C739F60AE86B0CCF3FAFDF143E998FDC8D89521DD
+CT=734B095C3C54FCDE26C33659C82CACCB
+PT=122A4F2ADE6C69364943658517A56587
+
+I=282
+KEY=E05BDC75E94EB2A8949A83D924919875A0DB984DCF30445A
+CT=122A4F2ADE6C69364943658517A56587
+PT=C6EF3170C5EF69B479AC6653E8B7E979
+
+I=283
+KEY=67AF0BE0DE572F595275B2A9E17EF1C1D977FE1E2787AD23
+CT=C6EF3170C5EF69B479AC6653E8B7E979
+PT=51113FF8A1000A5449F24E8E5363FB72
+
+I=284
+KEY=7C8DCBB512AE775603648D51407EFB959085B09074E45651
+CT=51113FF8A1000A5449F24E8E5363FB72
+PT=B9341E24A41C9D9CE56D6E4F17A7A311
+
+I=285
+KEY=EEBE49DAF88030F5BA509375E462660975E8DEDF6343F540
+CT=B9341E24A41C9D9CE56D6E4F17A7A311
+PT=26A135C466B061791DE40A40E9366FC6
+
+I=286
+KEY=A06A0B9127769EF79CF1A6B182D20770680CD49F8A759A86
+CT=26A135C466B061791DE40A40E9366FC6
+PT=AE832B68C147CF8A70A8E5CCC3FF05F2
+
+I=287
+KEY=CD394B7808099B2832728DD94395C8FA18A43153498A9F74
+CT=AE832B68C147CF8A70A8E5CCC3FF05F2
+PT=72747F478E3AE57C6C7D6D4E5C4FCE71
+
+I=288
+KEY=80D4A1BD538D11434006F29ECDAF2D8674D95C1D15C55105
+CT=72747F478E3AE57C6C7D6D4E5C4FCE71
+PT=21539022400BEE401E8FE7E9F0F7AAC3
+
+I=289
+KEY=C8BCB868E11B46E3615562BC8DA4C3C66A56BBF4E532FBC6
+CT=21539022400BEE401E8FE7E9F0F7AAC3
+PT=44149C7C375F07B7169C8A9A14133C8C
+
+I=290
+KEY=DFC35DD4FAD95C2A2541FEC0BAFBC4717CCA316EF121C74A
+CT=44149C7C375F07B7169C8A9A14133C8C
+PT=2A7FA9D2EACC0C5444510E7D69EB3FD6
+
+I=291
+KEY=73B0B53EE6D591140F3E57125037C825389B3F1398CAF89C
+CT=2A7FA9D2EACC0C5444510E7D69EB3FD6
+PT=9949145B8C88D03BBA46FEBE9856B732
+
+I=292
+KEY=7BFBD6A0A317DEE996774349DCBF181E82DDC1AD009C4FAE
+CT=9949145B8C88D03BBA46FEBE9856B732
+PT=714E072347ECDEA4F8EB2B02746FBC66
+
+I=293
+KEY=CA326A1D191B2BC6E739446A9B53C6BA7A36EAAF74F3F3C8
+CT=714E072347ECDEA4F8EB2B02746FBC66
+PT=CCF2295814759A5004E8C3E2B97C4958
+
+I=294
+KEY=428400F7196D32C62BCB6D328F265CEA7EDE294DCD8FBA90
+CT=CCF2295814759A5004E8C3E2B97C4958
+PT=12108AB0753EAAE007DEFF2EBA8A3EF0
+
+I=295
+KEY=3E38F6FA3F49742339DBE782FA18F60A7900D66377058460
+CT=12108AB0753EAAE007DEFF2EBA8A3EF0
+PT=0109AC127FB55B91BC922EDFF3C43819
+
+I=296
+KEY=07C585ABD1C227D638D24B9085ADAD9BC592F8BC84C1BC79
+CT=0109AC127FB55B91BC922EDFF3C43819
+PT=33FF03F6966E81EE28889CFA0B9BA8B9
+
+I=297
+KEY=FB823872148252C20B2D486613C32C75ED1A64468F5A14C0
+CT=33FF03F6966E81EE28889CFA0B9BA8B9
+PT=D8468C180BAC0F6D703611DDAD951014
+
+I=298
+KEY=F81900EAD21ECE3BD36BC47E186F23189D2C759B22CF04D4
+CT=D8468C180BAC0F6D703611DDAD951014
+PT=07994906A8377D64F2D32DB4BB170EF1
+
+I=299
+KEY=2ADC8C0244307531D4F28D78B0585E7C6FFF582F99D80A25
+CT=07994906A8377D64F2D32DB4BB170EF1
+PT=48382015F82AA7EC8944C40275595CEF
+
+I=300
+KEY=2E917F5C5BAB80939CCAAD6D4872F990E6BB9C2DEC8156CA
+CT=48382015F82AA7EC8944C40275595CEF
+PT=D4EEE0A1A56118EB8F6AE16FE16F70ED
+
+I=301
+KEY=126D396B29E0252248244DCCED13E17B69D17D420DEE2627
+CT=D4EEE0A1A56118EB8F6AE16FE16F70ED
+PT=358E5FAE4A4ED6B1058E32942AE030DB
+
+I=302
+KEY=D390A60684F5C9147DAA1262A75D37CA6C5F4FD6270E16FC
+CT=358E5FAE4A4ED6B1058E32942AE030DB
+PT=B9730D311EA8312DAC34F444A4560DDC
+
+I=303
+KEY=0B2A03E62FCD9B06C4D91F53B9F506E7C06BBB9283581B20
+CT=B9730D311EA8312DAC34F444A4560DDC
+PT=D64F286B32B4058A51B73844BCA93DDA
+
+I=304
+KEY=5858183C5713BBD6129637388B41036D91DC83D63FF126FA
+CT=D64F286B32B4058A51B73844BCA93DDA
+PT=78425B7FE64D972C642ED17369ED8844
+
+I=305
+KEY=C555D9DC23D3A1846AD46C476D0C9441F5F252A5561CAEBE
+CT=78425B7FE64D972C642ED17369ED8844
+PT=2DE9202F4CD7F67C7B7F94CF7F3B9B5A
+
+I=306
+KEY=7BA871DA6E336CFA473D4C6821DB623D8E8DC66A292735E4
+CT=2DE9202F4CD7F67C7B7F94CF7F3B9B5A
+PT=A30322EC9A51266B50153995BCEBC846
+
+I=307
+KEY=55BF35687EBA169AE43E6E84BB8A4456DE98FFFF95CCFDA2
+CT=A30322EC9A51266B50153995BCEBC846
+PT=14754B0469683F36E4791FD9B8B1C585
+
+I=308
+KEY=0404CAE90360F118F04B2580D2E27B603AE1E0262D7D3827
+CT=14754B0469683F36E4791FD9B8B1C585
+PT=E8592DC147A1DC4F48D43E365B9D63FF
+
+I=309
+KEY=109E16AA717A4EF4181208419543A72F7235DE1076E05BD8
+CT=E8592DC147A1DC4F48D43E365B9D63FF
+PT=47A3BF0743562C7D412563C94C2CD717
+
+I=310
+KEY=0A8DC7647F8C06D15FB1B746D6158B523310BDD93ACC8CCF
+CT=47A3BF0743562C7D412563C94C2CD717
+PT=63F8C6A062937471364050815D856793
+
+I=311
+KEY=CC9B8854C13F73623C4971E6B486FF230550ED586749EB5C
+CT=63F8C6A062937471364050815D856793
+PT=E70443AF44BF549607251A86CD83A4D3
+
+I=312
+KEY=2D067D896DF1E749DB4D3249F039ABB50275F7DEAACA4F8F
+CT=E70443AF44BF549607251A86CD83A4D3
+PT=ACEF2AE95CA660AEE513BF48BCF7D125
+
+I=313
+KEY=DEC45DD3C0DAD30A77A218A0AC9FCB1BE7664896163D9EAA
+CT=ACEF2AE95CA660AEE513BF48BCF7D125
+PT=859E9E4001245A50ED76055539672F1A
+
+I=314
+KEY=6F208E93D9C89CE8F23C86E0ADBB914B0A104DC32F5AB1B0
+CT=859E9E4001245A50ED76055539672F1A
+PT=42B059061FE4C86C7AC2B7C8B62820C2
+
+I=315
+KEY=86EC7CE558994E8EB08CDFE6B25F592770D2FA0B99729172
+CT=42B059061FE4C86C7AC2B7C8B62820C2
+PT=01C6296F1532450F182D6A3FC8249DD7
+
+I=316
+KEY=C74B31CEC9B31130B14AF689A76D1C2868FF903451560CA5
+CT=01C6296F1532450F182D6A3FC8249DD7
+PT=14334054946821E3FE8D72D1EF402EE1
+
+I=317
+KEY=AC636B2AD3699560A579B6DD33053DCB9672E2E5BE162244
+CT=14334054946821E3FE8D72D1EF402EE1
+PT=F09B2FE9A8F17CD847532D4979D2A8C4
+
+I=318
+KEY=6F956E3680FC783155E299349BF44113D121CFACC7C48A80
+CT=F09B2FE9A8F17CD847532D4979D2A8C4
+PT=4C97BD8822E63C7A2EE0E444563AF1C8
+
+I=319
+KEY=C69B2FB718C41B1A197524BCB9127D69FFC12BE891FE7B48
+CT=4C97BD8822E63C7A2EE0E444563AF1C8
+PT=344E85BE2C8B36430C8058B310062171
+
+I=320
+KEY=BFFA143B8A18CACF2D3BA10295994B2AF341735B81F85A39
+CT=344E85BE2C8B36430C8058B310062171
+PT=FF3F882CB22D13A8631DCA6DD702D0E0
+
+I=321
+KEY=22F58A0FC077AB5FD204292E27B45882905CB93656FA8AD9
+CT=FF3F882CB22D13A8631DCA6DD702D0E0
+PT=866B2E52CF71505973D9D6642C8178BB
+
+I=322
+KEY=DC8CE7A9130F3662546F077CE8C508DBE3856F527A7BF262
+CT=866B2E52CF71505973D9D6642C8178BB
+PT=4802741ADF67A3811A8AEC7008D8827E
+
+I=323
+KEY=743B09AA8FD3C6A01C6D736637A2AB5AF90F832272A3701C
+CT=4802741ADF67A3811A8AEC7008D8827E
+PT=FD3701579815D02BE878C74ABB98C59B
+
+I=324
+KEY=865B3EC9EFBE27D0E15A7231AFB77B7111774468C93BB587
+CT=FD3701579815D02BE878C74ABB98C59B
+PT=99BCA8250D54F3A9A72054AF5578F842
+
+I=325
+KEY=041C037E08923FFF78E6DA14A2E388D8B65710C79C434DC5
+CT=99BCA8250D54F3A9A72054AF5578F842
+PT=F0DA5C0E446547356D5027BA346A831C
+
+I=326
+KEY=FBABCE025CF5FF3D883C861AE686CFEDDB07377DA829CED9
+CT=F0DA5C0E446547356D5027BA346A831C
+PT=EED0140AF408652DD879E3289536C389
+
+I=327
+KEY=3F12399A3E5C0F9566EC9210128EAAC0037ED4553D1F0D50
+CT=EED0140AF408652DD879E3289536C389
+PT=FDC7299A95BDB941A299478B7B409EF8
+
+I=328
+KEY=D541517B701036E39B2BBB8A87331381A1E793DE465F93A8
+CT=FDC7299A95BDB941A299478B7B409EF8
+PT=5BE5AEC30578CD03BA7B17E8B16AAFBF
+
+I=329
+KEY=6657840FF425DD8AC0CE1549824BDE821B9C8436F7353C17
+CT=5BE5AEC30578CD03BA7B17E8B16AAFBF
+PT=3C7A9745F48DA61CF7875A449E24C735
+
+I=330
+KEY=52D29BBD64550DFBFCB4820C76C6789EEC1BDE726911FB22
+CT=3C7A9745F48DA61CF7875A449E24C735
+PT=69516DE0343F3552830D28CE8B9A282C
+
+I=331
+KEY=3699B16BB0349B9195E5EFEC42F94DCC6F16F6BCE28BD30E
+CT=69516DE0343F3552830D28CE8B9A282C
+PT=EB09EE300286690EA65A30526A43B86B
+
+I=332
+KEY=60E79B9E7C41814E7EEC01DC407F24C2C94CC6EE88C86B65
+CT=EB09EE300286690EA65A30526A43B86B
+PT=A235384FE517A5F455BBE6B850C05E33
+
+I=333
+KEY=11F650282BBCB584DCD93993A56881369CF72056D8083556
+CT=A235384FE517A5F455BBE6B850C05E33
+PT=41E297350390E91EC00FF875B3CA60BA
+
+I=334
+KEY=11B449F7EE983AB89D3BAEA6A6F868285CF8D8236BC255EC
+CT=41E297350390E91EC00FF875B3CA60BA
+PT=5FB9F6408D54401A9A76288AE3A04944
+
+I=335
+KEY=54CBA9A5782ED91FC28258E62BAC2832C68EF0A988621CA8
+CT=5FB9F6408D54401A9A76288AE3A04944
+PT=7C9CD2510E96FF37BF75E57E84098535
+
+I=336
+KEY=871169F28E704C95BE1E8AB7253AD70579FB15D70C6B999D
+CT=7C9CD2510E96FF37BF75E57E84098535
+PT=8E041B8C74A84D747B02714452B34F11
+
+I=337
+KEY=7F44ED6AA755957A301A913B51929A7102F964935ED8D68C
+CT=8E041B8C74A84D747B02714452B34F11
+PT=3698639F56657A40D52B9B8015448C2A
+
+I=338
+KEY=EEAF09001996BA6E0682F2A407F7E031D7D2FF134B9C5AA6
+CT=3698639F56657A40D52B9B8015448C2A
+PT=79FB5E4A065D29E1CA3E15897B60032F
+
+I=339
+KEY=D21CCA06254A64C97F79ACEE01AAC9D01DECEA9A30FC5989
+CT=79FB5E4A065D29E1CA3E15897B60032F
+PT=C582F5F8D9D2E9323C769B2B1AE369BD
+
+I=340
+KEY=29D2F84E4568BA6FBAFB5916D87820E2219A71B12A1F3034
+CT=C582F5F8D9D2E9323C769B2B1AE369BD
+PT=916405DC8F2AD50548997D87BCCADBFB
+
+I=341
+KEY=43AC4D54A8A0222F2B9F5CCA5752F5E769030C3696D5EBCF
+CT=916405DC8F2AD50548997D87BCCADBFB
+PT=0E9FF0E147A47056EC6B09837C9E0E62
+
+I=342
+KEY=9AF110B8274794772500AC2B10F685B1856805B5EA4BE5AD
+CT=0E9FF0E147A47056EC6B09837C9E0E62
+PT=3B6E3CAAC358427980E66E3D30D39E4F
+
+I=343
+KEY=49F910E7957BC95C1E6E9081D3AEC7C8058E6B88DA987BE2
+CT=3B6E3CAAC358427980E66E3D30D39E4F
+PT=25CBE5AB4C6785C0F2847CF89F2635AB
+
+I=344
+KEY=64D90092DD97AC3C3BA5752A9FC94208F70A177045BE4E49
+CT=25CBE5AB4C6785C0F2847CF89F2635AB
+PT=3D9200D39461D8B2CE7874DA20BFD9DA
+
+I=345
+KEY=C7A8403AFB011673063775F90BA89ABA397263AA65019793
+CT=3D9200D39461D8B2CE7874DA20BFD9DA
+PT=E61E7E06A1E1F656AE8F8C29C96E5A16
+
+I=346
+KEY=071AF635AF7A9602E0290BFFAA496CEC97FDEF83AC6FCD85
+CT=E61E7E06A1E1F656AE8F8C29C96E5A16
+PT=7488BB35F06E94F31A744D1EA95E71D0
+
+I=347
+KEY=A4B5ECB7047E08D694A1B0CA5A27F81F8D89A29D0531BC55
+CT=7488BB35F06E94F31A744D1EA95E71D0
+PT=3912DC00C0AB79C473CA2CC8F69262F0
+
+I=348
+KEY=BD4478B38A0E9347ADB36CCA9A8C81DBFE438E55F3A3DEA5
+CT=3912DC00C0AB79C473CA2CC8F69262F0
+PT=C4B546F134A016DADA8E7C478B1E7D45
+
+I=349
+KEY=F7B6F476517483AD69062A3BAE2C970124CDF21278BDA3E0
+CT=C4B546F134A016DADA8E7C478B1E7D45
+PT=298524C5D468EBFA97DEFEC7B80EE752
+
+I=350
+KEY=8E0C5244F7417C2440830EFE7A447CFBB3130CD5C0B344B2
+CT=298524C5D468EBFA97DEFEC7B80EE752
+PT=B27EFB90BA3A27A1077C6742D5B68396
+
+I=351
+KEY=C6E8F264FA0C9A9AF2FDF56EC07E5B5AB46F6B971505C724
+CT=B27EFB90BA3A27A1077C6742D5B68396
+PT=D02C27A94DD3B772B338C7462379B009
+
+I=352
+KEY=AD694D243DCC6B7B22D1D2C78DADEC280757ACD1367C772D
+CT=D02C27A94DD3B772B338C7462379B009
+PT=1CED06084E67BA4BAD3C331F4074B9FF
+
+I=353
+KEY=68AEF48D86D395583E3CD4CFC3CA5663AA6B9FCE7608CED2
+CT=1CED06084E67BA4BAD3C331F4074B9FF
+PT=C0D7811FE8630B3E7C3A60DA9042A6B2
+
+I=354
+KEY=670A8D40573F598AFEEB55D02BA95D5DD651FF14E64A6860
+CT=C0D7811FE8630B3E7C3A60DA9042A6B2
+PT=45F92C84CE2AEC6E7953C8AAC5901D0F
+
+I=355
+KEY=D44FD97B0D59C923BB127954E583B133AF0237BE23DA756F
+CT=45F92C84CE2AEC6E7953C8AAC5901D0F
+PT=23A4863C994EFE93E7CE1C89FE14143D
+
+I=356
+KEY=4E08C6A539C74A6598B6FF687CCD4FA048CC2B37DDCE6152
+CT=23A4863C994EFE93E7CE1C89FE14143D
+PT=85EB5F46988211E3077FDBE38F1EBE6B
+
+I=357
+KEY=21B17D5E461224B31D5DA02EE44F5E434FB3F0D452D0DF39
+CT=85EB5F46988211E3077FDBE38F1EBE6B
+PT=59CF6CCC81A8BC17A52D7550B40C7514
+
+I=358
+KEY=6CC595309F161F3E4492CCE265E7E254EA9E8584E6DCAA2D
+CT=59CF6CCC81A8BC17A52D7550B40C7514
+PT=13DF4C2AA74A4B9123B3A57FE94F85BE
+
+I=359
+KEY=77B90151B41B1B7D574D80C8C2ADA9C5C92D20FB0F932F93
+CT=13DF4C2AA74A4B9123B3A57FE94F85BE
+PT=6DEDE53AD5DC2A87744DA0EA561977A3
+
+I=360
+KEY=8E1683C57C1817C23AA065F217718342BD608011598A5830
+CT=6DEDE53AD5DC2A87744DA0EA561977A3
+PT=F9D912AAB5ED1ACBD0475411DF98F49C
+
+I=361
+KEY=E9FDD94AE4B4FABAC3797758A29C99896D27D4008612ACAC
+CT=F9D912AAB5ED1ACBD0475411DF98F49C
+PT=853C907D9FD35B61D2ABBE5C1A89DB4B
+
+I=362
+KEY=BCC524DF4D452AE14645E7253D4FC2E8BF8C6A5C9C9B77E7
+CT=853C907D9FD35B61D2ABBE5C1A89DB4B
+PT=874C4BC1993FBA12136443B57F9523BE
+
+I=363
+KEY=9F5EFA7196589240C109ACE4A47078FAACE829E9E30E5459
+CT=874C4BC1993FBA12136443B57F9523BE
+PT=E6B6E9133DD0EC2844EF3CC0C2F9E4AC
+
+I=364
+KEY=2F0731DB4FA3024127BF45F799A094D2E807152921F7B0F5
+CT=E6B6E9133DD0EC2844EF3CC0C2F9E4AC
+PT=20B41EE01134041DF8D11BB7F86928EA
+
+I=365
+KEY=7E44D240F06AAA5E070B5B17889490CF10D60E9ED99E981F
+CT=20B41EE01134041DF8D11BB7F86928EA
+PT=BF6B03096DCDC052B1325CC34BF6E56C
+
+I=366
+KEY=D8D3E3D538C8CA34B860581EE559509DA1E4525D92687D73
+CT=BF6B03096DCDC052B1325CC34BF6E56C
+PT=5ED3E40FB5C34DD1F370C3AD72C7C24D
+
+I=367
+KEY=F3DF20767CDA5E0CE6B3BC11509A1D4C529491F0E0AFBF3E
+CT=5ED3E40FB5C34DD1F370C3AD72C7C24D
+PT=3EA6BCE2317C5D696DF8240C481B34DD
+
+I=368
+KEY=484932A15D75173FD81500F361E640253F6CB5FCA8B48BE3
+CT=3EA6BCE2317C5D696DF8240C481B34DD
+PT=41D6E077746FE1A9307E1107631A5D2C
+
+I=369
+KEY=EF960956685DE1CE99C3E0841589A18C0F12A4FBCBAED6CF
+CT=41D6E077746FE1A9307E1107631A5D2C
+PT=D0C6DDEF0A623686BA303C278D445964
+
+I=370
+KEY=82477D8D682C1D4849053D6B1FEB970AB52298DC46EA8FAB
+CT=D0C6DDEF0A623686BA303C278D445964
+PT=EEFFA6025D6CAFBF9DC18E5B1B99A6ED
+
+I=371
+KEY=15D8DCF80A26856AA7FA9B69428738B528E316875D732946
+CT=EEFFA6025D6CAFBF9DC18E5B1B99A6ED
+PT=38E222ABAA07CDAE9CC02FAC84EC0FC1
+
+I=372
+KEY=556151278277D7579F18B9C2E880F51BB423392BD99F2687
+CT=38E222ABAA07CDAE9CC02FAC84EC0FC1
+PT=B00C719E6A320E4385794EB7F23C0D80
+
+I=373
+KEY=777F91003E4410572F14C85C82B2FB58315A779C2BA32B07
+CT=B00C719E6A320E4385794EB7F23C0D80
+PT=0E667CA932023D2EFD8DDBDED5A43D78
+
+I=374
+KEY=130507FC817F14432172B4F5B0B0C676CCD7AC42FE07167F
+CT=0E667CA932023D2EFD8DDBDED5A43D78
+PT=6B15DA892F0B5916F31BB74FC7D03F9A
+
+I=375
+KEY=D045A84BBF62DE2E4A676E7C9FBB9F603FCC1B0D39D729E5
+CT=6B15DA892F0B5916F31BB74FC7D03F9A
+PT=EBEF6DC298D63BF6E6E46F833B217033
+
+I=376
+KEY=7742FB68CDF60735A18803BE076DA496D928748E02F659D6
+CT=EBEF6DC298D63BF6E6E46F833B217033
+PT=48DC6F65F193AFCCE559EA6F04FBD79A
+
+I=377
+KEY=5CE32BC22C77B664E9546CDBF6FE0B5A3C719EE1060D8E4C
+CT=48DC6F65F193AFCCE559EA6F04FBD79A
+PT=D0596880F92716C51E41519C640AEFDA
+
+I=378
+KEY=2DA6B73C5131E24C390D045B0FD91D9F2230CF7D62076196
+CT=D0596880F92716C51E41519C640AEFDA
+PT=ABB7C3E499086F53C4DB97640168943B
+
+I=379
+KEY=E41C1A826978491892BAC7BF96D172CCE6EB5819636FF5AD
+CT=ABB7C3E499086F53C4DB97640168943B
+PT=0CC58B3D0370317E1025E1AF97962646
+
+I=380
+KEY=501012EE411DCDC59E7F4C8295A143B2F6CEB9B6F4F9D3EB
+CT=0CC58B3D0370317E1025E1AF97962646
+PT=28920AED2B644C4346FC146903887244
+
+I=381
+KEY=97B7E8C1147A5062B6ED466FBEC50FF1B032ADDFF771A1AF
+CT=28920AED2B644C4346FC146903887244
+PT=E7A28DA5EC871DAF8C2D196C7ED8977F
+
+I=382
+KEY=988B9928402BCD63514FCBCA5242125E3C1FB4B389A936D0
+CT=E7A28DA5EC871DAF8C2D196C7ED8977F
+PT=013876A92413AED2E360A241FE021B25
+
+I=383
+KEY=3432357430ACC9135077BD637651BC8CDF7F16F277AB2DF5
+CT=013876A92413AED2E360A241FE021B25
+PT=10F1A56A8CFDA1D5044D5D0E53F6A773
+
+I=384
+KEY=CE94F859CD3E85F440861809FAAC1D59DB324BFC245D8A86
+CT=10F1A56A8CFDA1D5044D5D0E53F6A773
+PT=941C717EE6642DD474719F099AEEB1EB
+
+I=385
+KEY=A1BFA52EA232FDF0D49A69771CC8308DAF43D4F5BEB33B6D
+CT=941C717EE6642DD474719F099AEEB1EB
+PT=F31B47230ABC94977E14E1080528C1C9
+
+I=386
+KEY=37B36A8E7A3B4F2A27812E541674A41AD15735FDBB9BFAA4
+CT=F31B47230ABC94977E14E1080528C1C9
+PT=A91264221890CA93541B662F64A11C62
+
+I=387
+KEY=04F603F98A9D1AC78E934A760EE46E89854C53D2DF3AE6C6
+CT=A91264221890CA93541B662F64A11C62
+PT=05F5171B639825EC67A37B3671F2F884
+
+I=388
+KEY=A294EBBBD53D18DD8B665D6D6D7C4B65E2EF28E4AEC81E42
+CT=05F5171B639825EC67A37B3671F2F884
+PT=B6FE84EB2987DE956953DEBA6FD2E029
+
+I=389
+KEY=E0E38A82F60E8EED3D98D98644FB95F08BBCF65EC11AFE6B
+CT=B6FE84EB2987DE956953DEBA6FD2E029
+PT=2741338CF00FBC70C4B1C67C97E85B97
+
+I=390
+KEY=2193D386143F6D761AD9EA0AB4F429804F0D302256F2A5FC
+CT=2741338CF00FBC70C4B1C67C97E85B97
+PT=E56C7C453E2E13028AD812F9CDB78E2F
+
+I=391
+KEY=05AD3BC4F1B29F17FFB5964F8ADA3A82C5D522DB9B452BD3
+CT=E56C7C453E2E13028AD812F9CDB78E2F
+PT=9A9B49AC0691F1576D515E935F042229
+
+I=392
+KEY=1588C005075F4674652EDFE38C4BCBD5A8847C48C44109FA
+CT=9A9B49AC0691F1576D515E935F042229
+PT=143E5F64AD38373D3B54FA24CC7C0AF5
+
+I=393
+KEY=731083CCCB22E7CF711080872173FCE893D0866C083D030F
+CT=143E5F64AD38373D3B54FA24CC7C0AF5
+PT=61F6AF426601588CB7C525255EC1A06D
+
+I=394
+KEY=DACEE3906B98DFC110E62FC54772A4642415A34956FCA362
+CT=61F6AF426601588CB7C525255EC1A06D
+PT=DB5DC1C3B3413F653D72F8744C2DD881
+
+I=395
+KEY=D9ACA0F56DCA4FC0CBBBEE06F4339B0119675B3D1AD17BE3
+CT=DB5DC1C3B3413F653D72F8744C2DD881
+PT=4E9D548DA49E992AD3123F53558909C9
+
+I=396
+KEY=12C2FE0C57D21C208526BA8B50AD022BCA75646E4F58722A
+CT=4E9D548DA49E992AD3123F53558909C9
+PT=EB2E835192E64ABC30C3F2662B703C47
+
+I=397
+KEY=7A43322D6174BA786E0839DAC24B4897FAB6960864284E6D
+CT=EB2E835192E64ABC30C3F2662B703C47
+PT=CD0690863F63F2B263D4C11190A7985B
+
+I=398
+KEY=EBC6D71978D39185A30EA95CFD28BA2599625719F48FD636
+CT=CD0690863F63F2B263D4C11190A7985B
+PT=C044E800B65CA78559D0642C370C7D3E
+
+I=399
+KEY=A1B6CE2EEC5FC386634A415C4B741DA0C0B23335C383AB08
+CT=C044E800B65CA78559D0642C370C7D3E
+PT=F1A81B68F6E5A6271A8CB24E7D9491EF
+
+=========================
+
+KEYSIZE=256
+
+I=0
+KEY=0000000000000000000000000000000000000000000000000000000000000000
+CT=00000000000000000000000000000000
+PT=058CCFFDBBCB382D1F6F56585D8A4ADE
+
+I=1
+KEY=85C6B2BB2300148F945AEBF1F021CF79058CCFFDBBCB382D1F6F56585D8A4ADE
+CT=058CCFFDBBCB382D1F6F56585D8A4ADE
+PT=15173A0EB65F5CC05E704EFE61D9E346
+
+I=2
+KEY=2447EC44111548FBB670B98F182D5DEE109BF5F30D9464ED411F18A63C53A998
+CT=15173A0EB65F5CC05E704EFE61D9E346
+PT=85F083ACC676D91EDD1ABFB43935237A
+
+I=3
+KEY=85D3E1D750CAA89BEE274AA7C32C2207956B765FCBE2BDF39C05A71205668AE2
+CT=85F083ACC676D91EDD1ABFB43935237A
+PT=42C8F0ABC58E0BEAC32911D2DD9FA8C8
+
+I=4
+KEY=CE86B24954745B2BAAF27010202EE7FAD7A386F40E6CB6195F2CB6C0D8F9222A
+CT=42C8F0ABC58E0BEAC32911D2DD9FA8C8
+PT=5E44123D2CA07981B073BB2749F557D6
+
+I=5
+KEY=CD7BCBBA4555A0D034FD7B528A1D042C89E794C922CCCF98EF5F0DE7910C75FC
+CT=5E44123D2CA07981B073BB2749F557D6
+PT=8B649458EA90F4F7E13467E509B7F164
+
+I=6
+KEY=EF28DFAED7794B1C7B892F3C98FCDC9602830091C85C3B6F0E6B6A0298BB8498
+CT=8B649458EA90F4F7E13467E509B7F164
+PT=F240D1F579DA2CA8839F7072DF52EBA3
+
+I=7
+KEY=C66605EC92F96B49F08CBC6276A0DC68F0C3D164B18617C78DF41A7047E96F3B
+CT=F240D1F579DA2CA8839F7072DF52EBA3
+PT=B05297490A394B4A1736DE7F8DC12969
+
+I=8
+KEY=347403B6E6344E1525B8D2BD4DCA343F4091462DBBBF5C8D9AC2C40FCA284652
+CT=B05297490A394B4A1736DE7F8DC12969
+PT=8BA49D44B98E67501235CE1C2F26BB28
+
+I=9
+KEY=B932CD0C70488602C56F92A0DA57BE27CB35DB6902313BDD88F70A13E50EFD7A
+CT=8BA49D44B98E67501235CE1C2F26BB28
+PT=86CE4E4D040C49F2717407157454162E
+
+I=10
+KEY=28F8B6B4AB2B0B81F3676F6E422D438C4DFB9524063D722FF9830D06915AEB54
+CT=86CE4E4D040C49F2717407157454162E
+PT=4E9CA7FB0FF9F38FC821CA91052483F9
+
+I=11
+KEY=5CD19F4D3C5B58602B101E15B39F51E4036732DF09C481A031A2C797947E68AD
+CT=4E9CA7FB0FF9F38FC821CA91052483F9
+PT=55E49ED59245C1850CB0C17C1CEEA05E
+
+I=12
+KEY=E822BB0D1F25F3DCA6FE0CB1A8AF39F15683AC0A9B8140253D1206EB8890C8F3
+CT=55E49ED59245C1850CB0C17C1CEEA05E
+PT=F7F0BFA319AC289C9F64E6FCDD531B44
+
+I=13
+KEY=8B64FF354C6E303F14EA34C9F667FEC9A17313A9822D68B9A276E01755C3D3B7
+CT=F7F0BFA319AC289C9F64E6FCDD531B44
+PT=6ACB8A177226AE47E2170F77D2FE4923
+
+I=14
+KEY=1A9D440EBAC3F3625E229B66C5D9249CCBB899BEF00BC6FE4061EF60873D9A94
+CT=6ACB8A177226AE47E2170F77D2FE4923
+PT=BAA9BB819332A87D6004164927EAC699
+
+I=15
+KEY=97F92B9AD44A3182FF10E07747C560B37111223F63396E832065F929A0D75C0D
+CT=BAA9BB819332A87D6004164927EAC699
+PT=EB84793E2D68632900B0517392EC4B94
+
+I=16
+KEY=2AEEBA2AC59870A7B4274B80FE74D55A9A955B014E510DAA20D5A85A323B1799
+CT=EB84793E2D68632900B0517392EC4B94
+PT=6C662FBE2B22394CC1D45453772C72BA
+
+I=17
+KEY=EEA4B3C4F96C42E3B7DF5A3870C85B69F6F374BF657334E6E101FC0945176523
+CT=6C662FBE2B22394CC1D45453772C72BA
+PT=70D2BBC1FA7D49848D94112DA93A3C3C
+
+I=18
+KEY=F930D1529C654F31549809C6CD5CC4608621CF7E9F0E7D626C95ED24EC2D591F
+CT=70D2BBC1FA7D49848D94112DA93A3C3C
+PT=1AFF91E67039133946638E4E505310C2
+
+I=19
+KEY=5D0F461C1A5FF7BA5C93F0CED9DD49FF9CDE5E98EF376E5B2AF6636ABC7E49DD
+CT=1AFF91E67039133946638E4E505310C2
+PT=8E4358B22DE7BCDC8B8409E6250633BF
+
+I=20
+KEY=AA4B475845EB19F601856A40AB517594129D062AC2D0D287A1726A8C99787A62
+CT=8E4358B22DE7BCDC8B8409E6250633BF
+PT=2A79FE5A222C9503954346D6C15AC679
+
+I=21
+KEY=9703F4DD85A3BE85343FFD15950A266B38E4F870E0FC478434312C5A5822BC1B
+CT=2A79FE5A222C9503954346D6C15AC679
+PT=0FF812C5B863282C294D7069F830EE86
+
+I=22
+KEY=3DD1B2ACBC6568851E767D20D82AD324371CEAB5589F6FA81D7C5C33A012529D
+CT=0FF812C5B863282C294D7069F830EE86
+PT=D449218625DE49D2B9514E032CA096E7
+
+I=23
+KEY=95CC16235D3DFF4F7DB2116D2B380F39E355CB337D41267AA42D12308CB2C47A
+CT=D449218625DE49D2B9514E032CA096E7
+PT=F951EAC3BC78DB0AE13FDC33048D2D81
+
+I=24
+KEY=A6F55AFBDA7EA939F6F2A28530C416781A0421F0C139FD704512CE03883FE9FB
+CT=F951EAC3BC78DB0AE13FDC33048D2D81
+PT=7D5A03A955F6403F918AC915AC22B797
+
+I=25
+KEY=7C5D39885F4C0F4FCF672321B711C5B7675E225994CFBD4FD4980716241D5E6C
+CT=7D5A03A955F6403F918AC915AC22B797
+PT=CA2E1C274073AD2A3AE35C60ECA52A58
+
+I=26
+KEY=4E7B914B84BFA1A2D7BD409AFADD2EDCAD703E7ED4BC1065EE7B5B76C8B87434
+CT=CA2E1C274073AD2A3AE35C60ECA52A58
+PT=C5048FA0148CED10A06E107269DA9C95
+
+I=27
+KEY=F62D8C4822C5F89D51E3C68695D91CA66874B1DEC030FD754E154B04A162E8A1
+CT=C5048FA0148CED10A06E107269DA9C95
+PT=CB9B457A7A24577DA71AC335F0572DAB
+
+I=28
+KEY=C37AAD7CB20087F4B98390C59D3ECFB2A3EFF4A4BA14AA08E90F88315135C50A
+CT=CB9B457A7A24577DA71AC335F0572DAB
+PT=FA60BFF170DD30C29DF1807C1612CD67
+
+I=29
+KEY=1A2C6858B37D0341BF8796FB72D00B72598F4B55CAC99ACA74FE084D4727086D
+CT=FA60BFF170DD30C29DF1807C1612CD67
+PT=E2FACFB5DF4E69C911838FCC546D0C8E
+
+I=30
+KEY=039B73E3A8DCF3C678FBC246AAECDAECBB7584E01587F303657D8781134A04E3
+CT=E2FACFB5DF4E69C911838FCC546D0C8E
+PT=749AB2B9176AFDB8B6714DF44BBF2B58
+
+I=31
+KEY=773D90EA7ECA29DFD9141A42EB2BBC64CFEF365902ED0EBBD30CCA7558F52FBB
+CT=749AB2B9176AFDB8B6714DF44BBF2B58
+PT=0285E58D09A8D33FB196FD16A8DF37C0
+
+I=32
+KEY=598262B046B44784D977F6BE2553C6ACCD6AD3D40B45DD84629A3763F02A187B
+CT=0285E58D09A8D33FB196FD16A8DF37C0
+PT=1C952C46AE829D8805031A44F9D85521
+
+I=33
+KEY=AFAE657D3220CD1E6199A49754525F4AD1FFFF92A5C7400C67992D2709F24D5A
+CT=1C952C46AE829D8805031A44F9D85521
+PT=EED0A47E63FF354B4D9C53F7FD75D720
+
+I=34
+KEY=A61F583BCFD120B8CABE1E4C616F4FC73F2F5BECC63875472A057ED0F4879A7A
+CT=EED0A47E63FF354B4D9C53F7FD75D720
+PT=10C1F0F7C32AD36F03AEA8DCE6AAE7BC
+
+I=35
+KEY=FB76D4B83A7F50482A92F5A92CB60F522FEEAB1B0512A62829ABD60C122D7DC6
+CT=10C1F0F7C32AD36F03AEA8DCE6AAE7BC
+PT=372488DF6543180F1F2AE15E5B0C8785
+
+I=36
+KEY=35EAC2BA73F55570CB727220C027FE6218CA23C46051BE27368137524921FA43
+CT=372488DF6543180F1F2AE15E5B0C8785
+PT=3DE420FF3699D68DB69966F57D09045A
+
+I=37
+KEY=48B6E08B9FD9B5C130E1829CD4540D9C252E033B56C868AA801851A73428FE19
+CT=3DE420FF3699D68DB69966F57D09045A
+PT=7858F396DC520131C789CB8F8C919CCD
+
+I=38
+KEY=DB39C13F29241FF29C5BEB839705AD5B5D76F0AD8A9A699B47919A28B8B962D4
+CT=7858F396DC520131C789CB8F8C919CCD
+PT=07BE8BBF9FCD7D04888E61935DD7222F
+
+I=39
+KEY=A5F9B675531AB58C1FFC316C9359EA335AC87B121557149FCF1FFBBBE56E40FB
+CT=07BE8BBF9FCD7D04888E61935DD7222F
+PT=EDD619B7C12E2AF6BDAA953B2E7871EF
+
+I=40
+KEY=A02D1F14A64BBC67DD7EE9EAB3FB0EADB71E62A5D4793E6972B56E80CB163114
+CT=EDD619B7C12E2AF6BDAA953B2E7871EF
+PT=C748CDB645F1A1E44A63FAF00B2C3A45
+
+I=41
+KEY=177D7A6843B5ABBEB212E68734A7A05C7056AF1391889F8D38D69470C03A0B51
+CT=C748CDB645F1A1E44A63FAF00B2C3A45
+PT=BD3ED4C8CD7DBF4299AC63FE119D291E
+
+I=42
+KEY=BD9BDC6BD09DEED3E75C918BE55E5332CD687BDB5CF520CFA17AF78ED1A7224F
+CT=BD3ED4C8CD7DBF4299AC63FE119D291E
+PT=A16B82F958441E90A965427C854EECBB
+
+I=43
+KEY=E6325C33EC76F8EDE02707A3AE82F1096C03F92204B13E5F081FB5F254E9CEF4
+CT=A16B82F958441E90A965427C854EECBB
+PT=E04E642689D1AB78E7CDE26D0563901C
+
+I=44
+KEY=B8543DB3071AB9F0802D4106FBDA59648C4D9D048D609527EFD2579F518A5EE8
+CT=E04E642689D1AB78E7CDE26D0563901C
+PT=08E59C72C13C030DA3C50300861EA097
+
+I=45
+KEY=ECDD43A6B225DB325BFFE5462B66E97884A801764C5C962A4C17549FD794FE7F
+CT=08E59C72C13C030DA3C50300861EA097
+PT=C224B2EFEE07AAC33F1F6EB1295D9A50
+
+I=46
+KEY=741D627C8B47BED4497C71FDC9854912468CB399A25B3CE973083A2EFEC9642F
+CT=C224B2EFEE07AAC33F1F6EB1295D9A50
+PT=1653CE734D27B44369D4FE582E7A885F
+
+I=47
+KEY=A47BDC62B1D80815AC6BF04481C5601F50DF7DEAEF7C88AA1ADCC476D0B3EC70
+CT=1653CE734D27B44369D4FE582E7A885F
+PT=CADC89828B6147FAEC581DDCFF3C0960
+
+I=48
+KEY=CB91E738F51C111DAC2E0A3BF7B076A39A03F468641DCF50F684D9AA2F8FE510
+CT=CADC89828B6147FAEC581DDCFF3C0960
+PT=49402F0F4AFA2518D57C5D1CFCECC0F2
+
+I=49
+KEY=BDA1FFAEE7B93EDFCA4374871A149550D343DB672EE7EA4823F884B6D36325E2
+CT=49402F0F4AFA2518D57C5D1CFCECC0F2
+PT=EBFF53AB449DE5A53EDC6E595AA47B10
+
+I=50
+KEY=18D865B8E8C779268D3876C22AF479FB38BC88CC6A7A0FED1D24EAEF89C75EF2
+CT=EBFF53AB449DE5A53EDC6E595AA47B10
+PT=30073458509F9AC9DA21B2DF566AB3BE
+
+I=51
+KEY=967E2580238300563A34A6E70D84B4FF08BBBC943AE59524C7055830DFADED4C
+CT=30073458509F9AC9DA21B2DF566AB3BE
+PT=5AB9F90CC2A7603A68E2ACA95A2DE55D
+
+I=52
+KEY=A469A4E2F0B3847F3B52886FAD7DBAF652024598F842F51EAFE7F49985800811
+CT=5AB9F90CC2A7603A68E2ACA95A2DE55D
+PT=F22A13F395B6064172CA9DC572C26B2E
+
+I=53
+KEY=9EA4946ED73FF8BB8700C18967C01968A028566B6DF4F35FDD2D695CF742633F
+CT=F22A13F395B6064172CA9DC572C26B2E
+PT=26E44B9F3DEBA8EE3531DDFA42F1DC14
+
+I=54
+KEY=3D25EEEACEF18702FD3896283CFF8A8386CC1DF4501F5BB1E81CB4A6B5B3BF2B
+CT=26E44B9F3DEBA8EE3531DDFA42F1DC14
+PT=32D9F05174FFF34594E952B7ADE09737
+
+I=55
+KEY=8BF2A692F6A35980C0CF02FF4650871BB415EDA524E0A8F47CF5E6111853281C
+CT=32D9F05174FFF34594E952B7ADE09737
+PT=7BEF027DEB1FF22774CE8A8A101DD41B
+
+I=56
+KEY=C90BF0E1A8B615B4C8BD318260BB80AECFFAEFD8CFFF5AD3083B6C9B084EFC07
+CT=7BEF027DEB1FF22774CE8A8A101DD41B
+PT=CF6B2444DFBBFE5B6A1CA99F2D13DE9A
+
+I=57
+KEY=C2A4C82B4AAEE0A22315026C6FE396900091CB9C1044A4886227C504255D229D
+CT=CF6B2444DFBBFE5B6A1CA99F2D13DE9A
+PT=14AD8C7B0F0460A3F48D5CD2CFFB385C
+
+I=58
+KEY=BF76E610192E2AEF42FF8F487CDDC318143C47E71F40C42B96AA99D6EAA61AC1
+CT=14AD8C7B0F0460A3F48D5CD2CFFB385C
+PT=A5A850FC44A09C5985CE9661AF84F186
+
+I=59
+KEY=1E42AEC368C600F18CBFA305EB559946B194171B5BE0587213640FB74522EB47
+CT=A5A850FC44A09C5985CE9661AF84F186
+PT=E2895D416951FDA66B695ABFA313F89D
+
+I=60
+KEY=4E9BC121E32849DAA501BEA4E534D9C2531D4A5A32B1A5D4780D5508E63113DA
+CT=E2895D416951FDA66B695ABFA313F89D
+PT=91E93AAECC5FB253F7463F101B2A4132
+
+I=61
+KEY=ACC045A67F680F14D3F8DA454C922071C2F470F4FEEE17878F4B6A18FD1B52E8
+CT=91E93AAECC5FB253F7463F101B2A4132
+PT=F0F339022B4001E72F3BCC1A140603AD
+
+I=62
+KEY=4B47D2639B4A04D3C87D35DB4E63E563320749F6D5AE1660A070A602E91D5145
+CT=F0F339022B4001E72F3BCC1A140603AD
+PT=DBECAFF90EDD4555A5D9A23817520D51
+
+I=63
+KEY=C73B1C617BE90F2710DFF2C3AC60E0F9E9EBE60FDB73533505A9043AFE4F5C14
+CT=DBECAFF90EDD4555A5D9A23817520D51
+PT=73315A63A8889095AFED497AEFE657B4
+
+I=64
+KEY=7F368758F7B303DE356481ED8EBFA46F9ADABC6C73FBC3A0AA444D4011A90BA0
+CT=73315A63A8889095AFED497AEFE657B4
+PT=3AB7E2F81D24D857308A1FC785559333
+
+I=65
+KEY=6D7EF76412498AB3C70AA3006CC87188A06D5E946EDF1BF79ACE528794FC9893
+CT=3AB7E2F81D24D857308A1FC785559333
+PT=7EAA2814E372F674AB0B6E0E428D1AF4
+
+I=66
+KEY=D626AD50A7B86153BF9215A6A8F7E908DEC776808DADED8331C53C89D6718267
+CT=7EAA2814E372F674AB0B6E0E428D1AF4
+PT=ADD212A59AC9EF6A55AEAC22D35A1BFE
+
+I=67
+KEY=4B9C7ED9AC7835C87DAB8BEF3ED6878B73156425176402E9646B90AB052B9999
+CT=ADD212A59AC9EF6A55AEAC22D35A1BFE
+PT=203ECD34AE1BB2F23BC673DBD74FA07B
+
+I=68
+KEY=E34FBDEF9D81B464DD1138093F132051532BA911B97FB01B5FADE370D26439E2
+CT=203ECD34AE1BB2F23BC673DBD74FA07B
+PT=0A18AFD5EEBBD338299897EA1F01324C
+
+I=69
+KEY=77BD51D39775121C22343FFC66D40F0B593306C457C463237635749ACD650BAE
+CT=0A18AFD5EEBBD338299897EA1F01324C
+PT=2892A6AE9517642A0977942360FB8104
+
+I=70
+KEY=2761BF5478726AF184C86B45AE331A7E71A1A06AC2D307097F42E0B9AD9E8AAA
+CT=2892A6AE9517642A0977942360FB8104
+PT=8A4CD7685B9A1E663C3130C34BC418B9
+
+I=71
+KEY=DD168B81E90D806FF468BE5E551F3344FBED77029949196F4373D07AE65A9213
+CT=8A4CD7685B9A1E663C3130C34BC418B9
+PT=C7C0A15A1A22363B378D5DD27A69D4C2
+
+I=72
+KEY=3442C07C0E98F523F9278D934F424BD83C2DD658836B2F5474FE8DA89C3346D1
+CT=C7C0A15A1A22363B378D5DD27A69D4C2
+PT=55A8EF8CAE213FE3FD6AA77E7415400A
+
+I=73
+KEY=291BD1577921B2947BC470C19727F0BD698539D42D4A10B789942AD6E82606DB
+CT=55A8EF8CAE213FE3FD6AA77E7415400A
+PT=0B07BEB71461356645936996AC45EB87
+
+I=74
+KEY=46475B4C21F0F4895FEFCC67632DBCDC62828763392B25D1CC0743404463ED5C
+CT=0B07BEB71461356645936996AC45EB87
+PT=6DFA5978F740C18CEE6F70FF50008BFD
+
+I=75
+KEY=CF89BDDE5D363B3C44DB6FED2DAB47AA0F78DE1BCE6BE45D226833BF146366A1
+CT=6DFA5978F740C18CEE6F70FF50008BFD
+PT=6F58747F0336A2C4D2A397511E06D703
+
+I=76
+KEY=85F7D4A4503F7C3D52998384F8B29BEF6020AA64CD5D4699F0CBA4EE0A65B1A2
+CT=6F58747F0336A2C4D2A397511E06D703
+PT=32AC7B1B8FFA7D411F46C129EEFFAF13
+
+I=77
+KEY=CDE87D2DFB6198CFC737D93433419757528CD17F42A73BD8EF8D65C7E49A1EB1
+CT=32AC7B1B8FFA7D411F46C129EEFFAF13
+PT=CF5D039714814E72ECE7B9D5D1B27D11
+
+I=78
+KEY=BCB9F75F11496AABFE2633E393B59B449DD1D2E8562675AA036ADC12352863A0
+CT=CF5D039714814E72ECE7B9D5D1B27D11
+PT=3455F997002A1818967E2679A07C1D56
+
+I=79
+KEY=99E143B3524E724A009533AEC659E15BA9842B7F560C6DB29514FA6B95547EF6
+CT=3455F997002A1818967E2679A07C1D56
+PT=1F2113D44E290F1379A3CEC6D57D6279
+
+I=80
+KEY=90086C83794D6878FF2CE748ECA6EDF4B6A538AB182562A1ECB734AD40291C8F
+CT=1F2113D44E290F1379A3CEC6D57D6279
+PT=88866DB676AA3B21954AFDE0A0F33007
+
+I=81
+KEY=FA254EB868F6CD5965346ACAE326BD2A3E23551D6E8F598079FDC94DE0DA2C88
+CT=88866DB676AA3B21954AFDE0A0F33007
+PT=A1665AD0252764E2691E65FEFB609CDA
+
+I=82
+KEY=92032C92FEEB0A5CD5D71AAF1BF5F47D9F450FCD4BA83D6210E3ACB31BBAB052
+CT=A1665AD0252764E2691E65FEFB609CDA
+PT=988CE348430A206546379A8C684C00F1
+
+I=83
+KEY=CF32144187F7B98256B5B4204DFABC8807C9EC8508A21D0756D4363F73F6B0A3
+CT=988CE348430A206546379A8C684C00F1
+PT=60289F0B6A9ADD08BF8924AA6D7F4D12
+
+I=84
+KEY=A7BD244360E3C325F3EA315C86959DD867E1738E6238C00FE95D12951E89FDB1
+CT=60289F0B6A9ADD08BF8924AA6D7F4D12
+PT=FA3EA122499D7E083D81F147D9D68B09
+
+I=85
+KEY=86213610EDC35A883A3364E8D529C6459DDFD2AC2BA5BE07D4DCE3D2C75F76B8
+CT=FA3EA122499D7E083D81F147D9D68B09
+PT=8E0B2452EF0515FC554A0AADF107714D
+
+I=86
+KEY=92CC3AE4A2A68CD93634075E902C66CB13D4F6FEC4A0ABFB8196E97F365807F5
+CT=8E0B2452EF0515FC554A0AADF107714D
+PT=463CEAE83A50BA54280E792AB6B29B94
+
+I=87
+KEY=6D86FA00DBB949A29D4A6166F1EF531E55E81C16FEF011AFA998905580EA9C61
+CT=463CEAE83A50BA54280E792AB6B29B94
+PT=416CA710B874E50CC98DF842B3435AD1
+
+I=88
+KEY=C9400C98A04F5041BE1C6090A866F7DA1484BB064684F4A36015681733A9C6B0
+CT=416CA710B874E50CC98DF842B3435AD1
+PT=3BA8BB5C572C0404E4B8199528825904
+
+I=89
+KEY=ED5043E9699B37844033E8BD170588342F2C005A11A8F0A784AD71821B2B9FB4
+CT=3BA8BB5C572C0404E4B8199528825904
+PT=1D2812DE70AA2D59894DA4DA7FE906FC
+
+I=90
+KEY=1964C6C301EEEF60B34E8E35175CAF8D320412846102DDFE0DE0D55864C29948
+CT=1D2812DE70AA2D59894DA4DA7FE906FC
+PT=2735CAAFE653442FFC2E878AE2829998
+
+I=91
+KEY=567B1E0737D0F72F82EB3A47D17209191531D82B875199D1F1CE52D2864000D0
+CT=2735CAAFE653442FFC2E878AE2829998
+PT=07B5FA4835E5DFC67E02F490A497145D
+
+I=92
+KEY=89AAD6DCA6A8973580D02768EBC8372412842263B2B446178FCCA64222D7148D
+CT=07B5FA4835E5DFC67E02F490A497145D
+PT=A31272EC8623213B015811FAE12330CE
+
+I=93
+KEY=4B4AB47A0DBA39907D8E919767E69518B196508F3497672C8E94B7B8C3F42443
+CT=A31272EC8623213B015811FAE12330CE
+PT=9132AB51C9738A62CABDE4977947E0BF
+
+I=94
+KEY=BEC71999AEE5517C243B65830D30DEBB20A4FBDEFDE4ED4E4429532FBAB3C4FC
+CT=9132AB51C9738A62CABDE4977947E0BF
+PT=689375EA83B61894631E6EFA2D509531
+
+I=95
+KEY=77CE2C97A458300D7C95C6871CEB56D648378E347E52F5DA27373DD597E351CD
+CT=689375EA83B61894631E6EFA2D509531
+PT=AAA5C6C5917DFC103383DE6C79EB2BA6
+
+I=96
+KEY=0AD691774612F7EFA41FE39B8B3A2D14E29248F1EF2F09CA14B4E3B9EE087A6B
+CT=AAA5C6C5917DFC103383DE6C79EB2BA6
+PT=29D9945BDB3770ED2A41D2760D0DC51D
+
+I=97
+KEY=4E1D42ADC4CEF6BAE3A5B9E08F7ACD65CB4BDCAA341879273EF531CFE305BF76
+CT=29D9945BDB3770ED2A41D2760D0DC51D
+PT=2F9B3C4E1FDCDC8F7D5DFBEA342284F2
+
+I=98
+KEY=2D76A3E35C075DB14E40A59F46E07A81E4D0E0E42BC4A5A843A8CA25D7273B84
+CT=2F9B3C4E1FDCDC8F7D5DFBEA342284F2
+PT=ED4CFCF1C8D226EBACCC8FF11B1C81B8
+
+I=99
+KEY=E7364D0D17D723A69C0BA956778BD0E9099C1C15E3168343EF6445D4CC3BBA3C
+CT=ED4CFCF1C8D226EBACCC8FF11B1C81B8
+PT=2F9B5E1392B767E8497F849D00E98193
+
+I=100
+KEY=709380C7012CB4272A69F6D4936B163E2607420671A1E4ABA61BC149CCD23BAF
+CT=2F9B5E1392B767E8497F849D00E98193
+PT=3BE783A4A38EFB44150AA7A08E1888F6
+
+I=101
+KEY=98FF27B8AB7B91F690231E24608076EF1DE0C1A2D22F1FEFB31166E942CAB359
+CT=3BE783A4A38EFB44150AA7A08E1888F6
+PT=F35AED9C83E53D2EADDE507345096218
+
+I=102
+KEY=24F9D2FF633EE9AAED7321CFCF4D1D20EEBA2C3E51CA22C11ECF369A07C3D141
+CT=F35AED9C83E53D2EADDE507345096218
+PT=A22BF93FD521A6E59C196022FF252DC2
+
+I=103
+KEY=70E491840BC5C42A878655E18E9AAAA74C91D50184EB842482D656B8F8E6FC83
+CT=A22BF93FD521A6E59C196022FF252DC2
+PT=11E67B52F8CD97D63268485EB546E1FE
+
+I=104
+KEY=098FF2D6DE55FF5C66D5AD7D5949643A5D77AE537C2613F2B0BE1EE64DA01D7D
+CT=11E67B52F8CD97D63268485EB546E1FE
+PT=1E67AF3F7E7FDEFB868696E96F718ACC
+
+I=105
+KEY=B89EA7CBAE57B8AD39F23B22A8F651A44310016C0259CD093638880F22D197B1
+CT=1E67AF3F7E7FDEFB868696E96F718ACC
+PT=332B0045710B2DD6EC3D619051580C7F
+
+I=106
+KEY=39F71BC56EBFA91088499DC41A0C5B5B703B01297352E0DFDA05E99F73899BCE
+CT=332B0045710B2DD6EC3D619051580C7F
+PT=86F3D75D18F7AB31C6C52C19B0C35023
+
+I=107
+KEY=417147DB03FDA0B26BEED7FE8A9487D5F6C8D6746BA54BEE1CC0C586C34ACBED
+CT=86F3D75D18F7AB31C6C52C19B0C35023
+PT=452E6C2DA8B93A1E282F1A86AECB9F15
+
+I=108
+KEY=C4336C26C20AD7811578044800A51E8EB3E6BA59C31C71F034EFDF006D8154F8
+CT=452E6C2DA8B93A1E282F1A86AECB9F15
+PT=637F010BAC28AC108331F4E26B262D3A
+
+I=109
+KEY=D0369C75D40EEF29CF7588FB87EE2ED2D099BB526F34DDE0B7DE2BE206A779C2
+CT=637F010BAC28AC108331F4E26B262D3A
+PT=3F3DCA8B4C2DDFD556880A17FB575E7B
+
+I=110
+KEY=4DE25218630A678C287EC42F93985D22EFA471D923190235E15621F5FDF027B9
+CT=3F3DCA8B4C2DDFD556880A17FB575E7B
+PT=3DA8C1D40B51A8BC6E728D7A1E6B3B2E
+
+I=111
+KEY=C0526C3096805B532433C0248E153A00D20CB00D2848AA898F24AC8FE39B1C97
+CT=3DA8C1D40B51A8BC6E728D7A1E6B3B2E
+PT=449B050578191E4C156F7040EF27D5EC
+
+I=112
+KEY=6A1B7384328BAA25B6A857FB12A90FD49697B5085051B4C59A4BDCCF0CBCC97B
+CT=449B050578191E4C156F7040EF27D5EC
+PT=D58ACA128F936803BDD5EC1E6DECAB04
+
+I=113
+KEY=44B7F3EB0EF0EF4325353D30F35C4D71431D7F1ADFC2DCC6279E30D16150627F
+CT=D58ACA128F936803BDD5EC1E6DECAB04
+PT=77F1011F968AD46338CA68D5DF37959E
+
+I=114
+KEY=E1E6BBD70AEAC4D65159422B3DFE82DF34EC7E05494808A51F545804BE67F7E1
+CT=77F1011F968AD46338CA68D5DF37959E
+PT=FC692161766A29C9E6A86C353E2F3FE5
+
+I=115
+KEY=5C33A88179175BB12593D6574245A6A6C8855F643F22216CF9FC34318048C804
+CT=FC692161766A29C9E6A86C353E2F3FE5
+PT=F5FD2F77BC4908F470142417048C6233
+
+I=116
+KEY=E6A3CDD47570AEC4FC3B3453F78F253F3D787013836B299889E8102684C4AA37
+CT=F5FD2F77BC4908F470142417048C6233
+PT=FBDC2774D7E426CBD8B62ABD0E0EAA6F
+
+I=117
+KEY=4F5B3EDC53366D4C74D94663E17CBDB6C6A45767548F0F53515E3A9B8ACA0058
+CT=FBDC2774D7E426CBD8B62ABD0E0EAA6F
+PT=796D978C9D724C1C9445EC5BD272CEB0
+
+I=118
+KEY=9119AD19E78100B3D04BED87FF5C22B5BFC9C0EBC9FD434FC51BD6C058B8CEE8
+CT=796D978C9D724C1C9445EC5BD272CEB0
+PT=15ECF7D3F516D3CBA0307959287A5BAB
+
+I=119
+KEY=600B4D7604FF2650611C453A50D02275AA2537383CEB9084652BAF9970C29543
+CT=15ECF7D3F516D3CBA0307959287A5BAB
+PT=DA67996084E9C74C143310FC3CF207DD
+
+I=120
+KEY=3B8E0B73BBF745BB360EA50E7DA9B3297042AE58B80257C87118BF654C30929E
+CT=DA67996084E9C74C143310FC3CF207DD
+PT=6E9BC50580D45D54FEEC74830C0D9516
+
+I=121
+KEY=231592D0CE761359AE2E85CC4E4156A01ED96B5D38D60A9C8FF4CBE6403D0788
+CT=6E9BC50580D45D54FEEC74830C0D9516
+PT=A4B0F6A50C72C5EE755FA5595334DF2E
+
+I=122
+KEY=7ABD82D278910B909B0D6219EF5E0D98BA699DF834A4CF72FAAB6EBF1309D8A6
+CT=A4B0F6A50C72C5EE755FA5595334DF2E
+PT=24CDAEEB54A1EB7E2D4A0BEE526EA6E0
+
+I=123
+KEY=5C8F7B23850BD287F011E257D691F8979EA433136005240CD7E1655141677E46
+CT=24CDAEEB54A1EB7E2D4A0BEE526EA6E0
+PT=84F24CDC0AA63CEA2DDE8F94C8776765
+
+I=124
+KEY=DF8EEE46309021F6E7D7D41908B6CABE1A567FCF6AA318E6FA3FEAC589101923
+CT=84F24CDC0AA63CEA2DDE8F94C8776765
+PT=EEA20542DEDB0B99A2144942FFEAC820
+
+I=125
+KEY=8634A663D618B3BB54F44A5849170ACDF4F47A8DB478137F582BA38776FAD103
+CT=EEA20542DEDB0B99A2144942FFEAC820
+PT=CDD91737753BE9F672A60DD722202127
+
+I=126
+KEY=E41913E97F21A4E6A948ABEB45279E0D392D6DBAC143FA892A8DAE5054DAF024
+CT=CDD91737753BE9F672A60DD722202127
+PT=E6E2F7846E06BB90F19B21521DD4D238
+
+I=127
+KEY=1E63624B5EADBE7D42255F208CC7D348DFCF9A3EAF454119DB168F02490E221C
+CT=E6E2F7846E06BB90F19B21521DD4D238
+PT=0110CA2647D43C8BD012976113EFB860
+
+I=128
+KEY=8476329019AA4D0D91C71E0DFFF47906DEDF5018E8917D920B0418635AE19A7C
+CT=0110CA2647D43C8BD012976113EFB860
+PT=CC9AACC98876387D09565F1A20D329AF
+
+I=129
+KEY=DB1C0803BC1AD91C5621FA8C54AA83EF1245FCD160E745EF025247797A32B3D3
+CT=CC9AACC98876387D09565F1A20D329AF
+PT=55AB296D67DEEBA179AD8093C1952CC2
+
+I=130
+KEY=5C0887FF7C888D7800C43BC9E88D9B3B47EED5BC0739AE4E7BFFC7EABBA79F11
+CT=55AB296D67DEEBA179AD8093C1952CC2
+PT=27016691505182706848CD5D7A2C5CAB
+
+I=131
+KEY=0FFBE12ADFA17F3BF26622C20311D38960EFB32D57682C3E13B70AB7C18BC3BA
+CT=27016691505182706848CD5D7A2C5CAB
+PT=5E6C9FAF480FFE51D7687ADE203D5367
+
+I=132
+KEY=C4C12330BC21062618E2E83EC3755DAC3E832C821F67D26FC4DF7069E1B690DD
+CT=5E6C9FAF480FFE51D7687ADE203D5367
+PT=082FF20DC6AFBA3888348E5724F5C526
+
+I=133
+KEY=3F6BF56A0136C1058924FCD831A65EBC36ACDE8FD9C868574CEBFE3EC54355FB
+CT=082FF20DC6AFBA3888348E5724F5C526
+PT=67AE68CDDA349A067339F28FA216A188
+
+I=134
+KEY=4AB9E8E9B5BB84353006AB43065C6B8F5102B64203FCF2513FD20CB16755F473
+CT=67AE68CDDA349A067339F28FA216A188
+PT=3316F37F97D679B78A537A0E107923AB
+
+I=135
+KEY=E04DE045508423D735B20168C7974CC26214453D942A8BE6B58176BF772CD7D8
+CT=3316F37F97D679B78A537A0E107923AB
+PT=00AEB331686999C5F5FB1E7C6CCF1072
+
+I=136
+KEY=D4D19E570760468E9703F0E49C4AC9F262BAF60CFC431223407A68C31BE3C7AA
+CT=00AEB331686999C5F5FB1E7C6CCF1072
+PT=29A5DB93D2AE9B1ED9714213EAD9AA1C
+
+I=137
+KEY=6D6789354D2CC3EFA9ABFC466F21A6E24B1F2D9F2EED893D990B2AD0F13A6DB6
+CT=29A5DB93D2AE9B1ED9714213EAD9AA1C
+PT=E98426CB0F858A084EB66311188D9200
+
+I=138
+KEY=06ED66801B81943BF1640AAE222A23C7A29B0B5421680335D7BD49C1E9B7FFB6
+CT=E98426CB0F858A084EB66311188D9200
+PT=21527326577425261F2D40268C428E29
+
+I=139
+KEY=2232758279A806C21870C85273C12FA883C97872761C2613C89009E765F5719F
+CT=21527326577425261F2D40268C428E29
+PT=CC9393A43B8A8194C0EC29F989E597A6
+
+I=140
+KEY=E7E22C2A6E6D4A1BFE7B706047094AF44F5AEBD64D96A787087C201EEC10E639
+CT=CC9393A43B8A8194C0EC29F989E597A6
+PT=714846062B262A823B24164900DF91AD
+
+I=141
+KEY=89A78F64BCAEE02CAC92928134C2567C3E12ADD066B08D0533583657ECCF7794
+CT=714846062B262A823B24164900DF91AD
+PT=1D0AC79D1E9BB36A6A6A8E49538C08FF
+
+I=142
+KEY=4F6E8D81296C95FAA0FE6F2D324A392223186A4D782B3E6F5932B81EBF437F6B
+CT=1D0AC79D1E9BB36A6A6A8E49538C08FF
+PT=403D8B10E0AB31493589AFFA8E8B1BEE
+
+I=143
+KEY=24E398291CF018E4666728F4F635F74D6325E15D98800F266CBB17E431C86485
+CT=403D8B10E0AB31493589AFFA8E8B1BEE
+PT=9E0516EDA401DAAF6AC013841C0D63C8
+
+I=144
+KEY=F80CF8AF1FA463D2ED7C7F59C1B239B0FD20F7B03C81D589067B04602DC5074D
+CT=9E0516EDA401DAAF6AC013841C0D63C8
+PT=74B2B200922B21AA20A0C5860CFB7E4D
+
+I=145
+KEY=577A5456424E1A76C3E113EB82CCDF34899245B0AEAAF42326DBC1E6213E7900
+CT=74B2B200922B21AA20A0C5860CFB7E4D
+PT=25AFF27E13888A638CDA2673D7F16AFD
+
+I=146
+KEY=7C623BBD4777E6EF9BC058DF5BA27BEAAC3DB7CEBD227E40AA01E795F6CF13FD
+CT=25AFF27E13888A638CDA2673D7F16AFD
+PT=A54F400AB9C52913D7302BA36BF217DD
+
+I=147
+KEY=A8B33E433720C4B925C4F0315DDB73B00972F7C404E757537D31CC369D3D0420
+CT=A54F400AB9C52913D7302BA36BF217DD
+PT=48A263A07112AA95EA1414CE03545790
+
+I=148
+KEY=DA864B91AED3E2FAC25782F4A50C13C841D0946475F5FDC69725D8F89E6953B0
+CT=48A263A07112AA95EA1414CE03545790
+PT=541547E924522E59C1721D130B64D92F
+
+I=149
+KEY=EEB5FF6F9C435510E12934F5E806553E15C5D38D51A7D39F5657C5EB950D8A9F
+CT=541547E924522E59C1721D130B64D92F
+PT=5830544939EB4607145538388840248B
+
+I=150
+KEY=24E609AD29E4C601189CB2FE119767884DF587C4684C95984202FDD31D4DAE14
+CT=5830544939EB4607145538388840248B
+PT=CBE1F82FD3318448AA36ADB5967EF865
+
+I=151
+KEY=5A7EBB76C38C2E5F038612A06E84BB2C86147FEBBB7D11D0E83450668B335671
+CT=CBE1F82FD3318448AA36ADB5967EF865
+PT=3B104547D2D620879E3CB2B5774C0FB4
+
+I=152
+KEY=827EFCB7BC862C2466B8C79FC297AD3DBD043AAC69AB31577608E2D3FC7F59C5
+CT=3B104547D2D620879E3CB2B5774C0FB4
+PT=B667F7544FE49A07611A160E3312F69A
+
+I=153
+KEY=9BC6C18805144F98CAEA7B252B3EE2930B63CDF8264FAB501712F4DDCF6DAF5F
+CT=B667F7544FE49A07611A160E3312F69A
+PT=C3E928FDEB5D7DDF7CF32C4DBCFE32F3
+
+I=154
+KEY=2BC00DF6D26F9A968C3BFF47AE761718C88AE505CD12D68F6BE1D89073939DAC
+CT=C3E928FDEB5D7DDF7CF32C4DBCFE32F3
+PT=72A9CF7AA2EDAF1907D77D10A02A45DE
+
+I=155
+KEY=15A0EE054E2D5E7EDCF3FC766860ACCDBA232A7F6FFF79966C36A580D3B9D872
+CT=72A9CF7AA2EDAF1907D77D10A02A45DE
+PT=97ABFAAD506940F88FDC8F55AD7EA919
+
+I=156
+KEY=C56C11F3A96852119C16751963C24CD42D88D0D23F96396EE3EA2AD57EC7716B
+CT=97ABFAAD506940F88FDC8F55AD7EA919
+PT=DD55A02B1EB01EB091CA6337D0BEB5BD
+
+I=157
+KEY=8634CC7B3416FCE337AAFA39791D1545F0DD70F9212627DE722049E2AE79C4D6
+CT=DD55A02B1EB01EB091CA6337D0BEB5BD
+PT=C5EB3DF5A328B267F3895CECD4A828AF
+
+I=158
+KEY=DDC1361E1432CCAC3551E2478A321A0035364D0C820E95B981A9150E7AD1EC79
+CT=C5EB3DF5A328B267F3895CECD4A828AF
+PT=49952DACD97FD5583A7D9C4FF515EC17
+
+I=159
+KEY=52658EEC2A7441D866CFA15944BB12857CA360A05B7140E1BBD489418FC4006E
+CT=49952DACD97FD5583A7D9C4FF515EC17
+PT=4971EEEF871E935AC470BD770802B04B
+
+I=160
+KEY=05FC7A181B1935EA8DCEC961B0DFC14B35D28E4FDC6FD3BB7FA4343687C6B025
+CT=4971EEEF871E935AC470BD770802B04B
+PT=3DB5E9165C24EC3790DC3E53E5E5D2DE
+
+I=161
+KEY=8D2793B7BDCF80338AA39C86008361BC08676759804B3F8CEF780A65622362FB
+CT=3DB5E9165C24EC3790DC3E53E5E5D2DE
+PT=1FDB5D4FBB59F082B3B617C8A23734F1
+
+I=162
+KEY=37BE37961B77866869826907BB9E9C1717BC3A163B12CF0E5CCE1DADC014560A
+CT=1FDB5D4FBB59F082B3B617C8A23734F1
+PT=8C59775AD3FF7C337B22C8E785321E25
+
+I=163
+KEY=F3184EA1C8FFE3D436BEE076AA999B659BE54D4CE8EDB33D27ECD54A4526482F
+CT=8C59775AD3FF7C337B22C8E785321E25
+PT=0CB834FCC0CFDAECAF4AFC5A2E38DF23
+
+I=164
+KEY=CACF50D99B066EB84CBFAEEC9B0D6769975D79B0282269D188A629106B1E970C
+CT=0CB834FCC0CFDAECAF4AFC5A2E38DF23
+PT=229EB7B6A97D91921BCD8C95A0D7C17B
+
+I=165
+KEY=3FA80E4FB785B9FC3B058CC62D289958B5C3CE06815FF843936BA585CBC95677
+CT=229EB7B6A97D91921BCD8C95A0D7C17B
+PT=0D7692C281DD4FF35D9B1620E1385C34
+
+I=166
+KEY=CE2A3A893C96A4F1AA81AD52EBCC3C23B8B55CC40082B7B0CEF0B3A52AF10A43
+CT=0D7692C281DD4FF35D9B1620E1385C34
+PT=D3C5FE594F5C8C5A359235448EB20146
+
+I=167
+KEY=FC8642DB8CB42D1B1251CB7FE6AFF90D6B70A29D4FDE3BEAFB6286E1A4430B05
+CT=D3C5FE594F5C8C5A359235448EB20146
+PT=8C0F88460C700D96847249807B84223F
+
+I=168
+KEY=2A9C9FD184A5B2418FD415A228A5C0AFE77F2ADB43AE367C7F10CF61DFC7293A
+CT=8C0F88460C700D96847249807B84223F
+PT=5A4237A5C2DABDCDA6389D5FC66032F6
+
+I=169
+KEY=FDB533163E989D2FA32CCA5D3CC5D376BD3D1D7E81748BB1D928523E19A71BCC
+CT=5A4237A5C2DABDCDA6389D5FC66032F6
+PT=BF8AAC6B1536CCCCECCC9D6BE970EB3E
+
+I=170
+KEY=3C4B3CF0FD0C4292B2497175D4400F8902B7B1159442477D35E4CF55F0D7F0F2
+CT=BF8AAC6B1536CCCCECCC9D6BE970EB3E
+PT=97CE58407FD26D63C86765CB05EA6277
+
+I=171
+KEY=367862F3E2C5520EA2269392B6139E9C9579E955EB902A1EFD83AA9EF53D9285
+CT=97CE58407FD26D63C86765CB05EA6277
+PT=B411687B044B624077A92D8C130697B9
+
+I=172
+KEY=0300AF491DAF6C607417FB1FD9B1EC612168812EEFDB485E8A2A8712E63B053C
+CT=B411687B044B624077A92D8C130697B9
+PT=D22E92A5132EA85F4FB25EE19C248008
+
+I=173
+KEY=7C92EF49A7D27E97F1884299B635F0ADF346138BFCF5E001C598D9F37A1F8534
+CT=D22E92A5132EA85F4FB25EE19C248008
+PT=FD6817CD680A2A8CE93E4B4F9CAA72AA
+
+I=174
+KEY=80EABB1D8C9B5F769FCAC87ED8D0C9CA0E2E044694FFCA8D2CA692BCE6B5F79E
+CT=FD6817CD680A2A8CE93E4B4F9CAA72AA
+PT=8DDD9B3B9278D2DE3453EA6769E1C39C
+
+I=175
+KEY=FB345E2D7BBBED527259FAEAEA79C05D83F39F7D0687185318F578DB8F543402
+CT=8DDD9B3B9278D2DE3453EA6769E1C39C
+PT=AE69F5CD8D342E74113E979ACE3539F2
+
+I=176
+KEY=7D93DC33FF2266770291160CD317C65E2D9A6AB08BB3362709CBEF4141610DF0
+CT=AE69F5CD8D342E74113E979ACE3539F2
+PT=30E19A4E84997172486DAE4FB4C41E58
+
+I=177
+KEY=82362FF3E9C1AD93474CF4CABD354E7E1D7BF0FE0F2A475541A6410EF5A513A8
+CT=30E19A4E84997172486DAE4FB4C41E58
+PT=75B3D07617EB189512DC5161908940C1
+
+I=178
+KEY=8EFD0FCB3855CCC16BD919FBD17596C768C8208818C15FC0537A106F652C5369
+CT=75B3D07617EB189512DC5161908940C1
+PT=FD13E89107FAFA44998721AD726C620F
+
+I=179
+KEY=2299D22282C798107F489637DCD479C395DBC8191F3BA584CAFD31C217403166
+CT=FD13E89107FAFA44998721AD726C620F
+PT=C1B0210C0387864717BD7D02063B6A69
+
+I=180
+KEY=75E05597A2BBDF23E5BD172C83548C9B546BE9151CBC23C3DD404CC0117B5B0F
+CT=C1B0210C0387864717BD7D02063B6A69
+PT=0E442B38E9024CCA5DC43A7B8D5F6FCF
+
+I=181
+KEY=4DBC8DCB8C25B5F4AD374BA3064216555A2FC22DF5BE6F09808476BB9C2434C0
+CT=0E442B38E9024CCA5DC43A7B8D5F6FCF
+PT=8FD213EC19D62FD2C19E6C91B97E56A0
+
+I=182
+KEY=E393BAD07E955EBC1446B847DE5A891ED5FDD1C1EC6840DB411A1A2A255A6260
+CT=8FD213EC19D62FD2C19E6C91B97E56A0
+PT=F52ADFD33A68EE198F33708E676D0CE9
+
+I=183
+KEY=3F33A76F87DB0388C2D66C7F2EFAA1B820D70E12D600AEC2CE296AA442376E89
+CT=F52ADFD33A68EE198F33708E676D0CE9
+PT=7649EB4283505EEEE1BE16DB6677B3F5
+
+I=184
+KEY=04BC65DE70C9E01EEEDA5A507C218C8D569EE5505550F02C2F977C7F2440DD7C
+CT=7649EB4283505EEEE1BE16DB6677B3F5
+PT=6FB1C4AD8A5B8A606621A8BF4277F3DC
+
+I=185
+KEY=8A6EF9710F4AE10EB60C8D25A8F67C50392F21FDDF0B7A4C49B6D4C066372EA0
+CT=6FB1C4AD8A5B8A606621A8BF4277F3DC
+PT=22C2CF9572D708F688291056E2F8E120
+
+I=186
+KEY=ED6D084D5F8AA4F201F9C20EA26A90E81BEDEE68ADDC72BAC19FC49684CFCF80
+CT=22C2CF9572D708F688291056E2F8E120
+PT=28AC7257911ECEB549D910BFA0905AE5
+
+I=187
+KEY=BA2735927D6A76B952C08A219FBB572233419C3F3CC2BC0F8846D429245F9565
+CT=28AC7257911ECEB549D910BFA0905AE5
+PT=2A1F3842DF988CDA0C6415450A657DB2
+
+I=188
+KEY=53BCC06CCCBC31A5BEE2CE88E6EAEFAC195EA47DE35A30D58422C16C2E3AE8D7
+CT=2A1F3842DF988CDA0C6415450A657DB2
+PT=6055EB3A24DE4D87C6BA5073A5BAC919
+
+I=189
+KEY=DF88C3CEC31C7B88D8AC0C7AAA2CED99790B4F47C7847D524298911F8B8021CE
+CT=6055EB3A24DE4D87C6BA5073A5BAC919
+PT=CC051CCD37068B41935FD14538DFEF82
+
+I=190
+KEY=265B351B93FF456D5A1EAADD2BEA1296B50E538AF082F613D1C7405AB35FCE4C
+CT=CC051CCD37068B41935FD14538DFEF82
+PT=225B63F455DD72EC87CF6FD5DF0FDAF3
+
+I=191
+KEY=BAC4C541E0A693CF8A3892A82F67CD959755307EA55F84FF56082F8F6C5014BF
+CT=225B63F455DD72EC87CF6FD5DF0FDAF3
+PT=64027F6B72F0A11628F66D5C502658E8
+
+I=192
+KEY=E8F68EF4909A128F331DFEFAE8560EBCF3574F15D7AF25E97EFE42D33C764C57
+CT=64027F6B72F0A11628F66D5C502658E8
+PT=529AAF9163EDA1BC39E66D2556BE938B
+
+I=193
+KEY=1951B1A50BED04096C17E816D4EC6225A1CDE084B442845547182FF66AC8DFDC
+CT=529AAF9163EDA1BC39E66D2556BE938B
+PT=F93E85D98EB9BDDD7D3844421235FBAB
+
+I=194
+KEY=D39AF070909FBC0E3226E28041B0286158F3655D3AFB39883A206BB478FD2477
+CT=F93E85D98EB9BDDD7D3844421235FBAB
+PT=16B6B3CC08003BA36C9E84B1EE9CD7CC
+
+I=195
+KEY=B705C6CCD010B980E386B8690C83E96C4E45D69132FB022B56BEEF059661F3BB
+CT=16B6B3CC08003BA36C9E84B1EE9CD7CC
+PT=301AFE66055149FA5775A9CE19F1FF63
+
+I=196
+KEY=B3C813D4FCBD31ED95E7E71CEC15153E7E5F28F737AA4BD101CB46CB8F900CD8
+CT=301AFE66055149FA5775A9CE19F1FF63
+PT=1090E68F7C8400861589E304A5B815CD
+
+I=197
+KEY=0EBC30ADB6946B6415C0309D636C79F46ECFCE784B2E4B571442A5CF2A281915
+CT=1090E68F7C8400861589E304A5B815CD
+PT=2778F0C712804C0B8D085B196A4D73C4
+
+I=198
+KEY=9C5815C6705B39DEECB8BDDDC9329A0D49B73EBF59AE075C994AFED640656AD1
+CT=2778F0C712804C0B8D085B196A4D73C4
+PT=14FECB137DC9C38A04D92B60A177A61D
+
+I=199
+KEY=9D83B41F8F415B5F3B2C08682383471B5D49F5AC2467C4D69D93D5B6E112CCCC
+CT=14FECB137DC9C38A04D92B60A177A61D
+PT=0EF1321EA52EAA7624E3F2EFD0C886AF
+
+I=200
+KEY=2960CEE0AF043ED1A549BA223F6C1CF153B8C7B281496EA0B970275931DA4A63
+CT=0EF1321EA52EAA7624E3F2EFD0C886AF
+PT=AFA8B2129577EC178B59D42D1B92D313
+
+I=201
+KEY=51E0DECF48A151021C70EC3EE3CE9008FC1075A0143E82B73229F3742A489970
+CT=AFA8B2129577EC178B59D42D1B92D313
+PT=3351631344E6EF86712327D3C05EBDEB
+
+I=202
+KEY=5F34A789B0B1185BA7D1BB3EF2677060CF4116B350D86D31430AD4A7EA16249B
+CT=3351631344E6EF86712327D3C05EBDEB
+PT=C299D0556B0D15014627CADBCCC3DC33
+
+I=203
+KEY=FC3E420F84F4C75802DCF68ABF0030E70DD8C6E63BD57830052D1E7C26D5F8A8
+CT=C299D0556B0D15014627CADBCCC3DC33
+PT=CEB83A2B9DD76B649BAAE48A8B772A5C
+
+I=204
+KEY=C04448AD77DBF33F22A2346C7A40F813C360FCCDA60213549E87FAF6ADA2D2F4
+CT=CEB83A2B9DD76B649BAAE48A8B772A5C
+PT=A8C6AEC94E82BC68AC8E29A8CB9504F6
+
+I=205
+KEY=3FA863ECC4AFA141DD7349C44F94FEE16BA65204E880AF3C3209D35E6637D602
+CT=A8C6AEC94E82BC68AC8E29A8CB9504F6
+PT=1EDED55C8D3309F828C17AF072C79D7A
+
+I=206
+KEY=8893E5FB27191AE09E4AB5F062289F117578875865B3A6C41AC8A9AE14F04B78
+CT=1EDED55C8D3309F828C17AF072C79D7A
+PT=FD2AC22891FB294EB0AD2BADFE759C29
+
+I=207
+KEY=90BA1205BB7927E86F9895855648D3EB88524570F4488F8AAA658203EA85D751
+CT=FD2AC22891FB294EB0AD2BADFE759C29
+PT=2FE6AE59ACD516EE1567A7A1C43FDE2A
+
+I=208
+KEY=278FD88834EA67564F301785C4045D6FA7B4EB29589D9964BF0225A22EBA097B
+CT=2FE6AE59ACD516EE1567A7A1C43FDE2A
+PT=35BEC13F159F61C7EF4C860AD3B41A75
+
+I=209
+KEY=E9D2F23C213D02724737A5E907BFBDF0920A2A164D02F8A3504EA3A8FD0E130E
+CT=35BEC13F159F61C7EF4C860AD3B41A75
+PT=650D65D6ED716DA515EAAF1A7447C3FB
+
+I=210
+KEY=4A0A997634E2D9305795FC90291F6FD9F7074FC0A073950645A40CB28949D0F5
+CT=650D65D6ED716DA515EAAF1A7447C3FB
+PT=7AFE0D2F234A6CDEDD7103DA09147285
+
+I=211
+KEY=BD671DD81F8FCD9D472564589AA13F5D8DF942EF8339F9D898D50F68805DA270
+CT=7AFE0D2F234A6CDEDD7103DA09147285
+PT=40627620B17313AF42EA7DD6CFD900F9
+
+I=212
+KEY=5668F777C46BF78DC664E72186626BF5CD9B34CF324AEA77DA3F72BE4F84A289
+CT=40627620B17313AF42EA7DD6CFD900F9
+PT=0C62985837C8C6FB468BD6E3928F8497
+
+I=213
+KEY=B82B5D4C3DEF62CFAE064CFDB5D904EFC1F9AC9705822C8C9CB4A45DDD0B261E
+CT=0C62985837C8C6FB468BD6E3928F8497
+PT=A1FFF4635AAF2AD8AE6EA8C70858EF3B
+
+I=214
+KEY=6A179EF63528EFA2B12DBA23D1EC8D21600658F45F2D065432DA0C9AD553C925
+CT=A1FFF4635AAF2AD8AE6EA8C70858EF3B
+PT=403F8E2D050E2976487BBEDD6466357E
+
+I=215
+KEY=6857720AC4DDCFFE8A96B455C973901A2039D6D95A232F227AA1B247B135FC5B
+CT=403F8E2D050E2976487BBEDD6466357E
+PT=2DD7EB8476988C850E8D95DC598FC61A
+
+I=216
+KEY=5B938E230BFE9056471E7C83A6ED03930DEE3D5D2CBBA3A7742C279BE8BA3A41
+CT=2DD7EB8476988C850E8D95DC598FC61A
+PT=676B96F400AE18138B302FD3D70D490E
+
+I=217
+KEY=4CE7ECA340DEC23715C53343EB9162DA6A85ABA92C15BBB4FF1C08483FB7734F
+CT=676B96F400AE18138B302FD3D70D490E
+PT=620AAA14B94BF6B60A83129085BCF02B
+
+I=218
+KEY=1024ECE618D140CAE8B9DFC8EB1DE137088F01BD955E4D02F59F1AD8BA0B8364
+CT=620AAA14B94BF6B60A83129085BCF02B
+PT=B701A38325DC282045C6F914394B9F70
+
+I=219
+KEY=6B8C6DA855E1E72E4A6AC44601B24D60BF8EA23EB0826522B059E3CC83401C14
+CT=B701A38325DC282045C6F914394B9F70
+PT=808D0B334B775C59F8C34A3524CB4126
+
+I=220
+KEY=C50A625A89465321DACCB9EB40DEF57D3F03A90DFBF5397B489AA9F9A78B5D32
+CT=808D0B334B775C59F8C34A3524CB4126
+PT=4E29C921CC295F6A3082C1BC02ACDA70
+
+I=221
+KEY=973341A4E3DB315FA97C7EEDF493EA71712A602C37DC661178186845A5278742
+CT=4E29C921CC295F6A3082C1BC02ACDA70
+PT=77BC204E50EFCA2AEBDC16D3F3C3D739
+
+I=222
+KEY=639EB8FB16B34B55550705FDCFF7C8CC069640626733AC3B93C47E9656E4507B
+CT=77BC204E50EFCA2AEBDC16D3F3C3D739
+PT=A677A7B55AA03EB0587EE00123D047F3
+
+I=223
+KEY=610A9602B725E4D87AB2904E91050D90A0E1E7D73D93928BCBBA9E9775341788
+CT=A677A7B55AA03EB0587EE00123D047F3
+PT=09AF5421548AC11466370484F8C556DE
+
+I=224
+KEY=314A6E0BD202458489059738917B6678A94EB3F66919539FAD8D9A138DF14156
+CT=09AF5421548AC11466370484F8C556DE
+PT=B6CDD2336AB8735EE7A9946A1FE7EE0C
+
+I=225
+KEY=73658C0F88490F7C3B9F2B7B39551BBF1F8361C503A120C14A240E799216AF5A
+CT=B6CDD2336AB8735EE7A9946A1FE7EE0C
+PT=B5A2F3B47E4AC87BC06612587253930E
+
+I=226
+KEY=968794DEC3E866DE4F999C860E9851E9AA2192717DEBE8BA8A421C21E0453C54
+CT=B5A2F3B47E4AC87BC06612587253930E
+PT=09C9C38BB3348147EB284FFA24D87244
+
+I=227
+KEY=205605E66A4BE2CF61E13243E104FED9A3E851FACEDF69FD616A53DBC49D4E10
+CT=09C9C38BB3348147EB284FFA24D87244
+PT=9D1EDCA2674E5A30416DF7CC2938DC63
+
+I=228
+KEY=9CA7508C83DB6E56EFF3489F2BD30C573EF68D58A99133CD2007A417EDA59273
+CT=9D1EDCA2674E5A30416DF7CC2938DC63
+PT=E8A2282B47DAB6A666A4607BBC857FC6
+
+I=229
+KEY=0F98884E85FEB533CFC281C2F4437915D654A573EE4B856B46A3C46C5120EDB5
+CT=E8A2282B47DAB6A666A4607BBC857FC6
+PT=B6675D2263DC1C1E0F04A9A9BC666D2D
+
+I=230
+KEY=3F3ED6DC6E08DF2515D08273832429286033F8518D97997549A76DC5ED468098
+CT=B6675D2263DC1C1E0F04A9A9BC666D2D
+PT=D6FF2642FD84C80674EAF8674242248D
+
+I=231
+KEY=67910C06B57CD52767674B70F59337D8B6CCDE13701351733D4D95A2AF04A415
+CT=D6FF2642FD84C80674EAF8674242248D
+PT=47D4419A669253C39A0CC96C7CD612C0
+
+I=232
+KEY=43EE254E414DB89044EE2F703B340F6AF1189F89168102B0A7415CCED3D2B6D5
+CT=47D4419A669253C39A0CC96C7CD612C0
+PT=B2B3FD7A1D4B0695B3499430F2E44CEA
+
+I=233
+KEY=89C9881E6D6CEFF00DDFC5618655FA4543AB62F30BCA04251408C8FE2136FA3F
+CT=B2B3FD7A1D4B0695B3499430F2E44CEA
+PT=4AAD0AE20AFF0675CF78992DFD2B685C
+
+I=234
+KEY=2C24846D047677F89EF73B917962D0FA0906681101350250DB7051D3DC1D9263
+CT=4AAD0AE20AFF0675CF78992DFD2B685C
+PT=C90343412CFE70201CE22D9AD2222788
+
+I=235
+KEY=770637F8F8F32915BF7630919D0726AEC0052B502DCB7270C7927C490E3FB5EB
+CT=C90343412CFE70201CE22D9AD2222788
+PT=923FE89134FAF362802C5A2EBF399D2C
+
+I=236
+KEY=426891CF6B068FAC7FFB5A04874AEC78523AC3C11931811247BE2667B10628C7
+CT=923FE89134FAF362802C5A2EBF399D2C
+PT=9C08F05026196BA3550A2496049B720B
+
+I=237
+KEY=B66BCCA5EFAF3F448BDD52DC48F2B904CE3233913F28EAB112B402F1B59D5ACC
+CT=9C08F05026196BA3550A2496049B720B
+PT=7B487FD67D0C2D987C3DEFD335C2EF17
+
+I=238
+KEY=079CCBC13FCFB0D032293FDFEC563F86B57A4C474224C7296E89ED22805FB5DB
+CT=7B487FD67D0C2D987C3DEFD335C2EF17
+PT=CEC12158856704CE8ABF0CA6C6F3006B
+
+I=239
+KEY=998AFEF458902CA632D60843A88D36637BBB6D1FC743C3E7E436E18446ACB5B0
+CT=CEC12158856704CE8ABF0CA6C6F3006B
+PT=DA19C7C7283ADD9C5145ABBA53F1E7E1
+
+I=240
+KEY=95EDAF196289EE6D24AA752DF489DEFCA1A2AAD8EF791E7BB5734A3E155D5251
+CT=DA19C7C7283ADD9C5145ABBA53F1E7E1
+PT=F043A57E686C1FE7DACB858F0C3E6857
+
+I=241
+KEY=3050D2C04C0860414427BF5B19792D7651E10FA68715019C6FB8CFB119633A06
+CT=F043A57E686C1FE7DACB858F0C3E6857
+PT=2FB7B264BB4B3FAFA01A6BB93CC2958D
+
+I=242
+KEY=26186DD7BE83659550BA3B52D99975037E56BDC23C5E3E33CFA2A40825A1AF8B
+CT=2FB7B264BB4B3FAFA01A6BB93CC2958D
+PT=D46BBD3ABD958DA722F3591578C30F5E
+
+I=243
+KEY=DE1D625B9C840580FDDE57EDE82419D1AA3D00F881CBB394ED51FD1D5D62A0D5
+CT=D46BBD3ABD958DA722F3591578C30F5E
+PT=3D69379AB60535902C38AB5E121DD035
+
+I=244
+KEY=FF9396CB65FFB9D47EF4E0253FD98BBA9754376237CE8604C16956434F7F70E0
+CT=3D69379AB60535902C38AB5E121DD035
+PT=A5767F4E6C8482290BC7B76D23EEF145
+
+I=245
+KEY=B98B5F1CA9752B1B07514B72C3D585F23222482C5B4A042DCAAEE12E6C9181A5
+CT=A5767F4E6C8482290BC7B76D23EEF145
+PT=9388736A82C99337C49BB4F32437B1DA
+
+I=246
+KEY=5F130919FB4ED29397E4781550B1D444A1AA3B46D983971A0E3555DD48A6307F
+CT=9388736A82C99337C49BB4F32437B1DA
+PT=915C6C5181E797DADC289F8FFF60CD19
+
+I=247
+KEY=D3F202F140D38545C8A04EC2D0993E2B30F65717586400C0D21DCA52B7C6FD66
+CT=915C6C5181E797DADC289F8FFF60CD19
+PT=A61167CDBE95ABFAD9C1A58BDA90F0D4
+
+I=248
+KEY=FBFA83B249C3B13C83E8FC111611391296E730DAE6F1AB3A0BDC6FD96D560DB2
+CT=A61167CDBE95ABFAD9C1A58BDA90F0D4
+PT=9AF2B4CF00B037976D0F5CAC4201885D
+
+I=249
+KEY=CC24CC54D0889912C7AD2473EBA8BBB30C158415E6419CAD66D333752F5785EF
+CT=9AF2B4CF00B037976D0F5CAC4201885D
+PT=A9B74046119B6699FD5EFD1E476BEE64
+
+I=250
+KEY=F520F18D9FACA98E5F57226127FA9B6BA5A2C453F7DAFA349B8DCE6B683C6B8B
+CT=A9B74046119B6699FD5EFD1E476BEE64
+PT=CD7EAA1EF3B91B69FD3E54FCC5A802E9
+
+I=251
+KEY=9BFD59A9F78FB1BE6F13B701D7EB0F6268DC6E4D0463E15D66B39A97AD946962
+CT=CD7EAA1EF3B91B69FD3E54FCC5A802E9
+PT=FD7095C419E2722425E6D4CA1A393D8C
+
+I=252
+KEY=C1C39AC5158C8CDBE82CF37D00B7896995ACFB891D81937943554E5DB7AD54EE
+CT=FD7095C419E2722425E6D4CA1A393D8C
+PT=9963CE47EB0322135C5D20B923FC341A
+
+I=253
+KEY=C9E26AE18D08643029C92F11BD3E8AA40CCF35CEF682B16A1F086EE4945160F4
+CT=9963CE47EB0322135C5D20B923FC341A
+PT=11589A1BDD037FABABBB9BF5AAC859A7
+
+I=254
+KEY=2183FF3C1EB1DF48DB8FA5F87F279F891D97AFD52B81CEC1B4B3F5113E993953
+CT=11589A1BDD037FABABBB9BF5AAC859A7
+PT=B6CEE1CD709BE6E055041FC2E1A87539
+
+I=255
+KEY=738690954B4B92CE2367567B3A960E8DAB594E185B1A2821E1B7EAD3DF314C6A
+CT=B6CEE1CD709BE6E055041FC2E1A87539
+PT=D776658F01CCEC460FA7145C6C6CBD42
+
+I=256
+KEY=71AB2DBD9923F08E516D8DF0CF57CC227C2F2B975AD6C467EE10FE8FB35DF128
+CT=D776658F01CCEC460FA7145C6C6CBD42
+PT=0C6D2578060A0A1024230D838AA45234
+
+I=257
+KEY=1C0E18C83D74E46DDF65BFC3335CFF0D70420EEF5CDCCE77CA33F30C39F9A31C
+CT=0C6D2578060A0A1024230D838AA45234
+PT=BFD55D67EF4883200FDAEEA5D44F0302
+
+I=258
+KEY=7DA814BD80D8CBBEE778E030682E7F34CF975388B3944D57C5E91DA9EDB6A01E
+CT=BFD55D67EF4883200FDAEEA5D44F0302
+PT=E821629542650FAFEF08D94AC889078A
+
+I=259
+KEY=10490CD6F16D915CE9891C69E10884D827B6311DF1F142F82AE1C4E3253FA794
+CT=E821629542650FAFEF08D94AC889078A
+PT=F2F81CD9CBD3E932686B6195A97EE13A
+
+I=260
+KEY=F0114F7C7101931F6A4595A6C3D2F34AD54E2DC43A22ABCA428AA5768C4146AE
+CT=F2F81CD9CBD3E932686B6195A97EE13A
+PT=C90348C14450EE3D9BFA30377D4B2440
+
+I=261
+KEY=C5802B19BA4921D3750A590F02658F621C4D65057E7245F7D9709541F10A62EE
+CT=C90348C14450EE3D9BFA30377D4B2440
+PT=619E907C4E7FD3A723E34B8D3880D71B
+
+I=262
+KEY=236500CE70AC49E98907DC4EDAE41CCA7DD3F579300D9650FA93DECCC98AB5F5
+CT=619E907C4E7FD3A723E34B8D3880D71B
+PT=932A17E8FDA853F6DB1C9271EC4FBF56
+
+I=263
+KEY=7BB7D14473E7E2D70F3C8C90D4B1035CEEF9E291CDA5C5A6218F4CBD25C50AA3
+CT=932A17E8FDA853F6DB1C9271EC4FBF56
+PT=549CB80C490E592E18ACC04FAA933489
+
+I=264
+KEY=415AD8391B32F6E61A861B4C8A4BBC6DBA655A9D84AB9C8839238CF28F563E2A
+CT=549CB80C490E592E18ACC04FAA933489
+PT=BF6337BEDE116D5A60B06DA8B270159C
+
+I=265
+KEY=058F24C125EB3E94B54BB6F1F099501C05066D235ABAF1D25993E15A3D262BB6
+CT=BF6337BEDE116D5A60B06DA8B270159C
+PT=CBD3D52496E6DF0DBD065BD924C5001F
+
+I=266
+KEY=B85B96EC639098C392FD33D11A49251ECED5B807CC5C2EDFE495BA8319E32BA9
+CT=CBD3D52496E6DF0DBD065BD924C5001F
+PT=AF8879C67DF265E118096478FBA003AD
+
+I=267
+KEY=526BF9DCAF4A4DFD05FAD0EA3B58131D615DC1C1B1AE4B3EFC9CDEFBE2432804
+CT=AF8879C67DF265E118096478FBA003AD
+PT=C627176029E2D22A51F5630B129A1095
+
+I=268
+KEY=553316781F120EE83A2D083D97D19F99A77AD6A1984C9914AD69BDF0F0D93891
+CT=C627176029E2D22A51F5630B129A1095
+PT=F46AC5870C65636D6C200312F2A15BE6
+
+I=269
+KEY=E9A37578C1402447D6CC1161F126D5C7531013269429FA79C149BEE202786377
+CT=F46AC5870C65636D6C200312F2A15BE6
+PT=4FBBFF3856FC0DEC7EE18585FFA4AC16
+
+I=270
+KEY=78521B42D0FBE8EA8BB6D44D66AE476D1CABEC1EC2D5F795BFA83B67FDDCCF61
+CT=4FBBFF3856FC0DEC7EE18585FFA4AC16
+PT=8711DAE7DD9B3F6D9FAD03669C1C8F5E
+
+I=271
+KEY=851C9A078620280FBCDDFB4FD3745C749BBA36F91F4EC8F82005380161C0403F
+CT=8711DAE7DD9B3F6D9FAD03669C1C8F5E
+PT=050E884136E09368DEFBC43F6B3182CC
+
+I=272
+KEY=50CCAA51D781B7090285D907E68B1F7A9EB4BEB829AE5B90FEFEFC3E0AF1C2F3
+CT=050E884136E09368DEFBC43F6B3182CC
+PT=CEC37197CEE3E0D797F441CC0541B851
+
+I=273
+KEY=DAB5ECB43982EAE8412102E2B7BC7CEA5077CF2FE74DBB47690ABDF20FB07AA2
+CT=CEC37197CEE3E0D797F441CC0541B851
+PT=197ECC091E5620DCA63BA2E6CFBC9F43
+
+I=274
+KEY=57974D1C4BBF761C9E09B8DAD3E510DF49090326F91B9B9BCF311F14C00CE5E1
+CT=197ECC091E5620DCA63BA2E6CFBC9F43
+PT=F2E836DEE9668E81D74A3C0F03CF3C10
+
+I=275
+KEY=E37677110C5A9A59EC06E0968BF5D14EBBE135F8107D151A187B231BC3C3D9F1
+CT=F2E836DEE9668E81D74A3C0F03CF3C10
+PT=DD581BB9F4A7BEC66CAC7916871F55C8
+
+I=276
+KEY=2CD760C245E62EA5B477BDA094B3AD5166B92E41E4DAABDC74D75A0D44DC8C39
+CT=DD581BB9F4A7BEC66CAC7916871F55C8
+PT=7B05D43A3BE733E0DE6E2CE494141B46
+
+I=277
+KEY=DE35BF6BC48E8B8E6A30DB886C9D75DD1DBCFA7BDF3D983CAAB976E9D0C8977F
+CT=7B05D43A3BE733E0DE6E2CE494141B46
+PT=1D561DCAA42E92568DD6ACD583FF7BCE
+
+I=278
+KEY=8AD7FCADA5D092DD5D221532EED3FD1000EAE7B17B130A6A276FDA3C5337ECB1
+CT=1D561DCAA42E92568DD6ACD583FF7BCE
+PT=1E9AB09A76FD91CC33B85390BDE631F8
+
+I=279
+KEY=534EEF6B1450693335980E00CD3CDE361E70572B0DEE9BA614D789ACEED1DD49
+CT=1E9AB09A76FD91CC33B85390BDE631F8
+PT=CBD0E3A07952EAC118A81B76D09276FD
+
+I=280
+KEY=8A39C2221622785E4DA9B14DAAE6ADF3D5A0B48B74BC71670C7F92DA3E43ABB4
+CT=CBD0E3A07952EAC118A81B76D09276FD
+PT=AC20057B857E6C34F7E68A5765573538
+
+I=281
+KEY=50887AD2D325CBC04B5FD69518318BAD7980B1F0F1C21D53FB99188D5B149E8C
+CT=AC20057B857E6C34F7E68A5765573538
+PT=DDFFD26BA5B33AEA36A0A6D75EAA047C
+
+I=282
+KEY=9613965C1776C5BAEA3CEE6154AABC9FA47F639B547127B9CD39BE5A05BE9AF0
+CT=DDFFD26BA5B33AEA36A0A6D75EAA047C
+PT=F0883B6DD3CA0515CB9F1ABA646CCB69
+
+I=283
+KEY=E7F6DB8A94597956CEE07447F9BB5CA454F758F687BB22AC06A6A4E061D25199
+CT=F0883B6DD3CA0515CB9F1ABA646CCB69
+PT=F4E27CA9E27B3E81B981298738C01FDA
+
+I=284
+KEY=0CB665943D6E6E32886A94C070366FB2A015245F65C01C2DBF278D6759124E43
+CT=F4E27CA9E27B3E81B981298738C01FDA
+PT=B03B2EB7A1E13E1A17C51FF5684E2A72
+
+I=285
+KEY=1EA698290E4B1D41B0CC4F3B9A9398FF102E0AE8C4212237A8E29292315C6431
+CT=B03B2EB7A1E13E1A17C51FF5684E2A72
+PT=BE133CCCE406C1C0BC1707115B5B0C84
+
+I=286
+KEY=BA38F49FA3D4A74ED41F8DA958A953C7AE3D36242027E3F714F595836A0768B5
+CT=BE133CCCE406C1C0BC1707115B5B0C84
+PT=A15B1C9BCF319AEF262E366C142A0DCF
+
+I=287
+KEY=935F2CEECBBCF3465DB9B0DB927AF4310F662ABFEF16791832DBA3EF7E2D657A
+CT=A15B1C9BCF319AEF262E366C142A0DCF
+PT=7A8DA23874D28EB75261D87D57451EAE
+
+I=288
+KEY=B8E67B884E3E229EBB516065499F790275EB88879BC4F7AF60BA7B9229687BD4
+CT=7A8DA23874D28EB75261D87D57451EAE
+PT=9331C989A7E291FD94BA4C945A79126E
+
+I=289
+KEY=CFB51BE6CDA499D66E7B36CAAC220FB7E6DA410E3C266652F4003706731169BA
+CT=9331C989A7E291FD94BA4C945A79126E
+PT=70A2F921A8BB0548D91A114478308448
+
+I=290
+KEY=19821B21FED0C1659AF4E16F49F63B699678B82F949D631A2D1A26420B21EDF2
+CT=70A2F921A8BB0548D91A114478308448
+PT=8ED8FC98045BA0EF9C15E9565EECE5BB
+
+I=291
+KEY=27DA5E31E794D670BDB701F361B8977018A044B790C6C3F5B10FCF1455CD0849
+CT=8ED8FC98045BA0EF9C15E9565EECE5BB
+PT=F6621989AFC0427E3E84039B6C6C2E75
+
+I=292
+KEY=64E8F7C4292DF7D0B01BED3FAE08DA4FEEC25D3E3F06818B8F8BCC8F39A1263C
+CT=F6621989AFC0427E3E84039B6C6C2E75
+PT=68F4804D1E8D383FAF4E76F80FB8F92B
+
+I=293
+KEY=EE626AFFE4997C11CAE2714FF96D84B18636DD73218BB9B420C5BA773619DF17
+CT=68F4804D1E8D383FAF4E76F80FB8F92B
+PT=2D61F123E2479D56AE5C327A57F6A28B
+
+I=294
+KEY=EA24B2DB953084C818B0E6F34BA1584DAB572C50C3CC24E28E99880D61EF7D9C
+CT=2D61F123E2479D56AE5C327A57F6A28B
+PT=C6CD16E7A122D105EE398E6C7F15B4EF
+
+I=295
+KEY=F209D1ADE0869F674F6FEDCD3DB7D2EB6D9A3AB762EEF5E760A006611EFAC973
+CT=C6CD16E7A122D105EE398E6C7F15B4EF
+PT=EDD6BBA5787DA2BF6A1ADF297DB98281
+
+I=296
+KEY=302BEB9AA2ACB3594D7E50859C187294804C81121A9357580ABAD94863434BF2
+CT=EDD6BBA5787DA2BF6A1ADF297DB98281
+PT=4A51E54F4F81469A06F6001F2F32F4AC
+
+I=297
+KEY=3270FC87B4DC04FDD3F20C01407BE123CA1D645D551211C20C4CD9574C71BF5E
+CT=4A51E54F4F81469A06F6001F2F32F4AC
+PT=F7A2303EA59907BCC32AA4FC5A6DE448
+
+I=298
+KEY=C85326465BF46A442BC1E544F9041C4A3DBF5463F08B167ECF667DAB161C5B16
+CT=F7A2303EA59907BCC32AA4FC5A6DE448
+PT=2274E43F9F8A7081DF74D5225EC28AD8
+
+I=299
+KEY=A54E889A4D9FFBF993C53A9DD3B951391FCBB05C6F0166FF1012A88948DED1CE
+CT=2274E43F9F8A7081DF74D5225EC28AD8
+PT=0C8358EC431313223B59126BDBB36571
+
+I=300
+KEY=FA14699C20CFFE7DB68786E6117F95851348E8B02C1275DD2B4BBAE2936DB4BF
+CT=0C8358EC431313223B59126BDBB36571
+PT=03237A81EEA2EAFBB5AC0B3E635CC1AC
+
+I=301
+KEY=B3744022A5397A735A4271261A2C96DF106B9231C2B09F269EE7B1DCF0317513
+CT=03237A81EEA2EAFBB5AC0B3E635CC1AC
+PT=409EBF7DF31FD9557118B1B5CAB5EBE3
+
+I=302
+KEY=8C7A22A934DCBC5E084E472DBAE4848350F52D4C31AF4673EFFF00693A849EF0
+CT=409EBF7DF31FD9557118B1B5CAB5EBE3
+PT=6CF5C9CF4A62C668B6481F7A12EE43DB
+
+I=303
+KEY=DB0497ED308C95BC9703265174B654D23C00E4837BCD801B59B71F13286ADD2B
+CT=6CF5C9CF4A62C668B6481F7A12EE43DB
+PT=D8A84E93CFF3EB9DC891333BDA5F3560
+
+I=304
+KEY=7A88D30D4CC9AB8EFA76139B68F0028AE4A8AA10B43E6B8691262C28F235E84B
+CT=D8A84E93CFF3EB9DC891333BDA5F3560
+PT=009E0C2454E321326336CC56D0660F91
+
+I=305
+KEY=55A78B8839B395B552630641648DFCE5E436A634E0DD4AB4F210E07E2253E7DA
+CT=009E0C2454E321326336CC56D0660F91
+PT=EBC89334F29560D9B9AEAE2F1D9DC65B
+
+I=306
+KEY=B41A907C82EDE32C6C1FD0DFED0A232D0FFE350012482A6D4BBE4E513FCE2181
+CT=EBC89334F29560D9B9AEAE2F1D9DC65B
+PT=4DA63E94EBB4DA255800C9B25068E47E
+
+I=307
+KEY=3E428E8A77067008EFDE7BD6174B05B742580B94F9FCF04813BE87E36FA6C5FF
+CT=4DA63E94EBB4DA255800C9B25068E47E
+PT=6833E2CEFA8CF4B5B4607FA49D7B658D
+
+I=308
+KEY=39D17AE8C7232386F8339427E4A79AAC2A6BE95A037004FDA7DEF847F2DDA072
+CT=6833E2CEFA8CF4B5B4607FA49D7B658D
+PT=41D882B653BEFEEEB9AE354F5ABCC058
+
+I=309
+KEY=E8D52C97FA4149312A45D3EFE0A326086BB36BEC50CEFA131E70CD08A861602A
+CT=41D882B653BEFEEEB9AE354F5ABCC058
+PT=D54A329BCF56B703BE0F02EE3AACB933
+
+I=310
+KEY=D36FAED6CF436A491111890449BC3C66BEF959779F984D10A07FCFE692CDD919
+CT=D54A329BCF56B703BE0F02EE3AACB933
+PT=5FAAEB95E0F9D0C3C43BF725DADC9595
+
+I=311
+KEY=9D7BCBB15816A0A941BBB787D2EEA155E153B2E27F619DD3644438C348114C8C
+CT=5FAAEB95E0F9D0C3C43BF725DADC9595
+PT=BC699D5E82FD43B45A7B925E8C1A2F3C
+
+I=312
+KEY=F2EB78917ECAC2E77C19B892E846AE715D3A2FBCFD9CDE673E3FAA9DC40B63B0
+CT=BC699D5E82FD43B45A7B925E8C1A2F3C
+PT=773D115B40F0E9EF780B2D10846FA684
+
+I=313
+KEY=B10B9F0CECA554749EC178F3C63547DD2A073EE7BD6C37884634878D4064C534
+CT=773D115B40F0E9EF780B2D10846FA684
+PT=50095809CC96520EB8E3A66F499EE147
+
+I=314
+KEY=E86E52AEB04DE0D3DC85A91E9B10D2677A0E66EE71FA6586FED721E209FA2473
+CT=50095809CC96520EB8E3A66F499EE147
+PT=6994CF8BA4C731CA33DAFE33D2A0BF94
+
+I=315
+KEY=44C3C8A2F0F931926AC73F3E5351B114139AA965D53D544CCD0DDFD1DB5A9BE7
+CT=6994CF8BA4C731CA33DAFE33D2A0BF94
+PT=981902A8FD71DF8B67D52E6FC2813B90
+
+I=316
+KEY=2D309D3D2603EC7E7B4EA626E9BDECFE8B83ABCD284C8BC7AAD8F1BE19DBA077
+CT=981902A8FD71DF8B67D52E6FC2813B90
+PT=35FA9A93AE142F562E62771991752B78
+
+I=317
+KEY=E80939BCB4DB83768EBAD3CF2DD3F270BE79315E8658A49184BA86A788AE8B0F
+CT=35FA9A93AE142F562E62771991752B78
+PT=A3651DBF8585004F0729AF4CA615C674
+
+I=318
+KEY=BF1A4C57D4434FA59A2E45DB589AA16F1D1C2CE103DDA4DE839329EB2EBB4D7B
+CT=A3651DBF8585004F0729AF4CA615C674
+PT=AF31F082CACEB768627B93A4D3E5349A
+
+I=319
+KEY=6EB47730BACAAB2207A3D12B0652B0CDB22DDC63C91313B6E1E8BA4FFD5E79E1
+CT=AF31F082CACEB768627B93A4D3E5349A
+PT=57B75D2B640F45DB2D4A1F71F08545A5
+
+I=320
+KEY=3EB0F3D31E648E260FE9F6FA8812ADD1E59A8148AD1C566DCCA2A53E0DDB3C44
+CT=57B75D2B640F45DB2D4A1F71F08545A5
+PT=A812DA38D7B82DF310366FA62FFD11E6
+
+I=321
+KEY=0409A87F024E710C27E456CA170B60184D885B707AA47B9EDC94CA9822262DA2
+CT=A812DA38D7B82DF310366FA62FFD11E6
+PT=447F235914368F2BECD5FF98D1A34205
+
+I=322
+KEY=7DE3A1E7234BF755908324E13DF413EB09F778296E92F4B530413500F3856FA7
+CT=447F235914368F2BECD5FF98D1A34205
+PT=5205860E4562B5CD6748EF89BF2791E9
+
+I=323
+KEY=12EE9519335A2D827649D4EB047EB5255BF2FE272BF041785709DA894CA2FE4E
+CT=5205860E4562B5CD6748EF89BF2791E9
+PT=30C0229AFDFF59E24426ACAD8D4AEFDB
+
+I=324
+KEY=78FF32A055D51E0A9D6E77D838AE72AD6B32DCBDD60F189A132F7624C1E81195
+CT=30C0229AFDFF59E24426ACAD8D4AEFDB
+PT=FF467C6E0F82F5D2F9487DDBDB43EFB3
+
+I=325
+KEY=6E49FA4CDEFC70619F739B488DD434969474A0D3D98DED48EA670BFF1AABFE26
+CT=FF467C6E0F82F5D2F9487DDBDB43EFB3
+PT=7E375B3D13871B09CA4D3357AC5EBB0E
+
+I=326
+KEY=90791666C996FF15EED1E20BAFB6B4B3EA43FBEECA0AF641202A38A8B6F54528
+CT=7E375B3D13871B09CA4D3357AC5EBB0E
+PT=E64A319F6FBD96BD799760C4077F9713
+
+I=327
+KEY=7F0D0CAB938585CF65726A6CB01DE8B00C09CA71A5B760FC59BD586CB18AD23B
+CT=E64A319F6FBD96BD799760C4077F9713
+PT=1487C8488C675BD46FAF2EEC0BC7AE7E
+
+I=328
+KEY=7B429E6D59D4D65E16ED325F49E93D9C188E023929D03B2836127680BA4D7C45
+CT=1487C8488C675BD46FAF2EEC0BC7AE7E
+PT=1F103E64A4F5239C9157E70487C50941
+
+I=329
+KEY=AF20B02C3C5BD4E33E34359B86BBF2CF079E3C5D8D2518B4A74591843D887504
+CT=1F103E64A4F5239C9157E70487C50941
+PT=24C8481DD1A2245735597A18A2433E41
+
+I=330
+KEY=E4F3CE6AFF9926837BAAB04C311F72A7235674405C873CE3921CEB9C9FCB4B45
+CT=24C8481DD1A2245735597A18A2433E41
+PT=3D9E715A686DE9AF8EE37AF54F82AA8A
+
+I=331
+KEY=A9BACBEC55AA453A83FF82CFDDB7F2F91EC8051A34EAD54C1CFF9169D049E1CF
+CT=3D9E715A686DE9AF8EE37AF54F82AA8A
+PT=B330735D9AB5B96501CDAF61A8EAD19F
+
+I=332
+KEY=5826BE9127DB557D401AF4DE6343F8AFADF87647AE5F6C291D323E0878A33050
+CT=B330735D9AB5B96501CDAF61A8EAD19F
+PT=61AE40475EA11DBCC364F5377673CE37
+
+I=333
+KEY=A8F0146E46A5391D0663380DF9F1FD6FCC563600F0FE7195DE56CB3F0ED0FE67
+CT=61AE40475EA11DBCC364F5377673CE37
+PT=525C1ED538B23D7CFA4A43114CF35BD4
+
+I=334
+KEY=20F90A51E7A0BB9B88AE1DD28C8B484A9E0A28D5C84C4CE9241C882E4223A5B3
+CT=525C1ED538B23D7CFA4A43114CF35BD4
+PT=C2957E002E35236D455F53006495E4B7
+
+I=335
+KEY=A71CC695B7AEB0D5148FA622536669385C9F56D5E6796F846143DB2E26B64104
+CT=C2957E002E35236D455F53006495E4B7
+PT=76F9C97A4B414E5DE532082BB12F5362
+
+I=336
+KEY=617CF5726F26BD9A3B52FC0D902A97AD2A669FAFAD3821D98471D30597991266
+CT=76F9C97A4B414E5DE532082BB12F5362
+PT=F4D9E814D4C61B2FB1D7CDCCBAF14AA1
+
+I=337
+KEY=D4DBBCC269A61933E4D63C3BDA5F522EDEBF77BB79FE3AF635A61EC92D6858C7
+CT=F4D9E814D4C61B2FB1D7CDCCBAF14AA1
+PT=6B51AF38B42F226D62474A97BD001FFF
+
+I=338
+KEY=512FAF06A5885D032A885EC030AF3C18B5EED883CDD1189B57E1545E90684738
+CT=6B51AF38B42F226D62474A97BD001FFF
+PT=868C58D6B805CF8F9EB04A8BA123371A
+
+I=339
+KEY=BDD2CB78E9B554FC7FEEEC05D02309F23362805575D4D714C9511ED5314B7022
+CT=868C58D6B805CF8F9EB04A8BA123371A
+PT=1752558A1F90975140CA41F68BE5333F
+
+I=340
+KEY=15CC46826BFD5B45ABAE9B0B2756D39C2430D5DF6A444045899B5F23BAAE431D
+CT=1752558A1F90975140CA41F68BE5333F
+PT=68801EAB4042E7390E64AA53C38C1D15
+
+I=341
+KEY=DF5FB425C5B25E15EA717736D8ABE6644CB0CB742A06A77C87FFF57079225E08
+CT=68801EAB4042E7390E64AA53C38C1D15
+PT=02FE87211909D8954EC90EF53100F26D
+
+I=342
+KEY=CD73FCED5EBA6038DD8B8A000111BEF94E4E4C55330F7FE9C936FB854822AC65
+CT=02FE87211909D8954EC90EF53100F26D
+PT=3A51FAFD22A2CC95B532023A37BBF0FE
+
+I=343
+KEY=EF890ED47D9F1581CC98C88F3BF7F88D741FB6A811ADB37C7C04F9BF7F995C9B
+CT=3A51FAFD22A2CC95B532023A37BBF0FE
+PT=D233A6BBC315BA5F4630AE7F99F77116
+
+I=344
+KEY=AA9CA1A7DFA24E1936E49D34054F7749A62C1013D2B809233A3457C0E66E2D8D
+CT=D233A6BBC315BA5F4630AE7F99F77116
+PT=E6B9619D7B0E1DF6CFE79FD51533406B
+
+I=345
+KEY=ADC4161B346687F98D4CB5B661662A8A4095718EA9B614D5F5D3C815F35D6DE6
+CT=E6B9619D7B0E1DF6CFE79FD51533406B
+PT=A746D31BCB29F7512E3F6E5EFD14FDAD
+
+I=346
+KEY=9C1CA3776C9ED13D220453C8AEFA0ECDE7D3A295629FE384DBECA64B0E49904B
+CT=A746D31BCB29F7512E3F6E5EFD14FDAD
+PT=B2489A51878848EC37E6782FB2110122
+
+I=347
+KEY=B64A5B45ABFDEC3EF8164FCEAE89919E559B38C4E517AB68EC0ADE64BC589169
+CT=B2489A51878848EC37E6782FB2110122
+PT=EF77F9367A063FDB874C9FC96983EAD1
+
+I=348
+KEY=AEFFDEE2501961FEEB985134E2B651EDBAECC1F29F1194B36B4641ADD5DB7BB8
+CT=EF77F9367A063FDB874C9FC96983EAD1
+PT=4ECFF4DA51BB2BE1EF8E85C4BBE51C69
+
+I=349
+KEY=6B28BA96CEB25B3862F413A2CBED4889F4233528CEAABF5284C8C4696E3E67D1
+CT=4ECFF4DA51BB2BE1EF8E85C4BBE51C69
+PT=0CAEAF484505A1AF13BB0ADCC665F91C
+
+I=350
+KEY=2062889724A47DD541F1F0A3FC8C5952F88D9A608BAF1EFD9773CEB5A85B9ECD
+CT=0CAEAF484505A1AF13BB0ADCC665F91C
+PT=6C75CA469CACCCE29CAE88202E02727C
+
+I=351
+KEY=C2115A8A6EE164B944A8C8128EBAB8E694F850261703D21F0BDD46958659ECB1
+CT=6C75CA469CACCCE29CAE88202E02727C
+PT=567060CEFF3AEDDE8AB5823450E35967
+
+I=352
+KEY=C3D2704E15936C6916073E234D0012CCC28830E8E8393FC18168C4A1D6BAB5D6
+CT=567060CEFF3AEDDE8AB5823450E35967
+PT=E04F927E409060080EC530D5C344CA24
+
+I=353
+KEY=49173A9FB3283181B71264E3FB5591FA22C7A296A8A95FC98FADF47415FE7FF2
+CT=E04F927E409060080EC530D5C344CA24
+PT=4D473408396C17D4BA3DBB63B46E7727
+
+I=354
+KEY=8BF3DDDC9217496E29F46E61233D62B66F80969E91C5481D35904F17A19008D5
+CT=4D473408396C17D4BA3DBB63B46E7727
+PT=BB6779933AC9E435C637CDA146A04284
+
+I=355
+KEY=6ACA3C31248BFBB5BB9FD54C4B31BC21D4E7EF0DAB0CAC28F3A782B6E7304A51
+CT=BB6779933AC9E435C637CDA146A04284
+PT=5C2129A55114540ED68591C60E45D6CF
+
+I=356
+KEY=1A270DAD402DC752332671216A6C3BFF88C6C6A8FA18F82625221370E9759C9E
+CT=5C2129A55114540ED68591C60E45D6CF
+PT=57790B87F69BF1C007E563A82987EEAE
+
+I=357
+KEY=6E39E75268AC2C51ABE11CE3CE16CAF3DFBFCD2F0C8309E622C770D8C0F27230
+CT=57790B87F69BF1C007E563A82987EEAE
+PT=58790B192C8B90B76F34990E28A6689A
+
+I=358
+KEY=2367A67114D722A79F9434B5A418BEEB87C6C636200899514DF3E9D6E8541AAA
+CT=58790B192C8B90B76F34990E28A6689A
+PT=599CA8B58EFE301A87CE72540CCB4067
+
+I=359
+KEY=A4CE195518F7E36D7E0D5C9666802411DE5A6E83AEF6A94BCA3D9B82E49F5ACD
+CT=599CA8B58EFE301A87CE72540CCB4067
+PT=4483131C7E03089F898166A5B3E85E3A
+
+I=360
+KEY=73C5204211D3648DAAF5FE071186C0E99AD97D9FD0F5A1D443BCFD27577704F7
+CT=4483131C7E03089F898166A5B3E85E3A
+PT=DBF64C5A0897B343BAF7047A6C564D02
+
+I=361
+KEY=1A3831AFF223BB2FE79C8EF8845E553C412F31C5D8621297F94BF95D3B2149F5
+CT=DBF64C5A0897B343BAF7047A6C564D02
+PT=B24420DA45E3620B619978CB09F1860C
+
+I=362
+KEY=31EF243EF87C32148751F8F299151042F36B111F9D81709C98D2819632D0CFF9
+CT=B24420DA45E3620B619978CB09F1860C
+PT=12B466EF6AE6F28AF78AC184DB8B3C83
+
+I=363
+KEY=9E935E6F5D76BEE2E639F2880C8352EEE1DF77F0F76782166F584012E95BF37A
+CT=12B466EF6AE6F28AF78AC184DB8B3C83
+PT=518E89A35CF55D591DE8BB924D8F96E7
+
+I=364
+KEY=C6398957838B02B5948A95DCBFBF2813B051FE53AB92DF4F72B0FB80A4D4659D
+CT=518E89A35CF55D591DE8BB924D8F96E7
+PT=1FDF7FE52BD46EF54F1F7A6242B04BD8
+
+I=365
+KEY=5764E84D9000518C185717581E0D70E5AF8E81B68046B1BA3DAF81E2E6642E45
+CT=1FDF7FE52BD46EF54F1F7A6242B04BD8
+PT=2C68E67C37B50056E80DC09B9ED84AA8
+
+I=366
+KEY=5F8CB51BF30B954B4AC09620B0A20FCA83E667CAB7F3B1ECD5A2417978BC64ED
+CT=2C68E67C37B50056E80DC09B9ED84AA8
+PT=14CC2D821B03BE21355A779B9066BE41
+
+I=367
+KEY=50B32E6D62EE3B8CE2DD5797BA70D8D2972A4A48ACF00FCDE0F836E2E8DADAAC
+CT=14CC2D821B03BE21355A779B9066BE41
+PT=BB09D339888C27294E73326E64AC3B21
+
+I=368
+KEY=E1B2199CAF1C3FA78E973ACF5C3AC8702C239971247C28E4AE8B048C8C76E18D
+CT=BB09D339888C27294E73326E64AC3B21
+PT=BCFBD8255802CC8233AEA86E49089328
+
+I=369
+KEY=3403D2498A4562E73734D065E9B44AD890D841547C7EE4669D25ACE2C57E72A5
+CT=BCFBD8255802CC8233AEA86E49089328
+PT=5A919AC72F12DB1FAB8E4876FBA8842B
+
+I=370
+KEY=B979FA15F93E5ACA1F6E452C9053751BCA49DB93536C3F7936ABE4943ED6F68E
+CT=5A919AC72F12DB1FAB8E4876FBA8842B
+PT=BDB03BD29FD3828AF1AE8C729F37F88A
+
+I=371
+KEY=A8CDF9FE3C0227A9107C700C404AE39777F9E041CCBFBDF3C70568E6A1E10E04
+CT=BDB03BD29FD3828AF1AE8C729F37F88A
+PT=0AAC43CE316476F3A532D44B4DFBF4B8
+
+I=372
+KEY=B4D497FBD5DE2CA68FF60C701E208A257D55A38FFDDBCB006237BCADEC1AFABC
+CT=0AAC43CE316476F3A532D44B4DFBF4B8
+PT=853A5EE7CB3C4BB3F0120BB2CFFB4436
+
+I=373
+KEY=A019DCC09A4CAAA3772BF4C54C8828E9F86FFD6836E780B39225B71F23E1BE8A
+CT=853A5EE7CB3C4BB3F0120BB2CFFB4436
+PT=B525599C918446AF4EA9F6965F3971EA
+
+I=374
+KEY=238BF8B851B0864F9BEC8E242B7795D14D4AA4F4A763C61CDC8C41897CD8CF60
+CT=B525599C918446AF4EA9F6965F3971EA
+PT=A8377EC293D41F74A0A2DB66BA7D3D2F
+
+I=375
+KEY=AF9E313988F294AE6A8155BC76F2514BE57DDA3634B7D9687C2E9AEFC6A5F24F
+CT=A8377EC293D41F74A0A2DB66BA7D3D2F
+PT=301BD4D318101A02166EBC23DED9C12D
+
+I=376
+KEY=3B6186F7ACE8E9B022DDE0ECF5D808D3D5660EE52CA7C36A6A4026CC187C3362
+CT=301BD4D318101A02166EBC23DED9C12D
+PT=05BD0686BE53B94FB1B42AE407BE081C
+
+I=377
+KEY=EADED20A0F405D9E3AAE404FB074162ED0DB086392F47A25DBF40C281FC23B7E
+CT=05BD0686BE53B94FB1B42AE407BE081C
+PT=7A3AF681F2043806EDB761F65D9A6C3A
+
+I=378
+KEY=AA6F474F5F5FF513FC992E4232061B75AAE1FEE260F0422336436DDE42585744
+CT=7A3AF681F2043806EDB761F65D9A6C3A
+PT=3C297DE35CCF4E6E0A800B9A3EE37C95
+
+I=379
+KEY=68BFE30863F135A09B81BE2800CBBC3796C883013C3F0C4D3CC366447CBB2BD1
+CT=3C297DE35CCF4E6E0A800B9A3EE37C95
+PT=5F8AAC15C74CC7EA87A1AC185103A9D7
+
+I=380
+KEY=9093DEBE66D714180BEB8FE51C4807ADC9422F14FB73CBA7BB62CA5C2DB88206
+CT=5F8AAC15C74CC7EA87A1AC185103A9D7
+PT=083AF3AF30961FD5A077F5564D55E9E9
+
+I=381
+KEY=A1E1049159A94DF638092C90F7707CD7C178DCBBCBE5D4721B153F0A60ED6BEF
+CT=083AF3AF30961FD5A077F5564D55E9E9
+PT=89BEFF6AB40B18ECD9413446E848253A
+
+I=382
+KEY=7C506732A8863DB1BF61EFC710F22D2348C623D17FEECC9EC2540B4C88A54ED5
+CT=89BEFF6AB40B18ECD9413446E848253A
+PT=095B2C04636C9C5BF9735BCA21211EAA
+
+I=383
+KEY=7283413612863BA1E1B5AE93DF1318F5419D0FD51C8250C53B275086A984507F
+CT=095B2C04636C9C5BF9735BCA21211EAA
+PT=E95DB3DB1E3A478C8A31212B28E0E7BC
+
+I=384
+KEY=BE861CED86D725162D938727D7AEFC1BA8C0BC0E02B81749B11671AD8164B7C3
+CT=E95DB3DB1E3A478C8A31212B28E0E7BC
+PT=9927F1D7EF0631500E1DF058932BF320
+
+I=385
+KEY=45AA89CBCE192CEEC22BF5F33DDE0E8D31E74DD9EDBE2619BF0B81F5124F44E3
+CT=9927F1D7EF0631500E1DF058932BF320
+PT=4B1147179F2AF27E5C9DBB7F01CC56A8
+
+I=386
+KEY=B08A08DABC52884E9EBB310236815BFE7AF60ACE7294D467E3963A8A1383124B
+CT=4B1147179F2AF27E5C9DBB7F01CC56A8
+PT=E9752A7D47734DACAC6E74A1A3EC4956
+
+I=387
+KEY=34B4424CE75A4A1BCE9E6C825F5F0DC1938320B335E799CB4FF84E2BB06F5B1D
+CT=E9752A7D47734DACAC6E74A1A3EC4956
+PT=AB2D652BCEE42804C5155980DA02CECC
+
+I=388
+KEY=F9954BB1A793565A79AA2B9DF408A34A38AE4598FB03B1CF8AED17AB6A6D95D1
+CT=AB2D652BCEE42804C5155980DA02CECC
+PT=3C6651362E89F6C6B28C04CA22F110EC
+
+I=389
+KEY=9548931715FB259E318020E30D68165604C814AED58A470938611361489C853D
+CT=3C6651362E89F6C6B28C04CA22F110EC
+PT=15598364698838475AB96F95CFCF3342
+
+I=390
+KEY=1CDB0706417BBE66B559237109353221119197CABC027F4E62D87CF48753B67F
+CT=15598364698838475AB96F95CFCF3342
+PT=D8B3BB941893206E1CA6654B81F403E4
+
+I=391
+KEY=8C4AD897B595252B0987673F45EE73F2C9222C5EA4915F207E7E19BF06A7B59B
+CT=D8B3BB941893206E1CA6654B81F403E4
+PT=ECE471CC2FF45C26C7143C41702F90D2
+
+I=392
+KEY=A6D3DF3279B7405256C0D22DA240524125C65D928B650306B96A25FE76882549
+CT=ECE471CC2FF45C26C7143C41702F90D2
+PT=AB387AE5A5FC892C311D97C22467940D
+
+I=393
+KEY=36F250F7C3906C7E0020055422CDB8B28EFE27772E998A2A8877B23C52EFB144
+CT=AB387AE5A5FC892C311D97C22467940D
+PT=FF48C2C77D5F52DF27C4060DF7F895D7
+
+I=394
+KEY=4FF045275860B943EDE02C802F34B71B71B6E5B053C6D8F5AFB3B431A5172493
+CT=FF48C2C77D5F52DF27C4060DF7F895D7
+PT=221BC444E2A6A7F8DE9DA16AB01EB2AC
+
+I=395
+KEY=E15B4E0E242FBABF1D47E9DBE6D0660253AD21F4B1607F0D712E155B1509963F
+CT=221BC444E2A6A7F8DE9DA16AB01EB2AC
+PT=DE252D19973ABD9F182049D39455784B
+
+I=396
+KEY=401023A611A3133C895A3684AB3E7C9D8D880CED265AC292690E5C88815CEE74
+CT=DE252D19973ABD9F182049D39455784B
+PT=843163BD101982EE948039915C8F60D8
+
+I=397
+KEY=B9DDF52C271F143E523532E45E6F368D09B96F503643407CFD8E6519DDD38EAC
+CT=843163BD101982EE948039915C8F60D8
+PT=6FD9D36B751854C3417F29E8F3B654D9
+
+I=398
+KEY=AC7F45F8630CE02525F9F4941B4E13206660BC3B435B14BFBCF14CF12E65DA75
+CT=6FD9D36B751854C3417F29E8F3B654D9
+PT=E1268BA8A1473DEDE6CA64DDF2C8B805
+
+I=399
+KEY=DE11FF0A429E1CD3DE016DAC294F771187463793E21C29525A3B282CDCAD6270
+CT=E1268BA8A1473DEDE6CA64DDF2C8B805
+PT=4DE0C6DF7CB1697284604D60271BC59A
+
+===========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/ecb_e_m.txt b/krb5-1-6/src/lib/crypto/aes/test/ecb_e_m.txt
new file mode 100644
index 000000000..40a95e7ca
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/ecb_e_m.txt
@@ -0,0 +1,6024 @@
+
+=========================
+
+FILENAME:  "ecb_e_m.txt"
+
+Electronic Codebook (ECB) Mode - ENCRYPTION
+Monte Carlo Test
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+=========================
+
+KEYSIZE=128
+
+I=0
+KEY=00000000000000000000000000000000
+PT=00000000000000000000000000000000
+CT=C34C052CC0DA8D73451AFE5F03BE297F
+
+I=1
+KEY=C34C052CC0DA8D73451AFE5F03BE297F
+PT=C34C052CC0DA8D73451AFE5F03BE297F
+CT=0AC15A9AFBB24D54AD99E987208272E2
+
+I=2
+KEY=C98D5FB63B68C027E88317D8233C5B9D
+PT=0AC15A9AFBB24D54AD99E987208272E2
+CT=A3D43BFFA65D0E80092F67A314857870
+
+I=3
+KEY=6A5964499D35CEA7E1AC707B37B923ED
+PT=A3D43BFFA65D0E80092F67A314857870
+CT=355F697E8B868B65B25A04E18D782AFA
+
+I=4
+KEY=5F060D3716B345C253F6749ABAC10917
+PT=355F697E8B868B65B25A04E18D782AFA
+CT=ACC863637868E3E068D2FD6E3508454A
+
+I=5
+KEY=F3CE6E546EDBA6223B2489F48FC94C5D
+PT=ACC863637868E3E068D2FD6E3508454A
+CT=665F9F12A824F3D52A1C71D6210D5470
+
+I=6
+KEY=9591F146C6FF55F71138F822AEC4182D
+PT=665F9F12A824F3D52A1C71D6210D5470
+CT=9B27361DBC8E5618E8E98036F5AD40B0
+
+I=7
+KEY=0EB6C75B7A7103EFF9D178145B69589D
+PT=9B27361DBC8E5618E8E98036F5AD40B0
+CT=21D9BD7EBA0163A293F2D56C316CBD36
+
+I=8
+KEY=2F6F7A25C070604D6A23AD786A05E5AB
+PT=21D9BD7EBA0163A293F2D56C316CBD36
+CT=3E8037A9988E28FF81F2A7154ACD91BE
+
+I=9
+KEY=11EF4D8C58FE48B2EBD10A6D20C87415
+PT=3E8037A9988E28FF81F2A7154ACD91BE
+CT=014EE14F1AA8C0D4A47A72F197F4DCB0
+
+I=10
+KEY=10A1ACC3425688664FAB789CB73CA8A5
+PT=014EE14F1AA8C0D4A47A72F197F4DCB0
+CT=0B542083DBC03A96AA00C1A5AE58C9F1
+
+I=11
+KEY=1BF58C409996B2F0E5ABB93919646154
+PT=0B542083DBC03A96AA00C1A5AE58C9F1
+CT=7340B59E1E3BB9211CE167F2DEBDB090
+
+I=12
+KEY=68B539DE87AD0BD1F94ADECBC7D9D1C4
+PT=7340B59E1E3BB9211CE167F2DEBDB090
+CT=67E05F75135BA834CBCDCFF068541BBE
+
+I=13
+KEY=0F5566AB94F6A3E53287113BAF8DCA7A
+PT=67E05F75135BA834CBCDCFF068541BBE
+CT=8BD5553105C3507B0A07FDB351B25B4F
+
+I=14
+KEY=8480339A9135F39E3880EC88FE3F9135
+PT=8BD5553105C3507B0A07FDB351B25B4F
+CT=649F061F95C0A79BD3066EFFE5B27CAB
+
+I=15
+KEY=E01F358504F55405EB8682771B8DED9E
+PT=649F061F95C0A79BD3066EFFE5B27CAB
+CT=697F4EB0603340E90FE91C27B6D9CEAA
+
+I=16
+KEY=89607B3564C614ECE46F9E50AD542334
+PT=697F4EB0603340E90FE91C27B6D9CEAA
+CT=A8CBBA624FA28A7F8637324E1E20CB9C
+
+I=17
+KEY=21ABC1572B649E936258AC1EB374E8A8
+PT=A8CBBA624FA28A7F8637324E1E20CB9C
+CT=73B852132DE715872A40EB25B1133C00
+
+I=18
+KEY=5213934406838B144818473B0267D4A8
+PT=73B852132DE715872A40EB25B1133C00
+CT=1328A1C2F386BB3E4D4BE0942B8249A2
+
+I=19
+KEY=413B3286F505302A0553A7AF29E59D0A
+PT=1328A1C2F386BB3E4D4BE0942B8249A2
+CT=06F72DEA0067F543AA8C342CC9191745
+
+I=20
+KEY=47CC1F6CF562C569AFDF9383E0FC8A4F
+PT=06F72DEA0067F543AA8C342CC9191745
+CT=110B6011B60C94382C2321BFCAA62A1C
+
+I=21
+KEY=56C77F7D436E515183FCB23C2A5AA053
+PT=110B6011B60C94382C2321BFCAA62A1C
+CT=80C90EF6794361DFA400EFE922F45A59
+
+I=22
+KEY=D60E718B3A2D308E27FC5DD508AEFA0A
+PT=80C90EF6794361DFA400EFE922F45A59
+CT=F8DF0AC62EE229245DB1F300F2E5B143
+
+I=23
+KEY=2ED17B4D14CF19AA7A4DAED5FA4B4B49
+PT=F8DF0AC62EE229245DB1F300F2E5B143
+CT=45390146539E773B502E84A0C29AD5B0
+
+I=24
+KEY=6BE87A0B47516E912A632A7538D19EF9
+PT=45390146539E773B502E84A0C29AD5B0
+CT=B07721757865838BDFC2329998B5174F
+
+I=25
+KEY=DB9F5B7E3F34ED1AF5A118ECA06489B6
+PT=B07721757865838BDFC2329998B5174F
+CT=B83F3B7A9FFBA35DF1D6661A0F8AD0F4
+
+I=26
+KEY=63A06004A0CF4E4704777EF6AFEE5942
+PT=B83F3B7A9FFBA35DF1D6661A0F8AD0F4
+CT=7098C99B1B245DE623B78F1B07D08EBE
+
+I=27
+KEY=1338A99FBBEB13A127C0F1EDA83ED7FC
+PT=7098C99B1B245DE623B78F1B07D08EBE
+CT=58A095EF9268B923920238486D0B13E1
+
+I=28
+KEY=4B983C702983AA82B5C2C9A5C535C41D
+PT=58A095EF9268B923920238486D0B13E1
+CT=97DD8052CE0D87715075A42942C120ED
+
+I=29
+KEY=DC45BC22E78E2DF3E5B76D8C87F4E4F0
+PT=97DD8052CE0D87715075A42942C120ED
+CT=F480B5A67DAFCB9524DC21453AF66FAF
+
+I=30
+KEY=28C509849A21E666C16B4CC9BD028B5F
+PT=F480B5A67DAFCB9524DC21453AF66FAF
+CT=71CE64CE8C98367F2F12E6851AC70FF3
+
+I=31
+KEY=590B6D4A16B9D019EE79AA4CA7C584AC
+PT=71CE64CE8C98367F2F12E6851AC70FF3
+CT=81C3AA693CC1C647399701DA17D5FDD5
+
+I=32
+KEY=D8C8C7232A78165ED7EEAB96B0107979
+PT=81C3AA693CC1C647399701DA17D5FDD5
+CT=5BB93103F6DDF0415592EE2217704D41
+
+I=33
+KEY=8371F620DCA5E61F827C45B4A7603438
+PT=5BB93103F6DDF0415592EE2217704D41
+CT=87B8B17FF9079829AB5C47E055FFCEE3
+
+I=34
+KEY=04C9475F25A27E3629200254F29FFADB
+PT=87B8B17FF9079829AB5C47E055FFCEE3
+CT=615FE7D34154F42D6CE9D647904295E0
+
+I=35
+KEY=6596A08C64F68A1B45C9D41362DD6F3B
+PT=615FE7D34154F42D6CE9D647904295E0
+CT=A60C213CDF9B54DF9041948F98585CE2
+
+I=36
+KEY=C39A81B0BB6DDEC4D588409CFA8533D9
+PT=A60C213CDF9B54DF9041948F98585CE2
+CT=FB126C61071EB9167B6FF28E5244E624
+
+I=37
+KEY=3888EDD1BC7367D2AEE7B212A8C1D5FD
+PT=FB126C61071EB9167B6FF28E5244E624
+CT=8A79CE45F030B91B53D1591D10FF1B02
+
+I=38
+KEY=B2F123944C43DEC9FD36EB0FB83ECEFF
+PT=8A79CE45F030B91B53D1591D10FF1B02
+CT=BE20190BAE15162F43E93F67A580192B
+
+I=39
+KEY=0CD13A9FE256C8E6BEDFD4681DBED7D4
+PT=BE20190BAE15162F43E93F67A580192B
+CT=0107D3E3511F91545D02B498A9E3C318
+
+I=40
+KEY=0DD6E97CB34959B2E3DD60F0B45D14CC
+PT=0107D3E3511F91545D02B498A9E3C318
+CT=2A832A1205D6B5FCF1B20126EE59DD9D
+
+I=41
+KEY=2755C36EB69FEC4E126F61D65A04C951
+PT=2A832A1205D6B5FCF1B20126EE59DD9D
+CT=F362782F550DCBFC49CEF15C3A0ABA7A
+
+I=42
+KEY=D437BB41E39227B25BA1908A600E732B
+PT=F362782F550DCBFC49CEF15C3A0ABA7A
+CT=51A8A0C6434A3BE8C939B6DDD56EAA53
+
+I=43
+KEY=859F1B87A0D81C5A92982657B560D978
+PT=51A8A0C6434A3BE8C939B6DDD56EAA53
+CT=89D3F1086F3D96C18A76C61F25A52221
+
+I=44
+KEY=0C4CEA8FCFE58A9B18EEE04890C5FB59
+PT=89D3F1086F3D96C18A76C61F25A52221
+CT=A5F7E0A5FA70DDB718EF970F50EB7B86
+
+I=45
+KEY=A9BB0A2A3595572C00017747C02E80DF
+PT=A5F7E0A5FA70DDB718EF970F50EB7B86
+CT=7BB64305538E71AFBF993B5BD23D5523
+
+I=46
+KEY=D20D492F661B2683BF984C1C1213D5FC
+PT=7BB64305538E71AFBF993B5BD23D5523
+CT=E6BF8F5338568603EC668C6D15331FA5
+
+I=47
+KEY=34B2C67C5E4DA08053FEC0710720CA59
+PT=E6BF8F5338568603EC668C6D15331FA5
+CT=27644649FCDF52085CDB20E3DEE1E2F6
+
+I=48
+KEY=13D68035A292F2880F25E092D9C128AF
+PT=27644649FCDF52085CDB20E3DEE1E2F6
+CT=7629AACAED7F49938373C83410AD1744
+
+I=49
+KEY=65FF2AFF4FEDBB1B8C5628A6C96C3FEB
+PT=7629AACAED7F49938373C83410AD1744
+CT=D440FC6E9A65819934FAF8641C05A17C
+
+I=50
+KEY=B1BFD691D5883A82B8ACD0C2D5699E97
+PT=D440FC6E9A65819934FAF8641C05A17C
+CT=FBEE29FEFD725E1852B58502D3076C46
+
+I=51
+KEY=4A51FF6F28FA649AEA1955C0066EF2D1
+PT=FBEE29FEFD725E1852B58502D3076C46
+CT=E345A47A6C89BE4350CDD8C9D319529D
+
+I=52
+KEY=A9145B154473DAD9BAD48D09D577A04C
+PT=E345A47A6C89BE4350CDD8C9D319529D
+CT=1C6A7CBAF21E483B6025DB6DA573C5C6
+
+I=53
+KEY=B57E27AFB66D92E2DAF156647004658A
+PT=1C6A7CBAF21E483B6025DB6DA573C5C6
+CT=2B05F4D8EB50D851A013798753B65A1F
+
+I=54
+KEY=9E7BD3775D3D4AB37AE22FE323B23F95
+PT=2B05F4D8EB50D851A013798753B65A1F
+CT=CEFE04978228A0DBCCE9EE42B21DD34A
+
+I=55
+KEY=5085D7E0DF15EA68B60BC1A191AFECDF
+PT=CEFE04978228A0DBCCE9EE42B21DD34A
+CT=7B41DF8CD85B61EA800536648DBDA2AE
+
+I=56
+KEY=2BC4086C074E8B82360EF7C51C124E71
+PT=7B41DF8CD85B61EA800536648DBDA2AE
+CT=08688872151D18CD19E2FC14B9E4C962
+
+I=57
+KEY=23AC801E1253934F2FEC0BD1A5F68713
+PT=08688872151D18CD19E2FC14B9E4C962
+CT=F08C88BE5E748C4D82D2E7D7813A33AF
+
+I=58
+KEY=D32008A04C271F02AD3EEC0624CCB4BC
+PT=F08C88BE5E748C4D82D2E7D7813A33AF
+CT=319B7D38AB1AC3AEA0A0490C341F4F20
+
+I=59
+KEY=E2BB7598E73DDCAC0D9EA50A10D3FB9C
+PT=319B7D38AB1AC3AEA0A0490C341F4F20
+CT=EE70748772E8D88B2717D78F31F0EA86
+
+I=60
+KEY=0CCB011F95D504272A8972852123111A
+PT=EE70748772E8D88B2717D78F31F0EA86
+CT=A3A5DC791EA1BBB9D7A2B292572DFD5C
+
+I=61
+KEY=AF6EDD668B74BF9EFD2BC017760EEC46
+PT=A3A5DC791EA1BBB9D7A2B292572DFD5C
+CT=255692B06B3A18498BCAF99F7B3EE374
+
+I=62
+KEY=8A384FD6E04EA7D776E139880D300F32
+PT=255692B06B3A18498BCAF99F7B3EE374
+CT=500E492232891293875F50279B5DC5C3
+
+I=63
+KEY=DA3606F4D2C7B544F1BE69AF966DCAF1
+PT=500E492232891293875F50279B5DC5C3
+CT=57C3FCCE9B5BA3BC19BBF7BB9B37A9AC
+
+I=64
+KEY=8DF5FA3A499C16F8E8059E140D5A635D
+PT=57C3FCCE9B5BA3BC19BBF7BB9B37A9AC
+CT=BF06FDFDB687C8B24FB0E2A6D6D37EA5
+
+I=65
+KEY=32F307C7FF1BDE4AA7B57CB2DB891DF8
+PT=BF06FDFDB687C8B24FB0E2A6D6D37EA5
+CT=6D459ED545CF3C6FF2746411CD9B3E31
+
+I=66
+KEY=5FB69912BAD4E22555C118A3161223C9
+PT=6D459ED545CF3C6FF2746411CD9B3E31
+CT=C74E0704A9D9EC2D90F75B34FC95CD32
+
+I=67
+KEY=98F89E16130D0E08C5364397EA87EEFB
+PT=C74E0704A9D9EC2D90F75B34FC95CD32
+CT=0453D4FBC2D7F8E0AD0AD90F98D1EC5C
+
+I=68
+KEY=9CAB4AEDD1DAF6E8683C9A98725602A7
+PT=0453D4FBC2D7F8E0AD0AD90F98D1EC5C
+CT=5BBA052D6C39DC1E9553B7646CB7344B
+
+I=69
+KEY=C7114FC0BDE32AF6FD6F2DFC1EE136EC
+PT=5BBA052D6C39DC1E9553B7646CB7344B
+CT=9870FFE04984426501ECB55FFBB363CB
+
+I=70
+KEY=5F61B020F4676893FC8398A3E5525527
+PT=9870FFE04984426501ECB55FFBB363CB
+CT=1363D65F7C943FC4512E41A717D3704D
+
+I=71
+KEY=4C02667F88F35757ADADD904F281256A
+PT=1363D65F7C943FC4512E41A717D3704D
+CT=664762AED6BC5FB74A646A928837FC83
+
+I=72
+KEY=2A4504D15E4F08E0E7C9B3967AB6D9E9
+PT=664762AED6BC5FB74A646A928837FC83
+CT=655CB6BAB4B0532273689E4DC9234C42
+
+I=73
+KEY=4F19B26BEAFF5BC294A12DDBB39595AB
+PT=655CB6BAB4B0532273689E4DC9234C42
+CT=E8AAE0E0B9D2BE6259AEBC478DC90FD9
+
+I=74
+KEY=A7B3528B532DE5A0CD0F919C3E5C9A72
+PT=E8AAE0E0B9D2BE6259AEBC478DC90FD9
+CT=FECACAF43DD920FA3078256C6A587741
+
+I=75
+KEY=5979987F6EF4C55AFD77B4F05404ED33
+PT=FECACAF43DD920FA3078256C6A587741
+CT=11F3F56529B8B172D87A4C86BB90F3B6
+
+I=76
+KEY=488A6D1A474C7428250DF876EF941E85
+PT=11F3F56529B8B172D87A4C86BB90F3B6
+CT=B44340D44F1ABA37CB09FE57FC771A9E
+
+I=77
+KEY=FCC92DCE0856CE1FEE04062113E3041B
+PT=B44340D44F1ABA37CB09FE57FC771A9E
+CT=C49F12B88C34A0D696FE283B01D5710C
+
+I=78
+KEY=38563F7684626EC978FA2E1A12367517
+PT=C49F12B88C34A0D696FE283B01D5710C
+CT=58D6D2D36C14DDBDA7604AB740918D76
+
+I=79
+KEY=6080EDA5E876B374DF9A64AD52A7F861
+PT=58D6D2D36C14DDBDA7604AB740918D76
+CT=21F735F77B0EAD7551CE06900A568EB3
+
+I=80
+KEY=4177D85293781E018E54623D58F176D2
+PT=21F735F77B0EAD7551CE06900A568EB3
+CT=FE2E9BDB393BF6D1BBF108B8AC3B6818
+
+I=81
+KEY=BF594389AA43E8D035A56A85F4CA1ECA
+PT=FE2E9BDB393BF6D1BBF108B8AC3B6818
+CT=FECFCD3722C6C8E6608258341220E739
+
+I=82
+KEY=41968EBE88852036552732B1E6EAF9F3
+PT=FECFCD3722C6C8E6608258341220E739
+CT=10A8BB234C9D9A22DEC7887E931F85BD
+
+I=83
+KEY=513E359DC418BA148BE0BACF75F57C4E
+PT=10A8BB234C9D9A22DEC7887E931F85BD
+CT=767EB7DBA70BC7094DF7A5BDD233EB5C
+
+I=84
+KEY=2740824663137D1DC6171F72A7C69712
+PT=767EB7DBA70BC7094DF7A5BDD233EB5C
+CT=FCD7184F3F4DB7CA182225B9A358209D
+
+I=85
+KEY=DB979A095C5ECAD7DE353ACB049EB78F
+PT=FCD7184F3F4DB7CA182225B9A358209D
+CT=A5CD025AEBF0380EAC66EF034806179F
+
+I=86
+KEY=7E5A9853B7AEF2D97253D5C84C98A010
+PT=A5CD025AEBF0380EAC66EF034806179F
+CT=FE46F4A72C7031FE8D900152CD20B95F
+
+I=87
+KEY=801C6CF49BDEC327FFC3D49A81B8194F
+PT=FE46F4A72C7031FE8D900152CD20B95F
+CT=CF1ACB502A4B608C61364891E34F93A0
+
+I=88
+KEY=4F06A7A4B195A3AB9EF59C0B62F78AEF
+PT=CF1ACB502A4B608C61364891E34F93A0
+CT=95AB1367FF6C03DE87FFA282A3E52200
+
+I=89
+KEY=DAADB4C34EF9A075190A3E89C112A8EF
+PT=95AB1367FF6C03DE87FFA282A3E52200
+CT=762B6393252B347F55AF3E4CA16F2FC9
+
+I=90
+KEY=AC86D7506BD2940A4CA500C5607D8726
+PT=762B6393252B347F55AF3E4CA16F2FC9
+CT=A63491A22E23AD921ADAB9CC0DA20521
+
+I=91
+KEY=0AB246F245F13998567FB9096DDF8207
+PT=A63491A22E23AD921ADAB9CC0DA20521
+CT=C0852A5E7CEEAFB5FA87C440B598BFD6
+
+I=92
+KEY=CA376CAC391F962DACF87D49D8473DD1
+PT=C0852A5E7CEEAFB5FA87C440B598BFD6
+CT=485747C528B08033169E991E98E4CBB5
+
+I=93
+KEY=82602B6911AF161EBA66E45740A3F664
+PT=485747C528B08033169E991E98E4CBB5
+CT=415B95B222161A8C9ED20CF99C26848C
+
+I=94
+KEY=C33BBEDB33B90C9224B4E8AEDC8572E8
+PT=415B95B222161A8C9ED20CF99C26848C
+CT=7E673E6348C38CD40C9B11F4C9F3E3A0
+
+I=95
+KEY=BD5C80B87B7A8046282FF95A15769148
+PT=7E673E6348C38CD40C9B11F4C9F3E3A0
+CT=B88508E55279AFF0D848C38DBEC76B2C
+
+I=96
+KEY=05D9885D29032FB6F0673AD7ABB1FA64
+PT=B88508E55279AFF0D848C38DBEC76B2C
+CT=3902B5DC34E815BA50A53DB9C8FFAA92
+
+I=97
+KEY=3CDB3D811DEB3A0CA0C2076E634E50F6
+PT=3902B5DC34E815BA50A53DB9C8FFAA92
+CT=FEF57F51360547EA6B88085B8656A1D0
+
+I=98
+KEY=C22E42D02BEE7DE6CB4A0F35E518F126
+PT=FEF57F51360547EA6B88085B8656A1D0
+CT=94D052E1F097106A5B714ADD0EF79E64
+
+I=99
+KEY=56FE1031DB796D8C903B45E8EBEF6F42
+PT=94D052E1F097106A5B714ADD0EF79E64
+CT=7FD3EF411360E5270F63A8BACCCC74C0
+
+I=100
+KEY=292DFF70C81988AB9F58ED5227231B82
+PT=7FD3EF411360E5270F63A8BACCCC74C0
+CT=F572692DE6EFBC2309B947D1A75BE009
+
+I=101
+KEY=DC5F965D2EF6348896E1AA838078FB8B
+PT=F572692DE6EFBC2309B947D1A75BE009
+CT=BFD3233C513448C283C05311B8085B5C
+
+I=102
+KEY=638CB5617FC27C4A1521F9923870A0D7
+PT=BFD3233C513448C283C05311B8085B5C
+CT=078739F570071AA1A96A1F00F31E05FD
+
+I=103
+KEY=640B8C940FC566EBBC4BE692CB6EA52A
+PT=078739F570071AA1A96A1F00F31E05FD
+CT=947CA236277CDD0AC13C194B99E8CF16
+
+I=104
+KEY=F0772EA228B9BBE17D77FFD952866A3C
+PT=947CA236277CDD0AC13C194B99E8CF16
+CT=34DE5F2D355BC4ACE54AD0CB8C008CB8
+
+I=105
+KEY=C4A9718F1DE27F4D983D2F12DE86E684
+PT=34DE5F2D355BC4ACE54AD0CB8C008CB8
+CT=E5729CBD84C89B914F35412F902A2CA3
+
+I=106
+KEY=21DBED32992AE4DCD7086E3D4EACCA27
+PT=E5729CBD84C89B914F35412F902A2CA3
+CT=EB326D6ABAFC93EADBEC9B05CE4AAF0C
+
+I=107
+KEY=CAE9805823D677360CE4F53880E6652B
+PT=EB326D6ABAFC93EADBEC9B05CE4AAF0C
+CT=9F088089F8D8E8E28A9A2A1FF50F2ED3
+
+I=108
+KEY=55E100D1DB0E9FD4867EDF2775E94BF8
+PT=9F088089F8D8E8E28A9A2A1FF50F2ED3
+CT=C8D2BF3D6ADB57F478656D4808142160
+
+I=109
+KEY=9D33BFECB1D5C820FE1BB26F7DFD6A98
+PT=C8D2BF3D6ADB57F478656D4808142160
+CT=062016811215B9DBDD3C794A15FBEBBA
+
+I=110
+KEY=9B13A96DA3C071FB2327CB2568068122
+PT=062016811215B9DBDD3C794A15FBEBBA
+CT=71F9F04E9AED1C302E5ED2AD36B5C7F5
+
+I=111
+KEY=EAEA5923392D6DCB0D7919885EB346D7
+PT=71F9F04E9AED1C302E5ED2AD36B5C7F5
+CT=253982568F6C3FDFDE173E46B614989C
+
+I=112
+KEY=CFD3DB75B6415214D36E27CEE8A7DE4B
+PT=253982568F6C3FDFDE173E46B614989C
+CT=6D51D51276A6FA9C933E4D4496D0455E
+
+I=113
+KEY=A2820E67C0E7A88840506A8A7E779B15
+PT=6D51D51276A6FA9C933E4D4496D0455E
+CT=B9A6924F773CE826BBBC6DDBFA4E146A
+
+I=114
+KEY=1B249C28B7DB40AEFBEC075184398F7F
+PT=B9A6924F773CE826BBBC6DDBFA4E146A
+CT=474943C523162BC81186779A07144BC6
+
+I=115
+KEY=5C6DDFED94CD6B66EA6A70CB832DC4B9
+PT=474943C523162BC81186779A07144BC6
+CT=20128A092B99B4BC212B1107C3BA1DF9
+
+I=116
+KEY=7C7F55E4BF54DFDACB4161CC4097D940
+PT=20128A092B99B4BC212B1107C3BA1DF9
+CT=90330B8FB5A50E958250A953EF5145C7
+
+I=117
+KEY=EC4C5E6B0AF1D14F4911C89FAFC69C87
+PT=90330B8FB5A50E958250A953EF5145C7
+CT=C1B788D0EB2C8C7B9E020CC2BEACD595
+
+I=118
+KEY=2DFBD6BBE1DD5D34D713C45D116A4912
+PT=C1B788D0EB2C8C7B9E020CC2BEACD595
+CT=EF87960DABBE82F6CFA8045CE4A9EED0
+
+I=119
+KEY=C27C40B64A63DFC218BBC001F5C3A7C2
+PT=EF87960DABBE82F6CFA8045CE4A9EED0
+CT=405C8408D5027DF90CBE3159701D161A
+
+I=120
+KEY=8220C4BE9F61A23B1405F15885DEB1D8
+PT=405C8408D5027DF90CBE3159701D161A
+CT=FCAB7F88E85D6573A98D23D684A5A5F3
+
+I=121
+KEY=7E8BBB36773CC748BD88D28E017B142B
+PT=FCAB7F88E85D6573A98D23D684A5A5F3
+CT=191E6F1EECBF5149F4D49446E97D8820
+
+I=122
+KEY=6795D4289B839601495C46C8E8069C0B
+PT=191E6F1EECBF5149F4D49446E97D8820
+CT=C77128F53D48594194EFBA67E46C6B23
+
+I=123
+KEY=A0E4FCDDA6CBCF40DDB3FCAF0C6AF728
+PT=C77128F53D48594194EFBA67E46C6B23
+CT=DFB898170571450CC5E2244AE4D3AF43
+
+I=124
+KEY=7F5C64CAA3BA8A4C1851D8E5E8B9586B
+PT=DFB898170571450CC5E2244AE4D3AF43
+CT=3BD1633B5053609A3B42CC098F9F5D87
+
+I=125
+KEY=448D07F1F3E9EAD6231314EC672605EC
+PT=3BD1633B5053609A3B42CC098F9F5D87
+CT=AC15B23F205AEB10470F853BA18361E0
+
+I=126
+KEY=E898B5CED3B301C6641C91D7C6A5640C
+PT=AC15B23F205AEB10470F853BA18361E0
+CT=2DA73BA6E01B1ADFBEEAFA2E37942078
+
+I=127
+KEY=C53F8E6833A81B19DAF66BF9F1314474
+PT=2DA73BA6E01B1ADFBEEAFA2E37942078
+CT=C5B3D7089173958B32340B88D35B738B
+
+I=128
+KEY=008C5960A2DB8E92E8C26071226A37FF
+PT=C5B3D7089173958B32340B88D35B738B
+CT=8318BAA96569F3ADCD30C08D54494392
+
+I=129
+KEY=8394E3C9C7B27D3F25F2A0FC7623746D
+PT=8318BAA96569F3ADCD30C08D54494392
+CT=4F6F2A06A1A344B261084563BCCC5A5A
+
+I=130
+KEY=CCFBC9CF6611398D44FAE59FCAEF2E37
+PT=4F6F2A06A1A344B261084563BCCC5A5A
+CT=07EC18166362BF049A48D146A63FF378
+
+I=131
+KEY=CB17D1D905738689DEB234D96CD0DD4F
+PT=07EC18166362BF049A48D146A63FF378
+CT=81CB17ABAC28A3ED135442454C212646
+
+I=132
+KEY=4ADCC672A95B2564CDE6769C20F1FB09
+PT=81CB17ABAC28A3ED135442454C212646
+CT=C1CBDE45E27B9B1198CE93A51E38D9C5
+
+I=133
+KEY=8B1718374B20BE755528E5393EC922CC
+PT=C1CBDE45E27B9B1198CE93A51E38D9C5
+CT=8E4EB89DDFEE065784556FA0B426954A
+
+I=134
+KEY=0559A0AA94CEB822D17D8A998AEFB786
+PT=8E4EB89DDFEE065784556FA0B426954A
+CT=6A966414CC6FE52F957E9DE7012EC4BD
+
+I=135
+KEY=6FCFC4BE58A15D0D4403177E8BC1733B
+PT=6A966414CC6FE52F957E9DE7012EC4BD
+CT=7C88474D963BFDFE61F052F51D1796EF
+
+I=136
+KEY=134783F3CE9AA0F325F3458B96D6E5D4
+PT=7C88474D963BFDFE61F052F51D1796EF
+CT=6269F5DA04B09D442DDCB46001573AE9
+
+I=137
+KEY=712E7629CA2A3DB7082FF1EB9781DF3D
+PT=6269F5DA04B09D442DDCB46001573AE9
+CT=FBD2965ACE0B360A12EF39873A8F3805
+
+I=138
+KEY=8AFCE07304210BBD1AC0C86CAD0EE738
+PT=FBD2965ACE0B360A12EF39873A8F3805
+CT=5B46EF12C9BE55DCD5571D82E5BC6FF1
+
+I=139
+KEY=D1BA0F61CD9F5E61CF97D5EE48B288C9
+PT=5B46EF12C9BE55DCD5571D82E5BC6FF1
+CT=403DEFDB60876F3161CF02F319F5EA9A
+
+I=140
+KEY=9187E0BAAD183150AE58D71D51476253
+PT=403DEFDB60876F3161CF02F319F5EA9A
+CT=70FD321C583C1B54ED6AD3A79721E84A
+
+I=141
+KEY=E17AD2A6F5242A04433204BAC6668A19
+PT=70FD321C583C1B54ED6AD3A79721E84A
+CT=32AE26E948D563782532AC711BFAB644
+
+I=142
+KEY=D3D4F44FBDF1497C6600A8CBDD9C3C5D
+PT=32AE26E948D563782532AC711BFAB644
+CT=ECF948F5EBB98E4C7286046E0F7AF127
+
+I=143
+KEY=3F2DBCBA5648C7301486ACA5D2E6CD7A
+PT=ECF948F5EBB98E4C7286046E0F7AF127
+CT=818F87EFA0B5E4098E737AD44DB537BA
+
+I=144
+KEY=BEA23B55F6FD23399AF5D6719F53FAC0
+PT=818F87EFA0B5E4098E737AD44DB537BA
+CT=029F170737413F1BFBE02C292D506E44
+
+I=145
+KEY=BC3D2C52C1BC1C226115FA58B2039484
+PT=029F170737413F1BFBE02C292D506E44
+CT=77A7C520912761121373E35FD3B5AF0F
+
+I=146
+KEY=CB9AE972509B7D307266190761B63B8B
+PT=77A7C520912761121373E35FD3B5AF0F
+CT=D407B965C368E1F77195ED446BEEBA73
+
+I=147
+KEY=1F9D501793F39CC703F3F4430A5881F8
+PT=D407B965C368E1F77195ED446BEEBA73
+CT=D1F304E0B3614A4840F128AA364BA6A3
+
+I=148
+KEY=CE6E54F72092D68F4302DCE93C13275B
+PT=D1F304E0B3614A4840F128AA364BA6A3
+CT=69B748543EE72474D0CC301BDBD50A6C
+
+I=149
+KEY=A7D91CA31E75F2FB93CEECF2E7C62D37
+PT=69B748543EE72474D0CC301BDBD50A6C
+CT=BA471D91DBC6D27EBA7B510E67830C3F
+
+I=150
+KEY=1D9E0132C5B3208529B5BDFC80452108
+PT=BA471D91DBC6D27EBA7B510E67830C3F
+CT=7C0CF396D078E01A741613B1E1D7A9CB
+
+I=151
+KEY=6192F2A415CBC09F5DA3AE4D619288C3
+PT=7C0CF396D078E01A741613B1E1D7A9CB
+CT=6F670A289398F49C75ACBBE9EAC2ABFC
+
+I=152
+KEY=0EF5F88C86533403280F15A48B50233F
+PT=6F670A289398F49C75ACBBE9EAC2ABFC
+CT=C392EF479528BF1B02296E6C894E4FDD
+
+I=153
+KEY=CD6717CB137B8B182A267BC8021E6CE2
+PT=C392EF479528BF1B02296E6C894E4FDD
+CT=C4226C8C98D5F137A4C6A239E04B0FB3
+
+I=154
+KEY=09457B478BAE7A2F8EE0D9F1E2556351
+PT=C4226C8C98D5F137A4C6A239E04B0FB3
+CT=2382714FC945AD4A1E03858B63973B9E
+
+I=155
+KEY=2AC70A0842EBD76590E35C7A81C258CF
+PT=2382714FC945AD4A1E03858B63973B9E
+CT=E41F350AC9320A8A23E27C0349978168
+
+I=156
+KEY=CED83F028BD9DDEFB3012079C855D9A7
+PT=E41F350AC9320A8A23E27C0349978168
+CT=7E9137997CB7676F3D0141797C6F31A8
+
+I=157
+KEY=B049089BF76EBA808E006100B43AE80F
+PT=7E9137997CB7676F3D0141797C6F31A8
+CT=4BF7EBC15369A757981EE4A0B7F55706
+
+I=158
+KEY=FBBEE35AA4071DD7161E85A003CFBF09
+PT=4BF7EBC15369A757981EE4A0B7F55706
+CT=EC677E86A8D2A5935D33D6471A58A781
+
+I=159
+KEY=17D99DDC0CD5B8444B2D53E719971888
+PT=EC677E86A8D2A5935D33D6471A58A781
+CT=F31066D48884BC9B37F218FCF385344B
+
+I=160
+KEY=E4C9FB08845104DF7CDF4B1BEA122CC3
+PT=F31066D48884BC9B37F218FCF385344B
+CT=51CFEA4E482A7B7BCF4D31DA5CED4370
+
+I=161
+KEY=B5061146CC7B7FA4B3927AC1B6FF6FB3
+PT=51CFEA4E482A7B7BCF4D31DA5CED4370
+CT=89F3CD1590669A16F8460991BFD3CF5C
+
+I=162
+KEY=3CF5DC535C1DE5B24BD47350092CA0EF
+PT=89F3CD1590669A16F8460991BFD3CF5C
+CT=9930DA8E5DBC1F6C87B0B41BD386E2E0
+
+I=163
+KEY=A5C506DD01A1FADECC64C74BDAAA420F
+PT=9930DA8E5DBC1F6C87B0B41BD386E2E0
+CT=41A8CB583E5B9D2BA7CDA3763B6529C0
+
+I=164
+KEY=E46DCD853FFA67F56BA9643DE1CF6BCF
+PT=41A8CB583E5B9D2BA7CDA3763B6529C0
+CT=53479DCFB0C69624B42B9C272B0A1A85
+
+I=165
+KEY=B72A504A8F3CF1D1DF82F81ACAC5714A
+PT=53479DCFB0C69624B42B9C272B0A1A85
+CT=E72F27AE86E913EF55309120358BAD35
+
+I=166
+KEY=500577E409D5E23E8AB2693AFF4EDC7F
+PT=E72F27AE86E913EF55309120358BAD35
+CT=9B1EF901BACC70819DBC627C7CDC8CD9
+
+I=167
+KEY=CB1B8EE5B31992BF170E0B46839250A6
+PT=9B1EF901BACC70819DBC627C7CDC8CD9
+CT=9546C7B789345E4C32EE84BCE8E78C7E
+
+I=168
+KEY=5E5D49523A2DCCF325E08FFA6B75DCD8
+PT=9546C7B789345E4C32EE84BCE8E78C7E
+CT=33700B93E03CE8202BAC7E64E3255108
+
+I=169
+KEY=6D2D42C1DA1124D30E4CF19E88508DD0
+PT=33700B93E03CE8202BAC7E64E3255108
+CT=44246615BCA5C0A8DCB7E63729398F0A
+
+I=170
+KEY=290924D466B4E47BD2FB17A9A16902DA
+PT=44246615BCA5C0A8DCB7E63729398F0A
+CT=3215FC55FEE5A30BFA11F8EBBC912652
+
+I=171
+KEY=1B1CD8819851477028EAEF421DF82488
+PT=3215FC55FEE5A30BFA11F8EBBC912652
+CT=796C9136407BC4F484B253DAEB206912
+
+I=172
+KEY=627049B7D82A8384AC58BC98F6D84D9A
+PT=796C9136407BC4F484B253DAEB206912
+CT=B18977B404F0671C10AA979389408CCA
+
+I=173
+KEY=D3F93E03DCDAE498BCF22B0B7F98C150
+PT=B18977B404F0671C10AA979389408CCA
+CT=B2592621EE947D4ED9AD4295E0675F93
+
+I=174
+KEY=61A01822324E99D6655F699E9FFF9EC3
+PT=B2592621EE947D4ED9AD4295E0675F93
+CT=62D3B7E28765DA8F83EBE19C97293C0A
+
+I=175
+KEY=0373AFC0B52B4359E6B4880208D6A2C9
+PT=62D3B7E28765DA8F83EBE19C97293C0A
+CT=F417D650D6B7631542CFF8F95FC81C9B
+
+I=176
+KEY=F7647990639C204CA47B70FB571EBE52
+PT=F417D650D6B7631542CFF8F95FC81C9B
+CT=700A5DE153D6B438FFF7BA902DEC32FF
+
+I=177
+KEY=876E2471304A94745B8CCA6B7AF28CAD
+PT=700A5DE153D6B438FFF7BA902DEC32FF
+CT=67DC08A48F1EC7E32121B8693BB23621
+
+I=178
+KEY=E0B22CD5BF5453977AAD72024140BA8C
+PT=67DC08A48F1EC7E32121B8693BB23621
+CT=90038BB156A7F7992E260E9CBFAC0D82
+
+I=179
+KEY=70B1A764E9F3A40E548B7C9EFEECB70E
+PT=90038BB156A7F7992E260E9CBFAC0D82
+CT=C6BB1407C2D037BF238BEC772BA95352
+
+I=180
+KEY=B60AB3632B2393B1770090E9D545E45C
+PT=C6BB1407C2D037BF238BEC772BA95352
+CT=8C3D249574FF74F84053977219D69F5E
+
+I=181
+KEY=3A3797F65FDCE7493753079BCC937B02
+PT=8C3D249574FF74F84053977219D69F5E
+CT=131F7FC5A1528AD5DCB167AFAA8BFD47
+
+I=182
+KEY=2928E833FE8E6D9CEBE2603466188645
+PT=131F7FC5A1528AD5DCB167AFAA8BFD47
+CT=6E68AE6FDF2C10B42B85486D3EFBCEB9
+
+I=183
+KEY=4740465C21A27D28C067285958E348FC
+PT=6E68AE6FDF2C10B42B85486D3EFBCEB9
+CT=26808ABFA3967D742D64A26CADF8DD70
+
+I=184
+KEY=61C0CCE38234005CED038A35F51B958C
+PT=26808ABFA3967D742D64A26CADF8DD70
+CT=8BBCBA5E4C219D000A2F6B701CDA09C3
+
+I=185
+KEY=EA7C76BDCE159D5CE72CE145E9C19C4F
+PT=8BBCBA5E4C219D000A2F6B701CDA09C3
+CT=5D707BB328BEFF51C8C1D984C1608AA0
+
+I=186
+KEY=B70C0D0EE6AB620D2FED38C128A116EF
+PT=5D707BB328BEFF51C8C1D984C1608AA0
+CT=8D0A485482B914FC282C2DA9F7147D0C
+
+I=187
+KEY=3A06455A641276F107C11568DFB56BE3
+PT=8D0A485482B914FC282C2DA9F7147D0C
+CT=C5678BC12445627CBAA94177F070F736
+
+I=188
+KEY=FF61CE9B4057148DBD68541F2FC59CD5
+PT=C5678BC12445627CBAA94177F070F736
+CT=EB9B50846E92C20CD6EDBA7A3A260684
+
+I=189
+KEY=14FA9E1F2EC5D6816B85EE6515E39A51
+PT=EB9B50846E92C20CD6EDBA7A3A260684
+CT=E2178B471A3F72A271013C4CBE41FA1C
+
+I=190
+KEY=F6ED155834FAA4231A84D229ABA2604D
+PT=E2178B471A3F72A271013C4CBE41FA1C
+CT=C10C8084A17D90339E5ED8C638B902A4
+
+I=191
+KEY=37E195DC9587341084DA0AEF931B62E9
+PT=C10C8084A17D90339E5ED8C638B902A4
+CT=03C839CCF269548279F30A1F45C30556
+
+I=192
+KEY=3429AC1067EE6092FD2900F0D6D867BF
+PT=03C839CCF269548279F30A1F45C30556
+CT=1C5DC5C94B5C7E332D4122A0A4FACD96
+
+I=193
+KEY=287469D92CB21EA1D06822507222AA29
+PT=1C5DC5C94B5C7E332D4122A0A4FACD96
+CT=E7292B7D15E9311F242FACFAFC0B0B81
+
+I=194
+KEY=CF5D42A4395B2FBEF4478EAA8E29A1A8
+PT=E7292B7D15E9311F242FACFAFC0B0B81
+CT=EA6DF86EEE09613104DB81B97B949AEC
+
+I=195
+KEY=2530BACAD7524E8FF09C0F13F5BD3B44
+PT=EA6DF86EEE09613104DB81B97B949AEC
+CT=8FBCCDEBA43FE3FFDE4C3C279BDD4A27
+
+I=196
+KEY=AA8C7721736DAD702ED033346E607163
+PT=8FBCCDEBA43FE3FFDE4C3C279BDD4A27
+CT=985971BE962C63B0F50D1004963E9BED
+
+I=197
+KEY=32D5069FE541CEC0DBDD2330F85EEA8E
+PT=985971BE962C63B0F50D1004963E9BED
+CT=F2CC0FF4B6D2F88766F1B8BE370FE463
+
+I=198
+KEY=C019096B53933647BD2C9B8ECF510EED
+PT=F2CC0FF4B6D2F88766F1B8BE370FE463
+CT=FE33F823B7B97FC017B35B6E22415D3E
+
+I=199
+KEY=3E2AF148E42A4987AA9FC0E0ED1053D3
+PT=FE33F823B7B97FC017B35B6E22415D3E
+CT=465D804A6053EC2580B59F0CD645C060
+
+I=200
+KEY=787771028479A5A22A2A5FEC3B5593B3
+PT=465D804A6053EC2580B59F0CD645C060
+CT=DE05AD28693E3D471B8F39BAD1803C0E
+
+I=201
+KEY=A672DC2AED4798E531A56656EAD5AFBD
+PT=DE05AD28693E3D471B8F39BAD1803C0E
+CT=61EB397D55A2FC3D78974C8A10200AC6
+
+I=202
+KEY=C799E557B8E564D849322ADCFAF5A57B
+PT=61EB397D55A2FC3D78974C8A10200AC6
+CT=BD95D742D81AD795AA4E10FB41F54294
+
+I=203
+KEY=7A0C321560FFB34DE37C3A27BB00E7EF
+PT=BD95D742D81AD795AA4E10FB41F54294
+CT=F43A1E8C6E057E68414D23DA6932DE2C
+
+I=204
+KEY=8E362C990EFACD25A23119FDD23239C3
+PT=F43A1E8C6E057E68414D23DA6932DE2C
+CT=8EBB208032245988E851148B34B92F0E
+
+I=205
+KEY=008D0C193CDE94AD4A600D76E68B16CD
+PT=8EBB208032245988E851148B34B92F0E
+CT=2F18B4B14A360E06C50C89A4E6FE6C17
+
+I=206
+KEY=2F95B8A876E89AAB8F6C84D200757ADA
+PT=2F18B4B14A360E06C50C89A4E6FE6C17
+CT=681E131FA7EA5EBE10B59D3F16009582
+
+I=207
+KEY=478BABB7D102C4159FD919ED1675EF58
+PT=681E131FA7EA5EBE10B59D3F16009582
+CT=376FA31CC9D18E756E96715D61403C5D
+
+I=208
+KEY=70E408AB18D34A60F14F68B07735D305
+PT=376FA31CC9D18E756E96715D61403C5D
+CT=519E87E4A1AC61C376842F028D1BD75F
+
+I=209
+KEY=217A8F4FB97F2BA387CB47B2FA2E045A
+PT=519E87E4A1AC61C376842F028D1BD75F
+CT=BFAED9E9964967342808C6C332E02204
+
+I=210
+KEY=9ED456A62F364C97AFC38171C8CE265E
+PT=BFAED9E9964967342808C6C332E02204
+CT=5A9F55C61A03D6A3196FFD6879CBCA02
+
+I=211
+KEY=C44B036035359A34B6AC7C19B105EC5C
+PT=5A9F55C61A03D6A3196FFD6879CBCA02
+CT=0FD872478223CDE765A62036EDD6F42F
+
+I=212
+KEY=CB937127B71657D3D30A5C2F5CD31873
+PT=0FD872478223CDE765A62036EDD6F42F
+CT=965ED2AF7D26CDA8A8B7E7B2F1ADA768
+
+I=213
+KEY=5DCDA388CA309A7B7BBDBB9DAD7EBF1B
+PT=965ED2AF7D26CDA8A8B7E7B2F1ADA768
+CT=05599B8D42D92457605A69200C6DC0AA
+
+I=214
+KEY=5894380588E9BE2C1BE7D2BDA1137FB1
+PT=05599B8D42D92457605A69200C6DC0AA
+CT=3436A49EE590788F625A6FB44BF72FA3
+
+I=215
+KEY=6CA29C9B6D79C6A379BDBD09EAE45012
+PT=3436A49EE590788F625A6FB44BF72FA3
+CT=DB181195EFF35E307167BADA138A837A
+
+I=216
+KEY=B7BA8D0E828A989308DA07D3F96ED368
+PT=DB181195EFF35E307167BADA138A837A
+CT=45E06B534233447E3CB696C1DD179477
+
+I=217
+KEY=F25AE65DC0B9DCED346C91122479471F
+PT=45E06B534233447E3CB696C1DD179477
+CT=D2EDC4E2B4EDD671D984E8AA5BABAAD7
+
+I=218
+KEY=20B722BF74540A9CEDE879B87FD2EDC8
+PT=D2EDC4E2B4EDD671D984E8AA5BABAAD7
+CT=DB92F4E9F2DD6A61E20A79CFC82CD061
+
+I=219
+KEY=FB25D656868960FD0FE20077B7FE3DA9
+PT=DB92F4E9F2DD6A61E20A79CFC82CD061
+CT=79383629DF124FD94A1C36BECB711747
+
+I=220
+KEY=821DE07F599B2F2445FE36C97C8F2AEE
+PT=79383629DF124FD94A1C36BECB711747
+CT=3F3F592FB3DB51CF08B70E6F2174AB43
+
+I=221
+KEY=BD22B950EA407EEB4D4938A65DFB81AD
+PT=3F3F592FB3DB51CF08B70E6F2174AB43
+CT=D34FDA2917E9697118502CB7A6CAE07C
+
+I=222
+KEY=6E6D6379FDA9179A55191411FB3161D1
+PT=D34FDA2917E9697118502CB7A6CAE07C
+CT=24D2C38E5C52A404DBE0D8BB6DA44AEE
+
+I=223
+KEY=4ABFA0F7A1FBB39E8EF9CCAA96952B3F
+PT=24D2C38E5C52A404DBE0D8BB6DA44AEE
+CT=2ED6A7503B3547C04E0B7B709218CD4A
+
+I=224
+KEY=646907A79ACEF45EC0F2B7DA048DE675
+PT=2ED6A7503B3547C04E0B7B709218CD4A
+CT=4F11BE7A8B5D1A04AB82F60000BC7B50
+
+I=225
+KEY=2B78B9DD1193EE5A6B7041DA04319D25
+PT=4F11BE7A8B5D1A04AB82F60000BC7B50
+CT=B98B51B76B262CB9ED157567A05770AF
+
+I=226
+KEY=92F3E86A7AB5C2E3866534BDA466ED8A
+PT=B98B51B76B262CB9ED157567A05770AF
+CT=D6CA5483F89D5AA01DBCFEBE30C26F5E
+
+I=227
+KEY=4439BCE9822898439BD9CA0394A482D4
+PT=D6CA5483F89D5AA01DBCFEBE30C26F5E
+CT=7706922EBA53937E287084C8FDFEB33F
+
+I=228
+KEY=333F2EC7387B0B3DB3A94ECB695A31EB
+PT=7706922EBA53937E287084C8FDFEB33F
+CT=0F2DA3B8BFCB1046CA94EC9322320BF9
+
+I=229
+KEY=3C128D7F87B01B7B793DA2584B683A12
+PT=0F2DA3B8BFCB1046CA94EC9322320BF9
+CT=29CAD5CDC5A2834A5D533335FED2EA81
+
+I=230
+KEY=15D858B242129831246E916DB5BAD093
+PT=29CAD5CDC5A2834A5D533335FED2EA81
+CT=A48A2D319552BF02E84E4662E75884DB
+
+I=231
+KEY=B1527583D7402733CC20D70F52E25448
+PT=A48A2D319552BF02E84E4662E75884DB
+CT=334560ECD22BB9F660BC4FFAB13891C9
+
+I=232
+KEY=8217156F056B9EC5AC9C98F5E3DAC581
+PT=334560ECD22BB9F660BC4FFAB13891C9
+CT=DAAEB8436205DFB6688D9DE0A21A6B9D
+
+I=233
+KEY=58B9AD2C676E4173C411051541C0AE1C
+PT=DAAEB8436205DFB6688D9DE0A21A6B9D
+CT=E38798615C2158872704125A7CFC6540
+
+I=234
+KEY=BB3E354D3B4F19F4E315174F3D3CCB5C
+PT=E38798615C2158872704125A7CFC6540
+CT=BACB9EA5499A093F6595E8D1D5CF7E50
+
+I=235
+KEY=01F5ABE872D510CB8680FF9EE8F3B50C
+PT=BACB9EA5499A093F6595E8D1D5CF7E50
+CT=813B0D4AC4C2B8371A1A132927D24F62
+
+I=236
+KEY=80CEA6A2B617A8FC9C9AECB7CF21FA6E
+PT=813B0D4AC4C2B8371A1A132927D24F62
+CT=D1AD1AE650B377520EE19370D9E968A9
+
+I=237
+KEY=5163BC44E6A4DFAE927B7FC716C892C7
+PT=D1AD1AE650B377520EE19370D9E968A9
+CT=3CEC25102A51A5A4C26E7391590D54ED
+
+I=238
+KEY=6D8F9954CCF57A0A50150C564FC5C62A
+PT=3CEC25102A51A5A4C26E7391590D54ED
+CT=505FD54017E89E9FAA6376E399F2FF09
+
+I=239
+KEY=3DD04C14DB1DE495FA767AB5D6373923
+PT=505FD54017E89E9FAA6376E399F2FF09
+CT=1B45550B4E3AB908A2CC72FFFB38701A
+
+I=240
+KEY=2695191F95275D9D58BA084A2D0F4939
+PT=1B45550B4E3AB908A2CC72FFFB38701A
+CT=E2469D9D2F91E3AA88DC7970C94E7237
+
+I=241
+KEY=C4D38482BAB6BE37D066713AE4413B0E
+PT=E2469D9D2F91E3AA88DC7970C94E7237
+CT=9352C72F2B5093D1AF52BA959963F59B
+
+I=242
+KEY=578143AD91E62DE67F34CBAF7D22CE95
+PT=9352C72F2B5093D1AF52BA959963F59B
+CT=F26DE32F035B270BA42075574056564E
+
+I=243
+KEY=A5ECA08292BD0AEDDB14BEF83D7498DB
+PT=F26DE32F035B270BA42075574056564E
+CT=6AC08B3D91FC31A34B3A81F7C300587E
+
+I=244
+KEY=CF2C2BBF03413B4E902E3F0FFE74C0A5
+PT=6AC08B3D91FC31A34B3A81F7C300587E
+CT=E5E6455304C3B5E2349E2372D6E4B0B8
+
+I=245
+KEY=2ACA6EEC07828EACA4B01C7D2890701D
+PT=E5E6455304C3B5E2349E2372D6E4B0B8
+CT=90524F27C63CCA1E4CA9674381786C30
+
+I=246
+KEY=BA9821CBC1BE44B2E8197B3EA9E81C2D
+PT=90524F27C63CCA1E4CA9674381786C30
+CT=44625D68290415039E2C6C05B4954896
+
+I=247
+KEY=FEFA7CA3E8BA51B17635173B1D7D54BB
+PT=44625D68290415039E2C6C05B4954896
+CT=EC401B0D3780FDB4A3952706B07F6CEF
+
+I=248
+KEY=12BA67AEDF3AAC05D5A0303DAD023854
+PT=EC401B0D3780FDB4A3952706B07F6CEF
+CT=DCEDC88021F6FD1C61C08DAABF0E73BA
+
+I=249
+KEY=CE57AF2EFECC5119B460BD97120C4BEE
+PT=DCEDC88021F6FD1C61C08DAABF0E73BA
+CT=C15C85D8161B97DD61EB8B514CDCFFD5
+
+I=250
+KEY=0F0B2AF6E8D7C6C4D58B36C65ED0B43B
+PT=C15C85D8161B97DD61EB8B514CDCFFD5
+CT=B68B65E041C84433DEA4D9E15E9F98AB
+
+I=251
+KEY=B9804F16A91F82F70B2FEF27004F2C90
+PT=B68B65E041C84433DEA4D9E15E9F98AB
+CT=8122505A5B6F8D985A8D9D7E9E2FF4F3
+
+I=252
+KEY=38A21F4CF2700F6F51A272599E60D863
+PT=8122505A5B6F8D985A8D9D7E9E2FF4F3
+CT=8F72F8FFA71D24C900D2BBE8784B9C48
+
+I=253
+KEY=B7D0E7B3556D2BA65170C9B1E62B442B
+PT=8F72F8FFA71D24C900D2BBE8784B9C48
+CT=1D541D794774264680CF3689365CD845
+
+I=254
+KEY=AA84FACA12190DE0D1BFFF38D0779C6E
+PT=1D541D794774264680CF3689365CD845
+CT=CBAE9336C5C1F038176B5123CC205BF7
+
+I=255
+KEY=612A69FCD7D8FDD8C6D4AE1B1C57C799
+PT=CBAE9336C5C1F038176B5123CC205BF7
+CT=C4CE2DC1BAE3028392BD8A005A360F56
+
+I=256
+KEY=A5E4443D6D3BFF5B5469241B4661C8CF
+PT=C4CE2DC1BAE3028392BD8A005A360F56
+CT=549B7075DE975B759A6DAE7D761CDC01
+
+I=257
+KEY=F17F3448B3ACA42ECE048A66307D14CE
+PT=549B7075DE975B759A6DAE7D761CDC01
+CT=2338FFEEE2A391B2DAFD1EBB0ECF19E3
+
+I=258
+KEY=D247CBA6510F359C14F994DD3EB20D2D
+PT=2338FFEEE2A391B2DAFD1EBB0ECF19E3
+CT=B27705C512C6849DE6012A490F834F36
+
+I=259
+KEY=6030CE6343C9B101F2F8BE943131421B
+PT=B27705C512C6849DE6012A490F834F36
+CT=33A239E0426921192F8C89C6FBCDD23C
+
+I=260
+KEY=5392F78301A09018DD743752CAFC9027
+PT=33A239E0426921192F8C89C6FBCDD23C
+CT=90CCBE46338C7E9FB25409F82BF81234
+
+I=261
+KEY=C35E49C5322CEE876F203EAAE1048213
+PT=90CCBE46338C7E9FB25409F82BF81234
+CT=873D1CAF1F2C2A56BEE419FE8A01489F
+
+I=262
+KEY=4463556A2D00C4D1D1C427546B05CA8C
+PT=873D1CAF1F2C2A56BEE419FE8A01489F
+CT=1E9ED35EB85ADD9AB88B6D85299FD8E7
+
+I=263
+KEY=5AFD8634955A194B694F4AD1429A126B
+PT=1E9ED35EB85ADD9AB88B6D85299FD8E7
+CT=36871F8BD629B27EEDE04E086FC539C4
+
+I=264
+KEY=6C7A99BF4373AB3584AF04D92D5F2BAF
+PT=36871F8BD629B27EEDE04E086FC539C4
+CT=10D10983F98D799235E8142BD67C1FD2
+
+I=265
+KEY=7CAB903CBAFED2A7B14710F2FB23347D
+PT=10D10983F98D799235E8142BD67C1FD2
+CT=193CEDEEE0410DE79F1B2FC077B14199
+
+I=266
+KEY=65977DD25ABFDF402E5C3F328C9275E4
+PT=193CEDEEE0410DE79F1B2FC077B14199
+CT=1EC99AD6EEF155B6B5F61452D2E73A7D
+
+I=267
+KEY=7B5EE704B44E8AF69BAA2B605E754F99
+PT=1EC99AD6EEF155B6B5F61452D2E73A7D
+CT=92DA7D1858210C87B32C6FEA1CC6A0E6
+
+I=268
+KEY=E9849A1CEC6F86712886448A42B3EF7F
+PT=92DA7D1858210C87B32C6FEA1CC6A0E6
+CT=A06C4ACCA35DE95CFAD365349969271D
+
+I=269
+KEY=49E8D0D04F326F2DD25521BEDBDAC862
+PT=A06C4ACCA35DE95CFAD365349969271D
+CT=4B892CB63A35A3DED0F43BA4309CBB2E
+
+I=270
+KEY=0261FC667507CCF302A11A1AEB46734C
+PT=4B892CB63A35A3DED0F43BA4309CBB2E
+CT=E05F73446706A68A5099088279B58064
+
+I=271
+KEY=E23E8F2212016A795238129892F3F328
+PT=E05F73446706A68A5099088279B58064
+CT=542D8314299AF433EC549EBFFCF2B3D9
+
+I=272
+KEY=B6130C363B9B9E4ABE6C8C276E0140F1
+PT=542D8314299AF433EC549EBFFCF2B3D9
+CT=4935A91590E8A70D9F75489F6D5B70E7
+
+I=273
+KEY=FF26A523AB7339472119C4B8035A3016
+PT=4935A91590E8A70D9F75489F6D5B70E7
+CT=C3A4940C6EC7D0E2F11C3CF60AB2C31D
+
+I=274
+KEY=3C82312FC5B4E9A5D005F84E09E8F30B
+PT=C3A4940C6EC7D0E2F11C3CF60AB2C31D
+CT=F109AC488D917B5FC28BA28C9720A46F
+
+I=275
+KEY=CD8B9D67482592FA128E5AC29EC85764
+PT=F109AC488D917B5FC28BA28C9720A46F
+CT=65234934641FA21D8C3A3804D09208F3
+
+I=276
+KEY=A8A8D4532C3A30E79EB462C64E5A5F97
+PT=65234934641FA21D8C3A3804D09208F3
+CT=DE015A71CB9C9A3B11C2C9B744B6B5ED
+
+I=277
+KEY=76A98E22E7A6AADC8F76AB710AECEA7A
+PT=DE015A71CB9C9A3B11C2C9B744B6B5ED
+CT=973D0C12D7826B45CC7824EF09D82BAB
+
+I=278
+KEY=E19482303024C199430E8F9E0334C1D1
+PT=973D0C12D7826B45CC7824EF09D82BAB
+CT=EBD2D23B9D08F63385A0D21FF76FAC33
+
+I=279
+KEY=0A46500BAD2C37AAC6AE5D81F45B6DE2
+PT=EBD2D23B9D08F63385A0D21FF76FAC33
+CT=A7A460A555E4C4E53457AE00FC0D9BA8
+
+I=280
+KEY=ADE230AEF8C8F34FF2F9F3810856F64A
+PT=A7A460A555E4C4E53457AE00FC0D9BA8
+CT=56F0329103B5238E03C781E2AB0E7A2D
+
+I=281
+KEY=FB12023FFB7DD0C1F13E7263A3588C67
+PT=56F0329103B5238E03C781E2AB0E7A2D
+CT=0D5710472E980CF439109BAC3EAB19A8
+
+I=282
+KEY=F6451278D5E5DC35C82EE9CF9DF395CF
+PT=0D5710472E980CF439109BAC3EAB19A8
+CT=063CB786AD88ECADC4EAC8FE39A84286
+
+I=283
+KEY=F079A5FE786D30980CC42131A45BD749
+PT=063CB786AD88ECADC4EAC8FE39A84286
+CT=825BD1E57F0E16D744C2A69233C8654B
+
+I=284
+KEY=7222741B0763264F480687A39793B202
+PT=825BD1E57F0E16D744C2A69233C8654B
+CT=8EA54322F26DC051F831A5CBBD07A73C
+
+I=285
+KEY=FC873739F50EE61EB03722682A94153E
+PT=8EA54322F26DC051F831A5CBBD07A73C
+CT=803F3194726F4D5C5BD80D12D1284F0A
+
+I=286
+KEY=7CB806AD8761AB42EBEF2F7AFBBC5A34
+PT=803F3194726F4D5C5BD80D12D1284F0A
+CT=5A1D90E682989AB1A84F01422CE69F82
+
+I=287
+KEY=26A5964B05F931F343A02E38D75AC5B6
+PT=5A1D90E682989AB1A84F01422CE69F82
+CT=3F5AFCD41950EEFBC3D7CEF744F0C060
+
+I=288
+KEY=19FF6A9F1CA9DF088077E0CF93AA05D6
+PT=3F5AFCD41950EEFBC3D7CEF744F0C060
+CT=2EE3691BD58D7645DA91CD4943F10157
+
+I=289
+KEY=371C0384C924A94D5AE62D86D05B0481
+PT=2EE3691BD58D7645DA91CD4943F10157
+CT=BEF4B188364E87A9E49855CC68C02A50
+
+I=290
+KEY=89E8B20CFF6A2EE4BE7E784AB89B2ED1
+PT=BEF4B188364E87A9E49855CC68C02A50
+CT=2263387A7A52AB73704774D07EA5AA69
+
+I=291
+KEY=AB8B8A7685388597CE390C9AC63E84B8
+PT=2263387A7A52AB73704774D07EA5AA69
+CT=84E68DA3E9D999016D0B734DAE8C128B
+
+I=292
+KEY=2F6D07D56CE11C96A3327FD768B29633
+PT=84E68DA3E9D999016D0B734DAE8C128B
+CT=978F5F49D7BA1189F16FC0635231DF5F
+
+I=293
+KEY=B8E2589CBB5B0D1F525DBFB43A83496C
+PT=978F5F49D7BA1189F16FC0635231DF5F
+CT=FE59B2F2BDE0AB5E1700A1771EDF8663
+
+I=294
+KEY=46BBEA6E06BBA641455D1EC3245CCF0F
+PT=FE59B2F2BDE0AB5E1700A1771EDF8663
+CT=A94B982DC50C338E25ABFB4113F904A8
+
+I=295
+KEY=EFF07243C3B795CF60F6E58237A5CBA7
+PT=A94B982DC50C338E25ABFB4113F904A8
+CT=79A5BB282D8247192AC9F8A3DB431EA1
+
+I=296
+KEY=9655C96BEE35D2D64A3F1D21ECE6D506
+PT=79A5BB282D8247192AC9F8A3DB431EA1
+CT=FC339DA0D4593CD79D407CD6F1E1E7ED
+
+I=297
+KEY=6A6654CB3A6CEE01D77F61F71D0732EB
+PT=FC339DA0D4593CD79D407CD6F1E1E7ED
+CT=08EAB51652B85C6E9BC07B718E57E144
+
+I=298
+KEY=628CE1DD68D4B26F4CBF1A869350D3AF
+PT=08EAB51652B85C6E9BC07B718E57E144
+CT=9EA63934609F947AAA926443D0D5BEFA
+
+I=299
+KEY=FC2AD8E9084B2615E62D7EC543856D55
+PT=9EA63934609F947AAA926443D0D5BEFA
+CT=7FE121C45E158FF1F527BAFDDBEAE223
+
+I=300
+KEY=83CBF92D565EA9E4130AC438986F8F76
+PT=7FE121C45E158FF1F527BAFDDBEAE223
+CT=B1B70D5AD08BE5DCB8126D8700F25969
+
+I=301
+KEY=327CF47786D54C38AB18A9BF989DD61F
+PT=B1B70D5AD08BE5DCB8126D8700F25969
+CT=389812FA2D4A6419380A2AC8961CCDA6
+
+I=302
+KEY=0AE4E68DAB9F2821931283770E811BB9
+PT=389812FA2D4A6419380A2AC8961CCDA6
+CT=CEF20323EE53A2BA576F4DF86A7AC078
+
+I=303
+KEY=C416E5AE45CC8A9BC47DCE8F64FBDBC1
+PT=CEF20323EE53A2BA576F4DF86A7AC078
+CT=A65611BF1901C940B883D746F1694278
+
+I=304
+KEY=6240F4115CCD43DB7CFE19C9959299B9
+PT=A65611BF1901C940B883D746F1694278
+CT=7E43C2A99D11C656351B96CECD400E75
+
+I=305
+KEY=1C0336B8C1DC858D49E58F0758D297CC
+PT=7E43C2A99D11C656351B96CECD400E75
+CT=7DE74D06851AD329C60DD1934C34CBE4
+
+I=306
+KEY=61E47BBE44C656A48FE85E9414E65C28
+PT=7DE74D06851AD329C60DD1934C34CBE4
+CT=A99B66FE5825C895DCC6BE718AB8BE34
+
+I=307
+KEY=C87F1D401CE39E31532EE0E59E5EE21C
+PT=A99B66FE5825C895DCC6BE718AB8BE34
+CT=4752E30DDA44BA393EF197270C111AB7
+
+I=308
+KEY=8F2DFE4DC6A724086DDF77C2924FF8AB
+PT=4752E30DDA44BA393EF197270C111AB7
+CT=5A3FC324D12AC30FE5BBE87FC4B655F0
+
+I=309
+KEY=D5123D69178DE70788649FBD56F9AD5B
+PT=5A3FC324D12AC30FE5BBE87FC4B655F0
+CT=79061587E9D9FEEF52F753AE9BCDC4B1
+
+I=310
+KEY=AC1428EEFE5419E8DA93CC13CD3469EA
+PT=79061587E9D9FEEF52F753AE9BCDC4B1
+CT=86C32E69874EAA0D103581199AFA813A
+
+I=311
+KEY=2AD70687791AB3E5CAA64D0A57CEE8D0
+PT=86C32E69874EAA0D103581199AFA813A
+CT=82A924A5928570E29D18DE200F8558DD
+
+I=312
+KEY=A87E2222EB9FC30757BE932A584BB00D
+PT=82A924A5928570E29D18DE200F8558DD
+CT=2D3E0ECCC1FEA93736BD205A5217D830
+
+I=313
+KEY=85402CEE2A616A306103B3700A5C683D
+PT=2D3E0ECCC1FEA93736BD205A5217D830
+CT=52FA0FCF771191A4A4C4E48C7B11DC1F
+
+I=314
+KEY=D7BA23215D70FB94C5C757FC714DB422
+PT=52FA0FCF771191A4A4C4E48C7B11DC1F
+CT=C2A47519AACA187B97C884D20ED1D825
+
+I=315
+KEY=151E5638F7BAE3EF520FD32E7F9C6C07
+PT=C2A47519AACA187B97C884D20ED1D825
+CT=66F1D0799F3C473978C189F745695293
+
+I=316
+KEY=73EF86416886A4D62ACE5AD93AF53E94
+PT=66F1D0799F3C473978C189F745695293
+CT=803361A1428EAC3E134B0726E5CF0754
+
+I=317
+KEY=F3DCE7E02A0808E839855DFFDF3A39C0
+PT=803361A1428EAC3E134B0726E5CF0754
+CT=2CC85CEDEE03D7AB279D766D3F2BADF4
+
+I=318
+KEY=DF14BB0DC40BDF431E182B92E0119434
+PT=2CC85CEDEE03D7AB279D766D3F2BADF4
+CT=706626C1CE6731DD4DBA263C4D7EAB67
+
+I=319
+KEY=AF729DCC0A6CEE9E53A20DAEAD6F3F53
+PT=706626C1CE6731DD4DBA263C4D7EAB67
+CT=BD7A59659E3774B85465C91740017628
+
+I=320
+KEY=1208C4A9945B9A2607C7C4B9ED6E497B
+PT=BD7A59659E3774B85465C91740017628
+CT=F1778330059467556D08223682EC32AA
+
+I=321
+KEY=E37F479991CFFD736ACFE68F6F827BD1
+PT=F1778330059467556D08223682EC32AA
+CT=7B3C6979DCEE500E3FBB2CF4E17B0A3B
+
+I=322
+KEY=98432EE04D21AD7D5574CA7B8EF971EA
+PT=7B3C6979DCEE500E3FBB2CF4E17B0A3B
+CT=AFEBC6E81B90C3D82ECE26D788AB2412
+
+I=323
+KEY=37A8E80856B16EA57BBAECAC065255F8
+PT=AFEBC6E81B90C3D82ECE26D788AB2412
+CT=E4087042AB32B9C43128AADACB4F7FA6
+
+I=324
+KEY=D3A0984AFD83D7614A924676CD1D2A5E
+PT=E4087042AB32B9C43128AADACB4F7FA6
+CT=07E1230BC456A3DCE7DF8A4EF7265BC8
+
+I=325
+KEY=D441BB4139D574BDAD4DCC383A3B7196
+PT=07E1230BC456A3DCE7DF8A4EF7265BC8
+CT=88F0C30172B9A0EA8CD657CE6847AC94
+
+I=326
+KEY=5CB178404B6CD457219B9BF6527CDD02
+PT=88F0C30172B9A0EA8CD657CE6847AC94
+CT=710FE26B2DAB5A12D147D6446732B272
+
+I=327
+KEY=2DBE9A2B66C78E45F0DC4DB2354E6F70
+PT=710FE26B2DAB5A12D147D6446732B272
+CT=9C30630A9ADF9B4EBF099452AB75D14A
+
+I=328
+KEY=B18EF921FC18150B4FD5D9E09E3BBE3A
+PT=9C30630A9ADF9B4EBF099452AB75D14A
+CT=77526DA4D9AE9FD4347AAC10EA4728AA
+
+I=329
+KEY=C6DC948525B68ADF7BAF75F0747C9690
+PT=77526DA4D9AE9FD4347AAC10EA4728AA
+CT=A9EDBD1A190BC67AC91D27BB7F5A1BD1
+
+I=330
+KEY=6F31299F3CBD4CA5B2B2524B0B268D41
+PT=A9EDBD1A190BC67AC91D27BB7F5A1BD1
+CT=B8700A2BAEABCB0C67251C26F82ACEF7
+
+I=331
+KEY=D74123B4921687A9D5974E6DF30C43B6
+PT=B8700A2BAEABCB0C67251C26F82ACEF7
+CT=FF5F30BA14A8C49276B040B00864BE29
+
+I=332
+KEY=281E130E86BE433BA3270EDDFB68FD9F
+PT=FF5F30BA14A8C49276B040B00864BE29
+CT=B448E87BE1E1A41FF94353F6018929C8
+
+I=333
+KEY=9C56FB75675FE7245A645D2BFAE1D457
+PT=B448E87BE1E1A41FF94353F6018929C8
+CT=9F59D422CB9265C17732E0B16DEF352A
+
+I=334
+KEY=030F2F57ACCD82E52D56BD9A970EE17D
+PT=9F59D422CB9265C17732E0B16DEF352A
+CT=06FD7DB54E62FAC3C511F4DE5C1E93B9
+
+I=335
+KEY=05F252E2E2AF7826E8474944CB1072C4
+PT=06FD7DB54E62FAC3C511F4DE5C1E93B9
+CT=0DDA3E4AD600F8D3EA6B06AE465DF3BC
+
+I=336
+KEY=08286CA834AF80F5022C4FEA8D4D8178
+PT=0DDA3E4AD600F8D3EA6B06AE465DF3BC
+CT=17305FA95D26FB72995165DA8A07FCDF
+
+I=337
+KEY=1F18330169897B879B7D2A30074A7DA7
+PT=17305FA95D26FB72995165DA8A07FCDF
+CT=12B56FEBEE2773A2258FC6E0F9115728
+
+I=338
+KEY=0DAD5CEA87AE0825BEF2ECD0FE5B2A8F
+PT=12B56FEBEE2773A2258FC6E0F9115728
+CT=36440D1A561E8F77B89DF6EA3D8EC7F5
+
+I=339
+KEY=3BE951F0D1B08752066F1A3AC3D5ED7A
+PT=36440D1A561E8F77B89DF6EA3D8EC7F5
+CT=752C4D620413C0F4A313CF37EB34CFDD
+
+I=340
+KEY=4EC51C92D5A347A6A57CD50D28E122A7
+PT=752C4D620413C0F4A313CF37EB34CFDD
+CT=B2A282D0B6A9EB8B7B7C962675AEC843
+
+I=341
+KEY=FC679E42630AAC2DDE00432B5D4FEAE4
+PT=B2A282D0B6A9EB8B7B7C962675AEC843
+CT=D0C3D785B5507C1460DDC44B123ED5FE
+
+I=342
+KEY=2CA449C7D65AD039BEDD87604F713F1A
+PT=D0C3D785B5507C1460DDC44B123ED5FE
+CT=4DAE52B77F8001CBAB8D1949E73DD578
+
+I=343
+KEY=610A1B70A9DAD1F215509E29A84CEA62
+PT=4DAE52B77F8001CBAB8D1949E73DD578
+CT=29AA82197E8158D88FFFE5BEAFC0C967
+
+I=344
+KEY=48A09969D75B892A9AAF7B97078C2305
+PT=29AA82197E8158D88FFFE5BEAFC0C967
+CT=58C665AA97945F7D3AA23BE8B8DDA20D
+
+I=345
+KEY=1066FCC340CFD657A00D407FBF518108
+PT=58C665AA97945F7D3AA23BE8B8DDA20D
+CT=5A104A7093DB3308EB4009829B5E26B1
+
+I=346
+KEY=4A76B6B3D314E55F4B4D49FD240FA7B9
+PT=5A104A7093DB3308EB4009829B5E26B1
+CT=8C8EA0BEE4640F6BB6D906A7A6EA3810
+
+I=347
+KEY=C6F8160D3770EA34FD944F5A82E59FA9
+PT=8C8EA0BEE4640F6BB6D906A7A6EA3810
+CT=1517ED0B6D4EC3B85479AB28DF48BFDB
+
+I=348
+KEY=D3EFFB065A3E298CA9EDE4725DAD2072
+PT=1517ED0B6D4EC3B85479AB28DF48BFDB
+CT=9546CCBB8094E65E464C38E0809552E3
+
+I=349
+KEY=46A937BDDAAACFD2EFA1DC92DD387291
+PT=9546CCBB8094E65E464C38E0809552E3
+CT=7D5AD8DEDB92F80D2B28C3458843AE84
+
+I=350
+KEY=3BF3EF63013837DFC4891FD7557BDC15
+PT=7D5AD8DEDB92F80D2B28C3458843AE84
+CT=E62676E27ED61D0FD7DFE170E0938361
+
+I=351
+KEY=DDD599817FEE2AD01356FEA7B5E85F74
+PT=E62676E27ED61D0FD7DFE170E0938361
+CT=DA9865198B9463681C66FB96C2C1DAA5
+
+I=352
+KEY=074DFC98F47A49B80F300531772985D1
+PT=DA9865198B9463681C66FB96C2C1DAA5
+CT=62CD9DAA9487F34AF168E6E20A0684CF
+
+I=353
+KEY=6580613260FDBAF2FE58E3D37D2F011E
+PT=62CD9DAA9487F34AF168E6E20A0684CF
+CT=10BA978FDABA586691946145BE246D3C
+
+I=354
+KEY=753AF6BDBA47E2946FCC8296C30B6C22
+PT=10BA978FDABA586691946145BE246D3C
+CT=13443CF524213B08776D7F5169B79C0F
+
+I=355
+KEY=667ECA489E66D99C18A1FDC7AABCF02D
+PT=13443CF524213B08776D7F5169B79C0F
+CT=6507336876ED4F6DB3E35D6CF5A89A2B
+
+I=356
+KEY=0379F920E88B96F1AB42A0AB5F146A06
+PT=6507336876ED4F6DB3E35D6CF5A89A2B
+CT=B84902B5CBBC6DB8111CA45BC5F99991
+
+I=357
+KEY=BB30FB952337FB49BA5E04F09AEDF397
+PT=B84902B5CBBC6DB8111CA45BC5F99991
+CT=20973140A999B8AD9982B9B706F7C32E
+
+I=358
+KEY=9BA7CAD58AAE43E423DCBD479C1A30B9
+PT=20973140A999B8AD9982B9B706F7C32E
+CT=EE7FF1177C5E080AA03854A2A819565E
+
+I=359
+KEY=75D83BC2F6F04BEE83E4E9E5340366E7
+PT=EE7FF1177C5E080AA03854A2A819565E
+CT=7A4F74EC2181269AC17D0E48A4DA2A88
+
+I=360
+KEY=0F974F2ED7716D744299E7AD90D94C6F
+PT=7A4F74EC2181269AC17D0E48A4DA2A88
+CT=5B7A7751F0FD91E203A14CE518838DD7
+
+I=361
+KEY=54ED387F278CFC964138AB48885AC1B8
+PT=5B7A7751F0FD91E203A14CE518838DD7
+CT=71319FDDBACB038354A37A41F1910F94
+
+I=362
+KEY=25DCA7A29D47FF15159BD10979CBCE2C
+PT=71319FDDBACB038354A37A41F1910F94
+CT=81AC58FD503FC3AA78199168AE2C9085
+
+I=363
+KEY=A470FF5FCD783CBF6D824061D7E75EA9
+PT=81AC58FD503FC3AA78199168AE2C9085
+CT=1F668F512038142C1155B950B0B040EC
+
+I=364
+KEY=BB16700EED4028937CD7F93167571E45
+PT=1F668F512038142C1155B950B0B040EC
+CT=6B27D7791E9B14A5AC3D9582DBDBD929
+
+I=365
+KEY=D031A777F3DB3C36D0EA6CB3BC8CC76C
+PT=6B27D7791E9B14A5AC3D9582DBDBD929
+CT=9B7151FDC4E135EE93DAB2D9EB74D59C
+
+I=366
+KEY=4B40F68A373A09D84330DE6A57F812F0
+PT=9B7151FDC4E135EE93DAB2D9EB74D59C
+CT=1F199945BCFA624B1AD3DCBBD95291B2
+
+I=367
+KEY=54596FCF8BC06B9359E302D18EAA8342
+PT=1F199945BCFA624B1AD3DCBBD95291B2
+CT=E2C82FA8FE98F26283A6E0B75D0A58C6
+
+I=368
+KEY=B6914067755899F1DA45E266D3A0DB84
+PT=E2C82FA8FE98F26283A6E0B75D0A58C6
+CT=5A240FFB99C3594C273B51CACF01B28B
+
+I=369
+KEY=ECB54F9CEC9BC0BDFD7EB3AC1CA1690F
+PT=5A240FFB99C3594C273B51CACF01B28B
+CT=D01847391534848FB102CA85C97749B1
+
+I=370
+KEY=3CAD08A5F9AF44324C7C7929D5D620BE
+PT=D01847391534848FB102CA85C97749B1
+CT=DC5CF60EBDF4A8DDDDF997E7ACA67515
+
+I=371
+KEY=E0F1FEAB445BECEF9185EECE797055AB
+PT=DC5CF60EBDF4A8DDDDF997E7ACA67515
+CT=749E3815FE305B307D9F4DB6A7E4658C
+
+I=372
+KEY=946FC6BEBA6BB7DFEC1AA378DE943027
+PT=749E3815FE305B307D9F4DB6A7E4658C
+CT=8152C1E676A4FC8B0CD093FEB4B51615
+
+I=373
+KEY=153D0758CCCF4B54E0CA30866A212632
+PT=8152C1E676A4FC8B0CD093FEB4B51615
+CT=0847044668710F6E5C93DD248AC921BA
+
+I=374
+KEY=1D7A031EA4BE443ABC59EDA2E0E80788
+PT=0847044668710F6E5C93DD248AC921BA
+CT=1D6C3EFB413A59AB40F34CEFBFF25C17
+
+I=375
+KEY=00163DE5E5841D91FCAAA14D5F1A5B9F
+PT=1D6C3EFB413A59AB40F34CEFBFF25C17
+CT=5D7C206A79D61868FFE7AA28044996D3
+
+I=376
+KEY=5D6A1D8F9C5205F9034D0B655B53CD4C
+PT=5D7C206A79D61868FFE7AA28044996D3
+CT=78B4DE3B84D5D1010245CA3077A41BAC
+
+I=377
+KEY=25DEC3B41887D4F80108C1552CF7D6E0
+PT=78B4DE3B84D5D1010245CA3077A41BAC
+CT=9E003AACEDECDBB077BDE832465F40C7
+
+I=378
+KEY=BBDEF918F56B0F4876B529676AA89627
+PT=9E003AACEDECDBB077BDE832465F40C7
+CT=EEFF9E6C73E6DC5432AA446385AA1499
+
+I=379
+KEY=55216774868DD31C441F6D04EF0282BE
+PT=EEFF9E6C73E6DC5432AA446385AA1499
+CT=03252A19E37D9F040C56E4D712982798
+
+I=380
+KEY=56044D6D65F04C18484989D3FD9AA526
+PT=03252A19E37D9F040C56E4D712982798
+CT=CF59A752BA0E14BE23AFD09437B39C65
+
+I=381
+KEY=995DEA3FDFFE58A66BE65947CA293943
+PT=CF59A752BA0E14BE23AFD09437B39C65
+CT=8B08FB7974A77167DFB234F57C8DFFE1
+
+I=382
+KEY=12551146AB5929C1B4546DB2B6A4C6A2
+PT=8B08FB7974A77167DFB234F57C8DFFE1
+CT=DD2A93C1106CFDAE4A1684EE02C82FE2
+
+I=383
+KEY=CF7F8287BB35D46FFE42E95CB46CE940
+PT=DD2A93C1106CFDAE4A1684EE02C82FE2
+CT=38696128584F60636354E9F802590391
+
+I=384
+KEY=F716E3AFE37AB40C9D1600A4B635EAD1
+PT=38696128584F60636354E9F802590391
+CT=7E552E3AD28729F642D590E3C289D598
+
+I=385
+KEY=8943CD9531FD9DFADFC3904774BC3F49
+PT=7E552E3AD28729F642D590E3C289D598
+CT=17A40392AA00D7B5A6E9F59007E60C22
+
+I=386
+KEY=9EE7CE079BFD4A4F792A65D7735A336B
+PT=17A40392AA00D7B5A6E9F59007E60C22
+CT=A048D6755C2AD24DD8833DDCEB145BA6
+
+I=387
+KEY=3EAF1872C7D79802A1A9580B984E68CD
+PT=A048D6755C2AD24DD8833DDCEB145BA6
+CT=2F1CCE852396986EC4B2852E5F684CD2
+
+I=388
+KEY=11B3D6F7E441006C651BDD25C726241F
+PT=2F1CCE852396986EC4B2852E5F684CD2
+CT=2C28BD1E98DA63B95C0C81202BBCFE39
+
+I=389
+KEY=3D9B6BE97C9B63D539175C05EC9ADA26
+PT=2C28BD1E98DA63B95C0C81202BBCFE39
+CT=6AE097A8E685B58BA2309B59D6A9EB2B
+
+I=390
+KEY=577BFC419A1ED65E9B27C75C3A33310D
+PT=6AE097A8E685B58BA2309B59D6A9EB2B
+CT=6EFC01751753999843A9BB6749097E0C
+
+I=391
+KEY=3987FD348D4D4FC6D88E7C3B733A4F01
+PT=6EFC01751753999843A9BB6749097E0C
+CT=6B6B75F78016052E4F89C73EA826D2F2
+
+I=392
+KEY=52EC88C30D5B4AE89707BB05DB1C9DF3
+PT=6B6B75F78016052E4F89C73EA826D2F2
+CT=1E9890E8F0AABCBFB8C4EDAEA0F563EF
+
+I=393
+KEY=4C74182BFDF1F6572FC356AB7BE9FE1C
+PT=1E9890E8F0AABCBFB8C4EDAEA0F563EF
+CT=143ED9FE6FD7DFB822C31DE8A3E868A9
+
+I=394
+KEY=584AC1D5922629EF0D004B43D80196B5
+PT=143ED9FE6FD7DFB822C31DE8A3E868A9
+CT=9C2834AA5C95F2874DC6B267C0469E14
+
+I=395
+KEY=C462F57FCEB3DB6840C6F924184708A1
+PT=9C2834AA5C95F2874DC6B267C0469E14
+CT=0720377F673352693EE2EF76D4FCFB0F
+
+I=396
+KEY=C342C200A98089017E241652CCBBF3AE
+PT=0720377F673352693EE2EF76D4FCFB0F
+CT=E83ED303F4B0ABF675C7BBC470B924FE
+
+I=397
+KEY=2B7C11035D3022F70BE3AD96BC02D750
+PT=E83ED303F4B0ABF675C7BBC470B924FE
+CT=D87ADD68CBCAEA46DFFF99AE3723BC94
+
+I=398
+KEY=F306CC6B96FAC8B1D41C34388B216BC4
+PT=D87ADD68CBCAEA46DFFF99AE3723BC94
+CT=2C290AE7C65B6E5BBAA32DE577DBA343
+
+I=399
+KEY=DF2FC68C50A1A6EA6EBF19DDFCFAC887
+PT=2C290AE7C65B6E5BBAA32DE577DBA343
+CT=A04377ABE259B0D0B5BA2D40A501971B
+
+=========================
+
+KEYSIZE=192
+
+I=0
+KEY=000000000000000000000000000000000000000000000000
+PT=00000000000000000000000000000000
+CT=F3F6752AE8D7831138F041560631B114
+
+I=1
+KEY=AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114
+PT=F3F6752AE8D7831138F041560631B114
+CT=77BA00ED5412DFF27C8ED91F3C376172
+
+I=2
+KEY=A92B07597B52873C844C75C7BCC55CE3447E98493A06D066
+PT=77BA00ED5412DFF27C8ED91F3C376172
+CT=2D92DE893574463412BD7D121A94952F
+
+I=3
+KEY=5FD632DA76165EDBA9DEAB4E89B11AD756C3E55B20924549
+PT=2D92DE893574463412BD7D121A94952F
+CT=96650F835912F5E748422727802C6CE1
+
+I=4
+KEY=984A4BEC5D3474103FBBA4CDD0A3EF301E81C27CA0BE29A8
+PT=96650F835912F5E748422727802C6CE1
+CT=5FCCD4B5F125ADC5B85A56DB32283732
+
+I=5
+KEY=6B7EDEEAC755885F60777078218642F5A6DB94A792961E9A
+PT=5FCCD4B5F125ADC5B85A56DB32283732
+CT=EA5B1DAE2E4F9FD254A2CC28E128EB9B
+
+I=6
+KEY=CA5585D8C9727F208A2C6DD60FC9DD27F279588F73BEF501
+PT=EA5B1DAE2E4F9FD254A2CC28E128EB9B
+CT=BB87C0FF5DB4B2A593B93398407F823A
+
+I=7
+KEY=BADA7C0D4A0CDD4631ABAD29527D6F8261C06B1733C1773B
+PT=BB87C0FF5DB4B2A593B93398407F823A
+CT=D5AF7D56281F86E3E079BE6B9465DBB4
+
+I=8
+KEY=FF98AB620A203FFCE404D07F7A62E96181B9D57CA7A4AC8F
+PT=D5AF7D56281F86E3E079BE6B9465DBB4
+CT=511331CCA62B067CAC47475800EE33CD
+
+I=9
+KEY=1186A7F46656EA07B517E1B3DC49EF1D2DFE9224A74A9F42
+PT=511331CCA62B067CAC47475800EE33CD
+CT=64ACDC3579D7871644DD585C582AF3A2
+
+I=10
+KEY=313ADFF9712EABE4D1BB3D86A59E680B6923CA78FF606CE0
+PT=64ACDC3579D7871644DD585C582AF3A2
+CT=EA3C45FB8A6E548DAB14BAE07966246C
+
+I=11
+KEY=DDABAC02BE6C40493B87787D2FF03C86C23770988606488C
+PT=EA3C45FB8A6E548DAB14BAE07966246C
+CT=6BC276C465C9ADBE900049A5B58D2DCB
+
+I=12
+KEY=9A9F7E267C2BFCD150450EB94A3991385237393D338B6547
+PT=6BC276C465C9ADBE900049A5B58D2DCB
+CT=E2F0FFA8D6DF327CA0FB80A325B21931
+
+I=13
+KEY=80246B9FB6224226B2B5F1119CE6A344F2CCB99E16397C76
+PT=E2F0FFA8D6DF327CA0FB80A325B21931
+CT=ACEE4C9B8A00A7760DD9CD2F6C6DFA8C
+
+I=14
+KEY=60CDC3E8265B71E81E5BBD8A16E60432FF1574B17A5486FA
+PT=ACEE4C9B8A00A7760DD9CD2F6C6DFA8C
+CT=9579E43690FD2800FED810F7442D366B
+
+I=15
+KEY=9DEC584DB87D63F48B2259BC861B2C3201CD64463E79B091
+PT=9579E43690FD2800FED810F7442D366B
+CT=72D4D064851A050D415FC94E3FBB6A1C
+
+I=16
+KEY=BBC1ED636907611EF9F689D80301293F4092AD0801C2DA8D
+PT=72D4D064851A050D415FC94E3FBB6A1C
+CT=0CCC3B9B35CE3584D7B78C14905BEE55
+
+I=17
+KEY=AE398529289F7994F53AB24336CF1CBB9725211C919934D8
+PT=0CCC3B9B35CE3584D7B78C14905BEE55
+CT=66B6A61BF7BCC6392B8FEC12152E5363
+
+I=18
+KEY=4617E60BD8AF29D5938C1458C173DA82BCAACD0E84B767BB
+PT=66B6A61BF7BCC6392B8FEC12152E5363
+CT=6C2247EA3BC566A84A30BF0B30AB4EEC
+
+I=19
+KEY=6B762D1391AA17CBFFAE53B2FAB6BC2AF69A7205B41C2957
+PT=6C2247EA3BC566A84A30BF0B30AB4EEC
+CT=C16FBCDFAE34E839BA449D697452550D
+
+I=20
+KEY=374499A8C09A60DA3EC1EF6D548254134CDEEF6CC04E7C5A
+PT=C16FBCDFAE34E839BA449D697452550D
+CT=C8B704B4AFE68AF5C91A810F2873F13F
+
+I=21
+KEY=09DCC638DD59F37CF676EBD9FB64DEE685C46E63E83D8D65
+PT=C8B704B4AFE68AF5C91A810F2873F13F
+CT=FC9C31036B26234ED1CBA46E0BE944EE
+
+I=22
+KEY=CE2CEB8869D7EC160AEADADA9042FDA8540FCA0DE3D4C98B
+PT=FC9C31036B26234ED1CBA46E0BE944EE
+CT=DCF13203AD179CD008779F189EBC78F0
+
+I=23
+KEY=505FBECF6B0B083CD61BE8D93D5561785C7855157D68B17B
+PT=DCF13203AD179CD008779F189EBC78F0
+CT=24AEB937E259D44D352FF39C1A8A79E0
+
+I=24
+KEY=1D1649FDB7484DD2F2B551EEDF0CB5356957A68967E2C89B
+PT=24AEB937E259D44D352FF39C1A8A79E0
+CT=19016D033872CB7694A712A84DBC43F2
+
+I=25
+KEY=9BE41771C0F74BDEEBB43CEDE77E7E43FDF0B4212A5E8B69
+PT=19016D033872CB7694A712A84DBC43F2
+CT=0536107FEA26AB6A4FE2667EF7FCF16A
+
+I=26
+KEY=FF3619AED9A1F724EE822C920D58D529B212D25FDDA27A03
+PT=0536107FEA26AB6A4FE2667EF7FCF16A
+CT=5D35213390FCA53AD422DC2ED4BF674D
+
+I=27
+KEY=59D2F5AF4BB6F28BB3B70DA19DA4701366300E71091D1D4E
+PT=5D35213390FCA53AD422DC2ED4BF674D
+CT=04A6F9B1AE64AD03659C4E375A690852
+
+I=28
+KEY=C8384D35CAF0074EB711F41033C0DD1003AC40465374151C
+PT=04A6F9B1AE64AD03659C4E375A690852
+CT=18AB347EFC2F8F93655E16732BB509DE
+
+I=29
+KEY=910CE58F963B684EAFBAC06ECFEF528366F2563578C11CC2
+PT=18AB347EFC2F8F93655E16732BB509DE
+CT=F6037C06C71793BD14A4FC89A05D918F
+
+I=30
+KEY=5D1EF94FBA1E098459B9BC6808F8C13E7256AABCD89C8D4D
+PT=F6037C06C71793BD14A4FC89A05D918F
+CT=75094DD9B2FDDAC96B49CAB676057288
+
+I=31
+KEY=61FDA8DA3EF8949C2CB0F1B1BA051BF7191F600AAE99FFC5
+PT=75094DD9B2FDDAC96B49CAB676057288
+CT=346F9F9E70C05B53DCDAF736FE59749D
+
+I=32
+KEY=5C383CCC2DCAE66A18DF6E2FCAC540A4C5C5973C50C08B58
+PT=346F9F9E70C05B53DCDAF736FE59749D
+CT=1DB82CC8EF5B736AAEFD1F1B9CE5B67D
+
+I=33
+KEY=1EC7FDBB8AE4FF05056742E7259E33CE6B388827CC253D25
+PT=1DB82CC8EF5B736AAEFD1F1B9CE5B67D
+CT=31B5E80D946AE577268973AF865151EB
+
+I=34
+KEY=FFE21FDAB07E755034D2AAEAB1F4D6B94DB1FB884A746CCE
+PT=31B5E80D946AE577268973AF865151EB
+CT=9FD63EB3EC6A15FC149A4F058EDA7080
+
+I=35
+KEY=7EC4053A63B2353BAB0494595D9EC345592BB48DC4AE1C4E
+PT=9FD63EB3EC6A15FC149A4F058EDA7080
+CT=41730A9E9D197435AC36902C57B16588
+
+I=36
+KEY=FB6D2FAFD47FE8D1EA779EC7C087B770F51D24A1931F79C6
+PT=41730A9E9D197435AC36902C57B16588
+CT=08AD282171F0772F85C0A43E8BACEC74
+
+I=37
+KEY=9531B1BBE0863D44E2DAB6E6B177C05F70DD809F18B395B2
+PT=08AD282171F0772F85C0A43E8BACEC74
+CT=8561E508FA237E4170CECD3A8352CFA4
+
+I=38
+KEY=0AB0CF2D1CA2957A67BB53EE4B54BE1E00134DA59BE15A16
+PT=8561E508FA237E4170CECD3A8352CFA4
+CT=4470EFA3C3172EBF64A064F59AE364A9
+
+I=39
+KEY=291FD5C38E400CFA23CBBC4D884390A164B3295001023EBF
+PT=4470EFA3C3172EBF64A064F59AE364A9
+CT=FCC5636DFE9E45CB7761DD14A1CF4773
+
+I=40
+KEY=114E4DEF0447E1D5DF0EDF2076DDD56A13D2F444A0CD79CC
+PT=FCC5636DFE9E45CB7761DD14A1CF4773
+CT=2130BA8736D4933678C3B536AEDBC500
+
+I=41
+KEY=0C19F74860652278FE3E65A74009465C6B1141720E16BCCC
+PT=2130BA8736D4933678C3B536AEDBC500
+CT=1725EECBA8F9A542E9956168390C82C2
+
+I=42
+KEY=EF9E7E57576D8A3EE91B8B6CE8F0E31E8284201A371A3E0E
+PT=1725EECBA8F9A542E9956168390C82C2
+CT=60912D3EEDC962D68A29AED73DDAA24D
+
+I=43
+KEY=CE6464925302B9F4898AA652053981C808AD8ECD0AC09C43
+PT=60912D3EEDC962D68A29AED73DDAA24D
+CT=43A8B490BBC75DC8D2D2F060C8672E9E
+
+I=44
+KEY=8657F15C75C74469CA2212C2BEFEDC00DA7F7EADC2A7B2DD
+PT=43A8B490BBC75DC8D2D2F060C8672E9E
+CT=67D856AF692A4BA7DEC7C8C14A37BD50
+
+I=45
+KEY=2D566517DCC2D4EBADFA446DD7D497A704B8B66C88900F8D
+PT=67D856AF692A4BA7DEC7C8C14A37BD50
+CT=293C5A05F31E863C6CA26DB8018751CA
+
+I=46
+KEY=826DFA3FD5229B9B84C61E6824CA119B681ADBD489175E47
+PT=293C5A05F31E863C6CA26DB8018751CA
+CT=9421BF2E7727F49C252D644B952C76C4
+
+I=47
+KEY=A5A13E0D1C01D7CF10E7A14653EDE5074D37BF9F1C3B2883
+PT=9421BF2E7727F49C252D644B952C76C4
+CT=CEE8F6FCF7CAF1C5EA9F746C10BD405B
+
+I=48
+KEY=923D8EE015266BA8DE0F57BAA42714C2A7A8CBF30C8668D8
+PT=CEE8F6FCF7CAF1C5EA9F746C10BD405B
+CT=403220B81E6E0837ACCEDA5ACB3730BE
+
+I=49
+KEY=B41FA03C1181401A9E3D7702BA491CF50B6611A9C7B15866
+PT=403220B81E6E0837ACCEDA5ACB3730BE
+CT=8C5D05679F78F853CF83CB8E5BBEBA44
+
+I=50
+KEY=00B6D7172075472F126072652531E4A6C4E5DA279C0FE222
+PT=8C5D05679F78F853CF83CB8E5BBEBA44
+CT=6F9C74C0BB40608AAD1A1202FCAF62EB
+
+I=51
+KEY=BEB1F890B29E8EFE7DFC06A59E71842C69FFC82560A080C9
+PT=6F9C74C0BB40608AAD1A1202FCAF62EB
+CT=B812DB4E295951BB04B1636A9CE91DDB
+
+I=52
+KEY=9455ABC4AC495686C5EEDDEBB728D5976D4EAB4FFC499D12
+PT=B812DB4E295951BB04B1636A9CE91DDB
+CT=B164574EAECAD5A06FFB4F3E6C607D61
+
+I=53
+KEY=1E9CCB2A3541F810748A8AA519E2003702B5E4719029E073
+PT=B164574EAECAD5A06FFB4F3E6C607D61
+CT=1433D23C1500EDBA0EFFD03D96E18F20
+
+I=54
+KEY=F4817B9409F1F1D160B958990CE2ED8D0C4A344C06C86F53
+PT=1433D23C1500EDBA0EFFD03D96E18F20
+CT=B81C889B6FAF5DA800AEBA561992853B
+
+I=55
+KEY=49F7CD1535080039D8A5D002634DB0250CE48E1A1F5AEA68
+PT=B81C889B6FAF5DA800AEBA561992853B
+CT=5B558B7C5916CF14FA5BC9266CFE875F
+
+I=56
+KEY=FCD5479474EA721783F05B7E3A5B7F31F6BF473C73A46D37
+PT=5B558B7C5916CF14FA5BC9266CFE875F
+CT=49BE310D74A9980E9A78B0A8BB3BA1AB
+
+I=57
+KEY=6A68208CC7D6782ECA4E6A734EF2E73F6CC7F794C89FCC9C
+PT=49BE310D74A9980E9A78B0A8BB3BA1AB
+CT=7BD5BABAD7F1EEAA56E17BF9B6678DC8
+
+I=58
+KEY=38DE1A69C03EF9C1B19BD0C9990309953A268C6D7EF84154
+PT=7BD5BABAD7F1EEAA56E17BF9B6678DC8
+CT=62448A767C344E7E7CDB02112F475EFE
+
+I=59
+KEY=02634EC657B436A8D3DF5ABFE53747EB46FD8E7C51BF1FAA
+PT=62448A767C344E7E7CDB02112F475EFE
+CT=F490A20D8B5C53E34C4CF5B7B72A4591
+
+I=60
+KEY=DCDAAB8CBD526850274FF8B26E6B14080AB17BCBE6955A3B
+PT=F490A20D8B5C53E34C4CF5B7B72A4591
+CT=ACFFD7CD5C01B183AB92DBB62DC088F6
+
+I=61
+KEY=51EB6B7172C22A248BB02F7F326AA58BA123A07DCB55D2CD
+PT=ACFFD7CD5C01B183AB92DBB62DC088F6
+CT=0BEDDFA8E7A1AC84E3E164A59D599BAB
+
+I=62
+KEY=4796B5FA7B22626B805DF0D7D5CB090F42C2C4D8560C4966
+PT=0BEDDFA8E7A1AC84E3E164A59D599BAB
+CT=9CC82E2B6B96254345C1FDBAD667275E
+
+I=63
+KEY=D8E112F9657BD2BF1C95DEFCBE5D2C4C07033962806B6E38
+PT=9CC82E2B6B96254345C1FDBAD667275E
+CT=75926F4D3503411CD3C059DA4FFABD62
+
+I=64
+KEY=A19B892107C4F8F86907B1B18B5E6D50D4C360B8CF91D35A
+PT=75926F4D3503411CD3C059DA4FFABD62
+CT=1073561CF6BA28EC57F4B7E5073D27FA
+
+I=65
+KEY=AEFE35F52D8D54A27974E7AD7DE445BC8337D75DC8ACF4A0
+PT=1073561CF6BA28EC57F4B7E5073D27FA
+CT=83E161BA51E6F3A4588C94F7A24BA81F
+
+I=66
+KEY=5E41A6382F88A350FA9586172C02B618DBBB43AA6AE75CBF
+PT=83E161BA51E6F3A4588C94F7A24BA81F
+CT=BD693B4C49378F17322D175932B87111
+
+I=67
+KEY=A2D760EE839234F147FCBD5B6535390FE99654F3585F2DAE
+PT=BD693B4C49378F17322D175932B87111
+CT=101A83CF8487BEDD2C93180BB5024EC9
+
+I=68
+KEY=0F463C72AF8E4B5357E63E94E1B287D2C5054CF8ED5D6367
+PT=101A83CF8487BEDD2C93180BB5024EC9
+CT=757949BE62D3328D09E2F45DF2AD095A
+
+I=69
+KEY=C3C0A16686A5D66B229F772A8361B55FCCE7B8A51FF06A3D
+PT=757949BE62D3328D09E2F45DF2AD095A
+CT=63EBBF9E15BECEC1A0885BECB3D06BF8
+
+I=70
+KEY=3A0B55738CF3B3E94174C8B496DF7B9E6C6FE349AC2001C5
+PT=63EBBF9E15BECEC1A0885BECB3D06BF8
+CT=E176B5C7AFCE06E8ED0C63A4CF7E3034
+
+I=71
+KEY=450F848D964934DAA0027D7339117D76816380ED635E31F1
+PT=E176B5C7AFCE06E8ED0C63A4CF7E3034
+CT=97B91F0A898E5B3A77A0883140D477BC
+
+I=72
+KEY=F3AF781D6EA3529237BB6279B09F264CF6C308DC238A464D
+PT=97B91F0A898E5B3A77A0883140D477BC
+CT=346AD1C470309DFE6CB08DCC24E17470
+
+I=73
+KEY=4E43AB584BF1F8C603D1B3BDC0AFBBB29A738510076B323D
+PT=346AD1C470309DFE6CB08DCC24E17470
+CT=F8B462FB7D758B3AF2CDF7D9244B738F
+
+I=74
+KEY=5A1F023E8F0987B4FB65D146BDDA308868BE72C9232041B2
+PT=F8B462FB7D758B3AF2CDF7D9244B738F
+CT=B44D090FD0B7F762146FF6301C6DBF54
+
+I=75
+KEY=FFC4BB75031165DA4F28D8496D6DC7EA7CD184F93F4DFEE6
+PT=B44D090FD0B7F762146FF6301C6DBF54
+CT=15CB042313710F2CD1C3409B5F3AF419
+
+I=76
+KEY=8107240E1FB855765AE3DC6A7E1CC8C6AD12C46260770AFF
+PT=15CB042313710F2CD1C3409B5F3AF419
+CT=0AB01B03F415A58D52CF7A1E40856275
+
+I=77
+KEY=4493743ADE27D1D85053C7698A096D4BFFDDBE7C20F2688A
+PT=0AB01B03F415A58D52CF7A1E40856275
+CT=05BE037C28719B4C4EEBEA329FAC63D5
+
+I=78
+KEY=F582EC062155016255EDC415A278F607B136544EBF5E0B5F
+PT=05BE037C28719B4C4EEBEA329FAC63D5
+CT=74C3C4F42B3F575C6B8D5BAD9AF0191F
+
+I=79
+KEY=8FAF8EEAA5E2D76B212E00E18947A15BDABB0FE325AE1240
+PT=74C3C4F42B3F575C6B8D5BAD9AF0191F
+CT=92CB4A3DF34E6711FB56391F26D949AD
+
+I=80
+KEY=1CAD393CC06BC104B3E54ADC7A09C64A21ED36FC03775BED
+PT=92CB4A3DF34E6711FB56391F26D949AD
+CT=3754BB3D8C3D7370EDBA842CDF17D5C0
+
+I=81
+KEY=E3AB53BB36BDFBBB84B1F1E1F634B53ACC57B2D0DC608E2D
+PT=3754BB3D8C3D7370EDBA842CDF17D5C0
+CT=94EAC7FD54D228619791BCCBF9F633F4
+
+I=82
+KEY=480B1D923E853259105B361CA2E69D5B5BC60E1B2596BDD9
+PT=94EAC7FD54D228619791BCCBF9F633F4
+CT=CAB29222355968E9CF492D5BF08B0999
+
+I=83
+KEY=D8F6791107FB3D26DAE9A43E97BFF5B2948F2340D51DB440
+PT=CAB29222355968E9CF492D5BF08B0999
+CT=00837C78B88005288DB39452F1EB8F13
+
+I=84
+KEY=6521B6B771FE24B2DA6AD8462F3FF09A193CB71224F63B53
+PT=00837C78B88005288DB39452F1EB8F13
+CT=2082F77D48A63E223A79217CD4516854
+
+I=85
+KEY=9D9F3198682E2476FAE82F3B6799CEB82345966EF0A75307
+PT=2082F77D48A63E223A79217CD4516854
+CT=C5074D4B3F455346B078DAFBC1327AB6
+
+I=86
+KEY=61832291235DC7C33FEF627058DC9DFE933D4C95319529B1
+PT=C5074D4B3F455346B078DAFBC1327AB6
+CT=72EE56572A2B7CEC53FC4E4FC0293D63
+
+I=87
+KEY=5C2877854338D45D4D01342772F7E112C0C102DAF1BC14D2
+PT=72EE56572A2B7CEC53FC4E4FC0293D63
+CT=7350039161DF9E8E45B360E6139E4226
+
+I=88
+KEY=A8225CF65297BA953E5137B613287F9C8572623CE22256F4
+PT=7350039161DF9E8E45B360E6139E4226
+CT=4339288215BE1BB87E31AF8FB35DEDC1
+
+I=89
+KEY=51649B52A8458F4B7D681F3406966424FB43CDB3517FBB35
+PT=4339288215BE1BB87E31AF8FB35DEDC1
+CT=4D7AB61CC2C930CBB0DF43EEE92EBA1F
+
+I=90
+KEY=750E4E7E9183E2FF3012A928C45F54EF4B9C8E5DB851012A
+PT=4D7AB61CC2C930CBB0DF43EEE92EBA1F
+CT=1090FE663EA77DC2EC30E8F89E662918
+
+I=91
+KEY=B65FBDF702246E442082574EFAF8292DA7AC66A526372832
+PT=1090FE663EA77DC2EC30E8F89E662918
+CT=14307A2CC40BDFB0413DF10F961337CA
+
+I=92
+KEY=7BEC3480AA0A44FF34B22D623EF3F69DE69197AAB0241FF8
+PT=14307A2CC40BDFB0413DF10F961337CA
+CT=8F378E272D82DE8E63EC418912EF8642
+
+I=93
+KEY=63921E8700657D6ABB85A34513712813857DD623A2CB99BA
+PT=8F378E272D82DE8E63EC418912EF8642
+CT=3947DDC00E3C4D958E508DF58AB4982A
+
+I=94
+KEY=754B2E8355FABCAF82C27E851D4D65860B2D5BD6287F0190
+PT=3947DDC00E3C4D958E508DF58AB4982A
+CT=492DB375B3CC640DD8FEDBAF2C943535
+
+I=95
+KEY=E8F8C2450F8597B3CBEFCDF0AE81018BD3D3807904EB34A5
+PT=492DB375B3CC640DD8FEDBAF2C943535
+CT=D74BD4118D448B674935B80E4B1BFB93
+
+I=96
+KEY=34A2C5B010AE479A1CA419E123C58AEC9AE638774FF0CF36
+PT=D74BD4118D448B674935B80E4B1BFB93
+CT=E9742B41295BC3ED3AA66E80E8718665
+
+I=97
+KEY=0E11D08AA9EC81A4F5D032A00A9E4901A04056F7A7814953
+PT=E9742B41295BC3ED3AA66E80E8718665
+CT=5FB17BFE146B410F90EC922B1385D0E4
+
+I=98
+KEY=B15779E61FD27B02AA61495E1EF5080E30ACC4DCB40499B7
+PT=5FB17BFE146B410F90EC922B1385D0E4
+CT=1B0CCF643F19DDBC0E3ED0EEAE83ACC1
+
+I=99
+KEY=861B580225193DD5B16D863A21ECD5B23E9214321A873576
+PT=1B0CCF643F19DDBC0E3ED0EEAE83ACC1
+CT=B3A7D434E30DC0CDEE4D17BBC27B855E
+
+I=100
+KEY=B6DF2A8726C31D6E02CA520EC2E1157FD0DF0389D8FCB028
+PT=B3A7D434E30DC0CDEE4D17BBC27B855E
+CT=57DE2345D91E26A2AB7CA88AEA23A84F
+
+I=101
+KEY=6976D3780B5F01E25514714B1BFF33DD7BA3AB0332DF1867
+PT=57DE2345D91E26A2AB7CA88AEA23A84F
+CT=7B03541D239B569FEE7ABD8980F1BD05
+
+I=102
+KEY=734CAC477A2727542E1725563864654295D9168AB22EA562
+PT=7B03541D239B569FEE7ABD8980F1BD05
+CT=5CB7E72B2E6CFF8C18AEB026FE40C2FA
+
+I=103
+KEY=B59171BEBC7BFB8672A0C27D16089ACE8D77A6AC4C6E6798
+PT=5CB7E72B2E6CFF8C18AEB026FE40C2FA
+CT=50B9186306DA92FE785D6EB9223E43A9
+
+I=104
+KEY=E460BA8A2F82DBB72219DA1E10D20830F52AC8156E502431
+PT=50B9186306DA92FE785D6EB9223E43A9
+CT=B3D8CE8B04B99CF2F82571E1588C358B
+
+I=105
+KEY=CE7C790CD4B34C4791C11495146B94C20D0FB9F436DC11BA
+PT=B3D8CE8B04B99CF2F82571E1588C358B
+CT=9845F0A5681A40A6DC3D9BCA639FE786
+
+I=106
+KEY=699FE59B482743180984E4307C71D464D132223E5543F63C
+PT=9845F0A5681A40A6DC3D9BCA639FE786
+CT=C7EBF5CEAAD5652563A8550020EC7070
+
+I=107
+KEY=FEBE2836F5099F53CE6F11FED6A4B141B29A773E75AF864C
+PT=C7EBF5CEAAD5652563A8550020EC7070
+CT=DE94A376634FE9856A84E2EE6EED86E8
+
+I=108
+KEY=22BCFFB0740FC30510FBB288B5EB58C4D81E95D01B4200A4
+PT=DE94A376634FE9856A84E2EE6EED86E8
+CT=64B9917E23328A4FE1F8FDB8AE43E7F3
+
+I=109
+KEY=E8491AFDF41F0DFB744223F696D9D28B39E66868B501E757
+PT=64B9917E23328A4FE1F8FDB8AE43E7F3
+CT=2C59820184ABC99E82A7F51D4E3A86A8
+
+I=110
+KEY=3BE5F390D72ABE6A581BA1F712721B15BB419D75FB3B61FF
+PT=2C59820184ABC99E82A7F51D4E3A86A8
+CT=387ACD0BAD539773287C209A0876581F
+
+I=111
+KEY=B7388762F772C83560616CFCBF218C66933DBDEFF34D39E0
+PT=387ACD0BAD539773287C209A0876581F
+CT=F12D3E1F21AFB9CACAB541EFB7334438
+
+I=112
+KEY=FBD600191276FA5C914C52E39E8E35AC5988FC00447E7DD8
+PT=F12D3E1F21AFB9CACAB541EFB7334438
+CT=68D2FA1BB635D9D35E4BF440335CBD80
+
+I=113
+KEY=1E2B19106450AA2FF99EA8F828BBEC7F07C308407722C058
+PT=68D2FA1BB635D9D35E4BF440335CBD80
+CT=4532507D5E0227054CB36CBD3C489D53
+
+I=114
+KEY=C0B60F65BAD77DA4BCACF88576B9CB7A4B7064FD4B6A5D0B
+PT=4532507D5E0227054CB36CBD3C489D53
+CT=6DB8FD7DE7924B7E92CF27BC0AD11D16
+
+I=115
+KEY=451836B53318CC33D11405F8912B8004D9BF434141BB401D
+PT=6DB8FD7DE7924B7E92CF27BC0AD11D16
+CT=A3D5F6A8D4372B66F8D3DD9FF945DECA
+
+I=116
+KEY=0E57235F9B527C5172C1F350451CAB62216C9EDEB8FE9ED7
+PT=A3D5F6A8D4372B66F8D3DD9FF945DECA
+CT=BEDFF233AD31EEB9943EEBF52F66AABF
+
+I=117
+KEY=BB7E1C438E5F36A3CC1E0163E82D45DBB552752B97983468
+PT=BEDFF233AD31EEB9943EEBF52F66AABF
+CT=4531EDEC06570582755199A0C4745EA5
+
+I=118
+KEY=DE70EC87811AFD32892FEC8FEE7A4059C003EC8B53EC6ACD
+PT=4531EDEC06570582755199A0C4745EA5
+CT=F3189383C202A472CE238571D187F8EB
+
+I=119
+KEY=CA2AE67397E9238A7A377F0C2C78E42B0E2069FA826B9226
+PT=F3189383C202A472CE238571D187F8EB
+CT=B48952CBAC43D0114985A9035DFF0382
+
+I=120
+KEY=335EF040D622E95BCEBE2DC7803B343A47A5C0F9DF9491A4
+PT=B48952CBAC43D0114985A9035DFF0382
+CT=9B71302FDFBC47DF6276AB73D4D0D8B3
+
+I=121
+KEY=683CC10DFBC6C09C55CF1DE85F8773E525D36B8A0B444917
+PT=9B71302FDFBC47DF6276AB73D4D0D8B3
+CT=69EED4A0C5428005199DF12B338393E2
+
+I=122
+KEY=B86C9A2F1A978E123C21C9489AC5F3E03C4E9AA138C7DAF5
+PT=69EED4A0C5428005199DF12B338393E2
+CT=D0C2ACA653E6D7D80D32F445B0DD2347
+
+I=123
+KEY=EF7E3DCDF05FFA86ECE365EEC9232438317C6EE4881AF9B2
+PT=D0C2ACA653E6D7D80D32F445B0DD2347
+CT=F373D4DBD7ADAFEF582621EC8C7CD2A2
+
+I=124
+KEY=B8059C7A6BA2273E1F90B1351E8E8BD7695A4F0804662B10
+PT=F373D4DBD7ADAFEF582621EC8C7CD2A2
+CT=0AD37AFC8C929513F9BDB976E69C7CF3
+
+I=125
+KEY=F5C9ECCBB672D46F1543CBC9921C1EC490E7F67EE2FA57E3
+PT=0AD37AFC8C929513F9BDB976E69C7CF3
+CT=E80B118DFB34F11DB344B6AE34EDEBC8
+
+I=126
+KEY=AA67DC18543A7A88FD48DA446928EFD923A340D0D617BC2B
+PT=E80B118DFB34F11DB344B6AE34EDEBC8
+CT=628D5C42DDEBA9AE4983F51D339366B4
+
+I=127
+KEY=BF0C30A039C0FEE89FC58606B4C346776A20B5CDE584DA9F
+PT=628D5C42DDEBA9AE4983F51D339366B4
+CT=1BE2A5A8CCA8E065557F6982AF3E056F
+
+I=128
+KEY=A219F6B8E2FF1AA3842723AE786BA6123F5FDC4F4ABADFF0
+PT=1BE2A5A8CCA8E065557F6982AF3E056F
+CT=5E1187D78AEB34780F07905A84D2EBBA
+
+I=129
+KEY=851DDD078D4B7802DA36A479F280926A30584C15CE68344A
+PT=5E1187D78AEB34780F07905A84D2EBBA
+CT=31EE3AC2EC79D14EBCA71E760326CD74
+
+I=130
+KEY=E6741084FEDEEFFEEBD89EBB1EF943248CFF5263CD4EF93E
+PT=31EE3AC2EC79D14EBCA71E760326CD74
+CT=298E3A00F280BBF8364CF8D6D44CF54E
+
+I=131
+KEY=8A41136FE9DB1FB5C256A4BBEC79F8DCBAB3AAB519020C70
+PT=298E3A00F280BBF8364CF8D6D44CF54E
+CT=39B7A0416C1F9B19C7B99A1F6A70258C
+
+I=132
+KEY=E1F1B622EB8BC9B1FBE104FA806663C57D0A30AA737229FC
+PT=39B7A0416C1F9B19C7B99A1F6A70258C
+CT=B1655FA9AB2C4956E2C56F7A6C421BE5
+
+I=133
+KEY=0EE0B7E1AF7093694A845B532B4A2A939FCF5FD01F303219
+PT=B1655FA9AB2C4956E2C56F7A6C421BE5
+CT=1AD9CBB1A28F7A2A6CBC7EC98EF483FC
+
+I=134
+KEY=180A2BD07F77D34E505D90E289C550B9F373211991C4B1E5
+PT=1AD9CBB1A28F7A2A6CBC7EC98EF483FC
+CT=6363BE57D6D587EE3ABA9FE81F3D3A10
+
+I=135
+KEY=848B7408CAACF02E333E2EB55F10D757C9C9BEF18EF98BF5
+PT=6363BE57D6D587EE3ABA9FE81F3D3A10
+CT=05618580D7915AA7398EF4DB7D1F1DE3
+
+I=136
+KEY=E581D7B4F84F2860365FAB3588818DF0F0474A2AF3E69616
+PT=05618580D7915AA7398EF4DB7D1F1DE3
+CT=F8D0118087404FD729F96CA6551338AD
+
+I=137
+KEY=6C81D6873EFFF763CE8FBAB50FC1C227D9BE268CA6F5AEBB
+PT=F8D0118087404FD729F96CA6551338AD
+CT=784913B38D32A7395D73AF1378A0DC56
+
+I=138
+KEY=D971137D872F606EB6C6A90682F3651E84CD899FDE5572ED
+PT=784913B38D32A7395D73AF1378A0DC56
+CT=D07C418BD183457B6683AE99C457FC0B
+
+I=139
+KEY=196BBA79E35EEC7966BAE88D53702065E24E27061A028EE6
+PT=D07C418BD183457B6683AE99C457FC0B
+CT=5595D16DF7668779825BC135D1408013
+
+I=140
+KEY=6F140EC274635FA2332F39E0A416A71C6015E633CB420EF5
+PT=5595D16DF7668779825BC135D1408013
+CT=1AB9F5075E063403FEFD976044C89C95
+
+I=141
+KEY=926F3A2AA0BD8C952996CCE7FA10931F9EE871538F8A9260
+PT=1AB9F5075E063403FEFD976044C89C95
+CT=6DF413E53FCEDA296D7ABA796179D600
+
+I=142
+KEY=740F74BF0E0C38154462DF02C5DE4936F392CB2AEEF34460
+PT=6DF413E53FCEDA296D7ABA796179D600
+CT=0D0F499B0D51948A9CCBC4B6531A05F7
+
+I=143
+KEY=2500C9B63042B24B496D9699C88FDDBC6F590F9CBDE94197
+PT=0D0F499B0D51948A9CCBC4B6531A05F7
+CT=85833A1072B6A0ED932D4D89D53A785A
+
+I=144
+KEY=FCB377C07622271FCCEEAC89BA397D51FC74421568D339CD
+PT=85833A1072B6A0ED932D4D89D53A785A
+CT=545EDE1A4B737F1E51CBDAE311E91D5C
+
+I=145
+KEY=BB108ABE391C394E98B07293F14A024FADBF98F6793A2491
+PT=545EDE1A4B737F1E51CBDAE311E91D5C
+CT=DA8CC635CF1450685DDAAA5A56BC3BD9
+
+I=146
+KEY=34F8623EC93A6C2A423CB4A63E5E5227F06532AC2F861F48
+PT=DA8CC635CF1450685DDAAA5A56BC3BD9
+CT=FE73162BF90B52DEE7D0EA9D73F8444D
+
+I=147
+KEY=5E3CB25583365D5EBC4FA28DC75500F917B5D8315C7E5B05
+PT=FE73162BF90B52DEE7D0EA9D73F8444D
+CT=BC75D12F66C232E1979D0F6C3E1ED8F1
+
+I=148
+KEY=EABE655116470AE1003A73A2A19732188028D75D626083F4
+PT=BC75D12F66C232E1979D0F6C3E1ED8F1
+CT=661A3FA0530BF47C266D609FE01DAF48
+
+I=149
+KEY=97A1B8E97CF217C366204C02F29CC664A645B7C2827D2CBC
+PT=661A3FA0530BF47C266D609FE01DAF48
+CT=791144514CF8E4CC15BC6ADE3291F9CD
+
+I=150
+KEY=5189DC6F535B5A091F310853BE6422A8B3F9DD1CB0ECD571
+PT=791144514CF8E4CC15BC6ADE3291F9CD
+CT=4369FDB3626F399A6526C476373A52D4
+
+I=151
+KEY=21CD36EDB27428AB5C58F5E0DC0B1B32D6DF196A87D687A5
+PT=4369FDB3626F399A6526C476373A52D4
+CT=4C8869494C044703CFDD09F83B2208AA
+
+I=152
+KEY=85C08C7D4667AE3710D09CA9900F5C3119021092BCF48F0F
+PT=4C8869494C044703CFDD09F83B2208AA
+CT=06BC45BDB38A7028CB2D189E9E0C3046
+
+I=153
+KEY=807182BD7E1F29BE166CD91423852C19D22F080C22F8BF49
+PT=06BC45BDB38A7028CB2D189E9E0C3046
+CT=74AFD5F37F8F0712710585FB8DB22FF8
+
+I=154
+KEY=1AF15D0DE00CEF3F62C30CE75C0A2B0BA32A8DF7AF4A90B1
+PT=74AFD5F37F8F0712710585FB8DB22FF8
+CT=B1A4EE894A12794E0C1A286DDBC01CFD
+
+I=155
+KEY=E0732BA619DCF2F5D367E26E16185245AF30A59A748A8C4C
+PT=B1A4EE894A12794E0C1A286DDBC01CFD
+CT=0EA90279135DFFC7F58DB959F9E8BFE1
+
+I=156
+KEY=AE8779E669BFF77EDDCEE0170545AD825ABD1CC38D6233AD
+PT=0EA90279135DFFC7F58DB959F9E8BFE1
+CT=3717C67E520D87778350E62525C01730
+
+I=157
+KEY=79D13142BE9066A2EAD9266957482AF5D9EDFAE6A8A2249D
+PT=3717C67E520D87778350E62525C01730
+CT=A8F96DA7AE81EF8810A317AB4C9B82A9
+
+I=158
+KEY=597D70828E56003942204BCEF9C9C57DC94EED4DE439A634
+PT=A8F96DA7AE81EF8810A317AB4C9B82A9
+CT=8C373A065986BAC9E345475F5D83FBCF
+
+I=159
+KEY=96C8CF3884D5DA18CE1771C8A04F7FB42A0BAA12B9BA5DFB
+PT=8C373A065986BAC9E345475F5D83FBCF
+CT=8E4D562CBEDC360EFB25B857DD4C4FF2
+
+I=160
+KEY=5A0A29B58F17F9F9405A27E41E9349BAD12E124564F61209
+PT=8E4D562CBEDC360EFB25B857DD4C4FF2
+CT=192CCD79E3B4C8F5617D1F55B789B7A3
+
+I=161
+KEY=29A4692EDE3EAABE5976EA9DFD27814FB0530D10D37FA5AA
+PT=192CCD79E3B4C8F5617D1F55B789B7A3
+CT=8A5F181E1748C98121D1C22204591B23
+
+I=162
+KEY=5E5CA30210E78677D329F283EA6F48CE9182CF32D726BE89
+PT=8A5F181E1748C98121D1C22204591B23
+CT=14512A4997094A0536594E63ACC5EF4A
+
+I=163
+KEY=7DA5F9C99B68DFB0C778D8CA7D6602CBA7DB81517BE351C3
+PT=14512A4997094A0536594E63ACC5EF4A
+CT=F91BA751D5E2ADC074FC6CC14476DE67
+
+I=164
+KEY=658144C57CCFDAD83E637F9BA884AF0BD327ED903F958FA4
+PT=F91BA751D5E2ADC074FC6CC14476DE67
+CT=5F7FED22BABA25D48C95C4E2CAEDB3F4
+
+I=165
+KEY=13C5D7A44396F6FD611C92B9123E8ADF5FB22972F5783C50
+PT=5F7FED22BABA25D48C95C4E2CAEDB3F4
+CT=0FCFB3CB93B2E7FDF7E156486929BD17
+
+I=166
+KEY=99DBAC1D5D268DB06ED32172818C6D22A8537F3A9C518147
+PT=0FCFB3CB93B2E7FDF7E156486929BD17
+CT=3E16265A02271FF68AE6310A6BFDEE60
+
+I=167
+KEY=A8876A49E2F1CC5250C5072883AB72D422B54E30F7AC6F27
+PT=3E16265A02271FF68AE6310A6BFDEE60
+CT=1657BF722B57D083D8864B6447317E05
+
+I=168
+KEY=0A615A71BC2BE3E94692B85AA8FCA257FA330554B09D1122
+PT=1657BF722B57D083D8864B6447317E05
+CT=018B742E941E27C547451B9E41F245F5
+
+I=169
+KEY=6AE11571E3D54C4B4719CC743CE28592BD761ECAF16F54D7
+PT=018B742E941E27C547451B9E41F245F5
+CT=8C5BB61774502B6A9C44BEE8D6C44A63
+
+I=170
+KEY=DCE75079013F0865CB427A6348B2AEF82132A02227AB1EB4
+PT=8C5BB61774502B6A9C44BEE8D6C44A63
+CT=361D3B51C751298194CB1AA32C0A86EE
+
+I=171
+KEY=E73232D50D457866FD5F41328FE38779B5F9BA810BA1985A
+PT=361D3B51C751298194CB1AA32C0A86EE
+CT=7B734F34DD4F332CBE5CFC7659C390BF
+
+I=172
+KEY=BEEF9073227655EB862C0E0652ACB4550BA546F7526208E5
+PT=7B734F34DD4F332CBE5CFC7659C390BF
+CT=63CCC9CE5DADA5B5AC68870E6C675943
+
+I=173
+KEY=1E9078C198526C1DE5E0C7C80F0111E0A7CDC1F93E0551A6
+PT=63CCC9CE5DADA5B5AC68870E6C675943
+CT=7BBC6F7B62807CBE1C93CADB5E6CAE0A
+
+I=174
+KEY=AD26AC70784FF1B99E5CA8B36D816D5EBB5E0B226069FFAC
+PT=7BBC6F7B62807CBE1C93CADB5E6CAE0A
+CT=E95B0C766EF9049163D3A249E196DDB8
+
+I=175
+KEY=E17835A277F1D1EE7707A4C5037869CFD88DA96B81FF2214
+PT=E95B0C766EF9049163D3A249E196DDB8
+CT=968263CBCDB4582FC9CDFD0C9FD0B4F0
+
+I=176
+KEY=22F9EB31E67C62DBE185C70ECECC31E0114054671E2F96E4
+PT=968263CBCDB4582FC9CDFD0C9FD0B4F0
+CT=9F573A339DFA07B844E4034718A4FE88
+
+I=177
+KEY=0FEC8766966A42DA7ED2FD3D5336365855A45720068B686C
+PT=9F573A339DFA07B844E4034718A4FE88
+CT=A0809BA3A742C0EB1BDA613B7472F56A
+
+I=178
+KEY=98E655519C9A8A95DE52669EF474F6B34E7E361B72F99D06
+PT=A0809BA3A742C0EB1BDA613B7472F56A
+CT=9BF1D85440818035FA6AC36E5A5F00A7
+
+I=179
+KEY=A8D37BE0EB386F8045A3BECAB4F57686B414F57528A69DA1
+PT=9BF1D85440818035FA6AC36E5A5F00A7
+CT=924E309AC04A655C50980360914E9830
+
+I=180
+KEY=7D89F156EA181E92D7ED8E5074BF13DAE48CF615B9E80591
+PT=924E309AC04A655C50980360914E9830
+CT=427819CDAE419A046D4586FF5A784A1C
+
+I=181
+KEY=B028A265666F69629595979DDAFE89DE89C970EAE3904F8D
+PT=427819CDAE419A046D4586FF5A784A1C
+CT=D8B51EEC0A6A6D17F1E476C922AD8548
+
+I=182
+KEY=DF20B45B990C5E734D208971D094E4C9782D0623C13DCAC5
+PT=D8B51EEC0A6A6D17F1E476C922AD8548
+CT=7823F1BBA96105168195CDAC34AB5315
+
+I=183
+KEY=AF4C64F7E4AA6DE2350378CA79F5E1DFF9B8CB8FF59699D0
+PT=7823F1BBA96105168195CDAC34AB5315
+CT=85DD0256BC29EAA867DB77C1A049574D
+
+I=184
+KEY=4047F74604E37A00B0DE7A9CC5DC0B779E63BC4E55DFCE9D
+PT=85DD0256BC29EAA867DB77C1A049574D
+CT=64C1880D34408CB1A92BBA354941D5B6
+
+I=185
+KEY=9C3BF36E47110C08D41FF291F19C87C63748067B1C9E1B2B
+PT=64C1880D34408CB1A92BBA354941D5B6
+CT=25B80866FE3198C775F64C412E734348
+
+I=186
+KEY=FAE7368F99242159F1A7FAF70FAD1F0142BE4A3A32ED5863
+PT=25B80866FE3198C775F64C412E734348
+CT=8D3D7E9A195363C96334C48120BC343A
+
+I=187
+KEY=5F48BD86A9C4DC897C9A846D16FE7CC8218A8EBB12516C59
+PT=8D3D7E9A195363C96334C48120BC343A
+CT=E886EEA0F2D556D693DC94FFC588D1F4
+
+I=188
+KEY=B7406993C120EA20941C6ACDE42B2A1EB2561A44D7D9BDAD
+PT=E886EEA0F2D556D693DC94FFC588D1F4
+CT=76CB89CBB935D422DED9784D4548A84F
+
+I=189
+KEY=4DB740C3FA55F4ABE2D7E3065D1EFE3C6C8F6209929115E2
+PT=76CB89CBB935D422DED9784D4548A84F
+CT=93D7AC7B18A1196D5C166203C44A43D3
+
+I=190
+KEY=353A0293DEFB648071004F7D45BFE7513099000A56DB5631
+PT=93D7AC7B18A1196D5C166203C44A43D3
+CT=8982BD77485524EE9E49769591E922CE
+
+I=191
+KEY=F6FC1F7E838CD8A7F882F20A0DEAC3BFAED0769FC73274FF
+PT=8982BD77485524EE9E49769591E922CE
+CT=89012A1E3F7669C76C5F5F4987108662
+
+I=192
+KEY=A1AA84E01EBC3E837183D814329CAA78C28F29D64022F29D
+PT=89012A1E3F7669C76C5F5F4987108662
+CT=139E37ADA17990054AF8EF5B717E884B
+
+I=193
+KEY=C631229E9871F2AC621DEFB993E53A7D8877C68D315C7AD6
+PT=139E37ADA17990054AF8EF5B717E884B
+CT=CEC8F9C90B2E393BDA4602C2A83F953C
+
+I=194
+KEY=824604723CD82F95ACD5167098CB03465231C44F9963EFEA
+PT=CEC8F9C90B2E393BDA4602C2A83F953C
+CT=2A2E1344AE4C6BA40568E170BF67FD74
+
+I=195
+KEY=2B17489FA71F683B86FB0534368768E25759253F2604129E
+PT=2A2E1344AE4C6BA40568E170BF67FD74
+CT=7402AC6982DBB0BED678746E4523556C
+
+I=196
+KEY=DA9C0CF5A89D3D94F2F9A95DB45CD85C81215151632747F2
+PT=7402AC6982DBB0BED678746E4523556C
+CT=36A36B5B55F950F00B9F3E31156BFD65
+
+I=197
+KEY=543619886B56830BC45AC206E1A588AC8ABE6F60764CBA97
+PT=36A36B5B55F950F00B9F3E31156BFD65
+CT=D7B36A117E824A49A5944C37BEE27F06
+
+I=198
+KEY=9494630598E7618213E9A8179F27C2E52F2A2357C8AEC591
+PT=D7B36A117E824A49A5944C37BEE27F06
+CT=2D60BC0BC950EEE7E36D50E971CF68D0
+
+I=199
+KEY=B0328218DF523A0C3E89141C56772C02CC4773BEB961AD41
+PT=2D60BC0BC950EEE7E36D50E971CF68D0
+CT=49A4643E535F45A1ABDEF41ABABBE268
+
+I=200
+KEY=5E3FD7ACD8EF334D772D7022052869A3679987A403DA4F29
+PT=49A4643E535F45A1ABDEF41ABABBE268
+CT=D5EEB5CC40AF8612708BAABE85685E4C
+
+I=201
+KEY=A232D0267D606002A2C3C5EE4587EFB117122D1A86B21165
+PT=D5EEB5CC40AF8612708BAABE85685E4C
+CT=3F5B875DE202C5441165FE5C5CA2D258
+
+I=202
+KEY=844ED6FAFA342BFE9D9842B3A7852AF50677D346DA10C33D
+PT=3F5B875DE202C5441165FE5C5CA2D258
+CT=9B5F0210E0EC623C6ACF1C0BC06EBF51
+
+I=203
+KEY=109F8CEC689E0F5306C740A3476948C96CB8CF4D1A7E7C6C
+PT=9B5F0210E0EC623C6ACF1C0BC06EBF51
+CT=E57015FAB0006446E544704DB6629059
+
+I=204
+KEY=D9ABCBAC4B271B04E3B75559F7692C8F89FCBF00AC1CEC35
+PT=E57015FAB0006446E544704DB6629059
+CT=85F0DF6B1ED933E87F6A9F609D516346
+
+I=205
+KEY=09915869AE1F57F766478A32E9B01F67F6962060314D8F73
+PT=85F0DF6B1ED933E87F6A9F609D516346
+CT=471B931539C155478A1D4B9BA50DCE43
+
+I=206
+KEY=BFB70AA6C4F05C1D215C1927D0714A207C8B6BFB94404130
+PT=471B931539C155478A1D4B9BA50DCE43
+CT=9AC55C1CC77E7B59CC9204898A38CEA7
+
+I=207
+KEY=660972D79B056F14BB99453B170F3179B0196F721E788F97
+PT=9AC55C1CC77E7B59CC9204898A38CEA7
+CT=19B00FEB13145F9F356173B42184D516
+
+I=208
+KEY=F09576EB17FB1A07A2294AD0041B6EE685781CC63FFC5A81
+PT=19B00FEB13145F9F356173B42184D516
+CT=5F1379E25F6DD8653B73F58E738D6243
+
+I=209
+KEY=8D170BBC5E3662BEFD3A33325B76B683BE0BE9484C7138C2
+PT=5F1379E25F6DD8653B73F58E738D6243
+CT=AEF55C09E7AD76CC9BA7B83874A0A86B
+
+I=210
+KEY=1A7BD2572D3CDB8C53CF6F3BBCDBC04F25AC517038D190A9
+PT=AEF55C09E7AD76CC9BA7B83874A0A86B
+CT=6BEF52E6D86DC15D2A03B5CB3EBAB130
+
+I=211
+KEY=B4BC0603F59BE3D038203DDD64B601120FAFE4BB066B2199
+PT=6BEF52E6D86DC15D2A03B5CB3EBAB130
+CT=FDC093FFED096B7812E77E23AD9C7C71
+
+I=212
+KEY=C00A0DDA74D55250C5E0AE2289BF6A6A1D489A98ABF75DE8
+PT=FDC093FFED096B7812E77E23AD9C7C71
+CT=072625CB0C022827E195DE8AB4FE7E0C
+
+I=213
+KEY=6534CBAB46880CE0C2C68BE985BD424DFCDD44121F0923E4
+PT=072625CB0C022827E195DE8AB4FE7E0C
+CT=11AA47C5557437AEE8A8BE31A849A047
+
+I=214
+KEY=C204AFE794D81224D36CCC2CD0C975E31475FA23B74083A3
+PT=11AA47C5557437AEE8A8BE31A849A047
+CT=4C91B3031567DFFC22829CBC3C419B6D
+
+I=215
+KEY=01A4820CC4D281B99FFD7F2FC5AEAA1F36F7669F8B0118CE
+PT=4C91B3031567DFFC22829CBC3C419B6D
+CT=54C0F95B0179CB753917A2592F58BD77
+
+I=216
+KEY=B5C1DD77446C8FD1CB3D8674C4D7616A0FE0C4C6A459A5B9
+PT=54C0F95B0179CB753917A2592F58BD77
+CT=A2A19A98250E432131F9EF4AE473677F
+
+I=217
+KEY=9FDC1167AC2D1A51699C1CECE1D9224B3E192B8C402AC2C6
+PT=A2A19A98250E432131F9EF4AE473677F
+CT=9B5780CA9669A92688F54887E303F2D3
+
+I=218
+KEY=C734A73F4A32D311F2CB9C2677B08B6DB6EC630BA3293015
+PT=9B5780CA9669A92688F54887E303F2D3
+CT=F1750745D1E74E41A07B99482ECABAAA
+
+I=219
+KEY=1612B86730F487EF03BE9B63A657C52C1697FA438DE38ABF
+PT=F1750745D1E74E41A07B99482ECABAAA
+CT=30F510DBDDAEC6FC0D2504C11DF23CFA
+
+I=220
+KEY=D52E3B50F72B085D334B8BB87BF903D01BB2FE829011B645
+PT=30F510DBDDAEC6FC0D2504C11DF23CFA
+CT=64998C3018185D722477A2DBFB84ABB8
+
+I=221
+KEY=7F9F2A23D320792E57D2078863E15EA23FC55C596B951DFD
+PT=64998C3018185D722477A2DBFB84ABB8
+CT=9293A4FF9ED5D57D81BB8A63381BF66A
+
+I=222
+KEY=B529B6E7080E0AE4C541A377FD348BDFBE7ED63A538EEB97
+PT=9293A4FF9ED5D57D81BB8A63381BF66A
+CT=A389ABCF609B41F28CC3188B2C126915
+
+I=223
+KEY=A5C4C3A89459F79566C808B89DAFCA2D32BDCEB17F9C8282
+PT=A389ABCF609B41F28CC3188B2C126915
+CT=5F4BC60608A3DF788631EBB66763E7DF
+
+I=224
+KEY=F59456291C6CF0C83983CEBE950C1555B48C250718FF655D
+PT=5F4BC60608A3DF788631EBB66763E7DF
+CT=EFDE2113118EDFD5A15D4DFA1C1E79B4
+
+I=225
+KEY=9A4CD87E44EA7DEED65DEFAD8482CA8015D168FD04E11CE9
+PT=EFDE2113118EDFD5A15D4DFA1C1E79B4
+CT=2526BA56DA8A9F9A5799A9D2BE96AEBA
+
+I=226
+KEY=A19D5DFAEC1C9B9DF37B55FB5E08551A4248C12FBA77B253
+PT=2526BA56DA8A9F9A5799A9D2BE96AEBA
+CT=83F237712EF89A7B1E84D69DEFC9B9B9
+
+I=227
+KEY=C48B0103470544867089628A70F0CF615CCC17B255BE0BEA
+PT=83F237712EF89A7B1E84D69DEFC9B9B9
+CT=13B7E26895FEEFE2356306D8D822DDD3
+
+I=228
+KEY=B366B0FE6BB3DB17633E80E2E50E208369AF116A8D9CD639
+PT=13B7E26895FEEFE2356306D8D822DDD3
+CT=BF8C47559B230A3311543BEAA90D4DA1
+
+I=229
+KEY=BE5A735484B72645DCB2C7B77E2D2AB078FB2A8024919B98
+PT=BF8C47559B230A3311543BEAA90D4DA1
+CT=D3C9AFCED64F46AC74FFF73302DE10EB
+
+I=230
+KEY=1DFD852FE9F131840F7B6879A8626C1C0C04DDB3264F8B73
+PT=D3C9AFCED64F46AC74FFF73302DE10EB
+CT=004386EABD8F3C60971D34B5A5F220F8
+
+I=231
+KEY=BB9831D80259A5A40F38EE9315ED507C9B19E90683BDAB8B
+PT=004386EABD8F3C60971D34B5A5F220F8
+CT=119A244F6A3ED1947A764CFE96568213
+
+I=232
+KEY=93B0F09E78E610741EA2CADC7FD381E8E16FA5F815EB2998
+PT=119A244F6A3ED1947A764CFE96568213
+CT=4C8D061BD62737E674DDCACEFC37DA11
+
+I=233
+KEY=43E5036A09590404522FCCC7A9F4B60E95B26F36E9DCF389
+PT=4C8D061BD62737E674DDCACEFC37DA11
+CT=7B5EFE44536B5AB9CF75A457BB8C2417
+
+I=234
+KEY=869CF7BF36FBB5D829713283FA9FECB75AC7CB615250D79E
+PT=7B5EFE44536B5AB9CF75A457BB8C2417
+CT=25771915A1C0F8149634963E1C91BD26
+
+I=235
+KEY=C9BD373897A760E30C062B965B5F14A3CCF35D5F4EC16AB8
+PT=25771915A1C0F8149634963E1C91BD26
+CT=8BB2BC7E7BAAEA1AAF7A9E285BEEB8F1
+
+I=236
+KEY=D2EE543EACA1592687B497E820F5FEB96389C377152FD249
+PT=8BB2BC7E7BAAEA1AAF7A9E285BEEB8F1
+CT=05556B6AB68D2DABCDB32FB724D44F57
+
+I=237
+KEY=9583438F7194754F82E1FC829678D312AE3AECC031FB9D1E
+PT=05556B6AB68D2DABCDB32FB724D44F57
+CT=A4CE8197B0EAE6AD57D5A0630D0CABD0
+
+I=238
+KEY=A5B96A3EFB2EF0C7262F7D15269235BFF9EF4CA33CF736CE
+PT=A4CE8197B0EAE6AD57D5A0630D0CABD0
+CT=8E40F09865AA8EA114EA7F36E11815C3
+
+I=239
+KEY=8E7A04E47969F5DBA86F8D8D4338BB1EED053395DDEF230D
+PT=8E40F09865AA8EA114EA7F36E11815C3
+CT=194A76947319ED92D96D292684C29B5A
+
+I=240
+KEY=E52197304B446A01B125FB193021568C34681AB3592DB857
+PT=194A76947319ED92D96D292684C29B5A
+CT=93526BBB6405BDEA68AC01F1C807EBF7
+
+I=241
+KEY=DA4552EC2C076DC3227790A25424EB665CC41B42912A53A0
+PT=93526BBB6405BDEA68AC01F1C807EBF7
+CT=59860971F900B739B36CB97D35B082D1
+
+I=242
+KEY=E7329ED9491CA8227BF199D3AD245C5FEFA8A23FA49AD171
+PT=59860971F900B739B36CB97D35B082D1
+CT=92F430D5B1F35B469ECDDFDCB2A110F5
+
+I=243
+KEY=1ADC19560D9AEF09E905A9061CD7071971657DE3163BC184
+PT=92F430D5B1F35B469ECDDFDCB2A110F5
+CT=F81D2505FD9A569A71502B23894DA535
+
+I=244
+KEY=6ED932F2BEBD486911188C03E14D5183003556C09F7664B1
+PT=F81D2505FD9A569A71502B23894DA535
+CT=93BACD72A0E761D34E8603FC44F6BA5E
+
+I=245
+KEY=F0A52339F0C68F5782A2417141AA30504EB3553CDB80DEEF
+PT=93BACD72A0E761D34E8603FC44F6BA5E
+CT=631DB808708B5EBB54A2DE6B62519235
+
+I=246
+KEY=0B262E7EA7109C03E1BFF97931216EEB1A118B57B9D14CDA
+PT=631DB808708B5EBB54A2DE6B62519235
+CT=C402023DA5F2F230FEEACE1C5F8B5390
+
+I=247
+KEY=1E7EB042CA0EA74F25BDFB4494D39CDBE4FB454BE65A1F4A
+PT=C402023DA5F2F230FEEACE1C5F8B5390
+CT=CAD88E79E0AB4A3B324F6D3ABBEA211C
+
+I=248
+KEY=215E3E970705BE3DEF65753D7478D6E0D6B428715DB03E56
+PT=CAD88E79E0AB4A3B324F6D3ABBEA211C
+CT=1B2303C4FEB78105B5BF35BC1C5C2FF9
+
+I=249
+KEY=512CE443B55593D9F44676F98ACF57E5630B1DCD41EC11AF
+PT=1B2303C4FEB78105B5BF35BC1C5C2FF9
+CT=06CAE1EED611AF829C83216697F8AEFA
+
+I=250
+KEY=533251960972B2BFF28C97175CDEF867FF883CABD614BF55
+PT=06CAE1EED611AF829C83216697F8AEFA
+CT=170194A7E4E85B0A339BF86460E5ABC6
+
+I=251
+KEY=B484A158FBC3D31FE58D03B0B836A36DCC13C4CFB6F11493
+PT=170194A7E4E85B0A339BF86460E5ABC6
+CT=AF7014D972F55B0CD759CAFBC0D9483B
+
+I=252
+KEY=C470759A6962C1934AFD1769CAC3F8611B4A0E3476285CA8
+PT=AF7014D972F55B0CD759CAFBC0D9483B
+CT=E8BD547419DADD980682B701CCEF3C7E
+
+I=253
+KEY=D27A5BF9DD3B6F61A240431DD31925F91DC8B935BAC760D6
+PT=E8BD547419DADD980682B701CCEF3C7E
+CT=E8F9CFAA891A471EBBC5806F03E0E18A
+
+I=254
+KEY=041C2FF776BAF2334AB98CB75A0362E7A60D395AB927815C
+PT=E8F9CFAA891A471EBBC5806F03E0E18A
+CT=F90F888C03CEBFC9A807DF2100488B24
+
+I=255
+KEY=9BB4307835C91BA4B3B6043B59CDDD2E0E0AE67BB96F0A78
+PT=F90F888C03CEBFC9A807DF2100488B24
+CT=7874C642B44810334C2CF572DA0DEF68
+
+I=256
+KEY=56E742B84F293B68CBC2C279ED85CD1D422613096362E510
+PT=7874C642B44810334C2CF572DA0DEF68
+CT=064513BBD5E667B651B93502E86B6C43
+
+I=257
+KEY=66E28C26E01570FCCD87D1C23863AAAB139F260B8B098953
+PT=064513BBD5E667B651B93502E86B6C43
+CT=D461A03D7D8669BBC32430D00D437E59
+
+I=258
+KEY=5674831937969B7619E671FF45E5C310D0BB16DB864AF70A
+PT=D461A03D7D8669BBC32430D00D437E59
+CT=0A07F858DBD1909FF970C95ED7287FB3
+
+I=259
+KEY=D45BCD0FF3E14A7013E189A79E34538F29CBDF85516288B9
+PT=0A07F858DBD1909FF970C95ED7287FB3
+CT=C2E45D29C1DF02CB4D768682ADD73E6B
+
+I=260
+KEY=40F81EBEF03AAAABD105D48E5FEB514464BD5907FCB5B6D2
+PT=C2E45D29C1DF02CB4D768682ADD73E6B
+CT=01E21E496061DAC195F24F6D1CF22B8A
+
+I=261
+KEY=99C8875EE8221C3FD0E7CAC73F8A8B85F14F166AE0479D58
+PT=01E21E496061DAC195F24F6D1CF22B8A
+CT=71D1C35E1126F6907CDB5414B8C97E84
+
+I=262
+KEY=F1582613B3466D7FA13609992EAC7D158D94427E588EE3DC
+PT=71D1C35E1126F6907CDB5414B8C97E84
+CT=8B7BBAF63C993D4BBB098A22D00C5608
+
+I=263
+KEY=4679A2F69656CFD32A4DB36F1235405E369DC85C8882B5D4
+PT=8B7BBAF63C993D4BBB098A22D00C5608
+CT=651B19F5C1B67FC52151E7C5F1246485
+
+I=264
+KEY=A404FC3490DFC7244F56AA9AD3833F9B17CC2F9979A6D151
+PT=651B19F5C1B67FC52151E7C5F1246485
+CT=158F0AE36B5585868DFB998520318FEB
+
+I=265
+KEY=F7DCCA4394981F2D5AD9A079B8D6BA1D9A37B61C59975EBA
+PT=158F0AE36B5585868DFB998520318FEB
+CT=B62EC94231405F3FB0D160FBFF2DE27E
+
+I=266
+KEY=1F38711C9B6BD060ECF7693B8996E5222AE6D6E7A6BABCC4
+PT=B62EC94231405F3FB0D160FBFF2DE27E
+CT=464AFFA35373CEE71523FF0AFBFB1F51
+
+I=267
+KEY=6B846AAC0C448654AABD9698DAE52BC53FC529ED5D41A395
+PT=464AFFA35373CEE71523FF0AFBFB1F51
+CT=C729EA9A05D5482491CE31DBBC03CE24
+
+I=268
+KEY=BD539A9B4001B6876D947C02DF3063E1AE0B1836E1426DB1
+PT=C729EA9A05D5482491CE31DBBC03CE24
+CT=C755C048ADAD22A628B077163097415F
+
+I=269
+KEY=18B524EEF606589DAAC1BC4A729D414786BB6F20D1D52CEE
+PT=C755C048ADAD22A628B077163097415F
+CT=2DADB8F8FC76D8C997627449E44D14B2
+
+I=270
+KEY=3C2C6A047706E3DD876C04B28EEB998E11D91B693598385C
+PT=2DADB8F8FC76D8C997627449E44D14B2
+CT=2D7109526C2F1B5D08DD356B163498D7
+
+I=271
+KEY=40593D776B6C5920AA1D0DE0E2C482D319042E0223ACA08B
+PT=2D7109526C2F1B5D08DD356B163498D7
+CT=D9C1D988ABD5C892B2E5BA7BF4F584D3
+
+I=272
+KEY=72B53E4711B3DE9873DCD46849114A41ABE19479D7592458
+PT=D9C1D988ABD5C892B2E5BA7BF4F584D3
+CT=0A32E78440A8AE4A3FF74B20A3F5F7DE
+
+I=273
+KEY=C0BEF126899B305B79EE33EC09B9E40B9416DF5974ACD386
+PT=0A32E78440A8AE4A3FF74B20A3F5F7DE
+CT=E7AA36688851D8E4E08E9EFE6987C571
+
+I=274
+KEY=D16257EFEE63CC399E44058481E83CEF749841A71D2B16F7
+PT=E7AA36688851D8E4E08E9EFE6987C571
+CT=0E3E2E99FFA84F8A69CAA897017DD09C
+
+I=275
+KEY=3509E5A7A66648B9907A2B1D7E4073651D52E9301C56C66B
+PT=0E3E2E99FFA84F8A69CAA897017DD09C
+CT=96766B7F6E78537994466BDC62607C85
+
+I=276
+KEY=46BC3EB6FA22C8AC060C40621038201C891482EC7E36BAEE
+PT=96766B7F6E78537994466BDC62607C85
+CT=AA42980BBABA21DACE6D9FCD28A5B0BA
+
+I=277
+KEY=26FC66C5E5C6E585AC4ED869AA8201C647791D2156930A54
+PT=AA42980BBABA21DACE6D9FCD28A5B0BA
+CT=EC057F10222EC91403E1B6CEFCE3556A
+
+I=278
+KEY=91FBDF7B24B0FEB4404BA77988ACC8D24498ABEFAA705F3E
+PT=EC057F10222EC91403E1B6CEFCE3556A
+CT=E6E91EC6B977C3547D08F717F6702E80
+
+I=279
+KEY=5BD8360BB35CE209A6A2B9BF31DB0B8639905CF85C0071BE
+PT=E6E91EC6B977C3547D08F717F6702E80
+CT=DF9BE6A5A61CC4B66C76447202CBFADA
+
+I=280
+KEY=E58D0EFAB72342BD79395F1A97C7CF3055E6188A5ECB8B64
+PT=DF9BE6A5A61CC4B66C76447202CBFADA
+CT=8466FA526E1038CC14A2EC6D85FC4EDF
+
+I=281
+KEY=7EB51DD43B05BB26FD5FA548F9D7F7FC4144F4E7DB37C5BB
+PT=8466FA526E1038CC14A2EC6D85FC4EDF
+CT=5C5A965E386B16D50F3487D54C04AA6B
+
+I=282
+KEY=8F4BEBA429FE57C4A1053316C1BCE1294E70733297336FD0
+PT=5C5A965E386B16D50F3487D54C04AA6B
+CT=BCD57B57FAA6E3F81660113345CD24F9
+
+I=283
+KEY=4A5DA421D27E62821DD048413B1A02D158106201D2FE4B29
+PT=BCD57B57FAA6E3F81660113345CD24F9
+CT=7450D38B3A6D8C4987EE3F7F71C68FFC
+
+I=284
+KEY=77934AE2BB39BC4469809BCA01778E98DFFE5D7EA338C4D5
+PT=7450D38B3A6D8C4987EE3F7F71C68FFC
+CT=A6D1D5A31BAB1CE9F027376539B2AAE2
+
+I=285
+KEY=2C6FD4455E96F2F6CF514E691ADC92712FD96A1B9A8A6E37
+PT=A6D1D5A31BAB1CE9F027376539B2AAE2
+CT=10894E2E6275D172259D4C23332508B9
+
+I=286
+KEY=2608AB9AA8CED631DFD8004778A943030A442638A9AF668E
+PT=10894E2E6275D172259D4C23332508B9
+CT=53C2AB8E42B4EF7FF659D3FB251453C7
+
+I=287
+KEY=68840BD9639AC3128C1AABC93A1DAC7CFC1DF5C38CBB3549
+PT=53C2AB8E42B4EF7FF659D3FB251453C7
+CT=3A9C38D026561B83B0F3E7B566C66CD2
+
+I=288
+KEY=EFCDF07C0E70D051B68693191C4BB7FF4CEE1276EA7D599B
+PT=3A9C38D026561B83B0F3E7B566C66CD2
+CT=B9F7E495B96BE7C0307D8F7A53200193
+
+I=289
+KEY=87DFC62793B45EF60F71778CA520503F7C939D0CB95D5808
+PT=B9F7E495B96BE7C0307D8F7A53200193
+CT=2425FE8AAA7ED06A5FFEC11D7B289891
+
+I=290
+KEY=5FD78DA64A9F50142B5489060F5E8055236D5C11C275C099
+PT=2425FE8AAA7ED06A5FFEC11D7B289891
+CT=93BC83BCF69DBB256C27AF250FDEFAEB
+
+I=291
+KEY=81C88579E065FD16B8E80ABAF9C33B704F4AF334CDAB3A72
+PT=93BC83BCF69DBB256C27AF250FDEFAEB
+CT=A1AF953D4BD1A474B1173D4686EBB8CF
+
+I=292
+KEY=DEE7FFE9A3814D2B19479F87B2129F04FE5DCE724B4082BD
+PT=A1AF953D4BD1A474B1173D4686EBB8CF
+CT=00AAC1CD74952011A03714A6BB091653
+
+I=293
+KEY=8331CC8136829F1E19ED5E4AC687BF155E6ADAD4F04994EE
+PT=00AAC1CD74952011A03714A6BB091653
+CT=00B92CBFFC3589CEB3ECAA7D221C3F0B
+
+I=294
+KEY=FF862EBFECC11E93195472F53AB236DBED8670A9D255ABE5
+PT=00B92CBFFC3589CEB3ECAA7D221C3F0B
+CT=2E07858E94AD300A35448EFA848A767A
+
+I=295
+KEY=18B8678C5497708E3753F77BAE1F06D1D8C2FE5356DFDD9F
+PT=2E07858E94AD300A35448EFA848A767A
+CT=B02F0C98F3B7BB7807F35F6DFD925238
+
+I=296
+KEY=C90D1E18331CA38F877CFBE35DA8BDA9DF31A13EAB4D8FA7
+PT=B02F0C98F3B7BB7807F35F6DFD925238
+CT=EAACC8624146D29129ED8B904E89F04A
+
+I=297
+KEY=A08AD721EE869F2E6DD033811CEE6F38F6DC2AAEE5C47FED
+PT=EAACC8624146D29129ED8B904E89F04A
+CT=8949A5A4289B65A32C5116E8A4B55A50
+
+I=298
+KEY=CED3055CB1AC48CAE499962534750A9BDA8D3C46417125BD
+PT=8949A5A4289B65A32C5116E8A4B55A50
+CT=B632C5FD8EB9676B5504A8BA13E63E2D
+
+I=299
+KEY=AD1DA883EFFC2F3052AB53D8BACC6DF08F8994FC52971B90
+PT=B632C5FD8EB9676B5504A8BA13E63E2D
+CT=EF28A1297C07A575686B3429AC9B62D1
+
+I=300
+KEY=007F57339EC932CCBD83F2F1C6CBC885E7E2A0D5FE0C7941
+PT=EF28A1297C07A575686B3429AC9B62D1
+CT=C99F15E4000944120D1C3DD283D99BFF
+
+I=301
+KEY=3688FDD4FD7822F2741CE715C6C28C97EAFE9D077DD5E2BE
+PT=C99F15E4000944120D1C3DD283D99BFF
+CT=0AC0219E2BD43F9F19F3A0997FCB9FCD
+
+I=302
+KEY=AB54BF259C6F5CEE7EDCC68BED16B308F30D3D9E021E7D73
+PT=0AC0219E2BD43F9F19F3A0997FCB9FCD
+CT=E27242BC80823BDC09C33C1BDB2EA3BE
+
+I=303
+KEY=9C88F101B483F8399CAE84376D9488D4FACE0185D930DECD
+PT=E27242BC80823BDC09C33C1BDB2EA3BE
+CT=7ABF9BD872F54E12FB7F0B11A6D10472
+
+I=304
+KEY=971A26707E5B8BC2E6111FEF1F61C6C601B10A947FE1DABF
+PT=7ABF9BD872F54E12FB7F0B11A6D10472
+CT=336653E5166F1B4146DBEAED74D72BB7
+
+I=305
+KEY=1FFD085658F88F24D5774C0A090EDD87476AE0790B36F108
+PT=336653E5166F1B4146DBEAED74D72BB7
+CT=4849136D0509CE6C404E5685FBEEE9B8
+
+I=306
+KEY=411DF55702805FE69D3E5F670C0713EB0724B6FCF0D818B0
+PT=4849136D0509CE6C404E5685FBEEE9B8
+CT=6CF8DCFD53E2ED214A449398D8BF0F6C
+
+I=307
+KEY=504BFF39E24E870FF1C6839A5FE5FECA4D602564286717DC
+PT=6CF8DCFD53E2ED214A449398D8BF0F6C
+CT=9C8326B89B3054A46ECA3BB76BC2F292
+
+I=308
+KEY=E4F4B55125D2D1056D45A522C4D5AA6E23AA1ED343A5E54E
+PT=9C8326B89B3054A46ECA3BB76BC2F292
+CT=C85479C9E038BA5495F67D6E8B2BEB64
+
+I=309
+KEY=F2E9B605207E0FD4A511DCEB24ED103AB65C63BDC88E0E2A
+PT=C85479C9E038BA5495F67D6E8B2BEB64
+CT=145607ACFFA06C08AB958DCB7BC0BDBC
+
+I=310
+KEY=CC0D3F478519145BB147DB47DB4D7C321DC9EE76B34EB396
+PT=145607ACFFA06C08AB958DCB7BC0BDBC
+CT=ED7EE0DA132D9964BE5E7B2581C3C270
+
+I=311
+KEY=EB3AFCDD9AAB59705C393B9DC860E556A3979553328D71E6
+PT=ED7EE0DA132D9964BE5E7B2581C3C270
+CT=6B576FD09F34ED38774AA383BB88B385
+
+I=312
+KEY=866ECC1B3691532D376E544D5754086ED4DD36D08905C263
+PT=6B576FD09F34ED38774AA383BB88B385
+CT=E540518151453A18C29BE22B5DE84D5B
+
+I=313
+KEY=2B3BF12A0A10E6F9D22E05CC061132761646D4FBD4ED8F38
+PT=E540518151453A18C29BE22B5DE84D5B
+CT=7865DE74099D486ECB584BE7890F3078
+
+I=314
+KEY=3C6EA741634001E0AA4BDBB80F8C7A18DD1E9F1C5DE2BF40
+PT=7865DE74099D486ECB584BE7890F3078
+CT=5226B72FA16653187980D265EB6C7C6D
+
+I=315
+KEY=A32E19E0F06CB649F86D6C97AEEA2900A49E4D79B68EC32D
+PT=5226B72FA16653187980D265EB6C7C6D
+CT=CA0D39D92B042BECABF7A14115B3A307
+
+I=316
+KEY=E48451707115D4A03260554E85EE02EC0F69EC38A33D602A
+PT=CA0D39D92B042BECABF7A14115B3A307
+CT=EC1658D60F1D94EF514FA8EDADAB3C1D
+
+I=317
+KEY=89A589616229672BDE760D988AF396035E2644D50E965C37
+PT=EC1658D60F1D94EF514FA8EDADAB3C1D
+CT=F278CD13BF2C6A1F2D9A9F0C1113205D
+
+I=318
+KEY=6013E84EFD076E402C0EC08B35DFFC1C73BCDBD91F857C6A
+PT=F278CD13BF2C6A1F2D9A9F0C1113205D
+CT=0B1A35F604DDB043BCD0573DC0850AF0
+
+I=319
+KEY=68BCE1DC00C592E22714F57D31024C5FCF6C8CE4DF00769A
+PT=0B1A35F604DDB043BCD0573DC0850AF0
+CT=EAC4FE6F8A04871AC434322CB06308E3
+
+I=320
+KEY=1BE682363F216340CDD00B12BB06CB450B58BEC86F637E79
+PT=EAC4FE6F8A04871AC434322CB06308E3
+CT=64B6BA31C6B15BE040DC2C0A07FFE60F
+
+I=321
+KEY=2082C6C0D49B4DECA966B1237DB790A54B8492C2689C9876
+PT=64B6BA31C6B15BE040DC2C0A07FFE60F
+CT=5ECDC37FEA4176145C6A308F91659D43
+
+I=322
+KEY=23668EEA68987F8CF7AB725C97F6E6B117EEA24DF9F90535
+PT=5ECDC37FEA4176145C6A308F91659D43
+CT=BB25C81945A062A7D53531593D9910F6
+
+I=323
+KEY=10B544566773DD5F4C8EBA45D2568416C2DB9314C46015C3
+PT=BB25C81945A062A7D53531593D9910F6
+CT=48D98FFFC4E378D42CFC785B53DFC38D
+
+I=324
+KEY=7F96DD27E1C0B7B7045735BA16B5FCC2EE27EB4F97BFD64E
+PT=48D98FFFC4E378D42CFC785B53DFC38D
+CT=7DCE20BAE8345CB68103461B4AFA9F09
+
+I=325
+KEY=A73354FC47570B2679991500FE81A0746F24AD54DD454947
+PT=7DCE20BAE8345CB68103461B4AFA9F09
+CT=099B315B4DD55CAB5D02163154DA521C
+
+I=326
+KEY=92A57B873A1D292F7002245BB354FCDF3226BB65899F1B5B
+PT=099B315B4DD55CAB5D02163154DA521C
+CT=37207C17099989D3EA0D13DBD6DF7FEF
+
+I=327
+KEY=7048AF52E1763E8E4722584CBACD750CD82BA8BE5F4064B4
+PT=37207C17099989D3EA0D13DBD6DF7FEF
+CT=7CE37081A6751A1518F03B70FBC1479D
+
+I=328
+KEY=24E37AF6A4BC72403BC128CD1CB86F19C0DB93CEA4812329
+PT=7CE37081A6751A1518F03B70FBC1479D
+CT=201BBD8456F70ED0BB4E19A7AE36F1A6
+
+I=329
+KEY=17E541A643CB8EE01BDA95494A4F61C97B958A690AB7D28F
+PT=201BBD8456F70ED0BB4E19A7AE36F1A6
+CT=3384168E4F022049B0E3AD6899B71DC9
+
+I=330
+KEY=31D5A160B61690A0285E83C7054D4180CB7627019300CF46
+PT=3384168E4F022049B0E3AD6899B71DC9
+CT=C83AA6AE617CB17E2977D394EBC4AD19
+
+I=331
+KEY=6EBA775B83D704AAE06425696431F0FEE201F49578C4625F
+PT=C83AA6AE617CB17E2977D394EBC4AD19
+CT=8AC467890AF8E729C7A86A471ADEB378
+
+I=332
+KEY=C1237F715488582E6AA042E06EC917D725A99ED2621AD127
+PT=8AC467890AF8E729C7A86A471ADEB378
+CT=B89CE4F733A9D67C8E504BC4BC2F7664
+
+I=333
+KEY=0A9E4BDAD3E856F1D23CA6175D60C1ABABF9D516DE35A743
+PT=B89CE4F733A9D67C8E504BC4BC2F7664
+CT=47B421469B794A5188255ACE84D89721
+
+I=334
+KEY=4BE367B885F7AF9195888751C6198BFA23DC8FD85AED3062
+PT=47B421469B794A5188255ACE84D89721
+CT=B6B09DBF9E62C60951368C9C8B63A860
+
+I=335
+KEY=CDFB62995E4C5D4E23381AEE587B4DF372EA0344D18E9802
+PT=B6B09DBF9E62C60951368C9C8B63A860
+CT=68933B4BD0BC23EB3178347DFE68E7F6
+
+I=336
+KEY=8887EBF40DE51F064BAB21A588C76E18439237392FE67FF4
+PT=68933B4BD0BC23EB3178347DFE68E7F6
+CT=C6F16CDDF00C982A927609B559B0BCBD
+
+I=337
+KEY=221D949B8CA9F4C48D5A4D7878CBF632D1E43E8C7656C349
+PT=C6F16CDDF00C982A927609B559B0BCBD
+CT=CBEE831F7623E3214E72AF57706525C7
+
+I=338
+KEY=3D35666DACEFF3C846B4CE670EE815139F9691DB0633E68E
+PT=CBEE831F7623E3214E72AF57706525C7
+CT=DFE0297AE9B69F0AD69D6189C1447333
+
+I=339
+KEY=43370C9C958216DC9954E71DE75E8A19490BF052C77795BD
+PT=DFE0297AE9B69F0AD69D6189C1447333
+CT=59C3B4D6055B9F73064B715CD5213C99
+
+I=340
+KEY=DF43233D68EE5C4AC09753CBE205156A4F40810E1256A924
+PT=59C3B4D6055B9F73064B715CD5213C99
+CT=5373F13BB16B3653FCC138FC9A9E8A47
+
+I=341
+KEY=472E0A65B06B4F4693E4A2F0536E2339B381B9F288C82363
+PT=5373F13BB16B3653FCC138FC9A9E8A47
+CT=9C7514B7FEDF2DC26B0C2C1954745077
+
+I=342
+KEY=1409E4DF955583A00F91B647ADB10EFBD88D95EBDCBC7314
+PT=9C7514B7FEDF2DC26B0C2C1954745077
+CT=2480D7C35D6B0207D84A9CEFA1C2CFDC
+
+I=343
+KEY=458552CAB6B1A8AC2B116184F0DA0CFC00C709047D7EBCC8
+PT=2480D7C35D6B0207D84A9CEFA1C2CFDC
+CT=46DE3E51F1355FA76652C8DA3642409B
+
+I=344
+KEY=2065D6F033E1EE2E6DCF5FD501EF535B6695C1DE4B3CFC53
+PT=46DE3E51F1355FA76652C8DA3642409B
+CT=13F328173D057A64DA3917468528DB4F
+
+I=345
+KEY=6D30053E2C95BC5A7E3C77C23CEA293FBCACD698CE14271C
+PT=13F328173D057A64DA3917468528DB4F
+CT=33D71B6CD0A68B685C89C9F2D70FDFCE
+
+I=346
+KEY=59D69C2D25BFB6A34DEB6CAEEC4CA257E0251F6A191BF8D2
+PT=33D71B6CD0A68B685C89C9F2D70FDFCE
+CT=8E9F57B5E945CD7DFC2B9FCD5AF96DFB
+
+I=347
+KEY=F41ABD021E5C144EC3743B1B05096F2A1C0E80A743E29529
+PT=8E9F57B5E945CD7DFC2B9FCD5AF96DFB
+CT=71295B41B9E5872E1BD4D5C3C4C62D71
+
+I=348
+KEY=41C1194732CD4654B25D605ABCECE80407DA55648724B858
+PT=71295B41B9E5872E1BD4D5C3C4C62D71
+CT=E704FBBAA917788CE906A54B2A56A232
+
+I=349
+KEY=AF58932371569CE655599BE015FB9088EEDCF02FAD721A6A
+PT=E704FBBAA917788CE906A54B2A56A232
+CT=8DBA56CF3E019B8EA80CCB772551CA5B
+
+I=350
+KEY=B1E68A05A144F4FAD8E3CD2F2BFA0B0646D03B588823D031
+PT=8DBA56CF3E019B8EA80CCB772551CA5B
+CT=18F8A23F785AFEFC4ECD527AC6DBE609
+
+I=351
+KEY=456D39FF40B1622BC01B6F1053A0F5FA081D69224EF83638
+PT=18F8A23F785AFEFC4ECD527AC6DBE609
+CT=073F93A707D6B9A82E99990CB13BD00E
+
+I=352
+KEY=1FF446993B6927C6C724FCB754764C522684F02EFFC3E636
+PT=073F93A707D6B9A82E99990CB13BD00E
+CT=76723E1239356EDC37FB5E1EAFDF4678
+
+I=353
+KEY=0DED89E36C3B06B9B156C2A56D43228E117FAE30501CA04E
+PT=76723E1239356EDC37FB5E1EAFDF4678
+CT=1B57D35B4E2484D3945B82D59114A531
+
+I=354
+KEY=E433448EB970D64FAA0111FE2367A65D85242CE5C108057F
+PT=1B57D35B4E2484D3945B82D59114A531
+CT=4466DCB75F6B83885EE32D9FD533A902
+
+I=355
+KEY=3751EC4737F029E3EE67CD497C0C25D5DBC7017A143BAC7D
+PT=4466DCB75F6B83885EE32D9FD533A902
+CT=A8B62B9FCAA9331A3282899DB475AADE
+
+I=356
+KEY=6C1042FACD259CC346D1E6D6B6A516CFE94588E7A04E06A3
+PT=A8B62B9FCAA9331A3282899DB475AADE
+CT=DFE1CB42B29F119E44F37F60A8C2BD7C
+
+I=357
+KEY=640D2DB3E708999A99302D94043A0751ADB6F787088CBBDF
+PT=DFE1CB42B29F119E44F37F60A8C2BD7C
+CT=891B211EE1BEA05AD7BA478FDFEBC507
+
+I=358
+KEY=C434FF9BD02BDF6C102B0C8AE584A70B7A0CB008D7677ED8
+PT=891B211EE1BEA05AD7BA478FDFEBC507
+CT=16ABB92A1E0F433250C551F84AE177CF
+
+I=359
+KEY=22A76DAFC8A7748E0680B5A0FB8BE4392AC9E1F09D860917
+PT=16ABB92A1E0F433250C551F84AE177CF
+CT=1A2F4BF6ED0CADB7FA3FC52F3C6AF191
+
+I=360
+KEY=5DDEDF839CF5C0D11CAFFE561687498ED0F624DFA1ECF886
+PT=1A2F4BF6ED0CADB7FA3FC52F3C6AF191
+CT=16AE687EE38FB85C0F70E20F5585F750
+
+I=361
+KEY=13D0157C6A30C26C0A019628F508F1D2DF86C6D0F4690FD6
+PT=16AE687EE38FB85C0F70E20F5585F750
+CT=6CD2D70F641B2A7814014177C4880107
+
+I=362
+KEY=6DBFF188E61696C966D341279113DBAACB8787A730E10ED1
+PT=6CD2D70F641B2A7814014177C4880107
+CT=8CAD28041AE53AA64CE0173DBD9046C2
+
+I=363
+KEY=44A13B269C44F018EA7E69238BF6E10C8767909A8D714813
+PT=8CAD28041AE53AA64CE0173DBD9046C2
+CT=FC8D4274BA1EF15CC39E750DD1848F7B
+
+I=364
+KEY=B7A8311B81A3B82C16F32B5731E8105044F9E5975CF5C768
+PT=FC8D4274BA1EF15CC39E750DD1848F7B
+CT=01CBDAEAADE486CF655401D8F7F7E84E
+
+I=365
+KEY=A3AC668823C917DE1738F1BD9C0C969F21ADE44FAB022F26
+PT=01CBDAEAADE486CF655401D8F7F7E84E
+CT=494C3219700E06EE9C4DCB61EF932FDF
+
+I=366
+KEY=05CC07DC3CBB1A4B5E74C3A4EC029071BDE02F2E449100F9
+PT=494C3219700E06EE9C4DCB61EF932FDF
+CT=BB0E7D5CD93B1839DF5CAED7996F9560
+
+I=367
+KEY=8768468EFC3CE954E57ABEF83539884862BC81F9DDFE9599
+PT=BB0E7D5CD93B1839DF5CAED7996F9560
+CT=CC1F9A504A67C24621ED127C63AE2A36
+
+I=368
+KEY=470E251F98662CEC296524A87F5E4A0E43519385BE50BFAF
+PT=CC1F9A504A67C24621ED127C63AE2A36
+CT=A48D3751956B71F925680073B35BC0A3
+
+I=369
+KEY=533C67C061CE6B9E8DE813F9EA353BF7663993F60D0B7F0C
+PT=A48D3751956B71F925680073B35BC0A3
+CT=80143AC021E94718146EBC7808A9DDD8
+
+I=370
+KEY=0303563B9274349D0DFC2939CBDC7CEF72572F8E05A2A2D4
+PT=80143AC021E94718146EBC7808A9DDD8
+CT=B90AC6ADEE1B60228096D022EE5C681B
+
+I=371
+KEY=1E7D3A52CC112BDCB4F6EF9425C71CCDF2C1FFACEBFECACF
+PT=B90AC6ADEE1B60228096D022EE5C681B
+CT=CB8553B21250642107E824E8FB27CAEA
+
+I=372
+KEY=750A36009059323E7F73BC26379778ECF529DB4410D90025
+PT=CB8553B21250642107E824E8FB27CAEA
+CT=9C86DA9646FCFEA7E778A5498F50E01E
+
+I=373
+KEY=6876C614C460B02CE3F566B0716B864B12517E0D9F89E03B
+PT=9C86DA9646FCFEA7E778A5498F50E01E
+CT=1481357AD5690762FD6F3809F1E5F219
+
+I=374
+KEY=7CE6B00F6B651FAEF77453CAA4028129EF3E46046E6C1222
+PT=1481357AD5690762FD6F3809F1E5F219
+CT=39B64998D4370E0CB47C1DC23EDCDD03
+
+I=375
+KEY=C3F72A84EF6F4A0CCEC21A5270358F255B425BC650B0CF21
+PT=39B64998D4370E0CB47C1DC23EDCDD03
+CT=EB1BA96272D7BB044A3381439BA4CD5B
+
+I=376
+KEY=C670185A26E7DA4A25D9B33002E234211171DA85CB14027A
+PT=EB1BA96272D7BB044A3381439BA4CD5B
+CT=F87EC3D7F55DA25790718E461BA2E194
+
+I=377
+KEY=72ECF820AC459D8DDDA770E7F7BF9676810054C3D0B6E3EE
+PT=F87EC3D7F55DA25790718E461BA2E194
+CT=AD7EA1621AD7FBA975D6BB0AB9AED116
+
+I=378
+KEY=CE4ECAD1C7D17D1170D9D185ED686DDFF4D6EFC9691832F8
+PT=AD7EA1621AD7FBA975D6BB0AB9AED116
+CT=473B6484F6EAE1FC837A2710AE8D462F
+
+I=379
+KEY=3273752C9A8682F237E2B5011B828C2377ACC8D9C79574D7
+PT=473B6484F6EAE1FC837A2710AE8D462F
+CT=0E3634529E49692762F4D80333738045
+
+I=380
+KEY=8C2CFBB98A4E5E3839D4815385CBE504155810DAF4E6F492
+PT=0E3634529E49692762F4D80333738045
+CT=F8EFEBD78C115CC620F25AB66038F2A0
+
+I=381
+KEY=0416DBCAFA0850D8C13B6A8409DAB9C235AA4A6C94DE0632
+PT=F8EFEBD78C115CC620F25AB66038F2A0
+CT=B4442C38E3B8E87D8AAE2C17A5571CE9
+
+I=382
+KEY=7A7815A748696E99757F46BCEA6251BFBF04667B31891ADB
+PT=B4442C38E3B8E87D8AAE2C17A5571CE9
+CT=576A20E194015AB069D769FCA7D842FC
+
+I=383
+KEY=3848903CD019B4572215665D7E630B0FD6D30F8796515827
+PT=576A20E194015AB069D769FCA7D842FC
+CT=E253D9FB4075B021DF452B3AD51204D6
+
+I=384
+KEY=3E468D281DF03284C046BFA63E16BB2E099624BD43435CF1
+PT=E253D9FB4075B021DF452B3AD51204D6
+CT=D9454AE62207E70A34F13B0063498A8F
+
+I=385
+KEY=860E4E60B132A8851903F5401C115C243D671FBD200AD67E
+PT=D9454AE62207E70A34F13B0063498A8F
+CT=A21F7DA8A298670D631F677D23504757
+
+I=386
+KEY=27B82EDF5FFD15DDBB1C88E8BE893B295E7878C0035A9129
+PT=A21F7DA8A298670D631F677D23504757
+CT=1D239EFBABD09A029FE11C59A385C909
+
+I=387
+KEY=631BCB74800FD13AA63F16131559A12BC1996499A0DF5820
+PT=1D239EFBABD09A029FE11C59A385C909
+CT=C87EB2AB019AFA608BE99CE77717B333
+
+I=388
+KEY=EE1326871289985E6E41A4B814C35B4B4A70F87ED7C8EB13
+PT=C87EB2AB019AFA608BE99CE77717B333
+CT=528DBF70307431E33815D1AA44C30FA8
+
+I=389
+KEY=F1D72A84C2FE044F3CCC1BC824B76AA8726529D4930BE4BB
+PT=528DBF70307431E33815D1AA44C30FA8
+CT=6C8014B427ED6331A5C174CF2846B70A
+
+I=390
+KEY=A1610602C8DD2836504C0F7C035A0999D7A45D1BBB4D53B1
+PT=6C8014B427ED6331A5C174CF2846B70A
+CT=3DF4C4BE003A13030E73026F7027ADB1
+
+I=391
+KEY=B2418E725A1435DD6DB8CBC203601A9AD9D75F74CB6AFE00
+PT=3DF4C4BE003A13030E73026F7027ADB1
+CT=39C50365300DCC5B47F827054879C642
+
+I=392
+KEY=761AF29E74671706547DC8A7336DD6C19E2F787183133842
+PT=39C50365300DCC5B47F827054879C642
+CT=847F488B3CEC2E1E4E1C6B9F37E4F631
+
+I=393
+KEY=C912116E7B47169AD002802C0F81F8DFD03313EEB4F7CE73
+PT=847F488B3CEC2E1E4E1C6B9F37E4F631
+CT=9A581179C883C5E057CC560A3DF6CD34
+
+I=394
+KEY=B08B1226353C6BD34A5A9155C7023D3F87FF45E489010347
+PT=9A581179C883C5E057CC560A3DF6CD34
+CT=799B437C3EF3663EFBD6F186EDFDF21A
+
+I=395
+KEY=1ECAE821E161A2C833C1D229F9F15B017C29B46264FCF15D
+PT=799B437C3EF3663EFBD6F186EDFDF21A
+CT=138A858B14FE28D9A47C76BB3FAE9AA1
+
+I=396
+KEY=3AD2B951E451EEA8204B57A2ED0F73D8D855C2D95B526BFC
+PT=138A858B14FE28D9A47C76BB3FAE9AA1
+CT=5E35BC76C5AC8765A6C396DFE5689579
+
+I=397
+KEY=791E5F91477E986E7E7EEBD428A3F4BD7E965406BE3AFE85
+PT=5E35BC76C5AC8765A6C396DFE5689579
+CT=53F8361BF47A82EF27492322BA6F57AD
+
+I=398
+KEY=194A170B3D4FA6E62D86DDCFDCD9765259DF77240455A928
+PT=53F8361BF47A82EF27492322BA6F57AD
+CT=FF626D77AE144C11480610EC1ABB5028
+
+I=399
+KEY=C9DC82F000187721D2E4B0B872CD3A4311D967C81EEEF900
+PT=FF626D77AE144C11480610EC1ABB5028
+CT=4E46F8C5092B29E29A971A0CD1F610FB
+
+=========================
+
+KEYSIZE=256
+
+I=0
+KEY=0000000000000000000000000000000000000000000000000000000000000000
+PT=00000000000000000000000000000000
+CT=8B79EECC93A0EE5DFF30B4EA21636DA4
+
+I=1
+KEY=AD3965683E6FA98B5F38AC26653679288B79EECC93A0EE5DFF30B4EA21636DA4
+PT=8B79EECC93A0EE5DFF30B4EA21636DA4
+CT=C737317FE0846F132B23C8C2A672CE22
+
+I=2
+KEY=28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386
+PT=C737317FE0846F132B23C8C2A672CE22
+CT=E58B82BFBA53C0040DC610C642121168
+
+I=3
+KEY=0721E93EACF9DC6C870D8133376B7C0DA9C55D0CC977414AD9D56CEEC503B2EE
+PT=E58B82BFBA53C0040DC610C642121168
+CT=10B296ABB40504995DB71DDA0B7E26FB
+
+I=4
+KEY=0ECE1E210ADA32EBC497AD50F516602EB977CBA77D7245D384627134CE7D9415
+PT=10B296ABB40504995DB71DDA0B7E26FB
+CT=B7198D8E88BAA25234C18517E99BB70D
+
+I=5
+KEY=D31313ACD90A9BB7D6596DEAB752003F0E6E4629F5C8E781B0A3F42327E62318
+PT=B7198D8E88BAA25234C18517E99BB70D
+CT=6125097DB5738C64513E125872EA436C
+
+I=6
+KEY=488B6A78D9AA23FEA7289E250928BDE36F4B4F5440BB6BE5E19DE67B550C6074
+PT=6125097DB5738C64513E125872EA436C
+CT=07FF2ED24B522F1E31D46E94BE5C505B
+
+I=7
+KEY=03DDD56B142AD3B0E4FFD2BAC6568E5468B461860BE944FBD04988EFEB50302F
+PT=07FF2ED24B522F1E31D46E94BE5C505B
+CT=EB3C1E3328F840B110E934B0129F2F23
+
+I=8
+KEY=20F9D92C65B2F00183464197B23BE5AF83887FB52311044AC0A0BC5FF9CF1F0C
+PT=EB3C1E3328F840B110E934B0129F2F23
+CT=107CB7B403DC3F6F09EC30EC1718D183
+
+I=9
+KEY=79CF0BCF8EFE3DE82E27778923D1AA1993F4C80120CD3B25C94C8CB3EED7CE8F
+PT=107CB7B403DC3F6F09EC30EC1718D183
+CT=CE9DB77B1FAE0CFEC5341FA5AF4CDE8A
+
+I=10
+KEY=F50ADABA26525BFA7BF6EEF2402450785D697F7A3F6337DB0C789316419B1005
+PT=CE9DB77B1FAE0CFEC5341FA5AF4CDE8A
+CT=157B5946862DA3E9A1A83E45857E207D
+
+I=11
+KEY=3B6947995411D0AE50645129D13BACC04812263CB94E9432ADD0AD53C4E53078
+PT=157B5946862DA3E9A1A83E45857E207D
+CT=4AE3583491DF78918CAB3AC241286855
+
+I=12
+KEY=AAD12F02F5E5681D16236B668EF2C46702F17E082891ECA3217B979185CD582D
+PT=4AE3583491DF78918CAB3AC241286855
+CT=05400C32DC84F1AB486A9BADB1415B50
+
+I=13
+KEY=EA02EB82D4B2112DD3BD64C1C908CEC307B1723AF4151D0869110C3C348C037D
+PT=05400C32DC84F1AB486A9BADB1415B50
+CT=E4C0781A2EA68D142504739731EF396E
+
+I=14
+KEY=D51A1846DFEB738F0AF138F74C968DCCE3710A20DAB3901C4C157FAB05633A13
+PT=E4C0781A2EA68D142504739731EF396E
+CT=44CC8A9C84E6AD66BD24F1EE1F925EC3
+
+I=15
+KEY=B6401DFC35AF21E53CD254431CC639E9A7BD80BC5E553D7AF1318E451AF164D0
+PT=44CC8A9C84E6AD66BD24F1EE1F925EC3
+CT=20AF5FDDF65856D1A60ADC03567AE163
+
+I=16
+KEY=D1D2E8B5644910077B3EDB245F029C0D8712DF61A80D6BAB573B52464C8B85B3
+PT=20AF5FDDF65856D1A60ADC03567AE163
+CT=CEB74DD6FBEAFDCEE54930D58AF22ACA
+
+I=17
+KEY=9F932DC2AB83FA5153E7081E7360ABB449A592B753E79665B2726293C679AF79
+PT=CEB74DD6FBEAFDCEE54930D58AF22ACA
+CT=72FB3F7BBBDBA9C036C94531A32E937D
+
+I=18
+KEY=06AABCA83922297791C9D07AEB639BDD3B5EADCCE83C3FA584BB27A265573C04
+PT=72FB3F7BBBDBA9C036C94531A32E937D
+CT=299B26D5D6DFA2C20824D8A84E98A244
+
+I=19
+KEY=6124BC71768DE5E9C14D37915D90F1AE12C58B193EE39D678C9FFF0A2BCF9E40
+PT=299B26D5D6DFA2C20824D8A84E98A244
+CT=0A35C0D4170BDE0258D79B668C7C98F4
+
+I=20
+KEY=282B067BD441670E11E576F26C4EA67D18F04BCD29E84365D448646CA7B306B4
+PT=0A35C0D4170BDE0258D79B668C7C98F4
+CT=F4E3E981FFC8B50FC9146B85A22E71D4
+
+I=21
+KEY=2864E2A3986F99C55EC21C225E3498ECEC13A24CD620F66A1D5C0FE9059D7760
+PT=F4E3E981FFC8B50FC9146B85A22E71D4
+CT=130ACF4CEAFE3277DF057D4D170582ED
+
+I=22
+KEY=600FD4DFD03132B0DB7B2432DBE027C2FF196D003CDEC41DC25972A41298F58D
+PT=130ACF4CEAFE3277DF057D4D170582ED
+CT=50001D54F2EA5EAA3BE2206F3845D9A9
+
+I=23
+KEY=C1CBE3A1679D6C1913EABE3400993100AF197054CE349AB7F9BB52CB2ADD2C24
+PT=50001D54F2EA5EAA3BE2206F3845D9A9
+CT=69F3EE4B230B2DB2492FE0E36B949154
+
+I=24
+KEY=7C6C63E14606A0B09254A531CACB45A0C6EA9E1FED3FB705B094B2284149BD70
+PT=69F3EE4B230B2DB2492FE0E36B949154
+CT=CEEE40F3D2FD9A5521F44AD3AB55198D
+
+I=25
+KEY=22BB6E21BCA0450240DB117B028837AF0804DEEC3FC22D509160F8FBEA1CA4FD
+PT=CEEE40F3D2FD9A5521F44AD3AB55198D
+CT=1FA1F1AE7BF2A8C66A6ED6D5F276846B
+
+I=26
+KEY=7364D9AE40CBB0CCA6640B7E542DBA2617A52F4244308596FB0E2E2E186A2096
+PT=1FA1F1AE7BF2A8C66A6ED6D5F276846B
+CT=6D5BD8391C73507D57B902AB3D58D228
+
+I=27
+KEY=A2D8BF7602FCD22755ADA9979B2DD33B7AFEF77B5843D5EBACB72C852532F2BE
+PT=6D5BD8391C73507D57B902AB3D58D228
+CT=15ACD05539318363F275C857FBC5D86C
+
+I=28
+KEY=3AD56A33CE89D8D3510C4152DEE734126F52272E617256885EC2E4D2DEF72AD2
+PT=15ACD05539318363F275C857FBC5D86C
+CT=B54F8D944301A899A2A88440FE8AB631
+
+I=29
+KEY=13ED08137C66C2000D3FE9E167387864DA1DAABA2273FE11FC6A6092207D9CE3
+PT=B54F8D944301A899A2A88440FE8AB631
+CT=23B4BF936BF383325F0DAF0548E32851
+
+I=30
+KEY=3C2C53CCDB4721F44B6C057BF758361AF9A9152949807D23A367CF97689EB4B2
+PT=23B4BF936BF383325F0DAF0548E32851
+CT=8B4984C6F39C7FD543B4A8629EAC6740
+
+I=31
+KEY=95E744B66044529E2DC2B06BF84FF3D672E091EFBA1C02F6E0D367F5F632D3F2
+PT=8B4984C6F39C7FD543B4A8629EAC6740
+CT=108834058381578E8AA7988E03942230
+
+I=32
+KEY=E7715B09238876A93F9858D9548CBEA56268A5EA399D55786A74FF7BF5A6F1C2
+PT=108834058381578E8AA7988E03942230
+CT=EE3974A2ECEA5A1E6FC09535323BFF29
+
+I=33
+KEY=08F25145082684F576933E4DF5C63DFE8C51D148D5770F6605B46A4EC79D0EEB
+PT=EE3974A2ECEA5A1E6FC09535323BFF29
+CT=1AC80F42E3529BCA587D4EA828BD3631
+
+I=34
+KEY=93D63C9069B415595934FA66C76A9CD09699DE0A362594AC5DC924E6EF2038DA
+PT=1AC80F42E3529BCA587D4EA828BD3631
+CT=E196DF1E8A0DE844EBD3FD84B307EEB6
+
+I=35
+KEY=0F5E4A3907A7BC56AAC2CB6F6871674C770F0114BC287CE8B61AD9625C27D66C
+PT=E196DF1E8A0DE844EBD3FD84B307EEB6
+CT=917AC29C88967EE5C792E72B046A4399
+
+I=36
+KEY=B935C42A3A93D1E45E94CBE1E232A135E675C38834BE020D71883E49584D95F5
+PT=917AC29C88967EE5C792E72B046A4399
+CT=9CE3D545895005F3EC432699F17FFDA2
+
+I=37
+KEY=CC3C0DCF9E6E91BE48B7F7AE251D1CB37A9616CDBDEE07FE9DCB18D0A9326857
+PT=9CE3D545895005F3EC432699F17FFDA2
+CT=089F0D41397E27B04D3268834ADF932C
+
+I=38
+KEY=29AB63D0AB0E237BA75D250BC67E362472091B8C8490204ED0F97053E3EDFB7B
+PT=089F0D41397E27B04D3268834ADF932C
+CT=9C364B0CC209389C00824505226B8989
+
+I=39
+KEY=7FB99ABACCC92D9C8B17CC0066F02F39EE3F5080469918D2D07B3556C18672F2
+PT=9C364B0CC209389C00824505226B8989
+CT=767FB14493BE17A29839FBF115B9B38B
+
+I=40
+KEY=DB08EEBD184AEEB002302A3C41E5595B9840E1C4D5270F704842CEA7D43FC179
+PT=767FB14493BE17A29839FBF115B9B38B
+CT=CBEC5B7FB05D673C19EBF0F4B647CDB5
+
+I=41
+KEY=F7C517C27F319857F1D9DA5D29B6B76353ACBABB657A684C51A93E5362780CCC
+PT=CBEC5B7FB05D673C19EBF0F4B647CDB5
+CT=9721CB9555EF079ADD547D8DE09CC0C7
+
+I=42
+KEY=47D5164E15743853C8B0E55ED3A965D6C48D712E30956FD68CFD43DE82E4CC0B
+PT=9721CB9555EF079ADD547D8DE09CC0C7
+CT=5B16109122E874A08A2A48D5B5753256
+
+I=43
+KEY=152E7EF1B0FAD417DA84B4FA0AB560DB9F9B61BF127D1B7606D70B0B3791FE5D
+PT=5B16109122E874A08A2A48D5B5753256
+CT=198A9B7C41C225334176614A16F1D7CB
+
+I=44
+KEY=81BB271A9F0CE56E452C9FBE4CF09FF88611FAC353BF3E4547A16A4121602996
+PT=198A9B7C41C225334176614A16F1D7CB
+CT=56E255DB999AFA713020C4E987F4433B
+
+I=45
+KEY=A654ABA71B351BCBFD1CB03B5F88CE1AD0F3AF18CA25C4347781AEA8A6946AAD
+PT=56E255DB999AFA713020C4E987F4433B
+CT=7BF8470233D197839D4FC1B365E79C8D
+
+I=46
+KEY=C700B39660C3C72E15E278B2D22DD528AB0BE81AF9F453B7EACE6F1BC373F620
+PT=7BF8470233D197839D4FC1B365E79C8D
+CT=D7CDF94CBBE5E7EF7E47E4CE9BD5E073
+
+I=47
+KEY=C49B1589810F1915998C8C79CA2382D87CC611564211B45894898BD558A61653
+PT=D7CDF94CBBE5E7EF7E47E4CE9BD5E073
+CT=A5617B71AF28E732A0B69BFA3B90F291
+
+I=48
+KEY=D37A9390FD2C8D4D01704352BAFC2EE2D9A76A27ED39536A343F102F6336E4C2
+PT=A5617B71AF28E732A0B69BFA3B90F291
+CT=156D08F6A2AC3F7202DBEE15D53C8BCD
+
+I=49
+KEY=E4E2958608635DF83B8E39FD503356D5CCCA62D14F956C1836E4FE3AB60A6F0F
+PT=156D08F6A2AC3F7202DBEE15D53C8BCD
+CT=1790CB4B9B4E01F4CA3AAB588A3B7A51
+
+I=50
+KEY=B0F77AF53FB1FAF66A421093111DC925DB5AA99AD4DB6DECFCDE55623C31155E
+PT=1790CB4B9B4E01F4CA3AAB588A3B7A51
+CT=5E2DC515FE9BAE8F16188DC052C63A80
+
+I=51
+KEY=487CA8ECBA3E2CAF61A16285005F01F685776C8F2A40C363EAC6D8A26EF72FDE
+PT=5E2DC515FE9BAE8F16188DC052C63A80
+CT=A625E46D2DA293F536D25C9207090AA5
+
+I=52
+KEY=410909F6119DDA628537B825D24E8DF9235288E207E25096DC14843069FE257B
+PT=A625E46D2DA293F536D25C9207090AA5
+CT=FEFCF38ABD12EAAD37F3AE73BC4B4A8C
+
+I=53
+KEY=F1027D98B61D2F383BCF60A83D317D03DDAE7B68BAF0BA3BEBE72A43D5B56FF7
+PT=FEFCF38ABD12EAAD37F3AE73BC4B4A8C
+CT=76D8221C2AAD44D226C769875A93CDA8
+
+I=54
+KEY=DDA104019F122286887545C85F6B09B1AB765974905DFEE9CD2043C48F26A25F
+PT=76D8221C2AAD44D226C769875A93CDA8
+CT=DE7FBEB010089D7EE0A1BD18F3461AEE
+
+I=55
+KEY=46CE686778BA955831B63F2ACFE397747509E7C4805563972D81FEDC7C60B8B1
+PT=DE7FBEB010089D7EE0A1BD18F3461AEE
+CT=A8B0824BD1FC52D92AFA0B4B23ABDEBD
+
+I=56
+KEY=EF1408D365E549B808DADADE3D4CBCDADDB9658F51A9314E077BF5975FCB660C
+PT=A8B0824BD1FC52D92AFA0B4B23ABDEBD
+CT=93AC85EE8DE4091894F0E1800A0DF443
+
+I=57
+KEY=8E8FC86B7F82A57799FE32DD1C748C8D4E15E061DC4D3856938B141755C6924F
+PT=93AC85EE8DE4091894F0E1800A0DF443
+CT=0FAE963D9B74341316D7EA8862D0766F
+
+I=58
+KEY=D3900458ABB1ACCE0707A49565D27C4C41BB765C47390C45855CFE9F3716E420
+PT=0FAE963D9B74341316D7EA8862D0766F
+CT=37930DFBC771510D0BBDCBFAB2A5852F
+
+I=59
+KEY=C55EE2F5633DE3E7EF3710C6C143AA7076287BA780485D488EE1356585B3610F
+PT=37930DFBC771510D0BBDCBFAB2A5852F
+CT=9C3B82D06CB9378F6CBBF6325B456A8B
+
+I=60
+KEY=AA16073435B24614EB1E9AE81FD921F0EA13F977ECF16AC7E25AC357DEF60B84
+PT=9C3B82D06CB9378F6CBBF6325B456A8B
+CT=2DB135F2599323714B4D0E66562FAF48
+
+I=61
+KEY=033F102BFB13F9F84A4E9FC0C6F52AC8C7A2CC85B56249B6A917CD3188D9A4CC
+PT=2DB135F2599323714B4D0E66562FAF48
+CT=130D64DC60EE70F07F6A68F26A9B5E19
+
+I=62
+KEY=60D36FD89196DB13031E829B54615707D4AFA859D58C3946D67DA5C3E242FAD5
+PT=130D64DC60EE70F07F6A68F26A9B5E19
+CT=E4E5C4A1E2A0DC99EEC583E311824371
+
+I=63
+KEY=532BC273D1843EB5CC1DE01D28684454304A6CF8372CE5DF38B82620F3C0B9A4
+PT=E4E5C4A1E2A0DC99EEC583E311824371
+CT=72CCE240749A6BFD0A93CDCBE2589B41
+
+I=64
+KEY=DAE91111E43D9DF4A0F44C27A6B1AB0842868EB843B68E22322BEBEB119822E5
+PT=72CCE240749A6BFD0A93CDCBE2589B41
+CT=300F85629B48F47444D2AA51EBAAD16C
+
+I=65
+KEY=5C7C95B43BEA70F20A5C490F9A9F716372890BDAD8FE7A5676F941BAFA32F389
+PT=300F85629B48F47444D2AA51EBAAD16C
+CT=89278608A583E1243704B39AB9C0F30C
+
+I=66
+KEY=5B64FDB468399A031D5745325331C2E8FBAE8DD27D7D9B7241FDF22043F20085
+PT=89278608A583E1243704B39AB9C0F30C
+CT=71B74D5FAA4558A59F3BC91AA564579A
+
+I=67
+KEY=0166230CCF036B4B22C63D36F71C3CF58A19C08DD738C3D7DEC63B3AE696571F
+PT=71B74D5FAA4558A59F3BC91AA564579A
+CT=7B433C70951E4BD140FF7A0CBF367429
+
+I=68
+KEY=D7A12389D7DD5DE963841B344315ADF9F15AFCFD422688069E39413659A02336
+PT=7B433C70951E4BD140FF7A0CBF367429
+CT=B0BE67EBCD672549AF03D323AF026FFF
+
+I=69
+KEY=A3EC2E92C58FE150F708C6FAEB1F459E41E49B168F41AD4F313A9215F6A24CC9
+PT=B0BE67EBCD672549AF03D323AF026FFF
+CT=99A829A7C5C7CD6A44C7EABA9A5421C7
+
+I=70
+KEY=CC3F7485BF8460CB1EA0AA3C20553644D84CB2B14A86602575FD78AF6CF66D0E
+PT=99A829A7C5C7CD6A44C7EABA9A5421C7
+CT=76E1A70AF79F89CFE68EAF15DC0E9BC5
+
+I=71
+KEY=17DC64F06B3A2941A21AE58E2FFAB363AEAD15BBBD19E9EA9373D7BAB0F8F6CB
+PT=76E1A70AF79F89CFE68EAF15DC0E9BC5
+CT=DB0805B5DCC1CA2CA7489C8E1237E7A2
+
+I=72
+KEY=DC7128E894C9DA167D0ACED5888F846275A5100E61D823C6343B4B34A2CF1169
+PT=DB0805B5DCC1CA2CA7489C8E1237E7A2
+CT=935D409B87A85A2CFCC09DE3D2A9A294
+
+I=73
+KEY=8073895C9316D299F4F32C602F2F2616E6F85095E67079EAC8FBD6D77066B3FD
+PT=935D409B87A85A2CFCC09DE3D2A9A294
+CT=F22B73EFF24249CBCB31BDC7C126B735
+
+I=74
+KEY=99E16793433652800ABAD7000638560914D3237A1432302103CA6B10B14004C8
+PT=F22B73EFF24249CBCB31BDC7C126B735
+CT=A16A380AE9B3F2B0AE39BB0E24BF7C0A
+
+I=75
+KEY=8F77C5E97DA567CC447B52F45175BC74B5B91B70FD81C291ADF3D01E95FF78C2
+PT=A16A380AE9B3F2B0AE39BB0E24BF7C0A
+CT=9CF088DE60AE87687481C9F217E86A7C
+
+I=76
+KEY=DA1B3C2C424D2BC6A1C7A3D18D41C3F5294993AE9D2F45F9D97219EC821712BE
+PT=9CF088DE60AE87687481C9F217E86A7C
+CT=1C8B68951E65E32E77F1A31571351C1B
+
+I=77
+KEY=3D64F3D4BF8F585917273805AA43DCD735C2FB3B834AA6D7AE83BAF9F3220EA5
+PT=1C8B68951E65E32E77F1A31571351C1B
+CT=4AD3F3B0C15D810F0EA0FF62C6B2D0FE
+
+I=78
+KEY=51D61FB1B31EB55C7AA2D918E7BE32A97F11088B421727D8A023459B3590DE5B
+PT=4AD3F3B0C15D810F0EA0FF62C6B2D0FE
+CT=0DFCF7CA661572E050C522AE554A4BF8
+
+I=79
+KEY=B93510F7689FB9856194CF629EF63AAA72EDFF4124025538F0E6673560DA95A3
+PT=0DFCF7CA661572E050C522AE554A4BF8
+CT=7C185A5A68675DAC7A16C8DDE4B8CF8B
+
+I=80
+KEY=8496679D7598A1B91D2F221CF958F90B0EF5A51B4C6508948AF0AFE884625A28
+PT=7C185A5A68675DAC7A16C8DDE4B8CF8B
+CT=88FDDDA7BC2B09E48598A94474C64DC7
+
+I=81
+KEY=F27BCC0F919566675B129C526A4DC796860878BCF04E01700F6806ACF0A417EF
+PT=88FDDDA7BC2B09E48598A94474C64DC7
+CT=35C5C98C9C774D0BE9EFFB55C90B2F9C
+
+I=82
+KEY=05F12B58DBF5602D31CFD0EB10313502B3CDB1306C394C7BE687FDF939AF3873
+PT=35C5C98C9C774D0BE9EFFB55C90B2F9C
+CT=C3374B5C81646AC881F0F924C22A723B
+
+I=83
+KEY=FD05BE617555BC8184C2F46911C46B9E70FAFA6CED5D26B3677704DDFB854A48
+PT=C3374B5C81646AC881F0F924C22A723B
+CT=0CE756792AF27525A088700DB66D4399
+
+I=84
+KEY=3831345DFA5ADDF7CE8B5F76B5E1EBDE7C1DAC15C7AF5396C7FF74D04DE809D1
+PT=0CE756792AF27525A088700DB66D4399
+CT=401CD076E03C108A7FD79651407923E9
+
+I=85
+KEY=B101FDD95C23BE560262D355E09FC39B3C017C632793431CB828E2810D912A38
+PT=401CD076E03C108A7FD79651407923E9
+CT=88614E46C416E5164F2A63CDA9DD7B89
+
+I=86
+KEY=0B53859962A79D216E395830E36F8D45B4603225E385A60AF702814CA44C51B1
+PT=88614E46C416E5164F2A63CDA9DD7B89
+CT=7411856C8F14A2E5F6C5F1830302A66F
+
+I=87
+KEY=FE07E3B8961C2A1B3E34A50F8CFA1A45C071B7496C9104EF01C770CFA74EF7DE
+PT=7411856C8F14A2E5F6C5F1830302A66F
+CT=B0A815E93EBAC7A68F8BB420C8A5692D
+
+I=88
+KEY=9F2E0D3DB033B1929009D6C4C460B24F70D9A2A0522BC3498E4CC4EF6FEB9EF3
+PT=B0A815E93EBAC7A68F8BB420C8A5692D
+CT=AA6D27BB26275F5CB3EC3D6A8AFB80BF
+
+I=89
+KEY=5E903EF160161E1CA79A26D28FE32175DAB4851B740C9C153DA0F985E5101E4C
+PT=AA6D27BB26275F5CB3EC3D6A8AFB80BF
+CT=EAF7941A7E5D3907B6F52C1106EED2CE
+
+I=90
+KEY=60284EF35A9246CC32002028E4969309304311010A51A5128B55D594E3FECC82
+PT=EAF7941A7E5D3907B6F52C1106EED2CE
+CT=1178DD3DBDB1810E360E6FE09AA0D75C
+
+I=91
+KEY=300CB519F3203AD4589749651BD99AC7213BCC3CB7E0241CBD5BBA74795E1BDE
+PT=1178DD3DBDB1810E360E6FE09AA0D75C
+CT=584B48263DE541E93B29C6E570D4A6F4
+
+I=92
+KEY=2F79EA55D0E3EAF1D0DBD364A7D64E2A7970841A8A0565F586727C91098ABD2A
+PT=584B48263DE541E93B29C6E570D4A6F4
+CT=7B2EC27F2F1BC24EAD4FC0AA0519685C
+
+I=93
+KEY=8B46F59BF2C4B226523C203E8FD3936D025E4665A51EA7BB2B3DBC3B0C93D576
+PT=7B2EC27F2F1BC24EAD4FC0AA0519685C
+CT=13404D003576493EBB36C07C6D16A1B6
+
+I=94
+KEY=C7E75C30B0CE770A0075E3EBEB244811111E0B659068EE85900B7C47618574C0
+PT=13404D003576493EBB36C07C6D16A1B6
+CT=A083421A139DF68C8F863B337F3408BE
+
+I=95
+KEY=A957F876769BE9005DCEE4B7514FAC62B19D497F83F518091F8D47741EB17C7E
+PT=A083421A139DF68C8F863B337F3408BE
+CT=BF86650C9ECBD6C14B420FBE6B6E488B
+
+I=96
+KEY=FD4DE7532652D17C5ACCEA759C52A95C0E1B2C731D3ECEC854CF48CA75DF34F5
+PT=BF86650C9ECBD6C14B420FBE6B6E488B
+CT=75CEFAE872574AB6F26B0CAF6F08D858
+
+I=97
+KEY=54DBCDC0A57363DE6B3A032607E968C27BD5D69B6F69847EA6A444651AD7ECAD
+PT=75CEFAE872574AB6F26B0CAF6F08D858
+CT=8A3F9C96598883E9D3760C8A8FE406C6
+
+I=98
+KEY=AC10312E365401908F2C8AE371CB8C90F1EA4A0D36E1079775D248EF9533EA6B
+PT=8A3F9C96598883E9D3760C8A8FE406C6
+CT=B8B372C0CC6D164F340DF26B8F832DF8
+
+I=99
+KEY=64265CF02043C966C01DF5255F8D2867495938CDFA8C11D841DFBA841AB0C793
+PT=B8B372C0CC6D164F340DF26B8F832DF8
+CT=A7F6267A6F0CEB0EF7D07959EE065760
+
+I=100
+KEY=CF6B88FB273B247B8D64B5A323EF5760EEAF1EB79580FAD6B60FC3DDF4B690F3
+PT=A7F6267A6F0CEB0EF7D07959EE065760
+CT=AD96ADAC9B786AB78B1B46D9E026C935
+
+I=101
+KEY=4C8EEA35A90CB46AF32235997D2ADBBE4339B31B0EF890613D148504149059C6
+PT=AD96ADAC9B786AB78B1B46D9E026C935
+CT=FC7BAC9A5F64571AABF4B0A451C8D88D
+
+I=102
+KEY=0DD6D30191FABEC371CF0BA223BECF19BF421F81519CC77B96E035A04558814B
+PT=FC7BAC9A5F64571AABF4B0A451C8D88D
+CT=2B56E363834F27090FAC8061507A4787
+
+I=103
+KEY=2E69324E634312611C33F695A137AFE49414FCE2D2D3E072994CB5C11522C6CC
+PT=2B56E363834F27090FAC8061507A4787
+CT=FD37886E30CEFA28F8E8A5662A9EC5DC
+
+I=104
+KEY=8AFAC0C1507472CCB28B37CA88B7139D6923748CE21D1A5A61A410A73FBC0310
+PT=FD37886E30CEFA28F8E8A5662A9EC5DC
+CT=F7F36142C000D5162F789C392971FCE7
+
+I=105
+KEY=7DC5DA2A80219692F9F26C5934826DF29ED015CE221DCF4C4EDC8C9E16CDFFF7
+PT=F7F36142C000D5162F789C392971FCE7
+CT=D560607A0F0BE8320F2CEE56B155163F
+
+I=106
+KEY=3CC9AE3E3EB90B511C6D8CD74419D6944BB075B42D16277E41F062C8A798E9C8
+PT=D560607A0F0BE8320F2CEE56B155163F
+CT=708133FEB47A226A616900D46FA85037
+
+I=107
+KEY=8B84B7F96F9B3184D5B6402ECAE344CB3B31464A996C05142099621CC830B9FF
+PT=708133FEB47A226A616900D46FA85037
+CT=1B2ED9348FC7A4E4AD8BFCE2A148D1AD
+
+I=108
+KEY=655CB7606D17582441247D23E222ECCF201F9F7E16ABA1F08D129EFE69786852
+PT=1B2ED9348FC7A4E4AD8BFCE2A148D1AD
+CT=B2B726C8605A6F5CBA97F04E85A1F985
+
+I=109
+KEY=E0BA77DAAD3E3502AB9A6CEBEC654D0492A8B9B676F1CEAC37856EB0ECD991D7
+PT=B2B726C8605A6F5CBA97F04E85A1F985
+CT=CD7F53BB4AEB364A1D8630E0B5C4A6A2
+
+I=110
+KEY=1470D5E493B0E8212F02D4419C46A8CD5FD7EA0D3C1AF8E62A035E50591D3775
+PT=CD7F53BB4AEB364A1D8630E0B5C4A6A2
+CT=57271A960FE2170BA3F1987E694BBD16
+
+I=111
+KEY=415408E88421573F93FDBE25DD4B90C208F0F09B33F8EFED89F2C62E30568A63
+PT=57271A960FE2170BA3F1987E694BBD16
+CT=E9D47C3E926475FFDB783624C3ADB17B
+
+I=112
+KEY=40B3017DC81EEE4BF652AE8BB8CEED1DE1248CA5A19C9A12528AF00AF3FB3B18
+PT=E9D47C3E926475FFDB783624C3ADB17B
+CT=D78F96812BB55723E04BE8818C262485
+
+I=113
+KEY=9EABE9B3608ACE61684BAD3F3FED5C9736AB1A248A29CD31B2C1188B7FDD1F9D
+PT=D78F96812BB55723E04BE8818C262485
+CT=E2092227E1A3D2E525942090DA0A3F3E
+
+I=114
+KEY=B095E4F38E060016EBC4C42D3A4EFBD6D4A238036B8A1FD49755381BA5D720A3
+PT=E2092227E1A3D2E525942090DA0A3F3E
+CT=95E9EE1F56A65FF85B752FC300F525AE
+
+I=115
+KEY=9B2841F44291552EA04DE13E4E78011B414BD61C3D2C402CCC2017D8A522050D
+PT=95E9EE1F56A65FF85B752FC300F525AE
+CT=32D8465F2E11A04F8984FEE8E710CD25
+
+I=116
+KEY=67D8B10D0DDB61932E610EB077F0D85F73939043133DE06345A4E9304232C828
+PT=32D8465F2E11A04F8984FEE8E710CD25
+CT=2D9803ECFB95B2591FE56B3CBB4307F2
+
+I=117
+KEY=B0C80A38EDE23A549EF08E5DC3CEA2F25E0B93AFE8A8523A5A41820CF971CFDA
+PT=2D9803ECFB95B2591FE56B3CBB4307F2
+CT=4B19F9BCAFD471BF9014ADA19891E4E6
+
+I=118
+KEY=85C6DF29F9AEBA6087E3746BA5CF6C1515126A13477C2385CA552FAD61E02B3C
+PT=4B19F9BCAFD471BF9014ADA19891E4E6
+CT=53159BC4FBD06FD03ABAC028A536C4A0
+
+I=119
+KEY=2D42BE0B33D92ECC40DF48CF0AE0CB764607F1D7BCAC4C55F0EFEF85C4D6EF9C
+PT=53159BC4FBD06FD03ABAC028A536C4A0
+CT=BCDB1347ACD50D0084D588D4540420E3
+
+I=120
+KEY=338A4DC6E729E6FCF71095BB4E6F52FEFADCE29010794155743A675190D2CF7F
+PT=BCDB1347ACD50D0084D588D4540420E3
+CT=E12DC82E79554E1202DA471C3221A554
+
+I=121
+KEY=47597486437CBCD33FC195C56FF972BB1BF12ABE692C0F4776E0204DA2F36A2B
+PT=E12DC82E79554E1202DA471C3221A554
+CT=23A43E9D6F7C5A6C842233CCEC120EB9
+
+I=122
+KEY=CEE8CF713EBF0C609E3429E5183014BB385514230650552BF2C213814EE16492
+PT=23A43E9D6F7C5A6C842233CCEC120EB9
+CT=9F3F4349BF98D3CC00DB167F0FFDC7AB
+
+I=123
+KEY=C9B3A1CAFA0D4F0DA942C17FFB75E333A76A576AB9C886E7F21905FE411CA339
+PT=9F3F4349BF98D3CC00DB167F0FFDC7AB
+CT=C4D8B8EBEF311C11FE2404220EA65E99
+
+I=124
+KEY=8360E6F464B61C4BAE31D3A72422128463B2EF8156F99AF60C3D01DC4FBAFDA0
+PT=C4D8B8EBEF311C11FE2404220EA65E99
+CT=47E3318C721E6C094763F0A18042911D
+
+I=125
+KEY=926B00B9767D0CAD5331CD6F0343C4A92451DE0D24E7F6FF4B5EF17DCFF86CBD
+PT=47E3318C721E6C094763F0A18042911D
+CT=D709FA9A1415B0FAC71B4CF52504791F
+
+I=126
+KEY=3F4349126EF6A51FD196742CB461D01EF358249730F246058C45BD88EAFC15A2
+PT=D709FA9A1415B0FAC71B4CF52504791F
+CT=7937DD067DDB85F200A492E5824DA23C
+
+I=127
+KEY=4420ADF6906CFBF8421524E88517327C8A6FF9914D29C3F78CE12F6D68B1B79E
+PT=7937DD067DDB85F200A492E5824DA23C
+CT=B68617F1372847206BA088D7100334A4
+
+I=128
+KEY=125BEB5234B89A376ABBB2185F24BDDE3CE9EE607A0184D7E741A7BA78B2833A
+PT=B68617F1372847206BA088D7100334A4
+CT=390938BA9F2264484DE63D8003C15369
+
+I=129
+KEY=A457831AB172D88111E87C3955D0C0F205E0D6DAE523E09FAAA79A3A7B73D053
+PT=390938BA9F2264484DE63D8003C15369
+CT=A69ED32FD728337A5C25FBC2230DC788
+
+I=130
+KEY=CC7ED4183BFAE0FA0F9DD348B8E194F2A37E05F5320BD3E5F68261F8587E17DB
+PT=A69ED32FD728337A5C25FBC2230DC788
+CT=EDB9D6099202FE4AE51EEC725478FB47
+
+I=131
+KEY=686AB4F5C19296AED306ADEA4FD52D1A4EC7D3FCA0092DAF139C8D8A0C06EC9C
+PT=EDB9D6099202FE4AE51EEC725478FB47
+CT=61059EA3BF0C953762CB37E50ED7081F
+
+I=132
+KEY=8115329FADEBA92AB2827BD7701A01442FC24D5F1F05B8987157BA6F02D1E483
+PT=61059EA3BF0C953762CB37E50ED7081F
+CT=A683E36EF7CCDABDBCA683C2D6560D25
+
+I=133
+KEY=49254E8904EED2766A6A1A615B63B97C8941AE31E8C96225CDF139ADD487E9A6
+PT=A683E36EF7CCDABDBCA683C2D6560D25
+CT=8EF424771561BFEC0058C7CAA5876EF6
+
+I=134
+KEY=259194CE8701581012F5592B61BCA99507B58A46FDA8DDC9CDA9FE6771008750
+PT=8EF424771561BFEC0058C7CAA5876EF6
+CT=79AC024A7BA5FFE143D40D34F2E587A6
+
+I=135
+KEY=CA0427FE28C77D0CA25D6851CCFE58C47E19880C860D22288E7DF35383E500F6
+PT=79AC024A7BA5FFE143D40D34F2E587A6
+CT=2258AB9F0E254CE21EB9B7F6EA690671
+
+I=136
+KEY=DA9A4B566C9F670DF850F891A5274CC95C41239388286ECA90C444A5698C0687
+PT=2258AB9F0E254CE21EB9B7F6EA690671
+CT=55ACB73E8A45BF964BD040C799724DAD
+
+I=137
+KEY=9F177A6A6B524C75DB5CC0DBB6AD733209ED94AD026DD15CDB140462F0FE4B2A
+PT=55ACB73E8A45BF964BD040C799724DAD
+CT=3E904B15F2E5DDC934DABC25259CB3CF
+
+I=138
+KEY=2AD96F6874C1BA6A82C5EE80A9A2E8E5377DDFB8F0880C95EFCEB847D562F8E5
+PT=3E904B15F2E5DDC934DABC25259CB3CF
+CT=3ACFF8D5B701A5BD1355DDA705D269CB
+
+I=139
+KEY=ADD59DF57CC01DE988C6D81E65B1D00E0DB2276D4789A928FC9B65E0D0B0912E
+PT=3ACFF8D5B701A5BD1355DDA705D269CB
+CT=3EF4AC14CC954FB4A9A808C7C00A2F1F
+
+I=140
+KEY=D3EBE43C4E9C96B37133F6AF8910A25F33468B798B1CE69C55336D2710BABE31
+PT=3EF4AC14CC954FB4A9A808C7C00A2F1F
+CT=61C50D5C736AEDCF03C06FC310CC19D9
+
+I=141
+KEY=FA45F434377F2E217C4A5B7A7526CC1952838625F8760B5356F302E40076A7E8
+PT=61C50D5C736AEDCF03C06FC310CC19D9
+CT=2BF543C6548ED0344262640AD95F95C9
+
+I=142
+KEY=71EAD73C81ED5AE731D19B0B2B42F0E87976C5E3ACF8DB67149166EED9293221
+PT=2BF543C6548ED0344262640AD95F95C9
+CT=F8C1DBDD20317FEB1625634A451931B5
+
+I=143
+KEY=3FD0019D000111D4300D2CEF39F53C0D81B71E3E8CC9A48C02B405A49C300394
+PT=F8C1DBDD20317FEB1625634A451931B5
+CT=DEDB54735B8B90C8EEC66EAECFB13ED6
+
+I=144
+KEY=070976B2D3AA1E737BC24A8A794A21BE5F6C4A4DD7423444EC726B0A53813D42
+PT=DEDB54735B8B90C8EEC66EAECFB13ED6
+CT=75941A1ADA444115961E058E2D6C6396
+
+I=145
+KEY=81AC2B7F073D0D06BA8A43D3381D3A3F2AF850570D0675517A6C6E847EED5ED4
+PT=75941A1ADA444115961E058E2D6C6396
+CT=7C66BE2B0354A6549E10489AF7A83424
+
+I=146
+KEY=37BDD1946BB9B5616115F015E9162F5B569EEE7C0E52D305E47C261E89456AF0
+PT=7C66BE2B0354A6549E10489AF7A83424
+CT=F589769555BDEFD0B29E6A65313BD2E1
+
+I=147
+KEY=CF27BD543BB4EED052B808D1EE350D35A31798E95BEF3CD556E24C7BB87EB811
+PT=F589769555BDEFD0B29E6A65313BD2E1
+CT=9B3215F70FBCC5ED9CC0D6D7E1E56F11
+
+I=148
+KEY=43321308251C33234CCD9ED19E5E74AF38258D1E5453F938CA229AAC599BD700
+PT=9B3215F70FBCC5ED9CC0D6D7E1E56F11
+CT=705CCB60E0A6E997578DCC804D49D265
+
+I=149
+KEY=F2152160EAD144776BA6BDED0AC49CD24879467EB4F510AF9DAF562C14D20565
+PT=705CCB60E0A6E997578DCC804D49D265
+CT=3DA4CEC68D47E55ECF21A1C5CDAFE4E6
+
+I=150
+KEY=593B7EDAE946A5269EF33D088D1B297675DD88B839B2F5F1528EF7E9D97DE183
+PT=3DA4CEC68D47E55ECF21A1C5CDAFE4E6
+CT=32299EDBED49B66271107CA1822F179E
+
+I=151
+KEY=852E4554AD1459CE81DBA17D18DA96C447F41663D4FB4393239E8B485B52F61D
+PT=32299EDBED49B66271107CA1822F179E
+CT=45856FD2080FA9BBFA0857BCF7381823
+
+I=152
+KEY=1D8F910508F9C08DB4DE4D5C465310F4027179B1DCF4EA28D996DCF4AC6AEE3E
+PT=45856FD2080FA9BBFA0857BCF7381823
+CT=6A8C18595AF5D1E46F9F168C31566BAF
+
+I=153
+KEY=1A42C028C1ABA740D95A47ABD7B4F40D68FD61E886013BCCB609CA789D3C8591
+PT=6A8C18595AF5D1E46F9F168C31566BAF
+CT=71A41A6B6BF9FB906B0617DCB76B4BA5
+
+I=154
+KEY=3C408CB08BCAF34B2BCE6EF787A96D5219597B83EDF8C05CDD0FDDA42A57CE34
+PT=71A41A6B6BF9FB906B0617DCB76B4BA5
+CT=9105B8FC516E0B19AEDD003979F8C298
+
+I=155
+KEY=804516E36B1B5E046B15CBE1D3F26EE9885CC37FBC96CB4573D2DD9D53AF0CAC
+PT=9105B8FC516E0B19AEDD003979F8C298
+CT=27ACD01CC0403AD6DB45C7DF3E515EDE
+
+I=156
+KEY=CD8199690660BD4DBA38CE522D1A12CEAFF013637CD6F193A8971A426DFE5272
+PT=27ACD01CC0403AD6DB45C7DF3E515EDE
+CT=86E2A23AC567C5F05F15A318E38360A7
+
+I=157
+KEY=0AD8BB3D5B2A538DF0BDD50EB74CC1BA2912B159B9B13463F782B95A8E7D32D5
+PT=86E2A23AC567C5F05F15A318E38360A7
+CT=CB03EDA81BF211B5FE03D4A0879E9EDD
+
+I=158
+KEY=081040B60AE9E733243F4C39013EEDB5E2115CF1A24325D609816DFA09E3AC08
+PT=CB03EDA81BF211B5FE03D4A0879E9EDD
+CT=6F1AD4AD727348DD593459E0D7661813
+
+I=159
+KEY=A51E29D20BB0963DF854C898299E114A8D0B885CD0306D0B50B5341ADE85B41B
+PT=6F1AD4AD727348DD593459E0D7661813
+CT=236B421E3103D4C17297D3F5C8BA1D17
+
+I=160
+KEY=49D4EB9964431F42F0FC6494A47A50CCAE60CA42E133B9CA2222E7EF163FA90C
+PT=236B421E3103D4C17297D3F5C8BA1D17
+CT=118AE5A5597E8DB200B26DBE11AC4BC8
+
+I=161
+KEY=0F3F7298BE444450A0A07A4B73897720BFEA2FE7B84D347822908A510793E2C4
+PT=118AE5A5597E8DB200B26DBE11AC4BC8
+CT=DF02587F25CC4C59E6AECE98BCAACCB8
+
+I=162
+KEY=7E30984A4C0B18D2F791858B83FC960960E877989D817821C43E44C9BB392E7C
+PT=DF02587F25CC4C59E6AECE98BCAACCB8
+CT=3DA0F35FDAEF499ADBF602939FC748D4
+
+I=163
+KEY=360A7168E056892E5BF0127EA3B58CAF5D4884C7476E31BB1FC8465A24FE66A8
+PT=3DA0F35FDAEF499ADBF602939FC748D4
+CT=FE462F878CEEDDDAA00855B85A81A14B
+
+I=164
+KEY=A75B3537E0EB98FC0F41C9E1306F6667A30EAB40CB80EC61BFC013E27E7FC7E3
+PT=FE462F878CEEDDDAA00855B85A81A14B
+CT=47EA8AC561D7A9F99F64F41A9AD46E5C
+
+I=165
+KEY=219E71FC6D23A5103DE4DA9C5EDFA0AEE4E42185AA57459820A4E7F8E4ABA9BF
+PT=47EA8AC561D7A9F99F64F41A9AD46E5C
+CT=650FAE7F29A098D787F60CC3C0D77580
+
+I=166
+KEY=038A888C6EA4E9502A15110832AE0DF081EB8FFA83F7DD4FA752EB3B247CDC3F
+PT=650FAE7F29A098D787F60CC3C0D77580
+CT=0334BF8CA2835C71F2A283736D54E933
+
+I=167
+KEY=714967419F9129B9649A13A9DA3291A582DF30762174813E55F068484928350C
+PT=0334BF8CA2835C71F2A283736D54E933
+CT=1B3A09B325F3D833A3C83D941832B204
+
+I=168
+KEY=BCDB12EAF8D3C95F821C0DD324FD36BB99E539C50487590DF63855DC511A8708
+PT=1B3A09B325F3D833A3C83D941832B204
+CT=CF980ED2619858290881314B7F0B9516
+
+I=169
+KEY=B8FA32AE829E8AF3EF543A407E2D61BA567D3717651F0124FEB964972E11121E
+PT=CF980ED2619858290881314B7F0B9516
+CT=98FF5ADA0739122DBBD241847D4A318D
+
+I=170
+KEY=D62592634F0ABD21AC98887A88845E2ECE826DCD62261309456B2513535B2393
+PT=98FF5ADA0739122DBBD241847D4A318D
+CT=1824306B9F54BE4CE3F94F037B4B8569
+
+I=171
+KEY=77005AE2FA1AD6D77D36566B9E988345D6A65DA6FD72AD45A6926A102810A6FA
+PT=1824306B9F54BE4CE3F94F037B4B8569
+CT=25BA57B9035625DD268492282535960C
+
+I=172
+KEY=BE766696DC4458442056D89C96CAFDF0F31C0A1FFE2488988016F8380D2530F6
+PT=25BA57B9035625DD268492282535960C
+CT=26AEAD4ED08CA78CE2A3358F36DA0E3F
+
+I=173
+KEY=1E1D3EBC714EE191EDB2A02B64EF2C23D5B2A7512EA82F1462B5CDB73BFF3EC9
+PT=26AEAD4ED08CA78CE2A3358F36DA0E3F
+CT=10AB48E0CB1D72D82794E35DBDEF88F6
+
+I=174
+KEY=D3EAD2DA40B4C94B506A0ED75210023BC519EFB1E5B55DCC45212EEA8610B63F
+PT=10AB48E0CB1D72D82794E35DBDEF88F6
+CT=878BCAC367294B227533E1451F654960
+
+I=175
+KEY=87D0B5D4A1314054EC37B67B4245BA8C42922572829C16EE3012CFAF9975FF5F
+PT=878BCAC367294B227533E1451F654960
+CT=98CC3311EC8E8B75944503734DEAC00D
+
+I=176
+KEY=EF3FA3235BB42B1326DE67088C68E2BDDA5E16636E129D9BA457CCDCD49F3F52
+PT=98CC3311EC8E8B75944503734DEAC00D
+CT=DAF5FB711E259B498918871933A2E1FD
+
+I=177
+KEY=2EBBBB1B070658DD43299478725AA88F00ABED12703706D22D4F4BC5E73DDEAF
+PT=DAF5FB711E259B498918871933A2E1FD
+CT=AACC545DEE8FF1F5C7A91A2EE3D25C1B
+
+I=178
+KEY=E15D1FC214F23FF93886D219B4DFCD45AA67B94F9EB8F727EAE651EB04EF82B4
+PT=AACC545DEE8FF1F5C7A91A2EE3D25C1B
+CT=B844B67FBFD12E2712CCB66EBB4F7691
+
+I=179
+KEY=CC3335B792121DE55FA04A4D6FEE57B012230F302169D900F82AE785BFA0F425
+PT=B844B67FBFD12E2712CCB66EBB4F7691
+CT=3E00C548BAEE6150FAA5B67986331FD5
+
+I=180
+KEY=18DB585F810069C584251CA1E04A58382C23CA789B87B850028F51FC3993EBF0
+PT=3E00C548BAEE6150FAA5B67986331FD5
+CT=EB23DEEA8449E8FA0D828C12B98437AE
+
+I=181
+KEY=DFE08CA44B0BC4F51C43BE3631E20735C70014921FCE50AA0F0DDDEE8017DC5E
+PT=EB23DEEA8449E8FA0D828C12B98437AE
+CT=35BBE35CFC1D8FC40BC52F20D3FB35D5
+
+I=182
+KEY=0F7DCC456D50A31AC9351794BFE6DD57F2BBF7CEE3D3DF6E04C8F2CE53ECE98B
+PT=35BBE35CFC1D8FC40BC52F20D3FB35D5
+CT=DFFE7AEEAAF4762C7EB52453B1F61AD8
+
+I=183
+KEY=D34FDEB3F04FB4563BC0FD204E8D459F2D458D204927A9427A7DD69DE21AF353
+PT=DFFE7AEEAAF4762C7EB52453B1F61AD8
+CT=C648DAF9EBFB4BC6166B15BF067E107F
+
+I=184
+KEY=5E90B747C9976A3F5050B0C51F116A81EB0D57D9A2DCE2846C16C322E464E32C
+PT=C648DAF9EBFB4BC6166B15BF067E107F
+CT=057258D07CAEE57807C396FAE651855A
+
+I=185
+KEY=52D3686BC0CD56B9DFF3A69F5073F30AEE7F0F09DE7207FC6BD555D802356676
+PT=057258D07CAEE57807C396FAE651855A
+CT=B1109BE49E6E0F4C4190D8E0D717E8D0
+
+I=186
+KEY=39C89286B658E006FBF97BAB1C4874025F6F94ED401C08B02A458D38D5228EA6
+PT=B1109BE49E6E0F4C4190D8E0D717E8D0
+CT=4DDE60FEEE40402058C988092603AB53
+
+I=187
+KEY=562C9A004CBF05A4CA97994D48C0874C12B1F413AE5C4890728C0531F32125F5
+PT=4DDE60FEEE40402058C988092603AB53
+CT=3B18CBF83791E93D661EB269CFEAB1BE
+
+I=188
+KEY=F95206C4D3862E01A4DFE3676A2F297C29A93FEB99CDA1AD1492B7583CCB944B
+PT=3B18CBF83791E93D661EB269CFEAB1BE
+CT=0A3204DEE28B65E849136960949E4E5E
+
+I=189
+KEY=FEFDBE4294E46E22074E77B6BB7F964B239B3B357B46C4455D81DE38A855DA15
+PT=0A3204DEE28B65E849136960949E4E5E
+CT=6C47ECB8B1478F0BBEDEF3A05A439776
+
+I=190
+KEY=05858C957F861410187DD8CC2EE48E364FDCD78DCA014B4EE35F2D98F2164D63
+PT=6C47ECB8B1478F0BBEDEF3A05A439776
+CT=881188C2834B0496CB97F15F7A5C332A
+
+I=191
+KEY=A51CABC6D50BF9043E95CE2BC511D26DC7CD5F4F494A4FD828C8DCC7884A7E49
+PT=881188C2834B0496CB97F15F7A5C332A
+CT=1FAE86251E2F615E3BFCAC545013CD12
+
+I=192
+KEY=4EE1F6812CC35A16AA63F1CB39669ED7D863D96A57652E8613347093D859B35B
+PT=1FAE86251E2F615E3BFCAC545013CD12
+CT=6017C6764080CB6D2BAC24C0F1BFF8F5
+
+I=193
+KEY=F4F31D57DD72E6BF842D3834372AA60CB8741F1C17E5E5EB3898545329E64BAE
+PT=6017C6764080CB6D2BAC24C0F1BFF8F5
+CT=10C8548253FB2BCD5D6F87CB28FAE7E7
+
+I=194
+KEY=9DBB357DC99A95C240E750F1970C5C65A8BC4B9E441ECE2665F7D398011CAC49
+PT=10C8548253FB2BCD5D6F87CB28FAE7E7
+CT=20E253845A3DD51FFC16141FDAA20749
+
+I=195
+KEY=A814CD8766E0BFFBD8530589D6202BE0885E181A1E231B3999E1C787DBBEAB00
+PT=20E253845A3DD51FFC16141FDAA20749
+CT=9383323218D891F9DCE7578FCD6A54A5
+
+I=196
+KEY=C516C26E23E38C2B87346F759D8AEF881BDD2A2806FB8AC04506900816D4FFA5
+PT=9383323218D891F9DCE7578FCD6A54A5
+CT=9CFF8002D46EAFAAC7B035A788A37CF5
+
+I=197
+KEY=9301F8120939D0E70C97F614F61F18648722AA2AD295256A82B6A5AF9E778350
+PT=9CFF8002D46EAFAAC7B035A788A37CF5
+CT=90C9F34994D5DA86406C7E82EDDD1009
+
+I=198
+KEY=82B163831972D2CEF8F1780AA6B0707A17EB59634640FFECC2DADB2D73AA9359
+PT=90C9F34994D5DA86406C7E82EDDD1009
+CT=C8B5021EE84635EB7E7D0F5DBE967FD0
+
+I=199
+KEY=F99FF8714EE5D822E0E25C499D7C96ACDF5E5B7DAE06CA07BCA7D470CD3CEC89
+PT=C8B5021EE84635EB7E7D0F5DBE967FD0
+CT=15CCB3C950764E24CA714707034DF9A7
+
+I=200
+KEY=3529E6B83266BD558B7F33FC00AE4904CA92E8B4FE70842376D69377CE71152E
+PT=15CCB3C950764E24CA714707034DF9A7
+CT=5FDA0EF6A2172D5DAA8E842F061A2E44
+
+I=201
+KEY=2D77F95D8B556740CD9E2CC546CA45C99548E6425C67A97EDC581758C86B3B6A
+PT=5FDA0EF6A2172D5DAA8E842F061A2E44
+CT=808781D0D10B3A02333E0A53E159287F
+
+I=202
+KEY=79298FD5F3C4B6378403CFAD05C3C96E15CF67928D6C937CEF661D0B29321315
+PT=808781D0D10B3A02333E0A53E159287F
+CT=CC760400725FCFD37E757D99C6361B93
+
+I=203
+KEY=69535F335F6AEBF452407F3F1C203410D9B96392FF335CAF91136092EF040886
+PT=CC760400725FCFD37E757D99C6361B93
+CT=247D3A6BB4C883C142C4000B085C3B79
+
+I=204
+KEY=1A4F8FD7BD8DBCFB3677C708CDDDC7C4FDC459F94BFBDF6ED3D76099E75833FF
+PT=247D3A6BB4C883C142C4000B085C3B79
+CT=47E4C802C61E6A1706BAE95AF75CA70D
+
+I=205
+KEY=A573989455A11CAD1E8642CD774806B1BA2091FB8DE5B579D56D89C3100494F2
+PT=47E4C802C61E6A1706BAE95AF75CA70D
+CT=4297101350A5CE6C435FAD2725C22E46
+
+I=206
+KEY=8D52414DD5600AA0CACD5AD399FD1B37F8B781E8DD407B15963224E435C6BAB4
+PT=4297101350A5CE6C435FAD2725C22E46
+CT=BEC56BF1F3B6BE60C0F4CB7AE77BF0F5
+
+I=207
+KEY=49D4DF2FB3B561817F2BA6599B66C9244672EA192EF6C57556C6EF9ED2BD4A41
+PT=BEC56BF1F3B6BE60C0F4CB7AE77BF0F5
+CT=5B590F24D329BB6ED981938A4CDB9907
+
+I=208
+KEY=68BD5721E2A51A184CDBAC3A035670701D2BE53DFDDF7E1B8F477C149E66D346
+PT=5B590F24D329BB6ED981938A4CDB9907
+CT=A8A15DBB79BB9B1131EF39C1E3FCFC9C
+
+I=209
+KEY=2CC71F1B9BE892100E8A340E61D0A128B58AB8868464E50ABEA845D57D9A2FDA
+PT=A8A15DBB79BB9B1131EF39C1E3FCFC9C
+CT=E8CBAB9E98D2866E779512AAC2FA2EA0
+
+I=210
+KEY=EEF45CE1BB444A6BA5A029363FB9D4DB5D4113181CB66364C93D577FBF60017A
+PT=E8CBAB9E98D2866E779512AAC2FA2EA0
+CT=7E4896F0A48A25FFE950B74B96F5F40E
+
+I=211
+KEY=151FE809785C11F8F19F31EA0246B416230985E8B83C469B206DE0342995F574
+PT=7E4896F0A48A25FFE950B74B96F5F40E
+CT=E1C642B54B89822E73A695C851BC8EBE
+
+I=212
+KEY=14FE470CD366C580F124EA924B918BF5C2CFC75DF3B5C4B553CB75FC78297BCA
+PT=E1C642B54B89822E73A695C851BC8EBE
+CT=5FA2C6A2303ED7219984F30B78BE6B96
+
+I=213
+KEY=92E61F4C495462354EF612492557D6AB9D6D01FFC38B1394CA4F86F70097105C
+PT=5FA2C6A2303ED7219984F30B78BE6B96
+CT=3791959FBF178682A711623C2F91616C
+
+I=214
+KEY=6C0B6F23AC7526204C451A8ADE54D404AAFC94607C9C95166D5EE4CB2F067130
+PT=3791959FBF178682A711623C2F91616C
+CT=E14FCACD5FD26FC2710776EE82317ABC
+
+I=215
+KEY=0DAE926E4172586817730DB9FDF2CE0B4BB35EAD234EFAD41C599225AD370B8C
+PT=E14FCACD5FD26FC2710776EE82317ABC
+CT=E576499EAF5365E7FE3B4961D9C74419
+
+I=216
+KEY=DCD553F2977BD114B61F724ABC6AFE8EAEC517338C1D9F33E262DB4474F04F95
+PT=E576499EAF5365E7FE3B4961D9C74419
+CT=38567558119E72929F2932E6C289095E
+
+I=217
+KEY=6333DA8D5B655B5B5AABBCAF0B010BE89693626B9D83EDA17D4BE9A2B67946CB
+PT=38567558119E72929F2932E6C289095E
+CT=D20AD648F558E5507CC5C905E92CC268
+
+I=218
+KEY=F9010180B464FBB8AD7C9D5E41B1E09A4499B42368DB08F1018E20A75F5584A3
+PT=D20AD648F558E5507CC5C905E92CC268
+CT=00C719F3757DDD2D2E64C3F2666FB2CB
+
+I=219
+KEY=8CE68ED02B4FFD9720B3D16FAE92D164445EADD01DA6D5DC2FEAE355393A3668
+PT=00C719F3757DDD2D2E64C3F2666FB2CB
+CT=AEEAB9F50456CA3233A964219D2E7816
+
+I=220
+KEY=57E26BA4DBD3549051B0D9436EB38D4FEAB4142519F01FEE1C438774A4144E7E
+PT=AEEAB9F50456CA3233A964219D2E7816
+CT=3F02C97E127FD697AFD58BC66941F654
+
+I=221
+KEY=4D0BC4A8796407C939797EF19D0CE7E3D5B6DD5B0B8FC979B3960CB2CD55B82A
+PT=3F02C97E127FD697AFD58BC66941F654
+CT=BC4C0DDBCF0003B7814EEF1ABD22B6A8
+
+I=222
+KEY=9C1FD1789544D2F3FF84574A216767CD69FAD080C48FCACE32D8E3A870770E82
+PT=BC4C0DDBCF0003B7814EEF1ABD22B6A8
+CT=D125D8C2920ADD3EA00103DC695A0D9D
+
+I=223
+KEY=ADBE97F99DBE61213892D9849B81B3FBB8DF0842568517F092D9E074192D031F
+PT=D125D8C2920ADD3EA00103DC695A0D9D
+CT=C0C57598639BA69E13C82E3AF24777C5
+
+I=224
+KEY=A14DC5CF6CD0BD9AC9499317C509CCB4781A7DDA351EB16E8111CE4EEB6A74DA
+PT=C0C57598639BA69E13C82E3AF24777C5
+CT=81E3B8F6A691BC30AA66AD70F0358881
+
+I=225
+KEY=0EC479D8681AC8CA455D64A4BB34C86DF9F9C52C938F0D5E2B77633E1B5FFC5B
+PT=81E3B8F6A691BC30AA66AD70F0358881
+CT=3CD03908D4ABA4B9885BCB1AC89D16C3
+
+I=226
+KEY=E74102D814426E659732B303E6D44DB7C529FC244724A9E7A32CA824D3C2EA98
+PT=3CD03908D4ABA4B9885BCB1AC89D16C3
+CT=61662DD8EE676E17AE5CF2BABDC54A67
+
+I=227
+KEY=EE4034F1A2EF16D7D848BB005CDA5E99A44FD1FCA943C7F00D705A9E6E07A0FF
+PT=61662DD8EE676E17AE5CF2BABDC54A67
+CT=4E637432B0FF54FD665A902725B977EB
+
+I=228
+KEY=45E8F2DF7FC6E49FB0AF3B73788A1065EA2CA5CE19BC930D6B2ACAB94BBED714
+PT=4E637432B0FF54FD665A902725B977EB
+CT=E53D1440407503B66530EEEEBBC9182B
+
+I=229
+KEY=0BEBC981186DEF84C01688CA16A061E00F11B18E59C990BB0E1A2457F077CF3F
+PT=E53D1440407503B66530EEEEBBC9182B
+CT=12134ADF5BB16D867B4EE9CE87EBE36D
+
+I=230
+KEY=6FADFDB92B0F888514730F17A37A81B61D02FB510278FD3D7554CD99779C2C52
+PT=12134ADF5BB16D867B4EE9CE87EBE36D
+CT=310EACEF26A3EB5E4511437145DC30F9
+
+I=231
+KEY=A565724F25EE29346543964864A0FFAA2C0C57BE24DB166330458EE832401CAB
+PT=310EACEF26A3EB5E4511437145DC30F9
+CT=6848E5A618419EC6BACD9CD40BB42083
+
+I=232
+KEY=1FAEBFE13AC7545DC742ED60241BC2E84444B2183C9A88A58A88123C39F43C28
+PT=6848E5A618419EC6BACD9CD40BB42083
+CT=C64DA25E7CB1A004E31CD37F9D4E1112
+
+I=233
+KEY=A8EE2725373C48BAD9C0009C53C298A982091046402B28A16994C143A4BA2D3A
+PT=C64DA25E7CB1A004E31CD37F9D4E1112
+CT=D02E6AE8FDD0C5813669080AA7B82527
+
+I=234
+KEY=0770874A41ED1396940D75E6A5A09F5352277AAEBDFBED205FFDC9490302081D
+PT=D02E6AE8FDD0C5813669080AA7B82527
+CT=5DDFBC75FE48D88E7D6F307E4A008BC7
+
+I=235
+KEY=D7D098F85AB45E754629D2AB7DA2226C0FF8C6DB43B335AE2292F937490283DA
+PT=5DDFBC75FE48D88E7D6F307E4A008BC7
+CT=E216C9AC28239E97237930079739ECE0
+
+I=236
+KEY=5D6FAFF37EE7400691E504578251ECB1EDEE0F776B90AB3901EBC930DE3B6F3A
+PT=E216C9AC28239E97237930079739ECE0
+CT=8D126659360D03548879000642E78029
+
+I=237
+KEY=D75C5C64D94D0BC8566F568278B502D560FC692E5D9DA86D8992C9369CDCEF13
+PT=8D126659360D03548879000642E78029
+CT=9EA4C85D0F07AD618A2EBEBBE50D72B6
+
+I=238
+KEY=D42BD9CDCD8BDA71E64817A2755C97C0FE58A173529A050C03BC778D79D19DA5
+PT=9EA4C85D0F07AD618A2EBEBBE50D72B6
+CT=1F525901AF1D94BA6CA3C7244E2CD885
+
+I=239
+KEY=32DD1758D2EFC602EE85C58A66D0B080E10AF872FD8791B66F1FB0A937FD4520
+PT=1F525901AF1D94BA6CA3C7244E2CD885
+CT=E131C071BFA21FCE21D18DB87B522903
+
+I=240
+KEY=BEC98C02D74E088458A668D0B6DDCF13003B380342258E784ECE3D114CAF6C23
+PT=E131C071BFA21FCE21D18DB87B522903
+CT=51F1B72C99C869BF73A6637D3A2E2278
+
+I=241
+KEY=D368F7BE25A6A0C9AD2004E764F43A3551CA8F2FDBEDE7C73D685E6C76814E5B
+PT=51F1B72C99C869BF73A6637D3A2E2278
+CT=0965CDD7A134672036F0C69774CFD380
+
+I=242
+KEY=E5A7E12124540DBB4147A55C276A35B958AF42F87AD980E70B9898FB024E9DDB
+PT=0965CDD7A134672036F0C69774CFD380
+CT=52ECEB721073FBF3D1BD5808351BEC5E
+
+I=243
+KEY=7D9702E2C8906805A580D5D85B03BBC60A43A98A6AAA7B14DA25C0F337557185
+PT=52ECEB721073FBF3D1BD5808351BEC5E
+CT=493CE4E2B090DA3A2354C9DA7DB44D39
+
+I=244
+KEY=8EFA5EC96F3AEF51AB38F4CCD969E5D5437F4D68DA3AA12EF97109294AE13CBC
+PT=493CE4E2B090DA3A2354C9DA7DB44D39
+CT=DA64246FF65969995F9A4E8AE7C805CF
+
+I=245
+KEY=19C97957444E9931293047A647D7A19A991B69072C63C8B7A6EB47A3AD293973
+PT=DA64246FF65969995F9A4E8AE7C805CF
+CT=CF85EBD76908CD8F8D3177E53DA3AD5E
+
+I=246
+KEY=7BDB3ED45BD78C131611FD9D54B8E9D2569E82D0456B05382BDA3046908A942D
+PT=CF85EBD76908CD8F8D3177E53DA3AD5E
+CT=45E1FDEFC98E62A841BD1D8D8236CEEF
+
+I=247
+KEY=19961521A42D96238D44F651E7E7D463137F7F3F8CE567906A672DCB12BC5AC2
+PT=45E1FDEFC98E62A841BD1D8D8236CEEF
+CT=E056EF7B711A9CBDED8878EF74AF1671
+
+I=248
+KEY=343360636E697E607319D4DCBC12B543F3299044FDFFFB2D87EF552466134CB3
+PT=E056EF7B711A9CBDED8878EF74AF1671
+CT=E4EFF77C6C3273393BE4814A16C3DF4A
+
+I=249
+KEY=B63D4D3D099F8E68F6A041D2EB1B1C1417C6673891CD8814BC0BD46E70D093F9
+PT=E4EFF77C6C3273393BE4814A16C3DF4A
+CT=EC562E353DF8BA76699B01A6ACC8AD52
+
+I=250
+KEY=EF500379EDE772968F1499F07B0B09CFFB90490DAC353262D590D5C8DC183EAB
+PT=EC562E353DF8BA76699B01A6ACC8AD52
+CT=4473050ADC687112AACB86AA73CB6C6D
+
+I=251
+KEY=EA5CD4EDD99E64018AD3104026F0F528BFE34C07705D43707F5B5362AFD352C6
+PT=4473050ADC687112AACB86AA73CB6C6D
+CT=6561A82EE86E4F18DF6965312F0C0984
+
+I=252
+KEY=2ABF9529FC88D85FF68CF6D72B9A9CB5DA82E42998330C68A032365380DF5B42
+PT=6561A82EE86E4F18DF6965312F0C0984
+CT=47590CE1C90F3AC2C68B272B4A667F61
+
+I=253
+KEY=A485B647790DBFF76F16C42A39F5F5559DDBE8C8513C36AA66B91178CAB92423
+PT=47590CE1C90F3AC2C68B272B4A667F61
+CT=4ED731A36BCB2672A810633E432D8922
+
+I=254
+KEY=F0D0E858B597595A06458FF6C2259127D30CD96B3AF710D8CEA972468994AD01
+PT=4ED731A36BCB2672A810633E432D8922
+CT=4AC2F0D5F52762F77DB5D9EF53B76642
+
+I=255
+KEY=EDDE80556ECA4CC51EFB33E23C43C04399CE29BECFD0722FB31CABA9DA23CB43
+PT=4AC2F0D5F52762F77DB5D9EF53B76642
+CT=A574FBE71E359A57D57A24A388FDF6EE
+
+I=256
+KEY=3C7C248C9FCE1D060D5B0664C0FF3F6B3CBAD259D1E5E87866668F0A52DE3DAD
+PT=A574FBE71E359A57D57A24A388FDF6EE
+CT=CCC3A011108469A7987F336C209BB84E
+
+I=257
+KEY=D43727570A809BE0D9EB78760FE4CDA9F0797248C16181DFFE19BC66724585E3
+PT=CCC3A011108469A7987F336C209BB84E
+CT=686357D3013977390164834D4E5324DC
+
+I=258
+KEY=2F060E361977E544B98779AB55886D57981A259BC058F6E6FF7D3F2B3C16A13F
+PT=686357D3013977390164834D4E5324DC
+CT=DDDAD6FBDBF7C7BE7EBF3F036009A270
+
+I=259
+KEY=A3630C05DC65905D37AFDB315B2AA4D945C0F3601BAF315881C200285C1F034F
+PT=DDDAD6FBDBF7C7BE7EBF3F036009A270
+CT=237124FEDF28B4201B6D1584B93D5F7C
+
+I=260
+KEY=3E6ADAAEF53A36294CDEA0D94BE742C166B1D79EC48785789AAF15ACE5225C33
+PT=237124FEDF28B4201B6D1584B93D5F7C
+CT=D1A9DDFB5662934AAD98B2861E50A871
+
+I=261
+KEY=234615019E03C466AEA186112C4EB523B7180A6592E516323737A72AFB72F442
+PT=D1A9DDFB5662934AAD98B2861E50A871
+CT=CA18344F4C7A0F068398CA8137C056DD
+
+I=262
+KEY=22ED93581611798050E94CC70F6090BF7D003E2ADE9F1934B4AF6DABCCB2A29F
+PT=CA18344F4C7A0F068398CA8137C056DD
+CT=91FA4D62D10E852D9EDA42FAC8C34557
+
+I=263
+KEY=A5981D9A37D6D3D948391D1D462B6DCFECFA73480F919C192A752F510471E7C8
+PT=91FA4D62D10E852D9EDA42FAC8C34557
+CT=B956221510135066B2B2552C4CB37642
+
+I=264
+KEY=BF2E4397D0E93DFFA38D69B30F33835B55AC515D1F82CC7F98C77A7D48C2918A
+PT=B956221510135066B2B2552C4CB37642
+CT=300CFCEAFED28E622CD08222D3A3B0B0
+
+I=265
+KEY=55432143B807A628001F8D062CE0157265A0ADB7E150421DB417F85F9B61213A
+PT=300CFCEAFED28E622CD08222D3A3B0B0
+CT=26681BCFDC630A21A684C60EF6A23747
+
+I=266
+KEY=2966A6CB3BA9028583813B91FD72748D43C8B6783D33483C12933E516DC3167D
+PT=26681BCFDC630A21A684C60EF6A23747
+CT=8EDD4B1B458D16841AD4525C01A8397E
+
+I=267
+KEY=1A22288AC28060F8E4B20C2AE0C82AEACD15FD6378BE5EB808476C0D6C6B2F03
+PT=8EDD4B1B458D16841AD4525C01A8397E
+CT=BFDE412A7CAF0326AD1727996056A61C
+
+I=268
+KEY=C882E880508E92FF709E9BD4A555B30A72CBBC4904115D9EA5504B940C3D891F
+PT=BFDE412A7CAF0326AD1727996056A61C
+CT=88C039A0B395C5D08848C64DFC150C57
+
+I=269
+KEY=298B3829EE60112C926E1FD583C9A2DEFA0B85E9B784984E2D188DD9F0288548
+PT=88C039A0B395C5D08848C64DFC150C57
+CT=ACDF23F2CB73FD8D3D814A79E3C94126
+
+I=270
+KEY=2F2A3D0DDB2DBA8B8E3FF8A9DE765FE356D4A61B7CF765C31099C7A013E1C46E
+PT=ACDF23F2CB73FD8D3D814A79E3C94126
+CT=A8BE26FE8780972650D5F384B744AC44
+
+I=271
+KEY=F8CC20E8296CD38F1EF8BB2777EE1200FE6A80E5FB77F2E5404C3424A4A5682A
+PT=A8BE26FE8780972650D5F384B744AC44
+CT=B5557CC20F64FCC576A6EC7BE324CE43
+
+I=272
+KEY=678B5341F1BC13DB366B36D59ADADC7C4B3FFC27F4130E2036EAD85F4781A669
+PT=B5557CC20F64FCC576A6EC7BE324CE43
+CT=B59281EFF9C8D19E5D9C053CBE1F2F33
+
+I=273
+KEY=E4701C9009693E38C455CE186A4B87DFFEAD7DC80DDBDFBE6B76DD63F99E895A
+PT=B59281EFF9C8D19E5D9C053CBE1F2F33
+CT=7E8B1D4BFF81C5B9AA1FCA81DF8DE64F
+
+I=274
+KEY=C1F886CBCBF2BD920A0E68F30FCB8FCE80266083F25A1A07C16917E226136F15
+PT=7E8B1D4BFF81C5B9AA1FCA81DF8DE64F
+CT=20841B35C77A109B528A1135E17D36EE
+
+I=275
+KEY=F05D61A9441B3C741D9D7489F2EE4A5EA0A27BB635200A9C93E306D7C76E59FB
+PT=20841B35C77A109B528A1135E17D36EE
+CT=C3195DC001FA1AD7C253DD3FE4A4BC7D
+
+I=276
+KEY=0C8E70943252DD5DC9819A9FDB375B3F63BB267634DA104B51B0DBE823CAE586
+PT=C3195DC001FA1AD7C253DD3FE4A4BC7D
+CT=7E06BD1B3440DB4CA73AF1A05B33AD3F
+
+I=277
+KEY=84F1B5CF1AD11205E98ECD317AD670A11DBD9B6D009ACB07F68A2A4878F948B9
+PT=7E06BD1B3440DB4CA73AF1A05B33AD3F
+CT=6224DBD71C1DC35A5C62777D2EA32C3E
+
+I=278
+KEY=E3465353AED687EF62CD1DA8D7DA3EEB7F9940BA1C87085DAAE85D35565A6487
+PT=6224DBD71C1DC35A5C62777D2EA32C3E
+CT=1E4E51CD7BA1F7467AC69755F8894EF4
+
+I=279
+KEY=31F715D1FFA116F58AB70E4A3EEF6E9561D711776726FF1BD02ECA60AED32A73
+PT=1E4E51CD7BA1F7467AC69755F8894EF4
+CT=4AB8AFEACB2A1B1AE9E74D647266E234
+
+I=280
+KEY=487B6847CA14B04D429C81278332273F2B6FBE9DAC0CE40139C98704DCB5C847
+PT=4AB8AFEACB2A1B1AE9E74D647266E234
+CT=64C0BBA15382C142BBEE84B86B7D0BA0
+
+I=281
+KEY=D1C9CA26B21945011B044EA6E29C9AD54FAF053CFF8E2543822703BCB7C8C3E7
+PT=64C0BBA15382C142BBEE84B86B7D0BA0
+CT=F82292AF614648EC6C1E9A1027167410
+
+I=282
+KEY=3F585C00E187BE1B0C9E09781C9548A8B78D97939EC86DAFEE3999AC90DEB7F7
+PT=F82292AF614648EC6C1E9A1027167410
+CT=31C38ED5F207B412A14A51632D8805CE
+
+I=283
+KEY=340B8C115BAFF387400CD8F0EE8F8F6F864E19466CCFD9BD4F73C8CFBD56B239
+PT=31C38ED5F207B412A14A51632D8805CE
+CT=3FC4CC8F4245BBBC5939A0C0A24A14DE
+
+I=284
+KEY=EA8EACF07402225D6C5181A8802DA515B98AD5C92E8A6201164A680F1F1CA6E7
+PT=3FC4CC8F4245BBBC5939A0C0A24A14DE
+CT=23A98FA41D6C3D4CD9CFB9737A6D7872
+
+I=285
+KEY=56EF7B73BF04F5F463E4D0EA0F6FC4DA9A235A6D33E65F4DCF85D17C6571DE95
+PT=23A98FA41D6C3D4CD9CFB9737A6D7872
+CT=82CC2D376B2772B7B988BEA17EFBB3D2
+
+I=286
+KEY=C425E380DA91C34B73CE922C59B13C8818EF775A58C12DFA760D6FDD1B8A6D47
+PT=82CC2D376B2772B7B988BEA17EFBB3D2
+CT=5330F6218D528A32B24085EA496A05A9
+
+I=287
+KEY=EA66C7FF9FCD2F9E76BCC5C6387E133E4BDF817BD593A7C8C44DEA3752E068EE
+PT=5330F6218D528A32B24085EA496A05A9
+CT=7C1E082C2C89C90AD91AE81DF73F1F5F
+
+I=288
+KEY=C89CF336490832FB54BB536813AEE6EA37C18957F91A6EC21D57022AA5DF77B1
+PT=7C1E082C2C89C90AD91AE81DF73F1F5F
+CT=2AB33673B654E2C49D6736D65A5F45C8
+
+I=289
+KEY=7CC5409A9AE1F997774C3FEB74A6E9061D72BF244F4E8C06803034FCFF803279
+PT=2AB33673B654E2C49D6736D65A5F45C8
+CT=21BA6CADDCA5E0BE779D1A2651794C81
+
+I=290
+KEY=E5E1873FDEE9DC066AF79C0E6027D0703CC8D38993EB6CB8F7AD2EDAAEF97EF8
+PT=21BA6CADDCA5E0BE779D1A2651794C81
+CT=8E2AF8BA54CF04812AE786C180FCFCA8
+
+I=291
+KEY=844AA67914DE1C11677B5526D5B12765B2E22B33C7246839DD4AA81B2E058250
+PT=8E2AF8BA54CF04812AE786C180FCFCA8
+CT=E48A7CD35CA33B1D919B8A83ADF4C6BE
+
+I=292
+KEY=FE3248768ACB0AF9DBD639AF7B7EB944566857E09B8753244CD1229883F144EE
+PT=E48A7CD35CA33B1D919B8A83ADF4C6BE
+CT=C377A76CF43C27784CC54079744413D1
+
+I=293
+KEY=709E7BC30A7DE8FADC071B3D04338FCA951FF08C6FBB745C001462E1F7B5573F
+PT=C377A76CF43C27784CC54079744413D1
+CT=01D8083A9EA403A4754EF82CA29CDD5B
+
+I=294
+KEY=448B1AEC2F68D202679183D85C4A6D2194C7F8B6F11F77F8755A9ACD55298A64
+PT=01D8083A9EA403A4754EF82CA29CDD5B
+CT=46ADC32EFF2C3EFF40B468E845EFC2E4
+
+I=295
+KEY=529401616FA6193014D6A10BEF1A816FD26A3B980E33490735EEF22510C64880
+PT=46ADC32EFF2C3EFF40B468E845EFC2E4
+CT=FCC6594B1BBF40E28BE798ABC00163F1
+
+I=296
+KEY=15A5E8BAF02EF91390AB7D35742CC5C12EAC62D3158C09E5BE096A8ED0C72B71
+PT=FCC6594B1BBF40E28BE798ABC00163F1
+CT=28D35B6E1140738ED1DF20FE11003B1E
+
+I=297
+KEY=589C04ECDF2B884807919A2018A93080067F39BD04CC7A6B6FD64A70C1C7106F
+PT=28D35B6E1140738ED1DF20FE11003B1E
+CT=3354C7962E19FB043FD4CD7B2C99E195
+
+I=298
+KEY=A6987BEB541098C7173475B34568F36B352BFE2B2AD5816F5002870BED5EF1FA
+PT=3354C7962E19FB043FD4CD7B2C99E195
+CT=EB76F282C9F10F507FACFCDEEC8BBBB8
+
+I=299
+KEY=3732B395057761A8A2624F52354668CFDE5D0CA9E3248E3F2FAE7BD501D54A42
+PT=EB76F282C9F10F507FACFCDEEC8BBBB8
+CT=77A4DAE8406992C5018D6B0310195E0C
+
+I=300
+KEY=E24C9F98F43E840AE04ED4928133F65AA9F9D641A34D1CFA2E2310D611CC144E
+PT=77A4DAE8406992C5018D6B0310195E0C
+CT=655DEC1062EDB50B8B31A66071E236A2
+
+I=301
+KEY=8BA207CA6E2B720810E66CCAB597E8DACCA43A51C1A0A9F1A512B6B6602E22EC
+PT=655DEC1062EDB50B8B31A66071E236A2
+CT=28A22A069D8FF3DE359860B0A5B6FD1F
+
+I=302
+KEY=22C629C84758D553AFE4876AA739A1F0E40610575C2F5A2F908AD606C598DFF3
+PT=28A22A069D8FF3DE359860B0A5B6FD1F
+CT=95DD88B4AFD0680E221C70422ADFFCD1
+
+I=303
+KEY=F86A3C799AAB6884220196BF07E1643D71DB98E3F3FF3221B296A644EF472322
+PT=95DD88B4AFD0680E221C70422ADFFCD1
+CT=323475C634FD6845BAA9F371F29DC363
+
+I=304
+KEY=83412E9600B279F76C93F171C469AD1943EFED25C7025A64083F55351DDAE041
+PT=323475C634FD6845BAA9F371F29DC363
+CT=61276AD535F9E73FCFB53DBF2D5D1F62
+
+I=305
+KEY=01AD15137C4A572322660716B6B4EDCD22C887F0F2FBBD5BC78A688A3087FF23
+PT=61276AD535F9E73FCFB53DBF2D5D1F62
+CT=105ECB04A5CA32FC93987569A7CB46D7
+
+I=306
+KEY=1CC639BA56CA0DF23E64BB3395C08BB332964CF457318FA754121DE3974CB9F4
+PT=105ECB04A5CA32FC93987569A7CB46D7
+CT=831DBB3F4BBD4343B94D54AA2B3E0620
+
+I=307
+KEY=25ABCF5B8DB1A7CCB1FA49936E0AB3C8B18BF7CB1C8CCCE4ED5F4949BC72BFD4
+PT=831DBB3F4BBD4343B94D54AA2B3E0620
+CT=40B9D9C6201E639DC9A04E500BCD7F61
+
+I=308
+KEY=75B34E0F371C4527732F22CF35AD923BF1322E0D3C92AF7924FF0719B7BFC0B5
+PT=40B9D9C6201E639DC9A04E500BCD7F61
+CT=A159BB0C751148C14D561E0407A9F6DB
+
+I=309
+KEY=1EB6E3491B431B7EFFCCC965C9041274506B95014983E7B869A9191DB016366E
+PT=A159BB0C751148C14D561E0407A9F6DB
+CT=2012E67815334AC48E5309DD129E0476
+
+I=310
+KEY=F0BDAFB216613A6FB3819D08B17EFDC1707973795CB0AD7CE7FA10C0A2883218
+PT=2012E67815334AC48E5309DD129E0476
+CT=53E415BC0C9013F83B77298395FC9FEF
+
+I=311
+KEY=9C5A3B9C862E07159AB06D5B7FB585C5239D66C55020BE84DC8D39433774ADF7
+PT=53E415BC0C9013F83B77298395FC9FEF
+CT=2B1EEAA13373494A2A56C15FD5ECA103
+
+I=312
+KEY=9764AC349B8222394160F4896BA6761808838C646353F7CEF6DBF81CE2980CF4
+PT=2B1EEAA13373494A2A56C15FD5ECA103
+CT=2A00E873782853DC842427A03C30A81A
+
+I=313
+KEY=42A1614569C4DE66D6336BC082B3B9DD228364171B7BA41272FFDFBCDEA8A4EE
+PT=2A00E873782853DC842427A03C30A81A
+CT=5FEB74E489C4C8121A15C2BCF51046A5
+
+I=314
+KEY=CED80BE0859A5863CFE41F0F2CE9F65B7D6810F392BF6C0068EA1D002BB8E24B
+PT=5FEB74E489C4C8121A15C2BCF51046A5
+CT=948214D5DB68997C37A48927AA97B89A
+
+I=315
+KEY=178DAF533EBB695D5E57401E5345C3E8E9EA042649D7F57C5F4E9427812F5AD1
+PT=948214D5DB68997C37A48927AA97B89A
+CT=AB8F3BB9917E4D1C8F1F2EDDB7070530
+
+I=316
+KEY=66F4B8B5A0BD877514FDB4CD2DD04D8C42653F9FD8A9B860D051BAFA36285FE1
+PT=AB8F3BB9917E4D1C8F1F2EDDB7070530
+CT=CB5FB11C6DB1AB6BC189F0F3FB47A2A5
+
+I=317
+KEY=9753278CFCEE8B059ECF573A2E0D65D6893A8E83B518130B11D84A09CD6FFD44
+PT=CB5FB11C6DB1AB6BC189F0F3FB47A2A5
+CT=F0CE65E6C5C263182E6C253F26460A1B
+
+I=318
+KEY=121A860A5B53C56E536DE56566F31E2079F4EB6570DA70133FB46F36EB29F75F
+PT=F0CE65E6C5C263182E6C253F26460A1B
+CT=9AA17B0F532814CA74FF0A046F377C48
+
+I=319
+KEY=88F5E58E9522495BF7B68430946F7C0FE355906A23F264D94B4B6532841E8B17
+PT=9AA17B0F532814CA74FF0A046F377C48
+CT=52CAAEF16E55858487AEDBDBA822002D
+
+I=320
+KEY=D9A3D3547F215D44D80C6A5D3548D4D2B19F3E9B4DA7E15DCCE5BEE92C3C8B3A
+PT=52CAAEF16E55858487AEDBDBA822002D
+CT=2599545FD15C7F59A6F02CDCB95E6589
+
+I=321
+KEY=6ACE86543B0F981C2D0FCB1408A42C3294066AC49CFB9E046A1592359562EEB3
+PT=2599545FD15C7F59A6F02CDCB95E6589
+CT=DC7A68313CE3E1963D31E5149CDBE22A
+
+I=322
+KEY=E9D6D08194DAFBB7B491124515118FA6487C02F5A0187F925724772109B90C99
+PT=DC7A68313CE3E1963D31E5149CDBE22A
+CT=333B588A7354CB3229E43780AFE4738D
+
+I=323
+KEY=762FC93CEED1EE9C6EF702A4E3BBABD67B475A7FD34CB4A07EC040A1A65D7F14
+PT=333B588A7354CB3229E43780AFE4738D
+CT=41727DC0D18725AFD2EF8FF51EAE1C2C
+
+I=324
+KEY=FF4EC1DF818E820424CFE5D09EE2E5423A3527BF02CB910FAC2FCF54B8F36338
+PT=41727DC0D18725AFD2EF8FF51EAE1C2C
+CT=A7236B16D9937C84F37BF9D79D0251F9
+
+I=325
+KEY=59BDAB706DEA2EC52AE05A2E4382A4169D164CA9DB58ED8B5F54368325F132C1
+PT=A7236B16D9937C84F37BF9D79D0251F9
+CT=B81D30EFDB86688F1DCA616EC771B9FD
+
+I=326
+KEY=4C008516CD614B6588A526FFE33C055B250B7C4600DE8504429E57EDE2808B3C
+PT=B81D30EFDB86688F1DCA616EC771B9FD
+CT=A5AD142C8F078ABF419B7CF5C86C9F83
+
+I=327
+KEY=DB65698F99E4A27019ABE194A89E9BC680A6686A8FD90FBB03052B182AEC14BF
+PT=A5AD142C8F078ABF419B7CF5C86C9F83
+CT=861B59E3B61A5D02F0D70DFF40EF7FF2
+
+I=328
+KEY=0790C16C53A7826B4B309DDF99B5239006BD318939C352B9F3D226E76A036B4D
+PT=861B59E3B61A5D02F0D70DFF40EF7FF2
+CT=B0F4C2C4D0D282BE3128AD78D34B1FA6
+
+I=329
+KEY=AFE168F089E676A806DD191003777E6DB649F34DE911D007C2FA8B9FB94874EB
+PT=B0F4C2C4D0D282BE3128AD78D34B1FA6
+CT=9DFCF5727851ADE8C37A9AA3AA77B20D
+
+I=330
+KEY=F261CDF199D9EF436C1A08EB9755A2112BB5063F91407DEF0180113C133FC6E6
+PT=9DFCF5727851ADE8C37A9AA3AA77B20D
+CT=9268DBA972B72C9DEF15CF9B8041F23B
+
+I=331
+KEY=E0D6DCF3BA840720688456A43E849C5CB9DDDD96E3F75172EE95DEA7937E34DD
+PT=9268DBA972B72C9DEF15CF9B8041F23B
+CT=D45A8B321CB6D8F28167C857BC2900BF
+
+I=332
+KEY=B77CF3A880C2E9E66D0C98A4D88555F46D8756A4FF4189806FF216F02F573462
+PT=D45A8B321CB6D8F28167C857BC2900BF
+CT=0124FE2D8BCB81E1286A18D2BABEA919
+
+I=333
+KEY=7729E55EFA6B249E0207E06AAF6F09206CA3A889748A086147980E2295E99D7B
+PT=0124FE2D8BCB81E1286A18D2BABEA919
+CT=A1BB0D975A50BE8BD8C2973D4BA7BF42
+
+I=334
+KEY=102384784C54539084BC7181AA95F184CD18A51E2EDAB6EA9F5A991FDE4E2239
+PT=A1BB0D975A50BE8BD8C2973D4BA7BF42
+CT=15302D5DBFD8E407EADDE9896B42CB13
+
+I=335
+KEY=9FF48EF1068BFC07DA38F7790D7418D2D8288843910252ED75877096B50CE92A
+PT=15302D5DBFD8E407EADDE9896B42CB13
+CT=90D93B8F802CFAD3F6E682DD704B5F43
+
+I=336
+KEY=84477EB9007ECDF8D1C4A6A976C76AB848F1B3CC112EA83E8361F24BC547B669
+PT=90D93B8F802CFAD3F6E682DD704B5F43
+CT=2DD7E0B91C5DDF0FD118F4CDD836A212
+
+I=337
+KEY=F1CE87DE930567CE29DF313D8778358D652653750D737731527906861D71147B
+PT=2DD7E0B91C5DDF0FD118F4CDD836A212
+CT=AC9D307EFF44703D6FDA621FFF8D077C
+
+I=338
+KEY=22D31C8F64CFB23620A70E7CD4A486D3C9BB630BF237070C3DA36499E2FC1307
+PT=AC9D307EFF44703D6FDA621FFF8D077C
+CT=CC6772DE3B27CB1DB3E5A804843EB6FF
+
+I=339
+KEY=FC9057D2D2D28BFAC4D5E3654717188205DC11D5C910CC118E46CC9D66C2A5F8
+PT=CC6772DE3B27CB1DB3E5A804843EB6FF
+CT=BDB021550FE0744090EAFEEBCF422061
+
+I=340
+KEY=1EA032190E7E4CC45D2E1E138429658AB86C3080C6F0B8511EAC3276A9808599
+PT=BDB021550FE0744090EAFEEBCF422061
+CT=C6E21F9A1305C3969F2D70C11D58A1A7
+
+I=341
+KEY=B633EDA212B952785755700FBDC91CA57E8E2F1AD5F57BC7818142B7B4D8243E
+PT=C6E21F9A1305C3969F2D70C11D58A1A7
+CT=01BC936B7063CA9D28DB1FFCCB9C2048
+
+I=342
+KEY=94A06984520AB40D74568F0D5286AEE37F32BC71A596B15AA95A5D4B7F440476
+PT=01BC936B7063CA9D28DB1FFCCB9C2048
+CT=88279D100DFA68CEBD9949F19C3333F4
+
+I=343
+KEY=96A3BD621155F71A9EFB8E35F95238ACF7152161A86CD99414C314BAE3773782
+PT=88279D100DFA68CEBD9949F19C3333F4
+CT=41574A686596D4741BF5DE52B5183260
+
+I=344
+KEY=185312E4301E5AADC373CEB3EBA66FB7B6426B09CDFA0DE00F36CAE8566F05E2
+PT=41574A686596D4741BF5DE52B5183260
+CT=BD9F5087C32A66A4797C7EE87355FF4A
+
+I=345
+KEY=BC5D60D256DCA48E88E52F05C349431A0BDD3B8E0ED06B44764AB400253AFAA8
+PT=BD9F5087C32A66A4797C7EE87355FF4A
+CT=A88BC3FAF87D6C1D3F98A2884EF1D4DA
+
+I=346
+KEY=1485A9209167A6FA2ECD2CE6AA03DBA5A356F874F6AD075949D216886BCB2E72
+PT=A88BC3FAF87D6C1D3F98A2884EF1D4DA
+CT=E514E6E34A050EB917F2382EDF92353A
+
+I=347
+KEY=2B62B0E29763FF09F53A2006B990E97746421E97BCA809E05E202EA6B4591B48
+PT=E514E6E34A050EB917F2382EDF92353A
+CT=142EEBE72E0F56ABE5D67FCC28F957F6
+
+I=348
+KEY=FC13067E362B7C9C39AA73B85F32011C526CF57092A75F4BBBF6516A9CA04CBE
+PT=142EEBE72E0F56ABE5D67FCC28F957F6
+CT=24FDB7A03FE8A9288BFAA5AC2527D015
+
+I=349
+KEY=8AC3B473244989EA74025FE98269BC17769142D0AD4FF663300CF4C6B9879CAB
+PT=24FDB7A03FE8A9288BFAA5AC2527D015
+CT=649095ABA5F4006B7B89D20F10A37AE9
+
+I=350
+KEY=FD0F4205DBFF0160203898EF02E9088E1201D77B08BBF6084B8526C9A924E642
+PT=649095ABA5F4006B7B89D20F10A37AE9
+CT=F5428E8BDDDC31FC8EF67BC7DB3201D3
+
+I=351
+KEY=701AF95194FB0918BC2CA79AFD507336E74359F0D567C7F4C5735D0E7216E791
+PT=F5428E8BDDDC31FC8EF67BC7DB3201D3
+CT=A56B2014A4929373DC1F6FD5C0AC138C
+
+I=352
+KEY=633D0E72722E6443D4E219086D221939422879E471F55487196C32DBB2BAF41D
+PT=A56B2014A4929373DC1F6FD5C0AC138C
+CT=F35F9CD43144B358843A48B4D1C41882
+
+I=353
+KEY=DCA79BA0184EC0A22A875E5057CA967AB177E53040B1E7DF9D567A6F637EEC9F
+PT=F35F9CD43144B358843A48B4D1C41882
+CT=A572C1F98330A1C1FA91DFD5A5B76AB9
+
+I=354
+KEY=A3D0FE4C3C1A1CE19CF66CF80135553D140524C9C381461E67C7A5BAC6C98626
+PT=A572C1F98330A1C1FA91DFD5A5B76AB9
+CT=23C56E065427F0409504053DD8A994CD
+
+I=355
+KEY=175C8D4085802768D20875CDBE6EFE2437C04ACF97A6B65EF2C3A0871E6012EB
+PT=23C56E065427F0409504053DD8A994CD
+CT=7E666724C1CAC0A582325381E9C98D73
+
+I=356
+KEY=800EE65CA3DE8643371DA10FB0605AB649A62DEB566C76FB70F1F306F7A99F98
+PT=7E666724C1CAC0A582325381E9C98D73
+CT=B6C18D730A074196884CADF151CAC890
+
+I=357
+KEY=F526E578E8978822944644B146154425FF67A0985C6B376DF8BD5EF7A6635708
+PT=B6C18D730A074196884CADF151CAC890
+CT=0068BB370419CD39748559C2DE206817
+
+I=358
+KEY=7D144850BE03306F41A642442890EA20FF0F1BAF5872FA548C38073578433F1F
+PT=0068BB370419CD39748559C2DE206817
+CT=56852D240F01729C4EAD0B1FFC3EDA1F
+
+I=359
+KEY=33B2189E3774B1A066BE522C07550F88A98A368B577388C8C2950C2A847DE500
+PT=56852D240F01729C4EAD0B1FFC3EDA1F
+CT=458633A84E1F5737E9668A37388CF3C2
+
+I=360
+KEY=CF53C76250347B0CC5CAC660D52199B1EC0C0523196CDFFF2BF3861DBCF116C2
+PT=458633A84E1F5737E9668A37388CF3C2
+CT=F96E181E03350F27106C8D24403A49DD
+
+I=361
+KEY=618676C1702531077565060B5DA0570B15621D3D1A59D0D83B9F0B39FCCB5F1F
+PT=F96E181E03350F27106C8D24403A49DD
+CT=B515584E252F703A4EB55E81EDA58E30
+
+I=362
+KEY=D2C8CF9645CD741F67263845150FE649A07745733F76A0E2752A55B8116ED12F
+PT=B515584E252F703A4EB55E81EDA58E30
+CT=54E7D10C236785AFE0A93B3971D6F237
+
+I=363
+KEY=D0847F41C7940023491C2F83D02F8271F490947F1C11254D95836E8160B82318
+PT=54E7D10C236785AFE0A93B3971D6F237
+CT=937DFDE10E96030A0A8823EA3EF31B98
+
+I=364
+KEY=17502FC3077EFD420D2268CE0FF26F4667ED699E128726479F0B4D6B5E4B3880
+PT=937DFDE10E96030A0A8823EA3EF31B98
+CT=93FDF0392A3391C74DBE4229792C9630
+
+I=365
+KEY=4D6AA08A6C7EB7CA9CBE7AF4500C229EF41099A738B4B780D2B50F422767AEB0
+PT=93FDF0392A3391C74DBE4229792C9630
+CT=B9F80E1476658E6CE7FADBA215298958
+
+I=366
+KEY=D8820A50934290C146AFE477D9D4A0224DE897B34ED139EC354FD4E0324E27E8
+PT=B9F80E1476658E6CE7FADBA215298958
+CT=87ACDCD1F1332B9961CC5E18F9009A39
+
+I=367
+KEY=50E8959452DD52247A6F21A0C7BEDEB8CA444B62BFE2127554838AF8CB4EBDD1
+PT=87ACDCD1F1332B9961CC5E18F9009A39
+CT=3DD6249971FEC0FB4432236078D98D53
+
+I=368
+KEY=7A1973C5B90748596A54C709D1598DA5F7926FFBCE1CD28E10B1A998B3973082
+PT=3DD6249971FEC0FB4432236078D98D53
+CT=D540F8BDE3442D17E88B524D00618309
+
+I=369
+KEY=F9C08719A452CA931A62C5BD8F1D669D22D297462D58FF99F83AFBD5B3F6B38B
+PT=D540F8BDE3442D17E88B524D00618309
+CT=7BB18B2DA9ED188BCE3B18C02C9B3F3B
+
+I=370
+KEY=5EBA35F7E58381DBE29EC4A1D9B5B9AD59631C6B84B5E7123601E3159F6D8CB0
+PT=7BB18B2DA9ED188BCE3B18C02C9B3F3B
+CT=9A7380BAA169495B0FC29BB002D70E48
+
+I=371
+KEY=E442442FE32FA6BDA63AF0A6AC5D5AB2C3109CD125DCAE4939C378A59DBA82F8
+PT=9A7380BAA169495B0FC29BB002D70E48
+CT=88F3FE65298F7498A788E4196F13FC80
+
+I=372
+KEY=39079A8713E148703212A6F7FFD1B04D4BE362B40C53DAD19E4B9CBCF2A97E78
+PT=88F3FE65298F7498A788E4196F13FC80
+CT=A5E6361FBA6418CD9B2F50992B50A557
+
+I=373
+KEY=A99A33F38B36E3EE4DEE59F8A4282A84EE0554ABB637C21C0564CC25D9F9DB2F
+PT=A5E6361FBA6418CD9B2F50992B50A557
+CT=B1430F431ACC1C498FABF2D33B63CC67
+
+I=374
+KEY=BC09FAC540F44949F3B8EDFE2444CA725F465BE8ACFBDE558ACF3EF6E29A1748
+PT=B1430F431ACC1C498FABF2D33B63CC67
+CT=A90D76642D8D7899DD4A85EB92C89382
+
+I=375
+KEY=D26C1D07B51073C609030DC782FFAE93F64B2D8C8176A6CC5785BB1D705284CA
+PT=A90D76642D8D7899DD4A85EB92C89382
+CT=57522F39211100EF248D4A34E35CE4CE
+
+I=376
+KEY=2D7ADCD18F615F814B8D8B07CE48B4A1A11902B5A067A6237308F129930E6004
+PT=57522F39211100EF248D4A34E35CE4CE
+CT=87AED1E0C9F067C5F3F6D3D3BBCDE872
+
+I=377
+KEY=CA206C3442FAEFF3CB1292C675F52C2426B7D3556997C1E680FE22FA28C38876
+PT=87AED1E0C9F067C5F3F6D3D3BBCDE872
+CT=05798F53DFAE4A78D7BEEC24BE775B55
+
+I=378
+KEY=6ECC5BC346B18446D77FFBC44CCB0B1823CE5C06B6398B9E5740CEDE96B4D323
+PT=05798F53DFAE4A78D7BEEC24BE775B55
+CT=7677CE104395FFA15B51F81DAFBCAB1A
+
+I=379
+KEY=2E52C8E239CF1E959AB831307034FEF755B99216F5AC743F0C1136C339087839
+PT=7677CE104395FFA15B51F81DAFBCAB1A
+CT=760DE53561246F944B3E6279B39373F1
+
+I=380
+KEY=79B65B7D435E2134A1AB9A1CC1F08A8423B4772394881BAB472F54BA8A9B0BC8
+PT=760DE53561246F944B3E6279B39373F1
+CT=5B61CC978A9C808767C272432765EC0B
+
+I=381
+KEY=9EF57B89E7B8127348A9EF05E93DCC8D78D5BBB41E149B2C20ED26F9ADFEE7C3
+PT=5B61CC978A9C808767C272432765EC0B
+CT=902CDF3BD5E869E9CCFF8F2A454E1D42
+
+I=382
+KEY=15BB7B6BC685E4865BFA134C59CFC9C5E8F9648FCBFCF2C5EC12A9D3E8B0FA81
+PT=902CDF3BD5E869E9CCFF8F2A454E1D42
+CT=38264937B9372C316478BDF7AE578900
+
+I=383
+KEY=735D93C1DDD54986ACC6C2B0DFCC5E8AD0DF2DB872CBDEF4886A142446E77381
+PT=38264937B9372C316478BDF7AE578900
+CT=3BFE31D3E909E6EC3112F88DB8FFCA45
+
+I=384
+KEY=675B0E7FC5BCC3AF319B1D55C1F62CCAEB211C6B9BC23818B978ECA9FE18B9C4
+PT=3BFE31D3E909E6EC3112F88DB8FFCA45
+CT=2BFD5F6532BC1D2A8DA34481F9228B84
+
+I=385
+KEY=0AB242F9783E75D04E98733E63458F53C0DC430EA97E253234DBA828073A3240
+PT=2BFD5F6532BC1D2A8DA34481F9228B84
+CT=161481003108BAEFCC02BFD335C6A89F
+
+I=386
+KEY=58457CB82A24222839CF20D837F168A8D6C8C20E98769FDDF8D917FB32FC9ADF
+PT=161481003108BAEFCC02BFD335C6A89F
+CT=8A50E98A1165C1B6137231E519EC137B
+
+I=387
+KEY=C2C52CEA5654AAC9BD60FA04068094EF5C982B8489135E6BEBAB261E2B1089A4
+PT=8A50E98A1165C1B6137231E519EC137B
+CT=24ACAA0F045F5A6765D3B468550585B5
+
+I=388
+KEY=816757A434D81AA348E0B2F4FC44F4387834818B8D4C040C8E7892767E150C11
+PT=24ACAA0F045F5A6765D3B468550585B5
+CT=9993F9CBDAD9CA98C74CCBDB3E079F50
+
+I=389
+KEY=647A9F1E43B08FD15EFC17342EB8970AE1A778405795CE94493459AD40129341
+PT=9993F9CBDAD9CA98C74CCBDB3E079F50
+CT=F676785AEF58297C28035E8E065829FF
+
+I=390
+KEY=4BB8B5020862EA9228B663DEDB39336717D1001AB8CDE7E861370723464ABABE
+PT=F676785AEF58297C28035E8E065829FF
+CT=ED16C74BD4252F7B72AA37D11E198508
+
+I=391
+KEY=5392AAED87CE40891A69F4690A8743FBFAC7C7516CE8C893139D30F258533FB6
+PT=ED16C74BD4252F7B72AA37D11E198508
+CT=3BE7B6A9E197598146E98B7A501A2226
+
+I=392
+KEY=9D8BABE9C12E6BA3A18EB23A92205456C12071F88D7F91125574BB8808491D90
+PT=3BE7B6A9E197598146E98B7A501A2226
+CT=CC1163A3D9AF3307ED740591AB66BD81
+
+I=393
+KEY=231B451E506AC98FF993A3C7AD9C37F70D31125B54D0A215B800BE19A32FA011
+PT=CC1163A3D9AF3307ED740591AB66BD81
+CT=43FB8B2B44C740956111DA816616771D
+
+I=394
+KEY=1699C517EE1713D02C6EA0957E4A00CE4ECA99701017E280D9116498C539D70C
+PT=43FB8B2B44C740956111DA816616771D
+CT=A511AEA01DB8E7E16E7C53931625BEC3
+
+I=395
+KEY=2624CE7970CC5DAFAC73C881FDD5F6EBEBDB37D00DAF0561B76D370BD31C69CF
+PT=A511AEA01DB8E7E16E7C53931625BEC3
+CT=82EF6D2A1FF1DBCDF39DC04BE523229F
+
+I=396
+KEY=60C9931E19ED0D095F8DF75AEA56689769345AFA125EDEAC44F0F740363F4B50
+PT=82EF6D2A1FF1DBCDF39DC04BE523229F
+CT=A595C8AAAAAD80DD4F40693FF2D89A19
+
+I=397
+KEY=D461E3605B0AD0E87F5A078ECFE25934CCA19250B8F35E710BB09E7FC4E7D149
+PT=A595C8AAAAAD80DD4F40693FF2D89A19
+CT=57B18DFEAD129795C3BB8D6C06764729
+
+I=398
+KEY=0BE3FC6C21764F1C15782D52D92919A09B101FAE15E1C9E4C80B1313C2919660
+PT=57B18DFEAD129795C3BB8D6C06764729
+CT=6F8606BBA6CC03A5D0A64FE21E277B60
+
+I=399
+KEY=982D617A0F737342E99123A5A573D266F4961915B32DCA4118AD5CF1DCB6ED00
+PT=6F8606BBA6CC03A5D0A64FE21E277B60
+CT=1F6763DF807A7E70960D4CD3118E601A
+
+===========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/ecb_iv.readme b/krb5-1-6/src/lib/crypto/aes/test/ecb_iv.readme
new file mode 100644
index 000000000..c37215768
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/ecb_iv.readme
@@ -0,0 +1,19 @@
+Description of the Intermediate Value Known Answer Test
+--------------------------------------------------------
+
+The test encrypts one plaintext with a variable number of rounds.
+In ECB encryption mode, the output PTi is the output after the 
+initial key addition and i rounds (a round ends with a key
+addition). 
+
+As explained in the documentation, in ECB decryption mode 
+there are several definitions of a `round' possible. In order
+to make visual inspection more intuitive, we output the
+intermediate values that correspond with the output of the
+encryption mode. 
+These values might actually not occur in a practical decryption,
+especially in an optimised implementation, where various operations
+of different rounds are interchanged.
+
+This explains also why the Java and the C code output different
+files for this test.
diff --git a/krb5-1-6/src/lib/crypto/aes/test/ecb_iv.txt b/krb5-1-6/src/lib/crypto/aes/test/ecb_iv.txt
new file mode 100644
index 000000000..3f6608e4e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/ecb_iv.txt
@@ -0,0 +1,123 @@
+
+=========================
+
+FILENAME:  "ecb_iv.txt"
+
+Electronic Codebook (ECB) Mode
+Intermediate Value Known Answer Tests
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+==========
+
+KEYSIZE=128
+KEY=000102030405060708090A0B0C0D0E0F
+
+Intermediate Ciphertext Values (Encryption)
+
+PT=000102030405060708090A0B0C0D0E0F
+CT1=B5C9179EB1CC1199B9C51B92B5C8159D
+CT2=2B65F6374C427C5B2FE3A9256896755B
+CT3=D1015FCBB4EF65679688462076B9D6AD
+CT4=8E17064A2A35A183729FE59FF3A591F1
+CT5=D7557DD55999DB3259E2183D558DCDD2
+CT6=73A96A5D7799A5F3111D2B63684B1F7F
+CT7=1B6B853069EEFC749AFEFD7B57A04CD1
+CT8=107EEADFB6F77933B5457A6F08F046B2
+CT9=8EC166481A677AA96A14FF6ECE88C010
+CT=0A940BB5416EF045F1C39458C653EA5A
+
+Intermediate Ciphertext Values (Decryption)
+
+CT=0A940BB5416EF045F1C39458C653EA5A
+PT1=8EC166481A677AA96A14FF6ECE88C010
+PT2=107EEADFB6F77933B5457A6F08F046B2
+PT3=1B6B853069EEFC749AFEFD7B57A04CD1
+PT4=73A96A5D7799A5F3111D2B63684B1F7F
+PT5=D7557DD55999DB3259E2183D558DCDD2
+PT6=8E17064A2A35A183729FE59FF3A591F1
+PT7=D1015FCBB4EF65679688462076B9D6AD
+PT8=2B65F6374C427C5B2FE3A9256896755B
+PT9=B5C9179EB1CC1199B9C51B92B5C8159D
+PT=000102030405060708090A0B0C0D0E0F
+
+==========
+
+KEYSIZE=192
+KEY=000102030405060708090A0B0C0D0E0F1011121314151617
+
+Intermediate Ciphertext Values (Encryption)
+
+PT=000102030405060708090A0B0C0D0E0F
+CT1=73727170777675743B25919A3F20979D
+CT2=C673B27A311EC2EB64AD47FF53B233D7
+CT3=0B5CC6BA34C807E6496D79B46826A1E8
+CT4=005B53A5B660E280307883487E4D1A4D
+CT5=88A105F0DDD45F3674DBC3DE1A211B03
+CT6=EB5CD8B5FD8A3F33F03A70FB5C620C06
+CT7=909913B09BD2CC5A70B6C647931F0A1F
+CT8=6EB6CA10E395AFD646B02C5E9E745A9F
+CT9=2CFD2FC41AF82B8DFB80E9BD1C989ECE
+CT10=31C5D5E27EAF073E5C21ADAAEAA969D4
+CT11=1DB94956A7268B0DE963D27E55868580
+CT=0060BFFE46834BB8DA5CF9A61FF220AE
+
+Intermediate Ciphertext Values (Decryption)
+
+CT=0060BFFE46834BB8DA5CF9A61FF220AE
+PT1=1DB94956A7268B0DE963D27E55868580
+PT2=31C5D5E27EAF073E5C21ADAAEAA969D4
+PT3=2CFD2FC41AF82B8DFB80E9BD1C989ECE
+PT4=6EB6CA10E395AFD646B02C5E9E745A9F
+PT5=909913B09BD2CC5A70B6C647931F0A1F
+PT6=EB5CD8B5FD8A3F33F03A70FB5C620C06
+PT7=88A105F0DDD45F3674DBC3DE1A211B03
+PT8=005B53A5B660E280307883487E4D1A4D
+PT9=0B5CC6BA34C807E6496D79B46826A1E8
+PT10=C673B27A311EC2EB64AD47FF53B233D7
+PT11=73727170777675743B25919A3F20979D
+PT=000102030405060708090A0B0C0D0E0F
+
+==========
+
+KEYSIZE=256
+KEY=000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+
+Intermediate Ciphertext Values (Encryption)
+
+PT=000102030405060708090A0B0C0D0E0F
+CT1=73727170777675747B7A79787F7E7D7C
+CT2=4E5D32BB8B67FD1BD4CFEC9FFB20AC4F
+CT3=96A212E486341549C4AAF7C843F0277A
+CT4=0F45F284CDD0CB16E3EA81ECC891A4E1
+CT5=E59BFC458A89063E0137BBE6DB63A058
+CT6=1D958D960EA3143383C17D5CD87BA327
+CT7=43843EF40D9219481935B77A586DB5DE
+CT8=5AA5ABADBC40230CBA6124E9FAEEEFB5
+CT9=DAD61937BDFD582927F14C990C5FC761
+CT10=E8A48C5DEE5C0792AB6DFFF5B038529D
+CT11=4B71E5A8BFB4E9A5312A18119E68E829
+CT12=DCBA75CEE6589DDC0D289A172E8415B5
+CT13=8A0E856B2074C1093104131D0628BFE8
+CT=5A6E045708FB7196F02E553D02C3A692
+
+Intermediate Ciphertext Values (Decryption)
+
+CT=5A6E045708FB7196F02E553D02C3A692
+PT1=8A0E856B2074C1093104131D0628BFE8
+PT2=DCBA75CEE6589DDC0D289A172E8415B5
+PT3=4B71E5A8BFB4E9A5312A18119E68E829
+PT4=E8A48C5DEE5C0792AB6DFFF5B038529D
+PT5=DAD61937BDFD582927F14C990C5FC761
+PT6=5AA5ABADBC40230CBA6124E9FAEEEFB5
+PT7=43843EF40D9219481935B77A586DB5DE
+PT8=1D958D960EA3143383C17D5CD87BA327
+PT9=E59BFC458A89063E0137BBE6DB63A058
+PT10=0F45F284CDD0CB16E3EA81ECC891A4E1
+PT11=96A212E486341549C4AAF7C843F0277A
+PT12=4E5D32BB8B67FD1BD4CFEC9FFB20AC4F
+PT13=73727170777675747B7A79787F7E7D7C
+PT=000102030405060708090A0B0C0D0E0F
+
+==========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/ecb_tbl.txt b/krb5-1-6/src/lib/crypto/aes/test/ecb_tbl.txt
new file mode 100644
index 000000000..f1eef5300
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/ecb_tbl.txt
@@ -0,0 +1,1955 @@
+/* Description of what tables are tested:
+   The provided implementations each use a different set of tables
+    - Java implementation: uses no tables
+    - reference C implementation: uses Logtable, Alogtable, S, Si, rcon
+    - fast C implementation: uses Logtable, Alogtable,  rcon
+        and additionally, T1, T2, T3, T4, T5, T6, T7, T8
+        and (for the inverse key schedule only) U1, U2, U3, U4.
+   All these tables are tested.
+
+=========================
+
+FILENAME:  "ecb_tbl.txt"
+
+Electronic Codebook (ECB) Mode
+Tables Known Answer Tests
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+==========
+
+KEYSIZE=128
+
+
+I=1
+KEY=00010203050607080A0B0C0D0F101112
+PT=506812A45F08C889B97F5980038B8359
+CT=D8F532538289EF7D06B506A4FD5BE9C9
+
+I=2
+KEY=14151617191A1B1C1E1F202123242526
+PT=5C6D71CA30DE8B8B00549984D2EC7D4B
+CT=59AB30F4D4EE6E4FF9907EF65B1FB68C
+
+I=3
+KEY=28292A2B2D2E2F30323334353738393A
+PT=53F3F4C64F8616E4E7C56199F48F21F6
+CT=BF1ED2FCB2AF3FD41443B56D85025CB1
+
+I=4
+KEY=3C3D3E3F41424344464748494B4C4D4E
+PT=A1EB65A3487165FB0F1C27FF9959F703
+CT=7316632D5C32233EDCB0780560EAE8B2
+
+I=5
+KEY=50515253555657585A5B5C5D5F606162
+PT=3553ECF0B1739558B08E350A98A39BFA
+CT=408C073E3E2538072B72625E68B8364B
+
+I=6
+KEY=64656667696A6B6C6E6F707173747576
+PT=67429969490B9711AE2B01DC497AFDE8
+CT=E1F94DFA776597BEACA262F2F6366FEA
+
+I=7
+KEY=78797A7B7D7E7F80828384858788898A
+PT=93385C1F2AEC8BED192F5A8E161DD508
+CT=F29E986C6A1C27D7B29FFD7EE92B75F1
+
+I=8
+KEY=8C8D8E8F91929394969798999B9C9D9E
+PT=B5BF946BE19BEB8DB3983B5F4C6E8DDB
+CT=131C886A57F8C2E713ABA6955E2B55B5
+
+I=9
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+PT=41321EE10E21BD907227C4450FF42324
+CT=D2AB7662DF9B8C740210E5EEB61C199D
+
+I=10
+KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+PT=00A82F59C91C8486D12C0A80124F6089
+CT=14C10554B2859C484CAB5869BBE7C470
+
+I=11
+KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA
+PT=7CE0FD076754691B4BBD9FAF8A1372FE
+CT=DB4D498F0A49CF55445D502C1F9AB3B5
+
+I=12
+KEY=DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=23605A8243D07764541BC5AD355B3129
+CT=6D96FEF7D66590A77A77BB2056667F7F
+
+I=13
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE010002
+PT=12A8CFA23EA764FD876232B4E842BC44
+CT=316FB68EDBA736C53E78477BF913725C
+
+I=14
+KEY=04050607090A0B0C0E0F101113141516
+PT=BCAF32415E8308B3723E5FDD853CCC80
+CT=6936F2B93AF8397FD3A771FC011C8C37
+
+I=15
+KEY=2C2D2E2F31323334363738393B3C3D3E
+PT=89AFAE685D801AD747ACE91FC49ADDE0
+CT=F3F92F7A9C59179C1FCC2C2BA0B082CD
+
+I=16
+KEY=40414243454647484A4B4C4D4F505152
+PT=F521D07B484357C4A69E76124A634216
+CT=6A95EA659EE3889158E7A9152FF04EBC
+
+I=17
+KEY=54555657595A5B5C5E5F606163646566
+PT=3E23B3BC065BCC152407E23896D77783
+CT=1959338344E945670678A5D432C90B93
+
+I=18
+KEY=68696A6B6D6E6F70727374757778797A
+PT=79F0FBA002BE1744670E7E99290D8F52
+CT=E49BDDD2369B83EE66E6C75A1161B394
+
+I=19
+KEY=7C7D7E7F81828384868788898B8C8D8E
+PT=DA23FE9D5BD63E1D72E3DAFBE21A6C2A
+CT=D3388F19057FF704B70784164A74867D
+
+I=20
+KEY=A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+PT=E3F5698BA90B6A022EFD7DB2C7E6C823
+CT=23AA03E2D5E4CD24F3217E596480D1E1
+
+I=21
+KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2
+PT=BDC2691D4F1B73D2700679C3BCBF9C6E
+CT=C84113D68B666AB2A50A8BDB222E91B9
+
+I=22
+KEY=08090A0B0D0E0F10121314151718191A
+PT=BA74E02093217EE1BA1B42BD5624349A
+CT=AC02403981CD4340B507963DB65CB7B6
+
+I=23
+KEY=6C6D6E6F71727374767778797B7C7D7E
+PT=B5C593B5851C57FBF8B3F57715E8F680
+CT=8D1299236223359474011F6BF5088414
+
+I=24
+KEY=80818283858687888A8B8C8D8F909192
+PT=3DA9BD9CEC072381788F9387C3BBF4EE
+CT=5A1D6AB8605505F7977E55B9A54D9B90
+
+I=25
+KEY=94959697999A9B9C9E9FA0A1A3A4A5A6
+PT=4197F3051121702AB65D316B3C637374
+CT=72E9C2D519CF555E4208805AABE3B258
+
+I=26
+KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA
+PT=9F46C62EC4F6EE3F6E8C62554BC48AB7
+CT=A8F3E81C4A23A39EF4D745DFFE026E80
+
+I=27
+KEY=BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+PT=0220673FE9E699A4EBC8E0DBEB6979C8
+CT=546F646449D31458F9EB4EF5483AEE6C
+
+I=28
+KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2
+PT=B2B99171337DED9BC8C2C23FF6F18867
+CT=4DBE4BC84AC797C0EE4EFB7F1A07401C
+
+I=29
+KEY=E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+PT=A7FACF4E301E984E5EFEEFD645B23505
+CT=25E10BFB411BBD4D625AC8795C8CA3B3
+
+I=30
+KEY=F8F9FAFBFDFEFE00020304050708090A
+PT=F7C762E4A9819160FD7ACFB6C4EEDCDD
+CT=315637405054EC803614E43DEF177579
+
+I=31
+KEY=0C0D0E0F11121314161718191B1C1D1E
+PT=9B64FC21EA08709F4915436FAA70F1BE
+CT=60C5BC8A1410247295C6386C59E572A8
+
+I=32
+KEY=20212223252627282A2B2C2D2F303132
+PT=52AF2C3DE07EE6777F55A4ABFC100B3F
+CT=01366FC8CA52DFE055D6A00A76471BA6
+
+I=33
+KEY=34353637393A3B3C3E3F404143444546
+PT=2FCA001224386C57AA3F968CBE2C816F
+CT=ECC46595516EC612449C3F581E7D42FF
+
+I=34
+KEY=48494A4B4D4E4F50525354555758595A
+PT=4149C73658A4A9C564342755EE2C132F
+CT=6B7FFE4C602A154B06EE9C7DAB5331C9
+
+I=35
+KEY=5C5D5E5F61626364666768696B6C6D6E
+PT=AF60005A00A1772F7C07A48A923C23D2
+CT=7DA234C14039A240DD02DD0FBF84EB67
+
+I=36
+KEY=70717273757677787A7B7C7D7F808182
+PT=6FCCBC28363759914B6F0280AFAF20C6
+CT=C7DC217D9E3604FFE7E91F080ECD5A3A
+
+I=37
+KEY=84858687898A8B8C8E8F909193949596
+PT=7D82A43DDF4FEFA2FC5947499884D386
+CT=37785901863F5C81260EA41E7580CDA5
+
+I=38
+KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AA
+PT=5D5A990EAAB9093AFE4CE254DFA49EF9
+CT=A07B9338E92ED105E6AD720FCCCE9FE4
+
+I=39
+KEY=ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+PT=4CD1E2FD3F4434B553AAE453F0ED1A02
+CT=AE0FB9722418CC21A7DA816BBC61322C
+
+I=40
+KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2
+PT=5A2C9A9641D4299125FA1B9363104B5E
+CT=C826A193080FF91FFB21F71D3373C877
+
+I=41
+KEY=D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+PT=B517FE34C0FA217D341740BFD4FE8DD4
+CT=1181B11B0E494E8D8B0AA6B1D5AC2C48
+
+I=42
+KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA
+PT=014BAF2278A69D331D5180103643E99A
+CT=6743C3D1519AB4F2CD9A78AB09A511BD
+
+I=43
+KEY=FCFDFEFF01020304060708090B0C0D0E
+PT=B529BD8164F20D0AA443D4932116841C
+CT=DC55C076D52BACDF2EEFD952946A439D
+
+I=44
+KEY=10111213151617181A1B1C1D1F202122
+PT=2E596DCBB2F33D4216A1176D5BD1E456
+CT=711B17B590FFC72B5C8E342B601E8003
+
+I=45
+KEY=24252627292A2B2C2E2F303133343536
+PT=7274A1EA2B7EE2424E9A0E4673689143
+CT=19983BB0950783A537E1339F4AA21C75
+
+I=46
+KEY=38393A3B3D3E3F40424344454748494A
+PT=AE20020BD4F13E9D90140BEE3B5D26AF
+CT=3BA7762E15554169C0F4FA39164C410C
+
+I=47
+KEY=4C4D4E4F51525354565758595B5C5D5E
+PT=BAAC065DA7AC26E855E79C8849D75A02
+CT=A0564C41245AFCA7AF8AA2E0E588EA89
+
+I=48
+KEY=60616263656667686A6B6C6D6F707172
+PT=7C917D8D1D45FAB9E2540E28832540CC
+CT=5E36A42A2E099F54AE85ECD92E2381ED
+
+I=49
+KEY=74757677797A7B7C7E7F808183848586
+PT=BDE6F89E16DAADB0E847A2A614566A91
+CT=770036F878CD0F6CA2268172F106F2FE
+
+I=50
+KEY=88898A8B8D8E8F90929394959798999A
+PT=C9DE163725F1F5BE44EBB1DB51D07FBC
+CT=7E4E03908B716116443CCF7C94E7C259
+
+I=51
+KEY=9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+PT=3AF57A58F0C07DFFA669572B521E2B92
+CT=482735A48C30613A242DD494C7F9185D
+
+I=52
+KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2
+PT=3D5EBAC306DDE4604F1B4FBBBFCDAE55
+CT=B4C0F6C9D4D7079ADDF9369FC081061D
+
+I=53
+KEY=C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+PT=C2DFA91BCEB76A1183C995020AC0B556
+CT=D5810FE0509AC53EDCD74F89962E6270
+
+I=54
+KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EA
+PT=C70F54305885E9A0746D01EC56C8596B
+CT=03F17A16B3F91848269ECDD38EBB2165
+
+I=55
+KEY=ECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+PT=C4F81B610E98012CE000182050C0C2B2
+CT=DA1248C3180348BAD4A93B4D9856C9DF
+
+I=56
+KEY=00010203050607080A0B0C0D0F101112
+PT=EAAB86B1D02A95D7404EFF67489F97D4
+CT=3D10D7B63F3452C06CDF6CCE18BE0C2C
+
+I=57
+KEY=14151617191A1B1C1E1F202123242526
+PT=7C55BDB40B88870B52BEC3738DE82886
+CT=4AB823E7477DFDDC0E6789018FCB6258
+
+I=58
+KEY=28292A2B2D2E2F30323334353738393A
+PT=BA6EAA88371FF0A3BD875E3F2A975CE0
+CT=E6478BA56A77E70CFDAA5C843ABDE30E
+
+I=59
+KEY=3C3D3E3F41424344464748494B4C4D4E
+PT=08059130C4C24BD30CF0575E4E0373DC
+CT=1673064895FBEAF7F09C5429FF75772D
+
+I=60
+KEY=50515253555657585A5B5C5D5F606162
+PT=9A8EAB004EF53093DFCF96F57E7EDA82
+CT=4488033AE9F2EFD0CA9383BFCA1A94E9
+
+I=61
+KEY=64656667696A6B6C6E6F707173747576
+PT=0745B589E2400C25F117B1D796C28129
+CT=978F3B8C8F9D6F46626CAC3C0BCB9217
+
+I=62
+KEY=78797A7B7D7E7F80828384858788898A
+PT=2F1777781216CEC3F044F134B1B92BBE
+CT=E08C8A7E582E15E5527F1D9E2EECB236
+
+I=63
+KEY=8C8D8E8F91929394969798999B9C9D9E
+PT=353A779FFC541B3A3805D90CE17580FC
+CT=CEC155B76AC5FFDA4CF4F9CA91E49A7A
+
+I=64
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+PT=1A1EAE4415CEFCF08C4AC1C8F68BEA8F
+CT=D5AC7165763225DD2A38CDC6862C29AD
+
+I=65
+KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+PT=E6E7E4E5B0B3B2B5D4D5AAAB16111013
+CT=03680FE19F7CE7275452020BE70E8204
+
+I=66
+KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA
+PT=F8F9FAFBFBF8F9E677767170EFE0E1E2
+CT=461DF740C9781C388E94BB861CEB54F6
+
+I=67
+KEY=DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=63626160A1A2A3A445444B4A75727370
+CT=451BD60367F96483042742219786A074
+
+I=68
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE010002
+PT=717073720605040B2D2C2B2A05FAFBF9
+CT=E4DFA42671A02E57EF173B85C0EA9F2B
+
+I=69
+KEY=04050607090A0B0C0E0F101113141516
+PT=78797A7BEAE9E8EF3736292891969794
+CT=ED11B89E76274282227D854700A78B9E
+
+I=70
+KEY=18191A1B1D1E1F20222324252728292A
+PT=838281803231300FDDDCDBDAA0AFAEAD
+CT=433946EAA51EA47AF33895F2B90B3B75
+
+I=71
+KEY=2C2D2E2F31323334363738393B3C3D3E
+PT=18191A1BBFBCBDBA75747B7A7F78797A
+CT=6BC6D616A5D7D0284A5910AB35022528
+
+I=72
+KEY=40414243454647484A4B4C4D4F505152
+PT=848586879B989996A3A2A5A4849B9A99
+CT=D2A920ECFE919D354B5F49EAE9719C98
+
+I=73
+KEY=54555657595A5B5C5E5F606163646566
+PT=0001020322212027CACBF4F551565754
+CT=3A061B17F6A92885EFBD0676985B373D
+
+I=74
+KEY=68696A6B6D6E6F70727374757778797A
+PT=CECFCCCDAFACADB2515057564A454447
+CT=FADEEC16E33EA2F4688499D157E20D8F
+
+I=75
+KEY=7C7D7E7F81828384868788898B8C8D8E
+PT=92939091CDCECFC813121D1C80878685
+CT=5CDEFEDE59601AA3C3CDA36FA6B1FA13
+
+I=76
+KEY=90919293959697989A9B9C9D9FA0A1A2
+PT=D2D3D0D16F6C6D6259585F5ED1EEEFEC
+CT=9574B00039844D92EBBA7EE8719265F8
+
+I=77
+KEY=A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+PT=ACADAEAF878485820F0E1110D5D2D3D0
+CT=9A9CF33758671787E5006928188643FA
+
+I=78
+KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CA
+PT=9091929364676619E6E7E0E1757A7B78
+CT=2CDDD634C846BA66BB46CBFEA4A674F9
+
+I=79
+KEY=CCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+PT=BABBB8B98A89888F74757A7B92959497
+CT=D28BAE029393C3E7E26E9FAFBBB4B98F
+
+I=80
+KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2
+PT=8D8C8F8E6E6D6C633B3A3D3CCAD5D4D7
+CT=EC27529B1BEE0A9AB6A0D73EBC82E9B7
+
+I=81
+KEY=F4F5F6F7F9FAFBFCFEFE010103040506
+PT=86878485010203040808F7F767606162
+CT=3CB25C09472AFF6EE7E2B47CCD7CCB17
+
+I=82
+KEY=08090A0B0D0E0F10121314151718191A
+PT=8E8F8C8D656667788A8B8C8D010E0F0C
+CT=DEE33103A7283370D725E44CA38F8FE5
+
+I=83
+KEY=1C1D1E1F21222324262728292B2C2D2E
+PT=C8C9CACB858687807A7B7475E7E0E1E2
+CT=27F9BCD1AAC64BFFC11E7815702C1A69
+
+I=84
+KEY=30313233353637383A3B3C3D3F404142
+PT=6D6C6F6E5053525D8C8D8A8BADD2D3D0
+CT=5DF534FFAD4ED0749A9988E9849D0021
+
+I=85
+KEY=44454647494A4B4C4E4F505153545556
+PT=28292A2B393A3B3C0607181903040506
+CT=A48BEE75DB04FB60CA2B80F752A8421B
+
+I=86
+KEY=58595A5B5D5E5F60626364656768696A
+PT=A5A4A7A6B0B3B28DDBDADDDCBDB2B3B0
+CT=024C8CF70BC86EE5CE03678CB7AF45F9
+
+I=87
+KEY=6C6D6E6F71727374767778797B7C7D7E
+PT=323330316467666130313E3F2C2B2A29
+CT=3C19AC0F8A3A3862CE577831301E166B
+
+I=88
+KEY=80818283858687888A8B8C8D8F909192
+PT=27262524080B0A05171611100B141516
+CT=C5E355B796A57421D59CA6BE82E73BCA
+
+I=89
+KEY=94959697999A9B9C9E9FA0A1A3A4A5A6
+PT=040506074142434435340B0AA3A4A5A6
+CT=D94033276417ABFB05A69D15B6E386E2
+
+I=90
+KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA
+PT=242526271112130C61606766BDB2B3B0
+CT=24B36559EA3A9B9B958FE6DA3E5B8D85
+
+I=91
+KEY=BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+PT=4B4A4948252627209E9F9091CEC9C8CB
+CT=20FD4FEAA0E8BF0CCE7861D74EF4CB72
+
+I=92
+KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2
+PT=68696A6B6665646B9F9E9998D9E6E7E4
+CT=350E20D5174277B9EC314C501570A11D
+
+I=93
+KEY=E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+PT=34353637C5C6C7C0F0F1EEEF7C7B7A79
+CT=87A29D61B7C604D238FE73045A7EFD57
+
+I=94
+KEY=F8F9FAFBFDFEFE00020304050708090A
+PT=32333031C2C1C13F0D0C0B0A050A0B08
+CT=2C3164C1CC7D0064816BDC0FAA362C52
+
+I=95
+KEY=0C0D0E0F11121314161718191B1C1D1E
+PT=CDCCCFCEBEBDBCBBABAAA5A4181F1E1D
+CT=195FE5E8A05A2ED594F6E4400EEE10B3
+
+I=96
+KEY=20212223252627282A2B2C2D2F303132
+PT=212023223635343BA0A1A6A7445B5A59
+CT=E4663DF19B9A21A5A284C2BD7F905025
+
+I=97
+KEY=34353637393A3B3C3E3F404143444546
+PT=0E0F0C0DA8ABAAAD2F2E515002050407
+CT=21B88714CFB4E2A933BD281A2C4743FD
+
+I=98
+KEY=48494A4B4D4E4F50525354555758595A
+PT=070605042A2928378E8F8889BDB2B3B0
+CT=CBFC3980D704FD0FC54378AB84E17870
+
+I=99
+KEY=5C5D5E5F61626364666768696B6C6D6E
+PT=CBCAC9C893909196A9A8A7A6A5A2A3A0
+CT=BC5144BAA48BDEB8B63E22E03DA418EF
+
+I=100
+KEY=70717273757677787A7B7C7D7F808182
+PT=80818283C1C2C3CC9C9D9A9B0CF3F2F1
+CT=5A1DBAEF1EE2984B8395DA3BDFFA3CCC
+
+I=101
+KEY=84858687898A8B8C8E8F909193949596
+PT=1213101125262720FAFBE4E5B1B6B7B4
+CT=F0B11CD0729DFCC80CEC903D97159574
+
+I=102
+KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AA
+PT=7F7E7D7C3033320D97969190222D2C2F
+CT=9F95314ACFDDC6D1914B7F19A9CC8209
+
+I=103
+KEY=ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+PT=4E4F4C4D484B4A4D81808F8E53545556
+CT=595736F6F0F70914A94E9E007F022519
+
+I=104
+KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2
+PT=DCDDDEDFB0B3B2BD15141312A1BEBFBC
+CT=1F19F57892CAE586FCDFB4C694DEB183
+
+I=105
+KEY=D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+PT=93929190282B2A2DC4C5FAFB92959497
+CT=540700EE1F6F3DAB0B3EDDF6CAEE1EF5
+
+I=106
+KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA
+PT=F5F4F7F6C4C7C6D9373631307E717073
+CT=14A342A91019A331687A2254E6626CA2
+
+I=107
+KEY=FCFDFEFF01020304060708090B0C0D0E
+PT=93929190B6B5B4B364656A6B05020300
+CT=7B25F3C3B2EEA18D743EF283140F29FF
+
+I=108
+KEY=10111213151617181A1B1C1D1F202122
+PT=BABBB8B90D0E0F00A4A5A2A3043B3A39
+CT=46C2587D66E5E6FA7F7CA6411AD28047
+
+I=109
+KEY=24252627292A2B2C2E2F303133343536
+PT=D8D9DADB7F7C7D7A10110E0F787F7E7D
+CT=09470E72229D954ED5EE73886DFEEBA9
+
+I=110
+KEY=38393A3B3D3E3F40424344454748494A
+PT=FEFFFCFDEFECED923B3A3D3C6768696A
+CT=D77C03DE92D4D0D79EF8D4824EF365EB
+
+I=111
+KEY=4C4D4E4F51525354565758595B5C5D5E
+PT=D6D7D4D58A89888F96979899A5A2A3A0
+CT=1D190219F290E0F1715D152D41A23593
+
+I=112
+KEY=60616263656667686A6B6C6D6F707172
+PT=18191A1BA8ABAAA5303136379B848586
+CT=A2CD332CE3A0818769616292E87F757B
+
+I=113
+KEY=74757677797A7B7C7E7F808183848586
+PT=6B6A6968A4A7A6A1D6D72829B0B7B6B5
+CT=D54AFA6CE60FBF9341A3690E21385102
+
+I=114
+KEY=88898A8B8D8E8F90929394959798999A
+PT=000102038A89889755545352A6A9A8AB
+CT=06E5C364DED628A3F5E05E613E356F46
+
+I=115
+KEY=9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+PT=2D2C2F2EB3B0B1B6B6B7B8B9F2F5F4F7
+CT=EAE63C0E62556DAC85D221099896355A
+
+I=116
+KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2
+PT=979695943536373856575051E09F9E9D
+CT=1FED060E2C6FC93EE764403A889985A2
+
+I=117
+KEY=C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+PT=A4A5A6A7989B9A9DB1B0AFAE7A7D7C7F
+CT=C25235C1A30FDEC1C7CB5C5737B2A588
+
+I=118
+KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EA
+PT=C1C0C3C2686B6A55A8A9AEAFEAE5E4E7
+CT=796DBEF95147D4D30873AD8B7B92EFC0
+
+I=119
+KEY=ECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+PT=C1C0C3C2141716118C8D828364636261
+CT=CBCF0FB34D98D0BD5C22CE37211A46BF
+
+I=120
+KEY=00010203050607080A0B0C0D0F101112
+PT=93929190CCCFCEC196979091E0FFFEFD
+CT=94B44DA6466126CAFA7C7FD09063FC24
+
+I=121
+KEY=14151617191A1B1C1E1F202123242526
+PT=B4B5B6B7F9FAFBFC25241B1A6E69686B
+CT=D78C5B5EBF9B4DBDA6AE506C5074C8FE
+
+I=122
+KEY=28292A2B2D2E2F30323334353738393A
+PT=868784850704051AC7C6C1C08788898A
+CT=6C27444C27204B043812CF8CF95F9769
+
+I=123
+KEY=3C3D3E3F41424344464748494B4C4D4E
+PT=F4F5F6F7AAA9A8AFFDFCF3F277707172
+CT=BE94524EE5A2AA50BBA8B75F4C0AEBCF
+
+I=124
+KEY=50515253555657585A5B5C5D5F606162
+PT=D3D2D1D00605040BC3C2C5C43E010003
+CT=A0AEAAE91BA9F31F51AEB3588CF3A39E
+
+I=125
+KEY=64656667696A6B6C6E6F707173747576
+PT=73727170424140476A6B74750D0A0B08
+CT=275297779C28266EF9FE4C6A13C08488
+
+I=126
+KEY=78797A7B7D7E7F80828384858788898A
+PT=C2C3C0C10A0908F754555253A1AEAFAC
+CT=86523D92BB8672CB01CF4A77FD725882
+
+I=127
+KEY=8C8D8E8F91929394969798999B9C9D9E
+PT=6D6C6F6EF8FBFAFD82838C8DF8FFFEFD
+CT=4B8327640E9F33322A04DD96FCBF9A36
+
+I=128
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+PT=F5F4F7F684878689A6A7A0A1D2CDCCCF
+CT=CE52AF650D088CA559425223F4D32694
+
+==========
+
+KEYSIZE=192
+
+
+I=1
+KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C
+PT=2D33EEF2C0430A8A9EBF45E809C40BB6
+CT=DFF4945E0336DF4C1C56BC700EFF837F
+
+I=2
+KEY=1E1F20212324252628292A2B2D2E2F30323334353738393A
+PT=6AA375D1FA155A61FB72353E0A5A8756
+CT=B6FDDEF4752765E347D5D2DC196D1252
+
+I=3
+KEY=3C3D3E3F41424344464748494B4C4D4E5051525355565758
+PT=BC3736518B9490DCB8ED60EB26758ED4
+CT=D23684E3D963B3AFCF1A114ACA90CBD6
+
+I=4
+KEY=5A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+PT=AA214402B46CFFB9F761EC11263A311E
+CT=3A7AC027753E2A18C2CEAB9E17C11FD0
+
+I=5
+KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394
+PT=02AEA86E572EEAB66B2C3AF5E9A46FD6
+CT=8F6786BD007528BA26603C1601CDD0D8
+
+I=6
+KEY=969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+PT=E2AEF6ACC33B965C4FA1F91C75FF6F36
+CT=D17D073B01E71502E28B47AB551168B3
+
+I=7
+KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0
+PT=0659DF46427162B9434865DD9499F91D
+CT=A469DA517119FAB95876F41D06D40FFA
+
+I=8
+KEY=D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=49A44239C748FEB456F59C276A5658DF
+CT=6091AA3B695C11F5C0B6AD26D3D862FF
+
+I=9
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C
+PT=66208F6E9D04525BDEDB2733B6A6BE37
+CT=70F9E67F9F8DF1294131662DC6E69364
+
+I=10
+KEY=0E0F10111314151618191A1B1D1E1F20222324252728292A
+PT=3393F8DFC729C97F5480B950BC9666B0
+CT=D154DCAFAD8B207FA5CBC95E9996B559
+
+I=11
+KEY=2C2D2E2F31323334363738393B3C3D3E4041424345464748
+PT=606834C8CE063F3234CF1145325DBD71
+CT=4934D541E8B46FA339C805A7AEB9E5DA
+
+I=12
+KEY=4A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+PT=FEC1C04F529BBD17D8CECFCC4718B17F
+CT=62564C738F3EFE186E1A127A0C4D3C61
+
+I=13
+KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384
+PT=32DF99B431ED5DC5ACF8CAF6DC6CE475
+CT=07805AA043986EB23693E23BEF8F3438
+
+I=14
+KEY=868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2
+PT=7FDC2B746F3F665296943B83710D1F82
+CT=DF0B4931038BADE848DEE3B4B85AA44B
+
+I=15
+KEY=A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0
+PT=8FBA1510A3C5B87E2EAA3F7A91455CA2
+CT=592D5FDED76582E4143C65099309477C
+
+I=16
+KEY=C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+PT=2C9B468B1C2EED92578D41B0716B223B
+CT=C9B8D6545580D3DFBCDD09B954ED4E92
+
+I=17
+KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFC
+PT=0A2BBF0EFC6BC0034F8A03433FCA1B1A
+CT=5DCCD5D6EB7C1B42ACB008201DF707A0
+
+I=18
+KEY=FEFE01010304050608090A0B0D0E0F10121314151718191A
+PT=25260E1F31F4104D387222E70632504B
+CT=A2A91682FFEB6ED1D34340946829E6F9
+
+I=19
+KEY=1C1D1E1F21222324262728292B2C2D2E3031323335363738
+PT=C527D25A49F08A5228D338642AE65137
+CT=E45D185B797000348D9267960A68435D
+
+I=20
+KEY=3A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+PT=3B49FC081432F5890D0E3D87E884A69E
+CT=45E060DAE5901CDA8089E10D4F4C246B
+
+I=21
+KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374
+PT=D173F9ED1E57597E166931DF2754A083
+CT=F6951AFACC0079A369C71FDCFF45DF50
+
+I=22
+KEY=767778797B7C7D7E80818283858687888A8B8C8D8F909192
+PT=8C2B7CAFA5AFE7F13562DAEAE1ADEDE0
+CT=9E95E00F351D5B3AC3D0E22E626DDAD6
+
+I=23
+KEY=94959697999A9B9C9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0
+PT=AAF4EC8C1A815AEB826CAB741339532C
+CT=9CB566FF26D92DAD083B51FDC18C173C
+
+I=24
+KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBEC
+PT=40BE8C5D9108E663F38F1A2395279ECF
+CT=C9C82766176A9B228EB9A974A010B4FB
+
+I=25
+KEY=2A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+PT=0C8AD9BC32D43E04716753AA4CFBE351
+CT=D8E26AA02945881D5137F1C1E1386E88
+
+I=26
+KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364
+PT=1407B1D5F87D63357C8DC7EBBAEBBFEE
+CT=C0E024CCD68FF5FFA4D139C355A77C55
+
+I=27
+KEY=84858687898A8B8C8E8F90919394959698999A9B9D9E9FA0
+PT=E62734D1AE3378C4549E939E6F123416
+CT=0B18B3D16F491619DA338640DF391D43
+
+I=28
+KEY=A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+PT=5A752CFF2A176DB1A1DE77F2D2CDEE41
+CT=DBE09AC8F66027BF20CB6E434F252EFC
+
+I=29
+KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDC
+PT=A9C8C3A4EABEDC80C64730DDD018CD88
+CT=6D04E5E43C5B9CBE05FEB9606B6480FE
+
+I=30
+KEY=1A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+PT=EE9B3DBBDB86180072130834D305999A
+CT=DD1D6553B96BE526D9FEE0FBD7176866
+
+I=31
+KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354
+PT=A7FA8C3586B8EBDE7568EAD6F634A879
+CT=0260CA7E3F979FD015B0DD4690E16D2A
+
+I=32
+KEY=929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+PT=37E0F4A87F127D45AC936FE7AD88C10A
+CT=9893734DE10EDCC8A67C3B110B8B8CC6
+
+I=33
+KEY=464748494B4C4D4E50515253555657585A5B5C5D5F606162
+PT=3F77D8B5D92BAC148E4E46F697A535C5
+CT=93B30B750516B2D18808D710C2EE84EF
+
+I=34
+KEY=828384858788898A8C8D8E8F91929394969798999B9C9D9E
+PT=D25EBB686C40F7E2C4DA1014936571CA
+CT=16F65FA47BE3CB5E6DFE7C6C37016C0E
+
+I=35
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBC
+PT=4F1C769D1E5B0552C7ECA84DEA26A549
+CT=F3847210D5391E2360608E5ACB560581
+
+I=36
+KEY=BEBFC0C1C3C4C5C6C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA
+PT=8548E2F882D7584D0FAFC54372B6633A
+CT=8754462CD223366D0753913E6AF2643D
+
+I=37
+KEY=DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8
+PT=87D7A336CB476F177CD2A51AF2A62CDF
+CT=1EA20617468D1B806A1FD58145462017
+
+I=38
+KEY=FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+PT=03B1FEAC668C4E485C1065DFC22B44EE
+CT=3B155D927355D737C6BE9DDA60136E2E
+
+I=39
+KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334
+PT=BDA15E66819FA72D653A6866AA287962
+CT=26144F7B66DAA91B6333DBD3850502B3
+
+I=40
+KEY=363738393B3C3D3E40414243454647484A4B4C4D4F505152
+PT=4D0C7A0D2505B80BF8B62CEB12467F0A
+CT=E4F9A4AB52CED8134C649BF319EBCC90
+
+I=41
+KEY=54555657595A5B5C5E5F60616364656668696A6B6D6E6F70
+PT=626D34C9429B37211330986466B94E5F
+CT=B9DDD29AC6128A6CAB121E34A4C62B36
+
+I=42
+KEY=727374757778797A7C7D7E7F81828384868788898B8C8D8E
+PT=333C3E6BF00656B088A17E5FF0E7F60A
+CT=6FCDDAD898F2CE4EFF51294F5EAAF5C9
+
+I=43
+KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABAC
+PT=687ED0CDC0D2A2BC8C466D05EF9D2891
+CT=C9A6FE2BF4028080BEA6F7FC417BD7E3
+
+I=44
+KEY=AEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CA
+PT=487830E78CC56C1693E64B2A6660C7B6
+CT=6A2026846D8609D60F298A9C0673127F
+
+I=45
+KEY=CCCDCECFD1D2D3D4D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8
+PT=7A48D6B7B52B29392AA2072A32B66160
+CT=2CB25C005E26EFEA44336C4C97A4240B
+
+I=46
+KEY=EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+PT=907320E64C8C5314D10F8D7A11C8618D
+CT=496967AB8680DDD73D09A0E4C7DCC8AA
+
+I=47
+KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324
+PT=B561F2CA2D6E65A4A98341F3ED9FF533
+CT=D5AF94DE93487D1F3A8C577CB84A66A4
+
+I=48
+KEY=262728292B2C2D2E30313233353637383A3B3C3D3F404142
+PT=DF769380D212792D026F049E2E3E48EF
+CT=84BDAC569CAE2828705F267CC8376E90
+
+I=49
+KEY=44454647494A4B4C4E4F50515354555658595A5B5D5E5F60
+PT=79F374BC445BDABF8FCCB8843D6054C6
+CT=F7401DDA5AD5AB712B7EB5D10C6F99B6
+
+I=50
+KEY=626364656768696A6C6D6E6F71727374767778797B7C7D7E
+PT=4E02F1242FA56B05C68DBAE8FE44C9D6
+CT=1C9D54318539EBD4C3B5B7E37BF119F0
+
+I=51
+KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C
+PT=CF73C93CBFF57AC635A6F4AD2A4A1545
+CT=ACA572D65FB2764CFFD4A6ECA090EA0D
+
+I=52
+KEY=9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA
+PT=9923548E2875750725B886566784C625
+CT=36D9C627B8C2A886A10CCB36EAE3DFBB
+
+I=53
+KEY=BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8
+PT=4888336B723A022C9545320F836A4207
+CT=010EDBF5981E143A81D646E597A4A568
+
+I=54
+KEY=DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+PT=F84D9A5561B0608B1160DEE000C41BA8
+CT=8DB44D538DC20CC2F40F3067FD298E60
+
+I=55
+KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314
+PT=C23192A0418E30A19B45AE3E3625BF22
+CT=930EB53BC71E6AC4B82972BDCD5AAFB3
+
+I=56
+KEY=161718191B1C1D1E20212223252627282A2B2C2D2F303132
+PT=B84E0690B28B0025381AD82A15E501A7
+CT=6C42A81EDCBC9517CCD89C30C95597B4
+
+I=57
+KEY=34353637393A3B3C3E3F40414344454648494A4B4D4E4F50
+PT=ACEF5E5C108876C4F06269F865B8F0B0
+CT=DA389847AD06DF19D76EE119C71E1DD3
+
+I=58
+KEY=525354555758595A5C5D5E5F61626364666768696B6C6D6E
+PT=0F1B3603E0F5DDEA4548246153A5E064
+CT=E018FDAE13D3118F9A5D1A647A3F0462
+
+I=59
+KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C
+PT=FBB63893450D42B58C6D88CD3C1809E3
+CT=2AA65DB36264239D3846180FABDFAD20
+
+I=60
+KEY=8E8F90919394959698999A9B9D9E9FA0A2A3A4A5A7A8A9AA
+PT=4BEF736DF150259DAE0C91354E8A5F92
+CT=1472163E9A4F780F1CEB44B07ECF4FDB
+
+I=61
+KEY=ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8
+PT=7D2D46242056EF13D3C3FC93C128F4C7
+CT=C8273FDC8F3A9F72E91097614B62397C
+
+I=62
+KEY=CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+PT=E9C1BA2DF415657A256EDB33934680FD
+CT=66C8427DCD733AAF7B3470CB7D976E3F
+
+I=63
+KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304
+PT=E23EE277B0AA0A1DFB81F7527C3514F1
+CT=146131CB17F1424D4F8DA91E6F80C1D0
+
+I=64
+KEY=060708090B0C0D0E10111213151617181A1B1C1D1F202122
+PT=3E7445B0B63CAAF75E4A911E12106B4C
+CT=2610D0AD83659081AE085266A88770DC
+
+I=65
+KEY=24252627292A2B2C2E2F30313334353638393A3B3D3E3F40
+PT=767774752023222544455A5BE6E1E0E3
+CT=38A2B5A974B0575C5D733917FB0D4570
+
+I=66
+KEY=424344454748494A4C4D4E4F51525354565758595B5C5D5E
+PT=72737475717E7F7CE9E8EBEA696A6B6C
+CT=E21D401EBC60DE20D6C486E4F39A588B
+
+I=67
+KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C
+PT=DFDEDDDC25262728C9C8CFCEF1EEEFEC
+CT=E51D5F88C670B079C0CA1F0C2C4405A2
+
+I=68
+KEY=7E7F80818384858688898A8B8D8E8F90929394959798999A
+PT=FFFE0100707776755F5E5D5C7675746B
+CT=246A94788A642FB3D1B823C8762380C8
+
+I=69
+KEY=9C9D9E9FA1A2A3A4A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8
+PT=E0E1E2E3424140479F9E9190292E2F2C
+CT=B80C391C5C41A4C3B30C68E0E3D7550F
+
+I=70
+KEY=BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+PT=2120272690EFEEED3B3A39384E4D4C4B
+CT=B77C4754FC64EB9A1154A9AF0BB1F21C
+
+I=71
+KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4
+PT=ECEDEEEF5350516EA1A0A7A6A3ACADAE
+CT=FB554DE520D159A06BF219FC7F34A02F
+
+I=72
+KEY=F6F7F8F9FBFCFDFE00010203050607080A0B0C0D0F101112
+PT=32333C3D25222320E9E8EBEACECDCCC3
+CT=A89FBA152D76B4927BEED160DDB76C57
+
+I=73
+KEY=14151617191A1B1C1E1F20212324252628292A2B2D2E2F30
+PT=40414243626160678A8BB4B511161714
+CT=5676EAB4A98D2E8473B3F3D46424247C
+
+I=74
+KEY=323334353738393A3C3D3E3F41424344464748494B4C4D4E
+PT=94959293F5FAFBF81F1E1D1C7C7F7E79
+CT=4E8F068BD7EDE52A639036EC86C33568
+
+I=75
+KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C
+PT=BEBFBCBD191A1B14CFCEC9C8546B6A69
+CT=F0193C4D7AFF1791EE4C07EB4A1824FC
+
+I=76
+KEY=6E6F70717374757678797A7B7D7E7F80828384858788898A
+PT=2C2D3233898E8F8CBBBAB9B8333031CE
+CT=AC8686EECA9BA761AFE82D67B928C33F
+
+I=77
+KEY=8C8D8E8F91929394969798999B9C9D9EA0A1A2A3A5A6A7A8
+PT=84858687BFBCBDBA37363938FDFAFBF8
+CT=5FAF8573E33B145B6A369CD3606AB2C9
+
+I=78
+KEY=AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+PT=828384857669686B909192930B08090E
+CT=31587E9944AB1C16B844ECAD0DF2E7DA
+
+I=79
+KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4
+PT=BEBFBCBD9695948B707176779E919093
+CT=D017FECD91148ABA37F6F3068AA67D8A
+
+I=80
+KEY=E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8FAFBFCFDFE010002
+PT=8B8A85846067666521202322D0D3D2DD
+CT=788EF2F021A73CBA2794B616078A8500
+
+I=81
+KEY=04050607090A0B0C0E0F10111314151618191A1B1D1E1F20
+PT=76777475F1F2F3F4F8F9E6E777707172
+CT=5D1EF20DCED6BCBC12131AC7C54788AA
+
+I=82
+KEY=222324252728292A2C2D2E2F31323334363738393B3C3D3E
+PT=A4A5A2A34F404142B4B5B6B727242522
+CT=B3C8CF961FAF9EA05FDDE6D1E4D8F663
+
+I=83
+KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C
+PT=94959697E1E2E3EC16171011839C9D9E
+CT=143075C70605861C7FAC6526199E459F
+
+I=84
+KEY=5E5F60616364656668696A6B6D6E6F70727374757778797A
+PT=03023D3C06010003DEDFDCDDFFFCFDE2
+CT=A5AE12EADE9A87268D898BFC8FC0252A
+
+I=85
+KEY=7C7D7E7F81828384868788898B8C8D8E9091929395969798
+PT=10111213F1F2F3F4CECFC0C1DBDCDDDE
+CT=0924F7CF2E877A4819F5244A360DCEA9
+
+I=86
+KEY=9A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+PT=67666160724D4C4F1D1C1F1E73707176
+CT=3D9E9635AFCC3E291CC7AB3F27D1C99A
+
+I=87
+KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4
+PT=E6E7E4E5A8ABAAD584858283909F9E9D
+CT=9D80FEEBF87510E2B8FB98BB54FD788C
+
+I=88
+KEY=D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2
+PT=71707F7E565150537D7C7F7E6162636C
+CT=5F9D1A082A1A37985F174002ECA01309
+
+I=89
+KEY=F4F5F6F7F9FAFBFCFEFE01010304050608090A0B0D0E0F10
+PT=64656667212223245555AAAA03040506
+CT=A390EBB1D1403930184A44B4876646E4
+
+I=90
+KEY=121314151718191A1C1D1E1F21222324262728292B2C2D2E
+PT=9E9F9899ABA4A5A6CFCECDCC2B28292E
+CT=700FE918981C3195BB6C4BCB46B74E29
+
+I=91
+KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C
+PT=C7C6C5C4D1D2D3DC626364653A454447
+CT=907984406F7BF2D17FB1EB15B673D747
+
+I=92
+KEY=4E4F50515354555658595A5B5D5E5F60626364656768696A
+PT=F6F7E8E9E0E7E6E51D1C1F1E5B585966
+CT=C32A956DCFC875C2AC7C7CC8B8CC26E1
+
+I=93
+KEY=6C6D6E6F71727374767778797B7C7D7E8081828385868788
+PT=BCBDBEBF5D5E5F5868696667F4F3F2F1
+CT=02646E2EBFA9B820CF8424E9B9B6EB51
+
+I=94
+KEY=8A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+PT=40414647B0AFAEAD9B9A99989B98999E
+CT=621FDA3A5BBD54C6D3C685816BD4EAD8
+
+I=95
+KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4
+PT=69686B6A0201001F0F0E0908B4BBBAB9
+CT=D4E216040426DFAF18B152469BC5AC2F
+
+I=96
+KEY=C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2
+PT=C7C6C9C8D8DFDEDD5A5B5859BEBDBCB3
+CT=9D0635B9D33B6CDBD71F5D246EA17CC8
+
+I=97
+KEY=E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6F8F9FAFBFDFEFE00
+PT=DEDFDCDD787B7A7DFFFEE1E0B2B5B4B7
+CT=10ABAD1BD9BAE5448808765583A2CC1A
+
+I=98
+KEY=020304050708090A0C0D0E0F11121314161718191B1C1D1E
+PT=4D4C4B4A606F6E6DD0D1D2D3FBF8F9FE
+CT=6891889E16544E355FF65A793C39C9A8
+
+I=99
+KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C
+PT=B7B6B5B4D7D4D5DAE5E4E3E2E1FEFFFC
+CT=CC735582E68072C163CD9DDF46B91279
+
+I=100
+KEY=3E3F40414344454648494A4B4D4E4F50525354555758595A
+PT=CECFB0B1F7F0F1F2AEAFACAD3E3D3C23
+CT=C5C68B9AEEB7F878DF578EFA562F9574
+
+I=101
+KEY=5C5D5E5F61626364666768696B6C6D6E7071727375767778
+PT=CACBC8C9CDCECFC812131C1D494E4F4C
+CT=5F4764395A667A47D73452955D0D2CE8
+
+I=102
+KEY=7A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+PT=9D9C9B9AD22D2C2FB1B0B3B20C0F0E09
+CT=701448331F66106CEFDDF1EB8267C357
+
+I=103
+KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4
+PT=7A7B787964676659959493924F404142
+CT=CB3EE56D2E14B4E1941666F13379D657
+
+I=104
+KEY=B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2
+PT=AAABA4A5CEC9C8CB1F1E1D1CABA8A9A6
+CT=9FE16EFD18AB6E1981191851FEDB0764
+
+I=105
+KEY=D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6E8E9EAEBEDEEEFF0
+PT=93929190282B2A2DC4C5FAFB92959497
+CT=3DC9BA24E1B223589B147ADCEB4C8E48
+
+I=106
+KEY=F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+PT=EFEEE9E8DED1D0D339383B3A888B8A8D
+CT=1C333032682E7D4DE5E5AFC05C3E483C
+
+I=107
+KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C
+PT=7F7E7D7CA2A1A0AF78797E7F112E2F2C
+CT=D593CC99A95AFEF7E92038E05A59D00A
+
+I=108
+KEY=2E2F30313334353638393A3B3D3E3F40424344454748494A
+PT=84859A9B2B2C2D2E868784852625245B
+CT=51E7F96F53B4353923452C222134E1EC
+
+I=109
+KEY=4C4D4E4F51525354565758595B5C5D5E6061626365666768
+PT=B0B1B2B3070405026869666710171615
+CT=4075B357A1A2B473400C3B25F32F81A4
+
+I=110
+KEY=6A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+PT=ACADAAABBDA2A3A00D0C0F0E595A5B5C
+CT=302E341A3EBCD74F0D55F61714570284
+
+I=111
+KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4
+PT=121310115655544B5253545569666764
+CT=57ABDD8231280DA01C5042B78CF76522
+
+I=112
+KEY=A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2
+PT=DEDFD0D166616063EAEBE8E94142434C
+CT=17F9EA7EEA17AC1ADF0E190FEF799E92
+
+I=113
+KEY=C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6D8D9DADBDDDEDFE0
+PT=DBDAD9D81417161166677879E0E7E6E5
+CT=2E1BDD563DD87EE5C338DD6D098D0A7A
+
+I=114
+KEY=E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+PT=6A6B6C6DE0EFEEED2B2A2928C0C3C2C5
+CT=EB869996E6F8BFB2BFDD9E0C4504DBB2
+
+I=115
+KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C
+PT=B1B0B3B21714151A1A1B1C1D5649484B
+CT=C2E01549E9DECF317468B3E018C61BA8
+
+I=116
+KEY=1E1F20212324252628292A2B2D2E2F30323334353738393A
+PT=39380706A3A4A5A6C4C5C6C77271706F
+CT=8DA875D033C01DD463B244A1770F4A22
+
+I=117
+KEY=3C3D3E3F41424344464748494B4C4D4E5051525355565758
+PT=5C5D5E5F1013121539383736E2E5E4E7
+CT=8BA0DCF3A186844F026D022F8839D696
+
+I=118
+KEY=5A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+PT=43424544EAD5D4D72E2F2C2D64676661
+CT=E9691FF9A6CC6970E51670A0FD5B88C1
+
+I=119
+KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394
+PT=55545756989B9A65F8F9FEFF18171615
+CT=F2BAEC06FAEED30F88EE63BA081A6E5B
+
+I=120
+KEY=969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+PT=05040B0A525554573C3D3E3F4A494847
+CT=9C39D4C459AE5753394D6094ADC21E78
+
+I=121
+KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0
+PT=14151617595A5B5C8584FBFA8E89888B
+CT=6345B532A11904502EA43BA99C6BD2B2
+
+I=122
+KEY=D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=7C7D7A7BFDF2F3F029282B2A51525354
+CT=5FFAE3061A95172E4070CEDCE1E428C8
+
+I=123
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C
+PT=38393A3B1E1D1C1341404746C23D3C3E
+CT=0A4566BE4CDF9ADCE5DEC865B5AB34CD
+
+I=124
+KEY=0E0F10111314151618191A1B1D1E1F20222324252728292A
+PT=8D8C939240474645818083827C7F7E41
+CT=CA17FCCE79B7404F2559B22928F126FB
+
+I=125
+KEY=2C2D2E2F31323334363738393B3C3D3E4041424345464748
+PT=3B3A39381A19181F32333C3D45424340
+CT=97CA39B849ED73A6470A97C821D82F58
+
+I=126
+KEY=4A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+PT=F0F1F6F738272625828380817F7C7D7A
+CT=8198CB06BC684C6D3E9B7989428DCF7A
+
+I=127
+KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384
+PT=89888B8A0407061966676061141B1A19
+CT=F53C464C705EE0F28D9A4C59374928BD
+
+I=128
+KEY=868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2
+PT=D3D2DDDCAAADACAF9C9D9E9FE8EBEAE5
+CT=9ADB3D4CCA559BB98C3E2ED73DBF1154
+
+==========
+
+KEYSIZE=256
+
+
+I=1
+KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+PT=834EADFCCAC7E1B30664B1ABA44815AB
+CT=1946DABF6A03A2A2C3D0B05080AED6FC
+
+I=2
+KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+PT=D9DC4DBA3021B05D67C0518F72B62BF1
+CT=5ED301D747D3CC715445EBDEC62F2FB4
+
+I=3
+KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+PT=A291D86301A4A739F7392173AA3C604C
+CT=6585C8F43D13A6BEAB6419FC5935B9D0
+
+I=4
+KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+PT=4264B2696498DE4DF79788A9F83E9390
+CT=2A5B56A596680FCC0E05F5E0F151ECAE
+
+I=5
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+PT=EE9932B3721804D5A83EF5949245B6F6
+CT=F5D6FF414FD2C6181494D20C37F2B8C4
+
+I=6
+KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=E6248F55C5FDCBCA9CBBB01C88A2EA77
+CT=85399C01F59FFFB5204F19F8482F00B8
+
+I=7
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+PT=B8358E41B9DFF65FD461D55A99266247
+CT=92097B4C88A041DDF98144BC8D22E8E7
+
+I=8
+KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+PT=F0E2D72260AF58E21E015AB3A4C0D906
+CT=89BD5B73B356AB412AEF9F76CEA2D65C
+
+I=9
+KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+PT=475B8B823CE8893DB3C44A9F2A379FF7
+CT=2536969093C55FF9454692F2FAC2F530
+
+I=10
+KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+PT=688F5281945812862F5F3076CF80412F
+CT=07FC76A872843F3F6E0081EE9396D637
+
+I=11
+KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+PT=08D1D2BC750AF553365D35E75AFACEAA
+CT=E38BA8EC2AA741358DCC93E8F141C491
+
+I=12
+KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+PT=8707121F47CC3EFCECA5F9A8474950A1
+CT=D028EE23E4A89075D0B03E868D7D3A42
+
+I=13
+KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+PT=E51AA0B135DBA566939C3B6359A980C5
+CT=8CD9423DFC459E547155C5D1D522E540
+
+I=14
+KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+PT=069A007FC76A459F98BAF917FEDF9521
+CT=080E9517EB1677719ACF728086040AE3
+
+I=15
+KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+PT=726165C1723FBCF6C026D7D00B091027
+CT=7C1700211A3991FC0ECDED0AB3E576B0
+
+I=16
+KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+PT=D7C544DE91D55CFCDE1F84CA382200CE
+CT=DABCBCC855839251DB51E224FBE87435
+
+I=17
+KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+PT=FED3C9A161B9B5B2BD611B41DC9DA357
+CT=68D56FAD0406947A4DD27A7448C10F1D
+
+I=18
+KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+PT=4F634CDC6551043409F30B635832CF82
+CT=DA9A11479844D1FFEE24BBF3719A9925
+
+I=19
+KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+PT=109CE98DB0DFB36734D9F3394711B4E6
+CT=5E4BA572F8D23E738DA9B05BA24B8D81
+
+I=20
+KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+PT=4EA6DFABA2D8A02FFDFFA89835987242
+CT=A115A2065D667E3F0B883837A6E903F8
+
+I=21
+KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+PT=5AE094F54AF58E6E3CDBF976DAC6D9EF
+CT=3E9E90DC33EAC2437D86AD30B137E66E
+
+I=22
+KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+PT=764D8E8E0F29926DBE5122E66354FDBE
+CT=01CE82D8FBCDAE824CB3C48E495C3692
+
+I=23
+KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+PT=3F0418F888CDF29A982BF6B75410D6A9
+CT=0C9CFF163CE936FAAF083CFD3DEA3117
+
+I=24
+KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+PT=E4A3E7CB12CDD56AA4A75197A9530220
+CT=5131BA9BD48F2BBA85560680DF504B52
+
+I=25
+KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+PT=211677684AAC1EC1A160F44C4EBF3F26
+CT=9DC503BBF09823AEC8A977A5AD26CCB2
+
+I=26
+KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+PT=D21E439FF749AC8F18D6D4B105E03895
+CT=9A6DB0C0862E506A9E397225884041D7
+
+I=27
+KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+PT=D9F6FF44646C4725BD4C0103FF5552A7
+CT=430BF9570804185E1AB6365FC6A6860C
+
+I=28
+KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+PT=0B1256C2A00B976250CFC5B0C37ED382
+CT=3525EBC02F4886E6A5A3762813E8CE8A
+
+I=29
+KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+PT=B056447FFC6DC4523A36CC2E972A3A79
+CT=07FA265C763779CCE224C7BAD671027B
+
+I=30
+KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+PT=5E25CA78F0DE55802524D38DA3FE4456
+CT=E8B72B4E8BE243438C9FFF1F0E205872
+
+I=31
+KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+PT=A5BCF4728FA5EAAD8567C0DC24675F83
+CT=109D4F999A0E11ACE1F05E6B22CBCB50
+
+I=32
+KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+PT=814E59F97ED84646B78B2CA022E9CA43
+CT=45A5E8D4C3ED58403FF08D68A0CC4029
+
+I=33
+KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+PT=15478BEEC58F4775C7A7F5D4395514D7
+CT=196865964DB3D417B6BD4D586BCB7634
+
+I=34
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+PT=253548FFCA461C67C8CBC78CD59F4756
+CT=60436AD45AC7D30D99195F815D98D2AE
+
+I=35
+KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=FD7AD8D73B9B0F8CC41600640F503D65
+CT=BB07A23F0B61014B197620C185E2CD75
+
+I=36
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+PT=06199DE52C6CBF8AF954CD65830BCD56
+CT=5BC0B2850129C854423AFF0751FE343B
+
+I=37
+KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+PT=F17C4FFE48E44C61BD891E257E725794
+CT=7541A78F96738E6417D2A24BD2BECA40
+
+I=38
+KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+PT=9A5B4A402A3E8A59BE6BF5CD8154F029
+CT=B0A303054412882E464591F1546C5B9E
+
+I=39
+KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+PT=79BD40B91A7E07DC939D441782AE6B17
+CT=778C06D8A355EEEE214FCEA14B4E0EEF
+
+I=40
+KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+PT=D8CEAAF8976E5FBE1012D8C84F323799
+CT=09614206D15CBACE63227D06DB6BEEBB
+
+I=41
+KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+PT=3316E2751E2E388B083DA23DD6AC3FBE
+CT=41B97FB20E427A9FDBBB358D9262255D
+
+I=42
+KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+PT=8B7CFBE37DE7DCA793521819242C5816
+CT=C1940F703D845F957652C2D64ABD7ADF
+
+I=43
+KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+PT=F23F033C0EEBF8EC55752662FD58CE68
+CT=D2D44FCDAE5332343366DB297EFCF21B
+
+I=44
+KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+PT=59EB34F6C8BDBACC5FC6AD73A59A1301
+CT=EA8196B79DBE167B6AA9896E287EED2B
+
+I=45
+KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+PT=DCDE8B6BD5CF7CC22D9505E3CE81261A
+CT=D6B0B0C4BA6C7DBE5ED467A1E3F06C2D
+
+I=46
+KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+PT=E33CF7E524FED781E7042FF9F4B35DC7
+CT=EC51EB295250C22C2FB01816FB72BCAE
+
+I=47
+KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+PT=27963C8FACDF73062867D164DF6D064C
+CT=ADED6630A07CE9C7408A155D3BD0D36F
+
+I=48
+KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+PT=77B1CE386B551B995F2F2A1DA994EEF8
+CT=697C9245B9937F32F5D1C82319F0363A
+
+I=49
+KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E
+PT=F083388B013679EFCF0BB9B15D52AE5C
+CT=AAD5AD50C6262AAEC30541A1B7B5B19C
+
+I=50
+KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+PT=C5009E0DAB55DB0ABDB636F2600290C8
+CT=7D34B893855341EC625BD6875AC18C0D
+
+I=51
+KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E
+PT=7804881E26CD532D8514D3683F00F1B9
+CT=7EF05105440F83862F5D780E88F02B41
+
+I=52
+KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+PT=46CDDCD73D1EB53E675CA012870A92A3
+CT=C377C06403382061AF2C9C93A8E70DF6
+
+I=53
+KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+PT=A9FB44062BB07FE130A8E8299EACB1AB
+CT=1DBDB3FFDC052DACC83318853ABC6DE5
+
+I=54
+KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+PT=2B6FF8D7A5CC3A28A22D5A6F221AF26B
+CT=69A6EAB00432517D0BF483C91C0963C7
+
+I=55
+KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+PT=1A9527C29B8ADD4B0E3E656DBB2AF8B4
+CT=0797F41DC217C80446E1D514BD6AB197
+
+I=56
+KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+PT=7F99CF2C75244DF015EB4B0C1050AEAE
+CT=9DFD76575902A637C01343C58E011A03
+
+I=57
+KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+PT=E84FF85B0D9454071909C1381646C4ED
+CT=ACF4328AE78F34B9FA9B459747CC2658
+
+I=58
+KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+PT=89AFD40F99521280D5399B12404F6DB4
+CT=B0479AEA12BAC4FE2384CF98995150C6
+
+I=59
+KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+PT=A09EF32DBC5119A35AB7FA38656F0329
+CT=9DD52789EFE3FFB99F33B3DA5030109A
+
+I=60
+KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+PT=61773457F068C376C7829B93E696E716
+CT=ABBB755E4621EF8F1214C19F649FB9FD
+
+I=61
+KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+PT=A34F0CAE726CCE41DD498747D891B967
+CT=DA27FB8174357BCE2BED0E7354F380F9
+
+I=62
+KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+PT=856F59496C7388EE2D2B1A27B7697847
+CT=C59A0663F0993838F6E5856593BDC5EF
+
+I=63
+KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+PT=CB090C593EF7720BD95908FB93B49DF4
+CT=ED60B264B5213E831607A99C0CE5E57E
+
+I=64
+KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+PT=A0AC75CD2F1923D460FC4D457AD95BAF
+CT=E50548746846F3EB77B8C520640884ED
+
+I=65
+KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+PT=2A2B282974777689E8E9EEEF525D5C5F
+CT=28282CC7D21D6A2923641E52D188EF0C
+
+I=66
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+PT=909192939390919E0F0E09089788898A
+CT=0DFA5B02ABB18E5A815305216D6D4F8E
+
+I=67
+KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=777675748D8E8F907170777649464744
+CT=7359635C0EECEFE31D673395FB46FB99
+
+I=68
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+PT=717073720605040B2D2C2B2A05FAFBF9
+CT=73C679F7D5AEF2745C9737BB4C47FB36
+
+I=69
+KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+PT=64656667FEFDFCC31B1A1D1CA5AAABA8
+CT=B192BD472A4D2EAFB786E97458967626
+
+I=70
+KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+PT=DBDAD9D86A696867B5B4B3B2C8D7D6D5
+CT=0EC327F6C8A2B147598CA3FDE61DC6A4
+
+I=71
+KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+PT=5C5D5E5FE3E0E1FE31303736333C3D3E
+CT=FC418EB3C41B859B38D4B6F646629729
+
+I=72
+KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+PT=545556574B48494673727574546B6A69
+CT=30249E5AC282B1C981EA64B609F3A154
+
+I=73
+KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+PT=ECEDEEEFC6C5C4BB56575051F5FAFBF8
+CT=5E6E08646D12150776BB43C2D78A9703
+
+I=74
+KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+PT=464744452724252AC9C8CFCED2CDCCCF
+CT=FAEB3D5DE652CD3447DCEB343F30394A
+
+I=75
+KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+PT=E6E7E4E54142435C878681801C131211
+CT=A8E88706823F6993EF80D05C1C7B2CF0
+
+I=76
+KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+PT=72737071CFCCCDC2F9F8FFFE710E0F0C
+CT=8CED86677E6E00A1A1B15968F2D3CCE6
+
+I=77
+KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+PT=505152537370714EC3C2C5C4010E0F0C
+CT=9FC7C23858BE03BDEBB84E90DB6786A9
+
+I=78
+KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+PT=A8A9AAAB5C5F5E51AEAFA8A93D222320
+CT=B4FBD65B33F70D8CF7F1111AC4649C36
+
+I=79
+KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+PT=DEDFDCDDF6F5F4EB10111617FEF1F0F3
+CT=C5C32D5ED03C4B53CC8C1BD0EF0DBBF6
+
+I=80
+KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+PT=BDBCBFBE5E5D5C530B0A0D0CFAC5C4C7
+CT=D1A7F03B773E5C212464B63709C6A891
+
+I=81
+KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E
+PT=8A8B8889050606F8F4F5F2F3636C6D6E
+CT=6B7161D8745947AC6950438EA138D028
+
+I=82
+KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+PT=A6A7A4A54D4E4F40B2B3B4B539262724
+CT=FD47A9F7E366EE7A09BC508B00460661
+
+I=83
+KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E
+PT=9C9D9E9FE9EAEBF40E0F08099B949596
+CT=00D40B003DC3A0D9310B659B98C7E416
+
+I=84
+KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+PT=2D2C2F2E1013121DCCCDCACBED121310
+CT=EEA4C79DCC8E2BDA691F20AC48BE0717
+
+I=85
+KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+PT=F4F5F6F7EDEEEFD0EAEBECEDF7F8F9FA
+CT=E78F43B11C204403E5751F89D05A2509
+
+I=86
+KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+PT=3D3C3F3E282B2A2573727574150A0B08
+CT=D0F0E3D1F1244BB979931E38DD1786EF
+
+I=87
+KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+PT=B6B7B4B5F8FBFAE5B4B5B2B3A0AFAEAD
+CT=042E639DC4E1E4DDE7B75B749EA6F765
+
+I=88
+KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+PT=B7B6B5B4989B9A95878681809BA4A5A6
+CT=BC032FDD0EFE29503A980A7D07AB46A8
+
+I=89
+KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+PT=A8A9AAABE5E6E798E9E8EFEE4748494A
+CT=0C93AC949C0DA6446EFFB86183B6C910
+
+I=90
+KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+PT=ECEDEEEFD9DADBD4B9B8BFBE657A7B78
+CT=E0D343E14DA75C917B4A5CEC4810D7C2
+
+I=91
+KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+PT=7F7E7D7C696A6B74CACBCCCD929D9C9F
+CT=0EAFB821748408279B937B626792E619
+
+I=92
+KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+PT=08090A0B0605040BFFFEF9F8B9C6C7C4
+CT=FA1AC6E02D23B106A1FEF18B274A553F
+
+I=93
+KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+PT=08090A0BF1F2F3CCFCFDFAFB68676665
+CT=0DADFE019CD12368075507DF33C1A1E9
+
+I=94
+KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+PT=CACBC8C93A393837050403020D121310
+CT=3A0879B414465D9FFBAF86B33A63A1B9
+
+I=95
+KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+PT=E9E8EBEA8281809F8F8E8988343B3A39
+CT=62199FADC76D0BE1805D3BA0B7D914BF
+
+I=96
+KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+PT=515053524645444BD0D1D6D7340B0A09
+CT=1B06D6C5D333E742730130CF78E719B4
+
+I=97
+KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+PT=42434041ECEFEE1193929594C6C9C8CB
+CT=F1F848824C32E9DCDCBF21580F069329
+
+I=98
+KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+PT=EFEEEDECC2C1C0CF76777071455A5B58
+CT=1A09050CBD684F784D8E965E0782F28A
+
+I=99
+KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+PT=5F5E5D5C3F3C3D221D1C1B1A19161714
+CT=79C2969E7DED2BA7D088F3F320692360
+
+I=100
+KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+PT=000102034142434C1C1D1A1B8D727371
+CT=091A658A2F7444C16ACCB669450C7B63
+
+I=101
+KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+PT=8E8F8C8DB1B2B38C56575051050A0B08
+CT=97C1E3A72CCA65FA977D5ED0E8A7BBFC
+
+I=102
+KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+PT=A7A6A5A4E8EBEAE57F7E7978CAD5D4D7
+CT=70C430C6DB9A17828937305A2DF91A2A
+
+I=103
+KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+PT=8A8B888994979689454443429F909192
+CT=629553457FBE2479098571C7C903FDE8
+
+I=104
+KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+PT=8C8D8E8FE0E3E2ED45444342F1CECFCC
+CT=A25B25A61F612669E7D91265C7D476BA
+
+I=105
+KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+PT=FFFEFDFC4C4F4E31D8D9DEDFB6B9B8BB
+CT=EB7E4E49B8AE0F024570DDA293254FED
+
+I=106
+KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+PT=FDFCFFFECCCFCEC12F2E29286679787B
+CT=38FE15D61CCA84516E924ADCE5014F67
+
+I=107
+KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+PT=67666564BAB9B8A77071767719161714
+CT=3AD208492249108C9F3EBEB167AD0583
+
+I=108
+KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+PT=9A9B98992D2E2F2084858283245B5A59
+CT=299BA9F9BF5AB05C3580FC26EDD1ED12
+
+I=109
+KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+PT=A4A5A6A70B0809365C5D5A5B2C232221
+CT=19DC705B857A60FB07717B2EA5717781
+
+I=110
+KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+PT=464744455754555AF3F2F5F4AFB0B1B2
+CT=FFC8AEB885B5EFCAD06B6DBEBF92E76B
+
+I=111
+KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+PT=323330317675746B7273747549464744
+CT=F58900C5E0B385253FF2546250A0142B
+
+I=112
+KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+PT=A8A9AAAB181B1A15808186872B141516
+CT=2EE67B56280BC462429CEE6E3370CBC1
+
+I=113
+KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E
+PT=E7E6E5E4202323DDAAABACAD343B3A39
+CT=20DB650A9C8E9A84AB4D25F7EDC8F03F
+
+I=114
+KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+PT=A8A9AAAB2221202FEDECEBEA1E010003
+CT=3C36DA169525CF818843805F25B78AE5
+
+I=115
+KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E
+PT=F9F8FBFA5F5C5D42424344450E010003
+CT=9A781D960DB9E45E37779042FEA51922
+
+I=116
+KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+PT=57565554F5F6F7F89697909120DFDEDD
+CT=6560395EC269C672A3C288226EFDBA77
+
+I=117
+KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+PT=F8F9FAFBCCCFCEF1DDDCDBDA0E010003
+CT=8C772B7A189AC544453D5916EBB27B9A
+
+I=118
+KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+PT=D9D8DBDA7073727D80818687C2DDDCDF
+CT=77CA5468CC48E843D05F78EED9D6578F
+
+I=119
+KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+PT=C5C4C7C6080B0A1588898E8F68676665
+CT=72CDCC71DC82C60D4429C9E2D8195BAA
+
+I=120
+KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+PT=83828180DCDFDED186878081F0CFCECD
+CT=8080D68CE60E94B40B5B8B69EEB35AFA
+
+I=121
+KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+PT=98999A9BDDDEDFA079787F7E0A050407
+CT=44222D3CDE299C04369D58AC0EBA1E8E
+
+I=122
+KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+PT=CECFCCCD4F4C4D429F9E9998DFC0C1C2
+CT=9B8721B0A8DFC691C5BC5885DBFCB27A
+
+I=123
+KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+PT=404142436665647B29282F2EABA4A5A6
+CT=0DC015CE9A3A3414B5E62EC643384183
+
+I=124
+KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+PT=33323130E6E5E4EB23222524DEA1A0A3
+CT=705715448A8DA412025CE38345C2A148
+
+I=125
+KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+PT=CFCECDCCF6F5F4CBE6E7E0E199969794
+CT=C32B5B0B6FBAE165266C569F4B6ECF0B
+
+I=126
+KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+PT=BABBB8B97271707FDCDDDADB29363734
+CT=4DCA6C75192A01DDCA9476AF2A521E87
+
+I=127
+KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+PT=C9C8CBCA4447465926272021545B5A59
+CT=058691E627ECBC36AC07B6DB423BD698
+
+I=128
+KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+PT=050407067477767956575051221D1C1F
+CT=7444527095838FE080FC2BCDD30847EB
+
+==========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/ecb_vk.txt b/krb5-1-6/src/lib/crypto/aes/test/ecb_vk.txt
new file mode 100644
index 000000000..5dfd60089
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/ecb_vk.txt
@@ -0,0 +1,2334 @@
+
+=========================
+
+FILENAME:  "ecb_vk.txt"
+
+Electronic Codebook (ECB) Mode
+Variable Key Known Answer Tests
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+==========
+
+KEYSIZE=128
+
+PT=00000000000000000000000000000000
+
+I=1
+KEY=80000000000000000000000000000000
+CT=0EDD33D3C621E546455BD8BA1418BEC8
+
+I=2
+KEY=40000000000000000000000000000000
+CT=C0CC0C5DA5BD63ACD44A80774FAD5222
+
+I=3
+KEY=20000000000000000000000000000000
+CT=2F0B4B71BC77851B9CA56D42EB8FF080
+
+I=4
+KEY=10000000000000000000000000000000
+CT=6B1E2FFFE8A114009D8FE22F6DB5F876
+
+I=5
+KEY=08000000000000000000000000000000
+CT=9AA042C315F94CBB97B62202F83358F5
+
+I=6
+KEY=04000000000000000000000000000000
+CT=DBE01DE67E346A800C4C4B4880311DE4
+
+I=7
+KEY=02000000000000000000000000000000
+CT=C117D2238D53836ACD92DDCDB85D6A21
+
+I=8
+KEY=01000000000000000000000000000000
+CT=DC0ED85DF9611ABB7249CDD168C5467E
+
+I=9
+KEY=00800000000000000000000000000000
+CT=807D678FFF1F56FA92DE3381904842F2
+
+I=10
+KEY=00400000000000000000000000000000
+CT=0E53B3FCAD8E4B130EF73AEB957FB402
+
+I=11
+KEY=00200000000000000000000000000000
+CT=969FFD3B7C35439417E7BDE923035D65
+
+I=12
+KEY=00100000000000000000000000000000
+CT=A99B512C19CA56070491166A1503BF15
+
+I=13
+KEY=00080000000000000000000000000000
+CT=6E9985252126EE344D26AE369D2327E3
+
+I=14
+KEY=00040000000000000000000000000000
+CT=B85F4809F904C275491FCDCD1610387E
+
+I=15
+KEY=00020000000000000000000000000000
+CT=ED365B8D7D20C1F5D53FB94DD211DF7B
+
+I=16
+KEY=00010000000000000000000000000000
+CT=B3A575E86A8DB4A7135D604C43304896
+
+I=17
+KEY=00008000000000000000000000000000
+CT=89704BCB8E69F846259EB0ACCBC7F8A2
+
+I=18
+KEY=00004000000000000000000000000000
+CT=C56EE7C92197861F10D7A92B90882055
+
+I=19
+KEY=00002000000000000000000000000000
+CT=92F296F6846E0EAF9422A5A24A08B069
+
+I=20
+KEY=00001000000000000000000000000000
+CT=E67E32BB8F11DEB8699318BEE9E91A60
+
+I=21
+KEY=00000800000000000000000000000000
+CT=B08EEF85EAF626DD91B65C4C3A97D92B
+
+I=22
+KEY=00000400000000000000000000000000
+CT=661083A6ADDCE79BB4E0859AB5538013
+
+I=23
+KEY=00000200000000000000000000000000
+CT=55DFE2941E0EB10AFC0B333BD34DE1FE
+
+I=24
+KEY=00000100000000000000000000000000
+CT=6BFE5945E715C9662609770F8846087A
+
+I=25
+KEY=00000080000000000000000000000000
+CT=79848E9C30C2F8CDA8B325F7FED2B139
+
+I=26
+KEY=00000040000000000000000000000000
+CT=7A713A53B99FEF34AC04DEEF80965BD0
+
+I=27
+KEY=00000020000000000000000000000000
+CT=18144A2B46620D32C3C32CE52D49257F
+
+I=28
+KEY=00000010000000000000000000000000
+CT=872E827C70887C80749F7B8BB1847C7E
+
+I=29
+KEY=00000008000000000000000000000000
+CT=6B86C6A4FE6A60C59B1A3102F8DE49F3
+
+I=30
+KEY=00000004000000000000000000000000
+CT=9848BB3DFDF6F532F094679A4C231A20
+
+I=31
+KEY=00000002000000000000000000000000
+CT=925AD528E852E329B2091CD3F1C2BCEE
+
+I=32
+KEY=00000001000000000000000000000000
+CT=80DF436544B0DD596722E46792A40CD8
+
+I=33
+KEY=00000000800000000000000000000000
+CT=525DAF18F93E83E1E74BBBDDE4263BBA
+
+I=34
+KEY=00000000400000000000000000000000
+CT=F65C9D2EE485D24701FFA3313B9D5BE6
+
+I=35
+KEY=00000000200000000000000000000000
+CT=E4FC8D8BCA06425BDF94AFA40FCC14BA
+
+I=36
+KEY=00000000100000000000000000000000
+CT=A53F0A5CA1E4E6440BB975FF320DE6F8
+
+I=37
+KEY=00000000080000000000000000000000
+CT=D55313B9394080462E87E02899B553F0
+
+I=38
+KEY=00000000040000000000000000000000
+CT=34A71D761F71BCD344384C7F97D27906
+
+I=39
+KEY=00000000020000000000000000000000
+CT=233F3D819599612EBC89580245C996A8
+
+I=40
+KEY=00000000010000000000000000000000
+CT=B4F1374E5268DBCB676E447529E53F89
+
+I=41
+KEY=00000000008000000000000000000000
+CT=0816BD27861D2BA891D1044E39951E96
+
+I=42
+KEY=00000000004000000000000000000000
+CT=F3BE9EA3F10C73CA64FDE5DB13A951D1
+
+I=43
+KEY=00000000002000000000000000000000
+CT=2448086A8106FBD03048DDF857D3F1C8
+
+I=44
+KEY=00000000001000000000000000000000
+CT=670756E65BEC8B68F03D77CDCDCE7B91
+
+I=45
+KEY=00000000000800000000000000000000
+CT=EF968CF0D36FD6C6EFFD225F6FB44CA9
+
+I=46
+KEY=00000000000400000000000000000000
+CT=2E8767157922E3826DDCEC1B0CC1E105
+
+I=47
+KEY=00000000000200000000000000000000
+CT=78CE7EEC670E45A967BAB17E26A1AD36
+
+I=48
+KEY=00000000000100000000000000000000
+CT=3C5CEE825655F098F6E81A2F417DA3FB
+
+I=49
+KEY=00000000000080000000000000000000
+CT=67BFDB431DCE1292200BC6F5207ADB12
+
+I=50
+KEY=00000000000040000000000000000000
+CT=7540FD38E447C0779228548747843A6F
+
+I=51
+KEY=00000000000020000000000000000000
+CT=B85E513301F8A936EA9EC8A21A85B5E6
+
+I=52
+KEY=00000000000010000000000000000000
+CT=04C67DBF16C11427D507A455DE2C9BC5
+
+I=53
+KEY=00000000000008000000000000000000
+CT=03F75EB8959E55079CFFB4FF149A37B6
+
+I=54
+KEY=00000000000004000000000000000000
+CT=74550287F666C63BB9BC7838433434B0
+
+I=55
+KEY=00000000000002000000000000000000
+CT=7D537200195EBC3AEFD1EAAB1C385221
+
+I=56
+KEY=00000000000001000000000000000000
+CT=CE24E4D40C68A82B535CBD3C8E21652A
+
+I=57
+KEY=00000000000000800000000000000000
+CT=AB20072405AA8FC40265C6F1F3DC8BC0
+
+I=58
+KEY=00000000000000400000000000000000
+CT=6CFD2CF688F566B093F67B9B3839E80A
+
+I=59
+KEY=00000000000000200000000000000000
+CT=BD95977E6B7239D407A012C5544BF584
+
+I=60
+KEY=00000000000000100000000000000000
+CT=DF9C0130AC77E7C72C997F587B46DBE0
+
+I=61
+KEY=00000000000000080000000000000000
+CT=E7F1B82CADC53A648798945B34EFEFF2
+
+I=62
+KEY=00000000000000040000000000000000
+CT=932C6DBF69255CF13EDCDB72233ACEA3
+
+I=63
+KEY=00000000000000020000000000000000
+CT=5C76002BC7206560EFE550C80B8F12CC
+
+I=64
+KEY=00000000000000010000000000000000
+CT=F6B7BDD1CAEEBAB574683893C4475484
+
+I=65
+KEY=00000000000000008000000000000000
+CT=A920E37CC6DC6B31DA8C0169569F5034
+
+I=66
+KEY=00000000000000004000000000000000
+CT=919380ECD9C778BC513148B0C28D65FD
+
+I=67
+KEY=00000000000000002000000000000000
+CT=EE67308DD3F2D9E6C2170755E5784BE1
+
+I=68
+KEY=00000000000000001000000000000000
+CT=3CC73E53B85609023A05E149B223AE09
+
+I=69
+KEY=00000000000000000800000000000000
+CT=983E8AF7CF05EBB28D71EB841C9406E6
+
+I=70
+KEY=00000000000000000400000000000000
+CT=0F3099B2D31FA5299EE5BF43193287FC
+
+I=71
+KEY=00000000000000000200000000000000
+CT=B763D84F38C27FE6931DCEB6715D4DB6
+
+I=72
+KEY=00000000000000000100000000000000
+CT=5AE3C9B0E3CC29C0C61565CD01F8A248
+
+I=73
+KEY=00000000000000000080000000000000
+CT=F58083572CD90981958565D48D2DEE25
+
+I=74
+KEY=00000000000000000040000000000000
+CT=7E6255EEF8F70C0EF10337AAB1CCCEF8
+
+I=75
+KEY=00000000000000000020000000000000
+CT=AAD4BAC34DB22821841CE2F631961902
+
+I=76
+KEY=00000000000000000010000000000000
+CT=D7431C0409BB1441BA9C6858DC7D4E81
+
+I=77
+KEY=00000000000000000008000000000000
+CT=EF9298C65E339F6E801A59C626456993
+
+I=78
+KEY=00000000000000000004000000000000
+CT=53FE29F68FF541ABC3F0EF3350B72F7E
+
+I=79
+KEY=00000000000000000002000000000000
+CT=F6BBA5C10DB02529E2C2DA3FB582CC14
+
+I=80
+KEY=00000000000000000001000000000000
+CT=E4239AA37FC531A386DAD1126FC0E9CD
+
+I=81
+KEY=00000000000000000000800000000000
+CT=8F7758F857D15BBE7BFD0E416404C365
+
+I=82
+KEY=00000000000000000000400000000000
+CT=D273EB57C687BCD1B4EA7218A509E7B8
+
+I=83
+KEY=00000000000000000000200000000000
+CT=65D64F8D76E8B3423FA25C4EB58A210A
+
+I=84
+KEY=00000000000000000000100000000000
+CT=623D802B4EC450D66A16625702FCDBE0
+
+I=85
+KEY=00000000000000000000080000000000
+CT=7496460CB28E5791BAEAF9B68FB00022
+
+I=86
+KEY=00000000000000000000040000000000
+CT=34EA600F18BB0694B41681A49D510C1D
+
+I=87
+KEY=00000000000000000000020000000000
+CT=5F8FF0D47D5766D29B5D6E8F46423BD8
+
+I=88
+KEY=00000000000000000000010000000000
+CT=225F9286C5928BF09F84D3F93F541959
+
+I=89
+KEY=00000000000000000000008000000000
+CT=B21E90D25DF383416A5F072CEBEB1FFB
+
+I=90
+KEY=00000000000000000000004000000000
+CT=4AEFCDA089318125453EB9E8EB5E492E
+
+I=91
+KEY=00000000000000000000002000000000
+CT=4D3E75C6CD40EC4869BC85158591ADB8
+
+I=92
+KEY=00000000000000000000001000000000
+CT=63A8B904405436A1B99D7751866771B7
+
+I=93
+KEY=00000000000000000000000800000000
+CT=64F0DAAE47529199792EAE172BA53293
+
+I=94
+KEY=00000000000000000000000400000000
+CT=C3EEF84BEA18225D515A8C852A9047EE
+
+I=95
+KEY=00000000000000000000000200000000
+CT=A44AC422B47D47B81AF73B3E9AC9596E
+
+I=96
+KEY=00000000000000000000000100000000
+CT=D16E04A8FBC435094F8D53ADF25F5084
+
+I=97
+KEY=00000000000000000000000080000000
+CT=EF13DC34BAB03E124EEAD8B6BF44B532
+
+I=98
+KEY=00000000000000000000000040000000
+CT=D94799075C24DCC067AF0D392049250D
+
+I=99
+KEY=00000000000000000000000020000000
+CT=14F431771EDDCE4764C21A2254B5E3C8
+
+I=100
+KEY=00000000000000000000000010000000
+CT=7039329F36F2ED682B02991F28D64679
+
+I=101
+KEY=00000000000000000000000008000000
+CT=124EE24EDE5551639DB8B8B941F6141D
+
+I=102
+KEY=00000000000000000000000004000000
+CT=C2852879A34D5184E478EC918B993FEE
+
+I=103
+KEY=00000000000000000000000002000000
+CT=86A806A3525B93E432053C9AB5ABBEDF
+
+I=104
+KEY=00000000000000000000000001000000
+CT=C1609BF5A4F07E37C17A36366EC23ECC
+
+I=105
+KEY=00000000000000000000000000800000
+CT=7E81E7CB92159A51FFCEA331B1E8EA53
+
+I=106
+KEY=00000000000000000000000000400000
+CT=37A7BE002856C5A59A6E03EAFCE7729A
+
+I=107
+KEY=00000000000000000000000000200000
+CT=BDF98A5A4F91E890C9A1D1E5FAAB138F
+
+I=108
+KEY=00000000000000000000000000100000
+CT=4E96ACB66E051F2BC739CC3D3E34A26B
+
+I=109
+KEY=00000000000000000000000000080000
+CT=EE996CDD120EB86E21ECFA49E8E1FCF1
+
+I=110
+KEY=00000000000000000000000000040000
+CT=61B9E6B579DBF6070C351A1440DD85FF
+
+I=111
+KEY=00000000000000000000000000020000
+CT=AC369E484316440B40DFC83AA96E28E7
+
+I=112
+KEY=00000000000000000000000000010000
+CT=0A2D16DE985C76D45C579C1159413BBE
+
+I=113
+KEY=00000000000000000000000000008000
+CT=DA3FDC38DA1D374FA4802CDA1A1C6B0F
+
+I=114
+KEY=00000000000000000000000000004000
+CT=B842523D4C41C2211AFE43A5800ADCE3
+
+I=115
+KEY=00000000000000000000000000002000
+CT=9E2CDA90D8E992DBA6C73D8229567192
+
+I=116
+KEY=00000000000000000000000000001000
+CT=D49583B781D9E20F5BE101415957FC49
+
+I=117
+KEY=00000000000000000000000000000800
+CT=EF09DA5C12B376E458B9B8670032498E
+
+I=118
+KEY=00000000000000000000000000000400
+CT=A96BE0463DA774461A5E1D5A9DD1AC10
+
+I=119
+KEY=00000000000000000000000000000200
+CT=32CEE3341060790D2D4B1362EF397090
+
+I=120
+KEY=00000000000000000000000000000100
+CT=21CEA416A3D3359D2C4D58FB6A035F06
+
+I=121
+KEY=00000000000000000000000000000080
+CT=172AEAB3D507678ECAF455C12587ADB7
+
+I=122
+KEY=00000000000000000000000000000040
+CT=B6F897941EF8EBFF9FE80A567EF38478
+
+I=123
+KEY=00000000000000000000000000000020
+CT=A9723259D94A7DC662FB0C782CA3F1DD
+
+I=124
+KEY=00000000000000000000000000000010
+CT=2F91C984B9A4839F30001B9F430493B4
+
+I=125
+KEY=00000000000000000000000000000008
+CT=0472406345A610B048CB99EE0EF3FA0F
+
+I=126
+KEY=00000000000000000000000000000004
+CT=F5F39086646F8C05ED16EFA4B617957C
+
+I=127
+KEY=00000000000000000000000000000002
+CT=26D50F485A30408D5AF47A5736292450
+
+I=128
+KEY=00000000000000000000000000000001
+CT=0545AAD56DA2A97C3663D1432A3D1C84
+
+==========
+
+KEYSIZE=192
+
+PT=00000000000000000000000000000000
+
+I=1
+KEY=800000000000000000000000000000000000000000000000
+CT=DE885DC87F5A92594082D02CC1E1B42C
+
+I=2
+KEY=400000000000000000000000000000000000000000000000
+CT=C749194F94673F9DD2AA1932849630C1
+
+I=3
+KEY=200000000000000000000000000000000000000000000000
+CT=0CEF643313912934D310297B90F56ECC
+
+I=4
+KEY=100000000000000000000000000000000000000000000000
+CT=C4495D39D4A553B225FBA02A7B1B87E1
+
+I=5
+KEY=080000000000000000000000000000000000000000000000
+CT=636D10B1A0BCAB541D680A7970ADC830
+
+I=6
+KEY=040000000000000000000000000000000000000000000000
+CT=07CF045786BD6AFCC147D99E45A901A7
+
+I=7
+KEY=020000000000000000000000000000000000000000000000
+CT=6A8E3F425A7599348F95398448827976
+
+I=8
+KEY=010000000000000000000000000000000000000000000000
+CT=5518276836148A00D91089A20D8BFF57
+
+I=9
+KEY=008000000000000000000000000000000000000000000000
+CT=F267E07B5E87E3BC20B969C61D4FCB06
+
+I=10
+KEY=004000000000000000000000000000000000000000000000
+CT=5A1CDE69571D401BFCD20DEBADA2212C
+
+I=11
+KEY=002000000000000000000000000000000000000000000000
+CT=70A9057263254701D12ADD7D74CD509E
+
+I=12
+KEY=001000000000000000000000000000000000000000000000
+CT=35713A7E108031279388A33A0FE2E190
+
+I=13
+KEY=000800000000000000000000000000000000000000000000
+CT=E74EDE82B1254714F0C7B4B243108655
+
+I=14
+KEY=000400000000000000000000000000000000000000000000
+CT=39272E3100FAA37B55B862320D1B3EB3
+
+I=15
+KEY=000200000000000000000000000000000000000000000000
+CT=6D6E24C659FC5AEF712F77BCA19C9DD0
+
+I=16
+KEY=000100000000000000000000000000000000000000000000
+CT=76D18212F972370D3CC2C6C372C6CF2F
+
+I=17
+KEY=000080000000000000000000000000000000000000000000
+CT=B21A1F0BAE39E55C7594ED570A7783EA
+
+I=18
+KEY=000040000000000000000000000000000000000000000000
+CT=77DE202111895AC48DD1C974B358B458
+
+I=19
+KEY=000020000000000000000000000000000000000000000000
+CT=67810B311969012AAF7B504FFAF39FD1
+
+I=20
+KEY=000010000000000000000000000000000000000000000000
+CT=C22EA2344D3E9417A6BA07843E713AEA
+
+I=21
+KEY=000008000000000000000000000000000000000000000000
+CT=C79CAF4B97BEE0BD0630AB354539D653
+
+I=22
+KEY=000004000000000000000000000000000000000000000000
+CT=135FD1AF761D9AE23DF4AA6B86760DB4
+
+I=23
+KEY=000002000000000000000000000000000000000000000000
+CT=D4659D0B06ACD4D56AB8D11A16FD83B9
+
+I=24
+KEY=000001000000000000000000000000000000000000000000
+CT=F7D270028FC188E4E4F35A4AAA25D4D4
+
+I=25
+KEY=000000800000000000000000000000000000000000000000
+CT=345CAE5A8C9620A9913D5473985852FF
+
+I=26
+KEY=000000400000000000000000000000000000000000000000
+CT=4E8980ADDE60B0E42C0B287FEA41E729
+
+I=27
+KEY=000000200000000000000000000000000000000000000000
+CT=F11B6D74E1F15155633DC39743C1A527
+
+I=28
+KEY=000000100000000000000000000000000000000000000000
+CT=9C87916C0180064F9D3179C6F5DD8C35
+
+I=29
+KEY=000000080000000000000000000000000000000000000000
+CT=71AB186BCAEA518E461D4F7FAD230E6A
+
+I=30
+KEY=000000040000000000000000000000000000000000000000
+CT=C4A31BBC3DAAF742F9141C2A5001A49C
+
+I=31
+KEY=000000020000000000000000000000000000000000000000
+CT=E7C47B7B1D40F182A8928C8A55671D07
+
+I=32
+KEY=000000010000000000000000000000000000000000000000
+CT=8E17F294B28FA373C6249538868A7EEF
+
+I=33
+KEY=000000008000000000000000000000000000000000000000
+CT=754404096A5CBC08AF09491BE249141A
+
+I=34
+KEY=000000004000000000000000000000000000000000000000
+CT=101CB56E55F05D86369B6D1069204F0A
+
+I=35
+KEY=000000002000000000000000000000000000000000000000
+CT=73F19BB6604205C6EE227B9759791E41
+
+I=36
+KEY=000000001000000000000000000000000000000000000000
+CT=6270C0028F0D136C37A56B2CB64D24D6
+
+I=37
+KEY=000000000800000000000000000000000000000000000000
+CT=A3BF7C2C38D1114A087ECF212E694346
+
+I=38
+KEY=000000000400000000000000000000000000000000000000
+CT=49CABFF2CEF7D9F95F5EFB1F7A1A7DDE
+
+I=39
+KEY=000000000200000000000000000000000000000000000000
+CT=EC7F8A47CC59B849469255AD49F62752
+
+I=40
+KEY=000000000100000000000000000000000000000000000000
+CT=68FAE55A13EFAF9B07B3552A8A0DC9D1
+
+I=41
+KEY=000000000080000000000000000000000000000000000000
+CT=211E6B19C69FAEF481F64F24099CDA65
+
+I=42
+KEY=000000000040000000000000000000000000000000000000
+CT=DBB918C75BC5732416F79FB0C8EE4C5C
+
+I=43
+KEY=000000000020000000000000000000000000000000000000
+CT=98D494E5D963A6C8B92536D3EC35E3FD
+
+I=44
+KEY=000000000010000000000000000000000000000000000000
+CT=C9A873404D403D6F074190851D67781A
+
+I=45
+KEY=000000000008000000000000000000000000000000000000
+CT=073AEF4A7C77D921928CB0DD9D27CAE7
+
+I=46
+KEY=000000000004000000000000000000000000000000000000
+CT=89BDE25CEE36FDE769A10E52298CF90F
+
+I=47
+KEY=000000000002000000000000000000000000000000000000
+CT=26D0842D37EAD38557C65E0A5E5F122E
+
+I=48
+KEY=000000000001000000000000000000000000000000000000
+CT=F8294BA375AF46B3F22905BBAFFAB107
+
+I=49
+KEY=000000000000800000000000000000000000000000000000
+CT=2AD63EB4D0D43813B979CF72B35BDB94
+
+I=50
+KEY=000000000000400000000000000000000000000000000000
+CT=7710C171EE0F4EFA39BE4C995180181D
+
+I=51
+KEY=000000000000200000000000000000000000000000000000
+CT=C0CB2B40DBA7BE8C0698FAE1E4B80FF8
+
+I=52
+KEY=000000000000100000000000000000000000000000000000
+CT=97970E505194622FD955CA1B80B784E9
+
+I=53
+KEY=000000000000080000000000000000000000000000000000
+CT=7CB1824B29F850900DF2CAD9CF04C1CF
+
+I=54
+KEY=000000000000040000000000000000000000000000000000
+CT=FDF4F036BB988E42F2F62DE63FE19A64
+
+I=55
+KEY=000000000000020000000000000000000000000000000000
+CT=08908CFE2C82606B2C15DF61B75CF3E2
+
+I=56
+KEY=000000000000010000000000000000000000000000000000
+CT=B3AA689EF2D07FF365ACB9ADBA2AF07A
+
+I=57
+KEY=000000000000008000000000000000000000000000000000
+CT=F2672CD8EAA3B98776660D0263656F5C
+
+I=58
+KEY=000000000000004000000000000000000000000000000000
+CT=5BDEAC00E986687B9E1D94A0DA7BF452
+
+I=59
+KEY=000000000000002000000000000000000000000000000000
+CT=E6D57BD66EA1627363EE0C4B711B0B21
+
+I=60
+KEY=000000000000001000000000000000000000000000000000
+CT=03730DD6ACB4AD9996A63BE7765EC06F
+
+I=61
+KEY=000000000000000800000000000000000000000000000000
+CT=A470E361AA5437B2BE8586D2F78DE582
+
+I=62
+KEY=000000000000000400000000000000000000000000000000
+CT=7567FEEFA559911FD479670246B484E3
+
+I=63
+KEY=000000000000000200000000000000000000000000000000
+CT=29829DEA15A4E7A4C049045E7B106E29
+
+I=64
+KEY=000000000000000100000000000000000000000000000000
+CT=A407834C3D89D48A2CB7A152208FA4ED
+
+I=65
+KEY=000000000000000080000000000000000000000000000000
+CT=68F948053F78FEF0D8F9FE7EF3A89819
+
+I=66
+KEY=000000000000000040000000000000000000000000000000
+CT=B605174CAB13AD8FE3B20DA3AE7B0234
+
+I=67
+KEY=000000000000000020000000000000000000000000000000
+CT=CCAB8F0AEBFF032893996D383CBFDBFA
+
+I=68
+KEY=000000000000000010000000000000000000000000000000
+CT=AF14BB8428C9730B7DC17B6C1CBEBCC8
+
+I=69
+KEY=000000000000000008000000000000000000000000000000
+CT=5A41A21332040877EB7B89E8E80D19FE
+
+I=70
+KEY=000000000000000004000000000000000000000000000000
+CT=AC1BA52EFCDDE368B1596F2F0AD893A0
+
+I=71
+KEY=000000000000000002000000000000000000000000000000
+CT=41B890E31B9045E6ECDC1BC3F2DB9BCC
+
+I=72
+KEY=000000000000000001000000000000000000000000000000
+CT=4D54A549728E55B19A23660424A0F146
+
+I=73
+KEY=000000000000000000800000000000000000000000000000
+CT=A917581F41C47C7DDCFFD5285E2D6A61
+
+I=74
+KEY=000000000000000000400000000000000000000000000000
+CT=604DF24BA6099B93A7405A524D764FCB
+
+I=75
+KEY=000000000000000000200000000000000000000000000000
+CT=78D9D156F28B190E232D1B7AE7FC730A
+
+I=76
+KEY=000000000000000000100000000000000000000000000000
+CT=5A12C39E442CD7F27B3CD77F5D029582
+
+I=77
+KEY=000000000000000000080000000000000000000000000000
+CT=FF2BF2F47CF7B0F28EE25AF95DBF790D
+
+I=78
+KEY=000000000000000000040000000000000000000000000000
+CT=1863BB7D193BDA39DF090659EB8AE48B
+
+I=79
+KEY=000000000000000000020000000000000000000000000000
+CT=38178F2FB4CFCF31E87E1ABCDC023EB5
+
+I=80
+KEY=000000000000000000010000000000000000000000000000
+CT=F5B13DC690CC0D541C6BA533023DC8C9
+
+I=81
+KEY=000000000000000000008000000000000000000000000000
+CT=48EC05238D7375D126DC9D08884D4827
+
+I=82
+KEY=000000000000000000004000000000000000000000000000
+CT=ACD0D81139691B310B92A6E377BACC87
+
+I=83
+KEY=000000000000000000002000000000000000000000000000
+CT=9A4AA43578B55CE9CC178F0D2E162C79
+
+I=84
+KEY=000000000000000000001000000000000000000000000000
+CT=08AD94BC737DB3C87D49B9E01B720D81
+
+I=85
+KEY=000000000000000000000800000000000000000000000000
+CT=3BCFB2D5D210E8332900C5991D551A2A
+
+I=86
+KEY=000000000000000000000400000000000000000000000000
+CT=C5F0C6B9397ACB29635CE1A0DA2D8D96
+
+I=87
+KEY=000000000000000000000200000000000000000000000000
+CT=844A29EFC693E2FA9900F87FBF5DCD5F
+
+I=88
+KEY=000000000000000000000100000000000000000000000000
+CT=5126A1C41051FEA158BE41200E1EA59D
+
+I=89
+KEY=000000000000000000000080000000000000000000000000
+CT=302123CA7B4F46D667FFFB0EB6AA7703
+
+I=90
+KEY=000000000000000000000040000000000000000000000000
+CT=A9D16BCE7DB5C024277709EE2A88D91A
+
+I=91
+KEY=000000000000000000000020000000000000000000000000
+CT=F013C5EC123A26CFC34B598C992A996B
+
+I=92
+KEY=000000000000000000000010000000000000000000000000
+CT=E38A825CD971A1D2E56FB1DBA248F2A8
+
+I=93
+KEY=000000000000000000000008000000000000000000000000
+CT=6E701773C0311E0BD4C5A097406D22B3
+
+I=94
+KEY=000000000000000000000004000000000000000000000000
+CT=754262CEF0C64BE4C3E67C35ABE439F7
+
+I=95
+KEY=000000000000000000000002000000000000000000000000
+CT=C9C2D4C47DF7D55CFA0EE5F1FE5070F4
+
+I=96
+KEY=000000000000000000000001000000000000000000000000
+CT=6AB4BEA85B172573D8BD2D5F4329F13D
+
+I=97
+KEY=000000000000000000000000800000000000000000000000
+CT=11F03EF28E2CC9AE5165C587F7396C8C
+
+I=98
+KEY=000000000000000000000000400000000000000000000000
+CT=0682F2EB1A68BAC7949922C630DD27FA
+
+I=99
+KEY=000000000000000000000000200000000000000000000000
+CT=ABB0FEC0413D659AFE8E3DCF6BA873BB
+
+I=100
+KEY=000000000000000000000000100000000000000000000000
+CT=FE86A32E19F805D6569B2EFADD9C92AA
+
+I=101
+KEY=000000000000000000000000080000000000000000000000
+CT=E434E472275D1837D3D717F2EECC88C3
+
+I=102
+KEY=000000000000000000000000040000000000000000000000
+CT=74E57DCD12A21D26EF8ADAFA5E60469A
+
+I=103
+KEY=000000000000000000000000020000000000000000000000
+CT=C275429D6DAD45DDD423FA63C816A9C1
+
+I=104
+KEY=000000000000000000000000010000000000000000000000
+CT=7F6EC1A9AE729E86F7744AED4B8F4F07
+
+I=105
+KEY=000000000000000000000000008000000000000000000000
+CT=48B5A71AB9292BD4F9E608EF102636B2
+
+I=106
+KEY=000000000000000000000000004000000000000000000000
+CT=076FB95D5F536C78CBED3181BCCF3CF1
+
+I=107
+KEY=000000000000000000000000002000000000000000000000
+CT=BFA76BEA1E684FD3BF9256119EE0BC0F
+
+I=108
+KEY=000000000000000000000000001000000000000000000000
+CT=7D395923D56577F3FF8670998F8C4A71
+
+I=109
+KEY=000000000000000000000000000800000000000000000000
+CT=BA02C986E529AC18A882C34BA389625F
+
+I=110
+KEY=000000000000000000000000000400000000000000000000
+CT=3DFCF2D882AFE75D3A191193013A84B5
+
+I=111
+KEY=000000000000000000000000000200000000000000000000
+CT=FAD1FDE1D0241784B63080D2C74D236C
+
+I=112
+KEY=000000000000000000000000000100000000000000000000
+CT=7D6C80D39E41F007A14FB9CD2B2C15CD
+
+I=113
+KEY=000000000000000000000000000080000000000000000000
+CT=7975F401FC10637BB33EA2DB058FF6EC
+
+I=114
+KEY=000000000000000000000000000040000000000000000000
+CT=657983865C55A818F02B7FCD52ED7E99
+
+I=115
+KEY=000000000000000000000000000020000000000000000000
+CT=B32BEB1776F9827FF4C3AC9997E84B20
+
+I=116
+KEY=000000000000000000000000000010000000000000000000
+CT=2AE2C7C374F0A41E3D46DBC3E66BB59F
+
+I=117
+KEY=000000000000000000000000000008000000000000000000
+CT=4D835E4ABDD4BDC6B88316A6E931A07F
+
+I=118
+KEY=000000000000000000000000000004000000000000000000
+CT=E07EFABFF1C353F7384EBB87B435A3F3
+
+I=119
+KEY=000000000000000000000000000002000000000000000000
+CT=ED3088DC3FAF89AD87B4356FF1BB09C2
+
+I=120
+KEY=000000000000000000000000000001000000000000000000
+CT=4324D01140C156FC898C2E32BA03FB05
+
+I=121
+KEY=000000000000000000000000000000800000000000000000
+CT=BE15D016FACB5BAFBC24FA9289132166
+
+I=122
+KEY=000000000000000000000000000000400000000000000000
+CT=AC9B7048EDB1ACF4D97A5B0B3F50884B
+
+I=123
+KEY=000000000000000000000000000000200000000000000000
+CT=448BECE1F86C7845DFA9A4BB2A016FB3
+
+I=124
+KEY=000000000000000000000000000000100000000000000000
+CT=10DD445E87686EB46EA9B1ABC49257F0
+
+I=125
+KEY=000000000000000000000000000000080000000000000000
+CT=B7FCCF7659FA756D4B7303EEA6C07458
+
+I=126
+KEY=000000000000000000000000000000040000000000000000
+CT=289117115CA3513BAA7640B1004872C2
+
+I=127
+KEY=000000000000000000000000000000020000000000000000
+CT=57CB42F7EE7186051F50B93FFA7B35BF
+
+I=128
+KEY=000000000000000000000000000000010000000000000000
+CT=F2741BFBFB81663B9136802FB9C3126A
+
+I=129
+KEY=000000000000000000000000000000008000000000000000
+CT=E32DDDC5C7398C096E3BD535B31DB5CE
+
+I=130
+KEY=000000000000000000000000000000004000000000000000
+CT=81D3C204E608AF9CC713EAEBCB72433F
+
+I=131
+KEY=000000000000000000000000000000002000000000000000
+CT=D4DEEF4BFC36AAA579496E6935F8F98E
+
+I=132
+KEY=000000000000000000000000000000001000000000000000
+CT=C356DB082B97802B038571C392C5C8F6
+
+I=133
+KEY=000000000000000000000000000000000800000000000000
+CT=A3919ECD4861845F2527B77F06AC6A4E
+
+I=134
+KEY=000000000000000000000000000000000400000000000000
+CT=A53858E17A2F802A20E40D44494FFDA0
+
+I=135
+KEY=000000000000000000000000000000000200000000000000
+CT=5D989E122B78C758921EDBEEB827F0C0
+
+I=136
+KEY=000000000000000000000000000000000100000000000000
+CT=4B1C0C8F9E7830CC3C4BE7BD226FA8DE
+
+I=137
+KEY=000000000000000000000000000000000080000000000000
+CT=82C40C5FD897FBCA7B899C70713573A1
+
+I=138
+KEY=000000000000000000000000000000000040000000000000
+CT=ED13EE2D45E00F75CCDB51EA8E3E36AD
+
+I=139
+KEY=000000000000000000000000000000000020000000000000
+CT=F121799EEFE8432423176A3CCF6462BB
+
+I=140
+KEY=000000000000000000000000000000000010000000000000
+CT=4FA0C06F07997E98271DD86F7B355C50
+
+I=141
+KEY=000000000000000000000000000000000008000000000000
+CT=849EB364B4E81D058649DC5B1BF029B9
+
+I=142
+KEY=000000000000000000000000000000000004000000000000
+CT=F48F9E0DE8DE7AD944A207809335D9B1
+
+I=143
+KEY=000000000000000000000000000000000002000000000000
+CT=E59E9205B5A81A4FD26DFCF308966022
+
+I=144
+KEY=000000000000000000000000000000000001000000000000
+CT=3A91A1BE14AAE9ED700BDF9D70018804
+
+I=145
+KEY=000000000000000000000000000000000000800000000000
+CT=8ABAD78DCB79A48D79070E7DA89664EC
+
+I=146
+KEY=000000000000000000000000000000000000400000000000
+CT=B68377D98AAE6044938A7457F6C649D9
+
+I=147
+KEY=000000000000000000000000000000000000200000000000
+CT=E4E1275C42F5F1B63D662C099D6CE33D
+
+I=148
+KEY=000000000000000000000000000000000000100000000000
+CT=7DEF32A34C6BE668F17DA1BB193B06EF
+
+I=149
+KEY=000000000000000000000000000000000000080000000000
+CT=78B6000CC3D30CB3A74B68D0EDBD2B53
+
+I=150
+KEY=000000000000000000000000000000000000040000000000
+CT=0A47531DE88DD8AE5C23EAE4F7D1F2D5
+
+I=151
+KEY=000000000000000000000000000000000000020000000000
+CT=667B24E8000CF68231EC484581D922E5
+
+I=152
+KEY=000000000000000000000000000000000000010000000000
+CT=39DAA5EBD4AACAE130E9C33236C52024
+
+I=153
+KEY=000000000000000000000000000000000000008000000000
+CT=E3C88760B3CB21360668A63E55BB45D1
+
+I=154
+KEY=000000000000000000000000000000000000004000000000
+CT=F131EE903C1CDB49D416866FD5D8DE51
+
+I=155
+KEY=000000000000000000000000000000000000002000000000
+CT=7A1916135B0447CF4033FC13047A583A
+
+I=156
+KEY=000000000000000000000000000000000000001000000000
+CT=F7D55FB27991143DCDFA90DDF0424FCB
+
+I=157
+KEY=000000000000000000000000000000000000000800000000
+CT=EA93E7D1CA1111DBD8F7EC111A848C0C
+
+I=158
+KEY=000000000000000000000000000000000000000400000000
+CT=2A689E39DFD3CBCBE221326E95888779
+
+I=159
+KEY=000000000000000000000000000000000000000200000000
+CT=C1CE399CA762318AC2C40D1928B4C57D
+
+I=160
+KEY=000000000000000000000000000000000000000100000000
+CT=D43FB6F2B2879C8BFAF0092DA2CA63ED
+
+I=161
+KEY=000000000000000000000000000000000000000080000000
+CT=224563E617158DF97650AF5D130E78A5
+
+I=162
+KEY=000000000000000000000000000000000000000040000000
+CT=6562FDF6833B7C4F7484AE6EBCC243DD
+
+I=163
+KEY=000000000000000000000000000000000000000020000000
+CT=93D58BA7BED22615D661D002885A7457
+
+I=164
+KEY=000000000000000000000000000000000000000010000000
+CT=9A0EF559003AD9E52D3E09ED3C1D3320
+
+I=165
+KEY=000000000000000000000000000000000000000008000000
+CT=96BAF5A7DC6F3DD27EB4C717A85D261C
+
+I=166
+KEY=000000000000000000000000000000000000000004000000
+CT=B8762E06884900E8452293190E19CCDB
+
+I=167
+KEY=000000000000000000000000000000000000000002000000
+CT=785416A22BD63CBABF4B1789355197D3
+
+I=168
+KEY=000000000000000000000000000000000000000001000000
+CT=A0D20CE1489BAA69A3612DCE90F7ABF6
+
+I=169
+KEY=000000000000000000000000000000000000000000800000
+CT=700244E93DC94230CC607FFBA0E48F32
+
+I=170
+KEY=000000000000000000000000000000000000000000400000
+CT=85329E476829F872A2B4A7E59F91FF2D
+
+I=171
+KEY=000000000000000000000000000000000000000000200000
+CT=E4219B4935D988DB719B8B8B2B53D247
+
+I=172
+KEY=000000000000000000000000000000000000000000100000
+CT=6ACDD04FD13D4DB4409FE8DD13FD737B
+
+I=173
+KEY=000000000000000000000000000000000000000000080000
+CT=9EB7A670AB59E15BE582378701C1EC14
+
+I=174
+KEY=000000000000000000000000000000000000000000040000
+CT=29DF2D6935FE657763BC7A9F22D3D492
+
+I=175
+KEY=000000000000000000000000000000000000000000020000
+CT=99303359D4A13AFDBE6C784028CE533A
+
+I=176
+KEY=000000000000000000000000000000000000000000010000
+CT=FF5C70A6334545F33B9DBF7BEA0417CA
+
+I=177
+KEY=000000000000000000000000000000000000000000008000
+CT=289F58A17E4C50EDA4269EFB3DF55815
+
+I=178
+KEY=000000000000000000000000000000000000000000004000
+CT=EA35DCB416E9E1C2861D1682F062B5EB
+
+I=179
+KEY=000000000000000000000000000000000000000000002000
+CT=3A47BF354BE775383C50B0C0A83E3A58
+
+I=180
+KEY=000000000000000000000000000000000000000000001000
+CT=BF6C1DC069FB95D05D43B01D8206D66B
+
+I=181
+KEY=000000000000000000000000000000000000000000000800
+CT=046D1D580D5898DA6595F32FD1F0C33D
+
+I=182
+KEY=000000000000000000000000000000000000000000000400
+CT=5F57803B7B82A110F7E9855D6A546082
+
+I=183
+KEY=000000000000000000000000000000000000000000000200
+CT=25336ECF34E7BE97862CDFF715FF05A8
+
+I=184
+KEY=000000000000000000000000000000000000000000000100
+CT=ACBAA2A943D8078022D693890E8C4FEF
+
+I=185
+KEY=000000000000000000000000000000000000000000000080
+CT=3947597879F6B58E4E2F0DF825A83A38
+
+I=186
+KEY=000000000000000000000000000000000000000000000040
+CT=4EB8CC3335496130655BF3CA570A4FC0
+
+I=187
+KEY=000000000000000000000000000000000000000000000020
+CT=BBDA7769AD1FDA425E18332D97868824
+
+I=188
+KEY=000000000000000000000000000000000000000000000010
+CT=5E7532D22DDB0829A29C868198397154
+
+I=189
+KEY=000000000000000000000000000000000000000000000008
+CT=E66DA67B630AB7AE3E682855E1A1698E
+
+I=190
+KEY=000000000000000000000000000000000000000000000004
+CT=4D93800F671B48559A64D1EA030A590A
+
+I=191
+KEY=000000000000000000000000000000000000000000000002
+CT=F33159FCC7D9AE30C062CD3B322AC764
+
+I=192
+KEY=000000000000000000000000000000000000000000000001
+CT=8BAE4EFB70D33A9792EEA9BE70889D72
+
+==========
+
+KEYSIZE=256
+
+PT=00000000000000000000000000000000
+
+I=1
+KEY=8000000000000000000000000000000000000000000000000000000000000000
+CT=E35A6DCB19B201A01EBCFA8AA22B5759
+
+I=2
+KEY=4000000000000000000000000000000000000000000000000000000000000000
+CT=5075C2405B76F22F553488CAE47CE90B
+
+I=3
+KEY=2000000000000000000000000000000000000000000000000000000000000000
+CT=49DF95D844A0145A7DE01C91793302D3
+
+I=4
+KEY=1000000000000000000000000000000000000000000000000000000000000000
+CT=E7396D778E940B8418A86120E5F421FE
+
+I=5
+KEY=0800000000000000000000000000000000000000000000000000000000000000
+CT=05F535C36FCEDE4657BE37F4087DB1EF
+
+I=6
+KEY=0400000000000000000000000000000000000000000000000000000000000000
+CT=D0C1DDDD10DA777C68AB36AF51F2C204
+
+I=7
+KEY=0200000000000000000000000000000000000000000000000000000000000000
+CT=1C55FB811B5C6464C4E5DE1535A75514
+
+I=8
+KEY=0100000000000000000000000000000000000000000000000000000000000000
+CT=52917F3AE957D5230D3A2AF57C7B5A71
+
+I=9
+KEY=0080000000000000000000000000000000000000000000000000000000000000
+CT=C6E3D5501752DD5E9AEF086D6B45D705
+
+I=10
+KEY=0040000000000000000000000000000000000000000000000000000000000000
+CT=A24A9C7AF1D9B1E17E1C9A3E711B3FA7
+
+I=11
+KEY=0020000000000000000000000000000000000000000000000000000000000000
+CT=B881ECA724A6D43DBC6B96F6F59A0D20
+
+I=12
+KEY=0010000000000000000000000000000000000000000000000000000000000000
+CT=EC524D9A24DFFF2A9639879B83B8E137
+
+I=13
+KEY=0008000000000000000000000000000000000000000000000000000000000000
+CT=34C4F345F5466215A037F443635D6F75
+
+I=14
+KEY=0004000000000000000000000000000000000000000000000000000000000000
+CT=5BA5055BEDB8895F672E29F2EB5A355D
+
+I=15
+KEY=0002000000000000000000000000000000000000000000000000000000000000
+CT=B3F692AA3A435259EBBEF9B51AD1E08D
+
+I=16
+KEY=0001000000000000000000000000000000000000000000000000000000000000
+CT=414FEB4376F2C64A5D2FBB2ED531BA7D
+
+I=17
+KEY=0000800000000000000000000000000000000000000000000000000000000000
+CT=A20D519E3BCA3303F07E81719F61605E
+
+I=18
+KEY=0000400000000000000000000000000000000000000000000000000000000000
+CT=A08D10E520AF811F45BD60A2DC0DC4B1
+
+I=19
+KEY=0000200000000000000000000000000000000000000000000000000000000000
+CT=B06893A8C563C430E6F3858826EFBBE4
+
+I=20
+KEY=0000100000000000000000000000000000000000000000000000000000000000
+CT=0FFEE26AE2D3929C6BD9C6BEDFF84409
+
+I=21
+KEY=0000080000000000000000000000000000000000000000000000000000000000
+CT=4D0F5E906ED77801FC0EF53EDC5F9E2B
+
+I=22
+KEY=0000040000000000000000000000000000000000000000000000000000000000
+CT=8B6EC00119AD8B026DCE56EA7DEFE930
+
+I=23
+KEY=0000020000000000000000000000000000000000000000000000000000000000
+CT=69026591D43363EE9D83B5007F0B484E
+
+I=24
+KEY=0000010000000000000000000000000000000000000000000000000000000000
+CT=27135D86950C6A2F86872706279A4761
+
+I=25
+KEY=0000008000000000000000000000000000000000000000000000000000000000
+CT=35E6DB8723F281DA410C3AC8535ED77C
+
+I=26
+KEY=0000004000000000000000000000000000000000000000000000000000000000
+CT=57427CF214B8C28E4BBF487CCB8D0E09
+
+I=27
+KEY=0000002000000000000000000000000000000000000000000000000000000000
+CT=6DF01BF56E5131AC87F96E99CAB86367
+
+I=28
+KEY=0000001000000000000000000000000000000000000000000000000000000000
+CT=3856C5B55790B768BBF7D43031579BCF
+
+I=29
+KEY=0000000800000000000000000000000000000000000000000000000000000000
+CT=1E6ED8FB7C15BC4D2F63BA7037ED44D0
+
+I=30
+KEY=0000000400000000000000000000000000000000000000000000000000000000
+CT=E1B2ED6CD8D93D455534E401156D4BCF
+
+I=31
+KEY=0000000200000000000000000000000000000000000000000000000000000000
+CT=EFBCCA5BDFDAD10E875F02336212CE36
+
+I=32
+KEY=0000000100000000000000000000000000000000000000000000000000000000
+CT=0B777F02FD18DCE2646DCFE868DFAFAD
+
+I=33
+KEY=0000000080000000000000000000000000000000000000000000000000000000
+CT=C8A104B5693D1B14F5BF1F10100BF508
+
+I=34
+KEY=0000000040000000000000000000000000000000000000000000000000000000
+CT=4CCE6615244AFCB38408FECE219962EA
+
+I=35
+KEY=0000000020000000000000000000000000000000000000000000000000000000
+CT=F99E7845D3A255B394C9C050CBA258B1
+
+I=36
+KEY=0000000010000000000000000000000000000000000000000000000000000000
+CT=B4AFBB787F9BCFB7B55FDF447F611295
+
+I=37
+KEY=0000000008000000000000000000000000000000000000000000000000000000
+CT=AE1C426A697FAF2808B7EF6ADDB5C020
+
+I=38
+KEY=0000000004000000000000000000000000000000000000000000000000000000
+CT=7572F92811A85B9BDD38DEAD9945BCAE
+
+I=39
+KEY=0000000002000000000000000000000000000000000000000000000000000000
+CT=71BC7AA46E43FB95A181527D9F6A360F
+
+I=40
+KEY=0000000001000000000000000000000000000000000000000000000000000000
+CT=5542EF2923066F1EC8F546DD0D8E7CA8
+
+I=41
+KEY=0000000000800000000000000000000000000000000000000000000000000000
+CT=6B92317C7D623790B748FDD7EFC42422
+
+I=42
+KEY=0000000000400000000000000000000000000000000000000000000000000000
+CT=0FE7C097E899C71EF045360F8D6C25CF
+
+I=43
+KEY=0000000000200000000000000000000000000000000000000000000000000000
+CT=4ECE7EE107D0264D04693151C25B9DF6
+
+I=44
+KEY=0000000000100000000000000000000000000000000000000000000000000000
+CT=FD6AE687CBFCA9E301045888D3BB9605
+
+I=45
+KEY=0000000000080000000000000000000000000000000000000000000000000000
+CT=476B579C8556C7254424902CC1D6D36E
+
+I=46
+KEY=0000000000040000000000000000000000000000000000000000000000000000
+CT=4133CBCDFDD6B8860A1FC18665D6D71B
+
+I=47
+KEY=0000000000020000000000000000000000000000000000000000000000000000
+CT=3B36EC2664798C108B816812C65DFDC7
+
+I=48
+KEY=0000000000010000000000000000000000000000000000000000000000000000
+CT=364E20A234FEA385D48DC5A09C9E70CF
+
+I=49
+KEY=0000000000008000000000000000000000000000000000000000000000000000
+CT=4A4BA25969DE3F5EE5642C71AAD0EFD1
+
+I=50
+KEY=0000000000004000000000000000000000000000000000000000000000000000
+CT=E42CBAAE43297F67A76C1C501BB79E36
+
+I=51
+KEY=0000000000002000000000000000000000000000000000000000000000000000
+CT=23CEDEDA4C15B4C037E8C61492217937
+
+I=52
+KEY=0000000000001000000000000000000000000000000000000000000000000000
+CT=A1719147A1F4A1A1180BD16E8593DCDE
+
+I=53
+KEY=0000000000000800000000000000000000000000000000000000000000000000
+CT=AB82337E9FB0EC60D1F25A1D0014192C
+
+I=54
+KEY=0000000000000400000000000000000000000000000000000000000000000000
+CT=74BF2D8FC5A8388DF1A3A4D7D33FC164
+
+I=55
+KEY=0000000000000200000000000000000000000000000000000000000000000000
+CT=D5B493317E6FBC6FFFD664B3C491368A
+
+I=56
+KEY=0000000000000100000000000000000000000000000000000000000000000000
+CT=BA767381586DA56A2A8D503D5F7ADA0B
+
+I=57
+KEY=0000000000000080000000000000000000000000000000000000000000000000
+CT=E8E6BC57DFE9CCADB0DECABF4E5CF91F
+
+I=58
+KEY=0000000000000040000000000000000000000000000000000000000000000000
+CT=3C8E5A5CDC9CEED90815D1F84BB2998C
+
+I=59
+KEY=0000000000000020000000000000000000000000000000000000000000000000
+CT=283843020BA38F056001B2FD585F7CC9
+
+I=60
+KEY=0000000000000010000000000000000000000000000000000000000000000000
+CT=D8ADC7426F623ECE8741A70621D28870
+
+I=61
+KEY=0000000000000008000000000000000000000000000000000000000000000000
+CT=D7C5C215592D06F00E6A80DA69A28EA9
+
+I=62
+KEY=0000000000000004000000000000000000000000000000000000000000000000
+CT=52CF6FA433C3C870CAC70190358F7F16
+
+I=63
+KEY=0000000000000002000000000000000000000000000000000000000000000000
+CT=F63D442A584DA71786ADEC9F3346DF75
+
+I=64
+KEY=0000000000000001000000000000000000000000000000000000000000000000
+CT=549078F4B0CA7079B45F9A5ADAFAFD99
+
+I=65
+KEY=0000000000000000800000000000000000000000000000000000000000000000
+CT=F2A5986EE4E9984BE2BAFB79EA8152FA
+
+I=66
+KEY=0000000000000000400000000000000000000000000000000000000000000000
+CT=8A74535017B4DB2776668A1FAE64384C
+
+I=67
+KEY=0000000000000000200000000000000000000000000000000000000000000000
+CT=E613342F57A97FD95DC088711A5D0ECD
+
+I=68
+KEY=0000000000000000100000000000000000000000000000000000000000000000
+CT=3FFAEBF6B22CF1DC82AE17CD48175B01
+
+I=69
+KEY=0000000000000000080000000000000000000000000000000000000000000000
+CT=BAFD52EFA15C248CCBF9757735E6B1CE
+
+I=70
+KEY=0000000000000000040000000000000000000000000000000000000000000000
+CT=7AF94BC018D9DDD4539D2DD1C6F4000F
+
+I=71
+KEY=0000000000000000020000000000000000000000000000000000000000000000
+CT=FE177AD61CA0FDB281086FBA8FE76803
+
+I=72
+KEY=0000000000000000010000000000000000000000000000000000000000000000
+CT=74DBEA15E2E9285BAD163D7D534251B6
+
+I=73
+KEY=0000000000000000008000000000000000000000000000000000000000000000
+CT=23DD21331B3A92F200FE56FF050FFE74
+
+I=74
+KEY=0000000000000000004000000000000000000000000000000000000000000000
+CT=A69C5AA34AB20A858CAFA766EACED6D8
+
+I=75
+KEY=0000000000000000002000000000000000000000000000000000000000000000
+CT=3F72BB4DF2A4F941A4A09CB78F04B97A
+
+I=76
+KEY=0000000000000000001000000000000000000000000000000000000000000000
+CT=72CC43577E1FD5FD14622D24D97FCDCC
+
+I=77
+KEY=0000000000000000000800000000000000000000000000000000000000000000
+CT=D83AF8EBE93E0B6B99CAFADE224937D1
+
+I=78
+KEY=0000000000000000000400000000000000000000000000000000000000000000
+CT=44042329128D56CAA8D084C8BD769D1E
+
+I=79
+KEY=0000000000000000000200000000000000000000000000000000000000000000
+CT=14102D72290DE4F2C430ADD1ED64BA1D
+
+I=80
+KEY=0000000000000000000100000000000000000000000000000000000000000000
+CT=449124097B1ECD0AE7065206DF06F03C
+
+I=81
+KEY=0000000000000000000080000000000000000000000000000000000000000000
+CT=D060A99F8CC153A42E11E5F97BD7584A
+
+I=82
+KEY=0000000000000000000040000000000000000000000000000000000000000000
+CT=65605B3EA9261488D53E48602ADEA299
+
+I=83
+KEY=0000000000000000000020000000000000000000000000000000000000000000
+CT=C5E5CAD7A208DE8EA6BE049EFE5C7346
+
+I=84
+KEY=0000000000000000000010000000000000000000000000000000000000000000
+CT=4C280C46D2181646048DD5BC0C0831A5
+
+I=85
+KEY=0000000000000000000008000000000000000000000000000000000000000000
+CT=5DD65CF37F2A0929559AABAFDA08E730
+
+I=86
+KEY=0000000000000000000004000000000000000000000000000000000000000000
+CT=31F2335CAAF264172F69A693225E6D22
+
+I=87
+KEY=0000000000000000000002000000000000000000000000000000000000000000
+CT=3E28B35F99A72662590DA96426DD377F
+
+I=88
+KEY=0000000000000000000001000000000000000000000000000000000000000000
+CT=570F40F5D7B20441486578ED344343BE
+
+I=89
+KEY=0000000000000000000000800000000000000000000000000000000000000000
+CT=C54308AD1C9E3B19F8B7417873045A8C
+
+I=90
+KEY=0000000000000000000000400000000000000000000000000000000000000000
+CT=CBF335E39CE13ADE2B696179E8FD0CE1
+
+I=91
+KEY=0000000000000000000000200000000000000000000000000000000000000000
+CT=9C2FBF422355D8293083D51F4A3C18A9
+
+I=92
+KEY=0000000000000000000000100000000000000000000000000000000000000000
+CT=5ED8B5A31ECEFAB16C9AA6986DA67BCE
+
+I=93
+KEY=0000000000000000000000080000000000000000000000000000000000000000
+CT=627815DCFC814ABC75900041B1DD7B59
+
+I=94
+KEY=0000000000000000000000040000000000000000000000000000000000000000
+CT=9EF3E82A50A59F166260494F7A7F2CC3
+
+I=95
+KEY=0000000000000000000000020000000000000000000000000000000000000000
+CT=878CD0D8D920888B5935D6C351128737
+
+I=96
+KEY=0000000000000000000000010000000000000000000000000000000000000000
+CT=E44429474D6FC3084EB2A6B8B46AF754
+
+I=97
+KEY=0000000000000000000000008000000000000000000000000000000000000000
+CT=EBAACF9641D54E1FB18D0A2BE4F19BE5
+
+I=98
+KEY=0000000000000000000000004000000000000000000000000000000000000000
+CT=13B3BF497CEE780E123C7E193DEA3A01
+
+I=99
+KEY=0000000000000000000000002000000000000000000000000000000000000000
+CT=6E8F381DE00A41161F0DF03B4155BFD4
+
+I=100
+KEY=0000000000000000000000001000000000000000000000000000000000000000
+CT=35E4F29BBA2BAE01144910783C3FEF49
+
+I=101
+KEY=0000000000000000000000000800000000000000000000000000000000000000
+CT=55B17BD66788CEAC366398A31F289FFB
+
+I=102
+KEY=0000000000000000000000000400000000000000000000000000000000000000
+CT=11341F56C0D6D1008D28741DAA7679CE
+
+I=103
+KEY=0000000000000000000000000200000000000000000000000000000000000000
+CT=4DF7253DF421D83358BDBE924745D98C
+
+I=104
+KEY=0000000000000000000000000100000000000000000000000000000000000000
+CT=BAE2EE651116D93EDC8E83B5F3347BE1
+
+I=105
+KEY=0000000000000000000000000080000000000000000000000000000000000000
+CT=F9721ABD06709157183AF3965A659D9D
+
+I=106
+KEY=0000000000000000000000000040000000000000000000000000000000000000
+CT=19A1C252A613FE2860A4AE6D75CE6FA3
+
+I=107
+KEY=0000000000000000000000000020000000000000000000000000000000000000
+CT=B5DDB2F5D9752C949FBDE3FFF5556C6E
+
+I=108
+KEY=0000000000000000000000000010000000000000000000000000000000000000
+CT=81B044FCFFC78ECCFCD171AAD0405C66
+
+I=109
+KEY=0000000000000000000000000008000000000000000000000000000000000000
+CT=C640566D3C06020EB2C42F1D62E56A9B
+
+I=110
+KEY=0000000000000000000000000004000000000000000000000000000000000000
+CT=EA6C4BCF425291679FDFFD26A424FBCC
+
+I=111
+KEY=0000000000000000000000000002000000000000000000000000000000000000
+CT=57F6901465D9440D9F15EE2CBA5A4090
+
+I=112
+KEY=0000000000000000000000000001000000000000000000000000000000000000
+CT=FBCFA74CADC7406260F63D96C8AAB6B1
+
+I=113
+KEY=0000000000000000000000000000800000000000000000000000000000000000
+CT=DFF4F096CEA211D4BBDACA033D0EC7D1
+
+I=114
+KEY=0000000000000000000000000000400000000000000000000000000000000000
+CT=1EE5190D551F0F42F675227A381296A9
+
+I=115
+KEY=0000000000000000000000000000200000000000000000000000000000000000
+CT=F98E1905012E580F097623C10B93054F
+
+I=116
+KEY=0000000000000000000000000000100000000000000000000000000000000000
+CT=E7D43743D21DD3C9F168C86856558B9A
+
+I=117
+KEY=0000000000000000000000000000080000000000000000000000000000000000
+CT=632A9DDA730DAB67593C5D08D8AC1059
+
+I=118
+KEY=0000000000000000000000000000040000000000000000000000000000000000
+CT=E084317000715B9057BC9DE9F3AB6124
+
+I=119
+KEY=0000000000000000000000000000020000000000000000000000000000000000
+CT=61F9EF33A0BB4E666C2ED99101919FAB
+
+I=120
+KEY=0000000000000000000000000000010000000000000000000000000000000000
+CT=6DC1D68A11834657D46703C22578D59A
+
+I=121
+KEY=0000000000000000000000000000008000000000000000000000000000000000
+CT=53AC1548863D3D16F1D4DC7242E05F2C
+
+I=122
+KEY=0000000000000000000000000000004000000000000000000000000000000000
+CT=E82CD587A408306AD78CEAE0916B9F8C
+
+I=123
+KEY=0000000000000000000000000000002000000000000000000000000000000000
+CT=0FD2D40EA6AD17A3A767F0A8600D6295
+
+I=124
+KEY=0000000000000000000000000000001000000000000000000000000000000000
+CT=AD84CC8255ADB39DFCA23F92761AE7E9
+
+I=125
+KEY=0000000000000000000000000000000800000000000000000000000000000000
+CT=F4F20CF7D51BEE7DA024A2B11A7ECA0B
+
+I=126
+KEY=0000000000000000000000000000000400000000000000000000000000000000
+CT=5057691B85D9CE93A193214DB0A016B6
+
+I=127
+KEY=0000000000000000000000000000000200000000000000000000000000000000
+CT=0F58C960876390BDEF4BB6BE95CAA1EE
+
+I=128
+KEY=0000000000000000000000000000000100000000000000000000000000000000
+CT=9A3E66EEBC21BC0BD9430B341EF465FA
+
+I=129
+KEY=0000000000000000000000000000000080000000000000000000000000000000
+CT=20415035F34B8BCBCB28ABF07F78F0D4
+
+I=130
+KEY=0000000000000000000000000000000040000000000000000000000000000000
+CT=AC89FC7BA10479EBF10DE65BCEF89B3C
+
+I=131
+KEY=0000000000000000000000000000000020000000000000000000000000000000
+CT=068FA75A30BE443171AF3F6FEB1A20D2
+
+I=132
+KEY=0000000000000000000000000000000010000000000000000000000000000000
+CT=50E02F213246C525A8C27700CA34B502
+
+I=133
+KEY=0000000000000000000000000000000008000000000000000000000000000000
+CT=227DA47D5A0906DB3AB042BB0A695FB6
+
+I=134
+KEY=0000000000000000000000000000000004000000000000000000000000000000
+CT=8663AC30ED12514F1DE46777F4514BFC
+
+I=135
+KEY=0000000000000000000000000000000002000000000000000000000000000000
+CT=A987D4BC12E1DE9F4B6DF43567C34A8B
+
+I=136
+KEY=0000000000000000000000000000000001000000000000000000000000000000
+CT=6D5A0370F599ACA605F63B04E5143D0C
+
+I=137
+KEY=0000000000000000000000000000000000800000000000000000000000000000
+CT=9809266E378B07B7AFDB3BAA97B7E442
+
+I=138
+KEY=0000000000000000000000000000000000400000000000000000000000000000
+CT=8F753252B30CCCACE12D9A301F4D5090
+
+I=139
+KEY=0000000000000000000000000000000000200000000000000000000000000000
+CT=032465F6C0CE34D41962F561692A1AFF
+
+I=140
+KEY=0000000000000000000000000000000000100000000000000000000000000000
+CT=C50E9AD5BEB8F3B00821DD47FF8AC093
+
+I=141
+KEY=0000000000000000000000000000000000080000000000000000000000000000
+CT=9C6FEA3D46268D54A6829B2AD25BB276
+
+I=142
+KEY=0000000000000000000000000000000000040000000000000000000000000000
+CT=0FD8575E87706F561343D7B3A41E044A
+
+I=143
+KEY=0000000000000000000000000000000000020000000000000000000000000000
+CT=BEE9BEB3739540D88CBCE77925F0A114
+
+I=144
+KEY=0000000000000000000000000000000000010000000000000000000000000000
+CT=D24EAEE7FFFBAC3D6F26C2DCE0DCDE28
+
+I=145
+KEY=0000000000000000000000000000000000008000000000000000000000000000
+CT=47771A90398FF0F7FA821C2F8F5E1398
+
+I=146
+KEY=0000000000000000000000000000000000004000000000000000000000000000
+CT=4639741B6F84B135AD118C8249B64ED0
+
+I=147
+KEY=0000000000000000000000000000000000002000000000000000000000000000
+CT=8EE5505EC85567697A3306F250A27720
+
+I=148
+KEY=0000000000000000000000000000000000001000000000000000000000000000
+CT=7C8A19AC1AEFBC5E0119D91A5F05D4C2
+
+I=149
+KEY=0000000000000000000000000000000000000800000000000000000000000000
+CT=5141B9B672E54773B672E3A6C424887B
+
+I=150
+KEY=0000000000000000000000000000000000000400000000000000000000000000
+CT=B5A2D3CD206653C6402F34FB0AE3613D
+
+I=151
+KEY=0000000000000000000000000000000000000200000000000000000000000000
+CT=0F5BD9408738231D114B0A82753279A3
+
+I=152
+KEY=0000000000000000000000000000000000000100000000000000000000000000
+CT=FEF033FF4268EA487FC74C5E43A45338
+
+I=153
+KEY=0000000000000000000000000000000000000080000000000000000000000000
+CT=A3EDC09DCD529B113910D904AD855581
+
+I=154
+KEY=0000000000000000000000000000000000000040000000000000000000000000
+CT=AB8FBB6F27A0AC7C55B59FDD36B72F1C
+
+I=155
+KEY=0000000000000000000000000000000000000020000000000000000000000000
+CT=EEA44D5ED4D769CC930CD83D8999EC46
+
+I=156
+KEY=0000000000000000000000000000000000000010000000000000000000000000
+CT=6972276803AE9AA7C6F431AB10979C34
+
+I=157
+KEY=0000000000000000000000000000000000000008000000000000000000000000
+CT=86DEAA9F39244101818178474D7DBDE9
+
+I=158
+KEY=0000000000000000000000000000000000000004000000000000000000000000
+CT=88C6B466EA361D662D8D08CBF181F4FE
+
+I=159
+KEY=0000000000000000000000000000000000000002000000000000000000000000
+CT=91AB2C6B7C63FF59F7CBEEBF91B20B95
+
+I=160
+KEY=0000000000000000000000000000000000000001000000000000000000000000
+CT=2DFE6C146AD5B3D8C3C1718F13B48E01
+
+I=161
+KEY=0000000000000000000000000000000000000000800000000000000000000000
+CT=C7CFF1623451711391A302EEC3584AAA
+
+I=162
+KEY=0000000000000000000000000000000000000000400000000000000000000000
+CT=089FE845CC05011686C66019D18BE050
+
+I=163
+KEY=0000000000000000000000000000000000000000200000000000000000000000
+CT=08C8410B9B427211A67124B0DCCEAD48
+
+I=164
+KEY=0000000000000000000000000000000000000000100000000000000000000000
+CT=8D91592F5566085254784606334D7629
+
+I=165
+KEY=0000000000000000000000000000000000000000080000000000000000000000
+CT=3298FEAAF2E1201D6299FF8846639C97
+
+I=166
+KEY=0000000000000000000000000000000000000000040000000000000000000000
+CT=C497CB9F0BDFE0EFC8C2F3F90760AA72
+
+I=167
+KEY=0000000000000000000000000000000000000000020000000000000000000000
+CT=2788AFD046E0309CBE4424690DA2AB89
+
+I=168
+KEY=0000000000000000000000000000000000000000010000000000000000000000
+CT=E9891707F25EF29FEE372890D4258982
+
+I=169
+KEY=0000000000000000000000000000000000000000008000000000000000000000
+CT=DB041D94A23D45D4D4DCED5A030CAF61
+
+I=170
+KEY=0000000000000000000000000000000000000000004000000000000000000000
+CT=FFAFDBF0ECB18DF9EA02C27077448E6D
+
+I=171
+KEY=0000000000000000000000000000000000000000002000000000000000000000
+CT=2DAAA42A7D0A1D3B0E4761D99CF2150A
+
+I=172
+KEY=0000000000000000000000000000000000000000001000000000000000000000
+CT=3B7A54CB7CF30ABE263DD6ED5BFE8D63
+
+I=173
+KEY=0000000000000000000000000000000000000000000800000000000000000000
+CT=EEFA090174C590C448A55D43648F534A
+
+I=174
+KEY=0000000000000000000000000000000000000000000400000000000000000000
+CT=9E15798731ED42F43EA2740A691DA872
+
+I=175
+KEY=0000000000000000000000000000000000000000000200000000000000000000
+CT=31FBD661540A5DEAAD1017CFD3909EC8
+
+I=176
+KEY=0000000000000000000000000000000000000000000100000000000000000000
+CT=CDA9AE05F224140E28CB951721B44D6A
+
+I=177
+KEY=0000000000000000000000000000000000000000000080000000000000000000
+CT=0C5BC512C60A1EAC3434EFB1A8FBB182
+
+I=178
+KEY=0000000000000000000000000000000000000000000040000000000000000000
+CT=AA863610DEEEEB62D045E87EA30B59B5
+
+I=179
+KEY=0000000000000000000000000000000000000000000020000000000000000000
+CT=6AC2448DE568D279C7EEBE1DF403920C
+
+I=180
+KEY=0000000000000000000000000000000000000000000010000000000000000000
+CT=E2011E3D292B26888AE801215FD0CB40
+
+I=181
+KEY=0000000000000000000000000000000000000000000008000000000000000000
+CT=E06F3E15EE3A61672D1C99BADE5B9DBE
+
+I=182
+KEY=0000000000000000000000000000000000000000000004000000000000000000
+CT=BB7027F0548CF6712CEB4C7A4B28E178
+
+I=183
+KEY=0000000000000000000000000000000000000000000002000000000000000000
+CT=061EC21FB70FADBDF87C3BD2AE23825B
+
+I=184
+KEY=0000000000000000000000000000000000000000000001000000000000000000
+CT=4C21F26FE94ABBAC381352375314C3EB
+
+I=185
+KEY=0000000000000000000000000000000000000000000000800000000000000000
+CT=F7CEE6DD99909C2B569EEDA61ED8942E
+
+I=186
+KEY=0000000000000000000000000000000000000000000000400000000000000000
+CT=CE98C4A876C65E4CCB261EBB1D9DF7F5
+
+I=187
+KEY=0000000000000000000000000000000000000000000000200000000000000000
+CT=A5491881CF833C3604ABC08044F402AC
+
+I=188
+KEY=0000000000000000000000000000000000000000000000100000000000000000
+CT=A1BA16E64CCCB3087D57A768507B0BFC
+
+I=189
+KEY=0000000000000000000000000000000000000000000000080000000000000000
+CT=D55951E202D2949EBD3BE43120C738BF
+
+I=190
+KEY=0000000000000000000000000000000000000000000000040000000000000000
+CT=EBB8E43069E69F450EFEC65DCD52B7FD
+
+I=191
+KEY=0000000000000000000000000000000000000000000000020000000000000000
+CT=2B292135663B4AA5ABFE9423D57E7EE9
+
+I=192
+KEY=0000000000000000000000000000000000000000000000010000000000000000
+CT=E91BF974B3BE3AD966249D8655292A85
+
+I=193
+KEY=0000000000000000000000000000000000000000000000008000000000000000
+CT=384365998EAA9562236CC58F6ADF9610
+
+I=194
+KEY=0000000000000000000000000000000000000000000000004000000000000000
+CT=C2E997012AA3D4D8D359C9A947CBE69F
+
+I=195
+KEY=0000000000000000000000000000000000000000000000002000000000000000
+CT=F49421204148BA213BE87E2D5C22B0BF
+
+I=196
+KEY=0000000000000000000000000000000000000000000000001000000000000000
+CT=82ED0ED9953AA92E4DF30929CA65C00F
+
+I=197
+KEY=0000000000000000000000000000000000000000000000000800000000000000
+CT=291EB1D11653C8479437C74A977F5106
+
+I=198
+KEY=0000000000000000000000000000000000000000000000000400000000000000
+CT=BCB997B1939B8983ABD550D6025683E3
+
+I=199
+KEY=0000000000000000000000000000000000000000000000000200000000000000
+CT=1FBA2592C6F489775CAADA71F9B983E9
+
+I=200
+KEY=0000000000000000000000000000000000000000000000000100000000000000
+CT=969F66F217AF1A3DB9E41C1B29039824
+
+I=201
+KEY=0000000000000000000000000000000000000000000000000080000000000000
+CT=A54BB7D6B17E423AC0A7744C19073CB8
+
+I=202
+KEY=0000000000000000000000000000000000000000000000000040000000000000
+CT=B0AC6E6578D1021F47DCF9748A32EAD5
+
+I=203
+KEY=0000000000000000000000000000000000000000000000000020000000000000
+CT=B87B361C3B7B194C77A4358D4669153E
+
+I=204
+KEY=0000000000000000000000000000000000000000000000000010000000000000
+CT=46A133847F96EAA8282A799DC8899D58
+
+I=205
+KEY=0000000000000000000000000000000000000000000000000008000000000000
+CT=2265EC3A9F2D5C9547A091CC8CFB18EA
+
+I=206
+KEY=0000000000000000000000000000000000000000000000000004000000000000
+CT=54CBF3A6FC4FE56D426117AA1FFD1DDE
+
+I=207
+KEY=0000000000000000000000000000000000000000000000000002000000000000
+CT=5312877CCEAB6CFB0905394A370A8003
+
+I=208
+KEY=0000000000000000000000000000000000000000000000000001000000000000
+CT=7190BD6EC613FE38B84ECFE28F702FE4
+
+I=209
+KEY=0000000000000000000000000000000000000000000000000000800000000000
+CT=D1FA5B9CA89A43B04C05F0EF29EF68CD
+
+I=210
+KEY=0000000000000000000000000000000000000000000000000000400000000000
+CT=808285751548ED934FD1056D2D9AE8BA
+
+I=211
+KEY=0000000000000000000000000000000000000000000000000000200000000000
+CT=2758DEF3E7B95A9AE89777BE64D5A6CF
+
+I=212
+KEY=0000000000000000000000000000000000000000000000000000100000000000
+CT=07D81F87DB3E0ACC82B01E08FB22F3C1
+
+I=213
+KEY=0000000000000000000000000000000000000000000000000000080000000000
+CT=8DA250E5553D650711A75EE1CB4FD1C7
+
+I=214
+KEY=0000000000000000000000000000000000000000000000000000040000000000
+CT=A93D946BD0E87F32719DF5F158CEE669
+
+I=215
+KEY=0000000000000000000000000000000000000000000000000000020000000000
+CT=03945236EC2A4D4EAF30B8ABEB54330D
+
+I=216
+KEY=0000000000000000000000000000000000000000000000000000010000000000
+CT=11CC35301F24B79DDE31AEA2D1354F88
+
+I=217
+KEY=0000000000000000000000000000000000000000000000000000008000000000
+CT=E73715B3E8D9A290F44AE6FFBF247E5D
+
+I=218
+KEY=0000000000000000000000000000000000000000000000000000004000000000
+CT=7345E07732B71CB158BBF64CCA5C5B96
+
+I=219
+KEY=0000000000000000000000000000000000000000000000000000002000000000
+CT=6E128F296D24705A1924FD9B70C4ED04
+
+I=220
+KEY=0000000000000000000000000000000000000000000000000000001000000000
+CT=95A789776F036783FBD330947083F54F
+
+I=221
+KEY=0000000000000000000000000000000000000000000000000000000800000000
+CT=360DEC2533EA4AA2E3E54FD3DE2906EB
+
+I=222
+KEY=0000000000000000000000000000000000000000000000000000000400000000
+CT=E68EFD7FECF4D601EA22727BD764965B
+
+I=223
+KEY=0000000000000000000000000000000000000000000000000000000200000000
+CT=9065C64A8BFF44AC33EDBB611CF83D7B
+
+I=224
+KEY=0000000000000000000000000000000000000000000000000000000100000000
+CT=8F33C8DF2A7A51CE8090E8F123BC3723
+
+I=225
+KEY=0000000000000000000000000000000000000000000000000000000080000000
+CT=807F391FFBA8291BA625623210F99018
+
+I=226
+KEY=0000000000000000000000000000000000000000000000000000000040000000
+CT=5E8B3F3A701522CE5CAA761C929D6292
+
+I=227
+KEY=0000000000000000000000000000000000000000000000000000000020000000
+CT=3BA404DC38735A78289E3809E8364835
+
+I=228
+KEY=0000000000000000000000000000000000000000000000000000000010000000
+CT=D23BEDBAD229F8305DC425B6B759DCC9
+
+I=229
+KEY=0000000000000000000000000000000000000000000000000000000008000000
+CT=44880F21CF5913040AE376AEE2A10AD8
+
+I=230
+KEY=0000000000000000000000000000000000000000000000000000000004000000
+CT=9BC98E29D057C0E828C3B5CCE69256C1
+
+I=231
+KEY=0000000000000000000000000000000000000000000000000000000002000000
+CT=B293CC7A975DA141A68279368057CC41
+
+I=232
+KEY=0000000000000000000000000000000000000000000000000000000001000000
+CT=8D60FB87ACD91385B313BE5F1D7BD30F
+
+I=233
+KEY=0000000000000000000000000000000000000000000000000000000000800000
+CT=2C8E56132D70291B303C48FDF75543CD
+
+I=234
+KEY=0000000000000000000000000000000000000000000000000000000000400000
+CT=D1F80035B826791F6CE4E59B7DB1BB0D
+
+I=235
+KEY=0000000000000000000000000000000000000000000000000000000000200000
+CT=42CE6224FC36469339A133DD08173BD4
+
+I=236
+KEY=0000000000000000000000000000000000000000000000000000000000100000
+CT=61817155EA41BCBA2AF7F06AE7CBF585
+
+I=237
+KEY=0000000000000000000000000000000000000000000000000000000000080000
+CT=D1923A9866068D2EF5FB77D57C3315B6
+
+I=238
+KEY=0000000000000000000000000000000000000000000000000000000000040000
+CT=B37CBDB5D719F49691CA968EF2E84140
+
+I=239
+KEY=0000000000000000000000000000000000000000000000000000000000020000
+CT=EC974E653A055D7F8F22171030F68E1D
+
+I=240
+KEY=0000000000000000000000000000000000000000000000000000000000010000
+CT=DDE5D3B9AAD9C32213BB3675A822499C
+
+I=241
+KEY=0000000000000000000000000000000000000000000000000000000000008000
+CT=D3B6E9216EA1AE57EB1C628A3C38AB78
+
+I=242
+KEY=0000000000000000000000000000000000000000000000000000000000004000
+CT=82C99ECC69472B7E96324B042AE8B87A
+
+I=243
+KEY=0000000000000000000000000000000000000000000000000000000000002000
+CT=97144DC5338C43600F84439C0AA0D147
+
+I=244
+KEY=0000000000000000000000000000000000000000000000000000000000001000
+CT=400AC4A0BBADA1DB2121EB144C7E5209
+
+I=245
+KEY=0000000000000000000000000000000000000000000000000000000000000800
+CT=EFD9D550EB419ED278F4885A490AB54C
+
+I=246
+KEY=0000000000000000000000000000000000000000000000000000000000000400
+CT=2AB7816E149B7C0404C88A8857793670
+
+I=247
+KEY=0000000000000000000000000000000000000000000000000000000000000200
+CT=5B591DFF9E8DEE15BAD24C025DBCA481
+
+I=248
+KEY=0000000000000000000000000000000000000000000000000000000000000100
+CT=0C06633E30721C3749F49AD8CBF2B754
+
+I=249
+KEY=0000000000000000000000000000000000000000000000000000000000000080
+CT=96D6D31A41B5123B2035FD91A921D4CA
+
+I=250
+KEY=0000000000000000000000000000000000000000000000000000000000000040
+CT=E7F6C34D86668BC2805CA7793C5E86AD
+
+I=251
+KEY=0000000000000000000000000000000000000000000000000000000000000020
+CT=F46DFF5FF500D6879C4D3E45CF0CF0F3
+
+I=252
+KEY=0000000000000000000000000000000000000000000000000000000000000010
+CT=60D842D9C61DA7495C116197B7CECBBE
+
+I=253
+KEY=0000000000000000000000000000000000000000000000000000000000000008
+CT=D45B24EDB673353EBDF248B8FA06B67A
+
+I=254
+KEY=0000000000000000000000000000000000000000000000000000000000000004
+CT=119EAEBCC165D0BD02C0D35DC82EF992
+
+I=255
+KEY=0000000000000000000000000000000000000000000000000000000000000002
+CT=E673143680414ADA301D0ED34626B9FE
+
+I=256
+KEY=0000000000000000000000000000000000000000000000000000000000000001
+CT=6B6CFE160A6263631B292F879EEFF926
+
+==========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/ecb_vt.txt b/krb5-1-6/src/lib/crypto/aes/test/ecb_vt.txt
new file mode 100644
index 000000000..6dea60fc4
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/test/ecb_vt.txt
@@ -0,0 +1,1566 @@
+
+=========================
+
+FILENAME:  "ecb_vt.txt"
+
+Electronic Codebook (ECB) Mode
+Variable Text Known Answer Tests
+
+Algorithm Name: Rijndael
+Principal Submitter: Joan Daemen
+
+==========
+
+KEYSIZE=128
+
+KEY=00000000000000000000000000000000
+
+I=1
+PT=80000000000000000000000000000000
+CT=3AD78E726C1EC02B7EBFE92B23D9EC34
+
+I=2
+PT=40000000000000000000000000000000
+CT=45BC707D29E8204D88DFBA2F0B0CAD9B
+
+I=3
+PT=20000000000000000000000000000000
+CT=161556838018F52805CDBD6202002E3F
+
+I=4
+PT=10000000000000000000000000000000
+CT=F5569B3AB6A6D11EFDE1BF0A64C6854A
+
+I=5
+PT=08000000000000000000000000000000
+CT=64E82B50E501FBD7DD4116921159B83E
+
+I=6
+PT=04000000000000000000000000000000
+CT=BAAC12FB613A7DE11450375C74034041
+
+I=7
+PT=02000000000000000000000000000000
+CT=BCF176A7EAAD8085EBACEA362462A281
+
+I=8
+PT=01000000000000000000000000000000
+CT=47711816E91D6FF059BBBF2BF58E0FD3
+
+I=9
+PT=00800000000000000000000000000000
+CT=B970DFBE40698AF1638FE38BD3DF3B2F
+
+I=10
+PT=00400000000000000000000000000000
+CT=F95B59A44F391E14CF20B74BDC32FCFF
+
+I=11
+PT=00200000000000000000000000000000
+CT=720F74AE04A2A435B9A7256E49378F5B
+
+I=12
+PT=00100000000000000000000000000000
+CT=2A0445F61D36BFA7E277070730CF76DA
+
+I=13
+PT=00080000000000000000000000000000
+CT=8D0536B997AEFEC1D94011BAB6699A03
+
+I=14
+PT=00040000000000000000000000000000
+CT=674F002E19F6ED47EFF319E51FAD4498
+
+I=15
+PT=00020000000000000000000000000000
+CT=292C02C5CB9163C80AC0F6CF1DD8E92D
+
+I=16
+PT=00010000000000000000000000000000
+CT=FA321CF18EF5FE727DD82A5C1E945141
+
+I=17
+PT=00008000000000000000000000000000
+CT=A5A7AFE1034C39CCCEBE3C584BC0BE05
+
+I=18
+PT=00004000000000000000000000000000
+CT=4FF5A52E697E77D081205DBDB21CEA39
+
+I=19
+PT=00002000000000000000000000000000
+CT=209E88DC94C9003000CE0769AF7B7166
+
+I=20
+PT=00001000000000000000000000000000
+CT=5DEE41AF864CB4B650E5F51551824D38
+
+I=21
+PT=00000800000000000000000000000000
+CT=A79A63FA7E4503AE6D6E09F5F9053030
+
+I=22
+PT=00000400000000000000000000000000
+CT=A48316749FAE7FAC7002031A6AFD8BA7
+
+I=23
+PT=00000200000000000000000000000000
+CT=D6EEE8A7357A0E1D64262CA9C337AC42
+
+I=24
+PT=00000100000000000000000000000000
+CT=B013CA8A62A858053E9FB667ED39829E
+
+I=25
+PT=00000080000000000000000000000000
+CT=DF6EA9E4538A45A52D5C1A43C88F4B55
+
+I=26
+PT=00000040000000000000000000000000
+CT=7D03BA451371591D3FD5547D9165C73B
+
+I=27
+PT=00000020000000000000000000000000
+CT=0E0426281A6277E186499D365D5F49FF
+
+I=28
+PT=00000010000000000000000000000000
+CT=DBC02169DD2059E6CC4C57C1FEDF5AB4
+
+I=29
+PT=00000008000000000000000000000000
+CT=826590E05D167DA6F00DCC75E22788EB
+
+I=30
+PT=00000004000000000000000000000000
+CT=34A73F21A04421D9786335FAAB49423A
+
+I=31
+PT=00000002000000000000000000000000
+CT=ED347D0E0128EE1A7392A1D36AB78AA9
+
+I=32
+PT=00000001000000000000000000000000
+CT=EE944B2FE6E9FC888042608DA9615F75
+
+I=33
+PT=00000000800000000000000000000000
+CT=9E7C85A909EF7218BA7947CFB4718F46
+
+I=34
+PT=00000000400000000000000000000000
+CT=811AE07A0B2B1F816587FA73699AE77D
+
+I=35
+PT=00000000200000000000000000000000
+CT=68466FBF43C2FE13D4B18F7EC5EA745F
+
+I=36
+PT=00000000100000000000000000000000
+CT=D20B015C7191B219780956E6101F9354
+
+I=37
+PT=00000000080000000000000000000000
+CT=5939D5C1BBF54EE1B3E326D757BDDE25
+
+I=38
+PT=00000000040000000000000000000000
+CT=B1FDAFE9A0240E8FFEA19CE94B5105D3
+
+I=39
+PT=00000000020000000000000000000000
+CT=D62962ECE02CDD68C06BDFEFB2F9495B
+
+I=40
+PT=00000000010000000000000000000000
+CT=B3BB2DE6F3C26587BA8BAC4F7AD9499A
+
+I=41
+PT=00000000008000000000000000000000
+CT=E0B1072D6D9FF703D6FBEF77852B0A6B
+
+I=42
+PT=00000000004000000000000000000000
+CT=D8DD51C907F478DE0228E83E61FD1758
+
+I=43
+PT=00000000002000000000000000000000
+CT=A42DFFE6E7C1671C06A25236FDD10017
+
+I=44
+PT=00000000001000000000000000000000
+CT=25ACF141550BFAB9EF451B6C6A5B2163
+
+I=45
+PT=00000000000800000000000000000000
+CT=4DA7FCA3949B16E821DBC84F19581018
+
+I=46
+PT=00000000000400000000000000000000
+CT=7D49B6347CBCC8919C7FA96A37A7A215
+
+I=47
+PT=00000000000200000000000000000000
+CT=900024B29A08C6721B95BA3B753DDB4D
+
+I=48
+PT=00000000000100000000000000000000
+CT=6D2182FB283B6934D90BA7848CAB5E66
+
+I=49
+PT=00000000000080000000000000000000
+CT=F73EF01B448D23A4D90DE8B2F9666E7A
+
+I=50
+PT=00000000000040000000000000000000
+CT=4AD9CDA2418643E9A3D926AF5E6B0412
+
+I=51
+PT=00000000000020000000000000000000
+CT=7CAEC8E7E5953997D545B033201C8C5B
+
+I=52
+PT=00000000000010000000000000000000
+CT=3C43CA1F6B6864503E27B48D88230CF5
+
+I=53
+PT=00000000000008000000000000000000
+CT=44F779B93108FE9FEEC880D79BA74488
+
+I=54
+PT=00000000000004000000000000000000
+CT=9E50E8D9CFD3A682A78E527C9072A1CF
+
+I=55
+PT=00000000000002000000000000000000
+CT=68D000CBC838BBE3C505D6F814C01F28
+
+I=56
+PT=00000000000001000000000000000000
+CT=2CB2A9FEC1ACD1D9B0FA05205E304F57
+
+I=57
+PT=00000000000000800000000000000000
+CT=01EB2806606E46444520A5CC6180CD4B
+
+I=58
+PT=00000000000000400000000000000000
+CT=DAA9B25168CC702326F217F1A0C0B162
+
+I=59
+PT=00000000000000200000000000000000
+CT=3E07E648975D9578D03555B1755807ED
+
+I=60
+PT=00000000000000100000000000000000
+CT=0B45F52E802C8B8DE09579425B80B711
+
+I=61
+PT=00000000000000080000000000000000
+CT=659595DA0B68F6DF0DD6CA77202986E1
+
+I=62
+PT=00000000000000040000000000000000
+CT=05FF42873893536E58C8FA98A45C73C4
+
+I=63
+PT=00000000000000020000000000000000
+CT=B5B03421DE8BBFFC4EADEC767339A9BD
+
+I=64
+PT=00000000000000010000000000000000
+CT=788BCD111ECF73D4E78D2E21BEF55460
+
+I=65
+PT=00000000000000008000000000000000
+CT=909CD9EC6790359F982DC6F2393D5315
+
+I=66
+PT=00000000000000004000000000000000
+CT=332950F361535FF24EFAC8C76293F12C
+
+I=67
+PT=00000000000000002000000000000000
+CT=A68CCD4E330FFDA9D576DA436DB53D75
+
+I=68
+PT=00000000000000001000000000000000
+CT=27C8A1CCFDB0B015D1ED5B3E77143791
+
+I=69
+PT=00000000000000000800000000000000
+CT=D76A4B95887A77DF610DD3E1D3B20325
+
+I=70
+PT=00000000000000000400000000000000
+CT=C068AB0DE71C66DAE83C361EF4B2D989
+
+I=71
+PT=00000000000000000200000000000000
+CT=C2120BCD49EDA9A288B3B4BE79AC8158
+
+I=72
+PT=00000000000000000100000000000000
+CT=0C546F62BF2773CD0F564FCECA7BA688
+
+I=73
+PT=00000000000000000080000000000000
+CT=18F3462BEDE4920213CCB66DAB1640AA
+
+I=74
+PT=00000000000000000040000000000000
+CT=FE42F245EDD0E24B216AEBD8B392D690
+
+I=75
+PT=00000000000000000020000000000000
+CT=3D3EEBC8D3D1558A194C2D00C337FF2B
+
+I=76
+PT=00000000000000000010000000000000
+CT=29AAEDF043E785DB42836F79BE6CBA28
+
+I=77
+PT=00000000000000000008000000000000
+CT=215F90C6744E2944358E78619159A611
+
+I=78
+PT=00000000000000000004000000000000
+CT=8606B1AA9E1D548E5442B06551E2C6DC
+
+I=79
+PT=00000000000000000002000000000000
+CT=987BB4B8740EC0EDE7FEA97DF033B5B1
+
+I=80
+PT=00000000000000000001000000000000
+CT=C0A3500DA5B0AE07D2F450930BEEDF1B
+
+I=81
+PT=00000000000000000000800000000000
+CT=525FDF8312FE8F32C781481A8DAAAE37
+
+I=82
+PT=00000000000000000000400000000000
+CT=BFD2C56AE5FB9C9DE33A6944572A6487
+
+I=83
+PT=00000000000000000000200000000000
+CT=7975A57A425CDF5AA1FA929101F650B0
+
+I=84
+PT=00000000000000000000100000000000
+CT=BF174BC49609A8709B2CD8366DAA79FE
+
+I=85
+PT=00000000000000000000080000000000
+CT=06C50C43222F56C874B1704E9F44BF7D
+
+I=86
+PT=00000000000000000000040000000000
+CT=0CEC48CD34043EA29CA3B8ED5278721E
+
+I=87
+PT=00000000000000000000020000000000
+CT=9548EA34A1560197B304D0ACB8A1698D
+
+I=88
+PT=00000000000000000000010000000000
+CT=22F9E9B1BD73B6B5B7D3062C986272F3
+
+I=89
+PT=00000000000000000000008000000000
+CT=FEE8E934BD0873295059002230E298D4
+
+I=90
+PT=00000000000000000000004000000000
+CT=1B08E2E3EB820D139CB4ABBDBE81D00D
+
+I=91
+PT=00000000000000000000002000000000
+CT=0021177681E4D90CEAF69DCED0145125
+
+I=92
+PT=00000000000000000000001000000000
+CT=4A8E314452CA8A8A3619FC54BC423643
+
+I=93
+PT=00000000000000000000000800000000
+CT=65047474F7222C94C6965425FF1BFD0A
+
+I=94
+PT=00000000000000000000000400000000
+CT=E123F551A9C4A8489622B16F961A9AA4
+
+I=95
+PT=00000000000000000000000200000000
+CT=EF05530948B80915028BB2B6FE429380
+
+I=96
+PT=00000000000000000000000100000000
+CT=72535B7FE0F0F777CEDCD55CD77E2DDF
+
+I=97
+PT=00000000000000000000000080000000
+CT=3423D8EFC31FA2F4C365C77D8F3B5C63
+
+I=98
+PT=00000000000000000000000040000000
+CT=DE0E51C264663F3C5DBC59580A98D8E4
+
+I=99
+PT=00000000000000000000000020000000
+CT=B2D9391166680947AB09264156719679
+
+I=100
+PT=00000000000000000000000010000000
+CT=10DB79F23B06D263835C424AF749ADB7
+
+I=101
+PT=00000000000000000000000008000000
+CT=DDF72D27E6B01EC107EA3E005B59563B
+
+I=102
+PT=00000000000000000000000004000000
+CT=8266B57485A5954A4236751DE07F6694
+
+I=103
+PT=00000000000000000000000002000000
+CT=669A501E1F1ADE6E5523DE01D6DBC987
+
+I=104
+PT=00000000000000000000000001000000
+CT=C20C48F2989725D461D1DB589DC0896E
+
+I=105
+PT=00000000000000000000000000800000
+CT=DE35158E7810ED1191825D2AA98FA97D
+
+I=106
+PT=00000000000000000000000000400000
+CT=4FE294F2C0F34D0671B693A237EBDDC8
+
+I=107
+PT=00000000000000000000000000200000
+CT=087AE74B10CCBFDF6739FEB9559C01A4
+
+I=108
+PT=00000000000000000000000000100000
+CT=5DC278970B7DEF77A5536C77AB59C207
+
+I=109
+PT=00000000000000000000000000080000
+CT=7607F078C77085184EAA9B060C1FBFFF
+
+I=110
+PT=00000000000000000000000000040000
+CT=9DB841531BCBE7998DAD19993FB3CC00
+
+I=111
+PT=00000000000000000000000000020000
+CT=D6A089B654854A94560BAE13298835B8
+
+I=112
+PT=00000000000000000000000000010000
+CT=E1E223C4CF90CC5D195B370D65114622
+
+I=113
+PT=00000000000000000000000000008000
+CT=1CBED73C50D053BDAD372CEEE54836A1
+
+I=114
+PT=00000000000000000000000000004000
+CT=D309E69376D257ADF2BFDA152B26555F
+
+I=115
+PT=00000000000000000000000000002000
+CT=740F7649117F0DEE6EAA7789A9994C36
+
+I=116
+PT=00000000000000000000000000001000
+CT=76AE64417C297184D668C5FD908B3CE5
+
+I=117
+PT=00000000000000000000000000000800
+CT=6095FEA4AA8035591F1787A819C48787
+
+I=118
+PT=00000000000000000000000000000400
+CT=D1FF4E7ACD1C79967FEBAB0F7465D450
+
+I=119
+PT=00000000000000000000000000000200
+CT=5F5AD3C42B9489557BB63BF49ECF5F8A
+
+I=120
+PT=00000000000000000000000000000100
+CT=FB56CC09B680B1D07C5A52149E29F07C
+
+I=121
+PT=00000000000000000000000000000080
+CT=FF49B8DF4A97CBE03833E66197620DAD
+
+I=122
+PT=00000000000000000000000000000040
+CT=5E070ADE533D2E090ED0F5BE13BC0983
+
+I=123
+PT=00000000000000000000000000000020
+CT=3AB4FB1D2B7BA376590A2C241D1F508D
+
+I=124
+PT=00000000000000000000000000000010
+CT=58B2431BC0BEDE02550F40238969EC78
+
+I=125
+PT=00000000000000000000000000000008
+CT=0253786E126504F0DAB90C48A30321DE
+
+I=126
+PT=00000000000000000000000000000004
+CT=200211214E7394DA2089B6ACD093ABE0
+
+I=127
+PT=00000000000000000000000000000002
+CT=0388DACE60B6A392F328C2B971B2FE78
+
+I=128
+PT=00000000000000000000000000000001
+CT=58E2FCCEFA7E3061367F1D57A4E7455A
+
+==========
+
+KEYSIZE=192
+
+KEY=000000000000000000000000000000000000000000000000
+
+I=1
+PT=80000000000000000000000000000000
+CT=6CD02513E8D4DC986B4AFE087A60BD0C
+
+I=2
+PT=40000000000000000000000000000000
+CT=423D2772A0CA56DAABB48D2129062987
+
+I=3
+PT=20000000000000000000000000000000
+CT=1021F2A8DA70EB2219DC16804445FF98
+
+I=4
+PT=10000000000000000000000000000000
+CT=C636E35B402577F96974D8804295EBB8
+
+I=5
+PT=08000000000000000000000000000000
+CT=1566D2E57E8393C19E29F892EA28A9A7
+
+I=6
+PT=04000000000000000000000000000000
+CT=883C878FED70B36CC09D040F9619DD19
+
+I=7
+PT=02000000000000000000000000000000
+CT=06734593A974965790E715594FC34AA9
+
+I=8
+PT=01000000000000000000000000000000
+CT=F19B389948D9A45534E5BD36C984134A
+
+I=9
+PT=00800000000000000000000000000000
+CT=D8410DFC14FA6D175EC968EA8CAC514C
+
+I=10
+PT=00400000000000000000000000000000
+CT=7E6C6EBB4029A177CF7B2FDD9AC6BB7A
+
+I=11
+PT=00200000000000000000000000000000
+CT=4B51DD4850DC0A6C3A46D924003D2C27
+
+I=12
+PT=00100000000000000000000000000000
+CT=2E510A9D917B15BE32A192B12A668F23
+
+I=13
+PT=00080000000000000000000000000000
+CT=88F6F79962B0FB77FEA8E7C632D3108E
+
+I=14
+PT=00040000000000000000000000000000
+CT=A3A35AB1D88DAF07B52794A0F065383A
+
+I=15
+PT=00020000000000000000000000000000
+CT=DC6CC878433E2B3BB193049A4ECBFC53
+
+I=16
+PT=00010000000000000000000000000000
+CT=EFCD3763EB7B1A415938248A9A5B4FD5
+
+I=17
+PT=00008000000000000000000000000000
+CT=AB7E9FB9A66DBE5BB44854F07D9015EE
+
+I=18
+PT=00004000000000000000000000000000
+CT=8B8E9D3365F8F6743ECF7E33E99255A4
+
+I=19
+PT=00002000000000000000000000000000
+CT=54D37B4F176FF3D8F6AFC866066D8572
+
+I=20
+PT=00001000000000000000000000000000
+CT=E83310889480FBF3C00342E3126D0D02
+
+I=21
+PT=00000800000000000000000000000000
+CT=D321AB2511F92F098174AA2DE6E85DA2
+
+I=22
+PT=00000400000000000000000000000000
+CT=D8E3F40B1112D5149D58C481DFA9983F
+
+I=23
+PT=00000200000000000000000000000000
+CT=2454C4E0806639DDF19854D6C68054AD
+
+I=24
+PT=00000100000000000000000000000000
+CT=A5506D410F7CA32F3955DD79D9D09418
+
+I=25
+PT=00000080000000000000000000000000
+CT=7908EE40677699568A7DC1AA317C7E4E
+
+I=26
+PT=00000040000000000000000000000000
+CT=B4B7B29DD43B2F5CF765E25192273982
+
+I=27
+PT=00000020000000000000000000000000
+CT=92AFE9668159BEFFE2A86F8503260164
+
+I=28
+PT=00000010000000000000000000000000
+CT=5C36A232FBA6D187A84657AD4028B18F
+
+I=29
+PT=00000008000000000000000000000000
+CT=A2E994DFAB3A798DF8F54F6DA87E58E2
+
+I=30
+PT=00000004000000000000000000000000
+CT=6CDAB10A72ADF77D71D0765BAAE95631
+
+I=31
+PT=00000002000000000000000000000000
+CT=9FE3C801BCAAF7BB800F2E6BF3278E21
+
+I=32
+PT=00000001000000000000000000000000
+CT=B459D90D9A6C392E5493BC91CF5A0863
+
+I=33
+PT=00000000800000000000000000000000
+CT=0518A9FA5007F6787E0FB4E5AC27D758
+
+I=34
+PT=00000000400000000000000000000000
+CT=BED9795415D28599700ED7952384A963
+
+I=35
+PT=00000000200000000000000000000000
+CT=F0140421173D60251EF6CAB0229B1B50
+
+I=36
+PT=00000000100000000000000000000000
+CT=460EB4652B3F6779EA28CB11B37529ED
+
+I=37
+PT=00000000080000000000000000000000
+CT=C4283D351C960A6AC13CD19CCF03AE38
+
+I=38
+PT=00000000040000000000000000000000
+CT=6815A10047B2C834A798EBDCC6786C75
+
+I=39
+PT=00000000020000000000000000000000
+CT=99BA19F0CDD5990D0386B32CE56C9C4C
+
+I=40
+PT=00000000010000000000000000000000
+CT=DE76F62C61E07915162DA13E79679DEC
+
+I=41
+PT=00000000008000000000000000000000
+CT=DD0325D6854803D06D1D2277D5FB8D67
+
+I=42
+PT=00000000004000000000000000000000
+CT=580B71A41DE37D6FAC83CCB0B3BB1C97
+
+I=43
+PT=00000000002000000000000000000000
+CT=E9B1AB470A1B02EF0FF5E6754A092C96
+
+I=44
+PT=00000000001000000000000000000000
+CT=8590620F5AF5993B7410282F4126BC1F
+
+I=45
+PT=00000000000800000000000000000000
+CT=8D4914D2F1B22B2E268E66E532D29D7C
+
+I=46
+PT=00000000000400000000000000000000
+CT=FD826CE48E62C5E30867044B86BA4B56
+
+I=47
+PT=00000000000200000000000000000000
+CT=100E7B831C9F35FA1271F5F1316C6FCF
+
+I=48
+PT=00000000000100000000000000000000
+CT=0A2DD0C17F68B996AA96C007003D0B31
+
+I=49
+PT=00000000000080000000000000000000
+CT=C95F68C57E06B0A2E1F623C83C5D80BF
+
+I=50
+PT=00000000000040000000000000000000
+CT=571CAFC92C7C8A5EC54C0741E186905C
+
+I=51
+PT=00000000000020000000000000000000
+CT=22514353E95312C112255E1EED0B2DF6
+
+I=52
+PT=00000000000010000000000000000000
+CT=791A8BF462BD17580BD9152C6D11C6C5
+
+I=53
+PT=00000000000008000000000000000000
+CT=5882A0178D548F84A165DB809C60DC28
+
+I=54
+PT=00000000000004000000000000000000
+CT=3CE4A90EED4458CA6039E42DDADB71C3
+
+I=55
+PT=00000000000002000000000000000000
+CT=D3CBAB261207A16BE2751E77044FD7C9
+
+I=56
+PT=00000000000001000000000000000000
+CT=24E32B698A7B32217093628B01F424AB
+
+I=57
+PT=00000000000000800000000000000000
+CT=9F6AFC0AF27CF565110C77E3C24F4F5B
+
+I=58
+PT=00000000000000400000000000000000
+CT=E088AA5CDA20EF267BB039B00C72C45B
+
+I=59
+PT=00000000000000200000000000000000
+CT=5CF1018B7E0BA1775601C2E279900360
+
+I=60
+PT=00000000000000100000000000000000
+CT=3B1A7388B89FB9416AD8753CF5AF35D2
+
+I=61
+PT=00000000000000080000000000000000
+CT=137FA4ED00AFCD9F5D8BC0D14BD5837A
+
+I=62
+PT=00000000000000040000000000000000
+CT=806F5C9B663559BB56F234881E4A3E60
+
+I=63
+PT=00000000000000020000000000000000
+CT=8069A449152292DF2DE8642992C632B6
+
+I=64
+PT=00000000000000010000000000000000
+CT=37C6CF2A1ABD1B1F1922B46C7B4A280D
+
+I=65
+PT=00000000000000008000000000000000
+CT=7A2835260E5A0AA2B5DC301800EC8438
+
+I=66
+PT=00000000000000004000000000000000
+CT=EE81FAF2F9058213FFCACF281CB8509E
+
+I=67
+PT=00000000000000002000000000000000
+CT=57F22D93C37129BA331FDBA38E005A1E
+
+I=68
+PT=00000000000000001000000000000000
+CT=EC798782E87B7D9F780CC3C3A46519B5
+
+I=69
+PT=00000000000000000800000000000000
+CT=43EA28497F5D40E3A4744FA2EDAA42DE
+
+I=70
+PT=00000000000000000400000000000000
+CT=91F004E7DEBF41B3414DD8C5C317372C
+
+I=71
+PT=00000000000000000200000000000000
+CT=C249EAE54E7B4DF43B938C1B4CC28314
+
+I=72
+PT=00000000000000000100000000000000
+CT=32C289D7EEFB99D2F17AD7B7D45FE1EC
+
+I=73
+PT=00000000000000000080000000000000
+CT=A675FB2E8DDBF810CEF01CF2B728CD2B
+
+I=74
+PT=00000000000000000040000000000000
+CT=A418AAAB6E6921CC731AA8A349386080
+
+I=75
+PT=00000000000000000020000000000000
+CT=2E2B0F44863E67D9B0215C4ABD60417F
+
+I=76
+PT=00000000000000000010000000000000
+CT=F0AF7CB19E911D481F6426DAEFDD2240
+
+I=77
+PT=00000000000000000008000000000000
+CT=CB1304DAAA2DF6878F56AC2E0F887E04
+
+I=78
+PT=00000000000000000004000000000000
+CT=B1B70A7E6A0CD1916D9B78BEA19084AE
+
+I=79
+PT=00000000000000000002000000000000
+CT=0CDE9F9BE646A5FCE3436B794A9CFC65
+
+I=80
+PT=00000000000000000001000000000000
+CT=68C7946D476A0A36674B36AFD7E5DF33
+
+I=81
+PT=00000000000000000000800000000000
+CT=48770159A07DD8DFFF06C80105F8D57C
+
+I=82
+PT=00000000000000000000400000000000
+CT=665E62801B3260E3C45BD3BE34DFDEBE
+
+I=83
+PT=00000000000000000000200000000000
+CT=4159C1F686BFBE5B0E50BDB0DA532B69
+
+I=84
+PT=00000000000000000000100000000000
+CT=6333100A5A4AD917DC2D4E78A04869A3
+
+I=85
+PT=00000000000000000000080000000000
+CT=866A4519AB1D199F25886B89D0539ACC
+
+I=86
+PT=00000000000000000000040000000000
+CT=EC0CFD37E4CBC7E8BE385283F7AEA75A
+
+I=87
+PT=00000000000000000000020000000000
+CT=CA2F383AACCA0810AA13F3E710621422
+
+I=88
+PT=00000000000000000000010000000000
+CT=1D0EEF6870444F950937831EC0A55D98
+
+I=89
+PT=00000000000000000000008000000000
+CT=37839B35ED6801E7670496D479A95017
+
+I=90
+PT=00000000000000000000004000000000
+CT=02317C8C7098C4F94AB867AC7A49DD8D
+
+I=91
+PT=00000000000000000000002000000000
+CT=FFB4CB4E3F7F8BF3367EBD43236518B4
+
+I=92
+PT=00000000000000000000001000000000
+CT=36BEDEF1E4AA3E4A40A305741713FCBF
+
+I=93
+PT=00000000000000000000000800000000
+CT=B2DFE3C4870269C1E3FEEC39161540D9
+
+I=94
+PT=00000000000000000000000400000000
+CT=147EF2518AD45DA0026056ECBF6A3DFA
+
+I=95
+PT=00000000000000000000000200000000
+CT=027A75E4DE635790E47ACE90D7928804
+
+I=96
+PT=00000000000000000000000100000000
+CT=C4CF3CCB59BF87D0AFBD629F48CFBB7B
+
+I=97
+PT=00000000000000000000000080000000
+CT=35165C93F564C97E1C32EF97E8151A87
+
+I=98
+PT=00000000000000000000000040000000
+CT=449DE37F7D5A1BBD628ABBE7E061701D
+
+I=99
+PT=00000000000000000000000020000000
+CT=B1D45EAF218F1799B149BAD677FE129F
+
+I=100
+PT=00000000000000000000000010000000
+CT=BE08AC6DB6BD0583AA9D2ABC71C73DCD
+
+I=101
+PT=00000000000000000000000008000000
+CT=BCC835BD3DF1A79E4C7C145B899A5C25
+
+I=102
+PT=00000000000000000000000004000000
+CT=3D311EA611FF5AF371301C58A8E9912D
+
+I=103
+PT=00000000000000000000000002000000
+CT=A5A1BEA594ACC7CA80F09EA5ADDB5C71
+
+I=104
+PT=00000000000000000000000001000000
+CT=0F09492429FE7222D6CD8190D9F2FFBF
+
+I=105
+PT=00000000000000000000000000800000
+CT=816D2220A16B8AAEE71364FD43636C6F
+
+I=106
+PT=00000000000000000000000000400000
+CT=D7E8702408419ED73191B107EAF75A0B
+
+I=107
+PT=00000000000000000000000000200000
+CT=9B170EFB1E235B433C78E276BEA082F0
+
+I=108
+PT=00000000000000000000000000100000
+CT=03BBECC5598AE974430F29395522F096
+
+I=109
+PT=00000000000000000000000000080000
+CT=DB53517766C0E8CF42059607CBA89380
+
+I=110
+PT=00000000000000000000000000040000
+CT=2E2AF4B7931F0AEFFAC5471148A5BB97
+
+I=111
+PT=00000000000000000000000000020000
+CT=C872C0408266403B984F635FF5683DE4
+
+I=112
+PT=00000000000000000000000000010000
+CT=15DCF750B0E3A68AD1F4EFD07E8967B4
+
+I=113
+PT=00000000000000000000000000008000
+CT=B41092048E9E6A749F6FD8CE515A23A3
+
+I=114
+PT=00000000000000000000000000004000
+CT=4DA9267D62507994312BD5C99ADDE730
+
+I=115
+PT=00000000000000000000000000002000
+CT=9E2FCA6D1D626E9C6A924EBF7DBF618A
+
+I=116
+PT=00000000000000000000000000001000
+CT=E092E8D7EF2C2465AEFB2493C3063590
+
+I=117
+PT=00000000000000000000000000000800
+CT=1C0E58DA37D1068378A88DBE2EDE4E10
+
+I=118
+PT=00000000000000000000000000000400
+CT=19063F854232B8509A6A3A6D46809959
+
+I=119
+PT=00000000000000000000000000000200
+CT=447FB09E54EFA285F7530F25C4EA0022
+
+I=120
+PT=00000000000000000000000000000100
+CT=F6ABE86321BE40E1FBFDAFED37CC1D9B
+
+I=121
+PT=00000000000000000000000000000080
+CT=4E8506CD006666341D6CF51F98B41F35
+
+I=122
+PT=00000000000000000000000000000040
+CT=53995DE0009CA18BECAFB8307C54C14C
+
+I=123
+PT=00000000000000000000000000000020
+CT=2006BF99F4C58B6CC2627856593FAEEA
+
+I=124
+PT=00000000000000000000000000000010
+CT=2DA697D2737CB30B744A4644FA1CBC6E
+
+I=125
+PT=00000000000000000000000000000008
+CT=47A22ACDB60C3A986A8F76ECD0EA3433
+
+I=126
+PT=00000000000000000000000000000004
+CT=FDAA17C2CDE20268FE36E164EA532151
+
+I=127
+PT=00000000000000000000000000000002
+CT=98E7247C07F0FE411C267E4384B0F600
+
+I=128
+PT=00000000000000000000000000000001
+CT=CD33B28AC773F74BA00ED1F312572435
+
+==========
+
+KEYSIZE=256
+
+KEY=0000000000000000000000000000000000000000000000000000000000000000
+
+I=1
+PT=80000000000000000000000000000000
+CT=DDC6BF790C15760D8D9AEB6F9A75FD4E
+
+I=2
+PT=40000000000000000000000000000000
+CT=C7098C217C334D0C9BDF37EA13B0822C
+
+I=3
+PT=20000000000000000000000000000000
+CT=60F0FB0D4C56A8D4EEFEC5264204042D
+
+I=4
+PT=10000000000000000000000000000000
+CT=73376FBBF654D0686E0E84001477106B
+
+I=5
+PT=08000000000000000000000000000000
+CT=2F443B52BA5F0C6EA0602C7C4FD259B6
+
+I=6
+PT=04000000000000000000000000000000
+CT=75D11B0E3A68C4223D88DBF017977DD7
+
+I=7
+PT=02000000000000000000000000000000
+CT=779B38D15BFFB63D8D609D551A5CC98E
+
+I=8
+PT=01000000000000000000000000000000
+CT=5275F3D86B4FB8684593133EBFA53CD3
+
+I=9
+PT=00800000000000000000000000000000
+CT=1CEF2074B336CEC62F12DEA2F6AB1481
+
+I=10
+PT=00400000000000000000000000000000
+CT=1AEF5ABBAD9D7160874578DCD8BAE172
+
+I=11
+PT=00200000000000000000000000000000
+CT=46C525DB17E72F26BF03216846B6F609
+
+I=12
+PT=00100000000000000000000000000000
+CT=E24411F941BBE08788781E3EC52CBAA4
+
+I=13
+PT=00080000000000000000000000000000
+CT=83A3DEDD1DD27018F6A6477E40527581
+
+I=14
+PT=00040000000000000000000000000000
+CT=B68F8A2CDBAB0C923C67FC8F0F1087DE
+
+I=15
+PT=00020000000000000000000000000000
+CT=649944A70C32BF87A7409E7AE128FDE8
+
+I=16
+PT=00010000000000000000000000000000
+CT=2846526D67387539C89314DE9E0C2D02
+
+I=17
+PT=00008000000000000000000000000000
+CT=A9A0B8402E53C70DD1688054BA58DDFD
+
+I=18
+PT=00004000000000000000000000000000
+CT=4A72E6E1B79C83AC4BE3EBA5699EED48
+
+I=19
+PT=00002000000000000000000000000000
+CT=B0E36B867BA4FF2B77D0614B0E364E4C
+
+I=20
+PT=00001000000000000000000000000000
+CT=49B57DE141F6418E3090F24DDD4014B6
+
+I=21
+PT=00000800000000000000000000000000
+CT=A6C0D5B9797258E1987AC5F6CD20146D
+
+I=22
+PT=00000400000000000000000000000000
+CT=426CF4BDCAA369175965D26E7C71EEA2
+
+I=23
+PT=00000200000000000000000000000000
+CT=E27F484CE54BC99BC1A52BDA3B518A26
+
+I=24
+PT=00000100000000000000000000000000
+CT=D16D186284C7E6EE64B8104E0EF20BA5
+
+I=25
+PT=00000080000000000000000000000000
+CT=6431F8538AD54E1E044A9F71F8EF556B
+
+I=26
+PT=00000040000000000000000000000000
+CT=ECD57CEB451D27EB96C55B2042257E8E
+
+I=27
+PT=00000020000000000000000000000000
+CT=4F0F188DC911B1954AFBC734C9F68872
+
+I=28
+PT=00000010000000000000000000000000
+CT=B54DEF0337626B65614E81EDFDE620F3
+
+I=29
+PT=00000008000000000000000000000000
+CT=6655D8074CAE0B90B0D3A3FE72D4D9DB
+
+I=30
+PT=00000004000000000000000000000000
+CT=C6B74B6B9EB4FC0C9A237DB1B616D09A
+
+I=31
+PT=00000002000000000000000000000000
+CT=D7B5D076EA56EC2B20791D7AD51CCF8F
+
+I=32
+PT=00000001000000000000000000000000
+CT=FE160C224BF003CE3BDDC90CB52ED22C
+
+I=33
+PT=00000000800000000000000000000000
+CT=5E00DA9BA94B5EC0D258D8A8002E0F6A
+
+I=34
+PT=00000000400000000000000000000000
+CT=09AC6DCFF4DACFF1651E2BA212A292A3
+
+I=35
+PT=00000000200000000000000000000000
+CT=B283617E318D99AF83A05D9810BA89F7
+
+I=36
+PT=00000000100000000000000000000000
+CT=0B5F70CCB40B0EF2538AE9B4A9770B35
+
+I=37
+PT=00000000080000000000000000000000
+CT=43282BF180248FB517839B37F4DDAAE4
+
+I=38
+PT=00000000040000000000000000000000
+CT=DDBD534C8B2E6D30A268F88C55AD765B
+
+I=39
+PT=00000000020000000000000000000000
+CT=A41A164E50EC2D9F175E752B755E0B5C
+
+I=40
+PT=00000000010000000000000000000000
+CT=37BFF99FF2F7AA97779E4ADF6F13FB10
+
+I=41
+PT=00000000008000000000000000000000
+CT=9BA4F7BD298152903A683C4CEC669216
+
+I=42
+PT=00000000004000000000000000000000
+CT=5FB750C7CE10DE7B4504248914D0DA06
+
+I=43
+PT=00000000002000000000000000000000
+CT=3E748BFA108E086F51D56EC74A9E0FB9
+
+I=44
+PT=00000000001000000000000000000000
+CT=31D4E56B99F5B73C1B8437DF332AFB98
+
+I=45
+PT=00000000000800000000000000000000
+CT=9DC6717B84FC55D266E7B1D9B5C52A5F
+
+I=46
+PT=00000000000400000000000000000000
+CT=8EF8BA007F23C0A50FC120E07041BCCD
+
+I=47
+PT=00000000000200000000000000000000
+CT=C58F38E1839FC1918A12B8C9E88C66B6
+
+I=48
+PT=00000000000100000000000000000000
+CT=B695D72A3FCF508C4050E12E40061C2D
+
+I=49
+PT=00000000000080000000000000000000
+CT=5D2736AD478A50583BC8C11BEFF16D7A
+
+I=50
+PT=00000000000040000000000000000000
+CT=DF0EACA8F17847AD41F9578F14C7B56B
+
+I=51
+PT=00000000000020000000000000000000
+CT=E5AA14AD48AD0A3C47CC35D5F8020E51
+
+I=52
+PT=00000000000010000000000000000000
+CT=11BE6C8F58EBD8CEF1A53F591A68E8CE
+
+I=53
+PT=00000000000008000000000000000000
+CT=ECFE7BAFCBF42C1FEE015488770B3053
+
+I=54
+PT=00000000000004000000000000000000
+CT=E552649F8D8EC4A1E1CD6DF50B6E6777
+
+I=55
+PT=00000000000002000000000000000000
+CT=521C0629DE93B9119CDB1DDC5809DDEA
+
+I=56
+PT=00000000000001000000000000000000
+CT=CB38A62A0BAB1784156BA038CBA99BF6
+
+I=57
+PT=00000000000000800000000000000000
+CT=76CCEE8AAACD394DE1EEF3DDA10CB54B
+
+I=58
+PT=00000000000000400000000000000000
+CT=6AFF910FA1D5673140E2DB59B8416049
+
+I=59
+PT=00000000000000200000000000000000
+CT=064A12C0EF73FB386801BF4F35F3120D
+
+I=60
+PT=00000000000000100000000000000000
+CT=2240E374929D5B1BB8FF0FFDDDF640EC
+
+I=61
+PT=00000000000000080000000000000000
+CT=D4BA15C904C7692185DE85C02052E180
+
+I=62
+PT=00000000000000040000000000000000
+CT=1714A315AB0166728A44CD91D4AE9018
+
+I=63
+PT=00000000000000020000000000000000
+CT=6C970BDD9F0E222722EA31A1D12DD0AD
+
+I=64
+PT=00000000000000010000000000000000
+CT=F5956EDF02BD36A401BBB6CE77C3D3FB
+
+I=65
+PT=00000000000000008000000000000000
+CT=0CA11F122CCD7C259DC597EED3DF9BC4
+
+I=66
+PT=00000000000000004000000000000000
+CT=50109AB4912AD2560B206F331B62EB6C
+
+I=67
+PT=00000000000000002000000000000000
+CT=DBE7C91A4175614889A2D4BEFD64845E
+
+I=68
+PT=00000000000000001000000000000000
+CT=0D3322853A571A6B46B79C0228E0DD25
+
+I=69
+PT=00000000000000000800000000000000
+CT=96E4EE0BB9A11C6FB8522F285BADDEB6
+
+I=70
+PT=00000000000000000400000000000000
+CT=96705C52D2CFCE82E630C93477C79C49
+
+I=71
+PT=00000000000000000200000000000000
+CT=C50130AED6A126149D71F3888C83C232
+
+I=72
+PT=00000000000000000100000000000000
+CT=4816EFE3DEB380566EBA0C17BF582090
+
+I=73
+PT=00000000000000000080000000000000
+CT=0390857B4C8C98E4CF7A2B6F3394C507
+
+I=74
+PT=00000000000000000040000000000000
+CT=422E73A02025EBE8B8B5D6E0FA24FCB2
+
+I=75
+PT=00000000000000000020000000000000
+CT=3271AA7F4BF1D7C38050A43076D4FF76
+
+I=76
+PT=00000000000000000010000000000000
+CT=D2074946F0D37B8975607BFC2E70234C
+
+I=77
+PT=00000000000000000008000000000000
+CT=1A509194C1270AB92E5A42D3A9F8D98B
+
+I=78
+PT=00000000000000000004000000000000
+CT=512438946360CCC4A5C6D73F6EED7130
+
+I=79
+PT=00000000000000000002000000000000
+CT=98CFCDEC46EBEA1A286B3004F2746A0D
+
+I=80
+PT=00000000000000000001000000000000
+CT=A1CF369949677A3AF3D58E3EABF2741B
+
+I=81
+PT=00000000000000000000800000000000
+CT=D84C2E1A0E4A52166FA8FF6889D1E5E2
+
+I=82
+PT=00000000000000000000400000000000
+CT=4AD91CCEEF60119B5078FD162D2735DE
+
+I=83
+PT=00000000000000000000200000000000
+CT=2860793D818E97AAFF1D339D7702438D
+
+I=84
+PT=00000000000000000000100000000000
+CT=6F9068BE73364AE250D89D78A6C9CE6F
+
+I=85
+PT=00000000000000000000080000000000
+CT=024FC3FEF4883FEB1A8DD005305FECCE
+
+I=86
+PT=00000000000000000000040000000000
+CT=08A61FE0816D75EA15EB3C9FB9CCDED6
+
+I=87
+PT=00000000000000000000020000000000
+CT=449C86DFA13F260175CE39797686FFA4
+
+I=88
+PT=00000000000000000000010000000000
+CT=4FFFFC29A59858E1133F2BFB1A8A4817
+
+I=89
+PT=00000000000000000000008000000000
+CT=19425D1F6480B25096561295697DC2B7
+
+I=90
+PT=00000000000000000000004000000000
+CT=31974727ECDD2C77C3A428FC3A8CB3FC
+
+I=91
+PT=00000000000000000000002000000000
+CT=A57CD704B3C95E744D08DF443458F2F5
+
+I=92
+PT=00000000000000000000001000000000
+CT=486D8C193DB1ED73ACB17990442FC40B
+
+I=93
+PT=00000000000000000000000800000000
+CT=5E4DBF4E83AB3BC055B9FCC7A6B3A763
+
+I=94
+PT=00000000000000000000000400000000
+CT=ACF2E0A693FBBCBA4D41B861E0D89E37
+
+I=95
+PT=00000000000000000000000200000000
+CT=32A7CB2AE066A51D2B78FC4B4CFCB608
+
+I=96
+PT=00000000000000000000000100000000
+CT=677D494DBB73CAF55C1990158DA12F14
+
+I=97
+PT=00000000000000000000000080000000
+CT=082A0D2367512ADF0D75A151BFBE0A17
+
+I=98
+PT=00000000000000000000000040000000
+CT=5E5BB7337923C482CE8CBA249E6A8C7D
+
+I=99
+PT=00000000000000000000000020000000
+CT=D3001BA7C7026EE3E5003179530AFCFC
+
+I=100
+PT=00000000000000000000000010000000
+CT=46EC44F8931E629FE8FD8961312EDDE1
+
+I=101
+PT=00000000000000000000000008000000
+CT=C5F8ECD79C7B30E81D17E32079969310
+
+I=102
+PT=00000000000000000000000004000000
+CT=5B8AD6919E24CAEBCC55401AEE0C9802
+
+I=103
+PT=00000000000000000000000002000000
+CT=C2302B7E701B5CC7F8B29E3516DBBFA6
+
+I=104
+PT=00000000000000000000000001000000
+CT=A1D04D6A76F9F7A94D49FAA64A87F244
+
+I=105
+PT=00000000000000000000000000800000
+CT=7FB6F92D35B5CB6C631600EDB9E860BA
+
+I=106
+PT=00000000000000000000000000400000
+CT=B2EF7078BCFACE07AEEC3F9B48830EB3
+
+I=107
+PT=00000000000000000000000000200000
+CT=F475A7493D24C7036E53390374C378B3
+
+I=108
+PT=00000000000000000000000000100000
+CT=B36802AC987377A37BD8EADC97C57D60
+
+I=109
+PT=00000000000000000000000000080000
+CT=ADDCD3D19689C4DDC738CE5F69DC9505
+
+I=110
+PT=00000000000000000000000000040000
+CT=0DAF8CA22884915403C0F0BB1F4BD74F
+
+I=111
+PT=00000000000000000000000000020000
+CT=4AF36BAE2660503B3248E4685059FD05
+
+I=112
+PT=00000000000000000000000000010000
+CT=7D5631814DD8E917D97A0D514C743971
+
+I=113
+PT=00000000000000000000000000008000
+CT=BC3352500FC0CBB9DB5B5F6B491C1BE8
+
+I=114
+PT=00000000000000000000000000004000
+CT=6A4A30BA87E87AF65C90AEB7AFEDC76B
+
+I=115
+PT=00000000000000000000000000002000
+CT=77E6125897668AC8E73E8C79A6FF8336
+
+I=116
+PT=00000000000000000000000000001000
+CT=3FA9D39104EBB323C7AAAA248960DD1E
+
+I=117
+PT=00000000000000000000000000000800
+CT=FAD75AD76AB10ADC49036B250E229D39
+
+I=118
+PT=00000000000000000000000000000400
+CT=2FACAA5FE35B228A16AC74088D702EC4
+
+I=119
+PT=00000000000000000000000000000200
+CT=88B6CBCFDFEF8AD91720A1BB69A1F33E
+
+I=120
+PT=00000000000000000000000000000100
+CT=C7E9D250998632D444356242EF04058D
+
+I=121
+PT=00000000000000000000000000000080
+CT=B14DAD8D3D9153F46C0D3A1AD63C7A05
+
+I=122
+PT=00000000000000000000000000000040
+CT=60ABA678A506608D0845966D29B5F790
+
+I=123
+PT=00000000000000000000000000000020
+CT=482DC43F2388EF25D24144E144BD834E
+
+I=124
+PT=00000000000000000000000000000010
+CT=1490A05A7CEE43BDE98B56E309DC0126
+
+I=125
+PT=00000000000000000000000000000008
+CT=ABFA77CD6E85DA245FB0BDC5E52CFC29
+
+I=126
+PT=00000000000000000000000000000004
+CT=DD4AB1284D4AE17B41E85924470C36F7
+
+I=127
+PT=00000000000000000000000000000002
+CT=CEA7403D4D606B6E074EC5D3BAF39D18
+
+I=128
+PT=00000000000000000000000000000001
+CT=530F8AFBC74536B9A963B4F1C4CB738B
+
+==========
\ No newline at end of file
diff --git a/krb5-1-6/src/lib/crypto/aes/test/katmct.pdf b/krb5-1-6/src/lib/crypto/aes/test/katmct.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..b494fb53716f92bdc6ca762cd5689493eb0bdc56
GIT binary patch
literal 100812
zcmc%PRZv{P*C={)f@g3ixH~i00Kwhe0}SqNfdn1gU4y&3ySux4(BKJ#<mUT-=bSpX
zPTi{WcHdU7y>@rke%Slhy_-%|Qksp6otqL9jqc!Zb`cZpUnD@uN$F%}i-{&Ago(zX
zXyIt(ZcWL>`7f*fuPtq3?{48r$)TvPBWVG3GPn45hlmI!nwz_;g{cE3S^zLIU_N}w
zlARO<Fqn|nX2}giK?@PJ?h_-3B8xtNv+jx^AR3~UHnDCpVJE_X4f02*juH}LNGG=2
zY>6^b6DwQtBoytrgR-Uv5Pi}`75GSJ9=K84PQ19Y3p5Jzr$kNph>?&su;(TysnV6D
z2mKXKweW^w)YXbW&ip`hOAR7L*$9`UXaJ2%bjv3OqUf6>z4r87b;=B^<zV8}CMiCZ
z_dG9{7$xpi#H?BcdwD@pOlfSqB;%!EV<1oo<|j~eX3ZOpW~G7MwBROitn8UsT#En>
z6PGHa8Y<ZL1j^Jl5ZfmzaS>tCs(%j{vsf5FL%m-VDB3dR#VVk!=wBJ~0b&jZ!G|BY
z^6%(hOSq(w9J�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
F{|1h!T}%J~

literal 0
HcmV?d00001

diff --git a/krb5-1-6/src/lib/crypto/aes/uitypes.h b/krb5-1-6/src/lib/crypto/aes/uitypes.h
new file mode 100644
index 000000000..3a7292183
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/uitypes.h
@@ -0,0 +1,83 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary 
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright 
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products 
+      built using this software without specific written permission. 
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness 
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 01/02/2002
+
+ This file contains code to obtain or set the definitions for fixed length 
+ unsigned integer types.
+*/
+
+#ifndef _UITYPES_H
+#define _UITYPES_H
+
+#include "autoconf.h"
+
+#if defined(__GNU_LIBRARY__)
+#define HAS_INTTYPES_H
+#elif !defined(_MSC_VER)
+#include <limits.h>
+#if ULONG_MAX > 0xFFFFFFFFUL
+  #define MODEL_64
+#else
+  #define MODEL_32
+#endif
+#endif
+
+#if defined HAS_INTTYPES_H || defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#define s_u32     u
+#define s_u64   ull
+#elif defined MODEL_32
+typedef unsigned char            uint8_t;
+typedef unsigned short int      uint16_t;
+typedef unsigned int            uint32_t;
+typedef unsigned long long int  uint64_t;
+#define s_u32     u
+#define s_u64   ull
+#elif defined MODEL_64
+typedef unsigned char            uint8_t;
+typedef unsigned short int      uint16_t;
+typedef unsigned int            uint32_t;
+typedef unsigned long int       uint64_t;
+#define s_u32     u
+#define s_u64    ul
+#elif defined(_MSC_VER)
+typedef unsigned  __int8         uint8_t;
+typedef unsigned __int16        uint16_t;
+typedef unsigned __int32        uint32_t;
+typedef unsigned __int64        uint64_t;
+#define s_u32    ui32
+#define s_u64    ui64
+#else
+#error You need to define fixed length types in uitypes.h
+#endif
+
+#define sfx_lo(x,y) x##y
+#define sfx_hi(x,y) sfx_lo(x,y)
+#define x_32(p)     sfx_hi(0x##p,s_u32)
+#define x_64(p)     sfx_hi(0x##p,s_u64)
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/aes/vb.txt b/krb5-1-6/src/lib/crypto/aes/vb.txt
new file mode 100644
index 000000000..dab133c2c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/aes/vb.txt
@@ -0,0 +1,87 @@
+
+Private Const BlkLenMax = 32        ' maximum block length in bytes
+Private Const KeyLenMax = 32        ' maximum block length in bytes
+Private Const KeySchLenMax = 128    ' maximum key schedule length in bytes
+Private BlkLen As Integer           ' actual block length
+Private KeyLen As Integer           ' actual key length
+
+Private Type AESctx     ' Type to hold the AES context data
+  Ekey(0 To KeySchLenMax - 1) As Long
+  Nrnd As Long
+  Ncol As Long
+End Type
+
+Private Type KeyBlk     ' Type to hold user key data
+ K(0 To KeyLenMax - 1) As Byte
+End Type
+
+Private Type IoBlk      ' Type to hold cipher input and output blocks
+ IO(0 To BlkLenMax - 1) As Byte
+End Type
+
+Rem Change "d:\dll_pth" in the following lines to the directory path where the AES DLL is located
+Private Declare Function AesBlkLen Lib "d:\dll_path\aes.dll" Alias "_aes_blk_len@8" (ByVal N As Long, C As AESctx) As Integer
+Private Declare Function AesEncKey Lib "d:\dll_path\aes.dll" Alias "_aes_enc_key@12" (K As KeyBlk, ByVal N As Long, C As AESctx) As Integer
+Private Declare Function AesDecKey Lib "d:\dll_path\aes.dll" Alias "_aes_dec_key@12" (K As KeyBlk, ByVal N As Long, C As AESctx) As Integer
+Private Declare Function AesEncBlk Lib "d:\dll_path\aes.dll" Alias "_aes_enc_blk@12" (Ib As IoBlk, Ob As IoBlk, C As AESctx) As Integer
+Private Declare Function AesDecBlk Lib "d:\dll_path\aes.dll" Alias "_aes_dec_blk@12" (Ib As IoBlk, Ob As IoBlk, C As AESctx) As Integer
+
+Private Sub Hex(X As Byte)  ' Output a byte in hexadecimal format
+Dim H As Byte
+H = Int(X / 16)
+If H < 10 Then
+    Debug.Print Chr(48 + H);
+Else
+    Debug.Print Chr(87 + H);
+End If
+H = Int(X Mod 16)
+If H < 10 Then
+    Debug.Print Chr(48 + H);
+Else
+    Debug.Print Chr(87 + H);
+End If
+End Sub
+
+Private Sub OutKey(S As String, B As KeyBlk)    ' Display a key value
+Debug.Print: Debug.Print S;
+For i = 0 To KeyLen - 1
+   Hex B.K(i)
+Next i
+End Sub
+
+Private Sub OutBlock(S As String, B As IoBlk)   ' Display an input/output block
+Debug.Print: Debug.Print S;
+For i = 0 To BlkLen - 1
+   Hex B.IO(i)
+Next i
+End Sub
+
+Rem The following Main routine should output the following in the immediate window:
+Rem Key =            00000000000000000000000000000000
+Rem Input =          00000000000000000000000000000000
+Rem Encrypted Text = 66e94bd4ef8a2c3b884cfa59ca342b2e
+Rem Decrypted Text = 00000000000000000000000000000000
+
+Sub Main()
+Dim Key As KeyBlk   ' These variables are automatically
+Dim Ib As IoBlk, Ob As IoBlk, Rb As IoBlk
+Dim Cx As AESctx    ' initialised to zero values in VBA
+Dim RetVal As Integer
+
+BlkLen = 16: KeyLen = 16
+
+Rem RetVal = AesBlkLen(BlkLen, Cx)          ' include if the cipher block size is variable
+
+OutKey "Key =            ", Key
+OutBlock "Input =          ", Ib
+
+RetVal = AesEncKey(Key, KeyLen, Cx)     ' set an all zero encryption key
+RetVal = AesEncBlk(Ib, Ob, Cx)          ' encrypt Ib to Ob
+OutBlock "Encrypted Text = ", Ob
+
+RetVal = AesDecKey(Key, KeyLen, Cx)     ' set an all zero decryption key
+RetVal = AesDecBlk(Ob, Rb, Cx)          ' decrypt Ob to Rb
+OutBlock "Decrypted Text = ", Rb
+Debug.Print
+
+End Sub
diff --git a/krb5-1-6/src/lib/crypto/arcfour/Makefile.in b/krb5-1-6/src/lib/crypto/arcfour/Makefile.in
new file mode 100644
index 000000000..458ad742c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/arcfour/Makefile.in
@@ -0,0 +1,64 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/arcfour
+mydir=lib/crypto/arcfour
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../md4
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=arcfour
+##DOS##OBJFILE=..\$(OUTPRE)arcfour.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS=\
+	arcfour.o	\
+	arcfour_s2k.o
+
+OBJS=\
+	$(OUTPRE)arcfour.$(OBJEXT)	\
+	$(OUTPRE)arcfour_s2k.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/arcfour.c	\
+	$(srcdir)/arcfour_s2k.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+arcfour.so arcfour.po $(OUTPRE)arcfour.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  arcfour-int.h arcfour.c arcfour.h
+arcfour_s2k.so arcfour_s2k.po $(OUTPRE)arcfour_s2k.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../md4/rsa-md4.h \
+  arcfour-int.h arcfour.h arcfour_s2k.c
diff --git a/krb5-1-6/src/lib/crypto/arcfour/arcfour-int.h b/krb5-1-6/src/lib/crypto/arcfour/arcfour-int.h
new file mode 100644
index 000000000..398fe57a1
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/arcfour/arcfour-int.h
@@ -0,0 +1,31 @@
+/*
+
+ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95).
+This cipher is widely believed and has been tested to be equivalent
+with the RC4 cipher from RSA Data Security, Inc.  (RC4 is a trademark
+of RSA Data Security)
+
+*/
+#ifndef ARCFOUR_INT_H
+#define ARCFOUR_INT_H
+
+#include "arcfour.h"
+
+#define CONFOUNDERLENGTH 8
+
+typedef struct
+{
+   unsigned int x;
+   unsigned int y;
+   unsigned char state[256];
+} ArcfourContext;
+
+typedef struct {
+  int initialized;
+  ArcfourContext ctx;
+} ArcFourCipherState;
+
+krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage);
+
+
+#endif /* ARCFOUR_INT_H */
diff --git a/krb5-1-6/src/lib/crypto/arcfour/arcfour.c b/krb5-1-6/src/lib/crypto/arcfour/arcfour.c
new file mode 100644
index 000000000..3481fadcb
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/arcfour/arcfour.c
@@ -0,0 +1,318 @@
+/*
+
+ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95).
+This cipher is widely believed and has been tested to be equivalent
+with the RC4 cipher from RSA Data Security, Inc.  (RC4 is a trademark
+of RSA Data Security)
+
+*/
+#include "k5-int.h"
+#include "arcfour-int.h"
+static const char *const l40 = "fortybits";
+
+void
+krb5_arcfour_encrypt_length(const struct krb5_enc_provider *enc,
+			    const struct krb5_hash_provider *hash,
+			    size_t inputlen, size_t *length)
+{
+  size_t blocksize, hashsize;
+
+  blocksize = enc->block_size;
+  hashsize = hash->hashsize;
+
+  /* checksum + (confounder + inputlen, in even blocksize) */
+  *length = hashsize + krb5_roundup(8 + inputlen, blocksize);
+}
+
+ krb5_keyusage
+ krb5int_arcfour_translate_usage(krb5_keyusage usage)
+{
+  switch (usage) {
+  case 1:			/* AS-REQ PA-ENC-TIMESTAMP padata timestamp,  */
+    return 1;
+  case 2:			/* ticket from kdc */
+    return 2;
+  case 3:			/* as-rep encrypted part */
+    return 8;
+  case 4:			/* tgs-req authz data */
+    return 4;
+  case 5:			/* tgs-req authz data in subkey */
+    return 5;
+  case 6:			/* tgs-req authenticator cksum */
+    return 6;			
+case 7:				/* tgs-req authenticator */
+  return 7;
+    case 8:
+    return 8;
+  case 9:			/* tgs-rep encrypted with subkey */
+    return 8;
+  case 10:			/* ap-rep authentication cksum */
+    return 10;			/* xxx  Microsoft never uses this*/
+  case 11:			/* app-req authenticator */
+    return 11;
+  case 12:			/* app-rep encrypted part */
+    return 12;
+  case 23: /* sign wrap token*/
+    return 13;
+  default:
+      return usage;
+}
+}
+
+krb5_error_code
+krb5_arcfour_encrypt(const struct krb5_enc_provider *enc,
+		     const struct krb5_hash_provider *hash,
+		     const krb5_keyblock *key, krb5_keyusage usage,
+		     const krb5_data *ivec, const krb5_data *input,
+		     krb5_data *output)
+{
+  krb5_keyblock k1, k2, k3;
+  krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder;
+  krb5_keyusage ms_usage;
+  size_t keylength, keybytes, blocksize, hashsize;
+  krb5_error_code ret;
+
+  blocksize = enc->block_size;
+  keybytes = enc->keybytes;
+  keylength = enc->keylength;
+  hashsize = hash->hashsize;
+  
+  d1.length=keybytes;
+  d1.data=malloc(d1.length);
+  if (d1.data == NULL)
+    return (ENOMEM);
+  memcpy(&k1, key, sizeof (krb5_keyblock));
+  k1.length=d1.length;
+  k1.contents= (void *) d1.data;
+
+  d2.length=keybytes;
+  d2.data=malloc(d2.length);
+  if (d2.data == NULL) {
+    free(d1.data);
+    return (ENOMEM);
+  }
+  memcpy(&k2, key, sizeof (krb5_keyblock));
+  k2.length=d2.length;
+  k2.contents=(void *) d2.data;
+
+  d3.length=keybytes;
+  d3.data=malloc(d3.length);
+  if (d3.data == NULL) {
+    free(d1.data);
+    free(d2.data);
+    return (ENOMEM);
+  }
+  memcpy(&k3, key, sizeof (krb5_keyblock));
+  k3.length=d3.length;
+  k3.contents= (void *) d3.data;
+  
+  salt.length=14;
+  salt.data=malloc(salt.length);
+  if (salt.data == NULL) {
+    free(d1.data);
+    free(d2.data);
+    free(d3.data);
+    return (ENOMEM);
+  }
+
+  /* is "input" already blocksize aligned?  if it is, then we need this
+     step, otherwise we do not */
+  plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize);
+  plaintext.data=malloc(plaintext.length);
+  if (plaintext.data == NULL) {
+    free(d1.data);
+    free(d2.data);
+    free(d3.data);
+    free(salt.data);
+    return(ENOMEM);
+  }
+
+  /* setup convienient pointers into the allocated data */
+  checksum.length=hashsize;
+  checksum.data=output->data;
+  ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize);
+  ciphertext.data=output->data+hashsize;
+  confounder.length=CONFOUNDERLENGTH;
+  confounder.data=plaintext.data;
+  output->length = plaintext.length+hashsize;
+  
+  /* begin the encryption, computer K1 */
+  ms_usage=krb5int_arcfour_translate_usage(usage);
+  if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+    strncpy(salt.data, l40, salt.length);
+    salt.data[10]=ms_usage & 0xff;
+    salt.data[11]=(ms_usage >> 8) & 0xff;
+    salt.data[12]=(ms_usage >> 16) & 0xff;
+    salt.data[13]=(ms_usage >> 24) & 0xff;
+  } else {
+    salt.length=4;
+    salt.data[0]=ms_usage & 0xff;
+    salt.data[1]=(ms_usage >> 8) & 0xff;
+    salt.data[2]=(ms_usage >> 16) & 0xff;
+    salt.data[3]=(ms_usage >> 24) & 0xff;
+  }
+  krb5_hmac(hash, key, 1, &salt, &d1);
+
+  memcpy(k2.contents, k1.contents, k2.length);
+
+  if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP)
+    memset(k1.contents+7, 0xab, 9);
+
+  ret=krb5_c_random_make_octets(/* XXX */ 0, &confounder);
+  memcpy(plaintext.data+confounder.length, input->data, input->length);
+  if (ret)
+    goto cleanup;
+
+  krb5_hmac(hash, &k2, 1, &plaintext, &checksum);
+
+  krb5_hmac(hash, &k1, 1, &checksum, &d3);
+
+  ret=(*(enc->encrypt))(&k3, ivec, &plaintext, &ciphertext);
+    
+ cleanup:
+  memset(d1.data, 0, d1.length);
+  memset(d2.data, 0, d2.length);
+  memset(d3.data, 0, d3.length);
+  memset(salt.data, 0, salt.length);
+  memset(plaintext.data, 0, plaintext.length);
+
+  free(d1.data);
+  free(d2.data);
+  free(d3.data);
+  free(salt.data);
+  free(plaintext.data);
+  return (ret);
+}
+
+/* This is the arcfour-hmac decryption routine */
+krb5_error_code
+krb5_arcfour_decrypt(const struct krb5_enc_provider *enc,
+		     const struct krb5_hash_provider *hash,
+		     const krb5_keyblock *key, krb5_keyusage usage,
+		     const krb5_data *ivec, const krb5_data *input,
+		     krb5_data *output)
+{
+  krb5_keyblock k1,k2,k3;
+  krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum;
+  krb5_keyusage ms_usage;
+  size_t keybytes, keylength, hashsize, blocksize;
+  krb5_error_code ret;
+
+  blocksize = enc->block_size;
+  keybytes = enc->keybytes;
+  keylength = enc->keylength;
+  hashsize = hash->hashsize;
+
+  d1.length=keybytes;
+  d1.data=malloc(d1.length);
+  if (d1.data == NULL)
+    return (ENOMEM);
+  memcpy(&k1, key, sizeof (krb5_keyblock));
+  k1.length=d1.length;
+  k1.contents= (void *) d1.data;
+  
+  d2.length=keybytes;
+  d2.data=malloc(d2.length);
+  if (d2.data == NULL) {
+    free(d1.data);
+    return (ENOMEM);
+  }
+  memcpy(&k2, key, sizeof(krb5_keyblock));
+  k2.length=d2.length;
+  k2.contents= (void *) d2.data;
+
+  d3.length=keybytes;
+  d3.data=malloc(d3.length);
+  if  (d3.data == NULL) {
+    free(d1.data);
+    free(d2.data);
+    return (ENOMEM);
+  }
+  memcpy(&k3, key, sizeof(krb5_keyblock));
+  k3.length=d3.length;
+  k3.contents= (void *) d3.data;
+
+  salt.length=14;
+  salt.data=malloc(salt.length);
+  if(salt.data==NULL) {
+    free(d1.data);
+    free(d2.data);
+    free(d3.data);
+    return (ENOMEM);
+  }
+
+  ciphertext.length=input->length-hashsize;
+  ciphertext.data=input->data+hashsize;
+  plaintext.length=ciphertext.length;
+  plaintext.data=malloc(plaintext.length);
+  if (plaintext.data == NULL) {
+    free(d1.data);
+    free(d2.data);
+    free(d3.data);
+    free(salt.data);
+    return (ENOMEM);
+  }
+
+  checksum.length=hashsize;
+  checksum.data=input->data;
+
+  /* compute the salt */
+  ms_usage=krb5int_arcfour_translate_usage(usage);
+  if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+    strncpy(salt.data, l40, salt.length);
+    salt.data[10]=ms_usage & 0xff;
+    salt.data[11]=(ms_usage>>8) & 0xff;
+    salt.data[12]=(ms_usage>>16) & 0xff;
+    salt.data[13]=(ms_usage>>24) & 0xff;
+  } else {
+    salt.length=4;
+    salt.data[0]=ms_usage & 0xff;
+    salt.data[1]=(ms_usage>>8) & 0xff;
+    salt.data[2]=(ms_usage>>16) & 0xff;
+    salt.data[3]=(ms_usage>>24) & 0xff;
+  }
+  ret=krb5_hmac(hash, key, 1, &salt, &d1);
+  if (ret)
+    goto cleanup;
+
+  memcpy(k2.contents, k1.contents, k2.length);
+
+  if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
+    memset(k1.contents+7, 0xab, 9);
+  
+  ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
+  if (ret)
+    goto cleanup;
+
+  ret=(*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext);
+  if (ret)
+    goto cleanup;
+
+  ret=krb5_hmac(hash, &k2, 1, &plaintext, &d1);
+  if (ret)
+    goto cleanup;
+
+  if (memcmp(checksum.data, d1.data, hashsize) != 0) {
+    ret=KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    goto cleanup;
+  }
+
+  memcpy(output->data, plaintext.data+CONFOUNDERLENGTH,
+	 (plaintext.length-CONFOUNDERLENGTH));
+  output->length=plaintext.length-CONFOUNDERLENGTH;
+
+ cleanup:
+  memset(d1.data, 0, d1.length);
+  memset(d2.data, 0, d2.length);
+  memset(d3.data, 0, d2.length);
+  memset(salt.data, 0, salt.length);
+  memset(plaintext.data, 0, plaintext.length);
+
+  free(d1.data);
+  free(d2.data);
+  free(d3.data);
+  free(salt.data);
+  free(plaintext.data);
+  return (ret);
+}
+
diff --git a/krb5-1-6/src/lib/crypto/arcfour/arcfour.h b/krb5-1-6/src/lib/crypto/arcfour/arcfour.h
new file mode 100644
index 000000000..c6e435334
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/arcfour/arcfour.h
@@ -0,0 +1,36 @@
+#ifndef ARCFOUR_H
+#define ARCFOUR_H
+
+extern void
+krb5_arcfour_encrypt_length(const struct krb5_enc_provider *,
+			const struct krb5_hash_provider *,
+			size_t,
+			size_t *);
+
+extern 
+krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *,
+			const struct krb5_hash_provider *,
+			const krb5_keyblock *,
+			krb5_keyusage,
+			const krb5_data *,
+     			const krb5_data *,
+			krb5_data *);
+
+extern 
+krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *,
+			const struct krb5_hash_provider *,
+			const krb5_keyblock *,
+			krb5_keyusage,
+			const krb5_data *,
+			const krb5_data *,
+			krb5_data *);
+
+extern krb5_error_code krb5int_arcfour_string_to_key(
+     const struct krb5_enc_provider *,
+     const krb5_data *,
+     const krb5_data *,
+     const krb5_data *,
+     krb5_keyblock *);
+
+extern const struct krb5_enc_provider krb5int_enc_arcfour;
+#endif /* ARCFOUR_H */
diff --git a/krb5-1-6/src/lib/crypto/arcfour/arcfour_s2k.c b/krb5-1-6/src/lib/crypto/arcfour/arcfour_s2k.c
new file mode 100644
index 000000000..efa92bfb1
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/arcfour/arcfour_s2k.c
@@ -0,0 +1,70 @@
+#include "k5-int.h"
+#include "rsa-md4.h"
+#include "arcfour-int.h"
+
+static void asctouni(unsigned char *unicode, unsigned char *ascii, size_t len)
+{
+	size_t counter;
+	for (counter=0;counter<len;counter++) {
+		unicode[2*counter]=ascii[counter];
+		unicode[2*counter + 1]=0x00;
+	}
+}
+
+krb5_error_code
+krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
+			      const krb5_data *string, const krb5_data *salt,
+			      const krb5_data *params, krb5_keyblock *key)
+{
+  size_t len,slen;
+  unsigned char *copystr;
+  krb5_MD4_CTX md4_context;
+
+  if (params != NULL)
+      return KRB5_ERR_BAD_S2K_PARAMS;
+  
+  if (key->length != 16)
+    return (KRB5_BAD_MSIZE);
+
+  /* We ignore salt per the Microsoft spec*/
+
+  /* compute the space needed for the new string.
+     Since the password must be stored in unicode, we need to increase
+     that number by 2x.
+
+     This should be re-evauated in the future, it makes the assumption that
+     thes user's password is in ascii.
+  */
+  slen = ((string->length)>128)?128:string->length;
+  len=(slen)*2;
+
+  copystr = malloc(len);
+  if (copystr == NULL)
+    return ENOMEM;
+
+  /* make the string.  start by creating the unicode version of the password*/
+  asctouni(copystr, string->data, slen );
+
+  /* the actual MD4 hash of the data */
+  krb5_MD4Init(&md4_context);
+  krb5_MD4Update(&md4_context, (unsigned char *)copystr, len);
+  krb5_MD4Final(&md4_context);
+  memcpy(key->contents, md4_context.digest, 16);
+
+#if 0  
+  /* test the string_to_key function */
+  printf("Hash=");
+  {
+    int counter;
+    for(counter=0;counter<16;counter++)
+      printf("%02x", md4_context.digest[counter]);
+    printf("\n");
+  }
+#endif /* 0 */
+
+  /* Zero out the data behind us */
+  memset (copystr, 0, len);
+  memset(&md4_context, 0, sizeof(md4_context));
+  free(copystr);
+  return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/block_size.c b/krb5-1-6/src/lib/crypto/block_size.c
new file mode 100644
index 000000000..e4c11e869
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/block_size.c
@@ -0,0 +1,47 @@
+/*
+ * 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_CALLCONV
+krb5_c_block_size(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);
+
+    *blocksize = krb5_enctypes_list[i].enc->block_size;
+
+    return(0);
+}
diff --git a/krb5-1-6/src/lib/crypto/checksum_length.c b/krb5-1-6/src/lib/crypto/checksum_length.c
new file mode 100644
index 000000000..16177be09
--- /dev/null
+++ b/krb5-1-6/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_CALLCONV
+krb5_c_checksum_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)
+	*length = krb5_cksumtypes_list[i].keyhash->hashsize;
+    else if (krb5_cksumtypes_list[i].trunc_size)
+	*length = krb5_cksumtypes_list[i].trunc_size;
+    else
+	*length = krb5_cksumtypes_list[i].hash->hashsize;
+
+    return(0);
+}
+	
diff --git a/krb5-1-6/src/lib/crypto/cksumtype_to_string.c b/krb5-1-6/src/lib/crypto/cksumtype_to_string.c
new file mode 100644
index 000000000..b0ac516e2
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/cksumtype_to_string.c
@@ -0,0 +1,46 @@
+/*
+ * 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_CALLCONV
+krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char *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/krb5-1-6/src/lib/crypto/cksumtypes.c b/krb5-1-6/src/lib/crypto/cksumtypes.c
new file mode 100644
index 000000000..ae7ed5f87
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/cksumtypes.c
@@ -0,0 +1,98 @@
+/*
+ * 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"
+
+const struct krb5_cksumtypes krb5_cksumtypes_list[] = {
+    { CKSUMTYPE_CRC32, KRB5_CKSUMFLAG_NOT_COLL_PROOF,
+      "crc32", "CRC-32",
+      0, NULL,
+      &krb5int_hash_crc32 },
+
+    { CKSUMTYPE_RSA_MD4, 0,
+      "md4", "RSA-MD4",
+      0, NULL,
+      &krb5int_hash_md4 },
+    { CKSUMTYPE_RSA_MD4_DES, 0,
+      "md4-des", "RSA-MD4 with DES cbc mode",
+      ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_md4des,
+      NULL },
+
+    { CKSUMTYPE_DESCBC, 0,
+      "des-cbc", "DES cbc mode",
+      ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_descbc,
+      NULL },
+
+    { CKSUMTYPE_RSA_MD5, 0,
+      "md5", "RSA-MD5",
+      0, NULL,
+      &krb5int_hash_md5 },
+    { CKSUMTYPE_RSA_MD5_DES, 0,
+      "md5-des", "RSA-MD5 with DES cbc mode",
+      ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_md5des,
+      NULL },
+
+    { CKSUMTYPE_NIST_SHA, 0,
+      "sha", "NIST-SHA",
+      0, NULL,
+      &krb5int_hash_sha1 },
+
+    { CKSUMTYPE_HMAC_SHA1_DES3, KRB5_CKSUMFLAG_DERIVE,
+      "hmac-sha1-des3", "HMAC-SHA1 DES3 key",
+      0, NULL,
+      &krb5int_hash_sha1 },
+    { CKSUMTYPE_HMAC_SHA1_DES3, KRB5_CKSUMFLAG_DERIVE,
+      "hmac-sha1-des3-kd", "HMAC-SHA1 DES3 key", /* alias */
+      0, NULL,
+      &krb5int_hash_sha1 },
+    { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0,
+      "hmac-md5-rc4", "Microsoft HMAC MD5 (RC4 key)", 
+      ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5,
+      NULL },
+    { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0,
+      "hmac-md5-enc", "Microsoft HMAC MD5 (RC4 key)",  /*Heimdal alias*/
+      ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5,
+      NULL },
+    { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0,
+      "hmac-md5-earcfour", "Microsoft HMAC MD5 (RC4 key)",  /* alias*/
+      ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5,
+      NULL },
+
+    { CKSUMTYPE_HMAC_SHA1_96_AES128, KRB5_CKSUMFLAG_DERIVE,
+      "hmac-sha1-96-aes128", "HMAC-SHA1 AES128 key",
+      0, NULL, 
+      &krb5int_hash_sha1, 12 },
+    { CKSUMTYPE_HMAC_SHA1_96_AES256, KRB5_CKSUMFLAG_DERIVE,
+      "hmac-sha1-96-aes256", "HMAC-SHA1 AES256 key",
+      0, NULL, 
+      &krb5int_hash_sha1, 12 },
+};
+
+const int krb5_cksumtypes_length =
+sizeof(krb5_cksumtypes_list)/sizeof(struct krb5_cksumtypes);
diff --git a/krb5-1-6/src/lib/crypto/cksumtypes.h b/krb5-1-6/src/lib/crypto/cksumtypes.h
new file mode 100644
index 000000000..dae70c8f2
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/cksumtypes.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 const struct krb5_cksumtypes krb5_cksumtypes_list[];
+extern const int krb5_cksumtypes_length;
diff --git a/krb5-1-6/src/lib/crypto/coll_proof_cksum.c b/krb5-1-6/src/lib/crypto/coll_proof_cksum.c
new file mode 100644
index 000000000..5c3ea48d3
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/coll_proof_cksum.c
@@ -0,0 +1,50 @@
+/*
+ * 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 KRB5_CALLCONV
+krb5_c_is_coll_proof_cksum(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);
+}
+
+krb5_boolean KRB5_CALLCONV
+is_coll_proof_cksum(krb5_cksumtype ctype)
+{
+    return krb5_c_is_coll_proof_cksum (ctype);
+}
diff --git a/krb5-1-6/src/lib/crypto/combine_keys.c b/krb5-1-6/src/lib/crypto/combine_keys.c
new file mode 100644
index 000000000..3d9765164
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/combine_keys.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS)
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the software,
+ * derivative works or modified versions, and any portions thereof.
+ * 
+ * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
+ * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Key combination function.
+ *
+ * If Key1 and Key2 are two keys to be combined, the algorithm to combine
+ * them is as follows.
+ *
+ * Definitions:
+ *
+ * k-truncate is defined as truncating to the key size the input.
+ *
+ * DR is defined as the generate "random" data from a key
+ * (defined in crypto draft)
+ *
+ * DK is defined as the key derivation function (krb5_derive_key())
+ *
+ * (note: | means "concatenate")
+ *
+ * Combine key algorithm:
+ *
+ * R1 = DR(Key1, n-fold(Key2)) [ Output is length of Key1 ]
+ * R2 = DR(Key2, n-fold(Key1)) [ Output is length of Key2 ]
+ *
+ * rnd = n-fold(R1 | R2) [ Note: output size of nfold must be appropriately
+ *			   sized for random-to-key function ]
+ * tkey = random-to-key(rnd)
+ * Combine-Key(Key1, Key2) = DK(tkey, CombineConstant)
+ *
+ * CombineConstant is defined as the byte string:
+ *
+ * { 0x63 0x6f 0x6d 0x62 0x69 0x6e 0x65 }, which corresponds to the
+ * ASCII encoding of the string "combine"
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+#include "dk.h"
+
+static krb5_error_code dr
+(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey,
+		unsigned char *outdata, const krb5_data *in_constant);
+
+/*
+ * We only support this combine_keys algorithm for des and 3des keys.
+ * Everything else should use the PRF defined in the crypto framework.
+ * We don't implement that yet.
+ */
+
+static krb5_boolean  enctype_ok (krb5_enctype e) 
+{
+    switch (e) {
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES3_CBC_SHA1:
+	return 1;
+    default:
+	return 0;
+    }
+}
+
+krb5_error_code krb5int_c_combine_keys
+(krb5_context context, krb5_keyblock *key1, krb5_keyblock *key2, krb5_keyblock *outkey)
+{
+    unsigned char *r1, *r2, *combined, *rnd, *output;
+    size_t keybytes, keylength;
+    const struct krb5_enc_provider *enc;
+    krb5_data input, randbits;
+    krb5_keyblock tkey;
+    krb5_error_code ret;
+    int i, myalloc = 0;
+    if (!(enctype_ok(key1->enctype)&&enctype_ok(key2->enctype)))
+	return (KRB5_CRYPTO_INTERNAL);
+    
+
+    if (key1->length != key2->length || key1->enctype != key2->enctype)
+	return (KRB5_CRYPTO_INTERNAL);
+
+    /*
+     * Find our encryption algorithm
+     */
+
+    for (i = 0; i < krb5_enctypes_length; i++) {
+	if (krb5_enctypes_list[i].etype == key1->enctype)
+	    break;
+    }
+
+    if (i == krb5_enctypes_length)
+	return (KRB5_BAD_ENCTYPE);
+
+    enc = krb5_enctypes_list[i].enc;
+
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    /*
+     * Allocate and set up buffers
+     */
+
+    if ((r1 = (unsigned char *) malloc(keybytes)) == NULL)
+	return (ENOMEM);
+
+    if ((r2 = (unsigned char *) malloc(keybytes)) == NULL) {
+	free(r1);
+	return (ENOMEM);
+    }
+
+    if ((rnd = (unsigned char *) malloc(keybytes)) == NULL) {
+	free(r1);
+	free(r2);
+	return (ENOMEM);
+    }
+
+    if ((combined = (unsigned char *) malloc(keybytes * 2)) == NULL) {
+	free(r1);
+	free(r2);
+	free(rnd);
+	return (ENOMEM);
+    }
+
+    if ((output = (unsigned char *) malloc(keylength)) == NULL) {
+	free(r1);
+	free(r2);
+	free(rnd);
+	free(combined);
+	return (ENOMEM);
+    }
+
+    /*
+     * Get R1 and R2 (by running the input keys through the DR algorithm.
+     * Note this is most of derive-key, but not all.
+     */
+
+    input.length = key2->length;
+    input.data = (char *) key2->contents;
+    if ((ret = dr(enc, key1, r1, &input)))
+	goto cleanup;
+
+#if 0
+    {
+	int i;
+	printf("R1 =");
+	for (i = 0; i < keybytes; i++)
+	    printf(" %02x", (unsigned char) r1[i]);
+	printf("\n");
+    }
+#endif
+
+    input.length = key1->length;
+    input.data = (char *) key1->contents;
+    if ((ret = dr(enc, key2, r2, &input)))
+	goto cleanup;
+
+#if 0
+    {
+	int i;
+	printf("R2 =");
+	for (i = 0; i < keybytes; i++)
+	    printf(" %02x", (unsigned char) r2[i]);
+	printf("\n");
+    }
+#endif
+
+    /*
+     * Concatenate the two keys together, and then run them through
+     * n-fold to reduce them to a length appropriate for the random-to-key
+     * operation.  Note here that krb5_nfold() takes sizes in bits, hence
+     * the multiply by 8.
+     */
+
+    memcpy(combined, r1, keybytes);
+    memcpy(combined + keybytes, r2, keybytes);
+
+    krb5_nfold((keybytes * 2) * 8, combined, keybytes * 8, rnd);
+
+#if 0
+    {
+	int i;
+	printf("rnd =");
+	for (i = 0; i < keybytes; i++)
+	    printf(" %02x", (unsigned char) rnd[i]);
+	printf("\n");
+    }
+#endif
+
+    /*
+     * Run the "random" bits through random-to-key to produce a encryption
+     * key.
+     */
+
+    randbits.length = keybytes;
+    randbits.data = (char *) rnd;
+    tkey.length = keylength;
+    tkey.contents = output;
+
+    if ((ret = (*(enc->make_key))(&randbits, &tkey)))
+	goto cleanup;
+
+#if 0
+    {
+	int i;
+	printf("tkey =");
+	for (i = 0; i < tkey.length; i++)
+	    printf(" %02x", (unsigned char) tkey.contents[i]);
+	printf("\n");
+    }
+#endif
+
+    /*
+     * Run through derive-key one more time to produce the final key.
+     * Note that the input to derive-key is the ASCII string "combine".
+     */
+
+    input.length = 7; /* Note; change this if string length changes */
+    input.data = "combine";
+
+    /*
+     * Just FYI: _if_ we have space here in the key, then simply use it
+     * without modification.  But if the key is blank (no allocated storage)
+     * then allocate some memory for it.  This allows programs to use one of
+     * the existing keys as the output key, _or_ pass in a blank keyblock
+     * for us to allocate.  It's easier for us to allocate it since we already
+     * know the crypto library internals
+     */
+
+    if (outkey->length == 0 || outkey->contents == NULL) {
+	outkey->contents = (krb5_octet *) malloc(keylength);
+	if (!outkey->contents) {
+	    ret = ENOMEM;
+	    goto cleanup;
+	}
+	outkey->length = keylength;
+	outkey->enctype = key1->enctype;
+	myalloc = 1;
+    }
+
+    if ((ret = krb5_derive_key(enc, &tkey, outkey, &input))) {
+	if (myalloc) {
+	    free(outkey->contents);
+	    outkey->contents = NULL;
+	}
+	goto cleanup;
+    }
+
+#if 0
+    {
+	int i;
+	printf("output =");
+	for (i = 0; i < outkey->length; i++)
+	    printf(" %02x", (unsigned char) outkey->contents[i]);
+	printf("\n");
+    }
+#endif
+
+    ret = 0;
+
+cleanup:
+    memset(r1, 0, keybytes);
+    memset(r2, 0, keybytes);
+    memset(rnd, 0, keybytes);
+    memset(combined, 0, keybytes * 2);
+    memset(output, 0, keylength);
+
+    free(r1);
+    free(r2);
+    free(rnd);
+    free(combined);
+    free(output);
+
+    return (ret);
+}
+
+/*
+ * Our DR function; mostly taken from derive.c
+ */
+
+static krb5_error_code dr
+(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, unsigned char *out, const krb5_data *in_constant)
+{
+    size_t blocksize, keybytes, keylength, n;
+    unsigned char *inblockdata, *outblockdata;
+    krb5_data inblock, outblock;
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    /* allocate and set up buffers */
+
+    if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
+	return(ENOMEM);
+
+    if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
+	free(inblockdata);
+	return(ENOMEM);
+    }
+
+    inblock.data = (char *) inblockdata;
+    inblock.length = blocksize;
+
+    outblock.data = (char *) outblockdata;
+    outblock.length = blocksize;
+
+    /* initialize the input block */
+
+    if (in_constant->length == inblock.length) {
+	memcpy(inblock.data, in_constant->data, inblock.length);
+    } else {
+	krb5_nfold(in_constant->length*8, (unsigned char *) in_constant->data,
+		   inblock.length*8, (unsigned char *) inblock.data);
+    }
+
+    /* loop encrypting the blocks until enough key bytes are generated */
+
+    n = 0;
+    while (n < keybytes) {
+	(*(enc->encrypt))(inkey, 0, &inblock, &outblock);
+
+	if ((keybytes - n) <= outblock.length) {
+	    memcpy(out+n, outblock.data, (keybytes - n));
+	    break;
+	}
+
+	memcpy(out+n, outblock.data, outblock.length);
+	memcpy(inblock.data, outblock.data, outblock.length);
+	n += outblock.length;
+    }
+
+    /* clean memory, free resources and exit */
+
+    memset(inblockdata, 0, blocksize);
+    memset(outblockdata, 0, blocksize);
+
+    free(outblockdata);
+    free(inblockdata);
+
+    return(0);
+}
+
diff --git a/krb5-1-6/src/lib/crypto/crc32/CRC.pm b/krb5-1-6/src/lib/crypto/crc32/CRC.pm
new file mode 100644
index 000000000..ee2ab2ae8
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crc32/CRC.pm
@@ -0,0 +1,156 @@
+# Copyright 2002 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+package CRC;
+
+# CRC: implement a CRC using the Poly package (yes this is slow)
+#
+# message M(x) = m_0 * x^0 + m_1 * x^1 + ... + m_(k-1) * x^(k-1)
+# generator P(x) = p_0 * x^0 + p_1 * x^1 + ... + p_n * x^n
+# remainder R(x) = r_0 * x^0 + r_1 * x^1 + ... + r_(n-1) * x^(n-1)
+#
+# R(x) = (x^n * M(x)) % P(x)
+#
+# Note that if F(x) = x^n * M(x) + R(x), then F(x) = 0 mod P(x) .
+#
+# In MIT Kerberos 5, R(x) is taken as the CRC, as opposed to what
+# ISO 3309 does.
+#
+# ISO 3309 adds a precomplement and a postcomplement.
+#
+# The ISO 3309 postcomplement is of the form
+#
+# A(x) = x^0 + x^1 + ... + x^(n-1) .
+#
+# The ISO 3309 precomplement is of the form
+#
+# B(x) = x^k * A(x) .
+#
+# The ISO 3309 FCS is then
+#
+# (x^n * M(x)) % P(x) + B(x) % P(x) + A(x) ,
+#
+# which is equivalent to
+#
+# (x^n * M(x) + B(x)) % P(x) + A(x) .
+#
+# In ISO 3309, the transmitted frame is
+#
+# F'(x) = x^n * M(x) + R(x) + R'(x) + A(x) ,
+#
+# where
+#
+# R'(x) = B(x) % P(x) .
+#
+# Note that this means that if a new remainder is computed over the
+# frame F'(x) (treating F'(x) as the new M(x)), it will be equal to a
+# constant.
+#
+# F'(x) = 0 + R'(x) + A(x) mod P(x) ,
+#
+# then
+#
+# (F'(x) + x^k * A(x)) * x^n
+#
+# = ((R'(x) + A(x)) + x^k * A(x)) * x^n mod P(x)
+#
+# = (x^k * A(x) + A(x) + x^k * A(x)) * x^n mod P(x)
+#
+# = (0 + A(x)) * x^n mod P(x)
+#
+# Note that (A(x) * x^n) % P(x) is a constant, and that this result
+# depends on B(x) being x^k * A(x).
+
+use Carp;
+use Poly;
+
+sub new {
+    my $self = shift;
+    my $class = ref($self) || $self;
+    my %args = @_;
+    $self = {bitsendian => "little"};
+    bless $self, $class;
+    $self->setpoly($args{"Poly"}) if exists $args{"Poly"};
+    $self->bitsendian($args{"bitsendian"})
+	if exists $args{"bitsendian"};
+    $self->{precomp} = $args{precomp} if exists $args{precomp};
+    $self->{postcomp} = $args{postcomp} if exists $args{postcomp};
+    return $self;
+}
+
+sub setpoly {
+    my $self = shift;
+    my($arg) = @_;
+    croak "need a polynomial" if !$arg->isa("Poly");
+    $self->{Poly} = $arg;
+    return $self;
+}
+
+sub crc {
+    my $self = shift;
+    my $msg = Poly->new(@_);
+    my($order, $r, $precomp);
+    $order = $self->{Poly}->order;
+    # B(x) = x^k * precomp
+    $precomp = $self->{precomp} ?
+	$self->{precomp} * Poly->powers2poly(scalar(@_)) : Poly->new;
+    # R(x) = (x^n * M(x)) % P(x)
+    $r = ($msg * Poly->powers2poly($order)) % $self->{Poly};
+    # B(x) % P(x)
+    $r += $precomp % $self->{Poly};
+    $r += $self->{postcomp} if exists $self->{postcomp};
+    return $r;
+}
+
+# endianness of bits of each octet
+#
+# Note that the message is always treated as being sent in big-endian
+# octet order.
+#
+# Usually, the message will be treated as bits being little-endian,
+# since that is the common case for serial implementations that
+# present data in octets; e.g., most UARTs shift octets onto the line
+# in little-endian order, and protocols such as ISO 3309, V.42,
+# etc. treat individual octets as being sent LSB-first.
+
+sub bitsendian {
+    my $self = shift;
+    my($arg) = @_;
+    croak "bad bit endianness" if $arg !~ /big|little/;
+    $self->{bitsendian} = $arg;
+    return $self;
+}
+
+sub crcstring {
+    my $self = shift;
+    my($arg) = @_;
+    my($packstr, @m);
+    {
+	$packstr = "B*", last if $self->{bitsendian} =~ /big/;
+	$packstr = "b*", last if $self->{bitsendian} =~ /little/;
+	croak "bad bit endianness";
+    };
+    @m = split //, unpack $packstr, $arg;
+    return $self->crc(@m);
+}
+
+1;
diff --git a/krb5-1-6/src/lib/crypto/crc32/Makefile.in b/krb5-1-6/src/lib/crypto/crc32/Makefile.in
new file mode 100644
index 000000000..1f7efcf24
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crc32/Makefile.in
@@ -0,0 +1,55 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/crc32
+mydir=lib/crypto/crc32
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=crc32
+##DOS##OBJFILE=..\$(OUTPRE)crc32.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= crc32.o
+
+OBJS= $(OUTPRE)crc32.$(OBJEXT) 
+
+SRCS= $(srcdir)/crc32.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+	$(RM) t_crc.o t_crc
+
+check-unix:: t_crc
+	$(RUN_SETUP) $(VALGRIND) ./t_crc
+
+t_crc: t_crc.o crc32.o $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_crc.o crc32.o $(SUPPORT_LIB)
+
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+crc32.so crc32.po $(OUTPRE)crc32.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  crc-32.h crc32.c
diff --git a/krb5-1-6/src/lib/crypto/crc32/Poly.pm b/krb5-1-6/src/lib/crypto/crc32/Poly.pm
new file mode 100644
index 000000000..cad0f77b5
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crc32/Poly.pm
@@ -0,0 +1,182 @@
+# Copyright 2002 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+package Poly;
+
+# Poly: implements some basic operations on polynomials in the field
+# of integers (mod 2).
+#
+# The rep is an array of coefficients, highest order term first.
+#
+# This is rather slow at the moment.
+
+use overload
+    '+' => \&add,
+    '-' => \&add,
+    '*' => \&mul,
+    '%' => sub {$_[2] ? mod($_[1], $_[0]) : mod($_[0], $_[1])},
+    '/' => sub { $_[2] ? scalar(div($_[1], $_[0]))
+		     : scalar(div($_[0], $_[1])) },
+    '<=>' => sub {$_[2] ? pcmp($_[1], $_[0]) : pcmp($_[0], $_[1])},
+    '""' => \&str
+;
+
+use Carp;
+
+# doesn't do much beyond normalize and bless
+sub new {
+    my $this = shift;
+    my $class = ref($this) || $this;
+    my(@x) = @_;
+    return bless [norm(@x)], $class;
+}
+
+# stringified P(x)
+sub pretty {
+    my(@x) = @{+shift};
+    my $n = @x;
+    local $_;
+    return "0" if !@x;
+    return join " + ", map {$n--; $_ ? ("x^$n") : ()} @x;
+}
+
+sub print {
+    my $self = shift;
+    print $self->pretty, "\n";
+}
+
+# This assumes normalization.
+sub order {
+    my $self = shift;
+    return $#{$self};
+}
+
+sub str {
+    return overload::StrVal($_[0]);
+}
+
+# strip leading zero coefficients
+sub norm {
+    my(@x) = @_;
+    shift @x while @x && !$x[0];
+    return @x;
+}
+
+# multiply $self by the single term of power $n
+sub multerm {
+    my($self, $n) = @_;
+    return $self->new(@$self, (0) x $n);
+}
+
+# This is really an order comparison; different polys of same order
+# compare equal.  It also assumes prior normalization.
+sub pcmp {
+    my @x = @{+shift};
+    my @y = @{+shift};
+    return @x <=> @y;
+}
+
+# convenience constructor; takes list of non-zero terms
+sub powers2poly
+{
+    my $self = shift;
+    my $poly = $self->new;
+    my $n;
+    foreach $n (@_) {
+	$poly += $one->multerm($n);
+    }
+    return $poly;
+}
+
+sub add {
+    my $self = shift;
+    my @x = @$self;
+    my @y = @{+shift};
+    my @r;
+    unshift @r, (pop @x || 0) ^ (pop @y || 0)
+	while @x || @y;
+    return $self->new(@r);
+}
+
+sub mul {
+    my($self) = shift;
+    my @y = @{+shift};
+    my $r = $self->new;
+    my $power = 0;
+    while (@y) {
+	$r += $self->multerm($power) if pop @y;
+	$power++;
+    }
+    return $r;
+}
+
+sub oldmod {
+    my($self, $div) = @_;
+    my @num = @$self;
+    my @div = @$div;
+    my $r = $self->new(splice @num, 0, @div);
+    do {
+	push @$r, shift @num while @num && $r < $div;
+	$r += $div if $r >= $div;
+    } while @num;
+    return $r;
+}
+
+sub div {
+    my($self, $div) = @_;
+    my $q = $self->new;
+    my $r = $self->new(@$self);
+    my $one = $self->new(1);
+    my ($tp, $power);
+    croak "divide by zero" if !@$div;
+    while ($div <= $r) {
+	$power = 0;
+	$power++ while ($tp = $div->multerm($power)) < $r;
+	$q += $one->multerm($power);
+	$r -= $tp;
+    }
+    return wantarray ? ($q, $r) : $q;
+}
+
+sub mod {
+    (&div)[1];
+}
+
+# bits and octets both big-endian
+sub hex {
+    my @x = @{+shift};
+    my $minwidth = shift || 32;
+    unshift @x, 0 while @x % 8 || @x < $minwidth;
+    return unpack "H*", pack "B*", join "", @x;
+}
+
+# bit-reversal of above
+sub revhex {
+    my @x = @{+shift};
+    my $minwidth = shift || 32;
+    unshift @x, 0 while @x % 8 || @x < $minwidth;
+    return unpack "H*", pack "B*", join "", reverse @x;
+}
+
+$one = Poly->new(1);
+
+1;
diff --git a/krb5-1-6/src/lib/crypto/crc32/crc-32.h b/krb5-1-6/src/lib/crypto/crc32/crc-32.h
new file mode 100644
index 000000000..10facaa58
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crc32/crc-32.h
@@ -0,0 +1,71 @@
+/*
+ * include/krb5/crc-32.h
+ *
+ * Copyright 1989,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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
+
+void
+mit_crc32 (const krb5_pointer in, size_t in_length, unsigned long *c);
+
+#ifdef CRC32_SHIFT4
+void mit_crc32_shift4(const krb5_pointer /* in */,
+		      const size_t /* in_length */,
+		      unsigned long * /* cksum */);
+#endif
+
+#endif /* KRB5_CRC32__ */
diff --git a/krb5-1-6/src/lib/crypto/crc32/crc.pl b/krb5-1-6/src/lib/crypto/crc32/crc.pl
new file mode 100644
index 000000000..b21b6b15d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crc32/crc.pl
@@ -0,0 +1,111 @@
+# Copyright 2002 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+use CRC;
+
+print "*** crudely testing polynomial functions ***\n";
+
+$x = Poly->new(1,1,1,1);
+$y = Poly->new(1,1);
+print "x = @{[$x->pretty]}\ny = @{[$y->pretty]}\n";
+$q = $x / $y;
+$r = $x % $y;
+print $x->pretty, " = (", $y->pretty , ") * (", $q->pretty,
+    ") + ", $r->pretty, "\n";
+$q = $y / $x;
+$r = $y % $x;
+print "y / x = @{[$q->pretty]}\ny % x = @{[$r->pretty]}\n";
+
+# ISO 3309 32-bit FCS polynomial
+$fcs32 = Poly->powers2poly(32,26,23,22,16,12,11,10,8,7,5,4,2,1,0);
+print "fcs32 = ", $fcs32->pretty, "\n";
+
+$crc = CRC->new(Poly => $fcs32, bitsendian => "little");
+
+print "\n";
+
+print "*** little endian, no complementation ***\n";
+for ($i = 0; $i < 256; $i++) {
+    $r = $crc->crcstring(pack "C", $i);
+    printf ("%02x: ", $i) if !($i % 8);
+    print ($r->revhex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+print "\n";
+
+print "*** little endian, 4 bits, no complementation ***\n";
+for ($i = 0; $i < 16; $i++) {
+    @m = (split //, unpack "b*", pack "C", $i)[0..3];
+    $r = $crc->crc(@m);
+    printf ("%02x: ", $i) if !($i % 8);
+    print ($r->revhex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+print "\n";
+
+print "*** test vectors for t_crc.c, little endian ***\n";
+for ($i = 1; $i <= 4; $i *=2) {
+    for ($j = 0; $j < $i * 8; $j++) {
+	@m = split //, unpack "b*", pack "V", 1 << $j;
+	splice @m, $i * 8;
+	$r = $crc->crc(@m);
+	$m = unpack "H*", pack "b*", join("", @m);
+	print "{HEX, \"$m\", 0x", $r->revhex, "},\n";
+    }
+}
+@m = ("foo", "test0123456789",
+      "MASSACHVSETTS INSTITVTE OF TECHNOLOGY");
+foreach $m (@m) {
+    $r = $crc->crcstring($m);
+    print "{STR, \"$m\", 0x", $r->revhex, "},\n";
+}
+__END__
+
+print "*** big endian, no complementation ***\n";
+for ($i = 0; $i < 256; $i++) {
+    $r = $crc->crcstring(pack "C", $i);
+    printf ("%02x: ", $i) if !($i % 8);
+    print ($r->hex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+# all ones polynomial of order 31
+$ones = Poly->new((1) x 32);
+
+print "*** big endian, ISO-3309 style\n";
+$crc = CRC->new(Poly => $fcs32,
+		bitsendian => "little",
+		precomp => $ones,
+		postcomp => $ones);
+for ($i = 0; $i < 256; $i++) {
+    $r = $crc->crcstring(pack "C", $i);
+    print ($r->hex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+for ($i = 0; $i < 0; $i++) {
+    $x = Poly->new((1) x 32, (0) x $i);
+    $y = Poly->new((1) x 32);
+    $f = ($x % $fcs32) + $y;
+    $r = (($f + $x) * Poly->powers2poly(32)) % $fcs32;
+    @out = @$r;
+    unshift @out, 0 while @out < 32;
+    print @out, "\n";
+}
diff --git a/krb5-1-6/src/lib/crypto/crc32/crc32.c b/krb5-1-6/src/lib/crypto/crc32/crc32.c
new file mode 100644
index 000000000..ef65476d9
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crc32/crc32.c
@@ -0,0 +1,192 @@
+/*
+ * lib/crypto/crc32/crc.c
+ *
+ * Copyright 1990, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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(krb5_pointer in, 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;
+}
+
+#ifdef CRC32_SHIFT4
+static unsigned long const tbl4[16] = {
+    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+};
+
+void
+mit_crc32_shift4(krb5_pointer in, size_t in_length, unsigned long *cksum)
+{
+    register unsigned char *data, b;
+    register unsigned long c = 0;
+    size_t i;
+
+    data = (u_char *)in;
+    for (i = 0; i < in_length; i++) {
+	b = data[i];
+	c = (c >> 4) ^ tbl4[(b ^ c) & 0x0f];
+	b >>= 4;
+	c = (c >> 4) ^ tbl4[(b ^ c) & 0x0f];
+    }
+    *cksum = c;
+}
+#endif
diff --git a/krb5-1-6/src/lib/crypto/crc32/t_crc.c b/krb5-1-6/src/lib/crypto/crc32/t_crc.c
new file mode 100644
index 000000000..e8a353a0b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crc32/t_crc.c
@@ -0,0 +1,213 @@
+/*
+ * lib/crypto/crc32/t_crc.c
+ *
+ * Copyright 2002,2005 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Sanity checks for CRC32.
+ */
+#include <sys/times.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "k5-int.h"
+#include "crc-32.h"
+
+#define HEX 1
+#define STR 2
+struct crc_trial {
+    int		type;
+    char	*data;
+    unsigned long	sum;
+};
+
+struct crc_trial trials[] = {
+    {HEX, "01", 0x77073096},
+    {HEX, "02", 0xee0e612c},
+    {HEX, "04", 0x076dc419},
+    {HEX, "08", 0x0edb8832},
+    {HEX, "10", 0x1db71064},
+    {HEX, "20", 0x3b6e20c8},
+    {HEX, "40", 0x76dc4190},
+    {HEX, "80", 0xedb88320},
+    {HEX, "0100", 0x191b3141},
+    {HEX, "0200", 0x32366282},
+    {HEX, "0400", 0x646cc504},
+    {HEX, "0800", 0xc8d98a08},
+    {HEX, "1000", 0x4ac21251},
+    {HEX, "2000", 0x958424a2},
+    {HEX, "4000", 0xf0794f05},
+    {HEX, "8000", 0x3b83984b},
+    {HEX, "0001", 0x77073096},
+    {HEX, "0002", 0xee0e612c},
+    {HEX, "0004", 0x076dc419},
+    {HEX, "0008", 0x0edb8832},
+    {HEX, "0010", 0x1db71064},
+    {HEX, "0020", 0x3b6e20c8},
+    {HEX, "0040", 0x76dc4190},
+    {HEX, "0080", 0xedb88320},
+    {HEX, "01000000", 0xb8bc6765},
+    {HEX, "02000000", 0xaa09c88b},
+    {HEX, "04000000", 0x8f629757},
+    {HEX, "08000000", 0xc5b428ef},
+    {HEX, "10000000", 0x5019579f},
+    {HEX, "20000000", 0xa032af3e},
+    {HEX, "40000000", 0x9b14583d},
+    {HEX, "80000000", 0xed59b63b},
+    {HEX, "00010000", 0x01c26a37},
+    {HEX, "00020000", 0x0384d46e},
+    {HEX, "00040000", 0x0709a8dc},
+    {HEX, "00080000", 0x0e1351b8},
+    {HEX, "00100000", 0x1c26a370},
+    {HEX, "00200000", 0x384d46e0},
+    {HEX, "00400000", 0x709a8dc0},
+    {HEX, "00800000", 0xe1351b80},
+    {HEX, "00000100", 0x191b3141},
+    {HEX, "00000200", 0x32366282},
+    {HEX, "00000400", 0x646cc504},
+    {HEX, "00000800", 0xc8d98a08},
+    {HEX, "00001000", 0x4ac21251},
+    {HEX, "00002000", 0x958424a2},
+    {HEX, "00004000", 0xf0794f05},
+    {HEX, "00008000", 0x3b83984b},
+    {HEX, "00000001", 0x77073096},
+    {HEX, "00000002", 0xee0e612c},
+    {HEX, "00000004", 0x076dc419},
+    {HEX, "00000008", 0x0edb8832},
+    {HEX, "00000010", 0x1db71064},
+    {HEX, "00000020", 0x3b6e20c8},
+    {HEX, "00000040", 0x76dc4190},
+    {HEX, "00000080", 0xedb88320},
+    {STR, "foo", 0x7332bc33},
+    {STR, "test0123456789", 0xb83e88d6},
+    {STR, "MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 0xe34180f7}
+};
+
+#define NTRIALS (sizeof(trials) / sizeof(trials[0]))
+
+static void
+timetest(unsigned int nblk, unsigned int blksiz)
+{
+    char *block;
+    int i;
+    struct tms before, after;
+    unsigned long cksum;
+
+    block = malloc(blksiz * nblk);
+    if (block == NULL)
+	exit(1);
+    for (i = 0; i < blksiz * nblk; i++)
+	block[i] = i % 256;
+    times(&before);
+    for (i = 0; i < nblk; i++) {
+	mit_crc32(block + i * blksiz, blksiz, &cksum);
+    }
+
+    times(&after);
+    printf("shift-8 implementation, %d blocks of %d bytes:\n",
+	   nblk, blksiz);
+    printf("\tu=%ld s=%ld cu=%ld cs=%ld\n",
+	   (long)(after.tms_utime - before.tms_utime),
+	   (long)(after.tms_stime - before.tms_stime),
+	   (long)(after.tms_cutime - before.tms_cutime),
+	   (long)(after.tms_cstime - before.tms_cstime));
+
+#ifdef CRC32_SHIFT4
+    times(&before);
+    for (i = 0; i < nblk; i++) {
+	mit_crc32_shift4(block + i * blksiz, blksiz, &cksum);
+    }
+    times(&after);
+    printf("shift-4 implementation, %d blocks of %d bytes:\n",
+	   nblk, blksiz);
+    printf("\tu=%ld s=%ld cu=%ld cs=%ld\n",
+	   (long)(after.tms_utime - before.tms_utime),
+	   (long)(after.tms_stime - before.tms_stime),
+	   (long)(after.tms_cutime - before.tms_cutime),
+	   (long)(after.tms_cstime - before.tms_cstime));
+#endif
+    free(block);
+}
+
+static void gethexstr(char *data, size_t *outlen, unsigned char *outbuf,
+		      size_t buflen)
+{
+    size_t inlen;
+    char *cp, buf[3];
+    long n;
+
+    inlen = strlen(data);
+    *outlen = 0;
+    for (cp = data; cp - data < inlen; cp += 2) {
+	strncpy(buf, cp, 2);
+	buf[2] = '\0';
+	n = strtol(buf, NULL, 16);
+	outbuf[(*outlen)++] = n;
+	if (*outlen > buflen)
+	    break;
+    }
+}
+
+static void
+verify(void)
+{
+    int i;
+    struct crc_trial trial;
+    unsigned char buf[4];
+    size_t len;
+    unsigned long cksum;
+    char *typestr;
+
+    for (i = 0; i < NTRIALS; i++) {
+	trial = trials[i];
+	switch (trial.type) {
+	case STR:
+	    len = strlen(trial.data);
+	    typestr = "STR";
+	    mit_crc32(trial.data, len, &cksum);
+	    break;
+	case HEX:
+	    typestr = "HEX";
+	    gethexstr(trial.data, &len, buf, 4);
+	    mit_crc32(buf, len, &cksum);
+	    break;
+	default:
+	    typestr = "BOGUS";
+	    fprintf(stderr, "bad trial type %d\n", trial.type);
+	    exit(1);
+	}
+	printf("%s: %s \"%s\" = 0x%08lx\n",
+	       (trial.sum == cksum) ? "OK" : "***BAD***",
+	       typestr, trial.data, cksum);
+    }
+}
+
+int
+main(void)
+{
+#if 0
+    timetest(64*1024, 1024);
+#endif
+    verify();
+    exit(0);
+}
diff --git a/krb5-1-6/src/lib/crypto/crypto_libinit.c b/krb5-1-6/src/lib/crypto/crypto_libinit.c
new file mode 100644
index 000000000..91bf8ac22
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/crypto_libinit.c
@@ -0,0 +1,33 @@
+#include <assert.h>
+#include "k5-int.h"
+
+MAKE_INIT_FUNCTION(cryptoint_initialize_library);
+MAKE_FINI_FUNCTION(cryptoint_cleanup_library);
+
+extern int krb5int_prng_init(void);
+extern void krb5int_prng_cleanup (void);
+
+/*
+ * Initialize the crypto library.
+ */
+
+int cryptoint_initialize_library (void)
+{
+    return krb5int_prng_init();
+}
+
+int krb5int_crypto_init(void)
+{
+    return CALL_INIT_FUNCTION(cryptoint_initialize_library);
+}
+
+/*
+ * Clean up the crypto library state
+ */
+
+void cryptoint_cleanup_library (void)
+{
+    if (!INITIALIZER_RAN(cryptoint_initialize_library))
+	return;
+    krb5int_prng_cleanup ();
+}
diff --git a/krb5-1-6/src/lib/crypto/decrypt.c b/krb5-1-6/src/lib/crypto/decrypt.c
new file mode 100644
index 000000000..c252eb7c2
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/decrypt.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_error_code KRB5_CALLCONV
+krb5_c_decrypt(krb5_context context, const krb5_keyblock *key,
+	       krb5_keyusage usage, const krb5_data *ivec,
+	       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/krb5-1-6/src/lib/crypto/default_state.c b/krb5-1-6/src/lib/crypto/default_state.c
new file mode 100644
index 000000000..33a189f26
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/default_state.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2001 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Section 6 (Encryption) of the Kerberos revisions document defines
+ * cipher states to be used to chain encryptions and decryptions
+ * together.  Examples of cipher states include initialization vectors
+ * for CBC encription.  Most Kerberos encryption systems can share
+ * code for initializing and freeing cipher states.  This file
+ * contains that default code.
+ */
+
+#include "k5-int.h"
+
+krb5_error_code krb5int_des_init_state
+(const krb5_keyblock *key, krb5_keyusage usage, krb5_data *new_state )
+{
+  new_state->length = 8;
+  new_state->data = (void *) malloc(8);
+  if (new_state->data) {
+    memset (new_state->data, 0, new_state->length);
+    /* We need to copy in the key for des-cbc-cr--ick, but that's how it works*/
+    if (key->enctype == ENCTYPE_DES_CBC_CRC) {
+      memcpy (new_state->data, key->contents, new_state->length);
+  }
+  } else {
+    return ENOMEM;
+  }
+  return 0;
+}
+
+krb5_error_code krb5int_default_free_state
+(krb5_data *state)
+{
+  if (state->data) {
+    free (state->data);
+    state-> data = NULL;
+    state->length = 0;
+  }
+  return 0;
+}
+
+    
+  
diff --git a/krb5-1-6/src/lib/crypto/des/ISSUES b/krb5-1-6/src/lib/crypto/des/ISSUES
new file mode 100644
index 000000000..412f94aa7
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/ISSUES
@@ -0,0 +1,13 @@
+Issues to be addressed for src/lib/crypto/des: -*- text -*-
+
+
+"const" could be used in more places
+
+
+Array types are used in calling interfaces.  Under ANSI C, a value of
+type "arraytype *" cannot be assigned to a variable of type "const
+arraytype *", so we get compilation warnings.
+
+Possible fix: Rewrite internal interfaces to not use arrays this way.
+Provide external routines compatible with old API, but not using
+const?
diff --git a/krb5-1-6/src/lib/crypto/des/Makefile.in b/krb5-1-6/src/lib/crypto/des/Makefile.in
new file mode 100644
index 000000000..5cf6de60a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/Makefile.in
@@ -0,0 +1,209 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/des
+mydir=lib/crypto/des
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=des
+##DOS##OBJFILE=..\$(OUTPRE)des.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS=\
+	afsstring2key.o	\
+	d3_cbc.o	\
+	d3_kysched.o	\
+	f_cbc.o 	\
+	f_cksum.o	\
+	f_parity.o 	\
+	f_sched.o 	\
+	f_tables.o	\
+	key_sched.o	\
+	string2key.o	\
+	weak_key.o
+
+OBJS=	$(OUTPRE)afsstring2key.$(OBJEXT)	\
+	$(OUTPRE)d3_cbc.$(OBJEXT)	\
+	$(OUTPRE)d3_kysched.$(OBJEXT)	\
+	$(OUTPRE)f_cbc.$(OBJEXT) 	\
+	$(OUTPRE)f_cksum.$(OBJEXT)	\
+	$(OUTPRE)f_parity.$(OBJEXT) 	\
+	$(OUTPRE)f_sched.$(OBJEXT) 	\
+	$(OUTPRE)f_tables.$(OBJEXT)	\
+	$(OUTPRE)key_sched.$(OBJEXT)	\
+	$(OUTPRE)string2key.$(OBJEXT)	\
+	$(OUTPRE)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)/string2key.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+TOBJS = $(OUTPRE)key_sched.$(OBJEXT) $(OUTPRE)f_sched.$(OBJEXT) $(OUTPRE)f_cbc.$(OBJEXT) \
+	$(OUTPRE)f_tables.$(OBJEXT) $(OUTPRE)f_cksum.$(OBJEXT)
+
+verify$(EXEEXT): t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \
+	$(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \
+		-lcom_err $(SUPPORT_LIB)
+
+destest$(EXEEXT): destest.$(OBJEXT) $(TOBJS) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ destest.$(OBJEXT) $(TOBJS) $(SUPPORT_LIB)
+
+TAFSS2KOBJS =								\
+	t_afss2k.$(OBJEXT) $(TOBJS)					\
+	afsstring2key.$(OBJEXT) f_parity.$(OBJEXT) weak_key.$(OBJEXT)
+
+t_afss2k$(EXEEXT): $(TAFSS2KOBJS) $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ $(TAFSS2KOBJS) -lcom_err $(SUPPORT_LIB)
+
+check-unix:: verify destest t_afss2k
+	$(RUN_SETUP) $(VALGRIND) ./verify -z
+	$(RUN_SETUP) $(VALGRIND) ./verify -m
+	$(RUN_SETUP) $(VALGRIND) ./verify
+	$(RUN_SETUP) $(VALGRIND) ./destest < $(srcdir)/keytest.data
+	$(RUN_SETUP) $(VALGRIND) ./t_afss2k
+
+check-windows::
+
+clean:: 
+	$(RM) destest$(EXEEXT) verify$(EXEEXT) destest.$(OBJEXT) \
+	t_verify.$(OBJEXT) t_afss2k.$(OBJEXT) t_afss2k$(EXEEXT)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+afsstring2key.so afsstring2key.po $(OUTPRE)afsstring2key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  afsstring2key.c des_int.h
+d3_cbc.so d3_cbc.po $(OUTPRE)d3_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h d3_cbc.c des_int.h \
+  f_tables.h
+d3_kysched.so d3_kysched.po $(OUTPRE)d3_kysched.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  d3_kysched.c des_int.h
+f_cbc.so f_cbc.po $(OUTPRE)f_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h des_int.h f_cbc.c \
+  f_tables.h
+f_cksum.so f_cksum.po $(OUTPRE)f_cksum.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h des_int.h f_cksum.c \
+  f_tables.h
+f_parity.so f_parity.po $(OUTPRE)f_parity.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  des_int.h f_parity.c
+f_sched.so f_sched.po $(OUTPRE)f_sched.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h des_int.h f_sched.c
+f_tables.so f_tables.po $(OUTPRE)f_tables.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  des_int.h f_tables.c f_tables.h
+key_sched.so key_sched.po $(OUTPRE)key_sched.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  des_int.h key_sched.c
+weak_key.so weak_key.po $(OUTPRE)weak_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  des_int.h weak_key.c
+string2key.so string2key.po $(OUTPRE)string2key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  des_int.h string2key.c
diff --git a/krb5-1-6/src/lib/crypto/des/afsstring2key.c b/krb5-1-6/src/lib/crypto/des/afsstring2key.c
new file mode 100644
index 000000000..97ec2d8a1
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/afsstring2key.c
@@ -0,0 +1,570 @@
+/*
+ * lib/crypto/des/string2key.c
+ *
+ * based on lib/crypto/des/string2key.c from MIT V5 
+ * and on lib/des/afs_string_to_key.c from UMD.
+ * constructed by Mark Eichin, Cygnus Support, 1995.
+ * made thread-safe by Ken Raeburn, MIT, 2001.
+ */
+
+/*
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Copyright (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>
+
+#define afs_crypt mit_afs_crypt
+char *afs_crypt (const char *, const char *, char *);
+
+#undef min
+#define min(a,b) ((a)>(b)?(b):(a))
+
+krb5_error_code
+mit_afs_string_to_key (krb5_keyblock *keyblock, const krb5_data *data,
+		       const krb5_data *salt)
+{
+  /* totally different approach from MIT string2key. */
+  /* much of the work has already been done by the only caller 
+     which is mit_des_string_to_key; in particular, *keyblock is already 
+     set up. */
+  
+    char *realm = salt->data;
+    unsigned int i, j;
+    krb5_octet *key = keyblock->contents;
+
+    if (data->length <= 8) {
+      /* One block only.  Run afs_crypt and use the first eight
+	 returned bytes after the copy of the (fixed) salt.
+
+	 Since the returned bytes are alphanumeric, the output is
+	 limited to 2**48 possibilities; for each byte, only 64
+	 possible values can be used.  */
+      unsigned char password[9]; /* trailing nul for crypt() */
+      char afs_crypt_buf[16];
+
+      memset (password, 0, sizeof (password));
+      memcpy (password, realm, min (salt->length, 8));
+      for (i=0; i<8; i++)
+	if (isupper(password[i]))
+	  password[i] = tolower(password[i]);
+      for (i=0; i<data->length; i++)
+	password[i] ^= data->data[i];
+      for (i=0; i<8; i++)
+	if (password[i] == '\0')
+	  password[i] = 'X';
+      password[8] = '\0';
+      /* Out-of-bounds salt characters are equivalent to a salt string
+	 of "p1".  */
+      strncpy((char *) key,
+	      (char *) afs_crypt((char *) password, "#~", afs_crypt_buf) + 2,
+	      8);
+      for (i=0; i<8; i++)
+	key[i] <<= 1;
+      /* now fix up key parity again */
+      mit_des_fixup_key_parity(key);
+      /* clean & free the input string */
+      memset(password, 0, (size_t) sizeof(password));
+    } else {
+      /* Multiple blocks.  Do a CBC checksum, twice, and use the
+	 result as the new key.  */
+      mit_des_cblock ikey, tkey;
+      mit_des_key_schedule key_sked;
+      unsigned int pw_len = salt->length+data->length;
+      unsigned char *password = malloc(pw_len+1);
+      if (!password) return ENOMEM;
+
+      /* Some bound checks from the original code are elided here as
+	 the malloc above makes sure we have enough storage. */
+      memcpy (password, data->data, data->length);
+      for (i=data->length, j = 0; j < salt->length; i++, j++) {
+	password[i] = realm[j];
+	if (isupper(password[i]))
+	  password[i] = tolower(password[i]);
+      }
+	
+      memcpy (ikey, "kerberos", sizeof(ikey));
+      memcpy (tkey, ikey, sizeof(tkey));
+      mit_des_fixup_key_parity (tkey);
+      (void) mit_des_key_sched (tkey, key_sked);
+      (void) mit_des_cbc_cksum (password, tkey, i, key_sked, ikey);
+
+      memcpy (ikey, tkey, sizeof(ikey));
+      mit_des_fixup_key_parity (tkey);
+      (void) mit_des_key_sched (tkey, key_sked);
+      (void) mit_des_cbc_cksum (password, key, i, key_sked, ikey);
+	
+      /* erase key_sked */
+      memset((char *)key_sked, 0,sizeof(key_sked));
+
+      /* now fix up key parity again */
+      mit_des_fixup_key_parity(key);
+      
+      /* clean & free the input string */
+      memset(password, 0, (size_t) pw_len);
+      krb5_xfree(password);
+    }
+#if 0
+    /* must free here because it was copied for this special case */
+    krb5_xfree(salt->data);
+#endif
+    return 0;
+}
+
+
+/* Portions of this code:
+   Copyright 1989 by the Massachusetts Institute of Technology
+   */
+ 
+/*
+ * Copyright (c) 1990 Regents of The University of Michigan.
+ * All Rights Reserved.
+ *
+ * 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 appears in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * The University of Michigan not be used in advertising or
+ * publicity pertaining to distribution of the software without
+ * specific, written prior permission. This software is supplied as
+ * is without expressed or implied warranties of any kind.
+ *
+ *	ITD Research Systems
+ *	University of Michigan
+ *	535 W. William Street
+ *	Ann Arbor, Michigan
+ *	+1-313-936-2652
+ *	netatalk@terminator.cc.umich.edu
+ */
+
+static void krb5_afs_crypt_setkey (char*, char*, char(*)[48]);
+static void krb5_afs_encrypt (char*,char*,char (*)[48]);
+
+/*
+ * Initial permutation,
+ */
+static const char	IP[] = {
+	58,50,42,34,26,18,10, 2,
+	60,52,44,36,28,20,12, 4,
+	62,54,46,38,30,22,14, 6,
+	64,56,48,40,32,24,16, 8,
+	57,49,41,33,25,17, 9, 1,
+	59,51,43,35,27,19,11, 3,
+	61,53,45,37,29,21,13, 5,
+	63,55,47,39,31,23,15, 7,
+};
+ 
+/*
+ * Final permutation, FP = IP^(-1)
+ */
+static const char	FP[] = {
+	40, 8,48,16,56,24,64,32,
+	39, 7,47,15,55,23,63,31,
+	38, 6,46,14,54,22,62,30,
+	37, 5,45,13,53,21,61,29,
+	36, 4,44,12,52,20,60,28,
+	35, 3,43,11,51,19,59,27,
+	34, 2,42,10,50,18,58,26,
+	33, 1,41, 9,49,17,57,25,
+};
+ 
+/*
+ * Permuted-choice 1 from the key bits to yield C and D.
+ * Note that bits 8,16... are left out: They are intended for a parity check.
+ */
+static const char	PC1_C[] = {
+	57,49,41,33,25,17, 9,
+	 1,58,50,42,34,26,18,
+	10, 2,59,51,43,35,27,
+	19,11, 3,60,52,44,36,
+};
+ 
+static const char	PC1_D[] = {
+	63,55,47,39,31,23,15,
+	 7,62,54,46,38,30,22,
+	14, 6,61,53,45,37,29,
+	21,13, 5,28,20,12, 4,
+};
+ 
+/*
+ * Sequence of shifts used for the key schedule.
+ */
+static const char	shifts[] = {
+	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
+};
+ 
+/*
+ * Permuted-choice 2, to pick out the bits from
+ * the CD array that generate the key schedule.
+ */
+static const char	PC2_C[] = {
+	14,17,11,24, 1, 5,
+	 3,28,15, 6,21,10,
+	23,19,12, 4,26, 8,
+	16, 7,27,20,13, 2,
+};
+ 
+static const char	PC2_D[] = {
+	41,52,31,37,47,55,
+	30,40,51,45,33,48,
+	44,49,39,56,34,53,
+	46,42,50,36,29,32,
+};
+ 
+/*
+ * The E bit-selection table.
+ */
+static const char	e[] = {
+	32, 1, 2, 3, 4, 5,
+	 4, 5, 6, 7, 8, 9,
+	 8, 9,10,11,12,13,
+	12,13,14,15,16,17,
+	16,17,18,19,20,21,
+	20,21,22,23,24,25,
+	24,25,26,27,28,29,
+	28,29,30,31,32, 1,
+};
+ 
+/*
+ * P is a permutation on the selected combination
+ * of the current L and key.
+ */
+static const char	P[] = {
+	16, 7,20,21,
+	29,12,28,17,
+	 1,15,23,26,
+	 5,18,31,10,
+	 2, 8,24,14,
+	32,27, 3, 9,
+	19,13,30, 6,
+	22,11, 4,25,
+};
+ 
+/*
+ * The 8 selection functions.
+ * For some reason, they give a 0-origin
+ * index, unlike everything else.
+ */
+static const char	S[8][64] = {
+	{14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
+	  0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
+	  4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
+	 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13},
+ 
+	{15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
+	  3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
+	  0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
+	 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9},
+ 
+	{10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
+	 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
+	 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
+	  1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12},
+ 
+	{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
+	 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
+	 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
+	  3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14},
+ 
+	{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
+	 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
+	  4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
+	 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3},
+ 
+	{12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
+	 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
+	  9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
+	  4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13},
+ 
+	{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
+	 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
+	  1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
+	  6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12},
+ 
+	{13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
+	  1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
+	  7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
+	  2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11},
+};
+ 
+ 
+char *afs_crypt(const char *pw, const char *salt,
+		/* must be at least 16 bytes */
+		char *iobuf)
+{
+	int i, j, c;
+	int temp;
+	char block[66];
+	char E[48];
+	/*
+	 * The key schedule.
+	 * Generated from the key.
+	 */
+	char KS[16][48];
+ 
+	for(i=0; i<66; i++)
+		block[i] = 0;
+	for(i=0; (c= *pw) && i<64; pw++){
+		for(j=0; j<7; j++, i++)
+			block[i] = (c>>(6-j)) & 01;
+		i++;
+	}
+	
+	krb5_afs_crypt_setkey(block, E, KS);
+
+	for(i=0; i<66; i++)
+		block[i] = 0;
+
+	for(i=0;i<2;i++){
+		c = *salt++;
+		iobuf[i] = c;
+		if(c>'Z') c -= 6;
+		if(c>'9') c -= 7;
+		c -= '.';
+		for(j=0;j<6;j++){
+			if((c>>j) & 01){
+				temp = E[6*i+j];
+				E[6*i+j] = E[6*i+j+24];
+				E[6*i+j+24] = temp;
+				}
+			}
+		}
+	
+	for(i=0; i<25; i++)
+		krb5_afs_encrypt(block,E,KS);
+	
+	for(i=0; i<11; i++){
+		c = 0;
+		for(j=0; j<6; j++){
+			c <<= 1;
+			c |= block[6*i+j];
+			}
+		c += '.';
+		if(c>'9') c += 7;
+		if(c>'Z') c += 6;
+		iobuf[i+2] = c;
+	}
+	iobuf[i+2] = 0;
+	if(iobuf[1]==0)
+		iobuf[1] = iobuf[0];
+	return(iobuf);
+}
+
+/*
+ * Set up the key schedule from the key.
+ */
+ 
+static void krb5_afs_crypt_setkey(char *key, char *E, char (*KS)[48])
+{
+	register int i, j, k;
+	int t;
+	/*
+	 * The C and D arrays used to calculate the key schedule.
+	 */
+	char C[28], D[28];
+ 
+	/*
+	 * First, generate C and D by permuting
+	 * the key.  The low order bit of each
+	 * 8-bit char is not used, so C and D are only 28
+	 * bits apiece.
+	 */
+	for (i=0; i<28; i++) {
+		C[i] = key[PC1_C[i]-1];
+		D[i] = key[PC1_D[i]-1];
+	}
+	/*
+	 * To generate Ki, rotate C and D according
+	 * to schedule and pick up a permutation
+	 * using PC2.
+	 */
+	for (i=0; i<16; i++) {
+		/*
+		 * rotate.
+		 */
+		for (k=0; k<shifts[i]; k++) {
+			t = C[0];
+			for (j=0; j<28-1; j++)
+				C[j] = C[j+1];
+			C[27] = t;
+			t = D[0];
+			for (j=0; j<28-1; j++)
+				D[j] = D[j+1];
+			D[27] = t;
+		}
+		/*
+		 * get Ki. Note C and D are concatenated.
+		 */
+		for (j=0; j<24; j++) {
+			KS[i][j] = C[PC2_C[j]-1];
+			KS[i][j+24] = D[PC2_D[j]-28-1];
+		}
+	}
+ 
+#if 0
+	for(i=0;i<48;i++) {
+		E[i] = e[i];
+	}
+#else
+	memcpy(E, e, 48);
+#endif
+}
+ 
+/*
+ * The payoff: encrypt a block.
+ */
+ 
+static void krb5_afs_encrypt(char *block, char *E, char (*KS)[48])
+{
+	const long edflag = 0;
+	int i, ii;
+	int t, j, k;
+	char tempL[32];
+	char f[32];
+	/*
+	 * The current block, divided into 2 halves.
+	 */
+	char L[64];
+	char *const R = &L[32];
+	/*
+	 * The combination of the key and the input, before selection.
+	 */
+	char preS[48];
+
+	/*
+	 * First, permute the bits in the input
+	 */
+	for (j=0; j<64; j++)
+		L[j] = block[IP[j]-1];
+	/*
+	 * Perform an encryption operation 16 times.
+	 */
+	for (ii=0; ii<16; ii++) {
+		/*
+		 * Set direction
+		 */
+		if (edflag)
+			i = 15-ii;
+		else
+			i = ii;
+		/*
+		 * Save the R array,
+		 * which will be the new L.
+		 */
+#if 0
+		for (j=0; j<32; j++)
+			tempL[j] = R[j];
+#else
+		memcpy(tempL, R, 32);
+#endif
+		/*
+		 * Expand R to 48 bits using the E selector;
+		 * exclusive-or with the current key bits.
+		 */
+		for (j=0; j<48; j++)
+			preS[j] = R[E[j]-1] ^ KS[i][j];
+		/*
+		 * The pre-select bits are now considered
+		 * in 8 groups of 6 bits each.
+		 * The 8 selection functions map these
+		 * 6-bit quantities into 4-bit quantities
+		 * and the results permuted
+		 * to make an f(R, K).
+		 * The indexing into the selection functions
+		 * is peculiar; it could be simplified by
+		 * rewriting the tables.
+		 */
+		for (j=0; j<8; j++) {
+			t = 6*j;
+			k = S[j][(preS[t+0]<<5)+
+				(preS[t+1]<<3)+
+				(preS[t+2]<<2)+
+				(preS[t+3]<<1)+
+				(preS[t+4]<<0)+
+				(preS[t+5]<<4)];
+			t = 4*j;
+				f[t+0] = (k>>3)&01;
+				f[t+1] = (k>>2)&01;
+				f[t+2] = (k>>1)&01;
+				f[t+3] = (k>>0)&01;
+		}
+		/*
+		 * The new R is L ^ f(R, K).
+		 * The f here has to be permuted first, though.
+		 */
+		for (j=0; j<32; j++)
+			R[j] = L[j] ^ f[P[j]-1];
+		/*
+		 * Finally, the new L (the original R)
+		 * is copied back.
+		 */
+#if 0
+		for (j=0; j<32; j++)
+			L[j] = tempL[j];
+#else
+		memcpy(L, tempL, 32);
+#endif
+	}
+	/*
+	 * The output L and R are reversed.
+	 */
+	for (j=0; j<32; j++) {
+		t = L[j];
+		L[j] = R[j];
+		R[j] = t;
+	}
+	/*
+	 * The final output
+	 * gets the inverse permutation of the very original.
+	 */
+	for (j=0; j<64; j++)
+		block[j] = L[FP[j]-1];
+}
diff --git a/krb5-1-6/src/lib/crypto/des/d3_cbc.c b/krb5-1-6/src/lib/crypto/des/d3_cbc.c
new file mode 100644
index 000000000..37c32c76f
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/d3_cbc.c
@@ -0,0 +1,226 @@
+/*
+ * 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 CBC encryption mode.
+ */
+
+#undef mit_des3_cbc_encrypt
+int
+mit_des3_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
+		     unsigned long length, const mit_des_key_schedule ks1,
+		     const mit_des_key_schedule ks2,
+		     const mit_des_key_schedule ks3,
+		     const mit_des_cblock ivec, int enc)
+{
+    if (enc)
+	krb5int_des3_cbc_encrypt(in, out, length, ks1, ks2, ks3, ivec);
+    else
+	krb5int_des3_cbc_decrypt(in, out, length, ks1, ks2, ks3, ivec);
+    return 0;
+}
+
+void
+krb5int_des3_cbc_encrypt(const mit_des_cblock *in,
+			 mit_des_cblock *out,
+			 unsigned long length,
+			 const mit_des_key_schedule ks1,
+			 const mit_des_key_schedule ks2,
+			 const mit_des_key_schedule ks3,
+			 const mit_des_cblock ivec)
+{
+    unsigned DES_INT32 left, right;
+    const unsigned DES_INT32 *kp1, *kp2, *kp3;
+    const unsigned char *ip;
+    unsigned char *op;
+
+    /*
+     * Get key pointer here.  This won't need to be reinitialized
+     */
+    kp1 = (const unsigned DES_INT32 *)ks1;
+    kp2 = (const unsigned DES_INT32 *)ks2;
+    kp3 = (const unsigned DES_INT32 *)ks3;
+
+    /*
+     * Initialize left and right with the contents of the initial
+     * vector.
+     */
+    ip = ivec;
+    GET_HALF_BLOCK(left, ip);
+    GET_HALF_BLOCK(right, ip);
+
+    /*
+     * Suitably initialized, now work the length down 8 bytes
+     * at a time.
+     */
+    ip = *in;
+    op = *out;
+    while (length > 0) {
+	/*
+	 * Get more input, xor it in.  If the length is
+	 * greater than or equal to 8 this is straight
+	 * forward.  Otherwise we have to fart around.
+	 */
+	if (length >= 8) {
+	    left  ^= ((*ip++) & FF_UINT32) << 24;
+	    left  ^= ((*ip++) & FF_UINT32) << 16;
+	    left  ^= ((*ip++) & FF_UINT32) <<  8;
+	    left  ^=  (*ip++) & FF_UINT32;
+	    right ^= ((*ip++) & FF_UINT32) << 24;
+	    right ^= ((*ip++) & FF_UINT32) << 16;
+	    right ^= ((*ip++) & FF_UINT32) <<  8;
+	    right ^=  (*ip++) & FF_UINT32;
+	    length -= 8;
+	} else {
+	    /*
+	     * Oh, shoot.  We need to pad the
+	     * end with zeroes.  Work backwards
+	     * to do this.
+	     */
+	    ip += (int) length;
+	    switch(length) {
+	    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;
+
+	    }
+	    length = 0;
+	}
+
+	/*
+	 * Encrypt what we have
+	 */
+	DES_DO_ENCRYPT(left, right, kp1);
+	DES_DO_DECRYPT(left, right, kp2);
+	DES_DO_ENCRYPT(left, right, kp3);
+
+	/*
+	 * Copy the results out
+	 */
+	PUT_HALF_BLOCK(left, op);
+	PUT_HALF_BLOCK(right, op);
+    }
+}
+
+void
+krb5int_des3_cbc_decrypt(const mit_des_cblock *in,
+			 mit_des_cblock *out,
+			 unsigned long length,
+			 const mit_des_key_schedule ks1,
+			 const mit_des_key_schedule ks2,
+			 const mit_des_key_schedule ks3,
+			 const mit_des_cblock ivec)
+{
+    unsigned DES_INT32 left, right;
+    const unsigned DES_INT32 *kp1, *kp2, *kp3;
+    const unsigned char *ip;
+    unsigned char *op;
+    unsigned DES_INT32 ocipherl, ocipherr;
+    unsigned DES_INT32 cipherl, cipherr;
+
+    /*
+     * Get key pointer here.  This won't need to be reinitialized
+     */
+    kp1 = (const unsigned DES_INT32 *)ks1;
+    kp2 = (const unsigned DES_INT32 *)ks2;
+    kp3 = (const unsigned DES_INT32 *)ks3;
+
+    /*
+     * Decrypting is harder than encrypting because of
+     * the necessity of remembering a lot more things.
+     * Should think about this a little more...
+     */
+
+    if (length <= 0)
+	return;
+
+    /*
+     * Prime the old cipher with ivec.
+     */
+    ip = ivec;
+    GET_HALF_BLOCK(ocipherl, ip);
+    GET_HALF_BLOCK(ocipherr, ip);
+
+    /*
+     * Now do this in earnest until we run out of length.
+     */
+    ip = *in;
+    op = *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, kp3);
+	DES_DO_ENCRYPT(left, right, kp2);
+	DES_DO_DECRYPT(left, right, kp1);
+
+	/*
+	 * 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;
+	    ocipherr = cipherr;
+	} 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;		/* we're done */
+	}
+    }
+}
diff --git a/krb5-1-6/src/lib/crypto/des/d3_kysched.c b/krb5-1-6/src/lib/crypto/des/d3_kysched.c
new file mode 100644
index 000000000..f18cc2419
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/d3_kysched.c
@@ -0,0 +1,50 @@
+/*
+ * 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"
+
+int
+mit_des3_key_sched(mit_des3_cblock k, mit_des3_key_schedule schedule)
+{
+    mit_des_make_key_sched(k[0],schedule[0]);
+    mit_des_make_key_sched(k[1],schedule[1]);
+    mit_des_make_key_sched(k[2],schedule[2]);
+
+    if (!mit_des_check_key_parity(k[0]))	/* bad parity --> return -1 */
+	return(-1);
+    if (mit_des_is_weak_key(k[0]))
+	return(-2);
+
+    if (!mit_des_check_key_parity(k[1]))
+	return(-1);
+    if (mit_des_is_weak_key(k[1]))
+	return(-2);
+
+    if (!mit_des_check_key_parity(k[2]))
+	return(-1);
+    if (mit_des_is_weak_key(k[2]))
+	return(-2);
+
+    /* if key was good, return 0 */
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/des/des_int.h b/krb5-1-6/src/lib/crypto/des/des_int.h
new file mode 100644
index 000000000..c330a935a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/des_int.h
@@ -0,0 +1,305 @@
+/*
+ * lib/crypto/des/des_int.h
+ *
+ * Copyright 1987, 1988, 1990, 2002 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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
+
+#include "k5-int.h"
+/*
+ * Begin "mit-des.h"
+ */
+#ifndef KRB5_MIT_DES__
+#define KRB5_MIT_DES__
+
+#define KRB5INT_CRYPTO_DES_INT	/* skip krb4-specific DES stuff */
+#include "kerberosIV/des.h"	/* for des_key_schedule, etc. */
+#undef KRB5INT_CRYPTO_DES_INT	/* don't screw other inclusions of des.h */
+
+typedef des_cblock mit_des_cblock;
+typedef des_key_schedule mit_des_key_schedule;
+
+/* Triple-DES structures */
+typedef mit_des_cblock		mit_des3_cblock[3];
+typedef mit_des_key_schedule	mit_des3_key_schedule[3];
+
+#define MIT_DES_ENCRYPT	1
+#define MIT_DES_DECRYPT	0
+
+typedef struct mit_des_ran_key_seed {
+    krb5_encrypt_block eblock;
+    krb5_data sequence;
+} mit_des_random_state;
+
+/* the first byte of the key is already in the keyblock */
+
+#define MIT_DES_BLOCK_LENGTH 		(8*sizeof(krb5_octet))
+#define	MIT_DES_CBC_CRC_PAD_MINIMUM	CRC32_CKSUM_LENGTH
+/* This used to be 8*sizeof(krb5_octet) */
+#define MIT_DES_KEYSIZE		 	8
+
+#define MIT_DES_CBC_CKSUM_LENGTH	(4*sizeof(krb5_octet))
+
+/*
+ * Check if k5-int.h has been included before us.  If so, then check to see
+ * that our view of the DES key size is the same as k5-int.h's.
+ */
+#ifdef	KRB5_MIT_DES_KEYSIZE
+#if	MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE
+error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE)
+#endif	/* MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE */
+#endif	/* KRB5_MIT_DES_KEYSIZE */
+#endif /* KRB5_MIT_DES__ */
+/*
+ * End "mit-des.h"
+ */
+
+/* afsstring2key.c */
+extern krb5_error_code mit_afs_string_to_key
+	(krb5_keyblock *keyblock,
+		   const krb5_data *data,
+		   const krb5_data *salt);
+extern char *mit_afs_crypt
+    (const char *pw, const char *salt, char *iobuf);
+
+/* f_cksum.c */
+extern unsigned long mit_des_cbc_cksum
+    (const krb5_octet *, krb5_octet *, unsigned long ,
+     const mit_des_key_schedule, const krb5_octet *);
+
+/* f_ecb.c */
+extern int mit_des_ecb_encrypt
+    (const mit_des_cblock *, mit_des_cblock *, mit_des_key_schedule , int );
+
+/* f_cbc.c */
+extern int mit_des_cbc_encrypt (const mit_des_cblock *in,
+				mit_des_cblock *out,
+				unsigned long length,
+				const mit_des_key_schedule schedule,
+				const mit_des_cblock ivec, int enc);
+    
+#define mit_des_zeroblock krb5int_c_mit_des_zeroblock
+extern const mit_des_cblock mit_des_zeroblock;
+
+/* fin_rndkey.c */
+extern krb5_error_code mit_des_finish_random_key
+    ( const krb5_encrypt_block *,
+		krb5_pointer *);
+
+/* finish_key.c */
+extern krb5_error_code mit_des_finish_key
+    ( krb5_encrypt_block *);
+
+/* init_rkey.c */
+extern krb5_error_code mit_des_init_random_key
+    ( const krb5_encrypt_block *,
+		const krb5_keyblock *,
+		krb5_pointer *);
+
+/* key_parity.c */
+extern void mit_des_fixup_key_parity (mit_des_cblock );
+extern int mit_des_check_key_parity (mit_des_cblock );
+
+/* key_sched.c */
+extern int mit_des_key_sched
+    (mit_des_cblock , mit_des_key_schedule );
+
+/* process_ky.c */
+extern krb5_error_code mit_des_process_key
+    ( krb5_encrypt_block *,  const krb5_keyblock *);
+
+/* random_key.c */
+extern krb5_error_code mit_des_random_key
+    ( const krb5_encrypt_block *, krb5_pointer ,
+                krb5_keyblock **);
+
+/* string2key.c */
+extern krb5_error_code mit_des_string_to_key
+    ( const krb5_encrypt_block *, 
+	       krb5_keyblock *, const krb5_data *, const krb5_data *);
+extern krb5_error_code mit_des_string_to_key_int
+	(krb5_keyblock *, const krb5_data *, const krb5_data *);
+
+/* weak_key.c */
+extern int mit_des_is_weak_key (mit_des_cblock );
+
+/* cmb_keys.c */
+krb5_error_code mit_des_combine_subkeys
+    (const krb5_keyblock *, const krb5_keyblock *,
+	       krb5_keyblock **);
+
+/* f_pcbc.c */
+int mit_des_pcbc_encrypt ();
+
+/* f_sched.c */
+int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule);
+
+
+/* misc.c */
+extern void swap_bits (char *);
+extern unsigned long long_swap_bits (unsigned long );
+extern unsigned long swap_six_bits_to_ansi (unsigned long );
+extern unsigned long swap_four_bits_to_ansi (unsigned long );
+extern unsigned long swap_bit_pos_1 (unsigned long );
+extern unsigned long swap_bit_pos_0 (unsigned long );
+extern unsigned long swap_bit_pos_0_to_ansi (unsigned long );
+extern unsigned long rev_swap_bit_pos_0 (unsigned long );
+extern unsigned long swap_byte_bits (unsigned long );
+extern unsigned long swap_long_bytes_bit_number (unsigned long );
+#ifdef FILE
+/* XXX depends on FILE being a #define! */
+extern void test_set (FILE *, const char *, int, const char *, int);
+#endif
+
+/* d3_ecb.c */
+extern int mit_des3_ecb_encrypt
+	(const mit_des_cblock *in,
+		   mit_des_cblock *out,
+		   mit_des_key_schedule sched1,
+		   mit_des_key_schedule sched2,
+		   mit_des_key_schedule sched3,
+		   int enc);
+
+/* d3_cbc.c */
+extern int mit_des3_cbc_encrypt
+	(const mit_des_cblock *in,
+	 mit_des_cblock *out,
+	 unsigned long length,
+	 const mit_des_key_schedule ks1,
+	 const mit_des_key_schedule ks2,
+	 const mit_des_key_schedule ks3,
+	 const mit_des_cblock ivec,
+	 int enc);
+
+void
+krb5int_des3_cbc_encrypt(const mit_des_cblock *in,
+			 mit_des_cblock *out,
+			 unsigned long length,
+			 const mit_des_key_schedule ks1,
+			 const mit_des_key_schedule ks2,
+			 const mit_des_key_schedule ks3,
+			 const mit_des_cblock ivec);
+void
+krb5int_des3_cbc_decrypt(const mit_des_cblock *in,
+			 mit_des_cblock *out,
+			 unsigned long length,
+			 const mit_des_key_schedule ks1,
+			 const mit_des_key_schedule ks2,
+			 const mit_des_key_schedule ks3,
+			 const mit_des_cblock ivec);
+
+
+#define mit_des3_cbc_encrypt(in,out,length,ks1,ks2,ks3,ivec,enc) \
+    ((enc ? krb5int_des3_cbc_encrypt : krb5int_des3_cbc_decrypt) \
+     (in, out, length, ks1, ks2, ks3, ivec), 0)
+
+void
+krb5int_des_cbc_encrypt(const mit_des_cblock *in,
+			mit_des_cblock *out,
+			unsigned long length,
+			const mit_des_key_schedule schedule,
+			const mit_des_cblock ivec);
+void
+krb5int_des_cbc_decrypt(const mit_des_cblock *in,
+			mit_des_cblock *out,
+			unsigned long length,
+			const mit_des_key_schedule schedule,
+			const mit_des_cblock ivec);
+
+#define mit_des_cbc_encrypt(in,out,length,schedule,ivec,enc) \
+    ((enc ? krb5int_des_cbc_encrypt : krb5int_des_cbc_decrypt) \
+     (in, out, length, schedule, ivec), 0)
+
+
+/* d3_procky.c */
+extern krb5_error_code mit_des3_process_key
+	(krb5_encrypt_block * eblock,
+		   const krb5_keyblock * keyblock);
+
+/* d3_kysched.c */
+extern int mit_des3_key_sched
+	(mit_des3_cblock key,
+		   mit_des3_key_schedule schedule);
+
+/* d3_str2ky.c */
+extern krb5_error_code mit_des3_string_to_key
+	(const krb5_encrypt_block * eblock,
+		   krb5_keyblock * keyblock,
+		   const krb5_data * data,
+		   const krb5_data * salt);
+
+/* u_nfold.c */
+extern krb5_error_code mit_des_n_fold
+	(const krb5_octet * input,
+		   const size_t in_len,
+		   krb5_octet * output,
+		   const size_t out_len);
+
+/* u_rn_key.c */
+extern int mit_des_is_weak_keyblock
+	(krb5_keyblock *keyblock);
+
+extern void mit_des_fixup_keyblock_parity
+	(krb5_keyblock *keyblock);
+
+extern krb5_error_code mit_des_set_random_generator_seed
+	(const krb5_data * seed,
+		   krb5_pointer random_state);
+
+extern krb5_error_code mit_des_set_random_sequence_number
+	(const krb5_data * sequence,
+		   krb5_pointer random_state);
+
+#endif	/*DES_INTERNAL_DEFS*/
diff --git a/krb5-1-6/src/lib/crypto/des/destest.c b/krb5-1-6/src/lib/crypto/des/destest.c
new file mode 100644
index 000000000..2582cc3d3
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/destest.c
@@ -0,0 +1,247 @@
+/*
+ * lib/crypto/des/destest.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Test a DES implementation against known inputs & outputs
+ */
+
+
+/*
+ * 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"
+
+#include <stdio.h>
+
+void convert (char *, unsigned char []);
+
+void des_cblock_print_file (mit_des_cblock, FILE *);
+
+krb5_octet zeroblock[8] = {0,0,0,0,0,0,0,0};
+
+int
+main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char block1[17], block2[17], block3[17];
+#if 0
+    mit_des_cblock key, input, output, output2;
+#else
+    /* Force tests of unaligned accesses.  */
+    union { unsigned char c[8*4+3]; long l; } u;
+    unsigned char *ioblocks = u.c;
+    unsigned char *input = ioblocks+1;
+    unsigned char *output = ioblocks+10;
+    unsigned char *output2 = ioblocks+19;
+    unsigned char *key = ioblocks+27;
+#endif
+    mit_des_key_schedule sched;
+    int num = 0;
+    int retval;
+
+    int error = 0;
+
+    while (scanf("%16s %16s %16s", block1, block2, block3) == 3) {
+	convert(block1, key);
+	convert(block2, input);
+	convert(block3, output);
+
+	retval = mit_des_key_sched(key, sched);
+	if (retval) {
+            fprintf(stderr, "des test: can't process key");
+            exit(1);
+        }
+	mit_des_cbc_encrypt((const mit_des_cblock *) input, output2, 8,
+			    sched, zeroblock, 1);
+
+	if (memcmp((char *)output2, (char *)output, 8)) {
+	    fprintf(stderr, 
+		    "DES ENCRYPT ERROR, key %s, text %s, real cipher %s, computed cyphertext %02X%02X%02X%02X%02X%02X%02X%02X\n",
+		    block1, block2, block3,
+		    output2[0],output2[1],output2[2],output2[3],
+		    output2[4],output2[5],output2[6],output2[7]);
+	    error++;
+	}
+
+	/*
+	 * Now try decrypting....
+	 */
+	mit_des_cbc_encrypt((const mit_des_cblock *) output, output2, 8,
+			    sched, zeroblock, 0);
+
+	if (memcmp((char *)output2, (char *)input, 8)) {
+	    fprintf(stderr, 
+		    "DES DECRYPT ERROR, key %s, text %s, real cipher %s, computed cleartext %02X%02X%02X%02X%02X%02X%02X%02X\n",
+		    block1, block2, block3,
+		    output2[0],output2[1],output2[2],output2[3],
+		    output2[4],output2[5],output2[6],output2[7]);
+	    error++;
+	}
+
+	num++;
+    }
+
+    if (error) 
+	printf("destest: failed to pass the test\n");
+    else
+	printf("destest: %d tests passed successfully\n", num);
+
+    exit( (error > 256 && error % 256) ? 1 : error);
+}
+
+int value[128] = {
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+0, 1, 2, 3, 4, 5, 6, 7,
+8, 9, -1, -1, -1, -1, -1, -1,
+-1, 10, 11, 12, 13, 14, 15, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+void
+convert(text, cblock)
+    char *text;
+    unsigned char cblock[];
+{
+    register int i;
+    for (i = 0; i < 8; i++) {
+	if (text[i*2] < 0 || text[i*2] >= 128)
+	    abort ();
+	if (value[(int) text[i*2]] == -1 || value[(int) text[i*2+1]] == -1) {
+	    printf("Bad value byte %d in %s\n", i, text);
+	    exit(1);
+	}
+	cblock[i] = 16*value[(int) text[i*2]] + value[(int) text[i*2+1]];
+    }
+    return;
+}
+
+/*
+ * Fake out the DES library, for the purposes of testing.
+ */
+
+#include "des_int.h"
+
+int
+mit_des_is_weak_key(key)
+    mit_des_cblock key;
+{
+    return 0;				/* fake it out for testing */
+}
+
+void
+des_cblock_print_file(x, fp)
+    mit_des_cblock x;
+    FILE *fp;
+{
+    unsigned char *y = (unsigned char *) x;
+    register int i = 0;
+    fprintf(fp," 0x { ");
+
+    while (i++ < 8) {
+        fprintf(fp,"%x",*y++);
+        if (i < 8)
+            fprintf(fp,", ");
+    }
+    fprintf(fp," }");
+}
+
+
+#define smask(step) ((1<<step)-1)
+#define pstep(x,step) (((x)&smask(step))^(((x)>>step)&smask(step)))
+#define parity_char(x) pstep(pstep(pstep((x),4),2),1)
+
+/*
+ * des_check_key_parity: returns true iff key has the correct des parity.
+ *                       See des_fix_key_parity for the definition of
+ *                       correct des parity.
+ */
+int
+mit_des_check_key_parity(key)
+     register mit_des_cblock key;
+{
+    int i;
+    
+    for (i=0; i<sizeof(mit_des_cblock); i++) {
+	if ((key[i] & 1) == parity_char(0xfe&key[i])) {
+	    printf("warning: bad parity key:");
+	    des_cblock_print_file(key, stdout); 
+	    putchar('\n');
+	      
+	    return 1;
+	}
+    }
+
+    return(1);
+}
+
+void
+mit_des_fixup_key_parity(key)
+     register mit_des_cblock key;
+{
+    int i;
+    for (i=0; i<sizeof(mit_des_cblock); i++) 
+      {
+	key[i] &= 0xfe;
+	key[i] |= 1^parity_char(key[i]);
+      }
+  
+    return;
+}
diff --git a/krb5-1-6/src/lib/crypto/des/doc/libdes.doc b/krb5-1-6/src/lib/crypto/des/doc/libdes.doc
new file mode 100644
index 000000000..70f9f336a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/doc/libdes.doc
@@ -0,0 +1,208 @@
+
+	How to use the Kerberos encryption library.
+
+			Revised		10/15/85	spm
+
+1)	The following include file is needed:
+	
+	/projects/auth/include/des.h	(VAX)
+	---------------					(PC8086)
+
+2)	The encryption library that should be linked to is:
+	
+	/projects/auth/lib/libdes.a		(VAX)
+|	/projects/auth/ibm/lib/libdes.a	(PC8086 cross-compilation environment)
+
+3)	For each key that may be simultaneously active,
+	allocate (either compile or malloc) a "Key_schedule" struct, 
+	defined in "des.h"
+
+4)	Create key schedules, as needed, prior to using the encryption
+	routines, via "des_set_key()".
+
+5)  Setup the input and output areas.  Make sure to note the restrictions
+	on lengths being multiples of eight bytes.
+
+6)	Invoke the encryption/decryption routines, "ecb_encrypt()"
+	 or "cbc_encrypt()"
+
+7)	To generate a cryptographic checksum, use "cbc_cksum()"
+/*	----------------------------------------------------------------	*/
+	
+	Routine Interfaces--
+
+/*	-----------------------------------------------------------------	*/
+
+int
+	des_set_key(k,schedule)
+		C_Block			*k;
+		Key_schedule	schedule;
+
+	Calculates a key schedule from (all) eight bytes of the input key, and
+	puts it into the indicated "Key_schedule" struct;
+
+	Make sure to pass valid eight bytes, no padding or other processing
+	it done.
+
+	The key schedule is then used in subsequent encryption/decryption
+	operations.  Many key schedules may be created and cached for later
+	use.
+
+	The user is responsible to clear keys and schedules no longer needed
+	to prevent their disclosure.
+
+|	Checks the parity of the key provided, to make sure it is odd per
+|	FIPS spec.  Returns 0 value for key ok, 1 for key_parity error.
+
+/*	----------------------------------------------------------------	*/
+	
+int
+	ecb_encrypt(input,output,schedule,encrypt)
+		C_Block			*input;		/* ptr to eight byte input value */
+		C_Block			*output;	/* ptr to eight byte output value */
+		int				encrypt;	/* 0 ==> decrypt, else encrypt */
+		Key_schedule	schedule;	/* addr of key schedule */
+
+This is the low level routine that encrypts or decrypts a single 8-byte
+block in electronic code book mode.  Always transforms the input
+data into the output data.
+
+If encrypt is non-zero, the input (cleartext) is encrypted into the
+output (ciphertext) using the specified key_schedule, pre-set via "des_set_key".
+
+If encrypt is zero, the input (now ciphertext) is decrypted into
+the output (now cleartext).
+
+Input and output may be the same space.
+
+Does not return any meaningful value.  Void is not used for compatibility
+with other compilers.
+
+/*	--------------------------------------------------------------	*/
+
+int	
+	cbc_encrypt(input,output,length,schedule,ivec,encrypt)
+
+		C_Block			*input;		/* ptr to input data */
+		C_Block			*output;	/* ptr to output data */
+		int				length;		/* desired length, in bytes */
+		Key_schedule	schedule;		/* addr of precomputed schedule */
+		C_Block			*ivec;		/* pointer to 8 byte initialization
+									 * vector
+									 */
+		int				encrypt		/* 0 ==> decrypt; else encrypt*/
+
+
+	If encrypt is non-zero, the routine cipher-block-chain encrypts
+	the INPUT (cleartext) into the OUTPUT (ciphertext) using the provided
+	key schedule and initialization vector.  If the length is not an integral
+	multiple of eight bytes, the last block is copied to a temp and zero 
+	filled (highest addresses).  The output is ALWAYS an integral multiple
+	of eight bytes.
+
+	If encrypt is zero, the routine cipher-block chain decrypts the INPUT
+	(ciphertext) into the OUTPUT (cleartext) using the provided key schedule
+	and	initialization vector.	Decryption ALWAYS operates on integral
+	multiples of 8 bytes, so will round the length provided up to the
+	appropriate	multiple. Consequently,	it will always produce the rounded-up
+	number of bytes of output cleartext. The application must determine if
+	the output cleartext was zero-padded due to cleartext lengths not integral
+	multiples of 8.
+
+	No errors or meaningful value are returned.  Void is not used for
+	compatibility with other compilers.
+
+
+/* cbc checksum (MAC) only routine  ---------------------------------------- */
+int	
+	cbc_cksum(input,output,length,schedule,ivec)
+
+	C_Block		 	*input;		/* >= length bytes of inputtext	 */
+	C_Block		 	*output;	/* >= length bytes of outputtext */
+	int				length;		/* in bytes						*/
+	Key_schedule	schedule;	/* precomputed key schedule	   */
+	C_Block			*ivec;		/* 8 bytes of ivec			   */
+
+
+	Produces a cryptographic checksum, 8 bytes, by cipher-block-chain
+	encrypting the input, discarding the ciphertext output, and only retaining
+	the last ciphertext 8-byte block.  Uses the provided key schedule and ivec.
+	The input is effectively zero-padded to an integral multiple of
+	eight bytes, though the original input is not modified.
+
+	No meaningful value is returned.  Void is not used for compatibility
+	with other compilers.
+
+
+/*	random_key ----------------------------------------*/
+int
+	random_key(key)
+
+	C_Block	*key;
+
+	The start for the random number generated is set from the current time
+	in microseconds, then the random number generator is invoked
+	to create an eight byte output key (not a schedule).  The key
+	generated is set to odd parity per FIPS spec.
+
+	The caller must	supply space for the output key, pointed to 
+	by "*key", then after getting a new key, call the des_set_key() 
+	routine when needed.
+
+	No meaningfull value is returned.  Void is not used for compatibility
+	with other compilers.
+
+
+/* string_to_key --------------------------------------------*/
+
+int
+	string_to_key(str,key)
+	register char		*str;
+	register C_Block	*key;
+
+	This routines converts an arbitrary length, null terminated string
+	to an 8 byte DES key, with each byte parity set to odd, per FIPS spec.
+
+	The algorithm is as follows:
+
+|	Take the first 8 bytes and remove the parity (leaving 56 bits).
+|	Do the same for the second 8 bytes, and the third, etc.  Do this for
+|	as many sets of 8 bytes as necessary, filling in the remainder of the
+|	last set with nulls.  Fold the second set back on the first (i.e. bit
+|	0 over bit 55, and bit 55 over bit 0).  Fold the third over the second
+|	(bit 0 of the third set is now over bit 0 of the first set).  Repeat
+|	until you have done this to all sets.  Xor the folded sets.  Break the
+|	result into 8 7 bit bytes, and generate odd parity for each byte.  You
+|	now have 64 bits.  Note that DES takes a 64 bit key, and uses only the
+|	non parity bits.
+
+
+/* read_password -------------------------------------------*/
+
+read_password(k,prompt,verify)
+	C_Block	*k;
+	char *prompt;
+	int	verify;
+
+This routine issues the supplied prompt, turns off echo, if possible, and
+reads an input string.  If verify is non-zero, it does it again, for use
+in applications such as changing a password. If verify is non-zero, both
+versions are compared, and the input is requested repeatedly until they
+match.  Then, the input string is mapped into a valid DES key, internally
+using the string_to_key routine.  The newly created key is copied to the
+area pointed to by parameter "k".  
+
+No meaningful value is returned.  If an error occurs trying to manipulate
+the terminal echo, the routine forces the process to exit.
+
+/* get_line ------------------------*/
+long get_line(p,max)
+	char	*p;
+	long	max;
+
+Reads input characters from standard input until either a newline appears or
+else the max length is reached.  The characters read are stuffed into
+the string pointed to, which will always be null terminated.  The newline
+is not inserted in the string.  The max parameter includes the byte needed
+for the null terminator, so allocate and pass one more than the maximum
+string length desired.
diff --git a/krb5-1-6/src/lib/crypto/des/f_cbc.c b/krb5-1-6/src/lib/crypto/des/f_cbc.c
new file mode 100644
index 000000000..24996e489
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/f_cbc.c
@@ -0,0 +1,255 @@
+/*
+ * 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_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode
+ */
+#include "des_int.h"
+#include "f_tables.h"
+
+/*
+ * des_cbc_encrypt - {en,de}crypt a stream in CBC mode
+ */
+
+/*
+ * This routine performs DES cipher-block-chaining operation, either
+ * encrypting from cleartext to ciphertext, if encrypt != 0 or
+ * decrypting from ciphertext to cleartext, if encrypt == 0.
+ *
+ * The key schedule is passed as an arg, as well as the cleartext or
+ * ciphertext.  The cleartext and ciphertext should be in host order.
+ *
+ * NOTE-- the output is ALWAYS an multiple of 8 bytes long.  If not
+ * enough space was provided, your program will get trashed.
+ *
+ * For encryption, the cleartext string is null padded, at the end, to
+ * an integral multiple of eight bytes.
+ *
+ * For decryption, the ciphertext will be used in integral multiples
+ * of 8 bytes, but only the first "length" bytes returned into the
+ * cleartext.
+ */
+
+const mit_des_cblock mit_des_zeroblock /* = all zero */;
+
+#undef mit_des_cbc_encrypt
+int
+mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
+		    unsigned long length, const mit_des_key_schedule schedule,
+		    const mit_des_cblock ivec, int enc)
+{
+    /*
+     * Deal with encryption and decryption separately.
+     */
+    if (enc)
+	krb5int_des_cbc_encrypt(in, out, length, schedule, ivec);
+    else
+	krb5int_des_cbc_decrypt(in, out, length, schedule, ivec);
+    return 0;
+}
+
+void
+krb5int_des_cbc_encrypt(const mit_des_cblock *in,
+			mit_des_cblock *out,
+			unsigned long length,
+			const mit_des_key_schedule schedule,
+			const mit_des_cblock ivec)
+{
+	unsigned DES_INT32 left, right;
+	const unsigned DES_INT32 *kp;
+	const unsigned char *ip;
+	unsigned char *op;
+
+	/*
+	 * Get key pointer here.  This won't need to be reinitialized
+	 */
+	kp = (const unsigned DES_INT32 *)schedule;
+
+	/*
+	 * Initialize left and right with the contents of the initial
+	 * vector.
+	 */
+	ip = ivec;
+	GET_HALF_BLOCK(left, ip);
+	GET_HALF_BLOCK(right, ip);
+
+	/*
+	 * Suitably initialized, now work the length down 8 bytes
+	 * at a time.
+	 */
+	ip = *in;
+	op = *out;
+	while (length > 0) {
+		/*
+		 * Get more input, xor it in.  If the length is
+		 * greater than or equal to 8 this is straight
+		 * forward.  Otherwise we have to fart around.
+		 */
+		if (length >= 8) {
+			unsigned DES_INT32 temp;
+			GET_HALF_BLOCK(temp, ip);
+			left  ^= temp;
+			GET_HALF_BLOCK(temp, ip);
+			right ^= temp;
+			length -= 8;
+		} else {
+			/*
+			 * Oh, shoot.  We need to pad the
+			 * end with zeroes.  Work backwards
+			 * to do this.
+			 */
+			ip += (int) length;
+			switch(length) {
+			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, kp);
+
+		/*
+		 * Copy the results out
+		 */
+		PUT_HALF_BLOCK(left, op);
+		PUT_HALF_BLOCK(right, op);
+	}
+}
+
+void
+krb5int_des_cbc_decrypt(const mit_des_cblock *in,
+			mit_des_cblock *out,
+			unsigned long length,
+			const mit_des_key_schedule schedule,
+			const mit_des_cblock ivec)
+{
+	unsigned DES_INT32 left, right;
+	const unsigned DES_INT32 *kp;
+	const unsigned char *ip;
+	unsigned char *op;
+	unsigned DES_INT32 ocipherl, ocipherr;
+	unsigned DES_INT32 cipherl, cipherr;
+
+	/*
+	 * Get key pointer here.  This won't need to be reinitialized
+	 */
+	kp = (const unsigned DES_INT32 *)schedule;
+
+	/*
+	 * Decrypting is harder than encrypting because of
+	 * the necessity of remembering a lot more things.
+	 * Should think about this a little more...
+	 */
+
+	if (length <= 0)
+		return;
+
+	/*
+	 * Prime the old cipher with ivec.
+	 */
+	ip = ivec;
+	GET_HALF_BLOCK(ocipherl, ip);
+	GET_HALF_BLOCK(ocipherr, ip);
+
+	/*
+	 * Now do this in earnest until we run out of length.
+	 */
+	ip = *in;
+	op = *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, 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;
+			ocipherr = cipherr;
+		} 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 */
+		}
+	}
+}
+
+#ifdef CONFIG_SMALL
+void krb5int_des_do_encrypt_2 (unsigned DES_INT32 *left,
+			       unsigned DES_INT32 *right,
+			       const unsigned DES_INT32 *kp)
+{
+    DES_DO_ENCRYPT_1 (*left, *right, kp);
+}
+
+void krb5int_des_do_decrypt_2 (unsigned DES_INT32 *left,
+			       unsigned DES_INT32 *right,
+			       const unsigned DES_INT32 *kp)
+{
+    DES_DO_DECRYPT_1 (*left, *right, kp);
+}
+#endif
diff --git a/krb5-1-6/src/lib/crypto/des/f_cksum.c b/krb5-1-6/src/lib/crypto/des/f_cksum.c
new file mode 100644
index 000000000..1b9e9a02b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/f_cksum.c
@@ -0,0 +1,120 @@
+/*
+ * 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_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode
+ */
+#include "des_int.h"
+#include "f_tables.h"
+
+/*
+ * This routine performs DES cipher-block-chaining checksum operation,
+ * a.k.a.  Message Authentication Code.  It ALWAYS encrypts from input
+ * to a single 64 bit output MAC checksum.
+ *
+ * The key schedule is passed as an arg, as well as the cleartext or
+ * ciphertext. The cleartext and ciphertext should be in host order.
+ *
+ * NOTE-- the output is ALWAYS 8 bytes long.  If not enough space was
+ * provided, your program will get trashed.
+ *
+ * The input is null padded, at the end (highest addr), to an integral
+ * multiple of eight bytes.
+ */
+
+unsigned long
+mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out,
+		  unsigned long length, const mit_des_key_schedule schedule,
+		  const krb5_octet *ivec)
+{
+	unsigned DES_INT32 left, right;
+	const unsigned DES_INT32 *kp;
+	const unsigned char *ip;
+	unsigned char *op;
+	register DES_INT32 len;
+
+	/*
+	 * Initialize left and right with the contents of the initial
+	 * vector.
+	 */
+	ip = ivec;
+	GET_HALF_BLOCK(left, ip);
+	GET_HALF_BLOCK(right, ip);
+
+	/*
+	 * Suitably initialized, now work the length down 8 bytes
+	 * at a time.
+	 */
+	ip = in;
+	len = length;
+	while (len > 0) {
+		/*
+		 * Get more input, xor it in.  If the length is
+		 * greater than or equal to 8 this is straight
+		 * forward.  Otherwise we have to fart around.
+		 */
+		if (len >= 8) {
+			left  ^= ((*ip++) & FF_UINT32) << 24;
+			left  ^= ((*ip++) & FF_UINT32) << 16;
+			left  ^= ((*ip++) & FF_UINT32) <<  8;
+			left  ^=  (*ip++) & FF_UINT32;
+			right ^= ((*ip++) & FF_UINT32) << 24;
+			right ^= ((*ip++) & FF_UINT32) << 16;
+			right ^= ((*ip++) & FF_UINT32) <<  8;
+			right ^=  (*ip++) & FF_UINT32;
+			len -= 8;
+		} else {
+			/*
+			 * Oh, shoot.  We need to pad the
+			 * end with zeroes.  Work backwards
+			 * to do this.
+			 */
+			ip += (int) len;
+			switch(len) {
+			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;
+			}
+			len = 0;
+		}
+
+		/*
+		 * Encrypt what we have
+		 */
+		kp = (const unsigned DES_INT32 *)schedule;
+		DES_DO_ENCRYPT(left, right, kp);
+	}
+
+	/*
+	 * Done.  Left and right have the checksum.  Put it into
+	 * the output.
+	 */
+	op = out;
+	PUT_HALF_BLOCK(left, op);
+	PUT_HALF_BLOCK(right, op);
+
+	/*
+	 * Return right.  I'll bet the MIT code returns this
+	 * inconsistantly (with the low order byte of the checksum
+	 * not always in the low order byte of the DES_INT32).  We won't.
+	 */
+	return right & 0xFFFFFFFFUL;
+}
diff --git a/krb5-1-6/src/lib/crypto/des/f_parity.c b/krb5-1-6/src/lib/crypto/des/f_parity.c
new file mode 100644
index 000000000..26cf6039b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/f_parity.c
@@ -0,0 +1,56 @@
+/*
+ * These routines check and fix parity of encryption keys for the DES
+ * algorithm.
+ *
+ * They are a replacement for routines in key_parity.c, that don't require
+ * the table building that they do.
+ *
+ * Mark Eichin -- Cygnus Support
+ */
+
+
+#include "des_int.h"
+
+/*
+ * des_fixup_key_parity: Forces odd parity per byte; parity is bits
+ *                       8,16,...64 in des order, implies 0, 8, 16, ...
+ *                       vax order.
+ */
+#define smask(step) ((1<<step)-1)
+#define pstep(x,step) (((x)&smask(step))^(((x)>>step)&smask(step)))
+#define parity_char(x) pstep(pstep(pstep((x),4),2),1)
+
+void
+mit_des_fixup_key_parity(mit_des_cblock key)
+{
+    int i;
+    for (i=0; i<sizeof(mit_des_cblock); i++) 
+      {
+	key[i] &= 0xfe;
+	key[i] |= 1^parity_char(key[i]);
+      }
+  
+    return;
+}
+
+/*
+ * des_check_key_parity: returns true iff key has the correct des parity.
+ *                       See des_fix_key_parity for the definition of
+ *                       correct des parity.
+ */
+int
+mit_des_check_key_parity(mit_des_cblock key)
+{
+    int i;
+    
+    for (i=0; i<sizeof(mit_des_cblock); i++) 
+      {
+	if((key[i] & 1) == parity_char(0xfe&key[i])) 
+	  {
+	    return 0;
+	  }
+      }
+
+    return(1);
+}
+
diff --git a/krb5-1-6/src/lib/crypto/des/f_sched.c b/krb5-1-6/src/lib/crypto/des/f_sched.c
new file mode 100644
index 000000000..99d1dc313
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/f_sched.c
@@ -0,0 +1,344 @@
+/*
+ * 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_make_sched.c - permute a DES key, returning the resulting key schedule
+ */
+#include "k5-int.h"
+#include "des_int.h"
+
+/*
+ * Permuted choice 1 tables.  These are used to extract bits
+ * from the left and right parts of the key to form Ci and Di.
+ * The code that uses these tables knows which bits from which
+ * part of each key are used to form Ci and Di.
+ */
+static const unsigned DES_INT32 PC1_CL[8] = {
+	0x00000000, 0x00000010, 0x00001000, 0x00001010,
+	0x00100000, 0x00100010, 0x00101000, 0x00101010
+};
+
+static const unsigned DES_INT32 PC1_DL[16] = {
+	0x00000000, 0x00100000, 0x00001000, 0x00101000,
+	0x00000010, 0x00100010, 0x00001010, 0x00101010,
+	0x00000001, 0x00100001, 0x00001001, 0x00101001,
+	0x00000011, 0x00100011, 0x00001011, 0x00101011
+};
+
+static const unsigned DES_INT32 PC1_CR[16] = {
+	0x00000000, 0x00000001, 0x00000100, 0x00000101,
+	0x00010000, 0x00010001, 0x00010100, 0x00010101,
+	0x01000000, 0x01000001, 0x01000100, 0x01000101,
+	0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const unsigned DES_INT32 PC1_DR[8] = {
+	0x00000000, 0x01000000, 0x00010000, 0x01010000,
+	0x00000100, 0x01000100, 0x00010100, 0x01010100
+};
+
+
+/*
+ * At the start of some iterations of the key schedule we do
+ * a circular left shift by one place, while for others we do a shift by
+ * two places.  This has bits set for the iterations where we do 2 bit
+ * shifts, starting at the low order bit.
+ */
+#define	TWO_BIT_SHIFTS	0x7efc
+
+/*
+ * Permuted choice 2 tables.  The first actually produces the low order
+ * 24 bits of the subkey Ki from the 28 bit value of Ci.  The second produces
+ * the high order 24 bits from Di.  The tables are indexed by six bit
+ * segments of Ci and Di respectively.  The code is handcrafted to compute
+ * the appropriate 6 bit chunks.
+ *
+ * Note that for ease of computation, the 24 bit values are produced with
+ * six bits going into each byte.  Note also that the table has been byte
+ * rearranged to produce keys which match the order we will apply them
+ * in in the des code.
+ */
+static const unsigned DES_INT32 PC2_C[4][64] = {
+  {
+	0x00000000, 0x00000004, 0x00010000, 0x00010004,
+	0x00000400, 0x00000404, 0x00010400, 0x00010404,
+	0x00000020, 0x00000024, 0x00010020, 0x00010024,
+	0x00000420, 0x00000424, 0x00010420, 0x00010424,
+	0x01000000, 0x01000004, 0x01010000, 0x01010004,
+	0x01000400, 0x01000404, 0x01010400, 0x01010404,
+	0x01000020, 0x01000024, 0x01010020, 0x01010024,
+	0x01000420, 0x01000424, 0x01010420, 0x01010424,
+	0x00020000, 0x00020004, 0x00030000, 0x00030004,
+	0x00020400, 0x00020404, 0x00030400, 0x00030404,
+	0x00020020, 0x00020024, 0x00030020, 0x00030024,
+	0x00020420, 0x00020424, 0x00030420, 0x00030424,
+	0x01020000, 0x01020004, 0x01030000, 0x01030004,
+	0x01020400, 0x01020404, 0x01030400, 0x01030404,
+	0x01020020, 0x01020024, 0x01030020, 0x01030024,
+	0x01020420, 0x01020424, 0x01030420, 0x01030424,
+  },
+  {
+	0x00000000, 0x02000000, 0x00000800, 0x02000800,
+	0x00080000, 0x02080000, 0x00080800, 0x02080800,
+	0x00000001, 0x02000001, 0x00000801, 0x02000801,
+	0x00080001, 0x02080001, 0x00080801, 0x02080801,
+	0x00000100, 0x02000100, 0x00000900, 0x02000900,
+	0x00080100, 0x02080100, 0x00080900, 0x02080900,
+	0x00000101, 0x02000101, 0x00000901, 0x02000901,
+	0x00080101, 0x02080101, 0x00080901, 0x02080901,
+	0x10000000, 0x12000000, 0x10000800, 0x12000800,
+	0x10080000, 0x12080000, 0x10080800, 0x12080800,
+	0x10000001, 0x12000001, 0x10000801, 0x12000801,
+	0x10080001, 0x12080001, 0x10080801, 0x12080801,
+	0x10000100, 0x12000100, 0x10000900, 0x12000900,
+	0x10080100, 0x12080100, 0x10080900, 0x12080900,
+	0x10000101, 0x12000101, 0x10000901, 0x12000901,
+	0x10080101, 0x12080101, 0x10080901, 0x12080901,
+  },
+  {
+	0x00000000, 0x00040000, 0x00002000, 0x00042000,
+	0x00100000, 0x00140000, 0x00102000, 0x00142000,
+	0x20000000, 0x20040000, 0x20002000, 0x20042000,
+	0x20100000, 0x20140000, 0x20102000, 0x20142000,
+	0x00000008, 0x00040008, 0x00002008, 0x00042008,
+	0x00100008, 0x00140008, 0x00102008, 0x00142008,
+	0x20000008, 0x20040008, 0x20002008, 0x20042008,
+	0x20100008, 0x20140008, 0x20102008, 0x20142008,
+	0x00200000, 0x00240000, 0x00202000, 0x00242000,
+	0x00300000, 0x00340000, 0x00302000, 0x00342000,
+	0x20200000, 0x20240000, 0x20202000, 0x20242000,
+	0x20300000, 0x20340000, 0x20302000, 0x20342000,
+	0x00200008, 0x00240008, 0x00202008, 0x00242008,
+	0x00300008, 0x00340008, 0x00302008, 0x00342008,
+	0x20200008, 0x20240008, 0x20202008, 0x20242008,
+	0x20300008, 0x20340008, 0x20302008, 0x20342008,
+  },
+  {
+	0x00000000, 0x00000010, 0x08000000, 0x08000010,
+	0x00000200, 0x00000210, 0x08000200, 0x08000210,
+	0x00000002, 0x00000012, 0x08000002, 0x08000012,
+	0x00000202, 0x00000212, 0x08000202, 0x08000212,
+	0x04000000, 0x04000010, 0x0c000000, 0x0c000010,
+	0x04000200, 0x04000210, 0x0c000200, 0x0c000210,
+	0x04000002, 0x04000012, 0x0c000002, 0x0c000012,
+	0x04000202, 0x04000212, 0x0c000202, 0x0c000212,
+	0x00001000, 0x00001010, 0x08001000, 0x08001010,
+	0x00001200, 0x00001210, 0x08001200, 0x08001210,
+	0x00001002, 0x00001012, 0x08001002, 0x08001012,
+	0x00001202, 0x00001212, 0x08001202, 0x08001212,
+	0x04001000, 0x04001010, 0x0c001000, 0x0c001010,
+	0x04001200, 0x04001210, 0x0c001200, 0x0c001210,
+	0x04001002, 0x04001012, 0x0c001002, 0x0c001012,
+	0x04001202, 0x04001212, 0x0c001202, 0x0c001212
+  },
+};
+
+static const unsigned DES_INT32 PC2_D[4][64] = {
+  {
+	0x00000000, 0x02000000, 0x00020000, 0x02020000,
+	0x00000100, 0x02000100, 0x00020100, 0x02020100,
+	0x00000008, 0x02000008, 0x00020008, 0x02020008,
+	0x00000108, 0x02000108, 0x00020108, 0x02020108,
+	0x00200000, 0x02200000, 0x00220000, 0x02220000,
+	0x00200100, 0x02200100, 0x00220100, 0x02220100,
+	0x00200008, 0x02200008, 0x00220008, 0x02220008,
+	0x00200108, 0x02200108, 0x00220108, 0x02220108,
+	0x00000200, 0x02000200, 0x00020200, 0x02020200,
+	0x00000300, 0x02000300, 0x00020300, 0x02020300,
+	0x00000208, 0x02000208, 0x00020208, 0x02020208,
+	0x00000308, 0x02000308, 0x00020308, 0x02020308,
+	0x00200200, 0x02200200, 0x00220200, 0x02220200,
+	0x00200300, 0x02200300, 0x00220300, 0x02220300,
+	0x00200208, 0x02200208, 0x00220208, 0x02220208,
+	0x00200308, 0x02200308, 0x00220308, 0x02220308,
+  },
+  {
+	0x00000000, 0x00001000, 0x00000020, 0x00001020,
+	0x00100000, 0x00101000, 0x00100020, 0x00101020,
+	0x08000000, 0x08001000, 0x08000020, 0x08001020,
+	0x08100000, 0x08101000, 0x08100020, 0x08101020,
+	0x00000004, 0x00001004, 0x00000024, 0x00001024,
+	0x00100004, 0x00101004, 0x00100024, 0x00101024,
+	0x08000004, 0x08001004, 0x08000024, 0x08001024,
+	0x08100004, 0x08101004, 0x08100024, 0x08101024,
+	0x00000400, 0x00001400, 0x00000420, 0x00001420,
+	0x00100400, 0x00101400, 0x00100420, 0x00101420,
+	0x08000400, 0x08001400, 0x08000420, 0x08001420,
+	0x08100400, 0x08101400, 0x08100420, 0x08101420,
+	0x00000404, 0x00001404, 0x00000424, 0x00001424,
+	0x00100404, 0x00101404, 0x00100424, 0x00101424,
+	0x08000404, 0x08001404, 0x08000424, 0x08001424,
+	0x08100404, 0x08101404, 0x08100424, 0x08101424,
+  },
+  {
+	0x00000000, 0x10000000, 0x00010000, 0x10010000,
+	0x00000002, 0x10000002, 0x00010002, 0x10010002,
+	0x00002000, 0x10002000, 0x00012000, 0x10012000,
+	0x00002002, 0x10002002, 0x00012002, 0x10012002,
+	0x00040000, 0x10040000, 0x00050000, 0x10050000,
+	0x00040002, 0x10040002, 0x00050002, 0x10050002,
+	0x00042000, 0x10042000, 0x00052000, 0x10052000,
+	0x00042002, 0x10042002, 0x00052002, 0x10052002,
+	0x20000000, 0x30000000, 0x20010000, 0x30010000,
+	0x20000002, 0x30000002, 0x20010002, 0x30010002,
+	0x20002000, 0x30002000, 0x20012000, 0x30012000,
+	0x20002002, 0x30002002, 0x20012002, 0x30012002,
+	0x20040000, 0x30040000, 0x20050000, 0x30050000,
+	0x20040002, 0x30040002, 0x20050002, 0x30050002,
+	0x20042000, 0x30042000, 0x20052000, 0x30052000,
+	0x20042002, 0x30042002, 0x20052002, 0x30052002,
+  },
+  {
+	0x00000000, 0x04000000, 0x00000001, 0x04000001,
+	0x01000000, 0x05000000, 0x01000001, 0x05000001,
+	0x00000010, 0x04000010, 0x00000011, 0x04000011,
+	0x01000010, 0x05000010, 0x01000011, 0x05000011,
+	0x00080000, 0x04080000, 0x00080001, 0x04080001,
+	0x01080000, 0x05080000, 0x01080001, 0x05080001,
+	0x00080010, 0x04080010, 0x00080011, 0x04080011,
+	0x01080010, 0x05080010, 0x01080011, 0x05080011,
+	0x00000800, 0x04000800, 0x00000801, 0x04000801,
+	0x01000800, 0x05000800, 0x01000801, 0x05000801,
+	0x00000810, 0x04000810, 0x00000811, 0x04000811,
+	0x01000810, 0x05000810, 0x01000811, 0x05000811,
+	0x00080800, 0x04080800, 0x00080801, 0x04080801,
+	0x01080800, 0x05080800, 0x01080801, 0x05080801,
+	0x00080810, 0x04080810, 0x00080811, 0x04080811,
+	0x01080810, 0x05080810, 0x01080811, 0x05080811
+  },
+};
+
+
+
+/*
+ * Permute the key to give us our key schedule.
+ */
+int
+mit_des_make_key_sched(mit_des_cblock key, mit_des_key_schedule schedule)
+{
+	register unsigned DES_INT32 c, d;
+
+	{
+		/*
+		 * Need a pointer for the keys and a temporary DES_INT32
+		 */
+		const unsigned char *k;
+		register unsigned DES_INT32 tmp;
+
+		/*
+		 * Fetch the key into something we can work with
+		 */
+		k = key;
+
+		/*
+		 * The first permutted choice gives us the 28 bits for C0 and
+		 * 28 for D0.  C0 gets 12 bits from the left key and 16 from
+		 * the right, while D0 gets 16 from the left and 12 from the
+		 * right.  The code knows which bits go where.
+		 */
+		tmp = ((unsigned DES_INT32)(*(k)++)) << 24;
+		tmp |= ((unsigned DES_INT32)(*(k)++)) << 16;
+		tmp |= ((unsigned DES_INT32)(*(k)++)) << 8;
+		tmp |= (unsigned DES_INT32)(*(k)++);		/* left part of key */
+		c =  PC1_CL[(tmp >> 29) & 0x7]
+		  | (PC1_CL[(tmp >> 21) & 0x7] << 1)
+		  | (PC1_CL[(tmp >> 13) & 0x7] << 2)
+		  | (PC1_CL[(tmp >>  5) & 0x7] << 3);
+		d =  PC1_DL[(tmp >> 25) & 0xf]
+		  | (PC1_DL[(tmp >> 17) & 0xf] << 1)
+		  | (PC1_DL[(tmp >>  9) & 0xf] << 2)
+		  | (PC1_DL[(tmp >>  1) & 0xf] << 3);
+
+		tmp = ((unsigned DES_INT32)(*(k)++)) << 24;
+		tmp |= ((unsigned DES_INT32)(*(k)++)) << 16;
+		tmp |= ((unsigned DES_INT32)(*(k)++)) << 8;
+		tmp |= (unsigned DES_INT32)(*(k)++);		/* right part of key */
+		c |= PC1_CR[(tmp >> 28) & 0xf]
+		  | (PC1_CR[(tmp >> 20) & 0xf] << 1)
+		  | (PC1_CR[(tmp >> 12) & 0xf] << 2)
+		  | (PC1_CR[(tmp >>  4) & 0xf] << 3);
+		d |= PC1_DR[(tmp >> 25) & 0x7]
+		  | (PC1_DR[(tmp >> 17) & 0x7] << 1)
+		  | (PC1_DR[(tmp >>  9) & 0x7] << 2)
+		  | (PC1_DR[(tmp >>  1) & 0x7] << 3);
+	}
+
+	{
+		/*
+		 * Need several temporaries in here
+		 */
+		register unsigned DES_INT32 ltmp, rtmp;
+		register unsigned DES_INT32 *k;
+		register int two_bit_shifts;
+		register int i;
+		/*
+		 * Now iterate to compute the key schedule.  Note that we
+		 * record the entire set of subkeys in 6 bit chunks since
+		 * they are used that way.  At 6 bits/char, we need
+		 * 48/6 char's/subkey * 16 subkeys/encryption == 128 bytes.
+		 * The schedule must be this big.
+		 */
+		k = (unsigned DES_INT32 *)schedule;
+		two_bit_shifts = TWO_BIT_SHIFTS;
+		for (i = 16; i > 0; i--) {
+			/*
+			 * Do the rotation.  One bit and two bit rotations
+			 * are done separately.  Note C and D are 28 bits.
+			 */
+			if (two_bit_shifts & 0x1) {
+				c = ((c << 2) & 0xffffffc) | (c >> 26);
+				d = ((d << 2) & 0xffffffc) | (d >> 26);
+			} else {
+				c = ((c << 1) & 0xffffffe) | (c >> 27);
+				d = ((d << 1) & 0xffffffe) | (d >> 27);
+			}
+			two_bit_shifts >>= 1;
+
+			/*
+			 * Apply permutted choice 2 to C to get the first
+			 * 24 bits worth of keys.  Note that bits 9, 18, 22
+			 * and 25 (using DES numbering) in C are unused.  The
+			 * shift-mask stuff is done to delete these bits from
+			 * the indices, since this cuts the table size in half.
+			 *
+			 * The table is torqued, by the way.  If the standard
+			 * byte order for this (high to low order) is 1234,
+			 * the table actually gives us 4132.
+			 */
+			ltmp = PC2_C[0][((c >> 22) & 0x3f)]
+			     | PC2_C[1][((c >> 15) & 0xf) | ((c >> 16) & 0x30)]
+			     | PC2_C[2][((c >>  4) & 0x3) | ((c >>  9) & 0x3c)]
+			     | PC2_C[3][((c      ) & 0x7) | ((c >>  4) & 0x38)];
+			/*
+			 * Apply permutted choice 2 to D to get the other half.
+			 * Here, bits 7, 10, 15 and 26 go unused.  The sqeezing
+			 * actually turns out to be cheaper here.
+			 *
+			 * This table is similarly torqued.  If the standard
+			 * byte order is 5678, the table has the bytes permuted
+			 * to give us 7685.
+			 */
+			rtmp = PC2_D[0][((d >> 22) & 0x3f)]
+			     | PC2_D[1][((d >> 14) & 0xf) | ((d >> 15) & 0x30)]
+			     | PC2_D[2][((d >>  7) & 0x3f)]
+			     | PC2_D[3][((d      ) & 0x3) | ((d >>  1) & 0x3c)];
+			
+			/*
+			 * Make up two words of the key schedule, with a
+			 * byte order which is convenient for the DES
+			 * inner loop.  The high order (first) word will
+			 * hold bytes 7135 (high to low order) while the
+			 * second holds bytes 4682.
+			 */
+			*k++ = (ltmp & 0x00ffff00) | (rtmp & 0xff0000ff);
+			*k++ = (ltmp & 0xff0000ff) | (rtmp & 0x00ffff00);
+		}
+	}
+	return (0);
+}
diff --git a/krb5-1-6/src/lib/crypto/des/f_tables.c b/krb5-1-6/src/lib/crypto/des/f_tables.c
new file mode 100644
index 000000000..f84ade538
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/f_tables.c
@@ -0,0 +1,351 @@
+/*
+ * 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_tables.c - precomputed tables used for the DES cipher function
+ */
+
+/*
+ * Include the header file so something will complain if the
+ * declarations get out of sync
+ */
+#include "des_int.h"
+#include "f_tables.h"
+
+/*
+ * These tables may be declared const if you want.  Many compilers
+ * don't support this, though.
+ */
+
+/*
+ * The DES algorithm which uses these is intended to be fairly speedy
+ * at the expense of some memory.  All the standard hacks are used.
+ * The S boxes and the P permutation are precomputed into one table.
+ * The E box never actually appears explicitly since it is easy to apply
+ * this algorithmically as needed.  The initial permutation and final
+ * (inverse initial) permutation are computed from tables designed to
+ * permute one byte at a time.  This should run pretty fast on machines
+ * with 32 bit words and bit field/multiple bit shift instructions which
+ * are fast.
+ */
+
+/*
+ * The initial permutation array.  This is used to compute both the
+ * left and the right halves of the initial permutation using bytes
+ * from words made from the following operations:
+ *
+ * ((left & 0x55555555) << 1) | (right & 0x55555555)  for left half
+ * (left & 0xaaaaaaaa) | ((right & 0xaaaaaaaa) >> 1)  for right half
+ *
+ * The scheme is that we index into the table using each byte.  The
+ * result from the high order byte is or'd with the result from the
+ * next byte shifted left once is or'd with the result from the next
+ * byte shifted left twice if or'd with the result from the low order
+ * byte shifted left by three.  Clear?
+ */
+
+const unsigned DES_INT32 des_IP_table[256] = {
+	0x00000000, 0x00000010, 0x00000001, 0x00000011,
+	0x00001000, 0x00001010, 0x00001001, 0x00001011,
+	0x00000100, 0x00000110, 0x00000101, 0x00000111,
+	0x00001100, 0x00001110, 0x00001101, 0x00001111,
+	0x00100000, 0x00100010, 0x00100001, 0x00100011,
+	0x00101000, 0x00101010, 0x00101001, 0x00101011,
+	0x00100100, 0x00100110, 0x00100101, 0x00100111,
+	0x00101100, 0x00101110, 0x00101101, 0x00101111,
+	0x00010000, 0x00010010, 0x00010001, 0x00010011,
+	0x00011000, 0x00011010, 0x00011001, 0x00011011,
+	0x00010100, 0x00010110, 0x00010101, 0x00010111,
+	0x00011100, 0x00011110, 0x00011101, 0x00011111,
+	0x00110000, 0x00110010, 0x00110001, 0x00110011,
+	0x00111000, 0x00111010, 0x00111001, 0x00111011,
+	0x00110100, 0x00110110, 0x00110101, 0x00110111,
+	0x00111100, 0x00111110, 0x00111101, 0x00111111,
+	0x10000000, 0x10000010, 0x10000001, 0x10000011,
+	0x10001000, 0x10001010, 0x10001001, 0x10001011,
+	0x10000100, 0x10000110, 0x10000101, 0x10000111,
+	0x10001100, 0x10001110, 0x10001101, 0x10001111,
+	0x10100000, 0x10100010, 0x10100001, 0x10100011,
+	0x10101000, 0x10101010, 0x10101001, 0x10101011,
+	0x10100100, 0x10100110, 0x10100101, 0x10100111,
+	0x10101100, 0x10101110, 0x10101101, 0x10101111,
+	0x10010000, 0x10010010, 0x10010001, 0x10010011,
+	0x10011000, 0x10011010, 0x10011001, 0x10011011,
+	0x10010100, 0x10010110, 0x10010101, 0x10010111,
+	0x10011100, 0x10011110, 0x10011101, 0x10011111,
+	0x10110000, 0x10110010, 0x10110001, 0x10110011,
+	0x10111000, 0x10111010, 0x10111001, 0x10111011,
+	0x10110100, 0x10110110, 0x10110101, 0x10110111,
+	0x10111100, 0x10111110, 0x10111101, 0x10111111,
+	0x01000000, 0x01000010, 0x01000001, 0x01000011,
+	0x01001000, 0x01001010, 0x01001001, 0x01001011,
+	0x01000100, 0x01000110, 0x01000101, 0x01000111,
+	0x01001100, 0x01001110, 0x01001101, 0x01001111,
+	0x01100000, 0x01100010, 0x01100001, 0x01100011,
+	0x01101000, 0x01101010, 0x01101001, 0x01101011,
+	0x01100100, 0x01100110, 0x01100101, 0x01100111,
+	0x01101100, 0x01101110, 0x01101101, 0x01101111,
+	0x01010000, 0x01010010, 0x01010001, 0x01010011,
+	0x01011000, 0x01011010, 0x01011001, 0x01011011,
+	0x01010100, 0x01010110, 0x01010101, 0x01010111,
+	0x01011100, 0x01011110, 0x01011101, 0x01011111,
+	0x01110000, 0x01110010, 0x01110001, 0x01110011,
+	0x01111000, 0x01111010, 0x01111001, 0x01111011,
+	0x01110100, 0x01110110, 0x01110101, 0x01110111,
+	0x01111100, 0x01111110, 0x01111101, 0x01111111,
+	0x11000000, 0x11000010, 0x11000001, 0x11000011,
+	0x11001000, 0x11001010, 0x11001001, 0x11001011,
+	0x11000100, 0x11000110, 0x11000101, 0x11000111,
+	0x11001100, 0x11001110, 0x11001101, 0x11001111,
+	0x11100000, 0x11100010, 0x11100001, 0x11100011,
+	0x11101000, 0x11101010, 0x11101001, 0x11101011,
+	0x11100100, 0x11100110, 0x11100101, 0x11100111,
+	0x11101100, 0x11101110, 0x11101101, 0x11101111,
+	0x11010000, 0x11010010, 0x11010001, 0x11010011,
+	0x11011000, 0x11011010, 0x11011001, 0x11011011,
+	0x11010100, 0x11010110, 0x11010101, 0x11010111,
+	0x11011100, 0x11011110, 0x11011101, 0x11011111,
+	0x11110000, 0x11110010, 0x11110001, 0x11110011,
+	0x11111000, 0x11111010, 0x11111001, 0x11111011,
+	0x11110100, 0x11110110, 0x11110101, 0x11110111,
+	0x11111100, 0x11111110, 0x11111101, 0x11111111
+};
+
+/*
+ * The final permutation array.  Like the IP array, used
+ * to compute both the left and right results from the bytes
+ * of words computed from:
+ *
+ * ((left & 0x0f0f0f0f) << 4) | (right & 0x0f0f0f0f)  for left result
+ * (left & 0xf0f0f0f0) | ((right & 0xf0f0f0f0) >> 4)  for right result
+ *
+ * The result from the high order byte is shifted left 6 bits and
+ * or'd with the result from the next byte shifted left 4 bits, which
+ * is or'd with the result from the next byte shifted left 2 bits,
+ * which is or'd with the result from the low byte.
+ */
+const unsigned DES_INT32 des_FP_table[256] = {
+	0x00000000, 0x02000000, 0x00020000, 0x02020000,
+	0x00000200, 0x02000200, 0x00020200, 0x02020200,
+	0x00000002, 0x02000002, 0x00020002, 0x02020002,
+	0x00000202, 0x02000202, 0x00020202, 0x02020202,
+	0x01000000, 0x03000000, 0x01020000, 0x03020000,
+	0x01000200, 0x03000200, 0x01020200, 0x03020200,
+	0x01000002, 0x03000002, 0x01020002, 0x03020002,
+	0x01000202, 0x03000202, 0x01020202, 0x03020202,
+	0x00010000, 0x02010000, 0x00030000, 0x02030000,
+	0x00010200, 0x02010200, 0x00030200, 0x02030200,
+	0x00010002, 0x02010002, 0x00030002, 0x02030002,
+	0x00010202, 0x02010202, 0x00030202, 0x02030202,
+	0x01010000, 0x03010000, 0x01030000, 0x03030000,
+	0x01010200, 0x03010200, 0x01030200, 0x03030200,
+	0x01010002, 0x03010002, 0x01030002, 0x03030002,
+	0x01010202, 0x03010202, 0x01030202, 0x03030202,
+	0x00000100, 0x02000100, 0x00020100, 0x02020100,
+	0x00000300, 0x02000300, 0x00020300, 0x02020300,
+	0x00000102, 0x02000102, 0x00020102, 0x02020102,
+	0x00000302, 0x02000302, 0x00020302, 0x02020302,
+	0x01000100, 0x03000100, 0x01020100, 0x03020100,
+	0x01000300, 0x03000300, 0x01020300, 0x03020300,
+	0x01000102, 0x03000102, 0x01020102, 0x03020102,
+	0x01000302, 0x03000302, 0x01020302, 0x03020302,
+	0x00010100, 0x02010100, 0x00030100, 0x02030100,
+	0x00010300, 0x02010300, 0x00030300, 0x02030300,
+	0x00010102, 0x02010102, 0x00030102, 0x02030102,
+	0x00010302, 0x02010302, 0x00030302, 0x02030302,
+	0x01010100, 0x03010100, 0x01030100, 0x03030100,
+	0x01010300, 0x03010300, 0x01030300, 0x03030300,
+	0x01010102, 0x03010102, 0x01030102, 0x03030102,
+	0x01010302, 0x03010302, 0x01030302, 0x03030302,
+	0x00000001, 0x02000001, 0x00020001, 0x02020001,
+	0x00000201, 0x02000201, 0x00020201, 0x02020201,
+	0x00000003, 0x02000003, 0x00020003, 0x02020003,
+	0x00000203, 0x02000203, 0x00020203, 0x02020203,
+	0x01000001, 0x03000001, 0x01020001, 0x03020001,
+	0x01000201, 0x03000201, 0x01020201, 0x03020201,
+	0x01000003, 0x03000003, 0x01020003, 0x03020003,
+	0x01000203, 0x03000203, 0x01020203, 0x03020203,
+	0x00010001, 0x02010001, 0x00030001, 0x02030001,
+	0x00010201, 0x02010201, 0x00030201, 0x02030201,
+	0x00010003, 0x02010003, 0x00030003, 0x02030003,
+	0x00010203, 0x02010203, 0x00030203, 0x02030203,
+	0x01010001, 0x03010001, 0x01030001, 0x03030001,
+	0x01010201, 0x03010201, 0x01030201, 0x03030201,
+	0x01010003, 0x03010003, 0x01030003, 0x03030003,
+	0x01010203, 0x03010203, 0x01030203, 0x03030203,
+	0x00000101, 0x02000101, 0x00020101, 0x02020101,
+	0x00000301, 0x02000301, 0x00020301, 0x02020301,
+	0x00000103, 0x02000103, 0x00020103, 0x02020103,
+	0x00000303, 0x02000303, 0x00020303, 0x02020303,
+	0x01000101, 0x03000101, 0x01020101, 0x03020101,
+	0x01000301, 0x03000301, 0x01020301, 0x03020301,
+	0x01000103, 0x03000103, 0x01020103, 0x03020103,
+	0x01000303, 0x03000303, 0x01020303, 0x03020303,
+	0x00010101, 0x02010101, 0x00030101, 0x02030101,
+	0x00010301, 0x02010301, 0x00030301, 0x02030301,
+	0x00010103, 0x02010103, 0x00030103, 0x02030103,
+	0x00010303, 0x02010303, 0x00030303, 0x02030303,
+	0x01010101, 0x03010101, 0x01030101, 0x03030101,
+	0x01010301, 0x03010301, 0x01030301, 0x03030301,
+	0x01010103, 0x03010103, 0x01030103, 0x03030103,
+	0x01010303, 0x03010303, 0x01030303, 0x03030303
+};
+
+
+/*
+ * The SP table is actually the S boxes and the P permutation
+ * table combined.  This table is actually reordered from the
+ * spec, to match the order of key application we follow.
+ */
+const unsigned DES_INT32 des_SP_table[8][64] = {
+  {
+	0x00100000, 0x02100001, 0x02000401, 0x00000000,	/* 7 */
+	0x00000400, 0x02000401, 0x00100401, 0x02100400,
+	0x02100401, 0x00100000, 0x00000000, 0x02000001,
+	0x00000001, 0x02000000, 0x02100001, 0x00000401,
+	0x02000400, 0x00100401, 0x00100001, 0x02000400,
+	0x02000001, 0x02100000, 0x02100400, 0x00100001,
+	0x02100000, 0x00000400, 0x00000401, 0x02100401,
+	0x00100400, 0x00000001, 0x02000000, 0x00100400,
+	0x02000000, 0x00100400, 0x00100000, 0x02000401,
+	0x02000401, 0x02100001, 0x02100001, 0x00000001,
+	0x00100001, 0x02000000, 0x02000400, 0x00100000,
+	0x02100400, 0x00000401, 0x00100401, 0x02100400,
+	0x00000401, 0x02000001, 0x02100401, 0x02100000,
+	0x00100400, 0x00000000, 0x00000001, 0x02100401,
+	0x00000000, 0x00100401, 0x02100000, 0x00000400,
+	0x02000001, 0x02000400, 0x00000400, 0x00100001,
+  },
+  {
+	0x00808200, 0x00000000, 0x00008000, 0x00808202,	/* 1 */
+	0x00808002, 0x00008202, 0x00000002, 0x00008000,
+	0x00000200, 0x00808200, 0x00808202, 0x00000200,
+	0x00800202, 0x00808002, 0x00800000, 0x00000002,
+	0x00000202, 0x00800200, 0x00800200, 0x00008200,
+	0x00008200, 0x00808000, 0x00808000, 0x00800202,
+	0x00008002, 0x00800002, 0x00800002, 0x00008002,
+	0x00000000, 0x00000202, 0x00008202, 0x00800000,
+	0x00008000, 0x00808202, 0x00000002, 0x00808000,
+	0x00808200, 0x00800000, 0x00800000, 0x00000200,
+	0x00808002, 0x00008000, 0x00008200, 0x00800002,
+	0x00000200, 0x00000002, 0x00800202, 0x00008202,
+	0x00808202, 0x00008002, 0x00808000, 0x00800202,
+	0x00800002, 0x00000202, 0x00008202, 0x00808200,
+	0x00000202, 0x00800200, 0x00800200, 0x00000000,
+	0x00008002, 0x00008200, 0x00000000, 0x00808002,
+  },
+  {
+	0x00000104, 0x04010100, 0x00000000, 0x04010004,	/* 3 */
+	0x04000100, 0x00000000, 0x00010104, 0x04000100,
+	0x00010004, 0x04000004, 0x04000004, 0x00010000,
+	0x04010104, 0x00010004, 0x04010000, 0x00000104,
+	0x04000000, 0x00000004, 0x04010100, 0x00000100,
+	0x00010100, 0x04010000, 0x04010004, 0x00010104,
+	0x04000104, 0x00010100, 0x00010000, 0x04000104,
+	0x00000004, 0x04010104, 0x00000100, 0x04000000,
+	0x04010100, 0x04000000, 0x00010004, 0x00000104,
+	0x00010000, 0x04010100, 0x04000100, 0x00000000,
+	0x00000100, 0x00010004, 0x04010104, 0x04000100,
+	0x04000004, 0x00000100, 0x00000000, 0x04010004,
+	0x04000104, 0x00010000, 0x04000000, 0x04010104,
+	0x00000004, 0x00010104, 0x00010100, 0x04000004,
+	0x04010000, 0x04000104, 0x00000104, 0x04010000,
+	0x00010104, 0x00000004, 0x04010004, 0x00010100,
+  },
+  {
+	0x00000080, 0x01040080, 0x01040000, 0x21000080,	/* 5 */
+	0x00040000, 0x00000080, 0x20000000, 0x01040000,
+	0x20040080, 0x00040000, 0x01000080, 0x20040080,
+	0x21000080, 0x21040000, 0x00040080, 0x20000000,
+	0x01000000, 0x20040000, 0x20040000, 0x00000000,
+	0x20000080, 0x21040080, 0x21040080, 0x01000080,
+	0x21040000, 0x20000080, 0x00000000, 0x21000000,
+	0x01040080, 0x01000000, 0x21000000, 0x00040080,
+	0x00040000, 0x21000080, 0x00000080, 0x01000000,
+	0x20000000, 0x01040000, 0x21000080, 0x20040080,
+	0x01000080, 0x20000000, 0x21040000, 0x01040080,
+	0x20040080, 0x00000080, 0x01000000, 0x21040000,
+	0x21040080, 0x00040080, 0x21000000, 0x21040080,
+	0x01040000, 0x00000000, 0x20040000, 0x21000000,
+	0x00040080, 0x01000080, 0x20000080, 0x00040000,
+	0x00000000, 0x20040000, 0x01040080, 0x20000080,
+  },
+  {
+	0x80401000, 0x80001040, 0x80001040, 0x00000040,	/* 4 */
+	0x00401040, 0x80400040, 0x80400000, 0x80001000,
+	0x00000000, 0x00401000, 0x00401000, 0x80401040,
+	0x80000040, 0x00000000, 0x00400040, 0x80400000,
+	0x80000000, 0x00001000, 0x00400000, 0x80401000,
+	0x00000040, 0x00400000, 0x80001000, 0x00001040,
+	0x80400040, 0x80000000, 0x00001040, 0x00400040,
+	0x00001000, 0x00401040, 0x80401040, 0x80000040,
+	0x00400040, 0x80400000, 0x00401000, 0x80401040,
+	0x80000040, 0x00000000, 0x00000000, 0x00401000,
+	0x00001040, 0x00400040, 0x80400040, 0x80000000,
+	0x80401000, 0x80001040, 0x80001040, 0x00000040,
+	0x80401040, 0x80000040, 0x80000000, 0x00001000,
+	0x80400000, 0x80001000, 0x00401040, 0x80400040,
+	0x80001000, 0x00001040, 0x00400000, 0x80401000,
+	0x00000040, 0x00400000, 0x00001000, 0x00401040,
+  },
+  {
+	0x10000008, 0x10200000, 0x00002000, 0x10202008,	/* 6 */
+	0x10200000, 0x00000008, 0x10202008, 0x00200000,
+	0x10002000, 0x00202008, 0x00200000, 0x10000008,
+	0x00200008, 0x10002000, 0x10000000, 0x00002008,
+	0x00000000, 0x00200008, 0x10002008, 0x00002000,
+	0x00202000, 0x10002008, 0x00000008, 0x10200008,
+	0x10200008, 0x00000000, 0x00202008, 0x10202000,
+	0x00002008, 0x00202000, 0x10202000, 0x10000000,
+	0x10002000, 0x00000008, 0x10200008, 0x00202000,
+	0x10202008, 0x00200000, 0x00002008, 0x10000008,
+	0x00200000, 0x10002000, 0x10000000, 0x00002008,
+	0x10000008, 0x10202008, 0x00202000, 0x10200000,
+	0x00202008, 0x10202000, 0x00000000, 0x10200008,
+	0x00000008, 0x00002000, 0x10200000, 0x00202008,
+	0x00002000, 0x00200008, 0x10002008, 0x00000000,
+	0x10202000, 0x10000000, 0x00200008, 0x10002008,
+  },
+  {
+	0x08000820, 0x00000800, 0x00020000, 0x08020820,	/* 8 */
+	0x08000000, 0x08000820, 0x00000020, 0x08000000,
+	0x00020020, 0x08020000, 0x08020820, 0x00020800,
+	0x08020800, 0x00020820, 0x00000800, 0x00000020,
+	0x08020000, 0x08000020, 0x08000800, 0x00000820,
+	0x00020800, 0x00020020, 0x08020020, 0x08020800,
+	0x00000820, 0x00000000, 0x00000000, 0x08020020,
+	0x08000020, 0x08000800, 0x00020820, 0x00020000,
+	0x00020820, 0x00020000, 0x08020800, 0x00000800,
+	0x00000020, 0x08020020, 0x00000800, 0x00020820,
+	0x08000800, 0x00000020, 0x08000020, 0x08020000,
+	0x08020020, 0x08000000, 0x00020000, 0x08000820,
+	0x00000000, 0x08020820, 0x00020020, 0x08000020,
+	0x08020000, 0x08000800, 0x08000820, 0x00000000,
+	0x08020820, 0x00020800, 0x00020800, 0x00000820,
+	0x00000820, 0x00020020, 0x08000000, 0x08020800,
+  },
+  {
+	0x40084010, 0x40004000, 0x00004000, 0x00084010,	/* 2 */
+	0x00080000, 0x00000010, 0x40080010, 0x40004010,
+	0x40000010, 0x40084010, 0x40084000, 0x40000000,
+	0x40004000, 0x00080000, 0x00000010, 0x40080010,
+	0x00084000, 0x00080010, 0x40004010, 0x00000000,
+	0x40000000, 0x00004000, 0x00084010, 0x40080000,
+	0x00080010, 0x40000010, 0x00000000, 0x00084000,
+	0x00004010, 0x40084000, 0x40080000, 0x00004010,
+	0x00000000, 0x00084010, 0x40080010, 0x00080000,
+	0x40004010, 0x40080000, 0x40084000, 0x00004000,
+	0x40080000, 0x40004000, 0x00000010, 0x40084010,
+	0x00084010, 0x00000010, 0x00004000, 0x40000000,
+	0x00004010, 0x40084000, 0x00080000, 0x40000010,
+	0x00080010, 0x40004010, 0x40000010, 0x00080010,
+	0x00084000, 0x00000000, 0x40004000, 0x00004010,
+	0x40000000, 0x40080010, 0x40084010, 0x00084000
+  },
+};
diff --git a/krb5-1-6/src/lib/crypto/des/f_tables.h b/krb5-1-6/src/lib/crypto/des/f_tables.h
new file mode 100644
index 000000000..65181157a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/f_tables.h
@@ -0,0 +1,260 @@
+/*
+ * 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_tables.h - declarations to import the DES tables, used internally
+ *		  by some of the library routines.
+ */
+#ifndef	__DES_TABLES_H__
+#define	__DES_TABLES_H__	/* nothing */
+
+#include "k5-platform.h"
+/*
+ * These may be declared const if you wish.  Be sure to change the
+ * declarations in des_tables.c as well.
+ */
+extern const unsigned DES_INT32 des_IP_table[256];
+extern const unsigned DES_INT32 des_FP_table[256];
+extern const unsigned DES_INT32 des_SP_table[8][64];
+
+/*
+ * Use standard shortforms to reference these to save typing
+ */
+#define	IP	des_IP_table
+#define	FP	des_FP_table
+#define	SP	des_SP_table
+
+#ifdef DEBUG
+#define	DEB(foofraw)	printf foofraw
+#else
+#define	DEB(foofraw)	/* nothing */
+#endif
+
+/*
+ * Code to do a DES round using the tables.  Note that the E expansion
+ * is easy to compute algorithmically, especially if done out-of-order.
+ * Take a look at its form and compare it to everything involving temp
+ * below.  Since SP[0-7] don't have any bits in common set it is okay
+ * to do the successive xor's.
+ *
+ * Note too that the SP table has been reordered to match the order of
+ * the keys (if the original order of SP was 12345678, the reordered
+ * table is 71354682).  This is unnecessary, but was done since some
+ * compilers seem to like you going through the matrix from beginning
+ * to end.
+ *
+ * There is a difference in the best way to do this depending on whether
+ * one is encrypting or decrypting.  If encrypting we move forward through
+ * the keys and hence should move forward through the table.  If decrypting
+ * we go back.  Part of the need for this comes from trying to emulate
+ * existing software which generates a single key schedule and uses it
+ * both for encrypting and decrypting.  Generating separate encryption
+ * and decryption key schedules would allow one to use the same code
+ * for both.
+ *
+ * left, right and temp should be unsigned DES_INT32 values.  left and right
+ * should be the high and low order parts of the cipher block at the
+ * current stage of processing (this makes sense if you read the spec).
+ * kp should be an unsigned DES_INT32 pointer which points at the current
+ * set of subkeys in the key schedule.  It is advanced to the next set
+ * (i.e. by 8 bytes) when this is done.
+ *
+ * This occurs in the innermost loop of the DES function.  The four
+ * variables should really be in registers.
+ *
+ * When using this, the inner loop of the DES function might look like:
+ *
+ *	for (i = 0; i < 8; i++) {
+ *		DES_SP_{EN,DE}CRYPT_ROUND(left, right, temp, kp);
+ *		DES_SP_{EN,DE}CRYPT_ROUND(right, left, temp, kp);
+ *	}
+ *
+ * Note the trick above.  You are supposed to do 16 rounds, swapping
+ * left and right at the end of each round.  By doing two rounds at
+ * a time and swapping left and right in the code we can avoid the
+ * swaps altogether.
+ */
+#define	DES_SP_ENCRYPT_ROUND(left, right, temp, kp) \
+	(temp) = (((right) >> 11) | ((right) << 21)) ^ *(kp)++; \
+	(left) ^= SP[0][((temp) >> 24) & 0x3f] \
+		| SP[1][((temp) >> 16) & 0x3f] \
+		| SP[2][((temp) >>  8) & 0x3f] \
+		| SP[3][((temp)      ) & 0x3f]; \
+	(temp) = (((right) >> 23) | ((right) << 9)) ^ *(kp)++; \
+	(left) ^= SP[4][((temp) >> 24) & 0x3f] \
+		| SP[5][((temp) >> 16) & 0x3f] \
+		| SP[6][((temp) >>  8) & 0x3f] \
+		| SP[7][((temp)      ) & 0x3f]
+
+#define	DES_SP_DECRYPT_ROUND(left, right, temp, kp) \
+	(temp) = (((right) >> 23) | ((right) << 9)) ^ *(--(kp)); \
+	(left) ^= SP[7][((temp)      ) & 0x3f] \
+		| SP[6][((temp) >>  8) & 0x3f] \
+		| SP[5][((temp) >> 16) & 0x3f] \
+		| SP[4][((temp) >> 24) & 0x3f]; \
+	(temp) = (((right) >> 11) | ((right) << 21)) ^ *(--(kp)); \
+	(left) ^= SP[3][((temp)      ) & 0x3f] \
+		| SP[2][((temp) >>  8) & 0x3f] \
+		| SP[1][((temp) >> 16) & 0x3f] \
+		| SP[0][((temp) >> 24) & 0x3f]
+
+/*
+ * Macros to help deal with the initial permutation table.  Note
+ * the IP table only deals with 32 bits at a time, allowing us to
+ * collect the bits we need to deal with each half into an unsigned
+ * DES_INT32.  By carefully selecting how the bits are ordered we also
+ * take advantages of symmetries in the table so that we can use a
+ * single table to compute the permutation of all bytes.  This sounds
+ * complicated, but if you go through the process of designing the
+ * table you'll find the symmetries fall right out.
+ *
+ * The follow macros compute the set of bits used to index the
+ * table for produce the left and right permuted result.
+ *
+ * The inserted cast to unsigned DES_INT32 circumvents a bug in
+ * the Macintosh MPW 3.2 C compiler which loses the unsignedness and
+ * propagates the high-order bit in the shift.
+ */
+#define	DES_IP_LEFT_BITS(left, right) \
+	((((left) & 0x55555555) << 1) | ((right) & 0x55555555))
+#define	DES_IP_RIGHT_BITS(left, right) \
+	(((left) & 0xaaaaaaaa) | \
+		( ( (unsigned DES_INT32) ((right) & 0xaaaaaaaa) ) >> 1))
+
+/*
+ * The following macro does an in-place initial permutation given
+ * the current left and right parts of the block and a single
+ * temporary.  Use this more as a guide for rolling your own, though.
+ * The best way to do the IP depends on the form of the data you
+ * are dealing with.  If you use this, though, try to make left,
+ * right and temp register unsigned DES_INT32s.
+ */
+#define	DES_INITIAL_PERM(left, right, temp) \
+	(temp) = DES_IP_RIGHT_BITS((left), (right)); \
+	(right) = DES_IP_LEFT_BITS((left), (right)); \
+	(left) = IP[((right) >> 24) & 0xff] \
+	       | (IP[((right) >> 16) & 0xff] << 1) \
+	       | (IP[((right) >>  8) & 0xff] << 2) \
+	       | (IP[(right) & 0xff] << 3); \
+	(right) = IP[((temp) >> 24) & 0xff] \
+		| (IP[((temp) >> 16) & 0xff] << 1) \
+		| (IP[((temp) >>  8) & 0xff] << 2) \
+		| (IP[(temp) & 0xff] << 3)
+
+/*
+ * Now the final permutation stuff.  The same comments apply to
+ * this as to the initial permutation, except that we use different
+ * bits and shifts.
+ *
+ * The inserted cast to unsigned DES_INT32 circumvents a bug in
+ * the Macintosh MPW 3.2 C compiler which loses the unsignedness and
+ * propagates the high-order bit in the shift.
+ */
+#define DES_FP_LEFT_BITS(left, right) \
+	((((left) & 0x0f0f0f0f) << 4) | ((right) & 0x0f0f0f0f))
+#define	DES_FP_RIGHT_BITS(left, right) \
+	(((left) & 0xf0f0f0f0) | \
+		( ( (unsigned DES_INT32) ((right) & 0xf0f0f0f0) ) >> 4))
+
+
+/*
+ * Here is a sample final permutation.  Note that there is a trick
+ * here.  DES requires swapping the left and right parts after the
+ * last cipher round but before the final permutation.  We do this
+ * swapping internally, which is why left and right are confused
+ * at the beginning.
+ */
+#define DES_FINAL_PERM(left, right, temp) \
+	(temp) = DES_FP_RIGHT_BITS((right), (left)); \
+	(right) = DES_FP_LEFT_BITS((right), (left)); \
+	(left) = (FP[((right) >> 24) & 0xff] << 6) \
+	       | (FP[((right) >> 16) & 0xff] << 4) \
+	       | (FP[((right) >>  8) & 0xff] << 2) \
+	       |  FP[(right) & 0xff]; \
+	(right) = (FP[((temp) >> 24) & 0xff] << 6) \
+		| (FP[((temp) >> 16) & 0xff] << 4) \
+		| (FP[((temp) >>  8) & 0xff] << 2) \
+		|  FP[temp & 0xff]
+
+
+/*
+ * Finally, as a sample of how all this might be held together, the
+ * following two macros do in-place encryptions and decryptions.  left
+ * and right are two unsigned DES_INT32 variables which at the beginning
+ * are expected to hold the clear (encrypted) block in host byte order
+ * (left the high order four bytes, right the low order).  At the end
+ * they will contain the encrypted (clear) block.  temp is an unsigned DES_INT32
+ * used as a temporary.  kp is an unsigned DES_INT32 pointer pointing at
+ * the start of the key schedule.  All these should be in registers.
+ *
+ * You can probably do better than these by rewriting for particular
+ * situations.  These aren't bad, though.
+ *
+ * The DEB macros enable debugging when this code breaks (typically
+ * when a buggy compiler breaks it), by printing the intermediate values
+ * at each stage of the encryption, so that by comparing the output to
+ * a known good machine, the location of the first error can be found.
+ */
+#define	DES_DO_ENCRYPT_1(left, right, kp) \
+	do { \
+		register int i; \
+		register unsigned DES_INT32 temp1; \
+		DEB (("do_encrypt %8lX %8lX \n", left, right)); \
+		DES_INITIAL_PERM((left), (right), (temp1)); \
+		DEB (("  after IP %8lX %8lX\n", left, right)); \
+		for (i = 0; i < 8; i++) { \
+			DES_SP_ENCRYPT_ROUND((left), (right), (temp1), (kp)); \
+			DEB (("  round %2d %8lX %8lX \n", i*2, left, right)); \
+			DES_SP_ENCRYPT_ROUND((right), (left), (temp1), (kp)); \
+			DEB (("  round %2d %8lX %8lX \n", 1+i*2, left, right)); \
+		} \
+		DES_FINAL_PERM((left), (right), (temp1)); \
+		(kp) -= (2 * 16); \
+		DEB (("  after FP %8lX %8lX \n", left, right)); \
+	} while (0)
+
+#define	DES_DO_DECRYPT_1(left, right, kp) \
+	do { \
+		register int i; \
+		register unsigned DES_INT32 temp2; \
+		DES_INITIAL_PERM((left), (right), (temp2)); \
+		(kp) += (2 * 16); \
+		for (i = 0; i < 8; i++) { \
+			DES_SP_DECRYPT_ROUND((left), (right), (temp2), (kp)); \
+			DES_SP_DECRYPT_ROUND((right), (left), (temp2), (kp)); \
+		} \
+		DES_FINAL_PERM((left), (right), (temp2)); \
+	} while (0)
+
+#ifdef CONFIG_SMALL
+extern void krb5int_des_do_encrypt_2(unsigned DES_INT32 *l,
+				     unsigned DES_INT32 *r,
+				     const unsigned DES_INT32 *k);
+extern void krb5int_des_do_decrypt_2(unsigned DES_INT32 *l,
+				     unsigned DES_INT32 *r,
+				     const unsigned DES_INT32 *k);
+#define DES_DO_ENCRYPT(L,R,K) krb5int_des_do_encrypt_2(&(L), &(R), (K))
+#define DES_DO_DECRYPT(L,R,K) krb5int_des_do_decrypt_2(&(L), &(R), (K))
+#else
+#define DES_DO_ENCRYPT DES_DO_ENCRYPT_1
+#define DES_DO_DECRYPT DES_DO_DECRYPT_1
+#endif
+
+/*
+ * These are handy dandy utility thingies for straightening out bytes.
+ * Included here because they're used a couple of places.
+ */
+#define	GET_HALF_BLOCK(lr, ip)	((lr) = load_32_be(ip), (ip) += 4)
+#define PUT_HALF_BLOCK(lr, op)	(store_32_be(lr, op), (op) += 4)
+
+/* Shorthand that we'll need in several places, for creating values that
+   really can hold 32 bits regardless of the prevailing int size.  */
+#define FF_UINT32	((unsigned DES_INT32) 0xFF)
+
+#endif	/* __DES_TABLES_H__ */
diff --git a/krb5-1-6/src/lib/crypto/des/key_sched.c b/krb5-1-6/src/lib/crypto/des/key_sched.c
new file mode 100644
index 000000000..26449a94c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/key_sched.c
@@ -0,0 +1,61 @@
+/*
+ * lib/crypto/des/key_sched.c
+ *
+ * Copyright 1985, 1986, 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This routine computes the DES key schedule given a key.  The
+ * permutations and shifts have been done at compile time, resulting
+ * in a direct one-step mapping from the input key to the key
+ * schedule.
+ *
+ * Also checks parity and weak keys.
+ *
+ * Watch out for the subscripts -- most effectively start at 1 instead
+ * of at zero.  Maybe some bugs in that area.
+ *
+ * In case the user wants to cache the computed key schedule, it is
+ * passed as an arg.  Also implies that caller has explicit control
+ * over zeroing both the key schedule and the key.
+ *
+ * Originally written 6/85 by Steve Miller, MIT Project Athena.
+ */
+
+#include "k5-int.h"
+#include "des_int.h"
+
+int
+mit_des_key_sched(mit_des_cblock k, mit_des_key_schedule schedule)
+{
+    mit_des_make_key_sched(k,schedule);
+
+    if (!mit_des_check_key_parity(k))	/* bad parity --> return -1 */
+	return(-1);
+
+    if (mit_des_is_weak_key(k))
+	return(-2);
+
+    /* if key was good, return 0 */
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/des/keytest.data b/krb5-1-6/src/lib/crypto/des/keytest.data
new file mode 100644
index 000000000..7ff34eedc
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/keytest.data
@@ -0,0 +1,171 @@
+0101010101010101 95F8A5E5DD31D900 8000000000000000
+0101010101010101 DD7F121CA5015619 4000000000000000
+0101010101010101 2E8653104F3834EA 2000000000000000
+0101010101010101 4BD388FF6CD81D4F 1000000000000000
+0101010101010101 20B9E767B2FB1456 0800000000000000
+0101010101010101 55579380D77138EF 0400000000000000
+0101010101010101 6CC5DEFAAF04512F 0200000000000000
+0101010101010101 0D9F279BA5D87260 0100000000000000
+0101010101010101 D9031B0271BD5A0A 0080000000000000
+0101010101010101 424250B37C3DD951 0040000000000000
+0101010101010101 B8061B7ECD9A21E5 0020000000000000
+0101010101010101 F15D0F286B65BD28 0010000000000000
+0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000
+0101010101010101 E6D5F82752AD63D1 0004000000000000
+0101010101010101 ECBFE3BD3F591A5E 0002000000000000
+0101010101010101 F356834379D165CD 0001000000000000
+0101010101010101 2B9F982F20037FA9 0000800000000000
+0101010101010101 889DE068A16F0BE6 0000400000000000
+0101010101010101 E19E275D846A1298 0000200000000000
+0101010101010101 329A8ED523D71AEC 0000100000000000
+0101010101010101 E7FCE22557D23C97 0000080000000000
+0101010101010101 12A9F5817FF2D65D 0000040000000000
+0101010101010101 A484C3AD38DC9C19 0000020000000000
+0101010101010101 FBE00A8A1EF8AD72 0000010000000000
+0101010101010101 750D079407521363 0000008000000000
+0101010101010101 64FEED9C724C2FAF 0000004000000000
+0101010101010101 F02B263B328E2B60 0000002000000000
+0101010101010101 9D64555A9A10B852 0000001000000000
+0101010101010101 D106FF0BED5255D7 0000000800000000
+0101010101010101 E1652C6B138C64A5 0000000400000000
+0101010101010101 E428581186EC8F46 0000000200000000
+0101010101010101 AEB5F5EDE22D1A36 0000000100000000
+0101010101010101 E943D7568AEC0C5C 0000000080000000
+0101010101010101 DF98C8276F54B04B 0000000040000000
+0101010101010101 B160E4680F6C696F 0000000020000000
+0101010101010101 FA0752B07D9C4AB8 0000000010000000
+0101010101010101 CA3A2B036DBC8502 0000000008000000
+0101010101010101 5E0905517BB59BCF 0000000004000000
+0101010101010101 814EEB3B91D90726 0000000002000000
+0101010101010101 4D49DB1532919C9F 0000000001000000
+0101010101010101 25EB5FC3F8CF0621 0000000000800000
+0101010101010101 AB6A20C0620D1C6F 0000000000400000
+0101010101010101 79E90DBC98F92CCA 0000000000200000
+0101010101010101 866ECEDD8072BB0E 0000000000100000
+0101010101010101 8B54536F2F3E64A8 0000000000080000
+0101010101010101 EA51D3975595B86B 0000000000040000
+0101010101010101 CAFFC6AC4542DE31 0000000000020000
+0101010101010101 8DD45A2DDF90796C 0000000000010000
+0101010101010101 1029D55E880EC2D0 0000000000008000
+0101010101010101 5D86CB23639DBEA9 0000000000004000
+0101010101010101 1D1CA853AE7C0C5F 0000000000002000
+0101010101010101 CE332329248F3228 0000000000001000
+0101010101010101 8405D1ABE24FB942 0000000000000800
+0101010101010101 E643D78090CA4207 0000000000000400
+0101010101010101 48221B9937748A23 0000000000000200
+0101010101010101 DD7C0BBD61FAFD54 0000000000000100
+0101010101010101 2FBC291A570DB5C4 0000000000000080
+0101010101010101 E07C30D7E4E26E12 0000000000000040
+0101010101010101 0953E2258E8E90A1 0000000000000020
+0101010101010101 5B711BC4CEEBF2EE 0000000000000010
+0101010101010101 CC083F1E6D9E85F6 0000000000000008
+0101010101010101 D2FD8867D50D2DFE 0000000000000004
+0101010101010101 06E7EA22CE92708F 0000000000000002
+0101010101010101 166B40B44ABA4BD6 0000000000000001
+8001010101010101 0000000000000000 95A8D72813DAA94D
+4001010101010101 0000000000000000 0EEC1487DD8C26D5
+2001010101010101 0000000000000000 7AD16FFB79C45926
+1001010101010101 0000000000000000 D3746294CA6A6CF3
+0801010101010101 0000000000000000 809F5F873C1FD761
+0401010101010101 0000000000000000 C02FAFFEC989D1FC
+0201010101010101 0000000000000000 4615AA1D33E72F10
+0180010101010101 0000000000000000 2055123350C00858
+0140010101010101 0000000000000000 DF3B99D6577397C8
+0120010101010101 0000000000000000 31FE17369B5288C9
+0110010101010101 0000000000000000 DFDD3CC64DAE1642
+0108010101010101 0000000000000000 178C83CE2B399D94
+0104010101010101 0000000000000000 50F636324A9B7F80
+0102010101010101 0000000000000000 A8468EE3BC18F06D
+0101800101010101 0000000000000000 A2DC9E92FD3CDE92
+0101400101010101 0000000000000000 CAC09F797D031287
+0101200101010101 0000000000000000 90BA680B22AEB525
+0101100101010101 0000000000000000 CE7A24F350E280B6
+0101080101010101 0000000000000000 882BFF0AA01A0B87
+0101040101010101 0000000000000000 25610288924511C2
+0101020101010101 0000000000000000 C71516C29C75D170
+0101018001010101 0000000000000000 5199C29A52C9F059
+0101014001010101 0000000000000000 C22F0A294A71F29F
+0101012001010101 0000000000000000 EE371483714C02EA
+0101011001010101 0000000000000000 A81FBD448F9E522F
+0101010801010101 0000000000000000 4F644C92E192DFED
+0101010401010101 0000000000000000 1AFA9A66A6DF92AE
+0101010201010101 0000000000000000 B3C1CC715CB879D8
+0101010180010101 0000000000000000 19D032E64AB0BD8B
+0101010140010101 0000000000000000 3CFAA7A7DC8720DC
+0101010120010101 0000000000000000 B7265F7F447AC6F3
+0101010110010101 0000000000000000 9DB73B3C0D163F54
+0101010108010101 0000000000000000 8181B65BABF4A975
+0101010104010101 0000000000000000 93C9B64042EAA240
+0101010102010101 0000000000000000 5570530829705592
+0101010101800101 0000000000000000 8638809E878787A0
+0101010101400101 0000000000000000 41B9A79AF79AC208
+0101010101200101 0000000000000000 7A9BE42F2009A892
+0101010101100101 0000000000000000 29038D56BA6D2745
+0101010101080101 0000000000000000 5495C6ABF1E5DF51
+0101010101040101 0000000000000000 AE13DBD561488933
+0101010101020101 0000000000000000 024D1FFA8904E389
+0101010101018001 0000000000000000 D1399712F99BF02E
+0101010101014001 0000000000000000 14C1D7C1CFFEC79E
+0101010101012001 0000000000000000 1DE5279DAE3BED6F
+0101010101011001 0000000000000000 E941A33F85501303
+0101010101010801 0000000000000000 DA99DBBC9A03F379
+0101010101010401 0000000000000000 B7FC92F91D8E92E9
+0101010101010201 0000000000000000 AE8E5CAA3CA04E85
+0101010101010180 0000000000000000 9CC62DF43B6EED74
+0101010101010140 0000000000000000 D863DBB5C59A91A0
+0101010101010120 0000000000000000 A1AB2190545B91D7
+0101010101010110 0000000000000000 0875041E64C570F7
+0101010101010108 0000000000000000 5A594528BEBEF1CC
+0101010101010104 0000000000000000 FCDB3291DE21F0C0
+0101010101010102 0000000000000000 869EFD7F9F265A09
+1046913489980131 0000000000000000 88D55E54F54C97B4
+1007103489988020 0000000000000000 0C0CC00C83EA48FD
+10071034C8980120 0000000000000000 83BC8EF3A6570183
+1046103489988020 0000000000000000 DF725DCAD94EA2E9
+1086911519190101 0000000000000000 E652B53B550BE8B0
+1086911519580101 0000000000000000 AF527120C485CBB0
+5107B01519580101 0000000000000000 0F04CE393DB926D5
+1007B01519190101 0000000000000000 C9F00FFC74079067
+3107915498080101 0000000000000000 7CFD82A593252B4E
+3107919498080101 0000000000000000 CB49A2F9E91363E3
+10079115B9080140 0000000000000000 00B588BE70D23F56
+3107911598080140 0000000000000000 406A9A6AB43399AE
+1007D01589980101 0000000000000000 6CB773611DCA9ADA
+9107911589980101 0000000000000000 67FD21C17DBB5D70
+9107D01589190101 0000000000000000 9592CB4110430787
+1007D01598980120 0000000000000000 A6B7FF68A318DDD3
+1007940498190101 0000000000000000 4D102196C914CA16
+0107910491190401 0000000000000000 2DFA9F4573594965
+0107910491190101 0000000000000000 B46604816C0E0774
+0107940491190401 0000000000000000 6E7E6221A4F34E87
+19079210981A0101 0000000000000000 AA85E74643233199
+1007911998190801 0000000000000000 2E5A19DB4D1962D6
+10079119981A0801 0000000000000000 23A866A809D30894
+1007921098190101 0000000000000000 D812D961F017D320
+100791159819010B 0000000000000000 055605816E58608F
+1004801598190101 0000000000000000 ABD88E8B1B7716F1
+1004801598190102 0000000000000000 537AC95BE69DA1E1
+1004801598190108 0000000000000000 AED0F6AE3C25CDD8
+1002911598100104 0000000000000000 B3E35A5EE53E7B8D
+1002911598190104 0000000000000000 61C79C71921A2EF8
+1002911598100201 0000000000000000 E2F5728F0995013C
+1002911698100101 0000000000000000 1AEAC39A61F0A464
+7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
+0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
+07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
+3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
+04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
+0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
+0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
+43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
+07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
+04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
+37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
+1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
+584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
+025816164629B007 480D39006EE762F2 A1F9915541020B56
+49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
+4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
+49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
+018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
+1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
diff --git a/krb5-1-6/src/lib/crypto/des/string2key.c b/krb5-1-6/src/lib/crypto/des/string2key.c
new file mode 100644
index 000000000..4fe9e4799
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/string2key.c
@@ -0,0 +1,261 @@
+/*
+ * lib/crypto/des/des_s2k.c
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Compute encryption key from salt and pass phrase.
+ */
+
+#include "k5-int.h"
+#include "des_int.h"
+
+krb5_error_code
+mit_des_string_to_key_int (krb5_keyblock *key,
+			   const krb5_data *pw, const krb5_data *salt)
+{
+    union {
+	/* 8 "forward" bytes, 8 "reverse" bytes */
+	unsigned char uc[16];
+	krb5_ui_4 ui[4];
+	mit_des_cblock cb;
+    } temp;
+    int i;
+    krb5_ui_4 x, y, z;
+    unsigned char *p;
+    des_key_schedule sched;
+    char *copy;
+    size_t copylen;
+
+    /* As long as the architecture is big-endian or little-endian, it
+       doesn't matter which it is.  Think of it as reversing the
+       bytes, and also reversing the bits within each byte.  But this
+       current algorithm is dependent on having four 8-bit char values
+       exactly overlay a 32-bit integral type.  */
+    if (sizeof(temp.uc) != sizeof(temp.ui)
+	|| (unsigned char)~0 != 0xFF
+	|| (krb5_ui_4)~(krb5_ui_4)0 != 0xFFFFFFFF
+	|| (temp.uc[0] = 1, temp.uc[1] = 2, temp.uc[2] = 3, temp.uc[3] = 4,
+	    !(temp.ui[0] == 0x01020304
+	      || temp.ui[0] == 0x04030201)))
+	abort();
+#define FETCH4(VAR, IDX)	VAR = temp.ui[IDX/4]
+#define PUT4(VAR, IDX)		temp.ui[IDX/4] = VAR
+
+    if (salt
+	&& (salt->length == SALT_TYPE_AFS_LENGTH
+	    /* XXX  Yuck!  Aren't we done with this yet?  */
+	    || salt->length == (unsigned) -1)) {
+	krb5_data afssalt;
+	char *at;
+
+	afssalt.data = salt->data;
+	at = strchr(afssalt.data, '@');
+	if (at) {
+	    *at = 0;
+	    afssalt.length = at - afssalt.data;
+	} else
+	    afssalt.length = strlen(afssalt.data);
+	return mit_afs_string_to_key(key, pw, &afssalt);
+    }
+
+    copylen = pw->length + (salt ? salt->length : 0);
+    /* Don't need NUL termination, at this point we're treating it as
+       a byte array, not a string.  */
+    copy = malloc(copylen);
+    if (copy == NULL)
+	return errno;
+    memcpy(copy, pw->data, pw->length);
+    if (salt)
+	memcpy(copy + pw->length, salt->data, salt->length);
+
+    memset(&temp, 0, sizeof(temp));
+    p = temp.uc;
+    /* Handle the fan-fold xor operation by splitting the data into
+       forward and reverse sections, and combine them later, rather
+       than having to do the reversal over and over again.  */
+    for (i = 0; i < copylen; i++) {
+	*p++ ^= copy[i];
+	if (p == temp.uc+16) {
+	    p = temp.uc;
+#ifdef PRINT_TEST_VECTORS
+	    {
+		int j;
+		printf("after %d input bytes:\nforward block:\t", i+1);
+		for (j = 0; j < 8; j++)
+		    printf(" %02x", temp.uc[j] & 0xff);
+		printf("\nreverse block:\t");
+		for (j = 8; j < 16; j++)
+		    printf(" %02x", temp.uc[j] & 0xff);
+		printf("\n");
+	    }
+#endif
+	}
+    }
+
+#ifdef PRINT_TEST_VECTORS
+    if (p != temp.uc) {
+	int j;
+	printf("at end, after %d input bytes:\nforward block:\t", i);
+	for (j = 0; j < 8; j++)
+	    printf(" %02x", temp.uc[j] & 0xff);
+	printf("\nreverse block:\t");
+	for (j = 8; j < 16; j++)
+	    printf(" %02x", temp.uc[j] & 0xff);
+	printf("\n");
+    }
+#endif
+#if 0
+    /* Algorithm described in Dr. Dobbs Journal 1983, reported in "bit
+       twiddling hacks" web page collected by Sean Eron Anderson; see
+       http://graphics.stanford.edu/~seander/bithacks.html for
+       details.
+
+       Avoids loops, uses 7*lg(N)=35 ops instead of 4*N=128 for the
+       obvious mask, ior, shift, shift sequence of each 32-bit
+       quantity.
+
+       If we could rely on 64-bit math, another 7 ops would save us
+       from having to do double the work.  */
+#define REVERSE_STEP(VAR, SHIFT, MASK)			\
+    VAR = ((VAR >> SHIFT) & MASK) | ((VAR << SHIFT) & (0xFFFFFFFFUL & ~MASK))
+#define REVERSE(VAR)						\
+    REVERSE_STEP (VAR, 1, 0x55555555UL); /* swap odd/even bits */	\
+    REVERSE_STEP (VAR, 2, 0x33333333UL); /* swap bitpairs */		\
+    REVERSE_STEP (VAR, 4, 0x0F0F0F0FUL); /* swap nibbles, etc */	\
+    REVERSE_STEP (VAR, 8, 0x00FF00FFUL);				\
+    REVERSE_STEP (VAR, 16, 0x0000FFFFUL);
+#else /* shorter */
+#define REVERSE(VAR)				\
+    {						\
+	krb5_ui_4 old = VAR, temp1 = 0;		\
+	int j;					\
+	for (j = 0; j < 32; j++) {		\
+	    temp1 = (temp1 << 1) | (old & 1);	\
+	    old >>= 1;				\
+	}					\
+	VAR = temp1;				\
+    }
+#endif
+
+    FETCH4 (x, 8);
+    FETCH4 (y, 12);
+    /* Ignore high bits of each input byte.  */
+    x &= 0x7F7F7F7F;
+    y &= 0x7F7F7F7F;
+    /* Reverse the bit strings -- after this, y is "before" x.  */
+    REVERSE (x);
+    REVERSE (y);
+#ifdef PRINT_TEST_VECTORS
+    {
+	int j;
+	union { unsigned char uc[4]; krb5_ui_4 ui; } t2;
+	printf("after reversal, reversed block:\n\t\t");
+	t2.ui = y;
+	for (j = 0; j < 4; j++)
+	    printf(" %02x", t2.uc[j] & 0xff);
+	t2.ui = x;
+	for (j = 0; j < 4; j++)
+	    printf(" %02x", t2.uc[j] & 0xff);
+	printf("\n");
+    }
+#endif
+    /* Ignored bits are now at the bottom of each byte, where we'll
+       put the parity bits.  Good.  */
+    FETCH4 (z, 0);
+    z &= 0x7F7F7F7F;
+    /* Ignored bits for z are at the top of each byte; fix that.  */
+    z <<= 1;
+    /* Finish the fan-fold xor for these four bytes.  */
+    z ^= y;
+    PUT4 (z, 0);
+    /* Now do the second four bytes.  */
+    FETCH4 (z, 4);
+    z &= 0x7F7F7F7F;
+    /* Ignored bits for z are at the top of each byte; fix that.  */
+    z <<= 1;
+    /* Finish the fan-fold xor for these four bytes.  */
+    z ^= x;
+    PUT4 (z, 4);
+
+#ifdef PRINT_TEST_VECTORS
+    {
+	int j;
+	printf("after reversal, combined block:\n\t\t");
+	for (j = 0; j < 8; j++)
+	    printf(" %02x", temp.uc[j] & 0xff);
+	printf("\n");
+    }
+#endif
+
+#define FIXUP(K)					\
+    (mit_des_fixup_key_parity(K),			\
+     mit_des_is_weak_key(K) ? (K[7] ^= 0xF0) : 0)
+
+    /* Now temp.cb is the temporary key, with invalid parity.  */
+    FIXUP(temp.cb);
+
+#ifdef PRINT_TEST_VECTORS
+    {
+	int j;
+	printf("after fixing parity and weak keys:\n\t\t");
+	for (j = 0; j < 8; j++)
+	    printf(" %02x", temp.uc[j] & 0xff);
+	printf("\n");
+    }
+#endif
+
+    mit_des_key_sched(temp.cb, sched);
+    mit_des_cbc_cksum(copy, temp.cb, copylen, sched, temp.cb);
+
+    memset(copy, 0, copylen);
+    free(copy);
+
+#ifdef PRINT_TEST_VECTORS
+    {
+	int j;
+	printf("cbc checksum:\n\t\t");
+	for (j = 0; j < 8; j++)
+	    printf(" %02x", temp.uc[j] & 0xff);
+	printf("\n");
+    }
+#endif
+
+    memset(sched, 0, sizeof(sched));
+    FIXUP (temp.cb);
+
+#ifdef PRINT_TEST_VECTORS
+    {
+	int j;
+	printf("after fixing parity and weak keys:\n\t\t");
+	for (j = 0; j < 8; j++)
+	    printf(" %02x", temp.uc[j] & 0xff);
+	printf("\n");
+    }
+#endif
+
+    memcpy(key->contents, temp.cb, 8);
+    memset(&temp, 0, sizeof(temp));
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/des/t_afss2k.c b/krb5-1-6/src/lib/crypto/des/t_afss2k.c
new file mode 100644
index 000000000..a6d0aa58d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/t_afss2k.c
@@ -0,0 +1,136 @@
+#include "des_int.h"
+
+static const char *me;
+
+struct test_case {
+	char *saltstr;
+	int saltlen;
+	unsigned char keys[12][8];
+};
+
+struct test_case test_cases[] = {
+	{
+		"Sodium Chloride", -1,
+		{
+			{ 0xa4, 0xd0, 0xd0, 0x9b, 0x86, 0x92, 0xb0, 0xc2, },
+			{ 0xf1, 0xf2, 0x9e, 0xab, 0xd0, 0xef, 0xdf, 0x73, },
+			{ 0xd6, 0x85, 0x61, 0xc4, 0xf2, 0x94, 0xf4, 0xa1, },
+			{ 0xd0, 0xe3, 0xa7, 0x83, 0x94, 0x61, 0xe0, 0xd0, },
+			{ 0xd5, 0x62, 0xcd, 0x94, 0x61, 0xcb, 0x97, 0xdf, },
+			{ 0x9e, 0xa2, 0xa2, 0xec, 0xa8, 0x8c, 0x6b, 0x8f, },
+			{ 0xe3, 0x91, 0x6d, 0xd3, 0x85, 0xf1, 0x67, 0xc4, },
+			{ 0xf4, 0xc4, 0x73, 0xc8, 0x8a, 0xe9, 0x94, 0x6d, },
+			{ 0xa1, 0x9e, 0xb3, 0xad, 0x6b, 0xe3, 0xab, 0xd9, },
+			{ 0xad, 0xa1, 0xce, 0x10, 0x37, 0x83, 0xa7, 0x8c, },
+			{ 0xd3, 0x01, 0xd0, 0xf7, 0x3e, 0x7a, 0x49, 0x0b, },
+			{ 0xb6, 0x2a, 0x4a, 0xec, 0x9d, 0x4c, 0x68, 0xdf, },
+		}
+	},
+	{
+		"NaCl", 4,
+		{
+			{ 0x61, 0xef, 0xe6, 0x83, 0xe5, 0x8a, 0x6b, 0x98 },
+			{ 0x68, 0xcd, 0x68, 0xad, 0xc4, 0x86, 0xcd, 0xe5 },
+			{ 0x83, 0xa1, 0xc8, 0x86, 0x8f, 0x67, 0xd0, 0x62 },
+			{ 0x9e, 0xc7, 0x8f, 0xa4, 0xa4, 0xb3, 0xe0, 0xd5 },
+			{ 0xd9, 0x92, 0x86, 0x8f, 0x9d, 0x8c, 0x85, 0xe6 },
+			{ 0xda, 0xf2, 0x92, 0x83, 0xf4, 0x9b, 0xa7, 0xad },
+			{ 0x91, 0xcd, 0xad, 0xef, 0x86, 0xdf, 0xd3, 0xa2 },
+			{ 0x73, 0xd3, 0x67, 0x68, 0x8f, 0x6e, 0xe3, 0x73 },
+			{ 0xc4, 0x61, 0x85, 0x9d, 0xad, 0xf4, 0xdc, 0xb0 },
+			{ 0xe9, 0x02, 0x83, 0x16, 0x2c, 0xec, 0xe0, 0x08 },
+			{ 0x61, 0xc8, 0x26, 0x29, 0xd9, 0x73, 0x6e, 0xb6 },
+			{ 0x8c, 0xa8, 0x9e, 0xc4, 0xa8, 0xdc, 0x31, 0x73 },
+		}
+	},
+	{
+		/* This one intentionally supplies a length shorter
+		   than the string.  The point of this is to ensure
+		   that s[len] is not zero, so that anything actually
+		   relying on that value (i.e., reading out of bounds)
+		   should generate incorrect results.  */
+		"NaCl2", 4,
+		{
+			{ 0x61, 0xef, 0xe6, 0x83, 0xe5, 0x8a, 0x6b, 0x98 },
+			{ 0x68, 0xcd, 0x68, 0xad, 0xc4, 0x86, 0xcd, 0xe5 },
+			{ 0x83, 0xa1, 0xc8, 0x86, 0x8f, 0x67, 0xd0, 0x62 },
+			{ 0x9e, 0xc7, 0x8f, 0xa4, 0xa4, 0xb3, 0xe0, 0xd5 },
+			{ 0xd9, 0x92, 0x86, 0x8f, 0x9d, 0x8c, 0x85, 0xe6 },
+			{ 0xda, 0xf2, 0x92, 0x83, 0xf4, 0x9b, 0xa7, 0xad },
+			{ 0x91, 0xcd, 0xad, 0xef, 0x86, 0xdf, 0xd3, 0xa2 },
+			{ 0x73, 0xd3, 0x67, 0x68, 0x8f, 0x6e, 0xe3, 0x73 },
+			{ 0xc4, 0x61, 0x85, 0x9d, 0xad, 0xf4, 0xdc, 0xb0 },
+			{ 0xe9, 0x02, 0x83, 0x16, 0x2c, 0xec, 0xe0, 0x08 },
+			{ 0x61, 0xc8, 0x26, 0x29, 0xd9, 0x73, 0x6e, 0xb6 },
+			{ 0x8c, 0xa8, 0x9e, 0xc4, 0xa8, 0xdc, 0x31, 0x73 },
+		}
+	},
+};
+
+static void do_it (struct test_case *tcase);
+
+int
+main (int argc, char *argv[])
+{
+	int i;
+
+	me = argv[0];
+	for (i = 0; i < sizeof (test_cases) / sizeof (struct test_case); i++)
+		do_it (&test_cases[i]);
+	return 0;
+}
+
+static void
+do_it (struct test_case *tcase)
+{
+	unsigned char keydata[8];
+	krb5_data salt, passwd;
+	krb5_keyblock key;
+	krb5_error_code err;
+	int i;
+	unsigned char longpass[2048];
+
+	key.contents = keydata;
+	key.length = sizeof (keydata);
+
+	salt.data = tcase->saltstr;
+	if (tcase->saltlen == -1)
+		salt.length = strlen (tcase->saltstr);
+	else
+		salt.length = tcase->saltlen;
+
+	/*
+	 * Try passwords with lengths equal to, greater than, and less
+	 * than 8 characters, since the AFS s2k algorithm does
+	 * interesting stuff depending on the length.
+	 */
+	passwd.data = "My Password";
+	for (i = 0; i < 12; i++) {
+		passwd.length = i;
+		err = mit_afs_string_to_key (&key, &passwd, &salt);
+		if (err != 0) {
+			com_err (me, err, "");
+			exit (1);
+		}
+		if (memcmp (tcase->keys[i], keydata, 8) != 0)
+			abort ();
+	}
+
+	/* Run another pass to make sure the characters after the
+	   password in the buffer aren't influencing the output.  The
+	   password is *not* required to be null-terminated.  */
+	memset (longpass, '!', sizeof (longpass));
+	longpass[sizeof (longpass)-1] = '\0';
+	memcpy (longpass, "My Password", strlen ("My Password"));
+	passwd.data = (char *) longpass;
+	for (i = 0; i < 12; i++) {
+		passwd.length = i;
+		err = mit_afs_string_to_key (&key, &passwd, &salt);
+		if (err != 0) {
+			com_err (me, err, "");
+			exit (1);
+		}
+		if (memcmp (tcase->keys[i], keydata, 8) != 0)
+			abort ();
+	}
+}
diff --git a/krb5-1-6/src/lib/crypto/des/t_verify.c b/krb5-1-6/src/lib/crypto/des/t_verify.c
new file mode 100644
index 000000000..a6ad07cb8
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/t_verify.c
@@ -0,0 +1,418 @@
+/*
+ * lib/crypto/des/verify.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Program to test the correctness of the DES library
+ * implementation.
+ *
+ * exit returns	 0 ==> success
+ * 		-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"
+
+static void do_encrypt(unsigned char *, unsigned char *);
+static void do_decrypt(unsigned char *, unsigned char *);
+
+char *progname;
+int nflag = 2;
+int vflag;
+int mflag;
+int zflag;
+int pid;
+int mit_des_debug;
+
+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 ";
+unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0};
+unsigned char output[64];
+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;
+
+/* 0x0123456789abcdef */
+unsigned char default_key[8] = {
+    0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
+};
+unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f };
+unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 };
+mit_des_cblock s_key;
+unsigned char default_ivec[8] = {
+    0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef
+};
+unsigned char *ivec;
+unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */
+
+unsigned char cipher1[8] = {
+    0x25,0xdd,0xac,0x3e,0x96,0x17,0x64,0x67
+};
+unsigned char cipher2[8] = {
+    0x3f,0xa4,0x0e,0x8a,0x98,0x4d,0x48,0x15
+};
+unsigned char cipher3[64] = {
+    0xe5,0xc7,0xcd,0xde,0x87,0x2b,0xf2,0x7c,
+    0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+    0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6
+};
+unsigned char checksum[8] = {
+    0x58,0xd2,0xe7,0x7e,0x86,0x06,0x27,0x33
+};
+
+unsigned char zresult[8] = {
+    0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7
+};
+
+unsigned char mresult[8] = {
+    0xa3, 0x80, 0xe0, 0x2a, 0x6b, 0xe5, 0x46, 0x96
+};
+
+    
+/*
+ * Can also add :
+ * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?)
+ */
+
+mit_des_key_schedule sched;
+
+int
+main(argc,argv)
+    int argc;
+    char *argv[];
+{
+    /* Local Declarations */
+    size_t  in_length;
+    int  retval;
+    int i, j;
+
+#ifdef WINDOWS
+    /* Set screen window buffer to infinite size -- MS default is tiny.  */
+    _wsetscreenbuf (fileno (stdout), _WINBUFINF);
+#endif
+    progname=argv[0];		/* salt away invoking program */
+
+    while (--argc > 0 && (*++argv)[0] == '-')
+	for (i=1; argv[0][i] != '\0'; i++) {
+	    switch (argv[0][i]) {
+
+		/* debug flag */
+	    case 'd':
+		mit_des_debug=3;
+		continue;
+
+	    case 'z':
+		zflag = 1;
+		continue;
+
+	    case 'm':
+		mflag = 1;
+		continue;
+
+	    default:
+		printf("%s: illegal flag \"%c\" ",
+		       progname,argv[0][i]);
+		exit(1);
+	    }
+	};
+
+    if (argc) {
+	fprintf(stderr, "Usage: %s [-dmz]\n", progname);
+	exit(1);
+    }
+
+    /* do some initialisation */
+
+    /* use known input and key */
+
+    /* ECB zero text zero key */
+    if (zflag) {
+	input = zero_text;
+	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");
+	for (j = 0; j<=7; j++)
+	    printf("%02x ",cipher_text[j]);
+	printf("\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)zresult, 8) ) {
+	    printf("verify: error in zero key test\n");
+	    exit(-1);
+	}
+
+	exit(0);
+    }
+
+    if (mflag) {
+	input = msb_text;
+	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");
+	do_encrypt(input,cipher_text);
+	printf("\tcipher  = (low to high bytes)\n\t\t");
+	for (j = 0; j<=7; j++) {
+	    printf("%02x ",cipher_text[j]);
+	}
+	printf("\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)mresult, 8) ) {
+	    printf("verify: error in msb test\n");
+	    exit(-1);
+	}
+	exit(0);
+    }
+
+    /* ECB mode Davies and Price */
+    {
+	input = zero_text;
+	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");
+	printf("Examples per Davies and Price.\n\n");
+	printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n");
+	printf("\tclear = 0\n");
+	printf("\tcipher = 25 dd ac 3e 96 17 64 67\n");
+	printf("ACTUAL ECB\n");
+	printf("\tclear \"%s\"\n", input);
+	do_encrypt(input,cipher_text);
+	printf("\tcipher  = (low to high bytes)\n\t\t");
+	for (j = 0; j<=7; j++)
+	    printf("%02x ",cipher_text[j]);
+	printf("\n\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)cipher1, 8) ) {
+	    printf("verify: error in ECB encryption\n");
+	    exit(-1);
+	}
+	else 
+	    printf("verify: ECB encryption is correct\n\n");
+    }
+
+    /* ECB mode */
+    {
+	mit_des_key_sched(default_key, sched);
+	input = clear_text;
+	ivec = default_ivec;
+	printf("EXAMPLE ECB\tkey = 0123456789abcdef\n");
+	printf("\tclear = \"Now is the time for all \"\n");
+	printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n");
+	printf("ACTUAL ECB\n\tclear \"%s\"",input);
+	do_encrypt(input,cipher_text);
+	printf("\n\tcipher	= (low to high bytes)\n\t\t");
+	for (j = 0; j<=7; j++) {
+	    printf("%02x ",cipher_text[j]);
+	}
+	printf("\n\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)cipher2, 8) ) {
+	    printf("verify: error in ECB encryption\n");
+	    exit(-1);
+	}
+	else 
+	    printf("verify: ECB encryption is correct\n\n");
+    }
+
+    /* CBC mode */
+    printf("EXAMPLE CBC\tkey = 0123456789abcdef");
+    printf("\tiv = 1234567890abcdef\n");
+    printf("\tclear = \"Now is the time for all \"\n");
+    printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n");
+    printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n");
+    printf("\t\t\t68 37 88 49 9a 7c 05 f6\n");
+
+    printf("ACTUAL CBC\n\tclear \"%s\"\n",input);
+    in_length =  strlen((char *)input);
+    if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) input,
+				      (mit_des_cblock *) cipher_text,
+				      (size_t) in_length, 
+				      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 <= 2; i++) {
+	printf("\t\t");
+	for (j = 0; j <= 7; j++) {
+	    printf("%02x ",cipher_text[i*8+j]);
+	}
+	printf("\n");
+    }
+    if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) cipher_text,
+				      (mit_des_cblock *) clear_text,
+				      (size_t) in_length, 
+				      sched,
+				      ivec,
+				      MIT_DES_DECRYPT))) {
+	com_err("des verify", retval, "can't decrypt");
+	exit(-1);
+    }
+    printf("\tdecrypted clear_text = \"%s\"\n",clear_text);
+
+    if ( memcmp((char *)cipher_text, (char *)cipher3, in_length) ) {
+	printf("verify: error in CBC encryption\n");
+	exit(-1);
+    }
+    else 
+	printf("verify: CBC encryption is correct\n\n");
+
+    printf("EXAMPLE CBC checksum");
+    printf("\tkey =  0123456789abcdef\tiv =  1234567890abcdef\n");
+    printf("\tclear =\t\t\"7654321 Now is the time for \"\n");
+    printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, ");
+    printf("or some part thereof\n");
+    input = clear_text2;
+    mit_des_cbc_cksum(input,cipher_text, strlen((char *)input),
+		      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 ( memcmp((char *)cipher_text, (char *)checksum, 8) ) {
+	printf("verify: error in CBC cheksum\n");
+	exit(-1);
+    }
+    else 
+	printf("verify: CBC checksum is correct\n\n");
+
+    exit(0);
+}
+
+#if 0
+void
+flip(array)
+    char *array;
+{
+    register int old,new,i,j;
+    /* flips the bit order within each byte from 0 lsb to 0 msb */
+    for (i = 0; i<=7; i++) {
+	old = *array;
+	new = 0;
+	for (j = 0; j<=7; j++) {
+	    if (old & 01)
+		new = new | 01;
+	    if (j < 7) {
+		old = old >> 1;
+		new = new << 1;
+	    }
+	}
+	*array = new;
+	array++;
+    }
+}
+#endif
+
+static void
+do_encrypt(in,out)
+    unsigned char *in;
+    unsigned char *out;
+{
+    int i, j;
+    for (i =1; i<=nflag; i++) {
+	mit_des_cbc_encrypt((const mit_des_cblock *)in,
+			    (mit_des_cblock *)out,
+			    8,
+			    sched,
+			    zero_text,
+			    MIT_DES_ENCRYPT);
+	if (mit_des_debug) {
+	    printf("\nclear %s\n",in);
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",in[j] & 0xff);
+	    printf("\tcipher ");
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",out[j] & 0xff);
+	}
+    }
+}
+
+static void
+do_decrypt(in,out)
+    unsigned char *out;
+    unsigned char *in;
+    /* try to invert it */
+{
+    int i, j;
+    for (i =1; i<=nflag; i++) {
+	mit_des_cbc_encrypt((const mit_des_cblock *)out,
+			    (mit_des_cblock *)in,
+			    8,
+			    sched,
+			    zero_text,
+			    MIT_DES_DECRYPT);
+	if (mit_des_debug) {
+	    printf("clear %s\n",in);
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",in[j] & 0xff);
+	    printf("\tcipher ");
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",out[j] & 0xff);
+	}
+    }
+}
+
+/*
+ * Fake out the DES library, for the purposes of testing.
+ */
+
+int
+mit_des_is_weak_key(key)
+    mit_des_cblock key;
+{
+    return 0;				/* fake it out for testing */
+}
diff --git a/krb5-1-6/src/lib/crypto/des/weak_key.c b/krb5-1-6/src/lib/crypto/des/weak_key.c
new file mode 100644
index 000000000..005b16387
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/des/weak_key.c
@@ -0,0 +1,85 @@
+/*
+ * lib/crypto/des/weak_key.c
+ *
+ * Copyright 1989,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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.
+ *
+ * Originally written 8/85 by Steve Miller, MIT Project Athena.
+ */
+
+#include "k5-int.h"
+#include "des_int.h"
+
+/*
+ * The following are the weak DES keys:
+ */
+static const mit_des_cblock weak[16] = {
+    /* weak keys */
+    {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
+    {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe},
+    {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e},
+    {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1},
+
+    /* semi-weak */
+    {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe},
+    {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01},
+
+    {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1},
+    {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e},
+
+    {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1},
+    {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01},
+
+    {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe},
+    {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e},
+
+    {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e},
+    {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01},
+
+    {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe},
+    {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1}
+};
+
+/*
+ * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key.
+ *
+ * Requires: key has correct odd parity.
+ */
+int
+mit_des_is_weak_key(mit_des_cblock key)
+{
+    int i;
+    const mit_des_cblock *weak_p = weak;
+
+    for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) {
+	if (!memcmp(weak_p++,key,sizeof(mit_des_cblock)))
+	    return 1;
+    }
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/dk/Makefile.in b/krb5-1-6/src/lib/crypto/dk/Makefile.in
new file mode 100644
index 000000000..4302d6116
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/Makefile.in
@@ -0,0 +1,112 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/dk
+mydir=lib/crypto/dk
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=dk
+##DOS##OBJFILE=..\$(OUTPRE)dk.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS=\
+	checksum.o	\
+	dk_decrypt.o	\
+	dk_encrypt.o	\
+	derive.o	\
+	dk_prf.o  \
+	stringtokey.o
+
+OBJS=\
+	$(OUTPRE)checksum.$(OBJEXT)	\
+	$(OUTPRE)dk_decrypt.$(OBJEXT)	\
+	$(OUTPRE)dk_encrypt.$(OBJEXT)	\
+	$(OUTPRE)derive.$(OBJEXT)	\
+	$(OUTPRE)dk_prf.$(OBJEXT) \
+	$(OUTPRE)stringtokey.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/checksum.c	\
+	$(srcdir)/dk_decrypt.c	\
+	$(srcdir)/dk_encrypt.c	\
+	$(srcdir)/dk_prf.c \
+	$(srcdir)/derive.c	\
+	$(srcdir)/stringtokey.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+checksum.so checksum.po $(OUTPRE)checksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../etypes.h \
+  checksum.c dk.h
+dk_decrypt.so dk_decrypt.po $(OUTPRE)dk_decrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h dk.h dk_decrypt.c
+dk_encrypt.so dk_encrypt.po $(OUTPRE)dk_encrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h dk.h dk_encrypt.c
+dk_prf.so dk_prf.po $(OUTPRE)dk_prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  dk.h dk_prf.c
+derive.so derive.po $(OUTPRE)derive.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  derive.c dk.h
+stringtokey.so stringtokey.po $(OUTPRE)stringtokey.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h dk.h stringtokey.c
diff --git a/krb5-1-6/src/lib/crypto/dk/checksum.c b/krb5-1-6/src/lib/crypto/dk/checksum.c
new file mode 100644
index 000000000..2f30cb740
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/checksum.c
@@ -0,0 +1,103 @@
+/*
+ * 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 "dk.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+krb5_error_code
+krb5_dk_make_checksum(const struct krb5_hash_provider *hash,
+		      const krb5_keyblock *key, krb5_keyusage usage,
+		      const krb5_data *input, krb5_data *output)
+{
+    int i;
+    const struct krb5_enc_provider *enc;
+    size_t blocksize, keybytes, keylength;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data datain;
+    unsigned char *kcdata;
+    krb5_keyblock kc;
+
+    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);
+
+    enc = krb5_enctypes_list[i].enc;
+
+    /* allocate and set to-be-derived keys */
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    /* key->length will be tested in enc->encrypt
+       output->length will be tested in krb5_hmac */
+
+    if ((kcdata = (unsigned char *) malloc(keylength)) == NULL)
+	return(ENOMEM);
+
+    kc.contents = kcdata;
+    kc.length = keylength;
+
+    /* derive the key */
+ 
+    datain.data = (char *) constantdata;
+    datain.length = K5CLENGTH;
+
+    datain.data[0] = (usage>>24)&0xff;
+    datain.data[1] = (usage>>16)&0xff;
+    datain.data[2] = (usage>>8)&0xff;
+    datain.data[3] = usage&0xff;
+
+    datain.data[4] = (char) 0x99;
+
+    if ((ret = krb5_derive_key(enc, key, &kc, &datain)) != 0)
+	goto cleanup;
+
+    /* hash the data */
+
+    datain = *input;
+
+    if ((ret = krb5_hmac(hash, &kc, 1, &datain, output)) != 0)
+	memset(output->data, 0, output->length);
+
+    /* ret is set correctly by the prior call */
+
+cleanup:
+    memset(kcdata, 0, keylength);
+
+    free(kcdata);
+
+    return(ret);
+}
+
diff --git a/krb5-1-6/src/lib/crypto/dk/derive.c b/krb5-1-6/src/lib/crypto/dk/derive.c
new file mode 100644
index 000000000..81dac4b57
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/derive.c
@@ -0,0 +1,217 @@
+/*
+ * 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 "dk.h"
+
+krb5_error_code
+krb5_derive_key(const struct krb5_enc_provider *enc,
+		const krb5_keyblock *inkey, krb5_keyblock *outkey,
+		const krb5_data *in_constant)
+{
+    size_t blocksize, keybytes, keylength, n;
+    unsigned char *inblockdata, *outblockdata, *rawkey;
+    krb5_data inblock, outblock;
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    if ((inkey->length != keylength) ||
+	(outkey->length != keylength))
+	return(KRB5_CRYPTO_INTERNAL);
+
+    /* allocate and set up buffers */
+
+    if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
+	return(ENOMEM);
+
+    if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
+	free(inblockdata);
+	return(ENOMEM);
+    }
+
+    if ((rawkey = (unsigned char *) malloc(keybytes)) == NULL) {
+	free(outblockdata);
+	free(inblockdata);
+	return(ENOMEM);
+    }
+
+    inblock.data = inblockdata;
+    inblock.length = blocksize;
+
+    outblock.data = outblockdata;
+    outblock.length = blocksize;
+
+    /* initialize the input block */
+
+    if (in_constant->length == inblock.length) {
+	memcpy(inblock.data, in_constant->data, inblock.length);
+    } else {
+	krb5_nfold(in_constant->length*8, in_constant->data,
+		   inblock.length*8, inblock.data);
+    }
+
+    /* loop encrypting the blocks until enough key bytes are generated */
+
+    n = 0;
+    while (n < keybytes) {
+	(*(enc->encrypt))(inkey, 0, &inblock, &outblock);
+
+	if ((keybytes - n) <= outblock.length) {
+	    memcpy(rawkey+n, outblock.data, (keybytes - n));
+	    break;
+	}
+
+	memcpy(rawkey+n, outblock.data, outblock.length);
+	memcpy(inblock.data, outblock.data, outblock.length);
+	n += outblock.length;
+    }
+
+    /* postprocess the key */
+
+    inblock.data = rawkey;
+    inblock.length = keybytes;
+
+    (*(enc->make_key))(&inblock, outkey);
+
+    /* clean memory, free resources and exit */
+
+    memset(inblockdata, 0, blocksize);
+    memset(outblockdata, 0, blocksize);
+    memset(rawkey, 0, keybytes);
+
+    free(rawkey);
+    free(outblockdata);
+    free(inblockdata);
+
+    return(0);
+}
+
+
+krb5_error_code
+krb5_derive_random(const struct krb5_enc_provider *enc,
+		   const krb5_keyblock *inkey, krb5_data *outrnd,
+		   const krb5_data *in_constant)
+{
+    size_t blocksize, keybytes, keylength, n;
+    unsigned char *inblockdata, *outblockdata, *rawkey;
+    krb5_data inblock, outblock;
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    if ((inkey->length != keylength) ||
+	(outrnd->length != keybytes))
+	return(KRB5_CRYPTO_INTERNAL);
+
+    /* allocate and set up buffers */
+
+    if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
+	return(ENOMEM);
+
+    if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
+	free(inblockdata);
+	return(ENOMEM);
+    }
+
+    if ((rawkey = (unsigned char *) malloc(keybytes)) == NULL) {
+	free(outblockdata);
+	free(inblockdata);
+	return(ENOMEM);
+    }
+
+    inblock.data = inblockdata;
+    inblock.length = blocksize;
+
+    outblock.data = outblockdata;
+    outblock.length = blocksize;
+
+    /* initialize the input block */
+
+    if (in_constant->length == inblock.length) {
+	memcpy(inblock.data, in_constant->data, inblock.length);
+    } else {
+	krb5_nfold(in_constant->length*8, in_constant->data,
+		   inblock.length*8, inblock.data);
+    }
+
+    /* loop encrypting the blocks until enough key bytes are generated */
+
+    n = 0;
+    while (n < keybytes) {
+	(*(enc->encrypt))(inkey, 0, &inblock, &outblock);
+
+	if ((keybytes - n) <= outblock.length) {
+	    memcpy(rawkey+n, outblock.data, (keybytes - n));
+	    break;
+	}
+
+	memcpy(rawkey+n, outblock.data, outblock.length);
+	memcpy(inblock.data, outblock.data, outblock.length);
+	n += outblock.length;
+    }
+
+    /* postprocess the key */
+
+    memcpy (outrnd->data, rawkey, keybytes);
+
+    /* clean memory, free resources and exit */
+
+    memset(inblockdata, 0, blocksize);
+    memset(outblockdata, 0, blocksize);
+    memset(rawkey, 0, keybytes);
+
+    free(rawkey);
+    free(outblockdata);
+    free(inblockdata);
+
+    return(0);
+}
+
+#if 0
+#include "etypes.h"
+void
+krb5_random2key (krb5_enctype enctype, krb5_data *inblock,
+		 krb5_keyblock *outkey)
+{
+    int i;
+    const struct krb5_enc_provider *enc;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+	if (krb5_enctypes_list[i].etype == enctype)
+	    break;
+    }
+
+    if (i == krb5_enctypes_length)
+	abort ();
+
+    enc = krb5_enctypes_list[i].enc;
+
+    enc->make_key (inblock, outkey);
+}
+#endif
diff --git a/krb5-1-6/src/lib/crypto/dk/dk.h b/krb5-1-6/src/lib/crypto/dk/dk.h
new file mode 100644
index 000000000..47bda6ebf
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/dk.h
@@ -0,0 +1,90 @@
+/*
+ * 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"
+
+void krb5_dk_encrypt_length
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		size_t input, size_t *length);
+
+krb5_error_code krb5_dk_encrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec,
+		const krb5_data *input, krb5_data *output);
+
+void krb5int_aes_encrypt_length
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		size_t input, size_t *length);
+
+krb5_error_code krb5int_aes_dk_encrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec,
+		const krb5_data *input, krb5_data *output);
+
+krb5_error_code krb5_dk_decrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *arg_output);
+
+krb5_error_code krb5int_aes_dk_decrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *arg_output);
+
+krb5_error_code krb5int_dk_string_to_key
+(const struct krb5_enc_provider *enc, 
+		const krb5_data *string, const krb5_data *salt,
+		const krb5_data *params, krb5_keyblock *key);
+
+krb5_error_code 
+krb5int_dk_prf(const struct krb5_enc_provider *enc,
+	       const struct krb5_hash_provider *hash,
+	       const krb5_keyblock *key, const krb5_data *in, krb5_data *out);
+
+krb5_error_code krb5_derive_key
+(const struct krb5_enc_provider *enc,
+		const krb5_keyblock *inkey,
+		krb5_keyblock *outkey, const krb5_data *in_constant);
+
+krb5_error_code krb5_dk_make_checksum
+(const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *input, krb5_data *output);
+
+krb5_error_code
+krb5_derive_random(const struct krb5_enc_provider *enc,
+		   const krb5_keyblock *inkey, krb5_data *outrnd,
+		   const krb5_data *in_constant);
diff --git a/krb5-1-6/src/lib/crypto/dk/dk_decrypt.c b/krb5-1-6/src/lib/crypto/dk/dk_decrypt.c
new file mode 100644
index 000000000..c4397382a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/dk_decrypt.c
@@ -0,0 +1,203 @@
+/*
+ * 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 "dk.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+static krb5_error_code
+krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
+				 const struct krb5_hash_provider *hash,
+				 const krb5_keyblock *key,
+				 krb5_keyusage usage,
+				 const krb5_data *ivec,
+				 const krb5_data *input,
+				 krb5_data *output,
+				 size_t hmacsize,
+				 int ivec_mode);
+
+krb5_error_code
+krb5_dk_decrypt(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *output)
+{
+    return krb5_dk_decrypt_maybe_trunc_hmac(enc, hash, key, usage,
+					    ivec, input, output, 0, 0);
+}
+
+krb5_error_code
+krb5int_aes_dk_decrypt(const struct krb5_enc_provider *enc,
+		       const struct krb5_hash_provider *hash,
+		       const krb5_keyblock *key, krb5_keyusage usage,
+		       const krb5_data *ivec, const krb5_data *input,
+		       krb5_data *output)
+{
+    return krb5_dk_decrypt_maybe_trunc_hmac(enc, hash, key, usage,
+					    ivec, input, output, 96 / 8, 1);
+}
+
+static krb5_error_code
+krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
+				 const struct krb5_hash_provider *hash,
+				 const krb5_keyblock *key, krb5_keyusage usage,
+				 const krb5_data *ivec, const krb5_data *input,
+				 krb5_data *output, size_t hmacsize,
+				 int ivec_mode)
+{
+    krb5_error_code ret;
+    size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen;
+    unsigned char *plaindata, *kedata, *kidata, *cksum, *cn;
+    krb5_keyblock ke, ki;
+    krb5_data d1, d2;
+    unsigned char constantdata[K5CLENGTH];
+
+    /* allocate and set up ciphertext and to-be-derived keys */
+
+    hashsize = hash->hashsize;
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    if (hmacsize == 0)
+	hmacsize = hashsize;
+    else if (hmacsize > hashsize)
+	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+
+    enclen = input->length - hmacsize;
+
+    if ((kedata = (unsigned char *) malloc(keylength)) == NULL)
+	return(ENOMEM);
+    if ((kidata = (unsigned char *) malloc(keylength)) == NULL) {
+	free(kedata);
+	return(ENOMEM);
+    }
+    if ((plaindata = (unsigned char *) malloc(enclen)) == NULL) {
+	free(kidata);
+	free(kedata);
+	return(ENOMEM);
+    }
+    if ((cksum = (unsigned char *) malloc(hashsize)) == NULL) {
+	free(plaindata);
+	free(kidata);
+	free(kedata);
+	return(ENOMEM);
+    }
+
+    ke.contents = kedata;
+    ke.length = keylength;
+    ki.contents = kidata;
+    ki.length = keylength;
+
+    /* derive the keys */
+
+    d1.data = (char *) constantdata;
+    d1.length = K5CLENGTH;
+
+    d1.data[0] = (usage>>24)&0xff;
+    d1.data[1] = (usage>>16)&0xff;
+    d1.data[2] = (usage>>8)&0xff;
+    d1.data[3] = usage&0xff;
+
+    d1.data[4] = (char) 0xAA;
+
+    if ((ret = krb5_derive_key(enc, key, &ke, &d1)) != 0)
+	goto cleanup;
+
+    d1.data[4] = 0x55;
+
+    if ((ret = krb5_derive_key(enc, key, &ki, &d1)) != 0)
+	goto cleanup;
+
+    /* decrypt the ciphertext */
+
+    d1.length = enclen;
+    d1.data = input->data;
+
+    d2.length = enclen;
+    d2.data = (char *) plaindata;
+
+    if ((ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2))) != 0)
+	goto cleanup;
+
+    if (ivec != NULL && ivec->length == blocksize) {
+	if (ivec_mode == 0)
+	    cn = (unsigned char *) d1.data + d1.length - blocksize;
+	else if (ivec_mode == 1) {
+	    int nblocks = (d1.length + blocksize - 1) / blocksize;
+	    cn = d1.data + blocksize * (nblocks - 2);
+	} else
+	    abort();
+    } else
+	cn = NULL;
+
+    /* verify the hash */
+
+    d1.length = hashsize;
+    d1.data = (char *) cksum;
+
+    if ((ret = krb5_hmac(hash, &ki, 1, &d2, &d1)) != 0)
+	goto cleanup;
+
+    if (memcmp(cksum, input->data+enclen, hmacsize) != 0) {
+	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+	goto cleanup;
+    }
+
+    /* because this encoding isn't self-describing wrt length, the
+       best we can do here is to compute the length minus the
+       confounder. */
+
+    plainlen = enclen - blocksize;
+
+    if (output->length < plainlen)
+	return(KRB5_BAD_MSIZE);
+
+    output->length = plainlen;
+
+    memcpy(output->data, d2.data+blocksize, output->length);
+
+    if (cn != NULL)
+	memcpy(ivec->data, cn, blocksize);
+
+    ret = 0;
+
+cleanup:
+    memset(kedata, 0, keylength);
+    memset(kidata, 0, keylength);
+    memset(plaindata, 0, enclen);
+    memset(cksum, 0, hashsize);
+
+    free(cksum);
+    free(plaindata);
+    free(kidata);
+    free(kedata);
+
+    return(ret);
+}
+
diff --git a/krb5-1-6/src/lib/crypto/dk/dk_encrypt.c b/krb5-1-6/src/lib/crypto/dk/dk_encrypt.c
new file mode 100644
index 000000000..dfa7e07da
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/dk_encrypt.c
@@ -0,0 +1,362 @@
+/*
+ * 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 "dk.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+/* the spec says that the confounder size and padding are specific to
+   the encryption algorithm.  This code (dk_encrypt_length and
+   dk_encrypt) assume the confounder is always the blocksize, and the
+   padding is always zero bytes up to the blocksize.  If these
+   assumptions ever fails, the keytype table should be extended to
+   include these bits of info. */
+
+void
+krb5_dk_encrypt_length(const struct krb5_enc_provider *enc,
+		       const struct krb5_hash_provider *hash,
+		       size_t inputlen, size_t *length)
+{
+    size_t blocksize, hashsize;
+
+    blocksize = enc->block_size;
+    hashsize = hash->hashsize;
+    *length = krb5_roundup(blocksize+inputlen, blocksize) + hashsize;
+}
+
+krb5_error_code
+krb5_dk_encrypt(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *output)
+{
+    size_t blocksize, keybytes, keylength, plainlen, enclen;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data d1, d2;
+    unsigned char *plaintext, *kedata, *kidata, *cn;
+    krb5_keyblock ke, ki;
+
+    /* allocate and set up plaintext and to-be-derived keys */
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+    plainlen = krb5_roundup(blocksize+input->length, blocksize);
+
+    krb5_dk_encrypt_length(enc, hash, input->length, &enclen);
+
+    /* key->length, ivec will be tested in enc->encrypt */
+
+    if (output->length < enclen)
+	return(KRB5_BAD_MSIZE);
+
+    if ((kedata = (unsigned char *) malloc(keylength)) == NULL)
+	return(ENOMEM);
+    if ((kidata = (unsigned char *) malloc(keylength)) == NULL) {
+	free(kedata);
+	return(ENOMEM);
+    }
+    if ((plaintext = (unsigned char *) malloc(plainlen)) == NULL) {
+	free(kidata);
+	free(kedata);
+	return(ENOMEM);
+    }
+
+    ke.contents = kedata;
+    ke.length = keylength;
+    ki.contents = kidata;
+    ki.length = keylength;
+
+    /* derive the keys */
+
+    d1.data = constantdata;
+    d1.length = K5CLENGTH;
+
+    d1.data[0] = (usage>>24)&0xff;
+    d1.data[1] = (usage>>16)&0xff;
+    d1.data[2] = (usage>>8)&0xff;
+    d1.data[3] = usage&0xff;
+
+    d1.data[4] = (char) 0xAA;
+
+    if ((ret = krb5_derive_key(enc, key, &ke, &d1)))
+	goto cleanup;
+
+    d1.data[4] = 0x55;
+
+    if ((ret = krb5_derive_key(enc, key, &ki, &d1)))
+	goto cleanup;
+
+    /* put together the plaintext */
+
+    d1.length = blocksize;
+    d1.data = plaintext;
+
+    if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &d1)))
+	goto cleanup;
+
+    memcpy(plaintext+blocksize, input->data, input->length);
+
+    memset(plaintext+blocksize+input->length, 0,
+	   plainlen - (blocksize+input->length));
+
+    /* encrypt the plaintext */
+
+    d1.length = plainlen;
+    d1.data = plaintext;
+
+    d2.length = plainlen;
+    d2.data = output->data;
+
+    if ((ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2))))
+	goto cleanup;
+
+    if (ivec != NULL && ivec->length == blocksize)
+	cn = d2.data + d2.length - blocksize;
+    else
+	cn = NULL;
+
+    /* hash the plaintext */
+
+    d2.length = enclen - plainlen;
+    d2.data = output->data+plainlen;
+
+    output->length = enclen;
+
+    if ((ret = krb5_hmac(hash, &ki, 1, &d1, &d2))) {
+	memset(d2.data, 0, d2.length);
+	goto cleanup;
+    }
+
+    /* update ivec */
+    if (cn != NULL)
+	memcpy(ivec->data, cn, blocksize);
+
+    /* ret is set correctly by the prior call */
+
+cleanup:
+    memset(kedata, 0, keylength);
+    memset(kidata, 0, keylength);
+    memset(plaintext, 0, plainlen);
+
+    free(plaintext);
+    free(kidata);
+    free(kedata);
+
+    return(ret);
+}
+
+/* Not necessarily "AES", per se, but "a CBC+CTS mode block cipher
+   with a 96-bit truncated HMAC".  */
+void
+krb5int_aes_encrypt_length(const struct krb5_enc_provider *enc,
+			   const struct krb5_hash_provider *hash,
+			   size_t inputlen, size_t *length)
+{
+    size_t blocksize, hashsize;
+
+    blocksize = enc->block_size;
+    hashsize = 96 / 8;
+
+    /* No roundup, since CTS requires no padding once we've hit the
+       block size.  */
+    *length = blocksize+inputlen + hashsize;
+}
+
+static krb5_error_code
+trunc_hmac (const struct krb5_hash_provider *hash,
+	    const krb5_keyblock *ki, unsigned int num,
+	    const krb5_data *input, const krb5_data *output)
+{
+    size_t hashsize;
+    krb5_data tmp;
+    krb5_error_code ret;
+
+    hashsize = hash->hashsize;
+    if (hashsize < output->length)
+	return KRB5_CRYPTO_INTERNAL;
+    tmp.length = hashsize;
+    tmp.data = malloc(hashsize);
+    if (tmp.data == NULL)
+	return errno;
+    ret = krb5_hmac(hash, ki, num, input, &tmp);
+    if (ret == 0)
+	memcpy(output->data, tmp.data, output->length);
+    memset(tmp.data, 0, hashsize);
+    free(tmp.data);
+    return ret;
+}
+
+krb5_error_code
+krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
+		       const struct krb5_hash_provider *hash,
+		       const krb5_keyblock *key, krb5_keyusage usage,
+		       const krb5_data *ivec, const krb5_data *input,
+		       krb5_data *output)
+{
+    size_t blocksize, keybytes, keylength, plainlen, enclen;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data d1, d2;
+    unsigned char *plaintext, *kedata, *kidata, *cn;
+    krb5_keyblock ke, ki;
+
+    /* allocate and set up plaintext and to-be-derived keys */
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+    plainlen = blocksize+input->length;
+
+    krb5int_aes_encrypt_length(enc, hash, input->length, &enclen);
+
+    /* key->length, ivec will be tested in enc->encrypt */
+
+    if (output->length < enclen)
+	return(KRB5_BAD_MSIZE);
+
+    if ((kedata = (unsigned char *) malloc(keylength)) == NULL)
+	return(ENOMEM);
+    if ((kidata = (unsigned char *) malloc(keylength)) == NULL) {
+	free(kedata);
+	return(ENOMEM);
+    }
+    if ((plaintext = (unsigned char *) malloc(plainlen)) == NULL) {
+	free(kidata);
+	free(kedata);
+	return(ENOMEM);
+    }
+
+    ke.contents = kedata;
+    ke.length = keylength;
+    ki.contents = kidata;
+    ki.length = keylength;
+
+    /* derive the keys */
+
+    d1.data = constantdata;
+    d1.length = K5CLENGTH;
+
+    d1.data[0] = (usage>>24)&0xff;
+    d1.data[1] = (usage>>16)&0xff;
+    d1.data[2] = (usage>>8)&0xff;
+    d1.data[3] = usage&0xff;
+
+    d1.data[4] = (char) 0xAA;
+
+    if ((ret = krb5_derive_key(enc, key, &ke, &d1)))
+	goto cleanup;
+
+    d1.data[4] = 0x55;
+
+    if ((ret = krb5_derive_key(enc, key, &ki, &d1)))
+	goto cleanup;
+
+    /* put together the plaintext */
+
+    d1.length = blocksize;
+    d1.data = plaintext;
+
+    if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &d1)))
+	goto cleanup;
+
+    memcpy(plaintext+blocksize, input->data, input->length);
+
+    /* Ciphertext stealing; there should be no more.  */
+    if (plainlen != blocksize + input->length)
+	abort();
+
+    /* encrypt the plaintext */
+
+    d1.length = plainlen;
+    d1.data = plaintext;
+
+    d2.length = plainlen;
+    d2.data = output->data;
+
+    if ((ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2))))
+	goto cleanup;
+
+    if (ivec != NULL && ivec->length == blocksize) {
+	int nblocks = (d2.length + blocksize - 1) / blocksize;
+	cn = d2.data + blocksize * (nblocks - 2);
+    } else
+	cn = NULL;
+
+    /* hash the plaintext */
+
+    d2.length = enclen - plainlen;
+    d2.data = output->data+plainlen;
+    if (d2.length != 96 / 8)
+	abort();
+
+    if ((ret = trunc_hmac(hash, &ki, 1, &d1, &d2))) {
+	memset(d2.data, 0, d2.length);
+	goto cleanup;
+    }
+
+    output->length = enclen;
+
+    /* update ivec */
+    if (cn != NULL) {
+	memcpy(ivec->data, cn, blocksize);
+#if 0
+	{
+	    int i;
+	    printf("\n%s: output:", __func__);
+	    for (i = 0; i < output->length; i++) {
+		if (i % 16 == 0)
+		    printf("\n%s: ", __func__);
+		printf(" %02x", i[(unsigned char *)output->data]);
+	    }
+	    printf("\n%s: outputIV:", __func__);
+	    for (i = 0; i < ivec->length; i++) {
+		if (i % 16 == 0)
+		    printf("\n%s: ", __func__);
+		printf(" %02x", i[(unsigned char *)ivec->data]);
+	    }
+	    printf("\n");  fflush(stdout);
+	}
+#endif
+    }
+
+    /* ret is set correctly by the prior call */
+
+cleanup:
+    memset(kedata, 0, keylength);
+    memset(kidata, 0, keylength);
+    memset(plaintext, 0, plainlen);
+
+    free(plaintext);
+    free(kidata);
+    free(kedata);
+
+    return(ret);
+}
+
diff --git a/krb5-1-6/src/lib/crypto/dk/dk_prf.c b/krb5-1-6/src/lib/crypto/dk/dk_prf.c
new file mode 100644
index 000000000..ec64caf16
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/dk_prf.c
@@ -0,0 +1,64 @@
+/*
+ * lib/crypto/dk/prf.c
+ *
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 
+ *
+ * This file contains an implementation of the RFC 3961 PRF for
+ *simplified profile enctypes.
+ */
+
+#include "k5-int.h"
+#include "dk.h"
+
+krb5_error_code
+krb5int_dk_prf (const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key,
+		const krb5_data *in, krb5_data *out)
+{
+  krb5_data tmp;
+  krb5_data prfconst;
+  krb5_keyblock *kp = NULL;
+  krb5_error_code ret = 0;
+  
+  prfconst.data = (char *) "prf";
+  prfconst.length = 3;
+  tmp.length = hash->hashsize;
+  tmp.data = malloc(hash->hashsize);
+  if (tmp.data == NULL)
+    return ENOMEM;
+  hash->hash(1, in, &tmp);
+  tmp.length = (tmp.length/enc->block_size)*enc->block_size; /*truncate to block size*/
+  ret = krb5int_c_init_keyblock(0, key->enctype,
+			   key->length, &kp);
+    if (ret == 0)
+      ret = krb5_derive_key(enc, key, kp, &prfconst);
+  if (ret == 0)
+    ret = enc->encrypt(kp, NULL, &tmp, out);
+      if (kp)
+	krb5int_c_free_keyblock(0, kp);
+  free (tmp.data);
+  return ret;
+}
diff --git a/krb5-1-6/src/lib/crypto/dk/stringtokey.c b/krb5-1-6/src/lib/crypto/dk/stringtokey.c
new file mode 100644
index 000000000..0e54b849f
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/dk/stringtokey.c
@@ -0,0 +1,96 @@
+/*
+ * 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 "dk.h"
+
+static const unsigned char kerberos[] = "kerberos";
+#define kerberos_len (sizeof(kerberos)-1)
+
+krb5_error_code
+krb5int_dk_string_to_key(const struct krb5_enc_provider *enc,
+			 const krb5_data *string, const krb5_data *salt,
+			 const krb5_data *parms, krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    size_t keybytes, keylength, concatlen;
+    unsigned char *concat, *foldstring, *foldkeydata;
+    krb5_data indata;
+    krb5_keyblock foldkey;
+
+    /* key->length is checked by krb5_derive_key */
+
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    concatlen = string->length+(salt?salt->length:0);
+
+    if ((concat = (unsigned char *) malloc(concatlen)) == NULL)
+	return(ENOMEM);
+    if ((foldstring = (unsigned char *) malloc(keybytes)) == NULL) {
+	free(concat);
+	return(ENOMEM);
+    }
+    if ((foldkeydata = (unsigned char *) malloc(keylength)) == NULL) {
+	free(foldstring);
+	free(concat);
+	return(ENOMEM);
+    }
+
+    /* construct input string ( = string + salt), fold it, make_key it */
+
+    memcpy(concat, string->data, string->length);
+    if (salt)
+	memcpy(concat+string->length, salt->data, salt->length);
+
+    krb5_nfold(concatlen*8, concat, keybytes*8, foldstring);
+
+    indata.length = keybytes;
+    indata.data = (char *) foldstring;
+    foldkey.length = keylength;
+    foldkey.contents = foldkeydata;
+
+    (*(enc->make_key))(&indata, &foldkey);
+
+    /* now derive the key from this one */
+
+    indata.length = kerberos_len;
+    indata.data = (char *) kerberos;
+
+    if ((ret = krb5_derive_key(enc, &foldkey, key, &indata)))
+	memset(key->contents, 0, key->length);
+
+    /* ret is set correctly by the prior call */
+
+    memset(concat, 0, concatlen);
+    memset(foldstring, 0, keybytes);
+    memset(foldkeydata, 0, keylength);
+
+    free(foldkeydata);
+    free(foldstring);
+    free(concat);
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/lib/crypto/enc_provider/Makefile.in b/krb5-1-6/src/lib/crypto/enc_provider/Makefile.in
new file mode 100644
index 000000000..ea60f1981
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enc_provider/Makefile.in
@@ -0,0 +1,87 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/enc_provider
+mydir=lib/crypto/enc_provider
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../des -I$(srcdir)/../arcfour -I$(srcdir)/../aes
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=enc_provider
+##DOS##OBJFILE=..\$(OUTPRE)enc_prov.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= des.o des3.o rc4.o aes.o
+
+OBJS= \
+	$(OUTPRE)des.$(OBJEXT) \
+	$(OUTPRE)des3.$(OBJEXT) \
+	$(OUTPRE)aes.$(OBJEXT) \
+	$(OUTPRE)rc4.$(OBJEXT)
+
+SRCS= \
+	$(srcdir)/des.c \
+	$(srcdir)/des3.c \
+	$(srcdir)/aes.c \
+	$(srcdir)/rc4.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+des.so des.po $(OUTPRE)des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../des/des_int.h \
+  des.c enc_provider.h
+des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../des/des_int.h \
+  des3.c
+aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../aes/aes.h $(srcdir)/../aes/uitypes.h aes.c \
+  enc_provider.h
+rc4.so rc4.po $(OUTPRE)rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../arcfour/arcfour-int.h $(srcdir)/../arcfour/arcfour.h \
+  enc_provider.h rc4.c
diff --git a/krb5-1-6/src/lib/crypto/enc_provider/aes.c b/krb5-1-6/src/lib/crypto/enc_provider/aes.c
new file mode 100644
index 000000000..45019692d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enc_provider/aes.c
@@ -0,0 +1,208 @@
+#include "k5-int.h"
+#include "enc_provider.h"
+#include "aes.h"
+
+#if 0
+aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]);
+aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+#endif
+
+#define CHECK_SIZES 0
+
+#if 0
+static void printd (const char *descr, krb5_data *d) {
+    int i, j;
+    const int r = 16;
+
+    printf("%s:", descr);
+
+    for (i = 0; i < d->length; i += r) {
+	printf("\n  %04x: ", i);
+	for (j = i; j < i + r && j < d->length; j++)
+	    printf(" %02x", 0xff & d->data[j]);
+#ifdef SHOW_TEXT
+	for (; j < i + r; j++)
+	    printf("   ");
+	printf("   ");
+	for (j = i; j < i + r && j < d->length; j++) {
+	    int c = 0xff & d->data[j];
+	    printf("%c", isprint(c) ? c : '.');
+	}
+#endif
+    }
+    printf("\n");
+}
+#endif
+
+#define enc(OUT, IN, CTX) (aes_enc_blk((IN),(OUT),(CTX)) == aes_good ? (void) 0 : abort())
+#define dec(OUT, IN, CTX) (aes_dec_blk((IN),(OUT),(CTX)) == aes_good ? (void) 0 : abort())
+
+static void xorblock(char *out, const char *in)
+{
+    int z;
+    for (z = 0; z < BLOCK_SIZE; z++)
+	out[z] ^= in[z];
+}
+
+krb5_error_code
+krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
+		    const krb5_data *input, krb5_data *output)
+{
+    aes_ctx ctx;
+    unsigned char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
+    int nblocks = 0, blockno;
+
+/*    CHECK_SIZES; */
+
+    if (aes_enc_key(key->contents, key->length, &ctx) != aes_good)
+	abort();
+
+    if (ivec)
+	memcpy(tmp, ivec->data, BLOCK_SIZE);
+    else
+	memset(tmp, 0, BLOCK_SIZE);
+
+    nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+    if (nblocks == 1) {
+	/* XXX Used for DK function.  */
+	enc(output->data, input->data, &ctx);
+    } else {
+	unsigned int nleft;
+
+	for (blockno = 0; blockno < nblocks - 2; blockno++) {
+	    xorblock(tmp, input->data + blockno * BLOCK_SIZE);
+	    enc(tmp2, tmp, &ctx);
+	    memcpy(output->data + blockno * BLOCK_SIZE, tmp2, BLOCK_SIZE);
+
+	    /* Set up for next block.  */
+	    memcpy(tmp, tmp2, BLOCK_SIZE);
+	}
+	/* Do final CTS step for last two blocks (the second of which
+	   may or may not be incomplete).  */
+	xorblock(tmp, input->data + (nblocks - 2) * BLOCK_SIZE);
+	enc(tmp2, tmp, &ctx);
+	nleft = input->length - (nblocks - 1) * BLOCK_SIZE;
+	memcpy(output->data + (nblocks - 1) * BLOCK_SIZE, tmp2, nleft);
+	memcpy(tmp, tmp2, BLOCK_SIZE);
+
+	memset(tmp3, 0, sizeof(tmp3));
+	memcpy(tmp3, input->data + (nblocks - 1) * BLOCK_SIZE, nleft);
+	xorblock(tmp, tmp3);
+	enc(tmp2, tmp, &ctx);
+	memcpy(output->data + (nblocks - 2) * BLOCK_SIZE, tmp2, BLOCK_SIZE);
+	if (ivec)
+	    memcpy(ivec->data, tmp2, BLOCK_SIZE);
+    }
+
+    return 0;
+}
+
+krb5_error_code
+krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
+		    const krb5_data *input, krb5_data *output)
+{
+    aes_ctx ctx;
+    unsigned char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
+    int nblocks = 0, blockno;
+
+    CHECK_SIZES;
+
+    if (aes_dec_key(key->contents, key->length, &ctx) != aes_good)
+	abort();
+
+    if (ivec)
+	memcpy(tmp, ivec->data, BLOCK_SIZE);
+    else
+	memset(tmp, 0, BLOCK_SIZE);
+
+    nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+    if (nblocks == 1) {
+	if (input->length < BLOCK_SIZE)
+	    abort();
+	dec(output->data, input->data, &ctx);
+    } else {
+
+	for (blockno = 0; blockno < nblocks - 2; blockno++) {
+	    dec(tmp2, input->data + blockno * BLOCK_SIZE, &ctx);
+	    xorblock(tmp2, tmp);
+	    memcpy(output->data + blockno * BLOCK_SIZE, tmp2, BLOCK_SIZE);
+	    memcpy(tmp, input->data + blockno * BLOCK_SIZE, BLOCK_SIZE);
+	}
+	/* Do last two blocks, the second of which (next-to-last block
+	   of plaintext) may be incomplete.  */
+	dec(tmp2, input->data + (nblocks - 2) * BLOCK_SIZE, &ctx);
+	/* Set tmp3 to last ciphertext block, padded.  */
+	memset(tmp3, 0, sizeof(tmp3));
+	memcpy(tmp3, input->data + (nblocks - 1) * BLOCK_SIZE,
+	       input->length - (nblocks - 1) * BLOCK_SIZE);
+	/* Set tmp2 to last (possibly partial) plaintext block, and
+	   save it.  */
+	xorblock(tmp2, tmp3);
+	memcpy(output->data + (nblocks - 1) * BLOCK_SIZE, tmp2,
+	       input->length - (nblocks - 1) * BLOCK_SIZE);
+	/* Maybe keep the trailing part, and copy in the last
+	   ciphertext block.  */
+	memcpy(tmp2, tmp3, input->length - (nblocks - 1) * BLOCK_SIZE);
+	/* Decrypt, to get next to last plaintext block xor previous
+	   ciphertext.  */
+	dec(tmp3, tmp2, &ctx);
+	xorblock(tmp3, tmp);
+	memcpy(output->data + (nblocks - 2) * BLOCK_SIZE, tmp3, BLOCK_SIZE);
+	if (ivec)
+	    memcpy(ivec->data, input->data + (nblocks - 2) * BLOCK_SIZE,
+		   BLOCK_SIZE);
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+k5_aes_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+    if (key->length != 16 && key->length != 32)
+	return(KRB5_BAD_KEYSIZE);
+    if (randombits->length != key->length)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    key->magic = KV5M_KEYBLOCK;
+
+    memcpy(key->contents, randombits->data, randombits->length);
+    return(0);
+}
+
+static krb5_error_code
+krb5int_aes_init_state (const krb5_keyblock *key, krb5_keyusage usage,
+			krb5_data *state)
+{
+    state->length = 16;
+    state->data = (void *) malloc(16);
+    if (state->data == NULL)
+	return ENOMEM;
+    memset(state->data, 0, state->length);
+    return 0;
+}
+
+const struct krb5_enc_provider krb5int_enc_aes128 = {
+    16,
+    16, 16,
+    krb5int_aes_encrypt,
+    krb5int_aes_decrypt,
+    k5_aes_make_key,
+    krb5int_aes_init_state,
+    krb5int_default_free_state
+};
+
+const struct krb5_enc_provider krb5int_enc_aes256 = {
+    16,
+    32, 32,
+    krb5int_aes_encrypt,
+    krb5int_aes_decrypt,
+    k5_aes_make_key,
+    krb5int_aes_init_state,
+    krb5int_default_free_state
+};
diff --git a/krb5-1-6/src/lib/crypto/enc_provider/des.c b/krb5-1-6/src/lib/crypto/enc_provider/des.c
new file mode 100644
index 000000000..561e980f8
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enc_provider/des.c
@@ -0,0 +1,117 @@
+/*
+ * 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 "enc_provider.h"
+
+static krb5_error_code
+k5_des_docrypt(const krb5_keyblock *key, const krb5_data *ivec,
+	       const krb5_data *input, krb5_data *output, int enc)
+{
+    mit_des_key_schedule schedule;
+
+    /* key->enctype was checked by the caller */
+
+    if (key->length != 8)
+	return(KRB5_BAD_KEYSIZE);
+    if ((input->length%8) != 0)
+	return(KRB5_BAD_MSIZE);
+    if (ivec && (ivec->length != 8))
+	return(KRB5_BAD_MSIZE);
+    if (input->length != output->length)
+	return(KRB5_BAD_MSIZE);
+
+    switch (mit_des_key_sched(key->contents, schedule)) {
+    case -1:
+	return(KRB5DES_BAD_KEYPAR);
+    case -2:
+	return(KRB5DES_WEAK_KEY);
+    }
+
+    /* this has a return value, but the code always returns zero */
+
+    mit_des_cbc_encrypt((krb5_pointer) input->data,
+			(krb5_pointer) output->data, input->length,
+			schedule,
+			(ivec
+			 ? (unsigned char *) ivec->data
+			 : (unsigned char *) mit_des_zeroblock),
+			enc);
+
+    memset(schedule, 0, sizeof(schedule));
+
+    return(0);
+}
+
+static krb5_error_code
+k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
+	       const krb5_data *input, krb5_data *output)
+{
+    return(k5_des_docrypt(key, ivec, input, output, 1));
+}
+
+static krb5_error_code
+k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
+	       const krb5_data *input, krb5_data *output)
+{
+    return(k5_des_docrypt(key, ivec, input, output, 0));
+}
+
+static krb5_error_code
+k5_des_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+    if (key->length != 8)
+	return(KRB5_BAD_KEYSIZE);
+    if (randombits->length != 7)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    key->magic = KV5M_KEYBLOCK;
+    key->length = 8;
+
+    /* take the seven bytes, move them around into the top 7 bits of the
+       8 key bytes, then compute the parity bits */
+
+    memcpy(key->contents, randombits->data, randombits->length);
+    key->contents[7] = (((key->contents[0]&1)<<1) | ((key->contents[1]&1)<<2) |
+			((key->contents[2]&1)<<3) | ((key->contents[3]&1)<<4) |
+			((key->contents[4]&1)<<5) | ((key->contents[5]&1)<<6) |
+			((key->contents[6]&1)<<7));
+
+    mit_des_fixup_key_parity(key->contents);
+
+    return(0);
+}
+
+const struct krb5_enc_provider krb5int_enc_des = {
+    8,
+    7, 8,
+    k5_des_encrypt,
+    k5_des_decrypt,
+    k5_des_make_key,
+    krb5int_des_init_state,
+    krb5int_default_free_state
+};
diff --git a/krb5-1-6/src/lib/crypto/enc_provider/des3.c b/krb5-1-6/src/lib/crypto/enc_provider/des3.c
new file mode 100644
index 000000000..f844747c8
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enc_provider/des3.c
@@ -0,0 +1,140 @@
+/*
+ * 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"
+
+static krb5_error_code
+validate_and_schedule(const krb5_keyblock *key, const krb5_data *ivec,
+		      const krb5_data *input, const krb5_data *output,
+		      mit_des3_key_schedule *schedule)
+{
+    /* key->enctype was checked by the caller */
+
+    if (key->length != 24)
+	return(KRB5_BAD_KEYSIZE);
+    if ((input->length%8) != 0)
+	return(KRB5_BAD_MSIZE);
+    if (ivec && (ivec->length != 8))
+	return(KRB5_BAD_MSIZE);
+    if (input->length != output->length)
+	return(KRB5_BAD_MSIZE);
+
+    switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents,
+			       *schedule)) {
+    case -1:
+	return(KRB5DES_BAD_KEYPAR);
+    case -2:
+	return(KRB5DES_WEAK_KEY);
+    }
+    return 0;
+}
+
+static krb5_error_code
+k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
+		const krb5_data *input, krb5_data *output)
+{
+    mit_des3_key_schedule schedule;
+    krb5_error_code err;
+
+    err = validate_and_schedule(key, ivec, input, output, &schedule);
+    if (err)
+	return err;
+
+    /* this has a return value, but the code always returns zero */
+    krb5int_des3_cbc_encrypt((krb5_pointer) input->data,
+			     (krb5_pointer) output->data, input->length,
+			     schedule[0], schedule[1], schedule[2],
+			     ivec?(unsigned char *) ivec->data:(unsigned char *)mit_des_zeroblock);
+
+    zap(schedule, sizeof(schedule));
+
+    return(0);
+}
+
+static krb5_error_code
+k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
+		const krb5_data *input, krb5_data *output)
+{
+    mit_des3_key_schedule schedule;
+    krb5_error_code err;
+
+    err = validate_and_schedule(key, ivec, input, output, &schedule);
+    if (err)
+	return err;
+
+    /* this has a return value, but the code always returns zero */
+    krb5int_des3_cbc_decrypt((krb5_pointer) input->data,
+			     (krb5_pointer) output->data, input->length,
+			     schedule[0], schedule[1], schedule[2],
+			     ivec?(unsigned char *) ivec->data:(unsigned char *)mit_des_zeroblock);
+
+    zap(schedule, sizeof(schedule));
+
+    return(0);
+}
+
+static krb5_error_code
+k5_des3_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+    int i;
+
+    if (key->length != 24)
+	return(KRB5_BAD_KEYSIZE);
+    if (randombits->length != 21)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    key->magic = KV5M_KEYBLOCK;
+    key->length = 24;
+
+    /* take the seven bytes, move them around into the top 7 bits of the
+       8 key bytes, then compute the parity bits.  Do this three times. */
+
+    for (i=0; i<3; i++) {
+	memcpy(key->contents+i*8, randombits->data+i*7, 7);
+	key->contents[i*8+7] = (((key->contents[i*8]&1)<<1) |
+				((key->contents[i*8+1]&1)<<2) |
+				((key->contents[i*8+2]&1)<<3) |
+				((key->contents[i*8+3]&1)<<4) |
+				((key->contents[i*8+4]&1)<<5) |
+				((key->contents[i*8+5]&1)<<6) |
+				((key->contents[i*8+6]&1)<<7));
+
+	mit_des_fixup_key_parity(key->contents+i*8);
+    }
+
+    return(0);
+}
+
+const struct krb5_enc_provider krb5int_enc_des3 = {
+    8,
+    21, 24,
+    k5_des3_encrypt,
+    k5_des3_decrypt,
+    k5_des3_make_key,
+    krb5int_des_init_state,
+    krb5int_default_free_state
+};
diff --git a/krb5-1-6/src/lib/crypto/enc_provider/enc_provider.h b/krb5-1-6/src/lib/crypto/enc_provider/enc_provider.h
new file mode 100644
index 000000000..5754d1a2d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enc_provider/enc_provider.h
@@ -0,0 +1,33 @@
+/*
+ * 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 const struct krb5_enc_provider krb5int_enc_des;
+extern const struct krb5_enc_provider krb5int_enc_des3;
+extern const struct krb5_enc_provider krb5int_enc_arcfour;
+extern const struct krb5_enc_provider krb5int_enc_aes128;
+extern const struct krb5_enc_provider krb5int_enc_aes256;
diff --git a/krb5-1-6/src/lib/crypto/enc_provider/rc4.c b/krb5-1-6/src/lib/crypto/enc_provider/rc4.c
new file mode 100644
index 000000000..685f89a89
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enc_provider/rc4.c
@@ -0,0 +1,216 @@
+/* arcfour.c 
+ *
+ * Copyright (c) 2000 by Computer Science Laboratory,
+ *                       Rensselaer Polytechnic Institute
+ *
+ * #include STD_DISCLAIMER
+ */
+
+#include "k5-int.h"
+#include "arcfour-int.h"
+#include "enc_provider.h"
+/* gets the next byte from the PRNG */
+#if ((__GNUC__ >= 2) )
+static __inline__ unsigned int k5_arcfour_byte(ArcfourContext *);
+#else
+static unsigned int k5_arcfour_byte(ArcfourContext *);
+#endif /* gcc inlines*/
+
+/* Initializes the context and sets the key. */
+static krb5_error_code k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key, 
+		  unsigned int keylen);
+
+/* Encrypts/decrypts data. */
+static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest, 
+		     const unsigned char *src, unsigned int len);
+
+/* Interface layer to kerb5 crypto layer */
+static krb5_error_code
+k5_arcfour_docrypt(const krb5_keyblock *, const krb5_data *,
+		   const krb5_data *, krb5_data *);
+
+/* from a random bitstrem, construct a key */
+static krb5_error_code
+k5_arcfour_make_key(const krb5_data *, krb5_keyblock *);
+
+static const unsigned char arcfour_weakkey1[] = {0x00, 0x00, 0xfd};
+static const unsigned char arcfour_weakkey2[] = {0x03, 0xfd, 0xfc};
+static const krb5_data arcfour_weakkeys[] = {
+    {KV5M_DATA, sizeof (arcfour_weakkey1),
+     (char * ) arcfour_weakkey1},
+    {KV5M_DATA, sizeof (arcfour_weakkey2),
+     (char * ) arcfour_weakkey2},
+    {KV5M_DATA, 0, 0}
+};
+
+/*xxx we really should check for c9x here and use inline on 
+ * more than just gcc. */
+#if ((__GNUC__ >= 2) )
+static __inline__ unsigned int k5_arcfour_byte(ArcfourContext * ctx)
+#else
+static unsigned int k5_arcfour_byte(ArcfourContext * ctx)
+#endif /* gcc inlines*/
+{
+  unsigned int x;
+  unsigned int y;
+  unsigned int sx, sy;
+  unsigned char *state;
+
+  state = ctx->state;
+  x = (ctx->x + 1) & 0xff;
+  sx = state[x];
+  y = (sx + ctx->y) & 0xff;
+  sy = state[y];
+  ctx->x = x;
+  ctx->y = y;
+  state[y] = sx;
+  state[x] = sy;
+  return state[(sx + sy) & 0xff];
+}
+
+static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest, 
+		     const unsigned char *src, unsigned int len)
+{
+  unsigned int i;
+  for (i = 0; i < len; i++)
+    dest[i] = src[i] ^ k5_arcfour_byte(ctx);
+}
+
+
+static krb5_error_code
+k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key, 
+		  unsigned int key_len)
+{
+  unsigned int t, u;
+  unsigned int keyindex;
+  unsigned int stateindex;
+  unsigned char* state;
+  unsigned int counter;
+
+  if (key_len != 16)
+    return KRB5_BAD_MSIZE;     /*this is probably not the correct error code
+				 to return */
+  for(counter=0;arcfour_weakkeys[counter].length >0; counter++)
+    if (memcmp(key, arcfour_weakkeys[counter].data,
+	       arcfour_weakkeys[counter].length) == 0)
+      return KRB5DES_WEAK_KEY; /* most certainly not the correct error */
+
+  state = &ctx->state[0];
+  ctx->x = 0;
+  ctx->y = 0;
+  for (counter = 0; counter < 256; counter++)
+    state[counter] = counter;
+  keyindex = 0;
+  stateindex = 0;
+  for (counter = 0; counter < 256; counter++)
+    {
+      t = state[counter];
+      stateindex = (stateindex + key[keyindex] + t) & 0xff;
+      u = state[stateindex];
+      state[stateindex] = t;
+      state[counter] = u;
+      if (++keyindex >= key_len)
+	keyindex = 0;
+    }
+  return 0;
+}
+
+
+/* The workhorse of the arcfour system, this impliments the cipher */
+static krb5_error_code
+k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state,
+	       const krb5_data *input, krb5_data *output)
+{
+  ArcfourContext *arcfour_ctx;
+  ArcFourCipherState *cipher_state;
+  int ret;
+
+  if (key->length != 16)
+    return(KRB5_BAD_KEYSIZE);
+  if (state && (state->length != sizeof (ArcFourCipherState)))
+    return(KRB5_BAD_MSIZE);
+  if (input->length != output->length)
+    return(KRB5_BAD_MSIZE);
+
+  if (state) {
+    cipher_state = (ArcFourCipherState *) state->data;
+    arcfour_ctx=&cipher_state->ctx;
+    if (cipher_state->initialized == 0) {
+      if ((ret=k5_arcfour_init(arcfour_ctx, key->contents, key->length))) {
+	return ret;
+      }
+      cipher_state->initialized = 1;
+    }
+    k5_arcfour_crypt(arcfour_ctx, (unsigned char *) output->data, (const unsigned char *) input->data, input->length);
+  }
+  else {
+    arcfour_ctx=malloc(sizeof (ArcfourContext));
+    if (arcfour_ctx == NULL)
+      return ENOMEM;
+    if ((ret=k5_arcfour_init(arcfour_ctx, key->contents, key->length))) {
+      free(arcfour_ctx);
+      return (ret);
+    }
+    k5_arcfour_crypt(arcfour_ctx, (unsigned char * ) output->data,
+		     (const unsigned char * ) input->data, input->length);
+    memset(arcfour_ctx, 0, sizeof (ArcfourContext));
+    free(arcfour_ctx);
+  }
+  
+  return 0;
+}
+
+static krb5_error_code
+k5_arcfour_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+    if (key->length != 16)
+	return(KRB5_BAD_KEYSIZE);
+    if (randombits->length != 16)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    key->magic = KV5M_KEYBLOCK;
+    key->length = 16;
+
+    memcpy(key->contents, randombits->data, randombits->length);
+
+    return(0);
+}
+
+static krb5_error_code
+k5_arcfour_init_state (const krb5_keyblock *key,
+		       krb5_keyusage keyusage, krb5_data *new_state)
+{
+  /* Note that we can't actually set up the state here  because the key
+   * will change  between now and when encrypt is called
+   * because  it is data dependent.  Yeah, this has strange
+   * properties. --SDH
+   */
+  new_state->length = sizeof (ArcFourCipherState);
+  new_state->data = malloc (new_state->length);
+  if (new_state->data) {
+    memset (new_state->data, 0 , new_state->length);
+    /* That will set initialized to zero*/
+  }else {
+    return (ENOMEM);
+  }
+  return 0;
+}
+
+/* Since the arcfour cipher is identical going forwards and backwards, 
+   we just call "docrypt" directly
+*/
+const struct krb5_enc_provider krb5int_enc_arcfour = {
+    /* This seems to work... although I am not sure what the
+       implications are in other places in the kerberos library */
+    1,
+    /* Keysize is arbitrary in arcfour, but the constraints of the
+       system, and to attempt to work with the MSFT system forces us
+       to 16byte/128bit.  Since there is no parity in the key, the
+       byte and length are the same.  */
+    16, 16,
+    k5_arcfour_docrypt,
+    k5_arcfour_docrypt,
+    k5_arcfour_make_key,
+    k5_arcfour_init_state, /*xxx not implemented yet*/
+    krb5int_default_free_state
+};
diff --git a/krb5-1-6/src/lib/crypto/encrypt.c b/krb5-1-6/src/lib/crypto/encrypt.c
new file mode 100644
index 000000000..c215dc429
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/encrypt.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_error_code KRB5_CALLCONV
+krb5_c_encrypt(krb5_context context, const krb5_keyblock *key,
+	       krb5_keyusage usage, const krb5_data *ivec,
+	       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/krb5-1-6/src/lib/crypto/encrypt_length.c b/krb5-1-6/src/lib/crypto/encrypt_length.c
new file mode 100644
index 000000000..71c25e735
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/encrypt_length.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_error_code KRB5_CALLCONV
+krb5_c_encrypt_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/krb5-1-6/src/lib/crypto/enctype_compare.c b/krb5-1-6/src/lib/crypto/enctype_compare.c
new file mode 100644
index 000000000..55e827764
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enctype_compare.c
@@ -0,0 +1,55 @@
+/*
+ * 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_CALLCONV
+krb5_c_enctype_compare(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/krb5-1-6/src/lib/crypto/enctype_to_string.c b/krb5-1-6/src/lib/crypto/enctype_to_string.c
new file mode 100644
index 000000000..f77dbff1c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/enctype_to_string.c
@@ -0,0 +1,46 @@
+/*
+ * 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_CALLCONV
+krb5_enctype_to_string(krb5_enctype enctype, char *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/krb5-1-6/src/lib/crypto/etypes.c b/krb5-1-6/src/lib/crypto/etypes.c
new file mode 100644
index 000000000..4273e2826
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/etypes.c
@@ -0,0 +1,214 @@
+/*
+ * 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"
+#include "arcfour.h"
+#include "aes_s2k.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. */
+
+const struct krb5_keytypes krb5_enctypes_list[] = {
+    { ENCTYPE_DES_CBC_CRC,
+      "des-cbc-crc", "DES cbc mode with CRC-32",
+      &krb5int_enc_des, &krb5int_hash_crc32,
+      8,
+      krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt,
+      krb5int_des_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_RSA_MD5 },
+    { ENCTYPE_DES_CBC_MD4,
+      "des-cbc-md4", "DES cbc mode with RSA-MD4",
+      &krb5int_enc_des, &krb5int_hash_md4,
+      8,
+      krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt,
+      krb5int_des_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_RSA_MD4 },
+    { ENCTYPE_DES_CBC_MD5,
+      "des-cbc-md5", "DES cbc mode with RSA-MD5",
+      &krb5int_enc_des, &krb5int_hash_md5,
+      8,
+      krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt,
+      krb5int_des_string_to_key,
+      NULL, /*PRF*/
+CKSUMTYPE_RSA_MD5 },
+    { ENCTYPE_DES_CBC_MD5,
+      "des", "DES cbc mode with RSA-MD5", /* alias */
+      &krb5int_enc_des, &krb5int_hash_md5,
+      8,
+      krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt,
+      krb5int_des_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_RSA_MD5 },
+
+    { ENCTYPE_DES_CBC_RAW,
+      "des-cbc-raw", "DES cbc mode raw",
+      &krb5int_enc_des, NULL,
+      8,
+      krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt,
+      krb5int_des_string_to_key,
+      NULL, /*PRF*/
+      0 },
+    { ENCTYPE_DES3_CBC_RAW,
+      "des3-cbc-raw", "Triple DES cbc mode raw",
+      &krb5int_enc_des3, NULL,
+      8,
+      krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt,
+      krb5int_dk_string_to_key,
+      NULL, /*PRF*/
+      0 },
+
+    { ENCTYPE_DES3_CBC_SHA1,
+      "des3-cbc-sha1", "Triple DES cbc mode with HMAC/sha1",
+      &krb5int_enc_des3, &krb5int_hash_sha1,
+      8,
+      krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt,
+      krb5int_dk_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_SHA1_DES3 },
+    { ENCTYPE_DES3_CBC_SHA1,	/* alias */
+      "des3-hmac-sha1", "Triple DES cbc mode with HMAC/sha1",
+      &krb5int_enc_des3, &krb5int_hash_sha1,
+      8,
+      krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt,
+      krb5int_dk_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_SHA1_DES3 },
+    { ENCTYPE_DES3_CBC_SHA1,	/* alias */
+      "des3-cbc-sha1-kd", "Triple DES cbc mode with HMAC/sha1",
+      &krb5int_enc_des3, &krb5int_hash_sha1,
+      8,
+      krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt,
+      krb5int_dk_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_SHA1_DES3 },
+
+    { ENCTYPE_DES_HMAC_SHA1,
+      "des-hmac-sha1", "DES with HMAC/sha1",
+      &krb5int_enc_des, &krb5int_hash_sha1,
+      8,
+      krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt,
+      krb5int_dk_string_to_key,
+      NULL, /*PRF*/
+      0 },
+    { ENCTYPE_ARCFOUR_HMAC, 
+      "arcfour-hmac","ArcFour with HMAC/md5", &krb5int_enc_arcfour,
+      &krb5int_hash_md5,
+      0,
+krb5_arcfour_encrypt_length, krb5_arcfour_encrypt,
+      krb5_arcfour_decrypt, krb5int_arcfour_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_MD5_ARCFOUR },
+    { ENCTYPE_ARCFOUR_HMAC,  /* alias */
+      "rc4-hmac", "ArcFour with HMAC/md5", &krb5int_enc_arcfour,
+      &krb5int_hash_md5,
+      0,
+      krb5_arcfour_encrypt_length, krb5_arcfour_encrypt,
+      krb5_arcfour_decrypt, krb5int_arcfour_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_MD5_ARCFOUR },
+    { ENCTYPE_ARCFOUR_HMAC,  /* alias */
+      "arcfour-hmac-md5", "ArcFour with HMAC/md5", &krb5int_enc_arcfour,
+      &krb5int_hash_md5,
+      0,
+      krb5_arcfour_encrypt_length, krb5_arcfour_encrypt,
+      krb5_arcfour_decrypt, krb5int_arcfour_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_MD5_ARCFOUR },
+    { ENCTYPE_ARCFOUR_HMAC_EXP, 
+      "arcfour-hmac-exp", "Exportable ArcFour with HMAC/md5",
+      &krb5int_enc_arcfour,
+      &krb5int_hash_md5,
+      0,
+      krb5_arcfour_encrypt_length, krb5_arcfour_encrypt,
+      krb5_arcfour_decrypt, krb5int_arcfour_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_MD5_ARCFOUR },
+    { ENCTYPE_ARCFOUR_HMAC_EXP, /* alias */
+      "rc4-hmac-exp", "Exportable ArcFour with HMAC/md5",
+      &krb5int_enc_arcfour,
+      &krb5int_hash_md5,
+      0,
+      krb5_arcfour_encrypt_length, krb5_arcfour_encrypt,
+      krb5_arcfour_decrypt, krb5int_arcfour_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_MD5_ARCFOUR },
+    { ENCTYPE_ARCFOUR_HMAC_EXP, /* alias */
+      "arcfour-hmac-md5-exp", "Exportable ArcFour with HMAC/md5",
+      &krb5int_enc_arcfour,
+      &krb5int_hash_md5,
+      0,
+      krb5_arcfour_encrypt_length, krb5_arcfour_encrypt,
+      krb5_arcfour_decrypt, krb5int_arcfour_string_to_key,
+      NULL, /*PRF*/
+      CKSUMTYPE_HMAC_MD5_ARCFOUR },
+
+    { ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+      "aes128-cts-hmac-sha1-96", "AES-128 CTS mode with 96-bit SHA-1 HMAC",
+      &krb5int_enc_aes128, &krb5int_hash_sha1,
+      16,
+      krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt,
+      krb5int_aes_string_to_key,
+      krb5int_dk_prf,
+      CKSUMTYPE_HMAC_SHA1_96_AES128 },
+    { ENCTYPE_AES128_CTS_HMAC_SHA1_96, /* alias */
+      "aes128-cts", "AES-128 CTS mode with 96-bit SHA-1 HMAC",
+      &krb5int_enc_aes128, &krb5int_hash_sha1,
+      16,
+      krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt,
+      krb5int_aes_string_to_key,
+      krb5int_dk_prf,
+      CKSUMTYPE_HMAC_SHA1_96_AES128 },
+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+      "aes256-cts-hmac-sha1-96", "AES-256 CTS mode with 96-bit SHA-1 HMAC",
+      &krb5int_enc_aes256, &krb5int_hash_sha1,
+      16,
+      krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt,
+      krb5int_aes_string_to_key,
+      krb5int_dk_prf,
+      CKSUMTYPE_HMAC_SHA1_96_AES256 },
+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96, /* alias */
+      "aes256-cts", "AES-256 CTS mode with 96-bit SHA-1 HMAC",
+      &krb5int_enc_aes256, &krb5int_hash_sha1,
+      16,
+      krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt,
+      krb5int_aes_string_to_key,
+      krb5int_dk_prf,
+      CKSUMTYPE_HMAC_SHA1_96_AES256 },
+};
+
+const int krb5_enctypes_length =
+sizeof(krb5_enctypes_list)/sizeof(struct krb5_keytypes);
diff --git a/krb5-1-6/src/lib/crypto/etypes.h b/krb5-1-6/src/lib/crypto/etypes.h
new file mode 100644
index 000000000..ca94e56ff
--- /dev/null
+++ b/krb5-1-6/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 const struct krb5_keytypes krb5_enctypes_list[];
+extern const int krb5_enctypes_length;
diff --git a/krb5-1-6/src/lib/crypto/hash_provider/Makefile.in b/krb5-1-6/src/lib/crypto/hash_provider/Makefile.in
new file mode 100644
index 000000000..37634df7d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/hash_provider/Makefile.in
@@ -0,0 +1,82 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/hash_provider
+mydir=lib/crypto/hash_provider
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../crc32 -I$(srcdir)/../md4 \
+	-I$(srcdir)/../md5 -I$(srcdir)/../sha1
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=hash_provider
+##DOS##OBJFILE=..\$(OUTPRE)hash_pro.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= hash_crc32.o hash_md4.o hash_md5.o hash_sha1.o
+
+OBJS= $(OUTPRE)hash_crc32.$(OBJEXT) $(OUTPRE)hash_md4.$(OBJEXT) \
+	$(OUTPRE)hash_md5.$(OBJEXT) $(OUTPRE)hash_sha1.$(OBJEXT)
+
+SRCS= $(srcdir)/hash_crc32.c $(srcdir)/hash_md4.c \
+	$(srcdir)/hash_md5.c $(srcdir)/hash_sha1.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+hash_crc32.so hash_crc32.po $(OUTPRE)hash_crc32.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../crc32/crc-32.h \
+  hash_crc32.c hash_provider.h
+hash_md4.so hash_md4.po $(OUTPRE)hash_md4.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../md4/rsa-md4.h \
+  hash_md4.c hash_provider.h
+hash_md5.so hash_md5.po $(OUTPRE)hash_md5.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../md5/rsa-md5.h \
+  hash_md5.c hash_provider.h
+hash_sha1.so hash_sha1.po $(OUTPRE)hash_sha1.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../sha1/shs.h \
+  hash_provider.h hash_sha1.c
diff --git a/krb5-1-6/src/lib/crypto/hash_provider/hash_crc32.c b/krb5-1-6/src/lib/crypto/hash_provider/hash_crc32.c
new file mode 100644
index 000000000..b48b3b363
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/hash_provider/hash_crc32.c
@@ -0,0 +1,59 @@
+/*
+ * 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 "crc-32.h"
+#include "hash_provider.h"
+
+static krb5_error_code
+k5_crc32_hash(unsigned int icount, const krb5_data *input,
+	      krb5_data *output)
+{
+    unsigned long c, cn;
+    int i;
+    
+    if (output->length != CRC32_CKSUM_LENGTH)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    c = 0;
+    for (i=0; i<icount; i++) {
+	mit_crc32(input[i].data, input[i].length, &cn);
+	c ^= cn;
+    }
+
+    output->data[0] = c&0xff;
+    output->data[1] = (c>>8)&0xff;
+    output->data[2] = (c>>16)&0xff;
+    output->data[3] = (c>>24)&0xff;
+
+    return(0);
+}
+
+const struct krb5_hash_provider krb5int_hash_crc32 = {
+    CRC32_CKSUM_LENGTH,
+    1,
+    k5_crc32_hash
+};
diff --git a/krb5-1-6/src/lib/crypto/hash_provider/hash_md4.c b/krb5-1-6/src/lib/crypto/hash_provider/hash_md4.c
new file mode 100644
index 000000000..97487923b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/hash_provider/hash_md4.c
@@ -0,0 +1,55 @@
+/*
+ * 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 "rsa-md4.h"
+#include "hash_provider.h"
+
+static krb5_error_code
+k5_md4_hash(unsigned int icount, const krb5_data *input,
+	    krb5_data *output)
+{
+    krb5_MD4_CTX ctx;
+    int i;
+
+    if (output->length != RSA_MD4_CKSUM_LENGTH)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    krb5_MD4Init(&ctx);
+    for (i=0; i<icount; i++)
+	krb5_MD4Update(&ctx, (unsigned char *) input[i].data, input[i].length);
+    krb5_MD4Final(&ctx);
+
+    memcpy(output->data, ctx.digest, RSA_MD4_CKSUM_LENGTH);
+
+    return(0);
+}
+
+const struct krb5_hash_provider krb5int_hash_md4 = {
+    RSA_MD4_CKSUM_LENGTH,
+    64,
+    k5_md4_hash
+};
diff --git a/krb5-1-6/src/lib/crypto/hash_provider/hash_md5.c b/krb5-1-6/src/lib/crypto/hash_provider/hash_md5.c
new file mode 100644
index 000000000..408729337
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/hash_provider/hash_md5.c
@@ -0,0 +1,55 @@
+/*
+ * 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 "rsa-md5.h"
+#include "hash_provider.h"
+
+static krb5_error_code
+k5_md5_hash(unsigned int icount, const krb5_data *input,
+	    krb5_data *output)
+{
+    krb5_MD5_CTX ctx;
+    int i;
+
+    if (output->length != RSA_MD5_CKSUM_LENGTH)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    krb5_MD5Init(&ctx);
+    for (i=0; i<icount; i++)
+	krb5_MD5Update(&ctx, (unsigned char *) input[i].data, input[i].length);
+    krb5_MD5Final(&ctx);
+
+    memcpy(output->data, ctx.digest, RSA_MD5_CKSUM_LENGTH);
+
+    return(0);
+}
+
+const struct krb5_hash_provider krb5int_hash_md5 = {
+    RSA_MD5_CKSUM_LENGTH,
+    64,
+    k5_md5_hash
+};
diff --git a/krb5-1-6/src/lib/crypto/hash_provider/hash_provider.h b/krb5-1-6/src/lib/crypto/hash_provider/hash_provider.h
new file mode 100644
index 000000000..4fa46097d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/hash_provider/hash_provider.h
@@ -0,0 +1,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"
+
+extern const struct krb5_hash_provider krb5int_hash_crc32;
+extern const struct krb5_hash_provider krb5int_hash_md4;
+extern const struct krb5_hash_provider krb5int_hash_md5;
+extern const struct krb5_hash_provider krb5int_hash_sha1;
diff --git a/krb5-1-6/src/lib/crypto/hash_provider/hash_sha1.c b/krb5-1-6/src/lib/crypto/hash_provider/hash_sha1.c
new file mode 100644
index 000000000..5fbea6a9c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/hash_provider/hash_sha1.c
@@ -0,0 +1,60 @@
+/*
+ * 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 "shs.h"
+#include "hash_provider.h"
+
+static krb5_error_code
+k5_sha1_hash(unsigned int icount, const krb5_data *input,
+	     krb5_data *output)
+{
+    SHS_INFO ctx;
+    int i;
+
+    if (output->length != SHS_DIGESTSIZE)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    shsInit(&ctx);
+    for (i=0; i<icount; i++)
+	shsUpdate(&ctx, (unsigned char *) input[i].data, input[i].length);
+    shsFinal(&ctx);
+
+    for (i=0; i<(sizeof(ctx.digest)/sizeof(ctx.digest[0])); i++) {
+	output->data[i*4] = (ctx.digest[i]>>24)&0xff;
+	output->data[i*4+1] = (ctx.digest[i]>>16)&0xff;
+	output->data[i*4+2] = (ctx.digest[i]>>8)&0xff;
+	output->data[i*4+3] = ctx.digest[i]&0xff;
+    }
+
+    return(0);
+}
+
+const struct krb5_hash_provider krb5int_hash_sha1 = {
+    SHS_DIGESTSIZE,
+    SHS_DATASIZE,
+    k5_sha1_hash
+};
diff --git a/krb5-1-6/src/lib/crypto/hmac.c b/krb5-1-6/src/lib/crypto/hmac.c
new file mode 100644
index 000000000..cc46374c5
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/hmac.c
@@ -0,0 +1,127 @@
+/*
+ * 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(const struct krb5_hash_provider *hash, const krb5_keyblock *key,
+	  unsigned int icount, 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;
+
+    hashsize = hash->hashsize;
+    blocksize = hash->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 = (char *) xorkey;
+	hashin[i+1] = input[i];
+    }
+
+    hashout.length = hashsize;
+    hashout.data = (char *) 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 = (char *) 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/krb5-1-6/src/lib/crypto/keyblocks.c b/krb5-1-6/src/lib/crypto/keyblocks.c
new file mode 100644
index 000000000..626443c83
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyblocks.c
@@ -0,0 +1,79 @@
+/*
+ * lib/crypto/keyblocks.c
+ *
+ * Copyright (C) 2002, 2005 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 
+ *
+ * krb5_init_keyblock- a function to set up 
+ *  an empty keyblock
+ */
+
+
+#include "k5-int.h"
+#include <assert.h>
+
+krb5_error_code   krb5int_c_init_keyblock
+	(krb5_context context, krb5_enctype enctype,
+	 size_t length, krb5_keyblock **out)
+{
+    krb5_keyblock *kb;
+    kb = malloc (sizeof(krb5_keyblock));
+    assert (out);
+    *out = NULL;
+    if (!kb) {
+	return ENOMEM;
+    }
+    kb->magic = KV5M_KEYBLOCK;
+    kb->enctype = enctype;
+    kb->length = length;
+    if(length) {
+	kb->contents = malloc (length);
+	if(!kb->contents) {
+	    free (kb);
+	    return ENOMEM;
+	}
+    } else {
+	kb->contents = NULL;
+    }
+    *out = kb;
+    return 0;
+}
+
+
+void 
+krb5int_c_free_keyblock(krb5_context context, register krb5_keyblock *val)
+{
+    krb5int_c_free_keyblock_contents(context, val);
+    krb5_xfree(val);
+}
+
+void 
+krb5int_c_free_keyblock_contents(krb5_context context, register krb5_keyblock *key)
+{
+     if (key->contents) {
+       krb5int_zap_data (key->contents, key->length);
+	  krb5_xfree(key->contents);
+	  key->contents = 0;
+     }
+}
diff --git a/krb5-1-6/src/lib/crypto/keyed_checksum_types.c b/krb5-1-6/src/lib/crypto/keyed_checksum_types.c
new file mode 100644
index 000000000..0e46466f2
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyed_checksum_types.c
@@ -0,0 +1,89 @@
+/*
+ * 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(krb5_enctype e1, krb5_enctype 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_CALLCONV
+krb5_c_keyed_checksum_types(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_CALLCONV
+krb5_free_cksumtypes(krb5_context context, krb5_cksumtype *val)
+{
+    if (val)
+	krb5_xfree(val);
+    return;
+}
+
diff --git a/krb5-1-6/src/lib/crypto/keyed_cksum.c b/krb5-1-6/src/lib/crypto/keyed_cksum.c
new file mode 100644
index 000000000..4d50c2c4a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyed_cksum.c
@@ -0,0 +1,55 @@
+/*
+ * 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 KRB5_CALLCONV
+krb5_c_is_keyed_cksum(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 0;   /* error case */
+}
+
+krb5_boolean KRB5_CALLCONV
+is_keyed_cksum(krb5_cksumtype ctype)
+{
+    return krb5_c_is_keyed_cksum (ctype);
+}
diff --git a/krb5-1-6/src/lib/crypto/keyhash_provider/Makefile.in b/krb5-1-6/src/lib/crypto/keyhash_provider/Makefile.in
new file mode 100644
index 000000000..9e3d36458
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyhash_provider/Makefile.in
@@ -0,0 +1,104 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/keyhash_provider
+mydir=lib/crypto/keyhash_provider
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../des -I$(srcdir)/../md4 \
+	-I$(srcdir)/../md5 -I$(srcdir)/../arcfour \
+	-I$(srcdir)/../hash_provider
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=keyhash_provider
+##DOS##OBJFILE=..\$(OUTPRE)kh_pro.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= descbc.o k5_md4des.o k5_md5des.o hmac_md5.o
+
+OBJS= $(OUTPRE)descbc.$(OBJEXT) $(OUTPRE)k5_md4des.$(OBJEXT) $(OUTPRE)k5_md5des.$(OBJEXT) $(OUTPRE)hmac_md5.$(OBJEXT)
+
+SRCS= $(srcdir)/descbc.c $(srcdir)/k5_md4des.c $(srcdir)/k5_md5des.c $(srcdir)/hmac_md5.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+t_cksum4.o: $(srcdir)/t_cksum.c
+	$(CC) -DMD=4 $(ALL_CFLAGS) -o t_cksum4.o -c $(srcdir)/t_cksum.c
+
+t_cksum5.o: $(srcdir)/t_cksum.c
+	$(CC) -DMD=5 $(ALL_CFLAGS) -o t_cksum5.o -c $(srcdir)/t_cksum.c
+
+t_cksum4: t_cksum4.o $(CRYTPO_DEPLIB)
+	$(CC_LINK) -o t_cksum4 t_cksum4.o $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(LIBS)
+
+t_cksum5: t_cksum5.o $(CRYPTO_DEPLIB)
+	$(CC_LINK) -o t_cksum5 t_cksum5.o $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(LIBS)
+
+check-unix:: t_cksum4 t_cksum5
+	$(RUN_SETUP) $(VALGRIND) $(C)t_cksum4 "this is a test"
+	$(RUN_SETUP) $(VALGRIND) $(C)t_cksum5 "this is a test"
+
+clean-unix::
+	$(RM) t_cksum4 t_cksum4.o
+	$(RM) t_cksum5 t_cksum5.o
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+descbc.so descbc.po $(OUTPRE)descbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../des/des_int.h \
+  descbc.c keyhash_provider.h
+k5_md4des.so k5_md4des.po $(OUTPRE)k5_md4des.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../des/des_int.h $(srcdir)/../md4/rsa-md4.h \
+  k5_md4des.c keyhash_provider.h
+k5_md5des.so k5_md5des.po $(OUTPRE)k5_md5des.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../des/des_int.h $(srcdir)/../md5/rsa-md5.h \
+  k5_md5des.c keyhash_provider.h
+hmac_md5.so hmac_md5.po $(OUTPRE)hmac_md5.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../arcfour/arcfour-int.h \
+  $(srcdir)/../arcfour/arcfour.h $(srcdir)/../hash_provider/hash_provider.h \
+  $(srcdir)/../md5/rsa-md5.h hmac_md5.c keyhash_provider.h
diff --git a/krb5-1-6/src/lib/crypto/keyhash_provider/descbc.c b/krb5-1-6/src/lib/crypto/keyhash_provider/descbc.c
new file mode 100644
index 000000000..fcccbfa7c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyhash_provider/descbc.c
@@ -0,0 +1,70 @@
+/*
+ * 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 "keyhash_provider.h"
+
+static krb5_error_code
+k5_descbc_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec,
+	       const krb5_data *input, krb5_data *output)
+{
+    mit_des_key_schedule schedule;
+
+    if (key->length != 8)
+	return(KRB5_BAD_KEYSIZE);
+    if ((input->length%8) != 0)
+	return(KRB5_BAD_MSIZE);
+    if (ivec && (ivec->length != 8))
+	return(KRB5_CRYPTO_INTERNAL);
+    if (output->length != 8)
+	return(KRB5_CRYPTO_INTERNAL);
+
+    switch (mit_des_key_sched(key->contents, schedule)) {
+    case -1:
+	return(KRB5DES_BAD_KEYPAR);
+    case -2:
+	return(KRB5DES_WEAK_KEY);
+    }
+
+    /* this has a return value, but it's useless to us */
+
+    mit_des_cbc_cksum((unsigned char *) input->data, 
+		      (unsigned char *) output->data, input->length,
+		      schedule, 
+		      ivec? (unsigned char *)ivec->data: 
+		            (unsigned char *)mit_des_zeroblock);
+
+    memset(schedule, 0, sizeof(schedule));
+
+    return(0);
+}
+
+const struct krb5_keyhash_provider krb5int_keyhash_descbc = {
+    8,
+    k5_descbc_hash,
+    NULL
+};
diff --git a/krb5-1-6/src/lib/crypto/keyhash_provider/hmac_md5.c b/krb5-1-6/src/lib/crypto/keyhash_provider/hmac_md5.c
new file mode 100644
index 000000000..a2472a832
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyhash_provider/hmac_md5.c
@@ -0,0 +1,96 @@
+/*
+ * lib/crypto/keyhash_provider/hmac_md5.c
+ *
+(I don't know)
+.
+ * Copyright2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+* Implementation of the Microsoft hmac-md5 checksum type.
+* Implemented based on draft-brezak-win2k-krb-rc4-hmac-03
+ */
+
+#include "k5-int.h"
+#include "keyhash_provider.h"
+#include "arcfour-int.h"
+#include "rsa-md5.h"
+#include "hash_provider.h"
+
+static  krb5_error_code
+k5_hmac_md5_hash (const krb5_keyblock *key, krb5_keyusage usage,
+		  const krb5_data *iv,
+		  const krb5_data *input, krb5_data *output)
+{
+  krb5_keyusage ms_usage;
+  krb5_error_code ret;
+  krb5_keyblock ks;
+  krb5_data ds, ks_constant, md5tmp;
+  krb5_MD5_CTX ctx;
+  char t[4];
+  
+
+  ds.length = key->length;
+  ks.length = key->length;
+  ds.data = malloc(ds.length);
+  if (ds.data == NULL)
+    return ENOMEM;
+  ks.contents = (void *) ds.data;
+
+  ks_constant.data = "signaturekey";
+  ks_constant.length = strlen(ks_constant.data)+1; /* Including null*/
+
+  ret = krb5_hmac( &krb5int_hash_md5, key, 1,
+		   &ks_constant, &ds);
+  if (ret)
+    goto cleanup;
+
+  krb5_MD5Init (&ctx);
+  ms_usage = krb5int_arcfour_translate_usage (usage);
+  t[0] = (ms_usage) & 0xff;
+  t[1] = (ms_usage>>8) & 0xff;
+  t[2] = (ms_usage >>16) & 0xff;
+  t[3] = (ms_usage>>24) & 0XFF;
+  krb5_MD5Update (&ctx, (unsigned char * ) &t, 4);
+  krb5_MD5Update (&ctx, (unsigned char *) input-> data,
+		  (unsigned int) input->length );
+  krb5_MD5Final(&ctx);
+  md5tmp.data = (void *) ctx.digest;
+  md5tmp.length = 16;
+  ret = krb5_hmac ( &krb5int_hash_md5, &ks, 1, &md5tmp,
+		    output);
+
+    cleanup:
+  memset(&ctx, 0, sizeof(ctx));
+  memset (ks.contents, 0, ks.length);
+  free (ks.contents);
+  return ret;
+}
+
+		 
+
+const struct krb5_keyhash_provider krb5int_keyhash_hmac_md5 = {
+  16,
+  k5_hmac_md5_hash,
+  NULL /*checksum  again*/
+};
+
diff --git a/krb5-1-6/src/lib/crypto/keyhash_provider/k5_md4des.c b/krb5-1-6/src/lib/crypto/keyhash_provider/k5_md4des.c
new file mode 100644
index 000000000..8e9623901
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyhash_provider/k5_md4des.c
@@ -0,0 +1,190 @@
+/*
+ * 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 "rsa-md4.h"
+#include "keyhash_provider.h"
+
+#define CONFLENGTH 8
+
+/* Force acceptance of krb5-beta5 md4des checksum for now. */
+#define KRB5_MD4DES_BETA5_COMPAT
+
+/* des-cbc(xorkey, conf | rsa-md4(conf | data)) */
+
+/* this could be done in terms of the md4 and des providers, but
+   that's less efficient, and there's no need for this to be generic */
+
+static krb5_error_code
+k5_md4des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec,
+	       const krb5_data *input, krb5_data *output)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    krb5_MD4_CTX ctx;
+    unsigned char conf[CONFLENGTH];
+    unsigned char xorkey[8];
+    int i;
+    mit_des_key_schedule schedule;
+
+    if (key->length != 8)
+	return(KRB5_BAD_KEYSIZE);
+    if (ivec)
+	return(KRB5_CRYPTO_INTERNAL);
+    if (output->length != (CONFLENGTH+RSA_MD4_CKSUM_LENGTH))
+	return(KRB5_CRYPTO_INTERNAL);
+
+    /* create the confouder */
+
+    data.length = CONFLENGTH;
+    data.data = (char *) conf;
+    if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &data)))
+	return(ret);
+
+    /* create and schedule the encryption key */
+
+    memcpy(xorkey, key->contents, sizeof(xorkey));
+    for (i=0; i<sizeof(xorkey); i++)
+	xorkey[i] ^= 0xf0;
+    
+    switch (ret = mit_des_key_sched(xorkey, schedule)) {
+    case -1:
+	return(KRB5DES_BAD_KEYPAR);
+    case -2:
+	return(KRB5DES_WEAK_KEY);
+    }
+
+    /* hash the confounder, then the input data */
+
+    krb5_MD4Init(&ctx);
+    krb5_MD4Update(&ctx, conf, CONFLENGTH);
+    krb5_MD4Update(&ctx, (unsigned char *) input->data,
+		   (unsigned int) input->length);
+    krb5_MD4Final(&ctx);
+
+    /* construct the buffer to be encrypted */
+
+    memcpy(output->data, conf, CONFLENGTH);
+    memcpy(output->data+CONFLENGTH, ctx.digest, RSA_MD4_CKSUM_LENGTH);
+
+    /* encrypt it, in place.  this has a return value, but it's
+       always zero.  */
+
+    mit_des_cbc_encrypt((krb5_pointer) output->data,
+			(krb5_pointer) output->data, output->length,
+			schedule, (unsigned char *) mit_des_zeroblock, 1);
+
+    return(0);
+}
+
+static krb5_error_code
+k5_md4des_verify(const krb5_keyblock *key, krb5_keyusage usage,
+		 const krb5_data *ivec,
+		 const krb5_data *input, const krb5_data *hash,
+		 krb5_boolean *valid)
+{
+    krb5_MD4_CTX ctx;
+    unsigned char plaintext[CONFLENGTH+RSA_MD4_CKSUM_LENGTH];
+    unsigned char xorkey[8];
+    int i;
+    mit_des_key_schedule schedule;
+    int compathash = 0;
+
+    if (key->length != 8)
+	return(KRB5_BAD_KEYSIZE);
+    if (ivec)
+	return(KRB5_CRYPTO_INTERNAL);
+    if (hash->length != (CONFLENGTH+RSA_MD4_CKSUM_LENGTH)) {
+#ifdef KRB5_MD4DES_BETA5_COMPAT
+	if (hash->length != RSA_MD4_CKSUM_LENGTH)
+	    return(KRB5_CRYPTO_INTERNAL);
+	else
+	    compathash = 1;
+#else
+	return(KRB5_CRYPTO_INTERNAL);
+#endif
+	return(KRB5_CRYPTO_INTERNAL);
+    }
+
+    /* create and schedule the encryption key */
+
+    memcpy(xorkey, key->contents, sizeof(xorkey));
+    if (!compathash) {
+	for (i=0; i<sizeof(xorkey); i++)
+	    xorkey[i] ^= 0xf0;
+    }
+    
+    switch (mit_des_key_sched(xorkey, schedule)) {
+    case -1:
+	return(KRB5DES_BAD_KEYPAR);
+    case -2:
+	return(KRB5DES_WEAK_KEY);
+    }
+
+    /* decrypt it.  this has a return value, but it's always zero.  */
+
+    if (!compathash) {
+	mit_des_cbc_encrypt((krb5_pointer) hash->data,
+			    (krb5_pointer) plaintext, hash->length,
+			    schedule, (unsigned char *) mit_des_zeroblock, 0);
+    } else {
+	mit_des_cbc_encrypt((krb5_pointer) hash->data,
+			    (krb5_pointer) plaintext, hash->length,
+			    schedule, xorkey, 0);
+    }
+
+    /* hash the confounder, then the input data */
+
+    krb5_MD4Init(&ctx);
+    if (!compathash) {
+	krb5_MD4Update(&ctx, plaintext, CONFLENGTH);
+    }
+    krb5_MD4Update(&ctx, (unsigned char *) input->data, 
+		   (unsigned int) input->length);
+    krb5_MD4Final(&ctx);
+
+    /* compare the decrypted hash to the computed one */
+
+    if (!compathash) {
+	*valid =
+	    (memcmp(plaintext+CONFLENGTH, ctx.digest, RSA_MD4_CKSUM_LENGTH)
+	     == 0);
+    } else {
+	*valid =
+	    (memcmp(plaintext, ctx.digest, RSA_MD4_CKSUM_LENGTH) == 0);
+    }
+
+    memset(plaintext, 0, sizeof(plaintext));
+
+    return(0);
+}
+
+const struct krb5_keyhash_provider krb5int_keyhash_md4des = {
+    CONFLENGTH+RSA_MD4_CKSUM_LENGTH,
+    k5_md4des_hash,
+    k5_md4des_verify
+};
diff --git a/krb5-1-6/src/lib/crypto/keyhash_provider/k5_md5des.c b/krb5-1-6/src/lib/crypto/keyhash_provider/k5_md5des.c
new file mode 100644
index 000000000..4f7b89812
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyhash_provider/k5_md5des.c
@@ -0,0 +1,187 @@
+/*
+ * 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 "rsa-md5.h"
+#include "keyhash_provider.h"
+
+#define CONFLENGTH 8
+
+/* Force acceptance of krb5-beta5 md5des checksum for now. */
+#define KRB5_MD5DES_BETA5_COMPAT
+
+/* des-cbc(xorkey, conf | rsa-md5(conf | data)) */
+
+/* this could be done in terms of the md5 and des providers, but
+   that's less efficient, and there's no need for this to be generic */
+
+static krb5_error_code
+k5_md5des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec,
+	       const krb5_data *input, krb5_data *output)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    krb5_MD5_CTX ctx;
+    unsigned char conf[CONFLENGTH];
+    unsigned char xorkey[8];
+    int i;
+    mit_des_key_schedule schedule;
+
+    if (key->length != 8)
+	return(KRB5_BAD_KEYSIZE);
+    if (ivec)
+	return(KRB5_CRYPTO_INTERNAL);
+    if (output->length != (CONFLENGTH+RSA_MD5_CKSUM_LENGTH))
+	return(KRB5_CRYPTO_INTERNAL);
+
+    /* create the confouder */
+
+    data.length = CONFLENGTH;
+    data.data = (char *) conf;
+    if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &data)))
+	return(ret);
+
+    /* create and schedule the encryption key */
+
+    memcpy(xorkey, key->contents, sizeof(xorkey));
+    for (i=0; i<sizeof(xorkey); i++)
+	xorkey[i] ^= 0xf0;
+    
+    switch (ret = mit_des_key_sched(xorkey, schedule)) {
+    case -1:
+	return(KRB5DES_BAD_KEYPAR);
+    case -2:
+	return(KRB5DES_WEAK_KEY);
+    }
+
+    /* hash the confounder, then the input data */
+
+    krb5_MD5Init(&ctx);
+    krb5_MD5Update(&ctx, conf, CONFLENGTH);
+    krb5_MD5Update(&ctx, (unsigned char *) input->data, 
+		   (unsigned int) input->length);
+    krb5_MD5Final(&ctx);
+
+    /* construct the buffer to be encrypted */
+
+    memcpy(output->data, conf, CONFLENGTH);
+    memcpy(output->data+CONFLENGTH, ctx.digest, RSA_MD5_CKSUM_LENGTH);
+
+    /* encrypt it, in place.  this has a return value, but it's
+       always zero.  */
+
+    mit_des_cbc_encrypt((krb5_pointer) output->data,
+			(krb5_pointer) output->data, output->length,
+			schedule, (unsigned char *) mit_des_zeroblock, 1);
+
+    return(0);
+}
+
+static krb5_error_code
+k5_md5des_verify(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec,
+		 const krb5_data *input, const krb5_data *hash,
+		 krb5_boolean *valid)
+{
+    krb5_MD5_CTX ctx;
+    unsigned char plaintext[CONFLENGTH+RSA_MD5_CKSUM_LENGTH];
+    unsigned char xorkey[8];
+    int i;
+    mit_des_key_schedule schedule;
+    int compathash = 0;
+
+    if (key->length != 8)
+	return(KRB5_BAD_KEYSIZE);
+    if (ivec)
+	return(KRB5_CRYPTO_INTERNAL);
+    if (hash->length != (CONFLENGTH+RSA_MD5_CKSUM_LENGTH)) {
+#ifdef KRB5_MD5DES_BETA5_COMPAT
+	if (hash->length != RSA_MD5_CKSUM_LENGTH)
+	    return(KRB5_CRYPTO_INTERNAL);
+	else
+	    compathash = 1;
+#else
+	return(KRB5_CRYPTO_INTERNAL);
+#endif
+    }
+
+    /* create and schedule the encryption key */
+
+    memcpy(xorkey, key->contents, sizeof(xorkey));
+    if (!compathash) {
+	for (i=0; i<sizeof(xorkey); i++)
+	    xorkey[i] ^= 0xf0;
+    }
+    
+    switch (mit_des_key_sched(xorkey, schedule)) {
+    case -1:
+	return(KRB5DES_BAD_KEYPAR);
+    case -2:
+	return(KRB5DES_WEAK_KEY);
+    }
+
+    /* decrypt it.  this has a return value, but it's always zero.  */
+
+    if (!compathash) {
+	mit_des_cbc_encrypt((krb5_pointer) hash->data,
+			    (krb5_pointer) plaintext, hash->length,
+			    schedule, (unsigned char *) mit_des_zeroblock, 0);
+    } else {
+	mit_des_cbc_encrypt((krb5_pointer) hash->data,
+			    (krb5_pointer) plaintext, hash->length,
+			    schedule, xorkey, 0);
+    }
+
+    /* hash the confounder, then the input data */
+
+    krb5_MD5Init(&ctx);
+    if (!compathash) {
+	krb5_MD5Update(&ctx, plaintext, CONFLENGTH);
+    }
+    krb5_MD5Update(&ctx, (unsigned char *) input->data, 
+		   (unsigned) input->length);
+    krb5_MD5Final(&ctx);
+
+    /* compare the decrypted hash to the computed one */
+
+    if (!compathash) {
+	*valid =
+	    (memcmp(plaintext+CONFLENGTH, ctx.digest, RSA_MD5_CKSUM_LENGTH)
+	     == 0);
+    } else {
+	*valid = 
+	    (memcmp(plaintext, ctx.digest, RSA_MD5_CKSUM_LENGTH) == 0);
+    }
+    memset(plaintext, 0, sizeof(plaintext));
+
+    return(0);
+}
+
+const struct krb5_keyhash_provider krb5int_keyhash_md5des = {
+    CONFLENGTH+RSA_MD5_CKSUM_LENGTH,
+    k5_md5des_hash,
+    k5_md5des_verify
+};
diff --git a/krb5-1-6/src/lib/crypto/keyhash_provider/keyhash_provider.h b/krb5-1-6/src/lib/crypto/keyhash_provider/keyhash_provider.h
new file mode 100644
index 000000000..6a96faf8f
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyhash_provider/keyhash_provider.h
@@ -0,0 +1,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"
+
+extern const struct krb5_keyhash_provider krb5int_keyhash_descbc;
+extern const struct krb5_keyhash_provider krb5int_keyhash_md4des;
+extern const struct krb5_keyhash_provider krb5int_keyhash_md5des;
+extern const struct krb5_keyhash_provider krb5int_keyhash_hmac_md5;
diff --git a/krb5-1-6/src/lib/crypto/keyhash_provider/t_cksum.c b/krb5-1-6/src/lib/crypto/keyhash_provider/t_cksum.c
new file mode 100644
index 000000000..98187f7f1
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keyhash_provider/t_cksum.c
@@ -0,0 +1,139 @@
+/*
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * t_cksum.c - Test checksum and checksum compatability for rsa-md[4,5]-des
+ */
+
+#include "k5-int.h"
+
+#define MD5_K5BETA_COMPAT
+#define MD4_K5BETA_COMPAT
+
+#if	MD == 4
+extern struct krb5_keyhash_provider krb5int_keyhash_md4des;
+#define khp krb5int_keyhash_md4des
+#endif
+
+#if	MD == 5
+extern struct krb5_keyhash_provider krb5int_keyhash_md5des;
+#define khp krb5int_keyhash_md5des
+#endif
+
+static void
+print_checksum(text, number, message, checksum)
+     char	*text;
+     int	number;
+     char	*message;
+     krb5_data	*checksum;
+{
+  int i;
+
+  printf("%s MD%d checksum(\"%s\") = ", text, number, message);
+  for (i=0; i<checksum->length; i++)
+    printf("%02x", (unsigned char) checksum->data[i]);
+  printf("\n");
+}
+
+/*
+ * Test the checksum verification of Old Style (tm) and correct RSA-MD[4,5]-DES
+ * checksums.
+ */
+
+krb5_octet testkey[8] = { 0x45, 0x01, 0x49, 0x61, 0x58, 0x19, 0x1a, 0x3d };
+
+int
+main(argc, argv)
+     int argc;
+     char **argv;
+{
+  int 			msgindex;
+  krb5_boolean		valid;
+  size_t		length;
+  krb5_keyblock		keyblock;
+  krb5_error_code	kret=0;
+  krb5_data		plaintext, newstyle_checksum;
+
+  /* this is a terrible seed, but that's ok for the test. */
+
+  plaintext.length = 8;
+  plaintext.data = (char *) testkey;
+
+  krb5_c_random_seed(/* XXX */ 0, &plaintext);
+
+  keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+  keyblock.length = sizeof(testkey);
+  keyblock.contents = testkey;
+
+  length = khp.hashsize;
+
+  newstyle_checksum.length = length;
+
+  if (!(newstyle_checksum.data = (char *)
+	malloc((unsigned) newstyle_checksum.length))) {
+    printf("cannot get memory for new style checksum\n");
+    return(ENOMEM);
+  }
+  for (msgindex = 1; msgindex < argc; msgindex++) {
+    plaintext.length = strlen(argv[msgindex]);
+    plaintext.data = argv[msgindex];
+
+    if ((kret = (*(khp.hash))(&keyblock, 0, 0, &plaintext, &newstyle_checksum))) {
+      printf("krb5_calculate_checksum choked with %d\n", kret);
+      break;
+    }
+    print_checksum("correct", MD, argv[msgindex], &newstyle_checksum);
+
+    if ((kret = (*(khp.verify))(&keyblock, 0, 0, &plaintext, &newstyle_checksum,
+				&valid))) {
+      printf("verify on new checksum choked with %d\n", kret);
+      break;
+    }
+    if (!valid) {
+      printf("verify on new checksum failed\n");
+      break;
+    }
+    printf("Verify succeeded for \"%s\"\n", argv[msgindex]);
+
+    newstyle_checksum.data[0]++;
+    if ((kret = (*(khp.verify))(&keyblock, 0, 0, &plaintext, &newstyle_checksum,
+				&valid))) {
+      printf("verify on new checksum choked with %d\n", kret);
+      break;
+    }
+    if (valid) {
+      printf("verify on new checksum succeeded, but shouldn't have\n");
+      break;
+    }
+    printf("Verify of bad checksum OK for \"%s\"\n", argv[msgindex]);
+    kret = 0;
+  }
+  free(newstyle_checksum.data);
+  if (!kret)
+    printf("%d tests passed successfully for MD%d checksum\n", argc-1, MD);
+  return(kret);
+}
diff --git a/krb5-1-6/src/lib/crypto/keylengths.c b/krb5-1-6/src/lib/crypto/keylengths.c
new file mode 100644
index 000000000..acd1da81b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/keylengths.c
@@ -0,0 +1,61 @@
+/*
+ * COPYRIGHT (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ * 
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ * 
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+/*
+ * keybytes is the number of bytes required as input to make a key,
+ * keylength is the length of the final key in bytes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_c_keylengths(krb5_context context, krb5_enctype enctype,
+		  size_t *keybytes, size_t *keylength)
+{
+    int i;
+
+    if (keybytes == NULL && keylength == NULL)
+	return(EINVAL);
+
+    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);
+
+    if (keybytes)
+	*keybytes = krb5_enctypes_list[i].enc->keybytes;
+    if (keylength)
+	*keylength = krb5_enctypes_list[i].enc->keylength;
+
+    return(0);
+}
diff --git a/krb5-1-6/src/lib/crypto/libk5crypto.exports b/krb5-1-6/src/lib/crypto/libk5crypto.exports
new file mode 100644
index 000000000..99eb2025b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/libk5crypto.exports
@@ -0,0 +1,158 @@
+des_FP_table
+des_IP_table
+des_SP_table
+is_coll_proof_cksum
+is_keyed_cksum
+krb5_MD4Final
+krb5_MD4Init
+krb5_MD4Update
+krb5_MD5Final
+krb5_MD5Init
+krb5_MD5Update
+krb5_arcfour_decrypt
+krb5_arcfour_encrypt
+krb5_arcfour_encrypt_length
+krb5_c_block_size
+krb5_c_checksum_length
+krb5_c_decrypt
+krb5_c_encrypt
+krb5_c_encrypt_length
+krb5_c_enctype_compare
+krb5_c_free_state
+krb5_c_init_state
+krb5_c_is_coll_proof_cksum
+krb5_c_is_keyed_cksum
+krb5_c_keyed_checksum_types
+krb5_c_keylengths
+krb5_c_make_checksum
+krb5_c_make_random_key
+krb5_c_prf
+krb5_c_prf_length
+krb5_c_random_add_entropy
+krb5_c_random_make_octets
+krb5_c_random_os_entropy
+krb5_c_random_seed
+krb5_c_random_to_key
+krb5_c_string_to_key
+krb5_c_string_to_key_with_params
+krb5_c_valid_cksumtype
+krb5_c_valid_enctype
+krb5_c_verify_checksum
+krb5_calculate_checksum
+krb5_checksum_size
+krb5_cksumtype_to_string
+krb5_cksumtypes_length
+krb5_cksumtypes_list
+krb5_decrypt
+krb5_decrypt_data
+krb5_derive_key
+krb5_derive_random
+krb5_dk_decrypt
+krb5_dk_encrypt
+krb5_dk_encrypt_length
+krb5_dk_make_checksum
+krb5_eblock_enctype
+krb5_encrypt
+krb5_encrypt_data
+krb5_encrypt_size
+krb5_enctype_to_string
+krb5_enctypes_length
+krb5_enctypes_list
+krb5_finish_key
+krb5_finish_random_key
+krb5_free_cksumtypes
+krb5_hmac
+krb5_init_random_key
+krb5_nfold
+krb5_old_decrypt
+krb5_old_encrypt
+krb5_old_encrypt_length
+krb5_process_key
+krb5_random_confounder
+krb5_random_key
+krb5_raw_decrypt
+krb5_raw_encrypt
+krb5_raw_encrypt_length
+krb5_string_to_cksumtype
+krb5_string_to_enctype
+krb5_string_to_key
+krb5_use_enctype
+krb5_verify_checksum
+krb5int_aes_dec_blk
+krb5int_aes_dec_key
+krb5int_aes_decrypt
+krb5int_aes_dk_decrypt
+krb5int_aes_dk_encrypt
+krb5int_aes_enc_blk
+krb5int_aes_enc_key
+krb5int_aes_encrypt
+krb5int_aes_encrypt_length
+krb5int_aes_string_to_key
+krb5int_arcfour_string_to_key
+krb5int_arcfour_translate_usage
+krb5int_c_combine_keys
+krb5int_c_mandatory_cksumtype
+krb5int_c_free_keyblock
+krb5int_c_free_keyblock_contents
+krb5int_c_init_keyblock
+krb5int_c_mit_des_zeroblock
+krb5int_default_free_state
+krb5int_des3_cbc_decrypt
+krb5int_des3_cbc_encrypt
+krb5int_des_cbc_decrypt
+krb5int_des_cbc_encrypt
+krb5int_des_init_state
+krb5int_des_string_to_key
+krb5int_dk_string_to_key
+krb5int_enc_aes128
+krb5int_enc_aes256
+krb5int_enc_arcfour
+krb5int_enc_des
+krb5int_enc_des3
+krb5int_fl_tab
+krb5int_ft_tab
+krb5int_hash_crc32
+krb5int_hash_md4
+krb5int_hash_md5
+krb5int_hash_sha1
+krb5int_il_tab
+krb5int_im_tab
+krb5int_it_tab
+krb5int_keyhash_descbc
+krb5int_keyhash_hmac_md5
+krb5int_keyhash_md4des
+krb5int_keyhash_md5des
+krb5int_pbkdf2_hmac_sha1
+krb5int_prng_cleanup
+krb5int_rcon_tab
+krb5int_yarrow_cipher_encrypt_block
+krb5int_yarrow_cipher_init
+krb5int_yarrow_final
+krb5int_yarrow_gate
+krb5int_yarrow_init
+krb5int_yarrow_input
+krb5int_yarrow_new_source
+krb5int_yarrow_output
+krb5int_yarrow_register_source_estimator
+krb5int_yarrow_reseed
+krb5int_yarrow_status
+krb5int_yarrow_str_error
+krb5int_yarrow_stretch
+mit_afs_crypt
+mit_afs_string_to_key
+mit_crc32
+mit_des3_cbc_encrypt
+mit_des3_key_sched
+mit_des_cbc_cksum
+mit_des_cbc_encrypt
+mit_des_check_key_parity
+mit_des_fixup_key_parity
+mit_des_is_weak_key
+mit_des_key_sched
+mit_des_make_key_sched
+mit_des_string_to_key_int
+shsFinal
+shsInit
+shsUpdate
+valid_cksumtype
+valid_enctype
diff --git a/krb5-1-6/src/lib/crypto/make_checksum.c b/krb5-1-6/src/lib/crypto/make_checksum.c
new file mode 100644
index 000000000..4a2f00072
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/make_checksum.c
@@ -0,0 +1,114 @@
+/*
+ * 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"
+#include "dk.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype,
+		     const krb5_keyblock *key, krb5_keyusage usage,
+		     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)
+	cksumlen = krb5_cksumtypes_list[i].keyhash->hashsize;
+    else
+	cksumlen = krb5_cksumtypes_list[i].hash->hashsize;
+
+    cksum->length = cksumlen;
+
+    if ((cksum->contents = (krb5_octet *) malloc(cksum->length)) == NULL)
+	return(ENOMEM);
+
+    data.length = cksum->length;
+    data.data = (char *) 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, usage, 0, input, &data);
+    } else if (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE) {
+	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;
+	if (krb5_cksumtypes_list[i].trunc_size) {
+	    krb5_octet *trunc;
+	    cksum->length = krb5_cksumtypes_list[i].trunc_size;
+	    trunc = (krb5_octet *) realloc(cksum->contents, cksum->length);
+	    if (trunc)
+		cksum->contents = trunc;
+	}
+    }
+
+cleanup:
+    if (ret) {
+	memset(cksum->contents, 0, cksum->length);
+	free(cksum->contents);
+	cksum->contents = NULL;
+    }
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/lib/crypto/make_random_key.c b/krb5-1-6/src/lib/crypto/make_random_key.c
new file mode 100644
index 000000000..0ae321dca
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/make_random_key.c
@@ -0,0 +1,83 @@
+/*
+ * 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_CALLCONV
+krb5_c_make_random_key(krb5_context context, krb5_enctype enctype,
+		       krb5_keyblock *random_key)
+{
+    int i;
+    krb5_error_code ret;
+    const struct krb5_enc_provider *enc;
+    size_t keybytes, keylength;
+    krb5_data random_data;
+    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;
+
+    keybytes = enc->keybytes;
+    keylength = enc->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.data = (char *) bytes;
+    random_data.length = keybytes;
+
+    if ((ret = krb5_c_random_make_octets(context, &random_data)))
+	goto cleanup;
+
+    random_key->magic = KV5M_KEYBLOCK;
+    random_key->enctype = enctype;
+    random_key->length = keylength;
+
+    ret = ((*(enc->make_key))(&random_data, 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/krb5-1-6/src/lib/crypto/mandatory_sumtype.c b/krb5-1-6/src/lib/crypto/mandatory_sumtype.c
new file mode 100644
index 000000000..f9322ff3f
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/mandatory_sumtype.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2003 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+
+krb5_error_code
+krb5int_c_mandatory_cksumtype (krb5_context ctx, krb5_enctype etype,
+			       krb5_cksumtype *cksumtype)
+{
+    int i;
+
+    for (i = 0; i < krb5_enctypes_length; i++)
+	if (krb5_enctypes_list[i].etype == etype) {
+	    *cksumtype = krb5_enctypes_list[i].required_ctype;
+	    return 0;
+	}
+
+    return KRB5_BAD_ENCTYPE;
+}
diff --git a/krb5-1-6/src/lib/crypto/md4/ISSUES b/krb5-1-6/src/lib/crypto/md4/ISSUES
new file mode 100644
index 000000000..1103bd87b
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md4/ISSUES
@@ -0,0 +1,3 @@
+Issues to be addressed for src/lib/crypto/md4: -*- text -*-
+
+Assumes int is >= 32 bits.
diff --git a/krb5-1-6/src/lib/crypto/md4/Makefile.in b/krb5-1-6/src/lib/crypto/md4/Makefile.in
new file mode 100644
index 000000000..3f6201852
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md4/Makefile.in
@@ -0,0 +1,72 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/md4
+mydir=lib/crypto/md4
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=md4
+##DOS##OBJFILE=..\$(OUTPRE)md4.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= md4.o
+
+OBJS= $(OUTPRE)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
+
+t_mddriver.o: t_mddriver.c
+	$(CC) -DMD=4 $(ALL_CFLAGS) -c  t_mddriver.c
+
+t_mddriver: t_mddriver.o md4.o $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o t_mddriver t_mddriver.o md4.o $(SUPPORT_LIB)
+
+$(OUTPRE)t_mddriver.obj: t_mddriver.c
+	$(CC) -DMD=4 $(ALL_CFLAGS) -Fo$@ -c $**
+
+$(OUTPRE)t_mddriver.exe: $(OUTPRE)t_mddriver.obj $(OUTPRE)md4.obj
+	link -out:$@ $**
+
+check-unix:: t_mddriver
+	$(RUN_SETUP) $(VALGRIND) $(C)t_mddriver -x
+
+check-windows:: $(OUTPRE)t_mddriver.exe
+	$(OUTPRE)$(C)t_mddriver.exe -x
+
+clean:: 
+	$(RM) $(OUTPRE)t_mddriver$(EXEEXT) $(OUTPRE)t_mddriver.$(OBJEXT) t_mddriver.c
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+md4.so md4.po $(OUTPRE)md4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  md4.c rsa-md4.h
diff --git a/krb5-1-6/src/lib/crypto/md4/md4.c b/krb5-1-6/src/lib/crypto/md4/md4.c
new file mode 100644
index 000000000..5e95d359f
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md4/md4.c
@@ -0,0 +1,257 @@
+/*
+ *	lib/crypto/md4/md4.c
+ */
+
+/*
+ **********************************************************************
+ ** md4.c                                                            **
+ ** RSA Data Security, Inc. MD4 Message Digest Algorithm             **
+ ** Created: 2/17/90 RLR                                             **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version                  **
+ **********************************************************************
+ */
+
+/*
+ **********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ **                                                                  **
+ ** License to copy and use this software is granted provided that   **
+ ** it is identified as the "RSA Data Security, Inc. MD4 Message     **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function.                                       **
+ **                                                                  **
+ ** License is also granted to make and use derivative works         **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD4 Message Digest Algorithm" in all         **
+ ** material mentioning or referencing the derived work.             **
+ **                                                                  **
+ ** 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"
+
+/* forward declaration */
+static void Transform (krb5_ui_4 *, krb5_ui_4 *);
+
+static const unsigned char PADDING[64] = {
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G and H are basic MD4 functions: selection, majority, parity */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) ((((x) << (n)) & 0xffffffff) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s) \
+  {(a) += F ((b), (c), (d)) + (x); \
+   (a) &= 0xffffffff; \
+   (a) = ROTATE_LEFT ((a), (s));}
+#define GG(a, b, c, d, x, s) \
+  {(a) += G ((b), (c), (d)) + (x) + 013240474631UL; \
+   (a) &= 0xffffffff; \
+   (a) = ROTATE_LEFT ((a), (s));}
+#define HH(a, b, c, d, x, s) \
+  {(a) += H ((b), (c), (d)) + (x) + 015666365641UL; \
+   (a) &= 0xffffffff; \
+   (a) = ROTATE_LEFT ((a), (s));}
+
+void
+krb5_MD4Init (krb5_MD4_CTX *mdContext)
+{
+  mdContext->i[0] = mdContext->i[1] = (krb5_ui_4)0;
+
+  /* Load magic initialization constants.
+   */
+  mdContext->buf[0] = 0x67452301UL;
+  mdContext->buf[1] = 0xefcdab89UL;
+  mdContext->buf[2] = 0x98badcfeUL;
+  mdContext->buf[3] = 0x10325476UL;
+}
+
+void
+krb5_MD4Update (krb5_MD4_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen)
+{
+  krb5_ui_4 in[16];
+  int mdi;
+  unsigned int i, ii;
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* update number of bits */
+  if ((mdContext->i[0] + ((krb5_ui_4)inLen << 3)) < mdContext->i[0])
+    mdContext->i[1]++;
+  mdContext->i[0] += ((krb5_ui_4)inLen << 3);
+  mdContext->i[1] += ((krb5_ui_4)inLen >> 29);
+
+  while (inLen--) {
+    /* add new character to buffer, increment mdi */
+    mdContext->in[mdi++] = *inBuf++;
+
+    /* transform if necessary */
+    if (mdi == 0x40) {
+      for (i = 0, ii = 0; i < 16; i++, ii += 4)
+        in[i] = (((krb5_ui_4)mdContext->in[ii+3]) << 24) |
+                (((krb5_ui_4)mdContext->in[ii+2]) << 16) |
+                (((krb5_ui_4)mdContext->in[ii+1]) << 8) |
+                ((krb5_ui_4)mdContext->in[ii]);
+      Transform (mdContext->buf, in);
+      mdi = 0;
+    }
+  }
+}
+
+void
+krb5_MD4Final (krb5_MD4_CTX *mdContext)
+{
+  krb5_ui_4 in[16];
+  int mdi;
+  unsigned int i, ii;
+  unsigned int padLen;
+
+  /* save number of bits */
+  in[14] = mdContext->i[0];
+  in[15] = mdContext->i[1];
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* pad out to 56 mod 64 */
+  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+  krb5_MD4Update (mdContext, PADDING, padLen);
+
+  /* append length in bits and transform */
+  for (i = 0, ii = 0; i < 14; i++, ii += 4)
+    in[i] = (((krb5_ui_4)mdContext->in[ii+3]) << 24) |
+            (((krb5_ui_4)mdContext->in[ii+2]) << 16) |
+            (((krb5_ui_4)mdContext->in[ii+1]) << 8) |
+            ((krb5_ui_4)mdContext->in[ii]);
+  Transform (mdContext->buf, in);
+
+
+  /* store buffer in digest */
+  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+    mdContext->digest[ii+1] =
+      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+    mdContext->digest[ii+2] =
+      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+    mdContext->digest[ii+3] =
+      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+  }
+}
+
+/* Basic MD4 step. Transform buf based on in.
+ */
+static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in)
+{
+  register krb5_ui_4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+#ifdef CONFIG_SMALL
+  int i;
+#define ROTATE { krb5_ui_4 temp; temp = d, d = c, c = b, b = a, a = temp; }
+  for (i = 0; i < 16; i++) {
+      static const unsigned char round1consts[] = { 3, 7, 11, 19, };
+      FF (a, b, c, d, in[i], round1consts[i%4]); ROTATE;
+  }
+  for (i = 0; i < 16; i++) {
+      static const unsigned char round2indices[] = {
+	  0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15
+      };
+      static const unsigned char round2consts[] = { 3, 5, 9, 13 };
+      GG (a, b, c, d, in[round2indices[i]], round2consts[i%4]); ROTATE;
+  }
+  for (i = 0; i < 16; i++) {
+      static const unsigned char round3indices[] = {
+	  0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
+      };
+      static const unsigned char round3consts[] = { 3, 9, 11, 15 };
+      HH (a, b, c, d, in[round3indices[i]], round3consts[i%4]); ROTATE;
+  }
+#else
+  /* Round 1 */
+  FF (a, b, c, d, in[ 0],  3);
+  FF (d, a, b, c, in[ 1],  7);
+  FF (c, d, a, b, in[ 2], 11);
+  FF (b, c, d, a, in[ 3], 19);
+  FF (a, b, c, d, in[ 4],  3);
+  FF (d, a, b, c, in[ 5],  7);
+  FF (c, d, a, b, in[ 6], 11);
+  FF (b, c, d, a, in[ 7], 19);
+  FF (a, b, c, d, in[ 8],  3);
+  FF (d, a, b, c, in[ 9],  7);
+  FF (c, d, a, b, in[10], 11);
+  FF (b, c, d, a, in[11], 19);
+  FF (a, b, c, d, in[12],  3);
+  FF (d, a, b, c, in[13],  7);
+  FF (c, d, a, b, in[14], 11);
+  FF (b, c, d, a, in[15], 19);
+
+  /* Round 2 */
+  GG (a, b, c, d, in[ 0],  3);
+  GG (d, a, b, c, in[ 4],  5);
+  GG (c, d, a, b, in[ 8],  9);
+  GG (b, c, d, a, in[12], 13);
+  GG (a, b, c, d, in[ 1],  3);
+  GG (d, a, b, c, in[ 5],  5);
+  GG (c, d, a, b, in[ 9],  9);
+  GG (b, c, d, a, in[13], 13);
+  GG (a, b, c, d, in[ 2],  3);
+  GG (d, a, b, c, in[ 6],  5);
+  GG (c, d, a, b, in[10],  9);
+  GG (b, c, d, a, in[14], 13);
+  GG (a, b, c, d, in[ 3],  3);
+  GG (d, a, b, c, in[ 7],  5);
+  GG (c, d, a, b, in[11],  9);
+  GG (b, c, d, a, in[15], 13);
+
+  /* Round 3 */
+  HH (a, b, c, d, in[ 0],  3);
+  HH (d, a, b, c, in[ 8],  9);
+  HH (c, d, a, b, in[ 4], 11);
+  HH (b, c, d, a, in[12], 15);
+  HH (a, b, c, d, in[ 2],  3);
+  HH (d, a, b, c, in[10],  9);
+  HH (c, d, a, b, in[ 6], 11);
+  HH (b, c, d, a, in[14], 15);
+  HH (a, b, c, d, in[ 1],  3);
+  HH (d, a, b, c, in[ 9],  9);
+  HH (c, d, a, b, in[ 5], 11);
+  HH (b, c, d, a, in[13], 15);
+  HH (a, b, c, d, in[ 3],  3);
+  HH (d, a, b, c, in[11],  9);
+  HH (c, d, a, b, in[ 7], 11);
+  HH (b, c, d, a, in[15], 15);
+#endif
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
+
+/*
+ **********************************************************************
+ ** End of md4.c                                                     **
+ ******************************* (cut) ********************************
+ */
diff --git a/krb5-1-6/src/lib/crypto/md4/rsa-md4.h b/krb5-1-6/src/lib/crypto/md4/rsa-md4.h
new file mode 100644
index 000000000..d4e6f6b79
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md4/rsa-md4.h
@@ -0,0 +1,94 @@
+/*
+ * lib/crypto/md4/rsa-md4.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * RSA MD4 header file, with Kerberos/STDC additions.
+ */
+
+#ifndef __KRB5_RSA_MD4_H__
+#define __KRB5_RSA_MD4_H__
+
+#ifdef unicos61
+#include <sys/types.h>
+#endif /* unicos61 */
+
+/* 16 u_char's in the digest */
+#define RSA_MD4_CKSUM_LENGTH	16
+/* des blocksize is 8, so this works nicely... */
+#define OLD_RSA_MD4_DES_CKSUM_LENGTH	16
+#define NEW_RSA_MD4_DES_CKSUM_LENGTH	24
+#define	RSA_MD4_DES_CONFOUND_LENGTH	8
+
+/*
+ **********************************************************************
+ ** md4.h -- Header file for implementation of MD4                   **
+ ** RSA Data Security, Inc. MD4 Message Digest Algorithm             **
+ ** Created: 2/17/90 RLR                                             **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version              **
+ **********************************************************************
+ */
+
+/*
+ **********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ **                                                                  **
+ ** License to copy and use this software is granted provided that   **
+ ** it is identified as the "RSA Data Security, Inc. MD4 Message     **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function.                                       **
+ **                                                                  **
+ ** License is also granted to make and use derivative works         **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD4 Message Digest Algorithm" in all         **
+ ** material mentioning or referencing the derived work.             **
+ **                                                                  **
+ ** 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.                                   **
+ **********************************************************************
+ */
+
+/* Data structure for MD4 (Message Digest) computation */
+typedef struct {
+  krb5_ui_4 i[2];			/* number of _bits_ handled mod 2^64 */
+  krb5_ui_4 buf[4];			/* scratch buffer */
+  unsigned char in[64];			/* input buffer */
+  unsigned char digest[16];		/* actual digest after MD4Final call */
+} krb5_MD4_CTX;
+
+extern void krb5_MD4Init(krb5_MD4_CTX *);
+extern void krb5_MD4Update(krb5_MD4_CTX *, const unsigned char *, unsigned int);
+extern void krb5_MD4Final(krb5_MD4_CTX *);
+
+/*
+ **********************************************************************
+ ** End of md4.h                                                     **
+ ******************************* (cut) ********************************
+ */
+#endif /* __KRB5_RSA_MD4_H__ */
diff --git a/krb5-1-6/src/lib/crypto/md5/ISSUES b/krb5-1-6/src/lib/crypto/md5/ISSUES
new file mode 100644
index 000000000..481e52914
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md5/ISSUES
@@ -0,0 +1,3 @@
+Issues to be addressed for src/lib/crypto/md5: -*- text -*-
+
+Assumes int is >= 32 bits.
diff --git a/krb5-1-6/src/lib/crypto/md5/Makefile.in b/krb5-1-6/src/lib/crypto/md5/Makefile.in
new file mode 100644
index 000000000..32893ad80
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md5/Makefile.in
@@ -0,0 +1,62 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/md5
+mydir=lib/crypto/md5
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=md5
+##DOS##OBJFILE=..\$(OUTPRE)md5.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= md5.o
+
+OBJS= $(OUTPRE)md5.$(OBJEXT) 
+
+SRCS= $(srcdir)/md5.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+t_mddriver: t_mddriver.o md5.o $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o t_mddriver t_mddriver.o md5.o $(SUPPORT_LIB)
+
+$(OUTPRE)t_mddriver.exe: $(OUTPRE)t_mddriver.obj $(OUTPRE)md5.obj
+	link -out:$@ $**
+
+check-unix:: t_mddriver
+	$(RUN_SETUP) $(VALGRIND) $(C)t_mddriver -x
+
+check-windows:: $(OUTPRE)t_mddriver.exe
+	$(OUTPRE)$(C)t_mddriver.exe -x
+
+clean:: 
+	$(RM) $(OUTPRE)t_mddriver$(EXEEXT) $(OUTPRE)t_mddriver.$(OBJEXT)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+md5.so md5.po $(OUTPRE)md5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  md5.c rsa-md5.h
diff --git a/krb5-1-6/src/lib/crypto/md5/md5.c b/krb5-1-6/src/lib/crypto/md5/md5.c
new file mode 100644
index 000000000..4b56755a8
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md5/md5.c
@@ -0,0 +1,355 @@
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines                         **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ * Modified by John Carr, MIT, to use Kerberos 5 typedefs.
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** 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-md5.h"
+
+/*
+ ***********************************************************************
+ **  Message-digest routines:                                         **
+ **  To form the message digest for a message M                       **
+ **    (1) Initialize a context buffer mdContext using krb5_MD5Init   **
+ **    (2) Call krb5_MD5Update on mdContext and M                     **
+ **    (3) Call krb5_MD5Final on mdContext                            **
+ **  The message digest is now in mdContext->digest[0...15]           **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in);
+
+static const unsigned char PADDING[64] = {
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) ((((x) << (n)) & 0xffffffff) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+  {(a) += F ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \
+   (a) &= 0xffffffff; \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+   (a) &= 0xffffffff; \
+  }
+#define GG(a, b, c, d, x, s, ac) \
+  {(a) += G ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \
+   (a) &= 0xffffffff; \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+   (a) &= 0xffffffff; \
+  }
+#define HH(a, b, c, d, x, s, ac) \
+  {(a) += H ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \
+   (a) &= 0xffffffff; \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+   (a) &= 0xffffffff; \
+  }
+#define II(a, b, c, d, x, s, ac) \
+  {(a) += I ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \
+   (a) &= 0xffffffff; \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+   (a) &= 0xffffffff; \
+  }
+
+/* The routine krb5_MD5Init initializes the message-digest context
+   mdContext. All fields are set to zero.
+ */
+void 
+krb5_MD5Init (krb5_MD5_CTX *mdContext)
+{
+  mdContext->i[0] = mdContext->i[1] = (krb5_ui_4)0;
+
+  /* Load magic initialization constants.
+   */
+  mdContext->buf[0] = 0x67452301UL;
+  mdContext->buf[1] = 0xefcdab89UL;
+  mdContext->buf[2] = 0x98badcfeUL;
+  mdContext->buf[3] = 0x10325476UL;
+}
+
+/* The routine krb5_MD5Update updates the message-digest context to
+   account for the presence of each of the characters inBuf[0..inLen-1]
+   in the message whose digest is being computed.
+ */
+void
+krb5_MD5Update (krb5_MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen)
+{
+  krb5_ui_4 in[16];
+  int mdi;
+  unsigned int i, ii;
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* update number of bits */
+  if ((mdContext->i[0] + ((krb5_ui_4)inLen << 3)) < mdContext->i[0])
+    mdContext->i[1]++;
+  mdContext->i[0] += ((krb5_ui_4)inLen << 3);
+  mdContext->i[1] += ((krb5_ui_4)inLen >> 29);
+
+  while (inLen--) {
+    /* add new character to buffer, increment mdi */
+    mdContext->in[mdi++] = *inBuf++;
+
+    /* transform if necessary */
+    if (mdi == 0x40) {
+      for (i = 0, ii = 0; i < 16; i++, ii += 4)
+        in[i] = (((krb5_ui_4)mdContext->in[ii+3]) << 24) |
+                (((krb5_ui_4)mdContext->in[ii+2]) << 16) |
+                (((krb5_ui_4)mdContext->in[ii+1]) << 8) |
+                ((krb5_ui_4)mdContext->in[ii]);
+      Transform (mdContext->buf, in);
+      mdi = 0;
+    }
+  }
+}
+
+/* The routine krb5_MD5Final terminates the message-digest computation and
+   ends with the desired message digest in mdContext->digest[0...15].
+ */
+void
+krb5_MD5Final (krb5_MD5_CTX *mdContext)
+{
+  krb5_ui_4 in[16];
+  int mdi;
+  unsigned int i, ii;
+  unsigned int padLen;
+
+  /* save number of bits */
+  in[14] = mdContext->i[0];
+  in[15] = mdContext->i[1];
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* pad out to 56 mod 64 */
+  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+  krb5_MD5Update (mdContext, PADDING, padLen);
+
+  /* append length in bits and transform */
+  for (i = 0, ii = 0; i < 14; i++, ii += 4)
+    in[i] = (((krb5_ui_4)mdContext->in[ii+3]) << 24) |
+            (((krb5_ui_4)mdContext->in[ii+2]) << 16) |
+            (((krb5_ui_4)mdContext->in[ii+1]) << 8) |
+            ((krb5_ui_4)mdContext->in[ii]);
+  Transform (mdContext->buf, in);
+
+  /* store buffer in digest */
+  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+    mdContext->digest[ii+1] =
+      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+    mdContext->digest[ii+2] =
+      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+    mdContext->digest[ii+3] =
+      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+  }
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in)
+{
+  register krb5_ui_4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+#ifdef CONFIG_SMALL
+
+  int i;
+#define ROTATE { krb5_ui_4 temp; temp = d, d = c, c = b, b = a, a = temp; }
+  for (i = 0; i < 16; i++) {
+      const unsigned char round1s[] = { 7, 12, 17, 22 };
+      const krb5_ui_4 round1consts[] = {
+	  3614090360UL,	  3905402710UL,	   606105819UL,	  3250441966UL,
+	  4118548399UL,	  1200080426UL,	  2821735955UL,	  4249261313UL,
+	  1770035416UL,	  2336552879UL,	  4294925233UL,	  2304563134UL,
+	  1804603682UL,	  4254626195UL,	  2792965006UL,	  1236535329UL,
+      };
+      FF (a, b, c, d, in[i], round1s[i%4], round1consts[i]);
+      ROTATE;
+  }
+  for (i = 0; i < 16; i++) {
+      const unsigned char round2s[] = { 5, 9, 14, 20 };
+      const krb5_ui_4 round2consts[] = {
+	  4129170786UL,	  3225465664UL,	   643717713UL,	  3921069994UL,
+	  3593408605UL,	    38016083UL,	  3634488961UL,	  3889429448UL,
+	   568446438UL,	  3275163606UL,	  4107603335UL,	  1163531501UL,
+	  2850285829UL,	  4243563512UL,	  1735328473UL,	  2368359562UL,
+      };
+      int r2index = (1 + i * 5) % 16;
+      GG (a, b, c, d, in[r2index], round2s[i%4], round2consts[i]);
+      ROTATE;
+  }
+  for (i = 0; i < 16; i++) {
+      static const unsigned char round3s[] = { 4, 11, 16, 23 };
+      static const krb5_ui_4 round3consts[] = {
+	  4294588738UL,	  2272392833UL,	  1839030562UL,	  4259657740UL,
+	  2763975236UL,	  1272893353UL,	  4139469664UL,	  3200236656UL,
+	   681279174UL,	  3936430074UL,	  3572445317UL,	    76029189UL,
+	  3654602809UL,	  3873151461UL,	   530742520UL,	  3299628645UL,
+      };
+      int r3index = (5 + i * 3) % 16;
+      HH (a, b, c, d, in[r3index], round3s[i%4], round3consts[i]);
+      ROTATE;
+  }
+  for (i = 0; i < 16; i++) {
+      static const unsigned char round4s[] = { 6, 10, 15, 21 };
+      static const krb5_ui_4 round4consts[] = {
+	  4096336452UL,	  1126891415UL,	  2878612391UL,	  4237533241UL,
+	  1700485571UL,	  2399980690UL,	  4293915773UL,	  2240044497UL,
+	  1873313359UL,	  4264355552UL,	  2734768916UL,	  1309151649UL,
+	  4149444226UL,	  3174756917UL,	   718787259UL,	  3951481745UL,
+      };
+      int r4index = (7 * i) % 16;
+      II (a, b, c, d, in[r4index], round4s[i%4], round4consts[i]);
+      ROTATE;
+  }
+
+#else
+
+  /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+  FF ( a, b, c, d, in[ 0], S11, 3614090360UL); /* 1 */
+  FF ( d, a, b, c, in[ 1], S12, 3905402710UL); /* 2 */
+  FF ( c, d, a, b, in[ 2], S13,  606105819UL); /* 3 */
+  FF ( b, c, d, a, in[ 3], S14, 3250441966UL); /* 4 */
+  FF ( a, b, c, d, in[ 4], S11, 4118548399UL); /* 5 */
+  FF ( d, a, b, c, in[ 5], S12, 1200080426UL); /* 6 */
+  FF ( c, d, a, b, in[ 6], S13, 2821735955UL); /* 7 */
+  FF ( b, c, d, a, in[ 7], S14, 4249261313UL); /* 8 */
+  FF ( a, b, c, d, in[ 8], S11, 1770035416UL); /* 9 */
+  FF ( d, a, b, c, in[ 9], S12, 2336552879UL); /* 10 */
+  FF ( c, d, a, b, in[10], S13, 4294925233UL); /* 11 */
+  FF ( b, c, d, a, in[11], S14, 2304563134UL); /* 12 */
+  FF ( a, b, c, d, in[12], S11, 1804603682UL); /* 13 */
+  FF ( d, a, b, c, in[13], S12, 4254626195UL); /* 14 */
+  FF ( c, d, a, b, in[14], S13, 2792965006UL); /* 15 */
+  FF ( b, c, d, a, in[15], S14, 1236535329UL); /* 16 */
+
+  /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+  GG ( a, b, c, d, in[ 1], S21, 4129170786UL); /* 17 */
+  GG ( d, a, b, c, in[ 6], S22, 3225465664UL); /* 18 */
+  GG ( c, d, a, b, in[11], S23,  643717713UL); /* 19 */
+  GG ( b, c, d, a, in[ 0], S24, 3921069994UL); /* 20 */
+  GG ( a, b, c, d, in[ 5], S21, 3593408605UL); /* 21 */
+  GG ( d, a, b, c, in[10], S22,   38016083UL); /* 22 */
+  GG ( c, d, a, b, in[15], S23, 3634488961UL); /* 23 */
+  GG ( b, c, d, a, in[ 4], S24, 3889429448UL); /* 24 */
+  GG ( a, b, c, d, in[ 9], S21,  568446438UL); /* 25 */
+  GG ( d, a, b, c, in[14], S22, 3275163606UL); /* 26 */
+  GG ( c, d, a, b, in[ 3], S23, 4107603335UL); /* 27 */
+  GG ( b, c, d, a, in[ 8], S24, 1163531501UL); /* 28 */
+  GG ( a, b, c, d, in[13], S21, 2850285829UL); /* 29 */
+  GG ( d, a, b, c, in[ 2], S22, 4243563512UL); /* 30 */
+  GG ( c, d, a, b, in[ 7], S23, 1735328473UL); /* 31 */
+  GG ( b, c, d, a, in[12], S24, 2368359562UL); /* 32 */
+
+  /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+  HH ( a, b, c, d, in[ 5], S31, 4294588738UL); /* 33 */
+  HH ( d, a, b, c, in[ 8], S32, 2272392833UL); /* 34 */
+  HH ( c, d, a, b, in[11], S33, 1839030562UL); /* 35 */
+  HH ( b, c, d, a, in[14], S34, 4259657740UL); /* 36 */
+  HH ( a, b, c, d, in[ 1], S31, 2763975236UL); /* 37 */
+  HH ( d, a, b, c, in[ 4], S32, 1272893353UL); /* 38 */
+  HH ( c, d, a, b, in[ 7], S33, 4139469664UL); /* 39 */
+  HH ( b, c, d, a, in[10], S34, 3200236656UL); /* 40 */
+  HH ( a, b, c, d, in[13], S31,  681279174UL); /* 41 */
+  HH ( d, a, b, c, in[ 0], S32, 3936430074UL); /* 42 */
+  HH ( c, d, a, b, in[ 3], S33, 3572445317UL); /* 43 */
+  HH ( b, c, d, a, in[ 6], S34,   76029189UL); /* 44 */
+  HH ( a, b, c, d, in[ 9], S31, 3654602809UL); /* 45 */
+  HH ( d, a, b, c, in[12], S32, 3873151461UL); /* 46 */
+  HH ( c, d, a, b, in[15], S33,  530742520UL); /* 47 */
+  HH ( b, c, d, a, in[ 2], S34, 3299628645UL); /* 48 */
+
+  /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+  II ( a, b, c, d, in[ 0], S41, 4096336452UL); /* 49 */
+  II ( d, a, b, c, in[ 7], S42, 1126891415UL); /* 50 */
+  II ( c, d, a, b, in[14], S43, 2878612391UL); /* 51 */
+  II ( b, c, d, a, in[ 5], S44, 4237533241UL); /* 52 */
+  II ( a, b, c, d, in[12], S41, 1700485571UL); /* 53 */
+  II ( d, a, b, c, in[ 3], S42, 2399980690UL); /* 54 */
+  II ( c, d, a, b, in[10], S43, 4293915773UL); /* 55 */
+  II ( b, c, d, a, in[ 1], S44, 2240044497UL); /* 56 */
+  II ( a, b, c, d, in[ 8], S41, 1873313359UL); /* 57 */
+  II ( d, a, b, c, in[15], S42, 4264355552UL); /* 58 */
+  II ( c, d, a, b, in[ 6], S43, 2734768916UL); /* 59 */
+  II ( b, c, d, a, in[13], S44, 1309151649UL); /* 60 */
+  II ( a, b, c, d, in[ 4], S41, 4149444226UL); /* 61 */
+  II ( d, a, b, c, in[11], S42, 3174756917UL); /* 62 */
+  II ( c, d, a, b, in[ 2], S43,  718787259UL); /* 63 */
+  II ( b, c, d, a, in[ 9], S44, 3951481745UL); /* 64 */
+
+#endif /* small? */
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
diff --git a/krb5-1-6/src/lib/crypto/md5/rsa-md5.h b/krb5-1-6/src/lib/crypto/md5/rsa-md5.h
new file mode 100644
index 000000000..846b23856
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md5/rsa-md5.h
@@ -0,0 +1,60 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5                    **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version               **
+ ** Revised (for MD5): RLR 4/27/91                                    **
+ **   -- G modified to have y&~z instead of y&z                       **
+ **   -- FF, GG, HH modified to add in last register done             **
+ **   -- Access pattern: round 2 works mod 5, round 3 works mod 3     **
+ **   -- distinct additive constant for each step                     **
+ **   -- round 4 added, working mod 7                                 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** 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.                                    **
+ ***********************************************************************
+ */
+
+#ifndef	KRB5_RSA_MD5__
+#define	KRB5_RSA_MD5__
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+  krb5_ui_4 i[2];			/* number of _bits_ handled mod 2^64 */
+  krb5_ui_4 buf[4];			/* scratch buffer */
+  unsigned char in[64];			/* input buffer */
+  unsigned char digest[16];		/* actual digest after MD5Final call */
+} krb5_MD5_CTX;
+
+extern void krb5_MD5Init(krb5_MD5_CTX *);
+extern void krb5_MD5Update(krb5_MD5_CTX *,const unsigned char *,unsigned int);
+extern void krb5_MD5Final(krb5_MD5_CTX *);
+
+#define	RSA_MD5_CKSUM_LENGTH		16
+#define	OLD_RSA_MD5_DES_CKSUM_LENGTH	16
+#define	NEW_RSA_MD5_DES_CKSUM_LENGTH	24
+#define	RSA_MD5_DES_CONFOUND_LENGTH	8
+
+#endif /* KRB5_RSA_MD5__ */
diff --git a/krb5-1-6/src/lib/crypto/md5/t_cksum.c b/krb5-1-6/src/lib/crypto/md5/t_cksum.c
new file mode 100644
index 000000000..17ecd51d7
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md5/t_cksum.c
@@ -0,0 +1,206 @@
+/*
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * 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/krb5-1-6/src/lib/crypto/md5/t_mddriver.c b/krb5-1-6/src/lib/crypto/md5/t_mddriver.c
new file mode 100644
index 000000000..d894aaaec
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/md5/t_mddriver.c
@@ -0,0 +1,323 @@
+/* MDDRIVER.C - test driver for MD2, MD4 and MD5
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. 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.
+ */
+
+/* The following makes MD default to MD5 if it has not already been
+  defined with C compiler flags.
+ */
+#ifndef MD
+#define MD 5
+#endif
+
+#include "k5-int.h"
+
+#if MD == 2
+#include "md2.h"
+#endif
+#if MD == 4
+#include "rsa-md4.h"
+#endif
+#if MD == 5
+#include "rsa-md5.h"
+#endif
+
+/* Length of test block, number of test blocks.
+ */
+#define TEST_BLOCK_LEN 1000
+#define TEST_BLOCK_COUNT 1000
+
+static void MDString (char *);
+static void MDTimeTrial (void);
+static void MDTestSuite (void);
+static void MDFile (char *);
+static void MDFilter (void);
+static void MDPrint (unsigned char [16]);
+
+struct md_test_entry {
+    char *string;
+    unsigned char digest[16];
+};
+
+#if MD == 2
+#define MD_CTX krb5_MD2_CTX
+#define MDInit krb5_MD2Init
+#define MDUpdate krb5_MD2Update
+#define MDFinal krb5_MD2Final
+#endif
+
+#if MD == 4
+#define MD_CTX krb5_MD4_CTX
+#define MDInit krb5_MD4Init
+#define MDUpdate krb5_MD4Update
+#define MDFinal krb5_MD4Final
+
+#define HAVE_TEST_SUITE
+/* Test suite from RFC 1320 */
+
+struct md_test_entry md_test_suite[] = {
+    { "",
+	  {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
+	   0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 }},
+    { "a",
+	  {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
+	   0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 }},
+    { "abc",
+	  {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
+	   0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d }},
+    { "message digest",
+	  {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
+	   0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b }},
+    { "abcdefghijklmnopqrstuvwxyz",
+	  {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
+	   0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 }},
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+	  {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
+	  0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 }},
+    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+	  {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
+	   0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 }},
+    {0, {0}}
+};
+
+#endif
+
+#if MD == 5
+#define MD_CTX krb5_MD5_CTX
+#define MDInit krb5_MD5Init
+#define MDUpdate krb5_MD5Update
+#define MDFinal krb5_MD5Final
+
+#define HAVE_TEST_SUITE
+/* Test suite from RFC 1321 */
+
+struct md_test_entry md_test_suite[] = {
+    { "",
+	  {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+	   0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e }},
+    { "a",
+	  {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
+	   0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 }},
+    { "abc",
+	  {0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+	   0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 }},
+    { "message digest",
+	  {0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
+	   0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 }},
+    { "abcdefghijklmnopqrstuvwxyz",
+	  {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
+	   0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b }},
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 
+	  {0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
+	   0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f }},
+    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+	  {0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
+	   0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a }},
+    { 0, {0} }
+};
+	
+#endif
+
+/* Main driver.
+
+Arguments (may be any combination):
+  -sstring - digests string
+  -t       - runs time trial
+  -x       - runs test script
+  filename - digests file
+  (none)   - digests standard input
+ */
+int main (argc, argv)
+int argc;
+char *argv[];
+{
+  int i;
+
+  if (argc > 1)
+ 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]);
+  else
+ MDFilter ();
+
+  return (0);
+}
+
+/* Digests a string and prints the result.
+ */
+static void MDString (string)
+char *string;
+{
+  MD_CTX context;
+  unsigned int len = strlen (string);
+
+  MDInit (&context);
+  MDUpdate (&context, (unsigned char *) string, len);
+  MDFinal (&context);
+
+  printf ("MD%d (\"%s\") = ", MD, string);
+  MDPrint (context.digest);
+  printf ("\n");
+}
+
+/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
+  blocks.
+ */
+static void MDTimeTrial ()
+{
+  MD_CTX context;
+  time_t endTime, startTime;
+  unsigned char block[TEST_BLOCK_LEN];
+  unsigned int i;
+  
+  printf("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
+  TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
+
+  /* Initialize block */
+  for (i = 0; i < TEST_BLOCK_LEN; i++)
+ block[i] = (unsigned char)(i & 0xff);
+
+  /* Start timer */
+  time (&startTime);
+
+  /* Digest blocks */
+  MDInit (&context);
+  for (i = 0; i < TEST_BLOCK_COUNT; i++)
+      MDUpdate (&context, block, TEST_BLOCK_LEN);
+  MDFinal (&context);
+
+  /* Stop timer */
+  time (&endTime);
+
+  printf (" done\n");
+  printf ("Digest = ");
+  MDPrint (context.digest);
+  printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
+  printf
+ ("Speed = %ld bytes/second\n",
+  (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));
+}
+
+/* Digests a reference suite of strings and prints the results.
+ */
+static void MDTestSuite ()
+{
+#ifdef HAVE_TEST_SUITE
+    MD_CTX context;
+    struct md_test_entry *entry;
+    int	i, num_tests = 0, num_failed = 0;
+    
+    printf ("MD%d test suite:\n\n", MD);
+    for (entry = md_test_suite; entry->string; entry++) {
+	unsigned int len = strlen (entry->string);
+
+	MDInit (&context);
+	MDUpdate (&context, (unsigned char *) entry->string, len);
+	MDFinal (&context);
+
+	printf ("MD%d (\"%s\") = ", MD, entry->string);
+	MDPrint (context.digest);
+	printf ("\n");
+	for (i=0; i < 16; i++) {
+	    if (context.digest[i] != entry->digest[i]) {
+		printf("\tIncorrect MD%d digest!  Should have been:\n\t\t ",
+		       MD);
+		MDPrint(entry->digest);
+		printf("\n");
+		num_failed++;
+	    }
+	}
+	num_tests++;
+    }
+    if (num_failed) {
+	printf("%d out of %d tests failed for MD%d!!!\n", num_failed,
+	       num_tests, MD);
+	exit(1);
+    } else {
+	printf ("%d tests passed successfully for MD%d.\n", num_tests, MD);
+	exit(0);
+    }
+#else
+  
+    printf ("MD%d test suite:\n", MD);
+    MDString ("");
+    MDString ("a");
+    MDString ("abc");
+    MDString ("message digest");
+    MDString ("abcdefghijklmnopqrstuvwxyz");
+    MDString
+	("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+    MDString
+	("12345678901234567890123456789012345678901234567890123456789012345678901234567890");
+#endif
+}
+
+/* Digests a file and prints the result. */
+
+static void MDFile (filename)
+    char *filename;
+{
+    FILE *file;
+    MD_CTX context;
+    int len;
+    unsigned char buffer[1024];
+
+    if ((file = fopen (filename, "rb")) == NULL)
+	printf ("%s can't be opened\n", filename);
+    else {
+	MDInit (&context);
+	while ((len = fread (buffer, 1, 1024, file)) != 0)
+	    MDUpdate (&context, buffer, len);
+	MDFinal (&context);
+
+	fclose (file);
+
+	printf ("MD%d (%s) = ", MD, filename);
+	MDPrint (context.digest);
+	printf ("\n");
+    }
+}
+
+/* Digests the standard input and prints the result.
+ */
+static void MDFilter ()
+{
+  MD_CTX context;
+  int len;
+  unsigned char buffer[16];
+
+  MDInit (&context);
+  while ((len = fread (buffer, 1, 16, stdin)) != 0)
+    MDUpdate (&context, buffer, len);
+  MDFinal (&context);
+
+  MDPrint (context.digest);
+  printf ("\n");
+}
+
+/* Prints a message digest in hexadecimal.
+ */
+static void MDPrint (digest)
+unsigned char digest[16];
+{
+  unsigned int i;
+
+  for (i = 0; i < 16; i++)
+ printf ("%02x", digest[i]);
+}
diff --git a/krb5-1-6/src/lib/crypto/nfold.c b/krb5-1-6/src/lib/crypto/nfold.c
new file mode 100644
index 000000000..1f1902d1c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/nfold.c
@@ -0,0 +1,130 @@
+/*
+ * 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"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+/*
+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(unsigned int inbits, const unsigned char *in, unsigned int outbits,
+	   unsigned char *out)
+{
+    int a,b,c,lcm;
+    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/krb5-1-6/src/lib/crypto/old/Makefile.in b/krb5-1-6/src/lib/crypto/old/Makefile.in
new file mode 100644
index 000000000..a39622292
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/old/Makefile.in
@@ -0,0 +1,68 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/old
+mydir=lib/crypto/old
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../des
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=old
+##DOS##OBJFILE=..\$(OUTPRE)old.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= old_decrypt.o old_encrypt.o des_stringtokey.o
+
+OBJS= $(OUTPRE)des_stringtokey.$(OBJEXT) $(OUTPRE)old_decrypt.$(OBJEXT) $(OUTPRE)old_encrypt.$(OBJEXT)
+
+SRCS= $(srcdir)/des_stringtokey.c $(srcdir)/old_decrypt.c \
+	$(srcdir)/old_encrypt.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+des_stringtokey.so des_stringtokey.po $(OUTPRE)des_stringtokey.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../des/des_int.h des_stringtokey.c old.h
+old_decrypt.so old_decrypt.po $(OUTPRE)old_decrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h old.h old_decrypt.c
+old_encrypt.so old_encrypt.po $(OUTPRE)old_encrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h old.h old_encrypt.c
diff --git a/krb5-1-6/src/lib/crypto/old/des_stringtokey.c b/krb5-1-6/src/lib/crypto/old/des_stringtokey.c
new file mode 100644
index 000000000..2bacb4ef9
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/old/des_stringtokey.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 "old.h"
+#include <des_int.h>
+
+/* XXX */
+extern krb5_error_code mit_des_string_to_key_int
+(krb5_keyblock * keyblock,
+		 const krb5_data * data,
+		 const krb5_data * salt);
+
+krb5_error_code
+krb5int_des_string_to_key(const struct krb5_enc_provider *enc,
+			  const krb5_data *string,
+			  const krb5_data *salt, const krb5_data *parm,
+			  krb5_keyblock *key)
+{
+    int type;
+    if (parm ) {
+	if (parm->length != 1)
+	    return KRB5_ERR_BAD_S2K_PARAMS;
+	type = parm->data[0];
+    }
+    else type = 0;
+    switch(type) {
+    case 0:
+    return(mit_des_string_to_key_int(key, string, salt));
+    case 1:
+	return mit_afs_string_to_key(key, string, salt);
+    default:
+	return KRB5_ERR_BAD_S2K_PARAMS;
+    }
+}
diff --git a/krb5-1-6/src/lib/crypto/old/old.h b/krb5-1-6/src/lib/crypto/old/old.h
new file mode 100644
index 000000000..94ee6421e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/old/old.h
@@ -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"
+
+void krb5_old_encrypt_length
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		size_t input, size_t *length);
+
+krb5_error_code krb5_old_encrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *output);
+
+krb5_error_code krb5_old_decrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *arg_output);
+
+krb5_error_code krb5int_des_string_to_key
+(const struct krb5_enc_provider *enc,
+		const krb5_data *string, const krb5_data *salt,
+		const krb5_data *params,
+		krb5_keyblock *key);
diff --git a/krb5-1-6/src/lib/crypto/old/old_decrypt.c b/krb5-1-6/src/lib/crypto/old/old_decrypt.c
new file mode 100644
index 000000000..cfbbd7272
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/old/old_decrypt.c
@@ -0,0 +1,143 @@
+/*
+ * 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 "old.h"
+
+krb5_error_code
+krb5_old_decrypt(const struct krb5_enc_provider *enc,
+		 const struct krb5_hash_provider *hash,
+		 const krb5_keyblock *key,
+		 krb5_keyusage usage,
+		 const krb5_data *ivec,
+		 const krb5_data *input,
+		 krb5_data *arg_output)
+{
+    krb5_error_code ret;
+    size_t blocksize, hashsize, plainsize;
+    unsigned char *cksumdata, *cn;
+    krb5_data output, cksum, crcivec;
+    int alloced;
+
+    blocksize = enc->block_size;
+    hashsize = hash->hashsize;
+
+    plainsize = input->length - blocksize - hashsize;
+
+    if (arg_output->length < plainsize)
+	return(KRB5_BAD_MSIZE);
+
+    /* if there's enough space to work in the app buffer, use it,
+       otherwise allocate our own */
+
+    if ((cksumdata = (unsigned char *) malloc(hashsize)) == NULL)
+	return(ENOMEM);
+
+    if (arg_output->length < input->length) {
+	output.length = input->length;
+
+	if ((output.data = (char *) malloc(output.length)) == NULL) {
+	    free(cksumdata);
+	    return(ENOMEM);
+	}
+
+	alloced = 1;
+    } else {
+	output.length = input->length;
+
+	output.data = arg_output->data;
+
+	alloced = 0;
+    }
+
+    /* decrypt it */
+
+    /* save last ciphertext block in case we decrypt in place */
+    if (ivec != NULL && ivec->length == blocksize) {
+	cn = malloc(blocksize);
+	if (cn == NULL) {
+	    ret = ENOMEM;
+	    goto cleanup;
+	}
+	memcpy(cn, input->data + input->length - blocksize, blocksize);
+    } else
+	cn = NULL;
+
+    /* XXX this is gross, but I don't have much choice */
+    if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) {
+	crcivec.length = key->length;
+	crcivec.data = (char *) key->contents;
+	ivec = &crcivec;
+    }
+
+    if ((ret = ((*(enc->decrypt))(key, ivec, input, &output))))
+	goto cleanup;
+
+    /* verify the checksum */
+
+    memcpy(cksumdata, output.data+blocksize, hashsize);
+    memset(output.data+blocksize, 0, hashsize);
+
+    cksum.length = hashsize;
+    cksum.data = output.data+blocksize;
+
+    if ((ret = ((*(hash->hash))(1, &output, &cksum))))
+	goto cleanup;
+
+    if (memcmp(cksum.data, cksumdata, cksum.length) != 0) {
+	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+	goto cleanup;
+    }
+
+    /* copy the plaintext around */
+
+    if (alloced) {
+	memcpy(arg_output->data, output.data+blocksize+hashsize,
+	       plainsize);
+    } else {
+	memmove(arg_output->data, arg_output->data+blocksize+hashsize,
+		plainsize);
+    }
+    arg_output->length = plainsize;
+
+    /* update ivec */
+    if (cn != NULL)
+	memcpy(ivec->data, cn, blocksize);
+
+    ret = 0;
+
+cleanup:
+    if (alloced) {
+	memset(output.data, 0, output.length);
+	free(output.data);
+    }
+
+    if (cn != NULL)
+	free(cn);
+    memset(cksumdata, 0, hashsize);
+    free(cksumdata);
+    return(ret);
+}
diff --git a/krb5-1-6/src/lib/crypto/old/old_encrypt.c b/krb5-1-6/src/lib/crypto/old/old_encrypt.c
new file mode 100644
index 000000000..98bd109e0
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/old/old_encrypt.c
@@ -0,0 +1,110 @@
+/*
+ * 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 "old.h"
+
+void
+krb5_old_encrypt_length(const struct krb5_enc_provider *enc,
+			const struct krb5_hash_provider *hash,
+			size_t inputlen,
+			size_t *length)
+{
+    size_t blocksize, hashsize;
+
+    blocksize = enc->block_size;
+    hashsize = hash->hashsize;
+
+    *length = krb5_roundup(blocksize+hashsize+inputlen, blocksize);
+}
+
+krb5_error_code
+krb5_old_encrypt(const struct krb5_enc_provider *enc,
+		 const struct krb5_hash_provider *hash,
+		 const krb5_keyblock *key,
+		 krb5_keyusage usage,
+		 const krb5_data *ivec,
+		 const krb5_data *input,
+		 krb5_data *output)
+{
+    krb5_error_code ret;
+    size_t blocksize, hashsize, enclen;
+    krb5_data datain, crcivec;
+    int real_ivec;
+
+    blocksize = enc->block_size;
+    hashsize = hash->hashsize;
+
+    krb5_old_encrypt_length(enc, hash, input->length, &enclen);
+
+    if (output->length < enclen)
+	return(KRB5_BAD_MSIZE);
+
+    output->length = enclen;
+
+    /* fill in confounded, padded, plaintext buffer with zero checksum */
+
+    memset(output->data, 0, output->length);
+
+    datain.length = blocksize;
+    datain.data = output->data;
+
+    if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &datain)))
+	return(ret);
+    memcpy(output->data+blocksize+hashsize, input->data, input->length);
+
+    /* compute the checksum */
+
+    datain.length = hashsize;
+    datain.data = output->data+blocksize;
+
+    if ((ret = ((*(hash->hash))(1, output, &datain))))
+	goto cleanup;
+
+    /* encrypt it */
+
+    /* XXX this is gross, but I don't have much choice */
+    if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) {
+	crcivec.length = key->length;
+	crcivec.data = (char *) key->contents;
+	ivec = &crcivec;
+	real_ivec = 0;
+    } else
+	real_ivec = 1;
+
+    if ((ret = ((*(enc->encrypt))(key, ivec, output, output))))
+	goto cleanup;
+
+    /* update ivec */
+    if (real_ivec && ivec != NULL && ivec->length == blocksize)
+	memcpy(ivec->data, output->data + output->length - blocksize,
+	       blocksize);
+cleanup:
+    if (ret)
+	memset(output->data, 0, output->length);
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/lib/crypto/old_api_glue.c b/krb5-1-6/src/lib/crypto/old_api_glue.c
new file mode 100644
index 000000000..fda16909a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/old_api_glue.c
@@ -0,0 +1,326 @@
+/*
+ * 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_CALLCONV
+krb5_encrypt(krb5_context context, krb5_const_pointer inptr,
+	     krb5_pointer outptr, size_t size, krb5_encrypt_block *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_CALLCONV
+krb5_decrypt(krb5_context context, krb5_const_pointer inptr,
+	     krb5_pointer outptr, size_t size, krb5_encrypt_block *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_CALLCONV
+krb5_process_key(krb5_context context, krb5_encrypt_block *eblock,
+		 const krb5_keyblock *key)
+{
+    eblock->key = (krb5_keyblock *) key;
+
+    return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock)
+{
+    return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock,
+		   krb5_keyblock *keyblock, const krb5_data *data,
+		   const krb5_data *salt)
+{
+    return(krb5_c_string_to_key(context, eblock->crypto_entry, data, salt,
+				keyblock));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+		     const krb5_keyblock *keyblock, krb5_pointer *ptr)
+{
+    krb5_data data;
+
+    data.length = keyblock->length;
+    data.data = (char *) keyblock->contents;
+
+    return(krb5_c_random_seed(context, &data));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+		       krb5_pointer *ptr)
+{
+    return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+		krb5_pointer ptr, krb5_keyblock **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_CALLCONV
+krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock)
+{
+    return(eblock->crypto_entry);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock,
+		 krb5_enctype enctype)
+{
+    eblock->crypto_entry = enctype;
+
+    return(0);
+}
+
+size_t KRB5_CALLCONV
+krb5_encrypt_size(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_CALLCONV
+krb5_checksum_size(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_CALLCONV
+krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype,
+			krb5_const_pointer in, size_t in_length,
+			krb5_const_pointer seed, size_t seed_length,
+			krb5_checksum *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_CALLCONV
+krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
+		     const krb5_checksum *cksum, krb5_const_pointer in,
+		     size_t in_length, krb5_const_pointer seed,
+		     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_CALLCONV
+krb5_random_confounder(size_t size, krb5_pointer ptr)
+{
+    krb5_data random_data;
+
+    random_data.length = size;
+    random_data.data = ptr;
+
+    return(krb5_c_random_make_octets(/* XXX */ 0, &random_data));
+}
+
+krb5_error_code krb5_encrypt_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(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 = (char *) 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/krb5-1-6/src/lib/crypto/pbkdf2.c b/krb5-1-6/src/lib/crypto/pbkdf2.c
new file mode 100644
index 000000000..ff446dbde
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/pbkdf2.c
@@ -0,0 +1,268 @@
+/*
+ * lib/crypto/pbkdf2.c
+ *
+ * Copyright 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Implementation of PBKDF2 from RFC 2898.
+ * Not currently used; likely to be used when we get around to AES support.
+ */
+
+#include <ctype.h>
+#include "k5-int.h"
+#include "hash_provider.h"
+
+/* Not exported, for now.  */
+static krb5_error_code
+krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *,
+				       krb5_data *),
+		size_t hlen, const krb5_data *pass, const krb5_data *salt,
+		unsigned long count, const krb5_data *output);
+
+static int debug_hmac = 0;
+
+static void printd (const char *descr, krb5_data *d) {
+    int i, j;
+    const int r = 16;
+
+    printf("%s:", descr);
+
+    for (i = 0; i < d->length; i += r) {
+	printf("\n  %04x: ", i);
+	for (j = i; j < i + r && j < d->length; j++)
+	    printf(" %02x", 0xff & d->data[j]);
+	for (; j < i + r; j++)
+	    printf("   ");
+	printf("   ");
+	for (j = i; j < i + r && j < d->length; j++) {
+	    int c = 0xff & d->data[j];
+	    printf("%c", isprint(c) ? c : '.');
+	}
+    }
+    printf("\n");
+}
+static void printk(const char *descr, krb5_keyblock *k) {
+    krb5_data d;
+    d.data = (char *) k->contents;
+    d.length = k->length;
+    printd(descr, &d);
+}
+
+static krb5_error_code
+F(char *output, char *u_tmp1, char *u_tmp2,
+  krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, krb5_data *),
+  size_t hlen,
+  const krb5_data *pass, const krb5_data *salt,
+  unsigned long count, int i)
+{
+    unsigned char ibytes[4];
+    size_t tlen;
+    int j, k;
+    krb5_keyblock pdata;
+    krb5_data sdata;
+    krb5_data out;
+    krb5_error_code err;
+
+    pdata.contents = pass->data;
+    pdata.length = pass->length;
+
+#if 0
+    printf("F(i=%d, count=%lu, pass=%d:%s)\n", i, count,
+	   pass->length, pass->data);
+    printk("F password", &pdata);
+#endif
+
+    /* Compute U_1.  */
+    ibytes[3] = i & 0xff;
+    ibytes[2] = (i >> 8) & 0xff;
+    ibytes[1] = (i >> 16) & 0xff;
+    ibytes[0] = (i >> 24) & 0xff;
+
+    tlen = salt->length;
+    memcpy(u_tmp2, salt->data, tlen);
+    memcpy(u_tmp2 + tlen, ibytes, 4);
+    tlen += 4;
+    sdata.data = u_tmp2;
+    sdata.length = tlen;
+
+#if 0
+    printd("initial salt", &sdata);
+#endif
+
+    out.data = u_tmp1;
+    out.length = hlen;
+
+#if 0
+    printf("F: computing hmac #1 (U_1) with %s\n", pdata.contents);
+#endif
+    err = (*prf)(&pdata, &sdata, &out);
+    if (err)
+	return err;
+#if 0
+    printd("F: prf return value", &out);
+#endif
+    memcpy(output, u_tmp1, hlen);
+
+    /* Compute U_2, .. U_c.  */
+    sdata.length = hlen;
+    for (j = 2; j <= count; j++) {
+#if 0
+	printf("F: computing hmac #%d (U_%d)\n", j, j);
+#endif
+	memcpy(u_tmp2, u_tmp1, hlen);
+	err = (*prf)(&pdata, &sdata, &out);
+	if (err)
+	    return err;
+#if 0
+	printd("F: prf return value", &out);
+#endif
+	/* And xor them together.  */
+	for (k = 0; k < hlen; k++)
+	    output[k] ^= u_tmp1[k];
+#if 0
+	printf("F: xor result:\n");
+	for (k = 0; k < hlen; k++)
+	    printf(" %02x", 0xff & output[k]);
+	printf("\n");
+#endif
+    }
+    return 0;
+}
+
+static krb5_error_code
+krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *,
+				       krb5_data *),
+		size_t hlen,
+		const krb5_data *pass, const krb5_data *salt,
+		unsigned long count, const krb5_data *output)
+{
+    int l, r, i;
+    char *utmp1, *utmp2;
+    char utmp3[20];		/* XXX length shouldn't be hardcoded! */
+
+    if (output->length == 0 || hlen == 0)
+	abort();
+    /* Step 1 & 2.  */
+    if (output->length / hlen > 0xffffffff)
+	abort();
+    /* Step 2.  */
+    l = (output->length + hlen - 1) / hlen;
+    r = output->length - (l - 1) * hlen;
+
+    utmp1 = /*output + dklen; */ malloc(hlen);
+    if (utmp1 == NULL)
+	return errno;
+    utmp2 = /*utmp1 + hlen; */ malloc(salt->length + 4 + hlen);
+    if (utmp2 == NULL) {
+	free(utmp1);
+	return errno;
+    }
+
+    /* Step 3.  */
+    for (i = 1; i <= l; i++) {
+#if 0
+	int j;
+#endif
+	krb5_error_code err;
+	char *out;
+
+	if (i == l)
+	    out = utmp3;
+	else
+	    out = output->data + (i-1) * hlen;
+	err = F(out, utmp1, utmp2, prf, hlen, pass, salt, count, i);
+	if (err) {
+	    free(utmp1);
+	    free(utmp2);
+	    return err;
+	}
+	if (i == l)
+	    memcpy(output->data + (i-1) * hlen, utmp3,
+		   output->length - (i-1) * hlen);
+
+#if 0
+	printf("after F(%d), @%p:\n", i, output->data);
+	for (j = (i-1) * hlen; j < i * hlen; j++)
+	    printf(" %02x", 0xff & output->data[j]);
+	printf ("\n");
+#endif
+    }
+    free(utmp1);
+    free(utmp2);
+    return 0;
+}
+
+static krb5_error_code hmac1(const struct krb5_hash_provider *h,
+			     krb5_keyblock *key, krb5_data *in, krb5_data *out)
+{
+    char tmp[40];
+    size_t blocksize, hashsize;
+    krb5_error_code err;
+    krb5_keyblock k;
+
+    k = *key;
+    key = &k;
+    if (debug_hmac)
+	printk(" test key", key);
+    blocksize = h->blocksize;
+    hashsize = h->hashsize;
+    if (hashsize > sizeof(tmp))
+	abort();
+    if (key->length > blocksize) {
+	krb5_data d, d2;
+	d.data = (char *) key->contents;
+	d.length = key->length;
+	d2.data = tmp;
+	d2.length = hashsize;
+	err = h->hash (1, &d, &d2);
+	if (err)
+	    return err;
+	key->length = d2.length;
+	key->contents = (krb5_octet *) d2.data;
+	if (debug_hmac)
+	    printk(" pre-hashed key", key);
+    }
+    if (debug_hmac)
+	printd(" hmac input", in);
+    err = krb5_hmac(h, key, 1, in, out);
+    if (err == 0 && debug_hmac)
+	printd(" hmac output", out);
+    return err;
+}
+
+static krb5_error_code
+foo(krb5_keyblock *pass, krb5_data *salt, krb5_data *out)
+{
+    krb5_error_code err;
+
+    memset(out->data, 0, out->length);
+    err = hmac1 (&krb5int_hash_sha1, pass, salt, out);
+    return err;
+}
+
+krb5_error_code
+krb5int_pbkdf2_hmac_sha1 (const krb5_data *out, unsigned long count,
+			  const krb5_data *pass, const krb5_data *salt)
+{
+    return krb5int_pbkdf2 (foo, 20, pass, salt, count, out);
+}
diff --git a/krb5-1-6/src/lib/crypto/prf.c b/krb5-1-6/src/lib/crypto/prf.c
new file mode 100644
index 000000000..f52564db4
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/prf.c
@@ -0,0 +1,87 @@
+/*
+ * lib/crypto/prf.c
+ *
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 
+ *
+ * This contains the implementation of krb5_c_prf, which  will find
+ *the enctype-specific PRF and then generate pseudo-random data.  This
+ *function yields krb5_c_prf_length bytes of output.
+ */
+
+
+#include "k5-int.h"
+#include "etypes.h"
+
+#include <assert.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_prf_length(krb5_context context, krb5_enctype enctype,
+		  size_t *len)
+{
+    int i;
+    assert (len);
+
+    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);
+
+    *len = krb5_enctypes_list[i].prf_length;
+    return 0;
+    
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_prf(krb5_context context, const krb5_keyblock *key,
+krb5_data *input, krb5_data *output)
+{
+    int i;
+    size_t len;
+    assert(input && output);
+    assert (output->data);
+
+
+    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_DATA;
+    if (!krb5_enctypes_list[i].prf)
+	return (KRB5_CRYPTO_INTERNAL);
+    krb5_c_prf_length (context, key->enctype, &len);
+    if( len != output->length)
+	return (KRB5_CRYPTO_INTERNAL);
+            return((*(krb5_enctypes_list[i].prf))
+	   (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash,
+	    key,  input, output));
+}
+
diff --git a/krb5-1-6/src/lib/crypto/prng.c b/krb5-1-6/src/lib/crypto/prng.c
new file mode 100644
index 000000000..32506d835
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/prng.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2001, 2002, 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#include "enc_provider.h"
+#include <assert.h>
+#include "k5-thread.h"
+
+#include "yarrow.h"
+static Yarrow_CTX y_ctx;
+static int init_error;
+#define yarrow_lock krb5int_yarrow_lock
+k5_mutex_t yarrow_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+/* Helper function to estimate entropy based on sample length
+ * and where it comes from.
+ */
+
+static size_t
+entropy_estimate (unsigned int randsource, size_t length)
+{
+  switch (randsource) {
+  case KRB5_C_RANDSOURCE_OLDAPI:
+    return (4*length);
+  case KRB5_C_RANDSOURCE_OSRAND:
+    return (8*length);
+  case KRB5_C_RANDSOURCE_TRUSTEDPARTY:
+    return (4*length);
+  case KRB5_C_RANDSOURCE_TIMING:return (2);
+  case KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL:
+    return (0);
+  default:
+    abort();
+  }
+return (0);
+}
+
+int krb5int_prng_init(void)
+{
+    unsigned i;
+    int yerr;
+
+    yerr = k5_mutex_finish_init(&yarrow_lock);
+    if (yerr)
+	return yerr;
+
+    yerr = krb5int_yarrow_init (&y_ctx, NULL);
+    if ((yerr != YARROW_OK) && (yerr != YARROW_NOT_SEEDED))
+	return KRB5_CRYPTO_INTERNAL;
+
+    for (i=0; i < KRB5_C_RANDSOURCE_MAX; i++ ) {
+	unsigned source_id;
+	if (krb5int_yarrow_new_source (&y_ctx, &source_id) != YARROW_OK )
+	    return KRB5_CRYPTO_INTERNAL;
+	assert (source_id == i);
+    }
+
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_add_entropy (krb5_context context, unsigned int randsource,
+			   const krb5_data *data)
+{
+  int yerr;
+
+  /* Make sure the mutex got initialized.  */
+  yerr = krb5int_crypto_init();
+  if (yerr)
+      return yerr;
+  /* Now, finally, feed in the data.  */
+  yerr = krb5int_yarrow_input (&y_ctx, randsource,
+			       data->data, data->length,
+			       entropy_estimate (randsource, data->length));
+  if (yerr != YARROW_OK)
+      return (KRB5_CRYPTO_INTERNAL);
+  return (0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_seed (krb5_context context, krb5_data *data)
+{
+    return krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_OLDAPI, data);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_make_octets(krb5_context context, krb5_data *data)
+{
+    int yerr;
+    yerr = krb5int_yarrow_output (&y_ctx, data->data, data->length);
+    if (yerr == YARROW_NOT_SEEDED) {
+      yerr = krb5int_yarrow_reseed (&y_ctx, YARROW_SLOW_POOL);
+      if (yerr == YARROW_OK)
+	yerr = krb5int_yarrow_output (&y_ctx, data->data, data->length);
+    }
+    if ( yerr != YARROW_OK)
+      return (KRB5_CRYPTO_INTERNAL);
+    return(0);
+}
+
+void krb5int_prng_cleanup (void)
+{
+    krb5int_yarrow_final (&y_ctx);
+    k5_mutex_destroy(&yarrow_lock);
+}
+
+
+/*
+ * Routines to get entropy from the OS.  For UNIX we try /dev/urandom
+ * and /dev/random.  Currently we don't do anything for Windows.
+ */
+#if defined(_WIN32)
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_os_entropy (krb5_context context, int strong, int *success)
+{
+  if (success)
+    *success  = 0;
+  return 0;
+}
+
+#else /*Windows*/
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+/*
+ * Helper function to read entropy from  a random device.  Takes the
+ * name of a device, opens it, makes sure it is a device and if so,
+ * reads entropy.  Returns  a boolean indicating whether entropy was
+ * read.
+ */
+
+static int
+read_entropy_from_device (krb5_context context, const char *device)
+{
+  krb5_data data;
+  struct stat sb;
+  int fd;
+  unsigned char buf[YARROW_SLOW_THRESH/8], *bp;
+  int left;
+  fd = open (device, O_RDONLY);
+  if (fd == -1)
+    return 0;
+  if (fstat (fd, &sb) == -1)
+    return 0;
+  if (S_ISREG(sb.st_mode)) {
+    close(fd);
+    return 0;
+  }
+
+  for (bp = &buf, left = sizeof (buf); left > 0;) {
+    ssize_t count;
+    count = read (fd, bp, (unsigned) left);
+    if (count <= 0) {
+      close(fd);
+      return 0;
+    }
+    left -= count;
+    bp += count;
+  }
+  close (fd);
+  data.length = sizeof (buf);
+  data.data = ( char * ) buf;
+  if ( krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_OSRAND, 
+				  &data) != 0) {
+    return 0;
+  }
+  return 1;
+}
+    
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_os_entropy (krb5_context context,
+			  int strong, int *success)
+{
+  int unused;
+  int *oursuccess = success?success:&unused;
+  *oursuccess = 0;
+  /* If we are getting strong data then try that first.  We are
+     guaranteed to cause a reseed of some kind if strong is true and
+     we have both /dev/random and /dev/urandom.  We want the strong
+     data included in the reseed so we get it first.*/
+  if (strong) {
+    if (read_entropy_from_device (context, "/dev/random"))
+      *oursuccess = 1;
+  }
+  if (read_entropy_from_device (context, "/dev/urandom"))
+    *oursuccess = 1;
+  return 0;
+}
+
+#endif /*Windows or pre-OSX Mac*/
diff --git a/krb5-1-6/src/lib/crypto/random_to_key.c b/krb5-1-6/src/lib/crypto/random_to_key.c
new file mode 100644
index 000000000..20f0abc0d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/random_to_key.c
@@ -0,0 +1,73 @@
+/*
+ * COPYRIGHT (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ * 
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ * 
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * Create a key given random data.  It is assumed that random_key has
+ * already been initialized and random_key->contents have been allocated
+ * with the correct length.
+ */
+#include "k5-int.h"
+#include "etypes.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_to_key(krb5_context context, krb5_enctype enctype,
+		     krb5_data *random_data, krb5_keyblock *random_key)
+{
+    int i;
+    krb5_error_code ret;
+    const struct krb5_enc_provider *enc;
+
+    if (random_data == NULL || random_key == NULL)
+	return(EINVAL);
+
+    if (random_key->contents == NULL)
+	return(EINVAL);
+
+    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;
+
+    if (random_key->length != enc->keylength)
+	return(KRB5_BAD_KEYSIZE);
+
+    ret = ((*(enc->make_key))(random_data, random_key));
+
+    if (ret) {
+	memset(random_key->contents, 0, random_key->length);
+    }
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/lib/crypto/raw/Makefile.in b/krb5-1-6/src/lib/crypto/raw/Makefile.in
new file mode 100644
index 000000000..e6d64adc8
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/raw/Makefile.in
@@ -0,0 +1,56 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/raw
+mydir=lib/crypto/raw
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=raw
+##DOS##OBJFILE=..\$(OUTPRE)raw.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= raw_decrypt.o raw_encrypt.o
+
+OBJS= $(OUTPRE)raw_decrypt.$(OBJEXT) $(OUTPRE)raw_encrypt.$(OBJEXT)
+
+SRCS= $(srcdir)/raw_decrypt.c $(srcdir)/raw_encrypt.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+raw_decrypt.so raw_decrypt.po $(OUTPRE)raw_decrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h raw.h raw_decrypt.c
+raw_encrypt.so raw_encrypt.po $(OUTPRE)raw_encrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h raw.h raw_encrypt.c
diff --git a/krb5-1-6/src/lib/crypto/raw/raw.h b/krb5-1-6/src/lib/crypto/raw/raw.h
new file mode 100644
index 000000000..d3f7dd835
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/raw/raw.h
@@ -0,0 +1,46 @@
+/*
+ * 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"
+
+void krb5_raw_encrypt_length
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		size_t input, size_t *length);
+
+krb5_error_code krb5_raw_encrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *output);
+
+krb5_error_code krb5_raw_decrypt
+(const struct krb5_enc_provider *enc,
+		const struct krb5_hash_provider *hash,
+		const krb5_keyblock *key, krb5_keyusage usage,
+		const krb5_data *ivec, const krb5_data *input,
+		krb5_data *arg_output);
diff --git a/krb5-1-6/src/lib/crypto/raw/raw_decrypt.c b/krb5-1-6/src/lib/crypto/raw/raw_decrypt.c
new file mode 100644
index 000000000..767da1f9f
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/raw/raw_decrypt.c
@@ -0,0 +1,38 @@
+/*
+ * 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 "raw.h"
+
+krb5_error_code
+krb5_raw_decrypt(const struct krb5_enc_provider *enc,
+		 const struct krb5_hash_provider *hash,
+		 const krb5_keyblock *key, krb5_keyusage usage,
+		 const krb5_data *ivec, const krb5_data *input,
+		 krb5_data *output)
+{
+    return((*(enc->decrypt))(key, ivec, input, output));
+}
diff --git a/krb5-1-6/src/lib/crypto/raw/raw_encrypt.c b/krb5-1-6/src/lib/crypto/raw/raw_encrypt.c
new file mode 100644
index 000000000..68b819c01
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/raw/raw_encrypt.c
@@ -0,0 +1,50 @@
+/*
+ * 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 "raw.h"
+
+void
+krb5_raw_encrypt_length(const struct krb5_enc_provider *enc,
+			const struct krb5_hash_provider *hash,
+			size_t inputlen, size_t *length)
+{
+    size_t blocksize;
+
+    blocksize = enc->block_size;
+
+    *length = krb5_roundup(inputlen, blocksize);
+}
+
+krb5_error_code
+krb5_raw_encrypt(const struct krb5_enc_provider *enc,
+		 const struct krb5_hash_provider *hash,
+		 const krb5_keyblock *key, krb5_keyusage usage,
+		 const krb5_data *ivec, const krb5_data *input,
+		 krb5_data *output)
+{
+    return((*(enc->encrypt))(key, ivec, input, output));
+}
diff --git a/krb5-1-6/src/lib/crypto/sha1/ISSUES b/krb5-1-6/src/lib/crypto/sha1/ISSUES
new file mode 100644
index 000000000..8b7e8a2a1
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/sha1/ISSUES
@@ -0,0 +1,7 @@
+Issues to be addressed for src/lib/crypto/sha1: -*- text -*-
+
+Assumes int (look for "count") is >= 32 bits.
+
+Changing the types of internal variables is easy, but shsUpdate takes
+an int parameter; changing that could change the ABI on some
+platforms.
diff --git a/krb5-1-6/src/lib/crypto/sha1/Makefile.in b/krb5-1-6/src/lib/crypto/sha1/Makefile.in
new file mode 100644
index 000000000..79bdcd6e5
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/sha1/Makefile.in
@@ -0,0 +1,67 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/sha1
+mydir=lib/crypto/sha1
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=sha1
+##DOS##OBJFILE=..\$(OUTPRE)sha1.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS= shs.o
+
+OBJS= $(OUTPRE)shs.$(OBJEXT) 
+
+SRCS= $(srcdir)/shs.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+t_shs: t_shs.o shs.o $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o t_shs t_shs.o shs.o $(SUPPORT_LIB)
+
+$(OUTPRE)t_shs.exe: $(OUTPRE)t_shs.obj $(OUTPRE)shs.obj
+	link -out:$@ $**
+
+check-unix:: t_shs t_shs3
+	$(RUN_SETUP) $(VALGRIND) $(C)t_shs -x
+	$(RUN_SETUP) $(VALGRIND) $(C)t_shs3
+
+check-windows:: $(OUTPRE)t_shs.exe $(OUTPRE)t_shs3.exe
+	$(OUTPRE)$(C)t_shs.exe -x
+	$(OUTPRE)$(C)t_shs3.exe
+
+clean:: 
+	$(RM) t_shs$(EXEEXT) t_shs.$(OBJEXT) t_shs3$(EXEEXT) t_shs3.$(OBJEXT)
+
+clean-unix:: clean-libobjs
+
+t_shs3: t_shs3.o shs.o $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o t_shs3 t_shs3.o shs.o $(SUPPORT_LIB)
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+shs.so shs.po $(OUTPRE)shs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  shs.c shs.h
diff --git a/krb5-1-6/src/lib/crypto/sha1/shs.c b/krb5-1-6/src/lib/crypto/sha1/shs.c
new file mode 100644
index 000000000..a027fd76d
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/sha1/shs.c
@@ -0,0 +1,386 @@
+#include "shs.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <string.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(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 (SHS_LONG *digest, const SHS_LONG *data);
+
+static
+void SHSTransform(SHS_LONG *digest, const SHS_LONG *data)
+{
+    SHS_LONG A, B, C, D, E;     /* Local vars */
+    SHS_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));
+
+#ifdef CONFIG_SMALL
+
+    {
+	int i;
+	SHS_LONG temp;
+	for (i = 0; i < 20; i++) {
+	    SHS_LONG x = (i < 16) ? eData[i] : expand(eData, i);
+	    subRound(A, B, C, D, E, f1, K1, x);
+	    temp = E, E = D, D = C, C = B, B = A, A = temp;
+	}
+	for (i = 20; i < 40; i++) {
+	    subRound(A, B, C, D, E, f2, K2, expand(eData, i));
+	    temp = E, E = D, D = C, C = B, B = A, A = temp;
+	}
+	for (i = 40; i < 60; i++) {
+	    subRound(A, B, C, D, E, f3, K3, expand(eData, i));
+	    temp = E, E = D, D = C, C = B, B = A, A = temp;
+	}
+	for (i = 60; i < 80; i++) {
+	    subRound(A, B, C, D, E, f4, K4, expand(eData, i));
+	    temp = E, E = D, D = C, C = B, B = A, A = temp;
+	}
+    }
+
+#else
+
+    /* 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 ) );
+
+#endif
+
+    /* 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;
+}
+
+/* Update SHS for a block of data */
+
+void shsUpdate(SHS_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count)
+{
+    SHS_LONG tmp;
+    int dataCount, canfill;
+    SHS_LONG *lp;
+
+    /* Update bitcount */
+    tmp = shsInfo->countLo;
+    shsInfo->countLo = tmp + (((SHS_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;
+	dataCount = SHS_DATASIZE - dataCount;
+	canfill = (count >= 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 |= (SHS_LONG) *buffer++ << ((--dataCount % 4) * 8);
+		count--;
+	    }
+	    lp++;
+	}
+	while (lp < shsInfo->data + 16) {
+	    if (count < 4) {
+		*lp = 0;
+		switch (count % 4) {
+		case 3:
+		    *lp |= (SHS_LONG) buffer[2] << 8;
+		case 2:
+		    *lp |= (SHS_LONG) buffer[1] << 16;
+		case 1:
+		    *lp |= (SHS_LONG) buffer[0] << 24;
+		}
+		count = 0;
+		break;		/* out of while loop */
+	    }
+	    *lp = (SHS_LONG) *buffer++ << 24;
+	    *lp |= (SHS_LONG) *buffer++ << 16;
+	    *lp |= (SHS_LONG) *buffer++ << 8;
+	    *lp++ |= (SHS_LONG) *buffer++;
+	    count -= 4;
+	}
+	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 = ((SHS_LONG) *buffer++) << 24;
+	    *lp |= ((SHS_LONG) *buffer++) << 16;
+	    *lp |= ((SHS_LONG) *buffer++) << 8;
+	    *lp++ |= (SHS_LONG) *buffer++;
+	}
+	SHSTransform(shsInfo->digest, shsInfo->data);
+	count -= SHS_DATASIZE;
+    }
+
+    if (count > 0) {
+	lp = shsInfo->data;
+	while (count > 4) {
+	    *lp = ((SHS_LONG) *buffer++) << 24;
+	    *lp |= ((SHS_LONG) *buffer++) << 16;
+	    *lp |= ((SHS_LONG) *buffer++) << 8;
+	    *lp++ |= (SHS_LONG) *buffer++;
+	    count -= 4;
+	}
+	*lp = 0;
+	switch (count % 4) {
+	case 0:
+	    *lp |= ((SHS_LONG) buffer[3]);
+	case 3:
+	    *lp |= ((SHS_LONG) buffer[2]) << 8;
+	case 2:
+	    *lp |= ((SHS_LONG) buffer[1]) << 16;
+	case 1:
+	    *lp |= ((SHS_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(SHS_INFO *shsInfo)
+{
+    int count;
+    SHS_LONG *lp;
+
+    /* 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++ |= (SHS_LONG) 0x80;
+	break;
+    case 2:
+	*lp++ |= (SHS_LONG) 0x80 << 8;
+	break;
+    case 1:
+	*lp++ |= (SHS_LONG) 0x80 << 16;
+	break;
+    case 0:
+	*lp++ = (SHS_LONG) 0x80 << 24;
+    }
+
+    /* at this point, lp can point *past* shsInfo->data.  If it points
+       there, just Transform and reset.  If it points to the last
+       element, set that to zero.  This pads out to 64 bytes if not
+       enough room for length words */
+
+    if (lp == shsInfo->data + 15)
+	*lp++ = 0;
+
+    if (lp == shsInfo->data + 16) {
+	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/krb5-1-6/src/lib/crypto/sha1/shs.h b/krb5-1-6/src/lib/crypto/sha1/shs.h
new file mode 100644
index 000000000..6dcb41b40
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/sha1/shs.h
@@ -0,0 +1,45 @@
+#ifndef _SHS_DEFINED
+
+#include "k5-int.h"
+
+#define _SHS_DEFINED
+
+/* Some useful types */
+
+typedef krb5_octet	SHS_BYTE;
+typedef krb5_ui_4	SHS_LONG;
+
+/* 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 {
+               SHS_LONG digest[ 5 ];            /* Message digest */
+               SHS_LONG countLo, countHi;       /* 64-bit bit count */
+               SHS_LONG data[ 16 ];             /* SHS data buffer */
+               } SHS_INFO;
+
+/* Message digest functions (shs.c) */
+void shsInit(SHS_INFO *shsInfo);
+void shsUpdate(SHS_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count);
+void shsFinal(SHS_INFO *shsInfo);
+
+
+/* Keyed Message digest functions (hmac_sha.c) */
+krb5_error_code hmac_sha(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
+
+#endif /* _SHS_DEFINED */
diff --git a/krb5-1-6/src/lib/crypto/sha1/t_shs.c b/krb5-1-6/src/lib/crypto/sha1/t_shs.c
new file mode 100644
index 000000000..adcb0927a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/sha1/t_shs.c
@@ -0,0 +1,135 @@
+/****************************************************************************
+*                                                                           *
+*                               SHS Test Code                               *
+*                                                                           *
+****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "shs.h"
+
+/* Test the SHS implementation */
+
+#ifdef NEW_SHS
+
+static SHS_LONG shsTestResults[][ 5 ] = {
+    { 0xA9993E36L, 0x4706816AL, 0xBA3E2571L, 0x7850C26CL, 0x9CD0D89DL, },
+    { 0x84983E44L, 0x1C3BD26EL, 0xBAAE4AA1L, 0xF95129E5L, 0xE54670F1L, },
+    { 0x34AA973CL, 0xD4C4DAA4L, 0xF61EEB2BL, 0xDBAD2731L, 0x6534016FL, }
+    };
+
+#else
+
+static SHS_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 ", (unsigned long) shsTestResults[shsTestLevel][i]);
+	}
+	printf("\nGot:      ");
+	for (i = 0; i < 5; i++) {
+	    printf("%8.8lx ", (unsigned long) shsInfo->digest[i]);
+	}
+	printf("\n");
+	return( -1 );
+    }
+    return( 0 );
+}
+
+int
+main()
+{
+    SHS_INFO shsInfo;
+    unsigned int i;
+#if 0
+    time_t secondCount;
+    SHS_BYTE data[ 200 ];
+#endif
+
+    /* 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, ( SHS_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, ( SHS_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, ( SHS_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/krb5-1-6/src/lib/crypto/sha1/t_shs3.c b/krb5-1-6/src/lib/crypto/sha1/t_shs3.c
new file mode 100644
index 000000000..96b36a76e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/sha1/t_shs3.c
@@ -0,0 +1,592 @@
+/* test shs code */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "shs.h"
+
+static void process(void);
+static void test1(void);
+static void test2(void);
+static void test3(void);
+static void test4(void);
+static void test5(void);
+static void test6(void);
+static void test7(void);
+
+/* 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 */
+
+static void longReverse( SHS_LONG *buffer, int byteCount )
+{
+    SHS_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( SHS_LONG );
+    while( byteCount-- ) {
+        value = *buffer;
+        value = ( ( value & 0xFF00FF00L ) >> 8  ) | 
+                ( ( value & 0x00FF00FFL ) << 8 );
+        *buffer++ = ( value << 16 ) | ( value >> 16 );
+    }
+}
+
+int rc;
+int mode;
+int Dflag;
+
+int
+main(argc,argv)
+	char **argv;
+{
+	char *argp;
+
+	while (--argc > 0) if (*(argp = *++argv)=='-')
+	while (*++argp) switch(*argp)
+	{
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+		if (mode) goto Usage;
+		mode = *argp;
+		break;
+	case 'D':
+		if (argc <= 1) goto Usage;
+		--argc;
+		Dflag = atoi(*++argv);
+		break;
+	case '-':
+		break;
+	default:
+		fprintf (stderr,"Bad switch char <%c>\n", *argp);
+	Usage:
+		fprintf(stderr, "Usage: t_shs [-1234567] [-D #]\n");
+		exit(1);
+	}
+	else goto Usage;
+
+	process();
+	exit(rc);
+}
+
+static void process(void)
+{
+	switch(mode)
+	{
+	case '1':
+		test1();
+		break;
+	case '2':
+		test2();
+		break;
+	case '3':
+		test3();
+		break;
+	case '4':
+		test4();
+		break;
+	case '5':
+		test5();
+		break;
+	case '6':
+		test6();
+		break;
+	case '7':
+		test7();
+		break;
+	default:
+		test1();
+		test2();
+		test3();
+		test4();
+		test5();
+		test6();
+		test7();
+	}
+}
+
+#ifndef shsDigest
+static unsigned char *
+shsDigest(si)
+	SHS_INFO *si;
+{
+	longReverse(si->digest, SHS_DIGESTSIZE);
+	return (unsigned char*) si->digest;
+}
+#endif
+
+unsigned char results1[SHS_DIGESTSIZE] = {
+0xa9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e,
+0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d};
+
+static void test1(void)
+{
+	SHS_INFO si[1];
+	unsigned char digest[SHS_DIGESTSIZE];
+	int failed;
+	int i;
+
+	printf("Running SHS test 1 ...\n");
+	shsInit(si);
+	shsUpdate(si, (SHS_BYTE *) "abc", 3);
+	shsFinal(si);
+	memcpy(digest, shsDigest(si), SHS_DIGESTSIZE);
+	if ((failed = memcmp(digest, results1, SHS_DIGESTSIZE)) != 0)
+	{
+		fprintf(stderr,"SHS test 1 failed!\n");
+		rc = 1;
+	}
+	printf ("%s, results = ", failed ? "Failed" : "Passed");
+	for (i = 0; i < SHS_DIGESTSIZE; ++i)
+		printf("%02x",digest[i]);
+	if (failed)
+	{
+		printf ("\n, expected ");
+		for (i = 0; i < SHS_DIGESTSIZE; ++i)
+			printf("%02x",results1[i]);
+	}
+	printf("\n");
+}
+
+unsigned char results2[SHS_DIGESTSIZE] = {
+0x84,0x98,0x3e,0x44,0x1c,0x3b,0xd2,0x6e,0xba,0xae,
+0x4a,0xa1,0xf9,0x51,0x29,0xe5,0xe5,0x46,0x70,0xf1};
+
+static void test2(void)
+{
+	SHS_INFO si[1];
+	unsigned char digest[SHS_DIGESTSIZE];
+	int failed;
+	int i;
+
+	printf("Running SHS test 2 ...\n");
+	shsInit(si);
+	shsUpdate(si,
+	(SHS_BYTE *) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+		56);
+	shsFinal(si);
+	memcpy(digest, shsDigest(si), SHS_DIGESTSIZE);
+	if ((failed = memcmp(digest, results2, SHS_DIGESTSIZE)) != 0)
+	{
+		fprintf(stderr,"SHS test 2 failed!\n");
+		rc = 1;
+	}
+	printf ("%s, results = ", failed ? "Failed" : "Passed");
+	for (i = 0; i < SHS_DIGESTSIZE; ++i)
+		printf("%02x",digest[i]);
+	if (failed)
+	{
+		printf ("\n, expected ");
+		for (i = 0; i < SHS_DIGESTSIZE; ++i)
+			printf("%02x",results2[i]);
+	}
+	printf("\n");
+}
+
+unsigned char results3[SHS_DIGESTSIZE] = {
+0x34,0xaa,0x97,0x3c,0xd4,0xc4,0xda,0xa4,0xf6,0x1e,
+0xeb,0x2b,0xdb,0xad,0x27,0x31,0x65,0x34,0x01,0x6f};
+
+static void test3(void)
+{
+	SHS_INFO si[1];
+	unsigned char digest[SHS_DIGESTSIZE];
+	int failed;
+	int i;
+
+	printf("Running SHS test 3 ...\n");
+	shsInit(si);
+	for (i = 0; i < 15625; ++i)
+		shsUpdate(si,
+(SHS_BYTE *) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+			64);
+	shsFinal(si);
+	memcpy(digest, shsDigest(si), SHS_DIGESTSIZE);
+	if ((failed = memcmp(digest, results3, SHS_DIGESTSIZE)) != 0)
+	{
+		fprintf(stderr,"SHS test 3 failed!\n");
+		rc = 1;
+	}
+	printf ("%s, results = ", failed ? "Failed" : "Passed");
+	for (i = 0; i < SHS_DIGESTSIZE; ++i)
+		printf("%02x",digest[i]);
+	if (failed)
+	{
+		printf ("\n, expected ");
+		for (i = 0; i < SHS_DIGESTSIZE; ++i)
+			printf("%02x",results3[i]);
+	}
+	printf("\n");
+}
+
+unsigned char randdata[] = {
+0xfe,0x28,0x79,0x25,0xf5,0x03,0xf9,0x1c,0xcd,0x70,0x7b,0xb0,0x42,0x02,0xb8,0x2f,
+0xf3,0x63,0xa2,0x79,0x8e,0x9b,0x33,0xd7,0x2b,0xc4,0xb4,0xd2,0xcb,0x61,0xec,0xbb,
+0x94,0xe1,0x8f,0x53,0x80,0x55,0xd9,0x90,0xb2,0x03,0x58,0xfa,0xa6,0xe5,0x18,0x57,
+0x68,0x04,0x24,0x98,0x41,0x7e,0x84,0xeb,0xc1,0x39,0xbc,0x1d,0xf7,0x4e,0x92,0x72,
+0x1a,0x5b,0xb6,0x99,0x43,0xa5,0x0a,0x45,0x73,0x55,0xfd,0x57,0x83,0x45,0x36,0x5c,
+0xfd,0x39,0x08,0x6e,0xe2,0x01,0x9a,0x8c,0x4e,0x39,0xd2,0x0d,0x5f,0x0e,0x35,0x15,
+0xb9,0xac,0x5f,0xa1,0x8a,0xe6,0xdd,0x6e,0x68,0x9d,0xf6,0x29,0x95,0xf6,0x7d,0x7b,
+0xd9,0x5e,0xf4,0x67,0x25,0xbd,0xee,0xed,0x53,0x60,0xb0,0x47,0xdf,0xef,0xf4,0x41,
+0xbd,0x45,0xcf,0x5c,0x93,0x41,0x87,0x97,0x82,0x39,0x20,0x66,0xb4,0xda,0xcb,0x66,
+0x93,0x02,0x2e,0x7f,0x94,0x4c,0xc7,0x3b,0x2c,0xcf,0xf6,0x99,0x6f,0x13,0xf1,0xc5,
+0x28,0x2b,0xa6,0x6c,0x39,0x26,0x7f,0x76,0x24,0x4a,0x6e,0x01,0x40,0x63,0xf8,0x00,
+0x06,0x23,0x5a,0xaa,0xa6,0x2f,0xd1,0x37,0xc7,0xcc,0x76,0xe9,0x54,0x1e,0x57,0x73,
+0xf5,0x33,0xaa,0x96,0xbe,0x35,0xcd,0x1d,0xd5,0x7d,0xac,0x50,0xd5,0xf8,0x47,0x2d,
+0xd6,0x93,0x5f,0x6e,0x38,0xd3,0xac,0xd0,0x7e,0xad,0x9e,0xf8,0x87,0x95,0x63,0x15,
+0x65,0xa3,0xd4,0xb3,0x9a,0x6c,0xac,0xcd,0x2a,0x54,0x83,0x13,0xc4,0xb4,0x94,0xfa,
+0x76,0x87,0xc5,0x8b,0x4a,0x10,0x92,0x05,0xd1,0x0e,0x97,0xfd,0xc8,0xfb,0xc5,0xdc,
+0x21,0x4c,0xc8,0x77,0x5c,0xed,0x32,0x22,0x77,0xc1,0x38,0x30,0xd7,0x8e,0x2a,0x70,
+0x72,0x67,0x13,0xe4,0xb7,0x18,0xd4,0x76,0xdd,0x32,0x12,0xf4,0x5d,0xc9,0xec,0xc1,
+0x2c,0x8a,0xfe,0x08,0x6c,0xea,0xf6,0xab,0x5a,0x0e,0x8e,0x81,0x1d,0xc8,0x5a,0x4b,
+0xed,0xb9,0x7f,0x4b,0x67,0xe3,0x65,0x46,0xc9,0xf2,0xab,0x37,0x0a,0x98,0x67,0x5b,
+0xb1,0x3b,0x02,0x91,0x38,0x71,0xea,0x62,0x88,0xae,0xb6,0xdb,0xfc,0x55,0x79,0x33,
+0x69,0x95,0x51,0xb6,0xe1,0x3b,0xab,0x22,0x68,0x54,0xf9,0x89,0x9c,0x94,0xe0,0xe3,
+0xd3,0x48,0x5c,0xe9,0x78,0x5b,0xb3,0x4b,0xba,0xd8,0x48,0xd8,0xaf,0x91,0x4e,0x23,
+0x38,0x23,0x23,0x6c,0xdf,0x2e,0xf0,0xff,0xac,0x1d,0x2d,0x27,0x10,0x45,0xa3,0x2d,
+0x8b,0x00,0xcd,0xe2,0xfc,0xb7,0xdb,0x52,0x13,0xb7,0x66,0x79,0xd9,0xd8,0x29,0x0e,
+0x32,0xbd,0x52,0x6b,0x75,0x71,0x08,0x83,0x1b,0x67,0x28,0x93,0x97,0x97,0x32,0xff,
+0x8b,0xd3,0x98,0xa3,0xce,0x2b,0x88,0x37,0x1c,0xcc,0xa0,0xd1,0x19,0x9b,0xe6,0x11,
+0xfc,0xc0,0x3c,0x4e,0xe1,0x35,0x49,0x29,0x19,0xcf,0x1d,0xe1,0x60,0x74,0xc0,0xe9,
+0xf7,0xb4,0x99,0xa0,0x23,0x50,0x51,0x78,0xcf,0xc0,0xe5,0xc2,0x1c,0x16,0xd2,0x24,
+0x5a,0x63,0x54,0x83,0xaa,0x74,0x3d,0x41,0x0d,0x52,0xee,0xfe,0x0f,0x4d,0x13,0xe1,
+0x27,0x00,0xc4,0xf3,0x2b,0x55,0xe0,0x9c,0x81,0xe0,0xfc,0xc2,0x13,0xd4,0x39,0x09
+};
+
+unsigned char results4[SHS_DIGESTSIZE] = {
+0x13,0x62,0xfc,0x87,0x68,0x33,0xd5,0x1d,0x2f,0x0c,
+0x73,0xe3,0xfb,0x87,0x6a,0x6b,0xc3,0x25,0x54,0xfc};
+
+static void test4(void)
+{
+	SHS_INFO si[1];
+	unsigned char digest[SHS_DIGESTSIZE];
+	int failed;
+	int i;
+
+	printf("Running SHS test 4 ...\n");
+	shsInit(si);
+	shsUpdate(si, randdata, 19);
+	shsFinal(si);
+	memcpy(digest, shsDigest(si), SHS_DIGESTSIZE);
+	if ((failed = memcmp(digest, results4, SHS_DIGESTSIZE)) != 0)
+	{
+		fprintf(stderr,"SHS test 4 failed!\n");
+		rc = 1;
+	}
+	printf ("%s, results = ", failed ? "Failed" : "Passed");
+	for (i = 0; i < SHS_DIGESTSIZE; ++i)
+		printf("%02x",digest[i]);
+	if (failed)
+	{
+		printf ("\n, expected ");
+		for (i = 0; i < SHS_DIGESTSIZE; ++i)
+			printf("%02x",results4[i]);
+	}
+	printf("\n");
+}
+
+unsigned char results5[SHS_DIGESTSIZE] = {
+0x19,0x4d,0xf6,0xeb,0x8e,0x02,0x6d,0x37,0x58,0x64,
+0xe5,0x95,0x19,0x2a,0xdd,0x1c,0xc4,0x3c,0x24,0x86};
+
+static void test5(void)
+{
+	SHS_INFO si[1];
+	unsigned char digest[SHS_DIGESTSIZE];
+	int failed;
+	int i;
+
+	printf("Running SHS test 5 ...\n");
+	shsInit(si);
+	shsUpdate(si, randdata, 19);
+	shsUpdate(si, randdata+32, 15);
+	shsFinal(si);
+	memcpy(digest, shsDigest(si), SHS_DIGESTSIZE);
+	if ((failed = memcmp(digest, results5, SHS_DIGESTSIZE)) != 0)
+	{
+		fprintf(stderr,"SHS test 5 failed!\n");
+		rc = 1;
+	}
+	printf ("%s, results = ", failed ? "Failed" : "Passed");
+	for (i = 0; i < SHS_DIGESTSIZE; ++i)
+		printf("%02x",digest[i]);
+	if (failed)
+	{
+		printf ("\n, expected ");
+		for (i = 0; i < SHS_DIGESTSIZE; ++i)
+			printf("%02x",results5[i]);
+	}
+	printf("\n");
+}
+
+unsigned char results6[SHS_DIGESTSIZE] = {
+0x4e,0x16,0x57,0x9d,0x4b,0x48,0xa9,0x1c,0x88,0x72,
+0x83,0xdb,0x88,0xd1,0xea,0x3a,0x45,0xdf,0xa1,0x10};
+
+static void test6(void)
+{
+	struct {
+		long pad1;
+		SHS_INFO si1;
+		long pad2;
+		SHS_INFO si2;
+		long pad3;
+	} sdata;
+	unsigned char digest[SHS_DIGESTSIZE];
+	int failed;
+	unsigned int i, j;
+
+	printf("Running SHS test 6 ...\n");
+	sdata.pad1 = 0x12345678;
+	sdata.pad2 = 0x87654321;
+	sdata.pad3 = 0x78563412;
+	shsInit((&sdata.si2));
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #20 %#lx\n",
+sdata.pad2);
+sdata.pad2 = 0x87654321;
+}
+if (sdata.pad3 != 0x78563412) {
+printf ("Overrun #21 %#lx\n",
+sdata.pad3);
+sdata.pad3 = 0x78563412;
+}
+	for (i = 0; i < 400; ++i)
+	{
+		shsInit(&sdata.si1);
+if (sdata.pad1 != 0x12345678) {
+printf ("Overrun #22 %#lx at %d\n",
+sdata.pad1, i);
+sdata.pad1 = 0x12345678;
+}
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #23 %#lx at %d\n",
+sdata.pad2, i);
+sdata.pad2 = 0x87654321;
+}
+		shsUpdate(&sdata.si1, (randdata+sizeof(randdata))-i, i);
+if (sdata.pad1 != 0x12345678) {
+printf ("Overrun #24 %#lx at %d\n",
+sdata.pad1, i);
+sdata.pad1 = 0x12345678;
+}
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #25 %#lx at %d\n",
+sdata.pad2, i);
+sdata.pad2 = 0x87654321;
+}
+		shsFinal(&sdata.si1);
+if (sdata.pad1 != 0x12345678) {
+printf ("Overrun #26 %#lx at %d\n",
+sdata.pad1, i);
+sdata.pad1 = 0x12345678;
+}
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #27 %#lx at %d\n",
+sdata.pad2, i);
+sdata.pad2 = 0x87654321;
+}
+		memcpy(digest, shsDigest(&sdata.si1), SHS_DIGESTSIZE);
+		if (Dflag & 1)
+		{
+			printf ("%d: ", i);
+			for (j = 0; j < SHS_DIGESTSIZE; ++j)
+				printf("%02x",digest[j]);
+			printf("\n");
+		}
+		shsUpdate((&sdata.si2), digest, SHS_DIGESTSIZE);
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #28 %#lx at %d\n",
+sdata.pad2, i);
+sdata.pad2 = 0x87654321;
+}
+if (sdata.pad3 != 0x78563412) {
+printf ("Overrun #29 %#lx at %d\n",
+sdata.pad3, i);
+sdata.pad3 = 0x78563412;
+}
+		if (Dflag & 2)
+			printf ("%d: %08lx%08lx%08lx%08lx%08lx\n",
+				i,
+				(unsigned long) sdata.si2.digest[0],
+				(unsigned long) sdata.si2.digest[1],
+				(unsigned long) sdata.si2.digest[2],
+				(unsigned long) sdata.si2.digest[3],
+				(unsigned long) sdata.si2.digest[4]);
+	}
+	shsFinal((&sdata.si2));
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #30 %#lx\n",
+sdata.pad2);
+sdata.pad2 = 0x87654321;
+}
+if (sdata.pad3 != 0x78563412) {
+printf ("Overrun #31 %#lx\n",
+sdata.pad3);
+sdata.pad3 = 0x78563412;
+}
+	memcpy(digest, shsDigest((&sdata.si2)), SHS_DIGESTSIZE);
+	if ((failed = memcmp(digest, results6, SHS_DIGESTSIZE)) != 0)
+	{
+		fprintf(stderr,"SHS test 6 failed!\n");
+		rc = 1;
+	}
+	printf ("%s, results = ", failed ? "Failed" : "Passed");
+	for (i = 0; i < SHS_DIGESTSIZE; ++i)
+		printf("%02x",digest[i]);
+	if (failed)
+	{
+		printf ("\n, expected ");
+		for (i = 0; i < SHS_DIGESTSIZE; ++i)
+			printf("%02x",results6[i]);
+	}
+	printf("\n");
+}
+
+unsigned char results7[SHS_DIGESTSIZE] = {
+0x89,0x41,0x65,0xce,0x76,0xc1,0xd1,0xd1,0xc3,0x6f,
+0xab,0x92,0x79,0x30,0x01,0x71,0x63,0x1f,0x74,0xfe};
+
+unsigned int jfsize[] = {0,1,31,32,
+	33,55,56,63,
+	64,65,71,72,
+	73,95,96,97,
+	119,120,123,127};
+unsigned int kfsize[] = {0,1,31,32,33,55,56,63};
+
+static void test7(void)
+{
+	struct {
+		long pad1;
+		SHS_INFO si1;
+		long pad2;
+		SHS_INFO si2;
+		long pad3;
+	} sdata;
+	unsigned char digest[SHS_DIGESTSIZE];
+	int failed;
+	unsigned int i, j, k, l;
+
+	printf("Running SHS test 7 ...\n");
+	sdata.pad1 = 0x12345678;
+	sdata.pad2 = 0x87654321;
+	sdata.pad3 = 0x78563412;
+	shsInit((&sdata.si2));
+	for (i = 1; i <= 128; ++i)
+	for (j = 0; j < 20; ++j)
+	for (k = 0; k < 8; ++k)
+	{
+		shsInit(&sdata.si1);
+		shsUpdate(&sdata.si1, (randdata+80+j), i);
+if (sdata.pad1 != 0x12345678) {
+printf ("Overrun #1 %#lx at %d,%d,%d\n",
+sdata.pad1, i,j,k);
+sdata.pad1 = 0x12345678;
+}
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #2 %#lx at %d,%d,%d\n",
+sdata.pad2, i,j,k);
+sdata.pad2 = 0x87654321;
+}
+		shsUpdate(&sdata.si1, randdata+i, jfsize[j]);
+if (sdata.pad1 != 0x12345678) {
+printf ("Overrun #3 %#lx at %d,%d,%d\n",
+sdata.pad1, i,j,k);
+sdata.pad1 = 0x12345678;
+}
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #4 %#lx at %d,%d,%d\n",
+sdata.pad2, i,j,k);
+sdata.pad2 = 0x87654321;
+}
+		if (k) shsUpdate(&sdata.si1, randdata+(i^j), kfsize[k]);
+if (sdata.pad1 != 0x12345678) {
+printf ("Overrun #5 %#lx at %d,%d,%d\n",
+sdata.pad1, i,j,k);
+sdata.pad1 = 0x12345678;
+}
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #6 %#lx at %d,%d,%d\n",
+sdata.pad2, i,j,k);
+sdata.pad2 = 0x87654321;
+}
+		shsFinal(&sdata.si1);
+if (sdata.pad1 != 0x12345678) {
+printf ("Overrun #7 %#lx at %d,%d,%d\n",
+sdata.pad1, i,j,k);
+sdata.pad1 = 0x12345678;
+}
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #8 %#lx at %d,%d,%d\n",
+sdata.pad2, i,j,k);
+sdata.pad2 = 0x87654321;
+}
+		memcpy(digest, shsDigest(&sdata.si1), SHS_DIGESTSIZE);
+		if (Dflag & 1)
+		{
+			printf ("%d,%d,%d: ", i, j, k);
+			for (l = 0; l < SHS_DIGESTSIZE; ++l)
+				printf("%02x",digest[l]);
+			printf("\n");
+		}
+		shsUpdate((&sdata.si2), digest, SHS_DIGESTSIZE);
+if (sdata.pad2 != 0x87654321) {
+printf ("Overrun #9 %#lx at %d,%d,%d\n",
+sdata.pad2, i,j,k);
+sdata.pad2 = 0x87654321;
+}
+if (sdata.pad3 != 0x78563412) {
+printf ("Overrun #10 %#lx at %d,%d,%d\n",
+sdata.pad3, i,j,k);
+sdata.pad3 = 0x78563412;
+}
+		if (Dflag & 2)
+			printf ("%d,%d,%d: %08lx%08lx%08lx%08lx%08lx\n",
+				i,j,k,
+				(unsigned long) sdata.si2.digest[0],
+				(unsigned long) sdata.si2.digest[1],
+				(unsigned long) sdata.si2.digest[2],
+				(unsigned long) sdata.si2.digest[3],
+				(unsigned long) sdata.si2.digest[4]);
+	}
+	shsFinal((&sdata.si2));
+	memcpy(digest, shsDigest((&sdata.si2)), SHS_DIGESTSIZE);
+	if ((failed = memcmp(digest, results7, SHS_DIGESTSIZE)) != 0)
+	{
+		fprintf(stderr,"SHS test 7 failed!\n");
+		rc = 1;
+	}
+	printf ("%s, results = ", failed ? "Failed" : "Passed");
+	for (i = 0; i < SHS_DIGESTSIZE; ++i)
+		printf("%02x",digest[i]);
+	if (failed)
+	{
+		printf ("\n, expected ");
+		for (i = 0; i < SHS_DIGESTSIZE; ++i)
+			printf("%02x",results7[i]);
+	}
+	printf("\n");
+}
diff --git a/krb5-1-6/src/lib/crypto/state.c b/krb5-1-6/src/lib/crypto/state.c
new file mode 100644
index 000000000..f69746c81
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/state.c
@@ -0,0 +1,72 @@
+/*
+ * lib/crypto/state.c
+ *
+ * Copyright (C) 2001 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+
+ * 
+ * 
+ *
+ *  * Section 6 (Encryption) of the Kerberos revisions document defines
+ * cipher states to be used to chain encryptions and decryptions
+ * together.  Examples of cipher states include initialization vectors
+ * for CBC encription.    This file contains implementations of
+ * krb5_c_init_state and krb5_c_free_state used by clients of the
+ * Kerberos crypto library.
+ */
+#include "k5-int.h"
+#include "etypes.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_init_state (krb5_context context, const krb5_keyblock *key,
+		   krb5_keyusage keyusage, krb5_data *new_state)
+{
+      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);
+
+    return (*(krb5_enctypes_list[i].enc->init_state))
+      (key, keyusage, new_state);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_free_state (krb5_context context, const krb5_keyblock *key,
+		   krb5_data *state)
+{
+      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);
+
+    return     (*(krb5_enctypes_list[i].enc->free_state))
+      (state);
+}
diff --git a/krb5-1-6/src/lib/crypto/string_to_cksumtype.c b/krb5-1-6/src/lib/crypto/string_to_cksumtype.c
new file mode 100644
index 000000000..710f26160
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/string_to_cksumtype.c
@@ -0,0 +1,43 @@
+/*
+ * 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_CALLCONV
+krb5_string_to_cksumtype(char *string, krb5_cksumtype *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/krb5-1-6/src/lib/crypto/string_to_enctype.c b/krb5-1-6/src/lib/crypto/string_to_enctype.c
new file mode 100644
index 000000000..9d3245bf0
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/string_to_enctype.c
@@ -0,0 +1,43 @@
+/*
+ * 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_CALLCONV
+krb5_string_to_enctype(char *string, krb5_enctype *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/krb5-1-6/src/lib/crypto/string_to_key.c b/krb5-1-6/src/lib/crypto/string_to_key.c
new file mode 100644
index 000000000..03165ab25
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/string_to_key.c
@@ -0,0 +1,99 @@
+/*
+ * 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_CALLCONV
+krb5_c_string_to_key_with_params(krb5_context context,
+				 krb5_enctype enctype,
+				 const krb5_data *string,
+				 const krb5_data *salt,
+				 const krb5_data *params,
+				 krb5_keyblock *key);
+
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key(krb5_context context, krb5_enctype enctype,
+		     const krb5_data *string, const krb5_data *salt,
+		     krb5_keyblock *key)
+{
+    return krb5_c_string_to_key_with_params(context, enctype, string, salt,
+					    NULL, key);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype,
+				 const krb5_data *string,
+				 const krb5_data *salt,
+				 const krb5_data *params, krb5_keyblock *key)
+{
+    int i;
+    krb5_error_code ret;
+    const 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;
+/* xxx AFS string2key function is indicated by a special length  in
+ * the salt in much of the code.  However only the DES enctypes can
+ * deal with this.  Using s2kparams would be a much better solution.*/
+    if (salt && salt->length == SALT_TYPE_AFS_LENGTH) {
+	switch (enctype) {
+	case ENCTYPE_DES_CBC_CRC:
+	case ENCTYPE_DES_CBC_MD4:
+	case ENCTYPE_DES_CBC_MD5:
+	    break;
+	default:
+	    return (KRB5_CRYPTO_INTERNAL);
+	}
+    }
+
+    keybytes = enc->keybytes;
+    keylength = enc->keylength;
+
+    if ((key->contents = (krb5_octet *) malloc(keylength)) == NULL)
+	return(ENOMEM);
+
+    key->magic = KV5M_KEYBLOCK;
+    key->enctype = enctype;
+    key->length = keylength;
+
+    ret = (*krb5_enctypes_list[i].str2key)(enc, string, salt, params, key);
+    if (ret) {
+	memset(key->contents, 0, keylength);
+	free(key->contents);
+    }
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/lib/crypto/t_cts.c b/krb5-1-6/src/lib/crypto/t_cts.c
new file mode 100644
index 000000000..5066a26df
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_cts.c
@@ -0,0 +1,177 @@
+/*
+ * lib/crypto/vectors.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Test vectors for crypto code, matching data submitted for inclusion
+ * with RFC1510bis.
+ *
+ * N.B.: Doesn't compile -- this file uses some routines internal to our
+ * crypto library which are declared "static" and thus aren't accessible
+ * without modifying the other sources.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "hash_provider.h"
+
+#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
+
+const char *whoami;
+
+static void printhex (size_t len, const char *p)
+{
+    while (len--)
+	printf ("%02x", 0xff & *p++);
+}
+
+static void printstringhex (const char *p) { printhex (strlen (p), p); }
+
+static void printdata (krb5_data *d) { printhex (d->length, d->data); }
+
+static void printkey (krb5_keyblock *k) { printhex (k->length, k->contents); }
+
+
+#define JURISIC "Juri\305\241i\304\207" /* hi Miro */
+#define ESZETT "\303\237"
+#define GCLEF  "\360\235\204\236" /* outside BMP, woo hoo!  */
+
+static void
+keyToData (krb5_keyblock *k, krb5_data *d)
+{
+    d->length = k->length;
+    d->data = k->contents;
+}
+
+void check_error (int r, int line) {
+    if (r != 0) {
+	fprintf (stderr, "%s:%d: %s\n", __FILE__, line,
+		 error_message (r));
+	exit (1);
+    }
+}
+#define CHECK check_error(r, __LINE__)
+
+extern struct krb5_enc_provider krb5int_enc_des3;
+struct krb5_enc_provider *enc = &krb5int_enc_des3;
+extern struct krb5_enc_provider krb5int_enc_aes128, krb5int_enc_aes256;
+
+static void printd (const char *descr, krb5_data *d) {
+    int i, j;
+    const int r = 16;
+
+    printf("%s:", descr);
+
+    for (i = 0; i < d->length; i += r) {
+	printf("\n  %04x: ", i);
+	for (j = i; j < i + r && j < d->length; j++)
+	    printf(" %02x", 0xff & d->data[j]);
+#ifdef SHOW_TEXT
+	for (; j < i + r; j++)
+	    printf("   ");
+	printf("   ");
+	for (j = i; j < i + r && j < d->length; j++) {
+	    int c = 0xff & d->data[j];
+	    printf("%c", isprint(c) ? c : '.');
+	}
+#endif
+    }
+    printf("\n");
+}
+static void printk(const char *descr, krb5_keyblock *k) {
+    krb5_data d;
+    d.data = k->contents;
+    d.length = k->length;
+    printd(descr, &d);
+}
+
+static void test_cts()
+{
+    static const char input[4*16] =
+	"I would like the General Gau's Chicken, please, and wonton soup.";
+    static const unsigned char aeskey[16] = "chicken teriyaki";
+    static const int lengths[] = { 17, 31, 32, 47, 48, 64 };
+    extern krb5_error_code krb5int_aes_encrypt(const krb5_keyblock *,
+					       const krb5_data *,
+					       const krb5_data *,
+					       krb5_data *);
+
+    int i;
+    char outbuf[64], encivbuf[16], decivbuf[16], outbuf2[64];
+    krb5_data in, out, enciv, deciv, out2;
+    krb5_keyblock key;
+    krb5_error_code err;
+
+    in.data = input;
+    out.data = outbuf;
+    out2.data = outbuf2;
+    enciv.length = deciv.length = 16;
+    enciv.data = encivbuf;
+    deciv.data = decivbuf;
+    key.contents = aeskey;
+    key.length = 16;
+
+    memset(enciv.data, 0, 16);
+    printk("AES 128-bit key", &key);
+    for (i = 0; i < sizeof(lengths)/sizeof(lengths[0]); i++) {
+    memset(enciv.data, 0, 16);
+    memset(deciv.data, 0, 16);
+
+	printf("\n");
+	in.length = out.length = lengths[i];
+	printd("IV", &enciv);
+	err = krb5int_aes_encrypt(&key, &enciv, &in, &out);
+	if (err) {
+	    printf("error %ld from krb5int_aes_encrypt\n", (long)err);
+	    exit(1);
+	}
+	printd("Input", &in);
+	printd("Output", &out);
+	printd("Next IV", &enciv);
+	out2.length = out.length;
+	err = krb5int_aes_decrypt(&key, &deciv, &out, &out2);
+	if (err) {
+	    printf("error %ld from krb5int_aes_decrypt\n", (long)err);
+	    exit(1);
+	}
+	if (out2.length != in.length
+	    || memcmp(in.data, out2.data, in.length)) {
+	    printd("Decryption result DOESN'T MATCH", &out2);
+	    exit(1);
+	}
+	if (memcmp(enciv.data, deciv.data, 16)) {
+	    printd("Decryption IV result DOESN'T MATCH", &deciv);
+	    exit(1);
+	}
+    }
+}
+
+int main (int argc, char **argv)
+{
+    whoami = argv[0];
+    test_cts();
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/t_encrypt.c b/krb5-1-6/src/lib/crypto/t_encrypt.c
new file mode 100644
index 000000000..eb2378b5e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_encrypt.c
@@ -0,0 +1,153 @@
+/*
+main * lib/crypto/t_encrypt.c
+ *
+ * Copyright2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * <<< Description >>>
+ */
+/* 
+ * Some black-box tests of crypto systems.  Make sure that we can decrypt things we encrypt, etc.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+#include <stdio.h>
+
+/* What enctypes should we test?*/
+krb5_enctype interesting_enctypes[] = {
+  ENCTYPE_DES_CBC_CRC,
+  ENCTYPE_DES_CBC_MD4,
+  ENCTYPE_DES_CBC_MD5,
+  ENCTYPE_DES3_CBC_SHA1,
+  ENCTYPE_ARCFOUR_HMAC,
+  ENCTYPE_ARCFOUR_HMAC_EXP,
+  ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+  ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+  0
+};
+
+#define test(msg, exp) \
+printf ("%s: . . . ", msg); \
+retval = (exp);\
+if( retval) { \
+  printf( "Failed: %s\n", error_message(retval)); \
+  abort(); \
+} else printf ("OK\n");
+  
+static int compare_results(krb5_data *d1, krb5_data *d2)
+{
+    if (d1->length != d2->length) {
+	/* Decryption can leave a little trailing cruft.
+	   For the current cryptosystems, this can be up to 7 bytes.  */
+	if (d1->length + 8 <= d2->length)
+	    return EINVAL;
+	if (d1->length > d2->length)
+	    return EINVAL;
+    }
+    if (memcmp(d1->data, d2->data, d1->length)) {
+	return EINVAL;
+    }
+    return 0;
+}
+
+int
+main ()
+{
+  krb5_context context = 0;
+  krb5_data  in, in2, out, out2, check, check2, state;
+  int i;
+  size_t len;
+  krb5_enc_data enc_out, enc_out2;
+  krb5_error_code retval;
+  krb5_keyblock *key;
+
+  in.data = "This is a test.\n";
+  in.length = strlen (in.data);
+  in2.data = "This is another test.\n";
+  in2.length = strlen (in2.data);
+
+  test ("Seeding random number generator",
+	krb5_c_random_seed (context, &in));
+  out.data = malloc(2048);
+  out2.data = malloc(2048);
+  check.data = malloc(2048);
+  check2.data = malloc(2048);
+  if (out.data == NULL || out2.data == NULL
+      || check.data == NULL || check2.data == NULL)
+      abort();
+  out.length = 2048;
+  out2.length = 2048;
+  check.length = 2048;
+  check2.length = 2048;
+  for (i = 0; interesting_enctypes[i]; i++) {
+    krb5_enctype enctype = interesting_enctypes [i];
+    printf ("Testing enctype %d\n", enctype);
+    test ("Initializing a keyblock",
+	  krb5_init_keyblock (context, enctype, 0, &key));
+    test ("Generating random key",
+	  krb5_c_make_random_key (context, enctype, key));
+    enc_out.ciphertext = out;
+    enc_out2.ciphertext = out2;
+    /* We use an intermediate `len' because size_t may be different size 
+       than `int' */
+    krb5_c_encrypt_length (context, key->enctype, in.length, &len);
+    enc_out.ciphertext.length = len;
+    test ("Encrypting",
+	  krb5_c_encrypt (context, key, 7, 0, &in, &enc_out));
+    test ("Decrypting",
+	  krb5_c_decrypt (context, key, 7, 0, &enc_out, &check));
+    test ("Comparing", compare_results (&in, &check));
+    enc_out.ciphertext.length = out.length;
+    check.length = 2048;
+    test ("init_state",
+	  krb5_c_init_state (context, key, 7, &state));
+    test ("Encrypting with state",
+	  krb5_c_encrypt (context, key, 7, &state, &in, &enc_out));
+    test ("Encrypting again with state",
+	  krb5_c_encrypt (context, key, 7, &state, &in2, &enc_out2));
+    test ("free_state",
+	  krb5_c_free_state (context, key, &state));
+    test ("init_state",
+	  krb5_c_init_state (context, key, 7, &state));
+    test ("Decrypting with state",
+	  krb5_c_decrypt (context, key, 7, &state, &enc_out, &check));
+    test ("Decrypting again with state",
+	  krb5_c_decrypt (context, key, 7, &state, &enc_out2, &check2));
+    test ("free_state",
+	  krb5_c_free_state (context, key, &state));
+    test ("Comparing",
+	  compare_results (&in, &check));
+    test ("Comparing",
+	  compare_results (&in2, &check2));
+    krb5_free_keyblock (context, key);
+  }
+
+  free(out.data);
+  free(out2.data);
+  free(check.data);
+  free(check2.data);
+  return 0;
+}
+
+	
diff --git a/krb5-1-6/src/lib/crypto/t_hmac.c b/krb5-1-6/src/lib/crypto/t_hmac.c
new file mode 100644
index 000000000..000e64b85
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_hmac.c
@@ -0,0 +1,271 @@
+/*
+ * lib/crypto/t_hmac.c
+ *
+ * Copyright 2001,2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Test vectors for HMAC-MD5 and HMAC-SHA1 (placeholder only).
+ * Tests taken from RFC 2202.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "hash_provider.h"
+
+#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
+
+const char *whoami;
+
+static void keyToData (krb5_keyblock *k, krb5_data *d) {
+    d->length = k->length;
+    d->data = (char *) k->contents;
+}
+
+#if 0
+static void check_error (int r, int line) {
+    if (r != 0) {
+	fprintf (stderr, "%s:%d: %s\n", __FILE__, line,
+		 error_message (r));
+	exit (1);
+    }
+}
+#define CHECK check_error(r, __LINE__)
+#endif
+
+static void printd (const char *descr, krb5_data *d) {
+    int i, j;
+    const int r = 16;
+
+    printf("%s (%d bytes):", descr, d->length);
+
+    for (i = 0; i < d->length; i += r) {
+	printf("\n  %04x: ", i);
+	for (j = i; j < i + r && j < d->length; j++)
+	    printf(" %02x", 0xff & d->data[j]);
+	for (; j < i + r; j++)
+	    printf("   ");
+	printf("   ");
+	for (j = i; j < i + r && j < d->length; j++) {
+	    int c = 0xff & d->data[j];
+	    printf("%c", isprint(c) ? c : '.');
+	}
+    }
+    printf("\n");
+}
+static void printk(const char *descr, krb5_keyblock *k) {
+    krb5_data d;
+    keyToData(k,&d);
+    printd(descr, &d);
+}
+
+
+
+struct hmac_test {
+    int key_len;
+    unsigned char key[180];
+    int data_len;
+    unsigned char data[80];
+    const char *hexdigest;
+};
+
+static krb5_error_code hmac1(const struct krb5_hash_provider *h, 
+			     krb5_keyblock *key,
+			     krb5_data *in, krb5_data *out)
+{
+    char tmp[40];
+    size_t blocksize, hashsize;
+    krb5_error_code err;
+
+    printk(" test key", key);
+    blocksize = h->blocksize;
+    hashsize = h->hashsize;
+    if (hashsize > sizeof(tmp))
+	abort();
+    if (key->length > blocksize) {
+	krb5_data d, d2;
+	d.data = (char *) key->contents;
+	d.length = key->length;
+	d2.data = tmp;
+	d2.length = hashsize;
+	err = h->hash (1, &d, &d2);
+	if (err) {
+	    com_err(whoami, err, "hashing key before calling hmac");
+	    exit(1);
+	}
+	key->length = d2.length;
+	key->contents = (krb5_octet *) d2.data;
+	printk(" pre-hashed key", key);
+    }
+    printd(" hmac input", in);
+    err = krb5_hmac(h, key, 1, in, out);
+    if (err == 0)
+	printd(" hmac output", out);
+    return err;
+}
+
+static void test_hmac()
+{
+    krb5_keyblock key;
+    krb5_data in, out;
+    char outbuf[20];
+    char stroutbuf[80];
+    krb5_error_code err;
+    int i, j;
+    int lose = 0;
+
+    /* RFC 2202 test vector.  */
+    static const struct hmac_test md5tests[] = {
+	{
+	    16, {
+		0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
+		0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
+	    },
+	    8, "Hi There",
+	    "0x9294727a3638bb1c13f48ef8158bfc9d"
+	},
+
+	{
+	    4, "Jefe",
+	    28, "what do ya want for nothing?",
+	    "0x750c783e6ab0b503eaa86e310a5db738"
+	},
+
+	{
+	    16, {
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+	    },
+	    50, {
+		0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+		0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+		0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+		0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+		0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	    },
+	    "0x56be34521d144c88dbb8c733f0e8b3f6"
+	},
+
+	{
+	    25, {
+		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+		0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
+		0x15, 0x16, 0x17, 0x18, 0x19
+	    },
+	    50, {
+		0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+		0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+		0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+		0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+		0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+	    },
+	    "0x697eaf0aca3a3aea3a75164746ffaa79"
+	},
+
+	{
+	    16, {
+		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c
+	    },
+	    20, "Test With Truncation",
+	    "0x56461ef2342edc00f9bab995690efd4c"
+	},
+
+	{
+	    80, {
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	    },
+	    54, "Test Using Larger Than Block-Size Key - Hash Key First",
+	    "0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
+	},
+
+	{
+	    80, {
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	    },
+	    73, 
+	    "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+	    "0x6f630fad67cda0ee1fb1f562db3aa53e"
+	},
+    };
+
+    for (i = 0; i < sizeof(md5tests)/sizeof(md5tests[0]); i++) {
+	key.contents = md5tests[i].key;
+	key.length = md5tests[i].key_len;
+	in.data = md5tests[i].data;
+	in.length = md5tests[i].data_len;
+
+	out.data = outbuf;
+	out.length = 20;
+	printf("\nTest #%d:\n", i+1);
+	err = hmac1(&krb5int_hash_md5, &key, &in, &out);
+	if (err) {
+	    com_err(whoami, err, "computing hmac");
+	    exit(1);
+	}
+
+	if (sizeof(stroutbuf) - 3 < 2 * out.length)
+	    abort();
+	strcpy(stroutbuf, "0x");
+	for (j = 0; j < out.length; j++)
+	    sprintf(stroutbuf + strlen(stroutbuf), "%02x", 0xff & outbuf[j]);
+	if (strcmp(stroutbuf, md5tests[i].hexdigest)) {
+	    printf("*** CHECK FAILED!\n"
+		   "\tReturned: %s.\n"
+		   "\tExpected: %s.\n", stroutbuf, md5tests[i].hexdigest);
+	    lose++;
+	} else
+	    printf("Matches expected result.\n");
+    }
+
+    /* Do again with SHA-1 tests....  */
+
+    if (lose) {
+	printf("%d failures; exiting.\n", lose);
+	exit(1);
+    }
+}
+
+
+int main (int argc, char **argv)
+{
+    whoami = argv[0];
+    test_hmac();
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/t_nfold.c b/krb5-1-6/src/lib/crypto/t_nfold.c
new file mode 100644
index 000000000..6be0a0934
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_nfold.c
@@ -0,0 +1,165 @@
+/*
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Program to test the correctness of nfold implementation.
+ *
+ * exit returns	 0 ==> success
+ * 		-1 ==> error
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "k5-int.h"
+
+#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
+
+static void printhex (size_t len, const unsigned char *p)
+{
+    while (len--)
+	printf ("%02x", 0xff & *p++);
+}
+
+static void printstringhex (const unsigned char *p) {
+    printhex (strlen ((const char *) p), p);
+}
+
+static void rfc_tests ()
+{
+    int i;
+    struct {
+	char *input;
+	unsigned int n;
+	unsigned char exp[192/8];
+    } tests[] = {
+	{ "012345", 64,
+	  { 0xbe,0x07,0x26,0x31,0x27,0x6b,0x19,0x55, }
+	},
+	{ "password", 56,
+	  { 0x78,0xa0,0x7b,0x6c,0xaf,0x85,0xfa, }
+	},
+	{ "Rough Consensus, and Running Code", 64,
+	  { 0xbb,0x6e,0xd3,0x08,0x70,0xb7,0xf0,0xe0, }
+	},
+	{ "password", 168,
+	  { 0x59,0xe4,0xa8,0xca,0x7c,0x03,0x85,0xc3,
+	    0xc3,0x7b,0x3f,0x6d,0x20,0x00,0x24,0x7c,
+	    0xb6,0xe6,0xbd,0x5b,0x3e, }
+	},
+	{ "MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 192,
+	  { 0xdb,0x3b,0x0d,0x8f,0x0b,0x06,0x1e,0x60,
+	    0x32,0x82,0xb3,0x08,0xa5,0x08,0x41,0x22,
+	    0x9a,0xd7,0x98,0xfa,0xb9,0x54,0x0c,0x1b, }
+	},
+    };
+    unsigned char outbuf[192/8];
+
+    printf ("RFC tests:\n");
+    for (i = 0; i < ASIZE (tests); i++) {
+	unsigned char *p = (unsigned char *) tests[i].input;
+	assert (tests[i].n / 8 <= sizeof (outbuf));
+	krb5_nfold (8 * strlen ((char *) p), p, tests[i].n, outbuf);
+	printf ("%d-fold(\"%s\") =\n", tests[i].n, p);
+	printf ("%d-fold(", tests[i].n);
+	printstringhex (p);
+	printf (") =\n\t");
+	printhex (tests[i].n / 8, outbuf);
+	printf ("\n\n");
+	if (memcmp (outbuf, tests[i].exp, tests[i].n/8) != 0) {
+	    printf ("wrong value! expected:\n\t");
+	    printhex (tests[i].n / 8, tests[i].exp);
+	    exit (1);
+	}
+    }
+}
+
+static void fold_kerberos(unsigned int nbytes)
+{
+    unsigned char cipher_text[300];
+    int j;
+
+    if (nbytes > 300)
+	abort();
+
+    printf("%d-fold(\"kerberos\") =\n\t", nbytes*8);
+    krb5_nfold(64, (unsigned char *) "kerberos", 8*nbytes, cipher_text);
+    for (j=0; j<nbytes; j++)
+	printf("%s%02x", (j&3) ? "" : " ", cipher_text[j]);
+    printf("\n");
+}
+
+unsigned char *nfold_in[] = {
+    (unsigned char *) "basch",
+    (unsigned char *) "eichin",
+    (unsigned char *) "sommerfeld",
+    (unsigned char *) "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", (int) strlen((char *) nfold_in[i]), 
+	       nfold_in[i]);
+	printf("\t192-Fold:\t");
+	krb5_nfold(strlen((char *) 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);
+	};
+    }
+    rfc_tests ();
+
+    printf("verify: N-fold is correct\n\n");
+
+    fold_kerberos(8);
+    fold_kerberos(16);
+    fold_kerberos(21);
+    fold_kerberos(32);
+
+    exit(0);
+}
diff --git a/krb5-1-6/src/lib/crypto/t_pkcs5.c b/krb5-1-6/src/lib/crypto/t_pkcs5.c
new file mode 100644
index 000000000..fa1f43dea
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_pkcs5.c
@@ -0,0 +1,105 @@
+/*
+ * lib/crypto/t_pkcs5.c
+ *
+ * Copyright 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Test vectors for PBKDF2 (from PKCS #5v2), based on RFC 3211.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "k5-int.h"
+
+static void printhex (size_t len, const char *p)
+{
+    while (len--)
+	printf (" %02X", 0xff & *p++);
+}
+
+static void printdata (krb5_data *d) {
+    printhex (d->length, d->data);
+}
+
+static void test_pbkdf2_rfc3211()
+{
+    char x[100];
+    krb5_error_code err;
+    krb5_data d, pass, salt;
+    int i;
+
+    /* RFC 3211 test cases.  */
+    static const struct {
+	const char *pass;
+	const char *salt;
+	unsigned int count;
+	size_t len;
+	const unsigned char expected[24];
+    } t[] = {
+	{ "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 5, 8,
+	  { 0xD1, 0xDA, 0xA7, 0x86, 0x15, 0xF2, 0x87, 0xE6 } },
+	{ "All n-entities must communicate with other "
+	  "n-entities via n-1 entiteeheehees",
+	  "\x12\x34\x56\x78\x78\x56\x34\x12", 500, 24,
+	  { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE,
+	    0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86,
+	    0x07, 0x12, 0x63, 0x80, 0xCC, 0x47, 0xAB, 0x2D } },
+    };
+
+    d.data = x;
+    printf("RFC 3211 test of PBKDF#2\n");
+
+    for (i = 0; i < sizeof(t)/sizeof(t[0]); i++) {
+
+	printf("pkbdf2(iter_count=%d, dklen=%d (%d bytes), salt=12 34 56 78 78 56 34 12,\n"
+	       "       pass=%s):\n  ->",
+	       t[i].count, t[i].len * 8, t[i].len, t[i].pass);
+
+	d.length = t[i].len;
+	pass.data = t[i].pass;
+	pass.length = strlen(pass.data);
+	salt.data = t[i].salt;
+	salt.length = strlen(salt.data);
+	err = krb5int_pbkdf2_hmac_sha1 (&d, t[i].count, &pass, &salt);
+	if (err) {
+	    printf("error in computing pbkdf2: %s\n", error_message(err));
+	    exit(1);
+	}
+	printdata(&d);
+	if (!memcmp(x, t[i].expected, t[i].len))
+	    printf("\nTest passed.\n\n");
+	else {
+	    printf("\n*** CHECK FAILED!\n");
+	    exit(1);
+	}
+    }
+}
+
+int main ()
+{
+    test_pbkdf2_rfc3211();
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/t_prf.c b/krb5-1-6/src/lib/crypto/t_prf.c
new file mode 100644
index 000000000..e6d98cb38
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prf.c
@@ -0,0 +1,88 @@
+/*
+ * lib/crypto/t_prf.c
+ *
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * This file contains tests for the PRF  code in Kerberos.  IT reads
+ *an input file, and writes an output file.  It is assumed that the
+ *output file will be diffed against expected output  to see whether
+ *regression tests pass.  The input file is a very primitive format.
+ *It  includes an enctype and  to be string2keyed   followed by a number of bytes of input
+ *length, followed by  that many bytes of input.  The program outputs
+ *krb5_c_prf of that input and key  as a hex string.
+ */
+
+#include "k5-int.h"
+#include <assert.h>
+
+int main () {
+  krb5_data input, output;
+  krb5_keyblock *key = NULL;
+  unsigned int in_length;
+  unsigned int i;
+  while (1) {
+      krb5_enctype enctype;
+      char s[1025];
+
+      if (scanf( "%d", &enctype) == EOF)
+	  break;
+      if (scanf("%1024s", &s[0]) == EOF)
+	  break;
+      assert (krb5_init_keyblock(0, enctype, 0, &key) == 0);
+      input.data = &s[0];
+      input.length = strlen(s);
+      assert(krb5_c_string_to_key (0, enctype, &input, &input, key) == 0);
+    
+      if (scanf("%u", &in_length) == EOF)
+	  break;
+
+      if (in_length ) {
+	  unsigned int lc;
+	  assert ((input.data = malloc(in_length)) != NULL);
+	  for (lc = in_length; lc > 0; lc--) {
+	      scanf ("%2x",  &i);
+	      input.data[in_length-lc] = (unsigned) (i&0xff);
+	  }
+	  input.length = in_length;
+	  assert (krb5_c_prf_length(0, enctype, &i) == 0);
+	  assert (output.data = malloc(i));
+	  output.length = i;
+	  assert (krb5_c_prf(0, key, &input, &output) == 0);
+      
+	  free (input.data);
+	  input.data = NULL;
+      }
+      for (; i > 0; i--) {
+	  printf ("%02x",
+		  (unsigned int) ((unsigned char ) output.data[output.length-i]));
+      }
+      printf ("\n");
+
+      free (output.data);
+      output.data = NULL;
+      krb5_free_keyblock(0, key);
+      key = NULL;
+  }
+
+  return (0);
+}
diff --git a/krb5-1-6/src/lib/crypto/t_prng.c b/krb5-1-6/src/lib/crypto/t_prng.c
new file mode 100644
index 000000000..49c0aec74
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prng.c
@@ -0,0 +1,87 @@
+/*
+ * lib/crypto/t_prng.c
+ *
+ * Copyright (C) 2001 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * This file contains tests for the PRNG code in Kerberos.  IT reads
+ *an input file, and writes an output file.  It is assumed that the
+ *output file will be diffed against expected output  to see whether
+ *regression tests pass.  The input file is very primitive format.  It
+ *is composed of alternating seeds and outputs.   The first  line in
+ *the file is an integer source Id from the krb5_c_randsource enum in
+ *krb5.h.  Then an integer seed length is be
+ *read.  Then that many bytes (encoded in hex) is read; whitspace or
+ *newlines may be inserted between bytes.  Then after the seed data is
+ *a  integer describing how many bytes of output should be written.
+ *Then another source ID and seed length is read.  If the seed length
+ *is 0, the source id is ignored and the seed is not seeded.
+ */
+
+#include "k5-int.h"
+#include <assert.h>
+
+int main () {
+  krb5_error_code ret;
+  krb5_data input, output;
+  unsigned int source_id, seed_length;
+  unsigned int i;
+  while (1) {
+        /* Read source*/
+    if (scanf ("%u", &source_id ) == EOF )
+      break;
+        /* Read seed length*/
+    if (scanf ("%u", &seed_length) == EOF)
+      break;
+    if (seed_length ) {
+      unsigned int lc;
+      assert ((input.data = malloc(seed_length)) != NULL);
+      for (lc = seed_length; lc > 0; lc--) {
+	scanf ("%2x",  &i);
+	input.data[seed_length-lc] = (unsigned) (i&0xff);
+      }
+      input.length = seed_length;
+      assert (krb5_c_random_add_entropy (0, source_id, &input) == 0);
+      free (input.data);
+      input.data = NULL;
+    }
+    if (scanf ("%u", &i) == EOF)
+      break;
+    if (i) {
+      assert ((output.data = malloc (i)) != NULL);
+      output.length = i;
+      ret = krb5_c_random_make_octets (0, &output);
+      if (ret)
+	printf ("failed\n");
+      else {
+	for (; i > 0; i--) {
+	  printf ("%02x",
+		  (unsigned int) ((unsigned char ) output.data[output.length-i]));
+	}
+	printf ("\n");
+      }
+      free (output.data);
+      output.data = NULL;
+    }
+  }
+  return (0);
+}
diff --git a/krb5-1-6/src/lib/crypto/t_prng.comments b/krb5-1-6/src/lib/crypto/t_prng.comments
new file mode 100644
index 000000000..1666b7060
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prng.comments
@@ -0,0 +1,14 @@
+Things this test tries to do:
+*adding data
+* getting random data
+* adding more data but not enough for reseed
+*getting more random data
+*adding enough to trigger a reseed
+*getting more random data
+* getting random data without a reseed inbetween
+* getting enough data to trigger a gate
+
+
+If you adjust the blocksize or the seeding parameters then this test
+should be adjusted.
+
diff --git a/krb5-1-6/src/lib/crypto/t_prng.expected b/krb5-1-6/src/lib/crypto/t_prng.expected
new file mode 100644
index 000000000..f7f165051
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prng.expected
@@ -0,0 +1,4 @@
+d2f8fbd707a8ece5cb11a02f
+eb4cb6e06236ea1c0529f7acbfca8d78cb85bb1d
+a244005ae870604342b0386025874ec4306c1dd483c118621b
+63e6408afdf9fd225839a7afcc6da6ae494fb4f82bd21ea06bb17ca0848bdae8cea671f545aac52699951caba960c536024b4102f47d61d61fd7b17582a4cf50ba7d215062558f71483249e079689893f3bf25def7f45f9e852281269904d401d6719e3115f6410088c6c5171e878494362684d2116633bb9ea8d9ed5faec73cb076c44d5d639bc2c8ae3de54f0e1e092d5ea439e607e9cd73053bbdf40723f5b48f298fdeeef845e22e06f2f6362fc67fba366e638a7988999d456dcc3d53b23388d685620a7c446d28cd94b13049761b64779db5412e78ac4bab2aacf103fd1b9ceb7213d43710d6a46fd4223fa20e0a68d3e16a82cbadea650ba815dc9ee99b4eb8e2acdac866a05d90ab9de3246db0560fb4b36633bb642c3ea9bf358937dda743f9cef1148791c2cac58995b8eb8fdb1c0cce1686e04ebef5ae7aae36691faafbe8920d3c013f125b687eb019faefa70fc750c52e2e2e33f426824bf1da31268a9bb8d9501f2290375755f8bf77b46639346b4011b78ce9d81105c7791ec5991a2f1eab037488b604df1a21c5c4e36a7c76dca5884d36e30fe8d30d0e7d93fab72062219390655eace2b434b0e2cd21ec9c5a8aa13e783afadcdf386fc43b960c518acb38d7e3da2f67695c1c1c25c4f251b40f4c2e42e89f6f642c32e66159f6ce24aa910fb5d95e3a899a4de5efcf570996e1a662d14362b65d00524df79cd56be93bd572526e4dfd1cf9f7586bc021105cf5456b28c1f45a6d354d000a113e15f64aa0b5253830c07afc8fa47b58dbba8bbae1645b2093035f2387036229dec6f7141b444b8bb7d0382a742bd5c746ba2d7af3af1cadb2dd90bda87d5daed2d2eebd243c7b2d06955d0cc7fe1061d4cfa3b061aaeb97084d9f9a7ec9dbe9e642f4f090d57b5ea1bd8b393f00896d3dc7089e1fc4c2fed7336c2a8c6d119a682c6cc4ae1ccedd30292f2c5570bf4d6287ce8e20b8b34e7fc38e87273f588cd33b8c913defaee5f6bf8fdeda72531c845a6f97a84d5e9b9a6497d4c48614dee7693df35faedc008fded852be8d4bffd475476336e54ed48a827b99d3f0e39019a40d43aef5ae522ec6e280f6a8e7d2713f3c3188bed2476a84af5a5afefa0fa178ed07de0e073693e8790f8bbd0cf9183e48f140b556e723565c382cf7a4c186748189a14e603e4ac70e2b80c266334231207721d16d834a973b48cfec584620624686603cfd66d55dbf8dd8eccd99d85f041c624ec3a7bec314af95d2313afd43cc5cc19249cf85b7ab0b5a4530b597341e7477b249fef1a07eb0d8fa790e9bce752e8b2f7086e98ab44751e0a1b37f29682ce67c0de7a2fd036f26ed719fc343bbf49432aec651d884c99c24d5943c747f7ec3b48d4c2236a8cb6151794daeda073774cc88ff121fdd423b81ef2f34c8f281ca2e5366faee87ff7a623484f2937cc0680ed76ead32b43cb6c67a21f8089b435f38a404d267397c6435cfac16591a3573d9e92f8c4a8028719c22662b903ddb16e08ea7bb2d6b8938c06bdddb4d174c7f2c5d812ed3a34ba8859a1ae841b3b9d5522372018c9aa55b048df826f05a087f185808cb66899f320783a1c4aa2dcd5f2665405ba7e5726e122b67559a39da30956e49fe7711d1b2506e159c5ea42ce0a1ad497220ee3b3e5ebcb73db975bd08e8be56e5f4533b8295b10d4b0fef466de6540f8fe10530c9716d83a12f5ffbba5b4dbc50ed89388d04e7a15d3d9d251041ed5303efa2525bc62a5aeb821f7838676811784584534be8a7fc667f09c3fe1bbf7d0aad29324f562086ecb8326829413867
diff --git a/krb5-1-6/src/lib/crypto/t_prng.reseedtest b/krb5-1-6/src/lib/crypto/t_prng.reseedtest
new file mode 100644
index 000000000..5eee0c064
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prng.reseedtest
@@ -0,0 +1,31 @@
+1
+160
+ cb 12 70 40 ee fb 76 2e 32 0d f1 0c a7 a9 36 f8
+ c8 f3 35 4e 0f 51 18 cd 25 0f 48 5b e4 97 aa 4f
+ be 7e 93 af dd 15 29 fc 24 4f 0b 9a 9b 1d ad 7f
+ 32 c8 a6 96 d4 34 aa 83 d2 d7 33 b0 2f aa ba f6
+ cf 8c 78 ad 8a 52 e1 48 e4 7c a7 c5 57 49 31 ea
+ db b7 9b 6b ab 13 f3 12 a5 ec 67 db 1e 83 73 be
+ ca 59 fc ed 29 8c f3 ef ca fd 81 55 fa 91 3b 31
+ da 24 d2 8b c1 a5 c1 3a 9c 50 a6 3c a1 60 31 0f
+ 62 c7 88 9b 1a e9 9f 3c 0f 04 d0 35 11 45 f0 8b
+ 84 a2 26 85 67 f1 e6 2b 34 6b ab 9b 3f c1 a1 0e
+0
+1
+40
+ f4 fc ab 98 45 a0 41 e4 4d 65 9c eb c2 c9 74 a4
+ 55 df 6c 78 78 bc db ae e7 63 b8 a7 33 3b d7 50
+ f6 33 c4 a0 1d 14 45 04
+0
+0
+40
+ 16 80 1d 78 39 4b 3a 27 80 87 08 6c a9 37 59 74
+ 60 f8 fc 37 10 4a 8a c4 d6 3e 6a 41 1a e1 5f 69
+ 92 12 5a e1 3b 86 f1 5d
+0
+0
+40
+ a3 c8 78 4a a0 4d ce 3c 2a 8e 34 bf f7 06 dc d7
+ 92 13 bd 74 45 72 40 b6 1c d6 55 28 47 1e f4 70
+ 74 e4 94 d7 17 a6 7e 3b
+20
diff --git a/krb5-1-6/src/lib/crypto/t_prng.reseedtest-comments b/krb5-1-6/src/lib/crypto/t_prng.reseedtest-comments
new file mode 100644
index 000000000..e50e09602
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prng.reseedtest-comments
@@ -0,0 +1,21 @@
+The reseedtest is intended to allow confirmation that if sufficient
+entropy is provided then the PRNG will reseed (well initially seed)
+itself before the first random data is requested.  This test is not
+useful to run in an automated manner because the point is to look at
+internal function call order.
+
+To test this, set a break point at krb5int_yarrow_reseed and
+krb5_c_random_make_octets and run the test.  The reseed function
+should be called with a pool of 1 (YARROW_SLOW_POOL) before
+krb5_c_random_make_octets is called.
+
+A slow reseed should require two sources to reach sufficient entropy.
+Sources  start out sending entropy to fast pool then alternate with
+slow pool.  So this test does the following:
+* Seed source 1
+* Seed source 1 (this time to slow pool)
+* Seed source 0
+* Seed source 0 (to slow pool triggering reseed)
+* Output some random data
+
+
diff --git a/krb5-1-6/src/lib/crypto/t_prng.reseedtest-expected b/krb5-1-6/src/lib/crypto/t_prng.reseedtest-expected
new file mode 100644
index 000000000..d7b50801e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prng.reseedtest-expected
@@ -0,0 +1 @@
+fd543f42aded9bd725c9b05682cd0f504c1b33d1
diff --git a/krb5-1-6/src/lib/crypto/t_prng.seed b/krb5-1-6/src/lib/crypto/t_prng.seed
new file mode 100644
index 000000000..79f4f6458
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/t_prng.seed
@@ -0,0 +1,25 @@
+2
+20
+ c9 72 2b e4 90 e1 fa 4b da d4 2f 43 0d dd d9 91
+ 39 d0 23 c4
+0
+1
+24
+ 87 1c 4f d4 4a 8b b8 cf 54 4e eb 9b 1f bb 7a 8e
+ 9a 7d 8d 62
+ ca 41 18 00
+12
+0
+0
+20
+1
+24
+ 28 d4 bd d4 81 85 ca 70 d5 f0 e4 a4 f3 45 80 01
+ 6a 34 79 69 0e e0 cd 21
+25
+2
+40
+ de 7c f0 c5 6a 37 0b 34 f4 0c 3a 19 31 eb 66 f1
+ ae 5f c6 a3 64 3f 2e a9 76 e1 87 93 df b6 94 86
+ bd 96 57 3f 31 e6 88 8c
+1290
diff --git a/krb5-1-6/src/lib/crypto/valid_cksumtype.c b/krb5-1-6/src/lib/crypto/valid_cksumtype.c
new file mode 100644
index 000000000..bc34c0b95
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/valid_cksumtype.c
@@ -0,0 +1,47 @@
+/*
+ * 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 KRB5_CALLCONV
+krb5_c_valid_cksumtype(krb5_cksumtype ctype)
+{
+    int i;
+
+    for (i=0; i<krb5_cksumtypes_length; i++) {
+	if (krb5_cksumtypes_list[i].ctype == ctype)
+	    return(1);
+    }
+
+    return(0);
+}
+
+krb5_boolean KRB5_CALLCONV
+valid_cksumtype(krb5_cksumtype ctype)
+{
+    return krb5_c_valid_cksumtype (ctype);
+}
diff --git a/krb5-1-6/src/lib/crypto/valid_enctype.c b/krb5-1-6/src/lib/crypto/valid_enctype.c
new file mode 100644
index 000000000..f36023084
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/valid_enctype.c
@@ -0,0 +1,47 @@
+/*
+ * 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 KRB5_CALLCONV
+krb5_c_valid_enctype(krb5_enctype etype)
+{
+    int i;
+
+    for (i=0; i<krb5_enctypes_length; i++) {
+	if (krb5_enctypes_list[i].etype == etype)
+	    return(1);
+    }
+
+    return(0);
+}
+
+krb5_boolean KRB5_CALLCONV
+valid_enctype(krb5_enctype etype)
+{
+    return krb5_c_valid_enctype (etype);
+}
diff --git a/krb5-1-6/src/lib/crypto/vectors.c b/krb5-1-6/src/lib/crypto/vectors.c
new file mode 100644
index 000000000..27b6206c9
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/vectors.c
@@ -0,0 +1,457 @@
+/*
+ * lib/crypto/vectors.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Test vectors for crypto code, matching data submitted for inclusion
+ * with RFC1510bis.
+ *
+ * N.B.: Doesn't compile -- this file uses some routines internal to our
+ * crypto library which are declared "static" and thus aren't accessible
+ * without modifying the other sources.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "hash_provider.h"
+
+#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
+
+const char *whoami;
+
+static void printhex (size_t len, const char *p)
+{
+    while (len--)
+	printf ("%02x", 0xff & *p++);
+}
+
+static void printstringhex (const char *p) { printhex (strlen (p), p); }
+
+static void printdata (krb5_data *d) { printhex (d->length, d->data); }
+
+static void printkey (krb5_keyblock *k) { printhex (k->length, k->contents); }
+
+static void test_nfold ()
+{
+    int i;
+    static const struct {
+	char *input;
+	int n;
+    } tests[] = {
+	{ "012345", 64, },
+	{ "password", 56, },
+	{ "Rough Consensus, and Running Code", 64, },
+	{ "password", 168, },
+	{ "MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 192 },
+	{ "Q", 168 },
+	{ "ba", 168 },
+    };
+    unsigned char outbuf[192/8];
+
+    for (i = 0; i < ASIZE (tests); i++) {
+	char *p = tests[i].input;
+	assert (tests[i].n / 8 <= sizeof (outbuf));
+	printf ("%d-fold(\"%s\") =\n", tests[i].n, p);
+	printf ("%d-fold(", tests[i].n);
+	printstringhex (p);
+	printf (") =\n\t");
+	krb5_nfold (8 * strlen (p), p, tests[i].n, outbuf);
+	printhex (tests[i].n / 8U, outbuf);
+	printf ("\n\n");
+    }
+}
+
+#define JURISIC "Juri\305\241i\304\207" /* hi Miro */
+#define ESZETT "\303\237"
+#define GCLEF  "\360\235\204\236" /* outside BMP, woo hoo!  */
+
+/* Some weak keys:
+    {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e},
+    {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1},
+   so try to generate them. */
+
+static void
+test_mit_des_s2k ()
+{
+    static const struct {
+	const char *pass;
+	const char *salt;
+    } pairs[] = {
+	{ "password", "ATHENA.MIT.EDUraeburn" },
+	{ "potatoe", "WHITEHOUSE.GOVdanny" },
+	{ "penny", "EXAMPLE.COMbuckaroo", },
+	{ GCLEF, "EXAMPLE.COMpianist" },
+	{ ESZETT, "ATHENA.MIT.EDU" JURISIC },
+	/* These two trigger weak-key fixups.  */
+	{ "11119999", "AAAAAAAA" },
+	{ "NNNN6666", "FFFFAAAA" },
+    };
+    int i;
+
+    for (i = 0; i < ASIZE (pairs); i++) {
+	const char *p = pairs[i].pass;
+	const char *s = pairs[i].salt;
+	krb5_data pd;
+	krb5_data sd;
+	unsigned char key_contents[60];
+	krb5_keyblock key;
+	krb5_error_code r;
+	char buf[80];
+
+	key.contents = key_contents;
+
+	pd.length = strlen (p);
+	pd.data = (char *) p;
+	sd.length = strlen (s);
+	sd.data = (char *) s;
+
+	assert (strlen (s) + 4 < sizeof (buf));
+	sprintf (buf, "\"%s\"", s);
+	printf (  "salt:     %-25s", buf);
+	printhex (strlen(s), s);
+	sprintf (buf, "\"%s\"", p);
+	printf ("\npassword: %-25s", buf);
+	printhex (strlen(p), p);
+	printf ("\n");
+	r = krb5int_des_string_to_key (0, &pd, &sd, 0, &key);
+	printf (  "DES key:  %-25s", "");
+	printhex (key.length, key.contents);
+	printf ("\n\n");
+    }
+}
+
+static void
+test_s2k (krb5_enctype enctype)
+{
+    static const struct {
+	const char *pass;
+	const char *salt;
+    } pairs[] = {
+	{ "password", "ATHENA.MIT.EDUraeburn" },
+	{ "potatoe", "WHITEHOUSE.GOVdanny" },
+	{ "penny", "EXAMPLE.COMbuckaroo", },
+	{ ESZETT, "ATHENA.MIT.EDU" JURISIC },
+	{ GCLEF, "EXAMPLE.COMpianist" },
+    };
+    int i;
+
+    for (i = 0; i < ASIZE (pairs); i++) {
+	const char *p = pairs[i].pass;
+	const char *s = pairs[i].salt;
+	krb5_data pd, sd;
+	unsigned char key_contents[60];
+	krb5_keyblock key;
+	krb5_error_code r;
+	char buf[80];
+
+	pd.length = strlen (p);
+	pd.data = (char *) p;
+	sd.length = strlen (s);
+	sd.data = (char *) s;
+	key.contents = key_contents;
+
+	assert (strlen (s) + 4 < sizeof (buf));
+	sprintf (buf, "\"%s\"", s);
+	printf (  "salt:\t%s\n\t", buf);
+	printhex (strlen(s), s);
+	sprintf (buf, "\"%s\"", p);
+	printf ("\npasswd:\t%s\n\t", buf);
+	printhex (strlen(p), p);
+	printf ("\n");
+	r = krb5_c_string_to_key (0, enctype, &pd, &sd, &key);
+	printf (  "key:\t");
+	printhex (key.length, key.contents);
+	printf ("\n\n");
+    }
+}
+
+static void test_des3_s2k () { test_s2k (ENCTYPE_DES3_CBC_SHA1); }
+
+static void
+keyToData (krb5_keyblock *k, krb5_data *d)
+{
+    d->length = k->length;
+    d->data = k->contents;
+}
+
+void check_error (int r, int line) {
+    if (r != 0) {
+	fprintf (stderr, "%s:%d: %s\n", __FILE__, line,
+		 error_message (r));
+	exit (1);
+    }
+}
+#define CHECK check_error(r, __LINE__)
+
+extern struct krb5_enc_provider krb5int_enc_des3;
+struct krb5_enc_provider *enc = &krb5int_enc_des3;
+extern struct krb5_enc_provider krb5int_enc_aes128, krb5int_enc_aes256;
+
+void DK (krb5_keyblock *out, krb5_keyblock *in, const krb5_data *usage) {
+    krb5_error_code r;
+    r = krb5_derive_key (enc, in, out, usage);
+    CHECK;
+}
+
+void DR (krb5_data *out, krb5_keyblock *in, const krb5_data *usage) {
+    krb5_error_code r;
+    r = krb5_derive_random (enc, in, out, usage);
+    CHECK;
+}
+
+#define KEYBYTES  21
+#define KEYLENGTH 24
+
+void test_dr_dk ()
+{
+    static const struct {
+	unsigned char keydata[KEYLENGTH];
+	int usage_len;
+	unsigned char usage[8];
+    } derive_tests[] = {
+	{
+	    {
+		0xdc, 0xe0, 0x6b, 0x1f, 0x64, 0xc8, 0x57, 0xa1,
+		0x1c, 0x3d, 0xb5, 0x7c, 0x51, 0x89, 0x9b, 0x2c,
+		0xc1, 0x79, 0x10, 0x08, 0xce, 0x97, 0x3b, 0x92,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0x55 },
+	},
+	{
+	    {
+		0x5e, 0x13, 0xd3, 0x1c, 0x70, 0xef, 0x76, 0x57,
+		0x46, 0x57, 0x85, 0x31, 0xcb, 0x51, 0xc1, 0x5b,
+		0xf1, 0x1c, 0xa8, 0x2c, 0x97, 0xce, 0xe9, 0xf2,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0xaa },
+	},
+	{
+	    {
+		0x98, 0xe6, 0xfd, 0x8a, 0x04, 0xa4, 0xb6, 0x85,
+		0x9b, 0x75, 0xa1, 0x76, 0x54, 0x0b, 0x97, 0x52,
+		0xba, 0xd3, 0xec, 0xd6, 0x10, 0xa2, 0x52, 0xbc,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0x55 },
+	},
+	{
+	    {
+		0x62, 0x2a, 0xec, 0x25, 0xa2, 0xfe, 0x2c, 0xad,
+		0x70, 0x94, 0x68, 0x0b, 0x7c, 0x64, 0x94, 0x02,
+		0x80, 0x08, 0x4c, 0x1a, 0x7c, 0xec, 0x92, 0xb5,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0xaa },
+	},
+	{
+	    {
+		0xd3, 0xf8, 0x29, 0x8c, 0xcb, 0x16, 0x64, 0x38,
+		0xdc, 0xb9, 0xb9, 0x3e, 0xe5, 0xa7, 0x62, 0x92,
+		0x86, 0xa4, 0x91, 0xf8, 0x38, 0xf8, 0x02, 0xfb,
+	     },
+	    8, { 'k', 'e', 'r', 'b', 'e', 'r', 'o', 's' },
+	},
+	{
+	    {
+		0xb5, 0x5e, 0x98, 0x34, 0x67, 0xe5, 0x51, 0xb3,
+		0xe5, 0xd0, 0xe5, 0xb6, 0xc8, 0x0d, 0x45, 0x76,
+		0x94, 0x23, 0xa8, 0x73, 0xdc, 0x62, 0xb3, 0x0e,
+	    },
+	    7, { 'c', 'o', 'm', 'b', 'i', 'n', 'e', },
+	},
+	{
+	    {
+		0xc1, 0x08, 0x16, 0x49, 0xad, 0xa7, 0x43, 0x62,
+		0xe6, 0xa1, 0x45, 0x9d, 0x01, 0xdf, 0xd3, 0x0d,
+		0x67, 0xc2, 0x23, 0x4c, 0x94, 0x07, 0x04, 0xda,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0x55 },
+	},
+	{
+	    {
+		0x5d, 0x15, 0x4a, 0xf2, 0x38, 0xf4, 0x67, 0x13,
+		0x15, 0x57, 0x19, 0xd5, 0x5e, 0x2f, 0x1f, 0x79,
+		0x0d, 0xd6, 0x61, 0xf2, 0x79, 0xa7, 0x91, 0x7c,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0xaa },
+	},
+	{
+	    {
+		0x79, 0x85, 0x62, 0xe0, 0x49, 0x85, 0x2f, 0x57,
+		0xdc, 0x8c, 0x34, 0x3b, 0xa1, 0x7f, 0x2c, 0xa1,
+		0xd9, 0x73, 0x94, 0xef, 0xc8, 0xad, 0xc4, 0x43,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0x55 },
+	},
+	{
+	    {
+		0x26, 0xdc, 0xe3, 0x34, 0xb5, 0x45, 0x29, 0x2f,
+		0x2f, 0xea, 0xb9, 0xa8, 0x70, 0x1a, 0x89, 0xa4,
+		0xb9, 0x9e, 0xb9, 0x94, 0x2c, 0xec, 0xd0, 0x16,
+	    },
+	    5, { 0x00, 0x00, 0x00, 0x01, 0xaa },
+	},
+    };
+    int i;
+
+    for (i = 0; i < ASIZE(derive_tests); i++) {
+#define D (derive_tests[i])
+	krb5_keyblock key;
+	krb5_data usage;
+
+	unsigned char drData[KEYBYTES];
+	krb5_data dr;
+	unsigned char dkData[KEYLENGTH];
+	krb5_keyblock dk;
+
+	key.length = KEYLENGTH, key.contents = D.keydata;
+	usage.length = D.usage_len, usage.data = D.usage;
+	dr.length = KEYBYTES, dr.data = drData;
+	dk.length = KEYLENGTH, dk.contents = dkData;
+
+	printf ("key:\t"); printkey (&key); printf ("\n");
+	printf ("usage:\t"); printdata (&usage); printf ("\n");
+	DR (&dr, &key, &usage);
+	printf ("DR:\t"); printdata (&dr); printf ("\n");
+	DK (&dk, &key, &usage);
+	printf ("DK:\t"); printkey (&dk); printf ("\n\n");
+    }
+}
+
+
+static void printd (const char *descr, krb5_data *d) {
+    int i, j;
+    const int r = 16;
+
+    printf("%s:", descr);
+
+    for (i = 0; i < d->length; i += r) {
+	printf("\n  %04x: ", i);
+	for (j = i; j < i + r && j < d->length; j++)
+	    printf(" %02x", 0xff & d->data[j]);
+	for (; j < i + r; j++)
+	    printf("   ");
+	printf("   ");
+	for (j = i; j < i + r && j < d->length; j++) {
+	    int c = 0xff & d->data[j];
+	    printf("%c", isprint(c) ? c : '.');
+	}
+    }
+    printf("\n");
+}
+static void printk(const char *descr, krb5_keyblock *k) {
+    krb5_data d;
+    d.data = k->contents;
+    d.length = k->length;
+    printd(descr, &d);
+}
+
+
+static void
+test_pbkdf2()
+{
+    static struct {
+	int count;
+	char *pass;
+	char *salt;
+    } test[] = {
+	{ 1, "password", "ATHENA.MIT.EDUraeburn" },
+	{ 2, "password", "ATHENA.MIT.EDUraeburn" },
+	{ 1200, "password", "ATHENA.MIT.EDUraeburn" },
+	{ 5, "password", "\x12\x34\x56\x78\x78\x56\x34\x12" },
+	{ 1200,
+	  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+	  "pass phrase equals block size" },
+	{ 1200,
+	  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+	  "pass phrase exceeds block size" },
+	{ 50, "\xf0\x9d\x84\x9e", "EXAMPLE.COMpianist" },
+    };
+    unsigned char x[100];
+    unsigned char x2[100];
+    int j;
+    krb5_error_code err;
+    krb5_data d;
+    krb5_keyblock k, dk;
+    krb5_data usage, pass, salt;
+
+    d.data = x;
+    dk.contents = x2;
+
+    usage.data = "kerberos";
+    usage.length = 8;
+
+    for (j = 0; j < sizeof(test)/sizeof(test[0]); j++) {
+	printf("pkbdf2(count=%d, pass=\"%s\", salt=",
+	       test[j].count, test[j].pass);
+	if (isprint(test[j].salt[0]))
+	    printf("\"%s\")\n", test[j].salt);
+	else {
+	    char *s = test[j].salt;
+	    printf("0x");
+	    while (*s)
+		printf("%02X", 0xff & *s++);
+	    printf(")\n");
+	}
+
+	d.length = 16;
+	pass.data = test[j].pass;
+	pass.length = strlen(pass.data);
+	salt.data = test[j].salt;
+	salt.length = strlen(salt.data);
+	err = krb5int_pbkdf2_hmac_sha1 (&d, test[j].count, &pass, &salt);
+	printd("128-bit PBKDF2 output", &d);
+	enc = &krb5int_enc_aes128;
+	k.contents = d.data;
+	k.length = d.length;
+	dk.length = d.length;
+	DK (&dk, &k, &usage);
+	printk("128-bit AES key",&dk);
+
+	d.length = 32;
+	err = krb5int_pbkdf2_hmac_sha1 (&d, test[j].count, &pass, &salt);
+	printd("256-bit PBKDF2 output", &d);
+	enc = &krb5int_enc_aes256;
+	k.contents = d.data;
+	k.length = d.length;
+	dk.length = d.length;
+	DK (&dk, &k, &usage);
+	printk("256-bit AES key", &dk);
+
+	printf("\n");
+    }
+}
+
+int main (int argc, char **argv)
+{
+    whoami = argv[0];
+    test_nfold ();
+#if 0
+    test_mit_des_s2k ();
+    test_des3_s2k ();
+    test_dr_dk ();
+#endif
+    test_pbkdf2();
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/verify_checksum.c b/krb5-1-6/src/lib/crypto/verify_checksum.c
new file mode 100644
index 000000000..30c9c07c0
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/verify_checksum.c
@@ -0,0 +1,80 @@
+/*
+ * 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_CALLCONV
+krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key,
+		       krb5_keyusage usage, const krb5_data *data,
+		       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 = (char *) cksum->contents;
+
+    if (krb5_cksumtypes_list[i].keyhash &&
+	krb5_cksumtypes_list[i].keyhash->verify)
+	return((*(krb5_cksumtypes_list[i].keyhash->verify))(key, usage, 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/krb5-1-6/src/lib/crypto/yarrow/ASSUMPTIONS b/krb5-1-6/src/lib/crypto/yarrow/ASSUMPTIONS
new file mode 100644
index 000000000..3e3c99c49
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/ASSUMPTIONS
@@ -0,0 +1,101 @@
+Assumptions
+===========
+
+The Yarrow design, described in "Yarrow-160: Notes on the Design and
+Analysis of the Yarrow Cryptographic Pseudonumber Generator" by John
+Kelsey, Bruce Schneier and Niels Ferguson of Counterpane Systems
+(available from http://www.counterpane.com/yarrow.html), left out some
+implementation details and has some ambiguities in the protocol.  ZKS
+has to made some assumptions and taken some decisions in its
+implementation of Yarrow. In the text, `we' represents ZKS.
+
+Here is the list of those assumptions: 
+
+1) To simplify the code and speed up running time, we limit the number
+of different sources to 20. This should be enough for most
+applications. This can be changed by redefining YARROW_MAX_SOURCE in
+yarrow.h.
+
+2) The Yarrow paper (in section 5.3) state that Pt is either
+implementation dependent or dynamically adjusted. We chose to fix the
+slow pool's Pt to 100 and the fast pool's Pt to 10. This can be
+changed by redefining YARROW_FAST_PT and YARROW_SLOW_PT in yarrow.c.
+
+3) Initialization when there is no saved state is not discussed in the
+Yarrow paper.  We have defined that CPRNG is becomes seeded after a
+slow reseed.  During initialization, a slow reseed is triggered by
+YARROW_K_OF_N_INIT_THRESH sources reaching the slow threshold
+YARROW_SLOW_INIT_THRESH.  During initialization, fast reseeds are
+triggered when a source reaches the fast threshold
+YARROW_FAST_INIT_THRESH.  After reseed the behavior of the pools is
+controlled by YARROW_K_OF_N_THRESH, YARROW_SLOW_THRESH and
+YARROW_FAST_THRESH.  
+
+Our default values for YARROW_K_OF_N_INIT_THRESH,
+YARROW_SLOW_INIT_THRESH and YARROW_FAST_INIT_THRESH are the same as
+YARROW_K_OF_N_THRESH, YARROW_SLOW_THRESH and YARROW_FAST_THRESH
+respectively.  Note this means that a Yarrow_Poll call by itself can
+never put us in an initialized state, as it only works on one pool,
+and the default YARROW_K_OF_N_INIT_THRESH value is 2.
+
+4) We define a function Yarrow_Poll which can gather entropy.  The
+user must allocate a source_id, and call Yarrow_Poll manually.
+Yarrow_Poll just adds samples from the machines state to the source
+given as an argument.
+
+5) Prior to initialization, Yarrow_Output will fail.
+
+6) The actions to take on state load are not described in the yarrow
+paper, all it says is that 2k bytes should be written (and by
+implication read back in somehow).  We read in the 2k bytes, hash
+them into the fast pool, and then do a forced fast reseed, and an
+immediate state save.
+
+7) In step 2 of the reseed process, we must hash the value i. The
+representation of this integer will affect the hash value. In our
+code, i is a 64-bit unsigned value. We update the hash context using
+the 64 bit big endian representation of i.
+
+8) Yarrow outputs random bits in blocks. If the calling function
+requests less bits than available, then the unused bits are kept
+in memory until the next call. In case of a reseed, we chose to 
+discard those leftover bits.
+
+9) The samples from one source must alternate between the two pools.
+As a default, we initialize the first pool to send the sample too to
+be the fast pool. This initialization is done only when a source is
+added, not when we reseed from one.
+
+10) The Yarrow paper states that the maximum number of outputs between
+reseeding is limited to min(2^n,2^(k/3)*Pg), but does not explain
+what is to happen when this limit is reached. It could be the case
+that we reach the limit but there is not enough entropy in the pools 
+to reseed. In our code, the Yarrow_Output_Block will do a forced
+fast reseed. 
+
+11) In the Yarrow paper, the limit on the number of outputs between
+reseeding is expressed in number of outputs:
+
+#oututs <= min(2^n, 2^(k/3).Pg)
+
+but we redefine it in terms of gates by dividing the numbers by Pg,
+the number of outputs per gate, and counting the number of gates
+instead.  This makes an overflow a little less likely.
+
+We don't use a bignum library, so in event of overflow, the limit in
+number of gates before reseed (y->gates_limit) is reduced down to
+2^64-1 (or 2^32-1 if 64 bit ints aren't available on the platform).
+
+12) The Yarrow paper describes that the cipher block C should be 
+incremented as part of the output function.  We treat the bytes
+of C as a big endian number to do the increment.
+
+13) Triple-DES key size.  The yarrow paper uses the letter k to
+represent the keysize in bits.  Due to the parity bits, the size of k
+is 192 bits.  However the effective key size is actually 168 bits, as
+the value of k is used in security limits, k must be 168 bits.  The
+paper uses k (eg set K to the next k output bits), so we have to do
+the parity padding function, to copy bits 0-6 to 0-7, 7-13 to 8-15
+etc.  The macro DES_Init performs the function of doing a DES key
+schedule from a packed key (no parity bits), internally doing the
+parity padding.  Other ciphers are simpler as there is no parity.
diff --git a/krb5-1-6/src/lib/crypto/yarrow/LICENSE b/krb5-1-6/src/lib/crypto/yarrow/LICENSE
new file mode 100644
index 000000000..c85475d7e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2000 by Zero-Knowledge Systems, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+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 Zero-Knowledge Systems,
+Inc. not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.  Zero-Knowledge Systems, Inc. makes no representations
+about the suitability of this software for any purpose.  It is
+provided "as is" without express or implied warranty.
+
+ZERO-KNOWLEDGE SYSTEMS, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL ZERO-KNOWLEDGE SYSTEMS, INC. BE LIABLE FOR
+ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/krb5-1-6/src/lib/crypto/yarrow/Makefile.in b/krb5-1-6/src/lib/crypto/yarrow/Makefile.in
new file mode 100644
index 000000000..11257e32e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/Makefile.in
@@ -0,0 +1,64 @@
+thisconfigdir=../../..
+myfulldir=lib/crypto/yarrow
+mydir=lib/crypto/yarrow
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../sha1 -I$(srcdir)/../enc_provider
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=yarrow
+##DOS##OBJFILE=..\$(OUTPRE)yarrow.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
+
+STLIBOBJS=\
+	yarrow.o \
+	ycipher.o
+OBJS=\
+	$(OUTPRE)yarrow.$(OBJEXT) \
+	$(OUTPRE)ycipher.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/yarrow.c \
+	$(srcdir)/ycipher.c 
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+yarrow.so yarrow.po $(OUTPRE)yarrow.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../sha1/shs.h yarrow.c yarrow.h ycipher.h \
+  yexcep.h yhash.h ylock.h ystate.h ytypes.h
+ycipher.so ycipher.po $(OUTPRE)ycipher.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../enc_provider/enc_provider.h $(srcdir)/../sha1/shs.h \
+  yarrow.h ycipher.c ycipher.h yhash.h ytypes.h
diff --git a/krb5-1-6/src/lib/crypto/yarrow/README b/krb5-1-6/src/lib/crypto/yarrow/README
new file mode 100644
index 000000000..3dd4b801a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/README
@@ -0,0 +1,94 @@
+Yarrow - Secure Pseudo-Random Number Generator
+==============================================
+
+This is an implementation of the cryptographic pseudo-random number
+generator Yarrow.  You are encouraged to use, modify, and incorporate
+this code.  Please see the accompanying LICENSE file for more details.
+
+
+Yarrow can be used with OpenSSL 0.9.5a (http://www.openssl.org) and
+other cryptographic libraries.
+
+The Yarrow design is described in "Yarrow-160: Notes on the Design and
+Analysis of the Yarrow Cryptographic Pseudorandom Number Generator" by
+John Kelsey, Bruce Schneier and Niels Ferguson of Counterpane Systems,
+available from http://www.counterpane.com/yarrow.html
+
+The Yarrow function calls are described in the yarrow(3) manpage.
+
+Installation
+============
+
+By default, Yarrow is built with OpenSSL. If the OpenSSL headers are
+not installed in the standard directory /usr/local/ssl/include,
+set the path in the Makefile.
+
+If it is possible that an application using Yarrow will fork(), Yarrow
+must be compiled with -DYARROW_DETECT_FORK (then the child process
+will have to seed Yarrow again), or the Yarrow_CTX must be allocated
+in shared memory.
+
+If compiled with -DYARROW_SAVE_STATE, Yarrow will use a seed file
+specified in the Yarrow_Init call.
+
+When the settings in the Makefile are correct, run "make".
+
+
+Yarrow with OpenSSL:
+-------------------
+
+The macros YARROW_CIPHER_3DES (default), YARROW_CIPHER_BLOWFISH and
+YARROW_CIPHER_IDEA for ciphers and YARROW_HASH_SHA1 (default) and
+YARROW_HASH_MD5 for hash functions are available to select algorithms
+from OpenSSL.
+
+CRYPTO_set_locking_callback() is required in multithreaded applications.
+
+
+Yarrow with other cryptographic libraries:
+-----------------------------------------
+
+The Yarrow implementation uses a symmetric cipher, a cryptographic
+hash function and a mutex. By default, Yarrow calls OpenSSL. For use
+with other cryptographic libraries, the following types and macros
+should be defined:
+
+Symmetric cipher - ycipher.h:
+
+  typedef struct { ... } CIPHER_CTX;
+
+  #define CIPHER_BLOCK_SIZE ...
+  #define CIPHER_KEY_SIZE ...
+
+  void CIPHER_Init(CIPHER_CTX *ctx, void *key);
+  void CIPHER_Encrypt_Block(CIPHER_CTX *ctx, void *in, void *out);
+
+Hash function - yhash.h:
+
+  typedef struct { ... } HASH_CTX;
+
+  #define HASH_DIGEST_SIZE ...
+  #define HASH_STATE_SIZE ...
+
+  void HASH_Init(HASH_CTX *ctx);
+  void HASH_Update(HASH_CTX *ctx, const void *data, unsigned long size);
+  void HASH_Final(HASH_CTX *ctx, unsigned char *md);
+
+Mutex - ylock.h:
+
+  int LOCK(void);
+  int UNLOCK(void);
+
+Learn More:
+----------
+
+It is Zero-Knowledge's hope that third party developers of yarrow will
+collaborate to derive test vectors for yarrow.  In an effort to further
+this discussion, we have created a mailing list for developers and
+interested parties.  To subscribe, send an email to
+"yarrow-request@zeroknowledge.com" with "subscribe" in the body of the
+message.
+
+For more information, or if you have questions or comments regarding open
+source at Zero-Knowledge Systems, please visit
+http://opensource.zeroknowledge.com
diff --git a/krb5-1-6/src/lib/crypto/yarrow/TODO b/krb5-1-6/src/lib/crypto/yarrow/TODO
new file mode 100644
index 000000000..bd133ecfd
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/TODO
@@ -0,0 +1,9 @@
+open issues:
+
+* when should the initial seed be considered complete?
+* poll system ressources for randomness on startup?
+* how frequently should the PRNG state be saved?
+* how to react to fork()?
+* what should the seed file contain, how should it be processed?
+* test fork() hack
+* test openSSL locks in multi-threaded environment
diff --git a/krb5-1-6/src/lib/crypto/yarrow/yarrow.c b/krb5-1-6/src/lib/crypto/yarrow/yarrow.c
new file mode 100644
index 000000000..b52057daa
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/yarrow.c
@@ -0,0 +1,955 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+/*
+ * Yarrow - Cryptographic Pseudo-Random Number Generator
+ * Copyright (c) 2000 Zero-Knowledge Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * 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 Zero-Knowledge Systems,
+ * Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Zero-Knowledge Systems, Inc. makes no representations
+ * about the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ * 
+ * See the accompanying LICENSE file for more information.
+ */
+
+#include "k5-int.h"
+
+#include <string.h>
+#include <limits.h>
+#ifdef _WIN32
+#include "port-sockets.h"
+#else
+#   include <unistd.h>
+#   include <netinet/in.h>
+#endif
+#if !defined(YARROW_NO_MATHLIB)
+#include <math.h>
+#endif
+
+#define YARROW_IMPL
+#include "yarrow.h"
+#include "yhash.h"
+#include "ycipher.h"
+#include "ylock.h"
+#include "ystate.h"
+#include "yexcep.h"
+
+#if defined( YARROW_DEBUG ) || defined( YARROW_TRACE )
+#   include <stdio.h>
+#endif
+
+#if defined( YARROW_TRACE )
+extern int yarrow_verbose;
+#define TRACE( x ) do { if (yarrow_verbose) { x } } while (0)
+#else
+#define TRACE( x ) 
+#endif
+
+#if defined(macintosh)
+#   define make_big_endian32(x) (x)
+#else
+#   define make_big_endian32(x) htonl(x)
+#endif
+
+#if defined( YARROW_DEBUG )
+static void hex_print(FILE* f, const char* var, void* data, size_t size);
+#endif
+
+static void block_increment( void* block, const int sz );
+#if defined( YARROW_SAVE_STATE )
+static int Yarrow_Load_State( Yarrow_CTX *y );
+static int Yarrow_Save_State( Yarrow_CTX *y );
+#endif
+
+static int yarrow_gate_locked(Yarrow_CTX* y);
+
+static const byte zero_block[CIPHER_BLOCK_SIZE] = { 0, };
+
+static const char* const yarrow_str_error[] = {
+    "ok",
+    "failed",
+    "failed: uninitialized",
+    "failed: already initialized",
+    "failed: no driver",
+    "failed: can't open driver",
+    "failed: invalid source id",
+    "failed: no more source ids available",
+    "failed: invalid argument",
+    "failed: insufficient privileges",
+    "failed: out of memory",
+    "failed: resource exhausted",
+    "failed: not enough entropy to generate output",
+    "failed: locking error",
+    "failed: no state to load",
+    "failed: state load or save failed",
+    "failed: not implemented"
+};
+
+/* calculate limits after initialization */
+
+static void krb5int_yarrow_init_Limits(Yarrow_CTX* y)
+{
+    double tmp1, tmp2, limit;
+    /* max number of gates between reseeds -> exceed this, do forced reseed */
+
+    /* #oututs <= min(2^n, 2^(k/3).Pg) */
+
+    /* => #gates <= min(2^n/Pg, 2^(k/3)) */
+
+    tmp1 = POW_CIPHER_BLOCK_SIZE / y->Pg;
+    tmp2 = POW_CIPHER_KEY_SIZE;
+    limit = min(tmp1, tmp2);
+    if (limit < COUNTER_MAX)
+    {
+	y->gates_limit = limit;
+    }
+    else
+    {
+	y->gates_limit = COUNTER_MAX;
+    }
+}
+
+static int yarrow_reseed_locked( Yarrow_CTX* y, int pool );
+
+/* if the program was forked, the child must not operate on the same
+   PRNG state */
+#ifdef YARROW_DETECT_FORK
+
+static int
+yarrow_input_locked( Yarrow_CTX* y, unsigned source_id,
+		     const void *sample,
+		     size_t size, size_t entropy_bits );
+
+static int Yarrow_detect_fork(Yarrow_CTX *y)
+{
+    pid_t newpid;
+    EXCEP_DECL;
+
+    /* this does not work for multi-threaded apps if threads have different
+     * pids */
+       newpid = getpid();
+    if ( y->pid != newpid )
+    {
+	/* we input the pid twice, so it will get into the fast pool at least once
+	 * Then we reseed.  This doesn't really increase entropy, but does make the
+	 * streams distinct assuming we already have good entropy*/
+	y->pid = newpid;
+	TRY (yarrow_input_locked (y, 0, &newpid,
+				  sizeof (newpid), 0));
+	TRY (yarrow_input_locked (y, 0, &newpid,
+				  sizeof (newpid), 0));
+	TRY (yarrow_reseed_locked (y, YARROW_FAST_POOL));
+    }
+
+ CATCH:
+    EXCEP_RET;
+}
+
+#else
+
+#define Yarrow_detect_fork(x) (YARROW_OK)
+
+#endif
+
+static void Yarrow_Make_Seeded( Yarrow_CTX* y )
+{
+    TRACE( printf( "SEEDED," ); );
+    y->seeded = 1;
+
+    /* now we are seeded switch to _THRESH values */
+
+    y->slow_thresh = YARROW_SLOW_THRESH;
+    y->fast_thresh = YARROW_FAST_THRESH;
+    y->slow_k_of_n_thresh = YARROW_K_OF_N_THRESH;
+}
+
+YARROW_DLL
+int krb5int_yarrow_init(Yarrow_CTX* y, const char *filename)
+{
+    EXCEP_DECL;
+    int locked = 0;
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+    TRY( LOCK() );
+    locked = 1;
+
+    y->seeded = 0;
+    y->saved = 0;
+
+#if defined( YARROW_DETECT_FORK )
+    y->pid = getpid();
+#endif
+
+    y->entropyfile = filename;
+    y->num_sources = 0;
+    mem_zero(y->C, sizeof(y->C));
+    HASH_Init(&y->pool[YARROW_FAST_POOL]);
+    HASH_Init(&y->pool[YARROW_SLOW_POOL]);
+
+    mem_zero(y->K, sizeof(y->K));
+
+    mem_zero(&y->cipher, sizeof(y->cipher));
+
+    TRY (krb5int_yarrow_cipher_init(&y->cipher, y->K));
+    y->out_left = 0;
+    y->out_count = 0;
+    y->gate_count = 0;
+    y->Pg = YARROW_OUTPUTS_PER_GATE;
+    y->Pt[YARROW_FAST_POOL] = YARROW_FAST_PT;
+    y->Pt[YARROW_SLOW_POOL] = YARROW_SLOW_PT;
+    y->slow_k_of_n = 0;
+
+    /* start with INIT_THRESH values, after seeded, switch to THRESH values */
+
+    y->slow_thresh = YARROW_SLOW_INIT_THRESH;
+    y->fast_thresh = YARROW_FAST_INIT_THRESH;
+    y->slow_k_of_n_thresh = YARROW_K_OF_N_INIT_THRESH;
+
+    krb5int_yarrow_init_Limits(y);
+
+#if defined( YARROW_SAVE_STATE )
+    if ( y->entropyfile != NULL )
+    {
+	int ret = Yarrow_Load_State( y );
+	if ( ret != YARROW_OK && ret != YARROW_NO_STATE )
+	{
+	    THROW( ret );
+	}
+
+	/*  if load suceeded then write new state back immediately
+	 */
+
+	/*  Also check that it's not already saved, because the reseed in
+	 *  Yarrow_Load_State may trigger a save
+	 */
+
+	if ( ret == YARROW_OK && !y->saved )
+	{
+	    TRY( Yarrow_Save_State( y ) );
+	}
+    }
+#endif
+
+    if ( !y->seeded )
+    {
+	THROW( YARROW_NOT_SEEDED );
+    }
+
+ CATCH:
+    if ( locked ) { TRY( UNLOCK() ); }
+    EXCEP_RET;
+}
+
+static
+int yarrow_input_maybe_locking( Yarrow_CTX* y, unsigned source_id, 
+				const void* sample, 
+				size_t size, size_t entropy_bits,
+				int do_lock )
+{
+    EXCEP_DECL;
+    int ret;
+    int locked = 0;
+    Source* source;
+    size_t new_entropy;
+    size_t estimate;
+  
+    if (do_lock) {
+	    TRY( LOCK() );
+	    locked = 1;
+    }
+    k5_assert_locked(&krb5int_yarrow_lock);
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+
+    if (source_id >= y->num_sources) { THROW( YARROW_BAD_SOURCE ); }
+  
+    source = &y->source[source_id];
+
+    if(source->pool != YARROW_FAST_POOL && source->pool != YARROW_SLOW_POOL)
+    {
+	THROW( YARROW_BAD_SOURCE );
+    }
+
+    /* hash in the sample */
+
+    HASH_Update(&y->pool[source->pool], (const void*)sample, size);
+  
+    /* only update entropy estimate if pool is not full */
+
+    if ( (source->pool == YARROW_FAST_POOL && 
+	  source->entropy[source->pool] < y->fast_thresh) ||
+	 (source->pool == YARROW_SLOW_POOL &&
+	  source->entropy[source->pool] < y->slow_thresh) )
+    {
+	new_entropy = min(entropy_bits, size * 8 * YARROW_ENTROPY_MULTIPLIER);
+	if (source->estimator)
+	{
+	    estimate = source->estimator(sample, size);
+	    new_entropy = min(new_entropy, estimate);
+	}
+	source->entropy[source->pool] += new_entropy;
+	if ( source->entropy[source->pool] > YARROW_POOL_SIZE )
+	{
+	    source->entropy[source->pool] = YARROW_POOL_SIZE;
+	}
+
+	if (source->pool == YARROW_FAST_POOL)
+	{
+	    if (source->entropy[YARROW_FAST_POOL] >= y->fast_thresh)
+	    {
+		ret = yarrow_reseed_locked(y, YARROW_FAST_POOL);
+		if ( ret != YARROW_OK && ret != YARROW_NOT_SEEDED )
+		{
+		    THROW( ret );
+		}
+	    }
+	}
+	else
+	{
+	    if (!source->reached_slow_thresh && 
+		source->entropy[YARROW_SLOW_POOL] >= y->slow_thresh)
+	    {
+		source->reached_slow_thresh = 1;
+		y->slow_k_of_n++;
+		if (y->slow_k_of_n >= y->slow_k_of_n_thresh)
+		{
+		    y->slow_k_of_n = 0;
+		    ret = yarrow_reseed_locked(y, YARROW_SLOW_POOL);
+		    if ( ret != YARROW_OK && ret != YARROW_NOT_SEEDED )
+		    {
+			THROW( ret );
+		    }
+		}
+	    }
+	}
+    }
+  
+    /* put samples in alternate pools */
+
+    source->pool = (source->pool + 1) % 2;
+  
+ CATCH:
+    if ( locked ) { TRY( UNLOCK() ); }
+    EXCEP_RET;
+}
+
+YARROW_DLL
+int krb5int_yarrow_input( Yarrow_CTX* y, unsigned source_id, 
+		  const void* sample, 
+		  size_t size, size_t entropy_bits )
+{
+    return yarrow_input_maybe_locking(y, source_id, sample, size,
+				      entropy_bits, 1);
+}
+
+static int
+yarrow_input_locked( Yarrow_CTX* y, unsigned source_id,
+		     const void *sample,
+		     size_t size, size_t entropy_bits )
+{
+    return yarrow_input_maybe_locking(y, source_id, sample, size,
+				      entropy_bits, 0);
+}
+
+YARROW_DLL
+int krb5int_yarrow_new_source(Yarrow_CTX* y, unsigned* source_id)
+{
+    EXCEP_DECL;
+    int locked = 0;
+    Source* source;
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+
+    TRY( LOCK() );
+    locked = 1;
+
+    if (y->num_sources + 1 > YARROW_MAX_SOURCES)
+    {
+	THROW( YARROW_TOO_MANY_SOURCES );
+    }
+
+    *source_id = y->num_sources;
+
+    source = &y->source[*source_id];
+
+    source->pool = YARROW_FAST_POOL;
+    source->entropy[YARROW_FAST_POOL] = 0;
+    source->entropy[YARROW_SLOW_POOL] = 0;
+    source->reached_slow_thresh = 0;
+    source->estimator = 0;
+
+    y->num_sources++;
+CATCH:
+    if ( locked ) { TRY( UNLOCK() ); }
+    EXCEP_RET;
+}
+
+int krb5int_yarrow_register_source_estimator(Yarrow_CTX* y, unsigned source_id, 
+                                     estimator_fn* fptr)
+{
+    EXCEP_DECL;
+    Source* source;
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+    if (source_id >= y->num_sources) { THROW( YARROW_BAD_SOURCE ); }
+
+    source = &y->source[source_id];
+
+    source->estimator = fptr;
+  
+ CATCH:
+    EXCEP_RET;
+}
+
+static int krb5int_yarrow_output_Block( Yarrow_CTX* y, void* out )
+{
+    EXCEP_DECL;
+
+    if (!y || !out) { THROW( YARROW_BAD_ARG ); }
+
+    TRACE( printf( "OUT," ); );
+
+    /* perform a gate function after Pg outputs */
+
+    y->out_count++;
+    if (y->out_count >= y->Pg)
+    {
+	y->out_count = 0;
+	TRY( yarrow_gate_locked( y ) );
+
+	/* require new seed after reaching gates_limit */
+
+	y->gate_count++;
+	if ( y->gate_count >= y->gates_limit )
+	{
+	    y->gate_count = 0;
+	    
+	    /* not defined whether to do slow or fast reseed */ 
+	    
+	    TRACE( printf( "OUTPUT LIMIT REACHED," ); );
+
+	    TRY( yarrow_reseed_locked( y, YARROW_SLOW_POOL ) );
+	}
+    }
+  
+    /* C <- (C + 1) mod 2^n */
+
+    block_increment( y->C, CIPHER_BLOCK_SIZE );
+
+    /* R <- E_k(C) */
+
+    TRY ( krb5int_yarrow_cipher_encrypt_block ( &y->cipher, y->C, out ));
+
+#if defined(YARROW_DEBUG)
+    printf("===\n");
+    hex_print( stdout, "output: C", y->C, CIPHER_BLOCK_SIZE );
+    hex_print( stdout, "output: K", y->K, CIPHER_KEY_SIZE );
+    hex_print( stdout, "output: O", out, CIPHER_BLOCK_SIZE );
+#endif
+ CATCH:
+    EXCEP_RET;
+}
+
+YARROW_DLL
+int krb5int_yarrow_status( Yarrow_CTX* y, int *num_sources, unsigned *source_id,
+		   size_t *entropy_bits, size_t *entropy_max )
+{
+    EXCEP_DECL;
+    int num = y->slow_k_of_n_thresh;
+    int source = -1;
+    int emax = y->slow_thresh;
+    size_t entropy = 0;
+    unsigned i;
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+    TRY( Yarrow_detect_fork( y ) );
+
+    if (num_sources) { *num_sources = num; }
+    if (source_id) { *source_id = -1; }
+    if (entropy_bits) { *entropy_bits = 0; }
+    if (entropy_max) { *entropy_max = emax; }
+
+    if (y->seeded)
+    {
+	if (num_sources) { *num_sources = 0; }
+	if (entropy_bits) { *entropy_bits = emax; }
+	THROW( YARROW_OK );
+    }
+
+    for (i = 0; i < y->num_sources; i++)
+    {
+	if (y->source[i].entropy[YARROW_SLOW_POOL] >= y->slow_thresh)
+	{
+	    num--;
+	}
+	else if (y->source[i].entropy[YARROW_SLOW_POOL] > entropy)
+	{
+	    source = i;
+	    entropy = y->source[i].entropy[YARROW_SLOW_POOL];
+	}
+    }
+
+    if (num_sources) { *num_sources = num; }
+    if (source_id) { *source_id = source; }
+    if (entropy_bits) { *entropy_bits = entropy; }
+    THROW( YARROW_NOT_SEEDED );
+
+ CATCH:
+    EXCEP_RET;
+}
+
+static int yarrow_output_locked(Yarrow_CTX*, void*, size_t);
+
+YARROW_DLL
+int krb5int_yarrow_output( Yarrow_CTX* y, void* out, size_t size )
+{
+    EXCEP_DECL;
+    TRY( LOCK() );
+    TRY( yarrow_output_locked(y, out, size));
+CATCH:
+    UNLOCK();
+    EXCEP_RET;
+}
+
+static
+int yarrow_output_locked( Yarrow_CTX* y, void* out, size_t size )
+{
+    EXCEP_DECL;
+    size_t left;
+    char* outp;
+    size_t use;
+
+    if (!y || !out) { THROW( YARROW_BAD_ARG ); }
+    TRY( Yarrow_detect_fork( y ) );
+
+    if (!y->seeded) { THROW( YARROW_NOT_SEEDED ); }
+
+    left = size;
+    outp = out;
+
+    if (y->out_left > 0)
+    {
+	use = min(left, y->out_left);
+	mem_copy(outp, y->out + CIPHER_BLOCK_SIZE - y->out_left, use);
+	left -= use;
+	y->out_left -= use;
+	outp += use;
+    }
+
+    for ( ; 
+	  left >= CIPHER_BLOCK_SIZE;
+	  left -= CIPHER_BLOCK_SIZE, outp += CIPHER_BLOCK_SIZE)
+    {
+	TRY( krb5int_yarrow_output_Block(y, outp) );
+    }
+
+    if (left > 0)
+    {
+	TRY( krb5int_yarrow_output_Block(y, y->out) );
+	mem_copy(outp, y->out, left);
+	y->out_left = CIPHER_BLOCK_SIZE - left;
+    }
+
+ CATCH:
+    EXCEP_RET;
+}
+
+static int yarrow_gate_locked(Yarrow_CTX* y)
+{
+    EXCEP_DECL;
+    byte new_K[CIPHER_KEY_SIZE];
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+  
+    TRACE( printf( "GATE[" ); );
+
+    /* K <- Next k bits of PRNG output */
+
+    TRY( yarrow_output_locked(y, new_K, CIPHER_KEY_SIZE) );
+    mem_copy(y->K, new_K, CIPHER_KEY_SIZE);
+
+    /* need to resetup the key schedule as the key has changed */
+
+    TRY (krb5int_yarrow_cipher_init(&y->cipher, y->K));
+
+ CATCH:
+    TRACE( printf( "]," ); );
+    mem_zero(new_K, sizeof(new_K));
+    EXCEP_RET;
+}
+
+int krb5int_yarrow_gate(Yarrow_CTX* y)
+{
+    EXCEP_DECL;
+    byte new_K[CIPHER_KEY_SIZE];
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+  
+    TRACE( printf( "GATE[" ); );
+
+    /* K <- Next k bits of PRNG output */
+
+    TRY( krb5int_yarrow_output(y, new_K, CIPHER_KEY_SIZE) );
+    mem_copy(y->K, new_K, CIPHER_KEY_SIZE);
+
+    /* need to resetup the key schedule as the key has changed */
+
+    TRY (krb5int_yarrow_cipher_init(&y->cipher, y->K));
+
+ CATCH:
+    TRACE( printf( "]," ); );
+    mem_zero(new_K, sizeof(new_K));
+    EXCEP_RET;
+}
+
+#if defined( YARROW_SAVE_STATE )
+static int Yarrow_Load_State( Yarrow_CTX *y )
+{
+    EXCEP_DECL;
+    Yarrow_STATE state;
+    
+    if ( !y ) { THROW( YARROW_BAD_ARG ); }
+
+    if ( y->entropyfile )
+    {
+	TRY( STATE_Load(y->entropyfile, &state) );
+	TRACE( printf( "LOAD STATE," ); );
+
+#if defined( YARROW_DEBUG )
+	hex_print( stderr, "state.load", state.seed, sizeof(state.seed));
+#endif
+    
+	/* what to do here is not defined by the Yarrow paper */
+	/* this is a place holder until we get some clarification */
+    
+	HASH_Update( &y->pool[YARROW_FAST_POOL], 
+		     state.seed, sizeof(state.seed) );
+
+	Yarrow_Make_Seeded( y );
+
+	TRY( krb5int_yarrow_reseed(y, YARROW_FAST_POOL) );
+    }
+ CATCH:
+    mem_zero(state.seed, sizeof(state.seed));
+    EXCEP_RET;
+}
+
+static int Yarrow_Save_State( Yarrow_CTX *y )
+{
+    EXCEP_DECL;
+    Yarrow_STATE state;
+    
+    if ( !y ) { THROW( YARROW_BAD_ARG ); }
+
+    if ( y->entropyfile && y->seeded ) 
+    {
+	TRACE( printf( "SAVE STATE[" ); );
+	TRY( krb5int_yarrow_output( y, state.seed, sizeof(state.seed) ) );
+	TRY( STATE_Save(y->entropyfile, &state) );
+    }
+    y->saved = 1;
+# if defined(YARROW_DEBUG)
+    hex_print(stdout, "state.save", state.seed, sizeof(state.seed));
+# endif
+
+ CATCH:
+    TRACE( printf( "]," ); );
+    mem_zero(state.seed, sizeof(state.seed));
+    EXCEP_RET;
+}
+
+#endif
+
+static int yarrow_reseed_locked(Yarrow_CTX* y, int pool)
+{
+    EXCEP_DECL;
+    HASH_CTX* fast_pool;
+    HASH_CTX* slow_pool;
+    byte digest[HASH_DIGEST_SIZE];
+    HASH_CTX hash;
+    byte v_0[HASH_DIGEST_SIZE];
+    byte v_i[HASH_DIGEST_SIZE];
+    krb5_ui_4 big_endian_int32;
+    COUNTER i;
+
+    k5_assert_locked(&krb5int_yarrow_lock);
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+    fast_pool = &y->pool[YARROW_FAST_POOL];
+    slow_pool = &y->pool[YARROW_SLOW_POOL];
+    if( pool != YARROW_FAST_POOL && pool != YARROW_SLOW_POOL )
+    {
+	THROW( YARROW_BAD_ARG );
+    }
+  
+    TRACE( printf( "%s RESEED,", 
+		   pool == YARROW_SLOW_POOL ? "SLOW" : "FAST" ); );
+
+    if (pool == YARROW_SLOW_POOL)
+    {
+	/* SLOW RESEED */
+
+	/* feed hash of slow pool into the fast pool */
+
+
+	HASH_Final(slow_pool, digest);
+
+	/*  Each pool contains the running hash of all inputs fed into it
+	 *  since it was last used to carry out a reseed -- this implies
+	 *  that the pool must be reinitialized after a reseed
+	 */
+
+	HASH_Init(slow_pool);    /* reinitialize slow pool */
+	HASH_Update(fast_pool, digest, sizeof(digest));
+
+	if (y->seeded == 0)
+	{
+	    Yarrow_Make_Seeded( y );
+	}
+    }
+
+    /* step 1. v_0 <- hash of all inputs into fast pool */
+
+    HASH_Final(fast_pool, &v_0);
+    HASH_Init(fast_pool);    /* reinitialize fast pool */ 
+
+    /* v_i <- v_0 */
+
+    mem_copy( v_i, v_0, sizeof(v_0) );
+
+    /* step 2. v_i = h(v_{i-1}|v_0|i) for i = 1,..,Pt */
+
+    /* note: this code has to work for Pt = 0 also */
+
+    for ( i = 0; i < y->Pt[pool]; i++ )
+    {
+	HASH_Init(&hash);
+	HASH_Update(&hash, v_i, sizeof(v_i));
+	HASH_Update(&hash, v_0, sizeof(v_0));
+	big_endian_int32 = make_big_endian32(0); /* MS word */
+	HASH_Update(&hash, &big_endian_int32, sizeof(krb5_ui_4));
+	big_endian_int32 = make_big_endian32(i & 0xFFFFFFFF); /* LS word */
+	HASH_Update(&hash, &big_endian_int32, sizeof(krb5_ui_4));
+	HASH_Final(&hash, &v_i);
+    }
+
+    /* step3. K = h'(h(v_Pt|K)) */
+
+    /* t = h(v_Pt|K) */
+
+    HASH_Init(&hash);
+    HASH_Update(&hash, v_i, sizeof(v_i));
+    HASH_Update(&hash, y->K, sizeof(y->K));
+    HASH_Final(&hash, v_i);
+
+#if defined(YARROW_DEBUG)
+    hex_print(stdout, "old K", y->K, sizeof(y->K));
+#endif
+    /* K <- h'(t) */
+
+    TRY( krb5int_yarrow_stretch(v_i, HASH_DIGEST_SIZE, y->K, CIPHER_KEY_SIZE) );
+
+    /* need to resetup the key schedule as the key has changed */
+
+    TRY(krb5int_yarrow_cipher_init(&y->cipher, y->K));
+
+#if defined(YARROW_DEBUG)
+    hex_print(stdout, "new K", y->K, sizeof(y->K));
+#endif
+
+    /* step 4. C <- E_k(0) */
+
+#if defined(YARROW_DEBUG)
+    hex_print(stdout, "old C", y->C, sizeof(y->C));
+#endif
+    TRY (krb5int_yarrow_cipher_encrypt_block (&y->cipher, zero_block, y->C));
+#if defined(YARROW_DEBUG)
+    hex_print(stdout, "new C", y->C, sizeof(y->C));
+#endif
+
+    /* discard part output from previous key */
+  
+    y->out_left = 0;
+
+    /*   step 5. Reset all entropy estimate accumulators of the entropy
+     *   accumulator to zero
+     */
+
+    for (i = 0; i < y->num_sources; i++)
+    {
+	y->source[i].entropy[pool] = 0;
+	if (pool == YARROW_SLOW_POOL)
+	{
+    /*   if this is a slow reseed, reset the fast pool entropy
+     *   accumulator also
+     */
+	    y->source[i].entropy[YARROW_FAST_POOL] = 0;
+	    y->source[i].reached_slow_thresh = 0;
+	}
+    }
+
+    /*  step 7. If a seed file is in use, the next 2k bits of output
+     *  are written to the seed file
+     */
+
+#if defined( YARROW_SAVE_STATE )
+    if ( y->seeded && y->entropyfile )
+    {
+	TRY( Yarrow_Save_State( y ) );
+    }
+#endif
+
+ CATCH:
+    /*   step 6. Wipe the memory of all intermediate values
+     *
+     */
+
+    mem_zero( digest, sizeof(digest) );
+    mem_zero( &hash, sizeof(hash) );
+    mem_zero( v_0, sizeof(v_0) );
+    mem_zero( v_i, sizeof(v_i) );
+
+    EXCEP_RET;
+}
+int krb5int_yarrow_reseed(Yarrow_CTX* y, int pool)
+{
+	int r;
+	LOCK();
+	r = yarrow_reseed_locked(y, pool);
+	UNLOCK();
+	return r;
+}
+
+int krb5int_yarrow_stretch(const byte* m, size_t size, byte* out, size_t out_size)
+{
+    EXCEP_DECL;
+    const byte* s_i;
+    byte* outp;
+    int left;
+    unsigned int use;
+    HASH_CTX hash, save;
+    byte digest[HASH_DIGEST_SIZE];
+  
+    if (m == NULL || size == 0 || out == NULL || out_size == 0)
+    {
+	THROW( YARROW_BAD_ARG );
+    }
+  
+    /* 
+     *   s_0 = m
+     *   s_1 = h(s_0 | ... | s_{i-1})
+     *
+     *   h'(m, k) = first k bits of (s_0 | s_1 | ...)
+     *
+     */
+
+    outp = out;
+    left = out_size;
+  
+    use = min(out_size, size);
+    mem_copy(outp, m, use);    /* get k bits or as many as available */
+
+    s_i = (const byte*)m;            /* pointer to s0 = m */
+    outp += use;
+    left -= use;
+
+    HASH_Init(&hash);
+    for ( ;
+	  left > 0;
+	  left -= HASH_DIGEST_SIZE)
+    {
+	HASH_Update(&hash, s_i, use);
+    
+	/* have to save hash state to one side as HASH_final changes state */
+
+	mem_copy(&save, &hash, sizeof(hash));
+	HASH_Final(&hash, digest);
+
+	use = min(HASH_DIGEST_SIZE, left);
+	mem_copy(outp, digest, use);
+
+	/* put state back for next time */
+
+	mem_copy(&hash, &save, sizeof(hash));
+
+	s_i = outp;            /* retain pointer to s_i */
+	outp += use;
+    }
+  
+ CATCH:
+    mem_zero(&hash, sizeof(hash));
+    mem_zero(digest, sizeof(digest));
+
+    EXCEP_RET;
+}
+
+static void block_increment(void* block, const int sz)
+{
+    byte* b = block;
+    int i;
+  
+    for (i = sz-1; (++b[i]) == 0 && i > 0; i--)
+    {
+	; /* nothing */
+    }
+}
+
+YARROW_DLL
+int krb5int_yarrow_final(Yarrow_CTX* y)
+{
+    EXCEP_DECL;
+    int locked = 0;
+
+    if (!y) { THROW( YARROW_BAD_ARG ); }
+    TRY( LOCK() );
+    locked = 1;
+
+#if defined( YARROW_SAVE_STATE )
+    if ( y->seeded && y->entropyfile )
+    {
+	TRY( Yarrow_Save_State( y ) );
+    }
+#endif
+
+ CATCH:
+    krb5int_yarrow_cipher_final(&y->cipher);
+    mem_zero( y, sizeof(Yarrow_CTX) );
+    if ( locked ) { TRY( UNLOCK() ); }
+    EXCEP_RET;
+}
+
+YARROW_DLL
+const char* krb5int_yarrow_str_error( int err )
+{
+    err = 1-err;
+    if ( err < 0 || err >= sizeof( yarrow_str_error ) / sizeof( char* ) )
+    {
+	err = 1-YARROW_FAIL;
+    } 
+    return yarrow_str_error[ err ];
+}
+
+#if defined(YARROW_DEBUG)
+static void hex_print(FILE* f, const char* var, void* data, size_t size)
+{
+    const char* conv = "0123456789abcdef";
+    size_t i;
+    char* p = (char*) data;
+    char c, d;
+
+    fprintf(f, var);
+    fprintf(f, " = ");
+    for (i = 0; i < size; i++)
+    {
+	c = conv[(p[i] >> 4) & 0xf];
+	d = conv[p[i] & 0xf];
+	fprintf(f, "%c%c", c, d);
+    }
+    fprintf(f, "\n");
+}
+#endif
diff --git a/krb5-1-6/src/lib/crypto/yarrow/yarrow.h b/krb5-1-6/src/lib/crypto/yarrow/yarrow.h
new file mode 100644
index 000000000..7e1fe1442
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/yarrow.h
@@ -0,0 +1,186 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+#ifndef YARROW_H
+#define YARROW_H
+
+#ifdef HAVE_UNISTD_H
+#define YARROW_DETECT_FORK
+#include <unistd.h>
+#endif
+#define YARROW_NO_MATHLIB
+
+#include "ytypes.h"
+#include "yhash.h"
+#include "ycipher.h"
+
+/* These error codes are returned by the functions below. */
+
+#define YARROW_OK                1  /* All is well */
+#define YARROW_FAIL              0  /* generic failure */
+#define YARROW_NOT_INIT         -1  /* YarrowInit hasn't been called */
+#define YARROW_ALREADY_INIT     -2  /* YarrowInit has already been called */
+#define YARROW_NO_DRIVER        -3  /* driver doesn't exist */
+#define YARROW_CANT_OPEN        -4  /* can't open driver */
+#define YARROW_BAD_SOURCE       -5  /* invalid source id */
+#define YARROW_TOO_MANY_SOURCES -6  /* can't create any more source ids */
+#define YARROW_BAD_ARG          -7  /* invalid argument */
+#define YARROW_ACCESS           -8  /* insufficient privileges */
+#define YARROW_NOMEM            -9  /* out of memory */
+#define YARROW_NORSRC          -10  /* a resource is exhausted */
+#define YARROW_NOT_SEEDED      -11  /* not enough entropy to generate output */
+#define YARROW_LOCKING         -12  /* locking error */
+#define YARROW_NO_STATE        -13  /* there is no state to load */
+#define YARROW_STATE_ERROR     -14  /* error with state load or save */
+#define YARROW_NOT_IMPL        -15  /* not implemented */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Yarrow implementation and configuration parameters */
+
+/* pool identification */
+#define YARROW_FAST_POOL 0
+#define YARROW_SLOW_POOL 1
+
+#define YARROW_MAX_SOURCES 20
+#define YARROW_ENTROPY_MULTIPLIER 0.5
+
+#define YARROW_POOL_SIZE (HASH_DIGEST_SIZE*8)
+
+#define YARROW_OUTPUTS_PER_GATE 10   /* Pg */
+#define YARROW_FAST_PT 10
+#define YARROW_SLOW_PT 100
+
+/* thresholds to use once seeded */
+
+#define YARROW_FAST_THRESH 100
+#define YARROW_SLOW_THRESH 160
+#define YARROW_K_OF_N_THRESH 2
+
+/* The Yarrow paper does not specify when the initial seed should be
+   considered complete. Use the same conditions as a slow reseed */
+
+#define YARROW_FAST_INIT_THRESH YARROW_FAST_THRESH
+#define YARROW_SLOW_INIT_THRESH YARROW_SLOW_THRESH
+#define YARROW_K_OF_N_INIT_THRESH YARROW_K_OF_N_THRESH
+
+/* sanity checks */
+
+#if YARROW_FAST_THRESH > YARROW_POOL_SIZE
+error "can't have higher YARROW_FAST_THRESH than pool size"
+#endif
+
+#if YARROW_SLOW_THRESH > YARROW_POOL_SIZE
+error "can't have higher YARROW_SLOW_THRESH than pool size"
+#endif
+
+#if YARROW_FAST_INIT_THRESH > YARROW_POOL_SIZE
+error "can't have higher YARROW_FAST_INIT_THRESH than pool size"
+#endif
+
+#if YARROW_SLOW_INIT_THRESH > YARROW_POOL_SIZE
+error "can't have higher YARROW_SLOW_INIT_THRESH than pool size"
+#endif
+
+typedef size_t estimator_fn(const void* sample, size_t size);
+
+typedef struct
+{
+    int pool;
+    size_t entropy[2];
+    int reached_slow_thresh;
+    estimator_fn* estimator;
+} Source;
+
+typedef struct
+{
+    /* state */
+    int seeded;
+    int saved;
+#if defined( YARROW_DETECT_FORK )
+    int pid;
+#endif
+    Source source[YARROW_MAX_SOURCES];
+    unsigned num_sources;
+    HASH_CTX pool[2];
+    byte out[CIPHER_BLOCK_SIZE];
+    unsigned out_left;
+    COUNTER out_count;
+    COUNTER gate_count;
+    COUNTER gates_limit;
+    byte C[CIPHER_BLOCK_SIZE];
+    CIPHER_CTX cipher;
+    byte K[CIPHER_KEY_SIZE];
+
+    const char *entropyfile;
+
+    /* parameters */
+    COUNTER Pt[2];
+    COUNTER Pg;
+    int slow_k_of_n;
+
+    /* current thresholds */
+    int slow_thresh;
+    int fast_thresh;
+    int slow_k_of_n_thresh;
+} Yarrow_CTX;
+
+#   define YARROW_DLL
+
+
+YARROW_DLL
+int krb5int_yarrow_init( Yarrow_CTX* y, const char *filename );
+
+
+YARROW_DLL
+int krb5int_yarrow_input( Yarrow_CTX* y, unsigned source_id,
+		  const void* sample, 
+		  size_t size, size_t entropy_bits );
+
+YARROW_DLL
+int krb5int_yarrow_status( Yarrow_CTX* y, int *num_sources, unsigned *source_id,
+		   size_t *entropy_bits, size_t *entropy_max );
+
+YARROW_DLL
+int krb5int_yarrow_output( Yarrow_CTX* y, void* out, size_t size );
+
+YARROW_DLL
+int krb5int_yarrow_new_source( Yarrow_CTX* y, unsigned* source_id );
+
+YARROW_DLL
+int krb5int_yarrow_register_source_estimator( Yarrow_CTX* y, unsigned source_id, 
+				      estimator_fn* fptr );
+
+YARROW_DLL
+int krb5int_yarrow_stretch( const byte* m, size_t size, byte* out, size_t out_size );
+
+YARROW_DLL
+int krb5int_yarrow_reseed( Yarrow_CTX* y, int pool );
+
+YARROW_DLL
+int krb5int_yarrow_gate( Yarrow_CTX* y );
+
+YARROW_DLL
+int krb5int_yarrow_final( Yarrow_CTX* y );
+
+YARROW_DLL
+const char* krb5int_yarrow_str_error( int );
+
+
+#   define mem_zero(p, n)       memset((p), 0, (n))
+#   define mem_copy(d, s, n)    memcpy((d), (s), (n))
+
+
+#if !defined(WIN32)
+#   define min(x, y) ((x) < (y) ? (x) : (y))
+#   define max(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* YARROW_H */
diff --git a/krb5-1-6/src/lib/crypto/yarrow/yarrow.man b/krb5-1-6/src/lib/crypto/yarrow/yarrow.man
new file mode 100644
index 000000000..a65b4e05c
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/yarrow.man
@@ -0,0 +1,315 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+''' Revision 1.1  2001/11/08 21:51:57  hartmans
+''' Add Yarrow from http://www.zeroknowledge.com/.
+'''
+''' This is version 0.1 of their Yarrow implementation.  I have flattened the distribution,
+''' copying files in the src directory directly into this directory.
+'''
+''' Revision 1.1.2.1  2000/08/13 21:11:24  adamb
+''' added some more assumptions
+''' included yarrow.man derived from yarrow.pod with pod2man
+'''
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+'''     Set up \*(-- to give an unbreakable dash;
+'''     string Tr holds user defined translation string.
+'''     Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+'''   \*(L" and \*(R", except that they are used on ".xx" lines,
+'''   such as .IP and .SH, which do another additional levels of
+'''   double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\"	If the F register is turned on, we'll generate
+.\"	index entries out stderr for the following things:
+.\"		TH	Title 
+.\"		SH	Header
+.\"		Sh	Subsection 
+.\"		Ip	Item
+.\"		X<>	Xref  (embedded
+.\"	Of course, you have to process the output yourself
+.\"	in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH YARROW 1 "perl 5.005, patch 03" "13/Aug/2000" "User Contributed Perl Documentation"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ          \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+.	\" AM - accent mark definitions
+.bd B 3
+.	\" fudge factors for nroff and troff
+.if n \{\
+.	ds #H 0
+.	ds #V .8m
+.	ds #F .3m
+.	ds #[ \f1
+.	ds #] \fP
+.\}
+.if t \{\
+.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.	ds #V .6m
+.	ds #F 0
+.	ds #[ \&
+.	ds #] \&
+.\}
+.	\" simple accents for nroff and troff
+.if n \{\
+.	ds ' \&
+.	ds ` \&
+.	ds ^ \&
+.	ds , \&
+.	ds ~ ~
+.	ds ? ?
+.	ds ! !
+.	ds /
+.	ds q
+.\}
+.if t \{\
+.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+.	\" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+.	\" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.	\" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.	ds : e
+.	ds 8 ss
+.	ds v \h'-1'\o'\(aa\(ga'
+.	ds _ \h'-1'^
+.	ds . \h'-1'.
+.	ds 3 3
+.	ds o a
+.	ds d- d\h'-1'\(ga
+.	ds D- D\h'-1'\(hy
+.	ds th \o'bp'
+.	ds Th \o'LP'
+.	ds ae ae
+.	ds Ae AE
+.	ds oe oe
+.	ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+Yarrow_Init, Yarrow_Poll, Yarrow_Input, Yarrow_Status, Yarrow_Output, Yarrow_New_Source, Yarrow_Register_Source_Estimator, Yarrow Final \- cryptographic pseudo-random number generator
+.SH "SYNOPSIS"
+int \fIYarrow_Init\fR\|(Yarrow_CTX *y, const char *filename);
+.PP
+int \fIYarrow_New_Source\fR\|(Yarrow_CTX* y, unsigned* source_id);
+.PP
+int \fIYarrow_Poll\fR\|(Yarrow_CTX *y, unsigned source_id)
+.PP
+int \fIYarrow_Input\fR\|( Yarrow_CTX* y, unsigned source_id,
+       const void* sample, size_t size,
+       size_t entropy_bits);
+.PP
+int \fIYarrow_Status\fR\|(Yarrow_CTX* y, int *num_sources,
+       unsigned *source_id, size_t *entropy_bits,
+       size_t *entropy_max);
+.PP
+int \fIYarrow_Output\fR\|(Yarrow_CTX* y, void* out, size_t size);
+.PP
+int \fIYarrow_Register_Source_Estimator\fR\|(Yarrow_CTX* y,
+       unsigned source_id,
+       size_t (*estimator)(const void* sample,
+                           size_t size));
+.PP
+int \fIYarrow_Final\fR\|(Yarrow_CTX* y);
+.SH "DESCRIPTION"
+\fIYarrow_Init()\fR initializes a \fBYarrow_CTX\fR structure. \fBfilename\fR can
+be NULL, or the path to a seed file that Yarrow will use to store the
+PRNG state for use in later sessions.  Returns \fBYARROW_OK\fR if the
+PRNG is seeded on exit, or \fBYARROW_NOT_SEEDED\fR if the PRNG is not yet
+seeded.
+.PP
+\fIYarrow_New_Source()\fR associates entropy sources such as keyboard input,
+mouse movements and other unpredictable events with a
+\fBYarrow_CTX\fR. The function assigns a unique number to the new source,
+and places it in \fBsource_id\fR.
+.PP
+\fIYarrow_Poll()\fR gathers entropy from the state of the machine and adds
+it to the source \fBsource_id\fR.  The source has to be allocated by the
+user with Yarrow_New_Source.  Returns \fBYARROW_OK\fR if the PRNG is
+seeded on exit, or \fBYARROW_NOT_SEEDED\fR if the PRNG is not yet seeded.
+.PP
+\fIYarrow_Input()\fR is used to add randomness from the source \fBsource_id\fR
+to the PRNG. It reads \fBsize\fR bytes at the address \fBsample\fR. An
+estimate of the entropy in bits contained in the sample must be
+specified as \fBentropy_bits\fR.
+.PP
+\fIYarrow_Status()\fR returns \fBYARROW_OK\fR if the PRNG has enough entropy to
+produce output, and \fBYARROW_NOT_SEEDED\fR if calls to \fIYarrow_Output()\fR
+would fail.
+.PP
+If num_sources is not NULL, the number of entropy sources that still
+need to be seeded is returned in \fB*num_sources\fR.
+.PP
+If source_id is not NULL, the entropy source that is closest to its
+threshold is returned in \fB*source_id\fR.  \fB*source_id\fR is set to \-1 if
+no sources have either reached their threshold or not collected any
+entropy yet.
+.PP
+If not NULL, \fB*entropy_bits\fR is set to the current number of bits for
+the source \fB*source_id\fR, and \fB*entropy_max\fR to the threshold.
+.PP
+\fIYarrow_Output()\fR generates \fBsize\fR bytes of cryptographically strong
+pseudo-random output and places them at \fBout\fR. The return value must
+always be checked. If an error occurs, the PRNG may produce
+predictable data or no output at all.
+.PP
+\fIYarrow_Register_Source_Estimator()\fR registers an entropy estimator
+for \fBsource_id\fR. An entropy estimator is a function that tries to
+estimate the entropy in a sample and returns the entropy in bits
+in order to detect abnormal situations in which the samples have a very
+low entropy.
+.PP
+\fIYarrow_Final()\fR writes the PRNG state to the seed file and erases it
+from memory.
+.SH "RETURN VALUES"
+All functions return \fBYARROW_OK\fR on success. Error conditions are reported
+as follows:
+.PP
+.Vb 16
+\& YARROW_FAIL              generic failure
+\& YARROW_NOT_INIT          YarrowInit() hasn't been called
+\& YARROW_ALREADY_INIT      YarrowInit() has already been called
+\& YARROW_NO_DRIVER         driver doesn't exist
+\& YARROW_CANT_OPEN         can't open driver
+\& YARROW_BAD_SOURCE        invalid source id
+\& YARROW_TOO_MANY_SOURCES  can't create any more source IDs
+\& YARROW_BAD_ARG           invalid argument
+\& YARROW_ACCESS            insufficient privileges
+\& YARROW_NOMEM             out of memory
+\& YARROW_NORSRC            a resource (apart from memory) is exhausted
+\& YARROW_NOT_SEEDED        not enough entropy to generate output
+\& YARROW_LOCKING           locking error
+\& YARROW_NO_STATE          there is no state to load 
+\& YARROW_STATE_ERROR       error with state load or save
+\& YARROW_NOT_IMPL          not implemented
+.Ve
+.SH "AUTHORS"
+Yarrow was designed by John Kelsey, Bruce Schneier and Niels Ferguson
+of Counterpane Systems. This implementation is (C) 2000 by
+Zero-Knowledge Systems Inc.
+
+.rn }` ''
+.IX Title "YARROW 1"
+.IX Name "Yarrow_Init, Yarrow_Poll, Yarrow_Input, Yarrow_Status, Yarrow_Output, Yarrow_New_Source, Yarrow_Register_Source_Estimator, Yarrow Final - cryptographic pseudo-random number generator"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "RETURN VALUES"
+
+.IX Header "AUTHORS"
+
diff --git a/krb5-1-6/src/lib/crypto/yarrow/yarrow.pod b/krb5-1-6/src/lib/crypto/yarrow/yarrow.pod
new file mode 100644
index 000000000..7892ebbe6
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/yarrow.pod
@@ -0,0 +1,112 @@
+=pod
+
+=head1 NAME
+
+Yarrow_Init, Yarrow_Poll, Yarrow_Input, Yarrow_Status, Yarrow_Output, Yarrow_New_Source, Yarrow_Register_Source_Estimator, Yarrow Final - cryptographic pseudo-random number generator
+
+=head1 SYNOPSIS
+
+int Yarrow_Init(Yarrow_CTX *y, const char *filename);
+
+int Yarrow_New_Source(Yarrow_CTX* y, unsigned* source_id);
+
+int Yarrow_Poll(Yarrow_CTX *y, unsigned source_id)
+
+int Yarrow_Input( Yarrow_CTX* y, unsigned source_id,
+       const void* sample, size_t size,
+       size_t entropy_bits);
+
+int Yarrow_Status(Yarrow_CTX* y, int *num_sources,
+       unsigned *source_id, size_t *entropy_bits,
+       size_t *entropy_max);
+
+int Yarrow_Output(Yarrow_CTX* y, void* out, size_t size);
+
+int Yarrow_Register_Source_Estimator(Yarrow_CTX* y,
+       unsigned source_id,
+       size_t (*estimator)(const void* sample,
+                           size_t size));
+
+int Yarrow_Final(Yarrow_CTX* y);
+
+=head1 DESCRIPTION
+
+Yarrow_Init() initializes a B<Yarrow_CTX> structure. B<filename> can
+be NULL, or the path to a seed file that Yarrow will use to store the
+PRNG state for use in later sessions.  Returns B<YARROW_OK> if the
+PRNG is seeded on exit, or B<YARROW_NOT_SEEDED> if the PRNG is not yet
+seeded.
+
+Yarrow_New_Source() associates entropy sources such as keyboard input,
+mouse movements and other unpredictable events with a
+B<Yarrow_CTX>. The function assigns a unique number to the new source,
+and places it in B<source_id>.
+
+Yarrow_Poll() gathers entropy from the state of the machine and adds
+it to the source B<source_id>.  The source has to be allocated by the
+user with Yarrow_New_Source.  Returns B<YARROW_OK> if the PRNG is
+seeded on exit, or B<YARROW_NOT_SEEDED> if the PRNG is not yet seeded.
+
+Yarrow_Input() is used to add randomness from the source B<source_id>
+to the PRNG. It reads B<size> bytes at the address B<sample>. An
+estimate of the entropy in bits contained in the sample must be
+specified as B<entropy_bits>.
+
+Yarrow_Status() returns B<YARROW_OK> if the PRNG has enough entropy to
+produce output, and B<YARROW_NOT_SEEDED> if calls to Yarrow_Output()
+would fail.
+
+If num_sources is not NULL, the number of entropy sources that still
+need to be seeded is returned in B<*num_sources>.
+
+If source_id is not NULL, the entropy source that is closest to its
+threshold is returned in B<*source_id>.  B<*source_id> is set to -1 if
+no sources have either reached their threshold or not collected any
+entropy yet.
+
+If not NULL, B<*entropy_bits> is set to the current number of bits for
+the source B<*source_id>, and B<*entropy_max> to the threshold.
+
+Yarrow_Output() generates B<size> bytes of cryptographically strong
+pseudo-random output and places them at B<out>. The return value must
+always be checked. If an error occurs, the PRNG may produce
+predictable data or no output at all.
+
+Yarrow_Register_Source_Estimator() registers an entropy estimator
+for B<source_id>. An entropy estimator is a function that tries to
+estimate the entropy in a sample and returns the entropy in bits
+in order to detect abnormal situations in which the samples have a very
+low entropy.
+
+Yarrow_Final() writes the PRNG state to the seed file and erases it
+from memory.
+
+=head1 RETURN VALUES
+
+All functions return B<YARROW_OK> on success. Error conditions are reported
+as follows:
+
+ YARROW_FAIL              generic failure
+ YARROW_NOT_INIT          YarrowInit() hasn't been called
+ YARROW_ALREADY_INIT      YarrowInit() has already been called
+ YARROW_NO_DRIVER         driver doesn't exist
+ YARROW_CANT_OPEN         can't open driver
+ YARROW_BAD_SOURCE        invalid source id
+ YARROW_TOO_MANY_SOURCES  can't create any more source IDs
+ YARROW_BAD_ARG           invalid argument
+ YARROW_ACCESS            insufficient privileges
+ YARROW_NOMEM             out of memory
+ YARROW_NORSRC            a resource (apart from memory) is exhausted
+ YARROW_NOT_SEEDED        not enough entropy to generate output
+ YARROW_LOCKING           locking error
+ YARROW_NO_STATE          there is no state to load 
+ YARROW_STATE_ERROR       error with state load or save
+ YARROW_NOT_IMPL          not implemented
+
+=head1 AUTHORS
+
+Yarrow was designed by John Kelsey, Bruce Schneier and Niels Ferguson
+of Counterpane Systems. This implementation is (C) 2000 by
+Zero-Knowledge Systems Inc.
+
+=cut
diff --git a/krb5-1-6/src/lib/crypto/yarrow/ycipher.c b/krb5-1-6/src/lib/crypto/yarrow/ycipher.c
new file mode 100644
index 000000000..01d105ffe
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/ycipher.c
@@ -0,0 +1,96 @@
+/*
+ * lib/crypto/yarrow/ycipher.c
+ *
+ * Copyright (C) 2001 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 
+ *
+ *  Routines  to implement krb5 cipher operations.
+ */
+#include "k5-int.h"
+#include "yarrow.h"
+#include "ycipher.h"
+#include "enc_provider.h"
+#include "assert.h"
+
+int
+krb5int_yarrow_cipher_init
+(CIPHER_CTX *ctx,
+ unsigned const char * key)
+{
+  size_t keybytes, keylength;
+  const struct krb5_enc_provider *enc = &yarrow_enc_provider;
+  krb5_error_code ret;
+  krb5_data randombits;
+  keybytes = enc->keybytes;
+  keylength = enc->keylength;
+  assert (keybytes == CIPHER_KEY_SIZE);
+  if (ctx->key.contents) {
+    memset (ctx->key.contents, 0, ctx->key.length);
+    free (ctx->key.contents);
+  }
+  ctx->key.contents = (void *) malloc  (keylength);
+  ctx->key.length = keylength;
+  if (ctx->key.contents == NULL)
+    return (YARROW_NOMEM);
+  randombits.data = (char *) key;
+  randombits.length = keybytes;
+  ret = enc->make_key (&randombits, &ctx->key);
+  if (ret) {
+    memset (ctx->key.contents, 0, ctx->key.length);
+    free(ctx->key.contents);
+    ctx->key.contents = NULL;
+    return (YARROW_FAIL);
+  }
+  return (YARROW_OK);
+}
+
+int krb5int_yarrow_cipher_encrypt_block
+(CIPHER_CTX *ctx, const unsigned char *in,
+ unsigned char *out)
+{
+  krb5_error_code ret;
+  krb5_data ind, outd;
+  const struct krb5_enc_provider *enc = &yarrow_enc_provider;
+  ind.data = (char *) in;
+  ind.length = CIPHER_BLOCK_SIZE;
+  outd.data = out;
+  outd.length = CIPHER_BLOCK_SIZE;
+  ret = enc->encrypt (&ctx->key, 0, &ind, &outd);
+  if (ret)
+    return YARROW_FAIL;
+  return YARROW_OK;
+}
+
+void
+krb5int_yarrow_cipher_final
+(CIPHER_CTX *ctx)
+
+{
+ if (ctx->key.contents) {
+    memset (ctx->key.contents, 0, ctx->key.length);
+    free (ctx->key.contents);
+  }
+  ctx->key.contents = 0;
+  ctx->key.length = 0;
+}
diff --git a/krb5-1-6/src/lib/crypto/yarrow/ycipher.h b/krb5-1-6/src/lib/crypto/yarrow/ycipher.h
new file mode 100644
index 000000000..96999c0db
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/ycipher.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+#ifndef YCIPHER_H
+#define YCIPHER_H
+
+/* block cipher interface */
+
+typedef struct 
+{
+    krb5_keyblock key;
+} CIPHER_CTX;
+
+/* We need to choose a cipher. To do this, choose an enc_provider.
+ * Be sure to update the block size and key size constants below;
+ * they are here because static data structures are sized based on
+ * them so they must be known at compile time./  Thus we cannot
+ * call the enc_provider function to get the info.
+ */
+
+#define yarrow_enc_provider krb5int_enc_aes256
+
+#define CIPHER_BLOCK_SIZE 16
+#define CIPHER_KEY_SIZE 32
+
+#if defined( YARROW_NO_MATHLIB )
+/* see macros at end for functions evaluated */
+#define POW_CIPHER_KEY_SIZE    115792089237316195423570985008687907853269984665640564039457584007913129639936.0
+#define POW_CIPHER_BLOCK_SIZE  340282366920938463463374607431768211456.0
+#endif
+
+
+int krb5int_yarrow_cipher_init (CIPHER_CTX *ctx, unsigned const char *key);
+int krb5int_yarrow_cipher_encrypt_block
+(CIPHER_CTX *ctx,  const unsigned char *in, unsigned char *out);
+void krb5int_yarrow_cipher_final (CIPHER_CTX *ctx);
+
+#if !defined( YARROW_NO_MATHLIB )
+#define POW_CIPHER_KEY_SIZE pow(2.0, CIPHER_KEY_SIZE * 8 / 3.0)
+#define POW_CIPHER_BLOCK_SIZE pow(2.0, CIPHER_BLOCK_SIZE * 8)
+#endif
+
+#endif /* YCIPHER_H */
diff --git a/krb5-1-6/src/lib/crypto/yarrow/yexcep.h b/krb5-1-6/src/lib/crypto/yarrow/yexcep.h
new file mode 100644
index 000000000..d27de2d5e
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/yexcep.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+#ifndef YEXCEP_H
+#define YEXCEP_H
+
+/*   yes, macros with gotos in them, but in the interests of
+ *   avoiding repetition of code, and having less error prone
+ *   error handling
+ *
+ *   EXCEP_DECL - declares the return value and local state variables
+ *                needed by the exception macros
+ *
+ *   THROW( x ) - set return value to x and goto function cleanup
+ *                section (CATCH: block).  In the catch block, THROW
+ *                does not goto catch label to avoid loops, and instead
+ *                falls through to the next statement.
+ *
+ *   EXCEP_OK   - success return value (=1)
+ *
+ *   EXCEP_FAIL - failure return value (=0), other user exceptions are 
+ *                given negative values (<0)
+ *
+ *   TRY( x )   - if code returns value <= 0 TRY sets return value to 
+ *                that value and goes to function cleanup section 
+ *                (CATCH: block).  In the catch block, TRY does not goto
+ *                the catch label to avoid loops, and instead
+ *                falls through to the next statement.  The
+ *                return value is set to the first non success value
+ *                returned by a TRY, unless this is overridden by a THROW.
+ *
+ *   CATCH:     - start of catch block, also switches behavior of 
+ *                TRY and THROW to not goto CATCH: inside the catch
+ *                block to avoid loops
+ *
+ *   EXCEP_RET  - return the current return value from the function
+ *                equivlanet to return (EXCEPTION)
+ *
+ *   EXCEPTION  - current return value, is set to EXCEP_OK by EXCEP_DECL
+ *
+ *   EXCEP_BOOL - convert current return value to EXCEP_OK, or EXCEP_FAIL
+ *                (EXCEP_FAIL is anything other than EXCEP_OK)
+ *
+ */
+
+/* example usage */
+
+/*
+ * 
+ * #define EXCEP_OK_COMMENT 2
+ * #define EXCEP_NULL_PTR -1
+ * #define EXCEP_OUT_OF_MEM -2
+ * 
+ * int bar( char *c )
+ * {
+ *     EXCEP_DECL;
+ * 
+ *     if ( !c ) { THROW( EXCEP_NULL_PTR ); }
+ *     if ( *c == '\0' ) { THROW( EXCEP_FAIL ); );
+ *     if ( *c == '#' ) { SET( EXCEP_COMMENT ); }
+ *  CATCH:
+ *     EXCEP_RET;
+ * }
+ * 
+ * int foo( char *c )
+ * {
+ *     EXCEP_DECL;
+ *     int *p = NULL;
+ * 
+ *     if ( !c ) { THROW( EXCEP_NULL_PTR ); }
+ *     TRY( bar( c ) );
+ *     if ( RETURN == EXCEP_COMMENT ) { print( "comment\n" ); }
+ *     p = strdup( c );
+ *     if ( !p ) { THROW( EXCEP_OUT_OF_MEM ); }
+ * 
+ *  CATCH:
+ *     if ( p ) { TRY( bar( p ) ); free( p ); }
+ *     THROW( EXCEP_BOOL );
+ *     if ( EXCEPTION == EXCEP_OK ) { printf( "success\n" ); }
+ *     EXCEP_RET;
+ * }
+ * 
+ */
+
+#define EXCEP_FAIL 0
+#define EXCEP_OK 1
+#define EXCEP_DECL int _thr = 0, _ret2 = 0, _ret = _ret2+EXCEP_OK
+
+#define THROW( x ) \
+    do { \
+        _ret = (x); \
+        if( !_thr ) { goto _catch; } \
+    } while ( 0 )
+
+#define TRY( x ) \
+    do { \
+        _ret2 = (x); \
+        if ( _ret > 0 && _ret2 <= 0 ) { THROW( _ret2 ); } \
+    } while ( 0 )
+
+#define SET( x ) (_ret = (x))
+#define EXCEP_RET return( _ret )
+#define EXCEPTION _ret
+#define RETURN _ret2
+#define CATCH _catch: _thr = 1; if ( 0 ) { goto _foo; } _foo
+#define EXCEP_BOOL ( _ret > 0 ? EXCEP_OK : EXCEP_FAIL )
+
+#endif
diff --git a/krb5-1-6/src/lib/crypto/yarrow/yhash.h b/krb5-1-6/src/lib/crypto/yarrow/yhash.h
new file mode 100644
index 000000000..aaa739fe1
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/yhash.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+#ifndef YHASH_H
+#define YHASH_H
+
+/* hash function interface */
+
+/* default to SHA1 for yarrow 160 */
+
+#include "shs.h"
+
+
+
+#define HASH_CTX SHS_INFO
+#define HASH_Init(x) shsInit(x)
+#define HASH_Update(x, buf, sz) shsUpdate(x, (const void*)buf, sz)
+#define HASH_Final(x, tdigest)  do { \
+  int loopvar; \
+  unsigned char *out2 = (void *)(tdigest); \
+  HASH_CTX  *ctx = (x); \
+  shsFinal(ctx); \
+for (loopvar=0; loopvar<(sizeof(ctx->digest)/sizeof(ctx->digest[0])); loopvar++) { \
+  out2[loopvar*4] = (ctx->digest[loopvar]>>24)&0xff; \
+  out2[loopvar*4+1] = (ctx->digest[loopvar]>>16)&0xff; \
+  out2[loopvar*4+2] = (ctx->digest[loopvar]>>8)&0xff; \
+  out2[loopvar*4+3] = ctx->digest[loopvar]&0xff; \
+} \
+  } while(0)
+
+
+#define HASH_DIGEST_SIZE SHS_DIGESTSIZE
+
+#endif /* YHASH_H */
diff --git a/krb5-1-6/src/lib/crypto/yarrow/ylock.h b/krb5-1-6/src/lib/crypto/yarrow/ylock.h
new file mode 100644
index 000000000..9c032dc61
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/ylock.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+#ifndef YLOCK_H
+#define YLOCK_H
+
+#include "yarrow.h"
+
+/* these functions should return:
+ *
+ *        YARROW_OK on success
+ *    and YARROW_LOCKING on failure
+ */
+
+#if 0
+static int LOCK( void ) {  return (YARROW_OK); }
+static int UNLOCK( void ) {  return (YARROW_OK); }
+#else
+#include "k5-thread.h"
+extern k5_mutex_t krb5int_yarrow_lock;
+#define LOCK()	(k5_mutex_lock(&krb5int_yarrow_lock) ? YARROW_LOCKING : YARROW_OK)
+#define UNLOCK() (k5_mutex_unlock(&krb5int_yarrow_lock) ? YARROW_LOCKING : YARROW_OK)
+#endif
+
+#endif /* YLOCK_H */
diff --git a/krb5-1-6/src/lib/crypto/yarrow/ystate.h b/krb5-1-6/src/lib/crypto/yarrow/ystate.h
new file mode 100644
index 000000000..2886ca338
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/ystate.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+#ifndef YSTATE_H
+#define YSTATE_H
+
+#ifdef YARROW_SAVE_STATE
+
+#include "ycipher.h"
+#include "ytypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Yarrow_STATE {
+    byte seed[CIPHER_KEY_SIZE * 2];    /* 2k bits saved to seed file */
+} Yarrow_STATE;
+
+int STATE_Save( const char *filename, const struct Yarrow_STATE* state );
+int STATE_Load( const char *filename, struct Yarrow_STATE* state );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* YARROW_SAVE_STATE */
+
+#endif /* YSTATE_H */
diff --git a/krb5-1-6/src/lib/crypto/yarrow/ytest.c b/krb5-1-6/src/lib/crypto/yarrow/ytest.c
new file mode 100644
index 000000000..93fb5f25a
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/ytest.c
@@ -0,0 +1,385 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+/*
+ * Yarrow - Cryptographic Pseudo-Random Number Generator
+ * Copyright (c) 2000 Zero-Knowledge Systems, Inc.
+ *
+ * See the accompanying LICENSE file for license information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "yarrow.h"
+#include "yexcep.h"
+
+void hex_print( FILE* f, const char* var, void* data, size_t size );
+void dump_yarrow_state( FILE* f, Yarrow_CTX* y );
+
+#define YARROW_SEED_FILE "seed"
+
+static void print_yarrow_status( Yarrow_CTX *y )
+{
+    int sid, pool;
+    Source* source;
+
+    for ( pool = 0; pool < 2; pool++ )
+    {
+	printf( " %s: ", pool == YARROW_SLOW_POOL ? "slow" : "fast" );
+	for ( sid = 0; sid < y->num_sources; sid++ )
+	{
+	    source = &y->source[ sid ];
+	    printf( "#%d=%d/%d, ", sid, source->entropy[pool], 
+		    pool == YARROW_SLOW_POOL ? 
+		    y->slow_thresh : y->fast_thresh );
+	}
+    }
+    printf( "\n" );
+}
+
+int yarrow_verbose = 0;
+#define VERBOSE( x ) if ( yarrow_verbose ) { x }
+
+int Instrumented_krb5int_yarrow_input( Yarrow_CTX* y, int sid, void* sample,
+			       size_t size, int entropy )
+{
+    int ret;
+
+    VERBOSE( printf( "krb5int_yarrow_input( #%d, %d bits, %s ) = [", sid, entropy, 
+		     y->source[sid].pool == 
+		     YARROW_SLOW_POOL ? "slow" : "fast" ); );
+    ret = krb5int_yarrow_input( y, sid, sample, size, entropy );
+
+    VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); );
+    VERBOSE( print_yarrow_status( y ); );
+    return (ret);
+}
+
+typedef int (*test_fn)( void );
+
+int test_1( void );
+int test_2( void );
+int test_3( void );
+int test_4( void );
+
+test_fn test_func[] =
+{
+    test_1, test_2, test_3, test_4
+};
+
+#define num_tests ( sizeof(test_func) / sizeof(test_fn) )
+
+int do_test( int t )
+{
+    EXCEP_DECL;
+    int ret;
+
+    printf( "doing test %d ... ", t ); fflush( stdout );
+    ret = test_func[ t-1 ]();
+    VERBOSE( printf( "\ndone test %d ", t ); );
+    printf( "[%s]\n", krb5int_yarrow_str_error( ret ) ); fflush( stdout );
+    THROW( ret );
+
+ CATCH:
+    THROW( EXCEP_BOOL );
+    EXCEP_RET;
+}
+
+int main( int argc, char* argv[] )
+{
+    EXCEP_DECL;
+    int test = 0;
+    char** argvp;
+    char* arg;
+    char* conv_ok = NULL;
+    int ok = YARROW_OK;
+    int done_some_tests = 0;
+    int i;
+    int ret;
+    
+    for ( argvp = argv+1, i = 1; i < argc; i++, argvp++ )
+    {
+	arg = *argvp;
+	if ( arg[0] == '-' ) 
+	{
+	    switch ( arg[1] )
+	    {
+	    case 'v': yarrow_verbose = 1; continue; 
+	    default: fprintf( stderr, "usage: test [-v] [[test] ... ]\n" );
+		THROW( YARROW_FAIL );
+	    }
+	}
+	conv_ok = NULL;
+	test = strtoul( arg, &conv_ok, 10 );
+	if ( !conv_ok || test < 1 || test > num_tests )
+	{
+	    fprintf( stderr, "usage: test [-v] [[test] ... ]\n" );
+	    THROW( YARROW_FAIL );
+	}
+	else
+	{
+	    ret = do_test( test );
+	    if ( ok ) { ok = ret; }
+	    done_some_tests = 1;
+	}
+    }
+
+    if ( !done_some_tests )
+    {
+	for ( i = 1; i <= num_tests; i++ )
+	{
+	    ret = do_test( i );
+	    if ( ok ) { ok = ret; }
+	}
+    }
+    THROW( ok );
+
+ CATCH:
+    switch (EXCEPTION)
+    {
+    case YARROW_OK:
+	exit (EXIT_SUCCESS);
+    default:
+	exit (EXIT_FAILURE);
+    }
+}
+
+int test_1( void )
+{
+    EXCEP_DECL;
+
+#if defined(YARROW_HASH_SHA1)
+    VERBOSE( printf( "\nsha1 test\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#elif defined(YARROW_MD5)
+    VERBOSE( printf( "\nmd5 test\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#else
+    VERBOSE( printf( "\nunknown hash function\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#endif
+ CATCH:
+    EXCEP_RET;
+}
+
+int test_2( void )
+{
+    EXCEP_DECL;
+
+#if defined(YARROW_CIPHER_3DES)
+    VERBOSE( printf( "\n3des test\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#elif defined(YARROW_CIPHER_BLOWFISH)
+    VERBOSE( printf( "\nblowfish test\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#elif defined(YARROW_CIPHER_IDEA)
+    VERBOSE( printf( "\nidea test\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#else
+    VERBOSE( printf( "\nunknown encryption function\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#endif
+ CATCH:
+    EXCEP_RET;
+}
+
+int test_3( void )
+{
+    EXCEP_DECL;
+
+#if !defined(YARROW_CIPHER_3DES) || !defined(YARROW_HASH_SHA1)
+    VERBOSE( printf( "\nnot Yarrow-SHA1-3DES (aka Yarrow-160)\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+#endif
+
+    VERBOSE( printf( "\nkrb5int_yarrow_stretch\n\n" ); );
+    THROW( YARROW_NOT_IMPL );
+    
+ CATCH:
+    EXCEP_RET;
+}
+
+int test_4( void )
+{
+    EXCEP_DECL;
+    Yarrow_CTX yarrow;
+    int initialized = 0;
+    unsigned user, mouse, keyboard;
+    int i, ret;
+    byte user_sample[ 20 ];
+    byte mouse_sample[ 4 ];
+    byte keyboard_sample[ 2 ];
+    byte random[ 30 ];
+    byte junk[ 48 ];
+
+    memset( user_sample,     3, sizeof( user_sample ) );
+    memset( mouse_sample,    1, sizeof( mouse_sample ) );
+    memset( keyboard_sample, 2, sizeof( keyboard_sample ) );
+
+    VERBOSE( printf( "\nGeneral workout test\n\n" ); )
+
+    VERBOSE( printf( "krb5int_yarrow_init() = [" ); );
+    ret = krb5int_yarrow_init( &yarrow, YARROW_SEED_FILE );
+    VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); );
+
+    if ( ret != YARROW_OK && ret != YARROW_NOT_SEEDED ) { THROW( ret ); }
+    initialized = 1;
+
+#if defined( YARROW_DEBUG )
+    dump_yarrow_state( stdout, &yarrow );
+#endif
+
+    ret = krb5int_yarrow_new_source( &yarrow, &user );
+    VERBOSE( printf( "krb5int_yarrow_new_source() = [%s]\n",
+		     krb5int_yarrow_str_error( ret ) ); );
+    if ( ret != YARROW_OK ) { THROW( ret ); }
+  
+    VERBOSE( printf( "Yarrow_Poll( #%d ) = [", user ); );
+    ret = Yarrow_Poll( &yarrow, user );
+    VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); );
+
+    ret = krb5int_yarrow_new_source( &yarrow, &mouse );
+    VERBOSE( printf( "krb5int_yarrow_new_source() = [%s]\n", 
+		     krb5int_yarrow_str_error( ret ) ); );
+    if ( ret != YARROW_OK ) { THROW( ret ); }
+
+    ret = krb5int_yarrow_new_source( &yarrow, &keyboard );
+    VERBOSE( printf( "krb5int_yarrow_new_source() = [%s]\n", 
+		     krb5int_yarrow_str_error( ret ) ); );
+    if ( ret != YARROW_OK ) { THROW( ret ); }
+
+/*  prematurely try to draw output, to check failure when no
+ *  seed file, or state saving turned off
+ */
+
+    VERBOSE( printf( "krb5int_yarrow_output( %d ) = [", sizeof( random ) ); );
+    ret = krb5int_yarrow_output( &yarrow, random, sizeof( random ) );
+    VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); );
+
+/*   do it twice so that we some slow samples 
+ *   (first sample goes to fast pool, and then samples alternate)
+ */
+
+    for ( i = 0; i < 2; i++ )
+    {
+	TRY( Instrumented_krb5int_yarrow_input( &yarrow, mouse, mouse_sample, 
+					sizeof( mouse_sample ), 2 ) );
+	
+	TRY( Instrumented_krb5int_yarrow_input( &yarrow, keyboard, keyboard_sample, 
+					sizeof( keyboard_sample ), 2 ) );
+
+	TRY( Instrumented_krb5int_yarrow_input( &yarrow, user, user_sample, 
+					sizeof( user_sample ), 2 ) );
+    }
+	
+#if defined( YARROW_DEBUG )
+    dump_yarrow_state( stdout, &yarrow );
+#endif
+
+    VERBOSE( printf( "\nInduce user source (#%d) to reach "
+		     "slow threshold\n\n", user ); );
+
+    /* induce fast reseed */
+
+    for ( i = 0; i < 7; i++ )
+    {
+	TRY( Instrumented_krb5int_yarrow_input( &yarrow, user, user_sample, 
+					sizeof( user_sample ), 
+					sizeof( user_sample ) * 3 ) );
+    }
+
+    VERBOSE( printf( "\nInduce mouse source (#%d) to reach "
+		     "slow threshold reseed\n\n", mouse ); );
+
+    /* induce slow reseed, by triggering a second source to reach it's
+       threshold */
+
+    for ( i = 0; i < 40; i++ )
+    {
+	TRY( Instrumented_krb5int_yarrow_input( &yarrow, mouse, mouse_sample, 
+					sizeof( mouse_sample ), 
+					sizeof( mouse_sample )*2 ) );
+    }
+
+    VERBOSE( printf( "\nProduce some output\n\n" ); );
+
+    for ( i = 0; i < 30; i++ )
+    {
+	VERBOSE( printf( "krb5int_yarrow_output( %d ) = [", sizeof( junk ) ); );
+	ret = krb5int_yarrow_output( &yarrow, junk, sizeof( junk ) );
+	VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); );
+	if ( ret != YARROW_OK ) { THROW( ret );	}
+    }
+
+    memset( junk, 0, sizeof( junk ) );
+
+    VERBOSE( printf( "\nTrigger some fast and slow reseeds\n\n" ); );
+
+    for ( i = 0; i < 30; i++ )
+    {
+	/* odd input to a different source so there are some slow reseeds */
+
+	if ( i % 16 == 0 )
+	{
+	    TRY( Instrumented_krb5int_yarrow_input( &yarrow, mouse, junk, 
+					    sizeof( junk ), 
+					    sizeof( junk ) * 3 ) );
+	}
+	else
+	{
+	    TRY( Instrumented_krb5int_yarrow_input( &yarrow, user, junk, 
+					    sizeof( junk ), 
+					    sizeof( junk ) * 3 ) );
+	}
+    }
+
+    VERBOSE( printf( "\nPrint some random output\n\n" ); );
+    
+    VERBOSE( printf( "krb5int_yarrow_output( %d ) = [", sizeof( random ) ); );
+    ret = krb5int_yarrow_output( &yarrow, random, sizeof( random ) );
+    VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); );
+    if ( ret != YARROW_OK )
+    {
+	THROW( ret );
+    }
+    else
+    {
+	VERBOSE( hex_print( stdout, "random", random, sizeof( random ) ); );
+    }
+
+    VERBOSE( printf( "\nClose down Yarrow\n\n" ); );
+
+ CATCH:
+    if ( initialized )
+    {
+	VERBOSE( printf( "krb5int_yarrow_final() = [" ); );
+	ret = krb5int_yarrow_final( &yarrow );
+	VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); );
+	THROW( ret );
+    }
+    EXCEP_RET;
+}
+
+void hex_print( FILE* f, const char* var, void* data, size_t size )
+{
+    const char* conv = "0123456789abcdef";
+    size_t i;
+    char* p = (char*) data;
+    char c, d;
+    
+    fprintf( f, var );
+    fprintf( f, " = " );
+    for ( i = 0; i < size; i++ )
+    {
+	c = conv[ (p[ i ] >> 4) & 0xf ];
+	d = conv[ p[ i ] & 0xf ];
+	fprintf( f, "%c%c", c, d );
+    }
+    fprintf( f, "\n" );
+}
+
+void dump_yarrow_state( FILE* f, Yarrow_CTX* y )
+{
+    fprintf( f, "===Yarrow State===\n" );
+    hex_print( f, "C", y->C, sizeof( y->C ) );
+    hex_print( f, "K", y->K, sizeof( y->K ) );
+}
diff --git a/krb5-1-6/src/lib/crypto/yarrow/ytypes.h b/krb5-1-6/src/lib/crypto/yarrow/ytypes.h
new file mode 100644
index 000000000..9265e5a84
--- /dev/null
+++ b/krb5-1-6/src/lib/crypto/yarrow/ytypes.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+
+#ifndef YTYPES_H
+#define YTYPES_H
+
+#include <limits.h>
+#include <stddef.h>
+#include "autoconf.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#define byte unsigned char 
+
+#define uint8 unsigned char
+#define int8 signed char
+
+
+#if defined(uint64)
+#   define COUNTER uint64
+#else
+#   define COUNTER krb5_ui_4
+#endif
+
+#define COUNTER_MAX ((COUNTER)0 - 1)
+
+#endif /* YTYPES_H */
diff --git a/krb5-1-6/src/lib/des425/ISSUES b/krb5-1-6/src/lib/des425/ISSUES
new file mode 100644
index 000000000..ec5ce0087
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/ISSUES
@@ -0,0 +1,28 @@
+-*- text -*-
+
+* unix_time.c also exists in ../krb4, and they're different; both
+  should probably call into the krb5 support anyways to avoid
+  duplicating code.
+
+* namespace intrusions
+
+* Check include/kerberosIV/des.h and see if all the prototyped
+  functions really are necessary to retain; if not, delete some of
+  these source files.
+
+* Much of this code requires that DES_INT32 be *exactly* 32 bits, and
+  4 bytes.
+
+* Array types are used in function call signatures, which is unclean.
+  It makes trying to add "const" qualifications in the right places
+  really, um, interesting.  But we're probably stuck with them.
+
+* quad_cksum is totally broken.  I have no idea whether the author
+  actually believed it implemented the documented algorithm, but I'm
+  certain it doesn't.  The only question is, is it still reasonably
+  secure, when the plaintext and checksum are visible to an attacker
+  as in the mk_safe message?
+
+* des_read_password and des_read_pw_string are not thread-safe.  Also,
+  they should be calling into the k5crypto library instead of
+  duplicating functionality.
diff --git a/krb5-1-6/src/lib/des425/Makefile.in b/krb5-1-6/src/lib/des425/Makefile.in
new file mode 100644
index 000000000..cf806b24b
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/Makefile.in
@@ -0,0 +1,259 @@
+thisconfigdir=../..
+myfulldir=lib/des425
+mydir=lib/des425
+BUILDTOP=$(REL)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../crypto/des -I$(srcdir)/../../include/kerberosIV
+DEFS=
+
+##DOS##BUILDTOP = ..\..
+##DOS##LIBNAME=$(OUTPRE)des425.lib
+##DOS##OBJFILE=$(OUTPRE)des425.lst
+##DOS##OBJFILEDEP=$(OUTPRE)des425.lst
+##DOS##OBJFILELIST=@$(OUTPRE)des425.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP=@KRB5_RUN_ENV@
+
+LIBBASE=des425
+LIBMAJOR=3
+LIBMINOR=0
+RELDIR=des425
+# Depends on libk5crypto and libkrb5
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS=-lkrb5 -lcom_err -lk5crypto
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+STOBJLISTS=OBJS.ST
+STLIBOBJS=cksum.o	\
+	des.o		\
+	enc_dec.o	\
+	key_parity.o	\
+	key_sched.o	\
+	new_rnd_key.o	\
+	pcbc_encrypt.o	\
+	quad_cksum.o	\
+	random_key.o	\
+	read_passwd.o  \
+	str_to_key.o	\
+	unix_time.o     \
+	util.o		\
+	weak_key.o
+
+
+OBJS=	$(OUTPRE)cksum.$(OBJEXT)	\
+	$(OUTPRE)des.$(OBJEXT)		\
+	$(OUTPRE)enc_dec.$(OBJEXT)	\
+	$(OUTPRE)key_parity.$(OBJEXT)	\
+	$(OUTPRE)key_sched.$(OBJEXT)	\
+	$(OUTPRE)new_rnd_key.$(OBJEXT)	\
+	$(OUTPRE)pcbc_encrypt.$(OBJEXT)	\
+	$(OUTPRE)quad_cksum.$(OBJEXT)	\
+	$(OUTPRE)random_key.$(OBJEXT)	\
+	$(OUTPRE)read_passwd.$(OBJEXT)	\
+	$(OUTPRE)str_to_key.$(OBJEXT)	\
+	$(OUTPRE)unix_time.$(OBJEXT)	\
+	$(OUTPRE)util.$(OBJEXT)		\
+	$(OUTPRE)weak_key.$(OBJEXT)
+
+SRCS=	$(srcdir)/cksum.c	\
+	$(srcdir)/des.c		\
+	$(srcdir)/enc_dec.c	\
+	$(srcdir)/key_parity.c	\
+	$(srcdir)/key_sched.c	\
+	$(srcdir)/new_rnd_key.c	\
+	$(srcdir)/pcbc_encrypt.c	\
+	$(srcdir)/quad_cksum.c	\
+	$(srcdir)/random_key.c	\
+	$(srcdir)/read_passwd.c \
+	$(srcdir)/str_to_key.c	\
+	$(srcdir)/unix_time.c   \
+	$(srcdir)/util.c	\
+	$(srcdir)/weak_key.c
+
+all-unix:: all-liblinks
+
+##DOS##LIBOBJS = $(OBJS)
+
+shared:
+	mkdir shared
+
+verify: verify.o $(DES425_DEPLIB) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $@ verify.o $(DES425_LIB) $(KRB5_BASE_LIBS)
+
+t_quad: t_quad.o quad_cksum.o $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_quad.o quad_cksum.o $(SUPPORT_LIB)
+
+t_pcbc: t_pcbc.o pcbc_encrypt.o key_sched.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $@ t_pcbc.o pcbc_encrypt.o key_sched.o $(KRB5_BASE_LIBS)
+
+check-unix:: verify t_quad t_pcbc
+	$(RUN_SETUP) $(VALGRIND) ./verify -z
+	$(RUN_SETUP) $(VALGRIND) ./verify -m
+	$(RUN_SETUP) $(VALGRIND) ./verify
+	$(RUN_SETUP) $(VALGRIND) ./t_quad
+	$(RUN_SETUP) $(VALGRIND) ./t_pcbc
+
+check-windows::
+
+clean:: 
+	$(RM) $(OUTPRE)verify$(EXEEXT) $(OUTPRE)verify.$(OBJEXT) \
+		$(OUTPRE)t_quad$(EXEEXT) $(OUTPRE)t_quad.$(OBJEXT) \
+		$(OUTPRE)t_pcbc$(EXEEXT) $(OUTPRE)t_pcbc.$(OBJEXT)
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+install-unix:: install-libs
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+cksum.so cksum.po $(OUTPRE)cksum.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../crypto/des/des_int.h \
+  cksum.c
+des.so des.po $(OUTPRE)des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../crypto/des/des_int.h \
+  des.c
+enc_dec.so enc_dec.po $(OUTPRE)enc_dec.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../crypto/des/des_int.h \
+  enc_dec.c
+key_parity.so key_parity.po $(OUTPRE)key_parity.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h key_parity.c
+key_sched.so key_sched.po $(OUTPRE)key_sched.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h key_sched.c
+new_rnd_key.so new_rnd_key.po $(OUTPRE)new_rnd_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h new_rnd_key.c
+pcbc_encrypt.so pcbc_encrypt.po $(OUTPRE)pcbc_encrypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h $(srcdir)/../crypto/des/f_tables.h \
+  pcbc_encrypt.c
+quad_cksum.so quad_cksum.po $(OUTPRE)quad_cksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h quad_cksum.c
+random_key.so random_key.po $(OUTPRE)random_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h random_key.c
+read_passwd.so read_passwd.po $(OUTPRE)read_passwd.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h read_passwd.c
+str_to_key.so str_to_key.po $(OUTPRE)str_to_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h str_to_key.c
+unix_time.so unix_time.po $(OUTPRE)unix_time.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h unix_time.c
+util.so util.po $(OUTPRE)util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../crypto/des/des_int.h \
+  util.c
+weak_key.so weak_key.po $(OUTPRE)weak_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../crypto/des/des_int.h weak_key.c
diff --git a/krb5-1-6/src/lib/des425/cksum.c b/krb5-1-6/src/lib/des425/cksum.c
new file mode 100644
index 000000000..33b5322ac
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/cksum.c
@@ -0,0 +1,68 @@
+/*
+ * lib/des425/cksum.c
+ *
+ * Copyright 1985, 1986, 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * These routines perform encryption and decryption using the DES
+ * private key algorithm, or else a subset of it-- fewer inner loops.
+ * (AUTH_DES_ITER defaults to 16, may be less.)
+ *
+ * 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.
+ *
+ *	spm	8/85	MIT project athena
+ */
+
+#include "des_int.h"
+#include "des.h"
+
+/*
+ * This routine performs DES cipher-block-chaining checksum operation,
+ * a.k.a.  Message Authentication Code.  It ALWAYS encrypts from input
+ * to a single 64 bit output MAC checksum.
+ *
+ * The key schedule is passed as an arg, as well as the cleartext or
+ * ciphertext. The cleartext and ciphertext should be in host order.
+ *
+ * NOTE-- the output is ALWAYS 8 bytes long.  If not enough space was
+ * provided, your program will get trashed.
+ *
+ * The input is null padded, at the end (highest addr), to an integral
+ * multiple of eight bytes.
+ */
+
+unsigned long KRB5_CALLCONV
+des_cbc_cksum(in,out,length,key,iv)
+    const des_cblock  *in;		/* >= length bytes of inputtext */
+    des_cblock  *out;			/* >= length bytes of outputtext */
+    register unsigned long length;	/* in bytes */
+    const mit_des_key_schedule key;	/* precomputed key schedule */
+    const des_cblock  *iv;		/* 8 bytes of ivec */
+{
+    return mit_des_cbc_cksum((const krb5_octet *)in, (krb5_octet *)out,
+			     length, key, (krb5_octet *)iv);
+}
diff --git a/krb5-1-6/src/lib/des425/des.c b/krb5-1-6/src/lib/des425/des.c
new file mode 100644
index 000000000..745b4bed5
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/des.c
@@ -0,0 +1,44 @@
+/*
+ * lib/des425/des.c
+ *
+ * Copyright 1985, 1986, 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "des_int.h"
+#include "des.h"
+#undef mit_des_cbc_encrypt
+
+int KRB5_CALLCONV
+des_ecb_encrypt(clear, cipher, schedule, enc)
+    des_cblock *clear;
+    des_cblock *cipher;
+    const mit_des_key_schedule schedule;
+    int enc;		/* 0 ==> decrypt, else encrypt */
+{
+    static const des_cblock iv;
+
+    return (mit_des_cbc_encrypt((const des_cblock *)clear, cipher,
+				8, schedule, iv, enc));
+}
diff --git a/krb5-1-6/src/lib/des425/enc_dec.c b/krb5-1-6/src/lib/des425/enc_dec.c
new file mode 100644
index 000000000..b75a63e20
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/enc_dec.c
@@ -0,0 +1,47 @@
+/*
+ * lib/des425/enc_dec.c
+ *
+ * Copyright 1985, 1986, 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+#include "des_int.h"
+#include "des.h"
+#undef mit_des_cbc_encrypt
+
+int
+des_cbc_encrypt(in,out,length,key,iv,enc)
+    des_cblock   *in;	/* >= length bytes of input text */
+    des_cblock  *out;		/* >= length bytes of output text */
+    register unsigned long length;	/* in bytes */
+    const mit_des_key_schedule key;		/* precomputed key schedule */
+    const des_cblock *iv;		/* 8 bytes of ivec */
+    int enc;		/* 0 ==> decrypt, else encrypt */
+{
+	return (mit_des_cbc_encrypt((const des_cblock *) in,
+				    out, length, key,
+				    (const unsigned char *)iv, /* YUCK! */
+				    enc));
+}
diff --git a/krb5-1-6/src/lib/des425/key_parity.c b/krb5-1-6/src/lib/des425/key_parity.c
new file mode 100644
index 000000000..96e13e2f4
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/key_parity.c
@@ -0,0 +1,52 @@
+/*
+ * lib/des425/key_parity.c
+ *
+ * Copyright 1989, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "des_int.h"
+#include "des.h"
+
+/*
+ * des_fixup_key_parity: Forces odd parity per byte; parity is bits
+ *                       8,16,...64 in des order, implies 0, 8, 16, ...
+ *                       vax order.
+ */
+void
+des_fixup_key_parity(key)
+     register mit_des_cblock key;
+{
+	mit_des_fixup_key_parity(key);
+}
+
+/*
+ * des_check_key_parity: returns true iff key has the correct des parity.
+ */
+int
+des_check_key_parity(key)
+     register mit_des_cblock key;
+{
+	return(mit_des_check_key_parity(key));
+}
+
diff --git a/krb5-1-6/src/lib/des425/key_sched.c b/krb5-1-6/src/lib/des425/key_sched.c
new file mode 100644
index 000000000..70f61ce5e
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/key_sched.c
@@ -0,0 +1,40 @@
+/*
+ * lib/des425/key_sched.c
+ *
+ * Copyright 1985, 1986, 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+
+#include <stdio.h>
+#include "des_int.h"
+#include "des.h"
+
+int KRB5_CALLCONV
+des_key_sched(k,schedule)
+    des_cblock k;
+    des_key_schedule schedule;
+{
+    return (mit_des_key_sched(k, schedule));
+}
diff --git a/krb5-1-6/src/lib/des425/libdes425.exports b/krb5-1-6/src/lib/des425/libdes425.exports
new file mode 100644
index 000000000..5753a6e96
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/libdes425.exports
@@ -0,0 +1,18 @@
+afs_string_to_key
+des_cbc_cksum
+des_cbc_encrypt
+des_cblock_print_file
+des_check_key_parity
+des_ecb_encrypt
+des_fixup_key_parity
+des_init_random_number_generator
+des_is_weak_key
+des_key_sched
+des_new_random_key
+des_pcbc_encrypt
+des_quad_cksum
+des_random_key
+des_read_password
+des_read_pw_string
+des_string_to_key
+unix_time_gmt_unixsec
diff --git a/krb5-1-6/src/lib/des425/mac_des_glue.c b/krb5-1-6/src/lib/des425/mac_des_glue.c
new file mode 100644
index 000000000..b7f3a6af8
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/mac_des_glue.c
@@ -0,0 +1,104 @@
+#include "des_int.h"
+#include "des.h"
+#undef mit_des3_cbc_encrypt
+
+/* These functions are exported on KfM for ABI compatibility with
+ * older versions of the library.  They have been pulled from the headers
+ * in the hope that someday we can remove them.
+ * 
+ * Do not change the ABIs of any of these functions!
+ */
+
+//int des_read_pw_string(char *, int, char *, int);
+char *des_crypt(const char *, const char *);
+char *des_fcrypt(const char *, const char *, char *);
+
+int make_key_sched(des_cblock *, des_key_schedule);
+int des_set_key(des_cblock *, des_key_schedule);
+
+void des_3cbc_encrypt(des_cblock *, des_cblock *, long, 
+                      des_key_schedule, des_key_schedule, des_key_schedule, 
+                      des_cblock *, int);
+void des_3ecb_encrypt(des_cblock *, des_cblock *, 
+                      des_key_schedule, des_key_schedule, des_key_schedule, 
+                      int);
+
+void des_generate_random_block(des_cblock);
+void des_set_random_generator_seed(des_cblock);
+void des_set_sequence_number(des_cblock);
+
+#pragma mark -
+
+/* Why was this exported on KfM?  Who knows... */
+int des_debug = 0;
+
+char *des_crypt(const char *str, const char *salt)
+{
+    char afs_buf[16];
+
+    return des_fcrypt(str, salt, afs_buf);
+}
+
+
+char *des_fcrypt(const char *str, const char *salt, char *buf)
+{
+    return mit_afs_crypt(str, salt, buf);
+}
+
+
+int make_key_sched(des_cblock *k, des_key_schedule schedule)
+{
+    return mit_des_key_sched((unsigned char *)k, schedule); /* YUCK! */
+}
+
+
+int des_set_key(des_cblock *key, des_key_schedule schedule)
+{
+    return make_key_sched(key, schedule);
+}
+
+
+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 *iv, int enc)
+{
+    mit_des3_cbc_encrypt((const des_cblock *)in, out, (unsigned long)length,
+			 ks1, ks2, ks3,
+			 (const unsigned char *)iv, /* YUCK! */
+			 enc);
+}
+
+
+void des_3ecb_encrypt(des_cblock *clear, des_cblock *cipher,
+                      des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, 
+                      int enc)
+{
+    static const des_cblock iv;
+
+    mit_des3_cbc_encrypt((const des_cblock *)clear, cipher, 8, ks1, ks2, ks3, iv, enc);
+}
+
+
+void des_generate_random_block(des_cblock block)
+{
+    krb5_data data;
+
+    data.length = sizeof(des_cblock);
+    data.data = (char *)block;
+    
+    /* This function can return an error, however we must ignore it. */
+    /* The worst that happens is that the resulting block is non-random */
+    krb5_c_random_make_octets(/* XXX */ 0, &data);
+}
+
+
+void des_set_random_generator_seed(des_cblock block)
+{
+    des_init_random_number_generator(block); /* XXX */
+}
+
+
+void des_set_sequence_number(des_cblock block)
+{
+    des_init_random_number_generator(block); /* XXX */
+}
diff --git a/krb5-1-6/src/lib/des425/new_rnd_key.c b/krb5-1-6/src/lib/des425/new_rnd_key.c
new file mode 100644
index 000000000..126ddf500
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/new_rnd_key.c
@@ -0,0 +1,96 @@
+/*
+ * lib/des425/new_rnd_key.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+/*
+ * Copyright (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 "des.h"
+#include "k5-int.h"
+
+void
+des_init_random_number_generator(key)
+    mit_des_cblock key;
+{
+    krb5_data seed;
+
+    seed.length = sizeof(key);
+    seed.data = (char *) key;
+
+    if (krb5_c_random_seed(/* XXX */ 0, &seed))
+	/* XXX */ abort();
+}
+
+/*
+ * 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.
+ */
+int KRB5_CALLCONV
+des_new_random_key(key)
+    mit_des_cblock key;
+{
+    krb5_keyblock keyblock;
+    krb5_error_code kret;
+
+    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);
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/des425/pcbc_encrypt.c b/krb5-1-6/src/lib/des425/pcbc_encrypt.c
new file mode 100644
index 000000000..70d7b6b84
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/pcbc_encrypt.c
@@ -0,0 +1,218 @@
+/*
+ * lib/des425/pcbc_encrypt.c
+ */
+
+/*
+ * 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 "des.h"
+#include <f_tables.h>
+
+/*
+ * des_pcbc_encrypt - {en,de}crypt a stream in PCBC mode
+ */
+int KRB5_CALLCONV
+des_pcbc_encrypt(in, out, length, schedule, ivec, enc)
+	des_cblock *in;
+	des_cblock *out;
+	long length;
+	const des_key_schedule schedule;
+	des_cblock *ivec;
+	int enc;
+{
+	register unsigned DES_INT32 left, right;
+	const unsigned DES_INT32 *kp;
+	const unsigned char *ip;
+	unsigned char *op;
+
+	/*
+	 * Copy the key pointer, just once
+	 */
+	kp = (const unsigned DES_INT32 *)schedule;
+
+	/*
+	 * Deal with encryption and decryption separately.
+	 */
+	if (enc) {
+		/* Initialization isn't really needed here, but gcc
+		   complains because it doesn't understand that the
+		   only case where these can be used uninitialized is
+		   to compute values that'll in turn be ignored
+		   because we won't go around the loop again.  */
+		register unsigned DES_INT32 plainl = 42;
+		register unsigned DES_INT32 plainr = 17;
+
+		/*
+		 * Initialize left and right with the contents of the initial
+		 * vector.
+		 */
+		ip = *ivec;
+		GET_HALF_BLOCK(left, ip);
+		GET_HALF_BLOCK(right, ip);
+
+		/*
+		 * Suitably initialized, now work the length down 8 bytes
+		 * at a time.
+		 */
+		ip = *in;
+		op = *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) & 0xff;
+				case 7:
+					right ^= (*(--ip) & 0xff) << 8;
+				case 6:
+					right ^= (*(--ip) & 0xff) << 16;
+				case 5:
+					right ^= (*(--ip) & 0xff) << 24;
+				case 4:
+					left ^= *(--ip) & 0xff;
+				case 3:
+					left ^= (*(--ip) & 0xff) << 8;
+				case 2:
+					left ^= (*(--ip) & 0xff) << 16;
+				case 1:
+					left ^= (*(--ip) & 0xff) << 24;
+					break;
+				}
+				length = 0;
+			}
+
+			/*
+			 * Encrypt what we have
+			 */
+			DES_DO_ENCRYPT(left, right, 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 = *ivec;
+		GET_HALF_BLOCK(ocipherl, ip);
+		GET_HALF_BLOCK(ocipherr, ip);
+
+		/*
+		 * Now do this in earnest until we run out of length.
+		 */
+		ip = *in;
+		op = *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, 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/krb5-1-6/src/lib/des425/quad_cksum.c b/krb5-1-6/src/lib/des425/quad_cksum.c
new file mode 100644
index 000000000..2a7b78cfd
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/quad_cksum.c
@@ -0,0 +1,200 @@
+/*
+ * lib/des425/quad_cksum.c
+ *
+ * Copyright 1985, 1986, 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * This routine does not implement:
+ *
+ *
+ * Quadratic Congruential Manipulation Dectection Code
+ *
+ * ref: "Message Authentication"
+ *		R.R. Jueneman, S. M. Matyas, C.H. Meyer
+ *		IEEE Communications Magazine,
+ *		Sept 1985 Vol 23 No 9 p 29-40
+ *
+ * This routine, part of the Athena DES library built for the Kerberos
+ * authentication system, calculates a manipulation detection code for
+ * a message.  It is a much faster alternative to the DES-checksum
+ * method. No guarantees are offered for its security.
+ *
+ * Implementation for 4.2bsd
+ * by S.P. Miller	Project Athena/MIT
+ */
+
+/*
+ * Algorithm (per paper):
+ *		define:
+ *		message to be composed of n m-bit blocks X1,...,Xn
+ *		optional secret seed S in block X1
+ *		MDC in block Xn+1
+ *		prime modulus N
+ *		accumulator Z
+ *		initial (secret) value of accumulator C
+ *		N, C, and S are known at both ends
+ *		C and , optionally, S, are hidden from the end users
+ *		then
+ *			(read array references as subscripts over time)
+ *			Z[0] = c;
+ *			for i = 1...n
+ *				Z[i] = (Z[i+1] + X[i])**2 modulo N
+ *			X[n+1] = Z[n] = MDC
+ *
+ *		Then pick
+ *			N = 2**31 -1
+ *			m = 16
+ *			iterate 4 times over plaintext, also use Zn
+ *			from iteration j as seed for iteration j+1,
+ *			total MDC is then a 128 bit array of the four
+ *			Zn;
+ *
+ *			return the last Zn and optionally, all
+ *			four as output args.
+ *
+ * Modifications:
+ *	To inhibit brute force searches of the seed space, this
+ *	implementation is modified to have
+ *	Z	= 64 bit accumulator
+ *	C	= 64 bit C seed
+ *	N	= 2**63 - 1
+ *  S	= S seed is not implemented here
+ *	arithmetic is not quite real double integer precision, since we
+ *	cant get at the carry or high order results from multiply,
+ *	but nontheless is 64 bit arithmetic.
+ */
+/*
+ * This code purports to implement the above algorithm, but fails.
+ *
+ * First of all, there was an implicit mod 2**32 being done on the
+ * machines where this was developed because of their word sizes, and
+ * for compabitility this has to be done on machines with 64-bit
+ * words, so we make it explicit.
+ *
+ * Second, in the squaring operation, I really doubt the carry-over
+ * from the low 31-bit half of the accumulator is being done right,
+ * and using a modulus of 0x7fffffff on the low half of the
+ * accumulator seems completely wrong.  And I challenge anyone to
+ * explain where the number 83653421 comes from.
+ *
+ * --Ken Raeburn  2001-04-06
+ */
+
+
+/* System include files */
+#include <stdio.h>
+#include <errno.h>
+
+#include "des_int.h"
+#include "des.h"
+
+/* Definitions for byte swapping */
+
+/* vax byte order is LSB first. This is not performance critical, and
+   is far more readable this way. */
+#define four_bytes_vax_to_nets(x) ((((((x[3]<<8)|x[2])<<8)|x[1])<<8)|x[0])
+#define vaxtohl(x) four_bytes_vax_to_nets(((const unsigned char *)(x)))
+#define two_bytes_vax_to_nets(x) ((x[1]<<8)|x[0])
+#define vaxtohs(x) two_bytes_vax_to_nets(((const unsigned char *)(x)))
+
+/* Externals */
+extern int des_debug;
+
+/*** Routines ***************************************************** */
+
+unsigned long KRB5_CALLCONV
+des_quad_cksum(in,out,length,out_count,c_seed)
+    const unsigned char *in;	/* input block */
+    unsigned DES_INT32 *out;	/* optional longer output */
+    long length;			/* original length in bytes */
+    int out_count;			/* number of iterations */
+    mit_des_cblock *c_seed;		/* secret seed, 8 bytes */
+{
+
+    /*
+     * this routine both returns the low order of the final (last in
+     * time) 32bits of the checksum, and if "out" is not a null
+     * pointer, a longer version, up to entire 32 bytes of the
+     * checksum is written unto the address pointed to.
+     */
+
+    register unsigned DES_INT32 z;
+    register unsigned DES_INT32 z2;
+    register unsigned DES_INT32 x;
+    register unsigned DES_INT32 x2;
+    const unsigned char *p;
+    register DES_INT32 len;
+    register int i;
+
+    /* use all 8 bytes of seed */
+
+    z = vaxtohl(c_seed);
+    z2 = vaxtohl((const char *)c_seed+4);
+    if (out == NULL)
+	out_count = 1;		/* default */
+
+    /* This is repeated n times!! */
+    for (i = 1; i <=4 && i<= out_count; i++) {
+	len = length;
+	p = in;
+	while (len) {
+	    /*
+	     * X = Z + Input ... sort of.  Carry out from low half
+	     * isn't done, so we're using all 32 bits of x now.
+	     */
+	    if (len > 1) {
+		x = (z + vaxtohs(p));
+		p += 2;
+		len -= 2;
+	    }
+	    else {
+		x = (z + *(const unsigned char *)p++);
+		len = 0;
+	    }
+	    x2 = z2;
+	    /*
+	     * I think this is supposed to be a squaring operation.
+	     * What it really is, I haven't figured out yet.
+	     *
+	     * Explicit mod 2**32 is for backwards compatibility.  Why
+	     * mod 0x7fffffff and not 0x80000000 on the low half of
+	     * the (supposed) accumulator?  And where does the number
+	     * 83653421 come from??
+	     */
+	    z  = (((x * x) + (x2 * x2)) & 0xffffffff) % 0x7fffffff;
+	    z2 = ((x * (x2+83653421)) & 0xffffffff) % 0x7fffffff; /* modulo */
+#ifdef DEBUG
+	    if (des_debug & 8)
+		printf("%d %d\n",z,z2);
+#endif
+	}
+
+	if (out != NULL) {
+	    *out++ = z;
+	    *out++ = z2;
+	}
+    }
+    /* return final z value as 32 bit version of checksum */
+    return z;
+}
diff --git a/krb5-1-6/src/lib/des425/random_key.c b/krb5-1-6/src/lib/des425/random_key.c
new file mode 100644
index 000000000..f367fc817
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/random_key.c
@@ -0,0 +1,74 @@
+/*
+ * lib/des425/random_key.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+/*
+ * Copyright (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 "des.h"
+
+/* random_key */
+int
+des_random_key(key)
+    mit_des_cblock *key;
+{
+    krb5_keyblock	keyblock;
+    krb5_error_code	kret;
+
+    if ((kret = krb5_c_make_random_key(/* XXX */ 0, ENCTYPE_DES_CBC_CRC,
+				      &keyblock)))
+	return(kret);
+
+    memcpy(key, keyblock.contents, sizeof(mit_des_cblock));
+
+    return(0);
+}
+
diff --git a/krb5-1-6/src/lib/des425/read_passwd.c b/krb5-1-6/src/lib/des425/read_passwd.c
new file mode 100644
index 000000000..e1b4c713c
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/read_passwd.c
@@ -0,0 +1,129 @@
+/*
+ * lib/des425/read_passwd.c
+ *
+ * Copyright 1985,1986,1987,1988,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This routine prints the supplied string to standard
+ * output as a prompt, and reads a password string without
+ * echoing.
+ */
+
+#if !defined(_WIN32)
+
+#include "des_int.h"
+#include "des.h"
+#include <stdio.h>
+#include <errno.h>
+#include <krb5.h>
+/* This is re-declared here because des.h might not declare it. */
+int KRB5_CALLCONV des_read_pw_string(char *, int, char *, int);
+static int des_rd_pwstr_2prompt(char *, int, char *, char *);
+
+
+/*** Routines ****************************************************** */
+static int
+des_rd_pwstr_2prompt(return_pwd, bufsize_in, prompt, prompt2)
+    char *return_pwd;
+    int bufsize_in;
+    char *prompt;
+    char *prompt2;
+{
+    krb5_data reply_data;      
+    krb5_prompt k5prompt;
+    krb5_error_code retval;
+    reply_data.length = bufsize_in;
+    reply_data.data = return_pwd;
+    k5prompt.prompt = prompt;
+    k5prompt.hidden = 1;
+    k5prompt.reply = &reply_data;
+    retval =  krb5_prompter_posix(NULL,
+				  NULL, NULL, NULL, 1, &k5prompt);
+
+    if ((retval==0) && prompt2) {
+	krb5_data verify_data;
+	verify_data.data = malloc(bufsize_in);
+	verify_data.length = bufsize_in;
+	k5prompt.prompt = prompt2;
+	k5prompt.reply = &verify_data;
+	if (!verify_data.data)
+	    return ENOMEM;
+	retval = krb5_prompter_posix(NULL,
+				     NULL,NULL, NULL, 1, &k5prompt);
+	if (retval) {
+	    free(verify_data.data);
+	} else {
+	    /* compare */
+	    if (strncmp(return_pwd, (char *)verify_data.data, bufsize_in)) {
+		retval = KRB5_LIBOS_BADPWDMATCH;
+		free(verify_data.data);
+	    }
+	}
+    }
+    return retval;
+}
+
+
+int KRB5_CALLCONV
+des_read_password(k,prompt,verify)
+    mit_des_cblock *k;
+    char *prompt;
+    int	verify;
+{
+    int ok;
+    char key_string[BUFSIZ];
+
+    ok = des_read_pw_string(key_string, sizeof(key_string), prompt, verify);
+    if (ok == 0)
+	des_string_to_key(key_string, *k);
+
+    memset(key_string, 0, sizeof (key_string));
+    return ok;
+}
+
+/* Note: this function is exported on KfM.  Do not change its ABI. */
+int KRB5_CALLCONV
+des_read_pw_string(s, max, prompt, verify)
+    char *s;
+    int max;
+    char *prompt;
+    int	verify;
+{
+    int ok;
+    char prompt2[BUFSIZ];
+
+    if (verify) {
+	strcpy(prompt2, "Verifying, please re-enter ");
+	strncat(prompt2, prompt, sizeof(prompt2)-(strlen(prompt2)+1));
+	prompt2[sizeof(prompt2)-1] = '\0';
+    }
+    ok = des_rd_pwstr_2prompt(s, max, prompt, verify ? prompt2 : 0);
+    return ok;
+}
+
+#else /* !unix */
+/*
+ * These are all just dummy functions to make the rest of the library happy...
+ */
+#endif /* _WINDOWS */
diff --git a/krb5-1-6/src/lib/des425/str_to_key.c b/krb5-1-6/src/lib/des425/str_to_key.c
new file mode 100644
index 000000000..4ddcaed4a
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/str_to_key.c
@@ -0,0 +1,168 @@
+/*
+ * lib/des425/str_to_key.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 1989,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * These routines perform encryption and decryption using the DES
+ * private key algorithm, or else a subset of it-- fewer inner loops.
+ * (AUTH_DES_ITER defaults to 16, may be less.)
+ *
+ * Under U.S. law, this software may not be exported outside the US
+ * without license from the U.S. Commerce department.
+ *
+ * The key schedule is passed as an arg, as well as the cleartext or
+ * ciphertext.  The cleartext and ciphertext should be in host order.
+ *
+ * These routines form the library interface to the DES facilities.
+ *
+ *	spm	8/85	MIT project athena
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include "des_int.h"
+#include "des.h"
+
+extern int mit_des_debug;
+
+/*
+ * Convert an arbitrary length string to a DES key.
+ */
+
+/*
+ * For krb5, a change was made to this algorithm: When each key is
+ * generated, after fixing parity, a check for weak and semi-weak keys
+ * is done.  If the key is weak or semi-weak, we XOR the last byte
+ * with 0xF0.  (In the case of the intermediate key, the weakness is
+ * probably irrelevant, but there it is.)  The odds that this will
+ * generate a different key for a random input string are pretty low,
+ * but non-zero.  So we need this different function for krb4 to use.
+ */
+int KRB5_CALLCONV
+des_string_to_key(str,key)
+    const char *str;
+    register mit_des_cblock key;
+{
+    const char *in_str;
+    register unsigned temp;
+    register int j;
+    unsigned long i, length;
+    unsigned char *k_p;
+    int forward;
+    register char *p_char;
+    char k_char[64];
+    mit_des_key_schedule key_sked;
+
+    in_str = str;
+    forward = 1;
+    p_char = k_char;
+    length = strlen(str);
+
+    /* init key array for bits */
+    memset(k_char, 0,sizeof(k_char));
+
+#ifdef DEBUG
+    if (mit_des_debug)
+	fprintf(stdout,
+		"\n\ninput str length = %ld  string = %s\nstring = 0x ",
+		length,str);
+#endif
+
+    /* get next 8 bytes, strip parity, xor */
+    for (i = 1; i <= length; i++) {
+	/* get next input key byte */
+	temp = (unsigned int) *str++;
+#ifdef DEBUG
+	if (mit_des_debug)
+	    fprintf(stdout,"%02x ",temp & 0xff);
+#endif
+	/* loop through bits within byte, ignore parity */
+	for (j = 0; j <= 6; j++) {
+	    if (forward)
+		*p_char++ ^= (int) temp & 01;
+	    else
+		*--p_char ^= (int) temp & 01;
+	    temp = temp >> 1;
+	}
+
+	/* check and flip direction */
+	if ((i%8) == 0)
+	    forward = !forward;
+    }
+
+    /* now stuff into the key des_cblock, and force odd parity */
+    p_char = k_char;
+    k_p = (unsigned char *) key;
+
+    for (i = 0; i <= 7; i++) {
+	temp = 0;
+	for (j = 0; j <= 6; j++)
+	    temp |= *p_char++ << (1+j);
+	*k_p++ = (unsigned char) temp;
+    }
+
+    /* fix key parity */
+    des_fixup_key_parity(key);
+
+    /* Now one-way encrypt it with the folded key */
+    (void) des_key_sched(key, key_sked);
+    (void) des_cbc_cksum((const des_cblock *)in_str, (des_cblock *)key,
+			 length, key_sked, (const des_cblock *)key);
+    /* erase key_sked */
+    memset(key_sked, 0,sizeof(key_sked));
+
+    /* now fix up key parity again */
+    des_fixup_key_parity(key);
+
+#ifdef DEBUG
+    if (mit_des_debug)
+	fprintf(stdout,
+		"\nResulting string_to_key = 0x%x 0x%x\n",
+		*((unsigned long *) key),
+		*((unsigned long *) key+1));
+#endif /* DEBUG */
+    return 0;			/* Really should be returning void, */
+				/* but the original spec was for it to */
+				/* return an int, and ANSI compilers */
+				/* can do dumb things sometimes */
+}
+
+void afs_string_to_key(char *str, char *cell, des_cblock key)
+{
+    krb5_data str_data;
+    krb5_data cell_data;
+    krb5_keyblock keyblock;
+
+    str_data.data = str;
+    str_data.length = strlen(str);
+    cell_data.data = cell;
+    cell_data.length = strlen(cell);
+    keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+    keyblock.length = sizeof(des_cblock);
+    keyblock.contents = key;
+
+    mit_afs_string_to_key(&keyblock, &str_data, &cell_data);
+}
diff --git a/krb5-1-6/src/lib/des425/string2key.c b/krb5-1-6/src/lib/des425/string2key.c
new file mode 100644
index 000000000..8756787a1
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/string2key.c
@@ -0,0 +1,174 @@
+/* THIS FILE DOES NOT GET COMPILED.  AUDIT BEFORE USE.  */
+/*
+ * lib/des425/string2key.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Wrapper for the V4 libdes for use with kerberos V5.
+ */
+
+
+#include "des.h"
+#include "des_int.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+extern int des_debug;
+#endif
+
+/*
+	converts the string pointed to by "data" into an encryption key
+	of type "enctype".  *keyblock is filled in with the key info;
+	in particular, keyblock->contents is to be set to allocated storage.
+	It is the responsibility of the caller to release this storage
+	when the generated key no longer needed.
+
+	The routine may use "princ" to seed or alter the conversion
+	algorithm.
+
+	If the particular function called does not know how to make a
+	key of type "enctype", an error may be returned.
+
+	returns: errors
+ */
+
+krb5_error_code mit_des_string_to_key (enctype, keyblock, data, princ)
+    const krb5_enctype enctype;
+    krb5_keyblock * keyblock;
+    const krb5_data * data;
+    krb5_const_principal princ;
+{
+    char copystr[512];
+
+    register char *str = copystr;
+    register krb5_octet *key;
+
+    register unsigned temp,i;
+    register int j;
+    register long length;
+    unsigned char *k_p;
+    int forward;
+    register char *p_char;
+    char k_char[64];
+    mit_des_key_schedule key_sked;
+
+#define min(A, B) ((A) < (B) ? (A): (B))
+
+    if ( enctype != ENCTYPE_DES )
+	return (KRB5_PROG_ENCTYPE_NOSUPP);
+
+    if ( !(keyblock->contents = (krb5_octet *)malloc(sizeof(mit_des_cblock))) )
+	return(ENOMEM);
+
+#define cleanup() {memset(keyblock->contents, 0, sizeof(mit_des_cblock));\
+		       krb5_xfree(keyblock->contents);}
+
+    keyblock->enctype = ENCTYPE_DES;
+    keyblock->length = sizeof(mit_des_cblock);
+    key = keyblock->contents;
+
+    memset(copystr, 0, sizeof(copystr));
+    j = min(data->length, 511);
+    (void) strncpy(copystr, data->data, j);
+    if ( princ != 0 )
+	for (i=0; princ[i] != 0 && j < 511; i++) {
+	    (void) strncpy(copystr+j, princ[i]->data, 
+			   min(princ[i]->length, 511-j));
+	    j += min(princ[i]->length, 511-j);
+	}
+
+    /* convert copystr to des key */
+    forward = 1;
+    p_char = k_char;
+    length = strlen(str);
+
+    /* init key array for bits */
+    memset(k_char,0,sizeof(k_char));
+
+#ifdef DEBUG
+    if (mit_des_debug)
+	fprintf(stdout,
+		"\n\ninput str length = %d  string = %s\nstring = 0x ",
+		length,str);
+#endif
+
+    /* get next 8 bytes, strip parity, xor */
+    for (i = 1; i <= length; i++) {
+	/* get next input key byte */
+	temp = (unsigned int) *str++;
+#ifdef DEBUG
+	if (mit_des_debug)
+	    fprintf(stdout,"%02x ",temp & 0xff);
+#endif
+	/* loop through bits within byte, ignore parity */
+	for (j = 0; j <= 6; j++) {
+	    if (forward)
+		*p_char++ ^= (int) temp & 01;
+	    else
+		*--p_char ^= (int) temp & 01;
+	    temp = temp >> 1;
+	}
+
+	/* check and flip direction */
+	if ((i%8) == 0)
+	    forward = !forward;
+    }
+
+    /* now stuff into the key mit_des_cblock, and force odd parity */
+    p_char = k_char;
+    k_p = (unsigned char *) key;
+
+    for (i = 0; i <= 7; i++) {
+	temp = 0;
+	for (j = 0; j <= 6; j++)
+	    temp |= *p_char++ << (1+j);
+	*k_p++ = (unsigned char) temp;
+    }
+
+    /* fix key parity */
+    mit_des_fixup_key_parity(key);
+
+    /* Now one-way encrypt it with the folded key */
+    (void) mit_des_key_sched(key, key_sked);
+    (void) mit_des_cbc_cksum((krb5_octet *)copystr, key, length, key_sked, key);
+    /* erase key_sked */
+    memset((char *)key_sked, 0, sizeof(key_sked));
+
+    /* now fix up key parity again */
+    mit_des_fixup_key_parity(key);
+
+#ifdef DEBUG
+    if (mit_des_debug)
+	fprintf(stdout,
+		"\nResulting string_to_key = 0x%x 0x%x\n",
+		*((unsigned long *) key),
+		*((unsigned long *) key+1));
+#endif
+    
+    return 0;
+}
+
+
+
+
diff --git a/krb5-1-6/src/lib/des425/t_pcbc.c b/krb5-1-6/src/lib/des425/t_pcbc.c
new file mode 100644
index 000000000..2932148b7
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/t_pcbc.c
@@ -0,0 +1,123 @@
+/*
+ * lib/des425/t_quad.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include "des_int.h"
+#include "des.h"
+
+char *progname;
+int des_debug;
+
+/* These test values were constructed by experimentation, because I
+   couldn't be bothered to look up the spec for the encryption mode
+   and see if any test vector is defined.  But really, the thing we
+   need to test is that the operation we use doesn't changed.  Like
+   with quad_cksum, compatibility is more important than strict
+   adherence to the spec, if we have to choose.  In any case, if you
+   have a useful test vector, send it in....  */
+struct {
+    unsigned char text[32];
+    des_cblock out[4];
+} tests[] = {
+    {
+	"Now is the time for all ",
+	{
+	    {  0x7f, 0x81, 0x65, 0x41, 0x21, 0xdb, 0xd4, 0xcf, },
+	    {  0xf8, 0xaa, 0x09, 0x90, 0xeb, 0xc7, 0x60, 0x2b, },
+	    {  0x45, 0x3e, 0x4e, 0x65, 0x83, 0x6c, 0xf1, 0x98, },
+	    {  0x4c, 0xfc, 0x69, 0x72, 0x23, 0xdb, 0x48, 0x78, }
+	}
+    }, {
+	"7654321 Now is the time for ",
+	{
+	    {  0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, },
+	    {  0x6d, 0xec, 0xb4, 0x70, 0xa0, 0xe5, 0x6b, 0x15, },
+	    {  0xae, 0xa6, 0xbf, 0x61, 0xed, 0x7d, 0x9c, 0x9f, },
+	    {  0xf7, 0x17, 0x46, 0x3b, 0x8a, 0xb3, 0xcc, 0x88, }
+	}
+    }, {
+	"hi",
+        { {  0x76, 0x61, 0x0e, 0x8b, 0x23, 0xa4, 0x5f, 0x34, } }
+    },
+};
+
+/* 0x0123456789abcdef */
+unsigned char default_key[8] = {
+    0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
+};
+des_cblock ivec = {
+    0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10
+};
+
+int
+main(argc,argv)
+    int argc;
+    char *argv[];
+{
+    int i;
+    int fail=0;
+    des_cblock out[32/8];
+    des_cblock out2[32/8];
+    des_key_schedule sked;
+
+    progname=argv[0];		/* salt away invoking program */
+
+    /* use known input and key */
+
+    for (i = 0; i < 3; i++) {
+	int wrong = 0, j, jmax;
+	des_key_sched (default_key, sked);
+	/* This could lose on alignment... */
+	des_pcbc_encrypt ((des_cblock *)&tests[i].text, out,
+			  strlen(tests[i].text) + 1, sked, &ivec, 1);
+	printf ("pcbc_encrypt(\"%s\") = {", tests[i].text);
+	jmax = (strlen (tests[i].text) + 8) & ~7U;
+	for (j = 0; j < jmax; j++) {
+	    if (j % 8 == 0)
+		printf ("\n\t");
+	    printf (" 0x%02x,", out[j/8][j%8]);
+	    if (out[j/8][j%8] != tests[i].out[j/8][j%8])
+		wrong = 1;
+	}
+	printf ("\n}\n");
+
+	/* reverse it */
+	des_pcbc_encrypt (out, out2, jmax, sked, &ivec, 0);
+	if (strcmp ((char *)out2, tests[i].text)) {
+	    printf ("decrypt failed\n");
+	    wrong = 1;
+	} else
+	    printf ("decrypt worked\n");
+
+	if (wrong) {
+	    printf ("wrong result!\n");
+	    fail = 1;
+	}
+    }
+    return fail;
+}
diff --git a/krb5-1-6/src/lib/des425/t_quad.c b/krb5-1-6/src/lib/des425/t_quad.c
new file mode 100644
index 000000000..b9299fd20
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/t_quad.c
@@ -0,0 +1,101 @@
+/*
+ * lib/des425/t_quad.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include "des_int.h"
+#include "des.h"
+
+extern unsigned long quad_cksum();
+char *progname;
+int des_debug;
+unsigned DES_INT32 out[8];
+struct {
+    unsigned char text[64];
+    unsigned DES_INT32 out[8];
+} tests[] = {
+    {
+	"Now is the time for all ",
+	{
+	    0x6c6240c5, 0x77db9b1c, 0x7991d316, 0x4e688989,
+	    0x27a0ae6a, 0x13be2da4, 0x4a2fdfc6, 0x7dfc494c,
+	}
+    }, {
+	"7654321 Now is the time for ",
+	{
+	    0x36839db5, 0x4d7be717, 0x15b0f5b6, 0x2304ff9c,
+	    0x75472d26, 0x6a5f833c, 0x7399a4ee, 0x1170fdfb,
+	}
+    }, {
+	{2,0,0,0, 1,0,0,0},
+	{
+	    0x7c81f205, 0x63d38e38, 0x314ece44, 0x05d3a4f8,
+	    0x6e10db76, 0x3eda7685, 0x2e841332, 0x1bdc7fd3,
+	}
+    },
+};
+
+/* 0x0123456789abcdef */
+unsigned char default_key[8] = {
+    0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
+};
+
+int
+main(argc,argv)
+    int argc;
+    char *argv[];
+{
+    int i;
+    int fail=0;
+
+    progname=argv[0];		/* salt away invoking program */
+
+    /* use known input and key */
+
+    for (i = 0; i < 3; i++) {
+	int wrong = 0, j;
+	des_quad_cksum (tests[i].text, out, 64L, 4,
+			(mit_des_cblock *) &default_key);
+	if (tests[i].text[0] == 2)
+	    printf ("quad_cksum(<binary blob 1>) = {");
+	else
+	    printf ("quad_cksum(\"%s\"...zero fill...) = {", tests[i].text);
+	for (j = 0; j < 8; j++) {
+	    if (j == 0 || j == 4)
+		printf ("\n\t");
+	    printf (" 0x%lx,", (unsigned long) out[j]);
+	    if (out[j] != tests[i].out[j])
+		wrong = 1;
+	}
+	printf ("\n}\n");
+	if (wrong) {
+	    printf ("wrong result!\n");
+	    fail = 1;
+	}
+    }
+    return fail;
+}
diff --git a/krb5-1-6/src/lib/des425/unix_time.c b/krb5-1-6/src/lib/des425/unix_time.c
new file mode 100644
index 000000000..53ce03b68
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/unix_time.c
@@ -0,0 +1,46 @@
+/*
+ * unix_time.c
+ * 
+ * Glue code for pasting Kerberos into the Unix environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ *
+ * Required for use by the Cygnus krb.a.
+ */
+
+
+#include "k5-int.h"
+
+#if !defined(_WIN32)
+#include <sys/time.h>
+
+krb5_ui_4
+unix_time_gmt_unixsec (usecptr)
+     krb5_ui_4	*usecptr;
+{
+	struct timeval	now;
+
+	(void) gettimeofday (&now, (struct timezone *)0);
+	if (usecptr)
+		*usecptr = now.tv_usec;
+	return now.tv_sec;
+}
+
+#endif /* !_WIN32 */
+
+#ifdef _WIN32
+#include <time.h>
+
+krb5_ui_4
+unix_time_gmt_unixsec (usecptr)
+    krb5_ui_4 *usecptr;
+{
+    time_t gmt;
+
+    time(&gmt);
+    if (usecptr)
+	*usecptr = gmt;
+    return gmt;
+}
+#endif /* _WIN32 */
diff --git a/krb5-1-6/src/lib/des425/util.c b/krb5-1-6/src/lib/des425/util.c
new file mode 100644
index 000000000..2c5ef9216
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/util.c
@@ -0,0 +1,33 @@
+/*
+ * lib/des425/util.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Miscellaneous debug printing utilities
+ */
+
+#include <stdio.h>
+
+/* Application include files */
+#include "k5-int.h"
+#include "des_int.h"
+#include "des.h"
+
+void des_cblock_print_file(x, fp)
+    des_cblock *x;
+    FILE *fp;
+{
+    unsigned char *y = *x;
+    register int i = 0;
+    fprintf(fp," 0x { ");
+
+    while (i++ < 8) {
+	fprintf(fp,"%x",*y++);
+	if (i < 8)
+	    fprintf(fp,", ");
+    }
+    fprintf(fp," }");
+}
diff --git a/krb5-1-6/src/lib/des425/verify.c b/krb5-1-6/src/lib/des425/verify.c
new file mode 100644
index 000000000..653730a2f
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/verify.c
@@ -0,0 +1,317 @@
+/*
+ * lib/des425/verify.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Program to test the correctness of the DES library
+ * implementation.
+ *
+ * exit returns	 0 ==> success
+ * 		-1 ==> error
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include "des_int.h"
+#include "des.h"
+
+char *progname;
+int nflag = 2;
+int vflag;
+int mflag;
+int zflag;
+int pid;
+int des_debug;
+des_key_schedule KS;
+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 ";
+unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0};
+unsigned char output[64];
+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;
+
+/* 0x0123456789abcdef */
+unsigned char default_key[8] = {
+    0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
+};
+unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f };
+unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 };
+des_cblock s_key;
+unsigned char default_ivec[8] = {
+    0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef
+};
+unsigned char *ivec;
+unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */
+int i,j;
+
+unsigned char cipher1[8] = {
+    0x25,0xdd,0xac,0x3e,0x96,0x17,0x64,0x67
+};
+unsigned char cipher2[8] = {
+    0x3f,0xa4,0x0e,0x8a,0x98,0x4d,0x48,0x15
+};
+unsigned char cipher3[64] = {
+    0xe5,0xc7,0xcd,0xde,0x87,0x2b,0xf2,0x7c,
+    0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+    0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6
+};
+unsigned char checksum[8] = {
+    0x58,0xd2,0xe7,0x7e,0x86,0x06,0x27,0x33
+};
+
+unsigned char zresult[8] = {
+    0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7
+};
+
+unsigned char mresult[8] = {
+    0xa3, 0x80, 0xe0, 0x2a, 0x6b, 0xe5, 0x46, 0x96
+};
+
+   
+/*
+ * Can also add :
+ * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?)
+ */
+
+void do_encrypt (unsigned char *, unsigned char *);
+void do_decrypt (unsigned char *, unsigned char *);
+
+int
+main(argc,argv)
+    int argc;
+    char *argv[];
+{
+    /* Local Declarations */
+    unsigned long in_length;
+
+    progname=argv[0];		/* salt away invoking program */
+
+    while (--argc > 0 && (*++argv)[0] == '-')
+	for (i=1; argv[0][i] != '\0'; i++) {
+	    switch (argv[0][i]) {
+
+		/* debug flag */
+	    case 'd':
+		des_debug=3;
+		continue;
+
+	    case 'z':
+		zflag = 1;
+		continue;
+
+	    case 'm':
+		mflag = 1;
+		continue;
+
+	    default:
+		printf("%s: illegal flag \"%c\" ",
+		       progname,argv[0][i]);
+		exit(1);
+	    }
+	};
+
+    if (argc) {
+	fprintf(stderr, "Usage: %s [-dmz]\n", progname);
+	exit(1);
+    }
+
+    /* use known input and key */
+
+    /* ECB zero text zero key */
+    if (zflag) {
+	input = zero_text;
+	des_key_sched(zero_key,KS);
+	printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n");
+	do_encrypt(input,cipher_text);
+	printf("\tcipher  = (low to high bytes)\n\t\t");
+	for (j = 0; j<=7; j++)
+	    printf("%02x ",cipher_text[j]);
+	printf("\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)zresult, 8) ) {
+	    printf("verify: error in zero key test\n");
+	    exit(-1);
+	}
+	exit(0);
+    }
+
+    if (mflag) {
+	input = msb_text;
+	des_key_sched(key3,KS);
+	printf("plaintext = 0x00 00 00 00 00 00 00 40, ");
+	printf("key = 0, cipher = 0x??\n");
+	do_encrypt(input,cipher_text);
+	printf("\tcipher  = (low to high bytes)\n\t\t");
+	for (j = 0; j<=7; j++) {
+	    printf("%02x ",cipher_text[j]);
+	}
+	printf("\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)mresult, 8) ) {
+	    printf("verify: error in msb test\n");
+	    exit(-1);
+	}
+	exit(0);
+    }
+
+    /* ECB mode Davies and Price */
+    {
+	input = zero_text;
+	des_key_sched(key2,KS);
+	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");
+	printf("Examples per Davies and Price.\n\n");
+	printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n");
+	printf("\tclear = 0\n");
+	printf("\tcipher = 25 dd ac 3e 96 17 64 67\n");
+	printf("ACTUAL ECB\n");
+	printf("\tclear \"%s\"\n", input);
+	do_encrypt(input,cipher_text);
+	printf("\tcipher  = (low to high bytes)\n\t\t");
+	for (j = 0; j<=7; j++)
+	    printf("%02x ",cipher_text[j]);
+	printf("\n\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)cipher1, 8) ) {
+	    printf("verify: error in ECB encryption\n");
+	    exit(-1);
+	}
+	else 
+	    printf("verify: ECB encription is correct\n\n");
+    }
+
+    /* ECB mode */
+    {
+	des_key_sched(default_key,KS);
+	input = clear_text;
+	ivec = default_ivec;
+	printf("EXAMPLE ECB\tkey = 0123456789abcdef\n");
+	printf("\tclear = \"Now is the time for all \"\n");
+	printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n");
+	printf("ACTUAL ECB\n\tclear \"%s\"",input);
+	do_encrypt(input,cipher_text);
+	printf("\n\tcipher	= (low to high bytes)\n\t\t");
+	for (j = 0; j<=7; j++) {
+	    printf("%02x ",cipher_text[j]);
+	}
+	printf("\n\n");
+	do_decrypt(output,cipher_text);
+	if ( memcmp((char *)cipher_text, (char *)cipher2, 8) ) {
+	    printf("verify: error in ECB encryption\n");
+	    exit(-1);
+	}
+	else 
+	    printf("verify: ECB encription is correct\n\n");
+    }
+
+    /* CBC mode */
+    printf("EXAMPLE CBC\tkey = 0123456789abcdef");
+    printf("\tiv = 1234567890abcdef\n");
+    printf("\tclear = \"Now is the time for all \"\n");
+    printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n");
+    printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n");
+    printf("\t\t\t68 37 88 49 9a 7c 05 f6\n");
+
+    printf("ACTUAL CBC\n\tclear \"%s\"\n",input);
+    in_length = strlen((char *) input);
+    des_cbc_encrypt(input,cipher_text, in_length,KS,ivec,1);
+    printf("\tciphertext = (low to high bytes)\n");
+    for (i = 0; i <= 7; i++) {
+	printf("\t\t");
+	for (j = 0; j <= 7; j++) {
+	    printf("%02x ",cipher_text[i*8+j]);
+	}
+	printf("\n");
+    }
+    des_cbc_encrypt(cipher_text,clear_text,in_length,KS,ivec,0);
+    printf("\tdecrypted clear_text = \"%s\"\n",clear_text);
+
+    if ( memcmp(cipher_text, cipher3, (size_t) in_length) ) {
+	printf("verify: error in CBC encryption\n");
+	exit(-1);
+    }
+    else 
+	printf("verify: CBC encription is correct\n\n");
+
+    printf("EXAMPLE CBC checksum");
+    printf("\tkey =  0123456789abcdef\tiv =  1234567890abcdef\n");
+    printf("\tclear =\t\t\"7654321 Now is the time for \"\n");
+    printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, ");
+    printf("or some part thereof\n");
+    input = clear_text2;
+    des_cbc_cksum(input,cipher_text,(long) strlen((char *) input),KS,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 ( memcmp((char *)cipher_text, (char *)checksum, 8) ) {
+	printf("verify: error in CBC cheksum\n");
+	exit(-1);
+    }
+    else 
+	printf("verify: CBC checksum is correct\n\n");
+    exit(0);
+}
+
+void
+do_encrypt(in,out)
+    unsigned char *in;
+    unsigned char *out;
+{
+    for (i =1; i<=nflag; i++) {
+	des_ecb_encrypt((unsigned long *) in, (unsigned long *)out, KS, 1);
+	if (des_debug) {
+	    printf("\nclear %s\n",in);
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",in[j] & 0xff);
+	    printf("\tcipher ");
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",out[j] & 0xff);
+	}
+    }
+}
+
+void
+do_decrypt(in,out)
+    unsigned char *out;
+    unsigned char *in;
+    /* try to invert it */
+{
+    for (i =1; i<=nflag; i++) {
+	des_ecb_encrypt((unsigned long *) out, (unsigned long *)in,KS,0);
+	if (des_debug) {
+	    printf("clear %s\n",in);
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",in[j] & 0xff);
+	    printf("\tcipher ");
+	    for (j = 0; j<=7; j++)
+		printf("%02X ",out[j] & 0xff);
+	}
+    }
+}
diff --git a/krb5-1-6/src/lib/des425/weak_key.c b/krb5-1-6/src/lib/des425/weak_key.c
new file mode 100644
index 000000000..f4ef6fbc5
--- /dev/null
+++ b/krb5-1-6/src/lib/des425/weak_key.c
@@ -0,0 +1,41 @@
+/*
+ * lib/des425/weak_key.c
+ *
+ * Copyright 1989,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "des_int.h"
+#include "des.h"
+
+/*
+ * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key.
+ *
+ * Requires: key has correct odd parity.
+ */
+int
+des_is_weak_key(key)
+     mit_des_cblock key;
+{
+	return (mit_des_is_weak_key(key));
+}
diff --git a/krb5-1-6/src/lib/glue4.c b/krb5-1-6/src/lib/glue4.c
new file mode 100644
index 000000000..bf9bbd8a0
--- /dev/null
+++ b/krb5-1-6/src/lib/glue4.c
@@ -0,0 +1,19 @@
+#include "krb5.h"
+
+krb5_data string_list[3] = {
+{11, "FOO.MIT.EDU"},
+{6, "jtkohl"},
+};
+
+krb5_data *princ[] = {&string_list[0], &string_list[1], 0};
+
+krb5_data string_list2[3] = {
+{11, "FOO.MIT.EDU"},
+{4, "rcmd"},
+{13, "lycus.mit.edu"},
+};
+
+krb5_data *princ2[] = {&string_list2[0], &string_list2[1], &string_list2[2], 0};
+				   
+krb5_last_req_entry lrentries[] = { {32000, 1}, {0, 3}, {10, 2} };
+krb5_last_req_entry *lrfoo1[] = {&lrentries[0], &lrentries[1], &lrentries[2], 0};
diff --git a/krb5-1-6/src/lib/gssapi/LICENSE b/krb5-1-6/src/lib/gssapi/LICENSE
new file mode 100644
index 000000000..612f8ad6e
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/LICENSE
@@ -0,0 +1,91 @@
+[ NOTE: MIT has only incorporated the mechglue and spnego change, and
+not the incremental propagation changes.  The filenames are different
+between the Sun and MIT sources.  The actual MIT filenames appear in
+the top-level README file.  Original text of Sun's LICENSE file
+follows. ]
+
+Subject to the license set forth below, Sun Microsystems, Inc. donates
+the attached files to MIT for the purpose of including these
+modifications and additions in future versions of the Kerberos system.
+
+Many of the files attached are subject to licenses issued by other
+entities, including OpenVision, MIT, and FundsXpress.  See the
+individual files, and/or related Readme files, for these licenses.
+
+In addition Sun requires that the license set forth below be
+incorporated into any future version of the Kerberos system which
+contains portions of the files attached.  The following files must be
+listed, in the top level Readme file, as being provided subject to such
+license:
+
+cmd/krb5/iprop/iprop.x
+cmd/krb5/iprop/iprop_hdr.h
+cmd/krb5/kadmin/server/ipropd_svc.c
+cmd/krb5/kproplog/kproplog.c
+cmd/krb5/slave/kpropd_rpc.c
+lib/gss_mechs/mech_krb5/et/kdb5_err.c
+lib/gss_mechs/mech_spnego/mech/gssapiP_spnego.h
+lib/gss_mechs/mech_spnego/mech/spnego_mech.c
+lib/krb5/kadm5/kadm_host_srv_names.c
+lib/krb5/kdb/kdb_convert.c
+lib/krb5/kdb/kdb_hdr.h
+lib/krb5/kdb/kdb_log.c
+lib/krb5/kdb/kdb_log.h
+lib/libgss/g_accept_sec_context.c
+lib/libgss/g_acquire_cred.c
+lib/libgss/g_canon_name.c
+lib/libgss/g_compare_name.c
+lib/libgss/g_context_time.c
+lib/libgss/g_delete_sec_context.c
+lib/libgss/g_dsp_name.c
+lib/libgss/g_dsp_status.c
+lib/libgss/g_dup_name.c
+lib/libgss/g_exp_sec_context.c
+lib/libgss/g_export_name.c
+lib/libgss/g_glue.c
+lib/libgss/g_imp_name.c
+lib/libgss/g_imp_sec_context.c
+lib/libgss/g_init_sec_context.c
+lib/libgss/g_initialize.c
+lib/libgss/g_inquire_context.c
+lib/libgss/g_inquire_cred.c
+lib/libgss/g_inquire_names.c
+lib/libgss/g_process_context.c
+lib/libgss/g_rel_buffer.c
+lib/libgss/g_rel_cred.c
+lib/libgss/g_rel_name.c
+lib/libgss/g_rel_oid_set.c
+lib/libgss/g_seal.c
+lib/libgss/g_sign.c
+lib/libgss/g_store_cred.c
+lib/libgss/g_unseal.c
+lib/libgss/g_userok.c
+lib/libgss/g_utils.c
+lib/libgss/g_verify.c
+lib/libgss/gssd_pname_to_uid.c
+uts/common/gssapi/include/gssapi_err_generic.h
+uts/common/gssapi/include/mechglueP.h
+
+Sun's License is as follows:
+
+Copyright (c) 2004 Sun Microsystems, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/krb5-1-6/src/lib/gssapi/Makefile.in b/krb5-1-6/src/lib/gssapi/Makefile.in
new file mode 100644
index 000000000..bd767f98e
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/Makefile.in
@@ -0,0 +1,159 @@
+thisconfigdir=../..
+myfulldir=lib/gssapi
+mydir=lib/gssapi
+BUILDTOP=$(REL)..$(S)..
+LOCAL_SUBDIRS= generic mechglue krb5 spnego
+DEFS=
+
+##DOSLIBNAME=$(OUTPRE)gssapi.lib
+##DOSOBJFILELIST=@$(OUTPRE)mechglue.lst @$(OUTPRE)spnego.lst @$(OUTPRE)generic.lst @$(OUTPRE)krb5.lst @$(OUTPRE)gssapi.lst
+##DOSOBJFILEDEP=$(OUTPRE)mechglue.lst $(OUTPRE)spnego.lst $(OUTPRE)generic.lst $(OUTPRE)krb5.lst $(OUTPRE)gssapi.lst
+
+##DOSOBJFILE=$(OUTPRE)gssapi.lst
+##DOSLIBOBJS=$(OBJS)
+
+##DOS##DLL_EXP_TYPE=GSS
+
+LOCALINCLUDES = -Igeneric -I$(srcdir)/generic -Ikrb5 -I$(srcdir)/krb5 -I$(srcdir)/mechglue
+STLIBOBJS=\
+	gss_libinit.o
+
+OBJS=\
+	$(OUTPRE)gss_libinit.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/gss_libinit.c
+
+LIBBASE=gssapi_krb5
+LIBMAJOR=2
+LIBMINOR=2
+LIBINITFUNC=gssint_lib_init
+LIBFINIFUNC=gssint_lib_fini
+STOBJLISTS=OBJS.ST generic/OBJS.ST mechglue/OBJS.ST krb5/OBJS.ST spnego/OBJS.ST
+SUBDIROBJLISTS=generic/OBJS.ST mechglue/OBJS.ST krb5/OBJS.ST spnego/OBJS.ST
+SHLIB_EXPDEPS=\
+	$(KRB5_DEPLIB) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB) $(COM_ERR_DEPLIB)
+SHLIB_EXPLIBS=-lkrb5 -lk5crypto -lcom_err $(SUPPORT_LIB) $(DL_LIB) $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+RELDIR=gssapi
+
+all-unix:: all-liblinks @MAINT@ verify-calling-conventions-gssapi
+
+install-unix:: install-libs
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs clean-misc-unix
+
+clean-windows::
+	$(RM) gssapi.lib gssapi.bak
+
+clean-misc-unix:
+	$(RM) merged-gssapi-header.h
+
+EHDRDIR=$(BUILDTOP)$(S)include$(S)gssapi
+EXPORTED_HEADERS= \
+	$(EHDRDIR)$(S)gssapi_krb5.h \
+	$(EHDRDIR)$(S)gssapi_generic.h \
+	$(EHDRDIR)$(S)gssapi.h
+merged-gssapi-header.h: $(EXPORTED_HEADERS)
+	cat $(EXPORTED_HEADERS) > merged.tmp
+	$(MV) merged.tmp merged-gssapi-header.h
+verify-calling-conventions-gssapi: merged-gssapi-header.h
+	$(PERL) -w $(SRCTOP)/util/def-check.pl merged-gssapi-header.h $(srcdir)/../gssapi32.def
+
+all-windows::
+	cd generic
+	@echo Making in gssapi\generic
+	$(MAKE) -$(MFLAGS)
+	cd ..\krb5
+	@echo Making in gssapi\krb5
+	$(MAKE) -$(MFLAGS)
+	cd ..\mechglue
+	@echo Making in gssapi\mechglue
+	$(MAKE) -$(MFLAGS)
+	cd ..\spnego
+	@echo Making in gssapi\spnego
+	$(MAKE) -$(MFLAGS)
+	cd ..
+
+clean-windows::
+	cd generic
+	@echo Making clean in gssapi\generic
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\krb5
+	@echo Making clean in gssapi\krb5
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\mechglue
+	@echo Making clean in gssapi\mechglue
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\spnego
+	@echo Making clean in gssapi\spnego
+	$(MAKE) -$(MFLAGS) clean
+	cd ..
+	@echo Making clean in gssapi
+
+# These rules are an attempt to handle several different problems:
+#
+# Certain files in subdirectories must be made current by the
+# recursion step before we can build files in this directory that
+# depend on them.  Existing but out-of-date versions must not be used.
+#
+# In a parallel make, nothing should be built more than once.  This
+# effect can be exaggerated for testing by sticking "sleep 5" into the
+# rules for generating the files in subdirectories.  For example, in
+# between testing for a directory and creating it -- do you then get
+# mkdir complaining that the directory exists?  Adding the sleep
+# command may also exaggerate the build-with-outdated-headers problem,
+# by causing the timestamp on the newly generated header to be several
+# seconds newer than object files built with its old version, even on
+# fast machines where the UNIX filesystem's one-second granularity
+# would mask the problem.
+#
+# We must not cause these files to always be considered newly updated
+# when it comes time to build the object files in this directory.
+# Otherwise, we wind up recompiling some files every time we run make.
+
+# This set of rules fails the parallel make case; it can build
+# gssapi-include and all-recurse at the same time, and both will
+# create include/gssapi and gssapi.h.
+#$(BUILDTOP)/include/gssapi/gssapi.h: generic/gssapi.h
+#	(cd generic && $(MAKE) gssapi-include)
+#generic/gssapi.h: generic/gssapi.hin
+#	(cd generic && $(MAKE) gssapi.h)
+#generic/gssapi_err_generic.h: generic/gssapi_err_generic.et
+#	(cd generic && $(MAKE) gssapi_err_generic.h)
+#krb5/gssapi_err_krb5.h: krb5/gssapi_err_krb5.et
+#	(cd krb5 && $(MAKE) gssapi_err_krb5.h)
+
+# This version, without the no-op command to run, reportedly caused
+# repeated rebuilds in certain cases.  With the no-op command, it
+# appears to be properly serializing the subdir processing and local
+# compiles... so far.
+##DOS##!if 0
+$(EXPORTED_HEADERS) generic/gssapi.h krb5/gssapi_err_krb5.h generic/gssapi_err_generic.h krb5/gssapi_krb5.h: all-recurse
+	: $@ updated by recursion rule
+##DOS##!endif
+
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+gss_libinit.so gss_libinit.po $(OUTPRE)gss_libinit.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/generic/gssapiP_generic.h \
+  $(srcdir)/generic/gssapi_generic.h $(srcdir)/krb5/gssapiP_krb5.h \
+  $(srcdir)/mechglue/mechglue.h $(srcdir)/mechglue/mglueP.h \
+  generic/gssapi_err_generic.h gss_libinit.c gss_libinit.h \
+  krb5/gssapi_err_krb5.h krb5/gssapi_krb5.h
diff --git a/krb5-1-6/src/lib/gssapi/README_SAMPLE_APP b/krb5-1-6/src/lib/gssapi/README_SAMPLE_APP
new file mode 100644
index 000000000..c26bb09ad
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/README_SAMPLE_APP
@@ -0,0 +1,4 @@
+A sample GSS-API client and server application can be found in the
+directory ./appl/gss-sample in this distribution.  Read the file
+./appl/gss-sample/README for information on how it works and how to
+build it.
diff --git a/krb5-1-6/src/lib/gssapi/generic/Makefile.in b/krb5-1-6/src/lib/gssapi/generic/Makefile.in
new file mode 100644
index 000000000..e63be6b78
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/Makefile.in
@@ -0,0 +1,205 @@
+thisconfigdir=../../..
+myfulldir=lib/gssapi/generic
+mydir=lib/gssapi/generic
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=generic
+##DOS##OBJFILE=..\$(OUTPRE)generic.lst
+
+##DOS##DLL_EXP_TYPE=GSS
+
+ETSRCS= gssapi_err_generic.c
+ETOBJS= $(OUTPRE)gssapi_err_generic.$(OBJEXT)
+ETHDRS= gssapi_err_generic.h
+
+EHDRDIR= $(BUILDTOP)$(S)include$(S)gssapi
+
+HDRS=	$(EHDRDIR)$(S)gssapi.h \
+	$(EHDRDIR)$(S)gssapi_generic.h
+
+MK_EHDRDIR=if test -d $(EHDRDIR); then :; else (set -x; mkdir $(EHDRDIR)); fi
+##DOS##MK_EHDRDIR=rem
+
+gssapi-include: $(EHDRDIR)$(S)gssapi.h
+
+$(EHDRDIR)$(S)gssapi.h: $(EHDRDIR)$(S)timestamp gssapi.h
+	$(CP) gssapi.h $@
+$(EHDRDIR)$(S)gssapi_generic.h: $(EHDRDIR)$(S)timestamp $(srcdir)$(S)gssapi_generic.h
+	$(CP) $(srcdir)$(S)gssapi_generic.h $@
+
+$(EHDRDIR)$(S)timestamp:
+	$(MK_EHDRDIR)
+	echo timestamp > $(EHDRDIR)$(S)timestamp
+
+$(OUTPRE)gssapi_err_generic.$(OBJEXT): gssapi_err_generic.c
+gssapi_err_generic.h: gssapi_err_generic.et
+gssapi_err_generic.c: gssapi_err_generic.et
+
+include_stdint=@include_stdint@
+include_inttypes=@include_inttypes@
+include_xom=@include_xom@
+##DOS##include_stdint=rem
+##DOS##include_inttypes=rem
+##DOS##include_xom=rem
+gssapi.h: gssapi.hin $(BUILDTOP)/include/autoconf.h
+	@echo "Creating gssapi.h" ; \
+	h=gss$$$$; $(RM) $$h; \
+	(echo "/* This is the gssapi.h prologue. */"; \
+	$(include_stdint) && \
+	$(include_inttypes) && \
+	$(include_xom) && \
+	echo "/* End of gssapi.h prologue. */"&& \
+	cat $(srcdir)/gssapi.hin )> $$h && \
+	(set -x; $(MV) $$h $@) ; e=$$?; $(RM) $$h; exit $$e
+
+#if HasHashLibrary
+# UTIL_VALIDATE_SRC= $(srcdir)/util_validate.c
+# UTIL_VALIDATE_OBJ= util_validate.$(OBJEXT)
+#else
+#UTIL_VALIDATE_SRC= $(srcdir)/utl_nohash_validate.c
+#UTIL_VALIDATE_OBJ= utl_nohash_validate.$(OBJEXT)
+#endif
+
+SRCS = \
+	$(srcdir)/disp_com_err_status.c \
+	$(srcdir)/disp_major_status.c \
+	$(srcdir)/gssapi_generic.c \
+	$(srcdir)/rel_buffer.c \
+	$(srcdir)/rel_oid_set.c \
+	$(srcdir)/util_buffer.c \
+	$(srcdir)/util_ordering.c \
+	$(srcdir)/util_set.c \
+	$(srcdir)/util_token.c \
+	$(srcdir)/util_validate.c \
+	gssapi_err_generic.c
+
+OBJS = \
+	$(OUTPRE)disp_com_err_status.$(OBJEXT) \
+	$(OUTPRE)disp_major_status.$(OBJEXT) \
+	$(OUTPRE)gssapi_generic.$(OBJEXT) \
+	$(OUTPRE)rel_buffer.$(OBJEXT) \
+	$(OUTPRE)rel_oid_set.$(OBJEXT) \
+	$(OUTPRE)util_buffer.$(OBJEXT) \
+	$(OUTPRE)util_ordering.$(OBJEXT) \
+	$(OUTPRE)util_set.$(OBJEXT) \
+	$(OUTPRE)util_token.$(OBJEXT) \
+	$(OUTPRE)util_validate.$(OBJEXT) \
+	$(OUTPRE)gssapi_err_generic.$(OBJEXT)
+
+STLIBOBJS = \
+	disp_com_err_status.o \
+	disp_major_status.o \
+	gssapi_generic.o \
+	rel_buffer.o \
+	rel_oid_set.o \
+	util_buffer.o \
+	util_ordering.o \
+	util_set.o \
+	util_token.o \
+	util_validate.o \
+	gssapi_err_generic.o
+
+EXPORTED_HEADERS= gssapi_generic.h
+EXPORTED_BUILT_HEADERS= gssapi.h
+
+$(OBJS): $(EXPORTED_HEADERS) $(ETHDRS)
+
+all-unix:: $(EXPORTED_HEADERS) $(ETHDRS) $(HDRS)
+all-unix:: all-libobjs
+
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-windows:: win-create-ehdrdir
+all-windows:: $(HDRS)
+
+win-create-ehdrdir:
+	if not exist $(EHDRDIR)\nul mkdir $(EHDRDIR)
+
+clean-unix:: clean-libobjs
+	$(RM) $(ETHDRS) $(ETSRCS) $(HDRS) $(EXPORTED_BUILT_HEADERS) \
+		$(EHDRDIR)$(S)timestamp
+
+clean-windows::
+	$(RM) $(HDRS)
+	-if exist $(EHDRDIR)\nul rmdir $(EHDRDIR)
+
+generate-files-mac: gssapi.h
+
+# Krb5InstallHeaders($(EXPORTED_HEADERS), $(KRB5_INCDIR)/krb5)
+install-headers-unix install:: gssapi.h
+	@set -x; for f in $(EXPORTED_HEADERS) ; \
+	do $(INSTALL_DATA) $(srcdir)/$$f	\
+		$(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \
+	done
+	@set -x; for f in $(EXPORTED_BUILT_HEADERS) ; \
+	do $(INSTALL_DATA) $$f	\
+		$(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \
+	done
+
+depend:: $(ETSRCS)
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+disp_com_err_status.so disp_com_err_status.po $(OUTPRE)disp_com_err_status.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(srcdir)/../gss_libinit.h \
+  disp_com_err_status.c gssapiP_generic.h gssapi_err_generic.h \
+  gssapi_generic.h
+disp_major_status.so disp_major_status.po $(OUTPRE)disp_major_status.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  disp_major_status.c gssapiP_generic.h gssapi_err_generic.h \
+  gssapi_generic.h
+gssapi_generic.so gssapi_generic.po $(OUTPRE)gssapi_generic.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.c \
+  gssapi_generic.h
+rel_buffer.so rel_buffer.po $(OUTPRE)rel_buffer.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
+  rel_buffer.c
+rel_oid_set.so rel_oid_set.po $(OUTPRE)rel_oid_set.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
+  rel_oid_set.c
+util_buffer.so util_buffer.po $(OUTPRE)util_buffer.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
+  util_buffer.c
+util_ordering.so util_ordering.po $(OUTPRE)util_ordering.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
+  util_ordering.c
+util_set.so util_set.po $(OUTPRE)util_set.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
+  util_set.c
+util_token.so util_token.po $(OUTPRE)util_token.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
+  util_token.c
+util_validate.so util_validate.po $(OUTPRE)util_validate.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(srcdir)/../gss_libinit.h \
+  gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \
+  util_validate.c
+gssapi_err_generic.so gssapi_err_generic.po $(OUTPRE)gssapi_err_generic.$(OBJEXT): \
+  $(COM_ERR_DEPS) gssapi_err_generic.c
diff --git a/krb5-1-6/src/lib/gssapi/generic/disp_com_err_status.c b/krb5-1-6/src/lib/gssapi/generic/disp_com_err_status.c
new file mode 100644
index 000000000..c04b67265
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/disp_com_err_status.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_generic.h"
+#include "gss_libinit.h"
+#include "com_err.h"
+
+/* XXXX internationalization!! */
+
+/**/
+
+static const char * const no_error = "No error";
+
+/**/
+
+/* if status_type == GSS_C_GSS_CODE, return up to three error messages,
+     for routine errors, call error, and status, in that order.
+     message_context == 0 : print the routine error
+     message_context == 1 : print the calling error
+     message_context > 2  : print supplementary info bit (message_context-2)
+   if status_type == GSS_C_MECH_CODE, return the output from error_message()
+   */
+
+OM_uint32
+g_display_com_err_status(minor_status, status_value, status_string)
+     OM_uint32 *minor_status;
+     OM_uint32 status_value;
+     gss_buffer_t status_string;
+{
+   status_string->length = 0;
+   status_string->value = NULL;
+
+   (void) gssint_initialize_library();
+
+   if (! g_make_string_buffer(((status_value == 0)?no_error:
+			       error_message(status_value)),
+			      status_string)) {
+      *minor_status = ENOMEM;
+      return(GSS_S_FAILURE);
+   }
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/disp_major_status.c b/krb5-1-6/src/lib/gssapi/generic/disp_major_status.c
new file mode 100644
index 000000000..218370d14
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/disp_major_status.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_generic.h"
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * $Id$
+ */
+
+/* This code has knowledge of the min and max errors of each type
+   within the gssapi major status */
+
+#define GSS_ERROR_STR(value, array, select, min, max, num) \
+   (((select(value) < (min)) || (select(value) > (max))) ? NULL : \
+    (array)[num(value)])
+
+/**/
+
+static const char * const calling_error_string[] = {
+   NULL,
+   "A required input parameter could not be read",
+   "A required input parameter could not be written",
+   "A parameter was malformed",
+};
+ 
+static const char * const calling_error = "calling error";
+
+#define GSS_CALLING_ERROR_STR(x) \
+   GSS_ERROR_STR((x), calling_error_string, GSS_CALLING_ERROR, \
+		 GSS_S_CALL_INACCESSIBLE_READ, GSS_S_CALL_BAD_STRUCTURE, \
+		 GSS_CALLING_ERROR_FIELD)
+
+/**/
+
+static const char * const routine_error_string[] = {
+   NULL,
+   "An unsupported mechanism was requested",
+   "An invalid name was supplied",
+   "A supplied name was of an unsupported type",
+   "Incorrect channel bindings were supplied",
+   "An invalid status code was supplied",
+   "A token had an invalid signature",
+   "No credentials were supplied",
+   "No context has been established",
+   "A token was invalid",
+   "A credential was invalid",
+   "The referenced credentials have expired",
+   "The context has expired",
+   "Miscellaneous failure",
+   "The quality-of-protection requested could not be provided",
+   "The operation is forbidden by the local security policy",
+   "The operation or option is not available",
+};   
+
+static const char * const routine_error = "routine error";
+
+#define GSS_ROUTINE_ERROR_STR(x) \
+   GSS_ERROR_STR((x), routine_error_string, GSS_ROUTINE_ERROR, \
+		 GSS_S_BAD_MECH, GSS_S_FAILURE, \
+		 GSS_ROUTINE_ERROR_FIELD)
+
+/**/
+
+/* this becomes overly gross after about 4 strings */
+
+static const char * const sinfo_string[] = {
+   "The routine must be called again to complete its function",
+   "The token was a duplicate of an earlier token",
+   "The token's validity period has expired",
+   "A later token has already been processed",
+};
+
+static const char * const sinfo_code = "supplementary info code";
+
+#define LSBGET(x) ((((x)^((x)-1))+1)>>1)
+#define LSBMASK(n) ((1<<(n))^((1<<(n))-1))
+
+#define GSS_SINFO_STR(x) \
+   ((((1<<(x)) < GSS_S_CONTINUE_NEEDED) || ((1<<(x)) > GSS_S_UNSEQ_TOKEN)) ? \
+    /**/NULL:sinfo_string[(x)])
+
+/**/
+
+static const char * const no_error = "No error";
+static const char * const unknown_error = "Unknown %s (field = %d)";
+
+/**/
+
+static int 
+display_unknown(kind, value, buffer)
+     const char *kind;
+     OM_uint32 value;
+     gss_buffer_t buffer;
+{
+   char *str;
+
+   if ((str =
+	(char *) xmalloc(strlen(unknown_error)+strlen(kind)+7)) == NULL)
+      return(0);
+
+   sprintf(str, unknown_error, kind, value);
+
+   buffer->length = strlen(str);
+   buffer->value = str;
+
+   return(1);
+}
+
+/* code should be set to the calling error field */
+
+static OM_uint32 display_calling(minor_status, code, status_string)
+     OM_uint32 *minor_status;
+     OM_uint32 code;
+     gss_buffer_t status_string;
+{
+   const char *str;
+
+   if ((str = GSS_CALLING_ERROR_STR(code))) {
+      if (! g_make_string_buffer(str, status_string)) {
+	 *minor_status = ENOMEM;
+	 return(GSS_S_FAILURE);
+      }
+   } else {
+      if (! display_unknown(calling_error, GSS_CALLING_ERROR_FIELD(code),
+			    status_string)) {
+	 *minor_status = ENOMEM;
+	 return(GSS_S_FAILURE);
+      }
+   }
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
+
+/* code should be set to the routine error field */
+
+static OM_uint32 display_routine(minor_status, code, status_string)
+     OM_uint32 *minor_status;
+     OM_uint32 code;
+     gss_buffer_t status_string;
+{
+   const char *str;
+
+   if ((str = GSS_ROUTINE_ERROR_STR(code))) {
+      if (! g_make_string_buffer(str, status_string)) {
+	 *minor_status = ENOMEM;
+	 return(GSS_S_FAILURE);
+      }
+   } else {
+      if (! display_unknown(routine_error, GSS_ROUTINE_ERROR_FIELD(code),
+			    status_string)) {
+	 *minor_status = ENOMEM;
+	 return(GSS_S_FAILURE);
+      }
+   }
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
+
+/* code should be set to the bit offset (log_2) of a supplementary info bit */
+
+static OM_uint32 display_bit(minor_status, code, status_string)
+     OM_uint32 *minor_status;
+     OM_uint32 code;
+     gss_buffer_t status_string;
+{
+   const char *str;
+
+   if ((str = GSS_SINFO_STR(code))) {
+      if (! g_make_string_buffer(str, status_string)) {
+	 *minor_status = ENOMEM;
+	 return(GSS_S_FAILURE);
+      }
+   } else {
+      if (! display_unknown(sinfo_code, 1<<code, status_string)) {
+	 *minor_status = ENOMEM;
+	 return(GSS_S_FAILURE);
+      }
+   }
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
+
+/**/
+
+/* return error messages, for routine errors, call error, and status,
+   in that order.
+     message_context == 0 : print the routine error
+     message_context == 1 : print the calling error
+     message_context > 2  : print supplementary info bit (message_context-2)
+     */
+
+OM_uint32 g_display_major_status(minor_status, status_value, 
+				 message_context, status_string)
+     OM_uint32 *minor_status;
+     OM_uint32 status_value;
+     OM_uint32 *message_context;
+     gss_buffer_t status_string;
+{
+   OM_uint32 ret, tmp;
+   int bit;
+
+   /*** deal with no error at all specially */
+
+   if (status_value == 0) {
+      if (! g_make_string_buffer(no_error, status_string)) {
+	 *minor_status = ENOMEM;
+	 return(GSS_S_FAILURE);
+      }
+      *message_context = 0;
+      *minor_status = 0;
+      return(GSS_S_COMPLETE);
+   }
+
+   /*** do routine error */
+
+   if (*message_context == 0) {
+      if ((tmp = GSS_ROUTINE_ERROR(status_value))) {
+	 status_value -= tmp;
+	 if ((ret = display_routine(minor_status, tmp, status_string)))
+	    return(ret);
+	 *minor_status = 0;
+	 if (status_value) {
+	    (*message_context)++;
+	    return(GSS_S_COMPLETE);
+	 } else {
+	    *message_context = 0;
+	    return(GSS_S_COMPLETE);
+	 }
+      } else {
+	 (*message_context)++;
+      }
+   } else {
+      status_value -= GSS_ROUTINE_ERROR(status_value);
+   }
+
+   /*** do calling error */
+
+   if (*message_context == 1) {
+      if ((tmp = GSS_CALLING_ERROR(status_value))) {
+	 status_value -= tmp;
+	 if ((ret = display_calling(minor_status, tmp, status_string)))
+	    return(ret);
+	 *minor_status = 0;
+	 if (status_value) {
+	    (*message_context)++;
+	    return(GSS_S_COMPLETE);
+	 } else {
+	    *message_context = 0;
+	    return(GSS_S_COMPLETE);
+	 }
+      } else {
+	 (*message_context)++;
+      }
+   } else {
+      status_value -= GSS_CALLING_ERROR(status_value);
+   }
+
+   /*** do sinfo bits (*message_context == 2 + number of bits done) */
+
+   tmp = GSS_SUPPLEMENTARY_INFO_FIELD(status_value);
+   /* mask off the bits which have been done */
+   if (*message_context > 2) {
+      tmp &= ~LSBMASK(*message_context-3);
+      status_value &= ~LSBMASK(*message_context-3);
+   }
+
+   if (!tmp) {
+      /* bogon input - there should be something left */
+      *minor_status = (OM_uint32) G_BAD_MSG_CTX;
+      return(GSS_S_FAILURE);
+   }
+
+   /* compute the bit offset */
+   /*SUPPRESS 570*/
+   for (bit=0; (((OM_uint32) 1)<<bit) != LSBGET(tmp); bit++) ;
+
+   /* print it */
+   if ((ret = display_bit(minor_status, bit, status_string)))
+      return(ret);
+
+   /* compute the new status_value/message_context */
+   status_value -= ((OM_uint32) 1)<<bit;
+
+   if (status_value) {
+      *message_context = bit+3;
+      return(GSS_S_COMPLETE);
+   } else {
+      *message_context = 0;
+      return(GSS_S_COMPLETE);
+   }
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/gssapi.hin b/krb5-1-6/src/lib/gssapi/generic/gssapi.hin
new file mode 100644
index 000000000..71b365b0b
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/gssapi.hin
@@ -0,0 +1,790 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GSSAPI_H_
+#define _GSSAPI_H_
+
+/*
+ * Determine platform-dependent configuration.
+ */
+
+#if defined(__MACH__) && defined(__APPLE__)
+#	include <TargetConditionals.h>
+#	if TARGET_RT_MAC_CFM
+#		error "Use KfM 4.0 SDK headers for CFM compilation."
+#	endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+#	pragma options align=mac68k
+#endif
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include <win-mac.h>
+#endif
+
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+/*
+ * First, include stddef.h to get size_t defined.
+ */
+#include <stddef.h>
+
+/*
+ * POSIX says that sys/types.h is where size_t is defined.
+ */
+#include <sys/types.h>
+
+/*
+ * $Id$
+ */
+
+/*
+ * First, define the three platform-dependent pointer types.
+ */
+
+struct gss_name_struct;
+typedef struct gss_name_struct * gss_name_t;
+
+struct gss_cred_id_struct;
+typedef struct gss_cred_id_struct * gss_cred_id_t;
+
+struct gss_ctx_id_struct;
+typedef struct gss_ctx_id_struct * gss_ctx_id_t;
+
+/*
+ * The following type must be defined as the smallest natural unsigned integer
+ * supported by the platform that has at least 32 bits of precision.
+ */
+typedef uint32_t gss_uint32;
+typedef int32_t gss_int32;
+
+#ifdef	OM_STRING
+/*
+ * We have included the xom.h header file.  Use the definition for
+ * OM_object identifier.
+ */
+typedef OM_object_identifier	gss_OID_desc, *gss_OID;
+#else	/* OM_STRING */
+/*
+ * We can't use X/Open definitions, so roll our own.
+ */
+typedef gss_uint32	OM_uint32;
+
+typedef struct gss_OID_desc_struct {
+      OM_uint32 length;
+      void *elements;
+} gss_OID_desc, *gss_OID;
+#endif	/* OM_STRING */
+
+typedef struct gss_OID_set_desc_struct  {
+      size_t  count;
+      gss_OID elements;
+} gss_OID_set_desc, *gss_OID_set;
+
+typedef struct gss_buffer_desc_struct {
+      size_t length;
+      void *value;
+} gss_buffer_desc, *gss_buffer_t;
+
+typedef struct gss_channel_bindings_struct {
+      OM_uint32 initiator_addrtype;
+      gss_buffer_desc initiator_address;
+      OM_uint32 acceptor_addrtype;
+      gss_buffer_desc acceptor_address;
+      gss_buffer_desc application_data;
+} *gss_channel_bindings_t;
+
+/*
+ * For now, define a QOP-type as an OM_uint32 (pending resolution of ongoing
+ * discussions).
+ */
+typedef	OM_uint32	gss_qop_t;
+typedef	int		gss_cred_usage_t;
+
+/*
+ * Flag bits for context-level services.
+ */
+#define GSS_C_DELEG_FLAG 1
+#define GSS_C_MUTUAL_FLAG 2
+#define GSS_C_REPLAY_FLAG 4
+#define GSS_C_SEQUENCE_FLAG 8
+#define GSS_C_CONF_FLAG 16
+#define GSS_C_INTEG_FLAG 32
+#define	GSS_C_ANON_FLAG 64
+#define GSS_C_PROT_READY_FLAG 128
+#define GSS_C_TRANS_FLAG 256
+
+/*
+ * Credential usage options
+ */
+#define GSS_C_BOTH 0
+#define GSS_C_INITIATE 1
+#define GSS_C_ACCEPT 2
+
+/*
+ * Status code types for gss_display_status
+ */
+#define GSS_C_GSS_CODE 1
+#define GSS_C_MECH_CODE 2
+
+/*
+ * The constant definitions for channel-bindings address families
+ */
+#define GSS_C_AF_UNSPEC     0
+#define GSS_C_AF_LOCAL      1
+#define GSS_C_AF_INET       2
+#define GSS_C_AF_IMPLINK    3
+#define GSS_C_AF_PUP        4
+#define GSS_C_AF_CHAOS      5
+#define GSS_C_AF_NS         6
+#define GSS_C_AF_NBS        7
+#define GSS_C_AF_ECMA       8
+#define GSS_C_AF_DATAKIT    9
+#define GSS_C_AF_CCITT      10
+#define GSS_C_AF_SNA        11
+#define GSS_C_AF_DECnet     12
+#define GSS_C_AF_DLI        13
+#define GSS_C_AF_LAT        14
+#define GSS_C_AF_HYLINK     15
+#define GSS_C_AF_APPLETALK  16
+#define GSS_C_AF_BSC        17
+#define GSS_C_AF_DSS        18
+#define GSS_C_AF_OSI        19
+#define GSS_C_AF_X25        21
+
+#define GSS_C_AF_NULLADDR   255
+
+/*
+ * Various Null values.
+ */
+#define GSS_C_NO_NAME ((gss_name_t) 0)
+#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
+#define GSS_C_NO_OID ((gss_OID) 0)
+#define GSS_C_NO_OID_SET ((gss_OID_set) 0)
+#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
+#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
+#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
+#define GSS_C_EMPTY_BUFFER {0, NULL}
+
+/*
+ * Some alternate names for a couple of the above values.  These are defined
+ * for V1 compatibility.
+ */
+#define	GSS_C_NULL_OID		GSS_C_NO_OID
+#define	GSS_C_NULL_OID_SET	GSS_C_NO_OID_SET
+
+/*
+ * Define the default Quality of Protection for per-message services.  Note
+ * that an implementation that offers multiple levels of QOP may either reserve
+ * a value (for example zero, as assumed here) to mean "default protection", or
+ * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
+ * QOP value.  However a value of 0 should always be interpreted by a GSSAPI
+ * implementation as a request for the default protection level.
+ */
+#define GSS_C_QOP_DEFAULT 0
+
+/*
+ * Expiration time of 2^32-1 seconds means infinite lifetime for a
+ * credential or security context
+ */
+#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful)
+
+
+/* Major status codes */
+
+#define GSS_S_COMPLETE 0
+
+/*
+ * Some "helper" definitions to make the status code macros obvious.
+ */
+#define GSS_C_CALLING_ERROR_OFFSET 24
+#define GSS_C_ROUTINE_ERROR_OFFSET 16
+#define GSS_C_SUPPLEMENTARY_OFFSET 0
+#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
+#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
+#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul)
+
+/*
+ * The macros that test status codes for error conditions.  Note that the
+ * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now
+ * evaluates its argument only once.
+ */
+#define GSS_CALLING_ERROR(x) \
+  ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
+#define GSS_ROUTINE_ERROR(x) \
+  ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
+#define GSS_SUPPLEMENTARY_INFO(x) \
+  ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
+#define GSS_ERROR(x) \
+  ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
+	  (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
+
+/*
+ * Now the actual status code definitions
+ */
+
+/*
+ * Calling errors:
+ */
+#define GSS_S_CALL_INACCESSIBLE_READ \
+                             (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET)
+#define GSS_S_CALL_INACCESSIBLE_WRITE \
+                             (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET)
+#define GSS_S_CALL_BAD_STRUCTURE \
+                             (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET)
+
+/*
+ * Routine errors:
+ */
+#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_CREDENTIAL \
+     (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CREDENTIALS_EXPIRED \
+     (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CONTEXT_EXPIRED \
+     (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#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)
+#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:
+ */
+#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
+#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))
+#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
+
+
+/*
+ * Finally, function prototypes for the GSSAPI routines.
+ */
+
+#if defined (_WIN32) && defined (_MSC_VER)
+# ifdef GSS_DLL_FILE
+#  define GSS_DLLIMP __declspec(dllexport)
+# else
+#  define GSS_DLLIMP __declspec(dllimport)
+# endif
+#else
+# define GSS_DLLIMP
+#endif
+
+/* Reserved static storage for GSS_oids.  Comments are quotes from RFC 2744.
+ *
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"},
+ * corresponding to an object-identifier value of
+ * {iso(1) member-body(2) United States(840) mit(113554)
+ * infosys(1) gssapi(2) generic(1) user_name(1)}.  The constant
+ * GSS_C_NT_USER_NAME should be initialized to point
+ * to that gss_OID_desc.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_NT_USER_NAME;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"},
+ * corresponding to an object-identifier value of
+ * {iso(1) member-body(2) United States(840) mit(113554)
+ * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
+ * The constant GSS_C_NT_MACHINE_UID_NAME should be
+ * initialized to point to that gss_OID_desc.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_NT_MACHINE_UID_NAME;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"},
+ * corresponding to an object-identifier value of
+ * {iso(1) member-body(2) United States(840) mit(113554)
+ * infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
+ * The constant GSS_C_NT_STRING_UID_NAME should be
+ * initialized to point to that gss_OID_desc.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_NT_STRING_UID_NAME;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
+ * corresponding to an object-identifier value of
+ * {iso(1) org(3) dod(6) internet(1) security(5)
+ * nametypes(6) gss-host-based-services(2)).  The constant
+ * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point
+ * to that gss_OID_desc.  This is a deprecated OID value, and
+ * implementations wishing to support hostbased-service names
+ * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID,
+ * defined below, to identify such names;
+ * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym
+ * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input
+ * parameter, but should not be emitted by GSS-API
+ * implementations
+ */
+GSS_DLLIMP extern gss_OID GSS_C_NT_HOSTBASED_SERVICE_X;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
+ *              "\x01\x02\x01\x04"}, corresponding to an
+ * object-identifier value of {iso(1) member-body(2)
+ * Unites States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) service_name(4)}.  The constant
+ * GSS_C_NT_HOSTBASED_SERVICE should be initialized
+ * to point to that gss_OID_desc.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_NT_HOSTBASED_SERVICE;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {6, (void *)"\x2b\x06\01\x05\x06\x03"},
+ * corresponding to an object identifier value of
+ * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
+ * 6(nametypes), 3(gss-anonymous-name)}.  The constant
+ * and GSS_C_NT_ANONYMOUS should be initialized to point
+ * to that gss_OID_desc.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_NT_ANONYMOUS;
+
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
+ * corresponding to an object-identifier value of
+ * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
+ * 6(nametypes), 4(gss-api-exported-name)}.  The constant
+ * GSS_C_NT_EXPORT_NAME should be initialized to point
+ * to that gss_OID_desc.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_NT_EXPORT_NAME;
+
+/* Function Prototypes */
+
+OM_uint32 KRB5_CALLCONV gss_acquire_cred
+(OM_uint32 *,		/* minor_status */
+            gss_name_t,			/* desired_name */
+            OM_uint32,			/* time_req */
+            gss_OID_set,		/* desired_mechs */
+            gss_cred_usage_t,		/* cred_usage */
+            gss_cred_id_t *,	/* output_cred_handle */
+            gss_OID_set *,		/* actual_mechs */
+            OM_uint32 *		/* time_rec */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_release_cred
+(OM_uint32 *,		/* minor_status */
+            gss_cred_id_t *		/* cred_handle */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_init_sec_context
+(OM_uint32 *,		/* minor_status */
+            gss_cred_id_t,		/* claimant_cred_handle */
+            gss_ctx_id_t *,		/* context_handle */
+            gss_name_t,			/* target_name */
+            gss_OID,			/* mech_type (used to be const) */
+            OM_uint32,			/* req_flags */
+            OM_uint32,			/* time_req */
+            gss_channel_bindings_t,	/* input_chan_bindings */
+            gss_buffer_t,		/* input_token */
+            gss_OID *,		/* actual_mech_type */
+            gss_buffer_t,		/* output_token */
+            OM_uint32 *,		/* ret_flags */
+            OM_uint32 *		/* time_rec */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_accept_sec_context
+(OM_uint32 *,		/* minor_status */
+            gss_ctx_id_t *,		/* context_handle */
+            gss_cred_id_t,		/* acceptor_cred_handle */
+            gss_buffer_t,		/* input_token_buffer */
+            gss_channel_bindings_t,	/* input_chan_bindings */
+            gss_name_t *,		/* src_name */
+            gss_OID *,		/* mech_type */
+            gss_buffer_t,		/* output_token */
+            OM_uint32 *,		/* ret_flags */
+            OM_uint32 *,		/* time_rec */
+            gss_cred_id_t *		/* delegated_cred_handle */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_process_context_token
+(OM_uint32 *,		/* minor_status */
+            gss_ctx_id_t,		/* context_handle */
+            gss_buffer_t		/* token_buffer */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_delete_sec_context
+(OM_uint32 *,		/* minor_status */
+            gss_ctx_id_t *,		/* context_handle */
+            gss_buffer_t		/* output_token */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_context_time
+(OM_uint32 *,		/* minor_status */
+            gss_ctx_id_t,		/* context_handle */
+            OM_uint32 *		/* time_rec */
+           );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_get_mic
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_qop_t,			/* qop_req */
+	    gss_buffer_t,		/* message_buffer */
+	    gss_buffer_t		/* message_token */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_verify_mic
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_buffer_t,		/* message_buffer */
+	    gss_buffer_t,		/* message_token */
+	    gss_qop_t *			/* qop_state */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_wrap
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    int,			/* conf_req_flag */
+	    gss_qop_t,			/* qop_req */
+	    gss_buffer_t,		/* input_message_buffer */
+	    int *,			/* conf_state */
+	    gss_buffer_t		/* output_message_buffer */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_unwrap
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_buffer_t,		/* input_message_buffer */
+	    gss_buffer_t,		/* output_message_buffer */
+	    int *,			/* conf_state */
+	    gss_qop_t *		/* qop_state */
+	   );
+
+OM_uint32 KRB5_CALLCONV gss_display_status
+(OM_uint32 *,		/* minor_status */
+            OM_uint32,			/* status_value */
+            int,			/* status_type */
+            gss_OID,			/* mech_type (used to be const) */
+            OM_uint32 *,		/* message_context */
+            gss_buffer_t		/* status_string */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_indicate_mechs
+(OM_uint32 *,		/* minor_status */
+            gss_OID_set *		/* mech_set */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_compare_name
+(OM_uint32 *,		/* minor_status */
+            gss_name_t,			/* name1 */
+            gss_name_t,			/* name2 */
+            int *			/* name_equal */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_display_name
+(OM_uint32 *,		/* minor_status */
+            gss_name_t,			/* input_name */
+            gss_buffer_t,		/* output_name_buffer */
+            gss_OID *		/* output_name_type */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_import_name
+(OM_uint32 *,		/* minor_status */
+            gss_buffer_t,		/* input_name_buffer */
+            gss_OID,			/* input_name_type(used to be const) */
+            gss_name_t *		/* output_name */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_release_name
+(OM_uint32 *,		/* minor_status */
+            gss_name_t *		/* input_name */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_release_buffer
+(OM_uint32 *,		/* minor_status */
+            gss_buffer_t		/* buffer */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_release_oid_set
+(OM_uint32 *,		/* minor_status */
+            gss_OID_set * 		/* set */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_inquire_cred
+(OM_uint32 *,		/* minor_status */
+            gss_cred_id_t,		/* cred_handle */
+            gss_name_t *,		/* name */
+            OM_uint32 *,		/* lifetime */
+            gss_cred_usage_t *,	/* cred_usage */
+            gss_OID_set *		/* mechanisms */
+           );
+
+/* Last argument new for V2 */
+OM_uint32 KRB5_CALLCONV gss_inquire_context
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_name_t *,		/* src_name */
+	    gss_name_t *,		/* targ_name */
+	    OM_uint32 *,		/* lifetime_rec */
+	    gss_OID *,		/* mech_type */
+	    OM_uint32 *,		/* ctx_flags */
+	    int *,           	/* locally_initiated */
+	    int *			/* open */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_wrap_size_limit
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    int,			/* conf_req_flag */
+	    gss_qop_t,			/* qop_req */
+	    OM_uint32,			/* req_output_size */
+	    OM_uint32 *			/* max_input_size */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_import_name_object
+(OM_uint32 *,		/* minor_status */
+	    void *,			/* input_name */
+	    gss_OID,			/* input_name_type */
+	    gss_name_t *		/* output_name */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_export_name_object
+(OM_uint32 *,		/* minor_status */
+	    gss_name_t,			/* input_name */
+	    gss_OID,			/* desired_name_type */
+	    void **		/* output_name */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_add_cred
+(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 */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_inquire_cred_by_mech
+(OM_uint32 *,		/* minor_status */
+	    gss_cred_id_t,		/* cred_handle */
+	    gss_OID,			/* mech_type */
+	    gss_name_t *,		/* name */
+	    OM_uint32 *,		/* initiator_lifetime */
+	    OM_uint32 *,		/* acceptor_lifetime */
+	    gss_cred_usage_t * 	/* cred_usage */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_export_sec_context
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t *,		/* context_handle */
+	    gss_buffer_t		/* interprocess_token */
+	    );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_import_sec_context
+(OM_uint32 *,		/* minor_status */
+	    gss_buffer_t,		/* interprocess_token */
+	    gss_ctx_id_t *		/* context_handle */
+	    );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_release_oid
+(OM_uint32 *,		/* minor_status */
+	    gss_OID *		/* oid */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_create_empty_oid_set
+(OM_uint32 *,		/* minor_status */
+	    gss_OID_set *		/* oid_set */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_add_oid_set_member
+(OM_uint32 *,		/* minor_status */
+	    gss_OID,			/* member_oid */
+	    gss_OID_set *		/* oid_set */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_test_oid_set_member
+(OM_uint32 *,		/* minor_status */
+	    gss_OID,			/* member */
+	    gss_OID_set,		/* set */
+	    int *			/* present */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_str_to_oid
+(OM_uint32 *,		/* minor_status */
+	    gss_buffer_t,		/* oid_str */
+	    gss_OID *		/* oid */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_oid_to_str
+(OM_uint32 *,		/* minor_status */
+	    gss_OID,			/* oid */
+	    gss_buffer_t		/* oid_str */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_inquire_names_for_mech
+(OM_uint32 *,		/* minor_status */
+	    gss_OID,			/* mechanism */
+	    gss_OID_set *		/* name_types */
+	   );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_inquire_mechs_for_name(
+    OM_uint32 *,		/* minor_status */
+    const gss_name_t,		/* input_name */
+    gss_OID_set *		/* mech_types */
+);
+
+/*
+ * The following routines are obsolete variants of gss_get_mic, gss_wrap,
+ * gss_verify_mic and gss_unwrap.  They should be provided by GSSAPI V2
+ * implementations for backwards compatibility with V1 applications.  Distinct
+ * entrypoints (as opposed to #defines) should be provided, to allow GSSAPI
+ * V1 applications to link against GSSAPI V2 implementations.
+ */
+OM_uint32 KRB5_CALLCONV gss_sign
+(OM_uint32 *,    /* minor_status */
+            gss_ctx_id_t,     	/* context_handle */
+            int,              	/* qop_req */
+            gss_buffer_t,     	/* message_buffer */
+            gss_buffer_t      	/* message_token */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_verify
+(OM_uint32 *,    /* minor_status */
+            gss_ctx_id_t,     	/* context_handle */
+            gss_buffer_t,     	/* message_buffer */
+            gss_buffer_t,     	/* token_buffer */
+            int *           /* qop_state */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_seal
+(OM_uint32 *,    /* minor_status */
+            gss_ctx_id_t,     	/* context_handle */
+            int,              	/* conf_req_flag */
+            int,              	/* qop_req */
+            gss_buffer_t,     	/* input_message_buffer */
+            int *,          /* conf_state */
+            gss_buffer_t      	/* output_message_buffer */
+           );
+
+OM_uint32 KRB5_CALLCONV gss_unseal
+(OM_uint32 *,    /* minor_status */
+            gss_ctx_id_t,     	/* context_handle */
+            gss_buffer_t,     	/* input_message_buffer */
+            gss_buffer_t,     	/* output_message_buffer */
+            int *,          /* conf_state */
+            int *           /* qop_state */
+           );
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_export_name
+(OM_uint32  *,		/* minor_status */
+		 const gss_name_t,	/* input_name */
+		 gss_buffer_t		/* exported_name */
+	);
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_duplicate_name
+(OM_uint32  *,		/* minor_status */
+		 const gss_name_t,	/* input_name */
+		 gss_name_t *		/* dest_name */
+	);
+
+/* New for V2 */
+OM_uint32 KRB5_CALLCONV gss_canonicalize_name
+(OM_uint32  *,		/* minor_status */
+		 const gss_name_t,	/* input_name */
+		 const gss_OID,		/* mech_type */
+		 gss_name_t *		/* output_name */
+	);
+
+#if TARGET_OS_MAC
+#  pragma options align=reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* XXXX these are not part of the GSSAPI C bindings!  (but should be) */
+
+#define GSS_CALLING_ERROR_FIELD(x) \
+   (((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK)
+#define GSS_ROUTINE_ERROR_FIELD(x) \
+   (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK)
+#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \
+   (((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK)
+
+/* XXXX This is a necessary evil until the spec is fixed */
+#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
+
+#endif /* _GSSAPI_H_ */
diff --git a/krb5-1-6/src/lib/gssapi/generic/gssapiP_generic.h b/krb5-1-6/src/lib/gssapi/generic/gssapiP_generic.h
new file mode 100644
index 000000000..e34055b6c
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/gssapiP_generic.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GSSAPIP_GENERIC_H_
+#define _GSSAPIP_GENERIC_H_
+
+/*
+ * $Id$
+ */
+
+#if defined(_WIN32)
+#include "k5-int.h"
+#else
+#include "autoconf.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#endif
+
+#include "k5-thread.h"
+
+#include "gssapi_generic.h"
+
+#include "gssapi_err_generic.h"
+#include <errno.h>
+
+#include "k5-platform.h"
+typedef UINT64_TYPE gssint_uint64;
+
+/** helper macros **/
+
+#define	g_OID_equal(o1, o2) \
+	(((o1)->length == (o2)->length) && \
+	(memcmp((o1)->elements, (o2)->elements, (o1)->length) == 0))
+
+/* this code knows that an int on the wire is 32 bits.  The type of
+   num should be at least this big, or the extra shifts may do weird
+   things */
+
+#define TWRITE_INT(ptr, num, bigend) \
+   (ptr)[0] = (char) ((bigend)?((num)>>24):((num)&0xff)); \
+   (ptr)[1] = (char) ((bigend)?(((num)>>16)&0xff):(((num)>>8)&0xff)); \
+   (ptr)[2] = (char) ((bigend)?(((num)>>8)&0xff):(((num)>>16)&0xff)); \
+   (ptr)[3] = (char) ((bigend)?((num)&0xff):((num)>>24)); \
+   (ptr) += 4;
+
+#define TWRITE_INT16(ptr, num, bigend) \
+   (ptr)[0] = (char) ((bigend)?((num)>>24):((num)&0xff)); \
+   (ptr)[1] = (char) ((bigend)?(((num)>>16)&0xff):(((num)>>8)&0xff)); \
+   (ptr) += 2;
+
+#define TREAD_INT(ptr, num, bigend) \
+   (num) = (((ptr)[0]<<((bigend)?24: 0)) | \
+            ((ptr)[1]<<((bigend)?16: 8)) | \
+            ((ptr)[2]<<((bigend)? 8:16)) | \
+            ((ptr)[3]<<((bigend)? 0:24))); \
+   (ptr) += 4;
+
+#define TREAD_INT16(ptr, num, bigend) \
+   (num) = (((ptr)[0]<<((bigend)?24: 0)) | \
+            ((ptr)[1]<<((bigend)?16: 8))); \
+   (ptr) += 2;
+
+#define TWRITE_STR(ptr, str, len) \
+   memcpy((ptr), (char *) (str), (len)); \
+   (ptr) += (len);
+
+#define TREAD_STR(ptr, str, len) \
+   (str) = (ptr); \
+   (ptr) += (len);
+
+#define TWRITE_BUF(ptr, buf, bigend) \
+   TWRITE_INT((ptr), (buf).length, (bigend)); \
+   TWRITE_STR((ptr), (buf).value, (buf).length);
+
+/** malloc wrappers; these may actually do something later */
+
+#define xmalloc(n) malloc(n)
+#define xrealloc(p,n) realloc(p,n)
+#ifdef xfree
+#undef xfree
+#endif
+#define xfree(p) free(p)
+
+/** helper functions **/
+
+/* hide names from applications, especially glib applications */
+#define	g_set_init		gssint_g_set_init
+#define	g_set_destroy		gssint_g_set_destroy
+#define	g_set_entry_add		gssint_g_set_entry_add
+#define	g_set_entry_delete	gssint_g_set_entry_delete
+#define	g_set_entry_get		gssint_g_set_entry_get
+#define	g_save_name		gssint_g_save_name
+#define	g_save_cred_id		gssint_g_save_cred_id
+#define	g_save_ctx_id		gssint_g_save_ctx_id
+#define	g_save_lucidctx_id	gssint_g_save_lucidctx_id
+#define	g_validate_name		gssint_g_validate_name
+#define	g_validate_cred_id	gssint_g_validate_cred_id
+#define	g_validate_ctx_id	gssint_g_validate_ctx_id
+#define	g_validate_lucidctx_id	gssint_g_validate_lucidctx_id
+#define	g_delete_name		gssint_g_delete_name
+#define	g_delete_cred_id	gssint_g_delete_cred_id
+#define	g_delete_ctx_id		gssint_g_delete_ctx_id
+#define	g_delete_lucidctx_id	gssint_g_delete_lucidctx_id
+#define	g_make_string_buffer	gssint_g_make_string_buffer
+#define	g_token_size		gssint_g_token_size
+#define	g_make_token_header	gssint_g_make_token_header
+#define	g_verify_token_header	gssint_g_verify_token_header
+#define	g_display_major_status	gssint_g_display_major_status
+#define	g_display_com_err_status gssint_g_display_com_err_status
+#define	g_order_init		gssint_g_order_init
+#define	g_order_check		gssint_g_order_check
+#define	g_order_free		gssint_g_order_free
+#define	g_queue_size		gssint_g_queue_size
+#define	g_queue_externalize	gssint_g_queue_externalize
+#define	g_queue_internalize	gssint_g_queue_internalize
+#define	g_canonicalize_host	gssint_g_canonicalize_host
+#define	g_local_host_name	gssint_g_local_host_name
+#define	g_strdup		gssint_g_strdup
+
+typedef struct _g_set_elt *g_set_elt;
+typedef struct {
+    k5_mutex_t mutex;
+    void *data;
+} g_set;
+#define G_SET_INIT { K5_MUTEX_PARTIAL_INITIALIZER, 0 }
+
+int g_set_init (g_set_elt *s);
+int g_set_destroy (g_set_elt *s);
+int g_set_entry_add (g_set_elt *s, void *key, void *value);
+int g_set_entry_delete (g_set_elt *s, void *key);
+int g_set_entry_get (g_set_elt *s, void *key, void **value);
+
+int g_save_name (g_set *vdb, gss_name_t name);
+int g_save_cred_id (g_set *vdb, gss_cred_id_t cred);
+int g_save_ctx_id (g_set *vdb, gss_ctx_id_t ctx);
+int g_save_lucidctx_id (g_set *vdb, void *lctx);
+
+int g_validate_name (g_set *vdb, gss_name_t name);
+int g_validate_cred_id (g_set *vdb, gss_cred_id_t cred);
+int g_validate_ctx_id (g_set *vdb, gss_ctx_id_t ctx);
+int g_validate_lucidctx_id (g_set *vdb, void *lctx);
+
+int g_delete_name (g_set *vdb, gss_name_t name);
+int g_delete_cred_id (g_set *vdb, gss_cred_id_t cred);
+int g_delete_ctx_id (g_set *vdb, gss_ctx_id_t ctx);
+int g_delete_lucidctx_id (g_set *vdb, void *lctx);
+
+int g_make_string_buffer (const char *str, gss_buffer_t buffer);
+
+unsigned int g_token_size (const gss_OID_desc * mech, unsigned int body_size);
+
+void g_make_token_header (const gss_OID_desc * mech, unsigned int body_size,
+			  unsigned char **buf, int tok_type);
+
+gss_int32 g_verify_token_header (const gss_OID_desc * mech, 
+				 unsigned int *body_size,
+				 unsigned char **buf, int tok_type, 
+				 unsigned int toksize_in,
+				 int wrapper_required);
+
+OM_uint32 g_display_major_status (OM_uint32 *minor_status,
+				 OM_uint32 status_value,
+				 OM_uint32 *message_context,
+				 gss_buffer_t status_string);
+
+OM_uint32 g_display_com_err_status (OM_uint32 *minor_status,
+				   OM_uint32 status_value,
+				   gss_buffer_t status_string);
+
+gss_int32 g_order_init (void **queue, gssint_uint64 seqnum,
+				  int do_replay, int do_sequence, int wide);
+
+gss_int32 g_order_check (void **queue, gssint_uint64 seqnum);
+
+void g_order_free (void **queue);
+
+gss_uint32 g_queue_size(void *vqueue, size_t *sizep);
+gss_uint32 g_queue_externalize(void *vqueue, unsigned char **buf,
+			       size_t *lenremain);
+gss_uint32 g_queue_internalize(void **vqueue, unsigned char **buf,
+			       size_t *lenremain);
+
+char *g_strdup (char *str);
+
+/** declarations of internal name mechanism functions **/
+
+OM_uint32 generic_gss_release_buffer
+(OM_uint32*,       /* minor_status */
+            gss_buffer_t      /* buffer */
+           );
+
+OM_uint32 generic_gss_release_oid_set
+(OM_uint32*,       /* minor_status */
+            gss_OID_set*      /* set */
+           );
+
+OM_uint32 generic_gss_release_oid
+(OM_uint32*,       /* minor_status */
+            gss_OID*         /* set */
+           );
+
+OM_uint32 generic_gss_copy_oid
+(OM_uint32 *,	/* minor_status */
+	    const gss_OID_desc * const,		/* oid */
+	    gss_OID *		/* new_oid */
+	    );
+
+OM_uint32 generic_gss_create_empty_oid_set
+(OM_uint32 *,	/* minor_status */
+	    gss_OID_set *	/* oid_set */
+	   );
+
+OM_uint32 generic_gss_add_oid_set_member
+(OM_uint32 *,	/* minor_status */
+	    const gss_OID_desc * const,		/* member_oid */
+	    gss_OID_set *	/* oid_set */
+	   );
+
+OM_uint32 generic_gss_test_oid_set_member
+(OM_uint32 *,	/* minor_status */
+	    const gss_OID_desc * const,		/* member */
+	    gss_OID_set,	/* set */
+	    int *		/* present */
+	   );
+
+OM_uint32 generic_gss_oid_to_str
+(OM_uint32 *,	/* minor_status */
+	    const gss_OID_desc * const,		/* oid */
+	    gss_buffer_t	/* oid_str */
+	   );
+
+OM_uint32 generic_gss_str_to_oid
+(OM_uint32 *,	/* minor_status */
+	    gss_buffer_t,	/* oid_str */
+	    gss_OID *		/* oid */
+	   );
+
+#endif /* _GSSAPIP_GENERIC_H_ */
diff --git a/krb5-1-6/src/lib/gssapi/generic/gssapi_err_generic.et b/krb5-1-6/src/lib/gssapi/generic/gssapi_err_generic.et
new file mode 100644
index 000000000..3e976e3db
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/gssapi_err_generic.et
@@ -0,0 +1,49 @@
+# 
+# Copyright 1993 by OpenVision Technologies, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software
+# and its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appears in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of OpenVision not be used
+# in advertising or publicity pertaining to distribution of the software
+# without specific, written prior permission. OpenVision makes no
+# representations about the suitability of this software for any
+# purpose.  It is provided "as is" without express or implied warranty.
+# 
+# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+# 
+
+#
+# $Id$
+#
+
+error_table ggss
+
+error_code G_BAD_SERVICE_NAME, "No @ in SERVICE-NAME name string"
+error_code G_BAD_STRING_UID, "STRING-UID-NAME contains nondigits"
+error_code G_NOUSER, "UID does not resolve to username"
+error_code G_VALIDATE_FAILED, "Validation error"
+error_code G_BUFFER_ALLOC, "Couldn't allocate gss_buffer_t data"
+error_code G_BAD_MSG_CTX, "Message context invalid"
+error_code G_WRONG_SIZE, "Buffer is the wrong size"
+error_code G_BAD_USAGE, "Credential usage type is unknown"
+error_code G_UNKNOWN_QOP, "Unknown quality of protection specified"
+error_code G_NO_HOSTNAME, "Local host name could not be determined"
+error_code G_BAD_HOSTNAME, "Hostname in SERVICE-NAME string could not be canonicalized"
+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"
+error_code G_CRED_USAGE_MISMATCH, "The given credential's usage does not match the requested usage"
+error_code G_STORE_ACCEPTOR_CRED_NOSUPP, "Storing of acceptor credentials is not supported by the mechanism"
+error_code G_STORE_NON_DEFAULT_CRED_NOSUPP, "Storing of non-default credentials is not supported by the mechanism"
+end
diff --git a/krb5-1-6/src/lib/gssapi/generic/gssapi_generic.c b/krb5-1-6/src/lib/gssapi/generic/gssapi_generic.c
new file mode 100644
index 000000000..db92abb96
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/gssapi_generic.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_generic.h"
+
+/*
+ * See krb5/gssapi_krb5.c for a description of the algorithm for
+ * encoding an object identifier.
+ */
+
+/* Reserved static storage for GSS_oids.  Comments are quotes from RFC 2744. */
+
+#define oids ((gss_OID_desc *)const_oids)
+static const gss_OID_desc const_oids[] = {
+    /*
+     * The implementation must reserve static storage for a
+	 * gss_OID_desc object containing the value */
+    {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"},
+    /* corresponding to an object-identifier value of
+	 * {iso(1) member-body(2) United States(840) mit(113554)
+	 * infosys(1) gssapi(2) generic(1) user_name(1)}.  The constant
+	 * GSS_C_NT_USER_NAME should be initialized to point
+	 * to that gss_OID_desc.
+	 */                                
+    
+    /*
+	 * The implementation must reserve static storage for a
+	 * gss_OID_desc object containing the value */
+    {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"},
+    /* corresponding to an object-identifier value of
+	 * {iso(1) member-body(2) United States(840) mit(113554)
+	 * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
+	 * The constant GSS_C_NT_MACHINE_UID_NAME should be
+	 * initialized to point to that gss_OID_desc.
+	 */
+     
+    /*
+    * The implementation must reserve static storage for a
+    * gss_OID_desc object containing the value */
+    {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"},
+    /* corresponding to an object-identifier value of
+    * {iso(1) member-body(2) United States(840) mit(113554)
+    * infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
+    * The constant GSS_C_NT_STRING_UID_NAME should be
+    * initialized to point to that gss_OID_desc.
+    */
+    
+    /*
+     * The implementation must reserve static storage for a
+     * gss_OID_desc object containing the value */
+    {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
+    /* corresponding to an object-identifier value of
+     * {iso(1) org(3) dod(6) internet(1) security(5)
+     * nametypes(6) gss-host-based-services(2)).  The constant
+     * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point
+     * to that gss_OID_desc.  This is a deprecated OID value, and
+     * implementations wishing to support hostbased-service names
+     * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID,
+     * defined below, to identify such names;
+     * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym
+     * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input
+     * parameter, but should not be emitted by GSS-API
+     * implementations
+     */
+    
+    /*
+     * The implementation must reserve static storage for a
+     * gss_OID_desc object containing the value */
+    {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"}, 
+    /* corresponding to an object-identifier value of 
+     * {iso(1) member-body(2) Unites States(840) mit(113554) 
+     * infosys(1) gssapi(2) generic(1) service_name(4)}.  
+     * The constant GSS_C_NT_HOSTBASED_SERVICE should be 
+     * initialized to point to that gss_OID_desc.
+     */
+
+    /*
+     * The implementation must reserve static storage for a
+     * gss_OID_desc object containing the value */
+    {6, (void *)"\x2b\x06\01\x05\x06\x03"},
+    /* corresponding to an object identifier value of
+     * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
+     * 6(nametypes), 3(gss-anonymous-name)}.  The constant
+     * and GSS_C_NT_ANONYMOUS should be initialized to point
+     * to that gss_OID_desc.
+     */
+    
+    /*
+     * The implementation must reserve static storage for a
+     * gss_OID_desc object containing the value */
+    {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
+    /* corresponding to an object-identifier value of
+     * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
+     * 6(nametypes), 4(gss-api-exported-name)}.  The constant
+     * GSS_C_NT_EXPORT_NAME should be initialized to point
+     * to that gss_OID_desc.
+     */
+};
+
+/* Here are the constants which point to the static structure above.
+ *
+ * Constants of the form GSS_C_NT_* are specified by rfc 2744.
+ *
+ * Constants of the form gss_nt_* are the original MIT krb5 names 
+ * found in gssapi_generic.h.  They are provided for compatibility. */ 
+
+GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME           = oids+0;
+GSS_DLLIMP gss_OID gss_nt_user_name             = oids+0;
+
+GSS_DLLIMP gss_OID GSS_C_NT_MACHINE_UID_NAME    = oids+1;
+GSS_DLLIMP gss_OID gss_nt_machine_uid_name      = oids+1;
+
+GSS_DLLIMP gss_OID GSS_C_NT_STRING_UID_NAME     = oids+2;
+GSS_DLLIMP gss_OID gss_nt_string_uid_name       = oids+2;
+
+GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE_X = oids+3;
+gss_OID gss_nt_service_name_v2       = oids+3;
+
+GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE   = oids+4;
+GSS_DLLIMP gss_OID gss_nt_service_name          = oids+4;
+
+GSS_DLLIMP gss_OID GSS_C_NT_ANONYMOUS           = oids+5;
+
+GSS_DLLIMP gss_OID GSS_C_NT_EXPORT_NAME         = oids+6;
+gss_OID gss_nt_exported_name         = oids+6;
diff --git a/krb5-1-6/src/lib/gssapi/generic/gssapi_generic.h b/krb5-1-6/src/lib/gssapi/generic/gssapi_generic.h
new file mode 100644
index 000000000..bf3c2af59
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/gssapi_generic.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GSSAPI_GENERIC_H_
+#define _GSSAPI_GENERIC_H_
+
+/*
+ * $Id$
+ */
+
+#include <gssapi/gssapi.h>
+
+#if defined(__cplusplus) && !defined(GSSAPIGENERIC_BEGIN_DECLS)
+#define GSSAPIGENERIC_BEGIN_DECLS	extern "C" {
+#define GSSAPIGENERIC_END_DECLS	}
+#else
+#define GSSAPIGENERIC_BEGIN_DECLS
+#define GSSAPIGENERIC_END_DECLS
+#endif
+
+GSSAPIGENERIC_BEGIN_DECLS
+
+/* Deprecated MIT krb5 oid names provided for compatibility.
+ * The correct oids (GSS_C_NT_USER_NAME, etc) from rfc 2744 
+ * are defined in gssapi.h. */
+
+GSS_DLLIMP extern gss_OID gss_nt_user_name;
+GSS_DLLIMP extern gss_OID gss_nt_machine_uid_name;
+GSS_DLLIMP extern gss_OID gss_nt_string_uid_name;
+extern gss_OID gss_nt_service_name_v2;
+GSS_DLLIMP extern gss_OID gss_nt_service_name;
+extern gss_OID gss_nt_exported_name;
+
+GSSAPIGENERIC_END_DECLS
+
+#endif /* _GSSAPI_GENERIC_H_ */
diff --git a/krb5-1-6/src/lib/gssapi/generic/rel_buffer.c b/krb5-1-6/src/lib/gssapi/generic/rel_buffer.c
new file mode 100644
index 000000000..555888184
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/rel_buffer.c
@@ -0,0 +1,57 @@
+/* #ident  "@(#)g_rel_buffer.c 1.2     96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_buffer
+ */
+
+#include "gssapiP_generic.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32
+generic_gss_release_buffer (minor_status,
+			    buffer)
+     OM_uint32 *		minor_status;
+     gss_buffer_t		buffer;
+{
+    if (minor_status)
+	*minor_status = 0;
+
+    /* if buffer is NULL, return */
+
+    if (buffer == GSS_C_NO_BUFFER)
+	return(GSS_S_COMPLETE);
+
+    if (buffer->value) {
+	free(buffer->value);
+	buffer->length = 0;
+	buffer->value = NULL;
+    }
+
+    return (GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/rel_oid_set.c b/krb5-1-6/src/lib/gssapi/generic/rel_oid_set.c
new file mode 100644
index 000000000..bd7f3cb2c
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/rel_oid_set.c
@@ -0,0 +1,61 @@
+/* #ident  "@(#)gss_release_oid_set.c 1.12     95/08/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_oid_set
+ */
+
+#include "gssapiP_generic.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32
+generic_gss_release_oid_set (minor_status,
+			     set)
+     OM_uint32 *		minor_status;
+     gss_OID_set *		set;
+{
+    size_t i;
+    if (minor_status)
+	*minor_status = 0;
+
+    if (set == NULL)
+	return(GSS_S_COMPLETE);
+
+    if (*set == GSS_C_NULL_OID_SET)
+	return(GSS_S_COMPLETE);
+
+    for (i=0; i<(*set)->count; i++)
+	free((*set)->elements[i].elements);
+
+    free((*set)->elements);
+    free(*set);
+
+    *set = GSS_C_NULL_OID_SET;
+    
+    return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/util_buffer.c b/krb5-1-6/src/lib/gssapi/generic/util_buffer.c
new file mode 100644
index 000000000..77cb2eb2f
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/util_buffer.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_generic.h"
+#include <string.h>
+
+/* return nonzero on success, 0 on failure
+   make sure that buffer is consistent (release'able) when this
+   function exits, no matter what the exit value */
+
+int g_make_string_buffer(str, buffer)
+     const char *str;
+     gss_buffer_t buffer;
+{
+   buffer->length = strlen(str);
+
+   if ((buffer->value = (void *) xmalloc(buffer->length + 1)) == NULL) {
+      buffer->length = 0;
+      return(0);
+   }
+
+   strcpy(buffer->value, str);
+
+   return(1);
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/util_canonhost.c b/krb5-1-6/src/lib/gssapi/generic/util_canonhost.c
new file mode 100644
index 000000000..829311db9
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/util_canonhost.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+/* This file could be OS specific */
+
+#include "gssapiP_generic.h"
+
+#include "port-sockets.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <ctype.h>
+#include <string.h>
+
+char *
+g_canonicalize_host(hostname)
+     char *hostname;
+{
+   struct hostent *hent;
+   char *haddr;
+   char *canon, *str;
+
+   if ((hent = gethostbyname(hostname)) == NULL)
+      return(NULL);
+
+   if (! (haddr = (char *) xmalloc(hent->h_length))) {
+	return(NULL);
+   }
+
+   memcpy(haddr, hent->h_addr_list[0], hent->h_length);
+
+   if (! (hent = gethostbyaddr(haddr, hent->h_length, hent->h_addrtype))) {
+	return(NULL);
+   }
+
+   xfree(haddr);
+
+   if ((canon = (char *) xmalloc(strlen(hent->h_name)+1)) == NULL)
+      return(NULL);
+
+   strcpy(canon, hent->h_name);
+
+   for (str = canon; *str; str++)
+      if (isupper(*str)) *str = tolower(*str);
+
+   return(canon);
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/util_localhost.c b/krb5-1-6/src/lib/gssapi/generic/util_localhost.c
new file mode 100644
index 000000000..13856e320
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/util_localhost.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+/* This file could be OS specific */
+
+#include <sys/param.h>
+
+#include "gssapiP_generic.h"
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+char *g_local_host_name()
+{
+     char buf[MAXHOSTNAMELEN+1], *ptr;
+
+     if (gethostname(buf, sizeof(buf)) < 0)
+	  return 0;
+
+     buf[sizeof(buf)-1] = '\0';
+
+     if (! (ptr = xmalloc(strlen(buf) + 1)))
+	  return 0;
+
+     return strcpy(ptr, buf);
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/util_ordering.c b/krb5-1-6/src/lib/gssapi/generic/util_ordering.c
new file mode 100644
index 000000000..218462bb0
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/util_ordering.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+/*
+ * functions to check sequence numbers for replay and sequencing
+ */
+
+#include "gssapiP_generic.h"
+#include <string.h>
+
+#define QUEUE_LENGTH 20
+
+typedef struct _queue {
+   int do_replay;
+   int do_sequence;
+   int start;
+   int length;
+   gssint_uint64 firstnum;
+   /* Stored as deltas from firstnum.  This way, the high bit won't
+      overflow unless we've actually gone through 2**n messages, or
+      gotten something *way* out of sequence.  */
+   gssint_uint64 elem[QUEUE_LENGTH];
+   /* All ones for 64-bit sequence numbers; 32 ones for 32-bit
+      sequence numbers.  */
+   gssint_uint64 mask;
+} queue;
+
+/* rep invariant:
+ *  - the queue is a circular queue.  The first element (q->elem[q->start])
+ * is the oldest.  The last element is the newest.
+ */
+
+#define QSIZE(q) (sizeof((q)->elem)/sizeof((q)->elem[0]))
+#define QELEM(q,i) ((q)->elem[(i)%QSIZE(q)])
+
+static void
+queue_insert(queue *q, int after, gssint_uint64 seqnum)
+{
+   /* insert.  this is not the fastest way, but it's easy, and it's
+      optimized for insert at end, which is the common case */
+   int i;
+
+   /* common case: at end, after == q->start+q->length-1 */
+
+   /* move all the elements (after,last] up one slot */
+
+   for (i=q->start+q->length-1; i>after; i--)
+      QELEM(q,i+1) = QELEM(q,i);
+
+   /* fill in slot after+1 */
+
+   QELEM(q,after+1) = seqnum;
+
+   /* Either increase the length by one, or move the starting point up
+      one (deleting the first element, which got bashed above), as
+      appropriate. */
+
+   if (q->length == QSIZE(q)) {
+      q->start++;
+      if (q->start == QSIZE(q))
+	 q->start = 0;
+   } else {
+      q->length++;
+   }
+}
+
+gss_int32
+g_order_init(void **vqueue, gssint_uint64 seqnum,
+	     int do_replay, int do_sequence, int wide_nums)
+{
+   queue *q;
+
+   if ((q = (queue *) malloc(sizeof(queue))) == NULL)
+      return(ENOMEM);
+
+   /* This stops valgrind from complaining about writing uninitialized
+      data if the caller exports the context and writes it to a file.
+      We don't actually use those bytes at all, but valgrind still
+      complains.  */
+   memset(q, 0xfe, sizeof(*q));
+
+   q->do_replay = do_replay;
+   q->do_sequence = do_sequence;
+   q->mask = wide_nums ? ~(gssint_uint64)0 : 0xffffffffUL;
+
+   q->start = 0;
+   q->length = 1;
+   q->firstnum = seqnum;
+   q->elem[q->start] = ((gssint_uint64)0 - 1) & q->mask;
+
+   *vqueue = (void *) q;
+   return(0);
+}
+
+gss_int32
+g_order_check(void **vqueue, gssint_uint64 seqnum)
+{
+   queue *q;
+   int i;
+   gssint_uint64 expected;
+
+   q = (queue *) (*vqueue);
+
+   if (!q->do_replay && !q->do_sequence)
+      return(GSS_S_COMPLETE);
+
+   /* All checks are done relative to the initial sequence number, to
+      avoid (or at least put off) the pain of wrapping.  */
+   seqnum -= q->firstnum;
+   /* If we're only doing 32-bit values, adjust for that again.
+
+      Note that this will probably be the wrong thing to if we get
+      2**32 messages sent with 32-bit sequence numbers.  */
+   seqnum &= q->mask;
+
+   /* rule 1: expected sequence number */
+
+   expected = (QELEM(q,q->start+q->length-1)+1) & q->mask;
+   if (seqnum == expected) { 
+      queue_insert(q, q->start+q->length-1, seqnum);
+      return(GSS_S_COMPLETE);
+   }
+
+   /* rule 2: > expected sequence number */
+
+   if ((seqnum > expected)) {
+      queue_insert(q, q->start+q->length-1, seqnum);
+      if (q->do_replay && !q->do_sequence)
+	 return(GSS_S_COMPLETE);
+      else
+	 return(GSS_S_GAP_TOKEN);
+   }
+
+   /* rule 3: seqnum < seqnum(first) */
+
+   if ((seqnum < QELEM(q,q->start)) &&
+       /* Is top bit of whatever width we're using set?
+
+	  We used to check for greater than or equal to firstnum, but
+	  (1) we've since switched to compute values relative to
+	  firstnum, so the lowest we can have is 0, and (2) the effect
+	  of the original scheme was highly dependent on whether
+	  firstnum was close to either side of 0.  (Consider
+	  firstnum==0xFFFFFFFE and we miss three packets; the next
+	  packet is *new* but would look old.)
+
+          This check should give us 2**31 or 2**63 messages "new", and
+          just as many "old".  That's not quite right either.  */
+       (seqnum & (1 + (q->mask >> 1)))
+       ) {
+      if (q->do_replay && !q->do_sequence)
+	 return(GSS_S_OLD_TOKEN);
+      else
+	 return(GSS_S_UNSEQ_TOKEN);
+   }
+
+   /* rule 4+5: seqnum in [seqnum(first),seqnum(last)]  */
+
+   else {
+      if (seqnum == QELEM(q,q->start+q->length-1))
+	 return(GSS_S_DUPLICATE_TOKEN);
+
+      for (i=q->start; i<q->start+q->length-1; i++) {
+	 if (seqnum == QELEM(q,i))
+	    return(GSS_S_DUPLICATE_TOKEN);
+	 if ((seqnum > QELEM(q,i)) && (seqnum < QELEM(q,i+1))) {
+	    queue_insert(q, i, seqnum);
+	    if (q->do_replay && !q->do_sequence)
+	       return(GSS_S_COMPLETE);
+	    else
+	       return(GSS_S_UNSEQ_TOKEN);
+	 }
+      }
+   }
+
+   /* this should never happen */
+   return(GSS_S_FAILURE);
+}
+
+void
+g_order_free(void **vqueue)
+{
+   queue *q;
+   
+   q = (queue *) (*vqueue);
+
+   free(q);
+
+   *vqueue = NULL;
+}
+
+/*
+ * These support functions are for the serialization routines
+ */
+gss_uint32
+g_queue_size(void *vqueue, size_t *sizep)
+{
+    *sizep += sizeof(queue);
+    return 0;
+}
+
+gss_uint32
+g_queue_externalize(void *vqueue, unsigned char **buf, size_t *lenremain)
+{
+    if (*lenremain < sizeof(queue))
+	return ENOMEM;
+    memcpy(*buf, vqueue, sizeof(queue));
+    *buf += sizeof(queue);
+    *lenremain -= sizeof(queue);
+    
+    return 0;
+}
+
+gss_uint32
+g_queue_internalize(void **vqueue, unsigned char **buf, size_t *lenremain)
+{
+    void *q;
+
+    if (*lenremain < sizeof(queue))
+	return EINVAL;
+    if ((q = malloc(sizeof(queue))) == 0)
+	return ENOMEM;
+    memcpy(q, *buf, sizeof(queue));
+    *buf += sizeof(queue);
+    *lenremain -= sizeof(queue);
+    *vqueue = q;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/util_set.c b/krb5-1-6/src/lib/gssapi/generic/util_set.c
new file mode 100644
index 000000000..fea810852
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/util_set.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 1995 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_generic.h"
+
+struct _g_set_elt {
+   void *key;
+   void *value;
+   struct _g_set_elt *next;
+};
+
+int g_set_init(g_set_elt *s)
+{
+   *s = NULL;
+
+   return(0);
+}
+
+#if 0
+int g_set_destroy(g_set_elt *s)
+{
+   g_set next;
+
+   while (*s) {
+      next = (*s)->next;
+      free(*s);
+      *s = next;
+   }
+
+   return(0);
+}
+#endif
+
+int g_set_entry_add(g_set_elt *s, void *key, void *value)
+{
+   g_set_elt first;
+
+   if ((first = (struct _g_set_elt *) malloc(sizeof(struct _g_set_elt))) == NULL)
+      return(ENOMEM);
+
+   first->key = key;
+   first->value = value;
+   first->next = *s;
+
+   *s = first;
+
+   return(0);
+}
+
+int g_set_entry_delete(g_set_elt *s, void *key)
+{
+   g_set_elt *p;
+
+   for (p=s; *p; p = &((*p)->next)) {
+      if ((*p)->key == key) {
+	 g_set_elt next = (*p)->next;
+	 free(*p);
+	 *p = next;
+
+	 return(0);
+      }
+   }
+
+   return(-1);
+}
+
+int g_set_entry_get(g_set_elt *s, void *key, void **value)
+{
+   g_set_elt p;
+
+   for (p = *s; p; p = p->next) {
+      if (p->key == key) {
+	 *value = p->value;
+
+	 return(0);
+      }
+   }
+
+   *value = NULL;
+
+   return(-1);
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/util_token.c b/krb5-1-6/src/lib/gssapi/generic/util_token.c
new file mode 100644
index 000000000..7b8dfed22
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/util_token.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_generic.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <limits.h>
+
+/*
+ * $Id$
+ */
+
+/* XXXX this code currently makes the assumption that a mech oid will
+   never be longer than 127 bytes.  This assumption is not inherent in
+   the interfaces, so the code can be fixed if the OSI namespace
+   balloons unexpectedly. */
+
+/* Each token looks like this:
+
+0x60				tag for APPLICATION 0, SEQUENCE
+					(constructed, definite-length)
+	<length>		possible multiple bytes, need to parse/generate
+	0x06			tag for OBJECT IDENTIFIER
+		<moid_length>	compile-time constant string (assume 1 byte)
+		<moid_bytes>	compile-time constant string
+	<inner_bytes>		the ANY containing the application token
+					bytes 0,1 are the token type
+					bytes 2,n are the token data
+
+Note that the token type field is a feature of RFC 1964 mechanisms and
+is not used by other GSSAPI mechanisms.  As such, a token type of -1
+is interpreted to mean that no token type should be expected or
+generated. 
+
+For the purposes of this abstraction, the token "header" consists of
+the sequence tag and length octets, the mech OID DER encoding, and the
+first two inner bytes, which indicate the token type.  The token
+"body" consists of everything else.
+
+*/
+
+static unsigned int der_length_size(length)
+     int length;
+{
+   if (length < (1<<7))
+      return(1);
+   else if (length < (1<<8))
+      return(2);
+#if INT_MAX == 0x7fff
+   else
+       return(3);
+#else
+   else if (length < (1<<16))
+      return(3);
+   else if (length < (1<<24))
+      return(4);
+   else
+      return(5);
+#endif
+}
+
+static void der_write_length(buf, length)
+     unsigned char **buf;
+     int length;
+{
+   if (length < (1<<7)) {
+      *(*buf)++ = (unsigned char) length;
+   } else {
+      *(*buf)++ = (unsigned char) (der_length_size(length)+127);
+#if INT_MAX > 0x7fff
+      if (length >= (1<<24))
+	 *(*buf)++ = (unsigned char) (length>>24);
+      if (length >= (1<<16))
+	 *(*buf)++ = (unsigned char) ((length>>16)&0xff);
+#endif
+      if (length >= (1<<8))
+	 *(*buf)++ = (unsigned char) ((length>>8)&0xff);
+      *(*buf)++ = (unsigned char) (length&0xff);
+   }
+}
+
+/* returns decoded length, or < 0 on failure.  Advances buf and
+   decrements bufsize */
+
+static int der_read_length(buf, bufsize)
+     unsigned char **buf;
+     int *bufsize;
+{
+   unsigned char sf;
+   int ret;
+
+   if (*bufsize < 1)
+      return(-1);
+   sf = *(*buf)++;
+   (*bufsize)--;
+   if (sf & 0x80) {
+      if ((sf &= 0x7f) > ((*bufsize)-1))
+	 return(-1);
+      if (sf > sizeof(int))
+	  return (-1);
+      ret = 0;
+      for (; sf; sf--) {
+	 ret = (ret<<8) + (*(*buf)++);
+	 (*bufsize)--;
+      }
+   } else {
+      ret = sf;
+   }
+
+   return(ret);
+}
+
+/* returns the length of a token, given the mech oid and the body size */
+
+unsigned int g_token_size(mech, body_size)
+     const gss_OID_desc * mech;
+     unsigned int body_size;
+{
+   /* set body_size to sequence contents size */
+   body_size += 4 + (int) mech->length;         /* NEED overflow check */
+   return(1 + der_length_size(body_size) + body_size);
+}
+
+/* fills in a buffer with the token header.  The buffer is assumed to
+   be the right size.  buf is advanced past the token header */
+
+void g_make_token_header(mech, body_size, buf, tok_type)
+     const gss_OID_desc * mech;
+     unsigned int body_size;
+     unsigned char **buf;
+     int tok_type;
+{
+   *(*buf)++ = 0x60;
+   der_write_length(buf, (tok_type == -1) ?2:4 + mech->length + body_size);
+   *(*buf)++ = 0x06;
+   *(*buf)++ = (unsigned char) mech->length;
+   TWRITE_STR(*buf, mech->elements, mech->length);
+   if (tok_type != -1) {
+       *(*buf)++ = (unsigned char) ((tok_type>>8)&0xff);
+       *(*buf)++ = (unsigned char) (tok_type&0xff);
+   }
+}
+
+/*
+ * Given a buffer containing a token, reads and verifies the token,
+ * leaving buf advanced past the token header, and setting body_size
+ * to the number of remaining bytes.  Returns 0 on success,
+ * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the
+ * mechanism in the token does not match the mech argument.  buf and
+ * *body_size are left unmodified on error.
+ */
+
+gss_int32 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize_in,
+				wrapper_required)
+     const gss_OID_desc * mech;
+     unsigned int *body_size;
+     unsigned char **buf_in;
+     int tok_type;
+     unsigned int toksize_in;
+     int wrapper_required;
+{
+   unsigned char *buf = *buf_in;
+   int seqsize;
+   gss_OID_desc toid;
+   int toksize = toksize_in;
+
+   if ((toksize-=1) < 0)
+      return(G_BAD_TOK_HEADER);
+   if (*buf++ != 0x60) {
+       if (wrapper_required)
+	   return(G_BAD_TOK_HEADER);
+       buf--;
+       toksize++;
+       goto skip_wrapper;
+   }
+
+   if ((seqsize = der_read_length(&buf, &toksize)) < 0)
+      return(G_BAD_TOK_HEADER);
+
+   if (seqsize != toksize)
+      return(G_BAD_TOK_HEADER);
+
+   if ((toksize-=1) < 0)
+      return(G_BAD_TOK_HEADER);
+   if (*buf++ != 0x06)
+      return(G_BAD_TOK_HEADER);
+ 
+   if ((toksize-=1) < 0)
+      return(G_BAD_TOK_HEADER);
+   toid.length = *buf++;
+
+   if ((toksize-=toid.length) < 0)
+      return(G_BAD_TOK_HEADER);
+   toid.elements = buf;
+   buf+=toid.length;
+
+   if (! g_OID_equal(&toid, mech)) 
+       return  G_WRONG_MECH;
+skip_wrapper:
+   if (tok_type != -1) {
+       if ((toksize-=2) < 0)
+	   return(G_BAD_TOK_HEADER);
+
+       if ((*buf++ != ((tok_type>>8)&0xff)) ||
+	   (*buf++ != (tok_type&0xff)))
+	   return(G_WRONG_TOKID);
+   }
+   *buf_in = buf;
+   *body_size = toksize;
+
+   return 0;
+}
diff --git a/krb5-1-6/src/lib/gssapi/generic/util_validate.c b/krb5-1-6/src/lib/gssapi/generic/util_validate.c
new file mode 100644
index 000000000..bb9d0d2ec
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/util_validate.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+/*
+ * functions to validate name, credential, and context handles
+ */
+
+#include "gssapiP_generic.h"
+#include "gss_libinit.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <fcntl.h>
+#include <limits.h>
+
+#ifdef HAVE_BSD_DB
+#include <sys/file.h>
+#include <db.h>
+
+static const int one = 1;
+static const DBT dbtone = { (void *) &one, sizeof(one) };
+
+typedef struct _vkey {
+   int type;
+   void *ptr;
+} vkey;
+#endif
+
+#define V_NAME		1
+#define V_CRED_ID	2
+#define V_CTX_ID	3
+#define V_LCTX_ID	4
+
+/* All these functions return 0 on failure, and non-zero on success */
+
+static int g_save(db, type, ptr)
+     g_set *db;
+#ifdef HAVE_BSD_DB
+     int type;
+#else
+     void *type;
+#endif
+     void *ptr;
+{
+   int ret;
+#ifdef HAVE_BSD_DB
+   DB **vdb;
+   vkey vk;
+   DBT key;
+
+   ret = gssint_initialize_library();
+   if (ret)
+       return 0;
+   ret = k5_mutex_lock(&db->mutex);
+   if (ret)
+       return 0;
+
+   vdb = (DB **) &db->data;
+
+   if (!*vdb)
+      *vdb = dbopen(NULL, O_CREAT|O_RDWR, O_CREAT|O_RDWR, DB_HASH, NULL);
+
+   vk.type = type;
+   vk.ptr = ptr;
+
+   key.data = &vk;
+   key.size = sizeof(vk);
+
+   ret = ((*((*vdb)->put))(*vdb, &key, &dbtone, 0) == 0);
+   k5_mutex_unlock(&db->mutex);
+   return ret;
+#else
+   g_set_elt *gs;
+
+   ret = gssint_initialize_library();
+   if (ret)
+       return 0;
+   ret = k5_mutex_lock(&db->mutex);
+   if (ret)
+       return 0;
+
+   gs = (g_set_elt *) &db->data;
+
+   if (!*gs)
+      if (g_set_init(gs)) {
+	 k5_mutex_unlock(&db->mutex);
+	 return(0);
+      }
+
+   ret = (g_set_entry_add(gs, ptr, type) == 0);
+   k5_mutex_unlock(&db->mutex);
+   return ret;
+#endif
+}
+
+static int g_validate(db, type, ptr)
+     g_set *db;
+#ifdef HAVE_BSD_DB
+     int type;
+#else
+     void *type;
+#endif
+     void *ptr;
+{
+   int ret;
+#ifdef HAVE_BSD_DB
+   DB **vdb;
+   vkey vk;
+   DBT key, value;
+
+   ret = k5_mutex_lock(&db->mutex);
+   if (ret)
+       return 0;
+
+   vdb = (DB **) &db->data;
+   if (!*vdb) {
+      k5_mutex_unlock(&db->mutex);
+      return(0);
+   }
+
+   vk.type = type;
+   vk.ptr = ptr;
+
+   key.data = &vk;
+   key.size = sizeof(vk);
+
+   if ((*((*vdb)->get))(*vdb, &key, &value, 0)) {
+      k5_mutex_unlock(&db->mutex);
+      return(0);
+   }
+
+   k5_mutex_unlock(&db->mutex);
+   return((value.size == sizeof(one)) &&
+	  (*((int *) value.data) == one));
+#else
+   g_set_elt *gs;
+   void *value;
+
+   ret = k5_mutex_lock(&db->mutex);
+   if (ret)
+       return 0;
+
+   gs = (g_set_elt *) &db->data;
+   if (!*gs) {
+      k5_mutex_unlock(&db->mutex);
+      return(0);
+   }
+
+   if (g_set_entry_get(gs, ptr, (void **) &value)) {
+      k5_mutex_unlock(&db->mutex);
+      return(0);
+   }
+   k5_mutex_unlock(&db->mutex);
+   return(value == type);
+#endif
+}
+
+static int g_delete(db, type, ptr)
+     g_set *db;
+#ifdef HAVE_BSD_DB
+     int type;
+#else
+     void *type;
+#endif
+     void *ptr;
+{
+   int ret;
+#ifdef HAVE_BSD_DB
+   DB **vdb;
+   vkey vk;
+   DBT key;
+
+   ret = k5_mutex_lock(&db->mutex);
+   if (ret)
+       return 0;
+
+   vdb = (DB **) &db->data;
+   if (!*vdb) {
+      k5_mutex_unlock(&db->mutex);
+      return(0);
+   }
+
+   vk.type = type;
+   vk.ptr = ptr;
+
+   key.data = &vk;
+   key.size = sizeof(vk);
+
+   ret = ((*((*vdb)->del))(*vdb, &key, 0) == 0);
+   k5_mutex_unlock(&db->mutex);
+   return ret;
+#else
+   g_set_elt *gs;
+
+   ret = k5_mutex_lock(&db->mutex);
+   if (ret)
+       return 0;
+
+   gs = (g_set_elt *) &db->data;
+   if (!*gs) {
+      k5_mutex_unlock(&db->mutex);
+      return(0);
+   }
+
+   if (g_set_entry_delete(gs, ptr)) {
+      k5_mutex_unlock(&db->mutex);
+      return(0);
+   }
+   k5_mutex_unlock(&db->mutex);
+   return(1);
+#endif
+}
+
+/* functions for each type */
+
+/* save */
+
+int g_save_name(vdb, name)
+     g_set *vdb;
+     gss_name_t name;
+{
+   return(g_save(vdb, V_NAME, (void *) name));
+}
+int g_save_cred_id(vdb, cred)
+     g_set *vdb;
+     gss_cred_id_t cred;
+{
+   return(g_save(vdb, V_CRED_ID, (void *) cred));
+}
+int g_save_ctx_id(vdb, ctx)
+     g_set *vdb;
+     gss_ctx_id_t ctx;
+{
+   return(g_save(vdb, V_CTX_ID, (void *) ctx));
+}
+int g_save_lucidctx_id(vdb, lctx)
+     g_set *vdb;
+     void *lctx;
+{
+   return(g_save(vdb, V_LCTX_ID, (void *) lctx));
+}
+
+
+/* validate */
+
+int g_validate_name(vdb, name)
+     g_set *vdb;
+     gss_name_t name;
+{
+   return(g_validate(vdb, V_NAME, (void *) name));
+}
+int g_validate_cred_id(vdb, cred)
+     g_set *vdb;
+     gss_cred_id_t cred;
+{
+   return(g_validate(vdb, V_CRED_ID, (void *) cred));
+}
+int g_validate_ctx_id(vdb, ctx)
+     g_set *vdb;
+     gss_ctx_id_t ctx;
+{
+   return(g_validate(vdb, V_CTX_ID, (void *) ctx));
+}
+int g_validate_lucidctx_id(vdb, lctx)
+     g_set *vdb;
+     void *lctx;
+{
+   return(g_validate(vdb, V_LCTX_ID, (void *) lctx));
+}
+
+/* delete */
+
+int g_delete_name(vdb, name)
+     g_set *vdb;
+     gss_name_t name;
+{
+   return(g_delete(vdb, V_NAME, (void *) name));
+}
+int g_delete_cred_id(vdb, cred)
+     g_set *vdb;
+     gss_cred_id_t cred;
+{
+   return(g_delete(vdb, V_CRED_ID, (void *) cred));
+}
+int g_delete_ctx_id(vdb, ctx)
+     g_set *vdb;
+     gss_ctx_id_t ctx;
+{
+   return(g_delete(vdb, V_CTX_ID, (void *) ctx));
+}
+int g_delete_lucidctx_id(vdb, lctx)
+     g_set *vdb;
+     void *lctx;
+{
+   return(g_delete(vdb, V_LCTX_ID, (void *) lctx));
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/generic/utl_nohash_validate.c b/krb5-1-6/src/lib/gssapi/generic/utl_nohash_validate.c
new file mode 100644
index 000000000..da20b71d6
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/generic/utl_nohash_validate.c
@@ -0,0 +1,121 @@
+/*
+ *  Copyright 1990,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+/*
+ * stub functions for those without the hash library.
+ */
+
+#include "gssapiP_generic.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+/* functions for each type */
+
+/* save */
+
+int g_save_name(vdb, name)
+     void **vdb;
+     gss_name_t *name;
+{
+	return 1;
+}
+int g_save_cred_id(vdb, cred)
+     void **vdb;
+     gss_cred_id_t *cred;
+{
+	return 1;
+}
+int g_save_ctx_id(vdb, ctx)
+     void **vdb;
+     gss_ctx_id_t *ctx;
+{
+	return 1;
+}
+int g_save_lucidctx_id(vdb, lctx)
+     void **vdb;
+     void *lctx;
+{
+	return 1;
+}
+
+/* validate */
+
+int g_validate_name(vdb, name)
+     void **vdb;
+     gss_name_t *name;
+{
+	return 1;
+}
+int g_validate_cred_id(vdb, cred)
+     void **vdb;
+     gss_cred_id_t *cred;
+{
+	return 1;
+}
+int g_validate_ctx_id(vdb, ctx)
+     void **vdb;
+     gss_ctx_id_t *ctx;
+{
+	return 1;
+}
+int g_validate_lucidctx_id(vdb, lctx)
+     void **vdb;
+     void *lctx;
+{
+	return 1;
+}
+
+/* delete */
+
+int g_delete_name(vdb, name)
+     void **vdb;
+     gss_name_t *name;
+{
+	return 1;
+}
+int g_delete_cred_id(vdb, cred)
+     void **vdb;
+     gss_cred_id_t *cred;
+{
+	return 1;
+}
+int g_delete_ctx_id(vdb, ctx)
+     void **vdb;
+     gss_ctx_id_t *ctx;
+{
+	return 1;
+}
+int g_delete_lucidctx_id(vdb, lctx)
+     void **vdb;
+     void *lctx;
+{
+	return 1;
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/gss_libinit.c b/krb5-1-6/src/lib/gssapi/gss_libinit.c
new file mode 100644
index 000000000..f075fe481
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/gss_libinit.c
@@ -0,0 +1,79 @@
+#include <assert.h>
+
+#include "gssapi_err_generic.h"
+#include "gssapi_err_krb5.h"
+#include "gssapiP_krb5.h"
+
+#include "gss_libinit.h"
+#include "k5-platform.h"
+
+#include "mglueP.h"
+
+/*
+ * Initialize the GSSAPI library.
+ */
+
+MAKE_INIT_FUNCTION(gssint_lib_init);
+MAKE_FINI_FUNCTION(gssint_lib_fini);
+
+int gssint_lib_init(void)
+{
+    int err;
+
+#ifdef SHOW_INITFINI_FUNCS
+    printf("gssint_lib_init\n");
+#endif
+
+#if !USE_BUNDLE_ERROR_STRINGS
+    add_error_table(&et_k5g_error_table);
+    add_error_table(&et_ggss_error_table);
+#endif
+    err = gssint_mechglue_init();
+    if (err)
+	return err;
+    err = k5_mutex_finish_init(&gssint_krb5_keytab_lock);
+    if (err)
+	return err;
+    err = k5_key_register(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, free);
+    if (err)
+	return err;
+    err = k5_key_register(K5_KEY_GSS_KRB5_CCACHE_NAME, free);
+    if (err)
+	return err;
+#ifndef _WIN32
+    err = k5_mutex_finish_init(&kg_kdc_flag_mutex);
+    if (err)
+	return err;
+#endif
+    return k5_mutex_finish_init(&kg_vdb.mutex);
+}
+
+void gssint_lib_fini(void)
+{
+    if (!INITIALIZER_RAN(gssint_lib_init) || PROGRAM_EXITING()) {
+#ifdef SHOW_INITFINI_FUNCS
+	printf("gssint_lib_fini: skipping\n");
+#endif
+	return;
+    }
+#ifdef SHOW_INITFINI_FUNCS
+    printf("gssint_lib_fini\n");
+#endif
+#if !USE_BUNDLE_ERROR_STRINGS
+    remove_error_table(&et_k5g_error_table);
+    remove_error_table(&et_ggss_error_table);
+#endif
+    k5_key_delete(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
+    k5_key_delete(K5_KEY_GSS_KRB5_CCACHE_NAME);
+    k5_mutex_destroy(&kg_vdb.mutex);
+#ifndef _WIN32
+    k5_mutex_destroy(&kg_kdc_flag_mutex);
+#endif
+    k5_mutex_destroy(&gssint_krb5_keytab_lock);
+    gssint_mechglue_fini();
+}
+
+OM_uint32 gssint_initialize_library (void)
+{
+    return CALL_INIT_FUNCTION(gssint_lib_init);
+}
diff --git a/krb5-1-6/src/lib/gssapi/gss_libinit.h b/krb5-1-6/src/lib/gssapi/gss_libinit.h
new file mode 100644
index 000000000..5a3660426
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/gss_libinit.h
@@ -0,0 +1,9 @@
+#ifndef GSSAPI_LIBINIT_H
+#define GSSAPI_LIBINIT_H
+
+#include "gssapi.h"
+
+OM_uint32 gssint_initialize_library (void);
+void gssint_cleanup_library (void);
+
+#endif /* GSSAPI_LIBINIT_H */
diff --git a/krb5-1-6/src/lib/gssapi/krb5/3des.txt b/krb5-1-6/src/lib/gssapi/krb5/3des.txt
new file mode 100644
index 000000000..64ca1ac49
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/3des.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Kerberos Working Group                                        K. Raeburn
+Category: Informational                                              MIT
+Document: draft-raeburn-krb-gssapi-krb5-3des-01.txt    November 24, 2000
+
+
+         Triple-DES Support for the Kerberos 5 GSSAPI Mechanism
+
+Status of this Memo
+
+   This document is an Internet-Draft and is in full conformance with
+   all provisions of Section 10 of RFC2026 [1]. Internet-Drafts are
+   working documents of the Internet Engineering Task Force (IETF), its
+   areas, and its working groups. Note that other groups may also
+   distribute working documents as Internet-Drafts. Internet-Drafts are
+   draft documents valid for a maximum of six months and may be updated,
+   replaced, or obsoleted by other documents at any time. It is
+   inappropriate to use Internet-Drafts as reference material or to cite
+   them other than as "work in progress."
+
+   The list of current Internet-Drafts can be accessed at
+   http://www.ietf.org/ietf/1id-abstracts.txt
+
+   The list of Internet-Draft Shadow Directories can be accessed at
+   http://www.ietf.org/shadow.html.
+
+1. Abstract
+
+   The GSSAPI Kerberos 5 mechanism definition [GSSAPI-KRB5] specifically
+   enumerates encryption and checksum types, independently of how such
+   schemes may be used in Kerberos.  In the long run, a new Kerberos-
+   based mechanism, which does not require separately enumerating for
+   the GSSAPI mechanism each of the various encryption types defined by
+   Kerberos, is probably a better approach.  Various people have
+   expressed interest in designing one, but the work has not yet been
+   completed.
+
+   The MIT Kerberos 5 release version 1.2 includes support for triple-
+   DES with key derivation [KrbRev].  Recent work by the EFF [EFF] has
+   demonstrated the vulnerability of single-DES mechanisms to brute-
+   force attacks by sufficiently motivated and well-funded parties.  So,
+   in the interest of providing increased security in the near term, MIT
+   is adding support for triple-DES to the existing mechanism
+   implementation we ship, as an interim measure.
+
+
+
+
+
+
+
+
+Raeburn                                                         [Page 1]
+
+INTERNET DRAFT       Triple-DES for GSSAPI Kerberos        November 2000
+
+
+2. New Algorithm Identifiers
+
+   One new sealing algorithm is defined, for use in Wrap tokens.
+
+
+   +--------------------------------------------------------------------+
+   |          name                                octet values          |
+   +--------------------------------------------------------------------+
+   |         DES3-KD                                 02 00              |
+   +--------------------------------------------------------------------+
+
+   This algorithm uses triple-DES with key derivation, with a usage
+   value KG_USAGE_SEAL.  (Unlike the EncryptedData definition in
+   [KrbRev], no integrity protection is needed, so this is "raw" triple-
+   DES, with no checksum attached to the encrypted data.)  Padding is
+   still to 8-byte multiples, and the IV for encrypting application data
+   is zero.
+
+   One new signing algorithm is defined, for use in MIC, Wrap, and
+   Delete tokens.
+
+
+   +--------------------------------------------------------------------+
+   |             name                               octet values        |
+   +--------------------------------------------------------------------+
+   |       HMAC SHA1 DES3-KD                           04 00            |
+   +--------------------------------------------------------------------+
+
+   This algorithm generates an HMAC using SHA-1 and a derived DES3 key
+   with usage KG_USAGE_SIGN, as described in [KrbRev].
+
+   [N.B.: The current [KrbRev] description refers to expired I-Ds from
+   Marc Horowitz.  The text in [KrbRev] may be inadequate to produce an
+   interoperable implementation.]
+
+   The checksum size for this algorithm is 20 octets.  See section 4.3
+   below for the use of checksum lengths of other than eight bytes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Raeburn                                                         [Page 2]
+
+INTERNET DRAFT       Triple-DES for GSSAPI Kerberos        November 2000
+
+
+3. Key Derivation
+
+   For purposes of key derivation, we add three new usage values to the
+   list defined in [KrbRev]; one for signing messages, one for sealing
+   messages, and one for encrypting sequence numbers:
+
+
+   +--------------------------------------------------------------------+
+   |             name                                    value          |
+   +--------------------------------------------------------------------+
+   |         KG_USAGE_SEAL                                22            |
+   |         KG_USAGE_SIGN                                23            |
+   |         KG_USAGE_SEQ                                 24            |
+   +--------------------------------------------------------------------+
+
+4. Adjustments to Previous Definitions
+
+4.1. Quality of Protection
+
+   The GSSAPI specification [GSSAPI] says that a zero QOP value
+   indicates the "default".  The original specification for the Kerberos
+   5 mechanism says that a zero QOP value (or a QOP value with the
+   appropriate bits clear) means DES encryption.
+
+   Rather than forcing the use of plain DES when the application doesn't
+   use mechanism-specific QOP values, we redefine the explicit DES QOP
+   value as a non-zero value, and define a triple-DES value as well.
+   Then a zero value continues to imply the default, which would be
+   triple-DES protection when given a triple-DES session key.
+
+   Our values are:
+
+   +--------------------------------------------------------------------+
+   |             name                  value      meaning               |
+   +--------------------------------------------------------------------+
+   | GSS_KRB5_INTEG_C_QOP_HMAC_SHA1    0x0004     SHA-1 HMAC, using     |
+   |                                              key derivation        |
+   |                                                                    |
+   |    GSS_KRB5_CONF_C_QOP_DES        0x0100     plain DES encryption  |
+   |                                                                    |
+   |  GSS_KRB5_CONF_C_QOP_DES3_KD      0x0200     triple-DES with key   |
+   |                                              derivation            |
+   +--------------------------------------------------------------------+
+
+   Rather than attempt to specify a generic mechanism for deriving a key
+   of one type given a key of another type, and evaluate the security
+   implications of using a short key to generate a longer key to satisfy
+   the requested quality of protection, our implementation will simply
+
+
+
+Raeburn                                                         [Page 3]
+
+INTERNET DRAFT       Triple-DES for GSSAPI Kerberos        November 2000
+
+
+   return an error if the nonzero QOP value specified does not
+   correspond to the session key type.
+
+4.2. MIC Sequence Number Encryption
+
+   The sequence numbers are encrypted in the context key (as defined in
+   [GSSAPI-KRB5] -- this will be either the Kerberos session key or
+   asubkey provided by the context initiator), using whatever encryption
+   system is designated by the type of that context key.  The IV is
+   formed from the first N bytes of the SGN_CKSUM field, where N is the
+   number of bytes needed for the IV.  (With all algorithms described
+   here and in [GSSAPI-KRB5], the checksum is at least as large as the
+   IV.)
+
+4.3. Message Layout
+
+   Both MIC and Wrap tokens, as defined in [GSSAPI-KRB5], contain an
+   checksum field SGN_CKSUM.  In [GSSAPI-KRB5], this field was specified
+   as being 8 bytes long.  We now change this size to be "defined by the
+   checksum algorithm", and retroactively amend the descriptions of all
+   the checksum algorithms described in [GSSAPI-KRB5] to explicitly
+   specify 8-byte output.  Application data continues to immediately
+   follow the checksum field in the Wrap token.
+
+   The revised message descriptions are thus:
+
+   MIC token:
+
+   Byte #             Name                Description
+   ----------------------------------------------------------------------
+    0..1              TOK_ID              Identification field.
+    2..3              SGN_ALG             Integrity algorithm indicator.
+    4..7              Filler              Contains ff ff ff ff
+    8..15             SND_SEQ             Sequence number field.
+   16..s+15           SGN_CKSUM           Checksum of "to-be-signed
+                                          data", calculated according to
+                                          algorithm specified in SGN_ALG
+                                          field.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Raeburn                                                         [Page 4]
+
+INTERNET DRAFT       Triple-DES for GSSAPI Kerberos        November 2000
+
+
+   Wrap token:
+
+   Byte #           Name             Description
+   ----------------------------------------------------------------------
+    0..1            TOK_ID           Identification field.  Tokens
+                                     emitted by GSS_Wrap() contain the
+                                     hex value 02 01 in this field.
+    2..3            SGN_ALG          Checksum algorithm indicator.
+    4..5            SEAL_ALG         Sealing algorithm indicator.
+    6..7            Filler           Contains ff ff
+    8..15           SND_SEQ          Encrypted sequence number field.
+   16..s+15         SGN_CKSUM        Checksum of plaintext padded data,
+                                     calculated according to algorithm
+                                     specified in SGN_ALG field.
+   s+16..last       Data             encrypted or plaintext padded data
+
+
+   Where "s" indicates the size of the checksum.
+
+   As indicated above in section 2, we define the HMAC SHA1 DES3-KD
+   checksum algorithm to produce a 20-byte output, so encrypted data
+   begins at byte 36.
+
+5. Backwards Compatibility Considerations
+
+   The context initiator should request of the KDC credentials using
+   session-key cryptosystem types supported by that implementation; if
+   the only types returned by the KDC are not supported by the mechanism
+   implementation, it should indicate a failure.  This may seem obvious,
+   but early implementations of both Kerberos and the GSSAPI Kerberos
+   mechanism supported only DES keys, so the cryptosystem compatibility
+   question was easy to overlook.
+
+   Under the current mechanism, no negotiation of algorithm types
+   occurs, so server-side (acceptor) implementations cannot request that
+   clients not use algorithm types not understood by the server.
+   However, administration of the server's Kerberos data (e.g., the
+   service key) has to be done in communication with the KDC, and it is
+   from the KDC that the client will request credentials.  The KDC could
+   therefore be tasked with limiting session keys for a given service to
+   types actually supported by the Kerberos and GSSAPI software on the
+   server.
+
+   This does have a drawback for cases where a service principal name is
+   used both for GSSAPI-based and non-GSSAPI-based communication (most
+   notably the "host" service key), if the GSSAPI implementation does
+   not understand triple-DES but the Kerberos implementation does.  It
+   means that triple-DES session keys cannot be issued for that service
+
+
+
+Raeburn                                                         [Page 5]
+
+INTERNET DRAFT       Triple-DES for GSSAPI Kerberos        November 2000
+
+
+   principal, which keeps the protection of non-GSSAPI services weaker
+   than necessary.
+
+   It would also be possible to have clients attempt to get single-DES
+   session keys before trying to get triple-DES session keys, and have
+   the KDC refuse to issue the single-DES keys only for the most
+   critical of services, for which single-DES protection is considered
+   inadequate.  However, that would eliminate the possibility of
+   connecting with the more secure cryptosystem to any service that can
+   be accessed with the weaker cryptosystem.
+
+   For MIT's 1.2 release, we chose to go with the former approach,
+   putting the burden on the KDC administration and gaining the best
+   protection possible for GSSAPI services, possibly at the cost of
+   weaker protection of non-GSSAPI Kerberos services running earlier
+   versions of the software.
+
+6. Security Considerations
+
+   Various tradeoffs arise regarding the mixing of new and old software,
+   or GSSAPI-based and non-GSSAPI Kerberos authentication.  They are
+   discussed in section 5.
+
+7. References
+
+   [EFF] Electronic Frontier Foundation, "Cracking DES: Secrets of
+   Encryption Research, Wiretap Politics, and Chip Design", O'Reilly &
+   Associates, Inc., May, 1998.
+
+   [GSSAPI] Linn, J., "Generic Security Service Application Program
+   Interface Version 2, Update 1", RFC 2743, January, 2000.
+
+   [GSSAPI-KRB5] Linn, J., "The Kerberos Version 5 GSS-API Mechanism",
+   RFC 1964, June, 1996.
+
+   [KrbRev] Neuman, C., Kohl, J., Ts'o, T., "The Kerberos Network
+   Authentication Service (V5)", draft-ietf-cat-kerberos-
+   revisions-06.txt, July 4, 2000.
+
+8. Author's Address
+
+   Kenneth Raeburn Massachusetts Institute of Technology 77
+   Massachusetts Avenue Cambridge, MA 02139
+
+9. Full Copyright Statement
+
+   Copyright (C) The Internet Society (2000).  All Rights Reserved.
+
+
+
+
+Raeburn                                                         [Page 6]
+
+INTERNET DRAFT       Triple-DES for GSSAPI Kerberos        November 2000
+
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE."
+
+10. Document Change History
+
+>From -00 to -01:
+
+   Converted master to GNU troff and tbl, rewriting tables in the
+   process.
+
+   Specify informational category only.  Modify some text to emphasize
+   that this document intends to describe MIT's extensions.
+
+   Point out that while EncryptedData for 3des-kd includes a checksum,
+   DES3-KD GSS encryption does not.
+
+   Shorten backwards-compatibility descriptions a little.
+
+   Submit to Kerberos working group rather than CAT.
+
+
+
+
+
+
+
+
+
+
+
+Raeburn                                                         [Page 7]
+
diff --git a/krb5-1-6/src/lib/gssapi/krb5/Makefile.in b/krb5-1-6/src/lib/gssapi/krb5/Makefile.in
new file mode 100644
index 000000000..805f5a118
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/Makefile.in
@@ -0,0 +1,774 @@
+thisconfigdir=../../..
+myfulldir=lib/gssapi/krb5
+mydir=lib/gssapi/krb5
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic -I../mechglue -I$(srcdir)/../mechglue
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=krb5
+##DOS##OBJFILE = ..\$(OUTPRE)krb5.lst
+
+##DOS##DLL_EXP_TYPE=GSS
+
+include_stdint=@include_stdint@
+##DOS##include_stdint=
+ETSRCS= gssapi_err_krb5.c
+ETOBJS= $(OUTPRE)gssapi_err_krb5.$(OBJEXT)
+ETHDRS= gssapi_err_krb5.h
+
+$(OUTPRE)gssapi_err_krb5.$(OBJEXT): gssapi_err_krb5.c
+gssapi_err_krb5.h: gssapi_err_krb5.et
+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 \
+	$(srcdir)/copy_ccache.c \
+	$(srcdir)/delete_sec_context.c \
+	$(srcdir)/disp_name.c \
+	$(srcdir)/disp_status.c \
+	$(srcdir)/duplicate_name.c \
+	$(srcdir)/export_name.c \
+	$(srcdir)/export_sec_context.c \
+	$(srcdir)/get_tkt_flags.c \
+	$(srcdir)/gssapi_krb5.c \
+	$(srcdir)/import_name.c \
+	$(srcdir)/import_sec_context.c \
+	$(srcdir)/indicate_mechs.c \
+	$(srcdir)/init_sec_context.c \
+	$(srcdir)/inq_context.c \
+	$(srcdir)/inq_cred.c \
+	$(srcdir)/inq_names.c \
+	$(srcdir)/k5seal.c \
+	$(srcdir)/k5sealv3.c \
+	$(srcdir)/k5unseal.c \
+	$(srcdir)/krb5_gss_glue.c \
+	$(srcdir)/lucid_context.c \
+	$(srcdir)/process_context_token.c \
+	$(srcdir)/rel_cred.c \
+	$(srcdir)/rel_oid.c \
+	$(srcdir)/rel_name.c \
+	$(srcdir)/seal.c \
+	$(srcdir)/set_allowable_enctypes.c \
+	$(srcdir)/ser_sctx.c \
+	$(srcdir)/set_ccache.c \
+	$(srcdir)/sign.c \
+	$(srcdir)/unseal.c \
+	$(srcdir)/util_cksum.c \
+	$(srcdir)/util_crypt.c \
+	$(srcdir)/util_seed.c \
+	$(srcdir)/util_seqnum.c \
+	$(srcdir)/val_cred.c \
+	$(srcdir)/verify.c \
+	$(srcdir)/wrap_size_limit.c \
+	gssapi_err_krb5.c
+
+#	$(srcdir)/pname_to_uid.c \
+#	$(srcdir)/k5mech.c
+
+OBJS = \
+	$(OUTPRE)accept_sec_context.$(OBJEXT) \
+	$(OUTPRE)acquire_cred.$(OBJEXT) \
+	$(OUTPRE)add_cred.$(OBJEXT) \
+	$(OUTPRE)canon_name.$(OBJEXT) \
+	$(OUTPRE)compare_name.$(OBJEXT) \
+	$(OUTPRE)context_time.$(OBJEXT) \
+	$(OUTPRE)copy_ccache.$(OBJEXT) \
+	$(OUTPRE)delete_sec_context.$(OBJEXT) \
+	$(OUTPRE)disp_name.$(OBJEXT) \
+	$(OUTPRE)disp_status.$(OBJEXT) \
+	$(OUTPRE)duplicate_name.$(OBJEXT) \
+	$(OUTPRE)export_name.$(OBJEXT) \
+	$(OUTPRE)export_sec_context.$(OBJEXT) \
+	$(OUTPRE)get_tkt_flags.$(OBJEXT) \
+	$(OUTPRE)gssapi_krb5.$(OBJEXT) \
+	$(OUTPRE)import_name.$(OBJEXT) \
+	$(OUTPRE)import_sec_context.$(OBJEXT) \
+	$(OUTPRE)indicate_mechs.$(OBJEXT) \
+	$(OUTPRE)init_sec_context.$(OBJEXT) \
+	$(OUTPRE)inq_context.$(OBJEXT) \
+	$(OUTPRE)inq_cred.$(OBJEXT) \
+	$(OUTPRE)inq_names.$(OBJEXT) \
+	$(OUTPRE)k5seal.$(OBJEXT) \
+	$(OUTPRE)k5sealv3.$(OBJEXT) \
+	$(OUTPRE)k5unseal.$(OBJEXT) \
+	$(OUTPRE)krb5_gss_glue.$(OBJEXT) \
+	$(OUTPRE)lucid_context.$(OBJEXT) \
+	$(OUTPRE)process_context_token.$(OBJEXT) \
+	$(OUTPRE)rel_cred.$(OBJEXT) \
+	$(OUTPRE)rel_oid.$(OBJEXT) \
+	$(OUTPRE)rel_name.$(OBJEXT) \
+	$(OUTPRE)seal.$(OBJEXT) \
+	$(OUTPRE)set_allowable_enctypes.$(OBJEXT) \
+	$(OUTPRE)ser_sctx.$(OBJEXT) \
+	$(OUTPRE)set_ccache.$(OBJEXT) \
+	$(OUTPRE)sign.$(OBJEXT) \
+	$(OUTPRE)unseal.$(OBJEXT) \
+	$(OUTPRE)util_cksum.$(OBJEXT) \
+	$(OUTPRE)util_crypt.$(OBJEXT) \
+	$(OUTPRE)util_seed.$(OBJEXT) \
+	$(OUTPRE)util_seqnum.$(OBJEXT) \
+	$(OUTPRE)val_cred.$(OBJEXT) \
+	$(OUTPRE)verify.$(OBJEXT) \
+	$(OUTPRE)wrap_size_limit.$(OBJEXT) \
+	$(OUTPRE)gssapi_err_krb5.$(OBJEXT)
+
+#	k5mech.$(OBJEXT) \
+#	pname_to_uid.$(OBJEXT)
+
+STLIBOBJS = \
+	accept_sec_context.o \
+	acquire_cred.o \
+	add_cred.o \
+	canon_name.o \
+	compare_name.o \
+	context_time.o \
+	copy_ccache.o \
+	delete_sec_context.o \
+	disp_name.o \
+	disp_status.o \
+	duplicate_name.o \
+	export_name.o \
+	export_sec_context.o \
+	get_tkt_flags.o \
+	gssapi_krb5.o \
+	import_name.o \
+	import_sec_context.o \
+	indicate_mechs.o \
+	init_sec_context.o \
+	inq_context.o \
+	inq_cred.o \
+	inq_names.o \
+	k5seal.o \
+	k5sealv3.o \
+	k5unseal.o \
+	krb5_gss_glue.o \
+	lucid_context.o \
+	process_context_token.o \
+	rel_cred.o \
+	rel_oid.o \
+	rel_name.o \
+	seal.o \
+	set_allowable_enctypes.o \
+	ser_sctx.o \
+	set_ccache.o \
+	sign.o \
+	unseal.o \
+	util_cksum.o \
+	util_crypt.o \
+	util_seed.o \
+	util_seqnum.o \
+	val_cred.o \
+	verify.o \
+	wrap_size_limit.o \
+	gssapi_err_krb5.o
+
+#	k5mech.o \
+#	pname_to_uid.o
+
+HDRS= $(ETHDRS)
+
+EHDRDIR=$(BUILDTOP)$(S)include$(S)gssapi
+EXPORTED_HEADERS= gssapi_krb5.h
+
+##DOS##LIBOBJS = $(OBJS)
+
+GSSAPI_KRB5_HDR=$(EHDRDIR)$(S)gssapi_krb5.h
+
+all-windows:: $(EHDRDIR) $(GSSAPI_KRB5_HDR) $(SRCS) $(HDRS)
+
+##DOS##$(EHDRDIR):
+##DOS##	mkdir $(EHDRDIR)
+
+MK_EHDRDIR=if test -d $(EHDRDIR); then :; else (set -x; mkdir $(EHDRDIR)); fi
+##DOS##MK_EHDRDIR=rem
+
+$(GSSAPI_KRB5_HDR): gssapi_krb5.h
+	@$(MK_EHDRDIR)
+	$(CP) gssapi_krb5.h "$@"
+
+all-unix:: $(SRCS) $(HDRS) $(GSSAPI_KRB5_HDR) includes
+all-unix:: all-libobjs
+
+clean-unix::
+	$(RM) $(BUILDTOP)/include/gssapi/gssapi_krb5.h
+	-$(RM) gssapi_krb5.h
+
+clean-unix:: clean-libobjs
+	$(RM) $(ETHDRS) $(ETSRCS)
+
+clean-windows::
+	$(RM) $(EHDRDIR)\gssapi_krb5.h
+	-if exist $(EHDRDIR)\nul rmdir $(EHDRDIR)
+
+generate-files-mac: gssapi_krb5.h
+
+##DOS##!if 0
+gssapi_krb5.h: gssapi_krb5.hin
+	@echo "Creating gssapi.h" ; \
+	h=gss$$$$; $(RM) $$h; \
+	(echo "/* This is the gssapi_krb5.h prologue. */"; \
+	$(include_stdint) ; \
+	echo "/* End of gssapi_krb5.h prologue. */"; \
+	cat $(srcdir)/gssapi_krb5.hin )> $$h && \
+	(set -x; $(MV) $$h $@) ; e=$$?; $(RM) $$h; exit $$e
+##DOS##!endif
+##DOS### No prologue needed for Windows, the support is
+##DOS### in gssapi_krb5.hin already.
+##DOS##gssapi_krb5.h: gssapi_krb5.hin
+##DOS##	$(CP) gssapi_krb5.hin gssapi_krb5.h
+
+install-headers-unix install::
+	@set -x; for f in $(EXPORTED_HEADERS) ; \
+	do $(INSTALL_DATA) $$f	\
+		$(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \
+	done
+
+depend:: $(ETSRCS)
+
+includes::  gssapi_krb5.h
+
+install::
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+accept_sec_context.so accept_sec_context.po $(OUTPRE)accept_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h accept_sec_context.c \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h
+acquire_cred.so acquire_cred.po $(OUTPRE)acquire_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h $(srcdir)/../gss_libinit.h \
+  ../generic/gssapi_err_generic.h acquire_cred.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+add_cred.so add_cred.po $(OUTPRE)add_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h add_cred.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+canon_name.so canon_name.po $(OUTPRE)canon_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h canon_name.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+compare_name.so compare_name.po $(OUTPRE)compare_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h compare_name.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+context_time.so context_time.po $(OUTPRE)context_time.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h context_time.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+copy_ccache.so copy_ccache.po $(OUTPRE)copy_ccache.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h copy_ccache.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+delete_sec_context.so delete_sec_context.po $(OUTPRE)delete_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h delete_sec_context.c \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h
+disp_name.so disp_name.po $(OUTPRE)disp_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h disp_name.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+disp_status.so disp_status.po $(OUTPRE)disp_status.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h $(srcdir)/../gss_libinit.h \
+  ../generic/gssapi_err_generic.h disp_status.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+duplicate_name.so duplicate_name.po $(OUTPRE)duplicate_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h duplicate_name.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+export_name.so export_name.po $(OUTPRE)export_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h export_name.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+export_sec_context.so export_sec_context.po $(OUTPRE)export_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h export_sec_context.c \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h
+get_tkt_flags.so get_tkt_flags.po $(OUTPRE)get_tkt_flags.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h get_tkt_flags.c gssapiP_krb5.h \
+  gssapi_err_krb5.h gssapi_krb5.h
+gssapi_krb5.so gssapi_krb5.po $(OUTPRE)gssapi_krb5.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.c gssapi_krb5.h
+import_name.so import_name.po $(OUTPRE)import_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h import_name.c
+import_sec_context.so import_sec_context.po $(OUTPRE)import_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h import_sec_context.c
+indicate_mechs.so indicate_mechs.po $(OUTPRE)indicate_mechs.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  $(srcdir)/../mechglue/mechglue.h $(srcdir)/../mechglue/mglueP.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h indicate_mechs.c
+init_sec_context.so init_sec_context.po $(OUTPRE)init_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h $(srcdir)/../gss_libinit.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h init_sec_context.c
+inq_context.so inq_context.po $(OUTPRE)inq_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h inq_context.c
+inq_cred.so inq_cred.po $(OUTPRE)inq_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h inq_cred.c
+inq_names.so inq_names.po $(OUTPRE)inq_names.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h inq_names.c
+k5seal.so k5seal.po $(OUTPRE)k5seal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h k5seal.c
+k5sealv3.so k5sealv3.po $(OUTPRE)k5sealv3.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h k5sealv3.c
+k5unseal.so k5unseal.po $(OUTPRE)k5unseal.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h k5unseal.c
+krb5_gss_glue.so krb5_gss_glue.po $(OUTPRE)krb5_gss_glue.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  $(srcdir)/../mechglue/mechglue.h $(srcdir)/../mechglue/mglueP.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h krb5_gss_glue.c
+lucid_context.so lucid_context.po $(OUTPRE)lucid_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h lucid_context.c
+process_context_token.so process_context_token.po $(OUTPRE)process_context_token.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h process_context_token.c
+rel_cred.so rel_cred.po $(OUTPRE)rel_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h rel_cred.c
+rel_oid.so rel_oid.po $(OUTPRE)rel_oid.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h rel_oid.c
+rel_name.so rel_name.po $(OUTPRE)rel_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h rel_name.c
+seal.so seal.po $(OUTPRE)seal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h seal.c
+set_allowable_enctypes.so set_allowable_enctypes.po \
+  $(OUTPRE)set_allowable_enctypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h set_allowable_enctypes.c
+ser_sctx.so ser_sctx.po $(OUTPRE)ser_sctx.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h ser_sctx.c
+set_ccache.so set_ccache.po $(OUTPRE)set_ccache.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h $(srcdir)/../gss_libinit.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h set_ccache.c
+sign.so sign.po $(OUTPRE)sign.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h sign.c
+unseal.so unseal.po $(OUTPRE)unseal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h unseal.c
+util_cksum.so util_cksum.po $(OUTPRE)util_cksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h util_cksum.c
+util_crypt.so util_crypt.po $(OUTPRE)util_crypt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h util_crypt.c
+util_seed.so util_seed.po $(OUTPRE)util_seed.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h util_seed.c
+util_seqnum.so util_seqnum.po $(OUTPRE)util_seqnum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h util_seqnum.c
+val_cred.so val_cred.po $(OUTPRE)val_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h val_cred.c
+verify.so verify.po $(OUTPRE)verify.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h ../generic/gssapi_err_generic.h \
+  gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h verify.c
+wrap_size_limit.so wrap_size_limit.po $(OUTPRE)wrap_size_limit.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \
+  gssapi_krb5.h wrap_size_limit.c
+gssapi_err_krb5.so gssapi_err_krb5.po $(OUTPRE)gssapi_err_krb5.$(OBJEXT): \
+  $(COM_ERR_DEPS) gssapi_err_krb5.c
diff --git a/krb5-1-6/src/lib/gssapi/krb5/accept_sec_context.c b/krb5-1-6/src/lib/gssapi/krb5/accept_sec_context.c
new file mode 100644
index 000000000..7dcdd1a51
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/accept_sec_context.c
@@ -0,0 +1,998 @@
+/*
+ * Copyright 2000, 2004  by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <assert.h>
+
+#ifdef CFX_EXERCISE
+#define CFX_ACCEPTOR_SUBKEY (time(0) & 1)
+#else
+#define CFX_ACCEPTOR_SUBKEY 1
+#endif
+
+/* 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)
+    krb5_context context;
+    krb5_auth_context auth_context;
+    krb5_data *inbuf;
+    krb5_gss_cred_id_t *out_cred;
+{
+    krb5_creds ** creds = NULL;
+    krb5_error_code retval;
+    krb5_ccache ccache = NULL;
+    krb5_gss_cred_id_t cred = NULL;
+    krb5_auth_context new_auth_ctx = NULL;
+	krb5_int32 flags_org;
+
+	if ((retval = krb5_auth_con_getflags(context, auth_context, &flags_org)))
+		return retval;
+	krb5_auth_con_setflags(context, auth_context,
+			       0);
+
+	/*
+	 * By the time krb5_rd_cred is called here (after krb5_rd_req has been
+	 * called in krb5_gss_accept_sec_context), the "keyblock" field of
+	 * auth_context contains a pointer to the session key, and the
+	 * "recv_subkey" field might contain a session subkey.  Either of
+	 * these (the "recv_subkey" if it isn't NULL, otherwise the
+	 * "keyblock") might have been used to encrypt the encrypted part of
+	 * the KRB_CRED message that contains the forwarded credentials.  (The
+	 * Java Crypto and Security Implementation from the DSTC in Australia
+	 * always uses the session key.  But apparently it never negotiates a
+	 * subkey, so this code works fine against a JCSI client.)  Up to the
+	 * present, though, GSSAPI clients linked against the MIT code (which
+	 * is almost all GSSAPI clients) don't encrypt the KRB_CRED message at
+	 * all -- at this level.  So if the first call to krb5_rd_cred fails,
+	 * we should call it a second time with another auth context freshly
+	 * created by krb5_auth_con_init.  All of its keyblock fields will be
+	 * NULL, so krb5_rd_cred will assume that the KRB_CRED message is
+	 * unencrypted.  (The MIT code doesn't actually send the KRB_CRED
+	 * message in the clear -- the "authenticator" whose "checksum" ends up
+	 * containing the KRB_CRED message does get encrypted.)
+	 */
+	if (krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)) {
+		if ((retval = krb5_auth_con_init(context, &new_auth_ctx)))
+			goto cleanup;
+		krb5_auth_con_setflags(context, new_auth_ctx, 0);
+		if ((retval = krb5_rd_cred(context, new_auth_ctx, inbuf,
+					   &creds, NULL)))
+			goto cleanup;
+		}
+
+    if ((retval = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) {
+	ccache = NULL;
+        goto cleanup;
+    }
+
+    if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
+	goto cleanup;
+
+    if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
+	goto cleanup;
+
+    /* 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;
+	}
+
+	/* zero it out... */
+	memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
+
+	retval = k5_mutex_init(&cred->lock);
+	if (retval) {
+	    xfree(cred);
+	    cred = NULL;
+	    goto cleanup;
+	}
+
+	/* copy the client principle into it... */
+	if ((retval =
+	     krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
+	    k5_mutex_destroy(&cred->lock);
+	    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->keytab = NULL; /* no keytab associated with this... */
+	cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
+	cred->ccache = ccache; /* the ccache containing the credential */
+	ccache = NULL; /* cred takes ownership so don't destroy */
+    }
+
+    /* If there were errors, there might have been a memory leak
+       if (!cred)
+       if ((retval = krb5_cc_close(context, ccache)))
+       goto cleanup;
+    */
+cleanup:
+    if (creds)
+	krb5_free_tgt_creds(context, creds);
+
+    if (ccache)
+	(void)krb5_cc_destroy(context, ccache);
+
+    if (out_cred)
+	*out_cred = cred; /* return credential */
+
+    if (new_auth_ctx)
+	krb5_auth_con_free(context, new_auth_ctx);
+
+    krb5_auth_con_setflags(context, auth_context, flags_org);
+
+    return retval;
+}
+
+OM_uint32
+krb5_gss_accept_sec_context(minor_status, context_handle, 
+			    verifier_cred_handle, input_token,
+			    input_chan_bindings, src_name, mech_type,
+			    output_token, ret_flags, time_rec,
+			    delegated_cred_handle)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t *context_handle;
+     gss_cred_id_t verifier_cred_handle;
+     gss_buffer_t input_token;
+     gss_channel_bindings_t input_chan_bindings;
+     gss_name_t *src_name;
+     gss_OID *mech_type;
+     gss_buffer_t output_token;
+     OM_uint32 *ret_flags;
+     OM_uint32 *time_rec;
+     gss_cred_id_t *delegated_cred_handle;
+{
+   krb5_context context;
+   unsigned char *ptr, *ptr2;
+   char *sptr;
+   long tmp;
+   size_t md5len;
+   int bigend;
+   krb5_gss_cred_id_t cred = 0;
+   krb5_data ap_rep, ap_req;
+   int i;
+   krb5_error_code code;
+   krb5_address addr, *paddr;
+   krb5_authenticator *authdat = 0;
+   krb5_checksum reqcksum;
+   krb5_principal name = NULL;
+   krb5_ui_4 gss_flags = 0;
+   int decode_req_message = 0;
+   krb5_gss_ctx_id_rec *ctx = 0;
+   krb5_timestamp now;
+   gss_buffer_desc token;
+   krb5_auth_context auth_context = NULL;
+   krb5_ticket * ticket = NULL;
+   int option_id;
+   krb5_data option;
+   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;
+   krb5int_access kaccess;
+   int cred_rcache = 0;
+
+   code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
+   if (code) {
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+   }
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   /* set up returns to be freeable */
+
+   if (src_name)
+      *src_name = (gss_name_t) NULL;
+   output_token->length = 0;
+   output_token->value = NULL;
+   token.value = 0;
+   reqcksum.contents = 0;
+   ap_req.data = 0;
+   ap_rep.data = 0;
+   
+   if (mech_type)
+      *mech_type = GSS_C_NULL_OID;
+   /* return a bogus cred handle */
+   if (delegated_cred_handle)
+      *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
+
+   /*
+    * Context handle must be unspecified.  Actually, it must be
+    * non-established, but currently, accept_sec_context never returns
+    * a non-established context handle.
+    */
+   /*SUPPRESS 29*/
+   if (*context_handle != GSS_C_NO_CONTEXT) {
+      *minor_status = 0;
+      krb5_free_context(context);
+      return(GSS_S_FAILURE);
+   }
+
+   /* handle default cred handle */
+   if (verifier_cred_handle == GSS_C_NO_CREDENTIAL) {
+       major_status = krb5_gss_acquire_cred(minor_status, 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) {
+	   code = *minor_status;
+	   goto fail;
+       }
+   } else {
+       major_status = krb5_gss_validate_cred(minor_status,
+					     verifier_cred_handle);
+       if (GSS_ERROR(major_status)) {
+	   code = *minor_status;
+	   goto fail;
+       }
+       cred_handle = verifier_cred_handle;
+   }
+
+   cred = (krb5_gss_cred_id_t) cred_handle;
+
+   /* make sure the supplied credentials are valid for accept */
+
+   if ((cred->usage != GSS_C_ACCEPT) &&
+       (cred->usage != GSS_C_BOTH)) {
+       code = 0;
+       major_status = GSS_S_NO_CRED;
+       goto fail;
+   }
+
+   /* verify the token's integrity, and leave the token in ap_req.
+      figure out which mech oid was used, and save it */
+
+   ptr = (unsigned char *) input_token->value;
+
+   if (!(code = g_verify_token_header(gss_mech_krb5,
+				      &(ap_req.length),
+				      &ptr, KG_TOK_CTX_AP_REQ,
+				      input_token->length, 1))) {
+       mech_used = gss_mech_krb5;
+   } else if ((code == G_WRONG_MECH)
+	      &&!(code = g_verify_token_header((gss_OID) gss_mech_krb5_wrong,
+					     &(ap_req.length), 
+					     &ptr, KG_TOK_CTX_AP_REQ,
+					     input_token->length, 1))) {
+       mech_used = gss_mech_krb5_wrong;
+   } else if ((code == G_WRONG_MECH) &&
+	      !(code = g_verify_token_header(gss_mech_krb5_old,
+					     &(ap_req.length), 
+					     &ptr, KG_TOK_CTX_AP_REQ,
+					     input_token->length, 1))) {
+       /*
+	* 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.
+	*/
+       mech_used = gss_mech_krb5_old;
+   } else if (code == G_WRONG_TOKID) {
+       major_status = GSS_S_CONTINUE_NEEDED;
+       code = KRB5KRB_AP_ERR_MSG_TYPE;
+       mech_used = gss_mech_krb5;
+       goto fail;
+   } else {
+       major_status = GSS_S_DEFECTIVE_TOKEN;
+       goto fail;
+   }
+
+   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;
+
+       paddr = &addr;
+   } else {
+       paddr = NULL;
+   }
+
+   /* decode the AP_REQ message */
+
+   /* decode the message */
+
+   if ((code = krb5_auth_con_init(context, &auth_context))) {
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
+   if (cred->rcache) {
+       cred_rcache = 1;
+       if ((code = krb5_auth_con_setrcache(context, auth_context, cred->rcache))) {
+	   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;
+       goto fail;
+   }
+   krb5_auth_con_setflags(context, auth_context,
+			  KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+
+   krb5_auth_con_getauthenticator(context, auth_context, &authdat);
+
+#if 0
+   /* make sure the necessary parts of the authdat are present */
+
+   if ((authdat->authenticator->subkey == NULL) ||
+       (authdat->ticket->enc_part2 == NULL)) {
+	   code = KG_NO_SUBKEY;
+	   major_status = GSS_S_FAILURE;
+	   goto fail;
+   }
+#endif
+
+   {
+       /* gss krb5 v1 */
+
+       /* stash this now, for later. */
+       code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &md5len);
+       if (code) {
+	   major_status = GSS_S_FAILURE;
+	   goto fail;
+       }
+
+       /* verify that the checksum is correct */
+
+       /*
+	 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;
+       }
+
+       /*
+	 "Be liberal in what you accept, and
+	 conservative in what you send"
+	 -- rfc1123
+
+	 This code will let this acceptor interoperate with an initiator
+	 using little-endian or big-endian integer encoding.
+       */
+
+       ptr = (unsigned char *) authdat->checksum->contents;
+       bigend = 0;
+
+       TREAD_INT(ptr, tmp, bigend);
+
+       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 */
+
+
+       /* 
+          The following section of code attempts to implement the
+          optional channel binding facility as described in RFC2743.
+
+          Since this facility is optional channel binding may or may
+          not have been provided by either the client or the server.
+
+          If the server has specified input_chan_bindings equal to
+          GSS_C_NO_CHANNEL_BINDINGS then we skip the check.  If
+          the server does provide channel bindings then we compute
+          a checksum and compare against those provided by the
+          client.         */
+
+       if ((code = kg_checksum_channel_bindings(context, 
+						input_chan_bindings,
+						&reqcksum, bigend))) {
+	 major_status = GSS_S_BAD_BINDINGS;
+	 goto fail;
+       }
+
+       /* Always read the clients bindings - eventhough we might ignore them */
+       TREAD_STR(ptr, ptr2, reqcksum.length);
+
+       if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS ) {
+           if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
+               xfree(reqcksum.contents);
+               reqcksum.contents = 0;
+	       code = 0;
+	       major_status = GSS_S_BAD_BINDINGS;
+                   goto fail;
+           }
+           
+       }
+
+       xfree(reqcksum.contents);
+       reqcksum.contents = 0;
+
+       TREAD_INT(ptr, gss_flags, bigend);
+#if 0
+       gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag; if
+					  there's a delegation, we'll set
+					  it below */
+#endif
+       decode_req_message = 0;
+
+       /* if the checksum length > 24, there are options to process */
+
+       if(authdat->checksum->length > 24 && (gss_flags & GSS_C_DELEG_FLAG)) {
+
+	   i = authdat->checksum->length - 24;
+
+	   if (i >= 4) {
+
+	       TREAD_INT16(ptr, option_id, bigend);
+
+	       TREAD_INT16(ptr, option.length, bigend);
+
+	       i -= 4;
+
+	       if (i < option.length || option.length < 0) {
+		   code = KG_BAD_LENGTH;
+		   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 */
+
+	       TREAD_STR(ptr, ptr2, option.length);
+	       option.data = (char *) ptr2;
+
+	       i -= option.length;
+
+	       if (option_id != KRB5_GSS_FOR_CREDS_OPTION) {
+		   major_status = GSS_S_FAILURE;
+		   goto fail;
+	       }
+
+		   /* store the delegated credential */
+
+		   code = rd_and_store_for_creds(context, auth_context, &option,
+						 (delegated_cred_handle) ?
+						 &deleg_cred : NULL);
+		   if (code) {
+		       major_status = GSS_S_FAILURE;
+		       goto fail;
+		   }
+
+	   } /* if i >= 4 */
+	   /* ignore any additional trailing data, for now */
+#ifdef CFX_EXERCISE
+	   {
+	       FILE *f = fopen("/tmp/gsslog", "a");
+	       if (f) {
+		   fprintf(f,
+			   "initial context token with delegation, %d extra bytes\n",
+			   i);
+		   fclose(f);
+	       }
+	   }
+#endif
+       } else {
+#ifdef CFX_EXERCISE
+	   {
+	       FILE *f = fopen("/tmp/gsslog", "a");
+	       if (f) {
+		   if (gss_flags & GSS_C_DELEG_FLAG)
+		       fprintf(f,
+			       "initial context token, delegation flag but too small\n");
+		   else
+		       /* no deleg flag, length might still be too big */
+		       fprintf(f,
+			       "initial context token, %d extra bytes\n",
+			       authdat->checksum->length - 24);
+		   fclose(f);
+	       }
+	   }
+#endif
+       }
+   }
+
+   /* create the ctx struct and start filling it in */
+
+   if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
+       == NULL) {
+       code = ENOMEM;
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
+
+   memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+   ctx->mech_used = (gss_OID) mech_used;
+   ctx->auth_context = auth_context;
+   ctx->initiate = 0;
+   ctx->gss_flags = (GSS_C_TRANS_FLAG |
+                    ((gss_flags) & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
+                            GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
+                            GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)));
+   ctx->seed_init = 0;
+   ctx->big_endian = bigend;
+   ctx->cred_rcache = cred_rcache;
+
+   /* Intern the ctx pointer so that delete_sec_context works */
+   if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
+       xfree(ctx);
+       ctx = 0;
+
+       code = G_VALIDATE_FAILED;
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
+
+   if ((code = krb5_copy_principal(context, ticket->server, &ctx->here))) {
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
+
+   if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) {
+       major_status = GSS_S_FAILURE;
+       goto fail;
+   }
+
+   if ((code = krb5_auth_con_getrecvsubkey(context, auth_context,
+					   &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))) {
+	   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;
+   }
+
+   ctx->proto = 0;
+   switch(ctx->subkey->enctype) {
+   case ENCTYPE_DES_CBC_MD5:
+   case ENCTYPE_DES_CBC_CRC:
+       ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
+       ctx->signalg = SGN_ALG_DES_MAC_MD5;
+       ctx->cksum_size = 8;
+       ctx->sealalg = SEAL_ALG_DES;
+
+       /* fill in the encryption descriptors */
+
+       if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
+	   major_status = GSS_S_FAILURE;
+	   goto fail;
+       }
+
+       for (i=0; i<ctx->enc->length; i++)
+	   /*SUPPRESS 113*/
+	   ctx->enc->contents[i] ^= 0xf0;
+
+       goto copy_subkey_to_seq;
+
+   case ENCTYPE_DES3_CBC_SHA1:
+       ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
+       ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
+       ctx->cksum_size = 20;
+       ctx->sealalg = SEAL_ALG_DES3KD;
+
+       /* fill in the encryption descriptors */
+   copy_subkey:
+       if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
+	   major_status = GSS_S_FAILURE;
+	   goto fail;
+       }
+   copy_subkey_to_seq:
+       if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
+	   major_status = GSS_S_FAILURE;
+	   goto fail;
+       }
+       break;
+
+   case ENCTYPE_ARCFOUR_HMAC:
+       ctx->signalg = SGN_ALG_HMAC_MD5 ;
+       ctx->cksum_size = 8;
+       ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
+       goto copy_subkey;
+
+   default:
+       ctx->signalg = -1;
+       ctx->sealalg = -1;
+       ctx->proto = 1;
+       code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, ctx->subkey->enctype,
+					    &ctx->cksumtype);
+       if (code)
+	   goto fail;
+       code = krb5_c_checksum_length(context, ctx->cksumtype,
+				     &ctx->cksum_size);
+       if (code)
+	   goto fail;
+       ctx->have_acceptor_subkey = 0;
+       goto copy_subkey;
+   }
+
+   ctx->endtime = ticket->enc_part2->times.endtime;
+   ctx->krb_flags = ticket->enc_part2->flags;
+
+   krb5_free_ticket(context, ticket); /* Done with ticket */
+
+   {
+       krb5_ui_4 seq_temp;
+       krb5_auth_con_getremoteseqnumber(context, auth_context, &seq_temp);
+       ctx->seq_recv = seq_temp;
+   }
+
+   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;
+   }
+
+   g_order_init(&(ctx->seqstate), ctx->seq_recv,
+		(ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
+		(ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
+
+   /* at this point, the entire context structure is filled in, 
+      so it can be released.  */
+
+   /* generate an AP_REP if necessary */
+
+   if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
+       unsigned char * ptr3;
+       krb5_ui_4 seq_temp;
+       int cfx_generate_subkey;
+
+       if (ctx->proto == 1)
+	   cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY;
+       else
+	   cfx_generate_subkey = 0;
+
+       if (cfx_generate_subkey) {
+	   krb5_int32 acflags;
+	   code = krb5_auth_con_getflags(context, auth_context, &acflags);
+	   if (code == 0) {
+	       acflags |= KRB5_AUTH_CONTEXT_USE_SUBKEY;
+	       code = krb5_auth_con_setflags(context, auth_context, acflags);
+	   }
+	   if (code) {
+	       major_status = GSS_S_FAILURE;
+	       goto fail;
+	   }
+       }
+
+       if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
+	   major_status = GSS_S_FAILURE;
+	   goto fail;
+       }
+
+       krb5_auth_con_getlocalseqnumber(context, auth_context, &seq_temp);
+       ctx->seq_send = seq_temp & 0xffffffffL;
+
+       if (cfx_generate_subkey) {
+	   /* Get the new acceptor subkey.  With the code above, there
+	      should always be one if we make it to this point.  */
+	   code = krb5_auth_con_getsendsubkey(context, auth_context,
+					      &ctx->acceptor_subkey);
+	   if (code != 0) {
+	       major_status = GSS_S_FAILURE;
+	       goto fail;
+	   }
+	   code = (*kaccess.krb5int_c_mandatory_cksumtype)(context,
+						ctx->acceptor_subkey->enctype,
+						&ctx->acceptor_subkey_cksumtype);
+	   if (code) {
+	       major_status = GSS_S_FAILURE;
+	       goto fail;
+	   }
+	   ctx->have_acceptor_subkey = 1;
+       }
+
+       /* the reply token hasn't been sent yet, but that's ok. */
+       ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
+       ctx->established = 1;
+
+       token.length = g_token_size(mech_used, ap_rep.length);
+
+       if ((token.value = (unsigned char *) xmalloc(token.length))
+	   == NULL) {
+	   major_status = GSS_S_FAILURE;
+	   code = ENOMEM;
+	   goto fail;
+       }
+       ptr3 = token.value;
+       g_make_token_header(mech_used, ap_rep.length,
+			   &ptr3, KG_TOK_CTX_AP_REP);
+
+       TWRITE_STR(ptr3, ap_rep.data, ap_rep.length);
+
+       ctx->established = 1;
+
+   } else {
+       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))) {
+	   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)
+      *mech_type = (gss_OID) mech_used;
+
+   if (time_rec)
+      *time_rec = ctx->endtime - now;
+
+   if (ret_flags)
+      *ret_flags = ctx->gss_flags;
+
+   *context_handle = (gss_ctx_id_t)ctx;
+   *output_token = token;
+
+   if (src_name)
+      *src_name = (gss_name_t) name;
+
+   if (delegated_cred_handle && deleg_cred) {
+       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;
+   }
+
+   /* finally! */
+
+   *minor_status = 0;
+   major_status = GSS_S_COMPLETE;
+
+ fail:
+   if (authdat)
+       krb5_free_authenticator(context, authdat);
+   /* The ctx structure has the handle of the auth_context */
+   if (auth_context && !ctx) {
+       if (cred_rcache)
+	   (void)krb5_auth_con_setrcache(context, auth_context, NULL);
+
+       krb5_auth_con_free(context, auth_context);
+   }
+   if (reqcksum.contents)
+       xfree(reqcksum.contents);
+   if (ap_rep.data)
+       krb5_free_data_contents(context, &ap_rep);
+
+   if (!GSS_ERROR(major_status) && major_status != GSS_S_CONTINUE_NEEDED) {
+       ctx->k5_context = context;
+       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);
+   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);
+   if (name) {
+       (void) kg_delete_name((gss_name_t) name);
+       krb5_free_principal(context, name);
+   }
+
+   *minor_status = code;
+
+   /*
+    * If decode_req_message is set, then we need to decode the ap_req
+    * message to determine whether or not to send a response token.
+    * We need to do this because for some errors we won't be able to
+    * decode the authenticator to read out the gss_flags field.
+    */
+   if (decode_req_message) {
+       krb5_ap_req 	* request;
+	   
+       if (decode_krb5_ap_req(&ap_req, &request)) {
+	   krb5_free_context(context);
+	   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)
+	   || (major_status == GSS_S_CONTINUE_NEEDED))) {
+       unsigned int tmsglen;
+       int 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) {
+	   krb5_free_context(context);
+	   return (major_status);
+       }
+
+       tmsglen = scratch.length;
+       toktype = KG_TOK_CTX_ERROR;
+
+       token.length = g_token_size(mech_used, tmsglen);
+       token.value = (unsigned char *) xmalloc(token.length);
+       if (!token.value) {
+	   krb5_free_context(context);
+	   return (major_status);
+       }
+
+       ptr = token.value;
+       g_make_token_header(mech_used, tmsglen, &ptr, toktype);
+
+       TWRITE_STR(ptr, scratch.data, scratch.length);
+       krb5_free_data_contents(context, &scratch);
+
+       *output_token = token;
+   }
+   if (!verifier_cred_handle && cred_handle) {
+	   krb5_gss_release_cred(minor_status, &cred_handle);
+   }
+   krb5_free_context(context);
+   return (major_status);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/acquire_cred.c b/krb5-1-6/src/lib/gssapi/krb5/acquire_cred.c
new file mode 100644
index 000000000..169889ee3
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/acquire_cred.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright 2000 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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 "gss_libinit.h"
+#include "gssapiP_krb5.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#if defined(USE_LOGIN_LIBRARY)
+#include <Kerberos/KerberosLoginPrivate.h>
+#elif defined(USE_LEASH)
+#ifdef _WIN64
+#define LEASH_DLL "leashw64.dll"
+#else
+#define LEASH_DLL "leashw32.dll"
+#endif
+static void (*pLeash_AcquireInitialTicketsIfNeeded)(krb5_context,krb5_principal,char*,int) = NULL;
+static HANDLE hLeashDLL = INVALID_HANDLE_VALUE;
+#endif
+
+k5_mutex_t gssint_krb5_keytab_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+static char *krb5_gss_keytab = NULL;
+
+/* Heimdal calls this gsskrb5_register_acceptor_identity. */
+OM_uint32 KRB5_CALLCONV
+krb5_gss_register_acceptor_identity(const char *keytab)
+{
+    size_t	len;
+    char *new, *old;
+    int err;
+
+    err = gssint_initialize_library();
+    if (err != 0)
+	return GSS_S_FAILURE;
+
+    if (keytab == NULL)
+	return GSS_S_FAILURE;
+
+    len = strlen(keytab);
+    new = malloc(len + 1);
+    if (new == NULL)
+	return GSS_S_FAILURE;
+    strcpy(new, keytab);
+
+    err = k5_mutex_lock(&gssint_krb5_keytab_lock);
+    if (err) {
+	free(new);
+	return GSS_S_FAILURE;
+    }
+    old = krb5_gss_keytab;
+    krb5_gss_keytab = new;
+    k5_mutex_unlock(&gssint_krb5_keytab_lock);
+    if (old != NULL)
+	free(old);
+    return GSS_S_COMPLETE;
+}
+
+/* get credentials corresponding to a key in the krb5 keytab.
+   If the default name is requested, return the name in output_princ.
+     If output_princ is non-NULL, the caller will use or free it, regardless
+     of the return value.
+   If successful, set the keytab-specific fields in cred
+   */
+
+static OM_uint32 
+acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
+     krb5_context context;
+     OM_uint32 *minor_status;
+     gss_name_t desired_name;
+     krb5_principal *output_princ;
+     krb5_gss_cred_id_rec *cred;
+{
+   krb5_error_code code;
+   krb5_principal princ;
+   krb5_keytab kt;
+   krb5_keytab_entry entry;
+
+   *output_princ = NULL;
+   cred->keytab = NULL;
+
+   /* open the default keytab */
+
+   code = gssint_initialize_library();
+   if (code != 0) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+   code = k5_mutex_lock(&gssint_krb5_keytab_lock);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+   if (krb5_gss_keytab != NULL) {
+      code = krb5_kt_resolve(context, krb5_gss_keytab, &kt);
+      k5_mutex_unlock(&gssint_krb5_keytab_lock);
+   } else {
+      k5_mutex_unlock(&gssint_krb5_keytab_lock);
+      code = krb5_kt_default(context, &kt);
+   }
+
+   if (code) {
+      *minor_status = code;
+      return(GSS_S_CRED_UNAVAIL);
+   }
+
+   if (desired_name != GSS_C_NO_NAME) {
+      princ = (krb5_principal) desired_name;
+      if ((code = krb5_kt_get_entry(context, kt, princ, 0, 0, &entry))) {
+	 (void) krb5_kt_close(context, kt);
+	 if (code == KRB5_KT_NOTFOUND)
+	    *minor_status = KG_KEYTAB_NOMATCH;
+	 else
+	    *minor_status = code;
+	 return(GSS_S_CRED_UNAVAIL);
+      }
+      krb5_kt_free_entry(context, &entry);
+
+      /* Open the replay cache for this principal. */
+      if ((code = krb5_get_server_rcache(context,
+					 krb5_princ_component(context, princ, 0),
+					 &cred->rcache))) {
+	 *minor_status = code;
+	 return(GSS_S_FAILURE);
+      }
+
+   }
+
+/* hooray.  we made it */
+
+   cred->keytab = kt;
+
+   return(GSS_S_COMPLETE);
+}
+
+/* get credentials corresponding to the default credential cache.
+   If the default name is requested, return the name in output_princ.
+     If output_princ is non-NULL, the caller will use or free it, regardless
+     of the return value.
+   If successful, set the ccache-specific fields in cred.
+   */
+
+static OM_uint32 
+acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
+     krb5_context context;
+     OM_uint32 *minor_status;
+     gss_name_t desired_name;
+     krb5_principal *output_princ;
+     krb5_gss_cred_id_rec *cred;
+{
+   krb5_error_code code;
+   krb5_ccache ccache;
+   krb5_principal princ, tmp_princ;
+   krb5_flags flags;
+   krb5_cc_cursor cur;
+   krb5_creds creds;
+   int got_endtime;
+   int caller_provided_ccache_name = 0;
+
+   cred->ccache = NULL;
+
+   /* load the GSS ccache name into the kg_context */
+   
+   if (GSS_ERROR(kg_sync_ccache_name(context, minor_status)))
+       return(GSS_S_FAILURE);
+
+   /* check to see if the caller provided a ccache name if so 
+    * we will just use that and not search the cache collection */
+   if (GSS_ERROR(kg_caller_provided_ccache_name (minor_status, &caller_provided_ccache_name))) {
+       return(GSS_S_FAILURE);
+   }
+
+#if defined(USE_LOGIN_LIBRARY) || defined(USE_LEASH)
+   if (desired_name && !caller_provided_ccache_name) {
+#if defined(USE_LOGIN_LIBRARY)
+       KLStatus err = klNoErr;
+       char *ccache_name = NULL;
+       KLPrincipal kl_desired_princ = NULL;
+
+       err = __KLCreatePrincipalFromKerberos5Principal ((krb5_principal) desired_name,
+                                                        &kl_desired_princ);
+       
+       if (!err) {
+           err = KLAcquireInitialTickets (kl_desired_princ, NULL, NULL, &ccache_name);
+       }
+
+       if (!err) {
+           err = krb5_cc_resolve (context, ccache_name, &ccache);
+       }
+       
+       if (err) {
+           *minor_status = err;
+           return(GSS_S_CRED_UNAVAIL);
+       }
+       
+       if (kl_desired_princ != NULL) { KLDisposePrincipal (kl_desired_princ); }
+       if (ccache_name      != NULL) { KLDisposeString (ccache_name); }
+       
+#elif defined(USE_LEASH)
+       if ( hLeashDLL == INVALID_HANDLE_VALUE ) {
+	   hLeashDLL = LoadLibrary(LEASH_DLL);
+	   if ( hLeashDLL != INVALID_HANDLE_VALUE ) {
+	       (FARPROC) pLeash_AcquireInitialTicketsIfNeeded =
+		   GetProcAddress(hLeashDLL, "not_an_API_Leash_AcquireInitialTicketsIfNeeded");
+	   }
+       }
+    
+       if ( pLeash_AcquireInitialTicketsIfNeeded ) {
+	   char ccname[256]="";
+	   pLeash_AcquireInitialTicketsIfNeeded(context, (krb5_principal) desired_name, ccname, sizeof(ccname));
+	   if (!ccname[0]) {
+	       *minor_status = KRB5_CC_NOTFOUND;
+	       return(GSS_S_CRED_UNAVAIL);
+	   }
+
+	   if ((code = krb5_cc_resolve (context, ccname, &ccache))) {
+	       *minor_status = code;
+	       return(GSS_S_CRED_UNAVAIL);
+	   }
+       } else {
+	   /* leash dll not available, open the default credential cache */
+   
+	   if ((code = krb5int_cc_default(context, &ccache))) {
+	       *minor_status = code;
+	       return(GSS_S_CRED_UNAVAIL);
+	   }
+       }
+#endif /* USE_LEASH */
+   } else
+#endif /* USE_LOGIN_LIBRARY || USE_LEASH */
+   {
+       /* open the default credential cache */
+   
+       if ((code = krb5int_cc_default(context, &ccache))) {
+	   *minor_status = code;
+	   return(GSS_S_CRED_UNAVAIL);
+       }
+   }
+
+   /* turn off OPENCLOSE mode while extensive frobbing is going on */
+
+   flags = 0;		/* turns off OPENCLOSE mode */
+   if ((code = krb5_cc_set_flags(context, ccache, flags))) {
+      (void)krb5_cc_close(context, ccache);
+      *minor_status = code;
+      return(GSS_S_CRED_UNAVAIL);
+   }
+
+   /* get out the principal name and see if it matches */
+
+   if ((code = krb5_cc_get_principal(context, ccache, &princ))) {
+      (void)krb5_cc_close(context, ccache);
+      *minor_status = code;
+      return(GSS_S_FAILURE);
+   }
+
+   if (desired_name != (gss_name_t) NULL) {
+      if (! krb5_principal_compare(context, princ, (krb5_principal) desired_name)) {
+	 (void)krb5_free_principal(context, princ);
+	 (void)krb5_cc_close(context, ccache);
+	 *minor_status = KG_CCACHE_NOMATCH;
+	 return(GSS_S_CRED_UNAVAIL);
+      }
+      (void)krb5_free_principal(context, princ);
+      princ = (krb5_principal) desired_name;
+   } else {
+      *output_princ = princ;
+   }
+
+   /* iterate over the ccache, find the tgt */
+
+   if ((code = krb5_cc_start_seq_get(context, ccache, &cur))) {
+      (void)krb5_cc_close(context, ccache);
+      *minor_status = code;
+      return(GSS_S_FAILURE);
+   }
+
+   /* this is hairy.  If there's a tgt for the principal's local realm
+      in here, that's what we want for the expire time.  But if
+      there's not, then we want to use the first key.  */
+
+   got_endtime = 0;
+
+   code = krb5_build_principal_ext(context, &tmp_princ,
+				   krb5_princ_realm(context, princ)->length,
+				   krb5_princ_realm(context, princ)->data,
+				   6, "krbtgt",
+				   krb5_princ_realm(context, princ)->length,
+				   krb5_princ_realm(context, princ)->data,
+				   0);
+   if (code) {
+      (void)krb5_cc_close(context, ccache);
+      *minor_status = code;
+      return(GSS_S_FAILURE);
+   }
+   while (!(code = krb5_cc_next_cred(context, ccache, &cur, &creds))) {
+      if (krb5_principal_compare(context, tmp_princ, creds.server)) {
+	 cred->tgt_expire = creds.times.endtime;
+	 got_endtime = 1;
+	 *minor_status = 0;
+	 code = 0;
+	 krb5_free_cred_contents(context, &creds);
+	 break;
+      }
+      if (got_endtime == 0) {
+	 cred->tgt_expire = creds.times.endtime;
+	 got_endtime = 1;
+      }
+      krb5_free_cred_contents(context, &creds);
+   }
+   krb5_free_principal(context, tmp_princ);
+
+   if (code && code != KRB5_CC_END) {
+      /* this means some error occurred reading the ccache */
+      (void)krb5_cc_end_seq_get(context, ccache, &cur);
+      (void)krb5_cc_close(context, ccache);
+      *minor_status = code;
+      return(GSS_S_FAILURE);
+   } else if (! got_endtime) {
+      /* this means the ccache was entirely empty */
+      (void)krb5_cc_end_seq_get(context, ccache, &cur);
+      (void)krb5_cc_close(context, ccache);
+      *minor_status = KG_EMPTY_CCACHE;
+      return(GSS_S_FAILURE);
+   } else {
+      /* this means that we found an endtime to use. */
+      if ((code = krb5_cc_end_seq_get(context, ccache, &cur))) {
+	 (void)krb5_cc_close(context, ccache);
+	 *minor_status = code;
+	 return(GSS_S_FAILURE);
+      }
+      flags = KRB5_TC_OPENCLOSE;	/* turns on OPENCLOSE mode */
+      if ((code = krb5_cc_set_flags(context, ccache, flags))) {
+	 (void)krb5_cc_close(context, ccache);
+	 *minor_status = code;
+	 return(GSS_S_FAILURE);
+      }
+   }
+
+   /* the credentials match and are valid */
+
+   cred->ccache = ccache;
+   /* minor_status is set while we are iterating over the ccache */
+   return(GSS_S_COMPLETE);
+}
+   
+/*ARGSUSED*/
+OM_uint32
+krb5_gss_acquire_cred(minor_status, desired_name, time_req,
+		      desired_mechs, cred_usage, output_cred_handle,
+		      actual_mechs, time_rec)
+     OM_uint32 *minor_status;
+     gss_name_t desired_name;
+     OM_uint32 time_req;
+     gss_OID_set desired_mechs;
+     gss_cred_usage_t cred_usage;
+     gss_cred_id_t *output_cred_handle;
+     gss_OID_set *actual_mechs;
+     OM_uint32 *time_rec;
+{
+   krb5_context context;
+   size_t i;
+   krb5_gss_cred_id_t cred;
+   gss_OID_set ret_mechs;
+   int req_old, req_new;
+   OM_uint32 ret;
+   krb5_error_code code;
+
+   code = gssint_initialize_library();
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   /* make sure all outputs are valid */
+
+   *output_cred_handle = NULL;
+   if (actual_mechs)
+      *actual_mechs = NULL;
+   if (time_rec)
+      *time_rec = 0;
+
+   /* validate the name */
+
+   /*SUPPRESS 29*/
+   if ((desired_name != (gss_name_t) NULL) &&
+       (! kg_validate_name(desired_name))) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      krb5_free_context(context);
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   }
+
+   /* verify that the requested mechanism set is the default, or
+      contains krb5 */
+
+   if (desired_mechs == GSS_C_NULL_OID_SET) {
+      req_old = 1;
+      req_new = 1;
+   } else {
+      req_old = 0;
+      req_new = 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 (!req_old && !req_new) {
+	 *minor_status = 0;
+	 krb5_free_context(context);
+	 return(GSS_S_BAD_MECH);
+      }
+   }
+
+   /* create the gss cred structure */
+
+   if ((cred =
+	(krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec))) == NULL) {
+      *minor_status = ENOMEM;
+      krb5_free_context(context);
+      return(GSS_S_FAILURE);
+   }
+   memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
+
+   cred->usage = cred_usage;
+   cred->princ = NULL;
+   cred->prerfc_mech = req_old;
+   cred->rfc_mech = req_new;
+
+   cred->keytab = NULL;
+   cred->ccache = NULL;
+
+   code = k5_mutex_init(&cred->lock);
+   if (code) {
+       *minor_status = code;
+       krb5_free_context(context);
+       return GSS_S_FAILURE;
+   }
+   /* Note that we don't need to lock this GSSAPI credential record
+      here, because no other thread can gain access to it until we
+      return it.  */
+
+   if ((cred_usage != GSS_C_INITIATE) &&
+       (cred_usage != GSS_C_ACCEPT) &&
+       (cred_usage != GSS_C_BOTH)) {
+      k5_mutex_destroy(&cred->lock);
+      xfree(cred);
+      *minor_status = (OM_uint32) G_BAD_USAGE;
+      krb5_free_context(context);
+      return(GSS_S_FAILURE);
+   }
+
+   /* if requested, acquire credentials for accepting */
+   /* this will fill in cred->princ if the desired_name is not specified */
+
+   if ((cred_usage == GSS_C_ACCEPT) ||
+       (cred_usage == GSS_C_BOTH))
+      if ((ret = acquire_accept_cred(context, minor_status, desired_name,
+				     &(cred->princ), cred))
+	  != GSS_S_COMPLETE) {
+	 if (cred->princ)
+	    krb5_free_principal(context, cred->princ);
+         k5_mutex_destroy(&cred->lock);
+         xfree(cred);
+	 /* minor_status set by acquire_accept_cred() */
+	 krb5_free_context(context);
+	 return(ret);
+      }
+
+   /* if requested, acquire credentials for initiation */
+   /* this will fill in cred->princ if it wasn't set above, and
+      the desired_name is not specified */
+
+   if ((cred_usage == GSS_C_INITIATE) ||
+       (cred_usage == GSS_C_BOTH))
+      if ((ret =
+	   acquire_init_cred(context, minor_status,
+			     cred->princ?(gss_name_t)cred->princ:desired_name,
+			     &(cred->princ), cred))
+	  != GSS_S_COMPLETE) {
+	 if (cred->keytab)
+	    krb5_kt_close(context, cred->keytab);
+	 if (cred->princ)
+	    krb5_free_principal(context, cred->princ);
+         k5_mutex_destroy(&cred->lock);
+         xfree(cred);
+	 /* minor_status set by acquire_init_cred() */
+	 krb5_free_context(context);
+	 return(ret);
+      }
+
+   /* if the princ wasn't filled in already, fill it in now */
+
+   if (!cred->princ && (desired_name != GSS_C_NO_CREDENTIAL))
+      if ((code = krb5_copy_principal(context, (krb5_principal) desired_name,
+				      &(cred->princ)))) {
+	 if (cred->ccache)
+	    (void)krb5_cc_close(context, cred->ccache);
+	 if (cred->keytab)
+	    (void)krb5_kt_close(context, cred->keytab);
+         k5_mutex_destroy(&cred->lock);
+         xfree(cred);
+	 *minor_status = code;
+	 krb5_free_context(context);
+	 return(GSS_S_FAILURE);
+      }
+
+   /*** at this point, the cred structure has been completely created */
+
+   /* compute time_rec */
+
+   if (cred_usage == GSS_C_ACCEPT) {
+      if (time_rec)
+	 *time_rec = GSS_C_INDEFINITE;
+   } else {
+      krb5_timestamp now;
+
+      if ((code = krb5_timeofday(context, &now))) {
+	 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);
+         k5_mutex_destroy(&cred->lock);
+         xfree(cred);
+	 *minor_status = code;
+	 krb5_free_context(context);
+	 return(GSS_S_FAILURE);
+      }
+
+      if (time_rec)
+	 *time_rec = (cred->tgt_expire > now) ? (cred->tgt_expire - now) : 0;
+   }
+
+   /* create mechs */
+
+   if (actual_mechs) {
+       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)))) {
+	   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);
+           k5_mutex_destroy(&cred->lock);
+	   xfree(cred);
+	   /* *minor_status set above */
+	   krb5_free_context(context);
+	   return(ret);
+       }
+   }
+
+   /* intern the credential handle */
+
+   if (! kg_save_cred_id((gss_cred_id_t) cred)) {
+      free(ret_mechs->elements);
+      free(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);
+      k5_mutex_destroy(&cred->lock);
+      xfree(cred);
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      krb5_free_context(context);
+      return(GSS_S_FAILURE);
+   }
+
+   /* return success */
+
+   *minor_status = 0;
+   *output_cred_handle = (gss_cred_id_t) cred;
+   if (actual_mechs)
+      *actual_mechs = ret_mechs;
+
+   krb5_free_context(context);
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/add_cred.c b/krb5-1-6/src/lib/gssapi/krb5/add_cred.c
new file mode 100644
index 000000000..225f125d2
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/add_cred.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2000 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright (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) &&
+	!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);
+    }
+
+    code = krb5_gss_init_context(&context);
+    if (code) {
+	*minor_status = code;
+	return GSS_S_FAILURE;
+    }
+
+    major_status = krb5_gss_validate_cred_1(minor_status, input_cred_handle,
+					    context);
+    if (GSS_ERROR(major_status)) {
+	krb5_free_context(context);
+	return major_status;
+    }
+
+    cred = (krb5_gss_cred_id_t) input_cred_handle;
+    k5_mutex_assert_locked(&cred->lock);
+
+    /* 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;
+      krb5_free_context(context);
+      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)) {
+	*minor_status = 0;
+	krb5_free_context(context);
+	return(GSS_S_DUPLICATE_ELEMENT);
+    }
+
+    if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) {
+	krb5_free_context(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;
+	krb5_free_context(context);
+	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;
+	krb5_free_context(context);
+	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];
+	const char *cctype, *ccname;
+	char ccboth[1024];
+
+	if ((new_cred =
+	     (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))
+	    == NULL) {
+	    *minor_status = ENOMEM;
+	    krb5_free_context(context);
+	    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->tgt_expire = cred->tgt_expire;
+
+	if (cred->princ)
+	    code = krb5_copy_principal(context, cred->princ, &new_cred->princ);
+	if (code) {
+	    xfree(new_cred);
+
+	    *minor_status = code;
+	    krb5_free_context(context);
+	    return(GSS_S_FAILURE);
+	}
+	    
+	if (cred->keytab) {
+	    kttype = krb5_kt_get_type(context, cred->keytab);
+	    if ((strlen(kttype)+2) > sizeof(ktboth)) {
+		if (new_cred->princ)
+		    krb5_free_principal(context, new_cred->princ);
+		xfree(new_cred);
+
+		*minor_status = ENOMEM;
+		krb5_free_context(context);
+		return(GSS_S_FAILURE);
+	    }
+
+	    strncpy(ktboth, kttype, sizeof(ktboth) - 1);
+	    ktboth[sizeof(ktboth) - 1] = '\0';
+	    strncat(ktboth, ":", sizeof(ktboth) - 1 - strlen(ktboth));
+
+	    code = krb5_kt_get_name(context, cred->keytab, 
+				    ktboth+strlen(ktboth),
+				    sizeof(ktboth)-strlen(ktboth));
+	    if (code) {
+		if(new_cred->princ)
+		    krb5_free_principal(context, new_cred->princ);
+		xfree(new_cred);
+
+		*minor_status = code;
+		krb5_free_context(context);
+		return(GSS_S_FAILURE);
+	    }
+
+	    code = krb5_kt_resolve(context, ktboth, &new_cred->keytab);
+	    if (code) {
+		if (new_cred->princ)
+		krb5_free_principal(context, new_cred->princ);
+		xfree(new_cred);
+
+		*minor_status = code;
+		krb5_free_context(context);
+		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);
+		if (new_cred->princ)
+		    krb5_free_principal(context, new_cred->princ);
+		xfree(new_cred);
+
+		krb5_free_context(context);
+		*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);
+		if (new_cred->princ)
+		krb5_free_principal(context, new_cred->princ);
+		xfree(new_cred);
+
+		krb5_free_context(context);
+		*minor_status = ENOMEM;
+		return(GSS_S_FAILURE);
+	    }
+
+	    strncpy(ccboth, cctype, sizeof(ccboth) - 1);
+	    ccboth[sizeof(ccboth) - 1] = '\0';
+	    strncat(ccboth, ":", sizeof(ccboth) - 1 - strlen(ccboth));
+	    strncat(ccboth, ccname, sizeof(ccboth) - 1 - strlen(ccboth));
+
+	    code = krb5_cc_resolve(context, ccboth, &new_cred->ccache);
+	    if (code) {
+		if (new_cred->rcache)
+		    krb5_rc_close(context, new_cred->rcache);
+		if (new_cred->keytab)
+		    krb5_kt_close(context, new_cred->keytab);
+		if (new_cred->princ)
+		    krb5_free_principal(context, new_cred->princ);
+		xfree(new_cred);
+		krb5_free_context(context);
+
+		*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);
+	    if (new_cred->princ)
+	    krb5_free_principal(context, new_cred->princ);
+	    xfree(new_cred);
+	    krb5_free_context(context);
+
+	    *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;
+
+    /* set the outputs */
+
+    if (GSS_ERROR(major_status = krb5_gss_inquire_cred(minor_status, 
+						       (gss_cred_id_t)cred,
+						       NULL, &lifetime,
+						       NULL, actual_mechs))) {
+	OM_uint32 dummy;
+	
+	if (output_cred_handle)
+	    (void) krb5_gss_release_cred(&dummy, (gss_cred_id_t *) &cred);
+	krb5_free_context(context);
+
+	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 = (gss_cred_id_t)cred;
+
+    krb5_free_context(context);
+    *minor_status = 0;
+    return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/canon_name.c b/krb5-1-6/src/lib/gssapi/krb5/canon_name.c
new file mode 100644
index 000000000..0f7c9cd9c
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/canon_name.c
@@ -0,0 +1,45 @@
+/*
+ * lib/gssapi/krb5/canon_name.c
+ *
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "gssapiP_krb5.h"
+
+/* This is trivial since we're a single mechanism implementation */
+
+OM_uint32 krb5_gss_canonicalize_name(OM_uint32  *minor_status,
+				     const gss_name_t input_name,
+				     const gss_OID mech_type,
+				     gss_name_t *output_name)
+{
+    if ((mech_type != GSS_C_NULL_OID) &&
+	!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/krb5-1-6/src/lib/gssapi/krb5/compare_name.c b/krb5-1-6/src/lib/gssapi/krb5/compare_name.c
new file mode 100644
index 000000000..805f9f1d7
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/compare_name.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32
+krb5_gss_compare_name(minor_status, name1, name2, name_equal)
+     OM_uint32 *minor_status;
+     gss_name_t name1;
+     gss_name_t name2;
+     int *name_equal;
+{ 
+   krb5_context context;
+   krb5_error_code code;
+
+   if (! kg_validate_name(name1)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   }
+
+   if (! kg_validate_name(name2)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   }
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   *minor_status = 0;
+   *name_equal = krb5_principal_compare(context, (krb5_principal) name1,
+					(krb5_principal) name2);
+   krb5_free_context(context);
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/context_time.c b/krb5-1-6/src/lib/gssapi/krb5/context_time.c
new file mode 100644
index 000000000..8b7930ffd
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/context_time.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32
+krb5_gss_context_time(minor_status, context_handle, time_rec)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     OM_uint32 *time_rec;
+{
+   krb5_error_code code;
+   krb5_gss_ctx_id_rec *ctx;
+   krb5_timestamp now;
+   krb5_deltat lifetime;
+
+   /* 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);
+   }
+
+   if ((code = krb5_timeofday(ctx->k5_context, &now))) {
+      *minor_status = code;
+      return(GSS_S_FAILURE);
+   }
+
+   if ((lifetime = ctx->endtime - now) <= 0) {
+      *time_rec = 0;
+      *minor_status = 0;
+      return(GSS_S_CONTEXT_EXPIRED);
+   } else {
+      *time_rec = lifetime;
+      *minor_status = 0;
+      return(GSS_S_COMPLETE);
+   }
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/copy_ccache.c b/krb5-1-6/src/lib/gssapi/krb5/copy_ccache.c
new file mode 100644
index 000000000..195be0f84
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/copy_ccache.c
@@ -0,0 +1,59 @@
+#include "gssapiP_krb5.h"
+
+OM_uint32 KRB5_CALLCONV 
+gss_krb5int_copy_ccache(minor_status, cred_handle, out_ccache)
+     OM_uint32 *minor_status;
+     gss_cred_id_t cred_handle;
+     krb5_ccache out_ccache;
+{
+   OM_uint32 stat;
+   krb5_gss_cred_id_t k5creds;
+   krb5_cc_cursor cursor;
+   krb5_creds creds;
+   krb5_error_code code;
+   krb5_context context;
+
+   /* validate the cred handle */
+   stat = krb5_gss_validate_cred(minor_status, cred_handle);
+   if (stat)
+       return(stat);
+   
+   k5creds = (krb5_gss_cred_id_t) cred_handle;
+   code = k5_mutex_lock(&k5creds->lock);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+   if (k5creds->usage == GSS_C_ACCEPT) {
+       k5_mutex_unlock(&k5creds->lock);
+       *minor_status = (OM_uint32) G_BAD_USAGE;
+       return(GSS_S_FAILURE);
+   }
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       k5_mutex_unlock(&k5creds->lock);
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   code = krb5_cc_start_seq_get(context, k5creds->ccache, &cursor);
+   if (code) {
+       k5_mutex_unlock(&k5creds->lock);
+       *minor_status = code;
+       krb5_free_context(context);
+       return(GSS_S_FAILURE);
+   }
+   while (!code && !krb5_cc_next_cred(context, k5creds->ccache, &cursor, &creds)) 
+       code = krb5_cc_store_cred(context, out_ccache, &creds);
+   krb5_cc_end_seq_get(context, k5creds->ccache, &cursor);
+   k5_mutex_unlock(&k5creds->lock);
+   krb5_free_context(context);
+   if (code) {
+       *minor_status = code;
+       return(GSS_S_FAILURE);
+   } else {
+       *minor_status = 0;
+       return(GSS_S_COMPLETE);
+   }
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/delete_sec_context.c b/krb5-1-6/src/lib/gssapi/krb5/delete_sec_context.c
new file mode 100644
index 000000000..1bc6799e3
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/delete_sec_context.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32
+krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t *context_handle;
+     gss_buffer_t output_token;
+{
+   krb5_context context;
+   krb5_gss_ctx_id_rec *ctx;
+
+   if (output_token) {
+      output_token->length = 0;
+      output_token->value = NULL;
+   }
+
+   /*SUPPRESS 29*/
+   if (*context_handle == GSS_C_NO_CONTEXT) {
+      *minor_status = 0;
+      return(GSS_S_COMPLETE);
+   }
+
+   /*SUPPRESS 29*/
+   /* 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_t) *context_handle;
+   context = ctx->k5_context;
+
+   /* construct a delete context token if necessary */
+
+   if (output_token) {
+      OM_uint32 major;
+      gss_buffer_desc empty;
+      empty.length = 0; empty.value = NULL;
+
+      if ((major = kg_seal(minor_status, *context_handle, 0,
+			   GSS_C_QOP_DEFAULT,
+			   &empty, NULL, output_token, KG_TOK_DEL_CTX)))
+	 return(major);
+   }
+
+   /* invalidate the context handle */
+
+   (void)kg_delete_ctx_id(*context_handle);
+
+   /* free all the context state */
+
+   if (ctx->seqstate)
+      g_order_free(&(ctx->seqstate));
+
+   if (ctx->enc)
+      krb5_free_keyblock(context, ctx->enc);
+
+   if (ctx->seq)
+      krb5_free_keyblock(context, ctx->seq);
+
+   if (ctx->here)
+      krb5_free_principal(context, ctx->here);
+   if (ctx->there)
+      krb5_free_principal(context, ctx->there);
+   if (ctx->subkey)
+      krb5_free_keyblock(context, ctx->subkey);
+   if (ctx->acceptor_subkey)
+       krb5_free_keyblock(context, ctx->acceptor_subkey);
+
+   if (ctx->auth_context) {
+       if (ctx->cred_rcache)
+	   (void)krb5_auth_con_setrcache(context, ctx->auth_context, NULL);
+
+       krb5_auth_con_free(context, ctx->auth_context);
+   }
+
+   if (ctx->mech_used)
+       gss_release_oid(minor_status, &ctx->mech_used);
+   
+   if (ctx->k5_context)
+       krb5_free_context(ctx->k5_context);
+
+   /* Zero out context */
+   memset(ctx, 0, sizeof(*ctx));
+   xfree(ctx);
+
+   /* zero the handle itself */
+
+   *context_handle = GSS_C_NO_CONTEXT;
+
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/disp_name.c b/krb5-1-6/src/lib/gssapi/krb5/disp_name.c
new file mode 100644
index 000000000..5d3a042d4
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/disp_name.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32
+krb5_gss_display_name(minor_status, input_name, output_name_buffer, 
+		      output_name_type)
+     OM_uint32 *minor_status;
+     gss_name_t input_name;
+     gss_buffer_t output_name_buffer;
+     gss_OID *output_name_type;
+{
+   krb5_context context;
+   krb5_error_code code;
+   char *str;
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   output_name_buffer->length = 0;
+   output_name_buffer->value = NULL;
+
+   if (! kg_validate_name(input_name)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      krb5_free_context(context);
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   }
+
+   if ((code = krb5_unparse_name(context,
+				 (krb5_principal) input_name, &str))) {
+      *minor_status = code;
+      krb5_free_context(context);
+      return(GSS_S_FAILURE);
+   }
+
+   if (! g_make_string_buffer(str, output_name_buffer)) {
+      krb5_free_unparsed_name(context, str);
+      krb5_free_context(context);
+
+      *minor_status = (OM_uint32) G_BUFFER_ALLOC;
+      return(GSS_S_FAILURE);
+   }
+
+   krb5_free_unparsed_name(context, str);
+   krb5_free_context(context);
+
+   *minor_status = 0;
+   if (output_name_type)
+      *output_name_type = (gss_OID) gss_nt_krb5_name;
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/disp_status.c b/krb5-1-6/src/lib/gssapi/krb5/disp_status.c
new file mode 100644
index 000000000..1988d50c6
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/disp_status.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+#include "gss_libinit.h"
+#include "com_err.h"
+
+/* XXXX internationalization!! */
+
+/**/
+
+OM_uint32
+krb5_gss_display_status(minor_status, status_value, status_type,
+			mech_type, message_context, status_string)
+     OM_uint32 *minor_status;
+     OM_uint32 status_value;
+     int status_type;
+     gss_OID mech_type;
+     OM_uint32 *message_context;
+     gss_buffer_t status_string;
+{
+   status_string->length = 0;
+   status_string->value = NULL;
+
+   if ((mech_type != GSS_C_NULL_OID) &&
+       !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,
+				    message_context, status_string));
+   } else if (status_type == GSS_C_MECH_CODE) {
+      (void) gssint_initialize_library();
+
+      if (*message_context) {
+	 *minor_status = (OM_uint32) G_BAD_MSG_CTX;
+	 return(GSS_S_FAILURE);
+      }
+
+      return(g_display_com_err_status(minor_status, status_value,
+				      status_string));
+   } else {
+      *minor_status = 0;
+      return(GSS_S_BAD_STATUS);
+   }
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/duplicate_name.c b/krb5-1-6/src/lib/gssapi/krb5/duplicate_name.c
new file mode 100644
index 000000000..cb2ca71c7
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/duplicate_name.c
@@ -0,0 +1,79 @@
+/*
+ * lib/gssapi/krb5/duplicate_name.c
+ *
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32 krb5_gss_duplicate_name(OM_uint32  *minor_status,
+				  const gss_name_t input_name,
+				  gss_name_t *dest_name)
+{
+	krb5_context context;
+	krb5_error_code code;
+	krb5_principal princ, outprinc;
+
+	if (minor_status)
+	    *minor_status = 0;
+
+	code = krb5_gss_init_context(&context);
+	if (code) {
+	    if (minor_status)
+		*minor_status = code;
+	    return GSS_S_FAILURE;
+	}
+
+	if (! kg_validate_name(input_name)) {
+		if (minor_status)
+			*minor_status = (OM_uint32) G_VALIDATE_FAILED;
+		krb5_free_context(context);
+		return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+	}
+
+	princ = (krb5_principal)input_name;
+	if ((code = krb5_copy_principal(context, princ, &outprinc))) {
+		*minor_status = code;
+		krb5_free_context(context);
+		return(GSS_S_FAILURE);
+	}
+
+	if (! kg_save_name((gss_name_t) outprinc)) {
+		krb5_free_principal(context, outprinc);
+		krb5_free_context(context);
+		*minor_status = (OM_uint32) G_VALIDATE_FAILED;
+		return(GSS_S_FAILURE);
+	}
+	
+	krb5_free_context(context);
+	*dest_name = (gss_name_t) outprinc;
+	return(GSS_S_COMPLETE);
+	
+}
+
+
+
+
+
+
diff --git a/krb5-1-6/src/lib/gssapi/krb5/export_name.c b/krb5-1-6/src/lib/gssapi/krb5/export_name.c
new file mode 100644
index 000000000..ce19b04d8
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/export_name.c
@@ -0,0 +1,96 @@
+/*
+ * lib/gssapi/krb5/export_name.c
+ *
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32 krb5_gss_export_name(OM_uint32  *minor_status,
+			       const gss_name_t input_name,
+			       gss_buffer_t exported_name)
+{
+	krb5_context context;
+	krb5_error_code code;
+	size_t length;
+	char *str, *cp;
+
+	if (minor_status)
+		*minor_status = 0;
+
+	code = krb5_gss_init_context(&context);
+	if (code) {
+	    if (minor_status)
+		*minor_status = code;
+	    return GSS_S_FAILURE;
+	}
+
+	exported_name->length = 0;
+	exported_name->value = NULL;
+	
+	if (! kg_validate_name(input_name)) {
+		if (minor_status)
+			*minor_status = (OM_uint32) G_VALIDATE_FAILED;
+		krb5_free_context(context);
+		return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+	}
+
+	if ((code = krb5_unparse_name(context, (krb5_principal) input_name, 
+				      &str))) {
+		if (minor_status)
+			*minor_status = code;
+		krb5_free_context(context);
+		return(GSS_S_FAILURE);
+	}
+
+	krb5_free_context(context);
+	length = strlen(str);
+	exported_name->length = 10 + length + gss_mech_krb5->length;
+	exported_name->value = malloc(exported_name->length);
+	if (!exported_name->value) {
+		free(str);
+		if (minor_status)
+			*minor_status = ENOMEM;
+		return(GSS_S_FAILURE);
+	}
+	cp = exported_name->value;
+
+	/* Note: we assume the OID will be less than 128 bytes... */
+	*cp++ = 0x04; *cp++ = 0x01;
+	*cp++ = (gss_mech_krb5->length+2) >> 8;
+	*cp++ = (gss_mech_krb5->length+2) & 0xFF;
+	*cp++ = 0x06;
+	*cp++ = (gss_mech_krb5->length) & 0xFF;
+	memcpy(cp, gss_mech_krb5->elements, gss_mech_krb5->length);
+	cp += gss_mech_krb5->length;
+	*cp++ = length >> 24;
+	*cp++ = length >> 16;
+	*cp++ = length >> 8;
+	*cp++ = length & 0xFF;
+	memcpy(cp, str, length);
+
+	free(str);
+
+	return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/export_sec_context.c b/krb5-1-6/src/lib/gssapi/krb5/export_sec_context.c
new file mode 100644
index 000000000..fb57b882a
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/export_sec_context.c
@@ -0,0 +1,102 @@
+/*
+ * lib/gssapi/krb5/export_sec_context.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * export_sec_context.c	- Externalize the security context.
+ */
+#include "gssapiP_krb5.h"
+
+OM_uint32
+krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token)
+    OM_uint32		*minor_status;
+    gss_ctx_id_t	*context_handle;
+    gss_buffer_t	interprocess_token;
+{
+    krb5_context	context;
+    krb5_error_code	kret;
+    OM_uint32		retval;
+    size_t		bufsize, blen;
+    krb5_gss_ctx_id_t	ctx;
+    krb5_octet		*obuffer, *obp;
+
+    /* Assume a tragic failure */
+    obuffer = (krb5_octet *) NULL;
+    retval = GSS_S_FAILURE;
+    *minor_status = 0;
+
+    if (!kg_validate_ctx_id(*context_handle)) {
+	    kret = (OM_uint32) G_VALIDATE_FAILED;
+	    retval = GSS_S_NO_CONTEXT;
+	    goto error_out;
+    }
+
+    ctx = (krb5_gss_ctx_id_t) *context_handle;
+    context = ctx->k5_context;
+    kret = krb5_gss_ser_init(context);
+    if (kret)
+	goto error_out;
+
+    /* Determine size needed for externalization of context */
+    bufsize = 0;
+    if ((kret = kg_ctx_size(context, (krb5_pointer) ctx,
+			    &bufsize)))
+	    goto error_out;
+
+    /* Allocate the buffer */
+    if ((obuffer = (krb5_octet *) xmalloc(bufsize)) == NULL) {
+	    kret = ENOMEM;
+	    goto error_out;
+    }
+
+    obp = obuffer;
+    blen = bufsize;
+    /* Externalize the context */
+    if ((kret = kg_ctx_externalize(context,
+				   (krb5_pointer) ctx, &obp, &blen)))
+	    goto error_out;
+
+    /* Success!  Return the buffer */
+    interprocess_token->length = bufsize - blen;
+    interprocess_token->value = obuffer;
+    *minor_status = 0;
+    retval = GSS_S_COMPLETE;
+
+    /* Now, clean up the context state */
+    (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+    *context_handle = GSS_C_NO_CONTEXT;
+
+    return (GSS_S_COMPLETE);
+
+error_out:
+    if (obuffer && bufsize) {
+	    memset(obuffer, 0, bufsize);
+	    xfree(obuffer);
+    }
+    if (*minor_status == 0) 
+	    *minor_status = (OM_uint32) kret;
+    return(retval);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/get_tkt_flags.c b/krb5-1-6/src/lib/gssapi/krb5/get_tkt_flags.c
new file mode 100644
index 000000000..19841a086
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/get_tkt_flags.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32 KRB5_CALLCONV 
+gss_krb5int_get_tkt_flags(minor_status, context_handle, ticket_flags)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     krb5_flags *ticket_flags;
+{
+   krb5_gss_ctx_id_rec *ctx;
+
+   /* 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);
+   }
+
+   if (ticket_flags)
+      *ticket_flags = ctx->krb_flags;
+
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/gssapiP_krb5.h b/krb5-1-6/src/lib/gssapi/krb5/gssapiP_krb5.h
new file mode 100644
index 000000000..8887a4ddf
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -0,0 +1,685 @@
+/*
+ * Copyright 2000 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GSSAPIP_KRB5_H_
+#define _GSSAPIP_KRB5_H_
+
+#include <k5-int.h>
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+/* work around sunos braindamage */
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+
+#include "gssapiP_generic.h"
+
+/* The include of gssapi_krb5.h will dtrt with the above #defines in
+ * effect.
+ */
+#include "gssapi_krb5.h"
+#include "gssapi_err_krb5.h"
+
+/* for debugging */
+#undef CFX_EXERCISE
+
+/** constants **/
+
+#define GSS_MECH_KRB5_OID_LENGTH 9
+#define GSS_MECH_KRB5_OID "\052\206\110\206\367\022\001\002\002"
+
+#define GSS_MECH_KRB5_OLD_OID_LENGTH 5
+#define GSS_MECH_KRB5_OLD_OID "\053\005\001\005\002"
+
+/* Incorrect krb5 mech OID emitted by MS. */
+#define GSS_MECH_KRB5_WRONG_OID_LENGTH 9
+#define GSS_MECH_KRB5_WRONG_OID "\052\206\110\202\367\022\001\002\002"
+
+
+#define CKSUMTYPE_KG_CB		0x8003
+
+#define KG_TOK_CTX_AP_REQ	0x0100
+#define KG_TOK_CTX_AP_REP	0x0200
+#define KG_TOK_CTX_ERROR	0x0300
+#define KG_TOK_SIGN_MSG		0x0101
+#define KG_TOK_SEAL_MSG		0x0201
+#define	KG_TOK_MIC_MSG		0x0101
+#define	KG_TOK_WRAP_MSG		0x0201
+#define KG_TOK_DEL_CTX		0x0102
+
+#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
+
+/* These are to be stored in little-endian order, i.e., des-mac is
+   stored as 02 00.  */
+enum sgn_alg {
+  SGN_ALG_DES_MAC_MD5           = 0x0000,
+  SGN_ALG_MD2_5                 = 0x0001,
+  SGN_ALG_DES_MAC               = 0x0002,
+  SGN_ALG_3			= 0x0003, /* not published */
+  SGN_ALG_HMAC_MD5              = 0x0011, /* microsoft w2k;  */
+  SGN_ALG_HMAC_SHA1_DES3_KD     = 0x0004
+};
+enum seal_alg {
+  SEAL_ALG_NONE            = 0xffff,
+  SEAL_ALG_DES             = 0x0000,
+  SEAL_ALG_1		   = 0x0001, /* not published */
+  SEAL_ALG_MICROSOFT_RC4   = 0x0010, /* microsoft w2k;  */
+  SEAL_ALG_DES3KD          = 0x0002
+};
+
+/* for 3DES */
+#define KG_USAGE_SEAL 22
+#define KG_USAGE_SIGN 23
+#define KG_USAGE_SEQ  24
+
+/* for draft-ietf-krb-wg-gssapi-cfx-01 */
+#define KG_USAGE_ACCEPTOR_SEAL	22
+#define KG_USAGE_ACCEPTOR_SIGN	23
+#define KG_USAGE_INITIATOR_SEAL	24
+#define KG_USAGE_INITIATOR_SIGN	25
+
+enum qop {
+  GSS_KRB5_INTEG_C_QOP_MD5       = 0x0001, /* *partial* MD5 = "MD2.5" */
+  GSS_KRB5_INTEG_C_QOP_DES_MD5   = 0x0002,
+  GSS_KRB5_INTEG_C_QOP_DES_MAC   = 0x0003,
+  GSS_KRB5_INTEG_C_QOP_HMAC_SHA1 = 0x0004,
+  GSS_KRB5_INTEG_C_QOP_MASK      = 0x00ff,
+  GSS_KRB5_CONF_C_QOP_DES        = 0x0100,
+  GSS_KRB5_CONF_C_QOP_DES3_KD    = 0x0200,
+  GSS_KRB5_CONF_C_QOP_MASK       = 0xff00
+};
+
+/** internal types **/
+
+typedef krb5_principal krb5_gss_name_t;
+
+typedef struct _krb5_gss_cred_id_rec {
+   /* protect against simultaneous accesses */
+   k5_mutex_t lock;
+
+   /* name/type of credential */
+   gss_cred_usage_t usage;
+   krb5_principal princ;	/* this is not interned as a gss_name_t */
+   int prerfc_mech;
+   int rfc_mech;
+
+   /* keytab (accept) data */
+   krb5_keytab keytab;
+   krb5_rcache rcache;
+
+   /* ccache (init) data */
+   krb5_ccache ccache;
+   krb5_timestamp tgt_expire;
+   krb5_enctype *req_enctypes;	/* limit negotiated enctypes to this list */
+} krb5_gss_cred_id_rec, *krb5_gss_cred_id_t; 
+
+typedef struct _krb5_gss_ctx_id_rec {
+   unsigned int initiate : 1;	/* nonzero if initiating, zero if accepting */
+   unsigned int established : 1;
+   unsigned int big_endian : 1;
+   unsigned int have_acceptor_subkey : 1;
+   unsigned int seed_init : 1;	/* XXX tested but never actually set */
+   OM_uint32 gss_flags;
+   unsigned char seed[16];
+   krb5_principal here;
+   krb5_principal there;
+   krb5_keyblock *subkey;
+   int signalg;
+   size_t cksum_size;
+   int sealalg;
+   krb5_keyblock *enc;
+   krb5_keyblock *seq;
+   krb5_timestamp endtime;
+   krb5_flags krb_flags;
+   /* 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. */
+   gssint_uint64 seq_send;
+   gssint_uint64 seq_recv;
+   void *seqstate;
+   krb5_context k5_context;
+   krb5_auth_context auth_context;
+   gss_OID_desc *mech_used;
+    /* Protocol spec revision
+       0 => RFC 1964 with 3DES and RC4 enhancements
+       1 => draft-ietf-krb-wg-gssapi-cfx-01
+       No others defined so far.  */
+   int proto;
+   krb5_cksumtype cksumtype;	/* for "main" subkey */
+   krb5_keyblock *acceptor_subkey; /* CFX only */
+   krb5_cksumtype acceptor_subkey_cksumtype;
+   int cred_rcache;		/* did we get rcache from creds? */
+} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
+
+extern g_set kg_vdb;
+
+extern k5_mutex_t gssint_krb5_keytab_lock;
+
+/* helper macros */
+
+#define kg_save_name(name)		g_save_name(&kg_vdb,name)
+#define kg_save_cred_id(cred)		g_save_cred_id(&kg_vdb,cred)
+#define kg_save_ctx_id(ctx)		g_save_ctx_id(&kg_vdb,ctx)
+#define kg_save_lucidctx_id(lctx)	g_save_lucidctx_id(&kg_vdb,lctx)
+
+#define kg_validate_name(name)		g_validate_name(&kg_vdb,name)
+#define kg_validate_cred_id(cred)	g_validate_cred_id(&kg_vdb,cred)
+#define kg_validate_ctx_id(ctx)		g_validate_ctx_id(&kg_vdb,ctx)
+#define kg_validate_lucidctx_id(lctx)	g_validate_lucidctx_id(&kg_vdb,lctx)
+
+#define kg_delete_name(name)		g_delete_name(&kg_vdb,name)
+#define kg_delete_cred_id(cred)		g_delete_cred_id(&kg_vdb,cred)
+#define kg_delete_ctx_id(ctx)		g_delete_ctx_id(&kg_vdb,ctx)
+#define kg_delete_lucidctx_id(lctx)	g_delete_lucidctx_id(&kg_vdb,lctx)
+
+/** helper functions **/
+
+OM_uint32 kg_get_defcred 
+	(OM_uint32 *minor_status, 
+		   gss_cred_id_t *cred);
+
+krb5_error_code kg_checksum_channel_bindings
+         (krb5_context context, gss_channel_bindings_t cb,
+					     krb5_checksum *cksum,
+					     int bigend);
+
+krb5_error_code kg_make_seq_num (krb5_context context,
+					   krb5_keyblock *key,
+            int direction, krb5_ui_4 seqnum, unsigned char *cksum,
+				unsigned char *buf);
+
+krb5_error_code kg_get_seq_num (krb5_context context,
+					  krb5_keyblock *key,
+            unsigned char *cksum, unsigned char *buf, int *direction,
+					  krb5_ui_4 *seqnum);
+
+krb5_error_code kg_make_seed (krb5_context context,
+					krb5_keyblock *key,
+					unsigned char *seed);
+
+int kg_confounder_size (krb5_context context, krb5_keyblock *key);
+
+krb5_error_code kg_make_confounder (krb5_context context, 
+	    krb5_keyblock *key, unsigned char *buf);
+
+krb5_error_code kg_encrypt (krb5_context context, 
+				      krb5_keyblock *key, int usage,
+				      krb5_pointer iv,
+				      krb5_const_pointer in,
+				      krb5_pointer out,
+				      unsigned int length);
+krb5_error_code
+kg_arcfour_docrypt (const krb5_keyblock *longterm_key , int ms_usage,
+		    const unsigned char *kd_data, size_t kd_data_len,
+		    const unsigned char *input_buf, size_t input_len,
+		    unsigned char *output_buf);
+
+krb5_error_code kg_decrypt (krb5_context context,
+				      krb5_keyblock *key,  int usage,
+				      krb5_pointer iv,
+				      krb5_const_pointer in,
+				      krb5_pointer out,
+				      unsigned int length);
+
+OM_uint32 kg_seal (OM_uint32 *minor_status,
+		  gss_ctx_id_t context_handle,
+		  int conf_req_flag,
+		  int qop_req,
+		  gss_buffer_t input_message_buffer,
+		  int *conf_state,
+		  gss_buffer_t output_message_buffer,
+		  int toktype);
+
+OM_uint32 kg_unseal (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);
+
+OM_uint32 kg_seal_size (OM_uint32 *minor_status,
+				  gss_ctx_id_t context_handle,
+				  int conf_req_flag,
+				  gss_qop_t qop_req,
+				  OM_uint32 output_size,
+				  OM_uint32 *input_size);
+
+krb5_error_code kg_ctx_size (krb5_context kcontext,
+				       krb5_pointer arg,
+				       size_t *sizep);
+
+krb5_error_code kg_ctx_externalize (krb5_context kcontext,
+					      krb5_pointer arg,
+					      krb5_octet **buffer,
+					      size_t *lenremain);
+
+krb5_error_code kg_ctx_internalize (krb5_context kcontext,
+					      krb5_pointer *argp,
+					      krb5_octet **buffer,
+					      size_t *lenremain);
+
+OM_uint32 kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status);
+
+OM_uint32 kg_caller_provided_ccache_name (OM_uint32 *minor_status, 
+                                          int *out_caller_provided_name);
+
+OM_uint32 kg_get_ccache_name (OM_uint32 *minor_status, 
+                              const char **out_name);
+
+OM_uint32 kg_set_ccache_name (OM_uint32 *minor_status, 
+                              const char *name);
+
+/** declarations of internal name mechanism functions **/
+
+OM_uint32 krb5_gss_acquire_cred
+(OM_uint32*,       /* minor_status */
+            gss_name_t,       /* desired_name */
+            OM_uint32,        /* time_req */
+            gss_OID_set,      /* desired_mechs */
+            gss_cred_usage_t, /* cred_usage */
+            gss_cred_id_t*,   /* output_cred_handle */
+            gss_OID_set*,     /* actual_mechs */
+            OM_uint32*        /* time_rec */
+           );
+
+OM_uint32 krb5_gss_release_cred
+(OM_uint32*,       /* minor_status */
+            gss_cred_id_t*    /* cred_handle */
+           );
+
+OM_uint32 krb5_gss_init_sec_context
+(OM_uint32*,       /* minor_status */
+            gss_cred_id_t,    /* claimant_cred_handle */
+            gss_ctx_id_t*,    /* context_handle */
+            gss_name_t,       /* target_name */
+            gss_OID,          /* mech_type */
+            OM_uint32,        /* req_flags */
+            OM_uint32,        /* time_req */
+            gss_channel_bindings_t,
+                              /* input_chan_bindings */
+            gss_buffer_t,     /* input_token */
+            gss_OID*,         /* actual_mech_type */
+            gss_buffer_t,     /* output_token */
+            OM_uint32*,       /* ret_flags */
+            OM_uint32*        /* time_rec */
+           );
+
+OM_uint32 krb5_gss_accept_sec_context
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t*,    /* context_handle */
+            gss_cred_id_t,    /* verifier_cred_handle */
+            gss_buffer_t,     /* input_token_buffer */
+            gss_channel_bindings_t,
+                              /* input_chan_bindings */
+            gss_name_t*,      /* src_name */
+            gss_OID*,         /* mech_type */
+            gss_buffer_t,     /* output_token */
+            OM_uint32*,       /* ret_flags */
+            OM_uint32*,       /* time_rec */
+            gss_cred_id_t*    /* delegated_cred_handle */
+           );
+
+OM_uint32 krb5_gss_process_context_token
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            gss_buffer_t      /* token_buffer */
+           );
+
+OM_uint32 krb5_gss_delete_sec_context
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t*,    /* context_handle */
+            gss_buffer_t      /* output_token */
+           );
+
+OM_uint32 krb5_gss_context_time
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            OM_uint32*        /* time_rec */
+           );
+
+OM_uint32 krb5_gss_sign
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            int,              /* qop_req */
+            gss_buffer_t,     /* message_buffer */
+            gss_buffer_t      /* message_token */
+           );
+
+OM_uint32 krb5_gss_verify
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            gss_buffer_t,     /* message_buffer */
+            gss_buffer_t,     /* token_buffer */
+            int*              /* qop_state */
+           );
+
+OM_uint32 krb5_gss_seal
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            int,              /* conf_req_flag */
+            int,              /* qop_req */
+            gss_buffer_t,     /* input_message_buffer */
+            int*,             /* conf_state */
+            gss_buffer_t      /* output_message_buffer */
+           );
+
+OM_uint32 krb5_gss_unseal
+(OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            gss_buffer_t,     /* input_message_buffer */
+            gss_buffer_t,     /* output_message_buffer */
+            int*,             /* conf_state */
+            int*              /* qop_state */
+           );
+
+OM_uint32 krb5_gss_display_status
+(OM_uint32*,       /* minor_status */
+            OM_uint32,        /* status_value */
+            int,              /* status_type */
+            gss_OID,          /* mech_type */
+            OM_uint32*,       /* message_context */
+            gss_buffer_t      /* status_string */
+           );
+
+OM_uint32 krb5_gss_indicate_mechs
+(OM_uint32*,       /* minor_status */
+            gss_OID_set*      /* mech_set */
+           );
+
+OM_uint32 krb5_gss_compare_name
+(OM_uint32*,       /* minor_status */
+            gss_name_t,       /* name1 */
+            gss_name_t,       /* name2 */
+            int*              /* name_equal */
+           );
+
+OM_uint32 krb5_gss_display_name
+(OM_uint32*,      /* minor_status */
+            gss_name_t,      /* input_name */
+            gss_buffer_t,    /* output_name_buffer */
+            gss_OID*         /* output_name_type */
+           );
+
+OM_uint32 krb5_gss_import_name
+(OM_uint32*,       /* minor_status */
+            gss_buffer_t,     /* input_name_buffer */
+            gss_OID,          /* input_name_type */
+            gss_name_t*       /* output_name */
+           );
+
+OM_uint32 krb5_gss_release_name
+(OM_uint32*,       /* minor_status */
+            gss_name_t*       /* input_name */
+           );
+
+OM_uint32 krb5_gss_inquire_cred
+(OM_uint32 *,      /* minor_status */
+            gss_cred_id_t,    /* cred_handle */
+            gss_name_t *,     /* name */
+            OM_uint32 *,      /* lifetime */
+            gss_cred_usage_t*,/* cred_usage */
+            gss_OID_set *     /* mechanisms */
+           );
+
+OM_uint32 krb5_gss_inquire_context
+(OM_uint32*,       /* minor_status */
+	    gss_ctx_id_t,     /* context_handle */
+	    gss_name_t*,      /* initiator_name */
+	    gss_name_t*,      /* acceptor_name */
+	    OM_uint32*,       /* lifetime_rec */
+	    gss_OID*,         /* mech_type */
+	    OM_uint32*,       /* ret_flags */
+	    int*,             /* locally_initiated */
+	    int*              /* open */
+	   );
+
+/* New V2 entry points */
+OM_uint32 krb5_gss_get_mic
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_qop_t,			/* qop_req */
+	    gss_buffer_t,		/* message_buffer */
+	    gss_buffer_t		/* message_token */
+	   );
+
+OM_uint32 krb5_gss_verify_mic
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_buffer_t,		/* message_buffer */
+	    gss_buffer_t,		/* message_token */
+	    gss_qop_t *			/* qop_state */
+	   );
+
+OM_uint32 krb5_gss_wrap
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    int,			/* conf_req_flag */
+	    gss_qop_t,			/* qop_req */
+	    gss_buffer_t,		/* input_message_buffer */
+	    int *,			/* conf_state */
+	    gss_buffer_t		/* output_message_buffer */
+	   );
+
+OM_uint32 krb5_gss_unwrap
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_buffer_t,		/* input_message_buffer */
+	    gss_buffer_t,		/* output_message_buffer */
+	    int *,			/* conf_state */
+	    gss_qop_t *			/* qop_state */
+	   );
+
+OM_uint32 krb5_gss_wrap_size_limit
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    int,			/* conf_req_flag */
+	    gss_qop_t,			/* qop_req */
+	    OM_uint32,			/* req_output_size */
+	    OM_uint32 *			/* max_input_size */
+	   );
+
+OM_uint32 krb5_gss_import_name_object
+(OM_uint32 *,		/* minor_status */
+	    void *,			/* input_name */
+	    gss_OID,			/* input_name_type */
+	    gss_name_t *		/* output_name */
+	   );
+
+OM_uint32 krb5_gss_export_name_object
+(OM_uint32 *,		/* minor_status */
+	    gss_name_t,			/* input_name */
+	    gss_OID,			/* desired_name_type */
+	    void * *			/* output_name */
+	   );
+
+OM_uint32 krb5_gss_add_cred
+(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 */
+	   );
+
+OM_uint32 krb5_gss_inquire_cred_by_mech
+(OM_uint32  *,		/* minor_status */
+	    gss_cred_id_t,		/* cred_handle */
+	    gss_OID,			/* mech_type */
+	    gss_name_t *,		/* name */
+	    OM_uint32 *,		/* initiator_lifetime */
+	    OM_uint32 *,		/* acceptor_lifetime */
+	    gss_cred_usage_t * 		/* cred_usage */
+	   );
+
+OM_uint32 krb5_gss_export_sec_context
+(OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t *,		/* context_handle */
+	    gss_buffer_t		/* interprocess_token */
+	    );
+
+OM_uint32 krb5_gss_import_sec_context
+(OM_uint32 *,		/* minor_status */
+	    gss_buffer_t,		/* interprocess_token */
+	    gss_ctx_id_t *		/* context_handle */
+	    );
+
+krb5_error_code krb5_gss_ser_init(krb5_context);
+
+OM_uint32 krb5_gss_release_oid
+(OM_uint32 *,		/* minor_status */
+	    gss_OID *			/* oid */
+	   );
+
+OM_uint32 krb5_gss_internal_release_oid
+(OM_uint32 *,		/* minor_status */
+	    gss_OID *			/* oid */
+	   );
+
+OM_uint32 krb5_gss_inquire_names_for_mech
+(OM_uint32 *,		/* minor_status */
+	    gss_OID,			/* mechanism */
+	    gss_OID_set *		/* name_types */
+	   );
+
+OM_uint32 krb5_gss_canonicalize_name
+(OM_uint32  *,		/* minor_status */
+	    const gss_name_t,		/* input_name */
+	    const gss_OID,		/* mech_type */
+	    gss_name_t *		/* output_name */
+	 );
+	
+OM_uint32 krb5_gss_export_name
+(OM_uint32  *,		/* minor_status */
+	    const gss_name_t,		/* input_name */
+	    gss_buffer_t		/* exported_name */
+	 );
+
+OM_uint32 krb5_gss_duplicate_name
+(OM_uint32  *,		/* minor_status */
+	    const gss_name_t,		/* input_name */
+	    gss_name_t *		/* dest_name */
+	 );
+
+OM_uint32 krb5_gss_validate_cred
+(OM_uint32 *,		/* minor_status */
+	    gss_cred_id_t		/* cred */
+         );
+
+OM_uint32
+krb5_gss_validate_cred_1(OM_uint32 * /* minor_status */,
+			 gss_cred_id_t /* cred_handle */,
+			 krb5_context /* context */);
+
+gss_OID krb5_gss_convert_static_mech_oid(gss_OID oid);
+	
+krb5_error_code gss_krb5int_make_seal_token_v3(krb5_context,
+					       krb5_gss_ctx_id_rec *,
+					       const gss_buffer_desc *,
+					       gss_buffer_t,
+					       int, int);
+
+OM_uint32 gss_krb5int_unseal_token_v3(krb5_context *contextptr,
+				      OM_uint32 *minor_status,
+				      krb5_gss_ctx_id_rec *ctx,
+				      unsigned char *ptr, int bodysize,
+				      gss_buffer_t message_buffer,
+				      int *conf_state, int *qop_state, 
+				      int toktype);
+
+/*
+ * These take unglued krb5-mech-specific contexts.
+ */
+
+OM_uint32 KRB5_CALLCONV gss_krb5int_get_tkt_flags 
+	(OM_uint32 *minor_status,
+		   gss_ctx_id_t context_handle,
+		   krb5_flags *ticket_flags);
+
+OM_uint32 KRB5_CALLCONV gss_krb5int_copy_ccache
+	(OM_uint32 *minor_status,
+		   gss_cred_id_t cred_handle,
+		   krb5_ccache out_ccache);
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, 
+				   gss_cred_id_t cred,
+				   OM_uint32 num_ktypes,
+				   krb5_enctype *ktypes);
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5int_export_lucid_sec_context(OM_uint32 *minor_status,
+				     gss_ctx_id_t *context_handle,
+				     OM_uint32 version,
+				     void **kctx);
+
+
+extern k5_mutex_t kg_kdc_flag_mutex;
+krb5_error_code krb5_gss_init_context (krb5_context *ctxp);
+
+krb5_error_code krb5_gss_use_kdc_context(void);
+
+#endif /* _GSSAPIP_KRB5_H_ */
diff --git a/krb5-1-6/src/lib/gssapi/krb5/gssapi_err_krb5.et b/krb5-1-6/src/lib/gssapi/krb5/gssapi_err_krb5.et
new file mode 100644
index 000000000..c2a705c84
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/gssapi_err_krb5.et
@@ -0,0 +1,40 @@
+# 
+# Copyright 1993 by OpenVision Technologies, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software
+# and its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appears in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of OpenVision not be used
+# in advertising or publicity pertaining to distribution of the software
+# without specific, written prior permission. OpenVision makes no
+# representations about the suitability of this software for any
+# purpose.  It is provided "as is" without express or implied warranty.
+# 
+# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+# 
+
+error_table k5g
+
+error_code KG_CCACHE_NOMATCH, "Principal in credential cache does not match desired name"
+error_code KG_KEYTAB_NOMATCH, "No principal in keytab matches desired name"
+error_code KG_TGT_MISSING, "Credential cache has no TGT"
+error_code KG_NO_SUBKEY, "Authenticator has no subkey"
+error_code KG_CONTEXT_ESTABLISHED, "Context is already fully established"
+error_code KG_BAD_SIGN_TYPE, "Unknown signature type in token"
+error_code KG_BAD_LENGTH, "Invalid field length in token"
+error_code KG_CTX_INCOMPLETE, "Attempt to use incomplete security context"
+error_code KG_CONTEXT, "Bad magic number for krb5_gss_ctx_id_t"
+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"
+error_code KG_LUCID_VERSION, "Requested lucid context version not supported"
+end
diff --git a/krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.c b/krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.c
new file mode 100644
index 000000000..a0953e0b2
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * $Id$
+ */
+
+
+/* For declaration of krb5_ser_context_init */
+#include "k5-int.h"
+#include "gssapiP_krb5.h"
+
+/** exported constants defined in gssapi_krb5{,_nx}.h **/
+
+/* these are bogus, but will compile */
+
+/*
+ * The OID of the draft krb5 mechanism, assigned by IETF, is:
+ * 	iso(1) org(3) dod(5) internet(1) security(5)
+ *	kerberosv5(2) = 1.3.5.1.5.2
+ * The OID of the krb5_name type is:
+ * 	iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * 	krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1
+ * The OID of the krb5_principal type is:
+ * 	iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * 	krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2
+ * 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
+ *	
+ */
+
+/*
+ * Encoding rules: The first two values are encoded in one byte as 40
+ * * value1 + value2.  Subsequent values are encoded base 128, most
+ * significant digit first, with the high bit (\200) set on all octets
+ * except the last in each value's encoding.
+ */
+
+const gss_OID_desc krb5_gss_oid_array[] = {
+   /* this is the official, rfc-specified OID */
+   {GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID},
+   /* this pre-RFC mech OID */
+   {GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID},
+   /* this is the unofficial, incorrect mech OID emitted by MS */
+   {GSS_MECH_KRB5_WRONG_OID_LENGTH, GSS_MECH_KRB5_WRONG_OID},
+   /* this is the v2 assigned OID */
+   {9, "\052\206\110\206\367\022\001\002\003"},
+   /* these two are name type OID's */
+
+    /* 2.1.1. Kerberos Principal Name Form:  (rfc 1964)
+     * This name form shall be represented by the Object Identifier {iso(1)
+     * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+     * krb5(2) krb5_name(1)}.  The recommended symbolic name for this type
+     * is "GSS_KRB5_NT_PRINCIPAL_NAME". */
+   {10, "\052\206\110\206\367\022\001\002\002\001"},
+
+   /* gss_nt_krb5_principal.  Object identifier for a krb5_principal. Do not use. */
+   {10, "\052\206\110\206\367\022\001\002\002\002"},
+   { 0, 0 }
+};
+
+const gss_OID_desc * const gss_mech_krb5              = krb5_gss_oid_array+0;
+const gss_OID_desc * const gss_mech_krb5_old          = krb5_gss_oid_array+1;
+const gss_OID_desc * const gss_mech_krb5_wrong        = krb5_gss_oid_array+2;
+const gss_OID_desc * const gss_nt_krb5_name           = krb5_gss_oid_array+4;
+const gss_OID_desc * const gss_nt_krb5_principal      = krb5_gss_oid_array+5;
+const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME = 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},
+   {3, (gss_OID) krb5_gss_oid_array+0},
+   {1, (gss_OID) krb5_gss_oid_array+2},
+   {3, (gss_OID) krb5_gss_oid_array+0},
+};
+
+const gss_OID_set_desc * const gss_mech_set_krb5 = oidsets+0;
+const gss_OID_set_desc * const gss_mech_set_krb5_old = oidsets+1;
+const gss_OID_set_desc * const gss_mech_set_krb5_both = oidsets+2;
+
+g_set kg_vdb = G_SET_INIT;
+
+/** default credential support */
+
+/*
+ * init_sec_context() will explicitly re-acquire default credentials,
+ * so handling the expiration/invalidation condition here isn't needed.
+ */
+OM_uint32
+kg_get_defcred(minor_status, cred)
+     OM_uint32 *minor_status;
+     gss_cred_id_t *cred;
+{
+    OM_uint32 major;
+    
+    if ((major = krb5_gss_acquire_cred(minor_status, 
+				      (gss_name_t) NULL, GSS_C_INDEFINITE, 
+				      GSS_C_NULL_OID_SET, GSS_C_INITIATE, 
+				      cred, NULL, NULL)) && GSS_ERROR(major)) {
+      return(major);
+   }
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
+
+OM_uint32
+kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status)
+{
+    OM_uint32 err = 0;
+    
+    /* 
+     * Sync up the context ccache name with the GSSAPI ccache name.
+     * If kg_ccache_name is NULL -- normal unless someone has called 
+     * gss_krb5_ccache_name() -- then the system default ccache will 
+     * be picked up and used by resetting the context default ccache.
+     * This is needed for platforms which support multiple ccaches.
+     */
+    
+    if (!err) {
+        /* if NULL, resets the context default ccache */
+        err = krb5_cc_set_default_name(context,
+				       (char *) k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME));
+    }
+    
+    *minor_status = err;
+    return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+/* This function returns whether or not the caller set a cccache name.  Used by
+ * gss_acquire_cred to figure out if the caller wants to only look at this 
+ * ccache or search the cache collection for the desired name */
+OM_uint32
+kg_caller_provided_ccache_name (OM_uint32 *minor_status, 
+int *out_caller_provided_name)
+{
+    if (out_caller_provided_name) {
+        *out_caller_provided_name = 
+	  (k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME) != NULL);
+    }
+    
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
+kg_get_ccache_name (OM_uint32 *minor_status, const char **out_name)
+{
+    const char *name = NULL;
+    OM_uint32 err = 0;
+    char *kg_ccache_name;
+
+    kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
+    
+    if (kg_ccache_name != NULL) {
+	name = strdup(kg_ccache_name);
+	if (name == NULL)
+	    err = errno;
+    } else {
+	krb5_context context = NULL;
+
+	/* Reset the context default ccache (see text above), and then
+	   retrieve it.  */
+	err = krb5_gss_init_context(&context);
+	if (!err)
+	    err = krb5_cc_set_default_name (context, NULL);
+	if (!err) {
+	    name = krb5_cc_default_name(context);
+	    if (name) {
+		name = strdup(name);
+		if (name == NULL)
+		    err = errno;
+	    }
+	}
+	if (context)
+	    krb5_free_context(context);
+    }
+
+    if (!err) {
+        if (out_name) {
+            *out_name = name;
+        }
+    }
+    
+    *minor_status = err;
+    return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+OM_uint32
+kg_set_ccache_name (OM_uint32 *minor_status, const char *name)
+{
+    char *new_name = NULL;
+    char *swap = NULL;
+    char *kg_ccache_name;
+    krb5_error_code kerr;
+
+    if (name) {
+	new_name = malloc(strlen(name) + 1);
+	if (new_name == NULL) {
+	    *minor_status = ENOMEM;
+	    return GSS_S_FAILURE;
+	}
+	strcpy(new_name, name);
+    }
+
+    kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
+    swap = kg_ccache_name;
+    kg_ccache_name = new_name;
+    new_name = swap;
+    kerr = k5_setspecific(K5_KEY_GSS_KRB5_CCACHE_NAME, kg_ccache_name);
+    if (kerr != 0) {
+	/* Can't store, so free up the storage.  */
+	free(kg_ccache_name);
+	/* ??? free(new_name); */
+	*minor_status = kerr;
+	return GSS_S_FAILURE;
+    }
+
+    free (new_name);
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.hin b/krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.hin
new file mode 100644
index 000000000..647d14e39
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/gssapi_krb5.hin
@@ -0,0 +1,272 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GSSAPI_KRB5_H_
+#define _GSSAPI_KRB5_H_
+
+#include <gssapi/gssapi.h>
+#include <krb5.h>
+
+/* C++ friendlyness */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Reserved static storage for GSS_oids.  See rfc 1964 for more details. */
+
+/* 2.1.1. Kerberos Principal Name Form: */
+GSS_DLLIMP extern const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME;
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * krb5(2) krb5_name(1)}.  The recommended symbolic name for this type
+ * is "GSS_KRB5_NT_PRINCIPAL_NAME". */
+
+/* 2.1.2. Host-Based Service Name Form */
+#define GSS_KRB5_NT_HOSTBASED_SERVICE_NAME GSS_C_NT_HOSTBASED_SERVICE
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) service_name(4)}.  The previously recommended symbolic
+ * name for this type is "GSS_KRB5_NT_HOSTBASED_SERVICE_NAME".  The
+ * currently preferred symbolic name for this type is
+ * "GSS_C_NT_HOSTBASED_SERVICE". */
+
+/* 2.2.1. User Name Form */
+#define GSS_KRB5_NT_USER_NAME GSS_C_NT_USER_NAME    
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) user_name(1)}.  The recommended symbolic name for this
+ * type is "GSS_KRB5_NT_USER_NAME". */
+
+/* 2.2.2. Machine UID Form */
+#define GSS_KRB5_NT_MACHINE_UID_NAME GSS_C_NT_MACHINE_UID_NAME
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) machine_uid_name(2)}.  The recommended symbolic name for
+ * this type is "GSS_KRB5_NT_MACHINE_UID_NAME". */
+
+/* 2.2.3. String UID Form */
+#define GSS_KRB5_NT_STRING_UID_NAME GSS_C_NT_STRING_UID_NAME
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) string_uid_name(3)}.  The recommended symbolic name for
+ * this type is "GSS_KRB5_NT_STRING_UID_NAME". */ 
+
+GSS_DLLIMP extern const gss_OID_desc * const gss_mech_krb5;
+GSS_DLLIMP extern const gss_OID_desc * const gss_mech_krb5_old;
+GSS_DLLIMP extern const gss_OID_desc * const gss_mech_krb5_wrong;
+GSS_DLLIMP extern const gss_OID_set_desc * const gss_mech_set_krb5;
+GSS_DLLIMP extern const gss_OID_set_desc * const gss_mech_set_krb5_old;
+GSS_DLLIMP extern const gss_OID_set_desc * const gss_mech_set_krb5_both;
+
+GSS_DLLIMP extern const gss_OID_desc * const gss_nt_krb5_name;
+GSS_DLLIMP extern const gss_OID_desc * const gss_nt_krb5_principal;
+
+GSS_DLLIMP extern const gss_OID_desc krb5_gss_oid_array[];
+
+#define gss_krb5_nt_general_name	gss_nt_krb5_name
+#define gss_krb5_nt_principal		gss_nt_krb5_principal
+#define gss_krb5_nt_service_name	gss_nt_service_name
+#define gss_krb5_nt_user_name		gss_nt_user_name
+#define gss_krb5_nt_machine_uid_name	gss_nt_machine_uid_name
+#define gss_krb5_nt_string_uid_name	gss_nt_string_uid_name
+
+
+#if defined(_WIN32)
+typedef  unsigned __int64 gss_uint64;
+#else /*windows*/
+#include <inttypes.h>
+typedef  uint64_t gss_uint64;
+#endif
+
+
+typedef struct gss_krb5_lucid_key {
+	OM_uint32	type;		/* key encryption type */
+	OM_uint32	length;		/* length of key data */
+	void *		data;		/* actual key data */
+} gss_krb5_lucid_key_t;
+
+typedef struct gss_krb5_rfc1964_keydata {
+	OM_uint32	sign_alg;	/* signing algorthm */
+	OM_uint32	seal_alg;	/* seal/encrypt algorthm */
+	gss_krb5_lucid_key_t	ctx_key;
+					/* Context key
+					   (Kerberos session key or subkey) */
+} gss_krb5_rfc1964_keydata_t;
+
+typedef struct gss_krb5_cfx_keydata {
+	OM_uint32		have_acceptor_subkey;
+					/* 1 if there is an acceptor_subkey
+					   present, 0 otherwise */
+	gss_krb5_lucid_key_t	ctx_key;
+					/* Context key
+					   (Kerberos session key or subkey) */
+	gss_krb5_lucid_key_t	acceptor_subkey;
+					/* acceptor-asserted subkey or
+					   0's if no acceptor subkey */
+} gss_krb5_cfx_keydata_t;
+
+typedef struct gss_krb5_lucid_context_v1 {
+	OM_uint32	version;	/* Structure version number (1)
+					   MUST be at beginning of struct! */
+	OM_uint32	initiate;	/* Are we the initiator? */
+	OM_uint32	endtime;	/* expiration time of context */
+	gss_uint64	send_seq;	/* sender sequence number */
+	gss_uint64	recv_seq;	/* receive sequence number */
+	OM_uint32	protocol;	/* 0: rfc1964,
+					   1: draft-ietf-krb-wg-gssapi-cfx-07 */
+	/*
+	 * if (protocol == 0) rfc1964_kd should be used
+	 * and cfx_kd contents are invalid and should be zero
+	 * if (protocol == 1) cfx_kd should be used
+	 * and rfc1964_kd contents are invalid and should be zero
+	 */
+	gss_krb5_rfc1964_keydata_t rfc1964_kd;
+	gss_krb5_cfx_keydata_t	   cfx_kd;
+} gss_krb5_lucid_context_v1_t;
+
+/*
+ * Mask for determining the returned structure version.
+ * See example below for usage.
+ */
+typedef struct gss_krb5_lucid_context_version {
+	OM_uint32	version;	/* Structure version number */
+} gss_krb5_lucid_context_version_t;
+
+
+
+
+/* Alias for Heimdal compat. */
+#define gsskrb5_register_acceptor_identity krb5_gss_register_acceptor_identity
+
+OM_uint32 KRB5_CALLCONV krb5_gss_register_acceptor_identity(const char *);
+
+OM_uint32 KRB5_CALLCONV gss_krb5_get_tkt_flags 
+	(OM_uint32 *minor_status,
+		   gss_ctx_id_t context_handle,
+		   krb5_flags *ticket_flags);
+
+OM_uint32 KRB5_CALLCONV gss_krb5_copy_ccache
+	(OM_uint32 *minor_status,
+		   gss_cred_id_t cred_handle,
+		   krb5_ccache out_ccache);
+
+OM_uint32 KRB5_CALLCONV gss_krb5_ccache_name
+	(OM_uint32 *minor_status, const char *name,
+		   const char **out_name);
+
+/*
+ * gss_krb5_set_allowable_enctypes
+ *
+ * This function may be called by a context initiator after calling
+ * gss_acquire_cred(), but before calling gss_init_sec_context(),
+ * to restrict the set of enctypes which will be negotiated during
+ * context establishment to those in the provided array.
+ *
+ * 'cred' must be a valid credential handle obtained via
+ * gss_acquire_cred().  It may not be GSS_C_NO_CREDENTIAL.
+ * gss_acquire_cred() may have been called to get a handle to
+ * the default credential.
+ *
+ * The purpose of this function is to limit the keys that may
+ * be exported via gss_krb5_export_lucid_sec_context(); thus it
+ * should limit the enctypes of all keys that will be needed
+ * after the security context has been established.
+ * (i.e. context establishment may use a session key with a
+ * stronger enctype than in the provided array, however a
+ * subkey must be established within the enctype limits
+ * established by this function.)
+ *
+ */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, 
+				gss_cred_id_t cred,
+				OM_uint32 num_ktypes,
+				krb5_enctype *ktypes);
+
+/*
+ * Returns a non-opaque (lucid) version of the internal context
+ * information.  
+ *
+ * Note that context_handle must not be used again by the caller
+ * after this call.  The GSS implementation is free to release any
+ * resources associated with the original context.  It is up to the
+ * GSS implementation whether it returns pointers to existing data,
+ * or copies of the data.  The caller should treat the returned
+ * lucid context as read-only.
+ * 
+ * The caller must call gss_krb5_free_lucid_context() to free
+ * the context and allocated resources when it is finished with it.
+ *
+ * 'version' is an integer indicating the highest version of lucid
+ * context understood by the caller.  The highest version
+ * understood by both the caller and the GSS implementation must
+ * be returned.  The caller can determine which version of the
+ * structure was actually returned by examining the version field
+ * of the returned structure.  gss_krb5_lucid_context_version_t
+ * may be used as a mask to examine the returned structure version.
+ *
+ * If there are no common versions, an error should be returned.
+ * (XXX Need error definition(s))
+ *
+ * For example:
+ *	void *return_ctx;
+ *	gss_krb5_lucid_context_v1_t *ctx;
+ *	OM_uint32 min_stat, maj_stat;
+ *	OM_uint32 vers;
+ *	gss_ctx_id_t *ctx_handle;
+ *
+ *	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
+ *			ctx_handle, 1, &return_ctx);
+ *	// Verify success 
+ *
+ *	vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version;
+ *	switch (vers) {
+ *	case 1:
+ *		ctx = (gss_krb5_lucid_context_v1_t *) return_ctx;
+ *		break;
+ *	default:
+ *		// Error, unknown version returned
+ *		break;
+ *	}
+ *
+ */
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
+				  gss_ctx_id_t *context_handle,
+				  OM_uint32 version,
+				  void **kctx);
+
+/*
+ * Frees the allocated storage associated with an
+ * exported struct gss_krb5_lucid_context.
+ */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status,
+				void *kctx);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _GSSAPI_KRB5_H_ */
diff --git a/krb5-1-6/src/lib/gssapi/krb5/import_name.c b/krb5-1-6/src/lib/gssapi/krb5/import_name.c
new file mode 100644
index 000000000..db63c4b24
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/import_name.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_krb5.h"
+
+#ifndef NO_PASSWORD
+#include <pwd.h>
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/*
+ * errors:
+ * GSS_S_BAD_NAMETYPE	if the type is bogus
+ * GSS_S_BAD_NAME	if the type is good but the name is bogus
+ * GSS_S_FAILURE	if memory allocation fails
+ */
+
+OM_uint32
+krb5_gss_import_name(minor_status, input_name_buffer, 
+		     input_name_type, output_name)
+     OM_uint32 *minor_status;
+     gss_buffer_t input_name_buffer;
+     gss_OID input_name_type;
+     gss_name_t *output_name;
+{
+   krb5_context context;
+   krb5_principal princ;
+   krb5_error_code code;
+   char *stringrep, *tmp, *tmp2, *cp;
+   OM_uint32	length;
+#ifndef NO_PASSWORD
+   struct passwd *pw;
+#endif
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   /* set up default returns */
+
+   *output_name = NULL;
+   *minor_status = 0;
+
+   /* Go find the appropriate string rep to pass into parse_name */
+
+   if ((input_name_type != GSS_C_NULL_OID) &&
+       (g_OID_equal(input_name_type, gss_nt_service_name) ||
+	g_OID_equal(input_name_type, gss_nt_service_name_v2))) {
+      char *service, *host;
+
+      if ((tmp =
+	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
+	 *minor_status = ENOMEM;
+	 krb5_free_context(context);
+	 return(GSS_S_FAILURE);
+      }
+
+      memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
+      tmp[input_name_buffer->length] = 0;
+
+      service = tmp;
+      if ((host = strchr(tmp, '@'))) {
+	 *host = '\0';
+	 host++;
+      }
+
+      code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST,
+				     &princ);
+
+      xfree(tmp);
+   } else if ((input_name_type != GSS_C_NULL_OID) &&
+	      (g_OID_equal(input_name_type, gss_nt_krb5_principal))) {
+      krb5_principal input;
+
+      if (input_name_buffer->length != sizeof(krb5_principal)) {
+	 *minor_status = (OM_uint32) G_WRONG_SIZE;
+	 krb5_free_context(context);
+	 return(GSS_S_BAD_NAME);
+      }
+
+      input = *((krb5_principal *) input_name_buffer->value);
+
+      if ((code = krb5_copy_principal(context, input, &princ))) {
+	 *minor_status = code;
+	 krb5_free_context(context);
+	 return(GSS_S_FAILURE);
+      }
+   } else {
+#ifndef NO_PASSWORD
+      uid_t uid;
+      struct passwd pwx;
+      char pwbuf[BUFSIZ];
+#endif
+
+      stringrep = NULL;
+
+      if ((tmp =
+	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
+	 *minor_status = ENOMEM;
+	 krb5_free_context(context);
+	 return(GSS_S_FAILURE);
+      }
+      tmp2 = 0;
+
+      memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
+      tmp[input_name_buffer->length] = 0;
+
+      if ((input_name_type == GSS_C_NULL_OID) ||
+	  g_OID_equal(input_name_type, gss_nt_krb5_name) ||
+	  g_OID_equal(input_name_type, gss_nt_user_name)) {
+	 stringrep = (char *) tmp;
+#ifndef NO_PASSWORD
+      } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) {
+	 uid = *(uid_t *) input_name_buffer->value;
+      do_getpwuid:
+	 if (k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) == 0)
+	     stringrep = pw->pw_name;
+	 else
+	    *minor_status = (OM_uint32) G_NOUSER;
+      } else if (g_OID_equal(input_name_type, gss_nt_string_uid_name)) {
+	 uid = atoi(tmp);
+	 goto do_getpwuid;
+#endif
+      } else if (g_OID_equal(input_name_type, gss_nt_exported_name)) {
+	 cp = tmp;
+	 if (*cp++ != 0x04)
+		 goto fail_name;
+	 if (*cp++ != 0x01)
+		 goto fail_name;
+	 if (*cp++ != 0x00)
+		 goto fail_name;
+	 length = *cp++;
+	 if (length != gss_mech_krb5->length+2)
+		 goto fail_name;
+	 if (*cp++ != 0x06)
+		 goto fail_name;
+	 length = *cp++;
+	 if (length != gss_mech_krb5->length)
+		 goto fail_name;
+	 if (memcmp(cp, gss_mech_krb5->elements, length) != 0)
+		 goto fail_name;
+	 cp += length;
+	 length = *cp++;
+	 length = (length << 8) | *cp++;
+	 length = (length << 8) | *cp++;
+	 length = (length << 8) | *cp++;
+	 tmp2 = malloc(length+1);
+	 if (tmp2 == NULL) {
+		 xfree(tmp);
+		 *minor_status = ENOMEM;
+		 krb5_free_context(context);
+		 return GSS_S_FAILURE;
+	 }
+	 strncpy(tmp2, cp, length);
+	 tmp2[length] = 0;
+	 
+	 stringrep = tmp2;
+     } else {
+	 xfree(tmp);
+	 krb5_free_context(context);
+	 return(GSS_S_BAD_NAMETYPE);
+      }
+
+      /* at this point, stringrep is set, or if not, *minor_status is. */
+
+      if (stringrep)
+	 code = krb5_parse_name(context, (char *) stringrep, &princ);
+      else {
+      fail_name:
+	 xfree(tmp);
+	 if (tmp2)
+		 xfree(tmp2);
+	 krb5_free_context(context);
+	 return(GSS_S_BAD_NAME);
+      }
+      
+      if (tmp2)
+	      xfree(tmp2);
+      xfree(tmp);
+   }
+
+   /* at this point, a krb5 function has been called to set princ.  code
+      contains the return status */
+
+   if (code) {
+      *minor_status = (OM_uint32) code;
+      krb5_free_context(context);
+      return(GSS_S_BAD_NAME);
+   }
+
+   /* save the name in the validation database */
+
+   if (! kg_save_name((gss_name_t) princ)) {
+      krb5_free_principal(context, princ);
+      krb5_free_context(context);
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      return(GSS_S_FAILURE);
+   }
+
+   krb5_free_context(context);
+
+   /* return it */
+
+   *output_name = (gss_name_t) princ;
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/import_sec_context.c b/krb5-1-6/src/lib/gssapi/krb5/import_sec_context.c
new file mode 100644
index 000000000..1255ecc6c
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/import_sec_context.c
@@ -0,0 +1,126 @@
+/*
+ * lib/gssapi/krb5/import_sec_context.c
+ *
+ * Copyright 1995,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * import_sec_context.c	- Internalize the security context.
+ */
+#include "gssapiP_krb5.h"
+/* for serialization initialization functions */
+#include "k5-int.h"
+
+/*
+ * Fix up the OID of the mechanism so that uses the static version of
+ * the OID if possible.
+ */
+gss_OID krb5_gss_convert_static_mech_oid(oid)
+     gss_OID	oid;
+{
+	const gss_OID_desc 	*p;
+	OM_uint32		minor_status;
+	
+	for (p = krb5_gss_oid_array; p->length; p++) {
+		if ((oid->length == p->length) &&
+		    (memcmp(oid->elements, p->elements, p->length) == 0)) {
+			gss_release_oid(&minor_status, &oid);
+			return (gss_OID) p;
+		}
+	}
+	return oid;
+}
+
+krb5_error_code
+krb5_gss_ser_init (krb5_context context)
+{
+    krb5_error_code code;
+    static krb5_error_code (KRB5_CALLCONV *const fns[])(krb5_context) = {
+	krb5_ser_context_init, krb5_ser_auth_context_init,
+	krb5_ser_ccache_init, krb5_ser_rcache_init, krb5_ser_keytab_init,
+    };
+    int i;
+
+    for (i = 0; i < sizeof(fns)/sizeof(fns[0]); i++)
+	if ((code = (fns[i])(context)) != 0)
+	    return code;
+    return 0;
+}
+
+OM_uint32
+krb5_gss_import_sec_context(minor_status, interprocess_token, context_handle)
+    OM_uint32		*minor_status;
+    gss_buffer_t	interprocess_token;
+    gss_ctx_id_t	*context_handle;
+{
+    krb5_context	context;
+    krb5_error_code	kret = 0;
+    size_t		blen;
+    krb5_gss_ctx_id_t	ctx;
+    krb5_octet		*ibp;
+
+    /* This is a bit screwy.  We create a krb5 context because we need
+       one when calling the serialization code.  However, one of the
+       objects we're unpacking is a krb5 context, so when we finish,
+       we can throw this one away.  */
+    kret = krb5_gss_init_context(&context);
+    if (kret) {
+	*minor_status = kret;
+	return GSS_S_FAILURE;
+    }
+    kret = krb5_gss_ser_init(context);
+    if (kret) {
+	krb5_free_context(context);
+	*minor_status = kret;
+	return GSS_S_FAILURE;
+    }
+
+    /* Assume a tragic failure */
+    ctx = (krb5_gss_ctx_id_t) NULL;
+    *minor_status = 0;
+
+    /* Internalize the context */
+    ibp = (krb5_octet *) interprocess_token->value;
+    blen = (size_t) interprocess_token->length;
+    kret = kg_ctx_internalize(context, (krb5_pointer *) &ctx, &ibp, &blen);
+    krb5_free_context(context);
+    if (kret) {
+       *minor_status = (OM_uint32) kret;
+       return(GSS_S_FAILURE);
+    }
+
+    /* intern the context handle */
+    if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
+       (void)krb5_gss_delete_sec_context(minor_status, 
+					 (gss_ctx_id_t *) &ctx, NULL);
+       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+       return(GSS_S_FAILURE);
+    }
+    ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used);
+    
+    *context_handle = (gss_ctx_id_t) ctx;
+
+    *minor_status = 0;
+    return (GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/indicate_mechs.c b/krb5-1-6/src/lib/gssapi/krb5/indicate_mechs.c
new file mode 100644
index 000000000..c7ee4746f
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/indicate_mechs.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_krb5.h"
+#include "mglueP.h"
+
+OM_uint32
+krb5_gss_indicate_mechs(minor_status, mech_set)
+     OM_uint32 *minor_status;
+     gss_OID_set *mech_set;
+{
+   *minor_status = 0;
+
+   if (gssint_copy_oid_set(minor_status, gss_mech_set_krb5_both, mech_set)) {
+         *mech_set     = GSS_C_NO_OID_SET;
+         *minor_status = ENOMEM;
+         return(GSS_S_FAILURE);
+   }
+
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/init_sec_context.c b/krb5-1-6/src/lib/gssapi/krb5/init_sec_context.c
new file mode 100644
index 000000000..4f14e598b
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/init_sec_context.c
@@ -0,0 +1,1021 @@
+/*
+ * Copyright 2000,2002, 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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 "gss_libinit.h"
+#include "gssapiP_krb5.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <stdlib.h>
+#include <assert.h>
+
+/*
+ * $Id$
+ */
+
+/* XXX This is for debugging only!!!  Should become a real bitfield
+   at some point */
+int krb5_gss_dbg_client_expcreds = 0;
+
+/*
+ * Common code which fetches the correct krb5 credentials from the
+ * ccache.
+ */
+static krb5_error_code get_credentials(context, cred, server, now,
+				       endtime, out_creds)
+    krb5_context context;
+    krb5_gss_cred_id_t cred;
+    krb5_principal server;
+    krb5_timestamp now;
+    krb5_timestamp endtime;
+    krb5_creds **out_creds;
+{
+    krb5_error_code	code;
+    krb5_creds 		in_creds;
+
+    k5_mutex_assert_locked(&cred->lock);
+    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;
+
+    in_creds.keyblock.enctype = 0;
+
+    code = krb5_get_credentials(context, 0, cred->ccache,
+				&in_creds, out_creds);
+    if (code)
+	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 != NULL &&
+	(*out_creds)->times.endtime < now) {
+	code = KRB5KRB_AP_ERR_TKT_EXPIRED;
+	goto cleanup;
+    }
+    
+cleanup:
+    if (in_creds.client)
+	    krb5_free_principal(context, in_creds.client);
+    if (in_creds.server)
+	    krb5_free_principal(context, in_creds.server);
+    return code;
+}
+struct gss_checksum_data {
+    krb5_gss_ctx_id_rec *ctx;
+    krb5_gss_cred_id_t cred;
+    krb5_checksum md5;
+    krb5_data checksum_data;
+};
+
+#ifdef CFX_EXERCISE
+#include "../../krb5/krb/auth_con.h"
+#endif
+static krb5_error_code KRB5_CALLCONV
+make_gss_checksum (krb5_context context, krb5_auth_context auth_context,
+		   void *cksum_data, krb5_data **out)
+{
+    krb5_error_code code;
+    krb5_int32 con_flags;
+    unsigned char *ptr;
+    struct gss_checksum_data *data = cksum_data;
+    krb5_data credmsg;
+    unsigned int junk;
+
+    data->checksum_data.data = 0;
+    credmsg.data = 0;
+    /* build the checksum field */
+
+    if (data->ctx->gss_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,
+				  data->cred->princ, data->ctx->there,
+				  data->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 */
+	    data->ctx->gss_flags &= ~GSS_C_DELEG_FLAG;
+
+	    data->checksum_data.length = 24;
+	} else {
+	    if (credmsg.length+28 > KRB5_INT16_MAX) {
+		krb5_free_data_contents(context, &credmsg);
+		return(KRB5KRB_ERR_FIELD_TOOLONG);
+	    }
+
+	    data->checksum_data.length = 28+credmsg.length;
+	}
+    } else {
+	data->checksum_data.length = 24;
+    }
+#ifdef CFX_EXERCISE
+    if (data->ctx->auth_context->keyblock != NULL
+	&& data->ctx->auth_context->keyblock->enctype == 18) {
+	srand(time(0) ^ getpid());
+	/* Our ftp client code stupidly assumes a base64-encoded
+	   version of the token will fit in 10K, so don't make this
+	   too big.  */
+	junk = rand() & 0xff;
+    } else
+	junk = 0;
+#else
+    junk = 0;
+#endif
+
+    data->checksum_data.length += junk;
+
+    /* now allocate a buffer to hold the checksum data and
+       (maybe) KRB_CRED msg */
+
+    if ((data->checksum_data.data =
+	 (char *) xmalloc(data->checksum_data.length)) == NULL) {
+	if (credmsg.data)
+	    krb5_free_data_contents(context, &credmsg);
+	return(ENOMEM);
+    }
+
+    ptr = data->checksum_data.data;
+
+    TWRITE_INT(ptr, data->md5.length, 0);
+    TWRITE_STR(ptr, (unsigned char *) data->md5.contents, data->md5.length);
+    TWRITE_INT(ptr, data->ctx->gss_flags, 0);
+
+    /* done with this, free it */
+    xfree(data->md5.contents);
+
+    if (credmsg.data) {
+	TWRITE_INT16(ptr, KRB5_GSS_FOR_CREDS_OPTION, 0);
+	TWRITE_INT16(ptr, credmsg.length, 0);
+	TWRITE_STR(ptr, (unsigned char *) credmsg.data, credmsg.length);
+
+	/* free credmsg data */
+	krb5_free_data_contents(context, &credmsg);
+    }
+    if (junk)
+	memset(ptr, 'i', junk);
+    *out = &data->checksum_data;
+    return 0;
+}
+    
+static krb5_error_code
+make_ap_req_v1(context, ctx, cred, k_cred, chan_bindings, mech_type, token)
+    krb5_context context;
+    krb5_gss_ctx_id_rec *ctx;
+    krb5_gss_cred_id_t cred;
+    krb5_creds *k_cred;
+    gss_channel_bindings_t chan_bindings;
+    gss_OID mech_type;
+    gss_buffer_t token;
+{
+    krb5_flags mk_req_flags = 0;
+    krb5_error_code code;
+    struct gss_checksum_data cksum_struct;
+    krb5_checksum md5;
+    krb5_data ap_req;
+    krb5_data *checksum_data = NULL;
+    unsigned char *ptr;
+    unsigned char *t;
+    unsigned int tlen;
+
+    k5_mutex_assert_locked(&cred->lock);
+    ap_req.data = 0;
+
+    /* compute the hash of the channel bindings */
+
+    if ((code = kg_checksum_channel_bindings(context, chan_bindings, &md5, 0)))
+        return(code);
+
+    krb5_auth_con_set_req_cksumtype(context, ctx->auth_context,
+				    CKSUMTYPE_KG_CB);
+    cksum_struct.md5 = md5;
+    cksum_struct.ctx = ctx;
+    cksum_struct.cred = cred;
+    cksum_struct.checksum_data.data = NULL;
+    switch (k_cred->keyblock.enctype) {
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES3_CBC_SHA1:
+      code = make_gss_checksum(context, ctx->auth_context, &cksum_struct,
+				 &checksum_data);
+	    if (code)
+		goto cleanup;
+	break;
+    default:
+	krb5_auth_con_set_checksum_func(context, ctx->auth_context,
+					make_gss_checksum, &cksum_struct);
+	    break;
+    }
+
+
+    /* call mk_req.  subkey and ap_req need to be used or destroyed */
+
+    mk_req_flags = AP_OPTS_USE_SUBKEY;
+
+    if (ctx->gss_flags & GSS_C_MUTUAL_FLAG)
+	mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED;
+
+    code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags,
+				checksum_data, k_cred, &ap_req);
+    krb5_free_data_contents(context, &cksum_struct.checksum_data);
+    if (code)
+	goto cleanup;
+
+   /* store the interesting stuff from creds and authent */
+   ctx->endtime = k_cred->times.endtime;
+   ctx->krb_flags = k_cred->ticket_flags;
+
+   /* build up the token */
+
+   /* allocate space for the token */
+   tlen = g_token_size((gss_OID) mech_type, ap_req.length);
+
+   if ((t = (unsigned char *) xmalloc(tlen)) == NULL) {
+      code = ENOMEM;
+      goto cleanup;
+   }
+
+   /* fill in the buffer */
+
+   ptr = t;
+
+   g_make_token_header(mech_type, ap_req.length,
+		       &ptr, KG_TOK_CTX_AP_REQ);
+
+   TWRITE_STR(ptr, (unsigned char *) ap_req.data, ap_req.length);
+
+   /* pass it back */
+
+   token->length = tlen;
+   token->value = (void *) t;
+
+   code = 0;
+    
+ cleanup:
+   if (checksum_data && checksum_data->data)
+       krb5_free_data_contents(context, checksum_data);
+   if (ap_req.data)
+       krb5_free_data_contents(context, &ap_req);
+
+   return (code);
+}
+
+/*
+ * setup_enc
+ *
+ * Fill in the encryption descriptors.  Called after AP-REQ is made.
+ */
+static OM_uint32
+setup_enc(
+   OM_uint32 *minor_status,
+   krb5_gss_ctx_id_rec *ctx,
+   krb5_context context)
+{
+   krb5_error_code code;
+   int i;
+   krb5int_access kaccess;
+
+   code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
+   if (code)
+       goto fail;
+
+   ctx->have_acceptor_subkey = 0;
+   ctx->proto = 0;
+   ctx->cksumtype = 0;
+   switch(ctx->subkey->enctype) {
+   case ENCTYPE_DES_CBC_MD5:
+   case ENCTYPE_DES_CBC_MD4:
+   case ENCTYPE_DES_CBC_CRC:
+      ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
+      ctx->signalg = SGN_ALG_DES_MAC_MD5;
+      ctx->cksum_size = 8;
+      ctx->sealalg = SEAL_ALG_DES;
+
+      /* The encryption key is the session key XOR
+	 0xf0f0f0f0f0f0f0f0.  */
+      if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc)))
+	 goto fail;
+
+      for (i=0; i<ctx->enc->length; i++)
+	 ctx->enc->contents[i] ^= 0xf0;
+
+      goto copy_subkey_to_seq;
+
+   case ENCTYPE_DES3_CBC_SHA1:
+       /* MIT extension */
+      ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
+      ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
+      ctx->cksum_size = 20;
+      ctx->sealalg = SEAL_ALG_DES3KD;
+
+   copy_subkey:
+      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
+      if (code)
+	 goto fail;
+   copy_subkey_to_seq:
+      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
+      if (code) {
+	 krb5_free_keyblock (context, ctx->enc);
+	 goto fail;
+      }
+      break;
+
+   case ENCTYPE_ARCFOUR_HMAC:
+       /* Microsoft extension */
+      ctx->signalg = SGN_ALG_HMAC_MD5 ;
+      ctx->cksum_size = 8;
+      ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
+
+      goto copy_subkey;
+
+   default:
+       /* Fill some fields we shouldn't be using on this path
+	  with garbage.  */
+       ctx->signalg = -10;
+       ctx->sealalg = -10;
+
+       ctx->proto = 1;
+       code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, ctx->subkey->enctype,
+					    &ctx->cksumtype);
+       if (code)
+	   goto fail;
+       code = krb5_c_checksum_length(context, ctx->cksumtype,
+				     &ctx->cksum_size);
+       if (code)
+	   goto fail;
+       goto copy_subkey;
+   }
+fail:
+   *minor_status = code;
+   return GSS_S_FAILURE;
+}
+
+/*
+ * new_connection
+ *
+ * Do the grunt work of setting up a new context.
+ */
+static OM_uint32
+new_connection(
+   OM_uint32 *minor_status,
+   krb5_gss_cred_id_t cred,
+   gss_ctx_id_t *context_handle,
+   gss_name_t target_name,
+   gss_OID mech_type,
+   OM_uint32 req_flags,
+   OM_uint32 time_req,
+   gss_channel_bindings_t input_chan_bindings,
+   gss_buffer_t input_token,
+   gss_OID *actual_mech_type,
+   gss_buffer_t output_token,
+   OM_uint32 *ret_flags,
+   OM_uint32 *time_rec,
+   krb5_context context,
+   int default_mech)
+{
+   OM_uint32 major_status;
+   krb5_error_code code;
+   krb5_creds *k_cred;
+   krb5_gss_ctx_id_rec *ctx, *ctx_free;
+   krb5_timestamp now;
+   gss_buffer_desc token;
+
+   k5_mutex_assert_locked(&cred->lock);
+   major_status = GSS_S_FAILURE;
+   token.length = 0;
+   token.value = NULL;
+
+   /* make sure the cred is usable for init */
+
+   if ((cred->usage != GSS_C_INITIATE) &&
+       (cred->usage != GSS_C_BOTH)) {
+      *minor_status = 0;
+      return(GSS_S_NO_CRED);
+   }
+
+   /* complain if the input token is non-null */
+
+   if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
+       *minor_status = 0;
+       return(GSS_S_DEFECTIVE_TOKEN);
+   }
+
+   /* create the ctx */
+
+   if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
+       == NULL) {
+      *minor_status = ENOMEM;
+      return(GSS_S_FAILURE);
+   }
+
+   /* fill in the ctx */
+   memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+   ctx_free = ctx;
+   if ((code = krb5_auth_con_init(context, &ctx->auth_context)))
+      goto fail;
+   krb5_auth_con_setflags(context, ctx->auth_context,
+			  KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+
+   /* limit the encryption types negotiated (if requested) */
+   if (cred->req_enctypes) {
+	if ((code = krb5_set_default_tgs_enctypes(context,
+						  cred->req_enctypes))) {
+	    goto fail;
+	}
+   }
+
+   ctx->initiate = 1;
+   ctx->gss_flags = (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
+                     GSS_C_TRANS_FLAG | 
+                     ((req_flags) & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
+                                     GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)));
+   ctx->seed_init = 0;
+   ctx->big_endian = 0;  /* all initiators do little-endian, as per spec */
+   ctx->seqstate = 0;
+
+   if ((code = krb5_timeofday(context, &now)))
+      goto fail;
+
+   if (time_req == 0 || time_req == GSS_C_INDEFINITE) {
+      ctx->endtime = 0;
+   } else {
+      ctx->endtime = now + time_req;
+   }
+
+   if ((code = krb5_copy_principal(context, cred->princ, &ctx->here)))
+      goto fail;
+      
+   if ((code = krb5_copy_principal(context, (krb5_principal) target_name,
+				   &ctx->there)))
+      goto fail;
+
+   code = get_credentials(context, cred, ctx->there, now,
+			  ctx->endtime, &k_cred);
+   if (code)
+      goto fail;
+
+   if (default_mech) {
+      mech_type = (gss_OID) gss_mech_krb5;
+   }
+
+   if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used)
+       != GSS_S_COMPLETE) {
+      code = *minor_status;
+      goto fail;
+   }
+   /*
+    * Now try to make it static if at all possible....
+    */
+   ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used);
+
+   {
+      /* gsskrb5 v1 */
+      krb5_ui_4 seq_temp;
+      if ((code = make_ap_req_v1(context, ctx,
+				 cred, k_cred, input_chan_bindings, 
+				 mech_type, &token))) {
+	 if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
+	     (code == KG_EMPTY_CCACHE))
+	    major_status = GSS_S_NO_CRED;
+	 if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
+	    major_status = GSS_S_CREDENTIALS_EXPIRED;
+	 goto fail;
+      }
+
+      krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &seq_temp);
+      ctx->seq_send = seq_temp;
+      krb5_auth_con_getsendsubkey(context, ctx->auth_context,
+				  &ctx->subkey);
+   }
+
+   major_status = setup_enc(minor_status, ctx, context);
+
+   if (k_cred) {
+      krb5_free_creds(context, k_cred);
+      k_cred = 0;
+   }
+      
+   /* at this point, the context is constructed and valid,
+      hence, releaseable */
+
+   /* intern the context handle */
+
+   if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
+      code = G_VALIDATE_FAILED;
+      goto fail;
+   }
+   *context_handle = (gss_ctx_id_t) ctx;
+   ctx_free = 0;
+
+   /* compute time_rec */
+   if (time_rec) {
+      if ((code = krb5_timeofday(context, &now)))
+	 goto fail;
+      *time_rec = ctx->endtime - now;
+   }
+
+   /* set the other returns */
+   *output_token = token;
+
+   if (ret_flags)
+      *ret_flags = ctx->gss_flags;
+
+   if (actual_mech_type)
+      *actual_mech_type = mech_type;
+
+   /* return successfully */
+
+   *minor_status = 0;
+   if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
+      ctx->established = 0;
+      return(GSS_S_CONTINUE_NEEDED);
+   } else {
+      ctx->seq_recv = ctx->seq_send;
+      g_order_init(&(ctx->seqstate), ctx->seq_recv,
+		   (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 
+		   (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
+      ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
+      ctx->established = 1;
+      return(GSS_S_COMPLETE);
+   }
+
+fail:
+   if (ctx_free) {
+       if (ctx_free->auth_context)
+	   krb5_auth_con_free(context, ctx_free->auth_context);
+       if (ctx_free->here)
+	   krb5_free_principal(context, ctx_free->here);
+       if (ctx_free->there)
+	   krb5_free_principal(context, ctx_free->there);
+       if (ctx_free->subkey)
+	   krb5_free_keyblock(context, ctx_free->subkey);
+       xfree(ctx_free);
+   } else
+	(void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+
+   *minor_status = code;
+   return (major_status);
+}
+
+/*
+ * mutual_auth
+ *
+ * Handle the reply from the acceptor, if we're doing mutual auth.
+ */
+static OM_uint32
+mutual_auth(
+   OM_uint32 *minor_status,
+   gss_ctx_id_t *context_handle,
+   gss_name_t target_name,
+   gss_OID mech_type,
+   OM_uint32 req_flags,
+   OM_uint32 time_req,
+   gss_channel_bindings_t input_chan_bindings,
+   gss_buffer_t input_token,
+   gss_OID *actual_mech_type,
+   gss_buffer_t output_token,
+   OM_uint32 *ret_flags,
+   OM_uint32 *time_rec,
+   krb5_context context)
+{
+   OM_uint32 major_status;
+   unsigned char *ptr;
+   char *sptr;
+   krb5_data ap_rep;
+   krb5_ap_rep_enc_part *ap_rep_data;
+   krb5_timestamp now;
+   krb5_gss_ctx_id_rec *ctx;
+   krb5_error *krb_error;
+   krb5_error_code code;
+   krb5int_access kaccess;
+
+   major_status = GSS_S_FAILURE;
+
+   code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
+   if (code)
+       goto fail;
+
+   /* validate the context handle */
+   /*SUPPRESS 29*/
+   if (! kg_validate_ctx_id(*context_handle)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      return(GSS_S_NO_CONTEXT);
+   }
+
+   ctx = (krb5_gss_ctx_id_t) *context_handle;
+
+   /* make sure the context is non-established, and that certain
+      arguments are unchanged */
+
+   if ((ctx->established) ||
+       ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) {
+      code = KG_CONTEXT_ESTABLISHED;
+      goto fail;
+   }
+
+   if (! krb5_principal_compare(context, ctx->there, 
+				(krb5_principal) target_name)) {
+      (void)krb5_gss_delete_sec_context(minor_status, 
+					context_handle, NULL);
+      code = 0;
+      major_status = GSS_S_BAD_NAME;
+      goto fail;
+   }
+
+   /* verify the token and leave the AP_REP message in ap_rep */
+
+   if (input_token == GSS_C_NO_BUFFER) {
+      (void)krb5_gss_delete_sec_context(minor_status, 
+					context_handle, NULL);
+      code = 0;
+      major_status = GSS_S_DEFECTIVE_TOKEN;
+      goto fail;
+   }
+
+   ptr = (unsigned char *) input_token->value;
+
+   if (g_verify_token_header(ctx->mech_used,
+			     &(ap_rep.length),
+			     &ptr, KG_TOK_CTX_AP_REP,
+			     input_token->length, 1)) {
+      if (g_verify_token_header((gss_OID) ctx->mech_used,
+				&(ap_rep.length),
+				&ptr, KG_TOK_CTX_ERROR,
+				input_token->length, 1) == 0) {
+
+	 /* Handle a KRB_ERROR message from the server */
+
+	 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);
+	 goto fail;
+      } else {
+	 *minor_status = 0;
+	 return(GSS_S_DEFECTIVE_TOKEN);
+      }
+   }
+
+   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,
+			   &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;
+   }
+
+   /* store away the sequence number */
+   ctx->seq_recv = ap_rep_data->seq_number;
+   g_order_init(&(ctx->seqstate), ctx->seq_recv,
+		(ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
+		(ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0, ctx->proto);
+
+   if (ctx->proto == 1 && ap_rep_data->subkey) {
+       /* Keep acceptor's subkey.  */
+       ctx->have_acceptor_subkey = 1;
+       code = krb5_copy_keyblock(context, ap_rep_data->subkey,
+				 &ctx->acceptor_subkey);
+       if (code)
+	   goto fail;
+       code = (*kaccess.krb5int_c_mandatory_cksumtype)(context,
+					    ctx->acceptor_subkey->enctype,
+					    &ctx->acceptor_subkey_cksumtype);
+       if (code)
+	   goto fail;
+   }
+
+   /* free the ap_rep_data */
+   krb5_free_ap_rep_enc_part(context, ap_rep_data);
+
+   /* set established */
+   ctx->established = 1;
+
+   /* set returns */
+
+   if (time_rec) {
+      if ((code = krb5_timeofday(context, &now)))
+	 goto fail;
+      *time_rec = ctx->endtime - now;
+   }
+
+   if (ret_flags)
+      *ret_flags = ctx->gss_flags;
+
+   if (actual_mech_type)
+      *actual_mech_type = mech_type;
+
+   /* success */
+
+   *minor_status = 0;
+   return GSS_S_COMPLETE;
+
+fail:
+   (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+
+   *minor_status = code;
+   return (major_status);
+}
+
+OM_uint32
+krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
+			  context_handle, target_name, mech_type,
+			  req_flags, time_req, input_chan_bindings,
+			  input_token, actual_mech_type, output_token,
+			  ret_flags, time_rec)
+    OM_uint32 *minor_status;
+    gss_cred_id_t claimant_cred_handle;
+    gss_ctx_id_t *context_handle;
+    gss_name_t target_name;
+    gss_OID mech_type;
+    OM_uint32 req_flags;
+    OM_uint32 time_req;
+    gss_channel_bindings_t input_chan_bindings;
+    gss_buffer_t input_token;
+    gss_OID *actual_mech_type;
+    gss_buffer_t output_token;
+    OM_uint32 *ret_flags;
+    OM_uint32 *time_rec;
+{
+   krb5_context context;
+   krb5_gss_cred_id_t cred;
+   int err;
+   krb5_error_code kerr;
+   int default_mech = 0;
+   OM_uint32 major_status;
+   OM_uint32 tmp_min_stat;
+
+   if (*context_handle == GSS_C_NO_CONTEXT) {
+       kerr = krb5_gss_init_context(&context);
+       if (kerr) {
+	   *minor_status = kerr;
+	   return GSS_S_FAILURE;
+       }
+       if (GSS_ERROR(kg_sync_ccache_name(context, minor_status)))
+	   return GSS_S_FAILURE;
+   } else {
+       context = ((krb5_gss_ctx_id_rec *)*context_handle)->k5_context;
+   }
+
+   /* set up return values so they can be "freed" successfully */
+
+   major_status = GSS_S_FAILURE; /* Default major code */
+   output_token->length = 0;
+   output_token->value = NULL;
+   if (actual_mech_type)
+      *actual_mech_type = NULL;
+
+   /* verify that the target_name is valid and usable */
+
+   if (! kg_validate_name(target_name)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      if (*context_handle == GSS_C_NO_CONTEXT)
+	  krb5_free_context(context);
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   }
+
+   /* verify the credential, or use the default */
+   /*SUPPRESS 29*/
+   if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) {
+      major_status = kg_get_defcred(minor_status, (gss_cred_id_t *)&cred);
+      if (major_status && GSS_ERROR(major_status)) {
+	 if (*context_handle == GSS_C_NO_CONTEXT)
+	    krb5_free_context(context);
+	 return(major_status);
+      }
+   } else {
+      major_status = krb5_gss_validate_cred(minor_status, claimant_cred_handle);
+      if (GSS_ERROR(major_status)) {
+	  if (*context_handle == GSS_C_NO_CONTEXT)
+	      krb5_free_context(context);
+	  return(major_status);
+      }
+      cred = (krb5_gss_cred_id_t) claimant_cred_handle;
+   }
+   kerr = k5_mutex_lock(&cred->lock);
+   if (kerr) {
+       krb5_free_context(context);
+       *minor_status = kerr;
+       return GSS_S_FAILURE;
+   }
+
+   /* verify the mech_type */
+
+   err = 0;
+   if (mech_type == GSS_C_NULL_OID) {
+       default_mech = 1;
+       if (cred->rfc_mech) {
+	   mech_type = (gss_OID) gss_mech_krb5;
+       } else if (cred->prerfc_mech) {
+	   mech_type = (gss_OID) gss_mech_krb5_old;
+       } else {
+	   err = 1;
+       }
+   } else if (g_OID_equal(mech_type, gss_mech_krb5)) {
+       if (!cred->rfc_mech)
+	   err = 1;
+   } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) {
+       if (!cred->prerfc_mech)
+	   err = 1;
+   } else if (g_OID_equal(mech_type, gss_mech_krb5_wrong)) {
+       if (!cred->rfc_mech)
+	   err = 1;
+   } else {
+       err = 1;
+   }
+   
+   if (err) {
+      k5_mutex_unlock(&cred->lock);
+      if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
+	 krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred);
+      *minor_status = 0;
+      if (*context_handle == GSS_C_NO_CONTEXT)
+	 krb5_free_context(context);
+      return(GSS_S_BAD_MECH);
+   }
+
+   /* is this a new connection or not? */
+
+   /*SUPPRESS 29*/
+   if (*context_handle == GSS_C_NO_CONTEXT) {
+      major_status = new_connection(minor_status, cred, context_handle,
+				    target_name, mech_type, req_flags,
+				    time_req, input_chan_bindings,
+				    input_token, actual_mech_type,
+				    output_token, ret_flags, time_rec,
+				    context, default_mech);
+      k5_mutex_unlock(&cred->lock);
+      if (*context_handle == GSS_C_NO_CONTEXT)
+	  krb5_free_context(context);
+      else
+	  ((krb5_gss_ctx_id_rec *) *context_handle)->k5_context = context;
+   } else {
+      /* mutual_auth doesn't care about the credentials */
+      k5_mutex_unlock(&cred->lock);
+      major_status = mutual_auth(minor_status, context_handle,
+				 target_name, mech_type, req_flags,
+				 time_req, input_chan_bindings,
+				 input_token, actual_mech_type,
+				 output_token, ret_flags, time_rec,
+				 context);
+      /* If context_handle is now NO_CONTEXT, mutual_auth called
+	 delete_sec_context, which would've zapped the krb5 context
+	 too.  */
+   }
+
+   if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
+      krb5_gss_release_cred(&tmp_min_stat, (gss_cred_id_t *)&cred);
+
+   return(major_status);
+}
+
+#ifndef _WIN32
+k5_mutex_t kg_kdc_flag_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+static int kdc_flag = 0;
+#endif
+
+krb5_error_code
+krb5_gss_init_context (krb5_context *ctxp)
+{
+    krb5_error_code err;
+#ifndef _WIN32
+    int is_kdc;
+#endif
+
+    err = gssint_initialize_library();
+    if (err)
+	return err;
+#ifndef _WIN32
+    err = k5_mutex_lock(&kg_kdc_flag_mutex);
+    if (err)
+	return err;
+    is_kdc = kdc_flag;
+    k5_mutex_unlock(&kg_kdc_flag_mutex);
+
+    if (is_kdc)
+	return krb5int_init_context_kdc(ctxp);
+#endif
+
+    return krb5_init_context(ctxp);
+}
+
+#ifndef _WIN32
+krb5_error_code
+krb5_gss_use_kdc_context()
+{
+    krb5_error_code err;
+
+    err = gssint_initialize_library();
+    if (err)
+	return err;
+    err = k5_mutex_lock(&kg_kdc_flag_mutex);
+    if (err)
+	return err;
+    kdc_flag = 1;
+    k5_mutex_unlock(&kg_kdc_flag_mutex);
+    return 0;
+}
+#endif
+
diff --git a/krb5-1-6/src/lib/gssapi/krb5/inq_context.c b/krb5-1-6/src/lib/gssapi/krb5/inq_context.c
new file mode 100644
index 000000000..0954ddc5d
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/inq_context.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32
+krb5_gss_inquire_context(minor_status, context_handle, initiator_name, 
+			 acceptor_name, lifetime_rec, mech_type, ret_flags,
+			 locally_initiated, open)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_name_t *initiator_name;
+     gss_name_t *acceptor_name;
+     OM_uint32 *lifetime_rec;
+     gss_OID *mech_type;
+     OM_uint32 *ret_flags;
+     int *locally_initiated;
+     int *open;
+{
+   krb5_context context;
+   krb5_error_code code;
+   krb5_gss_ctx_id_rec *ctx;
+   krb5_principal init, accept;
+   krb5_timestamp now;
+   krb5_deltat lifetime;
+
+   if (initiator_name)
+      *initiator_name = (gss_name_t) NULL;
+   if (acceptor_name)
+      *acceptor_name = (gss_name_t) 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);
+   }
+
+   init = NULL;
+   accept = NULL;
+   context = ctx->k5_context;
+
+   if ((code = krb5_timeofday(context, &now))) {
+      *minor_status = code;
+      return(GSS_S_FAILURE);
+   }
+
+   if ((lifetime = ctx->endtime - now) < 0)
+      lifetime = 0;
+
+   if (initiator_name) {
+      if ((code = krb5_copy_principal(context, 
+				      ctx->initiate?ctx->here:ctx->there,
+				      &init))) {
+	 *minor_status = code;
+	 return(GSS_S_FAILURE);
+      }
+      if (! kg_save_name((gss_name_t) init)) {
+	 krb5_free_principal(context, init);
+	 *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+	 return(GSS_S_FAILURE);
+      }
+   }
+
+   if (acceptor_name) {
+      if ((code = krb5_copy_principal(context, 
+				      ctx->initiate?ctx->there:ctx->here,
+				      &accept))) {
+	 if (init) krb5_free_principal(context, init);
+	 *minor_status = code;
+	 return(GSS_S_FAILURE);
+      }
+      if (! kg_save_name((gss_name_t) accept)) {
+	 krb5_free_principal(context, accept);
+	 if (init) {
+	    kg_delete_name((gss_name_t) accept);
+	    krb5_free_principal(context, init);
+	 }
+	 *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+	 return(GSS_S_FAILURE);
+      }
+   }
+
+   if (initiator_name)
+      *initiator_name = (gss_name_t) init;
+
+   if (acceptor_name)
+      *acceptor_name = (gss_name_t) accept;
+
+   if (lifetime_rec)
+      *lifetime_rec = lifetime;
+
+   if (mech_type)
+      *mech_type = (gss_OID) ctx->mech_used;
+
+   if (ret_flags)
+      *ret_flags = ctx->gss_flags;
+
+   if (locally_initiated)
+      *locally_initiated = ctx->initiate;
+
+   if (open)
+      *open = ctx->established;
+
+   *minor_status = 0;
+   return((lifetime == 0)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/inq_cred.c b/krb5-1-6/src/lib/gssapi/krb5/inq_cred.c
new file mode 100644
index 000000000..58425d80d
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/inq_cred.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2000 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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
+krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
+		      cred_usage, mechanisms)
+     OM_uint32 *minor_status;
+     gss_cred_id_t cred_handle;
+     gss_name_t *name;
+     OM_uint32 *lifetime_ret;
+     gss_cred_usage_t *cred_usage;
+     gss_OID_set *mechanisms;
+{
+   krb5_context context;
+   krb5_gss_cred_id_t cred;
+   krb5_error_code code;
+   krb5_timestamp now;
+   krb5_deltat lifetime;
+   krb5_principal ret_name;
+   gss_OID_set mechs;
+   OM_uint32 ret;
+
+   ret = GSS_S_FAILURE;
+   ret_name = NULL;
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   if (name) *name = NULL;
+   if (mechanisms) *mechanisms = NULL;
+
+   /* check for default credential */
+   /*SUPPRESS 29*/
+   if (cred_handle == GSS_C_NO_CREDENTIAL) {
+      OM_uint32 major;
+
+      if ((major = kg_get_defcred(minor_status, (gss_cred_id_t *)&cred)) &&
+	  GSS_ERROR(major)) {
+	 krb5_free_context(context);
+	 return(major);
+      }
+   } else {
+      OM_uint32 major;
+	   
+      major = krb5_gss_validate_cred(minor_status, cred_handle);
+      if (GSS_ERROR(major)) {
+	  krb5_free_context(context);
+	  return(major);
+      }
+      cred = (krb5_gss_cred_id_t) cred_handle;
+   }
+
+   if ((code = krb5_timeofday(context, &now))) {
+      *minor_status = code;
+      ret = GSS_S_FAILURE;
+      goto fail;
+   }
+
+   code = k5_mutex_lock(&cred->lock);
+   if (code != 0) {
+       *minor_status = code;
+       ret = GSS_S_FAILURE;
+       goto fail;
+   }
+   if (cred->tgt_expire > 0) {
+       if ((lifetime = cred->tgt_expire - now) < 0)
+	   lifetime = 0;
+   }
+   else
+       lifetime = GSS_C_INDEFINITE;
+
+   if (name) {
+      if (cred->princ &&
+	  (code = krb5_copy_principal(context, cred->princ, &ret_name))) {
+	 k5_mutex_unlock(&cred->lock);
+	 *minor_status = code;
+	 ret = GSS_S_FAILURE;
+	 goto fail;
+      }
+   }
+
+   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)))) {
+	   k5_mutex_unlock(&cred->lock);
+	   if (ret_name)
+	       krb5_free_principal(context, ret_name);
+	   /* *minor_status set above */
+	   goto fail;
+       }
+   }
+
+   if (name) {
+      if (ret_name != NULL && ! kg_save_name((gss_name_t) ret_name)) {
+	 k5_mutex_unlock(&cred->lock);
+	 if (cred_handle == GSS_C_NO_CREDENTIAL)
+	     krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred);
+
+	 (void) gss_release_oid_set(minor_status, &mechs);
+	 krb5_free_principal(context, ret_name);
+	 *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+	 krb5_free_context(context);
+	 return(GSS_S_FAILURE);
+      }
+      if (ret_name != NULL)
+	  *name = (gss_name_t) ret_name;
+      else
+	  *name = GSS_C_NO_NAME;
+   }
+
+   if (lifetime_ret)
+      *lifetime_ret = lifetime;
+
+   if (cred_usage)
+      *cred_usage = cred->usage;
+   k5_mutex_unlock(&cred->lock);
+
+   if (mechanisms)
+      *mechanisms = mechs;
+
+   if (cred_handle == GSS_C_NO_CREDENTIAL)
+       krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred);
+
+   krb5_free_context(context);
+   *minor_status = 0;
+   return((lifetime == 0)?GSS_S_CREDENTIALS_EXPIRED:GSS_S_COMPLETE);
+fail:
+   if (cred_handle == GSS_C_NO_CREDENTIAL) {
+       OM_uint32 tmp_min_stat;
+
+       krb5_gss_release_cred(&tmp_min_stat, (gss_cred_id_t *)&cred);
+   }
+   krb5_free_context(context);
+   return ret;
+}
+
+/* V2 interface */
+OM_uint32
+krb5_gss_inquire_cred_by_mech(minor_status, cred_handle,
+			      mech_type, name, initiator_lifetime,
+			      acceptor_lifetime, cred_usage)
+    OM_uint32		*minor_status;
+    gss_cred_id_t	cred_handle;
+    gss_OID		mech_type;
+    gss_name_t		*name;
+    OM_uint32		*initiator_lifetime;
+    OM_uint32		*acceptor_lifetime;
+    gss_cred_usage_t *cred_usage;
+{
+    krb5_gss_cred_id_t	cred;
+    OM_uint32		lifetime;
+    OM_uint32		mstat;
+
+    /*
+     * We only know how to handle our own creds.
+     */
+    if ((mech_type != GSS_C_NULL_OID) &&
+	!g_OID_equal(gss_mech_krb5_old, mech_type) &&
+	!g_OID_equal(gss_mech_krb5, mech_type)) {
+	*minor_status = 0;
+	return(GSS_S_NO_CRED);
+    }
+
+    cred = (krb5_gss_cred_id_t) cred_handle;
+    mstat = krb5_gss_inquire_cred(minor_status,
+				  cred_handle,
+				  name,
+				  &lifetime,
+				  cred_usage,
+				  (gss_OID_set *) NULL);
+    if (mstat == GSS_S_COMPLETE) {
+	if (cred &&
+	    ((cred->usage == GSS_C_INITIATE) ||
+	     (cred->usage == GSS_C_BOTH)) &&
+	    initiator_lifetime)
+	    *initiator_lifetime = lifetime;
+	if (cred &&
+	    ((cred->usage == GSS_C_ACCEPT) ||
+	     (cred->usage == GSS_C_BOTH)) &&
+	    acceptor_lifetime)
+	    *acceptor_lifetime = lifetime;
+    }
+    return(mstat);
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/krb5/inq_names.c b/krb5-1-6/src/lib/gssapi/krb5/inq_names.c
new file mode 100644
index 000000000..c9e3dc9ad
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/inq_names.c
@@ -0,0 +1,99 @@
+/*
+ * lib/gssapi/krb5/inq_names.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * inq_names.c - Return set of nametypes supported by the KRB5 mechanism.
+ */
+#include "gssapiP_krb5.h"
+
+OM_uint32
+krb5_gss_inquire_names_for_mech(minor_status, mechanism, name_types)
+    OM_uint32	*minor_status;
+    gss_OID	mechanism;
+    gss_OID_set	*name_types;
+{
+    OM_uint32	major, minor;
+
+    /*
+     * We only know how to handle our own mechanism.
+     */
+    if ((mechanism != GSS_C_NULL_OID) &&
+	!g_OID_equal(gss_mech_krb5, mechanism) &&
+	!g_OID_equal(gss_mech_krb5_old, mechanism)) {
+	*minor_status = 0;
+	return(GSS_S_BAD_MECH);
+    }
+
+    /* We're okay.  Create an empty OID set */
+    major = gss_create_empty_oid_set(minor_status, name_types);
+    if (major == GSS_S_COMPLETE) {
+	/* Now add our members. */
+	if (
+	    ((major = generic_gss_add_oid_set_member(minor_status,
+						     gss_nt_user_name,
+						     name_types)
+	      ) == GSS_S_COMPLETE) &&
+	    ((major = generic_gss_add_oid_set_member(minor_status,
+						     gss_nt_machine_uid_name,
+						     name_types)
+	      ) == GSS_S_COMPLETE) &&
+	    ((major = generic_gss_add_oid_set_member(minor_status,
+						     gss_nt_string_uid_name,
+						     name_types)
+	      ) == GSS_S_COMPLETE) &&
+	    ((major = generic_gss_add_oid_set_member(minor_status,
+						     gss_nt_service_name,
+						     name_types)
+	      ) == GSS_S_COMPLETE) &&
+	    ((major = generic_gss_add_oid_set_member(minor_status,
+						     gss_nt_service_name_v2,
+						     name_types)
+	      ) == GSS_S_COMPLETE) &&
+	    ((major = generic_gss_add_oid_set_member(minor_status,
+						     gss_nt_exported_name,
+						     name_types)
+	      ) == GSS_S_COMPLETE) &&
+	    ((major = generic_gss_add_oid_set_member(minor_status,
+						     gss_nt_krb5_name,
+						     name_types)
+	      ) == GSS_S_COMPLETE)
+	    ) {
+	    major = generic_gss_add_oid_set_member(minor_status,
+						   gss_nt_krb5_principal,
+						   name_types);
+	}
+
+	/*
+	 * If we choked, then release the set, but don't overwrite the minor
+	 * status with the release call.
+	 */
+	if (major != GSS_S_COMPLETE)
+	    (void) gss_release_oid_set(&minor,
+				       name_types);
+    }
+    return(major);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/k5seal.c b/krb5-1-6/src/lib/gssapi/krb5/k5seal.c
new file mode 100644
index 000000000..7a904d065
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/k5seal.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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 <assert.h>
+
+static krb5_error_code
+make_seal_token_v1 (krb5_context context,
+		    krb5_keyblock *enc,
+		    krb5_keyblock *seq,
+		    gssint_uint64 *seqnum,
+		    int direction,
+		    gss_buffer_t text,
+		    gss_buffer_t token,
+		    int signalg,
+		    size_t cksum_size,
+		    int sealalg,
+		    int encrypt,
+		    int toktype,
+		    int bigend,
+		    gss_OID oid)
+{
+    krb5_error_code code;
+    size_t sumlen;
+    char *data_ptr;
+    krb5_data plaind;
+    krb5_checksum md5cksum;
+    krb5_checksum cksum;
+				/* msglen contains the message length
+				 * we are signing/encrypting.  tmsglen
+				 * contains the length of the message
+				 * we plan to write out to the token.
+				 * tlen is the length of the token
+				 * including header. */
+    unsigned  conflen=0, tmsglen, tlen, msglen;
+    unsigned char *t, *ptr;
+    unsigned char *plain;
+    unsigned char pad;
+    krb5_keyusage sign_usage = KG_USAGE_SIGN;
+
+
+    assert((!encrypt) || (toktype == KG_TOK_SEAL_MSG));
+    /* create the token buffer */
+    /* Do we need confounder? */
+    if (encrypt || (!bigend && (toktype == KG_TOK_SEAL_MSG)))
+      conflen = kg_confounder_size(context, enc);
+    else conflen = 0;
+
+    if (toktype == KG_TOK_SEAL_MSG) {
+      switch (sealalg) {
+      case SEAL_ALG_MICROSOFT_RC4:
+	msglen = conflen + text->length+1;
+	pad = 1;
+	break;
+      default:
+	/* XXX knows that des block size is 8 */
+	msglen = (conflen+text->length+8)&(~7);
+	      pad = 8-(text->length%8);
+      }
+      tmsglen = msglen;
+    } else {
+      tmsglen = 0;
+      msglen = text->length;
+      pad = 0;
+    }
+    tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen);
+
+    if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
+      return(ENOMEM);
+
+    /*** fill in the token */
+
+    ptr = t;
+    g_make_token_header(oid, 14+cksum_size+tmsglen, &ptr, toktype);
+
+    /* 0..1 SIGN_ALG */
+    ptr[0] = signalg & 0xff;
+    ptr[1] = (signalg >> 8) & 0xff;
+
+    /* 2..3 SEAL_ALG or Filler */
+    if ((toktype == KG_TOK_SEAL_MSG) && encrypt) {
+      ptr[2] = sealalg & 0xff;
+      ptr[3] = (sealalg >> 8) & 0xff;
+    } else {
+      /* No seal */
+      ptr[2] = 0xff;
+      ptr[3] = 0xff;
+    }
+
+    /* 4..5 Filler */
+    ptr[4] = 0xff;
+    ptr[5] = 0xff;
+
+    /* pad the plaintext, encrypt if needed, and stick it in the token */
+
+    /* initialize the the cksum */
+    switch (signalg) {
+    case SGN_ALG_DES_MAC_MD5:
+    case SGN_ALG_MD2_5:
+      md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
+      break;
+    case SGN_ALG_HMAC_SHA1_DES3_KD:
+      md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
+      break;
+    case SGN_ALG_HMAC_MD5:
+      md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+      if (toktype != KG_TOK_SEAL_MSG)
+	sign_usage = 15;
+      break;
+    default:
+    case SGN_ALG_DES_MAC:
+      abort ();
+    }
+
+    code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
+    if (code)
+      return(code);
+    md5cksum.length = sumlen;
+
+
+    if ((plain = (unsigned char *) xmalloc(msglen ? msglen : 1)) == NULL) {
+      xfree(t);
+      return(ENOMEM);
+    }
+
+    if (conflen) {
+      if ((code = kg_make_confounder(context, enc, plain))) {
+	xfree(plain);
+	xfree(t);
+	return(code);
+      }
+    }
+
+    memcpy(plain+conflen, text->value, text->length);
+    if (pad) memset(plain+conflen+text->length, pad, pad);
+
+    /* compute the checksum */
+
+    /* 8 = head of token body as specified by mech spec */
+    if (! (data_ptr =
+	   (char *) xmalloc(8 + (bigend ? text->length : msglen)))) {
+      xfree(plain);
+      xfree(t);
+      return(ENOMEM);
+    }
+    (void) memcpy(data_ptr, ptr-2, 8);
+    if (bigend)
+      (void) memcpy(data_ptr+8, text->value, text->length);
+    else
+      (void) memcpy(data_ptr+8, plain, msglen);
+    plaind.length = 8 + (bigend ? text->length : msglen);
+    plaind.data = data_ptr;
+    code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq,
+				sign_usage, &plaind, &md5cksum);
+    xfree(data_ptr);
+
+    if (code) {
+      xfree(plain);
+      xfree(t);
+      return(code);
+    }
+    switch(signalg) {
+    case SGN_ALG_DES_MAC_MD5:
+    case 3:
+
+      if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL,
+			     (g_OID_equal(oid, gss_mech_krb5_old) ?
+			      seq->contents : NULL),
+			     md5cksum.contents, md5cksum.contents, 16))) {
+	krb5_free_checksum_contents(context, &md5cksum);
+	xfree (plain);
+	xfree(t);
+	return code;
+      }
+
+      cksum.length = cksum_size;
+      cksum.contents = md5cksum.contents + 16 - cksum.length;
+
+      memcpy(ptr+14, cksum.contents, cksum.length);
+      break;
+
+    case SGN_ALG_HMAC_SHA1_DES3_KD:
+      /*
+       * Using key derivation, the call to krb5_c_make_checksum
+       * already dealt with encrypting.
+       */
+      if (md5cksum.length != cksum_size)
+	abort ();
+      memcpy (ptr+14, md5cksum.contents, md5cksum.length);
+      break;
+    case SGN_ALG_HMAC_MD5:
+      memcpy (ptr+14, md5cksum.contents, cksum_size);
+      break;
+    }
+
+    krb5_free_checksum_contents(context, &md5cksum);
+
+    /* create the seq_num */
+
+    if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum,
+				ptr+14, ptr+6))) {
+      xfree (plain);
+      xfree(t);
+      return(code);
+    }
+
+    if (encrypt) {
+      switch(sealalg) {
+      case SEAL_ALG_MICROSOFT_RC4:
+	{
+	  unsigned char bigend_seqnum[4];
+	  krb5_keyblock *enc_key;
+	  int i;
+	  bigend_seqnum[0] = (*seqnum>>24) & 0xff;
+	  bigend_seqnum[1] = (*seqnum>>16) & 0xff;
+	  bigend_seqnum[2] = (*seqnum>>8) & 0xff;
+	  bigend_seqnum[3] = *seqnum & 0xff;
+	  code = krb5_copy_keyblock (context, enc, &enc_key);
+	  if (code)
+	    {
+	      xfree(plain);
+	      xfree(t);
+	      return(code);
+	    }	      
+	  assert (enc_key->length == 16);
+	  for (i = 0; i <= 15; i++)
+	    ((char *) enc_key->contents)[i] ^=0xf0;
+	  code = kg_arcfour_docrypt (enc_key, 0,
+				     bigend_seqnum, 4, 
+				     plain, tmsglen,
+				     ptr+14+cksum_size);
+	  krb5_free_keyblock (context, enc_key);
+	  if (code)
+	    {
+	      xfree(plain);
+	      xfree(t);
+	      return(code);
+	    }
+	}
+	break;
+      default:
+	    if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL,
+				   (krb5_pointer) plain,
+				   (krb5_pointer) (ptr+cksum_size+14),
+				   tmsglen))) {
+	      xfree(plain);
+	      xfree(t);
+	      return(code);
+	    }
+      }
+    }else {
+      if (tmsglen)
+	memcpy(ptr+14+cksum_size, plain, tmsglen);
+    }
+	    xfree(plain);
+
+
+    /* that's it.  return the token */
+
+    (*seqnum)++;
+    *seqnum &= 0xffffffffL;
+
+    token->length = tlen;
+    token->value = (void *) t;
+
+    return(0);
+}
+
+/* if signonly is true, ignore conf_req, conf_state,
+   and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */
+
+OM_uint32
+kg_seal(minor_status, context_handle, conf_req_flag, qop_req,
+	input_message_buffer, conf_state, output_message_buffer, toktype)
+    OM_uint32 *minor_status;
+    gss_ctx_id_t context_handle;
+    int conf_req_flag;
+    int qop_req;
+    gss_buffer_t input_message_buffer;
+    int *conf_state;
+    gss_buffer_t output_message_buffer;
+    int toktype;
+{
+    krb5_gss_ctx_id_rec *ctx;
+    krb5_error_code code;
+    krb5_timestamp now;
+    krb5_context context;
+
+    output_message_buffer->length = 0;
+    output_message_buffer->value = NULL;
+
+    /* Only default qop or matching established cryptosystem is allowed.
+
+       There are NO EXTENSIONS to this set for AES and friends!  The
+       new spec says "just use 0".  The old spec plus extensions would
+       actually allow for certain non-zero values.  Fix this to handle
+       them later.  */
+    if (qop_req != 0) {
+	*minor_status = (OM_uint32) G_UNKNOWN_QOP;
+	return GSS_S_FAILURE;
+    }
+
+    /* 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);
+    }
+
+    context = ctx->k5_context;
+    if ((code = krb5_timeofday(context, &now))) {
+	*minor_status = code;
+	return(GSS_S_FAILURE);
+    }
+
+    switch (ctx->proto)
+    {
+    case 0:
+	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);
+	break;
+    case 1:
+	code = gss_krb5int_make_seal_token_v3(context, ctx,
+					      input_message_buffer,
+					      output_message_buffer,
+					      conf_req_flag, toktype);
+	break;
+    default:
+	code = G_UNKNOWN_QOP;	/* XXX */
+	break;
+    }
+
+    if (code) {
+	*minor_status = code;
+	return(GSS_S_FAILURE);
+    }
+
+    if (conf_state)
+	*conf_state = conf_req_flag;
+
+    *minor_status = 0;
+    return((ctx->endtime < now)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/k5sealv3.c b/krb5-1-6/src/lib/gssapi/krb5/k5sealv3.c
new file mode 100644
index 000000000..2c084865e
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/k5sealv3.c
@@ -0,0 +1,511 @@
+/*
+ * lib/gssapi/krb5/k5sealv3.c
+ *
+ * Copyright 2003,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+/* draft-ietf-krb-wg-gssapi-cfx-05 */
+
+#include <assert.h>
+#include "k5-platform.h" 	/* for 64-bit support */
+#include "k5-int.h"		/* for zap() */
+#include "gssapiP_krb5.h"
+#include <stdarg.h>
+
+static int
+rotate_left (void *ptr, size_t bufsiz, size_t rc)
+{
+    /* Optimize for receiving.  After some debugging is done, the MIT
+       implementation won't do any rotates on sending, and while
+       debugging, they'll be randomly chosen.
+
+       Return 1 for success, 0 for failure (ENOMEM).  */
+    void *tbuf;
+
+    if (bufsiz == 0)
+	return 1;
+    rc = rc % bufsiz;
+    if (rc == 0)
+	return 1;
+
+    tbuf = malloc(rc);
+    if (tbuf == 0)
+	return 0;
+    memcpy(tbuf, ptr, rc);
+    memmove(ptr, (char *)ptr + rc, bufsiz - rc);
+    memcpy((char *)ptr + bufsiz - rc, tbuf, rc);
+    free(tbuf);
+    return 1;
+}
+
+static const gss_buffer_desc empty_message = { 0, 0 };
+
+#define FLAG_SENDER_IS_ACCEPTOR	0x01
+#define FLAG_WRAP_CONFIDENTIAL	0x02
+#define FLAG_ACCEPTOR_SUBKEY	0x04
+
+krb5_error_code
+gss_krb5int_make_seal_token_v3 (krb5_context context,
+				krb5_gss_ctx_id_rec *ctx,
+				const gss_buffer_desc * message,
+				gss_buffer_t token,
+				int conf_req_flag, int toktype)
+{
+    size_t bufsize = 16;
+    unsigned char *outbuf = 0;
+    krb5_error_code err;
+    int key_usage;
+    unsigned char acceptor_flag;
+    const gss_buffer_desc *message2 = message;
+#ifdef CFX_EXERCISE
+    size_t rrc;
+#endif
+    size_t ec;
+    unsigned short tok_id;
+    krb5_checksum sum;
+    krb5_keyblock *key;
+
+    assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
+    assert(ctx->big_endian == 0);
+
+    acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
+    key_usage = (toktype == KG_TOK_WRAP_MSG
+		 ? (ctx->initiate
+		    ? KG_USAGE_INITIATOR_SEAL
+		    : KG_USAGE_ACCEPTOR_SEAL)
+		 : (ctx->initiate
+		    ? KG_USAGE_INITIATOR_SIGN
+		    : KG_USAGE_ACCEPTOR_SIGN));
+    if (ctx->have_acceptor_subkey) {
+	key = ctx->acceptor_subkey;
+    } else {
+	key = ctx->enc;
+    }
+
+#ifdef CFX_EXERCISE
+    {
+	static int initialized = 0;
+	if (!initialized) {
+	    srand(time(0));
+	    initialized = 1;
+	}
+    }
+#endif
+
+    if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
+	krb5_data plain;
+	krb5_enc_data cipher;
+	size_t ec_max;
+
+	/* 300: Adds some slop.  */
+	if (SIZE_MAX - 300 < message->length)
+	    return ENOMEM;
+	ec_max = SIZE_MAX - message->length - 300;
+	if (ec_max > 0xffff)
+	    ec_max = 0xffff;
+#ifdef CFX_EXERCISE
+	/* For testing only.  For performance, always set ec = 0.  */
+	ec = ec_max & rand();
+#else
+	ec = 0;
+#endif
+	plain.length = message->length + 16 + ec;
+	plain.data = malloc(message->length + 16 + ec);
+	if (plain.data == NULL)
+	    return ENOMEM;
+
+	/* Get size of ciphertext.  */
+	bufsize = 16 + krb5_encrypt_size (plain.length, ctx->enc->enctype);
+	/* Allocate space for header plus encrypted data.  */
+	outbuf = malloc(bufsize);
+	if (outbuf == NULL) {
+	    free(plain.data);
+	    return ENOMEM;
+	}
+
+	/* TOK_ID */
+	store_16_be(0x0504, outbuf);
+	/* flags */
+	outbuf[2] = (acceptor_flag
+		     | (conf_req_flag ? FLAG_WRAP_CONFIDENTIAL : 0)
+		     | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
+	/* filler */
+	outbuf[3] = 0xff;
+	/* EC */
+	store_16_be(ec, outbuf+4);
+	/* RRC */
+	store_16_be(0, outbuf+6);
+	store_64_be(ctx->seq_send, outbuf+8);
+
+	memcpy(plain.data, message->value, message->length);
+	memset(plain.data + message->length, 'x', ec);
+	memcpy(plain.data + message->length + ec, outbuf, 16);
+
+	cipher.ciphertext.data = outbuf + 16;
+	cipher.ciphertext.length = bufsize - 16;
+	cipher.enctype = key->enctype;
+	err = krb5_c_encrypt(context, key, key_usage, 0, &plain, &cipher);
+	zap(plain.data, plain.length);
+	free(plain.data);
+	plain.data = 0;
+	if (err)
+	    goto error;
+
+	/* Now that we know we're returning a valid token....  */
+	ctx->seq_send++;
+
+#ifdef CFX_EXERCISE
+	rrc = rand() & 0xffff;
+	if (rotate_left(outbuf+16, bufsize-16,
+			(bufsize-16) - (rrc % (bufsize - 16))))
+	    store_16_be(rrc, outbuf+6);
+	/* If the rotate fails, don't worry about it.  */
+#endif
+    } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
+	krb5_data plain;
+
+	/* Here, message is the application-supplied data; message2 is
+	   what goes into the output token.  They may be the same, or
+	   message2 may be empty (for MIC).  */
+
+	tok_id = 0x0504;
+
+    wrap_with_checksum:
+	plain.length = message->length + 16;
+	plain.data = malloc(message->length + 16);
+	if (plain.data == NULL)
+	    return ENOMEM;
+
+	if (ctx->cksum_size > 0xffff)
+	    abort();
+
+	bufsize = 16 + message2->length + ctx->cksum_size;
+	outbuf = malloc(bufsize);
+	if (outbuf == NULL) {
+	    free(plain.data);
+	    plain.data = 0;
+	    err = ENOMEM;
+	    goto error;
+	}
+
+	/* TOK_ID */
+	store_16_be(tok_id, outbuf);
+	/* flags */
+	outbuf[2] = (acceptor_flag
+		     | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
+	/* filler */
+	outbuf[3] = 0xff;
+	if (toktype == KG_TOK_WRAP_MSG) {
+	    /* Use 0 for checksum calculation, substitute
+	       checksum length later.  */
+	    /* EC */
+	    store_16_be(0, outbuf+4);
+	    /* RRC */
+	    store_16_be(0, outbuf+6);
+	} else {
+	    /* MIC and DEL store 0xFF in EC and RRC.  */
+	    store_16_be(0xffff, outbuf+4);
+	    store_16_be(0xffff, outbuf+6);
+	}
+	store_64_be(ctx->seq_send, outbuf+8);
+
+	memcpy(plain.data, message->value, message->length);
+	memcpy(plain.data + message->length, outbuf, 16);
+
+	/* Fill in the output token -- data contents, if any, and
+	   space for the checksum.  */
+	if (message2->length)
+	    memcpy(outbuf + 16, message2->value, message2->length);
+
+	sum.contents = outbuf + 16 + message2->length;
+	sum.length = ctx->cksum_size;
+
+	err = krb5_c_make_checksum(context, ctx->cksumtype, key,
+				   key_usage, &plain, &sum);
+	zap(plain.data, plain.length);
+	free(plain.data);
+	plain.data = 0;
+	if (err) {
+	    zap(outbuf,bufsize);
+	    free(outbuf);
+	    goto error;
+	}
+	if (sum.length != ctx->cksum_size)
+	    abort();
+	memcpy(outbuf + 16 + message2->length, sum.contents, ctx->cksum_size);
+	krb5_free_checksum_contents(context, &sum);
+	sum.contents = 0;
+	/* Now that we know we're actually generating the token...  */
+	ctx->seq_send++;
+
+	if (toktype == KG_TOK_WRAP_MSG) {
+#ifdef CFX_EXERCISE
+	    rrc = rand() & 0xffff;
+	    /* If the rotate fails, don't worry about it.  */
+	    if (rotate_left(outbuf+16, bufsize-16,
+			    (bufsize-16) - (rrc % (bufsize - 16))))
+		store_16_be(rrc, outbuf+6);
+#endif
+	    /* Fix up EC field.  */
+	    store_16_be(ctx->cksum_size, outbuf+4);
+	} else {
+	    store_16_be(0xffff, outbuf+6);
+	}
+    } else if (toktype == KG_TOK_MIC_MSG) {
+	tok_id = 0x0404;
+	message2 = &empty_message;
+	goto wrap_with_checksum;
+    } else if (toktype == KG_TOK_DEL_CTX) {
+	tok_id = 0x0405;
+	message = message2 = &empty_message;
+	goto wrap_with_checksum;
+    } else
+	abort();
+
+    token->value = outbuf;
+    token->length = bufsize;
+    return 0;
+
+error:
+    free(outbuf);
+    token->value = NULL;
+    token->length = 0;
+    return err;
+}
+
+/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
+   conf_state is only valid if SEAL. */
+
+OM_uint32
+gss_krb5int_unseal_token_v3(krb5_context *contextptr,
+			    OM_uint32 *minor_status,
+			    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_context context = *contextptr;
+    krb5_data plain;
+    gssint_uint64 seqnum;
+    size_t ec, rrc;
+    int key_usage;
+    unsigned char acceptor_flag;
+    krb5_checksum sum;
+    krb5_error_code err;
+    krb5_boolean valid;
+    krb5_keyblock *key;
+
+    assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
+    assert(ctx->big_endian == 0);
+    assert(ctx->proto == 1);
+
+    if (qop_state)
+	*qop_state = GSS_C_QOP_DEFAULT;
+
+    acceptor_flag = ctx->initiate ? FLAG_SENDER_IS_ACCEPTOR : 0;
+    key_usage = (toktype == KG_TOK_WRAP_MSG
+		 ? (!ctx->initiate
+		    ? KG_USAGE_INITIATOR_SEAL
+		    : KG_USAGE_ACCEPTOR_SEAL)
+		 : (!ctx->initiate
+		    ? KG_USAGE_INITIATOR_SIGN
+		    : KG_USAGE_ACCEPTOR_SIGN));
+
+    /* Oops.  I wrote this code assuming ptr would be at the start of
+       the token header.  */
+    ptr -= 2;
+    bodysize += 2;
+
+    if (bodysize < 16) {
+    defective:
+	*minor_status = 0;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+    if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) {
+	*minor_status = G_BAD_DIRECTION;
+	return GSS_S_BAD_SIG;
+    }
+
+    /* Two things to note here.
+
+       First, we can't really enforce the use of the acceptor's subkey,
+       if we're the acceptor; the initiator may have sent messages
+       before getting the subkey.  We could probably enforce it if
+       we're the initiator.
+
+       Second, if someone tweaks the code to not set the flag telling
+       the krb5 library to generate a new subkey in the AP-REP
+       message, the MIT library may include a subkey anyways --
+       namely, a copy of the AP-REQ subkey, if it was provided.  So
+       the initiator may think we wanted a subkey, and set the flag,
+       even though we weren't trying to set the subkey.  The "other"
+       key, the one not asserted by the acceptor, will have the same
+       value in that case, though, so we can just ignore the flag.  */
+    if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) {
+	key = ctx->acceptor_subkey;
+    } else {
+	key = ctx->enc;
+    }
+
+    if (toktype == KG_TOK_WRAP_MSG) {
+	if (load_16_be(ptr) != 0x0504)
+	    goto defective;
+	if (ptr[3] != 0xff)
+	    goto defective;
+	ec = load_16_be(ptr+4);
+	rrc = load_16_be(ptr+6);
+	seqnum = load_64_be(ptr+8);
+	if (!rotate_left(ptr+16, bodysize-16, rrc)) {
+	no_mem:
+	    *minor_status = ENOMEM;
+	    return GSS_S_FAILURE;
+	}
+	if (ptr[2] & FLAG_WRAP_CONFIDENTIAL) {
+	    /* confidentiality */
+	    krb5_enc_data cipher;
+	    unsigned char *althdr;
+
+	    if (conf_state)
+		*conf_state = 1;
+	    /* Do we have no decrypt_size function?
+
+	       For all current cryptosystems, the ciphertext size will
+	       be larger than the plaintext size.  */
+	    cipher.enctype = key->enctype;
+	    cipher.ciphertext.length = bodysize - 16;
+	    cipher.ciphertext.data = ptr + 16;
+	    plain.length = bodysize - 16;
+	    plain.data = malloc(plain.length);
+	    if (plain.data == NULL)
+		goto no_mem;
+	    err = krb5_c_decrypt(context, key, key_usage, 0,
+				 &cipher, &plain);
+	    if (err) {
+		free(plain.data);
+		goto error;
+	    }
+	    /* Don't use bodysize here!  Use the fact that
+	       cipher.ciphertext.length has been adjusted to the
+	       correct length.  */
+	    althdr = plain.data + plain.length - 16;
+	    if (load_16_be(althdr) != 0x0504
+		|| althdr[2] != ptr[2]
+		|| althdr[3] != ptr[3]
+		|| memcmp(althdr+8, ptr+8, 8)) {
+		free(plain.data);
+		goto defective;
+	    }
+	    message_buffer->value = plain.data;
+	    message_buffer->length = plain.length - ec - 16;
+	    if(message_buffer->length == 0) {
+	      free(message_buffer->value);
+	      message_buffer->value = NULL;
+	    }
+	} else {
+	    /* no confidentiality */
+	    if (conf_state)
+		*conf_state = 0;
+	    if (ec + 16 < ec)
+		/* overflow check */
+		goto defective;
+	    if (ec + 16 > bodysize)
+		goto defective;
+	    /* We have: header | msg | cksum.
+	       We need cksum(msg | header).
+	       Rotate the first two.  */
+	    store_16_be(0, ptr+4);
+	    store_16_be(0, ptr+6);
+	    plain.length = bodysize-ec;
+	    plain.data = ptr;
+	    if (!rotate_left(ptr, bodysize-ec, 16))
+		goto no_mem;
+	    sum.length = ec;
+	    if (sum.length != ctx->cksum_size) {
+		*minor_status = 0;
+		return GSS_S_BAD_SIG;
+	    }
+	    sum.contents = ptr+bodysize-ec;
+	    sum.checksum_type = ctx->cksumtype;
+	    err = krb5_c_verify_checksum(context, key, key_usage,
+					 &plain, &sum, &valid);
+	    if (err)
+		goto error;
+	    if (!valid) {
+		*minor_status = 0;
+		return GSS_S_BAD_SIG;
+	    }
+	    message_buffer->length = plain.length - 16;
+	    message_buffer->value = malloc(message_buffer->length);
+	    if (message_buffer->value == NULL)
+		goto no_mem;
+	    memcpy(message_buffer->value, plain.data, message_buffer->length);
+	}
+	err = g_order_check(&ctx->seqstate, seqnum);
+	*minor_status = 0;
+	return err;
+    } else if (toktype == KG_TOK_MIC_MSG) {
+	/* wrap token, no confidentiality */
+	if (load_16_be(ptr) != 0x0404)
+	    goto defective;
+    verify_mic_1:
+	if (ptr[3] != 0xff)
+	    goto defective;
+	if (load_32_be(ptr+4) != 0xffffffffL)
+	    goto defective;
+	seqnum = load_64_be(ptr+8);
+	plain.length = message_buffer->length + 16;
+	plain.data = malloc(plain.length);
+	if (plain.data == NULL)
+	    goto no_mem;
+	if (message_buffer->length)
+	    memcpy(plain.data, message_buffer->value, message_buffer->length);
+	memcpy(plain.data + message_buffer->length, ptr, 16);
+	sum.length = bodysize - 16;
+	sum.contents = ptr + 16;
+	sum.checksum_type = ctx->cksumtype;
+	err = krb5_c_verify_checksum(context, key, key_usage,
+				     &plain, &sum, &valid);
+	free(plain.data);
+	plain.data = NULL;
+	if (err) {
+	error:
+	    *minor_status = err;
+	    return GSS_S_BAD_SIG; /* XXX */
+	}
+	if (!valid) {
+	    *minor_status = 0;
+	    return GSS_S_BAD_SIG;
+	}
+	err = g_order_check(&ctx->seqstate, seqnum);
+	*minor_status = 0;
+	return err;
+    } else if (toktype == KG_TOK_DEL_CTX) {
+	if (load_16_be(ptr) != 0x0405)
+	    goto defective;
+	message_buffer = &empty_message;
+	goto verify_mic_1;
+    } else {
+	goto defective;
+    }
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/k5unseal.c b/krb5-1-6/src/lib/gssapi/krb5/k5unseal.c
new file mode 100644
index 000000000..8c999868e
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/k5unseal.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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_MEMORY_H
+#include <memory.h>
+#endif
+#include <assert.h>
+
+/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
+   conf_state is only valid if SEAL. */
+
+static OM_uint32
+kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
+	     conf_state, qop_state, toktype)
+    krb5_context context;
+    OM_uint32 *minor_status;
+    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_error_code code;
+    int conflen = 0;
+    int signalg;
+    int sealalg;
+    gss_buffer_desc token;
+    krb5_checksum cksum;
+    krb5_checksum md5cksum;
+    krb5_data plaind;
+    char *data_ptr;
+    krb5_timestamp now;
+    unsigned char *plain;
+    unsigned int cksum_len = 0;
+    size_t plainlen;
+    int direction;
+    krb5_ui_4 seqnum;
+    OM_uint32 retval;
+    size_t sumlen;
+    krb5_keyusage sign_usage = KG_USAGE_SIGN;
+
+    if (toktype == KG_TOK_SEAL_MSG) {
+	message_buffer->length = 0;
+	message_buffer->value = NULL;
+    }
+
+    /* get the sign and seal algorithms */
+
+    signalg = ptr[0] + (ptr[1]<<8);
+    sealalg = ptr[2] + (ptr[3]<<8);
+
+    /* Sanity checks */
+
+    if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) {
+	*minor_status = 0;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if ((toktype != KG_TOK_SEAL_MSG) &&
+	(sealalg != 0xffff)) {
+	*minor_status = 0;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    /* in the current spec, there is only one valid seal algorithm per
+       key type, so a simple comparison is ok */
+
+    if ((toktype == KG_TOK_SEAL_MSG) &&
+	!((sealalg == 0xffff) ||
+	  (sealalg == ctx->sealalg))) {
+	*minor_status = 0;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    /* there are several mappings of seal algorithms to sign algorithms,
+       but few enough that we can try them all. */
+
+    if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
+	(ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
+	(ctx->sealalg == SEAL_ALG_DES3KD &&
+	 signalg != SGN_ALG_HMAC_SHA1_DES3_KD)||
+	(ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 &&
+	signalg != SGN_ALG_HMAC_MD5)) {
+	*minor_status = 0;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    switch (signalg) {
+    case SGN_ALG_DES_MAC_MD5:
+    case SGN_ALG_MD2_5:
+    case SGN_ALG_HMAC_MD5:
+	cksum_len = 8;
+	if (toktype != KG_TOK_SEAL_MSG)
+	  sign_usage = 15;
+	    break;
+    case SGN_ALG_3:
+	cksum_len = 16;
+	break;
+    case SGN_ALG_HMAC_SHA1_DES3_KD:
+	cksum_len = 20;
+	break;
+    default:
+	*minor_status = 0;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    /* get the token parameters */
+
+    if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction,
+			       &seqnum))) {
+	*minor_status = code;
+	return(GSS_S_BAD_SIG);
+    }
+
+    /* decode the message, if SEAL */
+
+    if (toktype == KG_TOK_SEAL_MSG) {
+	int tmsglen = bodysize-(14+cksum_len);
+	if (sealalg != 0xffff) {
+	    if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
+		*minor_status = ENOMEM;
+		return(GSS_S_FAILURE);
+	    }
+	    if (ctx->enc->enctype == ENCTYPE_ARCFOUR_HMAC) {
+	      unsigned char bigend_seqnum[4];
+	      krb5_keyblock *enc_key;
+	      int i;
+	      bigend_seqnum[0] = (seqnum>>24) & 0xff;
+	      bigend_seqnum[1] = (seqnum>>16) & 0xff;
+	      bigend_seqnum[2] = (seqnum>>8) & 0xff;
+	      bigend_seqnum[3] = seqnum & 0xff;
+	      code = krb5_copy_keyblock (context, ctx->enc, &enc_key);
+	      if (code)
+		{
+		  xfree(plain);
+		  *minor_status = code;
+		  return(GSS_S_FAILURE);
+		}
+
+	      assert (enc_key->length == 16);
+	      for (i = 0; i <= 15; i++)
+		((char *) enc_key->contents)[i] ^=0xf0;
+	      code = kg_arcfour_docrypt (enc_key, 0,
+					 &bigend_seqnum[0], 4, 
+					 ptr+14+cksum_len, tmsglen,
+					 plain);
+	      krb5_free_keyblock (context, enc_key);
+	    } else {
+	      code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL,
+				ptr+14+cksum_len, plain, tmsglen);
+		}
+	    if (code) {
+	      		xfree(plain);
+		*minor_status = code;
+		return(GSS_S_FAILURE);
+	    }
+	} else {
+	    plain = ptr+14+cksum_len;
+	}
+
+	plainlen = tmsglen;
+
+	if ((sealalg == 0xffff) && ctx->big_endian) {
+	    token.length = tmsglen;
+	} else {
+	    conflen = kg_confounder_size(context, ctx->enc);
+	    token.length = tmsglen - conflen - plain[tmsglen-1];
+	}
+
+	if (token.length) {
+	    if ((token.value = (void *) xmalloc(token.length)) == NULL) {
+		if (sealalg != 0xffff)
+		    xfree(plain);
+		*minor_status = ENOMEM;
+		return(GSS_S_FAILURE);
+	    }
+	    memcpy(token.value, plain+conflen, token.length);
+	} else {
+	    token.value = NULL;
+	}
+    } else if (toktype == KG_TOK_SIGN_MSG) {
+	token = *message_buffer;
+	plain = token.value;
+	plainlen = token.length;
+    } else {
+	token.length = 0;
+	token.value = NULL;
+	plain = token.value;
+	plainlen = token.length;
+    }
+
+    /* compute the checksum of the message */
+
+    /* initialize the the cksum */
+    switch (signalg) {
+    case SGN_ALG_DES_MAC_MD5:
+    case SGN_ALG_MD2_5:
+    case SGN_ALG_DES_MAC:
+    case SGN_ALG_3:
+	md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
+	break;
+    case SGN_ALG_HMAC_MD5:
+      md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+      break;
+    case SGN_ALG_HMAC_SHA1_DES3_KD:
+	md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
+	break;
+    default:
+	abort ();
+    }
+
+    code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
+    if (code)
+	return(code);
+    md5cksum.length = sumlen;
+
+    switch (signalg) {
+    case SGN_ALG_DES_MAC_MD5:
+    case SGN_ALG_3:
+	/* compute the checksum of the message */
+
+	/* 8 = bytes of token body to be checksummed according to spec */
+
+	if (! (data_ptr = (void *)
+	       xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) {
+	    if (sealalg != 0xffff)
+		xfree(plain);
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = ENOMEM;
+	    return(GSS_S_FAILURE);
+	}
+
+	(void) memcpy(data_ptr, ptr-2, 8);
+
+	if (ctx->big_endian)
+	    (void) memcpy(data_ptr+8, token.value, token.length);
+	else
+	    (void) memcpy(data_ptr+8, plain, plainlen);
+
+	plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
+	plaind.data = data_ptr;
+	code = krb5_c_make_checksum(context, md5cksum.checksum_type,
+				    ctx->seq, sign_usage,
+				    &plaind, &md5cksum);
+	xfree(data_ptr);
+
+	if (code) {
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = code;
+	    return(GSS_S_FAILURE);
+	}
+
+	if ((code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL,
+			       (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ?
+				ctx->seq->contents : NULL),
+			       md5cksum.contents, md5cksum.contents, 16))) {
+	    krb5_free_checksum_contents(context, &md5cksum);
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = code;
+	    return GSS_S_FAILURE;
+	}
+
+	if (signalg == 0)
+	    cksum.length = 8;
+	else
+	    cksum.length = 16;
+	cksum.contents = md5cksum.contents + 16 - cksum.length;
+
+	code = memcmp(cksum.contents, ptr+14, cksum.length);
+	break;
+
+    case SGN_ALG_MD2_5:
+	if (!ctx->seed_init &&
+	    (code = kg_make_seed(context, ctx->subkey, ctx->seed))) {
+	    krb5_free_checksum_contents(context, &md5cksum);
+	    if (sealalg != 0xffff)
+		xfree(plain);
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = code;
+	    return GSS_S_FAILURE;
+	}
+
+	if (! (data_ptr = (void *)
+	       xmalloc(sizeof(ctx->seed) + 8 +
+		       (ctx->big_endian ? token.length : plainlen)))) {
+	    krb5_free_checksum_contents(context, &md5cksum);
+	    if (sealalg == 0)
+		xfree(plain);
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = ENOMEM;
+	    return(GSS_S_FAILURE);
+	}
+	(void) memcpy(data_ptr, ptr-2, 8);
+	(void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed));
+	if (ctx->big_endian)
+	    (void) memcpy(data_ptr+8+sizeof(ctx->seed),
+			  token.value, token.length);
+	else
+	    (void) memcpy(data_ptr+8+sizeof(ctx->seed),
+			  plain, plainlen);
+	plaind.length = 8 + sizeof(ctx->seed) +
+	    (ctx->big_endian ? token.length : plainlen);
+	plaind.data = data_ptr;
+	krb5_free_checksum_contents(context, &md5cksum);
+	code = krb5_c_make_checksum(context, md5cksum.checksum_type,
+				    ctx->seq, sign_usage,
+				    &plaind, &md5cksum);
+	xfree(data_ptr);
+
+	if (code) {
+	    if (sealalg == 0)
+		xfree(plain);
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = code;
+	    return(GSS_S_FAILURE);
+	}
+
+	code = memcmp(md5cksum.contents, ptr+14, 8);
+	/* Falls through to defective-token??  */
+
+    default:
+	*minor_status = 0;
+	return(GSS_S_DEFECTIVE_TOKEN);
+
+    case SGN_ALG_HMAC_SHA1_DES3_KD:
+    case SGN_ALG_HMAC_MD5:
+	/* compute the checksum of the message */
+
+	/* 8 = bytes of token body to be checksummed according to spec */
+
+	if (! (data_ptr = (void *)
+	       xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) {
+	    if (sealalg != 0xffff)
+		xfree(plain);
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = ENOMEM;
+	    return(GSS_S_FAILURE);
+	}
+
+	(void) memcpy(data_ptr, ptr-2, 8);
+
+	if (ctx->big_endian)
+	    (void) memcpy(data_ptr+8, token.value, token.length);
+	else
+	    (void) memcpy(data_ptr+8, plain, plainlen);
+
+	plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
+	plaind.data = data_ptr;
+	code = krb5_c_make_checksum(context, md5cksum.checksum_type,
+				    ctx->seq, sign_usage,
+				    &plaind, &md5cksum);
+	xfree(data_ptr);
+
+	if (code) {
+	    if (toktype == KG_TOK_SEAL_MSG)
+		xfree(token.value);
+	    *minor_status = code;
+	    return(GSS_S_FAILURE);
+	}
+
+	code = memcmp(md5cksum.contents, ptr+14, cksum_len);
+	break;
+    }
+
+    krb5_free_checksum_contents(context, &md5cksum);
+    if (sealalg != 0xffff)
+	xfree(plain);
+
+    /* compare the computed checksum against the transmitted checksum */
+
+    if (code) {
+	if (toktype == KG_TOK_SEAL_MSG)
+	    xfree(token.value);
+	*minor_status = 0;
+	return(GSS_S_BAD_SIG);
+    }
+
+
+    /* it got through unscathed.  Make sure the context is unexpired */
+
+    if (toktype == KG_TOK_SEAL_MSG)
+	*message_buffer = token;
+
+    if (conf_state)
+	*conf_state = (sealalg != 0xffff);
+
+    if (qop_state)
+	*qop_state = GSS_C_QOP_DEFAULT;
+
+    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 && direction != 0xff) ||
+	(!ctx->initiate && direction != 0)) {
+	if (toktype == KG_TOK_SEAL_MSG) {
+	    xfree(token.value);
+	    message_buffer->value = NULL;
+	    message_buffer->length = 0;
+	}
+	*minor_status = G_BAD_DIRECTION;
+	return(GSS_S_BAD_SIG);
+    }
+
+    retval = g_order_check(&(ctx->seqstate), seqnum);
+
+    /* success or ordering violation */
+
+    *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(minor_status, context_handle, input_token_buffer,
+	  message_buffer, conf_state, qop_state, toktype)
+    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;
+    unsigned int bodysize;
+    int err;
+    int toktype2;
+
+    /* 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->proto)
+	switch (toktype) {
+	case KG_TOK_SIGN_MSG:
+	    toktype2 = 0x0404;
+	    break;
+	case KG_TOK_SEAL_MSG:
+	    toktype2 = 0x0504;
+	    break;
+	case KG_TOK_DEL_CTX:
+	    toktype2 = 0x0405;
+	    break;
+	default:
+	    toktype2 = toktype;
+	    break;
+	}
+    else
+	toktype2 = toktype;
+    err = g_verify_token_header(ctx->mech_used,
+				&bodysize, &ptr, toktype2,
+				input_token_buffer->length,
+				!ctx->proto);
+    if (err) {
+	*minor_status = err;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (ctx->proto == 0)
+	return kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize,
+			    message_buffer, conf_state, qop_state,
+			    toktype);
+    else
+	return gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx,
+					   ptr, bodysize, message_buffer,
+					   conf_state, qop_state, toktype);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/krb5_gss_glue.c b/krb5-1-6/src/lib/gssapi/krb5/krb5_gss_glue.c
new file mode 100644
index 000000000..77cf0da5e
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/krb5_gss_glue.c
@@ -0,0 +1,1105 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_krb5.h"
+#include "mglueP.h"
+
+/** mechglue wrappers **/
+
+static OM_uint32 k5glue_acquire_cred
+(void *, OM_uint32*,       /* minor_status */
+            gss_name_t,       /* desired_name */
+            OM_uint32,        /* time_req */
+            gss_OID_set,      /* desired_mechs */
+            gss_cred_usage_t, /* cred_usage */
+            gss_cred_id_t*,   /* output_cred_handle */
+            gss_OID_set*,     /* actual_mechs */
+            OM_uint32*        /* time_rec */
+           );
+
+static OM_uint32 k5glue_release_cred
+(void *, OM_uint32*,       /* minor_status */
+            gss_cred_id_t*    /* cred_handle */
+           );
+
+static OM_uint32 k5glue_init_sec_context
+(void *, OM_uint32*,       /* minor_status */
+            gss_cred_id_t,    /* claimant_cred_handle */
+            gss_ctx_id_t*,    /* context_handle */
+            gss_name_t,       /* target_name */
+            gss_OID,          /* mech_type */
+            OM_uint32,        /* req_flags */
+            OM_uint32,        /* time_req */
+            gss_channel_bindings_t,
+                              /* input_chan_bindings */
+            gss_buffer_t,     /* input_token */
+            gss_OID*,         /* actual_mech_type */
+            gss_buffer_t,     /* output_token */
+            OM_uint32*,       /* ret_flags */
+            OM_uint32*        /* time_rec */
+           );
+
+static OM_uint32 k5glue_accept_sec_context
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t*,    /* context_handle */
+            gss_cred_id_t,    /* verifier_cred_handle */
+            gss_buffer_t,     /* input_token_buffer */
+            gss_channel_bindings_t,
+                              /* input_chan_bindings */
+            gss_name_t*,      /* src_name */
+            gss_OID*,         /* mech_type */
+            gss_buffer_t,     /* output_token */
+            OM_uint32*,       /* ret_flags */
+            OM_uint32*,       /* time_rec */
+            gss_cred_id_t*    /* delegated_cred_handle */
+           );
+
+static OM_uint32 k5glue_process_context_token
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            gss_buffer_t      /* token_buffer */
+           );
+
+static OM_uint32 k5glue_delete_sec_context
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t*,    /* context_handle */
+            gss_buffer_t      /* output_token */
+           );
+
+static OM_uint32 k5glue_context_time
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            OM_uint32*        /* time_rec */
+           );
+
+static OM_uint32 k5glue_sign
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            int,              /* qop_req */
+            gss_buffer_t,     /* message_buffer */
+            gss_buffer_t      /* message_token */
+           );
+
+static OM_uint32 k5glue_verify
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            gss_buffer_t,     /* message_buffer */
+            gss_buffer_t,     /* token_buffer */
+            int*              /* qop_state */
+           );
+
+static OM_uint32 k5glue_seal
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            int,              /* conf_req_flag */
+            int,              /* qop_req */
+            gss_buffer_t,     /* input_message_buffer */
+            int*,             /* conf_state */
+            gss_buffer_t      /* output_message_buffer */
+           );
+
+static OM_uint32 k5glue_unseal
+(void *, OM_uint32*,       /* minor_status */
+            gss_ctx_id_t,     /* context_handle */
+            gss_buffer_t,     /* input_message_buffer */
+            gss_buffer_t,     /* output_message_buffer */
+            int*,             /* conf_state */
+            int*              /* qop_state */
+           );
+
+static OM_uint32 k5glue_display_status
+(void *, OM_uint32*,       /* minor_status */
+            OM_uint32,        /* status_value */
+            int,              /* status_type */
+            gss_OID,          /* mech_type */
+            OM_uint32*,       /* message_context */
+            gss_buffer_t      /* status_string */
+           );
+
+static OM_uint32 k5glue_indicate_mechs
+(void *, OM_uint32*,       /* minor_status */
+            gss_OID_set*      /* mech_set */
+           );
+
+static OM_uint32 k5glue_compare_name
+(void *, OM_uint32*,       /* minor_status */
+            gss_name_t,       /* name1 */
+            gss_name_t,       /* name2 */
+            int*              /* name_equal */
+           );
+
+static OM_uint32 k5glue_display_name
+(void *, OM_uint32*,      /* minor_status */
+            gss_name_t,      /* input_name */
+            gss_buffer_t,    /* output_name_buffer */
+            gss_OID*         /* output_name_type */
+           );
+
+static OM_uint32 k5glue_import_name
+(void *, OM_uint32*,       /* minor_status */
+            gss_buffer_t,     /* input_name_buffer */
+            gss_OID,          /* input_name_type */
+            gss_name_t*       /* output_name */
+           );
+
+static OM_uint32 k5glue_release_name
+(void *, OM_uint32*,       /* minor_status */
+            gss_name_t*       /* input_name */
+           );
+
+static OM_uint32 k5glue_inquire_cred
+(void *, OM_uint32 *,      /* minor_status */
+            gss_cred_id_t,    /* cred_handle */
+            gss_name_t *,     /* name */
+            OM_uint32 *,      /* lifetime */
+            gss_cred_usage_t*,/* cred_usage */
+            gss_OID_set *     /* mechanisms */
+           );
+
+static OM_uint32 k5glue_inquire_context
+(void *, OM_uint32*,       /* minor_status */
+	    gss_ctx_id_t,     /* context_handle */
+	    gss_name_t*,      /* initiator_name */
+	    gss_name_t*,      /* acceptor_name */
+	    OM_uint32*,       /* lifetime_rec */
+	    gss_OID*,         /* mech_type */
+	    OM_uint32*,       /* ret_flags */
+	    int*,             /* locally_initiated */
+	    int*              /* open */
+	   );
+
+#if 0
+/* New V2 entry points */
+static OM_uint32 k5glue_get_mic
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_qop_t,			/* qop_req */
+	    gss_buffer_t,		/* message_buffer */
+	    gss_buffer_t		/* message_token */
+	   );
+
+static OM_uint32 k5glue_verify_mic
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_buffer_t,		/* message_buffer */
+	    gss_buffer_t,		/* message_token */
+	    gss_qop_t *			/* qop_state */
+	   );
+
+static OM_uint32 k5glue_wrap
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    int,			/* conf_req_flag */
+	    gss_qop_t,			/* qop_req */
+	    gss_buffer_t,		/* input_message_buffer */
+	    int *,			/* conf_state */
+	    gss_buffer_t		/* output_message_buffer */
+	   );
+
+static OM_uint32 k5glue_unwrap
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    gss_buffer_t,		/* input_message_buffer */
+	    gss_buffer_t,		/* output_message_buffer */
+	    int *,			/* conf_state */
+	    gss_qop_t *			/* qop_state */
+	   );
+#endif
+
+static OM_uint32 k5glue_wrap_size_limit
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t,		/* context_handle */
+	    int,			/* conf_req_flag */
+	    gss_qop_t,			/* qop_req */
+	    OM_uint32,			/* req_output_size */
+	    OM_uint32 *			/* max_input_size */
+	   );
+
+#if 0
+static OM_uint32 k5glue_import_name_object
+(void *, OM_uint32 *,		/* minor_status */
+	    void *,			/* input_name */
+	    gss_OID,			/* input_name_type */
+	    gss_name_t *		/* output_name */
+	   );
+
+static OM_uint32 k5glue_export_name_object
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_name_t,			/* input_name */
+	    gss_OID,			/* desired_name_type */
+	    void * *			/* output_name */
+	   );
+#endif
+
+static OM_uint32 k5glue_add_cred
+(void *, 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 */
+	   );
+
+static OM_uint32 k5glue_inquire_cred_by_mech
+(void *, OM_uint32  *,		/* minor_status */
+	    gss_cred_id_t,		/* cred_handle */
+	    gss_OID,			/* mech_type */
+	    gss_name_t *,		/* name */
+	    OM_uint32 *,		/* initiator_lifetime */
+	    OM_uint32 *,		/* acceptor_lifetime */
+	    gss_cred_usage_t * 		/* cred_usage */
+	   );
+
+static OM_uint32 k5glue_export_sec_context
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_ctx_id_t *,		/* context_handle */
+	    gss_buffer_t		/* interprocess_token */
+	    );
+
+static OM_uint32 k5glue_import_sec_context
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_buffer_t,		/* interprocess_token */
+	    gss_ctx_id_t *		/* context_handle */
+	    );
+
+krb5_error_code k5glue_ser_init(krb5_context);
+
+static OM_uint32 k5glue_internal_release_oid
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_OID *			/* oid */
+	   );
+
+static OM_uint32 k5glue_inquire_names_for_mech
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_OID,			/* mechanism */
+	    gss_OID_set *		/* name_types */
+	   );
+
+#if 0
+static OM_uint32 k5glue_canonicalize_name
+(void *, OM_uint32  *,		/* minor_status */
+	    const gss_name_t,		/* input_name */
+	    const gss_OID,		/* mech_type */
+	    gss_name_t *		/* output_name */
+	 );
+#endif
+
+static OM_uint32 k5glue_export_name
+(void *, OM_uint32  *,		/* minor_status */
+	    const gss_name_t,		/* input_name */
+	    gss_buffer_t		/* exported_name */
+	 );
+
+#if 0
+static OM_uint32 k5glue_duplicate_name
+(void *, OM_uint32  *,		/* minor_status */
+	    const gss_name_t,		/* input_name */
+	    gss_name_t *		/* dest_name */
+	 );
+#endif
+
+#if 0
+static OM_uint32 k5glue_validate_cred
+(void *, OM_uint32 *,		/* minor_status */
+	    gss_cred_id_t		/* cred */
+         );
+#endif
+
+/*
+ * The krb5 mechanism provides two mech OIDs; use this initializer to
+ * ensure that both dispatch tables contain identical function
+ * pointers.
+ */
+#define KRB5_GSS_CONFIG_INIT				\
+    NULL,						\
+    k5glue_acquire_cred,				\
+    k5glue_release_cred,				\
+    k5glue_init_sec_context,				\
+    k5glue_accept_sec_context,				\
+    k5glue_process_context_token,			\
+    k5glue_delete_sec_context,				\
+    k5glue_context_time,				\
+    k5glue_sign,					\
+    k5glue_verify,					\
+    k5glue_seal,					\
+    k5glue_unseal,					\
+    k5glue_display_status,				\
+    k5glue_indicate_mechs,				\
+    k5glue_compare_name,				\
+    k5glue_display_name,				\
+    k5glue_import_name,					\
+    k5glue_release_name,				\
+    k5glue_inquire_cred,				\
+    k5glue_add_cred,					\
+    k5glue_export_sec_context,				\
+    k5glue_import_sec_context,				\
+    k5glue_inquire_cred_by_mech,			\
+    k5glue_inquire_names_for_mech,			\
+    k5glue_inquire_context,				\
+    k5glue_internal_release_oid,			\
+    k5glue_wrap_size_limit,				\
+    k5glue_export_name,					\
+    NULL			/* store_cred */
+
+static struct gss_config krb5_mechanism = {
+    100, "kerberos_v5",
+    { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
+    KRB5_GSS_CONFIG_INIT
+};
+
+static struct gss_config krb5_mechanism_old = {
+    200, "kerberos_v5 (pre-RFC OID)",
+    { GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID },
+    KRB5_GSS_CONFIG_INIT
+};
+
+static struct gss_config krb5_mechanism_wrong = {
+    300, "kerberos_v5 (wrong OID)",
+    { GSS_MECH_KRB5_WRONG_OID_LENGTH, GSS_MECH_KRB5_WRONG_OID },
+    KRB5_GSS_CONFIG_INIT
+};
+
+static gss_mechanism krb5_mech_configs[] = {
+    &krb5_mechanism, &krb5_mechanism_old, &krb5_mechanism_wrong, NULL
+};
+
+#ifdef MS_BUG_TEST
+static gss_mechanism krb5_mech_configs_hack[] = {
+    &krb5_mechanism, &krb5_mechanism_old, NULL
+};
+#endif
+
+#if 1
+#define gssint_get_mech_configs krb5_gss_get_mech_configs
+#endif
+
+gss_mechanism *
+gssint_get_mech_configs(void)
+{
+#ifdef MS_BUG_TEST
+    char *envstr = getenv("MS_FORCE_NO_MSOID");
+
+    if (envstr != NULL && strcmp(envstr, "1") == 0) {
+	return krb5_mech_configs_hack;
+    }
+#endif
+    return krb5_mech_configs;
+}
+
+static OM_uint32
+k5glue_accept_sec_context(ctx, minor_status, context_handle, verifier_cred_handle,
+		       input_token, input_chan_bindings, src_name, mech_type, 
+		       output_token, ret_flags, time_rec, delegated_cred_handle)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t *context_handle;
+     gss_cred_id_t verifier_cred_handle;
+     gss_buffer_t input_token;
+     gss_channel_bindings_t input_chan_bindings;
+     gss_name_t *src_name;
+     gss_OID *mech_type;
+     gss_buffer_t output_token;
+     OM_uint32 *ret_flags;
+     OM_uint32 *time_rec;
+     gss_cred_id_t *delegated_cred_handle;
+{
+   return(krb5_gss_accept_sec_context(minor_status,
+				      context_handle,
+				      verifier_cred_handle,
+				      input_token,
+				      input_chan_bindings,
+				      src_name,
+				      mech_type,
+				      output_token,
+				      ret_flags,
+				      time_rec,
+				      delegated_cred_handle));
+}
+
+static OM_uint32
+k5glue_acquire_cred(ctx, minor_status, desired_name, time_req, desired_mechs,
+		 cred_usage, output_cred_handle, actual_mechs, time_rec)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_name_t desired_name;
+     OM_uint32 time_req;
+     gss_OID_set desired_mechs;
+     gss_cred_usage_t cred_usage;
+     gss_cred_id_t *output_cred_handle;
+     gss_OID_set *actual_mechs;
+     OM_uint32 *time_rec;
+{
+   return(krb5_gss_acquire_cred(minor_status,
+				desired_name,
+				time_req,
+				desired_mechs,
+				cred_usage,
+				output_cred_handle,
+				actual_mechs,
+				time_rec));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_add_cred(ctx, 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)
+    void *ctx;
+    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;
+{
+    return(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));
+}
+
+#if 0
+/* V2 */
+static OM_uint32
+k5glue_add_oid_set_member(ctx, minor_status, member_oid, oid_set)
+    void *ctx;
+    OM_uint32	 *minor_status;
+    gss_OID	member_oid;
+    gss_OID_set	 *oid_set;
+{
+    return(generic_gss_add_oid_set_member(minor_status, member_oid, oid_set));
+}
+#endif
+
+static OM_uint32
+k5glue_compare_name(ctx, minor_status, name1, name2, name_equal)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_name_t name1;
+     gss_name_t name2;
+     int *name_equal;
+{
+   return(krb5_gss_compare_name(minor_status, name1,
+				name2, name_equal));
+}
+
+static OM_uint32
+k5glue_context_time(ctx, minor_status, context_handle, time_rec)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     OM_uint32 *time_rec;
+{
+   return(krb5_gss_context_time(minor_status, context_handle,
+				time_rec));
+}
+
+#if 0
+/* V2 */
+static OM_uint32
+k5glue_create_empty_oid_set(ctx, minor_status, oid_set)
+    void *ctx;
+    OM_uint32	 *minor_status;
+    gss_OID_set	 *oid_set;
+{
+    return(generic_gss_create_empty_oid_set(minor_status, oid_set));
+}
+#endif
+
+static OM_uint32
+k5glue_delete_sec_context(ctx, minor_status, context_handle, output_token)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t *context_handle;
+     gss_buffer_t output_token;
+{
+   return(krb5_gss_delete_sec_context(minor_status,
+				      context_handle, output_token));
+}
+
+static OM_uint32
+k5glue_display_name(ctx, minor_status, input_name, output_name_buffer, output_name_type)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_name_t input_name;
+     gss_buffer_t output_name_buffer;
+     gss_OID *output_name_type;
+{
+   return(krb5_gss_display_name(minor_status, input_name,
+				output_name_buffer, output_name_type));
+}
+
+static OM_uint32
+k5glue_display_status(ctx, minor_status, status_value, status_type,
+		   mech_type, message_context, status_string)
+    void *ctx;
+     OM_uint32 *minor_status;
+     OM_uint32 status_value;
+     int status_type;
+     gss_OID mech_type;
+     OM_uint32 *message_context;
+     gss_buffer_t status_string;
+{
+   return(krb5_gss_display_status(minor_status, status_value,
+				  status_type, mech_type, message_context,
+				  status_string));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_export_sec_context(ctx, minor_status, context_handle, interprocess_token)
+    void *ctx;
+     OM_uint32		 *minor_status;
+     gss_ctx_id_t	 *context_handle;
+     gss_buffer_t	interprocess_token;
+{
+   return(krb5_gss_export_sec_context(minor_status,
+				      context_handle,
+				      interprocess_token));
+}
+
+#if 0
+/* V2 */
+static OM_uint32
+k5glue_get_mic(ctx, minor_status, context_handle, qop_req,
+	    message_buffer, message_token)
+    void *ctx;
+     OM_uint32		 *minor_status;
+     gss_ctx_id_t	context_handle;
+     gss_qop_t		qop_req;
+     gss_buffer_t	message_buffer;
+     gss_buffer_t	message_token;
+{
+    return(krb5_gss_get_mic(minor_status, context_handle,
+			    qop_req, message_buffer, message_token));
+}
+#endif
+
+static OM_uint32
+k5glue_import_name(ctx, minor_status, input_name_buffer, input_name_type, output_name)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_buffer_t input_name_buffer;
+     gss_OID input_name_type;
+     gss_name_t *output_name;
+{
+#if 0
+    OM_uint32 err;
+    err = gssint_initialize_library();
+    if (err) {
+	*minor_status = err;
+	return GSS_S_FAILURE;
+    }
+#endif
+    return(krb5_gss_import_name(minor_status, input_name_buffer,
+				input_name_type, output_name));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_import_sec_context(ctx, minor_status, interprocess_token, context_handle)
+    void *ctx;
+     OM_uint32		 *minor_status;
+     gss_buffer_t	interprocess_token;
+     gss_ctx_id_t	 *context_handle;
+{
+   return(krb5_gss_import_sec_context(minor_status,
+				      interprocess_token,
+				      context_handle));
+}
+
+static OM_uint32
+k5glue_indicate_mechs(ctx, minor_status, mech_set)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_OID_set *mech_set;
+{
+   return(krb5_gss_indicate_mechs(minor_status, mech_set));
+}
+
+static OM_uint32
+k5glue_init_sec_context(ctx, minor_status, claimant_cred_handle, context_handle,
+		     target_name, mech_type, req_flags, time_req,
+		     input_chan_bindings, input_token, actual_mech_type,
+		     output_token, ret_flags, time_rec)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_cred_id_t claimant_cred_handle;
+     gss_ctx_id_t *context_handle;
+     gss_name_t target_name;
+     gss_OID mech_type;
+     OM_uint32 req_flags;
+     OM_uint32 time_req;
+     gss_channel_bindings_t input_chan_bindings;
+     gss_buffer_t input_token;
+     gss_OID *actual_mech_type;
+     gss_buffer_t output_token;
+     OM_uint32 *ret_flags;
+     OM_uint32 *time_rec;
+{
+   return(krb5_gss_init_sec_context(minor_status,
+				    claimant_cred_handle, context_handle,
+				    target_name, mech_type, req_flags,
+				    time_req, input_chan_bindings, input_token,
+				    actual_mech_type, output_token, ret_flags,
+				    time_rec));
+}
+
+static OM_uint32
+k5glue_inquire_context(ctx, minor_status, context_handle, initiator_name, acceptor_name,
+		    lifetime_rec, mech_type, ret_flags,
+		    locally_initiated, open)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_name_t *initiator_name;
+     gss_name_t *acceptor_name;
+     OM_uint32 *lifetime_rec;
+     gss_OID *mech_type;
+     OM_uint32 *ret_flags;
+     int *locally_initiated;
+     int *open;
+{
+   return(krb5_gss_inquire_context(minor_status, context_handle,
+				   initiator_name, acceptor_name, lifetime_rec,
+				   mech_type, ret_flags, locally_initiated,
+				   open));
+}
+
+static OM_uint32
+k5glue_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
+		 cred_usage, mechanisms)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_cred_id_t cred_handle;
+     gss_name_t *name;
+     OM_uint32 *lifetime_ret;
+     gss_cred_usage_t *cred_usage;
+     gss_OID_set *mechanisms;
+{
+   return(krb5_gss_inquire_cred(minor_status, cred_handle,
+				name, lifetime_ret, cred_usage, mechanisms));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_inquire_cred_by_mech(ctx, minor_status, cred_handle, mech_type, name,
+			 initiator_lifetime, acceptor_lifetime, cred_usage)
+    void *ctx;
+     OM_uint32		 *minor_status;
+     gss_cred_id_t	cred_handle;
+     gss_OID		mech_type;
+     gss_name_t		 *name;
+     OM_uint32		 *initiator_lifetime;
+     OM_uint32		 *acceptor_lifetime;
+     gss_cred_usage_t	 *cred_usage;
+{
+   return(krb5_gss_inquire_cred_by_mech(minor_status, cred_handle,
+					mech_type, name, initiator_lifetime,
+					acceptor_lifetime, cred_usage));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_inquire_names_for_mech(ctx, minor_status, mechanism, name_types)
+    void *ctx;
+    OM_uint32	 *minor_status;
+    gss_OID	mechanism;
+    gss_OID_set	 *name_types;
+{
+    return(krb5_gss_inquire_names_for_mech(minor_status,
+					   mechanism,
+					   name_types));
+}
+
+#if 0
+/* V2 */
+static OM_uint32
+k5glue_oid_to_str(ctx, minor_status, oid, oid_str)
+    void *ctx;
+    OM_uint32		 *minor_status;
+    gss_OID		oid;
+    gss_buffer_t	oid_str;
+{
+    return(generic_gss_oid_to_str(minor_status, oid, oid_str));
+}
+#endif
+
+static OM_uint32
+k5glue_process_context_token(ctx, minor_status, context_handle, token_buffer)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_buffer_t token_buffer;
+{
+   return(krb5_gss_process_context_token(minor_status,
+					 context_handle, token_buffer));
+}
+
+static OM_uint32
+k5glue_release_cred(ctx, minor_status, cred_handle)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_cred_id_t *cred_handle;
+{
+   return(krb5_gss_release_cred(minor_status, cred_handle));
+}
+
+static OM_uint32
+k5glue_release_name(ctx, minor_status, input_name)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_name_t *input_name;
+{
+   return(krb5_gss_release_name(minor_status, input_name));
+}
+
+#if 0
+static OM_uint32
+k5glue_release_buffer(ctx, minor_status, buffer)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_buffer_t buffer;
+{
+   return(generic_gss_release_buffer(minor_status,
+				     buffer));
+}
+#endif
+
+/* V2 */
+static OM_uint32
+k5glue_internal_release_oid(ctx, minor_status, oid)
+    void *ctx;
+     OM_uint32	 *minor_status;
+     gss_OID	 *oid;
+{
+    return(krb5_gss_internal_release_oid(minor_status, oid));
+}
+
+#if 0
+static OM_uint32
+k5glue_release_oid_set(ctx, minor_status, set)
+    void *ctx;
+     OM_uint32 * minor_status;
+     gss_OID_set *set;
+{
+   return(generic_gss_release_oid_set(minor_status, set));
+}
+#endif
+
+/* V1 only */
+static OM_uint32
+k5glue_seal(ctx, minor_status, context_handle, conf_req_flag, qop_req,
+	 input_message_buffer, conf_state, output_message_buffer)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     int conf_req_flag;
+     int qop_req;
+     gss_buffer_t input_message_buffer;
+     int *conf_state;
+     gss_buffer_t output_message_buffer;
+{
+   return(krb5_gss_seal(minor_status, context_handle,
+			conf_req_flag, qop_req, input_message_buffer,
+			conf_state, output_message_buffer));
+}
+
+static OM_uint32
+k5glue_sign(ctx, minor_status, context_handle,
+	      qop_req, message_buffer, 
+	      message_token)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     int qop_req;
+     gss_buffer_t message_buffer;
+     gss_buffer_t message_token;
+{
+   return(krb5_gss_sign(minor_status, context_handle,
+			qop_req, message_buffer, message_token));
+}
+
+#if 0
+/* V2 */
+static OM_uint32
+k5glue_verify_mic(ctx, minor_status, context_handle,
+	       message_buffer, token_buffer, qop_state)
+    void *ctx;
+     OM_uint32		 *minor_status;
+     gss_ctx_id_t	context_handle;
+     gss_buffer_t	message_buffer;
+     gss_buffer_t	token_buffer;
+     gss_qop_t		 *qop_state;
+{
+    return(krb5_gss_verify_mic(minor_status, context_handle,
+			       message_buffer, token_buffer, qop_state));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_wrap(ctx, minor_status, context_handle, conf_req_flag, qop_req,
+	 input_message_buffer, conf_state, output_message_buffer)
+    void *ctx;
+    OM_uint32		 *minor_status;
+    gss_ctx_id_t	context_handle;
+    int			conf_req_flag;
+    gss_qop_t		qop_req;
+    gss_buffer_t	input_message_buffer;
+    int			 *conf_state;
+    gss_buffer_t	output_message_buffer;
+{
+    return(krb5_gss_wrap(minor_status, context_handle, conf_req_flag, qop_req,
+			 input_message_buffer, conf_state,
+			 output_message_buffer));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_str_to_oid(ctx, minor_status, oid_str, oid)
+    void *ctx;
+    OM_uint32		 *minor_status;
+    gss_buffer_t	oid_str;
+    gss_OID		 *oid;
+{
+    return(generic_gss_str_to_oid(minor_status, oid_str, oid));
+}
+
+/* V2 */
+static OM_uint32
+k5glue_test_oid_set_member(ctx, minor_status, member, set, present)
+    void *ctx;
+    OM_uint32	 *minor_status;
+    gss_OID	member;
+    gss_OID_set	set;
+    int		 *present;
+{
+    return(generic_gss_test_oid_set_member(minor_status, member, set,
+					   present));
+}
+#endif
+
+/* V1 only */
+static OM_uint32
+k5glue_unseal(ctx, minor_status, context_handle, input_message_buffer,
+	   output_message_buffer, conf_state, qop_state)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_buffer_t input_message_buffer;
+     gss_buffer_t output_message_buffer;
+     int *conf_state;
+     int *qop_state;
+{
+   return(krb5_gss_unseal(minor_status, context_handle,
+			  input_message_buffer, output_message_buffer,
+			  conf_state, qop_state));
+}
+
+#if 0
+/* V2 */
+static OM_uint32
+k5glue_unwrap(ctx, minor_status, context_handle, input_message_buffer, 
+	   output_message_buffer, conf_state, qop_state)
+    void *ctx;
+    OM_uint32		 *minor_status;
+    gss_ctx_id_t	context_handle;
+    gss_buffer_t	input_message_buffer;
+    gss_buffer_t	output_message_buffer;
+    int			 *conf_state;
+    gss_qop_t		 *qop_state;
+{
+    return(krb5_gss_unwrap(minor_status, context_handle, input_message_buffer,
+			   output_message_buffer, conf_state, qop_state));
+}
+#endif
+
+/* V1 only */
+static OM_uint32
+k5glue_verify(ctx, minor_status, context_handle, message_buffer,
+	   token_buffer, qop_state)
+    void *ctx;
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_buffer_t message_buffer;
+     gss_buffer_t token_buffer;
+     int *qop_state;
+{
+   return(krb5_gss_verify(minor_status,
+			  context_handle,
+			  message_buffer,
+			  token_buffer,
+			  qop_state));
+}
+
+/* V2 interface */
+static OM_uint32
+k5glue_wrap_size_limit(ctx, minor_status, context_handle, conf_req_flag,
+		    qop_req, req_output_size, max_input_size)
+    void *ctx;
+    OM_uint32		 *minor_status;
+    gss_ctx_id_t	context_handle;
+    int			conf_req_flag;
+    gss_qop_t		qop_req;
+    OM_uint32		req_output_size;
+    OM_uint32		 *max_input_size;
+{
+   return(krb5_gss_wrap_size_limit(minor_status, context_handle,
+				   conf_req_flag, qop_req,
+				   req_output_size, max_input_size));
+}
+
+#if 0
+/* V2 interface */
+static OM_uint32
+k5glue_canonicalize_name(ctx, minor_status, input_name, mech_type, output_name)
+    void *ctx;
+	OM_uint32  *minor_status;
+	const gss_name_t input_name;
+	const gss_OID mech_type;
+	gss_name_t *output_name;
+{
+	return krb5_gss_canonicalize_name(minor_status, input_name,
+					  mech_type, output_name);
+}
+#endif
+
+/* V2 interface */
+static OM_uint32
+k5glue_export_name(ctx, minor_status, input_name, exported_name)
+    void *ctx;
+	OM_uint32  *minor_status;
+	const gss_name_t input_name;
+	gss_buffer_t exported_name;
+{
+	return krb5_gss_export_name(minor_status, input_name, exported_name);
+}
+
+#if 0
+/* V2 interface */
+static OM_uint32
+k5glue_duplicate_name(ctx, minor_status, input_name, dest_name)
+    void *ctx;
+	OM_uint32  *minor_status;
+	const gss_name_t input_name;
+	gss_name_t *dest_name;
+{
+	return krb5_gss_duplicate_name(minor_status, input_name, dest_name);
+}
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_get_tkt_flags(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t context_handle,
+    krb5_flags *ticket_flags)
+{
+    gss_union_ctx_id_t uctx;
+
+    uctx = (gss_union_ctx_id_t)context_handle;
+    if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type) &&
+	!g_OID_equal(uctx->mech_type, &krb5_mechanism_old.mech_type))
+	return GSS_S_BAD_MECH;
+    return gss_krb5int_get_tkt_flags(minor_status, uctx->internal_ctx_id,
+				     ticket_flags);
+}
+
+OM_uint32 KRB5_CALLCONV 
+gss_krb5_copy_ccache(
+    OM_uint32 *minor_status,
+    gss_cred_id_t cred_handle,
+    krb5_ccache out_ccache)
+{
+    gss_union_cred_t ucred;
+    gss_cred_id_t mcred;
+
+    ucred = (gss_union_cred_t)cred_handle;
+
+    mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism.mech_type);
+    if (mcred != GSS_C_NO_CREDENTIAL)
+	return gss_krb5int_copy_ccache(minor_status, mcred, out_ccache);
+
+    mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism_old.mech_type);
+    if (mcred != GSS_C_NO_CREDENTIAL)
+	return gss_krb5int_copy_ccache(minor_status, mcred, out_ccache);
+
+    return GSS_S_DEFECTIVE_CREDENTIAL;
+}
+
+/* XXX need to delete mechglue ctx too */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_export_lucid_sec_context(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t *context_handle,
+    OM_uint32 version,
+    void **kctx)
+{
+    gss_union_ctx_id_t uctx;
+
+    uctx = (gss_union_ctx_id_t)*context_handle;
+    if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type) &&
+	!g_OID_equal(uctx->mech_type, &krb5_mechanism_old.mech_type))
+	return GSS_S_BAD_MECH;
+    return gss_krb5int_export_lucid_sec_context(minor_status,
+						&uctx->internal_ctx_id,
+						version, kctx);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_set_allowable_enctypes(
+    OM_uint32 *minor_status, 
+    gss_cred_id_t cred,
+    OM_uint32 num_ktypes,
+    krb5_enctype *ktypes)
+{
+    gss_union_cred_t ucred;
+    gss_cred_id_t mcred;
+
+    ucred = (gss_union_cred_t)cred;
+    mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism.mech_type);
+    if (mcred != GSS_C_NO_CREDENTIAL)
+	return gss_krb5int_set_allowable_enctypes(minor_status, mcred,
+						  num_ktypes, ktypes);
+
+    mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism_old.mech_type);
+    if (mcred != GSS_C_NO_CREDENTIAL)
+	return gss_krb5int_set_allowable_enctypes(minor_status, mcred,
+						  num_ktypes, ktypes);
+
+    return GSS_S_DEFECTIVE_CREDENTIAL;
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/lucid_context.c b/krb5-1-6/src/lib/gssapi/krb5/lucid_context.c
new file mode 100644
index 000000000..a1679a93d
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/lucid_context.c
@@ -0,0 +1,309 @@
+/*
+ * lib/gssapi/krb5/lucid_context.c
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * lucid_context.c  -  Externalize a "lucid" security
+ * context from a krb5_gss_ctx_id_rec structure.
+ */
+#include "gssapiP_krb5.h"
+#include "gssapi_krb5.h"
+
+/*
+ * Local routine prototypes
+ */
+static void
+free_external_lucid_ctx_v1(
+    gss_krb5_lucid_context_v1_t *ctx);
+
+static void
+free_lucid_key_data(
+    gss_krb5_lucid_key_t *key);
+
+static krb5_error_code
+copy_keyblock_to_lucid_key(
+    krb5_keyblock *k5key,
+    gss_krb5_lucid_key_t *lkey);
+
+static krb5_error_code
+make_external_lucid_ctx_v1(
+    krb5_gss_ctx_id_rec * gctx,
+    unsigned int version,
+    void **out_ptr);
+
+
+/*
+ * Exported routines
+ */
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5int_export_lucid_sec_context(
+    OM_uint32		*minor_status,
+    gss_ctx_id_t	*context_handle,
+    OM_uint32		version,
+    void		**kctx)
+{
+    krb5_error_code	kret = 0;
+    OM_uint32		retval;
+    krb5_gss_ctx_id_t	ctx;
+    void		*lctx = NULL;
+
+    /* Assume failure */
+    retval = GSS_S_FAILURE;
+    *minor_status = 0;
+
+    if (kctx)
+	*kctx = NULL;
+    else {
+	kret = EINVAL;
+    	goto error_out;
+    }
+
+    if (!kg_validate_ctx_id(*context_handle)) {
+	    kret = (OM_uint32) G_VALIDATE_FAILED;
+	    retval = GSS_S_NO_CONTEXT;
+	    goto error_out;
+    }
+
+    ctx = (krb5_gss_ctx_id_t) *context_handle;
+    if (kret)
+	goto error_out;
+
+    /* Externalize a structure of the right version */
+    switch (version) {
+    case 1:
+	kret = make_external_lucid_ctx_v1((krb5_pointer)ctx,
+					      version, &lctx);
+        break;
+    default:
+	kret = (OM_uint32) KG_LUCID_VERSION;
+	break;
+    }
+
+    if (kret)
+	goto error_out;
+
+    /* Success!  Record the context and return the buffer */
+    if (! kg_save_lucidctx_id((void *)lctx)) {
+	kret = G_VALIDATE_FAILED;
+	goto error_out;
+    }
+
+    *kctx = lctx;
+    *minor_status = 0;
+    retval = GSS_S_COMPLETE;
+
+    /* Clean up the context state (it is an error for
+     * someone to attempt to use this context again)
+     */
+    (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+    *context_handle = GSS_C_NO_CONTEXT;
+
+    return (retval);
+
+error_out:
+    if (*minor_status == 0) 
+	    *minor_status = (OM_uint32) kret;
+    return(retval);
+}
+
+/*
+ * Frees the storage associated with an
+ * exported lucid context structure.
+ */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_free_lucid_sec_context(
+    OM_uint32 *minor_status,
+    void *kctx)
+{
+    OM_uint32		retval;
+    krb5_error_code	kret = 0;
+    int			version;
+
+    /* Assume failure */
+    retval = GSS_S_FAILURE;
+    *minor_status = 0;
+
+    if (!kctx) {
+	kret = EINVAL;
+	goto error_out;
+    }
+
+    /* Verify pointer is valid lucid context */
+    if (! kg_validate_lucidctx_id(kctx)) {
+	kret = G_VALIDATE_FAILED;
+	goto error_out;
+    }
+
+    /* Determine version and call correct free routine */
+    version = ((gss_krb5_lucid_context_version_t *)kctx)->version;
+    switch (version) {
+    case 1:
+	free_external_lucid_ctx_v1((gss_krb5_lucid_context_v1_t*) kctx);
+	break;
+    default:
+	kret = EINVAL;
+	break;
+    }
+
+    if (kret)
+	goto error_out;
+
+    /* Success! */
+    (void)kg_delete_lucidctx_id(kctx);
+    *minor_status = 0;
+    retval = GSS_S_COMPLETE;
+
+    return (retval);
+
+error_out:
+    if (*minor_status == 0) 
+	    *minor_status = (OM_uint32) kret;
+    return(retval);
+}
+
+/*
+ * Local routines
+ */
+
+static krb5_error_code
+make_external_lucid_ctx_v1(
+    krb5_gss_ctx_id_rec * gctx,
+    unsigned int version,
+    void **out_ptr)
+{
+    gss_krb5_lucid_context_v1_t *lctx = NULL;
+    unsigned int bufsize = sizeof(gss_krb5_lucid_context_v1_t);
+    krb5_error_code retval;
+
+    /* Allocate the structure */
+    if ((lctx = xmalloc(bufsize)) == NULL) {
+    	retval = ENOMEM;
+	goto error_out;
+    }
+
+    memset(lctx, 0, bufsize);
+
+    lctx->version = 1;
+    lctx->initiate = gctx->initiate ? 1 : 0;
+    lctx->endtime = gctx->endtime;
+    lctx->send_seq = gctx->seq_send;
+    lctx->recv_seq = gctx->seq_recv;
+    lctx->protocol = gctx->proto;
+    /* gctx->proto == 0 ==> rfc1964-style key information
+       gctx->proto == 1 ==> cfx-style (draft-ietf-krb-wg-gssapi-cfx-07) keys */
+    if (gctx->proto == 0) {
+	lctx->rfc1964_kd.sign_alg = gctx->signalg;
+	lctx->rfc1964_kd.seal_alg = gctx->sealalg;
+	/* Copy key */
+	if ((retval = copy_keyblock_to_lucid_key(gctx->subkey,
+	    				&lctx->rfc1964_kd.ctx_key)))
+	    goto error_out;
+    }
+    else if (gctx->proto == 1) {
+	/* Copy keys */
+	/* (subkey is always present, either a copy of the kerberos
+	   session key or a subkey) */
+	if ((retval = copy_keyblock_to_lucid_key(gctx->subkey,
+	    				&lctx->cfx_kd.ctx_key)))
+	    goto error_out;
+	if (gctx->have_acceptor_subkey) {
+	    if ((retval = copy_keyblock_to_lucid_key(gctx->enc,
+	    				&lctx->cfx_kd.acceptor_subkey)))
+		goto error_out;
+	    lctx->cfx_kd.have_acceptor_subkey = 1;
+	}
+    }
+    else {
+	return EINVAL;	/* XXX better error code? */
+    }
+
+    /* Success! */
+    *out_ptr = lctx;
+    return 0;
+
+error_out:
+    if (lctx) {
+	free_external_lucid_ctx_v1(lctx);
+    }
+    return retval;
+
+}
+
+/* Copy the contents of a krb5_keyblock to a gss_krb5_lucid_key_t structure */
+static krb5_error_code
+copy_keyblock_to_lucid_key(
+    krb5_keyblock *k5key,
+    gss_krb5_lucid_key_t *lkey)
+{
+    if (!k5key || !k5key->contents || k5key->length == 0)
+	return EINVAL;
+
+    memset(lkey, 0, sizeof(gss_krb5_lucid_key_t));
+
+    /* Allocate storage for the key data */
+    if ((lkey->data = xmalloc(k5key->length)) == NULL) {
+	return ENOMEM;
+    }
+    memcpy(lkey->data, k5key->contents, k5key->length);
+    lkey->length = k5key->length;
+    lkey->type = k5key->enctype;
+
+    return 0;
+}
+
+
+/* Free any storage associated with a gss_krb5_lucid_key_t structure */
+static void
+free_lucid_key_data(
+    gss_krb5_lucid_key_t *key)
+{
+    if (key) {
+	if (key->data && key->length) {
+	    memset(key->data, 0, key->length);
+	    xfree(key->data);
+	    memset(key, 0, sizeof(gss_krb5_lucid_key_t));
+	}
+    }
+}
+/* Free any storage associated with a gss_krb5_lucid_context_v1 structure */
+static void
+free_external_lucid_ctx_v1(
+    gss_krb5_lucid_context_v1_t *ctx)
+{
+    if (ctx) {
+	if (ctx->protocol == 0) {
+	    free_lucid_key_data(&ctx->rfc1964_kd.ctx_key);
+	}
+	if (ctx->protocol == 1) {
+	    free_lucid_key_data(&ctx->cfx_kd.ctx_key);
+	    if (ctx->cfx_kd.have_acceptor_subkey)
+		free_lucid_key_data(&ctx->cfx_kd.acceptor_subkey);
+	}
+	xfree(ctx);
+	ctx = NULL;
+    }
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/process_context_token.c b/krb5-1-6/src/lib/gssapi/krb5/process_context_token.c
new file mode 100644
index 000000000..49d8ec3f9
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/process_context_token.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32
+krb5_gss_process_context_token(minor_status, context_handle, 
+			       token_buffer)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_buffer_t token_buffer;
+{
+   krb5_gss_ctx_id_rec *ctx;
+   OM_uint32 majerr;
+
+   /* 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_t) context_handle;
+
+   if (! ctx->established) {
+      *minor_status = KG_CTX_INCOMPLETE;
+      return(GSS_S_NO_CONTEXT);
+   }
+
+   /* "unseal" the token */
+
+   if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle, 
+                                    token_buffer,
+				    GSS_C_NO_BUFFER, NULL, NULL,
+				    KG_TOK_DEL_CTX)))
+      return(majerr);
+
+   /* that's it.  delete the context */
+
+   return(krb5_gss_delete_sec_context(minor_status, &context_handle,
+				      GSS_C_NO_BUFFER));
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/rel_cred.c b/krb5-1-6/src/lib/gssapi/krb5/rel_cred.c
new file mode 100644
index 000000000..416d51a9e
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/rel_cred.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32 
+krb5_gss_release_cred(minor_status, cred_handle)
+     OM_uint32 *minor_status;
+     gss_cred_id_t *cred_handle;
+{
+   krb5_context context;
+   krb5_gss_cred_id_t cred;
+   krb5_error_code code1, code2, code3;
+
+   code1 = krb5_gss_init_context(&context);
+   if (code1) {
+       *minor_status = code1;
+       return GSS_S_FAILURE;
+   }
+
+   if (*cred_handle == GSS_C_NO_CREDENTIAL) {
+      *minor_status = 0;
+      krb5_free_context(context);
+      return(GSS_S_COMPLETE);
+   }
+
+   if (! kg_delete_cred_id(*cred_handle)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      krb5_free_context(context);
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_NO_CRED);
+   }
+
+   cred = (krb5_gss_cred_id_t)*cred_handle;
+
+   k5_mutex_destroy(&cred->lock);
+   /* ignore error destroying mutex */
+
+   if (cred->ccache)
+      code1 = krb5_cc_close(context, cred->ccache);
+   else
+      code1 = 0;
+
+   if (cred->keytab)
+      code2 = krb5_kt_close(context, cred->keytab);
+   else
+      code2 = 0;
+
+   if (cred->rcache)
+      code3 = krb5_rc_close(context, cred->rcache);
+   else
+      code3 = 0;
+   if (cred->princ)
+      krb5_free_principal(context, cred->princ);
+
+   if (cred->req_enctypes)
+       free(cred->req_enctypes);
+
+   xfree(cred);
+   krb5_free_context(context);
+
+   *cred_handle = NULL;
+
+   *minor_status = 0;
+   if (code1)
+      *minor_status = code1;
+   if (code2)
+      *minor_status = code2;
+   if (code3)
+      *minor_status = code3;
+
+   return(*minor_status?GSS_S_FAILURE:GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/rel_name.c b/krb5-1-6/src/lib/gssapi/krb5/rel_name.c
new file mode 100644
index 000000000..d906a70c0
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/rel_name.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32
+krb5_gss_release_name(minor_status, input_name)
+     OM_uint32 *minor_status;
+     gss_name_t *input_name;
+{
+   krb5_context context;
+   krb5_error_code code;
+
+   code = krb5_gss_init_context(&context);
+   if (code) {
+       *minor_status = code;
+       return GSS_S_FAILURE;
+   }
+
+   if (! kg_validate_name(*input_name)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      krb5_free_context(context);
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   }
+
+   (void)kg_delete_name(*input_name);
+
+   krb5_free_principal(context, (krb5_principal) *input_name);
+   krb5_free_context(context);
+
+   *input_name = (gss_name_t) NULL;
+
+   *minor_status = 0;
+   return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/rel_oid.c b/krb5-1-6/src/lib/gssapi/krb5/rel_oid.c
new file mode 100644
index 000000000..21408b5d6
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/rel_oid.c
@@ -0,0 +1,86 @@
+/*
+ * lib/gssapi/krb5/rel_oid.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * rel_oid.c - Release an OID.
+ */
+#include "gssapiP_krb5.h"
+
+OM_uint32 krb5_gss_internal_release_oid (OM_uint32 *, /* minor_status */
+					 gss_OID * /* oid */
+    );
+
+OM_uint32
+krb5_gss_release_oid(minor_status, oid)
+    OM_uint32	*minor_status;
+    gss_OID	*oid;
+{
+    /*
+     * The V2 API says the following!
+     *
+     * gss_release_oid[()] will recognize any of the GSSAPI's own OID values,
+     * and will silently ignore attempts to free these OIDs; for other OIDs
+     * it will call the C free() routine for both the OID data and the
+     * descriptor.  This allows applications to freely mix their own heap-
+     * allocated OID values with OIDs returned by GSS-API.
+     */
+    if (krb5_gss_internal_release_oid(minor_status, oid) != GSS_S_COMPLETE) {
+	/* Pawn it off on the generic routine */
+	return(generic_gss_release_oid(minor_status, oid));
+    }
+    else {
+	*oid = GSS_C_NO_OID;
+	*minor_status = 0;
+	return(GSS_S_COMPLETE);
+    }
+}
+
+OM_uint32
+krb5_gss_internal_release_oid(minor_status, oid)
+    OM_uint32	*minor_status;
+    gss_OID	*oid;
+{
+    /*
+     * This function only knows how to release internal OIDs. It will
+     * return GSS_S_CONTINUE_NEEDED for any OIDs it does not recognize.
+     */
+   
+    if ((*oid != gss_mech_krb5) &&
+	(*oid != gss_mech_krb5_old) &&
+	(*oid != gss_mech_krb5_wrong) &&
+	(*oid != gss_nt_krb5_name) &&
+	(*oid != gss_nt_krb5_principal)) {
+	/* We don't know about this OID */
+	return(GSS_S_CONTINUE_NEEDED);
+    }
+    else {
+	*oid = GSS_C_NO_OID;
+	*minor_status = 0;
+	return(GSS_S_COMPLETE);
+    }
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/krb5/seal.c b/krb5-1-6/src/lib/gssapi/krb5/seal.c
new file mode 100644
index 000000000..63d3dabe0
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/seal.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32
+krb5_gss_seal(minor_status, context_handle, conf_req_flag,
+	      qop_req, input_message_buffer, conf_state,
+	      output_message_buffer)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     int conf_req_flag;
+     int qop_req;
+     gss_buffer_t input_message_buffer;
+     int *conf_state;
+     gss_buffer_t output_message_buffer;
+{
+   return(kg_seal(minor_status, context_handle, conf_req_flag,
+		  qop_req, input_message_buffer, conf_state,
+		  output_message_buffer, KG_TOK_SEAL_MSG));
+}
+
+/* V2 interface */
+OM_uint32
+krb5_gss_wrap(minor_status, context_handle, conf_req_flag,
+	      qop_req, input_message_buffer, conf_state,
+	      output_message_buffer)
+    OM_uint32		*minor_status;
+    gss_ctx_id_t	context_handle;
+    int			conf_req_flag;
+    gss_qop_t		qop_req;
+    gss_buffer_t	input_message_buffer;
+    int			*conf_state;
+    gss_buffer_t	output_message_buffer;
+{
+    return(kg_seal(minor_status, context_handle, conf_req_flag,
+		   (int) qop_req, input_message_buffer, conf_state,
+		   output_message_buffer, KG_TOK_WRAP_MSG));
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/krb5/ser_sctx.c b/krb5-1-6/src/lib/gssapi/krb5/ser_sctx.c
new file mode 100644
index 000000000..00ea78254
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/ser_sctx.c
@@ -0,0 +1,676 @@
+/*
+ * lib/gssapi/krb5/ser_sctx.c
+ *
+ * Copyright 1995, 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_sctx.c - Handle [de]serialization of GSSAPI security context.
+ */
+#include "k5-int.h"
+#include "gssapiP_krb5.h"
+
+/*
+ * This module contains routines to [de]serialize 
+ *	krb5_gss_enc_desc and krb5_gss_ctx_id_t.
+ * XXX This whole serialization abstraction is unnecessary in a
+ * non-messaging environment, which krb5 is.  Someday, this should
+ * all get redone without the extra level of indirection. I've done
+ * some of this work here, since adding new serializers is an internal
+ * krb5 interface, and I won't use those.  There is some more
+ * deobfuscation (no longer anonymizing pointers, mostly) which could
+ * still be done. --marc
+ */
+
+static krb5_error_code
+kg_oid_externalize(kcontext, arg, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+     gss_OID oid = (gss_OID) arg;
+     krb5_error_code err;
+     
+     err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain);
+     if (err)
+	 return err;
+     err = krb5_ser_pack_int32((krb5_int32) oid->length,
+			       buffer, lenremain);
+     if (err)
+	 return err;
+     err = krb5_ser_pack_bytes((krb5_octet *) oid->elements,
+			       oid->length, buffer, lenremain);
+     if (err)
+	 return err;
+     err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain);
+     return err;
+}
+
+static krb5_error_code
+kg_oid_internalize(kcontext, argp, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	*argp;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+     gss_OID oid;
+     krb5_int32 ibuf;
+     krb5_octet		*bp;
+     size_t		remain;
+
+     bp = *buffer;
+     remain = *lenremain;
+
+     /* Read in and check our magic number */
+     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	return (EINVAL);
+
+     if (ibuf != KV5M_GSS_OID)
+	 return (EINVAL);
+
+     oid = (gss_OID) malloc(sizeof(gss_OID_desc));
+     if (oid == NULL)
+	  return ENOMEM;
+     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
+	 free(oid);
+	 return EINVAL;
+     }
+     oid->length = ibuf;
+     oid->elements = malloc(ibuf);
+     if (oid->elements == 0) {
+	     free(oid);
+	     return ENOMEM;
+     }
+     if (krb5_ser_unpack_bytes((krb5_octet *) oid->elements,
+			       oid->length, &bp, &remain)) {
+	 free(oid->elements);
+	 free(oid);
+	 return EINVAL;
+     }
+     
+     /* Read in and check our trailing magic number */
+     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
+	 free(oid->elements);
+	 free(oid);
+	 return (EINVAL);
+     }
+
+     if (ibuf != KV5M_GSS_OID) {
+	 free(oid->elements);
+	 free(oid);
+	 return (EINVAL);
+     }
+
+     *buffer = bp;
+     *lenremain = remain;
+     *argp = (krb5_pointer) oid;
+     return 0;
+}
+
+static krb5_error_code
+kg_oid_size(kcontext, arg, sizep)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    size_t		*sizep;
+{
+   krb5_error_code kret;
+   gss_OID oid;
+   size_t required;
+
+   kret = EINVAL;
+   if ((oid = (gss_OID) arg)) {
+      required = 2*sizeof(krb5_int32); /* For the header and trailer */
+      required += sizeof(krb5_int32);
+      required += oid->length;
+
+      kret = 0;
+
+      *sizep += required;
+   }
+
+   return(kret);
+}
+
+static krb5_error_code
+kg_queue_externalize(kcontext, arg, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+    krb5_error_code err;
+    err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
+    if (err == 0)
+	err = g_queue_externalize(arg, buffer, lenremain);
+    if (err == 0)
+	err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
+    return err;
+}
+
+static krb5_error_code
+kg_queue_internalize(kcontext, argp, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	*argp;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+     krb5_int32 ibuf;
+     krb5_octet		*bp;
+     size_t		remain;
+     krb5_error_code	err;
+
+     bp = *buffer;
+     remain = *lenremain;
+
+     /* Read in and check our magic number */
+     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	return (EINVAL);
+
+     if (ibuf != KV5M_GSS_QUEUE)
+	 return (EINVAL);
+
+     err = g_queue_internalize(argp, &bp, &remain);
+     if (err)
+	  return err;
+
+     /* Read in and check our trailing magic number */
+     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
+	 g_order_free(argp);
+	 return (EINVAL);
+     }
+
+     if (ibuf != KV5M_GSS_QUEUE) {
+	 g_order_free(argp);
+	 return (EINVAL);
+     }
+
+     *buffer = bp;
+     *lenremain = remain;
+     return 0;
+}
+
+static krb5_error_code
+kg_queue_size(kcontext, arg, sizep)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    size_t		*sizep;
+{
+   krb5_error_code kret;
+   size_t required;
+
+   kret = EINVAL;
+   if (arg) {
+      required = 2*sizeof(krb5_int32); /* For the header and trailer */
+      g_queue_size(arg, &required);
+
+      kret = 0;
+      *sizep += required;
+   }
+   return(kret);
+}
+
+/*
+ * Determine the size required for this krb5_gss_ctx_id_rec.
+ */
+krb5_error_code
+kg_ctx_size(kcontext, arg, sizep)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    size_t		*sizep;
+{
+    krb5_error_code	kret;
+    krb5_gss_ctx_id_rec	*ctx;
+    size_t		required;
+
+    /*
+     * krb5_gss_ctx_id_rec requires:
+     *	krb5_int32	for KG_CONTEXT
+     *	krb5_int32	for initiate.
+     *	krb5_int32	for established.
+     *	krb5_int32	for big_endian.
+     *	krb5_int32	for have_acceptor_subkey.
+     *	krb5_int32	for seed_init.
+     *	krb5_int32	for gss_flags.
+     *	sizeof(seed)	for seed
+     *	...		for here
+     *	...		for there
+     *	...		for subkey
+     *  krb5_int32	for signalg.
+     *  krb5_int32	for cksum_size.
+     *  krb5_int32	for sealalg.
+     *	...		for enc
+     *	...		for seq
+     *	krb5_int32	for endtime.
+     *	krb5_int32	for flags.
+     *	krb5_int64	for seq_send.
+     *	krb5_int64	for seq_recv.
+     *	...		for seqstate
+     *	...		for auth_context
+     *	...		for mech_used
+     *	krb5_int32	for proto
+     *	krb5_int32	for cksumtype
+     *	...		for acceptor_subkey
+     *	krb5_int32	for acceptor_key_cksumtype
+     *	krb5_int32	for cred_rcache
+     *	krb5_int32	for trailer.
+     */
+    kret = EINVAL;
+    if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
+	required = 17*sizeof(krb5_int32);
+	required += 2*sizeof(krb5_int64);
+	required += sizeof(ctx->seed);
+
+	kret = 0;
+	if (!kret && ctx->here)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_PRINCIPAL,
+				    (krb5_pointer) ctx->here,
+				    &required);
+
+	if (!kret && ctx->there)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_PRINCIPAL,
+				    (krb5_pointer) ctx->there,
+				    &required);
+
+	if (!kret && ctx->subkey)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) ctx->subkey,
+				    &required);
+
+	if (!kret && ctx->enc)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) ctx->enc,
+				    &required);
+
+	if (!kret && ctx->seq)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) ctx->seq,
+				    &required);
+
+	if (!kret)
+	    kret = kg_oid_size(kcontext,
+			       (krb5_pointer) ctx->mech_used,
+			       &required);
+
+	if (!kret && ctx->seqstate)
+	    kret = kg_queue_size(kcontext, ctx->seqstate, &required);
+
+	if (!kret)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_CONTEXT,
+				    (krb5_pointer) ctx->k5_context,
+				    &required);
+	if (!kret)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_AUTH_CONTEXT,
+				    (krb5_pointer) ctx->auth_context,
+				    &required);
+	if (!kret && ctx->acceptor_subkey)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) ctx->acceptor_subkey,
+				    &required);
+	if (!kret)
+	    *sizep += required;
+    }
+    return(kret);
+}
+
+/*
+ * Externalize this krb5_gss_ctx_id_ret.
+ */
+krb5_error_code
+kg_ctx_externalize(kcontext, arg, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+    krb5_error_code	kret;
+    krb5_gss_ctx_id_rec	*ctx;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    krb5int_access kaccess;
+
+    kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
+    if (kret) 
+        return(kret);
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
+	kret = ENOMEM;
+	if (!kg_ctx_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
+
+	    /* Now static data */
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->initiate,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->established,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->have_acceptor_subkey,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->gss_flags,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed,
+				       sizeof(ctx->seed),
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->signalg,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->cksum_size,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->sealalg,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->endtime,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_flags,
+				       &bp, &remain);
+	    (void) (*kaccess.krb5_ser_pack_int64)((krb5_int64) ctx->seq_send,
+				       &bp, &remain);
+	    (void) (*kaccess.krb5_ser_pack_int64)((krb5_int64) ctx->seq_recv,
+				       &bp, &remain);
+
+	    /* Now dynamic data */
+	    kret = 0;
+
+	    if (!kret && ctx->mech_used)
+		 kret = kg_oid_externalize(kcontext, ctx->mech_used,
+					   &bp, &remain); 
+	    
+	    if (!kret && ctx->here)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_PRINCIPAL,
+					       (krb5_pointer) ctx->here,
+					       &bp, &remain);
+
+	    if (!kret && ctx->there)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_PRINCIPAL,
+					       (krb5_pointer) ctx->there,
+					       &bp, &remain);
+
+	    if (!kret && ctx->subkey)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer) ctx->subkey,
+					       &bp, &remain);
+
+	    if (!kret && ctx->enc)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer) ctx->enc,
+					       &bp, &remain);
+
+	    if (!kret && ctx->seq)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer) ctx->seq,
+					       &bp, &remain);
+
+	    if (!kret && ctx->seqstate)
+		kret = kg_queue_externalize(kcontext,
+					    ctx->seqstate, &bp, &remain);
+
+	    if (!kret)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_CONTEXT,
+					       (krb5_pointer) ctx->k5_context,
+					       &bp, &remain);
+
+	    if (!kret)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_AUTH_CONTEXT,
+					       (krb5_pointer) ctx->auth_context,
+					       &bp, &remain);
+
+	    if (!kret)
+		kret = krb5_ser_pack_int32((krb5_int32) ctx->proto,
+					   &bp, &remain);
+	    if (!kret)
+		kret = krb5_ser_pack_int32((krb5_int32) ctx->cksumtype,
+					   &bp, &remain);
+	    if (!kret && ctx->acceptor_subkey)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer) ctx->acceptor_subkey,
+					       &bp, &remain);
+	    if (!kret)
+		kret = krb5_ser_pack_int32((krb5_int32) ctx->acceptor_subkey_cksumtype,
+					   &bp, &remain);
+
+	    if (!kret)
+		kret = krb5_ser_pack_int32((krb5_int32) ctx->cred_rcache,
+					   &bp, &remain);
+	    /* trailer */
+	    if (!kret)
+		kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
+	    if (!kret) {
+		*buffer = bp;
+		*lenremain = remain;
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Internalize this krb5_gss_ctx_id_t.
+ */
+krb5_error_code
+kg_ctx_internalize(kcontext, argp, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	*argp;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+    krb5_error_code	kret;
+    krb5_gss_ctx_id_rec	*ctx;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    krb5int_access kaccess;
+
+    kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
+    if (kret)
+        return(kret);
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KG_CONTEXT) {
+	kret = ENOMEM;
+
+	/* Get a context */
+	if ((remain >= (17*sizeof(krb5_int32)
+			+ 2*sizeof(krb5_int64)
+			+ sizeof(ctx->seed))) &&
+	    (ctx = (krb5_gss_ctx_id_rec *)
+	     xmalloc(sizeof(krb5_gss_ctx_id_rec)))) {
+	    memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+
+	    ctx->k5_context = kcontext;
+
+	    /* Get static data */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->initiate = (int) ibuf;
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    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->have_acceptor_subkey = (int) ibuf;
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->seed_init = (int) ibuf;
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->gss_flags = (int) ibuf;
+	    (void) krb5_ser_unpack_bytes((krb5_octet *) ctx->seed,
+					 sizeof(ctx->seed),
+					 &bp, &remain);
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->signalg = (int) ibuf;
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->cksum_size = (int) ibuf;
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->sealalg = (int) ibuf;
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->endtime = (krb5_timestamp) ibuf;
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->krb_flags = (krb5_flags) ibuf;
+	    (void) (*kaccess.krb5_ser_unpack_int64)(&ctx->seq_send, &bp, &remain);
+	    kret = (*kaccess.krb5_ser_unpack_int64)(&ctx->seq_recv, &bp, &remain);
+	    if (kret) {
+		free(ctx);
+		return kret;
+	    }
+
+	    if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp,
+					   &remain))) {
+		 if (kret == EINVAL)
+		      kret = 0;
+	    }
+	    /* Now get substructure data */
+	    if ((kret = krb5_internalize_opaque(kcontext,
+						KV5M_PRINCIPAL,
+						(krb5_pointer *) &ctx->here,
+						&bp, &remain))) {
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+	    if (!kret &&
+		(kret = krb5_internalize_opaque(kcontext,
+						KV5M_PRINCIPAL,
+						(krb5_pointer *) &ctx->there,
+						&bp, &remain))) {
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+	    if (!kret &&
+		(kret = krb5_internalize_opaque(kcontext,
+						KV5M_KEYBLOCK,
+						(krb5_pointer *) &ctx->subkey,
+						&bp, &remain))) {
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+	    if (!kret &&
+		(kret = krb5_internalize_opaque(kcontext,
+						KV5M_KEYBLOCK,
+						(krb5_pointer *) &ctx->enc,
+						&bp, &remain))) {
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+	    if (!kret &&
+		(kret = krb5_internalize_opaque(kcontext,
+						KV5M_KEYBLOCK,
+						(krb5_pointer *) &ctx->seq,
+						&bp, &remain))) {
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+
+	    if (!kret) {
+		kret = kg_queue_internalize(kcontext, &ctx->seqstate,
+					    &bp, &remain);
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+		
+	    if (!kret)
+		kret = krb5_internalize_opaque(kcontext,
+					       KV5M_CONTEXT,
+					       (krb5_pointer *) &ctx->k5_context,
+					       &bp, &remain);
+
+	    if (!kret)
+		kret = krb5_internalize_opaque(kcontext,
+					       KV5M_AUTH_CONTEXT,
+				       (krb5_pointer *) &ctx->auth_context,
+					       &bp, &remain);
+
+	    if (!kret)
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->proto = ibuf;
+	    if (!kret)
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->cksumtype = ibuf;
+	    if (!kret &&
+		(kret = krb5_internalize_opaque(kcontext,
+						KV5M_KEYBLOCK,
+						(krb5_pointer *) &ctx->acceptor_subkey,
+						&bp, &remain))) {
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+	    if (!kret)
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->cred_rcache = ibuf;
+	    if (!kret)
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ctx->acceptor_subkey_cksumtype = ibuf;
+
+	    /* Get trailer */
+	    if (!kret)
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    if (!kret && ibuf != KG_CONTEXT)
+		kret = EINVAL;
+
+	    if (!kret) {
+		*buffer = bp;
+		*lenremain = remain;
+		*argp = (krb5_pointer) ctx;
+	    } else {
+		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)
+		    krb5_free_principal(kcontext, ctx->there);
+		if (ctx->here)
+		    krb5_free_principal(kcontext, ctx->here);
+		xfree(ctx);
+	    }
+	}
+    }
+    return(kret);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/set_allowable_enctypes.c b/krb5-1-6/src/lib/gssapi/krb5/set_allowable_enctypes.c
new file mode 100644
index 000000000..f573d7dfc
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/set_allowable_enctypes.c
@@ -0,0 +1,133 @@
+/*
+ * lib/gssapi/krb5/set_allowable_enctypes.c
+ *
+ * Copyright 2004  by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * krb5_gss_set_allowable_enctypes()
+ */
+
+/*
+ * gss_krb5_set_allowable_enctypes
+ *
+ * This function may be called by a context initiator after calling
+ * gss_acquire_cred(), but before calling gss_init_sec_context(),
+ * to restrict the set of enctypes which will be negotiated during
+ * context establishment to those in the provided array.
+ *
+ * 'cred_handle' must be a valid credential handle obtained via
+ * gss_acquire_cred().  It may not be GSS_C_NO_CREDENTIAL.
+ * gss_acquire_cred() may be called with GSS_C_NO_CREDENTIAL
+ * to get a handle to the default credential.
+ *
+ * The purpose of this function is to limit the keys that may
+ * be exported via gss_krb5_export_lucid_sec_context(); thus it
+ * should limit the enctypes of all keys that will be needed
+ * after the security context has been established.
+ * (i.e. context establishment may use a session key with a
+ * stronger enctype than in the provided array, however a
+ * subkey must be established within the enctype limits
+ * established by this function.)
+ *
+ */
+
+#include "gssapiP_krb5.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include "gssapi_krb5.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, 
+				   gss_cred_id_t cred_handle,
+				   OM_uint32 num_ktypes,
+				   krb5_enctype *ktypes)
+{
+    int i;
+    krb5_enctype * new_ktypes;
+    OM_uint32 major_status;
+    krb5_gss_cred_id_t cred;
+    krb5_error_code kerr = 0;
+    OM_uint32 temp_status;
+
+    /* Assume a failure */
+    *minor_status = 0;
+    major_status = GSS_S_FAILURE;
+
+    /* verify and valildate cred handle */
+    if (cred_handle == GSS_C_NO_CREDENTIAL) {
+	kerr = KRB5_NOCREDS_SUPPLIED;
+	goto error_out;
+    }
+    major_status = krb5_gss_validate_cred(&temp_status, cred_handle);
+    if (GSS_ERROR(major_status)) {
+	kerr = temp_status;
+	goto error_out;
+    }
+    cred = (krb5_gss_cred_id_t) cred_handle;
+
+    if (ktypes) {
+	for (i = 0; i < num_ktypes && ktypes[i]; i++) {
+	    if (!krb5_c_valid_enctype(ktypes[i])) {
+		kerr = KRB5_PROG_ETYPE_NOSUPP;
+		goto error_out;
+	    }
+	}
+    } else {
+	kerr = k5_mutex_lock(&cred->lock);
+	if (kerr)
+	    goto error_out;
+	if (cred->req_enctypes)
+	    free(cred->req_enctypes);
+	cred->req_enctypes = NULL;
+	k5_mutex_unlock(&cred->lock);
+	return GSS_S_COMPLETE;
+    }
+
+    /* Copy the requested ktypes into the cred structure */
+    if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * (i + 1)))) {
+	memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
+	new_ktypes[i] = 0;	/* "null-terminate" the list */
+    }
+    else {
+	kerr = ENOMEM;
+	goto error_out;
+    }
+    kerr = k5_mutex_lock(&cred->lock);
+    if (kerr) {
+	free(new_ktypes);
+	goto error_out;
+    }
+    if (cred->req_enctypes)
+	free(cred->req_enctypes);
+    cred->req_enctypes = new_ktypes;
+    k5_mutex_unlock(&cred->lock);
+
+    /* Success! */
+    return GSS_S_COMPLETE;
+
+error_out:
+    *minor_status = kerr;
+    return(major_status);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/set_ccache.c b/krb5-1-6/src/lib/gssapi/krb5/set_ccache.c
new file mode 100644
index 000000000..931058290
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/set_ccache.c
@@ -0,0 +1,92 @@
+/*
+ * lib/gssapi/krb5/set_ccache.c
+ *
+ * Copyright 1999, 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Set ccache name used by gssapi, and optionally obtain old ccache
+ * name.  Caller should not free returned name.
+ */
+
+#include <string.h>
+#include "gssapiP_krb5.h"
+#include "gss_libinit.h"
+
+OM_uint32 KRB5_CALLCONV 
+gss_krb5_ccache_name(minor_status, name, out_name)
+	OM_uint32 *minor_status;
+	const char *name;
+	const char **out_name;
+{
+    char *old_name = NULL;
+    OM_uint32 err = 0;
+    OM_uint32 minor = 0;
+    char *gss_out_name;
+
+    err = gssint_initialize_library();
+    if (err) {
+	*minor_status = err;
+	return GSS_S_FAILURE;
+    }
+
+    gss_out_name = k5_getspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
+
+    if (out_name) {
+        const char *tmp_name = NULL;
+
+        if (!err) {
+            kg_get_ccache_name (&err, &tmp_name);
+        }
+        if (!err) {
+            old_name = gss_out_name;
+            gss_out_name = tmp_name;
+        }            
+    }
+    /* If out_name was NULL, we keep the same gss_out_name value, and
+       don't free up any storage (leave old_name NULL).  */
+
+    if (!err)
+        kg_set_ccache_name (&err, name);
+
+    minor = k5_setspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, gss_out_name);
+    if (minor) {
+	/* Um.  Now what?  */
+	if (err == 0) {
+	    err = minor;
+	}
+	free(gss_out_name);
+	gss_out_name = NULL;
+    }
+
+    if (!err) {
+        if (out_name) {
+            *out_name = gss_out_name;
+        }
+    }
+    
+    if (old_name != NULL) {
+        free (old_name);
+    }
+    
+    *minor_status = err;
+    return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/sign.c b/krb5-1-6/src/lib/gssapi/krb5/sign.c
new file mode 100644
index 000000000..2d192c9bb
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/sign.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32
+krb5_gss_sign(minor_status, context_handle,
+	      qop_req, message_buffer, 
+	      message_token)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     int qop_req;
+     gss_buffer_t message_buffer;
+     gss_buffer_t message_token;
+{
+   return(kg_seal(minor_status, context_handle, 0,
+		  qop_req, message_buffer, NULL,
+		  message_token, KG_TOK_SIGN_MSG));
+}
+
+/* V2 interface */
+OM_uint32
+krb5_gss_get_mic(minor_status, context_handle, qop_req,
+		 message_buffer, message_token)
+    OM_uint32		*minor_status;
+    gss_ctx_id_t	context_handle;
+    gss_qop_t		qop_req;
+    gss_buffer_t	message_buffer;
+    gss_buffer_t	message_token;
+{
+    return(kg_seal(minor_status, context_handle, 0,
+		   (int) qop_req, message_buffer, NULL,
+		   message_token, KG_TOK_MIC_MSG));
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/unseal.c b/krb5-1-6/src/lib/gssapi/krb5/unseal.c
new file mode 100644
index 000000000..71dc11048
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/unseal.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32
+krb5_gss_unseal(minor_status, context_handle,
+		input_message_buffer, output_message_buffer,
+		conf_state, qop_state)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_buffer_t input_message_buffer;
+     gss_buffer_t output_message_buffer;
+     int *conf_state;
+     int *qop_state;
+{
+   return(kg_unseal(minor_status, context_handle,
+		    input_message_buffer, output_message_buffer,
+		    conf_state, qop_state, KG_TOK_SEAL_MSG));
+}
+
+/* V2 interface */
+OM_uint32
+krb5_gss_unwrap(minor_status, context_handle,
+		input_message_buffer, output_message_buffer,
+		conf_state, qop_state)
+    OM_uint32		*minor_status;
+    gss_ctx_id_t	context_handle;
+    gss_buffer_t	input_message_buffer;
+    gss_buffer_t	output_message_buffer;
+    int			*conf_state;
+    gss_qop_t		*qop_state;
+{
+    OM_uint32		rstat;
+    int			qstate;
+
+    rstat = kg_unseal(minor_status, context_handle,
+		      input_message_buffer, output_message_buffer,
+		      conf_state, &qstate, KG_TOK_WRAP_MSG);
+    if (!rstat && qop_state)
+	*qop_state = (gss_qop_t) qstate;
+    return(rstat);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/util_cksum.c b/krb5-1-6/src/lib/gssapi/krb5/util_cksum.c
new file mode 100644
index 000000000..235d74947
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/util_cksum.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+/* Checksumming the channel bindings always uses plain MD5.  */
+krb5_error_code
+kg_checksum_channel_bindings(context, cb, cksum, bigend)
+     krb5_context context;
+     gss_channel_bindings_t cb;
+     krb5_checksum *cksum;
+     int bigend;
+{
+   size_t len;
+   char *buf = 0;
+   char *ptr;
+   size_t sumlen;
+   krb5_data plaind;
+   krb5_error_code code;
+   void *temp;
+
+   /* initialize the the cksum */
+   code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen);
+   if (code)
+       return(code);
+
+   cksum->checksum_type = CKSUMTYPE_RSA_MD5;
+   cksum->length = sumlen;
+ 
+   /* generate a buffer full of zeros if no cb specified */
+
+   if (cb == GSS_C_NO_CHANNEL_BINDINGS) {
+       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 */
+
+   len = (sizeof(krb5_int32)*5+
+	  cb->initiator_address.length+
+	  cb->acceptor_address.length+
+	  cb->application_data.length);
+
+   if ((buf = (char *) xmalloc(len)) == NULL)
+      return(ENOMEM);
+
+   /* helper macros.  This code currently depends on a long being 32
+      bits, and htonl dtrt. */
+
+   ptr = buf;
+
+   TWRITE_INT(ptr, cb->initiator_addrtype, bigend);
+   TWRITE_BUF(ptr, cb->initiator_address, bigend);
+   TWRITE_INT(ptr, cb->acceptor_addrtype, bigend);
+   TWRITE_BUF(ptr, cb->acceptor_address, bigend);
+   TWRITE_BUF(ptr, cb->application_data, bigend);
+
+   /* checksum the data */
+
+   plaind.length = len;
+   plaind.data = buf;
+
+   code = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, 0, 0,
+			       &plaind, cksum);
+   if (code)
+       goto cleanup;
+
+   if ((temp = xmalloc(cksum->length)) == NULL) {
+       krb5_free_checksum_contents(context, cksum);
+       code = ENOMEM;
+       goto cleanup;
+   }
+
+   memcpy(temp, cksum->contents, cksum->length);
+   krb5_free_checksum_contents(context, cksum);
+   cksum->contents = (krb5_octet *)temp;
+
+   /* success */
+ cleanup:
+   if (buf)
+       xfree(buf);
+   return code;
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/util_crypt.c b/krb5-1-6/src/lib/gssapi/krb5/util_crypt.c
new file mode 100644
index 000000000..dad4b023d
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/util_crypt.c
@@ -0,0 +1,240 @@
+/*
+  * Copyright2001 by the Massachusetts Institute of Technology.
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+int
+kg_confounder_size(context, key)
+     krb5_context context;
+     krb5_keyblock *key;
+{
+   krb5_error_code code;
+   size_t blocksize;
+   /* We special case rc4*/
+   if (key->enctype == ENCTYPE_ARCFOUR_HMAC)
+     return 8;
+   code = krb5_c_block_size(context, key->enctype, &blocksize);
+   if (code)
+      return(-1); /* XXX */
+
+   return(blocksize);
+}
+
+krb5_error_code
+kg_make_confounder(context, key, buf)
+     krb5_context context;
+     krb5_keyblock *key;
+     unsigned char *buf;
+{
+   krb5_error_code code;
+   size_t blocksize;
+   krb5_data lrandom;
+
+   code = krb5_c_block_size(context, key->enctype, &blocksize);
+   if (code)
+       return(code);
+
+   lrandom.length = blocksize;
+   lrandom.data = buf;
+
+   return(krb5_c_random_make_octets(context, &lrandom));
+}
+
+krb5_error_code
+kg_encrypt(context, key, usage, iv, in, out, length)
+     krb5_context context;
+     krb5_keyblock *key;
+     int usage;
+     krb5_pointer iv;
+     krb5_const_pointer in;
+     krb5_pointer out;
+     unsigned int length;
+{
+   krb5_error_code code;
+   size_t blocksize;
+   krb5_data ivd, *pivd, inputd;
+   krb5_enc_data outputd;
+
+   if (iv) {
+       code = krb5_c_block_size(context, key->enctype, &blocksize);
+       if (code)
+	   return(code);
+
+       ivd.length = blocksize;
+       ivd.data = malloc(ivd.length);
+       if (ivd.data == NULL)
+	   return ENOMEM;
+       memcpy(ivd.data, iv, ivd.length);
+       pivd = &ivd;
+   } else {
+       pivd = NULL;
+   }
+
+   inputd.length = length;
+   inputd.data = in;
+
+   outputd.ciphertext.length = length;
+   outputd.ciphertext.data = out;
+
+   code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd);
+   if (pivd != NULL)
+       free(pivd->data);
+   return code;
+}
+
+/* length is the length of the cleartext. */
+
+krb5_error_code
+kg_decrypt(context, key, usage, iv, in, out, length)
+     krb5_context context;
+     krb5_keyblock *key;
+     int usage;
+     krb5_pointer iv;
+     krb5_const_pointer in;
+     krb5_pointer out;
+     unsigned int length;
+{
+   krb5_error_code code;
+   size_t blocksize;
+   krb5_data ivd, *pivd, outputd;
+   krb5_enc_data inputd;
+
+   if (iv) {
+       code = krb5_c_block_size(context, key->enctype, &blocksize);
+       if (code)
+	   return(code);
+
+       ivd.length = blocksize;
+       ivd.data = malloc(ivd.length);
+       if (ivd.data == NULL)
+	   return ENOMEM;
+       memcpy(ivd.data, iv, ivd.length);
+       pivd = &ivd;
+   } else {
+       pivd = NULL;
+   }
+
+   inputd.enctype = ENCTYPE_UNKNOWN;
+   inputd.ciphertext.length = length;
+   inputd.ciphertext.data = in;
+
+   outputd.length = length;
+   outputd.data = out;
+
+   code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd);
+   if (pivd != NULL)
+       free(pivd->data);
+   return code;
+}
+
+krb5_error_code
+kg_arcfour_docrypt (const krb5_keyblock *longterm_key , int ms_usage,
+		    const unsigned char *kd_data, size_t kd_data_len,
+		    const unsigned char *input_buf, size_t input_len,
+		    unsigned char *output_buf)
+{
+  krb5_error_code code;
+  krb5_data input, output;
+  krb5int_access kaccess;
+  krb5_keyblock seq_enc_key, usage_key;
+  unsigned char t[4];
+
+  usage_key.length = longterm_key->length;
+  usage_key.contents = malloc(usage_key.length);
+  if (usage_key.contents == NULL)
+    return (ENOMEM);
+  seq_enc_key.length = longterm_key->length;
+  seq_enc_key.contents = malloc(seq_enc_key.length);
+  if (seq_enc_key.contents == NULL) {
+    free ((void *) usage_key.contents);
+    return (ENOMEM);
+  }
+  code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
+  if (code)
+    goto cleanup_arcfour;
+
+  t[0] = ms_usage &0xff;
+  t[1] = (ms_usage>>8) & 0xff;
+  t[2] = (ms_usage>>16) & 0xff;
+  t[3] = (ms_usage>>24) & 0xff;
+  input.data = (void *) &t;
+  input.length = 4;
+  output.data = (void *) usage_key.contents;
+  output.length = usage_key.length;
+  code = (*kaccess.krb5_hmac) (kaccess.md5_hash_provider,
+			       longterm_key, 1, &input, &output);
+  if (code)
+    goto cleanup_arcfour;
+	  
+  input.data = ( void *) kd_data;
+  input.length = kd_data_len;
+  output.data = (void *) seq_enc_key.contents;
+  code = (*kaccess.krb5_hmac) (kaccess.md5_hash_provider,
+			       &usage_key, 1, &input, &output);
+  if (code)
+    goto cleanup_arcfour;
+  input.data = ( void * ) input_buf;
+  input.length = input_len;
+  output.data = (void * ) output_buf;
+  output.length = input_len;
+  code =  ((*kaccess.arcfour_enc_provider->encrypt)(
+						    &seq_enc_key, 0, 
+						    &input, &output));
+ cleanup_arcfour:
+  memset ((void *) seq_enc_key.contents, 0, seq_enc_key.length);
+  memset ((void *) usage_key.contents, 0, usage_key.length);
+  free ((void *) usage_key.contents);
+  free ((void *) seq_enc_key.contents);
+  return (code);
+}
+		    
diff --git a/krb5-1-6/src/lib/gssapi/krb5/util_seed.c b/krb5-1-6/src/lib/gssapi/krb5/util_seed.c
new file mode 100644
index 000000000..9d39e4937
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/util_seed.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+static const unsigned char zeros[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
+
+krb5_error_code
+kg_make_seed(context, key, seed)
+     krb5_context context;
+     krb5_keyblock *key;
+     unsigned char *seed;
+{
+   krb5_error_code code;
+   krb5_keyblock *tmpkey;
+   int i;
+
+   code = krb5_copy_keyblock(context, key, &tmpkey);
+   if (code)
+      return(code);
+
+   /* reverse the key bytes, as per spec */
+
+   for (i=0; i<tmpkey->length; i++)
+      tmpkey->contents[i] = key->contents[key->length - 1 - i];
+
+   code = kg_encrypt(context, tmpkey, KG_USAGE_SEAL, NULL, zeros, seed, 16);
+
+   krb5_free_keyblock(context, tmpkey);
+
+   return(code);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/util_seqnum.c b/krb5-1-6/src/lib/gssapi/krb5/util_seqnum.c
new file mode 100644
index 000000000..ec7da5567
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/util_seqnum.c
@@ -0,0 +1,105 @@
+/*
+  * Copyright2001 by the Massachusetts Institute of Technology.
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+#include "k5-int.h"
+
+/*
+ * $Id$
+ */
+
+krb5_error_code
+kg_make_seq_num(context, key, direction, seqnum, cksum, buf)
+     krb5_context context;
+     krb5_keyblock *key;
+     int direction;
+     krb5_ui_4 seqnum;
+     unsigned char *cksum;
+     unsigned char *buf;
+{
+   unsigned char plain[8];
+
+   plain[4] = direction;
+   plain[5] = direction;
+   plain[6] = direction;
+   plain[7] = direction;
+   if (key->enctype == ENCTYPE_ARCFOUR_HMAC ) {
+     /* Yes, Microsoft used big-endian sequence number.*/
+     plain[0] = (seqnum>>24) & 0xff;
+     plain[1] = (seqnum>>16) & 0xff;
+     plain[2] = (seqnum>>8) & 0xff;
+     plain[3] = seqnum & 0xff;
+     return kg_arcfour_docrypt (key, 0, 
+				cksum, 8,
+				&plain[0], 8,
+				buf);
+     
+   }
+     
+   plain[0] = (unsigned char) (seqnum&0xff);
+   plain[1] = (unsigned char) ((seqnum>>8)&0xff);
+   plain[2] = (unsigned char) ((seqnum>>16)&0xff);
+   plain[3] = (unsigned char) ((seqnum>>24)&0xff);
+
+   return(kg_encrypt(context, key, KG_USAGE_SEQ, cksum, plain, buf, 8));
+}
+
+krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum)
+     krb5_context context;
+     krb5_keyblock *key;
+     unsigned char *cksum;
+     unsigned char *buf;
+     int *direction;
+     krb5_ui_4 *seqnum;
+{
+   krb5_error_code code;
+   unsigned char plain[8];
+
+   if (key->enctype == ENCTYPE_ARCFOUR_HMAC) {
+     code = kg_arcfour_docrypt (key, 0,
+				cksum, 8,
+				buf, 8,
+				plain);
+   } else {
+     code = kg_decrypt(context, key, KG_USAGE_SEQ, cksum, buf, plain, 8);
+   }
+   if (code)
+      return(code);
+
+   if ((plain[4] != plain[5]) ||
+       (plain[4] != plain[6]) ||
+       (plain[4] != plain[7]))
+      return((krb5_error_code) KG_BAD_SEQ);
+
+   *direction = plain[4];
+   if (key->enctype == ENCTYPE_ARCFOUR_HMAC) {
+     *seqnum = (plain[3]|(plain[2]<<8) | (plain[1]<<16)| (plain[0]<<24));
+   } else {
+     *seqnum = ((plain[0]) |
+	      (plain[1]<<8) |
+	      (plain[2]<<16) |
+	      (plain[3]<<24));
+   }
+
+   return(0);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/val_cred.c b/krb5-1-6/src/lib/gssapi/krb5/val_cred.c
new file mode 100644
index 000000000..de4b0637f
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/val_cred.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright 1997 by Massachusetts Institute of Technology
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * Check to see whether or not a GSSAPI krb5 credential is valid.  If
+ * it is not, return an error.
+ */
+
+OM_uint32
+krb5_gss_validate_cred_1(OM_uint32 *minor_status, gss_cred_id_t cred_handle,
+			 krb5_context context)
+{
+    krb5_gss_cred_id_t cred;
+    krb5_error_code code;
+    krb5_principal princ;
+
+    if (!kg_validate_cred_id(cred_handle)) {
+	*minor_status = (OM_uint32) G_VALIDATE_FAILED;
+	return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_DEFECTIVE_CREDENTIAL);
+    }
+
+    cred = (krb5_gss_cred_id_t) cred_handle;
+
+    code = k5_mutex_lock(&cred->lock);
+    if (code) {
+	*minor_status = code;
+	return GSS_S_FAILURE;
+    }
+
+    if (cred->ccache) {
+	if ((code = krb5_cc_get_principal(context, cred->ccache, &princ))) {
+	    k5_mutex_unlock(&cred->lock);
+	    *minor_status = code;
+	    return(GSS_S_DEFECTIVE_CREDENTIAL);
+	}
+	if (!krb5_principal_compare(context, princ, cred->princ)) {
+	    k5_mutex_unlock(&cred->lock);
+	    *minor_status = KG_CCACHE_NOMATCH;
+	    return(GSS_S_DEFECTIVE_CREDENTIAL);
+	}
+	(void)krb5_free_principal(context, princ);
+    }
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
+krb5_gss_validate_cred(minor_status, cred_handle)
+     OM_uint32 *minor_status;
+     gss_cred_id_t cred_handle;
+{
+    krb5_context context;
+    krb5_error_code code;
+    OM_uint32 maj;
+
+    code = krb5_gss_init_context(&context);
+    if (code) {
+	*minor_status = code;
+	return GSS_S_FAILURE;
+    }
+
+    maj = krb5_gss_validate_cred_1(minor_status, cred_handle, context);
+    if (maj == 0) {
+	krb5_gss_cred_id_t cred = (krb5_gss_cred_id_t) cred_handle;
+	k5_mutex_assert_locked(&cred->lock);
+	k5_mutex_unlock(&cred->lock);
+    }
+    krb5_free_context(context);
+    return maj;
+}
+
+		
+
+
diff --git a/krb5-1-6/src/lib/gssapi/krb5/verify.c b/krb5-1-6/src/lib/gssapi/krb5/verify.c
new file mode 100644
index 000000000..833697b19
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/verify.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+OM_uint32
+krb5_gss_verify(minor_status, context_handle,
+		message_buffer, token_buffer,
+		qop_state)
+     OM_uint32 *minor_status;
+     gss_ctx_id_t context_handle;
+     gss_buffer_t message_buffer;
+     gss_buffer_t token_buffer;
+     int *qop_state;
+{
+     return(kg_unseal(minor_status, context_handle,
+		      token_buffer, message_buffer,
+		      NULL, qop_state, KG_TOK_SIGN_MSG));
+}
+
+/* V2 interface */
+OM_uint32
+krb5_gss_verify_mic(minor_status, context_handle,
+		    message_buffer, token_buffer,
+		    qop_state)
+    OM_uint32		*minor_status;
+    gss_ctx_id_t	context_handle;
+    gss_buffer_t	message_buffer;
+    gss_buffer_t	token_buffer;
+    gss_qop_t		*qop_state;
+{
+    OM_uint32		rstat;
+    int			qstate;
+
+    rstat = kg_unseal(minor_status, context_handle,
+		      token_buffer, message_buffer,
+		      NULL, &qstate, KG_TOK_MIC_MSG);
+    if (!rstat && qop_state)
+	*qop_state = (gss_qop_t) qstate;
+    return(rstat);
+}
diff --git a/krb5-1-6/src/lib/gssapi/krb5/wrap_size_limit.c b/krb5-1-6/src/lib/gssapi/krb5/wrap_size_limit.c
new file mode 100644
index 000000000..b875a965a
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/krb5/wrap_size_limit.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2000 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * 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"
+
+/* V2 interface */
+OM_uint32
+krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+			 qop_req, req_output_size, max_input_size)
+    OM_uint32		*minor_status;
+    gss_ctx_id_t	context_handle;
+    int			conf_req_flag;
+    gss_qop_t		qop_req;
+    OM_uint32		req_output_size;
+    OM_uint32		*max_input_size;
+{
+    krb5_gss_ctx_id_rec	*ctx;
+    OM_uint32		data_size, conflen;
+    OM_uint32		ohlen;
+    int			overhead;
+
+    /* only default qop is allowed */
+    if (qop_req != GSS_C_QOP_DEFAULT) {
+	*minor_status = (OM_uint32) G_UNKNOWN_QOP;
+	return(GSS_S_FAILURE);
+    }
+    
+    /* 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);
+    }
+
+    if (ctx->proto == 1) {
+	/* No pseudo-ASN.1 wrapper overhead, so no sequence length and
+	   OID.  */
+	OM_uint32 sz = req_output_size;
+	/* Token header: 16 octets.  */
+	if (conf_req_flag) {
+	    while (sz > 0 && krb5_encrypt_size(sz, ctx->enc->enctype) + 16 > req_output_size)
+		sz--;
+	    /* Allow for encrypted copy of header.  */
+	    if (sz > 16)
+		sz -= 16;
+	    else
+		sz = 0;
+#ifdef CFX_EXERCISE
+	    /* Allow for EC padding.  In the MIT implementation, only
+	       added while testing.  */
+	    if (sz > 65535)
+		sz -= 65535;
+	    else
+		sz = 0;
+#endif
+	} else {
+	    /* Allow for token header and checksum.  */
+	    if (sz < 16 + ctx->cksum_size)
+		sz = 0;
+	    else
+		sz -= (16 + ctx->cksum_size);
+	}
+
+	*max_input_size = sz;
+	*minor_status = 0;
+	return GSS_S_COMPLETE;
+    }
+
+    /* Calculate the token size and subtract that from the output size */
+    overhead = 7 + ctx->mech_used->length;
+    data_size = req_output_size;
+    conflen = kg_confounder_size(ctx->k5_context, ctx->enc);
+    data_size = (conflen + data_size + 8) & (~(OM_uint32)7);
+    ohlen = g_token_size(ctx->mech_used,
+			 (unsigned int) (data_size + ctx->cksum_size + 14))
+      - req_output_size;
+
+    if (ohlen+overhead < req_output_size)
+      /*
+       * Cannot have trailer length that will cause us to pad over our
+       * length.
+       */
+      *max_input_size = (req_output_size - ohlen - overhead) & (~(OM_uint32)7);
+    else
+      *max_input_size = 0;
+
+    *minor_status = 0;
+    return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/libgssapi_krb5.exports b/krb5-1-6/src/lib/gssapi/libgssapi_krb5.exports
new file mode 100644
index 000000000..2d6199cde
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/libgssapi_krb5.exports
@@ -0,0 +1,73 @@
+GSS_C_NT_ANONYMOUS
+GSS_C_NT_EXPORT_NAME
+GSS_C_NT_HOSTBASED_SERVICE
+GSS_C_NT_HOSTBASED_SERVICE_X
+GSS_C_NT_MACHINE_UID_NAME
+GSS_C_NT_STRING_UID_NAME
+GSS_C_NT_USER_NAME
+GSS_KRB5_NT_PRINCIPAL_NAME
+gss_accept_sec_context
+gss_acquire_cred
+gss_add_cred
+gss_add_oid_set_member
+gss_canonicalize_name
+gss_compare_name
+gss_context_time
+gss_create_empty_oid_set
+gss_delete_sec_context
+gss_display_name
+gss_display_status
+gss_duplicate_name
+gss_export_name
+gss_export_sec_context
+gss_get_mic
+gss_import_name
+gss_import_sec_context
+gss_indicate_mechs
+gss_init_sec_context
+gss_inquire_context
+gss_inquire_cred
+gss_inquire_cred_by_mech
+gss_inquire_mechs_for_name
+gss_inquire_names_for_mech
+gss_krb5_ccache_name
+gss_krb5_copy_ccache
+gss_krb5_export_lucid_sec_context
+gss_krb5_get_tkt_flags
+gss_krb5_free_lucid_sec_context
+gss_krb5_set_allowable_enctypes
+gss_krb5int_make_seal_token_v3
+gss_krb5int_unseal_token_v3
+gss_mech_krb5
+gss_mech_krb5_old
+gss_mech_set_krb5
+gss_mech_set_krb5_both
+gss_mech_set_krb5_old
+gss_nt_exported_name
+gss_nt_krb5_name
+gss_nt_krb5_principal
+gss_nt_machine_uid_name
+gss_nt_service_name
+gss_nt_service_name_v2
+gss_nt_string_uid_name
+gss_nt_user_name
+gss_oid_to_str
+gss_process_context_token
+gss_release_buffer
+gss_release_cred
+gss_release_name
+gss_release_oid
+gss_release_oid_set
+gss_seal
+gss_sign
+gss_str_to_oid
+gss_test_oid_set_member
+gss_unseal
+gss_unwrap
+gss_verify
+gss_verify_mic
+gss_wrap
+gss_wrap_size_limit
+krb5_gss_dbg_client_expcreds
+krb5_gss_register_acceptor_identity
+krb5_gss_use_kdc_context
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/Makefile.in b/krb5-1-6/src/lib/gssapi/mechglue/Makefile.in
new file mode 100644
index 000000000..f8c9774a0
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/Makefile.in
@@ -0,0 +1,334 @@
+thisconfigdir=../../..
+myfulldir=lib/gssapi/mechglue
+mydir=lib/gssapi/mechglue
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic
+DEFS=
+
+##DOSBUILDTOP = ..\..\..
+##DOS##PREFIXDIR=mechglue
+##DOS##OBJFILE=..\$(OUTPRE)mechglue.lst
+
+##DOS##DLL_EXP_TYPE=GSS
+
+SRCS = \
+	$(srcdir)/g_accept_sec_context.c \
+	$(srcdir)/g_acquire_cred.c \
+	$(srcdir)/g_canon_name.c \
+	$(srcdir)/g_compare_name.c \
+	$(srcdir)/g_context_time.c \
+	$(srcdir)/g_delete_sec_context.c \
+	$(srcdir)/g_dsp_name.c \
+	$(srcdir)/g_dsp_status.c \
+	$(srcdir)/g_dup_name.c \
+	$(srcdir)/g_exp_sec_context.c \
+	$(srcdir)/g_export_name.c \
+	$(srcdir)/g_glue.c \
+	$(srcdir)/g_imp_name.c \
+	$(srcdir)/g_imp_sec_context.c \
+	$(srcdir)/g_init_sec_context.c \
+	$(srcdir)/g_initialize.c \
+	$(srcdir)/g_inq_context.c \
+	$(srcdir)/g_inq_cred.c \
+	$(srcdir)/g_inq_names.c \
+	$(srcdir)/g_mechname.c \
+	$(srcdir)/g_oid_ops.c \
+	$(srcdir)/g_process_context.c \
+	$(srcdir)/g_rel_buffer.c \
+	$(srcdir)/g_rel_cred.c \
+	$(srcdir)/g_rel_name.c \
+	$(srcdir)/g_rel_oid_set.c \
+	$(srcdir)/g_seal.c \
+	$(srcdir)/g_sign.c \
+	$(srcdir)/g_store_cred.c \
+	$(srcdir)/g_unseal.c \
+	$(srcdir)/g_verify.c \
+	$(srcdir)/oid_ops.c
+
+OBJS = \
+	$(OUTPRE)g_accept_sec_context.$(OBJEXT) \
+	$(OUTPRE)g_acquire_cred.$(OBJEXT) \
+	$(OUTPRE)g_canon_name.$(OBJEXT) \
+	$(OUTPRE)g_compare_name.$(OBJEXT) \
+	$(OUTPRE)g_context_time.$(OBJEXT) \
+	$(OUTPRE)g_delete_sec_context.$(OBJEXT) \
+	$(OUTPRE)g_dsp_name.$(OBJEXT) \
+	$(OUTPRE)g_dsp_status.$(OBJEXT) \
+	$(OUTPRE)g_dup_name.$(OBJEXT) \
+	$(OUTPRE)g_exp_sec_context.$(OBJEXT) \
+	$(OUTPRE)g_export_name.$(OBJEXT) \
+	$(OUTPRE)g_glue.$(OBJEXT) \
+	$(OUTPRE)g_imp_name.$(OBJEXT) \
+	$(OUTPRE)g_imp_sec_context.$(OBJEXT) \
+	$(OUTPRE)g_init_sec_context.$(OBJEXT) \
+	$(OUTPRE)g_initialize.$(OBJEXT) \
+	$(OUTPRE)g_inq_context.$(OBJEXT) \
+	$(OUTPRE)g_inq_cred.$(OBJEXT) \
+	$(OUTPRE)g_inq_names.$(OBJEXT) \
+	$(OUTPRE)g_mechname.$(OBJEXT) \
+	$(OUTPRE)g_oid_ops.$(OBJEXT) \
+	$(OUTPRE)g_process_context.$(OBJEXT) \
+	$(OUTPRE)g_rel_buffer.$(OBJEXT) \
+	$(OUTPRE)g_rel_cred.$(OBJEXT) \
+	$(OUTPRE)g_rel_name.$(OBJEXT) \
+	$(OUTPRE)g_rel_oid_set.$(OBJEXT) \
+	$(OUTPRE)g_seal.$(OBJEXT) \
+	$(OUTPRE)g_sign.$(OBJEXT) \
+	$(OUTPRE)g_store_cred.$(OBJEXT) \
+	$(OUTPRE)g_unseal.$(OBJEXT) \
+	$(OUTPRE)g_verify.$(OBJEXT) \
+	$(OUTPRE)oid_ops.$(OBJEXT)
+
+STLIBOBJS = \
+	g_accept_sec_context.o \
+	g_acquire_cred.o \
+	g_canon_name.o \
+	g_compare_name.o \
+	g_context_time.o \
+	g_delete_sec_context.o \
+	g_dsp_name.o \
+	g_dsp_status.o \
+	g_dup_name.o \
+	g_exp_sec_context.o \
+	g_export_name.o \
+	g_glue.o \
+	g_imp_name.o \
+	g_imp_sec_context.o \
+	g_init_sec_context.o \
+	g_initialize.o \
+	g_inq_context.o \
+	g_inq_cred.o \
+	g_inq_names.o \
+	g_mechname.o \
+	g_oid_ops.o \
+	g_process_context.o \
+	g_rel_buffer.o \
+	g_rel_cred.o \
+	g_rel_name.o \
+	g_rel_oid_set.o \
+	g_seal.o \
+	g_sign.o \
+	g_store_cred.o \
+	g_unseal.o \
+	g_verify.o \
+	oid_ops.o
+
+EHDRDIR= $(BUILDTOP)$(S)include$(S)gssapi
+EXPORTED_HEADERS = mechglue.h
+
+$(OBJS): $(EXPORTED_HEADERS)
+
+all-unix:: all-libobjs
+
+##DOS##LIBOBJS = $(OBJS)
+
+clean-unix:: clean-libobjs
+
+# Krb5InstallHeaders($(EXPORTED_HEADERS), $(KRB5_INCDIR)/krb5)
+install::
+	@set -x; for f in $(EXPORTED_HEADERS) ; \
+	do $(INSTALL_DATA) $(srcdir)$(S)$$f     \
+		$(DESTDIR)$(KRB5_INCDIR)$(S)gssapi$(S)$$f ; \
+	done
+
+includes::
+
+@libobj_frag@
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+g_accept_sec_context.so g_accept_sec_context.po $(OUTPRE)g_accept_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_accept_sec_context.c \
+  mechglue.h mglueP.h
+g_acquire_cred.so g_acquire_cred.po $(OUTPRE)g_acquire_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_acquire_cred.c mechglue.h \
+  mglueP.h
+g_canon_name.so g_canon_name.po $(OUTPRE)g_canon_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_canon_name.c mechglue.h \
+  mglueP.h
+g_compare_name.so g_compare_name.po $(OUTPRE)g_compare_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_compare_name.c mechglue.h \
+  mglueP.h
+g_context_time.so g_context_time.po $(OUTPRE)g_context_time.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_context_time.c mechglue.h \
+  mglueP.h
+g_delete_sec_context.so g_delete_sec_context.po $(OUTPRE)g_delete_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_delete_sec_context.c \
+  mechglue.h mglueP.h
+g_dsp_name.so g_dsp_name.po $(OUTPRE)g_dsp_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_dsp_name.c mechglue.h \
+  mglueP.h
+g_dsp_status.so g_dsp_status.po $(OUTPRE)g_dsp_status.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_dsp_status.c mechglue.h \
+  mglueP.h
+g_dup_name.so g_dup_name.po $(OUTPRE)g_dup_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_dup_name.c mechglue.h \
+  mglueP.h
+g_exp_sec_context.so g_exp_sec_context.po $(OUTPRE)g_exp_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_exp_sec_context.c \
+  mechglue.h mglueP.h
+g_export_name.so g_export_name.po $(OUTPRE)g_export_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_export_name.c mechglue.h \
+  mglueP.h
+g_glue.so g_glue.po $(OUTPRE)g_glue.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_glue.c mechglue.h \
+  mglueP.h
+g_imp_name.so g_imp_name.po $(OUTPRE)g_imp_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_imp_name.c mechglue.h \
+  mglueP.h
+g_imp_sec_context.so g_imp_sec_context.po $(OUTPRE)g_imp_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_imp_sec_context.c \
+  mechglue.h mglueP.h
+g_init_sec_context.so g_init_sec_context.po $(OUTPRE)g_init_sec_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_init_sec_context.c \
+  mechglue.h mglueP.h
+g_initialize.so g_initialize.po $(OUTPRE)g_initialize.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssapi.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h $(srcdir)/../gss_libinit.h \
+  ../generic/gssapi_err_generic.h g_initialize.c mechglue.h \
+  mglueP.h
+g_inq_context.so g_inq_context.po $(OUTPRE)g_inq_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_inq_context.c mechglue.h \
+  mglueP.h
+g_inq_cred.so g_inq_cred.po $(OUTPRE)g_inq_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_inq_cred.c mechglue.h \
+  mglueP.h
+g_inq_names.so g_inq_names.po $(OUTPRE)g_inq_names.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_inq_names.c mechglue.h \
+  mglueP.h
+g_mechname.so g_mechname.po $(OUTPRE)g_mechname.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_mechname.c mechglue.h \
+  mglueP.h
+g_oid_ops.so g_oid_ops.po $(OUTPRE)g_oid_ops.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_oid_ops.c mechglue.h \
+  mglueP.h
+g_process_context.so g_process_context.po $(OUTPRE)g_process_context.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_process_context.c \
+  mechglue.h mglueP.h
+g_rel_buffer.so g_rel_buffer.po $(OUTPRE)g_rel_buffer.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_rel_buffer.c mechglue.h \
+  mglueP.h
+g_rel_cred.so g_rel_cred.po $(OUTPRE)g_rel_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_rel_cred.c mechglue.h \
+  mglueP.h
+g_rel_name.so g_rel_name.po $(OUTPRE)g_rel_name.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_rel_name.c mechglue.h \
+  mglueP.h
+g_rel_oid_set.so g_rel_oid_set.po $(OUTPRE)g_rel_oid_set.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_rel_oid_set.c mechglue.h \
+  mglueP.h
+g_seal.so g_seal.po $(OUTPRE)g_seal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_seal.c mechglue.h \
+  mglueP.h
+g_sign.so g_sign.po $(OUTPRE)g_sign.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_sign.c mechglue.h \
+  mglueP.h
+g_store_cred.so g_store_cred.po $(OUTPRE)g_store_cred.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_store_cred.c mechglue.h \
+  mglueP.h
+g_unseal.so g_unseal.po $(OUTPRE)g_unseal.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_unseal.c mechglue.h \
+  mglueP.h
+g_verify.so g_verify.po $(OUTPRE)g_verify.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h g_verify.c mechglue.h \
+  mglueP.h
+oid_ops.so oid_ops.po $(OUTPRE)oid_ops.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
+  ../generic/gssapi_err_generic.h mechglue.h mglueP.h \
+  oid_ops.c
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_accept_sec_context.c b/krb5-1-6/src/lib/gssapi/mechglue/g_accept_sec_context.c
new file mode 100644
index 000000000..c18440fb9
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_accept_sec_context.c
@@ -0,0 +1,364 @@
+/* #pragma ident	"@(#)g_accept_sec_context.c	1.19	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_accept_sec_context
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+static OM_uint32
+val_acc_sec_ctx_args(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t *context_handle,
+    gss_cred_id_t verifier_cred_handle,
+    gss_buffer_t input_token_buffer,
+    gss_channel_bindings_t input_chan_bindings,
+    gss_name_t *src_name,
+    gss_OID *mech_type,
+    gss_buffer_t output_token,
+    OM_uint32 *ret_flags,
+    OM_uint32 *time_rec,
+    gss_cred_id_t *d_cred)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (src_name != NULL)
+	*src_name = GSS_C_NO_NAME;
+
+    if (mech_type != NULL)
+	*mech_type = GSS_C_NO_OID;
+
+    if (output_token != GSS_C_NO_BUFFER) {
+	output_token->length = 0;
+	output_token->value = NULL;
+    }
+
+    if (d_cred != NULL)
+	*d_cred = GSS_C_NO_CREDENTIAL;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (input_token_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (output_token == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_accept_sec_context (minor_status,
+                        context_handle,
+                        verifier_cred_handle,
+                        input_token_buffer,
+                        input_chan_bindings,
+                        src_name,
+                        mech_type,
+                        output_token,
+                        ret_flags,
+                        time_rec,
+                        d_cred)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t *		context_handle;
+gss_cred_id_t		verifier_cred_handle;
+gss_buffer_t		input_token_buffer;
+gss_channel_bindings_t	input_chan_bindings;
+gss_name_t *		src_name;
+gss_OID *		mech_type;
+gss_buffer_t		output_token;
+OM_uint32 *		ret_flags;
+OM_uint32 *		time_rec;
+gss_cred_id_t *		d_cred;
+
+{
+    OM_uint32		status, temp_status, temp_minor_status;
+    OM_uint32		temp_ret_flags = 0;
+    gss_union_ctx_id_t	union_ctx_id;
+    gss_union_cred_t	union_cred;
+    gss_cred_id_t	input_cred_handle = GSS_C_NO_CREDENTIAL;
+    gss_cred_id_t	tmp_d_cred = GSS_C_NO_CREDENTIAL;
+    gss_name_t		internal_name = GSS_C_NO_NAME;
+    gss_name_t		tmp_src_name = GSS_C_NO_NAME;
+    gss_OID_desc	token_mech_type_desc;
+    gss_OID		token_mech_type = &token_mech_type_desc;
+    gss_mechanism	mech;
+
+    status = val_acc_sec_ctx_args(minor_status,
+				  context_handle,
+				  verifier_cred_handle,
+				  input_token_buffer,
+				  input_chan_bindings,
+				  src_name,
+				  mech_type,
+				  output_token,
+				  ret_flags,
+				  time_rec,
+				  d_cred);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    /*
+     * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
+     * descriptor to hold the mech type information as well as the
+     * underlying mechanism context handle. Otherwise, cast the
+     * value of *context_handle to the union context variable.
+     */
+    
+    if(*context_handle == GSS_C_NO_CONTEXT) {
+	
+	if (GSS_EMPTY_BUFFER(input_token_buffer))
+	    return (GSS_S_CALL_INACCESSIBLE_READ);
+
+	/* Get the token mech type */
+	status = gssint_get_mech_type(token_mech_type, input_token_buffer);
+	if (status)
+	    return status;
+
+	status = GSS_S_FAILURE;
+	union_ctx_id = (gss_union_ctx_id_t)
+	    malloc(sizeof(gss_union_ctx_id_desc));
+	if (!union_ctx_id)
+	    return (GSS_S_FAILURE);
+
+	union_ctx_id->loopback = union_ctx_id;
+	union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT;
+	status = generic_gss_copy_oid(&temp_minor_status,
+				      token_mech_type,
+				      &union_ctx_id->mech_type);
+	if (status != GSS_S_COMPLETE) {
+	    free(union_ctx_id);
+	    return (status);
+	}
+
+	/* set the new context handle to caller's data */
+	*context_handle = (gss_ctx_id_t)union_ctx_id;
+    } else {
+	union_ctx_id = (gss_union_ctx_id_t)*context_handle;
+	token_mech_type = union_ctx_id->mech_type;
+    }
+    
+    /* 
+     * get the appropriate cred handle from the union cred struct.
+     * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
+     * use the default credential.
+     */
+    union_cred = (gss_union_cred_t) verifier_cred_handle;
+    input_cred_handle = gssint_get_mechanism_cred(union_cred, token_mech_type);
+    
+    /*
+     * now select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    mech = gssint_get_mechanism (token_mech_type);
+    if (mech && mech->gss_accept_sec_context) {
+
+	    status = mech->gss_accept_sec_context(
+						  mech->context,
+						  minor_status,
+						  &union_ctx_id->internal_ctx_id,
+						  input_cred_handle,
+						  input_token_buffer,
+						  input_chan_bindings,
+						  &internal_name,
+						  mech_type,
+						  output_token,
+						  &temp_ret_flags,
+						  time_rec,
+					d_cred ? &tmp_d_cred : NULL);
+
+	    /* If there's more work to do, keep going... */
+	    if (status == GSS_S_CONTINUE_NEEDED)
+		return GSS_S_CONTINUE_NEEDED;
+	    
+	    /* if the call failed, return with failure */
+	    if (status != GSS_S_COMPLETE)
+		goto error_out;
+
+	    /*
+	     * if src_name is non-NULL,
+	     * convert internal_name into a union name equivalent
+	     * First call the mechanism specific display_name()
+	     * then call gss_import_name() to create
+	     * the union name struct cast to src_name
+	     */
+	    if (internal_name != NULL) {
+		temp_status = gssint_convert_name_to_union_name(
+		       &temp_minor_status, mech,
+		       internal_name, &tmp_src_name);
+		if (temp_status != GSS_S_COMPLETE) {
+		    *minor_status = temp_minor_status;
+		    if (output_token->length)
+			(void) gss_release_buffer(&temp_minor_status,
+						  output_token);
+		    if (internal_name != GSS_C_NO_NAME)
+			mech->gss_release_name(
+			    mech->context,
+			    &temp_minor_status,
+			    &internal_name);
+		    return (temp_status);
+		}
+		if (src_name != NULL) {
+		    *src_name = tmp_src_name;
+		}
+	    } else if (src_name != NULL) {
+		*src_name = GSS_C_NO_NAME;
+	    }
+
+	    /* Ensure we're returning correct creds format */
+	    if ((temp_ret_flags & GSS_C_DELEG_FLAG) &&
+		tmp_d_cred != GSS_C_NO_CREDENTIAL) {
+		gss_union_cred_t d_u_cred = NULL;
+
+		d_u_cred = malloc(sizeof (gss_union_cred_desc));
+		if (d_u_cred == NULL) {
+		    status = GSS_S_FAILURE;
+		    goto error_out;
+		}
+		(void) memset(d_u_cred, 0,
+			      sizeof (gss_union_cred_desc));
+
+		d_u_cred->count = 1;
+
+		status = generic_gss_copy_oid(&temp_minor_status,
+					      token_mech_type,
+					      &d_u_cred->mechs_array);
+
+		if (status != GSS_S_COMPLETE) {
+		    free(d_u_cred);
+		    goto error_out;
+		}
+
+		d_u_cred->cred_array = malloc(sizeof (gss_cred_id_t));
+		if (d_u_cred->cred_array != NULL) {
+		    d_u_cred->cred_array[0] = tmp_d_cred;
+		} else {
+		    free(d_u_cred);
+		    status = GSS_S_FAILURE;
+		    goto error_out;
+		}
+
+		if (status != GSS_S_COMPLETE) {
+		    free(d_u_cred->cred_array);
+		    free(d_u_cred);
+		    goto error_out;
+		}
+
+		internal_name = GSS_C_NO_NAME;
+
+		d_u_cred->auxinfo.creation_time = time(0);
+		d_u_cred->auxinfo.time_rec = 0;
+		d_u_cred->loopback = d_u_cred;
+
+		if (mech->gss_inquire_cred) {
+		    status = mech->gss_inquire_cred(mech->context,
+						    minor_status,
+						    tmp_d_cred,
+						    &internal_name,
+						    &d_u_cred->auxinfo.time_rec,
+						    &d_u_cred->auxinfo.cred_usage,
+						    NULL);
+		}
+
+		if (internal_name != NULL) {
+		    temp_status = gssint_convert_name_to_union_name(
+			&temp_minor_status, mech,
+			internal_name, &tmp_src_name);
+		    if (temp_status != GSS_S_COMPLETE) {
+			*minor_status = temp_minor_status;
+			if (output_token->length)
+			    (void) gss_release_buffer(
+				&temp_minor_status,
+				output_token);
+			free(d_u_cred->cred_array);
+			free(d_u_cred);
+			return (temp_status);
+		    }
+		}
+
+		if (tmp_src_name != NULL) {
+		    status = gss_display_name(
+			&temp_minor_status,
+			tmp_src_name,
+			&d_u_cred->auxinfo.name,
+			&d_u_cred->auxinfo.name_type);
+		}
+
+		*d_cred = (gss_cred_id_t)d_u_cred;
+	    }
+
+	    if (src_name == NULL && tmp_src_name != NULL)
+		(void) gss_release_name(&temp_minor_status,
+					&tmp_src_name);
+	    if (ret_flags != NULL)
+		*ret_flags = temp_ret_flags;
+	    return	(status);
+    } else {
+
+	status = GSS_S_BAD_MECH;
+    }
+    
+error_out:
+    if (union_ctx_id) {
+	if (union_ctx_id->mech_type) {
+	    if (union_ctx_id->mech_type->elements)
+		free(union_ctx_id->mech_type->elements);
+	    free(union_ctx_id->mech_type);
+	    *context_handle = GSS_C_NO_CONTEXT;
+	}
+	free(union_ctx_id);
+    }
+
+    if (output_token->length)
+	(void) gss_release_buffer(&temp_minor_status, output_token);
+
+    if (src_name)
+	*src_name = GSS_C_NO_NAME;
+
+    if (tmp_src_name != GSS_C_NO_NAME)
+	(void) gss_release_buffer(&temp_minor_status,
+				  (gss_buffer_t)tmp_src_name);
+
+    return (status);
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_acquire_cred.c b/krb5-1-6/src/lib/gssapi/mechglue/g_acquire_cred.c
new file mode 100644
index 000000000..bd5bef8ea
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_acquire_cred.c
@@ -0,0 +1,516 @@
+/* #pragma ident	"@(#)g_acquire_cred.c	1.22	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_acquire_cred
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+static gss_OID_set
+create_actual_mechs(mechs_array, count)
+    const gss_OID	mechs_array;
+    int count;
+{
+    gss_OID_set 	actual_mechs;
+    int			i;
+    OM_uint32		minor;
+
+    actual_mechs = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
+    if (!actual_mechs)
+	return NULL;
+
+    actual_mechs->elements = (gss_OID)
+	malloc(sizeof (gss_OID_desc) * count);
+    if (!actual_mechs->elements) {
+	free(actual_mechs);
+	return NULL;
+    }
+    
+    actual_mechs->count = 0;
+
+    for (i = 0; i < count; i++) {
+	actual_mechs->elements[i].elements = (void *)
+	    malloc(mechs_array[i].length);
+	if (actual_mechs->elements[i].elements == NULL) {
+	    (void) gss_release_oid_set(&minor, &actual_mechs);
+	    return (NULL);
+	}
+	g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]);
+	actual_mechs->count++;
+    }
+
+    return actual_mechs;
+}
+
+static OM_uint32
+val_acq_cred_args(
+    OM_uint32 *minor_status,
+    gss_name_t desired_name,
+    OM_uint32 time_req,
+    gss_OID_set desired_mechs,
+    int cred_usage,
+    gss_cred_id_t *output_cred_handle,
+    gss_OID_set *actual_mechs,
+    OM_uint32 *time_rec)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (output_cred_handle != NULL)
+	*output_cred_handle = GSS_C_NO_CREDENTIAL;
+
+    if (actual_mechs != NULL)
+	*actual_mechs = GSS_C_NULL_OID_SET;
+
+    if (time_rec != NULL)
+	*time_rec = 0;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (output_cred_handle == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_acquire_cred(minor_status,
+                 desired_name,
+                 time_req,
+                 desired_mechs,
+		 cred_usage,
+                 output_cred_handle,
+                 actual_mechs,
+                 time_rec)
+
+OM_uint32 *		minor_status;
+gss_name_t		desired_name;
+OM_uint32		time_req;
+gss_OID_set		desired_mechs;
+int			cred_usage;
+gss_cred_id_t *		output_cred_handle;
+gss_OID_set *		actual_mechs;
+OM_uint32 *		time_rec;
+
+{
+    OM_uint32 major = GSS_S_FAILURE;
+    OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
+    gss_OID_set_desc default_OID_set;
+    gss_OID_set mechs;
+    gss_OID_desc default_OID;
+    gss_mechanism mech;
+    int i;
+    gss_union_cred_t creds;
+
+    major = val_acq_cred_args(minor_status,
+			      desired_name,
+			      time_req,
+			      desired_mechs,
+			      cred_usage,
+			      output_cred_handle,
+			      actual_mechs,
+			      time_rec);
+    if (major != GSS_S_COMPLETE)
+	return (major);
+
+    /* Initial value needed below. */
+    major = GSS_S_FAILURE;
+
+    /*
+     * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
+     * appropriate default.  We use the first mechanism in the
+     * mechansim list as the default. This set is created with
+     * statics thus needs not be freed
+     */
+    if(desired_mechs == GSS_C_NULL_OID_SET) {
+	mech = gssint_get_mechanism(NULL);
+	if (mech == NULL)
+	    return (GSS_S_BAD_MECH);
+	
+	mechs = &default_OID_set;
+	default_OID_set.count = 1;
+	default_OID_set.elements = &default_OID;
+	default_OID.length = mech->mech_type.length;
+	default_OID.elements = mech->mech_type.elements;
+    } else
+	mechs = desired_mechs;
+
+    if (mechs->count == 0)
+	return (GSS_S_BAD_MECH);
+
+    /* allocate the output credential structure */
+    creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
+    if (creds == NULL)
+	return (GSS_S_FAILURE);
+
+    /* initialize to 0s */
+    (void) memset(creds, 0, sizeof (gss_union_cred_desc));
+    creds->loopback = creds;
+
+    /* for each requested mech attempt to obtain a credential */
+    for (i = 0; i < mechs->count; i++) {
+	major = gss_add_cred(minor_status, (gss_cred_id_t)creds,
+			     desired_name,
+			     &mechs->elements[i],
+			     cred_usage, time_req, time_req, NULL,
+			     NULL, &initTimeOut, &acceptTimeOut);
+	if (major == GSS_S_COMPLETE) {
+	    /* update the credential's time */
+	    if (cred_usage == GSS_C_ACCEPT) {
+		if (outTime > acceptTimeOut)
+		    outTime = acceptTimeOut;
+	    } else if (cred_usage == GSS_C_INITIATE) {
+		if (outTime > initTimeOut)
+		    outTime = initTimeOut;
+	    } else {
+		/*
+		 * time_rec is the lesser of the
+		 * init/accept times
+		 */
+		if (initTimeOut > acceptTimeOut)
+		    outTime = (outTime > acceptTimeOut) ?
+			acceptTimeOut : outTime;
+		else
+		    outTime = (outTime > initTimeOut) ?
+			initTimeOut : outTime;
+	    }
+	}
+    } /* for */
+
+    /* ensure that we have at least one credential element */
+    if (creds->count < 1) {
+	free(creds);
+	return (major);
+    }
+
+    /*
+     * fill in output parameters
+     * setup the actual mechs output parameter
+     */
+    if (actual_mechs != NULL) {
+	if ((*actual_mechs = create_actual_mechs(creds->mechs_array,
+						 creds->count)) == NULL) {
+	    (void) gss_release_cred(minor_status,
+				    (gss_cred_id_t *)&creds);
+	    *minor_status = 0;
+	    return (GSS_S_FAILURE);
+	}
+    }
+
+    if (time_rec)
+	*time_rec = outTime;
+
+
+    creds->loopback = creds;
+    *output_cred_handle = (gss_cred_id_t)creds;
+    return (GSS_S_COMPLETE);
+}
+
+static OM_uint32
+val_add_cred_args(
+    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)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (output_cred_handle != NULL)
+	*output_cred_handle = GSS_C_NO_CREDENTIAL;
+
+    if (actual_mechs != NULL)
+	*actual_mechs = GSS_C_NO_OID_SET;
+
+    if (acceptor_time_rec != NULL)
+	*acceptor_time_rec = 0;
+
+    if (initiator_time_rec != NULL)
+	*initiator_time_rec = 0;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
+	output_cred_handle == NULL)
+
+	return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+/* V2 KRB5_CALLCONV */
+OM_uint32 KRB5_CALLCONV
+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;
+{
+    OM_uint32		status, temp_minor_status;
+    OM_uint32		time_req, time_rec;
+    gss_union_name_t	union_name;
+    gss_union_cred_t	new_union_cred, union_cred;
+    gss_name_t		internal_name = GSS_C_NO_NAME;
+    gss_name_t		allocated_name = GSS_C_NO_NAME;
+    gss_mechanism	mech;
+    gss_cred_id_t	cred = NULL;
+    gss_OID		new_mechs_array = NULL;
+    gss_cred_id_t *	new_cred_array = NULL;
+
+    status = val_add_cred_args(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);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    mech = gssint_get_mechanism(desired_mech);
+    if (!mech)
+	return GSS_S_BAD_MECH;
+    else if (!mech->gss_acquire_cred)
+	return (GSS_S_UNAVAILABLE);
+
+    if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+	union_cred = malloc(sizeof (gss_union_cred_desc));
+	if (union_cred == NULL)
+	    return (GSS_S_FAILURE);
+
+	(void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
+
+	/* for default credentials we will use GSS_C_NO_NAME */
+	internal_name = GSS_C_NO_NAME;
+    } else {
+	union_cred = (gss_union_cred_t)input_cred_handle;
+	if (gssint_get_mechanism_cred(union_cred, desired_mech) !=
+	    GSS_C_NO_CREDENTIAL)
+	    return (GSS_S_DUPLICATE_ELEMENT);
+
+	/* may need to create a mechanism specific name */
+	if (desired_name) {
+	    union_name = (gss_union_name_t)desired_name;
+	    if (union_name->mech_type &&
+		g_OID_equal(union_name->mech_type,
+			    &mech->mech_type))
+		internal_name = union_name->mech_name;
+	    else {
+		if (gssint_import_internal_name(minor_status,
+					       &mech->mech_type, union_name,
+					       &allocated_name) != GSS_S_COMPLETE)
+		    return (GSS_S_BAD_NAME);
+		internal_name = allocated_name;
+	    }
+	}
+    }
+
+
+    if (cred_usage == GSS_C_ACCEPT)
+	time_req = acceptor_time_req;
+    else if (cred_usage == GSS_C_INITIATE)
+	time_req = initiator_time_req;
+    else if (cred_usage == GSS_C_BOTH)
+	time_req = (acceptor_time_req > initiator_time_req) ?
+	    acceptor_time_req : initiator_time_req;
+
+    status = mech->gss_acquire_cred(mech->context, minor_status,
+				    internal_name, time_req,
+				    GSS_C_NULL_OID_SET, cred_usage,
+				    &cred, NULL, &time_rec);
+
+    if (status != GSS_S_COMPLETE)
+	goto errout;
+
+    /* may need to set credential auxinfo strucutre */
+    if (union_cred->auxinfo.creation_time == 0) {
+	union_cred->auxinfo.creation_time = time(NULL);
+	union_cred->auxinfo.time_rec = time_rec;
+	union_cred->auxinfo.cred_usage = cred_usage;
+
+	/*
+	 * we must set the name; if name is not supplied
+	 * we must do inquire cred to get it
+	 */
+	if (internal_name == NULL) {
+	    if (mech->gss_inquire_cred == NULL ||
+		((status = mech->gss_inquire_cred(
+		      mech->context,
+		      &temp_minor_status, cred,
+		      &allocated_name, NULL, NULL,
+		      NULL)) != GSS_S_COMPLETE))
+		goto errout;
+	    internal_name = allocated_name;
+	}
+
+	if (internal_name != GSS_C_NO_NAME) {
+	    status = mech->gss_display_name(mech->context,
+					    &temp_minor_status, internal_name,
+					    &union_cred->auxinfo.name,
+					    &union_cred->auxinfo.name_type);
+	
+	    if (status != GSS_S_COMPLETE)
+		goto errout;
+	}
+    }
+
+    /* now add the new credential elements */
+    new_mechs_array = (gss_OID)
+	malloc(sizeof (gss_OID_desc) * (union_cred->count+1));
+
+    new_cred_array = (gss_cred_id_t *)
+	malloc(sizeof (gss_cred_id_t) * (union_cred->count+1));
+
+    if (!new_mechs_array || !new_cred_array) {
+	status = GSS_S_FAILURE;
+	goto errout;
+    }
+
+    if (acceptor_time_rec)
+	if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)
+	    *acceptor_time_rec = time_rec;
+    if (initiator_time_rec)
+	if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH)
+	    *initiator_time_rec = time_rec;
+
+    /*
+     * OK, expand the mechanism array and the credential array
+     */
+    (void) memcpy(new_mechs_array, union_cred->mechs_array,
+		  sizeof (gss_OID_desc) * union_cred->count);
+    (void) memcpy(new_cred_array, union_cred->cred_array,
+		  sizeof (gss_cred_id_t) * union_cred->count);
+
+    new_cred_array[union_cred->count] = cred;
+    if ((new_mechs_array[union_cred->count].elements =
+	 malloc(mech->mech_type.length)) == NULL)
+	goto errout;
+
+    g_OID_copy(&new_mechs_array[union_cred->count],
+	       &mech->mech_type);
+
+    if (actual_mechs) {
+	*actual_mechs = create_actual_mechs(new_mechs_array,
+					    union_cred->count + 1);
+	if (*actual_mechs == NULL) {
+	    free(new_mechs_array[union_cred->count].elements);
+	    goto errout;
+	}
+    }
+
+    if (output_cred_handle == NULL) {
+	free(union_cred->mechs_array);
+	free(union_cred->cred_array);
+	new_union_cred = union_cred;
+    } else {
+	new_union_cred = malloc(sizeof (gss_union_cred_desc));
+	if (new_union_cred == NULL) {
+	    free(new_mechs_array[union_cred->count].elements);
+	    goto errout;
+	}
+	*new_union_cred = *union_cred;
+	*output_cred_handle = (gss_cred_id_t)new_union_cred;
+    }
+
+    new_union_cred->mechs_array = new_mechs_array;
+    new_union_cred->cred_array = new_cred_array;
+    new_union_cred->count++;
+    new_union_cred->loopback = new_union_cred;
+
+    /* We're done with the internal name. Free it if we allocated it. */
+
+    if (allocated_name)
+	(void) gssint_release_internal_name(&temp_minor_status,
+					   &mech->mech_type,
+					   &allocated_name);
+
+    return (GSS_S_COMPLETE);
+
+errout:
+    if (new_mechs_array)
+	free(new_mechs_array);
+    if (new_cred_array)
+	free(new_cred_array);
+
+    if (cred != NULL && mech->gss_release_cred)
+	mech->gss_release_cred(mech->context,
+			       &temp_minor_status, &cred);
+
+    if (allocated_name)
+	(void) gssint_release_internal_name(&temp_minor_status,
+					   &mech->mech_type,
+					   &allocated_name);
+
+    if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) {
+	if (union_cred->auxinfo.name.value)
+	    free(union_cred->auxinfo.name.value);
+	free(union_cred);
+    }
+
+    return (status);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_canon_name.c b/krb5-1-6/src/lib/gssapi/mechglue/g_canon_name.c
new file mode 100644
index 000000000..9f72055b3
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_canon_name.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident	"@(#)g_canon_name.c	1.15	04/02/23 SMI" */
+
+/*
+ * routine gss_canonicalize_name
+ *
+ * This routine is used to produce a mechanism specific
+ * representation of name that has been previously
+ * imported with gss_import_name.  The routine uses the mechanism
+ * specific implementation of gss_import_name to implement this
+ * function.
+ *
+ * We allow a NULL output_name, in which case we modify the
+ * input_name to include the mechanism specific name.
+ */
+
+#include <mglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+static OM_uint32
+val_canon_name_args(
+	OM_uint32 *minor_status,
+	const gss_name_t input_name,
+	const gss_OID mech_type,
+	gss_name_t *output_name)
+{
+
+	/* Initialize outputs. */
+
+	if (minor_status != NULL)
+		*minor_status = 0;
+
+	if (output_name != NULL)
+		*output_name = GSS_C_NO_NAME;
+
+	/* Validate arguments. */
+
+	if (minor_status == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	if (input_name == GSS_C_NO_NAME || mech_type == GSS_C_NULL_OID)
+		return (GSS_S_CALL_INACCESSIBLE_READ);
+
+	return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_canonicalize_name(minor_status,
+				input_name,
+				mech_type,
+				output_name)
+OM_uint32 *minor_status;
+const gss_name_t input_name;
+const gss_OID mech_type;
+gss_name_t *output_name;
+{
+	gss_union_name_t in_union, out_union = NULL, dest_union = NULL;
+	OM_uint32 major_status = GSS_S_FAILURE;
+
+	major_status = val_canon_name_args(minor_status,
+					   input_name,
+					   mech_type,
+					   output_name);
+	if (major_status != GSS_S_COMPLETE)
+		return (major_status);
+
+	/* Initial value needed below. */
+	major_status = GSS_S_FAILURE;
+
+	in_union = (gss_union_name_t)input_name;
+	/*
+	 * If the caller wants to reuse the name, and the name has already
+	 * been converted, then there is nothing for us to do.
+	 */
+	if (!output_name && in_union->mech_type &&
+		g_OID_equal(in_union->mech_type, mech_type))
+		return (GSS_S_COMPLETE);
+
+	/* ok, then we need to do something - start by creating data struct */
+	if (output_name) {
+		out_union =
+			(gss_union_name_t)malloc(sizeof (gss_union_name_desc));
+		if (!out_union)
+			goto allocation_failure;
+
+		out_union->mech_type = 0;
+		out_union->mech_name = 0;
+		out_union->name_type = 0;
+		out_union->external_name = 0;
+		out_union->loopback = out_union;
+
+		/* Allocate the buffer for the user specified representation */
+		if (gssint_create_copy_buffer(in_union->external_name,
+				&out_union->external_name, 1))
+			goto allocation_failure;
+
+		if (in_union->name_type != GSS_C_NULL_OID) {
+			if ((major_status = generic_gss_copy_oid(minor_status,
+				in_union->name_type, &out_union->name_type)))
+			goto allocation_failure;
+		}
+
+	}
+
+	/*
+	 * might need to delete any old mechanism names if we are
+	 * reusing the buffer.
+	 */
+	if (!output_name) {
+		if (in_union->mech_type) {
+			(void) gssint_release_internal_name(minor_status,
+							in_union->mech_type,
+							&in_union->mech_name);
+			(void) gss_release_oid(minor_status,
+					    &in_union->mech_type);
+			in_union->mech_type = 0;
+		}
+		dest_union = in_union;
+	} else
+		dest_union = out_union;
+
+	/* now let's create the new mech name */
+	if ((major_status = generic_gss_copy_oid(minor_status, mech_type,
+						&dest_union->mech_type)))
+		goto allocation_failure;
+
+	if ((major_status =
+		gssint_import_internal_name(minor_status, mech_type,
+						dest_union,
+						&dest_union->mech_name)))
+		goto allocation_failure;
+
+	if (output_name)
+		*output_name = (gss_name_t)dest_union;
+
+	return (GSS_S_COMPLETE);
+
+allocation_failure:
+	/* do not delete the src name external name format */
+	if (output_name) {
+		if (out_union->external_name) {
+			if (out_union->external_name->value)
+				free(out_union->external_name->value);
+			free(out_union->external_name);
+		}
+		if (out_union->name_type)
+			(void) gss_release_oid(minor_status,
+					    &out_union->name_type);
+
+		dest_union = out_union;
+	} else
+		dest_union = in_union;
+
+	/*
+	 * delete the partially created mech specific name
+	 * applies for both src and dest which ever is being used for output
+	 */
+
+	if (dest_union->mech_name) {
+		(void) gssint_release_internal_name(minor_status,
+						dest_union->mech_type,
+						&dest_union->mech_name);
+	}
+
+	if (dest_union->mech_type)
+		(void) gss_release_oid(minor_status, &dest_union->mech_type);
+
+
+	if (output_name)
+		free(out_union);
+
+	return (major_status);
+} /**********  gss_canonicalize_name ********/
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_compare_name.c b/krb5-1-6/src/lib/gssapi/mechglue/g_compare_name.c
new file mode 100644
index 000000000..7fb5cc9cf
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_compare_name.c
@@ -0,0 +1,197 @@
+/* #pragma ident	"@(#)g_compare_name.c	1.16	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_compare_name
+ *
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+static OM_uint32
+val_comp_name_args(
+    OM_uint32 *minor_status,
+    gss_name_t name1,
+    gss_name_t name2,
+    int *name_equal)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    /* Validate arguments. */
+
+    if (name1 == GSS_C_NO_NAME || name2 == GSS_C_NO_NAME)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+    if (name_equal == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_compare_name (minor_status,
+                  name1,
+                  name2,
+                  name_equal)
+
+OM_uint32 *		minor_status;
+gss_name_t		name1;
+gss_name_t		name2;
+int *			name_equal;
+
+{
+    OM_uint32		major_status, temp_minor;
+    gss_union_name_t	union_name1, union_name2;
+    gss_mechanism	mech;
+    gss_name_t		internal_name;
+    
+    major_status = val_comp_name_args(minor_status,
+				      name1, name2, name_equal);
+    if (major_status != GSS_S_COMPLETE)
+	return (major_status);
+
+    union_name1 = (gss_union_name_t) name1;
+    union_name2 = (gss_union_name_t) name2;
+    /*
+     * Try our hardest to make union_name1 be the mechanism-specific
+     * name.  (Of course we can't if both names aren't
+     * mechanism-specific.)
+     */
+    if (union_name1->mech_type == 0) {
+	union_name1 = (gss_union_name_t) name2;
+	union_name2 = (gss_union_name_t) name1;
+    }
+    /*
+     * If union_name1 is mechanism specific, then fetch its mechanism
+     * information.
+     */
+    if (union_name1->mech_type) {
+	mech = gssint_get_mechanism (union_name1->mech_type);
+	if (!mech)
+	    return (GSS_S_BAD_MECH);
+	if (!mech->gss_compare_name)
+			return (GSS_S_UNAVAILABLE);
+    }
+	
+    *name_equal = 0;		/* Default to *not* equal.... */
+
+    /*
+     * First case... both names are mechanism-specific
+     */
+    if (union_name1->mech_type && union_name2->mech_type) {
+	if (!g_OID_equal(union_name1->mech_type, union_name2->mech_type))
+	    return (GSS_S_COMPLETE);
+	if ((union_name1->mech_name == 0) || (union_name2->mech_name == 0))
+	    /* should never happen */
+	    return (GSS_S_BAD_NAME);
+	return (mech->gss_compare_name(mech->context, minor_status,
+				       union_name1->mech_name,
+				       union_name2->mech_name, name_equal));
+	
+    }
+
+    /*
+     * Second case... both names are NOT mechanism specific.
+     * 
+     * All we do here is make sure the two name_types are equal and then
+     * that the external_names are equal. Note the we do not take care
+     * of the case where two different external names map to the same
+     * internal name. We cannot determine this, since we as yet do not
+     * know what mechanism to use for calling the underlying
+     * gss_import_name().
+     */
+    if (!union_name1->mech_type && !union_name2->mech_type) {
+		/*
+		 * Second case, first sub-case... one name has null
+		 * name_type, the other doesn't.
+		 *
+		 * Not knowing a mech_type we can't import the name with
+		 * null name_type so we can't compare.
+		 */
+		if ((union_name1->name_type == GSS_C_NULL_OID &&
+		    union_name2->name_type != GSS_C_NULL_OID) ||
+		    (union_name1->name_type != GSS_C_NULL_OID &&
+		    union_name2->name_type == GSS_C_NULL_OID))
+			return (GSS_S_COMPLETE);
+		/*
+		 * Second case, second sub-case... both names have
+		 * name_types, but they are different.
+		 */
+		if ((union_name1->name_type != GSS_C_NULL_OID &&
+		    union_name2->name_type != GSS_C_NULL_OID) &&
+		    !g_OID_equal(union_name1->name_type,
+					union_name2->name_type))
+	    return (GSS_S_COMPLETE);
+		/*
+		 * Second case, third sub-case... both names have equal
+		 * name_types (and both have no mech_types) so we just
+		 * compare the external_names.
+		 */
+	if ((union_name1->external_name->length !=
+	     union_name2->external_name->length) ||
+	    (memcmp(union_name1->external_name->value,
+		    union_name2->external_name->value,
+		    union_name1->external_name->length) != 0))
+	    return (GSS_S_COMPLETE);
+	*name_equal = 1;
+	return (GSS_S_COMPLETE);
+    }
+
+    /*
+     * Final case... one name is mechanism specific, the other isn't.
+     * 
+     * We attempt to convert the general name to the mechanism type of
+     * the mechanism-specific name, and then do the compare.  If we
+     * can't import the general name, then we return that the name is
+     * _NOT_ equal.
+     */
+    if (union_name2->mech_type) {
+	/* We make union_name1 the mechanism specific name. */
+	union_name1 = (gss_union_name_t) name2;
+	union_name2 = (gss_union_name_t) name1;
+    }
+    major_status = gssint_import_internal_name(minor_status,
+					      union_name1->mech_type,
+					      union_name2,
+					      &internal_name);
+    if (major_status != GSS_S_COMPLETE)
+	return (GSS_S_COMPLETE); /* return complete, but not equal */
+
+    major_status = mech->gss_compare_name(mech->context, minor_status,
+					  union_name1->mech_name,
+					  internal_name, name_equal);
+    gssint_release_internal_name(&temp_minor, union_name1->mech_type,
+				&internal_name);
+    return (major_status);
+    
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_context_time.c b/krb5-1-6/src/lib/gssapi/mechglue/g_context_time.c
new file mode 100644
index 000000000..5ce6b56d8
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_context_time.c
@@ -0,0 +1,78 @@
+/* #pragma ident	"@(#)g_context_time.c	1.12	98/01/22 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routines for gss_context_time
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_context_time (minor_status,
+                  context_handle,
+                  time_rec)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+OM_uint32 *		time_rec;
+
+{
+    OM_uint32		status;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+    *minor_status = 0;
+
+    if (time_rec == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+    
+    if (mech) {
+
+	if (mech->gss_context_time)
+	    status = mech->gss_context_time(
+					    mech->context,
+					    minor_status,
+					    ctx->internal_ctx_id,
+					    time_rec);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return(status);
+    }
+    
+    return (GSS_S_BAD_MECH);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_delete_sec_context.c b/krb5-1-6/src/lib/gssapi/mechglue/g_delete_sec_context.c
new file mode 100644
index 000000000..bf2e9010f
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_delete_sec_context.c
@@ -0,0 +1,113 @@
+/* #pragma ident	"@(#)g_delete_sec_context.c	1.11	97/11/09 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_delete_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+static OM_uint32
+val_del_sec_ctx_args(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t *context_handle,
+    gss_buffer_t output_token)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (output_token != GSS_C_NO_BUFFER) {
+	output_token->length = 0;
+	output_token->value = NULL;
+    }
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV 
+gss_delete_sec_context (minor_status,
+                        context_handle,
+                        output_token)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t *		context_handle;
+gss_buffer_t		output_token;
+
+{
+    OM_uint32		status;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+
+    status = val_del_sec_ctx_args(minor_status, context_handle, output_token);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    ctx = (gss_union_ctx_id_t) *context_handle;
+    if (GSSINT_CHK_LOOP(ctx))
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+    mech = gssint_get_mechanism (ctx->mech_type);
+    
+    if (mech) {
+
+	if (mech->gss_delete_sec_context)
+	    status = mech->gss_delete_sec_context(
+						  mech->context,
+						  minor_status,
+						  &ctx->internal_ctx_id,
+						  output_token);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	/* now free up the space for the union context structure */
+	free(ctx->mech_type->elements);
+	free(ctx->mech_type);
+	free(*context_handle);
+	*context_handle = NULL;
+
+	return(status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_dsp_name.c b/krb5-1-6/src/lib/gssapi/mechglue/g_dsp_name.c
new file mode 100644
index 000000000..7db90584d
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_dsp_name.c
@@ -0,0 +1,136 @@
+/* #pragma ident	"@(#)g_dsp_name.c	1.13	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_display_name()
+ *
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+static OM_uint32
+val_dsp_name_args(
+    OM_uint32 *minor_status,
+    gss_name_t input_name,
+    gss_buffer_t output_name_buffer,
+    gss_OID *output_name_type)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (output_name_buffer != GSS_C_NO_BUFFER) {
+	output_name_buffer->length = 0;
+	output_name_buffer->value = NULL;
+    }
+
+    if (output_name_type != NULL)
+	*output_name_type = GSS_C_NO_OID;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (output_name_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (input_name == GSS_C_NO_NAME)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_display_name (minor_status,
+                  input_name,
+                  output_name_buffer,
+                  output_name_type)
+
+OM_uint32 *		minor_status;
+gss_name_t		input_name;
+gss_buffer_t		output_name_buffer;
+gss_OID *		output_name_type;
+
+{
+    OM_uint32		major_status;
+    gss_union_name_t	union_name;
+
+    major_status = val_dsp_name_args(minor_status, input_name,
+				     output_name_buffer, output_name_type);
+    if (major_status != GSS_S_COMPLETE)
+	return (major_status);
+
+    union_name = (gss_union_name_t) input_name;
+
+    if (union_name->mech_type) {
+	/*
+	 * OK, we have a mechanism-specific name; let's use it!
+	 */
+	return (gssint_display_internal_name(minor_status,
+					    union_name->mech_type,
+					    union_name->mech_name,
+					    output_name_buffer,
+					    output_name_type));
+    }
+    
+    /*
+     * copy the value of the external_name component of the union
+     * name into the output_name_buffer and point the output_name_type
+     * to the name_type component of union_name
+     */
+    if (output_name_type != NULL &&
+	union_name->name_type != GSS_C_NULL_OID) {
+	major_status = generic_gss_copy_oid(minor_status,
+					    union_name->name_type,
+					    output_name_type);
+	if (major_status != GSS_S_COMPLETE)
+	    return (major_status);
+    }
+
+    if ((output_name_buffer->value =
+	 malloc(union_name->external_name->length + 1)) == NULL) {
+	if (output_name_type && *output_name_type != GSS_C_NULL_OID) {
+	    (void) generic_gss_release_oid(minor_status,
+					   output_name_type);
+	    *output_name_type = NULL;
+	}
+	return (GSS_S_FAILURE);
+    }
+    output_name_buffer->length = union_name->external_name->length;
+    (void) memcpy(output_name_buffer->value,
+		  union_name->external_name->value,
+		  union_name->external_name->length);
+    ((char *)output_name_buffer->value)[output_name_buffer->length] = '\0';
+
+    return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_dsp_status.c b/krb5-1-6/src/lib/gssapi/mechglue/g_dsp_status.c
new file mode 100644
index 000000000..519d4a4a1
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_dsp_status.c
@@ -0,0 +1,327 @@
+/* #pragma ident	"@(#)g_dsp_status.c	1.17	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_display_status
+ *
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* local function */
+static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t);
+
+OM_uint32 KRB5_CALLCONV
+gss_display_status (minor_status,
+                    status_value,
+                    status_type,
+                    req_mech_type,
+                    message_context,
+                    status_string)
+
+OM_uint32 *		minor_status;
+OM_uint32		status_value;
+int			status_type;
+gss_OID			req_mech_type;
+OM_uint32 *		message_context;
+gss_buffer_t		status_string;
+
+{
+    gss_OID		mech_type = (gss_OID) req_mech_type;
+    gss_mechanism	mech;
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (status_string != GSS_C_NO_BUFFER) {
+	status_string->length = 0;
+	status_string->value = NULL;
+    }
+
+    if (minor_status == NULL ||
+	message_context == NULL ||
+	status_string == GSS_C_NO_BUFFER)
+
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    /* we handle major status codes, and the mechs do the minor */
+    if (status_type == GSS_C_GSS_CODE)
+	return (displayMajor(status_value, message_context,
+			     status_string));
+
+    /*
+     * must be the minor status - let mechs do the work
+     * select the appropriate underlying mechanism routine and
+     * call it.
+     */
+
+    mech = gssint_get_mechanism (mech_type);
+
+    if (mech && mech->gss_display_status) {
+	if (mech_type == GSS_C_NULL_OID)
+	    mech_type = &mech->mech_type;
+
+	return (mech->gss_display_status(mech->context, minor_status,
+					 status_value, status_type, mech_type,
+					 message_context, status_string));
+    }
+
+    if (!mech)
+	return (GSS_S_BAD_MECH);
+
+    return (GSS_S_UNAVAILABLE);
+}
+
+/*
+ * function to map the major error codes
+ * it uses case statements so that the strings could be wrapped by gettext
+ * msgCtxt is interpreted as:
+ *	0 - first call
+ *	1 - routine error
+ *	>= 2 - the supplementary error code bit shifted by 1
+ */
+static OM_uint32
+displayMajor(status, msgCtxt, outStr)
+OM_uint32 status;
+OM_uint32 *msgCtxt;
+gss_buffer_t outStr;
+{
+	OM_uint32 oneVal, mask = 0x1, currErr;
+	char *errStr = NULL;
+	int i, haveErr = 0;
+
+	/* take care of the success value first */
+	if (status == GSS_S_COMPLETE)
+		errStr = "The routine completed successfully";
+	else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) {
+		switch (oneVal) {
+		case GSS_S_CALL_INACCESSIBLE_READ:
+			errStr = "A required input parameter"
+				" could not be read";
+			break;
+
+		case GSS_S_CALL_INACCESSIBLE_WRITE:
+			errStr = "A required output parameter"
+				" could not be written";
+			break;
+
+		case GSS_S_CALL_BAD_STRUCTURE:
+			errStr = "A parameter was malformed";
+			break;
+
+		default:
+			errStr = "An invalid status code was supplied";
+			break;
+		}
+
+		/* we now need to determine new value of msgCtxt */
+		if (GSS_ROUTINE_ERROR(status))
+			*msgCtxt = 1;
+		else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+			*msgCtxt = (OM_uint32)(oneVal << 1);
+		else
+			*msgCtxt = 0;
+
+	} else if ((*msgCtxt == 0 || *msgCtxt == 1) &&
+		(oneVal = GSS_ROUTINE_ERROR(status))) {
+		switch (oneVal) {
+		case GSS_S_BAD_MECH:
+			errStr = "An unsupported mechanism"
+				" was requested";
+			break;
+
+		case GSS_S_BAD_NAME:
+			errStr = "An invalid name was supplied";
+			break;
+
+		case GSS_S_BAD_NAMETYPE:
+			errStr = "A supplied name was of an"
+				" unsupported type";
+			break;
+
+		case GSS_S_BAD_BINDINGS:
+			errStr = "Incorrect channel bindings"
+				" were supplied";
+			break;
+
+		case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */
+			errStr = "A token had an invalid Message"
+				" Integrity Check (MIC)";
+			break;
+
+		case GSS_S_NO_CRED:
+			errStr = "No credentials were supplied, or the"
+				" credentials were unavailable or"
+				" inaccessible";
+			break;
+
+		case GSS_S_NO_CONTEXT:
+			errStr = "No context has been established";
+			break;
+
+		case GSS_S_DEFECTIVE_TOKEN:
+			errStr = "Invalid token was supplied";
+			break;
+
+		case GSS_S_DEFECTIVE_CREDENTIAL:
+			errStr = "Invalid credential was supplied";
+			break;
+
+		case GSS_S_CREDENTIALS_EXPIRED:
+			errStr = "The referenced credential has"
+				" expired";
+			break;
+
+		case GSS_S_CONTEXT_EXPIRED:
+			errStr = "The referenced context has expired";
+			break;
+
+		case GSS_S_FAILURE:
+			errStr = "Unspecified GSS failure.  Minor code"
+				" may provide more information";
+			break;
+
+		case GSS_S_BAD_QOP:
+			errStr = "The quality-of-protection (QOP) "
+				"requested could not be provided";
+			break;
+
+		case GSS_S_UNAUTHORIZED:
+			errStr = "The operation is forbidden by local"
+				" security policy";
+			break;
+
+		case GSS_S_UNAVAILABLE:
+			errStr = "The operation or option is not"
+				" available or unsupported";
+			break;
+
+		case GSS_S_DUPLICATE_ELEMENT:
+			errStr = "The requested credential element"
+				" already exists";
+			break;
+
+		case GSS_S_NAME_NOT_MN:
+			errStr = "The provided name was not mechanism"
+				" specific (MN)";
+			break;
+
+		case GSS_S_BAD_STATUS:
+		default:
+			errStr = "An invalid status code was supplied";
+		}
+
+		/* we must determine if the caller should call us again */
+		if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+			*msgCtxt = (OM_uint32)(oneVal << 1);
+		else
+			*msgCtxt = 0;
+
+	} else if ((*msgCtxt == 0 || *msgCtxt >= 2) &&
+		(oneVal = GSS_SUPPLEMENTARY_INFO(status))) {
+		/*
+		 * if msgCtxt is not 0, then it should encode
+		 * the supplementary error code we should be printing
+		 */
+		if (*msgCtxt >= 2)
+			oneVal = (OM_uint32) (*msgCtxt) >> 1;
+		else
+			oneVal = GSS_SUPPLEMENTARY_INFO(status);
+
+		/* we display the errors LSB first */
+		for (i = 0; i < 16; i++) {
+			if (oneVal & mask) {
+				haveErr = 1;
+				break;
+			}
+			mask <<= 1;
+		}
+
+		/* isolate the bit or if not found set to illegal value */
+		if (haveErr)
+			currErr = oneVal & mask;
+		else
+			currErr = 1 << 17; /* illegal value */
+
+		switch (currErr) {
+		case GSS_S_CONTINUE_NEEDED:
+			errStr = "The routine must be called again to"
+				" complete its function";
+			break;
+
+		case GSS_S_DUPLICATE_TOKEN:
+			errStr = "The token was a duplicate of an"
+				" earlier token";
+			break;
+
+		case GSS_S_OLD_TOKEN:
+			errStr = "The token's validity period"
+				" has expired";
+			break;
+
+		case GSS_S_UNSEQ_TOKEN:
+			errStr = "A later token has already been"
+				" processed";
+			break;
+
+		case GSS_S_GAP_TOKEN:
+			errStr = "An expected per-message token was"
+				" not received";
+			break;
+
+		default:
+			errStr = "An invalid status code was supplied";
+		}
+
+		/*
+		 * we must check if there is any other supplementary errors
+		 * if found, then turn off current bit, and store next value
+		 * in msgCtxt shifted by 1 bit
+		 */
+		if (!haveErr)
+			*msgCtxt = 0;
+		else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask)
+			*msgCtxt = (OM_uint32)
+				((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1);
+		else
+			*msgCtxt = 0;
+	}
+
+	if (errStr == NULL)
+		errStr = "An invalid status code was supplied";
+
+	/* now copy the status code and return to caller */
+	outStr->length = strlen(errStr);
+	outStr->value = malloc((size_t)outStr->length+1);
+	if (outStr->value == NULL) {
+		outStr->length = 0;
+		return (GSS_S_FAILURE);
+	}
+
+	(void) strcpy((char *)outStr->value, errStr);
+	return (GSS_S_COMPLETE);
+} /* displayMajor */
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_dup_name.c b/krb5-1-6/src/lib/gssapi/mechglue/g_dup_name.c
new file mode 100644
index 000000000..1d37be9e1
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_dup_name.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident	"@(#)g_dup_name.c	1.14	04/02/23 SMI" */
+
+/*
+ *  routine gss_duplicate_name
+ *
+ * This routine does not rely on mechanism implementation of this
+ * name, but instead uses mechanism specific gss_import_name routine.
+ */
+
+#include <mglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+static OM_uint32
+val_dup_name_args(
+	OM_uint32 *minor_status,
+	const gss_name_t src_name,
+	gss_name_t *dest_name)
+{
+
+	/* Initialize outputs. */
+
+	if (minor_status != NULL)
+		*minor_status = 0;
+
+	if (dest_name != NULL)
+		*dest_name = GSS_C_NO_NAME;
+
+	/* Validate arguments. */
+
+	if (minor_status == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	/* if output_name is NULL, simply return */
+	if (dest_name == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	if (src_name == GSS_C_NO_NAME)
+		return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+	return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_duplicate_name(minor_status,
+		src_name,
+		dest_name)
+OM_uint32 *minor_status;
+const gss_name_t src_name;
+gss_name_t *dest_name;
+{
+		gss_union_name_t src_union, dest_union;
+		OM_uint32 major_status = GSS_S_FAILURE;
+
+	major_status = val_dup_name_args(minor_status, src_name, dest_name);
+	if (major_status != GSS_S_COMPLETE)
+		return (major_status);
+
+	src_union = (gss_union_name_t)src_name;
+
+	/*
+	 * First create the union name struct that will hold the external
+	 * name and the name type.
+	 */
+	dest_union = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
+	if (!dest_union)
+		goto allocation_failure;
+
+	dest_union->loopback = 0;
+	dest_union->mech_type = 0;
+	dest_union->mech_name = 0;
+	dest_union->name_type = 0;
+	dest_union->external_name = 0;
+
+	/* Now copy the external representaion */
+	if (gssint_create_copy_buffer(src_union->external_name,
+				&dest_union->external_name, 0))
+		goto allocation_failure;
+
+	if (src_union->name_type != GSS_C_NULL_OID) {
+		major_status = generic_gss_copy_oid(minor_status,
+						src_union->name_type,
+						&dest_union->name_type);
+		if (major_status != GSS_S_COMPLETE)
+			goto allocation_failure;
+	}
+
+	/*
+	 * See if source name is mechanim specific, if so then need to import it
+	 */
+	if (src_union->mech_type) {
+		major_status = generic_gss_copy_oid(minor_status,
+							src_union->mech_type,
+							&dest_union->mech_type);
+		if (major_status != GSS_S_COMPLETE)
+			goto allocation_failure;
+
+		major_status = gssint_import_internal_name(minor_status,
+							dest_union->mech_type,
+							dest_union,
+							&dest_union->mech_name);
+		if (major_status != GSS_S_COMPLETE)
+			goto allocation_failure;
+	}
+
+
+	dest_union->loopback = dest_union;
+	*dest_name = (gss_name_t)dest_union;
+	return (GSS_S_COMPLETE);
+
+allocation_failure:
+	if (dest_union) {
+		if (dest_union->external_name) {
+			if (dest_union->external_name->value)
+				free(dest_union->external_name->value);
+				free(dest_union->external_name);
+		}
+		if (dest_union->name_type)
+			(void) generic_gss_release_oid(minor_status,
+							&dest_union->name_type);
+		if (dest_union->mech_name)
+			(void) gssint_release_internal_name(minor_status,
+						dest_union->mech_type,
+						&dest_union->mech_name);
+		if (dest_union->mech_type)
+			(void) generic_gss_release_oid(minor_status,
+							&dest_union->mech_type);
+		free(dest_union);
+	}
+	return (major_status);
+} /*	gss_duplicate_name	*/
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_exp_sec_context.c b/krb5-1-6/src/lib/gssapi/mechglue/g_exp_sec_context.c
new file mode 100644
index 000000000..1490a2b37
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_exp_sec_context.c
@@ -0,0 +1,135 @@
+/* #pragma ident	"@(#)g_exp_sec_context.c	1.14	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_export_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+static OM_uint32
+val_exp_sec_ctx_args(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t *context_handle,
+    gss_buffer_t interprocess_token)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (interprocess_token != GSS_C_NO_BUFFER) {
+	interprocess_token->length = 0;
+	interprocess_token->value = NULL;
+    }
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    if (interprocess_token == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_export_sec_context(minor_status,
+                       context_handle,
+                       interprocess_token)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t *		context_handle;
+gss_buffer_t		interprocess_token;
+
+{
+    OM_uint32		status;
+    OM_uint32 		length;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+    gss_buffer_desc	token;
+    char		*buf;
+
+    status = val_exp_sec_ctx_args(minor_status,
+				  context_handle, interprocess_token);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    ctx = (gss_union_ctx_id_t) *context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+    if (!mech)
+	return GSS_S_BAD_MECH;
+    if (!mech->gss_export_sec_context)
+	return (GSS_S_UNAVAILABLE);
+    
+    status = mech->gss_export_sec_context(mech->context, minor_status,
+					  &ctx->internal_ctx_id, &token);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    length = token.length + 4 + ctx->mech_type->length;
+    interprocess_token->length = length;
+    interprocess_token->value = malloc(length);
+    if (interprocess_token->value == 0) {
+	(void) gss_release_buffer(minor_status, &token);
+	return (GSS_S_FAILURE);
+    }
+    buf = interprocess_token->value;
+    length = ctx->mech_type->length;
+    buf[3] = (unsigned char) (length & 0xFF);
+    length >>= 8;
+    buf[2] = (unsigned char) (length & 0xFF);
+    length >>= 8;
+    buf[1] = (unsigned char) (length & 0xFF);
+    length >>= 8;
+    buf[0] = (unsigned char) (length & 0xFF);
+    memcpy(buf+4, ctx->mech_type->elements, (size_t) ctx->mech_type->length);
+    memcpy(buf+4+ctx->mech_type->length, token.value, token.length);
+
+    (void) gss_release_buffer(minor_status, &token);
+
+    free(ctx->mech_type->elements);
+    free(ctx->mech_type);
+    free(ctx);
+    *context_handle = 0;
+    
+    return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_export_name.c b/krb5-1-6/src/lib/gssapi/mechglue/g_export_name.c
new file mode 100644
index 000000000..c845f8caf
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_export_name.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/* #pragma ident	"@(#)g_export_name.c	1.11	00/07/17 SMI" */
+
+/*
+ * glue routine gss_export_name
+ *
+ * Will either call the mechanism defined gss_export_name, or if one is
+ * not defined will call a generic_gss_export_name routine.
+ */
+
+#include <mglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_export_name(minor_status,
+			input_name,
+			exported_name)
+OM_uint32 *		minor_status;
+const gss_name_t	input_name;
+gss_buffer_t		exported_name;
+{
+	gss_union_name_t		union_name;
+
+	/* Initialize outputs. */
+
+	if (minor_status != NULL)
+		*minor_status = 0;
+
+	if (exported_name != GSS_C_NO_BUFFER) {
+		exported_name->value = NULL;
+		exported_name->length = 0;
+	}
+
+	/* Validate arguments. */
+
+	if (minor_status == NULL || exported_name == GSS_C_NO_BUFFER)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	if (input_name == GSS_C_NO_NAME)
+		return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+	union_name = (gss_union_name_t)input_name;
+
+	/* the name must be in mechanism specific format */
+	if (!union_name->mech_type)
+		return (GSS_S_NAME_NOT_MN);
+
+	return gssint_export_internal_name(minor_status, union_name->mech_type,
+					union_name->mech_name, exported_name);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_glue.c b/krb5-1-6/src/lib/gssapi/mechglue/g_glue.c
new file mode 100644
index 000000000..1331862dc
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_glue.c
@@ -0,0 +1,585 @@
+/* #pragma ident	"@(#)g_glue.c	1.25	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+#define	MSO_BIT (8*(sizeof (int) - 1))  /* Most significant octet bit */
+
+extern gss_mechanism *gssint_mechs_array;
+
+/*
+ * This file contains the support routines for the glue layer.
+ */
+
+/*
+ * get_der_length: Givin a pointer to a buffer that contains a DER encoded
+ * length, decode the length updating the buffer to point to the character
+ * after the DER encoding. The parameter bytes will point to the number of
+ * bytes that made up the DER encoding of the length originally pointed to
+ * by the buffer. Note we return -1 on error.
+ */
+int
+gssint_get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes)
+{
+    /* p points to the beginning of the buffer */
+    unsigned char *p = *buf;
+    int length, new_length;
+    int octets;
+
+    if (buf_len < 1)
+	return (-1);
+
+    /* We should have at least one byte */
+    *bytes = 1;
+
+    /*
+     * If the High order bit is not set then the length is just the value
+     * of *p.
+     */
+    if (*p < 128) {
+	*buf = p+1;	/* Advance the buffer */
+	return (*p);		/* return the length */
+    }
+
+    /*
+     * if the High order bit is set, then the low order bits represent
+     * the number of bytes that contain the DER encoding of the length.
+     */
+
+    octets = *p++ & 0x7f;
+    *bytes += octets;
+
+    /* See if the supplied buffer contains enough bytes for the length. */
+    if (octets > buf_len - 1)
+	return (-1);
+
+    /*
+     * Calculate a multibyte length. The length is encoded as an
+     * unsigned integer base 256.
+     */
+    for (length = 0; octets; octets--) {
+	new_length = (length << 8) + *p++;
+	if (new_length < length)  /* overflow */
+	    return (-1);
+	length = new_length;
+    }
+
+    *buf = p; /* Advance the buffer */
+
+    return (length);
+}
+
+/*
+ * der_length_size: Return the number of bytes to encode a given length.
+ */
+unsigned int
+gssint_der_length_size(unsigned int len)
+{
+    int i;
+
+    if (len < 128)
+	return (1);
+
+    for (i = 0; len; i++) {
+	len >>= 8;
+    }
+
+    return (i+1);
+}
+
+/*
+ * put_der_length: Encode the supplied length into the buffer pointed to
+ * by buf. max_length represents the maximum length of the buffer pointed
+ * to by buff. We will advance buf to point to the character after the newly
+ * DER encoded length. We return 0 on success or -l it the length cannot
+ * be encoded in max_len characters.
+ */
+int
+gssint_put_der_length(unsigned int length, unsigned char **buf, unsigned int max_len)
+{
+    unsigned char *s = *buf, *p;
+    unsigned int buf_len = 0;
+    int i, first;
+
+    /* Oops */
+    if (buf == 0 || max_len < 1)
+	return (-1);
+
+    /* Single byte is the length */
+    if (length < 128) {
+	*s++ = length;
+	*buf = s;
+	return (0);
+    }
+
+    /* First byte contains the number of octets */
+    p = s + 1;
+
+    /* Running total of the DER encoding length */
+    buf_len = 0;
+
+    /*
+     * Encode MSB first. We do the encoding by setting a shift
+     * factor to MSO_BIT (24 for 32 bit words) and then shifting the length
+     * by the factor. We then encode the resulting low order byte.
+     * We subtract 8 from the shift factor and repeat to ecnode the next
+     * byte. We stop when the shift factor is zero or we've run out of
+     * buffer to encode into.
+     */
+    first = 0;
+    for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) {
+	unsigned int v;
+	v = (length >> i) & 0xff;
+	if ((v) || first) {
+	    buf_len += 1;
+	    *p++ = v;
+	    first = 1;
+	}
+    }
+    if (i >= 0)			/* buffer overflow */
+	return (-1);
+
+    /*
+     * We go back now and set the first byte to be the length with
+     * the high order bit set.
+     */
+    *s = buf_len | 0x80;
+    *buf = p;
+
+    return (0);
+}
+
+
+/*
+ *  glue routine for get_mech_type
+ *
+ */
+
+OM_uint32 gssint_get_mech_type(OID, token)
+    gss_OID		OID;
+    gss_buffer_t	token;
+{
+    unsigned char * buffer_ptr;
+    int length;
+    
+    /*
+     * This routine reads the prefix of "token" in order to determine
+     * its mechanism type. It assumes the encoding suggested in
+     * Appendix B of RFC 1508. This format starts out as follows :
+     *
+     * tag for APPLICATION 0, Sequence[constructed, definite length]
+     * length of remainder of token
+     * tag of OBJECT IDENTIFIER
+     * length of mechanism OID
+     * encoding of mechanism OID
+     * <the rest of the token>
+     *
+     * Numerically, this looks like :
+     *
+     * 0x60
+     * <length> - could be multiple bytes
+     * 0x06
+     * <length> - assume only one byte, hence OID length < 127
+     * <mech OID bytes>
+     *
+     * The routine fills in the OID value and returns an error as necessary.
+     */
+    
+	if (OID == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	if ((token == NULL) || (token->value == NULL))
+	return (GSS_S_DEFECTIVE_TOKEN);
+    
+    /* Skip past the APP/Sequnce byte and the token length */
+    
+    buffer_ptr = (unsigned char *) token->value;
+
+    if (*(buffer_ptr++) != 0x60)
+	return (GSS_S_DEFECTIVE_TOKEN);
+    length = *buffer_ptr++;
+
+	/* check if token length is null */
+	if (length == 0)
+	    return (GSS_S_DEFECTIVE_TOKEN);
+
+    if (length & 0x80) {
+	if ((length & 0x7f) > 4)
+	    return (GSS_S_DEFECTIVE_TOKEN);
+	buffer_ptr += length & 0x7f;
+    }
+    
+    if (*(buffer_ptr++) != 0x06)
+	return (GSS_S_DEFECTIVE_TOKEN);
+    
+    OID->length = (OM_uint32) *(buffer_ptr++);
+    OID->elements = (void *) buffer_ptr;
+    return (GSS_S_COMPLETE);
+}
+
+
+/*
+ *  Internal routines to get and release an internal mechanism name
+ */
+
+#include "mglueP.h"
+
+OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name, 
+				internal_name)
+OM_uint32	*minor_status;
+gss_OID		mech_type;
+gss_union_name_t	union_name;
+gss_name_t	*internal_name;
+{
+    OM_uint32		status;
+    gss_mechanism	mech;
+
+    mech = gssint_get_mechanism (mech_type);
+    if (mech) {
+	if (mech->gss_import_name)
+	    status = mech->gss_import_name (
+					    mech->context,
+					    minor_status,
+					    union_name->external_name,
+					    union_name->name_type,
+					    internal_name);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return (status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 gssint_export_internal_name(minor_status, mech_type,
+				     internal_name, name_buf)
+    OM_uint32		*minor_status;
+    const gss_OID		mech_type;
+    const gss_name_t	internal_name;
+    gss_buffer_t		name_buf;
+{
+    OM_uint32 status;
+    gss_mechanism mech;
+    gss_buffer_desc dispName;
+    gss_OID nameOid;
+    unsigned char *buf = NULL;
+    const unsigned char tokId[] = "\x04\x01";
+    const unsigned int tokIdLen = 2;
+    const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4;
+    int mechOidDERLen = 0;
+    int mechOidLen = 0;
+
+    mech = gssint_get_mechanism(mech_type);
+    if (!mech)
+	return (GSS_S_BAD_MECH);
+
+    if (mech->gss_export_name)
+	return (mech->gss_export_name(mech->context,
+				      minor_status,
+				      internal_name,
+				      name_buf));
+
+    /*
+     * if we are here it is because the mechanism does not provide
+     * a gss_export_name so we will use our implementation.  We
+     * do required that the mechanism define a gss_display_name.
+     */
+    if (!mech->gss_display_name)
+	return (GSS_S_UNAVAILABLE);
+
+    /*
+     * NOTE: RFC2743 (section 3.2) governs the format of the outer
+     *	 wrapper of exported names; the mechanisms' specs govern
+     *	 the format of the inner portion of the exported name
+     *	 and, for some (e.g., RFC1964, the Kerberos V mech), a
+     *	 generic default as implemented here will do.
+     *
+     * The outer wrapper of an exported MN is: 2-octet tok Id
+     * (0x0401) + 2-octet network-byte order mech OID length + mech
+     * oid (in DER format, including DER tag and DER length) +
+     * 4-octet network-byte order length of inner portion + inner
+     * portion.
+     *
+     * For the Kerberos V mechanism the inner portion of an exported
+     * MN is the display name string and ignores the name type OID
+     * altogether.  And we hope this will be so for any future
+     * mechanisms also, so that factoring name export/import out of
+     * the mech and into libgss pays off.
+     */
+    if ((status = mech->gss_display_name(mech->context,
+					 minor_status,
+					 internal_name,
+					 &dispName,
+					 &nameOid))
+	!= GSS_S_COMPLETE)
+	return (status);
+
+    /* determine the size of the buffer needed */
+    mechOidDERLen = gssint_der_length_size(mech_type->length);
+    name_buf->length = tokIdLen + mechOidLenLen +
+	mechOidTagLen + mechOidDERLen +
+	mech_type->length +
+	nameLenLen + dispName.length;
+    if ((name_buf->value = (void*)malloc(name_buf->length)) ==
+	(void*)NULL) {
+	name_buf->length = 0;
+	(void) gss_release_buffer(&status, &dispName);
+	return (GSS_S_FAILURE);
+    }
+
+    /* now create the name ..... */
+    buf = (unsigned char *)name_buf->value;
+    (void) memset(name_buf->value, 0, name_buf->length);
+    (void) memcpy(buf, tokId, tokIdLen);
+    buf += tokIdLen;
+
+    /* spec allows only 2 bytes for the mech oid length */
+    mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length;
+    *buf++ = (mechOidLen & 0xFF00) >> 8;
+    *buf++ = (mechOidLen & 0x00FF);
+
+    /*
+     * DER Encoding of mech OID contains OID Tag (0x06), length and
+     * mech OID value
+     */
+    *buf++ = 0x06;
+    if (gssint_put_der_length(mech_type->length, &buf,
+		       (name_buf->length - tokIdLen -2)) != 0) {
+	name_buf->length = 0;
+	free(name_buf->value);
+	(void) gss_release_buffer(&status, &dispName);
+	return (GSS_S_FAILURE);
+    }
+
+    (void) memcpy(buf, mech_type->elements, mech_type->length);
+    buf += mech_type->length;
+
+    /* spec designates the next 4 bytes for the name length */
+    *buf++ = (dispName.length & 0xFF000000) >> 24;
+    *buf++ = (dispName.length & 0x00FF0000) >> 16;
+    *buf++ = (dispName.length & 0x0000FF00) >> 8;
+    *buf++ = (dispName.length & 0X000000FF);
+
+    /* for the final ingredient - add the name from gss_display_name */
+    (void) memcpy(buf, dispName.value, dispName.length);
+
+    /* release the buffer obtained from gss_display_name */
+    (void) gss_release_buffer(minor_status, &dispName);
+    return (GSS_S_COMPLETE);
+} /*  gssint_export_internal_name */
+
+OM_uint32 gssint_display_internal_name (minor_status, mech_type, internal_name, 
+				 external_name, name_type)
+OM_uint32	*minor_status;
+gss_OID		mech_type;
+gss_name_t	internal_name;
+gss_buffer_t	external_name;
+gss_OID		*name_type;
+{
+    OM_uint32		status;
+    gss_mechanism	mech;
+
+    mech = gssint_get_mechanism (mech_type);
+    if (mech) {
+	if (mech->gss_display_name)
+	    status = mech->gss_display_name (
+					     mech->context,
+					     minor_status,
+					     internal_name,
+					     external_name,
+					     name_type);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return (status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 gssint_release_internal_name (minor_status, mech_type, internal_name)
+OM_uint32	*minor_status;
+gss_OID		mech_type;
+gss_name_t	*internal_name;
+{
+    OM_uint32		status;
+    gss_mechanism	mech;
+
+    mech = gssint_get_mechanism (mech_type);
+    if (mech) {
+	if (mech->gss_release_name)
+	    status = mech->gss_release_name (
+					     mech->context,
+					     minor_status,
+					     internal_name);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return (status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+
+/*
+ * This function converts an internal gssapi name to a union gssapi
+ * name.  Note that internal_name should be considered "consumed" by
+ * this call, whether or not we return an error.
+ */
+OM_uint32 gssint_convert_name_to_union_name(minor_status, mech,
+					   internal_name, external_name)
+    OM_uint32 *minor_status;
+    gss_mechanism	mech;
+    gss_name_t	internal_name;
+    gss_name_t	*external_name;
+{
+    OM_uint32 major_status,tmp;
+    gss_union_name_t union_name;
+
+    union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
+    if (!union_name) {
+	    goto allocation_failure;
+    }
+    union_name->mech_type = 0;
+    union_name->mech_name = internal_name;
+    union_name->name_type = 0;
+    union_name->external_name = 0;
+
+    major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
+					&union_name->mech_type);
+    if (major_status != GSS_S_COMPLETE)
+	goto allocation_failure;
+
+    union_name->external_name =
+	(gss_buffer_t) malloc(sizeof(gss_buffer_desc));
+    if (!union_name->external_name) {
+	    goto allocation_failure;
+    }
+	
+    major_status = mech->gss_display_name(mech->context, minor_status,
+					  internal_name,
+					  union_name->external_name,
+					  &union_name->name_type);
+    if (major_status != GSS_S_COMPLETE)
+	goto allocation_failure;
+
+    union_name->loopback = union_name;
+    *external_name = /*(gss_name_t) CHECK */union_name;
+    return (GSS_S_COMPLETE);
+
+allocation_failure:
+    if (union_name) {
+	if (union_name->external_name) {
+	    if (union_name->external_name->value)
+		free(union_name->external_name->value);
+	    free(union_name->external_name);
+	}
+	if (union_name->name_type)
+	    gss_release_oid(&tmp, &union_name->name_type);
+	if (union_name->mech_type)
+	    gss_release_oid(&tmp, &union_name->mech_type);
+	free(union_name);
+    }
+    /*
+     * do as the top comment says - since we are now owners of
+     * internal_name, we must clean it up
+     */
+    if (internal_name)
+	(void) gssint_release_internal_name(&tmp, &mech->mech_type,
+					   &internal_name);
+    return (major_status);
+}
+
+/*
+ * Glue routine for returning the mechanism-specific credential from a
+ * external union credential.
+ */
+gss_cred_id_t
+gssint_get_mechanism_cred(union_cred, mech_type)
+    gss_union_cred_t	union_cred;
+    gss_OID		mech_type;
+{
+    int		i;
+    
+    if (union_cred == GSS_C_NO_CREDENTIAL)
+	return GSS_C_NO_CREDENTIAL;
+    
+    for (i=0; i < union_cred->count; i++) {
+	if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
+	    return union_cred->cred_array[i];
+    }
+    return GSS_C_NO_CREDENTIAL;
+}
+
+/*
+ * Routine to create and copy the gss_buffer_desc structure.
+ * Both space for the structure and the data is allocated.
+ */
+OM_uint32
+gssint_create_copy_buffer(srcBuf, destBuf, addNullChar)
+    const gss_buffer_t	srcBuf;
+    gss_buffer_t 		*destBuf;
+    int			addNullChar;
+{
+    gss_buffer_t aBuf;
+    unsigned int len;
+
+    if (destBuf == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    *destBuf = 0;
+
+    aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
+    if (!aBuf)
+	return (GSS_S_FAILURE);
+
+    if (addNullChar)
+	len = srcBuf->length + 1;
+    else
+	len = srcBuf->length;
+
+    if (!(aBuf->value = (void*)malloc(len))) {
+	free(aBuf);
+	return (GSS_S_FAILURE);
+    }
+
+
+    (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length);
+    aBuf->length = srcBuf->length;
+    *destBuf = aBuf;
+
+    /* optionally add a NULL character */
+    if (addNullChar)
+	((char *)aBuf->value)[aBuf->length] = '\0';
+
+    return (GSS_S_COMPLETE);
+} /* ****** gssint_create_copy_buffer  ****** */
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_imp_name.c b/krb5-1-6/src/lib/gssapi/mechglue/g_imp_name.c
new file mode 100644
index 000000000..fa7aa8d13
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_imp_name.c
@@ -0,0 +1,356 @@
+/* #pragma ident	"@(#)g_imp_name.c	1.26	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_import_name
+ *
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+/* local function to import GSS_C_EXPORT_NAME names */
+static OM_uint32 importExportName(OM_uint32 *, gss_union_name_t);
+
+static OM_uint32
+val_imp_name_args(
+    OM_uint32 *minor_status,
+    gss_buffer_t input_name_buffer,
+    gss_OID input_name_type,
+    gss_name_t *output_name)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (output_name != NULL)
+	*output_name = GSS_C_NO_NAME;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (output_name == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (input_name_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+    if (input_name_buffer->length == 0)
+	return GSS_S_BAD_NAME;
+
+    if (input_name_buffer->value == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_import_name(minor_status,
+                input_name_buffer,
+                input_name_type,
+                output_name)
+
+OM_uint32 *		minor_status;
+gss_buffer_t		input_name_buffer;
+gss_OID			input_name_type;
+gss_name_t *		output_name;
+
+{
+    gss_union_name_t	union_name;
+    OM_uint32		tmp, major_status = GSS_S_FAILURE;
+
+    major_status = val_imp_name_args(minor_status,
+				     input_name_buffer, input_name_type,
+				     output_name);
+    if (major_status != GSS_S_COMPLETE)
+	return (major_status);
+
+    /*
+     * First create the union name struct that will hold the external
+     * name and the name type.
+     */
+    union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
+    if (!union_name)
+	return (GSS_S_FAILURE);
+
+    union_name->loopback = 0;
+    union_name->mech_type = 0;
+    union_name->mech_name = 0;
+    union_name->name_type = 0;
+    union_name->external_name = 0;
+
+    /*
+     * All we do here is record the external name and name_type.
+     * When the name is actually used, the underlying gss_import_name()
+     * is called for the appropriate mechanism.  The exception to this
+     * rule is when the name of GSS_C_NT_EXPORT_NAME type.  If that is
+     * the case, then we make it MN in this call.
+     */
+    major_status = gssint_create_copy_buffer(input_name_buffer,
+					    &union_name->external_name, 0);
+    if (major_status != GSS_S_COMPLETE) {
+	free(union_name);
+	return (major_status);
+    }
+
+    if (input_name_type != GSS_C_NULL_OID) {
+	major_status = generic_gss_copy_oid(minor_status,
+					    input_name_type,
+					    &union_name->name_type);
+	if (major_status != GSS_S_COMPLETE)
+	    goto allocation_failure;
+    }
+
+    /*
+     * In MIT Distribution the mechanism is determined from the nametype;
+     * This is not a good idea - first mechanism that supports a given
+     * name type is picked up; later on the caller can request a
+     * different mechanism. So we don't determine the mechanism here. Now
+     * the user level and kernel level import_name routine looks similar
+     * except the kernel routine makes a copy of the nametype structure. We
+     * do however make this an MN for names of GSS_C_NT_EXPORT_NAME type.
+     */
+    if (input_name_type != GSS_C_NULL_OID &&
+	g_OID_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
+	major_status = importExportName(minor_status, union_name);
+	if (major_status != GSS_S_COMPLETE)
+	    goto allocation_failure;
+    }
+
+    union_name->loopback = union_name;
+    *output_name = (gss_name_t)union_name;
+    return (GSS_S_COMPLETE);
+
+allocation_failure:
+    if (union_name) {
+	if (union_name->external_name) {
+	    if (union_name->external_name->value)
+		free(union_name->external_name->value);
+	    free(union_name->external_name);
+	}
+	if (union_name->name_type)
+	    generic_gss_release_oid(&tmp, &union_name->name_type);
+	if (union_name->mech_name)
+	    gssint_release_internal_name(minor_status, union_name->mech_type,
+					&union_name->mech_name);
+	if (union_name->mech_type)
+	    generic_gss_release_oid(&tmp, &union_name->mech_type);
+	free(union_name);
+    }
+    return (major_status);
+}
+
+/*
+ * GSS export name constants
+ */
+static const char *expNameTokId = "\x04\x01";
+static const unsigned int expNameTokIdLen = 2;
+static const unsigned int mechOidLenLen = 2;
+static const unsigned int nameTypeLenLen = 2;
+
+static OM_uint32
+importExportName(minor, unionName)
+    OM_uint32 *minor;
+    gss_union_name_t unionName;
+{
+    gss_OID_desc mechOid;
+    gss_buffer_desc expName;
+    unsigned char *buf;
+    gss_mechanism mech;
+    OM_uint32 major, mechOidLen, nameLen, curLength;
+    unsigned int bytes;
+
+    expName.value = unionName->external_name->value;
+    expName.length = unionName->external_name->length;
+
+    curLength = expNameTokIdLen + mechOidLenLen;
+    if (expName.length < curLength)
+	return (GSS_S_DEFECTIVE_TOKEN);
+
+    buf = (unsigned char *)expName.value;
+    if (memcmp(expNameTokId, buf, expNameTokIdLen) != 0)
+	return (GSS_S_DEFECTIVE_TOKEN);
+
+    buf += expNameTokIdLen;
+
+    /* extract the mechanism oid length */
+    mechOidLen = (*buf++ << 8);
+    mechOidLen |= (*buf++);
+    curLength += mechOidLen;
+    if (expName.length < curLength)
+	return (GSS_S_DEFECTIVE_TOKEN);
+    /*
+     * The mechOid itself is encoded in DER format, OID Tag (0x06)
+     * length and the value of mech_OID
+     */
+    if (*buf++ != 0x06)
+	return (GSS_S_DEFECTIVE_TOKEN);
+
+    /*
+     * mechoid Length is encoded twice; once in 2 bytes as
+     * explained in RFC2743 (under mechanism independent exported
+     * name object format) and once using DER encoding
+     *
+     * We verify both lengths.
+     */
+
+    mechOid.length = gssint_get_der_length(&buf,
+				    (expName.length - curLength), &bytes);
+    mechOid.elements = (void *)buf;
+
+    /*
+     * 'bytes' is the length of the DER length, '1' is for the DER
+     * tag for OID
+     */
+    if ((bytes + mechOid.length + 1) != mechOidLen)
+	return (GSS_S_DEFECTIVE_TOKEN);
+
+    buf += mechOid.length;
+    if ((mech = gssint_get_mechanism(&mechOid)) == NULL)
+	return (GSS_S_BAD_MECH);
+
+    if (mech->gss_import_name == NULL)
+	return (GSS_S_UNAVAILABLE);
+
+    /*
+     * we must now determine if we should unwrap the name ourselves
+     * or make the mechanism do it - we should only unwrap it
+     * if we create it; so if mech->gss_export_name == NULL, we must
+     * have created it.
+     */
+    if (mech->gss_export_name) {
+	if ((major = mech->gss_import_name(mech->context, minor,
+					   &expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
+					   &unionName->mech_name)) != GSS_S_COMPLETE ||
+	    (major = generic_gss_copy_oid(minor, &mechOid,
+					  &unionName->mech_type)) !=
+	    GSS_S_COMPLETE) {
+	    return (major);
+	}
+	return (major);
+    }
+    /*
+     * we must have exported the name - so we now need to reconstruct it
+     * and call the mechanism to create it
+     *
+     * WARNING:	Older versions of gssint_export_internal_name() did
+     *		not export names correctly, but now it does.  In
+     *		order to stay compatible with existing exported
+     *		names we must support names exported the broken
+     *		way.
+     *
+     * Specifically, gssint_export_internal_name() used to include
+     * the name type OID in the encoding of the exported MN.
+     * Additionally, the Kerberos V mech used to make display names
+     * that included a null terminator which was counted in the
+     * display name gss_buffer_desc.
+     */
+    curLength += 4;		/* 4 bytes for name len */
+    if (expName.length < curLength)
+	return (GSS_S_DEFECTIVE_TOKEN);
+
+    /* next 4 bytes in the name are the name length */
+    nameLen = (*buf++) << 24;
+    nameLen |= (*buf++ << 16);
+    nameLen |= (*buf++ << 8);
+    nameLen |= (*buf++);
+
+    /*
+     * we use < here because bad code in rpcsec_gss rounds up exported
+     * name token lengths and pads with nulls, otherwise != would be
+     * appropriate
+     */
+    curLength += nameLen;   /* this is the total length */
+    if (expName.length < curLength)
+	return (GSS_S_DEFECTIVE_TOKEN);
+
+    /*
+     * We detect broken exported names here: they always start with
+     * a two-octet network-byte order OID length, which is always
+     * less than 256 bytes, so the first octet of the length is
+     * always '\0', which is not allowed in GSS-API display names
+     * (or never occurs in them anyways).  Of course, the OID
+     * shouldn't be there, but it is.  After the OID (sans DER tag
+     * and length) there's the name itself, though null-terminated;
+     * this null terminator should also not be there, but it is.
+     */
+    if (nameLen > 0 && *buf == '\0') {
+	OM_uint32 nameTypeLen;
+	/* next two bytes are the name oid */
+	if (nameLen < nameTypeLenLen)
+	    return (GSS_S_DEFECTIVE_TOKEN);
+
+	nameLen -= nameTypeLenLen;
+
+	nameTypeLen = (*buf++) << 8;
+	nameTypeLen |= (*buf++);
+
+	if (nameLen < nameTypeLen)
+	    return (GSS_S_DEFECTIVE_TOKEN);
+
+	buf += nameTypeLen;
+	nameLen -= nameTypeLen;
+
+	/*
+	 * adjust for expected null terminator that should
+	 * really not be there
+	 */
+	if (nameLen > 0 && *(buf + nameLen - 1) == '\0')
+	    nameLen--;
+    }
+
+    /*
+     * Can a name be null?  Let the mech decide.
+     *
+     * NOTE: We use GSS_C_NULL_OID as the name type when importing
+     *	 the unwrapped name.  Presumably the exported name had,
+     *	 prior to being exported been obtained in such a way
+     *	 that it has been properly perpared ("canonicalized," in
+     *	 GSS-API terms) accroding to some name type; we cannot
+     *	 tell what that name type was now, but the name should
+     *	 need no further preparation other than the lowest
+     *	 common denominator afforded by the mech to names
+     *	 imported with GSS_C_NULL_OID.  For the Kerberos V mech
+     *	 this means doing less busywork too (particularly once
+     *	 IDN is thrown in with Kerberos V extensions).
+     */
+    expName.length = nameLen;
+    expName.value = nameLen ? (void *)buf : NULL;
+    major = mech->gss_import_name(mech->context, minor, &expName,
+				  GSS_C_NULL_OID, &unionName->mech_name);
+    if (major != GSS_S_COMPLETE)
+	return (major);
+
+    return (generic_gss_copy_oid(minor, &mechOid, &unionName->mech_type));
+} /* importExportName */
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_imp_sec_context.c b/krb5-1-6/src/lib/gssapi/mechglue/g_imp_sec_context.c
new file mode 100644
index 000000000..1dd954207
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_imp_sec_context.c
@@ -0,0 +1,163 @@
+/* #pragma ident	"@(#)g_imp_sec_context.c	1.18	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_export_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+static OM_uint32
+val_imp_sec_ctx_args(
+    OM_uint32 *minor_status,
+    gss_buffer_t interprocess_token,
+    gss_ctx_id_t *context_handle)
+{
+
+    /* Initialize outputs. */
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (context_handle != NULL)
+	*context_handle = GSS_C_NO_CONTEXT;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (interprocess_token == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN);
+
+    if (GSS_EMPTY_BUFFER(interprocess_token))
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_import_sec_context(minor_status,
+                       interprocess_token,
+                       context_handle)
+
+OM_uint32 *		minor_status;
+gss_buffer_t		interprocess_token;
+gss_ctx_id_t *		context_handle;
+
+{
+    OM_uint32		length = 0;
+    OM_uint32		status;
+    char		*p;
+    gss_union_ctx_id_t	ctx;
+    gss_buffer_desc	token;
+    gss_mechanism	mech;
+
+    status = val_imp_sec_ctx_args(minor_status,
+				  interprocess_token, context_handle);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    /* Initial value needed below. */
+    status = GSS_S_FAILURE;
+
+    ctx = (gss_union_ctx_id_t) malloc(sizeof(gss_union_ctx_id_desc));
+    if (!ctx)
+	return (GSS_S_FAILURE);
+
+    ctx->mech_type = (gss_OID) malloc(sizeof(gss_OID_desc));
+    if (!ctx->mech_type) {
+	free(ctx);
+	return (GSS_S_FAILURE);
+    }
+
+    if (interprocess_token->length >= sizeof (OM_uint32)) {
+	p = interprocess_token->value;
+	length = (OM_uint32)*p++;
+	length = (OM_uint32)(length << 8) + *p++;
+	length = (OM_uint32)(length << 8) + *p++;
+	length = (OM_uint32)(length << 8) + *p++;
+    }
+
+    if (length == 0 ||
+	length > (interprocess_token->length - sizeof (OM_uint32))) {
+	free(ctx);
+	return (GSS_S_CALL_BAD_STRUCTURE | GSS_S_DEFECTIVE_TOKEN);
+    }
+
+    ctx->mech_type->length = length;
+    ctx->mech_type->elements = malloc(length);
+    if (!ctx->mech_type->elements) {
+	goto error_out;
+    }
+    memcpy(ctx->mech_type->elements, p, length);
+    p += length;
+
+    token.length = interprocess_token->length - sizeof (OM_uint32) - length;
+    token.value = p;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    mech = gssint_get_mechanism (ctx->mech_type);
+    if (!mech) {
+	status = GSS_S_BAD_MECH;
+	goto error_out;
+    }
+    if (!mech->gss_import_sec_context) {
+	status = GSS_S_UNAVAILABLE;
+	goto error_out;
+    }
+    
+    status = mech->gss_import_sec_context(mech->context, minor_status,
+					  &token, &ctx->internal_ctx_id);
+
+    if (status == GSS_S_COMPLETE) {
+	ctx->loopback = ctx;
+	*context_handle = ctx;
+	return (GSS_S_COMPLETE);
+    }
+    
+error_out:
+    if (ctx) {
+	if (ctx->mech_type) {
+	    if (ctx->mech_type->elements)
+		free(ctx->mech_type->elements);
+	    free(ctx->mech_type);
+	}
+	free(ctx);
+    }
+    return status;
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_init_sec_context.c b/krb5-1-6/src/lib/gssapi/mechglue/g_init_sec_context.c
new file mode 100644
index 000000000..52f93f124
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_init_sec_context.c
@@ -0,0 +1,252 @@
+/* #pragma ident	"@(#)g_init_sec_context.c	1.20	03/10/24 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_init_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+static OM_uint32
+val_init_sec_ctx_args(
+    OM_uint32 *minor_status,
+    gss_cred_id_t claimant_cred_handle,
+    gss_ctx_id_t *context_handle,
+    gss_name_t target_name,
+    gss_OID req_mech_type,
+    OM_uint32 req_flags,
+    OM_uint32 time_req,
+    gss_channel_bindings_t input_chan_bindings,
+    gss_buffer_t input_token,
+    gss_OID *actual_mech_type,
+    gss_buffer_t output_token,
+    OM_uint32 *ret_flags,
+    OM_uint32 *time_rec)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (actual_mech_type != NULL)
+	*actual_mech_type = GSS_C_NO_OID;
+
+    if (output_token != GSS_C_NO_BUFFER) {
+	output_token->length = 0;
+	output_token->value = NULL;
+    }
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
+
+    if (target_name == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+    if (output_token == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_init_sec_context (minor_status,
+                      claimant_cred_handle,
+                      context_handle,
+                      target_name,
+                      req_mech_type,
+                      req_flags,
+                      time_req,
+                      input_chan_bindings,
+                      input_token,
+                      actual_mech_type,
+                      output_token,
+                      ret_flags,
+                      time_rec)
+
+OM_uint32 *		minor_status;
+gss_cred_id_t		claimant_cred_handle;
+gss_ctx_id_t *		context_handle;
+gss_name_t		target_name;
+gss_OID			req_mech_type;
+OM_uint32		req_flags;
+OM_uint32		time_req;
+gss_channel_bindings_t	input_chan_bindings;
+gss_buffer_t		input_token;
+gss_OID *		actual_mech_type;
+gss_buffer_t		output_token;
+OM_uint32 *		ret_flags;
+OM_uint32 *		time_rec;
+
+{
+    OM_uint32		status, temp_minor_status;
+    gss_union_name_t	union_name;
+    gss_union_cred_t	union_cred;
+    gss_name_t		internal_name;
+    gss_union_ctx_id_t	union_ctx_id;
+    gss_OID		mech_type = (gss_OID) req_mech_type;
+    gss_mechanism	mech;
+    gss_cred_id_t	input_cred_handle;
+
+    status = val_init_sec_ctx_args(minor_status,
+				   claimant_cred_handle,
+				   context_handle,
+				   target_name,
+				   req_mech_type,
+				   req_flags,
+				   time_req,
+				   input_chan_bindings,
+				   input_token,
+				   actual_mech_type,
+				   output_token,
+				   ret_flags,
+				   time_rec);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    if (req_mech_type)
+	mech_type = (gss_OID)req_mech_type;
+
+    union_name = (gss_union_name_t)target_name;
+    
+    /*
+     * obtain the gss mechanism information for the requested
+     * mechanism.  If mech_type is NULL, set it to the resultant
+     * mechanism
+     */
+    mech = gssint_get_mechanism (mech_type);
+    if (mech == NULL)
+	return (GSS_S_BAD_MECH);
+
+    if (mech->gss_init_sec_context == NULL)
+	return (GSS_S_UNAVAILABLE);
+
+    if (mech_type == GSS_C_NULL_OID)
+	mech_type = &mech->mech_type;
+
+    /*
+     * If target_name is mechanism_specific, then it must match the
+     * mech_type that we're about to use.  Otherwise, do an import on
+     * the external_name form of the target name.
+     */
+    if (union_name->mech_type &&
+	g_OID_equal(union_name->mech_type, mech_type)) {
+	internal_name = union_name->mech_name;
+    } else {
+	if ((status = gssint_import_internal_name(minor_status, mech_type,
+						 union_name,
+						 &internal_name)) != GSS_S_COMPLETE)
+	    return (status);
+    }
+
+    /*
+     * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
+     * descriptor to hold the mech type information as well as the
+     * underlying mechanism context handle. Otherwise, cast the
+     * value of *context_handle to the union context variable.
+     */
+    
+    if(*context_handle == GSS_C_NO_CONTEXT) {
+	status = GSS_S_FAILURE;
+	union_ctx_id = (gss_union_ctx_id_t)
+	    malloc(sizeof(gss_union_ctx_id_desc));
+	if (union_ctx_id == NULL)
+	    goto end;
+
+	if (generic_gss_copy_oid(&temp_minor_status, mech_type,
+				 &union_ctx_id->mech_type) != GSS_S_COMPLETE) {
+	    free(union_ctx_id);
+	    goto end;
+	}
+
+	/* copy the supplied context handle */
+	union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT;
+    } else
+	union_ctx_id = *context_handle;
+    
+    /* 
+     * get the appropriate cred handle from the union cred struct.
+     * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
+     * use the default credential.
+     */
+    union_cred = (gss_union_cred_t) claimant_cred_handle;
+    input_cred_handle = gssint_get_mechanism_cred(union_cred, mech_type);
+    
+    /*
+     * now call the approprate underlying mechanism routine 
+     */
+    
+    status = mech->gss_init_sec_context(
+	mech->context,
+	minor_status,
+	input_cred_handle,
+	&union_ctx_id->internal_ctx_id,
+	internal_name,
+	mech_type,
+	req_flags,
+	time_req,
+	input_chan_bindings,
+	input_token,
+	actual_mech_type,
+	output_token,
+	ret_flags,
+	time_rec);
+
+    if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
+	/*
+	 * the spec says (the preferred) method is to delete all
+	 * context info on the first call to init, and on all
+	 * subsequent calls make the caller responsible for
+	 * calling gss_delete_sec_context
+	 */
+	if (*context_handle == GSS_C_NO_CONTEXT) {
+	    free(union_ctx_id->mech_type->elements);
+	    free(union_ctx_id->mech_type);
+	    free(union_ctx_id);
+	}
+    } else if (*context_handle == GSS_C_NO_CONTEXT) {
+	union_ctx_id->loopback = union_ctx_id;
+	*context_handle = (gss_ctx_id_t)union_ctx_id;
+    }
+
+end:
+    if (union_name->mech_name == NULL ||
+	union_name->mech_name != internal_name) {
+	(void) gssint_release_internal_name(&temp_minor_status,
+					   mech_type, &internal_name);
+    }
+
+    return(status);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_initialize.c b/krb5-1-6/src/lib/gssapi/mechglue/g_initialize.c
new file mode 100644
index 000000000..0c4513cac
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_initialize.c
@@ -0,0 +1,597 @@
+/* #pragma ident	"@(#)g_initialize.c	1.36	05/02/02 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This function will initialize the gssapi mechglue library
+ */
+
+#include "mglueP.h"
+#include "gss_libinit.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#define	M_DEFAULT	"default"
+
+#include "k5-thread.h"
+
+/* Local functions */
+static gss_mech_info searchMechList(const gss_OID);
+static void updateMechList(void);
+static void register_mech(gss_mechanism, const char *, void *);
+
+static OM_uint32 build_mechSet(void);
+static void init_hardcoded(void);
+
+/*
+ * list of mechanism libraries and their entry points.
+ * the list also maintains state of the mech libraries (loaded or not).
+ */
+static gss_mech_info g_mechList = NULL;
+static gss_mech_info g_mechListTail = NULL;
+static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+static gss_OID_set_desc g_mechSet = { 0, NULL };
+static k5_mutex_t g_mechSetLock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+int
+gssint_mechglue_init(void)
+{
+	int err;
+
+	err = k5_mutex_finish_init(&g_mechSetLock);
+	return k5_mutex_finish_init(&g_mechListLock);
+}
+
+void
+gssint_mechglue_fini(void)
+{
+	k5_mutex_destroy(&g_mechSetLock);
+	k5_mutex_destroy(&g_mechListLock);
+}
+
+
+/*
+ * function used to reclaim the memory used by a gss_OID structure.
+ * This routine requires direct access to the mechList.
+ */
+OM_uint32 KRB5_CALLCONV
+gss_release_oid(minor_status, oid)
+OM_uint32 *minor_status;
+gss_OID *oid;
+{
+	OM_uint32 major;
+	gss_mech_info aMech;
+
+	if (gssint_initialize_library())
+		return GSS_S_FAILURE;
+
+	if (minor_status == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	*minor_status = 0;
+
+	k5_mutex_lock(&g_mechListLock);
+	aMech = g_mechList;
+	while (aMech != NULL) {
+
+		/*
+		 * look through the loaded mechanism libraries for
+		 * gss_internal_release_oid until one returns success.
+		 * gss_internal_release_oid will only return success when
+		 * the OID was recognized as an internal mechanism OID. if no
+		 * mechanisms recognize the OID, then call the generic version.
+		 */
+		if (aMech->mech && aMech->mech->gss_internal_release_oid) {
+			major = aMech->mech->gss_internal_release_oid(
+					aMech->mech->context,
+					minor_status, oid);
+			if (major == GSS_S_COMPLETE) {
+				k5_mutex_unlock(&g_mechListLock);
+				return (GSS_S_COMPLETE);
+			}
+		}
+		aMech = aMech->next;
+	} /* while */
+	k5_mutex_unlock(&g_mechListLock);
+
+	return (generic_gss_release_oid(minor_status, oid));
+} /* gss_release_oid */
+
+
+/*
+ * this function will return an oid set indicating available mechanisms.
+ * The set returned is based on configuration file entries and
+ * NOT on the loaded mechanisms.  This function does not check if any
+ * of these can actually be loaded.
+ * This routine needs direct access to the mechanism list.
+ * To avoid reading the configuration file each call, we will save a
+ * a mech oid set, and only update it once the file has changed.
+ */
+OM_uint32 KRB5_CALLCONV
+gss_indicate_mechs(minorStatus, mechSet)
+OM_uint32 *minorStatus;
+gss_OID_set *mechSet;
+{
+	int i, j;
+	gss_OID curItem;
+
+	/* Initialize outputs. */
+
+	if (minorStatus != NULL)
+		*minorStatus = 0;
+
+	if (mechSet != NULL)
+		*mechSet = GSS_C_NO_OID_SET;
+
+	/* Validate arguments. */
+	if (minorStatus == NULL || mechSet == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	if (gssint_initialize_library())
+		return GSS_S_FAILURE;
+
+	if (build_mechSet())
+		return GSS_S_FAILURE;
+
+	/*
+	 * the mech set is created and it is up to date
+	 * so just copy it to caller
+	 */
+	if ((*mechSet =
+		(gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL)
+	{
+		return (GSS_S_FAILURE);
+	}
+
+	/*
+	 * need to lock the g_mechSet in case someone tries to update it while
+	 * I'm copying it.
+	 */
+	(void) k5_mutex_lock(&g_mechSetLock);
+
+	/* allocate space for the oid structures */
+	if (((*mechSet)->elements =
+		(void*) calloc(g_mechSet.count, sizeof (gss_OID_desc)))
+		== NULL)
+	{
+		(void) k5_mutex_unlock(&g_mechSetLock);
+		free(*mechSet);
+		*mechSet = NULL;
+		return (GSS_S_FAILURE);
+	}
+
+	/* now copy the oid structures */
+	(void) memcpy((*mechSet)->elements, g_mechSet.elements,
+		g_mechSet.count * sizeof (gss_OID_desc));
+
+	(*mechSet)->count = g_mechSet.count;
+
+	/* still need to copy each of the oid elements arrays */
+	for (i = 0; i < (*mechSet)->count; i++) {
+		curItem = &((*mechSet)->elements[i]);
+		curItem->elements =
+			(void *) malloc(g_mechSet.elements[i].length);
+		if (curItem->elements == NULL) {
+			(void) k5_mutex_unlock(&g_mechSetLock);
+			/*
+			 * must still free the allocated elements for
+			 * each allocated gss_OID_desc
+			 */
+			for (j = 0; j < i; j++) {
+				free((*mechSet)->elements[j].elements);
+			}
+			free((*mechSet)->elements);
+			free(mechSet);
+			*mechSet = NULL;
+			return (GSS_S_FAILURE);
+		}
+		g_OID_copy(curItem, &g_mechSet.elements[i]);
+	}
+	(void) k5_mutex_unlock(&g_mechSetLock);
+	return (GSS_S_COMPLETE);
+} /* gss_indicate_mechs */
+
+
+static OM_uint32
+build_mechSet(void)
+{
+	gss_mech_info mList;
+	int i, count;
+	gss_OID curItem;
+
+	/*
+	 * lock the mutex since we will be updating
+	 * the mechList structure
+	 * we need to keep the lock while we build the mechanism list
+	 * since we are accessing parts of the mechList which could be
+	 * modified.
+	 */
+	(void) k5_mutex_lock(&g_mechListLock);
+
+	updateMechList();
+
+	/*
+	 * we need to lock the mech set so that no one else will
+	 * try to read it as we are re-creating it
+	 */
+	(void) k5_mutex_lock(&g_mechSetLock);
+
+	/* if the oid list already exists we must free it first */
+	if (g_mechSet.count != 0) {
+		for (i = 0; i < g_mechSet.count; i++)
+			free(g_mechSet.elements[i].elements);
+		free(g_mechSet.elements);
+		g_mechSet.elements = NULL;
+		g_mechSet.count = 0;
+	}
+
+	/* determine how many elements to have in the list */
+	mList = g_mechList;
+	count = 0;
+	while (mList != NULL) {
+		count++;
+		mList = mList->next;
+	}
+
+	/* this should always be true, but.... */
+	if (count > 0) {
+		g_mechSet.elements =
+			(gss_OID) calloc(count, sizeof (gss_OID_desc));
+		if (g_mechSet.elements == NULL) {
+			(void) k5_mutex_unlock(&g_mechSetLock);
+			(void) k5_mutex_unlock(&g_mechListLock);
+			return (GSS_S_FAILURE);
+		}
+
+		(void) memset(g_mechSet.elements, 0,
+			      count * sizeof (gss_OID_desc));
+
+		/* now copy each oid element */
+		g_mechSet.count = count;
+		count = 0;
+		mList = g_mechList;
+		while (mList != NULL) {
+			curItem = &(g_mechSet.elements[count]);
+			curItem->elements = (void*)
+				malloc(mList->mech_type->length);
+			if (curItem->elements == NULL) {
+				/*
+				 * this is nasty - we must delete the
+				 * part of the array already copied
+				 */
+				for (i = 0; i < count; i++) {
+					free(g_mechSet.elements[i].
+					     elements);
+				}
+				free(g_mechSet.elements);
+				g_mechSet.count = 0;
+				g_mechSet.elements = NULL;
+				(void) k5_mutex_unlock(&g_mechSetLock);
+				(void) k5_mutex_unlock(&g_mechListLock);
+				return (GSS_S_FAILURE);
+			}
+			g_OID_copy(curItem, mList->mech_type);
+			count++;
+			mList = mList->next;
+		}
+	}
+
+	(void) k5_mutex_unlock(&g_mechSetLock);
+	(void) k5_mutex_unlock(&g_mechListLock);
+
+	return GSS_S_COMPLETE;
+}
+
+
+/*
+ * this function has been added for use by modules that need to
+ * know what (if any) optional parameters are supplied in the
+ * config file (MECH_CONF).
+ * It will return the option string for a specified mechanism.
+ * caller is responsible for freeing the memory
+ */
+char *
+gssint_get_modOptions(oid)
+const gss_OID oid;
+{
+	gss_mech_info aMech;
+	char *modOptions = NULL;
+
+	/* make sure we have fresh data */
+	(void) k5_mutex_lock(&g_mechListLock);
+	updateMechList();
+
+	if ((aMech = searchMechList(oid)) == NULL ||
+		aMech->optionStr == NULL) {
+		(void) k5_mutex_unlock(&g_mechListLock);
+		return (NULL);
+	}
+
+	if (aMech->optionStr)
+		modOptions = strdup(aMech->optionStr);
+	(void) k5_mutex_unlock(&g_mechListLock);
+
+	return (modOptions);
+} /* gssint_get_modOptions */
+
+/*
+ * given a mechanism string return the mechanism oid
+ */
+OM_uint32
+gssint_mech_to_oid(const char *mechStr, gss_OID* oid)
+{
+	gss_mech_info aMech;
+
+	if (oid == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	*oid = GSS_C_NULL_OID;
+
+	if ((mechStr == NULL) || (strlen(mechStr) == 0) ||
+		(strcasecmp(mechStr, M_DEFAULT) == 0))
+		return (GSS_S_COMPLETE);
+
+	/* ensure we have fresh data */
+	(void) k5_mutex_lock(&g_mechListLock);
+	updateMechList();
+	(void) k5_mutex_unlock(&g_mechListLock);
+
+	aMech = g_mechList;
+
+	/* no lock required - only looking at fields that are not updated */
+	while (aMech != NULL) {
+		if ((aMech->mechNameStr) &&
+			strcmp(aMech->mechNameStr, mechStr) == 0) {
+			*oid = aMech->mech_type;
+			return (GSS_S_COMPLETE);
+		}
+		aMech = aMech->next;
+	}
+	return (GSS_S_FAILURE);
+} /* gssint_mech_to_oid */
+
+
+/*
+ * Given the mechanism oid, return the readable mechanism name
+ * associated with that oid from the mech config file
+ * (/etc/gss/mech).
+ */
+const char *
+gssint_oid_to_mech(const gss_OID oid)
+{
+	gss_mech_info aMech;
+
+	if (oid == GSS_C_NULL_OID)
+		return (M_DEFAULT);
+
+	/* ensure we have fresh data */
+	(void) k5_mutex_lock(&g_mechListLock);
+	updateMechList();
+	aMech = searchMechList(oid);
+	(void) k5_mutex_unlock(&g_mechListLock);
+
+	if (aMech == NULL)
+		return (NULL);
+
+	return (aMech->mechNameStr);
+} /* gssint_oid_to_mech */
+
+
+/*
+ * return a list of mechanism strings supported
+ * upon return the array is terminated with a NULL entry
+ */
+OM_uint32
+gssint_get_mechanisms(char *mechArray[], int arrayLen)
+{
+	gss_mech_info aMech;
+	int i;
+
+	if (gssint_initialize_library())
+		return GSS_S_FAILURE;
+	if (mechArray == NULL || arrayLen < 1)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	/* ensure we have fresh data */
+	(void) k5_mutex_lock(&g_mechListLock);
+	updateMechList();
+	(void) k5_mutex_unlock(&g_mechListLock);
+
+	aMech = g_mechList;
+
+	/* no lock required - only looking at fields that are not updated */
+	for (i = 1; i < arrayLen; i++) {
+		if (aMech != NULL) {
+			*mechArray = aMech->mechNameStr;
+			mechArray++;
+			aMech = aMech->next;
+		} else
+			break;
+	}
+	*mechArray = NULL;
+	return (GSS_S_COMPLETE);
+} /* gss_get_mechanisms */
+
+
+/*
+ * determines if the mechList needs to be updated from file
+ * and performs the update.
+ * this functions must be called with a lock of g_mechListLock
+ */
+static void
+updateMechList(void)
+{
+
+	init_hardcoded();
+
+} /* updateMechList */
+
+/*
+ * Register a mechanism.  Called with g_mechListLock held.
+ */
+static void
+register_mech(gss_mechanism mech, const char *namestr, void *dl_handle)
+{
+	gss_mech_info cf, new_cf;
+
+	new_cf = malloc(sizeof(*new_cf));
+	if (new_cf == NULL)
+		return;
+
+	memset(new_cf, 0, sizeof(*new_cf));
+	new_cf->kmodName = NULL;
+	new_cf->uLibName = strdup(namestr);
+	new_cf->mechNameStr = strdup(mech->mechNameStr);
+	new_cf->mech_type = &mech->mech_type;
+	new_cf->mech = mech;
+	new_cf->next = NULL;
+
+	if (g_mechList == NULL) {
+		g_mechList = new_cf;
+		g_mechListTail = new_cf;
+		return;
+	} else if (mech->priority < g_mechList->mech->priority) {
+		new_cf->next = g_mechList;
+		g_mechList = new_cf;
+		return;
+	}
+	for (cf = g_mechList; cf != NULL; cf = cf->next) {
+		if (cf->next == NULL ||
+		    mech->priority < cf->next->mech->priority) {
+			new_cf->next = cf->next;
+			cf->next = new_cf;
+			if (g_mechListTail == cf) {
+				g_mechListTail = new_cf;
+			}
+			break;
+		}
+	}
+}
+
+/*
+ * Initialize the hardcoded mechanisms.  This function is called with
+ * g_mechListLock held.
+ */
+static void
+init_hardcoded(void)
+{
+	extern gss_mechanism *krb5_gss_get_mech_configs(void);
+	extern gss_mechanism *spnego_gss_get_mech_configs(void);
+	gss_mechanism *cflist;
+	static int inited;
+
+	if (inited)
+		return;
+
+	cflist = krb5_gss_get_mech_configs();
+	if (cflist == NULL)
+		return;
+	for ( ; *cflist != NULL; cflist++) {
+		register_mech(*cflist, "<builtin krb5>", NULL);
+	}
+	cflist = spnego_gss_get_mech_configs();
+	if (cflist == NULL)
+		return;
+	for ( ; *cflist != NULL; cflist++) {
+		register_mech(*cflist, "<builtin spnego>", NULL);
+	}
+	inited = 1;
+}
+
+
+/*
+ * given the mechanism type, return the mechanism structure
+ * containing the mechanism library entry points.
+ * will return NULL if mech type is not found
+ * This function will also trigger the loading of the mechanism
+ * module if it has not been already loaded.
+ */
+gss_mechanism
+gssint_get_mechanism(gss_OID oid)
+{
+	gss_mech_info aMech;
+
+	if (gssint_initialize_library())
+		return NULL;
+
+	(void) k5_mutex_lock(&g_mechListLock);
+	/* check if the mechanism is already loaded */
+	if ((aMech = searchMechList(oid)) != NULL && aMech->mech) {
+		(void) k5_mutex_unlock(&g_mechListLock);
+		return (aMech->mech);
+	}
+
+	/*
+	 * might need to re-read the configuration file before loading
+	 * the mechanism to ensure we have the latest info.
+	 */
+	updateMechList();
+
+	aMech = searchMechList(oid);
+
+	/* is the mechanism present in the list ? */
+	if (aMech == NULL) {
+		(void) k5_mutex_unlock(&g_mechListLock);
+		return ((gss_mechanism)NULL);
+	}
+
+	/* has another thread loaded the mech */
+	if (aMech->mech) {
+		(void) k5_mutex_unlock(&g_mechListLock);
+		return (aMech->mech);
+	} else {
+		return NULL;
+	}
+} /* gssint_get_mechanism */
+
+
+/*
+ * this routine is used for searching the list of mechanism data.
+ *
+ * this needs to be called with g_mechListLock held.
+ */
+static gss_mech_info searchMechList(oid)
+const gss_OID oid;
+{
+	gss_mech_info aMech = g_mechList;
+
+	/* if oid is null -> then get default which is the first in the list */
+	if (oid == GSS_C_NULL_OID)
+		return (aMech);
+
+	while (aMech != NULL) {
+		if (g_OID_equal(aMech->mech_type, oid))
+			return (aMech);
+		aMech = aMech->next;
+	}
+
+	/* none found */
+	return ((gss_mech_info) NULL);
+} /* searchMechList */
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_inq_context.c b/krb5-1-6/src/lib/gssapi/mechglue/g_inq_context.c
new file mode 100644
index 000000000..aeab57d60
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_inq_context.c
@@ -0,0 +1,173 @@
+/* #pragma ident	"@(#)g_inquire_context.c	1.15	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_inquire_context
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+static OM_uint32
+val_inq_ctx_args(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t context_handle,
+    gss_name_t *src_name,
+    gss_name_t *targ_name,
+    OM_uint32 *lifetime_rec,
+    gss_OID *mech_type,
+    OM_uint32 *ctx_flags,
+    int *locally_initiated,
+    int *open)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (src_name != NULL)
+	*src_name = GSS_C_NO_NAME;
+
+    if (targ_name != NULL)
+	*targ_name = GSS_C_NO_NAME;
+
+    if (mech_type != NULL)
+	*mech_type = GSS_C_NO_OID;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+/* Last argument new for V2 */
+OM_uint32 KRB5_CALLCONV
+gss_inquire_context(
+	    minor_status,
+	    context_handle,
+	    src_name,
+	    targ_name,
+	    lifetime_rec,
+	    mech_type,
+	    ctx_flags,
+	    locally_initiated,
+	    open)
+
+OM_uint32 *	minor_status;
+gss_ctx_id_t	context_handle;
+gss_name_t *	src_name;
+gss_name_t *	targ_name;
+OM_uint32 *	lifetime_rec;
+gss_OID *	mech_type;
+OM_uint32 *	ctx_flags;
+int *           locally_initiated;
+int *		open;
+
+
+{
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+    OM_uint32		status, temp_minor;
+    gss_name_t localTargName = NULL, localSourceName = NULL;
+
+    status = val_inq_ctx_args(minor_status,
+			      context_handle,
+			      src_name, targ_name,
+			      lifetime_rec,
+			      mech_type, ctx_flags,
+			      locally_initiated, open);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+    
+    if (!mech || !mech->gss_inquire_context || !mech->gss_display_name ||
+	!mech->gss_release_name) {
+	return (GSS_S_UNAVAILABLE);
+    }
+
+    status = mech->gss_inquire_context(
+			mech->context,
+			minor_status,
+			ctx->internal_ctx_id,
+			(src_name ? &localSourceName : NULL),
+			(targ_name ? &localTargName : NULL),
+			lifetime_rec,
+			NULL,
+			ctx_flags,
+			locally_initiated,
+			open);
+
+    if (status != GSS_S_COMPLETE) {
+	return status;
+    }
+
+    /* need to convert names */
+
+    if (src_name) {
+	    status = gssint_convert_name_to_union_name(minor_status, mech,
+						      localSourceName, src_name);
+
+	    if (status != GSS_S_COMPLETE) {
+		if (localTargName)
+		    mech->gss_release_name(mech->context,
+					   &temp_minor, &localTargName);
+		return (status);
+	    }
+
+    }
+
+    if (targ_name) {
+	    status = gssint_convert_name_to_union_name(minor_status, mech,
+						      localTargName, targ_name);
+
+	    if (status != GSS_S_COMPLETE) {
+		if (src_name)
+		    (void) gss_release_name(&temp_minor, src_name);
+
+		return (status);
+	    }
+    }
+
+    /* spec says mech type must point to static storage */
+    if (mech_type)
+	*mech_type = &mech->mech_type;
+    return(GSS_S_COMPLETE);
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_inq_cred.c b/krb5-1-6/src/lib/gssapi/mechglue/g_inq_cred.c
new file mode 100644
index 000000000..805579e78
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_inq_cred.c
@@ -0,0 +1,270 @@
+/* #pragma ident	"@(#)g_inquire_cred.c	1.16	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_inquire_cred
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_inquire_cred(minor_status,
+                 cred_handle,
+                 name,
+                 lifetime,
+		 cred_usage,
+                 mechanisms)
+
+OM_uint32 *		minor_status;
+gss_cred_id_t 		cred_handle;
+gss_name_t *		name;
+OM_uint32 *		lifetime;
+int *			cred_usage;
+gss_OID_set *		mechanisms;
+
+{
+    OM_uint32		status, elapsed_time, temp_minor_status;
+    gss_union_cred_t	union_cred;
+    gss_mechanism	mech;
+    gss_name_t		internal_name;
+    int			i;
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (name != NULL)
+	*name = GSS_C_NO_NAME;
+
+    if (mechanisms != NULL)
+	*mechanisms = GSS_C_NO_OID_SET;
+
+    /* Validate arguments. */
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (cred_handle == GSS_C_NO_CREDENTIAL) {
+	/*
+	 * No credential was supplied. This means we can't get a mechanism
+	 * pointer to call the mechanism specific gss_inquire_cred.
+	 * So, call get_mechanism with an arguement of GSS_C_NULL_OID.
+	 * get_mechanism will return the first mechanism in the mech
+	 * array, which becomes the default mechanism.
+	 */
+
+	if ((mech = gssint_get_mechanism(GSS_C_NULL_OID)) == NULL)
+	    return (GSS_S_DEFECTIVE_CREDENTIAL);
+
+	if (!mech->gss_inquire_cred)
+	    return (GSS_S_UNAVAILABLE);
+	
+	status = mech->gss_inquire_cred(mech->context, minor_status,
+					GSS_C_NO_CREDENTIAL,
+					name ? &internal_name : NULL,
+					lifetime, cred_usage, mechanisms);
+
+	if (status != GSS_S_COMPLETE)
+	    return(status);
+
+	if (name) {
+	    /*
+	     * Convert internal_name into a union_name equivalent.
+	     */
+	    status = gssint_convert_name_to_union_name(&temp_minor_status,
+						      mech, internal_name,
+						      name);
+	    if (status != GSS_S_COMPLETE) {
+		*minor_status = temp_minor_status;
+		if (mechanisms && *mechanisms) {
+		    (void) gss_release_oid_set(
+			&temp_minor_status,
+			mechanisms);
+		}
+		return (status);
+	    }
+	}
+	return(GSS_S_COMPLETE);
+    } 
+	
+    /* get the cred_handle cast as a union_credentials structure */
+	
+    union_cred = (gss_union_cred_t) cred_handle;
+    
+    /*
+     * get the information out of the union_cred structure that was
+     * placed there during gss_acquire_cred.
+     */
+    
+    if(cred_usage != NULL)
+	*cred_usage = union_cred->auxinfo.cred_usage;
+    
+    if(lifetime != NULL) {
+	elapsed_time = time(0) - union_cred->auxinfo.creation_time;
+	*lifetime = union_cred->auxinfo.time_rec < elapsed_time ? 0 :
+	union_cred->auxinfo.time_rec - elapsed_time;
+    }
+    
+    /*
+     * if name is non_null,
+     * call gss_import_name(), giving it the printable name held within
+     * union_cred in order to get an internal name to pass back to the
+     * caller. If this call fails, return failure to our caller.
+     */
+    
+    if(name != NULL) {
+	if ((gss_import_name(&temp_minor_status,
+			     &union_cred->auxinfo.name,
+			     union_cred->auxinfo.name_type,
+			     name) != GSS_S_COMPLETE) ||
+	    (gss_canonicalize_name(minor_status, *name,
+				   &union_cred->mechs_array[0],
+				   NULL) != GSS_S_COMPLETE)) {
+	    status = GSS_S_DEFECTIVE_CREDENTIAL;
+	    goto error;
+	}
+    }
+
+    /*
+     * copy the mechanism set in union_cred into an OID set and return in
+     * the mechanisms parameter.
+     */
+    
+    if(mechanisms != NULL) {
+	status = GSS_S_FAILURE;
+	*mechanisms = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
+	if (*mechanisms == NULL)
+	    goto error;
+
+	(*mechanisms)->count = 0;
+	(*mechanisms)->elements =
+	    (gss_OID) malloc(sizeof(gss_OID_desc) *
+			     union_cred->count);
+
+	if ((*mechanisms)->elements == NULL) {
+	    free(*mechanisms);
+	    *mechanisms = NULL;
+	    goto error;
+	}
+
+	for(i=0; i < union_cred->count; i++) {
+	    (*mechanisms)->elements[i].elements = (void *)
+		malloc(union_cred->mechs_array[i].length);
+	    if ((*mechanisms)->elements[i].elements == NULL)
+		goto error;
+	    g_OID_copy(&(*mechanisms)->elements[i],
+		       &union_cred->mechs_array[i]);
+	    (*mechanisms)->count++;
+	}
+    }
+    
+    return(GSS_S_COMPLETE);
+
+error:
+    /*
+     * cleanup any allocated memory - we can just call
+     * gss_release_oid_set, because the set is constructed so that
+     * count always references the currently copied number of
+     * elements.
+     */
+    if (mechanisms && *mechanisms != NULL)
+	(void) gss_release_oid_set(&temp_minor_status, mechanisms);
+
+    if (name && *name != NULL)
+	(void) gss_release_name(&temp_minor_status, name);
+
+    return (status);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
+			 initiator_lifetime, acceptor_lifetime, cred_usage)
+    OM_uint32		*minor_status;
+    gss_cred_id_t	cred_handle;
+    gss_OID		mech_type;
+    gss_name_t		*name;
+    OM_uint32		*initiator_lifetime;
+    OM_uint32		*acceptor_lifetime;
+    gss_cred_usage_t *cred_usage;
+{
+    gss_union_cred_t	union_cred;
+    gss_cred_id_t	mech_cred;
+    gss_mechanism	mech;
+    OM_uint32		status, temp_minor_status;
+    gss_name_t		internal_name;
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (name != NULL)
+	*name = GSS_C_NO_NAME;
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    mech = gssint_get_mechanism (mech_type);
+    if (!mech)
+	return (GSS_S_BAD_MECH);
+    if (!mech->gss_inquire_cred_by_mech)
+	return (GSS_S_BAD_BINDINGS);
+     
+    union_cred = (gss_union_cred_t) cred_handle;
+    mech_cred = gssint_get_mechanism_cred(union_cred, mech_type);
+
+#if 0
+    if (mech_cred == NULL)
+	return (GSS_S_DEFECTIVE_CREDENTIAL);
+#endif
+
+    status = mech->gss_inquire_cred_by_mech(mech->context, minor_status,
+					    mech_cred, mech_type,
+					    name ? &internal_name : NULL,
+					    initiator_lifetime,
+					    acceptor_lifetime, cred_usage);
+	
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    if (name) {
+	/*
+	 * Convert internal_name into a union_name equivalent.
+	 */
+	status = gssint_convert_name_to_union_name(
+	    &temp_minor_status, mech,
+	    internal_name, name);
+	if (status != GSS_S_COMPLETE) {
+	    *minor_status = temp_minor_status;
+	    return (status);
+	}
+    }
+
+    return (GSS_S_COMPLETE);
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_inq_names.c b/krb5-1-6/src/lib/gssapi/mechglue/g_inq_names.c
new file mode 100644
index 000000000..d1ed23152
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_inq_names.c
@@ -0,0 +1,190 @@
+/* #pragma ident	"@(#)g_inquire_names.c	1.16	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_inquire_context
+ */
+
+#include "mglueP.h"
+
+#define	MAX_MECH_OID_PAIRS 32
+
+/* Last argument new for V2 */
+OM_uint32 KRB5_CALLCONV
+gss_inquire_names_for_mech(minor_status, mechanism, name_types)
+
+OM_uint32 *	minor_status;
+gss_OID 	mechanism;
+gss_OID_set *	name_types;
+
+{
+    OM_uint32		status;
+    gss_mechanism	mech;
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (name_types != NULL)
+	*name_types = GSS_C_NO_OID_SET;
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (name_types == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    mech = gssint_get_mechanism (mechanism);
+    
+    if (mech) {
+
+	if (mech->gss_inquire_names_for_mech)
+	    status = mech->gss_inquire_names_for_mech(
+				mech->context,
+				minor_status,
+				mechanism,
+				name_types);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return(status);
+    }
+    
+    return (GSS_S_BAD_MECH);
+}
+
+static OM_uint32
+val_inq_mechs4name_args(
+    OM_uint32 *minor_status,
+    const gss_name_t input_name,
+    gss_OID_set *mech_set)
+{
+
+    /* Initialize outputs. */
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (mech_set != NULL)
+	*mech_set = GSS_C_NO_OID_SET;
+
+    /* Validate arguments.e
+ */
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (input_name == GSS_C_NO_NAME)
+	return (GSS_S_BAD_NAME);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_inquire_mechs_for_name(minor_status, input_name, mech_set)
+
+    OM_uint32 *		minor_status;
+    const gss_name_t	input_name;
+    gss_OID_set *		mech_set;
+
+{
+    OM_uint32		status;
+    static char		*mech_list[MAX_MECH_OID_PAIRS+1];
+    gss_OID_set		mech_name_types;
+    int			present;
+    char 			*mechanism;
+    gss_OID 		mechOid;
+    gss_OID 		name_type;
+    gss_buffer_desc		name_buffer;
+    int			i;
+
+    status = val_inq_mechs4name_args(minor_status, input_name, mech_set);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    status = gss_create_empty_oid_set(minor_status, mech_set);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+    *mech_list = NULL;
+    status = gssint_get_mechanisms(mech_list, MAX_MECH_OID_PAIRS+1);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+    for (i = 0; i < MAX_MECH_OID_PAIRS && mech_list[i] != NULL; i++) {
+	mechanism = mech_list[i];
+	if (gssint_mech_to_oid(mechanism, &mechOid) == GSS_S_COMPLETE) {
+	    status = gss_inquire_names_for_mech(
+		minor_status,
+		mechOid,
+		&mech_name_types);
+	    if (status == GSS_S_COMPLETE) {
+		status = gss_display_name(minor_status,
+					  input_name,
+					  &name_buffer,
+					  &name_type);
+
+		(void) gss_release_buffer(NULL, &name_buffer);
+
+		if (status == GSS_S_COMPLETE && name_type) {
+		    status = gss_test_oid_set_member(
+			minor_status,
+			name_type,
+			mech_name_types,
+			&present);
+		    if (status == GSS_S_COMPLETE &&
+			present) {
+			status = gss_add_oid_set_member(
+			    minor_status,
+			    mechOid,
+			    mech_set);
+			if (status != GSS_S_COMPLETE) {
+			    (void) gss_release_oid_set(
+				minor_status,
+				&mech_name_types);
+			    (void) gss_release_oid_set(
+				minor_status,
+				mech_set);
+			    return (status);
+			}
+		    }
+		}
+		(void) gss_release_oid_set(
+		    minor_status,
+		    &mech_name_types);
+	    }
+	} else {
+	    (void) gss_release_oid_set(
+		minor_status,
+		mech_set);
+	    return (GSS_S_FAILURE);
+	}
+    }
+    return (GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_mechname.c b/krb5-1-6/src/lib/gssapi/mechglue/g_mechname.c
new file mode 100644
index 000000000..0607c38f1
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_mechname.c
@@ -0,0 +1,112 @@
+/*
+ * g_mechname.c --- registry of mechanism-specific name types
+ *
+ * This file contains a registry of mechanism-specific name types.  It
+ * is used to determine which name types not should be lazy evaluated,
+ * but rather evaluated on the spot.
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+static gss_mech_spec_name name_list = NULL;
+
+/*
+ * generic searching helper function.
+ */
+static gss_mech_spec_name search_mech_spec(name_type)
+    gss_OID name_type;
+{
+    gss_mech_spec_name p;
+
+    for (p = name_list; p; p = p->next) {
+	if (g_OID_equal(name_type, p->name_type))
+	    return p;
+    }
+    return NULL;
+}
+
+/*
+ * Given a name_type, if it is specific to a mechanism, return the
+ * mechanism OID.  Otherwise, return NULL.
+ */
+gss_OID gss_find_mechanism_from_name_type(name_type)
+    gss_OID name_type;
+{
+    gss_mech_spec_name p;
+
+    p = search_mech_spec(name_type);
+    if (!p)
+	return NULL;
+    return p->mech;
+}
+
+/*
+ * This function adds a (name_type, mechanism) pair to the
+ * mechanism-specific name type registry.  If an entry for the
+ * name_type already exists, then zero out the mechanism entry.
+ * Otherwise, enter the pair into the registry.
+ */
+OM_uint32
+gss_add_mech_name_type(minor_status, name_type, mech)
+    OM_uint32	*minor_status;
+    gss_OID	name_type;
+    gss_OID	mech;
+{
+    OM_uint32	major_status, tmp;
+    gss_mech_spec_name p;
+
+    p = search_mech_spec(name_type);
+    if (p) {
+	/*
+	 * We found an entry for this name type; mark it as not being
+	 * a mechanism-specific name type.
+	 */
+	if (p->mech) {
+	    if (!g_OID_equal(mech, p->mech)) {
+		generic_gss_release_oid(minor_status, &p->mech);
+		p->mech = 0;
+	    }
+	}
+	return GSS_S_COMPLETE;
+    }
+    p = malloc(sizeof(gss_mech_spec_name_desc));
+    if (!p) {
+	*minor_status = ENOMEM;
+	goto allocation_failure;
+    }
+    p->name_type = 0;
+    p->mech = 0;
+    
+    major_status = generic_gss_copy_oid(minor_status, name_type,
+					&p->name_type);
+    if (major_status)
+	goto allocation_failure;
+    major_status = generic_gss_copy_oid(minor_status, mech,
+					&p->mech);
+    if (major_status)
+	goto allocation_failure;
+
+    p->next = name_list;
+    p->prev = 0;
+    name_list = p;
+
+    return GSS_S_COMPLETE;
+    
+allocation_failure:
+    if (p) {
+	if (p->mech)
+	    generic_gss_release_oid(&tmp, &p->mech);
+	if (p->name_type)
+	    generic_gss_release_oid(&tmp, &p->name_type);
+	free(p);
+    }
+    return GSS_S_FAILURE;
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_oid_ops.c b/krb5-1-6/src/lib/gssapi/mechglue/g_oid_ops.c
new file mode 100644
index 000000000..86e57972d
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_oid_ops.c
@@ -0,0 +1,88 @@
+/* #pragma ident	"@(#)g_oid_ops.c	1.11	98/01/22 SMI" */
+/*
+ * lib/gssapi/mechglue/g_oid_ops.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
+ */
+
+#include "mglueP.h"
+/* should include to get protos #include "../generic/gssapiP_generic.h" */
+
+extern gss_mechanism *gssint_mechs_array;
+
+/*
+ * gss_release_oid has been moved to g_initialize, becasue it requires access
+ * to the mechanism list.  All functions requiring direct access to the
+ * mechanism list are now in g_initialize.c
+ */
+
+OM_uint32 KRB5_CALLCONV
+gss_create_empty_oid_set(minor_status, oid_set)
+    OM_uint32	*minor_status;
+    gss_OID_set	*oid_set;
+{
+	return generic_gss_create_empty_oid_set(minor_status, oid_set);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_add_oid_set_member(minor_status, member_oid, oid_set)
+    OM_uint32	*minor_status;
+    gss_OID	member_oid;
+    gss_OID_set	*oid_set;
+{
+     return generic_gss_add_oid_set_member(minor_status, member_oid, oid_set);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_test_oid_set_member(minor_status, member, set, present)
+    OM_uint32	*minor_status;
+    gss_OID	member;
+    gss_OID_set	set;
+    int		*present;
+{
+    return generic_gss_test_oid_set_member(minor_status, member, set, present);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_oid_to_str(minor_status, oid, oid_str)
+    OM_uint32		*minor_status;
+    gss_OID		oid;
+    gss_buffer_t	oid_str;
+{
+    return generic_gss_oid_to_str(minor_status, oid, oid_str);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_str_to_oid(minor_status, oid_str, oid)
+    OM_uint32		*minor_status;
+    gss_buffer_t	oid_str;
+    gss_OID		*oid;
+{
+    return generic_gss_str_to_oid(minor_status, oid_str, oid);
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_process_context.c b/krb5-1-6/src/lib/gssapi/mechglue/g_process_context.c
new file mode 100644
index 000000000..18b12050c
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_process_context.c
@@ -0,0 +1,81 @@
+/* #pragma ident	"@(#)g_process_context.c	1.12	98/01/22 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_process_context
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_process_context_token (minor_status,
+                           context_handle,
+                           token_buffer)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+gss_buffer_t		token_buffer;
+
+{
+    OM_uint32		status;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+    
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+    *minor_status = 0;
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    if (token_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (GSS_EMPTY_BUFFER(token_buffer))
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+
+	if (mech->gss_process_context_token)
+	    status = mech->gss_process_context_token(
+						    mech->context,
+						    minor_status,
+						    ctx->internal_ctx_id,
+						    token_buffer);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return(status);
+    }
+    
+    return (GSS_S_BAD_MECH);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_rel_buffer.c b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_buffer.c
new file mode 100644
index 000000000..6f8367a1d
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_buffer.c
@@ -0,0 +1,58 @@
+/* #ident  "@(#)g_rel_buffer.c 1.2     96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_buffer
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_release_buffer (minor_status,
+		    buffer)
+
+OM_uint32 *		minor_status;
+gss_buffer_t		buffer;
+{
+    if (minor_status)
+	*minor_status = 0;
+
+    /* if buffer is NULL, return */
+
+    if(buffer == GSS_C_NO_BUFFER)
+	return(GSS_S_COMPLETE);
+
+    if ((buffer->length) &&
+	(buffer->value)) {
+	    free(buffer->value);
+	    buffer->length = 0;
+	    buffer->value = NULL;
+    }
+
+    return (GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_rel_cred.c b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_cred.c
new file mode 100644
index 000000000..6f58d6592
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_cred.c
@@ -0,0 +1,100 @@
+/* #pragma ident	"@(#)g_rel_cred.c	1.14	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_cred
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_release_cred(minor_status,
+                 cred_handle)
+
+OM_uint32 *		minor_status;
+gss_cred_id_t *		cred_handle;
+
+{
+    OM_uint32		status, temp_status;
+    int			j;
+    gss_union_cred_t	union_cred;
+    gss_mechanism	mech;
+    
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    *minor_status = 0;
+
+    if (cred_handle == NULL)
+	return (GSS_S_NO_CRED | GSS_S_CALL_INACCESSIBLE_READ);
+    
+    /*
+     * Loop through the union_cred struct, selecting the approprate 
+     * underlying mechanism routine and calling it. At the end,
+     * release all of the storage taken by the union_cred struct.
+     */
+    
+    union_cred = (gss_union_cred_t) *cred_handle;
+    if (GSSINT_CHK_LOOP(union_cred))
+	return (GSS_S_NO_CRED | GSS_S_CALL_INACCESSIBLE_READ);
+    *cred_handle = NULL;
+
+    if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
+	return (GSS_S_COMPLETE);
+
+    status = GSS_S_COMPLETE;
+    
+    for(j=0; j < union_cred->count; j++) {
+
+	mech = gssint_get_mechanism (&union_cred->mechs_array[j]);
+
+	if (union_cred->mechs_array[j].elements)
+		free(union_cred->mechs_array[j].elements);
+	if (mech) {
+	    if (mech->gss_release_cred) {
+		temp_status = mech->gss_release_cred
+		    (mech->context,
+		     minor_status,
+		     &union_cred->cred_array[j]);
+
+	    if (temp_status != GSS_S_COMPLETE)
+		status = GSS_S_NO_CRED;
+
+	    } else
+		status = GSS_S_UNAVAILABLE;
+	} else
+	    status = GSS_S_DEFECTIVE_CREDENTIAL;
+    }
+
+    gss_release_buffer(minor_status, &union_cred->auxinfo.name);
+    free(union_cred->cred_array);
+    free(union_cred->mechs_array);
+    free(union_cred);
+    
+    return(status);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_rel_name.c b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_name.c
new file mode 100644
index 000000000..a6615b707
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_name.c
@@ -0,0 +1,83 @@
+/* #pragma ident	"@(#)g_rel_name.c	1.11	04/02/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_name
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_release_name (minor_status,
+		  input_name)
+
+OM_uint32 *		minor_status;
+gss_name_t *		input_name;
+
+{
+    gss_union_name_t	union_name;
+    
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+    *minor_status = 0;
+    
+    /* if input_name is NULL, return error */
+    if (input_name == 0)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+    if (*input_name == GSS_C_NO_NAME)
+	return GSS_S_COMPLETE;
+
+    /*
+     * free up the space for the external_name and then
+     * free the union_name descriptor
+     */
+    
+    union_name = (gss_union_name_t) *input_name;
+    if (GSSINT_CHK_LOOP(union_name))
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+    *input_name = 0;
+    *minor_status = 0;
+
+    if (union_name->name_type)
+	    gss_release_oid(minor_status, &union_name->name_type);
+    
+    free(union_name->external_name->value);
+    free(union_name->external_name);
+
+    if (union_name->mech_type) {
+	    gssint_release_internal_name(minor_status, union_name->mech_type,
+					&union_name->mech_name);
+	    gss_release_oid(minor_status, &union_name->mech_type);
+    }
+
+    free(union_name);
+
+    return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_rel_oid_set.c b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_oid_set.c
new file mode 100644
index 000000000..f712a891a
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_rel_oid_set.c
@@ -0,0 +1,63 @@
+/* #pragma ident	"@(#)g_rel_oid_set.c	1.12	97/11/11 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_oid_set
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_release_oid_set (minor_status,
+		     set)
+
+OM_uint32 *		minor_status;
+gss_OID_set *		set;
+{
+    OM_uint32 index;
+    gss_OID oid;
+    if (minor_status)
+	*minor_status = 0;
+
+    if (set ==NULL)
+	return GSS_S_COMPLETE;
+
+    if (*set == GSS_C_NULL_OID_SET)
+	return(GSS_S_COMPLETE);
+
+    for (index=0; index<(*set)->count; index++) {
+      oid = &(*set)->elements[index];
+      free(oid->elements);
+    }
+    free((*set)->elements);
+    free(*set);
+
+    *set = GSS_C_NULL_OID_SET;
+    
+    return(GSS_S_COMPLETE);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_seal.c b/krb5-1-6/src/lib/gssapi/mechglue/g_seal.c
new file mode 100644
index 000000000..f784be1ab
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_seal.c
@@ -0,0 +1,196 @@
+/* #pragma ident	"@(#)g_seal.c	1.19	98/04/21 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_seal
+ */
+
+#include "mglueP.h"
+
+static OM_uint32
+val_seal_args(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    int qop_req,
+    gss_buffer_t input_message_buffer,
+    int *conf_state,
+    gss_buffer_t output_message_buffer)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (output_message_buffer != GSS_C_NO_BUFFER) {
+	output_message_buffer->length = 0;
+	output_message_buffer->value = NULL;
+    }
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    if (input_message_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (output_message_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_seal (minor_status,
+          context_handle,
+          conf_req_flag,
+          qop_req,
+          input_message_buffer,
+          conf_state,
+          output_message_buffer)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+int			conf_req_flag;
+int			qop_req;
+gss_buffer_t		input_message_buffer;
+int *			conf_state;
+gss_buffer_t		output_message_buffer;
+{
+ /* EXPORT DELETE START */
+
+    OM_uint32		status;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+
+    status = val_seal_args(minor_status, context_handle,
+			   conf_req_flag, qop_req,
+			   input_message_buffer, conf_state,
+			   output_message_buffer);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+    
+    if (mech) {
+	if (mech->gss_seal)
+	    status = mech->gss_seal(
+				    mech->context,
+				    minor_status,
+				    ctx->internal_ctx_id,
+				    conf_req_flag,
+				    qop_req,
+				    input_message_buffer,
+				    conf_state,
+				    output_message_buffer);
+	else
+	    status = GSS_S_UNAVAILABLE;
+	
+	return(status);
+    }
+ /* EXPORT DELETE END */
+ 
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_wrap (minor_status,
+          context_handle,
+          conf_req_flag,
+          qop_req,
+          input_message_buffer,
+          conf_state,
+          output_message_buffer)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+int			conf_req_flag;
+gss_qop_t		qop_req;
+gss_buffer_t		input_message_buffer;
+int *			conf_state;
+gss_buffer_t		output_message_buffer;
+
+{
+    return gss_seal(minor_status, (gss_ctx_id_t)context_handle,
+		    conf_req_flag, (int) qop_req,
+		    (gss_buffer_t)input_message_buffer, conf_state,
+		    output_message_buffer);
+}
+
+/*
+ * New for V2
+ */
+OM_uint32 KRB5_CALLCONV
+gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+		    qop_req, req_output_size, max_input_size)
+    OM_uint32		*minor_status;
+    gss_ctx_id_t	context_handle;
+    int			conf_req_flag;
+    gss_qop_t		qop_req;
+    OM_uint32		req_output_size;
+    OM_uint32		*max_input_size;
+{
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+    *minor_status = 0;
+    
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    if (max_input_size == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+    
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+
+    if (!mech)
+	return (GSS_S_BAD_MECH);
+
+    if (!mech->gss_wrap_size_limit)
+	return (GSS_S_UNAVAILABLE);
+    
+    return (mech->gss_wrap_size_limit(mech->context, minor_status,
+				      ctx->internal_ctx_id, conf_req_flag, qop_req,
+				      req_output_size, max_input_size));
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_sign.c b/krb5-1-6/src/lib/gssapi/mechglue/g_sign.c
new file mode 100644
index 000000000..c0510afe2
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_sign.c
@@ -0,0 +1,134 @@
+/* #pragma ident	"@(#)g_sign.c	1.14	98/04/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_sign
+ */
+
+#include "mglueP.h"
+
+static OM_uint32
+val_sign_args(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t context_handle,
+    int qop_req,
+    gss_buffer_t message_buffer,
+    gss_buffer_t msg_token)
+{
+
+    /* Initialize outputs. */
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (msg_token != GSS_C_NO_BUFFER) {
+	msg_token->value = NULL;
+	msg_token->length = 0;
+    }
+
+    /* Validate arguments. */
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    if (message_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (msg_token == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_sign (minor_status,
+          context_handle,
+          qop_req,
+          message_buffer,
+          msg_token)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+int			qop_req;
+gss_buffer_t		message_buffer;
+gss_buffer_t		msg_token;
+
+{
+    OM_uint32		status;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+
+    status = val_sign_args(minor_status, context_handle,
+			   qop_req, message_buffer, msg_token);
+    if (status != GSS_S_COMPLETE)
+	return (status);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+	if (mech->gss_sign)
+	    status = mech->gss_sign(
+				    mech->context,
+				    minor_status,
+				    ctx->internal_ctx_id,
+				    qop_req,
+				    message_buffer,
+				    msg_token);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return(status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_get_mic (minor_status,
+          context_handle,
+          qop_req,
+          message_buffer,
+          msg_token)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+gss_qop_t		qop_req;
+gss_buffer_t		message_buffer;
+gss_buffer_t		msg_token;
+
+{
+	return (gss_sign(minor_status, context_handle, (int) qop_req,
+			 message_buffer, msg_token));
+}
+
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_store_cred.c b/krb5-1-6/src/lib/gssapi/mechglue/g_store_cred.c
new file mode 100644
index 000000000..5663c28ea
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_store_cred.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* #pragma ident	"@(#)g_store_cred.c	1.2	04/04/05 SMI" */
+
+/*
+ *  glue routine for gss_store_cred
+ */
+
+#include <mglueP.h>
+
+static OM_uint32
+val_store_cred_args(
+	OM_uint32 *minor_status,
+	const gss_cred_id_t input_cred_handle,
+	gss_cred_usage_t cred_usage,
+	const gss_OID desired_mech,
+	OM_uint32 overwrite_cred,
+	OM_uint32 default_cred,
+	gss_OID_set *elements_stored,
+	gss_cred_usage_t *cred_usage_stored)
+{
+
+	/* Initialize outputs. */
+
+	if (minor_status != NULL)
+		*minor_status = 0;
+
+	if (elements_stored != NULL)
+		*elements_stored = GSS_C_NULL_OID_SET;
+
+	/* Validate arguments. */
+
+	if (minor_status == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	if (input_cred_handle == GSS_C_NO_CREDENTIAL)
+		return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED);
+
+	return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32 gss_store_cred(minor_status,
+			input_cred_handle,
+			cred_usage,
+			desired_mech,
+			overwrite_cred,
+			default_cred,
+			elements_stored,
+			cred_usage_stored)
+
+OM_uint32		*minor_status;
+const gss_cred_id_t	 input_cred_handle;
+gss_cred_usage_t	 cred_usage;
+const gss_OID		 desired_mech;
+OM_uint32		 overwrite_cred;
+OM_uint32		 default_cred;
+gss_OID_set		*elements_stored;
+gss_cred_usage_t	*cred_usage_stored;
+
+{
+	OM_uint32		major_status = GSS_S_FAILURE;
+	gss_union_cred_t	union_cred;
+	gss_cred_id_t		mech_cred;
+	gss_mechanism		mech;
+	gss_OID			dmech;
+	int			i;
+
+	major_status = val_store_cred_args(minor_status,
+					   input_cred_handle,
+					   cred_usage,
+					   desired_mech,
+					   overwrite_cred,
+					   default_cred,
+					   elements_stored,
+					   cred_usage_stored);
+	if (major_status != GSS_S_COMPLETE)
+		return (major_status);
+
+	/* Initial value needed below. */
+	major_status = GSS_S_FAILURE;
+
+	if (cred_usage_stored != NULL)
+		*cred_usage_stored = GSS_C_BOTH; /* there's no GSS_C_NEITHER */
+
+	union_cred = (gss_union_cred_t)input_cred_handle;
+
+	/* desired_mech != GSS_C_NULL_OID -> store one element */
+	if (desired_mech != GSS_C_NULL_OID) {
+		mech = gssint_get_mechanism(desired_mech);
+		if (mech == NULL)
+			return (GSS_S_BAD_MECH);
+
+		if (mech->gss_store_cred == NULL)
+			return (major_status);
+
+		mech_cred = gssint_get_mechanism_cred(union_cred, desired_mech);
+		if (mech_cred == GSS_C_NO_CREDENTIAL)
+			return (GSS_S_NO_CRED);
+
+		return (mech->gss_store_cred(mech->context,
+						minor_status,
+						(gss_cred_id_t)mech_cred,
+						cred_usage,
+						desired_mech,
+						overwrite_cred,
+						default_cred,
+						elements_stored,
+						cred_usage_stored));
+	}
+
+	/* desired_mech == GSS_C_NULL_OID -> store all elements */
+
+	*minor_status = 0;
+
+	for (i = 0; i < union_cred->count; i++) {
+		/* Get mech and cred element */
+		dmech = &union_cred->mechs_array[i];
+		mech = gssint_get_mechanism(dmech);
+		if (mech == NULL)
+			continue;
+
+		if (mech->gss_store_cred == NULL)
+			continue;
+
+		mech_cred = gssint_get_mechanism_cred(union_cred, dmech);
+		if (mech_cred == GSS_C_NO_CREDENTIAL)
+			continue; /* can't happen, but safe to ignore */
+
+		major_status = mech->gss_store_cred(mech->context,
+						minor_status,
+						(gss_cred_id_t)mech_cred,
+						cred_usage,
+						dmech,
+						overwrite_cred,
+						default_cred,
+						NULL,
+						cred_usage_stored);
+		if (major_status != GSS_S_COMPLETE)
+			continue;
+
+		/* Succeeded for at least one mech */
+
+		if (elements_stored == NULL)
+			continue;
+
+		if (*elements_stored == GSS_C_NULL_OID_SET) {
+			major_status = gss_create_empty_oid_set(minor_status,
+						elements_stored);
+
+			if (GSS_ERROR(major_status))
+				return (major_status);
+		}
+
+		major_status = gss_add_oid_set_member(minor_status, dmech,
+			elements_stored);
+
+		/* The caller should clean up elements_stored */
+		if (GSS_ERROR(major_status))
+			return (major_status);
+	}
+
+	/*
+	 * Success with some mechs may mask failure with others, but
+	 * that's what elements_stored is for.
+	 */
+	return (major_status);
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_unseal.c b/krb5-1-6/src/lib/gssapi/mechglue/g_unseal.c
new file mode 100644
index 000000000..56f567359
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_unseal.c
@@ -0,0 +1,122 @@
+/* #pragma ident	"@(#)g_unseal.c	1.13	98/01/22 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_unseal
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_unseal (minor_status,
+            context_handle,
+            input_message_buffer,
+            output_message_buffer,
+            conf_state,
+            qop_state)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+gss_buffer_t		input_message_buffer;
+gss_buffer_t		output_message_buffer;
+int *			conf_state;
+int *			qop_state;
+
+{
+/* EXPORT DELETE START */
+    OM_uint32		status;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (output_message_buffer != GSS_C_NO_BUFFER) {
+	output_message_buffer->length = 0;
+	output_message_buffer->value = NULL;
+    }
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    if (input_message_buffer == GSS_C_NO_BUFFER ||
+	GSS_EMPTY_BUFFER(input_message_buffer))
+
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (output_message_buffer == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+	if (mech->gss_unseal) 
+	    status = mech->gss_unseal(
+				      mech->context,
+				      minor_status,
+				      ctx->internal_ctx_id,
+				      input_message_buffer,
+				      output_message_buffer,
+				      conf_state,
+				      qop_state);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return(status);
+    }
+
+/* EXPORT DELETE END */
+
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_unwrap (minor_status,
+            context_handle,
+            input_message_buffer,
+            output_message_buffer,
+            conf_state,
+            qop_state)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+gss_buffer_t		input_message_buffer;
+gss_buffer_t		output_message_buffer;
+int *			conf_state;
+gss_qop_t *		qop_state;
+
+{
+    return (gss_unseal(minor_status, (gss_ctx_id_t)context_handle,
+		       (gss_buffer_t)input_message_buffer,
+		       output_message_buffer, conf_state, (int *) qop_state));
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/g_verify.c b/krb5-1-6/src/lib/gssapi/mechglue/g_verify.c
new file mode 100644
index 000000000..5f0374643
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/g_verify.c
@@ -0,0 +1,104 @@
+/* #pragma ident	"@(#)g_verify.c	1.13	98/04/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_verify
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_verify (minor_status,
+            context_handle,
+            message_buffer,
+            token_buffer,
+            qop_state)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+gss_buffer_t		message_buffer;
+gss_buffer_t		token_buffer;
+int *			qop_state;
+
+{
+    OM_uint32		status;
+    gss_union_ctx_id_t	ctx;
+    gss_mechanism	mech;
+
+
+    if (minor_status == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+    *minor_status = 0;
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+	return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+    if ((message_buffer == GSS_C_NO_BUFFER) ||
+	GSS_EMPTY_BUFFER(token_buffer))
+
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+	if (mech->gss_verify)
+	    status = mech->gss_verify(
+				      mech->context,
+				      minor_status,
+				      ctx->internal_ctx_id,
+				      message_buffer,
+				      token_buffer,
+				      qop_state);
+	else
+	    status = GSS_S_UNAVAILABLE;
+
+	return(status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_verify_mic (minor_status,
+            context_handle,
+            message_buffer,
+            token_buffer,
+            qop_state)
+
+OM_uint32 *		minor_status;
+gss_ctx_id_t		context_handle;
+gss_buffer_t		message_buffer;
+gss_buffer_t		token_buffer;
+gss_qop_t *		qop_state;
+
+{
+	return (gss_verify(minor_status, context_handle,
+			   message_buffer, token_buffer, (int *) qop_state));
+}
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/mech.conf b/krb5-1-6/src/lib/gssapi/mechglue/mech.conf
new file mode 100644
index 000000000..5257a01a2
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/mech.conf
@@ -0,0 +1,7 @@
+#
+#
+# GSSAPI Mechanism Definitions
+#
+# library				function
+/opt/SUNWgss/lib/mech_krb5.so	krb5_gss_initialize
+#mech_krb5.so			krb5_gss_initialize
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/mechglue.h b/krb5-1-6/src/lib/gssapi/mechglue/mechglue.h
new file mode 100644
index 000000000..4f4cd481c
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/mechglue.h
@@ -0,0 +1,38 @@
+/* #ident  "@(#)mechglue.h 1.13     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This header contains the mechglue definitions.
+ */
+
+#ifndef _GSS_MECHGLUE_H
+#define _GSS_MECHGLUE_H
+
+#include <gssapi/gssapi.h>
+
+/********************************************************/
+/* GSSAPI Extension functions -- these functions aren't */
+/* in the GSSAPI, but they are provided in this library */
+
+#endif /* _GSS_MECHGLUE_H */
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/mglueP.h b/krb5-1-6/src/lib/gssapi/mechglue/mglueP.h
new file mode 100644
index 000000000..70da996d1
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/mglueP.h
@@ -0,0 +1,492 @@
+/* #ident  "@(#)mglueP.h 1.2     96/01/18 SMI" */
+
+/*
+ * This header contains the private mechglue definitions.
+ *
+ * Copyright (c) 1995, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _GSS_MECHGLUEP_H
+#define _GSS_MECHGLUEP_H
+
+#include "autoconf.h"
+#include "mechglue.h"
+#include "gssapiP_generic.h"
+
+#define	g_OID_copy(o1, o2)					\
+do {								\
+	memcpy((o1)->elements, (o2)->elements, (o2)->length);	\
+	(o1)->length = (o2)->length;				\
+} while (0)
+
+#define	GSS_EMPTY_BUFFER(buf)	((buf) == NULL ||\
+	(buf)->value == NULL || (buf)->length == 0)
+
+/*
+ * Array of context IDs typed by mechanism OID
+ */
+typedef struct gss_ctx_id_struct {
+	struct gss_ctx_id_struct *loopback;
+	gss_OID			mech_type;
+	gss_ctx_id_t		internal_ctx_id;
+} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
+
+/*
+ * Generic GSSAPI names.  A name can either be a generic name, or a
+ * mechanism specific name....
+ */
+typedef struct gss_name_struct {
+	struct gss_name_struct *loopback;
+	gss_OID			name_type;
+	gss_buffer_t		external_name;
+	/*
+	 * These last two fields are only filled in for mechanism
+	 * names.
+	 */
+	gss_OID			mech_type;
+	gss_name_t		mech_name;
+} gss_union_name_desc, *gss_union_name_t;
+
+/*
+ * Structure for holding list of mechanism-specific name types
+ */
+typedef struct gss_mech_spec_name_t {
+    gss_OID	name_type;
+    gss_OID	mech;
+    struct gss_mech_spec_name_t	*next, *prev;
+} gss_mech_spec_name_desc, *gss_mech_spec_name;
+
+/*
+ * Credential auxiliary info, used in the credential structure
+ */
+typedef struct gss_union_cred_auxinfo {
+	gss_buffer_desc		name;
+	gss_OID			name_type;
+	OM_uint32		creation_time;
+	OM_uint32		time_rec;
+	int			cred_usage;
+} gss_union_cred_auxinfo;
+
+/*
+ * Set of Credentials typed on mechanism OID
+ */
+typedef struct gss_cred_id_struct {
+	struct gss_cred_id_struct *loopback;
+	int			count;
+	gss_OID			mechs_array;
+	gss_cred_id_t		*cred_array;
+	gss_union_cred_auxinfo	auxinfo;
+} gss_union_cred_desc, *gss_union_cred_t;
+ 
+/*
+ * Rudimentary pointer validation macro to check whether the
+ * "loopback" field of an opaque struct points back to itself.  This
+ * field also catches some programming errors where an opaque pointer
+ * is passed to a function expecting the address of the opaque
+ * pointer.
+ */
+#define GSSINT_CHK_LOOP(p) (!((p) != NULL && (p)->loopback == (p)))
+
+/********************************************************/
+/* The Mechanism Dispatch Table -- a mechanism needs to */
+/* define one of these and provide a function to return */
+/* it to initialize the GSSAPI library                  */
+
+/*
+ * This is the definition of the mechs_array struct, which is used to
+ * define the mechs array table. This table is used to indirectly
+ * access mechanism specific versions of the gssapi routines through
+ * the routines in the glue module (gssd_mech_glue.c)
+ *
+ * This contants all of the functions defined in gssapi.h except for
+ * gss_release_buffer() and gss_release_oid_set(), which I am
+ * assuming, for now, to be equal across mechanisms.  
+ */
+ 
+typedef struct gss_config {
+    OM_uint32	    priority;
+    char *	    mechNameStr;
+    gss_OID_desc    mech_type;
+    void *	    context;
+    OM_uint32       (*gss_acquire_cred)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_name_t,		/* desired_name */
+		    OM_uint32,		/* time_req */
+		    gss_OID_set,	/* desired_mechs */
+		    int,		/* cred_usage */
+		    gss_cred_id_t*,	/* output_cred_handle */
+		    gss_OID_set*,	/* actual_mechs */
+		    OM_uint32*		/* time_rec */
+		    );
+    OM_uint32       (*gss_release_cred)
+	(
+		    void*,		/* context */		       
+		    OM_uint32*,		/* minor_status */
+		    gss_cred_id_t*	/* cred_handle */
+		    );
+    OM_uint32       (*gss_init_sec_context)
+	(
+		    void*,			/* context */
+		    OM_uint32*,			/* minor_status */
+		    gss_cred_id_t,		/* claimant_cred_handle */
+		    gss_ctx_id_t*,		/* context_handle */
+		    gss_name_t,			/* target_name */
+		    gss_OID,			/* mech_type */
+		    OM_uint32,			/* req_flags */
+		    OM_uint32,			/* time_req */
+		    gss_channel_bindings_t,	/* input_chan_bindings */
+		    gss_buffer_t,		/* input_token */
+		    gss_OID*,			/* actual_mech_type */
+		    gss_buffer_t,		/* output_token */
+		    OM_uint32*,			/* ret_flags */
+		    OM_uint32*			/* time_rec */
+		    );
+    OM_uint32       (*gss_accept_sec_context)
+	(
+		    void*,			/* context */
+		    OM_uint32*,			/* minor_status */
+		    gss_ctx_id_t*,		/* context_handle */
+		    gss_cred_id_t,		/* verifier_cred_handle */
+		    gss_buffer_t,		/* input_token_buffer */
+		    gss_channel_bindings_t,	/* input_chan_bindings */
+		    gss_name_t*,		/* src_name */
+		    gss_OID*,			/* mech_type */
+		    gss_buffer_t,		/* output_token */
+		    OM_uint32*,			/* ret_flags */
+		    OM_uint32*,			/* time_rec */
+		    gss_cred_id_t*		/* delegated_cred_handle */
+		    );
+    OM_uint32       (*gss_process_context_token)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    gss_buffer_t	/* token_buffer */
+		    );
+    OM_uint32       (*gss_delete_sec_context)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_ctx_id_t*,	/* context_handle */
+		    gss_buffer_t	/* output_token */
+		    );
+    OM_uint32       (*gss_context_time)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    OM_uint32*		/* time_rec */
+		    );
+    OM_uint32       (*gss_sign)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    int,		/* qop_req */
+		    gss_buffer_t,	/* message_buffer */
+		    gss_buffer_t	/* message_token */
+		    );
+    OM_uint32       (*gss_verify)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    gss_buffer_t,	/* message_buffer */
+		    gss_buffer_t,	/* token_buffer */
+		    int*		/* qop_state */
+		    );
+    OM_uint32       (*gss_seal)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    int,		/* conf_req_flag */
+		    int,		/* qop_req */
+		    gss_buffer_t,	/* input_message_buffer */
+		    int*,		/* conf_state */
+		    gss_buffer_t	/* output_message_buffer */
+		    );
+    OM_uint32       (*gss_unseal)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    gss_buffer_t,	/* input_message_buffer */
+		    gss_buffer_t,	/* output_message_buffer */
+		    int*,		/* conf_state */
+		    int*		/* qop_state */
+		    );
+    OM_uint32       (*gss_display_status)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    OM_uint32,		/* status_value */
+		    int,		/* status_type */
+		    gss_OID,		/* mech_type */
+		    OM_uint32*,		/* message_context */
+		    gss_buffer_t	/* status_string */
+		    );
+    OM_uint32       (*gss_indicate_mechs)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_OID_set*	/* mech_set */
+		    );
+    OM_uint32       (*gss_compare_name)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_name_t,		/* name1 */
+		    gss_name_t,		/* name2 */
+		    int*		/* name_equal */
+		    );
+    OM_uint32       (*gss_display_name)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_name_t,		/* input_name */
+		    gss_buffer_t,	/* output_name_buffer */
+		    gss_OID*		/* output_name_type */
+		    );
+    OM_uint32       (*gss_import_name)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_buffer_t,	/* input_name_buffer */
+		    gss_OID,		/* input_name_type */
+		    gss_name_t*		/* output_name */
+		    );
+    OM_uint32       (*gss_release_name)
+	(
+		    void*,		/* context */
+		    OM_uint32*,		/* minor_status */
+		    gss_name_t*		/* input_name */
+		    );
+    OM_uint32       (*gss_inquire_cred)
+	(
+		    void*,			/* context */
+		    OM_uint32 *,		/* minor_status */
+		    gss_cred_id_t,		/* cred_handle */
+		    gss_name_t *,		/* name */
+		    OM_uint32 *,		/* lifetime */
+		    int *,			/* cred_usage */
+		    gss_OID_set *		/* mechanisms */
+		    );
+    OM_uint32	    (*gss_add_cred)
+	(
+		    void*,		/* context */
+		    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 */
+		    );
+    OM_uint32	    (*gss_export_sec_context)
+	(
+		    void*,		/* context */
+		    OM_uint32 *,	/* minor_status */
+		    gss_ctx_id_t *,	/* context_handle */
+		    gss_buffer_t	/* interprocess_token */
+		    );
+    OM_uint32	    (*gss_import_sec_context)
+	(
+		    void *,		/* context */
+		    OM_uint32 *,	/* minor_status */
+		    gss_buffer_t,	/* interprocess_token */
+		    gss_ctx_id_t *	/* context_handle */
+		    );
+    OM_uint32 	    (*gss_inquire_cred_by_mech)
+	(
+		    void *,		/* context */
+		    OM_uint32 *,	/* minor_status */
+		    gss_cred_id_t,	/* cred_handle */
+		    gss_OID,		/* mech_type */
+		    gss_name_t *,	/* name */
+		    OM_uint32 *,	/* initiator_lifetime */
+		    OM_uint32 *,	/* acceptor_lifetime */
+		    gss_cred_usage_t *	/* cred_usage */
+		    );
+    OM_uint32	    (*gss_inquire_names_for_mech)
+	(
+		    void *,		/* context */
+		    OM_uint32 *,	/* minor_status */
+		    gss_OID,		/* mechanism */
+		    gss_OID_set *	/* name_types */
+		    );
+    OM_uint32	(*gss_inquire_context)
+	(
+		    void *,		/* context */
+		    OM_uint32 *,	/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    gss_name_t *,	/* src_name */
+		    gss_name_t *,	/* targ_name */
+		    OM_uint32 *,	/* lifetime_rec */
+		    gss_OID *,		/* mech_type */
+		    OM_uint32 *,	/* ctx_flags */
+		    int *,           	/* locally_initiated */
+		    int *		/* open */
+		    );
+    OM_uint32	    (*gss_internal_release_oid)
+	(
+		    void *,		/* context */
+		    OM_uint32 *,	/* minor_status */
+		    gss_OID *		/* OID */
+	 );
+    OM_uint32	     (*gss_wrap_size_limit)
+	(
+		    void *,		/* context */
+		    OM_uint32 *,	/* minor_status */
+		    gss_ctx_id_t,	/* context_handle */
+		    int,		/* conf_req_flag */
+		    gss_qop_t,		/* qop_req */
+		    OM_uint32,		/* req_output_size */
+		    OM_uint32 *		/* max_input_size */
+	 );
+	OM_uint32		(*gss_export_name)
+	(
+		void *,			/* context */
+		OM_uint32 *,		/* minor_status */
+		const gss_name_t,	/* input_name */
+		gss_buffer_t		/* exported_name */
+	/* */);
+	OM_uint32	(*gss_store_cred)
+	(
+		void *,			/* context */
+		OM_uint32 *,		/* minor_status */
+		const gss_cred_id_t,	/* input_cred */
+		gss_cred_usage_t,	/* cred_usage */
+		const gss_OID,		/* desired_mech */
+		OM_uint32,		/* overwrite_cred */
+		OM_uint32,		/* default_cred */
+		gss_OID_set *,		/* elements_stored */
+		gss_cred_usage_t *	/* cred_usage_stored */
+	/* */);
+} *gss_mechanism;
+
+/*
+ * In the user space we use a wrapper structure to encompass the
+ * mechanism entry points.  The wrapper contain the mechanism
+ * entry points and other data which is only relevant to the gss-api
+ * layer.  In the kernel we use only the gss_config strucutre because
+ * the kernal does not cantain any of the extra gss-api specific data.
+ */
+typedef struct gss_mech_config {
+	char *kmodName;			/* kernel module name */
+	char *uLibName;			/* user library name */
+	char *mechNameStr;		/* mechanism string name */
+	char *optionStr;		/* optional mech parameters */
+	void *dl_handle;		/* RTLD object handle for the mech */
+	gss_OID mech_type;		/* mechanism oid */
+	gss_mechanism mech;		/* mechanism initialization struct */
+	struct gss_mech_config *next;	/* next element in the list */
+} *gss_mech_info;
+
+/********************************************************/
+/* Internal mechglue routines */
+
+int gssint_mechglue_init(void);
+void gssint_mechglue_fini(void);
+
+gss_mechanism gssint_get_mechanism (gss_OID);
+OM_uint32 gssint_get_mech_type (gss_OID, gss_buffer_t);
+char *gssint_get_kmodName(const gss_OID);
+char *gssint_get_modOptions(const gss_OID);
+OM_uint32 gssint_import_internal_name (OM_uint32 *, gss_OID, gss_union_name_t,
+				      gss_name_t *);
+OM_uint32 gssint_export_internal_name(OM_uint32 *, const gss_OID,
+	const gss_name_t, gss_buffer_t);
+OM_uint32 gssint_display_internal_name (OM_uint32 *, gss_OID, gss_name_t,
+				       gss_buffer_t, gss_OID *);
+OM_uint32 gssint_release_internal_name (OM_uint32 *, gss_OID, gss_name_t *);
+
+OM_uint32 gssint_convert_name_to_union_name
+	  (OM_uint32 *,		/* minor_status */
+	   gss_mechanism,	/* mech */
+	   gss_name_t,		/* internal_name */
+	   gss_name_t *		/* external_name */
+	   );
+gss_cred_id_t gssint_get_mechanism_cred
+	  (gss_union_cred_t,	/* union_cred */
+	   gss_OID		/* mech_type */
+	   );
+
+OM_uint32 gssint_create_copy_buffer(
+	const gss_buffer_t,	/* src buffer */
+	gss_buffer_t *,		/* destination buffer */
+	int			/* NULL terminate buffer ? */
+);
+
+OM_uint32 gssint_copy_oid_set(
+	OM_uint32 *,			/* minor_status */
+	const gss_OID_set_desc *,	/* oid set */
+	gss_OID_set *			/* new oid set */
+);
+
+gss_OID gss_find_mechanism_from_name_type (gss_OID); /* name_type */
+
+OM_uint32 gss_add_mech_name_type
+	   (OM_uint32 *,	/* minor_status */
+	    gss_OID,		/* name_type */
+	    gss_OID		/* mech */
+	       );
+
+/*
+ * Sun extensions to GSS-API v2
+ */
+
+OM_uint32
+gssint_mech_to_oid(
+	const char *mech,		/* mechanism string name */
+	gss_OID *oid			/* mechanism oid */
+);
+
+const char *
+gssint_oid_to_mech(
+	const gss_OID oid		/* mechanism oid */
+);
+
+OM_uint32
+gssint_get_mechanisms(
+	char *mechArray[],		/* array to populate with mechs */
+	int arrayLen			/* length of passed in array */
+);
+
+OM_uint32
+gss_store_cred(
+	OM_uint32 *,		/* minor_status */
+	const gss_cred_id_t,	/* input_cred_handle */
+	gss_cred_usage_t,	/* cred_usage */
+	const gss_OID,		/* desired_mech */
+	OM_uint32,		/* overwrite_cred */
+	OM_uint32,		/* default_cred */
+	gss_OID_set *,		/* elements_stored */
+	gss_cred_usage_t *	/* cred_usage_stored */
+);
+
+int
+gssint_get_der_length(
+	unsigned char **,	/* buf */
+	unsigned int,		/* buf_len */
+	unsigned int *		/* bytes */
+);
+
+unsigned int
+gssint_der_length_size(unsigned int /* len */);
+
+int
+gssint_put_der_length(
+	unsigned int,		/* length */
+	unsigned char **,	/* buf */
+	unsigned int		/* max_len */
+);
+
+#endif /* _GSS_MECHGLUEP_H */
diff --git a/krb5-1-6/src/lib/gssapi/mechglue/oid_ops.c b/krb5-1-6/src/lib/gssapi/mechglue/oid_ops.c
new file mode 100644
index 000000000..5c2ceb321
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/mechglue/oid_ops.c
@@ -0,0 +1,514 @@
+/* #pragma ident	"@(#)oid_ops.c	1.19	04/02/23 SMI" */
+/*
+ * lib/gssapi/generic/oid_ops.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <gssapi/gssapi_generic.h>
+#include <errno.h>
+#include <ctype.h>
+
+OM_uint32
+generic_gss_release_oid(minor_status, oid)
+    OM_uint32	*minor_status;
+    gss_OID	*oid;
+{
+    if (minor_status)
+	*minor_status = 0;
+
+    if (oid == NULL || *oid == GSS_C_NO_OID)
+	return(GSS_S_COMPLETE);
+
+    /*
+     * The V2 API says the following!
+     *
+     * gss_release_oid[()] will recognize any of the GSSAPI's own OID values,
+     * and will silently ignore attempts to free these OIDs; for other OIDs
+     * it will call the C free() routine for both the OID data and the
+     * descriptor.  This allows applications to freely mix their own heap-
+     * allocated OID values with OIDs returned by GSS-API.
+     */
+
+    /*
+     * We use the official OID definitions instead of the unofficial OID
+     * defintions. But we continue to support the unofficial OID
+     * gss_nt_service_name just in case if some gss applications use
+     * the old OID.
+     */
+
+    if ((*oid != GSS_C_NT_USER_NAME) &&
+	(*oid != GSS_C_NT_MACHINE_UID_NAME) &&
+	(*oid != GSS_C_NT_STRING_UID_NAME) &&
+	(*oid != GSS_C_NT_HOSTBASED_SERVICE) &&
+	(*oid != GSS_C_NT_ANONYMOUS) &&
+	(*oid != GSS_C_NT_EXPORT_NAME) &&
+	(*oid != gss_nt_service_name)) {
+	free((*oid)->elements);
+	free(*oid);
+    }
+    *oid = GSS_C_NO_OID;
+    return(GSS_S_COMPLETE);
+}
+
+OM_uint32
+generic_gss_copy_oid(minor_status, oid, new_oid)
+	OM_uint32	*minor_status;
+	const gss_OID_desc * const oid;
+	gss_OID		*new_oid;
+{
+	gss_OID		p;
+
+	*minor_status = 0;
+
+	p = (gss_OID) malloc(sizeof(gss_OID_desc));
+	if (!p) {
+		*minor_status = ENOMEM;
+		return GSS_S_FAILURE;
+	}
+	p->length = oid->length;
+	p->elements = malloc(p->length);
+	if (!p->elements) {
+		free(p);
+		return GSS_S_FAILURE;
+	}
+	memcpy(p->elements, oid->elements, p->length);
+	*new_oid = p;
+	return(GSS_S_COMPLETE);
+}
+
+
+OM_uint32
+generic_gss_create_empty_oid_set(minor_status, oid_set)
+    OM_uint32	*minor_status;
+    gss_OID_set	*oid_set;
+{
+    *minor_status = 0;
+
+    if ((*oid_set = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)))) {
+	memset(*oid_set, 0, sizeof(gss_OID_set_desc));
+	return(GSS_S_COMPLETE);
+    }
+    else {
+	*minor_status = ENOMEM;
+	return(GSS_S_FAILURE);
+    }
+}
+
+OM_uint32
+generic_gss_add_oid_set_member(minor_status, member_oid, oid_set)
+    OM_uint32	*minor_status;
+    const gss_OID_desc * const member_oid;
+    gss_OID_set	*oid_set;
+{
+    gss_OID	elist;
+    gss_OID	lastel;
+
+    *minor_status = 0;
+
+    if (member_oid == NULL || member_oid->length == 0 ||
+	member_oid->elements == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    elist = (*oid_set)->elements;
+    /* Get an enlarged copy of the array */
+    if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
+						  sizeof(gss_OID_desc)))) {
+	/* Copy in the old junk */
+	if (elist)
+	    memcpy((*oid_set)->elements,
+		   elist,
+		   ((*oid_set)->count * sizeof(gss_OID_desc)));
+
+	/* Duplicate the input element */
+	lastel = &(*oid_set)->elements[(*oid_set)->count];
+	if ((lastel->elements =
+	     (void *) malloc((size_t) member_oid->length))) {
+	    /* Success - copy elements */
+	    memcpy(lastel->elements, member_oid->elements,
+		   (size_t) member_oid->length);
+	    /* Set length */
+	    lastel->length = member_oid->length;
+
+	    /* Update count */
+	    (*oid_set)->count++;
+	    if (elist)
+		free(elist);
+	    *minor_status = 0;
+	    return(GSS_S_COMPLETE);
+	}
+	else
+	    free((*oid_set)->elements);
+    }
+    /* Failure - restore old contents of list */
+    (*oid_set)->elements = elist;
+    *minor_status = ENOMEM;
+    return(GSS_S_FAILURE);
+}
+
+OM_uint32
+generic_gss_test_oid_set_member(minor_status, member, set, present)
+    OM_uint32	*minor_status;
+    const gss_OID_desc * const member;
+    gss_OID_set	set;
+    int		*present;
+{
+    OM_uint32	i;
+    int		result;
+
+    *minor_status = 0;
+
+    if (member == NULL || set == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (present == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    result = 0;
+    for (i=0; i<set->count; i++) {
+	if ((set->elements[i].length == member->length) &&
+	    !memcmp(set->elements[i].elements,
+		    member->elements,
+		    (size_t) member->length)) {
+	    result = 1;
+	    break;
+	}
+    }
+    *present = result;
+    return(GSS_S_COMPLETE);
+}
+
+/*
+ * OID<->string routines.  These are uuuuugly.
+ */
+OM_uint32
+generic_gss_oid_to_str(minor_status, oid, oid_str)
+    OM_uint32		*minor_status;
+    const gss_OID_desc * const oid;
+    gss_buffer_t	oid_str;
+{
+    char		numstr[128];
+    OM_uint32		number;
+    int			numshift;
+    OM_uint32 string_length;
+    OM_uint32 i;
+    unsigned char	*cp;
+    char		*bp;
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (oid_str != GSS_C_NO_BUFFER) {
+	oid_str->length = 0;
+	oid_str->value = NULL;
+    }
+
+    if (oid == NULL || oid->length == 0 || oid->elements == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (oid_str == GSS_C_NO_BUFFER)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    /* Decoded according to krb5/gssapi_krb5.c */
+
+    /* First determine the size of the string */
+    string_length = 0;
+    number = 0;
+    numshift = 0;
+    cp = (unsigned char *) oid->elements;
+    number = (unsigned long) cp[0];
+    sprintf(numstr, "%lu ", (unsigned long)number/40);
+    string_length += strlen(numstr);
+    sprintf(numstr, "%lu ", (unsigned long)number%40);
+    string_length += strlen(numstr);
+    for (i=1; i<oid->length; i++) {
+	if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) {/* XXX */
+	    number = (number << 7) | (cp[i] & 0x7f);
+	    numshift += 7;
+	}
+	else {
+	    return(GSS_S_FAILURE);
+	}
+	if ((cp[i] & 0x80) == 0) {
+	    sprintf(numstr, "%lu ", (unsigned long)number);
+	    string_length += strlen(numstr);
+	    number = 0;
+	    numshift = 0;
+	}
+    }
+    /*
+     * If we get here, we've calculated the length of "n n n ... n ".  Add 4
+     * here for "{ " and "}\0".
+     */
+    string_length += 4;
+    if ((bp = (char *) malloc(string_length))) {
+	strcpy(bp, "{ ");
+	number = (OM_uint32) cp[0];
+	sprintf(numstr, "%lu ", (unsigned long)number/40);
+	strcat(bp, numstr);
+	sprintf(numstr, "%lu ", (unsigned long)number%40);
+	strcat(bp, numstr);
+	number = 0;
+	cp = (unsigned char *) oid->elements;
+	for (i=1; i<oid->length; i++) {
+	    number = (number << 7) | (cp[i] & 0x7f);
+	    if ((cp[i] & 0x80) == 0) {
+		sprintf(numstr, "%lu ", (unsigned long)number);
+		strcat(bp, numstr);
+		number = 0;
+	    }
+	}
+	strcat(bp, "}");
+	oid_str->length = strlen(bp)+1;
+	oid_str->value = (void *) bp;
+	return(GSS_S_COMPLETE);
+    }
+    *minor_status = ENOMEM;
+    return(GSS_S_FAILURE);
+}
+
+OM_uint32
+generic_gss_str_to_oid(minor_status, oid_str, oid)
+    OM_uint32		*minor_status;
+    gss_buffer_t	oid_str;
+    gss_OID		*oid;
+{
+    unsigned char	*cp, *bp, *startp;
+    int		brace;
+    long	numbuf;
+    long	onumbuf;
+    OM_uint32	nbytes;
+    int		index;
+    unsigned char *op;
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (oid != NULL)
+	*oid = GSS_C_NO_OID;
+
+    if (GSS_EMPTY_BUFFER(oid_str))
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (oid == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    brace = 0;
+    bp = oid_str->value;
+    cp = bp;
+    /* Skip over leading space */
+    while ((bp < &cp[oid_str->length]) && isspace(*bp))
+	bp++;
+    if (*bp == '{') {
+	brace = 1;
+	bp++;
+    }
+    while ((bp < &cp[oid_str->length]) && isspace(*bp))
+	bp++;
+    startp = bp;
+    nbytes = 0;
+
+    /*
+     * The first two numbers are chewed up by the first octet.
+     */
+    if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
+	*minor_status = EINVAL;
+	return(GSS_S_FAILURE);
+    }
+    while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+	bp++;
+    while ((bp < &cp[oid_str->length]) && isspace(*bp))
+	bp++;
+    if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
+	*minor_status = EINVAL;
+	return(GSS_S_FAILURE);
+    }
+    while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+	bp++;
+    while ((bp < &cp[oid_str->length]) &&
+	   (isspace(*bp) || *bp == '.'))
+	bp++;
+    nbytes++;
+    while (isdigit(*bp)) {
+	if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
+	    return(GSS_S_FAILURE);
+	}
+	while (numbuf) {
+	    nbytes++;
+	    numbuf >>= 7;
+	}
+	while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+	    bp++;
+	while ((bp < &cp[oid_str->length]) &&
+	       (isspace(*bp) || *bp == '.'))
+	    bp++;
+    }
+    if (brace && (*bp != '}')) {
+	return(GSS_S_FAILURE);
+    }
+
+    /*
+     * Phew!  We've come this far, so the syntax is good.
+     */
+    if ((*oid = (gss_OID) malloc(sizeof(gss_OID_desc)))) {
+	if (((*oid)->elements = (void *) malloc(nbytes))) {
+	    (*oid)->length = nbytes;
+	    op = (unsigned char *) (*oid)->elements;
+	    bp = startp;
+	    (void) sscanf((char *)bp, "%ld", &numbuf);
+	    while (isdigit(*bp))
+		bp++;
+	    while (isspace(*bp) || *bp == '.')
+		bp++;
+	    onumbuf = 40*numbuf;
+	    (void) sscanf((char *)bp, "%ld", &numbuf);
+	    onumbuf += numbuf;
+	    *op = (unsigned char) onumbuf;
+	    op++;
+	    while (isdigit(*bp))
+		bp++;
+	    while (isspace(*bp) || *bp == '.')
+		bp++;
+	    while (isdigit(*bp)) {
+		(void) sscanf((char *)bp, "%ld", &numbuf);
+		nbytes = 0;
+		/* Have to fill in the bytes msb-first */
+		onumbuf = numbuf;
+		while (numbuf) {
+		    nbytes++;
+		    numbuf >>= 7;
+		}
+		numbuf = onumbuf;
+		op += nbytes;
+		index = -1;
+		while (numbuf) {
+		    op[index] = (unsigned char) numbuf & 0x7f;
+		    if (index != -1)
+			op[index] |= 0x80;
+		    index--;
+		    numbuf >>= 7;
+		}
+		while (isdigit(*bp))
+		    bp++;
+		while (isspace(*bp) || *bp == '.')
+		    bp++;
+	    }
+	    return(GSS_S_COMPLETE);
+	}
+	else {
+	    free(*oid);
+	    *oid = GSS_C_NO_OID;
+	}
+    }
+    return(GSS_S_FAILURE);
+}
+
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+OM_uint32
+gssint_copy_oid_set(
+    OM_uint32 *minor_status,
+    const gss_OID_set_desc * const oidset,
+    gss_OID_set *new_oidset
+    )
+{
+    gss_OID_set_desc *copy;
+    OM_uint32 minor = 0;
+    OM_uint32 major = GSS_S_COMPLETE;
+    OM_uint32 index;
+
+    if (minor_status != NULL)
+	*minor_status = 0;
+
+    if (new_oidset != NULL)
+	*new_oidset = GSS_C_NO_OID_SET;
+
+    if (oidset == GSS_C_NO_OID_SET)
+	return (GSS_S_CALL_INACCESSIBLE_READ);
+
+    if (new_oidset == NULL)
+	return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+    if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) {
+	major = GSS_S_FAILURE;
+	goto done;
+    }
+
+    if ((copy->elements = (gss_OID_desc *)
+	 calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
+	major = GSS_S_FAILURE;
+	goto done;
+    }
+    copy->count = oidset->count;
+
+    for (index = 0; index < copy->count; index++) {
+	gss_OID_desc *out = ©->elements[index];
+	gss_OID_desc *in = &oidset->elements[index];
+
+	if ((out->elements = (void *) malloc(in->length)) == NULL) {
+	    major = GSS_S_FAILURE;
+	    goto done;
+	}
+	(void) memcpy(out->elements, in->elements, in->length);
+	out->length = in->length;
+    }
+
+    *new_oidset = copy;
+done:
+    if (major != GSS_S_COMPLETE) {
+	(void) gss_release_oid_set(&minor, ©);
+    }
+
+    return (major);
+}
diff --git a/krb5-1-6/src/lib/gssapi/spnego/Makefile.in b/krb5-1-6/src/lib/gssapi/spnego/Makefile.in
new file mode 100644
index 000000000..01ca39adf
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/spnego/Makefile.in
@@ -0,0 +1,43 @@
+thisconfigdir=../../..
+myfulldir=lib/gssapi/spnego
+mydir=lib/gssapi/spnego
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic -I../mechglue -I$(srcdir)/../mechglue
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=spnego
+##DOS##OBJFILE = ..\$(OUTPRE)spnego.lst
+
+##DOS##DLL_EXP_TYPE=GSS
+
+SRCS = $(srcdir)/spnego_mech.c
+
+OBJS = $(OUTPRE)spnego_mech.$(OBJEXT)
+
+STLIBOBJS = spnego_mech.o
+
+all-unix:: all-libobjs
+
+##DOS##LIBOBJS = $(OBJS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+spnego_mech.so spnego_mech.po $(OUTPRE)spnego_mech.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h $(srcdir)/../generic/gssapiP_generic.h \
+  $(srcdir)/../generic/gssapi_generic.h $(srcdir)/../mechglue/mechglue.h \
+  $(srcdir)/../mechglue/mglueP.h ../generic/gssapi_err_generic.h \
+  gssapiP_spnego.h spnego_mech.c
diff --git a/krb5-1-6/src/lib/gssapi/spnego/gssapiP_spnego.h b/krb5-1-6/src/lib/gssapi/spnego/gssapiP_spnego.h
new file mode 100644
index 000000000..1c8fd7a7b
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/spnego/gssapiP_spnego.h
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_GSSAPIP_SPNEGO_H_
+#define	_GSSAPIP_SPNEGO_H_
+
+/* #pragma ident	"@(#)gssapiP_spnego.h	1.3	03/09/18 SMI" */
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <gssapi/gssapi.h>
+#include <syslog.h>
+
+#define	SEC_CONTEXT_TOKEN 1
+#define	SPNEGO_SIZE_OF_INT 4
+
+#define	ACCEPT_COMPLETE 0
+#define	ACCEPT_INCOMPLETE 1
+#define	REJECT 2
+#define REQUEST_MIC 3
+#define	ACCEPT_DEFECTIVE_TOKEN 0xffffffffUL
+
+/*
+ * constants for der encoding/decoding routines.
+ */
+
+#define	MECH_OID		0x06
+#define	OCTET_STRING		0x04
+#define	CONTEXT			0xa0
+#define	SEQUENCE		0x30
+#define	SEQUENCE_OF		0x30
+#define	BIT_STRING		0x03
+#define	BIT_STRING_LENGTH	0x02
+#define	BIT_STRING_PADDING	0x01
+#define	ENUMERATED		0x0a
+#define	ENUMERATION_LENGTH	1
+#define	HEADER_ID		0x60
+
+/*
+ * SPNEGO specific error codes (minor status codes)
+ */
+#define	ERR_SPNEGO_NO_MECHS_AVAILABLE		0x20000001
+#define	ERR_SPNEGO_NO_CREDS_ACQUIRED		0x20000002
+#define	ERR_SPNEGO_NO_MECH_FROM_ACCEPTOR	0x20000003
+#define	ERR_SPNEGO_NEGOTIATION_FAILED		0x20000004
+#define	ERR_SPNEGO_NO_TOKEN_FROM_ACCEPTOR	0x20000005
+
+/*
+ * send_token_flag is used to indicate in later steps what type
+ * of token, if any should be sent or processed.
+ * NO_TOKEN_SEND = no token should be sent
+ * INIT_TOKEN_SEND = initial token will be sent
+ * CONT_TOKEN_SEND = continuing tokens to be sent
+ * CHECK_MIC = no token to be sent, but have a MIC to check.
+ * ERROR_TOKEN_SEND = error token from peer needs to be sent.
+ */
+
+typedef	enum {NO_TOKEN_SEND, INIT_TOKEN_SEND, CONT_TOKEN_SEND,
+		CHECK_MIC, ERROR_TOKEN_SEND} send_token_flag;
+
+/*
+ * The Mech OID:
+ * { iso(1) org(3) dod(6) internet(1) security(5)
+ *  mechanism(5) spnego(2) }
+ */
+
+#define	SPNEGO_OID_LENGTH 6
+#define	SPNEGO_OID "\053\006\001\005\005\002"
+
+typedef void *spnego_token_t;
+
+/* spnego name structure for internal representation. */
+typedef struct {
+	gss_OID type;
+	gss_buffer_t buffer;
+	gss_OID	mech_type;
+	gss_name_t	mech_name;
+} spnego_name_desc, *spnego_name_t;
+
+/* Structure for context handle */
+typedef struct {
+	OM_uint32	magic_num;
+	gss_buffer_desc DER_mechTypes;
+	gss_OID internal_mech;
+	gss_ctx_id_t ctx_handle;
+	char  *optionStr;
+	gss_cred_id_t default_cred;
+	int mic_reqd;
+	int mic_sent;
+	int mic_rcvd;
+	int firstpass;
+	int mech_complete;
+	int nego_done;
+	OM_uint32 ctx_flags;
+	gss_name_t internal_name;
+	gss_OID actual_mech;
+} spnego_gss_ctx_id_rec, *spnego_gss_ctx_id_t;
+
+/*
+ * The magic number must be less than a standard pagesize
+ * to avoid a possible collision with a real address.
+ */
+#define	SPNEGO_MAGIC_ID  0x00000fed
+
+/* SPNEGO oid structure */
+static const gss_OID_desc spnego_oids[] = {
+	{SPNEGO_OID_LENGTH, SPNEGO_OID},
+};
+
+const gss_OID_desc * const gss_mech_spnego = spnego_oids+0;
+static const gss_OID_set_desc spnego_oidsets[] = {
+	{1, (gss_OID) spnego_oids+0},
+};
+const gss_OID_set_desc * const gss_mech_set_spnego = spnego_oidsets+0;
+
+#ifdef DEBUG
+#define	dsyslog(a) syslog(LOG_DEBUG, a)
+#else
+#define	dsyslog(a)
+#define	SPNEGO_STATIC
+#endif	/* DEBUG */
+
+/*
+ * declarations of internal name mechanism functions
+ */
+
+OM_uint32 spnego_gss_acquire_cred
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	gss_name_t,		/* desired_name */
+	OM_uint32,		/* time_req */
+	gss_OID_set,		/* desired_mechs */
+	gss_cred_usage_t,	/* cred_usage */
+	gss_cred_id_t *,	/* output_cred_handle */
+	gss_OID_set *,		/* actual_mechs */
+	OM_uint32 *		/* time_rec */
+);
+
+OM_uint32 spnego_gss_release_cred
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	/* CSTYLED */
+	gss_cred_id_t	*	/* cred_handle */
+);
+
+OM_uint32 spnego_gss_init_sec_context
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	gss_cred_id_t,		/* claimant_cred_handle */
+	gss_ctx_id_t *,		/* context_handle */
+	gss_name_t,		/* target_name */
+	gss_OID,		/* mech_type */
+	OM_uint32,		/* req_flags */
+	OM_uint32,		/* time_req */
+	gss_channel_bindings_t, /* input_chan_bindings */
+	gss_buffer_t,		/* input_token */
+	gss_OID *,		/* actual_mech_type */
+	gss_buffer_t,		/* output_token */
+	OM_uint32 *,		/* ret_flags */
+	OM_uint32 *		/* time_rec */
+);
+
+OM_uint32 spnego_gss_accept_sec_context
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	gss_ctx_id_t *,		/* context_handle */
+	gss_cred_id_t,		/* verifier_cred_handle */
+	gss_buffer_t,		/* input_token_buffer */
+	gss_channel_bindings_t, /* input_chan_bindings */
+	gss_name_t *,		/* src_name */
+	gss_OID *,		/* mech_type */
+	gss_buffer_t,		/* output_token */
+	OM_uint32 *,		/* ret_flags */
+	OM_uint32 *,		/* time_rec */
+	/* CSTYLED */
+	gss_cred_id_t *		/* delegated_cred_handle */
+);
+
+OM_uint32 spnego_gss_display_name
+(
+	void *,
+	OM_uint32 *,		/* minor_status */
+	gss_name_t,		/*  input_name */
+	gss_buffer_t,		/*  output_name_buffer */
+	gss_OID *		/* output_name_type */
+);
+
+OM_uint32 spnego_gss_display_status
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	OM_uint32,		/* status_value */
+	int,			/* status_type */
+	gss_OID,		/* mech_type */
+	OM_uint32 *,		/* message_context */
+	gss_buffer_t		/* status_string */
+);
+
+OM_uint32 spnego_gss_import_name
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	gss_buffer_t,		/* input_name_buffer */
+	gss_OID,		/* input_name_type */
+	/* CSTYLED */
+	gss_name_t *		/* output_name */
+);
+
+OM_uint32 spnego_gss_release_name
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	/* CSTYLED */
+	gss_name_t *		/* input_name */
+);
+
+OM_uint32 spnego_gss_inquire_names_for_mech
+(
+	void *,			/* spnego context */
+	OM_uint32 *,		/* minor_status */
+	gss_OID,		/* mechanism */
+	gss_OID_set *		/* name_types */
+);
+
+OM_uint32 spnego_gss_unseal
+(
+	void *context,
+	OM_uint32 *minor_status,
+	gss_ctx_id_t context_handle,
+	gss_buffer_t input_message_buffer,
+	gss_buffer_t output_message_buffer,
+	int *conf_state,
+	int *qop_state
+);
+
+OM_uint32 spnego_gss_seal
+(
+	void *context,
+	OM_uint32 *minor_status,
+	gss_ctx_id_t context_handle,
+	int conf_req_flag,
+	int qop_req,
+	gss_buffer_t input_message_buffer,
+	int *conf_state,
+	gss_buffer_t output_message_buffer
+);
+
+OM_uint32 spnego_gss_process_context_token
+(
+	void *context,
+	OM_uint32	*minor_status,
+	const gss_ctx_id_t context_handle,
+	const gss_buffer_t token_buffer
+);
+
+OM_uint32 spnego_gss_delete_sec_context
+(
+	void *context,
+	OM_uint32 *minor_status,
+	gss_ctx_id_t *context_handle,
+	gss_buffer_t output_token
+);
+
+OM_uint32 spnego_gss_context_time
+(
+	void *context,
+	OM_uint32	*minor_status,
+	const gss_ctx_id_t context_handle,
+	OM_uint32	*time_rec
+);
+
+OM_uint32 spnego_gss_export_sec_context
+(
+	void *context,
+	OM_uint32	*minor_status,
+	gss_ctx_id_t	*context_handle,
+	gss_buffer_t	interprocess_token
+);
+
+OM_uint32 spnego_gss_import_sec_context
+(
+	void			*context,
+	OM_uint32		*minor_status,
+	const gss_buffer_t	interprocess_token,
+	gss_ctx_id_t		*context_handle
+);
+
+OM_uint32 spnego_gss_inquire_context
+(
+	void		*context,
+	OM_uint32	*minor_status,
+	const gss_ctx_id_t context_handle,
+	gss_name_t	*src_name,
+	gss_name_t	*targ_name,
+	OM_uint32	*lifetime_rec,
+	gss_OID		*mech_type,
+	OM_uint32	*ctx_flags,
+	int		*locally_initiated,
+	int		*open
+);
+
+OM_uint32 spnego_gss_wrap_size_limit
+(
+	void		*context,
+	OM_uint32	*minor_status,
+	const gss_ctx_id_t context_handle,
+	int		conf_req_flag,
+	gss_qop_t	qop_req,
+	OM_uint32	req_output_size,
+	OM_uint32	*max_input_size
+);
+
+OM_uint32 spnego_gss_sign
+(
+	void *context,
+	OM_uint32 *minor_status,
+	const gss_ctx_id_t context_handle,
+	int  qop_req,
+	const gss_buffer_t message_buffer,
+	gss_buffer_t message_token
+);
+
+OM_uint32 spnego_gss_verify
+(
+	void *context,
+	OM_uint32 *minor_status,
+	const gss_ctx_id_t context_handle,
+	const gss_buffer_t msg_buffer,
+	const gss_buffer_t token_buffer,
+	int *qop_state
+);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _GSSAPIP_SPNEGO_H_ */
diff --git a/krb5-1-6/src/lib/gssapi/spnego/spnego_mech.c b/krb5-1-6/src/lib/gssapi/spnego/spnego_mech.c
new file mode 100644
index 000000000..832abe6ec
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi/spnego/spnego_mech.c
@@ -0,0 +1,2854 @@
+/*
+ * Copyright (C) 2006 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * A module that implements the spnego security mechanism.
+ * It is used to negotiate the security mechanism between
+ * peers using the GSS-API.
+ *
+ */
+
+/* #pragma ident	"@(#)spnego_mech.c	1.7	04/09/28 SMI" */
+
+#include	<assert.h>
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<string.h>
+#include	<k5-int.h>
+#include	<krb5.h>
+#include	<mglueP.h>
+#include	"gssapiP_spnego.h"
+#include	<gssapi_err_generic.h>
+
+#undef g_token_size
+#undef g_verify_token_header
+#undef g_make_token_header
+
+#define HARD_ERROR(v) ((v) != GSS_S_COMPLETE && (v) != GSS_S_CONTINUE_NEEDED)
+typedef const gss_OID_desc *gss_OID_const;
+
+/* der routines defined in libgss */
+extern unsigned int gssint_der_length_size(OM_uint32);
+extern int gssint_get_der_length(unsigned char **, OM_uint32, OM_uint32*);
+extern int gssint_put_der_length(OM_uint32, unsigned char **, OM_uint32);
+
+
+/* private routines for spnego_mechanism */
+static spnego_token_t make_spnego_token(char *);
+static gss_buffer_desc make_err_msg(char *);
+static int g_token_size(gss_OID_const, unsigned int);
+static int g_make_token_header(gss_OID_const, unsigned int,
+			       unsigned char **, unsigned int);
+static int g_verify_token_header(gss_OID_const, unsigned int *,
+				 unsigned char **,
+				 int, unsigned int);
+static int g_verify_neg_token_init(unsigned char **, unsigned int);
+static gss_OID get_mech_oid(OM_uint32 *, unsigned char **, size_t);
+static gss_buffer_t get_input_token(unsigned char **, unsigned int);
+static gss_OID_set get_mech_set(OM_uint32 *, unsigned char **, unsigned int);
+static OM_uint32 get_req_flags(unsigned char **, OM_uint32, OM_uint32 *);
+static OM_uint32 get_available_mechs(OM_uint32 *, gss_name_t,
+	gss_cred_usage_t, gss_cred_id_t *, gss_OID_set *);
+static void release_spnego_ctx(spnego_gss_ctx_id_t *);
+static void check_spnego_options(spnego_gss_ctx_id_t);
+static spnego_gss_ctx_id_t create_spnego_ctx(void);
+static int put_req_flags(unsigned char **, OM_uint32, unsigned int);
+static int put_mech_set(gss_OID_set mechSet, gss_buffer_t buf);
+static int put_input_token(unsigned char **, gss_buffer_t, unsigned int);
+static int put_mech_oid(unsigned char **, gss_OID_const, unsigned int);
+static int put_negResult(unsigned char **, OM_uint32, unsigned int);
+
+static OM_uint32
+process_mic(OM_uint32 *, gss_buffer_t, spnego_gss_ctx_id_t,
+	    gss_buffer_t *, OM_uint32 *, send_token_flag *);
+static OM_uint32
+handle_mic(OM_uint32 *, gss_buffer_t, int, spnego_gss_ctx_id_t,
+	   gss_buffer_t *, OM_uint32 *, send_token_flag *);
+
+static OM_uint32
+init_ctx_new(OM_uint32 *, gss_cred_id_t, gss_ctx_id_t *,
+	     gss_OID_set *, send_token_flag *);
+static OM_uint32
+init_ctx_nego(OM_uint32 *, spnego_gss_ctx_id_t, OM_uint32, gss_OID,
+	      gss_buffer_t *, gss_buffer_t *,
+	      OM_uint32 *, send_token_flag *);
+static OM_uint32
+init_ctx_cont(OM_uint32 *, gss_ctx_id_t *, gss_buffer_t,
+	      gss_buffer_t *, gss_buffer_t *,
+	      OM_uint32 *, send_token_flag *);
+static OM_uint32
+init_ctx_reselect(OM_uint32 *, spnego_gss_ctx_id_t, OM_uint32,
+		  gss_OID, gss_buffer_t *, gss_buffer_t *,
+		  OM_uint32 *, send_token_flag *);
+static OM_uint32
+init_ctx_call_init(OM_uint32 *, spnego_gss_ctx_id_t, gss_cred_id_t,
+		   gss_name_t, OM_uint32, OM_uint32, gss_buffer_t,
+		   gss_OID *, gss_buffer_t, OM_uint32 *, OM_uint32 *,
+		   OM_uint32 *, send_token_flag *);
+
+static OM_uint32
+acc_ctx_new(OM_uint32 *, gss_buffer_t, gss_ctx_id_t *,
+	    gss_cred_id_t, gss_buffer_t *,
+	    gss_buffer_t *, OM_uint32 *, send_token_flag *);
+static OM_uint32
+acc_ctx_cont(OM_uint32 *, gss_buffer_t, gss_ctx_id_t *,
+	     gss_buffer_t *, gss_buffer_t *,
+	     OM_uint32 *, send_token_flag *);
+static OM_uint32
+acc_ctx_vfy_oid(OM_uint32 *, spnego_gss_ctx_id_t, gss_OID,
+		OM_uint32 *, send_token_flag *);
+static OM_uint32
+acc_ctx_call_acc(OM_uint32 *, spnego_gss_ctx_id_t, gss_cred_id_t,
+		 gss_buffer_t, gss_OID *, gss_buffer_t,
+		 OM_uint32 *, OM_uint32 *, gss_cred_id_t *,
+		 OM_uint32 *, send_token_flag *);
+
+static gss_OID
+negotiate_mech_type(OM_uint32 *, gss_OID_set, gss_OID_set,
+		OM_uint32 *);
+static int
+g_get_tag_and_length(unsigned char **, int, unsigned int, unsigned int *);
+
+static int
+make_spnego_tokenInit_msg(spnego_gss_ctx_id_t, gss_buffer_t,
+			OM_uint32, gss_buffer_t, send_token_flag,
+			gss_buffer_t);
+static int
+make_spnego_tokenTarg_msg(OM_uint32, gss_OID, gss_buffer_t,
+			gss_buffer_t, send_token_flag,
+			gss_buffer_t);
+
+static OM_uint32
+get_negTokenInit(OM_uint32 *, gss_buffer_t, gss_buffer_t,
+		 gss_OID_set *, OM_uint32 *, gss_buffer_t *,
+		 gss_buffer_t *);
+static OM_uint32
+get_negTokenResp(OM_uint32 *, unsigned char *, unsigned int,
+		 OM_uint32 *, gss_OID *, gss_buffer_t *, gss_buffer_t *);
+
+/*
+ * The Mech OID for SPNEGO:
+ * { iso(1) org(3) dod(6) internet(1) security(5)
+ *  mechanism(5) spnego(2) }
+ */
+static struct gss_config spnego_mechanism =
+{
+	400, "spnego",
+	{SPNEGO_OID_LENGTH, SPNEGO_OID},
+	NULL,
+	spnego_gss_acquire_cred,
+	spnego_gss_release_cred,
+	spnego_gss_init_sec_context,
+	spnego_gss_accept_sec_context,
+	NULL,				/* gss_process_context_token */
+	spnego_gss_delete_sec_context,	/* gss_delete_sec_context */
+	spnego_gss_context_time,	/* gss_context_time */
+	spnego_gss_sign,		/* gss_sign */
+	spnego_gss_verify,		/* gss_verify */
+	spnego_gss_seal,		/* gss_seal */
+	spnego_gss_unseal,		/* gss_unseal */
+	spnego_gss_display_status,
+	NULL,				/* gss_indicate_mechs */
+	NULL,				/* gss_compare_name */
+	spnego_gss_display_name,
+	spnego_gss_import_name,
+	spnego_gss_release_name,
+	NULL,				/* gss_inquire_cred */
+	NULL,				/* gss_add_cred */
+	spnego_gss_export_sec_context,	/* gss_export_sec_context */
+	spnego_gss_import_sec_context,	/* gss_import_sec_context */
+	NULL, 				/* gss_inquire_cred_by_mech */
+	spnego_gss_inquire_names_for_mech,
+	spnego_gss_inquire_context,	/* gss_inquire_context */
+	NULL,				/* gss_internal_release_oid */
+	spnego_gss_wrap_size_limit,	/* gss_wrap_size_limit */
+	NULL,				/* gss_export_name */
+	NULL,				/* gss_store_cred */
+};
+
+static gss_mechanism spnego_mech_configs[] = {
+	&spnego_mechanism, NULL
+};
+
+#if 1
+#define gssint_get_mech_configs spnego_gss_get_mech_configs
+#endif
+
+gss_mechanism *
+gssint_get_mech_configs(void)
+{
+	return spnego_mech_configs;
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_acquire_cred(void *ctx,
+			OM_uint32 *minor_status,
+			gss_name_t desired_name,
+			OM_uint32 time_req,
+			gss_OID_set desired_mechs,
+			gss_cred_usage_t cred_usage,
+			gss_cred_id_t *output_cred_handle,
+			gss_OID_set *actual_mechs,
+			OM_uint32 *time_rec)
+{
+	OM_uint32 status;
+	gss_OID_set amechs;
+	dsyslog("Entering spnego_gss_acquire_cred\n");
+
+	if (actual_mechs)
+		*actual_mechs = NULL;
+
+	if (time_rec)
+		*time_rec = 0;
+
+	/*
+	 * If the user did not specify a list of mechs,
+	 * use get_available_mechs to collect a list of
+	 * mechs for which creds are available.
+	 */
+	if (desired_mechs == GSS_C_NULL_OID_SET) {
+		status = get_available_mechs(minor_status,
+				desired_name, cred_usage,
+				output_cred_handle, &amechs);
+	} else {
+		/*
+		 * The caller gave a specific list of mechanisms,
+		 * so just get whatever creds are available.
+		 * gss_acquire_creds will return the subset of mechs for
+		 * which the given 'output_cred_handle' is valid.
+		 */
+		status = gss_acquire_cred(minor_status,
+				desired_name, time_req,
+				desired_mechs, cred_usage,
+				output_cred_handle, &amechs,
+				time_rec);
+	}
+
+	if (actual_mechs && amechs != GSS_C_NULL_OID_SET) {
+		(void) gssint_copy_oid_set(minor_status, amechs, actual_mechs);
+	}
+	(void) gss_release_oid_set(minor_status, &amechs);
+
+	dsyslog("Leaving spnego_gss_acquire_cred\n");
+	return (status);
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_release_cred(void *ctx,
+			OM_uint32 *minor_status,
+			gss_cred_id_t *cred_handle)
+{
+	OM_uint32 status;
+
+	dsyslog("Entering spnego_gss_release_cred\n");
+
+	if (minor_status == NULL || cred_handle == NULL)
+		return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+	*minor_status = 0;
+
+	if (*cred_handle == GSS_C_NO_CREDENTIAL)
+		return (GSS_S_COMPLETE);
+
+	status = gss_release_cred(minor_status, cred_handle);
+
+	dsyslog("Leaving spnego_gss_release_cred\n");
+	return (status);
+}
+
+static void
+check_spnego_options(spnego_gss_ctx_id_t spnego_ctx)
+{
+	spnego_ctx->optionStr = gssint_get_modOptions(
+		(const gss_OID)&spnego_oids[0]);
+}
+
+static spnego_gss_ctx_id_t
+create_spnego_ctx(void)
+{
+	spnego_gss_ctx_id_t spnego_ctx = NULL;
+	spnego_ctx = (spnego_gss_ctx_id_t)
+		malloc(sizeof (spnego_gss_ctx_id_rec));
+
+	if (spnego_ctx == NULL) {
+		return (NULL);
+	}
+
+	spnego_ctx->magic_num = SPNEGO_MAGIC_ID;
+	spnego_ctx->ctx_handle = GSS_C_NO_CONTEXT;
+	spnego_ctx->internal_mech = NULL;
+	spnego_ctx->optionStr = NULL;
+	spnego_ctx->DER_mechTypes.length = 0;
+	spnego_ctx->DER_mechTypes.value = NULL;
+	spnego_ctx->default_cred = GSS_C_NO_CREDENTIAL;
+	spnego_ctx->mic_reqd = 0;
+	spnego_ctx->mic_sent = 0;
+	spnego_ctx->mic_rcvd = 0;
+	spnego_ctx->mech_complete = 0;
+	spnego_ctx->nego_done = 0;
+	spnego_ctx->internal_name = GSS_C_NO_NAME;
+	spnego_ctx->actual_mech = GSS_C_NO_OID;
+
+	check_spnego_options(spnego_ctx);
+
+	return (spnego_ctx);
+}
+
+/*
+ * Both initiator and acceptor call here to verify and/or create
+ * mechListMIC, and to consistency-check the MIC state.
+ */
+static OM_uint32
+handle_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
+	   int send_mechtok, spnego_gss_ctx_id_t sc,
+	   gss_buffer_t *mic_out,
+	   OM_uint32 *negState, send_token_flag *tokflag)
+{
+	OM_uint32 ret;
+
+	ret = GSS_S_FAILURE;
+	*mic_out = GSS_C_NO_BUFFER;
+	if (mic_in != GSS_C_NO_BUFFER) {
+		if (sc->mic_rcvd) {
+			/* Reject MIC if we've already received a MIC. */
+			*negState = REJECT;
+			*tokflag = ERROR_TOKEN_SEND;
+			return GSS_S_DEFECTIVE_TOKEN;
+		}
+	} else if (sc->mic_reqd && !send_mechtok) {
+		/*
+		 * If the peer sends the final mechanism token, it
+		 * must send the MIC with that token if the
+		 * negotiation requires MICs.
+		 */
+		*negState = REJECT;
+		*tokflag = ERROR_TOKEN_SEND;
+		return GSS_S_DEFECTIVE_TOKEN;
+	}
+	ret = process_mic(minor_status, mic_in, sc, mic_out,
+			  negState, tokflag);
+	if (ret != GSS_S_COMPLETE) {
+		return ret;
+	}
+	if (sc->mic_reqd) {
+		assert(sc->mic_sent || sc->mic_rcvd);
+	}
+	if (sc->mic_sent && sc->mic_rcvd) {
+		ret = GSS_S_COMPLETE;
+		*negState = ACCEPT_COMPLETE;
+		if (*mic_out == GSS_C_NO_BUFFER) {
+			/*
+			 * We sent a MIC on the previous pass; we
+			 * shouldn't be sending a mechanism token.
+			 */
+			assert(!send_mechtok);
+			*tokflag = NO_TOKEN_SEND;
+		} else {
+			*tokflag = CONT_TOKEN_SEND;
+		}
+	} else if (sc->mic_reqd) {
+		*negState = ACCEPT_INCOMPLETE;
+		ret = GSS_S_CONTINUE_NEEDED;
+	} else if (*negState == ACCEPT_COMPLETE) {
+		ret = GSS_S_COMPLETE;
+	} else {
+		ret = GSS_S_CONTINUE_NEEDED;
+	}
+	return ret;
+}
+
+/*
+ * Perform the actual verification and/or generation of mechListMIC.
+ */
+static OM_uint32
+process_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
+	    spnego_gss_ctx_id_t sc, gss_buffer_t *mic_out,
+	    OM_uint32 *negState, send_token_flag *tokflag)
+{
+	OM_uint32 ret, tmpmin;
+	gss_qop_t qop_state;
+	gss_buffer_desc tmpmic = GSS_C_EMPTY_BUFFER;
+
+	ret = GSS_S_FAILURE;
+	if (mic_in != GSS_C_NO_BUFFER) {
+		ret = gss_verify_mic(minor_status, sc->ctx_handle,
+				     &sc->DER_mechTypes,
+				     mic_in, &qop_state);
+		if (ret != GSS_S_COMPLETE) {
+			*negState = REJECT;
+			*tokflag = ERROR_TOKEN_SEND;
+			return ret;
+		}
+		/* If we got a MIC, we must send a MIC. */
+		sc->mic_reqd = 1;
+		sc->mic_rcvd = 1;
+	}
+	if (sc->mic_reqd && !sc->mic_sent) {
+		ret = gss_get_mic(minor_status, sc->ctx_handle,
+				  GSS_C_QOP_DEFAULT,
+				  &sc->DER_mechTypes,
+				  &tmpmic);
+		if (ret != GSS_S_COMPLETE) {
+			gss_release_buffer(&tmpmin, &tmpmic);
+			*tokflag = NO_TOKEN_SEND;
+			return ret;
+		}
+		*mic_out = malloc(sizeof(gss_buffer_desc));
+		if (*mic_out == GSS_C_NO_BUFFER) {
+			gss_release_buffer(&tmpmin, &tmpmic);
+			*tokflag = NO_TOKEN_SEND;
+			return GSS_S_FAILURE;
+		}
+		**mic_out = tmpmic;
+		sc->mic_sent = 1;
+	}
+	return GSS_S_COMPLETE;
+}
+
+/*
+ * Initial call to spnego_gss_init_sec_context().
+ */
+static OM_uint32
+init_ctx_new(OM_uint32 *minor_status,
+	     gss_cred_id_t cred,
+	     gss_ctx_id_t *ctx,
+	     gss_OID_set *mechSet,
+	     send_token_flag *tokflag)
+{
+	OM_uint32 ret, tmpmin;
+	gss_cred_id_t creds = GSS_C_NO_CREDENTIAL;
+	spnego_gss_ctx_id_t sc = NULL;
+
+	/* determine negotiation mech set */
+	if (cred == GSS_C_NO_CREDENTIAL) {
+		ret = get_available_mechs(minor_status, GSS_C_NO_NAME,
+					  GSS_C_INITIATE, &creds, mechSet);
+		gss_release_cred(&tmpmin, &creds);
+	} else {
+		/*
+		 * Use the list of mechs included in the cred that we
+		 * were given.
+		 */
+		ret = gss_inquire_cred(minor_status, cred,
+				       NULL, NULL, NULL, mechSet);
+	}
+	if (ret != GSS_S_COMPLETE)
+		return ret;
+
+	sc = create_spnego_ctx();
+	if (sc == NULL)
+		return GSS_S_FAILURE;
+
+	/*
+	 * need to pull the first mech from mechSet to do first
+	 * gss_init_sec_context()
+	 */
+	ret = generic_gss_copy_oid(minor_status, (*mechSet)->elements,
+				   &sc->internal_mech);
+	if (ret != GSS_S_COMPLETE)
+		goto cleanup;
+
+	if (put_mech_set(*mechSet, &sc->DER_mechTypes) < 0) {
+		generic_gss_release_oid(&tmpmin, &sc->internal_mech);
+		ret = GSS_S_FAILURE;
+		goto cleanup;
+	}
+	/*
+	 * The actual context is not yet determined, set the output
+	 * context handle to refer to the spnego context itself.
+	 */
+	sc->ctx_handle = GSS_C_NO_CONTEXT;
+	*ctx = (gss_ctx_id_t)sc;
+	*tokflag = INIT_TOKEN_SEND;
+	ret = GSS_S_CONTINUE_NEEDED;
+
+cleanup:
+	gss_release_oid_set(&tmpmin, mechSet);
+	return ret;
+}
+
+/*
+ * Called by second and later calls to spnego_gss_init_sec_context()
+ * to decode reply and update state.
+ */
+static OM_uint32
+init_ctx_cont(OM_uint32 *minor_status, gss_ctx_id_t *ctx, gss_buffer_t buf,
+	      gss_buffer_t *responseToken, gss_buffer_t *mechListMIC,
+	      OM_uint32 *negState, send_token_flag *tokflag)
+{
+	OM_uint32 ret, tmpmin, acc_negState;
+	unsigned char *ptr;
+	spnego_gss_ctx_id_t sc;
+	gss_OID supportedMech = GSS_C_NO_OID;
+
+	sc = (spnego_gss_ctx_id_t)*ctx;
+	*negState = REJECT;
+	*tokflag = ERROR_TOKEN_SEND;
+
+	ptr = buf->value;
+	ret = get_negTokenResp(minor_status, ptr, buf->length,
+			       &acc_negState, &supportedMech,
+			       responseToken, mechListMIC);
+	if (ret != GSS_S_COMPLETE)
+		goto cleanup;
+	if (acc_negState == ACCEPT_DEFECTIVE_TOKEN &&
+	    supportedMech == GSS_C_NO_OID &&
+	    *responseToken == GSS_C_NO_BUFFER &&
+	    *mechListMIC == GSS_C_NO_BUFFER) {
+		/* Reject "empty" token. */
+		ret = GSS_S_DEFECTIVE_TOKEN;
+	}
+	if (acc_negState == REJECT) {
+		*minor_status = ERR_SPNEGO_NEGOTIATION_FAILED;
+		*tokflag = NO_TOKEN_SEND;
+		ret = GSS_S_FAILURE;
+		goto cleanup;
+	}
+	/*
+	 * nego_done is false for the first call to init_ctx_cont()
+	 */
+	if (!sc->nego_done) {
+		ret = init_ctx_nego(minor_status, sc,
+				    acc_negState,
+				    supportedMech, responseToken,
+				    mechListMIC,
+				    negState, tokflag);
+	} else if (!sc->mech_complete &&
+		   *responseToken == GSS_C_NO_BUFFER) {
+		/*
+		 * mech not finished and mech token missing
+		 */
+		ret = GSS_S_DEFECTIVE_TOKEN;
+	} else {
+		*negState = ACCEPT_INCOMPLETE;
+		*tokflag = CONT_TOKEN_SEND;
+		ret = GSS_S_CONTINUE_NEEDED;
+	}
+cleanup:
+	if (supportedMech != GSS_C_NO_OID)
+		generic_gss_release_oid(&tmpmin, &supportedMech);
+	return ret;
+}
+
+/*
+ * Consistency checking and mechanism negotiation handling for second
+ * call of spnego_gss_init_sec_context().  Call init_ctx_reselect() to
+ * update internal state if acceptor has counter-proposed.
+ */
+static OM_uint32
+init_ctx_nego(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
+	      OM_uint32 acc_negState, gss_OID supportedMech,
+	      gss_buffer_t *responseToken, gss_buffer_t *mechListMIC,
+	      OM_uint32 *negState, send_token_flag *tokflag)
+{
+	OM_uint32 ret;
+
+	*negState = REJECT;
+	*tokflag = ERROR_TOKEN_SEND;
+	ret = GSS_S_DEFECTIVE_TOKEN;
+	/*
+	 * Both supportedMech and negState must be present in first
+	 * acceptor token.
+	 */
+	if (supportedMech == GSS_C_NO_OID) {
+		*minor_status = ERR_SPNEGO_NO_MECH_FROM_ACCEPTOR;
+		return GSS_S_DEFECTIVE_TOKEN;
+	}
+	if (acc_negState == ACCEPT_DEFECTIVE_TOKEN) {
+		*minor_status = ERR_SPNEGO_NEGOTIATION_FAILED;
+		return GSS_S_DEFECTIVE_TOKEN;
+	}
+	if (!g_OID_equal(supportedMech, sc->internal_mech)) {
+		ret = init_ctx_reselect(minor_status, sc,
+					acc_negState, supportedMech,
+					responseToken, mechListMIC,
+					negState, tokflag);
+
+	} else if (*responseToken == GSS_C_NO_BUFFER) {
+		if (sc->mech_complete) {
+			/*
+			 * Mech completed on first call to its
+			 * init_sec_context().  Acceptor sends no mech
+			 * token.
+			 */
+			*negState = ACCEPT_COMPLETE;
+			*tokflag = NO_TOKEN_SEND;
+			ret = GSS_S_COMPLETE;
+		} else {
+			/*
+			 * Reject missing mech token when optimistic
+			 * mech selected.
+			 */
+			*minor_status = ERR_SPNEGO_NO_TOKEN_FROM_ACCEPTOR;
+			ret = GSS_S_DEFECTIVE_TOKEN;
+		}
+	} else if (sc->mech_complete) {
+		/* Reject spurious mech token. */
+		ret = GSS_S_DEFECTIVE_TOKEN;
+	} else {
+		*negState = ACCEPT_INCOMPLETE;
+		*tokflag = CONT_TOKEN_SEND;
+		ret = GSS_S_CONTINUE_NEEDED;
+	}
+	sc->nego_done = 1;
+	return ret;
+}
+
+/*
+ * Handle acceptor's counter-proposal of an alternative mechanism.
+ */
+static OM_uint32
+init_ctx_reselect(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
+		  OM_uint32 acc_negState, gss_OID supportedMech,
+		  gss_buffer_t *responseToken, gss_buffer_t *mechListMIC,
+		  OM_uint32 *negState, send_token_flag *tokflag)
+{
+	OM_uint32 ret, tmpmin;
+
+	generic_gss_release_oid(&tmpmin, &sc->internal_mech);
+	gss_delete_sec_context(&tmpmin, &sc->ctx_handle,
+			       GSS_C_NO_BUFFER);
+
+	ret = generic_gss_copy_oid(minor_status, supportedMech,
+				   &sc->internal_mech);
+	if (ret != GSS_S_COMPLETE) {
+		sc->internal_mech = GSS_C_NO_OID;
+		*tokflag = NO_TOKEN_SEND;
+		return ret;
+	}
+	if (*responseToken != GSS_C_NO_BUFFER) {
+		/* Reject spurious mech token. */
+		return GSS_S_DEFECTIVE_TOKEN;
+	}
+	/*
+	 * Windows 2003 and earlier don't correctly send a
+	 * negState of request-mic when counter-proposing a
+	 * mechanism.  They probably don't handle mechListMICs
+	 * properly either.
+	 */
+	if (acc_negState != REQUEST_MIC)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	sc->mech_complete = 0;
+	sc->mic_reqd = 1;
+	*negState = REQUEST_MIC;
+	*tokflag = CONT_TOKEN_SEND;
+	return GSS_S_CONTINUE_NEEDED;
+}
+
+/*
+ * Wrap call to mechanism gss_init_sec_context() and update state
+ * accordingly.
+ */
+static OM_uint32
+init_ctx_call_init(OM_uint32 *minor_status,
+		   spnego_gss_ctx_id_t sc,
+		   gss_cred_id_t claimant_cred_handle,
+		   gss_name_t target_name,
+		   OM_uint32 req_flags,
+		   OM_uint32 time_req,
+		   gss_buffer_t mechtok_in,
+		   gss_OID *actual_mech,
+		   gss_buffer_t mechtok_out,
+		   OM_uint32 *ret_flags,
+		   OM_uint32 *time_rec,
+		   OM_uint32 *negState,
+		   send_token_flag *send_token)
+{
+	OM_uint32 ret;
+
+	ret = gss_init_sec_context(minor_status,
+				   claimant_cred_handle,
+				   &sc->ctx_handle,
+				   target_name,
+				   sc->internal_mech,
+				   (req_flags | GSS_C_INTEG_FLAG),
+				   time_req,
+				   GSS_C_NO_CHANNEL_BINDINGS,
+				   mechtok_in,
+				   &sc->actual_mech,
+				   mechtok_out,
+				   &sc->ctx_flags,
+				   time_rec);
+	if (ret == GSS_S_COMPLETE) {
+		sc->mech_complete = 1;
+		if (ret_flags != NULL)
+			*ret_flags = sc->ctx_flags;
+		/*
+		 * If this isn't the first time we've been called,
+		 * we're done unless a MIC needs to be
+		 * generated/handled.
+		 */
+		if (*send_token == CONT_TOKEN_SEND &&
+		    (!sc->mic_reqd ||
+		     !(sc->ctx_flags & GSS_C_INTEG_FLAG))) {
+
+			*negState = ACCEPT_COMPLETE;
+			ret = GSS_S_COMPLETE;
+			if (mechtok_out->length == 0) {
+				*send_token = NO_TOKEN_SEND;
+			}
+		} else {
+			*negState = ACCEPT_INCOMPLETE;
+			ret = GSS_S_CONTINUE_NEEDED;
+		}
+	} else if (ret != GSS_S_CONTINUE_NEEDED) {
+		if (*send_token == INIT_TOKEN_SEND) {
+			/* Don't output token on error if first call. */
+			*send_token = NO_TOKEN_SEND;
+		} else {
+			*send_token = ERROR_TOKEN_SEND;
+		}
+		*negState = REJECT;
+	}
+	return ret;
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_init_sec_context(void *ct,
+			OM_uint32 *minor_status,
+			gss_cred_id_t claimant_cred_handle,
+			gss_ctx_id_t *context_handle,
+			gss_name_t target_name,
+			gss_OID mech_type,
+			OM_uint32 req_flags,
+			OM_uint32 time_req,
+			gss_channel_bindings_t input_chan_bindings,
+			gss_buffer_t input_token,
+			gss_OID *actual_mech,
+			gss_buffer_t output_token,
+			OM_uint32 *ret_flags,
+			OM_uint32 *time_rec)
+{
+	/*
+	 * send_token is used to indicate in later steps
+	 * what type of token, if any should be sent or processed.
+	 * NO_TOKEN_SEND = no token should be sent
+	 * INIT_TOKEN_SEND = initial token will be sent
+	 * CONT_TOKEN_SEND = continuing tokens to be sent
+	 * CHECK_MIC = no token to be sent, but have a MIC to check.
+	 */
+	send_token_flag send_token = NO_TOKEN_SEND;
+	OM_uint32 tmpmin, ret, negState;
+	gss_buffer_t mechtok_in, mechListMIC_in, mechListMIC_out;
+	gss_buffer_desc mechtok_out = GSS_C_EMPTY_BUFFER;
+	gss_OID_set mechSet = GSS_C_NO_OID_SET;
+	spnego_gss_ctx_id_t spnego_ctx = NULL;
+
+	dsyslog("Entering init_sec_context\n");
+
+	mechtok_in = mechListMIC_out = mechListMIC_in = GSS_C_NO_BUFFER;
+	negState = REJECT;
+
+	if (minor_status != NULL)
+		*minor_status = 0;
+	if (output_token != GSS_C_NO_BUFFER) {
+		output_token->length = 0;
+		output_token->value = NULL;
+	}
+	if (minor_status == NULL ||
+	    output_token == GSS_C_NO_BUFFER ||
+	    context_handle == NULL)
+		return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+	if (actual_mech != NULL)
+		*actual_mech = GSS_C_NO_OID;
+
+	if (*context_handle == GSS_C_NO_CONTEXT) {
+		ret = init_ctx_new(minor_status, claimant_cred_handle,
+				   context_handle, &mechSet, &send_token);
+		if (ret != GSS_S_CONTINUE_NEEDED) {
+			goto cleanup;
+		}
+	} else {
+		ret = init_ctx_cont(minor_status, context_handle,
+				    input_token, &mechtok_in,
+				    &mechListMIC_in, &negState, &send_token);
+		if (HARD_ERROR(ret)) {
+			goto cleanup;
+		}
+	}
+	spnego_ctx = (spnego_gss_ctx_id_t)*context_handle;
+	if (!spnego_ctx->mech_complete) {
+		ret = init_ctx_call_init(
+			minor_status, spnego_ctx,
+			claimant_cred_handle,
+			target_name, req_flags,
+			time_req, mechtok_in,
+			actual_mech, &mechtok_out,
+			ret_flags, time_rec,
+			&negState, &send_token);
+	}
+	/* create mic/check mic */
+	if (!HARD_ERROR(ret) && spnego_ctx->mech_complete &&
+	    (spnego_ctx->ctx_flags & GSS_C_INTEG_FLAG)) {
+
+		ret = handle_mic(minor_status,
+				 mechListMIC_in,
+				 (mechtok_out.length != 0),
+				 spnego_ctx, &mechListMIC_out,
+				 &negState, &send_token);
+	}
+cleanup:
+	if (send_token == INIT_TOKEN_SEND) {
+		if (make_spnego_tokenInit_msg(spnego_ctx,
+					      mechListMIC_out,
+					      req_flags,
+					      &mechtok_out, send_token,
+					      output_token) < 0) {
+
+			ret = GSS_S_FAILURE;
+		}
+	} else if (send_token != NO_TOKEN_SEND) {
+		if (make_spnego_tokenTarg_msg(negState, GSS_C_NO_OID,
+					      &mechtok_out, mechListMIC_out,
+					      send_token,
+					      output_token) < 0) {
+			ret = GSS_S_FAILURE;
+		}
+	}
+	gss_release_buffer(&tmpmin, &mechtok_out);
+	if (ret == GSS_S_COMPLETE) {
+		/*
+		 * Now, switch the output context to refer to the
+		 * negotiated mechanism's context.
+		 */
+		*context_handle = (gss_ctx_id_t)spnego_ctx->ctx_handle;
+		if (actual_mech != NULL)
+			*actual_mech = spnego_ctx->actual_mech;
+		release_spnego_ctx(&spnego_ctx);
+	} else if (ret != GSS_S_CONTINUE_NEEDED) {
+		if (spnego_ctx != NULL) {
+			gss_delete_sec_context(&tmpmin,
+					       &spnego_ctx->ctx_handle,
+					       GSS_C_NO_BUFFER);
+			release_spnego_ctx(&spnego_ctx);
+		}
+		*context_handle = GSS_C_NO_CONTEXT;
+	}
+	if (mechtok_in != GSS_C_NO_BUFFER) {
+		gss_release_buffer(&tmpmin, mechtok_in);
+		free(mechtok_in);
+	}
+	if (mechListMIC_in != GSS_C_NO_BUFFER) {
+		gss_release_buffer(&tmpmin, mechListMIC_in);
+		free(mechListMIC_in);
+	}
+	if (mechListMIC_out != GSS_C_NO_BUFFER) {
+		gss_release_buffer(&tmpmin, mechListMIC_out);
+		free(mechListMIC_out);
+	}
+	if (mechSet != GSS_C_NO_OID_SET) {
+		gss_release_oid_set(&tmpmin, &mechSet);
+	}
+	return ret;
+} /* init_sec_context */
+
+/*
+ * Set negState to REJECT if the token is defective, else
+ * ACCEPT_INCOMPLETE or REQUEST_MIC, depending on whether initiator's
+ * preferred mechanism is supported.
+ */
+static OM_uint32
+acc_ctx_new(OM_uint32 *minor_status,
+	    gss_buffer_t buf,
+	    gss_ctx_id_t *ctx,
+	    gss_cred_id_t cred,
+	    gss_buffer_t *mechToken,
+	    gss_buffer_t *mechListMIC,
+	    OM_uint32 *negState,
+	    send_token_flag *return_token)
+{
+	OM_uint32 tmpmin, ret, req_flags;
+	gss_OID_set supported_mechSet, mechTypes;
+	gss_buffer_desc der_mechTypes;
+	gss_OID mech_wanted;
+	spnego_gss_ctx_id_t sc = NULL;
+
+	*ctx = GSS_C_NO_CONTEXT;
+	ret = GSS_S_DEFECTIVE_TOKEN;
+	der_mechTypes.length = 0;
+	der_mechTypes.value = NULL;
+	*mechToken = *mechListMIC = GSS_C_NO_BUFFER;
+	supported_mechSet = mechTypes = GSS_C_NO_OID_SET;
+	*return_token = ERROR_TOKEN_SEND;
+	*negState = REJECT;
+	*minor_status = 0;
+
+	ret = get_negTokenInit(minor_status, buf, &der_mechTypes,
+			       &mechTypes, &req_flags,
+			       mechToken, mechListMIC);
+	if (ret != GSS_S_COMPLETE) {
+		goto cleanup;
+	}
+	if (cred != GSS_C_NO_CREDENTIAL) {
+		ret = gss_inquire_cred(minor_status, cred, NULL, NULL,
+				       NULL, &supported_mechSet);
+		if (ret != GSS_S_COMPLETE) {
+			*return_token = NO_TOKEN_SEND;
+			goto cleanup;
+		}
+	} else {
+		ret = get_available_mechs(minor_status, GSS_C_NO_NAME,
+					  GSS_C_ACCEPT, NULL,
+					  &supported_mechSet);
+		if (ret != GSS_S_COMPLETE) {
+			*return_token = NO_TOKEN_SEND;
+			goto cleanup;
+		}
+	}
+	/*
+	 * Select the best match between the list of mechs
+	 * that the initiator requested and the list that
+	 * the acceptor will support.
+	 */
+	mech_wanted = negotiate_mech_type(minor_status,
+					  supported_mechSet,
+					  mechTypes,
+					  negState);
+	if (*negState == REJECT) {
+		ret = GSS_S_BAD_MECH;
+		goto cleanup;
+	}
+	sc = create_spnego_ctx();
+	if (sc == NULL) {
+		ret = GSS_S_FAILURE;
+		*return_token = NO_TOKEN_SEND;
+		generic_gss_release_oid(&tmpmin, &mech_wanted);
+		goto cleanup;
+	}
+	sc->internal_mech = mech_wanted;
+	sc->DER_mechTypes = der_mechTypes;
+	der_mechTypes.length = 0;
+	der_mechTypes.value = NULL;
+
+	if (*negState == REQUEST_MIC)
+		sc->mic_reqd = 1;
+
+	*return_token = INIT_TOKEN_SEND;
+	sc->firstpass = 1;
+	*ctx = (gss_ctx_id_t)sc;
+	ret = GSS_S_COMPLETE;
+cleanup:
+	gss_release_oid_set(&tmpmin, &mechTypes);
+	gss_release_oid_set(&tmpmin, &supported_mechSet);
+	if (der_mechTypes.length != 0)
+		gss_release_buffer(&tmpmin, &der_mechTypes);
+
+	return ret;
+}
+
+static OM_uint32
+acc_ctx_cont(OM_uint32 *minstat,
+	     gss_buffer_t buf,
+	     gss_ctx_id_t *ctx,
+	     gss_buffer_t *responseToken,
+	     gss_buffer_t *mechListMIC,
+	     OM_uint32 *negState,
+	     send_token_flag *return_token)
+{
+	OM_uint32 ret, tmpmin;
+	gss_OID supportedMech;
+	spnego_gss_ctx_id_t sc;
+	unsigned int len;
+	unsigned char *ptr, *bufstart;
+
+	sc = (spnego_gss_ctx_id_t)*ctx;
+	ret = GSS_S_DEFECTIVE_TOKEN;
+	*negState = REJECT;
+	*minstat = 0;
+	supportedMech = GSS_C_NO_OID;
+	*return_token = ERROR_TOKEN_SEND;
+	*responseToken = *mechListMIC = GSS_C_NO_BUFFER;
+
+	ptr = bufstart = buf->value;
+#define REMAIN (buf->length - (ptr - bufstart))
+	if (REMAIN > INT_MAX)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	/*
+	 * Attempt to work with old Sun SPNEGO.
+	 */
+	if (*ptr == HEADER_ID) {
+		ret = g_verify_token_header(gss_mech_spnego,
+					    &len, &ptr, 0, REMAIN);
+		if (ret) {
+			*minstat = ret;
+			return GSS_S_DEFECTIVE_TOKEN;
+		}
+	}
+	if (*ptr != (CONTEXT | 0x01)) {
+		return GSS_S_DEFECTIVE_TOKEN;
+	}
+	ret = get_negTokenResp(minstat, ptr, REMAIN,
+			       negState, &supportedMech,
+			       responseToken, mechListMIC);
+	if (ret != GSS_S_COMPLETE)
+		goto cleanup;
+
+	if (*responseToken == GSS_C_NO_BUFFER &&
+	    *mechListMIC == GSS_C_NO_BUFFER) {
+
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto cleanup;
+	}
+	if (supportedMech != GSS_C_NO_OID) {
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto cleanup;
+	}
+	sc->firstpass = 0;
+	*negState = ACCEPT_INCOMPLETE;
+	*return_token = CONT_TOKEN_SEND;
+cleanup:
+	if (supportedMech != GSS_C_NO_OID) {
+		generic_gss_release_oid(&tmpmin, &supportedMech);
+	}
+	return ret;
+#undef REMAIN
+}
+
+/*
+ * Verify that mech OID is either exactly the same as the negotiated
+ * mech OID, or is a mech OID supported by the negotiated mech.  MS
+ * implementations can list a most preferred mech using an incorrect
+ * krb5 OID while emitting a krb5 initiator mech token having the
+ * correct krb5 mech OID.
+ */
+static OM_uint32
+acc_ctx_vfy_oid(OM_uint32 *minor_status,
+		spnego_gss_ctx_id_t sc, gss_OID mechoid,
+		OM_uint32 *negState, send_token_flag *tokflag)
+{
+	OM_uint32 ret, tmpmin;
+	gss_mechanism mech = NULL;
+	gss_OID_set mech_set = GSS_C_NO_OID_SET;
+	int present = 0;
+
+	if (g_OID_equal(sc->internal_mech, mechoid))
+		return GSS_S_COMPLETE;
+
+	mech = gssint_get_mechanism(sc->internal_mech);
+	if (mech == NULL || mech->gss_indicate_mechs == NULL) {
+		*minor_status = ERR_SPNEGO_NEGOTIATION_FAILED;
+		*negState = REJECT;
+		*tokflag = ERROR_TOKEN_SEND;
+		return GSS_S_BAD_MECH;
+	}
+	ret = mech->gss_indicate_mechs(NULL, minor_status, &mech_set);
+	if (ret != GSS_S_COMPLETE) {
+		*tokflag = NO_TOKEN_SEND;
+		goto cleanup;
+	}
+	ret = gss_test_oid_set_member(minor_status, mechoid,
+				      mech_set, &present);
+	if (ret != GSS_S_COMPLETE)
+		goto cleanup;
+	if (!present) {
+		*minor_status = ERR_SPNEGO_NEGOTIATION_FAILED;
+		*negState = REJECT;
+		*tokflag = ERROR_TOKEN_SEND;
+		ret = GSS_S_BAD_MECH;
+	}
+cleanup:
+	gss_release_oid_set(&tmpmin, &mech_set);
+	return ret;
+}
+
+/*
+ * Wrap call to gss_accept_sec_context() and update state
+ * accordingly.
+ */
+static OM_uint32
+acc_ctx_call_acc(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
+		 gss_cred_id_t cred, gss_buffer_t mechtok_in,
+		 gss_OID *mech_type, gss_buffer_t mechtok_out,
+		 OM_uint32 *ret_flags, OM_uint32 *time_rec,
+		 gss_cred_id_t *delegated_cred_handle,
+		 OM_uint32 *negState, send_token_flag *tokflag)
+{
+	OM_uint32 ret;
+	gss_OID_desc mechoid;
+
+	/*
+	 * mechoid is an alias; don't free it.
+	 */
+	ret = gssint_get_mech_type(&mechoid, mechtok_in);
+	if (ret != GSS_S_COMPLETE) {
+		*tokflag = NO_TOKEN_SEND;
+		return ret;
+	}
+	ret = acc_ctx_vfy_oid(minor_status, sc, &mechoid,
+			      negState, tokflag);
+	if (ret != GSS_S_COMPLETE)
+		return ret;
+
+	ret = gss_accept_sec_context(minor_status,
+				     &sc->ctx_handle,
+				     cred,
+				     mechtok_in,
+				     GSS_C_NO_CHANNEL_BINDINGS,
+				     &sc->internal_name,
+				     mech_type,
+				     mechtok_out,
+				     &sc->ctx_flags,
+				     time_rec,
+				     delegated_cred_handle);
+	if (ret == GSS_S_COMPLETE) {
+#ifdef MS_BUG_TEST
+		/*
+		 * Force MIC to be not required even if we previously
+		 * requested a MIC.
+		 */
+		char *envstr = getenv("MS_FORCE_NO_MIC");
+
+		if (envstr != NULL && strcmp(envstr, "1") == 0 &&
+		    !(sc->ctx_flags & GSS_C_MUTUAL_FLAG) &&
+		    sc->mic_reqd) {
+
+			sc->mic_reqd = 0;
+		}
+#endif
+		sc->mech_complete = 1;
+		if (ret_flags != NULL)
+			*ret_flags = sc->ctx_flags;
+
+		if (!sc->mic_reqd) {
+			*negState = ACCEPT_COMPLETE;
+			ret = GSS_S_COMPLETE;
+		} else {
+			ret = GSS_S_CONTINUE_NEEDED;
+		}
+	} else if (ret != GSS_S_CONTINUE_NEEDED) {
+		*negState = REJECT;
+		*tokflag = ERROR_TOKEN_SEND;
+	}
+	return ret;
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_accept_sec_context(void *ct,
+			    OM_uint32 *minor_status,
+			    gss_ctx_id_t *context_handle,
+			    gss_cred_id_t verifier_cred_handle,
+			    gss_buffer_t input_token,
+			    gss_channel_bindings_t input_chan_bindings,
+			    gss_name_t *src_name,
+			    gss_OID *mech_type,
+			    gss_buffer_t output_token,
+			    OM_uint32 *ret_flags,
+			    OM_uint32 *time_rec,
+			    gss_cred_id_t *delegated_cred_handle)
+{
+	OM_uint32 ret, tmpret, tmpmin, negState;
+	send_token_flag return_token;
+	gss_buffer_t mechtok_in, mic_in, mic_out;
+	gss_buffer_desc mechtok_out = GSS_C_EMPTY_BUFFER;
+	spnego_gss_ctx_id_t sc = NULL;
+	OM_uint32 mechstat = GSS_S_FAILURE;
+
+	mechtok_in = mic_in = mic_out = GSS_C_NO_BUFFER;
+
+	if (minor_status != NULL)
+		*minor_status = 0;
+	if (output_token != GSS_C_NO_BUFFER) {
+		output_token->length = 0;
+		output_token->value = NULL;
+	}
+
+	if (minor_status == NULL ||
+	    output_token == GSS_C_NO_BUFFER ||
+	    context_handle == NULL)
+		return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+	if (input_token == GSS_C_NO_BUFFER)
+		return GSS_S_CALL_INACCESSIBLE_READ;
+
+	if (*context_handle == GSS_C_NO_CONTEXT) {
+		if (src_name != NULL)
+			*src_name = GSS_C_NO_NAME;
+		if (mech_type != NULL)
+			*mech_type = GSS_C_NO_OID;
+		if (time_rec != NULL)
+			*time_rec = 0;
+		if (ret_flags != NULL)
+			*ret_flags = 0;
+		if (delegated_cred_handle != NULL)
+			*delegated_cred_handle = GSS_C_NO_CREDENTIAL;
+		/* Can set negState to REQUEST_MIC */
+		ret = acc_ctx_new(minor_status, input_token,
+				  context_handle, verifier_cred_handle,
+				  &mechtok_in, &mic_in,
+				  &negState, &return_token);
+		if (ret != GSS_S_COMPLETE)
+			goto cleanup;
+		ret = GSS_S_CONTINUE_NEEDED;
+	} else {
+		/* Can set negState to ACCEPT_INCOMPLETE */
+		ret = acc_ctx_cont(minor_status, input_token,
+				   context_handle, &mechtok_in,
+				   &mic_in, &negState, &return_token);
+		if (ret != GSS_S_COMPLETE)
+			goto cleanup;
+		ret = GSS_S_CONTINUE_NEEDED;
+	}
+	sc = (spnego_gss_ctx_id_t)*context_handle;
+	/*
+	 * Handle mechtok_in and mic_in only if they are
+	 * present in input_token.  If neither is present, whether
+	 * this is an error depends on whether this is the first
+	 * round-trip.  RET is set to a default value according to
+	 * whether it is the first round-trip.
+	 */
+	mechstat = GSS_S_FAILURE;
+	if (negState != REQUEST_MIC && mechtok_in != GSS_C_NO_BUFFER) {
+		ret = acc_ctx_call_acc(minor_status, sc,
+				       verifier_cred_handle, mechtok_in,
+				       mech_type, &mechtok_out,
+				       ret_flags, time_rec,
+				       delegated_cred_handle,
+				       &negState, &return_token);
+	} else if (negState == REQUEST_MIC) {
+		mechstat = GSS_S_CONTINUE_NEEDED;
+	}
+	if (!HARD_ERROR(ret) && sc->mech_complete &&
+	    (sc->ctx_flags & GSS_C_INTEG_FLAG)) {
+
+		ret = handle_mic(minor_status, mic_in,
+				 (mechtok_out.length != 0),
+				 sc, &mic_out,
+				 &negState, &return_token);
+	}
+cleanup:
+	if (return_token != NO_TOKEN_SEND && return_token != CHECK_MIC) {
+		tmpret = make_spnego_tokenTarg_msg(negState, sc->internal_mech,
+						   &mechtok_out, mic_out,
+						   return_token,
+						   output_token);
+		if (tmpret != GSS_S_COMPLETE) {
+			ret = tmpret;
+		}
+	}
+	if (ret == GSS_S_COMPLETE) {
+		*context_handle = (gss_ctx_id_t)sc->ctx_handle;
+		if (sc->internal_name != GSS_C_NO_NAME &&
+		    src_name != NULL) {
+			*src_name = sc->internal_name;
+		}
+		release_spnego_ctx(&sc);
+	}
+	gss_release_buffer(&tmpmin, &mechtok_out);
+	if (mechtok_in != GSS_C_NO_BUFFER) {
+		gss_release_buffer(&tmpmin, mechtok_in);
+		free(mechtok_in);
+	}
+	if (mic_in != GSS_C_NO_BUFFER) {
+		gss_release_buffer(&tmpmin, mic_in);
+		free(mic_in);
+	}
+	if (mic_out != GSS_C_NO_BUFFER) {
+		gss_release_buffer(&tmpmin, mic_out);
+		free(mic_out);
+	}
+	return ret;
+}
+
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_display_status(void *ctx,
+		OM_uint32 *minor_status,
+		OM_uint32 status_value,
+		int status_type,
+		gss_OID mech_type,
+		OM_uint32 *message_context,
+		gss_buffer_t status_string)
+{
+	dsyslog("Entering display_status\n");
+
+	*message_context = 0;
+	switch (status_value) {
+	    case ERR_SPNEGO_NO_MECHS_AVAILABLE:
+		/* CSTYLED */
+		*status_string = make_err_msg("SPNEGO cannot find mechanisms to negotiate");
+		break;
+	    case ERR_SPNEGO_NO_CREDS_ACQUIRED:
+		/* CSTYLED */
+		*status_string = make_err_msg("SPNEGO failed to acquire creds");
+		break;
+	    case ERR_SPNEGO_NO_MECH_FROM_ACCEPTOR:
+		/* CSTYLED */
+		*status_string = make_err_msg("SPNEGO acceptor did not select a mechanism");
+		break;
+	    case ERR_SPNEGO_NEGOTIATION_FAILED:
+		/* CSTYLED */
+		*status_string = make_err_msg("SPNEGO failed to negotiate a mechanism");
+		break;
+	    case ERR_SPNEGO_NO_TOKEN_FROM_ACCEPTOR:
+		/* CSTYLED */
+		*status_string = make_err_msg("SPNEGO acceptor did not return a valid token");
+		break;
+	    default:
+		status_string->length = 0;
+		status_string->value = "";
+		break;
+	}
+
+	dsyslog("Leaving display_status\n");
+	return (GSS_S_COMPLETE);
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_import_name(void *ctx,
+		    OM_uint32 *minor_status,
+		    gss_buffer_t input_name_buffer,
+		    gss_OID input_name_type,
+		    gss_name_t *output_name)
+{
+	OM_uint32 status;
+
+	dsyslog("Entering import_name\n");
+
+	status = gss_import_name(minor_status, input_name_buffer,
+			input_name_type, output_name);
+
+	dsyslog("Leaving import_name\n");
+	return (status);
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_release_name(void *ctx,
+			OM_uint32 *minor_status,
+			gss_name_t *input_name)
+{
+	OM_uint32 status;
+
+	dsyslog("Entering release_name\n");
+
+	status = gss_release_name(minor_status, input_name);
+
+	dsyslog("Leaving release_name\n");
+	return (status);
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_display_name(void *ctx,
+			OM_uint32 *minor_status,
+			gss_name_t input_name,
+			gss_buffer_t output_name_buffer,
+			gss_OID *output_name_type)
+{
+	OM_uint32 status = GSS_S_COMPLETE;
+	dsyslog("Entering display_name\n");
+
+	status = gss_display_name(minor_status, input_name,
+			output_name_buffer, output_name_type);
+
+	dsyslog("Leaving display_name\n");
+	return (status);
+}
+
+/*ARGSUSED*/
+OM_uint32
+spnego_gss_inquire_names_for_mech(void *ctx,
+				OM_uint32	*minor_status,
+				gss_OID		mechanism,
+				gss_OID_set	*name_types)
+{
+	OM_uint32   major, minor;
+
+	dsyslog("Entering inquire_names_for_mech\n");
+	/*
+	 * We only know how to handle our own mechanism.
+	 */
+	if ((mechanism != GSS_C_NULL_OID) &&
+	    !g_OID_equal(gss_mech_spnego, mechanism)) {
+		*minor_status = 0;
+		return (GSS_S_FAILURE);
+	}
+
+	major = gss_create_empty_oid_set(minor_status, name_types);
+	if (major == GSS_S_COMPLETE) {
+		/* Now add our members. */
+		if (((major = gss_add_oid_set_member(minor_status,
+				(gss_OID) GSS_C_NT_USER_NAME,
+				name_types)) == GSS_S_COMPLETE) &&
+		    ((major = gss_add_oid_set_member(minor_status,
+				(gss_OID) GSS_C_NT_MACHINE_UID_NAME,
+				name_types)) == GSS_S_COMPLETE) &&
+		    ((major = gss_add_oid_set_member(minor_status,
+				(gss_OID) GSS_C_NT_STRING_UID_NAME,
+				name_types)) == GSS_S_COMPLETE)) {
+			major = gss_add_oid_set_member(minor_status,
+				(gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
+				name_types);
+		}
+
+		if (major != GSS_S_COMPLETE)
+			(void) gss_release_oid_set(&minor, name_types);
+	}
+
+	dsyslog("Leaving inquire_names_for_mech\n");
+	return (major);
+}
+
+OM_uint32
+spnego_gss_unseal(void *context,
+		OM_uint32 *minor_status,
+		gss_ctx_id_t context_handle,
+		gss_buffer_t input_message_buffer,
+		gss_buffer_t output_message_buffer,
+		int *conf_state,
+		int *qop_state)
+{
+	OM_uint32 ret;
+	ret = gss_unseal(minor_status,
+			context_handle,
+			input_message_buffer,
+			output_message_buffer,
+			conf_state,
+			qop_state);
+
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_seal(void *context,
+		OM_uint32 *minor_status,
+		gss_ctx_id_t context_handle,
+		int conf_req_flag,
+		int qop_req,
+		gss_buffer_t input_message_buffer,
+		int *conf_state,
+		gss_buffer_t output_message_buffer)
+{
+	OM_uint32 ret;
+	ret = gss_seal(minor_status,
+		    context_handle,
+		    conf_req_flag,
+		    qop_req,
+		    input_message_buffer,
+		    conf_state,
+		    output_message_buffer);
+
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_process_context_token(void *context,
+				OM_uint32	*minor_status,
+				const gss_ctx_id_t context_handle,
+				const gss_buffer_t token_buffer)
+{
+	OM_uint32 ret;
+	ret = gss_process_context_token(minor_status,
+					context_handle,
+					token_buffer);
+
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_delete_sec_context(void *context,
+			    OM_uint32 *minor_status,
+			    gss_ctx_id_t *context_handle,
+			    gss_buffer_t output_token)
+{
+	OM_uint32 ret = GSS_S_COMPLETE;
+	spnego_gss_ctx_id_t *ctx =
+		    (spnego_gss_ctx_id_t *)context_handle;
+
+	if (context_handle == NULL)
+		return (GSS_S_FAILURE);
+
+	/*
+	 * If this is still an SPNEGO mech, release it locally.
+	 */
+	if (*ctx != NULL &&
+	    (*ctx)->magic_num == SPNEGO_MAGIC_ID) {
+		(void) release_spnego_ctx(ctx);
+	} else {
+		ret = gss_delete_sec_context(minor_status,
+				    context_handle,
+				    output_token);
+	}
+
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_context_time(void *context,
+			OM_uint32	*minor_status,
+			const gss_ctx_id_t context_handle,
+			OM_uint32	*time_rec)
+{
+	OM_uint32 ret;
+	ret = gss_context_time(minor_status,
+			    context_handle,
+			    time_rec);
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_export_sec_context(void *context,
+			    OM_uint32	  *minor_status,
+			    gss_ctx_id_t *context_handle,
+			    gss_buffer_t interprocess_token)
+{
+	OM_uint32 ret;
+	ret = gss_export_sec_context(minor_status,
+				    context_handle,
+				    interprocess_token);
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_import_sec_context(void *context,
+	OM_uint32		*minor_status,
+	const gss_buffer_t	interprocess_token,
+	gss_ctx_id_t		*context_handle)
+{
+	OM_uint32 ret;
+	ret = gss_import_sec_context(minor_status,
+				    interprocess_token,
+				    context_handle);
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_inquire_context(void *context,
+			OM_uint32	*minor_status,
+			const gss_ctx_id_t context_handle,
+			gss_name_t	*src_name,
+			gss_name_t	*targ_name,
+			OM_uint32	*lifetime_rec,
+			gss_OID		*mech_type,
+			OM_uint32	*ctx_flags,
+			int		*locally_initiated,
+			int		*open)
+{
+	OM_uint32 ret = GSS_S_COMPLETE;
+
+	ret = gss_inquire_context(minor_status,
+				context_handle,
+				src_name,
+				targ_name,
+				lifetime_rec,
+				mech_type,
+				ctx_flags,
+				locally_initiated,
+				open);
+
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_wrap_size_limit(void *context,
+	OM_uint32	*minor_status,
+	const gss_ctx_id_t context_handle,
+	int		conf_req_flag,
+	gss_qop_t	qop_req,
+	OM_uint32	req_output_size,
+	OM_uint32	*max_input_size)
+{
+	OM_uint32 ret;
+	ret = gss_wrap_size_limit(minor_status,
+				context_handle,
+				conf_req_flag,
+				qop_req,
+				req_output_size,
+				max_input_size);
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_sign(void *context,
+		OM_uint32 *minor_status,
+		const gss_ctx_id_t context_handle,
+		int  qop_req,
+		const gss_buffer_t message_buffer,
+		gss_buffer_t message_token)
+{
+	OM_uint32 ret;
+	ret = gss_sign(minor_status,
+		    context_handle,
+		    qop_req,
+		    message_buffer,
+		    message_token);
+	return (ret);
+}
+
+OM_uint32
+spnego_gss_verify(void *context,
+		OM_uint32 *minor_status,
+		const gss_ctx_id_t context_handle,
+		const gss_buffer_t msg_buffer,
+		const gss_buffer_t token_buffer,
+		int *qop_state)
+{
+	OM_uint32 ret;
+	ret = gss_verify_mic(minor_status,
+			    context_handle,
+			    msg_buffer,
+			    token_buffer,
+			    (gss_qop_t *)qop_state); /* XXX */
+	return (ret);
+}
+
+/*
+ * We will release everything but the ctx_handle so that it
+ * can be passed back to init/accept context. This routine should
+ * not be called until after the ctx_handle memory is assigned to
+ * the supplied context handle from init/accept context.
+ */
+static void
+release_spnego_ctx(spnego_gss_ctx_id_t *ctx)
+{
+	spnego_gss_ctx_id_t context;
+	OM_uint32 minor_stat;
+	context = *ctx;
+
+	if (context != NULL) {
+		(void) gss_release_buffer(&minor_stat,
+					&context->DER_mechTypes);
+
+		(void) generic_gss_release_oid(&minor_stat,
+				&context->internal_mech);
+
+		if (context->optionStr != NULL) {
+			free(context->optionStr);
+			context->optionStr = NULL;
+		}
+		free(context);
+		*ctx = NULL;
+	}
+}
+
+/*
+ * Can't use gss_indicate_mechs by itself to get available mechs for
+ * SPNEGO because it will also return the SPNEGO mech and we do not
+ * want to consider SPNEGO as an available security mech for
+ * negotiation. For this reason, get_available_mechs will return
+ * all available mechs except SPNEGO.
+ *
+ * If a ptr to a creds list is given, this function will attempt
+ * to acquire creds for the creds given and trim the list of
+ * returned mechanisms to only those for which creds are valid.
+ *
+ */
+static OM_uint32
+get_available_mechs(OM_uint32 *minor_status,
+	gss_name_t name, gss_cred_usage_t usage,
+	gss_cred_id_t *creds, gss_OID_set *rmechs)
+{
+	int		i;
+	int		found = 0;
+	OM_uint32 stat = GSS_S_COMPLETE, tmpmin;
+	gss_OID_set mechs, goodmechs;
+
+	stat = gss_indicate_mechs(minor_status, &mechs);
+
+	if (stat != GSS_S_COMPLETE) {
+		return (stat);
+	}
+
+	stat = gss_create_empty_oid_set(minor_status, rmechs);
+
+	if (stat != GSS_S_COMPLETE) {
+		(void) gss_release_oid_set(minor_status, &mechs);
+		return (stat);
+	}
+
+	for (i = 0; i < mechs->count && stat == GSS_S_COMPLETE; i++) {
+		if ((mechs->elements[i].length
+		    != spnego_mechanism.mech_type.length) ||
+		    memcmp(mechs->elements[i].elements,
+			spnego_mechanism.mech_type.elements,
+			spnego_mechanism.mech_type.length)) {
+
+			stat = gss_add_oid_set_member(minor_status,
+					    &mechs->elements[i],
+					    rmechs);
+			if (stat == GSS_S_COMPLETE)
+				found++;
+		}
+	}
+
+	/*
+	 * If the caller wanted a list of creds returned,
+	 * trim the list of mechanisms down to only those
+	 * for which the creds are valid.
+	 */
+	if (found > 0 && stat == GSS_S_COMPLETE && creds != NULL) {
+		stat = gss_acquire_cred(minor_status,
+			name, GSS_C_INDEFINITE, *rmechs, usage, creds,
+			&goodmechs, NULL);
+
+		/*
+		 * Drop the old list in favor of the new
+		 * "trimmed" list.
+		 */
+		(void) gss_release_oid_set(&tmpmin, rmechs);
+		if (stat == GSS_S_COMPLETE) {
+			(void) gssint_copy_oid_set(&tmpmin,
+					goodmechs, rmechs);
+			(void) gss_release_oid_set(&tmpmin, &goodmechs);
+		}
+	}
+
+	(void) gss_release_oid_set(&tmpmin, &mechs);
+	if (found == 0 || stat != GSS_S_COMPLETE) {
+		*minor_status = ERR_SPNEGO_NO_MECHS_AVAILABLE;
+		if (stat == GSS_S_COMPLETE)
+			stat = GSS_S_FAILURE;
+	}
+
+	return (stat);
+}
+
+/* following are token creation and reading routines */
+
+/*
+ * If buff_in is not pointing to a MECH_OID, then return NULL and do not
+ * advance the buffer, otherwise, decode the mech_oid from the buffer and
+ * place in gss_OID.
+ */
+static gss_OID
+get_mech_oid(OM_uint32 *minor_status, unsigned char **buff_in, size_t length)
+{
+	OM_uint32	status;
+	gss_OID_desc 	toid;
+	gss_OID		mech_out = NULL;
+	unsigned char		*start, *end;
+
+	if (length < 1 || **buff_in != MECH_OID)
+		return (NULL);
+
+	start = *buff_in;
+	end = start + length;
+
+	(*buff_in)++;
+	toid.length = *(*buff_in)++;
+
+	if ((*buff_in + toid.length) > end)
+		return (NULL);
+
+	toid.elements = *buff_in;
+	*buff_in += toid.length;
+
+	status = generic_gss_copy_oid(minor_status, &toid, &mech_out);
+
+	if (status != GSS_S_COMPLETE)
+		mech_out = NULL;
+
+	return (mech_out);
+}
+
+/*
+ * der encode the given mechanism oid into buf_out, advancing the
+ * buffer pointer.
+ */
+
+static int
+put_mech_oid(unsigned char **buf_out, gss_OID_const mech, unsigned int buflen)
+{
+	if (buflen < mech->length + 2)
+		return (-1);
+	*(*buf_out)++ = MECH_OID;
+	*(*buf_out)++ = (unsigned char) mech->length;
+	memcpy((void *)(*buf_out), mech->elements, mech->length);
+	*buf_out += mech->length;
+	return (0);
+}
+
+/*
+ * verify that buff_in points to an octet string, if it does not,
+ * return NULL and don't advance the pointer. If it is an octet string
+ * decode buff_in into a gss_buffer_t and return it, advancing the
+ * buffer pointer.
+ */
+static gss_buffer_t
+get_input_token(unsigned char **buff_in, unsigned int buff_length)
+{
+	gss_buffer_t input_token;
+	unsigned int bytes;
+
+	if (**buff_in != OCTET_STRING)
+		return (NULL);
+
+	(*buff_in)++;
+	input_token = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
+
+	if (input_token == NULL)
+		return (NULL);
+
+	input_token->length = gssint_get_der_length(buff_in, buff_length, &bytes);
+	if ((int)input_token->length == -1) {
+		free(input_token);
+		return (NULL);
+	}
+	input_token->value = malloc(input_token->length);
+
+	if (input_token->value == NULL) {
+		free(input_token);
+		return (NULL);
+	}
+
+	(void) memcpy(input_token->value, *buff_in, input_token->length);
+	*buff_in += input_token->length;
+	return (input_token);
+}
+
+/*
+ * verify that the input token length is not 0. If it is, just return.
+ * If the token length is greater than 0, der encode as an octet string
+ * and place in buf_out, advancing buf_out.
+ */
+
+static int
+put_input_token(unsigned char **buf_out, gss_buffer_t input_token,
+		unsigned int buflen)
+{
+	int ret;
+
+	/* if token length is 0, we do not want to send */
+	if (input_token->length == 0)
+		return (0);
+
+	if (input_token->length > buflen)
+		return (-1);
+
+	*(*buf_out)++ = OCTET_STRING;
+	if ((ret = gssint_put_der_length(input_token->length, buf_out,
+			    input_token->length)))
+		return (ret);
+	TWRITE_STR(*buf_out, input_token->value, input_token->length);
+	return (0);
+}
+
+/*
+ * verify that buff_in points to a sequence of der encoding. The mech
+ * set is the only sequence of encoded object in the token, so if it is
+ * a sequence of encoding, decode the mechset into a gss_OID_set and
+ * return it, advancing the buffer pointer.
+ */
+static gss_OID_set
+get_mech_set(OM_uint32 *minor_status, unsigned char **buff_in,
+	     unsigned int buff_length)
+{
+	gss_OID_set returned_mechSet;
+	OM_uint32 major_status;
+	OM_uint32 length;
+	OM_uint32 bytes;
+	OM_uint32 set_length;
+	unsigned char		*start;
+	int i;
+
+	if (**buff_in != SEQUENCE_OF)
+		return (NULL);
+
+	start = *buff_in;
+	(*buff_in)++;
+
+	length = gssint_get_der_length(buff_in, buff_length, &bytes);
+
+	major_status = gss_create_empty_oid_set(minor_status,
+						&returned_mechSet);
+	if (major_status != GSS_S_COMPLETE)
+		return (NULL);
+
+	for (set_length = 0, i = 0; set_length < length; i++) {
+		gss_OID_desc *temp = get_mech_oid(minor_status, buff_in,
+			buff_length - (*buff_in - start));
+		if (temp != NULL) {
+		    major_status = gss_add_oid_set_member(minor_status,
+					temp, &returned_mechSet);
+		    if (major_status == GSS_S_COMPLETE) {
+			set_length += returned_mechSet->elements[i].length +2;
+			generic_gss_release_oid(minor_status, &temp);
+		    }
+		}
+	}
+
+	return (returned_mechSet);
+}
+
+/*
+ * Encode mechSet into buf.
+ */
+static int
+put_mech_set(gss_OID_set mechSet, gss_buffer_t buf)
+{
+	unsigned char *ptr;
+	int i;
+	unsigned int tlen, ilen;
+
+	tlen = ilen = 0;
+	for (i = 0; i < mechSet->count; i++) {
+		/*
+		 * 0x06 [DER LEN] [OID]
+		 */
+		ilen += 1 +
+			gssint_der_length_size(mechSet->elements[i].length) +
+			mechSet->elements[i].length;
+	}
+	/*
+	 * 0x30 [DER LEN]
+	 */
+	tlen = 1 + gssint_der_length_size(ilen) + ilen;
+	ptr = malloc(tlen);
+	if (ptr == NULL)
+		return -1;
+
+	buf->value = ptr;
+	buf->length = tlen;
+#define REMAIN (buf->length - ((unsigned char *)buf->value - ptr))
+
+	*ptr++ = SEQUENCE_OF;
+	if (gssint_put_der_length(ilen, &ptr, REMAIN) < 0)
+		return -1;
+	for (i = 0; i < mechSet->count; i++) {
+		if (put_mech_oid(&ptr, &mechSet->elements[i], REMAIN) < 0) {
+			return -1;
+		}
+	}
+	return 0;
+#undef REMAIN
+}
+
+/*
+ * Verify that buff_in is pointing to a BIT_STRING with the correct
+ * length and padding for the req_flags. If it is, decode req_flags
+ * and return them, otherwise, return NULL.
+ */
+static OM_uint32
+get_req_flags(unsigned char **buff_in, OM_uint32 bodysize,
+	      OM_uint32 *req_flags)
+{
+	unsigned int len;
+
+	if (**buff_in != (CONTEXT | 0x01))
+		return (0);
+
+	if (g_get_tag_and_length(buff_in, (CONTEXT | 0x01),
+				bodysize, &len) < 0)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	if (*(*buff_in)++ != BIT_STRING)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	if (*(*buff_in)++ != BIT_STRING_LENGTH)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	if (*(*buff_in)++ != BIT_STRING_PADDING)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	*req_flags = (OM_uint32) (*(*buff_in)++ >> 1);
+	return (0);
+}
+
+/*
+ * der encode the passed req_flags into buf_out, advancing
+ * the buffer pointer.
+ */
+
+static int
+put_req_flags(unsigned char **buf_out, OM_uint32 req_flags,
+	      unsigned int buflen)
+{
+	int ret = 0;
+	if (buflen < 6)
+		return (-1);
+
+	*(*buf_out)++ = CONTEXT | 0x01;
+	if ((ret = gssint_put_der_length(4, buf_out, buflen-1)) != 0)
+		return (ret);
+
+	*(*buf_out)++ = BIT_STRING;
+	*(*buf_out)++ = BIT_STRING_LENGTH;
+	*(*buf_out)++ = BIT_STRING_PADDING;
+	*(*buf_out)++ = (unsigned char) (req_flags << 1);
+	return (ret);
+}
+
+static OM_uint32
+get_negTokenInit(OM_uint32 *minor_status,
+		 gss_buffer_t buf,
+		 gss_buffer_t der_mechSet,
+		 gss_OID_set *mechSet,
+		 OM_uint32 *req_flags,
+		 gss_buffer_t *mechtok,
+		 gss_buffer_t *mechListMIC)
+{
+	OM_uint32 err;
+	unsigned char *ptr, *bufstart;
+	unsigned int len;
+	gss_buffer_desc tmpbuf;
+
+	*minor_status = 0;
+	der_mechSet->length = 0;
+	der_mechSet->value = NULL;
+	*mechSet = GSS_C_NO_OID_SET;
+	*req_flags = 0;
+	*mechtok = *mechListMIC = GSS_C_NO_BUFFER;
+
+	ptr = bufstart = buf->value;
+	if ((buf->length - (ptr - bufstart)) > INT_MAX)
+		return GSS_S_FAILURE;
+#define REMAIN (buf->length - (ptr - bufstart))
+
+	err = g_verify_token_header(gss_mech_spnego,
+				    &len, &ptr, 0, REMAIN);
+	if (err) {
+		*minor_status = err;
+		return GSS_S_FAILURE;
+	}
+	*minor_status = g_verify_neg_token_init(&ptr, REMAIN);
+	if (*minor_status)
+		return GSS_S_FAILURE;
+
+	/* alias into input_token */
+	tmpbuf.value = ptr;
+	tmpbuf.length = REMAIN;
+	*mechSet = get_mech_set(minor_status, &ptr, REMAIN);
+	if (*mechSet == NULL)
+		return GSS_S_FAILURE;
+
+	tmpbuf.length = ptr - (unsigned char *)tmpbuf.value;
+	der_mechSet->value = malloc(tmpbuf.length);
+	if (der_mechSet->value == NULL)
+		return GSS_S_FAILURE;
+	memcpy(der_mechSet->value, tmpbuf.value, tmpbuf.length);
+	der_mechSet->length = tmpbuf.length;
+
+	err = get_req_flags(&ptr, REMAIN, req_flags);
+	if (err != GSS_S_COMPLETE) {
+		return err;
+	}
+	if (g_get_tag_and_length(&ptr, (CONTEXT | 0x02),
+				 REMAIN, &len) >= 0) {
+		*mechtok = get_input_token(&ptr, len);
+		if (*mechtok == GSS_C_NO_BUFFER) {
+			return GSS_S_FAILURE;
+		}
+	}
+	if (g_get_tag_and_length(&ptr, (CONTEXT | 0x03),
+				 REMAIN, &len) >= 0) {
+		*mechListMIC = get_input_token(&ptr, len);
+		if (*mechListMIC == GSS_C_NO_BUFFER) {
+			return GSS_S_FAILURE;
+		}
+	}
+	return GSS_S_COMPLETE;
+#undef REMAIN
+}
+
+static OM_uint32
+get_negTokenResp(OM_uint32 *minor_status,
+		 unsigned char *buf, unsigned int buflen,
+		 OM_uint32 *negState,
+		 gss_OID *supportedMech,
+		 gss_buffer_t *responseToken,
+		 gss_buffer_t *mechListMIC)
+{
+	unsigned char *ptr, *bufstart;
+	unsigned int len;
+	int tmplen;
+	unsigned int tag, bytes;
+
+	*negState = ACCEPT_DEFECTIVE_TOKEN;
+	*supportedMech = GSS_C_NO_OID;
+	*responseToken = *mechListMIC = GSS_C_NO_BUFFER;
+	ptr = bufstart = buf;
+#define REMAIN (buflen - (ptr - bufstart))
+
+	if (g_get_tag_and_length(&ptr, (CONTEXT | 0x01), REMAIN, &len) < 0)
+		return GSS_S_DEFECTIVE_TOKEN;
+	if (*ptr++ == SEQUENCE) {
+		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
+		if (tmplen < 0)
+			return GSS_S_DEFECTIVE_TOKEN;
+	}
+	if (REMAIN < 1)
+		tag = 0;
+	else
+		tag = *ptr++;
+
+	if (tag == CONTEXT) {
+		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
+		if (tmplen < 0)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		if (g_get_tag_and_length(&ptr, ENUMERATED,
+					 REMAIN, &len) < 0)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		if (len != ENUMERATION_LENGTH)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		if (REMAIN < 1)
+			return GSS_S_DEFECTIVE_TOKEN;
+		*negState = *ptr++;
+
+		if (REMAIN < 1)
+			tag = 0;
+		else
+			tag = *ptr++;
+	}
+	if (tag == (CONTEXT | 0x01)) {
+		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
+		if (tmplen < 0)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		*supportedMech = get_mech_oid(minor_status, &ptr, REMAIN);
+		if (*supportedMech == GSS_C_NO_OID)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		if (REMAIN < 1)
+			tag = 0;
+		else
+			tag = *ptr++;
+	}
+	if (tag == (CONTEXT | 0x02)) {
+		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
+		if (tmplen < 0)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		*responseToken = get_input_token(&ptr, REMAIN);
+		if (*responseToken == GSS_C_NO_BUFFER)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		if (REMAIN < 1)
+			tag = 0;
+		else
+			tag = *ptr++;
+	}
+	if (tag == (CONTEXT | 0x03)) {
+		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
+		if (tmplen < 0)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+		*mechListMIC = get_input_token(&ptr, REMAIN);
+		if (*mechListMIC == GSS_C_NO_BUFFER)
+			return GSS_S_DEFECTIVE_TOKEN;
+	}
+	return GSS_S_COMPLETE;
+#undef REMAIN
+}
+
+/*
+ * der encode the passed negResults as an ENUMERATED type and
+ * place it in buf_out, advancing the buffer.
+ */
+
+static int
+put_negResult(unsigned char **buf_out, OM_uint32 negResult,
+	      unsigned int buflen)
+{
+	if (buflen < 3)
+		return (-1);
+	*(*buf_out)++ = ENUMERATED;
+	*(*buf_out)++ = ENUMERATION_LENGTH;
+	*(*buf_out)++ = (unsigned char) negResult;
+	return (0);
+}
+
+/*
+ * This routine compares the recieved mechset to the mechset that
+ * this server can support. It looks sequentially through the mechset
+ * and the first one that matches what the server can support is
+ * chosen as the negotiated mechanism. If one is found, negResult
+ * is set to ACCEPT_INCOMPLETE if it's the first mech, REQUEST_MIC if
+ * it's not the first mech, otherwise we return NULL and negResult
+ * is set to REJECT.
+ *
+ * NOTE: There is currently no way to specify a preference order of
+ * mechanisms supported by the acceptor.
+ */
+static gss_OID
+negotiate_mech_type(OM_uint32 *minor_status,
+		    gss_OID_set supported_mechSet,
+		    gss_OID_set mechset,
+		    OM_uint32 *negResult)
+{
+	gss_OID returned_mech;
+	OM_uint32 status;
+	int present;
+	int i;
+
+	for (i = 0; i < mechset->count; i++) {
+		gss_test_oid_set_member(minor_status, &mechset->elements[i],
+					supported_mechSet, &present);
+		if (!present)
+			continue;
+
+		if (i == 0)
+			*negResult = ACCEPT_INCOMPLETE;
+		else
+			*negResult = REQUEST_MIC;
+
+		status = generic_gss_copy_oid(minor_status,
+					      &mechset->elements[i],
+					      &returned_mech);
+		if (status != GSS_S_COMPLETE) {
+			*negResult = REJECT;
+			return (NULL);
+		}
+		return (returned_mech);
+	}
+	*negResult = REJECT;
+	return (NULL);
+}
+
+/*
+ * the next two routines make a token buffer suitable for
+ * spnego_gss_display_status. These currently take the string
+ * in name and place it in the token. Eventually, if
+ * spnego_gss_display_status returns valid error messages,
+ * these routines will be changes to return the error string.
+ */
+static spnego_token_t
+make_spnego_token(char *name)
+{
+	spnego_token_t token;
+
+	token = (spnego_token_t)malloc(strlen(name)+1);
+
+	if (token == NULL)
+		return (NULL);
+	strcpy(token, name);
+	return (token);
+}
+
+static gss_buffer_desc
+make_err_msg(char *name)
+{
+	gss_buffer_desc buffer;
+
+	if (name == NULL) {
+		buffer.length = 0;
+		buffer.value = NULL;
+	} else {
+		buffer.length = strlen(name)+1;
+		buffer.value = make_spnego_token(name);
+	}
+
+	return (buffer);
+}
+
+/*
+ * Create the client side spnego token passed back to gss_init_sec_context
+ * and eventually up to the application program and over to the server.
+ *
+ * Use DER rules, definite length method per RFC 2478
+ */
+static int
+make_spnego_tokenInit_msg(spnego_gss_ctx_id_t spnego_ctx,
+			  gss_buffer_t mechListMIC, OM_uint32 req_flags,
+			  gss_buffer_t data, send_token_flag sendtoken,
+			  gss_buffer_t outbuf)
+{
+	int ret = 0;
+	unsigned int tlen, dataLen = 0;
+	unsigned int negTokenInitSize = 0;
+	unsigned int negTokenInitSeqSize = 0;
+	unsigned int negTokenInitContSize = 0;
+	unsigned int rspTokenSize = 0;
+	unsigned int mechListTokenSize = 0;
+	unsigned int micTokenSize = 0;
+	unsigned char *t;
+	unsigned char *ptr;
+
+	if (outbuf == GSS_C_NO_BUFFER)
+		return (-1);
+
+	outbuf->length = 0;
+	outbuf->value = NULL;
+
+	/* calculate the data length */
+
+	/*
+	 * 0xa0 [DER LEN] [mechTypes]
+	 */
+	mechListTokenSize = 1 +
+		gssint_der_length_size(spnego_ctx->DER_mechTypes.length) +
+		spnego_ctx->DER_mechTypes.length;
+	dataLen += mechListTokenSize;
+	/*
+	 * 4 bytes for ret_flags:
+	 *   ASN.1 token + ASN.1 Length + Padding + Flags
+	 *   0xa1 LENGTH BIT_STRING BIT_STRING_LEN PAD DATA
+	 */
+	if (req_flags != 0)
+		dataLen += 6;
+
+	/*
+	 * If a token from gss_init_sec_context exists,
+	 * add the length of the token + the ASN.1 overhead
+	 */
+	if (data != NULL) {
+		/*
+		 * Encoded in final output as:
+		 * 0xa2 [DER LEN] 0x04 [DER LEN] [DATA]
+		 * -----s--------|--------s2----------
+		 */
+		rspTokenSize = 1 +
+			gssint_der_length_size(data->length) +
+			data->length;
+		dataLen += 1 + gssint_der_length_size(rspTokenSize) +
+			rspTokenSize;
+	}
+
+	if (mechListMIC) {
+		/*
+		 * Encoded in final output as:
+		 * 0xa3 [DER LEN] 0x04 [DER LEN] [DATA]
+		 *	--s--     -----tlen------------
+		 */
+		micTokenSize = 1 +
+			gssint_der_length_size(mechListMIC->length) +
+			mechListMIC->length;
+		dataLen += 1 +
+			gssint_der_length_size(micTokenSize) +
+			micTokenSize;
+	}
+
+	/*
+	 * Add size of DER encoding
+	 * [ SEQUENCE { MechTypeList | ReqFLags | Token | mechListMIC } ]
+	 *   0x30 [DER_LEN] [data]
+	 *
+	 */
+	negTokenInitContSize = dataLen;
+	negTokenInitSeqSize = 1 + gssint_der_length_size(dataLen) + dataLen;
+	dataLen = negTokenInitSeqSize;
+
+	/*
+	 * negTokenInitSize indicates the bytes needed to
+	 * hold the ASN.1 encoding of the entire NegTokenInit
+	 * SEQUENCE.
+	 * 0xa0 [DER_LEN] + data
+	 *
+	 */
+	negTokenInitSize = 1 +
+		gssint_der_length_size(negTokenInitSeqSize) +
+		negTokenInitSeqSize;
+
+	tlen = g_token_size(gss_mech_spnego, negTokenInitSize);
+
+	t = (unsigned char *) malloc(tlen);
+
+	if (t == NULL) {
+		return (-1);
+	}
+
+	ptr = t;
+
+	/* create the message */
+	if ((ret = g_make_token_header(gss_mech_spnego, negTokenInitSize,
+			    &ptr, tlen)))
+		goto errout;
+
+	*ptr++ = CONTEXT; /* NegotiationToken identifier */
+	if ((ret = gssint_put_der_length(negTokenInitSeqSize, &ptr, tlen)))
+		goto errout;
+
+	*ptr++ = SEQUENCE;
+	if ((ret = gssint_put_der_length(negTokenInitContSize, &ptr,
+					 tlen - (int)(ptr-t))))
+		goto errout;
+
+	*ptr++ = CONTEXT; /* MechTypeList identifier */
+	if ((ret = gssint_put_der_length(spnego_ctx->DER_mechTypes.length,
+					 &ptr, tlen - (int)(ptr-t))))
+		goto errout;
+
+	/* We already encoded the MechSetList */
+	(void) memcpy(ptr, spnego_ctx->DER_mechTypes.value,
+		      spnego_ctx->DER_mechTypes.length);
+
+	ptr += spnego_ctx->DER_mechTypes.length;
+
+	if (req_flags != 0) {
+		if ((ret = put_req_flags(&ptr, req_flags,
+					 tlen - (int)(ptr-t))))
+			goto errout;
+	}
+
+	if (data != NULL) {
+		*ptr++ = CONTEXT | 0x02;
+		if ((ret = gssint_put_der_length(rspTokenSize,
+				&ptr, tlen - (int)(ptr - t))))
+			goto errout;
+
+		if ((ret = put_input_token(&ptr, data,
+			tlen - (int)(ptr - t))))
+			goto errout;
+	}
+
+	if (mechListMIC != GSS_C_NO_BUFFER) {
+		*ptr++ = CONTEXT | 0x03;
+		if ((ret = gssint_put_der_length(micTokenSize,
+				&ptr, tlen - (int)(ptr - t))))
+			goto errout;
+
+		if ((ret = put_input_token(&ptr, mechListMIC,
+				tlen - (int)(ptr - t))))
+			goto errout;
+	}
+
+errout:
+	if (ret != 0) {
+		if (t)
+			free(t);
+		t = NULL;
+		tlen = 0;
+	}
+	outbuf->length = tlen;
+	outbuf->value = (void *) t;
+
+	return (ret);
+}
+
+/*
+ * create the server side spnego token passed back to
+ * gss_accept_sec_context and eventually up to the application program
+ * and over to the client.
+ */
+static int
+make_spnego_tokenTarg_msg(OM_uint32 status, gss_OID mech_wanted,
+			  gss_buffer_t data, gss_buffer_t mechListMIC,
+			  send_token_flag sendtoken,
+			  gss_buffer_t outbuf)
+{
+	unsigned int tlen = 0;
+	unsigned int ret = 0;
+	unsigned int NegTokenTargSize = 0;
+	unsigned int NegTokenSize = 0;
+	unsigned int rspTokenSize = 0;
+	unsigned int micTokenSize = 0;
+	unsigned int dataLen = 0;
+	unsigned char *t;
+	unsigned char *ptr;
+
+	if (outbuf == GSS_C_NO_BUFFER)
+		return (GSS_S_DEFECTIVE_TOKEN);
+
+	outbuf->length = 0;
+	outbuf->value = NULL;
+
+	/*
+	 * ASN.1 encoding of the negResult
+	 * ENUMERATED type is 3 bytes
+	 *  ENUMERATED TAG, Length, Value,
+	 * Plus 2 bytes for the CONTEXT id and length.
+	 */
+	dataLen = 5;
+
+	/*
+	 * calculate data length
+	 *
+	 * If this is the initial token, include length of
+	 * mech_type and the negotiation result fields.
+	 */
+	if (sendtoken == INIT_TOKEN_SEND) {
+		int mechlistTokenSize;
+		/*
+		 * 1 byte for the CONTEXT ID(0xa0),
+		 * 1 byte for the OID ID(0x06)
+		 * 1 byte for OID Length field
+		 * Plus the rest... (OID Length, OID value)
+		 */
+		mechlistTokenSize = 3 + mech_wanted->length +
+			gssint_der_length_size(mech_wanted->length);
+
+		dataLen += mechlistTokenSize;
+	}
+	if (data != NULL && data->length > 0) {
+		/* Length of the inner token */
+		rspTokenSize = 1 + gssint_der_length_size(data->length) +
+			data->length;
+
+		dataLen += rspTokenSize;
+
+		/* Length of the outer token */
+		dataLen += 1 + gssint_der_length_size(rspTokenSize);
+	}
+	if (mechListMIC != NULL) {
+
+		/* Length of the inner token */
+		micTokenSize = 1 + gssint_der_length_size(mechListMIC->length) +
+			mechListMIC->length;
+
+		dataLen += micTokenSize;
+
+		/* Length of the outer token */
+		dataLen += 1 + gssint_der_length_size(micTokenSize);
+	}
+	/*
+	 * Add size of DER encoded:
+	 * NegTokenTarg [ SEQUENCE ] of
+	 *    NegResult[0] ENUMERATED {
+	 *	accept_completed(0),
+	 *	accept_incomplete(1),
+	 *	reject(2) }
+	 *    supportedMech [1] MechType OPTIONAL,
+	 *    responseToken [2] OCTET STRING OPTIONAL,
+	 *    mechListMIC   [3] OCTET STRING OPTIONAL
+	 *
+	 * size = data->length + MechListMic + SupportedMech len +
+	 *	Result Length + ASN.1 overhead
+	 */
+	NegTokenTargSize = dataLen;
+	dataLen += 1 + gssint_der_length_size(NegTokenTargSize);
+
+	/*
+	 * NegotiationToken [ CHOICE ]{
+	 *    negTokenInit  [0]	 NegTokenInit,
+	 *    negTokenTarg  [1]	 NegTokenTarg }
+	 */
+	NegTokenSize = dataLen;
+	dataLen += 1 + gssint_der_length_size(NegTokenSize);
+
+	tlen = dataLen;
+	t = (unsigned char *) malloc(tlen);
+
+	if (t == NULL) {
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto errout;
+	}
+
+	ptr = t;
+
+	/*
+	 * Indicate that we are sending CHOICE 1
+	 * (NegTokenTarg)
+	 */
+	*ptr++ = CONTEXT | 0x01;
+	if (gssint_put_der_length(NegTokenSize, &ptr, dataLen) < 0) {
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto errout;
+	}
+	*ptr++ = SEQUENCE;
+	if (gssint_put_der_length(NegTokenTargSize, &ptr,
+				  tlen - (int)(ptr-t)) < 0) {
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto errout;
+	}
+
+	/*
+	 * First field of the NegTokenTarg SEQUENCE
+	 * is the ENUMERATED NegResult.
+	 */
+	*ptr++ = CONTEXT;
+	if (gssint_put_der_length(3, &ptr,
+				  tlen - (int)(ptr-t)) < 0) {
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto errout;
+	}
+	if (put_negResult(&ptr, status, tlen - (int)(ptr - t)) < 0) {
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto errout;
+	}
+	if (sendtoken == INIT_TOKEN_SEND) {
+		/*
+		 * Next, is the Supported MechType
+		 */
+		*ptr++ = CONTEXT | 0x01;
+		if (gssint_put_der_length(mech_wanted->length + 2,
+					  &ptr,
+					  tlen - (int)(ptr - t)) < 0) {
+			ret = GSS_S_DEFECTIVE_TOKEN;
+			goto errout;
+		}
+		if (put_mech_oid(&ptr, mech_wanted,
+				 tlen - (int)(ptr - t)) < 0) {
+			ret = GSS_S_DEFECTIVE_TOKEN;
+			goto errout;
+		}
+	}
+	if (data != NULL && data->length > 0) {
+		*ptr++ = CONTEXT | 0x02;
+		if (gssint_put_der_length(rspTokenSize, &ptr,
+					  tlen - (int)(ptr - t)) < 0) {
+			ret = GSS_S_DEFECTIVE_TOKEN;
+			goto errout;
+		}
+		if (put_input_token(&ptr, data,
+				    tlen - (int)(ptr - t)) < 0) {
+			ret = GSS_S_DEFECTIVE_TOKEN;
+			goto errout;
+		}
+	}
+	if (mechListMIC != NULL) {
+		*ptr++ = CONTEXT | 0x03;
+		if (gssint_put_der_length(micTokenSize, &ptr,
+					  tlen - (int)(ptr - t)) < 0) {
+			ret = GSS_S_DEFECTIVE_TOKEN;
+			goto errout;
+		}
+		if (put_input_token(&ptr, mechListMIC,
+				    tlen - (int)(ptr - t)) < 0) {
+			ret = GSS_S_DEFECTIVE_TOKEN;
+			goto errout;
+		}
+	}
+	ret = GSS_S_COMPLETE;
+errout:
+	if (ret != GSS_S_COMPLETE) {
+		if (t)
+			free(t);
+	} else {
+		outbuf->length = ptr - t;
+		outbuf->value = (void *) t;
+	}
+
+	return (ret);
+}
+
+/* determine size of token */
+static int
+g_token_size(gss_OID_const mech, unsigned int body_size)
+{
+	int hdrsize;
+
+	/*
+	 * Initialize the header size to the
+	 * MECH_OID byte + the bytes needed to indicate the
+	 * length of the OID + the OID itself.
+	 *
+	 * 0x06 [MECHLENFIELD] MECHDATA
+	 */
+	hdrsize = 1 + gssint_der_length_size(mech->length) + mech->length;
+
+	/*
+	 * Now add the bytes needed for the initial header
+	 * token bytes:
+	 * 0x60 + [DER_LEN] + HDRSIZE
+	 */
+	hdrsize += 1 + gssint_der_length_size(body_size + hdrsize);
+
+	return (hdrsize + body_size);
+}
+
+/*
+ * generate token header.
+ *
+ * Use DER Definite Length method per RFC2478
+ * Use of indefinite length encoding will not be compatible
+ * with Microsoft or others that actually follow the spec.
+ */
+static int
+g_make_token_header(gss_OID_const mech,
+		    unsigned int body_size,
+		    unsigned char **buf,
+		    unsigned int totallen)
+{
+	int ret = 0;
+	unsigned int hdrsize;
+	unsigned char *p = *buf;
+
+	hdrsize = 1 + gssint_der_length_size(mech->length) + mech->length;
+
+	*(*buf)++ = HEADER_ID;
+	if ((ret = gssint_put_der_length(hdrsize + body_size, buf, totallen)))
+		return (ret);
+
+	*(*buf)++ = MECH_OID;
+	if ((ret = gssint_put_der_length(mech->length, buf,
+			    totallen - (int)(p - *buf))))
+		return (ret);
+	TWRITE_STR(*buf, mech->elements, mech->length);
+	return (0);
+}
+
+/*
+ * NOTE: This checks that the length returned by
+ * gssint_get_der_length() is not greater than the number of octets
+ * remaining, even though gssint_get_der_length() already checks, in
+ * theory.
+ */
+static int
+g_get_tag_and_length(unsigned char **buf, int tag,
+		     unsigned int buflen, unsigned int *outlen)
+{
+	unsigned char *ptr = *buf;
+	int ret = -1; /* pessimists, assume failure ! */
+	unsigned int encoded_len;
+	int tmplen = 0;
+
+	*outlen = 0;
+	if (buflen > 1 && *ptr == tag) {
+		ptr++;
+		tmplen = gssint_get_der_length(&ptr, buflen - 1,
+						&encoded_len);
+		if (tmplen < 0) {
+			ret = -1;
+		} else if (tmplen > buflen - (ptr - *buf)) {
+			ret = -1;
+		} else
+			ret = 0;
+	}
+	*outlen = tmplen;
+	*buf = ptr;
+	return (ret);
+}
+
+static int
+g_verify_neg_token_init(unsigned char **buf_in, unsigned int cur_size)
+{
+	unsigned char *buf = *buf_in;
+	unsigned char *endptr = buf + cur_size;
+	unsigned int seqsize;
+	int ret = 0;
+	unsigned int bytes;
+
+	/*
+	 * Verify this is a NegotiationToken type token
+	 * - check for a0(context specific identifier)
+	 * - get length and verify that enoughd ata exists
+	 */
+	if (g_get_tag_and_length(&buf, CONTEXT, cur_size, &seqsize) < 0)
+		return (G_BAD_TOK_HEADER);
+
+	cur_size = seqsize; /* should indicate bytes remaining */
+
+	/*
+	 * Verify the next piece, it should identify this as
+	 * a strucure of type NegTokenInit.
+	 */
+	if (*buf++ == SEQUENCE) {
+		if ((seqsize = gssint_get_der_length(&buf, cur_size, &bytes)) < 0)
+			return (G_BAD_TOK_HEADER);
+		/*
+		 * Make sure we have the entire buffer as described
+		 */
+		if (buf + seqsize > endptr)
+			return (G_BAD_TOK_HEADER);
+	} else {
+		return (G_BAD_TOK_HEADER);
+	}
+
+	cur_size = seqsize; /* should indicate bytes remaining */
+
+	/*
+	 * Verify that the first blob is a sequence of mechTypes
+	 */
+	if (*buf++ == CONTEXT) {
+		if ((seqsize = gssint_get_der_length(&buf, cur_size, &bytes)) < 0)
+			return (G_BAD_TOK_HEADER);
+		/*
+		 * Make sure we have the entire buffer as described
+		 */
+		if (buf + bytes > endptr)
+			return (G_BAD_TOK_HEADER);
+	} else {
+		return (G_BAD_TOK_HEADER);
+	}
+
+	/*
+	 * At this point, *buf should be at the beginning of the
+	 * DER encoded list of mech types that are to be negotiated.
+	 */
+	*buf_in = buf;
+
+	return (ret);
+
+}
+
+/* verify token header. */
+static int
+g_verify_token_header(gss_OID_const mech,
+		    unsigned int *body_size,
+		    unsigned char **buf_in,
+		    int tok_type,
+		    unsigned int toksize)
+{
+	unsigned char *buf = *buf_in;
+	int seqsize;
+	gss_OID_desc toid;
+	int ret = 0;
+	unsigned int bytes;
+
+	if (toksize-- < 1)
+		return (G_BAD_TOK_HEADER);
+
+	if (*buf++ != HEADER_ID)
+		return (G_BAD_TOK_HEADER);
+
+	if ((seqsize = gssint_get_der_length(&buf, toksize, &bytes)) < 0)
+		return (G_BAD_TOK_HEADER);
+
+	if ((seqsize + bytes) != toksize)
+		return (G_BAD_TOK_HEADER);
+
+	if (toksize-- < 1)
+		return (G_BAD_TOK_HEADER);
+
+
+	if (*buf++ != MECH_OID)
+		return (G_BAD_TOK_HEADER);
+
+	if (toksize-- < 1)
+		return (G_BAD_TOK_HEADER);
+
+	toid.length = *buf++;
+
+	if (toksize < toid.length)
+		return (G_BAD_TOK_HEADER);
+	else
+		toksize -= toid.length;
+
+	toid.elements = buf;
+	buf += toid.length;
+
+	if (!g_OID_equal(&toid, mech))
+		ret = G_WRONG_MECH;
+
+	/*
+	 * G_WRONG_MECH is not returned immediately because it's more important
+	 * to return G_BAD_TOK_HEADER if the token header is in fact bad
+	 */
+	if (toksize < 2)
+		return (G_BAD_TOK_HEADER);
+	else
+		toksize -= 2;
+
+	if (!ret) {
+		*buf_in = buf;
+		*body_size = toksize;
+	}
+
+	return (ret);
+}
diff --git a/krb5-1-6/src/lib/gssapi32.def b/krb5-1-6/src/lib/gssapi32.def
new file mode 100644
index 000000000..fa36f51ed
--- /dev/null
+++ b/krb5-1-6/src/lib/gssapi32.def
@@ -0,0 +1,99 @@
+;----------------------------------------------------
+;   GSSAPI32.DEF - GSSAPI32.DLL module definition file
+;----------------------------------------------------
+
+;LIBRARY		GSSAPI32
+DESCRIPTION	'Base Generic Security Service API'
+HEAPSIZE	8192
+
+EXPORTS
+	gss_acquire_cred			@10
+	gss_release_cred			@54
+	gss_init_sec_context			@27
+	gss_accept_sec_context			@9
+	gss_process_context_token		@52
+	gss_delete_sec_context			@17
+	gss_context_time			@15
+	gss_sign				@59
+	gss_verify				@64
+	gss_seal				@58
+	gss_unseal				@62
+	gss_display_status			@19
+	gss_indicate_mechs			@26
+	gss_compare_name			@14
+	gss_display_name			@18
+	gss_import_name				@24
+	gss_release_name			@55
+	gss_release_buffer			@53
+	gss_release_oid_set			@57
+	gss_inquire_cred			@29
+;
+; GSS-API v2  additional credential calls
+;
+	gss_add_cred				@11
+	gss_inquire_cred_by_mech		@30
+;
+; GSS-API v2  additional context-level calls
+;
+	gss_inquire_context			@28
+	gss_wrap_size_limit			@67
+	gss_export_sec_context			@22
+	gss_import_sec_context			@25
+;
+; GSS-API v2  additional calls for OID and OID_set operations
+;
+	gss_release_oid
+	gss_create_empty_oid_set		@16
+	gss_add_oid_set_member			@12
+	gss_test_oid_set_member			@61
+	gss_oid_to_str				@51
+	gss_str_to_oid				@60
+;
+; GSS-API v2  renamed message protection calls
+;
+	gss_wrap				@66
+	gss_unwrap				@63
+	gss_get_mic				@23
+	gss_verify_mic				@65
+;
+; GSS-API v2  future extensions
+;
+	gss_inquire_names_for_mech		@32
+	gss_inquire_mechs_for_name		@31
+	gss_canonicalize_name			@13
+	gss_export_name				@21
+	gss_duplicate_name			@20
+;
+; Krb5 specific function extensions
+;
+	gss_krb5_get_tkt_flags 			@37
+	gss_krb5_copy_ccache			@34
+	gss_krb5_ccache_name			@33
+        gss_krb5_set_allowable_enctypes		@38
+        gss_krb5_export_lucid_sec_context	@35
+        gss_krb5_free_lucid_sec_context		@36
+	krb5_gss_register_acceptor_identity	@69
+;
+; GSS-API variables
+;
+        gss_nt_krb5_name               	@45	DATA
+        gss_nt_krb5_principal          	@46	DATA
+	gss_nt_user_name	       	@50	DATA
+	gss_nt_machine_uid_name	       	@47	DATA
+	gss_nt_string_uid_name	       	@49	DATA
+	gss_nt_service_name	       	@48	DATA
+        GSS_C_NT_USER_NAME             	@7 	DATA
+        GSS_C_NT_MACHINE_UID_NAME      	@5 	DATA
+        GSS_C_NT_STRING_UID_NAME       	@6 	DATA
+        GSS_C_NT_HOSTBASED_SERVICE     	@3 	DATA
+        GSS_C_NT_HOSTBASED_SERVICE_X   	@4 	DATA
+        GSS_C_NT_ANONYMOUS             	@1 	DATA
+        GSS_C_NT_EXPORT_NAME           	@2 	DATA
+        krb5_gss_oid_array             	@68 	DATA
+        gss_mech_krb5                  	@39	DATA
+        gss_mech_krb5_old              	@40	DATA
+        gss_mech_set_krb5              	@42	DATA
+        gss_mech_set_krb5_old          	@44	DATA
+        gss_mech_set_krb5_both         	@43	DATA
+	GSS_KRB5_NT_PRINCIPAL_NAME     	@8 	DATA
+	gss_mech_krb5_wrong	       	@41	DATA	
diff --git a/krb5-1-6/src/lib/kadm5/Makefile.in b/krb5-1-6/src/lib/kadm5/Makefile.in
new file mode 100644
index 000000000..0201c1c63
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/Makefile.in
@@ -0,0 +1,206 @@
+thisconfigdir=../..
+myfulldir=lib/kadm5
+mydir=lib/kadm5
+BUILDTOP=$(REL)..$(S)..
+LOCAL_SUBDIRS = clnt srv unit-test
+DEFS=
+
+##DOSBUILDTOP = ..\..
+
+kadm_err.$(OBJEXT): kadm_err.c
+chpass_util_strings.$(OBJEXT): chpass_util_strings.c
+
+kadm_err.c kadm_err.h: $(srcdir)/kadm_err.et
+chpass_util_strings.c chpass_util_strings.h: $(srcdir)/chpass_util_strings.et
+
+clean::
+	$(RM) kadm_err.c kadm_err.h kadm_err.o
+	$(RM) chpass_util_strings.c chpass_util_strings.h chpass_util_strings.o
+
+SRCS =	kadm_err.c \
+	chpass_util_strings.c \
+	$(srcdir)/ovsec_glue.c \
+	$(srcdir)/misc_free.c \
+	$(srcdir)/kadm_rpc_xdr.c \
+	$(srcdir)/chpass_util.c \
+	$(srcdir)/alt_prof.c \
+	$(srcdir)/str_conv.c \
+	$(srcdir)/logger.c
+
+OBJS =	kadm_err.$(OBJEXT) \
+	chpass_util_strings.$(OBJEXT) \
+	ovsec_glue.$(OBJEXT) \
+	misc_free.$(OBJEXT) \
+	kadm_rpc_xdr.$(OBJEXT) \
+	chpass_util.$(OBJEXT) \
+	alt_prof.$(OBJEXT) \
+	str_conv.$(OBJEXT) \
+	logger.$(OBJEXT)
+
+STLIBOBJS = \
+	kadm_err.o \
+	chpass_util_strings.o \
+	ovsec_glue.o \
+	misc_free.o \
+	kadm_rpc_xdr.o \
+	chpass_util.o \
+	alt_prof.o \
+	str_conv.o \
+	logger.o
+
+HDRDIR=$(BUILDTOP)/include/kadm5
+HDRS =	$(HDRDIR)/admin.h \
+	$(HDRDIR)/admin_internal.h \
+	$(HDRDIR)/admin_xdr.h \
+	$(HDRDIR)/kadm_rpc.h \
+	$(HDRDIR)/server_internal.h \
+	$(HDRDIR)/chpass_util_strings.h \
+	$(HDRDIR)/kadm_err.h
+
+BUILD_HDRS = chpass_util_strings.h kadm_err.h
+SRC_HDRS = admin.h admin_internal.h admin_xdr.h kadm_rpc.h \
+		server_internal.h 
+
+$(HDRS): includes
+
+includes:: $(SRC_HDRS) $(BUILD_HDRS)
+	if [ -d $(HDRDIR) ]; then :; else mkdir -p $(HDRDIR); fi
+	for i in $(SRC_HDRS) ; do \
+		i=`basename $$i`; \
+		if cmp $(srcdir)/$$i $(HDRDIR)/$$i >/dev/null 2>&1; then :; \
+		else \
+			(set -x; $(RM) $(HDRDIR)/$$i; \
+			 $(CP) $(srcdir)/$$i $(HDRDIR)/$$i) ; \
+		fi ; \
+	done
+	for i in $(BUILD_HDRS) ; do \
+		i=`basename $$i`; \
+		if cmp $$i $(HDRDIR)/$$i >/dev/null 2>&1; then :; \
+		else \
+			(set -x; $(RM) $(HDRDIR)/$$i; \
+			 $(CP) $$i $(HDRDIR)/$$i) ; \
+		fi ; \
+	done
+
+clean-unix::
+	$(RM) $(HDRS)
+
+all-prerecurse: includes
+all-prerecurse: all-libobjs
+
+all-windows:: $(OBJS)
+
+generate-files-mac-prerecurse: includes
+
+check-windows::
+
+clean-unix:: clean-libobjs
+
+clean-windows::
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+kadm_err.so kadm_err.po $(OUTPRE)kadm_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) kadm_err.c
+chpass_util_strings.so chpass_util_strings.po $(OUTPRE)chpass_util_strings.$(OBJEXT): \
+  $(COM_ERR_DEPS) chpass_util_strings.c
+ovsec_glue.so ovsec_glue.po $(OUTPRE)ovsec_glue.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h ovsec_glue.c
+misc_free.so misc_free.po $(OUTPRE)misc_free.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h admin_internal.h misc_free.c \
+  server_internal.h
+kadm_rpc_xdr.so kadm_rpc_xdr.po $(OUTPRE)kadm_rpc_xdr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/admin_xdr.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h kadm_rpc_xdr.c
+chpass_util.so chpass_util.po $(OUTPRE)chpass_util.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h admin_internal.h chpass_util.c
+alt_prof.so alt_prof.po $(OUTPRE)alt_prof.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h alt_prof.c
+str_conv.so str_conv.po $(OUTPRE)str_conv.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h admin_internal.h str_conv.c
+logger.so logger.po $(OUTPRE)logger.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  logger.c
diff --git a/krb5-1-6/src/lib/kadm5/adb.h b/krb5-1-6/src/lib/kadm5/adb.h
new file mode 100644
index 000000000..66eadfc3b
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/adb.h
@@ -0,0 +1,149 @@
+/*
+ * Data Types for policy and principal information that
+ * exists in the respective databases.
+ *
+ * $Header$
+ *
+ * This file was originally created with rpcgen.
+ * It has been hacked up since then.
+ */
+
+#ifndef __ADB_H__
+#define __ADB_H__
+#include <sys/types.h>
+#include <gssrpc/types.h>
+#include "k5-int.h"
+#include <kdb.h>
+#include <db.h>
+#include <kadm5/admin.h>
+#include <kadm5/adb_err.h>
+#include <com_err.h>
+
+typedef	long		osa_adb_ret_t;
+
+#define OSA_ADB_POLICY_DB_MAGIC	0x12345A00
+#define OSA_ADB_PRINC_DB_MAGIC	0x12345B00
+
+#define OSA_ADB_SHARED		0x7001
+#define OSA_ADB_EXCLUSIVE	0x7002
+#define OSA_ADB_PERMANENT	0x7003
+
+#define OSA_ADB_PRINC_VERSION_MASK	0x12345C00
+#define OSA_ADB_PRINC_VERSION_1		0x12345C01
+#define OSA_ADB_POLICY_VERSION_MASK	0x12345D00
+#define OSA_ADB_POLICY_VERSION_1	0x12345D01
+
+typedef struct _osa_adb_db_lock_ent_t {
+     FILE	*lockfile;
+     char	*filename;
+     int	refcnt, lockmode, lockcnt;
+     krb5_context context;
+} osa_adb_lock_ent, *osa_adb_lock_t;
+
+typedef struct _osa_adb_db_ent_t {
+     int	magic;
+     DB		*db;
+     HASHINFO	info;
+     BTREEINFO	btinfo;
+     char	*filename;
+     osa_adb_lock_t lock;
+     int	opencnt;
+} osa_adb_db_ent, *osa_adb_db_t, *osa_adb_princ_t, *osa_adb_policy_t;
+
+/* an osa_pw_hist_ent stores all the key_datas for a single password */
+typedef struct _osa_pw_hist_t {
+     int n_key_data;
+     krb5_key_data *key_data;
+} osa_pw_hist_ent, *osa_pw_hist_t;
+
+typedef struct _osa_princ_ent_t {
+    int				version;
+    char			*policy;
+    long			aux_attributes;
+    unsigned int		old_key_len;
+    unsigned int		old_key_next;
+    krb5_kvno			admin_history_kvno;
+    osa_pw_hist_ent		*old_keys;
+} osa_princ_ent_rec, *osa_princ_ent_t;
+
+typedef struct _osa_policy_ent_t {
+    int		version;
+    char	*name;
+    uint32_t	pw_min_life;
+    uint32_t	pw_max_life;
+    uint32_t	pw_min_length;
+    uint32_t	pw_min_classes;
+    uint32_t	pw_history_num;
+    uint32_t	policy_refcnt;
+} osa_policy_ent_rec, *osa_policy_ent_t;
+
+typedef	void	(*osa_adb_iter_princ_func) (void *, osa_princ_ent_t);
+typedef	void	(*osa_adb_iter_policy_func) (void *, osa_policy_ent_t);
+  
+
+/*
+ * Return Code (the rest are in adb_err.h)
+ */
+ 
+#define OSA_ADB_OK		0
+
+/*
+ * xdr functions
+ */
+bool_t		xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp);
+bool_t		xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp);
+bool_t		xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp);
+bool_t          xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp);
+
+/*
+ * Functions
+ */
+
+osa_adb_ret_t	osa_adb_create_db(char *filename, char *lockfile, int magic);
+osa_adb_ret_t	osa_adb_destroy_db(char *filename, char *lockfile, int magic);
+osa_adb_ret_t   osa_adb_rename_db(char *filefrom, char *lockfrom,
+				  char *fileto, char *lockto, int magic);
+osa_adb_ret_t   osa_adb_rename_policy_db(kadm5_config_params *fromparams,
+					 kadm5_config_params *toparams);
+osa_adb_ret_t	osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
+				char *lockfile, int magic);
+osa_adb_ret_t	osa_adb_fini_db(osa_adb_db_t db, int magic);
+osa_adb_ret_t	osa_adb_get_lock(osa_adb_db_t db, int mode);
+osa_adb_ret_t	osa_adb_release_lock(osa_adb_db_t db);
+osa_adb_ret_t	osa_adb_open_and_lock(osa_adb_princ_t db, int locktype);
+osa_adb_ret_t	osa_adb_close_and_unlock(osa_adb_princ_t db);
+
+osa_adb_ret_t	osa_adb_create_policy_db(kadm5_config_params *params);
+osa_adb_ret_t	osa_adb_destroy_policy_db(kadm5_config_params *params);
+osa_adb_ret_t	osa_adb_open_princ(osa_adb_princ_t *db, char *filename);
+osa_adb_ret_t	osa_adb_open_policy(osa_adb_policy_t *db,
+				    kadm5_config_params *rparams);
+osa_adb_ret_t	osa_adb_close_princ(osa_adb_princ_t db);
+osa_adb_ret_t	osa_adb_close_policy(osa_adb_policy_t db);
+osa_adb_ret_t	osa_adb_create_princ(osa_adb_princ_t db,
+				 osa_princ_ent_t entry);
+osa_adb_ret_t	osa_adb_create_policy(osa_adb_policy_t db,
+				      osa_policy_ent_t entry);
+osa_adb_ret_t	osa_adb_destroy_princ(osa_adb_princ_t db,
+				      kadm5_princ_t name);
+osa_adb_ret_t	osa_adb_destroy_policy(osa_adb_policy_t db,
+				       kadm5_policy_t name);
+osa_adb_ret_t	osa_adb_get_princ(osa_adb_princ_t db,
+				  kadm5_princ_t name,
+				  osa_princ_ent_t *entry);
+osa_adb_ret_t	osa_adb_get_policy(osa_adb_policy_t db,
+				   kadm5_policy_t name,
+				   osa_policy_ent_t *entry);
+osa_adb_ret_t	osa_adb_put_princ(osa_adb_princ_t db,
+				  osa_princ_ent_t entry);
+osa_adb_ret_t	osa_adb_put_policy(osa_adb_policy_t db,
+				   osa_policy_ent_t entry);
+osa_adb_ret_t	osa_adb_iter_policy(osa_adb_policy_t db,
+				    osa_adb_iter_policy_func func,
+				    void * data);
+osa_adb_ret_t	osa_adb_iter_princ(osa_adb_princ_t db,
+				       osa_adb_iter_princ_func func,
+				       void *data);
+void		osa_free_policy_ent(osa_policy_ent_t val);
+void		osa_free_princ_ent(osa_princ_ent_t val);
+#endif /* __ADB_H__ */
diff --git a/krb5-1-6/src/lib/kadm5/admin.h b/krb5-1-6/src/lib/kadm5/admin.h
new file mode 100644
index 000000000..99d18d4e2
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/admin.h
@@ -0,0 +1,747 @@
+/*
+ * lib/kadm5/admin.h
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#ifndef __KADM5_ADMIN_H__
+#define __KADM5_ADMIN_H__
+
+#if !defined(USE_KADM5_API_VERSION)
+#define USE_KADM5_API_VERSION 2
+#endif
+     
+#include	<sys/types.h>
+#include	<gssrpc/rpc.h>
+#include	<krb5.h>
+#include	<kdb.h>
+#include	<com_err.h>
+#include	<kadm5/kadm_err.h>
+#include	<kadm5/chpass_util_strings.h>
+
+#define KADM5_ADMIN_SERVICE	"kadmin/admin"
+#define KADM5_CHANGEPW_SERVICE	"kadmin/changepw"
+#define KADM5_HIST_PRINCIPAL	"kadmin/history"
+
+typedef krb5_principal	kadm5_princ_t;
+typedef	char		*kadm5_policy_t;
+typedef long		kadm5_ret_t;
+
+#define KADM5_PW_FIRST_PROMPT \
+	(error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT))
+#define KADM5_PW_SECOND_PROMPT \
+	(error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT))
+
+/*
+ * Successful return code
+ */
+#define KADM5_OK	0
+
+/*
+ * Field masks
+ */
+
+/* kadm5_principal_ent_t */
+#define KADM5_PRINCIPAL		0x000001
+#define KADM5_PRINC_EXPIRE_TIME	0x000002
+#define KADM5_PW_EXPIRATION	0x000004
+#define KADM5_LAST_PWD_CHANGE	0x000008
+#define KADM5_ATTRIBUTES	0x000010
+#define KADM5_MAX_LIFE		0x000020
+#define KADM5_MOD_TIME		0x000040
+#define KADM5_MOD_NAME		0x000080
+#define KADM5_KVNO		0x000100
+#define KADM5_MKVNO		0x000200
+#define KADM5_AUX_ATTRIBUTES	0x000400
+#define KADM5_POLICY		0x000800
+#define KADM5_POLICY_CLR	0x001000
+/* version 2 masks */
+#define KADM5_MAX_RLIFE		0x002000
+#define KADM5_LAST_SUCCESS	0x004000
+#define KADM5_LAST_FAILED	0x008000
+#define KADM5_FAIL_AUTH_COUNT	0x010000
+#define KADM5_KEY_DATA		0x020000
+#define KADM5_TL_DATA		0x040000
+#ifdef notyet /* Novell */
+#define KADM5_CPW_FUNCTION      0x080000
+#define KADM5_RANDKEY_USED      0x100000
+#endif
+#define KADM5_LOAD		0x200000
+
+/* all but KEY_DATA and TL_DATA */
+#define KADM5_PRINCIPAL_NORMAL_MASK 0x01ffff
+
+
+/* kadm5_policy_ent_t */
+#define KADM5_PW_MAX_LIFE	0x004000
+#define KADM5_PW_MIN_LIFE	0x008000
+#define KADM5_PW_MIN_LENGTH	0x010000
+#define KADM5_PW_MIN_CLASSES	0x020000
+#define KADM5_PW_HISTORY_NUM	0x040000
+#define KADM5_REF_COUNT		0x080000
+
+/* kadm5_config_params */
+#define KADM5_CONFIG_REALM		0x000001
+#define KADM5_CONFIG_DBNAME		0x000002
+#define KADM5_CONFIG_MKEY_NAME		0x000004
+#define KADM5_CONFIG_MAX_LIFE		0x000008
+#define KADM5_CONFIG_MAX_RLIFE		0x000010
+#define KADM5_CONFIG_EXPIRATION		0x000020
+#define KADM5_CONFIG_FLAGS		0x000040
+#define KADM5_CONFIG_ADMIN_KEYTAB	0x000080
+#define KADM5_CONFIG_STASH_FILE		0x000100
+#define KADM5_CONFIG_ENCTYPE		0x000200
+#define KADM5_CONFIG_ADBNAME		0x000400
+#define KADM5_CONFIG_ADB_LOCKFILE	0x000800
+/*#define KADM5_CONFIG_PROFILE		0x001000*/
+#define KADM5_CONFIG_ACL_FILE		0x002000
+#define KADM5_CONFIG_KADMIND_PORT	0x004000
+#define KADM5_CONFIG_ENCTYPES		0x008000
+#define KADM5_CONFIG_ADMIN_SERVER	0x010000
+#define KADM5_CONFIG_DICT_FILE		0x020000
+#define KADM5_CONFIG_MKEY_FROM_KBD	0x040000
+#define KADM5_CONFIG_KPASSWD_PORT	0x080000
+#define KADM5_CONFIG_OLD_AUTH_GSSAPI	0x100000
+#define KADM5_CONFIG_NO_AUTH		0x200000
+#define KADM5_CONFIG_AUTH_NOFALLBACK	0x400000
+#ifdef notyet /* Novell */
+#define KADM5_CONFIG_KPASSWD_SERVER     0x800000
+#endif
+/*
+ * permission bits
+ */
+#define KADM5_PRIV_GET		0x01
+#define KADM5_PRIV_ADD		0x02
+#define KADM5_PRIV_MODIFY	0x04
+#define KADM5_PRIV_DELETE	0x08
+
+/*
+ * API versioning constants
+ */
+#define KADM5_MASK_BITS		0xffffff00
+
+#define KADM5_STRUCT_VERSION_MASK	0x12345600
+#define KADM5_STRUCT_VERSION_1	(KADM5_STRUCT_VERSION_MASK|0x01)
+#define KADM5_STRUCT_VERSION	KADM5_STRUCT_VERSION_1
+
+#define KADM5_API_VERSION_MASK	0x12345700
+#define KADM5_API_VERSION_1	(KADM5_API_VERSION_MASK|0x01)
+#define KADM5_API_VERSION_2	(KADM5_API_VERSION_MASK|0x02)
+
+typedef struct _kadm5_principal_ent_t_v2 {
+	krb5_principal	principal;
+	krb5_timestamp	princ_expire_time;
+	krb5_timestamp	last_pwd_change;
+	krb5_timestamp	pw_expiration;
+	krb5_deltat	max_life;
+	krb5_principal	mod_name;
+	krb5_timestamp	mod_date;
+	krb5_flags	attributes;
+	krb5_kvno	kvno;
+	krb5_kvno	mkvno;
+	char		*policy;
+	long		aux_attributes;
+
+	/* version 2 fields */
+	krb5_deltat max_renewable_life;
+        krb5_timestamp last_success;
+        krb5_timestamp last_failed;
+        krb5_kvno fail_auth_count;
+	krb5_int16 n_key_data;
+	krb5_int16 n_tl_data;
+        krb5_tl_data *tl_data;
+	krb5_key_data *key_data;
+} kadm5_principal_ent_rec_v2, *kadm5_principal_ent_t_v2;
+
+typedef struct _kadm5_principal_ent_t_v1 {
+	krb5_principal	principal;
+	krb5_timestamp	princ_expire_time;
+	krb5_timestamp	last_pwd_change;
+	krb5_timestamp	pw_expiration;
+	krb5_deltat	max_life;
+	krb5_principal	mod_name;
+	krb5_timestamp	mod_date;
+	krb5_flags	attributes;
+	krb5_kvno	kvno;
+	krb5_kvno	mkvno;
+	char		*policy;
+	long		aux_attributes;
+} kadm5_principal_ent_rec_v1, *kadm5_principal_ent_t_v1;
+
+#if USE_KADM5_API_VERSION == 1
+typedef struct _kadm5_principal_ent_t_v1
+     kadm5_principal_ent_rec, *kadm5_principal_ent_t;
+#else
+typedef struct _kadm5_principal_ent_t_v2
+     kadm5_principal_ent_rec, *kadm5_principal_ent_t;
+#endif
+
+typedef struct _kadm5_policy_ent_t {
+	char		*policy;
+	long		pw_min_life;
+	long		pw_max_life;
+	long		pw_min_length;
+	long		pw_min_classes;
+	long		pw_history_num;
+	long		policy_refcnt;
+} kadm5_policy_ent_rec, *kadm5_policy_ent_t;
+
+/*
+ * Data structure returned by kadm5_get_config_params()
+ */
+typedef struct _kadm5_config_params {
+     long		mask;
+     char *		realm;
+     int		kadmind_port;
+     int		kpasswd_port;
+
+     char *		admin_server;
+#ifdef notyet /* Novell */ /* ABI change? */
+     char *		kpasswd_server;
+#endif
+
+     char *		dbname;
+     char *		admin_dbname;
+     char *		admin_lockfile;
+     char *		admin_keytab;
+     char *		acl_file;
+     char *		dict_file;
+
+     int		mkey_from_kbd;
+     char *		stash_file;
+     char *		mkey_name;
+     krb5_enctype	enctype;
+     krb5_deltat	max_life;
+     krb5_deltat	max_rlife;
+     krb5_timestamp	expiration;
+     krb5_flags		flags;
+     krb5_key_salt_tuple *keysalts;
+     krb5_int32		num_keysalts;
+} kadm5_config_params;
+
+/***********************************************************************
+ * This is the old krb5_realm_read_params, which I mutated into
+ * kadm5_get_config_params but which old code (kdb5_* and krb5kdc)
+ * still uses.
+ ***********************************************************************/
+
+/*
+ * Data structure returned by krb5_read_realm_params()
+ */
+typedef struct __krb5_realm_params {
+    char *		realm_profile;
+    char *		realm_dbname;
+    char *		realm_mkey_name;
+    char *		realm_stash_file;
+    char *		realm_kdc_ports;
+    char *		realm_kdc_tcp_ports;
+    char *		realm_acl_file;
+    krb5_int32		realm_kadmind_port;
+    krb5_enctype	realm_enctype;
+    krb5_deltat		realm_max_life;
+    krb5_deltat		realm_max_rlife;
+    krb5_timestamp	realm_expiration;
+    krb5_flags		realm_flags;
+    krb5_key_salt_tuple	*realm_keysalts;
+    unsigned int	realm_reject_bad_transit:1;
+    unsigned int	realm_kadmind_port_valid:1;
+    unsigned int	realm_enctype_valid:1;
+    unsigned int	realm_max_life_valid:1;
+    unsigned int	realm_max_rlife_valid:1;
+    unsigned int	realm_expiration_valid:1;
+    unsigned int	realm_flags_valid:1;
+    unsigned int	realm_reject_bad_transit_valid:1;
+    krb5_int32		realm_num_keysalts;
+} krb5_realm_params;
+
+/*
+ * functions
+ */
+
+#if USE_KADM5_API_VERSION > 1
+krb5_error_code kadm5_get_config_params(krb5_context context,
+					int use_kdc_config,
+					kadm5_config_params *params_in,
+					kadm5_config_params *params_out);
+
+krb5_error_code kadm5_free_config_params(krb5_context context, 
+					 kadm5_config_params *params);
+
+krb5_error_code kadm5_free_realm_params(krb5_context kcontext,
+					kadm5_config_params *params);
+
+krb5_error_code kadm5_get_admin_service_name(krb5_context, char *,
+					     char *, size_t);
+#endif
+
+kadm5_ret_t    kadm5_init(char *client_name, char *pass,
+			  char *service_name,
+#if USE_KADM5_API_VERSION == 1
+			  char *realm,
+#else
+			  kadm5_config_params *params,
+#endif
+			  krb5_ui_4 struct_version,
+			  krb5_ui_4 api_version,
+			  char **db_args,
+			  void **server_handle);
+kadm5_ret_t    kadm5_init_with_password(char *client_name,
+					char *pass, 
+					char *service_name,
+#if USE_KADM5_API_VERSION == 1
+					char *realm,
+#else
+					kadm5_config_params *params,
+#endif
+					krb5_ui_4 struct_version,
+					krb5_ui_4 api_version,
+					char **db_args,
+					void **server_handle);
+kadm5_ret_t    kadm5_init_with_skey(char *client_name,
+				    char *keytab,
+				    char *service_name,
+#if USE_KADM5_API_VERSION == 1
+				    char *realm,
+#else
+				    kadm5_config_params *params,
+#endif
+				    krb5_ui_4 struct_version,
+				    krb5_ui_4 api_version,
+				    char **db_args,
+				    void **server_handle);
+#if USE_KADM5_API_VERSION > 1
+kadm5_ret_t    kadm5_init_with_creds(char *client_name,
+				     krb5_ccache cc,
+				     char *service_name,
+				     kadm5_config_params *params,
+				     krb5_ui_4 struct_version,
+				     krb5_ui_4 api_version,
+				     char **db_args,
+				     void **server_handle);
+#endif
+kadm5_ret_t    kadm5_lock(void *server_handle);
+kadm5_ret_t    kadm5_unlock(void *server_handle);
+kadm5_ret_t    kadm5_flush(void *server_handle);
+kadm5_ret_t    kadm5_destroy(void *server_handle);
+kadm5_ret_t    kadm5_create_principal(void *server_handle,
+				      kadm5_principal_ent_t ent,
+				      long mask, char *pass);
+kadm5_ret_t    kadm5_create_principal_3(void *server_handle,
+					kadm5_principal_ent_t ent,
+					long mask,
+					int n_ks_tuple,
+					krb5_key_salt_tuple *ks_tuple,
+					char *pass);
+kadm5_ret_t    kadm5_delete_principal(void *server_handle,
+				      krb5_principal principal);
+kadm5_ret_t    kadm5_modify_principal(void *server_handle,
+				      kadm5_principal_ent_t ent,
+				      long mask);
+kadm5_ret_t    kadm5_rename_principal(void *server_handle,
+				      krb5_principal,krb5_principal);
+#if USE_KADM5_API_VERSION == 1
+kadm5_ret_t    kadm5_get_principal(void *server_handle,
+				   krb5_principal principal,
+				   kadm5_principal_ent_t *ent);
+#else
+kadm5_ret_t    kadm5_get_principal(void *server_handle,
+				   krb5_principal principal,
+				   kadm5_principal_ent_t ent,
+				   long mask);
+#endif
+kadm5_ret_t    kadm5_chpass_principal(void *server_handle,
+				      krb5_principal principal,
+				      char *pass);
+kadm5_ret_t    kadm5_chpass_principal_3(void *server_handle,
+					krb5_principal principal,
+					krb5_boolean keepold,
+					int n_ks_tuple,
+					krb5_key_salt_tuple *ks_tuple,
+					char *pass);
+#if USE_KADM5_API_VERSION == 1
+kadm5_ret_t    kadm5_randkey_principal(void *server_handle,
+				       krb5_principal principal,
+				       krb5_keyblock **keyblock);
+#else
+kadm5_ret_t    kadm5_randkey_principal(void *server_handle,
+				       krb5_principal principal,
+				       krb5_keyblock **keyblocks,
+				       int *n_keys);
+kadm5_ret_t    kadm5_randkey_principal_3(void *server_handle,
+					 krb5_principal principal,
+					 krb5_boolean keepold,
+					 int n_ks_tuple,
+					 krb5_key_salt_tuple *ks_tuple,
+					 krb5_keyblock **keyblocks,
+					 int *n_keys);
+#endif
+kadm5_ret_t    kadm5_setv4key_principal(void *server_handle,
+					krb5_principal principal,
+					krb5_keyblock *keyblock);
+
+kadm5_ret_t    kadm5_setkey_principal(void *server_handle,
+				      krb5_principal principal,
+				      krb5_keyblock *keyblocks,
+				      int n_keys);
+
+kadm5_ret_t    kadm5_setkey_principal_3(void *server_handle,
+					krb5_principal principal,
+					krb5_boolean keepold,
+					int n_ks_tuple,
+					krb5_key_salt_tuple *ks_tuple,
+					krb5_keyblock *keyblocks,
+					int n_keys);
+
+kadm5_ret_t    kadm5_decrypt_key(void *server_handle,
+				 kadm5_principal_ent_t entry, krb5_int32
+				 ktype, krb5_int32 stype, krb5_int32
+				 kvno, krb5_keyblock *keyblock,
+				 krb5_keysalt *keysalt, int *kvnop);
+
+kadm5_ret_t    kadm5_create_policy(void *server_handle,
+				   kadm5_policy_ent_t ent,
+				   long mask);
+/*
+ * kadm5_create_policy_internal is not part of the supported,
+ * exposed API.  It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from kadm5_create_policy.
+ */
+kadm5_ret_t    kadm5_create_policy_internal(void *server_handle,
+					    kadm5_policy_ent_t
+					    entry, long mask);
+kadm5_ret_t    kadm5_delete_policy(void *server_handle,
+				   kadm5_policy_t policy);
+kadm5_ret_t    kadm5_modify_policy(void *server_handle,
+				   kadm5_policy_ent_t ent,
+				   long mask);
+/*
+ * kadm5_modify_policy_internal is not part of the supported,
+ * exposed API.  It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from kadm5_modify_policy.
+ */
+kadm5_ret_t    kadm5_modify_policy_internal(void *server_handle,
+					    kadm5_policy_ent_t
+					    entry, long mask);
+#if USE_KADM5_API_VERSION == 1
+kadm5_ret_t    kadm5_get_policy(void *server_handle,
+				kadm5_policy_t policy,
+				kadm5_policy_ent_t *ent);
+#else
+kadm5_ret_t    kadm5_get_policy(void *server_handle,
+				kadm5_policy_t policy,
+				kadm5_policy_ent_t ent);
+#endif
+kadm5_ret_t    kadm5_get_privs(void *server_handle,
+			       long *privs);
+
+kadm5_ret_t    kadm5_chpass_principal_util(void *server_handle,
+					   krb5_principal princ,
+					   char *new_pw, 
+					   char **ret_pw,
+					   char *msg_ret,
+					   unsigned int msg_len);
+
+kadm5_ret_t    kadm5_free_principal_ent(void *server_handle,
+					kadm5_principal_ent_t
+					ent);
+kadm5_ret_t    kadm5_free_policy_ent(void *server_handle,
+				     kadm5_policy_ent_t ent);
+
+kadm5_ret_t    kadm5_get_principals(void *server_handle,
+				    char *exp, char ***princs,
+				    int *count);
+
+kadm5_ret_t    kadm5_get_policies(void *server_handle,
+				  char *exp, char ***pols,
+				  int *count);
+
+#if USE_KADM5_API_VERSION > 1
+kadm5_ret_t    kadm5_free_key_data(void *server_handle,
+				   krb5_int16 *n_key_data,
+				   krb5_key_data *key_data);
+#endif
+
+kadm5_ret_t    kadm5_free_name_list(void *server_handle, char **names, 
+				    int count);
+
+krb5_error_code kadm5_init_krb5_context (krb5_context *);
+
+#if USE_KADM5_API_VERSION == 1
+/*
+ * OVSEC_KADM_API_VERSION_1 should be, if possible, compile-time
+ * compatible with KADM5_API_VERSION_2.  Basically, this means we have
+ * to continue to provide all the old ovsec_kadm function and symbol
+ * names.
+ */
+
+#define OVSEC_KADM_ACLFILE		"/krb5/ovsec_adm.acl"
+#define	OVSEC_KADM_WORDFILE		"/krb5/ovsec_adm.dict"
+
+#define OVSEC_KADM_ADMIN_SERVICE	"ovsec_adm/admin"
+#define OVSEC_KADM_CHANGEPW_SERVICE	"ovsec_adm/changepw"
+#define OVSEC_KADM_HIST_PRINCIPAL	"ovsec_adm/history"
+
+typedef krb5_principal	ovsec_kadm_princ_t;
+typedef krb5_keyblock	ovsec_kadm_keyblock;
+typedef	char		*ovsec_kadm_policy_t;
+typedef long		ovsec_kadm_ret_t;
+
+enum	ovsec_kadm_salttype { OVSEC_KADM_SALT_V4, OVSEC_KADM_SALT_NORMAL };
+enum	ovsec_kadm_saltmod  { OVSEC_KADM_MOD_KEEP, OVSEC_KADM_MOD_V4, OVSEC_KADM_MOD_NORMAL };
+
+#define OVSEC_KADM_PW_FIRST_PROMPT \
+	((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT))
+#define OVSEC_KADM_PW_SECOND_PROMPT \
+	((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT))
+
+/*
+ * Successful return code
+ */
+#define OVSEC_KADM_OK	0
+ 
+/*
+ * Create/Modify masks
+ */
+/* principal */
+#define OVSEC_KADM_PRINCIPAL		0x000001
+#define OVSEC_KADM_PRINC_EXPIRE_TIME	0x000002
+#define OVSEC_KADM_PW_EXPIRATION	0x000004
+#define OVSEC_KADM_LAST_PWD_CHANGE	0x000008
+#define OVSEC_KADM_ATTRIBUTES		0x000010
+#define OVSEC_KADM_MAX_LIFE		0x000020
+#define OVSEC_KADM_MOD_TIME		0x000040
+#define OVSEC_KADM_MOD_NAME		0x000080
+#define OVSEC_KADM_KVNO			0x000100
+#define OVSEC_KADM_MKVNO		0x000200
+#define OVSEC_KADM_AUX_ATTRIBUTES	0x000400
+#define OVSEC_KADM_POLICY		0x000800
+#define OVSEC_KADM_POLICY_CLR		0x001000
+/* policy */
+#define OVSEC_KADM_PW_MAX_LIFE		0x004000
+#define OVSEC_KADM_PW_MIN_LIFE		0x008000
+#define OVSEC_KADM_PW_MIN_LENGTH	0x010000
+#define OVSEC_KADM_PW_MIN_CLASSES	0x020000
+#define OVSEC_KADM_PW_HISTORY_NUM	0x040000
+#define OVSEC_KADM_REF_COUNT		0x080000
+
+/*
+ * permission bits
+ */
+#define OVSEC_KADM_PRIV_GET	0x01
+#define OVSEC_KADM_PRIV_ADD	0x02
+#define OVSEC_KADM_PRIV_MODIFY	0x04
+#define OVSEC_KADM_PRIV_DELETE	0x08
+
+/*
+ * API versioning constants
+ */
+#define OVSEC_KADM_MASK_BITS		0xffffff00
+
+#define OVSEC_KADM_STRUCT_VERSION_MASK	0x12345600
+#define OVSEC_KADM_STRUCT_VERSION_1	(OVSEC_KADM_STRUCT_VERSION_MASK|0x01)
+#define OVSEC_KADM_STRUCT_VERSION	OVSEC_KADM_STRUCT_VERSION_1
+
+#define OVSEC_KADM_API_VERSION_MASK	0x12345700
+#define OVSEC_KADM_API_VERSION_1	(OVSEC_KADM_API_VERSION_MASK|0x01)
+
+
+typedef struct _ovsec_kadm_principal_ent_t {
+	krb5_principal	principal;
+	krb5_timestamp	princ_expire_time;
+	krb5_timestamp	last_pwd_change;
+	krb5_timestamp	pw_expiration;
+	krb5_deltat	max_life;
+	krb5_principal	mod_name;
+	krb5_timestamp	mod_date;
+	krb5_flags	attributes;
+	krb5_kvno	kvno;
+	krb5_kvno	mkvno;
+	char		*policy;
+	long		aux_attributes;
+} ovsec_kadm_principal_ent_rec, *ovsec_kadm_principal_ent_t;
+
+typedef struct _ovsec_kadm_policy_ent_t {
+	char		*policy;
+	long		pw_min_life;
+	long		pw_max_life;
+	long		pw_min_length;
+	long		pw_min_classes;
+	long		pw_history_num;
+	long		policy_refcnt;
+} ovsec_kadm_policy_ent_rec, *ovsec_kadm_policy_ent_t;
+
+/*
+ * functions
+ */
+ovsec_kadm_ret_t    ovsec_kadm_init(char *client_name, char *pass,
+				    char *service_name, char *realm,
+				    krb5_ui_4 struct_version,
+				    krb5_ui_4 api_version,
+				    char **db_args,
+				    void **server_handle);
+ovsec_kadm_ret_t    ovsec_kadm_init_with_password(char *client_name,
+						  char *pass, 
+						  char *service_name,
+						  char *realm, 
+						  krb5_ui_4 struct_version,
+						  krb5_ui_4 api_version,
+						  char ** db_args,
+						  void **server_handle);
+ovsec_kadm_ret_t    ovsec_kadm_init_with_skey(char *client_name,
+					      char *keytab,
+					      char *service_name,
+					      char *realm,
+					      krb5_ui_4 struct_version,
+					      krb5_ui_4 api_version,
+					      char **db_args,
+					      void **server_handle);
+ovsec_kadm_ret_t    ovsec_kadm_flush(void *server_handle);
+ovsec_kadm_ret_t    ovsec_kadm_destroy(void *server_handle);
+ovsec_kadm_ret_t    ovsec_kadm_create_principal(void *server_handle,
+						ovsec_kadm_principal_ent_t ent,
+						long mask, char *pass);
+ovsec_kadm_ret_t    ovsec_kadm_delete_principal(void *server_handle,
+						krb5_principal principal);
+ovsec_kadm_ret_t    ovsec_kadm_modify_principal(void *server_handle,
+						ovsec_kadm_principal_ent_t ent,
+						long mask);
+ovsec_kadm_ret_t    ovsec_kadm_rename_principal(void *server_handle,
+						krb5_principal,krb5_principal);
+ovsec_kadm_ret_t    ovsec_kadm_get_principal(void *server_handle,
+					     krb5_principal principal,
+					     ovsec_kadm_principal_ent_t *ent);
+ovsec_kadm_ret_t    ovsec_kadm_chpass_principal(void *server_handle,
+						krb5_principal principal,
+						char *pass);
+ovsec_kadm_ret_t    ovsec_kadm_randkey_principal(void *server_handle,
+						 krb5_principal principal,
+						 krb5_keyblock **keyblock);
+ovsec_kadm_ret_t    ovsec_kadm_create_policy(void *server_handle,
+					     ovsec_kadm_policy_ent_t ent,
+					     long mask);
+/*
+ * ovsec_kadm_create_policy_internal is not part of the supported,
+ * exposed API.  It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from ovsec_kadm_create_policy.
+ */
+ovsec_kadm_ret_t    ovsec_kadm_create_policy_internal(void *server_handle,
+						      ovsec_kadm_policy_ent_t
+						      entry, long mask);
+ovsec_kadm_ret_t    ovsec_kadm_delete_policy(void *server_handle,
+					     ovsec_kadm_policy_t policy);
+ovsec_kadm_ret_t    ovsec_kadm_modify_policy(void *server_handle,
+					     ovsec_kadm_policy_ent_t ent,
+					     long mask);
+/*
+ * ovsec_kadm_modify_policy_internal is not part of the supported,
+ * exposed API.  It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from ovsec_kadm_modify_policy.
+ */
+ovsec_kadm_ret_t    ovsec_kadm_modify_policy_internal(void *server_handle,
+						      ovsec_kadm_policy_ent_t
+						      entry, long mask);
+ovsec_kadm_ret_t    ovsec_kadm_get_policy(void *server_handle,
+					  ovsec_kadm_policy_t policy,
+					  ovsec_kadm_policy_ent_t *ent);
+ovsec_kadm_ret_t    ovsec_kadm_get_privs(void *server_handle,
+					 long *privs);
+
+ovsec_kadm_ret_t    ovsec_kadm_chpass_principal_util(void *server_handle,
+						     krb5_principal princ,
+						     char *new_pw, 
+						     char **ret_pw,
+						     char *msg_ret);
+
+ovsec_kadm_ret_t    ovsec_kadm_free_principal_ent(void *server_handle,
+						  ovsec_kadm_principal_ent_t
+						  ent);
+ovsec_kadm_ret_t    ovsec_kadm_free_policy_ent(void *server_handle,
+					       ovsec_kadm_policy_ent_t ent);
+
+ovsec_kadm_ret_t ovsec_kadm_free_name_list(void *server_handle,
+					   char **names, int count);
+
+ovsec_kadm_ret_t    ovsec_kadm_get_principals(void *server_handle,
+					      char *exp, char ***princs,
+					      int *count);
+
+ovsec_kadm_ret_t    ovsec_kadm_get_policies(void *server_handle,
+					    char *exp, char ***pols,
+					    int *count);
+
+#define OVSEC_KADM_FAILURE KADM5_FAILURE
+#define OVSEC_KADM_AUTH_GET KADM5_AUTH_GET
+#define OVSEC_KADM_AUTH_ADD KADM5_AUTH_ADD
+#define OVSEC_KADM_AUTH_MODIFY KADM5_AUTH_MODIFY
+#define OVSEC_KADM_AUTH_DELETE KADM5_AUTH_DELETE
+#define OVSEC_KADM_AUTH_INSUFFICIENT KADM5_AUTH_INSUFFICIENT
+#define OVSEC_KADM_BAD_DB KADM5_BAD_DB
+#define OVSEC_KADM_DUP KADM5_DUP
+#define OVSEC_KADM_RPC_ERROR KADM5_RPC_ERROR
+#define OVSEC_KADM_NO_SRV KADM5_NO_SRV
+#define OVSEC_KADM_BAD_HIST_KEY KADM5_BAD_HIST_KEY
+#define OVSEC_KADM_NOT_INIT KADM5_NOT_INIT
+#define OVSEC_KADM_UNK_PRINC KADM5_UNK_PRINC
+#define OVSEC_KADM_UNK_POLICY KADM5_UNK_POLICY
+#define OVSEC_KADM_BAD_MASK KADM5_BAD_MASK
+#define OVSEC_KADM_BAD_CLASS KADM5_BAD_CLASS
+#define OVSEC_KADM_BAD_LENGTH KADM5_BAD_LENGTH
+#define OVSEC_KADM_BAD_POLICY KADM5_BAD_POLICY
+#define OVSEC_KADM_BAD_PRINCIPAL KADM5_BAD_PRINCIPAL
+#define OVSEC_KADM_BAD_AUX_ATTR KADM5_BAD_AUX_ATTR
+#define OVSEC_KADM_BAD_HISTORY KADM5_BAD_HISTORY
+#define OVSEC_KADM_BAD_MIN_PASS_LIFE KADM5_BAD_MIN_PASS_LIFE
+#define OVSEC_KADM_PASS_Q_TOOSHORT KADM5_PASS_Q_TOOSHORT
+#define OVSEC_KADM_PASS_Q_CLASS KADM5_PASS_Q_CLASS
+#define OVSEC_KADM_PASS_Q_DICT KADM5_PASS_Q_DICT
+#define OVSEC_KADM_PASS_REUSE KADM5_PASS_REUSE
+#define OVSEC_KADM_PASS_TOOSOON KADM5_PASS_TOOSOON
+#define OVSEC_KADM_POLICY_REF KADM5_POLICY_REF
+#define OVSEC_KADM_INIT KADM5_INIT
+#define OVSEC_KADM_BAD_PASSWORD KADM5_BAD_PASSWORD
+#define OVSEC_KADM_PROTECT_PRINCIPAL KADM5_PROTECT_PRINCIPAL
+#define OVSEC_KADM_BAD_SERVER_HANDLE KADM5_BAD_SERVER_HANDLE
+#define OVSEC_KADM_BAD_STRUCT_VERSION KADM5_BAD_STRUCT_VERSION
+#define OVSEC_KADM_OLD_STRUCT_VERSION KADM5_OLD_STRUCT_VERSION
+#define OVSEC_KADM_NEW_STRUCT_VERSION KADM5_NEW_STRUCT_VERSION
+#define OVSEC_KADM_BAD_API_VERSION KADM5_BAD_API_VERSION
+#define OVSEC_KADM_OLD_LIB_API_VERSION KADM5_OLD_LIB_API_VERSION
+#define OVSEC_KADM_OLD_SERVER_API_VERSION KADM5_OLD_SERVER_API_VERSION
+#define OVSEC_KADM_NEW_LIB_API_VERSION KADM5_NEW_LIB_API_VERSION
+#define OVSEC_KADM_NEW_SERVER_API_VERSION KADM5_NEW_SERVER_API_VERSION
+#define OVSEC_KADM_SECURE_PRINC_MISSING KADM5_SECURE_PRINC_MISSING
+#define OVSEC_KADM_NO_RENAME_SALT KADM5_NO_RENAME_SALT
+
+#endif /* USE_KADM5_API_VERSION == 1 */
+
+#endif /* __KADM5_ADMIN_H__ */
diff --git a/krb5-1-6/src/lib/kadm5/admin_internal.h b/krb5-1-6/src/lib/kadm5/admin_internal.h
new file mode 100644
index 000000000..6a9d31b0c
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/admin_internal.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ */
+
+#ifndef __KADM5_ADMIN_INTERNAL_H__
+#define __KADM5_ADMIN_INTERNAL_H__
+
+#include <kadm5/admin.h>
+
+#define KADM5_SERVER_HANDLE_MAGIC	0x12345800
+
+#define GENERIC_CHECK_HANDLE(handle, old_api_version, new_api_version) \
+{ \
+	kadm5_server_handle_t srvr = \
+	     (kadm5_server_handle_t) handle; \
+ \
+	if (! srvr) \
+		return KADM5_BAD_SERVER_HANDLE; \
+	if (srvr->magic_number != KADM5_SERVER_HANDLE_MAGIC) \
+		return KADM5_BAD_SERVER_HANDLE; \
+	if ((srvr->struct_version & KADM5_MASK_BITS) != \
+	    KADM5_STRUCT_VERSION_MASK) \
+		return KADM5_BAD_STRUCT_VERSION; \
+	if (srvr->struct_version < KADM5_STRUCT_VERSION_1) \
+		return KADM5_OLD_STRUCT_VERSION; \
+	if (srvr->struct_version > KADM5_STRUCT_VERSION_1) \
+		return KADM5_NEW_STRUCT_VERSION; \
+	if ((srvr->api_version & KADM5_MASK_BITS) != \
+	    KADM5_API_VERSION_MASK) \
+		return KADM5_BAD_API_VERSION; \
+	if (srvr->api_version < KADM5_API_VERSION_1) \
+		return old_api_version; \
+	if (srvr->api_version > KADM5_API_VERSION_2) \
+		return new_api_version; \
+}
+
+/*
+ * _KADM5_CHECK_HANDLE calls the function _kadm5_check_handle and
+ * returns any non-zero error code that function returns.
+ * _kadm5_check_handle, in client_handle.c and server_handle.c, exists
+ * in both the server- and client- side libraries.  In each library,
+ * it calls CHECK_HANDLE, which is defined by the appropriate
+ * _internal.h header file to call GENERIC_CHECK_HANDLE as well as
+ * CLIENT_CHECK_HANDLE and SERVER_CHECK_HANDLE.
+ *
+ * _KADM5_CHECK_HANDLE should be used by a function that needs to
+ * check the handle but wants to be the same code in both the client
+ * and server library; it makes a function call to the right handle
+ * checker.  Code that only exists in one library can call the
+ * CHECK_HANDLE macro, which inlines the test instead of making
+ * another function call.
+ *
+ * Got that?
+ */
+#define _KADM5_CHECK_HANDLE(handle) \
+{ int ecode; if ((ecode = _kadm5_check_handle((void *)handle))) return ecode;}
+
+int         _kadm5_check_handle(void *handle);
+kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
+					 void *lhandle,
+					 krb5_principal princ,
+					 char *new_pw, 
+					 char **ret_pw,
+					 char *msg_ret,
+					 unsigned int msg_len);
+
+/* this is needed by the alt_prof code I stole.  The functions
+   maybe shouldn't be named krb5_*, but they are. */
+
+krb5_error_code
+krb5_string_to_keysalts(char *string, const char *tupleseps,
+			const char *ksaltseps, krb5_boolean dups,
+			krb5_key_salt_tuple **ksaltp, krb5_int32 *nksaltp);
+
+krb5_error_code
+krb5_string_to_flags(char* string, const char* positive, const char* negative,
+		     krb5_flags *flagsp);
+
+#endif /* __KADM5_ADMIN_INTERNAL_H__ */
diff --git a/krb5-1-6/src/lib/kadm5/admin_xdr.h b/krb5-1-6/src/lib/kadm5/admin_xdr.h
new file mode 100644
index 000000000..05d1a7ea6
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/admin_xdr.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ * 
+ */
+
+#include    <kadm5/admin.h>
+#include    "kadm_rpc.h"
+#include    "server_internal.h"
+
+bool_t      xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp);
+bool_t	    xdr_nullstring(XDR *xdrs, char **objp);
+bool_t      xdr_nulltype(XDR *xdrs, void **objp, xdrproc_t proc);
+bool_t	    xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp);
+bool_t	    xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp);
+bool_t	    xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp);
+bool_t	    xdr_krb5_flags(XDR *xdrs, krb5_flags *objp);
+bool_t      xdr_krb5_ui_4(XDR *xdrs, krb5_ui_4 *objp);
+bool_t      xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp);
+bool_t      xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp);
+bool_t      xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp);
+bool_t      xdr_krb5_key_salt_tuple(XDR *xdrs, krb5_key_salt_tuple *objp);
+bool_t      xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head);
+bool_t	    xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp);
+bool_t      xdr_kadm5_principal_ent_rec_v1(XDR *xdrs, kadm5_principal_ent_rec *objp);
+bool_t	    xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp);
+bool_t	    xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp);
+bool_t	    xdr_kadm5_policy_ent_t(XDR *xdrs, kadm5_policy_ent_t *objp);
+bool_t	    xdr_kadm5_principal_ent_t(XDR *xdrs, kadm5_principal_ent_t *objp);
+bool_t	    xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp);
+bool_t      xdr_cprinc3_arg(XDR *xdrs, cprinc3_arg *objp);
+bool_t      xdr_generic_ret(XDR *xdrs, generic_ret *objp);
+bool_t	    xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp);
+bool_t	    xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp);
+bool_t	    xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp);
+bool_t	    xdr_chpass_arg(XDR *xdrs, chpass_arg *objp);
+bool_t      xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp);
+bool_t      xdr_setv4key_arg(XDR *xdrs, setv4key_arg *objp);
+bool_t      xdr_setkey_arg(XDR *xdrs, setkey_arg *objp);
+bool_t      xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp);
+bool_t	    xdr_chrand_arg(XDR *xdrs, chrand_arg *objp);
+bool_t      xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp);
+bool_t	    xdr_chrand_ret(XDR *xdrs, chrand_ret *objp);
+bool_t	    xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp);
+bool_t      xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp);
+bool_t	    xdr_gprincs_arg(XDR *xdrs, gprincs_arg *objp);
+bool_t      xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp);
+bool_t	    xdr_cpol_arg(XDR *xdrs, cpol_arg *objp);
+bool_t	    xdr_dpol_arg(XDR *xdrs, dpol_arg *objp);
+bool_t	    xdr_mpol_arg(XDR *xdrs, mpol_arg *objp);
+bool_t	    xdr_gpol_arg(XDR *xdrs, gpol_arg *objp);
+bool_t	    xdr_gpol_ret(XDR *xdrs, gpol_ret *objp);
+bool_t      xdr_gpols_arg(XDR *xdrs, gpols_arg *objp);
+bool_t      xdr_gpols_ret(XDR *xdrs, gpols_ret *objp);
+bool_t      xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp);
+bool_t	    xdr_krb5_principal(XDR *xdrs, krb5_principal *objp);
+bool_t	    xdr_krb5_octet(XDR *xdrs, krb5_octet *objp);
+bool_t	    xdr_krb5_int32(XDR *xdrs, krb5_int32 *objp);
+bool_t	    xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp);
+bool_t      xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp);
+bool_t	    xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp);
+bool_t      xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp);
+bool_t      xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp);
diff --git a/krb5-1-6/src/lib/kadm5/alt_prof.c b/krb5-1-6/src/lib/kadm5/alt_prof.c
new file mode 100644
index 000000000..5567b0c24
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/alt_prof.c
@@ -0,0 +1,1041 @@
+/*
+ * lib/kadm/alt_prof.c
+ *
+ * Copyright 1995,2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * alt_prof.c - Implement alternate profile file handling.
+ */
+#include "k5-int.h"
+#include <kadm5/admin.h>
+#include "adm_proto.h"
+#include <stdio.h>
+#include <ctype.h>
+
+static krb5_key_salt_tuple *copy_key_salt_tuple(ksalt, len)
+krb5_key_salt_tuple *ksalt;
+krb5_int32 len;
+{
+    krb5_key_salt_tuple *knew;    
+
+    if((knew = (krb5_key_salt_tuple *)
+		malloc((len ) * sizeof(krb5_key_salt_tuple)))) {
+         memcpy(knew, ksalt, len * sizeof(krb5_key_salt_tuple));
+	 return knew;
+    }
+    return 0;
+}
+
+/*
+ * krb5_aprof_init()	- Initialize alternate profile context.
+ *
+ * Parameters:
+ *	fname		- default file name of the profile.
+ *	envname		- environment variable name which can override fname.
+ *	acontextp	- Pointer to opaque context for alternate profile.
+ *
+ * Returns:
+ *	error codes from profile_init()
+ */
+krb5_error_code
+krb5_aprof_init(fname, envname, acontextp)
+    char		*fname;
+    char		*envname;
+    krb5_pointer	*acontextp;
+{
+    krb5_error_code	kret;
+    profile_t		profile;
+    const char *kdc_config;
+    size_t krb5_config_len, kdc_config_len;
+    char *profile_path;
+    char **filenames;
+    int i;
+
+    kret = krb5_get_default_config_files (&filenames);
+    if (kret)
+	return kret;
+    krb5_config_len = 0;
+    for (i = 0; filenames[i] != NULL; i++)
+	krb5_config_len += strlen(filenames[i]) + 1;
+    if (i > 0)
+	krb5_config_len--;
+    if (envname == NULL
+	|| (kdc_config = getenv(envname)) == NULL)
+	kdc_config = fname;
+    if (kdc_config == NULL)
+	kdc_config_len = 0;
+    else
+	kdc_config_len = strlen(kdc_config);
+    profile_path = malloc(2 + krb5_config_len + kdc_config_len);
+    if (profile_path == NULL) {
+	krb5_free_config_files(filenames);
+	return errno;
+    }
+    if (kdc_config_len)
+	strcpy(profile_path, kdc_config);
+    else
+	profile_path[0] = 0;
+    if (krb5_config_len)
+	for (i = 0; filenames[i] != NULL; i++) {
+	    if (kdc_config_len || i)
+		strcat(profile_path, ":");
+	    strcat(profile_path, filenames[i]);
+	}
+    krb5_free_config_files(filenames);
+    profile = (profile_t) NULL;
+    kret = profile_init_path(profile_path, &profile);
+    free(profile_path);
+    if (kret)
+	return kret;
+    *acontextp = profile;
+    return 0;
+}
+
+/*
+ * krb5_aprof_getvals()	- Get values from alternate profile.
+ *
+ * Parameters:
+ *	acontext	- opaque context for alternate profile.
+ *	hierarchy	- hierarchy of value to retrieve.
+ *	retdata		- Returned data values.
+ *
+ * Returns:
+ * 	error codes from profile_get_values()
+ */
+krb5_error_code
+krb5_aprof_getvals(acontext, hierarchy, retdata)
+    krb5_pointer	acontext;
+    const char		**hierarchy;
+    char		***retdata;
+{
+    return(profile_get_values((profile_t) acontext,
+			      hierarchy,
+			      retdata));
+}
+
+/*
+ * krb5_aprof_get_boolean()
+ *
+ * Parameters:
+ *	acontext	- opaque context for alternate profile
+ *	hierarchy	- hierarchy of value to retrieve
+ *	retdata		- Returned data value
+ * Returns:
+ *	error codes
+ */
+
+static krb5_error_code
+string_to_boolean (const char *string, krb5_boolean *out)
+{
+    static const char *const yes[] = { "y", "yes", "true", "t", "1", "on" };
+    static const char *const no[] = { "n", "no", "false", "f", "nil", "0", "off" };
+    int i;
+
+    for (i = 0; i < sizeof(yes)/sizeof(yes[0]); i++)
+	if (!strcasecmp(string, yes[i])) {
+	    *out = 1;
+	    return 0;
+	}
+    for (i = 0; i < sizeof(no)/sizeof(no[0]); i++)
+	if (!strcasecmp(string, no[i])) {
+	    *out = 0;
+	    return 0;
+	}
+    return PROF_BAD_BOOLEAN;
+}
+
+krb5_error_code
+krb5_aprof_get_boolean(krb5_pointer acontext, const char **hierarchy,
+		       int uselast, krb5_boolean *retdata)
+{
+    krb5_error_code kret;
+    char **values;
+    char *valp;
+    int idx;
+    krb5_boolean val;
+
+    kret = krb5_aprof_getvals (acontext, hierarchy, &values);
+    if (kret)
+	return kret;
+    idx = 0;
+    if (uselast) {
+	while (values[idx])
+	    idx++;
+	idx--;
+    }
+    valp = values[idx];
+    kret = string_to_boolean (valp, &val);
+    if (kret)
+	return kret;
+    *retdata = val;
+    return 0;
+}
+
+/*
+ * krb5_aprof_get_deltat()	- Get a delta time value from the alternate
+ *				  profile.
+ *
+ * Parameters:
+ *	acontext		- opaque context for alternate profile.
+ *	hierarchy		- hierarchy of value to retrieve.
+ *	uselast			- if true, use last value, otherwise use
+ *				  first value found.
+ *	deltatp			- returned delta time value.
+ *
+ * Returns:
+ * 	error codes from profile_get_values()
+ *	error codes from krb5_string_to_deltat()
+ */
+krb5_error_code
+krb5_aprof_get_deltat(acontext, hierarchy, uselast, deltatp)
+    krb5_pointer	acontext;
+    const char		**hierarchy;
+    krb5_boolean	uselast;
+    krb5_deltat		*deltatp;
+{
+    krb5_error_code	kret;
+    char		**values;
+    char		*valp;
+    int			idx;
+
+    if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
+	idx = 0;
+	if (uselast) {
+	    for (idx=0; values[idx]; idx++);
+	    idx--;
+	}
+	valp = values[idx];
+	kret = krb5_string_to_deltat(valp, deltatp);
+
+	/* Free the string storage */
+	for (idx=0; values[idx]; idx++)
+	    krb5_xfree(values[idx]);
+	krb5_xfree(values);
+    }
+    return(kret);
+}
+
+/*
+ * krb5_aprof_get_string()	- Get a string value from the alternate
+ *				  profile.
+ *
+ * Parameters:
+ *	acontext		- opaque context for alternate profile.
+ *	hierarchy		- hierarchy of value to retrieve.
+ *	uselast			- if true, use last value, otherwise use
+ *				  first value found.
+ *	stringp			- returned string value.
+ *
+ * Returns:
+ * 	error codes from profile_get_values()
+ */
+krb5_error_code
+krb5_aprof_get_string(acontext, hierarchy, uselast, stringp)
+    krb5_pointer	acontext;
+    const char		**hierarchy;
+    krb5_boolean	uselast;
+    char		**stringp;
+{
+    krb5_error_code	kret;
+    char		**values;
+    int			idx, i;
+
+    if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
+	idx = 0;
+	if (uselast) {
+	    for (idx=0; values[idx]; idx++);
+	    idx--;
+	}
+
+	*stringp = values[idx];
+
+	/* Free the string storage */
+	for (i=0; values[i]; i++)
+	    if (i != idx)
+		krb5_xfree(values[i]);
+	krb5_xfree(values);
+    }
+    return(kret);
+}
+
+/*
+ * krb5_aprof_get_int32()	- Get a 32-bit integer value from the alternate
+ *				  profile.
+ *
+ * Parameters:
+ *	acontext		- opaque context for alternate profile.
+ *	hierarchy		- hierarchy of value to retrieve.
+ *	uselast			- if true, use last value, otherwise use
+ *				  first value found.
+ *	intp			- returned 32-bit integer value.
+ *
+ * Returns:
+ * 	error codes from profile_get_values()
+ *	EINVAL			- value is not an integer
+ */
+krb5_error_code
+krb5_aprof_get_int32(acontext, hierarchy, uselast, intp)
+    krb5_pointer	acontext;
+    const char		**hierarchy;
+    krb5_boolean	uselast;
+    krb5_int32		*intp;
+{
+    krb5_error_code	kret;
+    char		**values;
+    int			idx;
+
+    if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
+	idx = 0;
+	if (uselast) {
+	    for (idx=0; values[idx]; idx++);
+	    idx--;
+	}
+
+	if (sscanf(values[idx], "%d", intp) != 1)
+	    kret = EINVAL;
+
+	/* Free the string storage */
+	for (idx=0; values[idx]; idx++)
+	    krb5_xfree(values[idx]);
+	krb5_xfree(values);
+    }
+    return(kret);
+}
+
+/*
+ * krb5_aprof_finish()	- Finish alternate profile context.
+ *
+ * Parameter:
+ *	acontext	- opaque context for alternate profile.
+ *
+ * Returns:
+ *	0 on success, something else on failure.
+ */
+krb5_error_code
+krb5_aprof_finish(acontext)
+    krb5_pointer	acontext;
+{
+    profile_release(acontext);
+    return(0);
+}
+
+/*
+ * Function: kadm5_get_config_params
+ *
+ * Purpose: Merge configuration parameters provided by the caller with
+ * values specified in configuration files and with default values.
+ *
+ * Arguments:
+ *
+ *	context		(r) krb5_context to use
+ *	profile		(r) profile file to use
+ *	envname		(r) envname that contains a profile name to
+ *			override profile
+ *	params_in	(r) params structure containing user-supplied
+ *			values, or NULL
+ *	params_out	(w) params structure to be filled in
+ *
+ * Effects:
+ *
+ * The fields and mask of params_out are filled in with values
+ * obtained from params_in, the specified profile, and default
+ * values.  Only and all fields specified in params_out->mask are
+ * set.  The context of params_out must be freed with
+ * kadm5_free_config_params.
+ *
+ * params_in and params_out may be the same pointer.  However, all pointers
+ * in params_in for which the mask is set will be re-assigned to newly copied
+ * versions, overwriting the old pointer value.
+ */
+krb5_error_code kadm5_get_config_params(context, use_kdc_config,
+					params_in, params_out)
+   krb5_context		context;
+   int			use_kdc_config;
+   kadm5_config_params	*params_in, *params_out;
+{
+    char		*filename;
+    char		*envname;
+    char		*lrealm;
+    krb5_pointer	aprofile = 0;
+    const char		*hierarchy[4];
+    char		*svalue;
+    krb5_int32		ivalue;
+    krb5_deltat		dtvalue;
+    kadm5_config_params params, empty_params;
+
+    krb5_error_code	kret = 0;
+
+    memset((char *) ¶ms, 0, sizeof(params));
+    memset((char *) &empty_params, 0, sizeof(empty_params));
+
+    if (params_in == NULL) params_in = &empty_params;
+
+    if (params_in->mask & KADM5_CONFIG_REALM) {
+	 lrealm = params.realm = strdup(params_in->realm);
+	 if (params.realm)
+	      params.mask |= KADM5_CONFIG_REALM;
+    } else {
+	 kret = krb5_get_default_realm(context, &lrealm);
+	 if (kret)
+	      goto cleanup;
+	 params.realm = lrealm;
+	 params.mask |= KADM5_CONFIG_REALM;
+    }
+    /*
+     * XXX These defaults should to work on both client and
+     * server.  kadm5_get_config_params can be implemented as a
+     * wrapper function in each library that provides correct
+     * defaults for NULL values.
+     */
+    if (use_kdc_config) {
+	filename = DEFAULT_KDC_PROFILE;
+	envname = KDC_PROFILE_ENV;
+    } else {
+	filename = DEFAULT_PROFILE_PATH;
+	envname = "KRB5_CONFIG";
+    }
+    if (context->profile_secure == TRUE) envname = 0;
+
+    kret = krb5_aprof_init(filename, envname, &aprofile);
+    if (kret)
+	    goto cleanup;
+    
+    /* Initialize realm parameters */
+    hierarchy[0] = "realms";
+    hierarchy[1] = lrealm;
+    hierarchy[3] = (char *) NULL;
+
+    /* Get the value for the admin server */
+    hierarchy[2] = "admin_server";
+    if (params_in->mask & KADM5_CONFIG_ADMIN_SERVER) {
+	 params.admin_server = strdup(params_in->admin_server);
+	 if (params.admin_server)
+	      params.mask |= KADM5_CONFIG_ADMIN_SERVER;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 params.admin_server = svalue;
+	 params.mask |= KADM5_CONFIG_ADMIN_SERVER;
+    }
+    if (params.mask & KADM5_CONFIG_ADMIN_SERVER) {
+	 char *p;
+	 p = strchr(params.admin_server, ':');
+	 if (p) {
+	      params.kadmind_port = atoi(p+1);
+	      params.mask |= KADM5_CONFIG_KADMIND_PORT;
+	      *p = '\0';
+	 }
+    }
+
+    /* Get the value for the database */
+    hierarchy[2] = "database_name";
+    if (params_in->mask & KADM5_CONFIG_DBNAME) {
+	 params.dbname = strdup(params_in->dbname);
+	 if (params.dbname)
+	      params.mask |= KADM5_CONFIG_DBNAME;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 params.dbname = svalue;
+	 params.mask |= KADM5_CONFIG_DBNAME;
+    } else {
+	 params.dbname = strdup(DEFAULT_KDB_FILE);
+	 if (params.dbname) 
+	      params.mask |= KADM5_CONFIG_DBNAME;
+    }
+
+    /*
+     * admin database name and lockfile are now always derived from dbname
+     */
+    if (params.mask & KADM5_CONFIG_DBNAME) {
+	 params.admin_dbname = (char *) malloc(strlen(params.dbname) + 7);
+	 if (params.admin_dbname) {
+	      sprintf(params.admin_dbname, "%s.kadm5", params.dbname);
+	      params.mask |= KADM5_CONFIG_ADBNAME;
+	 }
+    }
+
+    if (params.mask & KADM5_CONFIG_ADBNAME) {
+	 params.admin_lockfile = (char *) malloc(strlen(params.admin_dbname)
+						 + 6);
+	 if (params.admin_lockfile) {
+	      sprintf(params.admin_lockfile, "%s.lock", params.admin_dbname);
+	      params.mask |= KADM5_CONFIG_ADB_LOCKFILE;
+	 }
+    }
+    
+    /* Get the value for the admin (policy) database lock file*/
+    hierarchy[2] = "admin_keytab";
+    if (params_in->mask & KADM5_CONFIG_ADMIN_KEYTAB) {
+	 params.admin_keytab = strdup(params_in->admin_keytab);
+	 if (params.admin_keytab)
+	      params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
+	 params.admin_keytab = svalue;
+    } else if ((params.admin_keytab = (char *) getenv("KRB5_KTNAME"))) {
+	 params.admin_keytab = strdup(params.admin_keytab);
+	 if (params.admin_keytab)
+	      params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
+    } else {
+	 params.admin_keytab = strdup(DEFAULT_KADM5_KEYTAB);
+	 if (params.admin_keytab)
+	      params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
+    }
+    
+    /* Get the name of the acl file */
+    hierarchy[2] = "acl_file";
+    if (params_in->mask & KADM5_CONFIG_ACL_FILE) {
+	 params.acl_file = strdup(params_in->acl_file);
+	 if (params.acl_file)
+	      params.mask |= KADM5_CONFIG_ACL_FILE;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 params.mask |= KADM5_CONFIG_ACL_FILE;
+	 params.acl_file = svalue;
+    } else {
+	 params.acl_file = strdup(DEFAULT_KADM5_ACL_FILE);
+	 if (params.acl_file)
+	      params.mask |= KADM5_CONFIG_ACL_FILE;
+    }
+    
+    /* Get the name of the dict file */
+    hierarchy[2] = "dict_file";
+    if (params_in->mask & KADM5_CONFIG_DICT_FILE) {
+	 params.dict_file = strdup(params_in->dict_file);
+	 if (params.dict_file)
+	      params.mask |= KADM5_CONFIG_DICT_FILE;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 params.mask |= KADM5_CONFIG_DICT_FILE;
+	 params.dict_file = svalue;
+    }
+	    
+    /* Get the value for the kadmind port */
+    if (! (params.mask & KADM5_CONFIG_KADMIND_PORT)) {
+	 hierarchy[2] = "kadmind_port";
+	 if (params_in->mask & KADM5_CONFIG_KADMIND_PORT) {
+	      params.mask |= KADM5_CONFIG_KADMIND_PORT;
+	      params.kadmind_port = params_in->kadmind_port;
+	 } else if (aprofile &&
+		    !krb5_aprof_get_int32(aprofile, hierarchy, TRUE,
+					  &ivalue)) { 
+	      params.kadmind_port = ivalue;
+	      params.mask |= KADM5_CONFIG_KADMIND_PORT;
+	 } else {
+	      params.kadmind_port = DEFAULT_KADM5_PORT;
+	      params.mask |= KADM5_CONFIG_KADMIND_PORT;
+	 }
+    }
+    
+    /* Get the value for the kpasswd port */
+    if (! (params.mask & KADM5_CONFIG_KPASSWD_PORT)) {
+	hierarchy[2] = "kpasswd_port";
+	if (params_in->mask & KADM5_CONFIG_KPASSWD_PORT) {
+	    params.mask |= KADM5_CONFIG_KPASSWD_PORT;
+	    params.kpasswd_port = params_in->kpasswd_port;
+	} else if (aprofile &&
+		   !krb5_aprof_get_int32(aprofile, hierarchy, TRUE,
+					 &ivalue)) { 
+	    params.kpasswd_port = ivalue;
+	    params.mask |= KADM5_CONFIG_KPASSWD_PORT;
+	} else {
+	    params.kpasswd_port = DEFAULT_KPASSWD_PORT;
+	    params.mask |= KADM5_CONFIG_KPASSWD_PORT;
+	}
+    }
+    
+    /* Get the value for the master key name */
+	 hierarchy[2] = "master_key_name";
+    if (params_in->mask & KADM5_CONFIG_MKEY_NAME) {
+	 params.mkey_name = strdup(params_in->mkey_name);
+	 if (params.mkey_name)
+	      params.mask |= KADM5_CONFIG_MKEY_NAME;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 params.mask |= KADM5_CONFIG_MKEY_NAME;
+	 params.mkey_name = svalue;
+    }
+    
+    /* Get the value for the master key type */
+    hierarchy[2] = "master_key_type";
+    if (params_in->mask & KADM5_CONFIG_ENCTYPE) {
+	 params.mask |= KADM5_CONFIG_ENCTYPE;
+	 params.enctype = params_in->enctype;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 if (!krb5_string_to_enctype(svalue, ¶ms.enctype)) {
+	      params.mask |= KADM5_CONFIG_ENCTYPE;
+	      krb5_xfree(svalue);
+	 }
+    } else {
+	 params.mask |= KADM5_CONFIG_ENCTYPE;
+	 params.enctype = DEFAULT_KDC_ENCTYPE;
+    }
+    
+    /* Get the value for mkey_from_kbd */
+    if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) {
+	 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+	 params.mkey_from_kbd = params_in->mkey_from_kbd;
+    }
+    
+    /* Get the value for the stashfile */
+    hierarchy[2] = "key_stash_file";
+    if (params_in->mask & KADM5_CONFIG_STASH_FILE) {
+	 params.stash_file = strdup(params_in->stash_file);
+	 if (params.stash_file)
+	      params.mask |= KADM5_CONFIG_STASH_FILE;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 params.mask |= KADM5_CONFIG_STASH_FILE;
+	 params.stash_file = svalue;
+    }
+
+    /* Get the value for maximum ticket lifetime. */
+    hierarchy[2] = "max_life";
+    if (params_in->mask & KADM5_CONFIG_MAX_LIFE) {
+	 params.mask |= KADM5_CONFIG_MAX_LIFE;
+	 params.max_life = params_in->max_life;
+    } else if (aprofile &&
+	       !krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+	 params.max_life = dtvalue;
+	 params.mask |= KADM5_CONFIG_MAX_LIFE;
+    } else {
+	 params.max_life = 24 * 60 * 60; /* 1 day */
+	 params.mask |= KADM5_CONFIG_MAX_LIFE;
+    }	 
+	    
+    /* Get the value for maximum renewable ticket lifetime. */
+    hierarchy[2] = "max_renewable_life";
+    if (params_in->mask & KADM5_CONFIG_MAX_RLIFE) {
+	 params.mask |= KADM5_CONFIG_MAX_RLIFE;
+	 params.max_rlife = params_in->max_rlife;
+    } else if (aprofile &&
+	       !krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+	 params.max_rlife = dtvalue;
+	 params.mask |= KADM5_CONFIG_MAX_RLIFE;
+    } else {
+	 params.max_rlife = 0;
+	 params.mask |= KADM5_CONFIG_MAX_RLIFE;
+    }
+	    
+    /* Get the value for the default principal expiration */
+    hierarchy[2] = "default_principal_expiration";
+    if (params_in->mask & KADM5_CONFIG_EXPIRATION) {
+	 params.mask |= KADM5_CONFIG_EXPIRATION;
+	 params.expiration = params_in->expiration;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 if (!krb5_string_to_timestamp(svalue, ¶ms.expiration)) {
+	      params.mask |= KADM5_CONFIG_EXPIRATION;
+	      krb5_xfree(svalue);
+	 }
+    } else {
+	 params.mask |= KADM5_CONFIG_EXPIRATION;
+	 params.expiration = 0;
+    }
+    
+    /* Get the value for the default principal flags */
+    hierarchy[2] = "default_principal_flags";
+    if (params_in->mask & KADM5_CONFIG_FLAGS) {
+	 params.mask |= KADM5_CONFIG_FLAGS;
+	 params.flags = params_in->flags;
+    } else if (aprofile &&
+	       !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	 char *sp, *ep, *tp;
+	 
+	 sp = svalue;
+	 params.flags = 0;
+	 while (sp) {
+	      if ((ep = strchr(sp, (int) ',')) ||
+		  (ep = strchr(sp, (int) ' ')) ||
+		  (ep = strchr(sp, (int) '\t'))) {
+		   /* Fill in trailing whitespace of sp */
+		   tp = ep - 1;
+		   while (isspace((int) *tp) && (tp > sp)) {
+			*tp = '\0';
+			tp--;
+		   }
+		   *ep = '\0';
+		   ep++;
+		   /* Skip over trailing whitespace of ep */
+		   while (isspace((int) *ep) && (*ep)) ep++;
+	      }
+	      /* Convert this flag */
+	      if (krb5_string_to_flags(sp,
+				       "+",
+				       "-",
+				       ¶ms.flags))
+		   break;
+	      sp = ep;
+	 }
+	 if (!sp)
+	      params.mask |= KADM5_CONFIG_FLAGS;
+	 krb5_xfree(svalue);
+    } else {
+	 params.mask |= KADM5_CONFIG_FLAGS;
+	 params.flags = KRB5_KDB_DEF_FLAGS;
+    }
+
+    /* Get the value for the supported enctype/salttype matrix */
+    hierarchy[2] = "supported_enctypes";
+    if (params_in->mask & KADM5_CONFIG_ENCTYPES) {
+         /* The following scenario is when the input keysalts are !NULL */
+         if(params_in->keysalts) {
+	       params.keysalts = copy_key_salt_tuple(params_in->keysalts, 
+						     params_in->num_keysalts);
+	       if(params.keysalts) {
+		 params.mask |= KADM5_CONFIG_ENCTYPES;
+		 params.num_keysalts = params_in->num_keysalts;
+	       }
+	 } else {
+		 params.mask |= KADM5_CONFIG_ENCTYPES;
+		 params.keysalts = 0;
+		 params.num_keysalts = params_in->num_keysalts;
+	 }
+    } else {
+	 svalue = NULL;
+	 if (aprofile)
+	      krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);
+	 if (svalue == NULL)
+	     svalue = strdup("des3-hmac-sha1:normal des-cbc-crc:normal");
+
+	 params.keysalts = NULL;
+	 params.num_keysalts = 0;
+	 krb5_string_to_keysalts(svalue,
+				 ", \t",/* Tuple separators	*/
+				 ":.-",	/* Key/salt separators	*/
+				 0,	/* No duplicates	*/
+				 ¶ms.keysalts,
+				 ¶ms.num_keysalts);
+	 if (params.num_keysalts)
+	      params.mask |= KADM5_CONFIG_ENCTYPES;
+
+	 if (svalue)
+	      krb5_xfree(svalue);
+    }
+    
+    *params_out = params;
+    
+cleanup:
+    if (aprofile)
+	krb5_aprof_finish(aprofile);
+    if (kret) {
+	 kadm5_free_config_params(context, ¶ms);
+	 params_out->mask = 0;
+    }
+    return(kret);
+}
+/*
+ * kadm5_free_config_params()	- Free data allocated by above.
+ */
+krb5_error_code
+kadm5_free_config_params(context, params)
+    krb5_context	context;
+    kadm5_config_params	*params;
+{
+    if (params) {
+	if (params->dbname)
+	    krb5_xfree(params->dbname);
+	if (params->mkey_name)
+	    krb5_xfree(params->mkey_name);
+	if (params->stash_file)
+	    krb5_xfree(params->stash_file);
+	if (params->keysalts)
+	    krb5_xfree(params->keysalts);
+	if (params->admin_server)
+	     free(params->admin_server);
+	if (params->admin_keytab)
+	     free(params->admin_keytab);
+	if (params->dict_file)
+	     free(params->dict_file);
+	if (params->acl_file)
+	     free(params->acl_file);
+	if (params->realm)
+	     free(params->realm);
+	if (params->admin_dbname)
+	     free(params->admin_dbname);
+	if (params->admin_lockfile)
+	     free(params->admin_lockfile);
+
+    }
+    return(0);
+}
+
+krb5_error_code
+kadm5_get_admin_service_name(krb5_context ctx,
+			     char *realm_in,
+			     char *admin_name,
+			     size_t maxlen)
+{
+    krb5_error_code ret;
+    kadm5_config_params params_in, params_out;
+    struct hostent *hp;
+
+    memset(¶ms_in, 0, sizeof(params_in));
+    memset(¶ms_out, 0, sizeof(params_out));
+
+    params_in.mask |= KADM5_CONFIG_REALM;
+    params_in.realm = realm_in;
+    ret = kadm5_get_config_params(ctx, 0, ¶ms_in, ¶ms_out);
+    if (ret)
+	return ret;
+
+    if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) {
+	ret = KADM5_MISSING_KRB5_CONF_PARAMS;
+	goto err_params;
+    }
+
+    hp = gethostbyname(params_out.admin_server);
+    if (hp == NULL) {
+	ret = errno;
+	goto err_params;
+    }
+    if (strlen(hp->h_name) + sizeof("kadmin/") > maxlen) {
+	ret = ENOMEM;
+	goto err_params;
+    }
+    sprintf(admin_name, "kadmin/%s", hp->h_name);
+
+err_params:
+    kadm5_free_config_params(ctx, ¶ms_out);
+    return ret;
+}
+
+/***********************************************************************
+ * This is the old krb5_realm_read_params, which I mutated into
+ * kadm5_get_config_params but which old code (kdb5_* and krb5kdc)
+ * still uses.
+ ***********************************************************************/
+
+/*
+ * krb5_read_realm_params()	- Read per-realm parameters from KDC
+ *				  alternate profile.
+ */
+krb5_error_code
+krb5_read_realm_params(kcontext, realm, rparamp)
+    krb5_context	kcontext;
+    char		*realm;
+    krb5_realm_params	**rparamp;
+{
+    char		*filename;
+    char		*envname;
+    char		*lrealm;
+    krb5_pointer	aprofile = 0;
+    krb5_realm_params	*rparams;
+    const char		*hierarchy[4];
+    char		*svalue;
+    krb5_int32		ivalue;
+    krb5_boolean	bvalue;
+    krb5_deltat		dtvalue;
+
+    char		*kdcprofile = 0;
+    char		*kdcenv = 0;
+
+    krb5_error_code	kret;
+
+    filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
+    envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV;
+
+    if (kcontext->profile_secure == TRUE) envname = 0;
+
+    rparams = (krb5_realm_params *) NULL;
+    if (realm)
+	lrealm = strdup(realm);
+    else {
+	kret = krb5_get_default_realm(kcontext, &lrealm);
+	if (kret)
+	    goto cleanup;
+    }
+
+    kret = krb5_aprof_init(filename, envname, &aprofile);
+    if (kret)
+	goto cleanup;
+    
+    rparams = (krb5_realm_params *) malloc(sizeof(krb5_realm_params));
+    if (rparams == 0) {
+	kret = ENOMEM;
+	goto cleanup;
+    }
+
+    /* Initialize realm parameters */
+    memset((char *) rparams, 0, sizeof(krb5_realm_params));
+
+    /* Get the value for the database */
+    hierarchy[0] = "realms";
+    hierarchy[1] = lrealm;
+    hierarchy[2] = "database_name";
+    hierarchy[3] = (char *) NULL;
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+	rparams->realm_dbname = svalue;
+	
+    /* Get the value for the KDC port list */
+    hierarchy[2] = "kdc_ports";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+	rparams->realm_kdc_ports = svalue;
+    hierarchy[2] = "kdc_tcp_ports";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+	rparams->realm_kdc_tcp_ports = svalue;
+
+    /* Get the name of the acl file */
+    hierarchy[2] = "acl_file";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+	rparams->realm_acl_file = svalue;
+	    
+    /* Get the value for the kadmind port */
+    hierarchy[2] = "kadmind_port";
+    if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {
+	rparams->realm_kadmind_port = ivalue;
+	rparams->realm_kadmind_port_valid = 1;
+    }
+	    
+    /* Get the value for the master key name */
+    hierarchy[2] = "master_key_name";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+	rparams->realm_mkey_name = svalue;
+	    
+    /* Get the value for the master key type */
+    hierarchy[2] = "master_key_type";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	if (!krb5_string_to_enctype(svalue, &rparams->realm_enctype))
+	    rparams->realm_enctype_valid = 1;
+	krb5_xfree(svalue);
+    }
+	    
+    /* Get the value for the stashfile */
+    hierarchy[2] = "key_stash_file";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+	rparams->realm_stash_file = svalue;
+	    
+    /* Get the value for maximum ticket lifetime. */
+    hierarchy[2] = "max_life";
+    if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+	rparams->realm_max_life = dtvalue;
+	rparams->realm_max_life_valid = 1;
+    }
+	    
+    /* Get the value for maximum renewable ticket lifetime. */
+    hierarchy[2] = "max_renewable_life";
+    if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+	rparams->realm_max_rlife = dtvalue;
+	rparams->realm_max_rlife_valid = 1;
+    }
+	    
+    /* Get the value for the default principal expiration */
+    hierarchy[2] = "default_principal_expiration";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	if (!krb5_string_to_timestamp(svalue,
+				      &rparams->realm_expiration))
+	    rparams->realm_expiration_valid = 1;
+	krb5_xfree(svalue);
+    }
+
+    hierarchy[2] = "reject_bad_transit";
+    if (!krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) {
+	rparams->realm_reject_bad_transit = bvalue;
+	rparams->realm_reject_bad_transit_valid = 1;
+    }
+
+    /* Get the value for the default principal flags */
+    hierarchy[2] = "default_principal_flags";
+    if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+	char *sp, *ep, *tp;
+
+	sp = svalue;
+	rparams->realm_flags = 0;
+	while (sp) {
+	    if ((ep = strchr(sp, (int) ',')) ||
+		(ep = strchr(sp, (int) ' ')) ||
+		(ep = strchr(sp, (int) '\t'))) {
+		/* Fill in trailing whitespace of sp */
+		tp = ep - 1;
+		while (isspace((int) *tp) && (tp < sp)) {
+		    *tp = '\0';
+		    tp--;
+		}
+		*ep = '\0';
+		ep++;
+		/* Skip over trailing whitespace of ep */
+		while (isspace((int) *ep) && (*ep)) ep++;
+	    }
+	    /* Convert this flag */
+	    if (krb5_string_to_flags(sp,
+				     "+",
+				     "-",
+				     &rparams->realm_flags))
+		break;
+	    sp = ep;
+	}
+	if (!sp)
+	    rparams->realm_flags_valid = 1;
+	krb5_xfree(svalue);
+    }
+
+    rparams->realm_keysalts = NULL;
+    rparams->realm_num_keysalts = 0;
+
+cleanup:
+    if (aprofile)
+	krb5_aprof_finish(aprofile);
+    if (lrealm)
+	free(lrealm);
+    if (kret) {
+	if (rparams)
+	    krb5_free_realm_params(kcontext, rparams);
+	rparams = 0;
+    }
+    *rparamp = rparams;
+    return(kret);
+}
+
+/*
+ * krb5_free_realm_params()	- Free data allocated by above.
+ */
+krb5_error_code
+krb5_free_realm_params(kcontext, rparams)
+    krb5_context	kcontext;
+    krb5_realm_params	*rparams;
+{
+    if (rparams) {
+	if (rparams->realm_profile)
+	    krb5_xfree(rparams->realm_profile);
+	if (rparams->realm_dbname)
+	    krb5_xfree(rparams->realm_dbname);
+	if (rparams->realm_mkey_name)
+	    krb5_xfree(rparams->realm_mkey_name);
+	if (rparams->realm_stash_file)
+	    krb5_xfree(rparams->realm_stash_file);
+	if (rparams->realm_keysalts)
+	    krb5_xfree(rparams->realm_keysalts);
+	if (rparams->realm_kdc_ports)
+	    krb5_xfree(rparams->realm_kdc_ports);
+	if (rparams->realm_kdc_tcp_ports)
+	    krb5_xfree(rparams->realm_kdc_tcp_ports);
+	if (rparams->realm_acl_file)
+	    krb5_xfree(rparams->realm_acl_file);
+	krb5_xfree(rparams);
+    }
+    return(0);
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/chpass_util.c b/krb5-1-6/src/lib/kadm5/chpass_util.c
new file mode 100644
index 000000000..dc6ebb61b
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/chpass_util.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ */
+
+
+#include <stdio.h>
+#include "autoconf.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <time.h>
+
+#include <kadm5/admin.h>
+#include "admin_internal.h"
+
+#include <krb5.h>
+
+#define string_text error_message
+
+/*
+ * Function: kadm5_chpass_principal_util
+ *
+ * Purpose: Wrapper around chpass_principal. We can read new pw, change pw and return useful messages
+ *
+ * Arguments:
+ *
+ *      princ          (input) a krb5b_principal structure for the 
+ *                     principal whose password we should change.
+ *
+ *      new_password   (input) NULL or a null terminated string with the 
+ *                     the principal's desired new password.  If new_password
+ *                     is NULL then this routine will read a new password.
+ *    
+ *	pw_ret		(output) if non-NULL, points to a static buffer
+ *			containing the new password (if password is prompted
+ *			internally), or to the new_password argument (if
+ *			that is non-NULL).  If the former, then the buffer
+ *			is only valid until the next call to the function,
+ *			and the caller should be sure to zero it when
+ *			it is no longer needed.
+ *
+ *      msg_ret         (output) a useful message is copied here.
+ *
+ *      <return value>  exit status of 0 for success, else the com err code 
+ *                      for the last significant routine called.
+ *      
+ * Requires:
+ *      
+ *      A msg_ret should point to a buffer large enough for the messasge.
+ *
+ * Effects:
+ *      
+ * Modifies:
+ *
+ *
+ */
+
+kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
+					 void *lhandle,
+					 krb5_principal princ,
+					 char *new_pw, 
+					 char **ret_pw,
+					 char *msg_ret,
+					 unsigned int msg_len)
+{
+  int code, code2;
+  unsigned int pwsize;
+  static char buffer[255];
+  char *new_password;
+  kadm5_principal_ent_rec princ_ent;
+  kadm5_policy_ent_rec policy_ent;
+
+  _KADM5_CHECK_HANDLE(server_handle);
+
+  if (ret_pw)
+    *ret_pw = NULL;
+
+  if (new_pw != NULL) {
+    new_password = new_pw;
+  } else { /* read the password */
+    krb5_context context;
+
+    if ((code = (int) kadm5_init_krb5_context(&context)) == 0) {
+      pwsize = sizeof(buffer);
+      code = krb5_read_password(context, KADM5_PW_FIRST_PROMPT,
+				KADM5_PW_SECOND_PROMPT,
+				buffer, &pwsize);
+      krb5_free_context(context);
+    }
+
+    if (code == 0) 
+      new_password = buffer;
+    else {
+#ifdef ZEROPASSWD    
+      memset(buffer, 0, sizeof(buffer));
+#endif      
+      if (code == KRB5_LIBOS_BADPWDMATCH) {
+	strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH),
+		msg_len - 1);
+	msg_ret[msg_len - 1] = '\0';
+	return(code);
+      } else {
+        strncpy(msg_ret, error_message(code), msg_len - 1);
+        strncat(msg_ret, " ", msg_len - 1);
+        strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),
+		msg_len - 1);
+        strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
+		msg_len - 1);
+	msg_ret[msg_len - 1] = '\0';
+	return(code);
+      }
+    }
+    if (pwsize == 0) {
+#ifdef ZEROPASSWD    
+      memset(buffer, 0, sizeof(buffer));
+#endif      
+      strncpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ), msg_len - 1);
+      msg_ret[msg_len - 1] = '\0';
+      return(KRB5_LIBOS_CANTREADPWD); /* could do better */
+    }
+  }
+
+  if (ret_pw)
+    *ret_pw = new_password;
+
+  code = kadm5_chpass_principal(server_handle, princ, new_password);
+
+#ifdef ZEROPASSWD
+  if (!ret_pw)
+    memset(buffer, 0, sizeof(buffer)); /* in case we read a new password */
+#endif    
+
+  if (code == KADM5_OK) {
+    strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED), msg_len - 1);
+    msg_ret[msg_len - 1] = '\0';
+    return(0);
+  }
+
+  if ((code != KADM5_PASS_Q_TOOSHORT) && 
+      (code != KADM5_PASS_REUSE) &&(code != KADM5_PASS_Q_CLASS) && 
+      (code != KADM5_PASS_Q_DICT) && (code != KADM5_PASS_TOOSOON)) {
+    /* Can't get more info for other errors */
+    sprintf(buffer, "%s %s", error_message(code), 
+	    string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
+    sprintf(msg_ret, "%s\n%s\n", string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED), 
+	    buffer);
+    return(code);
+  }
+
+  /* Ok, we have a password quality error. Return a good message */
+
+  if (code == KADM5_PASS_REUSE) {
+    strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE), msg_len - 1);
+    msg_ret[msg_len - 1] = '\0';
+    return(code);
+  }
+
+  if (code == KADM5_PASS_Q_DICT) {
+    strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY),
+	    msg_len - 1);
+    msg_ret[msg_len - 1] = '\0';
+    return(code);
+  }
+  
+  /* Look up policy for the remaining messages */
+
+  code2 = kadm5_get_principal (lhandle, princ, &princ_ent,
+			       KADM5_PRINCIPAL_NORMAL_MASK);
+  if (code2 != 0) {
+    strncpy(msg_ret, error_message(code2), msg_len - 1);
+    strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, string_text(CHPASS_UTIL_GET_PRINC_INFO), msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, "\n", msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, error_message(code), msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
+	    msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, "\n\n", msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
+	    msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, "\n", msg_len - 1 - strlen(msg_ret));
+    msg_ret[msg_len - 1] = '\0';
+    return(code);
+  }
+  
+  if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) {
+    strncpy(msg_ret, error_message(code), msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret));
+    strncpy(msg_ret, string_text(CHPASS_UTIL_NO_POLICY_YET_Q_ERROR),
+	    msg_len - 1 - strlen(msg_ret));
+    strncat(msg_ret, "\n\n", msg_len - 1 - strlen(msg_ret));
+    strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
+	    msg_len - 1 - strlen(msg_ret));
+    msg_ret[msg_len - 1] = '\0';
+
+    (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+    return(code);
+  }
+
+  code2 = kadm5_get_policy(lhandle, princ_ent.policy,
+			   &policy_ent);
+  if (code2 != 0) {
+    sprintf(msg_ret, "%s %s\n%s %s\n\n%s\n ", error_message(code2), 
+	    string_text(CHPASS_UTIL_GET_POLICY_INFO),
+	    error_message(code),
+	    string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
+	    string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
+    (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+    return(code);
+  }
+  
+  if (code == KADM5_PASS_Q_TOOSHORT) {
+    sprintf(msg_ret, string_text(CHPASS_UTIL_PASSWORD_TOO_SHORT), 
+	    policy_ent.pw_min_length);
+    (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+    (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+    return(code);
+  }
+
+/* Can't get more info for other errors */
+
+  if (code == KADM5_PASS_Q_CLASS) {
+    sprintf(msg_ret, string_text(CHPASS_UTIL_TOO_FEW_CLASSES), 
+	    policy_ent.pw_min_classes);
+    (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+    (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+    return(code);
+  }
+
+  if (code == KADM5_PASS_TOOSOON) {
+    time_t until;
+    char *time_string, *ptr;
+
+    until = princ_ent.last_pwd_change + policy_ent.pw_min_life;
+
+    time_string = ctime(&until);
+    if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
+      *ptr = '\0';
+
+    sprintf(msg_ret, string_text(CHPASS_UTIL_PASSWORD_TOO_SOON), 
+	    time_string);
+    (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+    (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+    return(code);
+  }
+
+  /* We should never get here, but just in case ... */
+  sprintf(buffer, "%s %s", error_message(code), 
+	  string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
+  sprintf(msg_ret, "%s\n%s\n", string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED), 
+	  buffer);
+  (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+  (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+  return(code);
+}
diff --git a/krb5-1-6/src/lib/kadm5/chpass_util_strings.et b/krb5-1-6/src/lib/kadm5/chpass_util_strings.et
new file mode 100644
index 000000000..c65010ae1
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/chpass_util_strings.et
@@ -0,0 +1,58 @@
+# this is really a string table for ovsec_kadm_chpass_principal_util
+
+error_table ovku
+
+error_code CHPASS_UTIL_GET_POLICY_INFO, "while getting policy info."
+error_code CHPASS_UTIL_GET_PRINC_INFO, "while getting principal info."
+error_code CHPASS_UTIL_NEW_PASSWORD_MISMATCH, 
+	"New passwords do not match - password not changed.\n"
+
+error_code CHPASS_UTIL_NEW_PASSWORD_PROMPT, "New password"
+error_code CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT, "New password (again)"
+error_code CHPASS_UTIL_NO_PASSWORD_READ, "You must type a password. Passwords must be at least one character long.\n"
+error_code CHPASS_UTIL_NO_POLICY_YET_Q_ERROR, 
+"yet no policy set!  Contact your system security administrator."
+
+error_code CHPASS_UTIL_PASSWORD_CHANGED, "Password changed.\n"
+
+error_code CHPASS_UTIL_PASSWORD_IN_DICTIONARY,
+"New password was found in a dictionary of possible passwords and\n\
+therefore may be easily guessed. Please choose another password.\n\
+See the kpasswd man page for help in choosing a good password."
+
+error_code CHPASS_UTIL_PASSWORD_NOT_CHANGED, "Password not changed."
+
+error_code CHPASS_UTIL_PASSWORD_TOO_SHORT, 
+"New password is too short.\n\
+Please choose a password which is at least %d characters long."
+#	/*  <pw-min-len> */
+
+error_code CHPASS_UTIL_TOO_FEW_CLASSES, 
+"New password does not have enough character classes.\n\
+The character classes are:\n\
+	- lower-case letters,\n\
+	- upper-case letters,\n\
+	- digits,\n\
+	- punctuation, and\n\
+	- all other characters (e.g., control characters).\n\
+Please choose a password with at least %d character classes."
+# /* <min-classes> */
+
+
+error_code CHPASS_UTIL_PASSWORD_TOO_SOON,
+"Password cannot be changed because it was changed too recently.\n\
+Please wait until %s before you change it.\n\
+If you need to change your password before then, contact your system\n\
+security administrator."
+# /* <ctime(last-pw-change+pw-min-life)> */
+
+error_code CHPASS_UTIL_PASSWORD_REUSE, 
+"New password was used previously. Please choose a different password."
+
+error_code CHPASS_UTIL_WHILE_TRYING_TO_CHANGE, 
+"while trying to change password."
+
+error_code CHPASS_UTIL_WHILE_READING_PASSWORD, "while reading new password."
+
+end
+
diff --git a/krb5-1-6/src/lib/kadm5/clnt/Makefile.in b/krb5-1-6/src/lib/kadm5/clnt/Makefile.in
new file mode 100644
index 000000000..8c0bce105
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/Makefile.in
@@ -0,0 +1,165 @@
+thisconfigdir=../../..
+myfulldir=lib/kadm5/clnt
+mydir=lib/kadm5/clnt
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5
+DEFS=
+
+LIBBASE=kadm5clnt
+LIBMAJOR=5
+LIBMINOR=1
+STOBJLISTS=../OBJS.ST OBJS.ST
+SHLIB_EXPDEPS=\
+	$(TOPLIBD)/libgssrpc$(SHLIBEXT) \
+	$(TOPLIBD)/libgssapi_krb5$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT) \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(COM_ERR_DEPLIB)
+SHLIB_EXPLIBS=-lgssrpc -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+RELDIR=kadm5/clnt
+
+##DOSBUILDTOP = ..\..\..
+##DOSLIBNAME = libkadm5clnt.lib
+
+SRCS =	$(srcdir)/clnt_policy.c \
+	$(srcdir)/client_rpc.c \
+	$(srcdir)/client_principal.c \
+	$(srcdir)/client_init.c \
+	$(srcdir)/clnt_privs.c \
+	$(srcdir)/clnt_chpass_util.c
+
+OBJS =	\
+	clnt_policy.$(OBJEXT) \
+	client_rpc.$(OBJEXT) \
+	client_principal.$(OBJEXT) \
+	client_init.$(OBJEXT) \
+	clnt_privs.$(OBJEXT) \
+	clnt_chpass_util.$(OBJEXT)
+
+STLIBOBJS = \
+	clnt_policy.o \
+	client_rpc.o \
+	client_principal.o \
+	client_init.o \
+	clnt_privs.o \
+	clnt_chpass_util.o
+
+all-unix:: includes
+all-unix:: all-liblinks
+all-windows:: $(OBJS)
+
+generate-files-mac: includes
+
+includes:: client_internal.h
+	if cmp $(srcdir)/client_internal.h \
+	$(BUILDTOP)/include/kadm5/client_internal.h >/dev/null 2>&1; then :; \
+	else \
+		(set -x; $(RM) $(BUILDTOP)/include/kadm5/client_internal.h; \
+		 $(CP) $(srcdir)/client_internal.h \
+			$(BUILDTOP)/include/kadm5/client_internal.h) ; \
+	fi
+
+clean-unix::
+	$(RM) $(BUILDTOP)/include/kadm5/client_internal.h
+
+check-windows::
+
+clean-windows::
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+install:: install-libs
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+clnt_policy.so clnt_policy.po $(OUTPRE)clnt_policy.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h client_internal.h clnt_policy.c
+client_rpc.so client_rpc.po $(OUTPRE)client_rpc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h client_rpc.c
+client_principal.so client_principal.po $(OUTPRE)client_principal.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h client_internal.h client_principal.c
+client_init.so client_init.po $(OUTPRE)client_init.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_gssapi.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h client_init.c client_internal.h
+clnt_privs.so clnt_privs.po $(OUTPRE)clnt_privs.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h client_internal.h clnt_privs.c
+clnt_chpass_util.so clnt_chpass_util.po $(OUTPRE)clnt_chpass_util.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h client_internal.h \
+  clnt_chpass_util.c
diff --git a/krb5-1-6/src/lib/kadm5/clnt/client_handle.c b/krb5-1-6/src/lib/kadm5/clnt/client_handle.c
new file mode 100644
index 000000000..895777a6e
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/client_handle.c
@@ -0,0 +1,9 @@
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include "client_internal.h"
+
+int _kadm5_check_handle(void *handle)
+{
+     CHECK_HANDLE(handle);
+     return 0;
+}
diff --git a/krb5-1-6/src/lib/kadm5/clnt/client_init.c b/krb5-1-6/src/lib/kadm5/clnt/client_init.c
new file mode 100644
index 000000000..26a7304d9
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/client_init.c
@@ -0,0 +1,752 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ */
+
+/*
+ * 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 <netdb.h>
+#include "autoconf.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <string.h>
+#include <com_err.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <k5-int.h> /* for KRB5_ADM_DEFAULT_PORT */
+#include <krb5.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include "client_internal.h"
+
+#include <gssrpc/rpc.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssrpc/auth_gssapi.h>
+
+#define	ADM_CCACHE  "/tmp/ovsec_adm.XXXXXX"
+
+enum init_type { INIT_PASS, INIT_SKEY, INIT_CREDS };
+
+static kadm5_ret_t _kadm5_init_any(char *client_name,
+				   enum init_type init_type,
+				   char *pass,
+				   krb5_ccache ccache_in,
+				   char *service_name,
+				   kadm5_config_params *params,
+				   krb5_ui_4 struct_version,
+				   krb5_ui_4 api_version,
+				   char **db_args,
+				   void **server_handle);
+
+static kadm5_ret_t
+kadm5_get_init_creds(kadm5_server_handle_t handle,
+		     char *client_name, enum init_type init_type,
+		     char *pass, krb5_ccache ccache_in,
+		     char *svcname_in, char *realm,
+		     char *full_svcname, unsigned int full_svcname_len);
+
+static kadm5_ret_t
+kadm5_gic_iter(kadm5_server_handle_t handle,
+	       enum init_type init_type,
+	       krb5_ccache ccache,
+	       krb5_principal client, char *pass,
+	       char *svcname, char *realm,
+	       char *full_svcname, unsigned int full_svcname_len);
+
+static kadm5_ret_t
+kadm5_setup_gss(kadm5_server_handle_t handle,
+		kadm5_config_params *params_in,
+		char *client_name, char *full_svcname);
+
+static void
+kadm5_rpc_auth(kadm5_server_handle_t handle,
+	       kadm5_config_params *params_in,
+	       gss_cred_id_t gss_client_creds,
+	       gss_name_t gss_target);
+
+kadm5_ret_t kadm5_init_with_creds(char *client_name,
+				  krb5_ccache ccache,
+				  char *service_name,
+				  kadm5_config_params *params,
+				  krb5_ui_4 struct_version,
+				  krb5_ui_4 api_version,
+				  char **db_args,
+				  void **server_handle)
+{
+     return _kadm5_init_any(client_name, INIT_CREDS, NULL, ccache,
+			    service_name, params,
+			    struct_version, api_version, db_args,
+			    server_handle);
+}
+
+
+kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass,
+				     char *service_name,
+				     kadm5_config_params *params,
+				     krb5_ui_4 struct_version,
+				     krb5_ui_4 api_version,
+				     char **db_args,
+				     void **server_handle)
+{
+     return _kadm5_init_any(client_name, INIT_PASS, pass, NULL,
+			    service_name, params, struct_version,
+			    api_version, db_args, server_handle);
+}
+
+kadm5_ret_t kadm5_init(char *client_name, char *pass,
+		       char *service_name, 
+		       kadm5_config_params *params,
+		       krb5_ui_4 struct_version,
+		       krb5_ui_4 api_version,
+		       char **db_args,
+		       void **server_handle)
+{
+     return _kadm5_init_any(client_name, INIT_PASS, pass, NULL,
+			    service_name, params, struct_version,
+			    api_version, db_args, server_handle);
+}
+
+kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab,
+				 char *service_name,
+				 kadm5_config_params *params,
+				 krb5_ui_4 struct_version,
+				 krb5_ui_4 api_version,
+				 char **db_args,
+				 void **server_handle)
+{
+     return _kadm5_init_any(client_name, INIT_SKEY, keytab, NULL,
+			    service_name, params, struct_version,
+			    api_version, db_args, server_handle);
+}
+
+static kadm5_ret_t _kadm5_init_any(char *client_name,
+				   enum init_type init_type,
+				   char *pass,
+				   krb5_ccache ccache_in,
+				   char *service_name,
+				   kadm5_config_params *params_in,
+				   krb5_ui_4 struct_version,
+				   krb5_ui_4 api_version,
+				   char **db_args,
+				   void **server_handle)
+{
+     struct sockaddr_in addr;
+     struct hostent *hp;
+     int fd;
+
+     char full_svcname[BUFSIZ];
+     char *realm;
+     
+     kadm5_server_handle_t handle;
+     kadm5_config_params params_local;
+
+     int code = 0;
+     generic_ret *r;
+
+     initialize_ovk_error_table();
+/*      initialize_adb_error_table(); */
+     initialize_ovku_error_table();
+     
+     if (! server_handle) {
+	 return EINVAL;
+     }
+
+     if (! (handle = malloc(sizeof(*handle)))) {
+	  return ENOMEM;
+     }
+     if (! (handle->lhandle = malloc(sizeof(*handle)))) {
+	  free(handle);
+	  return ENOMEM;
+     }
+
+     handle->magic_number = KADM5_SERVER_HANDLE_MAGIC;
+     handle->struct_version = struct_version;
+     handle->api_version = api_version;
+     handle->clnt = 0;
+     handle->cache_name = 0;
+     handle->destroy_cache = 0;
+     *handle->lhandle = *handle;
+     handle->lhandle->api_version = KADM5_API_VERSION_2;
+     handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
+     handle->lhandle->lhandle = handle->lhandle;
+
+     krb5_init_context(&handle->context);
+
+     if(client_name == NULL) {
+	free(handle);
+	return EINVAL;
+     }
+
+     /*
+      * Verify the version numbers before proceeding; we can't use
+      * CHECK_HANDLE because not all fields are set yet.
+      */
+     GENERIC_CHECK_HANDLE(handle, KADM5_OLD_LIB_API_VERSION,
+			  KADM5_NEW_LIB_API_VERSION);
+     
+     /*
+      * Acquire relevant profile entries.  In version 2, merge values
+      * in params_in with values from profile, based on
+      * params_in->mask.
+      *
+      * In version 1, we've given a realm (which may be NULL) instead
+      * of params_in.  So use that realm, make params_in contain an
+      * empty mask, and behave like version 2.
+      */
+     memset((char *) ¶ms_local, 0, sizeof(params_local));
+     if (api_version == KADM5_API_VERSION_1) {
+	  realm = params_local.realm = (char *) params_in;
+	  if (params_in)
+	       params_local.mask = KADM5_CONFIG_REALM;
+
+	  /* Use old AUTH_GSSAPI for version 1 protocol. */
+	  params_local.mask |= KADM5_CONFIG_OLD_AUTH_GSSAPI;
+	  params_in = ¶ms_local;
+     } else {
+	  if (params_in && (params_in->mask & KADM5_CONFIG_REALM))
+	       realm = params_in->realm;
+	  else
+	       realm = NULL;
+     }
+
+#define ILLEGAL_PARAMS (KADM5_CONFIG_DBNAME | KADM5_CONFIG_ADBNAME | \
+			KADM5_CONFIG_ADB_LOCKFILE | \
+			KADM5_CONFIG_ACL_FILE | KADM5_CONFIG_DICT_FILE \
+			| KADM5_CONFIG_ADMIN_KEYTAB | \
+			KADM5_CONFIG_STASH_FILE | \
+			KADM5_CONFIG_MKEY_NAME | KADM5_CONFIG_ENCTYPE \
+			| KADM5_CONFIG_MAX_LIFE | \
+			KADM5_CONFIG_MAX_RLIFE | \
+			KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_FLAGS | \
+			KADM5_CONFIG_ENCTYPES | KADM5_CONFIG_MKEY_FROM_KBD)
+
+     if (params_in && params_in->mask & ILLEGAL_PARAMS) {
+	  free(handle);
+	  return KADM5_BAD_CLIENT_PARAMS;
+     }
+			
+     if ((code = kadm5_get_config_params(handle->context, 0,
+					 params_in, &handle->params))) {
+	  krb5_free_context(handle->context);
+	  free(handle);
+	  return(code);
+     }
+
+#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | \
+			 KADM5_CONFIG_ADMIN_SERVER | \
+			 KADM5_CONFIG_KADMIND_PORT) 
+
+     if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
+	  krb5_free_context(handle->context);
+	  free(handle);
+	  return KADM5_MISSING_KRB5_CONF_PARAMS;
+     }
+
+     /*
+      * Get credentials.  Also does some fallbacks in case kadmin/fqdn
+      * principal doesn't exist.
+      */
+     code = kadm5_get_init_creds(handle, client_name, init_type, pass,
+				 ccache_in, service_name, realm,
+				 full_svcname, sizeof(full_svcname));
+     if (code)
+	  goto error;
+     /*
+      * We have ticket; open the RPC connection.
+      */
+
+     hp = gethostbyname(handle->params.admin_server);
+     if (hp == (struct hostent *) NULL) {
+	  code = KADM5_BAD_SERVER_NAME;
+	  goto cleanup;
+     }
+
+     memset(&addr, 0, sizeof(addr));
+     addr.sin_family = hp->h_addrtype;
+     (void) memcpy((char *) &addr.sin_addr, (char *) hp->h_addr,
+		   sizeof(addr.sin_addr));
+     addr.sin_port = htons((u_short) handle->params.kadmind_port);
+     
+     fd = RPC_ANYSOCK;
+     
+     handle->clnt = clnttcp_create(&addr, KADM, KADMVERS, &fd, 0, 0);
+     if (handle->clnt == NULL) {
+	  code = KADM5_RPC_ERROR;
+#ifdef DEBUG
+	  clnt_pcreateerror("clnttcp_create");
+#endif
+	  goto error;
+     }
+     handle->lhandle->clnt = handle->clnt;
+
+     /* now that handle->clnt is set, we can check the handle */
+     if ((code = _kadm5_check_handle((void *) handle)))
+	  goto error;
+
+     /*
+      * The RPC connection is open; establish the GSS-API
+      * authentication context.
+      */
+     code = kadm5_setup_gss(handle, params_in, client_name, full_svcname);
+     if (code)
+	  goto error;
+
+     r = init_2(&handle->api_version, handle->clnt);
+     if (r == NULL) {
+	  code = KADM5_RPC_ERROR;
+#ifdef DEBUG
+	  clnt_perror(handle->clnt, "init_2 null resp");
+#endif
+	  goto error;
+     }
+     if (r->code) {
+	  code = r->code;
+	  goto error;
+     }
+
+     *server_handle = (void *) handle;
+
+     goto cleanup;
+
+error:
+     /*
+      * Note that it is illegal for this code to execute if "handle"
+      * has not been allocated and initialized.  I.e., don't use "goto
+      * error" before the block of code at the top of the function
+      * that allocates and initializes "handle".
+      */
+     if (handle->cache_name)
+	 free(handle->cache_name);
+     if(handle->clnt && handle->clnt->cl_auth)
+	  AUTH_DESTROY(handle->clnt->cl_auth);
+     if(handle->clnt)
+	  clnt_destroy(handle->clnt);
+
+cleanup:
+     if (code)
+	  free(handle);
+
+     return code;
+}
+
+/*
+ * kadm5_get_init_creds
+ *
+ * Get initial credentials for authenticating to server.  Perform
+ * fallback from kadmin/fqdn to kadmin/admin if svcname_in is NULL.
+ */
+static kadm5_ret_t
+kadm5_get_init_creds(kadm5_server_handle_t handle,
+		     char *client_name, enum init_type init_type,
+		     char *pass, krb5_ccache ccache_in,
+		     char *svcname_in, char *realm,
+		     char *full_svcname, unsigned int full_svcname_len)
+{
+     kadm5_ret_t code;
+     krb5_principal client;
+     krb5_ccache ccache;
+     char svcname[BUFSIZ];
+
+     client = NULL;
+     ccache = NULL;
+     /* NULL svcname means use host-based. */
+     if (svcname_in == NULL) {
+	  code = kadm5_get_admin_service_name(handle->context,
+					      handle->params.realm,
+					      svcname, sizeof(svcname));
+	  if (code) {
+	       code = KADM5_MISSING_KRB5_CONF_PARAMS;
+	       goto error;
+	  }
+     } else {
+	  strncpy(svcname, svcname_in, sizeof(svcname));
+	  svcname[sizeof(svcname)-1] = '\0';
+     }
+     /*
+      * Acquire a service ticket for svcname@realm in the name of
+      * client_name, using password pass (which could be NULL), and
+      * create a ccache to store them in.  If INIT_CREDS, use the
+      * ccache we were provided instead.
+      */
+     code = krb5_parse_name(handle->context, client_name, &client);
+     if (code)
+	  goto error;
+
+     if (init_type == INIT_CREDS) {
+	  ccache = ccache_in;
+	  handle->cache_name = (char *)
+	       malloc(strlen(krb5_cc_get_type(handle->context, ccache)) +
+		      strlen(krb5_cc_get_name(handle->context, ccache)) + 2);
+	  if (handle->cache_name == NULL) {
+	       code = ENOMEM;
+	       goto error;
+	  }
+	  sprintf(handle->cache_name, "%s:%s",
+		  krb5_cc_get_type(handle->context, ccache),
+		  krb5_cc_get_name(handle->context, ccache));
+     } else {
+	  static int counter = 0;
+
+	  handle->cache_name = malloc(sizeof("MEMORY:kadm5_")
+				      + 3*sizeof(counter));
+	  sprintf(handle->cache_name, "MEMORY:kadm5_%u", counter++);
+
+	  code = krb5_cc_resolve(handle->context, handle->cache_name,
+				 &ccache);
+	  if (code) 
+	       goto error;
+
+	  code = krb5_cc_initialize (handle->context, ccache, client);
+	  if (code) 
+	       goto error;
+
+	  handle->destroy_cache = 1;
+     }
+     handle->lhandle->cache_name = handle->cache_name;
+
+     code = kadm5_gic_iter(handle, init_type, ccache,
+			   client, pass, svcname, realm,
+			   full_svcname, full_svcname_len);
+     if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
+	  || code == KRB5_CC_NOTFOUND) && svcname_in == NULL) {
+	  /* Retry with old host-independent service princpal. */
+	  code = kadm5_gic_iter(handle, init_type, ccache,
+				client, pass,
+				KADM5_ADMIN_SERVICE, realm,
+				full_svcname, full_svcname_len);
+     }
+     /* Improved error messages */
+     if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) code = KADM5_BAD_PASSWORD;
+     if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN)
+	  code = KADM5_SECURE_PRINC_MISSING;
+
+error:
+     if (ccache != NULL && init_type != INIT_CREDS)
+	  krb5_cc_close(handle->context, ccache);
+     return code;
+}
+
+/*
+ * kadm5_gic_iter
+ *
+ * Perform one iteration of attempting to get credentials.  This
+ * includes searching existing ccache for requested service if
+ * INIT_CREDS.
+ */
+static kadm5_ret_t
+kadm5_gic_iter(kadm5_server_handle_t handle,
+	       enum init_type init_type,
+	       krb5_ccache ccache,
+	       krb5_principal client, char *pass,
+	       char *svcname, char *realm,
+	       char *full_svcname, unsigned int full_svcname_len)
+{
+     kadm5_ret_t code;
+     krb5_context ctx;
+     krb5_keytab kt;
+     krb5_get_init_creds_opt opt;
+     krb5_creds mcreds, outcreds;
+
+     ctx = handle->context;
+     kt = NULL;
+     memset(full_svcname, 0, full_svcname_len);
+     memset(&opt, 0, sizeof(opt));
+     memset(&mcreds, 0, sizeof(mcreds));
+     memset(&outcreds, 0, sizeof(outcreds));
+
+     code = ENOMEM;
+     if (realm) {
+          if ((strlen(svcname) + strlen(realm) + 1) >= full_svcname_len)
+	       goto error;
+	  sprintf(full_svcname, "%s@%s", svcname, realm);
+     } else {
+	  /* krb5_princ_realm(client) is not null terminated */
+          if ((strlen(svcname) + krb5_princ_realm(ctx, client)->length + 1)
+	      >= full_svcname_len)
+	       goto error;
+
+	  strcpy(full_svcname, svcname);
+	  strcat(full_svcname, "@");
+	  strncat(full_svcname,
+		  krb5_princ_realm(ctx, client)->data,
+		  krb5_princ_realm(ctx, client)->length);
+     }
+
+     if (init_type != INIT_CREDS)
+	  krb5_get_init_creds_opt_init(&opt);
+
+     if (init_type == INIT_PASS) {
+	  code = krb5_get_init_creds_password(ctx, &outcreds, client, pass,
+					      krb5_prompter_posix,
+					      NULL, 0,
+					      full_svcname, &opt);
+	  if (code)
+	       goto error;
+     } else if (init_type == INIT_SKEY) {
+	  if (pass) {
+	       code = krb5_kt_resolve(ctx, pass, &kt);
+	       if (code)
+		   goto error;
+	  }
+	  code = krb5_get_init_creds_keytab(ctx, &outcreds, client, kt,
+					    0, full_svcname, &opt);
+	  if (pass)
+	       krb5_kt_close(ctx, kt);
+	  if (code)
+	       goto error;
+     } else if (init_type == INIT_CREDS) {
+	  mcreds.client = client;
+	  code = krb5_parse_name(ctx, full_svcname, &mcreds.server);
+	  if (code)
+	       goto error;
+	  code = krb5_cc_retrieve_cred(ctx, ccache, 0,
+				       &mcreds, &outcreds);
+	  krb5_free_principal(ctx, mcreds.server);
+	  if (code)
+	       goto error;
+     }
+     if (init_type != INIT_CREDS) {
+	  /* Caller has initialized ccache. */
+	  code = krb5_cc_store_cred(ctx, ccache, &outcreds);
+	  if (code)
+	       goto error;
+     }
+error:
+     krb5_free_cred_contents(ctx, &outcreds);
+     return code;
+}
+
+/*
+ * kadm5_setup_gss
+ *
+ * Acquire GSSAPI credentials and set up RPC auth flavor.
+ */
+static kadm5_ret_t
+kadm5_setup_gss(kadm5_server_handle_t handle,
+		kadm5_config_params *params_in,
+		char *client_name, char *full_svcname)
+{
+     kadm5_ret_t code;
+     OM_uint32 gssstat, minor_stat;
+     gss_buffer_desc buf;
+     gss_name_t gss_client;
+     gss_name_t gss_target;
+     gss_cred_id_t gss_client_creds;
+     const char *c_ccname_orig;
+     char *ccname_orig;
+
+     code = KADM5_GSS_ERROR;
+     gss_client_creds = GSS_C_NO_CREDENTIAL;
+     ccname_orig = NULL;
+
+     /* Temporarily use the kadm5 cache. */
+     gssstat = gss_krb5_ccache_name(&minor_stat, handle->cache_name,
+				    &c_ccname_orig);
+     if (gssstat != GSS_S_COMPLETE) {
+	  code = KADM5_GSS_ERROR;
+	  goto error;
+     }
+     if (c_ccname_orig)
+	  ccname_orig = strdup(c_ccname_orig);
+     else
+	  ccname_orig = 0;
+
+     buf.value = full_svcname;
+     buf.length = strlen((char *)buf.value) + 1;
+     gssstat = gss_import_name(&minor_stat, &buf,
+			       (gss_OID) gss_nt_krb5_name, &gss_target);
+     if (gssstat != GSS_S_COMPLETE) {
+	  code = KADM5_GSS_ERROR;
+	  goto error;
+     }
+
+     buf.value = client_name;
+     buf.length = strlen((char *)buf.value) + 1;
+     gssstat = gss_import_name(&minor_stat, &buf,
+			       (gss_OID) gss_nt_krb5_name, &gss_client);
+     if (gssstat != GSS_S_COMPLETE) {
+	  code = KADM5_GSS_ERROR;
+	  goto error;
+     }
+
+     gssstat = gss_acquire_cred(&minor_stat, gss_client, 0,
+				GSS_C_NULL_OID_SET, GSS_C_INITIATE,
+				&gss_client_creds, NULL, NULL);
+     if (gssstat != GSS_S_COMPLETE) {
+	  code = KADM5_GSS_ERROR;
+	  goto error;
+     }
+
+     /*
+      * Do actual creation of RPC auth handle.  Implements auth flavor
+      * fallback.
+      */
+     kadm5_rpc_auth(handle, params_in, gss_client_creds, gss_target);
+
+error:
+     if (gss_client_creds != GSS_C_NO_CREDENTIAL)
+	  (void) gss_release_cred(&minor_stat, &gss_client_creds);
+
+     if (gss_client)
+	  gss_release_name(&minor_stat, &gss_client);
+     if (gss_target)
+	  gss_release_name(&minor_stat, &gss_target);
+
+     /* Revert to prior gss_krb5 ccache. */
+     if (ccname_orig) {
+	 gssstat = gss_krb5_ccache_name(&minor_stat, ccname_orig, NULL);
+	 if (gssstat) {
+	     return KADM5_GSS_ERROR;
+	 }
+	 free(ccname_orig);
+     } else {
+	 gssstat = gss_krb5_ccache_name(&minor_stat, NULL, NULL);
+	 if (gssstat) {
+	     return KADM5_GSS_ERROR;
+	 }
+     }
+
+     if (handle->clnt->cl_auth == NULL) {
+	  return KADM5_GSS_ERROR;
+     }
+     return 0;
+}
+
+/*
+ * kadm5_rpc_auth
+ *
+ * Create RPC auth handle.  Do auth flavor fallback if needed.
+ */
+static void
+kadm5_rpc_auth(kadm5_server_handle_t handle,
+	       kadm5_config_params *params_in,
+	       gss_cred_id_t gss_client_creds,
+	       gss_name_t gss_target)
+{
+     OM_uint32 gssstat, minor_stat;
+     struct rpc_gss_sec sec;
+
+     /* Allow unauthenticated option for testing. */
+     if (params_in != NULL && (params_in->mask & KADM5_CONFIG_NO_AUTH))
+	  return;
+
+     /* Use RPCSEC_GSS by default. */
+     if (params_in == NULL ||
+	 !(params_in->mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)) {
+	  sec.mech = gss_mech_krb5;
+	  sec.qop = GSS_C_QOP_DEFAULT;
+	  sec.svc = RPCSEC_GSS_SVC_PRIVACY;
+	  sec.cred = gss_client_creds;
+	  sec.req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
+
+	  handle->clnt->cl_auth = authgss_create(handle->clnt,
+						 gss_target, &sec);
+	  if (handle->clnt->cl_auth != NULL)
+	       return;
+     }
+
+     if (params_in != NULL && (params_in->mask & KADM5_CONFIG_AUTH_NOFALLBACK))
+	  return;
+
+     /* Fall back to old AUTH_GSSAPI. */
+     handle->clnt->cl_auth = auth_gssapi_create(handle->clnt,
+						&gssstat,
+						&minor_stat,
+						gss_client_creds,
+						gss_target,
+						(gss_OID) gss_mech_krb5,
+						GSS_C_MUTUAL_FLAG
+						| GSS_C_REPLAY_FLAG,
+						0, NULL, NULL, NULL);
+}
+
+kadm5_ret_t
+kadm5_destroy(void *server_handle)
+{
+     krb5_ccache	    ccache = NULL;
+     int		    code = KADM5_OK;
+     kadm5_server_handle_t	handle =
+	  (kadm5_server_handle_t) server_handle;
+
+     CHECK_HANDLE(server_handle);
+
+     if (handle->destroy_cache && handle->cache_name) {
+	 if ((code = krb5_cc_resolve(handle->context,
+				     handle->cache_name, &ccache)) == 0) 
+	     code = krb5_cc_destroy (handle->context, ccache);
+     }
+     if (handle->cache_name)
+	 free(handle->cache_name);
+     if (handle->clnt && handle->clnt->cl_auth)
+	  AUTH_DESTROY(handle->clnt->cl_auth);
+     if (handle->clnt)
+	  clnt_destroy(handle->clnt);
+     if (handle->lhandle)
+          free (handle->lhandle);
+
+     kadm5_free_config_params(handle->context, &handle->params);
+     krb5_free_context(handle->context);
+
+     handle->magic_number = 0;
+     free(handle);
+
+     return code;
+}
+/* not supported on client */
+kadm5_ret_t kadm5_lock(void *server_handle)
+{
+    return EINVAL;
+}
+
+/* not supported on client */
+kadm5_ret_t kadm5_unlock(void *server_handle)
+{
+    return EINVAL;
+}
+
+kadm5_ret_t kadm5_flush(void *server_handle)
+{
+     return KADM5_OK;
+}
+
+int _kadm5_check_handle(void *handle)
+{
+     CHECK_HANDLE(handle);
+     return 0;
+}
+
+krb5_error_code kadm5_init_krb5_context (krb5_context *ctx)
+{
+    return krb5_init_context(ctx);
+}
diff --git a/krb5-1-6/src/lib/kadm5/clnt/client_internal.h b/krb5-1-6/src/lib/kadm5/clnt/client_internal.h
new file mode 100644
index 000000000..c5ebfec77
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/client_internal.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ * 
+ * $Log$
+ * Revision 1.1  1996/07/24 22:22:43  tlyu
+ * 	* Makefile.in, configure.in: break out client lib into a
+ * 		subdirectory
+ *
+ * Revision 1.11  1996/07/22 20:35:46  marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches.  This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964.  before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.10.4.1  1996/07/18 03:08:37  marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.10.2.1  1996/06/20  02:16:46  marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.10  1996/06/06  20:09:16  bjaspan
+ * add destroy_cache, for kadm5_init_with_creds
+ *
+ * Revision 1.9  1996/05/30 21:04:42  bjaspan
+ * add lhandle to handle
+ *
+ * Revision 1.8  1996/05/28 20:33:49  bjaspan
+ * rework kadm5_config
+ *
+ * Revision 1.7  1996/05/17 21:36:59  bjaspan
+ * rename to kadm5, begin implementing version 2
+ *
+ * Revision 1.6  1996/05/16 21:45:07  bjaspan
+ * add context
+ *
+ * Revision 1.5  1996/05/08 21:10:23  bjaspan
+ * marc's changes
+ *
+ * Revision 1.4  1996/01/16  20:54:30  grier
+ * secure/3570 use krb5_ui_4 not unsigned int
+ *
+ * Revision 1.3  1995/11/14  17:48:57  grier
+ * long to int
+ *
+ * Revision 1.2  1994/08/16  18:53:47  jik
+ * Versioning stuff.
+ *
+ * Revision 1.1  1994/08/09  21:14:38  jik
+ * Initial revision
+ *
+ */
+
+/*
+ * This header file is used internally by the Admin API client
+ * libraries.  IF YOU THINK YOU NEED TO USE THIS FILE FOR ANYTHING,
+ * YOU'RE ALMOST CERTAINLY WRONG.
+ */
+
+#ifndef __KADM5_CLIENT_INTERNAL_H__
+#define __KADM5_CLIENT_INTERNAL_H__
+
+#include "admin_internal.h"
+
+typedef struct _kadm5_server_handle_t {
+	krb5_ui_4	magic_number;
+	krb5_ui_4	struct_version;
+	krb5_ui_4	api_version;
+	char *		cache_name;
+	int		destroy_cache;
+	CLIENT *	clnt;
+	krb5_context	context;
+	kadm5_config_params params;
+	struct _kadm5_server_handle_t *lhandle;
+} kadm5_server_handle_rec, *kadm5_server_handle_t;
+
+#define CLIENT_CHECK_HANDLE(handle) \
+{ \
+	kadm5_server_handle_t srvr = \
+	     (kadm5_server_handle_t) handle; \
+ \
+	if (! srvr->clnt) \
+	     return KADM5_BAD_SERVER_HANDLE; \
+	if (! srvr->cache_name) \
+	     return KADM5_BAD_SERVER_HANDLE; \
+	if (! srvr->lhandle) \
+	     return KADM5_BAD_SERVER_HANDLE; \
+}
+
+#define CHECK_HANDLE(handle) \
+     GENERIC_CHECK_HANDLE(handle, KADM5_OLD_LIB_API_VERSION, \
+			  KADM5_NEW_LIB_API_VERSION) \
+     CLIENT_CHECK_HANDLE(handle)
+
+#endif /* __KADM5_CLIENT_INTERNAL_H__ */
diff --git a/krb5-1-6/src/lib/kadm5/clnt/client_principal.c b/krb5-1-6/src/lib/kadm5/clnt/client_principal.c
new file mode 100644
index 000000000..7b65331fa
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/client_principal.c
@@ -0,0 +1,546 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include    <gssrpc/rpc.h>
+#include    <kadm5/admin.h>
+#include    <kadm5/kadm_rpc.h>
+#ifdef HAVE_MEMORY_H
+#include    <memory.h>
+#endif
+#include    <errno.h>
+#include    "client_internal.h"
+
+#ifdef DEBUG
+#define eret() do { clnt_perror(handle->clnt, "null ret"); return KADM5_RPC_ERROR; } while (0)
+#else
+#define eret() do { return KADM5_RPC_ERROR; } while (0)
+#endif
+
+kadm5_ret_t
+kadm5_create_principal(void *server_handle,
+			    kadm5_principal_ent_t princ, long mask,
+			    char *pw)
+{
+    generic_ret		*r;
+    cprinc_arg		arg;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    memset(&arg, 0, sizeof(arg));
+    arg.mask = mask;
+    arg.passwd = pw;
+    arg.api_version = handle->api_version;
+
+    if(princ == NULL)
+	return EINVAL;
+
+    if (handle->api_version == KADM5_API_VERSION_1) {
+       memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1));
+    } else {
+       memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
+    }
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 /*
+	  * hack hack cough cough.
+	  * krb5_unparse name dumps core if we pass it in garbage
+	  * or null. So, since the client is not allowed to set mod_name
+	  * anyway, we just fill it in with a dummy principal. The server of
+	  * course ignores this.
+	  */
+	 krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name);
+    } else
+	 arg.rec.mod_name = NULL;
+    
+    if(!(mask & KADM5_POLICY))
+	arg.rec.policy = NULL;
+    if (! (mask & KADM5_KEY_DATA)) {
+	 arg.rec.n_key_data = 0;
+	 arg.rec.key_data = NULL;
+    }
+    if (! (mask & KADM5_TL_DATA)) {
+	 arg.rec.n_tl_data = 0;
+	 arg.rec.tl_data = NULL;
+    }
+	 
+    r = create_principal_2(&arg, handle->clnt);
+
+    if (handle->api_version == KADM5_API_VERSION_1)
+	 krb5_free_principal(handle->context, arg.rec.mod_name);
+
+    if(r == NULL)
+	eret();
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_create_principal_3(void *server_handle,
+			 kadm5_principal_ent_t princ, long mask,
+			 int n_ks_tuple,
+			 krb5_key_salt_tuple *ks_tuple,
+			 char *pw)
+{
+    generic_ret		*r;
+    cprinc3_arg		arg;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    memset(&arg, 0, sizeof(arg));
+    arg.mask = mask;
+    arg.passwd = pw;
+    arg.api_version = handle->api_version;
+    arg.n_ks_tuple = n_ks_tuple;
+    arg.ks_tuple = ks_tuple;
+
+    if(princ == NULL)
+	return EINVAL;
+
+    if (handle->api_version == KADM5_API_VERSION_1) {
+       memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1));
+    } else {
+       memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
+    }
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 /*
+	  * hack hack cough cough.
+	  * krb5_unparse name dumps core if we pass it in garbage
+	  * or null. So, since the client is not allowed to set mod_name
+	  * anyway, we just fill it in with a dummy principal. The server of
+	  * course ignores this.
+	  */
+	 krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name);
+    } else
+	 arg.rec.mod_name = NULL;
+    
+    if(!(mask & KADM5_POLICY))
+	arg.rec.policy = NULL;
+    if (! (mask & KADM5_KEY_DATA)) {
+	 arg.rec.n_key_data = 0;
+	 arg.rec.key_data = NULL;
+    }
+    if (! (mask & KADM5_TL_DATA)) {
+	 arg.rec.n_tl_data = 0;
+	 arg.rec.tl_data = NULL;
+    }
+	 
+    r = create_principal3_2(&arg, handle->clnt);
+
+    if (handle->api_version == KADM5_API_VERSION_1)
+	 krb5_free_principal(handle->context, arg.rec.mod_name);
+
+    if(r == NULL)
+	eret();
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_delete_principal(void *server_handle, krb5_principal principal)
+{
+    dprinc_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    if(principal == NULL)
+	return EINVAL;
+    arg.princ = principal;
+    arg.api_version = handle->api_version;
+    r = delete_principal_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();    
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_modify_principal(void *server_handle,
+			    kadm5_principal_ent_t princ, long mask)
+{
+    mprinc_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    memset(&arg, 0, sizeof(arg));
+    arg.mask = mask;
+    arg.api_version = handle->api_version;
+    /*
+     * cough cough gag gag
+     * see comment in create_principal.
+     */
+    if(princ == NULL)
+	return EINVAL;
+    if (handle->api_version == KADM5_API_VERSION_1) {
+        memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1));
+    } else {
+        memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
+    }
+    if(!(mask & KADM5_POLICY))
+	arg.rec.policy = NULL;
+    if (! (mask & KADM5_KEY_DATA)) {
+	 arg.rec.n_key_data = 0;
+	 arg.rec.key_data = NULL;
+    }
+    if (! (mask & KADM5_TL_DATA)) {
+	 arg.rec.n_tl_data = 0;
+	 arg.rec.tl_data = NULL;
+    }
+
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 /*
+	  * See comment in create_principal
+	  */
+	 krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name);
+    } else
+	 arg.rec.mod_name = NULL;
+    
+    r = modify_principal_2(&arg, handle->clnt);
+
+    if (handle->api_version == KADM5_API_VERSION_1)
+	 krb5_free_principal(handle->context, arg.rec.mod_name);    
+
+    if(r == NULL)
+	eret();    
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_principal(void *server_handle,
+		    krb5_principal princ, kadm5_principal_ent_t ent,
+		    long mask)
+{
+    gprinc_arg	arg;
+    gprinc_ret	*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    if(princ == NULL)
+	return EINVAL;
+    arg.princ = princ;
+    if (handle->api_version == KADM5_API_VERSION_1)
+       arg.mask = KADM5_PRINCIPAL_NORMAL_MASK;
+    else
+       arg.mask = mask;
+    arg.api_version = handle->api_version;
+    r = get_principal_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 kadm5_principal_ent_t_v1 *entp;
+
+	 entp = (kadm5_principal_ent_t_v1 *) ent;
+	 if (r->code == 0) {
+	      if (!(*entp = (kadm5_principal_ent_t_v1)
+		    malloc(sizeof(kadm5_principal_ent_rec_v1))))
+		   return ENOMEM;
+	      /* this memcpy works because the v1 structure is an initial
+		 subset of the v2 struct.  C guarantees that this will
+		 result in the same layout in memory */
+	      memcpy(*entp, &r->rec, sizeof(**entp));
+	 } else {
+	    *entp = NULL;
+	 }
+    } else {
+	 if (r->code == 0)
+	      memcpy(ent, &r->rec, sizeof(r->rec));
+    }
+    
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_principals(void *server_handle,
+			  char *exp, char ***princs, int *count)
+{
+    gprincs_arg	arg;
+    gprincs_ret	*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    if(princs == NULL || count == NULL)
+	return EINVAL;
+    arg.exp = exp;
+    arg.api_version = handle->api_version;
+    r = get_princs_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();
+    if(r->code == 0) {
+	 *count = r->count;
+	 *princs = r->princs;
+    } else {
+	 *count = 0;
+	 *princs = NULL;
+    }
+    
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_rename_principal(void *server_handle,
+			    krb5_principal source, krb5_principal dest)
+{
+    rprinc_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.src = source;
+    arg.dest = dest;
+    arg.api_version = handle->api_version;
+    if (source == NULL || dest == NULL)
+	return EINVAL;
+    r = rename_principal_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();        
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_chpass_principal(void *server_handle,
+			    krb5_principal princ, char *password)
+{
+    chpass_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.princ = princ;
+    arg.pass = password;
+    arg.api_version = handle->api_version;
+
+    if(princ == NULL)
+	return EINVAL;
+    r = chpass_principal_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();        
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_chpass_principal_3(void *server_handle,
+			 krb5_principal princ, krb5_boolean keepold,
+			 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
+			 char *password)
+{
+    chpass3_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.princ = princ;
+    arg.pass = password;
+    arg.api_version = handle->api_version;
+    arg.keepold = keepold;
+    arg.n_ks_tuple = n_ks_tuple;
+    arg.ks_tuple = ks_tuple;
+
+    if(princ == NULL)
+	return EINVAL;
+    r = chpass_principal3_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();        
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_setv4key_principal(void *server_handle,
+			 krb5_principal princ,
+			 krb5_keyblock *keyblock)
+{
+    setv4key_arg	arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.princ = princ;
+    arg.keyblock = keyblock;
+    arg.api_version = handle->api_version;
+
+    if(princ == NULL || keyblock == NULL)
+	return EINVAL;
+    r = setv4key_principal_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();        
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_setkey_principal(void *server_handle,
+		       krb5_principal princ,
+		       krb5_keyblock *keyblocks,
+		       int n_keys)
+{
+    setkey_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.princ = princ;
+    arg.keyblocks = keyblocks;
+    arg.n_keys = n_keys;
+    arg.api_version = handle->api_version;
+
+    if(princ == NULL || keyblocks == NULL)
+	return EINVAL;
+    r = setkey_principal_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();        
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_setkey_principal_3(void *server_handle,
+			 krb5_principal princ,
+			 krb5_boolean keepold, int n_ks_tuple,
+			 krb5_key_salt_tuple *ks_tuple,
+			 krb5_keyblock *keyblocks,
+			 int n_keys)
+{
+    setkey3_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.princ = princ;
+    arg.keyblocks = keyblocks;
+    arg.n_keys = n_keys;
+    arg.api_version = handle->api_version;
+    arg.keepold = keepold;
+    arg.n_ks_tuple = n_ks_tuple;
+    arg.ks_tuple = ks_tuple;
+
+    if(princ == NULL || keyblocks == NULL)
+	return EINVAL;
+    r = setkey_principal3_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();        
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_randkey_principal_3(void *server_handle,
+			  krb5_principal princ,
+			  krb5_boolean keepold, int n_ks_tuple,
+			  krb5_key_salt_tuple *ks_tuple,
+			  krb5_keyblock **key, int *n_keys)
+{
+    chrand3_arg		arg;
+    chrand_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+    int			i, ret;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.princ = princ;
+    arg.api_version = handle->api_version;
+    arg.keepold = keepold;
+    arg.n_ks_tuple = n_ks_tuple;
+    arg.ks_tuple = ks_tuple;
+
+    if(princ == NULL)
+	return EINVAL;
+    r = chrand_principal3_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 if (key)
+	      krb5_copy_keyblock(handle->context, &r->key, key);
+    } else {
+	 if (n_keys)
+	      *n_keys = r->n_keys;
+	 if (key) {
+	      if(r->n_keys) {
+		      *key = (krb5_keyblock *) 
+			      malloc(r->n_keys*sizeof(krb5_keyblock));
+		      if (*key == NULL)
+			      return ENOMEM;
+		      for (i = 0; i < r->n_keys; i++) {
+			      ret = krb5_copy_keyblock_contents(handle->context,
+								&r->keys[i],
+								&(*key)[i]);
+			      if (ret) {
+				      free(*key);
+				      return ENOMEM;
+			      }
+		      }
+	      } else *key = NULL;
+         }
+    }
+
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_randkey_principal(void *server_handle,
+			krb5_principal princ,
+			krb5_keyblock **key, int *n_keys)
+{
+    chrand_arg		arg;
+    chrand_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+    int			i, ret;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.princ = princ;
+    arg.api_version = handle->api_version;
+
+    if(princ == NULL)
+	return EINVAL;
+    r = chrand_principal_2(&arg, handle->clnt);
+    if(r == NULL)
+	eret();
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 if (key)
+	      krb5_copy_keyblock(handle->context, &r->key, key);
+    } else {
+	 if (n_keys)
+	      *n_keys = r->n_keys;
+	 if (key) {
+	      if(r->n_keys) {
+		      *key = (krb5_keyblock *) 
+			      malloc(r->n_keys*sizeof(krb5_keyblock));
+		      if (*key == NULL)
+			      return ENOMEM;
+		      for (i = 0; i < r->n_keys; i++) {
+			      ret = krb5_copy_keyblock_contents(handle->context,
+								&r->keys[i],
+								&(*key)[i]);
+			      if (ret) {
+				      free(*key);
+				      return ENOMEM;
+			      }
+		      }
+	      } else *key = NULL;
+         }
+    }
+
+    return r->code;
+}
+
+/* not supported on client side */
+kadm5_ret_t kadm5_decrypt_key(void *server_handle,
+			      kadm5_principal_ent_t entry, krb5_int32
+			      ktype, krb5_int32 stype, krb5_int32
+			      kvno, krb5_keyblock *keyblock,
+			      krb5_keysalt *keysalt, int *kvnop)
+{
+     return EINVAL;
+}
diff --git a/krb5-1-6/src/lib/kadm5/clnt/client_rpc.c b/krb5-1-6/src/lib/kadm5/clnt/client_rpc.c
new file mode 100644
index 000000000..2823da9a1
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/client_rpc.c
@@ -0,0 +1,325 @@
+#include <gssrpc/rpc.h>
+#include <kadm5/kadm_rpc.h>
+#include <krb5.h>
+#include <kadm5/admin.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+generic_ret *
+create_principal_2(cprinc_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, CREATE_PRINCIPAL,
+		      (xdrproc_t) xdr_cprinc_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+create_principal3_2(cprinc3_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, CREATE_PRINCIPAL3,
+		      (xdrproc_t) xdr_cprinc3_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+delete_principal_2(dprinc_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, DELETE_PRINCIPAL,
+		      (xdrproc_t) xdr_dprinc_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+modify_principal_2(mprinc_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, MODIFY_PRINCIPAL,
+		      (xdrproc_t) xdr_mprinc_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+rename_principal_2(rprinc_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, RENAME_PRINCIPAL,
+		      (xdrproc_t) xdr_rprinc_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+gprinc_ret *
+get_principal_2(gprinc_arg *argp, CLIENT *clnt)
+{
+	static gprinc_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, GET_PRINCIPAL,
+		      (xdrproc_t) xdr_gprinc_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_gprinc_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+gprincs_ret *
+get_princs_2(gprincs_arg *argp, CLIENT *clnt)
+{
+	static gprincs_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, GET_PRINCS,
+		      (xdrproc_t) xdr_gprincs_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_gprincs_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) { 
+	     return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+chpass_principal_2(chpass_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, CHPASS_PRINCIPAL,
+		      (xdrproc_t) xdr_chpass_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+chpass_principal3_2(chpass3_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, CHPASS_PRINCIPAL3,
+		      (xdrproc_t) xdr_chpass3_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+setv4key_principal_2(setv4key_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, SETV4KEY_PRINCIPAL,
+		      (xdrproc_t) xdr_setv4key_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+setkey_principal_2(setkey_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, SETKEY_PRINCIPAL,
+		      (xdrproc_t) xdr_setkey_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+setkey_principal3_2(setkey3_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, SETKEY_PRINCIPAL3,
+		      (xdrproc_t) xdr_setkey3_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+chrand_ret *
+chrand_principal_2(chrand_arg *argp, CLIENT *clnt)
+{
+	static chrand_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, CHRAND_PRINCIPAL,
+		      (xdrproc_t) xdr_chrand_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_chrand_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+chrand_ret *
+chrand_principal3_2(chrand3_arg *argp, CLIENT *clnt)
+{
+	static chrand_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, CHRAND_PRINCIPAL3,
+		      (xdrproc_t) xdr_chrand3_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_chrand_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+create_policy_2(cpol_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, CREATE_POLICY,
+		      (xdrproc_t) xdr_cpol_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+delete_policy_2(dpol_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, DELETE_POLICY,
+		      (xdrproc_t) xdr_dpol_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+generic_ret *
+modify_policy_2(mpol_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, MODIFY_POLICY,
+		      (xdrproc_t) xdr_mpol_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+gpol_ret *
+get_policy_2(gpol_arg *argp, CLIENT *clnt)
+{
+	static gpol_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, GET_POLICY,
+		      (xdrproc_t) xdr_gpol_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_gpol_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
+
+gpols_ret *
+get_pols_2(gpols_arg *argp, CLIENT *clnt)
+{
+	static gpols_ret clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, GET_POLS,
+		      (xdrproc_t) xdr_gpols_arg, (caddr_t) argp,
+		      (xdrproc_t) xdr_gpols_ret, (caddr_t) &clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) { 
+	     return (NULL);
+	}
+	return (&clnt_res);
+}
+
+getprivs_ret *
+get_privs_2(void *argp, CLIENT *clnt)
+{
+     static getprivs_ret clnt_res;
+
+     memset((char *)&clnt_res, 0, sizeof(clnt_res));
+     if (clnt_call(clnt, GET_PRIVS,
+		   (xdrproc_t) xdr_u_int32, (caddr_t) argp,
+		   (xdrproc_t) xdr_getprivs_ret, (caddr_t) &clnt_res,
+		   TIMEOUT) != RPC_SUCCESS) {
+	  return (NULL);
+     }
+     return (&clnt_res);
+}
+
+generic_ret *
+init_2(void *argp, CLIENT *clnt)
+{
+     static generic_ret clnt_res;
+
+     memset((char *)&clnt_res, 0, sizeof(clnt_res));
+     if (clnt_call(clnt, INIT,
+		   (xdrproc_t) xdr_u_int32, (caddr_t) argp,
+		   (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+		   TIMEOUT) != RPC_SUCCESS) {
+	  return (NULL);
+     }
+     return (&clnt_res);
+}
diff --git a/krb5-1-6/src/lib/kadm5/clnt/clnt_chpass_util.c b/krb5-1-6/src/lib/kadm5/clnt/clnt_chpass_util.c
new file mode 100644
index 000000000..71ab64937
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/clnt_chpass_util.c
@@ -0,0 +1,16 @@
+#include <kadm5/admin.h>
+#include "client_internal.h"
+
+kadm5_ret_t kadm5_chpass_principal_util(void *server_handle,
+					krb5_principal princ,
+					char *new_pw, 
+					char **ret_pw,
+					char *msg_ret,
+					unsigned int msg_len)
+{
+  kadm5_server_handle_t handle = server_handle;
+
+  CHECK_HANDLE(server_handle);
+  return _kadm5_chpass_principal_util(handle, handle->lhandle, princ,
+				      new_pw, ret_pw, msg_ret, msg_len);
+}
diff --git a/krb5-1-6/src/lib/kadm5/clnt/clnt_policy.c b/krb5-1-6/src/lib/kadm5/clnt/clnt_policy.c
new file mode 100644
index 000000000..6877ec388
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/clnt_policy.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include    <gssrpc/rpc.h>
+#include    <kadm5/admin.h>
+#include    <kadm5/kadm_rpc.h>
+#include    "client_internal.h"
+#include	<stdlib.h>
+#include	<string.h>
+#include	<errno.h>
+
+kadm5_ret_t
+kadm5_create_policy(void *server_handle,
+			 kadm5_policy_ent_t policy, long mask)
+{
+    cpol_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    if(policy == (kadm5_policy_ent_t) NULL)
+	return EINVAL;
+
+    arg.mask = mask;
+    arg.api_version = handle->api_version;
+    memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec));
+    r = create_policy_2(&arg, handle->clnt);
+    if(r == NULL)
+	return KADM5_RPC_ERROR;    
+
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_delete_policy(void *server_handle, char *name)
+{
+    dpol_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+	 
+    CHECK_HANDLE(server_handle);
+
+    if(name == NULL)
+	return EINVAL;
+
+    arg.name = name;
+    arg.api_version = handle->api_version;
+
+    r = delete_policy_2(&arg, handle->clnt);
+    if(r == NULL)
+	return KADM5_RPC_ERROR;    
+
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_modify_policy(void *server_handle,
+			 kadm5_policy_ent_t policy, long mask)
+{
+    mpol_arg		arg;
+    generic_ret		*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    if(policy == (kadm5_policy_ent_t) NULL)
+	return EINVAL;
+	
+    arg.mask = mask;
+    arg.api_version = handle->api_version;
+
+    memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec));
+    r = modify_policy_2(&arg, handle->clnt);
+    if(r == NULL)
+	return KADM5_RPC_ERROR;    
+
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_policy(void *server_handle, char *name, kadm5_policy_ent_t ent)
+{
+    gpol_arg	    arg;
+    gpol_ret	    *r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.name = name;
+    arg.api_version = handle->api_version;
+
+    if(name == NULL)
+	return EINVAL;
+	
+    r = get_policy_2(&arg, handle->clnt);
+    if(r == NULL)
+	return KADM5_RPC_ERROR;
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 kadm5_policy_ent_t *entp;
+
+	 entp = (kadm5_policy_ent_t *) ent;
+	 if(r->code == 0) {
+	      if (!(*entp = (kadm5_policy_ent_t)
+		    malloc(sizeof(kadm5_policy_ent_rec))))
+		   return ENOMEM;
+	      memcpy(*entp, &r->rec, sizeof(**entp));
+	 } else {
+	      *entp = NULL;
+	 }
+    } else {
+	 if (r->code == 0)
+	      memcpy(ent, &r->rec, sizeof(r->rec));
+    }
+	 
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_policies(void *server_handle,
+			  char *exp, char ***pols, int *count)
+{
+    gpols_arg	arg;
+    gpols_ret	*r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    if(pols == NULL || count == NULL)
+	return EINVAL;
+    arg.exp = exp;
+    arg.api_version = handle->api_version;
+    r = get_pols_2(&arg, handle->clnt);
+    if(r == NULL)
+	return KADM5_RPC_ERROR;
+    if(r->code == 0) {
+	 *count = r->count;
+	 *pols = r->pols;
+    } else {
+	 *count = 0;
+	 *pols = NULL;
+    }
+    
+    return r->code;
+}
diff --git a/krb5-1-6/src/lib/kadm5/clnt/clnt_privs.c b/krb5-1-6/src/lib/kadm5/clnt/clnt_privs.c
new file mode 100644
index 000000000..5f7ed4370
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/clnt_privs.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ * 
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include    <gssrpc/rpc.h>
+#include    <kadm5/admin.h>
+#include    <kadm5/kadm_rpc.h>
+#include    "client_internal.h"
+
+kadm5_ret_t kadm5_get_privs(void *server_handle, long *privs)
+{
+     getprivs_ret *r;
+     kadm5_server_handle_t handle = server_handle;
+
+     r = get_privs_2(&handle->api_version, handle->clnt);
+     if (r == NULL)
+	  return KADM5_RPC_ERROR;
+     else if (r->code == KADM5_OK)
+	  *privs = r->privs;
+
+     return r->code;
+}
diff --git a/krb5-1-6/src/lib/kadm5/clnt/libkadm5clnt.exports b/krb5-1-6/src/lib/kadm5/clnt/libkadm5clnt.exports
new file mode 100644
index 000000000..f7f873e29
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/clnt/libkadm5clnt.exports
@@ -0,0 +1,131 @@
+_kadm5_check_handle
+_kadm5_chpass_principal_util
+kadm5_chpass_principal
+kadm5_chpass_principal_3
+kadm5_chpass_principal_util
+kadm5_create_policy
+kadm5_create_principal
+kadm5_create_principal_3
+kadm5_decrypt_key
+kadm5_delete_policy
+kadm5_delete_principal
+kadm5_destroy
+kadm5_flush
+kadm5_free_config_params
+kadm5_free_key_data
+kadm5_free_name_list
+kadm5_free_policy_ent
+kadm5_free_principal_ent
+kadm5_get_admin_service_name
+kadm5_get_config_params
+kadm5_get_policies
+kadm5_get_policy
+kadm5_get_principal
+kadm5_get_principals
+kadm5_get_privs
+kadm5_init
+kadm5_init_krb5_context
+kadm5_init_with_creds
+kadm5_init_with_password
+kadm5_init_with_skey
+kadm5_lock
+kadm5_modify_policy
+kadm5_modify_principal
+kadm5_randkey_principal
+kadm5_randkey_principal_3
+kadm5_rename_principal
+kadm5_setkey_principal
+kadm5_setkey_principal_3
+kadm5_setv4key_principal
+kadm5_unlock
+krb5_aprof_finish
+krb5_aprof_get_boolean
+krb5_aprof_get_deltat
+krb5_aprof_get_int32
+krb5_aprof_get_string
+krb5_aprof_getvals
+krb5_aprof_init
+krb5_flags_to_string
+krb5_free_key_data_contents
+krb5_free_realm_params
+krb5_input_flag_to_string
+krb5_keysalt_is_present
+krb5_keysalt_iterate
+krb5_klog_close
+krb5_klog_init
+krb5_klog_reopen
+krb5_klog_syslog
+krb5_read_realm_params
+krb5_string_to_flags
+krb5_string_to_keysalts
+ovsec_kadm_chpass_principal
+ovsec_kadm_chpass_principal_util
+ovsec_kadm_create_policy
+ovsec_kadm_create_principal
+ovsec_kadm_delete_policy
+ovsec_kadm_delete_principal
+ovsec_kadm_destroy
+ovsec_kadm_flush
+ovsec_kadm_free_name_list
+ovsec_kadm_free_policy_ent
+ovsec_kadm_free_principal_ent
+ovsec_kadm_get_policies
+ovsec_kadm_get_policy
+ovsec_kadm_get_principal
+ovsec_kadm_get_principals
+ovsec_kadm_get_privs
+ovsec_kadm_init
+ovsec_kadm_init_with_password
+ovsec_kadm_init_with_skey
+ovsec_kadm_modify_policy
+ovsec_kadm_modify_principal
+ovsec_kadm_randkey_principal
+ovsec_kadm_rename_principal
+xdr_chpass3_arg
+xdr_chpass_arg
+xdr_chrand3_arg
+xdr_chrand_arg
+xdr_chrand_ret
+xdr_cpol_arg
+xdr_cprinc3_arg
+xdr_cprinc_arg
+xdr_dpol_arg
+xdr_dprinc_arg
+xdr_generic_ret
+xdr_getprivs_ret
+xdr_gpol_arg
+xdr_gpol_ret
+xdr_gpols_arg
+xdr_gpols_ret
+xdr_gprinc_arg
+xdr_gprinc_ret
+xdr_gprincs_arg
+xdr_gprincs_ret
+xdr_kadm5_policy_ent_rec
+xdr_kadm5_principal_ent_rec
+xdr_kadm5_principal_ent_rec_v1
+xdr_kadm5_ret_t
+xdr_krb5_deltat
+xdr_krb5_enctype
+xdr_krb5_flags
+xdr_krb5_int16
+xdr_krb5_key_data_nocontents
+xdr_krb5_key_salt_tuple
+xdr_krb5_keyblock
+xdr_krb5_kvno
+xdr_krb5_octet
+xdr_krb5_principal
+xdr_krb5_salttype
+xdr_krb5_timestamp
+xdr_krb5_tl_data
+xdr_krb5_ui_2
+xdr_krb5_ui_4
+xdr_mpol_arg
+xdr_mprinc_arg
+xdr_nullstring
+xdr_nulltype
+xdr_rprinc_arg
+xdr_setkey3_arg
+xdr_setkey_arg
+xdr_setv4key_arg
+xdr_ui_4
diff --git a/krb5-1-6/src/lib/kadm5/kadm_err.et b/krb5-1-6/src/lib/kadm5/kadm_err.et
new file mode 100644
index 000000000..da18a74eb
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/kadm_err.et
@@ -0,0 +1,63 @@
+# This is the KADM5 error table.  The order of error codes
+# defined in this file MUST match that specified in the API
+# functionality specification, which is the master version.
+#
+error_table ovk
+# vv 0
+error_code KADM5_FAILURE, "Operation failed for unspecified reason"
+error_code KADM5_AUTH_GET, "Operation requires ``get'' privilege"
+error_code KADM5_AUTH_ADD, "Operation requires ``add'' privilege"
+error_code KADM5_AUTH_MODIFY, "Operation requires ``modify'' privilege"
+error_code KADM5_AUTH_DELETE, "Operation requires ``delete'' privilege"
+error_code KADM5_AUTH_INSUFFICIENT, "Insufficient authorization for operation"
+error_code KADM5_BAD_DB, "Database inconsistency detected"
+error_code KADM5_DUP, "Principal or policy already exists"
+error_code KADM5_RPC_ERROR, "Communication failure with server"
+error_code KADM5_NO_SRV, "No administration server found for realm"
+error_code KADM5_BAD_HIST_KEY, "Password history principal key version mismatch"
+error_code KADM5_NOT_INIT, "Connection to server not initialized"
+error_code KADM5_UNK_PRINC, "Principal does not exist"
+error_code KADM5_UNK_POLICY, "Policy does not exist"
+error_code KADM5_BAD_MASK, "Invalid field mask for operation"
+error_code KADM5_BAD_CLASS, "Invalid number of character classes"
+error_code KADM5_BAD_LENGTH, "Invalid password length"
+error_code KADM5_BAD_POLICY, "Illegal policy name"
+error_code KADM5_BAD_PRINCIPAL, "Illegal principal name"
+error_code KADM5_BAD_AUX_ATTR, "Invalid auxillary attributes"
+error_code KADM5_BAD_HISTORY, "Invalid password history count"
+error_code KADM5_BAD_MIN_PASS_LIFE, "Password minimum life is greater than password maximum life"
+error_code KADM5_PASS_Q_TOOSHORT, "Password is too short"
+error_code KADM5_PASS_Q_CLASS, "Password does not contain enough character classes"
+error_code KADM5_PASS_Q_DICT, "Password is in the password dictionary"
+error_code KADM5_PASS_REUSE, "Cannot reuse password"
+error_code KADM5_PASS_TOOSOON, "Current password's minimum life has not expired"
+error_code KADM5_POLICY_REF, "Policy is in use"
+error_code KADM5_INIT,	"Connection to server already initialized"
+error_code KADM5_BAD_PASSWORD, "Incorrect password"
+error_code KADM5_PROTECT_PRINCIPAL, "Cannot change protected principal"
+error_code KADM5_BAD_SERVER_HANDLE, "Programmer error!  Bad Admin server handle"
+error_code KADM5_BAD_STRUCT_VERSION, "Programmer error!  Bad API structure version"
+error_code KADM5_OLD_STRUCT_VERSION, "API structure version specified by application is no longer supported (to fix, recompile application against current KADM5 API header files and libraries)"
+error_code KADM5_NEW_STRUCT_VERSION, "API structure version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)"
+error_code KADM5_BAD_API_VERSION, "Programmer error!  Bad API version"
+error_code KADM5_OLD_LIB_API_VERSION, "API version specified by application is no longer supported by libraries (to fix, update application to adhere to current API version and recompile)"
+error_code KADM5_OLD_SERVER_API_VERSION, "API version specified by application is no longer supported by server (to fix, update application to adhere to current API version and recompile)"
+error_code KADM5_NEW_LIB_API_VERSION, "API version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)"
+error_code KADM5_NEW_SERVER_API_VERSION, "API version specified by application is unknown to server (to fix, obtain and install newest KADM5 Admin Server)"
+error_code KADM5_SECURE_PRINC_MISSING, "Database error! Required KADM5 principal missing"
+error_code KADM5_NO_RENAME_SALT, "The salt type of the specified principal does not support renaming"
+error_code KADM5_BAD_CLIENT_PARAMS, "Illegal configuration parameter for remote KADM5 client"
+error_code KADM5_BAD_SERVER_PARAMS, "Illegal configuration parameter for local KADM5 client"
+error_code KADM5_AUTH_LIST, "Operation requires ``list'' privilege"
+error_code KADM5_AUTH_CHANGEPW, "Operation requires ``change-password'' privilege"
+error_code KADM5_GSS_ERROR, "GSS-API (or Kerberos) error"
+error_code KADM5_BAD_TL_TYPE, "Programmer error!  Illegal tagged data list type"
+error_code KADM5_MISSING_CONF_PARAMS, "Required parameters in kdc.conf missing"
+error_code KADM5_BAD_SERVER_NAME, "Bad krb5 admin server hostname"
+error_code KADM5_AUTH_SETKEY, "Operation requires ``set-key'' privilege"
+error_code KADM5_SETKEY_DUP_ENCTYPES, "Multiple values for single or folded enctype"
+error_code KADM5_SETV4KEY_INVAL_ENCTYPE, "Invalid enctype for setv4key"
+error_code KADM5_SETKEY3_ETYPE_MISMATCH, "Mismatched enctypes for setkey3"
+error_code KADM5_MISSING_KRB5_CONF_PARAMS, "Missing parameters in krb5.conf required for kadmin client"
+error_code KADM5_XDR_FAILURE,		"XDR encoding error"
+end
diff --git a/krb5-1-6/src/lib/kadm5/kadm_rpc.h b/krb5-1-6/src/lib/kadm5/kadm_rpc.h
new file mode 100644
index 000000000..d793ed88c
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/kadm_rpc.h
@@ -0,0 +1,305 @@
+#ifndef __KADM_RPC_H__
+#define __KADM_RPC_H__
+
+#include <gssrpc/types.h>
+
+#include	<krb5.h>
+#include	<kadm5/admin.h>
+
+struct cprinc_arg {
+	krb5_ui_4 api_version;
+	kadm5_principal_ent_rec rec;
+	long mask;
+	char *passwd;
+};
+typedef struct cprinc_arg cprinc_arg;
+
+struct cprinc3_arg {
+	krb5_ui_4 api_version;
+	kadm5_principal_ent_rec rec;
+	long mask;
+	int n_ks_tuple;
+	krb5_key_salt_tuple *ks_tuple;
+	char *passwd;
+};
+typedef struct cprinc3_arg cprinc3_arg;
+
+struct generic_ret {
+	krb5_ui_4 api_version;
+	kadm5_ret_t code;
+};
+typedef struct generic_ret generic_ret;
+
+struct dprinc_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+};
+typedef struct dprinc_arg dprinc_arg;
+
+struct mprinc_arg {
+	krb5_ui_4 api_version;
+	kadm5_principal_ent_rec rec;
+	long mask;
+};
+typedef struct mprinc_arg mprinc_arg;
+
+struct rprinc_arg {
+	krb5_ui_4 api_version;
+	krb5_principal src;
+	krb5_principal dest;
+};
+typedef struct rprinc_arg rprinc_arg;
+
+struct gprincs_arg {
+        krb5_ui_4 api_version;
+	char *exp;
+};
+typedef struct gprincs_arg gprincs_arg;
+
+struct gprincs_ret {
+        krb5_ui_4 api_version;
+	kadm5_ret_t code;
+	char **princs;
+	int count;
+};
+typedef struct gprincs_ret gprincs_ret;
+
+struct chpass_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+	char *pass;
+};
+typedef struct chpass_arg chpass_arg;
+
+struct chpass3_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+	krb5_boolean keepold;
+	int n_ks_tuple;
+	krb5_key_salt_tuple *ks_tuple;
+	char *pass;
+};
+typedef struct chpass3_arg chpass3_arg;
+
+struct setv4key_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+        krb5_keyblock *keyblock;
+};
+typedef struct setv4key_arg setv4key_arg;
+
+struct setkey_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+        krb5_keyblock *keyblocks;
+        int n_keys;
+};
+typedef struct setkey_arg setkey_arg;
+
+struct setkey3_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+	krb5_boolean keepold;
+	int n_ks_tuple;
+	krb5_key_salt_tuple *ks_tuple;
+        krb5_keyblock *keyblocks;
+        int n_keys;
+};
+typedef struct setkey3_arg setkey3_arg;
+
+struct chrand_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+};
+typedef struct chrand_arg chrand_arg;
+
+struct chrand3_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+	krb5_boolean keepold;
+	int n_ks_tuple;
+	krb5_key_salt_tuple *ks_tuple;
+};
+typedef struct chrand3_arg chrand3_arg;
+
+struct chrand_ret {
+	krb5_ui_4 api_version;
+	kadm5_ret_t code;
+	krb5_keyblock key;
+	krb5_keyblock *keys;
+	int n_keys;
+};
+typedef struct chrand_ret chrand_ret;
+
+struct gprinc_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+	long mask;
+};
+typedef struct gprinc_arg gprinc_arg;
+
+struct gprinc_ret {
+	krb5_ui_4 api_version;
+	kadm5_ret_t code;
+	kadm5_principal_ent_rec rec;
+};
+typedef struct gprinc_ret gprinc_ret;
+
+struct cpol_arg {
+	krb5_ui_4 api_version;
+	kadm5_policy_ent_rec rec;
+	long mask;
+};
+typedef struct cpol_arg cpol_arg;
+
+struct dpol_arg {
+	krb5_ui_4 api_version;
+	char *name;
+};
+typedef struct dpol_arg dpol_arg;
+
+struct mpol_arg {
+	krb5_ui_4 api_version;
+	kadm5_policy_ent_rec rec;
+	long mask;
+};
+typedef struct mpol_arg mpol_arg;
+
+struct gpol_arg {
+	krb5_ui_4 api_version;
+	char *name;
+};
+typedef struct gpol_arg gpol_arg;
+
+struct gpol_ret {
+	krb5_ui_4 api_version;
+	kadm5_ret_t code;
+	kadm5_policy_ent_rec rec;
+};
+typedef struct gpol_ret gpol_ret;
+
+struct gpols_arg {
+        krb5_ui_4 api_version;
+	char *exp;
+};
+typedef struct gpols_arg gpols_arg;
+
+struct gpols_ret {
+        krb5_ui_4 api_version;
+	kadm5_ret_t code;
+	char **pols;
+	int count;
+};
+typedef struct gpols_ret gpols_ret;
+
+struct getprivs_ret {
+	krb5_ui_4 api_version;
+	kadm5_ret_t code;
+	long privs;
+};
+typedef struct getprivs_ret getprivs_ret;
+
+#define KADM 2112
+#define KADMVERS 2
+#define CREATE_PRINCIPAL 1
+extern  generic_ret * create_principal_2(cprinc_arg *, CLIENT *);
+extern  generic_ret * create_principal_2_svc(cprinc_arg *, struct svc_req *);
+#define DELETE_PRINCIPAL 2
+extern  generic_ret * delete_principal_2(dprinc_arg *, CLIENT *);
+extern  generic_ret * delete_principal_2_svc(dprinc_arg *, struct svc_req *);
+#define MODIFY_PRINCIPAL 3
+extern  generic_ret * modify_principal_2(mprinc_arg *, CLIENT *);
+extern  generic_ret * modify_principal_2_svc(mprinc_arg *, struct svc_req *);
+#define RENAME_PRINCIPAL 4
+extern  generic_ret * rename_principal_2(rprinc_arg *, CLIENT *);
+extern  generic_ret * rename_principal_2_svc(rprinc_arg *, struct svc_req *);
+#define GET_PRINCIPAL 5
+extern  gprinc_ret * get_principal_2(gprinc_arg *, CLIENT *);
+extern  gprinc_ret * get_principal_2_svc(gprinc_arg *, struct svc_req *);
+#define CHPASS_PRINCIPAL 6
+extern  generic_ret * chpass_principal_2(chpass_arg *, CLIENT *);
+extern  generic_ret * chpass_principal_2_svc(chpass_arg *, struct svc_req *);
+#define CHRAND_PRINCIPAL 7
+extern  chrand_ret * chrand_principal_2(chrand_arg *, CLIENT *);
+extern  chrand_ret * chrand_principal_2_svc(chrand_arg *, struct svc_req *);
+#define CREATE_POLICY 8
+extern  generic_ret * create_policy_2(cpol_arg *, CLIENT *);
+extern  generic_ret * create_policy_2_svc(cpol_arg *, struct svc_req *);
+#define DELETE_POLICY 9
+extern  generic_ret * delete_policy_2(dpol_arg *, CLIENT *);
+extern  generic_ret * delete_policy_2_svc(dpol_arg *, struct svc_req *);
+#define MODIFY_POLICY 10
+extern  generic_ret * modify_policy_2(mpol_arg *, CLIENT *);
+extern  generic_ret * modify_policy_2_svc(mpol_arg *, struct svc_req *);
+#define GET_POLICY 11
+extern  gpol_ret * get_policy_2(gpol_arg *, CLIENT *);
+extern  gpol_ret * get_policy_2_svc(gpol_arg *, struct svc_req *);
+#define GET_PRIVS 12
+extern  getprivs_ret * get_privs_2(void *, CLIENT *);
+extern  getprivs_ret * get_privs_2_svc(krb5_ui_4 *, struct svc_req *);
+#define INIT 13
+extern  generic_ret * init_2(void *, CLIENT *);
+extern  generic_ret * init_2_svc(krb5_ui_4 *, struct svc_req *);
+#define GET_PRINCS 14
+extern  gprincs_ret * get_princs_2(gprincs_arg *, CLIENT *);
+extern  gprincs_ret * get_princs_2_svc(gprincs_arg *, struct svc_req *);
+#define GET_POLS 15
+extern  gpols_ret * get_pols_2(gpols_arg *, CLIENT *);
+extern  gpols_ret * get_pols_2_svc(gpols_arg *, struct svc_req *);
+#define SETKEY_PRINCIPAL 16
+extern  generic_ret * setkey_principal_2(setkey_arg *, CLIENT *);
+extern  generic_ret * setkey_principal_2_svc(setkey_arg *, struct svc_req *);
+#define SETV4KEY_PRINCIPAL 17
+extern  generic_ret * setv4key_principal_2(setv4key_arg *, CLIENT *);
+extern  generic_ret * setv4key_principal_2_svc(setv4key_arg *, struct svc_req *);
+#define CREATE_PRINCIPAL3 18
+extern  generic_ret * create_principal3_2(cprinc3_arg *, CLIENT *);
+extern  generic_ret * create_principal3_2_svc(cprinc3_arg *, struct svc_req *);
+#define CHPASS_PRINCIPAL3 19
+extern  generic_ret * chpass_principal3_2(chpass3_arg *, CLIENT *);
+extern  generic_ret * chpass_principal3_2_svc(chpass3_arg *, struct svc_req *);
+#define CHRAND_PRINCIPAL3 20
+extern  chrand_ret * chrand_principal3_2(chrand3_arg *, CLIENT *);
+extern  chrand_ret * chrand_principal3_2_svc(chrand3_arg *, struct svc_req *);
+#define SETKEY_PRINCIPAL3 21
+extern  generic_ret * setkey_principal3_2(setkey3_arg *, CLIENT *);
+extern  generic_ret * setkey_principal3_2_svc(setkey3_arg *, struct svc_req *);
+
+extern bool_t xdr_cprinc_arg ();
+extern bool_t xdr_cprinc3_arg ();
+extern bool_t xdr_generic_ret ();
+extern bool_t xdr_dprinc_arg ();
+extern bool_t xdr_mprinc_arg ();
+extern bool_t xdr_rprinc_arg ();
+extern bool_t xdr_gprincs_arg ();
+extern bool_t xdr_gprincs_ret ();
+extern bool_t xdr_chpass_arg ();
+extern bool_t xdr_chpass3_arg ();
+extern bool_t xdr_setv4key_arg ();
+extern bool_t xdr_setkey_arg ();
+extern bool_t xdr_setkey3_arg ();
+extern bool_t xdr_chrand_arg ();
+extern bool_t xdr_chrand3_arg ();
+extern bool_t xdr_chrand_ret ();
+extern bool_t xdr_gprinc_arg ();
+extern bool_t xdr_gprinc_ret ();
+extern bool_t xdr_kadm5_ret_t ();
+extern bool_t xdr_kadm5_principal_ent_rec ();
+extern bool_t xdr_kadm5_policy_ent_rec ();
+extern bool_t	xdr_krb5_keyblock ();
+extern bool_t	xdr_krb5_principal ();
+extern bool_t	xdr_krb5_enctype ();
+extern bool_t	xdr_krb5_octet ();
+extern bool_t	xdr_krb5_int32 ();
+extern bool_t	xdr_u_int32 ();
+extern bool_t xdr_cpol_arg ();
+extern bool_t xdr_dpol_arg ();
+extern bool_t xdr_mpol_arg ();
+extern bool_t xdr_gpol_arg ();
+extern bool_t xdr_gpol_ret ();
+extern bool_t xdr_gpols_arg ();
+extern bool_t xdr_gpols_ret ();
+extern bool_t xdr_getprivs_ret ();
+
+
+#endif /* __KADM_RPC_H__ */
diff --git a/krb5-1-6/src/lib/kadm5/kadm_rpc_xdr.c b/krb5-1-6/src/lib/kadm5/kadm_rpc_xdr.c
new file mode 100644
index 000000000..d760ff14d
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/kadm_rpc_xdr.c
@@ -0,0 +1,1044 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ */
+
+#include <gssrpc/rpc.h>
+#include <krb5.h>
+#include <errno.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include <kadm5/admin_xdr.h>
+#include <stdlib.h>
+#include <string.h>
+
+static bool_t
+_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
+			     int v);
+/*
+ * Function: xdr_ui_4
+ *
+ * Purpose: XDR function which serves as a wrapper for xdr_u_int32,
+ * to prevent compiler warnings about type clashes between u_int32
+ * and krb5_ui_4.
+ */
+bool_t xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp)
+{
+  /* Assumes that krb5_ui_4 and u_int32 are both four bytes long.
+     This should not be a harmful assumption. */
+  return xdr_u_int32(xdrs, (uint32_t *) objp);
+}
+
+
+/*
+ * Function: xdr_nullstring
+ *
+ * Purpose: XDR function for "strings" that are either NULL-terminated
+ * or NULL.
+ */
+bool_t xdr_nullstring(XDR *xdrs, char **objp)
+{
+     u_int size;
+
+     if (xdrs->x_op == XDR_ENCODE) {
+	  if (*objp == NULL)
+	       size = 0;
+	  else
+	       size = strlen(*objp) + 1;
+     }
+     if (! xdr_u_int(xdrs, &size)) {
+	  return FALSE;
+	}
+     switch (xdrs->x_op) {
+     case XDR_DECODE:
+	  if (size == 0) {
+	       *objp = NULL;
+	       return TRUE;
+	  } else if (*objp == NULL) {
+	       *objp = (char *) mem_alloc(size);
+	       if (*objp == NULL) {
+		    errno = ENOMEM;
+		    return FALSE;
+	       }
+	  }
+	  return (xdr_opaque(xdrs, *objp, size));
+	  
+     case XDR_ENCODE:
+	  if (size != 0)
+	       return (xdr_opaque(xdrs, *objp, size));
+	  return TRUE;
+
+     case XDR_FREE:
+	  if (*objp != NULL)
+	       mem_free(*objp, size);
+	  *objp = NULL;
+	  return TRUE;
+     }
+
+     return FALSE;
+}
+
+/*
+ * Function: xdr_nulltype
+ *
+ * Purpose: XDR function for arbitrary pointer types that are either
+ * NULL or contain data.
+ */
+bool_t xdr_nulltype(XDR *xdrs, void **objp, xdrproc_t proc)
+{
+     bool_t null;
+
+     switch (xdrs->x_op) {
+     case XDR_DECODE:
+	  if (!xdr_bool(xdrs, &null))
+	      return FALSE;
+	  if (null) {
+	       *objp = NULL;
+	       return TRUE;
+	  }
+	  return (*proc)(xdrs, objp);
+
+     case XDR_ENCODE:
+	  if (*objp == NULL)
+	       null = TRUE;
+	  else
+	       null = FALSE;
+	  if (!xdr_bool(xdrs, &null))
+	       return FALSE;
+	  if (null == FALSE)
+	       return (*proc)(xdrs, objp);
+	  return TRUE;
+
+     case XDR_FREE:
+	  if (*objp)
+	       return (*proc)(xdrs, objp);
+	  return TRUE;
+     }
+
+     return FALSE;
+}
+
+bool_t
+xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp)
+{
+  /* This assumes that int32 and krb5_timestamp are the same size.
+     This shouldn't be a problem, since we've got a unit test which
+     checks for this. */
+	if (!xdr_int32(xdrs, (int32_t *) objp)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp)
+{
+	unsigned char tmp;
+
+	tmp = '\0'; /* for purify, else xdr_u_char performs a umr */
+
+	if (xdrs->x_op == XDR_ENCODE)
+		tmp = (unsigned char) *objp;
+
+	if (!xdr_u_char(xdrs, &tmp))
+		return (FALSE);
+
+	if (xdrs->x_op == XDR_DECODE)
+		*objp = (krb5_kvno) tmp;
+
+	return (TRUE);
+}
+
+bool_t
+xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp)
+{
+  /* This assumes that int32 and krb5_deltat are the same size.
+     This shouldn't be a problem, since we've got a unit test which
+     checks for this. */
+	if (!xdr_int32(xdrs, (int32_t *) objp)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_krb5_flags(XDR *xdrs, krb5_flags *objp)
+{
+  /* This assumes that int32 and krb5_flags are the same size.
+     This shouldn't be a problem, since we've got a unit test which
+     checks for this. */
+	if (!xdr_int32(xdrs, (int32_t *) objp)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_krb5_ui_4(XDR *xdrs, krb5_ui_4 *objp)
+{
+	if (!xdr_u_int32(xdrs, (uint32_t *) objp)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp)
+{
+    int tmp;
+
+    tmp = (int) *objp;
+
+    if (!xdr_int(xdrs, &tmp))
+	return(FALSE);
+
+    *objp = (krb5_int16) tmp;
+
+    return(TRUE);
+}
+
+/*
+ * Function: xdr_krb5_ui_2
+ *
+ * Purpose: XDR function which serves as a wrapper for xdr_u_int,
+ * to prevent compiler warnings about type clashes between u_int
+ * and krb5_ui_2.
+ */
+bool_t
+xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp)
+{
+    unsigned int tmp;
+
+    tmp = (unsigned int) *objp;
+
+    if (!xdr_u_int(xdrs, &tmp))
+	return(FALSE);
+
+    *objp = (krb5_ui_2) tmp;
+
+    return(TRUE);
+}
+
+
+
+bool_t xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp)
+{
+     /*
+      * Note that this function intentionally DOES NOT tranfer key
+      * length or contents!  xdr_krb5_key_data in adb_xdr.c does, but
+      * that is only for use within the server-side library.
+      */
+     unsigned int tmp;
+
+     if (xdrs->x_op == XDR_DECODE)
+	  memset((char *) objp, 0, sizeof(krb5_key_data));
+
+     if (!xdr_krb5_int16(xdrs, &objp->key_data_ver)) {
+	  return (FALSE);
+     }
+     if (!xdr_krb5_int16(xdrs, &objp->key_data_kvno)) {
+	  return (FALSE);
+     }
+     if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0])) {
+	  return (FALSE);
+     }
+     if (objp->key_data_ver > 1) {
+	  if (!xdr_krb5_int16(xdrs, &objp->key_data_type[1])) {
+	       return (FALSE);
+	  }
+     }
+     /*
+      * kadm5_get_principal on the server side allocates and returns
+      * key contents when asked.  Even though this function refuses to
+      * transmit that data, it still has to *free* the data at the
+      * appropriate time to avoid a memory leak.
+      */
+     if (xdrs->x_op == XDR_FREE) {
+	  tmp = (unsigned int) objp->key_data_length[0];
+	  if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
+			 &tmp, ~0))
+	       return FALSE;
+	  
+	  tmp = (unsigned int) objp->key_data_length[1];
+	  if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
+			 &tmp, ~0))
+	       return FALSE;
+     }
+     
+     return (TRUE);
+}
+
+
+bool_t
+xdr_krb5_key_salt_tuple(XDR *xdrs, krb5_key_salt_tuple *objp)
+{
+    if (!xdr_krb5_enctype(xdrs, &objp->ks_enctype))
+	return FALSE;
+    if (!xdr_krb5_salttype(xdrs, &objp->ks_salttype))
+	return FALSE;
+    return TRUE;
+}
+
+bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head)
+{
+     krb5_tl_data *tl, *tl2;
+     bool_t more;
+     unsigned int len;
+
+     switch (xdrs->x_op) {
+     case XDR_FREE:
+	  tl = tl2 = *tl_data_head;
+	  while (tl) {
+	       tl2 = tl->tl_data_next;
+	       free(tl->tl_data_contents);
+	       free(tl);
+	       tl = tl2;
+	  }
+	  break;
+	  
+     case XDR_ENCODE:
+	  tl = *tl_data_head;
+	  while (1) {
+	       more = (tl != NULL);
+	       if (!xdr_bool(xdrs, &more))
+		    return FALSE;
+	       if (tl == NULL)
+		    break;
+	       if (!xdr_krb5_int16(xdrs, &tl->tl_data_type))
+		    return FALSE;
+	       len = tl->tl_data_length;
+	       if (!xdr_bytes(xdrs, (char **) &tl->tl_data_contents, &len, ~0))
+		    return FALSE;
+	       tl = tl->tl_data_next;
+	  }
+	  break;
+
+     case XDR_DECODE:
+	  tl = NULL;
+	  while (1) {
+	       if (!xdr_bool(xdrs, &more))
+		    return FALSE;
+	       if (more == FALSE)
+		    break;
+	       tl2 = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
+	       if (tl2 == NULL)
+		    return FALSE;
+	       memset((char *) tl2, 0, sizeof(krb5_tl_data));
+	       if (!xdr_krb5_int16(xdrs, &tl2->tl_data_type))
+		    return FALSE;
+	       if (!xdr_bytes(xdrs, (char **)&tl2->tl_data_contents, &len, ~0))
+		    return FALSE;
+	       tl2->tl_data_length = len;
+
+	       tl2->tl_data_next = tl;
+	       tl = tl2;
+	  }
+
+	  *tl_data_head = tl;
+	  break;
+     }
+
+     return TRUE;
+}
+
+bool_t
+xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp)
+{
+	uint32_t tmp;
+
+	if (xdrs->x_op == XDR_ENCODE)
+		tmp = (uint32_t) *objp;
+
+	if (!xdr_u_int32(xdrs, &tmp))
+		return (FALSE);
+
+	if (xdrs->x_op == XDR_DECODE)
+		*objp = (kadm5_ret_t) tmp;
+
+	return (TRUE);
+}
+
+bool_t xdr_kadm5_principal_ent_rec_v1(XDR *xdrs,
+				      kadm5_principal_ent_rec *objp)
+{
+     return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_1);
+}
+
+bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs,
+				   kadm5_principal_ent_rec *objp)
+{
+     return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_2);
+}
+
+static bool_t
+_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
+			     int v)
+{
+     unsigned int n;
+     
+	if (!xdr_krb5_principal(xdrs, &objp->principal)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_timestamp(xdrs, &objp->princ_expire_time)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_timestamp(xdrs, &objp->last_pwd_change)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_timestamp(xdrs, &objp->pw_expiration)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_deltat(xdrs, &objp->max_life)) {
+		return (FALSE);
+	}
+        if (v == KADM5_API_VERSION_1) {
+	     if (!xdr_krb5_principal(xdrs, &objp->mod_name)) {
+		  return (FALSE);
+	     }
+	} else {
+	     if (!xdr_nulltype(xdrs, (void **) &objp->mod_name,
+			       xdr_krb5_principal)) {
+		  return (FALSE);
+	     }
+	}
+	if (!xdr_krb5_timestamp(xdrs, &objp->mod_date)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_flags(xdrs, &objp->attributes)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_kvno(xdrs, &objp->kvno)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_kvno(xdrs, &objp->mkvno)) {
+		return (FALSE);
+	}
+	if (!xdr_nullstring(xdrs, &objp->policy)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->aux_attributes)) {
+		return (FALSE);
+	}
+	if (v != KADM5_API_VERSION_1) {
+	     if (!xdr_krb5_deltat(xdrs, &objp->max_renewable_life)) {
+		  return (FALSE);
+	     }
+	     if (!xdr_krb5_timestamp(xdrs, &objp->last_success)) {
+		  return (FALSE);
+	     }
+	     if (!xdr_krb5_timestamp(xdrs, &objp->last_failed)) {
+		  return (FALSE);
+	     }
+	     if (!xdr_krb5_kvno(xdrs, &objp->fail_auth_count)) {
+		  return (FALSE);
+	     }
+	     if (!xdr_krb5_int16(xdrs, &objp->n_key_data)) {
+		  return (FALSE);
+	     }
+	     if (!xdr_krb5_int16(xdrs, &objp->n_tl_data)) {
+		  return (FALSE);
+	     }
+	     if (!xdr_nulltype(xdrs, (void **) &objp->tl_data,
+			       xdr_krb5_tl_data)) { 
+		  return FALSE;
+	     }
+	     n = objp->n_key_data;
+	     if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
+			    &n, ~0, sizeof(krb5_key_data),
+			    xdr_krb5_key_data_nocontents)) {
+		  return (FALSE);
+	     }
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp)
+{
+	if (!xdr_nullstring(xdrs, &objp->policy)) {
+		return (FALSE);
+	}
+	/* these all used to be u_int32, but it's stupid for sized types
+	   to be exposed at the api, and they're the same as longs on the
+	   wire. */
+	if (!xdr_long(xdrs, &objp->pw_min_life)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->pw_max_life)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->pw_min_length)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->pw_min_classes)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->pw_history_num)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->policy_refcnt)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (objp->api_version == KADM5_API_VERSION_1) {
+	     if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
+		  return (FALSE);
+	     }
+	} else {
+	     if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+		  return (FALSE);
+	     }
+	}
+	if (!xdr_long(xdrs, &objp->mask)) {
+		return (FALSE);
+	}
+	if (!xdr_nullstring(xdrs, &objp->passwd)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_cprinc3_arg(XDR *xdrs, cprinc3_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (objp->api_version == KADM5_API_VERSION_1) {
+		if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
+			return (FALSE);
+		}
+	} else {
+		if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+			return (FALSE);
+		}
+	}
+	if (!xdr_long(xdrs, &objp->mask)) {
+		return (FALSE);
+	}
+	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
+		       (unsigned int *)&objp->n_ks_tuple, ~0,
+		       sizeof(krb5_key_salt_tuple),
+		       xdr_krb5_key_salt_tuple)) {
+		return (FALSE);
+	}
+	if (!xdr_nullstring(xdrs, &objp->passwd)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_generic_ret(XDR *xdrs, generic_ret *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+		return (FALSE);
+	}
+
+	return(TRUE);
+}
+
+bool_t
+xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (objp->api_version == KADM5_API_VERSION_1) {
+	     if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
+		  return (FALSE);
+	     }
+	} else {
+	     if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+		  return (FALSE);
+	     }
+	}
+	if (!xdr_long(xdrs, &objp->mask)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->src)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->dest)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_gprincs_arg(XDR *xdrs, gprincs_arg *objp)
+{
+     if (!xdr_ui_4(xdrs, &objp->api_version)) {
+	  return (FALSE);
+     }
+     if (!xdr_nullstring(xdrs, &objp->exp)) {
+	  return (FALSE);
+     }
+     return (TRUE);
+}
+
+bool_t
+xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp)     
+{
+     if (!xdr_ui_4(xdrs, &objp->api_version)) {
+	  return (FALSE);
+     }
+     if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+	  return (FALSE);
+     }
+     if (objp->code == KADM5_OK) {
+	  if (!xdr_int(xdrs, &objp->count)) {
+	       return (FALSE);
+	  }
+	  if (!xdr_array(xdrs, (caddr_t *) &objp->princs,
+			 (unsigned int *) &objp->count, ~0,
+			 sizeof(char *), xdr_nullstring)) {
+	       return (FALSE);
+	  }
+     }
+
+     return (TRUE);
+}
+
+bool_t
+xdr_chpass_arg(XDR *xdrs, chpass_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	if (!xdr_nullstring(xdrs, &objp->pass)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	if (!xdr_bool(xdrs, &objp->keepold)) {
+		return (FALSE);
+	}
+	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
+		       (unsigned int*)&objp->n_ks_tuple, ~0,
+		       sizeof(krb5_key_salt_tuple),
+		       xdr_krb5_key_salt_tuple)) {
+		return (FALSE);
+	}
+	if (!xdr_nullstring(xdrs, &objp->pass)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_setv4key_arg(XDR *xdrs, setv4key_arg *objp)
+{
+	unsigned int n_keys = 1;
+
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblock,
+		       &n_keys, ~0,
+		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
+	        return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_setkey_arg(XDR *xdrs, setkey_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks,
+		       (unsigned int *) &objp->n_keys, ~0,
+		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
+	        return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	if (!xdr_bool(xdrs, &objp->keepold)) {
+		return (FALSE);
+	}
+	if (!xdr_array(xdrs, (caddr_t *) &objp->ks_tuple,
+		       (unsigned int *) &objp->n_ks_tuple, ~0,
+		       sizeof(krb5_key_salt_tuple), xdr_krb5_key_salt_tuple)) {
+		return (FALSE);
+	}
+	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks,
+		       (unsigned int *) &objp->n_keys, ~0,
+		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_chrand_arg(XDR *xdrs, chrand_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	if (!xdr_bool(xdrs, &objp->keepold)) {
+		return (FALSE);
+	}
+	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
+		       (unsigned int*)&objp->n_ks_tuple, ~0,
+		       sizeof(krb5_key_salt_tuple),
+		       xdr_krb5_key_salt_tuple)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_chrand_ret(XDR *xdrs, chrand_ret *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+		return (FALSE);
+	}
+	if (objp->api_version == KADM5_API_VERSION_1) {
+	     if(objp->code == KADM5_OK) {
+		  if (!xdr_krb5_keyblock(xdrs, &objp->key)) {
+		       return (FALSE);
+		  }
+	     }
+	} else {
+	     if (objp->code == KADM5_OK) {
+		  if (!xdr_array(xdrs, (char **)&objp->keys, &objp->n_keys, ~0,
+				 sizeof(krb5_keyblock),
+				 xdr_krb5_keyblock))
+		       return FALSE;
+	     }
+	}
+
+	return (TRUE);
+}
+
+bool_t
+xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return (FALSE);
+	}
+	if ((objp->api_version > KADM5_API_VERSION_1) &&
+	    !xdr_long(xdrs, &objp->mask)) {
+	     return FALSE;
+	}
+	     
+	return (TRUE);
+}
+
+bool_t
+xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+		return (FALSE);
+	}
+	if(objp->code == KADM5_OK)  {
+	     if (objp->api_version == KADM5_API_VERSION_1) {
+		  if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
+		       return (FALSE);
+		  }
+	     } else {
+		  if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+		       return (FALSE);
+		  }
+	     }
+	}
+
+	return (TRUE);
+}
+
+bool_t
+xdr_cpol_arg(XDR *xdrs, cpol_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->mask)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_dpol_arg(XDR *xdrs, dpol_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_nullstring(xdrs, &objp->name)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_mpol_arg(XDR *xdrs, mpol_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
+		return (FALSE);
+	}
+	if (!xdr_long(xdrs, &objp->mask)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_gpol_arg(XDR *xdrs, gpol_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_nullstring(xdrs, &objp->name)) {
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+bool_t
+xdr_gpol_ret(XDR *xdrs, gpol_ret *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+		return (FALSE);
+	}
+	if(objp->code == KADM5_OK) {
+	    if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec))
+		return (FALSE);
+	}
+
+	return (TRUE);
+}
+
+bool_t
+xdr_gpols_arg(XDR *xdrs, gpols_arg *objp)
+{
+     if (!xdr_ui_4(xdrs, &objp->api_version)) {
+	  return (FALSE);
+     }
+     if (!xdr_nullstring(xdrs, &objp->exp)) {
+	  return (FALSE);
+     }
+     return (TRUE);
+}
+
+bool_t
+xdr_gpols_ret(XDR *xdrs, gpols_ret *objp)     
+{
+     if (!xdr_ui_4(xdrs, &objp->api_version)) {
+	  return (FALSE);
+     }
+     if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+	  return (FALSE);
+     }
+     if (objp->code == KADM5_OK) {
+	  if (!xdr_int(xdrs, &objp->count)) {
+	       return (FALSE);
+	  }
+	  if (!xdr_array(xdrs, (caddr_t *) &objp->pols,
+			 (unsigned int *) &objp->count, ~0,
+			 sizeof(char *), xdr_nullstring)) {
+	       return (FALSE);
+	  }
+     }
+
+     return (TRUE);
+}
+
+bool_t xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return (FALSE);
+	}
+     if (! xdr_kadm5_ret_t(xdrs, &objp->code) ||
+	 ! xdr_long(xdrs, &objp->privs))
+	  return FALSE;
+
+     return TRUE;
+}
+
+bool_t
+xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
+{
+    int	    ret;
+    char	    *p = NULL;
+    krb5_principal  pr = NULL;
+    static krb5_context context = NULL;
+
+    /* using a static context here is ugly, but should work
+       ok, and the other solutions are even uglier */
+
+    if (!context &&
+	kadm5_init_krb5_context(&context))
+       return(FALSE);
+
+    switch(xdrs->x_op) {
+    case XDR_ENCODE:
+	if (*objp) {
+	     if((ret = krb5_unparse_name(context, *objp, &p)) != 0) 
+		  return FALSE;
+	}
+	if(!xdr_nullstring(xdrs, &p))
+	    return FALSE;
+	if (p) free(p);
+	break;
+    case XDR_DECODE:
+	if(!xdr_nullstring(xdrs, &p))
+	    return FALSE;
+	if (p) {
+	     ret = krb5_parse_name(context, p, &pr);
+	     if(ret != 0) 
+		  return FALSE;
+	     *objp = pr;
+	     free(p);
+	} else
+	     *objp = NULL;
+	break;
+    case XDR_FREE:
+	if(*objp != NULL) 
+	    krb5_free_principal(context, *objp);
+	break;
+    }
+    return TRUE;
+}
+
+bool_t
+xdr_krb5_octet(XDR *xdrs, krb5_octet *objp)
+{
+   if (!xdr_u_char(xdrs, objp))
+	return (FALSE);
+   return (TRUE);
+}
+
+bool_t
+xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp)
+{
+   /*
+    * This used to be xdr_krb5_keytype, but keytypes and enctypes have
+    * been merged into only enctypes.  However, randkey_principal
+    * already ensures that only a key of ENCTYPE_DES_CBC_CRC will be
+    * returned to v1 clients, and ENCTYPE_DES_CBC_CRC has the same
+    * value as KEYTYPE_DES used too, which is what all v1 clients
+    * expect.  Therefore, IMHO, just encoding whatever enctype we get
+    * is safe.
+    */
+
+   if (!xdr_u_int(xdrs, (unsigned int *) objp))
+	return (FALSE);
+   return (TRUE);
+}
+
+bool_t
+xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp)
+{
+    if (!xdr_int32(xdrs, (int32_t *) objp))
+	return FALSE;
+    return TRUE;
+}
+
+bool_t
+xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp)
+{
+   /* XXX This only works because free_keyblock assumes ->contents
+      is allocated by malloc() */
+
+   if(!xdr_krb5_enctype(xdrs, &objp->enctype))
+      return FALSE;
+   if(!xdr_bytes(xdrs, (char **) &objp->contents, (unsigned int *)
+		 &objp->length, ~0))
+      return FALSE;
+   return TRUE;
+}
diff --git a/krb5-1-6/src/lib/kadm5/logger.c b/krb5-1-6/src/lib/kadm5/logger.c
new file mode 100644
index 000000000..7fef3475a
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/logger.c
@@ -0,0 +1,972 @@
+/*
+ * lib/kadm/logger.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/* KADM5 wants non-syslog log files to contain syslog-like entries */
+#define VERBOSE_LOGS
+
+/*
+ * logger.c	- Handle logging functions for those who want it.
+ */
+#include "k5-int.h"
+#include "adm_proto.h"
+#include "com_err.h"
+#include <stdio.h>
+#include <ctype.h>
+#ifdef	HAVE_SYSLOG_H
+#include <syslog.h>
+#endif	/* HAVE_SYSLOG_H */
+#ifdef	HAVE_STDARG_H
+#include <stdarg.h>
+#else	/* HAVE_STDARG_H */
+#include <varargs.h>
+#endif	/* HAVE_STDARG_H */
+
+#define	KRB5_KLOG_MAX_ERRMSG_SIZE	2048
+#ifndef	MAXHOSTNAMELEN
+#define	MAXHOSTNAMELEN	256
+#endif	/* MAXHOSTNAMELEN */
+
+/* This is to assure that we have at least one match in the syslog stuff */
+#ifndef	LOG_AUTH
+#define	LOG_AUTH	0
+#endif	/* LOG_AUTH */
+#ifndef	LOG_ERR
+#define	LOG_ERR		0
+#endif	/* LOG_ERR */
+
+#define lspec_parse_err_1	"%s: cannot parse <%s>\n"
+#define lspec_parse_err_2	"%s: warning - logging entry syntax error\n"
+#define log_file_err		"%s: error writing to %s\n"
+#define log_device_err		"%s: error writing to %s device\n"
+#define log_ufo_string		"?\?\?" /* nb: avoid trigraphs */
+#define log_emerg_string	"EMERGENCY"
+#define log_alert_string	"ALERT"
+#define log_crit_string		"CRITICAL"
+#define log_err_string		"Error"
+#define log_warning_string	"Warning"
+#define log_notice_string	"Notice"
+#define log_info_string		"info"
+#define log_debug_string	"debug"
+
+/*
+ * Output logging.
+ *
+ * Output logging is now controlled by the configuration file.  We can specify
+ * the following syntaxes under the [logging]->entity specification.
+ *	FILE<opentype><pathname>
+ *	SYSLOG[=<severity>[:<facility>]]
+ *	STDERR
+ *	CONSOLE
+ *	DEVICE=<device-spec>
+ *
+ * Where:
+ *	<opentype> is ":" for open/append, "=" for open/create.
+ *	<pathname> is a valid path name.
+ *	<severity> is one of: (default = ERR)
+ *		EMERG
+ *		ALERT
+ *		CRIT
+ *		ERR
+ *		WARNING
+ *		NOTICE
+ *		INFO
+ *		DEBUG
+ *	<facility> is one of: (default = AUTH)
+ *		KERN
+ *		USER
+ *		MAIL
+ *		DAEMON
+ *		AUTH
+ *		LPR
+ *		NEWS
+ *		UUCP
+ *		CRON
+ *		LOCAL0..LOCAL7
+ *	<device-spec> is a valid device specification.
+ */
+struct log_entry {
+    enum log_type { K_LOG_FILE,
+			K_LOG_SYSLOG,
+			K_LOG_STDERR,
+			K_LOG_CONSOLE,
+			K_LOG_DEVICE,
+			K_LOG_NONE } log_type;
+    krb5_pointer log_2free;
+    union log_union {
+	struct log_file {
+	    FILE	*lf_filep;
+	    char	*lf_fname;
+	} log_file;
+	struct log_syslog {
+	    int		ls_facility;
+	    int		ls_severity;
+	} log_syslog;
+	struct log_device {
+	    FILE	*ld_filep;
+	    char	*ld_devname;
+	} log_device;
+    } log_union;
+};
+#define	lfu_filep	log_union.log_file.lf_filep
+#define	lfu_fname	log_union.log_file.lf_fname
+#define	lsu_facility	log_union.log_syslog.ls_facility
+#define	lsu_severity	log_union.log_syslog.ls_severity
+#define	ldu_filep	log_union.log_device.ld_filep
+#define	ldu_devname	log_union.log_device.ld_devname
+
+struct log_control {
+    struct log_entry	*log_entries;
+    int			log_nentries;
+    char		*log_whoami;
+    char		*log_hostname;
+    krb5_boolean	log_opened;
+};
+
+static struct log_control log_control = {
+    (struct log_entry *) NULL,
+    0,
+    (char *) NULL,
+    (char *) NULL,
+    0
+};
+static struct log_entry	def_log_entry;
+
+/*
+ * These macros define any special processing that needs to happen for
+ * devices.  For unix, of course, this is hardly anything.
+ */
+#define	DEVICE_OPEN(d, m)	fopen(d, m)
+#define	CONSOLE_OPEN(m)		fopen("/dev/console", m)
+#define	DEVICE_PRINT(f, m)	((fprintf(f, "%s\r\n", m) >= 0) ? 	\
+				 (fflush(f), 0) :			\
+				 -1)
+#define	DEVICE_CLOSE(d)		fclose(d)
+
+
+/*
+ * klog_com_err_proc()	- Handle com_err(3) messages as specified by the
+ *			  profile.
+ */
+static krb5_context err_context;
+static void
+klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
+{
+    char	outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
+    int		lindex;
+    const char	*actual_format;
+#ifdef	HAVE_SYSLOG
+    int		log_pri = -1;
+#endif	/* HAVE_SYSLOG */
+    char	*cp;
+    char	*syslogp;
+
+    /* Make the header */
+    sprintf(outbuf, "%s: ", whoami);
+    /*
+     * Squirrel away address after header for syslog since syslog makes
+     * a header
+     */
+    syslogp = &outbuf[strlen(outbuf)];
+
+    /* If reporting an error message, separate it. */
+    if (code) {
+        char *emsg;
+        outbuf[sizeof(outbuf) - 1] = '\0';
+
+	emsg = krb5_get_error_message (err_context, code);
+	strncat(outbuf, emsg, sizeof(outbuf) - 1 - strlen(outbuf));
+	strncat(outbuf, " - ", sizeof(outbuf) - 1 - strlen(outbuf));
+	krb5_free_error_message(err_context, emsg);
+    }
+    cp = &outbuf[strlen(outbuf)];
+    
+    actual_format = format;
+#ifdef	HAVE_SYSLOG
+    /*
+     * This is an unpleasant hack.  If the first character is less than
+     * 8, then we assume that it is a priority.
+     *
+     * Since it is not guaranteed that there is a direct mapping between
+     * syslog priorities (e.g. Ultrix and old BSD), we resort to this
+     * intermediate representation.
+     */
+    if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) {
+	actual_format = (format + 1);
+	switch ((unsigned char) *format) {
+#ifdef	LOG_EMERG
+	case 1:
+	    log_pri = LOG_EMERG;
+	    break;
+#endif /* LOG_EMERG */
+#ifdef	LOG_ALERT
+	case 2:
+	    log_pri = LOG_ALERT;
+	    break;
+#endif /* LOG_ALERT */
+#ifdef	LOG_CRIT
+	case 3:
+	    log_pri = LOG_CRIT;
+	    break;
+#endif /* LOG_CRIT */
+	default:
+	case 4:
+	    log_pri = LOG_ERR;
+	    break;
+#ifdef	LOG_WARNING
+	case 5:
+	    log_pri = LOG_WARNING;
+	    break;
+#endif /* LOG_WARNING */
+#ifdef	LOG_NOTICE
+	case 6:
+	    log_pri = LOG_NOTICE;
+	    break;
+#endif /* LOG_NOTICE */
+#ifdef	LOG_INFO
+	case 7:
+	    log_pri = LOG_INFO;
+	    break;
+#endif /* LOG_INFO */
+#ifdef	LOG_DEBUG
+	case 8:
+	    log_pri = LOG_DEBUG;
+	    break;
+#endif /* LOG_DEBUG */
+	}
+    } 
+#endif	/* HAVE_SYSLOG */
+
+    /* Now format the actual message */
+#if	HAVE_VSNPRINTF
+    vsnprintf(cp, sizeof(outbuf) - (cp - outbuf), actual_format, ap);
+#elif	HAVE_VSPRINTF
+    vsprintf(cp, actual_format, ap);
+#else	/* HAVE_VSPRINTF */
+    sprintf(cp, actual_format, ((int *) ap)[0], ((int *) ap)[1],
+	    ((int *) ap)[2], ((int *) ap)[3],
+	    ((int *) ap)[4], ((int *) ap)[5]);
+#endif	/* HAVE_VSPRINTF */
+    
+    /*
+     * Now that we have the message formatted, perform the output to each
+     * logging specification.
+     */
+    for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
+	switch (log_control.log_entries[lindex].log_type) {
+	case K_LOG_FILE:
+	case K_LOG_STDERR:
+	    /*
+	     * Files/standard error.
+	     */
+	    if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
+			outbuf) < 0) {
+		/* Attempt to report error */
+		fprintf(stderr, log_file_err, whoami,
+			log_control.log_entries[lindex].lfu_fname);
+	    }
+	    else {
+		fflush(log_control.log_entries[lindex].lfu_filep);
+	    }
+	    break;
+	case K_LOG_CONSOLE:
+	case K_LOG_DEVICE:
+	    /*
+	     * Devices (may need special handling)
+	     */
+	    if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
+			     outbuf) < 0) {
+		/* Attempt to report error */
+		fprintf(stderr, log_device_err, whoami,
+			log_control.log_entries[lindex].ldu_devname);
+	    }
+	    break;
+#ifdef	HAVE_SYSLOG
+	case K_LOG_SYSLOG:
+	    /*
+	     * System log.
+	     */
+	    /*
+	     * If we have specified a priority through our hackery, then
+	     * use it, otherwise use the default.
+	     */
+	    if (log_pri >= 0)
+		log_pri |= log_control.log_entries[lindex].lsu_facility;
+	    else
+		log_pri = log_control.log_entries[lindex].lsu_facility |
+		    log_control.log_entries[lindex].lsu_severity;
+					       
+	    /* Log the message with our header trimmed off */
+	    syslog(log_pri, "%s", syslogp);
+	    break;
+#endif /* HAVE_SYSLOG */
+	default:
+	    break;
+	}
+    }
+}
+
+/*
+ * krb5_klog_init()	- Initialize logging.
+ *
+ * This routine parses the syntax described above to specify destinations for
+ * com_err(3) or krb5_klog_syslog() messages generated by the caller.
+ *
+ * Parameters:
+ *	kcontext	- Kerberos context.
+ *	ename		- Entity name as it is to appear in the profile.
+ *	whoami		- Entity name as it is to appear in error output.
+ *	do_com_err	- Take over com_err(3) processing.
+ *
+ * Implicit inputs:
+ *	stderr		- This is where STDERR output goes.
+ *
+ * Implicit outputs:
+ *	log_nentries	- Number of log entries, both valid and invalid.
+ *	log_control	- List of entries (log_nentries long) which contains
+ *			  data for klog_com_err_proc() to use to determine
+ *			  where/how to send output.
+ */
+krb5_error_code
+krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err)
+{
+    const char	*logging_profent[3];
+    const char	*logging_defent[3];
+    char	**logging_specs;
+    int		i, ngood;
+    char	*cp, *cp2;
+    char	savec = '\0';
+    int		error;
+    int		do_openlog, log_facility;
+    FILE	*f;
+
+    /* Initialize */
+    do_openlog = 0;
+    log_facility = 0;
+
+    err_context = kcontext;
+
+    /*
+     * Look up [logging]-><ename> in the profile.  If that doesn't
+     * succeed, then look for [logging]->default.
+     */
+    logging_profent[0] = "logging";
+    logging_profent[1] = ename;
+    logging_profent[2] = (char *) NULL;
+    logging_defent[0] = "logging";
+    logging_defent[1] = "default";
+    logging_defent[2] = (char *) NULL;
+    logging_specs = (char **) NULL;
+    ngood = 0;
+    log_control.log_nentries = 0;
+    if (!profile_get_values(kcontext->profile,
+			    logging_profent,
+			    &logging_specs) ||
+	!profile_get_values(kcontext->profile,
+			    logging_defent,
+			    &logging_specs)) {
+	/*
+	 * We have a match, so we first count the number of elements
+	 */
+	for (log_control.log_nentries = 0;
+	     logging_specs[log_control.log_nentries];
+	     log_control.log_nentries++);
+
+	/*
+	 * Now allocate our structure.
+	 */
+	log_control.log_entries = (struct log_entry *)
+	    malloc(log_control.log_nentries * sizeof(struct log_entry));
+	if (log_control.log_entries) {
+	    /*
+	     * Scan through the list.
+	     */
+	    for (i=0; i<log_control.log_nentries; i++) {
+		log_control.log_entries[i].log_type = K_LOG_NONE;
+		log_control.log_entries[i].log_2free = logging_specs[i];
+		/*
+		 * The format is:
+		 *	<whitespace><data><whitespace>
+		 * so, trim off the leading and trailing whitespace here.
+		 */
+		for (cp = logging_specs[i]; isspace((int) *cp); cp++);
+		for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
+		     isspace((int) *cp2); cp2--);
+		cp2++;
+		*cp2 = '\0';
+		/*
+		 * Is this a file?
+		 */
+		if (!strncasecmp(cp, "FILE", 4)) {
+		    /*
+		     * Check for append/overwrite, then open the file.
+		     */
+		    if (cp[4] == ':' || cp[4] == '=') {
+			f = fopen(&cp[5], (cp[4] == ':') ? "a+" : "w");
+			if (f) {
+			    log_control.log_entries[i].lfu_filep = f;
+			    log_control.log_entries[i].log_type = K_LOG_FILE;
+			    log_control.log_entries[i].lfu_fname = &cp[5];
+			} else {
+			    fprintf(stderr,"Couldn't open log file %s: %s\n",
+				    &cp[5], error_message(errno));
+			    continue;
+			}
+		    }
+		}
+#ifdef	HAVE_SYSLOG
+		/*
+		 * Is this a syslog?
+		 */
+		else if (!strncasecmp(cp, "SYSLOG", 6)) {
+		    error = 0;
+		    log_control.log_entries[i].lsu_facility = LOG_AUTH;
+		    log_control.log_entries[i].lsu_severity = LOG_ERR;
+		    /*
+		     * Is there a severify specified?
+		     */
+		    if (cp[6] == ':') {
+			/*
+			 * Find the end of the severity.
+			 */
+			cp2 = strchr(&cp[7], ':');
+			if (cp2) {
+			    savec = *cp2;
+			    *cp2 = '\0';
+			    cp2++;
+			}
+
+			/*
+			 * Match a severity.
+			 */
+			if (!strcasecmp(&cp[7], "ERR")) {
+			    log_control.log_entries[i].lsu_severity = LOG_ERR;
+			}
+#ifdef	LOG_EMERG
+			else if (!strcasecmp(&cp[7], "EMERG")) {
+			    log_control.log_entries[i].lsu_severity =
+				LOG_EMERG;
+			}
+#endif	/* LOG_EMERG */
+#ifdef	LOG_ALERT
+			else if (!strcasecmp(&cp[7], "ALERT")) {
+			    log_control.log_entries[i].lsu_severity =
+				LOG_ALERT;
+			}
+#endif	/* LOG_ALERT */
+#ifdef	LOG_CRIT
+			else if (!strcasecmp(&cp[7], "CRIT")) {
+			    log_control.log_entries[i].lsu_severity = LOG_CRIT;
+			}
+#endif	/* LOG_CRIT */
+#ifdef	LOG_WARNING
+			else if (!strcasecmp(&cp[7], "WARNING")) {
+			    log_control.log_entries[i].lsu_severity =
+				LOG_WARNING;
+			}
+#endif	/* LOG_WARNING */
+#ifdef	LOG_NOTICE
+			else if (!strcasecmp(&cp[7], "NOTICE")) {
+			    log_control.log_entries[i].lsu_severity =
+				LOG_NOTICE;
+			}
+#endif	/* LOG_NOTICE */
+#ifdef	LOG_INFO
+			else if (!strcasecmp(&cp[7], "INFO")) {
+			    log_control.log_entries[i].lsu_severity = LOG_INFO;
+			}
+#endif	/* LOG_INFO */
+#ifdef	LOG_DEBUG
+			else if (!strcasecmp(&cp[7], "DEBUG")) {
+			    log_control.log_entries[i].lsu_severity =
+				LOG_DEBUG;
+			}
+#endif	/* LOG_DEBUG */
+			else
+			    error = 1;
+
+			/*
+			 * If there is a facility present, then parse that.
+			 */
+			if (cp2) {
+			    static const struct {
+				const char *name;
+				int value;
+			    } facilities[] = {
+				{ "AUTH",	LOG_AUTH	},
+#ifdef	LOG_AUTHPRIV
+				{ "AUTHPRIV",	LOG_AUTHPRIV	},
+#endif	/* LOG_AUTHPRIV */
+#ifdef	LOG_KERN
+				{ "KERN",	LOG_KERN	},
+#endif	/* LOG_KERN */
+#ifdef	LOG_USER
+				{ "USER",	LOG_USER	},
+#endif	/* LOG_USER */
+#ifdef	LOG_MAIL
+				{ "MAIL",	LOG_MAIL	},
+#endif	/* LOG_MAIL */
+#ifdef	LOG_DAEMON
+				{ "DAEMON",	LOG_DAEMON	},
+#endif	/* LOG_DAEMON */
+#ifdef	LOG_FTP
+				{ "FTP",	LOG_FTP		},
+#endif	/* LOG_FTP */
+#ifdef	LOG_LPR
+				{ "LPR",	LOG_LPR		},
+#endif	/* LOG_LPR */
+#ifdef	LOG_NEWS
+				{ "NEWS",	LOG_NEWS	},
+#endif	/* LOG_NEWS */
+#ifdef	LOG_UUCP
+				{ "UUCP",	LOG_UUCP	},
+#endif	/* LOG_UUCP */
+#ifdef	LOG_CRON
+				{ "CRON",	LOG_CRON	},
+#endif	/* LOG_CRON */
+#ifdef	LOG_LOCAL0
+				{ "LOCAL0",	LOG_LOCAL0	},
+#endif	/* LOG_LOCAL0 */
+#ifdef	LOG_LOCAL1
+				{ "LOCAL1",	LOG_LOCAL1	},
+#endif	/* LOG_LOCAL1 */
+#ifdef	LOG_LOCAL2
+				{ "LOCAL2",	LOG_LOCAL2	},
+#endif	/* LOG_LOCAL2 */
+#ifdef	LOG_LOCAL3
+				{ "LOCAL3",	LOG_LOCAL3	},
+#endif	/* LOG_LOCAL3 */
+#ifdef	LOG_LOCAL4
+				{ "LOCAL4",	LOG_LOCAL4	},
+#endif	/* LOG_LOCAL4 */
+#ifdef	LOG_LOCAL5
+				{ "LOCAL5",	LOG_LOCAL5	},
+#endif	/* LOG_LOCAL5 */
+#ifdef	LOG_LOCAL6
+				{ "LOCAL6",	LOG_LOCAL6	},
+#endif	/* LOG_LOCAL6 */
+#ifdef	LOG_LOCAL7
+				{ "LOCAL7",	LOG_LOCAL7	},
+#endif	/* LOG_LOCAL7 */
+			    };
+			    int j;
+
+			    for (j = 0; j < sizeof(facilities)/sizeof(facilities[0]); j++)
+				if (!strcasecmp(cp2, facilities[j].name)) {
+				    log_control.log_entries[i].lsu_facility = facilities[j].value;
+				    break;
+				}
+			    cp2--;
+			    *cp2 = savec;
+			}
+		    }
+		    if (!error) {
+			log_control.log_entries[i].log_type = K_LOG_SYSLOG;
+			do_openlog = 1;
+			log_facility = log_control.log_entries[i].lsu_facility;
+		    }
+		}
+#endif	/* HAVE_SYSLOG */
+		/*
+		 * Is this a standard error specification?
+		 */
+		else if (!strcasecmp(cp, "STDERR")) {
+		    log_control.log_entries[i].lfu_filep =
+			fdopen(fileno(stderr), "a+");
+		    if (log_control.log_entries[i].lfu_filep) {
+			log_control.log_entries[i].log_type = K_LOG_STDERR;
+			log_control.log_entries[i].lfu_fname =
+			    "standard error";
+		    }
+		}
+		/*
+		 * Is this a specification of the console?
+		 */
+		else if (!strcasecmp(cp, "CONSOLE")) {
+		    log_control.log_entries[i].ldu_filep =
+			CONSOLE_OPEN("a+");
+		    if (log_control.log_entries[i].ldu_filep) {
+			log_control.log_entries[i].log_type = K_LOG_CONSOLE;
+			log_control.log_entries[i].ldu_devname = "console";
+		    }
+		}
+		/*
+		 * Is this a specification of a device?
+		 */
+		else if (!strncasecmp(cp, "DEVICE", 6)) {
+		    /*
+		     * We handle devices very similarly to files.
+		     */
+		    if (cp[6] == '=') {
+			log_control.log_entries[i].ldu_filep = 
+			    DEVICE_OPEN(&cp[7], "w");
+			if (log_control.log_entries[i].ldu_filep) {
+			    log_control.log_entries[i].log_type = K_LOG_DEVICE;
+			    log_control.log_entries[i].ldu_devname = &cp[7];
+			}
+		    }
+		}
+		/*
+		 * See if we successfully parsed this specification.
+		 */
+		if (log_control.log_entries[i].log_type == K_LOG_NONE) {
+		    fprintf(stderr, lspec_parse_err_1, whoami, cp);
+		    fprintf(stderr, lspec_parse_err_2, whoami);
+		}
+		else
+		    ngood++;
+	    }
+	}
+	/*
+	 * If we didn't find anything, then free our lists.
+	 */
+	if (ngood == 0) {
+	    for (i=0; i<log_control.log_nentries; i++)
+		free(logging_specs[i]);
+	}
+	free(logging_specs);
+    }
+    /*
+     * If we didn't find anything, go for the default which is to log to
+     * the system log.
+     */
+    if (ngood == 0) {
+	if (log_control.log_entries)
+	    free(log_control.log_entries);
+	log_control.log_entries = &def_log_entry;
+	log_control.log_entries->log_type = K_LOG_SYSLOG;
+	log_control.log_entries->log_2free = (krb5_pointer) NULL;
+	log_facility = log_control.log_entries->lsu_facility = LOG_AUTH;
+	log_control.log_entries->lsu_severity = LOG_ERR;
+	do_openlog = 1;
+	log_control.log_nentries = 1;
+    }
+    if (log_control.log_nentries) {
+	log_control.log_whoami = (char *) malloc(strlen(whoami)+1);
+	if (log_control.log_whoami)
+	    strcpy(log_control.log_whoami, whoami);
+
+	log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1);
+	if (log_control.log_hostname) {
+	    gethostname(log_control.log_hostname, MAXHOSTNAMELEN);
+	    log_control.log_hostname[MAXHOSTNAMELEN] = '\0';
+	}
+#ifdef	HAVE_OPENLOG
+	if (do_openlog) {
+	    openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
+	    log_control.log_opened = 1;
+	}
+#endif /* HAVE_OPENLOG */
+	if (do_com_err)
+	    (void) set_com_err_hook(klog_com_err_proc);
+    }
+    return((log_control.log_nentries) ? 0 : ENOENT);
+}
+
+/*
+ * krb5_klog_close()	- Close the logging context and free all data.
+ */
+void
+krb5_klog_close(krb5_context kcontext)
+{
+    int lindex;
+    (void) reset_com_err_hook();
+    for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
+	switch (log_control.log_entries[lindex].log_type) {
+	case K_LOG_FILE:
+	case K_LOG_STDERR:
+	    /*
+	     * Files/standard error.
+	     */
+	    fclose(log_control.log_entries[lindex].lfu_filep);
+	    break;
+	case K_LOG_CONSOLE:
+	case K_LOG_DEVICE:
+	    /*
+	     * Devices (may need special handling)
+	     */
+	    DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
+	    break;
+#ifdef	HAVE_SYSLOG
+	case K_LOG_SYSLOG:
+	    /*
+	     * System log.
+	     */
+	    break;
+#endif	/* HAVE_SYSLOG */
+	default:
+	    break;
+	}
+	if (log_control.log_entries[lindex].log_2free)
+	    free(log_control.log_entries[lindex].log_2free);
+    }
+    if (log_control.log_entries != &def_log_entry)
+	free(log_control.log_entries);
+    log_control.log_entries = (struct log_entry *) NULL;
+    log_control.log_nentries = 0;
+    if (log_control.log_whoami)
+	free(log_control.log_whoami);
+    log_control.log_whoami = (char *) NULL;
+    if (log_control.log_hostname)
+	free(log_control.log_hostname);
+    log_control.log_hostname = (char *) NULL;
+#ifdef	HAVE_CLOSELOG
+    if (log_control.log_opened)
+	closelog();
+#endif	/* HAVE_CLOSELOG */
+}
+
+/*
+ * severity2string()	- Convert a severity to a string.
+ */
+static const char *
+severity2string(int severity)
+{
+    int s;
+    const char *ss;
+
+    s = severity & LOG_PRIMASK;
+    ss = log_ufo_string;
+    switch (s) {
+#ifdef	LOG_EMERG
+    case LOG_EMERG:
+	ss = log_emerg_string;
+	break;
+#endif	/* LOG_EMERG */
+#ifdef	LOG_ALERT
+    case LOG_ALERT:
+	ss = log_alert_string;
+	break;
+#endif	/* LOG_ALERT */
+#ifdef	LOG_CRIT
+    case LOG_CRIT:
+	ss = log_crit_string;
+	break;
+#endif	/* LOG_CRIT */
+    case LOG_ERR:
+	ss = log_err_string;
+	break;
+#ifdef	LOG_WARNING
+    case LOG_WARNING:
+	ss = log_warning_string;
+	break;
+#endif	/* LOG_WARNING */
+#ifdef	LOG_NOTICE
+    case LOG_NOTICE:
+	ss = log_notice_string;
+	break;
+#endif	/* LOG_NOTICE */
+#ifdef	LOG_INFO
+    case LOG_INFO:
+	ss = log_info_string;
+	break;
+#endif	/* LOG_INFO */
+#ifdef	LOG_DEBUG
+    case LOG_DEBUG:
+	ss = log_debug_string;
+	break;
+#endif	/* LOG_DEBUG */
+    }
+    return(ss);
+}
+
+/*
+ * krb5_klog_syslog()	- Simulate the calling sequence of syslog(3), while
+ *			  also performing the logging redirection as specified
+ *			  by krb5_klog_init().
+ */
+static int
+klog_vsyslog(int priority, const char *format, va_list arglist)
+{
+    char	outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
+    int		lindex;
+    char	*syslogp;
+    char	*cp;
+    time_t	now;
+#ifdef	HAVE_STRFTIME
+    size_t	soff;
+#endif	/* HAVE_STRFTIME */
+
+    /*
+     * Format a syslog-esque message of the format:
+     *
+     * (verbose form)
+     * 		<date> <hostname> <id>[<pid>](<priority>): <message>
+     *
+     * (short form)
+     *		<date> <message>
+     */
+    cp = outbuf;
+    (void) time(&now);
+#ifdef	HAVE_STRFTIME
+    /*
+     * Format the date: mon dd hh:mm:ss
+     */
+    soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", localtime(&now));
+    if (soff > 0)
+	cp += soff;
+    else
+	return(-1);
+#else	/* HAVE_STRFTIME */
+    /*
+     * Format the date:
+     * We ASSUME here that the output of ctime is of the format:
+     *	dow mon dd hh:mm:ss tzs yyyy\n
+     *  012345678901234567890123456789
+     */
+    strncpy(outbuf, ctime(&now) + 4, 15);
+    cp += 15;
+#endif	/* HAVE_STRFTIME */
+#ifdef VERBOSE_LOGS
+    sprintf(cp, " %s %s[%ld](%s): ",
+	    log_control.log_hostname ? log_control.log_hostname : "", 
+	    log_control.log_whoami ? log_control.log_whoami : "", 
+	    (long) getpid(),
+	    severity2string(priority));
+#else
+    sprintf(cp, " ");
+#endif
+    syslogp = &outbuf[strlen(outbuf)];
+
+    /* Now format the actual message */
+#ifdef	HAVE_VSNPRINTF
+    vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist);
+#elif	HAVE_VSPRINTF
+    vsprintf(syslogp, format, arglist);
+#else	/* HAVE_VSPRINTF */
+    sprintf(syslogp, format, ((int *) arglist)[0], ((int *) arglist)[1],
+	    ((int *) arglist)[2], ((int *) arglist)[3],
+	    ((int *) arglist)[4], ((int *) arglist)[5]);
+#endif	/* HAVE_VSPRINTF */
+
+    /*
+     * If the user did not use krb5_klog_init() instead of dropping
+     * the request on the floor, syslog it - if it exists
+     */
+#ifdef HAVE_SYSLOG
+    if (log_control.log_nentries == 0) {
+	/* Log the message with our header trimmed off */
+	syslog(priority, "%s", syslogp);
+    }
+#endif
+
+    /*
+     * Now that we have the message formatted, perform the output to each
+     * logging specification.
+     */
+    for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
+	switch (log_control.log_entries[lindex].log_type) {
+	case K_LOG_FILE:
+	case K_LOG_STDERR:
+	    /*
+	     * Files/standard error.
+	     */
+	    if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
+			outbuf) < 0) {
+		/* Attempt to report error */
+		fprintf(stderr, log_file_err, log_control.log_whoami,
+			log_control.log_entries[lindex].lfu_fname);
+	    }
+	    else {
+		fflush(log_control.log_entries[lindex].lfu_filep);
+	    }
+	    break;
+	case K_LOG_CONSOLE:
+	case K_LOG_DEVICE:
+	    /*
+	     * Devices (may need special handling)
+	     */
+	    if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
+			     outbuf) < 0) {
+		/* Attempt to report error */
+		fprintf(stderr, log_device_err, log_control.log_whoami,
+			log_control.log_entries[lindex].ldu_devname);
+	    }
+	    break;
+#ifdef	HAVE_SYSLOG
+	case K_LOG_SYSLOG:
+	    /*
+	     * System log.
+	     */
+					       
+	    /* Log the message with our header trimmed off */
+	    syslog(priority, "%s", syslogp);
+	    break;
+#endif /* HAVE_SYSLOG */
+	default:
+	    break;
+	}
+    }
+    return(0);
+}
+
+int
+krb5_klog_syslog(int priority, const char *format, ...)
+{
+    int		retval;
+    va_list	pvar;
+
+    va_start(pvar, format);
+    retval = klog_vsyslog(priority, format, pvar);
+    va_end(pvar);
+    return(retval);
+}
+
+/*
+ * krb5_klog_reopen() - Close and reopen any open (non-syslog) log files.
+ *                      This function is called when a SIGHUP is received
+ *                      so that external log-archival utilities may
+ *                      alert the Kerberos daemons that they should get
+ *                      a new file descriptor for the give filename.
+ */
+void
+krb5_klog_reopen(krb5_context kcontext)
+{
+    int lindex;
+    FILE *f;
+
+    /*
+     * Only logs which are actually files need to be closed
+     * and reopened in response to a SIGHUP
+     */
+    for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
+	if (log_control.log_entries[lindex].log_type == K_LOG_FILE) {
+	    fclose(log_control.log_entries[lindex].lfu_filep);
+	    /*
+	     * In case the old logfile did not get moved out of the
+	     * way, open for append to prevent squashing the old logs.
+	     */
+	    f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
+	    if (f) {
+		log_control.log_entries[lindex].lfu_filep = f;
+	    } else {
+		fprintf(stderr, "Couldn't open log file %s: %s\n",
+			log_control.log_entries[lindex].lfu_fname,
+			error_message(errno));
+	    }
+	}
+    }
+}
diff --git a/krb5-1-6/src/lib/kadm5/misc_free.c b/krb5-1-6/src/lib/kadm5/misc_free.c
new file mode 100644
index 000000000..9dc91b53f
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/misc_free.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+#include	<kadm5/admin.h>
+#include	<stdlib.h>
+#include	"server_internal.h"
+
+kadm5_ret_t
+kadm5_free_policy_ent(void *server_handle, kadm5_policy_ent_t val)
+{
+    kadm5_server_handle_t	handle = server_handle;
+
+    _KADM5_CHECK_HANDLE(server_handle);
+
+    if(val) {
+	if (val->policy)
+	    free(val->policy);
+	if (handle->api_version == KADM5_API_VERSION_1)
+	     free(val);
+    }
+    return KADM5_OK;
+}
+
+kadm5_ret_t
+     kadm5_free_name_list(void *server_handle, char **names, int count)
+{
+    _KADM5_CHECK_HANDLE(server_handle);
+	  
+    while (count--)
+	  free(names[count]);
+     free(names);
+    return KADM5_OK;
+}
+
+/* XXX this ought to be in libkrb5.a, but isn't */
+kadm5_ret_t krb5_free_key_data_contents(context, key)
+   krb5_context context;
+   krb5_key_data *key;
+{
+     int i, idx;
+     
+     idx = (key->key_data_ver == 1 ? 1 : 2);
+     for (i = 0; i < idx; i++) {
+	  if (key->key_data_contents[i]) {
+	       memset(key->key_data_contents[i], 0, key->key_data_length[i]);
+	       free(key->key_data_contents[i]);
+	  }
+     }
+     return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_free_key_data(void *server_handle,
+				krb5_int16 *n_key_data,
+				krb5_key_data *key_data)
+{
+     kadm5_server_handle_t	handle = server_handle;
+     int i, nkeys = (int) *n_key_data;
+
+     _KADM5_CHECK_HANDLE(server_handle);
+
+     if (key_data == NULL)
+	  return KADM5_OK;
+     
+     for (i = 0; i < nkeys; i++)
+	  krb5_free_key_data_contents(handle->context, &key_data[i]);
+     free(key_data);
+     return KADM5_OK;
+}
+
+kadm5_ret_t
+kadm5_free_principal_ent(void *server_handle,
+			      kadm5_principal_ent_t val)
+{
+    kadm5_server_handle_t	handle = server_handle;
+    int i;
+
+    _KADM5_CHECK_HANDLE(server_handle);
+
+    if(val) {
+	if(val->principal) 
+	    krb5_free_principal(handle->context, val->principal);
+	if(val->mod_name)
+	    krb5_free_principal(handle->context, val->mod_name);
+	if(val->policy)
+	    free(val->policy);
+	if (handle->api_version > KADM5_API_VERSION_1) {
+	     if (val->n_key_data) {
+		  for (i = 0; i < val->n_key_data; i++)
+		       krb5_free_key_data_contents(handle->context,
+						   &val->key_data[i]);
+		  free(val->key_data);
+	     }
+	     if (val->tl_data) {
+		  krb5_tl_data *tl;
+		  
+		  while (val->tl_data) {
+		       tl = val->tl_data->tl_data_next;
+		       free(val->tl_data->tl_data_contents);
+		       free(val->tl_data);
+		       val->tl_data = tl;
+		  }
+	     }
+	}
+	
+	if (handle->api_version == KADM5_API_VERSION_1)
+	     free(val);
+    }
+    return KADM5_OK;
+}
diff --git a/krb5-1-6/src/lib/kadm5/ovsec_glue.c b/krb5-1-6/src/lib/kadm5/ovsec_glue.c
new file mode 100644
index 000000000..a3ae6de42
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/ovsec_glue.c
@@ -0,0 +1,194 @@
+#define USE_KADM5_API_VERSION 1
+#include <kadm5/admin.h>
+#include <string.h>
+
+ovsec_kadm_ret_t ovsec_kadm_init_with_password(char *client_name, char *pass,
+					       char *service_name,
+					       char *realm,
+					       krb5_ui_4 struct_version,
+					       krb5_ui_4 api_version,
+					       char **db_args,
+					       void **server_handle)
+{
+     return kadm5_init_with_password(client_name, pass, service_name,
+				     realm, struct_version, api_version, db_args,
+				     server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_init_with_skey(char *client_name, char *keytab,
+					   char *service_name,
+					   char *realm,
+					   krb5_ui_4 struct_version,
+					   krb5_ui_4 api_version,
+					   char **db_args,
+					   void **server_handle)
+{
+     return kadm5_init_with_skey(client_name, keytab, service_name, realm,
+				 struct_version, api_version, db_args,
+				 server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_init(char *client_name, char *from_stash,
+				 char *service_name,
+				 char *realm,
+				 krb5_ui_4 struct_version,
+				 krb5_ui_4 api_version,
+				 char **db_args,
+				 void **server_handle)
+{
+     return kadm5_init(client_name, from_stash, service_name,
+		       realm, struct_version, api_version, db_args,
+		       server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_destroy(void *server_handle)
+{
+     return kadm5_destroy(server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_flush(void *server_handle)
+{
+     return kadm5_flush(server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_create_principal(void *server_handle,
+					     ovsec_kadm_principal_ent_t entry,
+					     long mask,
+					     char *password)
+{
+     return kadm5_create_principal(server_handle,
+				   (kadm5_principal_ent_t)
+				   entry, mask, password);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_delete_principal(void *server_handle,
+					     krb5_principal principal)
+{
+     return kadm5_delete_principal(server_handle, principal);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_modify_principal(void *server_handle,
+					     ovsec_kadm_principal_ent_t entry,
+					     long mask)
+{
+     return kadm5_modify_principal(server_handle,
+				   (kadm5_principal_ent_t) entry, mask);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_rename_principal(void *server_handle,
+					     krb5_principal source,
+					     krb5_principal target)
+{
+     return kadm5_rename_principal(server_handle, source, target);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_principal(void *server_handle,
+					  krb5_principal principal,
+					  ovsec_kadm_principal_ent_t *entry)
+{
+     return kadm5_get_principal(server_handle, principal,
+				(kadm5_principal_ent_t *) entry);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_chpass_principal(void *server_handle,
+					     krb5_principal principal,
+					     char *password)
+{
+     return kadm5_chpass_principal(server_handle, principal, password);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_chpass_principal_util(void *server_handle,
+						  krb5_principal princ,
+						  char *new_pw, 
+						  char **ret_pw,
+						  char *msg_ret)
+{
+    /* Oh crap.  Can't change the API without bumping the API version... */
+    memset(msg_ret, '\0', 1024);
+    return kadm5_chpass_principal_util(server_handle, princ, new_pw,
+				       ret_pw, msg_ret, 1024);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_randkey_principal(void *server_handle,
+					      krb5_principal principal,
+					      krb5_keyblock **key)
+{
+     return kadm5_randkey_principal(server_handle, principal, key);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_create_policy(void *server_handle,
+					  ovsec_kadm_policy_ent_t entry,
+					  long mask)
+{
+     return kadm5_create_policy(server_handle,
+				(kadm5_policy_ent_t) entry, mask); 
+}
+
+ovsec_kadm_ret_t ovsec_kadm_delete_policy(void *server_handle,
+					  ovsec_kadm_policy_t name)
+{
+     return kadm5_delete_policy(server_handle, (kadm5_policy_t) name);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_modify_policy(void *server_handle,
+					  ovsec_kadm_policy_ent_t entry,
+					  long mask)
+{
+     return kadm5_modify_policy(server_handle,
+				(kadm5_policy_ent_t) entry, mask); 
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_get_policy(void *server_handle,
+				       ovsec_kadm_policy_t name,
+				       ovsec_kadm_policy_ent_t *entry)
+{
+     return kadm5_get_policy(server_handle, (kadm5_policy_t) name,
+			     (kadm5_policy_ent_t *) entry);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_free_policy_ent(void *server_handle,
+					    ovsec_kadm_policy_ent_t val)
+{
+     return kadm5_free_policy_ent(server_handle, (kadm5_policy_ent_t) val);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_free_name_list(void *server_handle,
+					   char **names, int count) 
+{
+     return kadm5_free_name_list(server_handle, names, count);
+}
+
+ovsec_kadm_ret_t
+ovsec_kadm_free_principal_ent(void *server_handle,
+			      ovsec_kadm_principal_ent_t val)
+{
+     return kadm5_free_principal_ent(server_handle,
+				     (kadm5_principal_ent_t) val);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_privs(void *server_handle, long *privs)
+{
+     return kadm5_get_privs(server_handle, privs);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_principals(void *server_handle,
+					   char *exp,
+					   char ***princs,
+					   int *count)
+{
+     return kadm5_get_principals(server_handle, exp, princs, count);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_policies(void *server_handle,
+					   char *exp,
+					   char ***pols,
+					   int *count)
+{
+     return kadm5_get_policies(server_handle, exp, pols, count);
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/server_internal.h b/krb5-1-6/src/lib/kadm5/server_internal.h
new file mode 100644
index 000000000..4e890e8aa
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/server_internal.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+/*
+ * This header file is used internally by the Admin API server
+ * libraries and Admin server.  IF YOU THINK YOU NEED TO USE THIS FILE
+ * FOR ANYTHING, YOU'RE ALMOST CERTAINLY WRONG.
+ */
+
+#ifndef __KADM5_SERVER_INTERNAL_H__
+#define __KADM5_SERVER_INTERNAL_H__
+
+#include    "autoconf.h"
+#ifdef HAVE_MEMORY_H
+#include    <memory.h>
+#endif
+#include    <stdlib.h>
+#include    <errno.h>
+#include    <kdb.h>
+#include    <kadm5/admin.h>
+#include    "admin_internal.h"
+
+typedef struct _kadm5_server_handle_t {
+	krb5_ui_4	magic_number;
+	krb5_ui_4	struct_version;
+	krb5_ui_4	api_version;
+	krb5_context	context;
+	krb5_principal	current_caller;
+	kadm5_config_params  params;
+	struct _kadm5_server_handle_t *lhandle;
+        char **db_args;
+} kadm5_server_handle_rec, *kadm5_server_handle_t;
+
+#define OSA_ADB_PRINC_VERSION_1  0x12345C01
+
+typedef struct _osa_pw_hist_t {
+  int n_key_data;
+  krb5_key_data *key_data;
+} osa_pw_hist_ent, *osa_pw_hist_t;
+
+typedef struct _osa_princ_ent_t {
+  int                         version;
+  char                        *policy;
+  long                        aux_attributes;
+  unsigned int                old_key_len;
+  unsigned int                old_key_next;
+  krb5_kvno                   admin_history_kvno;
+  osa_pw_hist_ent             *old_keys;
+} osa_princ_ent_rec, *osa_princ_ent_t;
+
+
+kadm5_ret_t    adb_policy_init(kadm5_server_handle_t handle);
+kadm5_ret_t    adb_policy_close(kadm5_server_handle_t handle);
+kadm5_ret_t    passwd_check(kadm5_server_handle_t handle,
+			    char *pass, int use_policy,
+			    kadm5_policy_ent_t policy,
+			    krb5_principal principal);
+kadm5_ret_t    principal_exists(krb5_principal principal);
+krb5_error_code	    kdb_init_master(kadm5_server_handle_t handle,
+				    char *r, int from_keyboard);
+krb5_error_code	    kdb_init_hist(kadm5_server_handle_t handle,
+				  char *r);
+krb5_error_code     kdb_get_entry(kadm5_server_handle_t handle,
+				  krb5_principal principal, krb5_db_entry *kdb,
+				  osa_princ_ent_rec *adb);
+krb5_error_code     kdb_free_entry(kadm5_server_handle_t handle,
+				   krb5_db_entry *kdb, osa_princ_ent_rec *adb);
+krb5_error_code     kdb_put_entry(kadm5_server_handle_t handle,
+				  krb5_db_entry *kdb, osa_princ_ent_rec *adb);
+krb5_error_code     kdb_delete_entry(kadm5_server_handle_t handle,
+				     krb5_principal name);
+krb5_error_code     kdb_iter_entry(kadm5_server_handle_t handle,
+				   char *match_entry,
+				   void (*iter_fct)(void *, krb5_principal), 
+				   void *data);
+
+int		    init_dict(kadm5_config_params *);
+int		    find_word(const char *word);
+void		    destroy_dict(void);
+
+/* XXX this ought to be in libkrb5.a, but isn't */
+kadm5_ret_t krb5_copy_key_data_contents(krb5_context context,
+					krb5_key_data *from, 
+					krb5_key_data *to);
+kadm5_ret_t krb5_free_key_data_contents(krb5_context context, 
+					krb5_key_data *key);
+
+/*
+ * *Warning* 
+ * *Warning*	    This is going to break if we     
+ * *Warning*	    ever go multi-threaded	     
+ * *Warning* 
+ */
+extern	krb5_principal	current_caller;
+
+/*
+ * Why is this (or something similar) not defined *anywhere* in krb5?
+ */
+#define KSUCCESS	0
+#define WORD_NOT_FOUND	1
+
+/*
+ * all the various mask bits or'd together
+ */
+
+#define	ALL_PRINC_MASK \
+ (KADM5_PRINCIPAL | KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION | \
+  KADM5_LAST_PWD_CHANGE | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | \
+  KADM5_MOD_TIME | KADM5_MOD_NAME | KADM5_KVNO | KADM5_MKVNO | \
+  KADM5_AUX_ATTRIBUTES | KADM5_POLICY_CLR | KADM5_POLICY | \
+  KADM5_MAX_RLIFE | KADM5_TL_DATA | KADM5_KEY_DATA)
+
+#define ALL_POLICY_MASK \
+ (KADM5_POLICY | KADM5_PW_MAX_LIFE | KADM5_PW_MIN_LIFE | \
+  KADM5_PW_MIN_LENGTH | KADM5_PW_MIN_CLASSES | KADM5_PW_HISTORY_NUM | \
+  KADM5_REF_COUNT)
+
+#define SERVER_CHECK_HANDLE(handle) \
+{ \
+	kadm5_server_handle_t srvr = \
+	     (kadm5_server_handle_t) handle; \
+ \
+	if (! srvr->current_caller) \
+		return KADM5_BAD_SERVER_HANDLE; \
+	if (! srvr->lhandle) \
+	        return KADM5_BAD_SERVER_HANDLE; \
+}
+
+#define CHECK_HANDLE(handle) \
+     GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION, \
+			  KADM5_NEW_SERVER_API_VERSION) \
+     SERVER_CHECK_HANDLE(handle)
+
+bool_t          xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp);
+
+void
+osa_free_princ_ent(osa_princ_ent_t val);
+
+#endif /* __KADM5_SERVER_INTERNAL_H__ */
diff --git a/krb5-1-6/src/lib/kadm5/srv/Makefile.in b/krb5-1-6/src/lib/kadm5/srv/Makefile.in
new file mode 100644
index 000000000..4defd1630
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/Makefile.in
@@ -0,0 +1,255 @@
+thisconfigdir=../../..
+myfulldir=lib/kadm5/srv
+mydir=lib/kadm5/srv
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5 \
+	-I$(SRCTOP)/lib/gssapi/krb5 -I$(SRCTOP)/lib/gssapi/generic \
+	-I$(BUILDTOP)/lib/gssapi/krb5 -I$(BUILDTOP)/lib/gssapi/generic
+DEFINES = @HESIOD_DEFS@
+DEFS=
+
+##DOSBUILDTOP = ..\..\..
+##DOSLIBNAME = libkadm5srv.lib
+
+LIBBASE=kadm5srv
+LIBMAJOR=5
+LIBMINOR=1
+STOBJLISTS=../OBJS.ST OBJS.ST
+
+SHLIB_EXPDEPS=\
+	$(TOPLIBD)/libgssrpc$(SHLIBEXT) \
+	$(TOPLIBD)/libgssapi_krb5$(SHLIBEXT) \
+	$(TOPLIBD)/libkdb5$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT) \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(COM_ERR_DEPLIB)
+SHLIB_EXPLIBS =	-lgssrpc -lgssapi_krb5 -lkdb5 $(KDB5_DB_LIB) \
+		-lkrb5 -lk5crypto -lcom_err @GEN_LIB@
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+RELDIR=kadm5/srv
+
+SRCS =	$(srcdir)/svr_policy.c \
+	$(srcdir)/svr_principal.c \
+	$(srcdir)/server_acl.c \
+	$(srcdir)/server_kdb.c \
+	$(srcdir)/server_misc.c \
+	$(srcdir)/server_init.c \
+	$(srcdir)/server_dict.c \
+	$(srcdir)/svr_iters.c \
+	$(srcdir)/svr_chpass_util.c \
+	$(srcdir)/adb_xdr.c 
+
+OBJS =	svr_policy.$(OBJEXT) \
+	svr_principal.$(OBJEXT) \
+	server_acl.$(OBJEXT) \
+	server_kdb.$(OBJEXT) \
+	server_misc.$(OBJEXT) \
+	server_init.$(OBJEXT) \
+	server_dict.$(OBJEXT) \
+	svr_iters.$(OBJEXT) \
+	svr_chpass_util.$(OBJEXT) \
+	adb_xdr.$(OBJEXT) 
+
+STLIBOBJS = \
+	svr_policy.o \
+	svr_principal.o \
+	server_acl.o \
+	server_kdb.o \
+	server_misc.o \
+	server_init.o \
+	server_dict.o \
+	svr_iters.o \
+	svr_chpass_util.o \
+	adb_xdr.o
+
+all-unix:: includes
+all-unix:: all-liblinks
+all-windows:: $(OBJS)
+
+generate-files-mac: includes
+
+includes:: server_acl.h
+	if cmp $(srcdir)/server_acl.h \
+	$(BUILDTOP)/include/kadm5/server_acl.h >/dev/null 2>&1; then :; \
+	else \
+		(set -x; $(RM) $(BUILDTOP)/include/kadm5/server_acl.h; \
+		 $(CP) $(srcdir)/server_acl.h \
+			$(BUILDTOP)/include/kadm5/server_acl.h) ; \
+	fi
+
+clean-unix::
+	$(RM) $(BUILDTOP)/include/kadm5/server_acl.h
+
+check-windows::
+
+clean-windows::
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+install:: install-libs
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+svr_policy.so svr_policy.po $(OUTPRE)svr_policy.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h svr_policy.c
+svr_principal.so svr_principal.po $(OUTPRE)svr_principal.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h svr_principal.c
+server_acl.so server_acl.po $(OUTPRE)server_acl.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/syslog.h \
+  server_acl.c server_acl.h
+server_kdb.so server_kdb.po $(OUTPRE)server_kdb.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h server_kdb.c
+server_misc.so server_misc.po $(OUTPRE)server_misc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h server_misc.c
+server_init.so server_init.po $(OUTPRE)server_init.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \
+  $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.h $(BUILDTOP)/lib/gssapi/krb5/gssapi_krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../../gssapi/generic/gssapiP_generic.h \
+  $(srcdir)/../../gssapi/generic/gssapi_generic.h $(srcdir)/../../gssapi/krb5/gssapiP_krb5.h \
+  server_init.c
+server_dict.so server_dict.po $(OUTPRE)server_dict.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/adm_proto.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/syslog.h \
+  server_dict.c
+svr_iters.so svr_iters.po $(OUTPRE)svr_iters.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h svr_iters.c
+svr_chpass_util.so svr_chpass_util.po $(OUTPRE)svr_chpass_util.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
+  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h svr_chpass_util.c
+adb_xdr.so adb_xdr.po $(OUTPRE)adb_xdr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/admin_xdr.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h adb_xdr.c
diff --git a/krb5-1-6/src/lib/kadm5/srv/adb_xdr.c b/krb5-1-6/src/lib/kadm5/srv/adb_xdr.c
new file mode 100644
index 000000000..d5d17062a
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/adb_xdr.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/types.h>
+#include <krb5.h>
+#include <gssrpc/rpc.h>
+#include	"server_internal.h"
+#include "admin_xdr.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+bool_t
+xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp)
+{
+    unsigned int tmp;
+
+    if (!xdr_krb5_int16(xdrs, &objp->key_data_ver))
+	return(FALSE);
+    if (!xdr_krb5_int16(xdrs, &objp->key_data_kvno))
+	return(FALSE);
+    if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0]))
+	return(FALSE);
+    if (!xdr_krb5_int16(xdrs, &objp->key_data_type[1]))
+	return(FALSE);
+    if (!xdr_krb5_ui_2(xdrs, &objp->key_data_length[0]))
+	return(FALSE);
+    if (!xdr_krb5_ui_2(xdrs, &objp->key_data_length[1]))
+	return(FALSE);
+
+    tmp = (unsigned int) objp->key_data_length[0];
+    if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
+		   &tmp, ~0))
+	return FALSE;
+
+    tmp = (unsigned int) objp->key_data_length[1];
+    if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
+		   &tmp, ~0))
+	return FALSE;
+
+    /* don't need to copy tmp out, since key_data_length will be set
+       by the above encoding. */
+
+    return(TRUE);
+}
+
+bool_t
+xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp)
+{
+    if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
+		   (u_int *) &objp->n_key_data, ~0,
+		   sizeof(krb5_key_data),
+		   xdr_krb5_key_data))
+	return (FALSE);
+    return (TRUE);
+}
+
+bool_t
+xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp)
+{
+    switch (xdrs->x_op) {
+    case XDR_ENCODE:
+	 objp->version = OSA_ADB_PRINC_VERSION_1;
+	 /* fall through */
+    case XDR_FREE:
+	 if (!xdr_int(xdrs, &objp->version))
+	      return FALSE;
+	 break;
+    case XDR_DECODE:
+	 if (!xdr_int(xdrs, &objp->version))
+	      return FALSE;
+	 if (objp->version != OSA_ADB_PRINC_VERSION_1)
+	      return FALSE;
+	 break;
+    }
+    
+    if (!xdr_nullstring(xdrs, &objp->policy))
+	return (FALSE);
+    if (!xdr_long(xdrs, &objp->aux_attributes))
+	return (FALSE);
+    if (!xdr_u_int(xdrs, &objp->old_key_next))
+	return (FALSE);
+    if (!xdr_krb5_kvno(xdrs, &objp->admin_history_kvno))
+	return (FALSE);
+    if (!xdr_array(xdrs, (caddr_t *) &objp->old_keys,
+		   (unsigned int *) &objp->old_key_len, ~0,
+		   sizeof(osa_pw_hist_ent),
+		   xdr_osa_pw_hist_ent))
+	return (FALSE);
+    return (TRUE);
+}
+
+void
+osa_free_princ_ent(osa_princ_ent_t val)
+{
+    XDR xdrs;
+                                                                                                                            
+    xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+                                                                                                                            
+    xdr_osa_princ_ent_rec(&xdrs, val);
+    free(val);
+}
+                                                                                                                            
diff --git a/krb5-1-6/src/lib/kadm5/srv/libkadm5srv.exports b/krb5-1-6/src/lib/kadm5/srv/libkadm5srv.exports
new file mode 100644
index 000000000..96a3e4083
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/libkadm5srv.exports
@@ -0,0 +1,162 @@
+_kadm5_check_handle
+_kadm5_chpass_principal_util
+kadm5int_acl_check
+kadm5int_acl_finish
+kadm5int_acl_impose_restrictions
+kadm5int_acl_init
+adb_policy_close
+adb_policy_init
+destroy_dict
+find_word
+hist_db
+hist_key
+hist_kvno
+hist_princ
+init_dict
+kadm5_set_use_password_server
+kadm5_chpass_principal
+kadm5_chpass_principal_3
+kadm5_chpass_principal_util
+kadm5_create_policy
+kadm5_create_policy_internal
+kadm5_create_principal
+kadm5_create_principal_3
+kadm5_decrypt_key
+kadm5_delete_policy
+kadm5_delete_principal
+kadm5_destroy
+kadm5_flush
+kadm5_free_config_params
+kadm5_free_key_data
+kadm5_free_name_list
+kadm5_free_policy_ent
+kadm5_free_principal_ent
+kadm5_get_config_params
+kadm5_get_policies
+kadm5_get_policy
+kadm5_get_principal
+kadm5_get_principals
+kadm5_get_privs
+kadm5_init
+kadm5_init_krb5_context
+kadm5_init_with_creds
+kadm5_init_with_password
+kadm5_init_with_skey
+kadm5_lock
+kadm5_modify_policy
+kadm5_modify_policy_internal
+kadm5_modify_principal
+kadm5_randkey_principal
+kadm5_randkey_principal_3
+kadm5_rename_principal
+kadm5_setkey_principal
+kadm5_setkey_principal_3
+kadm5_setv4key_principal
+kadm5_unlock
+kdb_delete_entry
+kdb_free_entry
+kdb_get_entry
+kdb_init_hist
+kdb_init_master
+kdb_iter_entry
+kdb_put_entry
+krb5_aprof_finish
+krb5_aprof_get_boolean
+krb5_aprof_get_deltat
+krb5_aprof_get_int32
+krb5_aprof_get_string
+krb5_aprof_getvals
+krb5_aprof_init
+krb5_copy_key_data_contents
+krb5_flags_to_string
+krb5_free_key_data_contents
+krb5_free_realm_params
+krb5_input_flag_to_string
+krb5_keysalt_is_present
+krb5_keysalt_iterate
+krb5_klog_close
+krb5_klog_init
+krb5_klog_reopen
+krb5_klog_syslog
+krb5_read_realm_params
+krb5_string_to_flags
+krb5_string_to_keysalts
+master_db
+master_keyblock
+master_princ
+osa_free_princ_ent
+ovsec_kadm_chpass_principal
+ovsec_kadm_chpass_principal_util
+ovsec_kadm_create_policy
+ovsec_kadm_create_principal
+ovsec_kadm_delete_policy
+ovsec_kadm_delete_principal
+ovsec_kadm_destroy
+ovsec_kadm_flush
+ovsec_kadm_free_name_list
+ovsec_kadm_free_policy_ent
+ovsec_kadm_free_principal_ent
+ovsec_kadm_get_policies
+ovsec_kadm_get_policy
+ovsec_kadm_get_principal
+ovsec_kadm_get_principals
+ovsec_kadm_get_privs
+ovsec_kadm_init
+ovsec_kadm_init_with_password
+ovsec_kadm_init_with_skey
+ovsec_kadm_modify_policy
+ovsec_kadm_modify_principal
+ovsec_kadm_randkey_principal
+ovsec_kadm_rename_principal
+passwd_check
+xdr_chpass3_arg
+xdr_chpass_arg
+xdr_chrand3_arg
+xdr_chrand_arg
+xdr_chrand_ret
+xdr_cpol_arg
+xdr_cprinc3_arg
+xdr_cprinc_arg
+xdr_dpol_arg
+xdr_dprinc_arg
+xdr_generic_ret
+xdr_getprivs_ret
+xdr_gpol_arg
+xdr_gpol_ret
+xdr_gpols_arg
+xdr_gpols_ret
+xdr_gprinc_arg
+xdr_gprinc_ret
+xdr_gprincs_arg
+xdr_gprincs_ret
+xdr_kadm5_policy_ent_rec
+xdr_kadm5_principal_ent_rec
+xdr_kadm5_principal_ent_rec_v1
+xdr_kadm5_ret_t
+xdr_krb5_deltat
+xdr_krb5_enctype
+xdr_krb5_flags
+xdr_krb5_int16
+xdr_krb5_key_data
+xdr_krb5_key_data_nocontents
+xdr_krb5_key_salt_tuple
+xdr_krb5_keyblock
+xdr_krb5_kvno
+xdr_krb5_octet
+xdr_krb5_principal
+xdr_krb5_salttype
+xdr_krb5_timestamp
+xdr_krb5_tl_data
+xdr_krb5_ui_2
+xdr_krb5_ui_4
+xdr_mpol_arg
+xdr_mprinc_arg
+xdr_nullstring
+xdr_nulltype
+xdr_osa_princ_ent_rec
+xdr_osa_pw_hist_ent
+xdr_rprinc_arg
+xdr_setkey3_arg
+xdr_setkey_arg
+xdr_setv4key_arg
+xdr_ui_4
diff --git a/krb5-1-6/src/lib/kadm5/srv/server_acl.c b/krb5-1-6/src/lib/kadm5/srv/server_acl.c
new file mode 100644
index 000000000..6d8d6d7f6
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/server_acl.c
@@ -0,0 +1,807 @@
+/*
+ * lib/kadm5/srv/server_acl.c
+ *
+ * Copyright 1995-2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * srv_acl.c - Handle Kerberos ACL related functions.
+ */
+#include <stdio.h>
+#include <syslog.h>
+#include <sys/param.h>
+#include <gssapi/gssapi_generic.h>
+#include "k5-int.h"
+#include <kadm5/server_internal.h>
+#include <kadm5/admin.h>
+#include "adm_proto.h"
+#include "server_acl.h"
+#include <ctype.h>
+
+typedef struct _acl_op_table {
+    char	ao_op;
+    krb5_int32	ao_mask;
+} aop_t;
+
+typedef struct _acl_entry {
+    struct _acl_entry	*ae_next;
+    char		*ae_name;
+    krb5_boolean	ae_name_bad;
+    krb5_principal	ae_principal;
+    krb5_int32		ae_op_allowed;
+    char		*ae_target;
+    krb5_boolean	ae_target_bad;
+    krb5_principal	ae_target_princ;
+    char		*ae_restriction_string;
+			/* eg: "-maxlife 3h -service +proxiable" */
+    krb5_boolean	ae_restriction_bad;
+    restriction_t	*ae_restrictions;
+} aent_t;
+
+static const aop_t acl_op_table[] = {
+    { 'a',	ACL_ADD },
+    { 'd',	ACL_DELETE },
+    { 'm',	ACL_MODIFY },
+    { 'c',	ACL_CHANGEPW },
+    { 'i',	ACL_INQUIRE },
+    { 'l',	ACL_LIST },
+    { 's',	ACL_SETKEY },
+    { 'x',	ACL_ALL_MASK },
+    { '*',	ACL_ALL_MASK },
+    { '\0',	0 }
+};
+
+typedef struct _wildstate {
+    int		nwild;
+    krb5_data	*backref[9];
+} wildstate_t;
+
+static aent_t	*acl_list_head = (aent_t *) NULL;
+static aent_t	*acl_list_tail = (aent_t *) NULL;
+
+static const char *acl_acl_file = (char *) NULL;
+static int acl_inited = 0;
+static int acl_debug_level = 0;
+/*
+ * This is the catchall entry.  If nothing else appropriate is found, or in
+ * the case where the ACL file is not present, this entry controls what can
+ * be done.
+ */
+static const char *acl_catchall_entry = NULL;
+
+static const char *acl_line2long_msg = "%s: line %d too long, truncated";
+static const char *acl_op_bad_msg = "Unrecognized ACL operation '%c' in %s";
+static const char *acl_syn_err_msg = "%s: syntax error at line %d <%10s...>";
+static const char *acl_cantopen_msg = "%s while opening ACL file %s";
+
+
+/*
+ * kadm5int_acl_get_line() - Get a line from the ACL file.
+ *			Lines ending with \ are continued on the next line
+ */
+static char *
+kadm5int_acl_get_line(fp, lnp)
+    FILE	*fp;
+    int		*lnp;		/* caller should set to 1 before first call */
+{
+    int		i, domore;
+    static int	line_incr = 0;
+    static char acl_buf[BUFSIZ];
+
+    *lnp += line_incr;
+    line_incr = 0;
+    for (domore = 1; domore && !feof(fp); ) {
+	/* Copy in the line, with continuations */
+	for (i=0; ((i < sizeof acl_buf) && !feof(fp)); i++ ) {
+	    acl_buf[i] = fgetc(fp);
+	    if (acl_buf[i] == (char)EOF) {
+		if (i > 0 && acl_buf[i-1] == '\\')
+		    i--;
+		break;		/* it gets nulled-out below */
+	    }
+	    else if (acl_buf[i] == '\n') {
+		if (i == 0 || acl_buf[i-1] != '\\')
+		    break;	/* empty line or normal end of line */
+		else {
+		    i -= 2;	/* back up over "\\\n" and continue */
+		    line_incr++;
+		}
+	    }
+	}
+	/* Check if we exceeded our buffer size */
+	if (i == sizeof acl_buf && (i--, !feof(fp))) {
+	    int	c1 = acl_buf[i], c2;
+
+	    krb5_klog_syslog(LOG_ERR, acl_line2long_msg, acl_acl_file, *lnp);
+	    while ((c2 = fgetc(fp)) != EOF) {
+		if (c2 == '\n') {
+		    if (c1 != '\\')
+			break;
+		    line_incr++;
+		}
+		c1 = c2;
+	    }
+	}
+	acl_buf[i] = '\0';
+	if (acl_buf[0] == (char) EOF)	/* ptooey */
+	    acl_buf[0] = '\0';
+	else
+	    line_incr++;
+	if ((acl_buf[0] != '#') && (acl_buf[0] != '\0'))
+	    domore = 0;
+    }
+    if (domore || (strlen(acl_buf) == 0))
+	return((char *) NULL);
+    else
+	return(acl_buf);
+}
+
+/*
+ * kadm5int_acl_parse_line() - Parse the contents of an ACL line.
+ */
+static aent_t *
+kadm5int_acl_parse_line(lp)
+    const char *lp;
+{
+    static char acle_principal[BUFSIZ];
+    static char acle_ops[BUFSIZ];
+    static char acle_object[BUFSIZ];
+    static char acle_restrictions[BUFSIZ];
+    aent_t	*acle;
+    char	*op;
+    int		t, found, opok, nmatch;
+
+    DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("* kadm5int_acl_parse_line(line=%20s)\n", lp));
+    /*
+     * Format is still simple:
+     *  entry ::= [<whitespace>] <principal> <whitespace> <opstring>
+     *		  [<whitespace> <target> [<whitespace> <restrictions>
+     *					  [<whitespace>]]]
+     */
+    acle = (aent_t *) NULL;
+    acle_object[0] = '\0';
+    nmatch = sscanf(lp, "%s %s %s %[^\n]", acle_principal, acle_ops,
+		    acle_object, acle_restrictions);
+    if (nmatch >= 2) {
+	acle = (aent_t *) malloc(sizeof(aent_t));
+	if (acle) {
+	    acle->ae_next = (aent_t *) NULL;
+	    acle->ae_op_allowed = (krb5_int32) 0;
+	    acle->ae_target =
+		(nmatch >= 3) ? strdup(acle_object) : (char *) NULL;
+	    acle->ae_target_bad = 0;
+	    acle->ae_target_princ = (krb5_principal) NULL;
+	    opok = 1;
+	    for (op=acle_ops; *op; op++) {
+		char rop;
+
+		rop = (isupper((unsigned char) *op)) ? tolower((unsigned char) *op) : *op;
+		found = 0;
+		for (t=0; acl_op_table[t].ao_op; t++) {
+		    if (rop == acl_op_table[t].ao_op) {
+			found = 1;
+			if (rop == *op)
+			    acle->ae_op_allowed |= acl_op_table[t].ao_mask;
+			else
+			    acle->ae_op_allowed &= ~acl_op_table[t].ao_mask;
+		    }
+		}
+		if (!found) {
+		    krb5_klog_syslog(LOG_ERR, acl_op_bad_msg, *op, lp);
+		    opok = 0;
+		}
+	    }
+	    if (opok) {
+		acle->ae_name = (char *) malloc(strlen(acle_principal)+1);
+		if (acle->ae_name) {
+		    strcpy(acle->ae_name, acle_principal);
+		    acle->ae_principal = (krb5_principal) NULL;
+		    acle->ae_name_bad = 0;
+		    DPRINT(DEBUG_ACL, acl_debug_level,
+			   ("A ACL entry %s -> opmask %x\n",
+			    acle->ae_name, acle->ae_op_allowed));
+		}
+		else {
+		    if (acle->ae_target)
+			free(acle->ae_target);
+		    free(acle);
+		    acle = (aent_t *) NULL;
+		}
+	    }
+	    else {
+		if (acle->ae_target)
+		    free(acle->ae_target);
+		free(acle);
+		acle = (aent_t *) NULL;
+	    }
+	    if ( nmatch >= 4 ) {
+		char	*trailing;
+
+		trailing = &acle_restrictions[strlen(acle_restrictions)-1];
+		while ( isspace((int) *trailing) )
+		    trailing--;
+		trailing[1] = '\0';
+		acle->ae_restriction_string = strdup(acle_restrictions);
+	    }
+	    else {
+		acle->ae_restriction_string = (char *) NULL;
+	    }
+	    acle->ae_restriction_bad = 0;
+	    acle->ae_restrictions = (restriction_t *) NULL;
+	}
+    }
+    DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("X kadm5int_acl_parse_line() = %x\n", (long) acle));
+    return(acle);
+}
+
+/*
+ * kadm5int_acl_parse_restrictions() - Parse optional restrictions field
+ *
+ * Allowed restrictions are:
+ *	[+-]flagname		(recognized by krb5_string_to_flags)
+ *				flag is forced to indicated value
+ *	-clearpolicy		policy is forced clear
+ *	-policy pol		policy is forced to be "pol"
+ *	-{expire,pwexpire,maxlife,maxrenewlife} deltat
+ *				associated value will be forced to
+ *				MIN(deltat, requested value)
+ *
+ * Returns: 0 on success, or system errors
+ */
+static krb5_error_code
+kadm5int_acl_parse_restrictions(s, rpp)
+    char		*s;
+    restriction_t	**rpp;
+{
+    char		*sp, *tp, *ap;
+    static const char	*delims = "\t\n\f\v\r ,";
+    krb5_deltat		dt;
+    krb5_flags		flag;
+    krb5_error_code	code;
+
+   DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("* kadm5int_acl_parse_restrictions(s=%20s, rpp=0x%08x)\n", s, (long)rpp));
+
+    *rpp = (restriction_t *) NULL;
+    code = 0;
+    if (s) {
+	if (!(sp = strdup(s))	/* Don't munge the original */
+	    || !(*rpp = (restriction_t *) malloc(sizeof(restriction_t)))) {
+	    code = ENOMEM;
+	} else {
+	    memset(*rpp, 0, sizeof(**rpp));
+	    for (tp=strtok(sp, delims); tp; tp=strtok((char *)NULL, delims)) {
+		flag = 0;
+		if (!krb5_string_to_flags(tp, "+", "-", &flag)) {
+		    /* OK, but was it in the positive or negative sense? */
+		    if (flag) {
+			(*rpp)->require_attrs |= flag;
+		    } else {
+			flag = ~0;
+			(void) krb5_string_to_flags(tp, "+", "-", &flag);
+			(*rpp)->forbid_attrs |= ~flag;
+		    }
+		    (*rpp)->mask |= KADM5_ATTRIBUTES;
+		} else if (!strcmp(tp, "-clearpolicy")) {
+		    (*rpp)->mask |= KADM5_POLICY_CLR;
+		} else {
+		    /* everything else needs an argument ... */
+		    if (!(ap = strtok((char *)NULL, delims))) {
+			code = EINVAL;
+			break;
+		    }
+		    if (!strcmp(tp, "-policy")) {
+			if (!((*rpp)->policy = strdup(ap))) {
+			    code = ENOMEM;
+			    break;
+			}
+			(*rpp)->mask |= KADM5_POLICY;
+		    } else {
+			/* all other arguments must be a deltat ... */
+			if (krb5_string_to_deltat(ap, &dt)) {
+			    code = EINVAL;
+			    break;
+			}
+			if (!strcmp(tp, "-expire")) {
+			    (*rpp)->princ_lifetime = dt;
+			    (*rpp)->mask |= KADM5_PRINC_EXPIRE_TIME;
+			} else if (!strcmp(tp, "-pwexpire")) {
+			    (*rpp)->pw_lifetime = dt;
+			    (*rpp)->mask |= KADM5_PW_EXPIRATION;
+			} else if (!strcmp(tp, "-maxlife")) {
+			    (*rpp)->max_life = dt;
+			    (*rpp)->mask |= KADM5_MAX_LIFE;
+			} else if (!strcmp(tp, "-maxrenewlife")) {
+			    (*rpp)->max_renewable_life = dt;
+			    (*rpp)->mask |= KADM5_MAX_RLIFE;
+			} else {
+			    code = EINVAL;
+			    break;
+			}
+		    }
+		}
+	    }
+	}
+    }
+    if (sp)
+	free(sp);
+    if (*rpp && code) {
+	if ((*rpp)->policy)
+	    free((*rpp)->policy);
+	free(*rpp);
+	*rpp = (restriction_t *) NULL;
+    }
+    DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("X kadm5int_acl_parse_restrictions() = %d, mask=0x%08x\n",
+	    code, (*rpp) ? (*rpp)->mask : 0));
+    return code;
+}
+
+/*
+ * kadm5int_acl_impose_restrictions()	- impose restrictions, modifying *recp, *maskp
+ *
+ * Returns: 0 on success;
+ *	    malloc or timeofday errors
+ */
+krb5_error_code
+kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
+     krb5_context		kcontext;
+     kadm5_principal_ent_rec	*recp;
+     long			*maskp;
+     restriction_t		*rp;
+{
+    krb5_error_code	code;
+    krb5_int32		now;
+
+    DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("* kadm5int_acl_impose_restrictions(..., *maskp=0x%08x, rp=0x%08x)\n",
+	    *maskp, (long)rp));
+    if (!rp)
+	return 0;
+    if (rp->mask & (KADM5_PRINC_EXPIRE_TIME|KADM5_PW_EXPIRATION))
+	if ((code = krb5_timeofday(kcontext, &now)))
+	    return code;
+
+    if (rp->mask & KADM5_ATTRIBUTES) {
+	recp->attributes |= rp->require_attrs;
+	recp->attributes &= ~(rp->forbid_attrs);
+	*maskp |= KADM5_ATTRIBUTES;
+    }
+    if (rp->mask & KADM5_POLICY_CLR) {
+	*maskp &= ~KADM5_POLICY;
+	*maskp |= KADM5_POLICY_CLR;
+    } else if (rp->mask & KADM5_POLICY) {
+	if (recp->policy && strcmp(recp->policy, rp->policy)) {
+		free(recp->policy);
+		recp->policy = (char *) NULL;
+	}
+	if (!recp->policy) {
+	    recp->policy = strdup(rp->policy);  /* XDR will free it */
+	    if (!recp->policy)
+		return ENOMEM;
+	}
+	*maskp |= KADM5_POLICY;
+    }
+    if (rp->mask & KADM5_PRINC_EXPIRE_TIME) {
+	if (!(*maskp & KADM5_PRINC_EXPIRE_TIME)
+	    || (recp->princ_expire_time > (now + rp->princ_lifetime)))
+	    recp->princ_expire_time = now + rp->princ_lifetime;
+	*maskp |= KADM5_PRINC_EXPIRE_TIME;
+    }
+    if (rp->mask & KADM5_PW_EXPIRATION) {
+	if (!(*maskp & KADM5_PW_EXPIRATION)
+	    || (recp->pw_expiration > (now + rp->pw_lifetime)))
+	    recp->pw_expiration = now + rp->pw_lifetime;
+	*maskp |= KADM5_PW_EXPIRATION;
+    }
+    if (rp->mask & KADM5_MAX_LIFE) {
+	if (!(*maskp & KADM5_MAX_LIFE)
+	    || (recp->max_life > rp->max_life))
+	    recp->max_life = rp->max_life;
+	*maskp |= KADM5_MAX_LIFE;
+    }
+    if (rp->mask & KADM5_MAX_RLIFE) {
+	if (!(*maskp & KADM5_MAX_RLIFE)
+	    || (recp->max_renewable_life > rp->max_renewable_life))
+	    recp->max_renewable_life = rp->max_renewable_life;
+	*maskp |= KADM5_MAX_RLIFE;
+    }
+    DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("X kadm5int_acl_impose_restrictions() = 0, *maskp=0x%08x\n", *maskp));
+    return 0;
+}
+
+/*
+ * kadm5int_acl_free_entries() - Free all ACL entries.
+ */
+static void
+kadm5int_acl_free_entries()
+{
+    aent_t	*ap;
+    aent_t	*np;
+
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_free_entries()\n"));
+    for (ap=acl_list_head; ap; ap = np) {
+	if (ap->ae_name)
+	    free(ap->ae_name);
+	if (ap->ae_principal)
+	    krb5_free_principal((krb5_context) NULL, ap->ae_principal);
+	if (ap->ae_target)
+	    free(ap->ae_target);
+	if (ap->ae_target_princ)
+	    krb5_free_principal((krb5_context) NULL, ap->ae_target_princ);
+	if (ap->ae_restriction_string)
+	    free(ap->ae_restriction_string);
+	if (ap->ae_restrictions) {
+	    if (ap->ae_restrictions->policy)
+		free(ap->ae_restrictions->policy);
+	    free(ap->ae_restrictions);
+	}
+	np = ap->ae_next;
+	free(ap);
+    }
+    acl_list_head = acl_list_tail = (aent_t *) NULL;
+    acl_inited = 0;
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_free_entries()\n"));
+}
+
+/*
+ * kadm5int_acl_load_acl_file()	- Open and parse the ACL file.
+ */
+static int
+kadm5int_acl_load_acl_file()
+{
+    FILE 	*afp;
+    char 	*alinep;
+    aent_t	**aentpp;
+    int		alineno;
+    int		retval = 1;
+
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_load_acl_file()\n"));
+    /* Open the ACL file for read */
+    afp = fopen(acl_acl_file, "r");
+    if (afp) {
+	alineno = 1;
+	aentpp = &acl_list_head;
+
+	/* Get a non-comment line */
+	while ((alinep = kadm5int_acl_get_line(afp, &alineno))) {
+	    /* Parse it */
+	    *aentpp = kadm5int_acl_parse_line(alinep);
+	    /* If syntax error, then fall out */
+	    if (!*aentpp) {
+		krb5_klog_syslog(LOG_ERR, acl_syn_err_msg,
+			acl_acl_file, alineno, alinep);
+		retval = 0;
+		break;
+	    }
+	    acl_list_tail = *aentpp;
+	    aentpp = &(*aentpp)->ae_next;
+	}
+
+	fclose(afp);
+
+	if (acl_catchall_entry) {
+	     *aentpp = kadm5int_acl_parse_line(acl_catchall_entry);
+	     if (*aentpp) {
+		  acl_list_tail = *aentpp;
+	     }
+	     else {
+		  retval = 0;
+		  DPRINT(DEBUG_OPERATION, acl_debug_level,
+			 ("> catchall acl entry (%s) load failed\n",
+			  acl_catchall_entry));
+	     }
+	}
+    }
+    else {
+	krb5_klog_syslog(LOG_ERR, acl_cantopen_msg,
+			 error_message(errno), acl_acl_file);
+	if (acl_catchall_entry &&
+	    (acl_list_head = kadm5int_acl_parse_line(acl_catchall_entry))) {
+	    acl_list_tail = acl_list_head;
+	}
+	else {
+	    retval = 0;
+	    DPRINT(DEBUG_OPERATION, acl_debug_level,
+		   ("> catchall acl entry (%s) load failed\n",
+		    acl_catchall_entry));
+	}
+    }
+
+    if (!retval) {
+	kadm5int_acl_free_entries();
+    }
+    DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("X kadm5int_acl_load_acl_file() = %d\n", retval));
+    return(retval);
+}
+
+/*
+ * kadm5int_acl_match_data()	- See if two data entries match.
+ *
+ * Wildcarding is only supported for a whole component.
+ */
+static krb5_boolean
+kadm5int_acl_match_data(e1, e2, targetflag, ws)
+    krb5_data	*e1, *e2;
+    int		targetflag;
+    wildstate_t	*ws;
+{
+    krb5_boolean	retval;
+
+    DPRINT(DEBUG_CALLS, acl_debug_level, 
+	   ("* acl_match_entry(%s, %s)\n", e1->data, e2->data));
+    retval = 0;
+    if (!strncmp(e1->data, "*", e1->length)) {
+	retval = 1;
+	if (ws && !targetflag) {
+	    if (ws->nwild >= 9) {
+		DPRINT(DEBUG_ACL, acl_debug_level,
+		    ("Too many wildcards in ACL entry %s\n", entry->ae_name));
+	    }
+	    else
+		ws->backref[ws->nwild++] = e2;
+	}
+    }
+    else if (ws && targetflag && (e1->length == 2) && (e1->data[0] == '*') &&
+	     (e1->data[1] >= '1') && (e1->data[1] <= '9')) {
+	int	n = e1->data[1] - '1';
+	if (n >= ws->nwild) {
+	    DPRINT(DEBUG_ACL, acl_debug_level,
+		   ("Too many backrefs in ACL entry %s\n", entry->ae_name));
+	}
+	else if ((ws->backref[n]->length == e2->length) &&
+		 (!strncmp(ws->backref[n]->data, e2->data, e2->length)))
+	    retval = 1;
+	
+    }
+    else {
+	if ((e1->length == e2->length) &&
+	    (!strncmp(e1->data, e2->data, e1->length)))
+	    retval = 1;
+    }
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_match_entry()=%d\n",retval));
+    return(retval);
+}
+
+/*
+ * kadm5int_acl_find_entry()	- Find a matching entry.
+ */
+static aent_t *
+kadm5int_acl_find_entry(kcontext, principal, dest_princ)
+    krb5_context	kcontext;
+    krb5_principal	principal;
+    krb5_principal	dest_princ;
+{
+    aent_t		*entry;
+    krb5_error_code	kret;
+    int			i;
+    int			matchgood;
+    wildstate_t		state;
+
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_find_entry()\n"));
+    memset((char *)&state, 0, sizeof state);
+    for (entry=acl_list_head; entry; entry = entry->ae_next) {
+	if (entry->ae_name_bad)
+	    continue;
+	if (!strcmp(entry->ae_name, "*")) {
+	    DPRINT(DEBUG_ACL, acl_debug_level, ("A wildcard ACL match\n"));
+	    matchgood = 1;
+	}
+	else {
+	    if (!entry->ae_principal && !entry->ae_name_bad) {
+		kret = krb5_parse_name(kcontext,
+				       entry->ae_name,
+				       &entry->ae_principal);
+		if (kret)
+		    entry->ae_name_bad = 1;
+	    }
+	    if (entry->ae_name_bad) {
+		DPRINT(DEBUG_ACL, acl_debug_level,
+		       ("Bad ACL entry %s\n", entry->ae_name));
+		continue;
+	    }
+	    matchgood = 0;
+	    if (kadm5int_acl_match_data(&entry->ae_principal->realm,
+			       &principal->realm, 0, (wildstate_t *)0) &&
+		(entry->ae_principal->length == principal->length)) {
+		matchgood = 1;
+		for (i=0; i<principal->length; i++) {
+		    if (!kadm5int_acl_match_data(&entry->ae_principal->data[i],
+					&principal->data[i], 0, &state)) {
+			matchgood = 0;
+			break;
+		    }
+		}
+	    }
+	}
+	if (!matchgood)
+	    continue;
+
+	/* We've matched the principal.  If we have a target, then try it */
+	if (entry->ae_target && strcmp(entry->ae_target, "*")) {
+	    if (!entry->ae_target_princ && !entry->ae_target_bad) {
+		kret = krb5_parse_name(kcontext, entry->ae_target,
+				       &entry->ae_target_princ);
+		if (kret)
+		    entry->ae_target_bad = 1;
+	    }
+	    if (entry->ae_target_bad) {
+	        DPRINT(DEBUG_ACL, acl_debug_level,
+		       ("Bad target in ACL entry for %s\n", entry->ae_name));
+	        entry->ae_name_bad = 1;
+	        continue;
+	    }
+	    if (!dest_princ)
+	        matchgood = 0;
+	    else if (entry->ae_target_princ && dest_princ) {
+	        if (kadm5int_acl_match_data(&entry->ae_target_princ->realm,
+			           &dest_princ->realm, 1, (wildstate_t *)0) &&
+		    (entry->ae_target_princ->length == dest_princ->length)) {
+		    for (i=0; i<dest_princ->length; i++) {
+		        if (!kadm5int_acl_match_data(&entry->ae_target_princ->data[i],
+			  		    &dest_princ->data[i], 1, &state)) {
+			    matchgood = 0;
+			    break;
+		        }
+		    }
+	        }
+	        else
+		    matchgood = 0;
+	    }
+        }
+	if (!matchgood)
+	    continue;
+
+	if (entry->ae_restriction_string
+	    && !entry->ae_restriction_bad
+	    && !entry->ae_restrictions
+	    && kadm5int_acl_parse_restrictions(entry->ae_restriction_string,
+				      &entry->ae_restrictions)) {
+	    DPRINT(DEBUG_ACL, acl_debug_level,
+		   ("Bad restrictions in ACL entry for %s\n", entry->ae_name));
+	    entry->ae_restriction_bad = 1;
+	}
+	if (entry->ae_restriction_bad) {
+	    entry->ae_name_bad = 1;
+	    continue;
+	}
+	break;
+    }
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_find_entry()=%x\n",entry));
+    return(entry);
+}
+
+/*
+ * kadm5int_acl_init()	- Initialize ACL context.
+ */
+krb5_error_code
+kadm5int_acl_init(kcontext, debug_level, acl_file)
+    krb5_context	kcontext;
+    int			debug_level;
+    char		*acl_file;
+{
+    krb5_error_code	kret;
+
+    kret = 0;
+    acl_debug_level = debug_level;
+    DPRINT(DEBUG_CALLS, acl_debug_level,
+	   ("* kadm5int_acl_init(afile=%s)\n",
+	    ((acl_file) ? acl_file : "(null)")));
+    acl_acl_file = (acl_file) ? acl_file : (char *) KRB5_DEFAULT_ADMIN_ACL;
+    acl_inited = kadm5int_acl_load_acl_file();
+
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_init() = %d\n", kret));
+    return(kret);
+}
+
+/*
+ * kadm5int_acl_finish	- Terminate ACL context.
+ */
+void
+kadm5int_acl_finish(kcontext, debug_level)
+    krb5_context	kcontext;
+    int			debug_level;
+{
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_finish()\n"));
+    kadm5int_acl_free_entries();
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_finish()\n"));
+}
+
+/*
+ * kadm5int_acl_check()	- Is this operation permitted for this principal?
+ *			this code used not to be based on gssapi.  In order
+ *			to minimize porting hassles, I've put all the
+ *			gssapi hair in this function.  This might not be
+ *			the best medium-term solution.  (The best long-term
+ *			solution is, of course, a real authorization service.)
+ */
+krb5_boolean
+kadm5int_acl_check(kcontext, caller, opmask, principal, restrictions)
+    krb5_context	kcontext;
+    gss_name_t		caller;
+    krb5_int32		opmask;
+    krb5_principal	principal;
+    restriction_t	**restrictions;
+{
+    krb5_boolean	retval;
+    aent_t		*aentry;
+    gss_buffer_desc	caller_buf;
+    gss_OID		caller_oid;
+    OM_uint32		emaj, emin;
+    krb5_error_code	code;
+    krb5_principal	caller_princ;
+
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_op_permitted()\n"));
+
+    if (GSS_ERROR(emaj = gss_display_name(&emin, caller, &caller_buf,
+					  &caller_oid)))
+       return(0);
+
+    code = krb5_parse_name(kcontext, (char *) caller_buf.value,
+			   &caller_princ);
+
+    gss_release_buffer(&emin, &caller_buf);
+
+    if (code)
+       return(code);
+
+    retval = 0;
+
+    aentry = kadm5int_acl_find_entry(kcontext, caller_princ, principal);
+    if (aentry) {
+	if ((aentry->ae_op_allowed & opmask) == opmask) {
+	    retval = 1;
+	    if (restrictions) {
+		*restrictions =
+		    (aentry->ae_restrictions && aentry->ae_restrictions->mask)
+		    ? aentry->ae_restrictions
+		    : (restriction_t *) NULL;
+	    }
+	}
+    }
+
+    krb5_free_principal(kcontext, caller_princ);
+
+    DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_op_permitted()=%d\n",
+					  retval));
+    return(retval);
+}
+
+kadm5_ret_t
+kadm5_get_privs(void *server_handle, long *privs)
+{
+     CHECK_HANDLE(server_handle);
+
+     /* this is impossible to do with the current interface.  For now,
+	return all privs, which will confuse some clients, but not
+	deny any access to users of "smart" clients which try to cache */
+
+     *privs = ~0;
+
+     return KADM5_OK;
+}
diff --git a/krb5-1-6/src/lib/kadm5/srv/server_acl.h b/krb5-1-6/src/lib/kadm5/srv/server_acl.h
new file mode 100644
index 000000000..3e24a6357
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/server_acl.h
@@ -0,0 +1,103 @@
+/*
+ * lib/kadm5/srv/server_acl.h
+ *
+ * Copyright 1995-2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#ifndef	SERVER_ACL_H__
+#define	SERVER_ACL_H__
+
+/*
+ * Debug definitions.
+ */
+#define	DEBUG_SPROC	1
+#define	DEBUG_OPERATION	2
+#define	DEBUG_HOST	4
+#define	DEBUG_REALM	8
+#define	DEBUG_REQUESTS	16
+#define	DEBUG_ACL	32
+#define	DEBUG_PROTO	64
+#define	DEBUG_CALLS	128
+#define	DEBUG_NOSLAVES	256
+#ifdef	DEBUG
+#define	DPRINT(l1, cl, al)	if ((cl & l1) != 0) xprintf al
+#else	/* DEBUG */
+#define	DPRINT(l1, cl, al)
+#endif	/* DEBUG */
+#define	DLOG(l1, cl, msg)	if ((cl & l1) != 0)	\
+					com_err(programname, 0, msg)
+
+/*
+ * Access control bits.
+ */
+#define	ACL_ADD			1
+#define	ACL_DELETE		2
+#define	ACL_MODIFY		4
+#define	ACL_CHANGEPW		8
+/* #define ACL_CHANGE_OWN_PW	16 */
+#define	ACL_INQUIRE		32
+/* #define ACL_EXTRACT		64 */
+#define	ACL_LIST		128
+#define ACL_SETKEY		256
+#define	ACL_RENAME		(ACL_ADD+ACL_DELETE)
+
+#define	ACL_ALL_MASK		(ACL_ADD	| \
+				 ACL_DELETE	| \
+				 ACL_MODIFY	| \
+				 ACL_CHANGEPW	| \
+				 ACL_INQUIRE	| \
+				 ACL_LIST	| \
+				 ACL_SETKEY)
+
+typedef struct _restriction {
+    long		mask;
+    krb5_flags		require_attrs;
+    krb5_flags		forbid_attrs;
+    krb5_deltat		princ_lifetime;
+    krb5_deltat		pw_lifetime;
+    krb5_deltat		max_life;
+    krb5_deltat		max_renewable_life;
+    long		aux_attributes;
+    char		*policy;
+} restriction_t;
+
+krb5_error_code kadm5int_acl_init
+	(krb5_context,
+		   int,
+		   char *);
+void kadm5int_acl_finish
+	(krb5_context,
+		   int);
+krb5_boolean kadm5int_acl_check
+	(krb5_context,
+		   gss_name_t,
+		   krb5_int32,
+		   krb5_principal,
+		   restriction_t **);
+krb5_error_code kadm5int_acl_impose_restrictions
+	(krb5_context,
+		   kadm5_principal_ent_rec *,
+		   long *,
+		   restriction_t *);
+#endif	/* SERVER_ACL_H__ */
diff --git a/krb5-1-6/src/lib/kadm5/srv/server_dict.c b/krb5-1-6/src/lib/kadm5/srv/server_dict.c
new file mode 100644
index 000000000..53df800b9
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/server_dict.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include    <sys/types.h>
+#include    <sys/file.h>
+#include    <fcntl.h>
+#include    <sys/stat.h>
+#include    <unistd.h>
+#include <errno.h>
+#include    <kadm5/admin.h>
+#include    <stdlib.h>
+#include    <stdio.h>
+#include    <string.h>
+#ifdef HAVE_MEMORY_H
+#include    <memory.h>
+#endif
+#include    "adm_proto.h"
+#include    <syslog.h>
+#include    "server_internal.h"
+
+static char	    **word_list = NULL;	    /* list of word pointers */
+static char	    *word_block = NULL;	    /* actual word data */
+static unsigned int word_count = 0;	    /* number of words */
+
+
+/*
+ * Function: word_compare
+ * 
+ * Purpose: compare two words in the dictionary.
+ *
+ * Arguments:
+ *	w1		(input)	pointer to first word
+ *	w2		(input) pointer to second word
+ *	<return value>	result of strcmp
+ *
+ * Requires:
+ *	w1 and w2 to point to valid memory
+ * 
+ */
+
+static int
+word_compare(const void *s1, const void *s2)
+{
+    return (strcasecmp(*(const char **)s1, *(const char **)s2));
+}
+
+/*
+ * Function: init-dict
+ * 
+ * Purpose: Initialize in memory word dictionary
+ *
+ * Arguments:
+ *	    none
+ *	    <return value> KADM5_OK on success errno on failure;
+ * 			   (but success on ENOENT)
+ *
+ * Requires:
+ *	If WORDFILE exists, it must contain a list of words,
+ *	one word per-line.
+ * 
+ * Effects:
+ *	If WORDFILE exists, it is read into memory sorted for future
+ * use.  If it does not exist, it syslogs an error message and returns
+ * success.
+ *
+ * Modifies:
+ *	word_list to point to a chunck of allocated memory containing
+ *	pointers to words
+ *	word_block to contain the dictionary.
+ * 
+ */
+
+int init_dict(kadm5_config_params *params)
+{
+    int		    fd,
+		    len,
+		    i;
+    char	    *p,
+		    *t;
+    struct  stat    sb;
+    
+    if(word_list != NULL && word_block != NULL)
+	return KADM5_OK;
+    if (! (params->mask & KADM5_CONFIG_DICT_FILE)) {
+	 krb5_klog_syslog(LOG_INFO, "No dictionary file specified, continuing "
+		"without one.");
+	 return KADM5_OK;
+    }
+    if ((fd = open(params->dict_file, O_RDONLY)) == -1) {
+	 if (errno == ENOENT) {
+	      krb5_klog_syslog(LOG_ERR, 
+			       "WARNING!  Cannot find dictionary file %s, "
+			       "continuing without one.", params->dict_file);
+	      return KADM5_OK;
+	 } else
+	      return errno;
+    }
+    if (fstat(fd, &sb) == -1) 
+	return errno;
+    if ((word_block = (char *) malloc(sb.st_size + 1)) == NULL)
+	return errno;
+    if (read(fd, word_block, sb.st_size) != sb.st_size)
+	return errno;
+    (void) close(fd);
+    word_block[sb.st_size] = '\0';
+
+    p = word_block;
+    len = sb.st_size;
+    while(len > 0 && (t = memchr(p, '\n', len)) != NULL) {
+	*t = '\0';
+	len -= t - p + 1;	
+	p = t + 1;
+	word_count++;
+    }
+    if ((word_list = (char **) malloc(word_count * sizeof(char *))) == NULL)
+	return errno;
+    p = word_block;
+    for (i = 0; i < word_count; i++) {
+	word_list[i] = p;
+	p += strlen(p) + 1;
+    }
+    qsort(word_list, word_count, sizeof(char *), word_compare);
+    return KADM5_OK;
+}
+
+/*
+ * Function: find_word
+ * 
+ * Purpose: See if the specified word exists in the in-core dictionary
+ *
+ * Arguments:
+ *	word		(input) word to search for.
+ * 	<return value>	WORD_NOT_FOUND if not in dictionary,
+ *			KADM5_OK if if found word
+ *			errno if init needs to be called and returns an
+ *			error
+ *
+ * Requires:
+ *	word to be a null terminated string.
+ *	That word_list and word_block besetup
+ * 
+ * Effects:
+ *	finds word in dictionary.
+ * Modifies:
+ *	nothing.
+ * 
+ */
+
+int
+find_word(const char *word)
+{
+    char    **value;
+
+    if(word_list == NULL || word_block == NULL) 
+	    return WORD_NOT_FOUND;
+    if ((value = (char **) bsearch(&word, word_list, word_count, sizeof(char *),
+				   word_compare)) == NULL)
+	return WORD_NOT_FOUND;
+    else
+	return KADM5_OK;
+}
+
+/*
+ * Function: destroy_dict
+ * 
+ * Purpose: destroy in-core copy of dictionary.
+ *
+ * Arguments:
+ *	    none
+ *	    <return value>  none
+ * Requires:
+ *	    nothing
+ * Effects:
+ *	frees up memory occupied by word_list and word_block
+ *	sets count back to 0, and resets the pointers to NULL
+ *
+ * Modifies:
+ *	word_list, word_block, and word_count.
+ * 
+ */
+
+void
+destroy_dict(void)
+{
+    if(word_list) {
+	free(word_list);
+	word_list = NULL;
+    }
+    if(word_block) {
+	free(word_block);
+	word_block = NULL;
+    }
+    if(word_count)
+	word_count = 0;
+    return;
+}
diff --git a/krb5-1-6/src/lib/kadm5/srv/server_handle.c b/krb5-1-6/src/lib/kadm5/srv/server_handle.c
new file mode 100644
index 000000000..53abe94dd
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/server_handle.c
@@ -0,0 +1,9 @@
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include "server_internal.h"
+
+int _kadm5_check_handle(void *handle)
+{
+     CHECK_HANDLE(handle);
+     return 0;
+}
diff --git a/krb5-1-6/src/lib/kadm5/srv/server_init.c b/krb5-1-6/src/lib/kadm5/srv/server_init.c
new file mode 100644
index 000000000..4c0cb939d
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/server_init.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <com_err.h>
+#include "k5-int.h"		/* needed for gssapiP_krb5.h */
+#include <kadm5/admin.h>
+#include <krb5.h>
+#include "server_internal.h"
+#include "osconf.h"
+
+/*
+ * Function check_handle
+ *
+ * Purpose: Check a server handle and return a com_err code if it is
+ * invalid or 0 if it is valid.
+ *
+ * Arguments:
+ *
+ * 	handle		The server handle.
+ */
+
+static int check_handle(void *handle)
+{
+     CHECK_HANDLE(handle);
+     return 0;
+}
+
+static int dup_db_args(kadm5_server_handle_t handle, char **db_args)
+{
+    int count  = 0;
+    int ret = 0;
+
+    for (count=0; db_args && db_args[count]; count++);
+    if (count == 0) {
+	handle->db_args = NULL;
+	goto clean_n_exit;
+    }
+
+    handle->db_args = calloc(sizeof(char*), count+1);
+    if (handle->db_args == NULL) {
+	ret=ENOMEM;
+	goto clean_n_exit;
+    }
+
+    for (count=0; db_args[count]; count++) {
+	handle->db_args[count] = strdup(db_args[count]);
+	if (handle->db_args[count] == NULL) {
+	    ret = ENOMEM;
+	    goto clean_n_exit;
+	}
+    }
+
+ clean_n_exit:
+    if (ret && handle->db_args) {
+	for (count=0; handle->db_args[count]; count++)
+	    free(handle->db_args[count]);
+
+	free(handle->db_args), handle->db_args = NULL;
+    }
+
+    return ret;
+}
+
+static void free_db_args(kadm5_server_handle_t handle)
+{
+    int count;
+
+    if (handle->db_args) {
+	for (count=0; handle->db_args[count]; count++)
+	    free(handle->db_args[count]);
+
+	free(handle->db_args), handle->db_args = NULL;
+    }
+}
+
+kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass,
+				     char *service_name,
+				     kadm5_config_params *params,
+				     krb5_ui_4 struct_version,
+				     krb5_ui_4 api_version,
+				     char **db_args,
+				     void **server_handle)
+{
+     return kadm5_init(client_name, pass, service_name, params,
+		       struct_version, api_version, db_args,
+		       server_handle);
+}
+
+kadm5_ret_t kadm5_init_with_creds(char *client_name,
+				  krb5_ccache ccache,
+				  char *service_name,
+				  kadm5_config_params *params,
+				  krb5_ui_4 struct_version,
+				  krb5_ui_4 api_version,
+				  char **db_args,
+				  void **server_handle)
+{
+     /*
+      * A program calling init_with_creds *never* expects to prompt the
+      * user.  Therefore, always pass a dummy password in case this is
+      * KADM5_API_VERSION_1.  If this is KADM5_API_VERSION_2 and
+      * MKEY_FROM_KBD is non-zero, return an error.
+      */
+     if (api_version == KADM5_API_VERSION_2 && params &&
+	 (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) &&
+	 params->mkey_from_kbd)
+	  return KADM5_BAD_SERVER_PARAMS;
+     return kadm5_init(client_name, NULL, service_name, params,
+		       struct_version, api_version, db_args,
+		       server_handle);
+}
+
+
+kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab,
+				 char *service_name,
+				 kadm5_config_params *params,
+				 krb5_ui_4 struct_version,
+				 krb5_ui_4 api_version,
+				 char **db_args,
+				 void **server_handle)
+{
+     /*
+      * A program calling init_with_skey *never* expects to prompt the
+      * user.  Therefore, always pass a dummy password in case this is
+      * KADM5_API_VERSION_1.  If this is KADM5_API_VERSION_2 and
+      * MKEY_FROM_KBD is non-zero, return an error.
+      */
+     if (api_version == KADM5_API_VERSION_2 && params &&
+	 (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) &&
+	 params->mkey_from_kbd)
+	  return KADM5_BAD_SERVER_PARAMS;
+     return kadm5_init(client_name, NULL, service_name, params,
+		       struct_version, api_version, db_args,
+		       server_handle);
+}
+
+kadm5_ret_t kadm5_init(char *client_name, char *pass,
+		       char *service_name,
+		       kadm5_config_params *params_in,
+		       krb5_ui_4 struct_version,
+		       krb5_ui_4 api_version,
+		       char **db_args,
+		       void **server_handle)
+{
+     int ret;
+     kadm5_server_handle_t handle;
+     kadm5_config_params params_local; /* for v1 compat */
+
+    if (! server_handle)
+	 return EINVAL;
+
+    if (! client_name)
+	 return EINVAL;
+
+    if (! (handle = (kadm5_server_handle_t) malloc(sizeof *handle)))
+	 return ENOMEM;
+    memset(handle, 0, sizeof(*handle));
+
+    ret = dup_db_args(handle, db_args);
+    if (ret) {
+	free(handle);
+	return ret;
+    }
+
+    ret = (int) krb5int_init_context_kdc(&(handle->context));
+    if (ret) {
+	 free_db_args(handle);
+	 free(handle);
+	 return(ret);
+    }
+
+    initialize_ovk_error_table();
+/*     initialize_adb_error_table(); */
+    initialize_ovku_error_table();
+
+    handle->magic_number = KADM5_SERVER_HANDLE_MAGIC;
+    handle->struct_version = struct_version;
+    handle->api_version = api_version;
+
+     /*
+      * Verify the version numbers before proceeding; we can't use
+      * CHECK_HANDLE because not all fields are set yet.
+      */
+     GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION,
+			  KADM5_NEW_SERVER_API_VERSION);
+
+     /*
+      * Acquire relevant profile entries.  In version 2, merge values
+      * in params_in with values from profile, based on
+      * params_in->mask.
+      *
+      * In version 1, we've given a realm (which may be NULL) instead
+      * of params_in.  So use that realm, make params_in contain an
+      * empty mask, and behave like version 2.
+      */
+     memset((char *) ¶ms_local, 0, sizeof(params_local));
+     if (api_version == KADM5_API_VERSION_1) {
+	  params_local.realm = (char *) params_in;
+	  if (params_in)
+	       params_local.mask = KADM5_CONFIG_REALM;
+	  params_in = ¶ms_local;
+     }
+
+#if 0 /* Now that we look at krb5.conf as well as kdc.conf, we can
+	 expect to see admin_server being set sometimes.  */
+#define ILLEGAL_PARAMS (KADM5_CONFIG_ADMIN_SERVER)
+     if (params_in && (params_in->mask & ILLEGAL_PARAMS)) {
+	  krb5_free_context(handle->context);
+	  free_db_args(handle);
+	  free(handle);
+	  return KADM5_BAD_SERVER_PARAMS;
+     }
+#endif
+
+     ret = kadm5_get_config_params(handle->context, 1, params_in,
+				       &handle->params);
+     if (ret) {
+	  krb5_free_context(handle->context);
+	  free_db_args(handle);
+	  free(handle);
+	  return(ret);
+     }
+
+#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \
+			 KADM5_CONFIG_ADBNAME | \
+			 KADM5_CONFIG_ADB_LOCKFILE | \
+			 KADM5_CONFIG_ENCTYPE | \
+			 KADM5_CONFIG_FLAGS | \
+			 KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \
+			 KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES)
+
+     if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
+	  krb5_free_context(handle->context);
+	  free_db_args(handle);
+	  free(handle);
+	  return KADM5_MISSING_CONF_PARAMS;
+     }
+
+     ret = krb5_set_default_realm(handle->context, handle->params.realm);
+     if (ret) {
+	  krb5_free_context(handle->context);
+	  free_db_args(handle);
+	  free(handle);
+	  return ret;
+     }
+
+    ret = krb5_db_open(handle->context, db_args,
+		       KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
+    if (ret) {
+	 krb5_free_context(handle->context);
+	 free_db_args(handle);
+	 free(handle);
+	 return(ret);
+    }
+
+    if ((ret = krb5_parse_name(handle->context, client_name,
+			       &handle->current_caller))) {
+	 krb5_db_fini(handle->context);
+	 krb5_free_context(handle->context);
+	 free_db_args(handle);
+	 free(handle);
+	 return ret;
+    }
+
+    if (! (handle->lhandle = malloc(sizeof(*handle)))) {
+	 krb5_db_fini(handle->context);
+	 krb5_free_context(handle->context);
+	 free_db_args(handle);
+	 free(handle);
+	 return ENOMEM;
+    }
+    *handle->lhandle = *handle;
+    handle->lhandle->api_version = KADM5_API_VERSION_2;
+    handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
+    handle->lhandle->lhandle = handle->lhandle;
+
+    /* can't check the handle until current_caller is set */
+    ret = check_handle((void *) handle);
+    if (ret) {
+	free_db_args(handle);
+	free(handle);
+	return ret;
+    }
+
+    /*
+     * The KADM5_API_VERSION_1 spec said "If pass (or keytab) is NULL
+     * or an empty string, reads the master password from [the stash
+     * file].  Otherwise, the non-NULL password is ignored and the
+     * user is prompted for it via the tty."  However, the code was
+     * implemented the other way: when a non-NULL password was
+     * provided, the stash file was used.  This is somewhat more
+     * sensible, as then a local or remote client that provides a
+     * password does not prompt the user.  This code maintains the
+     * previous actual behavior, and not the old spec behavior,
+     * because that is how the unit tests are written.
+     *
+     * In KADM5_API_VERSION_2, this decision is controlled by
+     * params.
+     *
+     * kdb_init_master's third argument is "from_keyboard".
+     */
+    ret = kdb_init_master(handle, handle->params.realm,
+			  (handle->api_version == KADM5_API_VERSION_1 ?
+			   ((pass == NULL) || !(strlen(pass))) :
+			   ((handle->params.mask & KADM5_CONFIG_MKEY_FROM_KBD)
+			    && handle->params.mkey_from_kbd)
+			));
+    if (ret) {
+	krb5_db_fini(handle->context);
+	krb5_free_context(handle->context);
+	free_db_args(handle);
+	free(handle);
+	return ret;
+    }
+
+    ret = kdb_init_hist(handle, handle->params.realm);
+    if (ret) {
+	 krb5_db_fini(handle->context);
+	 krb5_free_context(handle->context);
+	 free_db_args(handle);
+	 free(handle);
+	 return ret;
+    }
+
+    ret = init_dict(&handle->params);
+    if (ret) {
+	 krb5_db_fini(handle->context);
+	 krb5_free_principal(handle->context, handle->current_caller);
+	 krb5_free_context(handle->context);
+	 free_db_args(handle);
+	 free(handle);
+	 return ret;
+    }
+
+    *server_handle = (void *) handle;
+
+    return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_destroy(void *server_handle)
+{
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    destroy_dict();
+
+    adb_policy_close(handle);
+    krb5_db_fini(handle->context);
+    krb5_free_principal(handle->context, handle->current_caller);
+    kadm5_free_config_params(handle->context, &handle->params);
+    krb5_free_context(handle->context);
+    handle->magic_number = 0;
+    free(handle->lhandle);
+    free_db_args(handle);
+    free(handle);
+
+    return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_lock(void *server_handle)
+{
+    kadm5_server_handle_t handle = server_handle;
+    kadm5_ret_t ret;
+
+    CHECK_HANDLE(server_handle);
+    ret = krb5_db_lock(handle->context, KRB5_DB_LOCKMODE_EXCLUSIVE);
+    if (ret)
+	return ret;
+
+    return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_unlock(void *server_handle)
+{
+    kadm5_server_handle_t handle = server_handle;
+    kadm5_ret_t ret;
+
+    CHECK_HANDLE(server_handle);
+    ret = krb5_db_unlock(handle->context);
+    if (ret)
+	return ret;
+
+    return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_flush(void *server_handle)
+{
+     kadm5_server_handle_t handle = server_handle;
+     kadm5_ret_t ret;
+
+     CHECK_HANDLE(server_handle);
+
+     if ((ret = krb5_db_fini(handle->context)) ||
+	 (ret = krb5_db_open(handle->context, handle->db_args,
+			     KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN)) ||
+	 (ret = adb_policy_close(handle)) ||
+	 (ret = adb_policy_init(handle))) {
+	  (void) kadm5_destroy(server_handle);
+	  return ret;
+     }
+     return KADM5_OK;
+}
+
+int _kadm5_check_handle(void *handle)
+{
+     CHECK_HANDLE(handle);
+     return 0;
+}
+
+#include "gssapiP_krb5.h"
+krb5_error_code kadm5_init_krb5_context (krb5_context *ctx)
+{
+    static int first_time = 1;
+    if (first_time) {
+	krb5_error_code err;
+	err = krb5_gss_use_kdc_context();
+	if (err)
+	    return err;
+	first_time = 0;
+    }
+    return krb5int_init_context_kdc(ctx);
+}
diff --git a/krb5-1-6/src/lib/kadm5/srv/server_kdb.c b/krb5-1-6/src/lib/kadm5/srv/server_kdb.c
new file mode 100644
index 000000000..6392ef10d
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/server_kdb.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "k5-int.h"
+#include <kadm5/admin.h>
+#include "server_internal.h"
+
+krb5_principal	    master_princ;
+krb5_keyblock	    master_keyblock;
+krb5_db_entry	    master_db;
+
+krb5_principal	    hist_princ;
+krb5_keyblock	    hist_key;
+krb5_db_entry	    hist_db;
+krb5_kvno	    hist_kvno;
+
+/* much of this code is stolen from the kdc.  there should be some
+   library code to deal with this. */
+
+krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
+				char *r, int from_keyboard)
+{
+    int		   ret = 0;
+    char	   *realm;
+    krb5_boolean   from_kbd = FALSE;
+
+    if (from_keyboard)
+      from_kbd = TRUE;
+
+    if (r == NULL)  {
+	if ((ret = krb5_get_default_realm(handle->context, &realm)))
+	    return ret;
+    } else {
+	realm = r;
+    }
+
+    if ((ret = krb5_db_setup_mkey_name(handle->context,
+				       handle->params.mkey_name,
+				       realm, NULL, &master_princ)))
+	goto done;
+
+    master_keyblock.enctype = handle->params.enctype;
+
+    ret = krb5_db_fetch_mkey(handle->context, master_princ,
+			     master_keyblock.enctype, from_kbd,
+			     FALSE /* only prompt once */,
+			     handle->params.stash_file,
+			     NULL /* I'm not sure about this,
+				     but it's what the kdc does --marc */,
+			     &master_keyblock);
+    if (ret)
+	goto done;
+				 
+    if ((ret = krb5_db_verify_master_key(handle->context, master_princ,
+					 &master_keyblock))) {
+	  krb5_db_fini(handle->context);
+	  return ret;
+    }
+
+done:
+    if (r == NULL)
+	free(realm);
+
+    return(ret);
+}
+
+/*
+ * Function: kdb_init_hist
+ *
+ * Purpose: Initializes the global history variables.
+ *
+ * Arguments:
+ *
+ *	handle		(r) kadm5 api server handle
+ *	r		(r) realm of history principal to use, or NULL
+ *
+ * Effects: This function sets the value of the following global
+ * variables:
+ *
+ *	hist_princ	krb5_principal holding the history principal
+ *	hist_db		krb5_db_entry of the history principal
+ *	hist_key	krb5_keyblock holding the history principal's key
+ *	hist_encblock	krb5_encrypt_block holding the procssed hist_key
+ *	hist_kvno	the version number of the history key
+ *
+ * If the history principal does not already exist, this function
+ * attempts to create it with kadm5_create_principal.  WARNING!
+ * If the history principal is deleted and this function is executed
+ * (by kadmind, or kadmin.local, or anything else with permission),
+ * the principal will be assigned a new random key and all existing
+ * password history information will become useless.
+ */
+krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
+{
+    int	    ret = 0;
+    char    *realm, *hist_name;
+    krb5_key_data *key_data;
+    krb5_key_salt_tuple ks[1];
+
+    if (r == NULL)  {
+	if ((ret = krb5_get_default_realm(handle->context, &realm)))
+	    return ret;
+    } else {
+	realm = r;
+    }
+
+    if ((hist_name = (char *) malloc(strlen(KADM5_HIST_PRINCIPAL) +
+				     strlen(realm) + 2)) == NULL)
+	goto done;
+
+    (void) sprintf(hist_name, "%s@%s", KADM5_HIST_PRINCIPAL, realm);
+
+    if ((ret = krb5_parse_name(handle->context, hist_name, &hist_princ)))
+	goto done;
+
+    if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL))) {
+	kadm5_principal_ent_rec ent;
+
+	if (ret != KADM5_UNK_PRINC)
+	    goto done;
+
+	/* try to create the principal */
+
+	memset(&ent, 0, sizeof(ent));
+
+	ent.principal = hist_princ;
+	ent.max_life = KRB5_KDB_DISALLOW_ALL_TIX;
+	ent.attributes = 0;
+
+	/* this uses hist_kvno.  So we set it to 2, which will be the
+	   correct value once the principal is created and randomized.
+	   Of course, it doesn't make sense to keep a history for the
+	   history principal, anyway. */
+
+	hist_kvno = 2;
+	ks[0].ks_enctype = handle->params.enctype;
+	ks[0].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
+	ret = kadm5_create_principal_3(handle, &ent,
+				       (KADM5_PRINCIPAL | KADM5_MAX_LIFE |
+					KADM5_ATTRIBUTES),
+				       1, ks,
+				       "to-be-random");
+	if (ret)
+	    goto done;
+
+	/* this won't let us randomize the hist_princ.  So we cheat. */
+
+	hist_princ = NULL;
+
+	ret = kadm5_randkey_principal_3(handle, ent.principal, 0, 1, ks,
+					NULL, NULL);
+
+	hist_princ = ent.principal;
+
+	if (ret)
+	    goto done;
+
+	/* now read the newly-created kdb record out of the
+	   database. */
+
+	if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL)))
+	    goto done;
+
+    }
+
+    ret = krb5_dbe_find_enctype(handle->context, &hist_db,
+				handle->params.enctype, -1, -1, &key_data);
+    if (ret)
+	goto done;
+
+    ret = krb5_dbekd_decrypt_key_data(handle->context, &master_keyblock,
+				  key_data, &hist_key, NULL);
+    if (ret)
+	goto done;
+
+    hist_kvno = key_data->key_data_kvno;
+
+done:
+    free(hist_name);
+    if (r == NULL)
+	free(realm);
+    return ret;
+}
+
+/*
+ * Function: kdb_get_entry
+ *
+ * Purpose: Gets an entry from the kerberos database and breaks
+ * it out into a krb5_db_entry and an osa_princ_ent_t.
+ *
+ * Arguments:
+ *
+ *		handle		(r) the server_handle
+ * 		principal	(r) the principal to get
+ * 		kdb		(w) krb5_db_entry to fill in
+ * 		adb		(w) osa_princ_ent_rec to fill in
+ *
+ * when the caller is done with kdb and adb, kdb_free_entry must be
+ * called to release them.  The adb record is filled in with the
+ * contents of the KRB5_TL_KADM_DATA record; if that record doesn't
+ * exist, an empty but valid adb record is returned.
+ */
+krb5_error_code
+kdb_get_entry(kadm5_server_handle_t handle,
+	      krb5_principal principal, krb5_db_entry *kdb,
+	      osa_princ_ent_rec *adb)
+{
+    krb5_error_code ret;
+    int nprincs;
+    krb5_boolean more;
+    krb5_tl_data tl_data;
+    XDR xdrs;
+
+    ret = krb5_db_get_principal(handle->context, principal, kdb, &nprincs,
+				&more);
+    if (ret)
+	return(ret);
+
+    if (more) {
+	krb5_db_free_principal(handle->context, kdb, nprincs);
+	return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+    } else if (nprincs != 1) {
+	krb5_db_free_principal(handle->context, kdb, nprincs);
+	return(KADM5_UNK_PRINC);
+    }
+
+    if (adb) {
+	memset(adb, 0, sizeof(*adb));
+
+	tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+	/*
+	 * XXX Currently, lookup_tl_data always returns zero; it sets
+	 * tl_data->tl_data_length to zero if the type isn't found.
+	 * This should be fixed...
+	 */
+	if ((ret = krb5_dbe_lookup_tl_data(handle->context, kdb, &tl_data))
+	    || (tl_data.tl_data_length == 0)) {
+	    /* there's no admin data.  this can happen, if the admin
+	       server is put into production after some principals
+	       are created.  In this case, return valid admin
+	       data (which is all zeros with the hist_kvno filled
+	       in), and when the entry is written, the admin
+	       data will get stored correctly. */
+
+	    adb->admin_history_kvno = hist_kvno;
+
+	    return(ret);
+	}
+
+	xdrmem_create(&xdrs, tl_data.tl_data_contents,
+		      tl_data.tl_data_length, XDR_DECODE);
+	if (! xdr_osa_princ_ent_rec(&xdrs, adb)) {
+	   xdr_destroy(&xdrs);
+	   krb5_db_free_principal(handle->context, kdb, 1);
+	   return(KADM5_XDR_FAILURE);
+	}
+	xdr_destroy(&xdrs);
+    }
+
+    return(0);
+}
+
+/*
+ * Function: kdb_free_entry
+ *
+ * Purpose: frees the resources allocated by kdb_get_entry
+ *
+ * Arguments:
+ *
+ *		handle		(r) the server_handle
+ * 		kdb		(w) krb5_db_entry to fill in
+ * 		adb		(w) osa_princ_ent_rec to fill in
+ *
+ * when the caller is done with kdb and adb, kdb_free_entry must be
+ * called to release them.
+ */
+
+krb5_error_code
+kdb_free_entry(kadm5_server_handle_t handle,
+	       krb5_db_entry *kdb, osa_princ_ent_rec *adb)
+{
+    XDR xdrs;
+
+
+    if (kdb)
+	krb5_db_free_principal(handle->context, kdb, 1);
+
+    if (adb) {
+	xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+	xdr_osa_princ_ent_rec(&xdrs, adb);
+	xdr_destroy(&xdrs);
+    }
+
+    return(0);
+}
+
+/*
+ * Function: kdb_put_entry
+ *
+ * Purpose: Stores the osa_princ_ent_t and krb5_db_entry into to
+ * database.
+ *
+ * Arguments:
+ *
+ *		handle	(r) the server_handle
+ * 		kdb	(r/w) the krb5_db_entry to store
+ * 		adb	(r) the osa_princ_db_ent to store
+ *
+ * Effects:
+ *
+ * The last modifier field of the kdb is set to the caller at now.
+ * adb is encoded with xdr_osa_princ_ent_ret and stored in kbd as
+ * KRB5_TL_KADM_DATA.  kdb is then written to the database.
+ */
+krb5_error_code
+kdb_put_entry(kadm5_server_handle_t handle,
+	      krb5_db_entry *kdb, osa_princ_ent_rec *adb)
+{
+    krb5_error_code ret;
+    krb5_int32 now;
+    XDR xdrs;
+    krb5_tl_data tl_data;
+    int one;
+
+    ret = krb5_timeofday(handle->context, &now);
+    if (ret)
+	return(ret);
+
+    ret = krb5_dbe_update_mod_princ_data(handle->context, kdb, now,
+					 handle->current_caller);
+    if (ret)
+	return(ret);
+    
+    xdralloc_create(&xdrs, XDR_ENCODE); 
+    if(! xdr_osa_princ_ent_rec(&xdrs, adb)) {
+	xdr_destroy(&xdrs);
+	return(KADM5_XDR_FAILURE);
+    }
+    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+    tl_data.tl_data_length = xdr_getpos(&xdrs);
+    tl_data.tl_data_contents = xdralloc_getdata(&xdrs);
+
+    ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data);
+
+    xdr_destroy(&xdrs);
+
+    if (ret)
+	return(ret);
+
+    one = 1;
+
+    ret = krb5_db_put_principal(handle->context, kdb, &one);
+    if (ret)
+	return(ret);
+
+    return(0);
+}
+
+krb5_error_code
+kdb_delete_entry(kadm5_server_handle_t handle, krb5_principal name)
+{
+    int one = 1;
+    krb5_error_code ret;
+    
+    ret = krb5_db_delete_principal(handle->context, name, &one);
+
+    return ret;
+}
+
+typedef struct _iter_data {
+    void (*func)(void *, krb5_principal);
+    void *data;
+} iter_data;
+
+static krb5_error_code
+kdb_iter_func(krb5_pointer data, krb5_db_entry *kdb)
+{
+    iter_data *id = (iter_data *) data;
+
+    (*(id->func))(id->data, kdb->princ);
+
+    return(0);
+}
+
+krb5_error_code
+kdb_iter_entry(kadm5_server_handle_t handle, char *match_entry,
+	       void (*iter_fct)(void *, krb5_principal), void *data)
+{
+    iter_data id;
+    krb5_error_code ret;
+
+    id.func = iter_fct;
+    id.data = data;
+
+    ret = krb5_db_iterate(handle->context, match_entry, kdb_iter_func, &id);
+    if (ret)
+	return(ret);
+
+    return(0);
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/srv/server_misc.c b/krb5-1-6/src/lib/kadm5/srv/server_misc.c
new file mode 100644
index 000000000..cd65371c9
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/server_misc.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include    "k5-int.h"
+#include    <kdb.h>
+#include    <ctype.h>
+#include    <pwd.h>
+
+/* for strcasecmp */
+#include    <string.h>
+
+#include    "server_internal.h"
+
+kadm5_ret_t
+adb_policy_init(kadm5_server_handle_t handle)
+{
+    /* now policy is initialized as part of database. No seperate call needed */
+    if( krb5_db_inited( handle->context ) )
+	return KADM5_OK;
+
+    return krb5_db_open( handle->context, NULL, 
+			 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN );
+}
+
+kadm5_ret_t
+adb_policy_close(kadm5_server_handle_t handle)
+{
+    /* will be taken care by database close */
+    return KADM5_OK;
+}
+
+#ifdef HESIOD
+/* stolen from v4sever/kadm_funcs.c */
+static char *
+reverse(str)
+	char	*str;
+{
+	static char newstr[80];
+	char	*p, *q;
+	int	i;
+
+	i = strlen(str);
+	if (i >= sizeof(newstr))
+		i = sizeof(newstr)-1;
+	p = str+i-1;
+	q = newstr;
+	q[i]='\0';
+	for(; i > 0; i--) 
+		*q++ = *p--;
+	
+	return(newstr);
+}
+#endif /* HESIOD */
+
+#if 0
+static int
+lower(str)
+	char	*str;
+{
+	register char	*cp;
+	int	effect=0;
+
+	for (cp = str; *cp; cp++) {
+		if (isupper(*cp)) {
+			*cp = tolower(*cp);
+			effect++;
+		}
+	}
+	return(effect);
+}
+#endif
+
+#ifdef HESIOD
+static int
+str_check_gecos(gecos, pwstr)
+	char	*gecos;
+	char	*pwstr;
+{
+	char		*cp, *ncp, *tcp;
+	
+	for (cp = gecos; *cp; ) {
+		/* Skip past punctuation */
+		for (; *cp; cp++)
+			if (isalnum(*cp))
+				break;
+		/* Skip to the end of the word */
+		for (ncp = cp; *ncp; ncp++)
+			if (!isalnum(*ncp) && *ncp != '\'')
+				break;
+		/* Delimit end of word */
+		if (*ncp)
+			*ncp++ = '\0';
+		/* Check word to see if it's the password */
+		if (*cp) {
+			if (!strcasecmp(pwstr, cp))
+				return 1;
+			tcp = reverse(cp);
+			if (!strcasecmp(pwstr, tcp))
+				return 1;
+			cp = ncp;				
+		} else
+			break;
+	}
+	return 0;
+}
+#endif /* HESIOD */
+
+/* some of this is stolen from gatekeeper ... */
+kadm5_ret_t
+passwd_check(kadm5_server_handle_t handle,
+	     char *password, int use_policy, kadm5_policy_ent_t pol,
+	     krb5_principal principal)
+{
+    int	    nupper = 0,
+	    nlower = 0,
+	    ndigit = 0, 
+	    npunct = 0,
+	    nspec = 0;
+    char    c, *s, *cp;
+#ifdef HESIOD
+    extern  struct passwd *hes_getpwnam();
+    struct  passwd *ent;
+#endif
+    
+    if(use_policy) {
+	if(strlen(password) < pol->pw_min_length)
+	    return KADM5_PASS_Q_TOOSHORT;
+	s = password;
+	while ((c = *s++)) {
+	    if (islower((unsigned char) c)) {
+		nlower = 1;
+		continue;
+	    }
+	    else if (isupper((unsigned char) c)) {
+		nupper = 1;
+		continue;
+	    } else if (isdigit((unsigned char) c)) {
+		ndigit = 1;
+		continue;
+	    } else if (ispunct((unsigned char) c)) {
+		npunct = 1;
+		continue;
+	    } else {
+		nspec = 1;
+		continue;
+	    }
+	}
+	if ((nupper + nlower + ndigit + npunct + nspec) < pol->pw_min_classes) 
+	    return KADM5_PASS_Q_CLASS;
+	if((find_word(password) == KADM5_OK))
+	    return KADM5_PASS_Q_DICT;
+	else { 
+	    int	i, n = krb5_princ_size(handle->context, principal);
+	    cp = krb5_princ_realm(handle->context, principal)->data;
+	    if (strcasecmp(cp, password) == 0)
+		return KADM5_PASS_Q_DICT;
+	    for (i = 0; i < n ; i++) {
+		cp = krb5_princ_component(handle->context, principal, i)->data;
+		if (strcasecmp(cp, password) == 0)
+		    return KADM5_PASS_Q_DICT;
+#ifdef HESIOD
+		ent = hes_getpwnam(cp);
+		if (ent && ent->pw_gecos)
+		    if (str_check_gecos(ent->pw_gecos, password))
+			return KADM5_PASS_Q_DICT; /* XXX new error code? */
+#endif
+	    }
+	    return KADM5_OK;
+	}
+    } else {
+	if (strlen(password) < 1)
+	    return KADM5_PASS_Q_TOOSHORT;
+    }
+    return KADM5_OK;    
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/srv/svr_chpass_util.c b/krb5-1-6/src/lib/kadm5/srv/svr_chpass_util.c
new file mode 100644
index 000000000..c8b63100a
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/svr_chpass_util.c
@@ -0,0 +1,16 @@
+#include <kadm5/admin.h>
+#include "server_internal.h"
+
+kadm5_ret_t kadm5_chpass_principal_util(void *server_handle,
+					krb5_principal princ,
+					char *new_pw, 
+					char **ret_pw,
+					char *msg_ret,
+					unsigned int msg_len)
+{
+  kadm5_server_handle_t handle = server_handle;
+
+  CHECK_HANDLE(server_handle);
+  return _kadm5_chpass_principal_util(handle, handle->lhandle, princ,
+				      new_pw, ret_pw, msg_ret, msg_len);
+}
diff --git a/krb5-1-6/src/lib/kadm5/srv/svr_iters.c b/krb5-1-6/src/lib/kadm5/srv/svr_iters.c
new file mode 100644
index 000000000..d78b9e554
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/svr_iters.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include "autoconf.h"
+#if defined(HAVE_COMPILE) && defined(HAVE_STEP)
+#define SOLARIS_REGEXPS
+#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC)
+#define POSIX_REGEXPS
+#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC)
+#define BSD_REGEXPS
+#else
+#error I cannot find any regexp functions
+#endif
+
+#include	<sys/types.h>
+#include	<string.h>
+#include	<kadm5/admin.h>
+#ifdef SOLARIS_REGEXPS
+#include	<regexpr.h>
+#endif
+#ifdef POSIX_REGEXPS
+#include	<regex.h>
+#endif
+#include <stdlib.h>
+
+#include	"server_internal.h"
+
+struct iter_data {
+     krb5_context context;
+     char **names;
+     int n_names, sz_names;
+     unsigned int malloc_failed;
+     char *exp;
+#ifdef SOLARIS_REGEXPS
+     char *expbuf;
+#endif
+#ifdef POSIX_REGEXPS
+     regex_t preg;
+#endif
+};
+
+/*
+ * Function: glob_to_regexp
+ *
+ * Arguments:
+ *
+ *	glob	(r) the shell-style glob (?*[]) to convert
+ *	realm	(r) the default realm to append, or NULL
+ *	regexp	(w) the ed-style regexp created from glob
+ *
+ * Effects:
+ *
+ * regexp is filled in with allocated memory contained a regular
+ * expression to be used with re_comp/compile that matches what the
+ * shell-style glob would match.  If glob does not contain an "@"
+ * character and realm is not NULL, "@*" is appended to the regexp.
+ *
+ * Conversion algorithm:
+ *
+ *	quoted characters are copied quoted
+ *	? is converted to .
+ *	* is converted to .*
+ * 	active characters are quoted: ^, $, .
+ *	[ and ] are active but supported and have the same meaning, so
+ *		they are copied
+ *	other characters are copied
+ *	regexp is anchored with ^ and $
+ */
+static kadm5_ret_t glob_to_regexp(char *glob, char *realm, char **regexp)
+{
+     int append_realm;
+     char *p;
+
+     /* validate the glob */
+     if (glob[strlen(glob)-1] == '\\')
+	  return EINVAL;
+
+     /* A character of glob can turn into two in regexp, plus ^ and $ */
+     /* and trailing null.  If glob has no @, also allocate space for */
+     /* the realm. */
+     append_realm = (realm != NULL) && (strchr(glob, '@') == NULL);
+     p = (char *) malloc(strlen(glob)*2+ 3 + (append_realm ? 2 : 0));
+     if (p == NULL)
+	  return ENOMEM;
+     *regexp = p;
+
+     *p++ = '^';
+     while (*glob) {
+	  switch (*glob) {
+	  case '?':
+	       *p++ = '.';
+	       break;
+	  case '*':
+	       *p++ = '.';
+	       *p++ = '*';
+	       break;
+	  case '.':
+	  case '^':
+	  case '$':
+	       *p++ = '\\';
+	       *p++ = *glob;
+	       break;
+	  case '\\':
+	       *p++ = '\\';
+	       *p++ = *++glob;
+	       break;
+	  default:
+	       *p++ = *glob;
+	       break;
+	  }
+	  glob++;
+     }
+
+     if (append_realm) {
+	  *p++ = '@';
+	  *p++ = '*';
+     }
+
+     *p++ = '$';
+     *p++ = '\0';
+     return KADM5_OK;
+}
+
+static void get_either_iter(struct iter_data *data, char *name)
+{
+     int match;
+#ifdef SOLARIS_REGEXPS
+     match = (step(name, data->expbuf) != 0);
+#endif
+#ifdef POSIX_REGEXPS
+     match = (regexec(&data->preg, name, 0, NULL, 0) == 0);
+#endif
+#ifdef BSD_REGEXPS
+     match = (re_exec(name) != 0);
+#endif
+     if (match) {
+	  if (data->n_names == data->sz_names) {
+	       int new_sz = data->sz_names * 2;
+	       char **new_names = realloc(data->names,
+					  new_sz * sizeof(char *));
+	       if (new_names) {
+		    data->names = new_names;
+		    data->sz_names = new_sz;
+	       } else {
+		    data->malloc_failed = 1;
+		    free(name);
+		    return;
+	       }
+	  }
+	  data->names[data->n_names++] = name;
+     } else
+	  free(name);
+}
+
+static void get_pols_iter(void *data, osa_policy_ent_t entry)
+{
+     char *name;
+
+     if ((name = strdup(entry->name)) == NULL)
+	  return;
+     get_either_iter(data, name);
+}
+
+static void get_princs_iter(void *data, krb5_principal princ)
+{
+     struct iter_data *id = (struct iter_data *) data;
+     char *name;
+     
+     if (krb5_unparse_name(id->context, princ, &name) != 0)
+	  return;
+     get_either_iter(data, name);
+}
+
+static kadm5_ret_t kadm5_get_either(int princ,
+				       void *server_handle,
+				       char *exp,
+				       char ***princs,
+				       int *count)
+{
+     struct iter_data data;
+#ifdef BSD_REGEXPS
+     char *msg;
+#endif
+     char *regexp;
+     int i, ret;
+     kadm5_server_handle_t handle = server_handle;
+     
+     *count = 0;
+     if (exp == NULL)
+	  exp = "*";
+
+     CHECK_HANDLE(server_handle);
+
+     if ((ret = glob_to_regexp(exp, princ ? handle->params.realm : NULL,
+			       ®exp)) != KADM5_OK)
+	  return ret;
+
+     if (
+#ifdef SOLARIS_REGEXPS
+	 ((data.expbuf = compile(regexp, NULL, NULL)) == NULL)
+#endif
+#ifdef POSIX_REGEXPS
+	 ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0)
+#endif
+#ifdef BSD_REGEXPS
+	 ((msg = (char *) re_comp(regexp)) != NULL)
+#endif
+	 )
+     {
+	  /* XXX syslog msg or regerr(regerrno) */
+	  free(regexp);
+	  return EINVAL;
+     }
+
+     data.n_names = 0;
+     data.sz_names = 10;
+     data.malloc_failed = 0;
+     data.names = malloc(sizeof(char *) * data.sz_names);
+     if (data.names == NULL) {
+	  free(regexp);
+	  return ENOMEM;
+     }
+
+     if (princ) {
+	  data.context = handle->context;
+	  ret = kdb_iter_entry(handle, exp, get_princs_iter, (void *) &data);
+     } else {
+	  ret = krb5_db_iter_policy(handle->context, exp, get_pols_iter, (void *)&data);
+     }
+     
+     free(regexp);
+#ifdef POSIX_REGEXPS
+     regfree(&data.preg);
+#endif
+     if ( !ret && data.malloc_failed)
+	  ret = ENOMEM;
+     if ( ret ) {
+	  for (i = 0; i < data.n_names; i++)
+	       free(data.names[i]);
+	  free(data.names);
+	  return ret;
+     }
+
+     *princs = data.names;
+     *count = data.n_names;
+     return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_get_principals(void *server_handle,
+					   char *exp,
+					   char ***princs,
+					   int *count)
+{
+     return kadm5_get_either(1, server_handle, exp, princs, count);
+}
+
+kadm5_ret_t kadm5_get_policies(void *server_handle,
+					   char *exp,
+					   char ***pols,
+					   int *count)
+{
+     return kadm5_get_either(0, server_handle, exp, pols, count);
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/srv/svr_misc_free.c b/krb5-1-6/src/lib/kadm5/srv/svr_misc_free.c
new file mode 100644
index 000000000..d20339705
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/svr_misc_free.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ * 
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+#include	<kadm5/admin.h>
+#include	<stdlib.h>
+#include	"server_internal.h"
+
+kadm5_ret_t
+kadm5_free_principal_ent(void *server_handle,
+			      kadm5_principal_ent_t val)
+{
+    kadm5_server_handle_t	handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    if(val) {
+	if(val->principal) 
+	    krb5_free_principal(handle->context, val->principal);
+	if(val->mod_name)
+	    krb5_free_principal(handle->context, val->mod_name);
+	if(val->policy)
+	    free(val->policy);
+
+	/* XXX free key_data and tl_data */
+
+	if (handle->api_version == KADM5_API_VERSION_1)
+	     free(val);
+    }
+    return KADM5_OK;
+}
diff --git a/krb5-1-6/src/lib/kadm5/srv/svr_policy.c b/krb5-1-6/src/lib/kadm5/srv/svr_policy.c
new file mode 100644
index 000000000..512876b79
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/svr_policy.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include	<sys/types.h>
+#include	<kadm5/admin.h>
+#include	"server_internal.h"
+#include	<stdlib.h>
+#include	<errno.h>
+
+#define MAX_PW_HISTORY	10
+#define MIN_PW_HISTORY	1
+#define	MIN_PW_CLASSES	1
+#define MAX_PW_CLASSES	5
+#define	MIN_PW_LENGTH	1
+
+/*
+ * Function: kadm5_create_policy
+ * 
+ * Purpose: Create Policies in the policy DB.
+ *
+ * Arguments:
+ *	entry	(input) The policy entry to be written out to the DB.
+ *	mask	(input)	Specifies which fields in entry are to ge written out
+ *			and which get default values.
+ *	<return value> 0 if successful otherwise an error code is returned.
+ *
+ * Requires:
+ *	Entry must be a valid principal entry, and mask have a valid value.
+ * 
+ * Effects:
+ *	Verifies that mask does not specify that the refcount should
+ *	be set as part of the creation, and calls
+ *	kadm5_create_policy_internal.  If the refcount *is*
+ *	specified, returns KADM5_BAD_MASK.
+ */
+
+kadm5_ret_t
+kadm5_create_policy(void *server_handle,
+			 kadm5_policy_ent_t entry, long mask)
+{
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(((kadm5_server_handle_t)server_handle)->context);
+
+    if (mask & KADM5_REF_COUNT)
+	return KADM5_BAD_MASK;
+    else
+	return kadm5_create_policy_internal(server_handle, entry, mask);
+}
+
+/*
+ * Function: kadm5_create_policy_internal
+ * 
+ * Purpose: Create Policies in the policy DB.
+ *
+ * Arguments:
+ *	entry	(input) The policy entry to be written out to the DB.
+ *	mask	(input)	Specifies which fields in entry are to ge written out
+ *			and which get default values.
+ *	<return value> 0 if successful otherwise an error code is returned.
+ *
+ * Requires:
+ *	Entry must be a valid principal entry, and mask have a valid value.
+ * 
+ * Effects:
+ *	Writes the data to the database, and does a database sync if
+ *	successful.
+ *
+ */
+
+kadm5_ret_t
+kadm5_create_policy_internal(void *server_handle,
+				  kadm5_policy_ent_t entry, long mask)
+{
+    kadm5_server_handle_t handle = server_handle;
+    osa_policy_ent_rec	pent;
+    int			ret;
+    char		*p;
+
+    CHECK_HANDLE(server_handle);
+
+    if ((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
+	return EINVAL;
+    if(strlen(entry->policy) == 0)
+	return KADM5_BAD_POLICY;
+    if (!(mask & KADM5_POLICY))
+	return KADM5_BAD_MASK;
+	
+    pent.name = entry->policy;
+    p = entry->policy;
+    while(*p != '\0') {
+	if(*p < ' ' || *p > '~')
+	    return KADM5_BAD_POLICY;
+	else
+	    p++;
+    }
+    if (!(mask & KADM5_PW_MAX_LIFE))
+	pent.pw_max_life = 0;
+    else
+	pent.pw_max_life = entry->pw_max_life;
+    if (!(mask & KADM5_PW_MIN_LIFE))
+	pent.pw_min_life = 0;
+    else {
+	if((mask & KADM5_PW_MAX_LIFE)) {
+	    if(entry->pw_min_life > entry->pw_max_life && entry->pw_max_life != 0)
+		return KADM5_BAD_MIN_PASS_LIFE;
+	}
+	pent.pw_min_life = entry->pw_min_life;
+    }
+    if (!(mask & KADM5_PW_MIN_LENGTH))
+	pent.pw_min_length = MIN_PW_LENGTH;
+    else {
+	if(entry->pw_min_length < MIN_PW_LENGTH)
+	    return KADM5_BAD_LENGTH;
+	pent.pw_min_length = entry->pw_min_length;
+    }
+    if (!(mask & KADM5_PW_MIN_CLASSES))
+	pent.pw_min_classes = MIN_PW_CLASSES;
+    else {
+	if(entry->pw_min_classes > MAX_PW_CLASSES || entry->pw_min_classes < MIN_PW_CLASSES)
+	    return KADM5_BAD_CLASS;
+	pent.pw_min_classes = entry->pw_min_classes;
+    }
+    if (!(mask & KADM5_PW_HISTORY_NUM))
+	pent.pw_history_num = MIN_PW_HISTORY;
+    else {
+	if(entry->pw_history_num < MIN_PW_HISTORY ||
+	   entry->pw_history_num > MAX_PW_HISTORY)
+	    return KADM5_BAD_HISTORY;
+	else
+	    pent.pw_history_num = entry->pw_history_num;
+    }
+    if (!(mask & KADM5_REF_COUNT))
+	pent.policy_refcnt = 0;
+    else
+	pent.policy_refcnt = entry->policy_refcnt;
+    if ((ret = krb5_db_create_policy(handle->context, &pent)))
+	return ret;
+    else
+	return KADM5_OK;
+}
+	  
+kadm5_ret_t
+kadm5_delete_policy(void *server_handle, kadm5_policy_t name)
+{
+    kadm5_server_handle_t handle = server_handle;
+    osa_policy_ent_t		entry;
+    int				ret;
+    int                         cnt=1;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if(name == (kadm5_policy_t) NULL)
+	return EINVAL;
+    if(strlen(name) == 0)
+	return KADM5_BAD_POLICY;
+    if((ret = krb5_db_get_policy(handle->context, name, &entry,&cnt)))
+	return ret;
+    if( cnt != 1 )
+	return KADM5_UNK_POLICY;
+
+    if(entry->policy_refcnt != 0) {
+	krb5_db_free_policy(handle->context, entry);
+	return KADM5_POLICY_REF;
+    }
+    krb5_db_free_policy(handle->context, entry);
+    if ((ret = krb5_db_delete_policy(handle->context, name)))
+	return ret;
+    else
+	return KADM5_OK;
+}
+
+kadm5_ret_t
+kadm5_modify_policy(void *server_handle,
+			 kadm5_policy_ent_t entry, long mask)
+{
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(((kadm5_server_handle_t)server_handle)->context);
+
+    if (mask & KADM5_REF_COUNT)
+	return KADM5_BAD_MASK;
+    else
+	return kadm5_modify_policy_internal(server_handle, entry, mask);
+}
+
+kadm5_ret_t
+kadm5_modify_policy_internal(void *server_handle,
+				  kadm5_policy_ent_t entry, long mask)
+{
+    kadm5_server_handle_t handle = server_handle;
+    osa_policy_ent_t	p;
+    int			ret;
+    int                 cnt=1;
+
+    CHECK_HANDLE(server_handle);
+
+    if((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
+	return EINVAL;
+    if(strlen(entry->policy) == 0)
+	return KADM5_BAD_POLICY;
+    if((mask & KADM5_POLICY))
+	return KADM5_BAD_MASK;
+		
+    if ((ret = krb5_db_get_policy(handle->context, entry->policy, &p, &cnt)))
+	return ret;
+    if (cnt != 1)
+	return KADM5_UNK_POLICY;
+
+    if ((mask & KADM5_PW_MAX_LIFE))
+	p->pw_max_life = entry->pw_max_life;
+    if ((mask & KADM5_PW_MIN_LIFE)) {
+	if(entry->pw_min_life > p->pw_max_life && p->pw_max_life != 0)	{
+	     krb5_db_free_policy(handle->context, p);
+	     return KADM5_BAD_MIN_PASS_LIFE;
+	}
+	p->pw_min_life = entry->pw_min_life;
+    }
+    if ((mask & KADM5_PW_MIN_LENGTH)) {
+	if(entry->pw_min_length < MIN_PW_LENGTH) {
+	      krb5_db_free_policy(handle->context, p);
+	      return KADM5_BAD_LENGTH;
+	 }
+	p->pw_min_length = entry->pw_min_length;
+    }
+    if ((mask & KADM5_PW_MIN_CLASSES)) {
+	if(entry->pw_min_classes > MAX_PW_CLASSES ||
+	   entry->pw_min_classes < MIN_PW_CLASSES) {
+	     krb5_db_free_policy(handle->context, p);
+	     return KADM5_BAD_CLASS;
+	}
+	p->pw_min_classes = entry->pw_min_classes;
+    }
+    if ((mask & KADM5_PW_HISTORY_NUM)) {
+	if(entry->pw_history_num < MIN_PW_HISTORY ||
+	   entry->pw_history_num > MAX_PW_HISTORY) {
+	     krb5_db_free_policy(handle->context, p);
+	     return KADM5_BAD_HISTORY;
+	}
+	p->pw_history_num = entry->pw_history_num;
+    }
+    if ((mask & KADM5_REF_COUNT))
+	p->policy_refcnt = entry->policy_refcnt;
+    ret = krb5_db_put_policy(handle->context, p);
+    krb5_db_free_policy(handle->context, p);
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_get_policy(void *server_handle, kadm5_policy_t name,
+		 kadm5_policy_ent_t entry) 
+{
+    osa_policy_ent_t		t;
+    kadm5_policy_ent_rec	entry_local, **entry_orig, *new;
+    int				ret;
+    kadm5_server_handle_t handle = server_handle;
+    int                         cnt=1;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    /*
+     * In version 1, entry is a pointer to a kadm5_policy_ent_t that
+     * should be filled with allocated memory.
+     */
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 entry_orig = (kadm5_policy_ent_rec **) entry;
+	 *entry_orig = NULL;
+	 entry = &entry_local;
+    }
+    
+    if (name == (kadm5_policy_t) NULL)
+	return EINVAL;
+    if(strlen(name) == 0)
+	return KADM5_BAD_POLICY;
+    if((ret = krb5_db_get_policy(handle->context, name, &t, &cnt)))
+	return ret;
+
+    if( cnt != 1 )
+	return KADM5_UNK_POLICY;
+
+    if ((entry->policy = (char *) malloc(strlen(t->name) + 1)) == NULL) {
+	 krb5_db_free_policy(handle->context, t);
+	 return ENOMEM;
+    }
+    strcpy(entry->policy, t->name);
+    entry->pw_min_life = t->pw_min_life;
+    entry->pw_max_life = t->pw_max_life;
+    entry->pw_min_length = t->pw_min_length;
+    entry->pw_min_classes = t->pw_min_classes;
+    entry->pw_history_num = t->pw_history_num;
+    entry->policy_refcnt = t->policy_refcnt;
+    krb5_db_free_policy(handle->context, t);
+
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 new = (kadm5_policy_ent_t) malloc(sizeof(kadm5_policy_ent_rec));
+	 if (new == NULL) {
+	      free(entry->policy);
+	      krb5_db_free_policy(handle->context, t);
+	      return ENOMEM;
+	 }
+	 *new = *entry;
+	 *entry_orig = new;
+    }
+    
+    return KADM5_OK;
+}
diff --git a/krb5-1-6/src/lib/kadm5/srv/svr_principal.c b/krb5-1-6/src/lib/kadm5/srv/svr_principal.c
new file mode 100644
index 000000000..f94d7e893
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/srv/svr_principal.c
@@ -0,0 +1,2109 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include	<sys/types.h>
+#include	<sys/time.h>
+#include	<errno.h>
+#include	<kadm5/admin.h>
+#include	<kdb.h>
+#include	<stdio.h>
+#include	<string.h>
+#include	"server_internal.h"
+#include	<stdarg.h>
+#include	<stdlib.h>
+#ifdef USE_PASSWORD_SERVER
+#include	<sys/wait.h>
+#endif
+
+extern	krb5_principal	    master_princ;
+extern	krb5_principal	    hist_princ;
+extern	krb5_keyblock	    master_keyblock;
+extern	krb5_keyblock	    hist_key;
+extern	krb5_db_entry	    master_db;
+extern	krb5_db_entry	    hist_db;
+extern  krb5_kvno	    hist_kvno;
+
+static int decrypt_key_data(krb5_context context,
+			    int n_key_data, krb5_key_data *key_data,
+			    krb5_keyblock **keyblocks, int *n_keys);
+
+static krb5_error_code 
+kadm5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc)
+{
+    register krb5_principal tempprinc;
+    register int i, nelems;
+                                                                                                                            
+    tempprinc = (krb5_principal)krb5_db_alloc(context, NULL, sizeof(krb5_principal_data));
+                                                                                                                            
+    if (tempprinc == 0)
+        return ENOMEM;
+                                                                                                                            
+    memcpy(tempprinc, inprinc, sizeof(krb5_principal_data));
+                                                                                                                            
+    nelems = (int) krb5_princ_size(context, inprinc);
+    tempprinc->data = krb5_db_alloc(context, NULL, nelems * sizeof(krb5_data));
+                                                                                                                            
+    if (tempprinc->data == 0) {
+	krb5_db_free(context, (char *)tempprinc);
+        return ENOMEM;
+    }
+                                                                                                                            
+    for (i = 0; i < nelems; i++) {
+        unsigned int len = krb5_princ_component(context, inprinc, i)->length;
+        krb5_princ_component(context, tempprinc, i)->length = len;
+        if (((krb5_princ_component(context, tempprinc, i)->data =
+              krb5_db_alloc(context, NULL, len)) == 0) && len) {
+            while (--i >= 0)
+                krb5_db_free(context, krb5_princ_component(context, tempprinc, i)->data);
+            krb5_db_free (context, tempprinc->data);
+            krb5_db_free (context, tempprinc);
+            return ENOMEM;
+        }
+        if (len)
+            memcpy(krb5_princ_component(context, tempprinc, i)->data,
+                   krb5_princ_component(context, inprinc, i)->data, len);
+    }
+                                                                                                                            
+    tempprinc->realm.data =
+	krb5_db_alloc(context, NULL, tempprinc->realm.length = inprinc->realm.length);
+    if (!tempprinc->realm.data && tempprinc->realm.length) {
+            for (i = 0; i < nelems; i++)
+		krb5_db_free(context, krb5_princ_component(context, tempprinc, i)->data);
+            krb5_db_free(context, tempprinc->data);
+            krb5_db_free(context, tempprinc);
+            return ENOMEM;
+    }
+    if (tempprinc->realm.length)
+        memcpy(tempprinc->realm.data, inprinc->realm.data,
+               inprinc->realm.length);
+                                                                                                                            
+    *outprinc = tempprinc;
+    return 0;
+}
+                                                                                                                            
+static void
+kadm5_free_principal(krb5_context context, krb5_principal val)
+{
+    register krb5_int32 i;
+                                                                                                                            
+    if (!val)
+        return;
+                                                                                                                            
+    if (val->data) {
+        i = krb5_princ_size(context, val);
+        while(--i >= 0)
+            krb5_db_free(context, krb5_princ_component(context, val, i)->data);
+        krb5_db_free(context, val->data);
+    }
+    if (val->realm.data)
+        krb5_db_free(context, val->realm.data);
+    krb5_db_free(context, val);
+}
+
+/*
+ * XXX Functions that ought to be in libkrb5.a, but aren't.
+ */
+kadm5_ret_t krb5_copy_key_data_contents(context, from, to)
+   krb5_context context;
+   krb5_key_data *from, *to;
+{
+     int i, idx;
+     
+     *to = *from;
+
+     idx = (from->key_data_ver == 1 ? 1 : 2);
+
+     for (i = 0; i < idx; i++) {
+       if ( from->key_data_length[i] ) {
+	 to->key_data_contents[i] = malloc(from->key_data_length[i]);
+	 if (to->key_data_contents[i] == NULL) {
+	   for (i = 0; i < idx; i++) {
+	     if (to->key_data_contents[i]) {
+	       memset(to->key_data_contents[i], 0,
+		      to->key_data_length[i]);
+	       free(to->key_data_contents[i]);
+	     }
+	   }
+	   return ENOMEM;
+	 }
+	 memcpy(to->key_data_contents[i], from->key_data_contents[i],
+		from->key_data_length[i]);
+       }
+     }
+     return 0;
+}
+
+static krb5_tl_data *dup_tl_data(krb5_tl_data *tl)
+{
+     krb5_tl_data *n;
+
+     n = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
+     if (n == NULL)
+	  return NULL;
+     n->tl_data_contents = malloc(tl->tl_data_length);
+     if (n->tl_data_contents == NULL) {
+	  free(n);
+	  return NULL;
+     }
+     memcpy(n->tl_data_contents, tl->tl_data_contents, tl->tl_data_length);
+     n->tl_data_type = tl->tl_data_type;
+     n->tl_data_length = tl->tl_data_length;
+     n->tl_data_next = NULL;
+     return n;
+}
+
+/* This is in lib/kdb/kdb_cpw.c, but is static */
+static void cleanup_key_data(context, count, data)
+   krb5_context	  context;
+   int			  count;
+   krb5_key_data	* data;
+{
+     int i, j;
+     
+     for (i = 0; i < count; i++)
+	  for (j = 0; j < data[i].key_data_ver; j++)
+	       if (data[i].key_data_length[j])
+		   krb5_db_free(context, data[i].key_data_contents[j]);
+     krb5_db_free(context, data);
+}
+
+kadm5_ret_t
+kadm5_create_principal(void *server_handle,
+			    kadm5_principal_ent_t entry, long mask,
+			    char *password)
+{
+    return
+	kadm5_create_principal_3(server_handle, entry, mask,
+				 0, NULL, password);
+}
+kadm5_ret_t
+kadm5_create_principal_3(void *server_handle,
+			 kadm5_principal_ent_t entry, long mask,
+			 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
+			 char *password)
+{
+    krb5_db_entry		kdb;
+    osa_princ_ent_rec		adb;
+    kadm5_policy_ent_rec	polent;
+    krb5_int32			now;
+    krb5_tl_data		*tl_data_orig, *tl_data_tail;
+    unsigned int		ret;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    /*
+     * Argument sanity checking, and opening up the DB
+     */
+    if(!(mask & KADM5_PRINCIPAL) || (mask & KADM5_MOD_NAME) ||
+       (mask & KADM5_MOD_TIME) || (mask & KADM5_LAST_PWD_CHANGE) ||
+       (mask & KADM5_MKVNO) || (mask & KADM5_POLICY_CLR) ||
+       (mask & KADM5_AUX_ATTRIBUTES) || (mask & KADM5_KEY_DATA) ||
+       (mask & KADM5_LAST_SUCCESS) || (mask & KADM5_LAST_FAILED) ||
+       (mask & KADM5_FAIL_AUTH_COUNT))
+	return KADM5_BAD_MASK;
+    if((mask & ~ALL_PRINC_MASK))
+	return KADM5_BAD_MASK;
+    if (entry == (kadm5_principal_ent_t) NULL || password == NULL)
+	return EINVAL;
+
+    /*
+     * Check to see if the principal exists
+     */
+    ret = kdb_get_entry(handle, entry->principal, &kdb, &adb);
+
+    switch(ret) {
+    case KADM5_UNK_PRINC:
+	break;
+    case 0:
+	kdb_free_entry(handle, &kdb, &adb);
+	return KADM5_DUP;
+    default:
+	return ret;
+    }
+
+    memset(&kdb, 0, sizeof(krb5_db_entry));
+    memset(&adb, 0, sizeof(osa_princ_ent_rec));
+
+    /*
+     * If a policy was specified, load it.
+     * If we can not find the one specified return an error
+     */
+    if ((mask & KADM5_POLICY)) {
+	 if ((ret = kadm5_get_policy(handle->lhandle, entry->policy,
+				     &polent)) != KADM5_OK) {
+	    if(ret == EINVAL) 
+		return KADM5_BAD_POLICY;
+	    else
+		return ret;
+	}
+    }
+    if ((ret = passwd_check(handle, password, (mask & KADM5_POLICY),
+			    &polent, entry->principal))) {
+	if (mask & KADM5_POLICY)
+	     (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+	return ret;
+    }
+    /*
+     * Start populating the various DB fields, using the
+     * "defaults" for fields that were not specified by the
+     * mask.
+     */
+    if ((ret = krb5_timeofday(handle->context, &now))) {
+	 if (mask & KADM5_POLICY)
+	      (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+	 return ret;
+    }
+
+    kdb.magic = KRB5_KDB_MAGIC_NUMBER;
+    kdb.len = KRB5_KDB_V1_BASE_LENGTH; /* gag me with a chainsaw */
+
+    if ((mask & KADM5_ATTRIBUTES)) 
+	kdb.attributes = entry->attributes;
+    else
+       kdb.attributes = handle->params.flags;
+
+    if ((mask & KADM5_MAX_LIFE))
+	kdb.max_life = entry->max_life; 
+    else 
+	kdb.max_life = handle->params.max_life;
+
+    if (mask & KADM5_MAX_RLIFE)
+	 kdb.max_renewable_life = entry->max_renewable_life;
+    else
+	 kdb.max_renewable_life = handle->params.max_rlife;
+
+    if ((mask & KADM5_PRINC_EXPIRE_TIME))
+	kdb.expiration = entry->princ_expire_time;
+    else
+	kdb.expiration = handle->params.expiration;
+
+    kdb.pw_expiration = 0;
+    if ((mask & KADM5_POLICY)) {
+	if(polent.pw_max_life)
+	    kdb.pw_expiration = now + polent.pw_max_life;
+	else
+	    kdb.pw_expiration = 0;
+    }
+    if ((mask & KADM5_PW_EXPIRATION))
+	 kdb.pw_expiration = entry->pw_expiration;
+    
+    kdb.last_success = 0;
+    kdb.last_failed = 0;
+    kdb.fail_auth_count = 0;
+
+    /* this is kind of gross, but in order to free the tl data, I need
+       to free the entire kdb entry, and that will try to free the
+       principal. */
+
+    if ((ret = kadm5_copy_principal(handle->context,
+				    entry->principal, &(kdb.princ)))) {
+	if (mask & KADM5_POLICY)
+	     (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+	return(ret);
+    }
+
+    if ((ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now))) {
+         krb5_db_free_principal(handle->context, &kdb, 1);
+	 if (mask & KADM5_POLICY)
+	     (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+	 return(ret);
+    }
+
+    if (mask & KADM5_TL_DATA) {
+	/* splice entry->tl_data onto the front of kdb.tl_data */
+	tl_data_orig = kdb.tl_data;
+	for (tl_data_tail = entry->tl_data; tl_data_tail;
+	     tl_data_tail = tl_data_tail->tl_data_next)
+	{
+	    ret = krb5_dbe_update_tl_data(handle->context, &kdb, tl_data_tail);
+	    if( ret )
+	    {
+		krb5_db_free_principal(handle->context, &kdb, 1);
+		if (mask & KADM5_POLICY)
+		    (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+		return ret;
+	    }
+	}
+    }
+
+    /* initialize the keys */
+
+    if ((ret = krb5_dbe_cpw(handle->context, &master_keyblock,
+			    n_ks_tuple?ks_tuple:handle->params.keysalts,
+			    n_ks_tuple?n_ks_tuple:handle->params.num_keysalts,
+			    password,
+			    (mask & KADM5_KVNO)?entry->kvno:1,
+			    FALSE, &kdb))) {
+	krb5_db_free_principal(handle->context, &kdb, 1);
+	if (mask & KADM5_POLICY)
+	     (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+	return(ret);
+    }
+
+    /* populate the admin-server-specific fields.  In the OV server,
+       this used to be in a separate database.  Since there's already
+       marshalling code for the admin fields, to keep things simple,
+       I'm going to keep it, and make all the admin stuff occupy a
+       single tl_data record, */
+
+    adb.admin_history_kvno = hist_kvno;
+    if ((mask & KADM5_POLICY)) {
+	adb.aux_attributes = KADM5_POLICY;
+
+	/* this does *not* need to be strdup'ed, because adb is xdr */
+	/* encoded in osa_adb_create_princ, and not ever freed */
+
+	adb.policy = entry->policy;
+    }
+
+    /* increment the policy ref count, if any */
+
+    if ((mask & KADM5_POLICY)) {
+	polent.policy_refcnt++;
+	if ((ret = kadm5_modify_policy_internal(handle->lhandle, &polent,
+						    KADM5_REF_COUNT))
+	    != KADM5_OK) {
+	    krb5_db_free_principal(handle->context, &kdb, 1);
+	    if (mask & KADM5_POLICY)
+		 (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+	    return(ret);
+	}
+    }
+
+    /* In all cases key and the principal data is set, let the database provider know */
+    kdb.mask = mask | KADM5_KEY_DATA | KADM5_PRINCIPAL ;
+
+    /* store the new db entry */
+    ret = kdb_put_entry(handle, &kdb, &adb);
+
+    krb5_db_free_principal(handle->context, &kdb, 1);
+
+    if (ret) {
+	if ((mask & KADM5_POLICY)) {
+	    /* decrement the policy ref count */
+
+	    polent.policy_refcnt--;
+	    /*
+	     * if this fails, there's nothing we can do anyway.  the
+	     * policy refcount wil be too high.
+	     */
+	    (void) kadm5_modify_policy_internal(handle->lhandle, &polent,
+						     KADM5_REF_COUNT);
+	}
+
+	if (mask & KADM5_POLICY)
+	     (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+	return(ret);
+    }
+
+    if (mask & KADM5_POLICY)
+	 (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+
+    return KADM5_OK;
+}
+
+	
+kadm5_ret_t
+kadm5_delete_principal(void *server_handle, krb5_principal principal)
+{
+    unsigned int		ret;
+    kadm5_policy_ent_rec	polent;
+    krb5_db_entry		kdb;
+    osa_princ_ent_rec		adb;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if (principal == NULL)
+	return EINVAL;
+
+    if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+	return(ret);
+
+    if ((adb.aux_attributes & KADM5_POLICY)) {
+	if ((ret = kadm5_get_policy(handle->lhandle,
+				    adb.policy, &polent))
+	    == KADM5_OK) {
+	    polent.policy_refcnt--;
+	    if ((ret = kadm5_modify_policy_internal(handle->lhandle, &polent,
+							 KADM5_REF_COUNT))
+		!= KADM5_OK) {
+		(void) kadm5_free_policy_ent(handle->lhandle, &polent);
+		kdb_free_entry(handle, &kdb, &adb);
+		return(ret);
+	    }
+	}
+	if ((ret = kadm5_free_policy_ent(handle->lhandle, &polent))) {
+	     kdb_free_entry(handle, &kdb, &adb);
+	     return ret;
+	}
+    }
+
+    ret = kdb_delete_entry(handle, principal);
+
+    kdb_free_entry(handle, &kdb, &adb);
+
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_modify_principal(void *server_handle,
+			    kadm5_principal_ent_t entry, long mask)
+{
+    int			    ret, ret2, i;
+    kadm5_policy_ent_rec    npol, opol;
+    int			    have_npol = 0, have_opol = 0;
+    krb5_db_entry	    kdb;
+    krb5_tl_data	    *tl_data_orig;
+    osa_princ_ent_rec	    adb;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if((mask & KADM5_PRINCIPAL) || (mask & KADM5_LAST_PWD_CHANGE) ||
+       (mask & KADM5_MOD_TIME) || (mask & KADM5_MOD_NAME) ||
+       (mask & KADM5_MKVNO) || (mask & KADM5_AUX_ATTRIBUTES) ||
+       (mask & KADM5_KEY_DATA) || (mask & KADM5_LAST_SUCCESS) ||
+       (mask & KADM5_LAST_FAILED))
+	return KADM5_BAD_MASK;
+    if((mask & ~ALL_PRINC_MASK))
+	return KADM5_BAD_MASK;
+    if((mask & KADM5_POLICY) && (mask & KADM5_POLICY_CLR))
+	return KADM5_BAD_MASK;
+    if(entry == (kadm5_principal_ent_t) NULL)
+	return EINVAL;
+    if (mask & KADM5_TL_DATA) {
+	 tl_data_orig = entry->tl_data;
+	 while (tl_data_orig) {
+	      if (tl_data_orig->tl_data_type < 256)
+		   return KADM5_BAD_TL_TYPE;
+	      tl_data_orig = tl_data_orig->tl_data_next;
+	 }
+    }
+
+    ret = kdb_get_entry(handle, entry->principal, &kdb, &adb);
+    if (ret)
+	return(ret);
+
+    /*
+     * This is pretty much the same as create ...
+     */
+
+    if ((mask & KADM5_POLICY)) {
+	 /* get the new policy */
+	 ret = kadm5_get_policy(handle->lhandle, entry->policy, &npol);
+	 if (ret) {
+	      switch (ret) {
+	      case EINVAL:
+		   ret = KADM5_BAD_POLICY;
+		   break;
+	      case KADM5_UNK_POLICY:
+	      case KADM5_BAD_POLICY:
+		   ret =  KADM5_UNK_POLICY;
+		   break;
+	      }
+	      goto done;
+	 }
+	 have_npol = 1;
+
+	 /* if we already have a policy, get it to decrement the refcnt */
+	 if(adb.aux_attributes & KADM5_POLICY) {
+	      /* ... but not if the old and new are the same */
+	      if(strcmp(adb.policy, entry->policy)) {
+		   ret = kadm5_get_policy(handle->lhandle,
+					  adb.policy, &opol);
+		   switch(ret) {
+		   case EINVAL:
+		   case KADM5_BAD_POLICY:
+		   case KADM5_UNK_POLICY:
+			break;
+		   case KADM5_OK:
+			have_opol = 1;
+			opol.policy_refcnt--;
+			break;
+		   default:
+			goto done;
+			break;
+		   }
+		   npol.policy_refcnt++;
+	      }
+	 } else npol.policy_refcnt++;
+
+	 /* set us up to use the new policy */
+	 adb.aux_attributes |= KADM5_POLICY;
+	 if (adb.policy)
+	      free(adb.policy);
+	 adb.policy = strdup(entry->policy);
+
+	 /* set pw_max_life based on new policy */
+	 if (npol.pw_max_life) {
+	     ret = krb5_dbe_lookup_last_pwd_change(handle->context, &kdb,
+						   &(kdb.pw_expiration));
+	     if (ret)
+		 goto done;
+	     kdb.pw_expiration += npol.pw_max_life;
+	 } else {
+	     kdb.pw_expiration = 0;
+	 }
+    }
+
+    if ((mask & KADM5_POLICY_CLR) &&
+	(adb.aux_attributes & KADM5_POLICY)) {
+	 ret = kadm5_get_policy(handle->lhandle, adb.policy, &opol);
+	 switch(ret) {
+	 case EINVAL:
+	 case KADM5_BAD_POLICY:
+	 case KADM5_UNK_POLICY:
+	      ret = KADM5_BAD_DB;
+	      goto done;
+	      break;
+	 case KADM5_OK:
+	      have_opol = 1;
+	      if (adb.policy)
+		   free(adb.policy);
+	      adb.policy = NULL;
+	      adb.aux_attributes &= ~KADM5_POLICY;
+	      kdb.pw_expiration = 0;
+	      opol.policy_refcnt--;
+	      break;
+	 default:
+	      goto done;
+	      break;
+	 }
+    }
+
+    if (((mask & KADM5_POLICY) || (mask & KADM5_POLICY_CLR)) &&
+	(((have_opol) &&
+	  (ret =
+	   kadm5_modify_policy_internal(handle->lhandle, &opol,
+					     KADM5_REF_COUNT))) ||
+	 ((have_npol) &&
+	  (ret =
+	   kadm5_modify_policy_internal(handle->lhandle, &npol,
+					     KADM5_REF_COUNT)))))
+	goto done;
+
+    if ((mask & KADM5_ATTRIBUTES)) 
+	kdb.attributes = entry->attributes;
+    if ((mask & KADM5_MAX_LIFE))
+	kdb.max_life = entry->max_life;
+    if ((mask & KADM5_PRINC_EXPIRE_TIME))
+	kdb.expiration = entry->princ_expire_time;
+    if (mask & KADM5_PW_EXPIRATION)
+	 kdb.pw_expiration = entry->pw_expiration;
+    if (mask & KADM5_MAX_RLIFE)
+	 kdb.max_renewable_life = entry->max_renewable_life;
+    if (mask & KADM5_FAIL_AUTH_COUNT)
+	 kdb.fail_auth_count = entry->fail_auth_count;
+    
+    if((mask & KADM5_KVNO)) {
+	 for (i = 0; i < kdb.n_key_data; i++)
+	      kdb.key_data[i].key_data_kvno = entry->kvno;
+    }
+
+    if (mask & KADM5_TL_DATA) {
+	 krb5_tl_data *tl;
+
+	 /* may have to change the version number of the API. Updates the list with the given tl_data rather than over-writting */
+
+	 for (tl = entry->tl_data; tl;
+	      tl = tl->tl_data_next)
+	 {
+	     ret = krb5_dbe_update_tl_data(handle->context, &kdb, tl);
+	     if( ret )
+	     {
+		 goto done;
+	     }
+	 }
+    }
+
+    /* let the mask propagate to the database provider */
+    kdb.mask = mask;
+
+    ret = kdb_put_entry(handle, &kdb, &adb);
+    if (ret) goto done;
+
+    ret = KADM5_OK;
+done:
+    if (have_opol) {
+	 ret2 = kadm5_free_policy_ent(handle->lhandle, &opol);
+	 ret = ret ? ret : ret2;
+    }
+    if (have_npol) {
+	 ret2 = kadm5_free_policy_ent(handle->lhandle, &npol);
+	 ret = ret ? ret : ret2;
+    }
+    kdb_free_entry(handle, &kdb, &adb);
+    return ret;
+}
+    
+kadm5_ret_t
+kadm5_rename_principal(void *server_handle,
+			    krb5_principal source, krb5_principal target)
+{
+    krb5_db_entry	kdb;
+    osa_princ_ent_rec	adb;
+    int			ret, i;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if (source == NULL || target == NULL)
+	return EINVAL;
+
+    if ((ret = kdb_get_entry(handle, target, &kdb, &adb)) == 0) {
+	kdb_free_entry(handle, &kdb, &adb);
+	return(KADM5_DUP);
+    }
+
+    if ((ret = kdb_get_entry(handle, source, &kdb, &adb)))
+	return ret;
+
+    /* this is kinda gross, but unavoidable */
+
+    for (i=0; i<kdb.n_key_data; i++) {
+	if ((kdb.key_data[i].key_data_ver == 1) ||
+	    (kdb.key_data[i].key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)) {
+	    ret = KADM5_NO_RENAME_SALT;
+	    goto done;
+	}
+    }
+
+    kadm5_free_principal(handle->context, kdb.princ);
+    ret = kadm5_copy_principal(handle->context, target, &kdb.princ);
+    if (ret) {
+	kdb.princ = NULL; /* so freeing the dbe doesn't lose */
+	goto done;
+    }
+
+    if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+	goto done;
+
+    ret = kdb_delete_entry(handle, source);
+
+done:
+    kdb_free_entry(handle, &kdb, &adb);
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_get_principal(void *server_handle, krb5_principal principal,
+		    kadm5_principal_ent_t entry,
+		    long in_mask)
+{
+    krb5_db_entry		kdb;
+    osa_princ_ent_rec		adb;
+    krb5_error_code		ret = 0;
+    long			mask;
+    int i;
+    kadm5_server_handle_t handle = server_handle;
+    kadm5_principal_ent_rec	entry_local, *entry_orig;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    /*
+     * In version 1, all the defined fields are always returned.
+     * entry is a pointer to a kadm5_principal_ent_t_v1 that should be
+     * filled with allocated memory.
+     */
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 mask = KADM5_PRINCIPAL_NORMAL_MASK;
+	 entry_orig = entry;
+	 entry = &entry_local;
+    } else {
+	 mask = in_mask;
+    }
+
+    memset((char *) entry, 0, sizeof(*entry));
+
+    if (principal == NULL)
+	return EINVAL;
+
+    if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+	return ret;
+
+    if ((mask & KADM5_POLICY) &&
+	adb.policy && (adb.aux_attributes & KADM5_POLICY)) {
+	if ((entry->policy = (char *) malloc(strlen(adb.policy) + 1)) == NULL) {
+	    ret = ENOMEM;
+	    goto done;
+	}
+	strcpy(entry->policy, adb.policy);
+    }
+
+    if (mask & KADM5_AUX_ATTRIBUTES)
+	 entry->aux_attributes = adb.aux_attributes;
+
+    if ((mask & KADM5_PRINCIPAL) &&
+	(ret = krb5_copy_principal(handle->context, principal,
+				   &entry->principal))) { 
+	goto done;
+    }
+
+    if (mask & KADM5_PRINC_EXPIRE_TIME)
+	 entry->princ_expire_time = kdb.expiration;
+
+    if ((mask & KADM5_LAST_PWD_CHANGE) &&
+	(ret = krb5_dbe_lookup_last_pwd_change(handle->context, &kdb,
+					       &(entry->last_pwd_change)))) {
+	goto done;
+    }
+
+    if (mask & KADM5_PW_EXPIRATION)
+	 entry->pw_expiration = kdb.pw_expiration;
+    if (mask & KADM5_MAX_LIFE)
+	 entry->max_life = kdb.max_life;
+
+    /* this is a little non-sensical because the function returns two */
+    /* values that must be checked separately against the mask */
+    if ((mask & KADM5_MOD_NAME) || (mask & KADM5_MOD_TIME)) {
+	ret = krb5_dbe_lookup_mod_princ_data(handle->context, &kdb,
+					     &(entry->mod_date), 
+					     &(entry->mod_name));
+	if (ret) {
+	    goto done;
+	}
+	
+	if (! (mask & KADM5_MOD_TIME))
+	    entry->mod_date = 0;
+	if (! (mask & KADM5_MOD_NAME)) {
+	    krb5_free_principal(handle->context, entry->principal);
+	    entry->principal = NULL;
+	}
+    }
+
+    if (mask & KADM5_ATTRIBUTES)
+	 entry->attributes = kdb.attributes;
+
+    if (mask & KADM5_KVNO)
+	 for (entry->kvno = 0, i=0; i<kdb.n_key_data; i++)
+	      if (kdb.key_data[i].key_data_kvno > entry->kvno)
+		   entry->kvno = kdb.key_data[i].key_data_kvno;
+    
+    if (handle->api_version == KADM5_API_VERSION_2)
+	 entry->mkvno = 0;
+    else {
+	 /* XXX I'll be damned if I know how to deal with this one --marc */
+	 entry->mkvno = 1;
+    }
+
+    /*
+     * The new fields that only exist in version 2 start here
+     */
+    if (handle->api_version == KADM5_API_VERSION_2) {
+	 if (mask & KADM5_MAX_RLIFE)
+	      entry->max_renewable_life = kdb.max_renewable_life;
+	 if (mask & KADM5_LAST_SUCCESS)
+	      entry->last_success = kdb.last_success;
+	 if (mask & KADM5_LAST_FAILED)
+	      entry->last_failed = kdb.last_failed;
+	 if (mask & KADM5_FAIL_AUTH_COUNT)
+	      entry->fail_auth_count = kdb.fail_auth_count;
+	 if (mask & KADM5_TL_DATA) {
+	      krb5_tl_data *tl, *tl2;
+
+	      entry->tl_data = NULL;
+	      
+	      tl = kdb.tl_data;
+	      while (tl) {
+		   if (tl->tl_data_type > 255) {
+			if ((tl2 = dup_tl_data(tl)) == NULL) {
+			     ret = ENOMEM;
+			     goto done;
+			}
+			tl2->tl_data_next = entry->tl_data;
+			entry->tl_data = tl2;
+			entry->n_tl_data++;
+		   }
+			
+		   tl = tl->tl_data_next;
+	      }
+	 }
+	 if (mask & KADM5_KEY_DATA) {
+	      entry->n_key_data = kdb.n_key_data;
+	      if(entry->n_key_data) {
+		      entry->key_data = (krb5_key_data *)
+			      malloc(entry->n_key_data*sizeof(krb5_key_data));
+		      if (entry->key_data == NULL) {
+			      ret = ENOMEM;
+			      goto done;
+		      }
+	      } else 
+		      entry->key_data = NULL;
+
+	      for (i = 0; i < entry->n_key_data; i++)
+		  ret = krb5_copy_key_data_contents(handle->context,
+						    &kdb.key_data[i],
+						    &entry->key_data[i]);
+		   if (ret)
+			goto done;
+	 }
+    }
+
+    /*
+     * If KADM5_API_VERSION_1, we return an allocated structure, and
+     * we need to convert the new structure back into the format the
+     * caller is expecting.
+     */
+    if (handle->api_version == KADM5_API_VERSION_1) {
+	 kadm5_principal_ent_t_v1 newv1;
+
+	 newv1 = ((kadm5_principal_ent_t_v1) calloc(1, sizeof(*newv1)));
+	 if (newv1 == NULL) {
+	      ret = ENOMEM;
+	      goto done;
+	 }
+	 
+	 newv1->principal = entry->principal;
+	 newv1->princ_expire_time = entry->princ_expire_time;
+	 newv1->last_pwd_change = entry->last_pwd_change;
+	 newv1->pw_expiration = entry->pw_expiration;
+	 newv1->max_life = entry->max_life;
+	 newv1->mod_name = entry->mod_name;
+	 newv1->mod_date = entry->mod_date;
+	 newv1->attributes = entry->attributes;
+	 newv1->kvno = entry->kvno;
+	 newv1->mkvno = entry->mkvno;
+	 newv1->policy = entry->policy;
+	 newv1->aux_attributes = entry->aux_attributes;
+
+	 *((kadm5_principal_ent_t_v1 *) entry_orig) = newv1;
+    }
+
+    ret = KADM5_OK;
+
+done:
+    if (ret && entry->principal)
+	 krb5_free_principal(handle->context, entry->principal);
+    kdb_free_entry(handle, &kdb, &adb);
+
+    return ret;
+}
+
+/*
+ * Function: check_pw_reuse
+ *
+ * Purpose: Check if a key appears in a list of keys, in order to
+ * enforce password history.
+ *
+ * Arguments:
+ *
+ *	context			(r) the krb5 context
+ *	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 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_keyblock
+ * 	for each password in pw_hist_data:
+ *		for each hist_key in password:
+ *			decrypt hist_key with hist_keyblock
+ *			compare the new_key and hist_key
+ *
+ * Returns krb5 errors, KADM5_PASS_RESUSE if a key in
+ * new_key_data is the same as a key in pw_hist_data, or 0.
+ */
+static kadm5_ret_t
+check_pw_reuse(krb5_context context,
+	       krb5_keyblock *hist_keyblock,
+	       int n_new_key_data, krb5_key_data *new_key_data,
+	       unsigned int n_pw_hist_data, osa_pw_hist_ent *pw_hist_data)
+{
+    int x, y, z;
+    krb5_keyblock newkey, histkey;
+    krb5_error_code ret;
+
+    for (x = 0; x < n_new_key_data; x++) {
+	ret = krb5_dbekd_decrypt_key_data(context,
+					  &master_keyblock,
+					  &(new_key_data[x]),
+					  &newkey, NULL);
+	if (ret)
+	    return(ret);
+	for (y = 0; y < n_pw_hist_data; y++) {
+	     for (z = 0; z < pw_hist_data[y].n_key_data; z++) {
+		 ret = krb5_dbekd_decrypt_key_data(context,
+						   hist_keyblock,
+						   &pw_hist_data[y].key_data[z],
+						   &histkey, NULL);
+		 if (ret)
+		     return(ret);		
+		 
+		 if ((newkey.length == histkey.length) &&
+		     (newkey.enctype == histkey.enctype) &&
+		     (memcmp(newkey.contents, histkey.contents,
+			     histkey.length) == 0)) {
+		     krb5_free_keyblock_contents(context, &histkey);
+		     krb5_free_keyblock_contents(context, &newkey);
+		     
+		     return(KADM5_PASS_REUSE);
+		 }
+		 krb5_free_keyblock_contents(context, &histkey);
+	     }
+	}
+	krb5_free_keyblock_contents(context, &newkey);
+    }
+
+    return(0);
+}
+
+/*
+ * Function: create_history_entry
+ *
+ * Purpose: Creates a password history entry from an array of
+ * key_data.
+ *
+ * Arguments:
+ *
+ *	context		(r) krb5_context to use
+ *	n_key_data	(r) number of elements in key_data
+ *	key_data	(r) keys to add to the history entry
+ *	hist		(w) history entry to fill in
+ *
+ * Effects:
+ *
+ * hist->key_data is allocated to store n_key_data key_datas.  Each
+ * 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.
+ */
+static
+int create_history_entry(krb5_context context, int n_key_data,
+			 krb5_key_data *key_data, osa_pw_hist_ent *hist)
+{
+     int i, ret;
+     krb5_keyblock key;
+     krb5_keysalt salt;
+     
+     hist->key_data = (krb5_key_data*)malloc(n_key_data*sizeof(krb5_key_data));
+     if (hist->key_data == NULL)
+	  return ENOMEM;
+     memset(hist->key_data, 0, n_key_data*sizeof(krb5_key_data));
+
+     for (i = 0; i < n_key_data; i++) {
+	 ret = krb5_dbekd_decrypt_key_data(context,
+					   &master_keyblock,
+					   &key_data[i],
+					   &key, &salt);
+	 if (ret)
+	     return ret;
+
+	 ret = krb5_dbekd_encrypt_key_data(context, &hist_key,
+					   &key, &salt,
+					   key_data[i].key_data_kvno,
+					   &hist->key_data[i]);
+	 if (ret)
+	     return ret;
+	 
+	 krb5_free_keyblock_contents(context, &key);
+	 /* krb5_free_keysalt(context, &salt); */
+     }
+
+     hist->n_key_data = n_key_data;
+     return 0;
+}
+
+static
+void free_history_entry(krb5_context context, osa_pw_hist_ent *hist)
+{
+     int i;
+
+     for (i = 0; i < hist->n_key_data; i++)
+	  krb5_free_key_data_contents(context, &hist->key_data[i]);
+     free(hist->key_data);
+}
+
+/*
+ * Function: add_to_history
+ *
+ * Purpose: Adds a password to a principal's password history.
+ *
+ * Arguments:
+ *
+ *	context		(r) krb5_context to use
+ *	adb		(r/w) admin principal entry to add keys to
+ *	pol		(r) adb's policy
+ *	pw		(r) keys for the password to add to adb's key history
+ *
+ * Effects:
+ *
+ * add_to_history adds a single password to adb's password history.
+ * pw contains n_key_data keys in its key_data, in storage should be
+ * allocated but not freed by the caller (XXX blech!).
+ *
+ * This function maintains adb->old_keys as a circular queue.  It
+ * starts empty, and grows each time this function is called until it
+ * is pol->pw_history_num items long.  adb->old_key_len holds the
+ * number of allocated entries in the array, and must therefore be [0,
+ * pol->pw_history_num).  adb->old_key_next is the index into the
+ * array where the next element should be written, and must be [0,
+ * adb->old_key_len).
+ */
+static kadm5_ret_t add_to_history(krb5_context context,
+				  osa_princ_ent_t adb,
+				  kadm5_policy_ent_t pol,
+				  osa_pw_hist_ent *pw)
+{
+     osa_pw_hist_ent *histp;
+     uint32_t nhist;
+     unsigned int i, knext, nkeys;
+
+     nhist = pol->pw_history_num;
+     /* A history of 1 means just check the current password */
+     if (nhist <= 1)
+	  return 0;
+
+     nkeys = adb->old_key_len;
+     knext = adb->old_key_next;
+     /* resize the adb->old_keys array if necessary */
+     if (nkeys + 1 < nhist) {
+	  if (adb->old_keys == NULL) {
+	       adb->old_keys = (osa_pw_hist_ent *)
+		    malloc((nkeys + 1) * sizeof (osa_pw_hist_ent));
+	  } else {
+	       adb->old_keys = (osa_pw_hist_ent *)
+		    realloc(adb->old_keys,
+			    (nkeys + 1) * sizeof (osa_pw_hist_ent));
+	  }
+	  if (adb->old_keys == NULL)
+	       return(ENOMEM);
+	  
+	  memset(&adb->old_keys[nkeys], 0, sizeof(osa_pw_hist_ent));
+     	  nkeys = ++adb->old_key_len;
+	  /*
+	   * To avoid losing old keys, shift forward each entry after
+	   * knext.
+	   */
+	  for (i = nkeys - 1; i > knext; i--) {
+	      adb->old_keys[i] = adb->old_keys[i - 1];
+	  }
+	  memset(&adb->old_keys[knext], 0, sizeof(osa_pw_hist_ent));
+     } else if (nkeys + 1 > nhist) {
+	 /*
+	  * The policy must have changed!  Shrink the array.
+	  * Can't simply realloc() down, since it might be wrapped.
+	  * To understand the arithmetic below, note that we are
+	  * copying into new positions 0 .. N-1 from old positions
+	  * old_key_next-N .. old_key_next-1, modulo old_key_len,
+	  * where N = pw_history_num - 1 is the length of the
+	  * shortened list.        Matt Crawford, FNAL
+	  */
+	 /*
+	  * M = adb->old_key_len, N = pol->pw_history_num - 1
+	  *
+	  * tmp[0] .. tmp[N-1] = old[(knext-N)%M] .. old[(knext-1)%M]
+	  */
+	 int j;
+	 osa_pw_hist_t tmp;
+
+	 tmp = (osa_pw_hist_ent *)
+	     malloc((nhist - 1) * sizeof (osa_pw_hist_ent));
+	 if (tmp == NULL)
+	     return ENOMEM;
+	 for (i = 0; i < nhist - 1; i++) {
+	     /*
+	      * Add nkeys once before taking remainder to avoid
+	      * negative values.
+	      */
+	     j = (i + nkeys + knext - (nhist - 1)) % nkeys;
+	     tmp[i] = adb->old_keys[j];
+	 }
+	 /* Now free the ones we don't keep (the oldest ones) */
+	 for (i = 0; i < nkeys - (nhist - 1); i++) {
+	     j = (i + nkeys + knext) % nkeys;
+	     histp = &adb->old_keys[j];
+	     for (j = 0; j < histp->n_key_data; j++) {
+		 krb5_free_key_data_contents(context, &histp->key_data[j]);
+	     }
+	     free(histp->key_data);
+	 }
+	 free((void *)adb->old_keys);
+	 adb->old_keys = tmp;
+	 nkeys = adb->old_key_len = nhist - 1;
+	 knext = adb->old_key_next = 0;
+     }
+
+     /*
+      * If nhist decreased since the last password change, and nkeys+1
+      * is less than the previous nhist, it is possible for knext to
+      * index into unallocated space.  This condition would not be
+      * caught by the resizing code above.
+      */
+     if (knext + 1 > nkeys)
+	 knext = adb->old_key_next = 0;
+     /* free the old pw history entry if it contains data */
+     histp = &adb->old_keys[knext];
+     for (i = 0; i < histp->n_key_data; i++)
+	  krb5_free_key_data_contents(context, &histp->key_data[i]);
+     free(histp->key_data);
+
+     /* store the new entry */
+     adb->old_keys[knext] = *pw;
+
+     /* update the next pointer */
+     if (++adb->old_key_next == nhist - 1)
+	 adb->old_key_next = 0;
+
+     return(0);
+}
+
+/* FIXME: don't use global variable for this */
+krb5_boolean use_password_server = 0;
+
+static krb5_boolean
+kadm5_use_password_server (void)
+{
+    return use_password_server;
+}
+
+void
+kadm5_set_use_password_server (void)
+{
+    use_password_server = 1;
+}
+
+#ifdef USE_PASSWORD_SERVER
+
+/*
+ * kadm5_launch_task () runs a program (task_path) to synchronize the 
+ * Apple password server with the Kerberos database.  Password server
+ * programs can receive arguments on the command line (task_argv)
+ * and a block of data via stdin (data_buffer).
+ *
+ * Because a failure to communicate with the tool results in the
+ * password server falling out of sync with the database,
+ * kadm5_launch_task() always fails if it can't talk to the tool.
+ */
+
+static kadm5_ret_t
+kadm5_launch_task (krb5_context context,
+                   const char *task_path, char * const task_argv[],
+                   const char *data_buffer) 
+{
+    kadm5_ret_t ret = 0;
+    int data_pipe[2];
+    
+    if (data_buffer != NULL) {
+        ret = pipe (data_pipe);
+        if (ret) { ret = errno; }
+    }
+
+    if (!ret) {
+        pid_t pid = fork ();
+        if (pid == -1) {
+            ret = errno;
+        } else if (pid == 0) {
+            /* The child: */
+            
+            if (data_buffer != NULL) {
+                if (dup2 (data_pipe[0], STDIN_FILENO) == -1) {
+                    _exit (1);
+                }
+            } else {
+                close (data_pipe[0]);
+            }
+
+            close (data_pipe[1]);
+            
+            execv (task_path, task_argv);
+            
+            _exit (1); /* Fail if execv fails */
+        } else {
+            /* The parent: */
+            int status;
+                       
+            if (data_buffer != NULL) {
+                /* Write out the buffer to the child */
+                if (krb5_net_write (context, data_pipe[1],
+                                    data_buffer, strlen (data_buffer)) < 0) {
+                    /* kill the child to make sure waitpid() won't hang later */
+                    ret = errno;
+                    kill (pid, SIGKILL);
+                }
+            }
+
+            close (data_buffer[0]);
+            close (data_buffer[1]);
+
+            waitpid (pid, &status, 0);
+
+            if (!ret) {
+                if (WIFEXITED (status)) {
+                    /* child read password and exited.  Check the return value. */
+                    if ((WEXITSTATUS (status) != 0) && (WEXITSTATUS (status) != 252)) {
+                       ret = KRB5KDC_ERR_POLICY; /* password change rejected */
+                    }
+                } else {
+                    /* child read password but crashed or was killed */
+                    ret = KRB5KRB_ERR_GENERIC; /* FIXME: better error */
+                }
+            }
+        }
+    }
+
+    return ret;
+}
+
+#endif
+
+kadm5_ret_t
+kadm5_chpass_principal(void *server_handle,
+			    krb5_principal principal, char *password)
+{
+    return
+	kadm5_chpass_principal_3(server_handle, principal, FALSE,
+				 0, NULL, password);
+}
+
+kadm5_ret_t
+kadm5_chpass_principal_3(void *server_handle,
+			 krb5_principal principal, krb5_boolean keepold,
+			 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
+			 char *password)
+{
+    krb5_int32			now;
+    kadm5_policy_ent_rec	pol;
+    osa_princ_ent_rec		adb;
+    krb5_db_entry		kdb, kdb_save;
+    int				ret, ret2, last_pwd, hist_added;
+    int				have_pol = 0;
+    kadm5_server_handle_t	handle = server_handle;
+    osa_pw_hist_ent		hist;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    hist_added = 0;
+    memset(&hist, 0, sizeof(hist));
+
+    if (principal == NULL || password == NULL)
+	return EINVAL;
+    if ((krb5_principal_compare(handle->context,
+				principal, hist_princ)) == TRUE)
+	return KADM5_PROTECT_PRINCIPAL;
+
+    if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+       return(ret);
+
+    /* we are going to need the current keys after the new keys are set */
+    if ((ret = kdb_get_entry(handle, principal, &kdb_save, NULL))) {
+	 kdb_free_entry(handle, &kdb, &adb);
+	 return(ret);
+    }
+    
+    if ((adb.aux_attributes & KADM5_POLICY)) {
+	if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, &pol)))
+	     goto done;
+	have_pol = 1;
+    }
+
+    if ((ret = passwd_check(handle, password, adb.aux_attributes &
+			    KADM5_POLICY, &pol, principal)))
+	 goto done;
+
+    ret = krb5_dbe_cpw(handle->context, &master_keyblock,
+		       n_ks_tuple?ks_tuple:handle->params.keysalts,
+		       n_ks_tuple?n_ks_tuple:handle->params.num_keysalts,
+		       password, 0 /* increment kvno */,
+		       keepold, &kdb);
+    if (ret)
+	goto done;
+
+    kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+    ret = krb5_timeofday(handle->context, &now);
+    if (ret)
+	 goto done;
+    
+    if ((adb.aux_attributes & KADM5_POLICY)) {
+       /* the policy was loaded before */
+
+	ret = krb5_dbe_lookup_last_pwd_change(handle->context,
+					      &kdb, &last_pwd);
+	if (ret)
+	    goto done;
+
+#if 0
+	 /*
+	  * The spec says this check is overridden if the caller has
+	  * modify privilege.  The admin server therefore makes this
+	  * check itself (in chpass_principal_wrapper, misc.c). A
+	  * local caller implicitly has all authorization bits.
+	  */
+	if ((now - last_pwd) < pol.pw_min_life &&
+	    !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+	     ret = KADM5_PASS_TOOSOON;
+	     goto done;
+	}
+#endif
+
+	ret = create_history_entry(handle->context,
+				   kdb_save.n_key_data,
+				   kdb_save.key_data, &hist);
+	if (ret)
+	    goto done;
+
+	ret = check_pw_reuse(handle->context, &hist_key,
+			     kdb.n_key_data, kdb.key_data,
+			     1, &hist);
+	if (ret)
+	    goto done;
+	 
+	if (pol.pw_history_num > 1) {
+	    if (adb.admin_history_kvno != hist_kvno) {
+		ret = KADM5_BAD_HIST_KEY;
+		goto done;
+	    }
+
+	    ret = check_pw_reuse(handle->context, &hist_key,
+				 kdb.n_key_data, kdb.key_data,
+				 adb.old_key_len, adb.old_keys);
+	    if (ret)
+		goto done;
+
+	    ret = add_to_history(handle->context, &adb, &pol, &hist);
+	    if (ret)
+		goto done;
+	    hist_added = 1;
+       }
+
+	if (pol.pw_max_life)
+	   kdb.pw_expiration = now + pol.pw_max_life;
+	else
+	   kdb.pw_expiration = 0;
+    } else {
+	kdb.pw_expiration = 0;
+    }
+
+#ifdef USE_PASSWORD_SERVER
+    if (kadm5_use_password_server () &&
+        (krb5_princ_size (handle->context, principal) == 1)) {
+        krb5_data *princ = krb5_princ_component (handle->context, principal, 0);
+        const char *path = "/usr/sbin/mkpassdb";
+        char *argv[] = { "mkpassdb", "-setpassword", NULL, NULL };
+        char *pstring = NULL;
+        char pwbuf[256];
+        int pwlen = strlen (password);
+
+        if (pwlen > 254) pwlen = 254;
+        strncpy (pwbuf, password, pwlen);
+        pwbuf[pwlen] = '\n';
+        pwbuf[pwlen + 1] = '\0';
+
+        if (!ret) {
+            pstring = malloc ((princ->length + 1) * sizeof (char));
+            if (pstring == NULL) { ret = errno; }
+        }
+
+        if (!ret) {
+            memcpy (pstring, princ->data, princ->length);
+            pstring [princ->length] = '\0';
+            argv[2] = pstring;
+
+            ret = kadm5_launch_task (handle->context, path, argv, pwbuf);
+        }
+        
+        if (pstring != NULL)
+            free (pstring);
+        
+        if (ret)
+            goto done;
+    }
+#endif
+
+    ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now);
+    if (ret)
+	goto done;
+
+    /* key data and attributes changed, let the database provider know */
+    kdb.mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES /* | KADM5_CPW_FUNCTION */;
+
+    if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+	goto done;
+
+    ret = KADM5_OK;
+done:
+    if (!hist_added && hist.key_data)
+	 free_history_entry(handle->context, &hist);
+    kdb_free_entry(handle, &kdb, &adb);
+    kdb_free_entry(handle, &kdb_save, NULL);
+    krb5_db_free_principal(handle->context, &kdb, 1);
+
+    if (have_pol && (ret2 = kadm5_free_policy_ent(handle->lhandle, &pol))
+	&& !ret) 
+	 ret = ret2;
+
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_randkey_principal(void *server_handle,
+			krb5_principal principal,
+			krb5_keyblock **keyblocks,
+			int *n_keys)
+{
+    return
+	kadm5_randkey_principal_3(server_handle, principal,
+				  FALSE, 0, NULL,
+				  keyblocks, n_keys);
+}
+kadm5_ret_t
+kadm5_randkey_principal_3(void *server_handle,
+			krb5_principal principal,
+			krb5_boolean keepold,
+			int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
+			krb5_keyblock **keyblocks,
+			int *n_keys)
+{
+    krb5_db_entry		kdb;
+    osa_princ_ent_rec		adb;
+    krb5_int32			now;
+    kadm5_policy_ent_rec	pol;
+    krb5_key_data		*key_data;
+    int				ret, last_pwd, have_pol = 0;
+    kadm5_server_handle_t	handle = server_handle;
+
+    if (keyblocks)
+	 *keyblocks = NULL;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if (principal == NULL)
+	return EINVAL;
+    if (hist_princ && /* this will be NULL when initializing the databse */
+	((krb5_principal_compare(handle->context,
+				 principal, hist_princ)) == TRUE))
+	return KADM5_PROTECT_PRINCIPAL;
+
+    if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+       return(ret);
+
+    ret = krb5_dbe_crk(handle->context, &master_keyblock,
+		       n_ks_tuple?ks_tuple:handle->params.keysalts,
+		       n_ks_tuple?n_ks_tuple:handle->params.num_keysalts,
+		       keepold,
+		       &kdb);
+    if (ret)
+	goto done;
+
+    kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+    ret = krb5_timeofday(handle->context, &now);
+    if (ret)
+	goto done;
+
+    if ((adb.aux_attributes & KADM5_POLICY)) {
+	if ((ret = kadm5_get_policy(handle->lhandle, adb.policy,
+				    &pol)) != KADM5_OK) 
+	   goto done;
+	have_pol = 1;
+
+	ret = krb5_dbe_lookup_last_pwd_change(handle->context,
+					      &kdb, &last_pwd);
+	if (ret)
+	     goto done;
+
+#if 0
+	 /*
+	  * The spec says this check is overridden if the caller has
+	  * modify privilege.  The admin server therefore makes this
+	  * check itself (in chpass_principal_wrapper, misc.c).  A
+	  * local caller implicitly has all authorization bits.
+	  */
+	if((now - last_pwd) < pol.pw_min_life &&
+	   !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+	     ret = KADM5_PASS_TOOSOON;
+	     goto done;
+	}
+#endif
+
+	if(pol.pw_history_num > 1) {
+	    if(adb.admin_history_kvno != hist_kvno) {
+		ret = KADM5_BAD_HIST_KEY;
+		goto done;
+	    }
+
+	    ret = check_pw_reuse(handle->context, &hist_key,
+				 kdb.n_key_data, kdb.key_data,
+				 adb.old_key_len, adb.old_keys);
+	    if (ret)
+		goto done;
+	}
+	if (pol.pw_max_life)
+	   kdb.pw_expiration = now + pol.pw_max_life;
+	else
+	   kdb.pw_expiration = 0;
+    } else {
+	kdb.pw_expiration = 0;
+    }
+
+    ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now);
+    if (ret)
+	 goto done;
+
+    if (keyblocks) {
+	 if (handle->api_version == KADM5_API_VERSION_1) {
+	      /* Version 1 clients will expect to see a DES_CRC enctype. */
+	     ret = krb5_dbe_find_enctype(handle->context, &kdb,
+					 ENCTYPE_DES_CBC_CRC,
+					 -1, -1, &key_data);
+	     if (ret)
+		 goto done;
+	     
+	     ret = decrypt_key_data(handle->context, 1, key_data,
+				     keyblocks, NULL);
+	     if (ret)
+		 goto done;
+	 } else {
+	     ret = decrypt_key_data(handle->context,
+				     kdb.n_key_data, kdb.key_data,
+				     keyblocks, n_keys);
+	     if (ret)
+		 goto done;
+	 }
+    }	 
+    
+    /* key data changed, let the database provider know */
+    kdb.mask = KADM5_KEY_DATA /* | KADM5_RANDKEY_USED */;
+
+    if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+	goto done;
+
+    ret = KADM5_OK;
+done:
+    kdb_free_entry(handle, &kdb, &adb);
+    if (have_pol)
+	 kadm5_free_policy_ent(handle->lhandle, &pol);
+
+    return ret;
+}
+
+/*
+ * kadm5_setv4key_principal:
+ *
+ * Set only ONE key of the principal, removing all others.  This key
+ * must have the DES_CBC_CRC enctype and is entered as having the
+ * krb4 salttype.  This is to enable things like kadmind4 to work.
+ */
+kadm5_ret_t
+kadm5_setv4key_principal(void *server_handle,
+		       krb5_principal principal,
+		       krb5_keyblock *keyblock)
+{
+    krb5_db_entry		kdb;
+    osa_princ_ent_rec		adb;
+    krb5_int32			now;
+    kadm5_policy_ent_rec	pol;
+    krb5_keysalt		keysalt;
+    int				i, k, kvno, ret, have_pol = 0;
+#if 0
+    int                         last_pwd;
+#endif
+    kadm5_server_handle_t	handle = server_handle;
+    krb5_key_data               tmp_key_data;
+
+    memset( &tmp_key_data, 0, sizeof(tmp_key_data));
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if (principal == NULL || keyblock == NULL)
+	return EINVAL;
+    if (hist_princ && /* this will be NULL when initializing the databse */
+	((krb5_principal_compare(handle->context,
+				 principal, hist_princ)) == TRUE))
+	return KADM5_PROTECT_PRINCIPAL;
+
+    if (keyblock->enctype != ENCTYPE_DES_CBC_CRC)
+	return KADM5_SETV4KEY_INVAL_ENCTYPE;
+    
+    if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+       return(ret);
+
+    for (kvno = 0, i=0; i<kdb.n_key_data; i++)
+	 if (kdb.key_data[i].key_data_kvno > kvno)
+	      kvno = kdb.key_data[i].key_data_kvno;
+
+    if (kdb.key_data != NULL)
+	 cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data);
+    
+    kdb.key_data = (krb5_key_data*)krb5_db_alloc(handle->context, NULL, sizeof(krb5_key_data));
+    if (kdb.key_data == NULL)
+	 return ENOMEM;
+    memset(kdb.key_data, 0, sizeof(krb5_key_data));
+    kdb.n_key_data = 1;
+    keysalt.type = KRB5_KDB_SALTTYPE_V4;
+    /* XXX data.magic? */
+    keysalt.data.length = 0;
+    keysalt.data.data = NULL;
+
+    /* use tmp_key_data as temporary location and reallocate later */
+    ret = krb5_dbekd_encrypt_key_data(handle->context, &master_keyblock,
+				      keyblock, &keysalt, kvno + 1,
+				      &tmp_key_data);
+    if (ret) {
+	goto done;
+    }
+
+    for (k = 0; k < tmp_key_data.key_data_ver; k++) {
+	kdb.key_data->key_data_type[k] = tmp_key_data.key_data_type[k];
+	kdb.key_data->key_data_length[k] = tmp_key_data.key_data_length[k];
+	if (tmp_key_data.key_data_contents[k]) {
+	    kdb.key_data->key_data_contents[k] = krb5_db_alloc(handle->context, NULL, tmp_key_data.key_data_length[k]);
+	    if (kdb.key_data->key_data_contents[k] == NULL) {
+		cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data);
+		kdb.key_data = NULL;
+		kdb.n_key_data = 0;
+		ret = ENOMEM;
+		goto done;
+	    }
+	    memcpy (kdb.key_data->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+	    memset (tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+	    free (tmp_key_data.key_data_contents[k]);
+	    tmp_key_data.key_data_contents[k] = NULL;
+	}
+    }
+
+
+
+    kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+    ret = krb5_timeofday(handle->context, &now);
+    if (ret)
+	goto done;
+
+    if ((adb.aux_attributes & KADM5_POLICY)) {
+	if ((ret = kadm5_get_policy(handle->lhandle, adb.policy,
+				    &pol)) != KADM5_OK) 
+	   goto done;
+	have_pol = 1;
+
+#if 0
+	/*
+	  * The spec says this check is overridden if the caller has
+	  * modify privilege.  The admin server therefore makes this
+	  * check itself (in chpass_principal_wrapper, misc.c).  A
+	  * local caller implicitly has all authorization bits.
+	  */
+	if (ret = krb5_dbe_lookup_last_pwd_change(handle->context,
+						  &kdb, &last_pwd))
+	     goto done;
+	if((now - last_pwd) < pol.pw_min_life &&
+	   !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+	     ret = KADM5_PASS_TOOSOON;
+	     goto done;
+	}
+#endif
+#if 0
+	/*
+	 * Should we be checking/updating pw history here?
+	 */
+	if(pol.pw_history_num > 1) {
+	    if(adb.admin_history_kvno != hist_kvno) {
+		ret = KADM5_BAD_HIST_KEY;
+		goto done;
+	    }
+
+	    if (ret = check_pw_reuse(handle->context,
+				     &hist_key,
+				     kdb.n_key_data, kdb.key_data,
+				     adb.old_key_len, adb.old_keys))
+		goto done;
+	}
+#endif
+	
+	if (pol.pw_max_life)
+	   kdb.pw_expiration = now + pol.pw_max_life;
+	else
+	   kdb.pw_expiration = 0;
+    } else {
+	kdb.pw_expiration = 0;
+    }
+
+    ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now);
+    if (ret)
+	 goto done;
+
+    if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+	goto done;
+
+    ret = KADM5_OK;
+done:
+    for (i = 0; i < tmp_key_data.key_data_ver; i++) {
+	if (tmp_key_data.key_data_contents[i]) {
+	    memset (tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+	    free (tmp_key_data.key_data_contents[i]);
+	}
+    }
+
+    kdb_free_entry(handle, &kdb, &adb);
+    if (have_pol)
+	 kadm5_free_policy_ent(handle->lhandle, &pol);
+
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_setkey_principal(void *server_handle,
+		       krb5_principal principal,
+		       krb5_keyblock *keyblocks,
+		       int n_keys)
+{
+    return
+	kadm5_setkey_principal_3(server_handle, principal,
+				 FALSE, 0, NULL,
+				 keyblocks, n_keys);
+}
+
+kadm5_ret_t
+kadm5_setkey_principal_3(void *server_handle,
+			 krb5_principal principal,
+			 krb5_boolean keepold,
+			 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
+			 krb5_keyblock *keyblocks,
+			 int n_keys)
+{
+    krb5_db_entry		kdb;
+    osa_princ_ent_rec		adb;
+    krb5_int32			now;
+    kadm5_policy_ent_rec	pol;
+    krb5_key_data		*old_key_data;
+    int				n_old_keys;
+    int				i, j, k, kvno, ret, have_pol = 0;
+#if 0
+    int                         last_pwd;
+#endif
+    kadm5_server_handle_t	handle = server_handle;
+    krb5_boolean		similar;
+    krb5_keysalt		keysalt;
+    krb5_key_data         tmp_key_data;
+    krb5_key_data        *tptr;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if (principal == NULL || keyblocks == NULL)
+	return EINVAL;
+    if (hist_princ && /* this will be NULL when initializing the databse */
+	((krb5_principal_compare(handle->context,
+				 principal, hist_princ)) == TRUE))
+	return KADM5_PROTECT_PRINCIPAL;
+
+    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) {
+		if (n_ks_tuple) {
+		    if (ks_tuple[i].ks_salttype == ks_tuple[j].ks_salttype)
+			return KADM5_SETKEY_DUP_ENCTYPES;
+		} else
+		    return KADM5_SETKEY_DUP_ENCTYPES;
+	    }
+	}
+    }
+
+    if (n_ks_tuple && n_ks_tuple != n_keys)
+	return KADM5_SETKEY3_ETYPE_MISMATCH;
+
+    if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+       return(ret);
+    
+    for (kvno = 0, i=0; i<kdb.n_key_data; i++)
+	 if (kdb.key_data[i].key_data_kvno > kvno)
+	      kvno = kdb.key_data[i].key_data_kvno;
+
+    if (keepold) {
+	old_key_data = kdb.key_data;
+	n_old_keys = kdb.n_key_data;
+    } else {
+	if (kdb.key_data != NULL)
+	    cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data);
+	n_old_keys = 0;
+	old_key_data = NULL;
+    }
+    
+    kdb.key_data = (krb5_key_data*)krb5_db_alloc(handle->context, NULL, (n_keys+n_old_keys)
+						 *sizeof(krb5_key_data));
+    if (kdb.key_data == NULL) {
+	ret = ENOMEM;
+	goto done;
+    }
+
+    memset(kdb.key_data, 0, (n_keys+n_old_keys)*sizeof(krb5_key_data));
+    kdb.n_key_data = 0;
+
+    for (i = 0; i < n_keys; i++) {
+	if (n_ks_tuple) {
+	    keysalt.type = ks_tuple[i].ks_salttype;
+	    keysalt.data.length = 0;
+	    keysalt.data.data = NULL;
+	    if (ks_tuple[i].ks_enctype != keyblocks[i].enctype) {
+		ret = KADM5_SETKEY3_ETYPE_MISMATCH;
+		goto done;
+	    }
+	}
+	memset (&tmp_key_data, 0, sizeof(tmp_key_data));
+
+	ret = krb5_dbekd_encrypt_key_data(handle->context,
+					  &master_keyblock,
+					  &keyblocks[i],
+					  n_ks_tuple ? &keysalt : NULL,
+					  kvno + 1,
+					  &tmp_key_data);
+	if (ret) {
+	    goto done;
+	}
+	tptr = &kdb.key_data[i];
+	for (k = 0; k < tmp_key_data.key_data_ver; k++) {
+	    tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
+	    tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
+	    if (tmp_key_data.key_data_contents[k]) {
+		tptr->key_data_contents[k] = krb5_db_alloc(handle->context, NULL, tmp_key_data.key_data_length[k]);
+		if (tptr->key_data_contents[k] == NULL) {
+		    int i1;
+		    for (i1 = k; i1 < tmp_key_data.key_data_ver; i1++) {
+			if (tmp_key_data.key_data_contents[i1]) {
+			    memset (tmp_key_data.key_data_contents[i1], 0, tmp_key_data.key_data_length[i1]);
+			    free (tmp_key_data.key_data_contents[i1]);
+			}
+		    }
+
+		    ret =  ENOMEM;
+		    goto done;
+		}
+		memcpy (tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+		memset (tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+		free (tmp_key_data.key_data_contents[k]);
+		tmp_key_data.key_data_contents[k] = NULL;
+	    }
+	}
+	kdb.n_key_data++;
+    }
+
+    /* copy old key data if necessary */
+    for (i = 0; i < n_old_keys; i++) {
+	kdb.key_data[i+n_keys] = old_key_data[i];
+	memset(&old_key_data[i], 0, sizeof (krb5_key_data));
+	kdb.n_key_data++;
+    }
+
+    if (old_key_data)
+	krb5_db_free(handle->context, old_key_data);
+
+    /* assert(kdb.n_key_data == n_keys + n_old_keys) */
+    kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+    if ((ret = krb5_timeofday(handle->context, &now)))
+	goto done;
+
+    if ((adb.aux_attributes & KADM5_POLICY)) {
+	if ((ret = kadm5_get_policy(handle->lhandle, adb.policy,
+				    &pol)) != KADM5_OK) 
+	   goto done;
+	have_pol = 1;
+
+#if 0
+	/*
+	  * The spec says this check is overridden if the caller has
+	  * modify privilege.  The admin server therefore makes this
+	  * check itself (in chpass_principal_wrapper, misc.c).  A
+	  * local caller implicitly has all authorization bits.
+	  */
+	if (ret = krb5_dbe_lookup_last_pwd_change(handle->context,
+						  &kdb, &last_pwd))
+	     goto done;
+	if((now - last_pwd) < pol.pw_min_life &&
+	   !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+	     ret = KADM5_PASS_TOOSOON;
+	     goto done;
+	}
+#endif
+#if 0
+	/*
+	 * Should we be checking/updating pw history here?
+	 */
+	if (pol.pw_history_num > 1) {
+	    if(adb.admin_history_kvno != hist_kvno) {
+		ret = KADM5_BAD_HIST_KEY;
+		goto done;
+	    }
+
+	    if (ret = check_pw_reuse(handle->context,
+				     &hist_key,
+				     kdb.n_key_data, kdb.key_data,
+				     adb.old_key_len, adb.old_keys))
+		goto done;
+	}
+#endif
+	
+	if (pol.pw_max_life)
+	   kdb.pw_expiration = now + pol.pw_max_life;
+	else
+	   kdb.pw_expiration = 0;
+    } else {
+	kdb.pw_expiration = 0;
+    }
+
+    if ((ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now)))
+        goto done;
+
+    if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+	goto done;
+
+    ret = KADM5_OK;
+done:
+    kdb_free_entry(handle, &kdb, &adb);
+    if (have_pol)
+	 kadm5_free_policy_ent(handle->lhandle, &pol);
+
+    return ret;
+}
+
+/*
+ * 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_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,
+			    int n_key_data, krb5_key_data *key_data,
+			    krb5_keyblock **keyblocks, int *n_keys)
+{
+     krb5_keyblock *keys;
+     int ret, i;
+
+     keys = (krb5_keyblock *) malloc(n_key_data*sizeof(krb5_keyblock));
+     if (keys == NULL)
+	  return ENOMEM;
+     memset((char *) keys, 0, n_key_data*sizeof(krb5_keyblock));
+
+     for (i = 0; i < n_key_data; i++) {
+          ret = krb5_dbekd_decrypt_key_data(context, &master_keyblock,
+					    &key_data[i], 
+					    &keys[i], NULL);
+	  if (ret) {
+	       for (; i >= 0; i--) {
+		   if (keys[i].contents) {
+		       memset (keys[i].contents, 0, keys[i].length);
+		       free( keys[i].contents );
+		   }
+	       }
+
+	       memset((char *) keys, 0, n_key_data*sizeof(krb5_keyblock));
+	       free(keys);
+	       return ret;
+	  }
+     }
+
+     *keyblocks = keys;
+     if (n_keys)
+	  *n_keys = n_key_data;
+
+     return 0;
+}
+
+/*
+ * Function: kadm5_decrypt_key
+ *
+ * Purpose: Retrieves and decrypts a principal key.
+ *
+ * Arguments:
+ *
+ *	server_handle	(r) kadm5 handle
+ *	entry		(r) principal retrieved with kadm5_get_principal
+ *	ktype		(r) enctype to search for, or -1 to ignore
+ *	stype		(r) salt type to search for, or -1 to ignore
+ *	kvno		(r) kvno to search for, -1 for max, 0 for max
+ *			only if it also matches ktype and stype
+ *	keyblock	(w) keyblock to fill in
+ *	keysalt		(w) keysalt to fill in, or NULL
+ *	kvnop		(w) kvno to fill in, or NULL
+ *
+ * Effects: Searches the key_data array of entry, which must have been
+ * retrived with kadm5_get_principal with the KADM5_KEY_DATA mask, to
+ * find a key with a specified enctype, salt type, and kvno in a
+ * principal entry.  If not found, return ENOENT.  Otherwise, decrypt
+ * it with the master key, and return the key in keyblock, the salt
+ * in salttype, and the key version number in kvno.
+ *
+ * If ktype or stype is -1, it is ignored for the search.  If kvno is
+ * -1, ktype and stype are ignored and the key with the max kvno is
+ * returned.  If kvno is 0, only the key with the max kvno is returned
+ * and only if it matches the ktype and stype; otherwise, ENOENT is
+ * returned.
+ */
+kadm5_ret_t kadm5_decrypt_key(void *server_handle,
+			      kadm5_principal_ent_t entry, krb5_int32
+			      ktype, krb5_int32 stype, krb5_int32
+			      kvno, krb5_keyblock *keyblock,
+			      krb5_keysalt *keysalt, int *kvnop)
+{
+    kadm5_server_handle_t handle = server_handle;
+    krb5_db_entry dbent;
+    krb5_key_data *key_data;
+    int ret;
+
+    CHECK_HANDLE(server_handle);
+
+    if (entry->n_key_data == 0 || entry->key_data == NULL)
+	 return EINVAL;
+
+    /* find_enctype only uses these two fields */
+    dbent.n_key_data = entry->n_key_data;
+    dbent.key_data = entry->key_data;
+    if ((ret = krb5_dbe_find_enctype(handle->context, &dbent, ktype,
+				    stype, kvno, &key_data)))
+	 return ret;
+
+    if ((ret = krb5_dbekd_decrypt_key_data(handle->context,
+					   &master_keyblock, key_data,
+					   keyblock, keysalt)))
+	 return ret;
+
+    /*
+     * Coerce the enctype of the output keyblock in case we got an
+     * inexact match on the enctype; this behavior will go away when
+     * the key storage architecture gets redesigned for 1.3.
+     */
+    keyblock->enctype = ktype;
+
+    if (kvnop)
+	 *kvnop = key_data->key_data_kvno;
+
+    return KADM5_OK;
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/str_conv.c b/krb5-1-6/src/lib/kadm5/str_conv.c
new file mode 100644
index 000000000..4a2a67873
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/str_conv.c
@@ -0,0 +1,417 @@
+/*
+ * lib/kadm/str_conv.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * str_conv.c - Convert between strings and Kerberos internal data.
+ */
+
+/*
+ * Table of contents:
+ *
+ * String decoding:
+ * ----------------
+ * krb5_string_to_flags()	- Convert string to krb5_flags.
+ *
+ * String encoding:
+ * ----------------
+ * krb5_flags_to_string()	- Convert krb5_flags to string.
+ */
+
+#include "k5-int.h"
+#include "admin_internal.h"
+#include "adm_proto.h"
+
+/*
+ * Local data structures.
+ */
+struct flags_lookup_entry {
+    krb5_flags		fl_flags;		/* Flag			*/
+    krb5_boolean	fl_sense;		/* Sense of the flag	*/
+    const char *	fl_specifier;		/* How to recognize it	*/
+    const char *	fl_output;		/* How to spit it out	*/
+};
+
+/*
+ * Local strings
+ */
+
+static const char default_tupleseps[]   = ", \t";
+static const char default_ksaltseps[]   = ":.";
+
+/* Keytype strings */
+/* Flags strings */
+static const char flags_pdate_in[]	= "postdateable";
+static const char flags_fwd_in[]	= "forwardable";
+static const char flags_tgtbased_in[]	= "tgt-based";
+static const char flags_renew_in[]	= "renewable";
+static const char flags_proxy_in[]	= "proxiable";
+static const char flags_dup_skey_in[]	= "dup-skey";
+static const char flags_tickets_in[]	= "allow-tickets";
+static const char flags_preauth_in[]	= "preauth";
+static const char flags_hwauth_in[]	= "hwauth";
+static const char flags_pwchange_in[]	= "pwchange";
+static const char flags_service_in[]	= "service";
+static const char flags_pwsvc_in[]	= "pwservice";
+static const char flags_md5_in[]	= "md5";
+static const char flags_pdate_out[]	= "Not Postdateable";
+static const char flags_fwd_out[]	= "Not Forwardable";
+static const char flags_tgtbased_out[]	= "No TGT-based requests";
+static const char flags_renew_out[]	= "Not renewable";
+static const char flags_proxy_out[]	= "Not proxiable";
+static const char flags_dup_skey_out[]	= "No DUP_SKEY requests";
+static const char flags_tickets_out[]	= "All Tickets Disallowed";
+static const char flags_preauth_out[]	= "Preauthorization required";
+static const char flags_hwauth_out[]	= "HW Authorization required";
+static const char flags_pwchange_out[]	= "Password Change required";
+static const char flags_service_out[]	= "Service Disabled";
+static const char flags_pwsvc_out[]	= "Password Changing Service";
+static const char flags_md5_out[]	= "RSA-MD5 supported";
+static const char flags_default_neg[]	= "-";
+static const char flags_default_sep[]	= " ";
+
+/*
+ * Lookup tables.
+ */
+
+static const struct flags_lookup_entry flags_table[] = {
+/* flag				sense	input specifier	   output string     */
+/*----------------------------- -------	------------------ ------------------*/
+{ KRB5_KDB_DISALLOW_POSTDATED,	0,	flags_pdate_in,	   flags_pdate_out   },
+{ KRB5_KDB_DISALLOW_FORWARDABLE,0,	flags_fwd_in,	   flags_fwd_out     },
+{ KRB5_KDB_DISALLOW_TGT_BASED,	0,	flags_tgtbased_in, flags_tgtbased_out},
+{ KRB5_KDB_DISALLOW_RENEWABLE,	0,	flags_renew_in,	   flags_renew_out   },
+{ KRB5_KDB_DISALLOW_PROXIABLE,	0,	flags_proxy_in,	   flags_proxy_out   },
+{ KRB5_KDB_DISALLOW_DUP_SKEY,	0,	flags_dup_skey_in, flags_dup_skey_out},
+{ KRB5_KDB_DISALLOW_ALL_TIX,	0,	flags_tickets_in,  flags_tickets_out },
+{ KRB5_KDB_REQUIRES_PRE_AUTH,	1,	flags_preauth_in,  flags_preauth_out },
+{ KRB5_KDB_REQUIRES_HW_AUTH,	1,	flags_hwauth_in,   flags_hwauth_out  },
+{ KRB5_KDB_REQUIRES_PWCHANGE,	1,	flags_pwchange_in, flags_pwchange_out},
+{ KRB5_KDB_DISALLOW_SVR,	0,	flags_service_in,  flags_service_out },
+{ KRB5_KDB_PWCHANGE_SERVICE,	1,	flags_pwsvc_in,	   flags_pwsvc_out   },
+{ KRB5_KDB_SUPPORT_DESMD5,	1,	flags_md5_in,	   flags_md5_out     }
+};
+static const int flags_table_nents = sizeof(flags_table)/
+				     sizeof(flags_table[0]);
+
+
+krb5_error_code
+krb5_string_to_flags(string, positive, negative, flagsp)
+    char	* string;
+    const char	* positive;
+    const char	* negative;
+    krb5_flags	* flagsp;
+{
+    int 	i;
+    int 	found;
+    const char	*neg;
+    size_t	nsize, psize;
+    int		cpos;
+    int		sense;
+
+    found = 0;
+    /* We need to have a way to negate it. */
+    neg = (negative) ? negative : flags_default_neg;
+    nsize = strlen(neg);
+    psize = (positive) ? strlen(positive) : 0;
+
+    cpos = 0;
+    sense = 1;
+    /* First check for positive or negative sense */
+    if (!strncasecmp(neg, string, nsize)) {
+	sense = 0;
+	cpos += (int) nsize;
+    }
+    else if (psize && !strncasecmp(positive, string, psize)) {
+	cpos += (int) psize;
+    }
+
+    for (i=0; i<flags_table_nents; i++) {
+	if (!strcasecmp(&string[cpos], flags_table[i].fl_specifier)) {
+	    found = 1;
+	    if (sense == (int) flags_table[i].fl_sense)
+		*flagsp |= flags_table[i].fl_flags;
+	    else
+		*flagsp &= ~flags_table[i].fl_flags;
+
+	    break;
+	}
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_flags_to_string(flags, sep, buffer, buflen)
+    krb5_flags	flags;
+    const char	* sep;
+    char	* buffer;
+    size_t	buflen;
+{
+    int			i;
+    krb5_flags		pflags;
+    const char		*sepstring;
+    char		*op;
+    int			initial;
+    krb5_error_code	retval;
+
+    retval = 0;
+    op = buffer;
+    pflags = 0;
+    initial = 1;
+    sepstring = (sep) ? sep : flags_default_sep;
+    /* Blast through the table matching all we can */
+    for (i=0; i<flags_table_nents; i++) {
+	if (flags & flags_table[i].fl_flags) {
+	    /* Found a match, see if it'll fit into the output buffer */
+	    if ((op+strlen(flags_table[i].fl_output)+strlen(sepstring)) <
+		(buffer + buflen)) {
+		if (!initial) {
+		    strcpy(op, sep);
+		    op += strlen(sep);
+		}
+		initial = 0;
+		strcpy(op, flags_table[i].fl_output);
+		op += strlen(flags_table[i].fl_output);
+	    }
+	    else {
+		retval = ENOMEM;
+		break;
+	    }
+	    /* Keep track of what we matched */
+	    pflags |= flags_table[i].fl_flags;
+	}
+    }
+    if (!retval) {
+	/* See if there's any leftovers */
+	if (flags & ~pflags)
+	    retval = EINVAL;
+	else if (initial)
+	    *buffer = '\0';
+    }
+    return(retval);
+}
+
+krb5_error_code
+krb5_input_flag_to_string(flag, buffer, buflen)
+    int		flag;
+    char	* buffer;
+    size_t	buflen;
+{
+    if(flag < 0 || flag >= flags_table_nents) return ENOENT; /* End of list */
+    if(strlen(flags_table[flag].fl_specifier) > buflen) return ENOMEM;
+    strcpy(buffer, flags_table[flag].fl_specifier);
+    return  0;
+}
+
+/*
+ * krb5_keysalt_is_present()	- Determine if a key/salt pair is present
+ *				  in a list of key/salt tuples.
+ *
+ *	Salttype may be negative to indicate a search for only a enctype.
+ */
+krb5_boolean
+krb5_keysalt_is_present(ksaltlist, nksalts, enctype, salttype)
+    krb5_key_salt_tuple	*ksaltlist;
+    krb5_int32		nksalts;
+    krb5_enctype	enctype;
+    krb5_int32		salttype;
+{
+    krb5_boolean	foundit;
+    int			i;
+
+    foundit = 0;
+    if (ksaltlist) {
+	for (i=0; i<nksalts; i++) {
+	    if ((ksaltlist[i].ks_enctype == enctype) &&
+		((ksaltlist[i].ks_salttype == salttype) ||
+		 (salttype < 0))) {
+		foundit = 1;
+		break;
+	    }
+	}
+    }
+    return(foundit);
+}
+
+/*
+ * krb5_string_to_keysalts()	- Convert a string representation to a list
+ *				  of key/salt tuples.
+ */
+krb5_error_code
+krb5_string_to_keysalts(string, tupleseps, ksaltseps, dups, ksaltp, nksaltp)
+    char		*string;
+    const char		*tupleseps;
+    const char		*ksaltseps;
+    krb5_boolean	dups;
+    krb5_key_salt_tuple	**ksaltp;
+    krb5_int32		*nksaltp;
+{
+    krb5_error_code	kret;
+    char 		*kp, *sp, *ep;
+    char		sepchar, trailchar;
+    krb5_enctype	ktype;
+    krb5_int32		stype;
+    krb5_key_salt_tuple	*savep;
+    const char		*tseplist;
+    const char		*ksseplist;
+    const char		*septmp;
+    size_t		len;
+    
+    kret = 0;
+    kp = string;
+    tseplist = (tupleseps) ? tupleseps : default_tupleseps;
+    ksseplist = (ksaltseps) ? ksaltseps : default_ksaltseps;
+    while (kp) {
+	/* Attempt to find a separator */
+	ep = (char *) NULL;
+	if (*tseplist) {
+	    septmp = tseplist;
+	    for (ep = strchr(kp, (int) *septmp);
+		 *(++septmp) && !ep;
+		 ep = strchr(kp, (int) *septmp));
+	}
+
+	if (ep) {
+	    trailchar = *ep;
+	    *ep = '\0';
+	    ep++;
+	}
+	/*
+	 * kp points to something (hopefully) of the form:
+	 *	<enctype><ksseplist><salttype>
+	 *	or
+	 *	<enctype>
+	 */
+	sp = (char *) NULL;
+	/* Attempt to find a separator */
+	septmp = ksseplist;
+	for (sp = strchr(kp, (int) *septmp);
+	     *(++septmp) && !sp;
+	     ep = strchr(kp, (int) *septmp));
+
+	if (sp) {
+	    /* Separate enctype from salttype */
+	    sepchar = *sp;
+	    *sp = '\0';
+	    sp++;
+	}
+	else
+	    stype = -1;
+
+	/*
+	 * Attempt to parse enctype and salttype.  If we parse well
+	 * then make sure that it specifies a unique key/salt combo
+	 */
+	if (!(kret = krb5_string_to_enctype(kp, &ktype)) &&
+	    (!sp || !(kret = krb5_string_to_salttype(sp, &stype))) &&
+	    (dups ||
+	     !krb5_keysalt_is_present(*ksaltp, *nksaltp, ktype, stype))) {
+
+	    /* Squirrel away old keysalt array */
+	    savep = *ksaltp;
+	    len = (size_t) *nksaltp;
+
+	    /* Get new keysalt array */
+	    *ksaltp = (krb5_key_salt_tuple *) 
+		malloc((len + 1) * sizeof(krb5_key_salt_tuple));
+	    if (*ksaltp) {
+
+		/* Copy old keysalt if appropriate */
+		if (savep) {
+		    memcpy(*ksaltp, savep,
+			   len * sizeof(krb5_key_salt_tuple));
+		    krb5_xfree(savep);
+		}
+
+		/* Save our values */
+		(*ksaltp)[(*nksaltp)].ks_enctype = ktype;
+		(*ksaltp)[(*nksaltp)].ks_salttype = stype;
+		(*nksaltp)++;
+	    }
+	    else {
+		*ksaltp = savep;
+		break;
+	    }
+	}
+	if (kret)
+	     return kret;
+	if (sp)
+	    sp[-1] = sepchar;
+	if (ep)
+	    ep[-1] = trailchar;
+	kp = ep;
+
+	/* Skip over extra separators - like spaces */
+	if (kp && *tseplist) {
+	  septmp = tseplist;
+	  while(*septmp && *kp) {
+	    if(*septmp == *kp) {
+	      /* Increment string - reset separator list */
+	      kp++;
+	      septmp = tseplist;
+	    } else {
+	      septmp++;
+	    }
+	  }
+	  if (!*kp) kp = NULL;
+	}
+    } /* while kp */
+    return(kret);
+}
+
+/*
+ * krb5_keysalt_iterate()	- Do something for each unique key/salt
+ *				  combination.
+ *
+ * If ignoresalt set, then salttype is ignored.
+ */
+krb5_error_code
+krb5_keysalt_iterate(ksaltlist, nksalt, ignoresalt, iterator, arg)
+    krb5_key_salt_tuple	*ksaltlist;
+    krb5_int32		nksalt;
+    krb5_boolean	ignoresalt;
+    krb5_error_code	(*iterator) (krb5_key_salt_tuple *, krb5_pointer);
+    krb5_pointer	arg;
+{
+    int			i;
+    krb5_error_code	kret;
+    krb5_key_salt_tuple	scratch;
+
+    kret = 0;
+    for (i=0; i<nksalt; i++) {
+	scratch.ks_enctype = ksaltlist[i].ks_enctype;
+	scratch.ks_salttype = (ignoresalt) ? -1 : ksaltlist[i].ks_salttype;
+	if (!krb5_keysalt_is_present(ksaltlist,
+				     i,
+				     scratch.ks_enctype,
+				     scratch.ks_salttype)) {
+	    kret = (*iterator)(&scratch, arg);
+	    if (kret)
+		break;
+	}
+    }
+    return(kret);
+}
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/Makefile.in b/krb5-1-6/src/lib/kadm5/unit-test/Makefile.in
new file mode 100644
index 000000000..44db16b8b
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/Makefile.in
@@ -0,0 +1,232 @@
+thisconfigdir=../../..
+myfulldir=lib/kadm5/unit-test
+mydir=lib/kadm5/unit-test
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFINES = -DUSE_KADM5_API_VERSION=1
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+DEFS=
+
+SRCS= init-test.c destroy-test.c handle-test.c iter-test.c setkey-test.c \
+	randkey-test.c lock-test.c
+
+all:: init-test destroy-test client-handle-test client-iter-test
+all:: randkey-test server-handle-test lock-test server-iter-test 
+all:: server-setkey-test client-setkey-test
+
+#
+# The client-side test programs.
+#
+
+init-test: init-test.o $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o init-test init-test.o \
+		$(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+
+destroy-test: destroy-test.o $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o destroy-test destroy-test.o \
+		$(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+
+client-handle-test: handle-test.o $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o client-handle-test handle-test.o \
+		$(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+
+client-iter-test: iter-test.o $(KADMLCNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o client-iter-test iter-test.o \
+		$(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+
+client-setkey-test: setkey-test.o $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o client-setkey-test setkey-test.o \
+		$(KADMCLNT_LIBS) $(KRB5_BASE_LIBS)
+
+#
+# The server-side test programs.
+#
+
+randkey-test: randkey-test.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o randkey-test randkey-test.o \
+		$(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+
+server-handle-test: handle-test.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o server-handle-test handle-test.o \
+		$(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+
+lock-test: lock-test.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o lock-test lock-test.o \
+		$(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+
+server-iter-test: iter-test.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o server-iter-test iter-test.o \
+		$(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+
+setkey-test.o: $(SRCTOP)/lib/kadm5/unit-test/setkey-test.c
+	$(CC) $(ALL_CFLAGS) -UUSE_KADM5_API_VERSION -DUSE_KADM5_API_VERSION=2 -c $(SRCTOP)/lib/kadm5/unit-test/setkey-test.c
+
+server-setkey-test: setkey-test.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o server-setkey-test setkey-test.o \
+		$(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+
+#
+# The unit-test targets
+#
+
+check:: check-@DO_TEST@
+
+check-::
+	@echo "+++"
+	@echo "+++ WARNING: lib/kadm5 unit tests not run."
+	@echo "+++ Either tcl, runtest, or Perl is unavailable."
+	@echo "+++"
+
+check-ok unit-test:: unit-test-client unit-test-server
+
+unit-test-client: unit-test-client-setup unit-test-client-body \
+	unit-test-client-cleanup
+
+unit-test-server: unit-test-server-setup unit-test-server-body \
+	unit-test-server-cleanup
+
+test-randkey:: randkey-test
+	$(ENV_SETUP) ./randkey-test
+
+test-handle-server:: server-handle-test
+	$(ENV_SETUP) ./server-handle-test
+
+test-handle-client:: client-handle-test
+	$(ENV_SETUP) ./client-handle-test
+
+test-noauth: init-test
+	$(ENV_SETUP) ./init-test
+
+test-destroy: destroy-test
+	$(ENV_SETUP) ./destroy-test
+
+unit-test-client-setup::
+	$(ENV_SETUP) $(START_SERVERS)
+
+unit-test-client-cleanup::
+	$(ENV_SETUP) $(STOP_SERVERS)
+
+unit-test-server-setup::
+	$(ENV_SETUP) $(START_SERVERS_LOCAL)
+
+unit-test-server-cleanup::
+	$(ENV_SETUP) $(STOP_SERVERS_LOCAL)
+
+unit-test-client-body: site.exp test-noauth test-destroy test-handle-client 
+	$(ENV_SETUP) $(RUNTEST) --tool api RPC=1 API=$(CLNTTCL) \
+		KINIT=$(BUILDTOP)/clients/kinit/kinit \
+		KDESTROY=$(BUILDTOP)/clients/kdestroy/kdestroy \
+		KADMIN_LOCAL=$(BUILDTOP)/kadmin/cli/kadmin.local \
+		PRIOCNTL_HACK=@PRIOCNTL_HACK@ $(RUNTESTFLAGS)
+	-mv api.log capi.log
+	-mv api.sum capi.sum
+
+unit-test-server-body: site.exp test-handle-server lock-test 
+	$(ENV_SETUP) $(RUNTEST) --tool api RPC=0 API=$(SRVTCL) \
+		LOCKTEST=./lock-test \
+		KADMIN_LOCAL=$(BUILDTOP)/kadmin/cli/kadmin.local \
+		PRIOCNTL_HACK=@PRIOCNTL_HACK@ $(RUNTESTFLAGS)
+	-mv api.log sapi.log
+	-mv api.sum sapi.sum
+
+clean::
+	$(RM) init-test client_init.o init-test.o
+	$(RM) destroy-test destroy-test.o
+	$(RM) client-handle-test handle-test.o
+	$(RM) client-iter-test iter-test.o
+	$(RM) randkey-test randkey-test.o
+	$(RM) server-handle-test handle-test.o
+	$(RM) lock-test lock-test.o
+	$(RM) server-iter-test iter-test.o
+	$(RM) server-setkey-test client-setkey-test setkey-test.o
+	$(RM) *.log *.plog *.sum *.psum unit-test-log.*
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)init-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h init-test.c
+$(OUTPRE)destroy-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/client_internal.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h destroy-test.c
+$(OUTPRE)handle-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/client_internal.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h handle-test.c
+$(OUTPRE)iter-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h iter-test.c
+$(OUTPRE)setkey-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h setkey-test.c
+$(OUTPRE)randkey-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h randkey-test.c
+$(OUTPRE)lock-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h lock-test.c
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/README.new-tests b/krb5-1-6/src/lib/kadm5/unit-test/README.new-tests
new file mode 100644
index 000000000..d63ecc285
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/README.new-tests
@@ -0,0 +1,12 @@
+The deja-gnu unit tests in this directory are arranged as follows:
+
+api.0: original unit tests for the ovsec_kadm_api
+
+api.1: additional tests for ovsec_kadm_api that run after api.0
+
+api.2: Each file whose name is the same as a file in api.0 contains
+all of the same tests, but using the kadm5 with KADM5_API_VERSION_1.
+Each file with a -v2 suffix tests KADM5_API_VERSION_2-specific
+functionality.  New tests should be added to the files in this
+directory, not api.0.  Tests should be added to the lowest-numbered
+version file they apply to.
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/chpass-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/chpass-principal.exp
new file mode 100644
index 000000000..93869f7d7
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/chpass-principal.exp
@@ -0,0 +1,176 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "chpass-principal 180"
+proc test180 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_chpass_principal $server_handle "%s/a" FoobarBax
+    } $test]
+
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test180 }
+
+test "chpass-principal 180.5"
+proc test1805 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_chpass_principal $server_handle "%s/a" FoobarBax
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test1805 }
+
+#
+# admin with changepw service tickets try to change other principals
+# password, failes with AUTH error
+test "chpass-principal 180.625"
+proc test180625 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_chpass_principal $server_handle "%s/a" password
+    } $test] "AUTH"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test180625 }
+
+test "chpass-principal 180.75"
+proc test18075 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_chpass_principal $server_handle "%s/a" Foobar
+    } $test] "AUTH_CHANGEPW"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test18075 }
+
+test "chpass-principal 182"
+proc test182 {} {
+    global test
+
+    if { ! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_chpass_principal $server_handle kadmin/history password
+    } "PROTECT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test182
+
+test "chpass-principal 183"
+proc test183 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if { ! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_chpass_principal null "%s/a" password
+    } $test] "BAD_SERVER_HANDLE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test183
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-policy.exp
new file mode 100644
index 000000000..e2d02a37f
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-policy.exp
@@ -0,0 +1,991 @@
+load_lib lib.t
+api_exit
+api_start
+
+# Description: (1) Fails for mask with undefined bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 1"
+proc test1 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		0xF01000
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test1
+
+# Description: (2) Fails if caller connected with CHANGEPW_SERVICE.
+test "create-policy 2"
+proc test2 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy";
+	return
+    }
+}
+if {$RPC} { test2 }
+
+# Description: (3) Fails for mask without POLICY bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 3"
+proc test3 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		0x000000
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test3
+
+# Description: (4) Fails for mask with REF_COUNT bit set.
+test "create-policy 4"
+proc test4 {} {
+    global test
+    
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY OVSEC_KADM_REF_COUNT}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test4
+
+# Description: (5) Fails for invalid policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 5"
+proc test5 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/"] \
+		{OVSEC_KADM_POLICY}
+    } $test] "BAD_POLICY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test5
+
+# Description: (6) Fails for existing policy name.
+test "create-policy 6"
+proc test6 {} {
+    global test
+#    set prms_id 777
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_create_policy $server_handle [simple_policy test-pol] \
+		{OVSEC_KADM_POLICY}
+    } "DUP"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test6
+
+# Description: (7) Fails for null policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 7"
+proc test7 {} {
+    global test
+#    set prms_id 1977
+#    setup_xfail {*-*-*} $prms_id
+    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_create_policy $server_handle [simple_policy null] \
+		{OVSEC_KADM_POLICY}
+    } "EINVAL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test7
+
+# Description: (8) Fails for empty-string policy name.
+test "create-policy 8"
+proc test8 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_create_policy $server_handle [simple_policy ""] \
+		{OVSEC_KADM_POLICY}
+    } "BAD_POLICY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test8
+
+# Description: (9) Accepts 0 for pw_min_life.
+test "create-policy 9"
+proc test9 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LIFE}
+    } $test]]} {
+	fail "$test: create failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+# Description: (10) Accepts non-zero for pw_min_life.
+test "create-policy 10"
+proc test10 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 32 0 0 0 0 0 } \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LIFE}
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+# Description: (11) Accepts 0 for pw_max_life.
+test "create-policy 11"
+proc test11 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MAX_LIFE}
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+# Description: (12) Accepts non-zero for pw_max_life.
+test "create-policy 12"
+proc test12 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 32 0 0 0 0 } \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MAX_LIFE}
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+# Description: (13) Rejects 0 for pw_min_length.
+test "create-policy 13"
+proc test13 {} {
+    global test
+    global prompt
+
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LENGTH}
+    } $test] "BAD_LENGTH"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+# Description: (14) Accepts non-zero for pw_min_length.
+test "create-policy 14"
+proc test14 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 8 0 0 0 } \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LENGTH}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 3\n"
+    expect {
+	-re "8\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test14
+
+# Description: (15) Rejects 0 for pw_min_classes.
+test "create-policy 15"
+proc test15 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+# Description: (16) Accepts 1 for pw_min_classes.
+test "create-policy 16"
+proc test16 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 1 0 0 } \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test16
+
+# Description: (17) Accepts 4 for pw_min_classes.
+test "create-policy 17"
+proc test17 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "5\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+# Description: (18) Rejects 5 for pw_min_classes.
+test "create-policy 18"
+proc test18 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test18
+
+# Description: (19) Rejects 0 for pw_history_num.
+test "create-policy 19"
+proc test19 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test19
+
+# Description: (20) Accepts 1 for pw_history_num.
+test "create-policy 20"
+proc test20 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd  [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test20
+
+# Description: (21) Accepts 10 for pw_history_num.
+test "create-policy 21"
+proc test21 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "10\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21
+    
+# Description: (21.5) Rejects 11 for pw_history_num.
+# 01/24/94: pshuang: untried.
+
+test "create-policy 21.5"
+proc test215 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 0 11 0} \
+		{OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test215
+
+
+# Description: (22) Fails for user with no access bits.
+test "create-policy 22"
+proc test22 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test22
+
+# Description: (23) Fails for user with "get" but not "add".
+test "create-policy 23"
+proc test23 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test23
+
+# Description: (24) Fails for user with "modify" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 24"
+proc test24 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test24
+
+# Description: (25) Fails for user with "delete" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 25"
+proc test25 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test25
+
+# Description: Succeeds for user with "add".
+test "create-policy 26"
+proc test26 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test26
+
+# Description: Succeeds for user with "get" and "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 27"
+proc test27 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/get-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test27
+
+# Description: (28) Rejects null policy argument.
+# 01/24/94: pshuang: untried.
+test "create-policy 28"
+proc test28 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_create_policy $server_handle null {OVSEC_KADM_POLICY}
+    } "EINVAL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test28
+
+test "create-policy 30"
+proc test30 {} {
+    global test
+    one_line_fail_test [format {
+	ovsec_kadm_create_policy null [simple_policy "%s/a"] \
+		{OVSEC_KADM_POLICY}
+    } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-principal.exp
new file mode 100644
index 000000000..676a83013
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/crte-principal.exp
@@ -0,0 +1,1336 @@
+load_lib lib.t
+api_exit
+api_start
+
+#test "create-principal 1"
+#
+#proc test1 {} {
+#	global test
+#	begin_dump
+#	one_line_fail_test [format {
+#	    ovsec_kadm_create_principal $server_handle \
+#		    [simple_principal "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+#	} $test $test] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test1
+
+test "create-principal 2"
+
+proc test2 {} {
+    global test
+    begin_dump
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_create_principal $server_handle null \
+		{OVSEC_KADM_PRINCIPAL} testpass
+    } "EINVAL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"
+}
+test2
+
+test "create-principal 3"
+proc test3 {} {
+    global test
+#    set prms_id 777
+#    setup_xfail {*-*-*} $prms_id
+    begin_dump
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} null
+    } $test] "EINVAL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+test3
+
+test "create-principal 4"
+proc test4 {} {
+    global test
+
+    begin_dump    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} ""
+    } $test] "_Q_TOOSHORT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"     
+}
+test4
+
+test "create-principal 5"
+proc test5 {} {
+    global test
+    begin_dump    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle \
+		[simple_principal "%s/a"] {0x100001} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+test5
+
+test "create-principal 6"
+proc test6 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_LAST_PWD_CHANGE} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test6
+
+test "create-principal 7"
+proc test7 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_MOD_TIME} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test7
+
+test "create-principal 8"
+proc test8 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_MOD_NAME} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test8
+
+test "create-principal 9"
+proc test9 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_MKVNO} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test9
+
+test "create-principal 10"
+proc test10 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_AUX_ATTRIBUTES} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test10
+
+test "create-principal 11"
+proc test11 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_POLICY_CLR} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test11
+
+test "create-principal 12"
+proc test12 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+
+}
+if {$RPC} { test12 }
+
+test "create-principal 13"
+proc test13 {} {
+    global test
+    begin_dump        
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test13 }
+
+test "create-principal 14"
+proc test14 {} {
+    global test
+    begin_dump        
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test14 }
+
+test "create-principal 15"
+proc test15 {} {
+    global test
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test15 }
+
+test "create-principal 16"
+proc test16 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+if {$RPC} { test16 }
+
+test "create-principal 17"
+proc test17 {} {
+    global test
+
+    begin_dump    
+    if {! (( [principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+		error_and_restart "$test: couldn't create principal \"$test/a\""
+		return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} testpass
+    } $test] "DUP"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test17
+
+test "create-principal 18"
+proc test18 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} tP
+    } $test] "_Q_TOOSHORT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+test18
+
+test "create-principal 19"
+proc test19 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} testpassword
+    } $test] "_Q_CLASS"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test19
+
+test "create-principal 20"
+proc test20 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} Abyssinia
+    } $test] "_Q_DICT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test20
+
+test "create-principal 21"
+proc test21 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal $server_handle \
+		[princ_w_pol "%s/a" non-existant-pol] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} NotinTheDictionary
+    } $test] "UNK_POLICY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test21
+
+test "create-principal 23"
+proc test23 {} {
+    global test
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    one_line_succeed_test \
+	    [format {ovsec_kadm_get_principal $server_handle "%s/a" p} $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test23
+
+test "create-principal 24"
+proc test24 {} {
+    global test
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    one_line_succeed_test \
+	    [format {ovsec_kadm_get_principal $server_handle "%s/a" p} $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test24 }
+
+
+test "create-principal 28"
+proc test28 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol.*$prompt$"   { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test28
+
+test "create-principal 29"
+proc test29 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_PRINC_EXPIRE_TIME} \
+		inTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 1\n"
+    expect {
+	-re "0.*$prompt$"   { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test29
+
+test "create-principal 30"
+proc test30 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_PW_EXPIRATION} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test30
+
+test "create-principal 31"
+proc test31 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol-nopw] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+		OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test31
+
+test "create-principal 32"
+proc test32 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+		OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+
+    send "lindex \$principal 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 0 } {
+	fail "$test: pw_expire $pw_expire should be 0"
+	return
+    } else {
+	pass "$test" 
+    }
+
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+perror"$test: unexpected failure in destroy"
+	return
+    }
+}
+test32
+
+test "create-principal 33"
+proc test33 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+perror"$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle \
+		{"%s/a" 0 0 1234 0 null 0 0 0 0 null 0} \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_PW_EXPIRATION} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test33
+
+test "create-principal 34"
+proc test34 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle \
+		{ "%s/a" 0 0 1234 0 null 0 0 0 0 test-pol-nopw 0} \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+		OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test34
+
+test "create-principal 35"
+proc test35 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle \
+		{"%s/a" 0 0 1234 0 null 0 0 0 0 test-pol 0} \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+		OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test35
+
+test "create-principal 36"
+proc test36 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle \
+		{"%s/a" 0 0 999999999 0 null 0 0 0 0 test-pol 0} \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+		OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {    
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy} ]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+
+    send "lindex \$principal 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 999999999 } {
+	fail "$test: pw_expire $pw_expire should be 999999999"
+	return
+    } else {
+	pass "$test"
+    }
+
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+perror"$test: unexpected failure in destroy"
+	return
+    }
+}
+test36
+
+test "create-principal 37"
+proc test37 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test37
+
+test "create-principal 38"
+proc test38 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol-nopw] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test38
+
+test "create-principal 39"
+proc test39 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: cannot not retrieve principal"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+	fail "$test: pw_expire is wrong"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+perror"$test: unexpected failure in destroy"
+	return
+    }
+}
+test39
+
+test "create-principal 40"
+proc test40 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+perror"$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL OVSEC_KADM_PW_EXPIRATION} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 4\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test40
+
+test "create-principal 43"
+proc test43 {} {
+    global test
+    one_line_fail_test [format {
+	ovsec_kadm_create_principal null \
+		    [simple_principal "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+    } $test $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/destroy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/destroy.exp
new file mode 100644
index 000000000..0f103991e
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/destroy.exp
@@ -0,0 +1,203 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "destroy 1"
+
+proc test1 {} {
+	global test
+	begin_dump
+	if {! [cmd {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+	}]} {
+		perror "$test: unexpected failure in init"
+		return
+	}
+	one_line_succeed_test {ovsec_kadm_destroy $server_handle}
+	end_dump_compare "no-diffs"
+}
+test1
+
+#test "destroy 2"
+#
+#proc test2 {} {
+#	global test
+#	begin_dump
+#	if {! [cmd {
+#	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		    server_handle
+#	}]} {
+#	    perror "$test: unexpected failure on init"
+#	    return
+#	}
+#	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test \
+#		{ovsec_kadm_get_principal $server_handle admin principal} \
+#		"NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test2
+
+#test "destroy 3"
+#proc test3 {} {
+#	global test
+#
+#	begin_dump
+#	if {! (( ! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+#	    error_and_restart "$test couldn't delete principal \"$test/a\""
+#	    return
+#	}
+#	if {! [cmd {
+#	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		    server_handle
+#	}]} {
+#	    perror "$test: unexpected failure on init"
+#	    return
+#	}
+#	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test [format {
+#	    ovsec_kadm_create_principal $server_handle \
+#		    [simple_principal "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+#	} $test $test] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test3
+
+#test "destroy 4"
+#proc test4 {} {
+#	global test prompt
+#
+#	if {! (([principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+#		error_and_restart "$test: couldn't create principal \"$test/a\""
+#		return
+#	}
+#	begin_dump
+#	if {! ([cmd {
+#	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		    server_handle
+#	}] &&
+#	    [cmd [format {
+#		ovsec_kadm_get_principal $server_handle "%s/a" principal
+#	    } $test]])} {
+#		error_and_restart "$test: error getting principal"
+#		return;
+#	}
+#	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test [format {
+#	    ovsec_kadm_modify_principal $server_handle \
+#		    {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {OVSEC_KADM_KVNO}
+#	} $test "77"] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test4
+
+#test "destroy 5"
+#
+#proc test5 {} {
+#	global test
+#
+#	if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#		error_and_restart "$test: couldn't create principal \"$test/a\""
+#		return
+#	}
+#	begin_dump
+#	if {! [cmd {
+#	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		    server_handle
+#	}]} {
+#	    perror "$test: unexpected failure on init"
+#	    return
+#	}
+#	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test [format {
+#	    ovsec_kadm_delete_principal $server_handle "%s/a"
+#	} $test] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test5
+
+#test	"destroy 6"
+#
+#proc test6 {} {
+#	global test
+#	begin_dump	
+#	one_line_fail_test {ovsec_kadm_destroy $server_handle} "NOT_INIT"
+#	end_dump_compare "no-diffs"	
+#}
+#test6
+
+
+#test	"destroy 7"
+#
+#proc test7 {} {
+#	global test
+#	begin_dump	
+#	if {! [cmd {
+#	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		    server_handle
+#	}]} {
+#		perror "$test: unexpected failure in init"
+#		return
+#	}
+#	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#	}
+#	one_line_fail_test {ovsec_kadm_destroy $server_handle} "NOT_INIT"
+#	end_dump_compare "no-diffs"	
+#}
+#test7
+
+test	"destroy 8"
+proc test8 {} {
+	global test
+	begin_dump	
+	if {! [cmd {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}]} {
+		perror "$test: unexpected failure in init"
+		return
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+	one_line_succeed_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+	end_dump_compare "no-diffs"		
+}
+test8
+
+test "destroy 9"
+proc test9 {} {
+	global test
+	one_line_fail_test {ovsec_kadm_destroy null} "BAD_SERVER_HANDLE"
+}
+test9
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-policy.exp
new file mode 100644
index 000000000..cd82738e6
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-policy.exp
@@ -0,0 +1,207 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "delete-policy 2"
+proc test2 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {ovsec_kadm_delete_policy $server_handle ""} "BAD_POL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test2
+
+test "delete-policy 5"
+proc test5 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if ${RPC} test5
+
+test "delete-policy 6"
+proc test6 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if ${RPC} test6
+
+test "delete-policy 7"
+proc test7 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test7
+
+test "delete-policy 10"
+proc test10 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_delete_policy $server_handle  "%s/a"
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    if { [policy_exists "$test/a"]} {
+	fail "$test"
+	return
+    }
+}
+test10
+
+test "delete-policy 12"
+proc test12 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test unexecpted failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_create_principal $server_handle [princ_w_pol "%s/a" \
+		"%s/a"] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} \
+		NotinTheDictionary
+    } $test $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {ovsec_kadm_delete_policy $server_handle test-pol} "POLICY_REF"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "delete-policy 13"
+proc test13 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_policy null "%s/a"
+    } $test] "BAD_SERVER_HANDLE"
+}
+test13
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-principal.exp
new file mode 100644
index 000000000..5c617fb35
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/dlte-principal.exp
@@ -0,0 +1,329 @@
+load_lib lib.t
+
+api_exit
+api_start
+
+#test "delete-principal 1"
+#proc test1 {} {
+#	global test
+#	one_line_fail_test [format {
+#	    ovsec_kadm_delete_principal $server_handle "%s/a"
+#	} $test] "NOT_INIT"
+#}
+#test1
+
+test "delete-principal 2"
+proc test2 {} {
+    global test
+   
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't delete principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {ovsec_kadm_delete_principal $server_handle null} "EINVAL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	error_and_restart "$test: unexpected failure in destroy"
+	return
+    }
+}
+test2
+
+test "delete-principal 5"
+proc test5 {} {
+    global test
+   
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't delete principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test] "UNK_PRINC"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test5
+
+test "delete-principal 6"
+proc test6 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" test-pol])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test6 }
+    
+	
+test "delete-principal 7"
+proc test7 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test7 }
+    
+	
+test "delete-principal 8"
+proc test8 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test8 }
+
+test "delete-principal 9"
+proc test9 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test9 }
+
+test "delete-principal 10"
+proc test10 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test10 }
+
+test "delete-principal 11"
+proc test11 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test]]} {
+	fail "$test: delete failed"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    if { [principal_exists "$test/a"] } {
+	fail "$test"
+	return
+    }
+}
+test11
+
+test "delete-principal 12"
+proc test12 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" test-pol])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_delete_principal $server_handle "%s/a"
+    } $test]]} {
+	fail "$test: delete failed"
+	return
+    }
+    if { [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test]]} {
+	fail "$test: principal still exists"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref - 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    pass "$test"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+
+test12
+
+test "delete-principal 13"
+proc test13 {} {
+	global test
+	one_line_fail_test [format {
+	    ovsec_kadm_delete_principal null "%s/a"
+	} $test] "BAD_SERVER_HANDLE"
+}
+test13
+    
+return ""
+
+
+
+
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/get-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/get-policy.exp
new file mode 100644
index 000000000..7b0181412
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/get-policy.exp
@@ -0,0 +1,199 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-policy 3"
+proc test3 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+	server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {ovsec_kadm_get_policy $server_handle "" p} "BAD_POLICY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test3
+
+test "get-policy 6"
+proc test6 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+	    server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {ovsec_kadm_get_policy $server_handle test-pol p} \
+	    "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } test6
+
+test "get-policy 7"
+proc test7 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+	    server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {ovsec_kadm_get_policy $server_handle test-pol p} \
+	    "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } test7
+
+test "get-policy 11"
+proc test11 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/get-pol StupidAdmin $OVSEC_KADM_ADMIN_SERVICE \
+		null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {ovsec_kadm_get_policy $server_handle test-pol p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+test "get-policy 12"
+proc test12 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/get-pol StupidAdmin \
+		$OVSEC_KADM_CHANGEPW_SERVICE null $OVSEC_KADM_STRUCT_VERSION \
+		$OVSEC_KADM_API_VERSION_1 server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {ovsec_kadm_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "get-policy 15"
+proc test15 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/pol StupidAdmin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {ovsec_kadm_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+test "get-policy 16"
+proc test16 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/pol StupidAdmin $OVSEC_KADM_CHANGEPW_SERVICE \
+		null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {ovsec_kadm_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test16
+
+test "get-policy 17"
+proc test17 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+	    server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {ovsec_kadm_get_policy $server_handle test-pol p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+test "get-policy 18"
+proc test18 {} {
+    global test
+
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {ovsec_kadm_get_policy $server_handle test-pol p} \
+	    "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } test18
+
+test "get-policy 21"
+proc test21 {} {
+    global test
+
+    one_line_fail_test {ovsec_kadm_get_policy null "pol1" p} "BAD_SERVER_HANDLE"
+}
+test21
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/get-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/get-principal.exp
new file mode 100644
index 000000000..cf055f787
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/get-principal.exp
@@ -0,0 +1,346 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-principal 1"
+proc test1 {} {
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {ovsec_kadm_get_principal $server_handle null p} "EINVAL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test1
+
+test "get-principal 2"
+proc test2 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test] "UNK_PRINC"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test2
+
+test "get-principal 3"
+proc test3 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test] "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test3 }
+    
+test "get-principal 4"
+proc test4 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test] "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test4 }
+
+test "get-principal 5"
+proc test5 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test] "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test5 }
+
+test "get-principal 6"
+proc test6 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test] "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test6 }
+
+test "get-principal 7"
+proc test7 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test] "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test7 }
+
+    
+test "get-principal 8"
+proc test8 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" p
+    } $test] "AUTH_GET"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test8 }
+
+    
+test "get-principal 9"
+proc test9 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {ovsec_kadm_get_principal $server_handle admin/none p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+test "get-principal 10"
+proc test10 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {ovsec_kadm_get_principal $server_handle admin/none p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+test "get-principal 11"
+proc test11 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/get p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+test "get-principal 12"
+proc test12 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/get p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "get-principal 13"
+proc test13 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/add p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+test "get-principal 14"
+proc test14 {} {
+    global test
+    if {! [cmd {
+	ovsec_kadm_init admin/get-mod admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/add p}
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test14
+
+test "get-principal 15"
+proc test15 {} {
+    one_line_fail_test \
+	    {ovsec_kadm_get_principal null "admin" p} "BAD_SERVER_HANDLE"
+}
+test15
+
+return ""
+
+
+
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/init.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/init.exp
new file mode 100644
index 000000000..d39ecce07
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/init.exp
@@ -0,0 +1,728 @@
+load_lib lib.t
+
+# Assumptions:
+# 
+# Principal "admin" exists, with "get", "add", "modify" and "delete"
+#   access bits and password "admin".
+# The string "not-the-password" isn't the password of any user in the database.
+# Database master password is "mrroot".
+
+api_exit
+api_start
+test "init 1"
+
+one_line_fail_test_nochk \
+	{ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE "" \
+	 $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
+
+test "init 2"
+
+one_line_fail_test_nochk \
+	{ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE @ \
+	 $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
+
+test "init 2.5"
+
+one_line_fail_test_nochk \
+	{ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE BAD.REALM \
+	 $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
+
+test "init 3"
+
+proc test3 {} {
+    global test
+    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+    one_line_fail_test_nochk [format {
+	ovsec_kadm_init admin admin "%s/a" null $OVSEC_KADM_STRUCT_VERSION \
+		$OVSEC_KADM_API_VERSION_1 server_handle
+    } $test]
+}
+if {$RPC} { test3 }
+
+test "init 4"
+
+proc test4 {} {
+    global test
+	if {! ((! [principal_exists "$test/a"]) || 
+         [delete_principal "$test/a"])} {
+		error_and_restart "$test: couldn't delete principal \"$test/a\""
+		return
+	}
+		
+	one_line_fail_test_nochk [format {
+	    ovsec_kadm_init admin admin "%s/a" null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	} $test]
+}
+if {$RPC} { test4 }
+
+test "init 5"
+
+if {$RPC} {
+    one_line_fail_test_nochk {
+	ovsec_kadm_init admin admin admin null $OVSEC_KADM_STRUCT_VERSION \
+		$OVSEC_KADM_API_VERSION_1 server_handle
+    }
+}
+
+test "init 6"
+
+proc test6 {} {
+    global test
+
+    send "ovsec_kadm_init admin null \$OVSEC_KADM_ADMIN_SERVICE null \$OVSEC_KADM_STRUCT_VERSION \$OVSEC_KADM_API_VERSION_1 server_handle\n"
+
+    expect {
+	-re "assword\[^\r\n\]*: *" { }
+	eof {
+		fail "$test: eof instead of password prompt"
+		api_exit
+		api_start
+		return
+	}
+	timeout {
+	    fail "$test: timeout instead of password prompt"
+	    return
+	}
+    }
+    one_line_succeed_test "admin"
+    if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	error_and_restart "$test: couldn't close database"
+    }
+}
+if { $RPC } { test6 } 
+
+test "init 7"
+proc test7 {} {
+    global test
+
+    send "ovsec_kadm_init admin \"\" \$OVSEC_KADM_ADMIN_SERVICE null \$OVSEC_KADM_STRUCT_VERSION \$OVSEC_KADM_API_VERSION_1 server_handle\n"
+
+    expect {
+	-re "assword\[^\r\n\]*: *" { }
+	-re "\n\[^\n\]+key:\[^\n\]*$" { }
+	eof {
+		fail "$test: eof instead of password prompt"
+		api_exit
+		api_start
+		return
+	}
+	timeout {
+	    fail "$test: timeout instead of password prompt"
+	    return
+	}
+    }
+    one_line_succeed_test "admin"
+    if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	error_and_restart "$test: couldn't close database"
+    }
+}
+if { $RPC } { test7 } 
+
+test "init 8"
+
+proc test8 {} {
+    global test
+	if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+		error_and_restart "$test: couldn't create principal \"$test/a\""
+		return
+	}
+ 	one_line_fail_test_nochk [format {
+	    ovsec_kadm_init "%s/a" admin $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	} $test]
+}
+if {$RPC} { test8 }
+
+test "init 9"
+
+if {$RPC} {
+    global test
+  one_line_fail_test_nochk {
+      ovsec_kadm_init admin not-the-password $OVSEC_KADM_ADMIN_SERVICE null \
+	      $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+	      server_handle
+  }
+}
+
+test "init 10"
+
+proc test10 {} {
+	global test
+#	set prms_id 562
+#	setup_xfail {*-*-*} $prms_id
+	one_line_fail_test_nochk {
+	    ovsec_kadm_init null admin $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+}
+test10
+
+#test "init 11"
+#
+#proc test11 {} {
+#	global test
+#	set prms_id 563
+#	setup_xfail {*-*-*} $prms_id
+#	one_line_fail_test_nochk {
+#	    ovsec_kadm_init "" admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		    server_handle
+#	}
+#}
+#test11
+
+test "init 12"
+
+proc test12 {} {
+	global test
+    one_line_fail_test_nochk [format {
+	ovsec_kadm_init "%s/a" admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    } $test]
+}
+if {$RPC} { test12 }
+
+test "init 13"
+
+proc test13 {} {
+	global test
+    one_line_fail_test_nochk [format {
+	ovsec_kadm_init "%s/a@SECURE-TEST.OV.COM" admin \
+		$OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION \
+		$OVSEC_KADM_API_VERSION_1 server_handle
+    } $test]
+}
+if {$RPC} { test13 }
+
+test "init 14"
+
+proc test14 {} {
+	global test
+    one_line_fail_test_nochk [format {
+	ovsec_kadm_init "%s/a@BAD.REALM" admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    } $test]
+}
+if {$RPC} { test14 }
+
+test "init 15"
+
+if {$RPC} {
+    one_line_fail_test_nochk {
+	ovsec_kadm_init admin@BAD.REALM admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }
+}
+
+test "init 16"
+
+proc test16 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test16
+
+test "init 17"
+
+proc test17 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin@SECURE-TEST.OV.COM admin \
+		    $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION \
+		    $OVSEC_KADM_API_VERSION_1 server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test17
+
+test "init 18"
+
+proc test18 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test18
+
+test "init 19"
+
+proc test19 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin@SECURE-TEST.OV.COM admin \
+		    $OVSEC_KADM_ADMIN_SERVICE SECURE-TEST.OV.COM \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test19
+
+test "init 20"
+
+proc test20 {} {
+	global test
+  if {! [cmd {
+      ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	      $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+	      server_handle
+  }]} {
+		error_and_restart "$test: couldn't init database"
+		return
+	}
+	one_line_succeed_test \
+		{ovsec_kadm_get_principal $server_handle admin principal}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test20
+
+#test "init 21"
+#
+#proc test21 {} {
+#    global test
+#    if {! [cmd {
+#	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+#		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		server_handle
+#    }]} {
+#	error_and_restart "$test: couldn't init database"
+#	return
+#    }
+#    one_line_fail_test_nochk {
+#	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		server_handle
+#    }
+#    if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+#	error_and_restart "$test: couldn't close database"
+#    }
+#}
+#test21
+
+
+proc test22 {} {
+	global test prompt
+	set prompting 0
+	send [string trim {
+	    ovsec_kadm_init admin null null null $OVSEC_KADM_STRUCT_VERSION \
+		    $OVSEC_KADM_API_VERSION_1 server_handle
+	}]
+	send "\n"
+	expect {
+	    -re "\n\[^\n\]+:\[^\n\]*$" { set prompting 1}
+	    -re "\nOK .*$prompt$" { fail "$test: premature success" }
+	    -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+		timeout { fail "$test: timeout" }
+		eof { fail "$test: eof" }
+	}
+	if {$prompting} {
+	    one_line_succeed_test mrroot
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	    error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test22 }
+
+test "init 22.5"
+proc test225 {} {
+	global test prompt
+	set prompting 0
+	send [string trim {
+	    ovsec_kadm_init admin null null null $OVSEC_KADM_STRUCT_VERSION \
+		    $OVSEC_KADM_API_VERSION_1 server_handle
+	}]
+	send "\n"
+	expect {
+	    -re "\n\[^\n\]+:\[^\n\]*$" { set prompting 1}
+	    -re "\nOK .*$prompt$" { fail "$test: premature success" }
+	    -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+		timeout { fail "$test: timeout" }
+		eof { fail "$test: eof" }
+	}
+	if {$prompting} {
+	    one_line_succeed_test mrroot
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	    error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test225 }
+
+test "init 23"
+
+proc test23 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin not-the-password $OVSEC_KADM_ADMIN_SERVICE \
+		    null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test23 }
+
+test "init 24"
+
+proc test24 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin admin null null $OVSEC_KADM_STRUCT_VERSION \
+		    $OVSEC_KADM_API_VERSION_1 server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test24 }
+
+test "init 25"
+
+proc test25 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin admin foobar null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test25 }
+
+test "init 26"
+
+#proc test26 {} {
+#	global test
+#
+#	api_exit
+#	api_start
+#	one_line_fail_test_nochk {
+#	    ovsec_kadm_get_principal $server_handle admin principal
+#	}
+#}
+#test26
+
+#test "init 27"
+#
+#proc test27 {} {
+#	global test
+#
+#	if {! ((! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+#		error_and_restart "$test: couldn't delete principal \"$test/a\""
+#		return
+#	}
+#	begin_dump
+#	if {[cmd [format {
+#	    ovsec_kadm_create_principal $server_handle [simple_principal \
+#		    "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+#	} $test $test]]} {
+#		fail "$test: unexpected success in add"
+#		return
+#	}
+#	end_dump_compare "no-diffs"
+#}
+#test27
+
+#test "init 28"
+#
+#proc test28 {} {
+#    global test prompt
+#
+#    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#	error_and_restart "$test: couldn't create principal \"$test/a\""
+#	return
+#    }
+#    begin_dump
+#    if {! ([cmd {
+#	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+#		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+#		server_handle
+#    }] && [cmd [format {
+#	ovsec_kadm_get_principal $server_handle "%s/a" principal
+#    } $test]])} {
+#	error_and_restart "$test: error getting principal"
+#	return;
+#    }
+#    send "lindex \$principal 8\n"
+#    expect {
+#	-re "\n(\[0-9\]+).*$prompt$" {set kvno $expect_out(1,string) }
+#	timeout {
+#	    error_and_restart "$test: timeout getting principal kvno"
+#	    return
+#	}
+#	eof {
+#	    error_and_restart "$test: eof getting principal kvno"
+#	    return
+#	}
+#    }
+#    api_exit
+#    api_start
+#    set new_kvno [expr "$kvno + 1"]
+#    if {[cmd [format {
+#	ovsec_kadm_modify_principal $server_handle \
+#		{"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {OVSEC_KADM_KVNO}
+#    } $test $new_kvno]]} {
+#	fail "$test: unexpected success in modify"
+#	return;
+#    }
+#    end_dump_compare "no-diffs"
+#}
+#test28
+
+#test "init 29"
+#
+#proc test29 {} {
+#    global test
+#
+#    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#	error_and_restart "$test: couldn't create principal \"$test/a\""
+#	return
+#    }
+#    begin_dump
+#    if {[cmd [format {
+#	ovsec_kadm_delete_principal $server_handle "%s/a"
+#    } $test]]} {
+#	fail "$test: unexpected success in delete"
+#	return
+#    }
+#    end_dump_compare "no-diffs"
+#}
+#test29
+
+test "init 30"
+proc test30 {} {
+	global test
+	if {[cmd {
+	    ovsec_kadm_init admin foobar $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}]} {
+		error_and_restart "$test: unexpected success"
+		return
+	}
+	one_line_succeed_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if ${RPC} { test30 }
+
+test "init 31"
+proc test31 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $bad_struct_version_mask $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	} "BAD_STRUCT_VERSION" 
+}
+test31
+
+test "init 32"
+proc test32 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $no_struct_version_mask $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	} "BAD_STRUCT_VERSION" 
+}
+test32
+
+test "init 33"
+proc test33 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $old_struct_version $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	} "OLD_STRUCT_VERSION" 
+}
+test33
+
+test "init 34"
+proc test34 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $new_struct_version $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	} "NEW_STRUCT_VERSION" 
+}
+test34
+
+test "init 35"
+proc test35 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_STRUCT_VERSION $bad_api_version_mask \
+		    server_handle
+	} "BAD_API_VERSION" 
+}
+test35
+
+test "init 36"
+proc test36 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_STRUCT_VERSION $no_api_version_mask \
+		    server_handle
+	} "BAD_API_VERSION" 
+}
+test36
+
+test "init 37"
+proc test37 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_STRUCT_VERSION $old_api_version \
+		    server_handle
+	} "OLD_LIB_API_VERSION" 
+}
+if { $RPC } test37
+
+test "init 38"
+proc test38 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_STRUCT_VERSION $old_api_version \
+		    server_handle
+	} "OLD_SERVER_API_VERSION" 
+}
+if { ! $RPC } test38
+
+test "init 39"
+proc test39 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_STRUCT_VERSION $new_api_version \
+		    server_handle
+	} "NEW_LIB_API_VERSION" 
+}
+if { $RPC } test39
+
+test "init 40"
+proc test40 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_STRUCT_VERSION $new_api_version \
+		    server_handle
+	} "NEW_SERVER_API_VERSION" 
+}
+if { ! $RPC } test40
+
+test "init 41"
+proc test41 {} {
+	global test
+	one_line_fail_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_API_VERSION_1 $OVSEC_KADM_STRUCT_VERSION \
+		    server_handle
+	} "BAD_"
+}
+test41
+
+test "init 42"
+proc test42 {} {
+	global test
+	one_line_succeed_test {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+	    	    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    server_handle
+	}
+	if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test42
+
+
+proc test45_46 {service} {
+    global test kadmin_local env
+
+    spawn $kadmin_local -q "delprinc -force $service"
+    expect {
+	-re "Principal .* deleted." {}
+	default {
+	    perror "kadmin.local delprinc failed\n";
+	}
+    }
+    expect eof
+    wait
+
+    one_line_fail_test [concat {ovsec_kadm_init admin admin } \
+	    $service \
+	    { null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+	    server_handle}] "SECURE_PRINC_MISSING"
+
+    # this leaves the keytab with an incorrect entry
+    spawn $kadmin_local -q "ank -randkey $service"
+    expect eof
+    wait
+
+    # restart the api so it gets a new ccache
+    api_exit
+    api_start
+}
+
+if {$RPC} {
+    test "init 45"
+
+    test45_46 ovsec_adm/admin
+
+    test "init 46"
+
+    test45_46 ovsec_adm/changepw
+
+    # re-extract the keytab so it is right
+    exec rm $env(K5ROOT)/ovsec_adm.srvtab
+    exec $env(MAKE_KEYTAB) -princ ovsec_adm/admin -princ ovsec_adm/changepw \
+	    -princ kadmin/admin -princ kadmin/changepw \
+	    $env(K5ROOT)/ovsec_adm.srvtab
+}
+
+return ""
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-policy.exp
new file mode 100644
index 000000000..ec55999b7
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-policy.exp
@@ -0,0 +1,703 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "modify-policy 2"
+proc test2 {} {
+    global test
+
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test2 }
+
+test "modify-policy 4"
+proc test4 {} {
+    global test
+    
+    if {! ([policy_exists "$test/a"] ||
+	   [create_policy "$test/a"])} {
+            error_and_restart "$test: couldn't create policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_REF_COUNT}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test4
+
+test "modify-policy 8"
+proc test8 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_modify_policy $server_handle [simple_policy ""] \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } "BAD_POLICY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test8
+
+test "modify-policy 9"
+proc test9 {} {
+    global test
+    global prompt
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MIN_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+test "modify-policy 10"
+proc test10 {} {
+    global test
+    global prompt
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 32 0 0 0 0 0} \
+		{OVSEC_KADM_PW_MIN_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+
+test "modify-policy 11"
+proc test11 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+test "modify-policy 12"
+proc test12 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 0 32 0 0 0 0} \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "modify-policy 13"
+proc test13 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MIN_LENGTH}
+    } $test] "BAD_LENGTH"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+test "modify-policy 14"
+proc test14 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 8 0 0 0} \
+		{OVSEC_KADM_PW_MIN_LENGTH}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 3\n"
+    expect {
+	-re "8\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test14
+
+test "modify-policy 15"
+proc test15 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+test "modify-policy 16"
+proc test16 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 1 0 0} \
+		{OVSEC_KADM_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test16
+
+test "modify-policy 17"
+proc test17 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+		{OVSEC_KADM_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "5\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+test "modify-policy 18"
+proc test18 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+		{OVSEC_KADM_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test18
+
+test "modify-policy 19"
+proc test19 {} {
+    global test
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test19
+
+test "modify-policy 20"
+proc test20 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+		{OVSEC_KADM_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test20
+
+test "modify-policy 21"
+proc test21 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+		{OVSEC_KADM_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "10\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21
+
+test "modify-policy 22"
+proc test22 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test22
+
+test "modify-policy 23"
+proc test23 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test23
+
+test "modify-policy 26"
+proc test26 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test26
+
+test "modify-policy 30"
+proc test30 {} {
+    global test
+
+    one_line_fail_test [format {
+	ovsec_kadm_modify_policy null [simple_policy "%s/a"] \
+		{OVSEC_KADM_PW_MAX_LIFE}
+    } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-principal.exp
new file mode 100644
index 000000000..d6a9cbc90
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/mod-principal.exp
@@ -0,0 +1,1942 @@
+load_lib lib.t
+api_exit
+api_start
+
+#test "modify-principal 1"
+#proc test1 {} {
+#	global test
+#	one_line_fail_test [format {
+#	    ovsec_kadm_modify_principal $server_handle [simple_principal \
+#		    "%s/a"] {OVSEC_KADM_PW_EXPIRATION}
+#	} $test] "NOT_INIT"
+#}
+#test1
+
+test "modify-principal 2"
+proc test2 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test2 }
+
+test "modify-principal 4"
+proc test4 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINCIPAL}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test4
+
+
+test "modify-principal 5"
+proc test5 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_LAST_PWD_CHANGE}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test5
+
+test "modify-principal 6"
+proc test6 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_MOD_TIME}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test6
+
+test "modify-principal 7"
+proc test7 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_MOD_NAME}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test7
+
+test "modify-principal 8"
+proc test8 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_MKVNO}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test8
+
+test "modify-principal 9"
+proc test9 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_AUX_ATTRIBUTES}
+    } $test] "BAD_MASK"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+test "modify-principal 10"
+proc test10 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test] "UNK_PRINC"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+test "modify-principal 11"
+proc test11 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test11 }
+
+test "modify-principal 12"
+proc test12 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test12 }
+
+test "modify-principal 13"
+proc test13 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test13 }
+
+test "modify-principal 14"
+proc test14 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test14 }
+
+test "modify-principal 15"
+proc test15 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+test "modify-principal 17"
+proc test17 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		no-policy] {OVSEC_KADM_POLICY}
+    } $test] "UNK_POLICY"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+test "modify-principal 18"
+proc test18 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal "$test/a"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {OVSEC_KADM_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref + 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test18
+
+test "modify-principal 19"
+proc test19 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal "$test/a"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {OVSEC_KADM_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref + 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test19
+
+test "modify-principal 20"
+proc test20 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_POLICY_CLR}
+    } $test]]} {
+	perror "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ fail "$test" }
+	timeout				{ pass "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref - 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test20
+
+test "modify-principal 21"
+proc test21 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol old_p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol-nopw old_p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol-nopw] {OVSEC_KADM_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$old_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    send "lindex \$old_p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set old_p2_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol new_p1}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol-nopw new_p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$new_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    send "lindex \$new_p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set new_p2_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$old_p1_ref - 1"] != $new_p1_ref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { [expr "$old_p2_ref + 1"] != $new_p2_ref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21
+
+test "modify-principal 21.5"
+proc test21.5 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol old_p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {OVSEC_KADM_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$old_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol new_p1}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$new_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+
+    if {$old_p1_ref != $new_p1_ref} {
+	fail "$test: policy reference count changed ($old_p1_ref to $new_p1_ref)"
+	return
+    }
+
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21.5
+
+test "modify-principal 22"
+proc test22 {} {
+    global test
+    global prompt
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modifiy failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test22
+
+test "modify-principal 23"
+proc test23 {} {
+    global test
+    global prompt
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" test-pol-nopw])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modifiy failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test23
+
+test "modify-principal 24"
+proc test24 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	error_and_restart "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PW_EXPIRATION}
+    } $test]]} {
+    	fail "$test: could not modify principal"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_get_policy $server_handle %s policy
+    } test-pol]]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 0 } {
+	fail "$test: pw_expire $pw_expire should be 0"
+	return
+    } else {
+	pass "$test"
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} { 
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test24
+
+test "modify-principal 25"
+proc test25 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test25
+
+test "modify-principal 26"
+proc test26 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol-nopw" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test26
+
+test "modify-principal 27"
+proc test27 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test27
+
+test "modify-principal 28"
+proc test28 {} {
+    global test
+    global prompt
+#    set prms_id 1358
+#    setup_xfail {*-*-*} $prms_id    
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 999999999 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 999999999 } {
+	fail "$test: pw_expire $pw_expire should be 999999999"
+	return
+    }
+    pass "$test"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test28
+
+test "modify-principal 29"
+proc test29 {} {
+    global test
+    global prompt
+    
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { ! ([create_principal_pol "$test/a" test-pol])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_POLICY_CLR}
+    } $test]]} {
+	fail "$test: modifiy failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test29
+
+test "modify-principal 30"
+proc test30 {} {
+    global test
+    global prompt
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal_pol "$test/a" test-pol])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol-nopw] {OVSEC_KADM_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test30
+
+test "modify-principal 31"
+proc test31 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {OVSEC_KADM_POLICY}
+    } $test]]} {
+	fail "modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { [expr "$pw_mod_date + $pw_max_life"] != $pw_expire } {
+	fail "$test: pw_expire is wrong"
+	return
+    }
+
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test31
+
+test "modify-principal 32"
+proc test32 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't delete principal \"$test/a\""
+	return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 1234 0 0 0 0 0 0 0 0 0 0} \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 1\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test32
+
+test "modify-principal 33"
+proc test33 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_ALL_TIX 0 0 0 0} \
+		{OVSEC_KADM_ATTRIBUTES}
+    } $test]]} {
+	fail "$test: modified fail"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+	-re "KRB5_KDB_DISALLOW_ALL_TIX.*$prompt$"		{ pass "$test" }
+	timeout							{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test33
+
+test "modify-principal 33.25"
+proc test3325 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 KRB5_KDB_REQUIRES_PWCHANGE 0 0 0 0} \
+		{OVSEC_KADM_ATTRIBUTES}
+    } $test]]} {
+	fail "$test: modified fail"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+	-re "KRB5_KDB_REQUIRES_PWCHANGE.*$prompt$"		{ pass "$test" }
+	timeout							{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test3325
+
+test "modify-principal 33.5"
+proc test335 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_TGT_BASED 0 0 0 0} \
+		{OVSEC_KADM_ATTRIBUTES}
+    } $test]]} {
+	fail "$test: modified fail"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+	-re "KRB5_KDB_DISALLOW_TGT_BASED.*$prompt$"		{ pass "$test" }
+	timeout							{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test335
+
+
+test "modify-principal 34"
+proc test34 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 0 3456 0 0 0 0 0 0 0} {OVSEC_KADM_MAX_LIFE}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+	-re "3456\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test34
+
+test "modify-principal 35"
+proc test35 {} {
+    global prompt
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 0 7 0 0 0} {OVSEC_KADM_KVNO}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 8\n"
+    expect {
+	-re "7\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test35
+
+test "modify-principal 36"
+proc test36 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol pol}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {OVSEC_KADM_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    send "lindex \$pol 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol pol2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    send "lindex \$pol2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { $oldref != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test36
+
+test "modify-principal 37"
+proc test37 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal "$test/a"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_POLICY_CLR}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test37
+
+test "modify-principal 38"
+proc test38 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 1\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test38
+
+test "modify-principal 39"
+proc test39 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+		{OVSEC_KADM_MAX_LIFE}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_get_principal $server_handle "%s/a" principal
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test39
+
+test "modify-principal 40"
+proc test40 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_modify_principal $server_handle null \
+		{OVSEC_KADM_PRINC_EXPIRE_TIME}
+    } "EINVAL"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test40
+
+test "modify-principal 43"
+proc test43 {} {
+	global test
+	one_line_fail_test [format {
+	    ovsec_kadm_modify_principal null [simple_principal \
+		    "%s/a"] {OVSEC_KADM_PW_EXPIRATION}
+	} $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/randkey-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/randkey-principal.exp
new file mode 100644
index 000000000..c96700194
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/randkey-principal.exp
@@ -0,0 +1,319 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "randkey-principal 1"
+proc test1 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd [format {
+	ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test] "PASS_TOOSOON"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test1 } 
+
+test "randkey-principal 3"
+proc test3 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd [format {
+	ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test] "PASS_TOOSOON"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if ${RPC} { test3 } 
+
+test "randkey-principal 13"
+proc test13 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+		once-a-min] OVSEC_KADM_POLICY
+    } $test]]} {
+	perror "$test: failed modify"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+test "randkey-principal 15"
+proc test15 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test] "AUTH_CHANGEPW"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test15 }
+
+test "randkey-principal 28"
+proc test28 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test28
+
+test "randkey-principal 28.25"
+proc test2825 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test] "AUTH"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test2825 }
+
+test "randkey-principal 28.5"
+proc test285 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test285
+
+test "randkey-principal 30"
+proc test30 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal "$test/a"]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    if {! [cmd [format {
+	ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test30
+
+test "randkey-principal 31"
+proc test31 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal "$test/a"]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd [format {
+	ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_randkey_principal $server_handle "%s/a" key
+    } $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test31
+
+test "randkey-principal 32"
+proc test32 {} {
+    global test
+
+    if { ! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	ovsec_kadm_randkey_principal $server_handle kadmin/history key
+    } "PROTECT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test32
+
+test "randkey-principal 33"
+proc test33 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if { ! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_randkey_principal null "%s/a" key
+    } $test] "BAD_SERVER_HANDLE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+
+test33
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.0/rename-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.0/rename-principal.exp
new file mode 100644
index 000000000..d5f012f8b
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.0/rename-principal.exp
@@ -0,0 +1,509 @@
+load_lib lib.t
+api_exit
+api_start
+
+#test "rename-principal 1"
+#proc test1 {} {
+#	global test
+#	one_line_fail_test [format {
+#	    ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+#	} $test $test] "NOT_INIT"
+#}
+#test1
+
+test "rename-principal 2"
+proc test2 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "INSUFFICIENT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+
+}
+if {$RPC} { test2 }
+
+test "rename-principal 3"
+proc test3 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_INSUFFICIENT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test3 }
+
+test "rename-principal 4"
+proc test4 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_INSUFFICIENT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test4 }
+
+test "rename-principal 5"
+proc test5 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_INSUFFICIENT"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test5 }
+
+test "rename-principal 6"
+proc test6 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/mod-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test6 }
+
+test "rename-principal 7"
+proc test7 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/mod-delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test7 }
+
+test "rename-principal 8"
+proc test8 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/get-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test8 }
+
+test "rename-principal 9"
+proc test9 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/get-delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test9 }
+
+test "rename-principal 10"
+proc test10 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/no-delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_DELETE"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test10 }
+
+test "rename-principal 11"
+proc test11 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/no-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH_ADD"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test11 }
+
+test "rename-principal 12"
+proc test12 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test12 }
+
+
+test "rename-principal 13"
+proc test13 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "AUTH"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test13 }
+
+test "rename-principal 14"
+proc test14 {} {
+    global test
+    
+    if {[principal_exists "$test/a"]} {
+	delete_principal "$test/a"
+    }
+
+    if {[create_principal_with_keysalts "$test/a" "des-cbc-crc:v4"]} {
+	error_and_restart "$test: couldn't create no-salt principal \"$test/a\""
+	return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test]
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test14
+
+test "rename-principal 15"
+proc test15 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( [principal_exists "$test/b"]) ||
+	   [create_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "DUP"
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+test "rename-principal 16"
+proc test16 {} {
+	global test
+	one_line_fail_test [format {
+	    ovsec_kadm_rename_principal null "%s/a" "%s/b"
+	} $test $test] "BAD_SERVER_HANDLE"
+}
+test16
+
+test "rename-principal 18"
+proc test18 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! (( ! [principal_exists "$test/b"]) ||
+	   [delete_principal "$test/b"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+		$OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+    } $test $test] "NO_RENAME_SALT"
+
+    if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test18
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.1/lock.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.1/lock.exp
new file mode 100644
index 000000000..02df75bf7
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.1/lock.exp
@@ -0,0 +1,287 @@
+# This is in api.1 so that it happens after all the tests in api.0.
+# If some API function does not unlock the database then the server
+# (whichs runs through all api tests) will still have it locked, and
+# these tests will fail.
+
+load_lib lib.t
+
+api_exit
+
+if { $RPC } {
+    return
+}
+
+send_user "UNTESTED: lock: DAL changes broke locking code (see MIT RT ticket 3201)\n"
+untested "lock: DAL changes broke locking code (see MIT RT ticket 3201)"
+return
+
+set locktest $LOCKTEST
+set lockfile $env(K5ROOT)/kdb5.kadm5.lock
+
+# The lock tests use the program lock-test in the unit test
+# directory.  The basic idea is that lock-test can be told to acquire
+# various kinds of locks and then wait for input before proceeding;
+# this is necessary because otherwise we'd have no way to test locking
+# interactions without a race condition.
+#
+# lock_test_start and lock_test_continue work together to give a crude
+# form of continuations.  lock_test_continue expects a list of
+# commands for lock-test (passed on the command line) and responses
+# (read from stdout).  When it gets to a command of "wait",
+# lock_test_continue returns, and its return value is a list of the
+# arguments that it should be passed to continue processing that
+# particular list of commands for that particular lock-test after
+# whatever that requried lock-test to wait has been completed.
+#
+# lock_test is simply a wrapper for tests that do not involve wait.
+
+proc lock_test_setup {test cmds} {
+    global locktest spawn_id
+
+    verbose "test $test"
+
+    set cmdline ""
+    foreach cmdpair $cmds {
+	if {[lindex $cmdpair 0] == "eof"} {
+	    break
+	}
+	set cmdline "$cmdline [lindex $cmdpair 0]"
+    }
+
+    verbose "spawning $locktest $cmdline"
+    eval "spawn $locktest $cmdline"
+}
+
+proc lock_test {test cmds} {
+    global spawn_id
+
+    lock_test_setup $test $cmds
+    set lockany [lock_test_continue $test $spawn_id 0 "" 0 $cmds]
+    while {$lockany != {}} {
+	set lockany [eval lock_test_continue $lockany]
+    }
+}
+
+proc lock_test_start {test cmds} {
+    global spawn_id
+
+    lock_test_setup $test $cmds
+    return [lock_test_continue $test $spawn_id 0 "" 0 $cmds]
+}
+
+proc lock_test_continue {test my_spawn_id test_failed fail_output cont cmds} {
+    global wait_error_index wait_errno_index wait_status_index
+    global spawn_id
+
+    set spawn_id $my_spawn_id
+
+    if {$cont == 1} {
+	send -i $spawn_id "\n"
+    }
+
+    while {[llength $cmds] > 0} {
+	set cmdpair [lindex $cmds 0]
+	set cmds [lrange $cmds 1 end]
+	set cmd [lindex $cmdpair 0]
+	set output [lindex $cmdpair 1]
+
+	verbose "test $test: command: $cmd"
+
+	if {$cmd == "wait"} {
+	    # ah, for continuations...
+	    return [list $test $spawn_id $test_failed $fail_output 1 $cmds]
+	} 
+	if {$cmd == "eof"} {
+	    set status $output
+	    set output "doesnotmatchanything"
+	}
+
+	expect {
+	    -i $spawn_id
+	    -re "$output" { verbose "test $test: read: $output" }
+	    timeout {
+		set test_failed 1
+		set fail_output "timeout while waiting for $output"
+	    }
+	    eof {
+		if {$cmd != "eof"} {
+		    set test_failed 1
+		    set fail_output "eof while waiting for $output"
+		}
+	    }
+	}
+
+	if {$test_failed == 1} { break }
+    }
+
+    # In timeout cases, the process may not be dead yet.
+    catch { exec kill -9 [exp_pid -i $spawn_id] } x
+    set ret [wait -i $spawn_id]
+    verbose "% Exit $ret" 2
+
+    if {$test_failed == 0} {
+	if {[lindex $ret $wait_error_index] == -1} {
+	    set test_failed 1
+	    set fail_output "wait returned error [lindex $ret $wait_errno_index]"
+	} else {
+	    if { [lindex $ret $wait_status_index] == $status ||
+	    (($status<0) && ([lindex $ret $wait_status_index] == ($status+256))) } {
+		verbose "test $test: status $status"
+	    } else {
+		set test_failed 1
+		set fail_output "unexpected return status [lindex $ret $wait_status_index], should be $status"
+	    }
+	}
+    }
+    
+    if {$test_failed == 0} {
+	pass $test 
+    } else { 
+	fail "$test: $fail_output"
+    }
+
+    return {}
+}
+
+set lock1 [lock_test_start 1 [list \
+	[list shared	"shared"] \
+	[list release	"released"] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock1
+
+set lock2 [lock_test_start 2 [list \
+	[list exclusive	exclusive] \
+	[list release	released] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock2
+
+set lock3 [lock_test_start 5 [list \
+	[list permanent	permanent] \
+	[list release	released] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock3
+
+set lock4 [lock_test_start 4 [list \
+	[list release	"Database not locked"] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock4
+
+set lock5 [lock_test_start 5 [list \
+	[list shared	shared] \
+	[list wait	""] \
+	[list eof	0]]]
+set lock5_1 [lock_test_start 5.1 [list \
+	[list shared	shared] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock5_1
+eval lock_test_continue $lock5
+
+set lock6 [lock_test_start 6 [list \
+	[list exclusive exclusive] \
+	[list wait	""] \
+	[list eof	0]]]
+set lock6_1 [lock_test_start 6.1 [list \
+	[list shared	"Cannot lock database"] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock6_1
+eval lock_test_continue $lock6
+
+set lock7 [lock_test_start 7 [list \
+	[list shared	shared] \
+	[list wait	""] \
+	[list eof	0]]]
+set lock7_1 [lock_test_start 7.1 [list \
+	[list exclusive	"Cannot lock database"] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock7_1
+eval lock_test_continue $lock7
+
+set lock8 [lock_test_start 8 [list \
+	[list permanent	permanent] \
+	[list wait	""] \
+	[list release	"released" ] \
+	[list wait	""] \
+	[list eof	0]]]
+set lock8_1 [lock_test_start 8.1 [list \
+	[list "" "administration database lock file missing while opening database" ] \
+	[list wait	""] \
+	[list eof	1]]]
+eval lock_test_continue $lock8_1
+eval set lock8 \[lock_test_continue $lock8\]
+eval lock_test_continue $lock8
+
+set lock9 [lock_test_start 9 [list \
+	[list exclusive exclusive] \
+	[list release released] \
+	[list wait	""] \
+	[list exclusive	"database lock file missing while getting exclusive"] \
+	[list wait	""] \
+	[list eof	0]]]
+set lock9_1 [lock_test_start 9.1 [list \
+	[list permanent	permanent] \
+	[list wait	""] \
+	[list release	released] \
+	[list wait	""] \
+	[list eof	0]]]
+eval set lock9 \[lock_test_continue $lock9\]
+eval lock_test_continue $lock9
+eval set lock9_1 \[lock_test_continue $lock9_1\]
+eval lock_test_continue $lock9_1
+
+if {! [file exists $lockfile]} {
+    perror "lock file missing before test 10"
+}
+set lock10 [lock_test_start 10 [list \
+	[list permanent	permanent] \
+	[list wait	""] \
+	[list release	released] \
+	[list wait	""] \
+	[list eof	0]]]
+if {[file exists $lockfile]} {
+    fail "test 10: lock file exists"
+}
+eval set lock10 \[lock_test_continue $lock10\]
+eval lock_test_continue $lock10
+if {[file exists $lockfile]} {
+    pass "test 11: lock file exists"
+} else {
+    fail "test 11: lock file does not exist"
+}
+
+set lock12 [lock_test_start 12 [list \
+	[list shared	shared] \
+	[list wait	""] \
+	[list eof	0]]]
+set lock12_1 [lock_test_start 12.1 [list \
+	[list "get test-pol"	retrieved] \
+	[list wait	""] \
+	[list eof	0]]]
+eval lock_test_continue $lock12_1
+eval lock_test_continue $lock12
+
+set lock13 [lock_test_start 13 [list \
+	[list "get lock13"	"Principal or policy does not exist"] \
+	[list wait	""] \
+	[list "get lock13"	retrieved] \
+	[list wait	""] \
+	[list eof	0]]]
+set test13_spawn_id $spawn_id
+# create_policy could call api_exit immediately when it starts up.
+# If it does, and the spawn ID in $spawn_id is ours rather than its,
+# it'll close our spawn ID.  So, we call api_start to give it something
+# to close.
+api_start
+create_policy lock13
+set api_spawn_id $spawn_id
+set spawn_id $test13_spawn_id
+eval set lock13 \[lock_test_continue $lock13\]
+eval lock_test_continue $lock13
+set spawn_id $api_spawn_id
+delete_policy lock13
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp
new file mode 100644
index 000000000..d249af0d9
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp
@@ -0,0 +1,68 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "chpass-principal 200"
+proc test200 {} {
+    global test prompt
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal "$test/a"]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+
+    # I'd like to specify a long list of keysalt tuples and make sure
+    # that chpass does the right thing, but we can only use those
+    # enctypes that krbtgt has a key for: des-cbc-crc:normal and
+    # des-cbc-crc:v4, according to the prototype kdc.conf.
+    if {! [cmd [format {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_chpass_principal $server_handle "%s/a" newpassword
+    } $test]]} {
+	perror "$test: unexpected failure in chpass_principal"
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle  "%s/a" p \
+		{KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+    } $test]]} {
+	perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 16\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting num_keys"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting num_keys"
+	    return
+	}
+    }
+
+    # XXX Perhaps I should actually check the key type returned.
+    if {$num_keys == 3} {
+	pass "$test"
+    } else {
+	fail "$test: $num_keys keys, should be 3"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test200
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal.exp
new file mode 100644
index 000000000..0571df20c
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/chpass-principal.exp
@@ -0,0 +1,176 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "chpass-principal 180"
+proc test180 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_chpass_principal $server_handle "%s/a" FoobarBax
+    } $test]
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test180 }
+
+test "chpass-principal 180.5"
+proc test1805 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_chpass_principal $server_handle "%s/a" FoobarBax
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test1805 }
+
+#
+# admin with changepw service tickets try to change other principals
+# password, failes with AUTH error
+test "chpass-principal 180.625"
+proc test180625 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_chpass_principal $server_handle "%s/a" password
+    } $test] "AUTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test180625 }
+
+test "chpass-principal 180.75"
+proc test18075 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_chpass_principal $server_handle "%s/a" Foobar
+    } $test] "AUTH_CHANGEPW"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test18075 }
+
+test "chpass-principal 182"
+proc test182 {} {
+    global test
+
+    if { ! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_chpass_principal $server_handle kadmin/history password
+    } "PROTECT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test182
+
+test "chpass-principal 183"
+proc test183 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if { ! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_chpass_principal null "%s/a" password
+    } $test] "BAD_SERVER_HANDLE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test183
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-policy.exp
new file mode 100644
index 000000000..f11253c2c
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-policy.exp
@@ -0,0 +1,991 @@
+load_lib lib.t
+api_exit
+api_start
+
+# Description: (1) Fails for mask with undefined bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 1"
+proc test1 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		0xF01000
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test1
+
+# Description: (2) Fails if caller connected with CHANGEPW_SERVICE.
+test "create-policy 2"
+proc test2 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy";
+	return
+    }
+}
+if {$RPC} { test2 }
+
+# Description: (3) Fails for mask without POLICY bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 3"
+proc test3 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		0x000000
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test3
+
+# Description: (4) Fails for mask with REF_COUNT bit set.
+test "create-policy 4"
+proc test4 {} {
+    global test
+    
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY KADM5_REF_COUNT}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test4
+
+# Description: (5) Fails for invalid policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 5"
+proc test5 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/"] \
+		{KADM5_POLICY}
+    } $test] "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test5
+
+# Description: (6) Fails for existing policy name.
+test "create-policy 6"
+proc test6 {} {
+    global test
+#    set prms_id 777
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_create_policy $server_handle [simple_policy test-pol] \
+		{KADM5_POLICY}
+    } "DUP"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test6
+
+# Description: (7) Fails for null policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 7"
+proc test7 {} {
+    global test
+#    set prms_id 1977
+#    setup_xfail {*-*-*} $prms_id
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_create_policy $server_handle [simple_policy null] \
+		{KADM5_POLICY}
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test7
+
+# Description: (8) Fails for empty-string policy name.
+test "create-policy 8"
+proc test8 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_create_policy $server_handle [simple_policy ""] \
+		{KADM5_POLICY}
+    } "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test8
+
+# Description: (9) Accepts 0 for pw_min_life.
+test "create-policy 9"
+proc test9 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY KADM5_PW_MIN_LIFE}
+    } $test]]} {
+	fail "$test: create failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+# Description: (10) Accepts non-zero for pw_min_life.
+test "create-policy 10"
+proc test10 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_create_policy $server_handle {"%s/a" 32 0 0 0 0 0 } \
+		{KADM5_POLICY KADM5_PW_MIN_LIFE}
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+# Description: (11) Accepts 0 for pw_max_life.
+test "create-policy 11"
+proc test11 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY KADM5_PW_MAX_LIFE}
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+# Description: (12) Accepts non-zero for pw_max_life.
+test "create-policy 12"
+proc test12 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 32 0 0 0 0 } \
+		{KADM5_POLICY KADM5_PW_MAX_LIFE}
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+# Description: (13) Rejects 0 for pw_min_length.
+test "create-policy 13"
+proc test13 {} {
+    global test
+    global prompt
+
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY KADM5_PW_MIN_LENGTH}
+    } $test] "BAD_LENGTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+# Description: (14) Accepts non-zero for pw_min_length.
+test "create-policy 14"
+proc test14 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 0 8 0 0 0 } \
+		{KADM5_POLICY KADM5_PW_MIN_LENGTH}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 3\n"
+    expect {
+	-re "8\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test14
+
+# Description: (15) Rejects 0 for pw_min_classes.
+test "create-policy 15"
+proc test15 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+# Description: (16) Accepts 1 for pw_min_classes.
+test "create-policy 16"
+proc test16 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 0 0 1 0 0 } \
+		{KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test16
+
+# Description: (17) Accepts 4 for pw_min_classes.
+test "create-policy 17"
+proc test17 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+		{KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "5\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+# Description: (18) Rejects 5 for pw_min_classes.
+test "create-policy 18"
+proc test18 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+		{KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test18
+
+# Description: (19) Rejects 0 for pw_history_num.
+test "create-policy 19"
+proc test19 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY KADM5_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test19
+
+# Description: (20) Accepts 1 for pw_history_num.
+test "create-policy 20"
+proc test20 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd  [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+		{KADM5_POLICY KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retreuve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test20
+
+# Description: (21) Accepts 10 for pw_history_num.
+test "create-policy 21"
+proc test21 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+		{KADM5_POLICY KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "10\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21
+    
+# Description: (21.5) Rejects 11 for pw_history_num.
+# 01/24/94: pshuang: untried.
+
+test "create-policy 21.5"
+proc test215 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 11 0} \
+		{KADM5_POLICY KADM5_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test215
+
+
+# Description: (22) Fails for user with no access bits.
+test "create-policy 22"
+proc test22 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test22
+
+# Description: (23) Fails for user with "get" but not "add".
+test "create-policy 23"
+proc test23 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test23
+
+# Description: (24) Fails for user with "modify" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 24"
+proc test24 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test24
+
+# Description: (25) Fails for user with "delete" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 25"
+proc test25 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test25
+
+# Description: Succeeds for user with "add".
+test "create-policy 26"
+proc test26 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test26
+
+# Description: Succeeds for user with "get" and "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 27"
+proc test27 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+	   [delete_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/get-add admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test27
+
+# Description: (28) Rejects null policy argument.
+# 01/24/94: pshuang: untried.
+test "create-policy 28"
+proc test28 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_create_policy $server_handle null {KADM5_POLICY}
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test28
+
+test "create-policy 30"
+proc test30 {} {
+    global test
+    one_line_fail_test [format {
+	kadm5_create_policy null [simple_policy "%s/a"] \
+		{KADM5_POLICY}
+    } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-principal.exp
new file mode 100644
index 000000000..8a84af271
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/crte-principal.exp
@@ -0,0 +1,1335 @@
+load_lib lib.t
+api_exit
+api_start
+
+#test "create-principal 1"
+#
+#proc test1 {} {
+#	global test
+#	begin_dump
+#	one_line_fail_test [format {
+#	    kadm5_create_principal $server_handle \
+#		    [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+#	} $test $test] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test1
+
+test "create-principal 2"
+
+proc test2 {} {
+    global test
+    begin_dump
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_create_principal $server_handle null \
+		{KADM5_PRINCIPAL} testpass
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"
+}
+test2
+
+test "create-principal 3"
+proc test3 {} {
+    global test
+#    set prms_id 777
+#    setup_xfail {*-*-*} $prms_id
+    begin_dump
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} null
+    } $test] "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+test3
+
+test "create-principal 4"
+proc test4 {} {
+    global test
+
+    begin_dump    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} ""
+    } $test] "_Q_TOOSHORT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"     
+}
+test4
+
+test "create-principal 5"
+proc test5 {} {
+    global test
+    begin_dump    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle \
+		[simple_principal "%s/a"] {0x100001} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+test5
+
+test "create-principal 6"
+proc test6 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_LAST_PWD_CHANGE} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test6
+
+test "create-principal 7"
+proc test7 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MOD_TIME} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test7
+
+test "create-principal 8"
+proc test8 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MOD_NAME} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test8
+
+test "create-principal 9"
+proc test9 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MKVNO} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test9
+
+test "create-principal 10"
+proc test10 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_AUX_ATTRIBUTES} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test10
+
+test "create-principal 11"
+proc test11 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_POLICY_CLR} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test11
+
+test "create-principal 12"
+proc test12 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+
+}
+if {$RPC} { test12 }
+
+test "create-principal 13"
+proc test13 {} {
+    global test
+    begin_dump        
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test13 }
+
+test "create-principal 14"
+proc test14 {} {
+    global test
+    begin_dump        
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test14 }
+
+test "create-principal 15"
+proc test15 {} {
+    global test
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test15 }
+
+test "create-principal 16"
+proc test16 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+if {$RPC} { test16 }
+
+test "create-principal 17"
+proc test17 {} {
+    global test
+
+    begin_dump    
+    if {! (( [principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+		error_and_restart "$test: couldn't create principal \"$test/a\""
+		return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test] "DUP"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test17
+
+test "create-principal 18"
+proc test18 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{KADM5_PRINCIPAL KADM5_POLICY} tP
+    } $test] "_Q_TOOSHORT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"    
+}
+test18
+
+test "create-principal 19"
+proc test19 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{KADM5_PRINCIPAL KADM5_POLICY} testpassword
+    } $test] "_Q_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test19
+
+test "create-principal 20"
+proc test20 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{KADM5_PRINCIPAL KADM5_POLICY} Abyssinia
+    } $test] "_Q_DICT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test20
+
+test "create-principal 21"
+proc test21 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_create_principal $server_handle \
+		[princ_w_pol "%s/a" non-existant-pol] \
+		{KADM5_PRINCIPAL KADM5_POLICY} NotinTheDictionary
+    } $test] "UNK_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    end_dump_compare "no-diffs"        
+}
+test21
+
+test "create-principal 23"
+proc test23 {} {
+    global test
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    one_line_succeed_test \
+	    [format {kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK} $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test23
+
+test "create-principal 24"
+proc test24 {} {
+    global test
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/rename admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    one_line_succeed_test \
+	    [format {kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK} $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test24 }
+
+
+test "create-principal 28"
+proc test28 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{KADM5_PRINCIPAL KADM5_POLICY} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol.*$prompt$"   { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test28
+
+test "create-principal 29"
+proc test29 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL KADM5_PRINC_EXPIRE_TIME} \
+		inTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 1\n"
+    expect {
+	-re "0.*$prompt$"   { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test29
+
+test "create-principal 30"
+proc test30 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test30
+
+test "create-principal 31"
+proc test31 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol-nopw] \
+		{KADM5_PRINCIPAL KADM5_POLICY \
+		KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test31
+
+test "create-principal 32"
+proc test32 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle \
+		[princ_w_pol "%s/a" test-pol] \
+		{KADM5_PRINCIPAL KADM5_POLICY \
+		KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+
+    send "lindex \$principal 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 0 } {
+	fail "$test: pw_expire $pw_expire should be 0"
+	return
+    } else {
+	pass "$test"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test32
+
+test "create-principal 33"
+proc test33 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle \
+		{"%s/a" 0 0 1234 0 null 0 0 0 0 null 0} \
+		{KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test33
+
+test "create-principal 34"
+proc test34 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle \
+		{ "%s/a" 0 0 1234 0 null 0 0 0 0 test-pol-nopw 0} \
+		{KADM5_PRINCIPAL KADM5_POLICY \
+		KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test34
+
+test "create-principal 35"
+proc test35 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle \
+		{"%s/a" 0 0 1234 0 null 0 0 0 0 test-pol 0} \
+		{KADM5_PRINCIPAL KADM5_POLICY \
+		KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test35
+
+test "create-principal 36"
+proc test36 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle \
+		{"%s/a" 0 0 999999999 0 null 0 0 0 0 test-pol 0} \
+		{KADM5_PRINCIPAL KADM5_POLICY \
+		KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {    
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy} ]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+
+    send "lindex \$principal 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 999999999 } {
+	fail "$test: pw_expire is wrong"
+	return
+    } else {
+	pass "$test"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test36
+
+test "create-principal 37"
+proc test37 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test37
+
+test "create-principal 38"
+proc test38 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol-nopw] {KADM5_PRINCIPAL KADM5_POLICY} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test38
+
+test "create-principal 39"
+proc test39 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {KADM5_PRINCIPAL KADM5_POLICY} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if { ! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: cannot not retrieve principal"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+	fail "$test: pw_expire is wrong"
+	return
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test39
+
+test "create-principal 40"
+proc test40 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+		NotinTheDictionary
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: can not retreive principal"
+	return;
+    }
+    send "lindex \$principal 4\n"
+    expect {
+	-re "0.*$prompt$"	    { pass "$test" }
+	timeout			    { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test40
+
+test "create-principal 43"
+proc test43 {} {
+    global test
+    one_line_fail_test [format {
+	kadm5_create_principal null \
+		    [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+    } $test $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/destroy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/destroy.exp
new file mode 100644
index 000000000..744cacd21
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/destroy.exp
@@ -0,0 +1,203 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "destroy 1"
+
+proc test1 {} {
+	global test
+	begin_dump
+	if {! [cmd {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+	}]} {
+		perror "$test: unexpected failure in init"
+		return
+	}
+	one_line_succeed_test {kadm5_destroy $server_handle}
+	end_dump_compare "no-diffs"
+}
+test1
+
+#test "destroy 2"
+#
+#proc test2 {} {
+#	global test
+#	begin_dump
+#	if {! [cmd {
+#	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		    server_handle
+#	}]} {
+#	    perror "$test: unexpected failure on init"
+#	    return
+#	}
+#	if {! [cmd {kadm5_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test \
+#		{kadm5_get_principal $server_handle admin principal} \
+#		"NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test2
+
+#test "destroy 3"
+#proc test3 {} {
+#	global test
+#
+#	begin_dump
+#	if {! (( ! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+#	    error_and_restart "$test couldn't delete principal \"$test/a\""
+#	    return
+#	}
+#	if {! [cmd {
+#	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		    server_handle
+#	}]} {
+#	    perror "$test: unexpected failure on init"
+#	    return
+#	}
+#	if {! [cmd {kadm5_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test [format {
+#	    kadm5_create_principal $server_handle \
+#		    [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+#	} $test $test] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test3
+
+#test "destroy 4"
+#proc test4 {} {
+#	global test prompt
+#
+#	if {! (([principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+#		error_and_restart "$test: couldn't create principal \"$test/a\""
+#		return
+#	}
+#	begin_dump
+#	if {! ([cmd {
+#	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		    server_handle
+#	}] &&
+#	    [cmd [format {
+#		kadm5_get_principal $server_handle "%s/a" principal
+#	    } $test]])} {
+#		error_and_restart "$test: error getting principal"
+#		return;
+#	}
+#	if {! [cmd {kadm5_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test [format {
+#	    kadm5_modify_principal $server_handle \
+#		    {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {KADM5_KVNO}
+#	} $test "77"] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test4
+
+#test "destroy 5"
+#
+#proc test5 {} {
+#	global test
+#
+#	if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#		error_and_restart "$test: couldn't create principal \"$test/a\""
+#		return
+#	}
+#	begin_dump
+#	if {! [cmd {
+#	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		    server_handle
+#	}]} {
+#	    perror "$test: unexpected failure on init"
+#	    return
+#	}
+#	if {! [cmd {kadm5_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#		return
+#	}
+#	one_line_fail_test [format {
+#	    kadm5_delete_principal $server_handle "%s/a"
+#	} $test] "NOT_INIT"
+#	end_dump_compare "no-diffs"
+#}
+#test5
+
+#test	"destroy 6"
+#
+#proc test6 {} {
+#	global test
+#	begin_dump	
+#	one_line_fail_test {kadm5_destroy $server_handle} "NOT_INIT"
+#	end_dump_compare "no-diffs"	
+#}
+#test6
+
+
+#test	"destroy 7"
+#
+#proc test7 {} {
+#	global test
+#	begin_dump	
+#	if {! [cmd {
+#	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		    server_handle
+#	}]} {
+#		perror "$test: unexpected failure in init"
+#		return
+#	}
+#	if {! [cmd {kadm5_destroy $server_handle}]} {
+#		error_and_restart "$test: couldn't close database"
+#	}
+#	one_line_fail_test {kadm5_destroy $server_handle} "NOT_INIT"
+#	end_dump_compare "no-diffs"	
+#}
+#test7
+
+test	"destroy 8"
+proc test8 {} {
+	global test
+	begin_dump	
+	if {! [cmd {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}]} {
+		perror "$test: unexpected failure in init"
+		return
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+	one_line_succeed_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+	end_dump_compare "no-diffs"		
+}
+test8
+
+test "destroy 9"
+proc test9 {} {
+	global test
+	one_line_fail_test {kadm5_destroy null} "BAD_SERVER_HANDLE"
+}
+test9
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-policy.exp
new file mode 100644
index 000000000..c2a53182a
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-policy.exp
@@ -0,0 +1,207 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "delete-policy 2"
+proc test2 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {kadm5_delete_policy $server_handle ""} "BAD_POL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test2
+
+test "delete-policy 5"
+proc test5 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if ${RPC} test5
+
+test "delete-policy 6"
+proc test6 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if ${RPC} test6
+
+test "delete-policy 7"
+proc test7 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test7
+
+test "delete-policy 10"
+proc test10 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_delete_policy $server_handle  "%s/a"
+    } $test]]} {
+	fail "$test"
+	return
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    if { [policy_exists "$test/a"]} {
+	fail "$test"
+	return
+    }
+}
+test10
+
+test "delete-policy 12"
+proc test12 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+    if {! ((! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test unexecpted failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+		"%s/a"] {KADM5_PRINCIPAL KADM5_POLICY} \
+		NotinTheDictionary
+    } $test $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {kadm5_delete_policy $server_handle test-pol} "POLICY_REF"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "delete-policy 13"
+proc test13 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_policy null "%s/a"
+    } $test] "BAD_SERVER_HANDLE"
+}
+test13
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-principal.exp
new file mode 100644
index 000000000..f9dad7801
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/dlte-principal.exp
@@ -0,0 +1,329 @@
+load_lib lib.t
+
+api_exit
+api_start
+
+#test "delete-principal 1"
+#proc test1 {} {
+#	global test
+#	one_line_fail_test [format {
+#	    kadm5_delete_principal $server_handle "%s/a"
+#	} $test] "NOT_INIT"
+#}
+#test1
+
+test "delete-principal 2"
+proc test2 {} {
+    global test
+   
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't delete principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {kadm5_delete_principal $server_handle null} "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	error_and_restart "$test: unexpected failure in destroy"
+	return
+    }
+}
+test2
+
+test "delete-principal 5"
+proc test5 {} {
+    global test
+   
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't delete principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test] "UNK_PRINC"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test5
+
+test "delete-principal 6"
+proc test6 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" test-pol])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test6 }
+    
+	
+test "delete-principal 7"
+proc test7 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test7 }
+    
+	
+test "delete-principal 8"
+proc test8 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test8 }
+
+test "delete-principal 9"
+proc test9 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test9 }
+
+test "delete-principal 10"
+proc test10 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test10 }
+
+test "delete-principal 11"
+proc test11 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test]]} {
+	fail "$test: delete failed"
+	return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    if { [principal_exists "$test/a"] } {
+	fail "$test"
+	return
+    }
+}
+test11
+
+test "delete-principal 12"
+proc test12 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" test-pol])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_delete_principal $server_handle "%s/a"
+    } $test]]} {
+	fail "$test: delete failed"
+	return
+    }
+    if { [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	fail "$test: principal still exists"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref - 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    pass "$test"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+
+test12
+
+test "delete-principal 13"
+proc test13 {} {
+	global test
+	one_line_fail_test [format {
+	    kadm5_delete_principal null "%s/a"
+	} $test] "BAD_SERVER_HANDLE"
+}
+test13
+    
+return ""
+
+
+
+
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-policy.exp
new file mode 100644
index 000000000..83aef80e8
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-policy.exp
@@ -0,0 +1,199 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-policy 3"
+proc test3 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle "" p} "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test3
+
+test "get-policy 6"
+proc test6 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+	    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	    server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+	    "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } test6
+
+test "get-policy 7"
+proc test7 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+	    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	    server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+	    "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } test7
+
+test "get-policy 11"
+proc test11 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/get-pol StupidAdmin $KADM5_ADMIN_SERVICE \
+		null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {kadm5_get_policy $server_handle test-pol p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+test "get-policy 12"
+proc test12 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/get-pol StupidAdmin \
+		$KADM5_CHANGEPW_SERVICE null $KADM5_STRUCT_VERSION \
+		$KADM5_API_VERSION_2 server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {kadm5_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "get-policy 15"
+proc test15 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/pol StupidAdmin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {kadm5_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+test "get-policy 16"
+proc test16 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/pol StupidAdmin $KADM5_CHANGEPW_SERVICE \
+		null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {kadm5_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test16
+
+test "get-policy 17"
+proc test17 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+	    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	    server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {kadm5_get_policy $server_handle test-pol p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+test "get-policy 18"
+proc test18 {} {
+    global test
+
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+	    "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } test18
+
+test "get-policy 21"
+proc test21 {} {
+    global test
+
+    one_line_fail_test {kadm5_get_policy null "pol1" p} "BAD_SERVER_HANDLE"
+}
+test21
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp
new file mode 100644
index 000000000..65c28b808
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp
@@ -0,0 +1,250 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-principal 100"
+proc test100 {} {
+    global test prompt
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd {
+	kadm5_get_principal $server_handle testuser p \
+		{KADM5_PRINCIPAL_NORMAL_MASK}
+    }]} {
+	perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 16\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting num_keys"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting num_keys"
+	    return
+	}
+    }
+    send "lindex \$p 17\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" { set num_tl $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting num_tl"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting num_tl"
+	    return
+	}
+    }
+    send "lindex \$p 18\n"
+    expect {
+	-re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+	-re "\n$prompt" { set key_data {} }
+	timeout {
+	    error_and_restart "$test: timeout getting key_data"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting key_data"
+	    return
+	}
+    }
+    send "lindex \$p 19\n"
+    expect {
+	-re "({.*})\n$prompt" {set tl_data $expect_out(1,string) }
+	-re "\n$prompt" { set tl_data {} }
+	timeout {
+	    error_and_restart "$test: timeout getting tl_data"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting tl_data"
+	    return
+	}
+    }
+    
+    set failed 0
+    if {$num_keys != 0} {
+	fail "$test: num_keys $num_keys should be 0"
+	set failed 1
+    }
+    if {$num_tl != 0} {
+	fail "$test: num_tl $num_tl should be 0"
+	set failed 1
+    }
+    if {$key_data != {}} {
+	fail "$test: key_data $key_data should be {}"
+	set failed 1
+    }
+    if {$tl_data != "{}"} {
+	fail "$test: tl_data $tl_data should be empty"
+	set failed 1
+    }
+    if {$failed == 0} {
+	pass "$test"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test100
+
+proc test101_102 {rpc} {
+    global test prompt
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd {
+	kadm5_get_principal $server_handle testuser p \
+		{KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+    }]} {
+	perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 16\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting num_keys"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting num_keys"
+	    return
+	}
+    }
+    send "lindex \$p 18\n"
+    expect {
+	-re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+	-re "\n$prompt" { set key_data {} }
+	timeout {
+	    error_and_restart "$test: timeout getting key_data"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting key_data"
+	    return
+	}
+    }
+
+    set failed 0
+    if {$num_keys != 3} {
+	fail "$test: num_keys $num_keys should be 3"
+	set failed 1
+    }
+    for {set i 0} {$i < $num_keys} {incr i} {
+	set key "[lindex [lindex $key_data $i] 2]"
+	if {($rpc && [string compare $key ""] != 0) ||
+	    ((! $rpc) && [string compare $key ""] == 0)} {
+	    fail "$test: key_data $key is wrong"
+	    set failed 1
+	    
+	}
+    }
+    if {$failed == 0} { pass "$test" }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test "get-principal 101" 
+if {$RPC} {test101_102 $RPC}
+test "get-principal 102" 
+if {! $RPC} {test101_102 $RPC}
+
+test "get-principal 103"
+proc test103 {} {
+    global test prompt
+
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		"{%s/a} 0 0 0 0 {%s/a} 0 0 0 0 null 0 0 0 0 0 0 1 {} {{999 6 foobar}}" \
+		{KADM5_TL_DATA}
+    } $test $test]]} {
+	fail "$test: cannot set TL_DATA"
+	return
+    }
+
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle {%s/a} p \
+		{KADM5_PRINCIPAL_NORMAL_MASK KADM5_TL_DATA}
+    } $test]]} {
+	perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 17\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" { set num_tl $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting num_tl"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting num_tl"
+	    return
+	}
+    }
+    send "lindex \$p 19\n"
+    expect {
+	-re "({.*})\n$prompt" {set tl_data $expect_out(1,string) }
+	-re "\n$prompt" { set tl_data {} }
+	timeout {
+	    error_and_restart "$test: timeout getting tl_data"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting tl_data"
+	    return
+	}
+    }
+    
+    if {$num_tl == 0} {
+	fail "$test: num_tl $num_tl should not be 0"
+    } elseif {$tl_data == "{{999 6 foobar}}"} {
+	pass "$test"
+    } else {
+	fail "$test: tl_data $tl_data should be {{999 6 foobar}}"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test103
+
+return ""
+
+
+
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal.exp
new file mode 100644
index 000000000..f7a73078d
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/get-principal.exp
@@ -0,0 +1,346 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-principal 1"
+proc test1 {} {
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test \
+	    {kadm5_get_principal $server_handle null p KADM5_PRINCIPAL_NORMAL_MASK} "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test1
+
+test "get-principal 2"
+proc test2 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "UNK_PRINC"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test2
+
+test "get-principal 3"
+proc test3 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test3 }
+    
+test "get-principal 4"
+proc test4 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test4 }
+
+test "get-principal 5"
+proc test5 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test5 }
+
+test "get-principal 6"
+proc test6 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test6 }
+
+test "get-principal 7"
+proc test7 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test7 }
+
+    
+test "get-principal 8"
+proc test8 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test8 }
+
+    
+test "get-principal 9"
+proc test9 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {kadm5_get_principal $server_handle admin/none p KADM5_PRINCIPAL_NORMAL_MASK} 
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+test "get-principal 10"
+proc test10 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test \
+	    {kadm5_get_principal $server_handle admin/none p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+test "get-principal 11"
+proc test11 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/get p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+test "get-principal 12"
+proc test12 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/get p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "get-principal 13"
+proc test13 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/add p KADM5_PRINCIPAL_NORMAL_MASK} 
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+test "get-principal 14"
+proc test14 {} {
+    global test
+    if {! [cmd {
+	kadm5_init admin/get-mod admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/add p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test14
+
+test "get-principal 15"
+proc test15 {} {
+    one_line_fail_test \
+	    {kadm5_get_principal null "admin" p KADM5_PRINCIPAL_NORMAL_MASK} "BAD_SERVER_HANDLE"
+}
+test15
+
+return ""
+
+
+
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/init-v2.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/init-v2.exp
new file mode 100644
index 000000000..ae1384727
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/init-v2.exp
@@ -0,0 +1,619 @@
+load_lib lib.t
+
+api_exit
+api_start
+
+if ![info exists RESOLVE] {
+    set RESOLVE [findfile $objdir/../../../tests/resolve/resolve]
+}
+proc get_hostname { } {
+    global RESOLVE
+    global hostname
+    global localhostname
+    global domain
+
+    if {[info exists hostname] && [info exists localhostname]} {
+	return 1
+    }
+
+    catch "exec $RESOLVE -q >myname" exec_output
+    if ![string match "" $exec_output] {
+	send_log "$exec_output\n"
+	verbose $exec_output
+	send_error "ERROR: can't get hostname\n"
+	return 0
+    }
+    set file [open myname r]
+    if { [ gets $file hostname ] == -1 } {
+	send_error "ERROR: no output from hostname\n"
+	return 0
+    }
+    close $file
+    catch "exec rm -f myname" exec_output
+    regexp "^(\[^.\]*)\.(.*)$" $hostname foo localhostname domain
+
+    set hostname [string tolower $hostname]
+    set localhostname [string tolower $localhostname]
+    set domain [string tolower $domain]
+    verbose "hostname: $hostname; localhostname: $localhostname; domain $domain"
+
+    return 1
+}
+
+
+test "init 101"
+proc test101 {} {
+    global test
+    global hostname
+
+    get_hostname
+    tcl_cmd "set hostname $hostname"
+
+    # XXX Fix to work with a remote TEST_SERVER.  For now, make sure
+    # it fails in that case.
+    one_line_succeed_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ADMIN_SERVER KADM5_CONFIG_KADMIND_PORT} [list $hostname 1751]] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ADMIN_SERVER KADM5_CONFIG_KADMIND_PORT} [list $hostname 4]] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "RPC_ERROR"
+}
+if {$RPC} test101
+
+test "init 102"
+proc test102 {} {
+    global test
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ADMIN_SERVER} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_SERVER_NAME"
+}
+if {$RPC} test102
+
+test "init 103"
+proc test103 {} {
+    global test
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_DBNAME} /does-not-exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "ENOENT"
+}
+#if {! $RPC} test103
+if {! $RPC} {
+    send_user "UNTESTED: test103: test needs updating for DAL changes (see MIT RT ticket 3202)\n"
+    untested "test103: test needs updating for DAL changes (see MIT RT ticket 3202)"
+}
+
+
+test "init 106"
+proc test106 {} {
+    global test prompt
+
+    set prompting 0
+    send [string trim {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_MKEY_FROM_KBD} 1] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]
+    send "\n"
+    expect {
+	-re "\n\[^\n\]+:\[^\n\]*$" { set prompting 1}
+	-re "\nOK .*$prompt$" { fail "$test: premature success" }
+	-re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+	timeout { fail "$test: timeout" }
+	eof { fail "$test: eof" }
+    }
+    if {$prompting} {
+	one_line_succeed_test mrroot
+    }
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+	error_and_restart "$test: couldn't close database"
+    }
+}
+if {! $RPC} test106
+
+test "init 107"
+proc test107 {} {
+    global test
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_STASH_FILE} /does-not-exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "KDB_CANTREAD_STORED"
+}
+if {! $RPC} test107
+
+test "init 108"
+proc test108 {} {
+    global test
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_MKEY_NAME} does/not/exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "KDB_NOMASTERKEY"
+}
+if {! $RPC} test108
+
+test "init 109-113"
+proc test109 {} {
+    global test prompt
+
+    delete_principal "$test/a"
+
+    # I'd like to specify flags explicitly and check them, as in the
+    # following config_params, but tcl gets mighty confused if I do and 
+    # I have no idea why.
+#		[config_params {KADM5_CONFIG_MAX_LIFE KADM5_CONFIG_MAX_RLIFE KADM5_CONFIG_EXPIRATION KADM5_CONFIG_FLAGS KADM5_CONFIG_ENCTYPES} {10 20 30 KRB5_KDB_DISALLOW_TGT_BASED {}} ]
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_MAX_LIFE KADM5_CONFIG_MAX_RLIFE KADM5_CONFIG_EXPIRATION KADM5_CONFIG_ENCTYPES} {10 20 30 {}} ] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	fail "$test: cannot init with max_life"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test]]} {
+	fail "$test: can not create principal"
+	return;
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" p \
+		{KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+    } $test]]} {
+	fail "$test: can not get principal"
+	return;
+    }
+    send "puts \$p\n"
+    expect {
+	-re "$prompt" { }
+	timeout {
+	    error_and_restart "$test: timeout getting prompt"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting prompt"
+	    return
+	}
+    }
+    send "lindex \$p 4\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting max_life"
+	    return
+	}
+    }
+    send "lindex \$p 12\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set max_rlife $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting max_rlife"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting max_rlife"
+	    return
+	}
+    }
+    send "lindex \$p 1\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set expiration $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting expiration"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting expiration"
+	    return
+	}
+    }
+    send "lindex \$p 7\n"
+    expect {
+	-re "(\[A-Z_\]*)\n$prompt" {set flags $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting flags"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting flags"
+	    return
+	}
+    }
+    # This sorta worries me.  Since the test is setting ENCTYPES to
+    # nothing, the principal has no keys.  That means that nothing is
+    # printed for the keys in the correct case; but it feels too
+    # likely that nothing will be printed in the case of some problem.
+    send "lindex \$p 18\n"
+    expect {
+	-re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+	-re "\n$prompt" { set key_data {} }
+	timeout {
+	    error_and_restart "$test: timeout getting flags"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting flags"
+	    return
+	}
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+    if {$max_life == 10} {
+	pass "$test"
+    } else {
+	fail "$test: $max_life is not 10"
+    }
+    if {$max_rlife == 20} {
+	pass "$test"
+    } else {
+	fail "$test: $max_rlife is not 20"
+    }
+    if {$expiration == 30} {
+	pass "$test"
+    } else {
+	fail "$test: $expiration is not 30"
+    }
+    if {$flags == ""} {
+	pass "$test"
+    } else {
+	fail "$test: flags $flags are wrong"
+    }
+    if {$key_data == {}} {
+	pass "$test"
+    } else {
+	fail "$test: key_data $key_data is wrong"
+    }
+}
+if {! $RPC} test109
+
+test "init 115"
+proc test115 {} {
+    global test
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_DBNAME} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ADBNAME} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ACL_FILE} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_DICT_FILE} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ADMIN_KEYTAB} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_MKEY_FROM_KBD} 0] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_STASH_FILE} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_MKEY_NAME} does.not.exist] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ENCTYPE} 0] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_MAX_LIFE} 0] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_MAX_RLIFE} 0] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_EXPIRATION} 0] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_FLAGS} 0] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+		[config_params {KADM5_CONFIG_ENCTYPES} {{}}] \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "BAD_CLIENT_PARAMS"
+}
+if {$RPC} test115
+
+test "init 116"
+proc test116 {} {
+    global test
+
+    delete_principal "$test/a"
+
+    if {! [cmd {kadm5_init admin/get-add admin $KADM5_ADMIN_SERVICE \
+	    null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	    get_add_handle}]} {
+	error_and_restart "$test: couldn't init with admin/get-add"
+    }
+
+    if {! [cmd {kadm5_init admin/mod-delete admin $KADM5_ADMIN_SERVICE \
+	    null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	    mod_delete_handle}]} {
+	error_and_restart "$test: couldn't init with admin/get-add"
+    }
+
+    one_line_succeed_test {
+	kadm5_get_principal $get_add_handle testuser p \
+		KADM5_PRINCIPAL_NORMAL_MASK
+    }
+    one_line_succeed_test [format {
+	kadm5_create_principal $get_add_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test]
+    one_line_fail_test { 
+	kadm5_modify_principal $get_add_handle [simple_principal testuser] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } "AUTH_MODIFY"
+    one_line_fail_test {
+	kadm5_delete_principal $get_add_handle testuser
+    } "AUTH_DELETE"
+
+    one_line_fail_test {
+	kadm5_get_principal $mod_delete_handle testuser p \
+		KADM5_PRINCIPAL_NORMAL_MASK
+    } "AUTH_GET"
+    one_line_fail_test [format {
+	kadm5_create_principal $mod_delete_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    one_line_succeed_test { 
+	kadm5_modify_principal $mod_delete_handle [simple_principal testuser] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    }
+    one_line_succeed_test [format {
+	kadm5_delete_principal $mod_delete_handle "%s/a"
+    } $test]
+
+    if {! [cmd {kadm5_destroy $get_add_handle}]} {
+	error_and_restart "$test: couldn't close get_add_handle"
+    }
+    if {! [cmd {kadm5_destroy $mod_delete_handle}]} {
+	error_and_restart "$test: couldn't close mod_delete_handle"
+    }
+}
+if {$RPC} test116
+
+test "init 117"
+proc test117 {} {
+    global test env prompt
+
+    if {[catch "exec grep max_life $env(KRB5_KDC_PROFILE)"] != 1} {
+	warning \
+	   "$test: max_life in $env(KRB5_KDC_PROFILE), cannot perform test"
+	return
+    }
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+        [delete_principal "$test/a"])} {
+        error_and_restart "$test: couldn't delete principal \"$test/a\""
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	fail "$test: unexpected failure in init"
+	return
+    }
+
+    if {! [cmd [format {
+	kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL} "%s/a"
+    } $test $test]]} {
+	perror "$test: unexpected failure creating principal"
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_MAX_LIFE
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting max_life"
+	    return
+	}
+    }
+    
+    if {$max_life == 86400} {
+	pass "$test"
+    } else {
+	fail "$test: max_life $max_life should be 86400"
+    }
+
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+	error_and_restart "$test: couldn't close server_handle"
+    }
+}
+test117
+    
+send "puts \$KADM5_ADMIN_SERVICE\n"
+expect {
+    -re "(\[a-zA-Z/@\]+)\n$prompt" {
+	set KADM5_ADMIN_SERVICE $expect_out(1,string) 
+    }
+    default {
+	error_and_restart "$test: timeout/eof getting admin_service"
+	return
+    }
+}
+
+send "puts \$KADM5_CHANGEPW_SERVICE\n"
+expect {
+    -re "(\[a-zA-Z/@\]+)\n$prompt" {
+	set KADM5_CHANGEPW_SERVICE $expect_out(1,string) 
+    }
+    default {
+	error_and_restart "$test: timeout/eof getting changepw_service"
+	return
+    }
+}
+
+test "init 150"
+proc test150 {} {
+    global test KADM5_ADMIN_SERVICE
+
+    kdestroy
+    kinit testuser notathena "-S $KADM5_ADMIN_SERVICE"
+    one_line_succeed_test {
+	kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+		null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }
+    kdestroy
+}
+if {$RPC} test150
+
+test "init 151"
+proc test151 {} {
+    global test KADM5_CHANGEPW_SERVICE
+
+    kdestroy
+    kinit testuser notathena "-S $KADM5_CHANGEPW_SERVICE"
+    one_line_succeed_test {
+	kadm5_init_with_creds testuser null $KADM5_CHANGEPW_SERVICE \
+		null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }
+    kdestroy
+}
+if {$RPC} test151
+
+test "init 152"
+proc test152 {} {
+    global test KADM5_ADMIN_SERVICE
+
+    kdestroy
+    one_line_fail_test {
+	kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+		null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "KRB5_FCC_NOFILE"
+}
+if {$RPC} test152
+
+test "init 153"
+proc test153 {} {
+    global test KADM5_ADMIN_SERVICE
+
+    kinit testuser notathena
+    one_line_fail_test {
+	kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+		null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "KRB5_CC_NOTFOUND"
+}
+if {$RPC} test153
+
+test "init 154"
+proc test154 {} {
+    global test env
+
+    set orig $env(KRB5_KDC_PROFILE)
+    set env(KRB5_KDC_PROFILE) /does-not-exist
+    api_exit; api_start
+    set env(KRB5_KDC_PROFILE) $orig
+
+    one_line_fail_test {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } "ENOENT"
+
+    api_exit; lib_start_api
+}
+if {0 && ! $RPC} test154
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/init.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/init.exp
new file mode 100644
index 000000000..335f6e041
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/init.exp
@@ -0,0 +1,732 @@
+load_lib lib.t
+
+# Assumptions:
+# 
+# Principal "admin" exists, with "get", "add", "modify" and "delete"
+#   access bits and password "admin".
+# The string "not-the-password" isn't the password of any user in the database.
+# Database master password is "mrroot".
+
+api_exit
+api_start
+test "init 1"
+
+one_line_fail_test_nochk \
+	{kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+	[config_params {KADM5_CONFIG_REALM} {""}] \
+	 $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle}
+
+test "init 2"
+
+one_line_fail_test_nochk \
+	{kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+	[config_params {KADM5_CONFIG_REALM} {@}] \
+	 $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle}
+
+test "init 2.5"
+
+one_line_fail_test_nochk \
+	{kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+	[config_params {KADM5_CONFIG_REALM} {BAD.REALM}] \
+	 $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle}
+
+test "init 3"
+
+proc test3 {} {
+    global test
+    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+	error_and_restart "$test: couldn't create principal \"$test/a\""
+	return
+    }
+    one_line_fail_test_nochk [format {
+	kadm5_init admin admin "%s/a" null $KADM5_STRUCT_VERSION \
+		$KADM5_API_VERSION_2 server_handle
+    } $test]
+}
+if {$RPC} { test3 }
+
+test "init 4"
+
+proc test4 {} {
+    global test
+	if {! ((! [principal_exists "$test/a"]) || 
+         [delete_principal "$test/a"])} {
+		error_and_restart "$test: couldn't delete principal \"$test/a\""
+		return
+	}
+		
+	one_line_fail_test_nochk [format {
+	    kadm5_init admin admin "%s/a" null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	} $test]
+}
+if {$RPC} { test4 }
+
+test "init 5"
+
+if {$RPC} {
+    one_line_fail_test_nochk {
+	kadm5_init admin admin admin null $KADM5_STRUCT_VERSION \
+		$KADM5_API_VERSION_2 server_handle
+    }
+}
+
+test "init 6"
+
+proc test6 {} {
+    global test
+
+    send "kadm5_init admin null \$KADM5_ADMIN_SERVICE null \$KADM5_STRUCT_VERSION \$KADM5_API_VERSION_2 server_handle\n"
+
+    expect {
+	-re "assword\[^\r\n\]*:" { }
+	eof {
+		fail "$test: eof instead of password prompt"
+		api_exit
+		api_start
+		return
+	}
+	timeout {
+	    fail "$test: timeout instead of password prompt"
+	    return
+	}
+    }
+    one_line_succeed_test "admin"
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+	error_and_restart "$test: couldn't close database"
+    }
+}
+if { $RPC } { test6 } 
+
+test "init 7"
+proc test7 {} {
+    global test
+
+    send "kadm5_init admin \"\" \$KADM5_ADMIN_SERVICE null \$KADM5_STRUCT_VERSION \$KADM5_API_VERSION_2 server_handle\n"
+
+    expect {
+	-re "assword\[^\r\n\]*:" { }
+	-re "key:$" { }
+	eof {
+		fail "$test: eof instead of password prompt"
+		api_exit
+		api_start
+		return
+	}
+	timeout {
+	    fail "$test: timeout instead of password prompt"
+	    return
+	}
+    }
+    one_line_succeed_test "admin"
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+	error_and_restart "$test: couldn't close database"
+    }
+}
+if { $RPC } { test7 } 
+
+test "init 8"
+
+proc test8 {} {
+    global test
+	if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+		error_and_restart "$test: couldn't create principal \"$test/a\""
+		return
+	}
+ 	one_line_fail_test_nochk [format {
+	    kadm5_init "%s/a" admin $KADM5_ADMIN_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	} $test]
+}
+if {$RPC} { test8 }
+
+test "init 9"
+
+if {$RPC} {
+    global test
+  one_line_fail_test_nochk {
+      kadm5_init admin not-the-password $KADM5_ADMIN_SERVICE null \
+	      $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	      server_handle
+  }
+}
+
+test "init 10"
+
+proc test10 {} {
+	global test
+#	set prms_id 562
+#	setup_xfail {*-*-*} $prms_id
+	one_line_fail_test_nochk {
+	    kadm5_init null admin $KADM5_ADMIN_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+}
+test10
+
+#test "init 11"
+#
+#proc test11 {} {
+#	global test
+#	set prms_id 563
+#	setup_xfail {*-*-*} $prms_id
+#	one_line_fail_test_nochk {
+#	    kadm5_init "" admin $KADM5_ADMIN_SERVICE null \
+#		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		    server_handle
+#	}
+#}
+#test11
+
+test "init 12"
+
+proc test12 {} {
+	global test
+    one_line_fail_test_nochk [format {
+	kadm5_init "%s/a" admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } $test]
+}
+if {$RPC} { test12 }
+
+test "init 13"
+
+proc test13 {} {
+	global test
+    one_line_fail_test_nochk [format {
+	kadm5_init "%s/a@SECURE-TEST.OV.COM" admin \
+		$KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION \
+		$KADM5_API_VERSION_2 server_handle
+    } $test]
+}
+if {$RPC} { test13 }
+
+test "init 14"
+
+proc test14 {} {
+	global test
+    one_line_fail_test_nochk [format {
+	kadm5_init "%s/a@BAD.REALM" admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } $test]
+}
+if {$RPC} { test14 }
+
+test "init 15"
+
+if {$RPC} {
+    one_line_fail_test_nochk {
+	kadm5_init admin@BAD.REALM admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }
+}
+
+test "init 16"
+
+proc test16 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test16
+
+test "init 17"
+
+proc test17 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin@SECURE-TEST.OV.COM admin \
+		    $KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION \
+		    $KADM5_API_VERSION_2 server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test17
+
+test "init 18"
+
+proc test18 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test18
+
+test "init 19"
+
+proc test19 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin@SECURE-TEST.OV.COM admin \
+		    $KADM5_ADMIN_SERVICE \
+		    [config_params {KADM5_CONFIG_REALM} {SECURE-TEST.OV.COM}] \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test19
+
+test "init 20"
+
+proc test20 {} {
+	global test
+  if {! [cmd {
+      kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	      $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	      server_handle
+  }]} {
+		error_and_restart "$test: couldn't init database"
+		return
+	}
+	one_line_succeed_test \
+		{kadm5_get_principal $server_handle admin principal KADM5_PRINCIPAL_NORMAL_MASK}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test20
+
+#test "init 21"
+#
+#proc test21 {} {
+#    global test
+#    if {! [cmd {
+#	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+#		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		server_handle
+#    }]} {
+#	error_and_restart "$test: couldn't init database"
+#	return
+#    }
+#    one_line_fail_test_nochk {
+#	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		server_handle
+#    }
+#    if {! [cmd {kadm5_destroy $server_handle}]} {
+#	error_and_restart "$test: couldn't close database"
+#    }
+#}
+#test21
+
+
+# proc test22 {} {
+# 	global test prompt
+# 	set prompting 0
+# 	send [string trim {
+# 	    kadm5_init admin null null null $KADM5_STRUCT_VERSION \
+# 		    $KADM5_API_VERSION_2 server_handle
+# 	}]
+# 	send "\n"
+# 	expect {
+# 	    -re ":$" { set prompting 1}
+# 	    -re "\nOK .*$prompt$" { fail "$test: premature success" }
+# 	    -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+# 		timeout { fail "$test: timeout" }
+# 		eof { fail "$test: eof" }
+# 	}
+# 	if {$prompting} {
+# 	    one_line_succeed_test mrroot
+# 	}
+# 	if {! [cmd {kadm5_destroy $server_handle}]} {
+# 	    error_and_restart "$test: couldn't close database"
+# 	}
+# }
+# if {! $RPC} { test22 }
+# 
+# test "init 22.5"
+# proc test225 {} {
+# 	global test prompt
+# 	set prompting 0
+# 	send [string trim {
+# 	    kadm5_init admin null null null $KADM5_STRUCT_VERSION \
+# 		    $KADM5_API_VERSION_2 server_handle
+# 	}]
+# 	send "\n"
+# 	expect {
+# 	    -re ":$" { set prompting 1}
+# 	    -re "\nOK .*$prompt$" { fail "$test: premature success" }
+# 	    -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+# 		timeout { fail "$test: timeout" }
+# 		eof { fail "$test: eof" }
+# 	}
+# 	if {$prompting} {
+# 	    one_line_succeed_test mrroot
+# 	}
+# 	if {! [cmd {kadm5_destroy $server_handle}]} {
+# 	    error_and_restart "$test: couldn't close database"
+# 	}
+# }
+# if {! $RPC} { test225 }
+
+test "init 23"
+
+proc test23 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin not-the-password $KADM5_ADMIN_SERVICE \
+		    null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test23 }
+
+test "init 24"
+
+proc test24 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin admin null null $KADM5_STRUCT_VERSION \
+		    $KADM5_API_VERSION_2 server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test24 }
+
+test "init 25"
+
+proc test25 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin admin foobar null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if {! $RPC} { test25 }
+
+test "init 26"
+
+#proc test26 {} {
+#	global test
+#
+#	api_exit
+#	api_start
+#	one_line_fail_test_nochk {
+#	    kadm5_get_principal $server_handle admin principal
+#	}
+#}
+#test26
+
+#test "init 27"
+#
+#proc test27 {} {
+#	global test
+#
+#	if {! ((! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+#		error_and_restart "$test: couldn't delete principal \"$test/a\""
+#		return
+#	}
+#	begin_dump
+#	if {[cmd [format {
+#	    kadm5_create_principal $server_handle [simple_principal \
+#		    "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+#	} $test $test]]} {
+#		fail "$test: unexpected success in add"
+#		return
+#	}
+#	end_dump_compare "no-diffs"
+#}
+#test27
+
+#test "init 28"
+#
+#proc test28 {} {
+#    global test prompt
+#
+#    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#	error_and_restart "$test: couldn't create principal \"$test/a\""
+#	return
+#    }
+#    begin_dump
+#    if {! ([cmd {
+#	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+#		server_handle
+#    }] && [cmd [format {
+#	kadm5_get_principal $server_handle "%s/a" principal
+#    } $test]])} {
+#	error_and_restart "$test: error getting principal"
+#	return;
+#    }
+#    send "lindex \$principal 8\n"
+#    expect {
+#	-re "\n(\[0-9\]+).*$prompt$" {set kvno $expect_out(1,string) }
+#	timeout {
+#	    error_and_restart "$test: timeout getting principal kvno"
+#	    return
+#	}
+#	eof {
+#	    error_and_restart "$test: eof getting principal kvno"
+#	    return
+#	}
+#    }
+#    api_exit
+#    api_start
+#    set new_kvno [expr "$kvno + 1"]
+#    if {[cmd [format {
+#	kadm5_modify_principal $server_handle \
+#		{"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {KADM5_KVNO}
+#    } $test $new_kvno]]} {
+#	fail "$test: unexpected success in modify"
+#	return;
+#    }
+#    end_dump_compare "no-diffs"
+#}
+#test28
+
+#test "init 29"
+#
+#proc test29 {} {
+#    global test
+#
+#    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#	error_and_restart "$test: couldn't create principal \"$test/a\""
+#	return
+#    }
+#    begin_dump
+#    if {[cmd [format {
+#	kadm5_delete_principal $server_handle "%s/a"
+#    } $test]]} {
+#	fail "$test: unexpected success in delete"
+#	return
+#    }
+#    end_dump_compare "no-diffs"
+#}
+#test29
+
+test "init 30"
+proc test30 {} {
+	global test
+	if {[cmd {
+	    kadm5_init admin foobar $KADM5_ADMIN_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}]} {
+		error_and_restart "$test: unexpected success"
+		return
+	}
+	one_line_succeed_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+if ${RPC} { test30 }
+
+test "init 31"
+proc test31 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $bad_struct_version_mask $KADM5_API_VERSION_2 \
+		    server_handle
+	} "BAD_STRUCT_VERSION" 
+}
+test31
+
+test "init 32"
+proc test32 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $no_struct_version_mask $KADM5_API_VERSION_2 \
+		    server_handle
+	} "BAD_STRUCT_VERSION" 
+}
+test32
+
+test "init 33"
+proc test33 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $old_struct_version $KADM5_API_VERSION_2 \
+		    server_handle
+	} "OLD_STRUCT_VERSION" 
+}
+test33
+
+test "init 34"
+proc test34 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $new_struct_version $KADM5_API_VERSION_2 \
+		    server_handle
+	} "NEW_STRUCT_VERSION" 
+}
+test34
+
+test "init 35"
+proc test35 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_STRUCT_VERSION $bad_api_version_mask \
+		    server_handle
+	} "BAD_API_VERSION" 
+}
+test35
+
+test "init 36"
+proc test36 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_STRUCT_VERSION $no_api_version_mask \
+		    server_handle
+	} "BAD_API_VERSION" 
+}
+test36
+
+test "init 37"
+proc test37 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_STRUCT_VERSION $old_api_version \
+		    server_handle
+	} "OLD_LIB_API_VERSION" 
+}
+if { $RPC } test37
+
+test "init 38"
+proc test38 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_STRUCT_VERSION $old_api_version \
+		    server_handle
+	} "OLD_SERVER_API_VERSION" 
+}
+if { ! $RPC } test38
+
+test "init 39"
+proc test39 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_STRUCT_VERSION $new_api_version \
+		    server_handle
+	} "NEW_LIB_API_VERSION" 
+}
+if { $RPC } test39
+
+test "init 40"
+proc test40 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_STRUCT_VERSION $new_api_version \
+		    server_handle
+	} "NEW_SERVER_API_VERSION" 
+}
+if { ! $RPC } test40
+
+test "init 41"
+proc test41 {} {
+	global test
+	one_line_fail_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_API_VERSION_2 $KADM5_STRUCT_VERSION \
+		    server_handle
+	} "BAD_"
+}
+test41
+
+test "init 42"
+proc test42 {} {
+	global test
+	one_line_succeed_test {
+	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+	    	    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    server_handle
+	}
+	if {! [cmd {kadm5_destroy $server_handle}]} {
+		error_and_restart "$test: couldn't close database"
+	}
+}
+test42
+
+
+proc test45_46 {service} {
+    global test kadmin_local env
+
+    spawn $kadmin_local -q "delprinc -force $service"
+    expect {
+	-re "Principal .* deleted." {}
+	default {
+	    perror "kadmin.local delprinc failed\n";
+	}
+    }
+    expect eof
+    wait
+
+    one_line_fail_test [concat {kadm5_init admin admin } \
+	    $service \
+	    { null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+	    server_handle}] "SECURE_PRINC_MISSING"
+
+    # this leaves the keytab with an incorrect entry
+    spawn $kadmin_local -q "ank -randkey $service"
+    expect eof
+    wait
+
+    # restart the api so it gets a new ccache
+    api_exit
+    api_start
+}
+
+if {$RPC} {
+    test "init 45"
+
+    test45_46 ovsec_adm/admin
+
+    test "init 46"
+
+    test45_46 ovsec_adm/changepw
+
+    # re-extract the keytab so it is right
+    exec rm $env(K5ROOT)/ovsec_adm.srvtab
+    exec $env(MAKE_KEYTAB) -princ ovsec_adm/admin -princ ovsec_adm/changepw \
+	    -princ kadmin/admin -princ kadmin/changepw \
+	    $env(K5ROOT)/ovsec_adm.srvtab
+}
+
+return ""
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-policy.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-policy.exp
new file mode 100644
index 000000000..2cc168648
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-policy.exp
@@ -0,0 +1,703 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "modify-policy 2"
+proc test2 {} {
+    global test
+
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test2 }
+
+test "modify-policy 4"
+proc test4 {} {
+    global test
+    
+    if {! ([policy_exists "$test/a"] ||
+	   [create_policy "$test/a"])} {
+            error_and_restart "$test: couldn't create policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_REF_COUNT}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test4
+
+test "modify-policy 8"
+proc test8 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_modify_policy $server_handle [simple_policy ""] \
+		{KADM5_PW_MAX_LIFE}
+    } "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test8
+
+test "modify-policy 9"
+proc test9 {} {
+    global test
+    global prompt
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MIN_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+test "modify-policy 10"
+proc test10 {} {
+    global test
+    global prompt
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle {"%s/a" 32 0 0 0 0 0} \
+		{KADM5_PW_MIN_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+
+test "modify-policy 11"
+proc test11 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MAX_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test11
+
+test "modify-policy 12"
+proc test12 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle {"%s/a" 0 32 0 0 0 0} \
+		{KADM5_PW_MAX_LIFE}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "32\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test12
+
+test "modify-policy 13"
+proc test13 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MIN_LENGTH}
+    } $test] "BAD_LENGTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+test "modify-policy 14"
+proc test14 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle {"%s/a" 0 0 8 0 0 0} \
+		{KADM5_PW_MIN_LENGTH}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 3\n"
+    expect {
+	-re "8\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test14
+
+test "modify-policy 15"
+proc test15 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+test "modify-policy 16"
+proc test16 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle {"%s/a" 0 0 0 1 0 0} \
+		{KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test16
+
+test "modify-policy 17"
+proc test17 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a"])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+		{KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+	-re "5\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+test "modify-policy 18"
+proc test18 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+		{KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test18
+
+test "modify-policy 19"
+proc test19 {} {
+    global test
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test19
+
+test "modify-policy 20"
+proc test20 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+		{KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "1\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test20
+
+test "modify-policy 21"
+proc test21 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+		{KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+	fail $test
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+	fail "$test: can not retrieve policy"
+	return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+	-re "10\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21
+
+test "modify-policy 22"
+proc test22 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test22
+
+test "modify-policy 23"
+proc test23 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} test23
+
+test "modify-policy 26"
+proc test26 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+	   [create_policy "$test/a" ])} {
+	    error_and_restart "$test: couldn't create policy \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+		{KADM5_PW_MAX_LIFE}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test26
+
+test "modify-policy 30"
+proc test30 {} {
+    global test
+
+    one_line_fail_test [format {
+	kadm5_modify_policy null [simple_policy "%s/a"] \
+		{KADM5_PW_MAX_LIFE}
+    } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp
new file mode 100644
index 000000000..44c835e57
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp
@@ -0,0 +1,114 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "modify-principal 100-105"
+proc test100_104 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+
+    set origtest "$test"
+
+    test "modify-principal 100"
+    one_line_succeed_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MAX_RLIFE}
+    } $origtest]
+
+    test "modify-principal 101"
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_LAST_SUCCESS}
+    } $origtest] "BAD_MASK"
+
+    test "modify-principal 102"
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_LAST_FAILED}
+    } $origtest] "BAD_MASK"
+
+    test "modify-principal 103"
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_FAIL_AUTH_COUNT}
+    } $origtest] "BAD_MASK"
+
+    test "modify-principal 103.5"
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_KEY_DATA}
+    } $origtest] "BAD_MASK"
+
+    test "modify-principal 105"
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle \
+            "{%s/a} 0 0 0 0 {%s/a} 0 0 0 0 null 0 0 0 0 0 0 1 {} {{1 1 x}}" \
+		{KADM5_TL_DATA}
+    } $origtest $origtest] "BAD_TL_TYPE"
+
+    test "modify-principal 100,104"
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		"{%s/a} 0 0 0 0 {%s/a} 0 0 0 0 null 0 88 0 0 0 0 1 {} {{990 6 foobar}}" \
+		{KADM5_MAX_RLIFE KADM5_TL_DATA}
+    } $origtest $origtest]]} {
+	fail "$test: cannot set MAX_RLIFE or TL_DATA"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal {KADM5_PRINCIPAL_NORMAL_MASK KADM5_TL_DATA}
+    } $origtest]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 12\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set rlife $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting rlife"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting rlife"
+	    return
+	}
+    }
+    send "lindex \$principal 19\n"
+    expect {
+	-re "\(\{.*\}\)\n$prompt$" {set tl $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting tl_data"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting tl_data"
+	    return
+	}
+    }
+    if {($rlife == 88) && ($tl == "{{990 6 foobar}}")} {
+	pass "$test"
+    } else {
+	fail "$test: $rlife should be 88, $tl should be {{990 6 foobar}}"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test100_104
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal.exp
new file mode 100644
index 000000000..4472c78ce
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/mod-principal.exp
@@ -0,0 +1,1942 @@
+load_lib lib.t
+api_exit
+api_start
+
+#test "modify-principal 1"
+#proc test1 {} {
+#	global test
+#	one_line_fail_test [format {
+#	    kadm5_modify_principal $server_handle [simple_principal \
+#		    "%s/a"] {KADM5_PW_EXPIRATION}
+#	} $test] "NOT_INIT"
+#}
+#test1
+
+test "modify-principal 2"
+proc test2 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test2 }
+
+test "modify-principal 4"
+proc test4 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINCIPAL}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test4
+
+
+test "modify-principal 5"
+proc test5 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_LAST_PWD_CHANGE}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test5
+
+test "modify-principal 6"
+proc test6 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MOD_TIME}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test6
+
+test "modify-principal 7"
+proc test7 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MOD_NAME}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test7
+
+test "modify-principal 8"
+proc test8 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MKVNO}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test8
+
+test "modify-principal 9"
+proc test9 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_AUX_ATTRIBUTES}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test9
+
+test "modify-principal 10"
+proc test10 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test] "UNK_PRINC"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test10
+
+test "modify-principal 11"
+proc test11 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test11 }
+
+test "modify-principal 12"
+proc test12 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test12 }
+
+test "modify-principal 13"
+proc test13 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test13 }
+
+test "modify-principal 14"
+proc test14 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test14 }
+
+test "modify-principal 15"
+proc test15 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test15
+
+test "modify-principal 17"
+proc test17 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		no-policy] {KADM5_POLICY}
+    } $test] "UNK_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test17
+
+test "modify-principal 18"
+proc test18 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal "$test/a"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {KADM5_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref + 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test18
+
+test "modify-principal 19"
+proc test19 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal "$test/a"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {KADM5_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref + 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test19
+
+test "modify-principal 20"
+proc test20 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_POLICY_CLR}
+    } $test]]} {
+	perror "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ fail "$test" }
+	timeout				{ pass "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$oldref - 1"] != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test20
+
+test "modify-principal 21"
+proc test21 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol old_p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol-nopw old_p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol-nopw] {KADM5_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$old_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    send "lindex \$old_p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set old_p2_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol new_p1}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol-nopw new_p2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$new_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    send "lindex \$new_p2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set new_p2_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { [expr "$old_p1_ref - 1"] != $new_p1_ref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { [expr "$old_p2_ref + 1"] != $new_p2_ref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21
+
+test "modify-principal 21.5"
+proc test21.5 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol old_p1}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {KADM5_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$old_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol new_p1}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    
+    send "lindex \$new_p1 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+
+    if {$old_p1_ref != $new_p1_ref} {
+	fail "$test: policy reference count changed ($old_p1_ref to $new_p1_ref)"
+	return
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test21.5
+
+test "modify-principal 22"
+proc test22 {} {
+    global test
+    global prompt
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modifiy failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test22
+
+test "modify-principal 23"
+proc test23 {} {
+    global test
+    global prompt
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" test-pol-nopw])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modifiy failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test23
+
+test "modify-principal 24"
+proc test24 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	error_and_restart "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PW_EXPIRATION}
+    } $test]]} {
+    	fail "$test: could not modify principal"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_get_policy $server_handle %s policy
+    } test-pol]]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 0 } {
+	fail "$test: pw_expire $pw_expire should be 0"
+	return
+    } else {
+	pass "$test"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} { 
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test24
+
+test "modify-principal 25"
+proc test25 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test25
+
+test "modify-principal 26"
+proc test26 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol-nopw" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test26
+
+test "modify-principal 27"
+proc test27 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test27
+
+test "modify-principal 28"
+proc test28 {} {
+    global test
+    global prompt
+#    set prms_id 1358
+#    setup_xfail {*-*-*} $prms_id    
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal_pol "$test/a" "test-pol" ])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 999999999 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { $pw_expire != 999999999 } {
+	fail "$test: pw_expire $pw_expire should be 999999999"
+	return
+    }
+    pass "$test"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test28
+
+test "modify-principal 29"
+proc test29 {} {
+    global test
+    global prompt
+    
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { ! ([create_principal_pol "$test/a" test-pol])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_POLICY_CLR}
+    } $test]]} {
+	fail "$test: modifiy failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test29
+
+test "modify-principal 30"
+proc test30 {} {
+    global test
+    global prompt
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal_pol "$test/a" test-pol])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol-nopw] {KADM5_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test30
+
+test "modify-principal 31"
+proc test31 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {KADM5_POLICY}
+    } $test]]} {
+	fail "modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+	error_and_restart "$test: cannot retrieve policy"
+	return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_mod_date"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_mod_date"
+	    return
+	}
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_expire"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_expire"
+	    return
+	}
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting pw_max_life"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting pw_max_life"
+	    return
+	}
+    }
+    if { [expr "$pw_mod_date + $pw_max_life"] != $pw_expire } {
+	fail "$test: pw_expire is wrong"
+	return
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test31
+
+test "modify-principal 32"
+proc test32 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	error_and_restart "$test: couldn't delete principal \"$test/a\""
+	return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 1234 0 0 0 0 0 0 0 0 0 0} \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 1\n"
+    expect {
+	-re "1234\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test32
+
+test "modify-principal 33"
+proc test33 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_ALL_TIX 0 0 0 0} \
+		{KADM5_ATTRIBUTES}
+    } $test]]} {
+	fail "$test: modified fail"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+	-re "KRB5_KDB_DISALLOW_ALL_TIX.*$prompt$"		{ pass "$test" }
+	timeout							{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test33
+
+test "modify-principal 33.25"
+proc test3325 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 KRB5_KDB_REQUIRES_PWCHANGE 0 0 0 0} \
+		{KADM5_ATTRIBUTES}
+    } $test]]} {
+	fail "$test: modified fail"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+	-re "KRB5_KDB_REQUIRES_PWCHANGE.*$prompt$"		{ pass "$test" }
+	timeout							{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test3325
+
+test "modify-principal 33.5"
+proc test335 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_TGT_BASED 0 0 0 0} \
+		{KADM5_ATTRIBUTES}
+    } $test]]} {
+	fail "$test: modified fail"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+	-re "KRB5_KDB_DISALLOW_TGT_BASED.*$prompt$"		{ pass "$test" }
+	timeout							{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test335
+
+
+test "modify-principal 34"
+proc test34 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 0 3456 0 0 0 0 0 0 0} {KADM5_MAX_LIFE}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+	-re "3456\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test34
+
+test "modify-principal 35"
+proc test35 {} {
+    global prompt
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd [format {
+	kadm5_modify_principal $server_handle \
+		{"%s/a" 0 0 0 0 0 0 0 7 0 0 0} {KADM5_KVNO}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 8\n"
+    expect {
+	-re "7\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test35
+
+test "modify-principal 36"
+proc test36 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol pol}]}  {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		test-pol] {KADM5_POLICY}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+	-re "test-pol\n$prompt$"	{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    send "lindex \$pol 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol pol2}]} {
+	perror "$test: unexpected failure on get policy"
+	return
+    }
+    send "lindex \$pol2 6\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting principal kvno (second time)"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting principal kvno (second time)"
+	    return
+	}
+    }
+    if { $oldref != $newref } {
+	fail "$test: policy reference count is wrong"
+	return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test36
+
+test "modify-principal 37"
+proc test37 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if { !( [create_principal "$test/a"])} {
+	error_and_restart "$test: could not create principal \"$test/a\""
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_POLICY_CLR}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test37
+
+test "modify-principal 38"
+proc test38 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 1\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test38
+
+test "modify-principal 39"
+proc test39 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! ([create_principal "$test/a"])} {
+	perror "$test: unexpected failure in creating principal"
+	return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+		{KADM5_MAX_LIFE}
+    } $test]]} {
+	fail "$test: modify failed"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+	error_and_restart "$test: could not retrieve principal"
+	return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+	-re "0\n$prompt$"		{ pass "$test" }
+	timeout				{ fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test39
+
+test "modify-principal 40"
+proc test40 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_modify_principal $server_handle null \
+		{KADM5_PRINC_EXPIRE_TIME}
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test40
+
+test "modify-principal 43"
+proc test43 {} {
+	global test
+	one_line_fail_test [format {
+	    kadm5_modify_principal null [simple_principal \
+		    "%s/a"] {KADM5_PW_EXPIRATION}
+	} $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp
new file mode 100644
index 000000000..c9d1104bc
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp
@@ -0,0 +1,62 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "randkey-principal 100"
+proc test100 {} {
+    global test prompt
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal "$test/a"]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+
+    # I'd like to specify a long list of keysalt tuples and make sure
+    # that randkey does the right thing, but we can only use those
+    # enctypes that krbtgt has a key for: des-cbc-crc:normal and
+    # des-cbc-crc:v4, according to the prototype kdc.conf.
+    if {! [cmd [format {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]]} {
+	perror "$test: unexpected failure in randkey_principal"
+    }
+    send "puts \$num_keys\n"
+    expect {
+	-re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+	timeout {
+	    error_and_restart "$test: timeout getting num_keys"
+	    return
+	}
+	eof {
+	    error_and_restart "$test: eof getting num_keys"
+	    return
+	}
+    }
+
+    # XXX Perhaps I should actually check the key type returned.
+    if {$num_keys == 2} {
+	pass "$test"
+    } else {
+	fail "$test: $num_keys keys, should be 2"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test100
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal.exp b/krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal.exp
new file mode 100644
index 000000000..ecf79e476
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/api.2/randkey-principal.exp
@@ -0,0 +1,319 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "randkey-principal 1"
+proc test1 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd [format {
+	kadm5_init "%s/a" "%s/a" $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "PASS_TOOSOON"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test1 } 
+
+test "randkey-principal 3"
+proc test3 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd [format {
+	kadm5_init "%s/a" "%s/a" $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "PASS_TOOSOON"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if ${RPC} { test3 } 
+
+test "randkey-principal 13"
+proc test13 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+		once-a-min] KADM5_POLICY
+    } $test]]} {
+	perror "$test: failed modify"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test13
+
+test "randkey-principal 15"
+proc test15 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "AUTH_CHANGEPW"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if { $RPC } { test15 }
+
+test "randkey-principal 28"
+proc test28 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test28
+
+test "randkey-principal 28.25"
+proc test2825 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "AUTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+if {$RPC} { test2825 }
+
+test "randkey-principal 28.5"
+proc test285 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [cmd {
+	kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test285
+
+test "randkey-principal 30"
+proc test30 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't delete principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal "$test/a"]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    if {! [cmd [format {
+	kadm5_init "%s/a" "%s/a" $KADM5_CHANGEPW_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test30
+
+test "randkey-principal 31"
+proc test31 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+	   [delete_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if {! [create_principal "$test/a"]} {
+	error_and_restart "$test: creating principal"
+	return
+    }
+    
+    if {! [cmd [format {
+	kadm5_init "%s/a" "%s/a" $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    } $test $test]]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_succeed_test [format {
+	kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test31
+
+test "randkey-principal 32"
+proc test32 {} {
+    global test
+
+    if { ! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test {
+	kadm5_randkey_principal $server_handle kadmin/history keys num_keys
+    } "PROTECT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+test32
+
+test "randkey-principal 33"
+proc test33 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+	   [create_principal "$test/a"])} {
+	    error_and_restart "$test: couldn't create principal \"$test/a\""
+	    return
+    }
+    if { ! [cmd {
+	kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		server_handle
+    }]} {
+	perror "$test: unexpected failure in init"
+	return
+    }
+    one_line_fail_test [format {
+	kadm5_randkey_principal null "%s/a" keys num_keys
+    } $test] "BAD_SERVER_HANDLE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+	perror "$test: unexpected failure in destroy"
+	return
+    }
+}
+
+test33
+
+return ""
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/config/unix.exp b/krb5-1-6/src/lib/kadm5/unit-test/config/unix.exp
new file mode 100644
index 000000000..a78515f91
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/config/unix.exp
@@ -0,0 +1,179 @@
+set prompt "% "
+set stty_init {-onlcr -opost intr \^C kill \^U}
+set kadmin_local $KADMIN_LOCAL
+
+# Backward compatibility until we're using expect 5 everywhere
+if {[info exists exp_version_4]} {
+	global wait_error_index wait_errno_index wait_status_index
+	set wait_error_index 0
+	set wait_errno_index 1
+	set wait_status_index 1
+} else {
+	set wait_error_index 2
+	set wait_errno_index 3
+	set wait_status_index 3
+}
+
+# Hack around Solaris 9 kernel race condition that causes last output
+# from a pty to get dropped.
+if { $PRIOCNTL_HACK } {
+    catch {exec priocntl -s -c FX -m 30 -p 30 -i pid [getpid]}
+    rename spawn oldspawn
+    proc spawn { args } {
+	upvar 1 spawn_id spawn_id
+	set newargs {}
+	set inflags 1
+	set eatnext 0
+	foreach arg $args {
+	    if { $arg == "-ignore" \
+		     || $arg == "-open" \
+		     || $arg == "-leaveopen" } {
+		lappend newargs $arg
+		set eatnext 1
+		continue
+	    }
+	    if [string match "-*" $arg] {
+		lappend newargs $arg
+		continue
+	    }
+	    if { $eatnext } {
+		set eatnext 0
+		lappend newargs $arg
+		continue
+	    }
+	    if { $inflags } {
+		set inflags 0
+		set newargs [concat $newargs {priocntl -e -c FX -p 0}]
+	    }
+	    lappend newargs $arg
+	}
+	set pid [eval oldspawn $newargs]
+	return $pid
+    }
+}
+
+# Variables for keeping track of api process state
+set api_pid "0"
+
+proc api_exit {} {
+	global spawn_id
+        global api_pid
+
+#	puts stdout "Starting api_exit (spawn_id $spawn_id)."
+	catch {close} errMsg
+        catch {wait} errMsg
+#       puts stdout "Finishing api_exit for $api_pid."
+        set api_pid "0"
+}
+
+proc api_isrunning {pid} {
+        global api_pid
+    
+#        puts stdout "testing $pid, api_pid is $api_pid"
+        if {$pid == $api_pid} {
+	    return 1;
+	} else {
+	    return 0;
+	}
+}
+
+proc api_version {} {
+}
+
+proc api_start {} {
+	global API 
+	global env
+	global spawn_id
+	global prompt
+        global api_pid
+
+	set pid [spawn $API]
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF starting API" }
+		timeout { error "Timeout starting API" }
+	}
+	if {! [info exists env(TCLUTIL)]} {
+		error "TCLUTIL environment variable isn't set"
+	}
+	# tcl 8.4 for some reason screws up autodetection of output
+	# EOL translation.  Work around it for now.
+	send "if { \[info commands fconfigure\] ne \"\" } { fconfigure stdout -translation lf }\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF starting API" }
+		timeout { error "Timeout starting API" }
+	}
+	send "source $env(TCLUTIL)\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF starting API" }
+		timeout { error "Timeout starting API" }
+	}
+	send "set current_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION &~ \$OVSEC_KADM_STRUCT_VERSION_MASK\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set current_api_version \[expr \$OVSEC_KADM_API_VERSION_1 &~ \$OVSEC_KADM_API_VERSION_MASK\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set bad_struct_version_mask \[expr 0x65432100 | \$current_struct_version\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set bad_api_version_mask \[expr 0x65432100 | \$current_api_version\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set no_api_version_mask \$current_api_version\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set no_struct_version_mask \$current_struct_version\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set old_api_version \[expr \$OVSEC_KADM_API_VERSION_MASK | 0x00\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set old_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION_MASK | 0x00\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set new_api_version \[expr \$OVSEC_KADM_API_VERSION_MASK | 0xca\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+	send "set new_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION_MASK | 0xca\]\n"
+	expect {
+		-re "$prompt$" {}
+		eof { error "EOF setting API varibles"}
+		timeout { error "timeout setting API varibles"}
+	}
+
+	set api_pid $pid
+#	puts stdout "Finishing api_start (spawn_id $spawn_id, pid $api_pid)."
+	return $pid
+}
+api_start
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/destroy-test.c b/krb5-1-6/src/lib/kadm5/unit-test/destroy-test.c
new file mode 100644
index 000000000..6d7435c45
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/destroy-test.c
@@ -0,0 +1,42 @@
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <krb5.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <kadm5/client_internal.h>
+#include <string.h>
+
+#define	TEST_NUM    25
+
+int main()
+{
+     ovsec_kadm_ret_t ret;
+     char   *cp;
+     int    x;
+     void *server_handle;
+     kadm5_server_handle_t handle;
+
+     for(x = 0; x < TEST_NUM; x++) {
+	ret = ovsec_kadm_init("admin", "admin", "ovsec_adm/admin", 0,
+			      OVSEC_KADM_STRUCT_VERSION,
+			      OVSEC_KADM_API_VERSION_1, NULL,
+			      &server_handle);
+	if(ret != OVSEC_KADM_OK) {
+	    com_err("test", ret, "init");
+	    exit(2);
+	}
+	handle = (kadm5_server_handle_t) server_handle;
+	cp = (char *) strdup(((char *) (strchr(handle->cache_name, ':')) + 1));
+	ovsec_kadm_destroy(server_handle);
+	if(access(cp, F_OK) == 0) {
+	    puts("ticket cache not destroyed");
+	    exit(2);
+	}
+	free(cp);
+     }
+     exit(0);
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/diff-files/destroy-1 b/krb5-1-6/src/lib/kadm5/unit-test/diff-files/destroy-1
new file mode 100644
index 000000000..593d67320
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/diff-files/destroy-1
@@ -0,0 +1,2 @@
+##! nochanges
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/diff-files/no-diffs b/krb5-1-6/src/lib/kadm5/unit-test/diff-files/no-diffs
new file mode 100644
index 000000000..593d67320
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/diff-files/no-diffs
@@ -0,0 +1,2 @@
+##! nochanges
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/handle-test.c b/krb5-1-6/src/lib/kadm5/unit-test/handle-test.c
new file mode 100644
index 000000000..3f723851d
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/handle-test.c
@@ -0,0 +1,130 @@
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <krb5.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <kadm5/client_internal.h>
+
+
+int main(int argc, char *argv[])
+{
+     ovsec_kadm_ret_t ret;
+     void *server_handle;
+     kadm5_server_handle_t handle;
+     kadm5_server_handle_rec orig_handle;
+     ovsec_kadm_policy_ent_t	pol;
+     ovsec_kadm_principal_ent_t	princ;
+     krb5_keyblock	*key;
+     krb5_principal	tprinc;
+     krb5_context	context;
+
+
+    kadm5_init_krb5_context(&context);
+     
+    ret = ovsec_kadm_init("admin/none", "admin", "ovsec_adm/admin", 0,
+			  OVSEC_KADM_STRUCT_VERSION, OVSEC_KADM_API_VERSION_1, NULL,
+			  &server_handle);
+    if(ret != OVSEC_KADM_OK) {
+	com_err("test", ret, "init");
+	exit(2);
+    }
+    handle = (kadm5_server_handle_t) server_handle;
+    orig_handle = *handle;
+    handle->magic_number = OVSEC_KADM_STRUCT_VERSION;
+    krb5_parse_name(context, "testuser", &tprinc);
+    ret = ovsec_kadm_get_principal(server_handle, tprinc, &princ);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "get-principal",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_get_policy(server_handle, "pol1", &pol);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "get-policy",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_create_principal(server_handle, princ, OVSEC_KADM_PRINCIPAL, "pass");
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "create-principal",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_create_policy(server_handle, pol, OVSEC_KADM_POLICY);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "create-policy",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_modify_principal(server_handle, princ, OVSEC_KADM_PW_EXPIRATION);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "modify-principal",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_modify_policy(server_handle, pol, OVSEC_KADM_PW_MAX_LIFE);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "modify-policy",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_delete_principal(server_handle, tprinc);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "delete-principal",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_delete_policy(server_handle, "pol1");
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "delete-policy",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_chpass_principal(server_handle, tprinc, "FooBar");
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "chpass",
+		error_message(ret));
+	exit(1);
+    }
+    ret = ovsec_kadm_randkey_principal(server_handle, tprinc, &key);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "randkey",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_rename_principal(server_handle, tprinc, tprinc);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "rename",
+		error_message(ret));
+	exit(1);
+    }
+    
+    ret = ovsec_kadm_destroy(server_handle);
+    if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+	fprintf(stderr, "%s -- returned -- %s\n", "destroy",
+		error_message(ret));
+	exit(1);
+    }
+
+    *handle = orig_handle;
+    ret = ovsec_kadm_destroy(server_handle);
+    if (ret != OVSEC_KADM_OK) {
+	fprintf(stderr, "valid %s -- returned -- %s\n", "destroy",
+		error_message(ret));
+	exit(1);
+    }
+
+    exit(0);
+}
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/init-test.c b/krb5-1-6/src/lib/kadm5/unit-test/init-test.c
new file mode 100644
index 000000000..575b24f35
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/init-test.c
@@ -0,0 +1,30 @@
+#undef USE_KADM5_API_VERSION
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <krb5.h>
+#include <string.h>
+
+int main()
+{
+     kadm5_ret_t ret;
+     void *server_handle;
+     kadm5_config_params params;
+
+     memset(¶ms, 0, sizeof(params));
+     params.mask |= KADM5_CONFIG_NO_AUTH;
+     ret = kadm5_init("admin", "admin", NULL, ¶ms,
+		      KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+		      &server_handle);
+     if (ret == KADM5_RPC_ERROR)
+	  exit(0);
+     else if (ret != 0) {
+	  com_err("init-test", ret, "while initializing without auth");
+	  exit(1);
+     } else {
+	 fprintf(stderr, "Unexpected success while initializing without auth!\n");
+	 (void) kadm5_destroy(server_handle);
+	 exit(1);
+     }
+}
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/iter-test.c b/krb5-1-6/src/lib/kadm5/unit-test/iter-test.c
new file mode 100644
index 000000000..17e561ef1
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/iter-test.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <kadm5/admin.h>
+#include <string.h>
+
+int main(int argc, char **argv)
+{
+     ovsec_kadm_ret_t ret;
+     void *server_handle;
+     char **names;
+     int count, princ, i;
+
+     if (argc != 3) {
+	  fprintf(stderr, "Usage: %s [-princ|-pol] exp\n", argv[0]);
+	  exit(1);
+     }
+     princ = (strcmp(argv[1], "-princ") == 0);
+     
+     ret = ovsec_kadm_init("admin", "admin", OVSEC_KADM_ADMIN_SERVICE, 0,
+			   OVSEC_KADM_STRUCT_VERSION,
+			   OVSEC_KADM_API_VERSION_1, NULL,
+			   &server_handle);
+     if (ret != OVSEC_KADM_OK) {
+	  com_err("iter-test", ret, "while initializing");
+	  exit(1);
+     }
+
+     if (princ)
+	  ret = ovsec_kadm_get_principals(server_handle, argv[2], &names,
+					  &count);
+     else
+	  ret = ovsec_kadm_get_policies(server_handle, argv[2],
+					&names, &count);
+					
+     if (ret != OVSEC_KADM_OK) {
+	  com_err("iter-test", ret, "while retrieving list");
+	  exit(1);
+     }
+
+     for (i = 0; i < count; i++)
+	  printf("%d: %s\n", i, names[i]);
+
+     ovsec_kadm_free_name_list(server_handle, names, count);
+
+     (void) ovsec_kadm_destroy(server_handle);
+
+     return 0;
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/lib/lib.t b/krb5-1-6/src/lib/kadm5/unit-test/lib/lib.t
new file mode 100644
index 000000000..20277942c
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/lib/lib.t
@@ -0,0 +1,305 @@
+global timeout
+set timeout 60
+
+set lib_pid 0
+
+#
+# The functions in this library used to be responsible for bazillions
+# of wasted api_starts.  Now, they all just use their own library
+# handle so they are not interrupted when the main tests call init or
+# destroy.  They have to keep track of when the api exists and
+# restarts, though, since the lib_handle needs to be re-opened in that
+# case.
+#
+proc lib_start_api {} {
+    global spawn_id lib_pid test
+
+    if {! [api_isrunning $lib_pid]} {
+	api_exit
+	set lib_pid [api_start]
+	if {! [cmd {
+	    ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+		    $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+		    lib_handle
+	}]} {
+	    error "$test: unexpected failure in init"
+	    return
+	}
+	verbose "+++ restarted api ($lib_pid) for lib"
+    } else {
+	verbose "+++ api $lib_pid already running for lib"
+    }	
+}
+
+proc cmd {command} {
+    global prompt
+    global spawn_id
+    global test
+
+    send "[string trim $command]\n"
+    expect {
+	-re "OK .*$prompt$" { return 1 }
+        -re "ERROR .*$prompt$" { return 0 }
+	"wrong # args" { error "$test: wrong number args"; return 0 }
+        timeout { fail "$test: timeout"; return 0 }
+        eof { fail "$test: eof"; api_exit; lib_start_api; return 0 }
+    }
+}
+
+proc tcl_cmd {command} {
+    global prompt spawn_id test
+
+    send "[string trim $command]\n"
+    expect {
+	-re "$prompt$" { return 1}
+	"wrong # args" { error "$test: wrong number args"; return 0 }
+	timeout { error_and_restart "timeout" }
+	eof { api_exit; lib_start_api; return 0 }
+    }
+}
+
+proc one_line_succeed_test {command} {
+    global prompt
+    global spawn_id
+    global test
+
+    send "[string trim $command]\n"
+    expect {
+	-re "OK .*$prompt$"		{ pass "$test"; return 1 }
+	-re "ERROR .*$prompt$" { 
+		fail "$test: $expect_out(buffer)"; return 0
+	}
+	"wrong # args" { error "$test: wrong number args"; return 0 }
+	timeout				{ fail "$test: timeout"; return 0 }
+	eof				{ fail "$test: eof"; api_exit; lib_start_api; return 0 }
+    }
+}
+
+proc one_line_fail_test {command code} {
+    global prompt
+    global spawn_id
+    global test
+
+    send "[string trim $command]\n"
+    expect {
+	-re "ERROR .*$code.*$prompt$"	{ pass "$test"; return 1 }
+	-re "ERROR .*$prompt$"	{ fail "$test: bad failure"; return 0 }
+	-re "OK .*$prompt$"		{ fail "$test: bad success"; return 0 }
+	"wrong # args" { error "$test: wrong number args"; return 0 }
+	timeout				{ fail "$test: timeout"; return 0 }
+	eof				{ fail "$test: eof"; api_exit; lib_start_api; return 0 }
+    }
+}
+
+proc one_line_fail_test_nochk {command} {
+    global prompt
+    global spawn_id
+    global test
+
+    send "[string trim $command]\n"
+    expect {
+	-re "ERROR .*$prompt$"	{ pass "$test:"; return 1 }
+	-re "OK .*$prompt$"		{ fail "$test: bad success"; return 0 }
+	"wrong # args" { error "$test: wrong number args"; return 0 }
+	timeout				{ fail "$test: timeout"; return 0 }
+	eof				{ fail "$test: eof"; api_exit; lib_start_api; return 0 }
+    }
+}
+
+proc resync {} {
+    global prompt spawn_id test
+
+    expect {
+	-re "$prompt$"	{}
+	"wrong # args" { error "$test: wrong number args"; return 0 }
+	eof { api_exit; lib_start_api }
+    }
+}
+
+proc create_principal {name} {
+    lib_start_api
+
+    set ret [cmd [format {
+	ovsec_kadm_create_principal $lib_handle [simple_principal \
+		"%s"] {OVSEC_KADM_PRINCIPAL} "%s"
+    } $name $name]]
+
+    return $ret
+}
+
+proc create_policy {name} {
+    lib_start_api
+
+    set ret [cmd [format {
+	    ovsec_kadm_create_policy $lib_handle [simple_policy "%s"] \
+		    {OVSEC_KADM_POLICY}
+	} $name $name]]
+
+    return $ret
+}
+
+proc create_principal_pol {name policy} {
+    lib_start_api
+
+    set ret [cmd [format {
+	    ovsec_kadm_create_principal $lib_handle [princ_w_pol "%s" \
+		    "%s"] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} "%s"
+    } $name $policy $name]]
+
+    return $ret
+}
+
+proc delete_principal {name} {
+    lib_start_api
+
+    set ret [cmd [format {
+	    ovsec_kadm_delete_principal $lib_handle "%s"
+    } $name]]
+
+    return $ret
+}
+
+proc delete_policy {name} {
+    lib_start_api
+
+    set ret [cmd [format {ovsec_kadm_delete_policy $lib_handle "%s"} $name]]
+
+    return $ret
+}
+
+proc principal_exists {name} {
+#    puts stdout "Starting principal_exists."
+
+    lib_start_api
+
+    set ret [cmd [format {
+	ovsec_kadm_get_principal $lib_handle "%s" principal
+    } $name]]
+
+#   puts stdout "Finishing principal_exists."
+
+    return $ret
+}
+
+proc policy_exists {name} {
+    lib_start_api
+
+#    puts stdout "Starting policy_exists."
+
+    set ret [cmd [format {
+	    ovsec_kadm_get_policy $lib_handle "%s" policy
+	} $name]]
+
+#    puts stdout "Finishing policy_exists."
+
+    return $ret
+}
+
+proc error_and_restart {error} {
+    api_exit
+    api_start
+    perror $error
+}
+
+proc test {name} {
+   global test verbose
+
+   set test $name
+   if {$verbose >= 1} {
+	puts stdout "At $test"
+   }
+}
+
+proc begin_dump {} {
+    global TOP
+    global RPC
+    
+    if { ! $RPC } {
+#	exec $env(SIMPLE_DUMP) > /tmp/dump.before
+    }
+}
+
+proc end_dump_compare {name} {
+    global  file
+    global  TOP
+    global  RPC
+
+    if { ! $RPC } { 
+#	set file $TOP/admin/lib/unit-test/diff-files/$name
+#	exec $env(SIMPLE_DUMP) > /tmp/dump.after
+#	exec $env(COMPARE_DUMP) /tmp/dump.before /tmp/dump.after $file
+    }
+}
+
+proc kinit { princ pass {opts ""} } {
+	global env;
+        global KINIT
+
+	eval spawn $KINIT -5 $opts $princ
+	expect {
+		-re {Password for .*: $}
+		    {send "$pass\n"}
+		timeout {puts "Timeout waiting for prompt" ; close }
+	}
+
+	# this necessary so close(1) in the child will not sleep waiting for
+	# the parent, which is us, to read pending data.
+
+	expect {
+		"when initializing cache" { error "kinit failed: $expect_out(buffer)" }
+		eof {}
+	}
+	wait
+}
+
+proc kdestroy {} {
+        global KDESTROY
+	global errorCode errorInfo
+	global env
+
+	if {[info exists errorCode]} {
+		set saveErrorCode $errorCode
+	}
+	if {[info exists errorInfo]} {
+		set saveErrorInfo $errorInfo
+	}
+	catch "system $KDESTROY -5 2>/dev/null"
+	if {[info exists saveErrorCode]} {
+		set errorCode $saveErrorCode
+	} elseif {[info exists errorCode]} {
+		unset errorCode
+	}
+	if {[info exists saveErrorInfo]} {
+		set errorInfo $saveErrorInfo
+	} elseif {[info exists errorInfo]} {
+		unset errorInfo
+	}
+}
+
+proc create_principal_with_keysalts {name keysalts} {
+    global kadmin_local
+
+    spawn $kadmin_local -e "$keysalts"
+    expect {
+	"kadmin.local:" {}
+	default { error "waiting for kadmin.local prompt"; return 1}
+    }
+    send "ank -pw \"$name\" \"$name\"\n"
+    expect {
+	-re "Principal \"$name.*\" created." {}
+	"kadmin.local:" {
+	    error "expecting principal created message"; 
+	    return 1
+	}
+	default { error "waiting for principal created message"; return 1 }
+    }
+    expect {
+	"kadmin.local:" {}
+	default { error "waiting for kadmin.local prompt"; return 1 }
+    }
+    close
+    wait
+    return 0
+}
+
+    
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/lock-test.c b/krb5-1-6/src/lib/kadm5/unit-test/lock-test.c
new file mode 100644
index 000000000..489b7b88e
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/lock-test.c
@@ -0,0 +1,111 @@
+#if USE_KADM5_API_VERSION == 1
+#undef USE_KADM5_API_VERSION
+#define USE_KADM5_API_VERSION 2
+#endif
+
+#include <stdio.h>
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <kdb.h>
+#include <string.h>
+
+char *whoami;
+
+static void usage()
+{
+     fprintf(stderr,
+	     "Usage: %s {shared|exclusive|permanent|release|"
+	     "get name|wait} ...\n", whoami);
+     exit(1);
+}
+
+int main(int argc, char **argv)
+{
+     krb5_error_code ret;
+     osa_policy_ent_t entry;
+     krb5_context context;
+     kadm5_config_params params;
+     krb5_error_code kret;
+
+     whoami = argv[0];
+
+     kret = kadm5_init_krb5_context(&context);
+     if (kret) {
+	 com_err(whoami, kret, "while initializing krb5");
+	 exit(1);
+     }
+
+     params.mask = 0;
+     ret = kadm5_get_config_params(context, 1, ¶ms, ¶ms);
+     if (ret) {
+	  com_err(whoami, ret, "while retrieving configuration parameters");
+	  exit(1);
+     }
+     if (! (params.mask & KADM5_CONFIG_ADBNAME)) {
+	  com_err(whoami, KADM5_BAD_SERVER_PARAMS,
+		  "while retrieving configuration parameters");
+	  exit(1);
+     }
+
+     ret = krb5_db_open( context, NULL, KRB5_KDB_OPEN_RW);
+     if (ret) {
+	  com_err(whoami, ret, "while opening database");
+	  exit(1);
+     }
+
+     argc--; argv++;
+     while (argc) {
+	  if (strcmp(*argv, "shared") == 0) {
+	       ret = krb5_db_lock(context, KRB5_DB_LOCKMODE_SHARED);
+	       if (ret)
+		    com_err(whoami, ret, "while getting shared lock");
+	       else
+		    printf("shared\n");
+	  } else if (strcmp(*argv, "exclusive") == 0) {
+	       ret = krb5_db_lock(context, KRB5_DB_LOCKMODE_EXCLUSIVE );
+	       if (ret)
+		    com_err(whoami, ret, "while getting exclusive lock");
+	       else
+		    printf("exclusive\n");
+	  } else if (strcmp(*argv, "permanent") == 0) {
+	       ret = krb5_db_lock(context, KRB5_DB_LOCKMODE_EXCLUSIVE );
+	       if (ret)
+		    com_err(whoami, ret, "while getting permanent lock");
+	       else
+		    printf("permanent\n");
+	  } else if (strcmp(*argv, "release") == 0) {
+	       ret = krb5_db_unlock(context);
+	       if (ret)
+		    com_err(whoami, ret, "while releasing lock");
+	       else
+		    printf("released\n");
+	  } else if (strcmp(*argv, "get") == 0) {
+	       int cnt = 1;
+	       argc--; argv++;
+	       if (!argc) usage();
+	       if ((ret = krb5_db_get_policy(context, *argv,
+					     &entry, &cnt)) ) {
+		    com_err(whoami, ret, "while getting policy");
+	       } else {
+		    printf("retrieved\n");
+		    krb5_db_free_policy(context, entry);
+	       }
+	  } else if (strcmp(*argv, "wait") == 0) {
+	       getchar();
+	  } else {
+	       fprintf(stderr, "%s: Invalid argument \"%s\"\n",
+		       whoami, *argv);
+	       usage();
+	  }
+
+	  argc--; argv++;
+     }
+
+     ret = krb5_db_fini(context);
+     if (ret) {
+	  com_err(whoami, ret, "while closing database");
+	  exit(1);
+     }
+
+     return 0;
+}
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/randkey-test.c b/krb5-1-6/src/lib/kadm5/unit-test/randkey-test.c
new file mode 100644
index 000000000..4b17bcb22
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/randkey-test.c
@@ -0,0 +1,45 @@
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <krb5.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#define	TEST_NUM    1000
+
+int main()
+{
+     ovsec_kadm_ret_t ret;
+     krb5_keyblock  *keys[TEST_NUM];
+     krb5_principal tprinc;
+     krb5_keyblock  *newkey;
+     krb5_context context;
+     void *server_handle;
+
+     int    x, i;
+
+     kadm5_init_krb5_context(&context);
+
+     krb5_parse_name(context, "testuser", &tprinc);
+     ret = ovsec_kadm_init("admin", "admin", "ovsec_adm/admin", 0,
+			   OVSEC_KADM_STRUCT_VERSION,
+			   OVSEC_KADM_API_VERSION_1, NULL,
+			   &server_handle);
+     if(ret != OVSEC_KADM_OK) {
+	com_err("test", ret, "init");
+	exit(2);
+     }
+     for(x = 0; x < TEST_NUM; x++) {
+	ovsec_kadm_randkey_principal(server_handle, tprinc, &newkey);
+	for(i = 0; i < x; i++) {
+	    if (!memcmp(newkey->contents, keys[i]->contents, newkey->length))
+		puts("match found");
+	}
+	krb5_copy_keyblock(context, newkey, &keys[x]);
+	krb5_free_keyblock(context, newkey);
+     }
+     ovsec_kadm_destroy(server_handle);
+     exit(0);
+}
+
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/setkey-test.c b/krb5-1-6/src/lib/kadm5/unit-test/setkey-test.c
new file mode 100644
index 000000000..865fc14b7
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/setkey-test.c
@@ -0,0 +1,233 @@
+#include <stdio.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+
+#if	HAVE_SRAND48
+#define	RAND()		lrand48()
+#define	SRAND(a)	srand48(a)
+#define	RAND_TYPE	long
+#elif	HAVE_SRAND
+#define	RAND()		rand()
+#define	SRAND(a)	srand(a)
+#define	RAND_TYPE	int
+#elif	HAVE_SRANDOM
+#define	RAND()		random()
+#define	SRAND(a)	srandom(a)
+#define	RAND_TYPE	long
+#else	/* no random */
+need a random number generator
+#endif	/* no random */
+
+krb5_keyblock test1[] = {
+    {0, ENCTYPE_DES_CBC_CRC, 0, 0},
+    {-1},
+};
+krb5_keyblock test2[] = {
+     {0, ENCTYPE_DES_CBC_RAW, 0, 0},
+     {-1},
+};
+krb5_keyblock test3[] = {
+     {0, ENCTYPE_DES_CBC_MD5, 0, 0},
+     {-1},
+};
+
+krb5_keyblock *tests[] = { 
+  test1, test2, test3, NULL
+};
+
+#if 0
+int keyblocks_equal(krb5_keyblock *kb1, krb5_keyblock *kb2)
+{
+  return (kb1->enctype == kb2->enctype &&
+	  kb1->length == kb2->length &&
+	  memcmp(kb1->contents, kb2->contents, kb1->length) == 0);
+}
+#endif
+
+krb5_data tgtname = {
+    0,
+    KRB5_TGS_NAME_SIZE,
+    KRB5_TGS_NAME
+};
+
+krb5_enctype ktypes[] = { 0, 0 };
+
+extern krb5_kt_ops krb5_ktf_writable_ops;
+
+int
+main(int argc, char **argv)
+{
+  krb5_context context;
+  krb5_keytab kt;
+  krb5_keytab_entry ktent;
+  krb5_encrypt_block eblock;
+  krb5_creds my_creds;
+  kadm5_principal_ent_rec princ_ent;
+  krb5_principal princ, server;
+  char pw[16];
+  char *whoami, *principal, *authprinc;
+  krb5_data pwdata;
+  void *handle;
+  int ret, i, test, encnum;
+
+  whoami = argv[0];
+
+  if (argc != 2 && argc != 3) {
+    fprintf(stderr, "Usage: %s principal [authuser]\n", whoami);
+    exit(1);
+  }
+  principal = argv[1];
+  authprinc = argv[2] ? argv[2] : argv[0];
+
+  /*
+   * Setup.  Initialize data structures, open keytab, open connection
+   * to kadm5 server.
+   */
+
+  memset((char *) &context, 0, sizeof(context));
+  kadm5_init_krb5_context(&context);
+
+  ret = krb5_parse_name(context, principal, &princ);
+  if (ret) {
+    com_err(whoami, ret, "while parsing principal name %s", principal);
+    exit(1);
+  }
+    
+  if((ret = krb5_build_principal_ext(context, &server,
+				     krb5_princ_realm(kcontext, princ)->length,
+				     krb5_princ_realm(kcontext, princ)->data,
+				     tgtname.length, tgtname.data,
+				     krb5_princ_realm(kcontext, princ)->length,
+				     krb5_princ_realm(kcontext, princ)->data,
+				     0))) {
+       com_err(whoami, ret, "while building server name");
+       exit(1);
+  }
+
+  /* register the WRFILE keytab type  */
+  ret = krb5_kt_register(context, &krb5_ktf_writable_ops);
+  if (ret) {
+       com_err(whoami, ret,
+	       "while registering writable key table functions");
+       exit(1);
+  }
+
+  ret = krb5_kt_default(context, &kt);
+  if (ret) {
+       com_err(whoami, ret, "while opening keytab");
+       exit(1);
+  }
+
+  ret = kadm5_init(authprinc, NULL, KADM5_ADMIN_SERVICE, NULL,
+		   KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+		   &handle);
+  if (ret) {
+    com_err(whoami, ret, "while initializing connection");
+    exit(1);
+  }
+
+  /* these pw's don't need to be secure, just different every time */
+  SRAND((RAND_TYPE)time((void *) NULL));
+  pwdata.data = pw;
+  pwdata.length = sizeof(pw);
+  
+  /*
+   * For each test:
+   *
+   * For each enctype in the test, construct a random password/key.
+   * Assign all keys to principal with kadm5_setkey_principal.  Add
+   * each key to the keytab, and acquire an initial ticket with the
+   * keytab (XXX can I specify the enctype & kvno explicitly?).  If
+   * krb5_get_in_tkt_with_keytab succeeds, then the keys were set
+   * successfully.
+   */
+  for (test = 0; tests[test] != NULL; test++) {
+       krb5_keyblock *testp = tests[test];
+       printf("+ Test %d:\n", test);
+
+       for (encnum = 0; testp[encnum].magic != -1; encnum++) {
+	    for (i = 0; i < sizeof(pw); i++)
+		 pw[i] = (RAND() % 26) + '0'; /* XXX */
+
+	    krb5_use_enctype(context, &eblock, testp[encnum].enctype);
+	    ret = krb5_string_to_key(context, &eblock, &testp[encnum],
+				     &pwdata, NULL);
+	    if (ret) {
+		 com_err(whoami, ret, "while converting string to key");
+		 exit(1);
+	    }
+       }
+       
+       /* now, encnum == # of keyblocks in testp */
+       ret = kadm5_setkey_principal(handle, princ, testp, encnum);
+       if (ret) {
+	    com_err(whoami, ret, "while setting keys");
+	    exit(1);
+       }
+
+       ret = kadm5_get_principal(handle, princ, &princ_ent, KADM5_KVNO);
+       if (ret) {
+	    com_err(whoami, ret, "while retrieving principal");
+	    exit(1);
+       }
+
+       for (encnum = 0; testp[encnum].magic != -1; encnum++) {
+	    printf("+   enctype %d\n", testp[encnum].enctype);
+		   
+	    memset((char *) &ktent, 0, sizeof(ktent));
+	    ktent.principal = princ;
+	    ktent.key = testp[encnum];
+	    ktent.vno = princ_ent.kvno;
+
+	    ret = krb5_kt_add_entry(context, kt, &ktent);
+	    if (ret) {
+		 com_err(whoami, ret, "while adding keytab entry");
+		 exit(1);
+	    }
+
+	    memset((char *)&my_creds, 0, sizeof(my_creds));
+	    my_creds.client = princ;
+	    my_creds.server = server;
+	    
+	    ktypes[0] = testp[encnum].enctype;
+	    ret = krb5_get_in_tkt_with_keytab(context,
+					      0 /* options */,
+					      NULL /* addrs */,
+					      ktypes,
+					      NULL /* preauth */,
+					      kt, 0,
+					      &my_creds, 0);
+	    if (ret) {
+		 com_err(whoami, ret, "while acquiring initial ticket");
+		 exit(1);
+	    }
+
+	    /* since I can't specify enctype explicitly ... */
+	    ret = krb5_kt_remove_entry(context, kt, &ktent);
+	    if (ret) {
+		 com_err(whoami, ret, "while removing keytab entry");
+		 exit(1);
+	    }
+       }
+  }
+  
+  ret = krb5_kt_close(context, kt);
+  if (ret) {
+       com_err(whoami, ret, "while closing keytab");
+       exit(1);
+  }
+
+  ret = kadm5_destroy(handle);
+  if (ret) {
+       com_err(whoami, ret, "while closing kadmin connection");
+       exit(1);
+  }
+
+  return 0;
+}
+
+  
+  
+    
+    
+  
diff --git a/krb5-1-6/src/lib/kadm5/unit-test/site.exp b/krb5-1-6/src/lib/kadm5/unit-test/site.exp
new file mode 100644
index 000000000..18b435dd1
--- /dev/null
+++ b/krb5-1-6/src/lib/kadm5/unit-test/site.exp
@@ -0,0 +1,2 @@
+set tool ovsec_kadm_srv_tcl
+set prompt "% "
diff --git a/krb5-1-6/src/lib/kdb/Makefile.in b/krb5-1-6/src/lib/kdb/Makefile.in
new file mode 100644
index 000000000..65ee8e770
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/Makefile.in
@@ -0,0 +1,119 @@
+thisconfigdir=../..
+myfulldir=lib/kdb
+mydir=lib/kdb
+BUILDTOP=$(REL)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+CFLAGS=@CFLAGS@ -DKDB5_USE_LIB_KDB_DB2
+LOCALINCLUDES= -I.
+DEFS=
+
+LIBBASE=kdb5
+LIBMAJOR=4
+LIBMINOR=0
+LIBINITFUNC=kdb_init_lock_list
+LIBFINIFUNC=kdb_fini_lock_list
+RELDIR=kdb
+# Depends on libk5crypto and libkrb5
+
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS=-lkrb5 -lcom_err -lk5crypto $(SUPPORT_LIB) $(DL_LIB) $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+adb_err.$(OBJEXT): adb_err.c
+adb_err.c adb_err.h: $(srcdir)/adb_err.et
+
+SRCS= \
+	$(srcdir)/kdb5.c \
+	$(srcdir)/encrypt_key.c \
+	$(srcdir)/decrypt_key.c \
+	$(srcdir)/kdb_default.c \
+	$(srcdir)/kdb_cpw.c \
+	adb_err.c \
+	$(srcdir)/keytab.c
+
+STOBJLISTS=OBJS.ST
+STLIBOBJS= \
+	kdb5.o \
+	encrypt_key.o \
+	decrypt_key.o \
+	kdb_default.o \
+	kdb_cpw.o \
+	adb_err.o \
+	keytab.o
+
+all-unix:: all-liblinks
+install-unix:: install-libs
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+	$(RM) adb_err.c adb_err.h
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+kdb5.so kdb5.po $(OUTPRE)kdb5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h adb_err.h kdb5.c kdb5.h
+encrypt_key.so encrypt_key.po $(OUTPRE)encrypt_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h encrypt_key.c
+decrypt_key.so decrypt_key.po $(OUTPRE)decrypt_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h decrypt_key.c
+kdb_default.so kdb_default.po $(OUTPRE)kdb_default.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb_default.c
+kdb_cpw.so kdb_cpw.po $(OUTPRE)kdb_cpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb_cpw.c
+adb_err.so adb_err.po $(OUTPRE)adb_err.$(OBJEXT): $(COM_ERR_DEPS) \
+  adb_err.c
+keytab.so keytab.po $(OUTPRE)keytab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/kdb_kt.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  keytab.c
diff --git a/krb5-1-6/src/lib/kdb/adb_err.et b/krb5-1-6/src/lib/kdb/adb_err.et
new file mode 100644
index 000000000..394802571
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/adb_err.et
@@ -0,0 +1,16 @@
+error_table adb
+error_code OSA_ADB_NOERR,		"No Error"
+error_code OSA_ADB_DUP,			"Principal or policy already exists"
+error_code OSA_ADB_NOENT,		"Principal or policy does not exist"
+error_code OSA_ADB_DBINIT,		"Database not initialized"
+error_code OSA_ADB_BAD_POLICY,		"Invalid policy name"
+error_code OSA_ADB_BAD_PRINC,		"Invalid principal name"
+error_code OSA_ADB_BAD_DB,		"Database inconsistency detected"
+error_code OSA_ADB_XDR_FAILURE,		"XDR encoding error"
+error_code OSA_ADB_FAILURE,		"Failure!"
+error_code OSA_ADB_BADLOCKMODE,		"Bad lock mode"
+error_code OSA_ADB_CANTLOCK_DB,		"Cannot lock database"
+error_code OSA_ADB_NOTLOCKED,		"Database not locked"
+error_code OSA_ADB_NOLOCKFILE,		"KADM5 administration database lock file missing"
+error_code OSA_ADB_NOEXCL_PERM,		"Insufficient permission to lock file"
+end
diff --git a/krb5-1-6/src/lib/kdb/decrypt_key.c b/krb5-1-6/src/lib/kdb/decrypt_key.c
new file mode 100644
index 000000000..c2ddbfd2c
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/decrypt_key.c
@@ -0,0 +1,139 @@
+/*
+ * lib/kdb/decrypt_key.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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"
+#include "kdb.h"
+
+/*
+ * Decrypt a key from storage in the database.  "eblock" is used
+ * to decrypt the key in "in" into "out"; the storage pointed to by "out"
+ * is allocated before use.
+ */
+
+krb5_error_code
+krb5_dbekd_decrypt_key_data( krb5_context 	  context,
+			     const krb5_keyblock	* mkey,
+			     const krb5_key_data	* key_data,
+			     krb5_keyblock 	* dbkey,
+			     krb5_keysalt 	* keysalt)
+{
+    krb5_error_code 	  retval = 0;
+    krb5_int16		  tmplen;
+    krb5_octet		* ptr;
+    krb5_enc_data	  cipher;
+    krb5_data		  plain;
+
+    ptr = key_data->key_data_contents[0];
+
+    if (ptr) {
+	krb5_kdb_decode_int16(ptr, tmplen);
+	ptr += 2;
+
+	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 */
+    if (keysalt) {
+	if (key_data->key_data_ver == 2) {
+	    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))){
+		    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],
+		       (size_t) keysalt->data.length);
+	    } else
+		keysalt->data.data = (char *) NULL;
+	} else {
+	    keysalt->type = KRB5_KDB_SALTTYPE_NORMAL;
+	    keysalt->data.data = (char *) NULL;
+	    keysalt->data.length = 0;
+	}
+    }
+
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/kdb/encrypt_key.c b/krb5-1-6/src/lib/kdb/encrypt_key.c
new file mode 100644
index 000000000..ed35e6969
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/encrypt_key.c
@@ -0,0 +1,136 @@
+/*
+ * lib/kdb/encrypt_key.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * 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"
+#include "kdb.h"
+
+/*
+ * Encrypt a key for storage in the database.  "eblock" is used
+ * to encrypt the key in "in" into "out"; the storage pointed to by "out"
+ * is allocated before use.
+ */
+
+krb5_error_code
+krb5_dbekd_encrypt_key_data( krb5_context 		  context,
+			     const krb5_keyblock	* mkey,
+			     const krb5_keyblock 	* dbkey,
+			     const krb5_keysalt		* keysalt,
+			     int			  keyver,
+			     krb5_key_data	        * key_data)
+{
+    krb5_error_code 		  retval;
+    krb5_octet			* ptr;
+    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])
+	    krb5_xfree(key_data->key_data_contents[i]);
+
+    key_data->key_data_ver = 1;
+    key_data->key_data_kvno = keyver;
+
+    /* 
+     * The First element of the type/length/contents 
+     * fields is the key type/length/contents
+     */
+    if ((retval = krb5_c_encrypt_length(context, mkey->enctype, dbkey->length,
+					&len)))
+	return(retval);
+
+    if ((ptr = (krb5_octet *) malloc(2 + len)) == NULL)
+	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(dbkey->length, ptr);
+    ptr += 2;
+
+    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]);
+	return retval;
+    }
+
+    /* After key comes the salt in necessary */
+    if (keysalt) {
+	if (keysalt->type > 0) {
+	    key_data->key_data_ver++;
+	    key_data->key_data_type[1] = keysalt->type;
+	    if ((key_data->key_data_length[1] = keysalt->data.length) != 0) {
+		key_data->key_data_contents[1] =
+		    (krb5_octet *)malloc(keysalt->data.length);
+		if (key_data->key_data_contents[1] == NULL) {
+		    krb5_xfree(key_data->key_data_contents[0]);
+		    return ENOMEM;
+		}
+		memcpy(key_data->key_data_contents[1], keysalt->data.data,
+		       (size_t) keysalt->data.length);
+	    }
+	}
+    }
+
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/kdb/kdb5.c b/krb5-1-6/src/lib/kdb/kdb5.c
new file mode 100644
index 000000000..a20af6b17
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/kdb5.c
@@ -0,0 +1,1958 @@
+/*
+ * Copyright 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This code was based on code donated to MIT by Novell for
+ * distribution under the MIT license.
+ */
+
+/* 
+ * Include files
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <k5-int.h>
+#include <osconf.h>
+#include "kdb5.h"
+#include <assert.h>
+
+/* Currently DB2 policy related errors are exported from DAL.  But
+   other databases should set_err function to return string.  */
+#include "adb_err.h"
+
+/*
+ * Type definitions
+ */
+#define KRB5_TL_DB_ARGS                 0x7fff
+
+/*
+ * internal static variable
+ */
+
+static k5_mutex_t db_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+#ifdef _KDB5_STATIC_LINK
+#undef _KDB5_DYNAMIC_LINK
+#else
+#undef _KDB5_DYNAMIC_LINK
+/* to avoid redefinition problem */
+#define _KDB5_DYNAMIC_LINK
+#endif
+
+static db_library lib_list;
+
+/*
+ * Helper Functions
+ */
+
+MAKE_INIT_FUNCTION(kdb_init_lock_list);
+MAKE_FINI_FUNCTION(kdb_fini_lock_list);
+
+int
+kdb_init_lock_list(void)
+{
+    return k5_mutex_finish_init(&db_lock);
+}
+
+static int
+kdb_lock_list()
+{
+    int err;
+    err = CALL_INIT_FUNCTION (kdb_init_lock_list);
+    if (err)
+	return err;
+    return k5_mutex_lock(&db_lock);
+}
+
+void
+kdb_fini_lock_list(void)
+{
+    if (INITIALIZER_RAN(kdb_init_lock_list))
+	k5_mutex_destroy(&db_lock);
+}
+
+static int
+kdb_unlock_list()
+{
+    return k5_mutex_unlock(&db_lock);
+}
+
+#define kdb_init_lib_lock(a) 0
+#define kdb_destroy_lib_lock(a) (void)0
+#define kdb_lock_lib_lock(a, b) 0
+#define kdb_unlock_lib_lock(a, b) (void)0
+
+/* Caller must free result*/
+
+static char *
+kdb_get_conf_section(krb5_context kcontext)
+{
+    krb5_error_code status = 0;
+    char   *result = NULL;
+    char   *value = NULL;
+
+    if (kcontext->default_realm == NULL)
+	return NULL;
+    /* The profile has to have been initialized.  If the profile was
+       not initialized, expect nothing less than a crash.  */
+    status = profile_get_string(kcontext->profile,
+				/* realms */
+				KDB_REALM_SECTION,
+				kcontext->default_realm,
+				/* under the realm name, database_module */
+				KDB_MODULE_POINTER,
+				/* default value is the realm name itself */
+				kcontext->default_realm,
+				&value);
+
+    if (status) {
+	/* some problem */
+	result = strdup(kcontext->default_realm);
+	/* let NULL be handled by the caller */
+    } else {
+	result = strdup(value);
+	/* free profile string */
+	profile_release_string(value);
+    }
+
+    return result;
+}
+
+static char *
+kdb_get_library_name(krb5_context kcontext)
+{
+    krb5_error_code status = 0;
+    char   *result = NULL;
+    char   *value = NULL;
+    char   *lib = NULL;
+
+    status = profile_get_string(kcontext->profile,
+				/* realms */
+				KDB_REALM_SECTION,
+				kcontext->default_realm,
+				/* under the realm name, database_module */
+				KDB_MODULE_POINTER,
+				/* default value is the realm name itself */
+				kcontext->default_realm,
+				&value);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+#define DB2_NAME "db2"
+    /* we got the module section. Get the library name from the module */
+    status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value,
+				KDB_LIB_POINTER,
+				/* default to db2 */
+				DB2_NAME,
+				&lib);
+
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    result = strdup(lib);
+  clean_n_exit:
+    if (value) {
+	/* free profile string */
+	profile_release_string(value);
+    }
+
+    if (lib) {
+	/* free profile string */
+	profile_release_string(lib);
+    }
+    return result;
+}
+
+static void
+kdb_setup_opt_functions(db_library lib)
+{
+    if (lib->vftabl.set_master_key == NULL) {
+	lib->vftabl.set_master_key = kdb_def_set_mkey;
+    }
+
+    if (lib->vftabl.get_master_key == NULL) {
+	lib->vftabl.get_master_key = kdb_def_get_mkey;
+    }
+
+    if (lib->vftabl.fetch_master_key == NULL) {
+	lib->vftabl.fetch_master_key = krb5_db_def_fetch_mkey;
+    }
+
+    if (lib->vftabl.verify_master_key == NULL) {
+	lib->vftabl.verify_master_key = krb5_def_verify_master_key;
+    }
+
+    if (lib->vftabl.dbe_search_enctype == NULL) {
+	lib->vftabl.dbe_search_enctype = krb5_dbe_def_search_enctype;
+    }
+
+    if (lib->vftabl.db_change_pwd == NULL) {
+	lib->vftabl.db_change_pwd = krb5_dbe_def_cpw;
+    }
+
+    if (lib->vftabl.store_master_key == NULL) {
+	lib->vftabl.store_master_key = krb5_def_store_mkey;
+    }
+
+    if (lib->vftabl.promote_db == NULL) {
+	lib->vftabl.promote_db = krb5_def_promote_db;
+    }
+}
+
+static int kdb_db2_pol_err_loaded = 0;
+#ifdef _KDB5_STATIC_LINK
+#define DEF_SYMBOL(a) extern kdb_vftabl krb5_db_vftabl_ ## a
+#define GET_SYMBOL(a) (krb5_db_vftabl_ ## a)
+static krb5_error_code
+kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
+{
+    krb5_error_code status;
+    void   *vftabl_addr = NULL;
+    char    buf[KRB5_MAX_ERR_STR];
+
+    if (!strcmp("kdb_db2", lib_name) && (kdb_db2_pol_err_loaded == 0)) {
+	initialize_adb_error_table();
+	kdb_db2_pol_err_loaded = 1;
+    }
+
+    *lib = calloc((size_t) 1, sizeof(**lib));
+    if (*lib == NULL) {
+	status = ENOMEM;
+	goto clean_n_exit;
+    }
+
+    status = kdb_init_lib_lock(*lib);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    strcpy((*lib)->name, lib_name);
+
+#if !defined(KDB5_USE_LIB_KDB_DB2) && !defined(KDB5_USE_LIB_TEST)
+#error No database module defined
+#endif
+
+#ifdef KDB5_USE_LIB_KDB_DB2
+    if (strcmp(lib_name, "kdb_db2") == 0) {
+	DEF_SYMBOL(kdb_db2);
+	vftabl_addr = (void *) &GET_SYMBOL(kdb_db2);
+    } else
+#endif
+#ifdef KDB5_USE_LIB_TEST
+    if (strcmp(lib_name, "test") == 0) {
+	DEF_SYMBOL(test);
+	vftabl_addr = (void *) &GET_SYMBOL(test);
+    } else
+#endif
+    {
+	sprintf(buf, "Program not built to support %s database type\n",
+		lib_name);
+	status = KRB5_KDB_DBTYPE_NOSUP;
+	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
+	goto clean_n_exit;
+    }
+
+    memcpy(&(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
+
+    kdb_setup_opt_functions(*lib);
+
+    if ((status = (*lib)->vftabl.init_library())) {
+	/* ERROR. library not initialized cleanly */
+	sprintf(buf, "%s library initialization failed, error code %ld\n",
+		lib_name, status);
+	status = KRB5_KDB_DBTYPE_INIT;
+	krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
+	goto clean_n_exit;
+    }
+
+  clean_n_exit:
+    if (status) {
+	free(*lib), *lib = NULL;
+    }
+    return status;
+}
+
+#else /* KDB5_STATIC_LINK*/
+
+static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH;
+#define db_dl_n_locations (sizeof(db_dl_location) / sizeof(db_dl_location[0]))
+
+static krb5_error_code
+kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
+{
+    krb5_error_code status = 0;
+    int     ndx;
+    void  **vftabl_addrs = NULL;
+    /* N.B.: If this is "const" but not "static", the Solaris 10
+       native compiler has trouble building the library because of
+       absolute relocations needed in read-only section ".rodata".
+       When it's static, it goes into ".picdata", which is
+       read-write.  */
+    static const char *const dbpath_names[] = {
+	KDB_MODULE_SECTION, "db_module_dir", NULL,
+    };
+    const char *filebases[2];
+    char **profpath = NULL;
+    char **path = NULL;
+
+    filebases[0] = lib_name;
+    filebases[1] = NULL;
+
+    if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
+	initialize_adb_error_table();
+	kdb_db2_pol_err_loaded = 1;
+    }
+
+    *lib = calloc((size_t) 1, sizeof(**lib));
+    if (*lib == NULL) {
+	status = ENOMEM;
+	goto clean_n_exit;
+    }
+
+    status = kdb_init_lib_lock(*lib);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    strcpy((*lib)->name, lib_name);
+
+    /* Fetch the list of directories specified in the config
+       file(s) first.  */
+    status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
+    if (status != 0 && status != PROF_NO_RELATION)
+	goto clean_n_exit;
+    ndx = 0;
+    if (profpath)
+	while (profpath[ndx] != NULL)
+	    ndx++;
+
+    path = calloc(ndx + db_dl_n_locations, sizeof (char *));
+    if (path == NULL) {
+	status = errno;
+	goto clean_n_exit;
+    }
+    if (ndx)
+	memcpy(path, profpath, ndx * sizeof(profpath[0]));
+    memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
+    status = 0;
+    
+    if ((status = krb5int_open_plugin_dirs ((const char **) path, 
+                                            filebases, 
+                                            &(*lib)->dl_dir_handle, &kcontext->err))) {
+        char *err_str = krb5_get_error_message(kcontext, status);
+	status = KRB5_KDB_DBTYPE_NOTFOUND;
+	krb5_set_error_message (kcontext, status,
+				"Unable to find requested database type: %s", err_str);
+	krb5_free_error_message (kcontext, err_str);
+	goto clean_n_exit;
+    }
+
+    if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
+                                               &vftabl_addrs, &kcontext->err))) {
+        char *err_str = krb5_get_error_message(kcontext, status);
+        status = KRB5_KDB_DBTYPE_INIT;
+        krb5_set_error_message (kcontext, status,
+                                "plugin symbol 'kdb_function_table' lookup failed: %s", err_str);
+        krb5_free_error_message (kcontext, err_str);
+	goto clean_n_exit;
+    }
+
+    if (vftabl_addrs[0] == NULL) {
+	/* No plugins! */
+	status = KRB5_KDB_DBTYPE_NOTFOUND;
+	krb5_set_error_message (kcontext, status,
+				_("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"),
+				lib_name);
+	goto clean_n_exit;
+    }
+
+    memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl));
+    kdb_setup_opt_functions(*lib);
+    
+    if ((status = (*lib)->vftabl.init_library())) {
+        /* ERROR. library not initialized cleanly */
+        goto clean_n_exit;
+    }    
+    
+clean_n_exit:
+    if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); }
+    /* Both of these DTRT with NULL.  */
+    profile_free_list(profpath);
+    free(path);
+    if (status) {
+        if (*lib) {
+	    kdb_destroy_lib_lock(*lib);
+            if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
+                krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
+            }
+	    free(*lib);
+	    *lib = NULL;
+	}
+    }
+    return status;
+}
+
+#endif /* end of _KDB5_STATIC_LINK */
+
+static krb5_error_code
+kdb_find_library(krb5_context kcontext, char *lib_name, db_library * lib)
+{
+    /* lock here so that no two threads try to do the same at the same time */
+    krb5_error_code status = 0;
+    int     locked = 0;
+    db_library curr_elt, prev_elt = NULL;
+
+    if ((status = kdb_lock_list()) != 0) {
+	goto clean_n_exit;
+    }
+    locked = 1;
+
+    curr_elt = lib_list;
+    while (curr_elt != NULL) {
+	if (strcmp(lib_name, curr_elt->name) == 0) {
+	    *lib = curr_elt;
+	    goto clean_n_exit;
+	}
+	prev_elt = curr_elt;
+	curr_elt = curr_elt->next;
+    }
+
+    /* module not found. create and add to list */
+    status = kdb_load_library(kcontext, lib_name, lib);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    if (prev_elt) {
+	/* prev_elt points to the last element in the list */
+	prev_elt->next = *lib;
+	(*lib)->prev = prev_elt;
+    } else {
+	lib_list = *lib;
+    }
+
+  clean_n_exit:
+    if (*lib) {
+	(*lib)->reference_cnt++;
+    }
+
+    if (locked) {
+	kdb_unlock_list();
+    }
+
+    return status;
+}
+
+static krb5_error_code
+kdb_free_library(db_library lib)
+{
+    krb5_error_code status = 0;
+    int     locked = 0;
+
+    if ((status = kdb_lock_list()) != 0) {
+	goto clean_n_exit;
+    }
+    locked = 1;
+
+    lib->reference_cnt--;
+
+    if (lib->reference_cnt == 0) {
+	status = lib->vftabl.fini_library();
+	if (status) {
+	    goto clean_n_exit;
+	}
+
+	/* close the library */
+        if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle))) {
+            krb5int_close_plugin_dirs (&lib->dl_dir_handle);
+        }
+        
+	kdb_destroy_lib_lock(lib);
+
+	if (lib->prev == NULL) {
+	    /* first element in the list */
+	    lib_list = lib->next;
+	} else {
+	    lib->prev->next = lib->next;
+	}
+
+	if (lib->next) {
+	    lib->next->prev = lib->prev;
+	}
+	free(lib);
+    }
+
+  clean_n_exit:
+    if (locked) {
+	kdb_unlock_list();
+    }
+
+    return status;
+}
+
+static krb5_error_code
+kdb_setup_lib_handle(krb5_context kcontext)
+{
+    char   *library = NULL;
+    krb5_error_code status = 0;
+    db_library lib = NULL;
+    kdb5_dal_handle *dal_handle = NULL;
+
+    dal_handle = calloc((size_t) 1, sizeof(kdb5_dal_handle));
+    if (dal_handle == NULL) {
+	status = ENOMEM;
+	goto clean_n_exit;
+    }
+
+    library = kdb_get_library_name(kcontext);
+    if (library == NULL) {
+	status = KRB5_KDB_DBTYPE_NOTFOUND;
+	goto clean_n_exit;
+    }
+
+    status = kdb_find_library(kcontext, library, &lib);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    dal_handle->lib_handle = lib;
+    kcontext->db_context = (void *) dal_handle;
+
+  clean_n_exit:
+    free(library);
+
+    if (status) {
+	free(dal_handle);
+	if (lib) {
+	    kdb_free_library(lib);
+	}
+    }
+
+    return status;
+}
+
+static krb5_error_code
+kdb_free_lib_handle(krb5_context kcontext)
+{
+    krb5_error_code status = 0;
+
+    status =
+	kdb_free_library(((kdb5_dal_handle *) kcontext->db_context)->
+			 lib_handle);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    free(kcontext->db_context);
+    kcontext->db_context = NULL;
+
+  clean_n_exit:
+    return status;
+}
+
+static void
+get_errmsg (krb5_context kcontext, krb5_error_code err_code)
+{
+    kdb5_dal_handle *dal_handle;
+    const char *e;
+    if (err_code == 0)
+	return;
+    assert(kcontext != NULL);
+    /* Must be called with dal_handle->lib_handle locked!  */
+    assert(kcontext->db_context != NULL);
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    if (dal_handle->lib_handle->vftabl.errcode_2_string == NULL)
+	return;
+    e = dal_handle->lib_handle->vftabl.errcode_2_string(kcontext, err_code);
+    assert (e != NULL);
+    krb5_set_error_message(kcontext, err_code, "%s", e);
+    if (dal_handle->lib_handle->vftabl.release_errcode_string)
+	dal_handle->lib_handle->vftabl.release_errcode_string(kcontext, e);
+}
+
+/*
+ *      External functions... DAL API
+ */
+krb5_error_code
+krb5_db_open(krb5_context kcontext, char **db_args, int mode)
+{
+    krb5_error_code status = 0;
+    char   *section = NULL;
+    kdb5_dal_handle *dal_handle;
+
+    section = kdb_get_conf_section(kcontext);
+    if (section == NULL) {
+	status = KRB5_KDB_SERVER_INTERNAL_ERR;
+	krb5_set_error_message (kcontext, status,
+		"unable to determine configuration section for realm %s\n",
+		kcontext->default_realm ? kcontext->default_realm : "[UNSET]");
+	goto clean_n_exit;
+    }
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.init_module(kcontext, section, db_args,
+						   mode);
+    get_errmsg(kcontext, status);
+
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    if (section)
+	free(section);
+    return status;
+}
+
+krb5_error_code
+krb5_db_inited(krb5_context kcontext)
+{
+    return !(kcontext && kcontext->db_context &&
+	     ((kdb5_dal_handle *) kcontext->db_context)->db_context);
+}
+
+krb5_error_code
+krb5_db_create(krb5_context kcontext, char **db_args)
+{
+    krb5_error_code status = 0;
+    char   *section = NULL;
+    kdb5_dal_handle *dal_handle;
+
+    section = kdb_get_conf_section(kcontext);
+    if (section == NULL) {
+	status = KRB5_KDB_SERVER_INTERNAL_ERR;
+	krb5_set_error_message (kcontext, status,
+		"unable to determine configuration section for realm %s\n",
+		kcontext->default_realm);
+	goto clean_n_exit;
+    }
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_create(kcontext, section, db_args);
+    get_errmsg(kcontext, status);
+
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    if (section)
+	free(section);
+    return status;
+}
+
+krb5_error_code
+krb5_db_fini(krb5_context kcontext)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	/* module not loaded. So nothing to be done */
+	goto clean_n_exit;
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.fini_module(kcontext);
+    get_errmsg(kcontext, status);
+
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = kdb_free_lib_handle(kcontext);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_destroy(krb5_context kcontext, char **db_args)
+{
+    krb5_error_code status = 0;
+    char   *section = NULL;
+    kdb5_dal_handle *dal_handle;
+
+    section = kdb_get_conf_section(kcontext);
+    if (section == NULL) {
+	status = KRB5_KDB_SERVER_INTERNAL_ERR;
+	krb5_set_error_message (kcontext, status,
+		"unable to determine configuration section for realm %s\n",
+		kcontext->default_realm);
+	goto clean_n_exit;
+    }
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_destroy(kcontext, section, db_args);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    if (section)
+	free(section);
+    return status;
+}
+
+krb5_error_code
+krb5_db_get_age(krb5_context kcontext, char *db_name, time_t * t)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_get_age(kcontext, db_name, t);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_set_option(krb5_context kcontext, int option, void *value)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_set_option(kcontext, option, value);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_lock(krb5_context kcontext, int lock_mode)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    /* acquire an exclusive lock, ensures no other thread uses this context */
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, TRUE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_lock(kcontext, lock_mode);
+    get_errmsg(kcontext, status);
+
+    /* exclusive lock is still held, so no other thread could use this context */
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_unlock(krb5_context kcontext)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    /* normal lock acquired and exclusive lock released */
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_unlock(kcontext);
+    get_errmsg(kcontext, status);
+
+    kdb_unlock_lib_lock(dal_handle->lib_handle, TRUE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_get_principal(krb5_context kcontext,
+		      krb5_const_principal search_for,
+		      krb5_db_entry * entries,
+		      int *nentries, krb5_boolean * more)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_get_principal(kcontext, search_for,
+							entries, nentries,
+							more);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_free_principal(krb5_context kcontext, krb5_db_entry * entry, int count)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_free_principal(kcontext, entry,
+							 count);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_put_principal(krb5_context kcontext,
+		      krb5_db_entry * entries, int *nentries)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+    char  **db_args = NULL;
+    krb5_tl_data *prev, *curr, *next;
+    int     db_args_size = 0;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    /* Giving db_args as part of tl data causes, db2 to store the
+       tl_data as such.  To prevent this, tl_data is collated and
+       passed as a sepearte argument. Currently supports only one
+       principal.  but passing it as a seperate argument makes it
+       difficult for kadmin remote to pass arguments to server.  */
+    prev = NULL, curr = entries->tl_data;
+    while (curr) {
+	if (curr->tl_data_type == KRB5_TL_DB_ARGS) {
+	    char  **t;
+	    /* Since this is expected to be NULL terminated string and
+	       this could come from any client, do a check before
+	       passing it to db.  */
+	    if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] !=
+		'\0') {
+		/* not null terminated. Dangerous input */
+		status = EINVAL;
+		goto clean_n_exit;
+	    }
+
+	    db_args_size++;
+	    t = realloc(db_args, sizeof(char *) * (db_args_size + 1));	/* 1 for NULL */
+	    if (t == NULL) {
+		status = ENOMEM;
+		goto clean_n_exit;
+	    }
+
+	    db_args = t;
+	    db_args[db_args_size - 1] = (char *) curr->tl_data_contents;
+	    db_args[db_args_size] = NULL;
+
+	    next = curr->tl_data_next;
+	    if (prev == NULL) {
+		/* current node is the first in the linked list. remove it */
+		entries->tl_data = curr->tl_data_next;
+	    } else {
+		prev->tl_data_next = curr->tl_data_next;
+	    }
+	    entries->n_tl_data--;
+	    krb5_db_free(kcontext, curr);
+
+	    /* previous does not change */
+	    curr = next;
+	} else {
+	    prev = curr;
+	    curr = curr->tl_data_next;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_put_principal(kcontext, entries,
+							     nentries,
+							     db_args);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    while (db_args_size) {
+	if (db_args[db_args_size - 1])
+	    krb5_db_free(kcontext, db_args[db_args_size - 1]);
+
+	db_args_size--;
+    }
+
+    if (db_args)
+	free(db_args);
+
+    return status;
+}
+
+krb5_error_code
+krb5_db_delete_principal(krb5_context kcontext,
+			 krb5_principal search_for, int *nentries)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_delete_principal(kcontext,
+							   search_for,
+							   nentries);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_iterate(krb5_context kcontext,
+		char *match_entry,
+		int (*func) (krb5_pointer, krb5_db_entry *),
+		krb5_pointer func_arg)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_iterate(kcontext,
+						       match_entry,
+						       func, func_arg);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_supported_realms(krb5_context kcontext, char **realms)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_supported_realms(kcontext, realms);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_free_supported_realms(krb5_context kcontext, char **realms)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_free_supported_realms(kcontext,
+								realms);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_set_master_key_ext(krb5_context kcontext,
+			   char *pwd, krb5_keyblock * key)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.set_master_key(kcontext, pwd, key);
+    get_errmsg(kcontext, status);
+
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_set_mkey(krb5_context context, krb5_keyblock * key)
+{
+    return krb5_db_set_master_key_ext(context, NULL, key);
+}
+
+krb5_error_code
+krb5_db_get_mkey(krb5_context kcontext, krb5_keyblock ** key)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    /* Lets use temp key and copy it later to avoid memory problems
+       when freed by the caller.  */
+    status = dal_handle->lib_handle->vftabl.get_master_key(kcontext, key);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_store_master_key(krb5_context kcontext,
+			 char *db_arg,
+			 krb5_principal mname,
+			 krb5_keyblock * key, char *master_pwd)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.store_master_key(kcontext,
+							     db_arg,
+							     mname,
+							     key, master_pwd);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+char   *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
+char   *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
+
+krb5_error_code
+krb5_db_fetch_mkey(krb5_context context,
+		   krb5_principal mname,
+		   krb5_enctype etype,
+		   krb5_boolean fromkeyboard,
+		   krb5_boolean twice,
+		   char *db_args, krb5_data * salt, krb5_keyblock * key)
+{
+    krb5_error_code retval;
+    char    password[BUFSIZ];
+    krb5_data pwd;
+    unsigned int size = sizeof(password);
+    int     kvno;
+    krb5_keyblock tmp_key;
+
+    memset(&tmp_key, 0, sizeof(tmp_key));
+
+    if (fromkeyboard) {
+	krb5_data scratch;
+
+	if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
+					 twice ? krb5_mkey_pwd_prompt2 : 0,
+					 password, &size))) {
+	    goto clean_n_exit;
+	}
+
+	pwd.data = password;
+	pwd.length = size;
+	if (!salt) {
+	    retval = krb5_principal2salt(context, mname, &scratch);
+	    if (retval)
+		goto clean_n_exit;
+	}
+	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 */
+
+    } else {
+	kdb5_dal_handle *dal_handle;
+
+	if (context->db_context == NULL) {
+	    retval = kdb_setup_lib_handle(context);
+	    if (retval) {
+		goto clean_n_exit;
+	    }
+	}
+
+	dal_handle = (kdb5_dal_handle *) context->db_context;
+	retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+	if (retval) {
+	    goto clean_n_exit;
+	}
+
+	tmp_key.enctype = key->enctype;
+	retval = dal_handle->lib_handle->vftabl.fetch_master_key(context,
+								 mname,
+								 &tmp_key,
+								 &kvno,
+								 db_args);
+	get_errmsg(context, retval);
+	kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+	if (retval) {
+	    goto clean_n_exit;
+	}
+
+	key->contents = malloc(tmp_key.length);
+	if (key->contents == NULL) {
+	    retval = ENOMEM;
+	    goto clean_n_exit;
+	}
+
+	key->magic = tmp_key.magic;
+	key->enctype = tmp_key.enctype;
+	key->length = tmp_key.length;
+	memcpy(key->contents, tmp_key.contents, tmp_key.length);
+    }
+
+  clean_n_exit:
+    if (tmp_key.contents) {
+	memset(tmp_key.contents, 0, tmp_key.length);
+	krb5_db_free(context, tmp_key.contents);
+    }
+    return retval;
+}
+
+krb5_error_code
+krb5_db_verify_master_key(krb5_context kcontext,
+			  krb5_principal mprinc, krb5_keyblock * mkey)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.verify_master_key(kcontext,
+							      mprinc, mkey);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+void   *
+krb5_db_alloc(krb5_context kcontext, void *ptr, size_t size)
+{
+    krb5_error_code status;
+    kdb5_dal_handle *dal_handle;
+    void   *new_ptr = NULL;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+
+    new_ptr = dal_handle->lib_handle->vftabl.db_alloc(kcontext, ptr, size);
+
+  clean_n_exit:
+    return new_ptr;
+}
+
+void
+krb5_db_free(krb5_context kcontext, void *ptr)
+{
+    krb5_error_code status;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+
+    dal_handle->lib_handle->vftabl.db_free(kcontext, ptr);
+
+  clean_n_exit:
+    return;
+}
+
+/* has to be modified */
+
+krb5_error_code
+krb5_dbe_find_enctype(krb5_context kcontext,
+		      krb5_db_entry * dbentp,
+		      krb5_int32 ktype,
+		      krb5_int32 stype,
+		      krb5_int32 kvno, krb5_key_data ** kdatap)
+{
+    krb5_int32 start = 0;
+    return krb5_dbe_search_enctype(kcontext, dbentp, &start, ktype, stype,
+				   kvno, kdatap);
+}
+
+krb5_error_code
+krb5_dbe_search_enctype(krb5_context kcontext,
+			krb5_db_entry * dbentp,
+			krb5_int32 * start,
+			krb5_int32 ktype,
+			krb5_int32 stype,
+			krb5_int32 kvno, krb5_key_data ** kdatap)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.dbe_search_enctype(kcontext,
+							       dbentp,
+							       start,
+							       ktype,
+							       stype,
+							       kvno, kdatap);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+#define	REALM_SEP_STRING	"@"
+
+krb5_error_code
+krb5_db_setup_mkey_name(krb5_context context,
+			const char *keyname,
+			const char *realm,
+			char **fullname, krb5_principal * principal)
+{
+    krb5_error_code retval;
+    size_t  keylen;
+    size_t  rlen = strlen(realm);
+    char   *fname;
+
+    if (!keyname)
+	keyname = KRB5_KDB_M_NAME;	/* XXX external? */
+
+    keylen = strlen(keyname);
+
+    fname = malloc(keylen + rlen + strlen(REALM_SEP_STRING) + 1);
+    if (!fname)
+	return ENOMEM;
+
+    strcpy(fname, keyname);
+    strcat(fname, REALM_SEP_STRING);
+    strcat(fname, realm);
+
+    if ((retval = krb5_parse_name(context, fname, principal)))
+	return retval;
+    if (fullname)
+	*fullname = fname;
+    else
+	free(fname);
+    return 0;
+}
+
+krb5_error_code
+krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
+    krb5_context context;
+    krb5_db_entry *entry;
+    krb5_timestamp *stamp;
+{
+    krb5_tl_data tl_data;
+    krb5_error_code code;
+    krb5_int32 tmp;
+
+    tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+
+    if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
+	return (code);
+
+    if (tl_data.tl_data_length != 4) {
+	*stamp = 0;
+	return (0);
+    }
+
+    krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
+
+    *stamp = (krb5_timestamp) tmp;
+
+    return (0);
+}
+
+krb5_error_code
+krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
+    krb5_context context;
+    krb5_db_entry *entry;
+    krb5_tl_data *ret_tl_data;
+{
+    krb5_tl_data *tl_data;
+
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
+	if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
+	    *ret_tl_data = *tl_data;
+	    return (0);
+	}
+    }
+
+    /* if the requested record isn't found, return zero bytes.
+     * if it ever means something to have a zero-length tl_data,
+     * this code and its callers will have to be changed */
+
+    ret_tl_data->tl_data_length = 0;
+    ret_tl_data->tl_data_contents = NULL;
+    return (0);
+}
+
+krb5_error_code
+krb5_dbe_create_key_data(context, entry)
+    krb5_context context;
+    krb5_db_entry *entry;
+{
+    if ((entry->key_data =
+	 (krb5_key_data *) krb5_db_alloc(context, entry->key_data,
+					 (sizeof(krb5_key_data) *
+					  (entry->n_key_data + 1)))) == NULL)
+	return (ENOMEM);
+
+    memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
+    entry->n_key_data++;
+
+    return 0;
+}
+
+krb5_error_code
+krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
+    krb5_context context;
+    krb5_db_entry *entry;
+    krb5_timestamp mod_date;
+    krb5_const_principal mod_princ;
+{
+    krb5_tl_data tl_data;
+
+    krb5_error_code retval = 0;
+    krb5_octet *nextloc = 0;
+    char   *unparse_mod_princ = 0;
+    unsigned int unparse_mod_princ_size;
+
+    if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ)))
+	return (retval);
+
+    unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
+
+    if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
+	== NULL) {
+	free(unparse_mod_princ);
+	return (ENOMEM);
+    }
+
+    tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
+    tl_data.tl_data_length = unparse_mod_princ_size + 4;
+    tl_data.tl_data_contents = nextloc;
+
+    /* Mod Date */
+    krb5_kdb_encode_int32(mod_date, nextloc);
+
+    /* Mod Princ */
+    memcpy(nextloc + 4, unparse_mod_princ, unparse_mod_princ_size);
+
+    retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
+
+    free(unparse_mod_princ);
+    free(nextloc);
+
+    return (retval);
+}
+
+krb5_error_code
+krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
+    krb5_context context;
+    krb5_db_entry *entry;
+    krb5_timestamp *mod_time;
+    krb5_principal *mod_princ;
+{
+    krb5_tl_data tl_data;
+    krb5_error_code code;
+
+    tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
+
+    if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
+	return (code);
+
+    if ((tl_data.tl_data_length < 5) ||
+	(tl_data.tl_data_contents[tl_data.tl_data_length - 1] != '\0'))
+	return (KRB5_KDB_TRUNCATED_RECORD);
+
+    /* Mod Date */
+    krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
+
+    /* Mod Princ */
+    if ((code = krb5_parse_name(context,
+				(const char *) (tl_data.tl_data_contents + 4),
+				mod_princ)))
+	return (code);
+
+    return (0);
+}
+
+krb5_error_code
+krb5_dbe_update_last_pwd_change(context, entry, stamp)
+    krb5_context context;
+    krb5_db_entry *entry;
+    krb5_timestamp stamp;
+{
+    krb5_tl_data tl_data;
+    krb5_octet buf[4];		/* this is the encoded size of an int32 */
+
+    tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+    tl_data.tl_data_length = sizeof(buf);
+    krb5_kdb_encode_int32((krb5_int32) stamp, buf);
+    tl_data.tl_data_contents = buf;
+
+    return (krb5_dbe_update_tl_data(context, entry, &tl_data));
+}
+
+krb5_error_code
+krb5_dbe_update_tl_data(context, entry, new_tl_data)
+    krb5_context context;
+    krb5_db_entry *entry;
+    krb5_tl_data *new_tl_data;
+{
+    krb5_tl_data *tl_data = NULL;
+    krb5_octet *tmp;
+
+    /* copy the new data first, so we can fail cleanly if malloc()
+     * fails */
+    if ((tmp =
+	 (krb5_octet *) krb5_db_alloc(context, NULL,
+				      new_tl_data->tl_data_length)) == NULL)
+	return (ENOMEM);
+
+    /* Find an existing entry of the specified type and point at
+     * it, or NULL if not found */
+
+    if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) {	/* db_args can be multiple */
+	for (tl_data = entry->tl_data; tl_data;
+	     tl_data = tl_data->tl_data_next)
+	    if (tl_data->tl_data_type == new_tl_data->tl_data_type)
+		break;
+    }
+
+    /* if necessary, chain a new record in the beginning and point at it */
+
+    if (!tl_data) {
+	if ((tl_data =
+	     (krb5_tl_data *) krb5_db_alloc(context, NULL,
+					    sizeof(krb5_tl_data)))
+	    == NULL) {
+	    free(tmp);
+	    return (ENOMEM);
+	}
+	memset(tl_data, 0, sizeof(krb5_tl_data));
+	tl_data->tl_data_next = entry->tl_data;
+	entry->tl_data = tl_data;
+	entry->n_tl_data++;
+    }
+
+    /* fill in the record */
+
+    if (tl_data->tl_data_contents)
+	krb5_db_free(context, tl_data->tl_data_contents);
+
+    tl_data->tl_data_type = new_tl_data->tl_data_type;
+    tl_data->tl_data_length = new_tl_data->tl_data_length;
+    tl_data->tl_data_contents = tmp;
+    memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
+
+    return (0);
+}
+
+/* change password functions */
+krb5_error_code
+krb5_dbe_cpw(krb5_context kcontext,
+	     krb5_keyblock * master_key,
+	     krb5_key_salt_tuple * ks_tuple,
+	     int ks_tuple_count,
+	     char *passwd,
+	     int new_kvno, krb5_boolean keepold, krb5_db_entry * db_entry)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_change_pwd(kcontext,
+							  master_key,
+							  ks_tuple,
+							  ks_tuple_count,
+							  passwd,
+							  new_kvno,
+							  keepold, db_entry);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+/* policy management functions */
+krb5_error_code
+krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_create_policy(kcontext, policy);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_get_policy(krb5_context kcontext, char *name,
+		   osa_policy_ent_t * policy, int *cnt)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_get_policy(kcontext, name, policy,
+						     cnt);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_put_policy(kcontext, policy);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_iter_policy(krb5_context kcontext, char *match_entry,
+		    osa_adb_iter_policy_func func, void *data)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.db_iter_policy(kcontext, match_entry,
+						      func, data);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db_delete_policy(krb5_context kcontext, char *policy)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status = dal_handle->lib_handle->vftabl.db_delete_policy(kcontext, policy);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return status;
+}
+
+void
+krb5_db_free_policy(krb5_context kcontext, osa_policy_ent_t policy)
+{
+    krb5_error_code status = 0;
+    kdb5_dal_handle *dal_handle;
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    dal_handle->lib_handle->vftabl.db_free_policy(kcontext, policy);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    return;
+}
+
+krb5_error_code
+krb5_db_promote(krb5_context kcontext, char **db_args)
+{
+    krb5_error_code status = 0;
+    char   *section = NULL;
+    kdb5_dal_handle *dal_handle;
+
+    section = kdb_get_conf_section(kcontext);
+    if (section == NULL) {
+	status = KRB5_KDB_SERVER_INTERNAL_ERR;
+	krb5_set_error_message (kcontext, status,
+		"unable to determine configuration section for realm %s\n",
+		kcontext->default_realm);
+	goto clean_n_exit;
+    }
+
+    if (kcontext->db_context == NULL) {
+	status = kdb_setup_lib_handle(kcontext);
+	if (status) {
+	    goto clean_n_exit;
+	}
+    }
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    status = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE);
+    if (status) {
+	goto clean_n_exit;
+    }
+
+    status =
+	dal_handle->lib_handle->vftabl.promote_db(kcontext, section, db_args);
+    get_errmsg(kcontext, status);
+    kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
+
+  clean_n_exit:
+    if (section)
+	free(section);
+    return status;
+}
+
diff --git a/krb5-1-6/src/lib/kdb/kdb5.h b/krb5-1-6/src/lib/kdb/kdb5.h
new file mode 100644
index 000000000..f19b077e4
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/kdb5.h
@@ -0,0 +1,197 @@
+#ifndef _KRB5_KDB5_H_
+#define _KRB5_KDB5_H_
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <utime.h>
+#include <utime.h>
+#include <k5-int.h>
+#include "kdb.h"
+
+#define KDB_MAX_DB_NAME 128
+#define KDB_REALM_SECTION  "realms"
+#define KDB_MODULE_POINTER "database_module"
+#define KDB_MODULE_DEF_SECTION "dbdefaults"
+#define KDB_MODULE_SECTION "dbmodules"
+#define KDB_LIB_POINTER    "db_library"
+#define KDB_DATABASE_CONF_FILE  DEFAULT_SECURE_PROFILE_PATH
+#define KDB_DATABASE_ENV_PROF KDC_PROFILE_ENV
+
+#define KRB5_DB_GET_DB_CONTEXT(kcontext) (((kdb5_dal_handle*) (kcontext)->db_context)->db_context)
+#define KRB5_DB_GET_PROFILE(kcontext)  ((kcontext)->profile)
+#define KRB5_DB_GET_REALM(kcontext)    ((kcontext)->default_realm)
+
+typedef struct _kdb_vftabl{
+    short int maj_ver;
+    short int min_ver;
+
+    krb5_error_code (*init_library)();
+    krb5_error_code (*fini_library)();
+    krb5_error_code (*init_module) (krb5_context kcontext,
+				    char * conf_section,
+				    char ** db_args,
+				    int mode);
+
+    krb5_error_code (*fini_module) (krb5_context kcontext);
+
+    krb5_error_code (*db_create) (krb5_context kcontext,
+				  char * conf_section,
+				  char ** db_args);
+
+    krb5_error_code (*db_destroy) (krb5_context kcontext,
+				   char *conf_section,
+				   char ** db_args);
+
+    krb5_error_code (*db_get_age) (krb5_context kcontext,
+				   char *db_name,
+				   time_t *age);
+
+    krb5_error_code (*db_set_option) (krb5_context kcontext,
+				      int option,
+				      void *value);
+
+    krb5_error_code (*db_lock) (krb5_context kcontext,
+				int mode);
+
+    krb5_error_code (*db_unlock) (krb5_context kcontext);
+
+    krb5_error_code (*db_get_principal) (krb5_context kcontext,
+					 krb5_const_principal search_for,
+					 krb5_db_entry *entries,
+					 int *nentries,
+					 krb5_boolean *more);
+
+    krb5_error_code (*db_free_principal) (krb5_context kcontext,
+					  krb5_db_entry *entry,
+					  int count);
+
+    krb5_error_code (*db_put_principal) (krb5_context kcontext,
+					 krb5_db_entry *entries,
+					 int *nentries,
+					 char **db_args);
+
+    krb5_error_code (*db_delete_principal) (krb5_context kcontext,
+					    krb5_const_principal search_for,
+					    int *nentries);
+
+    krb5_error_code (*db_iterate) (krb5_context kcontext,
+				   char *match_entry,
+				   int (*func) (krb5_pointer, krb5_db_entry *),
+				   krb5_pointer func_arg);
+
+    krb5_error_code (*db_create_policy) (krb5_context kcontext,
+					 osa_policy_ent_t policy);
+
+    krb5_error_code (*db_get_policy) (krb5_context kcontext,
+				      char *name,
+				      osa_policy_ent_t *policy,
+				      int *cnt);
+
+    krb5_error_code (*db_put_policy) (krb5_context kcontext,
+				      osa_policy_ent_t policy);
+
+    krb5_error_code (*db_iter_policy) (krb5_context kcontext,
+				       char *match_entry,
+				       osa_adb_iter_policy_func func,
+				       void *data);
+
+
+    krb5_error_code (*db_delete_policy) (krb5_context kcontext,
+					 char *policy);
+
+    void (*db_free_policy) (krb5_context kcontext,
+			    osa_policy_ent_t val);
+
+    krb5_error_code (*db_supported_realms) (krb5_context kcontext,
+					    char **realms);
+
+    krb5_error_code (*db_free_supported_realms) (krb5_context kcontext,
+						 char **realms);
+
+
+    const char * (*errcode_2_string) (krb5_context kcontext,
+				      long err_code);
+    void (*release_errcode_string) (krb5_context kcontext, const char *msg);
+
+    void * (*db_alloc) (krb5_context kcontext, void *ptr, size_t size);
+    void   (*db_free)  (krb5_context kcontext, void *ptr);
+
+
+
+    /* optional functions */
+    krb5_error_code (*set_master_key) (krb5_context kcontext,
+				       char *pwd,
+				       krb5_keyblock *key);
+
+    krb5_error_code (*get_master_key) (krb5_context kcontext,
+				       krb5_keyblock **key);
+
+
+    krb5_error_code (*setup_master_key_name) (krb5_context kcontext,
+					      char *keyname,
+					      char *realm,
+					      char **fullname,
+					      krb5_principal  *principal);
+
+    krb5_error_code (*store_master_key) (krb5_context kcontext,
+					 char *db_arg,
+					 krb5_principal mname,
+					 krb5_keyblock *key,
+					 char *master_pwd);
+
+    krb5_error_code (*fetch_master_key) (krb5_context kcontext,
+					 krb5_principal mname,
+					 krb5_keyblock *key,
+					 int *kvno,
+					 char *db_args);
+
+    krb5_error_code (*verify_master_key) (krb5_context kcontext,
+					  krb5_principal mprinc,
+					  krb5_keyblock *mkey);
+
+    krb5_error_code (*dbe_search_enctype) (krb5_context kcontext,
+					   krb5_db_entry *dbentp,
+					   krb5_int32 *start,
+					   krb5_int32 ktype,
+					   krb5_int32 stype,
+					   krb5_int32 kvno,
+					   krb5_key_data **kdatap);
+
+
+    krb5_error_code
+    (*db_change_pwd) (krb5_context	  context,
+		      krb5_keyblock     * master_key,
+		      krb5_key_salt_tuple * ks_tuple,
+		      int		  ks_tuple_count,
+		      char 		* passwd,
+		      int		  new_kvno,
+		      krb5_boolean	  keepold,
+		      krb5_db_entry	* db_entry);
+
+    /* Promote a temporary database to be the live one.  */
+    krb5_error_code (*promote_db) (krb5_context context,
+				   char *conf_section,
+				   char **db_args);
+
+} kdb_vftabl;
+
+typedef struct _db_library {
+    char name[KDB_MAX_DB_NAME];
+    int reference_cnt;
+    struct plugin_dir_handle dl_dir_handle;
+    kdb_vftabl vftabl;
+    struct _db_library *next, *prev;
+} *db_library;
+
+typedef struct _kdb5_dal_handle
+{
+    /* Helps us to change db_library without affecting modules to some
+       extent.  */
+    void *db_context;
+    db_library lib_handle;
+} kdb5_dal_handle;
+
+#endif  /* end of _KRB5_KDB5_H_ */
diff --git a/krb5-1-6/src/lib/kdb/kdb_cpw.c b/krb5-1-6/src/lib/kdb/kdb_cpw.c
new file mode 100644
index 000000000..86bec7a43
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/kdb_cpw.c
@@ -0,0 +1,649 @@
+/*
+ * lib/kdb/kdb_cpw.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+/*
+ * Copyright (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 "kdb.h"
+#include <stdio.h>
+#include <errno.h>
+
+static int
+get_key_data_kvno(context, count, data)
+    krb5_context	  context;
+    int			  count;
+    krb5_key_data	* data;
+{
+    int i, kvno;
+    /* Find last key version number */
+    for (kvno = i = 0; i < count; i++) {
+	if (kvno < data[i].key_data_kvno) {
+	    kvno = data[i].key_data_kvno;
+	}
+    }
+    return(kvno);
+}
+
+static void
+cleanup_key_data(context, count, data)
+    krb5_context	  context;
+    int			  count;
+    krb5_key_data	* data;
+{
+    int i, j;
+
+    /* If data is NULL, count is always 0 */
+    if (data == NULL) return;
+
+    for (i = 0; i < count; i++) {
+	for (j = 0; j < data[i].key_data_ver; j++) {
+	    if (data[i].key_data_length[j]) {
+	    	krb5_db_free(context, data[i].key_data_contents[j]);
+	    }
+	}
+    }
+    krb5_db_free(context, data);
+}
+
+static krb5_error_code
+add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno)
+    krb5_context	  context;
+    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	  key;
+    krb5_db_entry	  krbtgt_entry;
+    krb5_boolean	  more;
+    int			  max_kvno, one, i, j, k;
+    krb5_error_code	  retval;
+    krb5_key_data         tmp_key_data;
+    krb5_key_data        *tptr;
+
+    memset( &tmp_key_data, 0, sizeof(tmp_key_data));
+
+
+    retval = krb5_build_principal_ext(context, &krbtgt_princ,
+				      db_entry->princ->realm.length,
+				      db_entry->princ->realm.data,
+				      KRB5_TGS_NAME_SIZE,
+				      KRB5_TGS_NAME,
+				      db_entry->princ->realm.length,
+				      db_entry->princ->realm.data,
+				      0);
+    if (retval)
+	return retval;
+
+    /* Get tgt from database */
+    retval = krb5_db_get_principal(context, krbtgt_princ, &krbtgt_entry,
+				   &one, &more);
+    krb5_free_principal(context, krbtgt_princ); /* don't need it anymore */
+    if (retval)
+	return(retval);
+    if ((one > 1) || (more)) {
+	krb5_db_free_principal(context, &krbtgt_entry, one);
+	return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
+    }
+    if (!one) 
+	return KRB5_KDB_NOENTRY;
+
+    /* Get max kvno */
+    for (max_kvno = j = 0; j < krbtgt_entry.n_key_data; j++) {
+	 if (max_kvno < krbtgt_entry.key_data[j].key_data_kvno) {
+	     max_kvno = krbtgt_entry.key_data[j].key_data_kvno;
+	}
+    }
+
+    for (i = 0; i < ks_tuple_count; i++) {
+	krb5_boolean similar;
+
+	similar = 0;
+
+	/*
+	 * 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 (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)
+		break;
+	}
+
+	if (similar)
+	    continue;
+
+        if ((retval = krb5_dbe_create_key_data(context, db_entry))) 
+	    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. */
+
+	/* make new key */
+	if ((retval = krb5_c_make_random_key(context, ks_tuple[i].ks_enctype,
+					     &key)))
+	    goto add_key_rnd_err;
+
+
+	/* db library will free this. Since, its a so, it could actually be using different memory management
+	   function. So, its better if the memory is allocated by the db's malloc. So, a temporary memory is used
+	   here which will later be copied to the db_entry */
+    	retval = krb5_dbekd_encrypt_key_data(context, master_key, 
+					     &key, NULL, kvno, 
+					     &tmp_key_data); 
+
+	krb5_free_keyblock_contents(context, &key);
+	if( retval )
+	    goto add_key_rnd_err;
+
+	tptr = &db_entry->key_data[db_entry->n_key_data-1];
+
+	tptr->key_data_ver = tmp_key_data.key_data_ver;
+	tptr->key_data_kvno = tmp_key_data.key_data_kvno;
+
+	for( k = 0; k < tmp_key_data.key_data_ver; k++ )
+	{
+	    tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
+	    tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
+	    if( tmp_key_data.key_data_contents[k] )
+	    {
+		tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
+		if( tptr->key_data_contents[k] == NULL )
+		{
+		    cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+		    db_entry->key_data = NULL;
+		    db_entry->n_key_data = 0;
+		    retval = ENOMEM;
+		    goto add_key_rnd_err;
+		}
+		memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+		memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+		free( tmp_key_data.key_data_contents[k] );
+		tmp_key_data.key_data_contents[k] = NULL;
+	    }
+	}
+
+    }
+
+add_key_rnd_err:
+    krb5_db_free_principal(context, &krbtgt_entry, one);
+
+    for( i = 0; i < tmp_key_data.key_data_ver; i++ )
+    {
+	if( tmp_key_data.key_data_contents[i] )
+	{
+	    memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+	    free( tmp_key_data.key_data_contents[i] );
+	}
+    }
+    return(retval);
+}
+
+/*
+ * Change random key for a krb5_db_entry 
+ * Assumes the max kvno
+ *
+ * As a side effect all old keys are nuked if keepold is false.
+ */
+krb5_error_code
+krb5_dbe_crk(context, master_key, ks_tuple, ks_tuple_count, keepold, db_entry)
+    krb5_context	  context;
+    krb5_keyblock       * master_key;
+    krb5_key_salt_tuple	* ks_tuple;
+    int			  ks_tuple_count;
+    krb5_boolean	  keepold;
+    krb5_db_entry	* db_entry;
+{
+    int 		  key_data_count;
+    int			  n_new_key_data;
+    krb5_key_data 	* key_data;
+    krb5_error_code	  retval;
+    int			  kvno;
+    int			  i;
+
+    /* First save the old keydata */
+    kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data);
+    key_data_count = db_entry->n_key_data;
+    key_data = db_entry->key_data;
+    db_entry->key_data = NULL;
+    db_entry->n_key_data = 0;
+
+    /* increment the kvno */
+    kvno++;
+
+    retval = add_key_rnd(context, master_key, ks_tuple,
+			 ks_tuple_count, db_entry, kvno);
+    if (retval) {
+	cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+	db_entry->n_key_data = key_data_count;
+	db_entry->key_data = key_data;
+    } else if (keepold) {
+	n_new_key_data = db_entry->n_key_data;
+	for (i = 0; i < key_data_count; i++) {
+	    retval = krb5_dbe_create_key_data(context, db_entry);
+	    if (retval) {
+		cleanup_key_data(context, db_entry->n_key_data,
+				 db_entry->key_data);
+		break;
+	    }
+	    db_entry->key_data[i+n_new_key_data] = key_data[i];
+	    memset(&key_data[i], 0, sizeof(krb5_key_data));
+	}
+	krb5_db_free(context, key_data); /* we moved the cotents to new memory. But, the original block which contained the data */
+    } else {
+	cleanup_key_data(context, key_data_count, key_data);
+    }
+    return(retval);
+}
+
+/*
+ * Add random key for a krb5_db_entry 
+ * Assumes the max kvno
+ *
+ * As a side effect all old keys older than the max kvno are nuked.
+ */
+krb5_error_code
+krb5_dbe_ark(context, master_key, ks_tuple, ks_tuple_count, db_entry)
+    krb5_context	  context;
+    krb5_keyblock       * master_key;
+    krb5_key_salt_tuple	* ks_tuple;
+    int			  ks_tuple_count;
+    krb5_db_entry	* db_entry;
+{
+    int 		  key_data_count;
+    krb5_key_data 	* key_data;
+    krb5_error_code	  retval;
+    int			  kvno;
+    int			  i;
+
+    /* First save the old keydata */
+    kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data);
+    key_data_count = db_entry->n_key_data;
+    key_data = db_entry->key_data;
+    db_entry->key_data = NULL;
+    db_entry->n_key_data = 0;
+
+    /* increment the kvno */
+    kvno++;
+
+    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;
+	db_entry->key_data = key_data;
+    } else {
+	/* Copy keys with key_data_kvno == kvno - 1 ( = old kvno ) */
+	for (i = 0; i < key_data_count; i++) {
+	    if (key_data[i].key_data_kvno == (kvno - 1)) {
+		if ((retval = krb5_dbe_create_key_data(context, db_entry))) {
+		    cleanup_key_data(context, db_entry->n_key_data,
+				     db_entry->key_data);
+		    break;
+		}
+		/* We should decrypt/re-encrypt the data to use the same mkvno*/
+		db_entry->key_data[db_entry->n_key_data - 1] = key_data[i];
+		memset(&key_data[i], 0, sizeof(krb5_key_data));
+	    }
+	}
+	cleanup_key_data(context, key_data_count, key_data);
+    }
+    return(retval);
+}
+
+/*
+ * Add key_data for a krb5_db_entry 
+ * If passwd is NULL the assumes that the caller wants a random password.
+ */
+static krb5_error_code
+add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd, 
+	    db_entry, kvno)
+    krb5_context	  context;
+    krb5_keyblock       * master_key;
+    krb5_key_salt_tuple	* ks_tuple;
+    int			  ks_tuple_count;
+    char 		* passwd;
+    krb5_db_entry	* db_entry;
+    int			  kvno;
+{
+    krb5_error_code	  retval;
+    krb5_keysalt	  key_salt;
+    krb5_keyblock	  key;
+    krb5_data	  	  pwd;
+    int			  i, j, k;
+    krb5_key_data         tmp_key_data;
+    krb5_key_data        *tptr;
+
+    memset( &tmp_key_data, 0, sizeof(tmp_key_data));
+
+    retval = 0;
+
+    for (i = 0; i < ks_tuple_count; i++) {
+	krb5_boolean similar;
+
+	similar = 0;
+
+	/*
+	 * 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 (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 (j < i)
+	    continue;
+
+	if ((retval = krb5_dbe_create_key_data(context, db_entry))) 
+	    return(retval);
+
+	/* Convert password string to key using appropriate salt */
+	switch (key_salt.type = ks_tuple[i].ks_salttype) {
+    	case KRB5_KDB_SALTTYPE_ONLYREALM: {
+            krb5_data * saltdata;
+            if ((retval = krb5_copy_data(context, krb5_princ_realm(context,
+					      db_entry->princ), &saltdata)))
+	 	return(retval);
+
+	    key_salt.data = *saltdata;
+	    krb5_xfree(saltdata);
+	}
+		break;
+    	case KRB5_KDB_SALTTYPE_NOREALM:
+            if ((retval=krb5_principal2salt_norealm(context, db_entry->princ,
+						    &key_salt.data))) 
+		return(retval);
+            break;
+	case KRB5_KDB_SALTTYPE_NORMAL:
+            if ((retval = krb5_principal2salt(context, db_entry->princ,
+					      &key_salt.data))) 
+		return(retval);
+            break;
+    	case KRB5_KDB_SALTTYPE_V4:
+            key_salt.data.length = 0;
+            key_salt.data.data = 0;
+            break;
+    	case KRB5_KDB_SALTTYPE_AFS3: {
+#if 0
+            krb5_data * saltdata;
+            if (retval = krb5_copy_data(context, krb5_princ_realm(context,
+					db_entry->princ), &saltdata))
+	 	return(retval);
+
+	    key_salt.data = *saltdata;
+	    key_salt.data.length = SALT_TYPE_AFS_LENGTH; /*length actually used below...*/
+	    krb5_xfree(saltdata);
+#else
+	    /* Why do we do this? Well, the afs_mit_string_to_key needs to
+	       use strlen, and the realm is not NULL terminated.... */
+	    unsigned int slen = 
+		(*krb5_princ_realm(context,db_entry->princ)).length;
+	    if(!(key_salt.data.data = (char *) malloc(slen+1)))
+	        return ENOMEM;
+	    key_salt.data.data[slen] = 0;
+	    memcpy((char *)key_salt.data.data,
+		   (char *)(*krb5_princ_realm(context,db_entry->princ)).data,
+		   slen);
+	    key_salt.data.length = SALT_TYPE_AFS_LENGTH; /*length actually used below...*/
+#endif
+
+	}
+		break;
+	default:
+	    return(KRB5_KDB_BAD_SALTTYPE);
+	}
+
+    	pwd.data = passwd;
+    	pwd.length = strlen(passwd);
+
+	/* AFS string to key will happen here */
+	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);
+	}
+
+	if (key_salt.data.length == SALT_TYPE_AFS_LENGTH)
+	    key_salt.data.length = 
+	      krb5_princ_realm(context, db_entry->princ)->length;
+
+	/* memory allocation to be done by db. So, use temporary block and later copy
+	   it to the memory allocated by db */
+	retval = krb5_dbekd_encrypt_key_data(context, master_key, &key,
+					     (const krb5_keysalt *)&key_salt,
+					     kvno, &tmp_key_data);
+	if (key_salt.data.data)
+	    free(key_salt.data.data);
+	krb5_xfree(key.contents);
+
+	if( retval )
+	    return retval;
+
+	tptr = &db_entry->key_data[db_entry->n_key_data-1];
+
+	tptr->key_data_ver = tmp_key_data.key_data_ver;
+	tptr->key_data_kvno = tmp_key_data.key_data_kvno;
+
+	for( k = 0; k < tmp_key_data.key_data_ver; k++ )
+	{
+	    tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
+	    tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
+	    if( tmp_key_data.key_data_contents[k] )
+	    {
+		tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
+		if( tptr->key_data_contents[k] == NULL )
+		{
+		    cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+		    db_entry->key_data = NULL;
+		    db_entry->n_key_data = 0;
+		    retval = ENOMEM;
+		    goto add_key_pwd_err;
+		}
+		memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+		memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+		free( tmp_key_data.key_data_contents[k] );
+		tmp_key_data.key_data_contents[k] = NULL;
+	    }
+	}
+    }
+ add_key_pwd_err:
+    for( i = 0; i < tmp_key_data.key_data_ver; i++ )
+    {
+	if( tmp_key_data.key_data_contents[i] )
+	{
+	    memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+	    free( tmp_key_data.key_data_contents[i] );
+	}
+    }
+
+    return(retval);
+}
+
+/*
+ * Change password for a krb5_db_entry 
+ * Assumes the max kvno
+ *
+ * As a side effect all old keys are nuked if keepold is false.
+ */
+krb5_error_code
+krb5_dbe_def_cpw(context, master_key, ks_tuple, ks_tuple_count, passwd,
+	     new_kvno, keepold, db_entry)
+    krb5_context	  context;
+    krb5_keyblock       * master_key;
+    krb5_key_salt_tuple	* ks_tuple;
+    int			  ks_tuple_count;
+    char 		* passwd;
+    int			  new_kvno;
+    krb5_boolean	  keepold;
+    krb5_db_entry	* db_entry;
+{
+    int 		  key_data_count;
+    int			  n_new_key_data;
+    krb5_key_data 	* key_data;
+    krb5_error_code	  retval;
+    int			  old_kvno;
+    int			  i;
+
+    /* First save the old keydata */
+    old_kvno = get_key_data_kvno(context, db_entry->n_key_data,
+				 db_entry->key_data);
+    key_data_count = db_entry->n_key_data;
+    key_data = db_entry->key_data;
+    db_entry->key_data = NULL;
+    db_entry->n_key_data = 0;
+
+    /* increment the kvno.  if the requested kvno is too small, 
+       increment the old kvno */
+    if (new_kvno < old_kvno+1)
+       new_kvno = old_kvno+1;
+
+    retval = add_key_pwd(context, master_key, ks_tuple, ks_tuple_count,
+			 passwd, db_entry, new_kvno);
+    if (retval) {
+	cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+	db_entry->n_key_data = key_data_count;
+	db_entry->key_data = key_data;
+    } else if (keepold) {
+	n_new_key_data = db_entry->n_key_data;
+	for (i = 0; i < key_data_count; i++) {
+	    retval = krb5_dbe_create_key_data(context, db_entry);
+	    if (retval) {
+		cleanup_key_data(context, db_entry->n_key_data,
+				 db_entry->key_data);
+		break;
+	    }
+	    db_entry->key_data[i+n_new_key_data] = key_data[i];
+	    memset(&key_data[i], 0, sizeof(krb5_key_data));
+	}
+	krb5_db_free( context, key_data );
+    } else {
+	cleanup_key_data(context, key_data_count, key_data);
+    }
+    return(retval);
+}
+
+/*
+ * Add password for a krb5_db_entry 
+ * Assumes the max kvno
+ *
+ * As a side effect all old keys older than the max kvno are nuked.
+ */
+krb5_error_code
+krb5_dbe_apw(context, master_key, ks_tuple, ks_tuple_count, passwd, db_entry)
+    krb5_context	  context;
+    krb5_keyblock       * master_key;
+    krb5_key_salt_tuple	* ks_tuple;
+    int			  ks_tuple_count;
+    char 		* passwd;
+    krb5_db_entry	* db_entry;
+{
+    int 		  key_data_count;
+    krb5_key_data 	* key_data;
+    krb5_error_code	  retval;
+    int			  old_kvno, new_kvno;
+    int			  i;
+
+    /* First save the old keydata */
+    old_kvno = get_key_data_kvno(context, db_entry->n_key_data,
+				 db_entry->key_data);
+    key_data_count = db_entry->n_key_data;
+    key_data = db_entry->key_data;
+    db_entry->key_data = NULL;
+    db_entry->n_key_data = 0;
+
+    /* increment the kvno */
+    new_kvno = old_kvno+1;
+
+    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;
+	db_entry->key_data = key_data;
+    } else {
+	/* Copy keys with key_data_kvno == old_kvno */
+	for (i = 0; i < key_data_count; i++) {
+	    if (key_data[i].key_data_kvno == old_kvno) {
+		if ((retval = krb5_dbe_create_key_data(context, db_entry))) {
+		    cleanup_key_data(context, db_entry->n_key_data,
+				     db_entry->key_data);
+		    break;
+		}
+		/* We should decrypt/re-encrypt the data to use the same mkvno*/
+		db_entry->key_data[db_entry->n_key_data - 1] = key_data[i];
+		memset(&key_data[i], 0, sizeof(krb5_key_data));
+	    }
+	}
+	cleanup_key_data(context, key_data_count, key_data);
+    }
+    return(retval);
+}
+
+
diff --git a/krb5-1-6/src/lib/kdb/kdb_default.c b/krb5-1-6/src/lib/kdb/kdb_default.c
new file mode 100644
index 000000000..34e8dc047
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/kdb_default.c
@@ -0,0 +1,340 @@
+/*
+ * lib/kdb/kdb_helper.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+#include "kdb.h"
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+/*
+ * Given a particular enctype and optional salttype and kvno, find the
+ * most appropriate krb5_key_data entry of the database entry.
+ *
+ * If stype or kvno is negative, it is ignored.
+ * If kvno is 0 get the key which is maxkvno for the princ and matches
+ * the other attributes.
+ */
+krb5_error_code
+krb5_dbe_def_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, kdatap)
+    krb5_context	kcontext;
+    krb5_db_entry	*dbentp;
+    krb5_int32		*start;
+    krb5_int32		ktype;
+    krb5_int32		stype;
+    krb5_int32		kvno;
+    krb5_key_data	**kdatap;
+{
+    int			i, idx;
+    int			maxkvno;
+    krb5_key_data	*datap;
+    krb5_error_code	ret;
+
+    ret = 0;
+    if (kvno == -1 && stype == -1 && ktype == -1)
+	kvno = 0;
+
+    if (kvno == 0) { 
+	/* Get the max key version */
+	for (i = 0; i < dbentp->n_key_data; i++) {
+	    if (kvno < dbentp->key_data[i].key_data_kvno) { 
+		kvno = dbentp->key_data[i].key_data_kvno;
+	    }
+	}
+    }
+
+    maxkvno = -1;
+    datap = (krb5_key_data *) NULL;
+    for (i = *start; i < dbentp->n_key_data; i++) {
+        krb5_boolean    similar;
+        krb5_int32      db_stype;
+
+	ret = 0;
+	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;
+	}
+
+	/*
+	 * Filter out non-permitted enctypes.
+	 */
+	if (!krb5_is_permitted_enctype(kcontext,
+				       dbentp->key_data[i].key_data_type[0])) {
+	    ret = KRB5_KDB_NO_PERMITTED_KEY;
+	    continue;
+	}
+	
+
+	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) {
+		    datap = &dbentp->key_data[i];
+		    idx = i;
+		    maxkvno = kvno;
+		    break;
+		}
+	    } else {
+		if (dbentp->key_data[i].key_data_kvno > maxkvno) {
+		    maxkvno = dbentp->key_data[i].key_data_kvno;
+		    datap = &dbentp->key_data[i];
+		    idx = i;
+		}
+	    }
+	}
+    }
+    if (maxkvno < 0)
+	return ret ? ret : KRB5_KDB_NO_MATCHING_KEY;
+    *kdatap = datap;
+    *start = idx+1;
+    return 0;
+}
+    
+/*
+ *  kdb default functions. Ideally, some other file should have this functions. For now, TBD.
+ */
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+krb5_error_code
+krb5_def_store_mkey(context, keyfile, mname, key, master_pwd)
+    krb5_context context;
+    char *keyfile;
+    krb5_principal mname;
+    krb5_keyblock *key;
+    char *master_pwd;
+{
+    FILE *kf;
+    krb5_error_code retval = 0;
+    krb5_ui_2 enctype;
+    char defkeyfile[MAXPATHLEN+1];
+    krb5_data *realm = krb5_princ_realm(context, mname);
+#if HAVE_UMASK
+    mode_t oumask;
+#endif
+
+    if (!keyfile) {
+	(void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
+	(void) strncat(defkeyfile, realm->data,
+		       min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
+			   realm->length));
+	defkeyfile[sizeof(defkeyfile) - 1] = '\0';
+	keyfile = defkeyfile;
+    }
+
+#if HAVE_UMASK
+    oumask = umask(077);
+#endif
+#ifdef ANSI_STDIO
+    if (!(kf = fopen(keyfile, "wb")))
+#else
+    if (!(kf = fopen(keyfile, "w")))
+#endif
+    {
+	int e = errno;
+#if HAVE_UMASK
+	(void) umask(oumask);
+#endif
+	krb5_set_error_message (context, e,
+				"%s accessing file '%s'",
+				error_message (e), keyfile);
+	return e;
+    }
+    enctype = key->enctype;
+    if ((fwrite((krb5_pointer) &enctype,
+		2, 1, kf) != 1) ||
+	(fwrite((krb5_pointer) &key->length,
+		sizeof(key->length), 1, kf) != 1) ||
+	(fwrite((krb5_pointer) key->contents,
+		sizeof(key->contents[0]), (unsigned) key->length, 
+		kf) != key->length)) {
+	retval = errno;
+	(void) fclose(kf);
+    }
+    if (fclose(kf) == EOF)
+	retval = errno;
+#if HAVE_UMASK
+    (void) umask(oumask);
+#endif
+    return retval;
+}
+
+
+krb5_error_code
+krb5_db_def_fetch_mkey( krb5_context   context,
+			krb5_principal mname,
+			krb5_keyblock *key,
+			int           *kvno,
+			char          *db_args)
+{
+    krb5_error_code retval;
+    krb5_ui_2 enctype;
+    char defkeyfile[MAXPATHLEN+1];
+    krb5_data *realm = krb5_princ_realm(context, mname);
+    FILE *kf = NULL;
+
+    retval = 0;
+    key->magic = KV5M_KEYBLOCK;
+    (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
+    (void) strncat(defkeyfile, realm->data,
+		   min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
+		       realm->length));
+    defkeyfile[sizeof(defkeyfile) - 1] = '\0';
+	
+#ifdef ANSI_STDIO
+    if (!(kf = fopen((db_args) ? db_args : defkeyfile, "rb")))
+#else
+    if (!(kf = fopen((db_args) ? db_args : defkeyfile, "r")))
+#endif
+	return KRB5_KDB_CANTREAD_STORED;
+
+    if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) {
+	retval = KRB5_KDB_CANTREAD_STORED;
+	goto errout;
+    }
+
+    if (key->enctype == ENCTYPE_UNKNOWN)
+	key->enctype = enctype;
+    else if (enctype != key->enctype) {
+	retval = KRB5_KDB_BADSTORED_MKEY;
+	goto errout;
+    }
+
+    if (fread((krb5_pointer) &key->length,
+	      sizeof(key->length), 1, kf) != 1) {
+	retval = KRB5_KDB_CANTREAD_STORED;
+	goto errout;
+    }
+
+    if (!key->length || ((int) key->length) < 0) {
+	retval = KRB5_KDB_BADSTORED_MKEY;
+	goto errout;
+    }
+	
+    if (!(key->contents = (krb5_octet *)malloc(key->length))) {
+	retval = ENOMEM;
+	goto errout;
+    }
+
+    if (fread((krb5_pointer) key->contents,
+	      sizeof(key->contents[0]), key->length, kf) 
+	!= key->length) {
+	retval = KRB5_KDB_CANTREAD_STORED;
+	memset(key->contents, 0,  key->length);
+	free(key->contents);
+	key->contents = 0;
+    } else
+	retval = 0;
+
+    *kvno = 0;
+
+ errout:
+    (void) fclose(kf);
+    return retval;
+
+}
+
+
+krb5_error_code
+krb5_def_verify_master_key(context, mprinc, mkey)
+    krb5_context context;
+    krb5_principal mprinc;
+    krb5_keyblock *mkey;
+{
+    krb5_error_code retval;
+    krb5_db_entry master_entry;
+    int nprinc;
+    krb5_boolean more;
+    krb5_keyblock tempkey;
+
+    nprinc = 1;
+    if ((retval = krb5_db_get_principal(context, mprinc,
+					&master_entry, &nprinc, &more)))
+	return(retval);
+	
+    if (nprinc != 1) {
+	if (nprinc)
+	    krb5_db_free_principal(context, &master_entry, nprinc);
+	return(KRB5_KDB_NOMASTERKEY);
+    } else if (more) {
+	krb5_db_free_principal(context, &master_entry, nprinc);
+	return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+    }	
+
+    if ((retval = krb5_dbekd_decrypt_key_data(context, mkey, 
+					      &master_entry.key_data[0],
+					      &tempkey, NULL))) {
+	krb5_db_free_principal(context, &master_entry, nprinc);
+	return retval;
+    }
+
+    if (mkey->length != tempkey.length ||
+	memcmp((char *)mkey->contents,
+	       (char *)tempkey.contents,mkey->length)) {
+	retval = KRB5_KDB_BADMASTERKEY;
+    }
+
+    memset((char *)tempkey.contents, 0, tempkey.length);
+    krb5_xfree(tempkey.contents);
+    krb5_db_free_principal(context, &master_entry, nprinc);
+    
+    return retval;
+}
+
+
+krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,
+				   char *pwd,
+				   krb5_keyblock *key )
+{
+    /* printf("default set master key\n"); */
+    return 0;
+}
+
+krb5_error_code kdb_def_get_mkey ( krb5_context kcontext,
+				   krb5_keyblock **key )
+{
+    /* printf("default get master key\n"); */
+    return 0;
+}
+
+krb5_error_code krb5_def_promote_db (krb5_context kcontext,
+				     char *s, char **args)
+{
+    /* printf("default promote_db\n"); */
+    return KRB5_PLUGIN_OP_NOTSUPP;
+}
diff --git a/krb5-1-6/src/lib/kdb/keytab.c b/krb5-1-6/src/lib/kdb/keytab.c
new file mode 100644
index 000000000..227a42e08
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/keytab.c
@@ -0,0 +1,236 @@
+/*
+ * kadmin/v5server/keytab.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+#include <string.h>
+
+#include "k5-int.h"
+#include "kdb_kt.h"
+
+static int
+is_xrealm_tgt(krb5_context, krb5_const_principal);
+
+krb5_error_code krb5_ktkdb_close (krb5_context, krb5_keytab);
+
+krb5_error_code krb5_ktkdb_get_entry (krb5_context, krb5_keytab, krb5_const_principal,
+		   krb5_kvno, krb5_enctype, krb5_keytab_entry *);
+
+static krb5_error_code
+krb5_ktkdb_get_name(krb5_context context, krb5_keytab keytab,
+		    char *name, unsigned int namelen)
+{
+    if (namelen < sizeof("KDB:"))
+	return KRB5_KT_NAME_TOOLONG;
+    strcpy(name, "KDB:");
+    return 0;
+}
+
+krb5_kt_ops krb5_kt_kdb_ops = {
+    0,
+    "KDB", 	/* Prefix -- this string should not appear anywhere else! */
+    krb5_ktkdb_resolve,		/* resolve */
+    krb5_ktkdb_get_name,	/* get_name */
+    krb5_ktkdb_close,		/* close */
+    krb5_ktkdb_get_entry,	/* get */
+    NULL,			/* start_seq_get */
+    NULL,			/* get_next */
+    NULL,			/* end_get */
+    NULL,			/* add (extended) */
+    NULL,			/* remove (extended) */
+    NULL, 		/* (void *) &krb5_ktfile_ser_entry */
+};
+
+typedef struct krb5_ktkdb_data {
+    char * name;
+} krb5_ktkdb_data;
+
+krb5_error_code
+krb5_ktkdb_resolve(context, name, id)
+    krb5_context  	  context;
+    const char		* name;
+    krb5_keytab		* id;
+{
+    if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
+        return(ENOMEM);
+    (*id)->ops = &krb5_kt_kdb_ops;
+    (*id)->magic = KV5M_KEYTAB;
+    return(0);
+}
+
+krb5_error_code
+krb5_ktkdb_close(context, kt)
+     krb5_context context;
+     krb5_keytab kt;
+{
+  /*
+   * This routine is responsible for freeing all memory allocated 
+   * for this keytab.  There are no system resources that need
+   * to be freed nor are there any open files.
+   *
+   * This routine should undo anything done by krb5_ktkdb_resolve().
+   */
+
+  kt->ops = NULL;
+  krb5_xfree(kt);
+
+  return 0;
+}
+
+static krb5_context ktkdb_ctx = NULL;
+
+/*
+ * Set a different context for use with ktkdb_get_entry().  This is
+ * primarily useful for kadmind, where the gssapi library context,
+ * which will be used for the keytab, will necessarily have a
+ * different context than that used by the kadm5 library to access the
+ * database for its own purposes.
+ */
+krb5_error_code
+krb5_ktkdb_set_context(krb5_context ctx)
+{
+    ktkdb_ctx = ctx;
+    return 0;
+}
+
+krb5_error_code
+krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry)
+    krb5_context 	  in_context;
+    krb5_keytab 	  id;
+    krb5_const_principal  principal;
+    krb5_kvno 	 	  kvno;
+    krb5_enctype 	  enctype;
+    krb5_keytab_entry 	* entry;
+{
+    krb5_context	  context;
+    krb5_keyblock       * master_key;
+    krb5_error_code 	  kerror = 0;
+    krb5_key_data 	* key_data;
+    krb5_db_entry 	  db_entry;
+    krb5_boolean 	  more = 0;
+    int 	 	  n = 0;
+    int xrealm_tgt;
+    krb5_boolean similar;
+
+    if (ktkdb_ctx)
+	context = ktkdb_ctx;
+    else
+	context = in_context;
+
+    xrealm_tgt = is_xrealm_tgt(context, principal);
+
+    /* Check whether database is inited. Open is commented */
+    if ((kerror = krb5_db_inited(context)))
+        return(kerror);
+
+    /* get_principal */
+    kerror = krb5_db_get_principal(context, principal, &
+				       db_entry, &n, &more);
+    if (kerror) {
+      /*        krb5_db_close_database(context); */
+        return(kerror);
+    }
+    if (n != 1) {
+      /* krb5_db_close_database(context); */
+	return KRB5_KT_NOTFOUND;
+    }
+
+    if (db_entry.attributes & KRB5_KDB_DISALLOW_SVR
+	|| db_entry.attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
+	kerror = KRB5_KT_NOTFOUND;
+	goto error;
+    }
+
+    /* match key */
+    kerror = krb5_db_get_mkey(context, &master_key);
+    if (kerror)
+	goto error;
+
+    /* For cross realm tgts, we match whatever enctype is provided;
+     * for other principals, we only match the first enctype that is
+     * found.  Since the TGS and AS code do the same thing, then we
+     * will only successfully decrypt  tickets we have issued.*/
+    kerror = krb5_dbe_find_enctype(context, &db_entry,
+				   xrealm_tgt?enctype:-1,
+				   -1, kvno, &key_data);
+    if (kerror)
+	goto error;
+
+
+    kerror = krb5_dbekd_decrypt_key_data(context, master_key,
+					 key_data, &entry->key, NULL);
+    if (kerror)
+	goto error;
+
+    if (enctype > 0) {	
+	kerror = krb5_c_enctype_compare(context, enctype,
+					entry->key.enctype, &similar);
+	if (kerror)
+	    goto error;
+
+	if (!similar) {
+	    kerror = KRB5_KDB_NO_PERMITTED_KEY;
+	    goto error;
+	}
+    }
+    /*
+     * Coerce the enctype of the output keyblock in case we got an
+     * inexact match on the enctype.
+     */
+    entry->key.enctype = enctype;
+
+    kerror = krb5_copy_principal(context, principal, &entry->principal);
+    if (kerror)
+	goto error;
+
+    /* Close database */
+  error:
+    krb5_db_free_principal(context, &db_entry, 1);
+    /*    krb5_db_close_database(context); */
+    return(kerror);
+}
+
+/*
+ * is_xrealm_tgt: Returns true if the principal is a cross-realm  TGT
+ * principal-- a principal with first component  krbtgt and second
+ * component not equal to realm.
+ */
+static int
+is_xrealm_tgt(krb5_context context, krb5_const_principal princ)
+{
+    krb5_data *dat;
+    if (krb5_princ_size(context, princ) != 2)
+	return 0;
+    dat = krb5_princ_component(context, princ, 0);
+    if (strncmp("krbtgt", dat->data, dat->length) != 0)
+	return 0;
+    dat = krb5_princ_component(context, princ, 1);
+    if (dat->length != princ->realm.length)
+	return 1;
+    if (strncmp(dat->data, princ->realm.data, dat->length) == 0)
+	return 0;
+    return 1;
+
+}
+
diff --git a/krb5-1-6/src/lib/kdb/libkdb5.exports b/krb5-1-6/src/lib/kdb/libkdb5.exports
new file mode 100644
index 000000000..dd9f95288
--- /dev/null
+++ b/krb5-1-6/src/lib/kdb/libkdb5.exports
@@ -0,0 +1,51 @@
+krb5_db_open
+krb5_db_inited
+krb5_db_alloc
+krb5_db_free
+krb5_db_create
+krb5_db_delete_principal
+krb5_db_destroy
+krb5_db_fetch_mkey
+krb5_db_fini
+krb5_db_free_principal
+krb5_db_get_age
+krb5_db_get_mkey
+krb5_db_get_principal
+krb5_db_iterate
+krb5_db_lock
+krb5_db_put_principal
+krb5_db_set_mkey
+krb5_db_setup_mkey_name
+krb5_db_unlock
+krb5_db_store_master_key
+krb5_db_verify_master_key
+krb5_dbe_apw
+krb5_dbe_ark
+krb5_dbe_cpw
+krb5_dbe_create_key_data
+krb5_dbe_crk
+krb5_dbe_find_enctype
+krb5_dbe_lookup_last_pwd_change
+krb5_dbe_lookup_mod_princ_data
+krb5_dbe_lookup_tl_data
+krb5_dbe_search_enctype
+krb5_dbe_update_last_pwd_change
+krb5_dbe_update_mod_princ_data
+krb5_dbe_update_tl_data
+krb5_dbekd_decrypt_key_data
+krb5_dbekd_encrypt_key_data
+krb5_kt_kdb_ops
+krb5_ktkdb_close
+krb5_ktkdb_get_entry
+krb5_ktkdb_resolve
+krb5_ktkdb_set_context
+krb5_mkey_pwd_prompt1
+krb5_mkey_pwd_prompt2
+krb5_db_create_policy
+krb5_db_get_policy
+krb5_db_put_policy
+krb5_db_iter_policy
+krb5_db_delete_policy
+krb5_db_free_policy
+krb5_def_store_mkey
+krb5_db_promote
diff --git a/krb5-1-6/src/lib/krb4/CCache-glue.c b/krb5-1-6/src/lib/krb4/CCache-glue.c
new file mode 100644
index 000000000..2ccbb153a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/CCache-glue.c
@@ -0,0 +1,741 @@
+/*
+ * CCache-glue.c
+ *
+ * This file contains implementations of krb4 credentials cache operations in terms
+ * of the CCache API (<http://www.umich.edu/~sgr/v4Cache/>).
+ *
+ * $Header$
+ */
+
+
+#include "krb.h"
+#include "krb4int.h"
+
+#if !defined (USE_CCAPI) || !USE_CCAPI
+#error "Cannot use CCache glue without the CCAPI!"
+#endif
+
+#ifdef USE_LOGIN_LIBRARY
+#include <KerberosLoginPrivate.h>
+#endif /* USE_LOGIN_LIBRARY */
+#include <CredentialsCache.h>
+
+#include <string.h>
+#include <stdlib.h>
+ 
+/*
+ * The following functions are part of the KfM ABI.  
+ * They are deprecated, so they only appear here, not in krb.h.
+ *
+ * Do not change the ABI of these functions!
+ */
+int KRB5_CALLCONV krb_get_num_cred(void);
+int KRB5_CALLCONV krb_get_nth_cred(char *, char *, char *, int);
+int KRB5_CALLCONV krb_delete_cred(char *, char *,char *);
+int KRB5_CALLCONV dest_all_tkts(void);
+ 
+/* Internal functions */
+static void UpdateDefaultCache (void);
+
+/* 
+ * The way Kerberos v4 normally works is that at any given point in time there is a
+ * file where all the tickets go, determined by an environment variable. If a user kinits
+ * to a new principal, the existing tickets are replaced with new ones. At any point in time, there is a 
+ * "current" or "default" principal, which is determined by the principal associated with
+ * the current ticket file.
+ * 
+ * In the CCache API implementation, this corresponds to always having a "default"
+ * or "current" named cache. The default principal then corresponds to that cache.
+ *
+ * Unfortunately, Kerberos v4 also has this notion that the default cache exists (in the sense
+ * that its name is known) even before the actual file has been created.
+ *
+ * In addition to this, we cannot make the default cache system-wide global, because then
+ * we get all sorts of interesting scenarios in which context switches between processes
+ * can cause credentials to be stored in wrong caches.
+ *
+ * To solve all the problems, we have to emulate the concept of an environment variable,
+ * by having a system-wide concept of what a default credentials cache is; then, we copy 
+ * the system-wide value into the per-process value when the application starts up.
+ *
+ * However, in order to allow applications to be able to sanely handle the user model we
+ * want to support, in which the user has some way of selecting the system-wide default
+ * user _without_ quitting and relaunching all applications (this is also necessary for
+ * KClient support), calls had to be added to the Kerberos v4 library to reset the 
+ * per-process cached value of default cache.
+ */
+ 
+/*
+ * Name of the default cache
+ */
+char* gDefaultCacheName = NULL;
+
+/*
+ * Initialize credentials cache
+ *
+ * Creating the cache will blow away an existing one. The assumption is that
+ * whoever called us made sure that the one that we blow away if it exists
+ * is the right one to blow away.
+ */
+
+int KRB5_CALLCONV
+krb_in_tkt (
+	char*		pname,
+	char*		pinst,
+	char*		realm)
+{
+	char			principal [MAX_K_NAME_SZ + 1];
+	cc_int32		err = ccNoError;
+	cc_context_t	cc_context = NULL;
+    cc_int32		cc_version;
+    cc_ccache_t		ccache = NULL;
+	
+	err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+    
+	if (err == ccNoError) {
+        sprintf (principal, "%s%s%s@%s", pname, (pinst [0] == '\0') ? "" : ".", pinst, realm);
+	}
+    
+	if (err == ccNoError) {
+        err = cc_context_create_ccache (cc_context, TKT_FILE, cc_credentials_v4, principal, &ccache);
+	}
+
+    if (ccache != NULL)
+    	cc_ccache_release (ccache);
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+    if (err != ccNoError)
+		return KFAILURE;
+    else
+        return KSUCCESS;
+}
+
+int KRB5_CALLCONV
+krb_save_credentials(
+    char	*service,
+    char	*instance,
+    char	*realm,
+    C_Block	session,
+    int		lifetime,
+    int		kvno,
+    KTEXT	ticket,
+    long	issue_date)
+{
+    return krb4int_save_credentials_addr(service, instance, realm,
+					 session, lifetime, kvno,
+					 ticket, issue_date, 0);
+}
+
+/*
+ * Store a ticket into the default credentials cache
+ * cache must exist (if it didn't exist, it would have been created by in_tkt)
+ */
+int
+krb4int_save_credentials_addr(
+	char*			service,
+	char*			instance,
+	char*			realm,
+	C_Block			session,
+	int				lifetime,
+	int				kvno,
+	KTEXT			ticket,
+	KRB4_32			issue_date,
+	KRB_UINT32		local_address)
+{
+	cc_int32				cc_err = ccNoError;
+	int						kerr = KSUCCESS;
+	cc_credentials_v4_t		v4creds;
+	cc_credentials_union	creds;
+	cc_ccache_t				ccache = NULL;
+	cc_string_t				principal;
+	cc_context_t			cc_context = NULL;
+    cc_int32				cc_version;
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+	
+	if (cc_err == ccNoError) {
+        /* First try existing cache */
+        cc_err = cc_context_open_ccache (cc_context, TKT_FILE, &ccache);
+	}
+	
+    if (cc_err == ccNoError) {
+        /* Now we have a cache. Fill out the credentials and put them in the cache. */
+        /* To fill out the credentials, we need the principal */
+        cc_err = cc_ccache_get_principal (ccache, cc_credentials_v4, &principal);
+	}
+    
+    if (cc_err == ccNoError) {
+        kerr = kname_parse (v4creds.principal, v4creds.principal_instance, v4creds.realm, (char*) principal -> data);
+        cc_string_release (principal);
+	}
+    
+	if ((cc_err == ccNoError) && (kerr == KSUCCESS)) {
+		strncpy (v4creds.service, service, SNAME_SZ);
+        strncpy (v4creds.service_instance, instance, INST_SZ);
+        strncpy (v4creds.realm, realm, REALM_SZ);
+        memmove (v4creds.session_key, session, sizeof (C_Block));
+        v4creds.kvno = kvno;
+        v4creds.string_to_key_type = cc_v4_stk_unknown;
+        v4creds.issue_date = issue_date;
+        v4creds.address = local_address;
+        v4creds.lifetime = lifetime;
+        v4creds.ticket_size = ticket -> length;
+        memmove (v4creds.ticket, ticket -> dat, ticket -> length);
+        
+        creds.version = cc_credentials_v4;
+        creds.credentials.credentials_v4 = &v4creds;
+        
+        cc_err = cc_ccache_store_credentials (ccache, &creds);
+    }
+	
+    if (ccache != NULL)
+        cc_ccache_release (ccache);
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+    if (kerr != KSUCCESS)
+        return kerr;
+	if (cc_err != ccNoError)
+		return KFAILURE;
+    else
+        return KSUCCESS;
+}
+
+/*
+ * Credentials file -> realm mapping
+ *
+ * Determine the realm by opening the named cache and parsing realm from the principal
+ */
+int KRB5_CALLCONV
+krb_get_tf_realm (
+	const char*		ticket_file,
+	char*			realm)
+{
+	cc_string_t		principal;
+	char			pname [ANAME_SZ];
+	char			pinst [INST_SZ];
+	char			prealm [REALM_SZ];
+    int				kerr = KSUCCESS;
+	cc_int32		cc_err = ccNoError;
+	cc_context_t	cc_context = NULL;
+    cc_int32		cc_version = 0;
+    cc_ccache_t		ccache = NULL;
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+	
+    if (cc_err == ccNoError) {
+        cc_err = cc_context_open_ccache (cc_context, ticket_file, &ccache);
+	}
+
+    if (cc_err == ccNoError) {
+        cc_err = cc_ccache_get_principal (ccache, cc_credentials_v4, &principal);
+	}
+
+    if (cc_err == ccNoError) {
+        /* found cache. get princiapl and parse it */
+        kerr = kname_parse (pname, pinst, prealm, (char*) principal -> data);
+        cc_string_release (principal);
+    }
+    
+    if ((cc_err == ccNoError) && (kerr == KSUCCESS)) {
+        strcpy (realm, prealm);
+    }
+    
+    if (ccache != NULL) 
+        cc_ccache_release (ccache);
+    if (cc_context != NULL) 
+        cc_context_release (cc_context);
+    
+    if (kerr != KSUCCESS)
+        return kerr;
+	if (cc_err != ccNoError)
+		return GC_NOTKT;
+    else
+        return KSUCCESS;
+}
+
+/*
+ * Credentials file -> name, instance, realm mapping
+ */
+int KRB5_CALLCONV
+krb_get_tf_fullname (
+	const char*		ticket_file,
+	char*			name,
+	char*			instance,
+	char*			realm)
+{
+	cc_string_t		principal;
+	int				kerr = KSUCCESS;
+	cc_int32		cc_err = ccNoError;
+	cc_context_t	cc_context = NULL;
+    cc_int32		cc_version;
+    cc_ccache_t		ccache = NULL;
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+	
+    if (cc_err == ccNoError) {
+        cc_err = cc_context_open_ccache (cc_context, ticket_file, &ccache);
+	}
+
+    if (cc_err == ccNoError) {
+        /* found cache. get principal and parse it */
+        cc_err = cc_ccache_get_principal (ccache, cc_credentials_v4, &principal);
+	}
+
+    if (cc_err == ccNoError) {
+        kerr = kname_parse (name, instance, realm, (char*) principal -> data);
+        cc_string_release (principal);
+	}
+    
+    if (ccache != NULL)
+        cc_ccache_release (ccache);    
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+    if (kerr != KSUCCESS)
+        return kerr;
+	if (cc_err != ccNoError)
+		return GC_NOTKT;
+    else
+        return KSUCCESS;
+}
+
+
+/*
+ * Retrieval from credentials cache
+ */
+int KRB5_CALLCONV
+krb_get_cred (
+	char*			service,
+	char*			instance,
+	char*			realm,
+	CREDENTIALS*	creds)
+{
+	int							kerr = KSUCCESS;
+    cc_int32					cc_err = ccNoError;
+	cc_credentials_t			theCreds = NULL;
+	cc_credentials_iterator_t	iterator = NULL;
+	cc_context_t				cc_context = NULL;
+    cc_int32					cc_version;
+    cc_ccache_t					ccache = NULL;
+		
+#ifdef USE_LOGIN_LIBRARY
+	// If we are requesting a tgt, prompt for it
+	if (strncmp (service, KRB_TICKET_GRANTING_TICKET, ANAME_SZ) == 0) {
+		OSStatus	err;
+		char		*cacheName;
+		KLPrincipal	outPrincipal;
+		
+		err = __KLInternalAcquireInitialTicketsForCache (TKT_FILE, kerberosVersion_V4, NULL, 
+                                                                 &outPrincipal, &cacheName);
+
+		if (err == klNoErr) {
+                	krb_set_tkt_string (cacheName);		// Tickets for the krb4 principal went here
+			KLDisposeString (cacheName);	
+			KLDisposePrincipal (outPrincipal);
+		} else {
+			return GC_NOTKT;
+		}
+	}
+#endif /* USE_LOGIN_LIBRARY */     
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+
+	if (cc_err == ccNoError) {
+        cc_err = cc_context_open_ccache (cc_context, TKT_FILE, &ccache);
+	}
+
+	if (cc_err == ccNoError) {
+        cc_err = cc_ccache_new_credentials_iterator (ccache, &iterator);
+	}
+
+	if (cc_err == ccNoError) {
+        for (;;) {
+            /* get next creds */
+            cc_err = cc_credentials_iterator_next (iterator, &theCreds);
+            if (cc_err == ccIteratorEnd) {
+                kerr = GC_NOTKT;
+                break;
+            }
+            if (cc_err != ccNoError) {
+                kerr = KFAILURE;
+                break;
+            }
+            
+            /* version, service, instance, realm check */
+            if ((theCreds -> data -> version == cc_credentials_v4) &&
+                (strcmp (theCreds -> data -> credentials.credentials_v4 -> service, service) == 0) &&
+                (strcmp (theCreds -> data -> credentials.credentials_v4 -> service_instance, instance) == 0) &&
+                (strcmp (theCreds -> data -> credentials.credentials_v4 -> realm, realm) == 0)) {
+                
+                /* Match! */
+                strcpy (creds -> service, service);
+                strcpy (creds -> instance, instance);
+                strcpy (creds -> realm, realm);
+                memmove (creds -> session, theCreds -> data -> credentials.credentials_v4 -> session_key, sizeof (C_Block));
+                creds -> lifetime = theCreds -> data -> credentials.credentials_v4 -> lifetime;
+                creds -> kvno = theCreds -> data -> credentials.credentials_v4 -> kvno;
+                creds -> ticket_st.length = theCreds -> data -> credentials.credentials_v4 -> ticket_size;
+                memmove (creds -> ticket_st.dat, theCreds -> data -> credentials.credentials_v4 -> ticket, creds -> ticket_st.length);
+                creds -> issue_date = theCreds -> data -> credentials.credentials_v4 -> issue_date;
+                strcpy (creds -> pname, theCreds -> data -> credentials.credentials_v4 -> principal);
+                strcpy (creds -> pinst, theCreds -> data -> credentials.credentials_v4 -> principal_instance);
+                creds -> stk_type = theCreds -> data -> credentials.credentials_v4 -> string_to_key_type;
+                
+                cc_credentials_release (theCreds);
+                kerr = KSUCCESS;
+                break;
+            } else  {
+                cc_credentials_release (theCreds);
+            }
+        }
+	}
+    
+    if (iterator != NULL)
+        cc_credentials_iterator_release (iterator);
+    if (ccache != NULL)
+        cc_ccache_release (ccache);    
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+    if (kerr != KSUCCESS)
+        return kerr;
+	if (cc_err != ccNoError)
+		return GC_NOTKT;
+    else
+        return KSUCCESS;
+}
+
+
+/*
+ * Getting name of default credentials cache
+ */
+const char* KRB5_CALLCONV
+tkt_string (void)
+{
+	if (gDefaultCacheName == NULL) {
+        UpdateDefaultCache ();
+    }
+	return gDefaultCacheName;
+}
+
+/*
+ * Synchronize default cache for this process with system default cache
+ */
+ 
+static void
+UpdateDefaultCache (void)
+{
+	cc_string_t 	name;
+    cc_int32		cc_err = ccNoError;
+	cc_context_t	cc_context = NULL;
+    cc_int32		cc_version;
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+    
+    if (cc_err == ccNoError) {
+        cc_err = cc_context_get_default_ccache_name (cc_context, &name);
+	}
+    
+	if (cc_err == ccNoError) {
+		krb_set_tkt_string ((char*) name -> data);
+		cc_string_release (name);
+	}
+    
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+}
+
+/*
+ * Setting name of default credentials cache
+ */
+void
+krb_set_tkt_string (
+	const char*			val)
+{
+	/* If we get called with the return value of tkt_string, we
+	   shouldn't dispose of the input string */
+	if (val != gDefaultCacheName) {
+		if (gDefaultCacheName != NULL)
+			free (gDefaultCacheName);
+			
+		gDefaultCacheName = malloc (strlen (val) + 1);
+		if (gDefaultCacheName != NULL)
+			strcpy (gDefaultCacheName, val);
+	}
+}
+
+/*
+ * Destroy credentials file
+ *
+ * Implementation in dest_tkt.c
+ */
+int KRB5_CALLCONV
+dest_tkt (void)
+{
+	cc_int32		cc_err = ccNoError;
+	cc_context_t	cc_context = NULL;
+    cc_int32		cc_version;
+    cc_ccache_t		ccache = NULL;
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+
+    if (cc_err == ccNoError) {
+        cc_err = cc_context_open_ccache (cc_context, TKT_FILE, &ccache);
+	}
+    
+	if (cc_err == ccNoError) {
+        cc_ccache_destroy (ccache);
+	}
+    
+    if (ccache != NULL)
+        cc_ccache_release (ccache);    
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+	if (cc_err != ccNoError)
+		return RET_TKFIL;
+    else
+        return KSUCCESS;
+}
+
+/*
+ * The following functions are not part of the standard Kerberos v4 API. 
+ * They were created for Mac implementation, and used by admin tools 
+ * such as CNS-Config.
+ */
+ 
+/*
+ * Number of credentials in credentials cache
+ */
+int KRB5_CALLCONV
+krb_get_num_cred (void)
+{
+	cc_credentials_t			theCreds = NULL;
+	int							count = 0;
+	cc_credentials_iterator_t	iterator = NULL;
+    cc_int32					cc_err = ccNoError;
+	cc_context_t				cc_context = NULL;
+    cc_int32					cc_version;
+    cc_ccache_t					ccache = NULL;
+    
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+
+    if (cc_err == ccNoError) {
+        cc_err = cc_context_open_ccache (cc_context, TKT_FILE, &ccache);
+	}
+		
+    if (cc_err == ccNoError) {
+        cc_err = cc_ccache_new_credentials_iterator (ccache, &iterator);
+	}
+	
+    if (cc_err == ccNoError) {
+        for (;;) {
+            /* get next creds */
+            cc_err = cc_credentials_iterator_next (iterator, &theCreds);
+            if (cc_err != ccNoError)
+                break;
+    
+            if (theCreds -> data -> version == cc_credentials_v4) 
+                count++;
+                
+            cc_credentials_release (theCreds);
+        }
+    }
+    
+    if (iterator != NULL)
+        cc_credentials_iterator_release (iterator);
+    if (ccache != NULL)
+        cc_ccache_release (ccache);    
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+	if (cc_err != ccNoError)
+		return 0;
+    else
+        return count;
+}
+
+/*
+ * Retrieval from credentials file
+ * This function is _not_!! well-defined under CCache API, because
+ * there is no guarantee about order of credentials remaining the same.
+ */
+int KRB5_CALLCONV
+krb_get_nth_cred (
+	char*			sname,
+	char*			sinstance,
+	char*			srealm,
+	int				n)
+{
+	cc_credentials_t 			theCreds = NULL;
+	int							count = 0;
+	cc_credentials_iterator_t	iterator = NULL;
+    cc_int32					cc_err = ccNoError;
+	cc_context_t				cc_context = NULL;
+    cc_int32					cc_version;
+    cc_ccache_t					ccache = NULL;
+	
+	if (n < 1)
+		return KFAILURE;
+
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+		
+    if (cc_err == ccNoError) {
+        cc_err = cc_context_open_ccache (cc_context, TKT_FILE, &ccache);
+	}
+		
+    if (cc_err == ccNoError) {   
+        cc_err = cc_ccache_new_credentials_iterator (ccache, &iterator);
+	}
+	
+    if (cc_err == ccNoError) {
+        for (count = 0; count < n;) {
+            /* get next creds */
+            cc_err = cc_credentials_iterator_next (iterator, &theCreds);
+            if (cc_err != ccNoError)
+                break;
+    
+            if (theCreds -> data -> version == cc_credentials_v4) 
+                count++;
+            
+            if (count < n - 1)	
+                cc_credentials_release (theCreds);
+        }
+    }
+    
+    if (cc_err == ccNoError) {
+        strcpy (sname, theCreds -> data -> credentials.credentials_v4 -> service);
+        strcpy (sinstance, theCreds -> data -> credentials.credentials_v4 -> service_instance);
+        strcpy (srealm, theCreds -> data -> credentials.credentials_v4 -> realm);
+	}
+    
+    if (theCreds != NULL)
+        cc_credentials_release (theCreds);
+    if (iterator != NULL)
+        cc_credentials_iterator_release (iterator);
+    if (ccache != NULL)
+        cc_ccache_release (ccache);    
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+	if (cc_err != ccNoError)
+		return KFAILURE;
+    else
+        return KSUCCESS;
+}
+
+/*
+ * Deletion from credentials file
+ */
+int KRB5_CALLCONV
+krb_delete_cred (
+	char*	sname,
+	char*	sinstance,
+	char*	srealm)
+{
+	cc_credentials_t			theCreds = NULL;
+	cc_credentials_iterator_t	iterator = NULL;
+    cc_int32					cc_err = ccNoError;
+	cc_context_t				cc_context = NULL;
+    cc_int32					cc_version;
+    cc_ccache_t					ccache = NULL;
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+
+	if (cc_err == ccNoError) {
+        cc_err = cc_context_open_ccache (cc_context, TKT_FILE, &ccache);
+	}
+		
+	if (cc_err == ccNoError) {
+        cc_err = cc_ccache_new_credentials_iterator (ccache, &iterator);
+	}
+	
+	if (cc_err == ccNoError) {
+        for (;;) {
+            /* get next creds */
+            cc_err = cc_credentials_iterator_next (iterator, &theCreds);
+            if (cc_err != ccNoError) {
+                break;
+            }
+    
+            if ((theCreds -> data -> version == cc_credentials_v4) &&
+                (strcmp (theCreds -> data -> credentials.credentials_v4 -> service, sname) == 0) &&
+                (strcmp (theCreds -> data -> credentials.credentials_v4 -> service_instance, sinstance) == 0) &&
+                (strcmp (theCreds -> data -> credentials.credentials_v4 -> realm, srealm) == 0)) {
+                
+                cc_ccache_remove_credentials (ccache, theCreds);
+                cc_credentials_release (theCreds);
+                break;
+            }
+            
+            cc_credentials_release (theCreds);
+        }
+    }
+    
+    if (iterator != NULL)
+        cc_credentials_iterator_release (iterator);
+    if (ccache != NULL)
+        cc_ccache_release (ccache);    
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+	if (cc_err != ccNoError)
+		return KFAILURE;
+    else
+        return KSUCCESS;    
+}
+
+/*
+ * Destroy all credential caches
+ *
+ * Implementation in memcache.c
+ */
+int KRB5_CALLCONV
+dest_all_tkts (void)
+{
+	int						count = 0;
+	cc_ccache_iterator_t	iterator = NULL;
+    cc_int32				cc_err = ccNoError;
+	cc_context_t			cc_context = NULL;
+    cc_int32				cc_version;
+    cc_ccache_t				ccache = NULL;
+	
+	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
+    
+    if (cc_err == ccNoError) {
+        cc_err = cc_context_new_ccache_iterator (cc_context, &iterator);
+	}
+    
+    if (cc_err == ccNoError) {
+        for (;;) {
+            /* get next ccache */
+            cc_err = cc_ccache_iterator_next (iterator, &ccache);
+            
+            if (cc_err != ccNoError)
+                break;
+            
+            cc_ccache_destroy (ccache);
+            count++;
+        }	
+    }
+    
+    if (iterator != NULL)
+        cc_credentials_iterator_release (iterator);
+    if (cc_context != NULL)
+        cc_context_release (cc_context);
+    
+    if ((cc_err == ccIteratorEnd) && (count == 0)) {
+        /* first time, nothing to destroy */
+        return KFAILURE;
+    } else {
+        if (cc_err == ccIteratorEnd) {
+             /* done */
+            return KSUCCESS;
+        } else {
+            /* error */
+            return KFAILURE;
+        }
+    }
+}
diff --git a/krb5-1-6/src/lib/krb4/FSp-glue.c b/krb5-1-6/src/lib/krb4/FSp-glue.c
new file mode 100644
index 000000000..7bf0e7b54
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/FSp-glue.c
@@ -0,0 +1,112 @@
+/*
+ * lib/krb4/FSp-glue.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2002 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * MacOS-specific glue for using FSSpecs to deal with srvtabs.
+ */
+
+#include "krb.h"
+#include "krb4int.h"
+#include <stdio.h>
+#include <string.h>
+
+#include <Kerberos/FSpUtils.h>
+/* 
+ * These functions are compiled in for ABI compatibility with older versions of KfM.
+ * They are deprecated so they do not appear in the KfM headers anymore.
+ * 
+ * Do not change their ABIs!
+ */
+int KRB5_CALLCONV FSp_krb_get_svc_in_tkt (char *, char *, char *, char *, char *, int, const FSSpec *);
+int KRB5_CALLCONV FSp_put_svc_key (const FSSpec *, char *, char *, char *, int, char *);
+int KRB5_CALLCONV FSp_read_service_key (char *, char *, char *, int, const FSSpec*, char *);
+
+static int FSp_srvtab_to_key (char *, char *, char *, char *, C_Block);
+
+int KRB5_CALLCONV
+FSp_read_service_key(
+    char *service,              /* Service Name */
+    char *instance,             /* Instance name or "*" */
+    char *realm,                /* Realm */
+    int kvno,                   /* Key version number */
+    const FSSpec *filespec,     /* Filespec */
+    char *key)                  /* Pointer to key to be filled in */
+{
+    int retval = KFAILURE;
+    char file [MAXPATHLEN];
+    if (filespec != NULL) {
+        if (FSSpecToPOSIXPath (filespec, file, sizeof(file)) != noErr) {
+            return retval;
+        }
+    }
+    retval = read_service_key(service, instance, realm, kvno, file, key);
+    if (file != NULL) {
+        free (file);
+    }
+    return retval;
+}
+
+int KRB5_CALLCONV
+FSp_put_svc_key(
+    const FSSpec *sfilespec,
+    char *name,
+    char *inst,
+    char *realm,
+    int newvno,
+    char *key)
+{
+    int retval = KFAILURE;
+    char sfile[MAXPATHLEN];
+
+    if (sfilespec != NULL) {
+        if (FSSpecToPOSIXPath (sfilespec, sfile, sizeof(sfile)) != noErr) {
+            return retval;
+        }
+    }
+    retval = put_svc_key(sfile, name, inst, realm, newvno, key);
+    if (sfile != NULL) {
+        free (sfile);
+    }
+    return retval;
+}
+
+int KRB5_CALLCONV
+FSp_krb_get_svc_in_tkt(
+    char *user, char *instance, char *realm, 
+    char *service, char *sinstance, int life,
+    const FSSpec *srvtab)
+{
+    /* Cast the FSSpec into the password field.  It will be pulled out again */
+    /* by FSp_srvtab_to_key and used to read the real password */
+    return krb_get_in_tkt(user, instance, realm, service, sinstance,
+                          life, FSp_srvtab_to_key, NULL, (char *)srvtab);
+}
+
+static int FSp_srvtab_to_key(char *user, char *instance, char *realm, 
+			     char *srvtab, C_Block key)
+{
+    /* FSp_read_service_key correctly handles a NULL FSSpecPtr */
+    return FSp_read_service_key(user, instance, realm, 0,
+				(FSSpec *)srvtab, (char *)key);
+}
diff --git a/krb5-1-6/src/lib/krb4/Makefile.in b/krb5-1-6/src/lib/krb4/Makefile.in
new file mode 100644
index 000000000..9d5695f51
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/Makefile.in
@@ -0,0 +1,662 @@
+thisconfigdir=../..
+myfulldir=lib/krb4
+mydir=lib/krb4
+BUILDTOP=$(REL)..$(S)..
+LOCALINCLUDES = -I$(BUILDTOP)/include/kerberosIV -I$(srcdir)/../../include/kerberosIV -I.
+DEFINES= -DKRB4_USE_KEYTAB
+DEFS=
+
+##DOS##BUILDTOP = ..\..
+##DOS##LIBNAME=$(OUTPRE)krb4.lib
+##DOS##OBJFILE=$(OUTPRE)krb4.lst
+
+LIBBASE=krb4
+LIBMAJOR=2
+LIBMINOR=0
+RELDIR=krb4
+
+# Depends on libk5crypto, libkrb5, KRB4_CRYPTO_LIB and _et_list...
+# Depends on libkrb5, expect to find
+#	krb5_init_context, krb5_free_context, profile_get_values
+#
+KRB4_CRYPTO_LIBS=-ldes425
+
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libdes425$(SHLIBEXT) \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS=-lkrb5 -lcom_err -ldes425 -lk5crypto
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+EHDRDIR=$(BUILDTOP)$(S)include$(S)kerberosIV
+KRB_ERR=@KRB_ERR@
+##DOS##KRB_ERR=$(OUTPRE)krb_err.$(OBJEXT)
+
+# Name of generated krb_err.c, needed for err_txt.* dependency on Darwin.
+KRB_ERR_C=@KRB_ERR_C@
+##DOS##KRB_ERR_C=
+
+OBJS	= \
+	$(OUTPRE)change_password.$(OBJEXT) \
+	$(OUTPRE)cr_auth_repl.$(OBJEXT) \
+	$(OUTPRE)cr_ciph.$(OBJEXT) \
+	$(OUTPRE)cr_tkt.$(OBJEXT) \
+	$(OUTPRE)debug.$(OBJEXT) \
+	$(OUTPRE)decomp_tkt.$(OBJEXT) \
+	$(OUTPRE)err_txt.$(OBJEXT) \
+	$(OUTPRE)g_ad_tkt.$(OBJEXT) \
+	$(OUTPRE)g_in_tkt.$(OBJEXT) \
+	$(OUTPRE)g_phost.$(OBJEXT) \
+	$(OUTPRE)g_pw_in_tkt.$(OBJEXT) \
+	$(OUTPRE)g_pw_tkt.$(OBJEXT) \
+	$(OUTPRE)g_tkt_svc.$(OBJEXT) \
+	$(OUTPRE)gethostname.$(OBJEXT) \
+	$(OUTPRE)getst.$(OBJEXT) \
+	$(OUTPRE)kadm_err.$(OBJEXT) \
+	$(OUTPRE)kadm_net.$(OBJEXT) \
+	$(OUTPRE)kadm_stream.$(OBJEXT) \
+	$(OUTPRE)kname_parse.$(OBJEXT) \
+	$(OUTPRE)lifetime.$(OBJEXT) \
+	$(OUTPRE)mk_auth.$(OBJEXT) \
+	$(OUTPRE)mk_err.$(OBJEXT) \
+	$(OUTPRE)mk_priv.$(OBJEXT) \
+	$(OUTPRE)mk_req.$(OBJEXT) \
+	$(OUTPRE)mk_safe.$(OBJEXT) \
+	$(OUTPRE)month_sname.$(OBJEXT) \
+	$(OUTPRE)password_to_key.$(OBJEXT) \
+	$(OUTPRE)prot_client.$(OBJEXT) \
+	$(OUTPRE)prot_common.$(OBJEXT) \
+	$(OUTPRE)prot_kdc.$(OBJEXT) \
+	$(OUTPRE)pkt_cipher.$(OBJEXT) \
+	$(OUTPRE)pkt_clen.$(OBJEXT) \
+	$(OUTPRE)rd_err.$(OBJEXT) \
+	$(OUTPRE)rd_priv.$(OBJEXT) \
+	$(OUTPRE)rd_safe.$(OBJEXT) \
+	$(OUTPRE)send_to_kdc.$(OBJEXT) \
+	$(OUTPRE)stime.$(OBJEXT) \
+	$(OUTPRE)strnlen.$(OBJEXT) \
+	$(OUTPRE)rd_preauth.$(OBJEXT) \
+	$(OUTPRE)mk_preauth.$(OBJEXT) \
+	$(OSOBJS) $(CACHEOBJS) $(SETENVOBJS) $(STRCASEOBJS) $(SHMOBJS) \
+	$(LIB_KRB_HOSTOBJS) $(SERVER_KRB_OBJS) $(NETIO_OBJS) $(REALMDBOBJS) $(KRB_ERR)
+
+SRCS = \
+	change_password.c \
+	cr_auth_repl.c \
+	cr_ciph.c \
+	cr_tkt.c \
+	debug.c \
+	decomp_tkt.c \
+	g_ad_tkt.c \
+	g_pw_in_tkt.c \
+	g_phost.c \
+	g_pw_tkt.c \
+	g_tkt_svc.c \
+	getst.c \
+	gethostname.c \
+	kadm_err.c \
+	kadm_net.c \
+	kadm_stream.c \
+	kname_parse.c \
+	err_txt.c \
+	lifetime.c \
+	g_in_tkt.c \
+	mk_auth.c \
+	mk_err.c \
+	mk_priv.c \
+	mk_req.c \
+	mk_safe.c \
+	month_sname.c \
+	password_to_key.c \
+	pkt_cipher.c \
+	pkt_clen.c \
+	prot_client.c \
+	prot_common.c \
+	prot_kdc.c \
+	rd_err.c \
+	rd_priv.c \
+	rd_safe.c \
+	send_to_kdc.c \
+	stime.c \
+	strnlen.c \
+	rd_preauth.c \
+	mk_preauth.c \
+	unix_time.c \
+	$(OSSRCS) $(CACHESRCS) $(SETENVSRCS) $(STRCASESRCS) $(SHMSRCS) \
+	$(LIB_KRB_HOSTSRCS) $(SERVER_KRB_SRCS) $(NETIO_SRCS) $(REALMDBSRCS)
+
+STLIBOBJS  = $(OBJS)
+STOBJLISTS=OBJS.ST
+
+#
+# These objects implement the time computation routines.
+#
+OSOBJS = $(OUTPRE)unix_time.$(OBJEXT)
+OSSRCS = unix_time.c
+
+##DOS##OSOBJS = $(OUTPRE)win_time.obj
+
+#
+# These objects implement ticket cacheing for Unix.  They are
+# replaced by other files when compiling for Windows or Mac.
+#
+CACHESRCS = \
+	tf_util.c	dest_tkt.c	in_tkt.c \
+	tkt_string.c	g_tf_fname.c	g_tf_realm.c \
+	g_cred.c	save_creds.c
+CACHEOBJS = \
+	$(OUTPRE)tf_util.$(OBJEXT) $(OUTPRE)dest_tkt.$(OBJEXT) $(OUTPRE)in_tkt.$(OBJEXT) \
+	$(OUTPRE)tkt_string.$(OBJEXT) $(OUTPRE)g_tf_fname.$(OBJEXT) $(OUTPRE)g_tf_realm.$(OBJEXT) \
+	$(OUTPRE)g_cred.$(OBJEXT) $(OUTPRE)save_creds.$(OBJEXT)
+
+##DOS##CACHEOBJS = $(OUTPRE)memcache.$(OBJEXT)
+
+#
+# These objects implement Kerberos realm<->host database lookup.
+# They read config files and/or network databases in various ways
+# on various platforms.
+#
+
+CNFFILE = g_cnffile
+##DOS##CNFFILE = win_store
+
+REALMDBSRCS=$(CNFFILE).c RealmsConfig-glue.c
+REALMDBOBJS=$(OUTPRE)$(CNFFILE).$(OBJEXT) $(OUTPRE)RealmsConfig-glue.$(OBJEXT)
+
+#
+# These objects are only used on server or debug implementations of Kerberos,
+# and they cause some major or minor sort of trouble for some
+# client-only platform (Mac or Windows).
+#
+SERVER_KRB_SRCS = \
+	klog.c		kuserok.c	log.c \
+	kntoln.c \
+	fgetst.c	rd_svc_key.c	cr_err_repl.c \
+	rd_req.c	g_svc_in_tkt.c	recvauth.c \
+	ad_print.c	cr_death_pkt.c \
+	kparse.c	put_svc_key.c	sendauth.c
+SERVER_KRB_OBJS = \
+	$(OUTPRE)klog.$(OBJEXT) $(OUTPRE)kuserok.$(OBJEXT) $(OUTPRE)log.$(OBJEXT) \
+	$(OUTPRE)kntoln.$(OBJEXT) \
+	$(OUTPRE)fgetst.$(OBJEXT) $(OUTPRE)rd_svc_key.$(OBJEXT) $(OUTPRE)cr_err_repl.$(OBJEXT) \
+	$(OUTPRE)rd_req.$(OBJEXT) $(OUTPRE)g_svc_in_tkt.$(OBJEXT) $(OUTPRE)recvauth.$(OBJEXT) \
+	$(OUTPRE)ad_print.$(OBJEXT) $(OUTPRE)cr_death_pkt.$(OBJEXT) \
+	$(OUTPRE)kparse.$(OBJEXT) $(OUTPRE)put_svc_key.$(OBJEXT) $(OUTPRE)sendauth.$(OBJEXT)
+#
+# These objects are included on Unix and Windows (for kstream and kadm)
+# but not under Mac (there are no file descriptors).
+#
+NETIO_SRCS=netread.c netwrite.c
+NETIO_OBJS=$(OUTPRE)netread.$(OBJEXT) $(OUTPRE)netwrite.$(OBJEXT)
+
+#
+# These objects glue the Kerberos library to the operating system
+# (time-of-day access, etc).  They are replaced in Mac and Windows
+# by other _glue.* routines.
+#
+LIB_KRB_HOSTSRCS=unix_glue.c
+LIB_KRB_HOSTOBJS=$(OUTPRE)unix_glue.$(OBJEXT)
+
+##DOS##LIB_KRB_HOSTOBJS=$(OUTPRE)win_glue.obj
+
+ARCHIVEARGS= $@ $(OBJS)
+
+# We want *library* compiler options...
+DBG=$(DBG_LIB)
+
+all-unix:: includes all-liblinks
+
+##DOS##LIBOBJS = $(OBJS)
+
+# comp_et_depend(krb_err)
+krb_err.h: krb_err.et
+krb_err.c: krb_err.et
+
+kadm_err.h: kadm_err.et
+kadm_err.c: kadm_err.et
+
+GEN_ERRTXT=$(AWK) -f $(srcdir)$(S)et_errtxt.awk outfile=$@
+
+krb_err_txt.c: krb_err.et $(srcdir)$(S)et_errtxt.awk
+	$(GEN_ERRTXT) $(srcdir)/krb_err.et
+
+# Will be empty on Darwin, krb_err_txt.c elsewhere.
+KRB_ERR_TXT=@KRB_ERR_TXT@
+##DOS##KRB_ERR_TXT=krb_err_txt.c
+err_txt.so err_txt.po $(OUTPRE)err_txt.$(OBJEXT): err_txt.c $(KRB_ERR_C) $(KRB_ERR_TXT)
+
+depend-dependencies: krb_err.h $(EHDRDIR)$(S)krb_err.h \
+	kadm_err.h $(EHDRDIR)$(S)kadm_err.h \
+	krb_err.c
+
+includes: $(EHDRDIR)$(S)krb_err.h $(EHDRDIR)$(S)kadm_err.h
+
+$(EHDRDIR)$(S)krb_err.h: krb_err.h
+	$(CP) krb_err.h $@
+$(EHDRDIR)$(S)kadm_err.h: kadm_err.h
+	$(CP) kadm_err.h $@
+
+clean-unix::
+	$(RM) $(EHDRDIR)/krb_err.h
+	$(RM) $(EHDRDIR)/kadm_err.h
+	$(RM) krb_err_txt.c
+
+clean::
+	-$(RM) $(OBJS)
+
+clean-:: clean-unix
+
+clean-unix::
+	-$(RM) krb_err.c
+	-$(RM) krb_err.h
+	-$(RM) kadm_err.c
+	-$(RM) kadm_err.h
+	-$(RM) ../../include/kerberosIV/krb_err.h
+	-$(RM) ../../include/kerberosIV/kadm_err.h
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+
+check-unix:: $(TEST_PROGS)
+check-windows::
+
+
+install-unix:: install-libs
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+change_password.so change_password.po $(OUTPRE)change_password.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/kadm.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/prot.h \
+  $(SRCTOP)/include/port-sockets.h change_password.c \
+  krb4int.h
+cr_auth_repl.so cr_auth_repl.po $(OUTPRE)cr_auth_repl.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h cr_auth_repl.c
+cr_ciph.so cr_ciph.po $(OUTPRE)cr_ciph.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h cr_ciph.c
+cr_tkt.so cr_tkt.po $(OUTPRE)cr_tkt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/port-sockets.h cr_tkt.c
+debug.so debug.po $(OUTPRE)debug.$(OBJEXT): $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  debug.c
+decomp_tkt.so decomp_tkt.po $(OUTPRE)decomp_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/prot.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb54proto.h \
+  $(SRCTOP)/include/port-sockets.h decomp_tkt.c
+g_ad_tkt.so g_ad_tkt.po $(OUTPRE)g_ad_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  g_ad_tkt.c krb4int.h
+g_pw_in_tkt.so g_pw_in_tkt.po $(OUTPRE)g_pw_in_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/prot.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/port-sockets.h \
+  g_pw_in_tkt.c krb4int.h
+g_phost.so g_phost.po $(OUTPRE)g_phost.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/port-sockets.h g_phost.c
+g_pw_tkt.so g_pw_tkt.po $(OUTPRE)g_pw_tkt.$(OBJEXT): \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/mit-copyright.h g_pw_tkt.c
+g_tkt_svc.so g_tkt_svc.po $(OUTPRE)g_tkt_svc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  g_tkt_svc.c
+getst.so getst.po $(OUTPRE)getst.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/mit-copyright.h $(SRCTOP)/include/port-sockets.h \
+  getst.c krb4int.h
+gethostname.so gethostname.po $(OUTPRE)gethostname.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  $(SRCTOP)/include/port-sockets.h gethostname.c krb4int.h
+kadm_err.so kadm_err.po $(OUTPRE)kadm_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) kadm_err.c
+kadm_net.so kadm_net.po $(OUTPRE)kadm_net.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/kerberosIV/kadm_err.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/kadm.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/krbports.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  kadm_net.c
+kadm_stream.so kadm_stream.po $(OUTPRE)kadm_stream.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/kerberosIV/kadm_err.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/kadm.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/prot.h \
+  $(SRCTOP)/include/port-sockets.h kadm_stream.c
+kname_parse.so kname_parse.po $(OUTPRE)kname_parse.$(OBJEXT): \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  kname_parse.c
+err_txt.so err_txt.po $(OUTPRE)err_txt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/port-sockets.h err_txt.c krb4int.h
+lifetime.so lifetime.po $(OUTPRE)lifetime.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h lifetime.c
+g_in_tkt.so g_in_tkt.po $(OUTPRE)g_in_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  g_in_tkt.c krb4int.h
+mk_auth.so mk_auth.po $(OUTPRE)mk_auth.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h mk_auth.c
+mk_err.so mk_err.po $(OUTPRE)mk_err.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h mk_err.c
+mk_priv.so mk_priv.po $(OUTPRE)mk_priv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/lsb_addr_cmp.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  mk_priv.c
+mk_req.so mk_req.po $(OUTPRE)mk_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  krb4int.h mk_req.c
+mk_safe.so mk_safe.po $(OUTPRE)mk_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/lsb_addr_cmp.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  mk_safe.c
+month_sname.so month_sname.po $(OUTPRE)month_sname.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  krb4int.h month_sname.c
+password_to_key.so password_to_key.po $(OUTPRE)password_to_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  krb4int.h password_to_key.c
+pkt_cipher.so pkt_cipher.po $(OUTPRE)pkt_cipher.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/mit-copyright.h $(SRCTOP)/include/kerberosIV/prot.h \
+  pkt_cipher.c
+pkt_clen.so pkt_clen.po $(OUTPRE)pkt_clen.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/mit-copyright.h $(SRCTOP)/include/kerberosIV/prot.h \
+  pkt_clen.c
+prot_client.so prot_client.po $(OUTPRE)prot_client.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h prot_client.c
+prot_common.so prot_common.po $(OUTPRE)prot_common.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h prot_common.c
+prot_kdc.so prot_kdc.po $(OUTPRE)prot_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  prot_kdc.c
+rd_err.so rd_err.po $(OUTPRE)rd_err.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h rd_err.c
+rd_priv.so rd_priv.po $(OUTPRE)rd_priv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/lsb_addr_cmp.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  rd_priv.c
+rd_safe.so rd_safe.po $(OUTPRE)rd_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/lsb_addr_cmp.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  rd_safe.c
+send_to_kdc.so send_to_kdc.po $(OUTPRE)send_to_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/krbports.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  krb4int.h send_to_kdc.c
+stime.so stime.po $(OUTPRE)stime.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/port-sockets.h krb4int.h stime.c
+strnlen.so strnlen.po $(OUTPRE)strnlen.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h strnlen.c
+rd_preauth.so rd_preauth.po $(OUTPRE)rd_preauth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/krb_db.h $(SRCTOP)/include/kerberosIV/prot.h \
+  $(SRCTOP)/include/port-sockets.h krb4int.h rd_preauth.c
+mk_preauth.so mk_preauth.po $(OUTPRE)mk_preauth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h mk_preauth.c
+unix_time.so unix_time.po $(OUTPRE)unix_time.$(OBJEXT): \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  unix_time.c
+tf_util.so tf_util.po $(OUTPRE)tf_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  krb4int.h tf_util.c
+dest_tkt.so dest_tkt.po $(OUTPRE)dest_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h dest_tkt.c
+in_tkt.so in_tkt.po $(OUTPRE)in_tkt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h in_tkt.c
+tkt_string.so tkt_string.po $(OUTPRE)tkt_string.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  tkt_string.c
+g_tf_fname.so g_tf_fname.po $(OUTPRE)g_tf_fname.$(OBJEXT): \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/mit-copyright.h g_tf_fname.c
+g_tf_realm.so g_tf_realm.po $(OUTPRE)g_tf_realm.$(OBJEXT): \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  g_tf_realm.c
+g_cred.so g_cred.po $(OUTPRE)g_cred.$(OBJEXT): $(KRB_ERR_H_DEP) \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  g_cred.c
+save_creds.so save_creds.po $(OUTPRE)save_creds.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  krb4int.h save_creds.c
+unix_glue.so unix_glue.po $(OUTPRE)unix_glue.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  krb4int.h unix_glue.c
+klog.so klog.po $(OUTPRE)klog.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/klog.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  klog.c krb4int.h
+kuserok.so kuserok.po $(OUTPRE)kuserok.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  kuserok.c
+log.so log.po $(OUTPRE)log.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/klog.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  krb4int.h log.c
+kntoln.so kntoln.po $(OUTPRE)kntoln.$(OBJEXT): $(KRB_ERR_H_DEP) \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  kntoln.c
+fgetst.so fgetst.po $(OUTPRE)fgetst.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/mit-copyright.h $(SRCTOP)/include/port-sockets.h \
+  fgetst.c krb4int.h
+rd_svc_key.so rd_svc_key.po $(OUTPRE)rd_svc_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/mit-copyright.h $(SRCTOP)/include/kerberosIV/prot.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/krb54proto.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  krb4int.h rd_svc_key.c
+cr_err_repl.so cr_err_repl.po $(OUTPRE)cr_err_repl.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h cr_err_repl.c
+rd_req.so rd_req.po $(OUTPRE)rd_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb54proto.h rd_req.c
+g_svc_in_tkt.so g_svc_in_tkt.po $(OUTPRE)g_svc_in_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h $(SRCTOP)/include/port-sockets.h \
+  g_svc_in_tkt.c krb4int.h
+recvauth.so recvauth.po $(OUTPRE)recvauth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  recvauth.c
+ad_print.so ad_print.po $(OUTPRE)ad_print.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  ad_print.c krb4int.h
+cr_death_pkt.so cr_death_pkt.po $(OUTPRE)cr_death_pkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/kerberosIV/prot.h cr_death_pkt.c
+kparse.so kparse.po $(OUTPRE)kparse.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/kparse.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  kparse.c
+put_svc_key.so put_svc_key.po $(OUTPRE)put_svc_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  krb4int.h put_svc_key.c
+sendauth.so sendauth.po $(OUTPRE)sendauth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/mit-copyright.h \
+  $(SRCTOP)/include/port-sockets.h krb4int.h sendauth.c
+netread.so netread.po $(OUTPRE)netread.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/port-sockets.h netread.c
+netwrite.so netwrite.po $(OUTPRE)netwrite.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/port-sockets.h \
+  netwrite.c
+g_cnffile.so g_cnffile.po $(OUTPRE)g_cnffile.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h g_cnffile.c krb4int.h
+RealmsConfig-glue.so RealmsConfig-glue.po $(OUTPRE)RealmsConfig-glue.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h RealmsConfig-glue.c \
+  krb4int.h
diff --git a/krb5-1-6/src/lib/krb4/Password.c b/krb5-1-6/src/lib/krb4/Password.c
new file mode 100644
index 000000000..5862e0e65
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/Password.c
@@ -0,0 +1,436 @@
+#include "kerberos.h"
+#define KRB_DEFS
+#include "krb_driver.h"
+
+#include <Types.h>
+#include <Dialogs.h>
+#include <Controls.h>
+#include <ToolUtils.h>
+#include <OSUtils.h>
+#include <Resources.h>
+
+/* 	added for OpenInitRF.c
+ 	FIXME jcm - should check that they are not in c-mac 
+	or other included file
+*/
+
+#include <Errors.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Traps.h>
+#include <GestaltEqu.h>
+#include <Folders.h>
+
+
+// #include "debug.h"
+
+#define kLoginDLOGID		-4081
+#define kErrorALERTID		-4082
+#define kLoginOKItem		1
+#define kLoginCnclItem		2
+#define kLoginNameItem		10
+#define kLoginVisPwItem		9
+#define kLoginFrameItem		5
+#define kLoginIvisPwItem	6
+#define kBadUserError		1
+#define kNotUniqueError		2
+#define kGenError			3
+#define kIntegrityError		4
+#define kBadPasswordError	5
+#define cr 					0x0D
+#define enter 				0x03
+#define bs 					0x08
+#define tab 				0x09
+#define larrow 				0x1C
+#define rarrow 				0x1D
+#define uarrow 				0x1E
+#define darrow 				0x1F
+#define DialogNotDone 		1
+
+typedef union {								// used to convert ProcPtr to Handle
+	Handle		H;
+	ProcPtr		P;
+} Proc2Hand;
+
+static char gPassword [MAX_K_NAME_SZ]	= "\0";
+
+pascal void FrameOKbtn( WindowPtr myWindow, short itemNo );
+pascal Boolean TwoItemFilter( DialogPtr dlog, EventRecord *event, short *itemHit );
+
+/* 
+	FIXME jcm - begin OpenInitRF
+	Mac_store thinks that it is managing the open resource file
+	is this code in conflict?
+*/
+
+void GetExtensionsFolder(short *vRefNumP, long *dirIDP)
+{
+	Boolean hasFolderMgr = false;
+	long feature;
+	
+/*	
+	FIXME Error:   Ô_GestaltDispatchÕ has not been declared - not needed now? - jcm
+	if (TrapAvailable(_GestaltDispatch)) 
+*/
+	if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true;
+	if (!hasFolderMgr) {
+		GetSystemFolder(vRefNumP, dirIDP);
+		return;
+	}
+	else {
+		if (FindFolder(kOnSystemDisk, kExtensionFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
+			*vRefNumP = 0;
+			*dirIDP = 0;
+		}
+	}
+}
+	
+short SearchFolderForINIT(long targetType, long targetCreator, short vRefNum, long dirID)
+{
+	HParamBlockRec fi;
+	Str255 filename;
+	short refnum;
+	
+	fi.fileParam.ioCompletion = nil;
+	fi.fileParam.ioNamePtr = filename;
+	fi.fileParam.ioVRefNum = vRefNum;
+	fi.fileParam.ioDirID = dirID;
+	fi.fileParam.ioFDirIndex = 1;
+	
+	while (PBHGetFInfo(&fi, false) == noErr) {
+		/* scan system folder for driver resource files of specific type & creator */
+		if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
+			fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
+			refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
+			return refnum;
+			}
+		/* check next file in folder */
+		fi.fileParam.ioFDirIndex++;
+		fi.fileParam.ioDirID = dirID;	/* PBHGetFInfo() clobbers ioDirID */
+		}
+	return(-1);
+}	
+
+short OpenInitRF()
+{
+	short refnum;
+	short vRefNum;
+	long dirID;
+	
+	/* first search Extensions Panels */
+	GetExtensionsFolder(&vRefNum, &dirID);
+	refnum = SearchFolderForINIT('INIT', 'krbL', vRefNum, dirID);
+	if (refnum != -1) return(refnum);
+		
+	/* next search System Folder  */
+	GetSystemFolder(&vRefNum, &dirID);
+	refnum = SearchFolderForINIT('INIT', 'krbL', vRefNum, dirID);
+	if (refnum != -1) return(refnum);
+		
+	/* finally, search Control Panels */
+	GetCPanelFolder(&vRefNum, &dirID);
+	refnum = SearchFolderForINIT('INIT', 'krbL', vRefNum, dirID);
+	if (refnum != -1) return(refnum);
+		
+	return -1;
+}	
+
+int DisplayError( short errorID )
+{
+	OSErr			err;
+	Str255			errText;
+	
+	GetIndString(errText,kErrorALERTID,errorID);
+	if (errText[0] == 0) {
+		SysBeep(1);		// nothing else we can do
+		return cKrbCorruptedFile;
+	}
+
+	ParamText(errText,"\p","\p","\p");
+	err = StopAlert(kErrorALERTID,nil);
+	
+	return DialogNotDone;
+}
+
+
+
+OSErr GetUserInfo( char *password )
+{
+	DialogPtr		myDLOG;
+	short			itemHit;
+	short			itemType;
+	Handle			itemHandle;
+	Rect			itemRect;
+	OSErr			rc = DialogNotDone;
+	Str255			tempStr,tpswd,tuser;
+	Proc2Hand		procConv;
+	short			rf;
+	char uname[ANAME_SZ]="\0";
+	char uinst[INST_SZ]="\0";
+	char realm[REALM_SZ]="\0";
+	char UserName[MAX_K_NAME_SZ]="\0";
+	CursHandle		aCursor;
+	
+	krb_get_lrealm (realm, 1);
+
+	//////////////////////////////////////////////////////
+	// already got a password, just get the initial ticket
+	//////////////////////////////////////////////////////
+	if (*gPassword)	{
+		strncpy (UserName, krb_get_default_user( ), sizeof(UserName)-1);
+		UserName[sizeof(UserName) - 1] = '\0';
+		/* FIXME jcm - if we have a password then no dialog 
+		   comes up for setting the uinstance. */
+		rc = kname_parse(uname, uinst, realm, UserName);
+			if (rc) return rc;
+		(void) dest_all_tkts();		// start from scratch
+		rc = krb_get_pw_in_tkt(uname,uinst,realm,"krbtgt",realm,DEFAULT_TKT_LIFE,gPassword);
+		*gPassword = 0;		// Always clear, password only good for one shot
+		return rc;
+	}
+	
+	/////////////////////////
+	// Ask user for password
+	/////////////////////////
+	rf = OpenInitRF();		// need the resource file for the dialog resources
+	if (rf<=0) return rf;
+	password[0] = 0;
+	myDLOG = GetNewDialog( kLoginDLOGID, (void *) NULL, (WindowPtr) -1 );
+	if( myDLOG == NULL ) {
+		CloseResFile(rf);
+		return cKrbCorruptedFile;
+	}
+
+	// Insert user's name in dialog
+	strncpy (UserName, krb_get_default_user( ), sizeof(UserName) - 1);
+	UserName[sizeof(UserName) - 1] = '\0';
+	if (*UserName) {
+		tempStr[0] = strlen(UserName);
+		memcpy( &(tempStr[1]), UserName, tempStr[0]);
+		GetDItem( myDLOG, kLoginNameItem, &itemType, &itemHandle, &itemRect );
+		SetIText( itemHandle, tempStr );
+		SelIText( myDLOG, kLoginVisPwItem,0,0 );
+	}
+	else SelIText( myDLOG, kLoginNameItem,0,0 );
+	
+	// Establish a user item around the OK button to draw the default button frame in
+	GetDItem( myDLOG, kLoginOKItem, &itemType, &itemHandle, &itemRect );
+	InsetRect( &itemRect, -4, -4 );				// position user item around OK button
+	procConv.P = (ProcPtr) FrameOKbtn;			// convert ProcPtr to a Handle
+	SetDItem( myDLOG, kLoginFrameItem, userItem, procConv.H, &itemRect );
+	
+	InitCursor();
+	do {
+		do {										// display the dialog & handle events
+			SetOKEnable(myDLOG);
+			ModalDialog( (ModalFilterProcPtr) TwoItemFilter, (short *) &itemHit );
+		} while( itemHit != kLoginOKItem && itemHit != kLoginCnclItem );
+		
+		if( itemHit == kLoginOKItem ) {				// OK button pressed?			
+			GetDItem( myDLOG, kLoginNameItem, &itemType, &itemHandle, &itemRect );
+			GetIText( itemHandle, tempStr );
+		
+			tempStr[0] = ( tempStr[0] < MAX_K_NAME_SZ ) ? tempStr[0] : MAX_K_NAME_SZ-1 ;
+			memcpy ((void*) UserName, (void*) &(tempStr[1]), tempStr[0]);
+			UserName[tempStr[0]] = 0;
+			
+			GetDItem( myDLOG, kLoginIvisPwItem, &itemType, &itemHandle, &itemRect );
+			GetIText( itemHandle, tempStr );
+		
+			tempStr[0] = ( tempStr[0] < ANAME_SZ ) ? tempStr[0] : ANAME_SZ-1 ;
+			memcpy( (void*) password, (void*) &(tempStr[1]), tempStr[0]);
+			password[tempStr[0]] = 0;
+
+			//----------------------------------------------------
+			// Get the ticket
+			//----------------------------------------------------
+			aCursor = GetCursor(watchCursor);
+			SetCursor(*aCursor);
+			ShowCursor();
+			
+			rc = kname_parse(uname, uinst, realm, UserName);
+			if (rc) return rc;
+
+			(void) dest_all_tkts();		// start from scratch
+			rc = krb_get_pw_in_tkt(uname,uinst,realm,"krbtgt",realm,DEFAULT_TKT_LIFE,password);
+			InitCursor();
+			if (!rc) 
+			switch (rc) {
+				case KDC_PR_UNKNOWN:
+				case KDC_NULL_KEY:
+					rc = DisplayError(kBadUserError);
+					SelIText( myDLOG, kLoginNameItem,0,256 );
+					break;
+				case KDC_PR_N_UNIQUE:
+					rc = DisplayError(kNotUniqueError);
+					SelIText( myDLOG, kLoginNameItem,0,256 );
+					break;
+				case KDC_GEN_ERR:
+					rc = DisplayError(kGenError);
+					SelIText( myDLOG, kLoginNameItem,0,256 );
+					break;
+				case RD_AP_MODIFIED:
+					rc = DisplayError(kIntegrityError);
+					SelIText( myDLOG, kLoginNameItem,0,256 );
+					break;
+				case INTK_BADPW:
+					rc = DisplayError(kBadPasswordError);
+					SelIText( myDLOG, kLoginVisPwItem,0,256 );
+					break;
+				default:
+					break;
+			}
+			//----------------------------------------------------
+		}
+		else rc = cKrbUserCancelled;						// pressed the Cancel button
+	} while( rc == DialogNotDone );
+
+	DisposDialog( myDLOG );
+	CloseResFile(rf);
+	return rc;
+}
+
+
+static pascal void FrameOKbtn( WindowPtr myWindow, short itemNo )
+{
+	short		tempType;
+	Handle		tempHandle;
+	Rect		itemRect;
+
+	GetDItem( (DialogPtr) myWindow, itemNo, &tempType, &tempHandle, &itemRect );
+	PenSize( 3, 3 );
+	FrameRoundRect( &itemRect, 16, 16 );		// make it an OK button suitable for framing
+}
+
+
+static pascal Boolean TwoItemFilter( DialogPtr dlog, EventRecord *event, short *itemHit )
+{
+	DialogPtr	evtDlog;
+	short		selStart, selEnd;
+	Handle		okBtnHandle;
+	short		tempType;
+	Rect		tempRect;
+	long		tempTicks;
+
+	if( event->what != keyDown && event->what != autoKey )
+		return false;				// don't care about this event
+
+	switch( event->message & charCodeMask )
+	{
+	case cr:						// Return  (hitting return or enter is the same as hitting the OK button)
+	case enter:						// Enter
+	
+		if (!OKIsEnabled(dlog)) {
+			event->what = nullEvent;
+			return false;
+		}
+		
+		GetDItem( dlog, kLoginOKItem, &tempType, &okBtnHandle, &tempRect );
+		HiliteControl( (ControlHandle) okBtnHandle, 1 );	// hilite the OK button
+		Delay( 10, &tempTicks );	// wait a little while
+		HiliteControl( (ControlHandle) okBtnHandle, 0 );
+
+		*itemHit = kLoginOKItem;		// OK Button
+		return true;				// We handled the event
+
+	case tab:						// Tab
+	case larrow:					// Left arrow  (Keys that just change the selection)
+	case rarrow:					// Right arrow
+	case uarrow:					// Up arrow
+	case darrow:					// Down arrow
+		return false;				// Let ModalDialog handle them
+
+	default:
+	
+		// First see if we're in password field, do stuff to make ¥ displayed
+		
+		if( ((DialogPeek) dlog)->editField == kLoginVisPwItem - 1 ) {
+
+			selStart = (**((DialogPeek) dlog)->textH).selStart;	// Get the selection in the visible item
+			selEnd = (**((DialogPeek) dlog)->textH).selEnd;
+
+			SelIText( dlog, kLoginIvisPwItem, selStart, selEnd );	// Select text in invisible item
+			DialogSelect( event,&evtDlog, itemHit );			// Input key
+
+			SelIText( dlog, kLoginVisPwItem, selStart, selEnd );	// Select same area in visible item
+			if( ( event->message & charCodeMask ) != bs )		// If it's not a backspace (backspace is the only key that can affect both the text and the selection- thus we need to process it in both fields, but not change it for the hidden field.
+				event->message = 'Â¥';							// Replace with character to use
+		}
+		
+		// Do the key event and set the hilite on the OK button accordingly
+		
+		DialogSelect( event,&evtDlog, itemHit );			// Input key
+		SetOKEnable(dlog);
+		
+		// Pass a NULL event back to DialogMgr
+		
+		event->what = nullEvent;
+		
+		return false;
+	}
+}
+
+static int SetOKEnable( DialogPtr dlog )
+{
+	short		itemType,state;
+	Handle		itemHandle;
+	Rect		itemRect;
+	Str255		tpswd,tuser;
+	ControlHandle okButton;
+
+	GetDItem( dlog, kLoginNameItem, &itemType, &itemHandle, &itemRect );
+	GetIText( itemHandle, tuser );
+	GetDItem( dlog, kLoginVisPwItem, &itemType, &itemHandle, &itemRect );
+	GetIText( itemHandle, tpswd );
+	GetDItem( dlog, kLoginOKItem, &itemType, (Handle *) &okButton, &itemRect );
+	state = (tuser[0] && tpswd[0]) ? 0 : 255;
+	HiliteControl(okButton,state);
+}
+
+static int OKIsEnabled( DialogPtr dlog )
+{
+	short		itemType;
+	Rect		itemRect;
+	ControlHandle okButton;
+
+	GetDItem( dlog, kLoginOKItem, &itemType, (Handle *) &okButton, &itemRect );
+	return ((**okButton).contrlHilite != 255);
+}
+
+
+extern OSErr INTERFACE 
+CacheInitialTicket( serviceName )
+     char *serviceName;
+{
+	char service[ANAME_SZ]="\0";
+	char instance[INST_SZ]="\0";
+	char realm[REALM_SZ]="\0";
+	OSErr err = noErr;
+	char uname[ANAME_SZ]="\0";
+	char uinst[INST_SZ]="\0";
+	char urealm[REALM_SZ]="\0";
+	char password[KKEY_SZ]="\0";
+	char UserName[MAX_K_NAME_SZ]="\0";
+	char oldName[120]="\0";	
+								
+	err = GetUserInfo( password );
+	if (err) return err;
+	
+	if (!serviceName || (serviceName[0] == '\0'))
+		return err;
+	
+	strncpy (UserName, krb_get_default_user(), sizeof(UserName) - 1);
+	UserName[sizeof(UserName) - 1] = '\0';
+			
+ 	err = kname_parse(uname, uinst, urealm, UserName);
+ 	if (err) return err;
+ 	
+ 	if (urealm[0] == '\0')
+ 		krb_get_lrealm (urealm, 1);
+	
+	err = kname_parse(service, instance, realm, serviceName); // check if there is a service name
+	if (err) return err;
+	
+	err = krb_get_pw_in_tkt(uname,uinst,urealm,service,instance,DEFAULT_TKT_LIFE,password);
+	return err;
+}
diff --git a/krb5-1-6/src/lib/krb4/RealmsConfig-glue.c b/krb5-1-6/src/lib/krb4/RealmsConfig-glue.c
new file mode 100644
index 000000000..dbdfe54cd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/RealmsConfig-glue.c
@@ -0,0 +1,697 @@
+/*
+ * lib/krb4/RealmsConfig-glue.c
+ *
+ * Copyright 1985-2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * These calls implement the layer of Kerberos v4 library which
+ * accesses realms configuration by calling into the Kerberos Profile
+ * library.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "profile.h"
+#include "krb.h"
+#include "krb4int.h"
+#include "k5-int.h"		/* for accessor, addrlist stuff */
+#include "port-sockets.h"
+
+#define KRB5_PRIVATE 1
+/* For krb5_get_default_config_files and krb5_free_config_files */
+#include "krb5.h"
+#undef KRB5_PRIVATE
+
+/* These two *must* be kept in sync to avoid buffer overflows. */
+#define SCNSCRATCH	"%1023s"
+#define SCRATCHSZ	1024
+#if SCRATCHSZ < MAXHOSTNAMELEN
+#error "SCRATCHSZ must be at least MAXHOSTNAMELEN"
+#endif
+
+/*
+ * Returns to the caller an initialized profile using the same files
+ * as Kerberos4Lib would.
+ */
+int KRB5_CALLCONV
+krb_get_profile(profile_t* profile)
+{
+    int			retval = KSUCCESS;
+    profile_filespec_t	*files = NULL;
+
+    /* Use krb5 to get the config files */
+    retval = krb5_get_default_config_files(&files);
+
+    if (retval == KSUCCESS) {
+	retval = profile_init((const_profile_filespec_t *)files, profile);
+    }
+
+    if (files) {
+	krb5_free_config_files(files);
+    }
+
+    if (retval == ENOENT) {
+	/* No edu.mit.Kerberos file */
+	return KFAILURE;
+    }
+
+    if ((retval == PROF_SECTION_NOTOP) ||
+	(retval == PROF_SECTION_SYNTAX) ||
+	(retval == PROF_RELATION_SYNTAX) ||
+	(retval == PROF_EXTRA_CBRACE) ||
+	(retval == PROF_MISSING_OBRACE)) {
+	/* Bad config file format */
+	return retval;
+    }
+
+    return retval;
+}
+
+/* Caller must ensure that n >= 1 and that pointers are non-NULL. */
+static int
+krb_prof_get_nth(
+    char	*ret,
+    size_t	retlen,
+    const char	*realm,
+    int		n,
+    const char	*sec,
+    const char	*key)
+{
+    int		result;
+    long	profErr;
+    profile_t	profile = NULL;
+    const	char *names[4];
+    void	*iter = NULL;
+    char	*name = NULL;
+    char	*value = NULL;
+    int		i;
+
+    result = KFAILURE;
+
+    profErr = krb_get_profile(&profile);
+    if (profErr) {
+	/*
+	 * Can krb_get_profile() return errors that change PROFILE?
+	 */
+	goto cleanup;
+    }
+    names[0] = sec;
+    names[1] = realm;
+    names[2] = key;
+    names[3] = NULL;
+    profErr = profile_iterator_create(profile, names,
+				      PROFILE_ITER_RELATIONS_ONLY, &iter);
+    if (profErr)
+	goto cleanup;
+
+    result = KSUCCESS;
+    for (i = 1; i <= n; i++) {
+	if (name != NULL)
+	    profile_release_string(name);
+	if (value != NULL)
+	    profile_release_string(value);
+	name = value = NULL;
+
+	profErr = profile_iterator(&iter, &name, &value);
+	if (profErr || (name == NULL)) {
+	    result = KFAILURE;
+	    break;
+	}
+    }
+    if (result == KSUCCESS) {
+	/* Return error rather than truncating. */
+	/* Don't strncpy because retlen is a guess for some callers */
+	if (strlen(value) >= retlen)
+	    result = KFAILURE;
+	else
+	    strcpy(ret, value);
+    }
+cleanup:
+    if (name != NULL)
+	profile_release_string(name);
+    if (value != NULL)
+	profile_release_string(value);
+    if (iter != NULL)
+	profile_iterator_free(&iter);
+    if (profile != NULL)
+	profile_abandon(profile);
+    return result;
+}
+
+/*
+ * Index -> realm name mapping
+ *
+ * Not really. The original implementation has a cryptic comment
+ * indicating that the function can only work for n = 1, and always
+ * returns the default realm. I don't know _why_ that's the case, but
+ * I have to do it that way...
+ *
+ * Old description from g_krbrlm.c:
+ *
+ * krb_get_lrealm takes a pointer to a string, and a number, n.  It fills
+ * in the string, r, with the name of the nth realm specified on the
+ * first line of the kerberos config file (KRB_CONF, defined in "krb.h").
+ * It returns 0 (KSUCCESS) on success, and KFAILURE on failure.  If the
+ * config file does not exist, and if n=1, a successful return will occur
+ * with r = KRB_REALM (also defined in "krb.h").
+ *
+ * NOTE: for archaic & compatibility reasons, this routine will only return
+ * valid results when n = 1.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst().  This will also look in KRB_FB_CONF is
+ * ATHENA_CONF_FALLBACK is defined.
+ */
+int KRB5_CALLCONV
+krb_get_lrealm(
+    char	*realm,
+    int		n)
+{
+    int         result = KSUCCESS;
+    profile_t   profile = NULL;
+    char       *profileDefaultRealm = NULL;
+    char      **profileV4Realms = NULL;
+    int         profileHasDefaultRealm = 0;
+    int         profileDefaultRealmIsV4RealmInProfile = 0;
+    char        krbConfLocalRealm[REALM_SZ];
+    int         krbConfHasLocalRealm = 0;
+
+    if ((realm == NULL) || (n != 1)) { result = KFAILURE; }
+
+    if (result == KSUCCESS) {
+        /* Some callers don't check the return value so we initialize
+         * to an empty string in case it never gets filled in. */
+        realm [0] = '\0';  
+    }
+    
+    if (result == KSUCCESS) {
+        int profileErr = krb_get_profile (&profile);
+
+        if (!profileErr) {
+            /* Get the default realm from the profile */
+            profileErr = profile_get_string(profile, REALMS_V4_PROF_LIBDEFAULTS_SECTION,
+                                            REALMS_V4_DEFAULT_REALM, NULL, NULL,
+                                            &profileDefaultRealm);
+            if (profileDefaultRealm == NULL) { profileErr = KFAILURE; }
+        }
+
+        if (!profileErr) {
+            /* If there is an equivalent v4 realm to the default realm, use that instead */
+            char *profileV4EquivalentRealm = NULL;
+
+            if (profile_get_string (profile, "realms", profileDefaultRealm, "v4_realm", NULL,
+                                    &profileV4EquivalentRealm) == 0 &&
+                profileV4EquivalentRealm != NULL) {
+
+                profile_release_string (profileDefaultRealm);
+                profileDefaultRealm = profileV4EquivalentRealm;
+            }
+        }
+
+        if (!profileErr) {
+            if (strlen (profileDefaultRealm) < REALM_SZ) {
+                profileHasDefaultRealm = 1;  /* a reasonable default realm */
+            } else {
+                profileErr = KFAILURE;
+            }
+        }
+
+        if (!profileErr) {
+            /* Walk through the v4 realms list looking for the default realm */
+            const char *profileV4RealmsList[] = { REALMS_V4_PROF_REALMS_SECTION, NULL };
+
+            if (profile_get_subsection_names (profile, profileV4RealmsList,
+                                              &profileV4Realms) == 0 &&
+                profileV4Realms != NULL) {
+
+                char **profileRealm;
+                for (profileRealm = profileV4Realms; *profileRealm != NULL; profileRealm++) {
+                    if (strcmp (*profileRealm, profileDefaultRealm) == 0) {
+                        /* default realm is a v4 realm */
+                        profileDefaultRealmIsV4RealmInProfile = 1;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    
+    if (result == KSUCCESS) {
+        /* Try to get old-style config file lookup for fallback. */
+        FILE	*cnffile = NULL;
+        char	scratch[SCRATCHSZ];
+
+        cnffile = krb__get_cnffile();
+        if (cnffile != NULL) {
+            if (fscanf(cnffile, SCNSCRATCH, scratch) == 1) {
+                if (strlen(scratch) < REALM_SZ) {
+                    strncpy(krbConfLocalRealm, scratch, REALM_SZ);
+                    krbConfHasLocalRealm = 1;
+                }
+            }
+            fclose(cnffile);
+        }
+    }
+
+    if (result == KSUCCESS) {
+        /*
+         * We want to favor the profile value over the krb.conf value
+         * but not stop suppporting its use with a v5-only profile. 
+         * So we only use the krb.conf realm when the default profile
+         * realm doesn't exist in the v4 realm section of the profile.
+         */
+        if (krbConfHasLocalRealm && !profileDefaultRealmIsV4RealmInProfile) {
+            strncpy (realm, krbConfLocalRealm, REALM_SZ);
+        } else if (profileHasDefaultRealm) {
+            strncpy (realm, profileDefaultRealm, REALM_SZ);
+        } else {
+            result = KFAILURE;  /* No default realm */
+        }
+    }
+
+    if (profileDefaultRealm != NULL) { profile_release_string (profileDefaultRealm); }
+    if (profileV4Realms     != NULL) { profile_free_list (profileV4Realms); }
+    if (profile             != NULL) { profile_abandon (profile); }
+
+    return result;
+}
+
+/*
+ * Realm, index -> admin KDC mapping
+ *
+ * Old description from g_admhst.c:
+ *
+ * Given a Kerberos realm, find a host on which the Kerberos database
+ * administration server can be found.
+ *
+ * krb_get_admhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer n, and
+ * returns (in h) the nth administrative host entry from the configuration
+ * file (KRB_CONF, defined in "krb.h") associated with the specified realm.
+ * If ATHENA_CONF_FALLBACK is defined, also look in old location.
+ *
+ * On error, get_admhst returns KFAILURE. If all goes well, the routine
+ * returns KSUCCESS.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst().
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * a Kerberos admin server.  In the long run, this functionality will be
+ * provided by a nameserver.
+ */
+int KRB5_CALLCONV
+krb_get_admhst(
+    char	*host,
+    char	*realm,
+    int		n)
+{
+    int		result;
+    int		i;
+    FILE	*cnffile;
+    char	linebuf[BUFSIZ];
+    char	trealm[SCRATCHSZ];
+    char	thost[SCRATCHSZ];
+    char	scratch[SCRATCHSZ];
+
+    if (n < 1 || host == NULL || realm == NULL)
+	return KFAILURE;
+
+    result = krb_prof_get_nth(host, MAXHOSTNAMELEN, realm, n,
+			      REALMS_V4_PROF_REALMS_SECTION,
+			      REALMS_V4_PROF_ADMIN_KDC);
+    if (result == KSUCCESS)
+	return result;
+
+    /*
+     * Do old-style config file lookup.
+     */
+    cnffile = krb__get_cnffile();
+    if (cnffile == NULL)
+	return KFAILURE;
+    result = KSUCCESS;
+    for (i = 0; i < n;) {
+	if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+	    result = KFAILURE;
+	    break;
+	}
+	if (!strchr(linebuf, '\n')) {
+	    result = KFAILURE;
+	    break;
+	}
+	/*
+	 * Need to scan for a token after 'admin' to make sure that
+	 * admin matched correctly.
+	 */
+	if (sscanf(linebuf, SCNSCRATCH " " SCNSCRATCH " admin " SCNSCRATCH,
+		   trealm, thost, scratch) != 3)
+	    continue;
+	if (!strcmp(trealm, realm))
+	    i++;
+    }
+    fclose(cnffile);
+    if (result == KSUCCESS && strlen(thost) < MAX_HSTNM)
+	strcpy(host, thost);
+    else
+	result = KFAILURE;
+    return result;
+}
+
+/*
+ * Realm, index -> kpasswd KDC mapping
+ */
+int
+krb_get_kpasswdhst(
+    char	*host,
+    char	*realm,
+    int		n)
+{
+    if (n < 1 || host == NULL || realm == NULL)
+	return KFAILURE;
+
+    return krb_prof_get_nth(host, MAXHOSTNAMELEN, realm, n,
+			    REALMS_V4_PROF_REALMS_SECTION,
+			    REALMS_V4_PROF_KPASSWD_KDC);
+}
+
+/*
+ * Realm, index -> KDC mapping
+ *
+ * Old description from g_krbhst.c:
+ *
+ * Given a Kerberos realm, find a host on which the Kerberos authenti-
+ * cation server can be found.
+ *
+ * krb_get_krbhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer, n, and
+ * returns (in h) the nth entry from the configuration file (KRB_CONF,
+ * defined in "krb.h") associated with the specified realm.
+ *
+ * On end-of-file, krb_get_krbhst returns KFAILURE.  If n=1 and the
+ * configuration file does not exist, krb_get_krbhst will return KRB_HOST
+ * (also defined in "krb.h").  If all goes well, the routine returnes
+ * KSUCCESS.
+ *
+ * The KRB_CONF file contains the name of the local realm in the first
+ * line (not used by this routine), followed by lines indicating realm/host
+ * entries.  The words "admin server" following the hostname indicate that
+ * the host provides an administrative database server.
+ * This will also look in KRB_FB_CONF if ATHENA_CONF_FALLBACK is defined.
+ *
+ * For example:
+ *
+ *	ATHENA.MIT.EDU
+ *	ATHENA.MIT.EDU kerberos-1.mit.edu admin server
+ *	ATHENA.MIT.EDU kerberos-2.mit.edu
+ *	LCS.MIT.EDU kerberos.lcs.mit.edu admin server
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * kerberos.  In the long run, this functionality will be provided by a
+ * nameserver.
+ */
+#ifdef KRB5_DNS_LOOKUP
+static struct {
+    time_t when;
+    char realm[REALM_SZ+1];
+    struct srv_dns_entry *srv;
+} dnscache = { 0, { 0 }, 0 };
+#define DNS_CACHE_TIMEOUT	60 /* seconds */
+#endif
+
+int KRB5_CALLCONV
+krb_get_krbhst(
+    char	*host,
+    const char	*realm,
+    int		n)
+{
+    int		result;
+    int		i;
+    FILE	*cnffile;
+    char	linebuf[BUFSIZ];
+    char	tr[SCRATCHSZ];
+    char	scratch[SCRATCHSZ];
+#ifdef KRB5_DNS_LOOKUP
+    time_t now;
+#endif
+
+    if (n < 1 || host == NULL || realm == NULL)
+	return KFAILURE;
+
+#ifdef KRB5_DNS_LOOKUP
+    /* We'll only have this realm's info in the DNS cache if there is
+       no data in the local config files.
+
+       XXX The files could've been updated in the last few seconds.
+       Do we care?  */
+    if (!strncmp(dnscache.realm, realm, REALM_SZ)
+	&& (time(&now), abs(dnscache.when - now) < DNS_CACHE_TIMEOUT)) {
+	struct srv_dns_entry *entry;
+
+    get_from_dnscache:
+	/* n starts at 1, addrs indices run 0..naddrs */
+	for (i = 1, entry = dnscache.srv; i < n && entry; i++)
+	    entry = entry->next;
+	if (entry == NULL)
+	    return KFAILURE;
+	if (strlen(entry->host) + 6 >= MAXHOSTNAMELEN)
+	    return KFAILURE;
+	sprintf(host, "%s:%d", entry->host, entry->port);
+	return KSUCCESS;
+    }
+#endif
+
+    result = krb_prof_get_nth(host, MAXHOSTNAMELEN, realm, n,
+			      REALMS_V4_PROF_REALMS_SECTION,
+			      REALMS_V4_PROF_KDC);
+    if (result == KSUCCESS)
+	return result;
+    /*
+     * Do old-style config file lookup.
+     */
+    do {
+	cnffile = krb__get_cnffile();
+	if (cnffile == NULL)
+	    break;
+	/* Skip default realm name. */
+	if (fscanf(cnffile, SCNSCRATCH, tr) == EOF) {
+	    fclose(cnffile);
+	    break;
+	}
+	result = KSUCCESS;
+	for (i = 0; i < n;) {
+	    if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+		result = KFAILURE;
+		break;
+	    }
+	    if (!strchr(linebuf, '\n')) {
+		result = KFAILURE;
+		break;
+	    }
+	    if ((sscanf(linebuf, SCNSCRATCH " " SCNSCRATCH,
+			tr, scratch) != 2))
+		continue;
+	    if (!strcmp(tr, realm))
+		i++;
+	}
+	fclose(cnffile);
+	if (result == KSUCCESS && strlen(scratch) < MAXHOSTNAMELEN) {
+	    strcpy(host, scratch);
+	    return KSUCCESS;
+	}
+	if (i > 0)
+	    /* Found some, but not as many as requested.  */
+	    return KFAILURE;
+    } while (0);
+#ifdef KRB5_DNS_LOOKUP
+    do {
+	krb5int_access k5;
+	krb5_error_code err;
+	krb5_data realmdat;
+	struct srv_dns_entry *srv;
+
+	err = krb5int_accessor(&k5, KRB5INT_ACCESS_VERSION);
+	if (err)
+	    break;
+
+	if (k5.use_dns_kdc(krb5__krb4_context)) {
+	    realmdat.data = realm;
+	    realmdat.length = strlen(realm);
+	    err = k5.make_srv_query_realm(&realmdat, "_kerberos-iv", "_udp",
+					  &srv);
+	    if (err)
+		break;
+
+	    if (srv == 0)
+		break;
+
+	    if (dnscache.srv)
+		k5.free_srv_dns_data(dnscache.srv);
+	    dnscache.srv = srv;
+	    strncpy(dnscache.realm, realm, REALM_SZ);
+	    dnscache.when = now;
+	    goto get_from_dnscache;
+	}
+    } while (0);
+#endif
+    return KFAILURE;
+}
+
+/*
+ * Hostname -> realm name mapping
+ *
+ * Old description from realmofhost.c:
+ *
+ * Given a fully-qualified domain-style primary host name,
+ * return the name of the Kerberos realm for the host.
+ * If the hostname contains no discernable domain, or an error occurs,
+ * return the local realm name, as supplied by get_krbrlm().
+ * If the hostname contains a domain, but no translation is found,
+ * the hostname's domain is converted to upper-case and returned.
+ *
+ * The format of each line of the translation file is:
+ * domain_name kerberos_realm
+ * -or-
+ * host_name kerberos_realm
+ *
+ * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
+ * host names should be in the usual form (e.g. FOO.BAR.BAZ)
+ */
+char * KRB5_CALLCONV
+krb_realmofhost(char *host)
+{
+    /* Argh! */
+    static char	realm[REALM_SZ];
+    char	*lhost;
+    const char	*names[] = {REALMS_V4_PROF_DOMAIN_SECTION, NULL, NULL};
+    char	**values = NULL;
+    profile_t	profile = NULL;
+    long	profErr;
+    char	hostname[MAXHOSTNAMELEN];
+    char	*p;
+    char	*domain;
+    FILE	*trans_file = NULL;
+    int		retval;
+    char	thost[SCRATCHSZ];
+    char	trealm[SCRATCHSZ];
+    struct hostent	*h;
+
+    /* Return local realm if all else fails */
+    krb_get_lrealm(realm, 1);
+
+    /* Forward-resolve in case domain is missing. */
+    h = gethostbyname(host);
+    if (h == NULL)
+	lhost = host;
+    else
+	lhost = h->h_name;
+
+    if (strlen(lhost) >= MAXHOSTNAMELEN)
+	return realm;
+    strcpy(hostname, lhost);
+
+    /* Remove possible trailing dot. */
+    p = strrchr(hostname, '.');
+    if (p != NULL && p[1] == '\0')
+	*p = '\0';
+    domain = strchr(hostname, '.');
+    /*
+     * If the hostname is just below the top, e.g., CYGNUS.COM, then
+     * we special-case it; if someone really wants a realm called COM
+     * they will just have to specify it properly.
+     */
+    if (domain != NULL) {
+	domain++;
+	p = strchr(domain, '.');
+	if (p == NULL)
+	    domain = lhost;
+	if (strlen(domain) < REALM_SZ) {
+	    strncpy(realm, domain, REALM_SZ);
+	    /* Upcase realm name. */
+	    for (p = hostname; *p != '\0'; p++) {
+		if (*p > 0 && islower((unsigned char)*p))
+		    *p = toupper((unsigned char)*p);
+	    }
+	}
+    }
+    /* Downcase hostname. */
+    for (p = hostname; *p != '\0'; p++) {
+	if (*p > 0 && isupper((unsigned char)*p))
+	    *p = tolower((unsigned char)*p);
+    }
+
+    profErr = krb_get_profile(&profile);
+    if (profErr)
+	goto cleanup;
+
+    for (domain = hostname; domain != NULL && *domain != '\0';) {
+	names[1] = domain;
+	values = NULL;
+	profErr = profile_get_values(profile, names, &values);
+	if (!profErr && strlen(values[0]) < REALM_SZ) {
+	    /* Found, return it */
+	    strncpy(realm, values[0], REALM_SZ);
+	    profile_free_list(values);
+	    break;
+	} else {
+	    /* Skip over leading dot. */
+	    if (*domain == '.')
+		domain++;
+	    domain = strchr(domain, '.');
+	}
+	profile_free_list(values);
+    }
+cleanup:
+    if (profile != NULL)
+	profile_abandon(profile);
+
+    trans_file = krb__get_realmsfile();
+    if (trans_file == NULL)
+	return realm;
+    domain = strchr(hostname, '.');
+    for (;;) {
+	retval = fscanf(trans_file, SCNSCRATCH " " SCNSCRATCH,
+			thost, trealm);
+	if (retval == EOF)
+	    break;
+	if (retval != 2 || strlen(trealm) >= REALM_SZ)
+	    continue;		/* Ignore malformed lines. */
+	/* Attempt to match domain. */
+	if (*thost == '.') {
+	    if (domain && !strcasecmp(thost, domain)) {
+		strncpy(realm, trealm, REALM_SZ);
+		continue;	/* Try again for an exact match. */
+	    }
+	} else {
+	    /* Hostname must match exactly. */
+	    if (!strcasecmp(thost, hostname)) {
+		strncpy(realm, trealm, REALM_SZ);
+		break;
+	    }
+	}
+    }
+    fclose(trans_file);
+    return realm;
+}
diff --git a/krb5-1-6/src/lib/krb4/ad_print.c b/krb5-1-6/src/lib/krb4/ad_print.c
new file mode 100644
index 000000000..632957208
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ad_print.c
@@ -0,0 +1,85 @@
+/*
+ * lib/krb4/ad_print.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.  All
+ * Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "des.h"
+#include "krb4int.h"
+#include <stdio.h>
+#include "port-sockets.h"
+
+#ifndef _WIN32
+
+/*
+ * Print some of the contents of the given authenticator structure
+ * (AUTH_DAT defined in "krb.h").  Fields printed are:
+ *
+ * pname, pinst, prealm, netaddr, flags, cksum, timestamp, session
+ */
+
+void
+ad_print(x)
+    AUTH_DAT *x;
+{
+    struct in_addr ina;
+    ina.s_addr = x->address;
+  
+    printf("\n%s %s %s ", x->pname, x->pinst, x->prealm);
+    far_fputs (inet_ntoa(ina), stdout);
+    printf(" flags %u cksum 0x%lX\n\ttkt_tm 0x%lX sess_key",
+            x->k_flags, (long) x->checksum, (long) x->time_sec);
+    printf("[8] =");
+#ifdef NOENCRYPTION
+    placebo_cblock_print(x->session);
+#else /* Do Encryption */
+    des_cblock_print_file(&x->session,stdout);
+#endif /* NOENCRYPTION */
+    /* skip reply for now */
+}
+
+#ifdef NOENCRYPTION
+/*
+ * Print in hex the 8 bytes of the given session key.
+ *
+ * Printed format is:  " 0x { x, x, x, x, x, x, x, x }"
+ */
+
+placebo_cblock_print(x)
+    des_cblock x;
+{
+    unsigned char *y = (unsigned char *) x;
+    register int i = 0;
+
+    printf(" 0x { ");
+
+    while (i++ <8) {
+        printf("%x",*y++);
+        if (i<8) printf(", ");
+    }
+    printf(" }");
+}
+#endif /* NOENCRYPTION */
+
+#endif
diff --git a/krb5-1-6/src/lib/krb4/change_password.c b/krb5-1-6/src/lib/krb4/change_password.c
new file mode 100644
index 000000000..7c3bcd01d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/change_password.c
@@ -0,0 +1,127 @@
+/*
+ * change_password.c
+ *
+ * Copyright 1987, 1988, 2002 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "krb.h"
+#include "krb4int.h"
+#include "kadm.h"
+#include "prot.h"
+
+/*
+ * krb_change_password(): This disgusting function handles changing passwords
+ * in a krb4-only environment.  
+ * -1783126240
+ * THIS IS NOT A NORMAL KRB4 API FUNCTION!  DON'T USE IN PORTABLE CODE!
+ */
+
+int KRB5_CALLCONV
+krb_change_password(char *principal, char *instance, char *realm, 
+		    char *oldPassword, char *newPassword)
+{
+    int		err;
+    des_cblock	key;
+    KRB_UINT32	tempKey;
+    size_t	sendSize;
+    u_char	*sendStream;
+    size_t	receiveSize;
+    u_char	*receiveStream;
+    Kadm_Client	client_parm;
+    u_char	*p;
+
+    err = 0;
+    
+    /* Check inputs: */
+    if (principal == NULL || instance == NULL || realm == NULL ||
+        oldPassword == NULL || newPassword == NULL) {
+        return KFAILURE;
+    }
+    
+    /*
+     * Get tickets to change the old password and shove them in the
+     * client_parm
+     */
+    err = krb_get_pw_in_tkt_creds(principal, instance, realm, 
+				  PWSERV_NAME, KADM_SINST, 1,
+				  oldPassword, &client_parm.creds);
+    if (err != KSUCCESS)
+	goto cleanup;
+
+    /* Now create the key to send to the server */
+    /* Use this and not mit_password_to_key so that we don't prompt */
+    des_string_to_key(newPassword, key);
+
+    /* Create the link to the server */
+    err = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm, &client_parm, 1);
+    if (err != KADM_SUCCESS)
+	goto cleanup;
+
+    /* Connect to the KDC */
+    err = kadm_cli_conn(&client_parm);
+    if (err != KADM_SUCCESS)
+	goto cleanup;
+
+    /* possible problem with vts_long on a non-multiple of four boundary */
+    sendSize = 0;		/* start of our output packet */
+    sendStream = malloc(1);	/* to make it reallocable */
+    if (sendStream == NULL)
+	goto disconnect;
+    sendStream[sendSize++] = CHANGE_PW;
+
+    /* change key to stream */
+    /* This looks backwards but gets inverted on the server side. */
+    p = key + 4;
+    KRB4_GET32BE(tempKey, p);
+    sendSize += vts_long(tempKey, &sendStream, (int)sendSize);
+    p = key;
+    KRB4_GET32BE(tempKey, p);
+    sendSize += vts_long(tempKey, &sendStream, (int)sendSize);
+    tempKey = 0;
+
+    if (newPassword) {
+	sendSize += vts_string(newPassword, &sendStream, (int)sendSize);
+    }
+
+    /* send the data to the kdc */
+    err = kadm_cli_send(&client_parm, sendStream, sendSize,
+			&receiveStream, &receiveSize);
+    free(sendStream);
+    if (receiveSize > 0)
+	/* If there is a string from the kdc, free it - we don't care */
+	free(receiveStream);
+    if (err != KADM_SUCCESS)
+	goto disconnect;
+
+disconnect:	
+    /* Disconnect */
+    kadm_cli_disconn(&client_parm);
+
+cleanup:
+    memset(&client_parm.creds.session, 0, sizeof(client_parm.creds.session));
+    memset(&key, 0, sizeof(key));
+    return err;
+}
diff --git a/krb5-1-6/src/lib/krb4/cr_auth_repl.c b/krb5-1-6/src/lib/krb4/cr_auth_repl.c
new file mode 100644
index 000000000..277d9af8e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/cr_auth_repl.c
@@ -0,0 +1,136 @@
+/*
+ * lib/krb4/cr_auth_repl.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * This routine is called by the Kerberos authentication server
+ * to create a reply to an authentication request.  The routine
+ * takes the user's name, instance, and realm, the client's
+ * timestamp, the number of tickets, the user's key version
+ * number and the ciphertext containing the tickets themselves.
+ * It constructs a packet and returns a pointer to it.
+ *
+ * Notes: The packet returned by this routine is static.  Thus, if you
+ * intend to keep the result beyond the next call to this routine, you
+ * must copy it elsewhere.
+ *
+ * The packet is built in the following format:
+ * 
+ * 			variable
+ * type			or constant	   data
+ * ----			-----------	   ----
+ * 
+ * unsigned char	KRB_PROT_VERSION   protocol version number
+ * 
+ * unsigned char	AUTH_MSG_KDC_REPLY protocol message type
+ * 
+ * [least significant	HOST_BYTE_ORDER	   sender's (server's) byte
+ *  bit of above field]			   order
+ * 
+ * string		pname		   principal's name
+ * 
+ * string		pinst		   principal's instance
+ * 
+ * string		prealm		   principal's realm
+ * 
+ * unsigned long	time_ws		   client's timestamp
+ * 
+ * unsigned char	n		   number of tickets
+ * 
+ * unsigned long	x_date		   expiration date
+ * 
+ * unsigned char	kvno		   master key version
+ * 
+ * short		w_1		   cipher length
+ * 
+ * ---			cipher->dat	   cipher data
+ */
+
+KTEXT
+create_auth_reply(pname, pinst, prealm, time_ws, n, x_date, kvno, cipher)
+    char *pname;                /* Principal's name */
+    char *pinst;                /* Principal's instance */
+    char *prealm;               /* Principal's authentication domain */
+    long time_ws;               /* Workstation time */
+    int n;                      /* Number of tickets */
+    unsigned long x_date;	/* Principal's expiration date */
+    int kvno;                   /* Principal's key version number */
+    KTEXT cipher;               /* Cipher text with tickets and
+				 * session keys */
+{
+    static KTEXT_ST pkt_st;
+    KTEXT pkt = &pkt_st;
+    unsigned char *p;
+    size_t pnamelen, pinstlen, prealmlen;
+
+    /* Create fixed part of packet */
+    p = pkt->dat;
+    /* This is really crusty. */
+    if (n != 0)
+	*p++ = 3;
+    else
+	*p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_KDC_REPLY;	/* always big-endian */
+
+    /* Make sure the response will actually fit into its buffer. */
+    pnamelen = strlen(pname) + 1;
+    pinstlen = strlen(pinst) + 1;
+    prealmlen = strlen(prealm) + 1;
+    if (sizeof(pkt->dat) < (1 + 1 + pnamelen + pinstlen + prealmlen
+			    + 4 + 1 + 4 + 1 + 2 + cipher->length)
+	|| cipher->length > 65535 || cipher->length < 0) {
+	pkt->length = 0;
+        return NULL;
+    }
+    /* Add the basic info */
+    memcpy(p, pname, pnamelen);
+    p += pnamelen;
+    memcpy(p, pinst, pinstlen);
+    p += pinstlen;
+    memcpy(p, prealm, prealmlen);
+    p += prealmlen;
+
+    /* Workstation timestamp */
+    KRB4_PUT32BE(p, time_ws);
+
+    *p++ = n;
+
+    /* Expiration date */
+    KRB4_PUT32BE(p, x_date);
+
+    /* Now send the ciphertext and info to help decode it */
+    *p++ = kvno;
+    KRB4_PUT16BE(p, cipher->length);
+    memcpy(p, cipher->dat, (size_t)cipher->length);
+    p += cipher->length;
+
+    /* And return the packet */
+    pkt->length = p - pkt->dat;
+    return pkt;
+}
diff --git a/krb5-1-6/src/lib/krb4/cr_ciph.c b/krb5-1-6/src/lib/krb4/cr_ciph.c
new file mode 100644
index 000000000..481cb7ee3
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/cr_ciph.c
@@ -0,0 +1,136 @@
+/*
+ * lib/krb4/cr_ciph.c
+ *
+ * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include <string.h>
+
+/*
+ * This routine is used by the authentication server to create
+ * a packet for its client, containing a ticket for the requested
+ * service (given in "tkt"), and some information about the ticket,
+#ifndef NOENCRYPTION
+ * all encrypted in the given key ("key").
+#endif
+ *
+ * Returns KSUCCESS no matter what.
+ *
+ * The length of the cipher is stored in c->length; the format of
+ * c->dat is as follows:
+ *
+ * 			variable
+ * type			or constant	   data
+ * ----			-----------	   ----
+ * 
+ * 
+ * 8 bytes		session		session key for client, service
+ * 
+ * string		service		service name
+ * 
+ * string		instance	service instance
+ * 
+ * string		realm		KDC realm
+ * 
+ * unsigned char	life		ticket lifetime
+ * 
+ * unsigned char	kvno		service key version number
+ * 
+ * unsigned char	tkt->length	length of following ticket
+ * 
+ * data			tkt->dat	ticket for service
+ * 
+ * 4 bytes		kdc_time	KDC's timestamp
+ *
+ * <=7 bytes		null		   null pad to 8 byte multiple
+ *
+ */
+
+int
+create_ciph(c, session, service, instance, realm, life, kvno, tkt,
+	    kdc_time, key)
+    KTEXT           c;		/* Text block to hold ciphertext */
+    C_Block         session;	/* Session key to send to user */
+    char            *service;	/* Service name on ticket */
+    char            *instance;	/* Instance name on ticket */
+    char            *realm;	/* Realm of this KDC */
+    unsigned long   life;	/* Lifetime of the ticket */
+    int             kvno;	/* Key version number for service */
+    KTEXT           tkt;	/* The ticket for the service */
+    unsigned long   kdc_time;	/* KDC time */
+    C_Block         key;	/* Key to encrypt ciphertext with */
+{
+    unsigned char   *ptr;
+    size_t          servicelen, instancelen, realmlen;
+    Key_schedule    key_s;
+
+    ptr = c->dat;
+
+    /* Validate lengths. */
+    servicelen = strlen(service) + 1;
+    instancelen = strlen(instance) + 1;
+    realmlen = strlen(realm) + 1;
+    if (sizeof(c->dat) / 8 < ((8 + servicelen + instancelen + realmlen
+			       + 1 + 1 + 1 + tkt->length
+			       + 4 + 7) / 8)
+	|| tkt->length > 255 || tkt->length < 0) {
+        c->length = 0;
+        return KFAILURE;
+    }
+
+    memcpy(ptr, session, 8);
+    ptr += 8;
+
+    memcpy(ptr, service, servicelen);
+    ptr += servicelen;
+    memcpy(ptr, instance, instancelen);
+    ptr += instancelen;
+    memcpy(ptr, realm, realmlen);
+    ptr += realmlen;
+
+    *ptr++ = life;
+    *ptr++ = kvno;
+    *ptr++ = tkt->length;
+
+    memcpy(ptr, tkt->dat, (size_t)tkt->length);
+    ptr += tkt->length;
+
+    KRB4_PUT32BE(ptr, kdc_time);
+
+    /* guarantee null padded encrypted data to multiple of 8 bytes */
+    memset(ptr, 0, 7);
+
+    c->length = (((ptr - c->dat) + 7) / 8) * 8;
+
+#ifndef NOENCRYPTION
+    key_sched(key, key_s);
+    pcbc_encrypt((C_Block *)c->dat, (C_Block *)c->dat,
+		 (long)c->length, key_s, (C_Block*)key, ENCRYPT);
+    memset(key_s, 0, sizeof(key_s));
+#endif /* NOENCRYPTION */
+
+    return KSUCCESS;
+}
diff --git a/krb5-1-6/src/lib/krb4/cr_death_pkt.c b/krb5-1-6/src/lib/krb4/cr_death_pkt.c
new file mode 100644
index 000000000..63d756277
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/cr_death_pkt.c
@@ -0,0 +1,78 @@
+/*
+ * lib/krb4/cr_death_pkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * This routine creates a packet to type AUTH_MSG_DIE which is sent to
+ * the Kerberos server to make it shut down.  It is used only in the
+ * development environment.
+ *
+ * It takes a string "a_name" which is sent in the packet.  A pointer
+ * to the packet is returned.
+ *
+ * The format of the killer packet is:
+ *
+ * type			variable		data
+ *			or constant
+ * ----			-----------		----
+ *
+ * unsigned char	KRB_PROT_VERSION	protocol version number
+ * 
+ * unsigned char	AUTH_MSG_DIE		message type
+ * 
+ * [least significant	HOST_BYTE_ORDER		byte order of sender
+ *  bit of above field]
+ * 
+ * string		a_name			presumably, name of
+ * 						principal sending killer
+ * 						packet
+ */
+
+#ifdef DEBUG
+KTEXT
+krb_create_death_packet(a_name)
+    char *a_name;
+{
+    static KTEXT_ST pkt_st;
+    KTEXT pkt = &pkt_st;
+    unsigned char *p;
+    size_t namelen;
+
+    p = pkt->dat;
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_DIE;
+    namelen = strlen(a_name) + 1;
+    if (1 + 1 + namelen > sizeof(pkt->dat))
+	return NULL;
+    memcpy(p, a_name, namelen);
+    p += namelen;
+    pkt->length = p - pkt->dat;
+    return pkt;
+}
+#endif /* DEBUG */
diff --git a/krb5-1-6/src/lib/krb4/cr_err_repl.c b/krb5-1-6/src/lib/krb4/cr_err_repl.c
new file mode 100644
index 000000000..5dad8c1b1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/cr_err_repl.c
@@ -0,0 +1,110 @@
+/*
+ * lib/krb4/cr_err_repl.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * This routine is used by the Kerberos authentication server to
+ * create an error reply packet to send back to its client.
+ *
+ * It takes a pointer to the packet to be built, the name, instance,
+ * and realm of the principal, the client's timestamp, an error code
+ * and an error string as arguments.  Its return value is undefined.
+ *
+ * The packet is built in the following format:
+ * 
+ * type			variable	   data
+ *			or constant
+ * ----			-----------	   ----
+ *
+ * unsigned char	req_ack_vno	   protocol version number
+ * 
+ * unsigned char	AUTH_MSG_ERR_REPLY protocol message type
+ * 
+ * [least significant	HOST_BYTE_ORDER	   sender's (server's) byte
+ * bit of above field]			   order
+ * 
+ * string		pname		   principal's name
+ * 
+ * string		pinst		   principal's instance
+ * 
+ * string		prealm		   principal's realm
+ * 
+ * unsigned long	time_ws		   client's timestamp
+ * 
+ * unsigned long	e		   error code
+ * 
+ * string		e_string	   error text
+ */
+
+void
+cr_err_reply(pkt,pname,pinst,prealm,time_ws,e,e_string)
+    KTEXT pkt;
+    char *pname;		/* Principal's name */
+    char *pinst;		/* Principal's instance */
+    char *prealm;		/* Principal's authentication domain */
+    u_long time_ws;		/* Workstation time */
+    u_long e;			/* Error code */
+    char *e_string;		/* Text of error */
+{
+    unsigned char *p;
+    size_t pnamelen, pinstlen, prealmlen, e_stringlen;
+
+    p = pkt->dat;
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_ERR_REPLY;
+
+    /* Make sure the reply will fit into the buffer. */
+    pnamelen = strlen(pname) + 1;
+    pinstlen = strlen(pinst) + 1;
+    prealmlen = strlen(prealm) + 1;
+    e_stringlen = strlen(e_string) + 1;
+    if(sizeof(pkt->dat) < (1 + 1 + pnamelen + pinstlen + prealmlen
+			   + 4 + 4 + e_stringlen)) {
+        pkt->length = 0;
+	return;
+    }
+    /* Add the basic info */
+    memcpy(p, pname, pnamelen);
+    p += pnamelen;
+    memcpy(p, pinst, pinstlen);
+    p += pinstlen;
+    memcpy(p, prealm, prealmlen);
+    p += prealmlen;
+    /* ws timestamp */
+    KRB4_PUT32BE(p, time_ws);
+    /* err code */
+    KRB4_PUT32BE(p, e);
+    /* err text */
+    memcpy(p, e_string, e_stringlen);
+    p += e_stringlen;
+
+    /* And return */
+    pkt->length = p - pkt->dat;
+    return;
+}
diff --git a/krb5-1-6/src/lib/krb4/cr_tkt.c b/krb5-1-6/src/lib/krb4/cr_tkt.c
new file mode 100644
index 000000000..2c01257d8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/cr_tkt.c
@@ -0,0 +1,254 @@
+/*
+ * lib/krb4/cr_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <krb5.h>
+#include "des.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+#include "port-sockets.h"
+
+static int
+krb_cr_tkt_int (KTEXT tkt, unsigned int flags_in, char *pname, 
+		char *pinstance, char *prealm, long paddress,
+		char *session, int life, long time_sec, 
+		char *sname, char *sinstance);
+
+/*
+ * Create ticket takes as arguments information that should be in a
+ * ticket, and the KTEXT object in which the ticket should be
+ * constructed.  It then constructs a ticket and returns, leaving the
+ * newly created ticket in tkt.
+#ifndef NOENCRYPTION
+ * The data in tkt->dat is encrypted in the server's key.
+#endif
+ * The length of the ticket is a multiple of
+ * eight bytes and is in tkt->length.
+ *
+ * If the ticket is too long, the ticket will contain nulls.
+ * The return value of the routine is undefined.
+ *
+ * The corresponding routine to extract information from a ticket it
+ * decomp_ticket.  When changes are made to this routine, the
+ * corresponding changes should also be made to that file.
+ *
+ * The packet is built in the following format:
+ * 
+ * 			variable
+ * type			or constant	   data
+ * ----			-----------	   ----
+ *
+ * tkt->length		length of ticket (multiple of 8 bytes)
+ * 
+#ifdef NOENCRYPTION
+ * tkt->dat:
+#else
+ * tkt->dat:		(encrypted in server's key)
+#endif
+ * 
+ * unsigned char	flags		   namely, HOST_BYTE_ORDER
+ * 
+ * string		pname		   client's name
+ * 
+ * string		pinstance	   client's instance
+ * 
+ * string		prealm		   client's realm
+ * 
+ * 4 bytes		paddress	   client's address
+ * 
+ * 8 bytes		session		   session key
+ * 
+ * 1 byte		life		   ticket lifetime
+ * 
+ * 4 bytes		time_sec	   KDC timestamp
+ * 
+ * string		sname		   service's name
+ * 
+ * string		sinstance	   service's instance
+ * 
+ * <=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)
+    KTEXT   tkt;                /* Gets filled in by the ticket */
+    unsigned int 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 */
+    int     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 */
+{
+    int kerr;
+    Key_schedule key_s;
+
+    kerr = krb_cr_tkt_int(tkt, flags, pname, pinstance, prealm, paddress,
+			  session, life, time_sec, sname, sinstance);
+    if (kerr)
+	return kerr;
+
+    /* 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);
+    memset(key_s, 0, sizeof(key_s));
+    return 0;
+}
+
+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 int 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 */
+    int     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 */
+{
+    int kerr;
+    krb5_data in;
+    krb5_enc_data out;
+    krb5_error_code ret;
+    size_t enclen;
+
+    kerr = krb_cr_tkt_int(tkt, flags, pname, pinstance, prealm,
+			  paddress, session, life, time_sec,
+			  sname, sinstance);
+    if (kerr)
+	return kerr;
+
+    /* Encrypt the ticket in the services key */
+    in.length = tkt->length;
+    in.data = (char *)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);
+    }
+    return 0;
+}
+
+static int
+krb_cr_tkt_int(tkt, flags_in, pname, pinstance, prealm, paddress,
+	       session, life, time_sec, sname, sinstance)
+    KTEXT   tkt;                /* Gets filled in by the ticket */
+    unsigned int flags_in;      /* 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 */
+    int     life;               /* Lifetime of the ticket */
+    long    time_sec;           /* Issue time and date */
+    char    *sname;             /* Service Name */
+    char    *sinstance;         /* Instance Name */
+{
+    register unsigned char *data; /* running index into ticket */
+    size_t pnamelen, pinstlen, prealmlen, snamelen, sinstlen;
+    struct in_addr paddr;
+
+    /* Be really paranoid. */
+    if (sizeof(paddr.s_addr) != 4)
+	return KFAILURE;
+
+    tkt->length = 0;            /* Clear previous data  */
+
+    /* Check length of ticket */
+    pnamelen = strlen(pname) + 1;
+    pinstlen = strlen(pinstance) + 1;
+    prealmlen = strlen(prealm) + 1;
+    snamelen = strlen(sname) + 1;
+    sinstlen = strlen(sinstance) + 1;
+    if (sizeof(tkt->dat) / 8 < ((1 + pnamelen + pinstlen + prealmlen
+				 + 4 /* address */
+				 + 8 /* session */
+				 + 1 /* life */
+				 + 4 /* issue time */
+				 + snamelen + sinstlen
+				 + 7) / 8) /* roundoff */
+	|| life > 255 || life < 0) {
+        memset(tkt->dat, 0, sizeof(tkt->dat));
+        return KFAILURE /* XXX */;
+    }
+
+    data = tkt->dat;
+    *data++ = flags_in;
+    memcpy(data, pname, pnamelen);
+    data += pnamelen;
+    memcpy(data, pinstance, pinstlen);
+    data += pinstlen;
+    memcpy(data, prealm, prealmlen);
+    data += prealmlen;
+
+    paddr.s_addr = paddress;
+    memcpy(data, &paddr.s_addr, sizeof(paddr.s_addr));
+    data += sizeof(paddr.s_addr);
+
+    memcpy(data, session, 8);
+    data += 8;
+    *data++ = life;
+    /* issue time */
+    KRB4_PUT32BE(data, time_sec);
+
+    memcpy(data, sname, snamelen);
+    data += snamelen;
+    memcpy(data, sinstance, sinstlen);
+    data += sinstlen;
+
+    /* guarantee null padded ticket to multiple of 8 bytes */
+    memset(data, 0, 7);
+    tkt->length = ((data - tkt->dat + 7) / 8) * 8;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb4/debug.c b/krb5-1-6/src/lib/krb4/debug.c
new file mode 100644
index 000000000..bd2ec904a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/debug.c
@@ -0,0 +1,15 @@
+/*
+ * debug.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+
+/* Declare global debugging variables. */
+
+int krb_ap_req_debug = 0;
+int krb_debug = 0;
diff --git a/krb5-1-6/src/lib/krb4/decomp_tkt.c b/krb5-1-6/src/lib/krb4/decomp_tkt.c
new file mode 100644
index 000000000..7d85991a0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/decomp_tkt.c
@@ -0,0 +1,295 @@
+/*
+ * lib/krb4/decomp_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000, 2001 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "des.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+#include <krb5.h>
+#include "krb54proto.h"
+#include "port-sockets.h"
+
+#ifdef KRB_CRYPT_DEBUG
+extern int krb_debug;
+#endif
+
+static int dcmp_tkt_int (KTEXT tkt, unsigned char *flags, 
+				   char *pname, char *pinstance, char *prealm,
+				   unsigned KRB4_32 *paddress, C_Block session,
+				   int *life, unsigned KRB4_32 *time_sec, 
+				   char *sname, char *sinstance, C_Block key, 
+				   Key_schedule key_s, krb5_keyblock *k5key);
+/*
+ * This routine takes a ticket and pointers to the variables that
+ * should be filled in based on the information in the ticket.  It
+#ifndef NOENCRYPTION
+ * decrypts the ticket using the given key, and 
+#endif
+ * fills in values for its arguments.
+ *
+ * Note: if the client realm field in the ticket is the null string,
+ * then the "prealm" variable is filled in with the local realm (as
+ * defined by KRB_REALM).
+ *
+ * If the ticket byte order is different than the host's byte order
+ * (as indicated by the byte order bit of the "flags" field), then
+ * the KDC timestamp "time_sec" is byte-swapped.  The other fields
+ * potentially affected by byte order, "paddress" and "session" are
+ * not byte-swapped.
+ *
+ * The routine returns KFAILURE if any of the "pname", "pinstance",
+ * or "prealm" fields is too big, otherwise it returns KSUCCESS.
+ *
+ * The corresponding routine to generate tickets is create_ticket.
+ * When changes are made to this routine, the corresponding changes
+ * should also be made to that file.
+ *
+ * See create_ticket.c for the format of the ticket packet.
+ */
+
+int KRB5_CALLCONV		/* XXX should this be exported on win32? */
+decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
+              life, time_sec, sname, sinstance, key, key_s)
+    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 */
+{
+    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 */
+{
+    int tkt_le;			/* little-endian ticket? */
+    unsigned char *ptr = tkt->dat;
+    int kret, len;
+    struct in_addr paddr;
+
+    /* Be really paranoid. */
+    if (sizeof(paddr.s_addr) != 4)
+	return KFAILURE;
+
+#ifndef NOENCRYPTION
+    /* Do the decryption */
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_debug) {
+	FILE *fp;
+	char *keybuf[BUFSIZ];	/* Avoid secret stuff in stdio buffers */
+
+	fp = fopen("/kerberos/tkt.des", "wb");
+	setbuf(fp, keybuf);
+	fwrite(tkt->dat, 1, tkt->length, fp);
+	fclose(fp);
+	memset(keybuf, 0, sizeof(keybuf));	/* Clear the buffer */
+    }
+#endif
+    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 = (char *)tkt->dat;
+	out.length = tkt->length;
+	out.data = malloc((size_t)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) {
+	FILE *fp;
+	char *keybuf[BUFSIZ];	/* Avoid secret stuff in stdio buffers */
+
+	fp = fopen("/kerberos/tkt.clear", "wb");
+	setbuf(fp, keybuf);
+	fwrite(tkt->dat, 1, tkt->length, fp);
+	fclose(fp);
+	memset(keybuf, 0, sizeof(keybuf));	/* Clear the buffer */
+    }
+#endif
+
+#define TKT_REMAIN (tkt->length - (ptr - tkt->dat))
+    kret = KFAILURE;
+    if (TKT_REMAIN < 1)
+	goto cleanup;
+    *flags = *ptr++;
+    tkt_le = (*flags >> K_FLAG_ORDER) & 1;
+
+    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
+    if (len <= 0 || len > ANAME_SZ)
+	goto cleanup;
+    memcpy(pname, ptr, (size_t)len);
+    ptr += len;
+
+    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
+    if (len <= 0 || len > INST_SZ)
+	goto cleanup;
+    memcpy(pinstance, ptr, (size_t)len);
+    ptr += len;
+
+    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
+    if (len <= 0 || len > REALM_SZ)
+	goto cleanup;
+    memcpy(prealm, ptr, (size_t)len);
+    ptr += len;
+
+    /*
+     * This hack may be needed for some really krb4 servers, such as
+     * AFS kaserver (?), that fail to fill in the realm of a ticket
+     * under some circumstances.
+     */
+    if (*prealm == '\0')
+	krb_get_lrealm(prealm, 1);
+
+    /*
+     * Ensure there's enough remaining in the ticket to get the
+     * fixed-size stuff.
+     */
+    if (TKT_REMAIN < 4 + 8 + 1 + 4)
+	goto cleanup;
+
+    memcpy(&paddr.s_addr, ptr, sizeof(paddr.s_addr));
+    ptr += sizeof(paddr.s_addr);
+    *paddress = paddr.s_addr;
+
+    memcpy(session, ptr, 8); /* session key */
+    memset(ptr, 0, 8);
+    ptr += 8;
+#ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */
+    if (tkt_swap_bytes)
+        swap_C_Block(session);
+#endif
+
+    *life = *ptr++;
+
+    KRB4_GET32(*time_sec, ptr, tkt_le);
+
+    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
+    if (len <= 0 || len > SNAME_SZ)
+	goto cleanup;
+    memcpy(sname, ptr, (size_t)len);
+    ptr += len;
+
+    len = krb4int_strnlen((char *)ptr, TKT_REMAIN) + 1;
+    if (len <= 0 || len > INST_SZ)
+	goto cleanup;
+    memcpy(sinstance, ptr, (size_t)len);
+    ptr += len;
+    kret = KSUCCESS;
+
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_debug) {
+	krb_log("service=%s.%s len(sname)=%d, len(sinstance)=%d",
+		sname, sinstance, strlen(sname), strlen(sinstance));
+	krb_log("ptr - tkt->dat=%d",(char *)ptr - (char *)tkt->dat);
+    }
+#endif
+
+cleanup:
+    if (kret != KSUCCESS) {
+	memset(session, 0, sizeof(session));
+	memset(tkt->dat, 0, (size_t)tkt->length);
+	return kret;
+    }
+    return KSUCCESS;
+}
diff --git a/krb5-1-6/src/lib/krb4/dest_tkt.c b/krb5-1-6/src/lib/krb4/dest_tkt.c
new file mode 100644
index 000000000..4f7c1e377
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/dest_tkt.c
@@ -0,0 +1,160 @@
+/*
+ * lib/krb4/dest_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000, 2001 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "k5-util.h"
+#define do_seteuid krb5_seteuid
+
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#ifndef O_SYNC
+#define O_SYNC 0
+#endif
+
+/*
+ * dest_tkt() is used to destroy the ticket store upon logout.
+ * If the ticket file does not exist, dest_tkt() returns RET_TKFIL.
+ * Otherwise the function returns RET_OK on success, KFAILURE on
+ * failure.
+ *
+ * The ticket file (TKT_FILE) is defined in "krb.h".
+ */
+
+int KRB5_CALLCONV
+dest_tkt()
+{
+    const char *file = TKT_FILE;
+    int i,fd;
+    int ret;
+    struct stat statpre, statpost;
+    char buf[BUFSIZ];
+    uid_t me, metoo;
+#ifdef TKT_SHMEM
+    char shmidname[MAXPATHLEN];
+    size_t shmidlen;
+#endif /* TKT_SHMEM */
+
+    /* If ticket cache selector is null, use default cache.  */
+    if (file == 0)
+	file = tkt_string();
+
+    errno = 0;
+    ret = KSUCCESS;
+    me = getuid();
+    metoo = geteuid();
+
+    if (lstat(file, &statpre) < 0)
+	return (errno == ENOENT) ? RET_TKFIL : KFAILURE;
+    /*
+     * This does not guard against certain cases that are vulnerable
+     * to race conditions, such as world-writable or group-writable
+     * directories that are not stickybitted, or untrusted path
+     * components.  In all other cases, the following checks should be
+     * sufficient.  It is assumed that the aforementioned certain
+     * vulnerable cases are unlikely to arise on a well-administered
+     * system where the user is not deliberately being stupid.
+     */
+    if (!(statpre.st_mode & S_IFREG) || me != statpre.st_uid
+	|| statpre.st_nlink != 1)
+	return KFAILURE;
+    /*
+     * Yes, we do uid twiddling here.  It's not optimal, but some
+     * applications may expect that the ruid is what should really own
+     * the ticket file, e.g. setuid applications.
+     */
+    if (me != metoo && do_seteuid(me) < 0)
+	return KFAILURE;
+    if ((fd = open(file, O_RDWR|O_SYNC, 0)) < 0) {
+	ret = (errno == ENOENT) ? RET_TKFIL : KFAILURE;
+	goto out;
+    }
+    /*
+     * Do some additional paranoid things.  The worst-case situation
+     * is that a user may be fooled into opening a non-regular file
+     * briefly if the file is in a directory with improper
+     * permissions.
+     */
+    if (fstat(fd, &statpost) < 0) {
+	(void)close(fd);
+	ret = KFAILURE;
+	goto out;
+    }
+    if (statpre.st_dev != statpost.st_dev
+	|| statpre.st_ino != statpost.st_ino) {
+	(void)close(fd);
+	errno = 0;
+	ret = KFAILURE;
+	goto out;
+    }
+
+    memset(buf, 0, BUFSIZ);
+    for (i = 0; i < statpost.st_size; i += BUFSIZ)
+	if (write(fd, buf, BUFSIZ) != BUFSIZ) {
+#ifndef NO_FSYNC
+	    (void) fsync(fd);
+#endif
+	    (void) close(fd);
+	    goto out;
+	}
+
+#ifndef NO_FSYNC
+    (void) fsync(fd);
+#endif
+    (void) close(fd);
+
+    (void) unlink(file);
+
+out:
+    if (me != metoo && do_seteuid(metoo) < 0)
+	return KFAILURE;
+    if (ret != KSUCCESS)
+	return ret;
+
+#ifdef TKT_SHMEM
+    /* 
+     * handle the shared memory case 
+     */
+    shmidlen = strlen(file) + sizeof(".shm");
+    if (shmidlen > sizeof(shmidname))
+	return RET_TKFIL;
+    (void)strcpy(shmidname, file);
+    (void)strcat(shmidname, ".shm");
+    return krb_shm_dest(shmidname);
+#else  /* !TKT_SHMEM */
+    return KSUCCESS;
+#endif /* !TKT_SHMEM */
+}
diff --git a/krb5-1-6/src/lib/krb4/err_txt.c b/krb5-1-6/src/lib/krb4/err_txt.c
new file mode 100644
index 000000000..0c4a01158
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/err_txt.c
@@ -0,0 +1,87 @@
+/*
+ * lib/krb4/err_txt.c
+ *
+ * Copyright 1988, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "krb4int.h"
+
+/*
+ * This is gross.  We want krb_err_txt to match the contents of the
+ * com_err error table, but the text is static in krb_err.c.  We can't
+ * alias it by making a pointer to it, either, so we have to suck in
+ * another copy of it that is named differently.   */
+#if TARGET_OS_MAC && !defined(DEPEND)
+#undef initialize_krb_error_table
+#define initialize_krb_error_table	krb4int_init_krb_err_tbl
+void krb4int_init_krb_err_tbl(void);
+#include "krb_err.c"
+#undef initialize_krb_error_table
+
+/*
+ * Depends on the name of the static table generated by compile_et,
+ * but since this is only on Darwin, where we will always use a
+ * certain compile_et, it should be ok.
+ */
+const char * const * const krb_err_txt = text;
+#else
+#ifndef DEPEND
+/* Don't put this in auto-generated dependencies. */
+#include "krb_err_txt.c"
+#endif
+#endif
+
+void initialize_krb_error_table(void);
+
+static int inited = 0;
+
+void
+krb4int_et_init(void)
+{
+    if (inited)
+	return;
+    add_error_table(&et_krb_error_table);
+    inited = 1;\
+}
+
+void
+krb4int_et_fini(void)
+{
+    if (inited)
+	remove_error_table(&et_krb_error_table);
+}
+
+const char * KRB5_CALLCONV
+krb_get_err_text(code)
+    int code;
+{
+    krb4int_et_init();
+    /*
+     * Shift krb error code into com_err number space.
+     */
+    if (code >= 0 && code < MAX_KRB_ERRORS)
+	return error_message(ERROR_TABLE_BASE_krb + code);
+    else
+	return "Invalid Kerberos error code";
+}
diff --git a/krb5-1-6/src/lib/krb4/et_errtxt.awk b/krb5-1-6/src/lib/krb4/et_errtxt.awk
new file mode 100755
index 000000000..888dad695
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/et_errtxt.awk
@@ -0,0 +1,71 @@
+/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
+	print "/*" > outfile
+	print " * " outfile ":" > outfile
+	print " * This file is automatically generated; please do not edit it." > outfile
+	print " */" > outfile
+	print "#if TARGET_OS_MAC" > outfile
+	print "const char * const * const krb_err_txt" > outfile
+	print "#else" > outfile
+	print "const char * const krb_err_txt[]" > outfile
+	print "#endif" > outfile
+	print "\t= {" > outfile
+	table_item_count = 0
+}
+
+(continuation == 1) && ($0 ~ /\\[ \t]*$/) {
+	text=substr($0,1,length($0)-1);
+#	printf "\t\t\"%s\"\n", text > outfile
+	cont_buf=cont_buf text;
+}
+
+(continuation == 1) && ($0 ~ /"[ \t]*$/) {
+# "
+#	printf "\t\t\"%s,\n", $0 > outfile
+	printf "\t%s,\n", cont_buf $0 > outfile
+	continuation = 0;
+}
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/ {
+	table_item_count++
+	skipone=1
+	next
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/ {
+	text=""
+	for (i=3; i<=NF; i++) { 
+	    text = text FS $i
+	}
+	text=substr(text,2,length(text)-1);
+	printf "\t%s,\n", text > outfile
+	table_item_count++
+}
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*\\[ \t]*$/ {
+	text=""
+	for (i=3; i<=NF; i++) { 
+	    text = text FS $i
+	}
+	text=substr(text,2,length(text)-2);
+#	printf "\t%s\"\n", text > outfile
+	cont_buf=text
+	continuation++;
+}
+
+/^[ \t]*".*\\[ \t]*$/ {
+	if (skipone) {
+	    text=substr($0,1,length($0)-1);
+#	    printf "\t%s\"\n", text > outfile
+	    cont_buf=text
+	    continuation++;
+	}
+	skipone=0
+}
+
+{ 
+	if (skipone) {
+	    printf "\t%s,\n", $0 > outfile
+	}
+	skipone=0
+}
+END {
+	print "};" > outfile
+}
diff --git a/krb5-1-6/src/lib/krb4/fgetst.c b/krb5-1-6/src/lib/krb4/fgetst.c
new file mode 100644
index 000000000..e652ac93a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/fgetst.c
@@ -0,0 +1,38 @@
+/*
+ * fgetst.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology. 
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>. 
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include "krb.h"
+#include "krb4int.h"
+
+/*
+ * fgetst takes a file descriptor, a character pointer, and a count.
+ * It reads from the file it has either read "count" characters, or
+ * until it reads a null byte.  When finished, what has been read exists
+ * in "s". If "count" characters were actually read, the last is changed
+ * to a null, so the returned string is always null-terminated.  fgetst
+ * returns the number of characters read, including the null terminator. 
+ */
+
+int
+fgetst(f, s, n)
+    FILE   *f;
+    register char *s;
+    int     n;
+{
+    register int count = n;
+    int     ch;		/* NOT char; otherwise you don't see EOF */
+
+    while ((ch = getc(f)) != EOF && ch && --count) {
+	*s++ = ch;
+    }
+    *s = '\0';
+    return (n - count);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_ad_tkt.c b/krb5-1-6/src/lib/krb4/g_ad_tkt.c
new file mode 100644
index 000000000..353fdcee5
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_ad_tkt.c
@@ -0,0 +1,383 @@
+/*
+ * lib/krb4/g_ad_tkt.c
+ *
+ * Copyright 1986, 1987, 1988, 2000, 2001 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "des.h"
+#include "krb4int.h"
+#include "prot.h"
+#include <string.h>
+
+#include <stdio.h>
+
+extern int krb_debug;
+extern int swap_bytes;
+
+/*
+ * get_ad_tkt obtains a new service ticket from Kerberos, using
+ * the ticket-granting ticket which must be in the ticket file.
+ * It is typically called by krb_mk_req() when the client side
+ * of an application is creating authentication information to be
+ * sent to the server side.
+ *
+ * get_ad_tkt takes four arguments: three pointers to strings which
+ * contain the name, instance, and realm of the service for which the
+ * ticket is to be obtained; and an integer indicating the desired
+ * lifetime of the ticket.
+ *
+ * It returns an error status if the ticket couldn't be obtained,
+ * or AD_OK if all went well.  The ticket is stored in the ticket
+ * cache.
+ *
+ * The request sent to the Kerberos ticket-granting service looks
+ * like this:
+ *
+ * pkt->dat
+ *
+ * TEXT			original contents of	authenticator+ticket
+ *			pkt->dat		built in krb_mk_req call
+ * 
+ * 4 bytes		time_ws			always 0 (?)  FIXME!
+ * char			lifetime		lifetime argument passed
+ * string		service			service name argument
+ * string		sinstance		service instance arg.
+ *
+ * See "prot.h" for the reply packet layout and definitions of the
+ * extraction macros like pkt_version(), pkt_msg_type(), etc.
+ */
+
+/*
+ * g_ad_tk_parse()
+ *
+ * Parse the returned packet from the KDC.
+ *
+ * Note that the caller is responsible for clearing the returned
+ * session key if there is an error; that makes the error handling
+ * code a little less hairy.
+ */
+static int
+g_ad_tkt_parse(KTEXT rpkt, C_Block tgtses, C_Block ses,
+	       char *s_name, char *s_instance, char *rlm,
+	       char *service, char *sinstance, char *realm,
+	       int *lifetime, int *kvno, KTEXT tkt,
+	       unsigned KRB4_32 *kdc_time,
+	       KRB4_32 *t_local)
+{
+    unsigned char *ptr;
+    unsigned int t_switch;
+    int msg_byte_order;
+    unsigned long rep_err_code;
+    unsigned long cip_len;
+    KTEXT_ST cip_st;
+    KTEXT cip = &cip_st;	/* Returned Ciphertext */
+    Key_schedule key_s;
+    int len, i;
+    KRB4_32 t_diff;		/* Difference between timestamps */
+
+    ptr = rpkt->dat;
+#define RPKT_REMAIN (rpkt->length - (ptr - rpkt->dat))
+    if (RPKT_REMAIN < 1 + 1)
+	return INTK_PROT;
+    /* check packet version of the returned packet */
+    if (*ptr++ != KRB_PROT_VERSION)
+	return INTK_PROT;
+
+    /* This used to be
+         switch (pkt_msg_type(rpkt) & ~1) {
+       but SCO 3.2v4 cc compiled that incorrectly.  */
+    t_switch = *ptr++;
+    /* Check byte order (little-endian == 1) */
+    msg_byte_order = t_switch & 1;
+    t_switch &= ~1;
+    /*
+     * Skip over some stuff (3 strings and various integers -- see
+     * cr_auth_repl.c for details).  Maybe we should actually verify
+     * these?
+     */
+    for (i = 0; i < 3; i++) {
+	len = krb4int_strnlen((char *)ptr, RPKT_REMAIN) + 1;
+	if (len <= 0)
+	    return INTK_PROT;
+	ptr += len;
+    }
+    switch (t_switch) {
+    case AUTH_MSG_KDC_REPLY:
+	if (RPKT_REMAIN < 4 + 1 + 4 + 1)
+	    return INTK_PROT;
+	ptr += 4 + 1 + 4 + 1;
+	break;
+    case AUTH_MSG_ERR_REPLY:
+	if (RPKT_REMAIN < 8)
+	    return INTK_PROT;
+	ptr += 4;
+	KRB4_GET32(rep_err_code, ptr, msg_byte_order);
+	return rep_err_code;
+
+    default:
+	return INTK_PROT;
+    }
+
+    /* Extract the ciphertext */
+    if (RPKT_REMAIN < 2)
+	return INTK_PROT;
+    KRB4_GET16(cip_len, ptr, msg_byte_order);
+    if (RPKT_REMAIN < cip_len)
+	return INTK_PROT;
+    /*
+     * RPKT_REMAIN will always be non-negative and at most the maximum
+     * possible value of cip->length, so this assignment is safe.
+     */
+    cip->length = cip_len;
+    memcpy(cip->dat, ptr, (size_t)cip->length);
+    ptr += cip->length;
+
+#ifndef NOENCRYPTION
+    /* Attempt to decrypt it */
+
+    key_sched(tgtses, key_s);
+    DEB (("About to do decryption ..."));
+    pcbc_encrypt((C_Block *)cip->dat, (C_Block *)cip->dat,
+                 (long)cip->length, key_s, (C_Block *)tgtses, 0);
+#endif /* !NOENCRYPTION */
+    /*
+     * Stomp on key schedule.  Caller should stomp on tgtses.
+     */
+    memset(key_s, 0, sizeof(key_s));
+
+    ptr = cip->dat;
+#define CIP_REMAIN (cip->length - (ptr - cip->dat))
+    if (CIP_REMAIN < 8)
+	return RD_AP_MODIFIED;
+    memcpy(ses, ptr, 8);
+    /*
+     * Stomp on decrypted session key immediately after copying it.
+     */
+    memset(ptr, 0, 8);
+    ptr += 8;
+
+    len = krb4int_strnlen((char *)ptr, CIP_REMAIN) + 1;
+    if (len <= 0 || len > SNAME_SZ)
+	return RD_AP_MODIFIED;
+    memcpy(s_name, ptr, (size_t)len);
+    ptr += len;
+
+    len = krb4int_strnlen((char *)ptr, CIP_REMAIN) + 1;
+    if (len <= 0 || len > INST_SZ)
+	return RD_AP_MODIFIED;
+    memcpy(s_instance, ptr, (size_t)len);
+    ptr += len;
+
+    len = krb4int_strnlen((char *)ptr, CIP_REMAIN) + 1;
+    if (len <= 0 || len > REALM_SZ)
+	return RD_AP_MODIFIED;
+    memcpy(rlm, ptr, (size_t)len);
+    ptr += len;
+
+    if (strcmp(s_name, service) || strcmp(s_instance, sinstance)
+	|| strcmp(rlm, realm))	/* not what we asked for */
+	return INTK_ERR;	/* we need a better code here XXX */
+
+    if (CIP_REMAIN < 1 + 1 + 1)
+	return RD_AP_MODIFIED;
+    *lifetime = *ptr++;
+    *kvno = *ptr++;
+    tkt->length = *ptr++;
+
+    if (CIP_REMAIN < tkt->length)
+	return RD_AP_MODIFIED;
+    memcpy(tkt->dat, ptr, (size_t)tkt->length);
+    ptr += tkt->length;
+
+    /* Time (coarse) */
+    if (CIP_REMAIN < 4)
+	return RD_AP_MODIFIED;
+    KRB4_GET32(*kdc_time, ptr, msg_byte_order);
+
+    /* check KDC time stamp */
+    *t_local = TIME_GMT_UNIXSEC;
+    t_diff = *t_local - *kdc_time;
+    if (t_diff < 0)
+	t_diff = -t_diff;	/* Absolute value of difference */
+    if (t_diff > CLOCK_SKEW)
+	return RD_AP_TIME;	/* XXX should probably be better code */
+
+    return 0;
+}
+
+int KRB5_CALLCONV
+get_ad_tkt(service, sinstance, realm, lifetime)
+    char    *service;
+    char    *sinstance;
+    char    *realm;
+    int     lifetime;
+{
+    KTEXT_ST pkt_st;
+    KTEXT pkt = & pkt_st;	/* Packet to KDC */
+    KTEXT_ST rpkt_st;
+    KTEXT rpkt = &rpkt_st;	/* Returned packet */
+    KTEXT_ST tkt_st;
+    KTEXT tkt = &tkt_st;	/* Current ticket */
+    C_Block ses;                /* Session key for tkt */
+    CREDENTIALS cr;
+    int kvno;			/* Kvno for session key */
+    int kerror;
+    char lrealm[REALM_SZ];
+    KRB4_32 time_ws = 0;
+    char s_name[SNAME_SZ];
+    char s_instance[INST_SZ];
+    char rlm[REALM_SZ];
+    unsigned char *ptr;
+    KRB4_32 t_local;
+    struct sockaddr_in laddr;
+    socklen_t addrlen;
+    unsigned KRB4_32 kdc_time;   /* KDC time */
+    size_t snamelen, sinstlen;
+
+    kerror = krb_get_tf_realm(TKT_FILE, lrealm);
+#if USE_LOGIN_LIBRARY
+    if (kerror == GC_NOTKT) {
+        /* No tickets... call krb_get_cred (KLL will prompt) and try again. */
+        if ((kerror = krb_get_cred ("krbtgt", realm, realm, &cr)) == KSUCCESS) {
+            /* Now get the realm again. */
+            kerror = krb_get_tf_realm (TKT_FILE, lrealm);
+        }
+    }
+#endif
+    if (kerror != KSUCCESS)
+	return kerror;
+
+    /* Create skeleton of packet to be sent */
+    pkt->length = 0;
+
+    /*
+     * Look for the session key (and other stuff we don't need)
+     * in the ticket file for krbtgt.realm@lrealm where "realm" 
+     * is the service's realm (passed in "realm" argument) and 
+     * "lrealm" is the realm of our initial ticket (the local realm).
+     * If that fails, and the server's realm and the local realm are
+     * the same thing, give up - no TGT available for local realm.
+     *
+     * If the server realm and local realm are different, though,
+     * try getting a ticket-granting ticket for the server's realm,
+     * i.e. a ticket for "krbtgt.alienrealm@lrealm", by calling get_ad_tkt().
+     * If that succeeds, the ticket will be in ticket cache, get it
+     * into the "cr" structure by calling krb_get_cred().
+     */
+    kerror = krb_get_cred("krbtgt", realm, lrealm, &cr);
+    if (kerror != KSUCCESS) {
+	/*
+	 * If realm == lrealm, we have no hope, so let's not even try.
+	 */
+	if (strncmp(realm, lrealm, sizeof(lrealm)) == 0)
+	    return AD_NOTGT;
+	else {
+	    kerror = get_ad_tkt("krbtgt", realm, lrealm, lifetime);
+	    if (kerror != KSUCCESS) {
+		if (kerror == KDC_PR_UNKNOWN)	/* no cross-realm ticket */
+		    return AD_NOTGT;		/* So call it no ticket */
+		return kerror;
+	    }
+	    kerror = krb_get_cred("krbtgt",realm,lrealm,&cr);
+	    if (kerror != KSUCCESS)
+		return kerror;
+	}
+    }
+
+    /*
+     * Make up a request packet to the "krbtgt.realm@lrealm".
+     * Start by calling krb_mk_req() which puts ticket+authenticator
+     * into "pkt".  Then tack other stuff on the end.
+     */
+    kerror = krb_mk_req(pkt, "krbtgt", realm, lrealm, 0L);
+    if (kerror) {
+	/* stomp stomp stomp */
+	memset(cr.session, 0, sizeof(cr.session));
+	return AD_NOTGT;
+    }
+
+    ptr = pkt->dat + pkt->length;
+
+    snamelen = strlen(service) + 1;
+    sinstlen = strlen(sinstance) + 1;
+    if (sizeof(pkt->dat) - (ptr - pkt->dat) < (4 + 1
+					       + snamelen
+					       + sinstlen)) {
+	/* stomp stomp stomp */
+	memset(cr.session, 0, sizeof(cr.session));
+	return INTK_ERR;
+    }
+
+    /* timestamp */   /* FIXME -- always 0 now, should we fill it in??? */
+    KRB4_PUT32BE(ptr, time_ws);
+
+    *ptr++ = lifetime;
+
+    memcpy(ptr, service, snamelen);
+    ptr += snamelen;
+    memcpy(ptr, sinstance, sinstlen);
+    ptr += sinstlen;
+
+    pkt->length = ptr - pkt->dat;
+
+    /* Send the request to the local ticket-granting server */
+    rpkt->length = 0;
+    addrlen = sizeof(laddr);
+    kerror = krb4int_send_to_kdc_addr(pkt, rpkt, realm,
+				      (struct sockaddr *)&laddr, &addrlen);
+
+    if (!kerror) {
+	/* No error; parse return packet from KDC. */
+	kerror = g_ad_tkt_parse(rpkt, cr.session, ses,
+				s_name, s_instance, rlm,
+				service, sinstance, realm,
+				&lifetime, &kvno, tkt,
+				&kdc_time, &t_local);
+    }
+    /*
+     * Unconditionally stomp on cr.session because we don't need it
+     * anymore.
+     */
+    memset(cr.session, 0, sizeof(cr.session));
+    if (kerror) {
+	/*
+	 * Stomp on ses for good measure, since g_ad_tkt_parse()
+	 * doesn't do that for us.
+	 */
+	memset(ses, 0, sizeof(ses));
+	return kerror;
+    }
+
+    kerror = krb4int_save_credentials_addr(s_name, s_instance, rlm,
+					   ses, lifetime, kvno, tkt,
+					   t_local,
+					   laddr.sin_addr.s_addr);
+    /*
+     * Unconditionally stomp on ses because we don't need it anymore.
+     */
+    memset(ses, 0, sizeof(ses));
+    if (kerror)
+	return kerror;
+    return AD_OK;
+}
diff --git a/krb5-1-6/src/lib/krb4/g_cnffile.c b/krb5-1-6/src/lib/krb4/g_cnffile.c
new file mode 100644
index 000000000..dd5ed5c60
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_cnffile.c
@@ -0,0 +1,123 @@
+/* Copyright 1994 Cygnus Support */
+/* Mark W. Eichin */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* common code for looking at krb.conf and krb.realms file */
+/* this may be superceded by <gnu>'s work for the Mac port, but
+   it solves a problem for now. */
+
+#include <stdio.h>
+#include "krb.h"
+#include "k5-int.h"
+#include "krb4int.h"
+
+krb5_context krb5__krb4_context = 0;
+
+static FILE*
+krb__v5_get_file(s)
+     const char *s;
+{
+	FILE *cnffile = 0;
+	const char* names[3];
+	char **full_name = 0, **cpp;
+	krb5_error_code retval;
+
+	if (!krb5__krb4_context)
+		krb5_init_context(&krb5__krb4_context);
+	names[0] = "libdefaults";
+	names[1] = s;
+	names[2] = 0;
+	if (krb5__krb4_context) {
+	    retval = profile_get_values(krb5__krb4_context->profile, names, 
+					&full_name);
+	    if (retval == 0 && full_name && full_name[0]) {
+		cnffile = fopen(full_name[0],"r");
+		for (cpp = full_name; *cpp; cpp++) 
+		    krb5_xfree(*cpp);
+		krb5_xfree(full_name);
+	    }
+	}
+	return cnffile;
+}
+
+char *
+krb__get_srvtabname(default_srvtabname)
+	const char *default_srvtabname;
+{
+	const char* names[3];
+	char **full_name = 0, **cpp;
+	krb5_error_code retval;
+	static char retname[MAXPATHLEN];
+
+	if (!krb5__krb4_context)
+		krb5_init_context(&krb5__krb4_context);
+	names[0] = "libdefaults";
+	names[1] = "krb4_srvtab";
+	names[2] = 0;
+	if (krb5__krb4_context) {
+	    retval = profile_get_values(krb5__krb4_context->profile, names, 
+					&full_name);
+	    if (retval == 0 && full_name && full_name[0]) {
+		retname[0] = '\0';
+		strncat(retname, full_name[0], sizeof(retname));
+		for (cpp = full_name; *cpp; cpp++) 
+		    krb5_xfree(*cpp);
+		krb5_xfree(full_name);
+		return retname;
+	    }
+	}
+	retname[0] = '\0';
+	strncat(retname, default_srvtabname, sizeof(retname));
+	return retname;
+}
+
+FILE*
+krb__get_cnffile()
+{
+	char *s;
+	FILE *cnffile = 0;
+	extern char *getenv();
+
+	/* standard V4 override first */
+	s = getenv("KRB_CONF");
+	if (s) cnffile = fopen(s,"r");
+	/* if that's wrong, use V5 config */
+	if (!cnffile) cnffile = krb__v5_get_file("krb4_config");
+	/* and if V5 config doesn't have it, go to hard-coded values */
+	if (!cnffile) cnffile = fopen(KRB_CONF,"r");
+#ifdef ATHENA_CONF_FALLBACK
+	if (!cnffile) cnffile = fopen(KRB_FB_CONF,"r");
+#endif
+	return cnffile;
+}
+
+
+FILE*
+krb__get_realmsfile()
+{
+	FILE *realmsfile = 0;
+	char *s;
+
+	/* standard (not really) V4 override first */
+	s = getenv("KRB_REALMS");
+	if (s) realmsfile = fopen(s,"r");
+	if (!realmsfile) realmsfile = krb__v5_get_file("krb4_realms");
+	if (!realmsfile) realmsfile = fopen(KRB_RLM_TRANS, "r");
+
+#ifdef ATHENA_CONF_FALLBACK
+	if (!realmsfile) realmsfile = fopen(KRB_FB_RLM_TRANS, "r");
+#endif
+
+	return realmsfile;
+}
+
+
diff --git a/krb5-1-6/src/lib/krb4/g_cred.c b/krb5-1-6/src/lib/krb4/g_cred.c
new file mode 100644
index 000000000..498a5f106
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_cred.c
@@ -0,0 +1,58 @@
+/*
+ * g_cred.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include <string.h>
+#include "krb.h"
+
+/*
+ * krb_get_cred takes a service name, instance, and realm, and a
+ * structure of type CREDENTIALS to be filled in with ticket
+ * information.  It then searches the ticket file for the appropriate
+ * ticket and fills in the structure with the corresponding
+ * information from the file.  If successful, it returns KSUCCESS.
+ * On failure it returns a Kerberos error code.
+ */
+
+int KRB5_CALLCONV
+krb_get_cred(service,instance,realm,c)
+    char *service;		/* Service name */
+    char *instance;		/* Instance */
+    char *realm;		/* Auth domain */
+    CREDENTIALS *c;		/* Credentials struct */
+{
+    int tf_status;              /* return value of tf function calls */
+
+    /* Open ticket file and lock it for shared reading */
+    if ((tf_status = tf_init(TKT_FILE, R_TKT_FIL)) != KSUCCESS)
+	return(tf_status);
+
+    /* Copy principal's name and instance into the CREDENTIALS struc c */
+
+    if ( (tf_status = tf_get_pname(c->pname)) != KSUCCESS ||
+    	 (tf_status = tf_get_pinst(c->pinst)) != KSUCCESS )
+	return (tf_status);
+
+    /* Search for requested service credentials and copy into c */
+       
+    while ((tf_status = tf_get_cred(c)) == KSUCCESS) {
+        /* Is this the right ticket? */
+	if ((strcmp(c->service,service) == 0) &&
+           (strcmp(c->instance,instance) == 0) &&
+           (strcmp(c->realm,realm) == 0))
+		   break;
+    }
+    (void) tf_close();
+
+    if (tf_status == EOF)
+	return (GC_NOTKT);
+    return(tf_status);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_in_tkt.c b/krb5-1-6/src/lib/krb4/g_in_tkt.c
new file mode 100644
index 000000000..cf4ebd15d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_in_tkt.c
@@ -0,0 +1,555 @@
+/*
+ * lib/krb4/g_in_tkt.c
+ *
+ * Copyright 1986-2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "des.h"
+#include "krb4int.h"
+#include "prot.h"
+
+#include "port-sockets.h"
+#include <string.h>
+
+/* Define a couple of function types including parameters.  These
+   are needed on MS-Windows to convert arguments of the function pointers
+   to the proper types during calls.  These declarations are found
+   in <krb-sed.h>, but the code below is too opaque if you can't also
+   see them here.  */
+#ifndef	KEY_PROC_TYPE_DEFINED
+typedef int (*key_proc_type) (char *, char *, char *,
+					     char *, C_Block);
+#endif
+#ifndef	DECRYPT_TKT_TYPE_DEFINED
+typedef int (*decrypt_tkt_type) (char *, char *, char *, char *,
+				     key_proc_type, KTEXT *);
+#endif
+
+static int decrypt_tkt(char *, char *, char *, char *, key_proc_type, KTEXT *);
+static int krb_mk_in_tkt_preauth(char *, char *, char *, char *, char *,
+				 int, char *, int, KTEXT, int *, struct sockaddr_in *);			
+static int krb_parse_in_tkt_creds(char *, char *, char *, char *, char *,
+				  int, KTEXT, int, CREDENTIALS *);
+
+/*
+ * decrypt_tkt(): Given user, instance, realm, passwd, key_proc
+ * and the cipher text sent from the KDC, decrypt the cipher text
+ * using the key returned by key_proc.
+ */
+
+static int
+decrypt_tkt(user, instance, realm, arg, key_proc, cipp)
+    char *user;
+    char *instance;
+    char *realm;
+    char *arg;
+    key_proc_type key_proc;
+    KTEXT *cipp;
+{
+    KTEXT cip = *cipp;
+    C_Block key;		/* Key for decrypting cipher */
+    Key_schedule key_s;
+    register int rc;
+
+#ifndef NOENCRYPTION
+    /* Attempt to decrypt it */
+#endif
+    /* generate a key from the supplied arg or password.  */
+    rc = (*key_proc)(user, instance, realm, arg, key);
+    if (rc)
+	return rc;
+
+#ifndef NOENCRYPTION
+    key_sched(key, key_s);
+    pcbc_encrypt((C_Block *)cip->dat, (C_Block *)cip->dat,
+		 (long)cip->length, key_s, (C_Block *)key, 0);
+#endif /* !NOENCRYPTION */
+    /* Get rid of all traces of key */
+    memset(key, 0, sizeof(key));
+    memset(key_s, 0, sizeof(key_s));
+
+    return 0;
+}
+
+/*
+ * krb_get_in_tkt() gets a ticket for a given principal to use a given
+ * service and stores the returned ticket and session key for future
+ * use.
+ *
+ * The "user", "instance", and "realm" arguments give the identity of
+ * the client who will use the ticket.  The "service" and "sinstance"
+ * arguments give the identity of the server that the client wishes
+ * to use.  (The realm of the server is the same as the Kerberos server
+ * to whom the request is sent.)  The "life" argument indicates the
+ * desired lifetime of the ticket; the "key_proc" argument is a pointer
+ * to the routine used for getting the client's private key to decrypt
+ * the reply from Kerberos.  The "decrypt_proc" argument is a pointer
+ * to the routine used to decrypt the reply from Kerberos; and "arg"
+ * is an argument to be passed on to the "key_proc" routine.
+ *
+ * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it
+ * returns an error code:  If an AUTH_MSG_ERR_REPLY packet is returned
+ * by Kerberos, then the error code it contains is returned.  Other
+ * error codes returned by this routine include INTK_PROT to indicate
+ * wrong protocol version, INTK_BADPW to indicate bad password (if
+ * decrypted ticket didn't make sense), INTK_ERR if the ticket was for
+ * the wrong server or the ticket store couldn't be initialized.
+ *
+ * The format of the message sent to Kerberos is as follows:
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ *
+ * 1 byte		KRB_PROT_VERSION	protocol version number
+ * 1 byte		AUTH_MSG_KDC_REQUEST |	message type
+ *			HOST_BYTE_ORDER		local byte order in lsb
+ * string		user			client's name
+ * string		instance		client's instance
+ * string		realm			client's realm
+ * 4 bytes		tlocal.tv_sec		timestamp in seconds
+ * 1 byte		life			desired lifetime
+ * string		service			service's name
+ * string		sinstance		service's instance
+ */
+
+static int
+krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life,
+		      preauth_p, preauth_len, cip, byteorder, local_addr)
+    char *user;
+    char *instance;
+    char *realm;
+    char *service;
+    char *sinstance;
+    int life;
+    char *preauth_p;
+    int   preauth_len;
+    KTEXT cip;
+    int  *byteorder;
+    struct sockaddr_in *local_addr;
+{
+    KTEXT_ST pkt_st;
+    KTEXT pkt = &pkt_st;	/* Packet to KDC */
+    KTEXT_ST rpkt_st;
+    KTEXT rpkt = &rpkt_st;	/* Returned packet */
+    unsigned char *p;
+    size_t userlen, instlen, realmlen, servicelen, sinstlen;
+    unsigned KRB4_32 t_local;
+
+    int msg_byte_order;
+    int kerror;
+    socklen_t addrlen;
+#if 0
+    unsigned long exp_date;
+#endif
+    unsigned long rep_err_code;
+    unsigned long cip_len;
+    unsigned int t_switch;
+    int i, len;
+
+    /* BUILD REQUEST PACKET */
+
+    p = pkt->dat;
+
+    userlen = strlen(user) + 1;
+    instlen = strlen(instance) + 1;
+    realmlen = strlen(realm) + 1;
+    servicelen = strlen(service) + 1;
+    sinstlen = strlen(sinstance) + 1;
+    /* Make sure the ticket data will fit into the buffer. */
+    if (sizeof(pkt->dat) < (1 + 1 + userlen + instlen + realmlen
+			    + 4 + 1 + servicelen + sinstlen
+			    + preauth_len)) {
+        pkt->length = 0;
+	return INTK_ERR;
+    }
+
+    /* Set up the fixed part of the packet */
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_KDC_REQUEST;
+
+    /* Now for the variable info */
+    memcpy(p, user, userlen);
+    p += userlen;
+    memcpy(p, instance, instlen);
+    p += instlen;
+    memcpy(p, realm, realmlen);
+    p += realmlen;
+
+    /* timestamp */
+    t_local = TIME_GMT_UNIXSEC;
+    KRB4_PUT32BE(p, t_local);
+
+    *p++ = life;
+
+    memcpy(p, service, servicelen);
+    p += servicelen;
+    memcpy(p, sinstance, sinstlen);
+    p += sinstlen;
+
+    if (preauth_len)
+	memcpy(p, preauth_p, (size_t)preauth_len);
+    p += preauth_len;
+
+    pkt->length = p - pkt->dat;
+
+    /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */
+    rpkt->length = 0;
+    addrlen = sizeof(struct sockaddr_in);
+    kerror = krb4int_send_to_kdc_addr(pkt, rpkt, realm,
+				      (struct sockaddr *)local_addr,
+				      &addrlen);
+    if (kerror)
+	return kerror;
+
+    p = rpkt->dat;
+#define RPKT_REMAIN (rpkt->length - (p - rpkt->dat))
+
+    /* check packet version of the returned packet */
+    if (RPKT_REMAIN < 1 + 1)
+	return INTK_PROT;
+    if (*p++ != KRB_PROT_VERSION)
+        return INTK_PROT;
+
+    /* This used to be
+         switch (pkt_msg_type(rpkt) & ~1) {
+       but SCO 3.2v4 cc compiled that incorrectly.  */
+    t_switch = *p++;
+    /* Check byte order */
+    msg_byte_order = t_switch & 1;
+    t_switch &= ~1;
+
+    /* EXTRACT INFORMATION FROM RETURN PACKET */
+
+    /*
+     * Skip over some stuff (3 strings and various integers -- see
+     * cr_auth_repl.c for details).
+     */
+    for (i = 0; i < 3; i++) {
+	len = krb4int_strnlen((char *)p, RPKT_REMAIN) + 1;
+	if (len <= 0)
+	    return INTK_PROT;
+	p += len;
+    }
+    switch (t_switch) {
+    case AUTH_MSG_KDC_REPLY:
+	if (RPKT_REMAIN < 4 + 1 + 4 + 1)
+	    return INTK_PROT;
+	p += 4 + 1 + 4 + 1;
+        break;
+    case AUTH_MSG_ERR_REPLY:
+	if (RPKT_REMAIN < 8)
+	    return INTK_PROT;
+	p += 4;
+	KRB4_GET32(rep_err_code, p, msg_byte_order);
+	return rep_err_code;
+    default:
+        return INTK_PROT;
+    }
+
+    /* Extract the ciphertext */
+    if (RPKT_REMAIN < 2)
+	return INTK_PROT;
+    KRB4_GET16(cip_len, p, msg_byte_order);
+    if (RPKT_REMAIN < cip_len)
+	return INTK_ERR;
+    /*
+     * RPKT_REMAIN will always be non-negative and at most the maximum
+     * possible value of cip->length, so this assignment is safe.
+     */
+    cip->length = cip_len;
+    memcpy(cip->dat, p, (size_t)cip->length);
+    p += cip->length;
+
+    *byteorder = msg_byte_order;
+    return INTK_OK;
+}
+
+static int
+krb_parse_in_tkt_creds(user, instance, realm, service, sinstance, life, cip,
+		       byteorder, creds)
+    char *user;
+    char *instance;
+    char *realm;
+    char *service;
+    char *sinstance;
+    int life;
+    KTEXT cip;
+    int byteorder;
+    CREDENTIALS *creds;
+{
+    unsigned char *ptr;
+    int len;
+    int kvno;			/* Kvno for session key */
+    char s_name[SNAME_SZ];
+    char s_instance[INST_SZ];
+    char rlm[REALM_SZ];
+    KTEXT_ST tkt_st;
+    KTEXT tkt = &tkt_st;	/* Current ticket */
+    unsigned long kdc_time;   /* KDC time */
+    unsigned KRB4_32 t_local;	/* Must be 4 bytes long for memcpy below! */
+    KRB4_32 t_diff;	/* Difference between timestamps */
+    int lifetime;
+
+    ptr = cip->dat;
+    /* Assume that cip->length >= 0 for now. */
+#define CIP_REMAIN (cip->length - (ptr - cip->dat))
+
+    /* Skip session key for now */
+    if (CIP_REMAIN < 8)
+	return INTK_BADPW;
+    ptr += 8;
+
+    /* extract server's name */
+    len = krb4int_strnlen((char *)ptr, CIP_REMAIN) + 1;
+    if (len <= 0 || len > sizeof(s_name))
+	return INTK_BADPW;
+    memcpy(s_name, ptr, (size_t)len);
+    ptr += len;
+
+    /* extract server's instance */
+    len = krb4int_strnlen((char *)ptr, CIP_REMAIN) + 1;
+    if (len <= 0 || len > sizeof(s_instance))
+	return INTK_BADPW;
+    memcpy(s_instance, ptr, (size_t)len);
+    ptr += len;
+
+    /* extract server's realm */
+    len = krb4int_strnlen((char *)ptr, CIP_REMAIN) + 1;
+    if (len <= 0 || len > sizeof(rlm))
+	return INTK_BADPW;
+    memcpy(rlm, ptr, (size_t)len);
+    ptr += len;
+
+    /* extract ticket lifetime, server key version, ticket length */
+    /* be sure to avoid sign extension on lifetime! */
+    if (CIP_REMAIN < 3)
+	return INTK_BADPW;
+    lifetime = *ptr++;
+    kvno = *ptr++;
+    tkt->length = *ptr++;
+
+    /* extract ticket itself */
+    if (CIP_REMAIN < tkt->length)
+	return INTK_BADPW;
+    memcpy(tkt->dat, ptr, (size_t)tkt->length);
+    ptr += tkt->length;
+
+    if (strcmp(s_name, service) || strcmp(s_instance, sinstance)
+	|| strcmp(rlm, realm))	/* not what we asked for */
+	return INTK_ERR;	/* we need a better code here XXX */
+
+    /* check KDC time stamp */
+    if (CIP_REMAIN < 4)
+	return INTK_BADPW;
+    KRB4_GET32(kdc_time, ptr, byteorder);
+
+    t_local = TIME_GMT_UNIXSEC;
+    t_diff = t_local - kdc_time;
+    if (t_diff < 0)
+	t_diff = -t_diff;	/* Absolute value of difference */
+    if (t_diff > CLOCK_SKEW) {
+        return RD_AP_TIME;	/* XXX should probably be better code */
+    }
+
+    /* stash ticket, session key, etc. for future use */
+    strncpy(creds->service, s_name, sizeof(creds->service));
+    strncpy(creds->instance, s_instance, sizeof(creds->instance));
+    strncpy(creds->realm, rlm, sizeof(creds->realm));
+    memmove(creds->session, cip->dat, sizeof(C_Block));
+    creds->lifetime = lifetime;
+    creds->kvno = kvno;
+    creds->ticket_st.length = tkt->length;
+    memmove(creds->ticket_st.dat, tkt->dat, (size_t)tkt->length);
+    creds->issue_date = t_local;
+    strncpy(creds->pname, user, sizeof(creds->pname));
+    strncpy(creds->pinst, instance, sizeof(creds->pinst));
+
+    return INTK_OK;
+}
+
+int
+krb_get_in_tkt_preauth_creds(user, instance, realm, service, sinstance, life,
+			     key_proc, decrypt_proc,
+			     arg, preauth_p, preauth_len, creds, laddrp)
+    char *user;
+    char *instance;
+    char *realm;
+    char *service;
+    char *sinstance;
+    int life;
+    key_proc_type key_proc;
+    decrypt_tkt_type decrypt_proc;
+    char *arg;
+    char *preauth_p;
+    int   preauth_len;
+    CREDENTIALS *creds;
+    KRB_UINT32 *laddrp;
+{
+    int ok;
+    char key_string[BUFSIZ];
+    KTEXT_ST cip_st;
+    KTEXT cip = &cip_st;	/* Returned Ciphertext */
+    int kerror;
+    int byteorder;
+    key_proc_type *keyprocs = krb_get_keyprocs (key_proc);
+    int i = 0;
+    struct sockaddr_in local_addr;
+
+    kerror = krb_mk_in_tkt_preauth(user, instance, realm, 
+				   service, sinstance,
+				   life, preauth_p, preauth_len,
+				   cip, &byteorder, &local_addr);
+    if (kerror)
+	return kerror;
+
+    /* If arg is null, we have to prompt for the password.  decrypt_tkt, by
+       way of the *_passwd_to_key functions, will prompt if the password is
+       NULL, but that means that each separate encryption type will prompt
+       separately.  Obtain the password first so that we can try multiple
+       encryption types without re-prompting.
+
+       Don't, however, prompt on a Windows or Macintosh environment, since
+       that's harder.  Rely on our caller to do it. */
+#if !(defined(_WIN32) || defined(USE_LOGIN_LIBRARY))
+    if (arg == NULL) {
+        ok = des_read_pw_string(key_string, sizeof(key_string), "Password", 0);
+        if (ok != 0)
+            return ok;
+        arg = key_string;
+    }
+#endif
+    
+    /* Attempt to decrypt the reply.  Loop trying password_to_key algorithms 
+       until we succeed or we get an error other than "bad password" */
+    do {
+	KTEXT_ST cip_copy_st;
+	memcpy(&cip_copy_st, &cip_st, sizeof(cip_st));
+	cip = &cip_copy_st;
+        if (decrypt_proc == NULL) {
+            decrypt_tkt (user, instance, realm, arg, keyprocs[i], &cip);
+        } else {
+            (*decrypt_proc)(user, instance, realm, arg, keyprocs[i], &cip);
+        }
+        kerror = krb_parse_in_tkt_creds(user, instance, realm,
+                    service, sinstance, life, cip, byteorder, creds);
+    } while ((keyprocs [++i] != NULL) && (kerror == INTK_BADPW));
+    cip = &cip_st;
+
+    /* Fill in the local address if the caller wants it */
+    if (laddrp != NULL) {
+        *laddrp = local_addr.sin_addr.s_addr;
+    }
+
+    /* stomp stomp stomp */
+    memset(key_string, 0, sizeof(key_string));
+    memset(cip->dat, 0, (size_t)cip->length);
+    return kerror;
+}
+
+int KRB5_CALLCONV
+krb_get_in_tkt_creds(user, instance, realm, service, sinstance, life,
+		     key_proc, decrypt_proc, arg, creds)
+    char *user;
+    char *instance;
+    char *realm;
+    char *service;
+    char *sinstance;
+    int life;
+    key_proc_type key_proc;
+    decrypt_tkt_type decrypt_proc;
+    char *arg;
+    CREDENTIALS *creds;
+{
+#if TARGET_OS_MAC
+    KRB_UINT32 *laddrp = &creds->address;
+#else
+    KRB_UINT32 *laddrp = NULL; /* Only the Mac stores the address */
+#endif
+    
+    return krb_get_in_tkt_preauth_creds(user, instance, realm,
+					service, sinstance, life,
+					key_proc, decrypt_proc, arg,
+					NULL, 0, creds, laddrp);
+}
+
+int KRB5_CALLCONV
+krb_get_in_tkt_preauth(user, instance, realm, service, sinstance, life,
+		       key_proc, decrypt_proc,
+		       arg, preauth_p, preauth_len)
+    char *user;
+    char *instance;
+    char *realm;
+    char *service;
+    char *sinstance;
+    int life;
+    key_proc_type key_proc;
+    decrypt_tkt_type decrypt_proc;
+    char *arg;
+    char *preauth_p;
+    int   preauth_len;
+{
+    int retval;
+    KRB_UINT32 laddr;
+    CREDENTIALS creds;
+
+    do {
+	retval = krb_get_in_tkt_preauth_creds(user, instance, realm,
+					      service, sinstance, life,
+					      key_proc, decrypt_proc,
+					      arg, preauth_p, preauth_len,
+					      &creds, &laddr);
+	if (retval != KSUCCESS) break;
+	if (krb_in_tkt(user, instance, realm) != KSUCCESS) {
+	    retval = INTK_ERR;
+	    break;
+	}
+	retval = krb4int_save_credentials_addr(creds.service, creds.instance,
+					       creds.realm, creds.session,
+					       creds.lifetime, creds.kvno,
+					       &creds.ticket_st,
+					       creds.issue_date, laddr);
+	if (retval != KSUCCESS) break;
+    } while (0);
+    memset(&creds, 0, sizeof(creds));
+    return retval;
+}
+
+int KRB5_CALLCONV
+krb_get_in_tkt(user, instance, realm, service, sinstance, life,
+               key_proc, decrypt_proc, arg)
+    char *user;
+    char *instance;
+    char *realm;
+    char *service;
+    char *sinstance;
+    int life;
+    key_proc_type key_proc;
+    decrypt_tkt_type decrypt_proc;
+    char *arg;
+{
+    return krb_get_in_tkt_preauth(user, instance, realm,
+				  service, sinstance, life,
+			   	  key_proc, decrypt_proc, arg,
+				  NULL, 0);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_phost.c b/krb5-1-6/src/lib/krb4/g_phost.c
new file mode 100644
index 000000000..ba1108f21
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_phost.c
@@ -0,0 +1,92 @@
+/*
+ * lib/krb4/g_phost.c
+ *
+ * Copyright 1988, 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "port-sockets.h"
+
+/*
+ * This routine takes an alias for a host name and returns the first
+ * field, lower case, of its domain name.  For example, if "menel" is
+ * an alias for host officially named "menelaus" (in /etc/hosts), for
+ * the host whose official name is "MENELAUS.MIT.EDU", the name "menelaus"
+ * is returned.
+ *
+ * This is done for historical Athena reasons: the Kerberos name of
+ * rcmd servers (rlogin, rsh, rcp) is of the form "rcmd.host@realm"
+ * where "host"is the lowercase for of the host name ("menelaus").
+ * This should go away: the instance should be the domain name
+ * (MENELAUS.MIT.EDU).  But for now we need this routine...
+ *
+ * A pointer to the name is returned, if found, otherwise a pointer
+ * to the original "alias" argument is returned.
+ */
+
+char * KRB5_CALLCONV
+krb_get_phost(alias)
+    char *alias;
+{
+    struct hostent *h;
+    char *p;
+    unsigned char *ucp;
+    static char hostname_mem[MAXHOSTNAMELEN];
+#ifdef DO_REVERSE_RESOLVE
+    char *rev_addr; int rev_type, rev_len;
+#endif
+
+    if ((h=gethostbyname(alias)) != (struct hostent *)NULL ) {
+#ifdef DO_REVERSE_RESOLVE
+	if (! h->h_addr_list ||! h->h_addr_list[0]) {
+		return(0);
+	}
+	rev_type = h->h_addrtype;
+	rev_len = h->h_length;
+	rev_addr = malloc(rev_len);
+	_fmemcpy(rev_addr, h->h_addr_list[0], rev_len);
+	h = gethostbyaddr(rev_addr, rev_len, rev_type);
+	free(rev_addr);
+	if (h == 0) {
+		return (0);
+	}
+#endif
+	/* We don't want to return a *, so we copy to a safe location. */
+	strncpy (hostname_mem, h->h_name, sizeof (hostname_mem));
+	/* Bail out if h_name is too long. */
+	if (hostname_mem[MAXHOSTNAMELEN-1] != '\0')
+	    return NULL;
+	p = strchr( hostname_mem, '.' );
+        if (p)
+            *p = 0;
+        ucp = (unsigned char *)hostname_mem;
+        do {
+            if (isupper(*ucp)) *ucp=tolower(*ucp);
+        } while (*ucp++);
+    }
+    return(hostname_mem);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_pw_in_tkt.c b/krb5-1-6/src/lib/krb4/g_pw_in_tkt.c
new file mode 100644
index 000000000..db2bb8730
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_pw_in_tkt.c
@@ -0,0 +1,383 @@
+/*
+ * lib/krb4/g_pw_in_tkt.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <krb5.h>
+#include "krb.h"
+#include "krb4int.h"
+#include "krb_err.h"
+#include "prot.h"
+#include <string.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef INTK_PW_NULL
+#define INTK_PW_NULL KRBET_GT_PW_NULL
+#endif
+
+/*
+ * This file contains two routines: passwd_to_key() converts
+ * a password into a DES key (prompting for the password if
+ * not supplied), and krb_get_pw_in_tkt() gets an initial ticket for
+ * a user.
+ */
+
+/*
+ * passwd_to_key(): given a password, return a DES key.
+ * There are extra arguments here which (used to be?)
+ * used by srvtab_to_key().
+ *
+ * If the "passwd" argument is not null, generate a DES
+ * key from it, using string_to_key().
+ *
+ * If the "passwd" argument is null, then on a Unix system we call
+ * des_read_password() to prompt for a password and then convert it
+ * into a DES key.  But "prompting" the user is harder in a Windows or
+ * Macintosh environment, so we rely on our caller to explicitly do
+ * that now.
+ *
+ * In either case, the resulting key is put in the "key" argument,
+ * and 0 is returned.
+ */
+/*ARGSUSED */
+static int
+passwd_to_key(user,instance,realm,passwd,key)
+    char *user, *instance, *realm, *passwd;
+    C_Block key;
+{
+#if defined(_WIN32)
+    string_to_key(passwd, key);
+#else /* unix */
+#ifdef NOENCRYPTION
+    if (!passwd)
+	placebo_read_password(key, "Password: ", 0);
+#else /* Do encyryption */
+    if (passwd)
+        string_to_key(passwd, key);
+    else {
+        des_read_password((des_cblock *)key, "Password", 0);
+    }
+#endif /* NOENCRYPTION */
+#endif /* unix */
+    return (0);
+}
+
+/*
+ * krb_get_pw_in_tkt() takes the name of the server for which the initial
+ * ticket is to be obtained, the name of the principal the ticket is
+ * for, the desired lifetime of the ticket, and the user's password.
+ * It passes its arguments on to krb_get_in_tkt(), which contacts
+ * Kerberos to get the ticket, decrypts it using the password provided,
+ * and stores it away for future use.
+ *
+ * On a Unix system, krb_get_pw_in_tkt() is able to prompt the user
+ * for a password, if the supplied password is null.  On a a non Unix
+ * system, it now requires the caller to supply a non-null password.
+ * This is because of the complexities of prompting the user in a
+ * non-terminal-oriented environment like the Macintosh (running in a
+ * driver) or MS-Windows (in a DLL).
+ *
+ * krb_get_pw_in_tkt() passes two additional arguments to krb_get_in_tkt():
+ * the name of a routine (passwd_to_key()) to be used to get the
+ * password in case the "password" argument is null and NULL for the
+ * decryption procedure indicating that krb_get_in_tkt should use the 
+ * default method of decrypting the response from the KDC.
+ *
+ * The result of the call to krb_get_in_tkt() is returned.
+ */
+
+int KRB5_CALLCONV
+krb_get_pw_in_tkt(user,instance,realm,service,sinstance,life,password)
+    char *user, *instance, *realm, *service, *sinstance;
+    int life;
+    char *password;
+{
+#if defined(_WIN32) || (defined(USE_LOGIN_LIBRARY) && USE_LOGIN_LIBRARY)
+    /* In spite of the comments above, we don't allow that path here,
+       to simplify coding the non-UNIX clients. The only code that now
+       depends on this behavior is the preauth support, which has a
+       seperate function without this trap. Strictly speaking, this 
+       is an API change. */
+
+    if (password == 0)
+    	return INTK_PW_NULL;
+#endif
+
+    return(krb_get_in_tkt(user,instance,realm,service,sinstance,life,
+                          (key_proc_type)NULL, /* krb_get_in_tkt will try them all */
+                          (decrypt_tkt_type)NULL, password));
+}
+
+int KRB5_CALLCONV
+krb_get_pw_in_tkt_creds(
+    char *user, char *instance, char *realm, char *service, char *sinstance,
+    int life, char *password, CREDENTIALS *creds)
+{
+    return krb_get_in_tkt_creds(user, instance, realm,
+				service, sinstance, life,
+				(key_proc_type)NULL,  /* krb_get_in_tkt_creds will try them all */
+				NULL, password, creds);
+}
+
+
+/*
+ * krb_get_pw_in_tkt_preauth() gets handed the password or key explicitly,
+ * since the whole point of "pre" authentication is to prove that we've
+ * already got the key, and the only way to do that is to ask the user
+ * for it. Clearly we shouldn't ask twice.
+ */
+ 
+static C_Block old_key;
+
+static int stub_key(user,instance,realm,passwd,key)
+    char *user, *instance, *realm, *passwd;
+    C_Block key;
+{
+   (void) memcpy((char *) key, (char *) old_key, sizeof(old_key));
+   return 0;
+}
+
+int KRB5_CALLCONV
+krb_get_pw_in_tkt_preauth(user,instance,realm,service,sinstance,life,password)
+    char *user, *instance, *realm, *service, *sinstance;
+    int life;
+    char *password;
+{
+    char          *preauth_p;
+    int            preauth_len;
+    int            ret_st;
+    key_proc_type *keyprocs = krb_get_keyprocs (NULL);
+    int            i = 0;
+    
+#if defined(_WIN32) || (defined(USE_LOGIN_LIBRARY) && USE_LOGIN_LIBRARY)
+   /* On non-Unix systems, we can't handle a null password, because
+      passwd_to_key can't handle prompting for the password.  */
+    if (password == 0)
+        return INTK_PW_NULL;
+#endif
+
+    /* Loop trying all the key_proc types */
+	do {
+        krb_mk_preauth(&preauth_p, &preauth_len, keyprocs[i],
+                            user, instance, realm, password, old_key);
+        ret_st = krb_get_in_tkt_preauth(user,instance,realm,service,sinstance,life,
+				   (key_proc_type) stub_key,
+				   (decrypt_tkt_type) NULL, password,
+				   preauth_p, preauth_len);
+                   
+        krb_free_preauth(preauth_p, preauth_len);
+    } while ((keyprocs[++i] != NULL) && (ret_st == INTK_BADPW));
+    
+      return ret_st;
+}
+
+/* FIXME!  This routine belongs in the krb library and should simply
+   be shared between the encrypted and NOENCRYPTION versions!  */
+ 
+#ifdef NOENCRYPTION
+/*
+ * This routine prints the supplied string to standard
+ * output as a prompt, and reads a password string without
+ * echoing.
+ */
+
+#include <stdio.h>
+#ifdef	BSDUNIX
+#include <string.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <setjmp.h>
+#else
+int      strcmp();
+#endif
+#if defined(__svr4__) || defined(__SVR4)
+#include <sgtty.h>
+#endif
+
+#ifdef	BSDUNIX
+static jmp_buf env;
+#endif
+
+#ifdef BSDUNIX
+static void sig_restore();
+static push_signals(), pop_signals();
+int placebo_read_pw_string();
+#endif
+
+/*** Routines ****************************************************** */
+int
+placebo_read_password(k,prompt,verify)
+    des_cblock *k;
+    char *prompt;
+    int	verify;
+{
+    int ok;
+    char key_string[BUFSIZ];
+
+#ifdef BSDUNIX
+    if (setjmp(env)) {
+	ok = -1;
+	goto lose;
+    }
+#endif
+
+    ok = placebo_read_pw_string(key_string, BUFSIZ, prompt, verify);
+    if (ok == 0)
+	memset(k, 0, sizeof(C_Block));
+
+lose:
+    memset(key_string, 0, sizeof (key_string));
+    return ok;
+}
+
+/*
+ * This version just returns the string, doesn't map to key.
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
+
+int
+placebo_read_pw_string(s,max,prompt,verify)
+    char *s;
+    int	max;
+    char *prompt;
+    int	verify;
+{
+    int ok = 0;
+    char *ptr;
+    
+#ifdef BSDUNIX
+    jmp_buf old_env;
+    struct sgttyb tty_state;
+#endif
+    char key_string[BUFSIZ];
+
+    if (max > BUFSIZ) {
+	return -1;
+    }
+
+#ifdef	BSDUNIX
+    memcpy(env, old_env, sizeof(env));
+    if (setjmp(env))
+	goto lose;
+
+    /* save terminal state */
+    if (ioctl(0,TIOCGETP,&tty_state) == -1) 
+	return -1;
+
+    push_signals();
+    /* Turn off echo */
+    tty_state.sg_flags &= ~ECHO;
+    if (ioctl(0,TIOCSETP,&tty_state) == -1)
+	return -1;
+#endif
+    while (!ok) {
+	printf(prompt);
+	fflush(stdout);
+#ifdef	CROSSMSDOS
+	h19line(s,sizeof(s),0);
+	if (!strlen(s))
+	    continue;
+#else
+	if (!fgets(s, max, stdin)) {
+	    clearerr(stdin);
+	    continue;
+	}
+	if ((ptr = strchr(s, '\n')))
+	    *ptr = '\0';
+#endif
+	if (verify) {
+	    printf("\nVerifying, please re-enter %s",prompt);
+	    fflush(stdout);
+#ifdef CROSSMSDOS
+	    h19line(key_string,sizeof(key_string),0);
+	    if (!strlen(key_string))
+		continue;
+#else
+	    if (!fgets(key_string, sizeof(key_string), stdin)) {
+		clearerr(stdin);
+		continue;
+	    }
+            if ((ptr = strchr(key_string, '\n')))
+	    *ptr = '\0';
+#endif
+	    if (strcmp(s,key_string)) {
+		printf("\n\07\07Mismatch - try again\n");
+		fflush(stdout);
+		continue;
+	    }
+	}
+	ok = 1;
+    }
+
+#ifdef	BSDUNIX
+lose:
+    if (!ok)
+	memset(s, 0, max);
+    printf("\n");
+    /* turn echo back on */
+    tty_state.sg_flags |= ECHO;
+    if (ioctl(0,TIOCSETP,&tty_state))
+	ok = 0;
+    pop_signals();
+    memcpy(old_env, env, sizeof(env));
+#endif
+    if (verify)
+	memset(key_string, 0, sizeof (key_string));
+    s[max-1] = 0;		/* force termination */
+    return !ok;			/* return nonzero if not okay */
+}
+
+#ifdef	BSDUNIX
+/*
+ * this can be static since we should never have more than
+ * one set saved....
+ */
+static sigtype (*old_sigfunc[NSIG])();
+
+static push_signals()
+{
+    register i;
+    for (i = 0; i < NSIG; i++)
+	old_sigfunc[i] = signal(i,sig_restore);
+}
+
+static pop_signals()
+{
+    register i;
+    for (i = 0; i < NSIG; i++)
+	signal(i,old_sigfunc[i]);
+}
+
+static void sig_restore(sig,code,scp)
+    int sig,code;
+    struct sigcontext *scp;
+{
+    longjmp(env,1);
+}
+#endif
+#endif /* NOENCRYPTION */
diff --git a/krb5-1-6/src/lib/krb4/g_pw_tkt.c b/krb5-1-6/src/lib/krb4/g_pw_tkt.c
new file mode 100644
index 000000000..f074fbc6c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_pw_tkt.c
@@ -0,0 +1,68 @@
+/*
+ * g_pw_tkt.c
+ *
+ * Copyright 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+
+/*
+ * Get a ticket for the password-changing server ("changepw.KRB_MASTER").
+ *
+ * Given the name, instance, realm, and current password of the
+ * principal for which the user wants a password-changing-ticket,
+ * return either:
+ *
+ *	GT_PW_BADPW if current password was wrong,
+ *	GT_PW_NULL  if principal had a NULL password,
+ *	or the result of the krb_get_pw_in_tkt() call.
+ *
+ * First, try to get a ticket for "user.instance@realm" to use the
+ * "changepw.KRB_MASTER" server (KRB_MASTER is defined in "krb.h").
+ * The requested lifetime for the ticket is "1", and the current
+ * password is the "cpw" argument given.
+ *
+ * If the password was bad, give up.
+ *
+ * If the principal had a NULL password in the Kerberos database
+ * (indicating that the principal is known to Kerberos, but hasn't
+ * got a password yet), try instead to get a ticket for the principal
+ * "default.changepw@realm" to use the "changepw.KRB_MASTER" server.
+ * Use the password "changepwkrb" instead of "cpw".  Return GT_PW_NULL
+ * if all goes well, otherwise the error.
+ *
+ * If this routine succeeds, a ticket and session key for either the
+ * principal "user.instance@realm" or "default.changepw@realm" to use
+ * the password-changing server will be in the user's ticket file.
+ */
+
+int KRB5_CALLCONV
+get_pw_tkt(user,instance,realm,cpw)
+    char *user;
+    char *instance;
+    char *realm;
+    char *cpw;
+{
+    int kerror;
+
+    kerror = krb_get_pw_in_tkt(user, instance, realm, "changepw",
+			       KRB_MASTER, 1, cpw);
+
+    if (kerror == INTK_BADPW)
+	return(GT_PW_BADPW);
+
+    if (kerror == KDC_NULL_KEY) {
+	kerror = krb_get_pw_in_tkt("default","changepw",realm,"changepw",
+				   KRB_MASTER,1,"changepwkrb");
+	if (kerror)
+	    return(kerror);
+	return(GT_PW_NULL);
+    }
+
+    return(kerror);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_svc_in_tkt.c b/krb5-1-6/src/lib/krb4/g_svc_in_tkt.c
new file mode 100644
index 000000000..7ed4efd2a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_svc_in_tkt.c
@@ -0,0 +1,152 @@
+/*
+ * lib/krb4/g_svc_in_tkt.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "krb.h"
+#include "prot.h"
+#include "krb4int.h"
+
+/*
+ * This file contains two routines: srvtab_to_key(), which gets
+ * a server's key from a srvtab file, and krb_get_svc_in_tkt() which
+ * gets an initial ticket for a server.
+ */
+
+/*
+ * srvtab_to_key(): given a "srvtab" file (where the keys for the
+ * service on a host are stored), return the private key of the
+ * given service (user.instance@realm).
+ *
+ * srvtab_to_key() passes its arguments on to read_service_key(),
+ * plus one additional argument, the key version number.
+ * (Currently, the key version number is always 0; this value
+ * is treated as a wildcard by read_service_key().)
+ *
+ * If the "srvtab" argument is null, KEYFILE (defined in "krb.h")
+ * is passed in its place.
+ *
+ * It returns the return value of the read_service_key() call.
+ * The service key is placed in "key".
+ */
+
+static int srvtab_to_key(user, instance, realm, srvtab, key)
+    char *user, *instance, *realm, *srvtab;
+    C_Block key;
+{
+    if (!srvtab)
+        srvtab = KEYFILE;
+
+    return(read_service_key(user, instance, realm, 0, srvtab,
+                            (char *)key));
+}
+
+/*
+ * krb_get_svc_in_tkt() passes its arguments on to krb_get_in_tkt(),
+ * plus two additional arguments: a pointer to the srvtab_to_key()
+ * function to be used to get the key from the key file and a NULL
+ * for the decryption procedure indicating that krb_get_in_tkt should 
+ * use the default method of decrypting the response from the KDC.
+ *
+ * It returns the return value of the krb_get_in_tkt() call.
+ */
+
+int KRB5_CALLCONV
+krb_get_svc_in_tkt(user, instance, realm, service, sinstance, life, srvtab)
+    char *user, *instance, *realm, *service, *sinstance;
+    int life;
+    char *srvtab;
+{
+    return(krb_get_in_tkt(user, instance, realm, service, sinstance, life,
+                          (key_proc_type) srvtab_to_key, NULL, srvtab));
+}
+
+/* and we need a preauth version as well. */
+static C_Block old_key;
+ 
+static int stub_key(user,instance,realm,passwd,key)
+    char *user, *instance, *realm, *passwd;
+    C_Block key;
+{
+   memcpy(key, old_key, sizeof(C_Block));
+   return 0;
+}
+
+int
+krb_get_svc_in_tkt_preauth(user, instance, realm, service, sinstance, life, srvtab)
+    char *user, *instance, *realm, *service, *sinstance;
+    int life;
+    char *srvtab;
+{
+   char *preauth_p;
+   int   preauth_len;
+   int   ret_st;
+ 
+   krb_mk_preauth(&preauth_p, &preauth_len,
+                  (key_proc_type) srvtab_to_key, user, instance, realm,
+		  srvtab, old_key);
+   ret_st = krb_get_in_tkt_preauth(user,instance,realm,service,sinstance,life,
+				   (key_proc_type) stub_key, NULL, srvtab,
+				   preauth_p, preauth_len);
+ 
+   krb_free_preauth(preauth_p, preauth_len);
+   return ret_st;
+}
+
+/* DEC's dss-kerberos adds krb_svc_init; simple enough */
+
+int
+krb_svc_init(user,instance,realm,lifetime,srvtab_file,tkt_file)
+    char *user;
+    char *instance;
+    char *realm;
+    int lifetime;
+    char *srvtab_file;
+    char *tkt_file;
+{
+    if (tkt_file)
+	krb_set_tkt_string(tkt_file);
+
+    return krb_get_svc_in_tkt(user,instance,realm,
+			      KRB_TICKET_GRANTING_TICKET,realm,lifetime,srvtab_file);
+}
+
+
+int
+krb_svc_init_preauth(user,instance,realm,lifetime,srvtab_file,tkt_file)
+    char *user;
+    char *instance;
+    char *realm;
+    int lifetime;
+    char *srvtab_file;
+    char *tkt_file;
+{
+    if (tkt_file)
+        krb_set_tkt_string(tkt_file);
+ 
+    return krb_get_svc_in_tkt_preauth(user,instance,realm,
+                              	      KRB_TICKET_GRANTING_TICKET,realm,lifetime,srvtab_file);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_tf_fname.c b/krb5-1-6/src/lib/krb4/g_tf_fname.c
new file mode 100644
index 000000000..e03fe24b1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_tf_fname.c
@@ -0,0 +1,67 @@
+/*
+ * g_tf_fname.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include <string.h>
+#include <stdio.h>		/* For EOF */
+
+/*
+ * This file contains a routine to extract the fullname of a user
+ * from the ticket file.
+ */
+
+/*
+ * krb_get_tf_fullname() takes four arguments: the name of the 
+ * ticket file, and variables for name, instance, and realm to be
+ * returned in.  Since the realm of a ticket file is not really fully 
+ * supported, the realm used will be that of the the first ticket in 
+ * the file as this is the one that was obtained with a password by
+ * krb_get_in_tkt().
+ */
+
+int KRB5_CALLCONV
+krb_get_tf_fullname(ticket_file, name, instance, realm)
+  const char *ticket_file;
+  char *name;
+  char *instance;
+  char *realm;
+{
+    int tf_status;
+    CREDENTIALS c;
+
+    /* If ticket cache selector is null, use default cache.  */
+    if (ticket_file == 0)
+	ticket_file = tkt_string();
+
+    if ((tf_status = tf_init(ticket_file, R_TKT_FIL)) != KSUCCESS)
+	return(tf_status);
+
+    if (((tf_status = tf_get_pname(c.pname)) != KSUCCESS) ||
+	((tf_status = tf_get_pinst(c.pinst)) != KSUCCESS))
+	return (tf_status);
+    
+    if (name)
+	strcpy(name, c.pname);
+    if (instance)
+	strcpy(instance, c.pinst);
+    if ((tf_status = tf_get_cred(&c)) == KSUCCESS) {
+	if (realm)
+	    strcpy(realm, c.realm);
+    }
+    else {
+	if (tf_status == EOF)
+	    return(KFAILURE);
+	else
+	    return(tf_status);
+    }    
+    (void) tf_close();
+    
+    return(tf_status);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_tf_realm.c b/krb5-1-6/src/lib/krb4/g_tf_realm.c
new file mode 100644
index 000000000..fe99e61e1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_tf_realm.c
@@ -0,0 +1,44 @@
+/*
+ * lib/krb4/g_tf_realm.c
+ *
+ * Copyright 1987-2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+
+/*
+ * This file contains a routine to extract the realm of a kerberos
+ * ticket file.
+ */
+
+/*
+ * krb_get_tf_realm() takes two arguments: the name of a ticket 
+ * and a variable to store the name of the realm in.
+ * 
+ */
+
+int KRB5_CALLCONV
+krb_get_tf_realm(const char *ticket_file, char *realm)
+{
+    return krb_get_tf_fullname(ticket_file, NULL, NULL, realm);
+}
diff --git a/krb5-1-6/src/lib/krb4/g_tkt_svc.c b/krb5-1-6/src/lib/krb4/g_tkt_svc.c
new file mode 100644
index 000000000..a16451776
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/g_tkt_svc.c
@@ -0,0 +1,174 @@
+/* 
+ * g_tkt_svc.c
+ *
+ * Gets a ticket for a service.  Adopted from KClient.
+ */
+
+#include <string.h>
+#include "krb.h"
+#include "port-sockets.h"
+
+/* FIXME -- this should probably be calling mk_auth nowadays.  */
+#define	KRB_SENDAUTH_VERS "AUTHV0.1" 	/* MUST be KRB_SENDAUTH_VLEN chars */
+
+
+static int
+ParseFullName(name, instance, realm, fname)
+	char *name;
+	char *instance;
+	char *realm;
+	char *fname;
+{
+	int err;
+	
+	if (!*fname) return KNAME_FMT;					/* null names are not OK */
+	*instance = '\0';
+	err = kname_parse(name,instance,realm,fname);
+	if (err) return err;
+	if (!*name) return KNAME_FMT;					/* null names are not OK */
+	if (!*realm) { 
+		if ((err = krb_get_lrealm (realm, 1)))
+			return err;
+		if (!*realm) return KNAME_FMT;		/* FIXME -- should give better error */
+	}
+	return KSUCCESS;
+}
+
+
+
+static void
+CopyTicket(dest, src, numBytes, version, includeVersion)
+	char *dest;
+	KTEXT src;
+	unsigned long *numBytes;
+	char *version;
+	int includeVersion;
+{
+	unsigned long tkt_len;
+	unsigned long nbytes = 0;
+		
+    /* first put version info into the buffer */
+    if (includeVersion) {
+		(void) strncpy(dest, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
+		(void) strncpy(dest+KRB_SENDAUTH_VLEN, version, KRB_SENDAUTH_VLEN);
+		nbytes = 2*KRB_SENDAUTH_VLEN;
+	}
+    
+    /* put ticket length into buffer */
+    tkt_len = htonl((unsigned long) src->length);
+	(void) memcpy((char *)(dest+nbytes), (char *) &tkt_len, sizeof(tkt_len));
+    nbytes += sizeof(tkt_len);
+
+    /* put ticket into buffer */
+    (void) memcpy ((char *)(dest+nbytes), (char *) src->dat, src->length);
+    nbytes += src->length;
+    
+    *numBytes = nbytes;
+}
+
+
+static int
+CredIsExpired( cr )
+     CREDENTIALS *cr;
+{
+    KRB4_32 now;
+
+    /* This routine is for use with clients only in order to determine
+       if a credential is still good.
+       Note: twice CLOCK_SKEW was added to age of ticket so that we could 
+       be more sure that the ticket was good. 
+       FIXME:  I think this is a bug -- should use the same algorithm
+       everywhere to determine ticket expiration.   */
+
+    now = TIME_GMT_UNIXSEC;	
+    return now + 2 * CLOCK_SKEW > krb_life_to_time(cr->issue_date,
+						   cr->lifetime);
+}
+
+
+/*
+ * Gets a ticket and returns it to application in buf
+	  -> service		Formal Kerberos name of service
+	  -> buf		Buffer to receive ticket
+	  -> checksum		checksum for this service
+	 <-> buflen		length of ticket buffer (must be at least
+					1258 bytes)
+	 <-  sessionKey		for internal use
+	 <-  schedule		for internal use
+
+ * Result is:
+ *   GC_NOTKT		if there is no matching TGT in the cache
+ *   MK_AP_TGTEXP	if the matching TGT is expired
+ * Other errors possible.  These could cause a dialogue with the user
+ * to get a new TGT.
+ */ 
+
+int KRB5_CALLCONV
+krb_get_ticket_for_service (serviceName, buf, buflen, checksum, sessionKey,
+		schedule, version, includeVersion)
+	char *serviceName;
+	char *buf;
+	unsigned KRB4_32 *buflen;
+	int checksum;
+	des_cblock sessionKey;
+	Key_schedule schedule;
+	char *version;
+	int includeVersion;
+{
+	char service[SNAME_SZ];
+	char instance[INST_SZ];
+	char realm[REALM_SZ];
+	int err;
+	char lrealm[REALM_SZ];
+	CREDENTIALS cr;
+	
+	service[0] = '\0';
+	instance[0] = '\0';
+	realm[0] = '\0';
+	
+	/* parse out service name */
+	
+	err = ParseFullName(service, instance, realm, serviceName);
+	if (err)
+		return err;
+
+    if ((err = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS)
+		return(err);
+
+ 	/* Make sure we have an intial ticket for the user in this realm 
+ 	   Check local realm, not realm for service since krb_mk_req will
+ 	   get additional krbtgt if necessary. This is so that inter-realm
+ 	   works without asking for a password twice.
+ 	   FIXME gnu - I think this is a bug.  We should allow direct
+ 	   authentication to the desired realm, regardless of what the "local"
+ 	   realm is.   I fixed it.   FIXME -- not quite right.   */
+ 	err = krb_get_cred (KRB_TICKET_GRANTING_TICKET, realm, lrealm, &cr);
+ 	if (err) 
+ 		return err;
+
+	err = CredIsExpired(&cr);
+  	if (err)
+  		return RD_AP_EXP;		/* Expired ticket */
+	
+	/* Get a ticket for the service */
+	err = krb_mk_req(&(cr.ticket_st),service,instance,realm,checksum);
+	if (err)
+		return err;
+	
+	CopyTicket(buf, &(cr.ticket_st), buflen, version, includeVersion);
+	
+	/* get the session key for later use in deciphering the server response */
+	err = krb_get_cred(service,instance,realm,&cr);
+	if (err)
+		return err;
+	memcpy((char *)sessionKey, (char *)cr.session, sizeof(C_Block));
+  	err = key_sched(sessionKey, schedule);
+	if (err)
+		return KFAILURE;		/* Bad DES key for some reason (FIXME better error) */
+	
+	else
+		return KSUCCESS;
+	
+}
+
+
diff --git a/krb5-1-6/src/lib/krb4/gethostname.c b/krb5-1-6/src/lib/krb4/gethostname.c
new file mode 100644
index 000000000..cc40dd078
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/gethostname.c
@@ -0,0 +1,36 @@
+/*
+ * gethostname.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "krb4int.h"
+#include "autoconf.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef	GETHOSTNAME
+#define	GETHOSTNAME	gethostname	/* A rather simple default */
+#endif
+
+/*
+ * Return the local host's name in "name", up to "namelen" characters.
+ * "name" will be null-terminated if "namelen" is big enough.
+ * The return code is 0 on success, -1 on failure.  (The calling
+ * interface is identical to BSD gethostname(2).)
+ */
+
+int
+k_gethostname(name, namelen)
+    char *name;
+    int namelen;
+{
+    return GETHOSTNAME(name, namelen);
+}
diff --git a/krb5-1-6/src/lib/krb4/getst.c b/krb5-1-6/src/lib/krb4/getst.c
new file mode 100644
index 000000000..336170d41
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/getst.c
@@ -0,0 +1,40 @@
+/*
+ * getst.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "krb4int.h"
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/*
+ * getst() takes a file descriptor, a string and a count.  It reads
+ * from the file until either it has read "count" characters, or until
+ * it reads a null byte.  When finished, what has been read exists in
+ * the given string "s".  If "count" characters were actually read, the
+ * last is changed to a null, so the returned string is always null-
+ * terminated.  getst() returns the number of characters read, including
+ * the null terminator.
+ */
+
+int
+getst(fd, s, n)
+    int fd;
+    register char *s;
+    int n;
+{
+    register int count = n;
+    while (read(fd, s, 1) > 0 && --count)
+        if (*s++ == '\0')
+            return (n - count);
+    *s = '\0';
+    return (n - count);
+}
diff --git a/krb5-1-6/src/lib/krb4/in_tkt.c b/krb5-1-6/src/lib/krb4/in_tkt.c
new file mode 100644
index 000000000..26336e226
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/in_tkt.c
@@ -0,0 +1,200 @@
+/*
+ * lib/krb4/in_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000, 2001 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "krb.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "autoconf.h"
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+extern int krb_debug;
+
+/*
+ * in_tkt() is used to initialize the ticket store.  It creates the
+ * file to contain the tickets and writes the given user's name "pname"
+ * and instance "pinst" in the file.  in_tkt() returns KSUCCESS on
+ * success, or KFAILURE if something goes wrong.
+ */
+
+#include "k5-util.h"
+#define do_seteuid krb5_seteuid
+
+#ifndef O_SYNC
+#define O_SYNC 0
+#endif
+
+int KRB5_CALLCONV
+in_tkt(pname,pinst)
+    char *pname;
+    char *pinst;
+{
+    int tktfile;
+    uid_t me, metoo, getuid(), geteuid();
+    struct stat statpre, statpost;
+    int count;
+    const char *file = TKT_FILE;
+    int fd;
+    register int i;
+    char charbuf[BUFSIZ];
+    mode_t mask;
+#ifdef TKT_SHMEM
+    char shmidname[MAXPATHLEN];
+#endif /* TKT_SHMEM */
+
+    /* If ticket cache selector is null, use default cache.  */
+    if (file == 0)
+	file = tkt_string();
+
+    me = getuid ();
+    metoo = geteuid();
+    if (lstat(file, &statpre) == 0) {
+	if (statpre.st_uid != me || !(statpre.st_mode & S_IFREG)
+	    || statpre.st_nlink != 1 || statpre.st_mode & 077) {
+	    if (krb_debug)
+		fprintf(stderr,"Error initializing %s",file);
+	    return(KFAILURE);
+	}
+	/*
+	 * Yes, we do uid twiddling here.  It's not optimal, but some
+	 * applications may expect that the ruid is what should really
+	 * own the ticket file, e.g. setuid applications.
+	 */
+	if (me != metoo && do_seteuid(me) < 0)
+	    return KFAILURE;
+	/* file already exists, and permissions appear ok, so nuke it */
+	fd = open(file, O_RDWR|O_SYNC, 0);
+	(void)unlink(file);
+	if (me != metoo && do_seteuid(metoo) < 0)
+	    return KFAILURE;
+	if (fd < 0) {
+	    goto out; /* can't zero it, but we can still try truncating it */
+	}
+
+	/*
+	 * Do some additional paranoid things.  The worst-case
+	 * situation is that a user may be fooled into opening a
+	 * non-regular file briefly if the file is in a directory with
+	 * improper permissions.
+	 */
+	if (fstat(fd, &statpost) < 0) {
+	    (void)close(fd);
+	    goto out;
+	}
+	if (statpre.st_dev != statpost.st_dev
+	    || statpre.st_ino != statpost.st_ino) {
+	    (void)close(fd);
+	    errno = 0;
+	    goto out;
+	}
+
+	memset(charbuf, 0, sizeof(charbuf));
+
+	for (i = 0; i < statpost.st_size; i += sizeof(charbuf))
+	    if (write(fd, charbuf, sizeof(charbuf)) != sizeof(charbuf)) {
+#ifndef NO_FSYNC
+		(void) fsync(fd);
+#endif
+		(void) close(fd);
+		goto out;
+	    }
+	
+#ifndef NO_FSYNC
+	(void) fsync(fd);
+#endif
+	(void) close(fd);
+    }
+ out:
+    /* arrange so the file is owned by the ruid
+       (swap real & effective uid if necessary).
+       This isn't a security problem, since the ticket file, if it already
+       exists, has the right uid (== ruid) and mode. */
+    if (me != metoo) {
+	if (do_seteuid(me) < 0) {
+	    /* can't switch??? barf! */
+	    if (krb_debug)
+		perror("in_tkt: seteuid");
+	    return(KFAILURE);
+	} else
+	    if (krb_debug)
+		printf("swapped UID's %d and %d\n",(int) metoo, (int) me);
+    }
+    /* Set umask to ensure that we have write access on the created
+       ticket file.  */
+    mask = umask(077);
+    tktfile = open(file, O_RDWR|O_SYNC|O_CREAT|O_EXCL, 0600);
+    umask(mask);
+    if (me != metoo) {
+	if (do_seteuid(metoo) < 0) {
+	    /* can't switch??? barf! */
+	    if (krb_debug)
+		perror("in_tkt: seteuid2");
+	    return(KFAILURE);
+	} else
+	    if (krb_debug)
+		printf("swapped UID's %d and %d\n", (int) me, (int) metoo);
+    }
+    if (tktfile < 0) {
+	if (krb_debug)
+	    fprintf(stderr,"Error initializing %s",TKT_FILE);
+        return(KFAILURE);
+    }
+    count = strlen(pname)+1;
+    if (write(tktfile,pname,count) != count) {
+        (void) close(tktfile);
+        return(KFAILURE);
+    }
+    count = strlen(pinst)+1;
+    if (write(tktfile,pinst,count) != count) {
+        (void) close(tktfile);
+        return(KFAILURE);
+    }
+    (void) close(tktfile);
+#ifdef TKT_SHMEM
+    (void) strncpy(shmidname, file, sizeof(shmidname) - 1);
+    shmidname[sizeof(shmidname) - 1] = '\0';
+    (void) strncat(shmidname, ".shm", sizeof(shmidname) - 1 - strlen(shmidname));
+    return(krb_shm_create(shmidname));
+#else /* !TKT_SHMEM */
+    return(KSUCCESS);
+#endif /* TKT_SHMEM */
+}
+
+int KRB5_CALLCONV
+krb_in_tkt(pname, pinst, prealm)
+    char *pname;
+    char *pinst;
+    char *prealm;
+{
+    return in_tkt(pname, pinst);
+}
diff --git a/krb5-1-6/src/lib/krb4/kadm_err.et b/krb5-1-6/src/lib/krb4/kadm_err.et
new file mode 100644
index 000000000..07ab9da4b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/kadm_err.et
@@ -0,0 +1,58 @@
+#	kadmin.v4/server/kadm_err.et
+#
+# Copyright 1988 by the Massachusetts Institute of Technology.
+#
+# For copying and distribution information, please see the file
+# <mit-copyright.h>.
+#
+# Kerberos administration server error table
+#
+	et	kadm
+
+# KADM_SUCCESS, as all success codes should be, is zero
+
+ec KADM_RCSID,		"$Header$"
+# /* Building and unbuilding the packet errors */
+ec KADM_NO_REALM,	"Cannot fetch local realm"
+ec KADM_NO_CRED,	"Unable to fetch credentials"
+ec KADM_BAD_KEY,	"Bad key supplied"
+ec KADM_NO_ENCRYPT,	"Can't encrypt data"
+ec KADM_NO_AUTH,	"Cannot encode/decode authentication info"
+ec KADM_WRONG_REALM,	"Principal attemping change is in wrong realm"
+ec KADM_NO_ROOM,	"Packet is too large"
+ec KADM_BAD_VER,	"Version number is incorrect"
+ec KADM_BAD_CHK,	"Checksum does not match"
+ec KADM_NO_READ,	"Unsealing private data failed"
+ec KADM_NO_OPCODE,	"Unsupported operation"
+ec KADM_NO_HOST,	"Could not find administrating host"
+ec KADM_UNK_HOST,	"Administrating host name is unknown"
+ec KADM_NO_SERV,	"Could not find service name in services database"
+ec KADM_NO_SOCK,	"Could not create socket"
+ec KADM_NO_CONN,	"Could not connect to server"
+ec KADM_NO_HERE,	"Could not fetch local socket address"
+ec KADM_NO_MAST,	"Could not fetch master key"
+ec KADM_NO_VERI,	"Could not verify master key"
+
+# /* From the server side routines */
+ec KADM_INUSE,		"Entry already exists in database"
+ec KADM_UK_SERROR,	"Database store error"
+ec KADM_UK_RERROR,	"Database read error"
+ec KADM_UNAUTH,		"Insufficient access to perform requested operation"
+# KADM_DATA isn't really an error, but...
+ec KADM_DATA,		"Data is available for return to client"
+ec KADM_NOENTRY,	"No such entry in the database"
+
+ec KADM_NOMEM,		"Memory exhausted"
+ec KADM_NO_HOSTNAME,	"Could not fetch system hostname"
+ec KADM_NO_BIND,	"Could not bind port"
+ec KADM_LENGTH_ERROR,	"Length mismatch problem"
+ec KADM_ILL_WILDCARD,	"Illegal use of wildcard"
+
+ec KADM_DB_INUSE,	"Database locked or in use"
+
+ec KADM_INSECURE_PW,	"Insecure password rejected"
+ec KADM_PW_MISMATCH,	"Cleartext password and DES key did not match"
+
+ec KADM_NOT_SERV_PRINC,	"Invalid principal for change srvtab request"
+ec KADM_REALM_TOO_LONG, "Realm name too long"
+end
diff --git a/krb5-1-6/src/lib/krb4/kadm_net.c b/krb5-1-6/src/lib/krb4/kadm_net.c
new file mode 100644
index 000000000..a94aab846
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/kadm_net.c
@@ -0,0 +1,392 @@
+/*
+ * lib/krb4/kadm_net.c
+ *
+ * Copyright 1988, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Kerberos administration server client-side network access routines
+ * These routines do actual network traffic, in a machine dependent manner.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define	DEFINE_SOCKADDR		/* Ask krb.h for struct sockaddr, etc */
+#include "port-sockets.h"
+#include "krb.h"
+#include "krbports.h"
+#include "kadm.h"
+#include "kadm_err.h"
+#include "prot.h"
+
+/* XXX FIXME! */
+#if defined(_WIN32)
+	#define SIGNAL(s, f) 0
+#else
+	#define SIGNAL(s, f) signal(s, f)
+#endif
+
+static void clear_secrets(des_cblock sess_key, Key_schedule sess_sched);
+/* XXX FIXME! */
+#ifdef SIGPIPE
+static krb5_sigtype (*opipe)();
+#endif
+
+/*
+ * kadm_init_link
+ *	receives    : principal, instance, realm
+ *
+ * initializes client parm, the Kadm_Client structure which holds the
+ * data about the connection between the server and client, the services
+ * used, the locations and other fun things
+ */
+int
+kadm_init_link(char *principal, char *instance, char *realm,
+	       Kadm_Client *client_parm, int changepw)
+{
+    struct servent *sep;	       /* service we will talk to */
+    u_short sep_port;
+    struct hostent *hop;	       /* host we will talk to */
+    char adm_hostname[MAXHOSTNAMELEN];
+    char *scol = 0;
+
+    (void) strcpy(client_parm->sname, principal);
+    (void) strcpy(client_parm->sinst, instance);
+    (void) strcpy(client_parm->krbrlm, realm);
+    client_parm->admin_fd = -1;
+    client_parm->default_port = 1;
+
+    /*
+     * set up the admin_addr - fetch name of admin or kpasswd host
+     * (usually the admin host is the kpasswd host unless you have
+     * some sort of realm on crack)
+     */
+    if (changepw) {
+#if 0 /* XXX */
+	if (krb_get_kpasswdhst(adm_hostname, client_parm->krbrlm, 1) != KSUCCESS)
+#endif
+	    if (krb_get_admhst(adm_hostname, client_parm->krbrlm, 1) != KSUCCESS)
+		return KADM_NO_HOST;
+    } else {
+	if (krb_get_admhst(adm_hostname, client_parm->krbrlm, 1) != KSUCCESS)
+	    return KADM_NO_HOST;
+    }
+    scol = strchr(adm_hostname,':');
+    if (scol) *scol = 0;
+    if ((hop = gethostbyname(adm_hostname)) == NULL)
+	/*
+	 * couldn't find the admin servers address
+	 */
+	return KADM_UNK_HOST;
+    if (scol) {
+	sep_port = htons(atoi(scol+1));
+	client_parm->default_port = 0;
+    } else if ((sep = getservbyname(KADM_SNAME, "tcp")) != NULL)
+	sep_port = sep->s_port;
+    else
+	sep_port = htons(KADM_PORT); /* KADM_SNAME = kerberos_master/tcp */
+    memset(&client_parm->admin_addr, 0, sizeof(client_parm->admin_addr));
+    client_parm->admin_addr.sin_family = hop->h_addrtype;
+    memcpy(&client_parm->admin_addr.sin_addr, hop->h_addr, hop->h_length);
+    client_parm->admin_addr.sin_port = sep_port;
+
+    return KADM_SUCCESS;
+}
+
+/*
+ * kadm_cli_send
+ *	recieves   : opcode, packet, packet length, serv_name, serv_inst
+ *	returns    : return code from the packet build, the server, or
+ *			 something else
+ *
+ * It assembles a packet as follows:
+ *	 8 bytes    : VERSION STRING
+ *	 4 bytes    : LENGTH OF MESSAGE DATA and OPCODE
+ *		    : KTEXT
+ *		    : OPCODE       \
+ *		    : DATA          > Encrypted (with make priv)
+ *		    : ......       /
+ *
+ * If it builds the packet and it is small enough, then it attempts to open the
+ * connection to the admin server.  If the connection is succesfully open
+ * then it sends the data and waits for a reply.
+ */
+int
+kadm_cli_send(Kadm_Client *client_parm,
+	      u_char *st_dat,	/* the actual data */
+	      size_t st_siz,	/* length of said data */
+	      u_char **ret_dat, /* to give return info */
+	      size_t *ret_siz)	/* length of returned info */
+{
+/* Macros for use in returning data... used in kadm_cli_send */
+#define RET_N_FREE(r) {clear_secrets(sess_key, sess_sched); free((char *)act_st); free((char *)priv_pak); return r;}
+#define RET_N_FREE2(r) {free((char *)*ret_dat); *ret_dat = 0; *ret_siz = 0; clear_secrets(sess_key, sess_sched); return(r);}
+
+    int		act_len;      /* current offset into packet, return */
+    KRB_INT32	retdat;		/* data */
+    KTEXT_ST	authent;	/* the authenticator we will build */
+    u_char	*act_st;      /* the pointer to the complete packet */
+    u_char	*priv_pak;	/* private version of the packet */
+    long	priv_len;	/* length of private packet */
+    u_long	cksum;		/* checksum of the packet */
+    MSG_DAT	mdat;
+    u_char	*return_dat;
+    u_char	*p;
+    KRB_UINT32	uretdat;
+
+    /* Keys for use in the transactions */
+    des_cblock	sess_key;	/* to be filled in by kadm_cli_keyd */
+    Key_schedule sess_sched;
+
+    act_st = malloc(KADM_VERSIZE); /* verstr stored first */
+    strncpy((char *)act_st, KADM_VERSTR, KADM_VERSIZE);
+    act_len = KADM_VERSIZE;
+
+    if ((retdat = kadm_cli_keyd(client_parm, sess_key, sess_sched)) != KADM_SUCCESS) {
+	free(act_st);
+	return retdat;	       /* couldnt get key working */
+    }
+    priv_pak = malloc(st_siz + 200);
+    /* 200 bytes for extra info case */
+    /* XXX Check mk_priv return type */
+    if ((priv_len = krb_mk_priv(st_dat, priv_pak, (u_long)st_siz,
+				sess_sched, (C_Block *)sess_key,
+				&client_parm->my_addr,
+				&client_parm->admin_addr)) < 0)
+	RET_N_FREE(KADM_NO_ENCRYPT); /* whoops... we got a lose here */
+    /*
+     * here is the length of priv data.  receiver calcs size of
+     * authenticator by subtracting vno size, priv size, and
+     * sizeof(u_long) (for the size indication) from total size
+     */
+    act_len += vts_long((KRB_UINT32)priv_len, &act_st, (int)act_len);
+#ifdef NOENCRYPTION
+    cksum = 0;
+#else
+    cksum = quad_cksum(priv_pak, NULL, priv_len, 0, &sess_key);
+#endif
+    /* XXX cast unsigned->signed */
+    if ((retdat = krb_mk_req_creds(&authent, &client_parm->creds, (long)cksum)) != 0) {
+	/* authenticator? */
+	RET_N_FREE(retdat);
+    }
+
+    act_st = realloc(act_st, (unsigned) (act_len + authent.length
+					    + priv_len));
+    if (!act_st) {
+	clear_secrets(sess_key, sess_sched);
+	free(priv_pak);
+	return KADM_NOMEM;
+    }
+    memcpy(act_st + act_len, authent.dat, authent.length);
+    memcpy(act_st + act_len + authent.length, priv_pak, priv_len);
+    free(priv_pak);
+    if ((retdat = kadm_cli_out(client_parm, act_st,
+			       act_len + authent.length + priv_len,
+			       ret_dat, ret_siz)) != KADM_SUCCESS)
+	RET_N_FREE(retdat);
+    free(act_st);
+
+    /* first see if it's a YOULOSE */
+    if ((*ret_siz >= KADM_VERSIZE) &&
+	!strncmp(KADM_ULOSE, (char *)*ret_dat, KADM_VERSIZE))
+    {
+	/* it's a youlose packet */
+	if (*ret_siz < KADM_VERSIZE + 4)
+	    RET_N_FREE2(KADM_BAD_VER);
+	p = *ret_dat + KADM_VERSIZE;
+	KRB4_GET32BE(uretdat, p);
+	/* XXX unsigned->signed */
+	retdat = (KRB_INT32)uretdat;
+	RET_N_FREE2(retdat);
+    }
+    /* need to decode the ret_dat */
+    if ((retdat = krb_rd_priv(*ret_dat, (u_long)*ret_siz, sess_sched,
+			      (C_Block *)sess_key, &client_parm->admin_addr,
+			      &client_parm->my_addr, &mdat)) != 0)
+	RET_N_FREE2(retdat);
+    if (mdat.app_length < KADM_VERSIZE + 4)
+	/* too short! */
+	RET_N_FREE2(KADM_BAD_VER);
+    if (strncmp((char *)mdat.app_data, KADM_VERSTR, KADM_VERSIZE))
+	/* bad version */
+	RET_N_FREE2(KADM_BAD_VER);
+    p = mdat.app_data + KADM_VERSIZE;
+    KRB4_GET32BE(uretdat, p);
+    /* XXX unsigned->signed */
+    retdat = (KRB_INT32)uretdat;
+    if ((mdat.app_length - KADM_VERSIZE - 4) != 0) {
+	if (!(return_dat =
+	      malloc((unsigned)(mdat.app_length - KADM_VERSIZE - 4))))
+	    RET_N_FREE2(KADM_NOMEM);
+	memcpy(return_dat, p, mdat.app_length - KADM_VERSIZE - 4);
+    } else {
+	/* If it's zero length, still need to malloc a 1 byte string; */
+	/* malloc's of zero will return NULL on AIX & A/UX */
+	if (!(return_dat = malloc((unsigned) 1)))
+	    RET_N_FREE2(KADM_NOMEM);
+	*return_dat = '\0';
+    }
+    free(*ret_dat);
+    clear_secrets(sess_key, sess_sched);
+    *ret_dat = return_dat;
+    *ret_siz = mdat.app_length - KADM_VERSIZE - 4;
+    return retdat;
+}
+
+int kadm_cli_conn(Kadm_Client *client_parm)
+{					/* this connects and sets my_addr */
+#if 0
+    int on = 1;
+#endif
+    if ((client_parm->admin_fd =
+	 socket(client_parm->admin_addr.sin_family, SOCK_STREAM,0)) < 0)
+	return KADM_NO_SOCK;		/* couldnt create the socket */
+    if (SOCKET_CONNECT(client_parm->admin_fd,
+		(struct sockaddr *) & client_parm->admin_addr,
+		sizeof(client_parm->admin_addr))) {
+	(void) SOCKET_CLOSE(client_parm->admin_fd);
+	client_parm->admin_fd = -1;
+
+        /* The V4 kadmind port number is 751.  The RFC assigned
+	   number, for V5, is 749.  Sometimes the entry in
+	   /etc/services on a client machine will say 749, but the
+	   server may be listening on port 751.  We try to partially
+	   cope by automatically falling back to try port 751 if we
+	   don't get a reply on port we are using.  */
+        if (client_parm->admin_addr.sin_port != htons(KADM_PORT)
+	     && client_parm->default_port) {
+	    client_parm->admin_addr.sin_port = htons(KADM_PORT);
+	    return kadm_cli_conn(client_parm);
+	}
+
+	return KADM_NO_CONN;		/* couldnt get the connect */
+    }
+#ifdef SIGPIPE
+    opipe = SIGNAL(SIGPIPE, SIG_IGN);
+#endif
+    client_parm->my_addr_len = sizeof(client_parm->my_addr);
+    if (SOCKET_GETSOCKNAME(client_parm->admin_fd,
+		    (struct sockaddr *) & client_parm->my_addr,
+		    &client_parm->my_addr_len) < 0) {
+	(void) SOCKET_CLOSE(client_parm->admin_fd);
+	client_parm->admin_fd = -1;
+#ifdef SIGPIPE
+	(void) SIGNAL(SIGPIPE, opipe);
+#endif
+	return KADM_NO_HERE;		/* couldnt find out who we are */
+    }
+#if 0
+    if (setsockopt(client_parm.admin_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
+		   sizeof(on)) < 0) {
+	(void) closesocket(client_parm.admin_fd);
+	client_parm.admin_fd = -1;
+#ifdef SIGPIPE
+	(void) SIGNAL(SIGPIPE, opipe);
+#endif
+	return KADM_NO_CONN;		/* XXX */
+    }
+#endif
+    return KADM_SUCCESS;
+}
+
+void kadm_cli_disconn(Kadm_Client *client_parm)
+{
+    (void) SOCKET_CLOSE(client_parm->admin_fd);
+#ifdef SIGPIPE
+    (void) SIGNAL(SIGPIPE, opipe);
+#endif
+    return;
+}
+
+int kadm_cli_out(Kadm_Client *client_parm, u_char *dat, int dat_len,
+		 u_char **ret_dat, size_t *ret_siz)
+{
+    u_short		dlen;
+    int			retval;
+    unsigned char	buf[2], *p;
+
+    dlen = (u_short)dat_len;
+    if (dlen > 0x7fff)		/* XXX krb_net_write signedness */
+	return KADM_NO_ROOM;
+
+    p = buf;
+    KRB4_PUT16BE(p, dlen);
+    if (krb_net_write(client_parm->admin_fd, (char *)buf, 2) < 0)
+	return SOCKET_ERRNO;	/* XXX */
+
+    if (krb_net_write(client_parm->admin_fd, (char *)dat, (int)dat_len) < 0)
+	return SOCKET_ERRNO;	/* XXX */
+
+    retval = krb_net_read(client_parm->admin_fd, (char *)buf, 2);
+    if (retval != 2) {
+	if (retval < 0)
+	    return SOCKET_ERRNO; /* XXX */
+	else
+	    return EPIPE;	/* short read ! */
+    }
+
+    p = buf;
+    KRB4_GET16BE(dlen, p);
+    if (dlen > INT_MAX)		/* XXX krb_net_read signedness */
+	return KADM_NO_ROOM;
+    *ret_dat = malloc(dlen);
+    if (!*ret_dat)
+	return KADM_NOMEM;
+
+    retval = krb_net_read(client_parm->admin_fd, (char *)*ret_dat, (int)dlen);
+    if (retval != dlen) {
+	if (retval < 0)
+	    return SOCKET_ERRNO; /* XXX */
+	else
+	    return EPIPE;	/* short read ! */
+    }
+    *ret_siz = dlen;
+    return KADM_SUCCESS;
+}
+
+static void
+clear_secrets(des_cblock sess_key, Key_schedule sess_sched)
+{
+    memset(sess_key, 0, sizeof(sess_key));
+    memset(sess_sched, 0, sizeof(sess_sched));
+    return;
+}
+
+/* takes in the sess_key and key_schedule and sets them appropriately */
+int kadm_cli_keyd(Kadm_Client *client_parm,
+		  des_cblock s_k, des_key_schedule s_s)
+{
+    int stat;
+
+    memcpy(s_k, client_parm->creds.session, sizeof(des_cblock));
+    stat = key_sched(s_k, s_s);
+    if (stat)
+	return stat;
+    return KADM_SUCCESS;
+}				       /* This code "works" */
diff --git a/krb5-1-6/src/lib/krb4/kadm_stream.c b/krb5-1-6/src/lib/krb4/kadm_stream.c
new file mode 100644
index 000000000..dc9fef110
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/kadm_stream.c
@@ -0,0 +1,325 @@
+/*
+ * kadm_stream.c
+ *
+ * Copyright 1988, 2002 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Stream conversion functions for Kerberos administration server
+ */
+
+/*
+  kadm_stream.c
+  this holds the stream support routines for the kerberos administration server
+
+    vals_to_stream: converts a vals struct to a stream for transmission
+       internals build_field_header, vts_[string, char, long, short]
+    stream_to_vals: converts a stream to a vals struct
+       internals check_field_header, stv_[string, char, long, short]
+    error: prints out a kadm error message, returns
+    fatal: prints out a kadm fatal error message, exits
+*/
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "kadm.h"
+#include "kadm_err.h"
+#include "prot.h"
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+/*
+vals_to_stream
+  recieves    : kadm_vals *, u_char *
+  returns     : a realloced and filled in u_char *
+
+this function creates a byte-stream representation of the kadm_vals structure
+*/
+int
+vals_to_stream(Kadm_vals *dt_in, u_char **dt_out)
+{
+    int vsloop, stsize;		/* loop counter, stream size */
+
+    stsize = build_field_header(dt_in->fields, dt_out);
+    for (vsloop = 31; vsloop >= 0; vsloop--)
+	if (IS_FIELD(vsloop, dt_in->fields)) {
+	    switch (vsloop) {
+	    case KADM_NAME:
+		stsize += vts_string(dt_in->name, dt_out, stsize);
+		break;
+	    case KADM_INST:
+		stsize += vts_string(dt_in->instance, dt_out, stsize);
+		break;
+	    case KADM_EXPDATE:
+		stsize += vts_long((KRB_UINT32)dt_in->exp_date,
+				   dt_out, stsize);
+		break;
+	    case KADM_ATTR:
+		stsize += vts_short(dt_in->attributes, dt_out, stsize);
+		break;
+	    case KADM_MAXLIFE:
+		stsize += vts_char(dt_in->max_life, dt_out, stsize);
+		break;
+	    case KADM_DESKEY:
+		stsize += vts_long(dt_in->key_high, dt_out, stsize);
+		stsize += vts_long(dt_in->key_low, dt_out, stsize);
+		break;
+	    default:
+		break;
+	    }
+	}
+    return stsize;
+}
+
+int
+build_field_header(
+    u_char *cont,		/* container for fields data */
+    u_char **st)		/* stream */
+{
+    *st = malloc(4);
+    if (*st == NULL)
+	return -1;
+    memcpy(*st, cont, 4);
+    return 4;	       /* return pointer to current stream location */
+}
+
+int
+vts_string(char *dat, u_char **st, int loc)
+{
+    size_t len;
+    unsigned char *p;
+
+    if (loc < 0)
+	return -1;
+    len = strlen(dat) + 1;
+    p = realloc(*st, (size_t)loc + len);
+    if (p == NULL)
+	return -1;
+    memcpy(p + loc, dat, len);
+    *st = p;
+    return len;
+}
+
+int
+vts_short(KRB_UINT32 dat, u_char **st, int loc)
+{
+    unsigned char *p;
+
+    if (loc < 0)
+	return -1;
+    p = realloc(*st, (size_t)loc + 2);
+    if (p == NULL)
+	return -1;
+
+    *st = p; /* KRB4_PUT32BE will modify p */
+
+    p += loc; /* place bytes at the end */
+    KRB4_PUT16BE(p, dat);
+
+    return 2;
+}
+
+int
+vts_long(KRB_UINT32 dat, u_char **st, int loc)
+{
+    unsigned char *p;
+
+    if (loc < 0)
+	return -1;
+    p = realloc(*st, (size_t)loc + 4);
+    if (p == NULL)
+	return -1;
+
+    *st = p; /* KRB4_PUT32BE will modify p */
+
+    p += loc; /* place bytes at the end */
+    KRB4_PUT32BE(p, dat);
+
+    return 4;
+}
+
+int
+vts_char(KRB_UINT32 dat, u_char **st, int loc)
+{
+    unsigned char *p;
+
+    if (loc < 0)
+	return -1;
+    p = realloc(*st, (size_t)loc + 1);
+    if (p == NULL)
+	return -1;
+    p[loc] = dat & 0xff;
+    *st = p;
+    return 1;
+}
+
+/*
+stream_to_vals
+  recieves    : u_char *, kadm_vals *
+  returns     : a kadm_vals filled in according to u_char *
+
+this decodes a byte stream represntation of a vals struct into kadm_vals
+*/
+int
+stream_to_vals(
+    u_char *dt_in,
+    Kadm_vals *dt_out,
+    int maxlen)			/* max length to use */
+{
+    register int vsloop, stsize; /* loop counter, stream size */
+    register int status;
+
+    memset(dt_out, 0, sizeof(*dt_out));
+
+    stsize = check_field_header(dt_in, dt_out->fields, maxlen);
+    if (stsize < 0)
+	return -1;
+    for (vsloop = 31; vsloop >= 0; vsloop--)
+	if (IS_FIELD(vsloop, dt_out->fields))
+	    switch (vsloop) {
+	    case KADM_NAME:
+		status = stv_string(dt_in, dt_out->name, stsize,
+				    sizeof(dt_out->name), maxlen);
+		if (status < 0)
+		    return -1;
+		stsize += status;
+		break;
+	    case KADM_INST:
+		status = stv_string(dt_in, dt_out->instance, stsize,
+				    sizeof(dt_out->instance), maxlen);
+		if (status < 0)
+		    return -1;
+		stsize += status;
+		break;
+	    case KADM_EXPDATE:
+	    {
+		KRB_UINT32 exp_date;
+
+		status = stv_long(dt_in, &exp_date, stsize, maxlen);
+		if (status < 0)
+		    return -1;
+		dt_out->exp_date = exp_date;
+		stsize += status;
+	    }
+	    break;
+	    case KADM_ATTR:
+		status = stv_short(dt_in, &dt_out->attributes, stsize,
+				   maxlen);
+		if (status < 0)
+		    return -1;
+		stsize += status;
+		break;
+	    case KADM_MAXLIFE:
+		status = stv_char(dt_in, &dt_out->max_life, stsize,
+				  maxlen);
+		if (status < 0)
+		    return -1;
+		stsize += status;
+		break;
+	    case KADM_DESKEY:
+		status = stv_long(dt_in, &dt_out->key_high, stsize,
+				  maxlen);
+		if (status < 0)
+		    return -1;
+		stsize += status;
+		status = stv_long(dt_in, &dt_out->key_low, stsize,
+				  maxlen);
+		if (status < 0)
+		    return -1;
+		stsize += status;
+		break;
+	    default:
+		break;
+	    }
+    return stsize;
+}
+
+int
+check_field_header(
+    u_char *st,			/* stream */
+    u_char *cont,		/* container for fields data */
+    int maxlen)
+{
+    if (4 > maxlen)
+	return -1;
+    memcpy(cont, st, 4);
+    return 4;	       /* return pointer to current stream location */
+}
+
+int
+stv_string(
+    register u_char *st,	/* base pointer to the stream */
+    char *dat,			/* a string to read from the stream */
+    register int loc,	 /* offset into the stream for current data */
+    int stlen,			/* max length of string to copy in */
+    int maxlen)			/* max length of input stream */
+{
+    int maxcount;		/* max count of chars to copy */
+
+    if (loc < 0)
+	return -1;
+    maxcount = min(maxlen - loc, stlen);
+    if (maxcount <= 0)	     /* No strings left in the input stream */
+	return -1;
+
+    (void) strncpy(dat, (char *)st + loc, (size_t)maxcount);
+
+    if (dat[maxcount - 1]) /* not null-term --> not enuf room */
+	return -1;
+    return strlen(dat) + 1;
+}
+
+int
+stv_short(u_char *st, u_short *dat, int loc, int maxlen)
+{
+    u_short temp;
+    unsigned char *p;
+
+    if (loc < 0 || loc + 2 > maxlen)
+	return -1;
+    p = st + loc;
+    KRB4_GET16BE(temp, p);
+    *dat = temp;
+    return 2;
+}
+
+int
+stv_long(u_char *st, KRB_UINT32 *dat, int loc, int maxlen)
+{
+    KRB_UINT32 temp;
+    unsigned char *p;
+
+    if (loc < 0 || loc + 4 > maxlen)
+	return -1;
+    p = st + loc;
+    KRB4_GET32BE(temp, p);
+    *dat = temp;
+    return 4;
+}
+
+int
+stv_char(u_char *st, u_char *dat, int loc, int maxlen)
+{
+    if (loc < 0 || loc + 1 > maxlen)
+	return -1;
+    *dat = *(st + loc);
+    return 1;
+}
diff --git a/krb5-1-6/src/lib/krb4/klog.c b/krb5-1-6/src/lib/krb4/klog.c
new file mode 100644
index 000000000..da48efeb2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/klog.c
@@ -0,0 +1,124 @@
+/*
+ * lib/krb4/klog.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "autoconf.h"
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#if !defined(VMS) && !defined(_WIN32)
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+
+#include "krb4int.h"
+#include <klog.h>
+
+static char *log_name = KRBLOG;
+static char logtxt[1000];
+
+/*
+ * This file contains two logging routines: kset_logfile()
+ * to determine the file to which log entries should be written;
+ * and klog() to write log entries to the file.
+ */
+
+/*
+ * klog() is used to add entries to the logfile (see kset_logfile()
+ * below).  Note that it is probably not portable since it makes
+ * assumptions about what the compiler will do when it is called
+ * with less than the correct number of arguments which is the
+ * way it is usually called.
+ *
+ * The log entry consists of a timestamp and the given arguments
+ * printed according to the given "format" string.
+ *
+ * The log file is opened and closed for each log entry.
+ *
+ * If the given log type "type" is unknown, or if the log file
+ * cannot be opened, no entry is made to the log file.
+ *
+ * The return value is always a pointer to the formatted log
+ * text string "logtxt".
+ */
+
+char * klog(type,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0)
+    int type;
+    char *format;
+    char *a1,*a2,*a3,*a4,*a5,*a6,*a7,*a8,*a9,*a0;
+{
+    FILE *logfile;
+    time_t now;
+    struct tm *tm;
+    static int logtype_array[NLOGTYPE];
+    static int array_initialized;
+
+    if (!(array_initialized++)) {
+        logtype_array[L_NET_ERR] = 1;
+        logtype_array[L_KRB_PERR] = 1;
+        logtype_array[L_KRB_PWARN] = 1;
+        logtype_array[L_APPL_REQ] = 1;
+        logtype_array[L_INI_REQ] = 1;
+        logtype_array[L_DEATH_REQ] = 1;
+        logtype_array[L_NTGT_INTK] = 1;
+        logtype_array[L_ERR_SEXP] = 1;
+        logtype_array[L_ERR_MKV] = 1;
+        logtype_array[L_ERR_NKY] = 1;
+        logtype_array[L_ERR_NUN] = 1;
+        logtype_array[L_ERR_UNK] = 1;
+    }
+
+    (void) sprintf(logtxt,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0);
+
+    if (!logtype_array[type])
+	return(logtxt);
+
+    if ((logfile = fopen(log_name,"a")) == NULL)
+        return(logtxt);
+
+    (void) time(&now);
+    tm = localtime(&now);
+
+    fprintf(logfile,"%2d-%s-%d %02d:%02d:%02d ",tm->tm_mday,
+            month_sname(tm->tm_mon + 1),1900+tm->tm_year,
+            tm->tm_hour, tm->tm_min, tm->tm_sec);
+    fprintf(logfile,"%s\n",logtxt);
+    (void) fclose(logfile);
+    return(logtxt);
+}
+
+/*
+ * kset_logfile() changes the name of the file to which
+ * messages are logged.  If kset_logfile() is not called,
+ * the logfile defaults to KRBLOG, defined in "krb.h".
+ */
+
+void
+kset_logfile(filename)
+    char *filename;
+{
+    log_name = filename;
+}
diff --git a/krb5-1-6/src/lib/krb4/kname_parse.c b/krb5-1-6/src/lib/krb4/kname_parse.c
new file mode 100644
index 000000000..db3a1cf0b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/kname_parse.c
@@ -0,0 +1,411 @@
+/*
+ * lib/krb4/kname_parse.c
+ *
+ * Copyright 1987, 1988, 2001 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdio.h>
+#include "krb.h"
+#include <string.h>
+
+static int k_isname_unparsed(const char *s);
+static int k_isinst_unparsed(const char *s);
+static int k_isrealm_unparsed(const char *s);
+
+/*
+ * max size of full name
+ *
+ * XXX This does not account for backslach quoting, and besides we
+ * might want to use MAX_K_NAME_SZ.
+ */
+#define FULL_SZ (ANAME_SZ + INST_SZ + REALM_SZ)
+
+#define NAME    0		/* which field are we in? */
+#define INST    1
+#define REALM   2
+
+/*
+ * This file contains four routines for handling Kerberos names.
+ *
+ * kname_parse() breaks a Kerberos name into its name, instance,
+ * and realm components.
+ *
+ * k_isname(), k_isinst(), and k_isrealm() check a given string to see if
+ * it's a syntactically legitimate respective part of a Kerberos name,
+ * returning 1 if it is, 0 if it isn't.
+ *
+ * Definition of "syntactically legitimate" names is according to
+ * the Project Athena Technical Plan Section E.2.1, page 7 "Specifying
+ * names", version dated 21 Dec 1987.
+ */
+
+/*
+ * kname_parse() takes a Kerberos name "fullname" of the form:
+ *
+ *		username[.instance][@realm]
+ *
+ * and returns the three components ("name", "instance", and "realm"
+ * in the example above) in the given arguments "np", "ip", and "rp".
+ *
+ * If successful, it returns KSUCCESS.  If there was an error,
+ * KNAME_FMT is returned.
+ *
+ * For proper operation, this routine requires that the ip, np, and rp
+ * arguments be initialized, either to null strings, or to default values
+ * of name, instance, and realm.  FIXME-gnu:  Does anyone use it this way?
+ */
+
+int KRB5_CALLCONV
+kname_parse(np, ip, rp, fullname)
+    char *np;
+    char *ip;
+    char *rp;
+    char *fullname;
+{
+    char buf[FULL_SZ];
+    char *rnext, *wnext;	/* next char to read, write */
+    register char c;
+    int backslash;
+    int field;
+
+    backslash = 0;
+    rnext = buf;
+    wnext = np;
+    field = NAME;
+
+    if (strlen(fullname) > FULL_SZ)
+        return KNAME_FMT;
+    (void) strcpy(buf, fullname);
+
+    while ((c = *rnext++)) {
+        if (backslash) {
+            *wnext++ = c;
+            backslash = 0;
+            continue;
+        }
+        switch (c) {
+        case '\\':
+            backslash++;
+            break;
+        case '.':
+            switch (field) {
+            case NAME:
+                if (wnext == np)
+                    return KNAME_FMT;
+                *wnext = '\0';
+                field = INST;
+                wnext = ip;
+                break;
+            case INST:		/* We now allow period in instance */
+            case REALM:
+                *wnext++ = c;
+                break;
+            default:
+                DEB (("unknown field value\n"));
+                return KNAME_FMT;
+            }
+            break;
+        case '@':
+            switch (field) {
+            case NAME:
+                if (wnext == np)
+                    return KNAME_FMT;
+                *ip = '\0';
+                /* fall through */
+            case INST:
+                *wnext = '\0';
+                field = REALM;
+                wnext = rp;
+                break;
+            case REALM:
+                return KNAME_FMT;
+            default:
+                DEB (("unknown field value\n"));
+                return KNAME_FMT;
+            }
+            break;
+        default:
+            *wnext++ = c;
+        }
+	/*
+	 * Paranoia: check length each time through to ensure that we
+	 * don't overwrite things.
+	 */
+	switch (field) {
+	case NAME:
+	    if (wnext - np >= ANAME_SZ)
+		return KNAME_FMT;
+	    break;
+	case INST:
+	    if (wnext - ip >= INST_SZ)
+		return KNAME_FMT;
+	    break;
+	case REALM:
+	    if (wnext - rp >= REALM_SZ)
+		return KNAME_FMT;
+	    break;
+	default:
+	    DEB (("unknown field value\n"));
+	    return KNAME_FMT;
+	}
+    }
+    *wnext = '\0';
+    return KSUCCESS;
+}
+
+/*
+ * k_isname() returns 1 if the given name is a syntactically legitimate
+ * Kerberos name; returns 0 if it's not.
+ */
+
+int KRB5_CALLCONV
+k_isname(s)
+    char *s;
+{
+    register char c;
+    int backslash = 0;
+
+    if (!*s)
+        return 0;
+    if (strlen(s) > ANAME_SZ - 1)
+        return 0;
+    while((c = *s++)) {
+        if (backslash) {
+            backslash = 0;
+            continue;
+        }
+        switch(c) {
+        case '\\':
+            backslash = 1;
+            break;
+        case '.':
+            return 0;
+            /* break; */
+        case '@':
+            return 0;
+            /* break; */
+        }
+    }
+    return 1;
+}
+
+
+/*
+ * k_isinst() returns 1 if the given name is a syntactically legitimate
+ * Kerberos instance; returns 0 if it's not.
+ *
+ * We now allow periods in instance names -- they are unambiguous.
+ */
+
+int KRB5_CALLCONV
+k_isinst(s)
+    char *s;
+{
+    register char c;
+    int backslash = 0;
+
+    if (strlen(s) > INST_SZ - 1)
+        return 0;
+    while((c = *s++)) {
+        if (backslash) {
+            backslash = 0;
+            continue;
+        }
+        switch(c) {
+        case '\\':
+            backslash = 1;
+            break;
+        case '@':
+            return 0;
+            /* break; */
+        }
+    }
+    return 1;
+}
+
+/*
+ * k_isrealm() returns 1 if the given name is a syntactically legitimate
+ * Kerberos realm; returns 0 if it's not.
+ */
+
+int KRB5_CALLCONV
+k_isrealm(s)
+    char *s;
+{
+    register char c;
+    int backslash = 0;
+
+    if (!*s)
+        return 0;
+    if (strlen(s) > REALM_SZ - 1)
+        return 0;
+    while((c = *s++)) {
+        if (backslash) {
+            backslash = 0;
+            continue;
+        }
+        switch(c) {
+        case '\\':
+            backslash = 1;
+            break;
+        case '@':
+            return 0;
+            /* break; */
+        }
+    }
+    return 1;
+}
+
+int KRB5_CALLCONV
+kname_unparse(
+    char	*outFullName,
+    const char	*inName,
+    const char	*inInstance,
+    const char	*inRealm)
+{
+    const char	*read;
+    char	*write = outFullName;
+
+    if (inName == NULL)
+	return KFAILURE;
+
+    if (outFullName == NULL)
+        return KFAILURE;
+
+    if (!k_isname_unparsed(inName) ||
+	((inInstance != NULL) && !k_isinst_unparsed(inInstance)) ||
+	((inRealm != NULL) && !k_isrealm_unparsed(inRealm))) {
+
+	return KFAILURE;
+    }
+
+    for (read = inName; *read != '\0'; read++, write++) {
+	if ((*read == '.') || (*read == '@')) {
+	    *write = '\\';
+	    write++;
+	}
+	*write = *read;
+    }
+
+    if ((inInstance != NULL) && (inInstance[0] != '\0')) {
+	*write = '.';
+	write++;
+	for (read = inInstance; *read != '\0'; read++, write++) {
+	    if (*read == '@') {
+		*write = '\\';
+		write++;
+	    }
+	    *write = *read;
+	}
+    }
+
+    if ((inRealm != NULL) && (inRealm[0] != '\0')) {
+	*write = '@';
+	write++;
+	for (read = inRealm; *read != '\0'; read++, write++) {
+	    if (*read == '@') {
+		*write = '\\';
+		write++;
+	    }
+	    *write = *read;
+	}
+    }
+
+    *write = '\0';
+    return KSUCCESS;
+}
+
+/*
+ * k_isname, k_isrealm, k_isinst expect an unparsed realm -- i.e., one where all
+ * components have special characters escaped with \. However,
+ * for kname_unparse, we need to be able to sanity-check components without \.
+ * That's what k_is*_unparsed are for.
+ */
+
+static int
+k_isname_unparsed(const char *s)
+{
+    int len = strlen(s);
+    const char* c;
+    /* Has to be non-empty and has to fit in ANAME_SZ when escaped with \ */
+
+    if (!*s)
+        return 0;
+
+    for (c = s; *c != '\0'; c++) {
+    	switch (*c) {
+	case '.':
+	case '@':
+	    len++;
+	    break;
+    	}
+    }
+
+    if (len > ANAME_SZ - 1)
+        return 0;
+    return 1;
+}
+
+static int
+k_isinst_unparsed(const char *s)
+{
+    int len = strlen(s);
+    const char* c;
+    /* Has to fit in INST_SZ when escaped with \ */
+
+    for (c = s; *c != '\0'; c++) {
+    	switch (*c) {
+	case '.':
+	case '@':
+	    len++;
+	    break;
+    	}
+    }
+
+    if (len > INST_SZ - 1)
+        return 0;
+    return 1;
+}
+
+static int
+k_isrealm_unparsed(const char *s)
+{
+    int len = strlen(s);
+    const char* c;
+    /* Has to be non-empty and has to fit in REALM_SZ when escaped with \ */
+
+    if (!*s)
+        return 0;
+
+    for (c = s; *c != '\0'; c++) {
+    	switch (*c) {
+	case '@':
+	    len++;
+	    break;
+    	}
+    }
+
+    if (len > REALM_SZ - 1)
+        return 0;
+    return 1;
+}
diff --git a/krb5-1-6/src/lib/krb4/kntoln.c b/krb5-1-6/src/lib/krb4/kntoln.c
new file mode 100644
index 000000000..ca48381b9
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/kntoln.c
@@ -0,0 +1,62 @@
+/*
+ * kntoln.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include <string.h>
+
+/*
+ * krb_kntoln converts an auth name into a local name by looking up
+ * the auth name in the /etc/aname file.  The format of the aname
+ * file is:
+ *
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ * | anl | inl | rll | lnl | name | instance | realm | lname |
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ * | 1by | 1by | 1by | 1by | name | instance | realm | lname |
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ *
+ * If the /etc/aname file can not be opened it will set the
+ * local name to the auth name.  Thus, in this case it performs as
+ * the identity function.
+ *
+ * The name instance and realm are passed to krb_kntoln through
+ * the AUTH_DAT structure (ad).
+ *
+ * Now here's what it *really* does:
+ *
+ * Given a Kerberos name in an AUTH_DAT structure, check that the
+ * instance is null, and that the realm is the same as the local
+ * realm, and return the principal's name in "lname".  Return
+ * KSUCCESS if all goes well, otherwise KFAILURE.
+ */
+
+/* The definition of MAX_USERNAME here MUST agree with kuserok.c, or bad
+ * things will happen. */
+#define MAX_USERNAME 10
+
+int
+krb_kntoln(ad,lname)
+    AUTH_DAT *ad;
+    char *lname;
+{
+    static char lrealm[REALM_SZ];
+
+    if (!(*lrealm) && (krb_get_lrealm(lrealm,1) == KFAILURE))
+        return(KFAILURE);
+
+    if (strcmp(ad->pinst,""))
+        return(KFAILURE);
+    if (strcmp(ad->prealm,lrealm))
+        return(KFAILURE);
+    (void) strncpy(lname,ad->pname,MAX_USERNAME-1);
+    lname[MAX_USERNAME - 1] = '\0';
+    return(KSUCCESS);
+}
diff --git a/krb5-1-6/src/lib/krb4/kparse.c b/krb5-1-6/src/lib/krb4/kparse.c
new file mode 100644
index 000000000..f6607a9ca
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/kparse.c
@@ -0,0 +1,784 @@
+/*
+ * kparse.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Purpose:
+ * This module was developed to parse the "~/.klogin" files for
+ * Kerberos-authenticated rlogin/rcp/rsh services.  However, it is
+ * general purpose and can be used to parse any such parameter file.
+ *
+ * The parameter file should consist of one or more entries, with each
+ * entry on a separate line and consisting of zero or more
+ * "keyword=value" combinations.  The keyword is case insensitive, but
+ * the value is not.  Any string may be enclosed in quotes, and
+ * c-style "\" literals are supported.  A comma may be used to
+ * separate the k/v combinations, and multiple commas are ignored.
+ * Whitespace (blank or tab) may be used freely and is ignored.
+ *
+ * Full error processing is available.  When PS_BAD_KEYWORD or
+ * PS_SYNTAX is returned from fGetParameterSet(), the string ErrorMsg
+ * contains a meaningful error message.
+ *
+ * Keywords and their default values are programmed by an external
+ * table.
+ *
+ * Routines:
+ * fGetParameterSet()      parse one line of the parameter file
+ * fGetKeywordValue()      parse one "keyword=value" combo
+ * fGetToken()             parse one token
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <kparse.h>
+#include <string.h>
+#include "autoconf.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#define MAXKEY          80
+#define MAXVALUE        80
+
+static char *strutol (char *);
+
+
+#ifndef HAVE_STRDUP
+static char *strdup();
+#endif
+#ifndef HAVE_STDLIB_H
+extern char *malloc();
+#endif
+
+static int sLineNbr=1;		/* current line nbr in parameter file */
+static char ErrorMsg[80];	/* meaningful only when KV_SYNTAX, PS_SYNTAX,
+				 * or PS_BAD_KEYWORD is returned by
+				 * fGetKeywordValue or fGetParameterSet */
+
+int fGetParameterSet( fp,parm,parmcount )
+    FILE *fp;
+    parmtable parm[];
+    int parmcount;
+{
+    int rc,i;
+    char keyword[MAXKEY];
+    char value[MAXVALUE];
+
+    while (TRUE) {
+        rc=fGetKeywordValue(fp,keyword,MAXKEY,value,MAXVALUE);
+
+        switch (rc) {
+
+        case KV_EOF:
+            return(PS_EOF);
+
+        case KV_EOL:
+            return(PS_OKAY);
+
+        case KV_SYNTAX:
+            return(PS_SYNTAX);
+
+        case KV_OKAY:
+            /*
+             * got a reasonable keyword/value pair.  Search the
+             * parameter table to see if we recognize the keyword; if
+             * not, return an error.  If we DO recognize it, make sure
+             * it has not already been given.  If not already given,
+             * save the value.
+             */
+            for (i=0; i<parmcount; i++) {
+                if (strcmp(strutol(keyword),parm[i].keyword)==0) {
+                    if (parm[i].value) {
+                        sprintf(ErrorMsg,"duplicate keyword \"%s\" found",
+                                keyword);
+                        return(PS_BAD_KEYWORD);
+                    }
+                    parm[i].value = strdup(value);
+                    break;
+                }
+            }
+            if (i >= parmcount) {
+                sprintf(ErrorMsg, "unrecognized keyword \"%s\" found",
+			keyword);
+                return(PS_BAD_KEYWORD);
+            }
+            break;
+
+        default:
+            sprintf(ErrorMsg,
+		    "panic: bad return (%d) from fGetToken()",rc);
+            break;
+        }
+    }
+}
+
+/*
+ * Routine: ParmCompare
+ *
+ * Purpose:
+ * ParmCompare checks a specified value for a particular keyword.
+ * fails if keyword not found or keyword found but the value was
+ * different. Like strcmp, ParmCompare returns 0 for a match found, -1
+ * otherwise
+ */
+int ParmCompare( parm, parmcount, keyword, value )
+    parmtable parm[];
+    int parmcount;
+    char *keyword;
+    char *value;
+{
+    int i;
+
+    for (i=0; i<parmcount; i++) {
+        if (strcmp(parm[i].keyword,keyword)==0) {
+            if (parm[i].value) {
+                return(strcmp(parm[i].value,value));
+            } else {
+                return(strcmp(parm[i].defvalue,value));
+            }
+        }
+    }
+    return(-1);
+}
+
+void FreeParameterSet(parm,parmcount)
+    parmtable parm[];
+    int parmcount;
+{
+    int i;
+
+    for (i=0; i<parmcount; i++) {
+        if (parm[i].value) {
+            free(parm[i].value);
+            parm[i].value = (char *)NULL;
+        }
+    }
+}
+
+int fGetKeywordValue( fp, keyword, klen, value, vlen )
+    FILE *fp;
+    char *keyword;
+    int klen;
+    char *value;
+    int vlen;
+{
+    int rc;
+    int gotit;
+
+    *keyword = *value = '\0';   /* preset strings to NULL */
+
+    /*
+     * Looking for a keyword.
+     *          return an exception for EOF or BAD_QSTRING
+     *          ignore leading WHITEspace
+     *          ignore any number of leading commas
+     *          newline means we have all the parms for this
+     *          	statement; give an indication that there is
+     *          	nothing more on this line.
+     *          stop looking if we find QSTRING, STRING, or NUMBER
+     *          return syntax error for any other PUNKtuation
+     */
+    gotit = FALSE;
+    do {
+        rc = fGetToken(fp,keyword,klen);
+
+        switch (rc) {
+
+        case GTOK_WHITE:
+            break;
+
+        case GTOK_EOF:
+            return(KV_EOF);
+
+        case GTOK_BAD_QSTRING:
+            sprintf(ErrorMsg,"unterminated string \"%s found",keyword);
+            return(KV_SYNTAX);
+
+        case GTOK_PUNK:
+            if (strcmp("\n",keyword)==0) {
+                return(KV_EOL);
+            } else if (strcmp(",",keyword)!=0) {
+                sprintf(ErrorMsg,"expecting rvalue, found \'%s\'",keyword);
+            }
+            break;
+
+        case GTOK_STRING:
+        case GTOK_QSTRING:
+        case GTOK_NUMBER:
+            gotit = TRUE;
+            break;
+
+        default:
+            sprintf(ErrorMsg,"panic: bad return (%d) from fGetToken()",rc);
+            return(KV_SYNTAX);
+        }
+
+    } while (!gotit);
+
+    /*
+     * now we expect an equal sign.
+     *          skip any whitespace
+     *          stop looking if we find an equal sign
+     *          anything else causes a syntax error
+     */
+    gotit = FALSE;
+    do {
+        rc = fGetToken(fp,value,vlen);
+
+        switch (rc) {
+
+        case GTOK_WHITE:
+            break;
+
+        case GTOK_BAD_QSTRING:
+            sprintf(ErrorMsg,
+		    "expecting \'=\', found unterminated string \"%s",
+                    value);
+            return(KV_SYNTAX);
+
+        case GTOK_PUNK:
+            if (strcmp("=",value)==0) {
+                gotit = TRUE;
+            } else {
+                if (strcmp("\n",value)==0) {
+                    sprintf(ErrorMsg,"expecting \"=\", found newline");
+                    fUngetChar('\n',fp);
+                } else {
+                    sprintf(ErrorMsg,
+			    "expecting rvalue, found \'%s\'",keyword);
+                }
+                return(KV_SYNTAX);
+            }
+            break;
+
+        case GTOK_STRING:
+        case GTOK_QSTRING:
+        case GTOK_NUMBER:
+            sprintf(ErrorMsg,"expecting \'=\', found \"%s\"",value);
+            return(KV_SYNTAX);
+
+        case GTOK_EOF:
+            sprintf(ErrorMsg,"expecting \'=\', found EOF");
+            return(KV_SYNTAX);
+
+        default:
+            sprintf(ErrorMsg,
+		    "panic: bad return (%d) from fGetToken()",rc);
+            return(KV_SYNTAX);
+        }
+
+    } while ( !gotit );
+
+    /*
+     * got the keyword and equal sign, now get a value.
+     *          ignore any whitespace
+     *          any punctuation is a syntax error
+     */
+    gotit = FALSE;
+    do {
+        rc = fGetToken(fp,value,vlen);
+
+        switch (rc) {
+
+        case GTOK_WHITE:
+            break;
+
+        case GTOK_EOF:
+            sprintf(ErrorMsg,"expecting rvalue, found EOF");
+            return(KV_SYNTAX);
+
+        case GTOK_BAD_QSTRING:
+            sprintf(ErrorMsg,"unterminated quoted string \"%s",value);
+            return(KV_SYNTAX);
+
+        case GTOK_PUNK:
+            if (strcmp("\n",value)==0) {
+                sprintf(ErrorMsg,"expecting rvalue, found newline");
+                fUngetChar('\n',fp);
+            } else {
+                sprintf(ErrorMsg,
+			"expecting rvalue, found \'%s\'",value);
+            }
+            return(KV_SYNTAX);
+            break;
+
+        case GTOK_STRING:
+        case GTOK_QSTRING:
+        case GTOK_NUMBER:
+            gotit = TRUE;
+            return(KV_OKAY);
+
+        default:
+            sprintf(ErrorMsg,
+		    "panic: bad return (%d) from fGetToken()",rc);
+            return(KV_SYNTAX);
+        }
+
+    } while ( !gotit );
+    /*NOTREACHED*/
+    return 0; /* to keep gcc happy */
+}
+
+/*
+ * Routine Name: fGetToken
+ *
+ * Function: read the next token from the specified file.
+ * A token is defined as a group of characters
+ * terminated by a white space char (SPACE, CR,
+ * LF, FF, TAB). The token returned is stripped of
+ * both leading and trailing white space, and is
+ * terminated by a NULL terminator.  An alternate
+ * definition of a token is a string enclosed in
+ * single or double quotes.
+ *
+ * Explicit Parameters:
+ * fp              pointer to the input FILE
+ * dest    pointer to destination buffer
+ * maxlen  length of the destination buffer. The buffer
+ * length INCLUDES the NULL terminator.
+ *
+ * Implicit Parameters: stderr  where the "token too long" message goes
+ *
+ * External Procedures: fgetc
+ *
+ * Side Effects:                None
+ *
+ * Return Value:                A token classification value, as
+ *				defined in kparse.h. Note that the
+ *				classification for end of file is
+ *				always zero.
+ */
+int fGetToken(fp, dest, maxlen)
+    FILE *fp;
+    char *dest;
+    int  maxlen;
+{
+    int ch='\0';
+    int len=0;
+    char *p = dest;
+    int digits;
+
+    ch=fGetChar(fp);
+
+    /*
+     * check for a quoted string.  If found, take all characters
+     * that fit until a closing quote is found.  Note that this
+     * algorithm will not behave well for a string which is too long.
+     */
+    if (ISQUOTE(ch)) {
+        int done = FALSE;
+        do {
+            ch = fGetChar(fp);
+            done = ((maxlen<++len)||ISLINEFEED(ch)||(ch==EOF)
+		    ||ISQUOTE(ch));
+            if (ch=='\\')
+                ch = fGetLiteral(fp);
+            if (!done)
+                *p++ = ch;
+            else if ((ch!=EOF) && !ISQUOTE(ch))
+                fUngetChar(ch,fp);
+        } while (!done);
+        *p = '\0';
+        if (ISLINEFEED(ch)) return(GTOK_BAD_QSTRING);
+        return(GTOK_QSTRING);
+    }
+
+    /*
+     * Not a quoted string.  If its a token character (rules are
+     * defined via the ISTOKENCHAR macro, in kparse.h) take it and all
+     * token chars following it until we run out of space.
+     */
+    digits=TRUE;
+    if (ISTOKENCHAR(ch)) {
+        while ( (ISTOKENCHAR(ch)) && len<maxlen-1 ) {
+            if (!isdigit(ch)) digits=FALSE;
+            *p++ = ch;
+            len++;
+            ch = fGetChar(fp);
+        };
+        *p = '\0';
+
+        if (ch!=EOF) {
+            fUngetChar(ch,fp);
+        }
+        if (digits) {
+            return(GTOK_NUMBER);
+        } else {
+            return(GTOK_STRING);
+        }
+    }
+
+    /*
+     * Neither a quoted string nor a token character.  Return a string
+     * with just that one character in it.
+     */
+    if (ch==EOF) {
+        return(GTOK_EOF);
+    }
+    if (!ISWHITESPACE(ch)) {
+        *p++ = ch;
+        *p='\0';
+    } else {
+        *p++ = ' ';		/* white space is always the
+				 * blank character */
+        *p='\0';
+        /*
+         * The character is a white space. Flush all additional white
+         * space.
+         */
+        while (ISWHITESPACE(ch) && ((ch=fGetChar(fp)) != EOF))
+            ;
+        if (ch!=EOF) {
+            fUngetChar(ch,fp);
+        }
+        return(GTOK_WHITE);
+    }
+    return(GTOK_PUNK);
+}
+
+/*
+ * fGetLiteral is called after we find a '\' in the input stream.  A
+ * string of numbers following the backslash are converted to the
+ * appropriate value; hex (0xn), octal (0n), and decimal (otherwise)
+ * are all supported.  If the char after the \ is not a number, we
+ * special case certain values (\n, \f, \r, \b) or return a literal
+ * otherwise (useful for \", for example).
+ */
+int fGetLiteral(fp)
+    FILE *fp;
+{
+    int ch;
+    int n=0;
+    int base;
+
+    ch = fGetChar(fp);
+
+    if (!isdigit(ch)) {
+        switch (ch) {
+        case 'n':       return('\n');
+        case 'f':       return('\f');
+        case 'r':       return('\r');
+        case 'b':       return('\b');
+        default:        return(ch);
+        }
+    }
+
+    /*
+     * got a number.  might be decimal (no prefix), octal (prefix 0),
+     * or hexadecimal (prefix 0x).  Set the base appropriately.
+     */
+    if (ch!='0') {
+        base=10;                /* its a decimal number */
+    } else {
+        /*
+         * found a zero, its either hex or octal
+         */
+        ch = fGetChar(fp);
+        if ((ch!='x') && (ch!='X')) {
+            base=010;
+        } else {
+            ch = fGetChar(fp);
+            base=0x10;
+        }
+    }
+
+    switch (base) {
+
+    case 010:                   /* octal */
+        while (ISOCTAL(ch)) {
+            n = (n*base) + ch - '0';
+            ch = fGetChar(fp);
+        }
+        break;
+
+    case 10:                    /* decimal */
+        while (isdigit(ch)) {
+            n = (n*base) + ch - '0';
+            ch = fGetChar(fp);
+        }
+        break;
+    case 0x10:                  /* hexadecimal */
+        while (isxdigit(ch)) {
+            if (isdigit(ch)) {
+                n = (n*base) + ch - '0';
+            } else {
+                n = (n*base) + toupper(ch) - 'A' + 0xA ;
+            }
+            ch = fGetChar(fp);
+        }
+        break;
+    default:
+#ifdef DEBUG
+        fprintf(stderr,"fGetLiteral() died real bad. Fix kparse.c.");
+#endif
+        break;
+    }
+    fUngetChar(ch,fp);
+    return(n);
+}
+
+/*
+ * exactly the same as ungetc(3) except that the line number of the
+ * input file is maintained.
+ */
+int fUngetChar(ch,fp)
+    int ch;
+    FILE *fp;
+{
+    if (ch=='\n') sLineNbr--;
+    return(ungetc(ch,fp));
+}
+
+
+/*
+ * exactly the same as fgetc(3) except that the line number of the
+ * input file is maintained.
+ */
+int fGetChar(fp)
+    FILE *fp;
+{
+    int ch = fgetc(fp);
+    if (ch=='\n') sLineNbr++;
+    return(ch);
+}
+
+/*
+ * strutol changes all characters in a string to lower case, in place.
+ * the pointer to the beginning of the string is returned.
+ */
+
+static char * strutol( start )
+    char *start;
+{
+    char *q;
+    for (q=start; *q; q++)
+        if (isupper((unsigned char) *q))
+	    *q=tolower((unsigned char) *q);
+    return(start);
+}
+
+#ifdef GTOK_TEST	     /* mainline test routine for fGetToken() */
+
+#define MAXTOKEN 100
+
+char *pgm = "gettoken";
+
+main(argc,argv)
+    int argc;
+    char **argv;
+{
+    char *p;
+    int type;
+    FILE *fp;
+
+    if (--argc) {
+        fp = fopen(*++argv,"ra");
+        if (fp == (FILE *)NULL) {
+            fprintf(stderr,"can\'t open \"%s\"\n",*argv);
+        }
+    } else
+        fp = stdin;
+
+    p = malloc(MAXTOKEN);
+    while (type = fGetToken(fp,p,MAXTOKEN)) {
+        switch(type) {
+        case GTOK_BAD_QSTRING:
+	    printf("BAD QSTRING!\t");
+	    break;
+        case GTOK_EOF:
+	    printf("EOF!\t");
+	    break;
+        case GTOK_QSTRING:
+	    printf("QSTRING\t");
+	    break;
+        case GTOK_STRING:
+	    printf("STRING\t");
+	    break;
+        case GTOK_NUMBER:
+	    printf("NUMBER\t");
+	    break;
+        case GTOK_PUNK:
+	    printf("PUNK\t");
+	    break;
+        case GTOK_WHITE:
+	    printf("WHITE\t");
+	    break;
+        default:
+	    printf("HUH?\t");
+	    break;
+        }
+        if (*p=='\n')
+            printf("\\n\n");
+	else
+            printf("%s\n",p);
+    }
+    exit(0);
+}
+#endif
+
+#ifdef KVTEST
+
+main(argc,argv)
+    int argc;
+    char **argv;
+{
+    int rc,ch;
+    FILE *fp;
+    char key[MAXKEY],valu[MAXVALUE];
+    char *filename;
+
+    if (argc != 2) {
+        fprintf(stderr,"usage: test <filename>\n");
+        exit(1);
+    }
+
+    if (!(fp=fopen(*++argv,"r"))) {
+        fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+        exit(1);
+    }
+    filename = *argv;
+
+    while ((rc=fGetKeywordValue(fp,key,MAXKEY,valu,MAXVALUE))!=KV_EOF){
+
+        switch (rc) {
+
+        case KV_EOL:
+            printf("%s, line %d: nada mas.\n",filename,sLineNbr-1);
+            break;
+
+        case KV_SYNTAX:
+            printf("%s, line %d: syntax error: %s\n",
+                   filename,sLineNbr,ErrorMsg);
+            while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+            break;
+
+        case KV_OKAY:
+            printf("%s, line %d: okay, %s=\"%s\"\n",
+                   filename,sLineNbr,key,valu);
+            break;
+
+        default:
+            printf("panic: bad return (%d) from fGetKeywordValue\n",rc);
+            break;
+        }
+    }
+    printf("EOF");
+    fclose(fp);
+    exit(0);
+}
+#endif
+
+#ifdef PSTEST
+
+parmtable kparm[] = {
+    /*  keyword, default, found value */
+    { "user",       "",    (char *)NULL },
+    { "realm",   "Athena", (char *)NULL },
+    { "instance",   "",    (char *)NULL }
+};
+
+main(argc,argv)
+    int argc;
+    char **argv;
+{
+    int rc,i,ch;
+    FILE *fp;
+    char *filename;
+
+    if (argc != 2) {
+        fprintf(stderr,"usage: test <filename>\n");
+        exit(1);
+    }
+
+    if (!(fp=fopen(*++argv,"r"))) {
+        fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+        exit(1);
+    }
+    filename = *argv;
+
+    while ((rc=fGetParameterSet(fp,kparm,PARMCOUNT(kparm))) != PS_EOF) {
+
+        switch (rc) {
+
+        case PS_BAD_KEYWORD:
+            printf("%s, line %d: %s\n",filename,sLineNbr,ErrorMsg);
+            while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+            break;
+
+        case PS_SYNTAX:
+            printf("%s, line %d: syntax error: %s\n",
+                   filename,sLineNbr,ErrorMsg);
+            while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+            break;
+
+        case PS_OKAY:
+            printf("%s, line %d: valid parameter set found:\n",
+                   filename,sLineNbr-1);
+            for (i=0; i<PARMCOUNT(kparm); i++) {
+                printf("\t%s = \"%s\"\n",kparm[i].keyword,
+                       (kparm[i].value ? kparm[i].value
+			: kparm[i].defvalue));
+            }
+            break;
+
+        default:
+            printf("panic: bad return (%d) from fGetParameterSet\n",rc);
+            break;
+        }
+        FreeParameterSet(kparm,PARMCOUNT(kparm));
+    }
+    printf("EOF");
+    fclose(fp);
+    exit(0);
+}
+#endif
+
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)strdup.c	5.3 (Berkeley) 6/1/90 */
+
+#ifndef HAVE_STRDUP
+static char *
+strdup(str)
+	const char *str;
+{
+	int len;
+	char *copy;
+
+	if (!str)
+		return((char *)0);
+	len = strlen(str) + 1;
+	if (!(copy = malloc((u_int)len)))
+		return((char *)0);
+	memcpy(copy, str, len);
+	return(copy);
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb4/krb4int.h b/krb5-1-6/src/lib/krb4/krb4int.h
new file mode 100644
index 000000000..15ea14564
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/krb4int.h
@@ -0,0 +1,125 @@
+/*
+ * lib/krb4/krb4int.h
+ *
+ * Copyright 2001-2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * A series of private prototypes that we are not exporting but should
+ * be available for self consistancy in the library.
+ */
+
+#include "port-sockets.h"
+
+/* ad_print.c */
+void ad_print(AUTH_DAT *x);
+
+/* fgetst.c */
+int fgetst(FILE *, char *, int);
+
+/* getst.c */
+int getst(int, char *, int);
+
+/* g_cnffile.c */
+FILE *krb__get_realmsfile(void);
+
+FILE *krb__get_cnffile(void);
+
+/* g_svc_in_tkt.c */
+int krb_svc_init(char *, char *, char *, int, char *, char *);
+int krb_svc_init_preauth(char *, char *, char *, int, char *, char *);
+
+int krb_get_svc_in_tkt_preauth(char *, char *, char *, char *, char *, int, char *);
+
+/* gethostname.c */
+int k_gethostname(char *, int);
+
+/* g_in_tkt.c */
+int krb_get_in_tkt_preauth_creds(char *, char *, char *,
+				 char *, char *, int,
+				 key_proc_type, decrypt_tkt_type,
+				 char *, char *, int, CREDENTIALS *, KRB_UINT32 *);
+
+/* klog.c */
+void kset_logfile(char *);
+
+/* log.c */
+void krb_log(const char *, ...);
+
+void krb_set_logfile(char *);
+
+/* month_sname.c */
+const char * month_sname(int);
+
+/* password_to_key.c */
+key_proc_type *krb_get_keyprocs (key_proc_type keyproc);
+int KRB5_CALLCONV mit_passwd_to_key(char *user, char *instance, char *realm, 
+				    char *passwd, C_Block key);
+int KRB5_CALLCONV krb5_passwd_to_key(char *user, char *instance, char *realm,
+				     char *passwd, C_Block key);
+int KRB5_CALLCONV afs_passwd_to_key(char *user, char *instance, char *realm,
+				    char *passwd, C_Block key);
+
+/* rd_preauth.c */
+#ifdef KRB_DB_DEFS
+int krb_rd_preauth(KTEXT, char *, int, Principal *, des_cblock);
+#endif
+
+/* sendauth.c */
+int krb_net_rd_sendauth(int, KTEXT, KRB4_32 *);
+
+/* stime.c */
+char *krb_stime(long *);
+
+/* tf_util.c */
+int tf_save_cred(char *, char *, char *, C_Block, int , int, KTEXT, KRB4_32);
+
+
+/* unix_glue.c */
+int krb_start_session(char *);
+
+int krb_end_session(char *);
+
+#ifndef _WIN32
+/* For windows users, these are defined in krb.h */
+char *krb_get_default_user (void);
+
+int krb_set_default_user (char *);
+#endif
+
+/* RealmConfig-glue.c */
+int krb_get_kpasswdhst(char *, char *, int);
+
+/* err_txt.c */
+void krb4int_et_init(void);
+void krb4int_et_fini(void);
+
+int krb4int_save_credentials_addr(
+    char *, char *, char *, C_Block, int, int, KTEXT, KRB4_32, KRB_UINT32);
+
+int krb4int_send_to_kdc_addr(KTEXT, KTEXT, char *,
+			     struct sockaddr *, socklen_t *);
+
+/* 
+ * Exported by libdes425 and called by krb_get_in_pw_tkt, but not part of
+ * the standard DES interface and therefore not prototyped in des.h.
+ */
+int KRB5_CALLCONV des_read_pw_string(char *, int, char *, int);
diff --git a/krb5-1-6/src/lib/krb4/krb_err.et b/krb5-1-6/src/lib/krb4/krb_err.et
new file mode 100644
index 000000000..c4f225d6c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/krb_err.et
@@ -0,0 +1,776 @@
+#	Copyright 1987,1988 Massachusetts Institute of Technology
+#
+#	For copying and distribution information, see the file
+#	"mit-copyright.h".
+# 
+#
+	error_table	krb
+
+	ec		KRBET_KSUCCESS,
+			"Kerberos successful"
+
+	ec		KRBET_KDC_NAME_EXP,
+			"Kerberos principal expired"
+
+	ec		KRBET_KDC_SERVICE_EXP,
+			"Kerberos service expired"
+
+	ec		KRBET_KDC_AUTH_EXP,
+			"Kerberos auth expired"
+
+	ec		KRBET_KDC_PKT_VER,
+			"Unknown kerberos protocol version"
+
+	ec		KRBET_KDC_P_MKEY_VER,
+			"Incorrect kerberos master key version for principal"
+
+	ec		KRBET_KDC_S_MKEY_VER,
+			"Incorrect kerberos master key version for service"
+
+	ec		KRBET_KDC_BYTE_ORDER,
+			"Bad byte order (kerberos)"
+
+	ec		KRBET_KDC_PR_UNKNOWN,
+			"Kerberos principal unknown"
+
+	ec		KRBET_KDC_PR_N_UNIQUE,
+			"Kerberos principal not unique"
+
+	ec		KRBET_KDC_NULL_KEY,
+			"Kerberos principal has null key"
+
+	ec		KRBET_KRB_RES11,
+		        "Reserved error message 11 (kerberos)"
+
+	ec		KRBET_KRB_RES12,
+		        "Reserved error message 12 (kerberos)"
+  
+	ec		KRBET_KRB_RES13,
+		        "Reserved error message 13 (kerberos)"
+
+	ec		KRBET_KRB_RES14,
+		        "Reserved error message 14 (kerberos)"
+
+	ec		KRBET_KRB_RES15,
+		        "Reserved error message 15 (kerberos)"
+
+	ec		KRBET_KRB_RES16,
+		        "Reserved error message 16 (kerberos)"
+
+	ec		KRBET_KRB_RES17,
+		        "Reserved error message 17 (kerberos)"
+
+	ec		KRBET_KRB_RES18,
+		        "Reserved error message 18 (kerberos)"
+
+	ec		KRBET_KRB_RES19,
+		        "Reserved error message 19 (kerberos)"
+
+	ec		KRBET_KDC_GEN_ERR,
+			"Generic error from Kerberos KDC"
+
+	ec		KRBET_GC_TKFIL,
+			"Can't read Kerberos ticket file"
+
+	ec		KRBET_GC_NOTKT,
+			"Can't find Kerberos ticket or TGT"
+
+	ec		KRBET_KRB_RES23,
+			"Reserved error message 23 (krb_get_cred)"
+
+	ec		KRBET_KRB_RES24,
+			"Reserved error message 24 (krb_get_cred)"
+
+	ec		KRBET_KRB_RES25,
+			"Reserved error message 25 (krb_get_cred)"
+
+	ec		KRBET_MK_AP_TGTEXP,
+			"Kerberos TGT Expired"
+
+	ec		KRBET_KRB_RES27,
+			"Reserved error message 27 (krb_mk_req)"
+
+	ec		KRBET_KRB_RES28,
+			"Reserved error message 28 (krb_mk_req)"
+
+	ec		KRBET_KRB_RES29,
+			"Reserved error message 29 (krb_mk_req)"
+
+	ec		KRBET_KRB_RES30,
+			"Reserved error message 30 (krb_mk_req)"
+
+	ec		KRBET_RD_AP_UNDEC,
+			"Can't decode authenticator (krb_rd_req)"
+
+	ec		KRBET_RD_AP_EXP,
+			"Kerberos ticket expired (krb_rd_req)"
+
+	ec		KRBET_RD_AP_NYV,
+			"Kerberos ticket not yet valid (krb_rd_req)"
+
+	ec		KRBET_RD_AP_REPEAT,
+			"Repeated request (krb_rd_req)"
+
+	ec		KRBET_RD_AP_NOT_US,
+			"Kerberos ticket is for wrong server (krb_rd_req)"
+
+	ec		KRBET_RD_AP_INCON,
+			"Kerberos request inconsistent"
+
+	ec		KRBET_RD_AP_TIME,
+			"Time is out of bounds (krb_rd_req)"
+
+	ec		KRBET_RD_AP_BADD,
+			"Incorrect net address (krb_rd_req)"
+
+	ec		KRBET_RD_AP_VERSION,
+			"Kerberos protocol version mismatch (krb_rd_req)"
+
+	ec		KRBET_RD_AP_MSG_TYPE,
+			"Invalid msg type (krb_rd_req)"
+
+	ec		KRBET_RD_AP_MODIFIED,
+			"Message integrity error (krb_rd_req)"
+
+	ec		KRBET_RD_AP_ORDER,
+			"Message out of order (krb_rd_req)"
+
+	ec		KRBET_RD_AP_UNAUTHOR,
+			"Unauthorized request (krb_rd_req)"
+
+	ec		KRBET_KRB_RES44,
+			"Reserved error message 44 (krb_rd_req)"
+
+	ec		KRBET_KRB_RES45,
+			"Reserved error message 45 (krb_rd_req)"
+
+	ec		KRBET_KRB_RES46,
+			"Reserved error message 46 (krb_rd_req)"
+
+	ec		KRBET_KRB_RES47,
+			"Reserved error message 47 (krb_rd_req)"
+
+	ec		KRBET_KRB_RES48,
+			"Reserved error message 48 (krb_rd_req)"
+
+	ec		KRBET_KRB_RES49,
+			"Reserved error message 49 (krb_rd_req)"
+
+	ec		KRBET_KRB_RES50,
+			"Reserved error message 50 (krb_rd_req)"
+
+	ec		KRBET_GT_PW_NULL,
+			"Current password is null (get_pw_tkt)"
+
+	ec		KRBET_GT_PW_BADPW,
+			"Incorrect current password (get_pw_tkt)"
+
+	ec		KRBET_GT_PW_PROT,
+			"Protocol error (get_pw_tkt)"
+
+	ec		KRBET_GT_PW_KDCERR,
+			"Error returned by KDC (get_pw_tkt)"
+
+	ec		KRBET_GT_PW_NULLTKT,
+			"Null Kerberos ticket returned by KDC (get_pw_tkt)"
+
+	ec		KRBET_SKDC_RETRY,
+			"Retry count exceeded (send_to_kdc)"
+
+	ec		KRBET_SKDC_CANT,
+			"Can't send request (send_to_kdc)"
+
+	ec		KRBET_KRB_RES58,
+			"Reserved error message 58 (send_to_kdc)"
+
+	ec		KRBET_KRB_RES59,
+			"Reserved error message 59 (send_to_kdc)"
+
+	ec		KRBET_KRB_RES60,
+			"Reserved error message 60 (send_to_kdc)"
+
+	ec		KRBET_INTK_W_NOTALL,
+			"Kerberos error: not all tickets returned"
+
+	ec		KRBET_INTK_BADPW,
+			"Incorrect password (get_in_tkt)"
+
+	ec		KRBET_INTK_PROT,
+			"Protocol error (get_in_tkt)"
+
+	ec		KRBET_KRB_RES64,
+			"Reserved error message 64 (get_in_tkt)"
+
+	ec		KRBET_KRB_RES65,
+			"Reserved error message 65 (get_in_tkt)"
+
+	ec		KRBET_KRB_RES66,
+			"Reserved error message 66 (get_in_tkt)"
+
+	ec		KRBET_KRB_RES67,
+			"Reserved error message 67 (get_in_tkt)"
+
+	ec		KRBET_KRB_RES68,
+			"Reserved error message 68 (get_in_tkt)"
+
+	ec		KRBET_KRB_RES69,
+			"Reserved error message 69 (get_in_tkt)"
+
+	ec		KRBET_INTK_ERR,
+			"Other error (get_in_tkt)"
+
+	ec		KRBET_AD_NOTGT,
+			"Don't have Kerberos ticket-granting ticket (get_ad_tkt)"
+
+	ec		KRBET_KRB_RES72,
+			"Reserved error message 72 (get_ad_tkt)"
+
+	ec		KRBET_KRB_RES73,
+			"Reserved error message 73 (get_ad_tkt)"
+
+	ec		KRBET_KRB_RES74,
+			"Reserved error message 74 (get_ad_tkt)"
+
+	ec		KRBET_KRB_RES75,
+			"Reserved error message 75 (get_ad_tkt)"
+
+	ec		KRBET_NO_TKT_FIL,
+			"You have no tickets cached"
+
+	ec		KRBET_TKT_FIL_ACC,
+			"Couldn't access ticket file (tf_util)"
+
+	ec		KRBET_TKT_FIL_LCK,
+			"Couldn't lock ticket file (tf_util)"
+
+	ec		KRBET_TKT_FIL_FMT,
+			"Bad ticket file format (tf_util)"
+
+	ec		KRBET_TKT_FIL_INI,
+			"tf_init not called before reading from ticket file (tf_util)"
+
+	ec		KRBET_KNAME_FMT,
+			"Bad Kerberos name format (kname_parse)"
+
+	ec		KRBET_RES82,
+			"Reserved error message 82"
+
+	ec		KRBET_RES83,
+			"Reserved error message 83"
+
+	ec		KRBET_RES84,
+			"Reserved error message 84"
+
+	ec		KRBET_RES85,
+			"Reserved error message 85"
+
+	ec		KRBET_RES86,
+			"Reserved error message 86"
+
+	ec		KRBET_RES87,
+			"Reserved error message 87"
+
+	ec		KRBET_RES88,
+			"Reserved error message 88"
+
+	ec		KRBET_RES89,
+			"Reserved error message 89"
+
+	ec		KRBET_RES90,
+			"Reserved error message 90"
+
+	ec		KRBET_RES91,
+			"Reserved error message 91"
+
+	ec		KRBET_RES92,
+			"Reserved error message 92"
+
+	ec		KRBET_RES93,
+			"Reserved error message 93"
+
+	ec		KRBET_RES94,
+			"Reserved error message 94"
+
+	ec		KRBET_RES95,
+			"Reserved error message 95"
+
+	ec		KRBET_RES96,
+			"Reserved error message 96"
+
+	ec		KRBET_RES97,
+			"Reserved error message 97"
+
+	ec		KRBET_RES98,
+			"Reserved error message 98"
+
+	ec		KRBET_RES99,
+			"Reserved error message 99"
+
+	ec		KRBET_RES100,
+			"Reserved error message 100"
+
+	ec		KRBET_RES101,
+			"Reserved error message 101"
+
+	ec		KRBET_RES102,
+			"Reserved error message 102"
+
+	ec		KRBET_RES103,
+			"Reserved error message 103"
+
+	ec		KRBET_RES104,
+			"Reserved error message 104"
+
+	ec		KRBET_RES105,
+			"Reserved error message 105"
+
+	ec		KRBET_RES106,
+			"Reserved error message 106"
+
+	ec		KRBET_RES107,
+			"Reserved error message 107"
+
+	ec		KRBET_RES108,
+			"Reserved error message 108"
+
+	ec		KRBET_RES109,
+			"Reserved error message 109"
+
+	ec		KRBET_RES110,
+			"Reserved error message 110"
+
+	ec		KRBET_RES111,
+			"Reserved error message 111"
+
+	ec		KRBET_RES112,
+			"Reserved error message 112"
+
+	ec		KRBET_RES113,
+			"Reserved error message 113"
+
+	ec		KRBET_RES114,
+			"Reserved error message 114"
+
+	ec		KRBET_RES115,
+			"Reserved error message 115"
+
+	ec		KRBET_RES116,
+			"Reserved error message 116"
+
+	ec		KRBET_RES117,
+			"Reserved error message 117"
+
+	ec		KRBET_RES118,
+			"Reserved error message 118"
+
+	ec		KRBET_RES119,
+			"Reserved error message 119"
+
+	ec		KRBET_RES120,
+			"Reserved error message 120"
+
+	ec		KRBET_RES121,
+			"Reserved error message 121"
+
+	ec		KRBET_RES122,
+			"Reserved error message 122"
+
+	ec		KRBET_RES123,
+			"Reserved error message 123"
+
+	ec		KRBET_RES124,
+			"Reserved error message 124"
+
+	ec		KRBET_RES125,
+			"Reserved error message 125"
+
+	ec		KRBET_RES126,
+			"Reserved error message 126"
+
+	ec		KRBET_RES127,
+			"Reserved error message 127"
+
+	ec		KRBET_RES128,
+			"Reserved error message 128"
+
+	ec		KRBET_RES129,
+			"Reserved error message 129"
+
+	ec		KRBET_RES130,
+			"Reserved error message 130"
+
+	ec		KRBET_RES131,
+			"Reserved error message 131"
+
+	ec		KRBET_RES132,
+			"Reserved error message 132"
+
+	ec		KRBET_RES133,
+			"Reserved error message 133"
+
+	ec		KRBET_RES134,
+			"Reserved error message 134"
+
+	ec		KRBET_RES135,
+			"Reserved error message 135"
+
+	ec		KRBET_RES136,
+			"Reserved error message 136"
+
+	ec		KRBET_RES137,
+			"Reserved error message 137"
+
+	ec		KRBET_RES138,
+			"Reserved error message 138"
+
+	ec		KRBET_RES139,
+			"Reserved error message 139"
+
+	ec		KRBET_RES140,
+			"Reserved error message 140"
+
+	ec		KRBET_RES141,
+			"Reserved error message 141"
+
+	ec		KRBET_RES142,
+			"Reserved error message 142"
+
+	ec		KRBET_RES143,
+			"Reserved error message 143"
+
+	ec		KRBET_RES144,
+			"Reserved error message 144"
+
+	ec		KRBET_RES145,
+			"Reserved error message 145"
+
+	ec		KRBET_RES146,
+			"Reserved error message 146"
+
+	ec		KRBET_RES147,
+			"Reserved error message 147"
+
+	ec		KRBET_RES148,
+			"Reserved error message 148"
+
+	ec		KRBET_RES149,
+			"Reserved error message 149"
+
+	ec		KRBET_RES150,
+			"Reserved error message 150"
+
+	ec		KRBET_RES151,
+			"Reserved error message 151"
+
+	ec		KRBET_RES152,
+			"Reserved error message 152"
+
+	ec		KRBET_RES153,
+			"Reserved error message 153"
+
+	ec		KRBET_RES154,
+			"Reserved error message 154"
+
+	ec		KRBET_RES155,
+			"Reserved error message 155"
+
+	ec		KRBET_RES156,
+			"Reserved error message 156"
+
+	ec		KRBET_RES157,
+			"Reserved error message 157"
+
+	ec		KRBET_RES158,
+			"Reserved error message 158"
+
+	ec		KRBET_RES159,
+			"Reserved error message 159"
+
+	ec		KRBET_RES160,
+			"Reserved error message 160"
+
+	ec		KRBET_RES161,
+			"Reserved error message 161"
+
+	ec		KRBET_RES162,
+			"Reserved error message 162"
+
+	ec		KRBET_RES163,
+			"Reserved error message 163"
+
+	ec		KRBET_RES164,
+			"Reserved error message 164"
+
+	ec		KRBET_RES165,
+			"Reserved error message 165"
+
+	ec		KRBET_RES166,
+			"Reserved error message 166"
+
+	ec		KRBET_RES167,
+			"Reserved error message 167"
+
+	ec		KRBET_RES168,
+			"Reserved error message 168"
+
+	ec		KRBET_RES169,
+			"Reserved error message 169"
+
+	ec		KRBET_RES170,
+			"Reserved error message 170"
+
+	ec		KRBET_RES171,
+			"Reserved error message 171"
+
+	ec		KRBET_RES172,
+			"Reserved error message 172"
+
+	ec		KRBET_RES173,
+			"Reserved error message 173"
+
+	ec		KRBET_RES174,
+			"Reserved error message 174"
+
+	ec		KRBET_RES175,
+			"Reserved error message 175"
+
+	ec		KRBET_RES176,
+			"Reserved error message 176"
+
+	ec		KRBET_RES177,
+			"Reserved error message 177"
+
+	ec		KRBET_RES178,
+			"Reserved error message 178"
+
+	ec		KRBET_RES179,
+			"Reserved error message 179"
+
+	ec		KRBET_RES180,
+			"Reserved error message 180"
+
+	ec		KRBET_RES181,
+			"Reserved error message 181"
+
+	ec		KRBET_RES182,
+			"Reserved error message 182"
+
+	ec		KRBET_RES183,
+			"Reserved error message 183"
+
+	ec		KRBET_RES184,
+			"Reserved error message 184"
+
+	ec		KRBET_RES185,
+			"Reserved error message 185"
+
+	ec		KRBET_RES186,
+			"Reserved error message 186"
+
+	ec		KRBET_RES187,
+			"Reserved error message 187"
+
+	ec		KRBET_RES188,
+			"Reserved error message 188"
+
+	ec		KRBET_RES189,
+			"Reserved error message 189"
+
+	ec		KRBET_RES190,
+			"Reserved error message 190"
+
+	ec		KRBET_RES191,
+			"Reserved error message 191"
+
+	ec		KRBET_RES192,
+			"Reserved error message 192"
+
+	ec		KRBET_RES193,
+			"Reserved error message 193"
+
+	ec		KRBET_RES194,
+			"Reserved error message 194"
+
+	ec		KRBET_RES195,
+			"Reserved error message 195"
+
+	ec		KRBET_RES196,
+			"Reserved error message 196"
+
+	ec		KRBET_RES197,
+			"Reserved error message 197"
+
+	ec		KRBET_RES198,
+			"Reserved error message 198"
+
+	ec		KRBET_RES199,
+			"Reserved error message 199"
+
+	ec		KRBET_RES200,
+			"Reserved error message 200"
+
+	ec		KRBET_RES201,
+			"Reserved error message 201"
+
+	ec		KRBET_RES202,
+			"Reserved error message 202"
+
+	ec		KRBET_RES203,
+			"Reserved error message 203"
+
+	ec		KRBET_RES204,
+			"Reserved error message 204"
+
+	ec		KRBET_RES205,
+			"Reserved error message 205"
+
+	ec		KRBET_RES206,
+			"Reserved error message 206"
+
+	ec		KRBET_RES207,
+			"Reserved error message 207"
+
+	ec		KRBET_RES208,
+			"Reserved error message 208"
+
+	ec		KRBET_RES209,
+			"Reserved error message 209"
+
+	ec		KRBET_RES210,
+			"Reserved error message 210"
+
+	ec		KRBET_RES211,
+			"Reserved error message 211"
+
+	ec		KRBET_RES212,
+			"Reserved error message 212"
+
+	ec		KRBET_RES213,
+			"Reserved error message 213"
+
+	ec		KRBET_RES214,
+			"Reserved error message 214"
+
+	ec		KRBET_RES215,
+			"Reserved error message 215"
+
+	ec		KRBET_RES216,
+			"Reserved error message 216"
+
+	ec		KRBET_RES217,
+			"Reserved error message 217"
+
+	ec		KRBET_RES218,
+			"Reserved error message 218"
+
+	ec		KRBET_RES219,
+			"Reserved error message 219"
+
+	ec		KRBET_RES220,
+			"Reserved error message 220"
+
+	ec		KRBET_RES221,
+			"Reserved error message 221"
+
+	ec		KRBET_RES222,
+			"Reserved error message 222"
+
+	ec		KRBET_RES223,
+			"Reserved error message 223"
+
+	ec		KRBET_RES224,
+			"Reserved error message 224"
+
+	ec		KRBET_RES225,
+			"Reserved error message 225"
+
+	ec		KRBET_RES226,
+			"Reserved error message 226"
+
+	ec		KRBET_RES227,
+			"Reserved error message 227"
+
+	ec		KRBET_RES228,
+			"Reserved error message 228"
+
+	ec		KRBET_RES229,
+			"Reserved error message 229"
+
+	ec		KRBET_RES230,
+			"Reserved error message 230"
+
+	ec		KRBET_RES231,
+			"Reserved error message 231"
+
+	ec		KRBET_RES232,
+			"Reserved error message 232"
+
+	ec		KRBET_RES233,
+			"Reserved error message 233"
+
+	ec		KRBET_RES234,
+			"Reserved error message 234"
+
+	ec		KRBET_RES235,
+			"Reserved error message 235"
+
+	ec		KRBET_RES236,
+			"Reserved error message 236"
+
+	ec		KRBET_RES237,
+			"Reserved error message 237"
+
+	ec		KRBET_RES238,
+			"Reserved error message 238"
+
+	ec		KRBET_RES239,
+			"Reserved error message 239"
+
+	ec		KRBET_RES240,
+			"Reserved error message 240"
+
+	ec		KRBET_RES241,
+			"Reserved error message 241"
+
+	ec		KRBET_RES242,
+			"Reserved error message 242"
+
+	ec		KRBET_RES243,
+			"Reserved error message 243"
+
+	ec		KRBET_RES244,
+			"Reserved error message 244"
+
+	ec		KRBET_RES245,
+			"Reserved error message 245"
+
+	ec		KRBET_RES246,
+			"Reserved error message 246"
+
+	ec		KRBET_RES247,
+			"Reserved error message 247"
+
+	ec		KRBET_RES248,
+			"Reserved error message 248"
+
+	ec		KRBET_RES249,
+			"Reserved error message 249"
+
+	ec		KRBET_RES250,
+			"Reserved error message 250"
+
+	ec		KRBET_RES251,
+			"Reserved error message 251"
+
+	ec		KRBET_RES252,
+			"Reserved error message 252"
+
+	ec		KRBET_RES253,
+			"Reserved error message 253"
+
+	ec		KRBET_RES254,
+			"Reserved error message 254"
+
+	ec		KRBET_KFAILURE,
+			"Generic kerberos error (kfailure)"
+	end
diff --git a/krb5-1-6/src/lib/krb4/kuserok.c b/krb5-1-6/src/lib/krb4/kuserok.c
new file mode 100644
index 000000000..579128ed3
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/kuserok.c
@@ -0,0 +1,260 @@
+/*
+ * lib/krb4/kuserok.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * kuserok: check if a kerberos principal has
+ * access to a local account
+ */
+
+#include "krb.h"
+
+#if !defined(_WIN32)
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <string.h>
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef __SCO__
+/* just for F_OK for sco */
+#include <sys/unistd.h>
+#endif
+
+#ifndef HAVE_SETEUID
+#ifdef HAVE_SETRESUID
+#define seteuid(e) setresuid(-1,e,-1)
+#define setegid(e) setresgid(-1,e,-1)
+#endif
+#endif
+
+#define OK 0
+#define NOTOK 1
+#define MAX_USERNAME 10
+
+/*
+ * Given a Kerberos principal "kdata", and a local username "luser",
+ * determine whether user is authorized to login according to the
+ * authorization file ("~luser/.klogin" by default).  Returns OK
+ * if authorized, NOTOK if not authorized.
+ *
+ * If there is no account for "luser" on the local machine, returns
+ * NOTOK.  If there is no authorization file, and the given Kerberos
+ * name "kdata" translates to the same name as "luser" (using
+ * krb_kntoln()), returns OK.  Otherwise, if the authorization file
+ * can't be accessed, returns NOTOK.  Otherwise, the file is read for
+ * a matching principal name, instance, and realm.  If one is found,
+ * returns OK, if none is found, returns NOTOK.
+ *
+ * The file entries are in the format:
+ *
+ *	name.instance@realm
+ *
+ * one entry per line.
+ *
+ * The ATHENA_COMPAT code supports old-style Athena ~luser/.klogin
+ * file entries.  See the file "kparse.c".
+ */
+
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_KLOGIN)
+
+#include <kparse.h>
+
+/*
+ * The parmtable defines the keywords we will recognize with their
+ * default values, and keeps a pointer to the found value.  The found
+ * value should be filled in with strsave(), since FreeParameterSet()
+ * will release memory for all non-NULL found strings. 
+ *
+*** NOTE WELL! *** 
+ *
+ * The table below is very nice, but we cannot hard-code a default for the
+ * realm: we have to get the realm via krb_get_lrealm().  Even though the
+ * default shows as "from krb_get_lrealm, below", it gets changed in
+ * kuserok to whatever krb_get_lrealm() tells us.  That code assumes that
+ * the realm will be the entry number in the table below, so if you
+ * change the order of the entries below, you have to change the
+ * #definition of REALM_SCRIPT to reflect it. 
+ */
+#define REALM_SUBSCRIPT 1
+parmtable kparm[] = {
+
+/* keyword	default 			found value     */
+{"user",	"", 				(char *) NULL},
+{"realm",	"see krb_get_lrealm, below",	(char *) NULL},
+{"instance",	 "",				(char *) NULL},
+};
+#define KPARMS kparm,PARMCOUNT(kparm)
+#endif
+
+int KRB5_CALLCONV
+kuserok(kdata, luser)
+    AUTH_DAT	*kdata;
+    char	*luser;
+{
+    struct stat sbuf;
+    struct passwd *pwd;
+    char pbuf[MAXPATHLEN];
+    int isok = NOTOK, rc;
+    FILE *fp;
+    char kuser[MAX_USERNAME];
+    char principal[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+    char linebuf[BUFSIZ];
+    char *newline;
+    int gobble;
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_KLOGIN)
+    char local_realm[REALM_SZ];
+#endif
+
+    /* no account => no access */
+    if ((pwd = getpwnam(luser)) == NULL) {
+	return(NOTOK);
+    }
+    if (strlen (pwd->pw_dir) + sizeof ("/.klogin") >= sizeof (pbuf))
+	return NOTOK;
+    (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
+    pbuf[sizeof(pbuf) - 1] = '\0';
+    (void) strncat(pbuf, "/.klogin", sizeof(pbuf) - 1 - strlen(pbuf));
+
+    if (access(pbuf, F_OK)) {	 /* not accessible */
+	/*
+	 * if he's trying to log in as himself, and there is no .klogin file,
+	 * let him.  To find out, call
+	 * krb_kntoln to convert the triple in kdata to a name which we can
+	 * string compare. 
+	 */
+	if (!krb_kntoln(kdata, kuser) && (strcmp(kuser, luser) == 0)) {
+	    return(OK);
+	}
+    }
+    /* open ~/.klogin */
+    if ((fp = fopen(pbuf, "r")) == NULL) {
+        /* however, root might not have enough access, so temporarily switch
+	 * over to the user's uid, try the access again, and switch back
+	 */
+        if(getuid() == 0) {
+	  uid_t old_euid = geteuid();
+	  if (seteuid(pwd->pw_uid) < 0)
+	      return NOTOK;
+	  fp = fopen(pbuf, "r");
+	  if (seteuid(old_euid) < 0)
+	      return NOTOK;
+	  if ((fp) == NULL) {
+	    return(NOTOK);
+	  }
+	} else {
+	  return(NOTOK);
+	}
+    }
+    /*
+     * security:  if the user does not own his own .klogin file,
+     * do not grant access
+     */
+    if (fstat(fileno(fp), &sbuf)) {
+	fclose(fp);
+	return(NOTOK);
+    }
+    /*
+     * however, allow root to own the .klogin file, to allow creative
+     * access management schemes.
+     */
+    if (sbuf.st_uid && (sbuf.st_uid != pwd->pw_uid)) {
+	fclose(fp);
+	return(NOTOK);
+    }
+
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_KLOGIN)
+    /* Accept old-style .klogin files */
+
+    /*
+     * change the default realm from the hard-coded value to the
+     * accepted realm that Kerberos specifies. 
+     */
+    rc = krb_get_lrealm(local_realm, 1);
+    if (rc == KSUCCESS)
+	kparm[REALM_SUBSCRIPT].defvalue = local_realm;
+    else
+	return (rc);
+
+    /* check each line */
+    while ((isok != OK) && (rc = fGetParameterSet(fp, KPARMS)) != PS_EOF) {
+	switch (rc) {
+	case PS_BAD_KEYWORD:
+	case PS_SYNTAX:
+	    while (((gobble = fGetChar(fp)) != EOF) && (gobble != '\n'));
+	    break;
+
+	case PS_OKAY:
+	    isok = (ParmCompare(KPARMS, "user", kdata->pname) ||
+		    ParmCompare(KPARMS, "instance", kdata->pinst) ||
+		    ParmCompare(KPARMS, "realm", kdata->prealm));
+	    break;
+
+	default:
+	    break;
+	}
+	FreeParameterSet(kparm, PARMCOUNT(kparm));
+    }
+    /* reset the stream for parsing new-style names, if necessary */
+    rewind(fp);
+#endif
+
+    /* check each line */
+    while ((isok != OK) && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
+	/* null-terminate the input string */
+	linebuf[BUFSIZ-1] = '\0';
+	newline = NULL;
+	/* nuke the newline if it exists */
+	if ((newline = strchr(linebuf, '\n')))
+	    *newline = '\0';
+
+	/* Default the fields (default realm is filled in later) */
+	principal[0] = '\0';
+	inst[0] = '\0';
+	realm[0] = '\0';
+	rc = kname_parse(principal, inst, realm, linebuf);
+	if (rc == KSUCCESS) {
+	    if (realm[0] == '\0') {
+		rc = krb_get_lrealm(realm, 1);
+		if (rc != KSUCCESS)
+		    goto nextline;
+	    }
+	    isok = (strncmp(kdata->pname, principal, ANAME_SZ) ||
+		    strncmp(kdata->pinst, inst, INST_SZ) ||
+		    strncmp(kdata->prealm, realm, REALM_SZ));
+	}
+    nextline:
+	/* clean up the rest of the line if necessary */
+	if (!newline)
+	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
+    }
+    fclose(fp);
+    return(isok);
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/krb4/libkrb4.exports b/krb5-1-6/src/lib/krb4/libkrb4.exports
new file mode 100644
index 000000000..ff35a4684
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/libkrb4.exports
@@ -0,0 +1,165 @@
+FreeParameterSet
+ParmCompare
+__krb_sendauth_hidden_tkt_len
+ad_print
+afs_passwd_to_key
+cr_err_reply
+create_auth_reply
+create_ciph
+decomp_ticket
+decomp_tkt_krb5
+dest_tkt
+et_kadm_error_table
+et_krb_error_table
+fGetChar
+fGetKeywordValue
+fGetLiteral
+fGetParameterSet
+fGetToken
+fUngetChar
+fgetst
+get_ad_tkt
+get_pw_tkt
+get_service_key
+getst
+in_tkt
+initialize_kadm_error_table
+initialize_krb_error_table
+k_gethostname
+k_isinst
+k_isname
+k_isrealm
+kadm_build_field_header
+kadm_check_field_header
+kadm_cli_conn
+kadm_cli_disconn
+kadm_cli_keyd
+kadm_cli_out
+kadm_cli_send
+kadm_init_link
+kadm_stream_to_vals
+kadm_stv_char
+kadm_stv_long
+kadm_stv_short
+kadm_stv_string
+kadm_vals_to_stream
+kadm_vts_char
+kadm_vts_long
+kadm_vts_short
+kadm_vts_string
+klog
+kname_parse
+kname_unparse
+krb4int_address_less
+krb4int_et_fini
+krb4int_et_init
+krb4int_save_credentials_addr
+krb4int_send_to_kdc_addr
+krb4int_strnlen
+krb4prot_decode_ciph
+krb4prot_decode_error
+krb4prot_decode_header
+krb4prot_decode_kdc_reply
+krb4prot_decode_kdc_request
+krb4prot_decode_naminstrlm
+krb4prot_encode_apreq
+krb4prot_encode_authent
+krb4prot_encode_ciph
+krb4prot_encode_err_reply
+krb4prot_encode_kdc_reply
+krb4prot_encode_kdc_request
+krb4prot_encode_naminstrlm
+krb4prot_encode_tkt
+krb54_get_service_keyblock
+krb5__krb4_context
+krb5_passwd_to_key
+krb__get_cnffile
+krb__get_realmsfile
+krb__get_srvtabname
+krb_ap_req_debug
+krb_change_password
+krb_check_auth
+krb_clear_key_krb5
+krb_cr_tkt_krb5
+krb_create_ticket
+krb_debug
+krb_end_session
+krb_err_txt
+krb_free_preauth
+krb_get_admhst
+krb_get_cred
+krb_get_default_user
+krb_get_err_text
+krb_get_in_tkt
+krb_get_in_tkt_creds
+krb_get_in_tkt_preauth
+krb_get_in_tkt_preauth_creds
+krb_get_keyprocs
+krb_get_kpasswdhst
+krb_get_krbhst
+krb_get_lrealm
+krb_get_phost
+krb_get_profile
+krb_get_pw_in_tkt
+krb_get_pw_in_tkt_creds
+krb_get_pw_in_tkt_preauth
+krb_get_svc_in_tkt
+krb_get_svc_in_tkt_preauth
+krb_get_tf_fullname
+krb_get_tf_realm
+krb_get_ticket_for_service
+krb_ignore_ip_address
+krb_in_tkt
+krb_kntoln
+krb_life_to_time
+krb_log
+krb_mk_auth
+krb_mk_err
+krb_mk_preauth
+krb_mk_priv
+krb_mk_req
+krb_mk_req_creds
+krb_mk_safe
+krb_net_rd_sendauth
+krb_net_read
+krb_net_write
+krb_rd_err
+krb_rd_preauth
+krb_rd_priv
+krb_rd_req
+krb_rd_req_int
+krb_rd_safe
+krb_realmofhost
+krb_recvauth
+krb_save_credentials
+krb_sendauth
+krb_set_default_user
+krb_set_key
+krb_set_key_krb5
+krb_set_lifetime
+krb_set_logfile
+krb_set_tkt_string
+krb_start_session
+krb_stime
+krb_svc_init
+krb_svc_init_preauth
+krb_time_to_life
+kset_logfile
+kuserok
+mit_passwd_to_key
+month_sname
+pkt_cipher
+pkt_clen
+private_msg_ver
+put_svc_key
+read_service_key
+send_to_kdc
+swap_bytes
+tf_close
+tf_get_cred
+tf_get_pinst
+tf_get_pname
+tf_init
+tf_save_cred
+tkt_string
+unix_time_gmt_unixsec
diff --git a/krb5-1-6/src/lib/krb4/lifetime.c b/krb5-1-6/src/lib/krb4/lifetime.c
new file mode 100644
index 000000000..826e090df
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/lifetime.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000, 2001, 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "krb.h"
+#include "k5-int.h"
+
+/*
+ * krb_life_to_time
+ *
+ * Given a start date and a lifetime byte, compute the expiration
+ * date.
+ */
+KRB4_32 KRB5_CALLCONV
+krb_life_to_time(KRB4_32 start, int life)
+{
+    krb5int_access k5internals;
+
+    if (krb5int_accessor(&k5internals, KRB5INT_ACCESS_VERSION)
+	|| k5internals.krb_life_to_time == NULL)
+	return start;
+    return k5internals.krb_life_to_time(start, life);
+}
+
+/*
+ * krb_time_to_life
+ *
+ * Given the start date and the end date, compute the lifetime byte.
+ * Round up, since we can adjust the start date backwards if we are
+ * issuing the ticket to cause it to expire at the correct time.
+ */
+int KRB5_CALLCONV
+krb_time_to_life(KRB4_32 start, KRB4_32 end)
+{
+    krb5int_access k5internals;
+
+    if (krb5int_accessor(&k5internals, KRB5INT_ACCESS_VERSION)
+	|| k5internals.krb_time_to_life == NULL)
+	return 0;
+    return k5internals.krb_time_to_life(start, end);
+}
diff --git a/krb5-1-6/src/lib/krb4/log.c b/krb5-1-6/src/lib/krb4/log.c
new file mode 100644
index 000000000..ada6fdfe0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/log.c
@@ -0,0 +1,148 @@
+/*
+ * lib/krb4/log.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifdef KRB_CRYPT_DEBUG
+/* This file used to contain log() and set_logfile(). If you define 
+   KRB_CRYPT_DEBUG, you'll need to define those to point to krb_log and
+   krb_set_logfile, or change all the invokers. */
+#endif
+
+#include "krb.h"
+#include "autoconf.h"
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#if !defined(VMS) && !defined(_WIN32)
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "krb4int.h"
+#include <klog.h>
+
+static char *log_name = KRBLOG;
+#if 0
+static is_open;
+#endif
+
+/*
+ * This file contains three logging routines: set_logfile()
+ * to determine the file that log entries should be written to;
+ * and log() and new_log() to write log entries to the file.
+ */
+
+/*
+ * krb_log() is used to add entries to the logfile (see krb_set_logfile()
+ * below).  Note that it is probably not portable since it makes
+ * assumptions about what the compiler will do when it is called
+ * with less than the correct number of arguments which is the
+ * way it is usually called.
+ *
+ * The log entry consists of a timestamp and the given arguments
+ * printed according to the given "format".
+ *
+ * The log file is opened and closed for each log entry.
+ *
+ * The return value is undefined.
+ */
+
+void krb_log(const char *format,...)
+{
+    FILE *logfile;
+    time_t now;
+    struct tm *tm;
+    va_list args;
+
+    va_start(args, format);
+
+    if ((logfile = fopen(log_name,"a")) != NULL) {
+	(void) time(&now);
+	tm = localtime(&now);
+
+	fprintf(logfile,"%2d-%s-%d %02d:%02d:%02d ",tm->tm_mday,
+		month_sname(tm->tm_mon + 1),1900+tm->tm_year,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+	vfprintf(logfile,format,args);
+	fprintf(logfile,"\n");
+	(void) fclose(logfile);
+    }
+    va_end(args);
+    return;
+}
+
+/*
+ * krb_set_logfile() changes the name of the file to which
+ * messages are logged.  If krb_set_logfile() is not called,
+ * the logfile defaults to KRBLOG, defined in "krb.h".
+ */
+
+void
+krb_set_logfile(filename)
+    char *filename;
+{
+    log_name = filename;
+#if 0
+    is_open = 0;
+#endif
+}
+
+#if 0
+/*
+ * new_log() appends a log entry containing the give time "t" and the
+ * string "string" to the logfile (see set_logfile() above).  The file
+ * is opened once and left open.  The routine returns 1 on failure, 0
+ * on success.
+ */
+
+krb_new_log(t,string)
+    long t;
+    char *string;
+{
+    static FILE *logfile;
+
+    struct tm *tm;
+
+    if (!is_open) {
+        if ((logfile = fopen(log_name,"a")) == NULL) return(1);
+        is_open = 1;
+    }
+
+    if (t) {
+        tm = localtime(&t);
+
+        fprintf(logfile,"\n%2d-%s-%d %02d:%02d:%02d  %s",tm->tm_mday,
+                month_sname(tm->tm_mon + 1),1900+tm->tm_year,
+                tm->tm_hour, tm->tm_min, tm->tm_sec, string);
+    }
+    else {
+        fprintf(logfile,"\n%20s%s","",string);
+    }
+
+    (void) fflush(logfile);
+    return(0);
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb4/mac_glue.c b/krb5-1-6/src/lib/krb4/mac_glue.c
new file mode 100644
index 000000000..77d11c2cc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mac_glue.c
@@ -0,0 +1,48 @@
+/*
+ * mac_glue.c
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Macintosh ooperating system interface for Kerberos.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+
+/* Mac Cincludes */
+#include <string.h>
+#include <stddef.h>
+
+/* FIXME!  swab should be swapping, but for initial test, don't bother.  */
+
+void swab(char *from, char *to, int nbytes) {}
+
+mymemset( void *s, register int c, register size_t n )
+{
+	// written because memset doesn't work in think C (ARGGGG!!!!!!)
+	register char *j = s;
+	while( n-- )
+		*j++ = c;
+}
+
+int INTERFACE
+krb_start_session (x)
+	char *x;
+{
+	return KSUCCESS;
+}
+
+int INTERFACE
+krb_end_session (x)
+	char *x;
+{
+	return KSUCCESS;
+}
+
+/* FIXME:  These stubs should go away.  */
+int read() {return 0;}
+int write () {return 0;}
+int krb_ignore_ip_address = 0;
diff --git a/krb5-1-6/src/lib/krb4/mac_store.c b/krb5-1-6/src/lib/krb4/mac_store.c
new file mode 100644
index 000000000..262ba58bd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mac_store.c
@@ -0,0 +1,731 @@
+/*
+ * mac_store.c
+ *
+ * Kerberos configuration store
+ * Originally coded by Tim Miller / Brown University as KRB_Store.c
+ * Mods 1/92 By Peter Bosanko
+ *
+ * Modified May-June 1994 by Julia Menapace and John Gilmore
+ * of Cygnus Support.
+ *
+ * This file incorporates replacements for the Unix files
+ * g_admhst.c, g_krbhst.c, realmofhost.c, and g_krbrlm.c.
+ */
+
+/* Headers from in_tkt.c, merged in by gnu FIXME */
+#include <types.h>
+
+/* Headers from store.c from KClient */
+#include <string.h>
+#include <traps.h>
+#include <gestaltEqu.h>
+#include <Folders.h>
+#include <Resources.h>
+#include <Memory.h>
+#include <Files.h>
+
+#include "krb.h"
+#include "mac_store.h"	/* includes memcache.h */
+#include "krb_driver.h"
+
+#define	prefname	"\pKerberos Client Preferences"
+const	OSType	preftype = 'PREF';
+const	OSType	prefcrea	= 'krbL';
+const	OSType	unametype = 'UNam';
+const	OSType	lrealmtype = 'LRlm';
+const	OSType	templatetype = 'TMPL';
+const	OSType	realmmaptype = 'RMap';
+const	OSType	servermaptype = 'SMap';
+#define kNumTemplates 4
+#define kFirstTemplate 128
+#define kMapResNum 1024
+
+
+/* Lower level routines and data structures  */
+
+
+/* Need to check this in each high-level routine, and call init_store
+   if not set.  */
+static	int		initialized_store = 0;		
+
+static	char		fLRealm[REALM_SZ] = "";
+static	Handle		fRealmMap = 0;
+static	Handle		fServerMap = 0;
+static	short		fPrefVRefNum;
+static	long		fPrefDirID;
+OSErr			fConstructErr = -1;
+
+/* Current default user name (for prompts, etc).  */
+
+static char gUserName[MAX_K_NAME_SZ]; 
+
+
+/* Routines for dealing with the realm versus host database */
+
+/*
+ * krb_get_admhst
+ *
+ * Given a Kerberos realm, find a host on which the Kerberos database
+ * administration server can be found.
+ *
+ * krb_get_admhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer n, and
+ * returns (in h) the nth administrative host entry from the configuration
+ * file (KRB_CONF, defined in "krb.h") associated with the specified realm.
+ * If ATHENA_CONF_FALLBACK is defined, also look in old location.
+ *
+ * On error, get_admhst returns KFAILURE. If all goes well, the routine
+ * returns KSUCCESS.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst().
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * a Kerberos admin server.  In the long run, this functionality will be
+ * provided by a nameserver.  (HAH!)
+ */
+int
+krb_get_admhst (h, r, n)
+	char *h;
+	char *r;
+	int n;
+{
+	if (!initialized_store) 
+		if (init_store())
+			return KFAILURE;
+	if(GetNthServer(n, r, 1, h)) return KFAILURE;
+	else return KSUCCESS;
+}
+
+/*
+ * Given a Kerberos realm, find a host on which the Kerberos authenti-
+ * cation server can be found.
+ *
+ * krb_get_krbhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer, n, and
+ * returns (in h) the nth entry from the configuration information
+ * associated with the specified realm.
+ *
+ * If no info is found, krb_get_krbhst returns KFAILURE.  If n=1 and the
+ * configuration file does not exist, krb_get_krbhst will return KRB_HOST
+ * (defined in "krb.h").  If all goes well, the routine returnes
+ * KSUCCESS.
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * kerberos.  In the long run, this functionality will be provided by a
+ * nameserver.  (AH SO!)
+ */
+int	krb_get_krbhst(h, r, n)
+	char *h;
+	char *r;
+	int n;
+{
+	if (!initialized_store) 
+		if (init_store())
+			return KFAILURE;
+	if (GetNthServer(n, r, 0, h)) return KFAILURE;
+	else return KSUCCESS;
+}
+
+
+/*
+ * krb_get_lrealm takes a pointer to a string, and a number, n.  It fills
+ * in the string, r, with the name of the local realm specified in
+ * the local Kerberos configuration.
+ * It returns 0 (KSUCCESS) on success, and KFAILURE on failure.  If the
+ * config info does not exist, and if n=1, a successful return will occur
+ * with r = KRB_REALM (also defined in "krb.h").  [FIXME -- not implem.]
+ *
+ * NOTE: for archaic & compatibility reasons, this routine will only return
+ * valid results when n = 1.
+ */
+
+int	krb_get_lrealm(char *r, int n)
+{
+	if (!initialized_store) 
+		if (init_store())
+			return KFAILURE;
+	if (n != 1)
+		return KFAILURE;
+	if (GetLocalRealm(r))
+		return KFAILURE;
+	return KSUCCESS;
+}
+
+
+/*
+ * krb_realmofhost.
+ * Given a fully-qualified domain-style primary host name,
+ * return the name of the Kerberos realm for the host.
+ * If the hostname contains no discernable domain, or an error occurs,
+ * return the local realm name, as supplied by get_krbrlm().
+ * If the hostname contains a domain, but no translation is found,
+ * the hostname's domain is converted to upper-case and returned.
+ *
+ * In the database,
+ * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
+ * host names should be in the usual form (e.g. FOO.BAR.BAZ)
+ */
+
+char *krb_realmofhost(char *host)
+{
+	static char	realm[REALM_SZ];
+	
+	if (!initialized_store) 
+		if (init_store())
+			return 0;
+
+	/* Store realm string through REALM pointer arg */
+	GetRealm(host, realm);	
+	return realm;
+}
+
+
+char * INTERFACE
+krb_get_default_user (void)
+{
+    if (!initialized_store)
+	if (init_store())
+	    return 0;
+
+    return gUserName;
+}
+
+
+int INTERFACE
+krb_set_default_user (uName)
+    char* uName;
+{
+    if (!initialized_store)
+	if (init_store())
+	    return KFAILURE;
+
+    if( strcmp( gUserName, uName ) != 0 ) {
+	strcpy( gUserName, uName );
+	if (WriteUser() != 0)
+	    return KFAILURE;
+    }
+    return KSUCCESS;
+}
+
+
+
+void GetPrefsFolder(short *vRefNumP, long *dirIDP)
+{
+	Boolean hasFolderMgr = false;
+	long feature;
+/*	
+	FIXME Error:   Ô_GestaltDispatchÕ has not been declared - not needed now? - jcm
+	if (TrapAvailable(_GestaltDispatch)) 
+*/
+	if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true;
+	if (!hasFolderMgr) {
+		GetSystemFolder(vRefNumP, dirIDP);
+		return;
+		}
+	else {
+		if (FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
+			*vRefNumP = 0;
+			*dirIDP = 0;
+			}
+		}
+	}
+
+
+/*
+    init_store() is used to initialize the config store.  It opens the
+    driver preferences file and reads the local realm, user name, and
+    realm and server maps from resources in the prefs file into driver
+    storage.  If the preferences file doesn't exist, init_store creates it.
+    Returns 0 on success, or 1 if something goes wrong.
+ */
+int
+init_store()
+{
+	short refnum;
+	Handle	temp;
+	int hasPrefFile;
+	
+	/* If a prefs file exists, load from it, otherwise load defaults from self */
+	GetPrefsFolder(&fPrefVRefNum, &fPrefDirID);
+	refnum = HOpenResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, fsRdPerm);
+	hasPrefFile = (refnum != -1); 		// did we open it?
+	
+	temp = GetResource(lrealmtype, kMapResNum);
+	if(ResError() || !temp) {
+		if(refnum != -1) CloseResFile(refnum);
+		fConstructErr = cKrbCorruptedFile;
+		return 1;
+	}
+	strcpy(fLRealm, *temp);
+	ReleaseResource(temp);
+	
+	temp = GetResource(unametype, kMapResNum);
+	if(ResError() || !temp) {
+		if(refnum != -1) CloseResFile(refnum);
+		fConstructErr = cKrbCorruptedFile;
+		return 1;
+	}
+	strcpy(gUserName, *temp);
+	ReleaseResource(temp);
+	
+	fRealmMap = GetResource(realmmaptype, kMapResNum);
+	if(ResError() || !fRealmMap) {
+		if(refnum != -1) CloseResFile(refnum);
+		*fLRealm = 0;
+		fConstructErr = cKrbCorruptedFile;
+		return 1;
+	}
+	DetachResource(fRealmMap);
+	
+	fServerMap = GetResource(servermaptype, kMapResNum);
+	if(ResError() || !fServerMap) {
+		if(refnum != -1) CloseResFile(refnum);
+		*fLRealm = 0;
+		DisposeHandle(fRealmMap);
+		fRealmMap = 0;
+		fConstructErr = cKrbCorruptedFile;
+		return 1;
+	}
+	DetachResource(fServerMap);
+	
+	if(refnum != -1) CloseResFile(refnum);
+	fConstructErr = noErr;
+	
+	if (!hasPrefFile) {
+		fConstructErr = CreatePrefFile();		// make prefs file if we need to
+	}
+	
+	initialized_store = 1;
+	return 0;
+}
+
+
+/****************Private routines******************/
+
+OSErr	OpenPrefsFile(short *refnum)
+{
+	*refnum = HOpenResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, fsRdWrPerm);
+	
+	if(ResError()) {	/* doesn't exist, create it */
+		FInfo	fndrinfo;
+		
+		HCreateResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname);
+		if(ResError()) {
+			return ResError();
+			}
+		*refnum = HOpenResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, fsRdWrPerm);
+		if(ResError()) {
+			return ResError();
+			}
+		HGetFInfo(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, &fndrinfo); 
+		fndrinfo.fdCreator = prefcrea;
+		fndrinfo.fdType = preftype;
+		HSetFInfo(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, &fndrinfo); 
+		}
+	
+	return noErr;
+	}
+
+
+
+OSErr	CreatePrefFile()
+{
+	short	refnum, i;
+	OSErr	err;
+	Handle	tmpls[ kNumTemplates ];
+
+	// Get all the templates for ResEdit
+	for( i = 0; i < kNumTemplates; i++ ) {
+		tmpls[i] = GetResource( templatetype, kFirstTemplate + i );
+		if( ResError() || !tmpls[i] ) return cKrbCorruptedFile;
+	}
+	
+	err = OpenPrefsFile( &refnum );
+	if( err ) return err;
+	
+	// write out the templates
+	for( i = 0; i < kNumTemplates && !err; i++ ) {
+		short	tmplid;
+		ResType	theType;
+		Str255	resName;
+
+		GetResInfo( tmpls[i], &tmplid, &theType, resName );
+		err = WritePref( refnum, tmpls[i], templatetype, tmplid, resName );	
+		ReleaseResource( tmpls[i] );
+	}
+
+	if( !err )
+		err = WritePref( refnum, fRealmMap, realmmaptype, kMapResNum, "\p" );	
+	if( !err )
+		err = WritePref( refnum, fServerMap, servermaptype, kMapResNum, "\p" );	
+	if( !err )
+		err = WritePrefStr( refnum, fLRealm, lrealmtype, kMapResNum, "\p" );	
+	if( !err )
+		err = WritePrefStr( refnum, gUserName, unametype, kMapResNum, "\p" );	
+
+	CloseResFile( refnum );
+	if( !err ) err = ResError();
+	return err;
+}
+
+OSErr	WriteUser()
+{
+	short	refnum;
+	OSErr	err;
+
+	err = OpenPrefsFile( &refnum );
+	if( err ) return err;
+
+	err = WritePrefStr( refnum, gUserName, unametype, kMapResNum, "\p" );	
+
+	CloseResFile( refnum );
+	if( !err ) err = ResError();
+	return err;
+}
+
+OSErr	WritePref( short refnum, Handle dataHandle, OSType mapType, short resID, Str255 resName )
+{
+	OSErr	err;
+	Handle	resHandle;
+
+	resHandle = Get1Resource( mapType, resID );
+	if( !resHandle ) {								// create a new resource:
+		resHandle = dataHandle;
+		err = HandToHand( &resHandle );				// copy the data handle
+		if( err != noErr ) return err;
+
+		AddResource( resHandle, mapType, resID, resName );
+		if( ( err = ResError() ) != noErr ) {
+			DisposHandle( resHandle );
+			return err;
+		}
+		SetResAttrs( resHandle, resSysHeap | GetResAttrs( resHandle ) );
+	}
+	else {											/* modify an existing resource: */
+		Size handleSize = GetHandleSize( dataHandle );
+		SetHandleSize( resHandle, handleSize );
+		if( ( err = MemError() ) != noErr ) {
+			ReleaseResource( resHandle );
+			return err;
+		}
+		BlockMove( *dataHandle, *resHandle, handleSize );
+		ChangedResource( resHandle );
+		if( ( err = ResError() ) != noErr ) {
+			ReleaseResource( resHandle );
+			return err;
+		}
+	}
+
+	UpdateResFile( refnum );
+	err = ResError();
+	ReleaseResource( resHandle );
+	return err;
+}
+
+OSErr	WritePrefStr( short refnum, char *dataString, OSType mapType, short resID, Str255 resName )
+{
+	OSErr		err;
+	Handle	dataHandle;
+
+	err = PtrToHand( dataString, &dataHandle, strlen( dataString ) + 1 );
+	if( err == noErr ) {
+		err = WritePref( refnum, dataHandle, mapType, resID, resName );
+		DisposHandle( dataHandle );
+	}
+	return err;
+}
+	
+OSErr	WriteRealmMap()
+{
+	short	refnum;
+	OSErr	err;
+	
+	err = OpenPrefsFile( &refnum );
+	if( err ) return err;
+		
+ 	err = WritePref( refnum, fRealmMap, realmmaptype, kMapResNum, "\p" );	
+
+	CloseResFile( refnum );
+	if( !err ) err = ResError();
+	return err;
+}
+
+OSErr	WriteServerMap()
+{
+	short	refnum;
+	OSErr	err;
+	
+	err = OpenPrefsFile(&refnum);
+	if( err ) return err;
+	
+	err = WritePref( refnum, fServerMap, servermaptype, kMapResNum,"\p" );	
+
+	CloseResFile( refnum );
+	if( !err ) err = ResError();
+	return err;
+}
+
+OSErr	GetLocalRealm(char *lrealm)
+{
+	if (!initialized_store)
+		init_store();
+	
+	strcpy(lrealm, fLRealm);
+	return noErr;
+	}
+
+OSErr	SetLocalRealm( const char *lrealm )
+{
+	short	refnum;
+	OSErr	err;
+		
+	if (!initialized_store)
+		init_store();
+	
+	strcpy( fLRealm, (char *) lrealm );
+	
+	err = OpenPrefsFile( &refnum );
+	if( err ) return err;
+	
+	err = WritePrefStr( refnum, fLRealm, lrealmtype, kMapResNum, "\p" );	
+
+	CloseResFile( refnum );
+	if( !err ) err = ResError();
+	return err;
+}
+
+OSErr	GetRealm(const char *host, char *realm)
+{
+	int	numrealms;
+	char	*curnetorhost, *currealm;
+	char	*domain;
+	
+	if (!initialized_store)
+		init_store();
+	
+	numrealms = *((short *)*fRealmMap);
+	GetLocalRealm(realm);
+	
+	domain = strchr( host, '.');
+	if(!domain) return noErr;
+	
+	curnetorhost = (*fRealmMap) + 2;
+	currealm = strchr(curnetorhost, '\0') + 1;
+	for( ; numrealms > 0; numrealms--) {
+		if(!strcasecmp(curnetorhost, host)) {
+			strcpy(realm, currealm);
+			return noErr;
+			}
+		if(!strcasecmp(curnetorhost, domain)) {
+			strcpy(realm, currealm);
+			}
+		
+		if(numrealms > 1) {
+			curnetorhost = strchr(currealm, '\0') + 1;
+			currealm = strchr(curnetorhost, '\0') + 1;
+			}
+		}
+	
+	return noErr;
+	}
+
+OSErr	AddRealmMap(const char *netorhost, const char *realm)
+{
+	int	numrealms;
+	char	*curptr;
+	
+	SetHandleSize(fRealmMap, strlen(netorhost)+1 + strlen(realm)+1 +
+										GetHandleSize(fRealmMap));
+	if(MemError()) return MemError();
+	
+	numrealms = ++(*((short *)*fRealmMap));
+	
+	for(curptr = (*fRealmMap)+2; numrealms > 1; numrealms--) {
+		curptr = strchr(curptr, '\0') + 1;
+		curptr = strchr(curptr, '\0') + 1;
+		}
+	
+	strcpy(curptr, netorhost);
+	curptr = strchr(curptr, '\0') + 1;
+	strcpy(curptr, realm);
+	
+	return WriteRealmMap();
+	}
+
+OSErr	DeleteRealmMap(const char *netorhost)
+{
+	int	numrealms = *((short *)*fRealmMap);
+	char	*curptr, *fromptr, *nextptr;
+		
+	for(curptr = (*fRealmMap)+2; numrealms > 0; numrealms--) {
+		if(!strcasecmp(curptr, netorhost)) break;	/* got it! */
+		
+		curptr = strchr(curptr, '\0') + 1;
+		curptr = strchr(curptr, '\0') + 1;
+		}
+	
+	if(numrealms == 0) return cKrbMapDoesntExist;
+	
+	*(short*)*fRealmMap -= 1;
+	
+	if(numrealms > 1) {
+		fromptr = strchr(curptr, '\0') + 1;
+		fromptr = strchr(fromptr, '\0') + 1;
+		}
+	
+	for( ; numrealms > 1; numrealms--) {
+		nextptr = strchr(fromptr, '\0') + 1;
+		strcpy(curptr, fromptr);
+		curptr = strchr(curptr, '\0') + 1;
+		fromptr = nextptr;
+		
+		nextptr = strchr(fromptr, '\0') + 1;
+		strcpy(curptr, fromptr);
+		curptr = strchr(curptr, '\0') + 1;
+		fromptr = nextptr;
+		}
+	
+	SetHandleSize(fRealmMap, curptr-(*fRealmMap));
+	if(MemError()) return MemError();
+	return WriteRealmMap();
+	}
+
+OSErr	GetNthRealmMap(const int n, char *netorhost, char *realm)
+{
+	int	i;
+	char	*curptr;
+	
+	if(n > *(short*)*fRealmMap) return cKrbMapDoesntExist;
+	
+	for(curptr = (*fRealmMap) + 2, i = 1; i < n; i++) {
+		curptr = strchr(curptr, '\0') + 1;
+		curptr = strchr(curptr, '\0') + 1;
+		}
+	
+	strcpy(netorhost, curptr);
+	curptr = strchr(curptr, '\0') + 1;
+	strcpy(realm, curptr);
+	
+	return noErr;
+	}
+
+OSErr	GetNthServer(const int n, const char *realm, const int mustadmin,
+										char *server)
+{
+	int	numservers = *(short*)*fServerMap, i = 0;
+	char	*currealm, *curserver;
+	
+	currealm = (*fServerMap) + 2;
+	curserver = strchr(currealm, '\0') + 1 + 1;
+	for( ; numservers > 0; numservers--) {
+		if(!strcmp(currealm, realm)) {
+			if(!mustadmin || *(curserver-1)) i++;
+			if(i >= n) {
+				strcpy(server, curserver);
+				return noErr;
+				}
+			}
+		
+		if(numservers > 1) {
+			currealm = strchr(curserver, '\0') + 1;
+			curserver = strchr(currealm, '\0') + 1 + 1;
+			}
+		}
+
+	return cKrbMapDoesntExist;
+	}
+
+OSErr	AddServerMap(const char *realm, const char *server,
+										const int isadmin)
+{
+	int	numservers;
+	char	*curptr;
+	
+	SetHandleSize(fServerMap, strlen(realm)+1 + 1 + strlen(server)+1 +
+										GetHandleSize(fServerMap));
+	if(MemError()) return MemError();
+	
+	numservers = ++(*((short *)*fServerMap));
+	
+	for(curptr = (*fServerMap)+2; numservers > 1; numservers--) {
+		curptr = strchr(curptr, '\0') + 1 + 1;
+		curptr = strchr(curptr, '\0') + 1;
+		}
+	
+	strcpy(curptr, realm);
+	curptr = strchr(curptr, '\0') + 1;
+	*curptr = (char) isadmin;
+	curptr++;
+	strcpy(curptr, server);
+	
+	return WriteServerMap();
+	}
+
+OSErr	DeleteServerMap(const char *realm, const char *server)
+{
+	int	numservers = *((short *)*fServerMap);
+	char	*curptr, *fromptr, *nextptr;
+		
+	for(curptr = (*fServerMap)+2; numservers > 0; numservers--) {
+		if(!strcmp(curptr, realm)) {
+			nextptr = strchr(curptr, '\0') + 1 + 1;
+			if(!strcasecmp(nextptr, server)) {
+				break;	/* got it! */
+				}
+			}
+		
+		curptr = strchr(curptr, '\0') + 1 + 1;
+		curptr = strchr(curptr, '\0') + 1;
+		}
+	
+	if(numservers == 0) return cKrbMapDoesntExist;
+	
+	*(short*)*fServerMap -= 1;
+	
+	if(numservers > 1) {
+		fromptr = strchr(curptr, '\0') + 1 + 1;
+		fromptr = strchr(fromptr, '\0') + 1;
+		}
+	
+	for( ; numservers > 1; numservers--) {
+		nextptr = strchr(fromptr, '\0') + 1;
+		strcpy(curptr, fromptr);
+		curptr = strchr(curptr, '\0') + 1;
+		fromptr = nextptr;
+		
+		*curptr = *fromptr;
+		curptr++;
+		fromptr++;
+		
+		nextptr = strchr(fromptr, '\0') + 1;
+		strcpy(curptr, fromptr);
+		curptr = strchr(curptr, '\0') + 1;
+		fromptr = nextptr;
+		}
+	
+	SetHandleSize(fServerMap, curptr-(*fServerMap));
+	if(MemError()) return MemError();
+	return WriteServerMap();
+	}
+
+OSErr	GetNthServerMap(const int n, char *realm, char *server, int *admin)
+{
+	int	i;
+	char	*curptr;
+	
+	if(n > *(short*)*fServerMap) return cKrbMapDoesntExist;
+	
+	for(curptr = (*fServerMap) + 2, i = 1; i < n; i++) {
+		curptr = strchr(curptr, '\0') + 1 + 1;
+		curptr = strchr(curptr, '\0') + 1;
+		}
+	
+	strcpy(realm, curptr);
+	curptr = strchr(curptr, '\0') + 1;
+	*admin = *curptr;
+	curptr++;
+	strcpy(server, curptr);
+	
+	return noErr;
+}
diff --git a/krb5-1-6/src/lib/krb4/mac_store.h b/krb5-1-6/src/lib/krb4/mac_store.h
new file mode 100644
index 000000000..b1652dc55
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mac_store.h
@@ -0,0 +1,56 @@
+/*
+	store.h
+		Kerberos credential store
+		Originally coded by Tim Miller / Brown University
+		Mods 1/92 By Peter Bosanko
+
+		Modified May 1994 by Julia Menapace and John Gilmore, Cygnus
+		Support.
+*/
+
+#include "memcache.h"
+
+extern	OSErr		fConstructErr;
+
+		OSErr	CreatePrefFile();
+		OSErr	WriteUser();		/* saves gUserName to prefs file  */
+
+		/* Used internally...  */
+		OSErr	WritePref(short refnum, Handle dataHandle, OSType mapType, short resID,
+							Str255 resName);
+		OSErr	WritePrefStr(short refnum, char *dataString, OSType mapType, short resID,
+							Str255 resName);
+
+			/*** Realm info routines: ***/
+		OSErr	GetLocalRealm(char *lrealm);	/* stuffs local realm in lrealm */
+		OSErr	SetLocalRealm(const char *lrealm);	/* sets local realm */
+
+		OSErr	GetRealm(const char *host, char *realm);	/* yields realm for given
+												host's net name */
+		OSErr	AddRealmMap(const char *netorhost, const char *realm);	/* says hosts
+												with this name or in this domain (if
+												begins with period) map to this realm
+												(provided no more specific map is
+												found) */
+		OSErr	DeleteRealmMap(const char *netorhost);	/* deletes realm map for the
+												net or net hostname */
+		OSErr	GetNthRealmMap(const int n, char *netorhost, char *realm);	/* yields
+												the Nth mapping of a net or host to
+												a kerberos realm */
+
+		OSErr	GetNthServer(const int n, const char *realm, const int mustadmin,
+								char *server);	/* yields Nth (administrating if
+													mustadmin is true) server for
+													the given realm */
+		OSErr	AddServerMap(const char *realm, const char *server,
+								const int isadmin);	/* says this server services this
+												realm (administratively if isadmin) */
+		OSErr	DeleteServerMap(const char *realm, const char *server);	/* deletes
+												the map of this realm to this server */
+		OSErr	GetNthServerMap(const int n, char *realm, char *server, int *admin);
+											/* yields Nth realm-server mapping */
+
+		OSErr		OpenPrefsFile(short *refnum);	/* open (create if necessary) prefs file
+																for writing */
+		OSErr		WriteRealmMap();
+		OSErr		WriteServerMap();
diff --git a/krb5-1-6/src/lib/krb4/mac_stubs.c b/krb5-1-6/src/lib/krb4/mac_stubs.c
new file mode 100644
index 000000000..2cd1f0ac7
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mac_stubs.c
@@ -0,0 +1,525 @@
+/* 
+ * mac_stubs.c
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Macintosh oopserating system stub interface for Kerberos.
+ * Applications call these routines, which then call the driver to do the work.
+ */
+
+#include "krb.h"
+#include "krb_driver.h"	/* Mac driver interface */
+
+#include <string.h>
+#include <stddef.h>
+#include <Files.h>
+#include <Devices.h>
+
+/* We export the driver reference under the name mac_stubs_kdriver,
+   but for convenience throughout this code, we call it "kdriver",
+   which was its name when it was static.  */
+short mac_stubs_kdriver = 0;		/* .Kerberos driver ref */
+#define	kdriver mac_stubs_kdriver
+
+ParamBlockRec pb[1];
+struct krbHiParmBlock khipb[1];
+struct krbParmBlock klopb[1];
+
+short lowcall (long cscode, krbParmBlock *klopb, short kdriver)
+{
+	short s;
+	ParamBlockRec pb;
+	
+	memset (&pb, 0, sizeof(ParamBlockRec));
+	*(long *)pb.cntrlParam.csParam = (long)klopb;
+	pb.cntrlParam.ioCompletion = nil;
+	pb.cntrlParam.ioCRefNum = kdriver;
+	pb.cntrlParam.csCode = cscode;
+	
+	if (s = PBControl(&pb, false))
+		return KFAILURE;
+	if (s = pb.cntrlParam.ioResult)
+		return -(s - cKrbKerberosErrBlock);	/* Restore krb err code from driver err */
+
+	return KSUCCESS;
+}
+
+
+short hicall (long cscode, krbHiParmBlock *khipb, short kdriver)
+{
+	short s;
+	ParamBlockRec pb;
+	memset(&pb, 0, sizeof(ParamBlockRec));
+	*(long *)pb.cntrlParam.csParam = (long)khipb;
+	pb.cntrlParam.ioCompletion = nil;
+	pb.cntrlParam.ioCRefNum = kdriver;
+
+	pb.cntrlParam.csCode = cscode;
+	if (s = PBControl(&pb, false))
+		return KFAILURE;
+	if (s = pb.cntrlParam.ioResult)
+		return -(s - cKrbKerberosErrBlock);	/* Restore krb err code from driver err */
+
+	return KSUCCESS;
+}
+
+
+int INTERFACE
+krb_start_session (x)
+	char *x;
+{
+	short s;
+	
+	/*
+	 * Open the .Kerberos driver if not already open
+	 */
+	if (!kdriver) {
+		s = OpenDriver("\p.Kerberos", &kdriver);
+		if (s) {
+			return KFAILURE;	/* Improve this error code */
+		}
+	}
+
+	return KSUCCESS;
+}
+
+
+int INTERFACE
+krb_end_session (x)
+	char *x;
+{
+	short s;
+
+#if 0 /* This driver doesn't want to be closed.  FIXME, is this OK? */
+	if (kdriver) {
+		s = CloseDriver(kdriver);
+		if (s)
+			return KFAILURE;
+		kdriver = 0;
+	}
+#endif
+	return KSUCCESS;
+}
+
+
+char * INTERFACE
+krb_realmofhost (host)
+	char *host;
+{
+	short s;
+	ParamBlockRec pb;
+	static char realm[REALM_SZ];
+
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->host = host;
+	klopb->uRealm = realm;
+	
+	/* FIXME jcm - no error handling for return value of lowcall in krb_realmofhost */
+	s = lowcall (cKrbGetRealm , klopb, kdriver);
+
+	return realm;
+}
+
+int INTERFACE
+krb_get_lrealm (realm, n)
+	char *realm;
+	int n;
+{
+	short s;
+	ParamBlockRec pb;
+
+	if (n != 1)
+		return KFAILURE;
+
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->uRealm = realm;
+
+	s = lowcall (cKrbGetLocalRealm, klopb, kdriver);
+	return s;
+		
+}
+
+
+int INTERFACE
+kname_parse (name, instance, realm, fullname)
+	char *name, *instance, *realm, *fullname;
+{
+	short s;
+	ParamBlockRec pb;
+
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->uName = name;
+	klopb->uInstance = instance;
+	klopb->uRealm = realm;
+	klopb->fullname = fullname;
+
+	s = lowcall (cKrbKnameParse, klopb, kdriver);
+	return s;
+}
+
+const char* INTERFACE
+krb_get_err_text (error_code)
+	int error_code;
+{
+	short s;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->admin = error_code;	
+	s = lowcall (cKrbGetErrText, klopb, kdriver);
+	if (s != KSUCCESS)
+		return "Error in get_err_text";	
+	return klopb->uName;
+}
+
+
+int INTERFACE
+krb_get_pw_in_tkt(user,instance,realm,service,sinstance,life,password)
+    char *user, *instance, *realm, *service, *sinstance;
+    int life;
+    char *password;
+{
+	short s;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->uName = user;	
+	klopb->uInstance = instance;
+	klopb->uRealm = realm;
+	klopb->sName = service;
+	klopb->sInstance = sinstance;
+	klopb->admin = life;
+	klopb->fullname = password;
+	
+	s = lowcall (cKrbGetPwInTkt, klopb, kdriver);
+	return s;
+}
+
+
+/* FIXME:  For now, we handle the preauth version exactly the same
+   as the non-preauth.   */
+krb_get_pw_in_tkt_preauth(user,instance,realm,service,sinstance,life,password)
+    char *user, *instance, *realm, *service, *sinstance;
+    int life;
+    char *password;
+{
+	short s;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->uName = user;	
+	klopb->uInstance = instance;
+	klopb->uRealm = realm;
+	klopb->sName = service;
+	klopb->sInstance = sinstance;
+	klopb->admin = life;
+	klopb->fullname = password;
+	
+	s = lowcall (cKrbGetPwInTkt, klopb, kdriver);
+	return s;
+}
+
+
+
+char* INTERFACE
+krb_get_default_user (void)
+{
+	short s;
+	static char return_name[MAX_K_NAME_SZ];
+	
+	memset(khipb, 0, sizeof(*khipb));
+	khipb->user = return_name;
+	s = hicall (cKrbGetUserName, khipb, kdriver);
+	if (s != KSUCCESS)
+		return 0;
+	return return_name;
+}
+
+
+int INTERFACE
+krb_set_default_user (uName)
+	char* uName;
+{
+	short s;
+	
+	memset(khipb, 0, sizeof(*khipb));
+	khipb->user = uName;
+	s = hicall (cKrbSetUserName, khipb, kdriver);
+	return s;
+}
+
+int INTERFACE
+krb_get_cred (name, instance, realm, cr)
+	char *name;
+	char *instance;
+	char *realm;
+	CREDENTIALS *cr;
+{
+	short s;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	
+	strcpy(cr->service, name);
+	strcpy(cr->instance, instance);
+	strcpy(cr->realm, realm);
+	
+	klopb->cred = cr;
+
+	s = lowcall (cKrbGetCredentials, klopb, kdriver);
+	return s;
+}
+
+int INTERFACE
+krb_save_credentials (sname, sinstance, srealm, session, 
+			lifetime, kvno,ticket, issue_date)
+	char *sname;		/* service name */
+	char *sinstance;	/* service instance */
+	char *srealm;		/* service realm */
+	C_Block session;	/* Session key */
+	int lifetime;		/* Lifetime */
+	int kvno;			/* Key version number */
+    KTEXT ticket; 	    /* The ticket itself */
+	long issue_date;	/* The issue time */
+	
+{
+	short s;
+	CREDENTIALS cr;
+	
+	strcpy(cr.service, sname);
+	strcpy(cr.instance, sinstance);
+	strcpy(cr.realm, srealm);
+	memcpy(cr.session, session, sizeof(C_Block));
+	cr.lifetime = lifetime;
+	cr.kvno = kvno;
+	cr.ticket_st = *ticket;
+	cr.issue_date = issue_date;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->cred = &cr;
+
+	s = lowcall (cKrbAddCredentials, klopb, kdriver);
+	return s;
+}
+
+
+int INTERFACE
+krb_delete_cred (sname, sinstance, srealm)
+	char *sname;
+	char *sinstance;
+	char *srealm;
+{
+	short s;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	
+	klopb->sName = sname;
+	klopb->sInstance = sinstance;
+	klopb->sRealm = srealm;
+	
+	s = lowcall (cKrbDeleteCredentials, klopb, kdriver);
+	return s;
+}
+
+int INTERFACE
+dest_tkt (cachename)
+	char *cachename;		/* This parameter is ignored. */
+{
+	short s;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	s = lowcall (cKrbDeleteAllSessions, klopb, kdriver);
+	return s;
+}
+
+/* 
+ *	returns service name, service instance and realm of the nth credential. 
+ *  credential numbering is 1 based.
+ */
+
+int INTERFACE
+krb_get_nth_cred (sname, sinstance, srealm, n)
+	char *sname;
+	char *sinstance;
+	char *srealm;
+	int n;
+{
+	short s;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	
+	klopb->sName = sname;
+	klopb->sInstance = sinstance;
+	klopb->sRealm = srealm;
+	klopb->itemNumber = &n;
+	
+	s = lowcall (cKrbGetNthCredentials, klopb, kdriver);
+	return s;
+}
+
+/*
+ * Return the number of credentials in the current credential cache (ticket cache).
+ * On error, returns -1. 
+ */
+int INTERFACE
+krb_get_num_cred ()
+{
+	int s;
+	int n;
+	
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->itemNumber = &n;
+	
+	s = lowcall (cKrbGetNumCredentials, klopb, kdriver);
+	if (s) 
+		return -1;
+	return *(klopb->itemNumber);
+}
+
+
+
+/* GetNthRealmMap
+   yields the Nth mapping of a net or host to a Kerberos realm 
+	  -> itemNumber 	which mapping, traditionally the first
+	  -> host	   		host or net
+	  -> uRealm    		pointer to buffer that will receive realm name
+*/
+
+OSErr INTERFACE
+GetNthRealmMap(n, netorhost, realm)
+	int n;
+	char *netorhost;
+	char *realm;
+{
+	int s;
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->itemNumber = &n;
+	klopb->host = netorhost;
+	klopb->uRealm = realm;
+	
+	s = lowcall (cKrbGetNthRealmMap, klopb, kdriver);
+	return s;
+}
+
+/* GetNthServerMap
+   yields Nth realm-server mapping
+   -> itemNumber		which mapping should be returned
+   -> uRealm			pointer to buffer that will receive realm name	
+   -> host				pointer to buffer that will receive server name
+   -> admin				pointer to admin flag
+ */
+	
+OSErr	INTERFACE
+GetNthServerMap(n, realm, server, admin)	
+    int n;
+    char *realm;
+    char *server; 
+    int *admin;
+{
+	int s;
+	memset(klopb, 0, sizeof(*klopb));
+	klopb->itemNumber = &n;
+	klopb->uRealm = realm;
+	klopb->host = server;
+	klopb->adminReturn = admin;
+
+	s = lowcall (cKrbGetNthServerMap, klopb, kdriver);
+	return s;
+}
+
+
+
+/* krb_get_ticket_for_service
+ * Gets a ticket and returns it to application in buf
+	  -> service		Formal Kerberos name of service
+	  -> buf		Buffer to receive ticket
+	  -> checksum		checksum for this service
+	 <-> buflen		length of ticket buffer (must be at least
+					1258 bytes)
+	 <-  sessionKey		for internal use
+	 <-  schedule		for internal use
+
+ * Result is:
+ *   GC_NOTKT		if there is no matching TGT in the cache
+ *   MK_AP_TGTEXP	if the matching TGT is expired
+ * Other errors possible.  These could cause a dialogue with the user
+ * to get a new TGT.
+ */ 
+
+int INTERFACE
+krb_get_ticket_for_service (serviceName, buf, buflen, checksum, sessionKey,
+		schedule, version, includeVersion)
+	char *serviceName;
+	char *buf;
+	unsigned KRB4_32 *buflen;
+	int checksum;
+	des_cblock sessionKey;
+	Key_schedule schedule;
+	char *version;
+	int includeVersion;
+{
+	short s;
+
+	if (includeVersion)
+		return KFAILURE;		/* Not implmented in the kclient driver iface */
+	
+	memset(khipb, 0, sizeof(*khipb));
+	khipb->service = serviceName;
+	khipb->buf = buf;
+	khipb->buflen = *buflen;
+	khipb->checksum = checksum;
+
+	s = hicall (cKrbGetTicketForService, khipb, kdriver);
+	/* These are ARRAYS in the hiparmblock, for some reason! */
+	memcpy (sessionKey, khipb->sessionKey, sizeof (khipb[0].sessionKey));
+	memcpy (schedule,   khipb->schedule,   sizeof (khipb[0].schedule));
+	*buflen = khipb->buflen;
+	return s;
+}
+
+
+/* 	krb_get_tf_fullname -- return name, instance and realm of the
+	principal in the current ticket file. The ticket file name is not 
+	currently used for anything since there is only one credentials 
+	cache/ticket file
+*/
+
+int INTERFACE
+krb_get_tf_fullname (tktfile, name, instance, realm)
+  char *tktfile;
+  char *name;
+  char *instance;
+  char *realm;
+
+{
+	short s;
+	memset (klopb, 0, sizeof(*klopb));
+	klopb->fullname = tktfile;
+	klopb->uName = name;
+	klopb->uInstance = instance;
+	klopb->uRealm = realm;
+	
+	s = lowcall (cKrbGetTfFullname, klopb, kdriver);
+	return s;
+}
+
+
+
+#if 0
+	xbzero(khipb, sizeof(krbHiParmBlock));
+	khipb->service = (char *)cannon;
+	khipb->buf = (char *)buf;				/* where to build it */
+	khipb->checksum = 0;
+	khipb->buflen = sizeof(buf);
+	if (s = hicall(cKrbGetTicketForService, khipb, kdriver))
+		return s;
+	xbcopy(khipb->sessionKey, sessionKey, sizeof(sessionKey));	/* save the session key */
+	/*
+	 * cKrbGetTicketForService put a longword buffer length into the buffer
+	 * which we don't want, so we ignore it.
+     * Make room for first 3 bytes which preceed the auth data.
+	 */
+	cp = &buf[4-3];						/* skip long, make room for 3 bytes */
+	cp[0] = tp[0];						/* copy type and modifier */
+	cp[1] = tp[1];
+	cp[2] = KRB_AUTH;					/* suboption command */
+	len = khipb->buflen - sizeof(long) + 3; /* data - 4 + 3 */
+
+#endif /* 0 */
diff --git a/krb5-1-6/src/lib/krb4/mac_time.c b/krb5-1-6/src/lib/krb4/mac_time.c
new file mode 100644
index 000000000..bec4d8f53
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mac_time.c
@@ -0,0 +1,152 @@
+/*
+ * mac_time.c
+ * (Originally time_stuff.c)
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Macintosh ooperating system interface for Kerberos.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "des.h"
+#include "AddressXlation.h"	/* for ip_addr */
+#include <time.h>
+#include <sys/time.h>
+
+#include <script.h>			/* Defines MachineLocation, used by getTimeZoneOffset */
+#include <ToolUtils.h>		/* Defines BitTst(), called by getTimeZoneOffset() */
+#include <OSUtils.h>		/* Defines GetDateTime */
+
+/* Mac Cincludes */
+#include <string.h>
+#include <stddef.h>
+
+
+  /*******************************
+  The Unix epoch is 1/1/70, the Mac epoch is 1/1/04.
+
+  70 - 4 = 66 year differential
+
+  Thus the offset is:
+
+  (66 yrs) * (365 days/yr) * (24 hours/day) * (60 mins/hour) * (60 secs/min)
+  plus
+  (17 leap days) * (24 hours/day) * (60 mins/hour) * (60 secs/min)
+
+  Don't forget the offset from GMT.
+  *******************************/
+
+
+/* returns the offset in hours between the mac local time and the GMT  */
+
+unsigned long
+getTimeZoneOffset()
+{
+	MachineLocation		macLocation;
+	long			gmtDelta;
+
+	macLocation.gmtFlags.gmtDelta=0L;
+	ReadLocation(&macLocation); 
+	gmtDelta=macLocation.gmtFlags.gmtDelta & 0x00FFFFFF;
+	if (BitTst((void *)&gmtDelta,23L))	gmtDelta |= 0xFF000000;
+	gmtDelta /= 3600L;
+	return(gmtDelta);
+}
+
+
+/* Returns the GMT in seconds using the Unix epoch, ie. Net time */
+
+static unsigned long
+gettimeofdaynet_no_offset()
+{
+	time_t the_time;
+	
+	GetDateTime (&the_time);
+	the_time = the_time - 
+		((66 * 365 * 24 * 60 * 60) + 
+		      (17 *  24 * 60 * 60) +
+           (getTimeZoneOffset() * 60 * 60));
+	return the_time;
+}
+
+
+
+int	
+gettimeofdaynet (struct timeval *tp, struct timezone *tz)
+{ 
+	tp->tv_sec = gettimeofdaynet_no_offset();
+	return 0;
+}
+
+
+#if 0
+
+int	
+gettimeofdaynet (struct timeval *tp, struct timezone *tz)
+{
+	int result;
+	
+	if (!net_got_offset)
+		result = get_net_offset();
+	else result = 0;
+	
+	time ((time_t *) &(tp->tv_sec));
+
+	tp->tv_sec = tp->tv_sec - (66 * 365 * 24 * 60 * 60
+            + 17 * 60 * 60 * 24) + net_offset;
+
+	return (result);
+}
+
+
+#define TIME_PORT 37
+#define TM_OFFSET 2208988800
+
+/*
+ *
+ *   get_net_offset () -- Use UDP time protocol to figure out the
+ *	offset between what the Mac thinks the time is an what
+ *	the network thinks.
+ *
+ */
+int
+get_net_offset()
+{
+     time_t tv;
+     char buf[512],ts[256];
+     long *nettime;
+     int attempts, cc, time_port;
+     long unixtime;
+	 char	realm[REALM_SZ];
+	 ip_addr	fromaddr;
+	 unsigned short	fromport;
+	 int result;
+	 
+     nettime = (long *)buf;
+	 time_port = TIME_PORT;
+
+	 cc = sizeof(buf);
+	 result = hosts_send_recv(ts, 1, buf, &cc, "", time_port);
+     time (&tv);
+	 
+	 if (result!=KSUCCESS || cc<4) {
+	 	net_offset = 0;
+	 	if (!result) result = 100;
+	 	return result;
+	 }
+						
+     unixtime = (long) ntohl(*nettime) - TM_OFFSET;
+
+     tv  -= 66 * 365 * 24 * 60 * 60
+	  + 17 * 60 * 60 * 24;			/* Convert to unix time w/o offset */
+     net_offset = unixtime - tv;
+     net_got_offset = 1;
+     
+     return 0;
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/krb4/memcache.c b/krb5-1-6/src/lib/krb4/memcache.c
new file mode 100644
index 000000000..18a74126b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/memcache.c
@@ -0,0 +1,891 @@
+/*
+ * memcache.c
+ *
+ * Kerberos credential cache
+ * Originally coded by Tim Miller / Brown University as KRB_Store.c
+ * Mods 1/92 By Peter Bosanko
+ *
+ * Modified May-June 1994 by Julia Menapace and John Gilmore
+ * of Cygnus Support.
+ *
+ * This file incorporates replacements for the Unix files
+ * in_tkt.c, dest_tkt.c, tf_util.c, and tkt_string.c.
+ */
+
+#include "krb.h"
+#include "krb4int.h"
+#include "autoconf.h"
+
+#ifdef _WIN32
+#include <errno.h>
+
+typedef DWORD OSErr;
+#define noErr 0
+#define cKrbCredsDontExist 12001
+#define cKrbSessDoesntExist 12002
+#define memFullErr ENOMEM
+#endif
+
+#ifndef unix
+#ifdef _AIX
+#define unix
+#endif
+#endif
+
+#ifdef unix
+/* Unix interface to memory cache Mac functions.  */
+
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *malloc (), *realloc ();
+#endif
+
+typedef int OSErr;
+#define noErr 0
+#define memFullErr ENOMEM
+
+#endif /* unix */
+
+#include "memcache.h"
+
+
+/* Lower level data structures  */
+
+static	int		fNumSessions = 0;
+static	Session		**fSessions = 0;
+
+#ifndef _WIN32
+#define change_cache()
+#endif
+
+#if defined (_WIN32) || defined (unix)
+/* Fake Mac handles up for general use.  */
+#define	Handle	char **
+#define	Size	int
+
+static OSErr memerror = noErr;
+
+/*
+ * Simulates Macintosh routine by allocating a block of memory
+ * and a pointer to that block of memory.  If the requested block
+ * size is 0, then we just allocate the indirect pointer and 0
+ * it, otherwise we allocate an indirect pointer and place a pointer
+ * to the actual allocated block in the indirect pointer location.
+ */
+Handle 
+NewHandleSys(s)
+	int s;
+{
+	Handle h;
+
+	h = (char **) malloc(sizeof(char *));
+
+	if (h == NULL) {
+		memerror = memFullErr;
+		return (NULL);
+	}
+
+	if (s > 0) {
+		*h = malloc(s);
+
+		if (*h == NULL) {
+			free(h);
+			memerror = memFullErr;
+			return (NULL);
+		}
+	}
+	else
+		*h = NULL;
+
+	memerror = noErr;
+
+	return h;
+}
+
+/*
+ * Frees allocated indirect pointer and the block of memory it points
+ * to.  If the indirect pointer is NULL, then the block is considered
+ * to have 0 length.
+ */
+void
+DisposHandle(h)
+	Handle h;
+{
+	if (*h != NULL)
+		free(*h);
+	free(h);
+}
+
+/*
+ * Resizes a block of memory pointed to by and indirect pointer.  The
+ * indirect pointer is updated when the block of memory is reallocated.
+ * If the indirect pointer is 0, then the block of memory is allocated
+ * rather than reallocated.  If the size requested is 0, then the block
+ * is deallcated rather than reallocated.
+ */
+void
+SetHandleSize(h, s)
+	Handle h;
+	int s;
+{
+	if (*h != NULL) {
+		if (s > 0) {
+			*h = realloc(*h, s);
+			if (*h == NULL) {
+				memerror = memFullErr;
+				return;
+			}
+		}
+		else {
+			free(*h);
+			*h = NULL;
+		}
+	}
+
+	else {
+		if (s > 0) {
+			*h = malloc(s);
+			if (*h == NULL) {
+				memerror = memFullErr;
+				return;
+			}
+		}
+	}
+
+	memerror = noErr;
+}
+
+OSErr
+MemError()
+{
+	return memerror;
+}
+
+#endif /* Windows || unix */
+
+#ifdef _WIN32
+
+/*
+ * change_cache should be called after the cache changes.
+ * If the session count is > 0 it forces the DLL to stay in
+ * memory even after the calling program exits providing cross
+ * session ticket cacheing.  Also a notification message is
+ * is posted out to all top level Windows so that they may
+ * recheck the cache based on the changes made.  The
+ * krb_get_notifcation_message routine will return the
+ * current notificaiton message for the system which an
+ * application can expect to get.
+ */
+void
+change_cache()
+{
+	char fname[260];
+	static BOOL locked = FALSE;
+
+	if (fNumSessions > 0 && !locked) {
+		GetModuleFileName(get_lib_instance(), fname, sizeof(fname));
+		LoadLibrary(fname);
+		locked = TRUE;
+	}
+
+	else if (fNumSessions == 0 && locked) {
+		FreeLibrary(get_lib_instance());
+		locked = FALSE;
+	}
+
+	PostMessage(HWND_BROADCAST, krb_get_notification_message(), 0, 0);
+}
+
+
+/*
+ * Returns a system wide unique notification message.  This
+ * message will be broadcast to all top level windows when
+ * the credential cache changes.
+ */
+unsigned int
+krb_get_notification_message(void)
+{
+	static UINT message = 0;
+
+	if (message == 0)
+		message = RegisterWindowMessage(WM_KERBEROS_CHANGED);
+
+	return message;
+}
+
+
+#endif /* Windows */
+
+
+/* The low level routines in this file are capable of storing
+   tickets for multiple "sessions", each led by a different
+   ticket-granting ticket.  For now, since the top level code
+   doesn't know how to handle that, we are short-cutting all
+   that with a fixed top level identifying tag for the (one)
+   session supported. 
+
+   FIXME jcm - Force one named cache for now for compatibility with
+   Cygnus source tree.  Figure out later how to access the multiple
+   cache functionality in KClient.
+ */
+
+char uname[] = "Fixed User";
+char uinstance[] = "Fixed Instance";
+char urealm[] = "Fixed Realm";
+
+static char curr_auth_uname [ANAME_SZ];
+static char curr_auth_uinst [INST_SZ];
+
+
+/*
+    in_tkt() is used to initialize the ticket cache.
+    It inits the driver's credentials storage, by deleting any tickets.  
+    in_tkt() returns KSUCCESS on success, or KFAILURE if something goes wrong.
+
+    User name, instance and realm are not currently being stored in
+    the credentials cache because currently we are forcing a single
+    named cache by using a fixed user name,inst,and realm in the
+    memcache accessor routines.
+
+    FIXME jcm - needed while stubbing out multi-caching with fixed
+    user etc...  Store currently authenticated user name and instance
+    in this file.  We will use this information to fill out the p_user
+    and p_inst fields in the credential.
+
+    FIXME jcm - more kludges: make sure default user name matches the
+    current credentials cache.  Telnet asks for default user name.  It
+    may have last been set to another user name programmatically or
+    via ResEdit.
+
+ */
+int KRB5_CALLCONV
+in_tkt(pname,pinst)
+    char *pname;
+    char *pinst;
+{
+  int retval;
+	
+  strncpy (curr_auth_uname, pname, ANAME_SZ);
+  strncpy (curr_auth_uinst, pinst, INST_SZ);
+	
+  krb_set_default_user (pname);
+	
+  retval = dest_tkt();
+  if (!retval) 
+    return retval;
+  else 	
+    return KSUCCESS;
+	
+}
+
+int KRB5_CALLCONV
+krb_in_tkt(pname, pinst, prealm)
+    char *pname;
+    char *pinst;
+    char *prealm;
+{
+    return in_tkt(pname, pinst);
+}
+
+/*
+ * dest_tkt() is used to destroy the ticket store upon logout.
+ * If the ticket file does not exist, dest_tkt() returns RET_TKFIL.
+ * Otherwise the function returns RET_OK on success, KFAILURE on
+ * failure.
+ *
+ */
+int KRB5_CALLCONV
+dest_tkt()
+{
+ 	/* 	
+		FIXME jcm - Force one named cache for now for
+		compatibility with Cygnus source tree.  Figure out
+		later how to access the multiple cache functionality in
+		KClient.
+	*/
+	OSErr err;
+ 
+	err = DeleteSession(uname, uinstance, urealm);
+ 
+	change_cache();
+ 
+	switch(err) {
+		case noErr:	
+			return RET_OK;
+		case cKrbSessDoesntExist:
+			return RET_TKFIL;
+		default:
+			return KFAILURE;
+		}
+	}
+
+
+int	dest_all_tkts()		
+{
+	int	i=0;
+	char	name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+	int ndeletes=0;
+	int err=0;
+
+	(void) GetNumSessions(&i);
+	if(!i) return RET_TKFIL;
+
+	for( ; i; i--) {
+		if(!GetNthSession(i, name, inst, realm)) {
+			if (err = DeleteSession(name, inst, realm))
+				break;
+			ndeletes++;
+			}
+		else {
+			err = KFAILURE;
+			break;
+			}
+		}
+
+	if (ndeletes > 0)
+		change_cache();
+
+	if (err)
+		return KFAILURE;
+	else
+		return KSUCCESS;
+	}
+
+
+/* krb_get_tf_realm -- return the realm of the current ticket file. */
+int KRB5_CALLCONV
+krb_get_tf_realm (tktfile, lrealm)
+	char *tktfile;
+	char *lrealm;		/* Result stored through here */
+{
+	
+	return krb_get_tf_fullname(tktfile, (char*) 0, (char*) 0 , lrealm);
+}
+
+
+/* krb_get_tf_fullname -- return name, instance and realm of the
+principal in the current ticket file. */
+int KRB5_CALLCONV
+krb_get_tf_fullname (tktfile, name, instance, realm)
+  char *tktfile;
+  char *name;
+  char *instance;
+  char *realm;
+  
+{
+	OSErr err;
+
+/* 
+	Explaining this ugly hack:
+	uname, uinstance, and urealm in the session record are "fixed" 
+	to short circuit multicache functionality, yielding only one 
+	session/cache for all cases.  This was done under protest to remain 
+	API compatable with UNIX. The principal's and service realm are 
+	always the same and are stored in the same field of the credential. 
+	Principal's name and instance are stored neither in the session 
+	record or the credentials cache but in the file static variables 
+	curr_auth_uname, and curr_auth_uinst as set by in_tkt from its 
+	arguments pname and pinst.  
+	
+   FIXME for multiple sessions -- keep track of which one is
+   the "current" session, as picked by the user.  tktfile not
+   used for anything right now...
+*/
+	   
+	err = GetNthCredentials(uname, uinstance, urealm, name,
+				instance, realm, 1);
+				
+	if (err != noErr) 
+		return NO_TKT_FIL;
+	
+	if (name)
+		strcpy(name, curr_auth_uname);	
+	if (instance)
+		strcpy(instance, curr_auth_uinst);
+
+	return KSUCCESS;
+	
+}
+
+
+/*
+ * krb_get_cred takes a service name, instance, and realm, and a
+ * structure of type CREDENTIALS to be filled in with ticket
+ * information.  It then searches the ticket file for the appropriate
+ * ticket and fills in the structure with the corresponding
+ * information from the file.  If successful, it returns KSUCCESS.
+ * On failure it returns a Kerberos error code.
+ */
+int KRB5_CALLCONV
+krb_get_cred (service, instance, realm, c)
+	char *service;		/* Service name */
+	char *instance;		/* Instance */
+	char *realm;		/* Authorization domain */
+	CREDENTIALS *c;		/* Credentials struct */
+{
+	strcpy(c->service, service);
+	strcpy(c->instance, instance);
+	strcpy(c->realm, realm);
+
+	/* 	
+		FIXME jcm - Force one named cache for now for
+		compatibility with Cygnus source tree.  Figure out
+		later how to access the multiple cache functionality
+		from KClient.
+	*/
+
+	switch(GetCredentials(uname, uinstance, urealm, c)) {
+		case noErr:
+			return KSUCCESS;
+		case cKrbCredsDontExist:
+		case cKrbSessDoesntExist: 
+			return GC_NOTKT;
+		default:
+			return KFAILURE;
+		}
+}
+
+/*
+ * This routine takes a ticket and associated info and 
+ * stores them in the ticket cache.  The peer
+ * routine for extracting a ticket and associated info from the
+ * ticket cache is krb_get_cred().  When changes are made to
+ * this routine, the corresponding changes should be made
+ * in krb_get_cred() as well.
+ *
+ * Returns KSUCCESS if all goes well, otherwise KFAILURE.
+ */
+
+int
+krb4int_save_credentials_addr(sname, sinst, srealm, session, 
+			      lifetime, kvno, ticket, issue_date, laddr)
+
+	char* sname;		/* Service name */
+	char* sinst;		/* Instance */	
+	char* srealm;		/* Auth domain */
+	C_Block session;	/* Session key */
+	int lifetime;		/* Lifetime */
+	int kvno;		/* Key version number */
+    	KTEXT ticket; 		/* The ticket itself */
+	KRB4_32 issue_date;	/* The issue time */
+	KRB_UINT32 laddr;
+{
+	CREDENTIALS	cr;
+
+	strcpy(cr.service, sname);
+	strcpy(cr.instance, sinst);
+	strcpy(cr.realm, srealm);
+	memcpy((void*)cr.session, (void*)session, sizeof(C_Block));
+	cr.lifetime = lifetime;
+	cr.kvno = kvno;
+	cr.ticket_st = *ticket;
+	cr.issue_date = issue_date;
+	strcpy(cr.pname, curr_auth_uname);	/* FIXME for mult sessions */
+	strcpy(cr.pinst, curr_auth_uinst);	/* FIXME for mult sessions */
+
+	if(AddCredentials(uname, uinstance, urealm, &cr)) return KFAILURE;
+	change_cache();
+	return KSUCCESS;
+}
+
+int KRB5_CALLCONV
+krb_save_credentials(
+    char	*name,
+    char	*inst,
+    char	*realm,
+    C_Block	session,
+    int		lifetime,
+    int		kvno,
+    KTEXT	ticket,
+    KRB4_32	issue_date)
+{
+    return krb4int_save_credentials_addr(name, inst, realm, session,
+					 lifetime, kvno, ticket,
+					 issue_date, 0);
+}
+
+
+int
+krb_delete_cred (sname, sinstance, srealm)
+	char *sname;
+	char *sinstance;
+	char *srealm;
+{
+	
+    if (DeleteCredentials (uname, uinstance, urealm, sname, sinstance, srealm))
+	return KFAILURE;
+
+	change_cache();
+
+	return KSUCCESS;
+	
+  /*
+    FIXME jcm - translate better between KClient internal OSErr errors 
+    (eg. cKrbCredsDontExist) and kerberos error codes (eg. GC_NOTKT)
+    */
+}	
+
+int
+krb_get_nth_cred (sname, sinstance, srealm, n)
+	char *sname;
+	char *sinstance;
+	char *srealm;
+	int n;
+{	
+    if (GetNthCredentials(uname, uinstance, urealm, sname, sinstance, srealm, n))
+	return KFAILURE;
+    else
+	return KSUCCESS;
+}
+
+/*
+ * Return the number of credentials in the current credential cache (ticket cache).
+ * On error, returns -1. 
+ */
+int
+krb_get_num_cred ()
+{
+  int n;
+  int s;
+
+  s = GetNumCredentials(uname, uinstance, urealm, &n);
+  if (s) return -1;
+  else return n;
+}
+
+
+
+/* Lower level routines */
+
+OSErr	GetNumSessions(n)
+     int *n;
+{
+	*n = fNumSessions;
+	return 0;
+	}
+
+/* n starts at 1, not 0 */
+OSErr
+GetNthSession(n, name, instance, realm)
+     const int n;
+     char *name;
+     char *instance;
+     char *realm;
+{
+	Session	*sptr;
+
+	if(n > fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+	sptr = (*fSessions) + n-1;
+	if (name)	strcpy(name, sptr->name);
+	if (instance)	strcpy(instance, sptr->instance);
+	if (realm)	strcpy(realm, sptr->realm);
+
+	return noErr;
+	}
+
+OSErr	DeleteSession(name, instance, realm)
+     const char *name;
+     const char *instance;
+     const char *realm;
+{
+	int		i;
+	Session	*sptr;
+	Handle	creds;
+
+	if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+	sptr = *fSessions;
+
+	for(i = 0; i < fNumSessions; i++) {
+		if(!strcmp(sptr[i].name, name) &&
+			!strcmp(sptr[i].instance, instance) &&
+			!strcmp(sptr[i].realm, realm)) {
+			break;
+			}
+		}
+
+	if(i == fNumSessions) return cKrbSessDoesntExist;
+
+	fNumSessions--;
+
+	creds = (Handle) sptr[i].creds;
+
+	for( ; i < fNumSessions; i++) {
+		strcpy(sptr[i].name, sptr[i+1].name);
+		strcpy(sptr[i].instance, sptr[i+1].instance);
+		strcpy(sptr[i].realm, sptr[i+1].realm);
+		}
+
+	SetHandleSize((Handle) fSessions, fNumSessions * sizeof(Session));
+	if(creds) DisposHandle(creds);
+
+	return MemError();
+	}
+
+OSErr	GetCredentials(name, instance, realm, cr)
+     const char *name;
+     const char *instance;
+     const char *realm;
+     CREDENTIALS *cr;
+{
+	int		i;
+	Session	*sptr;
+	CREDENTIALS	*cptr;
+	
+	if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+	sptr = *fSessions;
+
+	for(i = 0; i < fNumSessions; i++) {
+		if(!strcmp(sptr[i].name, name) &&
+			!strcmp(sptr[i].instance, instance) &&
+			!strcmp(sptr[i].realm, realm)) {
+			break;
+			}
+		}
+
+	if(i == fNumSessions) return cKrbSessDoesntExist;
+
+	sptr = sptr + i;
+
+	if(!sptr->numcreds || !sptr->creds) return cKrbCredsDontExist;
+
+	cptr = *(sptr->creds);
+
+	for(i = 0; i < sptr->numcreds; i++) {
+		if(!strcmp(cptr[i].service, cr->service) &&
+			!strcmp(cptr[i].instance, cr->instance) &&
+			!strcmp(cptr[i].realm, cr->realm)) {
+			break;
+			}
+		}
+
+	if(i == sptr->numcreds) return cKrbCredsDontExist;
+
+	*cr = cptr[i];
+	return noErr;
+	}
+
+OSErr	AddCredentials(name, instance, realm, cr)
+     const char *name;
+     const char *instance;
+     const char *realm;
+     const CREDENTIALS *cr;
+{
+	Session	*sptr;
+	Handle	creds;
+	int		i, thesess;
+	CREDENTIALS	*cptr;
+
+	/* find the appropriate session, or create it if it doesn't exist */
+	if(!fSessions) {
+		fSessions = (Session**) NewHandleSys(0);
+		if(MemError()) return MemError();
+		fNumSessions = 0;
+		}
+
+	sptr = *fSessions;
+
+	for(thesess = 0; thesess < fNumSessions; thesess++) {
+		if(!strcmp(sptr[thesess].name, name) &&
+			!strcmp(sptr[thesess].instance, instance) &&
+			!strcmp(sptr[thesess].realm, realm)) {
+			break;
+			}
+		}
+
+	sptr = (*fSessions) + thesess;
+
+	if(thesess == fNumSessions) {	/* doesn't exist, create it */
+		fNumSessions++;
+		SetHandleSize((Handle) fSessions, fNumSessions * sizeof(Session));
+		if(MemError()) return MemError();
+
+		/* fSessions may have been moved, so redereference */
+		sptr = (*fSessions) + thesess;
+		strcpy(sptr->name, (char *)name);
+		strcpy(sptr->instance, (char *)instance);
+		strcpy(sptr->realm, (char *)realm);
+		sptr->numcreds = 0;
+		sptr->creds = 0;
+		}
+
+		/* if the session has no assoc creds, create storage for them so rest of algorithm
+			doesn't break */
+	if(!sptr->numcreds || !sptr->creds) {
+		creds = NewHandleSys((Size) 0);
+		if(MemError()) return MemError();
+
+		/* rederef */ 
+		sptr = (*fSessions) + thesess;
+		sptr->creds = (CREDENTIALS **)creds;
+		sptr->numcreds = 0;
+		}
+
+		/* find creds if we already have an instance of them, or create a new slot for them
+			if we don't */
+	cptr = *(sptr->creds);
+
+	for(i = 0; i < sptr->numcreds; i++) {
+		if(!strcmp(cptr[i].service, cr->service) &&
+			!strcmp(cptr[i].instance, cr->instance) &&
+			!strcmp(cptr[i].realm, cr->realm)) {
+			break;
+			}
+		}
+
+	if(i == sptr->numcreds) {
+		sptr->numcreds++;
+		SetHandleSize((Handle)sptr->creds, sptr->numcreds * sizeof(CREDENTIALS));
+		if(MemError()) return MemError();
+
+		/* rederef */
+		sptr = (*fSessions) + thesess;
+		cptr = *(sptr->creds);
+		}
+
+		/* store them (possibly replacing previous creds if they already exist) */
+	cptr[i] = *cr;
+	return noErr;
+	}
+
+OSErr
+DeleteCredentials (uname, uinst, urealm, sname, sinst, srealm)
+     const char *uname;
+     const char *uinst;
+     const char *urealm;
+     const char *sname;
+     const char *sinst;
+     const char *srealm;
+{
+	int		i;
+	Session	*sptr;
+	CREDENTIALS	*cptr;
+
+	if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+	sptr = *fSessions;
+
+	for(i = 0; i < fNumSessions; i++) {
+		if(!strcmp(sptr[i].name, uname) &&
+			!strcmp(sptr[i].instance, uinstance) &&
+			!strcmp(sptr[i].realm, urealm)) {
+			break;
+			}
+		}
+
+	if(i == fNumSessions) return cKrbSessDoesntExist;
+
+	sptr = sptr + i;
+
+	if(!sptr->numcreds || !sptr->creds) return cKrbCredsDontExist;
+
+	cptr = *(sptr->creds);
+
+	for(i = 0; i < sptr->numcreds; i++) {
+		if(!strcmp(cptr[i].service, sname) &&
+			!strcmp(cptr[i].instance, sinst) &&
+			!strcmp(cptr[i].realm, srealm)) {
+			break;
+			}
+		}
+
+	if(i == sptr->numcreds) return cKrbCredsDontExist;
+
+	sptr->numcreds--;
+
+	for( ; i < sptr->numcreds; i++) {
+		cptr[i] = cptr[i+1];
+		}
+
+	SetHandleSize((Handle) sptr->creds, sptr->numcreds * sizeof(CREDENTIALS));
+
+	return MemError();
+	}
+
+OSErr	GetNumCredentials(name, instance, realm, n)
+     const char *name;
+     const char *instance;
+     const char *realm;
+     int *n;
+{
+	int		i;
+	Session	*sptr;
+
+	if(!fNumSessions || !fSessions) {
+		*n = 0;
+		return cKrbSessDoesntExist;
+		}
+
+	sptr = *fSessions;
+
+	for(i = 0; i < fNumSessions; i++) {
+		if(!strcmp(sptr[i].name, name) &&
+			!strcmp(sptr[i].instance, instance) &&
+			!strcmp(sptr[i].realm, realm)) {
+			break;
+			}
+		}
+
+	if(i == fNumSessions) {
+		*n = 0;
+		return cKrbCredsDontExist;
+		}
+
+	*n = sptr[i].numcreds;
+	return noErr;
+	}
+
+/* returns service name, service instance and realm of the nth credential. */
+/* n starts at 1, not 0 */
+OSErr
+GetNthCredentials(uname, uinstance, urealm, sname, sinst, srealm, n)
+     const char *uname;
+     const char *uinstance;
+     const char *urealm;
+     char *sname;
+     char *sinst;
+     char *srealm;
+     const int n;
+{
+	int		i;
+	Session	*sptr;
+	CREDENTIALS	*cptr;
+
+	if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+	sptr = *fSessions;
+
+	for(i = 0; i < fNumSessions; i++) {
+		if(!strcmp(sptr[i].name, uname) &&
+			!strcmp(sptr[i].instance, uinstance) &&
+			!strcmp(sptr[i].realm, urealm)) {
+			break;
+			}
+		}
+
+	if(i == fNumSessions) return cKrbSessDoesntExist;
+
+	sptr = (*fSessions) + i;
+
+	if(n > sptr->numcreds || !sptr->creds) return cKrbCredsDontExist;
+
+	cptr = (*(sptr->creds)) + n-1;
+
+	/* 
+	   check for null pointers cuz. some callers don't provide  
+	   storage for all this info, eg. Kerb_get_tf_fullname. 
+	*/
+	
+	if (sname) 
+		strcpy(sname, cptr->service);
+	if (sinst)
+		strcpy(sinst, cptr->instance);
+	if (srealm)
+		strcpy(srealm, cptr->realm);
+	return noErr;
+}
diff --git a/krb5-1-6/src/lib/krb4/memcache.h b/krb5-1-6/src/lib/krb4/memcache.h
new file mode 100644
index 000000000..d6d04190b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/memcache.h
@@ -0,0 +1,36 @@
+/*
+	memcache.h
+		Kerberos credential store in memory
+		Originally coded by Tim Miller / Brown University
+		Mods 1/92 By Peter Bosanko
+
+		Modified May-June 1994 by Julia Menapace and John Gilmore,
+		Cygnus Support.
+*/
+
+struct Session {
+	char		name[ANAME_SZ];
+	char		instance[INST_SZ];
+	char		realm[REALM_SZ];
+	int		numcreds;
+	CREDENTIALS	**creds;
+};
+typedef struct Session Session;
+
+OSErr GetNumSessions(int *n);
+OSErr GetNthSession(const int n, char *name, char *instance, char *realm);
+OSErr DeleteSession(const char *name, const char *instance, const char *realm);
+OSErr GetCredentials(const char *name, const char *instance, const char *realm,
+		     CREDENTIALS *cr);	
+/* name, instance, and realm of service wanted should be set in *cr
+   before calling */
+OSErr AddCredentials(const char *name, const char *instance, const char *realm,
+		     const CREDENTIALS *cr);
+OSErr DeleteCredentials(const char *uname, const char *uinst,
+			const char *urealm, const char *sname,
+			const char *sinst, const char *srealm);
+OSErr GetNumCredentials(const char *name, const char *instance,
+			const char *realm, int *n);
+OSErr GetNthCredentials(const char *uname, const char *uinst,
+			const char *urealm, char *sname, char *sinst,
+			char *srealm, const int n);
diff --git a/krb5-1-6/src/lib/krb4/mk_auth.c b/krb5-1-6/src/lib/krb4/mk_auth.c
new file mode 100644
index 000000000..cf85ea2f8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mk_auth.c
@@ -0,0 +1,249 @@
+/*
+ * lib/krb4/mk_auth.c
+ *
+ * Copyright 1987, 1988, 2000, 2001 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Derived from sendauth.c by John Gilmore, 10 October 1994.
+ */
+
+#include <stdio.h>
+#include "krb.h"
+#include "prot.h"
+#include <errno.h>
+#include <string.h>
+
+#define	KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in recvauth.c and sendauth.c.
+ */
+
+/*
+ * This file contains two routines: krb_mk_auth() and krb_check_auth().
+ *
+ * krb_mk_auth() packages a ticket for transmission to an application
+ * server.
+ *
+ * krb_krb_check_auth() validates a mutual-authentication response from
+ * the application server.
+ * 
+ * These routines are portable versions that implement a protocol
+ * compatible with the original Unix "sendauth".
+ */
+
+/*
+ * The first argument to krb_mk_auth() contains a bitfield of
+ * options (the options are defined in "krb.h"):
+ *
+ * KOPT_DONT_CANON	Don't canonicalize instance as a hostname.
+ *			(If this option is not chosen, krb_get_phost()
+ *			is called to canonicalize it.)
+ *
+ * KOPT_DONT_MK_REQ 	Don't request server ticket from Kerberos.
+ *			A ticket must be supplied in the "ticket"
+ *			argument.
+ *			(If this option is not chosen, and there
+ *			is no ticket for the given server in the
+ *			ticket cache, one will be fetched using
+ *			krb_mk_req() and returned in "ticket".)
+ *
+ * KOPT_DO_MUTUAL	Do mutual authentication, requiring that the
+ * 			receiving server return the checksum+1 encrypted
+ *			in the session key.  The mutual authentication
+ *			is done using krb_mk_priv() on the other side
+ *			(see "recvauth.c") and krb_rd_priv() on this
+ *			side.
+ *
+ * The "ticket" argument is used to store the new ticket
+ * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
+ * chosen, the ticket must be supplied in the "ticket" argument.
+ * The "service", "inst", and "realm" arguments identify the ticket.
+ * If "realm" is null, the local realm is used.
+ *
+ * The following argument is only needed if the KOPT_DO_MUTUAL option
+ * is chosen:
+ *
+ *   The "checksum" argument is a number that the server will add 1 to
+ *   to authenticate itself back to the client.
+ *
+ * The application protocol version number (of up to KRB_SENDAUTH_VLEN
+ * characters) is passed in "version".
+ *
+ * The ticket is packaged into a message in the buffer pointed to by
+ * the argument "buf".
+ *
+ * If all goes well, KSUCCESS is returned, otherwise some error code.
+ *
+ * The format of the message packaged to send to the application server is:
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ *
+ * KRB_SENDAUTH_VLEN	KRB_SENDAUTH_VER	sendauth protocol
+ * bytes					version number
+ *
+ * KRB_SENDAUTH_VLEN	version			application protocol
+ * bytes					version number
+ *
+ * 4 bytes		ticket->length		length of ticket
+ *
+ * ticket->length	ticket->dat		ticket itself
+ */
+
+/*
+ * Build a "sendauth" packet compatible with Unix sendauth/recvauth.
+ */
+int KRB5_CALLCONV
+krb_mk_auth(options, ticket, service, inst, realm, checksum, version, buf)
+     long options;		/* bit-pattern of options */
+     KTEXT ticket;		/* where to put ticket (return); or
+				   supplied in case of KOPT_DONT_MK_REQ */
+     char *service;		/* service name */
+     char *inst;		/* instance (OUTPUT canonicalized) */
+     char *realm;		/* realm */
+     unsigned KRB4_32 checksum; /* checksum to include in request */
+     char *version;		/* version string */
+     KTEXT buf;			/* Output buffer to fill  */
+{
+    int rem;
+    char krb_realm[REALM_SZ];
+    char *phost;
+    int phostlen;
+    unsigned char *p;
+
+    rem = KSUCCESS;
+
+    /* get current realm if not passed in */
+    if (!realm) {
+	rem = krb_get_lrealm(krb_realm,1);
+	if (rem != KSUCCESS)
+	    return rem;
+	realm = krb_realm;
+    }
+
+    if (!(options & KOPT_DONT_CANON)) {
+	phost = krb_get_phost(inst);
+	phostlen = krb4int_strnlen(phost, INST_SZ) + 1;
+	if (phostlen <= 0 || phostlen > INST_SZ)
+	    return KFAILURE;
+	memcpy(inst, phost, (size_t)phostlen);
+    }
+
+    /* get the ticket if desired */
+    if (!(options & KOPT_DONT_MK_REQ)) {
+	rem = krb_mk_req(ticket, service, inst, realm, (KRB4_32)checksum);
+	if (rem != KSUCCESS)
+	    return rem;
+    }
+
+#ifdef ATHENA_COMPAT
+    /* this is only for compatibility with old servers */
+    if (options & KOPT_DO_OLDSTYLE) {
+	(void) sprintf(buf->dat,"%d ",ticket->length);
+	(void) write(fd, buf, strlen(buf));
+	(void) write(fd, (char *) ticket->dat, ticket->length);
+	return(rem);
+    }
+#endif /* ATHENA_COMPAT */
+
+    /* Check buffer size */
+    if (sizeof(buf->dat) < (KRB_SENDAUTH_VLEN + KRB_SENDAUTH_VLEN
+			    + 4 + ticket->length)
+	|| ticket->length < 0)
+	return KFAILURE;
+
+    /* zero the buffer */
+    memset(buf->dat, 0, sizeof(buf->dat));
+    p = buf->dat;
+
+    /* insert version strings */
+    strncpy((char *)p, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
+    p += KRB_SENDAUTH_VLEN;
+    strncpy((char *)p, version, KRB_SENDAUTH_VLEN);
+    p += KRB_SENDAUTH_VLEN;
+
+    /* put ticket length into buffer */
+    KRB4_PUT32BE(p, ticket->length);
+
+    /* put ticket into buffer */
+    memcpy(p, ticket->dat, (size_t)ticket->length);
+    p += ticket->length;
+
+    buf->length = p - buf->dat;
+    return KSUCCESS;
+}
+
+/*
+ * For mutual authentication using mk_auth, check the server's response
+ * to validate that we're really talking to the server which holds the
+ * key that we obtained from the Kerberos key server.
+ *
+ * The "buf" argument is the response we received from the app server.
+ * The "checksum" argument is a number that the server has added 1 to
+ * to authenticate itself back to the client (us); the "msg_data" argument
+ * returns the returned mutual-authentication message from the server
+ * (i.e., the checksum+1); "session" holds the
+ * session key of the server, extracted from the ticket file, for use
+ * in decrypting the mutual authentication message from the server;
+ * and "schedule" returns the key schedule for that decryption.  The
+ * the local and server addresses are given in "laddr" and "faddr".
+ */
+int KRB5_CALLCONV
+krb_check_auth (buf, checksum, msg_data, session, schedule, laddr, faddr)
+     KTEXT buf;			/* The response we read from app server */
+     unsigned KRB4_32 checksum; /* checksum we included in request */
+     MSG_DAT *msg_data;	/* mutual auth MSG_DAT (return) */
+     C_Block session;		/* credentials (input) */
+     Key_schedule schedule;	/* key schedule (return) */
+     struct sockaddr_in *laddr;	/* local address */
+     struct sockaddr_in *faddr;	/* address of foreign host on fd */
+{
+    int cc;
+    unsigned KRB4_32 cksum;
+    unsigned char *p;
+
+    /* decrypt it */
+#ifndef NOENCRYPTION
+    key_sched(session, schedule);
+#endif /* !NOENCRYPTION */
+    if (buf->length < 0)
+	return KFAILURE;
+    cc = krb_rd_priv(buf->dat, (unsigned KRB4_32)buf->length, schedule,
+		     (C_Block *)session, faddr, laddr, msg_data);
+    if (cc)
+	return cc;
+
+    /*
+     * Fetch the (incremented) checksum that we supplied in the
+     * request.
+     */
+    if (msg_data->app_length < 4)
+	return KFAILURE;
+    p = msg_data->app_data;
+    KRB4_GET32BE(cksum, p);
+
+    /* if it doesn't match, fail -- reply wasn't from our real server.  */
+    if (cksum != checksum + 1)
+	return KFAILURE;	/* XXX */
+    return KSUCCESS;
+}
diff --git a/krb5-1-6/src/lib/krb4/mk_err.c b/krb5-1-6/src/lib/krb4/mk_err.c
new file mode 100644
index 000000000..5eeca1bdb
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mk_err.c
@@ -0,0 +1,83 @@
+/*
+ * lib/krb4/mk_err.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * This routine creates a general purpose error reply message.  It
+ * doesn't use KTEXT because application protocol may have long
+ * messages, and may want this part of buffer contiguous to other
+ * stuff.
+ *
+ * The error reply is built in "p", using the error code "e" and
+ * error text "e_string" given.  The length of the error reply is
+ * returned.
+ *
+ * The error reply is in the following format:
+ *
+ * unsigned char	KRB_PROT_VERSION	protocol version no.
+ * unsigned char	AUTH_MSG_APPL_ERR	message type
+ * (least significant
+ * bit of above)	HOST_BYTE_ORDER		local byte order
+ * 4 bytes		e			given error code
+ * string		e_string		given error text
+ */
+
+long KRB5_CALLCONV
+krb_mk_err(p, e, e_string)
+    u_char *p;		/* Where to build error packet */
+    KRB4_32 e;			/* Error code */
+    char *e_string;		/* Text of error */
+{
+    u_char      *start;
+    size_t	e_len;
+
+    e_len = strlen(e_string) + 1;
+
+    /* Just return the buffer length if p is NULL, because writing to the
+     * buffer would be a bad idea.  Note that this feature is a change from
+     * previous versions, and can therefore only be used safely in this
+     * source tree, where we know this function supports it. */
+    if (p == NULL) {
+        return 1 + 1 + 4 + e_len;
+    }
+
+    start = p;
+
+    /* Create fixed part of packet */
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_APPL_ERR;
+
+    /* Add the basic info */
+    KRB4_PUT32BE(p, e);
+    memcpy(p, e_string, e_len); /* err text */
+    p += e_len;
+
+    /* And return the length */
+    return p - start;
+}
diff --git a/krb5-1-6/src/lib/krb4/mk_preauth.c b/krb5-1-6/src/lib/krb4/mk_preauth.c
new file mode 100644
index 000000000..1215e1145
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mk_preauth.c
@@ -0,0 +1,78 @@
+/* mk_preauth.c */
+/* part of Cygnus Network Security */
+/* Copyright 1994 Cygnus Support */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include <string.h>
+
+#include "autoconf.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *malloc(), *calloc(), *realloc();
+#endif
+
+int
+krb_mk_preauth(preauth_p, preauth_len,
+	       key_proc, aname, inst, realm, password, key)
+    char **preauth_p;
+    int  *preauth_len;
+    key_proc_type key_proc;
+    char *aname;
+    char *inst;
+    char *realm;
+    char *password;
+    C_Block key;
+{
+#ifdef NOENCRYPTION
+    *preauth_len = strlen(aname) + 1; /* include the trailing 0 */
+    *preauth_p = malloc(*preauth_len);
+    strcpy(*preauth_p, aname);	/* this will copy the trailing 0 */
+#else
+    des_key_schedule key_s;
+    int sl = strlen(aname);
+#endif
+
+    (*key_proc)(aname, inst, realm, password, key);
+
+#ifndef NOENCRYPTION
+    /* 
+     * preauth_len is set to a length greater than sl + 1 
+     * and a multpile of 8
+     */
+    *preauth_len = (((sl + 1) / 8) + 1) * 8;
+    /* allocate memory for preauth_p and fill it with 0 */
+    *preauth_p = malloc((size_t)*preauth_len);
+    /* create the key schedule */
+    if (des_key_sched(key, key_s)) {
+	return 1;
+    }
+    /* 
+     * encrypt aname using key_s as the key schedule and key as the
+     * initialization vector.
+     */
+    des_pcbc_encrypt((des_cblock *)aname, (des_cblock *)*preauth_p,
+		     (long)(sl + 1), key_s, (des_cblock *)key, DES_ENCRYPT);
+    memset(key_s, 0, sizeof(key_s));
+#endif
+    return 0;
+}
+
+void
+krb_free_preauth(preauth_p, preauth_len)
+     char *preauth_p;
+     int preauth_len;
+{
+    free(preauth_p);
+    return;
+}
diff --git a/krb5-1-6/src/lib/krb4/mk_priv.c b/krb5-1-6/src/lib/krb4/mk_priv.c
new file mode 100644
index 000000000..470ad9473
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mk_priv.c
@@ -0,0 +1,301 @@
+/*
+ * lib/krb4/mk_priv.c
+ *
+ * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * This routine constructs a Kerberos 'private msg', i.e.
+ * cryptographically sealed with a private session key.
+ *
+ * Returns either < 0 ===> error, or resulting size of message
+ *
+ * Steve Miller    Project Athena  MIT/DEC
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include "lsb_addr_cmp.h"
+#include "port-sockets.h"
+
+extern int krb_debug;
+
+/*
+ * krb_mk_priv() constructs an AUTH_MSG_PRIVATE message.  It takes
+ * some user data "in" of "length" bytes and creates a packet in "out"
+ * consisting of the user data, a timestamp, and the sender's network
+ * address.
+#ifndef NOENCRYTION
+ * The packet is encrypted by pcbc_encrypt(), using the given
+ * "key" and "schedule".
+#endif
+ * The length of the resulting packet "out" is
+ * returned.
+ *
+ * It is similar to krb_mk_safe() except for the additional key
+ * schedule argument "schedule" and the fact that the data is encrypted
+ * rather than appended with a checksum.  Also, the protocol version
+ * number is "private_msg_ver", defined in krb_rd_priv.c, rather than
+ * KRB_PROT_VERSION, defined in "krb.h".
+ *
+ * The "out" packet consists of:
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ *
+ * 1 byte		private_msg_ver		protocol version number
+ * 1 byte		AUTH_MSG_PRIVATE |	message type plus local
+ *			HOST_BYTE_ORDER		byte order in low bit
+ *
+#ifdef NOENCRYPTION
+ * 4 bytes		c_length		length of data
+#else
+ * 4 bytes		c_length		length of encrypted data
+ *
+ * ===================== begin encrypt ================================
+#endif
+ * 
+ * 4 bytes		length			length of user data
+ * length		in			user data
+ * 1 byte		msg_time_5ms		timestamp milliseconds
+ * 4 bytes		sender->sin.addr.s_addr	sender's IP address
+ *
+ * 4 bytes		msg_time_sec or		timestamp seconds with
+ *			-msg_time_sec		direction in sign bit
+ *
+ * 0<=n<=7  bytes	pad to 8 byte multiple	zeroes
+#ifndef NOENCRYPTION
+ *			(done by pcbc_encrypt())
+ *
+ * ======================= end encrypt ================================
+#endif
+ */
+
+/* Utility function:
+
+   Determine order of addresses, if SENDER less than RECEIVER return 1
+   so caller will negate timestamp.  Return -1 for failure.  */
+int
+krb4int_address_less (struct sockaddr_in *sender, struct sockaddr_in *receiver)
+{
+    unsigned long sender_addr, receiver_addr;
+    unsigned short sender_port, receiver_port;
+    switch (sender->sin_family) {
+    case AF_INET:
+	sender_addr = sender->sin_addr.s_addr;
+	sender_port = sender->sin_port;
+	break;
+#ifdef KRB5_USE_INET6
+    case AF_INET6:
+    {
+	struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sender;
+	if (IN6_IS_ADDR_V4MAPPED (&s6->sin6_addr)) {
+	    struct sockaddr_in sintmp = { 0 };
+	    memcpy (&sintmp.sin_addr.s_addr,
+		    12+(char*)&s6->sin6_addr.s6_addr,
+		    4);
+	    sender_addr = sintmp.sin_addr.s_addr;
+	} else
+	    return -1;
+	sender_port = s6->sin6_port;
+	break;
+    }
+#endif
+    default:
+	return -1;
+    }
+    switch (receiver->sin_family) {
+    case AF_INET:
+	receiver_addr = receiver->sin_addr.s_addr;
+	receiver_port = receiver->sin_port;
+	break;
+#ifdef KRB5_USE_INET6
+    case AF_INET6:
+    {
+	struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) receiver;
+	if (IN6_IS_ADDR_V4MAPPED (&s6->sin6_addr)) {
+	    struct sockaddr_in sintmp = { 0 };
+	    memcpy (&sintmp.sin_addr.s_addr,
+		    12+(char*)&s6->sin6_addr.s6_addr,
+		    4);
+	    receiver_addr = sintmp.sin_addr.s_addr;
+	} else
+	    return -1;
+	receiver_port = s6->sin6_port;
+	break;
+    }
+#endif
+    default:
+	return -1;
+    }
+    /* For compatibility with broken old code, compares are done in
+       VAX byte order (LSBFIRST).  */
+    if (lsb_net_ulong_less(sender_addr, receiver_addr) == -1
+	|| (lsb_net_ulong_less(sender_addr, receiver_addr) == 0
+	    && lsb_net_ushort_less(sender_port, receiver_port) == -1))
+	return 1;
+    return 0;
+    /*
+     * all that for one tiny bit!  Heaven help those that talk to
+     * themselves.
+     */
+}
+
+long KRB5_CALLCONV
+krb_mk_priv(in, out, length, schedule, key, sender, receiver)
+    u_char *in;		/* application data */
+    u_char *out;		/* put msg here, leave room for
+				 * header! breaks if in and out
+				 * (header stuff) overlap */
+    unsigned KRB4_32 length;	/* of in data */
+    Key_schedule schedule;	/* precomputed key schedule */
+    C_Block *key;		/* encryption key for seed and ivec */
+    struct sockaddr_in *sender;   /* sender address */
+    struct sockaddr_in *receiver; /* receiver address */
+{
+    register u_char     *p,*q;
+    u_char *c_length_ptr;
+    extern int private_msg_ver; /* in krb_rd_priv.c */
+
+    unsigned KRB4_32 c_length, c_length_raw;
+    u_char msg_time_5ms;
+    unsigned KRB4_32 msg_time_sec;
+    unsigned KRB4_32 msg_time_usec;
+
+    /* Be really paranoid. */
+    if (sizeof(sender->sin_addr.s_addr) != 4)
+	return -1;
+    /*
+     * get the current time to use instead of a sequence #, since
+     * process lifetime may be shorter than the lifetime of a session
+     * key.
+     */
+    msg_time_sec = TIME_GMT_UNIXSEC_US(&msg_time_usec);
+    msg_time_5ms = msg_time_usec / 5000; /* 5ms quanta */
+
+    p = out;
+
+    /* Cruftiness below! */
+    *p++ = private_msg_ver ? private_msg_ver : KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_PRIVATE;
+
+    /* save ptr to cipher length */
+    c_length_ptr = p;
+    p += 4;
+
+#ifndef NOENCRYPTION
+    /* start for encrypted stuff */
+#endif
+    q = p;
+
+    /* stuff input length */
+    KRB4_PUT32BE(p, length);
+
+#ifdef NOENCRYPTION
+    /* make all the stuff contiguous for checksum */
+#else
+    /* make all the stuff contiguous for checksum and encryption */
+#endif
+    memcpy(p, in, (size_t)length);
+    p += length;
+
+    /* stuff time 5ms */
+    *p++ = msg_time_5ms;
+
+    /* stuff source address */
+    if (sender->sin_family == AF_INET)
+	memcpy(p, &sender->sin_addr.s_addr, sizeof(sender->sin_addr.s_addr));
+#ifdef KRB5_USE_INET6
+    else if (sender->sin_family == AF_INET6
+	     && IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr))
+	memcpy(p, 12+(char*)&((struct sockaddr_in6 *)sender)->sin6_addr, 4);
+#endif
+    else
+	/* The address isn't one we can encode in 4 bytes -- but
+	   that's okay if the receiver doesn't care.  */
+	memset(p, 0, 4);
+    p += sizeof(sender->sin_addr.s_addr);
+
+    /*
+     * direction bit is the sign bit of the timestamp.  Ok
+     * until 2038??
+     */
+    switch (krb4int_address_less (sender, receiver)) {
+    case 1:
+	msg_time_sec = -msg_time_sec;
+	break;
+    case -1:
+	/* Which way should we go in this case?  */
+    case 0:
+	break;
+    }
+
+    /* stuff time sec */
+    KRB4_PUT32BE(p, msg_time_sec);
+
+    /*
+     * All that for one tiny bit!  Heaven help those that talk to
+     * themselves.
+     */
+
+#ifdef notdef
+    /*
+     * calculate the checksum of the length, address, sequence, and
+     * inp data
+     */
+    cksum = quad_cksum(q,NULL,p-q,0,key);
+    DEB (("\ncksum = %u",cksum));
+    /* stuff checksum */
+    memcpy(p, &cksum, sizeof(cksum));
+    p += sizeof(cksum);
+#endif
+
+#ifdef NOENCRYPTION
+    /*
+     * All the data have been assembled, compute length
+     */
+#else
+    /*
+     * All the data have been assembled, compute length and encrypt
+     * starting with the length, data, and timestamps use the key as
+     * an ivec.
+     */
+#endif
+
+    c_length_raw = p - q;
+    c_length = ((c_length_raw + sizeof(C_Block) -1)
+		/ sizeof(C_Block)) * sizeof(C_Block);
+    /* stuff the length */
+    p = c_length_ptr;
+    KRB4_PUT32BE(p, c_length);
+
+#ifndef NOENCRYPTION
+    /* pcbc encrypt, pad as needed, use key as ivec */
+    pcbc_encrypt((C_Block *)q,(C_Block *)q, (long)c_length_raw,
+		 schedule, key, ENCRYPT);
+#endif /* NOENCRYPTION */
+
+    return q - out + c_length;	/* resulting size */
+}
diff --git a/krb5-1-6/src/lib/krb4/mk_req.c b/krb5-1-6/src/lib/krb4/mk_req.c
new file mode 100644
index 000000000..fc92c58e6
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mk_req.c
@@ -0,0 +1,285 @@
+/*
+ * lib/krb4/mk_req.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000, 2002 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include <string.h>
+#include "krb4int.h"
+
+extern int krb_ap_req_debug;
+static int lifetime = 255;		/* Default based on the TGT */
+
+static int krb_mk_req_creds_prealm(KTEXT, CREDENTIALS *, KRB4_32, char *);
+
+/*
+ * krb_mk_req takes a text structure in which an authenticator is to
+ * be built, the name of a service, an instance, a realm,
+ * and a checksum.  It then retrieves a ticket for
+ * the desired service and creates an authenticator in the text
+ * structure passed as the first argument.  krb_mk_req returns
+ * KSUCCESS on success and a Kerberos error code on failure.
+ *
+ * The peer procedure on the other end is krb_rd_req.  When making
+ * any changes to this routine it is important to make corresponding
+ * changes to krb_rd_req.
+ *
+ * The authenticator consists of the following:
+ *
+ * authent->dat
+ *
+ * unsigned char	KRB_PROT_VERSION	protocol version no.
+ * unsigned char	AUTH_MSG_APPL_REQUEST	message type
+ * (least significant
+ * bit of above)	HOST_BYTE_ORDER		local byte ordering
+ * unsigned char	kvno from ticket	server's key version
+ * string		realm			server's realm
+ * unsigned char	tl			ticket length
+ * unsigned char	idl			request id length
+ * text			ticket->dat		ticket for server
+ * text			req_id->dat		request id
+ *
+ * The ticket information is retrieved from the ticket cache or
+ * fetched from Kerberos.  The request id (called the "authenticator"
+#ifdef NOENCRYPTION
+ * in the papers on Kerberos) contains the following:
+#else
+ * in the papers on Kerberos) contains information encrypted in the session
+ * key for the client and ticket-granting service:  {req_id}Kc,tgs
+ * Before encryption, it contains the following:
+#endif
+ *
+ * req_id->dat
+ *
+ * string		cr.pname		{name, instance, and
+ * string		cr.pinst		realm of principal
+ * string		myrealm			making this request}
+ * 4 bytes		checksum		checksum argument given
+ * unsigned char	time_usecs		time (microseconds)
+ * 4 bytes		time_secs		time (seconds)
+ *
+ * req_id->length = 3 strings + 3 terminating nulls + 5 bytes for time,
+ *                  all rounded up to multiple of 8.
+ */
+
+static int
+krb_mk_req_creds_prealm(authent, creds, checksum, myrealm)
+    register	KTEXT authent;	/* Place to build the authenticator */
+    CREDENTIALS	*creds;
+    KRB4_32	checksum;	/* Checksum of data (optional) */
+    char	*myrealm;	/* Client's realm */
+{
+    KTEXT_ST req_st; /* Temp storage for req id */
+    KTEXT req_id = &req_st;
+    unsigned char *p, *q, *reqid_lenp;
+    int tl;			/* Tkt len */
+    int idl;			/* Reqid len */
+    register KTEXT ticket;	/* Pointer to tkt_st */
+    Key_schedule  key_s;
+    size_t realmlen, pnamelen, pinstlen, myrealmlen;
+    unsigned KRB4_32 time_secs;
+    unsigned KRB4_32 time_usecs;
+
+    /* Don't risk exposing stack garbage to correspondent, even if
+       encrypted from other prying eyes.  */
+    memset(&req_st, 0x69, sizeof(req_st));
+
+    ticket = &creds->ticket_st;
+    /* Get the ticket and move it into the authenticator */
+    if (krb_ap_req_debug)
+        DEB (("Realm: %s\n", creds->realm));
+
+    realmlen = strlen(creds->realm) + 1;
+    if (sizeof(authent->dat) < (1 + 1 + 1
+				+ realmlen
+				+ 1 + 1 + ticket->length)
+	|| ticket->length < 0 || ticket->length > 255) {
+	authent->length = 0;
+	return KFAILURE;
+    }
+
+    if (krb_ap_req_debug)
+        DEB (("%s %s %s %s %s\n", creds->service, creds->instance,
+	      creds->realm, creds->pname, creds->pinst));
+
+    p = authent->dat;
+
+    /* The fixed parts of the authenticator */
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_APPL_REQUEST;
+    *p++ = creds->kvno;
+
+    memcpy(p, creds->realm, realmlen);
+    p += realmlen;
+
+    tl = ticket->length;
+    *p++ = tl;
+    /* Save ptr to where req_id->length goes. */
+    reqid_lenp = p;
+    p++;
+    memcpy(p, ticket->dat, (size_t)tl);
+    p += tl;
+
+    if (krb_ap_req_debug)
+        DEB (("Ticket->length = %d\n",ticket->length));
+    if (krb_ap_req_debug)
+        DEB (("Issue date: %d\n",creds->issue_date));
+
+    pnamelen = strlen(creds->pname) + 1;
+    pinstlen = strlen(creds->pinst) + 1;
+    myrealmlen = strlen(myrealm) + 1;
+    if (sizeof(req_id->dat) / 8 < (pnamelen + pinstlen + myrealmlen
+				   + 4 + 1 + 4 + 7) / 8) {
+	return KFAILURE;
+    }
+
+    q = req_id->dat;
+
+    /* Build request id */
+    /* Auth name */
+    memcpy(q, creds->pname, pnamelen);
+    q += pnamelen;
+    /* Principal's instance */
+    memcpy(q, creds->pinst, pinstlen);
+    q += pinstlen;    
+    /* Authentication domain */
+    memcpy(q, myrealm, myrealmlen);
+    q += myrealmlen;
+    /* Checksum */
+    KRB4_PUT32BE(q, checksum);
+
+    /* Fill in the times on the request id */
+    time_secs = TIME_GMT_UNIXSEC_US (&time_usecs);
+    *q++ = time_usecs;		/* time_usecs % 255 */
+    /* Time (coarse) */
+    KRB4_PUT32BE(q, time_secs);
+
+    /* Fill to a multiple of 8 bytes for DES */
+    req_id->length = ((q - req_id->dat + 7) / 8) * 8;
+
+#ifndef NOENCRYPTION
+    /* Encrypt the request ID using the session key */
+    key_sched(creds->session, key_s);
+    pcbc_encrypt((C_Block *)req_id->dat, (C_Block *)req_id->dat,
+                 (long)req_id->length, key_s, &creds->session, 1);
+    /* clean up */
+    memset(key_s, 0, sizeof(key_s));
+#endif /* NOENCRYPTION */
+
+    /* Copy it into the authenticator */
+    idl = req_id->length;
+    if (idl > 255)
+	return KFAILURE;
+    *reqid_lenp = idl;
+    memcpy(p, req_id->dat, (size_t)idl);
+    p += idl;
+
+    authent->length = p - authent->dat;
+
+    /* clean up */
+    memset(req_id, 0, sizeof(*req_id));
+
+    if (krb_ap_req_debug)
+        DEB (("Authent->length = %d\n",authent->length));
+    if (krb_ap_req_debug)
+        DEB (("idl = %d, tl = %d\n", idl, tl));
+
+    return KSUCCESS;
+}
+
+int KRB5_CALLCONV
+krb_mk_req(authent, service, instance, realm, checksum)
+    register	KTEXT authent;	/* Place to build the authenticator */
+    char	*service;	/* Name of the service */
+    char	*instance;	/* Service instance */
+    char	*realm;	/* Authentication domain of service */
+    KRB4_32	checksum;	/* Checksum of data (optional) */
+{
+    char krb_realm[REALM_SZ];	/* Our local realm, if not specified */
+    char myrealm[REALM_SZ];	/* Realm of initial TGT. */
+    int retval;
+    CREDENTIALS creds;
+
+    /* get current realm if not passed in */
+    if (realm == NULL) {
+	retval = krb_get_lrealm(krb_realm, 1);
+	if (retval != KSUCCESS)
+	    return retval;
+	realm = krb_realm;
+    }
+    /*
+     * Determine realm of these tickets.  We will send this to the
+     * KDC from which we are requesting tickets so it knows what to
+     * with our session key.
+     */
+    retval = krb_get_tf_realm(TKT_FILE, myrealm);
+    if (retval != KSUCCESS)
+	retval = krb_get_lrealm(myrealm, 1);
+    if (retval != KSUCCESS)
+	return retval;
+
+    retval = krb_get_cred(service, instance, realm, &creds);
+    if (retval == RET_NOTKT) {
+	retval = get_ad_tkt(service, instance, realm, lifetime);
+        if (retval)
+            return retval;
+	retval = krb_get_cred(service, instance, realm, &creds);
+        if (retval)
+	    return retval;
+    }
+    if (retval != KSUCCESS)
+	return retval;
+
+    retval = krb_mk_req_creds_prealm(authent, &creds, checksum, myrealm);
+    memset(&creds.session, 0, sizeof(creds.session));
+    return retval;
+}
+
+int KRB5_CALLCONV
+krb_mk_req_creds(authent, creds, checksum)
+    register	KTEXT authent;	/* Place to build the authenticator */
+    CREDENTIALS	*creds;
+    KRB4_32	checksum;	/* Checksum of data (optional) */
+{
+    return krb_mk_req_creds_prealm(authent, creds, checksum, creds->realm);
+}
+
+/* 
+ * krb_set_lifetime sets the default lifetime for additional tickets
+ * obtained via krb_mk_req().
+ * 
+ * It returns the previous value of the default lifetime.
+ */
+
+int KRB5_CALLCONV
+krb_set_lifetime(newval)
+int newval;
+{
+    int olife = lifetime;
+
+    lifetime = newval;
+    return olife;
+}
diff --git a/krb5-1-6/src/lib/krb4/mk_safe.c b/krb5-1-6/src/lib/krb4/mk_safe.c
new file mode 100644
index 000000000..2a157caad
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/mk_safe.c
@@ -0,0 +1,167 @@
+/*
+ * lib/krb4/mk_req.c
+ *
+ * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * This routine constructs a Kerberos 'safe msg', i.e. authenticated
+ * using a private session key to seed a checksum. Msg is NOT
+ * encrypted.
+ *
+ * Returns either <0 ===> error, or resulting size of message
+ *
+ * Steve Miller    Project Athena  MIT/DEC
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "krb.h"
+#include "des.h"
+#include "prot.h"
+#include "lsb_addr_cmp.h"
+#include "port-sockets.h"
+
+extern int krb_debug;
+
+/*
+ * krb_mk_safe() constructs an AUTH_MSG_SAFE message.  It takes some
+ * user data "in" of "length" bytes and creates a packet in "out"
+ * consisting of the user data, a timestamp, and the sender's network
+ * address, followed by a checksum computed on the above, using the
+ * given "key".  The length of the resulting packet is returned.
+ *
+ * The "out" packet consists of:
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ *
+ * 1 byte		KRB_PROT_VERSION	protocol version number
+ * 1 byte		AUTH_MSG_SAFE |		message type plus local
+ *			HOST_BYTE_ORDER		byte order in low bit
+ *
+ * ===================== begin checksum ================================
+ * 
+ * 4 bytes		length			length of user data
+ * length		in			user data
+ * 1 byte		msg_time_5ms		timestamp milliseconds
+ * 4 bytes		sender->sin.addr.s_addr	sender's IP address
+ *
+ * 4 bytes		msg_time_sec or		timestamp seconds with
+ *			-msg_time_sec		direction in sign bit
+ *
+ * ======================= end checksum ================================
+ *
+ * 16 bytes		big_cksum		quadratic checksum of
+ *						above using "key"
+ */
+
+long KRB5_CALLCONV
+krb_mk_safe(in, out, length, key, sender, receiver)
+    u_char *in;			/* application data */
+    u_char *out;		/*
+				 * put msg here, leave room for header!
+				 * breaks if in and out (header stuff)
+				 * overlap
+				 */
+    unsigned KRB4_32 length;	/* of in data */
+    C_Block *key;		/* encryption key for seed and ivec */
+    struct sockaddr_in *sender;	/* sender address */
+    struct sockaddr_in *receiver; /* receiver address */
+{
+    register u_char     *p,*q;
+
+    unsigned KRB4_32 cksum;
+    unsigned KRB4_32 big_cksum[4];
+    unsigned KRB4_32 msg_secs;
+    unsigned KRB4_32 msg_usecs;
+    u_char msg_time_5ms;
+    KRB4_32 msg_time_sec;
+    int i;
+
+    /* Be really paranoid. */
+    if (sizeof(sender->sin_addr.s_addr) != 4)
+	return -1;
+    /*
+     * get the current time to use instead of a sequence #, since
+     * process lifetime may be shorter than the lifetime of a session
+     * key.
+     */
+    msg_secs = TIME_GMT_UNIXSEC_US(&msg_usecs);
+    msg_time_sec = msg_secs;
+    msg_time_5ms = msg_usecs / 5000; /* 5ms quanta */
+
+    p = out;
+
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_SAFE;
+
+    q = p;			/* start for checksum stuff */
+    /* stuff input length */
+    KRB4_PUT32BE(p, length);
+
+    /* make all the stuff contiguous for checksum */
+    memcpy(p, in, length);
+    p += length;
+
+    /* stuff time 5ms */
+    *p++ = msg_time_5ms;
+
+    /* stuff source address */
+    if (sender->sin_family == AF_INET)
+	memcpy(p, &sender->sin_addr.s_addr, sizeof(sender->sin_addr.s_addr));
+#ifdef KRB5_USE_INET6
+    else if (sender->sin_family == AF_INET6
+	     && IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr))
+	memcpy(p, 12+(char*)&((struct sockaddr_in6 *)sender)->sin6_addr, 4);
+#endif
+    else
+	/* The address isn't one we can encode in 4 bytes -- but
+	   that's okay if the receiver doesn't care.  */
+	memset(p, 0, 4);
+    p += sizeof(sender->sin_addr.s_addr);
+
+    /*
+     * direction bit is the sign bit of the timestamp.  Ok until
+     * 2038??
+     */
+    if (krb4int_address_less (sender, receiver) == 1)
+	msg_time_sec = -msg_time_sec;
+    /* stuff time sec */
+    KRB4_PUT32BE(p, msg_time_sec);
+
+#ifdef NOENCRYPTION
+    cksum = 0;
+    memset(big_cksum, 0, sizeof(big_cksum));
+#else /* Do encryption */
+    /* calculate the checksum of length, timestamps, and input data */
+    cksum = quad_cksum(q, (unsigned KRB4_32 *)big_cksum,
+		       p - q, 2, key);
+#endif /* NOENCRYPTION */
+    DEB(("\ncksum = %u",cksum));
+
+    /* stuff checksum */
+    for (i = 0; i < 4; i++)
+	KRB4_PUT32BE(p, big_cksum[i]);
+
+    return p - out;		/* resulting size */
+}
diff --git a/krb5-1-6/src/lib/krb4/month_sname.c b/krb5-1-6/src/lib/krb4/month_sname.c
new file mode 100644
index 000000000..48be89e53
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/month_sname.c
@@ -0,0 +1,28 @@
+/*
+ * month_sname.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+/*
+ * Given an integer 1-12, month_sname() returns a string
+ * containing the first three letters of the corresponding
+ * month.  Returns 0 if the argument is out of range.
+ */
+
+#include <krb.h>
+#include "krb4int.h"
+
+const char *month_sname(n)
+    int n;
+{
+    static const char name[][4] = {
+        "Jan","Feb","Mar","Apr","May","Jun",
+        "Jul","Aug","Sep","Oct","Nov","Dec"
+    };
+    return((n < 1 || n > 12) ? 0 : name [n-1]);
+}
diff --git a/krb5-1-6/src/lib/krb4/netread.c b/krb5-1-6/src/lib/krb4/netread.c
new file mode 100644
index 000000000..b366df3d2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/netread.c
@@ -0,0 +1,69 @@
+/*
+ * lib/krb4/netwrite.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <errno.h>
+#include "krb.h"
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "port-sockets.h"
+
+/*
+ * krb_net_read() reads from the file descriptor "fd" to the buffer
+ * "buf", until either 1) "len" bytes have been read or 2) cannot
+ * read anymore from "fd".  It returns the number of bytes read
+ * or a read() error.  (The calling interface is identical to
+ * read(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+int
+krb_net_read(fd, buf, len)
+int fd;
+register char *buf;
+register int len;
+{
+    int cc, len2 = 0;
+
+    do {
+	cc = SOCKET_READ(fd, buf, len);
+	if (cc < 0)
+	  {
+	    if (SOCKET_ERRNO == SOCKET_EINTR)
+	      continue;
+	    return(cc);		 /* errno is already set */
+	  }
+	else if (cc == 0) {
+	    return(len2);
+	} else {
+	    buf += cc;
+	    len2 += cc;
+	    len -= cc;
+	}
+    } while (len > 0);
+    return(len2);
+}
diff --git a/krb5-1-6/src/lib/krb4/netwrite.c b/krb5-1-6/src/lib/krb4/netwrite.c
new file mode 100644
index 000000000..31832488d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/netwrite.c
@@ -0,0 +1,65 @@
+/*
+ * lib/krb4/netwrite.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <errno.h>
+#include "krb.h"
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "port-sockets.h"
+
+/*
+ * krb_net_write() writes "len" bytes from "buf" to the file
+ * descriptor "fd".  It returns the number of bytes written or
+ * a write() error.  (The calling interface is identical to
+ * write(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+int
+krb_net_write(fd, buf, len)
+int fd;
+register char *buf;
+int len;
+{
+    int cc;
+    register int wrlen = len;
+    do {
+	cc = SOCKET_WRITE(fd, buf, wrlen);
+	if (cc < 0)
+	  {
+	    if (SOCKET_ERRNO == SOCKET_EINTR)
+	      continue;
+	    return(cc);
+	  }
+	else {
+	    buf += cc;
+	    wrlen -= cc;
+	}
+    } while (wrlen > 0);
+    return(len);
+}
diff --git a/krb5-1-6/src/lib/krb4/password_to_key.c b/krb5-1-6/src/lib/krb4/password_to_key.c
new file mode 100644
index 000000000..c6e60d98c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/password_to_key.c
@@ -0,0 +1,152 @@
+/*
+ * lib/krb4/password_to_key.c
+ *
+ * Copyright 1999, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * password_to_key functions merged from KfM
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef USE_CCAPI
+#include <CredentialsCache.h>
+#endif
+#include "krb.h"
+#include "krb4int.h"
+
+/*
+ * passwd_to_key(): given a password, return a DES key.
+ * There are extra arguments here which (used to be?)
+ * used by srvtab_to_key().
+ *
+ * If the "passwd" argument is not null, generate a DES
+ * key from it, using string_to_key().
+ *
+ * If the "passwd" argument is null, then on a Unix system we call
+ * des_read_password() to prompt for a password and then convert it
+ * into a DES key.  But "prompting" the user is harder in a Windows or
+ * Macintosh environment, so we rely on our caller to explicitly do
+ * that now.
+ *
+ * In either case, the resulting key is put in the "key" argument,
+ * and 0 is returned.
+ */
+
+
+key_proc_type *krb_get_keyprocs (key_proc_type keyproc)
+{
+    static key_proc_type default_keyprocs[4] = { mit_passwd_to_key, 
+                                                 afs_passwd_to_key, 
+                                                 krb5_passwd_to_key, 
+                                                 NULL };
+                                                  
+    static key_proc_type user_keyprocs[2] = { NULL, NULL };
+    
+    /* generate the list of key procs */
+    if (keyproc == NULL) {
+        return default_keyprocs; /* use the default */
+    } else {
+        user_keyprocs[0] = keyproc;
+        return user_keyprocs;  /* use the caller provided keyprocs */
+    }
+}
+
+int KRB5_CALLCONV
+mit_passwd_to_key(
+    char	*user,
+    char	*instance,
+    char	*realm,
+    char	*passwd,
+    C_Block	key)
+{
+#if 0 /* what system? */
+#pragma unused(user)
+#pragma unused(instance)
+#pragma unused(realm)
+#endif
+
+    if (passwd) {
+        des_string_to_key(passwd, key);
+    } else {
+#if !(defined(_WIN32) || defined(USE_LOGIN_LIBRARY))
+        des_read_password((des_cblock *)key, "Password", 0);
+#else
+        return (-1);
+#endif
+    }
+    return (0);
+}
+
+/* So we can use a v4 kinit against a v5 kdc with no krb4 salted key */
+int KRB5_CALLCONV
+krb5_passwd_to_key(
+    char	*user,
+    char	*instance,
+    char	*realm,
+    char	*passwd,
+    C_Block	key)
+{
+    size_t	len, tlen;
+    char	*p;
+
+    if (user && instance && realm && passwd) {
+        len = MAX_K_NAME_SZ + strlen(passwd) + 1;
+	tlen = strlen(passwd) + strlen(realm) + strlen(user) + strlen(instance) + 1;
+	if (tlen > len)
+	    return 0;
+        p = malloc (tlen);
+        if (p != NULL) {
+            sprintf (p, "%s%s%s%s", passwd, realm, user, instance);
+            des_string_to_key (p, key);
+            free (p);
+            return 0;
+        }
+    }
+    return -1;
+}
+
+int KRB5_CALLCONV
+afs_passwd_to_key(
+    char	*user,
+    char	*instance,
+    char	*realm,
+    char	*passwd,
+    C_Block	key)
+{
+#if 0 /* what system? */
+#pragma unused(user)
+#pragma unused(instance)
+#endif
+
+    if (passwd) {
+        afs_string_to_key(passwd, realm, key);
+    } else {
+#if !(defined(_WIN32) || defined(USE_LOGIN_LIBRARY))
+        des_read_password((des_cblock *)key, "Password", 0);
+#else
+        return (-1);
+#endif
+    }
+    return (0);
+}
diff --git a/krb5-1-6/src/lib/krb4/pkt_cipher.c b/krb5-1-6/src/lib/krb4/pkt_cipher.c
new file mode 100644
index 000000000..29123480e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/pkt_cipher.c
@@ -0,0 +1,35 @@
+/*
+ * pkt_cipher.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <string.h>
+#include "krb.h"
+#include "prot.h"
+
+
+/*
+ * This routine takes a reply packet from the Kerberos ticket-granting
+ * service and returns a pointer to the beginning of the ciphertext in it.
+ *
+ * See "prot.h" for packet format.
+ */
+
+KTEXT
+pkt_cipher(packet)
+    KTEXT packet;
+{
+    unsigned char *ptr = pkt_a_realm(packet) + 6
+	+ strlen((char *)pkt_a_realm(packet));
+    /* Skip a few more fields */
+    ptr += 3 + 4;		/* add 4 for exp_date */
+
+    /* And return the pointer */
+    return((KTEXT) ptr);
+}
diff --git a/krb5-1-6/src/lib/krb4/pkt_clen.c b/krb5-1-6/src/lib/krb4/pkt_clen.c
new file mode 100644
index 000000000..52763a4dd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/pkt_clen.c
@@ -0,0 +1,47 @@
+/*
+ * pkt_clen.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <string.h>
+#include "krb.h"
+#include "prot.h"
+
+extern int krb_debug;
+int swap_bytes=0;
+
+/*
+ * Given a pointer to an AUTH_MSG_KDC_REPLY packet, return the length of
+ * its ciphertext portion.  The external variable "swap_bytes" is assumed
+ * to have been set to indicate whether or not the packet is in local
+ * byte order.  pkt_clen() takes this into account when reading the
+ * ciphertext length out of the packet.
+ */
+
+int
+pkt_clen(pkt)
+    KTEXT pkt;
+{
+    static unsigned short temp;
+    int clen = 0;
+
+    /* Start of ticket list */
+    unsigned char *ptr = pkt_a_realm(pkt) + 10
+	+ strlen((char *)pkt_a_realm(pkt));
+
+    /* Finally the length */
+    memcpy((char *)&temp, (char *)(++ptr), 2); /* alignment */
+    if (swap_bytes)
+	temp = krb4_swab16(temp);    
+
+    clen = (int) temp;
+
+    DEB (("Clen is %d\n",clen));
+    return(clen);
+}
diff --git a/krb5-1-6/src/lib/krb4/prot_client.c b/krb5-1-6/src/lib/krb4/prot_client.c
new file mode 100644
index 000000000..315f7f08a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/prot_client.c
@@ -0,0 +1,370 @@
+/*
+ * lib/krb4/prot_client.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.  All
+ * Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Contains protocol encoders and decoders used by a krb4 client.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * encode_kdc_request
+ *
+ * Packet format is originally from g_in_tkt.c.
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ * 1 byte		KRB_PROT_VERSION	protocol version number
+ * 1 byte		AUTH_MSG_KDC_REQUEST |	message type
+ *			HOST_BYTE_ORDER		local byte order in lsb
+ * string		user			client's name
+ * string		instance		client's instance
+ * string		realm			client's realm
+ * 4 bytes		tlocal.tv_sec		timestamp in seconds
+ * 1 byte		life			desired lifetime
+ * string		service			service's name
+ * string		sinstance		service's instance
+ */
+int KRB5_CALLCONV
+krb4prot_encode_kdc_request(char *pname, char *pinst, char *prealm,
+			    KRB4_32 tlocal, int life,
+			    char *sname, char *sinst,
+			    char *preauth, int preauthlen,
+			    int chklen,	/* check input str len? */
+			    int le, /* little-endian? */
+			    KTEXT pkt)
+{
+    unsigned char *p;
+    int ret;
+    size_t snamelen, sinstlen;
+
+    p = pkt->dat;
+
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_KDC_REQUEST | !!le;
+
+    ret = krb4prot_encode_naminstrlm(pname, pinst, prealm, chklen,
+				     pkt, &p);
+    if (ret)
+	return ret;
+
+    snamelen = strlen(sname) + 1;
+    sinstlen = strlen(sinst) + 1;
+    if (chklen && (snamelen > ANAME_SZ || sinstlen > INST_SZ))
+	return KRB4PROT_ERR_OVERRUN;
+    if ((sizeof(pkt->dat) - (p - pkt->dat))
+	< (4 + 1 + snamelen + sinstlen + preauthlen))
+	return KRB4PROT_ERR_OVERRUN;
+
+    /* timestamp */
+    KRB4_PUT32(p, tlocal, le);
+
+    *p++ = life;
+
+    memcpy(p, sname, snamelen);
+    p += snamelen;
+    memcpy(p, sinst, sinstlen);
+    p += sinstlen;
+
+    if (preauthlen)
+	memcpy(p, preauth, (size_t)preauthlen);
+    p += preauthlen;
+
+    pkt->length = p - pkt->dat;
+    return KRB4PROT_OK;
+}
+
+/*
+ * decode_kdc_reply
+ */
+int KRB5_CALLCONV
+krb4prot_decode_kdc_reply(KTEXT pkt,
+			  int *le,
+			  char *pname, char *pinst, char *prealm,
+			  long *time_ws, int *n,
+			  unsigned long *x_date, int *kvno,
+			  KTEXT ciph)
+{
+    unsigned char *p;
+    int msg_type;
+    int ret;
+    unsigned int ciph_len;
+
+    p = pkt->dat;
+    if (pkt->length < 2)
+	return KRB4PROT_ERR_UNDERRUN;
+    if (*p++ != KRB_PROT_VERSION)
+	return KRB4PROT_ERR_PROT_VERS;
+    msg_type = *p++;
+    *le = msg_type & 1;
+    msg_type &= ~1;
+    if (msg_type != AUTH_MSG_KDC_REPLY)
+	return KRB4PROT_ERR_MSG_TYPE;
+
+    ret = krb4prot_decode_naminstrlm(ciph, &p, pname, pinst, prealm);
+    if (ret)
+	return ret;
+
+#define PKT_REMAIN (pkt->length - (p - pkt->dat))
+
+    if (PKT_REMAIN < (4		/* time */
+		      + 1	/* number of tickets */
+		      + 4	/* exp date */
+		      + 1	/* kvno */
+		      + 2))	/* ciph length */
+	return KRB4PROT_ERR_UNDERRUN;
+    if (time_ws != NULL)
+	KRB4_GET32(*time_ws, p, *le); /* XXX signed/unsigned */
+    else
+	p += 4;
+    if (n != NULL)
+	*n = *p++;
+    else
+	p++;
+    if (x_date != NULL)
+	KRB4_GET32(*x_date, p, *le);
+    else
+	p += 4;
+    if (kvno != NULL)
+	*kvno = *p++;
+    else
+	p++;
+    KRB4_GET16(ciph_len, p, *le);
+    if (PKT_REMAIN < ciph_len)
+	return KRB4PROT_ERR_UNDERRUN;
+    ciph->length = ciph_len;
+    memcpy(ciph->dat, p, (size_t)ciph->length);
+    return KRB4PROT_OK;
+#undef PKT_REMAIN
+}
+
+int KRB5_CALLCONV
+krb4prot_decode_ciph(KTEXT ciph, int le,
+		     C_Block session,
+		     char *name, char *inst, char *realm,
+		     int *life, int *kvno,
+		     KTEXT tkt, unsigned long *kdc_time)
+{
+    unsigned char *p;
+    int ret;
+
+    p = ciph->dat;
+    if (ciph->length < 8)
+	return KRB4PROT_ERR_UNDERRUN;
+    memcpy(session, p, 8);
+    p += 8;
+    ret = krb4prot_decode_naminstrlm(ciph, &p, name, inst, realm);
+    if (ret)
+	return ret;
+#define CIPH_REMAIN (ciph->length - (p - ciph->dat))
+    if (CIPH_REMAIN < (1	/* life */
+		       + 1	/* kvno */
+		       + 1))	/* tkt->length */
+	return KRB4PROT_ERR_UNDERRUN;
+    if (life != NULL)
+	*life = *p++;
+    else
+	p++;
+    if (kvno != NULL)
+	*kvno = *p++;
+    else
+	p++;
+    tkt->length = *p++;
+    if (CIPH_REMAIN < (tkt->length
+		       + 4))	/* kdc_time */
+	return KRB4PROT_ERR_UNDERRUN;
+    memcpy(tkt->dat, p, (size_t)tkt->length);
+    p += tkt->length;
+
+    if (kdc_time != NULL)
+	KRB4_GET32(*kdc_time, p, le);
+
+    return KRB4PROT_OK;
+#undef CIPH_REMAIN
+}
+
+/*
+ * encode_apreq
+ *
+ * The following was originally from mk_req.c.
+ *
+ * unsigned char	KRB_PROT_VERSION	protocol version no.
+ * unsigned char	AUTH_MSG_APPL_REQUEST	message type
+ * (least significant
+ * bit of above)	HOST_BYTE_ORDER		local byte ordering
+ * unsigned char	kvno from ticket	server's key version
+ * string		realm			server's realm
+ * unsigned char	tl			ticket length
+ * unsigned char	idl			request id length
+ * binary		ticket->dat		ticket for server
+ * binary		req_id->dat		request id
+ */
+int KRB5_CALLCONV
+krb4prot_encode_apreq(int kvno, char *realm,
+		      KTEXT tkt, KTEXT req_id,
+		      int chklen, /* check str len? */
+		      int le,	/* little-endian? */
+		      KTEXT pkt)
+{
+    unsigned char *p;
+    size_t realmlen;
+
+    p = pkt->dat;
+    /* Assume >= 3 bytes in a KTEXT. */
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_APPL_REQUEST | !!le;
+
+    *p++ = kvno;
+
+    realmlen = strlen(realm) + 1;
+    if (chklen && realmlen > REALM_SZ)
+	return KRB4PROT_ERR_OVERRUN;
+    if (tkt->length > 255 || req_id->length > 255)
+	return KRB4PROT_ERR_OVERRUN;
+    if ((sizeof(pkt->dat) - (p - pkt->dat))
+	< (realmlen
+	   + 1			/* tkt->length */
+	   + 1			/* req_id->length */
+	   + tkt->length + req_id->length))
+	return KRB4PROT_ERR_OVERRUN;
+
+    memcpy(p, realm, realmlen);
+    p += realmlen;
+
+    *p++ = tkt->length;
+    *p++ = req_id->length;
+    memcpy(p, tkt->dat, (size_t)tkt->length);
+    p += tkt->length;
+    memcpy(p, req_id->dat, (size_t)req_id->length);
+    p += req_id->length;
+
+    pkt->length = p - pkt->dat;
+    return KRB4PROT_OK;
+}
+
+/*
+ * encode_authent
+ *
+ * Encodes an authenticator (called req_id in some of the code for
+ * some weird reason).  Does not encrypt.
+ *
+ * The following packet layout is originally from mk_req.c.  It is
+ * rounded up to the next multiple of 8 bytes.
+ *
+ * string		cr.pname		{name, instance, and
+ * string		cr.pinst		realm of principal
+ * string		myrealm			making this request}
+ * 4 bytes		checksum		checksum argument given
+ * unsigned char	time_usecs		time (microseconds)
+ * 4 bytes		time_secs		time (seconds)
+ */
+int KRB5_CALLCONV
+krb4prot_encode_authent(char *pname, char *pinst, char *prealm,
+			KRB4_32 checksum,
+			int time_usec, long time_sec,
+			int chklen, /* check str lens? */
+			int le,	/* little-endian? */
+			KTEXT pkt)
+{
+    unsigned char *p;
+    int ret;
+
+    p = pkt->dat;
+    ret = krb4prot_encode_naminstrlm(pname, pinst, prealm, chklen,
+				     pkt, &p);
+    if (ret)
+	return ret;
+    if ((sizeof(pkt->dat) - (p - pkt->dat)) / 8
+	< (4			/* checksum */
+	   + 1			/* microsec */
+	   + 4			/* time */
+	   + 7) / 8)		/* roundoff */
+	return KRB4PROT_ERR_OVERRUN;
+
+    KRB4_PUT32(p, checksum, le);
+    *p++ = time_usec;
+    KRB4_PUT32(p, time_sec, le);
+
+    memset(p, 0, 7);		/* nul-pad */
+    pkt->length = (((p - pkt->dat) + 7) / 8) * 8;
+    return KRB4PROT_OK;
+}
+
+/*
+ * decode_error
+ *
+ * Decodes an error reply from the KDC.
+ */
+int KRB5_CALLCONV
+krb4prot_decode_error(KTEXT pkt, int *le,
+		      char *pname, char *pinst, char *prealm,
+		      unsigned long *time_ws,
+		      unsigned long *err, char *err_string)
+{
+    unsigned char *p;
+    int msg_type, ret, errstrlen;
+
+    p = pkt->dat;
+    if (pkt->length < 2)
+	return KRB4PROT_ERR_UNDERRUN;
+    if (*p++ != KRB_PROT_VERSION)
+	return KRB4PROT_ERR_PROT_VERS;
+    msg_type = *p++;
+    *le = msg_type & 1;
+    msg_type &= ~1;
+    if (msg_type != AUTH_MSG_ERR_REPLY)
+	return KRB4PROT_ERR_MSG_TYPE;
+
+    ret = krb4prot_decode_naminstrlm(pkt, &p, pname, pinst, prealm);
+    if (ret)
+	return ret;
+
+#define PKT_REMAIN (pkt->length - (p - pkt->dat))
+    if (PKT_REMAIN < (4		/* time */
+		      + 4))	/* err code */
+	return KRB4PROT_ERR_UNDERRUN;
+
+    if (time_ws != NULL)
+	KRB4_GET32(*time_ws, p, le);
+    else
+	p += 4;
+    if (err != NULL)
+	KRB4_GET32(*err, p, le);
+    else
+	p += 4;
+
+    if (PKT_REMAIN <= 0)	/* allow for missing error string */
+	return KRB4PROT_OK;
+
+    errstrlen = krb4int_strnlen((char *)p, PKT_REMAIN) + 1;
+    if (errstrlen <= 0)		/* If it's there, it must be nul-terminated. */
+	return KRB4PROT_ERR_OVERRUN;
+    if (err_string != NULL)
+	memcpy(err_string, p, (size_t)errstrlen);
+
+    return KRB4PROT_OK;
+#undef PKT_REMAIN
+}
diff --git a/krb5-1-6/src/lib/krb4/prot_common.c b/krb5-1-6/src/lib/krb4/prot_common.c
new file mode 100644
index 000000000..3e36de129
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/prot_common.c
@@ -0,0 +1,136 @@
+/*
+ * lib/krb4/prot_common.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.  All
+ * Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Contains some common code used by multiple encoders/decoders.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * encode_naminstrlm
+ *
+ * Takes input string triplet of a principal, encodes into PKT.
+ * Assumes that input strings are properly terminated.  If CHKLEN is
+ * non-zero, validate input string lengths against their respective
+ * limits.  The pointer P is the address of the moving pointer used by
+ * the caller, and is updated here.
+ *
+ * Returns zero on success, non-zero on failure.
+ *
+ * PKT->LENGTH is NOT updated.  The caller must update it.
+ */
+int KRB5_CALLCONV
+krb4prot_encode_naminstrlm(char *name, char *inst, char *realm,
+			   int chklen, /* check input str len? */
+			   KTEXT pkt, /* buffer to encode into */
+			   unsigned char **p /* moving pointer */)
+{
+    size_t namelen, instlen, realmlen;
+
+    namelen = strlen(name) + 1;
+    instlen = strlen(inst) + 1;
+    realmlen = strlen(realm) + 1;
+    if (chklen && (namelen > ANAME_SZ || instlen > INST_SZ
+		   || realmlen > REALM_SZ))
+	return KRB4PROT_ERR_OVERRUN;
+    if (*p - pkt->dat < namelen + instlen + realmlen)
+	return KRB4PROT_ERR_OVERRUN;
+    memcpy(*p, name, namelen);
+    *p += namelen;
+    memcpy(*p, inst, instlen);
+    *p += namelen;
+    memcpy(*p, realm, realmlen);
+    *p += namelen;
+    return KRB4PROT_OK;
+}
+
+/*
+ * decode_naminstrlm
+ *
+ * Grabs a string triplet corresponding to a principal.  The input
+ * buffer PKT should have its length properly set.  The pointer P is
+ * the address of the moving pointer used by the caller, and will be
+ * updated.  If any input pointer is NULL, merely skip the string.
+ *
+ * The output strings NAME, INST, and REALM are assumed to be of the
+ * correct sizes (ANAME_SZ, INST_SZ, REALM_SZ).
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
+int KRB5_CALLCONV
+krb4prot_decode_naminstrlm(KTEXT pkt, /* buffer to decode from */
+			   unsigned char **p, /* moving pointer */
+			   char *name, char *inst, char *realm)
+{
+    int len;
+
+#define PKT_REMAIN (pkt->length - (*p - pkt->dat))
+    if (PKT_REMAIN <= 0)
+	return KRB4PROT_ERR_UNDERRUN;
+    len = krb4int_strnlen((char *)*p, PKT_REMAIN) + 1;
+    if (len == 0 || len > ANAME_SZ)
+	return KRB4PROT_ERR_OVERRUN;
+    if (name != NULL)
+	memcpy(name, *p, (size_t)len);
+    *p += len;
+
+    if (PKT_REMAIN <= 0)
+	return KRB4PROT_ERR_UNDERRUN;
+    len = krb4int_strnlen((char *)*p, PKT_REMAIN) + 1;
+    if (len <= 0 || len > INST_SZ)
+	return KRB4PROT_ERR_OVERRUN;
+    if (name != NULL)
+	memcpy(inst, *p, (size_t)len);
+    *p += len;
+
+    if (PKT_REMAIN <= 0)
+	return KRB4PROT_ERR_UNDERRUN;
+    len = krb4int_strnlen((char *)*p, PKT_REMAIN) + 1;
+    if (len <= 0 || len > REALM_SZ)
+	return KRB4PROT_ERR_OVERRUN;
+    if (realm != NULL)
+	memcpy(realm, *p, (size_t)len);
+    *p += len;
+    return KRB4PROT_OK;
+#undef PKT_REMAIN
+}
+
+int KRB5_CALLCONV
+krb4prot_decode_header(KTEXT pkt,
+		       int *pver, int *msgtype, int *le)
+{
+    unsigned char *p;
+
+    p = pkt->dat;
+    if (pkt->length < 2)
+	return KRB4PROT_ERR_UNDERRUN;
+    *pver = *p++;
+    *msgtype = *p++;
+    *le = *msgtype & 1;
+    *msgtype &= ~1;
+    return KRB4PROT_OK;
+}
diff --git a/krb5-1-6/src/lib/krb4/prot_kdc.c b/krb5-1-6/src/lib/krb4/prot_kdc.c
new file mode 100644
index 000000000..aaaa9d00c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/prot_kdc.c
@@ -0,0 +1,461 @@
+/*
+ * lib/krb4/prot_kdc.c
+ *
+ * Copyright 1985--1988, 2000, 2001 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Contains the protocol encoders and decoders used by the KDC.
+ */
+
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+#include "port-sockets.h"
+
+/*
+ * encode_kdc_reply
+ *
+ * Encodes a reply from the KDC to the client.
+ *
+ * Returns KRB4PROT_OK on success, non-zero on failure.
+ *
+ * Caller is responsible for cleaning up OUTBUF.
+ *
+ * This packet layout description was originally in cr_auth_repl.c:
+ *
+ * 			variable
+ * type			or constant	   data
+ * ----			-----------	   ----
+ * unsigned char	KRB_PROT_VERSION   protocol version number
+ * 
+ * unsigned char	AUTH_MSG_KDC_REPLY protocol message type
+ * 
+ * [least significant	HOST_BYTE_ORDER	   sender's (server's) byte
+ *  bit of above field]			   order
+ * 
+ * string		pname		   principal's name
+ * 
+ * string		pinst		   principal's instance
+ * 
+ * string		prealm		   principal's realm
+ * 
+ * unsigned long	time_ws		   client's timestamp
+ * 
+ * unsigned char	n		   number of tickets
+ * 
+ * unsigned long	x_date		   expiration date
+ * 
+ * unsigned char	kvno		   master key version
+ * 
+ * short		cipher->length	   cipher length
+ * 
+ * binary		cipher->dat	   cipher data
+ */
+int KRB5_CALLCONV
+krb4prot_encode_kdc_reply(char *pname, char *pinst, char *prealm,
+			  long time_ws,
+			  int n, /* Number of tickets; 0 for krb4 (!) */
+			  unsigned long x_date,	/* exp date */
+			  int kvno,
+			  KTEXT cipher,	/* encrypted ticket */
+			  int chklen, /* check input str len? */
+			  int le, /* little-endian? */
+			  KTEXT outbuf)
+{
+    unsigned char *p;
+    int ret;
+
+    p = outbuf->dat;
+    /* This is really crusty. */
+    if (n != 0)
+	*p++ = 3;
+    else
+	*p++ = KRB_PROT_VERSION;
+    /* little-endianness based on input, usually big-endian, though. */
+    *p++ = AUTH_MSG_KDC_REPLY | !!le;
+
+    ret = krb4prot_encode_naminstrlm(pname, pinst, prealm, chklen,
+				     outbuf, &p);
+    if (ret)
+	return ret;
+
+    /* Check lengths */
+    if (cipher->length > 65535 || cipher->length < 0)
+	return KRB4PROT_ERR_OVERRUN;
+    if ((sizeof(outbuf->dat) - (p - outbuf->dat)
+	 < (4			/* timestamp */
+	    + 1			/* num of tickets */
+	    + 4			/* exp date */
+	    + 1			/* kvno */
+	    + 2			/* cipher->length */
+	    + cipher->length)))	/* cipher->dat */
+        return KRB4PROT_ERR_OVERRUN;
+
+    /* Workstation timestamp */
+    KRB4_PUT32(p, time_ws, le);
+
+    /* Number of tickets */
+    *p++ = n;
+
+    /* Expiration date */
+    KRB4_PUT32(p, x_date, le);
+
+    /* Now send the ciphertext and info to help decode it */
+    *p++ = kvno;
+    KRB4_PUT16(p, cipher->length, le);
+    memcpy(p, cipher->dat, (size_t)cipher->length);
+    p += cipher->length;
+
+    /* And return the packet */
+    outbuf->length = p - outbuf->dat;
+    return KRB4PROT_OK;
+}
+
+/*
+ * encode_ciph
+ *
+ * Encodes a "cipher" that is to be included in a KDC reply message.
+ *
+ * Caller is responsible for cleaning up CIPH.
+ *
+ * Returns KRB4PROT_OK on success, non-zero on failure.
+ *
+ * Packet format below is originally from cr_ciph.c:
+ *
+ * 			variable
+ * type			or constant	data
+ * ----			-----------	----
+ * 8 bytes		session		session key for client, service
+ * 
+ * string		service		service name
+ * 
+ * string		instance	service instance
+ * 
+ * string		realm		KDC realm
+ * 
+ * unsigned char	life		ticket lifetime
+ * 
+ * unsigned char	kvno		service key version number
+ * 
+ * unsigned char	tkt->length	length of following ticket
+ * 
+ * data			tkt->dat	ticket for service
+ * 
+ * 4 bytes		kdc_time	KDC's timestamp
+ *
+ * <=7 bytes		null		null pad to 8 byte multiple
+ */
+int KRB5_CALLCONV
+krb4prot_encode_ciph(C_Block session,
+		     char *name, char *inst, char *realm,
+		     unsigned long life, int kvno,
+		     KTEXT tkt,	/* ticket */
+		     unsigned long kdc_time,
+		     int chklen, /* check str lens? */
+		     int le,	/* little-endian? */
+		     KTEXT ciph) /* output buffer */
+{
+    unsigned char *p;
+    int ret;
+
+    p = ciph->dat;
+    /*
+     * Assume that there will be >= 8 bytes in a KTEXT.  If there
+     * aren't, we have worse problems.
+     */
+    memcpy(p, session, 8);
+    p += 8;
+
+    ret = krb4prot_encode_naminstrlm(name, inst, realm, chklen,
+				     ciph, &p);
+    if (ret)
+	return ret;
+    if (tkt->length > 255 || tkt->length < 0)
+	return KRB4PROT_ERR_OVERRUN;
+    if ((sizeof(ciph->dat) - (p - ciph->dat)) / 8
+	< (1			/* life */
+	   + 1			/* kvno */
+	   + 1			/* tkt->length */
+	   + tkt->length	/* tkt->dat */
+	   + 4			/* kdc_time */
+	   + 7) / 8)		/* roundoff */
+	return KRB4PROT_ERR_OVERRUN;
+
+    *p++ = life;
+    *p++ = kvno;
+    *p++ = tkt->length;
+
+    memcpy(p, tkt->dat, (size_t)tkt->length);
+    p += tkt->length;
+
+    KRB4_PUT32(p, kdc_time, le);
+
+    /* Guarantee null pad to multiple of 8 bytes */
+    memset(p, 0, 7);
+    ciph->length = (((p - ciph->dat) + 7) / 8) * 8;
+    return KRB4PROT_OK;
+}
+
+/*
+ * encode_tkt
+ *
+ * Encode ticket to include in a "cipher".  Does not encrypt.
+ *
+ * Caller is responsible for cleaning TKT.
+ *
+ * The length of the ticket is a multiple of
+ * eight bytes and is in tkt->length.
+ *
+ * If the ticket is not a multiple of eight bytes long, the ticket
+ * will contain nulls.
+ *
+ * Returns KRB4PROT_OK on success, non-zero on failure.
+ *
+ * The following packet layout is from cr_tkt.c:
+ *
+ * 			variable
+ * type			or constant	   data
+ * ----			-----------	   ----
+ * unsigned char	flags		   namely, HOST_BYTE_ORDER
+ * 
+ * string		pname		   client's name
+ * 
+ * string		pinstance	   client's instance
+ * 
+ * string		prealm		   client's realm
+ * 
+ * 4 bytes		paddress	   client's address
+ * 
+ * 8 bytes		session		   session key
+ * 
+ * 1 byte		life		   ticket lifetime
+ * 
+ * 4 bytes		time_sec	   KDC timestamp
+ * 
+ * string		sname		   service's name
+ * 
+ * string		sinstance	   service's instance
+ * 
+ * <=7 bytes		null		   null pad to 8 byte multiple
+ */
+int KRB5_CALLCONV
+krb4prot_encode_tkt(unsigned int flags,
+		    char *pname, char *pinst, char *prealm,
+		    unsigned long paddress,
+		    char *session,
+		    int life, long time_sec,
+		    char *sname, char *sinst,
+		    int chklen,	/* check str lens? */
+		    int le,	/* little-endian? */
+		    KTEXT tkt)	/* output buf */
+{
+    struct in_addr paddr;
+    unsigned char *p;
+    size_t snamelen, sinstlen;
+
+    /* Be really paranoid. */
+    if (sizeof(paddr.s_addr) != 4)
+	return KFAILURE;
+
+    p = tkt->dat;
+    /*
+     * Assume at least one byte in a KTEXT.  If not, we have bigger
+     * problems.  Also, bitwise-OR in the little-endian flag.
+     */
+    *p++ = flags | !!le;
+
+    if (krb4prot_encode_naminstrlm(pname, pinst, prealm, chklen,
+				   tkt, &p))
+	return KFAILURE;
+
+    snamelen = strlen(sname) + 1;
+    sinstlen = strlen(sinst) + 1;
+    if (life > 255 || life < 0)
+	return KFAILURE;
+    if (chklen && (snamelen > ANAME_SZ || sinstlen > INST_SZ))
+	return KFAILURE;
+    if ((sizeof(tkt->dat) - (p - tkt->dat)) / 8
+	< (4			/* address */
+	   + 8			/* session */
+	   + 1			/* life */
+	   + 4			/* issue time */
+	   + snamelen + sinstlen
+	   + 7) / 8)		/* roundoff */
+        return KFAILURE;
+
+    paddr.s_addr = paddress;
+    memcpy(p, &paddr.s_addr, sizeof(paddr.s_addr));
+    p += sizeof(paddr.s_addr);
+
+    memcpy(p, session, 8);
+    p += 8;
+    *p++ = life;
+    /* issue time */
+    KRB4_PUT32(p, time_sec, le);
+
+    memcpy(p, sname, snamelen);
+    p += snamelen;
+    memcpy(p, sinst, sinstlen);
+    p += sinstlen;
+
+    /* guarantee null padded ticket to multiple of 8 bytes */
+    memset(p, 0, 7);
+    tkt->length = ((p - tkt->dat + 7) / 8) * 8;
+    return KSUCCESS;
+}
+
+/*
+ * encode_err_reply
+ *
+ * Encode an error reply message from the KDC to the client.
+ *
+ * Returns KRB4PROT_OK on success, non-zero on error.
+ *
+ * The following packet layout description is from cr_err_repl.c:
+ * 
+ * type			variable	   data
+ *			or constant
+ * ----			-----------	   ----
+ * unsigned char	req_ack_vno	   protocol version number
+ * 
+ * unsigned char	AUTH_MSG_ERR_REPLY protocol message type
+ * 
+ * [least significant	HOST_BYTE_ORDER	   sender's (server's) byte
+ * bit of above field]			   order
+ * 
+ * string		pname		   principal's name
+ * 
+ * string		pinst		   principal's instance
+ * 
+ * string		prealm		   principal's realm
+ * 
+ * unsigned long	time_ws		   client's timestamp
+ * 
+ * unsigned long	e		   error code
+ * 
+ * string		e_string	   error text
+ */
+int KRB5_CALLCONV
+krb4prot_encode_err_reply(char *pname, char *pinst, char *prealm,
+			  unsigned long time_ws,
+			  unsigned long err, /* error code */
+			  char *err_string, /* error text */
+			  int chklen, /* check str lens? */
+			  int le, /* little-endian? */
+			  KTEXT pkt) /* output buf */
+{
+    unsigned char *p;
+    size_t err_stringlen;
+
+    p = pkt->dat;
+    /* Assume >= 2 bytes in KTEXT. */
+    *p++ = KRB_PROT_VERSION;
+    *p++ = AUTH_MSG_ERR_REPLY | !!le;
+
+    if (krb4prot_encode_naminstrlm(pname, pinst, prealm, chklen,
+				   pkt, &p))
+	return KFAILURE;
+
+    err_stringlen = strlen(err_string) + 1;
+    if ((sizeof(pkt->dat) - (p - pkt->dat))
+	< (4			/* timestamp */
+	   + 4			/* err code */
+	   + err_stringlen))
+	return KFAILURE;
+    /* ws timestamp */
+    KRB4_PUT32(p, time_ws, le);
+    /* err code */
+    KRB4_PUT32(p, err, le);
+    /* err text */
+    memcpy(p, err_string, err_stringlen);
+    p += err_stringlen;
+
+    /* And return */
+    pkt->length = p - pkt->dat;
+    return KSUCCESS;
+}
+
+/*
+ * decode_kdc_request
+ *
+ * Decode an initial ticket request sent from the client to the KDC.
+ *
+ * Packet format is described in g_in_tkt.c.
+ *
+ * Returns KRB4PROT_OK on success, non-zero on failure.
+ */
+int KRB5_CALLCONV
+krb4prot_decode_kdc_request(KTEXT pkt,
+			    int *le,
+			    char *pname, char *pinst, char *prealm,
+			    long *req_time, int *life,
+			    char *sname, char *sinst)
+{
+    unsigned char *p;
+    int msg_type, ret, len;
+
+    p = pkt->dat;
+
+    /* Get prot vers and msg type */
+    if (pkt->length < 2)
+	return KRB4PROT_ERR_UNDERRUN;
+    if (*p++ != KRB_PROT_VERSION)
+	return KRB4PROT_ERR_PROT_VERS;
+    msg_type = *p++;
+    *le = msg_type & 1;
+    msg_type &= ~1;
+    if (msg_type != AUTH_MSG_KDC_REQUEST)
+	return KRB4PROT_ERR_MSG_TYPE;
+
+    ret = krb4prot_decode_naminstrlm(pkt, &p, pname, pinst, prealm);
+    if (ret)
+	return ret;
+
+#define PKT_REMAIN (pkt->length - (p - pkt->dat))
+
+    if (PKT_REMAIN < (4		/* time */
+		      + 1))	/* life */
+	return KRB4PROT_ERR_UNDERRUN;
+
+    KRB4_GET32(*req_time, p, *le);
+
+    *life = *p++;
+
+    if (PKT_REMAIN <= 0)
+	return KRB4PROT_ERR_UNDERRUN;
+    len = krb4int_strnlen((char *)p, PKT_REMAIN) + 1;
+    if (len <= 0 || len > ANAME_SZ)
+	return KRB4PROT_ERR_OVERRUN;
+    memcpy(sname, p, (size_t)len);
+    p += len;
+
+    if (PKT_REMAIN <= 0)
+	return KRB4PROT_ERR_UNDERRUN;
+    len = krb4int_strnlen((char *)p, PKT_REMAIN) + 1;
+    if (len <= 0 || len > INST_SZ)
+	return KRB4PROT_ERR_OVERRUN;
+    memcpy(sinst, p, (size_t)len);
+    p += len;
+
+    /* XXX krb4 preauth? */
+    return KRB4PROT_OK;
+}
diff --git a/krb5-1-6/src/lib/krb4/put_svc_key.c b/krb5-1-6/src/lib/krb4/put_svc_key.c
new file mode 100644
index 000000000..dda60163d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/put_svc_key.c
@@ -0,0 +1,94 @@
+/* lib/krb/put_svc_key.c */
+/* Copyright 1994 Cygnus Support */
+/* Mark W. Eichin */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * put_svc_key is a simple version of what 'ksrvutil add' provides, for some
+ *    circumstances when service keys are distributed by applictions.
+ *
+ * Caveats: currently uses UNIX I/O (open, read) rather than stdio - this 
+ *    should be fixed.
+ *          It could probably be made more general (and then actually be used
+ *    by ksrvutil.) This version supports just enough to be useful.
+ */
+
+#include "krb.h"
+#include "krb4int.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define KEYSZ sizeof(C_Block)
+/* strict put_svc_key.
+   The srvtab must already exist;
+   The key (exact match) must already be in the file;
+   version numbers are not checked.
+ */
+int KRB5_CALLCONV
+put_svc_key(sfile,name,inst,realm,newvno,key)
+	char *sfile;
+	char *name;
+	char *inst;
+	char *realm;
+	int newvno;
+	char *key;
+{
+	int fd;
+	char fname[SNAME_SZ], finst[INST_SZ], frlm[REALM_SZ];
+	unsigned char fvno;
+	char fkey[KEYSZ];
+
+	if (!sfile)
+		sfile = KEYFILE;
+
+	if ((fd = open(sfile, O_RDWR)) < 0)
+		return KFAILURE;
+
+	while(getst(fd,fname,SNAME_SZ) > 0) {
+		getst(fd,finst,INST_SZ);
+		getst(fd,frlm,REALM_SZ);
+		if (!strcmp(fname,name)
+		    && !strcmp(finst,inst)
+		    && !strcmp(frlm,realm)) {
+			/* all matched, so write new data */
+			fvno = newvno;
+			lseek(fd,0,SEEK_CUR);
+			if (write(fd,&fvno,1) != 1) {
+				close(fd);
+				return KFAILURE;
+			}
+			if (write(fd,key,KEYSZ) != KEYSZ) {
+				close(fd);
+				return KFAILURE;
+			}
+			close(fd);
+			return KSUCCESS;
+		}
+                if (read(fd,&fvno,1) != 1) {
+                        close(fd);
+                        return KFAILURE;
+                }
+                if (read(fd,fkey,KEYSZ) != KEYSZ) {
+                        close(fd);
+                        return KFAILURE;
+                }
+	}
+	/* never found it */
+	close(fd);
+	return KFAILURE;
+}
diff --git a/krb5-1-6/src/lib/krb4/rd_err.c b/krb5-1-6/src/lib/krb4/rd_err.c
new file mode 100644
index 000000000..47f5167b5
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/rd_err.c
@@ -0,0 +1,78 @@
+/*
+ * lib/krb4/rd_err.c
+ *
+ * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Steve Miller    Project Athena  MIT/DEC
+ */
+
+#include <string.h>
+
+#include "krb.h"
+#include "prot.h"
+
+/*
+ * Given an AUTH_MSG_APPL_ERR message, "in" and its length "in_length",
+ * return the error code from the message in "code" and the text in
+ * "m_data" as follows:
+ *
+ *	m_data->app_data	points to the error text
+ *	m_data->app_length	points to the length of the error text
+ *
+ * If all goes well, return RD_AP_OK.  If the version number
+ * is wrong, return RD_AP_VERSION, and if it's not an AUTH_MSG_APPL_ERR
+ * type message, return RD_AP_MSG_TYPE.
+ *
+ * The AUTH_MSG_APPL_ERR message format can be found in mk_err.c
+ */
+
+int KRB5_CALLCONV
+krb_rd_err(in, in_length, code, m_data)
+    u_char *in;                 /* pointer to the msg received */
+    u_long in_length;           /* of in msg */
+    long *code;                 /* received error code */
+    MSG_DAT *m_data;
+{
+    register u_char *p;
+    int le;
+    unsigned KRB4_32 raw_code;
+
+    p = in;                     /* beginning of message */
+
+    if (in_length < 1 + 1 + 4)
+	return RD_AP_MODIFIED;	/* XXX should have better error code */
+    if (*p++ != KRB_PROT_VERSION)
+        return RD_AP_VERSION;
+    if (((*p) & ~1) != AUTH_MSG_APPL_ERR)
+        return RD_AP_MSG_TYPE;
+    le = *p++ & 1;
+
+    KRB4_GET32(raw_code, p, le);
+    *code = raw_code;		/* XXX unsigned->signed conversion! */
+
+    m_data->app_data = p;       /* we're now at the error text
+                                 * message */
+    m_data->app_length = p - in;
+
+    return RD_AP_OK;           /* OK == 0 */
+}
diff --git a/krb5-1-6/src/lib/krb4/rd_preauth.c b/krb5-1-6/src/lib/krb4/rd_preauth.c
new file mode 100644
index 000000000..b30838cc4
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/rd_preauth.c
@@ -0,0 +1,62 @@
+/* rd_preauth.c */
+/* part of Cygnus Network Security */
+/* Copyright 1994 Cygnus Support */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "krb_db.h"
+#include "prot.h"
+#include "des.h"
+#include "krb4int.h"
+#include <string.h>
+
+/* #define      KERB_ERR_PREAUTH_SHORT		11 */
+/* #define	KERB_ERR_PREAUTH_MISMATCH	12 */
+
+
+int
+krb_rd_preauth(pkt, preauth_p, preauth_len, auth_pr, key)
+    KTEXT pkt;
+    char *preauth_p;
+    int preauth_len;
+    Principal *auth_pr;
+    des_cblock key;
+{
+    int st;
+    char *name_p;
+
+    name_p = auth_pr->name;
+   
+#ifndef NOENCRYPTION
+    /* Decrypt preauth_p using key as the key and initialization vector. */
+    /* check preauth_len */
+    if ((((strlen(name_p) + 1) / 8) + 1) * 8 != preauth_len)
+	return KERB_ERR_PREAUTH_SHORT;
+    else {
+	des_key_schedule key_s;
+
+	if (des_key_sched(key, key_s)) {
+	    return 1;
+	}
+	des_pcbc_encrypt((des_cblock *)preauth_p, (des_cblock *)preauth_p,
+			 (long)preauth_len, key_s, (des_cblock *)key, 
+			 DES_DECRYPT);
+	memset(key_s, 0, sizeof(key_s));
+    }
+#endif /* R3_NO_MODIFICATIONS */
+
+    /* since the preauth data has the trailing 0, this just works */
+    st = strcmp(preauth_p, name_p);
+    if (st)
+	return KERB_ERR_PREAUTH_MISMATCH;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb4/rd_priv.c b/krb5-1-6/src/lib/krb4/rd_priv.c
new file mode 100644
index 000000000..1ba60081c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/rd_priv.c
@@ -0,0 +1,233 @@
+/*
+ * lib/krb4/rd_priv.c
+ *
+ * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * This routine dissects a a Kerberos 'private msg', decrypting it,
+ * checking its integrity, and returning a pointer to the application
+ * data contained and its length.
+ *
+ * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...).  If
+ * the return value is RD_AP_TIME, then either the times are too far
+ * out of synch, OR the packet was modified.
+ *
+ * Steve Miller    Project Athena  MIT/DEC
+ */
+
+/* system include files */
+#include <stdio.h>
+#include <string.h>
+
+/* application include files */
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include "lsb_addr_cmp.h"
+#include "port-sockets.h"
+
+extern int krb_debug;
+
+/* This one is exported, for use by krb_mk_priv.  */
+int private_msg_ver = KRB_PROT_VERSION;
+
+/*
+#ifdef NOENCRPYTION
+ * krb_rd_priv() checks the integrity of an
+#else
+ * krb_rd_priv() decrypts and checks the integrity of an
+#endif
+ * AUTH_MSG_PRIVATE message.  Given the message received, "in",
+ * the length of that message, "in_length", the key "schedule"
+#ifdef NOENCRYPTION
+ * and "key", and the network addresses of the
+#else
+ * and "key" to decrypt with, and the network addresses of the
+#endif
+ * "sender" and "receiver" of the message, krb_rd_safe() returns
+ * RD_AP_OK if the message is okay, otherwise some error code.
+ *
+ * The message data retrieved from "in" are returned in the structure
+#ifdef NOENCRYPTION
+ * "m_data".  The pointer to the application data
+#else
+ * "m_data".  The pointer to the decrypted application data
+#endif
+ * (m_data->app_data) refers back to the appropriate place in "in".
+ *
+ * See the file "mk_priv.c" for the format of the AUTH_MSG_PRIVATE
+ * message.  The structure containing the extracted message
+ * information, MSG_DAT, is defined in "krb.h".
+ */
+
+long KRB5_CALLCONV
+krb_rd_priv(in, in_length, schedule, key, sender, receiver, m_data)
+    u_char *in;			/* pointer to the msg received */
+    unsigned KRB4_32 in_length; /* length of "in" msg */
+    Key_schedule schedule;	/* precomputed key schedule */
+    C_Block *key;		/* encryption key for seed and ivec */
+    struct sockaddr_in *sender;
+    struct sockaddr_in *receiver;
+    MSG_DAT *m_data;		/*various input/output data from msg */
+{
+    register u_char *p,*q;
+    int v, t, le;
+    struct in_addr src_addr;
+    unsigned KRB4_32 c_length;
+    int swap_bytes;
+    unsigned KRB4_32 t_local;
+    KRB4_32 delta_t;		/* Difference between timestamps */
+
+    p = in;			/* beginning of message */
+#define IN_REMAIN (in_length - (p - in))
+    swap_bytes = 0;
+
+    if (IN_REMAIN < 1 + 1 + 4)
+	return RD_AP_MODIFIED;
+    v = *p++;
+    if (v != KRB_PROT_VERSION && v != 3)
+        return RD_AP_VERSION;
+    private_msg_ver = v;
+    t = *p++;
+    if ((t & ~1) != AUTH_MSG_PRIVATE)
+        return RD_AP_MSG_TYPE;
+    le = t & 1;
+
+    /* get cipher length */
+    KRB4_GET32(c_length, p, le);
+    /* check for rational length so we don't go comatose */
+    if (IN_REMAIN < c_length)
+        return RD_AP_MODIFIED;
+
+#ifndef NOENCRYPTION
+    /*
+     * decrypt to obtain length, timestamps, app_data, and checksum
+     * use the session key as an ivec
+     */
+#endif
+
+    q = p;			/* mark start of encrypted stuff */
+
+#ifndef NOENCRYPTION
+    /* pcbc decrypt, use key as ivec */
+    pcbc_encrypt((C_Block *)q, (C_Block *)q, (long)c_length,
+                 schedule, key, DECRYPT);
+#endif
+
+    /* safely get application data length */
+    KRB4_GET32(m_data->app_length, p, le);
+
+    if (IN_REMAIN < m_data->app_length + 4 + 1 + 4)
+	return RD_AP_MODIFIED;
+
+#ifndef NOENCRYPTION
+    /* we're now at the decrypted application data */
+#endif
+    m_data->app_data = p;
+
+    p += m_data->app_length;
+
+    /* safely get time_5ms */
+    m_data->time_5ms = *p++;
+
+    /* safely get src address */
+    memcpy(&src_addr.s_addr, p, sizeof(src_addr.s_addr));
+    /* don't swap, net order always */
+    p += sizeof(src_addr.s_addr);
+
+    if (!krb_ignore_ip_address) {
+	switch (sender->sin_family) {
+	case AF_INET:
+	    if (src_addr.s_addr != sender->sin_addr.s_addr)
+		return RD_AP_MODIFIED;
+	    break;
+#ifdef KRB5_USE_INET6
+	case AF_INET6:
+	    if (IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr)
+		&& !memcmp (&src_addr.s_addr,
+			    12 + (char *) &((struct sockaddr_in6 *)sender)->sin6_addr,
+			    4))
+		break;
+	    /* Not v4 mapped?  Not ignoring addresses?  You lose.  */
+	    return RD_AP_MODIFIED;
+#endif
+	default:
+	    return RD_AP_MODIFIED;
+	}
+    }
+
+    /* safely get time_sec */
+    KRB4_GET32(m_data->time_sec, p, le);
+
+    /* check direction bit is the sign bit */
+    /* For compatibility with broken old code, compares are done in VAX 
+       byte order (LSBFIRST) */ 
+    /* However, if we don't have good ip addresses anyhow, just clear
+       the bit. This makes it harder to detect replay of sent packets
+       back to the receiver, but most higher level protocols can deal
+       with that more directly. */
+    if (krb_ignore_ip_address) {
+	if (m_data->time_sec < 0)
+	    m_data->time_sec = -m_data->time_sec;
+    } else
+	switch (krb4int_address_less (sender, receiver)) {
+	case 1:
+	    m_data->time_sec = -m_data->time_sec;
+	    break;
+	case -1:
+	    if (m_data->time_sec < 0)
+		m_data->time_sec = -m_data->time_sec;
+	    break;
+	}
+
+    /* check the time integrity of the msg */
+    t_local = TIME_GMT_UNIXSEC;
+    delta_t = t_local - m_data->time_sec;
+    if (delta_t < 0)
+	delta_t = -delta_t;	/* Absolute value of difference */
+    if (delta_t > CLOCK_SKEW)
+        return RD_AP_TIME;	/* XXX should probably be better code */
+    DEB(("\ndelta_t = %d", delta_t));
+
+    /*
+     * caller must check timestamps for proper order and
+     * replays, since server might have multiple clients
+     * each with its own timestamps and we don't assume
+     * tightly synchronized clocks.
+     */
+
+#ifdef notdef
+    memcpy((char *)&cksum, (char *) p, sizeof(cksum));
+    if (swap_bytes) cksum = krb4_swab32(cksum)
+    /*
+     * calculate the checksum of the length, sequence,
+     * and input data, on the sending byte order!!
+     */
+    calc_cksum = quad_cksum(q, NULL, p-q, 0, key);
+
+    DEB (("\ncalc_cksum = %u, received cksum = %u",
+	       calc_cksum, cksum));
+    if (cksum != calc_cksum)
+	return RD_AP_MODIFIED;
+#endif
+    return RD_AP_OK;        /* OK == 0 */
+}
diff --git a/krb5-1-6/src/lib/krb4/rd_req.c b/krb5-1-6/src/lib/krb4/rd_req.c
new file mode 100644
index 000000000..a1d70c643
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/rd_req.c
@@ -0,0 +1,543 @@
+/*
+ * lib/krb4/rd_req.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000, 2001, 2002 by the
+ * Massachusetts Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "des.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+#include <krb5.h>
+#include <krb54proto.h>
+
+extern int krb_ap_req_debug;
+
+static int
+krb_rd_req_with_key(KTEXT, char *, char *, KRB_UINT32, AUTH_DAT *,
+		    Key_schedule, krb5_keyblock *);
+
+/* declared in krb.h */
+int krb_ignore_ip_address = 0;
+
+/*
+ * Keep the following information around for subsequent calls
+ * to this routine by the same server using the same key.
+ */
+
+static Key_schedule serv_key;	/* Key sched to decrypt ticket */
+static C_Block ky;              /* Initialization vector */
+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
+ * key or password string and returns a DES key (either the original
+ * key, or the password converted into a DES key) and a key schedule
+ * for it.
+ *
+ * krb_rd_req() reads an authentication request and returns information
+ * about the identity of the requestor, or an indication that the
+ * identity information was not authentic.
+ */
+
+/*
+ * krb_set_key() takes as its first argument either a DES key or a
+ * password string.  The "cvt" argument indicates how the first
+ * argument "key" is to be interpreted: if "cvt" is null, "key" is
+ * taken to be a DES key; if "cvt" is non-null, "key" is taken to
+ * be a password string, and is converted into a DES key using
+ * string_to_key().  In either case, the resulting key is returned
+ * in the external static variable "ky".  A key schedule is
+ * generated for "ky" and returned in the external static variable
+ * "serv_key".
+ *
+ * This routine returns the return value of des_key_sched.
+ *
+ * krb_set_key() needs to be in the same .o file as krb_rd_req() so that
+ * the key set by krb_set_key() is available in private storage for
+ * krb_rd_req().
+ */
+
+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;
+#else /* Encrypt */
+    if (cvt)
+        string_to_key(key, ky);
+    else
+        memcpy((char *)ky, key, 8);
+    return des_key_sched(ky,serv_key);
+#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
+ * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(),
+ * checks its integrity and returns a judgement as to the requestor's
+ * identity.
+ *
+ * The "authent" argument is a pointer to the received message.
+ * The "service" and "instance" arguments name the receiving server,
+ * and are used to get the service's ticket to decrypt the ticket
+ * in the message, and to compare against the server name inside the
+ * ticket.  "from_addr" is the network address of the host from which
+ * the message was received; this is checked against the network
+ * address in the ticket.  If "from_addr" is zero, the check is not
+ * performed.  "ad" is an AUTH_DAT structure which is
+ * filled in with information about the sender's identity according
+ * to the authenticator and ticket sent in the message.  Finally,
+ * "fn" contains the name of the file containing the server's key.
+ * (If "fn" is NULL, the server's key is assumed to have been set
+ * by krb_set_key().  If "fn" is the null string ("") the default
+ * file KEYFILE, defined in "krb.h", is used.)
+ *
+ * krb_rd_req() returns RD_AP_OK if the authentication information
+ * was genuine, or one of the following error codes (defined in
+ * "krb.h"):
+ *
+ *	RD_AP_VERSION		- wrong protocol version number
+ *	RD_AP_MSG_TYPE		- wrong message type
+ *	RD_AP_UNDEC		- couldn't decipher the message
+ *	RD_AP_INCON		- inconsistencies found
+ *	RD_AP_BADD		- wrong network address
+ *	RD_AP_TIME		- client time (in authenticator)
+ *				  too far off server time
+ *	RD_AP_NYV		- Kerberos time (in ticket) too
+ *				  far off server time
+ *	RD_AP_EXP		- ticket expired
+ *
+ * For the message format, see krb_mk_req().
+ *
+ * Mutual authentication is not implemented.
+ */
+
+static int
+krb_rd_req_with_key(authent, service, instance, from_addr, ad, ks, k5key)
+    register KTEXT authent;	/* The received message */
+    char *service;		/* Service name */
+    char *instance;		/* Service instance */
+    unsigned KRB4_32 from_addr; /* Net address of originating host */
+    AUTH_DAT *ad;		/* Structure to be filled in */
+    Key_schedule ks;
+    krb5_keyblock *k5key;
+{
+    KTEXT_ST ticket;		/* Temp storage for ticket */
+    KTEXT tkt = &ticket;
+    KTEXT_ST req_id_st;		/* Temp storage for authenticator */
+    register KTEXT req_id = &req_id_st;
+
+    char realm[REALM_SZ];	/* Realm of issuing kerberos */
+    Key_schedule seskey_sched; /* Key sched for session key */
+    char sname[SNAME_SZ];	/* Service name from ticket */
+    char iname[INST_SZ];	/* Instance name from ticket */
+    char r_aname[ANAME_SZ];	/* Client name from authenticator */
+    char r_inst[INST_SZ];	/* Client instance from authenticator */
+    char r_realm[REALM_SZ];	/* Client realm from authenticator */
+    unsigned int r_time_ms;     /* Fine time from authenticator */
+    unsigned KRB4_32 r_time_sec;   /* Coarse time from authenticator */
+    register unsigned char *ptr; /* For stepping through */
+    unsigned KRB4_32 t_local;	/* Local time on our side of the protocol */
+    KRB4_32 delta_t;      	/* Time in authenticator minus local time */
+#ifdef KRB_CRYPT_DEBUG
+    KRB4_32 tkt_age;		/* Age of ticket */
+#endif
+    int le;			/* is little endian? */
+    int mutual;			/* Mutual authentication requested? */
+    int t;			/* msg type */
+    unsigned char s_kvno;	/* Version number of the server's key
+				   Kerberos used to encrypt ticket */
+    int ret;
+    int len;
+
+    tkt->mbz = req_id->mbz = 0;
+
+    if (authent->length < 1 + 1 + 1)
+	return RD_AP_MODIFIED;
+
+    ptr = authent->dat;
+#define AUTHENT_REMAIN (authent->length - (ptr - authent->dat))
+
+    /* get msg version, type and byte order, and server key version */
+
+    /* check version */
+    if (KRB_PROT_VERSION != *ptr++)
+        return RD_AP_VERSION;
+
+    /* byte order */
+    t = *ptr++;
+    le = t & 1;
+
+    /* check msg type */
+    mutual = 0;
+    switch (t & ~1) {
+    case AUTH_MSG_APPL_REQUEST:
+        break;
+    case AUTH_MSG_APPL_REQUEST_MUTUAL:
+        mutual++;
+        break;
+    default:
+        return RD_AP_MSG_TYPE;
+    }
+
+#ifdef lint
+    /* XXX mutual is set but not used; why??? */
+    /* this is a crock to get lint to shut up */
+    if (mutual)
+        mutual = 0;
+#endif /* lint */
+    s_kvno = *ptr++;		/* get server key version */
+    len = krb4int_strnlen((char *)ptr, AUTHENT_REMAIN) + 1;
+    if (len <= 0 || len > sizeof(realm)) {
+	return RD_AP_MODIFIED;  /* must have been modified, the client wouldn't
+	                           try to trick us with wacky data */
+    }
+    /* And the realm of the issuing KDC */
+    (void)memcpy(realm, ptr, (size_t)len);
+    ptr += len;			/* skip the realm "hint" */
+
+    /* Get ticket length */
+    tkt->length = *ptr++;
+    /* Get authenticator length while we're at it. */
+    req_id->length = *ptr++;
+    if (AUTHENT_REMAIN < tkt->length + req_id->length)
+	return RD_AP_MODIFIED;
+    /* Copy ticket */
+    memcpy(tkt->dat, ptr, (size_t)tkt->length);
+    ptr += tkt->length;
+
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_ap_req_debug)
+        log("ticket->length: %d",tkt->length);
+    if (krb_ap_req_debug)
+	log("authent->length: %d", authent->length);
+#endif
+
+#ifndef NOENCRYPTION
+    /* Decrypt and take apart ticket */
+#endif
+
+    if (k5key == NULL) {
+	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,ks)) {
+#ifdef KRB_CRYPT_DEBUG
+	    log("Can't decode ticket");
+#endif
+	    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,
+			    k5key)) {
+	    return RD_AP_UNDEC;
+	}
+    }
+
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_ap_req_debug) {
+        log("Ticket Contents.");
+        log(" Aname:   %s%s%s@%s",ad->pname,
+	    ((int)*(ad->pinst) ? "." : ""), ad->pinst,
+            ((int)*(ad->prealm) ? ad->prealm : "Athena"));
+        log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname);
+	log("    sname=%s, sinst=%s", sname, iname);
+    }
+#endif
+
+    /* Extract the authenticator */
+    memcpy(req_id->dat, ptr, (size_t)req_id->length);
+
+#ifndef NOENCRYPTION
+    /* And decrypt it with the session key from the ticket */
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_ap_req_debug) log("About to decrypt authenticator");
+#endif
+
+    key_sched(ad->session, seskey_sched);
+    pcbc_encrypt((C_Block *)req_id->dat, (C_Block *)req_id->dat,
+                 (long)req_id->length,
+		 seskey_sched, &ad->session, DES_DECRYPT);
+    memset(seskey_sched, 0, sizeof(seskey_sched));
+
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_ap_req_debug) log("Done.");
+#endif
+#endif /* NOENCRYPTION */
+
+    ptr = req_id->dat;
+#define REQID_REMAIN (req_id->length - (ptr - req_id->dat))
+
+    ret = RD_AP_MODIFIED;
+
+    len = krb4int_strnlen((char *)ptr, REQID_REMAIN) + 1;
+    if (len <= 0 || len > ANAME_SZ)
+	goto cleanup;
+    memcpy(r_aname, ptr, (size_t)len); /* Authentication name */
+    ptr += len;
+    len = krb4int_strnlen((char *)ptr, REQID_REMAIN) + 1;
+    if (len <= 0 || len > INST_SZ)
+	goto cleanup;
+    memcpy(r_inst, ptr, (size_t)len); /* Authentication instance */
+    ptr += len;
+    len = krb4int_strnlen((char *)ptr, REQID_REMAIN) + 1;
+    if (len <= 0 || len > REALM_SZ)
+	goto cleanup;
+    memcpy(r_realm, ptr, (size_t)len); /* Authentication name */
+    ptr += len;
+
+    if (REQID_REMAIN < 4 + 1 + 4)
+	goto cleanup;
+    KRB4_GET32(ad->checksum, ptr, le);
+    r_time_ms = *ptr++;		/* Time (fine) */
+#ifdef lint
+    /* XXX r_time_ms is set but not used.  why??? */
+    /* this is a crock to get lint to shut up */
+    if (r_time_ms)
+        r_time_ms = 0;
+#endif /* lint */
+    /* Time (coarse) */
+    KRB4_GET32(r_time_sec, ptr, le);
+
+    /* Check for authenticity of the request */
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_ap_req_debug)
+        log("Pname:   %s %s",ad->pname,r_aname);
+#endif
+
+    ret = RD_AP_INCON;
+    if (strcmp(ad->pname,r_aname) != 0)
+	goto cleanup;
+    if (strcmp(ad->pinst,r_inst) != 0)
+	goto cleanup;
+
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_ap_req_debug)
+        log("Realm:   %s %s",ad->prealm,r_realm);
+#endif
+
+    if (strcmp(ad->prealm,r_realm) != 0)
+	goto cleanup;
+
+    /* check the time integrity of the msg */
+    ret = RD_AP_TIME;
+    t_local = TIME_GMT_UNIXSEC;
+    delta_t = t_local - r_time_sec;
+    if (delta_t < 0) delta_t = -delta_t;  /* Absolute value of difference */
+    if (delta_t > CLOCK_SKEW) {
+#ifdef KRB_CRYPT_DEBUG
+        if (krb_ap_req_debug)
+            log("Time out of range: %d - %d = %d",
+                time_secs, r_time_sec, delta_t);
+#endif
+	goto cleanup;
+    }
+
+    /* Now check for expiration of ticket */
+
+    ret = RD_AP_NYV;
+#ifdef KRB_CRYPT_DEBUG
+    tkt_age = t_local - ad->time_sec;
+    if (krb_ap_req_debug)
+        log("Time: %d Issue Date: %d Diff: %d Life %x",
+            time_secs, ad->time_sec, tkt_age, ad->life);
+#endif
+    if (t_local < ad->time_sec) {
+        if ((ad->time_sec - t_local) > CLOCK_SKEW)
+	    goto cleanup;
+    } else if (krb_life_to_time((KRB4_32)ad->time_sec, ad->life)
+	     < t_local + CLOCK_SKEW) {
+        /*
+	 * This calculation is different than the same expiration
+	 * calculation in  krb5.  In krb5  the ticket lasts for
+	 * clock_skew seconds longer than its expiration; in krb4 it
+	 * lasts clock_skew seconds less.  This difference is
+	 * necessary to avoid using an almost expired tgt to get a new
+	 * tgt that will last for another 5 minutes.  This code
+	 * interacts with the login in src/kdc/kerberos_v4.c to
+	 * back-date tickets to avoid them expiring late.  The
+	 * combination may be overly conservative, but I'm fairly sure
+	 * either  removing the kerberos_v4 backdating or replacing
+	 * this check with the krb5 check is sufficient to create a
+	 * security problem.
+	 */
+	ret = RD_AP_EXP;
+	goto cleanup;
+    }
+
+#ifdef KRB_CRYPT_DEBUG
+    if (krb_ap_req_debug)
+        log("Address: %d %d",ad->address,from_addr);
+#endif
+
+    if (!krb_ignore_ip_address
+	&& from_addr && (ad->address != from_addr)) {
+	ret = RD_AP_BADD;
+	goto cleanup;
+    }
+
+    /* All seems OK */
+    ad->reply.length = 0;
+    ret = 0;
+
+cleanup:
+    if (ret) {
+	/* Stomp on session key if there is an error. */
+	memset(ad->session, 0, sizeof(ad->session));
+	return ret;
+    }
+
+    return RD_AP_OK;
+}
+
+int KRB5_CALLCONV
+krb_rd_req_int(authent, service, instance, from_addr, ad, key)
+    KTEXT authent;		/* The received message */
+    char *service;		/* Service name */
+    char *instance;		/* Service instance */
+    KRB_UINT32 from_addr;	/* Net address of originating host */
+    AUTH_DAT *ad;		/* Structure to be filled in */
+    C_Block key;		/* Key to decrypt ticket with */
+{
+    Key_schedule ks;
+    int ret;
+
+    do {
+	ret = des_key_sched(key, ks);
+	if (ret) break;
+	ret = krb_rd_req_with_key(authent, service, instance,
+				  from_addr, ad, ks, NULL);
+    } while (0);
+    memset(ks, 0, sizeof(ks));
+    return ret;
+}
+
+int KRB5_CALLCONV
+krb_rd_req(authent, service, instance, from_addr, ad, fn)
+    register KTEXT authent;	/* The received message */
+    char *service;		/* Service name */
+    char *instance;		/* Service instance */
+    unsigned KRB4_32 from_addr; /* Net address of originating host */
+    AUTH_DAT *ad;		/* Structure to be filled in */
+    char *fn;		/* Filename to get keys from */
+{
+    unsigned char *ptr;
+    unsigned char s_kvno;
+    char realm[REALM_SZ];
+    unsigned char skey[KKEY_SZ];
+#ifdef KRB4_USE_KEYTAB
+    krb5_keyblock keyblock;
+#endif
+    int len;
+    int status;
+
+#define AUTHENT_REMAIN (authent->length - (ptr - authent->dat))
+    if (authent->length < 3)
+	return RD_AP_MODIFIED;
+    ptr = authent->dat + 2;
+    s_kvno = *ptr++;		/* get server key version */
+    len = krb4int_strnlen((char *)ptr, AUTHENT_REMAIN) + 1;
+    if (len <= 0 || len > sizeof(realm))
+	return RD_AP_MODIFIED;
+    (void)memcpy(realm, ptr, (size_t)len);
+#undef AUTHENT_REMAIN
+    /*
+     * If "fn" is NULL, key info should already be set; don't
+     * bother with ticket file.  Otherwise, check to see if we
+     * already have key info for the given server and key version
+     * (saved in the static st_* variables).  If not, go get it
+     * from the ticket file.  If "fn" is the null string, use the
+     * default ticket file.
+     */
+    if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance)
+	       || strcmp(st_rlm,realm) || (st_kvno != s_kvno))) {
+        if (*fn == 0)
+	    fn = KEYFILE;
+        st_kvno = s_kvno;
+        if (read_service_key(service,instance,realm, (int)s_kvno,
+			     fn, (char *)skey) == 0) {
+	    if ((status = krb_set_key((char *)skey,0)))
+		return(status);
+#ifdef KRB4_USE_KEYTAB
+	} else if (krb54_get_service_keyblock(service, instance,
+					      realm, (int)s_kvno,
+					      fn, &keyblock) == 0) {
+	    krb_set_key_krb5(krb5__krb4_context, &keyblock);
+	    krb5_free_keyblock_contents(krb5__krb4_context, &keyblock);
+#endif
+	} else
+	    return RD_AP_UNDEC;
+
+	len = krb4int_strnlen(realm, sizeof(st_rlm)) + 1;
+	if (len <= 0)
+	    return KFAILURE;
+	memcpy(st_rlm, realm, (size_t)len);
+	len = krb4int_strnlen(service, sizeof(st_nam)) + 1;
+	if (len <= 0)
+	    return KFAILURE;
+	memcpy(st_nam, service, (size_t)len);
+	len = krb4int_strnlen(instance, sizeof(st_inst)) + 1;
+	if (len <= 0)
+	    return KFAILURE;
+	memcpy(st_inst, instance, (size_t)len);
+    }
+    return krb_rd_req_with_key(authent, service, instance,
+			       from_addr, ad,
+			       krb5_key ? NULL : serv_key,
+			       krb5_key ? &srv_k5key : NULL);
+}
diff --git a/krb5-1-6/src/lib/krb4/rd_safe.c b/krb5-1-6/src/lib/krb4/rd_safe.c
new file mode 100644
index 000000000..7df0d6599
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/rd_safe.c
@@ -0,0 +1,208 @@
+/*
+ * lib/krb4/rd_safe.c
+ *
+ * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * This routine dissects a a Kerberos 'safe msg', checking its
+ * integrity, and returning a pointer to the application data
+ * contained and its length.
+ *
+ * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...)
+ *
+ * Steve Miller    Project Athena  MIT/DEC
+ */
+
+/* system include files */
+#include <stdio.h>
+#include <string.h>
+
+/* application include files */
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include "lsb_addr_cmp.h"
+#include "port-sockets.h"
+
+extern int krb_debug;
+
+/*
+ * krb_rd_safe() checks the integrity of an AUTH_MSG_SAFE message.
+ * Given the message received, "in", the length of that message,
+ * "in_length", the "key" to compute the checksum with, and the
+ * network addresses of the "sender" and "receiver" of the message,
+ * krb_rd_safe() returns RD_AP_OK if message is okay, otherwise
+ * some error code.
+ *
+ * The message data retrieved from "in" is returned in the structure
+ * "m_data".  The pointer to the application data (m_data->app_data)
+ * refers back to the appropriate place in "in".
+ *
+ * See the file "mk_safe.c" for the format of the AUTH_MSG_SAFE
+ * message.  The structure containing the extracted message
+ * information, MSG_DAT, is defined in "krb.h".
+ */
+
+long KRB5_CALLCONV
+krb_rd_safe(in,in_length,key,sender,receiver,m_data)
+    u_char *in;			/* pointer to the msg received */
+    unsigned KRB4_32 in_length;		/* length of "in" msg */
+    C_Block *key;			/* encryption key for seed and ivec */
+    struct sockaddr_in *sender;	/* sender's address */
+    struct sockaddr_in *receiver;	/* receiver's address -- me */
+    MSG_DAT *m_data;		/* where to put message information */
+{
+    int i;
+    unsigned KRB4_32 calc_cksum[4];
+    unsigned KRB4_32 big_cksum[4];
+    int le;
+
+    u_char     *p,*q;
+    int t;
+    struct in_addr src_addr;
+    unsigned KRB4_32 t_local;	/* Local time in our machine */
+    KRB4_32 delta_t;		/* Difference between timestamps */
+
+    /* Be very conservative */
+    if (sizeof(src_addr.s_addr) != 4) {
+#ifdef DEBUG
+	fprintf(stderr, "\nkrb_rd_safe protocol err "
+		"sizeof(src_addr.s_addr) != 4\n");
+#endif
+	return RD_AP_VERSION;
+    }
+
+    p = in;                     /* beginning of message */
+#define IN_REMAIN (in_length - (p - in))
+    if (IN_REMAIN < 1 + 1 + 4)
+	return RD_AP_MODIFIED;
+
+    if (*p++ != KRB_PROT_VERSION)
+	return RD_AP_VERSION;
+    t = *p++;
+    if ((t & ~1) != AUTH_MSG_SAFE)
+	return RD_AP_MSG_TYPE;
+    le = t & 1;
+
+    q = p;                      /* mark start of cksum stuff */
+
+    /* safely get length */
+    KRB4_GET32(m_data->app_length, p, le);
+
+    if (IN_REMAIN < m_data->app_length + 1 + 4 + 4 + 4 * 4)
+	return RD_AP_MODIFIED;
+
+    m_data->app_data = p;       /* we're now at the application data */
+
+    /* skip app data */
+    p += m_data->app_length;
+
+    /* safely get time_5ms */
+    m_data->time_5ms = *p++;
+
+    /* safely get src address */
+    (void)memcpy(&src_addr.s_addr, p, sizeof(src_addr.s_addr));
+    /* don't swap, net order always */
+    p += sizeof(src_addr.s_addr);
+
+    if (!krb_ignore_ip_address) {
+	switch (sender->sin_family) {
+	case AF_INET:
+	    if (src_addr.s_addr != sender->sin_addr.s_addr)
+		return RD_AP_MODIFIED;
+	    break;
+#ifdef KRB5_USE_INET6
+	case AF_INET6:
+	    if (IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr)
+		&& !memcmp (&src_addr.s_addr,
+			    12 + (char *) &((struct sockaddr_in6 *)sender)->sin6_addr,
+			    4))
+		break;
+	    /* Not v4 mapped?  Not ignoring addresses?  You lose.  */
+	    return RD_AP_MODIFIED;
+#endif
+	default:
+	    return RD_AP_MODIFIED;
+	}
+    }
+
+    /* safely get time_sec */
+    KRB4_GET32(m_data->time_sec, p, le);
+
+    /* check direction bit is the sign bit */
+    /* For compatibility with broken old code, compares are done in VAX 
+       byte order (LSBFIRST) */ 
+    /* However, if we don't have good ip addresses anyhow, just clear
+       the bit. This makes it harder to detect replay of sent packets
+       back to the receiver, but most higher level protocols can deal
+       with that more directly. */
+    if (krb_ignore_ip_address) {
+	if (m_data->time_sec < 0)
+	    m_data->time_sec = -m_data->time_sec;
+    } else
+	switch (krb4int_address_less (sender, receiver)) {
+	case 1:
+	    m_data->time_sec = -m_data->time_sec;
+	    break;
+	case -1:
+	    if (m_data->time_sec < 0)
+		m_data->time_sec = -m_data->time_sec;
+	    break;
+	}
+
+    /* check the time integrity of the msg */
+    t_local = TIME_GMT_UNIXSEC;
+    delta_t = t_local - m_data->time_sec;
+    if (delta_t < 0) delta_t = -delta_t;  /* Absolute value of difference */
+    if (delta_t > CLOCK_SKEW) {
+        return(RD_AP_TIME);		/* XXX should probably be better
+					   code */
+    }
+
+    /*
+     * caller must check timestamps for proper order and replays, since
+     * server might have multiple clients each with its own timestamps
+     * and we don't assume tightly synchronized clocks.
+     */
+
+#ifdef NOENCRYPTION
+    memset(calc_cksum, 0, sizeof(calc_cksum));
+#else /* Do encryption */
+    /* calculate the checksum of the length, timestamps, and
+     * input data, on the sending byte order !! */
+    quad_cksum(q,calc_cksum,p-q,2,key);
+#endif /* NOENCRYPTION */
+
+    for (i = 0; i < 4; i++)
+	KRB4_GET32(big_cksum[i], p, le);
+
+    DEB (("\n0: calc %l big %lx\n1: calc %lx big %lx\n2: calc %lx big %lx\n3: calc %lx big %lx\n",
+               calc_cksum[0], big_cksum[0],
+               calc_cksum[1], big_cksum[1],
+               calc_cksum[2], big_cksum[2],
+               calc_cksum[3], big_cksum[3]));
+    for (i = 0; i < 4; i++)
+	if (big_cksum[i] != calc_cksum[i])
+	    return RD_AP_MODIFIED;
+
+    return RD_AP_OK;		/* OK == 0 */
+}
diff --git a/krb5-1-6/src/lib/krb4/rd_svc_key.c b/krb5-1-6/src/lib/krb4/rd_svc_key.c
new file mode 100644
index 000000000..2728f4a1c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/rd_svc_key.c
@@ -0,0 +1,344 @@
+/*
+ * rd_svc_key.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "krb4int.h"
+#include <stdio.h>
+#include <string.h>
+
+#include "k5-int.h"
+#include <krb54proto.h>
+#include "prot.h"
+
+/*
+ * The private keys for servers on a given host are stored in a
+ * "srvtab" file (typically "/etc/srvtab").  This routine extracts
+ * a given server's key from the file.
+ *
+ * read_service_key() takes the server's name ("service"), "instance",
+ * and "realm" and a key version number "kvno", and looks in the given
+ * "file" for the corresponding entry, and if found, returns the entry's
+ * key field in "key".
+ * 
+ * If "instance" contains the string "*", then it will match
+ * any instance, and the chosen instance will be copied to that
+ * string.  For this reason it is important that the there is enough
+ * space beyond the "*" to receive the entry.
+ *
+ * If "kvno" is 0, it is treated as a wild card and the first
+ * matching entry regardless of the "vno" field is returned.
+ *
+ * This routine returns KSUCCESS on success, otherwise KFAILURE.
+ *
+ * The format of each "srvtab" entry is as follows:
+ *
+ * Size			Variable		Field in file
+ * ----			--------		-------------
+ * string		serv			server name
+ * string		inst			server instance
+ * string		realm			server realm
+ * 1 byte		vno			server key version #
+ * 8 bytes		key			server's key
+ * ...			...			...
+ */
+
+#ifdef __i960__
+/* special hack to use a global srvtab variable... */
+#define open vxworks_srvtab_open
+#define close vxworks_srvtab_close
+#define getst vxworks_srvtab_getst
+#define read vxworks_srvtab_read
+
+extern char *vxworks_srvtab_base;
+char *vxworks_srvtab_ptr;
+int vxworks_srvtab_getchar(s)
+     char *s;
+{
+  int tmp1;
+  if(vxworks_srvtab_ptr >= (vxworks_srvtab_base + strlen(vxworks_srvtab_base)))
+    return 0;
+
+  sscanf(vxworks_srvtab_ptr, "%2x", &tmp1);
+
+  *s = tmp1;
+  vxworks_srvtab_ptr+=2;
+  return 1;
+}
+
+int vxworks_srvtab_getst(fd,s,n)
+    int fd;
+    register char *s;
+    int n;
+{
+    register count = n;
+    while (vxworks_srvtab_getchar(s) && --count)
+        if (*s++ == '\0')
+            return (n - count);
+    *s = '\0';
+    return (n - count);
+}
+
+int vxworks_srvtab_open(s, n, m)
+     char *s;
+     int n, m;
+{
+  vxworks_srvtab_ptr = vxworks_srvtab_base;
+  return 1;
+}
+
+int vxworks_srvtab_close(fd)
+     int fd;
+{
+  vxworks_srvtab_ptr = 0;
+  return 0;
+}
+
+int vxworks_srvtab_read(fd, s, n)
+     int fd;
+     char *s;
+     int n;
+{
+  int count = n;
+  /* we want to get exactly n chars. */
+  while(vxworks_srvtab_getchar(s) && --count)
+    s++;
+  return (n-count);
+}
+#endif
+
+#ifdef KRB4_USE_KEYTAB
+/*
+ * This function looks up the requested Krb4 srvtab key using the krb5
+ * keytab format, if possible.
+ */
+extern krb5_error_code
+krb54_get_service_keyblock(service,instance,realm,kvno,file,keyblock)
+    char *service;		/* Service Name */
+    char *instance;		/* Instance name or "*" */
+    char *realm;		/* Realm */
+    int kvno;			/* Key version number */
+    char *file;		/* Filename */
+    krb5_keyblock * keyblock;
+{
+    krb5_error_code retval;
+    krb5_principal princ = NULL;
+    krb5_keytab kt_id;
+    krb5_keytab_entry kt_entry;
+    char sname[ANAME_SZ+1];
+    char sinst[INST_SZ+1];
+    char srealm[REALM_SZ+1];
+    char keytabname[MAX_KEYTAB_NAME_LEN + 1];	/* + 1 for NULL termination */
+
+    if (!krb5__krb4_context) {
+	    retval = krb5_init_context(&krb5__krb4_context);
+	    if (retval)
+		    return retval;
+    }
+
+    if (!strcmp(instance, "*")) {
+	if ((retval = krb5_sname_to_principal(krb5__krb4_context, NULL, NULL,
+					      KRB5_NT_SRV_HST, &princ)))
+	    goto errout;
+	
+	if ((retval = krb5_524_conv_principal(krb5__krb4_context, princ,
+					      sname, sinst, srealm)))
+	    goto errout;
+
+	instance = sinst;
+	krb5_free_principal(krb5__krb4_context, princ);
+	princ = 0;
+    }
+    
+    if ((retval = krb5_425_conv_principal(krb5__krb4_context, service,
+					  instance, realm, &princ)))
+	goto errout;
+
+    /*
+     * Figure out what name to use; if the name is one of the standard
+     * /etc/srvtab, /etc/athena/srvtab, etc., use the default keytab
+     * name.  Otherwise, append .krb5 to the filename and try to use
+     * that.
+     */
+    if (file &&
+	strcmp(file, "/etc/srvtab") &&
+	strcmp(file, "/etc/athena/srvtab") &&
+	strcmp(file, KEYFILE)) {
+	    strncpy(keytabname, file, sizeof(keytabname));
+	    keytabname[sizeof(keytabname)-1] = 0;
+	    if (strlen(keytabname)+6 < sizeof(keytabname))
+		    strcat(keytabname, ".krb5");
+    } else {
+	    if ((retval = krb5_kt_default_name(krb5__krb4_context,
+				(char *)keytabname, sizeof(keytabname)-1)))
+		    goto errout;
+    }
+    
+    if ((retval = krb5_kt_resolve(krb5__krb4_context, keytabname, &kt_id)))
+	    goto errout;
+
+    if ((retval = krb5_kt_get_entry(krb5__krb4_context, kt_id, princ, kvno,
+				    0, &kt_entry))) {
+	krb5_kt_close(krb5__krb4_context, kt_id);
+	goto errout;
+    }
+
+    retval = krb5_copy_keyblock_contents(krb5__krb4_context,
+					 &kt_entry.key, keyblock);
+    /* Bash types */
+    /* KLUDGE! If it's a non-raw des3 key, bash its enctype */
+    /* See kdc/kerberos_v4.c */
+    if (keyblock->enctype == ENCTYPE_DES3_CBC_SHA1 )
+      keyblock->enctype = ENCTYPE_DES3_CBC_RAW;
+    
+    krb5_kt_free_entry(krb5__krb4_context, &kt_entry);
+    krb5_kt_close (krb5__krb4_context, kt_id);
+
+errout:
+    if (princ)
+	krb5_free_principal(krb5__krb4_context, princ);
+    return retval;
+}
+#endif
+
+
+int KRB5_CALLCONV
+read_service_key(service,instance,realm,kvno,file,key)
+    char *service;		/* Service Name */
+    char *instance;		/* Instance name or "*" */
+    char *realm;		/* Realm */
+    int kvno;			/* Key version number */
+    char *file;		/* Filename */
+    char *key;		/* Pointer to key to be filled in */
+{
+    int kret;
+    
+#ifdef KRB4_USE_KEYTAB
+    krb5_error_code	retval;
+    krb5_keyblock 	keyblock;
+#endif
+
+    kret = get_service_key(service,instance,realm,&kvno,file,key);
+
+    if (! kret)
+	return KSUCCESS;
+
+#ifdef KRB4_USE_KEYTAB
+    kret = KFAILURE;
+    keyblock.magic = KV5M_KEYBLOCK;
+    keyblock.contents = 0;
+
+    retval = krb54_get_service_keyblock(service,instance,realm,kvno,file,
+					&keyblock);
+    if (retval)
+	    goto errout;
+
+    if ((keyblock.length != sizeof(C_Block)) ||
+	((keyblock.enctype != ENCTYPE_DES_CBC_CRC) &&
+	 (keyblock.enctype != ENCTYPE_DES_CBC_MD4) &&
+	 (keyblock.enctype != ENCTYPE_DES_CBC_MD5))) {
+	    goto errout;
+    }
+    (void) memcpy(key, keyblock.contents, sizeof(C_Block));
+    kret = KSUCCESS;
+    
+errout:
+    if (keyblock.contents)
+	    krb5_free_keyblock_contents(krb5__krb4_context, &keyblock);
+#endif
+    
+    return kret;
+}
+
+/* kvno is passed by reference, so that if it is zero, and we find a match,
+   the match gets written back into *kvno so the caller can find it.
+ */
+int KRB5_CALLCONV
+get_service_key(service,instance,realm,kvno,file,key)
+    char *service;              /* Service Name */
+    char *instance;             /* Instance name or "*" */
+    char *realm;                /* Realm */
+    int *kvno;                 /* Key version number */
+    char *file;                 /* Filename */
+    char *key;                  /* Pointer to key to be filled in */
+{
+    char serv[SNAME_SZ];
+    char inst[INST_SZ];
+    char rlm[REALM_SZ];
+    unsigned char vno;          /* Key version number */
+    int wcard;
+    char krb_realm[REALM_SZ];
+
+    int stab;
+
+    if (!file)
+	file = KEYFILE;
+
+    if ((stab = open(file, 0, 0)) < 0)
+        return(KFAILURE);
+
+    wcard = (instance[0] == '*') && (instance[1] == '\0');
+    /* get current realm if not passed in */
+    if (!realm) {
+	int rem;
+
+	rem = krb_get_lrealm(krb_realm,1);
+	if (rem != KSUCCESS)
+	    return(rem);
+	realm = krb_realm;
+    }
+
+    while(getst(stab,serv,SNAME_SZ) > 0) { /* Read sname */
+        (void) getst(stab,inst,INST_SZ); /* Instance */
+        (void) getst(stab,rlm,REALM_SZ); /* Realm */
+        /* Vers number */
+        if (read(stab,(char *)&vno,1) != 1) {
+	    close(stab);
+            return(KFAILURE);
+	}
+        /* Key */
+        if (read(stab,key,8) != 8) {
+	    close(stab);
+            return(KFAILURE);
+	}
+        /* Is this the right service */
+        if (strcmp(serv,service))
+            continue;
+        /* How about instance */
+        if (!wcard && strcmp(inst,instance))
+            continue;
+        if (wcard)
+            (void) strncpy(instance,inst,INST_SZ);
+        /* Is this the right realm */
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_SRVTAB)
+	/* XXX For backward compatibility:  if keyfile says "Athena"
+	   and caller wants "ATHENA.MIT.EDU", call it a match */
+        if (strcmp(rlm,realm) &&
+	    (strcmp(rlm,"Athena") ||
+	     strcmp(realm,"ATHENA.MIT.EDU")))
+	    continue;
+#else /* ! ATHENA_COMPAT */
+        if (strcmp(rlm,realm)) 
+	    continue;
+#endif /* ATHENA_COMPAT */
+
+        /* How about the key version number */
+        if (*kvno && *kvno != (int) vno)
+            continue;
+
+        (void) close(stab);
+	*kvno = vno;
+        return(KSUCCESS);
+    }
+
+    /* Can't find the requested service */
+    (void) close(stab);
+    return(KFAILURE);
+}
diff --git a/krb5-1-6/src/lib/krb4/recvauth.c b/krb5-1-6/src/lib/krb4/recvauth.c
new file mode 100644
index 000000000..c5f857e98
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/recvauth.c
@@ -0,0 +1,308 @@
+/*
+ * lib/krb4/recvauth.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include "autoconf.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "port-sockets.h"
+
+
+#define	KRB_SENDAUTH_VERS	"AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
+					      chars */
+
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in krb_sendauth.c
+ * be sure to support old versions of krb_sendauth!
+ */
+
+/*
+ * krb_recvauth() reads (and optionally responds to) a message sent
+ * using krb_sendauth().  The "options" argument is a bit-field of
+ * selected options (see "sendauth.c" for options description).
+ * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
+ * (mutual authentication requested).  The "fd" argument supplies
+ * a file descriptor to read from (and write to, if mutual authenti-
+ * cation is requested).
+ *
+ * Part of the received message will be a Kerberos ticket sent by the
+ * client; this is read into the "ticket" argument.  The "service" and
+ * "instance" arguments supply the server's Kerberos name.  If the
+ * "instance" argument is the string "*", it is treated as a wild card
+ * and filled in during the krb_rd_req() call (see read_service_key()).
+ *
+ * The "faddr" and "laddr" give the sending (client) and receiving
+ * (local server) network addresses.  ("laddr" may be left NULL unless
+ * mutual authentication is requested, in which case it must be set.)
+ *
+ * The authentication information extracted from the message is returned
+ * in "kdata".  The "filename" argument indicates the file where the
+ * server's key can be found.  (It is passed on to krb_rd_req().)  If
+ * left null, the default "/etc/srvtab" will be used.
+ *
+ * If mutual authentication is requested, the session key schedule must
+ * be computed in order to reply; this schedule is returned in the
+ * "schedule" argument.  A string containing the application version
+ * number from the received message is returned in "version", which
+ * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
+ *
+ * See krb_sendauth() for the format of the received client message.
+ *
+ * This routine supports another client format, for backward
+ * compatibility, consisting of:
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ *
+ * string		tmp_buf, tkt_len	length of ticket, in
+ * 						ascii
+ *
+ * char			' ' (space char)	separator
+ *
+ * tkt_len		ticket->dat		the ticket
+ *
+ * This old-style version does not support mutual authentication.
+ *
+ * krb_recvauth() first reads the protocol version string from the
+ * given file descriptor.  If it doesn't match the current protocol
+ * version (KRB_SENDAUTH_VERS), the old-style format is assumed.  In
+ * that case, the string of characters up to the first space is read
+ * and interpreted as the ticket length, then the ticket is read.
+ *
+ * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
+ * next reads the application protocol version string.  Then the
+ * ticket length and ticket itself are read.
+ *
+ * The ticket is decrypted and checked by the call to krb_rd_req().
+ * If no mutual authentication is required, the result of the
+ * krb_rd_req() call is retured by this routine.  If mutual authenti-
+ * cation is required, a message in the following format is returned
+ * on "fd":
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ *
+ * 4 bytes		tkt_len			length of ticket or -1
+ *						if error occurred
+ *
+ * priv_len		tmp_buf			"private" message created
+ *						by krb_mk_priv() which
+ *						contains the incremented
+ *						checksum sent by the client
+ *						encrypted in the session
+ *						key.  (This field is not
+ *						present in case of error.)
+ *
+ * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
+ * other error code is returned.
+ */
+
+#ifndef max
+#define	max(a,b) (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+int KRB5_CALLCONV
+krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
+	     filename, schedule, version)
+    long options;			 /* bit-pattern of options */
+    int fd;				 /* file descr. to read from */
+    KTEXT ticket;			 /* storage for client's ticket */
+    char *service;			 /* service expected */
+    char *instance;			 /* inst expected (may be filled in) */
+    struct sockaddr_in *faddr;	 /* address of foreign host on fd */
+    struct sockaddr_in *laddr;	 /* local address */
+    AUTH_DAT *kdata;		 /* kerberos data (returned) */
+    char *filename;			 /* name of file with service keys */
+    Key_schedule schedule;		 /* key schedule (return) */
+    char *version;			 /* version string (filled in) */
+{
+
+    int i, cc, old_vers = 0;
+    char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
+    char *cp = NULL;
+    int rem;
+    KRB4_32 tkt_len, priv_len;
+    unsigned KRB4_32 cksum;
+    u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)] = { 0 };
+
+    /* read the protocol version number */
+    if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) !=
+	KRB_SENDAUTH_VLEN)
+	    return(errno);
+    krb_vers[KRB_SENDAUTH_VLEN] = '\0';
+
+    /* check version string */
+    if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) {
+	/* Assume the old version of sendkerberosdata: send ascii
+	   length, ' ', and ticket. */
+	if (options & KOPT_DO_MUTUAL)
+	    return(KFAILURE);	 /* XXX can't do old style with mutual auth */
+	old_vers = 1;
+
+	/* copy what we have read into tmp_buf */
+	(void) memcpy((char *) tmp_buf, krb_vers, KRB_SENDAUTH_VLEN);
+
+	/* search for space, and make it a null */
+	for (i = 0; i < KRB_SENDAUTH_VLEN; i++)
+	    if (tmp_buf[i]== ' ') {
+		tmp_buf[i] = '\0';
+		/* point cp to the beginning of the real ticket */
+		cp = (char *) &tmp_buf[i+1];
+		break;
+	    }
+
+	if (i == KRB_SENDAUTH_VLEN)
+	    /* didn't find the space, keep reading to find it */
+	    for (; i<20; i++) {
+		if (read(fd, (char *)&tmp_buf[i], 1) != 1) {
+		    return(KFAILURE);
+		}
+		if (tmp_buf[i] == ' ') {
+		    tmp_buf[i] = '\0';
+		    /* point cp to the beginning of the real ticket */
+		    cp = (char *) &tmp_buf[i+1];
+		    break;
+		}
+	    }
+
+	if (i==20)
+	    return(KFAILURE);
+
+	tkt_len = (KRB4_32) atoi((char *) tmp_buf);
+
+	/* sanity check the length */
+	/* These conditions make sure that cp got initialized */
+	if ((tkt_len<=0)||(tkt_len>MAX_KTXT_LEN))
+	    return(KFAILURE);
+
+	if (i < KRB_SENDAUTH_VLEN) {
+	    /* since we already got the space, and part of the ticket,
+	       we read fewer bytes to get the rest of the ticket */
+	    int len_to_read = tkt_len - KRB_SENDAUTH_VLEN + 1 + i;
+	    if (len_to_read <= 0)
+		return KFAILURE;
+	    if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN),
+			     len_to_read)
+		!= len_to_read)
+		return(errno);
+	} else {
+	    if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) !=
+		(int) tkt_len)
+		return(errno);
+	}
+	ticket->length = tkt_len;
+	/* copy the ticket into the struct */
+	(void) memcpy((char *) ticket->dat, cp, ticket->length);
+
+    } else {
+	/* read the application version string */
+	if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
+	    KRB_SENDAUTH_VLEN)
+	    return(errno);
+	version[KRB_SENDAUTH_VLEN] = '\0';
+
+	/* get the length of the ticket */
+	if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
+	    sizeof(tkt_len))
+	    return(errno);
+    
+	/* sanity check */
+	ticket->length = ntohl((unsigned KRB4_32)tkt_len);
+	if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
+	    if (options & KOPT_DO_MUTUAL) {
+		rem = KFAILURE;
+		goto mutual_fail;
+	    } else
+		return(KFAILURE); /* XXX there may still be junk on the fd? */
+	}
+
+	/* read the ticket */
+	if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
+	    != ticket->length)
+	    return(errno);
+    }
+    /*
+     * now have the ticket.  decrypt it to get the authenticated
+     * data.
+     */
+    rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
+		     kdata,filename);
+
+    if (old_vers) return(rem);	 /* XXX can't do mutual with old client */
+
+    /* if we are doing mutual auth, compose a response */
+    if (options & KOPT_DO_MUTUAL) {
+	if (rem != KSUCCESS)
+	    /* the krb_rd_req failed */
+	    goto mutual_fail;
+
+	/* add one to the (formerly) sealed checksum, and re-seal it
+	   for return to the client */
+	cksum = kdata->checksum + 1;
+	cksum = htonl(cksum);
+#ifndef NOENCRYPTION
+	key_sched(kdata->session,schedule);
+#endif /* !NOENCRYPTION */
+	priv_len = krb_mk_priv((unsigned char *)&cksum,
+			       tmp_buf,
+			       (unsigned KRB4_32) sizeof(cksum),
+			       schedule,
+			       &kdata->session,
+			       laddr,
+			       faddr);
+	if (priv_len < 0) {
+	    /* re-sealing failed; notify the client */
+	    rem = KFAILURE;	 /* XXX */
+mutual_fail:
+	    priv_len = -1;
+	    tkt_len = htonl((unsigned KRB4_32) priv_len);
+	    /* a length of -1 is interpreted as an authentication
+	       failure by the client */
+	    if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+		!= sizeof(tkt_len))
+		return(cc);
+	    return(rem);
+	} else {
+	    /* re-sealing succeeded, send the private message */
+	    tkt_len = htonl((unsigned KRB4_32)priv_len);
+	    if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+		 != sizeof(tkt_len))
+		return(cc);
+	    if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
+		!= (int) priv_len)
+		return(cc);
+	}
+    }
+    return(rem);
+}
diff --git a/krb5-1-6/src/lib/krb4/ren-cyg.sh b/krb5-1-6/src/lib/krb4/ren-cyg.sh
new file mode 100755
index 000000000..d3d31a9d4
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ren-cyg.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Rename Kerberos Cygnus V4 filenames to proposed names
+# for converting old trees.
+awk '/^@ / {	if ($6 != "")
+			if ($6 != $4)
+				print "mv	" $6 "	" $4
+			else ;
+		else if ($2 != $4 && $2 != "-")
+			print "mv	" $2 "	" $4
+	  }
+    ' <ren.msg | grep -v '(gone)' | sh -x
diff --git a/krb5-1-6/src/lib/krb4/ren-pc.bat b/krb5-1-6/src/lib/krb4/ren-pc.bat
new file mode 100644
index 000000000..e25755fdb
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ren-pc.bat
@@ -0,0 +1,29 @@
+rename	crerrep.c	cr_err_repl.c
+rename	crauthre.c	cr_auth_repl.c
+rename	cr_death.c	cr_death_pkt.c
+rename	crticket.c	cr_tkt.c
+rename	decomtkt.c	decomp_tkt.c
+rename	getadtkt.c	g_ad_tkt.c
+rename	getadmhs.c	g_admhst.c
+rename	get_cred.c	g_cred.c
+rename	getintkt.c	g_pw_in_tkt.c
+rename	getkrbhs.c	g_krbhst.c
+rename	getphost.c	g_phost.c
+rename	getpwtkt.c	g_pw_tkt.c
+rename	get_req.c	g_request.c
+rename	g_svctkt.c	g_svc_in_tkt.c
+rename	gettfnam.c	g_tf_fname.c
+rename	gettfrlm.c	g_tf_realm.c
+rename	getrealm.c	realmofhost.c
+rename	k_gethst.c	gethostname.c
+rename	knm_pars.c	kname_parse.c
+rename	k_errtxt.c	err_txt.c
+rename	k_gettkt.c	g_in_tkt.c
+rename	mth_snam.c	month_sname.c
+rename	pkt_ciph.c	pkt_cipher.c
+rename	rdservky.c	rd_svc_key.c
+rename	savecred.c	save_creds.c
+rename	send_kdc.c	send_to_kdc.c
+rename	s_cascmp.c	strcasecmp.c
+rename	tkt_strg.c	tkt_string.c
+rename	util.c	ad_print.c
diff --git a/krb5-1-6/src/lib/krb4/ren-pc.sh b/krb5-1-6/src/lib/krb4/ren-pc.sh
new file mode 100644
index 000000000..bea2beb01
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ren-pc.sh
@@ -0,0 +1,7 @@
+# Rename Kerberos V4 MIT PC-port filenames to proposed names
+# for converting old PC trees on Unix systems.
+awk '/^@ / {
+		if ($3 != $4 && $3 != "-")
+			print "mv	" $3 "	" $4
+	   }
+    ' <ren.msg | grep -v '(gone)' | sh -x
diff --git a/krb5-1-6/src/lib/krb4/ren-pl10.sh b/krb5-1-6/src/lib/krb4/ren-pl10.sh
new file mode 100644
index 000000000..d72a72c50
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ren-pl10.sh
@@ -0,0 +1,7 @@
+# Rename Kerberos V4 pl10 filenames to proposed names
+# for converting old trees.
+awk '/^@ / {
+		if ($2 != $4 && $2 != "-")
+			print "mv	" $2 "	" $4
+	   }
+    ' <ren.msg | grep -v '(gone)' | sh -x
diff --git a/krb5-1-6/src/lib/krb4/ren.msg b/krb5-1-6/src/lib/krb4/ren.msg
new file mode 100644
index 000000000..45b404afa
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ren.msg
@@ -0,0 +1,117 @@
+Subject: Kerberos file renaming for short DOS names
+Date: Tue, 19 Apr 1994 13:34:28 -0700
+From: John Gilmore <gnu@cygnus.com>
+
+[edited since sending, to bring it up to date with what actually happened.]
+
+I'd like to come up with some file naming and configuration
+conventions that will work in DOS, Unix, and Mac environments.  At
+Cygnus, we are creating a single freely available K4 source tree that
+works on many Unixes, Windows, and Mac.  It currently works on Unixes.
+(To get a copy, send mail to info@cygnus.com requesting our Kerberos
+release.  It's in a hidden FTP location due to export control.)
+
+I diffed the current MIT release of Kerberos for PC and Windows
+against the V4 patchlevel 10 release, and identified some 30 files in
+lib/krb that have been renamed between Unix and PC.  Comparing source
+trees becomes much more painful when files are renamed.  If we don't
+come to sync on the file names, it will be very hard to collaborate,
+which would make more work for all of us.
+
+My plan, which we have used successfully in the GNU software, is to
+make sure that all filenames are unique if you take the first 8 chars
+and the first 3 after the dot.  No files have more than a single dot
+in them.  We don't restrict file names to just 8.3 characters, since
+doing so would impact readability for the (99.9%) of the developers
+who are on Unix or Mac, where long file names are fine.
+
+There's an additional complication that names longer than 14
+characters present problems to old System V Unix and to `ar' on Unix.
+DJ Delorie's excellent `doschk' program points out all these problems.
+(prep.ai.mit.edu:/pub/gnu/doschk-1.1.tar.gz).
+
+Here's my proposal for the lib/krb directory.  In general, I tried to
+regularize the names, turning get_ into g_, removing krb_, turning
+reply into repl, turning ticket into tkt, keeping all file names
+unique across the various libraries, and making a file name more like
+the function name contained in it when there were conflicts.  Some
+resulting truncated names are more readable than in the current MIT K4
+PC, some are less readable -- but the overall advantage is that the
+new names should be acceptable to Unix/Mac developers, while the old
+ones weren't.
+
+  MIT K4 patch10	MIT K4 PC	PROPOSED NAME	(trunc to 8.3)	old Cyg
+$1     $2		$3		$4		$5		$6
+
+@ add_ticket.c		(gone)		add_tkt.c	add_tkt.c	
+@ -			-		ChangeLog	changelo
+@ cr_err_reply.c	crerrep.c	cr_err_repl.c	cr_err_r.c
+@ create_auth_reply.c	crauthre.c	cr_auth_repl.c	cr_auth_.c	cr_auth_reply.c
+@ create_ciph.c		cr_ciph.c	cr_ciph.c	cr_ciph.c
+@ create_death_packet.c	cr_death.c	cr_death_pkt.c	cr_death.c	cr_death_pkt.c
+@ create_ticket.c	crticket.c	cr_tkt.c	cr_tkt.c
+@ debug_decl.c		debug.c		debug.c		debug.c
+@ decomp_ticket.c	decomtkt.c	decomp_tkt.c	decomp_t.c
+@ -			-		DNR.c		dnr.c
+@ extract_ticket.c	ext_tkt.c	ext_tkt.c	ext_tkt.c	extract_tkt.c
+@ -			-		g_cnffile.c	g_cnffil.c
+@ get_ad_tkt.c		getadtkt.c	g_ad_tkt.c	g_ad_tkt.c
+@ get_admhst.c		getadmhs.c	g_admhst.c	g_admhst.c
+@ get_cred.c		get_cred.c	g_cred.c	g_cred.c
+@ get_in_tkt.c		getintkt.c	g_pw_in_tkt.c	g_pw_in_.c
+@ get_krbhst.c		getkrbhs.c	g_krbhst.c	g_krbhst.c
+@ get_krbrlm.c		g_krbrlm.c	g_krbrlm.c	g_krbrlm.c
+@ get_phost.c		getphost.c	g_phost.c	g_phost.c
+@ get_pw_tkt.c		getpwtkt.c	g_pw_tkt.c	g_pw_tkt.c
+@ get_request.c		get_req.c	(gone)		(gone)
+@ get_svc_in_tkt.c	g_svctkt.c	g_svc_in_tkt.c	g_svc_in.c	get_svc_in.c
+@ get_tf_fullname.c	gettfnam.c	g_tf_fname.c	g_tf_fna.c	get_tf_fname.c
+@ get_tf_realm.c	gettfrlm.c	g_tf_realm.c	g_tf_rea.c
+@ -			-		g_tkt_svc.c	g_tkt_sv.c
+@ getrealm.c		getrealm.c	realmofhost.c	realmofh.c
+@ k_gethostname.c	k_gethst.c	gethostname.c	gethostn.c
+@ kname_parse.c		knm_pars.c	kname_parse.c	kname_pa.c
+@ krb_err_txt.c		k_errtxt.c	err_txt.c	err_txt.c
+@ krb_get_in_tkt.c	k_gettkt.c	g_in_tkt.c	g_in_tkt.c	krb_get_in.c
+@ -			-		mac_store.c	mac_stor.c
+@ -			-		mac_store.h	mac_stor.h
+@ -			-		mac_stubs.c	mac_stub.c
+@ -			-		Makefile.in	makefile.in
+@ -			-		mk_preauth.c	mk_preau.c
+@ month_sname.c		mth_snam.c	month_sname.c	month_sn.c
+@ pkt_cipher.c		pkt_ciph.c	pkt_cipher.c	pkt_ciph.c
+@ -			-		Password.c	password.c
+@ -			-		rd_preauth.c	rd_preau.c
+@ -			-		put_svc_key.c	put_svc_.c
+@ read_service_key.c	rdservky.c	rd_svc_key.c	rd_svc_k.c	read_svc_key.c
+@ save_credentials.c	savecred.c	save_creds.c	save_cre.c	save_creds.c
+@ send_to_kdc.c		send_kdc.c	send_to_kdc.c	send_to_.c
+@ strcasecmp.c		s_cascmp.c	strcasecmp.c	strcasec.c
+@ tkt_string.c		tkt_strg.c	tkt_string.c	tkt_stri.c
+@ -			-		unix_glue.c	unix_glu.c
+@ util.c		util.c		ad_print.c	ad_print.c
+@ -			-		win_store.c	win_stor.c
+# Cleanup for simplified sed scripts that use this table
+@sed s/tf_ad_print\./tf_util\./g
+
+I've supplied Unix shell scripts in the distribution for moving:
+ren-pl10.sh	V4 pl10 filenames to proposed names	for converting old trees
+ren-pc.sh	V4 MIT PC names to proposed names	for converting old trees
+ren2long.sh	truncated names to proposed names	for moving DOS->unix
+ren2dos.sh	proposed names to truncated names	for unix->DOS names
+
+There's also shell scripts to produce sed scripts for converting Makefiles
+and documentation.  You use them like:
+	./sed-pl10.sh >/tmp/sed
+	sed -f /tmp/sed <Makefile >newMakefile
+sed-pl10.sh	V4 pl10 filenames to proposed names	for converting old trees
+sed-pc.sh	V4 MIT PC names to proposed names	for converting old trees
+
+I'll also supply a DOS script for moving:
+ren-pc.bat	V4 MIT PC names to proposed names	for converting old trees
+
+And an MPW script for moving
+ren-pl10.mpw	V4 pl10 filenames to proposed names	for converting old trees
+
+	John Gilmore
+	Cygnus Support
diff --git a/krb5-1-6/src/lib/krb4/ren2dos.sh b/krb5-1-6/src/lib/krb4/ren2dos.sh
new file mode 100644
index 000000000..3989e2c6e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ren2dos.sh
@@ -0,0 +1,7 @@
+# Rename Unix filenames to DOS-truncated filenames for KRB library.
+# for converting Unix distributions to DOS distributions
+awk '/^@ / {
+		if ($4 != $5)
+			print "mv	" $4 "	" $5
+	  }
+    ' <ren.msg | sh -x
diff --git a/krb5-1-6/src/lib/krb4/ren2long.sh b/krb5-1-6/src/lib/krb4/ren2long.sh
new file mode 100644
index 000000000..7d1a25966
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/ren2long.sh
@@ -0,0 +1,7 @@
+# Rename DOS-truncated filenames to Unix filenames for KRB library.
+# for converting DOS distributions to Unix distributions
+awk '/^@ / {
+		if ($4 != $5)
+			print "mv	" $5 "	" $4
+	  }
+    ' <ren.msg | sh -x
diff --git a/krb5-1-6/src/lib/krb4/save_creds.c b/krb5-1-6/src/lib/krb4/save_creds.c
new file mode 100644
index 000000000..5cc8ae8ec
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/save_creds.c
@@ -0,0 +1,87 @@
+/*
+ * save_creds.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2002 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdio.h>
+#include "krb.h"
+#include "krb4int.h"
+
+/*
+ * This routine takes a ticket and associated info and calls
+ * tf_save_cred() to store them in the ticket cache.  The peer
+ * routine for extracting a ticket and associated info from the
+ * ticket cache is krb_get_cred().  When changes are made to
+ * this routine, the corresponding changes should be made
+ * in krb_get_cred() as well.
+ *
+ * Returns KSUCCESS if all goes well, otherwise an error returned
+ * by the tf_init() or tf_save_cred() routines.
+ *
+ * This used to just be called save_credentials, but when we formalized
+ * the DOS/Mac interface, we created and exported krb_save_credentials
+ * to avoid namespace pollution.
+ */
+
+int
+krb4int_save_credentials_addr(service, instance, realm, session, lifetime, kvno,
+                 ticket, issue_date, local_addr)
+    char *service;		/* Service name */
+    char *instance;		/* Instance */
+    char *realm;		/* Auth domain */
+    C_Block session;		/* Session key */
+    int lifetime;		/* Lifetime */
+    int kvno;			/* Key version number */
+    KTEXT ticket;		/* The ticket itself */
+    KRB4_32 issue_date;		/* The issue time */
+    KRB_UINT32 local_addr;
+{
+    int tf_status;   /* return values of the tf_util calls */
+
+    /* Open and lock the ticket file for writing */
+    if ((tf_status = tf_init(TKT_FILE, W_TKT_FIL)) != KSUCCESS)
+	return(tf_status);
+
+    /* Save credentials by appending to the ticket file */
+    tf_status = tf_save_cred(service, instance, realm, session,
+			     lifetime, kvno, ticket, issue_date);
+    (void) tf_close();
+    return (tf_status);
+}
+
+int KRB5_CALLCONV
+krb_save_credentials(
+    char	*service,
+    char	*instance,
+    char	*realm,
+    C_Block	session,
+    int		lifetime,
+    int		kvno,
+    KTEXT	ticket,
+    long	issue_date)
+{
+    return krb4int_save_credentials_addr(service, instance, realm,
+					 session, lifetime, kvno,
+					 ticket, (KRB4_32)issue_date, 0);
+}
diff --git a/krb5-1-6/src/lib/krb4/sed-cyg.sh b/krb5-1-6/src/lib/krb4/sed-cyg.sh
new file mode 100755
index 000000000..3859df138
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/sed-cyg.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Produce a sed script for converting Kerberos Cygnus V4 filenames to proposed
+# names -- for converting old makefiles and doc.
+# We fix any "oldfoo." into "newfoo." including .c and .o and .h files.
+awk '/^@ / {	if ($6 != "")
+			if ($6 != $4)
+				print "s/" $6 "/" $4 "/g"
+			else ;
+		else if ($2 != $4 && $2 != "-")
+			print "s/" $2 "/" $4 "/g"
+	  }
+     /^@sed / { print $2 }
+    ' <ren.msg | grep -v '(gone)' | sed 's/\.c/\\./g'
diff --git a/krb5-1-6/src/lib/krb4/sed-pc.sh b/krb5-1-6/src/lib/krb4/sed-pc.sh
new file mode 100755
index 000000000..a222dca3f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/sed-pc.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Produce a sed script for converting Kerberos V4 MIT PC filenames to proposed
+# names -- for converting old makefiles and doc.
+# We fix any "oldfoo." into "newfoo." including .c and .o and .h files.
+awk '/^@ / {	
+		if ($3 != $4)
+			print "s/" $3 "/" $4 "/g"
+	  }
+     /^@sed / { print $2 }
+    ' <ren.msg | grep -v '(gone)' | sed 's/\.c/\\./g'
+
diff --git a/krb5-1-6/src/lib/krb4/sed-pl10.sh b/krb5-1-6/src/lib/krb4/sed-pl10.sh
new file mode 100755
index 000000000..a6ab27c96
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/sed-pl10.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Produce a sed script for converting Kerberos V4 pl10 filenames to proposed
+# names -- for converting old makefiles and doc.
+# We fix any "oldfoo." into "newfoo." including .c and .o and .h files.
+awk '/^@ / {	
+		if ($2 != $4)
+			print "s/" $2 "/" $4 "/g"
+	  }
+     /^@sed / { print $2 }
+    ' <ren.msg | sed 's/\.c/\\./g'
diff --git a/krb5-1-6/src/lib/krb4/send_to_kdc.c b/krb5-1-6/src/lib/krb4/send_to_kdc.c
new file mode 100644
index 000000000..95d9d9113
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/send_to_kdc.c
@@ -0,0 +1,206 @@
+/*
+ * lib/krb4/send_to_kdc.c
+ *
+ * Copyright 1987-2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "krbports.h"
+#include "prot.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "autoconf.h"
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "port-sockets.h"
+#include "fake-addrinfo.h"
+#include "k5-int.h"
+#include "krb4int.h"
+
+#define S_AD_SZ sizeof(struct sockaddr_in)
+
+/* These are really defaults from getservbyname() or hardcoded. */
+static int cached_krb_udp_port = 0;
+static int cached_krbsec_udp_port = 0;
+
+int krb4int_send_to_kdc_addr(KTEXT, KTEXT, char *,
+			     struct sockaddr *, socklen_t *);
+
+#ifdef DEBUG
+static char *prog = "send_to_kdc";
+#endif
+
+/*
+ * send_to_kdc() sends a message to the Kerberos authentication
+ * server(s) in the given realm and returns the reply message.
+ * The "pkt" argument points to the message to be sent to Kerberos;
+ * the "rpkt" argument will be filled in with Kerberos' reply.
+ * The "realm" argument indicates the realm of the Kerberos server(s)
+ * to transact with.  If the realm is null, the local realm is used.
+ *
+ * If more than one Kerberos server is known for a given realm,
+ * different servers will be queried until one of them replies.
+ * Several attempts (retries) are made for each server before
+ * giving up entirely.
+ *
+ * The following results can be returned:
+ *
+ * KSUCCESS	- an answer was received from a Kerberos host
+ *
+ * SKDC_CANT    - can't get local realm
+ *              - can't find "kerberos" in /etc/services database
+ *              - can't open socket
+ *              - can't bind socket
+ *              - all ports in use
+ *              - couldn't find any Kerberos host
+ *
+ * SKDC_RETRY   - couldn't get an answer from any Kerberos server,
+ *		  after several retries
+ */
+
+int
+krb4int_send_to_kdc_addr(
+    KTEXT pkt, KTEXT rpkt, char *realm,
+    struct sockaddr *addr, socklen_t *addrlen)
+{
+    struct addrlist	al = ADDRLIST_INIT;
+    char		lrealm[REALM_SZ];
+    krb5int_access	internals;
+    krb5_error_code	retval;
+    struct servent	*sp;
+    int			krb_udp_port = 0;
+    int			krbsec_udp_port = 0;
+    char		krbhst[MAXHOSTNAMELEN];
+    char		*scol;
+    int			i;
+    int			err;
+    krb5_data		message, reply;
+
+    /*
+     * If "realm" is non-null, use that, otherwise get the
+     * local realm.
+     */
+    if (realm)
+	strncpy(lrealm, realm, sizeof(lrealm) - 1);
+    else {
+	if (krb_get_lrealm(lrealm, 1)) {
+	    DEB (("%s: can't get local realm\n", prog));
+	    return SKDC_CANT;
+	}
+    }
+    lrealm[sizeof(lrealm) - 1] = '\0';
+    DEB (("lrealm is %s\n", lrealm));
+
+    retval = krb5int_accessor(&internals, KRB5INT_ACCESS_VERSION);
+    if (retval)
+	return KFAILURE;
+
+    /* The first time, decide what port to use for the KDC.  */
+    if (cached_krb_udp_port == 0) {
+	sp = getservbyname("kerberos","udp");
+        if (sp)
+	    cached_krb_udp_port = sp->s_port;
+	else
+	    cached_krb_udp_port = htons(KERBEROS_PORT); /* kerberos/udp */
+        DEB (("cached_krb_udp_port is %d\n", cached_krb_udp_port));
+    }
+    /* If kerberos/udp isn't 750, try using kerberos-sec/udp (or 750) 
+       as a fallback. */
+    if (cached_krbsec_udp_port == 0 && 
+	cached_krb_udp_port != htons(KERBEROS_PORT)) {
+	sp = getservbyname("kerberos-sec","udp");
+        if (sp)
+	    cached_krbsec_udp_port = sp->s_port;
+	else
+	    cached_krbsec_udp_port = htons(KERBEROS_PORT); /* kerberos/udp */
+        DEB (("cached_krbsec_udp_port is %d\n", cached_krbsec_udp_port));
+    }
+
+    for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
+#ifdef DEBUG
+        if (krb_debug) {
+            DEB (("Getting host entry for %s...",krbhst));
+            (void) fflush(stdout);
+        }
+#endif
+	if (0 != (scol = strchr(krbhst,':'))) {
+	    krb_udp_port = htons(atoi(scol+1));
+	    *scol = 0;
+	    if (krb_udp_port == 0) {
+#ifdef DEBUG
+		if (krb_debug) {
+		    DEB (("bad port number %s\n",scol+1));
+		    (void) fflush(stdout);
+		}
+#endif
+		continue;
+	    }
+	    krbsec_udp_port = 0;
+	} else {
+	    krb_udp_port = cached_krb_udp_port;
+	    krbsec_udp_port = cached_krbsec_udp_port;
+	}
+        err = internals.add_host_to_list(&al, krbhst,
+					 krb_udp_port, krbsec_udp_port,
+					 SOCK_DGRAM, PF_INET);
+	if (err) {
+	    retval = SKDC_CANT;
+	    goto free_al;
+	}
+    }
+    if (al.naddrs == 0) {
+	DEB (("%s: can't find any Kerberos host.\n", prog));
+        retval = SKDC_CANT;
+    }
+
+    message.length = pkt->length;
+    message.data = (char *)pkt->dat; /* XXX yuck */
+    retval = internals.sendto_udp(NULL, &message, &al, NULL, &reply, addr,
+				  addrlen, NULL, 0, NULL, NULL, NULL);
+    DEB(("sendto_udp returns %d\n", retval));
+free_al:
+    internals.free_addrlist(&al);
+    if (retval)
+	return SKDC_CANT;
+    DEB(("reply.length=%d\n", reply.length));
+    if (reply.length > sizeof(rpkt->dat))
+	retval = SKDC_CANT;
+    rpkt->length = 0;
+    if (!retval) {
+	memcpy(rpkt->dat, reply.data, reply.length);
+	rpkt->length = reply.length;
+    }
+    krb5_free_data_contents(NULL, &reply);
+    return retval;
+}
+
+int
+send_to_kdc(KTEXT pkt, KTEXT rpkt, char *realm)
+{
+    return krb4int_send_to_kdc_addr(pkt, rpkt, realm, NULL, NULL);
+}
diff --git a/krb5-1-6/src/lib/krb4/sendauth.c b/krb5-1-6/src/lib/krb4/sendauth.c
new file mode 100644
index 000000000..83729442a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/sendauth.c
@@ -0,0 +1,282 @@
+/*
+ * sendauth.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+#include "mit-copyright.h"
+
+#include "krb.h"
+#include "krb4int.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include "port-sockets.h"
+
+#define	KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in krb_recvauth.c
+ */
+
+/*
+ * This file contains two routines: krb_sendauth() and krb_sendsrv().
+ *
+ * krb_sendauth() transmits a ticket over a file descriptor for a
+ * desired service, instance, and realm, doing mutual authentication
+ * with the server if desired.
+ *
+ * Most of the real work of krb_sendauth() has been moved into mk_auth.c
+ * for portability; sendauth takes a Unix file descriptor as argument,
+ * which doesn't work on other operating systems.
+ *
+ * krb_sendsvc() sends a service name to a remote knetd server, and is
+ * only for Athena compatability.
+ */
+
+/*
+ * The first argument to krb_sendauth() contains a bitfield of
+ * options (the options are defined in "krb.h"):
+ *
+ * KOPT_DONT_CANON	Don't canonicalize instance as a hostname.
+ *			(If this option is not chosen, krb_get_phost()
+ *			is called to canonicalize it.)
+ *
+ * KOPT_DONT_MK_REQ 	Don't request server ticket from Kerberos.
+ *			A ticket must be supplied in the "ticket"
+ *			argument.
+ *			(If this option is not chosen, and there
+ *			is no ticket for the given server in the
+ *			ticket cache, one will be fetched using
+ *			krb_mk_req() and returned in "ticket".)
+ *
+ * KOPT_DO_MUTUAL	Do mutual authentication, requiring that the
+ * 			receiving server return the checksum+1 encrypted
+ *			in the session key.  The mutual authentication
+ *			is done using krb_mk_priv() on the other side
+ *			(see "recvauth.c") and krb_rd_priv() on this
+ *			side.
+ *
+ * The "fd" argument is a file descriptor to write to the remote
+ * server on.  The "ticket" argument is used to store the new ticket
+ * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
+ * chosen, the ticket must be supplied in the "ticket" argument.
+ * The "service", "inst", and "realm" arguments identify the ticket.
+ * If "realm" is null, the local realm is used.
+ *
+ * The following arguments are only needed if the KOPT_DO_MUTUAL option
+ * is chosen:
+ *
+ *   The "checksum" argument is a number that the server will add 1 to
+ *   to authenticate itself back to the client; the "msg_data" argument
+ *   holds the returned mutual-authentication message from the server
+ *   (i.e., the checksum+1); the "cred" structure is used to hold the
+ *   session key of the server, extracted from the ticket file, for use
+ *   in decrypting the mutual authentication message from the server;
+ *   and "schedule" holds the key schedule for that decryption.  The
+ *   the local and server addresses are given in "laddr" and "faddr".
+ *
+ * The application protocol version number (of up to KRB_SENDAUTH_VLEN
+ * characters) is passed in "version".
+ *
+ * If all goes well, KSUCCESS is returned, otherwise some error code.
+ *
+ * The format of the message sent to the server is:
+ *
+ * Size			Variable		Field
+ * ----			--------		-----
+ *
+ * KRB_SENDAUTH_VLEN	KRB_SENDAUTH_VER	sendauth protocol
+ * bytes					version number
+ *
+ * KRB_SENDAUTH_VLEN	version			application protocol
+ * bytes					version number
+ *
+ * 4 bytes		ticket->length		length of ticket
+ *
+ * ticket->length	ticket->dat		ticket itself
+ */
+
+/*
+ * XXX: Note that krb_rd_priv() is coded in such a way that
+ * "msg_data->app_data" will be pointing into "packet", which
+ * will disappear when krb_sendauth() returns.
+ * 
+ * See FIXME KLUDGE code in appl/bsd/kcmd.c.
+ */
+KRB4_32 __krb_sendauth_hidden_tkt_len=0;
+#define raw_tkt_len __krb_sendauth_hidden_tkt_len
+
+
+/* 
+ * Read a server's sendauth response out of a file descriptor.
+ * Returns a Kerberos error code.
+ *
+ * Note sneaky code using raw_tkt_len to stash away a bit of info
+ * for use by appl/bsd/kcmd.c.  Now that krb_net_rd_sendauth is
+ * a separate function, kcmd should call it directly to get this
+ * sneaky info.  
+ */
+int
+krb_net_rd_sendauth (fd, reply, raw_len)
+     int fd;			/* file descriptor to write onto */
+     KTEXT reply;		/* Where we put the reply message */
+     KRB4_32 *raw_len;		/* Where to read the length field info */
+{
+    KRB4_32 tkt_len;
+    int got;
+
+    reply->length = 0;		/* Nothing read from net yet */
+    reply->mbz = 0;
+
+    /* get the length of the reply */
+  reread:
+    got = krb_net_read(fd, (char *)raw_len, sizeof(KRB4_32));
+    if (got != sizeof(KRB4_32))
+	return KFAILURE;
+
+    /* Here's an amazing hack.  If we are contacting an rlogin server,
+       and it is running on a Sun4, and it was compiled with the wrong
+       shared libary version, it will print an ld.so warning message
+       when it starts up.  We just ignore any such message and keep
+       going.  This doesn't affect security: we just require the
+       ticket to follow the warning message.  */
+    if (!memcmp("ld.s", raw_len, 4)) {
+    	char c;
+
+	while (krb_net_read(fd, &c, 1) == 1 && c != '\n')
+	    ;
+	goto reread;
+    }
+
+    tkt_len = ntohl(*raw_len);
+
+    /* if the length is negative, the server failed to recognize us. */
+    if ((tkt_len < 0) || (tkt_len > sizeof(reply->dat)))
+	return KFAILURE;	 /* XXX */
+    /* read the reply... */
+    got = krb_net_read(fd, (char *)reply->dat, (int) tkt_len);
+    if (got != (int) tkt_len)
+	return KFAILURE;
+
+    reply->length = tkt_len;
+    reply->mbz = 0;
+    return KSUCCESS;
+}
+
+
+/*
+ * krb_sendauth
+ * 
+ * The original routine, provided on Unix.
+ * Obtains a service ticket using the ticket-granting ticket,
+ * uses it to stuff an authorization request down a Unix socket to the
+ * end-user application server, sucks a response out of the socket, 
+ * and decodes it to verify mutual authentication.
+ */
+int KRB5_CALLCONV
+krb_sendauth(options, fd, ticket, service, inst, realm, checksum,
+	     msg_data, cred, schedule, laddr, faddr, version)
+     long options;		/* bit-pattern of options */
+     int fd;			/* file descriptor to write onto */
+     KTEXT ticket;		/* where to put ticket (return); or
+				   supplied in case of KOPT_DONT_MK_REQ */
+     char *service;         /* service name */
+     char *inst;            /* service instance */
+     char *realm;           /* service realm */
+     unsigned KRB4_32 checksum; /* checksum to include in request */
+     MSG_DAT *msg_data;		/* mutual auth MSG_DAT (return) */
+     CREDENTIALS *cred;		/* credentials (return) */
+     Key_schedule schedule;	/* key schedule (return) */
+     struct sockaddr_in *laddr;	/* local address */
+     struct sockaddr_in *faddr;	/* address of foreign host on fd */
+     char *version;		/* version string */
+{
+    int rem, cc;
+    char srv_inst[INST_SZ];
+    char krb_realm[REALM_SZ];
+    KTEXT_ST packet[1];		/* Re-use same one for msg and reply */
+
+    /* get current realm if not passed in */
+    if (!realm) {
+	rem = krb_get_lrealm(krb_realm,1);
+	if (rem != KSUCCESS)
+	    return(rem);
+	realm = krb_realm;
+    }
+
+    /* copy instance into local storage, so mk_auth can canonicalize */
+    (void) strncpy(srv_inst, inst, INST_SZ-1);
+    srv_inst[INST_SZ-1] = 0;
+    rem = krb_mk_auth (options, ticket, service, srv_inst, realm, checksum,
+   			   version, packet);
+    if (rem != KSUCCESS)
+	return rem;
+
+#ifdef ATHENA_COMPAT
+    /* this is only for compatibility with old servers */
+    if (options & KOPT_DO_OLDSTYLE) {
+	(void) sprintf(buf,"%d ",ticket->length);
+	(void) write(fd, buf, strlen(buf));
+	(void) write(fd, (char *) ticket->dat, ticket->length);
+	return(rem);
+    }
+#endif /* ATHENA_COMPAT */
+
+    /* write the request to the server */
+    if ((cc = krb_net_write(fd, packet->dat, packet->length)) != packet->length)
+	return(cc);
+
+    /* mutual authentication, if desired */
+    if (options & KOPT_DO_MUTUAL) {
+	/* get credentials so we have service session
+	   key for decryption below */
+	cc = krb_get_cred(service, srv_inst, realm, cred);
+	if (cc)
+	    return(cc);
+
+	/* Get the reply out of the socket.  */
+	cc = krb_net_rd_sendauth (fd, packet, &raw_tkt_len);
+	if (cc != KSUCCESS)
+	    return cc;
+
+	/* Check the reply to verify that server is really who we expect.  */
+	cc = krb_check_auth (packet, checksum,
+		msg_data, cred->session, schedule, laddr, faddr);
+	if (cc != KSUCCESS)
+	    return cc;
+    }
+    return(KSUCCESS);
+}
+
+
+#ifdef ATHENA_COMPAT
+/*
+ * krb_sendsvc
+ */
+
+int
+krb_sendsvc(fd, service)
+     int fd;
+     char *service;
+{
+    /* write the service name length and then the service name to
+       the fd */
+    KRB4_32 serv_length;
+    int cc;
+
+    serv_length = htonl((unsigned long)strlen(service));
+    if ((cc = krb_net_write(fd, (char *) &serv_length,
+	sizeof(serv_length)))
+	!= sizeof(serv_length))
+	return(cc);
+    if ((cc = krb_net_write(fd, service, strlen(service)))
+	!= strlen(service))
+	return(cc);
+    return(KSUCCESS);
+}
+#endif /* ATHENA_COMPAT */
diff --git a/krb5-1-6/src/lib/krb4/setenv.c b/krb5-1-6/src/lib/krb4/setenv.c
new file mode 100644
index 000000000..76a2a615b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/setenv.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setenv.c	5.2 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#include "conf.h"
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * setenv --
+ *	Set the value of the environmental variable "name" to be
+ *	"value".  If rewrite is set, replace any current value.
+ */
+int setenv(name, value, rewrite)
+	register char *name, *value;
+	int rewrite;
+{
+	extern char **environ;
+	static int alloced;			/* if allocated space before */
+	register char *C;
+	int l_value, offset;
+	char *malloc(), *realloc(), *_findenv();
+
+	if (*value == '=')			/* no `=' in value */
+		++value;
+	l_value = strlen(value);
+	if ((C = _findenv(name, &offset))) {	/* find if already exists */
+		if (!rewrite)
+			return(0);
+		if (strlen(C) >= l_value) {	/* old larger; copy over */
+			while (*C++ = *value++);
+			return(0);
+		}
+	}
+	else {					/* create new slot */
+		register int	cnt;
+		register char	**P;
+
+		for (P = environ, cnt = 0; *P; ++P, ++cnt);
+		if (alloced) {			/* just increase size */
+			environ = (char **)realloc((char *)environ,
+			    (u_int)(sizeof(char *) * (cnt + 2)));
+			if (!environ)
+				return(-1);
+		}
+		else {				/* get new space */
+			alloced = 1;		/* copy old entries into it */
+			P = (char **)malloc((u_int)(sizeof(char *) *
+			    (cnt + 2)));
+			if (!P)
+				return(-1);
+			memcpy(P, environ, cnt * sizeof(char *));
+			environ = P;
+		}
+		environ[cnt + 1] = NULL;
+		offset = cnt;
+	}
+	for (C = name; *C && *C != '='; ++C);	/* no `=' in name */
+	if (!(environ[offset] =			/* name + `=' + value */
+	    malloc((u_int)((int)(C - name) + l_value + 2))))
+		return(-1);
+	for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
+	for (*C++ = '='; *C++ = *value++;);
+	return(0);
+}
+
+/*
+ * unsetenv(name) --
+ *	Delete environmental variable "name".
+ */
+void
+unsetenv(name)
+	char	*name;
+{
+	extern	char	**environ;
+	register char	**P;
+	int	offset;
+	char    *_findenv();
+
+	while (_findenv(name, &offset))		/* if set multiple times */
+		for (P = &environ[offset];; ++P)
+			if (!(*P = *(P + 1)))
+				break;
+}
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef HAVE_GETENV
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getenv.c	5.5 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * getenv --
+ *	Returns ptr to value associated with name, if any, else NULL.
+ */
+char *
+getenv(name)
+	char *name;
+{
+	int offset;
+	char *_findenv();
+
+	return(_findenv(name, &offset));
+}
+#endif
+/*
+ * _findenv --
+ *	Returns pointer to value associated with name, if any, else NULL.
+ *	Sets offset to be the offset of the name/value combination in the
+ *	environmental array, for use by setenv(3) and unsetenv(3).
+ *	Explicitly removes '=' in argument name.
+ *
+ *	This routine *should* be a static; don't use it.
+ */
+char *
+_findenv(name, offset)
+	register char *name;
+	int *offset;
+{
+	extern char **environ;
+	register int len;
+	register char **P, *C;
+
+	for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+	for (P = environ; *P; ++P)
+		if (!strncmp(*P, name, len))
+			if (*(C = *P + len) == '=') {
+				*offset = P - environ;
+				return(++C);
+			}
+	return(NULL);
+}
diff --git a/krb5-1-6/src/lib/krb4/stime.c b/krb5-1-6/src/lib/krb4/stime.c
new file mode 100644
index 000000000..92c86895e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/stime.c
@@ -0,0 +1,57 @@
+/*
+ * lib/krb4/stime.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "krb4int.h"
+#include <stdio.h>                      /* for sprintf() */
+#ifndef _WIN32
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+/*
+ * Given a pointer to a long containing the number of seconds
+ * since the beginning of time (midnight 1 Jan 1970 GMT), return
+ * a string containing the local time in the form:
+ *
+ * "25-Jan-88 10:17:56"
+ */
+
+char *krb_stime(t)
+    long *t;
+{
+    static char st[40];
+    static time_t adjusted_time;
+    struct tm *tm;
+
+    adjusted_time = *t - CONVERT_TIME_EPOCH;
+    tm = localtime(&adjusted_time);
+    (void) sprintf(st,"%2d-%s-%d %02d:%02d:%02d",tm->tm_mday,
+                   month_sname(tm->tm_mon + 1),1900+tm->tm_year,
+                   tm->tm_hour, tm->tm_min, tm->tm_sec);
+    return st;
+}
+
diff --git a/krb5-1-6/src/lib/krb4/strcasecmp.c b/krb5-1-6/src/lib/krb4/strcasecmp.c
new file mode 100644
index 000000000..31bf0afbf
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/strcasecmp.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+strcasecmp(s1, s2)
+	char *s1, *s2;
+{
+	register unsigned char	*cm = charmap,
+			*us1 = (unsigned char *)s1,
+			*us2 = (unsigned char *)s2;
+
+	while (cm[*us1] == cm[*us2++])
+		if (*us1++ == '\0')
+			return(0);
+	return(cm[*us1] - cm[*--us2]);
+}
+
+strncasecmp(s1, s2, n)
+	char *s1, *s2;
+	register int n;
+{
+	register unsigned char	*cm = charmap,
+			*us1 = (unsigned char *)s1,
+			*us2 = (unsigned char *)s2;
+
+	while (--n >= 0 && cm[*us1] == cm[*us2++])
+		if (*us1++ == '\0')
+			return(0);
+	return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
+}
diff --git a/krb5-1-6/src/lib/krb4/strnlen.c b/krb5-1-6/src/lib/krb4/strnlen.c
new file mode 100644
index 000000000..5dc80115c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/strnlen.c
@@ -0,0 +1,50 @@
+/*
+ * lib/krb4/strnlen.c
+ *
+ * Copyright 2000, 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include <stddef.h>
+#include "krb.h"
+#include "prot.h"
+
+/*
+ * krb4int_strnlen()
+ *
+ * Return the length of the string if a NUL is found in the first n
+ * bytes, otherwise, -1.
+ */
+
+int KRB5_CALLCONV
+krb4int_strnlen(const char *s, int n)
+{
+    int i = 0;
+
+    for (i = 0; i < n; i++) {
+        if (s[i] == '\0') {
+            return i;
+	}
+    }
+    return -1;
+}
diff --git a/krb5-1-6/src/lib/krb4/swab.c b/krb5-1-6/src/lib/krb4/swab.c
new file mode 100644
index 000000000..e07b28b43
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/swab.c
@@ -0,0 +1,18 @@
+/* simple implementation of swab. */
+
+swab(from,to,nbytes) 
+        char *from;
+        char *to;
+        int nbytes;
+{
+	char tmp;
+        while ( (nbytes-=2) >= 0 ) {
+                tmp = from[1];
+                to[1] = from[0];
+		to[0] = tmp;
+                to++; to++;
+                from++; from++;
+        }
+}
+
+
diff --git a/krb5-1-6/src/lib/krb4/tf_shm.c b/krb5-1-6/src/lib/krb4/tf_shm.c
new file mode 100644
index 000000000..bd08f7f72
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/tf_shm.c
@@ -0,0 +1,171 @@
+/*
+ * tf_shm.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Shared memory segment functions for session keys.  Derived from code
+ * contributed by Dan Kolkowitz (kolk@jessica.stanford.edu).
+ */
+
+#include "mit-copyright.h"
+
+#include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "krb.h"
+#include "des.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define MAX_BUFF sizeof(des_cblock)*1000 /* room for 1k keys */
+
+extern int krb_debug;
+
+/*
+ * krb_create_shmtkt:
+ *
+ * create a shared memory segment for session keys, leaving its id
+ * in the specified filename.
+ */
+
+int
+krb_shm_create(file_name)
+char *file_name;
+{
+    int retval;
+    int shmid;
+    struct shmid_ds shm_buf;
+    FILE *sfile;
+    uid_t me, metoo, getuid(), geteuid();
+
+    (void) krb_shm_dest(file_name);	/* nuke it if it exists...
+					 this cleans up to make sure we
+					 don't slowly lose memory. */
+
+    shmid = shmget((long)IPC_PRIVATE,MAX_BUFF, IPC_CREAT);
+    if (shmid == -1) { 
+	if (krb_debug)
+	    perror("krb_shm_create shmget");
+	return(KFAILURE);		/* XXX */
+    }
+    me = getuid();
+    metoo = geteuid();
+    /* 
+     * now set up the buffer so that we can modify it 
+     */
+    shm_buf.shm_perm.uid = me;
+    shm_buf.shm_perm.gid = getgid();
+    shm_buf.shm_perm.mode = 0600;
+    if (shmctl(shmid,IPC_SET,&shm_buf) < 0) { /*can now map it */
+	if (krb_debug)
+	    perror("krb_shm_create shmctl");
+	(void) shmctl(shmid, IPC_RMID, 0);
+	return(KFAILURE);		/* XXX */
+    }
+#if !defined(_AIX)
+    (void) shmctl(shmid, SHM_LOCK, 0);	/* attempt to lock-in-core */
+#endif
+    /* arrange so the file is owned by the ruid
+       (swap real & effective uid if necessary). */
+    if (me != metoo) {
+	if (setreuid(metoo, me) < 0) {
+	    /* can't switch??? barf! */
+	    if (krb_debug)
+		perror("krb_shm_create: setreuid");
+	    (void) shmctl(shmid, IPC_RMID, 0);
+	    return(KFAILURE);
+	} else
+	    if (krb_debug)
+		printf("swapped UID's %d and %d\n",metoo,me);
+    }
+    if ((sfile = fopen(file_name,"w")) == 0) {
+	if (krb_debug)
+	    perror("krb_shm_create file");
+	(void) shmctl(shmid, IPC_RMID, 0);
+	return(KFAILURE);		/* XXX */
+    } 
+    if (fchmod(fileno(sfile),0600) < 0) {
+	if (krb_debug)
+	    perror("krb_shm_create fchmod");
+	(void) shmctl(shmid, IPC_RMID, 0);
+	return(KFAILURE);		/* XXX */
+    }	
+    if (me != metoo) {
+	if (setreuid(me, metoo) < 0) {
+	    /* can't switch??? barf! */
+	    if (krb_debug)
+		perror("krb_shm_create: setreuid2");
+	    (void) shmctl(shmid, IPC_RMID, 0);
+	    return(KFAILURE);
+	} else
+	    if (krb_debug)
+		printf("swapped UID's %d and %d\n",me,metoo);
+    }
+
+    (void) fprintf(sfile,"%d",shmid);
+    (void) fflush(sfile);
+    (void) fclose(sfile);
+    return(KSUCCESS);
+}
+
+
+/*
+ * krb_is_diskless:
+ *
+ * check / to see if file .diskless exists.  If so it is diskless.
+ *     Do it this way now to avoid dependencies on a particular routine.
+ *      Choose root file system since that will be private to the client.
+ */
+
+int krb_is_diskless()
+{
+	struct stat buf;
+	if (stat("/.diskless",&buf) < 0) 
+		return(0);
+	else return(1);
+}
+			
+/*
+ * krb_shm_dest: destroy shared memory segment with session keys, and remove
+ * file pointing to it.
+ */
+
+int krb_shm_dest(file)
+char *file;
+{
+    int shmid;
+    FILE *sfile;
+    struct stat st_buf;
+
+    if (stat(file,&st_buf) == 0) {
+	/* successful stat */
+	if ((sfile = fopen(file,"r")) == 0) {
+	    if (krb_debug)
+		perror("cannot open shared memory file");
+	    return(KFAILURE);		/* XXX */
+	}
+	if (fscanf(sfile,"%d",&shmid) == 1) {
+		if (shmctl(shmid,IPC_RMID,0) != 0) {
+		    if (krb_debug)
+			perror("krb_shm_dest: cannot delete shm segment");
+		    (void) fclose(sfile);
+		    return(KFAILURE);	/* XXX */
+		}		    
+	} else {
+	    if (krb_debug)
+		fprintf(stderr, "bad format in shmid file\n");
+	    (void) fclose(sfile);
+	    return(KFAILURE);		/* XXX */
+	}
+	(void) fclose(sfile);
+	(void) unlink(file);
+	return(KSUCCESS);
+    } else
+	return(RET_TKFIL);		/* XXX */
+}
+
+	
+
diff --git a/krb5-1-6/src/lib/krb4/tf_util.c b/krb5-1-6/src/lib/krb4/tf_util.c
new file mode 100644
index 000000000..b083c73b8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/tf_util.c
@@ -0,0 +1,1097 @@
+/*
+ * lib/krb4/tf_util.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2000, 2001 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "k5-int.h"
+#include "krb4int.h"
+
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* TKT_SHMEM */
+
+
+
+#define TOO_BIG -1
+#define TF_LCK_RETRY ((unsigned)2)	/* seconds to sleep before
+					 * retry if ticket file is
+					 * locked */
+extern int krb_debug;
+
+void tf_close();
+
+#ifdef TKT_SHMEM
+char *krb_shm_addr;
+static char *tmp_shm_addr;
+static const char krb_dummy_skey[8];
+
+char *shmat();
+#endif /* TKT_SHMEM */
+
+#ifdef NEED_UTIMES
+
+#include <sys/time.h>
+#ifdef __SCO__
+#include <utime.h>
+#endif
+#if defined(__svr4__) || defined(__SVR4)
+#include <utime.h>
+#endif
+int utimes(path, times)
+     char* path;
+     struct timeval times[2];
+{
+  struct utimbuf tv;
+  tv.actime = times[0].tv_sec;
+  tv.modtime = times[1].tv_sec;
+  return utime(path,&tv);
+}
+#endif
+
+#ifdef HAVE_SETEUID
+#define do_seteuid(e) seteuid((e))
+#else
+#ifdef HAVE_SETRESUID
+#define do_seteuid(e) setresuid(-1, (e), -1)
+#else
+#ifdef HAVE_SETREUID
+#define do_seteuid(e) setreuid(geteuid(), (e))
+#else
+#define do_seteuid(e) (errno = EPERM, -1)
+#endif
+#endif
+#endif
+
+
+#ifdef K5_LE
+/* This was taken from jhutz's patch for heimdal krb4. It only
+ * applies to little endian systems. Big endian systems have a
+ * less elegant solution documented below.
+ *
+ * This record is written after every real ticket, to ensure that
+ * both 32- and 64-bit readers will perceive the next real ticket
+ * as starting in the same place.  This record looks like a ticket
+ * with the following properties:
+ *   Field         32-bit             64-bit
+ *   ============  =================  =================
+ *   sname         "."                "."
+ *   sinst         ""                 ""
+ *   srealm        ".."               ".."
+ *   session key   002E2E00 xxxxxxxx  xxxxxxxx 00000000
+ *   lifetime      0                  0
+ *   kvno          0                  12
+ *   ticket        12 nulls           4 nulls
+ *   issue         0                  0
+ *
+ * Our code always reads and writes the 32-bit format, but knows
+ * to skip 00000000 at the front of a record, and to completely
+ * ignore tickets for the special alignment principal.
+ */
+static unsigned char align_rec[] = {
+    0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00, 0x2e,
+    0x2e, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00
+};
+
+#else /* Big Endian */
+
+/* These alignment records are for big endian systems. We need more
+ * of them because the portion of the 64-bit issue_date that overlaps
+ * with the start of a ticket on 32-bit systems contains an unpredictable
+ * number of NULL bytes. Preceeding these records is a second copy of the
+ * 32-bit issue_date. The srealm for the alignment records is always one of
+ * ".." or "?.."
+ */
+
+/* No NULL bytes
+ * This is actually two alignment records since both 32- and 64-bit
+ * readers will agree on everything in the first record up through the
+ * issue_date size, except where sname starts.
+ *   Field (1)     32-bit             64-bit
+ *   ============  =================  =================
+ *   sname         "????."            "."
+ *   sinst         ""                 ""
+ *   srealm        ".."               ".."
+ *   session key   00000000 xxxxxxxx  00000000 xxxxxxxx
+ *   lifetime      0                  0
+ *   kvno          0                  0
+ *   ticket        4 nulls           4 nulls
+ *   issue         0                  0
+ *
+ *   Field (2)     32-bit             64-bit
+ *   ============  =================  =================
+ *   sname         "."                "."
+ *   sinst         ""                 ""
+ *   srealm        ".."               ".."
+ *   session key   002E2E00 xxxxxxxx  xxxxxxxx 00000000
+ *   lifetime      0                  0
+ *   kvno          0                  12
+ *   ticket        12 nulls           4 nulls
+ *   issue         0                  0
+ *
+ */
+static unsigned char align_rec_0[] = {
+    0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00,
+    0x00, 0x2e, 0x2e, 0x00, 0xff, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00
+};
+
+/* One NULL byte
+ *   Field         32-bit             64-bit
+ *   ============  =================  =================
+ *   sname         "x"  |"xx"|"xxx"   "."
+ *   sinst         "xx."|"x."|"."     ".."
+ *   srealm        ".."               "..."
+ *   session key   2E2E2E00 xxxxxxxx  xxxxxxxx 00000000
+ *   lifetime      0                  0
+ *   kvno          0                  12
+ *   ticket        12 nulls           4 nulls
+ *   issue         0                  0
+ */
+static unsigned char align_rec_1[] = {
+    0x2e, 0x00, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e,
+    0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00
+};
+
+/* Two NULL bytes
+ *   Field         32-bit             64-bit
+ *   ============  =================  =================
+ *   sname         "x"  |"x" |"xx"    ".."
+ *   sinst         ""   |"x" |""      ""
+ *   srealm        "x.."|".."|".."    ".."
+ *   session key   002E2E00 xxxxxxxx  xxxxxxxx 00000000
+ *   lifetime      0                  0
+ *   kvno          0                  12
+ *   ticket        12 nulls           4 nulls
+ *   issue         0                  0
+ */
+ static unsigned char align_rec_2[] = {
+    0x2e, 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0xff,
+    0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* Three NULL bytes
+ * Things break here for 32-bit krb4 libraries that don't
+ * understand this alignment record. We can't really do
+ * anything about the fact that the three strings ended
+ * in the duplicate timestamp. The good news is that this
+ * only happens once every 0x1000000 seconds, once roughly
+ * every six and a half months. We'll live.
+ *
+ * Discussion on the krbdev list has suggested the
+ * issue_date be incremented by one in this case to avoid
+ * the problem. I'm leaving this here just in case.
+ *
+ *   Field         32-bit             64-bit
+ *   ============  =================  =================
+ *   sname         ""                 "."
+ *   sinst         ""                 ""
+ *   srealm        ""                 ".."
+ *   session key   2E00002E 2E00FFFF  xxxx0000 0000xxxx
+ *   lifetime      0                  0
+ *   kvno          4294901760         917504
+ *   ticket        14 nulls           4 nulls
+ *   issue         0                  0
+ */
+/*
+static unsigned char align_rec_3[] = {
+    0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+*/
+#endif /* K5_LE*/
+
+/*
+ * fd must be initialized to something that won't ever occur as a real
+ * file descriptor. Since open(2) returns only non-negative numbers as
+ * valid file descriptors, and tf_init always stuffs the return value
+ * from open in here even if it is an error flag, we must
+ * 	a. Initialize fd to a negative number, to indicate that it is
+ * 	   not initially valid.
+ *	b. When checking for a valid fd, assume that negative values
+ *	   are invalid (ie. when deciding whether tf_init has been
+ *	   called.)
+ *	c. In tf_close, be sure it gets reinitialized to a negative
+ *	   number. 
+ */
+static int  fd = -1;
+static int  curpos;			/* Position in tfbfr */
+static int  lastpos;			/* End of tfbfr */
+static char tfbfr[BUFSIZ];		/* Buffer for ticket data */
+
+static int tf_gets (char *, int), tf_read (char *, int);
+
+/*
+ * This file contains routines for manipulating the ticket cache file.
+ *
+ * The ticket file is in the following format:
+ *
+ *      principal's name        (null-terminated string)
+ *      principal's instance    (null-terminated string)
+ *      CREDENTIAL_1
+ *      CREDENTIAL_2
+ *      ...
+ *      CREDENTIAL_n
+ *      EOF
+ *
+ *      Where "CREDENTIAL_x" consists of the following fixed-length
+ *      fields from the CREDENTIALS structure (see "krb.h"):
+ *
+ *              string          service[ANAME_SZ]
+ *              string          instance[INST_SZ]
+ *              string          realm[REALM_SZ]
+ *              C_Block         session
+ *              int             lifetime
+ *              int             kvno
+ *              KTEXT_ST        ticket_st
+ *              KRB4_32         issue_date
+ *
+ * Strings are stored NUL-terminated, and read back until a NUL is
+ * found or the indicated number of bytes have been read.  (So if you
+ * try to store a string exactly that long or longer, reading them
+ * back will not work.)  The KTEXT_ST structure is stored as an int
+ * length followed by that many data bytes.  All ints are stored using
+ * host size and byte order for "int".
+ *
+ * Short description of routines:
+ *
+ * tf_init() opens the ticket file and locks it.
+ *
+ * tf_get_pname() returns the principal's name.
+ *
+ * tf_get_pinst() returns the principal's instance (may be null).
+ *
+ * tf_get_cred() returns the next CREDENTIALS record.
+ *
+ * tf_save_cred() appends a new CREDENTIAL record to the ticket file.
+ *
+ * tf_close() closes the ticket file and releases the lock.
+ *
+ * tf_gets() returns the next null-terminated string.  It's an internal
+ * routine used by tf_get_pname(), tf_get_pinst(), and tf_get_cred().
+ *
+ * tf_read() reads a given number of bytes.  It's an internal routine
+ * used by tf_get_cred().
+ */
+
+/*
+ * tf_init() should be called before the other ticket file routines.
+ * It takes the name of the ticket file to use, "tf_name", and a
+ * read/write flag "rw" as arguments. 
+ *
+ * It tries to open the ticket file, checks the mode, and if everything
+ * is okay, locks the file.  If it's opened for reading, the lock is
+ * shared.  If it's opened for writing, the lock is exclusive. 
+ *
+ * Returns KSUCCESS if all went well, otherwise one of the following: 
+ *
+ * NO_TKT_FIL   - file wasn't there
+ * TKT_FIL_ACC  - file was in wrong mode, etc.
+ * TKT_FIL_LCK  - couldn't lock the file, even after a retry
+ */
+
+int KRB5_CALLCONV tf_init(tf_name, rw)
+    const char   *tf_name;
+    int rw;
+{
+    int     wflag;
+    uid_t   me, metoo;
+    struct stat stat_buf, stat_buffd;
+#ifdef TKT_SHMEM
+    char shmidname[MAXPATHLEN]; 
+    FILE *sfp;
+    int shmid;
+#endif
+
+    if (!krb5__krb4_context) {
+	    if (krb5_init_context(&krb5__krb4_context))
+		    return TKT_FIL_LCK;
+    }
+
+    me = getuid();
+    metoo = geteuid();
+
+    switch (rw) {
+    case R_TKT_FIL:
+	wflag = 0;
+	break;
+    case W_TKT_FIL:
+	wflag = 1;
+	break;
+    default:
+	if (krb_debug) fprintf(stderr, "tf_init: illegal parameter\n");
+	return TKT_FIL_ACC;
+    }
+
+    /* If ticket cache selector is null, use default cache.  */
+    if (tf_name == 0)
+	tf_name = tkt_string();
+
+#ifdef TKT_SHMEM
+    (void) strncpy(shmidname, tf_name, sizeof(shmidname) - 1);
+    shmidname[sizeof(shmidname) - 1] = '\0';
+    (void) strncat(shmidname, ".shm", sizeof(shmidname) - 1 - strlen(shmidname));
+#endif /* TKT_SHMEM */
+
+    /*
+     * If "wflag" is set, open the ticket file in append-writeonly mode
+     * and lock the ticket file in exclusive mode.  If unable to lock
+     * the file, sleep and try again.  If we fail again, return with the
+     * proper error message. 
+     */
+
+    curpos = sizeof(tfbfr);
+
+#ifdef TKT_SHMEM
+    if (lstat(shmidname, &stat_buf) < 0) {
+	switch (errno) {
+	case ENOENT:
+	    return NO_TKT_FIL;
+	default:
+	    return TKT_FIL_ACC;
+	}
+    }
+    if (stat_buf.st_uid != me || !(stat_buf.st_mode & S_IFREG)
+	|| stat_buf.st_nlink != 1 || stat_buf.st_mode & 077) {
+	return TKT_FIL_ACC;
+    }
+
+    /*
+     * Yes, we do uid twiddling here.  It's not optimal, but some
+     * applications may expect that the ruid is what should really own
+     * the ticket file, e.g. setuid applications.
+     */
+    if (me != metoo && do_seteuid(me) < 0)
+	return KFAILURE;
+    sfp = fopen(shmidname, "r");	/* only need read/write on the
+					   actual tickets */
+    if (me != metoo && do_seteuid(metoo) < 0)
+	return KFAILURE;
+    if (sfp == 0) {
+        switch(errno) {
+        case ENOENT:
+	    return NO_TKT_FIL;
+	default:
+	    return TKT_FIL_ACC;
+	}
+    }
+
+    /*
+     * fstat() the file to check that the file we opened is the one we
+     * think it is.
+     */
+    if (fstat(fileno(sfp), &stat_buffd) < 0) {
+        (void) close(fd);
+	fd = -1;
+	switch(errno) {
+	case ENOENT:
+	    return NO_TKT_FIL;
+	default:
+	    return TKT_FIL_ACC;
+	}
+    }
+    /* Check that it's the right file */
+    if ((stat_buf.st_ino != stat_buffd.st_ino) ||
+	(stat_buf.st_dev != stat_buffd.st_dev)) {
+        (void) close(fd);
+	fd = -1;
+	return TKT_FIL_ACC;
+    }
+    /* Check ownership */
+    if ((stat_buffd.st_uid != me && me != 0) ||
+	((stat_buffd.st_mode & S_IFMT) != S_IFREG)) {
+        (void) close(fd);
+	fd = -1;
+	return TKT_FIL_ACC;
+    }
+
+
+
+    shmid = -1;
+    {
+	char buf[BUFSIZ];
+	int val;			/* useful for debugging fscanf */
+	/* We provide our own buffer here since some STDIO libraries
+	   barf on unbuffered input with fscanf() */
+	setbuf(sfp, buf);
+	if ((val = fscanf(sfp,"%d",&shmid)) != 1) {
+	    (void) fclose(sfp);
+	    return TKT_FIL_ACC;
+	}
+	if (shmid < 0) {
+	    (void) fclose(sfp);
+	    return TKT_FIL_ACC;
+	}
+	(void) fclose(sfp);
+    }
+    /*
+    * global krb_shm_addr is initialized to 0.  Ultrix bombs when you try and
+    * attach the same segment twice so we need this check.
+    */
+    if (!krb_shm_addr) {
+    	if ((krb_shm_addr = shmat(shmid,0,0)) == -1){
+		if (krb_debug)
+		    fprintf(stderr,
+			    "cannot attach shared memory for segment %d\n",
+			    shmid);
+		krb_shm_addr = 0;	/* reset so we catch further errors */
+		return TKT_FIL_ACC;
+	    }
+    }
+    tmp_shm_addr = krb_shm_addr;
+#endif /* TKT_SHMEM */
+    
+    if (lstat(tf_name, &stat_buf) < 0) {
+	switch (errno) {
+	case ENOENT:
+	    return NO_TKT_FIL;
+	default:
+	    return TKT_FIL_ACC;
+	}
+    }
+    if (stat_buf.st_uid != me || !(stat_buf.st_mode & S_IFREG)
+	|| stat_buf.st_nlink != 1 || stat_buf.st_mode & 077) {
+	return TKT_FIL_ACC;
+    }
+
+    if (wflag) {
+	if (me != metoo && do_seteuid(me) < 0)
+	    return KFAILURE;
+	fd = open(tf_name, O_RDWR, 0600);
+	if (me != metoo && do_seteuid(metoo) < 0)
+	    return KFAILURE;
+	if (fd < 0) {
+	    switch(errno) {
+	    case ENOENT:
+	        return NO_TKT_FIL;
+	    default:
+	        return TKT_FIL_ACC;
+	  }
+	}
+	/*
+	 * fstat() the file to check that the file we opened is the
+	 * one we think it is, and to check ownership.
+	 */
+	if (fstat(fd, &stat_buffd) < 0) {
+	    (void) close(fd);
+	    fd = -1;
+	    switch(errno) {
+	    case ENOENT:
+	        return NO_TKT_FIL;
+	    default:
+	        return TKT_FIL_ACC;
+	    }
+	}
+	/* Check that it's the right file */
+	if ((stat_buf.st_ino != stat_buffd.st_ino) ||
+	    (stat_buf.st_dev != stat_buffd.st_dev)) {
+	    (void) close(fd);
+	    fd = -1;
+	    return TKT_FIL_ACC;
+	}
+	/* Check ownership */
+	if ((stat_buffd.st_uid != me && me != 0) ||
+	    ((stat_buffd.st_mode & S_IFMT) != S_IFREG)) {
+	    (void) close(fd);
+	    fd = -1;
+	    return TKT_FIL_ACC;
+	}
+	if (krb5_lock_file(krb5__krb4_context, fd,
+			   KRB5_LOCKMODE_EXCLUSIVE |
+			   KRB5_LOCKMODE_DONTBLOCK) < 0) {
+	    sleep(TF_LCK_RETRY);
+	    if (krb5_lock_file(krb5__krb4_context, fd,
+			   KRB5_LOCKMODE_EXCLUSIVE |
+			   KRB5_LOCKMODE_DONTBLOCK) < 0) {
+		(void) close(fd);
+		fd = -1;
+		return TKT_FIL_LCK;
+	    }
+	}
+	return KSUCCESS;
+    }
+    /*
+     * Otherwise "wflag" is not set and the ticket file should be opened
+     * for read-only operations and locked for shared access. 
+     */
+
+    if (me != metoo && do_seteuid(me) < 0)
+	return KFAILURE;
+    fd = open(tf_name, O_RDONLY, 0600);
+    if (me != metoo && do_seteuid(metoo) < 0)
+	return KFAILURE;
+    if (fd < 0) {
+        switch(errno) {
+	case ENOENT:
+	    return NO_TKT_FIL;
+	default:
+	    return TKT_FIL_ACC;
+	}
+    }
+    /*
+     * fstat() the file to check that the file we opened is the one we
+     * think it is, and to check ownership.
+     */
+    if (fstat(fd, &stat_buffd) < 0) {
+        (void) close(fd);
+	fd = -1;
+	switch(errno) {
+	case ENOENT:
+	    return NO_TKT_FIL;
+	default:
+	    return TKT_FIL_ACC;
+	}
+    }
+    /* Check that it's the right file */
+    if ((stat_buf.st_ino != stat_buffd.st_ino) ||
+	(stat_buf.st_dev != stat_buffd.st_dev)) {
+        (void) close(fd);
+	fd = -1;
+	return TKT_FIL_ACC;
+    }
+    /* Check ownership */
+    if ((stat_buffd.st_uid != me && me != 0) ||
+	((stat_buffd.st_mode & S_IFMT) != S_IFREG)) {
+        (void) close(fd);
+	fd = -1;
+	return TKT_FIL_ACC;
+    }
+    if (krb5_lock_file(krb5__krb4_context, fd,
+			   KRB5_LOCKMODE_SHARED |
+			   KRB5_LOCKMODE_DONTBLOCK) < 0) {
+	sleep(TF_LCK_RETRY);
+	if (krb5_lock_file(krb5__krb4_context, fd,
+			   KRB5_LOCKMODE_SHARED |
+			   KRB5_LOCKMODE_DONTBLOCK) < 0) {
+	    (void) close(fd);
+	    fd = -1;
+	    return TKT_FIL_LCK;
+	}
+    }
+    return KSUCCESS;
+}
+
+/*
+ * tf_get_pname() reads the principal's name from the ticket file. It
+ * should only be called after tf_init() has been called.  The
+ * principal's name is filled into the "p" parameter.  If all goes well,
+ * KSUCCESS is returned.  If tf_init() wasn't called, TKT_FIL_INI is
+ * returned.  If the name was null, or EOF was encountered, or the name
+ * was longer than ANAME_SZ, TKT_FIL_FMT is returned. 
+ */
+
+int KRB5_CALLCONV tf_get_pname(p)
+    char   *p;
+{
+    if (fd < 0) {
+	if (krb_debug)
+	    fprintf(stderr, "tf_get_pname called before tf_init.\n");
+	return TKT_FIL_INI;
+    }
+    if (tf_gets(p, ANAME_SZ) < 2)	/* can't be just a null */
+	return TKT_FIL_FMT;
+    return KSUCCESS;
+}
+
+/*
+ * tf_get_pinst() reads the principal's instance from a ticket file.
+ * It should only be called after tf_init() and tf_get_pname() have been
+ * called.  The instance is filled into the "inst" parameter.  If all
+ * goes well, KSUCCESS is returned.  If tf_init() wasn't called,
+ * TKT_FIL_INI is returned.  If EOF was encountered, or the instance
+ * was longer than ANAME_SZ, TKT_FIL_FMT is returned.  Note that the
+ * instance may be null. 
+ */
+
+int KRB5_CALLCONV tf_get_pinst(inst)
+    char   *inst;
+{
+    if (fd < 0) {
+	if (krb_debug)
+	    fprintf(stderr, "tf_get_pinst called before tf_init.\n");
+	return TKT_FIL_INI;
+    }
+    if (tf_gets(inst, INST_SZ) < 1)
+	return TKT_FIL_FMT;
+    return KSUCCESS;
+}
+
+/*
+ * tf_get_cred() reads a CREDENTIALS record from a ticket file and fills
+ * in the given structure "c".  It should only be called after tf_init(),
+ * tf_get_pname(), and tf_get_pinst() have been called. If all goes well,
+ * KSUCCESS is returned.  Possible error codes are: 
+ *
+ * TKT_FIL_INI  - tf_init wasn't called first
+ * TKT_FIL_FMT  - bad format
+ * EOF          - end of file encountered
+ */
+
+static int  real_tf_get_cred(c)
+    CREDENTIALS *c;
+{
+    KTEXT   ticket = &c->ticket_st;	/* pointer to ticket */
+    int     k_errno;
+    unsigned char nullbuf[3];  /* used for 64-bit issue_date tf compatibility */
+
+    if (fd < 0) {
+	if (krb_debug)
+	    fprintf(stderr, "tf_get_cred called before tf_init.\n");
+	return TKT_FIL_INI;
+    }
+    if ((k_errno = tf_gets(c->service, SNAME_SZ)) < 2) {
+
+#ifdef K5_BE
+	/* If we're big endian then we can have a null service name as part of
+	 * an alignment record. */
+	if (k_errno < 2)
+	    switch (k_errno) {
+	    case TOO_BIG:
+		tf_close();
+		return TKT_FIL_FMT;
+	    case 0:
+		return EOF;
+	    }
+#else /* Little Endian */
+	/* If we read an empty service name, it's possible that's because
+	 * the file was written by someone who thinks issue_date should be
+	 * 64 bits.  If that is the case, there will be three more zeros,
+	 * followed by the real record.*/
+
+	if (k_errno == 1 && 
+	    tf_read(nullbuf, 3) == 3 &&
+	    !nullbuf[0] && !nullbuf[1] && !nullbuf[2])
+	    k_errno = tf_gets(c->service, SNAME_SZ);
+
+	if (k_errno < 2)
+	switch (k_errno) {
+	case TOO_BIG:
+	case 1:		/* can't be just a null */
+	    tf_close();
+	    return TKT_FIL_FMT;
+	case 0:
+	    return EOF;
+	}
+#endif/*K5_BE*/
+
+    }
+    if ((k_errno = tf_gets(c->instance, INST_SZ)) < 1)
+	switch (k_errno) {
+	case TOO_BIG:
+	    return TKT_FIL_FMT;
+	case 0:
+	    return EOF;
+	}
+    if ((k_errno = tf_gets(c->realm, REALM_SZ)) < 2) {
+	switch (k_errno) {
+	case TOO_BIG:
+	case 1:		/* can't be just a null */
+	    tf_close();
+	    return TKT_FIL_FMT;
+	case 0:
+	    return EOF;
+	}
+    }
+    
+    if (
+	tf_read((char *) (c->session), KEY_SZ) < 1 ||
+	tf_read((char *) &(c->lifetime), sizeof(c->lifetime)) < 1 ||
+	tf_read((char *) &(c->kvno), sizeof(c->kvno)) < 1 ||
+	tf_read((char *) &(ticket->length), sizeof(ticket->length))
+	< 1 ||
+    /* don't try to read a silly amount into ticket->dat */
+	ticket->length > MAX_KTXT_LEN ||
+	tf_read((char *) (ticket->dat), ticket->length) < 1 ||
+	tf_read((char *) &(c->issue_date), sizeof(c->issue_date)) < 1
+	) {
+	tf_close();
+	return TKT_FIL_FMT;
+    }
+
+#ifdef K5_BE
+    /* If the issue_date is 0 and we're not dealing with an alignment
+       record, then it's likely we've run into an issue_date written by
+       a 64-bit library that is using long instead of KRB4_32. Let's get
+       the next four bytes instead.
+     */
+    if (0 == c->issue_date) {
+	int len = strlen(c->realm);
+	if (!(2 == len && 0 == strcmp(c->realm, "..")) &&
+	    !(3 == len && 0 == strcmp(c->realm + 1, ".."))) {
+	    if (tf_read((char *) &(c->issue_date), sizeof(c->issue_date)) < 1) {
+		tf_close();
+		return TKT_FIL_FMT;
+	    }
+	}
+    }
+
+#endif
+    
+    return KSUCCESS;
+}
+
+int KRB5_CALLCONV tf_get_cred(c)
+    CREDENTIALS *c;
+{
+    int     k_errno;
+    int     fake;
+    
+    do {
+	fake = 0;
+	k_errno = real_tf_get_cred(c);
+	if (k_errno)
+	    return k_errno;
+	
+#ifdef K5_BE
+	/* Here we're checking to see if the realm is one of the 
+	 * alignment record realms, ".." or "?..", so we can skip it.
+	 * If it's not, then we need to verify that the service name
+	 * was not null as this should be a valid ticket.
+	 */
+	{
+	    int len = strlen(c->realm);
+	    if (2 == len && 0 == strcmp(c->realm, ".."))
+		fake = 1;
+	    if (3 == len && 0 == strcmp(c->realm + 1, ".."))
+		fake = 1;
+	    if (!fake && 0 == strlen(c->service)) {
+		tf_close();
+		return TKT_FIL_FMT;
+	    }
+	}
+#else /* Little Endian */
+	/* Here we're checking to see if the service principal is the
+	 * special alignment record principal ".@..", so we can skip it.
+	 */
+	if (strcmp(c->service, ".") == 0 &&
+	    strcmp(c->instance, "") == 0 &&
+	    strcmp(c->realm, "..") == 0)
+	    fake = 1;
+#endif/*K5_BE*/
+    } while (fake);
+    
+#ifdef TKT_SHMEM
+    memcpy(c->session, tmp_shm_addr, KEY_SZ);
+    tmp_shm_addr += KEY_SZ;
+#endif /* TKT_SHMEM */
+    return KSUCCESS;
+}
+
+/*
+ * tf_close() closes the ticket file and sets "fd" to -1. If "fd" is
+ * not a valid file descriptor, it just returns.  It also clears the
+ * buffer used to read tickets.
+ *
+ * The return value is not defined.
+ */
+
+void KRB5_CALLCONV tf_close()
+{
+    if (!(fd < 0)) {
+#ifdef TKT_SHMEM
+	if (shmdt(krb_shm_addr)) {
+	    /* what kind of error? */
+	    if (krb_debug)
+		fprintf(stderr, "shmdt 0x%x: errno %d",krb_shm_addr, errno);
+	} else {
+	    krb_shm_addr = 0;
+	}
+#endif /* TKT_SHMEM */
+	if (!krb5__krb4_context)
+		krb5_init_context(&krb5__krb4_context);
+	(void) krb5_lock_file(krb5__krb4_context, fd, KRB5_LOCKMODE_UNLOCK);
+	(void) close(fd);
+	fd = -1;		/* see declaration of fd above */
+    }
+    memset(tfbfr, 0, sizeof(tfbfr));
+}
+
+/*
+ * tf_gets() is an internal routine.  It takes a string "s" and a count
+ * "n", and reads from the file until either it has read "n" characters,
+ * or until it reads a null byte. When finished, what has been read exists
+ * in "s". If it encounters EOF or an error, it closes the ticket file. 
+ *
+ * Possible return values are:
+ *
+ * n            the number of bytes read (including null terminator)
+ *              when all goes well
+ *
+ * 0            end of file or read error
+ *
+ * TOO_BIG      if "count" characters are read and no null is
+ *		encountered. This is an indication that the ticket
+ *		file is seriously ill.
+ */
+
+static int
+tf_gets(s, n)
+    register char *s;
+    int n;
+{
+    register int count;
+
+    if (fd < 0) {
+	if (krb_debug)
+	    fprintf(stderr, "tf_gets called before tf_init.\n");
+	return TKT_FIL_INI;
+    }
+    for (count = n - 1; count > 0; --count) {
+	if (curpos >= sizeof(tfbfr)) {
+	    lastpos = read(fd, tfbfr, sizeof(tfbfr));
+	    curpos = 0;
+	}
+	if (curpos == lastpos) {
+	    tf_close();
+	    return 0;
+	}
+	*s = tfbfr[curpos++];
+	if (*s++ == '\0')
+	    return (n - count);
+    }
+    tf_close();
+    return TOO_BIG;
+}
+
+/*
+ * tf_read() is an internal routine.  It takes a string "s" and a count
+ * "n", and reads from the file until "n" bytes have been read.  When
+ * finished, what has been read exists in "s".  If it encounters EOF or
+ * an error, it closes the ticket file.
+ *
+ * Possible return values are:
+ *
+ * n		the number of bytes read when all goes well
+ *
+ * 0		on end of file or read error
+ */
+
+static int
+tf_read(s, n)
+    register char *s;
+    register int  n;
+{
+    register int count;
+    
+    for (count = n; count > 0; --count) {
+	if (curpos >= sizeof(tfbfr)) {
+	    lastpos = read(fd, tfbfr, sizeof(tfbfr));
+	    curpos = 0;
+	}
+	if (curpos == lastpos) {
+	    tf_close();
+	    return 0;
+	}
+	*s++ = tfbfr[curpos++];
+    }
+    return n;
+}
+     
+/*
+ * tf_save_cred() appends an incoming ticket to the end of the ticket
+ * file.  You must call tf_init() before calling tf_save_cred().
+ *
+ * The "service", "instance", and "realm" arguments specify the
+ * server's name; "session" contains the session key to be used with
+ * the ticket; "kvno" is the server key version number in which the
+ * ticket is encrypted, "ticket" contains the actual ticket, and
+ * "issue_date" is the time the ticket was requested (local host's time).
+ *
+ * Returns KSUCCESS if all goes well, TKT_FIL_INI if tf_init() wasn't
+ * called previously, and KFAILURE for anything else that went wrong.
+ */
+
+int tf_save_cred(service, instance, realm, session, lifetime, kvno,
+		 ticket, issue_date)
+    char   *service;		/* Service name */
+    char   *instance;		/* Instance */
+    char   *realm;		/* Auth domain */
+    C_Block session;		/* Session key */
+    int     lifetime;		/* Lifetime */
+    int     kvno;		/* Key version number */
+    KTEXT   ticket;		/* The ticket itself */
+    KRB4_32 issue_date;		/* The issue time */
+{
+
+    off_t   lseek();
+    unsigned int count;		/* count for write */
+#ifdef TKT_SHMEM
+    int	    *skey_check;
+#endif /* TKT_SHMEM */
+
+    if (fd < 0) {		/* fd is ticket file as set by tf_init */
+	  if (krb_debug)
+	      fprintf(stderr, "tf_save_cred called before tf_init.\n");
+	  return TKT_FIL_INI;
+    }
+    /* Find the end of the ticket file */
+    (void) lseek(fd, (off_t)0, 2);
+#ifdef TKT_SHMEM
+    /* scan to end of existing keys: pick first 'empty' slot.
+       we assume that no real keys will be completely zero (it's a weak
+       key under DES) */
+
+    skey_check = (int *) krb_shm_addr;
+
+    while (*skey_check && *(skey_check+1))
+	skey_check += 2;
+    tmp_shm_addr = (char *)skey_check;
+#endif /* TKT_SHMEM */
+
+    /* Write the ticket and associated data */
+    /* Service */
+    count = strlen(service) + 1;
+    if (write(fd, service, count) != count)
+	goto bad;
+    /* Instance */
+    count = strlen(instance) + 1;
+    if (write(fd, instance, count) != count)
+	goto bad;
+    /* Realm */
+    count = strlen(realm) + 1;
+    if (write(fd, realm, count) != count)
+	goto bad;
+    /* Session key */
+#ifdef TKT_SHMEM
+    memcpy(tmp_shm_addr, session, 8);
+    tmp_shm_addr+=8;
+    if (write(fd,krb_dummy_skey,8) != 8)
+	goto bad;
+#else /* ! TKT_SHMEM */
+    if (write(fd, (char *) session, 8) != 8)
+	goto bad;
+#endif /* TKT_SHMEM */
+    /* Lifetime */
+    if (write(fd, (char *) &lifetime, sizeof(int)) != sizeof(int))
+	goto bad;
+    /* Key vno */
+    if (write(fd, (char *) &kvno, sizeof(int)) != sizeof(int))
+	goto bad;
+    /* Tkt length */
+    if (write(fd, (char *) &(ticket->length), sizeof(int)) !=
+	sizeof(int))
+	goto bad;
+    /* Ticket */
+    count = ticket->length;
+    if (write(fd, (char *) (ticket->dat), count) != count)
+	goto bad;
+    /* Issue date */
+    if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
+	!= sizeof(KRB4_32))
+	goto bad;
+    /* Alignment Record */
+#ifdef K5_BE
+    {
+	int null_bytes = 0;
+	if (0 == (issue_date & 0xff000000))
+	    ++null_bytes;
+	if (0 == (issue_date & 0x00ff0000))
+	    ++null_bytes;
+	if (0 == (issue_date & 0x0000ff00))
+	    ++null_bytes;
+	if (0 == (issue_date & 0x000000ff))
+	    ++null_bytes;
+	
+	switch(null_bytes) {
+	case 0:
+	    /* Issue date */
+	    if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
+		!= sizeof(KRB4_32))
+	goto bad;
+	    if (write(fd, align_rec_0, sizeof(align_rec_0))
+		!= sizeof(align_rec_0))
+		goto bad;
+	    break;
+	    
+	case 1:
+	    if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
+		!= sizeof(KRB4_32))
+		goto bad;
+	    if (write(fd, align_rec_1, sizeof(align_rec_1))
+		!= sizeof(align_rec_1))
+		goto bad;
+	    break;
+	    
+	case 3:
+	    /* Three NULLS are troublesome but rare. We'll just pretend 
+	     * they don't exist by decrementing the issue_date.
+	     */
+	    --issue_date;
+	case 2:
+	    if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
+		!= sizeof(KRB4_32))
+		goto bad;
+	    if (write(fd, align_rec_2, sizeof(align_rec_2))
+		!= sizeof(align_rec_2))
+		goto bad;
+	    break;
+	    
+	default:
+	    goto bad;
+	}
+	
+    }    
+#else
+    if (write(fd, align_rec, sizeof(align_rec)) != sizeof(align_rec))
+	goto bad;
+#endif 
+
+    /* Actually, we should check each write for success */
+    return (KSUCCESS);
+bad:
+    return (KFAILURE);
+}
diff --git a/krb5-1-6/src/lib/krb4/tkt_string.c b/krb5-1-6/src/lib/krb4/tkt_string.c
new file mode 100644
index 000000000..123596ca2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/tkt_string.c
@@ -0,0 +1,100 @@
+/*
+ * tkt_string.c
+ *
+ * Copyright 1985, 1986, 1987, 1988, 2002 by the Massachusetts
+ * Institute of Technology.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "autoconf.h"
+#include "port-sockets.h" /* XXX this gets us MAXPATHLEN but we should find
+			     a better way */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+char *getenv();
+#endif
+
+
+#ifdef _WIN32
+typedef unsigned long uid_t;
+uid_t getuid(void) { return 0; }
+#endif /* _WIN32 */
+
+/*
+ * This routine is used to generate the name of the file that holds
+ * the user's cache of server tickets and associated session keys.
+ *
+ * If it is set, krb_ticket_string contains the ticket file name.
+ * Otherwise, the filename is constructed as follows:
+ *
+ * If it is set, the environment variable "KRBTKFILE" will be used as
+ * the ticket file name.  Otherwise TKT_ROOT (defined in "krb.h") and
+ * the user's uid are concatenated to produce the ticket file name
+ * (e.g., "/tmp/tkt123").  A pointer to the string containing the ticket
+ * file name is returned.
+ */
+
+static char krb_ticket_string[MAXPATHLEN];
+
+const char *tkt_string()
+{
+    char *env;
+    uid_t getuid();
+
+    if (!*krb_ticket_string) {
+	env = getenv("KRBTKFILE");
+        if (env) {
+	    (void) strncpy(krb_ticket_string, env,
+			   sizeof(krb_ticket_string)-1);
+	    krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
+	} else {
+	    /* 32 bits of signed integer will always fit in 11 characters
+	     (including the sign), so no need to worry about overflow */
+	    (void) sprintf(krb_ticket_string, "%s%d",TKT_ROOT,(int) getuid());
+        }
+    }
+    return krb_ticket_string;
+}
+
+/*
+ * This routine is used to set the name of the file that holds the user's
+ * cache of server tickets and associated session keys.
+ *
+ * The value passed in is copied into local storage.
+ *
+ * NOTE:  This routine should be called during initialization, before other
+ * Kerberos routines are called; otherwise tkt_string() above may be called
+ * and return an undesired ticket file name until this routine is called.
+ */
+
+void KRB5_CALLCONV
+krb_set_tkt_string(val)
+    const char *val;
+{
+    (void) strncpy(krb_ticket_string, val, sizeof(krb_ticket_string)-1);
+    krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
+}
diff --git a/krb5-1-6/src/lib/krb4/unix_glue.c b/krb5-1-6/src/lib/krb4/unix_glue.c
new file mode 100644
index 000000000..93a30ed01
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/unix_glue.c
@@ -0,0 +1,40 @@
+/*
+ * unix_glue.c
+ * 
+ * Glue code for pasting Kerberos into the Unix environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#include "krb.h"
+#include <sys/time.h>
+#include "krb4int.h"
+
+/* Start and end Kerberos library access.  On Unix, this is a No-op.  */
+int
+krb_start_session (x)
+	char *x;
+{
+	return KSUCCESS;
+}
+
+int
+krb_end_session (x)
+	char *x;
+{
+	return KSUCCESS;
+}
+
+char *
+krb_get_default_user ()
+{
+	return 0;		/* FIXME */
+}
+
+int
+krb_set_default_user (x)
+	char *x;
+{
+	return KFAILURE;	/* FIXME */
+}
diff --git a/krb5-1-6/src/lib/krb4/unix_time.c b/krb5-1-6/src/lib/krb4/unix_time.c
new file mode 100644
index 000000000..411ee38d6
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/unix_time.c
@@ -0,0 +1,26 @@
+/*
+ * unix_time.c
+ * 
+ * Glue code for pasting Kerberos into the Unix environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#include "krb.h"
+#include <sys/time.h>
+
+/* Time handling.  Translate Unix time calls into Kerberos cnternal 
+   procedure calls.  See ../../include/cc-unix.h.  */
+
+unsigned KRB4_32 KRB5_CALLCONV
+unix_time_gmt_unixsec (usecptr)
+	unsigned KRB4_32	*usecptr;
+{
+	struct timeval	now;
+
+	(void) gettimeofday (&now, (struct timezone *)0);
+	if (usecptr)
+		*usecptr = now.tv_usec;
+	return now.tv_sec;
+}
diff --git a/krb5-1-6/src/lib/krb4/vmslink.com b/krb5-1-6/src/lib/krb4/vmslink.com
new file mode 100644
index 000000000..95cabfe1d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/vmslink.com
@@ -0,0 +1,79 @@
+$ write sys$output "start of run"
+$ cc /decc /inc=inc /debug=all des.c
+$ cc /decc /inc=inc /debug=all d3des.c
+$ cc /decc /inc=inc /debug=all cbc.c
+$ cc /decc /inc=([],inc) /debug=all qcksum.c
+$ cc /decc /inc=([],inc) /debug=all str2key.c
+$ cc /decc /inc=([],inc) /debug=all parity.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all ad_print.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all add_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_auth_repl.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_ciph.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_death_pkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_err_repl.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_tkt.c
+$ write sys$output "begin d"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all debug.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all decomp_tkt.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all dest_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all err_txt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all ext_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all fakeenv.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all fgetst.c
+$ write sys$output "begin g"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_ad_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_admhst.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_cnffile.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_cred.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_in_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_krbhst.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_krbrlm.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_phost.c
+sgtty $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_pw_in_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_pw_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_request.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_svc_in_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_tf_fname.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_tf_realm.c
+$ write sys$output "end g_"
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",BSD42) /debug=all gethostname.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all getst.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all in_tkt.c
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",NEED_TIME_H) /debug=all klog.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kname_parse.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kntoln.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kparse.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all krbglue.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kuserok.c
+$ write sys$output "end k"
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",NEED_TIME_H) /debug=all log.c 
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_err.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_preauth.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_priv.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_req.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_safe.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all month_sname.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all netread.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all netwrite.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all pkt_cipher.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all pkt_clen.c
+$ write sys$output "begin rd"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_err.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_preauth.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_priv.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_req.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_safe.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_svc_key.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all realmofhost.c
+$ write sys$output "begin recv"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all recvauth.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all save_creds.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all send_to_kdc.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all sendauth.c
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",NEED_TIME_H) /debug=all stime.c 
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all tf_shm.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all tf_util.c
+MAXPATHLEN $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all tkt_string.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all vmsswab.c
+$ library /create /list libkrb *.obj
+
diff --git a/krb5-1-6/src/lib/krb4/vmsswab.c b/krb5-1-6/src/lib/krb4/vmsswab.c
new file mode 100644
index 000000000..019580882
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/vmsswab.c
@@ -0,0 +1,34 @@
+/* Copyright 1994 Cygnus Support */
+/* Mark W. Eichin */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* VMS doesn't have swab, but everything else does */
+/* so make this available anyway ... someday it might go
+   into the VMS makefile fragment, but for now it is only
+   referenced by l.com. */
+
+swab(from,to,nbytes) 
+        char *from;
+        char *to;
+        int nbytes;
+{
+	char tmp;
+
+        while ( (nbytes-=2) >= 0 ) {
+		tmp = from[1];
+                to[1] = from[0];
+		to[0] = tmp;
+                to++; to++;
+                from++; from++;
+        }
+}
+
diff --git a/krb5-1-6/src/lib/krb4/win_glue.c b/krb5-1-6/src/lib/krb4/win_glue.c
new file mode 100644
index 000000000..e9cb5db33
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/win_glue.c
@@ -0,0 +1,51 @@
+/*
+ * win-glue.c
+ * 
+ * Glue code for pasting Kerberos into the Windows environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#include "krb.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <windows.h>
+
+
+/*
+ * We needed a way to print out what might be FAR pointers on Windows,
+ * but might be ordinary pointers on real machines.  Printf modifiers
+ * scattered through the code don't cut it,
+ * since they might break on real machines.  Microloss
+ * didn't provide a function to print a char *, so we wrote one.
+ * It gets #define'd to fputs on real machines. 
+ */
+int
+far_fputs(string, stream)
+	char *string;
+	FILE *stream;
+{
+	return fprintf(stream, "%Fs", string);
+}
+
+int
+krb_start_session(x)
+     char *x;
+{
+	return KSUCCESS;
+}
+
+int
+krb_end_session(x)
+     char *x;
+{
+	return KSUCCESS;
+}
+
+void KRB5_CALLCONV
+krb_set_tkt_string(val)
+char *val;
+{
+}
diff --git a/krb5-1-6/src/lib/krb4/win_store.c b/krb5-1-6/src/lib/krb4/win_store.c
new file mode 100644
index 000000000..74c79ac5a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/win_store.c
@@ -0,0 +1,150 @@
+/*
+ * win_store.c
+ *
+ * Kerberos configuration storage management routines.
+ *
+ * Originally coded by John Rivlin / Fusion Software, Inc.
+ *
+ * This file incorporates replacements for the following Unix files:
+ *   g_cnffil.c
+ */
+
+#include "krb.h"
+#include "k5-int.h"
+#include <stdio.h>
+#include <assert.h>
+
+krb5_context krb5__krb4_context = 0;
+
+char *
+krb__get_srvtabname(default_srvtabname)
+	const char *default_srvtabname;
+{
+	const char* names[3];
+	char **full_name = 0, **cpp;
+	krb5_error_code retval;
+	char *retname;
+
+	if (!krb5__krb4_context) {
+		retval = krb5_init_context(&krb5__krb4_context);
+		if (!retval)
+			return NULL;
+	}
+	names[0] = "libdefaults";
+	names[1] = "krb4_srvtab";
+	names[2] = 0;
+	retval = profile_get_values(krb5__krb4_context->profile, names, 
+				    &full_name);
+	if (retval == 0 && full_name && full_name[0]) {
+		retname = strdup(full_name[0]);
+		for (cpp = full_name; *cpp; cpp++) 
+			krb5_xfree(*cpp);
+		krb5_xfree(full_name);
+	} else {
+		retname = strdup(default_srvtabname);
+	}
+	return retname;
+}
+
+/*
+ * Returns an open file handle to the configuration file.  This
+ * file was called "krb.conf" on Unix.  Here we search for the entry
+ * "krb.conf=" in the "[FILES]" section of the "kerberos.ini" file
+ * located in the Windows directory.  If the entry doesn't exist in
+ * the kerberos.ini file, then "krb.con" in the Windows directory is
+ * used in its place.
+ */
+FILE*
+krb__get_cnffile()
+{
+	FILE *cnffile = 0;
+	char cnfname[FILENAME_MAX];
+	char defname[FILENAME_MAX];
+	UINT rc;
+
+	defname[sizeof(defname) - 1] = '\0';
+	rc = GetWindowsDirectory(defname, sizeof(defname) - 1);
+	assert(rc > 0);
+
+	strncat(defname, "\\", sizeof(defname) - 1 - strlen(defname));
+
+	strncat(defname, DEF_KRB_CONF, sizeof(defname) - 1 - strlen(defname));
+
+	cnfname[sizeof(cnfname) - 1] = '\0';
+	GetPrivateProfileString(INI_FILES, INI_KRB_CONF, defname,
+		cnfname, sizeof(cnfname) - 1, KERBEROS_INI);
+
+	cnffile = fopen(cnfname, "r");
+
+	return cnffile;
+}
+
+
+/*
+ * Returns an open file handle to the realms file.  This
+ * file was called "krb.realms" on Unix.  Here we search for the entry
+ * "krb.realms=" in the "[FILES]" section of the "kerberos.ini" file
+ * located in the Windows directory.  If the entry doesn't exist in
+ * the kerberos.ini file, then "krb.rea" in the Windows directory is
+ * used in its place.
+ */
+FILE*
+krb__get_realmsfile()
+{
+	FILE *realmsfile = 0;
+	char realmsname[FILENAME_MAX];
+	char defname[FILENAME_MAX];
+	UINT rc;
+
+	defname[sizeof(defname) - 1] = '\0';
+	rc = GetWindowsDirectory(defname, sizeof(defname) - 1);
+	assert(rc > 0);
+
+	strncat(defname, "\\", sizeof(defname) - 1 - strlen(defname));
+
+	strncat(defname, DEF_KRB_REALMS, sizeof(defname) - 1 - strlen(defname));
+
+	defname[sizeof(defname) - 1] = '\0';
+	GetPrivateProfileString(INI_FILES, INI_KRB_REALMS, defname,
+		realmsname, sizeof(realmsname) - 1, KERBEROS_INI);
+
+	realmsfile = fopen(realmsname, "r");
+
+	return realmsfile;
+}
+
+
+/*
+ * Returns the current default user.  This information is stored in
+ * the [DEFAULTS] section of the "kerberos.ini" file located in the
+ * Windows directory.
+ */
+char * KRB5_CALLCONV
+krb_get_default_user()
+{
+	static char username[ANAME_SZ];
+
+	GetPrivateProfileString(INI_DEFAULTS, INI_USER, "",
+		username, sizeof(username), KERBEROS_INI);
+
+	return username;
+}
+
+
+/*
+ * Sets the default user name stored in the "kerberos.ini" file.
+ */
+int KRB5_CALLCONV
+krb_set_default_user(username)
+	char *username;
+{
+	BOOL rc;
+
+	rc = WritePrivateProfileString(INI_DEFAULTS, INI_USER,
+		username, KERBEROS_INI);
+
+	if (rc)
+		return KSUCCESS;
+	else
+		return KFAILURE;
+}
diff --git a/krb5-1-6/src/lib/krb4/win_time.c b/krb5-1-6/src/lib/krb4/win_time.c
new file mode 100644
index 000000000..2560c3192
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4/win_time.c
@@ -0,0 +1,121 @@
+/*
+ * win_time.c
+ * 
+ * Glue code for pasting Kerberos into the Windows environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#include "krb.h"
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/timeb.h>
+#include <stdio.h>
+#include <windows.h>
+#include <dos.h>
+
+#ifdef _WIN32
+
+unsigned KRB4_32
+win_time_gmt_unixsec (usecptr)
+    unsigned KRB4_32	*usecptr;
+{
+    struct _timeb timeptr;
+
+    _ftime(&timeptr);                           /* Get the current time */
+
+    if (usecptr)
+	*usecptr = timeptr.millitm * 1000;
+
+    return timeptr.time + CONVERT_TIME_EPOCH;
+}
+
+#else
+
+/*
+ * Time handling.  Translate Unix time calls into Kerberos internal 
+ * procedure calls.  See ../../include/c-win.h.
+ *
+ * Due to the fact that DOS time can be unreliable we have reverted
+ * to using the AT hardware clock and converting it to Unix time.
+ */
+
+unsigned KRB4_32
+win_time_gmt_unixsec (usecptr)
+	unsigned KRB4_32	*usecptr;
+{
+	struct tm tm;
+	union _REGS inregs;
+	union _REGS outregs;
+	struct _timeb now;
+	time_t time;
+
+	_ftime(&now);
+
+	#if 0
+		if (usecptr)
+			*usecptr = now.millitm * 1000;
+	#endif
+
+	/* Get time from AT hardware clock INT 0x1A, AH=2 */
+	memset(&inregs, 0, sizeof(inregs));
+	inregs.h.ah = 2;
+
+	_int86(0x1a, &inregs, &outregs);
+
+	/* 0x13 = decimal 13, hence the decoding below */
+	tm.tm_sec = 10 * ((outregs.h.dh & 0xF0) >> 4) + (outregs.h.dh & 0x0F);
+	tm.tm_min = 10 * ((outregs.h.cl & 0xF0) >> 4) + (outregs.h.cl & 0x0F);
+	tm.tm_hour = 10 * ((outregs.h.ch & 0xF0) >> 4) + (outregs.h.ch & 0x0F);
+
+	/* Get date from AT hardware clock INT 0x1A, AH=4 */
+	memset(&inregs, 0, sizeof(inregs));
+	inregs.h.ah = 4;
+
+	_int86(0x1a, &inregs, &outregs);
+
+	tm.tm_mday = 10 * ((outregs.h.dl & 0xF0) >> 4) + (outregs.h.dl & 0x0F);
+	tm.tm_mon = 10 * ((outregs.h.dh & 0xF0) >> 4) + (outregs.h.dh & 0x0F) - 1;
+	tm.tm_year = 10 * ((outregs.h.cl & 0xF0) >> 4) + (outregs.h.cl & 0x0F);
+	tm.tm_year += 100 * ((10 * (outregs.h.ch & 0xF0) >> 4)
+	            + (outregs.h.ch & 0x0F) - 19);
+
+    	tm.tm_wday = 0;
+	tm.tm_yday = 0;
+	tm.tm_isdst = now.dstflag;
+
+	time = mktime(&tm);
+
+	if (usecptr)
+		*usecptr = 0;
+
+	return time + CONVERT_TIME_EPOCH;
+}
+
+#endif
+
+/*
+ * This routine figures out the current time epoch and returns the
+ * conversion factor.  It exists because 
+ * Microloss screwed the pooch on the time() and _ftime() calls in
+ * its release 7.0 libraries.  They changed the epoch to Dec 31, 1899!
+ * Idiots...   We try to cope.
+ */
+
+static struct tm jan_1_70 = {0, 0, 0, 1, 0, 70};
+static long epoch = 0;
+static int epoch_set = 0;
+
+long
+win_time_get_epoch()
+{
+
+	if (!epoch_set) {
+		epoch = - mktime (&jan_1_70);	/* Seconds til 1970 localtime */
+		epoch += timezone;		/* Seconds til 1970 GMT */
+		epoch_set = 1;
+	}
+	return epoch;
+}
diff --git a/krb5-1-6/src/lib/krb4_32.def b/krb5-1-6/src/lib/krb4_32.def
new file mode 100644
index 000000000..11814cebd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb4_32.def
@@ -0,0 +1,86 @@
+;-----------------------------
+;   KRB4_32.DEF - module definition file
+;-----------------------------
+
+;LIBRARY		KRB4_32
+DESCRIPTION	'DLL for Kerberos support'
+HEAPSIZE	8192
+
+EXPORTS
+	dest_tkt
+	get_service_key
+	in_tkt
+	kname_parse
+	krb_check_auth
+	krb_get_admhst
+	krb_get_cred
+	krb_get_default_user
+	krb_get_err_text
+	krb_get_krbhst
+	krb_get_lrealm
+	krb_get_phost
+	krb_get_pw_in_tkt
+	krb_get_pw_in_tkt_preauth
+	krb_get_svc_in_tkt
+	krb_get_tf_fullname
+	krb_get_tf_realm
+	krb_get_ticket_for_service
+	krb_mk_auth
+	krb_mk_err
+	krb_mk_priv
+	krb_mk_req
+	krb_mk_safe
+	krb_rd_err
+	krb_rd_priv
+	krb_rd_req
+	krb_rd_safe
+	krb_realmofhost
+	krb_recvauth
+	krb_save_credentials
+	krb_set_default_user
+;	kuserok
+	put_svc_key
+	read_service_key
+;	kadm_change_pw2
+;	kadm_init_link
+;	kadm_get_err_text
+;	kadm_change_pw
+;	kstream_create_from_fd
+;	kstream_create_rlogin_from_fd
+;	kstream_create_rcp_from_fd
+;	kstream_write
+;	kstream_read
+;	kstream_flush
+;	kstream_destroy
+;	kstream_set_buffer_mode
+	krb_in_tkt
+
+; Added to match exports from KfM
+    krb_change_password
+    decomp_ticket
+    krb_err_txt
+    ;krb_ad_tkt
+    krb_get_in_tkt
+    krb_get_in_tkt_creds
+    krb_get_pw_in_tkt_creds
+    ;krb_pw_tkt
+    k_isrealm
+    k_isinst
+    k_isname
+    kname_unparse
+    ;kuserok
+    krb_set_lifetime
+    krb_rd_req_int
+    krb_sendauth
+    ;tkt_string
+    krb_set_tkt_string
+    krb_get_num_cred
+    krb_get_nth_cred
+    krb_delete_cred
+    dest_all_tkts
+    krb_get_profile 
+    ;FSp_krb_get_svc_in_tkt
+    ;FSp_put_svc_key
+    ;FSp_read_service_key
+    krb_time_to_life
+    krb_life_to_time
diff --git a/krb5-1-6/src/lib/krb5.rc b/krb5-1-6/src/lib/krb5.rc
new file mode 100644
index 000000000..f8e540024
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5.rc
@@ -0,0 +1,44 @@
+/*
+ * lib/krb5/os/win-pwd.h
+ *
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "win-mac.h"
+
+ID_READ_PWD_DIALOG DIALOG 60, 72, 200, 84
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU |
+	DS_SETFONT
+CAPTION "Kerberos Password/Challenge"
+FONT 8, "Helv"
+{
+  LTEXT "", ID_READ_PWD_PROMPT, 10, 8, 180, 10
+  LTEXT "", ID_READ_PWD_PROMPT2, 10, 24, 180, 10
+  EDITTEXT ID_READ_PWD_PWD, 10, 42, 180, 12, ES_AUTOHSCROLL | ES_PASSWORD |
+	WS_BORDER | WS_TABSTOP
+  DEFPUSHBUTTON "&OK", IDOK, 55, 61, 40, 14
+  PUSHBUTTON "&Cancel", IDCANCEL, 107, 61, 40, 14
+}
+
+#include "..\windows\version.rc"
diff --git a/krb5-1-6/src/lib/krb5/Makefile.in b/krb5-1-6/src/lib/krb5/Makefile.in
new file mode 100644
index 000000000..bb8e21d4b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/Makefile.in
@@ -0,0 +1,148 @@
+thisconfigdir=../..
+myfulldir=lib/krb5
+mydir=lib/krb5
+BUILDTOP=$(REL)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/ccache -I$(srcdir)/keytab -I$(srcdir)/rcache -I$(srcdir)/os
+LOCAL_SUBDIRS= error_tables asn.1 ccache keytab krb os rcache
+DEFS=
+
+##DOSBUILDTOP = ..\..
+##DOSLIBNAME=$(OUTPRE)krb5.lib
+##DOSOBJFILEDEP=$(OUTPRE)asn1.lst $(OUTPRE)ccache.lst $(OUTPRE)err_tbls.lst $(OUTPRE)keytab.lst $(OUTPRE)krb.lst $(OUTPRE)os.lst $(OUTPRE)posix.lst $(OUTPRE)rcache.lst $(OUTPRE)krb5.lst
+##DOSOBJFILELIST=@$(OUTPRE)asn1.lst @$(OUTPRE)ccache.lst @$(OUTPRE)err_tbls.lst @$(OUTPRE)keytab.lst @$(OUTPRE)krb.lst @$(OUTPRE)os.lst @$(OUTPRE)posix.lst @$(OUTPRE)rcache.lst @$(OUTPRE)krb5.lst
+##DOSOBJFILE=$(OUTPRE)krb5.lst
+##DOSLIBOBJS=$(OBJS)
+##DOSLOCALINCLUDES=-Iccache\ccapi -I..\..\windows\lib -Iccache -Ikeytab -Ircache -Ios
+
+TST=if test -n "`cat DONE`" ; then
+
+STLIBOBJS=krb5_libinit.o
+
+LIBBASE=krb5
+LIBMAJOR=3
+LIBMINOR=3
+LIBINITFUNC=profile_library_initializer krb5int_lib_init
+LIBFINIFUNC=profile_library_finalizer krb5int_lib_fini
+
+STOBJLISTS= \
+	OBJS.ST \
+	error_tables/OBJS.ST \
+	asn.1/OBJS.ST \
+	ccache/OBJS.ST \
+	keytab/OBJS.ST \
+	krb/OBJS.ST \
+	rcache/OBJS.ST \
+	os/OBJS.ST \
+	$(BUILDTOP)/util/profile/OBJS.ST
+
+SUBDIROBJLISTS= \
+	error_tables/OBJS.ST \
+	asn.1/OBJS.ST \
+	ccache/OBJS.ST \
+	keytab/OBJS.ST \
+	krb/OBJS.ST \
+	rcache/OBJS.ST \
+	os/OBJS.ST \
+	$(BUILDTOP)/util/profile/OBJS.ST
+
+OBJS=\
+	$(OUTPRE)krb5_libinit.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/krb5_libinit.c
+
+RELDIR=krb5
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+SHLIB_EXPLIBS=-lk5crypto -lcom_err $(SUPPORT_LIB) @GEN_LIB@ $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+all-unix:: all-liblinks
+
+all-windows::
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+clean-windows::
+	$(RM) $(OUTPRE)krb5.lib krb5.bak
+
+all-windows::
+	cd asn.1
+	@echo Making in krb5\asn.1
+	$(MAKE) -$(MFLAGS)
+	cd ..\ccache
+	@echo Making in krb5\ccache
+	$(MAKE) -$(MFLAGS)
+	cd ..\error_tables
+	@echo Making in krb5\error_tables
+	$(MAKE) -$(MFLAGS)
+	cd ..\keytab
+	@echo Making in krb5\keytab
+	$(MAKE) -$(MFLAGS)
+	cd ..\krb
+	@echo Making in krb5\krb
+	$(MAKE) -$(MFLAGS)
+	cd ..\os
+	@echo Making in krb5\os
+	$(MAKE) -$(MFLAGS)
+	cd ..\posix
+	@echo Making in krb5\posix
+	$(MAKE) -$(MFLAGS)
+	cd ..\rcache
+	@echo Making in krb5\rcache
+	$(MAKE) -$(MFLAGS)
+	cd ..
+
+clean-windows::
+	cd asn.1
+	@echo Making clean in krb5\asn.1
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\ccache
+	@echo Making clean in krb5\ccache
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\error_tables
+	@echo Making clean in krb5\error_tables
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\keytab
+	@echo Making clean in krb5\keytab
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\krb
+	@echo Making clean in krb5\krb
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\os
+	@echo Making clean in krb5\os
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\posix
+	@echo Making clean in krb5\posix
+	$(MAKE) -$(MFLAGS) clean
+	cd ..\rcache
+	@echo Making clean in krb5\rcache
+	$(MAKE) -$(MFLAGS) clean
+	cd ..
+	@echo Making clean locally
+
+install-unix:: install-libs
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+krb5_libinit.so krb5_libinit.po $(OUTPRE)krb5_libinit.$(OBJEXT): \
+  $(BUILDTOP)/include/asn1_err.h $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/kdb5_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/krb5_err.h $(BUILDTOP)/include/kv5m_err.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/ccache/cc-int.h \
+  $(srcdir)/keytab/kt-int.h $(srcdir)/os/os-proto.h $(srcdir)/rcache/rc-int.h \
+  krb5_libinit.c krb5_libinit.h
diff --git a/krb5-1-6/src/lib/krb5/asn.1/.saberinit b/krb5-1-6/src/lib/krb5/asn.1/.saberinit
new file mode 100644
index 000000000..d14fddb66
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/.saberinit
@@ -0,0 +1,4 @@
+alias hex print (unsigned)
+setopt load_flags -I../include
+load -lisode
+alias reload load
diff --git a/krb5-1-6/src/lib/krb5/asn.1/KRB5-asn.py b/krb5-1-6/src/lib/krb5/asn.1/KRB5-asn.py
new file mode 100644
index 000000000..e455fd9a1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/KRB5-asn.py
@@ -0,0 +1,436 @@
+-- lib/krb5/asn.1/KRB5-asn.py
+--
+-- Copyright 1989 by the Massachusetts Institute of Technology.
+--
+-- Export of this software from the United States of America may
+--   require a specific license from the United States Government.
+--   It is the responsibility of any person or organization contemplating
+--   export to obtain such a license before exporting.
+-- 
+-- WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+-- distribute this software and its documentation for any purpose and
+-- without fee is hereby granted, provided that the above copyright
+-- notice appear in all copies and that both that copyright notice and
+-- this permission notice appear in supporting documentation, and that
+-- the name of M.I.T. not be used in advertising or publicity pertaining
+-- to distribution of the software without specific, written prior
+-- permission.  Furthermore if you modify this software you must label
+-- your software as modified software and not distribute it in such a
+-- fashion that it might be confused with the original M.I.T. software.
+-- M.I.T. makes no representations about the suitability of
+-- this software for any purpose.  It is provided "as is" without express
+-- or implied warranty.
+--
+-- ASN.1 definitions for the kerberos network objects
+--
+-- Do not change the order of any structure containing some
+-- element_KRB5_xx unless the corresponding translation code is also
+-- changed.
+--
+
+KRB5 DEFINITIONS ::=
+BEGIN
+
+-- needed to do the Right Thing with pepsy; this isn't a valid ASN.1
+-- token, however.
+
+SECTIONS encode decode none
+
+-- the order of stuff in this file matches the order in the draft RFC
+
+Realm ::= GeneralString
+
+HostAddress ::= SEQUENCE  {
+	addr-type[0]			INTEGER,
+	address[1]			OCTET STRING
+}
+
+HostAddresses ::=	SEQUENCE OF SEQUENCE {
+	addr-type[0]	INTEGER,
+	address[1]	OCTET STRING
+}
+
+AuthorizationData ::=	SEQUENCE OF SEQUENCE {
+	ad-type[0]	INTEGER,
+	ad-data[1]	OCTET STRING
+}
+
+KDCOptions ::= BIT STRING {
+	reserved(0),
+	forwardable(1),
+	forwarded(2),
+	proxiable(3),
+	proxy(4),
+	allow-postdate(5),
+	postdated(6),
+	unused7(7),
+	renewable(8),
+	unused9(9),
+	renewable-ok(27),
+	enc-tkt-in-skey(28),
+	renew(30),
+	validate(31)
+}
+
+LastReq ::=	SEQUENCE OF SEQUENCE {
+	lr-type[0]	INTEGER,
+	lr-value[1]	KerberosTime
+}
+
+KerberosTime ::=	GeneralizedTime -- Specifying UTC time zone (Z)
+
+PrincipalName ::= SEQUENCE{
+	name-type[0]	INTEGER,
+	name-string[1]	SEQUENCE OF GeneralString
+}
+
+Ticket ::=	[APPLICATION 1] SEQUENCE {
+	tkt-vno[0]	INTEGER,
+	realm[1]	Realm,
+	sname[2]	PrincipalName,
+	enc-part[3]	EncryptedData	-- EncTicketPart
+}
+
+TransitedEncoding ::= SEQUENCE {
+	tr-type[0]	INTEGER, -- Only supported value is 1 == DOMAIN-COMPRESS
+	contents[1]	OCTET STRING
+}
+
+-- Encrypted part of ticket
+EncTicketPart ::=	[APPLICATION 3] SEQUENCE {
+	flags[0]	TicketFlags,
+	key[1]		EncryptionKey,
+	crealm[2]	Realm,
+	cname[3]	PrincipalName,
+	transited[4]	TransitedEncoding,
+	authtime[5]	KerberosTime,
+	starttime[6]	KerberosTime OPTIONAL,
+	endtime[7]	KerberosTime,
+	renew-till[8]	KerberosTime OPTIONAL,
+	caddr[9]	HostAddresses OPTIONAL,
+	authorization-data[10]	AuthorizationData OPTIONAL
+}
+
+-- Unencrypted authenticator
+Authenticator ::=	[APPLICATION 2] SEQUENCE  {
+	authenticator-vno[0]	INTEGER,
+	crealm[1]		Realm,
+	cname[2]		PrincipalName,
+	cksum[3]		Checksum OPTIONAL,
+	cusec[4]		INTEGER,
+	ctime[5]		KerberosTime,
+	subkey[6]		EncryptionKey OPTIONAL,
+	seq-number[7]		INTEGER OPTIONAL,
+	authorization-data[8]	AuthorizationData OPTIONAL
+}
+
+TicketFlags ::= BIT STRING {
+	reserved(0),
+	forwardable(1),
+	forwarded(2),
+	proxiable(3),
+	proxy(4),
+	may-postdate(5),
+	postdated(6),
+	invalid(7),
+	renewable(8),
+	initial(9)
+}
+
+AS-REQ ::= [APPLICATION 10] KDC-REQ
+TGS-REQ ::= [APPLICATION 12] KDC-REQ
+
+KDC-REQ ::= SEQUENCE {
+	pvno[1]		INTEGER,
+	msg-type[2]	INTEGER,
+	padata[3]	SEQUENCE OF PA-DATA OPTIONAL,
+	req-body[4]	KDC-REQ-BODY
+}
+
+PA-DATA ::= SEQUENCE {
+	padata-type[1]	INTEGER,
+	pa-data[2]	OCTET STRING -- might be encoded AP-REQ
+}
+
+KDC-REQ-BODY ::=	SEQUENCE {
+	 kdc-options[0]	KDCOptions,
+	 cname[1]	PrincipalName OPTIONAL, -- Used only in AS-REQ
+	 realm[2]	Realm, -- Server's realm  Also client's in AS-REQ
+	 sname[3]	PrincipalName OPTIONAL,
+	 from[4]	KerberosTime OPTIONAL,
+	 till[5]	KerberosTime,
+	 rtime[6]	KerberosTime OPTIONAL,
+	 nonce[7]	INTEGER,
+	 etype[8]	SEQUENCE OF INTEGER, -- EncryptionType, 
+			-- in preference order
+	 addresses[9]	HostAddresses OPTIONAL,
+	 enc-authorization-data[10]	EncryptedData OPTIONAL, 
+			-- AuthorizationData
+	 additional-tickets[11]	SEQUENCE OF Ticket OPTIONAL
+}
+
+AS-REP ::= [APPLICATION 11] KDC-REP
+TGS-REP ::= [APPLICATION 13] KDC-REP
+KDC-REP ::= SEQUENCE {
+	pvno[0]				INTEGER,
+	msg-type[1]			INTEGER,
+	padata[2]			SEQUENCE OF PA-DATA OPTIONAL,
+	crealm[3]			Realm,
+	cname[4]			PrincipalName,
+	ticket[5]			Ticket,		-- Ticket
+	enc-part[6]			EncryptedData	-- EncKDCRepPart
+}
+
+EncASRepPart ::= [APPLICATION 25] EncKDCRepPart
+EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
+EncKDCRepPart ::=  SEQUENCE {
+	key[0]		EncryptionKey,
+	last-req[1]	LastReq,
+	nonce[2]	INTEGER,
+	key-expiration[3]	KerberosTime OPTIONAL,
+	flags[4]	TicketFlags,
+	authtime[5]	KerberosTime,
+	starttime[6]	KerberosTime OPTIONAL,
+	endtime[7]	KerberosTime,
+	renew-till[8]	KerberosTime OPTIONAL,
+	srealm[9]	Realm,
+	sname[10]	PrincipalName,
+	caddr[11]	HostAddresses OPTIONAL
+}
+
+AP-REQ ::= [APPLICATION 14] SEQUENCE {
+	pvno[0]				INTEGER,
+	msg-type[1]			INTEGER,
+	ap-options[2]			APOptions,
+	ticket[3]			Ticket,
+	authenticator[4]		EncryptedData	-- Authenticator
+}
+
+APOptions ::= BIT STRING {
+	reserved(0),
+	use-session-key(1),
+	mutual-required(2)
+}
+
+AP-REP ::= [APPLICATION 15] SEQUENCE {
+	pvno[0]				INTEGER,
+	msg-type[1]			INTEGER,
+	enc-part[2]			EncryptedData	-- EncAPRepPart
+}
+
+EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
+	ctime[0]			KerberosTime,
+	cusec[1]			INTEGER,
+	subkey[2]			EncryptionKey OPTIONAL,
+	seq-number[3]			INTEGER OPTIONAL
+}
+
+KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
+	pvno[0]				INTEGER,
+	msg-type[1]			INTEGER,
+	safe-body[2]			KRB-SAFE-BODY,
+	cksum[3]			Checksum			
+}
+
+KRB-SAFE-BODY ::= SEQUENCE {
+	user-data[0]			OCTET STRING,
+	timestamp[1]			KerberosTime OPTIONAL,
+	usec[2]				INTEGER OPTIONAL,
+	seq-number[3]			INTEGER OPTIONAL,
+	s-address[4]			HostAddress,	-- sender's addr
+	r-address[5]			HostAddress OPTIONAL -- recip's addr 
+}
+
+KRB-PRIV ::=	[APPLICATION 21] SEQUENCE {
+	pvno[0]		INTEGER,
+	msg-type[1]	INTEGER,
+	enc-part[3]	EncryptedData	-- EncKrbPrivPart 
+}
+
+EncKrbPrivPart ::=	[APPLICATION 28] SEQUENCE {
+	user-data[0]	OCTET STRING,
+	timestamp[1]	KerberosTime OPTIONAL,
+	usec[2]		INTEGER OPTIONAL,
+	seq-number[3]	INTEGER OPTIONAL,
+	s-address[4]	HostAddress,	-- sender's addr
+	r-address[5]	HostAddress OPTIONAL	-- recip's addr 
+}
+
+-- The KRB-CRED message allows easy forwarding of credentials.
+
+KRB-CRED ::= [APPLICATION 22] SEQUENCE {
+	pvno[0]		INTEGER,
+	msg-type[1]	INTEGER, -- KRB_CRED
+	tickets[2]	SEQUENCE OF Ticket,
+	enc-part[3]	EncryptedData -- EncKrbCredPart 
+}
+
+EncKrbCredPart ::= [APPLICATION 29] SEQUENCE {
+	ticket-info[0] 	SEQUENCE OF KRB-CRED-INFO,	
+	nonce[1]	INTEGER OPTIONAL,
+	timestamp[2]	KerberosTime OPTIONAL,
+	usec[3]		INTEGER OPTIONAL,
+	s-address[4]	HostAddress OPTIONAL,
+	r-address[5]	HostAddress OPTIONAL
+}
+
+KRB-CRED-INFO	::=	SEQUENCE {
+	key[0]		EncryptionKey,
+        prealm[1] 	Realm OPTIONAL,
+        pname[2] 	PrincipalName OPTIONAL,
+        flags[3] 	TicketFlags OPTIONAL,
+        authtime[4] 	KerberosTime OPTIONAL,
+        starttime[5] 	KerberosTime OPTIONAL,
+        endtime[6] 	KerberosTime OPTIONAL,
+        renew-till[7] 	KerberosTime OPTIONAL,
+        srealm[8] 	Realm OPTIONAL,
+        sname[9] 	PrincipalName OPTIONAL,
+        caddr[10] 	HostAddresses OPTIONAL 
+}
+
+KRB-ERROR ::=	[APPLICATION 30] SEQUENCE {
+	pvno[0]		INTEGER,
+	msg-type[1]	INTEGER,
+	ctime[2]	KerberosTime OPTIONAL,
+	cusec[3]	INTEGER OPTIONAL,
+	stime[4]	KerberosTime,
+	susec[5]	INTEGER,
+	error-code[6]	INTEGER,
+	crealm[7]	Realm OPTIONAL,
+	cname[8]	PrincipalName OPTIONAL,
+	realm[9]	Realm, -- Correct realm
+	sname[10]	PrincipalName, -- Correct name
+	e-text[11]	GeneralString OPTIONAL,
+	e-data[12]	OCTET STRING OPTIONAL
+}
+
+EncryptedData ::=	SEQUENCE {
+	etype[0]	INTEGER, -- EncryptionType
+	kvno[1]		INTEGER OPTIONAL,
+	cipher[2]	OCTET STRING -- CipherText
+}
+
+EncryptionKey ::= SEQUENCE {
+	keytype[0]			INTEGER,
+	keyvalue[1]			OCTET STRING
+}
+
+Checksum ::= SEQUENCE {
+	cksumtype[0]			INTEGER,
+	checksum[1]			OCTET STRING
+}
+
+METHOD-DATA ::= SEQUENCE {
+	method-type[0]	INTEGER,
+	method-data[1]	OCTET STRING OPTIONAL
+}
+
+ETYPE-INFO-ENTRY ::= SEQUENCE {
+	etype[0]	INTEGER,
+	salt[1]		OCTET STRING OPTIONAL
+}
+
+ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY
+
+PA-ENC-TS-ENC   ::= SEQUENCE {
+       patimestamp[0]               KerberosTime, -- client's time
+       pausec[1]                    INTEGER OPTIONAL
+}
+
+-- These ASN.1 definitions are NOT part of the official Kerberos protocol... 
+
+-- New ASN.1 definitions for the kadmin protocol.
+-- Originally contributed from the Sandia modifications
+
+PasswdSequence ::= SEQUENCE {
+	passwd[0]			OCTET STRING,
+	phrase[1]			OCTET STRING
+}
+
+PasswdData ::= SEQUENCE {
+	passwd-sequence-count[0]	INTEGER,
+	passwd-sequence[1]		SEQUENCE OF PasswdSequence
+}
+
+-- encodings from 
+-- Integrating Single-use Authentication Mechanisms with Kerberos
+
+PA-SAM-CHALLENGE ::= SEQUENCE {
+    sam-type[0]                 INTEGER,
+    sam-flags[1]                SAMFlags,
+    sam-type-name[2]            GeneralString OPTIONAL,
+    sam-track-id[3]             GeneralString OPTIONAL,
+    sam-challenge-label[4]      GeneralString OPTIONAL,
+    sam-challenge[5]            GeneralString OPTIONAL,
+    sam-response-prompt[6]      GeneralString OPTIONAL,
+    sam-pk-for-sad[7]           OCTET STRING OPTIONAL,
+    sam-nonce[8]                INTEGER OPTIONAL,
+    sam-cksum[9]                Checksum OPTIONAL
+}
+
+PA-SAM-CHALLENGE-2 ::= SEQUENCE {
+    sam-body[0]                 PA-SAM-CHALLENGE-2-BODY,
+    sam-cksum[1]                SEQUENCE (1..MAX) OF Checksum,
+    ...
+}
+
+PA-SAM-CHALLENGE-2-BODY ::= SEQUENCE {
+    sam-type[0]                 INTEGER,
+    sam-flags[1]                SAMFlags,
+    sam-type-name[2]            GeneralString OPTIONAL,
+    sam-track-id[3]             GeneralString OPTIONAL,
+    sam-challenge-label[4]      GeneralString OPTIONAL,
+    sam-challenge[5]            GeneralString OPTIONAL,
+    sam-response-prompt[6]      GeneralString OPTIONAL,
+    sam-pk-for-sad[7]           EncryptionKey OPTIONAL,
+    sam-nonce[8]                INTEGER,
+    sam-etype[9]		INTEGER,
+    ...
+}
+
+-- these are [0].. [2] in the draft
+SAMFlags ::= BIT STRING (SIZE (32..MAX))
+    -- use-sad-as-key(0)
+    -- send-encrypted-sad(1)
+    -- must-pk-encrypt-sad(2)
+
+PA-SAM-RESPONSE ::= SEQUENCE {
+    sam-type[0]                 INTEGER,
+    sam-flags[1]                SAMFlags,
+    sam-track-id[2]             GeneralString OPTIONAL,
+    -- sam-enc-key is reserved for future use, so I'm making it OPTIONAL - mwe
+    sam-enc-key[3]              EncryptedData,
+                                   -- PA-ENC-SAM-KEY
+    sam-enc-nonce-or-ts[4]      EncryptedData,
+                                   -- PA-ENC-SAM-RESPONSE-ENC
+    sam-nonce[5]                INTEGER OPTIONAL,
+    sam-patimestamp[6]          KerberosTime OPTIONAL
+}
+
+PA-SAM-RESPONSE-2 ::= SEQUENCE {
+    sam-type[0]                 INTEGER,
+    sam-flags[1]                SAMFlags,
+    sam-track-id[2]             GeneralString OPTIONAL,
+    sam-enc-nonce-or-sad[3]     EncryptedData,
+                                   -- PA-ENC-SAM-RESPONSE-ENC
+    sam-nonce[4]                INTEGER,
+    ...
+}
+
+PA-ENC-SAM-KEY ::= SEQUENCE {
+             sam-key[0]                 EncryptionKey
+}
+
+PA-ENC-SAM-RESPONSE-ENC ::= SEQUENCE {
+     sam-nonce[0]               INTEGER OPTIONAL,
+     sam-timestamp[1]           KerberosTime OPTIONAL,
+     sam-usec[2]                INTEGER OPTIONAL,
+     sam-passcode[3]            GeneralString OPTIONAL
+}
+
+PA-ENC-SAM-RESPONSE-ENC-2 ::= SEQUENCE {
+     sam-nonce[0]               INTEGER,
+     sam-sad[1]                 GeneralString OPTIONAL,
+     ...
+}
+END
diff --git a/krb5-1-6/src/lib/krb5/asn.1/Makefile.in b/krb5-1-6/src/lib/krb5/asn.1/Makefile.in
new file mode 100644
index 000000000..2b29cdcf8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/Makefile.in
@@ -0,0 +1,174 @@
+thisconfigdir=../../..
+myfulldir=lib/krb5/asn.1
+mydir=lib/krb5/asn.1
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=asn.1
+##DOS##OBJFILE=..\$(OUTPRE)asn1.lst
+
+EHDRDIR=$(BUILDTOP)/include/krb5/asn.1
+
+STLIBOBJS= \
+	asn1_decode.o\
+	asn1_k_decode.o\
+	asn1_encode.o\
+	asn1_get.o\
+	asn1_make.o\
+	asn1buf.o\
+	krb5_decode.o\
+	krb5_encode.o\
+	asn1_k_encode.o\
+	ldap_key_seq.o\
+	asn1_misc.o
+
+SRCS= \
+	$(srcdir)/asn1_decode.c\
+	$(srcdir)/asn1_k_decode.c\
+	$(srcdir)/asn1_encode.c\
+	$(srcdir)/asn1_get.c\
+	$(srcdir)/asn1_make.c\
+	$(srcdir)/asn1buf.c\
+	$(srcdir)/krb5_decode.c\
+	$(srcdir)/krb5_encode.c\
+	$(srcdir)/asn1_k_encode.c\
+	$(srcdir)/ldap_key_seq.c\
+	$(srcdir)/asn1_misc.c
+
+OBJS= \
+	$(OUTPRE)asn1_decode.$(OBJEXT)\
+	$(OUTPRE)asn1_k_decode.$(OBJEXT)\
+	$(OUTPRE)asn1_encode.$(OBJEXT)\
+	$(OUTPRE)asn1_get.$(OBJEXT)\
+	$(OUTPRE)asn1_make.$(OBJEXT)\
+	$(OUTPRE)asn1buf.$(OBJEXT)\
+	$(OUTPRE)krb5_decode.$(OBJEXT)\
+	$(OUTPRE)krb5_encode.$(OBJEXT)\
+	$(OUTPRE)asn1_k_encode.$(OBJEXT)\
+	$(OUTPRE)ldap_key_seq.$(OBJEXT)\
+	$(OUTPRE)asn1_misc.$(OBJEXT)
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+asn1_decode.so asn1_decode.po $(OUTPRE)asn1_decode.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_decode.c asn1_decode.h \
+  asn1_get.h asn1buf.h krbasn1.h
+asn1_k_decode.so asn1_k_decode.po $(OUTPRE)asn1_k_decode.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_decode.h asn1_get.h \
+  asn1_k_decode.c asn1_k_decode.h asn1_misc.h asn1buf.h \
+  krbasn1.h
+asn1_encode.so asn1_encode.po $(OUTPRE)asn1_encode.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_encode.c asn1_encode.h \
+  asn1_make.h asn1buf.h krbasn1.h
+asn1_get.so asn1_get.po $(OUTPRE)asn1_get.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_get.c asn1_get.h \
+  asn1buf.h krbasn1.h
+asn1_make.so asn1_make.po $(OUTPRE)asn1_make.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_make.c asn1_make.h \
+  asn1buf.h krbasn1.h
+asn1buf.so asn1buf.po $(OUTPRE)asn1buf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  asn1_get.h asn1buf.c asn1buf.h krbasn1.h
+krb5_decode.so krb5_decode.po $(OUTPRE)krb5_decode.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_decode.h asn1_get.h \
+  asn1_k_decode.h asn1buf.h krb5_decode.c krbasn1.h
+krb5_encode.so krb5_encode.po $(OUTPRE)krb5_encode.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_encode.h asn1_k_encode.h \
+  asn1_make.h asn1buf.h krb5_encode.c krbasn1.h
+asn1_k_encode.so asn1_k_encode.po $(OUTPRE)asn1_k_encode.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_encode.h asn1_k_encode.c \
+  asn1_k_encode.h asn1_make.h asn1buf.h krbasn1.h
+ldap_key_seq.so ldap_key_seq.po $(OUTPRE)ldap_key_seq.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_decode.h asn1_encode.h \
+  asn1_get.h asn1_make.h asn1buf.h krbasn1.h ldap_key_seq.c
+asn1_misc.so asn1_misc.po $(OUTPRE)asn1_misc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h asn1_misc.c asn1_misc.h \
+  krbasn1.h
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_decode.c b/krb5-1-6/src/lib/krb5/asn.1/asn1_decode.c
new file mode 100644
index 000000000..aa4be3263
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_decode.c
@@ -0,0 +1,261 @@
+/*
+ * src/lib/krb5/asn.1/asn1_decode.c
+ * 
+ * Copyright 1994, 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* ASN.1 primitive decoders */
+#include "asn1_decode.h"
+#include "asn1_get.h"
+#include <stdio.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#include <time.h>
+#endif
+
+#define setup()\
+asn1_error_code retval;\
+taginfo tinfo
+
+#define asn1class	(tinfo.asn1class)
+#define construction	(tinfo.construction)
+#define tagnum		(tinfo.tagnum)
+#define length		(tinfo.length)
+
+#define tag(type)\
+retval = asn1_get_tag_2(buf,&tinfo);\
+if(retval) return retval;\
+if(asn1class != UNIVERSAL || construction != PRIMITIVE || tagnum != type)\
+  return ASN1_BAD_ID
+  
+#define cleanup()\
+return 0
+
+extern time_t krb5int_gmt_mktime (struct tm *);
+
+asn1_error_code asn1_decode_integer(asn1buf *buf, long int *val)
+{
+  setup();
+  asn1_octet o;
+  long n = 0; /* initialize to keep gcc happy */
+  int i;
+
+  tag(ASN1_INTEGER);
+
+  for (i = 0; i < length; i++) {
+    retval = asn1buf_remove_octet(buf, &o);
+    if (retval) return retval;
+    if (!i) {
+      n = (0x80 & o) ? -1 : 0;	/* grab sign bit */
+      if (n < 0 && length > sizeof (long))
+	return ASN1_OVERFLOW;
+      else if (length > sizeof (long) + 1) /* allow extra octet for positive */
+	return ASN1_OVERFLOW;
+    }
+    n = (n << 8) | o;
+  }
+  *val = n;
+  cleanup();
+}
+
+asn1_error_code asn1_decode_unsigned_integer(asn1buf *buf, long unsigned int *val)
+{
+  setup();
+  asn1_octet o;
+  unsigned long n;
+  int i;
+
+  tag(ASN1_INTEGER);
+
+  for (i = 0, n = 0; i < length; i++) {
+    retval = asn1buf_remove_octet(buf, &o);
+    if(retval) return retval;
+    if (!i) {
+      if (0x80 & o)
+	return ASN1_OVERFLOW;
+      else if (length > sizeof (long) + 1)
+	return ASN1_OVERFLOW;
+    }
+    n = (n << 8) | o;
+  }
+  *val = n;
+  cleanup();
+}
+
+/*
+ * asn1_decode_maybe_unsigned
+ *
+ * This is needed because older releases of MIT krb5 have signed
+ * sequence numbers.  We want to accept both signed and unsigned
+ * sequence numbers, in the range -2^31..2^32-1, mapping negative
+ * numbers into their positive equivalents in the same way that C's
+ * normal integer conversions do, i.e., would preserve bits on a
+ * two's-complement architecture.
+ */
+asn1_error_code asn1_decode_maybe_unsigned(asn1buf *buf, unsigned long *val)
+{
+  setup();
+  asn1_octet o;
+  unsigned long n, bitsremain;
+  unsigned int i;
+
+  tag(ASN1_INTEGER);
+  o = 0;
+  n = 0;
+  bitsremain = ~0UL;
+  for (i = 0; i < length; i++) {
+    /* Accounts for u_long width not being a multiple of 8. */
+    if (bitsremain < 0xff) return ASN1_OVERFLOW;
+    retval = asn1buf_remove_octet(buf, &o);
+    if (retval) return retval;
+    if (bitsremain == ~0UL) {
+      if (i == 0)
+	n = (o & 0x80) ? ~0UL : 0UL; /* grab sign bit */
+      /*
+       * Skip leading zero or 0xFF octets to humor non-compliant encoders.
+       */
+      if (n == 0 && o == 0)
+	continue;
+      if (n == ~0UL && o == 0xff)
+	continue;
+    }
+    n = (n << 8) | o;
+    bitsremain >>= 8;
+  }
+  *val = n;
+  cleanup();
+}
+
+asn1_error_code asn1_decode_oid(asn1buf *buf, unsigned int *retlen, asn1_octet **val)
+{
+  setup();
+  tag(ASN1_OBJECTIDENTIFIER);
+  retval = asn1buf_remove_octetstring(buf, length, val);
+  if (retval) return retval;
+  *retlen = length;
+  cleanup();
+}
+
+asn1_error_code asn1_decode_octetstring(asn1buf *buf, unsigned int *retlen, asn1_octet **val)
+{
+  setup();
+  tag(ASN1_OCTETSTRING);
+  retval = asn1buf_remove_octetstring(buf,length,val);
+  if(retval) return retval;
+  *retlen = length;
+  cleanup();
+}
+
+asn1_error_code asn1_decode_charstring(asn1buf *buf, unsigned int *retlen, char **val)
+{
+  setup();
+  tag(ASN1_OCTETSTRING);
+  retval = asn1buf_remove_charstring(buf,length,val);
+  if(retval) return retval;
+  *retlen = length;
+  cleanup();
+}
+
+
+asn1_error_code asn1_decode_generalstring(asn1buf *buf, unsigned int *retlen, char **val)
+{
+  setup();
+  tag(ASN1_GENERALSTRING);
+  retval = asn1buf_remove_charstring(buf,length,val);
+  if(retval) return retval;
+  *retlen = length;
+  cleanup();
+}
+
+
+asn1_error_code asn1_decode_null(asn1buf *buf)
+{
+  setup();
+  tag(ASN1_NULL);
+  if(length != 0) return ASN1_BAD_LENGTH;
+  cleanup();
+}
+
+asn1_error_code asn1_decode_printablestring(asn1buf *buf, int *retlen, char **val)
+{
+  setup();
+  tag(ASN1_PRINTABLESTRING);
+  retval = asn1buf_remove_charstring(buf,length,val);
+  if(retval) return retval;
+  *retlen = length;
+  cleanup();
+}
+
+asn1_error_code asn1_decode_ia5string(asn1buf *buf, int *retlen, char **val)
+{
+  setup();
+  tag(ASN1_IA5STRING);
+  retval = asn1buf_remove_charstring(buf,length,val);
+  if(retval) return retval;
+  *retlen = length;
+  cleanup();
+}
+
+asn1_error_code asn1_decode_generaltime(asn1buf *buf, time_t *val)
+{
+  setup();
+  char *s;
+  struct tm ts;
+  time_t t;
+
+  tag(ASN1_GENERALTIME);
+
+  if(length != 15) return ASN1_BAD_LENGTH;
+  retval = asn1buf_remove_charstring(buf,15,&s);
+  /* Time encoding: YYYYMMDDhhmmssZ */
+  if(s[14] != 'Z') {
+      free(s);
+      return ASN1_BAD_FORMAT;
+  }
+  if(s[0] == '1' && !memcmp("19700101000000Z", s, 15)) {
+      t = 0;
+      free(s);
+      goto done;
+  }
+#define c2i(c) ((c)-'0')
+  ts.tm_year = 1000*c2i(s[0]) + 100*c2i(s[1]) + 10*c2i(s[2]) + c2i(s[3])
+    - 1900;
+  ts.tm_mon = 10*c2i(s[4]) + c2i(s[5]) - 1;
+  ts.tm_mday = 10*c2i(s[6]) + c2i(s[7]);
+  ts.tm_hour = 10*c2i(s[8]) + c2i(s[9]);
+  ts.tm_min = 10*c2i(s[10]) + c2i(s[11]);
+  ts.tm_sec = 10*c2i(s[12]) + c2i(s[13]);
+  ts.tm_isdst = -1;
+  t = krb5int_gmt_mktime(&ts);
+  free(s);
+
+  if(t == -1) return ASN1_BAD_TIMEFORMAT;
+
+done:
+  *val = t;
+  cleanup();
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_decode.h b/krb5-1-6/src/lib/krb5/asn.1/asn1_decode.h
new file mode 100644
index 000000000..cafbf3fd3
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_decode.h
@@ -0,0 +1,92 @@
+/*
+ * src/lib/krb5/asn.1/asn1_decode.h
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __ASN1_DECODE_H__
+#define __ASN1_DECODE_H__
+
+#include "k5-int.h"
+#include "krbasn1.h"
+#include "asn1buf.h"
+
+/*
+   Overview
+
+     These procedures take an asn1buf whose current position points
+     to the beginning of an ASN.1 primitive (<id><length><contents>).
+     The primitive is removed from the buffer and decoded.
+
+   Operations
+
+    asn1_decode_integer
+    asn1_decode_unsigned_integer
+    asn1_decode_octetstring
+    asn1_decode_charstring
+    asn1_decode_generalstring
+    asn1_decode_null
+    asn1_decode_printablestring
+    asn1_decode_ia5string
+    asn1_decode_generaltime
+*/
+
+/* asn1_error_code asn1_decode_type(asn1buf *buf, ctype *val); */
+/* requires  *buf is allocated
+   modifies  *buf, *len
+   effects   Decodes the octet string in *buf into *val.
+             Returns ENOMEM if memory is exhausted.
+	     Returns asn1 errors. */
+
+asn1_error_code asn1_decode_integer
+	(asn1buf *buf, long *val);
+asn1_error_code asn1_decode_unsigned_integer
+	(asn1buf *buf, unsigned long *val);
+asn1_error_code asn1_decode_maybe_unsigned
+	(asn1buf *buf, unsigned long *val);
+asn1_error_code asn1_decode_null
+	(asn1buf *buf);
+
+asn1_error_code asn1_decode_oid
+	(asn1buf *buf, unsigned int *retlen, asn1_octet **val);
+asn1_error_code asn1_decode_octetstring
+	(asn1buf *buf, unsigned int *retlen, asn1_octet **val);
+asn1_error_code asn1_decode_generalstring
+	(asn1buf *buf, unsigned int *retlen, char **val);
+asn1_error_code asn1_decode_charstring
+	(asn1buf *buf, unsigned int *retlen, char **val);
+/* Note: A charstring is a special hack to account for the fact that
+         krb5 structures store some OCTET STRING values in krb5_octet
+	 arrays and others in krb5_data structures 
+	 (which use char arrays).
+	 From the ASN.1 point of view, the two string types are the same,
+	 only the receptacles differ. */
+asn1_error_code asn1_decode_printablestring
+	(asn1buf *buf, int *retlen, char **val);
+asn1_error_code asn1_decode_ia5string
+	(asn1buf *buf, int *retlen, char **val);
+
+asn1_error_code asn1_decode_generaltime
+	(asn1buf *buf, time_t *val);
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_encode.c b/krb5-1-6/src/lib/krb5/asn.1/asn1_encode.c
new file mode 100644
index 000000000..c5e3452b8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_encode.c
@@ -0,0 +1,297 @@
+/*
+ * src/lib/krb5/asn.1/asn1_encode.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* ASN.1 primitive encoders */
+
+#include "asn1_encode.h"
+#include "asn1_make.h"
+
+static asn1_error_code asn1_encode_integer_internal(asn1buf *buf,  long val,
+						    unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length = 0;
+  long valcopy;
+  int digit;
+  
+  valcopy = val;
+  do {
+    digit = (int) (valcopy&0xFF);
+    retval = asn1buf_insert_octet(buf,(asn1_octet) digit);
+    if(retval) return retval;
+    length++;
+    valcopy = valcopy >> 8;
+  } while (valcopy != 0 && valcopy != ~0);
+
+  if((val > 0) && ((digit&0x80) == 0x80)) { /* make sure the high bit is */
+    retval = asn1buf_insert_octet(buf,0); /* of the proper signed-ness */
+    if(retval) return retval;
+    length++;
+  }else if((val < 0) && ((digit&0x80) != 0x80)){
+    retval = asn1buf_insert_octet(buf,0xFF);
+    if(retval) return retval;
+    length++;
+  }
+
+
+  *retlen = length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_integer(asn1buf * buf,  long val,
+ unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length = 0;
+  unsigned  int partlen;
+  retval = asn1_encode_integer_internal(buf, val, &partlen);
+  if (retval) return retval;
+
+  length = partlen;
+    retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen); 
+  if(retval) return retval;
+  length += partlen;
+
+  *retlen = length;
+  return 0;
+}
+
+asn1_error_code
+asn1_encode_enumerated(asn1buf * buf, long val,
+		       unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length = 0;
+  unsigned  int partlen;
+  retval = asn1_encode_integer_internal(buf, val, &partlen);
+  if (retval) return retval;
+
+  length = partlen;
+    retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_ENUMERATED,length, &partlen); 
+  if(retval) return retval;
+  length += partlen;
+
+  *retlen = length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, unsigned long val,
+					     unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length = 0;
+  unsigned int partlen;
+  unsigned long valcopy;
+  int digit;
+  
+  valcopy = val;
+  do {
+    digit = (int) (valcopy&0xFF);
+    retval = asn1buf_insert_octet(buf,(asn1_octet) digit);
+    if(retval) return retval;
+    length++;
+    valcopy = valcopy >> 8;
+  } while (valcopy != 0 && valcopy != ~0);
+
+  if(digit&0x80) {		          /* make sure the high bit is */
+    retval = asn1buf_insert_octet(buf,0); /* of the proper signed-ness */
+    if(retval) return retval;
+    length++;
+  }
+
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen); 
+  if(retval) return retval;
+  length += partlen;
+
+  *retlen = length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_oid(asn1buf *buf, unsigned int len,
+				const asn1_octet *val,
+				unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length;
+
+  retval = asn1buf_insert_octetstring(buf, len, val);
+  if (retval) return retval;
+  retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_OBJECTIDENTIFIER,
+			 len, &length);
+  if (retval) return retval;
+
+  *retlen = len + length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_octetstring(asn1buf *buf, unsigned int len,
+					const asn1_octet *val,
+					unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length;
+
+  retval = asn1buf_insert_octetstring(buf,len,val);
+  if(retval) return retval;
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_OCTETSTRING,len,&length);
+  if(retval) return retval;
+
+  *retlen = len + length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_charstring(asn1buf *buf, unsigned int len,
+				       const char *val, unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length;
+
+  retval = asn1buf_insert_charstring(buf,len,val);
+  if(retval) return retval;
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_OCTETSTRING,len,&length);
+  if(retval) return retval;
+
+  *retlen = len + length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen)
+{
+  asn1_error_code retval;
+  
+  retval = asn1buf_insert_octet(buf,0x00);
+  if(retval) return retval;
+  retval = asn1buf_insert_octet(buf,0x05);
+  if(retval) return retval;
+
+  *retlen = 2;
+  return 0;
+}
+
+asn1_error_code asn1_encode_printablestring(asn1buf *buf, unsigned int len,
+					    const char *val, int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length;
+
+  retval = asn1buf_insert_charstring(buf,len,val);
+  if(retval) return retval;
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_PRINTABLESTRING,len,			 &length);
+  if(retval) return retval;
+
+  *retlen = len + length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len,
+				      const char *val, int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length;
+
+  retval = asn1buf_insert_charstring(buf,len,val);
+  if(retval) return retval;
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_IA5STRING,len,			 &length);
+  if(retval) return retval;
+
+  *retlen = len + length;
+  return 0;
+}
+
+asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val,
+					unsigned int *retlen)
+{
+  asn1_error_code retval;
+  struct tm *gtime, gtimebuf;
+  char s[16], *sp;
+  unsigned int length, sum=0;
+  time_t gmt_time = val;
+
+  /*
+   * Time encoding: YYYYMMDDhhmmssZ
+   */
+  if (gmt_time == 0) {
+      sp = "19700101000000Z";
+  } else {
+
+      /*
+       * Sanity check this just to be paranoid, as gmtime can return NULL,
+       * and some bogus implementations might overrun on the sprintf.
+       */
+#ifdef HAVE_GMTIME_R
+# ifdef GMTIME_R_RETURNS_INT
+      if (gmtime_r(&gmt_time, >imebuf) != 0)
+	  return ASN1_BAD_GMTIME;
+# else
+      if (gmtime_r(&gmt_time, >imebuf) == NULL)
+	  return ASN1_BAD_GMTIME;
+# endif
+#else
+      gtime = gmtime(&gmt_time);
+      if (gtime == NULL)
+	  return ASN1_BAD_GMTIME;
+      memcpy(>imebuf, gtime, sizeof(gtimebuf));
+#endif
+      gtime = >imebuf;
+
+      if (gtime->tm_year > 8099 || gtime->tm_mon > 11 ||
+	  gtime->tm_mday > 31 || gtime->tm_hour > 23 ||
+	  gtime->tm_min > 59 || gtime->tm_sec > 59)
+	  return ASN1_BAD_GMTIME;
+      sprintf(s, "%04d%02d%02d%02d%02d%02dZ",
+	      1900+gtime->tm_year, gtime->tm_mon+1, gtime->tm_mday,
+	      gtime->tm_hour, gtime->tm_min, gtime->tm_sec);
+      sp = s;
+  }
+
+  retval = asn1buf_insert_charstring(buf,15,sp);
+  if(retval) return retval;
+  sum = 15;
+
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_GENERALTIME,sum,&length);
+  if(retval) return retval;
+  sum += length;
+
+  *retlen = sum;
+  return 0;
+}
+
+asn1_error_code asn1_encode_generalstring(asn1buf *buf, unsigned int len,
+					  const char *val,
+					  unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int length;
+
+  retval = asn1buf_insert_charstring(buf,len,val);
+  if(retval) return retval;
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_GENERALSTRING,len,
+			 &length);
+  if(retval) return retval;
+
+  *retlen = len + length;
+  return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_encode.h b/krb5-1-6/src/lib/krb5/asn.1/asn1_encode.h
new file mode 100644
index 000000000..79eee48d5
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_encode.h
@@ -0,0 +1,159 @@
+/*
+ * src/lib/krb5/asn.1/asn1_encode.h
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __ASN1_ENCODE_H__
+#define __ASN1_ENCODE_H__
+
+#include "k5-int.h"
+#include "krbasn1.h"
+#include "asn1buf.h"
+#include <time.h>
+
+/*
+   Overview
+
+     Each of these procedures inserts the encoding of an ASN.1
+     primitive in a coding buffer.
+
+   Operations
+
+     asn1_encode_integer
+     asn1_encode_octetstring
+     asn1_encode_null
+     asn1_encode_printablestring
+     asn1_encode_ia5string
+     asn1_encode_generaltime
+     asn1_encode_generalstring
+*/
+
+asn1_error_code asn1_encode_integer
+	(asn1buf *buf, long val, unsigned int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_enumerated
+(asn1buf *buf, long val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_unsigned_integer
+	(asn1buf *buf, unsigned long val, 
+		   unsigned int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_octetstring
+	(asn1buf *buf,
+		   unsigned int len, const asn1_octet *val,
+		   unsigned int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_oid
+	(asn1buf *buf,
+		   unsigned int len, const asn1_octet *val,
+		   unsigned int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_charstring
+	(asn1buf *buf,
+		   unsigned int len, const char *val,
+		   unsigned int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_null
+	(asn1buf *buf, int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of NULL into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_printablestring
+	(asn1buf *buf,
+		   unsigned int len, const char *val,
+		   int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_ia5string
+	(asn1buf *buf,
+		   unsigned int len, const char *val,
+		   int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+asn1_error_code asn1_encode_generaltime
+	(asn1buf *buf, time_t val, unsigned int *retlen);
+/* requires  *buf is allocated
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer.
+   Note: The encoding of GeneralizedTime is YYYYMMDDhhmmZ */
+
+asn1_error_code asn1_encode_generalstring
+	(asn1buf *buf,
+		   unsigned int len, const char *val,
+		   unsigned int *retlen);
+/* requires  *buf is allocated,  val has a length of len characters
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of val into *buf and returns 
+              the length of the encoding in *retlen.
+             Returns ENOMEM to signal an unsuccesful attempt
+              to expand the buffer. */
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_get.c b/krb5-1-6/src/lib/krb5/asn.1/asn1_get.c
new file mode 100644
index 000000000..8da5fd880
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_get.c
@@ -0,0 +1,118 @@
+/*
+ * src/lib/krb5/asn.1/asn1_get.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "asn1_get.h"
+
+asn1_error_code
+asn1_get_tag_2(asn1buf *buf, taginfo *t)
+{
+    asn1_error_code retval;
+
+    if (buf == NULL || buf->base == NULL ||
+	buf->bound - buf->next + 1 <= 0) {
+	t->tagnum = ASN1_TAGNUM_CEILING; /* emphatically not an EOC tag */
+	t->asn1class = UNIVERSAL;
+	t->construction = PRIMITIVE;
+	t->length = 0;
+	t->indef = 0;
+	return 0;
+    }
+    {
+	/* asn1_get_id(buf, t) */
+	asn1_tagnum tn=0;
+	asn1_octet o;
+
+#define ASN1_CLASS_MASK 0xC0
+#define ASN1_CONSTRUCTION_MASK 0x20
+#define ASN1_TAG_NUMBER_MASK 0x1F
+
+	retval = asn1buf_remove_octet(buf,&o);
+	if (retval)
+	    return retval;
+
+	t->asn1class = (asn1_class)(o&ASN1_CLASS_MASK);
+	t->construction = (asn1_construction)(o&ASN1_CONSTRUCTION_MASK);
+	if ((o&ASN1_TAG_NUMBER_MASK) != ASN1_TAG_NUMBER_MASK){
+	    /* low-tag-number form */
+	    t->tagnum = (asn1_tagnum)(o&ASN1_TAG_NUMBER_MASK);
+	} else {
+	    /* high-tag-number form */
+	    do {
+		retval = asn1buf_remove_octet(buf,&o);
+		if (retval) return retval;
+		tn = (tn<<7) + (asn1_tagnum)(o&0x7F);
+	    }while(o&0x80);
+	    t->tagnum = tn;
+	}
+    }
+
+    {
+	/* asn1_get_length(buf, t) */
+	asn1_octet o;
+
+	t->indef = 0;
+	retval = asn1buf_remove_octet(buf,&o);
+	if (retval) return retval;
+	if ((o&0x80) == 0) {
+	    t->length = (int)(o&0x7F);
+	} else {
+	    int num;
+	    int len=0;
+    
+	    for (num = (int)(o&0x7F); num>0; num--) {
+		retval = asn1buf_remove_octet(buf,&o);
+		if(retval) return retval;
+		len = (len<<8) + (int)o;
+	    }
+	    if (len < 0)
+		return ASN1_OVERRUN;
+	    if (!len)
+		t->indef = 1;
+	    t->length = len;
+	}
+    }
+    if (t->indef && t->construction != CONSTRUCTED)
+	return ASN1_MISMATCH_INDEF;
+    return 0;
+}
+
+asn1_error_code asn1_get_sequence(asn1buf *buf, unsigned int *retlen, int *indef)
+{
+    taginfo t;
+    asn1_error_code retval;
+
+    retval = asn1_get_tag_2(buf, &t);
+    if (retval)
+	return retval;
+    if (t.asn1class != UNIVERSAL || t.construction != CONSTRUCTED ||
+	t.tagnum != ASN1_SEQUENCE)
+	return ASN1_BAD_ID;
+    if (retlen)
+	*retlen = t.length;
+    if (indef)
+	*indef = t.indef;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_get.h b/krb5-1-6/src/lib/krb5/asn.1/asn1_get.h
new file mode 100644
index 000000000..50a1b75ce
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_get.h
@@ -0,0 +1,77 @@
+/*
+ * src/lib/krb5/asn.1/asn1_get.h
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __ASN1_GET_H__
+#define __ASN1_GET_H__
+
+/* ASN.1 substructure decoding procedures */
+
+#include "k5-int.h"
+#include "krbasn1.h"
+#include "asn1buf.h"
+
+typedef struct {
+    asn1_class asn1class;
+    asn1_construction construction;
+    asn1_tagnum tagnum;
+    unsigned int length;
+    int indef;
+} taginfo;
+
+asn1_error_code asn1_get_tag_2 (asn1buf *buf, taginfo *tinfo);
+
+#if 0
+asn1_error_code asn1_get_tag_indef
+	(asn1buf *buf,
+		   asn1_class *Class,
+		   asn1_construction *construction,
+		   asn1_tagnum *tagnum,
+		   unsigned int *retlen, int *indef);
+
+asn1_error_code asn1_get_tag
+	(asn1buf *buf,
+		   asn1_class *Class,
+		   asn1_construction *construction,
+		   asn1_tagnum *tagnum,
+		   unsigned int *retlen);
+/* requires  *buf is allocated
+   effects   Decodes the tag in *buf.  If class != NULL, returns
+              the class in *Class.  Similarly, the construction,
+	      tag number, and length are returned in *construction,
+	      *tagnum, and *retlen, respectively.
+	     If *buf is empty to begin with,
+	      *tagnum is set to ASN1_TAGNUM_CEILING.
+	     Returns ASN1_OVERRUN if *buf is exhausted during the parse. */
+#endif
+
+asn1_error_code asn1_get_sequence
+	(asn1buf *buf, unsigned int *retlen, int *indef);
+/* requires  *buf is allocated
+   effects   Decodes a tag from *buf and returns ASN1_BAD_ID if it
+              doesn't have a sequence ID.  If retlen != NULL, the
+	      associated length is returned in *retlen. */
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.c b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.c
new file mode 100644
index 000000000..4b581e35e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.c
@@ -0,0 +1,1566 @@
+/*
+ * src/lib/krb5/asn.1/asn1_k_decode.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "asn1_k_decode.h"
+#include "asn1_decode.h"
+#include "asn1_get.h"
+#include "asn1_misc.h"
+
+/* Declare useful decoder variables. */
+#define setup()					\
+  asn1_error_code retval;			\
+  asn1_class asn1class;				\
+  asn1_construction construction;		\
+  asn1_tagnum tagnum;				\
+  unsigned int length, taglen
+
+#define unused_var(x) if (0) { x = 0; x = x - x; }
+
+/* This is used for prefetch of next tag in sequence. */
+#define next_tag()								\
+{ taginfo t2;									\
+  retval = asn1_get_tag_2(&subbuf, &t2);					\
+  if (retval) return retval;							\
+  /* Copy out to match previous functionality, until better integrated.  */	\
+  asn1class = t2.asn1class;							\
+  construction = t2.construction;						\
+  tagnum = t2.tagnum;								\
+  taglen = t2.length;								\
+  indef = t2.indef;								\
+}
+
+/* Force check for EOC tag. */
+#define get_eoc()									\
+    {											\
+	taginfo t3;									\
+	retval = asn1_get_tag_2(&subbuf, &t3);						\
+	if(retval) return retval;							\
+        if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)				\
+	    return ASN1_MISSING_EOC;							\
+        /* Copy out to match previous functionality, until better integrated.  */	\
+	asn1class = t3.asn1class;							\
+	construction = t3.construction;							\
+	tagnum = t3.tagnum;								\
+	taglen = t3.length;								\
+	indef = t3.indef;								\
+    }
+
+#define alloc_field(var, type)			\
+  var = (type*)calloc(1, sizeof(type));		\
+  if ((var) == NULL) return ENOMEM
+
+/* Fetch an expected APPLICATION class tag and verify. */
+#define apptag(tagexpect)								\
+  {											\
+      taginfo t1;									\
+      retval = asn1_get_tag_2(buf, &t1);						\
+      if (retval) return retval;						   	\
+      if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED ||	   	\
+	  t1.tagnum != (tagexpect)) return ASN1_BAD_ID;					\
+      /* Copy out to match previous functionality, until better integrated.  */		\
+      asn1class = t1.asn1class;								\
+      construction = t1.construction;							\
+      tagnum = t1.tagnum;								\
+      applen = t1.length;								\
+  }
+
+/**** normal fields ****/
+
+/*
+ * get_field_body
+ *
+ * Get bare field.  This also prefetches the next tag.  The call to
+ * get_eoc() assumes that any values fetched by this macro are
+ * enclosed in a context-specific tag.
+ */
+#define get_field_body(var, decoder)		\
+  retval = decoder(&subbuf, &(var));		\
+  if (retval) return retval;			\
+  if (!taglen && indef) { get_eoc(); }		\
+  next_tag()
+
+/*
+ * get_field
+ *
+ * Get field having an expected context specific tag.  This assumes
+ * that context-specific tags are monotonically increasing in its
+ * verification of tag numbers.
+ */
+#define get_field(var, tagexpect, decoder)				\
+  if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
+  if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
+  if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
+      && (tagnum || taglen || asn1class != UNIVERSAL))			\
+    return ASN1_BAD_ID;							\
+  get_field_body(var,decoder)
+
+/*
+ * opt_field
+ *
+ * Get an optional field with an expected context specific tag.
+ * Assumes that OPTVAL will have the default value, thus failing to
+ * distinguish between absent optional values and present optional
+ * values that happen to have the value of OPTVAL.
+ */
+#define opt_field(var, tagexpect, decoder, optvalue)			\
+  if (asn1buf_remains(&subbuf, seqindef)) {				\
+    if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
+	&& (tagnum || taglen || asn1class != UNIVERSAL))		\
+      return ASN1_BAD_ID;						\
+    if (tagnum == (tagexpect)) {					\
+      get_field_body(var, decoder);					\
+    } else var = optvalue;						\
+  }
+  
+/**** fields w/ length ****/
+
+/* similar to get_field_body */
+#define get_lenfield_body(len, var, decoder)	\
+  retval = decoder(&subbuf, &(len), &(var));	\
+  if (retval) return retval;			\
+  if (!taglen && indef) { get_eoc(); }		\
+  next_tag()
+
+/* similar to get_field_body */
+#define get_lenfield(len, var, tagexpect, decoder)			\
+  if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
+  if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
+  if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
+      && (tagnum || taglen || asn1class != UNIVERSAL))			\
+    return ASN1_BAD_ID;							\
+  get_lenfield_body(len, var, decoder)
+
+/* similar to opt_field */
+#define opt_lenfield(len, var, tagexpect, decoder)	\
+  if (tagnum == (tagexpect)) {				\
+    get_lenfield_body(len, var, decoder);		\
+  } else { len = 0; var = 0; }
+
+/*
+ * Deal with implicitly tagged fields
+ */
+#define get_implicit_octet_string(len, var, tagexpect)		    \
+  if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD;		    \
+  if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE)   \
+     return ASN1_BAD_ID;					    \
+  retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));	    \
+  if (retval) return retval;					    \
+  (len) = taglen;						    \
+  next_tag()
+
+#define opt_implicit_octet_string(len, var, tagexpect)		    \
+  if (tagnum == (tagexpect)) {					    \
+    if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \
+	return ASN1_BAD_ID;					    \
+    retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));   \
+    if (retval) return retval;					    \
+    (len) = taglen;						    \
+    next_tag();							    \
+  } else { (len) = 0; (var) = NULL; }
+
+/*
+ * begin_structure
+ *
+ * Declares some variables for decoding SEQUENCE types.  This is meant
+ * to be called in an inner block that ends with a call to
+ * end_structure().
+ */
+#define begin_structure()					\
+  asn1buf subbuf;						\
+  int seqindef;							\
+  int indef;							\
+  retval = asn1_get_sequence(buf, &length, &seqindef);		\
+  if (retval) return retval;					\
+  retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
+  if (retval) return retval;					\
+  next_tag()
+
+/*
+ * This is used for structures which have no tagging.
+ * It is the same as begin_structure() except next_tag()
+ * is not called.
+ */
+#define begin_structure_no_tag()				\
+  asn1buf subbuf;						\
+  int seqindef;							\
+  int indef;							\
+  retval = asn1_get_sequence(buf, &length, &seqindef);		\
+  if (retval) return retval;					\
+  retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
+  if (retval) return retval
+
+/* skip trailing garbage */
+#define end_structure()						\
+  retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum,	\
+			length, indef, seqindef);		\
+  if (retval) return retval
+
+/*
+ * begin_choice
+ *
+ * Declares some variables for decoding CHOICE types.  This is meant
+ * to be called in an inner block that ends with a call to
+ * end_choice().
+ */
+#define begin_choice()						\
+  asn1buf subbuf;						\
+  int seqindef;							\
+  int indef;							\
+  taginfo t;							\
+  retval = asn1_get_tag_2(buf, &t);				\
+  if (retval) return retval;					\
+  tagnum = t.tagnum;                                            \
+  taglen = t.length;                                            \
+  indef = t.indef;                                              \
+  length = t.length;                                            \
+  seqindef = t.indef;                                           \
+  asn1class = t.asn1class;					\
+  construction = t.construction;				\
+  retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
+  if (retval) return retval
+
+/* skip trailing garbage */
+#define end_choice()						\
+  length -= t.length;						\
+  retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum,	\
+			length, t.indef, seqindef);		\
+  if (retval) return retval
+
+/*
+ * sequence_of
+ *
+ * Declares some variables for decoding SEQUENCE OF types.  This is
+ * meant to be called in an inner block that ends with a call to
+ * end_sequence_of().
+ */
+#define sequence_of(buf)			\
+  unsigned int length, taglen;			\
+  asn1_class asn1class;				\
+  asn1_construction construction;		\
+  asn1_tagnum tagnum;				\
+  int indef;					\
+  sequence_of_common(buf)
+
+/*
+ * sequence_of_no_tagvars
+ *
+ * This is meant for use inside decoder functions that have an outer
+ * sequence structure and thus declares variables of different names
+ * than does sequence_of() to avoid shadowing.
+ */
+#define sequence_of_no_tagvars(buf)		\
+  asn1_class eseqclass;				\
+  asn1_construction eseqconstr;			\
+  asn1_tagnum eseqnum;				\
+  unsigned int eseqlen;				\
+  int eseqindef;				\
+  sequence_of_common(buf)
+
+/*
+ * sequence_of_common
+ *
+ * Fetches the outer SEQUENCE OF length info into {length,seqofindef}
+ * and imbeds an inner buffer seqbuf.  Unlike begin_structure(), it
+ * does not prefetch the next tag.
+ */
+#define sequence_of_common(buf)					\
+  int size = 0;							\
+  asn1buf seqbuf;						\
+  int seqofindef;						\
+  retval = asn1_get_sequence(buf, &length, &seqofindef);	\
+  if (retval) return retval;					\
+  retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef);	\
+  if (retval) return retval
+
+/*
+ * end_sequence_of
+ *
+ * Attempts to fetch an EOC tag, if any, and to sync over trailing
+ * garbage, if any.
+ */
+#define end_sequence_of(buf)							\
+  {										\
+      taginfo t4;								\
+      retval = asn1_get_tag_2(&seqbuf, &t4);					\
+      if (retval) return retval;						\
+      /* Copy out to match previous functionality, until better integrated.  */	\
+      asn1class = t4.asn1class;							\
+      construction = t4.construction;						\
+      tagnum = t4.tagnum;							\
+      taglen = t4.length;							\
+      indef = t4.indef;								\
+  }										\
+  retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum,			\
+			length, indef, seqofindef);				\
+  if (retval) return retval;
+
+/*
+ * end_sequence_of_no_tagvars
+ *
+ * Like end_sequence_of(), but uses the different (non-shadowing)
+ * variable names.
+ */
+#define end_sequence_of_no_tagvars(buf)						\
+  {										\
+      taginfo t5;								\
+      retval = asn1_get_tag_2(&seqbuf, &t5);					\
+      if (retval) return retval;						\
+      /* Copy out to match previous functionality, until better integrated.  */	\
+      eseqclass = t5.asn1class;							\
+      eseqconstr = t5.construction;						\
+      eseqnum = t5.tagnum;							\
+      eseqlen = t5.length;							\
+      eseqindef = t5.indef;							\
+  }										\
+  retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum,			\
+			eseqlen, eseqindef, seqofindef);			\
+  if (retval) return retval;
+
+#define cleanup()				\
+  return 0
+
+/* scalars */
+asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val)
+{
+    time_t	t;
+    asn1_error_code retval;
+    
+    retval =  asn1_decode_generaltime(buf,&t);
+    if (retval)
+	return retval;
+
+    *val = t;
+    return 0;
+}
+
+#define integer_convert(fname,ktype)\
+asn1_error_code fname(asn1buf * buf, ktype * val)\
+{\
+  asn1_error_code retval;\
+  long n;\
+  retval = asn1_decode_integer(buf,&n);\
+  if(retval) return retval;\
+  *val = (ktype)n;\
+  return 0;\
+}
+#define unsigned_integer_convert(fname,ktype)\
+asn1_error_code fname(asn1buf * buf, ktype * val)\
+{\
+  asn1_error_code retval;\
+  unsigned long n;\
+  retval = asn1_decode_unsigned_integer(buf,&n);\
+  if(retval) return retval;\
+  *val = (ktype)n;\
+  return 0;\
+}
+integer_convert(asn1_decode_int,int)
+integer_convert(asn1_decode_int32,krb5_int32)
+integer_convert(asn1_decode_kvno,krb5_kvno)
+integer_convert(asn1_decode_enctype,krb5_enctype)
+integer_convert(asn1_decode_cksumtype,krb5_cksumtype)
+integer_convert(asn1_decode_octet,krb5_octet)
+integer_convert(asn1_decode_addrtype,krb5_addrtype)
+integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
+unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
+unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
+
+asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val)
+{
+  asn1_error_code retval;
+  unsigned long n;
+
+  retval = asn1_decode_maybe_unsigned(buf, &n);
+  if (retval) return retval;
+  *val = (krb5_ui_4)n & 0xffffffff;
+  return 0;
+}
+
+asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val)
+{
+  asn1_error_code retval;
+  unsigned long n;
+  
+  retval = asn1_decode_unsigned_integer(buf,&n);
+  if(retval) return retval;
+  
+  *val = (krb5_msgtype) n;
+  return 0;
+}
+
+
+/* structures */
+asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val)
+{
+  return asn1_decode_generalstring(buf,
+				   &((*val)->realm.length),
+				   &((*val)->realm.data));
+}
+
+asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val)
+{
+  setup();
+  { begin_structure();
+    get_field((*val)->type,0,asn1_decode_int32);
+  
+    { sequence_of_no_tagvars(&subbuf);
+      while(asn1buf_remains(&seqbuf,seqofindef) > 0){
+	size++;
+	if ((*val)->data == NULL)
+	  (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data));
+	else
+	  (*val)->data = (krb5_data*)realloc((*val)->data,
+					     size*sizeof(krb5_data));
+	if((*val)->data == NULL) return ENOMEM;
+	retval = asn1_decode_generalstring(&seqbuf,
+					   &((*val)->data[size-1].length),
+					   &((*val)->data[size-1].data));
+	if(retval) return retval;
+      }
+      (*val)->length = size;
+      end_sequence_of_no_tagvars(&subbuf);
+    }
+    if (indef) {
+	get_eoc();
+    }
+    next_tag();
+    end_structure();
+    (*val)->magic = KV5M_PRINCIPAL;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->checksum_type,0,asn1_decode_cksumtype);
+    get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
+    end_structure();
+    val->magic = KV5M_CHECKSUM;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->enctype,0,asn1_decode_enctype);
+    get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
+    end_structure();
+    val->magic = KV5M_KEYBLOCK;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->enctype,0,asn1_decode_enctype);
+    opt_field(val->kvno,1,asn1_decode_kvno,0);
+    get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring);
+    end_structure();
+    val->magic = KV5M_ENC_DATA;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val)
+{
+  asn1_error_code retval;
+  asn1_octet unused, o;
+  taginfo t;
+  int i;
+  krb5_flags f=0;
+  unsigned int length;
+
+  retval = asn1_get_tag_2(buf, &t);
+  if (retval) return retval;
+  if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE ||
+      t.tagnum != ASN1_BITSTRING)
+      return ASN1_BAD_ID;
+  length = t.length;
+
+  retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */
+  if(retval) return retval;
+
+  /* Number of unused bits must be between 0 and 7. */
+  if (unused > 7) return ASN1_BAD_FORMAT;
+  length--;
+
+  for(i = 0; i < length; i++) {
+    retval = asn1buf_remove_octet(buf,&o);
+    if(retval) return retval;
+    /* ignore bits past number 31 */
+    if (i < 4)
+      f = (f<<8) | ((krb5_flags)o&0xFF);
+  }
+  if (length <= 4) {
+    /* Mask out unused bits, but only if necessary. */
+    f &= ~(krb5_flags)0 << unused;
+  }
+  /* left-justify */
+  if (length < 4)
+    f <<= (4 - length) * 8;
+  *val = f;
+  return 0;
+}
+
+asn1_error_code asn1_decode_ticket_flags(asn1buf *buf, krb5_flags *val)
+{ return asn1_decode_krb5_flags(buf,val); }
+
+asn1_error_code asn1_decode_ap_options(asn1buf *buf, krb5_flags *val)
+{ return asn1_decode_krb5_flags(buf,val); }
+
+asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val)
+{ return asn1_decode_krb5_flags(buf,val); }
+
+asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->tr_type,0,asn1_decode_octet);
+    get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring);
+    end_structure();
+    val->magic = KV5M_TRANSITED;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val)
+{
+  setup();
+  { begin_structure();
+    alloc_field(val->session,krb5_keyblock);
+    get_field(*(val->session),0,asn1_decode_encryption_key);
+    get_field(val->last_req,1,asn1_decode_last_req);
+    get_field(val->nonce,2,asn1_decode_int32);
+    opt_field(val->key_exp,3,asn1_decode_kerberos_time,0);
+    get_field(val->flags,4,asn1_decode_ticket_flags);
+    get_field(val->times.authtime,5,asn1_decode_kerberos_time);
+    /* Set to authtime if missing */
+    opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime);
+    get_field(val->times.endtime,7,asn1_decode_kerberos_time);
+    opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0);
+    alloc_field(val->server,krb5_principal_data);
+    get_field(val->server,9,asn1_decode_realm);
+    get_field(val->server,10,asn1_decode_principal_name);
+    opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL);
+    end_structure();
+    val->magic = KV5M_ENC_KDC_REP_PART;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val)
+{
+  setup();
+  unsigned int applen;
+  apptag(1);
+  { begin_structure();
+    { krb5_kvno vno;
+      get_field(vno,0,asn1_decode_kvno);
+      if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
+    alloc_field(val->server,krb5_principal_data);
+    get_field(val->server,1,asn1_decode_realm);
+    get_field(val->server,2,asn1_decode_principal_name);
+    get_field(val->enc_part,3,asn1_decode_encrypted_data);
+    end_structure();
+    val->magic = KV5M_TICKET;
+  }
+  if (!applen) {
+      taginfo t;
+      retval = asn1_get_tag_2(buf, &t);
+      if (retval) return retval;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val)
+{
+  setup();
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,1,asn1_decode_kvno);
+      if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
+    get_field(val->msg_type,2,asn1_decode_msgtype);
+    opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL);
+    get_field(*val,4,asn1_decode_kdc_req_body);
+    end_structure();
+    val->magic = KV5M_KDC_REQ;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val)
+{
+  setup();
+  { 
+    krb5_principal psave;
+    begin_structure();
+    get_field(val->kdc_options,0,asn1_decode_kdc_options);
+    if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); }
+    opt_field(val->client,1,asn1_decode_principal_name,NULL);
+    alloc_field(val->server,krb5_principal_data);
+    get_field(val->server,2,asn1_decode_realm);
+    if(val->client != NULL){
+      retval = asn1_krb5_realm_copy(val->client,val->server);
+      if(retval) return retval; }
+
+    /* If opt_field server is missing, memory reference to server is
+       lost and results in memory leak */
+    psave = val->server;
+    opt_field(val->server,3,asn1_decode_principal_name,NULL);
+    if(val->server == NULL){
+      if(psave->realm.data) {
+	free(psave->realm.data);
+	psave->realm.data = NULL;
+	psave->realm.length=0;
+      }
+      free(psave);
+    }
+    opt_field(val->from,4,asn1_decode_kerberos_time,0);
+    get_field(val->till,5,asn1_decode_kerberos_time);
+    opt_field(val->rtime,6,asn1_decode_kerberos_time,0);
+    get_field(val->nonce,7,asn1_decode_int32);
+    get_lenfield(val->nktypes,val->ktype,8,asn1_decode_sequence_of_enctype);
+    opt_field(val->addresses,9,asn1_decode_host_addresses,0);
+    if(tagnum == 10){
+      get_field(val->authorization_data,10,asn1_decode_encrypted_data); }
+    else{
+      val->authorization_data.magic = KV5M_ENC_DATA;
+      val->authorization_data.enctype = 0;
+      val->authorization_data.kvno = 0;
+      val->authorization_data.ciphertext.data = NULL;
+      val->authorization_data.ciphertext.length = 0;
+    }
+    opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL);
+    end_structure();
+    val->magic = KV5M_KDC_REQ;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val)
+{
+  setup();
+  { begin_structure();
+    get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring);
+    opt_field(val->timestamp,1,asn1_decode_kerberos_time,0);
+    opt_field(val->usec,2,asn1_decode_int32,0);
+    opt_field(val->seq_number,3,asn1_decode_seqnum,0);
+    alloc_field(val->s_address,krb5_address);
+    get_field(*(val->s_address),4,asn1_decode_host_address);
+    if(tagnum == 5){
+      alloc_field(val->r_address,krb5_address);
+      get_field(*(val->r_address),5,asn1_decode_host_address);
+    } else val->r_address = NULL;
+    end_structure();
+    val->magic = KV5M_SAFE;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->addrtype,0,asn1_decode_addrtype);
+    get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
+    end_structure();
+    val->magic = KV5M_ADDRESS;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val)
+{
+  setup();
+  { begin_structure();
+    { krb5_kvno pvno;
+      get_field(pvno,0,asn1_decode_kvno);
+      if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
+    get_field(val->msg_type,1,asn1_decode_msgtype);
+    opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL);
+    alloc_field(val->client,krb5_principal_data);
+    get_field(val->client,3,asn1_decode_realm);
+    get_field(val->client,4,asn1_decode_principal_name);
+    alloc_field(val->ticket,krb5_ticket);
+    get_field(*(val->ticket),5,asn1_decode_ticket);
+    get_field(val->enc_part,6,asn1_decode_encrypted_data);
+    end_structure();
+    val->magic = KV5M_KDC_REP;
+  }
+  cleanup();
+}
+
+
+/* arrays */
+#define get_element(element,decoder)\
+retval = decoder(&seqbuf,element);\
+if(retval) return retval
+     
+#define array_append(array,size,element,type)\
+size++;\
+if (*(array) == NULL)\
+     *(array) = (type**)malloc((size+1)*sizeof(type*));\
+else\
+  *(array) = (type**)realloc(*(array),\
+			     (size+1)*sizeof(type*));\
+if(*(array) == NULL) return ENOMEM;\
+(*(array))[(size)-1] = elt
+     
+#define decode_array_body(type,decoder)\
+  asn1_error_code retval;\
+  type *elt;\
+\
+  { sequence_of(buf);\
+    while(asn1buf_remains(&seqbuf,seqofindef) > 0){\
+      alloc_field(elt,type);\
+      get_element(elt,decoder);\
+      array_append(val,size,elt,type);\
+    }\
+    if (*val == NULL)\
+	*val = (type **)malloc(sizeof(type*));\
+    (*val)[size] = NULL;\
+    end_sequence_of(buf);\
+  }\
+  cleanup()
+
+
+asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val)
+{
+  decode_array_body(krb5_authdata,asn1_decode_authdata_elt);
+}
+
+asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->ad_type,0,asn1_decode_authdatatype);
+    get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
+    end_structure();
+    val->magic = KV5M_AUTHDATA;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val)
+{
+  decode_array_body(krb5_address,asn1_decode_host_address);
+}
+
+asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val)
+{
+  decode_array_body(krb5_ticket,asn1_decode_ticket);
+}
+
+asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val)
+{
+  decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info);
+}
+
+asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val)
+{
+  setup();
+  { begin_structure();
+    alloc_field(val->session,krb5_keyblock);
+    get_field(*(val->session),0,asn1_decode_encryption_key);
+    if(tagnum == 1){
+      alloc_field(val->client,krb5_principal_data);
+      opt_field(val->client,1,asn1_decode_realm,NULL);
+      opt_field(val->client,2,asn1_decode_principal_name,NULL); }
+    opt_field(val->flags,3,asn1_decode_ticket_flags,0);
+    opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0);
+    opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0);
+    opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0);
+    opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0);
+    if(tagnum == 8){
+      alloc_field(val->server,krb5_principal_data);
+      opt_field(val->server,8,asn1_decode_realm,NULL);
+      opt_field(val->server,9,asn1_decode_principal_name,NULL); }
+    opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL);
+    end_structure();
+    val->magic = KV5M_CRED_INFO;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val)
+{
+  decode_array_body(krb5_pa_data,asn1_decode_pa_data);
+}
+
+asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->pa_type,1,asn1_decode_int32);
+    get_lenfield(val->length,val->contents,2,asn1_decode_octetstring);
+    end_structure();
+    val->magic = KV5M_PA_DATA;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val)
+{
+  decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry);
+}
+
+asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->lr_type,0,asn1_decode_int32);
+    get_field(val->value,1,asn1_decode_kerberos_time);
+    end_structure();
+    val->magic = KV5M_LAST_REQ_ENTRY;
+#ifdef KRB5_GENEROUS_LR_TYPE
+    /* If we are only a single byte wide and negative - fill in the
+       other bits */
+    if((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U;
+#endif
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val)
+{
+  asn1_error_code retval;
+  { sequence_of(buf);
+    while(asn1buf_remains(&seqbuf,seqofindef) > 0){
+      size++;
+      if (*val == NULL)
+        *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype));
+      else
+        *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype));
+      if(*val == NULL) return ENOMEM;
+      retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1]));
+      if(retval) return retval;
+    }
+    *num = size;
+    end_sequence_of(buf);
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val)
+{
+  decode_array_body(krb5_checksum, asn1_decode_checksum);
+}
+
+static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val )
+{
+  setup();
+  { begin_structure();
+    get_field(val->etype,0,asn1_decode_enctype);
+    if (tagnum == 1) {
+	    get_lenfield(val->length,val->salt,1,asn1_decode_generalstring);
+    } else {
+	    val->length = KRB5_ETYPE_NO_SALT;
+	    val->salt = 0;
+    }
+    if ( tagnum ==2) {
+      krb5_octet *params ;
+      get_lenfield( val->s2kparams.length, params,
+		      2, asn1_decode_octetstring);
+      val->s2kparams.data = ( char *) params;
+    } else {
+	val->s2kparams.data = NULL;
+	val->s2kparams.length = 0;
+    }
+    end_structure();
+    val->magic = KV5M_ETYPE_INFO_ENTRY;
+  }
+  cleanup();
+}
+
+static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val )
+{
+  setup();
+  { begin_structure();
+    get_field(val->etype,0,asn1_decode_enctype);
+    if (tagnum == 1) {
+	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
+    } else {
+	    val->length = KRB5_ETYPE_NO_SALT;
+	    val->salt = 0;
+    }
+    if ( tagnum ==2) {
+      krb5_octet *params ;
+      get_lenfield( val->s2kparams.length, params,
+		      2, asn1_decode_octetstring);
+      val->s2kparams.data = ( char *) params;
+    } else {
+	val->s2kparams.data = NULL;
+	val->s2kparams.length = 0;
+    }
+    end_structure();
+    val->magic = KV5M_ETYPE_INFO_ENTRY;
+  }
+  cleanup();
+}
+
+
+static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val )
+{
+  setup();
+  { begin_structure();
+    get_field(val->etype,0,asn1_decode_enctype);
+    if (tagnum == 1) {
+	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
+    } else {
+	    val->length = KRB5_ETYPE_NO_SALT;
+	    val->salt = 0;
+    }
+    val->s2kparams.data = NULL;
+    val->s2kparams.length = 0;
+    
+    end_structure();
+    val->magic = KV5M_ETYPE_INFO_ENTRY;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val )
+{
+  decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry);
+}
+
+asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val ,
+					krb5_boolean v1_3_behavior)
+{
+    if (v1_3_behavior) {
+	decode_array_body(krb5_etype_info_entry,
+			  asn1_decode_etype_info2_entry_1_3);
+    } else {
+	decode_array_body(krb5_etype_info_entry,
+			  asn1_decode_etype_info2_entry);
+    }
+}
+
+asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val)
+{
+  setup();
+  { begin_structure();
+    alloc_field(val->passwd,krb5_data);
+    get_lenfield(val->passwd->length,val->passwd->data,
+		 0,asn1_decode_charstring);
+    val->passwd->magic = KV5M_DATA;
+    alloc_field(val->phrase,krb5_data);
+    get_lenfield(val->phrase->length,val->phrase->data,
+		 1,asn1_decode_charstring);
+    val->phrase->magic = KV5M_DATA;
+    end_structure();
+    val->magic = KV5M_PASSWD_PHRASE_ELEMENT;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val)
+{
+  decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence);
+}
+
+asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val)
+{ return asn1_decode_krb5_flags(buf,val); }
+
+#define opt_string(val,n,fn) opt_lenfield((val).length,(val).data,n,fn)
+#define opt_cksum(var,tagexpect,decoder)\
+if(tagnum == (tagexpect)){\
+  get_field_body(var,decoder); }\
+else var.length = 0
+
+asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->sam_type,0,asn1_decode_int32);
+    get_field(val->sam_flags,1,asn1_decode_sam_flags);
+    opt_string(val->sam_type_name,2,asn1_decode_charstring);
+    opt_string(val->sam_track_id,3,asn1_decode_charstring);
+    opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
+    opt_string(val->sam_challenge,5,asn1_decode_charstring);
+    opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
+    opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
+    opt_field(val->sam_nonce,8,asn1_decode_int32,0);
+    opt_cksum(val->sam_cksum,9,asn1_decode_checksum);
+    end_structure();
+    val->magic = KV5M_SAM_CHALLENGE;
+  }
+  cleanup();
+}
+asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val)
+{
+  setup();
+  { char *save, *end;
+    size_t alloclen;
+    begin_structure();
+    if (tagnum != 0) return ASN1_MISSING_FIELD;
+    if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) 
+      return ASN1_BAD_ID;
+    save = subbuf.next;
+    { sequence_of_no_tagvars(&subbuf);
+      unused_var(size);
+      end_sequence_of_no_tagvars(&subbuf);
+    }
+    end = subbuf.next;
+    alloclen = end - save;
+    if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL)
+      return ENOMEM;
+    val->sam_challenge_2_body.length = alloclen;
+    memcpy(val->sam_challenge_2_body.data, save, alloclen);
+    next_tag();
+    get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum);
+    end_structure();
+  }
+  cleanup();
+}
+asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->sam_type,0,asn1_decode_int32);
+    get_field(val->sam_flags,1,asn1_decode_sam_flags);
+    opt_string(val->sam_type_name,2,asn1_decode_charstring);
+    opt_string(val->sam_track_id,3,asn1_decode_charstring);
+    opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
+    opt_string(val->sam_challenge,5,asn1_decode_charstring);
+    opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
+    opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
+    get_field(val->sam_nonce,8,asn1_decode_int32);
+    get_field(val->sam_etype, 9, asn1_decode_int32);
+    end_structure();
+    val->magic = KV5M_SAM_CHALLENGE;
+  }
+  cleanup();
+}
+asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val)
+{
+  setup();
+  { begin_structure();
+    /* alloc_field(val->sam_key,krb5_keyblock); */
+    get_field(val->sam_key,0,asn1_decode_encryption_key);
+    end_structure();
+    val->magic = KV5M_SAM_KEY;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val)
+{
+  setup();
+  { begin_structure();
+    opt_field(val->sam_nonce,0,asn1_decode_int32,0);
+    opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0);
+    opt_field(val->sam_usec,2,asn1_decode_int32,0);
+    opt_string(val->sam_sad,3,asn1_decode_charstring);
+    end_structure();
+    val->magic = KV5M_ENC_SAM_RESPONSE_ENC;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->sam_nonce,0,asn1_decode_int32);
+    opt_string(val->sam_sad,1,asn1_decode_charstring);
+    end_structure();
+    val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
+  }
+  cleanup();
+}
+
+#define opt_encfield(fld,tag,fn) \
+    if(tagnum == tag){ \
+      get_field(fld,tag,fn); } \
+    else{\
+      fld.magic = 0;\
+      fld.enctype = 0;\
+      fld.kvno = 0;\
+      fld.ciphertext.data = NULL;\
+      fld.ciphertext.length = 0;\
+    }
+
+asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->sam_type,0,asn1_decode_int32);
+    get_field(val->sam_flags,1,asn1_decode_sam_flags);
+    opt_string(val->sam_track_id,2,asn1_decode_charstring);
+    opt_encfield(val->sam_enc_key,3,asn1_decode_encrypted_data);
+    get_field(val->sam_enc_nonce_or_ts,4,asn1_decode_encrypted_data);
+    opt_field(val->sam_nonce,5,asn1_decode_int32,0);
+    opt_field(val->sam_patimestamp,6,asn1_decode_kerberos_time,0);
+    end_structure();
+    val->magic = KV5M_SAM_RESPONSE;
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->sam_type,0,asn1_decode_int32);
+    get_field(val->sam_flags,1,asn1_decode_sam_flags);
+    opt_string(val->sam_track_id,2,asn1_decode_charstring);
+    get_field(val->sam_enc_nonce_or_sad,3,asn1_decode_encrypted_data);
+    get_field(val->sam_nonce,4,asn1_decode_int32);
+    end_structure();
+    val->magic = KV5M_SAM_RESPONSE;
+  }
+  cleanup();
+}
+
+
+asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val)
+{
+  setup();
+  { begin_structure();
+    get_field(val->sam_key,0,asn1_decode_encryption_key);
+    get_field(val->sam_flags,1,asn1_decode_sam_flags);
+    get_field(val->stime,2,asn1_decode_kerberos_time);
+    get_field(val->susec,3,asn1_decode_int32);
+    alloc_field(val->client,krb5_principal_data);
+    get_field(val->client,4,asn1_decode_realm);
+    get_field(val->client,5,asn1_decode_principal_name);
+    opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */
+    end_structure();
+    val->magic = KV5M_PREDICTED_SAM_RESPONSE;
+  }
+  cleanup();
+}
+
+/* PKINIT */
+
+asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val)
+{
+    setup();
+    {
+      begin_structure();
+      opt_implicit_octet_string(val->subjectName.length, val->subjectName.data, 0);
+      opt_implicit_octet_string(val->issuerAndSerialNumber.length, val->issuerAndSerialNumber.data, 1);
+      opt_implicit_octet_string(val->subjectKeyIdentifier.length, val->subjectKeyIdentifier.data, 2);
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier ***val)
+{
+    decode_array_body(krb5_external_principal_identifier,asn1_decode_external_principal_identifier);
+}
+
+asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val)
+{
+  setup();
+  {
+    begin_structure();
+    get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
+    opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_external_principal_identifier, NULL);
+    opt_implicit_octet_string(val->kdcPkId.length, val->kdcPkId.data, 2);
+    end_structure();
+  }
+  cleanup();
+}
+
+#if 0	/* XXX   This needs to be tested!!! XXX */
+asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
+{
+    setup();
+    { 
+      char *start, *end;
+      size_t alloclen;
+
+      begin_explicit_choice();
+      if (t.tagnum == choice_trusted_cas_principalName) {
+	val->choice = choice_trusted_cas_principalName;
+      } else if (t.tagnum == choice_trusted_cas_caName) {
+	val->choice = choice_trusted_cas_caName;
+	start = subbuf.next;
+	{
+	  sequence_of_no_tagvars(&subbuf);
+	  unused_var(size);
+	  end_sequence_of_no_tagvars(&subbuf);
+	}
+	end = subbuf.next;
+	alloclen = end - start;
+	val->u.caName.data = malloc(alloclen);
+	if (val->u.caName.data == NULL)
+	  return ENOMEM;
+	memcpy(val->u.caName.data, start, alloclen);
+	val->u.caName.length = alloclen;
+	next_tag();
+      } else if (t.tagnum == choice_trusted_cas_issuerAndSerial) {
+	val->choice = choice_trusted_cas_issuerAndSerial;
+	start = subbuf.next;
+	{
+	  sequence_of_no_tagvars(&subbuf);
+	  unused_var(size);
+	  end_sequence_of_no_tagvars(&subbuf);
+	}
+	end = subbuf.next;
+	alloclen = end - start;
+	val->u.issuerAndSerial.data = malloc(alloclen);
+	if (val->u.issuerAndSerial.data == NULL)
+	  return ENOMEM;
+	memcpy(val->u.issuerAndSerial.data, start, alloclen);
+	val->u.issuerAndSerial.length = alloclen;
+	next_tag();
+      } else return ASN1_BAD_ID;
+      end_explicit_choice();
+    }
+    cleanup();
+}
+#else
+asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
+{
+    setup();
+    { begin_choice();
+      if (tagnum == choice_trusted_cas_principalName) {
+	val->choice = choice_trusted_cas_principalName;
+	asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName));
+      } else if (tagnum == choice_trusted_cas_caName) {
+	val->choice = choice_trusted_cas_caName;
+	get_implicit_octet_string(val->u.caName.length, val->u.caName.data, choice_trusted_cas_caName);
+      } else if (tagnum == choice_trusted_cas_issuerAndSerial) {
+	val->choice = choice_trusted_cas_issuerAndSerial;
+	get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data,
+				  choice_trusted_cas_issuerAndSerial);
+      } else return ASN1_BAD_ID;
+      end_choice();
+    }
+    cleanup();
+}
+#endif
+
+asn1_error_code asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val)
+{
+    decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca);
+}
+
+asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val)
+{
+  setup();
+  { begin_structure();
+    get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
+    opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_trusted_ca, NULL);
+    opt_lenfield(val->kdcCert.length, val->kdcCert.data, 2, asn1_decode_octetstring);
+    opt_lenfield(val->encryptionCert.length, val->encryptionCert.data, 2, asn1_decode_octetstring);
+    end_structure();
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val)
+{
+    setup();
+    { begin_structure();
+      get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0);
+
+      opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring);
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val)
+{
+    setup();
+    { begin_structure();
+      get_field(val->cusec, 0, asn1_decode_int32);
+      get_field(val->ctime, 1, asn1_decode_kerberos_time);
+      get_field(val->nonce, 2, asn1_decode_int32);
+      opt_lenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_decode_octetstring);
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val)
+{
+    setup();
+    { begin_structure();
+      alloc_field(val->kdcName,krb5_principal_data);
+      get_field(val->kdcName, 0, asn1_decode_principal_name); 
+      get_field(val->kdcName, 1, asn1_decode_realm); 
+      get_field(val->cusec, 2, asn1_decode_int32);
+      get_field(val->ctime, 3, asn1_decode_kerberos_time);
+      get_field(val->nonce, 4, asn1_decode_int32);
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf,  krb5_algorithm_identifier *val) {
+
+  setup();
+  { begin_structure_no_tag();
+    /*
+     * Forbid indefinite encoding because we don't read enough tag
+     * information from the trailing octets ("ANY DEFINED BY") to
+     * synchronize EOC tags, etc.
+     */
+    if (seqindef) return ASN1_BAD_FORMAT;
+    /*
+     * Set up tag variables because we don't actually call anything
+     * that fetches tag info for us; it's all buried in the decoder
+     * primitives.
+     */
+    tagnum = ASN1_TAGNUM_CEILING;
+    asn1class = UNIVERSAL;
+    construction = PRIMITIVE;
+    taglen = 0;
+    indef = 0;
+    retval = asn1_decode_oid(&subbuf, &val->algorithm.length, 
+			     &val->algorithm.data);
+    if(retval) return retval;
+    val->parameters.length = 0;
+    val->parameters.data = NULL;
+
+    if(length > subbuf.next - subbuf.base) {
+      unsigned int size = length - (subbuf.next - subbuf.base);
+      retval = asn1buf_remove_octetstring(&subbuf, size, 
+					  &val->parameters.data);
+      if(retval) return retval;
+      val->parameters.length = size;
+    }
+    
+    end_structure();
+  }
+  cleanup();      
+}
+
+asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val)
+{
+    asn1_octet unused;
+    setup();
+    { begin_structure_no_tag();
+
+      retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm);
+      if (retval) return retval;
+
+      /* SubjectPublicKey encoded as a BIT STRING */
+      next_tag();
+      if (asn1class != UNIVERSAL || construction != PRIMITIVE ||
+          tagnum != ASN1_BITSTRING)
+        return ASN1_BAD_ID;
+
+      retval = asn1buf_remove_octet(&subbuf, &unused);
+      if(retval) return retval;
+
+      /* Number of unused bits must be between 0 and 7. */
+      /* What to do if unused is not zero? */
+      if (unused > 7) return ASN1_BAD_FORMAT;
+      taglen--;
+
+      val->subjectPublicKey.length = 0;
+      val->subjectPublicKey.data = NULL;
+      retval = asn1buf_remove_octetstring(&subbuf, taglen, 
+					  &val->subjectPublicKey.data);
+      if(retval) return retval;
+      val->subjectPublicKey.length = taglen;
+      /*
+       * We didn't call any macro that does next_tag(); do so now to
+       * preload tag of any trailing encodings.
+       */
+      next_tag();
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier ***val)
+{
+    decode_array_body(krb5_algorithm_identifier, asn1_decode_algorithm_identifier);
+}
+
+asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val)
+{
+    setup();
+    { begin_structure();
+      retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data);
+      if(retval) return retval;
+      val->subjectPublicKey.length = taglen;
+      next_tag();
+      get_field(val->nonce, 1, asn1_decode_int32);
+      opt_field(val->dhKeyExpiration, 2, asn1_decode_kerberos_time, 0);
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val)
+{
+    setup();
+    { begin_structure();
+      get_field(val->replyKey, 0, asn1_decode_encryption_key);
+      get_field(val->asChecksum, 1, asn1_decode_checksum); 
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val)
+{
+    setup();
+    { begin_structure();
+      get_field(val->replyKey, 0, asn1_decode_encryption_key);
+      get_field(val->nonce, 1, asn1_decode_int32); 
+      end_structure();
+    }
+    cleanup();
+}
+
+
+asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val)
+{
+    setup();
+    { begin_structure();
+      get_field(*val, 0, asn1_decode_realm);
+      get_field(*val, 1, asn1_decode_principal_name);
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val)
+{
+    setup();
+    { begin_structure();
+      get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator);
+      if (tagnum == 1) { alloc_field(val->clientPublicValue, krb5_subject_pk_info); }      
+      /* can't call opt_field because it does decoder(&subbuf, &(val)); */
+      if (asn1buf_remains(&subbuf, seqindef)) {                             
+	if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)  
+	    && (tagnum || taglen || asn1class != UNIVERSAL))                
+	  return ASN1_BAD_ID;                                               
+	if (tagnum == 1) {                                        
+	  retval = asn1_decode_subject_pk_info(&subbuf, 
+					       val->clientPublicValue);
+	  if (!taglen && indef) { get_eoc(); }
+	  next_tag();
+	} else val->clientPublicValue = NULL;  
+      }      
+      /* can't call opt_field because it does decoder(&subbuf, &(val)); */
+      if (asn1buf_remains(&subbuf, seqindef)) {
+        if (tagnum == 2) {
+	  asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes);
+	  if (!taglen && indef) { get_eoc(); }
+	  next_tag();
+	} else val->supportedCMSTypes = NULL;
+      }
+      opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring);
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val)
+{
+    setup();
+    { begin_structure();
+      get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9);
+      if (tagnum == 1) {
+	alloc_field(val->clientPublicValue, krb5_subject_pk_info);      
+	/* can't call opt_field because it does decoder(&subbuf, &(val)); */
+	if (asn1buf_remains(&subbuf, seqindef)) {                             
+	  if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)  
+	    && (tagnum || taglen || asn1class != UNIVERSAL))                
+	    return ASN1_BAD_ID;                                               
+	  if (tagnum == 1) {                                        
+	    retval = asn1_decode_subject_pk_info(&subbuf, 
+					         val->clientPublicValue);
+	    if (!taglen && indef) { get_eoc(); }
+	    next_tag();
+	  } else val->clientPublicValue = NULL;  
+	}
+      }
+      end_structure();
+    }
+    cleanup();
+}
+
+asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val)
+{
+  setup();
+  { begin_choice();
+    if (tagnum == choice_pa_pk_as_rep_dhInfo) {
+      val->choice = choice_pa_pk_as_rep_dhInfo;
+      get_field_body(val->u.dh_Info, asn1_decode_dh_rep_info);
+    } else if (tagnum == choice_pa_pk_as_rep_encKeyPack) {
+      val->choice = choice_pa_pk_as_rep_encKeyPack;
+      get_implicit_octet_string(val->u.encKeyPack.length, val->u.encKeyPack.data,
+				choice_pa_pk_as_rep_encKeyPack);
+    } else {
+      val->choice = choice_pa_pk_as_rep_UNKNOWN;
+    }
+    end_choice();
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val)
+{
+  setup();
+  { begin_structure();
+    if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) {
+      val->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
+      get_lenfield(val->u.dhSignedData.length, val->u.dhSignedData.data,
+		    choice_pa_pk_as_rep_draft9_dhSignedData, asn1_decode_octetstring);
+    } else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) {
+      val->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
+      get_lenfield(val->u.encKeyPack.length, val->u.encKeyPack.data,
+		    choice_pa_pk_as_rep_draft9_encKeyPack, asn1_decode_octetstring);
+    } else {
+      val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN;
+    }
+    end_structure();
+  }
+  cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_typed_data(asn1buf *buf, krb5_typed_data ***val)
+{
+    decode_array_body(krb5_typed_data,asn1_decode_typed_data);
+}
+
+asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val) 
+{
+  setup();
+  { begin_structure();
+    get_field(val->type,0,asn1_decode_int32);
+    get_lenfield(val->length,val->data,1,asn1_decode_octetstring);
+    end_structure();
+  }
+  cleanup();
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.h b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.h
new file mode 100644
index 000000000..72c4e293c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_decode.h
@@ -0,0 +1,235 @@
+/*
+ * src/lib/krb5/asn.1/asn1_k_decode.h
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __ASN1_DECODE_KRB5_H__
+#define __ASN1_DECODE_KRB5_H__
+
+#include "k5-int.h"
+#include "krbasn1.h"
+#include "asn1buf.h"
+
+/* asn1_error_code asn1_decode_scalar_type(asn1buf *buf, krb5_scalar *val); */
+/* requires  *buf is allocated, *buf's current position points to the
+              beginning of an encoding (<id> <len> <contents>),
+	      *val is allocated
+   effects   Decodes the encoding in *buf, returning the result in *val.
+             Returns ASN1_BAD_ID if the encoded id does not
+	      indicate the proper type.
+             Returns ASN1_OVERRUN if the encoded length exceeds
+	      the bounds of *buf */
+
+
+/* asn1_error_code asn1_decode_structure_type(asn1buf *buf,
+                                              krb5_structure *val); */
+/* requires  *buf is allocated, *buf's current position points to the
+              beginning of an encoding (<id> <len> <contents>),
+	      *val is allocated
+	     Assumes that *val is a freshly-allocated structure (i.e.
+	      does not attempt to clean up or free *val).
+   effects   Decodes the encoding in *buf, returning the result in *val.
+             Returns ASN1_BAD_ID if the encoded id does not
+	      indicate the proper type.
+             Returns ASN1_OVERRUN if the encoded length exceeds
+	      the bounds of *buf */
+
+/* asn1_error_code asn1_decode_array_type(asn1buf *buf, krb5_scalar ***val); */
+/* requires  *buf is allocated, *buf's current position points to the
+              beginning of an encoding (<id> <len> <contents>)
+	     Assumes that *val is empty (i.e. does not attempt to
+	      clean up or free *val).
+   effects   Decodes the encoding in *buf, returning the result in *val.
+             Returns ASN1_BAD_ID if the encoded id does not
+	      indicate the proper type.
+             Returns ASN1_OVERRUN if the encoded length exceeds
+	      the bounds of *buf */
+
+/* scalars */
+asn1_error_code asn1_decode_int
+	(asn1buf *buf, int *val);
+asn1_error_code asn1_decode_int32
+	(asn1buf *buf, krb5_int32 *val);
+asn1_error_code asn1_decode_kvno
+	(asn1buf *buf, krb5_kvno *val);
+asn1_error_code asn1_decode_enctype
+	(asn1buf *buf, krb5_enctype *val);
+asn1_error_code asn1_decode_msgtype
+	(asn1buf *buf, krb5_msgtype *val);
+asn1_error_code asn1_decode_cksumtype
+	(asn1buf *buf, krb5_cksumtype *val);
+asn1_error_code asn1_decode_octet
+	(asn1buf *buf, krb5_octet *val);
+asn1_error_code asn1_decode_addrtype
+	(asn1buf *buf, krb5_addrtype *val);
+asn1_error_code asn1_decode_authdatatype
+	(asn1buf *buf, krb5_authdatatype *val);
+asn1_error_code asn1_decode_ui_2
+	(asn1buf *buf, krb5_ui_2 *val);
+asn1_error_code asn1_decode_ui_4
+	(asn1buf *buf, krb5_ui_4 *val);
+asn1_error_code asn1_decode_seqnum
+	(asn1buf *buf, krb5_ui_4 *val);
+asn1_error_code asn1_decode_kerberos_time
+	(asn1buf *buf, krb5_timestamp *val);
+asn1_error_code asn1_decode_sam_flags
+	(asn1buf *buf, krb5_flags *val);
+
+/* structures */
+asn1_error_code asn1_decode_realm
+	(asn1buf *buf, krb5_principal *val);
+asn1_error_code asn1_decode_principal_name
+	(asn1buf *buf, krb5_principal *val);
+asn1_error_code asn1_decode_checksum
+	(asn1buf *buf, krb5_checksum *val);
+asn1_error_code asn1_decode_encryption_key
+	(asn1buf *buf, krb5_keyblock *val);
+asn1_error_code asn1_decode_encrypted_data
+	(asn1buf *buf, krb5_enc_data *val);
+asn1_error_code asn1_decode_ticket_flags
+	(asn1buf *buf, krb5_flags *val);
+asn1_error_code asn1_decode_transited_encoding
+	(asn1buf *buf, krb5_transited *val);
+asn1_error_code asn1_decode_enc_kdc_rep_part
+	(asn1buf *buf, krb5_enc_kdc_rep_part *val);
+asn1_error_code asn1_decode_krb5_flags
+	(asn1buf *buf, krb5_flags *val);
+asn1_error_code asn1_decode_ap_options
+	(asn1buf *buf, krb5_flags *val);
+asn1_error_code asn1_decode_kdc_options
+	(asn1buf *buf, krb5_flags *val);
+asn1_error_code asn1_decode_ticket
+	(asn1buf *buf, krb5_ticket *val);
+asn1_error_code asn1_decode_kdc_req
+	(asn1buf *buf, krb5_kdc_req *val);
+asn1_error_code asn1_decode_kdc_req_body
+	(asn1buf *buf, krb5_kdc_req *val);
+asn1_error_code asn1_decode_krb_safe_body
+	(asn1buf *buf, krb5_safe *val);
+asn1_error_code asn1_decode_host_address
+	(asn1buf *buf, krb5_address *val);
+asn1_error_code asn1_decode_kdc_rep
+	(asn1buf *buf, krb5_kdc_rep *val);
+asn1_error_code asn1_decode_last_req_entry
+	(asn1buf *buf, krb5_last_req_entry *val);
+asn1_error_code asn1_decode_authdata_elt
+	(asn1buf *buf, krb5_authdata *val);
+asn1_error_code asn1_decode_krb_cred_info
+	(asn1buf *buf, krb5_cred_info *val);
+asn1_error_code asn1_decode_pa_data
+	(asn1buf *buf, krb5_pa_data *val);
+asn1_error_code asn1_decode_passwdsequence
+	(asn1buf *buf, passwd_phrase_element *val);
+asn1_error_code asn1_decode_sam_challenge
+	(asn1buf *buf, krb5_sam_challenge *val);
+asn1_error_code asn1_decode_sam_challenge_2
+	(asn1buf *buf, krb5_sam_challenge_2 *val);
+asn1_error_code asn1_decode_sam_challenge_2_body
+	(asn1buf *buf, krb5_sam_challenge_2_body *val);
+asn1_error_code asn1_decode_enc_sam_key
+	(asn1buf *buf, krb5_sam_key *val);
+asn1_error_code asn1_decode_enc_sam_response_enc
+	(asn1buf *buf, krb5_enc_sam_response_enc *val);
+asn1_error_code asn1_decode_enc_sam_response_enc_2
+	(asn1buf *buf, krb5_enc_sam_response_enc_2 *val);
+asn1_error_code asn1_decode_sam_response
+	(asn1buf *buf, krb5_sam_response *val);
+asn1_error_code asn1_decode_sam_response_2
+	(asn1buf *buf, krb5_sam_response_2 *val);
+asn1_error_code asn1_decode_predicted_sam_response
+	(asn1buf *buf, krb5_predicted_sam_response *val);
+asn1_error_code asn1_decode_external_principal_identifier
+	(asn1buf *buf, krb5_external_principal_identifier *val);
+asn1_error_code asn1_decode_pa_pk_as_req
+	(asn1buf *buf, krb5_pa_pk_as_req *val);
+asn1_error_code asn1_decode_trusted_ca
+	(asn1buf *buf, krb5_trusted_ca *val);
+asn1_error_code asn1_decode_pa_pk_as_req_draft9
+	(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val);
+asn1_error_code asn1_decode_dh_rep_info
+	(asn1buf *buf, krb5_dh_rep_info *val);
+asn1_error_code asn1_decode_pk_authenticator
+	(asn1buf *buf, krb5_pk_authenticator *val);
+asn1_error_code asn1_decode_pk_authenticator_draft9
+	(asn1buf *buf, krb5_pk_authenticator_draft9 *val);
+asn1_error_code asn1_decode_subject_pk_info
+	(asn1buf *buf, krb5_subject_pk_info *val);
+asn1_error_code asn1_decode_algorithm_identifier
+	(asn1buf *buf, krb5_algorithm_identifier *val);
+asn1_error_code asn1_decode_auth_pack
+	(asn1buf *buf, krb5_auth_pack *val);
+asn1_error_code asn1_decode_auth_pack_draft9
+	(asn1buf *buf, krb5_auth_pack_draft9 *val);
+asn1_error_code asn1_decode_pa_pk_as_rep
+	(asn1buf *buf, krb5_pa_pk_as_rep *val);
+asn1_error_code asn1_decode_pa_pk_as_rep_draft9
+	(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val);
+asn1_error_code asn1_decode_kdc_dh_key_info
+        (asn1buf *buf, krb5_kdc_dh_key_info *val);
+asn1_error_code asn1_decode_krb5_principal_name
+	(asn1buf *buf, krb5_principal *val);
+asn1_error_code asn1_decode_reply_key_pack
+        (asn1buf *buf, krb5_reply_key_pack *val);
+asn1_error_code asn1_decode_reply_key_pack_draft9
+        (asn1buf *buf, krb5_reply_key_pack_draft9 *val);
+asn1_error_code asn1_decode_sequence_of_typed_data
+        (asn1buf *buf, krb5_typed_data ***val);
+asn1_error_code asn1_decode_typed_data
+        (asn1buf *buf, krb5_typed_data *val);
+
+/* arrays */
+asn1_error_code asn1_decode_authorization_data
+	(asn1buf *buf, krb5_authdata ***val);
+asn1_error_code asn1_decode_host_addresses
+	(asn1buf *buf, krb5_address ***val);
+asn1_error_code asn1_decode_sequence_of_ticket
+	(asn1buf *buf, krb5_ticket ***val);
+asn1_error_code asn1_decode_sequence_of_krb_cred_info
+	(asn1buf *buf, krb5_cred_info ***val);
+asn1_error_code asn1_decode_sequence_of_pa_data
+	(asn1buf *buf, krb5_pa_data ***val);
+asn1_error_code asn1_decode_last_req
+	(asn1buf *buf, krb5_last_req_entry ***val);
+
+asn1_error_code asn1_decode_sequence_of_enctype
+	(asn1buf *buf, int *num, krb5_enctype **val);
+
+asn1_error_code asn1_decode_sequence_of_checksum
+	(asn1buf *buf, krb5_checksum ***val);
+
+asn1_error_code asn1_decode_sequence_of_passwdsequence
+	(asn1buf *buf, passwd_phrase_element ***val);
+
+asn1_error_code asn1_decode_etype_info
+	(asn1buf *buf, krb5_etype_info_entry ***val);
+asn1_error_code asn1_decode_etype_info2
+	(asn1buf *buf, krb5_etype_info_entry ***val, krb5_boolean v1_3_behavior);
+asn1_error_code asn1_decode_sequence_of_external_principal_identifier
+	(asn1buf *buf, krb5_external_principal_identifier ***val);
+asn1_error_code asn1_decode_sequence_of_trusted_ca
+	(asn1buf *buf, krb5_trusted_ca ***val);
+asn1_error_code asn1_decode_sequence_of_algorithm_identifier
+	(asn1buf *buf, krb5_algorithm_identifier ***val);
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.c b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.c
new file mode 100644
index 000000000..4869ea732
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -0,0 +1,1395 @@
+/*
+ * src/lib/krb5/asn.1/asn1_k_encode.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "asn1_k_encode.h"
+#include "asn1_make.h"
+#include "asn1_encode.h"
+#include <assert.h>
+
+/**** asn1 macros ****/
+#if 0
+   How to write an asn1 encoder function using these macros:
+
+   asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf,
+                                                 const krb5_type *val,
+                                                 int *retlen)
+   {
+     asn1_setup();
+
+     asn1_addfield(val->last_field, n, asn1_type);
+     asn1_addfield(rep->next_to_last_field, n-1, asn1_type);
+     ...
+
+     /* for OPTIONAL fields */
+     if(rep->field_i == should_not_be_omitted)
+       asn1_addfield(rep->field_i, i, asn1_type);
+
+     /* for string fields (these encoders take an additional argument,
+	the length of the string) */
+     addlenfield(rep->field_length, rep->field, i-1, asn1_type);
+
+     /* if you really have to do things yourself... */
+     retval = asn1_encode_asn1_type(buf,rep->field,&length);
+     if(retval) return retval;
+     sum += length;
+     retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length,
+			     &length);
+     if(retval) return retval;
+     sum += length;
+
+     ...
+     asn1_addfield(rep->second_field, 1, asn1_type);
+     asn1_addfield(rep->first_field, 0, asn1_type);
+     asn1_makeseq();
+
+     asn1_cleanup();
+   }
+#endif
+
+/* setup() -- create and initialize bookkeeping variables
+     retval: stores error codes returned from subroutines
+     length: length of the most-recently produced encoding
+     sum: cumulative length of the entire encoding */
+#define asn1_setup()\
+  asn1_error_code retval;\
+  unsigned int length, sum=0
+  
+/* asn1_addfield -- add a field, or component, to the encoding */
+#define asn1_addfield(value,tag,encoder)\
+{ retval = encoder(buf,value,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length;\
+  retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length; }
+
+/* asn1_addlenfield -- add a field whose length must be separately specified */
+#define asn1_addlenfield(len,value,tag,encoder)\
+{ retval = encoder(buf,len,value,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length;\
+  retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length; }
+
+/* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */
+#define asn1_addfield_implicit(value,tag,encoder)\
+{ retval = encoder(buf,value,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length;\
+  retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,length,&length); \
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length; }
+
+/* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */
+#define asn1_insert_implicit_octetstring(len,value,tag)\
+{ retval = asn1buf_insert_octetstring(buf,len,value);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += len;\
+  retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,len,&length); \
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length; }
+
+/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */
+#define asn1_insert_implicit_bitstring(len,value,tag)\
+{ retval = asn1buf_insert_octetstring(buf,len,value);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += len;\
+  retval = asn1buf_insert_octet(buf, 0);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum++;\
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,tag,len+1,&length); \
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length; }
+
+/* form a sequence (by adding a sequence header to the current encoding) */
+#define asn1_makeseq()\
+  retval = asn1_make_sequence(buf,sum,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length
+
+/* add an APPLICATION class tag to the current encoding */
+#define asn1_apptag(num)\
+  retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length
+
+/* produce the final output and clean up the workspace */
+#define asn1_cleanup()\
+  *retlen = sum;\
+  return 0
+
+asn1_error_code asn1_encode_ui_4(asn1buf *buf, const krb5_ui_4 val, unsigned int *retlen)
+{
+  return asn1_encode_unsigned_integer(buf,val,retlen);
+}
+
+
+asn1_error_code asn1_encode_realm(asn1buf *buf, const krb5_principal val, unsigned int *retlen)
+{
+  if (val == NULL ||
+      (val->realm.length && val->realm.data == NULL))
+	  return ASN1_MISSING_FIELD;
+  return asn1_encode_generalstring(buf,val->realm.length,val->realm.data,
+				   retlen);
+}
+
+asn1_error_code asn1_encode_principal_name(asn1buf *buf, const krb5_principal val, unsigned int *retlen)
+{
+  asn1_setup();
+  int n;
+
+  if (val == NULL || val->data == NULL) return ASN1_MISSING_FIELD;
+
+  for(n = (int) ((val->length)-1); n >= 0; n--){
+    if (val->data[n].length &&
+	val->data[n].data == NULL)
+	    return ASN1_MISSING_FIELD;
+    retval = asn1_encode_generalstring(buf,
+				       (val->data)[n].length,
+				       (val->data)[n].data,
+				       &length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+  retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length);
+  if(retval) return retval;
+  sum += length;
+
+  asn1_addfield(val->type,0,asn1_encode_integer);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val, unsigned int *retlen)
+{
+  return asn1_encode_generaltime(buf,val,retlen);
+}
+
+asn1_error_code asn1_encode_host_address(asn1buf *buf, const krb5_address *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
+
+  asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
+  asn1_addfield(val->addrtype,0,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_host_addresses(asn1buf *buf, const krb5_address **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++); /* go to end of array */
+  for(i--; i>=0; i--){
+    retval = asn1_encode_host_address(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_encrypted_data(asn1buf *buf, const krb5_enc_data *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL ||
+     (val->ciphertext.length && val->ciphertext.data == NULL))
+	  return ASN1_MISSING_FIELD;
+
+  asn1_addlenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_encode_charstring);
+  /* krb5_kvno should be int */
+  if(val->kvno)
+    asn1_addfield((int) val->kvno,1,asn1_encode_integer);
+  asn1_addfield(val->enctype,0,asn1_encode_integer);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_krb5_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
+{
+  asn1_setup();
+  krb5_flags valcopy = val;
+  int i;
+
+  for(i=0; i<4; i++){
+    retval = asn1buf_insert_octet(buf,(asn1_octet) (valcopy&0xFF));
+    if(retval) return retval;
+    valcopy >>= 8;
+  }
+  retval = asn1buf_insert_octet(buf,0);	/* 0 padding bits */
+  if(retval) return retval;
+  sum = 5;
+
+  retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_BITSTRING,sum,
+			 &length);
+  if(retval) return retval;
+  sum += length;
+
+  *retlen = sum;
+  return 0;
+}
+
+asn1_error_code asn1_encode_ap_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
+{
+  return asn1_encode_krb5_flags(buf,val,retlen);
+}
+
+asn1_error_code asn1_encode_ticket_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
+{
+  return asn1_encode_krb5_flags(buf,val,retlen);
+}
+
+asn1_error_code asn1_encode_kdc_options(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
+{
+  return asn1_encode_krb5_flags(buf,val,retlen);
+}
+
+asn1_error_code asn1_encode_authorization_data(asn1buf *buf, const krb5_authdata **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+  
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+  
+  for(i=0; val[i] != NULL; i++); /* get to the end of the array */
+  for(i--; i>=0; i--){
+    retval = asn1_encode_krb5_authdata_elt(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_krb5_authdata_elt(asn1buf *buf, const krb5_authdata *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val == NULL ||
+     (val->length && val->contents == NULL))
+	  return ASN1_MISSING_FIELD;
+
+  /* ad-data[1]		OCTET STRING */
+  asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
+  /* ad-type[0]		INTEGER */
+  asn1_addfield(val->ad_type,0,asn1_encode_integer);
+  /* SEQUENCE */
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_kdc_rep(int msg_type, asn1buf *buf, const krb5_kdc_rep *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  asn1_addfield(&(val->enc_part),6,asn1_encode_encrypted_data);
+  asn1_addfield(val->ticket,5,asn1_encode_ticket);
+  asn1_addfield(val->client,4,asn1_encode_principal_name);
+  asn1_addfield(val->client,3,asn1_encode_realm);
+  if(val->padata != NULL && val->padata[0] != NULL)
+    asn1_addfield((const krb5_pa_data**)val->padata,2,asn1_encode_sequence_of_pa_data);
+  if (msg_type != KRB5_AS_REP && msg_type != KRB5_TGS_REP)
+	  return KRB5_BADMSGTYPE;
+  asn1_addfield(msg_type,1,asn1_encode_integer);
+  asn1_addfield(KVNO,0,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_enc_kdc_rep_part(asn1buf *buf, const krb5_enc_kdc_rep_part *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  /* caddr[11]		HostAddresses OPTIONAL */
+  if(val->caddrs != NULL && val->caddrs[0] != NULL)
+    asn1_addfield((const krb5_address**)(val->caddrs),11,asn1_encode_host_addresses);
+
+  /* sname[10]		PrincipalName */
+  asn1_addfield(val->server,10,asn1_encode_principal_name);
+
+  /* srealm[9]		Realm */
+  asn1_addfield(val->server,9,asn1_encode_realm);
+
+  /* renew-till[8]	KerberosTime OPTIONAL */
+  if(val->flags & TKT_FLG_RENEWABLE)
+    asn1_addfield(val->times.renew_till,8,asn1_encode_kerberos_time);
+
+  /* endtime[7]		KerberosTime */
+  asn1_addfield(val->times.endtime,7,asn1_encode_kerberos_time);
+
+  /* starttime[6]	KerberosTime OPTIONAL */
+  if(val->times.starttime)
+    asn1_addfield(val->times.starttime,6,asn1_encode_kerberos_time);
+
+  /* authtime[5]	KerberosTime */
+  asn1_addfield(val->times.authtime,5,asn1_encode_kerberos_time);
+
+  /* flags[4]		TicketFlags */
+  asn1_addfield(val->flags,4,asn1_encode_ticket_flags);
+
+  /* key-expiration[3]	KerberosTime OPTIONAL */
+  if(val->key_exp)
+    asn1_addfield(val->key_exp,3,asn1_encode_kerberos_time);
+
+  /* nonce[2]		INTEGER */
+  asn1_addfield(val->nonce,2,asn1_encode_integer);
+
+  /* last-req[1]	LastReq */
+  asn1_addfield((const krb5_last_req_entry**)val->last_req,1,asn1_encode_last_req);
+
+  /* key[0]		EncryptionKey */
+  asn1_addfield(val->session,0,asn1_encode_encryption_key);
+
+  /* EncKDCRepPart ::= SEQUENCE */
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_checksum(asn1buf *buf, const krb5_checksum ** val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  for (i=0; val[i] != NULL; i++);
+  for (i--; i>=0; i--){
+    retval = asn1_encode_checksum(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *rep, unsigned int *retlen)
+{
+  asn1_setup();
+  
+  if(rep == NULL) return ASN1_MISSING_FIELD;
+
+  /* additional-tickets[11]	SEQUENCE OF Ticket OPTIONAL */
+  if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL)
+    asn1_addfield((const krb5_ticket**)rep->second_ticket,
+		  11,asn1_encode_sequence_of_ticket);
+
+  /* enc-authorization-data[10]	EncryptedData OPTIONAL, */
+  /* 				-- Encrypted AuthorizationData encoding */
+  if(rep->authorization_data.ciphertext.data != NULL)
+    asn1_addfield(&(rep->authorization_data),10,asn1_encode_encrypted_data);
+
+  /* addresses[9]		HostAddresses OPTIONAL, */
+  if(rep->addresses != NULL && rep->addresses[0] != NULL)
+    asn1_addfield((const krb5_address**)rep->addresses,9,asn1_encode_host_addresses);
+
+  /* etype[8]			SEQUENCE OF INTEGER, -- EncryptionType, */
+  /* 				-- in preference order */
+  asn1_addlenfield(rep->nktypes,rep->ktype,8,asn1_encode_sequence_of_enctype);
+
+  /* nonce[7]			INTEGER, */
+  asn1_addfield(rep->nonce,7,asn1_encode_integer);
+
+  /* rtime[6]			KerberosTime OPTIONAL, */
+  if(rep->rtime)
+    asn1_addfield(rep->rtime,6,asn1_encode_kerberos_time);
+
+  /* till[5]			KerberosTime, */
+  asn1_addfield(rep->till,5,asn1_encode_kerberos_time);
+
+  /* from[4]			KerberosTime OPTIONAL, */
+  if(rep->from)
+  asn1_addfield(rep->from,4,asn1_encode_kerberos_time);
+
+  /* sname[3]			PrincipalName OPTIONAL, */
+  if(rep->server != NULL)
+    asn1_addfield(rep->server,3,asn1_encode_principal_name);
+
+  /* realm[2]			Realm, -- Server's realm */
+  /* 				-- Also client's in AS-REQ */
+  if(rep->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY){
+    if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL){
+      asn1_addfield(rep->second_ticket[0]->server,2,asn1_encode_realm)
+    } else return ASN1_MISSING_FIELD;
+  }else if(rep->server != NULL){
+    asn1_addfield(rep->server,2,asn1_encode_realm);
+  }else return ASN1_MISSING_FIELD;
+
+  /* cname[1]			PrincipalName OPTIONAL, */
+  /* 				-- Used only in AS-REQ */
+  if(rep->client != NULL)
+    asn1_addfield(rep->client,1,asn1_encode_principal_name);
+
+  /* kdc-options[0]		KDCOptions, */
+  asn1_addfield(rep->kdc_options,0,asn1_encode_kdc_options);
+
+  /* KDC-REQ-BODY ::= SEQUENCE */
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_encryption_key(asn1buf *buf, const krb5_keyblock *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val == NULL ||
+      (val->length && val->contents == NULL))
+	  return ASN1_MISSING_FIELD;
+
+  asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
+  asn1_addfield(val->enctype,0,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_checksum(asn1buf *buf, const krb5_checksum *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val == NULL ||
+     (val->length && val->contents == NULL))
+	  return ASN1_MISSING_FIELD;
+
+  asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
+  asn1_addfield(val->checksum_type,0,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_transited_encoding(asn1buf *buf, const krb5_transited *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL ||
+     (val->tr_contents.length != 0 && val->tr_contents.data == NULL))
+    return ASN1_MISSING_FIELD;
+
+  asn1_addlenfield(val->tr_contents.length,val->tr_contents.data,
+		   1,asn1_encode_charstring);
+  asn1_addfield(val->tr_type,0,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_last_req(asn1buf *buf, const krb5_last_req_entry **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++); /* go to end of array */
+  for(i--; i>=0; i--){
+    retval = asn1_encode_last_req_entry(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_last_req_entry(asn1buf *buf, const krb5_last_req_entry *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  asn1_addfield(val->value,1,asn1_encode_kerberos_time);
+  asn1_addfield(val->lr_type,0,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_pa_data(asn1buf *buf, const krb5_pa_data **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if (val == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++);
+  for(i--; i>=0; i--){
+    retval = asn1_encode_pa_data(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_data(asn1buf *buf, const krb5_pa_data *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL || (val->length != 0 && val->contents == NULL))
+     return ASN1_MISSING_FIELD;
+
+  asn1_addlenfield(val->length,val->contents,2,asn1_encode_octetstring);
+  asn1_addfield(val->pa_type,1,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_ticket(asn1buf *buf, const krb5_ticket **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++);
+  for(i--; i>=0; i--){
+    retval = asn1_encode_ticket(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_ticket(asn1buf *buf, const krb5_ticket *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  asn1_addfield(&(val->enc_part),3,asn1_encode_encrypted_data);
+  asn1_addfield(val->server,2,asn1_encode_principal_name);
+  asn1_addfield(val->server,1,asn1_encode_realm);
+  asn1_addfield(KVNO,0,asn1_encode_integer);
+  asn1_makeseq();
+  asn1_apptag(1);
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_enctype(asn1buf *buf, const int len, const krb5_enctype *val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=len-1; i>=0; i--){
+    retval = asn1_encode_integer(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_kdc_req(int msg_type, asn1buf *buf, const krb5_kdc_req *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  asn1_addfield(val,4,asn1_encode_kdc_req_body);
+  if(val->padata != NULL && val->padata[0] != NULL)
+    asn1_addfield((const krb5_pa_data**)val->padata,3,asn1_encode_sequence_of_pa_data);
+  if (msg_type != KRB5_AS_REQ && msg_type != KRB5_TGS_REQ)
+	  return KRB5_BADMSGTYPE;
+  asn1_addfield(msg_type,2,asn1_encode_integer);
+  asn1_addfield(KVNO,1,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_krb_safe_body(asn1buf *buf, const krb5_safe *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  if(val->r_address != NULL)
+    asn1_addfield(val->r_address,5,asn1_encode_host_address);
+  asn1_addfield(val->s_address,4,asn1_encode_host_address);
+  if(val->seq_number)
+    asn1_addfield(val->seq_number,3,asn1_encode_unsigned_integer);
+  if(val->timestamp){
+    asn1_addfield(val->usec,2,asn1_encode_integer);
+    asn1_addfield(val->timestamp,1,asn1_encode_kerberos_time);
+  }
+  if (val->user_data.length && val->user_data.data == NULL)
+	  return ASN1_MISSING_FIELD;
+  asn1_addlenfield(val->user_data.length,val->user_data.data,0,asn1_encode_charstring)
+;
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_krb_cred_info(asn1buf *buf, const krb5_cred_info **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++);
+  for(i--; i>=0; i--){
+    retval = asn1_encode_krb_cred_info(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_krb_cred_info(asn1buf *buf, const krb5_cred_info *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if(val == NULL) return ASN1_MISSING_FIELD;
+
+  if(val->caddrs != NULL && val->caddrs[0] != NULL)
+    asn1_addfield((const krb5_address**)val->caddrs,10,asn1_encode_host_addresses);
+  if(val->server != NULL){
+    asn1_addfield(val->server,9,asn1_encode_principal_name);
+    asn1_addfield(val->server,8,asn1_encode_realm);
+  }
+  if(val->times.renew_till)
+    asn1_addfield(val->times.renew_till,7,asn1_encode_kerberos_time);
+  if(val->times.endtime)
+    asn1_addfield(val->times.endtime,6,asn1_encode_kerberos_time);
+  if(val->times.starttime)
+    asn1_addfield(val->times.starttime,5,asn1_encode_kerberos_time);
+  if(val->times.authtime)
+    asn1_addfield(val->times.authtime,4,asn1_encode_kerberos_time);
+  if(val->flags)
+    asn1_addfield(val->flags,3,asn1_encode_ticket_flags);
+  if(val->client != NULL){
+    asn1_addfield(val->client,2,asn1_encode_principal_name);
+    asn1_addfield(val->client,1,asn1_encode_realm);
+  }
+  asn1_addfield(val->session,0,asn1_encode_encryption_key);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_etype_info_entry(asn1buf *buf, const krb5_etype_info_entry *val,
+					     unsigned int *retlen, int etype_info2)
+{
+  asn1_setup();
+
+  assert(val->s2kparams.data == NULL || etype_info2);
+  if(val == NULL || (val->length > 0 && val->length != KRB5_ETYPE_NO_SALT &&
+		     val->salt == NULL))
+     return ASN1_MISSING_FIELD;
+  if(val->s2kparams.data != NULL)
+      asn1_addlenfield(val->s2kparams.length, val->s2kparams.data, 2,
+		       asn1_encode_octetstring);
+  if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT){
+      if (etype_info2)
+	  asn1_addlenfield(val->length,val->salt,1,
+			   asn1_encode_generalstring)
+      else 	  asn1_addlenfield(val->length,val->salt,1,
+				   asn1_encode_octetstring);
+  }
+asn1_addfield(val->etype,0,asn1_encode_integer);
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_etype_info(asn1buf *buf, const krb5_etype_info_entry **val,
+				       unsigned int *retlen, int etype_info2)
+{
+    asn1_setup();
+    int i;
+  
+    if (val == NULL) return ASN1_MISSING_FIELD;
+  
+    for(i=0; val[i] != NULL; i++); /* get to the end of the array */
+    for(i--; i>=0; i--){
+	retval = asn1_encode_etype_info_entry(buf,val[i],&length, etype_info2);
+	if(retval) return retval;
+	sum += length;
+    }
+    asn1_makeseq();
+    asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_passwdsequence(asn1buf *buf, const passwd_phrase_element **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+  
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+  
+  for(i=0; val[i] != NULL; i++); /* get to the end of the array */
+  for(i--; i>=0; i--){
+    retval = asn1_encode_passwdsequence(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_passwdsequence(asn1buf *buf, const passwd_phrase_element *val, unsigned int *retlen)
+{
+  asn1_setup();
+  asn1_addlenfield(val->phrase->length,val->phrase->data,1,asn1_encode_charstring);
+  asn1_addlenfield(val->passwd->length,val->passwd->data,0,asn1_encode_charstring);
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sam_flags(asn1buf *buf, const krb5_flags val, unsigned int *retlen)
+{
+  return asn1_encode_krb5_flags(buf,val,retlen);
+}
+
+#define add_optstring(val,n,fn) \
+     if ((val).length > 0) {asn1_addlenfield((val).length,(val).data,n,fn);}
+
+asn1_error_code asn1_encode_sam_challenge(asn1buf *buf, const krb5_sam_challenge *val, unsigned int *retlen)
+{
+  asn1_setup();
+  /* possibly wrong */
+  if (val->sam_cksum.length)
+    asn1_addfield(&(val->sam_cksum),9,asn1_encode_checksum);
+
+  if (val->sam_nonce)
+    asn1_addfield(val->sam_nonce,8,asn1_encode_integer);
+
+  add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring);
+  add_optstring(val->sam_response_prompt,6,asn1_encode_charstring);
+  add_optstring(val->sam_challenge,5,asn1_encode_charstring);
+  add_optstring(val->sam_challenge_label,4,asn1_encode_charstring);
+  add_optstring(val->sam_track_id,3,asn1_encode_charstring);
+  add_optstring(val->sam_type_name,2,asn1_encode_charstring);
+
+  asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
+  asn1_addfield(val->sam_type,0,asn1_encode_integer);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val, unsigned int *retlen)
+{
+  asn1_setup();
+  if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0]))
+      return ASN1_MISSING_FIELD;
+
+  asn1_addfield((const krb5_checksum **) val->sam_cksum, 1, asn1_encode_sequence_of_checksum);
+  retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length,
+				      (unsigned char *)val->sam_challenge_2_body.data);
+  if(retval){
+	  asn1buf_destroy(&buf);
+	  return retval; 
+  }
+  sum += val->sam_challenge_2_body.length;
+  retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0,
+			  val->sam_challenge_2_body.length, &length);
+  if(retval) {
+	  asn1buf_destroy(&buf);
+	  return retval;
+  }
+  sum += length;
+  
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sam_challenge_2_body(asn1buf *buf, const krb5_sam_challenge_2_body *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  asn1_addfield(val->sam_etype, 9, asn1_encode_integer);
+  asn1_addfield(val->sam_nonce,8,asn1_encode_integer);
+  add_optstring(val->sam_pk_for_sad,7,asn1_encode_charstring);
+  add_optstring(val->sam_response_prompt,6,asn1_encode_charstring);
+  add_optstring(val->sam_challenge,5,asn1_encode_charstring);
+  add_optstring(val->sam_challenge_label,4,asn1_encode_charstring);
+  add_optstring(val->sam_track_id,3,asn1_encode_charstring);
+  add_optstring(val->sam_type_name,2,asn1_encode_charstring);
+
+  asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
+  asn1_addfield(val->sam_type,0,asn1_encode_integer);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sam_key(asn1buf *buf, const krb5_sam_key *val, unsigned int *retlen)
+{
+  asn1_setup();
+  asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+
+asn1_error_code asn1_encode_enc_sam_response_enc(asn1buf *buf, const krb5_enc_sam_response_enc *val, unsigned int *retlen)
+{
+  asn1_setup();
+  add_optstring(val->sam_sad,3,asn1_encode_charstring);
+  asn1_addfield(val->sam_usec,2,asn1_encode_integer);
+  asn1_addfield(val->sam_timestamp,1,asn1_encode_kerberos_time);
+  asn1_addfield(val->sam_nonce,0,asn1_encode_integer);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_enc_sam_response_enc_2(asn1buf *buf, const krb5_enc_sam_response_enc_2 *val, unsigned int *retlen)
+{
+  asn1_setup();
+  add_optstring(val->sam_sad,1,asn1_encode_charstring);
+  asn1_addfield(val->sam_nonce,0,asn1_encode_integer);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sam_response(asn1buf *buf, const krb5_sam_response *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->sam_patimestamp)
+    asn1_addfield(val->sam_patimestamp,6,asn1_encode_kerberos_time);
+  if (val->sam_nonce)
+    asn1_addfield(val->sam_nonce,5,asn1_encode_integer);
+  asn1_addfield(&(val->sam_enc_nonce_or_ts),4,asn1_encode_encrypted_data);
+  if (val->sam_enc_key.ciphertext.length)
+    asn1_addfield(&(val->sam_enc_key),3,asn1_encode_encrypted_data);
+  add_optstring(val->sam_track_id,2,asn1_encode_charstring);
+  asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
+  asn1_addfield(val->sam_type,0,asn1_encode_integer);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sam_response_2(asn1buf *buf, const krb5_sam_response_2 *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  asn1_addfield(val->sam_nonce,4,asn1_encode_integer);
+  asn1_addfield(&(val->sam_enc_nonce_or_sad),3,asn1_encode_encrypted_data);
+  add_optstring(val->sam_track_id,2,asn1_encode_charstring);
+  asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
+  asn1_addfield(val->sam_type,0,asn1_encode_integer);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_predicted_sam_response(asn1buf *buf, const krb5_predicted_sam_response *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  add_optstring(val->msd,6,asn1_encode_charstring);
+  asn1_addfield(val->client,5,asn1_encode_principal_name);
+  asn1_addfield(val->client,4,asn1_encode_realm);
+  asn1_addfield(val->susec,3,asn1_encode_integer);
+  asn1_addfield(val->stime,2,asn1_encode_kerberos_time);
+  asn1_addfield(val->sam_flags,1,asn1_encode_sam_flags);
+  asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key);
+
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+/*
+ * Do some ugliness to insert a raw pre-encoded KRB-SAFE-BODY.
+ */
+asn1_error_code asn1_encode_krb_saved_safe_body(asn1buf *buf, const krb5_data *body, unsigned int *retlen)
+{
+  asn1_error_code retval;
+
+  retval = asn1buf_insert_octetstring(buf, body->length,
+				      (krb5_octet *)body->data);
+  if (retval){
+    asn1buf_destroy(&buf);
+    return retval; 
+  }
+  *retlen = body->length;
+  return 0;
+}
+
+/*
+ * PKINIT
+ */
+
+asn1_error_code asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen)
+{
+  asn1_setup();
+  asn1_addlenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_encode_octetstring);
+  asn1_addfield(val->nonce, 2, asn1_encode_integer);
+  asn1_addfield(val->ctime, 1, asn1_encode_kerberos_time);
+  asn1_addfield(val->cusec, 0, asn1_encode_integer);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pk_authenticator_draft9(asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  asn1_addfield(val->nonce, 4, asn1_encode_integer);
+  asn1_addfield(val->ctime, 3, asn1_encode_kerberos_time);
+  asn1_addfield(val->cusec, 2, asn1_encode_integer);
+  asn1_addfield(val->kdcName, 1, asn1_encode_realm);
+  asn1_addfield(val->kdcName, 0, asn1_encode_principal_name);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+
+asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->parameters.length != 0) {
+    retval = asn1buf_insert_octetstring(buf, val->parameters.length, 
+					val->parameters.data);
+    if(retval) {
+      asn1buf_destroy(&buf);
+      return retval;
+    }
+    sum += val->parameters.length;
+  }
+  
+  retval = asn1_encode_oid(buf, val->algorithm.length, 
+			   val->algorithm.data,
+			   &length);
+  
+  if(retval) {
+    asn1buf_destroy(&buf);
+    return retval;
+  }
+  sum += length;  
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING);
+
+  if (val->algorithm.parameters.length != 0) {
+    retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length, 
+					val->algorithm.parameters.data);
+    if(retval) {
+      asn1buf_destroy(&buf);
+      return retval;
+    }
+    sum += val->algorithm.parameters.length;
+  }
+  
+  retval = asn1_encode_oid(buf, val->algorithm.algorithm.length, 
+			   val->algorithm.algorithm.data,
+			   &length);
+  
+  if(retval) {
+    asn1buf_destroy(&buf);
+    return retval;
+  }
+  sum += length;  
+  
+  retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, 
+			  val->algorithm.parameters.length + length, 
+			  &length);
+
+  if(retval) {
+    asn1buf_destroy(&buf);
+    return retval;
+  }
+  sum += length;  
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++);
+  for(i--; i>=0; i--){
+    retval = asn1_encode_algorithm_identifier(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->clientDHNonce.length != 0)
+    asn1_addlenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_encode_octetstring);
+  if (val->supportedCMSTypes != NULL)
+    asn1_addfield((const krb5_algorithm_identifier **)val->supportedCMSTypes,2,asn1_encode_sequence_of_algorithm_identifier);
+  if (val->clientPublicValue != NULL)
+    asn1_addfield(val->clientPublicValue,1,asn1_encode_subject_pk_info);
+  asn1_addfield(&(val->pkAuthenticator),0,asn1_encode_pk_authenticator);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_auth_pack_draft9(asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->clientPublicValue != NULL)
+    asn1_addfield(val->clientPublicValue, 1, asn1_encode_subject_pk_info);
+  asn1_addfield(&(val->pkAuthenticator), 0, asn1_encode_pk_authenticator_draft9);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  /* Verify there is something to encode */
+  if (val->subjectKeyIdentifier.length == 0 && val->issuerAndSerialNumber.length == 0 && val->subjectName.length == 0)
+    return ASN1_MISSING_FIELD;
+
+  if (val->subjectKeyIdentifier.length != 0) 
+    asn1_insert_implicit_octetstring(val->subjectKeyIdentifier.length,val->subjectKeyIdentifier.data,2);
+
+  if (val->issuerAndSerialNumber.length != 0) 
+    asn1_insert_implicit_octetstring(val->issuerAndSerialNumber.length,val->issuerAndSerialNumber.data,1);
+
+  if (val->subjectName.length != 0) 
+    asn1_insert_implicit_octetstring(val->subjectName.length,val->subjectName.data,0);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++);
+  for(i--; i>=0; i--){
+    retval = asn1_encode_external_principal_identifier(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_req(asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->kdcPkId.length != 0) 
+    asn1_insert_implicit_octetstring(val->kdcPkId.length,val->kdcPkId.data,2);
+
+  if (val->trustedCertifiers != NULL)
+    asn1_addfield((const krb5_external_principal_identifier **)val->trustedCertifiers,1,asn1_encode_sequence_of_external_principal_identifier);
+
+  asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_trusted_ca(asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  switch (val->choice) {
+    case choice_trusted_cas_issuerAndSerial:
+      asn1_insert_implicit_octetstring(val->u.issuerAndSerial.length,val->u.issuerAndSerial.data,2);
+      break;
+    case choice_trusted_cas_caName:
+      asn1_insert_implicit_octetstring(val->u.caName.length,val->u.caName.data,1);
+      break;
+    case choice_trusted_cas_principalName:
+      asn1_addfield_implicit(val->u.principalName,0,asn1_encode_principal_name);
+      break;
+    default:
+      return ASN1_MISSING_FIELD;
+  }
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_trusted_ca(asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++);
+  for(i--; i>=0; i--){
+    retval = asn1_encode_trusted_ca(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_req_draft9(asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->encryptionCert.length != 0)
+    asn1_insert_implicit_octetstring(val->encryptionCert.length,val->encryptionCert.data,3);
+
+  if (val->kdcCert.length != 0) 
+    asn1_insert_implicit_octetstring(val->kdcCert.length,val->kdcCert.data,2);
+
+  if (val->trustedCertifiers != NULL)
+    asn1_addfield((const krb5_trusted_ca **)val->trustedCertifiers,1,asn1_encode_sequence_of_trusted_ca);
+
+  asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_dh_rep_info(asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->serverDHNonce.length != 0)
+    asn1_insert_implicit_octetstring(val->serverDHNonce.length,val->serverDHNonce.data,1);
+  
+  asn1_insert_implicit_octetstring(val->dhSignedData.length,val->dhSignedData.data,0);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  if (val->dhKeyExpiration != 0) 
+    asn1_addfield(val->dhKeyExpiration, 2, asn1_encode_kerberos_time);
+  asn1_addfield(val->nonce, 1, asn1_encode_integer);
+
+  asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,3);
+  retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, 
+			  val->subjectPublicKey.length + 1 + length,
+			  &length);
+  if(retval) {
+    asn1buf_destroy(&buf);
+    return retval;
+  }
+  sum += length; 
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_reply_key_pack(asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  asn1_addfield(&(val->asChecksum), 1, asn1_encode_checksum);
+  asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_reply_key_pack_draft9(asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  asn1_addfield(val->nonce, 1, asn1_encode_integer);
+  asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
+
+  asn1_makeseq();
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_rep(asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  switch (val->choice)
+  {
+    case choice_pa_pk_as_rep_dhInfo:
+      asn1_addfield(&(val->u.dh_Info), choice_pa_pk_as_rep_dhInfo, asn1_encode_dh_rep_info);
+      break;
+    case choice_pa_pk_as_rep_encKeyPack:
+      asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
+      break;
+    default:
+      return ASN1_MISSING_FIELD;
+  }
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_rep_draft9(asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen)
+{
+  asn1_setup();
+
+  switch (val->choice)
+  {
+    case choice_pa_pk_as_rep_draft9_dhSignedData:
+      asn1_insert_implicit_octetstring(val->u.dhSignedData.length,val->u.dhSignedData.data,0);
+      break;
+    case choice_pa_pk_as_rep_encKeyPack:
+      asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
+      break;
+    default:
+      return ASN1_MISSING_FIELD;
+  }
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_td_trusted_certifiers(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
+{
+  asn1_setup();
+  retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length);
+  if (retval) {
+    asn1buf_destroy(&buf);
+    return retval;
+  }
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_typed_data(asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen)
+{
+  asn1_setup();
+  int i;
+
+  if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+  for(i=0; val[i] != NULL; i++);
+  for(i--; i>=0; i--){
+    retval = asn1_encode_typed_data(buf,val[i],&length);
+    if(retval) return retval;
+    sum += length;
+  }
+  asn1_makeseq();
+
+  asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_typed_data(asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen)
+{
+  asn1_setup();
+  asn1_addlenfield(val->length, val->data, 1, asn1_encode_octetstring);
+  asn1_addfield(val->type, 0, asn1_encode_integer);
+  asn1_makeseq();
+  asn1_cleanup();
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.h b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.h
new file mode 100644
index 000000000..b5f24c42b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_k_encode.h
@@ -0,0 +1,339 @@
+/*
+ * src/lib/krb5/asn.1/asn1_k_encode.h
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __ASN1_ENCODE_KRB5_H__
+#define __ASN1_ENCODE_KRB5_H__
+
+#include "k5-int.h"
+#include <stdio.h>
+#include "asn1buf.h"
+
+/*
+   Overview
+
+     Encoding routines for various ASN.1 "substructures" as defined in
+     the krb5 protocol.
+
+   Operations
+
+    asn1_encode_krb5_flags
+    asn1_encode_ap_options
+    asn1_encode_ticket_flags
+    asn1_encode_kdc_options
+    asn1_encode_kerberos_time
+
+    asn1_encode_realm
+    asn1_encode_principal_name
+    asn1_encode_encrypted_data
+    asn1_encode_authorization_data
+    asn1_encode_krb5_authdata_elt
+    asn1_encode_kdc_rep
+    asn1_encode_ticket
+    asn1_encode_encryption_key
+    asn1_encode_checksum
+    asn1_encode_host_address
+    asn1_encode_transited_encoding
+    asn1_encode_enc_kdc_rep_part
+    asn1_encode_kdc_req
+    asn1_encode_kdc_req_body
+    asn1_encode_krb_safe_body
+    asn1_encode_krb_cred_info
+    asn1_encode_last_req_entry
+    asn1_encode_pa_data
+
+    asn1_encode_host_addresses
+    asn1_encode_last_req
+    asn1_encode_sequence_of_pa_data
+    asn1_encode_sequence_of_ticket
+    asn1_encode_sequence_of_enctype
+    asn1_encode_sequence_of_checksum
+    asn1_encode_sequence_of_krb_cred_info
+*/
+
+/*
+**** for simple val's ****
+asn1_error_code asn1_encode_asn1_type(asn1buf *buf,
+                                      const krb5_type val,
+				      int *retlen);
+   requires  *buf is allocated
+   effects   Inserts the encoding of val into *buf and
+              returns the length of this encoding in *retlen.
+	     Returns ASN1_MISSING_FIELD if a required field is empty in val.
+	     Returns ENOMEM if memory runs out.
+
+**** for struct val's ****
+asn1_error_code asn1_encode_asn1_type(asn1buf *buf,
+                                      const krb5_type *val,
+				      int *retlen);
+   requires  *buf is allocated
+   effects   Inserts the encoding of *val into *buf and
+              returns the length of this encoding in *retlen.
+	     Returns ASN1_MISSING_FIELD if a required field is empty in val.
+	     Returns ENOMEM if memory runs out.
+
+**** for array val's ****
+asn1_error_code asn1_encode_asn1_type(asn1buf *buf,
+                                      const krb5_type **val,
+				      int *retlen);
+   requires  *buf is allocated, **val != NULL, *val[0] != NULL,
+              **val is a NULL-terminated array of pointers to krb5_type
+   effects   Inserts the encoding of **val into *buf and
+              returns the length of this encoding in *retlen.
+	     Returns ASN1_MISSING_FIELD if a required field is empty in val.
+	     Returns ENOMEM if memory runs out.
+*/
+
+asn1_error_code asn1_encode_ui_4 (asn1buf *buf,
+					    const krb5_ui_4 val,
+					    unsigned int *retlen);
+
+asn1_error_code asn1_encode_msgtype (asn1buf *buf,
+					       const /*krb5_msgtype*/int val,
+					       unsigned int *retlen);
+
+asn1_error_code asn1_encode_realm
+	(asn1buf *buf, const krb5_principal val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_principal_name
+	(asn1buf *buf, const krb5_principal val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_encrypted_data
+	(asn1buf *buf, const krb5_enc_data *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_krb5_flags
+	(asn1buf *buf, const krb5_flags val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_ap_options
+	(asn1buf *buf, const krb5_flags val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_ticket_flags
+	(asn1buf *buf, const krb5_flags val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_kdc_options
+	(asn1buf *buf, const krb5_flags val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_authorization_data
+	(asn1buf *buf, const krb5_authdata **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_krb5_authdata_elt
+	(asn1buf *buf, const krb5_authdata *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_kdc_rep
+	(int msg_type, asn1buf *buf, const krb5_kdc_rep *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_enc_kdc_rep_part
+	(asn1buf *buf, const krb5_enc_kdc_rep_part *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_ticket
+	(asn1buf *buf, const krb5_ticket *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_encryption_key
+	(asn1buf *buf, const krb5_keyblock *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_kerberos_time
+	(asn1buf *buf, const krb5_timestamp val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_checksum
+	(asn1buf *buf, const krb5_checksum *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_host_address
+	(asn1buf *buf, const krb5_address *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_host_addresses
+	(asn1buf *buf, const krb5_address **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_transited_encoding
+	(asn1buf *buf, const krb5_transited *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_last_req
+	(asn1buf *buf, const krb5_last_req_entry **val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_pa_data
+	(asn1buf *buf, const krb5_pa_data **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_ticket
+	(asn1buf *buf, const krb5_ticket **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_enctype
+	(asn1buf *buf,
+		   const int len, const krb5_enctype *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_checksum
+	(asn1buf *buf, const krb5_checksum **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_kdc_req
+	(int msg_type,
+		   asn1buf *buf,
+		   const krb5_kdc_req *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_kdc_req_body
+	(asn1buf *buf, const krb5_kdc_req *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_krb_safe_body
+	(asn1buf *buf, const krb5_safe *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_krb_cred_info
+	(asn1buf *buf, const krb5_cred_info **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_krb_cred_info
+	(asn1buf *buf, const krb5_cred_info *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_last_req_entry
+	(asn1buf *buf, const krb5_last_req_entry *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_data
+	(asn1buf *buf, const krb5_pa_data *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_alt_method
+	(asn1buf *buf, const krb5_alt_method *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_etype_info_entry
+	(asn1buf *buf, const krb5_etype_info_entry *val,
+		   unsigned int *retlen, int etype_info2);
+
+asn1_error_code asn1_encode_etype_info
+	(asn1buf *buf, const krb5_etype_info_entry **val,
+		   unsigned int *retlen, int etype_info2);
+
+asn1_error_code asn1_encode_passwdsequence
+	(asn1buf *buf, const passwd_phrase_element *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_passwdsequence
+	(asn1buf *buf, const passwd_phrase_element **val,
+	unsigned int *retlen);
+
+asn1_error_code asn1_encode_sam_flags
+	(asn1buf * buf, const krb5_flags val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sam_challenge
+	(asn1buf *buf, const krb5_sam_challenge * val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sam_challenge_2
+	(asn1buf *buf, const krb5_sam_challenge_2 * val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sam_challenge_2_body
+	(asn1buf *buf, const krb5_sam_challenge_2_body * val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_sam_key
+	(asn1buf *buf, const krb5_sam_key *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_enc_sam_response_enc
+	(asn1buf *buf, const krb5_enc_sam_response_enc *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_enc_sam_response_enc_2
+	(asn1buf *buf, const krb5_enc_sam_response_enc_2 *val,
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_sam_response
+	(asn1buf *buf, const krb5_sam_response *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sam_response_2
+	(asn1buf *buf, const krb5_sam_response_2 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_predicted_sam_response
+	(asn1buf *buf, const krb5_predicted_sam_response *val, 
+		   unsigned int *retlen);
+
+asn1_error_code asn1_encode_krb_saved_safe_body
+	(asn1buf *buf, const krb5_data *body, unsigned int *retlen);
+
+/* PKINIT */
+
+asn1_error_code asn1_encode_pk_authenticator
+	(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pk_authenticator_draft9
+	(asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_algorithm_identifier
+	(asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_subject_pk_info
+	(asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_algorithm_identifier
+	(asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_auth_pack
+	(asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_auth_pack_draft9
+	(asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_external_principal_identifier
+	(asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_external_principal_identifier
+	(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_req
+	(asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_trusted_ca
+	(asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_trusted_ca
+	(asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_req_draft9
+	(asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_dh_rep_info
+	(asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_kdc_dh_key_info
+	(asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_reply_key_pack
+	(asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_reply_key_pack_draft9
+	(asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_rep
+	(asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_rep_draft9
+	(asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_td_trusted_certifiers
+	(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_typed_data
+	(asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_typed_data
+	(asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen);
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_make.c b/krb5-1-6/src/lib/krb5/asn.1/asn1_make.c
new file mode 100644
index 000000000..dddf2da8f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_make.c
@@ -0,0 +1,160 @@
+/*
+ * src/lib/krb5/asn.1/asn1_make.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "asn1_make.h"
+
+asn1_error_code asn1_make_etag(asn1buf *buf, asn1_class asn1class,
+			       asn1_tagnum tagnum, unsigned int in_len,
+			       unsigned int *retlen)
+{
+  return asn1_make_tag(buf,asn1class,CONSTRUCTED,tagnum,in_len,retlen);
+}
+
+
+asn1_error_code asn1_make_tag(asn1buf *buf, asn1_class asn1class,
+			      asn1_construction construction,
+			      asn1_tagnum tagnum, unsigned int in_len,
+			      unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int sumlen=0, length;
+
+  if(tagnum > ASN1_TAGNUM_MAX) return ASN1_OVERFLOW;
+
+  retval = asn1_make_length(buf,in_len, &length);
+  if(retval) return retval;
+  sumlen += length;
+  retval = asn1_make_id(buf,asn1class,construction,tagnum,&length);
+  if(retval) return retval;
+  sumlen += length;
+
+  *retlen = sumlen;
+  return 0;
+}
+
+asn1_error_code asn1_make_length(asn1buf *buf, const unsigned int in_len, unsigned int *retlen)
+{
+  asn1_error_code retval;
+
+  if(in_len < 128){
+    retval = asn1buf_insert_octet(buf, (asn1_octet)(in_len&0x7F));
+    if(retval) return retval;
+    *retlen = 1;
+  }else{
+    int in_copy=in_len, length=0;
+
+    while(in_copy != 0){
+      retval = asn1buf_insert_octet(buf, (asn1_octet)(in_copy&0xFF));
+      if(retval) return retval;
+      in_copy = in_copy >> 8;
+      length++;
+    }
+    retval = asn1buf_insert_octet(buf, (asn1_octet) (0x80 | (asn1_octet)(length&0x7F)));
+    if(retval) return retval;
+    length++;
+    *retlen = length;
+  }
+
+  return 0;
+}
+
+asn1_error_code asn1_make_id(asn1buf *buf, asn1_class asn1class,
+			     asn1_construction construction,
+			     asn1_tagnum tagnum, unsigned int *retlen)
+{
+  asn1_error_code retval;
+
+  if(tagnum < 31) {
+    retval = asn1buf_insert_octet(buf, (asn1_octet) (asn1class | construction |
+						     (asn1_octet)tagnum));
+    if(retval) return retval;
+    *retlen = 1;
+  }else{
+    asn1_tagnum tagcopy = tagnum;
+    int length = 0;
+
+    retval = asn1buf_insert_octet(buf, (asn1_octet)(tagcopy&0x7F));
+    if(retval) return retval;
+    tagcopy >>= 7;
+    length++;
+
+    for(; tagcopy != 0; tagcopy >>= 7){
+      retval = asn1buf_insert_octet(buf, (asn1_octet) (0x80 | (asn1_octet)(tagcopy&0x7F)));
+      if(retval) return retval;
+      length++;
+    }
+
+    retval = asn1buf_insert_octet(buf, (asn1_octet) (asn1class | construction | 0x1F));
+    if(retval) return retval;
+    length++;
+    *retlen = length;
+  }
+
+  return 0;
+}
+
+asn1_error_code asn1_make_sequence(asn1buf *buf, const unsigned int seq_len, unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int len, sum=0;
+
+  retval = asn1_make_length(buf,seq_len,&len);
+  if(retval) return retval;
+  sum += len;
+  retval = asn1_make_id(buf,UNIVERSAL,CONSTRUCTED,ASN1_SEQUENCE,&len);
+  if(retval) return retval;
+  sum += len;
+
+  *retlen = sum;
+  return 0;
+}
+
+asn1_error_code asn1_make_set(asn1buf *buf, const unsigned int set_len, unsigned int *retlen)
+{
+  asn1_error_code retval;
+  unsigned int len, sum=0;
+
+  retval = asn1_make_length(buf,set_len,&len);
+  if(retval) return retval;
+  sum += len;
+  retval = asn1_make_id(buf,UNIVERSAL,CONSTRUCTED,ASN1_SET,&len);
+  if(retval) return retval;
+  sum += len;
+
+  *retlen = sum;
+  return 0;
+}
+
+asn1_error_code asn1_make_string(asn1buf *buf, const unsigned int length, const char *string, int *retlen)
+{
+  asn1_error_code retval;
+
+  retval = asn1buf_insert_charstring(buf,length,string);
+  if(retval) return retval;
+
+  *retlen = length;
+  return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_make.h b/krb5-1-6/src/lib/krb5/asn.1/asn1_make.h
new file mode 100644
index 000000000..715054908
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_make.h
@@ -0,0 +1,134 @@
+/*
+ * src/lib/krb5/asn.1/asn1_make.h
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __ASN1_MAKE_H__
+#define __ASN1_MAKE_H__
+
+#include "k5-int.h"
+#include "krbasn1.h"
+#include "asn1buf.h"
+
+/*
+   Overview
+
+     Each of these procedures constructs a subpart of an ASN.1
+     primitive in a coding buffer.
+
+    Operations
+
+      asn1_make_etag
+      asn1_make_sequence
+      asn1_make_set
+      asn1_make_tag
+      asn1_make_string
+*/
+
+asn1_error_code asn1_make_etag
+	(asn1buf *buf,
+		   const asn1_class asn1class,
+		   const asn1_tagnum tagnum,
+		   const unsigned int in_len,
+		   unsigned int *retlen);
+/* requires  *buf is allocated, in_len is the length of an ASN.1 encoding
+             which has just been inserted in *buf
+   modifies  *buf, *retlen
+   effects   Inserts an explicit tag with class = asn1class, id# = tag
+              length = in_len into *buf.
+	     Returns the length of this encoding in *retlen.
+	     Returns ENOMEM if memory runs out. */
+
+asn1_error_code asn1_make_tag
+	(asn1buf *buf, const asn1_class asn1class,
+		   const asn1_construction construction,
+		   const asn1_tagnum tagnum,
+		   const unsigned int in_len,
+		   unsigned int *retlen);
+/* requires  *buf is allocated, in_len is the length of an ASN.1 encoding
+             which has just been inserted in *buf
+   modifies  *buf, *retlen
+   effects   Inserts the encoding of a tag with class = asn1class,
+              primitive/constructed staus = construction,
+	      id# = tag and length = in_len into *buf.
+	     Returns the length of this encoding in *retlen.
+	     Returns ENOMEM if memory runs out.
+	     Returns ASN1_OVERFLOW if tagnum exceeds the limits of
+	      the implementation. */
+
+asn1_error_code asn1_make_sequence
+	(asn1buf *buf, const unsigned int seq_len, unsigned int *len);
+/* requires  *buf is allocated, seq_len is the length of a series of
+             sequence components which have just been inserted in *buf
+   modifies  *buf, *retlen
+   effects   Inserts the sequence header for a sequence of length seq_len
+              in *buf.  Returns the length of this encoding in *retlen.
+             Returns ENOMEM if memory runs out. */
+
+asn1_error_code asn1_make_set
+	(asn1buf *buf, const unsigned int set_len, 
+		   unsigned int *retlen);
+/* requires  *buf is allocated, seq_len is the length of a series of
+             sequence components which have just been inserted in *buf
+   modifies  *buf, *retlen
+   effects   Inserts the set header for a set of length set_len in *buf.
+             Returns the length of this encoding in *retlen.
+             Returns ENOMEM if memory runs out. */
+
+asn1_error_code asn1_make_string
+	(asn1buf *buf,
+		   const unsigned int len, const char *string,
+		   int *retlen);
+/* requires  *buf is allocated, len is the length of *string
+   effects   Inserts the encoding of *string (a series of octets) in *buf.
+             Returns the length of this encoding in *retlen.
+             Returns ENOMEM if memory runs out. */
+
+
+/****************************************************************/
+/* Private procedures */
+
+/* "helper" procedure for asn1_make_tag */
+asn1_error_code asn1_make_length
+	(asn1buf *buf, const unsigned int in_len, 
+		   unsigned int *retlen);
+/* requires  *buf is allocated, in_len is the length of an ASN.1 encoding
+             which has just been inserted in *buf
+   modifies  *buf, *retlen
+   effects   inserts length octet(s) for in_len into *buf */
+
+/* "helper" procedure for asn1_make_tag */
+asn1_error_code asn1_make_id
+	(asn1buf *buf,
+		   const asn1_class asn1class,
+		   const asn1_construction construction,
+		   const asn1_tagnum tagnum,
+		   unsigned int *retlen);
+/* requires  *buf is allocated, asn1class and tagnum are appropriate for
+             the ASN.1 encoding which has just been inserted in *buf
+   modifies  *buf, *retlen
+   effects   Inserts id octet(s) of class asn1class and tag number tagnum
+             into *buf */
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_misc.c b/krb5-1-6/src/lib/krb5/asn.1/asn1_misc.c
new file mode 100644
index 000000000..62412ae6e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_misc.c
@@ -0,0 +1,37 @@
+/*
+ * src/lib/krb5/asn.1/asn1_misc.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "asn1_misc.h"
+
+asn1_error_code asn1_krb5_realm_copy(krb5_principal target, krb5_principal source)
+{
+  target->realm.length = source->realm.length;
+  target->realm.data = (char*)malloc(target->realm.length); /* copy realm */
+  if (target->realm.data == NULL) return ENOMEM;
+  memcpy(target->realm.data,source->realm.data, /* to client */
+	 target->realm.length);
+  return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1_misc.h b/krb5-1-6/src/lib/krb5/asn.1/asn1_misc.h
new file mode 100644
index 000000000..31b30dac2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1_misc.h
@@ -0,0 +1,39 @@
+/*
+ * src/lib/krb5/asn.1/asn1_misc.h
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __ASN1_MISC_H__
+#define __ASN1_MISC_H__
+
+#include "k5-int.h"
+#include "krbasn1.h"
+
+asn1_error_code asn1_krb5_realm_copy
+	(krb5_principal target, krb5_principal source);
+/* requires  target, source, and source->realm are allocated
+   effects   Copies source->realm into target->realm.
+             Returns ENOMEM if memory is exhausted. */
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1buf.c b/krb5-1-6/src/lib/krb5/asn.1/asn1buf.c
new file mode 100644
index 000000000..8baac2424
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1buf.c
@@ -0,0 +1,384 @@
+/* Coding Buffer Implementation */
+
+/*
+  Implementation
+
+    Encoding mode
+
+    The encoding buffer is filled from bottom (lowest address) to top
+    (highest address).  This makes it easier to expand the buffer,
+    since realloc preserves the existing portion of the buffer.
+
+    Note: Since ASN.1 encoding must be done in reverse, this means
+    that you can't simply memcpy out the buffer data, since it will be
+    backwards.  You need to reverse-iterate through it, instead.
+
+    ***This decision may have been a mistake.  In practice, the
+    implementation will probably be tuned such that reallocation is
+    rarely necessary.  Also, the realloc probably has recopy the
+    buffer itself, so we don't really gain that much by avoiding an
+    explicit copy of the buffer.  --Keep this in mind for future reference.
+
+
+    Decoding mode
+
+    The decoding buffer is in normal order and is created by wrapping
+    an asn1buf around a krb5_data structure.
+  */
+
+/* Abstraction Function
+
+   Programs should use just pointers to asn1buf's (e.g. asn1buf *mybuf).
+   These pointers must always point to a valid, allocated asn1buf
+   structure or be NULL.
+
+   The contents of the asn1buf represent an octet string.  This string
+   begins at base and continues to the octet immediately preceding next.
+   If next == base or mybuf == NULL, then the asn1buf represents an empty
+   octet string. */
+
+/* Representation Invariant
+
+   Pointers to asn1buf's must always point to a valid, allocated
+   asn1buf structure or be NULL.
+
+   base points to a valid, allocated octet array or is NULL
+   bound, if non-NULL, points to the last valid octet
+   next >= base
+   next <= bound+2  (i.e. next should be able to step just past the bound,
+                     but no further.  (The bound should move out in response
+		     to being crossed by next.)) */
+
+#define ASN1BUF_OMIT_INLINE_FUNCS
+#include "asn1buf.h"
+#undef ASN1BUF_OMIT_INLINE_FUNCS
+#include <stdio.h>
+#include "asn1_get.h"
+
+#define asn1_is_eoc(class, num, indef)	\
+((class) == UNIVERSAL && !(num) && !(indef))
+
+asn1_error_code asn1buf_create(asn1buf **buf)
+{
+  *buf = (asn1buf*)malloc(sizeof(asn1buf));
+  if (*buf == NULL) return ENOMEM;
+  (*buf)->base = NULL;
+  (*buf)->bound = NULL;
+  (*buf)->next = NULL;
+  return 0;
+}
+
+asn1_error_code asn1buf_wrap_data(asn1buf *buf, const krb5_data *code)
+{
+  if(code == NULL || code->data == NULL) return ASN1_MISSING_FIELD;
+  buf->next = buf->base = code->data;
+  buf->bound = code->data + code->length - 1;
+  return 0;
+}
+
+asn1_error_code asn1buf_imbed(asn1buf *subbuf, const asn1buf *buf, const unsigned int length, const int indef)
+{
+  subbuf->base = subbuf->next = buf->next;
+  if (!indef) {
+      subbuf->bound = subbuf->base + length - 1;
+      if (subbuf->bound > buf->bound)
+	  return ASN1_OVERRUN;
+  } else /* constructed indefinite */
+      subbuf->bound = buf->bound;
+  return 0;
+}
+
+asn1_error_code asn1buf_sync(asn1buf *buf, asn1buf *subbuf,
+			     asn1_class asn1class, asn1_tagnum lasttag,
+			     unsigned int length, int indef, int seqindef)
+{
+  asn1_error_code retval;
+
+  if (!seqindef) {
+    /* sequence was encoded as definite length */
+    buf->next = subbuf->bound + 1;
+  } else if (!asn1_is_eoc(asn1class, lasttag, indef)) {
+      retval = asn1buf_skiptail(subbuf, length, indef);
+      if (retval)
+	  return retval;
+  } else {
+    /* We have just read the EOC octets. */
+    buf->next = subbuf->next;
+  }
+  return 0;
+}
+
+asn1_error_code asn1buf_skiptail(asn1buf *buf, const unsigned int length, const int indef)
+{
+  asn1_error_code retval;
+  taginfo t;
+  int nestlevel;
+
+  nestlevel = 1 + indef;
+  if (!indef) {
+    if (length <= buf->bound - buf->next + 1)
+      buf->next += length;
+    else
+      return ASN1_OVERRUN;
+  }
+  while (nestlevel > 0) {
+    if (buf->bound - buf->next + 1 <= 0)
+      return ASN1_OVERRUN;
+    retval = asn1_get_tag_2(buf, &t);
+    if (retval) return retval;
+    if (!t.indef) {
+      if (t.length <= buf->bound - buf->next + 1)
+	buf->next += t.length;
+      else
+	return ASN1_OVERRUN;
+    }
+    if (t.indef)
+      nestlevel++;
+    if (asn1_is_eoc(t.asn1class, t.tagnum, t.indef))
+      nestlevel--;		/* got an EOC encoding */
+  }
+  return 0;
+}
+
+asn1_error_code asn1buf_destroy(asn1buf **buf)
+{
+  if (*buf != NULL) {
+    if ((*buf)->base != NULL) free((*buf)->base);
+    free(*buf);
+    *buf = NULL;
+  }
+  return 0;
+}
+
+#ifdef asn1buf_insert_octet
+#undef asn1buf_insert_octet
+#endif
+asn1_error_code asn1buf_insert_octet(asn1buf *buf, const int o)
+{
+  asn1_error_code retval;
+
+  retval = asn1buf_ensure_space(buf,1U);
+  if(retval) return retval;
+  *(buf->next) = (char)o;
+  (buf->next)++;
+  return 0;
+}
+
+asn1_error_code asn1buf_insert_octetstring(asn1buf *buf, const unsigned int len, const krb5_octet *s)
+{
+  asn1_error_code retval;
+  int length;
+
+  retval = asn1buf_ensure_space(buf,len);
+  if(retval) return retval;
+  for(length=1; length<=len; length++,(buf->next)++)
+    *(buf->next) = (char)(s[len-length]);
+  return 0;
+}
+
+asn1_error_code asn1buf_insert_charstring(asn1buf *buf, const unsigned int len, const char *s)
+{
+  asn1_error_code retval;
+  int length;
+
+  retval = asn1buf_ensure_space(buf,len);
+  if(retval) return retval;
+  for(length=1; length<=len; length++,(buf->next)++)
+    *(buf->next) = (char)(s[len-length]);
+  return 0;
+}
+
+#undef asn1buf_remove_octet
+asn1_error_code asn1buf_remove_octet(asn1buf *buf, asn1_octet *o)
+{
+  if(buf->next > buf->bound) return ASN1_OVERRUN;
+  *o = (asn1_octet)(*((buf->next)++));
+  return 0;
+}
+
+asn1_error_code asn1buf_remove_octetstring(asn1buf *buf, const unsigned int len, asn1_octet **s)
+{
+  int i;
+
+  if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN;
+  if (len == 0) {
+      *s = 0;
+      return 0;
+  }
+  *s = (asn1_octet*)malloc(len*sizeof(asn1_octet));
+  if (*s == NULL)
+      return ENOMEM;
+  for(i=0; i<len; i++)
+    (*s)[i] = (asn1_octet)(buf->next)[i];
+  buf->next += len;
+  return 0;
+}
+
+asn1_error_code asn1buf_remove_charstring(asn1buf *buf, const unsigned int len, char **s)
+{
+  int i;
+
+  if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN;
+  if (len == 0) {
+      *s = 0;
+      return 0;
+  }
+  *s = (char*)malloc(len*sizeof(char));
+  if (*s == NULL) return ENOMEM;
+  for(i=0; i<len; i++)
+    (*s)[i] = (char)(buf->next)[i];
+  buf->next += len;
+  return 0;
+}
+
+int asn1buf_remains(asn1buf *buf, int indef)
+{
+  int remain;
+  if(buf == NULL || buf->base == NULL) return 0;
+  remain = buf->bound - buf->next +1;
+  if (remain <= 0) return remain;
+  /*
+   * Two 0 octets means the end of an indefinite encoding.
+   */
+  if (indef && remain >= 2 && !*(buf->next) && !*(buf->next + 1))
+      return 0;
+  else return remain;
+}
+
+asn1_error_code asn12krb5_buf(const asn1buf *buf, krb5_data **code)
+{
+  int i;
+  *code = (krb5_data*)calloc(1,sizeof(krb5_data));
+  if(*code == NULL) return ENOMEM;
+  (*code)->magic = KV5M_DATA;
+  (*code)->data = NULL;
+  (*code)->length = 0;
+  (*code)->length = asn1buf_len(buf);
+  (*code)->data = (char*)malloc((((*code)->length)+1)*sizeof(char));
+  if ((*code)->data == NULL) {
+    free(*code);
+    *code = NULL;
+    return ENOMEM;
+  }
+  for(i=0; i < (*code)->length; i++)
+    ((*code)->data)[i] = (buf->base)[((*code)->length)-i-1];
+  ((*code)->data)[(*code)->length] = '\0';
+  return 0;
+}
+
+
+
+/* These parse and unparse procedures should be moved out. They're
+   useful only for debugging and superfluous in the production version. */
+
+asn1_error_code asn1buf_unparse(const asn1buf *buf, char **s)
+{
+  if(*s != NULL) free(*s);
+  if(buf == NULL){
+    *s = malloc(sizeof("<NULL>"));
+    if(*s == NULL) return ENOMEM;
+    strcpy(*s,"<NULL>");
+  }else if(buf->base == NULL){
+    *s = malloc(sizeof("<EMPTY>"));
+    if(*s == NULL) return ENOMEM;
+    strcpy(*s,"<EMPTY>");
+  }else{
+    unsigned int length = asn1buf_len(buf);
+    int i;
+
+    *s = calloc(length+1, sizeof(char));
+    if(*s == NULL) return ENOMEM;
+    (*s)[length] = '\0';
+    for(i=0; i<length; i++) ;
+/*      OLDDECLARG( (*s)[i] = , (buf->base)[length-i-1]) */
+  }
+  return 0;
+}
+
+asn1_error_code asn1buf_hex_unparse(const asn1buf *buf, char **s)
+{
+#define hexchar(d) ((d)<=9 ? ('0'+(d)) :\
+		    ((d)<=15 ? ('A'+(d)-10) :\
+		    'X'))
+
+  if(*s != NULL) free(*s);
+
+  if(buf == NULL){
+    *s = malloc(sizeof("<NULL>"));
+    if(*s == NULL) return ENOMEM;
+    strcpy(*s,"<NULL>");
+  }else if(buf->base == NULL){
+    *s = malloc(sizeof("<EMPTY>"));
+    if(*s == NULL) return ENOMEM;
+    strcpy(*s,"<EMPTY>");
+  }else{
+    unsigned int length = asn1buf_len(buf);
+    int i;
+
+    *s = malloc(3*length);
+    if(*s == NULL) return ENOMEM;
+    for(i = length-1; i >= 0; i--){
+      (*s)[3*(length-i-1)] = hexchar(((buf->base)[i]&0xF0)>>4);
+      (*s)[3*(length-i-1)+1] = hexchar((buf->base)[i]&0x0F);
+      (*s)[3*(length-i-1)+2] = ' ';
+    }
+    (*s)[3*length-1] = '\0';
+  }
+  return 0;
+}
+
+/****************************************************************/
+/* Private Procedures */
+
+#undef asn1buf_size
+int asn1buf_size(const asn1buf *buf)
+{
+  if(buf == NULL || buf->base == NULL) return 0;
+  return buf->bound - buf->base + 1;
+}
+
+#undef asn1buf_free
+int asn1buf_free(const asn1buf *buf)
+{
+  if(buf == NULL || buf->base == NULL) return 0;
+  else return buf->bound - buf->next + 1;
+}
+
+#undef asn1buf_ensure_space
+asn1_error_code asn1buf_ensure_space(asn1buf *buf, const unsigned int amount)
+{
+  int avail = asn1buf_free(buf);
+  if(avail < amount){
+    asn1_error_code retval = asn1buf_expand(buf, amount-avail);
+    if(retval) return retval;
+  }
+  return 0;
+}
+
+asn1_error_code asn1buf_expand(asn1buf *buf, unsigned int inc)
+{
+#define STANDARD_INCREMENT 200
+  int next_offset = buf->next - buf->base;
+  int bound_offset;
+  if (buf->base == NULL) bound_offset = -1;
+  else bound_offset = buf->bound - buf->base;
+
+  if (inc < STANDARD_INCREMENT)
+    inc = STANDARD_INCREMENT;
+
+  if (buf->base == NULL)
+    buf->base = malloc((asn1buf_size(buf)+inc) * sizeof(asn1_octet));
+  else
+    buf->base = realloc(buf->base,
+			(asn1buf_size(buf)+inc) * sizeof(asn1_octet));
+  if (buf->base == NULL) return ENOMEM;
+  buf->bound = (buf->base) + bound_offset + inc;
+  buf->next = (buf->base) + next_offset;
+  return 0;
+}
+
+#undef asn1buf_len
+int asn1buf_len(const asn1buf *buf)
+{
+  return buf->next - buf->base;
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1buf.h b/krb5-1-6/src/lib/krb5/asn.1/asn1buf.h
new file mode 100644
index 000000000..854801edd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1buf.h
@@ -0,0 +1,231 @@
+/* Coding Buffer Specifications */
+#ifndef __ASN1BUF_H__
+#define __ASN1BUF_H__
+
+#include "k5-int.h"
+#include "krbasn1.h"
+
+typedef struct code_buffer_rep {
+  char *base, *bound, *next;
+} asn1buf;
+
+
+/**************** Private Procedures ****************/
+
+int asn1buf_size
+	(const asn1buf *buf);
+/* requires  *buf has been created and not destroyed
+   effects   Returns the total size 
+	(in octets) of buf's octet buffer. */
+#define asn1buf_size(buf) \
+  (((buf) == NULL || (buf)->base == NULL) \
+   ? 0 \
+   : ((buf)->bound - (buf)->base + 1))
+
+int asn1buf_free
+	(const asn1buf *buf);
+/* requires  *buf is allocated
+   effects   Returns the number of unused, allocated octets in *buf. */
+#define asn1buf_free(buf) \
+  (((buf) == NULL || (buf)->base == NULL) \
+   ? 0 \
+   : ((buf)->bound - (buf)->next + 1))
+
+
+asn1_error_code asn1buf_ensure_space
+	(asn1buf *buf, const unsigned int amount);
+/* requires  *buf is allocated
+   modifies  *buf
+   effects  If buf has less than amount octets of free space, then it is
+            expanded to have at least amount octets of free space.
+            Returns ENOMEM memory is exhausted. */
+#define asn1buf_ensure_space(buf,amount) \
+  ((asn1buf_free(buf) < (amount)) \
+   ? (asn1buf_expand((buf), (amount)-asn1buf_free(buf))) \
+   : 0)
+
+
+asn1_error_code asn1buf_expand
+	(asn1buf *buf, unsigned int inc);
+/* requires  *buf is allocated
+   modifies  *buf
+   effects   Expands *buf by allocating space for inc more octets.
+             Returns ENOMEM if memory is exhausted. */
+
+int asn1buf_len
+	(const asn1buf *buf);
+/* requires  *buf is allocated
+   effects   Returns the length of the encoding in *buf. */
+#define asn1buf_len(buf)	((buf)->next - (buf)->base)
+
+/****** End of private procedures *****/
+	
+/*
+  Overview 
+    
+    The coding buffer is an array of char (to match a krb5_data structure)
+     with 3 reference pointers:
+     1) base - The bottom of the octet array.  Used for memory management
+               operations on the array (e.g. alloc, realloc, free).
+     2) next - Points to the next available octet position in the array.
+               During encoding, this is the next free position, and it
+                 advances as octets are added to the array.
+	       During decoding, this is the next unread position, and it
+                 advances as octets are read from the array.
+     3) bound - Points to the top of the array. Used for bounds-checking.
+    
+    All pointers to encoding buffers should be initalized to NULL.
+    
+  Operations
+
+    asn1buf_create
+    asn1buf_wrap_data
+    asn1buf_destroy
+    asn1buf_insert_octet
+    asn1buf_insert_charstring
+    asn1buf_remove_octet
+    asn1buf_remove_charstring
+    asn1buf_unparse
+    asn1buf_hex_unparse
+    asn12krb5_buf
+    asn1buf_remains
+
+    (asn1buf_size)
+    (asn1buf_free)
+    (asn1buf_ensure_space)
+    (asn1buf_expand)
+    (asn1buf_len)
+*/
+
+asn1_error_code asn1buf_create
+	(asn1buf **buf);
+/* effects   Creates a new encoding buffer pointed to by *buf.
+             Returns ENOMEM if the buffer can't be created. */
+
+asn1_error_code asn1buf_wrap_data
+	(asn1buf *buf, const krb5_data *code);
+/* requires  *buf has already been allocated
+   effects   Turns *buf into a "wrapper" for *code.  i.e. *buf is set up
+              such that its bottom is the beginning of *code, and its top
+	      is the top of *code.
+	     Returns ASN1_MISSING_FIELD if code is empty. */
+
+asn1_error_code asn1buf_imbed
+	(asn1buf *subbuf, const asn1buf *buf, 
+		   const unsigned int length,
+		   const int indef);
+/* requires  *subbuf and *buf are allocated
+   effects   *subbuf becomes a sub-buffer of *buf.  *subbuf begins
+              at *buf's current position and is length octets long.
+              (Unless this would exceed the bounds of *buf -- in
+	      that case, ASN1_OVERRUN is returned)  *subbuf's current
+	      position starts at the beginning of *subbuf. */
+
+asn1_error_code asn1buf_sync
+	(asn1buf *buf, asn1buf *subbuf, const asn1_class Class, 
+		   const asn1_tagnum lasttag,
+		   const unsigned int length, const int indef,
+		   const int seqindef);
+/* requires  *subbuf is a sub-buffer of *buf, as created by asn1buf_imbed.
+             lasttag is the last tagnumber read.
+   effects   Synchronizes *buf's current position to match that of *subbuf. */
+
+asn1_error_code asn1buf_skiptail
+	(asn1buf *buf, const unsigned int length,
+		   const int indef);
+/* requires  *buf is a subbuffer used in a decoding of a
+             constructed indefinite sequence.
+   effects   skips trailing fields. */
+
+asn1_error_code asn1buf_destroy
+	(asn1buf **buf);
+/* effects   Deallocates **buf, sets *buf to NULL. */
+
+asn1_error_code asn1buf_insert_octet
+	(asn1buf *buf, const int o);
+/* requires  *buf is allocated
+   effects   Inserts o into the buffer *buf, expanding the buffer if
+             necessary.  Returns ENOMEM memory is exhausted. */
+#if ((__GNUC__ >= 2) && !defined(ASN1BUF_OMIT_INLINE_FUNCS))
+extern __inline__ asn1_error_code asn1buf_insert_octet(asn1buf *buf, const int o)
+{
+  asn1_error_code retval;
+
+  retval = asn1buf_ensure_space(buf,1U);
+  if(retval) return retval;
+  *(buf->next) = (char)o;
+  (buf->next)++;
+  return 0;
+}
+#endif
+
+asn1_error_code asn1buf_insert_octetstring
+	(asn1buf *buf, const unsigned int len, const asn1_octet *s);
+/* requires  *buf is allocated
+   modifies  *buf
+   effects   Inserts the contents of s (an octet array of length len)
+              into the buffer *buf, expanding the buffer if necessary.
+	     Returns ENOMEM if memory is exhausted. */
+
+asn1_error_code asn1buf_insert_charstring
+	(asn1buf *buf, const unsigned int len, const char *s);
+/* requires  *buf is allocated
+   modifies  *buf
+   effects   Inserts the contents of s (a character array of length len)
+              into the buffer *buf, expanding the buffer if necessary.
+	     Returns ENOMEM if memory is exhausted. */
+
+asn1_error_code asn1buf_remove_octet
+	(asn1buf *buf, asn1_octet *o);
+/* requires  *buf is allocated
+   effects   Returns *buf's current octet in *o and advances to
+              the next octet.
+	     Returns ASN1_OVERRUN if *buf has already been exhausted. */
+#define asn1buf_remove_octet(buf,o) \
+  (((buf)->next > (buf)->bound) \
+   ? ASN1_OVERRUN \
+   : ((*(o) = (asn1_octet)(*(((buf)->next)++))),0))
+
+asn1_error_code asn1buf_remove_octetstring
+	(asn1buf *buf, const unsigned int len, asn1_octet **s);
+/* requires  *buf is allocated
+   effects   Removes the next len octets of *buf and returns them in **s.
+	     Returns ASN1_OVERRUN if there are fewer than len unread octets
+	      left in *buf.
+	     Returns ENOMEM if *s could not be allocated. */
+
+asn1_error_code asn1buf_remove_charstring
+	(asn1buf *buf, const unsigned int len,
+					  char **s);
+/* requires  *buf is allocated
+   effects   Removes the next len octets of *buf and returns them in **s.
+	     Returns ASN1_OVERRUN if there are fewer than len unread octets
+	      left in *buf.
+	     Returns ENOMEM if *s could not be allocated. */
+
+asn1_error_code asn1buf_unparse
+	(const asn1buf *buf, char **s);
+/* modifies  *s
+   effects   Returns a human-readable representation of *buf in *s,
+             where each octet in *buf is represented by a character in *s. */
+
+asn1_error_code asn1buf_hex_unparse
+	(const asn1buf *buf, char **s);
+/* modifies  *s
+   effects   Returns a human-readable representation of *buf in *s,
+             where each octet in *buf is represented by a 2-digit
+	     hexadecimal number in *s. */
+
+asn1_error_code asn12krb5_buf
+	(const asn1buf *buf, krb5_data **code);
+/* modifies  *code
+   effects   Instantiates **code with the krb5_data representation of **buf. */
+
+
+int asn1buf_remains
+	(asn1buf *buf, int indef);
+/* requires  *buf is a buffer containing an asn.1 structure or array
+   modifies  *buf
+   effects   Returns the number of unprocessed octets remaining in *buf. */
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/asn1glue.h b/krb5-1-6/src/lib/krb5/asn.1/asn1glue.h
new file mode 100644
index 000000000..fa3c95675
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/asn1glue.h
@@ -0,0 +1,46 @@
+/*
+ * lib/krb5/asn.1/asn1glue.h
+ *
+ * Copyright 1989,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Header file for some glue functions (macros, mostly)
+ */
+
+
+#ifndef __KRB5_GLUE_H__
+#define __KRB5_GLUE_H__
+
+#define krb5_data2qbuf(val) str2qb((val)->data, (val)->length, 1)
+
+#define krb5_kdcoptions2KRB5_KDCOptions(val, err) (struct type_KRB5_KDCOptions *)krb5_flags2KRB5_TicketFlags(val, err)
+#define KRB5_KDCOptions2krb5_kdcoptions(val, err) KRB5_TicketFlags2krb5_flags((struct type_KRB5_TicketFlags *) (val), err)
+#define krb5_apoptions2KRB5_APOptions(val, err) (struct type_KRB5_APOptions *)krb5_flags2KRB5_TicketFlags(val, err)
+#define KRB5_APOptions2krb5_apoptions(val, err) KRB5_TicketFlags2krb5_flags((struct type_KRB5_APOptions *) (val), err)
+
+/* to keep lint happy */
+#define xbcopy(src,dst,size) memcpy((char *)(dst), (char *)(src), size)
+#define xmalloc(n) malloc((unsigned) (n))
+#define xcalloc(n,s) calloc((unsigned)(n), (unsigned)(s))
+
+#endif /* __KRB5_GLUE_H__ */
diff --git a/krb5-1-6/src/lib/krb5/asn.1/krb5_decode.c b/krb5-1-6/src/lib/krb5/asn.1/krb5_decode.c
new file mode 100644
index 000000000..cbd6a1294
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/krb5_decode.c
@@ -0,0 +1,1083 @@
+/*
+ * src/lib/krb5/asn.1/krb5_decode.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#include "krbasn1.h"
+#include "asn1_k_decode.h"
+#include "asn1_decode.h"
+#include "asn1_get.h"
+
+/* setup *********************************************************/
+/* set up variables */
+/* the setup* macros can return, but are always used at function start
+   and thus need no malloc cleanup */
+#define setup_buf_only()\
+asn1_error_code retval;\
+asn1buf buf;\
+\
+retval = asn1buf_wrap_data(&buf,code);\
+if(retval) return retval
+
+#define setup_no_tagnum()\
+asn1_class asn1class;\
+asn1_construction construction;\
+setup_buf_only()
+
+#define setup_no_length()\
+asn1_tagnum tagnum;\
+setup_no_tagnum()
+
+#define setup()\
+unsigned int length;\
+setup_no_length()
+
+/* helper macros for cleanup */
+#define clean_return(val) { retval = val; goto error_out; }
+
+/* alloc_field is the first thing to allocate storage that may need cleanup */
+#define alloc_field(var,type)\
+var = (type*)calloc(1,sizeof(type));\
+if((var) == NULL) clean_return(ENOMEM)
+
+/* process encoding header ***************************************/
+/* decode tag and check that it == [APPLICATION tagnum] */
+#define check_apptag(tagexpect)						\
+{									\
+    taginfo t1;								\
+    retval = asn1_get_tag_2(&buf, &t1);					\
+    if (retval) clean_return (retval);					\
+    if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED)	\
+	clean_return(ASN1_BAD_ID);					\
+    if (t1.tagnum != (tagexpect)) clean_return(KRB5_BADMSGTYPE);	\
+    asn1class = t1.asn1class;						\
+    construction = t1.construction;					\
+    tagnum = t1.tagnum;							\
+}
+
+
+
+/* process a structure *******************************************/
+
+/* decode an explicit tag and place the number in tagnum */
+#define next_tag()				\
+{ taginfo t2;					\
+  retval = asn1_get_tag_2(&subbuf, &t2);	\
+  if(retval) clean_return(retval);		\
+  asn1class = t2.asn1class;			\
+  construction = t2.construction;		\
+  tagnum = t2.tagnum;				\
+  indef = t2.indef;				\
+  taglen = t2.length;				\
+}
+
+#define get_eoc()						\
+{								\
+    taginfo t3;							\
+    retval = asn1_get_tag_2(&subbuf, &t3);			\
+    if (retval) return retval;					\
+    if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)	\
+        return ASN1_MISSING_EOC;				\
+    asn1class = t3.asn1class;					\
+    construction = t3.construction;				\
+    tagnum = t3.tagnum;						\
+    indef = t3.indef;						\
+}
+
+/* decode sequence header and initialize tagnum with the first field */
+#define begin_structure()\
+unsigned int taglen;\
+asn1buf subbuf;\
+int seqindef;\
+int indef;\
+retval = asn1_get_sequence(&buf,&length,&seqindef);\
+if(retval) clean_return(retval);\
+retval = asn1buf_imbed(&subbuf,&buf,length,seqindef);\
+if(retval) clean_return(retval);\
+next_tag()
+
+#define end_structure()\
+retval = asn1buf_sync(&buf,&subbuf,asn1class,tagnum,length,indef,seqindef);\
+if (retval) clean_return(retval)
+
+/* process fields *******************************************/
+/* normal fields ************************/
+#define get_field_body(var,decoder)\
+retval = decoder(&subbuf,&(var));\
+if(retval) clean_return(retval);\
+if (indef) { get_eoc(); }\
+next_tag()
+
+/* decode a field (<[UNIVERSAL id]> <length> <contents>)
+    check that the id number == tagexpect then
+    decode into var
+    get the next tag */
+#define get_field(var,tagexpect,decoder)\
+if(tagnum > (tagexpect)) clean_return(ASN1_MISSING_FIELD);\
+if(tagnum < (tagexpect)) clean_return(ASN1_MISPLACED_FIELD);\
+if(asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)\
+  clean_return(ASN1_BAD_ID);\
+get_field_body(var,decoder)
+
+/* decode (or skip, if not present) an optional field */
+#define opt_field(var,tagexpect,decoder)				\
+  if (asn1buf_remains(&subbuf, seqindef)) {				\
+    if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
+      clean_return(ASN1_BAD_ID);					\
+    if (tagnum == (tagexpect)) {					\
+      get_field_body(var,decoder);					\
+    }									\
+  }
+
+/* field w/ accompanying length *********/
+#define get_lenfield_body(len,var,decoder)\
+retval = decoder(&subbuf,&(len),&(var));\
+if(retval) clean_return(retval);\
+if (indef) { get_eoc(); }\
+next_tag()
+
+/* decode a field w/ its length (for string types) */
+#define get_lenfield(len,var,tagexpect,decoder)\
+if(tagnum > (tagexpect)) clean_return(ASN1_MISSING_FIELD);\
+if(tagnum < (tagexpect)) clean_return(ASN1_MISPLACED_FIELD);\
+if(asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)\
+  clean_return(ASN1_BAD_ID);\
+get_lenfield_body(len,var,decoder)
+
+/* decode an optional field w/ length */
+#define opt_lenfield(len,var,tagexpect,decoder)				\
+  if (asn1buf_remains(&subbuf, seqindef)) {				\
+    if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
+      clean_return(ASN1_BAD_ID);					\
+    if (tagnum == (tagexpect)) {					\
+      get_lenfield_body(len,var,decoder);				\
+    }									\
+  }
+  
+
+/* clean up ******************************************************/
+/* finish up */
+/* to make things less painful, assume the cleanup is passed rep */
+#define cleanup(cleanup_routine)\
+   return 0; \
+error_out: \
+   if (rep && *rep) { \
+	cleanup_routine(*rep); \
+	*rep = NULL; \
+   } \
+   return retval;
+
+#define cleanup_none()\
+   return 0; \
+error_out: \
+   return retval;
+	
+#define cleanup_manual()\
+   return 0;
+
+#define free_field(rep,f) if ((rep)->f) free((rep)->f)
+#define clear_field(rep,f) (*(rep))->f = 0
+
+krb5_error_code decode_krb5_authenticator(const krb5_data *code, krb5_authenticator **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_authenticator);
+  clear_field(rep,subkey);
+  clear_field(rep,checksum);
+  clear_field(rep,client);
+
+  check_apptag(2);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
+    alloc_field((*rep)->client,krb5_principal_data);
+    get_field((*rep)->client,1,asn1_decode_realm);
+    get_field((*rep)->client,2,asn1_decode_principal_name);
+    if(tagnum == 3){
+      alloc_field((*rep)->checksum,krb5_checksum);
+      get_field(*((*rep)->checksum),3,asn1_decode_checksum); }
+    get_field((*rep)->cusec,4,asn1_decode_int32);
+    get_field((*rep)->ctime,5,asn1_decode_kerberos_time);
+    if(tagnum == 6){ alloc_field((*rep)->subkey,krb5_keyblock); }
+    opt_field(*((*rep)->subkey),6,asn1_decode_encryption_key);
+    opt_field((*rep)->seq_number,7,asn1_decode_seqnum);
+    opt_field((*rep)->authorization_data,8,asn1_decode_authorization_data);
+    (*rep)->magic = KV5M_AUTHENTICATOR;
+    end_structure();
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,subkey);
+      free_field(*rep,checksum);
+      free_field(*rep,client);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code
+KRB5_CALLCONV
+krb5_decode_ticket(const krb5_data *code, krb5_ticket **rep)
+{
+    return decode_krb5_ticket(code, rep);
+}
+
+krb5_error_code decode_krb5_ticket(const krb5_data *code, krb5_ticket **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_ticket);
+  clear_field(rep,server);
+  
+  check_apptag(1);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO);
+    }
+    alloc_field((*rep)->server,krb5_principal_data);
+    get_field((*rep)->server,1,asn1_decode_realm);
+    get_field((*rep)->server,2,asn1_decode_principal_name);
+    get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
+    (*rep)->magic = KV5M_TICKET;
+    end_structure();
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,server);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_encryption_key(const krb5_data *code, krb5_keyblock **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_keyblock);
+
+  { begin_structure();
+    get_field((*rep)->enctype,0,asn1_decode_enctype);
+    get_lenfield((*rep)->length,(*rep)->contents,1,asn1_decode_octetstring);
+    end_structure();
+    (*rep)->magic = KV5M_KEYBLOCK;
+  }
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_enc_tkt_part(const krb5_data *code, krb5_enc_tkt_part **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_enc_tkt_part);
+  clear_field(rep,session);
+  clear_field(rep,client);
+
+  check_apptag(3);
+  { begin_structure();
+    get_field((*rep)->flags,0,asn1_decode_ticket_flags);
+    alloc_field((*rep)->session,krb5_keyblock);
+    get_field(*((*rep)->session),1,asn1_decode_encryption_key);
+    alloc_field((*rep)->client,krb5_principal_data);
+    get_field((*rep)->client,2,asn1_decode_realm);
+    get_field((*rep)->client,3,asn1_decode_principal_name);
+    get_field((*rep)->transited,4,asn1_decode_transited_encoding);
+    get_field((*rep)->times.authtime,5,asn1_decode_kerberos_time);
+    if (tagnum == 6)
+      { get_field((*rep)->times.starttime,6,asn1_decode_kerberos_time); }
+    else
+      (*rep)->times.starttime=(*rep)->times.authtime;
+    get_field((*rep)->times.endtime,7,asn1_decode_kerberos_time);
+    opt_field((*rep)->times.renew_till,8,asn1_decode_kerberos_time);
+    opt_field((*rep)->caddrs,9,asn1_decode_host_addresses);
+    opt_field((*rep)->authorization_data,10,asn1_decode_authorization_data);
+    (*rep)->magic = KV5M_ENC_TKT_PART;
+    end_structure();
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,session);
+      free_field(*rep,client);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_enc_kdc_rep_part(const krb5_data *code, krb5_enc_kdc_rep_part **rep)
+{
+  taginfo t4;
+  setup_buf_only();
+  alloc_field(*rep,krb5_enc_kdc_rep_part);
+
+  retval = asn1_get_tag_2(&buf, &t4);
+  if (retval) clean_return(retval);
+  if (t4.asn1class != APPLICATION || t4.construction != CONSTRUCTED) clean_return(ASN1_BAD_ID);
+  if (t4.tagnum == 25) (*rep)->msg_type = KRB5_AS_REP;
+  else if(t4.tagnum == 26) (*rep)->msg_type = KRB5_TGS_REP;
+  else clean_return(KRB5_BADMSGTYPE);
+
+  retval = asn1_decode_enc_kdc_rep_part(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_as_rep(const krb5_data *code, krb5_kdc_rep **rep)
+{
+  setup_no_length();
+  alloc_field(*rep,krb5_kdc_rep);
+
+  check_apptag(11);
+  retval = asn1_decode_kdc_rep(&buf,*rep);
+  if(retval) clean_return(retval);
+#ifdef KRB5_MSGTYPE_STRICT
+  if((*rep)->msg_type != KRB5_AS_REP)
+    clean_return(KRB5_BADMSGTYPE);
+#endif
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_tgs_rep(const krb5_data *code, krb5_kdc_rep **rep)
+{
+  setup_no_length();
+  alloc_field(*rep,krb5_kdc_rep);
+
+  check_apptag(13);
+  retval = asn1_decode_kdc_rep(&buf,*rep);
+  if(retval) clean_return(retval);
+#ifdef KRB5_MSGTYPE_STRICT
+  if((*rep)->msg_type != KRB5_TGS_REP) clean_return(KRB5_BADMSGTYPE);
+#endif
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_ap_req);
+  clear_field(rep,ticket);
+
+  check_apptag(14);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
+    { krb5_msgtype msg_type;
+      get_field(msg_type,1,asn1_decode_msgtype);
+#ifdef KRB5_MSGTYPE_STRICT
+      if(msg_type != KRB5_AP_REQ) clean_return(KRB5_BADMSGTYPE);
+#endif
+    }
+    get_field((*rep)->ap_options,2,asn1_decode_ap_options);
+    alloc_field((*rep)->ticket,krb5_ticket);
+    get_field(*((*rep)->ticket),3,asn1_decode_ticket);
+    get_field((*rep)->authenticator,4,asn1_decode_encrypted_data);
+    end_structure();
+    (*rep)->magic = KV5M_AP_REQ;
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,ticket);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_ap_rep(const krb5_data *code, krb5_ap_rep **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_ap_rep);
+
+  check_apptag(15);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
+    { krb5_msgtype msg_type;
+      get_field(msg_type,1,asn1_decode_msgtype);
+#ifdef KRB5_MSGTYPE_STRICT
+      if(msg_type != KRB5_AP_REP) clean_return(KRB5_BADMSGTYPE);
+#endif
+    }
+    get_field((*rep)->enc_part,2,asn1_decode_encrypted_data);
+    end_structure();
+    (*rep)->magic = KV5M_AP_REP;
+  }
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_ap_rep_enc_part(const krb5_data *code, krb5_ap_rep_enc_part **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_ap_rep_enc_part);
+  clear_field(rep,subkey);
+
+  check_apptag(27);
+  { begin_structure();
+    get_field((*rep)->ctime,0,asn1_decode_kerberos_time);
+    get_field((*rep)->cusec,1,asn1_decode_int32);
+    if(tagnum == 2){ alloc_field((*rep)->subkey,krb5_keyblock); }
+    opt_field(*((*rep)->subkey),2,asn1_decode_encryption_key);
+    opt_field((*rep)->seq_number,3,asn1_decode_seqnum);
+    end_structure();
+    (*rep)->magic = KV5M_AP_REP_ENC_PART;
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,subkey);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_as_req(const krb5_data *code, krb5_kdc_req **rep)
+{
+  setup_no_length();
+  alloc_field(*rep,krb5_kdc_req);
+
+  check_apptag(10);
+  retval = asn1_decode_kdc_req(&buf,*rep);
+  if(retval) clean_return(retval);
+#ifdef KRB5_MSGTYPE_STRICT
+  if((*rep)->msg_type != KRB5_AS_REQ) clean_return(KRB5_BADMSGTYPE);
+#endif
+  
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_tgs_req(const krb5_data *code, krb5_kdc_req **rep)
+{
+  setup_no_length();
+  alloc_field(*rep,krb5_kdc_req);
+
+  check_apptag(12);
+  retval = asn1_decode_kdc_req(&buf,*rep);
+  if(retval) clean_return(retval);
+#ifdef KRB5_MSGTYPE_STRICT
+  if((*rep)->msg_type != KRB5_TGS_REQ) clean_return(KRB5_BADMSGTYPE);
+#endif
+  
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_kdc_req_body(const krb5_data *code, krb5_kdc_req **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_kdc_req);
+
+  retval = asn1_decode_kdc_req_body(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+/*
+ * decode_krb5_safe_with_body
+ *
+ * Like decode_krb5_safe(), but grabs the encoding of the
+ * KRB-SAFE-BODY as well, in case re-encoding would produce a
+ * different encoding.  (Yes, we're using DER, but there's this
+ * annoying problem with pre-1.3.x code using signed sequence numbers,
+ * which we permissively decode and cram into unsigned 32-bit numbers.
+ * When they're re-encoded, they're no longer negative if they started
+ * out negative, so checksum verification fails.)
+ *
+ * This does *not* perform any copying; the returned pointer to the
+ * encoded KRB-SAFE-BODY points into the input buffer.
+ */
+krb5_error_code decode_krb5_safe_with_body(
+  const krb5_data *code,
+  krb5_safe **rep,
+  krb5_data *body)
+{
+  krb5_data tmpbody;
+  setup();
+  alloc_field(*rep,krb5_safe);
+  clear_field(rep,checksum);
+  tmpbody.magic = 0;
+
+  check_apptag(20);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
+    { krb5_msgtype msg_type;
+      get_field(msg_type,1,asn1_decode_msgtype);
+#ifdef KRB5_MSGTYPE_STRICT
+      if(msg_type != KRB5_SAFE) clean_return(KRB5_BADMSGTYPE);
+#endif
+    }
+    /*
+     * Gross kludge to extract pointer to encoded safe-body.  Relies
+     * on tag prefetch done by next_tag().  Don't handle indefinite
+     * encoding, as it's too much work.
+     */
+    if (!indef) {
+      tmpbody.length = taglen;
+      tmpbody.data = subbuf.next;
+    } else {
+      tmpbody.length = 0;
+      tmpbody.data = NULL;
+    }
+    get_field(**rep,2,asn1_decode_krb_safe_body);
+    alloc_field((*rep)->checksum,krb5_checksum);
+    get_field(*((*rep)->checksum),3,asn1_decode_checksum);
+  (*rep)->magic = KV5M_SAFE;
+    end_structure();
+  }
+  if (body != NULL)
+    *body = tmpbody;
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,checksum);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_safe(const krb5_data *code, krb5_safe **rep)
+{
+  return decode_krb5_safe_with_body(code, rep, NULL);
+}
+
+krb5_error_code decode_krb5_priv(const krb5_data *code, krb5_priv **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_priv);
+
+  check_apptag(21);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
+    { krb5_msgtype msg_type;
+      get_field(msg_type,1,asn1_decode_msgtype);
+#ifdef KRB5_MSGTYPE_STRICT
+      if(msg_type != KRB5_PRIV) clean_return(KRB5_BADMSGTYPE);
+#endif
+    }
+    get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
+    (*rep)->magic = KV5M_PRIV;
+    end_structure();
+  }
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_enc_priv_part(const krb5_data *code, krb5_priv_enc_part **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_priv_enc_part);
+  clear_field(rep,r_address);
+  clear_field(rep,s_address);
+
+  check_apptag(28);
+  { begin_structure();
+    get_lenfield((*rep)->user_data.length,(*rep)->user_data.data,0,asn1_decode_charstring);
+    opt_field((*rep)->timestamp,1,asn1_decode_kerberos_time);
+    opt_field((*rep)->usec,2,asn1_decode_int32);
+    opt_field((*rep)->seq_number,3,asn1_decode_seqnum);
+    alloc_field((*rep)->s_address,krb5_address);
+    get_field(*((*rep)->s_address),4,asn1_decode_host_address);
+    if(tagnum == 5){ alloc_field((*rep)->r_address,krb5_address); }
+    opt_field(*((*rep)->r_address),5,asn1_decode_host_address);
+    (*rep)->magic = KV5M_PRIV_ENC_PART;
+    end_structure();
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,r_address);
+      free_field(*rep,s_address);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_cred(const krb5_data *code, krb5_cred **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_cred);
+
+  check_apptag(22);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
+    { krb5_msgtype msg_type;
+      get_field(msg_type,1,asn1_decode_msgtype);
+#ifdef KRB5_MSGTYPE_STRICT
+      if(msg_type != KRB5_CRED) clean_return(KRB5_BADMSGTYPE);
+#endif
+    }
+    get_field((*rep)->tickets,2,asn1_decode_sequence_of_ticket);
+    get_field((*rep)->enc_part,3,asn1_decode_encrypted_data);
+    (*rep)->magic = KV5M_CRED;
+    end_structure();
+  }
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_enc_cred_part(const krb5_data *code, krb5_cred_enc_part **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_cred_enc_part);
+  clear_field(rep,r_address);
+  clear_field(rep,s_address);
+
+  check_apptag(29);
+  { begin_structure();
+    get_field((*rep)->ticket_info,0,asn1_decode_sequence_of_krb_cred_info);
+    opt_field((*rep)->nonce,1,asn1_decode_int32);
+    opt_field((*rep)->timestamp,2,asn1_decode_kerberos_time);
+    opt_field((*rep)->usec,3,asn1_decode_int32);
+    if(tagnum == 4){ alloc_field((*rep)->s_address,krb5_address); }
+    opt_field(*((*rep)->s_address),4,asn1_decode_host_address);
+    if(tagnum == 5){ alloc_field((*rep)->r_address,krb5_address); }
+    opt_field(*((*rep)->r_address),5,asn1_decode_host_address);
+    (*rep)->magic = KV5M_CRED_ENC_PART;
+    end_structure();
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,r_address);
+      free_field(*rep,s_address);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+
+krb5_error_code decode_krb5_error(const krb5_data *code, krb5_error **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_error);
+  clear_field(rep,server);
+  clear_field(rep,client);
+  
+  check_apptag(30);
+  { begin_structure();
+    { krb5_kvno kvno;
+      get_field(kvno,0,asn1_decode_kvno);
+      if(kvno != KVNO) clean_return(KRB5KDC_ERR_BAD_PVNO); }
+    { krb5_msgtype msg_type;
+      get_field(msg_type,1,asn1_decode_msgtype);
+#ifdef KRB5_MSGTYPE_STRICT
+      if(msg_type != KRB5_ERROR) clean_return(KRB5_BADMSGTYPE);
+#endif
+    }
+    opt_field((*rep)->ctime,2,asn1_decode_kerberos_time);
+    opt_field((*rep)->cusec,3,asn1_decode_int32);
+    get_field((*rep)->stime,4,asn1_decode_kerberos_time);
+    get_field((*rep)->susec,5,asn1_decode_int32);
+    get_field((*rep)->error,6,asn1_decode_ui_4);
+    if(tagnum == 7){ alloc_field((*rep)->client,krb5_principal_data); }
+    opt_field((*rep)->client,7,asn1_decode_realm);
+    opt_field((*rep)->client,8,asn1_decode_principal_name);
+    alloc_field((*rep)->server,krb5_principal_data);
+    get_field((*rep)->server,9,asn1_decode_realm);
+    get_field((*rep)->server,10,asn1_decode_principal_name);
+    opt_lenfield((*rep)->text.length,(*rep)->text.data,11,asn1_decode_generalstring);
+    opt_lenfield((*rep)->e_data.length,(*rep)->e_data.data,12,asn1_decode_charstring);
+    (*rep)->magic = KV5M_ERROR;
+    end_structure();
+  }
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+      free_field(*rep,server);
+      free_field(*rep,client);
+      free(*rep);
+      *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_authdata(const krb5_data *code, krb5_authdata ***rep)
+{
+  setup_buf_only();
+  *rep = 0;
+  retval = asn1_decode_authorization_data(&buf,rep);
+  if(retval) clean_return(retval);
+  cleanup_none();		/* we're not allocating anything here... */
+}
+
+krb5_error_code decode_krb5_pwd_sequence(const krb5_data *code, passwd_phrase_element **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,passwd_phrase_element);
+  retval = asn1_decode_passwdsequence(&buf,*rep);
+  if(retval) clean_return(retval);
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_pwd_data(const krb5_data *code, krb5_pwd_data **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_pwd_data);
+  { begin_structure();
+    get_field((*rep)->sequence_count,0,asn1_decode_int);
+    get_field((*rep)->element,1,asn1_decode_sequence_of_passwdsequence);
+    (*rep)->magic = KV5M_PWD_DATA;
+    end_structure (); }
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_padata_sequence(const krb5_data *code, krb5_pa_data ***rep)
+{
+  setup_buf_only();
+  *rep = 0;
+  retval = asn1_decode_sequence_of_pa_data(&buf,rep);
+  if(retval) clean_return(retval);
+  cleanup_none();		/* we're not allocating anything here */
+}
+
+krb5_error_code decode_krb5_alt_method(const krb5_data *code, krb5_alt_method **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_alt_method);
+  { begin_structure();
+    get_field((*rep)->method,0,asn1_decode_int32);
+    if (tagnum == 1) {
+	get_lenfield((*rep)->length,(*rep)->data,1,asn1_decode_octetstring);
+    } else {
+	(*rep)->length = 0;
+	(*rep)->data = 0;
+    }
+    (*rep)->magic = KV5M_ALT_METHOD;
+    end_structure();
+  }
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_etype_info(const krb5_data *code, krb5_etype_info_entry ***rep)
+{
+  setup_buf_only();
+  *rep = 0;
+  retval = asn1_decode_etype_info(&buf,rep);
+  if(retval) clean_return(retval);
+  cleanup_none();		/* we're not allocating anything here */
+}
+
+krb5_error_code decode_krb5_etype_info2(const krb5_data *code, krb5_etype_info_entry ***rep)
+{
+    setup_buf_only();
+    *rep = 0;
+    retval = asn1_decode_etype_info2(&buf,rep, 0);
+    if (retval == ASN1_BAD_ID) {
+	retval = asn1buf_wrap_data(&buf,code);
+	if(retval) clean_return(retval);
+	retval = asn1_decode_etype_info2(&buf, rep, 1);
+    }
+    if(retval) clean_return(retval);
+    cleanup_none();		/* we're not allocating anything here */
+}
+
+
+krb5_error_code decode_krb5_enc_data(const krb5_data *code, krb5_enc_data **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_enc_data);
+
+  retval = asn1_decode_encrypted_data(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_enc_ts(const krb5_data *code, krb5_pa_enc_ts **rep)
+{
+  setup();
+  alloc_field(*rep,krb5_pa_enc_ts);
+  { begin_structure();
+    get_field((*rep)->patimestamp,0,asn1_decode_kerberos_time);
+    if (tagnum == 1) {
+	get_field((*rep)->pausec,1,asn1_decode_int32);
+    } else
+	(*rep)->pausec = 0;
+    end_structure (); }
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_sam_challenge(const krb5_data *code, krb5_sam_challenge **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_sam_challenge);
+
+  retval = asn1_decode_sam_challenge(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_sam_challenge_2(const krb5_data *code, krb5_sam_challenge_2 **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_sam_challenge_2);
+
+  retval = asn1_decode_sam_challenge_2(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_sam_challenge_2_body(const krb5_data *code, krb5_sam_challenge_2_body **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_sam_challenge_2_body);
+
+  retval = asn1_decode_sam_challenge_2_body(&buf, *rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_enc_sam_key(const krb5_data *code, krb5_sam_key **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_sam_key);
+
+  retval = asn1_decode_enc_sam_key(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_enc_sam_response_enc(const krb5_data *code, krb5_enc_sam_response_enc **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_enc_sam_response_enc);
+
+  retval = asn1_decode_enc_sam_response_enc(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_enc_sam_response_enc_2(const krb5_data *code, krb5_enc_sam_response_enc_2 **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_enc_sam_response_enc_2);
+
+  retval = asn1_decode_enc_sam_response_enc_2(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_sam_response(const krb5_data *code, krb5_sam_response **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_sam_response);
+
+  retval = asn1_decode_sam_response(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_sam_response_2(const krb5_data *code, krb5_sam_response_2 **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep,krb5_sam_response_2);
+
+  retval = asn1_decode_sam_response_2(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_predicted_sam_response(const krb5_data *code, krb5_predicted_sam_response **rep)
+{
+  setup_buf_only();		/* preallocated */
+  alloc_field(*rep,krb5_predicted_sam_response);
+
+  retval = asn1_decode_predicted_sam_response(&buf,*rep);
+  if(retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_pa_pk_as_req);
+
+  retval = asn1_decode_pa_pk_as_req(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_pk_as_req_draft9(const krb5_data *code, krb5_pa_pk_as_req_draft9 **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_pa_pk_as_req_draft9);
+
+  retval = asn1_decode_pa_pk_as_req_draft9(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_pk_as_rep(const krb5_data *code, krb5_pa_pk_as_rep **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_pa_pk_as_rep);
+
+  retval = asn1_decode_pa_pk_as_rep(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_pk_as_rep_draft9(const krb5_data *code, krb5_pa_pk_as_rep_draft9 **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_pa_pk_as_rep_draft9);
+
+  retval = asn1_decode_pa_pk_as_rep_draft9(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_auth_pack(const krb5_data *code, krb5_auth_pack **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_auth_pack);
+
+  retval = asn1_decode_auth_pack(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_auth_pack_draft9(const krb5_data *code, krb5_auth_pack_draft9 **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_auth_pack_draft9);
+
+  retval = asn1_decode_auth_pack_draft9(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_kdc_dh_key_info(const krb5_data *code, krb5_kdc_dh_key_info **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_kdc_dh_key_info);
+
+  retval = asn1_decode_kdc_dh_key_info(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_principal_name(const krb5_data *code, krb5_principal_data **rep) 
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_principal_data);
+
+  retval = asn1_decode_krb5_principal_name(&buf, rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_reply_key_pack(const krb5_data *code, krb5_reply_key_pack **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_reply_key_pack);
+
+  retval = asn1_decode_reply_key_pack(&buf, *rep);
+  if (retval)
+    goto error_out;
+
+  cleanup_manual();
+error_out:
+  if (rep && *rep) {
+    if ((*rep)->replyKey.contents)
+	free((*rep)->replyKey.contents);
+    if ((*rep)->asChecksum.contents)
+      free((*rep)->asChecksum.contents);
+    free(*rep);
+    *rep = NULL;
+  }
+  return retval;
+}
+
+krb5_error_code decode_krb5_reply_key_pack_draft9(const krb5_data *code, krb5_reply_key_pack_draft9 **rep)
+{
+  setup_buf_only();
+  alloc_field(*rep, krb5_reply_key_pack_draft9);
+
+  retval = asn1_decode_reply_key_pack_draft9(&buf, *rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_typed_data(const krb5_data *code, krb5_typed_data ***rep)
+{
+  setup_buf_only();
+  retval = asn1_decode_sequence_of_typed_data(&buf, rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_td_trusted_certifiers(const krb5_data *code, krb5_external_principal_identifier ***rep)
+{
+  setup_buf_only();
+  retval = asn1_decode_sequence_of_external_principal_identifier(&buf, rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
+
+krb5_error_code decode_krb5_td_dh_parameters(const krb5_data *code, krb5_algorithm_identifier ***rep)
+{
+  setup_buf_only();
+  retval = asn1_decode_sequence_of_algorithm_identifier(&buf, rep);
+  if (retval) clean_return(retval);
+
+  cleanup(free);
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/krb5_encode.c b/krb5-1-6/src/lib/krb5/asn.1/krb5_encode.c
new file mode 100644
index 000000000..682e9a289
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/krb5_encode.c
@@ -0,0 +1,1014 @@
+/*
+ * src/lib/krb5/asn.1/krb5_encode.c
+ * 
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#include "asn1_k_encode.h"
+#include "asn1_encode.h"
+#include "krbasn1.h"
+#include "asn1buf.h"
+#include "asn1_make.h"
+
+/**************** Macros (these save a lot of typing) ****************/
+
+/**** krb5 macros ****/
+#if 0
+   How to write a krb5 encoder function using these macros:
+
+   asn1_error_code encode_krb5_structure(const krb5_type *rep,
+                                         krb5_data **code)
+   {
+     krb5_setup();
+
+     krb5_addfield(rep->last_field, n, asn1_type);
+     krb5_addfield(rep->next_to_last_field, n-1, asn1_type);
+     ...
+
+     /* for OPTIONAL fields */
+     if(rep->field_i == should_not_be_omitted)
+       krb5_addfield(rep->field_i, i, asn1_type);
+
+     /* for string fields (these encoders take an additional argument,
+	the length of the string) */
+     addlenfield(rep->field_length, rep->field, i-1, asn1_type);
+
+     /* if you really have to do things yourself... */
+     retval = asn1_encode_asn1_type(buf,rep->field,&length);
+     if(retval) return retval;
+     sum += length;
+     retval = asn1_make_etag(buf,
+			    [UNIVERSAL/APPLICATION/CONTEXT_SPECIFIC/PRIVATE],
+			    tag_number, length, &length);
+     if(retval) return retval;
+     sum += length;
+
+     ...
+     krb5_addfield(rep->second_field, 1, asn1_type);
+     krb5_addfield(rep->first_field, 0, asn1_type);
+     krb5_makeseq();
+     krb5_apptag(tag_number);
+
+     krb5_cleanup();
+   }
+#endif
+
+/* setup() -- create and initialize bookkeeping variables
+     retval: stores error codes returned from subroutines
+     buf: the coding buffer
+     length: length of the most-recently produced encoding
+     sum: cumulative length of the entire encoding */
+#define krb5_setup()\
+  asn1_error_code retval;\
+  asn1buf *buf=NULL;\
+  unsigned int length, sum=0;\
+\
+  if(rep == NULL) return ASN1_MISSING_FIELD;\
+\
+  retval = asn1buf_create(&buf);\
+  if(retval) return retval
+  
+/* krb5_addfield -- add a field, or component, to the encoding */
+#define krb5_addfield(value,tag,encoder)\
+{ retval = encoder(buf,value,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length;\
+  retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length; }
+
+/* krb5_addlenfield -- add a field whose length must be separately specified */
+#define krb5_addlenfield(len,value,tag,encoder)\
+{ retval = encoder(buf,len,value,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length;\
+  retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length; }
+
+/* form a sequence (by adding a sequence header to the current encoding) */
+#define krb5_makeseq()\
+  retval = asn1_make_sequence(buf,sum,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length
+
+/* add an APPLICATION class tag to the current encoding */
+#define krb5_apptag(num)\
+  retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  sum += length
+
+/* produce the final output and clean up the workspace */
+#define krb5_cleanup()\
+  retval = asn12krb5_buf(buf,code);\
+  if(retval){\
+    asn1buf_destroy(&buf);\
+    return retval; }\
+  retval = asn1buf_destroy(&buf);\
+  if(retval){\
+    return retval; }\
+\
+  return 0
+
+krb5_error_code encode_krb5_authenticator(const krb5_authenticator *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* authorization-data[8]	AuthorizationData OPTIONAL */
+  if(rep->authorization_data != NULL &&
+     rep->authorization_data[0] != NULL){
+    retval = asn1_encode_authorization_data(buf, (const krb5_authdata **)
+					    rep->authorization_data,
+					    &length);
+    if(retval){
+      asn1buf_destroy(&buf);
+      return retval; }
+    sum += length;
+    retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,8,length,&length);
+    if(retval){
+      asn1buf_destroy(&buf);
+      return retval; }
+    sum += length;
+  }
+
+  /* seq-number[7]		INTEGER OPTIONAL */
+  if(rep->seq_number != 0)
+    krb5_addfield(rep->seq_number,7,asn1_encode_unsigned_integer);
+
+  /* subkey[6]			EncryptionKey OPTIONAL */
+  if(rep->subkey != NULL)
+    krb5_addfield(rep->subkey,6,asn1_encode_encryption_key);
+
+  /* ctime[5]			KerberosTime */
+  krb5_addfield(rep->ctime,5,asn1_encode_kerberos_time);
+
+  /* cusec[4]			INTEGER */
+  krb5_addfield(rep->cusec,4,asn1_encode_integer);
+
+  /* cksum[3]			Checksum OPTIONAL */
+  if(rep->checksum != NULL)
+    krb5_addfield(rep->checksum,3,asn1_encode_checksum);
+
+  /* cname[2]			PrincipalName */
+  krb5_addfield(rep->client,2,asn1_encode_principal_name);
+
+  /* crealm[1]			Realm */
+  krb5_addfield(rep->client,1,asn1_encode_realm);
+
+  /* authenticator-vno[0]	INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* Authenticator ::= [APPLICATION 2] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(2);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_ticket(const krb5_ticket *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* enc-part[3]	EncryptedData */
+  krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
+
+  /* sname [2]		PrincipalName */
+  krb5_addfield(rep->server,2,asn1_encode_principal_name);
+
+  /* realm [1]		Realm */
+  krb5_addfield(rep->server,1,asn1_encode_realm);
+
+  /* tkt-vno [0]	INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* Ticket ::= [APPLICATION 1] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(1);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_encryption_key(const krb5_keyblock *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* keyvalue[1]	OCTET STRING */
+  krb5_addlenfield(rep->length,rep->contents,1,asn1_encode_octetstring);
+
+  /* enctype[0]		INTEGER */
+  krb5_addfield(rep->enctype,0,asn1_encode_integer);
+
+  /* EncryptionKey ::= SEQUENCE */
+  krb5_makeseq();
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* authorization-data[10]	AuthorizationData OPTIONAL */
+  if(rep->authorization_data != NULL &&
+     rep->authorization_data[0] != NULL)
+    krb5_addfield((const krb5_authdata**)rep->authorization_data,
+		  10,asn1_encode_authorization_data);
+
+  /* caddr[9]			HostAddresses OPTIONAL */
+  if(rep->caddrs != NULL && rep->caddrs[0] != NULL)
+    krb5_addfield((const krb5_address**)rep->caddrs,9,asn1_encode_host_addresses);
+
+  /* renew-till[8]		KerberosTime OPTIONAL */
+  if(rep->times.renew_till)
+    krb5_addfield(rep->times.renew_till,8,asn1_encode_kerberos_time);
+
+  /* endtime[7]			KerberosTime */
+  krb5_addfield(rep->times.endtime,7,asn1_encode_kerberos_time);
+
+  /* starttime[6]		KerberosTime OPTIONAL */
+  if(rep->times.starttime)
+    krb5_addfield(rep->times.starttime,6,asn1_encode_kerberos_time);
+
+  /* authtime[5]		KerberosTime */
+  krb5_addfield(rep->times.authtime,5,asn1_encode_kerberos_time);
+
+  /* transited[4]		TransitedEncoding */
+  krb5_addfield(&(rep->transited),4,asn1_encode_transited_encoding);
+
+  /* cname[3]			PrincipalName */
+  krb5_addfield(rep->client,3,asn1_encode_principal_name);
+
+  /* crealm[2]			Realm */
+  krb5_addfield(rep->client,2,asn1_encode_realm);
+
+  /* key[1]			EncryptionKey */
+  krb5_addfield(rep->session,1,asn1_encode_encryption_key);
+
+  /* flags[0]			TicketFlags */
+  krb5_addfield(rep->flags,0,asn1_encode_ticket_flags);
+
+  /* EncTicketPart ::= [APPLICATION 3] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(3);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_enc_kdc_rep_part(const krb5_enc_kdc_rep_part *rep, krb5_data **code)
+{
+  asn1_error_code retval;
+  asn1buf *buf=NULL;
+  unsigned int length, sum=0;
+
+  if(rep == NULL) return ASN1_MISSING_FIELD;
+
+  retval = asn1buf_create(&buf);
+  if(retval) return retval;
+
+  retval = asn1_encode_enc_kdc_rep_part(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+#ifdef KRB5_ENCKRB5KDCREPPART_COMPAT
+  krb5_apptag(26);
+#else
+  /* XXX WRONG!!! Should use 25 || 26, not the outer KDC_REP tags! */
+  if (rep->msg_type == KRB5_AS_REP) { krb5_apptag(ASN1_KRB_AS_REP); }
+  else if (rep->msg_type == KRB5_TGS_REP) { krb5_apptag(ASN1_KRB_TGS_REP); }
+  else return KRB5_BADMSGTYPE;
+#endif
+  krb5_cleanup();
+}
+
+/* yes, the translation is identical to that used for KDC__REP */ 
+krb5_error_code encode_krb5_as_rep(const krb5_kdc_rep *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* AS-REP ::= [APPLICATION 11] KDC-REP */
+  retval = asn1_encode_kdc_rep(KRB5_AS_REP,buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+  krb5_apptag(11);
+
+  krb5_cleanup();
+}
+
+/* yes, the translation is identical to that used for KDC__REP */ 
+krb5_error_code encode_krb5_tgs_rep(const krb5_kdc_rep *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* TGS-REP ::= [APPLICATION 13] KDC-REP */
+  retval = asn1_encode_kdc_rep(KRB5_TGS_REP,buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+  krb5_apptag(13);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_ap_req(const krb5_ap_req *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* authenticator[4]	EncryptedData */
+  krb5_addfield(&(rep->authenticator),4,asn1_encode_encrypted_data);
+
+  /* ticket[3]		Ticket */
+  krb5_addfield(rep->ticket,3,asn1_encode_ticket);
+
+  /* ap-options[2]	APOptions */
+  krb5_addfield(rep->ap_options,2,asn1_encode_ap_options);
+
+  /* msg-type[1]	INTEGER */
+  krb5_addfield(ASN1_KRB_AP_REQ,1,asn1_encode_integer);
+
+  /* pvno[0]		INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* AP-REQ ::=	[APPLICATION 14] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(14);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_ap_rep(const krb5_ap_rep *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* enc-part[2]	EncryptedData */
+  krb5_addfield(&(rep->enc_part),2,asn1_encode_encrypted_data);
+  
+  /* msg-type[1]	INTEGER */
+  krb5_addfield(ASN1_KRB_AP_REP,1,asn1_encode_integer);
+  
+  /* pvno[0]		INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+  
+  /* AP-REP ::=	[APPLICATION 15] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(15);
+  
+  krb5_cleanup();
+}
+
+
+krb5_error_code encode_krb5_ap_rep_enc_part(const krb5_ap_rep_enc_part *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* seq-number[3]	INTEGER OPTIONAL */
+  if(rep->seq_number)
+    krb5_addfield(rep->seq_number,3,asn1_encode_unsigned_integer);
+
+  /* subkey[2]		EncryptionKey OPTIONAL */
+  if(rep->subkey != NULL)
+    krb5_addfield(rep->subkey,2,asn1_encode_encryption_key);
+
+  /* cusec[1]		INTEGER */
+  krb5_addfield(rep->cusec,1,asn1_encode_integer);
+
+  /* ctime[0]		KerberosTime */
+  krb5_addfield(rep->ctime,0,asn1_encode_kerberos_time);
+
+  /* EncAPRepPart ::= [APPLICATION 27] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(27);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_as_req(const krb5_kdc_req *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* AS-REQ ::= [APPLICATION 10] KDC-REQ */
+  retval = asn1_encode_kdc_req(KRB5_AS_REQ,buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+  krb5_apptag(10);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_tgs_req(const krb5_kdc_req *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* TGS-REQ ::= [APPLICATION 12] KDC-REQ */
+  retval = asn1_encode_kdc_req(KRB5_TGS_REQ,buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+  krb5_apptag(12);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_kdc_req_body(const krb5_kdc_req *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  retval = asn1_encode_kdc_req_body(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+  krb5_cleanup();
+}
+
+
+krb5_error_code encode_krb5_safe(const krb5_safe *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* cksum[3]		Checksum */
+  krb5_addfield(rep->checksum,3,asn1_encode_checksum);
+
+  /* safe-body[2]	KRB-SAFE-BODY */
+  krb5_addfield(rep,2,asn1_encode_krb_safe_body);
+
+  /* msg-type[1]	INTEGER */
+  krb5_addfield(ASN1_KRB_SAFE,1,asn1_encode_integer);
+
+  /* pvno[0]		INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* KRB-SAFE ::= [APPLICATION 20] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(20);
+
+  krb5_cleanup();
+}
+
+/*
+ * encode_krb5_safe_with_body
+ *
+ * Like encode_krb5_safe(), except takes a saved KRB-SAFE-BODY
+ * encoding to avoid problems with re-encoding.
+ */
+krb5_error_code encode_krb5_safe_with_body(
+  const krb5_safe *rep,
+  const krb5_data *body,
+  krb5_data **code)
+{
+  krb5_setup();
+
+  if (body == NULL) {
+      asn1buf_destroy(&buf);
+      return ASN1_MISSING_FIELD;
+  }
+
+  /* cksum[3]		Checksum */
+  krb5_addfield(rep->checksum,3,asn1_encode_checksum);
+
+  /* safe-body[2]	KRB-SAFE-BODY */
+  krb5_addfield(body,2,asn1_encode_krb_saved_safe_body);
+
+  /* msg-type[1]	INTEGER */
+  krb5_addfield(ASN1_KRB_SAFE,1,asn1_encode_integer);
+
+  /* pvno[0]		INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* KRB-SAFE ::= [APPLICATION 20] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(20);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_priv(const krb5_priv *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* enc-part[3]	EncryptedData */
+  krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
+
+  /* msg-type[1]	INTEGER */
+  krb5_addfield(ASN1_KRB_PRIV,1,asn1_encode_integer);
+
+  /* pvno[0]		INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* KRB-PRIV ::= [APPLICATION 21] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(21);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_enc_priv_part(const krb5_priv_enc_part *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* r-address[5]	HostAddress OPTIONAL -- recip's addr */
+  if(rep->r_address)
+    krb5_addfield(rep->r_address,5,asn1_encode_host_address);
+
+  /* s-address[4]	HostAddress -- sender's addr */
+  krb5_addfield(rep->s_address,4,asn1_encode_host_address);
+
+  /* seq-number[3]	INTEGER OPTIONAL */
+  if(rep->seq_number)
+    krb5_addfield(rep->seq_number,3,asn1_encode_unsigned_integer);
+
+  /* usec[2]		INTEGER OPTIONAL */
+  if(rep->timestamp){
+    krb5_addfield(rep->usec,2,asn1_encode_integer);
+    /* timestamp[1]	KerberosTime OPTIONAL */
+    krb5_addfield(rep->timestamp,1,asn1_encode_kerberos_time);
+  }
+
+  /* user-data[0]	OCTET STRING */
+  krb5_addlenfield(rep->user_data.length,rep->user_data.data,0,asn1_encode_charstring);
+
+  /* EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(28);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_cred(const krb5_cred *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* enc-part[3]	EncryptedData */
+  krb5_addfield(&(rep->enc_part),3,asn1_encode_encrypted_data);
+
+  /* tickets[2]		SEQUENCE OF Ticket */
+  krb5_addfield((const krb5_ticket**)rep->tickets,2,asn1_encode_sequence_of_ticket);
+
+  /* msg-type[1]	INTEGER, -- KRB_CRED */
+  krb5_addfield(ASN1_KRB_CRED,1,asn1_encode_integer);
+
+  /* pvno[0]		INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* KRB-CRED ::= [APPLICATION 22] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(22);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_enc_cred_part(const krb5_cred_enc_part *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* r-address[5]	HostAddress OPTIONAL */
+  if(rep->r_address != NULL)
+    krb5_addfield(rep->r_address,5,asn1_encode_host_address);
+
+  /* s-address[4]	HostAddress OPTIONAL */
+  if(rep->s_address != NULL)
+    krb5_addfield(rep->s_address,4,asn1_encode_host_address);
+
+  /* usec[3]		INTEGER OPTIONAL */
+  if(rep->timestamp){
+    krb5_addfield(rep->usec,3,asn1_encode_integer);
+    /* timestamp[2]	KerberosTime OPTIONAL */
+    krb5_addfield(rep->timestamp,2,asn1_encode_kerberos_time);
+  }
+
+  /* nonce[1]		INTEGER OPTIONAL */
+  if(rep->nonce)
+    krb5_addfield(rep->nonce,1,asn1_encode_integer);
+
+  /* ticket-info[0]	SEQUENCE OF KrbCredInfo */
+  krb5_addfield((const krb5_cred_info**)rep->ticket_info,
+		0,asn1_encode_sequence_of_krb_cred_info);
+
+  /* EncKrbCredPart ::= [APPLICATION 29] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(29);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_error(const krb5_error *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* e-data[12]		OCTET STRING OPTIONAL */
+  if(rep->e_data.data != NULL && rep->e_data.length > 0)
+    krb5_addlenfield(rep->e_data.length,rep->e_data.data,12,asn1_encode_charstring);
+
+  /* e-text[11]		GeneralString OPTIONAL */
+  if(rep->text.data != NULL && rep->text.length > 0)
+    krb5_addlenfield(rep->text.length,rep->text.data,11,asn1_encode_generalstring);
+
+  /* sname[10]		PrincipalName -- Correct name */
+  krb5_addfield(rep->server,10,asn1_encode_principal_name);
+
+  /* realm[9]		Realm -- Correct realm */
+  krb5_addfield(rep->server,9,asn1_encode_realm);
+
+  /* cname[8]		PrincipalName OPTIONAL */
+  if(rep->client != NULL){
+    krb5_addfield(rep->client,8,asn1_encode_principal_name);
+    /* crealm[7]		Realm OPTIONAL */
+    krb5_addfield(rep->client,7,asn1_encode_realm);
+  }
+
+  /* error-code[6]	INTEGER */
+  krb5_addfield(rep->error,6,asn1_encode_ui_4);
+
+  /* susec[5]		INTEGER */
+  krb5_addfield(rep->susec,5,asn1_encode_integer);
+
+  /* stime[4]		KerberosTime */
+  krb5_addfield(rep->stime,4,asn1_encode_kerberos_time);
+
+  /* cusec[3]		INTEGER OPTIONAL */
+  if(rep->cusec)
+    krb5_addfield(rep->cusec,3,asn1_encode_integer);
+
+  /* ctime[2]		KerberosTime OPTIONAL */
+  if(rep->ctime)
+    krb5_addfield(rep->ctime,2,asn1_encode_kerberos_time);
+
+  /* msg-type[1]	INTEGER */
+  krb5_addfield(ASN1_KRB_ERROR,1,asn1_encode_integer);
+
+  /* pvno[0]		INTEGER */
+  krb5_addfield(KVNO,0,asn1_encode_integer);
+
+  /* KRB-ERROR ::= [APPLICATION 30] SEQUENCE */
+  krb5_makeseq();
+  krb5_apptag(30);
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_authdata(const krb5_authdata **rep, krb5_data **code)
+{
+  asn1_error_code retval;
+  asn1buf *buf=NULL;
+  unsigned int length;
+  
+  if(rep == NULL) return ASN1_MISSING_FIELD;
+
+  retval = asn1buf_create(&buf);
+  if(retval) return retval;
+
+  retval = asn1_encode_authorization_data(buf,(const krb5_authdata**)rep,
+					  &length);
+  if(retval) return retval;
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_authdata_elt(const krb5_authdata *rep, krb5_data **code)
+{
+  asn1_error_code retval;
+  asn1buf *buf=NULL;
+  unsigned int length;
+  
+  if(rep == NULL) return ASN1_MISSING_FIELD;
+
+  retval = asn1buf_create(&buf);
+  if(retval) return retval;
+
+  retval = asn1_encode_krb5_authdata_elt(buf,rep, &length);
+  if(retval) return retval;
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_alt_method(const krb5_alt_method *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* method-data[1]		OctetString OPTIONAL */
+  if(rep->data != NULL && rep->length > 0)
+    krb5_addlenfield(rep->length,rep->data,1,asn1_encode_octetstring);
+
+  /* method-type[0]		Integer */
+  krb5_addfield(rep->method,0,asn1_encode_integer);
+
+  krb5_makeseq();
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_etype_info(const krb5_etype_info_entry **rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_etype_info(buf,rep,&length, 0);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_etype_info2(const krb5_etype_info_entry **rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_etype_info(buf,rep,&length, 1);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+  
+
+krb5_error_code encode_krb5_enc_data(const krb5_enc_data *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  retval = asn1_encode_encrypted_data(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_enc_ts(const krb5_pa_enc_ts *rep, krb5_data **code)
+{
+  krb5_setup();
+
+  /* pausec[1]                    INTEGER OPTIONAL */
+  if (rep->pausec)
+	  krb5_addfield(rep->pausec,1,asn1_encode_integer);
+
+  /* patimestamp[0]               KerberosTime, -- client's time */
+  krb5_addfield(rep->patimestamp,0,asn1_encode_kerberos_time);
+
+  krb5_makeseq();
+
+  krb5_cleanup();
+}
+
+/* Sandia Additions */
+krb5_error_code encode_krb5_pwd_sequence(const passwd_phrase_element *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_passwdsequence(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pwd_data(const krb5_pwd_data *rep, krb5_data **code)
+{
+  krb5_setup();
+  krb5_addfield((const passwd_phrase_element**)rep->element,1,asn1_encode_sequence_of_passwdsequence);
+  krb5_addfield(rep->sequence_count,0,asn1_encode_integer);
+  krb5_makeseq();
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_padata_sequence(const krb5_pa_data **rep, krb5_data **code)
+{
+  krb5_setup();
+
+  retval = asn1_encode_sequence_of_pa_data(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+
+  krb5_cleanup();
+}
+
+/* sam preauth additions */
+krb5_error_code encode_krb5_sam_challenge(const krb5_sam_challenge *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sam_challenge(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_sam_challenge_2(const krb5_sam_challenge_2 *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sam_challenge_2(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_sam_challenge_2_body(const krb5_sam_challenge_2_body *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sam_challenge_2_body(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_sam_key(const krb5_sam_key *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sam_key(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_enc_sam_response_enc(const krb5_enc_sam_response_enc *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_enc_sam_response_enc(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_enc_sam_response_enc_2(const krb5_enc_sam_response_enc_2 *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_enc_sam_response_enc_2(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_sam_response(const krb5_sam_response *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sam_response(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_sam_response_2(const krb5_sam_response_2 *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sam_response_2(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_predicted_sam_response(const krb5_predicted_sam_response *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_predicted_sam_response(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_setpw_req(const krb5_principal target,
+				      char *password, krb5_data **code)
+{
+  /* Macros really want us to have a variable called rep which we do not need*/
+  const char *rep = "dummy string";
+
+  krb5_setup();
+
+  krb5_addfield(target,2,asn1_encode_realm);
+  krb5_addfield(target,1,asn1_encode_principal_name);
+  krb5_addlenfield(strlen(password), password,0,asn1_encode_octetstring);
+  krb5_makeseq();
+
+
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_pk_as_req(const krb5_pa_pk_as_req *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_pa_pk_as_req(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_pk_as_req_draft9(const krb5_pa_pk_as_req_draft9 *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_pa_pk_as_req_draft9(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_pk_as_rep(const krb5_pa_pk_as_rep *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_pa_pk_as_rep(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_pk_as_rep_draft9(const krb5_pa_pk_as_rep_draft9 *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_pa_pk_as_rep_draft9(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_auth_pack(const krb5_auth_pack *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_auth_pack(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_auth_pack_draft9(const krb5_auth_pack_draft9 *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_auth_pack_draft9(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_kdc_dh_key_info(const krb5_kdc_dh_key_info *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_kdc_dh_key_info(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_reply_key_pack(const krb5_reply_key_pack *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_reply_key_pack(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_reply_key_pack_draft9(const krb5_reply_key_pack_draft9 *rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_reply_key_pack_draft9(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_td_trusted_certifiers(const krb5_external_principal_identifier **rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_td_trusted_certifiers(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_typed_data(const krb5_typed_data **rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sequence_of_typed_data(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_td_dh_parameters(const krb5_algorithm_identifier **rep, krb5_data **code)
+{
+  krb5_setup();
+  retval = asn1_encode_sequence_of_algorithm_identifier(buf,rep,&length);
+  if(retval) return retval;
+  sum += length;
+  krb5_cleanup();
+}
diff --git a/krb5-1-6/src/lib/krb5/asn.1/krbasn1.h b/krb5-1-6/src/lib/krb5/asn.1/krbasn1.h
new file mode 100644
index 000000000..7a45298ad
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/krbasn1.h
@@ -0,0 +1,81 @@
+#ifndef __KRBASN1_H__
+#define __KRBASN1_H__
+
+#include "k5-int.h"
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>		/* For INT_MAX */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+/*
+ * Older versions of the Kerberos are always sending the
+ * enc_kdc_rep_part structure with an application tag of #26, instead
+ * of using the application tag of #25 (AS REP) or #26 (AS REP) as
+ * necessary.  Worse yet, they will only accept a tag of #26, so we
+ * need to follow this for backwards compatibility.  #defining
+ * KRB5_ENCKRB5KDCREPPART_COMPAT will preserve this wrong (but
+ * compatible) behavior.
+ */
+#define KRB5_ENCKRB5KDCREPPART_COMPAT
+
+/*
+ * If KRB5_MSGTYPE_STRICT is defined, then be strict about checking
+ * the msgtype fields.  Unfortunately, there old versions of Kerberos
+ * don't set these fields correctly, so we have to make allowances for
+ * them.
+ */
+/* #define KRB5_MSGTYPE_STRICT */
+
+/*
+ * If KRB5_GENEROUS_LR_TYPE is defined, then we are generous about
+ * accepting a one byte negative lr_type - which is not sign
+ * extended. Prior to July 2000, we were sending a negative lr_type as
+ * a positve single byte value - instead of a signed integer. This
+ * allows us to receive the old value and deal
+ */
+#define KRB5_GENEROUS_LR_TYPE
+
+typedef krb5_octet asn1_octet;
+typedef krb5_error_code asn1_error_code;
+
+typedef enum { PRIMITIVE = 0x00, CONSTRUCTED = 0x20 } asn1_construction;
+
+typedef enum { UNIVERSAL = 0x00, APPLICATION = 0x40,
+		 CONTEXT_SPECIFIC = 0x80, PRIVATE = 0xC0 } asn1_class;
+
+typedef int asn1_tagnum;
+#define ASN1_TAGNUM_CEILING INT_MAX
+#define ASN1_TAGNUM_MAX (ASN1_TAGNUM_CEILING-1)
+
+/* This is Kerberos Version 5 */
+#define KVNO 5
+
+/* Universal Tag Numbers */
+#define ASN1_INTEGER		2
+#define ASN1_BITSTRING		3
+#define ASN1_OCTETSTRING	4
+#define ASN1_NULL		5
+#define ASN1_OBJECTIDENTIFIER	6
+#define ASN1_ENUMERATED 10
+#define ASN1_SEQUENCE		16
+#define ASN1_SET		17
+#define ASN1_PRINTABLESTRING	19
+#define ASN1_IA5STRING		22
+#define ASN1_UTCTIME		23
+#define ASN1_GENERALTIME	24
+#define ASN1_GENERALSTRING	27
+
+/* Kerberos Message Types */
+#define ASN1_KRB_AS_REQ		10
+#define ASN1_KRB_AS_REP		11
+#define ASN1_KRB_TGS_REQ	12
+#define ASN1_KRB_TGS_REP	13
+#define ASN1_KRB_AP_REQ		14
+#define ASN1_KRB_AP_REP		15
+#define ASN1_KRB_SAFE		20
+#define ASN1_KRB_PRIV		21
+#define ASN1_KRB_CRED		22
+#define ASN1_KRB_ERROR		30
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/asn.1/ldap_key_seq.c b/krb5-1-6/src/lib/krb5/asn.1/ldap_key_seq.c
new file mode 100644
index 000000000..1fe9a548f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/asn.1/ldap_key_seq.c
@@ -0,0 +1,479 @@
+/* ... copyright ... */
+
+/* Novell key-format scheme:
+
+   KrbKeySet ::= SEQUENCE {
+   attribute-major-vno       [0] UInt16,
+   attribute-minor-vno       [1] UInt16,
+   kvno                      [2] UInt32,
+   mkvno                     [3] UInt32 OPTIONAL,
+   keys                      [4] SEQUENCE OF KrbKey,
+   ...
+   }
+
+   KrbKey ::= SEQUENCE {
+   salt      [0] KrbSalt OPTIONAL,
+   key       [1] EncryptionKey,
+   s2kparams [2] OCTET STRING OPTIONAL,
+    ...
+   }
+
+   KrbSalt ::= SEQUENCE {
+   type      [0] Int32,
+   salt      [1] OCTET STRING OPTIONAL
+   }
+
+   EncryptionKey ::= SEQUENCE {
+   keytype   [0] Int32,
+   keyvalue  [1] OCTET STRING
+   }
+
+ */
+
+#include <k5-int.h>
+#include <kdb.h>
+
+#include "krbasn1.h"
+#include "asn1_encode.h"
+#include "asn1_decode.h"
+#include "asn1_make.h"
+#include "asn1_get.h"
+
+#define asn1_encode_sequence_of_keys krb5int_ldap_encode_sequence_of_keys
+#define asn1_decode_sequence_of_keys krb5int_ldap_decode_sequence_of_keys
+
+#define cleanup(err)							\
+	{								\
+		ret = err;						\
+		goto last;						\
+	}
+
+#define checkerr							\
+		if (ret != 0)						\
+			goto last
+
+/************************************************************************/
+/* Encode the Principal's keys						*/
+/************************************************************************/
+
+static asn1_error_code
+asn1_encode_key(asn1buf *buf,
+		krb5_key_data key_data,
+		unsigned int *retlen)
+{
+    asn1_error_code ret = 0;
+    unsigned int length, sum = 0;
+
+    /* Encode the key type and value.  */
+    {
+	unsigned int key_len = 0;
+	/* key value */
+	ret = asn1_encode_octetstring (buf,
+				       key_data.key_data_length[0],
+				       key_data.key_data_contents[0],
+				       &length); checkerr;
+	key_len += length;
+	ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr;
+	key_len += length;
+	/* key type */
+	ret = asn1_encode_integer (buf, key_data.key_data_type[0], &length);
+	checkerr;
+	key_len += length;
+	ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
+	key_len += length;
+
+	ret = asn1_make_sequence(buf, key_len, &length); checkerr;
+	key_len += length;
+	ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, key_len, &length); checkerr;
+	key_len += length;
+
+	sum += key_len;
+    }
+    /* Encode the salt type and value (optional) */
+    if (key_data.key_data_ver > 1) {
+	unsigned int salt_len = 0;
+	/* salt value (optional) */
+	if (key_data.key_data_length[1] > 0) {
+	    ret = asn1_encode_octetstring (buf,
+					   key_data.key_data_length[1],
+					   key_data.key_data_contents[1],
+					   &length); checkerr;
+	    salt_len += length;
+	    ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length);
+	    checkerr;
+	    salt_len += length;
+	}
+	/* salt type */
+	ret = asn1_encode_integer (buf, key_data.key_data_type[1], &length);
+	checkerr;
+	salt_len += length;
+	ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
+	salt_len += length;
+
+	ret = asn1_make_sequence(buf, salt_len, &length); checkerr;
+	salt_len += length;
+	ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, salt_len, &length); checkerr;
+	salt_len += length;
+
+	sum += salt_len;
+    }
+
+    ret = asn1_make_sequence(buf, sum, &length); checkerr;
+    sum += length;
+
+    *retlen = sum;
+
+last:
+    return ret;
+}
+
+/* Major version and minor version are both '1' - first version */
+/* asn1_error_code asn1_encode_sequence_of_keys (krb5_key_data *key_data, */
+krb5_error_code
+asn1_encode_sequence_of_keys (krb5_key_data *key_data,
+			      krb5_int16 n_key_data,
+			      krb5_int32 mkvno,	/* Master key version number */
+			      krb5_data **code)
+{
+    asn1_error_code ret = 0;
+    asn1buf *buf = NULL;
+    unsigned int length, sum = 0;
+    unsigned long tmp_ul;
+
+    *code = NULL;
+
+    if (n_key_data == 0) cleanup (ASN1_MISSING_FIELD);
+
+    /* Allocate the buffer */
+    ret = asn1buf_create(&buf);
+    checkerr;
+
+    /* Sequence of keys */
+    {
+	int i;
+	unsigned int seq_len = 0;
+
+	for (i = n_key_data - 1; i >= 0; i--) {
+	    ret = asn1_encode_key (buf, key_data[i], &length); checkerr;
+	    seq_len += length;
+	}
+	ret = asn1_make_sequence(buf, seq_len, &length); checkerr;
+	seq_len += length;
+	ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 4, seq_len, &length); checkerr;
+	seq_len += length;
+
+	sum += seq_len;
+    }
+
+    /* mkvno */
+    if (mkvno < 0)
+	cleanup (ASN1_BAD_FORMAT);
+    tmp_ul = (unsigned long)mkvno;
+    ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length); checkerr;
+    sum += length;
+    ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 3, length, &length); checkerr;
+    sum += length;
+
+    /* kvno (assuming all keys in array have same version) */
+    if (key_data[0].key_data_kvno < 0)
+	cleanup (ASN1_BAD_FORMAT);
+    tmp_ul = (unsigned long)key_data[0].key_data_kvno;
+    ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length);
+    checkerr;
+    sum += length;
+    ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 2, length, &length); checkerr;
+    sum += length;
+
+    /* attribute-minor-vno == 1 */
+    ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr;
+    sum += length;
+    ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr;
+    sum += length;
+
+    /* attribute-major-vno == 1 */
+    ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr;
+    sum += length;
+    ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr;
+    sum += length;
+
+    ret = asn1_make_sequence(buf, sum, &length); checkerr;
+    sum += length;
+
+    /* The reverse encoding is straightened out here */
+    ret = asn12krb5_buf (buf, code); checkerr;
+
+last:
+    asn1buf_destroy (&buf);
+
+    if (ret != 0 && *code != NULL) {
+        if ((*code)->data != NULL)
+            free ((*code)->data);
+        free (*code);
+    }
+
+    return ret;
+}
+
+/************************************************************************/
+/* Decode the Principal's keys						*/
+/************************************************************************/
+
+#define safe_syncbuf(outer,inner)					\
+	if (! ((inner)->next == (inner)->bound + 1 &&			\
+	       (inner)->next == (outer)->next + buflen))		\
+	    cleanup (ASN1_BAD_LENGTH);					\
+	asn1buf_sync((outer), (inner), 0, 0, 0, 0, 0);
+
+static asn1_error_code
+decode_tagged_integer (asn1buf *buf, asn1_tagnum expectedtag, long *val)
+{
+    int buflen;
+    asn1_error_code ret = 0;
+    asn1buf tmp, subbuf;
+    taginfo t;
+
+    /* Work on a copy of 'buf' */
+    ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
+    ret = asn1_get_tag_2(&tmp, &t); checkerr;
+    if (t.tagnum != expectedtag)
+	cleanup (ASN1_MISSING_FIELD);
+
+    buflen = t.length;
+    ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
+    ret = asn1_decode_integer(&subbuf, val); checkerr;
+
+    safe_syncbuf(&tmp, &subbuf);
+    *buf = tmp;
+
+last:
+    return ret;
+}
+
+#if 0 /* not currently used */
+static asn1_error_code
+decode_tagged_unsigned_integer (asn1buf *buf, int expectedtag, unsigned long *val)
+{
+    int buflen;
+    asn1_error_code ret = 0;
+    asn1buf tmp, subbuf;
+    taginfo t;
+
+    /* Work on a copy of 'buf' */
+    ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
+    ret = asn1_get_tag_2(&tmp, &t); checkerr;
+    if (t.tagnum != expectedtag)
+	cleanup (ASN1_MISSING_FIELD);
+
+    buflen = t.length;
+    ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
+    ret = asn1_decode_unsigned_integer(&subbuf, val); checkerr;
+
+    safe_syncbuf(&tmp, &subbuf);
+    *buf = tmp;
+
+last:
+    return ret;
+}
+#endif
+
+static asn1_error_code
+decode_tagged_octetstring (asn1buf *buf, asn1_tagnum expectedtag, int *len,
+			   asn1_octet **val)
+{
+    int buflen;
+    asn1_error_code ret = 0;
+    asn1buf tmp, subbuf;
+    taginfo t;
+
+    *val = NULL;
+
+    /* Work on a copy of 'buf' */
+    ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr;
+    ret = asn1_get_tag_2(&tmp, &t); checkerr;
+    if (t.tagnum != expectedtag)
+	cleanup (ASN1_MISSING_FIELD);
+
+    buflen = t.length;
+    ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr;
+    ret = asn1_decode_octetstring (&subbuf, len, val); checkerr;
+
+    safe_syncbuf(&tmp, &subbuf);
+    *buf = tmp;
+
+last:
+    if (ret != 0 && *val != NULL)
+	free (*val);
+    return ret;
+}
+
+static asn1_error_code asn1_decode_key(asn1buf *buf, krb5_key_data *key)
+{
+    int buflen, seqindef;
+    unsigned int length;
+    asn1_error_code ret;
+    asn1buf subbuf;
+    taginfo t;
+
+    key->key_data_contents[0] = NULL;
+    key->key_data_contents[1] = NULL;
+
+    ret = asn1_get_sequence(buf, &length, &seqindef); checkerr;
+    buflen = length;
+    ret = asn1buf_imbed(&subbuf, buf, length, seqindef); checkerr;
+
+    asn1_get_tag_2(&subbuf, &t);
+    /* Salt */
+    if (t.tagnum == 0) {
+	int buflen;
+	asn1buf slt;
+	unsigned long keytype;
+	int keylen;
+
+	key->key_data_ver = 2;
+	asn1_get_sequence(&subbuf, &length, &seqindef);
+	buflen = length;
+	asn1buf_imbed(&slt, &subbuf, length, seqindef);
+
+	ret = decode_tagged_integer (&slt, 0, &keytype);
+	key->key_data_type[1] = keytype; /* XXX range check?? */
+	checkerr;
+
+	if (asn1buf_remains(&slt, 0) != 0) { /* Salt value is optional */
+	    ret = decode_tagged_octetstring (&slt, 1, &keylen,
+		    &key->key_data_contents[1]); checkerr;
+	}
+	safe_syncbuf (&subbuf, &slt);
+	key->key_data_length[1] = keylen; /* XXX range check?? */
+
+	ret = asn1_get_tag_2(&subbuf, &t); checkerr;
+    } else
+	key->key_data_ver = 1;
+
+    /* Key */
+    {
+	int buflen;
+	asn1buf kbuf;
+	long lval;
+	int ival;
+
+	if (t.tagnum != 1)
+	    cleanup (ASN1_MISSING_FIELD);
+
+	ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
+	buflen = length;
+	ret = asn1buf_imbed(&kbuf, &subbuf, length, seqindef); checkerr;
+
+	ret = decode_tagged_integer (&kbuf, 0, &lval);
+	checkerr;
+	key->key_data_type[0] = lval; /* XXX range check? */
+
+	ret = decode_tagged_octetstring (&kbuf, 1, &ival,
+					 &key->key_data_contents[0]); checkerr;
+	key->key_data_length[0] = ival;	/* XXX range check? */
+
+	safe_syncbuf (&subbuf, &kbuf);
+    }
+
+    safe_syncbuf (buf, &subbuf);
+
+last:
+    if (ret != 0) {
+	if (key->key_data_contents[0] != NULL) {
+	    free (key->key_data_contents[0]);
+	    key->key_data_contents[0] = NULL;
+	}
+	if (key->key_data_contents[1] != NULL) {
+	    free (key->key_data_contents[1]);
+	    key->key_data_contents[1] = NULL;
+	}
+    }
+    return ret;
+}
+
+/* asn1_error_code asn1_decode_sequence_of_keys (krb5_data *in, */
+krb5_error_code asn1_decode_sequence_of_keys (krb5_data *in,
+					      krb5_key_data **out,
+					      krb5_int16 *n_key_data,
+					      int *mkvno)
+{
+    asn1_error_code ret;
+    asn1buf buf, subbuf;
+    int seqindef;
+    unsigned int length;
+    taginfo t;
+    int kvno, maj, min;
+    long lval;
+
+    *n_key_data = 0;
+    *out = NULL;
+
+    ret = asn1buf_wrap_data(&buf, in); checkerr;
+
+    ret = asn1_get_sequence(&buf, &length, &seqindef); checkerr;
+    ret = asn1buf_imbed(&subbuf, &buf, length, seqindef); checkerr;
+
+    /* attribute-major-vno */
+    ret = decode_tagged_integer (&subbuf, 0, &lval); checkerr;
+    maj = lval;			/* XXX range check? */
+
+    /* attribute-minor-vno */
+    ret = decode_tagged_integer (&subbuf, 1, &lval); checkerr;
+    min = lval;			/* XXX range check? */
+
+    if (maj != 1 || min != 1)
+	cleanup (ASN1_BAD_FORMAT);
+
+    /* kvno (assuming all keys in array have same version) */
+    ret = decode_tagged_integer (&subbuf, 2, &lval); checkerr;
+    kvno = lval;		/* XXX range check? */
+
+    /* mkvno (optional) */
+    ret = decode_tagged_integer (&subbuf, 3, &lval); checkerr;
+    *mkvno = lval;		/* XXX range check? */
+
+    ret = asn1_get_tag_2(&subbuf, &t); checkerr;
+
+    /* Sequence of keys */
+    {
+	int i, buflen;
+	asn1buf keyseq;
+	if (t.tagnum != 4)
+	    cleanup (ASN1_MISSING_FIELD);
+	ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr;
+	buflen = length;
+	ret = asn1buf_imbed(&keyseq, &subbuf, length, seqindef); checkerr;
+	for (i = 1, *out = NULL; ; i++) {
+	    krb5_key_data *tmp;
+	    tmp = (krb5_key_data *) realloc (*out, i * sizeof (krb5_key_data));
+	    if (tmp == NULL)
+		cleanup (ENOMEM);
+	    *out = tmp;
+	    (*out)[i - 1].key_data_kvno = kvno;
+	    ret = asn1_decode_key(&keyseq, &(*out)[i - 1]); checkerr;
+	    (*n_key_data)++;
+	    if (asn1buf_remains(&keyseq, 0) == 0)
+		break; /* Not freeing the last key structure */
+	}
+	safe_syncbuf (&subbuf, &keyseq);
+    }
+
+    /*
+     * There could be other data inside the outermost sequence ... tags we don't
+     * know about. So, not invoking "safe_syncbuf(&buf,&subbuf)"
+     */
+
+last:
+    if (ret != 0) {
+	int i;
+	for (i = 0; i < *n_key_data; i++) {
+	    if ((*out)[i].key_data_contents[0] != NULL)
+		free ((*out)[i].key_data_contents[0]);
+	    if ((*out)[i].key_data_contents[1] != NULL)
+		free ((*out)[i].key_data_contents[1]);
+	}
+	free (*out);
+	*out = NULL;
+    }
+
+    return ret;
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/Makefile.in b/krb5-1-6/src/lib/krb5/ccache/Makefile.in
new file mode 100644
index 000000000..7d4b1d866
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/Makefile.in
@@ -0,0 +1,213 @@
+thisconfigdir=../../..
+myfulldir=lib/krb5/ccache
+mydir=lib/krb5/ccache
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCAL_SUBDIRS =
+DEFS=
+
+RUN_SETUP = @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+LOCALINCLUDES = -I$(srcdir)$(S)ccapi $(WIN_INCLUDES)
+
+##DOS##WIN_INCLUDES = -I$(SRCTOP)\windows\lib
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=ccache
+##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst
+
+##WIN32##MSLSA_OBJ = $(OUTPRE)cc_mslsa.$(OBJEXT)
+##WIN32##MSLSA_SRC = $(srcdir)/cc_mslsa.c
+
+STLIBOBJS= \
+	ccbase.o \
+	cccopy.o \
+	cccursor.o \
+	ccdefault.o \
+	ccdefops.o \
+	cc_retr.o \
+	cc_file.o \
+	cc_memory.o \
+	cc_keyring.o \
+	ccfns.o \
+	ser_cc.o
+
+OBJS=	$(OUTPRE)ccbase.$(OBJEXT) \
+	$(OUTPRE)cccopy.$(OBJEXT) \
+	$(OUTPRE)cccursor.$(OBJEXT) \
+	$(OUTPRE)ccdefault.$(OBJEXT) \
+	$(OUTPRE)ccdefops.$(OBJEXT) \
+	$(OUTPRE)cc_retr.$(OBJEXT) \
+	$(OUTPRE)cc_file.$(OBJEXT) \
+	$(OUTPRE)cc_memory.$(OBJEXT) \
+	$(OUTPRE)cc_keyring.$(OBJEXT) \
+	$(OUTPRE)ccfns.$(OBJEXT) \
+	$(OUTPRE)ser_cc.$(OBJEXT) $(MSLSA_OBJ)
+
+SRCS=	$(srcdir)/ccbase.c \
+	$(srcdir)/cccopy.c \
+	$(srcdir)/cccursor.c \
+	$(srcdir)/ccdefault.c \
+	$(srcdir)/ccdefops.c \
+	$(srcdir)/cc_retr.c \
+	$(srcdir)/cc_file.c \
+	$(srcdir)/cc_memory.c \
+	$(srcdir)/cc_keyring.c \
+	$(srcdir)/ccfns.c \
+	$(srcdir)/ser_cc.c $(MSLSA_SRC)
+
+##DOS##OBJS=$(OBJS) $(OUTPRE)ccfns.$(OBJEXT)
+
+all-unix:: all-libobjs
+
+all-windows:: subdirs $(OBJFILE) 
+
+##DOS##subdirs:: ccapi\$(OUTPRE)file.lst
+
+##DOS##ccapi\$(OUTPRE)file.lst::
+##DOS##	cd ccapi
+##DOS##	@echo Making in krb5\ccache\ccapi
+##DOS##	$(MAKE) -$(MFLAGS)
+##DOS##	cd ..
+
+##DOS##$(OBJFILE): $(OBJS) ccapi\$(OUTPRE)file.lst
+##DOS##	$(RM) $(OBJFILE)
+##WIN32##	$(LIBECHO) -p $(PREFIXDIR)\ $(OUTPRE)*.obj \
+##WIN32##		ccapi\$(OUTPRE)*.obj > $(OBJFILE)
+
+
+clean-unix:: clean-libobjs
+
+clean-windows::
+	cd ccapi
+	@echo Making clean in krb5\ccache\ccapi
+	$(MAKE) -$(MFLAGS) clean
+	cd ..
+	@echo Making clean in krb5\ccache
+	$(RM) $(OBJFILE)
+
+T_CC_OBJS=t_cc.o
+
+t_cc: $(T_CC_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_cc $(T_CC_OBJS) $(KRB5_BASE_LIBS)
+
+T_CCCURSOR_OBJS = t_cccursor.o
+t_cccursor: $(T_CCCURSOR_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $@ $(T_CCCURSOR_OBJS) $(KRB5_BASE_LIBS)
+
+check-unix:: t_cc
+	KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\
+	$(RUN_SETUP) $(VALGRIND) ./t_cc 
+
+clean-unix::
+	$(RM) t_cc t_cc.o
+
+##WIN32## $(OUTPRE)cc_mslsa.$(OBJEXT): cc_mslsa.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS)
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+ccbase.so ccbase.po $(OUTPRE)ccbase.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  cc-int.h ccbase.c fcc.h
+cccopy.so cccopy.po $(OUTPRE)cccopy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  cccopy.c
+cccursor.so cccursor.po $(OUTPRE)cccursor.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cccursor.c
+ccdefault.so ccdefault.po $(OUTPRE)ccdefault.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h ccdefault.c
+ccdefops.so ccdefops.po $(OUTPRE)ccdefops.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h ccdefops.c fcc.h
+cc_retr.so cc_retr.po $(OUTPRE)cc_retr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  cc-int.h cc_retr.c
+cc_file.so cc_file.po $(OUTPRE)cc_file.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  cc_file.c
+cc_memory.so cc_memory.po $(OUTPRE)cc_memory.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cc_memory.c
+cc_keyring.so cc_keyring.po $(OUTPRE)cc_keyring.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cc_keyring.c
+ccfns.so ccfns.po $(OUTPRE)ccfns.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ccfns.c
+ser_cc.so ser_cc.po $(OUTPRE)ser_cc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ser_cc.c
diff --git a/krb5-1-6/src/lib/krb5/ccache/cc-int.h b/krb5-1-6/src/lib/krb5/ccache/cc-int.h
new file mode 100644
index 000000000..430e4c375
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cc-int.h
@@ -0,0 +1,49 @@
+/*
+ * lib/krb5/ccache/file/cc-int.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This file contains constant and function declarations used in the
+ * file-based credential cache routines.
+ */
+
+#ifndef __KRB5_CCACHE_H__
+#define __KRB5_CCACHE_H__
+
+#include "k5-int.h"
+
+krb5_boolean
+krb5int_cc_creds_match_request(krb5_context, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds);
+
+int
+krb5int_cc_initialize(void);
+
+void
+krb5int_cc_finalize(void);
+
+extern k5_mutex_t krb5int_mcc_mutex;
+extern k5_mutex_t krb5int_krcc_mutex;
+extern k5_mutex_t krb5int_cc_file_mutex;
+
+#endif /* __KRB5_CCACHE_H__ */
diff --git a/krb5-1-6/src/lib/krb5/ccache/cc_file.c b/krb5-1-6/src/lib/krb5/ccache/cc_file.c
new file mode 100644
index 000000000..b11bbb9d2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cc_file.c
@@ -0,0 +1,2446 @@
+/*
+ * lib/krb5/ccache/cc_file.c
+ *
+ * Copyright 1990,1991,1992,1993,1994,2000,2004 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Original stdio support copyright 1995 by Cygnus Support.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * implementation of file-based credentials cache
+ */
+
+/*
+If OPENCLOSE is defined, each of the functions opens and closes the
+file whenever it needs to access it.  Otherwise, the file is opened
+once in initialize and closed once is close.
+
+This library depends on UNIX-like file descriptors, and UNIX-like
+behavior from the functions: open, close, read, write, lseek.
+
+The quasi-BNF grammar for a credentials cache:
+
+file ::= 
+        principal list-of-credentials
+
+credential ::=
+	client (principal)
+	server (principal)
+	keyblock (keyblock)
+	times (ticket_times)
+	is_skey (boolean)
+	ticket_flags (flags)
+	ticket (data)
+	second_ticket (data)
+
+principal ::= 
+	number of components (int32)
+	component 1 (data)
+	component 2 (data)
+	...
+	
+data ::=
+	length (int32)
+	string of length bytes
+
+etc.
+ */
+/* todo:
+   Make sure that each time a function returns KRB5_NOMEM, everything
+   allocated earlier in the function and stack tree is freed.
+
+   File locking
+
+   Use pread/pwrite if available, so multiple threads can read
+   simultaneously.  (That may require reader/writer locks.)
+
+   fcc_nseq.c and fcc_read don't check return values a lot.
+ */
+#include "k5-int.h"
+
+
+#include <stdio.h>
+#include <errno.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#if !defined(_WIN32)
+#include <netinet/in.h>
+#else
+#include "port-sockets.h"
+#endif
+#else
+# error find some way to use net-byte-order file version numbers.
+#endif
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_close
+        (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_destroy
+        (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_end_seq_get
+        (krb5_context, krb5_ccache id, krb5_cc_cursor *cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_generate_new
+        (krb5_context, krb5_ccache *id);
+
+static const char * KRB5_CALLCONV krb5_fcc_get_name
+        (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_get_principal
+        (krb5_context, krb5_ccache id, krb5_principal *princ);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_initialize
+        (krb5_context, krb5_ccache id, krb5_principal princ);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_next_cred
+        (krb5_context, krb5_ccache id, krb5_cc_cursor *cursor,
+	 krb5_creds *creds);
+
+static krb5_error_code krb5_fcc_read
+        (krb5_context, krb5_ccache id, krb5_pointer buf, unsigned int len);
+static krb5_error_code krb5_fcc_read_principal
+        (krb5_context, krb5_ccache id, krb5_principal *princ);
+static krb5_error_code krb5_fcc_read_keyblock
+        (krb5_context, krb5_ccache id, krb5_keyblock *keyblock);
+static krb5_error_code krb5_fcc_read_data
+        (krb5_context, krb5_ccache id, krb5_data *data);
+static krb5_error_code krb5_fcc_read_int32
+        (krb5_context, krb5_ccache id, krb5_int32 *i);
+static krb5_error_code krb5_fcc_read_ui_2
+        (krb5_context, krb5_ccache id, krb5_ui_2 *i);
+static krb5_error_code krb5_fcc_read_octet
+        (krb5_context, krb5_ccache id, krb5_octet *i);
+static krb5_error_code krb5_fcc_read_times
+        (krb5_context, krb5_ccache id, krb5_ticket_times *t);
+static krb5_error_code krb5_fcc_read_addrs
+        (krb5_context, krb5_ccache, krb5_address ***);
+static krb5_error_code krb5_fcc_read_addr
+        (krb5_context, krb5_ccache, krb5_address *);
+static krb5_error_code krb5_fcc_read_authdata
+        (krb5_context, krb5_ccache, krb5_authdata ***);
+static krb5_error_code krb5_fcc_read_authdatum
+        (krb5_context, krb5_ccache, krb5_authdata *);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_resolve
+        (krb5_context, krb5_ccache *id, const char *residual);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_retrieve
+        (krb5_context, krb5_ccache id, krb5_flags whichfields,
+	 krb5_creds *mcreds, krb5_creds *creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_start_seq_get
+        (krb5_context, krb5_ccache id, krb5_cc_cursor *cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_store
+        (krb5_context, krb5_ccache id, krb5_creds *creds);
+
+static krb5_error_code krb5_fcc_skip_header
+        (krb5_context, krb5_ccache);
+static krb5_error_code krb5_fcc_skip_principal
+        (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_set_flags
+        (krb5_context, krb5_ccache id, krb5_flags flags);
+
+extern const krb5_cc_ops krb5_cc_file_ops;
+
+krb5_error_code krb5_change_cache (void);
+
+static krb5_error_code krb5_fcc_write
+        (krb5_context, krb5_ccache id, krb5_pointer buf, unsigned int len);
+static krb5_error_code krb5_fcc_store_principal
+        (krb5_context, krb5_ccache id, krb5_principal princ);
+static krb5_error_code krb5_fcc_store_keyblock
+        (krb5_context, krb5_ccache id, krb5_keyblock *keyblock);
+static krb5_error_code krb5_fcc_store_data
+        (krb5_context, krb5_ccache id, krb5_data *data);
+static krb5_error_code krb5_fcc_store_int32
+        (krb5_context, krb5_ccache id, krb5_int32 i);
+static krb5_error_code krb5_fcc_store_ui_4
+        (krb5_context, krb5_ccache id, krb5_ui_4 i);
+static krb5_error_code krb5_fcc_store_ui_2
+        (krb5_context, krb5_ccache id, krb5_int32 i);
+static krb5_error_code krb5_fcc_store_octet
+        (krb5_context, krb5_ccache id, krb5_int32 i);
+static krb5_error_code krb5_fcc_store_times
+        (krb5_context, krb5_ccache id, krb5_ticket_times *t);
+static krb5_error_code krb5_fcc_store_addrs
+        (krb5_context, krb5_ccache, krb5_address **);
+static krb5_error_code krb5_fcc_store_addr
+        (krb5_context, krb5_ccache, krb5_address *);
+static krb5_error_code krb5_fcc_store_authdata
+        (krb5_context, krb5_ccache, krb5_authdata **);
+static krb5_error_code krb5_fcc_store_authdatum
+        (krb5_context, krb5_ccache, krb5_authdata *);
+
+static krb5_error_code krb5_fcc_interpret
+        (krb5_context, int);
+
+struct _krb5_fcc_data;
+static krb5_error_code krb5_fcc_close_file
+        (krb5_context, struct _krb5_fcc_data *data);
+static krb5_error_code krb5_fcc_open_file
+        (krb5_context, krb5_ccache, int);
+
+
+#define KRB5_OK 0
+
+#define KRB5_FCC_MAXLEN 100
+
+/*
+ * FCC version 2 contains type information for principals.  FCC
+ * version 1 does not.
+ *  
+ * FCC version 3 contains keyblock encryption type information, and is
+ * architecture independent.  Previous versions are not.
+ *
+ * The code will accept version 1, 2, and 3 ccaches, and depending 
+ * what KRB5_FCC_DEFAULT_FVNO is set to, it will create version 1, 2,
+ * or 3 FCC caches.
+ *
+ * The default credentials cache should be type 3 for now (see
+ * init_ctx.c).
+ */
+
+#define KRB5_FCC_FVNO_1 0x0501		/* krb v5, fcc v1 */
+#define KRB5_FCC_FVNO_2 0x0502		/* krb v5, fcc v2 */
+#define KRB5_FCC_FVNO_3 0x0503		/* krb v5, fcc v3 */
+#define KRB5_FCC_FVNO_4 0x0504		/* krb v5, fcc v4 */
+
+#define	FCC_OPEN_AND_ERASE	1
+#define	FCC_OPEN_RDWR		2
+#define	FCC_OPEN_RDONLY		3
+
+/* Credential file header tags.
+ * The header tags are constructed as:
+ *	krb5_ui_2	tag
+ *	krb5_ui_2	len
+ *	krb5_octet	data[len]
+ * This format allows for older versions of the fcc processing code to skip
+ * past unrecognized tag formats.
+ */
+#define FCC_TAG_DELTATIME	1
+
+#ifndef TKT_ROOT
+#ifdef MSDOS_FILESYSTEM
+#define TKT_ROOT "\\tkt"
+#else
+#define TKT_ROOT "/tmp/tkt"
+#endif
+#endif
+
+/* macros to make checking flags easier */
+#define OPENCLOSE(id) (((krb5_fcc_data *)id->data)->flags & KRB5_TC_OPENCLOSE)
+
+typedef struct _krb5_fcc_data {
+    char *filename;
+    /* Lock this one before reading or modifying the data stored here
+       that can be changed.  (Filename is fixed after
+       initialization.)  */
+    k5_mutex_t lock;
+    int file;
+    krb5_flags flags;
+    int mode;				/* needed for locking code */
+    int version;	      		/* version number of the file */
+
+    /* Buffer data on reading, for performance.
+       We used to have a stdio option, but we get more precise control
+       by using the POSIX I/O functions.  */
+#define FCC_BUFSIZ 1024
+    int valid_bytes;
+    int cur_offset;
+    char buf[FCC_BUFSIZ];
+} krb5_fcc_data;
+
+static inline void invalidate_cache(krb5_fcc_data *data)
+{
+    data->valid_bytes = 0;
+}
+
+static off_t fcc_lseek(krb5_fcc_data *data, off_t offset, int whence)
+{
+    /* If we read some extra data in advance, and then want to know or
+       use our "current" position, we need to back up a little.  */
+    if (whence == SEEK_CUR && data->valid_bytes) {
+	assert(data->valid_bytes > 0);
+	assert(data->cur_offset > 0);
+	assert(data->cur_offset <= data->valid_bytes);
+	offset -= (data->valid_bytes - data->cur_offset);
+    }
+    invalidate_cache(data);
+    return lseek(data->file, offset, whence);
+}
+
+struct fcc_set {
+    struct fcc_set *next;
+    krb5_fcc_data *data;
+    unsigned int refcount;
+};
+
+k5_mutex_t krb5int_cc_file_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+static struct fcc_set *fccs = NULL;
+
+/* An off_t can be arbitrarily complex */
+typedef struct _krb5_fcc_cursor {
+    off_t pos;
+} krb5_fcc_cursor;
+
+#define MAYBE_OPEN(CONTEXT, ID, MODE)					\
+{									\
+    k5_assert_locked(&((krb5_fcc_data *)(ID)->data)->lock);		\
+    if (OPENCLOSE (ID)) {						\
+	krb5_error_code maybe_open_ret;					\
+	maybe_open_ret = krb5_fcc_open_file (CONTEXT,ID,MODE);		\
+	if (maybe_open_ret) {						\
+	    k5_mutex_unlock(&((krb5_fcc_data *)(ID)->data)->lock);	\
+	    return maybe_open_ret;					\
+	}								\
+    }									\
+}
+
+#define MAYBE_CLOSE(CONTEXT, ID, RET)					\
+{									\
+    if (OPENCLOSE (ID)) {						\
+	krb5_error_code maybe_close_ret;				\
+        maybe_close_ret = krb5_fcc_close_file (CONTEXT,			\
+					       (krb5_fcc_data *)(ID)->data); \
+	if (!(RET)) RET = maybe_close_ret; } }
+
+#define MAYBE_CLOSE_IGNORE(CONTEXT, ID) \
+{                                                                       \
+    if (OPENCLOSE (ID)) {                                               \
+        (void) krb5_fcc_close_file (CONTEXT,(krb5_fcc_data *)(ID)->data); } }
+
+#define CHECK(ret) if (ret != KRB5_OK) goto errout;
+
+#define NO_FILE -1
+
+/*
+ * Effects:
+ * Reads len bytes from the cache id, storing them in buf.
+ *
+ * Requires:
+ * Must be called with mutex locked.
+ *
+ * Errors:
+ * KRB5_CC_END - there were not len bytes available
+ * system errors (read)
+ */
+static krb5_error_code
+krb5_fcc_read(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned int len)
+{
+#if 0
+     int ret;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     ret = read(((krb5_fcc_data *) id->data)->file, (char *) buf, len);
+     if (ret == -1)
+	  return krb5_fcc_interpret(context, errno);
+     if (ret != len)
+	  return KRB5_CC_END;
+     else
+	  return KRB5_OK;
+#else
+     krb5_fcc_data *data = (krb5_fcc_data *) id->data;
+
+     k5_assert_locked(&data->lock);
+
+     while (len > 0) {
+	 int nread, e;
+	 size_t ncopied;
+
+	 assert (data->valid_bytes >= 0);
+	 if (data->valid_bytes > 0)
+	     assert(data->cur_offset <= data->valid_bytes);
+	 if (data->valid_bytes == 0
+	     || data->cur_offset == data->valid_bytes) {
+	     /* Fill buffer from current file position.  */
+	     nread = read(data->file, data->buf, sizeof(data->buf));
+	     e = errno;
+	     if (nread < 0)
+		 return krb5_fcc_interpret(context, e);
+	     if (nread == 0)
+		 /* EOF */
+		 return KRB5_CC_END;
+	     data->valid_bytes = nread;
+	     data->cur_offset = 0;
+	 }
+	 assert(data->cur_offset < data->valid_bytes);
+	 ncopied = len;
+	 assert(ncopied == len);
+	 if (data->valid_bytes - data->cur_offset < ncopied)
+	     ncopied = data->valid_bytes - data->cur_offset;
+	 memcpy(buf, data->buf + data->cur_offset, ncopied);
+	 data->cur_offset += ncopied;
+	 assert(data->cur_offset > 0);
+	 assert(data->cur_offset <= data->valid_bytes);
+	 len -= ncopied;
+	 assert(len >= 0);
+	 /* Don't do arithmetic on void pointers.  */
+	 buf = (char*)buf + ncopied;
+     }
+     return 0;
+#endif
+}
+
+/*
+ * FOR ALL OF THE FOLLOWING FUNCTIONS:
+ *
+ * Requires:
+ * id is open and set to read at the appropriate place in the file
+ *
+ * mutex is locked
+ *
+ * Effects:
+ * Fills in the second argument with data of the appropriate type from
+ * the file.  In some cases, the functions have to allocate space for
+ * variable length fields; therefore, krb5_destroy_<type> must be
+ * called for each filled in structure.
+ *
+ * Errors:
+ * system errors (read errors)
+ * KRB5_CC_NOMEM
+ */
+
+#define ALLOC(NUM,TYPE) \
+    (((NUM) <= (((size_t)0-1)/ sizeof(TYPE)))		\
+     ? (TYPE *) calloc((NUM), sizeof(TYPE))		\
+     : (errno = ENOMEM,(TYPE *) 0))
+
+static krb5_error_code
+krb5_fcc_read_principal(krb5_context context, krb5_ccache id, krb5_principal *princ)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_error_code kret;
+    register krb5_principal tmpprinc;
+    krb5_int32 length, type;
+    int i;
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    *princ = NULL;
+
+    if (data->version == KRB5_FCC_FVNO_1) {
+	type = KRB5_NT_UNKNOWN;
+    } else {
+        /* Read principal type */
+        kret = krb5_fcc_read_int32(context, id, &type);
+        if (kret != KRB5_OK)
+	    return kret;
+    }
+
+    /* Read the number of components */
+    kret = krb5_fcc_read_int32(context, id, &length);
+    if (kret != KRB5_OK)
+	return kret;
+
+    /*
+     * DCE includes the principal's realm in the count; the new format
+     * does not.
+     */
+    if (data->version == KRB5_FCC_FVNO_1)
+	length--;
+    if (length < 0)
+	return KRB5_CC_NOMEM;
+
+    tmpprinc = (krb5_principal) malloc(sizeof(krb5_principal_data));
+    if (tmpprinc == NULL)
+	return KRB5_CC_NOMEM;
+    if (length) {
+	size_t msize = length;
+	if (msize != length) {
+	    free(tmpprinc);
+	    return KRB5_CC_NOMEM;
+	}
+	tmpprinc->data = ALLOC (msize, krb5_data);
+	if (tmpprinc->data == 0) {
+	    free((char *)tmpprinc);
+	    return KRB5_CC_NOMEM;
+	}
+    } else
+	tmpprinc->data = 0;
+    tmpprinc->magic = KV5M_PRINCIPAL;
+    tmpprinc->length = length;
+    tmpprinc->type = type;
+
+    kret = krb5_fcc_read_data(context, id, krb5_princ_realm(context, tmpprinc));
+
+    i = 0;
+    CHECK(kret);
+
+    for (i=0; i < length; i++) {
+	kret = krb5_fcc_read_data(context, id, krb5_princ_component(context, tmpprinc, i));
+	CHECK(kret);
+    }
+    *princ = tmpprinc;
+    return KRB5_OK;
+
+ errout:
+    while(--i >= 0)
+	free(krb5_princ_component(context, tmpprinc, i)->data);
+    free((char *)tmpprinc->data);
+    free((char *)tmpprinc);
+    return kret;
+}
+
+static krb5_error_code
+krb5_fcc_read_addrs(krb5_context context, krb5_ccache id, krb5_address ***addrs)
+{
+     krb5_error_code kret;
+     krb5_int32 length;
+     size_t msize;
+     int i;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     *addrs = 0;
+
+     /* Read the number of components */
+     kret = krb5_fcc_read_int32(context, id, &length);
+     CHECK(kret);
+
+     /* Make *addrs able to hold length pointers to krb5_address structs
+      * Add one extra for a null-terminated list
+      */
+     msize = length;
+     msize += 1;
+     if (msize == 0 || msize - 1 != length || length < 0)
+	 return KRB5_CC_NOMEM;
+     *addrs = ALLOC (msize, krb5_address *);
+     if (*addrs == NULL)
+	  return KRB5_CC_NOMEM;
+
+     for (i=0; i < length; i++) {
+	  (*addrs)[i] = (krb5_address *) malloc(sizeof(krb5_address));
+	  if ((*addrs)[i] == NULL) {
+	      krb5_free_addresses(context, *addrs);
+	      return KRB5_CC_NOMEM;
+	  }
+	  (*addrs)[i]->contents = NULL;
+	  kret = krb5_fcc_read_addr(context, id, (*addrs)[i]);
+	  CHECK(kret);
+     }
+
+     return KRB5_OK;
+ errout:
+     if (*addrs) {
+	 krb5_free_addresses(context, *addrs);
+	 *addrs = NULL;
+     }
+     return kret;
+}
+
+static krb5_error_code
+krb5_fcc_read_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *keyblock)
+{
+     krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+     krb5_error_code kret;
+     krb5_ui_2 ui2;
+     krb5_int32 int32;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     keyblock->magic = KV5M_KEYBLOCK;
+     keyblock->contents = 0;
+
+     kret = krb5_fcc_read_ui_2(context, id, &ui2);
+     keyblock->enctype = ui2;
+     CHECK(kret);
+     if (data->version == KRB5_FCC_FVNO_3) {
+	 /* This works because the old etype is the same as the new enctype. */
+	     kret = krb5_fcc_read_ui_2(context, id, &ui2);
+	     /* keyblock->enctype = ui2; */
+	     CHECK(kret);
+     }
+
+     kret = krb5_fcc_read_int32(context, id, &int32);
+     CHECK(kret);
+     if (int32 < 0)
+	  return KRB5_CC_NOMEM;
+     keyblock->length = int32;
+     /* Overflow check.  */
+     if (keyblock->length != int32)
+	 return KRB5_CC_NOMEM;
+     if ( keyblock->length == 0 )
+	 return KRB5_OK;
+     keyblock->contents = ALLOC (keyblock->length, krb5_octet);
+     if (keyblock->contents == NULL)
+	 return KRB5_CC_NOMEM;
+     
+     kret = krb5_fcc_read(context, id, keyblock->contents, keyblock->length);
+     if (kret)
+	 goto errout;
+
+     return KRB5_OK;
+ errout:
+     if (keyblock->contents) {
+	 krb5_xfree(keyblock->contents);
+	 keyblock->contents = NULL;
+     }
+     return kret;
+}
+
+static krb5_error_code
+krb5_fcc_read_data(krb5_context context, krb5_ccache id, krb5_data *data)
+{
+     krb5_error_code kret;
+     krb5_int32 len;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     data->magic = KV5M_DATA;
+     data->data = 0;
+
+     kret = krb5_fcc_read_int32(context, id, &len);
+     CHECK(kret);
+     if (len < 0)
+        return KRB5_CC_NOMEM;
+     data->length = len;
+     if (data->length != len || data->length + 1 == 0)
+	 return KRB5_CC_NOMEM;
+
+     if (data->length == 0) {
+	data->data = 0;
+	return KRB5_OK;
+     }
+
+     data->data = (char *) malloc(data->length+1);
+     if (data->data == NULL)
+	  return KRB5_CC_NOMEM;
+
+     kret = krb5_fcc_read(context, id, data->data, (unsigned) data->length);
+     CHECK(kret);
+     
+     data->data[data->length] = 0; /* Null terminate, just in case.... */
+     return KRB5_OK;
+ errout:
+     if (data->data) {
+	 krb5_xfree(data->data);
+	 data->data = NULL;
+     }
+     return kret;
+}
+
+static krb5_error_code
+krb5_fcc_read_addr(krb5_context context, krb5_ccache id, krb5_address *addr)
+{
+     krb5_error_code kret;
+     krb5_ui_2 ui2;
+     krb5_int32 int32;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     addr->magic = KV5M_ADDRESS;
+     addr->contents = 0;
+
+     kret = krb5_fcc_read_ui_2(context, id, &ui2);
+     CHECK(kret);
+     addr->addrtype = ui2;
+     
+     kret = krb5_fcc_read_int32(context, id, &int32);
+     CHECK(kret);
+     if ((int32 & VALID_INT_BITS) != int32)     /* Overflow int??? */
+	  return KRB5_CC_NOMEM;
+     addr->length = int32;
+     /* Length field is "unsigned int", which may be smaller than 32
+        bits.  */
+     if (addr->length != int32)
+	 return KRB5_CC_NOMEM;	/* XXX */
+
+     if (addr->length == 0)
+	     return KRB5_OK;
+
+     addr->contents = (krb5_octet *) malloc(addr->length);
+     if (addr->contents == NULL)
+	  return KRB5_CC_NOMEM;
+
+     kret = krb5_fcc_read(context, id, addr->contents, addr->length);
+     CHECK(kret);
+
+     return KRB5_OK;
+ errout:
+     if (addr->contents) {
+	 krb5_xfree(addr->contents);
+	 addr->contents = NULL;
+     }
+     return kret;
+}
+
+static krb5_error_code
+krb5_fcc_read_int32(krb5_context context, krb5_ccache id, krb5_int32 *i)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_error_code retval;
+    unsigned char buf[4];
+    krb5_int32 val;
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if ((data->version == KRB5_FCC_FVNO_1) ||
+	(data->version == KRB5_FCC_FVNO_2)) 
+	return krb5_fcc_read(context, id, (krb5_pointer) i, sizeof(krb5_int32));
+    else {
+	retval = krb5_fcc_read(context, id, buf, 4);
+	if (retval)
+	    return retval;
+        val = buf[0];
+        val = (val << 8) | buf[1];
+        val = (val << 8) | buf[2];
+        val = (val << 8) | buf[3];
+        *i = val;
+	return 0;
+    }
+}
+
+static krb5_error_code
+krb5_fcc_read_ui_2(krb5_context context, krb5_ccache id, krb5_ui_2 *i)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_error_code retval;
+    unsigned char buf[2];
+    
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if ((data->version == KRB5_FCC_FVNO_1) ||
+	(data->version == KRB5_FCC_FVNO_2))
+	return krb5_fcc_read(context, id, (krb5_pointer) i, sizeof(krb5_ui_2));
+    else {
+	retval = krb5_fcc_read(context, id, buf, 2);
+	if (retval)
+	    return retval;
+	*i = (buf[0] << 8) + buf[1];
+	return 0;
+    }
+}    
+
+static krb5_error_code
+krb5_fcc_read_octet(krb5_context context, krb5_ccache id, krb5_octet *i)
+{
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+    return krb5_fcc_read(context, id, (krb5_pointer) i, 1);
+}    
+
+
+static krb5_error_code
+krb5_fcc_read_times(krb5_context context, krb5_ccache id, krb5_ticket_times *t)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_error_code retval;
+    krb5_int32 i;
+    
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if ((data->version == KRB5_FCC_FVNO_1) ||
+	(data->version == KRB5_FCC_FVNO_2))
+	return krb5_fcc_read(context, id, (krb5_pointer) t, sizeof(krb5_ticket_times));
+    else {
+	retval = krb5_fcc_read_int32(context, id, &i);
+	CHECK(retval);
+	t->authtime = i;
+	
+	retval = krb5_fcc_read_int32(context, id, &i);
+	CHECK(retval);
+	t->starttime = i;
+
+	retval = krb5_fcc_read_int32(context, id, &i);
+	CHECK(retval);
+	t->endtime = i;
+
+	retval = krb5_fcc_read_int32(context, id, &i);
+	CHECK(retval);
+	t->renew_till = i;
+    }
+    return 0;
+errout:
+    return retval;
+}
+
+static krb5_error_code
+krb5_fcc_read_authdata(krb5_context context, krb5_ccache id, krb5_authdata ***a)
+{
+     krb5_error_code kret;
+     krb5_int32 length;
+     size_t msize;
+     int i;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     *a = 0;
+
+     /* Read the number of components */
+     kret = krb5_fcc_read_int32(context, id, &length);
+     CHECK(kret);
+
+     if (length == 0)
+	 return KRB5_OK;
+
+     /* Make *a able to hold length pointers to krb5_authdata structs
+      * Add one extra for a null-terminated list
+      */
+     msize = length;
+     msize += 1;
+     if (msize == 0 || msize - 1 != length || length < 0)
+	 return KRB5_CC_NOMEM;
+     *a = ALLOC (msize, krb5_authdata *);
+     if (*a == NULL)
+	  return KRB5_CC_NOMEM;
+
+     for (i=0; i < length; i++) {
+	  (*a)[i] = (krb5_authdata *) malloc(sizeof(krb5_authdata));
+	  if ((*a)[i] == NULL) {
+	      krb5_free_authdata(context, *a);
+	      return KRB5_CC_NOMEM;
+	  }
+	  (*a)[i]->contents = NULL;
+	  kret = krb5_fcc_read_authdatum(context, id, (*a)[i]);
+	  CHECK(kret);
+     }
+
+     return KRB5_OK;
+ errout:
+     if (*a) {
+	 krb5_free_authdata(context, *a);
+	 *a = NULL;
+     }
+     return kret;
+}
+
+static krb5_error_code
+krb5_fcc_read_authdatum(krb5_context context, krb5_ccache id, krb5_authdata *a)
+{
+    krb5_error_code kret;
+    krb5_int32 int32;
+    krb5_ui_2 ui2;
+    
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    a->magic = KV5M_AUTHDATA;
+    a->contents = NULL;
+
+    kret = krb5_fcc_read_ui_2(context, id, &ui2);
+    CHECK(kret);
+    a->ad_type = (krb5_authdatatype)ui2;
+    kret = krb5_fcc_read_int32(context, id, &int32);
+    CHECK(kret);
+    if ((int32 & VALID_INT_BITS) != int32)     /* Overflow int??? */
+          return KRB5_CC_NOMEM;
+    a->length = int32;
+    /* Value could have gotten truncated if int is smaller than 32
+       bits.  */
+    if (a->length != int32)
+	return KRB5_CC_NOMEM;	/* XXX */
+    
+    if (a->length == 0 )
+	    return KRB5_OK;
+
+    a->contents = (krb5_octet *) malloc(a->length);
+    if (a->contents == NULL)
+	return KRB5_CC_NOMEM;
+
+    kret = krb5_fcc_read(context, id, a->contents, a->length);
+    CHECK(kret);
+    
+     return KRB5_OK;
+ errout:
+     if (a->contents) {
+	 krb5_xfree(a->contents);
+	 a->contents = NULL;
+     }
+     return kret;
+    
+}
+#undef CHECK
+
+#define CHECK(ret) if (ret != KRB5_OK) return ret;
+
+/*
+ * Requires:
+ * id is open
+ *
+ * Effects:
+ * Writes len bytes from buf into the file cred cache id.
+ *
+ * Errors:
+ * system errors
+ */
+static krb5_error_code
+krb5_fcc_write(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned int len)
+{
+     int ret;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+     invalidate_cache((krb5_fcc_data *) id->data);
+
+     ret = write(((krb5_fcc_data *)id->data)->file, (char *) buf, len);
+     if (ret < 0)
+	  return krb5_fcc_interpret(context, errno);
+     if (ret != len)
+         return KRB5_CC_WRITE;
+     return KRB5_OK;
+}
+
+/*
+ * FOR ALL OF THE FOLLOWING FUNCTIONS:
+ * 
+ * Requires:
+ * ((krb5_fcc_data *) id->data)->file is open and at the right position.
+ *
+ * mutex is locked
+ * 
+ * Effects:
+ * Stores an encoded version of the second argument in the
+ * cache file.
+ *
+ * Errors:
+ * system errors
+ */
+
+static krb5_error_code
+krb5_fcc_store_principal(krb5_context context, krb5_ccache id, krb5_principal princ)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_error_code ret;
+    krb5_int32 i, length, tmp, type;
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    type = krb5_princ_type(context, princ);
+    tmp = length = krb5_princ_size(context, princ);
+
+    if (data->version == KRB5_FCC_FVNO_1) {
+	/*
+	 * DCE-compatible format means that the length count
+	 * includes the realm.  (It also doesn't include the
+	 * principal type information.)
+	 */
+	tmp++;
+    } else {
+	ret = krb5_fcc_store_int32(context, id, type);
+	CHECK(ret);
+    }
+    
+    ret = krb5_fcc_store_int32(context, id, tmp);
+    CHECK(ret);
+
+    ret = krb5_fcc_store_data(context, id, krb5_princ_realm(context, princ));
+    CHECK(ret);
+
+    for (i=0; i < length; i++) {
+	ret = krb5_fcc_store_data(context, id, krb5_princ_component(context, princ, i));
+	CHECK(ret);
+    }
+
+    return KRB5_OK;
+}
+
+static krb5_error_code
+krb5_fcc_store_addrs(krb5_context context, krb5_ccache id, krb5_address **addrs)
+{
+     krb5_error_code ret;
+     krb5_address **temp;
+     krb5_int32 i, length = 0;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     /* Count the number of components */
+     if (addrs) {
+	     temp = addrs;
+	     while (*temp++)
+		     length += 1;
+     }
+
+     ret = krb5_fcc_store_int32(context, id, length);
+     CHECK(ret);
+     for (i=0; i < length; i++) {
+	  ret = krb5_fcc_store_addr(context, id, addrs[i]);
+	  CHECK(ret);
+     }
+
+     return KRB5_OK;
+}
+
+static krb5_error_code
+krb5_fcc_store_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *keyblock)
+{
+     krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+     krb5_error_code ret;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     ret = krb5_fcc_store_ui_2(context, id, keyblock->enctype);
+     CHECK(ret);
+     if (data->version == KRB5_FCC_FVNO_3) {
+	 ret = krb5_fcc_store_ui_2(context, id, keyblock->enctype);
+	 CHECK(ret);
+     }
+     ret = krb5_fcc_store_ui_4(context, id, keyblock->length);
+     CHECK(ret);
+     return krb5_fcc_write(context, id, (char *) keyblock->contents, keyblock->length);
+}
+
+static krb5_error_code
+krb5_fcc_store_addr(krb5_context context, krb5_ccache id, krb5_address *addr)
+{
+     krb5_error_code ret;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     ret = krb5_fcc_store_ui_2(context, id, addr->addrtype);
+     CHECK(ret);
+     ret = krb5_fcc_store_ui_4(context, id, addr->length);
+     CHECK(ret);
+     return krb5_fcc_write(context, id, (char *) addr->contents, addr->length);
+}
+
+
+static krb5_error_code
+krb5_fcc_store_data(krb5_context context, krb5_ccache id, krb5_data *data)
+{
+     krb5_error_code ret;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     ret = krb5_fcc_store_ui_4(context, id, data->length);
+     CHECK(ret);
+     return krb5_fcc_write(context, id, data->data, data->length);
+}
+
+static krb5_error_code
+krb5_fcc_store_int32(krb5_context context, krb5_ccache id, krb5_int32 i)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    unsigned char buf[4];
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if ((data->version == KRB5_FCC_FVNO_1) ||
+	(data->version == KRB5_FCC_FVNO_2)) 
+	return krb5_fcc_write(context, id, (char *) &i, sizeof(krb5_int32));
+    else {
+        buf[3] = (unsigned char) (i & 0xFF);
+	i >>= 8;
+        buf[2] = (unsigned char) (i & 0xFF);
+	i >>= 8;
+        buf[1] = (unsigned char) (i & 0xFF);
+	i >>= 8;
+        buf[0] = (unsigned char) (i & 0xFF);
+	return krb5_fcc_write(context, id, buf, 4);
+    }
+}
+
+static krb5_error_code
+krb5_fcc_store_ui_4(krb5_context context, krb5_ccache id, krb5_ui_4 i)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    unsigned char buf[4];
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if ((data->version == KRB5_FCC_FVNO_1) ||
+	(data->version == KRB5_FCC_FVNO_2)) 
+	return krb5_fcc_write(context, id, (char *) &i, sizeof(krb5_int32));
+    else {
+        buf[3] = (unsigned char) (i & 0xFF);
+	i >>= 8;
+        buf[2] = (unsigned char) (i & 0xFF);
+	i >>= 8;
+        buf[1] = (unsigned char) (i & 0xFF);
+	i >>= 8;
+        buf[0] = (unsigned char) (i & 0xFF);
+	return krb5_fcc_write(context, id, buf, 4);
+    }
+}
+
+static krb5_error_code
+krb5_fcc_store_ui_2(krb5_context context, krb5_ccache id, krb5_int32 i)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_ui_2 ibuf;
+    unsigned char buf[2];
+    
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if ((data->version == KRB5_FCC_FVNO_1) ||
+	(data->version == KRB5_FCC_FVNO_2)) {
+        ibuf = (krb5_ui_2) i;
+	return krb5_fcc_write(context, id, (char *) &ibuf, sizeof(krb5_ui_2));
+    } else {
+        buf[1] = (unsigned char) (i & 0xFF);
+	i >>= 8;
+        buf[0] = (unsigned char) (i & 0xFF);
+	return krb5_fcc_write(context, id, buf, 2);
+    }
+}
+   
+static krb5_error_code
+krb5_fcc_store_octet(krb5_context context, krb5_ccache id, krb5_int32 i)
+{
+    krb5_octet ibuf;
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    ibuf = (krb5_octet) i;
+    return krb5_fcc_write(context, id, (char *) &ibuf, 1);
+}
+   
+static krb5_error_code
+krb5_fcc_store_times(krb5_context context, krb5_ccache id, krb5_ticket_times *t)
+{
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_error_code retval;
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if ((data->version == KRB5_FCC_FVNO_1) ||
+	(data->version == KRB5_FCC_FVNO_2))
+	return krb5_fcc_write(context, id, (char *) t, sizeof(krb5_ticket_times));
+    else {
+	retval = krb5_fcc_store_int32(context, id, t->authtime);
+	CHECK(retval);
+	retval = krb5_fcc_store_int32(context, id, t->starttime);
+	CHECK(retval);
+	retval = krb5_fcc_store_int32(context, id, t->endtime);
+	CHECK(retval);
+	retval = krb5_fcc_store_int32(context, id, t->renew_till);
+	CHECK(retval);
+	return 0;
+    }
+}
+   
+static krb5_error_code
+krb5_fcc_store_authdata(krb5_context context, krb5_ccache id, krb5_authdata **a)
+{
+    krb5_error_code ret;
+    krb5_authdata **temp;
+    krb5_int32 i, length=0;
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    if (a != NULL) {
+	for (temp=a; *temp; temp++)
+	    length++;
+    }
+
+    ret = krb5_fcc_store_int32(context, id, length);
+    CHECK(ret);
+    for (i=0; i<length; i++) {
+	ret = krb5_fcc_store_authdatum (context, id, a[i]);
+	CHECK(ret);
+    }
+    return KRB5_OK;
+}
+
+static krb5_error_code
+krb5_fcc_store_authdatum (krb5_context context, krb5_ccache id, krb5_authdata *a)
+{
+    krb5_error_code ret;
+
+    k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+    ret = krb5_fcc_store_ui_2(context, id, a->ad_type);
+    CHECK(ret);
+    ret = krb5_fcc_store_ui_4(context, id, a->length);
+    CHECK(ret);
+    return krb5_fcc_write(context, id, (krb5_pointer) a->contents, a->length);
+}
+#undef CHECK
+
+static krb5_error_code
+krb5_fcc_close_file (krb5_context context, krb5_fcc_data *data)
+{
+     int ret;
+     krb5_error_code retval;
+
+     k5_assert_locked(&data->lock);
+
+     if (data->file == NO_FILE)
+	 return KRB5_FCC_INTERNAL;
+
+     retval = krb5_unlock_file(context, data->file);
+     ret = close (data->file);
+     data->file = NO_FILE;
+     if (retval)
+	 return retval;
+
+     return ret ? krb5_fcc_interpret (context, errno) : 0;
+}
+
+#if defined(ANSI_STDIO) || defined(_WIN32)
+#define BINARY_MODE "b"
+#else
+#define BINARY_MODE ""
+#endif
+
+#ifndef HAVE_SETVBUF
+#undef setvbuf
+#define setvbuf(FILE,BUF,MODE,SIZE) \
+  ((SIZE) < BUFSIZE ? (abort(),0) : setbuf(FILE, BUF))
+#endif
+
+static krb5_error_code
+krb5_fcc_open_file (krb5_context context, krb5_ccache id, int mode)
+{
+    krb5_os_context os_ctx = (krb5_os_context)context->os_context;
+    krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+    krb5_ui_2 fcc_fvno;
+    krb5_ui_2 fcc_flen;
+    krb5_ui_2 fcc_tag;
+    krb5_ui_2 fcc_taglen;
+    int f, open_flag;
+    int lock_flag;
+    krb5_error_code retval = 0;
+
+    k5_assert_locked(&data->lock);
+    invalidate_cache(data);
+
+    if (data->file != NO_FILE) {
+	/* Don't know what state it's in; shut down and start anew.  */
+	(void) krb5_unlock_file(context, data->file);
+	(void) close (data->file);
+	data->file = NO_FILE;
+    }
+
+    switch(mode) {
+    case FCC_OPEN_AND_ERASE:
+	unlink(data->filename);
+	open_flag = O_CREAT|O_EXCL|O_TRUNC|O_RDWR;
+	break;
+    case FCC_OPEN_RDWR:
+	open_flag = O_RDWR;
+	break;
+    case FCC_OPEN_RDONLY:
+    default:
+	open_flag = O_RDONLY;
+	break;
+    }
+
+    f = THREEPARAMOPEN (data->filename, open_flag | O_BINARY, 0600);
+    if (f == NO_FILE)
+	return krb5_fcc_interpret (context, errno);
+
+    data->mode = mode;
+
+    if (data->mode == FCC_OPEN_RDONLY)
+	lock_flag = KRB5_LOCKMODE_SHARED;
+    else 
+	lock_flag = KRB5_LOCKMODE_EXCLUSIVE;
+    if ((retval = krb5_lock_file(context, f, lock_flag))) {
+	(void) close(f);
+	return retval;
+    }
+
+    if (mode == FCC_OPEN_AND_ERASE) {
+	 /* write the version number */
+         int cnt;
+
+         fcc_fvno = htons(context->fcc_default_format);
+         data->version = context->fcc_default_format;
+         if ((cnt = write(f, (char *)&fcc_fvno, sizeof(fcc_fvno))) !=
+             sizeof(fcc_fvno)) {
+             retval = ((cnt == -1) ? krb5_fcc_interpret(context, errno) :
+                       KRB5_CC_IO);
+             goto done;
+         }
+         data->file = f;
+
+	 if (data->version == KRB5_FCC_FVNO_4) {
+             /* V4 of the credentials cache format allows for header tags */
+	     fcc_flen = 0;
+
+	     if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)
+		 fcc_flen += (2*sizeof(krb5_ui_2) + 2*sizeof(krb5_int32));
+
+	     /* Write header length */
+	     retval = krb5_fcc_store_ui_2(context, id, (krb5_int32)fcc_flen);
+	     if (retval) goto done;
+
+	     if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) {
+		 /* Write time offset tag */
+		 fcc_tag = FCC_TAG_DELTATIME;
+		 fcc_taglen = 2*sizeof(krb5_int32);
+		 
+		 retval = krb5_fcc_store_ui_2(context,id,(krb5_int32)fcc_tag);
+		 if (retval) goto done;
+		 retval = krb5_fcc_store_ui_2(context,id,(krb5_int32)fcc_taglen);
+		 if (retval) goto done;
+		 retval = krb5_fcc_store_int32(context,id,os_ctx->time_offset);
+		 if (retval) goto done;
+		 retval = krb5_fcc_store_int32(context,id,os_ctx->usec_offset);
+		 if (retval) goto done;
+	     }
+	 }
+	 invalidate_cache(data);
+	 goto done;
+     }
+
+     /* verify a valid version number is there */
+    invalidate_cache(data);
+     if (read(f, (char *)&fcc_fvno, sizeof(fcc_fvno)) != sizeof(fcc_fvno)) {
+	 retval = KRB5_CC_FORMAT;
+	 goto done;
+     }
+     data->version = ntohs(fcc_fvno);
+    if ((data->version != KRB5_FCC_FVNO_4) &&
+	(data->version != KRB5_FCC_FVNO_3) &&
+	(data->version != KRB5_FCC_FVNO_2) &&
+	(data->version != KRB5_FCC_FVNO_1)) {
+	retval = KRB5_CCACHE_BADVNO;
+	goto done;
+    }
+
+    data->file = f;
+
+     if (data->version == KRB5_FCC_FVNO_4) {
+	 char buf[1024];
+
+	 if (krb5_fcc_read_ui_2(context, id, &fcc_flen) ||
+	     (fcc_flen > sizeof(buf)))
+	 {
+	     retval = KRB5_CC_FORMAT;
+	     goto done;
+	 }
+
+	 while (fcc_flen) {
+	     if ((fcc_flen < (2 * sizeof(krb5_ui_2))) ||
+		 krb5_fcc_read_ui_2(context, id, &fcc_tag) ||
+		 krb5_fcc_read_ui_2(context, id, &fcc_taglen) ||
+		 (fcc_taglen > (fcc_flen - 2*sizeof(krb5_ui_2))))
+	     {
+		 retval = KRB5_CC_FORMAT;
+		 goto done;
+	     }
+
+	     switch (fcc_tag) {
+	     case FCC_TAG_DELTATIME:
+		 if (fcc_taglen != 2*sizeof(krb5_int32)) {
+		     retval = KRB5_CC_FORMAT;
+		     goto done;
+		 }
+		 if (!(context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) ||
+		     (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID))
+		 {
+		     if (krb5_fcc_read(context, id, buf, fcc_taglen)) {
+			 retval = KRB5_CC_FORMAT;
+			 goto done;
+		     }
+		     break;
+		 }
+		 if (krb5_fcc_read_int32(context, id, &os_ctx->time_offset) ||
+		     krb5_fcc_read_int32(context, id, &os_ctx->usec_offset))
+		 {
+		     retval = KRB5_CC_FORMAT;
+		     goto done;
+		 }
+		 os_ctx->os_flags =
+		     ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
+		      KRB5_OS_TOFFSET_VALID);
+		 break;
+	     default:
+		 if (fcc_taglen && krb5_fcc_read(context,id,buf,fcc_taglen)) {
+		     retval = KRB5_CC_FORMAT;
+		     goto done;
+		 }
+		 break;
+	     }
+	     fcc_flen -= (2*sizeof(krb5_ui_2) + fcc_taglen);
+	 }
+     }
+
+done:
+     if (retval) {
+         data->file = -1;
+         (void) krb5_unlock_file(context, f);
+         (void) close(f);
+     }
+     return retval;
+}
+
+static krb5_error_code
+krb5_fcc_skip_header(krb5_context context, krb5_ccache id)
+{
+     krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+     krb5_error_code kret;
+     krb5_ui_2 fcc_flen;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     fcc_lseek(data, (off_t) sizeof(krb5_ui_2), SEEK_SET);
+     if (data->version == KRB5_FCC_FVNO_4) {
+	 kret = krb5_fcc_read_ui_2(context, id, &fcc_flen);
+	 if (kret) return kret;
+         if(fcc_lseek(data, (off_t) fcc_flen, SEEK_CUR) < 0)
+		return errno;
+     }
+     return KRB5_OK;
+}
+
+static krb5_error_code
+krb5_fcc_skip_principal(krb5_context context, krb5_ccache id)
+{
+     krb5_error_code kret;
+     krb5_principal princ;
+
+     k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
+     kret = krb5_fcc_read_principal(context, id, &princ);
+     if (kret != KRB5_OK)
+	  return kret;
+
+     krb5_free_principal(context, princ);
+     return KRB5_OK;
+}
+
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Creates/refreshes the file cred cache id.  If the cache exists, its
+ * contents are destroyed.
+ *
+ * Errors:
+ * system errors
+ * permission errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
+{
+     krb5_error_code kret = 0;
+     int reti = 0;
+
+     kret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+     if (kret)
+	 return kret;
+
+     MAYBE_OPEN(context, id, FCC_OPEN_AND_ERASE);
+
+#if defined(HAVE_FCHMOD) || defined(HAVE_CHMOD)
+     {
+#ifdef HAVE_FCHMOD
+         reti = fchmod(((krb5_fcc_data *) id->data)->file, S_IREAD | S_IWRITE);
+#else
+         reti = chmod(((krb5_fcc_data *) id->data)->filename, S_IREAD | S_IWRITE);
+#endif
+         if (reti == -1) {
+             kret = krb5_fcc_interpret(context, errno);
+             MAYBE_CLOSE(context, id, kret);
+	     k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+             return kret;
+         }
+     }
+#endif
+     kret = krb5_fcc_store_principal(context, id, princ);
+
+     MAYBE_CLOSE(context, id, kret);
+     k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+     krb5_change_cache ();
+     return kret;
+}
+
+/*
+ * Drop the ref count; if it hits zero, remove the entry from the
+ * fcc_set list and free it.
+ */
+static krb5_error_code dereference(krb5_context context, krb5_fcc_data *data)
+{
+    krb5_error_code kerr;
+    struct fcc_set **fccsp;
+
+    kerr = k5_mutex_lock(&krb5int_cc_file_mutex);
+    if (kerr)
+	return kerr;
+    for (fccsp = &fccs; *fccsp != NULL; fccsp = &(*fccsp)->next)
+	if ((*fccsp)->data == data)
+	    break;
+    assert(*fccsp != NULL);
+    assert((*fccsp)->data == data);
+    (*fccsp)->refcount--;
+    if ((*fccsp)->refcount == 0) {
+        struct fcc_set *temp;
+	data = (*fccsp)->data;
+	temp = *fccsp;
+	*fccsp = (*fccsp)->next;
+	free(temp);
+	k5_mutex_unlock(&krb5int_cc_file_mutex);
+	k5_mutex_assert_unlocked(&data->lock);
+	free(data->filename);
+	zap(data->buf, sizeof(data->buf));
+	if (data->file >= 0) {
+	    k5_mutex_lock(&data->lock);
+	    krb5_fcc_close_file(context, data);
+	    k5_mutex_unlock(&data->lock);
+	}
+	k5_mutex_destroy(&data->lock);
+	free(data);
+    } else
+	k5_mutex_unlock(&krb5int_cc_file_mutex);
+    return 0;
+}
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Closes the file cache, invalidates the id, and frees any resources
+ * associated with the cache.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_close(krb5_context context, krb5_ccache id)
+{
+     dereference(context, (krb5_fcc_data *) id->data);
+     krb5_xfree(id);
+     return KRB5_OK;
+}
+
+/*
+ * Effects:
+ * Destroys the contents of id.
+ *
+ * Errors:
+ * system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_destroy(krb5_context context, krb5_ccache id)
+{
+     krb5_error_code kret = 0;
+     krb5_fcc_data *data = (krb5_fcc_data *) id->data;
+     register int ret;
+
+     struct stat buf;
+     unsigned long i, size;
+     unsigned int wlen;
+     char zeros[BUFSIZ];
+
+     kret = k5_mutex_lock(&data->lock);
+     if (kret)
+	 return kret;
+
+     if (OPENCLOSE(id)) {
+	 invalidate_cache(data);
+	  ret = THREEPARAMOPEN(data->filename,
+			       O_RDWR | O_BINARY, 0);
+	  if (ret < 0) {
+	      kret = krb5_fcc_interpret(context, errno);
+	      goto cleanup;
+	  }
+	  data->file = ret;
+     }
+     else
+	  fcc_lseek(data, (off_t) 0, SEEK_SET);
+
+#ifdef MSDOS_FILESYSTEM
+/* "disgusting bit of UNIX trivia" - that's how the writers of NFS describe
+** the ability of UNIX to still write to a file which has been unlinked.
+** Naturally, the PC can't do this. As a result, we have to delete the file
+** after we wipe it clean but that throws off all the error handling code.
+** So we have do the work ourselves.
+*/
+    ret = fstat(data->file, &buf);
+    if (ret == -1) {
+        kret = krb5_fcc_interpret(context, errno);
+        size = 0;                               /* Nothing to wipe clean */
+    } else
+        size = (unsigned long) buf.st_size;
+
+    memset(zeros, 0, BUFSIZ);
+    while (size > 0) {
+        wlen = (int) ((size > BUFSIZ) ? BUFSIZ : size); /* How much to write */
+        i = write(data->file, zeros, wlen);
+        if (i < 0) {
+            kret = krb5_fcc_interpret(context, errno);
+            /* Don't jump to cleanup--we still want to delete the file. */
+            break;
+        }
+        size -= i;                              /* We've read this much */
+    }
+
+    if (OPENCLOSE(id)) {
+        (void) close(((krb5_fcc_data *)id->data)->file);
+        data->file = -1;
+    }
+
+    ret = unlink(data->filename);
+    if (ret < 0) {
+        kret = krb5_fcc_interpret(context, errno);
+        goto cleanup;
+    }
+
+#else /* MSDOS_FILESYSTEM */
+
+     ret = unlink(data->filename);
+     if (ret < 0) {
+	 kret = krb5_fcc_interpret(context, errno);
+	 if (OPENCLOSE(id)) {
+	     (void) close(((krb5_fcc_data *)id->data)->file);
+	     data->file = -1;
+             kret = ret;
+	 }
+	 goto cleanup;
+     }
+     
+     ret = fstat(data->file, &buf);
+     if (ret < 0) {
+	 kret = krb5_fcc_interpret(context, errno);
+	 if (OPENCLOSE(id)) {
+	     (void) close(((krb5_fcc_data *)id->data)->file);
+	     data->file = -1;
+	 }
+	 goto cleanup;
+     }
+
+     /* XXX This may not be legal XXX */
+     size = (unsigned long) buf.st_size;
+     memset(zeros, 0, BUFSIZ);
+     for (i=0; i < size / BUFSIZ; i++)
+	  if (write(data->file, zeros, BUFSIZ) < 0) {
+	      kret = krb5_fcc_interpret(context, errno);
+	      if (OPENCLOSE(id)) {
+		  (void) close(((krb5_fcc_data *)id->data)->file);
+		  data->file = -1;
+	      }
+	      goto cleanup;
+	  }
+
+     wlen = (unsigned int) (size % BUFSIZ);
+     if (write(data->file, zeros, wlen) < 0) {
+	 kret = krb5_fcc_interpret(context, errno);
+	 if (OPENCLOSE(id)) {
+	     (void) close(((krb5_fcc_data *)id->data)->file);
+	     data->file = -1;
+	 }
+	 goto cleanup;
+     }
+
+     ret = close(data->file);
+     data->file = -1;
+
+     if (ret)
+	 kret = krb5_fcc_interpret(context, errno);
+
+#endif /* MSDOS_FILESYSTEM */
+
+  cleanup:
+     k5_mutex_unlock(&data->lock);
+     dereference(context, data);
+     krb5_xfree(id);
+
+     krb5_change_cache ();
+     return kret;
+}
+
+extern const krb5_cc_ops krb5_fcc_ops;
+
+/*
+ * Requires:
+ * residual is a legal path name, and a null-terminated string
+ *
+ * Modifies:
+ * id
+ * 
+ * Effects:
+ * creates a file-based cred cache that will reside in the file
+ * residual.  The cache is not opened, but the filename is reserved.
+ * 
+ * Returns:
+ * A filled in krb5_ccache structure "id".
+ *
+ * Errors:
+ * KRB5_CC_NOMEM - there was insufficient memory to allocate the
+ * 		krb5_ccache.  id is undefined.
+ * permission errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
+{
+     krb5_ccache lid;
+     krb5_error_code kret;
+     krb5_fcc_data *data;
+     struct fcc_set *setptr;
+
+     kret = k5_mutex_lock(&krb5int_cc_file_mutex);
+     if (kret)
+	 return kret;
+     for (setptr = fccs; setptr; setptr = setptr->next) {
+	 if (!strcmp(setptr->data->filename, residual))
+	     break;
+     }
+     if (setptr) {
+	 data = setptr->data;
+	 assert(setptr->refcount != 0);
+	 setptr->refcount++;
+	 assert(setptr->refcount != 0);
+	 kret = k5_mutex_lock(&data->lock);
+	 if (kret) {
+	     k5_mutex_unlock(&krb5int_cc_file_mutex);
+	     return kret;
+	 }
+	 k5_mutex_unlock(&krb5int_cc_file_mutex);
+     } else {
+	 data = malloc(sizeof(krb5_fcc_data));
+	 if (data == NULL) {
+	     k5_mutex_unlock(&krb5int_cc_file_mutex);
+	     return KRB5_CC_NOMEM;
+	 }
+	 data->filename = strdup(residual);
+	 if (data->filename == NULL) {
+	     k5_mutex_unlock(&krb5int_cc_file_mutex);
+	     free(data);
+	     return KRB5_CC_NOMEM;
+	 }
+	 kret = k5_mutex_init(&data->lock);
+	 if (kret) {
+	     k5_mutex_unlock(&krb5int_cc_file_mutex);
+	     free(data->filename);
+	     free(data);
+	     return kret;
+	 }
+	 kret = k5_mutex_lock(&data->lock);
+	 if (kret) {
+	     k5_mutex_unlock(&krb5int_cc_file_mutex);
+	     k5_mutex_destroy(&data->lock);
+	     free(data->filename);
+	     free(data);
+	     return kret;
+	 }
+	 /* data->version,mode filled in for real later */
+	 data->version = data->mode = 0;
+	 data->flags = KRB5_TC_OPENCLOSE;
+	 data->file = -1;
+	 data->valid_bytes = 0;
+	 setptr = malloc(sizeof(struct fcc_set));
+	 if (setptr == NULL) {
+	     k5_mutex_unlock(&krb5int_cc_file_mutex);
+	     k5_mutex_destroy(&data->lock);
+	     free(data->filename);
+	     free(data);
+	     return KRB5_CC_NOMEM;
+	 }
+	 setptr->refcount = 1;
+	 setptr->data = data;
+	 setptr->next = fccs;
+	 fccs = setptr;
+	 k5_mutex_unlock(&krb5int_cc_file_mutex);
+     }
+
+     k5_mutex_assert_locked(&data->lock);
+     k5_mutex_unlock(&data->lock);
+     lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+     if (lid == NULL) {
+	 dereference(context, data);
+	 return KRB5_CC_NOMEM;
+     }
+
+     lid->ops = &krb5_fcc_ops;
+     lid->data = data;
+     lid->magic = KV5M_CCACHE;
+
+     /* other routines will get errors on open, and callers must expect them,
+	if cache is non-existent/unusable */
+     *id = lid;
+     return KRB5_OK;
+}
+
+/*
+ * Effects:
+ * Prepares for a sequential search of the credentials cache.
+ * Returns and krb5_cc_cursor to be used with krb5_fcc_next_cred and
+ * krb5_fcc_end_seq_get.
+ *
+ * If the cache is modified between the time of this call and the time
+ * of the final krb5_fcc_end_seq_get, the results are undefined.
+ *
+ * Errors:
+ * KRB5_CC_NOMEM
+ * system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_start_seq_get(krb5_context context, krb5_ccache id,
+		       krb5_cc_cursor *cursor)
+{
+     krb5_fcc_cursor *fcursor;
+     krb5_error_code kret = KRB5_OK;
+     krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+
+     kret = k5_mutex_lock(&data->lock);
+     if (kret)
+	 return kret;
+
+     fcursor = (krb5_fcc_cursor *) malloc(sizeof(krb5_fcc_cursor));
+     if (fcursor == NULL) {
+	 k5_mutex_unlock(&data->lock);
+	 return KRB5_CC_NOMEM;
+     }
+     if (OPENCLOSE(id)) {
+          kret = krb5_fcc_open_file(context, id, FCC_OPEN_RDONLY);
+          if (kret) {
+              krb5_xfree(fcursor);
+	      k5_mutex_unlock(&data->lock);
+              return kret;
+          }
+     }
+
+     /* Make sure we start reading right after the primary principal */
+     kret = krb5_fcc_skip_header(context, id);
+     if (kret) goto done;
+     kret = krb5_fcc_skip_principal(context, id);
+     if (kret) goto done;
+
+     fcursor->pos = fcc_lseek(data, (off_t) 0, SEEK_CUR);
+     *cursor = (krb5_cc_cursor) fcursor;
+
+done:
+     MAYBE_CLOSE(context, id, kret);
+     k5_mutex_unlock(&data->lock);
+     return kret;
+}
+
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_fcc_start_seq_get.
+ *
+ * Modifes:
+ * cursor, creds
+ * 
+ * Effects:
+ * Fills in creds with the "next" credentals structure from the cache
+ * id.  The actual order the creds are returned in is arbitrary.
+ * Space is allocated for the variable length fields in the
+ * credentials structure, so the object returned must be passed to
+ * krb5_destroy_credential.
+ *
+ * The cursor is updated for the next call to krb5_fcc_next_cred.
+ *
+ * Errors:
+ * system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
+		   krb5_creds *creds)
+{
+#define TCHECK(ret) if (ret != KRB5_OK) goto lose;
+     krb5_error_code kret;
+     krb5_fcc_cursor *fcursor;
+     krb5_int32 int32;
+     krb5_octet octet;
+     krb5_fcc_data *d = (krb5_fcc_data *) id->data;
+
+     kret = k5_mutex_lock(&d->lock);
+     if (kret)
+	 return kret;
+
+     memset((char *)creds, 0, sizeof(*creds));
+     MAYBE_OPEN(context, id, FCC_OPEN_RDONLY);
+     fcursor = (krb5_fcc_cursor *) *cursor;
+
+     kret = (fcc_lseek(d, fcursor->pos, SEEK_SET) == (off_t) -1);
+     if (kret) {
+	 kret = krb5_fcc_interpret(context, errno);
+	 MAYBE_CLOSE(context, id, kret);
+	 k5_mutex_unlock(&d->lock);
+	 return kret;
+     }
+
+     kret = krb5_fcc_read_principal(context, id, &creds->client);
+     TCHECK(kret);
+     kret = krb5_fcc_read_principal(context, id, &creds->server);
+     TCHECK(kret);
+     kret = krb5_fcc_read_keyblock(context, id, &creds->keyblock);
+     TCHECK(kret);
+     kret = krb5_fcc_read_times(context, id, &creds->times);
+     TCHECK(kret);
+     kret = krb5_fcc_read_octet(context, id, &octet);
+     TCHECK(kret);
+     creds->is_skey = octet;
+     kret = krb5_fcc_read_int32(context, id, &int32);
+     TCHECK(kret);
+     creds->ticket_flags = int32;
+     kret = krb5_fcc_read_addrs(context, id, &creds->addresses);
+     TCHECK(kret);
+     kret = krb5_fcc_read_authdata(context, id, &creds->authdata);
+     TCHECK(kret);
+     kret = krb5_fcc_read_data(context, id, &creds->ticket);
+     TCHECK(kret);
+     kret = krb5_fcc_read_data(context, id, &creds->second_ticket);
+     TCHECK(kret);
+     
+     fcursor->pos = fcc_lseek(d, (off_t) 0, SEEK_CUR);
+     cursor = (krb5_cc_cursor *) fcursor;
+
+lose:
+     MAYBE_CLOSE (context, id, kret);
+     k5_mutex_unlock(&d->lock);
+     if (kret != KRB5_OK)
+	 krb5_free_cred_contents(context, creds);
+     return kret;
+}
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_fcc_start_seq_get.
+ *
+ * Modifies:
+ * id, cursor
+ *
+ * Effects:
+ * Finishes sequential processing of the file credentials ccache id,
+ * and invalidates the cursor (it must never be used after this call).
+ */
+/* ARGSUSED */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
+{
+     /* We don't do anything with the file cache itself, so
+	no need to lock anything.  */
+
+     /* don't close; it may be left open by the caller,
+        and if not, fcc_start_seq_get and/or fcc_next_cred will do the
+        MAYBE_CLOSE.
+     MAYBE_CLOSE(context, id, kret); */
+     krb5_xfree((krb5_fcc_cursor *) *cursor);
+     return 0;
+}
+
+
+/*
+ * Effects:
+ * Creates a new file cred cache whose name is guaranteed to be
+ * unique.  The name begins with the string TKT_ROOT (from fcc.h).
+ * The cache is not opened, but the new filename is reserved.
+ *  
+ * Returns:
+ * The filled in krb5_ccache id.
+ *
+ * Errors:
+ * KRB5_CC_NOMEM - there was insufficient memory to allocate the
+ * 		krb5_ccache.  id is undefined.
+ * system errors (from open)
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
+{
+     krb5_ccache lid;
+     int ret;
+     krb5_error_code    kret = 0;
+     char scratch[sizeof(TKT_ROOT)+6+1]; /* +6 for the scratch part, +1 for
+					    NUL */
+     krb5_fcc_data *data;
+     krb5_int16 fcc_fvno = htons(context->fcc_default_format);
+     krb5_int16 fcc_flen = 0;
+     int errsave, cnt;
+     struct fcc_set *setptr;
+     
+     /* Set master lock */
+     kret = k5_mutex_lock(&krb5int_cc_file_mutex);
+     if (kret)
+	 return kret;
+
+     (void) strcpy(scratch, TKT_ROOT);
+     (void) strcat(scratch, "XXXXXX");
+#ifdef HAVE_MKSTEMP
+     ret = mkstemp(scratch);
+     if (ret == -1) {
+         k5_mutex_unlock(&krb5int_cc_file_mutex);
+	 return krb5_fcc_interpret(context, errno);
+     }
+#else /*HAVE_MKSTEMP*/
+     mktemp(scratch);
+     /* Make sure the file name is reserved */
+     ret = THREEPARAMOPEN(scratch, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, 0);
+     if (ret == -1) {
+	  return krb5_fcc_interpret(context, errno);
+     }
+#endif
+
+     /* Allocate memory */
+     data = (krb5_pointer) malloc(sizeof(krb5_fcc_data));
+     if (data == NULL) {
+	  close(ret);
+	  unlink(scratch);
+	  k5_mutex_unlock(&krb5int_cc_file_mutex);
+	  return KRB5_CC_NOMEM;
+     }
+
+     data->filename = strdup(scratch);
+     if (data->filename == NULL) {
+          k5_mutex_unlock(&krb5int_cc_file_mutex);
+	  free(data);
+	  close(ret);
+	  unlink(scratch);
+	  k5_mutex_unlock(&krb5int_cc_file_mutex);
+	  return KRB5_CC_NOMEM;
+     }
+
+     kret = k5_mutex_init(&data->lock);
+     if (kret) {
+       k5_mutex_unlock(&krb5int_cc_file_mutex);
+       free(data->filename);
+       free(data);
+       close(ret);
+       unlink(scratch);
+       return kret;
+     }
+     kret = k5_mutex_lock(&data->lock);
+     if (kret) {
+       k5_mutex_unlock(&krb5int_cc_file_mutex);
+       k5_mutex_destroy(&data->lock);
+       free(data->filename);
+       free(data);
+       close(ret);
+       unlink(scratch);
+       return kret;
+     }
+
+     /*
+      * The file is initially closed at the end of this call...
+      */
+     data->flags = 0;
+     data->file = -1;
+     data->valid_bytes = 0;
+     /* data->version,mode filled in for real later */
+     data->version = data->mode = 0;
+
+
+     /* Ignore user's umask, set mode = 0600 */
+#ifndef HAVE_FCHMOD
+#ifdef HAVE_CHMOD
+     chmod(data->filename, S_IRUSR | S_IWUSR);
+#endif
+#else
+     fchmod(ret, S_IRUSR | S_IWUSR);
+#endif
+     if ((cnt = write(ret, (char *)&fcc_fvno, sizeof(fcc_fvno)))
+	 != sizeof(fcc_fvno)) {
+	  errsave = errno;
+	  (void) close(ret);
+	  (void) unlink(data->filename);
+	  kret = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
+	  goto err_out;
+     }
+     /* For version 4 we save a length for the rest of the header */
+     if (context->fcc_default_format == KRB5_FCC_FVNO_4) {
+	  if ((cnt = write(ret, (char *)&fcc_flen, sizeof(fcc_flen)))
+	      != sizeof(fcc_flen)) {
+	       errsave = errno;
+	       (void) close(ret);
+	       (void) unlink(data->filename);
+	       kret = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
+	       goto err_out;
+	  }
+     }
+     if (close(ret) == -1) {
+	  errsave = errno;
+	  (void) unlink(data->filename);
+	  kret = krb5_fcc_interpret(context, errsave);
+	  goto err_out;
+     }
+
+
+     setptr = malloc(sizeof(struct fcc_set));
+     if (setptr == NULL) {
+       k5_mutex_unlock(&krb5int_cc_file_mutex);
+       k5_mutex_destroy(&data->lock);
+       free(data->filename);
+       free(data);
+       (void) close(ret);
+       (void) unlink(scratch);
+       return KRB5_CC_NOMEM;
+     }
+     setptr->refcount = 1;
+     setptr->data = data;
+     setptr->next = fccs;
+     fccs = setptr;
+     k5_mutex_unlock(&krb5int_cc_file_mutex);
+
+     k5_mutex_assert_locked(&data->lock);
+     k5_mutex_unlock(&data->lock);
+     lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+     if (lid == NULL) {
+	 dereference(context, data);
+	 return KRB5_CC_NOMEM;
+     }
+
+     lid->ops = &krb5_fcc_ops;
+     lid->data = data;
+     lid->magic = KV5M_CCACHE;
+
+     /* default to open/close on every trn - otherwise destroy 
+	will get as to state confused */
+     ((krb5_fcc_data *) lid->data)->flags = KRB5_TC_OPENCLOSE;
+
+     *id = lid;
+
+       
+     krb5_change_cache ();
+     return KRB5_OK;
+
+err_out:
+     k5_mutex_unlock(&krb5int_cc_file_mutex);
+     k5_mutex_destroy(&data->lock);
+     free(data->filename);
+     free(data);
+     return kret;
+}
+
+/*
+ * Requires:
+ * id is a file credential cache
+ * 
+ * Returns:
+ * The name of the file cred cache id.
+ */
+static const char * KRB5_CALLCONV
+krb5_fcc_get_name (krb5_context context, krb5_ccache id)
+{
+     return (char *) ((krb5_fcc_data *) id->data)->filename;
+}
+
+/*
+ * Modifies:
+ * id, princ
+ *
+ * Effects:
+ * Retrieves the primary principal from id, as set with
+ * krb5_fcc_initialize.  The principal is returned is allocated
+ * storage that must be freed by the caller via krb5_free_principal.
+ *
+ * Errors:
+ * system errors
+ * KRB5_CC_NOMEM
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ)
+{
+     krb5_error_code kret = KRB5_OK;
+
+     kret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+     if (kret)
+	 return kret;
+
+     MAYBE_OPEN(context, id, FCC_OPEN_RDONLY);
+     
+     /* make sure we're beyond the header */
+     kret = krb5_fcc_skip_header(context, id);
+     if (kret) goto done;
+     kret = krb5_fcc_read_principal(context, id, princ);
+
+done:
+     MAYBE_CLOSE(context, id, kret);
+     k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+     return kret;
+}
+
+     
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds)
+{
+    return krb5_cc_retrieve_cred_default (context, id, whichfields,
+					  mcreds, creds);
+}
+
+
+/*
+ * Modifies:
+ * the file cache
+ *
+ * Effects:
+ * stores creds in the file cred cache
+ *
+ * Errors:
+ * system errors
+ * storage failure errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
+{
+#define TCHECK(ret) if (ret != KRB5_OK) goto lose;
+     krb5_error_code ret;
+
+     ret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+     if (ret)
+	 return ret;
+
+     /* Make sure we are writing to the end of the file */
+     MAYBE_OPEN(context, id, FCC_OPEN_RDWR);
+
+     /* Make sure we are writing to the end of the file */
+     ret = fcc_lseek((krb5_fcc_data *) id->data, (off_t) 0, SEEK_END);
+     if (ret < 0) {
+          MAYBE_CLOSE_IGNORE(context, id);
+	  k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+	  return krb5_fcc_interpret(context, errno);
+     }
+
+     ret = krb5_fcc_store_principal(context, id, creds->client);
+     TCHECK(ret);
+     ret = krb5_fcc_store_principal(context, id, creds->server);
+     TCHECK(ret);
+     ret = krb5_fcc_store_keyblock(context, id, &creds->keyblock);
+     TCHECK(ret);
+     ret = krb5_fcc_store_times(context, id, &creds->times);
+     TCHECK(ret);
+     ret = krb5_fcc_store_octet(context, id, (krb5_int32) creds->is_skey);
+     TCHECK(ret);
+     ret = krb5_fcc_store_int32(context, id, creds->ticket_flags);
+     TCHECK(ret);
+     ret = krb5_fcc_store_addrs(context, id, creds->addresses);
+     TCHECK(ret);
+     ret = krb5_fcc_store_authdata(context, id, creds->authdata);
+     TCHECK(ret);
+     ret = krb5_fcc_store_data(context, id, &creds->ticket);
+     TCHECK(ret);
+     ret = krb5_fcc_store_data(context, id, &creds->second_ticket);
+     TCHECK(ret);
+
+lose:
+     MAYBE_CLOSE(context, id, ret);
+     k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+     krb5_change_cache ();
+     return ret;
+#undef TCHECK
+}
+
+/* 
+ * Non-functional stub implementation for krb5_fcc_remove
+ * 
+ * Errors:
+ *    KRB5_CC_NOSUPP - not implemented
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags,
+                     krb5_creds *creds)
+{
+    return KRB5_CC_NOSUPP;
+}
+
+/*
+ * Requires:
+ * id is a cred cache returned by krb5_fcc_resolve or
+ * krb5_fcc_generate_new, but has not been opened by krb5_fcc_initialize.
+ *
+ * Modifies:
+ * id
+ * 
+ * Effects:
+ * Sets the operational flags of id to flags.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
+{
+    krb5_error_code ret = KRB5_OK;
+
+    ret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+    if (ret)
+	return ret;
+
+    /* XXX This should check for illegal combinations, if any.. */
+    if (flags & KRB5_TC_OPENCLOSE) {
+	/* asking to turn on OPENCLOSE mode */
+	if (!OPENCLOSE(id)
+	    /* XXX Is this test necessary? */
+	    && ((krb5_fcc_data *) id->data)->file != NO_FILE)
+            (void) krb5_fcc_close_file (context, ((krb5_fcc_data *) id->data));
+    } else {
+	/* asking to turn off OPENCLOSE mode, meaning it must be
+	   left open.  We open if it's not yet open */
+        MAYBE_OPEN(context, id, FCC_OPEN_RDONLY);
+    }
+
+    ((krb5_fcc_data *) id->data)->flags = flags;
+    k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+    return ret;
+}
+
+/*
+ * Requires:
+ * id is a cred cache returned by krb5_fcc_resolve or
+ * krb5_fcc_generate_new, but has not been opened by krb5_fcc_initialize.
+ *
+ * Modifies:
+ * id (mutex only; temporary)
+ * 
+ * Effects:
+ * Returns the operational flags of id.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags)
+{
+    krb5_error_code ret = KRB5_OK;
+
+    ret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+    if (ret)
+	return ret;
+    *flags = ((krb5_fcc_data *) id->data)->flags;
+    k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+    return ret;
+}
+
+
+static krb5_error_code
+krb5_fcc_interpret(krb5_context context, int errnum)
+{
+    register krb5_error_code retval;
+    switch (errnum) {
+    case ENOENT:
+	retval = KRB5_FCC_NOFILE;
+	break;
+    case EPERM:
+    case EACCES:
+#ifdef EISDIR
+    case EISDIR:                        /* Mac doesn't have EISDIR */
+#endif
+    case ENOTDIR:
+#ifdef ELOOP
+    case ELOOP:                         /* Bad symlink is like no file. */
+#endif
+#ifdef ETXTBSY
+    case ETXTBSY:
+#endif
+    case EBUSY:
+    case EROFS:
+	retval = KRB5_FCC_PERM;
+	break;
+    case EINVAL:
+    case EEXIST:			/* XXX */
+    case EFAULT:
+    case EBADF:
+#ifdef ENAMETOOLONG
+    case ENAMETOOLONG:
+#endif
+#ifdef EWOULDBLOCK
+    case EWOULDBLOCK:
+#endif
+	retval = KRB5_FCC_INTERNAL;
+	break;
+#ifdef EDQUOT
+    case EDQUOT:
+#endif
+    case ENOSPC:
+    case EIO:
+    case ENFILE:
+    case EMFILE:
+    case ENXIO:
+    default:
+	retval = KRB5_CC_IO;		/* XXX */
+	krb5_set_error_message(context, retval,
+			       "Credentials cache I/O operation failed (%s)",
+			       strerror(errnum));
+    }
+    return retval;
+}
+
+const krb5_cc_ops krb5_fcc_ops = {
+     0,
+     "FILE",
+     krb5_fcc_get_name,
+     krb5_fcc_resolve,
+     krb5_fcc_generate_new,
+     krb5_fcc_initialize,
+     krb5_fcc_destroy,
+     krb5_fcc_close,
+     krb5_fcc_store,
+     krb5_fcc_retrieve,
+     krb5_fcc_get_principal,
+     krb5_fcc_start_seq_get,
+     krb5_fcc_next_cred,
+     krb5_fcc_end_seq_get,
+     krb5_fcc_remove_cred,
+     krb5_fcc_set_flags,
+     krb5_fcc_get_flags,
+};
+
+#if defined(_WIN32)
+/*
+ * krb5_change_cache should be called after the cache changes.
+ * A notification message is is posted out to all top level
+ * windows so that they may recheck the cache based on the
+ * changes made.  We register a unique message type with which
+ * we'll communicate to all other processes. 
+ */
+
+krb5_error_code 
+krb5_change_cache (void) {
+
+    PostMessage(HWND_BROADCAST, krb5_get_notification_message(), 0, 0);
+
+    return 0;
+}
+
+unsigned int KRB5_CALLCONV
+krb5_get_notification_message (void) {
+    static unsigned int message = 0;
+
+    if (message == 0)
+        message = RegisterWindowMessage(WM_KERBEROS5_CHANGED);
+
+    return message;
+}
+#else /* _WIN32 */
+
+krb5_error_code
+krb5_change_cache (void)
+{
+    return 0;
+}
+unsigned int
+krb5_get_notification_message (void)
+{
+    return 0;
+}
+
+#endif /* _WIN32 */
+
+const krb5_cc_ops krb5_cc_file_ops = {
+     0,
+     "FILE",
+     krb5_fcc_get_name,
+     krb5_fcc_resolve,
+     krb5_fcc_generate_new,
+     krb5_fcc_initialize,
+     krb5_fcc_destroy,
+     krb5_fcc_close,
+     krb5_fcc_store,
+     krb5_fcc_retrieve,
+     krb5_fcc_get_principal,
+     krb5_fcc_start_seq_get,
+     krb5_fcc_next_cred,
+     krb5_fcc_end_seq_get,
+     krb5_fcc_remove_cred,
+     krb5_fcc_set_flags,
+     krb5_fcc_get_flags,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+};
diff --git a/krb5-1-6/src/lib/krb5/ccache/cc_keyring.c b/krb5-1-6/src/lib/krb5/ccache/cc_keyring.c
new file mode 100644
index 000000000..1e335b69a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cc_keyring.c
@@ -0,0 +1,2075 @@
+/*
+ * lib/krb5/ccache/cc_keyring.c
+ *
+ * Copyright (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ *
+ */
+/*
+ * Copyright 1990,1991,1992,1993,1994,2000,2004 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Original stdio support copyright 1995 by Cygnus Support.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Implementation of a credentials cache stored in the Linux keyring facility
+ *
+ * Some assumptions:
+ *
+ *	- A credentials cache "file" == a keyring with separate keys
+ *	  for the information in the ccache (see below)
+ *	- A credentials cache keyring will contain only keys,
+ *	  not other keyrings
+ *	- Each Kerberos ticket will have its own key within the ccache keyring
+ *	- The principal information for the ccache is stored in a
+ *	  special key, which is not counted in the 'numkeys' count
+ */
+
+#include "k5-int.h"
+
+#ifdef USE_KEYRING_CCACHE
+
+#include <errno.h>
+#include <keyutils.h>
+
+#ifdef DEBUG
+#define KRCC_DEBUG	    1
+#endif
+
+#if KRCC_DEBUG
+void debug_print(char *fmt, ...);	/* prototype to silence warning */
+#include <syslog.h>
+#define DEBUG_PRINT(x) debug_print x
+void
+debug_print(char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+#ifdef DEBUG_STDERR
+	vfprintf(stderr, fmt, ap);
+#else
+	vsyslog(LOG_ERR, fmt, ap);
+#endif
+	va_end(ap);
+}
+#else
+#define DEBUG_PRINT(x)
+#endif
+
+/*
+ * We always use "user" key type
+ */
+#define KRCC_KEY_TYPE_USER "user"
+
+/*
+ * We create ccaches as separate keyrings
+ */
+#define KRCC_KEY_TYPE_KEYRING "keyring"
+
+/*
+ * Special name of the key within a ccache keyring
+ * holding principal information
+ */
+#define KRCC_SPEC_PRINC_KEYNAME "__krb5_princ__"
+
+/*
+ * XXX The following two really belong in some external
+ * header since outside programs will need to use these
+ * same names.
+ */
+/*
+ * Special name for key to communicate key serial numbers
+ * This is used by the Linux gssd process to pass the
+ * user's keyring values it gets in an upcall.
+ * The format of the contents should be
+ *    <session_key>:<process_key>:<thread_key>
+ */
+#define KRCC_SPEC_IDS_KEYNAME "_gssd_keyring_ids_"
+
+/*
+ * Special name for the key to communicate the name(s)
+ * of credentials caches to be used for requests.
+ * This should currently contain a single name, but
+ * in the future may contain a list that may be
+ * intelligently chosen from.
+ */
+#define KRCC_SPEC_CCACHE_SET_KEYNAME "__krb5_cc_set__"
+
+#define KRB5_OK 0
+
+/* Hopefully big enough to hold a serialized credential */
+#define GUESS_CRED_SIZE 4096
+
+#define ALLOC(NUM,TYPE) \
+    (((NUM) <= (((size_t)0-1)/ sizeof(TYPE)))           \
+     ? (TYPE *) calloc((NUM), sizeof(TYPE))             \
+     : (errno = ENOMEM,(TYPE *) 0))
+
+#define CHECK_N_GO(ret, errdest) if (ret != KRB5_OK) goto errdest
+#define CHECK(ret) if (ret != KRB5_OK) goto errout
+#define CHECK_OUT(ret) if (ret != KRB5_OK) return ret
+
+typedef struct krb5_krcc_ring_ids {
+    key_serial_t	session;
+    key_serial_t	process;
+    key_serial_t	thread;
+} krb5_krcc_ring_ids_t;
+
+typedef struct _krb5_krcc_cursor
+{
+    int     numkeys;
+    int     currkey;
+    key_serial_t princ_id;
+    key_serial_t *keys;
+} *krb5_krcc_cursor;
+
+/*
+ * This represents a credentials cache "file"
+ * where ring_id is the keyring serial number for
+ * this credentials cache "file".  Each key
+ * in the keyring contains a separate key.
+ */
+typedef struct _krb5_krcc_data
+{
+    char   *name;		/* Name for this credentials cache */
+    k5_mutex_t lock;		/* synchronization */
+    key_serial_t parent_id;	/* parent keyring of this ccache keyring */
+    key_serial_t ring_id;	/* keyring representing ccache */
+    key_serial_t princ_id;	/* key holding principal info */
+    int     numkeys;		/* # of keys in this ring
+				 * (does NOT include principal info) */
+} krb5_krcc_data;
+
+/* Passed internally to assure we don't go past the bounds of our buffer */
+typedef struct _krb5_krcc_buffer_cursor
+{
+    char   *bpp;
+    char   *endp;
+} krb5_krcc_bc;
+
+/* Global mutex */
+k5_mutex_t krb5int_krcc_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+
+/*
+ * Internal functions (exported via the krb5_krcc_ops)
+ */
+
+extern const krb5_cc_ops krb5_krcc_ops;
+
+static const char *KRB5_CALLCONV krb5_krcc_get_name
+    (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_resolve
+    (krb5_context, krb5_ccache * id, const char *residual);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_generate_new
+    (krb5_context, krb5_ccache * id);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_initialize
+    (krb5_context, krb5_ccache id, krb5_principal princ);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_destroy
+    (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_close
+    (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_store
+    (krb5_context, krb5_ccache id, krb5_creds * creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_retrieve
+    (krb5_context, krb5_ccache id, krb5_flags whichfields,
+     krb5_creds * mcreds, krb5_creds * creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_get_principal
+    (krb5_context, krb5_ccache id, krb5_principal * princ);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_start_seq_get
+    (krb5_context, krb5_ccache id, krb5_cc_cursor * cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_next_cred
+    (krb5_context, krb5_ccache id, krb5_cc_cursor * cursor,
+     krb5_creds * creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_end_seq_get
+    (krb5_context, krb5_ccache id, krb5_cc_cursor * cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_remove_cred
+    (krb5_context context, krb5_ccache cache, krb5_flags flags,
+     krb5_creds * creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_set_flags
+    (krb5_context, krb5_ccache id, krb5_flags flags);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_get_flags
+    (krb5_context context, krb5_ccache id, krb5_flags * flags);
+
+/*
+ * Internal utility functions
+ */
+
+static krb5_error_code krb5_krcc_clearcache
+    (krb5_context context, krb5_ccache id);
+
+static krb5_error_code krb5_krcc_new_data
+    (const char *, key_serial_t ring, key_serial_t parent_ring,
+     krb5_krcc_data **);
+
+static krb5_error_code krb5_krcc_save_principal
+    (krb5_context context, krb5_ccache id, krb5_principal princ);
+
+static krb5_error_code krb5_krcc_retrieve_principal
+    (krb5_context context, krb5_ccache id, krb5_principal * princ);
+
+static int krb5_krcc_get_ring_ids(krb5_krcc_ring_ids_t *p);
+
+/* Routines to parse a key from a keyring into a cred structure */
+static krb5_error_code krb5_krcc_parse
+    (krb5_context, krb5_ccache id, krb5_pointer buf, unsigned int len,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_cred
+    (krb5_context context, krb5_ccache id, krb5_creds * creds,
+     char *payload, int psize);
+static krb5_error_code krb5_krcc_parse_principal
+    (krb5_context context, krb5_ccache id, krb5_principal * princ,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_keyblock
+    (krb5_context context, krb5_ccache id, krb5_keyblock * keyblock,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_times
+    (krb5_context context, krb5_ccache id, krb5_ticket_times * t,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_krb5data
+    (krb5_context context, krb5_ccache id, krb5_data * data,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_int32
+    (krb5_context context, krb5_ccache id, krb5_int32 * i, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_octet
+    (krb5_context context, krb5_ccache id, krb5_octet * octet,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_addrs
+    (krb5_context context, krb5_ccache id, krb5_address *** a,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_addr
+    (krb5_context context, krb5_ccache id, krb5_address * a,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_authdata
+    (krb5_context context, krb5_ccache id, krb5_authdata *** ad,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_authdatum
+    (krb5_context context, krb5_ccache id, krb5_authdata * ad,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_parse_ui_2
+    (krb5_context, krb5_ccache id, krb5_ui_2 * i, krb5_krcc_bc * bc);
+
+/* Routines to unparse a cred structure into keyring key */
+static krb5_error_code krb5_krcc_unparse
+    (krb5_context, krb5_ccache id, krb5_pointer buf, unsigned int len,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_cred
+    (krb5_context context, krb5_ccache id, krb5_creds * creds,
+     char **datapp, unsigned int *lenptr);
+static krb5_error_code krb5_krcc_unparse_principal
+    (krb5_context, krb5_ccache id, krb5_principal princ, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_keyblock
+    (krb5_context, krb5_ccache id, krb5_keyblock * keyblock,
+     krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_times
+    (krb5_context, krb5_ccache id, krb5_ticket_times * t, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_krb5data
+    (krb5_context, krb5_ccache id, krb5_data * data, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_int32
+    (krb5_context, krb5_ccache id, krb5_int32 i, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_octet
+    (krb5_context, krb5_ccache id, krb5_int32 i, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_addrs
+    (krb5_context, krb5_ccache, krb5_address ** a, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_addr
+    (krb5_context, krb5_ccache, krb5_address * a, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_authdata
+    (krb5_context, krb5_ccache, krb5_authdata ** ad, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_authdatum
+    (krb5_context, krb5_ccache, krb5_authdata * ad, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_ui_4
+    (krb5_context, krb5_ccache id, krb5_ui_4 i, krb5_krcc_bc * bc);
+static krb5_error_code krb5_krcc_unparse_ui_2
+    (krb5_context, krb5_ccache id, krb5_int32 i, krb5_krcc_bc * bc);
+
+/* Note the following is a stub function for Linux */
+extern krb5_error_code krb5_change_cache(void);
+
+/*
+ * Determine how many keys exist in a ccache keyring.
+ * Subtracts out the "hidden" key holding the principal information.
+ */
+static int KRB5_CALLCONV
+krb5_krcc_getkeycount(key_serial_t cred_ring)
+{
+    int res, nkeys;
+    
+    res = keyctl_read(cred_ring, NULL, 0);
+    if (res > 0)
+	nkeys = (res / sizeof(key_serial_t)) - 1;
+    else
+	nkeys = 0;
+    return(nkeys);
+}
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Creates/refreshes the cred cache id.  If the cache exists, its
+ * contents are destroyed.
+ *
+ * Errors:
+ * system errors
+ * permission errors
+ */
+
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_initialize(krb5_context context, krb5_ccache id,
+		     krb5_principal princ)
+{
+    krb5_error_code kret;
+
+    DEBUG_PRINT(("krb5_krcc_initialize: entered\n"));
+
+    kret = k5_mutex_lock(&((krb5_krcc_data *) id->data)->lock);
+    if (kret)
+	return kret;
+
+    kret = krb5_krcc_clearcache(context, id);
+    if (kret != KRB5_OK)
+	goto out;
+
+    kret = krb5_krcc_save_principal(context, id, princ);
+    if (kret == KRB5_OK)
+	krb5_change_cache();
+
+out:
+    k5_mutex_unlock(&((krb5_krcc_data *) id->data)->lock);
+    return kret;
+}
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Invalidates the id, and frees any resources associated with the cache.
+ * (Does NOT destroy the underlying ccache in the keyring.)
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_close(krb5_context context, krb5_ccache id)
+{
+    krb5_krcc_data *d;
+
+    DEBUG_PRINT(("krb5_krcc_close: entered\n"));
+
+    d = (krb5_krcc_data *) id->data;
+
+    krb5_xfree(d->name);
+    k5_mutex_destroy(&d->lock);
+    krb5_xfree(d);
+
+    krb5_xfree(id);
+
+    return KRB5_OK;
+}
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Clears out a ccache keyring, unlinking all keys within it
+ * (Including the "hidden" key with the principal information)
+ *
+ * Requires:
+ * Must be called with mutex locked.
+ *
+ * Errors:
+ * system errors
+ */
+
+static  krb5_error_code
+krb5_krcc_clearcache(krb5_context context, krb5_ccache id)
+{
+    krb5_krcc_data *d;
+    int     res;
+
+    k5_assert_locked(&((krb5_krcc_data *) id->data)->lock);
+
+    d = (krb5_krcc_data *) id->data;
+
+    DEBUG_PRINT(("krb5_krcc_clearcache: ring_id %d, princ_id %d, "
+		 "numkeys is %d\n", d->ring_id, d->princ_id, d->numkeys));
+
+    res = keyctl_clear(d->ring_id);
+    if (res != 0) {
+	return errno;
+    }
+    d->numkeys = 0;
+    d->princ_id = 0;
+
+    return KRB5_OK;
+}
+
+/*
+ * Effects:
+ * Destroys the contents of id.
+ *
+ * Errors:
+ * system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_destroy(krb5_context context, krb5_ccache id)
+{
+    krb5_error_code kret;
+    krb5_krcc_data *d;
+    int     res;
+
+    DEBUG_PRINT(("krb5_krcc_destroy: entered\n"));
+
+    d = (krb5_krcc_data *) id->data;
+
+    kret = k5_mutex_lock(&d->lock);
+    if (kret)
+	return kret;
+
+    krb5_krcc_clearcache(context, id);
+    krb5_xfree(d->name);
+    res = keyctl_unlink(d->ring_id, d->parent_id);
+    if (res < 0) {
+	kret = errno;
+	DEBUG_PRINT(("krb5_krcc_destroy: unlinking key %d from ring %d: %s",
+		     d->ring_id, d->parent_id, error_message(errno)));
+	goto cleanup;
+    }
+cleanup:
+    k5_mutex_unlock(&d->lock);
+    k5_mutex_destroy(&d->lock);
+    krb5_xfree(d);
+    krb5_xfree(id);
+
+    krb5_change_cache();
+
+    return KRB5_OK;
+}
+
+
+/*
+ * Requires:
+ * residual is a legal path name, and a null-terminated string
+ *
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * creates a cred cache that will reside in the keyring with
+ * a name of <residual>.
+ *
+ * Returns:
+ * A filled in krb5_ccache structure "id".
+ *
+ * Errors:
+ * KRB5_CC_NOMEM - there was insufficient memory to allocate the
+ *              krb5_ccache.  id is undefined.
+ * permission errors
+ */
+
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_resolve(krb5_context context, krb5_ccache * id, const char *full_residual)
+{
+    krb5_ccache lid;
+    krb5_error_code kret;
+    krb5_krcc_data *d;
+    key_serial_t key;
+    key_serial_t pkey = 0;
+    int     nkeys = 0;
+    int     res;
+    krb5_krcc_ring_ids_t ids;
+    key_serial_t ring_id;
+    const char *residual;
+
+    DEBUG_PRINT(("krb5_krcc_resolve: entered with name '%s'\n",
+		 full_residual));
+
+    res = krb5_krcc_get_ring_ids(&ids);
+    if (res) {
+	kret = EINVAL;
+	DEBUG_PRINT(("krb5_krcc_resolve: Error getting ring id values!\n"));
+	return kret;
+    }
+
+    if (strncmp(full_residual, "thread:", 7) == 0) {
+	residual = full_residual + 7;
+	ring_id = ids.thread;
+    } else if (strncmp(full_residual, "process:", 8) == 0) {
+	residual = full_residual + 8;
+	ring_id = ids.process;
+    } else {
+	residual = full_residual;
+	ring_id = ids.session;
+    }
+
+    DEBUG_PRINT(("krb5_krcc_resolve: searching ring %d for residual '%s'\n",
+    		ring_id, residual));
+
+    /*
+     * Use keyctl_search instead of request_key. If we're supposed
+     * to be looking for a process ccache, we shouldn't find a
+     * thread ccache.
+     * XXX But should we look in the session ring if we don't find it
+     * in the process ring?  Same goes for thread.  Should we look in
+     * the process and session rings if not found in the thread ring?
+     *
+     */
+    key = keyctl_search(ring_id, KRCC_KEY_TYPE_KEYRING, residual, 0);
+    if (key < 0) {
+	key = add_key(KRCC_KEY_TYPE_KEYRING, residual, NULL, 0, ring_id);
+	if (key < 0) {
+	    kret = errno;
+	    DEBUG_PRINT(("krb5_krcc_resolve: Error adding new "
+			 "keyring '%s': %s\n", residual, strerror(errno)));
+	    return kret;
+	}
+	DEBUG_PRINT(("krb5_krcc_resolve: new keyring '%s', "
+			"key %d, added to keyring %d\n",
+			residual, key, ring_id));
+    } else {
+	DEBUG_PRINT(("krb5_krcc_resolve: found existing "
+			"key %d, with name '%s' in keyring %d\n",
+			key, residual, ring_id));
+	/* Determine key containing principal information */
+	pkey = keyctl_search(key, KRCC_KEY_TYPE_USER,
+			     KRCC_SPEC_PRINC_KEYNAME, 0);
+	if (pkey < 0) {
+	    DEBUG_PRINT(("krb5_krcc_resolve: Error locating principal "
+			 "info for existing ccache in ring %d: %s\n",
+			 key, strerror(errno)));
+	    pkey = 0;
+	}
+	/* Determine how many keys exist */
+	nkeys = krb5_krcc_getkeycount(key);
+    }
+
+    lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+    if (lid == NULL)
+	return KRB5_CC_NOMEM;
+
+
+    kret = krb5_krcc_new_data(residual, key, ring_id, &d);
+    if (kret) {
+	free(lid);
+	return kret;
+    }
+
+    DEBUG_PRINT(("krb5_krcc_resolve: ring_id %d, princ_id %d, "
+		 "nkeys %d\n", key, pkey, nkeys));
+    d->princ_id = pkey;
+    d->numkeys = nkeys;
+    lid->ops = &krb5_krcc_ops;
+    lid->data = d;
+    lid->magic = KV5M_CCACHE;
+    *id = lid;
+    return KRB5_OK;
+}
+
+/*
+ * Effects:
+ * Prepares for a sequential search of the credentials cache.
+ * Returns a krb5_cc_cursor to be used with krb5_krcc_next_cred and
+ * krb5_krcc_end_seq_get.
+ *
+ * If the cache is modified between the time of this call and the time
+ * of the final krb5_krcc_end_seq_get, the results are undefined.
+ *
+ * Errors:
+ * KRB5_CC_NOMEM
+ * system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_start_seq_get(krb5_context context, krb5_ccache id,
+			krb5_cc_cursor * cursor)
+{
+    krb5_krcc_cursor krcursor;
+    krb5_error_code kret;
+    krb5_krcc_data *d;
+    unsigned int size;
+    int     res;
+
+    DEBUG_PRINT(("krb5_krcc_start_seq_get: entered\n"));
+
+    d = id->data;
+    kret = k5_mutex_lock(&d->lock);
+    if (kret)
+	return kret;
+
+    /*
+     * Determine how many keys currently exist and update numkeys.
+     * We cannot depend on the current value of numkeys because
+     * the ccache may have been updated elsewhere
+     */
+    d->numkeys = krb5_krcc_getkeycount(d->ring_id);
+
+    size = sizeof(*krcursor) + ((d->numkeys + 1) * sizeof(key_serial_t));
+
+    krcursor = (krb5_krcc_cursor) malloc(size);
+    if (krcursor == NULL) {
+	k5_mutex_unlock(&d->lock);
+	return KRB5_CC_NOMEM;
+    }
+
+    krcursor->keys = (key_serial_t *) ((char *) krcursor + sizeof(*krcursor));
+    res = keyctl_read(d->ring_id, (char *) krcursor->keys,
+		      ((d->numkeys + 1) * sizeof(key_serial_t)));
+    if (res < 0 || res > ((d->numkeys + 1) * sizeof(key_serial_t))) {
+	DEBUG_PRINT(("Read %d bytes from keyring, numkeys %d: %s\n",
+		     res, d->numkeys, strerror(errno)));
+	free(krcursor);
+	k5_mutex_unlock(&d->lock);
+	return KRB5_CC_IO;
+    }
+
+    krcursor->numkeys = d->numkeys;
+    krcursor->currkey = 0;
+    krcursor->princ_id = d->princ_id;
+
+    k5_mutex_unlock(&d->lock);
+    *cursor = (krb5_cc_cursor) krcursor;
+    return KRB5_OK;
+}
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_krcc_start_seq_get.
+ *
+ * Modifes:
+ * cursor, creds
+ *
+ * Effects:
+ * Fills in creds with the "next" credentals structure from the cache
+ * id.  The actual order the creds are returned in is arbitrary.
+ * Space is allocated for the variable length fields in the
+ * credentials structure, so the object returned must be passed to
+ * krb5_destroy_credential.
+ *
+ * The cursor is updated for the next call to krb5_krcc_next_cred.
+ *
+ * Errors:
+ * system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_next_cred(krb5_context context, krb5_ccache id,
+		    krb5_cc_cursor * cursor, krb5_creds * creds)
+{
+    krb5_krcc_cursor krcursor;
+    krb5_error_code kret;
+    int     psize;
+    void   *payload = NULL;
+
+    DEBUG_PRINT(("krb5_krcc_next_cred: entered\n"));
+
+    /*
+     * The cursor has the entire list of keys.
+     * (Note that we don't support _remove_cred.)
+     */
+    krcursor = (krb5_krcc_cursor) * cursor;
+    if (krcursor == NULL)
+	return KRB5_CC_END;
+    memset(creds, 0, sizeof(krb5_creds));
+
+    /* If we're pointing past the end of the keys array, there are no more */
+    if (krcursor->currkey > krcursor->numkeys)
+	return KRB5_CC_END;
+
+    /* If we're pointing at the entry with the principal, skip it */
+    if (krcursor->keys[krcursor->currkey] == krcursor->princ_id) {
+	krcursor->currkey++;
+	/* Check if we have now reached the end */
+	if (krcursor->currkey > krcursor->numkeys)
+	  return KRB5_CC_END;
+    }
+
+    /* Read the key, the right size buffer will ba allocated and returned */
+    psize = keyctl_read_alloc(krcursor->keys[krcursor->currkey], &payload);
+    if (psize == -1) {
+	DEBUG_PRINT(("Error reading key %d: %s\n",
+		     krcursor->keys[krcursor->currkey],
+		     strerror(errno)));
+	kret = KRB5_FCC_NOFILE;
+	goto freepayload;
+    }
+    krcursor->currkey++;
+
+    kret = krb5_krcc_parse_cred(context, id, creds, payload, psize);
+
+  freepayload:
+    if (payload) free(payload);
+    return kret;
+}
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_krcc_start_seq_get.
+ *
+ * Modifies:
+ * id, cursor
+ *
+ * Effects:
+ * Finishes sequential processing of the keyring credentials ccache id,
+ * and invalidates the cursor (it must never be used after this call).
+ */
+/* ARGSUSED */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_end_seq_get(krb5_context context, krb5_ccache id,
+		      krb5_cc_cursor * cursor)
+{
+    DEBUG_PRINT(("krb5_krcc_end_seq_get: entered\n"));
+
+    free(*cursor);
+    *cursor = 0L;
+    return KRB5_OK;
+}
+
+/* Utility routine: Creates the back-end data for a keyring cache.
+
+   Call with the global list lock held.  */
+static  krb5_error_code
+krb5_krcc_new_data(const char *name, key_serial_t ring,
+		   key_serial_t parent_ring, krb5_krcc_data ** datapp)
+{
+    krb5_error_code kret;
+    krb5_krcc_data *d;
+
+    d = malloc(sizeof(krb5_krcc_data));
+    if (d == NULL)
+	return KRB5_CC_NOMEM;
+
+    kret = k5_mutex_init(&d->lock);
+    if (kret) {
+	krb5_xfree(d);
+	return kret;
+    }
+
+    d->name = strdup(name);
+    if (d->name == NULL) {
+	k5_mutex_destroy(&d->lock);
+	krb5_xfree(d);
+	return KRB5_CC_NOMEM;
+    }
+    d->princ_id = 0;
+    d->ring_id = ring;
+    d->parent_id = parent_ring;
+    d->numkeys = 0;
+
+    *datapp = d;
+    return 0;
+}
+
+/* Utility routine: Creates a random memory ccache name. 
+ * This algorithm was selected because it creates readable 
+ * random ccache names in a fixed size buffer.  */
+
+static krb5_error_code
+random_string (krb5_context context, char *string, krb5_int32 length)
+{
+    static const unsigned char charlist[] =
+	"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    krb5_error_code err = 0;
+    unsigned char *bytes = NULL;
+    size_t bytecount = length - 1;
+
+    if (!err) {
+	bytes = malloc (bytecount);
+	if (bytes == NULL) { err = ENOMEM; }
+    }
+
+    if (!err) {
+	krb5_data data;
+	data.length = bytecount;
+	data.data = (char *) bytes;
+	err = krb5_c_random_make_octets (context, &data);
+    }
+
+    if (!err) {
+	krb5_int32 i;
+	for (i = 0; i < bytecount; i++) {
+	    string [i] = charlist[bytes[i] % (sizeof (charlist) - 1)];
+	}
+	string[length - 1] = '\0';
+    }
+
+    if (bytes != NULL) { free (bytes); }
+
+    return err;
+}
+
+/*
+ * Effects:
+ * Creates a new keyring cred cache whose name is guaranteed to be
+ * unique.
+ *
+ * Returns:
+ * The filled in krb5_ccache id.
+ *
+ * Errors:
+ * KRB5_CC_NOMEM - there was insufficient memory to allocate the
+ *              krb5_ccache.  id is undefined.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_generate_new(krb5_context context, krb5_ccache * id)
+{
+    krb5_ccache lid;
+    char uniquename[8];
+    krb5_error_code kret;
+    krb5_krcc_data *d;
+    key_serial_t ring_id = KEY_SPEC_SESSION_KEYRING;
+    key_serial_t key;
+
+    DEBUG_PRINT(("krb5_krcc_generate_new: entered\n"));
+
+    /* Allocate memory */
+    lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+    if (lid == NULL)
+	return KRB5_CC_NOMEM;
+
+    lid->ops = &krb5_krcc_ops;
+
+    kret = k5_mutex_lock(&krb5int_krcc_mutex);
+    if (kret) {
+	free(lid);
+	return kret;
+    }
+
+/* XXX These values are platform-specific and should not be here! */
+/* XXX There is a bug in FC5 where these are not included in errno.h  */
+#ifndef ENOKEY
+#define ENOKEY          126     /* Required key not available */
+#endif
+#ifndef EKEYEXPIRED
+#define EKEYEXPIRED     127     /* Key has expired */
+#endif
+#ifndef EKEYREVOKED
+#define EKEYREVOKED     128     /* Key has been revoked */
+#endif
+#ifndef EKEYREJECTED
+#define EKEYREJECTED    129     /* Key was rejected by service */
+#endif
+
+    /*
+     * Loop until we successfully create a new ccache keyring with
+     * a unique name, or we get an error.
+     */
+    while (1) {
+	random_string(context, uniquename, sizeof(uniquename));
+	DEBUG_PRINT(("krb5_krcc_generate_new: searching for name '%s'\n",
+		     uniquename));
+	key = keyctl_search(ring_id, KRCC_KEY_TYPE_KEYRING, uniquename, 0);
+/*XXX*/ DEBUG_PRINT(("krb5_krcc_generate_new: after searching for '%s', key = %d, errno = %d\n", uniquename, key, errno));
+	if (key < 0 && errno == ENOKEY) {
+	    /* name does not already exist, create it to reserve the name */
+	    key = add_key(KRCC_KEY_TYPE_KEYRING, uniquename, NULL, 0, ring_id);
+	    if (key < 0) {
+		kret = errno;
+		DEBUG_PRINT(("krb5_krcc_generate_new: '%s' trying to "
+			     "create '%s'\n", strerror(errno), uniquename));
+		k5_mutex_unlock(&krb5int_krcc_mutex);
+		return kret;
+	    }
+	    break;
+	}
+    }
+	    
+    kret = krb5_krcc_new_data(uniquename, key, ring_id, &d);
+    k5_mutex_unlock(&krb5int_krcc_mutex);
+    if (kret) {
+	krb5_xfree(lid);
+	return kret;
+    }
+    lid->data = d;
+    *id = lid;
+    krb5_change_cache();
+    return KRB5_OK;
+}
+
+/*
+ * Requires:
+ * id is a keyring credential cache
+ *
+ * Returns:
+ * The name of the keyring cred cache id.
+ */
+static const char *KRB5_CALLCONV
+krb5_krcc_get_name(krb5_context context, krb5_ccache id)
+{
+    DEBUG_PRINT(("krb5_krcc_get_name: entered\n"));
+    return (char *) ((krb5_krcc_data *) id->data)->name;
+}
+
+/*
+ * Modifies:
+ * id, princ
+ *
+ * Effects:
+ * Retrieves the primary principal from id, as set with
+ * krb5_krcc_initialize.  The principal is returned is allocated
+ * storage that must be freed by the caller via krb5_free_principal.
+ *
+ * Errors:
+ * system errors
+ * KRB5_CC_NOMEM
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_get_principal(krb5_context context, krb5_ccache id,
+			krb5_principal * princ)
+{
+    DEBUG_PRINT(("krb5_krcc_get_principal: entered\n"));
+
+    return krb5_krcc_retrieve_principal(context, id, princ);
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_retrieve(krb5_context context, krb5_ccache id,
+		   krb5_flags whichfields, krb5_creds * mcreds,
+		   krb5_creds * creds)
+{
+    DEBUG_PRINT(("krb5_krcc_retrieve: entered\n"));
+
+    return krb5_cc_retrieve_cred_default(context, id, whichfields,
+					 mcreds, creds);
+}
+
+/*
+ * Non-functional stub implementation for krb5_krcc_remove
+ *
+ * Errors:
+ *    KRB5_CC_NOSUPP - not implemented
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_remove_cred(krb5_context context, krb5_ccache cache,
+		      krb5_flags flags, krb5_creds * creds)
+{
+    DEBUG_PRINT(("krb5_krcc_remove_cred: entered (returning KRB5_CC_NOSUPP)\n"));
+
+    return KRB5_CC_NOSUPP;
+}
+
+/*
+ * Requires:
+ * id is a cred cache returned by krb5_krcc_resolve or
+ * krb5_krcc_generate_new, but has not been opened by krb5_krcc_initialize.
+ *
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Sets the operational flags of id to flags.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
+{
+    DEBUG_PRINT(("krb5_krcc_set_flags: entered\n"));
+
+    return KRB5_OK;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags * flags)
+{
+    DEBUG_PRINT(("krb5_krcc_get_flags: entered\n"));
+
+    *flags = 0;
+    return KRB5_OK;
+}
+
+/* store: Save away creds in the ccache keyring.  */
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_store(krb5_context context, krb5_ccache id, krb5_creds * creds)
+{
+    krb5_error_code kret;
+    krb5_krcc_data *d = (krb5_krcc_data *) id->data;
+    char   *payload = NULL;
+    unsigned int payloadlen;
+    key_serial_t newkey;
+    char   *keyname = NULL;
+
+    DEBUG_PRINT(("krb5_krcc_store: entered\n"));
+
+    kret = k5_mutex_lock(&d->lock);
+    if (kret)
+	return kret;
+
+    /* Get the service principal name and use it as the key name */
+    kret = krb5_unparse_name(context, creds->server, &keyname);
+    if (kret) {
+	DEBUG_PRINT(("Error unparsing service principal name!\n"));
+	goto errout;
+    }
+
+    /* Serialize credential into memory */
+    kret = krb5_krcc_unparse_cred(context, id, creds, &payload, &payloadlen);
+    if (kret != KRB5_OK)
+	goto errout;
+
+    /* Add new key (credentials) into keyring */
+    DEBUG_PRINT(("krb5_krcc_store: adding new key '%s' to keyring %d\n",
+			keyname, d->ring_id));
+    newkey = add_key(KRCC_KEY_TYPE_USER, keyname, payload,
+		     payloadlen, d->ring_id);
+    if (newkey < 0) {
+	kret = errno;
+	DEBUG_PRINT(("Error adding user key '%s': %s\n",
+		     keyname, strerror(kret)));
+    } else {
+	d->numkeys++;
+	kret = KRB5_OK;
+    }
+
+  errout:
+    if (keyname)
+	krb5_free_unparsed_name(context, keyname);
+    if (payload)
+	free(payload);
+
+    k5_mutex_unlock(&d->lock);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_save_principal(krb5_context context, krb5_ccache id,
+			 krb5_principal princ)
+{
+    krb5_krcc_data *d;
+    krb5_error_code kret;
+    char   *payload;
+    key_serial_t newkey;
+    unsigned int payloadsize;
+    krb5_krcc_bc bc;
+
+    k5_assert_locked(&((krb5_krcc_data *) id->data)->lock);
+
+    d = (krb5_krcc_data *) id->data;
+
+    payload = malloc(GUESS_CRED_SIZE);
+    if (payload == NULL)
+	return KRB5_CC_NOMEM;
+
+    bc.bpp = payload;
+    bc.endp = payload + GUESS_CRED_SIZE;
+
+    kret = krb5_krcc_unparse_principal(context, id, princ, &bc);
+    CHECK_N_GO(kret, errout);
+
+    /* Add new key into keyring */
+    payloadsize = bc.bpp - payload;
+#ifdef KRCC_DEBUG
+    {
+	krb5_error_code rc;
+	char *princname = NULL;
+	rc = krb5_unparse_name(context, princ, &princname);
+	DEBUG_PRINT(("krb5_krcc_save_principal: adding new key '%s' "
+		     "to keyring %d for principal '%s'\n",
+		     KRCC_SPEC_PRINC_KEYNAME, d->ring_id,
+		     rc ? "<unknown>" : princname));
+	if (rc == 0)
+	    krb5_free_unparsed_name(context, princname);
+    }
+#endif
+    newkey = add_key(KRCC_KEY_TYPE_USER, KRCC_SPEC_PRINC_KEYNAME, payload,
+    		     payloadsize, d->ring_id);
+    if (newkey < 0) {
+	kret = errno;
+	DEBUG_PRINT(("Error adding principal key: %s\n", strerror(kret)));
+    } else {
+	d->princ_id = newkey;
+	kret = KRB5_OK;
+    }
+
+  errout:
+    free(payload);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_retrieve_principal(krb5_context context, krb5_ccache id,
+			     krb5_principal * princ)
+{
+    krb5_krcc_data *d = (krb5_krcc_data *) id->data;
+    krb5_error_code kret;
+    void   *payload = NULL;
+    int     psize;
+    krb5_krcc_bc bc;
+
+    kret = k5_mutex_lock(&d->lock);
+    if (kret)
+	return kret;
+
+    if (!d->princ_id) {
+	princ = 0L;
+	kret = KRB5_FCC_NOFILE;
+	goto errout;
+    }
+
+    psize = keyctl_read_alloc(d->princ_id, &payload);
+    if (psize == -1) {
+	DEBUG_PRINT(("Reading principal key %d: %s\n",
+		     d->princ_id, strerror(errno)));
+	kret = KRB5_CC_IO;
+	goto errout;
+    }
+    bc.bpp = payload;
+    bc.endp = (char *)payload + psize;
+    kret = krb5_krcc_parse_principal(context, id, princ, &bc);
+
+  errout:
+    if (payload)
+	free(payload);
+    k5_mutex_unlock(&d->lock);
+    return kret;
+}
+
+static int
+krb5_krcc_get_ring_ids(krb5_krcc_ring_ids_t *p)
+{
+    key_serial_t ids_key;
+    char ids_buf[128];
+    key_serial_t session, process, thread;
+    long val;
+
+    DEBUG_PRINT(("krb5_krcc_get_ring_ids: entered\n"));
+
+    if (!p)
+	return EINVAL;
+
+    /* Use the defaults in case we find no ids key */
+    p->session = KEY_SPEC_SESSION_KEYRING;
+    p->process = KEY_SPEC_PROCESS_KEYRING;
+    p->thread = KEY_SPEC_THREAD_KEYRING;
+
+    /*
+     * Note that in the "normal" case, this will not be found.
+     * The Linux gssd creates this key while creating a
+     * context to communicate the user's key serial numbers.
+     */
+    ids_key = request_key(KRCC_KEY_TYPE_USER, KRCC_SPEC_IDS_KEYNAME, NULL, 0);
+    if (ids_key < 0)
+	goto out;
+
+    DEBUG_PRINT(("krb5_krcc_get_ring_ids: processing '%s' key %d\n",
+		KRCC_SPEC_IDS_KEYNAME, ids_key));
+    /*
+     * Read and parse the ids file
+     */
+    memset(ids_buf, '\0', sizeof(ids_buf));
+    val = keyctl_read(ids_key, ids_buf, sizeof(ids_buf));
+    if (val > sizeof(ids_buf))
+	goto out;
+
+    val = sscanf(ids_buf, "%d:%d:%d", &session, &process, &thread);
+    if (val != 3)
+	goto out;
+
+    p->session = session;
+    p->process = process;
+    p->thread = thread;
+
+  out:
+    DEBUG_PRINT(("krb5_krcc_get_ring_ids: returning %d:%d:%d\n",
+		p->session, p->process, p->thread));
+    return 0;
+}
+
+/*
+ * ===============================================================
+ * INTERNAL functions to parse a credential from a key payload
+ * (Borrowed heavily from krb5_fcc_{read|store}_ funtions.)
+ * ===============================================================
+ */
+
+/*
+ * Effects:
+ * Copies len bytes from the key payload buffer into buf.
+ * Updates payload pointer and returns KRB5_CC_END if we
+ * try to read past the end of the payload buffer's data.
+ *
+ * Requires:
+ * Must be called with mutex locked.
+ *
+ * Errors:
+ * KRB5_CC_END - there were not len bytes available
+ */
+static  krb5_error_code
+krb5_krcc_parse(krb5_context context, krb5_ccache id, krb5_pointer buf,
+		unsigned int len, krb5_krcc_bc * bc)
+{
+    DEBUG_PRINT(("krb5_krcc_parse: entered\n"));
+
+    if ((bc->endp == bc->bpp) || (bc->endp - bc->bpp) < len)
+	return KRB5_CC_END;
+
+    memcpy(buf, bc->bpp, len);
+    bc->bpp += len;
+
+    return KRB5_OK;
+}
+
+/*
+ * Take a key (credential) read from a keyring entry
+ * and parse it into a credential structure.
+ */
+static  krb5_error_code
+krb5_krcc_parse_cred(krb5_context context, krb5_ccache id, krb5_creds * creds,
+		     char *payload, int psize)
+{
+    krb5_error_code kret;
+    krb5_octet octet;
+    krb5_int32 int32;
+    krb5_krcc_bc bc;
+
+    /* Parse the pieces of the credential */
+    bc.bpp = payload;
+    bc.endp = bc.bpp + psize;
+    kret = krb5_krcc_parse_principal(context, id, &creds->client, &bc);
+    CHECK_N_GO(kret, out);
+
+    kret = krb5_krcc_parse_principal(context, id, &creds->server, &bc);
+    CHECK_N_GO(kret, cleanclient);
+
+    kret = krb5_krcc_parse_keyblock(context, id, &creds->keyblock, &bc);
+    CHECK_N_GO(kret, cleanserver);
+
+    kret = krb5_krcc_parse_times(context, id, &creds->times, &bc);
+    CHECK_N_GO(kret, cleanserver);
+
+    kret = krb5_krcc_parse_octet(context, id, &octet, &bc);
+    CHECK_N_GO(kret, cleanserver);
+    creds->is_skey = octet;
+
+    kret = krb5_krcc_parse_int32(context, id, &int32, &bc);
+    CHECK_N_GO(kret, cleanserver);
+    creds->ticket_flags = int32;
+
+    kret = krb5_krcc_parse_addrs(context, id, &creds->addresses, &bc);
+    CHECK_N_GO(kret, cleanblock);
+
+    kret = krb5_krcc_parse_authdata(context, id, &creds->authdata, &bc);
+    CHECK_N_GO(kret, cleanaddrs);
+
+    kret = krb5_krcc_parse_krb5data(context, id, &creds->ticket, &bc);
+    CHECK_N_GO(kret, cleanauthdata);
+
+    kret = krb5_krcc_parse_krb5data(context, id, &creds->second_ticket, &bc);
+    CHECK_N_GO(kret, cleanticket);
+
+    kret = KRB5_OK;
+    goto out;
+
+  cleanticket:
+    memset(creds->ticket.data, 0, (unsigned) creds->ticket.length);
+    krb5_xfree(creds->ticket.data);
+  cleanauthdata:
+    /* XXX ??? */
+  cleanaddrs:
+    krb5_free_addresses(context, creds->addresses);
+  cleanblock:
+    krb5_xfree(creds->keyblock.contents);
+  cleanserver:
+    krb5_free_principal(context, creds->server);
+  cleanclient:
+    krb5_free_principal(context, creds->client);
+
+  out:
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_principal(krb5_context context, krb5_ccache id,
+			  krb5_principal * princ, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    register krb5_principal tmpprinc;
+    krb5_int32 length, type;
+    int     i;
+
+    /* Read principal type */
+    kret = krb5_krcc_parse_int32(context, id, &type, bc);
+    if (kret != KRB5_OK)
+	return kret;
+
+    /* Read the number of components */
+    kret = krb5_krcc_parse_int32(context, id, &length, bc);
+    if (kret != KRB5_OK)
+	return kret;
+
+    if (length < 0)
+	return KRB5_CC_NOMEM;
+
+    tmpprinc = (krb5_principal) malloc(sizeof(krb5_principal_data));
+    if (tmpprinc == NULL)
+	return KRB5_CC_NOMEM;
+    if (length) {
+	size_t  msize = length;
+	if (msize != length) {
+	    free(tmpprinc);
+	    return KRB5_CC_NOMEM;
+	}
+	tmpprinc->data = ALLOC(msize, krb5_data);
+	if (tmpprinc->data == 0) {
+	    free((char *) tmpprinc);
+	    return KRB5_CC_NOMEM;
+	}
+    } else
+	tmpprinc->data = 0;
+    tmpprinc->magic = KV5M_PRINCIPAL;
+    tmpprinc->length = length;
+    tmpprinc->type = type;
+
+    kret = krb5_krcc_parse_krb5data(context, id,
+				    krb5_princ_realm(context, tmpprinc), bc);
+    i = 0;
+    CHECK(kret);
+
+    for (i = 0; i < length; i++) {
+	kret = krb5_krcc_parse_krb5data(context, id,
+					krb5_princ_component(context, tmpprinc,
+							     i), bc);
+	CHECK(kret);
+    }
+    *princ = tmpprinc;
+    return KRB5_OK;
+
+  errout:
+    while (--i >= 0)
+	free(krb5_princ_component(context, tmpprinc, i)->data);
+    free((char *) tmpprinc->data);
+    free((char *) tmpprinc);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_keyblock(krb5_context context, krb5_ccache id,
+			 krb5_keyblock * keyblock, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_ui_2 ui2;
+    krb5_int32 int32;
+
+    keyblock->magic = KV5M_KEYBLOCK;
+    keyblock->contents = 0;
+
+    kret = krb5_krcc_parse_ui_2(context, id, &ui2, bc);
+    CHECK(kret);
+    keyblock->enctype = ui2;
+
+    kret = krb5_krcc_parse_int32(context, id, &int32, bc);
+    CHECK(kret);
+    if (int32 < 0)
+	return KRB5_CC_NOMEM;
+    keyblock->length = int32;
+    /* Overflow check.  */
+    if (keyblock->length != int32)
+	return KRB5_CC_NOMEM;
+    if (keyblock->length == 0)
+	return KRB5_OK;
+    keyblock->contents = ALLOC(keyblock->length, krb5_octet);
+    if (keyblock->contents == NULL)
+	return KRB5_CC_NOMEM;
+
+    kret = krb5_krcc_parse(context, id, keyblock->contents,
+			   keyblock->length, bc);
+    CHECK(kret);
+
+    return KRB5_OK;
+  errout:
+    if (keyblock->contents)
+	krb5_xfree(keyblock->contents);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_times(krb5_context context, krb5_ccache id,
+		      krb5_ticket_times * t, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_int32 i;
+
+    kret = krb5_krcc_parse_int32(context, id, &i, bc);
+    CHECK(kret);
+    t->authtime = i;
+
+    kret = krb5_krcc_parse_int32(context, id, &i, bc);
+    CHECK(kret);
+    t->starttime = i;
+
+    kret = krb5_krcc_parse_int32(context, id, &i, bc);
+    CHECK(kret);
+    t->endtime = i;
+
+    kret = krb5_krcc_parse_int32(context, id, &i, bc);
+    CHECK(kret);
+    t->renew_till = i;
+
+    return 0;
+  errout:
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_krb5data(krb5_context context, krb5_ccache id,
+			 krb5_data * data, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_int32 len;
+
+    data->magic = KV5M_DATA;
+    data->data = 0;
+
+    kret = krb5_krcc_parse_int32(context, id, &len, bc);
+    CHECK(kret);
+    if (len < 0)
+	return KRB5_CC_NOMEM;
+    data->length = len;
+    if (data->length != len || data->length + 1 == 0)
+	return KRB5_CC_NOMEM;
+
+    if (data->length == 0) {
+	data->data = 0;
+	return KRB5_OK;
+    }
+
+    data->data = (char *) malloc(data->length + 1);
+    if (data->data == NULL)
+	return KRB5_CC_NOMEM;
+
+    kret = krb5_krcc_parse(context, id, data->data, (unsigned) data->length,
+			   bc);
+    CHECK(kret);
+
+    data->data[data->length] = 0;	/* Null terminate, just in case.... */
+    return KRB5_OK;
+  errout:
+    if (data->data)
+	krb5_xfree(data->data);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_int32(krb5_context context, krb5_ccache id, krb5_int32 * i,
+		      krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    unsigned char buf[4];
+    krb5_int32 val;
+
+    kret = krb5_krcc_parse(context, id, buf, 4, bc);
+    if (kret)
+	return kret;
+    val = buf[0];
+    val = (val << 8) | buf[1];
+    val = (val << 8) | buf[2];
+    val = (val << 8) | buf[3];
+    *i = val;
+    return 0;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_octet(krb5_context context, krb5_ccache id, krb5_octet * i,
+		      krb5_krcc_bc * bc)
+{
+    return krb5_krcc_parse(context, id, (krb5_pointer) i, 1, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_parse_addrs(krb5_context context, krb5_ccache id,
+		      krb5_address *** addrs, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_int32 length;
+    size_t  msize;
+    int     i;
+
+    *addrs = 0;
+
+    /* Read the number of components */
+    kret = krb5_krcc_parse_int32(context, id, &length, bc);
+    CHECK(kret);
+
+    /*
+     * Make *addrs able to hold length pointers to krb5_address structs
+     * Add one extra for a null-terminated list
+     */
+    msize = length;
+    msize += 1;
+    if (msize == 0 || msize - 1 != length || length < 0)
+	return KRB5_CC_NOMEM;
+    *addrs = ALLOC(msize, krb5_address *);
+    if (*addrs == NULL)
+	return KRB5_CC_NOMEM;
+
+    for (i = 0; i < length; i++) {
+	(*addrs)[i] = (krb5_address *) malloc(sizeof(krb5_address));
+	if ((*addrs)[i] == NULL) {
+	    krb5_free_addresses(context, *addrs);
+	    return KRB5_CC_NOMEM;
+	}
+	kret = krb5_krcc_parse_addr(context, id, (*addrs)[i], bc);
+	CHECK(kret);
+    }
+
+    return KRB5_OK;
+  errout:
+    if (*addrs)
+	krb5_free_addresses(context, *addrs);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_addr(krb5_context context, krb5_ccache id, krb5_address * addr,
+		     krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_ui_2 ui2;
+    krb5_int32 int32;
+
+    addr->magic = KV5M_ADDRESS;
+    addr->contents = 0;
+
+    kret = krb5_krcc_parse_ui_2(context, id, &ui2, bc);
+    CHECK(kret);
+    addr->addrtype = ui2;
+
+    kret = krb5_krcc_parse_int32(context, id, &int32, bc);
+    CHECK(kret);
+    if ((int32 & VALID_INT_BITS) != int32)	/* Overflow int??? */
+	return KRB5_CC_NOMEM;
+    addr->length = int32;
+    /*
+     * Length field is "unsigned int", which may be smaller
+     * than 32 bits.
+     */
+    if (addr->length != int32)
+	return KRB5_CC_NOMEM;	/* XXX */
+
+    if (addr->length == 0)
+	return KRB5_OK;
+
+    addr->contents = (krb5_octet *) malloc(addr->length);
+    if (addr->contents == NULL)
+	return KRB5_CC_NOMEM;
+
+    kret = krb5_krcc_parse(context, id, addr->contents, addr->length, bc);
+    CHECK(kret);
+
+    return KRB5_OK;
+  errout:
+    if (addr->contents)
+	krb5_xfree(addr->contents);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_authdata(krb5_context context, krb5_ccache id,
+			 krb5_authdata *** a, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_int32 length;
+    size_t  msize;
+    int     i;
+
+    *a = 0;
+
+    /* Read the number of components */
+    kret = krb5_krcc_parse_int32(context, id, &length, bc);
+    CHECK(kret);
+
+    if (length == 0)
+	return KRB5_OK;
+
+    /*
+     * Make *a able to hold length pointers to krb5_authdata structs
+     * Add one extra for a null-terminated list
+     */
+    msize = length;
+    msize += 1;
+    if (msize == 0 || msize - 1 != length || length < 0)
+	return KRB5_CC_NOMEM;
+    *a = ALLOC(msize, krb5_authdata *);
+    if (*a == NULL)
+	return KRB5_CC_NOMEM;
+
+    for (i = 0; i < length; i++) {
+	(*a)[i] = (krb5_authdata *) malloc(sizeof(krb5_authdata));
+	if ((*a)[i] == NULL) {
+	    krb5_free_authdata(context, *a);
+	    return KRB5_CC_NOMEM;
+	}
+	kret = krb5_krcc_parse_authdatum(context, id, (*a)[i], bc);
+	CHECK(kret);
+    }
+
+    return KRB5_OK;
+  errout:
+    if (*a)
+	krb5_free_authdata(context, *a);
+    return kret;
+}
+
+static  krb5_error_code
+krb5_krcc_parse_authdatum(krb5_context context, krb5_ccache id,
+			  krb5_authdata * a, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_int32 int32;
+    krb5_ui_2 ui2;
+
+    a->magic = KV5M_AUTHDATA;
+    a->contents = NULL;
+
+    kret = krb5_krcc_parse_ui_2(context, id, &ui2, bc);
+    CHECK(kret);
+    a->ad_type = (krb5_authdatatype) ui2;
+    kret = krb5_krcc_parse_int32(context, id, &int32, bc);
+    CHECK(kret);
+    if ((int32 & VALID_INT_BITS) != int32)	/* Overflow int??? */
+	return KRB5_CC_NOMEM;
+    a->length = int32;
+    /*
+     * Value could have gotten truncated if int is
+     * smaller than 32 bits.
+     */
+    if (a->length != int32)
+	return KRB5_CC_NOMEM;	/* XXX */
+
+    if (a->length == 0)
+	return KRB5_OK;
+
+    a->contents = (krb5_octet *) malloc(a->length);
+    if (a->contents == NULL)
+	return KRB5_CC_NOMEM;
+
+    kret = krb5_krcc_parse(context, id, a->contents, a->length, bc);
+    CHECK(kret);
+
+    return KRB5_OK;
+  errout:
+    if (a->contents)
+	krb5_xfree(a->contents);
+    return kret;
+
+}
+
+static  krb5_error_code
+krb5_krcc_parse_ui_2(krb5_context context, krb5_ccache id, krb5_ui_2 * i,
+		     krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    unsigned char buf[2];
+
+    kret = krb5_krcc_parse(context, id, buf, 2, bc);
+    if (kret)
+	return kret;
+    *i = (buf[0] << 8) + buf[1];
+    return 0;
+}
+
+/*
+ * Requires:
+ * locked mutex
+ *
+ * Effects:
+ * Copies len bytes from buf into the payload buffer (bc->bpp).
+ * Detects attempts to write past end of the payload buffer.
+ * Updates payload buffer pointer accordingly.
+ *
+ * Errors:
+ * system errors
+ */
+static  krb5_error_code
+krb5_krcc_unparse(krb5_context context, krb5_ccache id, krb5_pointer buf,
+		  unsigned int len, krb5_krcc_bc * bc)
+{
+    if (bc->bpp + len > bc->endp)
+	return KRB5_CC_WRITE;
+
+    memcpy(bc->bpp, buf, len);
+    bc->bpp += len;
+
+    return KRB5_OK;
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_principal(krb5_context context, krb5_ccache id,
+			    krb5_principal princ, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_int32 i, length, tmp, type;
+
+    type = krb5_princ_type(context, princ);
+    tmp = length = krb5_princ_size(context, princ);
+
+    kret = krb5_krcc_unparse_int32(context, id, type, bc);
+    CHECK_OUT(kret);
+
+    kret = krb5_krcc_unparse_int32(context, id, tmp, bc);
+    CHECK_OUT(kret);
+
+    kret = krb5_krcc_unparse_krb5data(context, id,
+				      krb5_princ_realm(context, princ), bc);
+    CHECK_OUT(kret);
+
+    for (i = 0; i < length; i++) {
+	kret = krb5_krcc_unparse_krb5data(context, id,
+					  krb5_princ_component(context, princ,
+							       i), bc);
+	CHECK_OUT(kret);
+    }
+
+    return KRB5_OK;
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_keyblock(krb5_context context, krb5_ccache id,
+			   krb5_keyblock * keyblock, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+
+    kret = krb5_krcc_unparse_ui_2(context, id, keyblock->enctype, bc);
+    CHECK_OUT(kret);
+    kret = krb5_krcc_unparse_ui_4(context, id, keyblock->length, bc);
+    CHECK_OUT(kret);
+    return krb5_krcc_unparse(context, id, (char *) keyblock->contents,
+			     keyblock->length, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_times(krb5_context context, krb5_ccache id,
+			krb5_ticket_times * t, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+
+    kret = krb5_krcc_unparse_int32(context, id, t->authtime, bc);
+    CHECK_OUT(kret);
+    kret = krb5_krcc_unparse_int32(context, id, t->starttime, bc);
+    CHECK_OUT(kret);
+    kret = krb5_krcc_unparse_int32(context, id, t->endtime, bc);
+    CHECK_OUT(kret);
+    kret = krb5_krcc_unparse_int32(context, id, t->renew_till, bc);
+    CHECK_OUT(kret);
+    return 0;
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_krb5data(krb5_context context, krb5_ccache id,
+			   krb5_data * data, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+
+    kret = krb5_krcc_unparse_ui_4(context, id, data->length, bc);
+    CHECK_OUT(kret);
+    return krb5_krcc_unparse(context, id, data->data, data->length, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_int32(krb5_context context, krb5_ccache id, krb5_int32 i,
+			krb5_krcc_bc * bc)
+{
+    unsigned char buf[4];
+
+    buf[3] = (unsigned char) (i & 0xFF);
+    i >>= 8;
+    buf[2] = (unsigned char) (i & 0xFF);
+    i >>= 8;
+    buf[1] = (unsigned char) (i & 0xFF);
+    i >>= 8;
+    buf[0] = (unsigned char) (i & 0xFF);
+    return krb5_krcc_unparse(context, id, buf, 4, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_octet(krb5_context context, krb5_ccache id, krb5_int32 i,
+			krb5_krcc_bc * bc)
+{
+    krb5_octet ibuf;
+
+    ibuf = (krb5_octet) i;
+    return krb5_krcc_unparse(context, id, (char *) &ibuf, 1, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_addrs(krb5_context context, krb5_ccache id,
+			krb5_address ** addrs, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_address **temp;
+    krb5_int32 i, length = 0;
+
+    /* Count the number of components */
+    if (addrs) {
+	temp = addrs;
+	while (*temp++)
+	    length += 1;
+    }
+
+    kret = krb5_krcc_unparse_int32(context, id, length, bc);
+    CHECK_OUT(kret);
+    for (i = 0; i < length; i++) {
+	kret = krb5_krcc_unparse_addr(context, id, addrs[i], bc);
+	CHECK_OUT(kret);
+    }
+
+    return KRB5_OK;
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_addr(krb5_context context, krb5_ccache id,
+		       krb5_address * addr, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+
+    kret = krb5_krcc_unparse_ui_2(context, id, addr->addrtype, bc);
+    CHECK_OUT(kret);
+    kret = krb5_krcc_unparse_ui_4(context, id, addr->length, bc);
+    CHECK_OUT(kret);
+    return krb5_krcc_unparse(context, id, (char *) addr->contents,
+			     addr->length, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_authdata(krb5_context context, krb5_ccache id,
+			   krb5_authdata ** a, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+    krb5_authdata **temp;
+    krb5_int32 i, length = 0;
+
+    if (a != NULL) {
+	for (temp = a; *temp; temp++)
+	    length++;
+    }
+
+    kret = krb5_krcc_unparse_int32(context, id, length, bc);
+    CHECK_OUT(kret);
+    for (i = 0; i < length; i++) {
+	kret = krb5_krcc_unparse_authdatum(context, id, a[i], bc);
+	CHECK_OUT(kret);
+    }
+    return KRB5_OK;
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_authdatum(krb5_context context, krb5_ccache id,
+			    krb5_authdata * a, krb5_krcc_bc * bc)
+{
+    krb5_error_code kret;
+
+    kret = krb5_krcc_unparse_ui_2(context, id, a->ad_type, bc);
+    CHECK_OUT(kret);
+    kret = krb5_krcc_unparse_ui_4(context, id, a->length, bc);
+    CHECK_OUT(kret);
+    return krb5_krcc_unparse(context, id, (krb5_pointer) a->contents,
+			     a->length, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_ui_4(krb5_context context, krb5_ccache id, krb5_ui_4 i,
+		       krb5_krcc_bc * bc)
+{
+    unsigned char buf[4];
+
+    buf[3] = (unsigned char) (i & 0xFF);
+    i >>= 8;
+    buf[2] = (unsigned char) (i & 0xFF);
+    i >>= 8;
+    buf[1] = (unsigned char) (i & 0xFF);
+    i >>= 8;
+    buf[0] = (unsigned char) (i & 0xFF);
+    return krb5_krcc_unparse(context, id, buf, 4, bc);
+}
+
+static  krb5_error_code
+krb5_krcc_unparse_ui_2(krb5_context context, krb5_ccache id, krb5_int32 i,
+		       krb5_krcc_bc * bc)
+{
+    unsigned char buf[2];
+
+    buf[1] = (unsigned char) (i & 0xFF);
+    i >>= 8;
+    buf[0] = (unsigned char) (i & 0xFF);
+    return krb5_krcc_unparse(context, id, buf, 2, bc);
+}
+
+/*
+ * ===============================================================
+ * INTERNAL functions to unparse a credential into a key payload
+ * (Borrowed heavily from krb5_fcc_{read|store}_ funtions.)
+ * ===============================================================
+ */
+
+/*
+ * Take a credential structure and unparse it (serialize)
+ * for storage into a keyring key entry.
+ * Caller is responsible for freeing returned buffer.
+ */
+static  krb5_error_code
+krb5_krcc_unparse_cred(krb5_context context, krb5_ccache id,
+		       krb5_creds * creds, char **datapp, unsigned int *lenptr)
+{
+    krb5_error_code kret;
+    char   *buf;
+    krb5_krcc_bc bc;
+
+    if (!creds || !datapp || !lenptr)
+	return EINVAL;
+
+    *datapp = NULL;
+    *lenptr = 0;
+
+    buf = malloc(GUESS_CRED_SIZE);
+    if (buf == NULL)
+	return KRB5_CC_NOMEM;
+
+    bc.bpp = buf;
+    bc.endp = buf + GUESS_CRED_SIZE;
+
+    kret = krb5_krcc_unparse_principal(context, id, creds->client, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_principal(context, id, creds->server, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_keyblock(context, id, &creds->keyblock, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_times(context, id, &creds->times, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_octet(context, id, (krb5_int32) creds->is_skey,
+				   &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_int32(context, id, creds->ticket_flags, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_addrs(context, id, creds->addresses, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_authdata(context, id, creds->authdata, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_krb5data(context, id, &creds->ticket, &bc);
+    CHECK_N_GO(kret, errout);
+
+    kret = krb5_krcc_unparse_krb5data(context, id, &creds->second_ticket, &bc);
+    CHECK_N_GO(kret, errout);
+
+    /* Success! */
+    *datapp = buf;
+    *lenptr = bc.bpp - buf;
+    kret = KRB5_OK;
+
+  errout:
+    return kret;
+}
+
+/*
+ * ccache implementation storing credentials in the Linux keyring facility
+ * The default is to put them at the session keyring level.
+ * If "KEYRING:process:" or "KEYRING:thread:" is specified, then they will
+ * be stored at the process or thread level respectively.
+ */
+const krb5_cc_ops krb5_krcc_ops = {
+    0,
+    "KEYRING",
+    krb5_krcc_get_name,
+    krb5_krcc_resolve,
+    krb5_krcc_generate_new,
+    krb5_krcc_initialize,
+    krb5_krcc_destroy,
+    krb5_krcc_close,
+    krb5_krcc_store,
+    krb5_krcc_retrieve,
+    krb5_krcc_get_principal,
+    krb5_krcc_start_seq_get,
+    krb5_krcc_next_cred,
+    krb5_krcc_end_seq_get,
+    krb5_krcc_remove_cred,
+    krb5_krcc_set_flags,
+    krb5_krcc_get_flags		/* added after 1.4 release */
+};
+
+#else /* !USE_KEYRING_CCACHE */
+
+/*
+ * Export this, but it shouldn't be used.
+ */
+const krb5_cc_ops krb5_krcc_ops = {
+    0,
+    "KEYRING",
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL			/* added after 1.4 release */
+};
+#endif	/* USE_KEYRING_CCACHE */
diff --git a/krb5-1-6/src/lib/krb5/ccache/cc_memory.c b/krb5-1-6/src/lib/krb5/ccache/cc_memory.c
new file mode 100644
index 000000000..124548ce6
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cc_memory.c
@@ -0,0 +1,781 @@
+/*
+ * lib/krb5/ccache/cc_memory.c
+ *
+ * Copyright 1990,1991,2000,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * implementation of memory-based credentials cache
+ */
+#include "k5-int.h"
+#include <errno.h>
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_close
+	(krb5_context, krb5_ccache id );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_destroy 
+	(krb5_context, krb5_ccache id );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_end_seq_get 
+	(krb5_context, krb5_ccache id , krb5_cc_cursor *cursor );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new 
+	(krb5_context, krb5_ccache *id );
+
+static const char * KRB5_CALLCONV krb5_mcc_get_name 
+	(krb5_context, krb5_ccache id );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_get_principal 
+	(krb5_context, krb5_ccache id , krb5_principal *princ );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_initialize 
+	(krb5_context, krb5_ccache id , krb5_principal princ );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_next_cred 
+	(krb5_context, 
+		   krb5_ccache id , 
+		   krb5_cc_cursor *cursor , 
+		   krb5_creds *creds );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_resolve 
+	(krb5_context, krb5_ccache *id , const char *residual );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_retrieve 
+	(krb5_context, 
+		   krb5_ccache id , 
+		   krb5_flags whichfields , 
+		   krb5_creds *mcreds , 
+		   krb5_creds *creds );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_start_seq_get 
+	(krb5_context, krb5_ccache id , krb5_cc_cursor *cursor );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_store 
+	(krb5_context, krb5_ccache id , krb5_creds *creds );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_set_flags 
+	(krb5_context, krb5_ccache id , krb5_flags flags );
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_new(
+    krb5_context,
+    krb5_cc_ptcursor *);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_next(
+    krb5_context,
+    krb5_cc_ptcursor,
+    krb5_ccache *);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_free(
+    krb5_context,
+    krb5_cc_ptcursor *);
+
+extern const krb5_cc_ops krb5_mcc_ops;
+extern krb5_error_code krb5_change_cache (void);
+
+#define KRB5_OK 0
+
+typedef struct _krb5_mcc_link {
+    struct _krb5_mcc_link *next;
+    krb5_creds *creds;
+} krb5_mcc_link, *krb5_mcc_cursor;
+
+typedef struct _krb5_mcc_data {
+    char *name;
+    k5_mutex_t lock;
+    krb5_principal prin;
+    krb5_mcc_cursor link;
+} krb5_mcc_data;
+
+typedef struct krb5_mcc_list_node {
+    struct krb5_mcc_list_node *next;
+    krb5_mcc_data *cache;
+} krb5_mcc_list_node;
+
+struct krb5_mcc_ptcursor_data {
+    struct krb5_mcc_list_node *cur;
+};
+
+k5_mutex_t krb5int_mcc_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+static krb5_mcc_list_node *mcc_head = 0;
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Creates/refreshes the file cred cache id.  If the cache exists, its
+ * contents are destroyed.
+ *
+ * Errors:
+ * system errors
+ * permission errors
+ */
+static void krb5_mcc_free (krb5_context context, krb5_ccache id);
+
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
+{
+    krb5_error_code ret; 
+
+    krb5_mcc_free(context, id);
+    ret = krb5_copy_principal(context, princ,
+			      &((krb5_mcc_data *)id->data)->prin);
+    if (ret == KRB5_OK)
+        krb5_change_cache();
+    return ret;
+}
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Closes the file cache, invalidates the id, and frees any resources
+ * associated with the cache.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_close(krb5_context context, krb5_ccache id)
+{
+     krb5_xfree(id);
+     return KRB5_OK;
+}
+
+void
+krb5_mcc_free(krb5_context context, krb5_ccache id)
+{
+    krb5_mcc_cursor curr,next;
+    krb5_mcc_data *d;
+
+    d = (krb5_mcc_data *) id->data;
+    for (curr = d->link; curr;) {
+	krb5_free_creds(context, curr->creds);
+	next = curr->next;
+	krb5_xfree(curr);
+	curr = next;
+    }
+    d->link = NULL;
+    krb5_free_principal(context, d->prin);
+}
+
+/*
+ * Effects:
+ * Destroys the contents of id.
+ *
+ * Errors:
+ * none
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_destroy(krb5_context context, krb5_ccache id)
+{
+    krb5_mcc_list_node **curr, *node;
+    krb5_mcc_data *d;
+    krb5_error_code err;
+
+    err = k5_mutex_lock(&krb5int_mcc_mutex);
+    if (err)
+	return err;
+
+    d = (krb5_mcc_data *)id->data;
+    for (curr = &mcc_head; *curr; curr = &(*curr)->next) {
+	if ((*curr)->cache == d) {
+	    node = *curr;
+	    *curr = node->next;
+	    free(node);
+	    break;
+	}
+    }
+    k5_mutex_unlock(&krb5int_mcc_mutex);
+
+    krb5_mcc_free(context, id);
+    krb5_xfree(d->name);
+    k5_mutex_destroy(&d->lock);
+    krb5_xfree(d); 
+    krb5_xfree(id);
+
+    krb5_change_cache ();
+    return KRB5_OK;
+}
+
+/*
+ * Requires:
+ * residual is a legal path name, and a null-terminated string
+ *
+ * Modifies:
+ * id
+ * 
+ * Effects:
+ * creates a file-based cred cache that will reside in the file
+ * residual.  The cache is not opened, but the filename is reserved.
+ * 
+ * Returns:
+ * A filled in krb5_ccache structure "id".
+ *
+ * Errors:
+ * KRB5_CC_NOMEM - there was insufficient memory to allocate the
+ *              krb5_ccache.  id is undefined.
+ * permission errors
+ */
+static krb5_error_code new_mcc_data (const char *, krb5_mcc_data **);
+
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
+{
+    krb5_ccache lid;
+    krb5_mcc_list_node *ptr;
+    krb5_error_code err;
+    krb5_mcc_data *d;
+
+    lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+    if (lid == NULL)
+	return KRB5_CC_NOMEM;
+
+    lid->ops = &krb5_mcc_ops;
+
+    err = k5_mutex_lock(&krb5int_mcc_mutex);
+    if (err)
+	return err;
+    for (ptr = mcc_head; ptr; ptr=ptr->next)
+	if (!strcmp(ptr->cache->name, residual))
+	    break;
+    if (ptr)
+	d = ptr->cache;
+    else {
+	err = new_mcc_data(residual, &d);
+	if (err) {
+	    k5_mutex_unlock(&krb5int_mcc_mutex);
+	    krb5_xfree(lid);
+	    return err;
+	}
+    }
+    k5_mutex_unlock(&krb5int_mcc_mutex);
+    lid->data = d;
+    *id = lid; 
+    return KRB5_OK;
+}
+
+/*
+ * Effects:
+ * Prepares for a sequential search of the credentials cache.
+ * Returns a krb5_cc_cursor to be used with krb5_mcc_next_cred and
+ * krb5_mcc_end_seq_get.
+ *
+ * If the cache is modified between the time of this call and the time
+ * of the final krb5_mcc_end_seq_get, the results are undefined.
+ *
+ * Errors:
+ * KRB5_CC_NOMEM
+ * system errors
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id,
+		       krb5_cc_cursor *cursor)
+{
+     krb5_mcc_cursor mcursor;
+     krb5_error_code err;
+     krb5_mcc_data *d;
+
+     d = id->data;
+     err = k5_mutex_lock(&d->lock);
+     if (err)
+	 return err;
+     mcursor = d->link;
+     k5_mutex_unlock(&d->lock);
+     *cursor = (krb5_cc_cursor) mcursor;
+     return KRB5_OK;
+}
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_mcc_start_seq_get.
+ *
+ * Modifes:
+ * cursor, creds
+ * 
+ * Effects:
+ * Fills in creds with the "next" credentals structure from the cache
+ * id.  The actual order the creds are returned in is arbitrary.
+ * Space is allocated for the variable length fields in the
+ * credentials structure, so the object returned must be passed to
+ * krb5_destroy_credential.
+ *
+ * The cursor is updated for the next call to krb5_mcc_next_cred.
+ *
+ * Errors:
+ * system errors
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_next_cred(krb5_context context, krb5_ccache id,
+		   krb5_cc_cursor *cursor, krb5_creds *creds)
+{
+     krb5_mcc_cursor mcursor;
+     krb5_error_code retval;
+     krb5_data *scratch;
+
+     /* Once the node in the linked list is created, it's never
+	modified, so we don't need to worry about locking here.  (Note
+	that we don't support _remove_cred.)  */
+     mcursor = (krb5_mcc_cursor) *cursor;
+     if (mcursor == NULL)
+	return KRB5_CC_END;
+     memset(creds, 0, sizeof(krb5_creds));     
+     if (mcursor->creds) {
+	*creds = *mcursor->creds;
+	retval = krb5_copy_principal(context, mcursor->creds->client, &creds->client);
+	if (retval)
+		return retval;
+	retval = krb5_copy_principal(context, mcursor->creds->server,
+		&creds->server);
+	if (retval)
+		goto cleanclient;
+	retval = krb5_copy_keyblock_contents(context, &mcursor->creds->keyblock,
+		&creds->keyblock);
+	if (retval)
+		goto cleanserver;
+	retval = krb5_copy_addresses(context, mcursor->creds->addresses,
+		&creds->addresses);
+	if (retval)
+		goto cleanblock;
+	retval = krb5_copy_data(context, &mcursor->creds->ticket, &scratch);
+	if (retval)
+		goto cleanaddrs;
+	creds->ticket = *scratch;
+	krb5_xfree(scratch);
+	retval = krb5_copy_data(context, &mcursor->creds->second_ticket, &scratch);
+	if (retval)
+		goto cleanticket;
+	creds->second_ticket = *scratch;
+	krb5_xfree(scratch);
+	retval = krb5_copy_authdata(context, mcursor->creds->authdata,
+		&creds->authdata);
+	if (retval)
+		goto clearticket;
+     }
+     *cursor = (krb5_cc_cursor)mcursor->next;
+     return KRB5_OK;
+
+clearticket:
+	memset(creds->ticket.data,0, (unsigned) creds->ticket.length);
+cleanticket:
+	krb5_xfree(creds->ticket.data);
+cleanaddrs:
+	krb5_free_addresses(context, creds->addresses);
+cleanblock:
+	krb5_xfree(creds->keyblock.contents);
+cleanserver:
+	krb5_free_principal(context, creds->server);
+cleanclient:
+	krb5_free_principal(context, creds->client);
+	return retval;
+}
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_mcc_start_seq_get.
+ *
+ * Modifies:
+ * id, cursor
+ *
+ * Effects:
+ * Finishes sequential processing of the file credentials ccache id,
+ * and invalidates the cursor (it must never be used after this call).
+ */
+/* ARGSUSED */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
+{
+     *cursor = 0L;
+     return KRB5_OK;
+}
+
+/* Utility routine: Creates the back-end data for a memory cache, and
+   threads it into the global linked list.
+
+   Call with the global list lock held.  */
+static krb5_error_code
+new_mcc_data (const char *name, krb5_mcc_data **dataptr)
+{
+    krb5_error_code err;
+    krb5_mcc_data *d;
+    krb5_mcc_list_node *n;
+
+    d = malloc(sizeof(krb5_mcc_data));
+    if (d == NULL)
+	return KRB5_CC_NOMEM;
+
+    err = k5_mutex_init(&d->lock);
+    if (err) {
+	krb5_xfree(d);
+	return err;
+    }
+
+    d->name = malloc(strlen(name) + 1);
+    if (d->name == NULL) {
+	k5_mutex_destroy(&d->lock);
+	krb5_xfree(d);
+	return KRB5_CC_NOMEM;
+    }
+    d->link = NULL;
+    d->prin = NULL;
+
+    /* Set up the filename */
+    strcpy(d->name, name);
+
+    n = malloc(sizeof(krb5_mcc_list_node));
+    if (n == NULL) {
+	free(d->name);
+	k5_mutex_destroy(&d->lock);
+	free(d);
+	return KRB5_CC_NOMEM;
+    }
+
+    n->cache = d;
+    n->next = mcc_head;
+    mcc_head = n;
+
+    *dataptr = d;
+    return 0;
+}
+
+static krb5_error_code random_string (krb5_context, char *, unsigned int);
+ 
+/*
+ * Effects:
+ * Creates a new file cred cache whose name is guaranteed to be
+ * unique.  The name begins with the string TKT_ROOT (from mcc.h).
+ * The cache is not opened, but the new filename is reserved.
+ *  
+ * Returns:
+ * The filled in krb5_ccache id.
+ *
+ * Errors:
+ * KRB5_CC_NOMEM - there was insufficient memory to allocate the
+ *              krb5_ccache.  id is undefined.
+ * system errors (from open)
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
+{
+    krb5_ccache lid;
+    char uniquename[8];
+    krb5_error_code err;
+    krb5_mcc_data *d;
+
+    /* Allocate memory */
+    lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+    if (lid == NULL)
+	return KRB5_CC_NOMEM;
+
+    lid->ops = &krb5_mcc_ops;
+    
+    err = k5_mutex_lock(&krb5int_mcc_mutex);
+    if (err) {
+	free(lid);
+	return err;
+    }
+    
+    /* Check for uniqueness with mutex locked to avoid race conditions */
+    while (1) {
+        krb5_mcc_list_node *ptr;
+
+        random_string (context, uniquename, sizeof (uniquename));
+        
+	for (ptr = mcc_head; ptr; ptr=ptr->next) {
+            if (!strcmp(ptr->cache->name, uniquename)) {
+		break;  /* got a match, loop again */
+            }
+	}
+        if (!ptr) break; /* got to the end without finding a match */
+    }
+    
+    err = new_mcc_data(uniquename, &d);
+
+    k5_mutex_unlock(&krb5int_mcc_mutex);
+    if (err) {
+	krb5_xfree(lid);
+	return err;
+    }
+    lid->data = d;
+    *id = lid;
+    krb5_change_cache ();
+    return KRB5_OK;
+}
+
+/* Utility routine: Creates a random memory ccache name. 
+ * This algorithm was selected because it creates readable 
+ * random ccache names in a fixed size buffer.  */
+
+static krb5_error_code
+random_string (krb5_context context, char *string, unsigned int length)
+{
+    static const unsigned char charlist[] =
+        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    krb5_error_code err = 0;
+    unsigned char *bytes = NULL;
+    unsigned int bytecount = length - 1;
+    
+    if (!err) {
+        bytes = malloc (bytecount);
+        if (bytes == NULL) { err = ENOMEM; }
+    }
+    
+    if (!err) {
+        krb5_data data;
+        data.length = bytecount;
+        data.data = (char *) bytes;
+        err = krb5_c_random_make_octets (context, &data);
+    }
+    
+    if (!err) {
+        unsigned int i;
+        for (i = 0; i < bytecount; i++) {
+            string [i] = charlist[bytes[i] % (sizeof (charlist) - 1)];
+        }
+        string[length - 1] = '\0';
+    }
+    
+    if (bytes != NULL) { free (bytes); }
+    
+    return err;
+}
+
+/*
+ * Requires:
+ * id is a file credential cache
+ * 
+ * Returns:
+ * The name of the file cred cache id.
+ */
+const char * KRB5_CALLCONV
+krb5_mcc_get_name (krb5_context context, krb5_ccache id)
+{
+     return (char *) ((krb5_mcc_data *) id->data)->name;
+}
+
+/*
+ * Modifies:
+ * id, princ
+ *
+ * Effects:
+ * Retrieves the primary principal from id, as set with
+ * krb5_mcc_initialize.  The principal is returned is allocated
+ * storage that must be freed by the caller via krb5_free_principal.
+ *
+ * Errors:
+ * system errors
+ * KRB5_CC_NOMEM
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ)
+{
+     krb5_mcc_data *ptr = (krb5_mcc_data *)id->data;
+     if (!ptr->prin) {
+        *princ = 0L;
+        return KRB5_FCC_NOFILE;
+     }
+     return krb5_copy_principal(context, ptr->prin, princ);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields,
+		  krb5_creds *mcreds, krb5_creds *creds)
+{
+    return krb5_cc_retrieve_cred_default (context, id, whichfields,
+					  mcreds, creds);
+}
+
+/* 
+ * Non-functional stub implementation for krb5_mcc_remove
+ * 
+ * Errors:
+ *    KRB5_CC_NOSUPP - not implemented
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags,
+                     krb5_creds *creds)
+{
+    return KRB5_CC_NOSUPP;
+}
+
+
+/*
+ * Requires:
+ * id is a cred cache returned by krb5_mcc_resolve or
+ * krb5_mcc_generate_new, but has not been opened by krb5_mcc_initialize.
+ *
+ * Modifies:
+ * id
+ * 
+ * Effects:
+ * Sets the operational flags of id to flags.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
+{
+    return KRB5_OK;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags)
+{
+    *flags = 0;
+    return KRB5_OK;
+}
+
+/* store: Save away creds in the ccache.  */
+krb5_error_code KRB5_CALLCONV
+krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds)
+{
+    krb5_error_code err;
+    krb5_mcc_link *new_node;
+    krb5_mcc_data *mptr = (krb5_mcc_data *)id->data;
+
+    new_node = malloc(sizeof(krb5_mcc_link));
+    if (new_node == NULL)
+	return errno;
+    err = krb5_copy_creds(ctx, creds, &new_node->creds);
+    if (err) {
+	free(new_node);
+	return err;
+    }
+    err = k5_mutex_lock(&mptr->lock);
+    if (err)
+	return err;
+    new_node->next = mptr->link;
+    mptr->link = new_node;
+    k5_mutex_unlock(&mptr->lock);
+    return 0;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_ptcursor_new(
+    krb5_context context,
+    krb5_cc_ptcursor *cursor)
+{
+    krb5_error_code ret = 0;
+    krb5_cc_ptcursor n = NULL;
+    struct krb5_mcc_ptcursor_data *cdata = NULL;
+
+    *cursor = NULL;
+
+    n = malloc(sizeof(*n));
+    if (n == NULL)
+	return ENOMEM;
+    n->ops = &krb5_mcc_ops;
+    cdata = malloc(sizeof(struct krb5_mcc_ptcursor_data));
+    if (cdata == NULL) {
+	ret = ENOMEM;
+	goto errout;
+    }
+    n->data = cdata;
+    ret = k5_mutex_lock(&krb5int_mcc_mutex);
+    if (ret)
+	goto errout;
+    cdata->cur = mcc_head;
+    ret = k5_mutex_unlock(&krb5int_mcc_mutex);
+    if (ret)
+	goto errout;
+
+errout:
+    if (ret) {
+	krb5_mcc_ptcursor_free(context, &n);
+    }
+    *cursor = n;
+    return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_ptcursor_next(
+    krb5_context context,
+    krb5_cc_ptcursor cursor,
+    krb5_ccache *ccache)
+{
+    krb5_error_code ret = 0;
+    struct krb5_mcc_ptcursor_data *cdata = NULL;
+
+    *ccache = NULL;
+    cdata = cursor->data;
+    if (cdata->cur == NULL)
+	return 0;
+
+    *ccache = malloc(sizeof(**ccache));
+    if (*ccache == NULL)
+	return ENOMEM;
+
+    (*ccache)->ops = &krb5_mcc_ops;
+    (*ccache)->data = cdata->cur->cache;
+    ret = k5_mutex_lock(&krb5int_mcc_mutex);
+    if (ret)
+	goto errout;
+    cdata->cur = cdata->cur->next;
+    ret = k5_mutex_unlock(&krb5int_mcc_mutex);
+    if (ret)
+	goto errout;
+errout:
+    if (ret && *ccache != NULL) {
+	free(*ccache);
+	*ccache = NULL;
+    }
+    return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_ptcursor_free(
+    krb5_context context,
+    krb5_cc_ptcursor *cursor)
+{
+    if (*cursor == NULL)
+	return 0;
+    if ((*cursor)->data != NULL)
+	free((*cursor)->data);
+    free(*cursor);
+    *cursor = NULL;
+    return 0;
+}
+
+const krb5_cc_ops krb5_mcc_ops = {
+     0,
+     "MEMORY",
+     krb5_mcc_get_name,
+     krb5_mcc_resolve,
+     krb5_mcc_generate_new,
+     krb5_mcc_initialize,
+     krb5_mcc_destroy,
+     krb5_mcc_close,
+     krb5_mcc_store,
+     krb5_mcc_retrieve,
+     krb5_mcc_get_principal,
+     krb5_mcc_start_seq_get,
+     krb5_mcc_next_cred,
+     krb5_mcc_end_seq_get,
+     krb5_mcc_remove_cred,
+     krb5_mcc_set_flags,
+     krb5_mcc_get_flags,
+     krb5_mcc_ptcursor_new,
+     krb5_mcc_ptcursor_next,
+     krb5_mcc_ptcursor_free,
+     NULL,
+     NULL,
+     NULL,
+};
diff --git a/krb5-1-6/src/lib/krb5/ccache/cc_mslsa.c b/krb5-1-6/src/lib/krb5/ccache/cc_mslsa.c
new file mode 100644
index 000000000..80c5b4832
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cc_mslsa.c
@@ -0,0 +1,2762 @@
+/*
+ * lib/krb5/ccache/cc_mslsa.c
+ *
+ * Copyright 2007 Secure Endpoints Inc.
+ *
+ * Copyright 2003,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Copyright 2000 by Carnegie Mellon University
+ *
+ * All Rights Reserved
+ * 
+ * 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 Carnegie Mellon
+ * University not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.
+ * 
+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
+ * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Implementation of microsoft windows lsa credentials cache
+ */
+
+#ifdef _WIN32
+#define UNICODE
+#define _UNICODE
+
+#include "k5-int.h"
+#include "com_err.h"
+#include "cc-int.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <conio.h>
+#include <time.h>
+
+#define SECURITY_WIN32
+#include <security.h>
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x0600
+#include <ntsecapi.h>
+#include <ntstatus.h>
+
+
+/* The following two features can only be built using the version of the
+ * Platform SDK for Microsoft Windows Vista.  If AES support is defined
+ * in NTSecAPI.h then we know that we have the required data structures.
+ *
+ * To build with the Windows XP SP2 SDK, the NTSecAPI.h from the Vista
+ * SDK should be used in place of the XP SP2 SDK version.
+ */
+#ifdef TRUST_ATTRIBUTE_TRUST_USES_AES_KEYS
+#define KERB_SUBMIT_TICKET 1
+#define HAVE_CACHE_INFO_EX2 1
+#endif
+
+#define MAX_MSG_SIZE 256
+#define MAX_MSPRINC_SIZE 1024
+
+/* THREAD SAFETY 
+ * The functions is_windows_2000(), is_windows_xp(), 
+ * does_retrieve_ticket_cache_ticket() and does_query_ticket_cache_ex2() 
+ * contain static variables to cache the responses of the tests being 
+ * performed.  There is no harm in the test being performed more than 
+ * once since the result will always be the same.
+ */
+
+static BOOL 
+is_windows_2000 (void)
+{
+   static BOOL fChecked = FALSE;
+   static BOOL fIsWin2K = FALSE;
+
+   if (!fChecked)
+   {
+       OSVERSIONINFO Version;
+
+       memset (&Version, 0x00, sizeof(Version));
+       Version.dwOSVersionInfoSize = sizeof(Version);
+
+       if (GetVersionEx (&Version))
+       {
+           if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+                Version.dwMajorVersion >= 5)
+               fIsWin2K = TRUE;
+       }
+       fChecked = TRUE;
+   }
+
+   return fIsWin2K;
+}
+
+static BOOL 
+is_windows_xp (void)
+{
+   static BOOL fChecked = FALSE;
+   static BOOL fIsWinXP = FALSE;
+
+   if (!fChecked)
+   {
+       OSVERSIONINFO Version;
+
+       memset (&Version, 0x00, sizeof(Version));
+       Version.dwOSVersionInfoSize = sizeof(Version);
+
+       if (GetVersionEx (&Version))
+       {
+           if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+                (Version.dwMajorVersion > 5 ||
+                 Version.dwMajorVersion == 5 && Version.dwMinorVersion >= 1) )
+               fIsWinXP = TRUE;
+       }
+       fChecked = TRUE;
+   }
+
+   return fIsWinXP;
+}
+
+static BOOL
+is_windows_vista (void)
+{
+    static BOOL fChecked = FALSE;
+    static BOOL fIsVista = FALSE;
+
+    if (!fChecked)
+    {
+	OSVERSIONINFO Version;
+
+	memset (&Version, 0x00, sizeof(Version));
+	Version.dwOSVersionInfoSize = sizeof(Version);
+
+	if (GetVersionEx (&Version))
+	{
+	    if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT && Version.dwMajorVersion >= 6)
+		fIsVista = TRUE;
+	}
+	fChecked = TRUE;
+    }
+
+    return fIsVista;
+}
+
+static BOOL
+is_process_uac_limited (void)
+{
+    static BOOL fChecked = FALSE;
+    static BOOL fIsUAC = FALSE;
+
+    if (!fChecked)
+    {
+	NTSTATUS Status = 0;
+	HANDLE  TokenHandle;
+	DWORD   ElevationLevel;
+	DWORD   ReqLen;
+	BOOL    Success;
+
+	if (is_windows_vista()) {
+	    Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+	    if ( Success ) {
+		Success = GetTokenInformation( TokenHandle, 
+					       TokenOrigin+1 /* ElevationLevel */,
+					       &ElevationLevel, sizeof(DWORD), &ReqLen );
+		CloseHandle( TokenHandle );
+		if ( Success && ElevationLevel == 3 /* Limited */ )
+		    fIsUAC = TRUE;
+	    }
+	}
+	fChecked = TRUE;
+    }
+    return fIsUAC;
+
+}
+
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+static BOOL
+is_broken_wow64(void)
+{
+    static BOOL fChecked = FALSE;
+    static BOOL fIsBrokenWow64 = FALSE;
+
+    if (!fChecked)
+    {
+	BOOL isWow64 = FALSE;
+	OSVERSIONINFO Version;
+	HANDLE h1 = NULL;
+	LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
+		
+	h1 = GetModuleHandle(L"kernel32.dll");
+	fnIsWow64Process = 
+	    (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
+
+	/* If we don't find the fnIsWow64Process function then we 
+	 * are not running in a broken Wow64 
+	 */
+	if (fnIsWow64Process) {
+	    memset (&Version, 0x00, sizeof(Version));
+	    Version.dwOSVersionInfoSize = sizeof(Version);
+
+	    if (fnIsWow64Process(GetCurrentProcess(), &isWow64) && 
+		GetVersionEx (&Version)) {
+		if (isWow64 && 
+		    Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+		    Version.dwMajorVersion < 6)
+		    fIsBrokenWow64 = TRUE;
+	    } 
+	}
+	fChecked = TRUE;
+    }
+
+    return fIsBrokenWow64;
+}
+
+/* This flag is only supported by versions of Windows which have obtained
+ * a code change from Microsoft.   When the code change is installed,
+ * setting this flag will cause all retrieved credentials to be stored 
+ * in the LSA cache.
+ */
+#ifndef KERB_RETRIEVE_TICKET_CACHE_TICKET
+#define KERB_RETRIEVE_TICKET_CACHE_TICKET  0x20
+#endif
+
+static VOID
+ShowWinError(LPSTR szAPI, DWORD dwError)
+{
+
+    // TODO - Write errors to event log so that scripts that don't
+    // check for errors will still get something in the event log
+
+    // This code is completely unsafe for use on non-English systems
+    // Any call to this function will result in the FormatMessage
+    // call failing and the program terminating.  This might have
+    // been acceptable when this code was part of ms2mit.exe as
+    // a standalone executable but it is not appropriate for a library
+
+#ifdef COMMENT
+    WCHAR szMsgBuf[MAX_MSG_SIZE];
+    DWORD dwRes;
+
+    printf("Error calling function %s: %lu\n", szAPI, dwError);
+
+    dwRes = FormatMessage (
+        FORMAT_MESSAGE_FROM_SYSTEM,
+        NULL,
+        dwError,
+        MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
+        szMsgBuf,
+        MAX_MSG_SIZE,
+        NULL);
+    if (0 == dwRes) {
+        printf("FormatMessage failed with %d\n", GetLastError());
+        ExitProcess(EXIT_FAILURE);
+    }
+
+    printf("%S",szMsgBuf);
+#endif /* COMMENT */
+}
+
+static VOID
+ShowLsaError(LPSTR szAPI, NTSTATUS Status)
+{
+    //
+    // Convert the NTSTATUS to Winerror. Then call ShowWinError().
+    //
+    ShowWinError(szAPI, LsaNtStatusToWinError(Status));
+}
+
+static BOOL
+WINAPI
+UnicodeToANSI(LPTSTR lpInputString, LPSTR lpszOutputString, int nOutStringLen)
+{
+    CPINFO CodePageInfo;
+
+    GetCPInfo(CP_ACP, &CodePageInfo);
+
+    if (CodePageInfo.MaxCharSize > 1) {
+        // Only supporting non-Unicode strings
+        int reqLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) lpInputString, -1,
+                                         NULL, 0, NULL, NULL);
+        if ( reqLen > nOutStringLen) 
+        {
+            return FALSE;
+        } else {
+            if (WideCharToMultiByte(CP_ACP, 
+				    /* WC_NO_BEST_FIT_CHARS | */ WC_COMPOSITECHECK, 
+				    (LPCWSTR) lpInputString, -1,
+				    lpszOutputString, 
+				    nOutStringLen, NULL, NULL) == 0)
+		return FALSE;
+        }
+    } 
+    else
+    {
+        // Looks like unicode, better translate it
+        if (WideCharToMultiByte(CP_ACP, 
+				/* WC_NO_BEST_FIT_CHARS | */ WC_COMPOSITECHECK, 
+				(LPCWSTR) lpInputString, -1,
+				lpszOutputString, 
+				nOutStringLen, NULL, NULL) == 0)
+	    return FALSE;
+    }
+
+    return TRUE;
+}  // UnicodeToANSI
+
+static VOID
+WINAPI
+ANSIToUnicode(LPSTR lpInputString, LPTSTR lpszOutputString, int nOutStringLen)
+{
+
+    CPINFO CodePageInfo;
+
+    lstrcpy(lpszOutputString, (LPTSTR) lpInputString);
+
+    GetCPInfo(CP_ACP, &CodePageInfo);
+
+    if (CodePageInfo.MaxCharSize > 1 || ((LPBYTE) lpInputString)[1] != '\0')
+    {
+        // Looks like ANSI or MultiByte, better translate it
+        MultiByteToWideChar(CP_ACP, 0, (LPCSTR) lpInputString, -1,
+                            (LPWSTR) lpszOutputString, nOutStringLen);
+    }
+    else
+        lstrcpy(lpszOutputString, (LPTSTR) lpInputString);
+}  // ANSIToUnicode
+
+
+static void
+MITPrincToMSPrinc(krb5_context context, krb5_principal principal, UNICODE_STRING * msprinc)
+{
+    char *aname = NULL;
+
+    if (!krb5_unparse_name(context, principal, &aname)) {
+        msprinc->Length = strlen(aname) * sizeof(WCHAR);
+        if ( msprinc->Length <= msprinc->MaximumLength )
+            ANSIToUnicode(aname, msprinc->Buffer, msprinc->MaximumLength);
+        else 
+            msprinc->Length = 0;
+        krb5_free_unparsed_name(context,aname);
+    }
+}
+
+static BOOL
+UnicodeStringToMITPrinc(UNICODE_STRING *service, WCHAR *realm, krb5_context context, 
+                        krb5_principal *principal)
+{
+    WCHAR princbuf[512];
+    char aname[512];
+
+    princbuf[0]=0;
+    wcsncpy(princbuf, service->Buffer, service->Length/sizeof(WCHAR));
+    princbuf[service->Length/sizeof(WCHAR)]=0;
+    wcscat(princbuf, L"@");
+    wcscat(princbuf, realm);
+    if (UnicodeToANSI(princbuf, aname, sizeof(aname))) {
+        if (krb5_parse_name(context, aname, principal) == 0)
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+
+static BOOL
+KerbExternalNameToMITPrinc(KERB_EXTERNAL_NAME *msprinc, WCHAR *realm, krb5_context context, 
+                           krb5_principal *principal)
+{
+    WCHAR princbuf[512],tmpbuf[128];
+    char aname[512];
+    USHORT i;
+    princbuf[0]=0;
+    for (i=0;i<msprinc->NameCount;i++) {
+        wcsncpy(tmpbuf, msprinc->Names[i].Buffer,
+                msprinc->Names[i].Length/sizeof(WCHAR));
+        tmpbuf[msprinc->Names[i].Length/sizeof(WCHAR)]=0;
+        if (princbuf[0])
+            wcscat(princbuf, L"/");
+        wcscat(princbuf, tmpbuf);
+    }
+    wcscat(princbuf, L"@");
+    wcscat(princbuf, realm);
+    if (UnicodeToANSI(princbuf, aname, sizeof(aname))) {
+        if (krb5_parse_name(context, aname, principal) == 0)
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+static time_t
+FileTimeToUnixTime(LARGE_INTEGER *ltime)
+{
+    FILETIME filetime, localfiletime;
+    SYSTEMTIME systime;
+    struct tm utime;
+    filetime.dwLowDateTime=ltime->LowPart;
+    filetime.dwHighDateTime=ltime->HighPart;
+    FileTimeToLocalFileTime(&filetime, &localfiletime);
+    FileTimeToSystemTime(&localfiletime, &systime);
+    utime.tm_sec=systime.wSecond;
+    utime.tm_min=systime.wMinute;
+    utime.tm_hour=systime.wHour;
+    utime.tm_mday=systime.wDay;
+    utime.tm_mon=systime.wMonth-1;
+    utime.tm_year=systime.wYear-1900;
+    utime.tm_isdst=-1;
+    return(mktime(&utime));
+}
+
+static void
+MSSessionKeyToMITKeyblock(KERB_CRYPTO_KEY *mskey, krb5_context context, krb5_keyblock *keyblock)
+{
+    krb5_keyblock tmpblock;
+    tmpblock.magic=KV5M_KEYBLOCK;
+    tmpblock.enctype=mskey->KeyType;
+    tmpblock.length=mskey->Length;
+    tmpblock.contents=mskey->Value;
+    krb5_copy_keyblock_contents(context, &tmpblock, keyblock);
+}
+
+static BOOL
+IsMSSessionKeyNull(KERB_CRYPTO_KEY *mskey)
+{
+    DWORD i;
+    
+    if (is_process_uac_limited())
+	return TRUE;
+
+    if (mskey->KeyType == KERB_ETYPE_NULL)
+	return TRUE;
+
+    for ( i=0; i<mskey->Length; i++ ) {
+	if (mskey->Value[i])
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+MSFlagsToMITFlags(ULONG msflags, ULONG *mitflags)
+{
+    *mitflags=msflags;
+}
+
+static BOOL
+MSTicketToMITTicket(KERB_EXTERNAL_TICKET *msticket, krb5_context context, krb5_data *ticket)
+{
+    krb5_data tmpdata, *newdata = 0;
+    krb5_error_code rc;
+
+    tmpdata.magic=KV5M_DATA;
+    tmpdata.length=msticket->EncodedTicketSize;
+    tmpdata.data=msticket->EncodedTicket;
+
+    // this is ugly and will break krb5_free_data() 
+    // now that this is being done within the library it won't break krb5_free_data()
+    rc = krb5_copy_data(context, &tmpdata, &newdata);
+    if (rc)
+        return FALSE;
+    
+    memcpy(ticket, newdata, sizeof(krb5_data));
+    krb5_xfree(newdata);
+    return TRUE;
+}
+
+/*
+ * PreserveInitialTicketIdentity()
+ *
+ * This will find the "PreserveInitialTicketIdentity" key in the registry.  
+ * Returns 1 to preserve and 0 to not.
+ */
+
+static DWORD
+PreserveInitialTicketIdentity(void)
+{
+    HKEY hKey;
+    DWORD size = sizeof(DWORD);
+    DWORD type = REG_DWORD;
+    const char *key_path = "Software\\MIT\\Kerberos5";
+    const char *value_name = "PreserveInitialTicketIdentity";
+    DWORD retval = 1;     /* default to Preserve */
+
+    if (RegOpenKeyExA(HKEY_CURRENT_USER, key_path, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
+        goto syskey;
+    if (RegQueryValueExA(hKey, value_name, 0, &type, (LPBYTE)&retval, &size) != ERROR_SUCCESS)
+    {
+        RegCloseKey(hKey);
+        goto syskey;
+    }
+    RegCloseKey(hKey);
+    goto done;
+
+  syskey:
+    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_path, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
+        goto done;
+    if (RegQueryValueExA(hKey, value_name, 0, &type, (LPBYTE)&retval, &size) != ERROR_SUCCESS)
+    {
+        RegCloseKey(hKey);
+        goto done;
+    }
+    RegCloseKey(hKey);
+
+  done:
+    return retval;
+}
+
+
+static BOOL
+MSCredToMITCred(KERB_EXTERNAL_TICKET *msticket, UNICODE_STRING ClientRealm, 
+                krb5_context context, krb5_creds *creds)
+{
+    WCHAR wrealm[128];
+    ZeroMemory(creds, sizeof(krb5_creds));
+    creds->magic=KV5M_CREDS;
+
+    // construct Client Principal
+    wcsncpy(wrealm, ClientRealm.Buffer, ClientRealm.Length/sizeof(WCHAR));
+    wrealm[ClientRealm.Length/sizeof(WCHAR)]=0;
+    if (!KerbExternalNameToMITPrinc(msticket->ClientName, wrealm, context, &creds->client))
+        return FALSE;
+
+    // construct Service Principal
+    wcsncpy(wrealm, msticket->DomainName.Buffer,
+            msticket->DomainName.Length/sizeof(WCHAR));
+    wrealm[msticket->DomainName.Length/sizeof(WCHAR)]=0;
+    if (!KerbExternalNameToMITPrinc(msticket->ServiceName, wrealm, context, &creds->server))
+        return FALSE;
+    MSSessionKeyToMITKeyblock(&msticket->SessionKey, context, 
+                              &creds->keyblock);
+    MSFlagsToMITFlags(msticket->TicketFlags, &creds->ticket_flags);
+    creds->times.starttime=FileTimeToUnixTime(&msticket->StartTime);
+    creds->times.endtime=FileTimeToUnixTime(&msticket->EndTime);
+    creds->times.renew_till=FileTimeToUnixTime(&msticket->RenewUntil);
+
+    creds->addresses = NULL;
+
+    return MSTicketToMITTicket(msticket, context, &creds->ticket);
+}
+
+#ifdef HAVE_CACHE_INFO_EX2
+/* CacheInfoEx2ToMITCred is used when we do not need the real ticket */
+static BOOL
+CacheInfoEx2ToMITCred(KERB_TICKET_CACHE_INFO_EX2 *info,
+                      krb5_context context, krb5_creds *creds)
+{
+    WCHAR wrealm[128];
+    ZeroMemory(creds, sizeof(krb5_creds));
+    creds->magic=KV5M_CREDS;
+
+    // construct Client Principal
+    wcsncpy(wrealm, info->ClientRealm.Buffer, info->ClientRealm.Length/sizeof(WCHAR));
+    wrealm[info->ClientRealm.Length/sizeof(WCHAR)]=0;
+    if (!UnicodeStringToMITPrinc(&info->ClientName, wrealm, context, &creds->client))
+	return FALSE;
+
+    // construct Service Principal
+    wcsncpy(wrealm, info->ServerRealm.Buffer,
+            info->ServerRealm.Length/sizeof(WCHAR));
+    wrealm[info->ServerRealm.Length/sizeof(WCHAR)]=0;
+    if (!UnicodeStringToMITPrinc(&info->ServerName, wrealm, context, &creds->server))
+	return FALSE;
+
+    creds->keyblock.magic = KV5M_KEYBLOCK;
+    creds->keyblock.enctype = info->SessionKeyType;
+    creds->ticket_flags = info->TicketFlags;
+    MSFlagsToMITFlags(info->TicketFlags, &creds->ticket_flags);
+    creds->times.starttime=FileTimeToUnixTime(&info->StartTime);
+    creds->times.endtime=FileTimeToUnixTime(&info->EndTime);
+    creds->times.renew_till=FileTimeToUnixTime(&info->RenewTime);
+
+    /* MS Tickets are addressless.  MIT requires an empty address
+     * not a NULL list of addresses.
+     */
+    creds->addresses = (krb5_address **)malloc(sizeof(krb5_address *));
+    memset(creds->addresses, 0, sizeof(krb5_address *));
+
+    return TRUE;
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
+
+static BOOL
+PackageConnectLookup(HANDLE *pLogonHandle, ULONG *pPackageId)
+{
+    LSA_STRING Name;
+    NTSTATUS Status;
+
+    Status = LsaConnectUntrusted(
+        pLogonHandle
+        );
+
+    if (FAILED(Status))
+    {
+        ShowLsaError("LsaConnectUntrusted", Status);
+        return FALSE;
+    }
+
+    Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
+    Name.Length = strlen(Name.Buffer);
+    Name.MaximumLength = Name.Length + 1;
+
+    Status = LsaLookupAuthenticationPackage(
+        *pLogonHandle,
+        &Name,
+        pPackageId
+        );
+
+    if (FAILED(Status))
+    {
+        ShowLsaError("LsaLookupAuthenticationPackage", Status);
+        return FALSE;
+    }
+
+    return TRUE;
+
+}
+
+static BOOL 
+does_retrieve_ticket_cache_ticket (void)
+{
+   static BOOL fChecked = FALSE;
+   static BOOL fCachesTicket = FALSE;
+
+   if (!fChecked)
+   {
+       NTSTATUS Status = 0;
+       NTSTATUS SubStatus = 0;
+       HANDLE LogonHandle;
+       ULONG  PackageId;
+       ULONG RequestSize;
+       PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+       PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
+       ULONG ResponseSize;
+
+       RequestSize = sizeof(*pTicketRequest) + 1;
+
+       if (!PackageConnectLookup(&LogonHandle, &PackageId))
+           return FALSE;
+
+       pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+       if (!pTicketRequest) {
+           CloseHandle(LogonHandle);
+           return FALSE;
+       }
+
+       pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+       pTicketRequest->LogonId.LowPart = 0;
+       pTicketRequest->LogonId.HighPart = 0;
+       pTicketRequest->TargetName.Length = 0;
+       pTicketRequest->TargetName.MaximumLength = 0;
+       pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
+       pTicketRequest->CacheOptions = 
+           KERB_RETRIEVE_TICKET_DONT_USE_CACHE | KERB_RETRIEVE_TICKET_CACHE_TICKET;
+       pTicketRequest->EncryptionType = 0;
+       pTicketRequest->TicketFlags = 0;
+
+       Status = LsaCallAuthenticationPackage( LogonHandle,
+                                              PackageId,
+                                              pTicketRequest,
+                                              RequestSize,
+                                              &pTicketResponse,
+                                              &ResponseSize,
+                                              &SubStatus
+                                              );                                             
+
+       LocalFree(pTicketRequest);
+       CloseHandle(LogonHandle);
+
+       if (FAILED(Status) || FAILED(SubStatus)) {
+           if ( SubStatus == STATUS_NOT_SUPPORTED )
+               /* The combination of the two CacheOption flags 
+                * is not supported; therefore, the new flag is supported 
+                */
+               fCachesTicket = TRUE;
+       }
+       fChecked = TRUE;
+   }
+
+   return fCachesTicket;
+}
+
+#ifdef HAVE_CACHE_INFO_EX2
+static BOOL 
+does_query_ticket_cache_ex2 (void)
+{
+   static BOOL fChecked = FALSE;
+   static BOOL fEx2Response = FALSE;
+
+   if (!fChecked)
+   {
+       NTSTATUS Status = 0;
+       NTSTATUS SubStatus = 0;
+       HANDLE LogonHandle;
+       ULONG  PackageId;
+       ULONG RequestSize;
+       PKERB_QUERY_TKT_CACHE_REQUEST pCacheRequest = NULL;
+       PKERB_QUERY_TKT_CACHE_EX2_RESPONSE pCacheResponse = NULL;
+       ULONG ResponseSize;
+
+       RequestSize = sizeof(*pCacheRequest) + 1;
+
+       if (!PackageConnectLookup(&LogonHandle, &PackageId))
+           return FALSE;
+
+       pCacheRequest = (PKERB_QUERY_TKT_CACHE_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+       if (!pCacheRequest) {
+           CloseHandle(LogonHandle);
+           return FALSE;
+       }
+
+       pCacheRequest->MessageType = KerbQueryTicketCacheEx2Message;
+       pCacheRequest->LogonId.LowPart = 0;
+       pCacheRequest->LogonId.HighPart = 0;
+
+       Status = LsaCallAuthenticationPackage( LogonHandle,
+                                              PackageId,
+                                              pCacheRequest,
+                                              RequestSize,
+                                              &pCacheResponse,
+                                              &ResponseSize,
+                                              &SubStatus
+                                              );                                             
+
+       LocalFree(pCacheRequest);
+       CloseHandle(LogonHandle);
+
+       if (!(FAILED(Status) || FAILED(SubStatus))) {
+           LsaFreeReturnBuffer(pCacheResponse);
+           fEx2Response = TRUE;
+       }
+       fChecked = TRUE;
+   }
+
+   return fEx2Response;
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
+
+static DWORD
+ConcatenateUnicodeStrings(UNICODE_STRING *pTarget, UNICODE_STRING Source1, UNICODE_STRING Source2)
+{
+    //
+    // The buffers for Source1 and Source2 cannot overlap pTarget's
+    // buffer.  Source1.Length + Source2.Length must be <= 0xFFFF,
+    // otherwise we overflow...
+    //
+
+    USHORT TotalSize = Source1.Length + Source2.Length;
+    PBYTE buffer = (PBYTE) pTarget->Buffer;
+
+    if (TotalSize > pTarget->MaximumLength)
+        return ERROR_INSUFFICIENT_BUFFER;
+
+    if ( pTarget->Buffer != Source1.Buffer )
+        memcpy(buffer, Source1.Buffer, Source1.Length);
+    memcpy(buffer + Source1.Length, Source2.Buffer, Source2.Length);
+
+    pTarget->Length = TotalSize;
+    return ERROR_SUCCESS;
+}
+
+static BOOL
+get_STRING_from_registry(HKEY hBaseKey, char * key, char * value, char * outbuf, DWORD  outlen)
+{
+    HKEY hKey;
+    DWORD dwCount;
+    LONG rc;
+
+	if (!outbuf || outlen == 0)
+		return FALSE;
+
+    rc = RegOpenKeyExA(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey);
+    if (rc)
+        return FALSE;
+
+    dwCount = outlen;
+    rc = RegQueryValueExA(hKey, value, 0, 0, (LPBYTE) outbuf, &dwCount);
+    RegCloseKey(hKey);
+
+    return rc?FALSE:TRUE;
+}
+
+static BOOL
+GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+    NTSTATUS Status = 0;
+    HANDLE  TokenHandle;
+    TOKEN_STATISTICS Stats;
+    DWORD   ReqLen;
+    BOOL    Success;
+
+    if (!ppSessionData)
+        return FALSE;
+    *ppSessionData = NULL;
+
+    Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+    if ( !Success )
+        return FALSE;
+
+    Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+    CloseHandle( TokenHandle );
+    if ( !Success )
+        return FALSE;
+
+    Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
+    if ( FAILED(Status) || !ppSessionData )
+        return FALSE;
+
+    return TRUE;
+}
+
+//
+// IsKerberosLogon() does not validate whether or not there are valid tickets in the 
+// cache.  It validates whether or not it is reasonable to assume that if we 
+// attempted to retrieve valid tickets we could do so.  Microsoft does not 
+// automatically renew expired tickets.  Therefore, the cache could contain
+// expired or invalid tickets.  Microsoft also caches the user's password 
+// and will use it to retrieve new TGTs if the cache is empty and tickets
+// are requested.
+
+static BOOL
+IsKerberosLogon(VOID)
+{
+    PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
+    BOOL    Success = FALSE;
+
+    if ( GetSecurityLogonSessionData(&pSessionData) ) {
+        if ( pSessionData->AuthenticationPackage.Buffer ) {
+            WCHAR buffer[256];
+            WCHAR *usBuffer;
+            int usLength;
+
+            Success = FALSE;
+            usBuffer = (pSessionData->AuthenticationPackage).Buffer;
+            usLength = (pSessionData->AuthenticationPackage).Length;
+            if (usLength < 256)
+            {
+                lstrcpynW (buffer, usBuffer, usLength);
+                lstrcatW (buffer,L"");
+                if ( !lstrcmpW(L"Kerberos",buffer) )
+                    Success = TRUE;
+            }
+        }
+        LsaFreeReturnBuffer(pSessionData);
+    }
+    return Success;
+}
+
+static DWORD
+ConstructTicketRequest(UNICODE_STRING DomainName, PKERB_RETRIEVE_TKT_REQUEST * outRequest, ULONG * outSize)
+{
+    DWORD Error;
+    UNICODE_STRING TargetPrefix;
+    USHORT TargetSize;
+    ULONG RequestSize;
+    PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+
+    *outRequest = NULL;
+    *outSize = 0;
+
+    //
+    // Set up the "krbtgt/" target prefix into a UNICODE_STRING so we
+    // can easily concatenate it later.
+    //
+
+    TargetPrefix.Buffer = L"krbtgt/";
+    TargetPrefix.Length = wcslen(TargetPrefix.Buffer) * sizeof(WCHAR);
+    TargetPrefix.MaximumLength = TargetPrefix.Length;
+
+    //
+    // We will need to concatenate the "krbtgt/" prefix and the 
+    // Logon Session's DnsDomainName into our request's target name.
+    //
+    // Therefore, first compute the necessary buffer size for that.
+    //
+    // Note that we might theoretically have integer overflow.
+    //
+
+    TargetSize = TargetPrefix.Length + DomainName.Length;
+
+    //
+    // The ticket request buffer needs to be a single buffer.  That buffer
+    // needs to include the buffer for the target name.
+    //
+
+    RequestSize = sizeof(*pTicketRequest) + TargetSize;
+
+    //
+    // Allocate the request buffer and make sure it's zero-filled.
+    //
+
+    pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+    if (!pTicketRequest)
+        return GetLastError();
+
+    //
+    // Concatenate the target prefix with the previous reponse's
+    // target domain.
+    //
+
+    pTicketRequest->TargetName.Length = 0;
+    pTicketRequest->TargetName.MaximumLength = TargetSize;
+    pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
+    Error = ConcatenateUnicodeStrings(&(pTicketRequest->TargetName),
+                                        TargetPrefix,
+                                        DomainName);
+    *outRequest = pTicketRequest;
+    *outSize    = RequestSize;
+    return Error;
+}
+
+static BOOL
+PurgeAllTickets(HANDLE LogonHandle, ULONG  PackageId)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    KERB_PURGE_TKT_CACHE_REQUEST PurgeRequest;
+
+    PurgeRequest.MessageType = KerbPurgeTicketCacheMessage;
+    PurgeRequest.LogonId.LowPart = 0;
+    PurgeRequest.LogonId.HighPart = 0;
+    PurgeRequest.ServerName.Buffer = L"";
+    PurgeRequest.ServerName.Length = 0;
+    PurgeRequest.ServerName.MaximumLength = 0;
+    PurgeRequest.RealmName.Buffer = L"";
+    PurgeRequest.RealmName.Length = 0;
+    PurgeRequest.RealmName.MaximumLength = 0;
+    Status = LsaCallAuthenticationPackage(LogonHandle,
+                                           PackageId,
+                                           &PurgeRequest,
+                                           sizeof(PurgeRequest),
+                                           NULL,
+                                           NULL,
+                                           &SubStatus
+                                           );
+    if (FAILED(Status) || FAILED(SubStatus))
+        return FALSE;
+    return TRUE;
+}
+
+static BOOL
+PurgeTicket2000( HANDLE LogonHandle, ULONG  PackageId, 
+                 krb5_context context, krb5_creds *cred )
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    KERB_PURGE_TKT_CACHE_REQUEST * pPurgeRequest;
+    DWORD dwRequestLen = sizeof(KERB_PURGE_TKT_CACHE_REQUEST) + 2048;
+    char * sname = NULL, * srealm = NULL;
+
+    if (krb5_unparse_name(context, cred->server, &sname))
+        return FALSE;
+
+    pPurgeRequest = malloc(dwRequestLen);
+    if ( pPurgeRequest == NULL )
+        return FALSE;
+    memset(pPurgeRequest, 0, dwRequestLen);
+
+    srealm = strrchr(sname, '@');
+    *srealm = '\0';
+    srealm++;
+
+    pPurgeRequest->MessageType = KerbPurgeTicketCacheMessage;
+    pPurgeRequest->LogonId.LowPart = 0;
+    pPurgeRequest->LogonId.HighPart = 0;
+    pPurgeRequest->ServerName.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_REQUEST));
+    pPurgeRequest->ServerName.Length = strlen(sname)*sizeof(WCHAR);
+    pPurgeRequest->ServerName.MaximumLength = 256;
+    ANSIToUnicode(sname, pPurgeRequest->ServerName.Buffer,
+                  pPurgeRequest->ServerName.MaximumLength);
+    pPurgeRequest->RealmName.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_REQUEST)+512);
+    pPurgeRequest->RealmName.Length = strlen(srealm)*sizeof(WCHAR);
+    pPurgeRequest->RealmName.MaximumLength = 256;
+    ANSIToUnicode(srealm, pPurgeRequest->RealmName.Buffer,
+                  pPurgeRequest->RealmName.MaximumLength);
+
+    Status = LsaCallAuthenticationPackage( LogonHandle,
+                                           PackageId,
+                                           pPurgeRequest,
+                                           dwRequestLen,
+                                           NULL,
+                                           NULL,
+                                           &SubStatus
+                                           );
+    free(pPurgeRequest);
+    krb5_free_unparsed_name(context, sname);
+
+    if (FAILED(Status) || FAILED(SubStatus))
+        return FALSE;
+
+    return TRUE;
+}
+
+
+static BOOL
+PurgeTicketXP( HANDLE LogonHandle, ULONG  PackageId, 
+               krb5_context context, krb5_flags flags, krb5_creds *cred)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    KERB_PURGE_TKT_CACHE_EX_REQUEST * pPurgeRequest;
+    DWORD dwRequestLen = sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 4096;
+    char * cname = NULL, * crealm = NULL;
+    char * sname = NULL, * srealm = NULL;
+
+    if (krb5_unparse_name(context, cred->client, &cname))
+        return FALSE;
+    
+    if (krb5_unparse_name(context, cred->server, &sname)) {
+        krb5_free_unparsed_name(context, cname);
+        return FALSE;
+    }
+
+    pPurgeRequest = malloc(dwRequestLen);
+    if ( pPurgeRequest == NULL )
+        return FALSE;
+    memset(pPurgeRequest, 0, dwRequestLen);
+
+    crealm = strrchr(cname, '@');
+    *crealm = '\0';
+    crealm++;
+
+    srealm = strrchr(sname, '@');
+    *srealm = '\0';
+    srealm++;
+
+    pPurgeRequest->MessageType = KerbPurgeTicketCacheExMessage;
+    pPurgeRequest->LogonId.LowPart = 0;
+    pPurgeRequest->LogonId.HighPart = 0;
+    pPurgeRequest->Flags = 0;
+    pPurgeRequest->TicketTemplate.ClientName.Buffer = (PWSTR)((CHAR *)pPurgeRequest + sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST));
+    pPurgeRequest->TicketTemplate.ClientName.Length = strlen(cname)*sizeof(WCHAR);
+    pPurgeRequest->TicketTemplate.ClientName.MaximumLength = 256;
+    ANSIToUnicode(cname, pPurgeRequest->TicketTemplate.ClientName.Buffer,
+                  pPurgeRequest->TicketTemplate.ClientName.MaximumLength);
+
+    pPurgeRequest->TicketTemplate.ClientRealm.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 512);
+    pPurgeRequest->TicketTemplate.ClientRealm.Length = strlen(crealm)*sizeof(WCHAR);
+    pPurgeRequest->TicketTemplate.ClientRealm.MaximumLength = 256;
+    ANSIToUnicode(crealm, pPurgeRequest->TicketTemplate.ClientRealm.Buffer,
+                  pPurgeRequest->TicketTemplate.ClientRealm.MaximumLength);
+
+    pPurgeRequest->TicketTemplate.ServerName.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 1024);
+    pPurgeRequest->TicketTemplate.ServerName.Length = strlen(sname)*sizeof(WCHAR);
+    pPurgeRequest->TicketTemplate.ServerName.MaximumLength = 256;
+    ANSIToUnicode(sname, pPurgeRequest->TicketTemplate.ServerName.Buffer,
+                  pPurgeRequest->TicketTemplate.ServerName.MaximumLength);
+
+    pPurgeRequest->TicketTemplate.ServerRealm.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 1536);
+    pPurgeRequest->TicketTemplate.ServerRealm.Length = strlen(srealm)*sizeof(WCHAR);
+    pPurgeRequest->TicketTemplate.ServerRealm.MaximumLength = 256;
+    ANSIToUnicode(srealm, pPurgeRequest->TicketTemplate.ServerRealm.Buffer,
+                  pPurgeRequest->TicketTemplate.ServerRealm.MaximumLength);
+
+    pPurgeRequest->TicketTemplate.StartTime;
+    pPurgeRequest->TicketTemplate.EndTime;
+    pPurgeRequest->TicketTemplate.RenewTime;
+    pPurgeRequest->TicketTemplate.EncryptionType = cred->keyblock.enctype;
+    pPurgeRequest->TicketTemplate.TicketFlags = flags;
+
+    Status = LsaCallAuthenticationPackage( LogonHandle,
+                                           PackageId,
+                                           pPurgeRequest,
+                                           dwRequestLen,
+                                           NULL,
+                                           NULL,
+                                           &SubStatus
+                                           );
+    free(pPurgeRequest);
+    krb5_free_unparsed_name(context,cname);
+    krb5_free_unparsed_name(context,sname);
+
+    if (FAILED(Status) || FAILED(SubStatus))
+        return FALSE;
+    return TRUE;
+}
+
+#ifdef KERB_SUBMIT_TICKET
+static BOOL
+KerbSubmitTicket( HANDLE LogonHandle, ULONG  PackageId, 
+                  krb5_context context, krb5_creds *cred)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    KERB_SUBMIT_TKT_REQUEST * pSubmitRequest;
+    DWORD dwRequestLen;
+    krb5_auth_context auth_context;
+    krb5_keyblock * keyblock = 0;
+    krb5_replay_data replaydata;
+    krb5_data * krb_cred = 0;
+    krb5_error_code rc;
+
+    if (krb5_auth_con_init(context, &auth_context)) {
+        return FALSE;
+    }
+
+    if (krb5_auth_con_setflags(context, auth_context,
+                               KRB5_AUTH_CONTEXT_RET_TIME)) {
+        return FALSE;
+    }
+    
+    krb5_auth_con_getsendsubkey(context, auth_context, &keyblock);
+    if (keyblock == NULL)
+        krb5_auth_con_getkey(context, auth_context, &keyblock);
+
+    /* make up a key, any key, that can be used to generate the 
+    * encrypted KRB_CRED pdu.  The Vista release LSA requires 
+    * that an enctype other than NULL be used. */
+    if (keyblock == NULL) {
+        keyblock = (krb5_keyblock *)malloc(sizeof(krb5_keyblock));
+        keyblock->enctype = ENCTYPE_ARCFOUR_HMAC;
+        keyblock->length = 16;
+        keyblock->contents = (krb5_octet *)malloc(16);
+        keyblock->contents[0] = 0xde;
+        keyblock->contents[1] = 0xad;
+        keyblock->contents[2] = 0xbe;
+        keyblock->contents[3] = 0xef;
+        keyblock->contents[4] = 0xfe;
+        keyblock->contents[5] = 0xed;
+        keyblock->contents[6] = 0xf0;
+        keyblock->contents[7] = 0xd;
+        keyblock->contents[8] = 0xde;
+        keyblock->contents[9] = 0xad;
+        keyblock->contents[10] = 0xbe;
+        keyblock->contents[11] = 0xef;
+        keyblock->contents[12] = 0xfe;
+        keyblock->contents[13] = 0xed;
+        keyblock->contents[14] = 0xf0;
+        keyblock->contents[15] = 0xd;
+        krb5_auth_con_setsendsubkey(context, auth_context, keyblock);
+    }
+    rc = krb5_mk_1cred(context, auth_context, cred, &krb_cred, &replaydata);
+    if (rc) {
+        krb5_auth_con_free(context, auth_context);
+        if (keyblock)
+            krb5_free_keyblock(context, keyblock);
+        if (krb_cred)
+            krb5_free_data(context, krb_cred);
+        return FALSE;
+    }
+
+    dwRequestLen = sizeof(KERB_SUBMIT_TKT_REQUEST) + krb_cred->length + (keyblock ? keyblock->length : 0);
+
+    pSubmitRequest = (PKERB_SUBMIT_TKT_REQUEST)malloc(dwRequestLen);
+    memset(pSubmitRequest, 0, dwRequestLen);
+
+    pSubmitRequest->MessageType = KerbSubmitTicketMessage;
+    pSubmitRequest->LogonId.LowPart = 0;
+    pSubmitRequest->LogonId.HighPart = 0;
+    pSubmitRequest->Flags = 0;
+    
+    if (keyblock) {
+        pSubmitRequest->Key.KeyType = keyblock->enctype;
+        pSubmitRequest->Key.Length = keyblock->length;
+        pSubmitRequest->Key.Offset = sizeof(KERB_SUBMIT_TKT_REQUEST)+krb_cred->length;
+    } else {
+        pSubmitRequest->Key.KeyType = ENCTYPE_NULL;
+        pSubmitRequest->Key.Length = 0;
+        pSubmitRequest->Key.Offset = 0;
+    }
+    pSubmitRequest->KerbCredSize = krb_cred->length;
+    pSubmitRequest->KerbCredOffset = sizeof(KERB_SUBMIT_TKT_REQUEST);
+    memcpy(((CHAR *)pSubmitRequest)+sizeof(KERB_SUBMIT_TKT_REQUEST),
+           krb_cred->data, krb_cred->length);
+    if (keyblock)
+        memcpy(((CHAR *)pSubmitRequest)+sizeof(KERB_SUBMIT_TKT_REQUEST)+krb_cred->length,
+                keyblock->contents, keyblock->length);
+    krb5_free_data(context, krb_cred);
+
+    Status = LsaCallAuthenticationPackage( LogonHandle,
+                                           PackageId,
+                                           pSubmitRequest,
+                                           dwRequestLen,
+                                           NULL,
+                                           NULL,
+                                           &SubStatus
+                                           );
+    free(pSubmitRequest);
+    if (keyblock)
+        krb5_free_keyblock(context, keyblock);
+    krb5_auth_con_free(context, auth_context);
+
+    if (FAILED(Status) || FAILED(SubStatus)) {
+        return FALSE;                         
+    }
+    return TRUE;
+}
+#endif /* KERB_SUBMIT_TICKET */
+
+/* 
+ * A simple function to determine if there is an exact match between two tickets
+ * We rely on the fact that the external tickets contain the raw Kerberos ticket.
+ * If the EncodedTicket fields match, the KERB_EXTERNAL_TICKETs must be the same.
+ */
+static BOOL
+KerbExternalTicketMatch( PKERB_EXTERNAL_TICKET one, PKERB_EXTERNAL_TICKET two )
+{
+    if ( one->EncodedTicketSize != two->EncodedTicketSize )
+        return FALSE;
+
+    if ( memcmp(one->EncodedTicket, two->EncodedTicket, one->EncodedTicketSize) )
+         return FALSE;
+
+    return TRUE;
+}
+
+krb5_boolean
+krb5_is_permitted_tgs_enctype(krb5_context context, krb5_const_principal princ, krb5_enctype etype)
+{
+    krb5_enctype *list, *ptr;
+    krb5_boolean ret;
+
+    if (krb5_get_tgs_ktypes(context, princ, &list))
+        return(0);
+    
+    ret = 0;
+
+    for (ptr = list; *ptr; ptr++)
+	if (*ptr == etype)
+	    ret = 1;
+
+    krb5_free_ktypes (context, list);
+
+    return(ret);
+}
+
+#define ENABLE_PURGING 1
+// to allow the purging of expired tickets from LSA cache.  This is necessary
+// to force the retrieval of new TGTs.  Microsoft does not appear to retrieve
+// new tickets when they expire.  Instead they continue to accept the expired
+// tickets.  This is safe to do because the LSA purges its cache when it 
+// retrieves a new TGT (ms calls this renew) but not when it renews the TGT
+// (ms calls this refresh).
+
+static BOOL
+GetMSTGT(krb5_context context, HANDLE LogonHandle, ULONG PackageId, KERB_EXTERNAL_TICKET **ticket, BOOL enforce_tgs_enctypes)
+{
+    //
+    // INVARIANTS:
+    //
+    //   (FAILED(Status) || FAILED(SubStatus)) ==> error
+    //   bIsLsaError ==> LsaCallAuthenticationPackage() error
+    //
+
+    BOOL bIsLsaError = FALSE;
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    DWORD   Error;
+
+    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+    PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+    PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
+    ULONG RequestSize;
+    ULONG ResponseSize;
+#ifdef ENABLE_PURGING
+    int    purge_cache = 0;
+#endif /* ENABLE_PURGING */
+    int    ignore_cache = 0;
+    krb5_enctype *etype_list = NULL, *ptr = NULL, etype = 0;
+
+    if (is_process_uac_limited()) {
+	Status = STATUS_ACCESS_DENIED;
+        goto cleanup;
+    }
+
+    memset(&CacheRequest, 0, sizeof(KERB_QUERY_TKT_CACHE_REQUEST));
+    CacheRequest.MessageType = KerbRetrieveTicketMessage;
+    CacheRequest.LogonId.LowPart = 0;
+    CacheRequest.LogonId.HighPart = 0;
+
+    Status = LsaCallAuthenticationPackage(
+        LogonHandle,
+        PackageId,
+        &CacheRequest,
+        sizeof(CacheRequest),
+        &pTicketResponse,
+        &ResponseSize,
+        &SubStatus
+        );
+
+    if (FAILED(Status))
+    {
+        // if the call to LsaCallAuthenticationPackage failed we cannot
+        // perform any queries most likely because the Kerberos package 
+        // is not available or we do not have access
+        bIsLsaError = TRUE;
+        goto cleanup;
+    }
+
+    if (FAILED(SubStatus)) {
+        PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
+        BOOL    Success = FALSE;
+        OSVERSIONINFOEX verinfo;
+        int supported = 0;
+
+        // SubStatus 0x8009030E is not documented.  However, it appears
+        // to mean there is no TGT
+        if (SubStatus != 0x8009030E) {
+            bIsLsaError = TRUE;
+            goto cleanup;
+        }
+
+        verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+        GetVersionEx((OSVERSIONINFO *)&verinfo);
+        supported = (verinfo.dwMajorVersion > 5) || 
+            (verinfo.dwMajorVersion == 5 && verinfo.dwMinorVersion >= 1);
+
+        // If we could not get a TGT from the cache we won't know what the
+        // Kerberos Domain should have been.  On Windows XP and 2003 Server
+        // we can extract it from the Security Logon Session Data.  However,
+        // the required fields are not supported on Windows 2000.  :(
+        if ( supported && GetSecurityLogonSessionData(&pSessionData) ) {
+            if ( pSessionData->DnsDomainName.Buffer ) {
+                Error = ConstructTicketRequest(pSessionData->DnsDomainName,
+                                                &pTicketRequest, &RequestSize);
+                LsaFreeReturnBuffer(pSessionData);
+                if ( Error )
+                    goto cleanup;
+            } else {
+                LsaFreeReturnBuffer(pSessionData);
+                bIsLsaError = TRUE;
+                goto cleanup;
+            }
+        } else {
+            CHAR  UserDnsDomain[256];
+            WCHAR UnicodeUserDnsDomain[256];
+            UNICODE_STRING wrapper;
+            if ( !get_STRING_from_registry(HKEY_CURRENT_USER,
+                                          "Volatile Environment",
+                                          "USERDNSDOMAIN",
+                                           UserDnsDomain,
+                                           sizeof(UserDnsDomain)
+                                           ) )
+            {
+                goto cleanup;
+            }
+
+            ANSIToUnicode(UserDnsDomain,UnicodeUserDnsDomain,256);
+            wrapper.Buffer = UnicodeUserDnsDomain;
+            wrapper.Length = wcslen(UnicodeUserDnsDomain) * sizeof(WCHAR);
+            wrapper.MaximumLength = 256;
+
+            Error = ConstructTicketRequest(wrapper,
+                                             &pTicketRequest, &RequestSize);
+            if ( Error )
+                goto cleanup;
+        }
+    } else {
+        /* We have succeeded in obtaining a credential from the cache. 
+         * Assuming the enctype is one that we support and the ticket
+         * has not expired and is not marked invalid we will use it.
+         * Otherwise, we must create a new ticket request and obtain
+         * a credential we can use. 
+         */
+
+#ifdef PURGE_ALL
+        purge_cache = 1;
+#else
+        /* Check Supported Enctypes */
+        if ( !enforce_tgs_enctypes ||
+	     IsMSSessionKeyNull(&pTicketResponse->Ticket.SessionKey) ||
+             krb5_is_permitted_tgs_enctype(context, NULL, pTicketResponse->Ticket.SessionKey.KeyType) ) {
+            FILETIME Now, MinLife, EndTime, LocalEndTime;
+            __int64  temp;
+            // FILETIME is in units of 100 nano-seconds
+            // If obtained tickets are either expired or have a lifetime
+            // less than 20 minutes, retry ...
+            GetSystemTimeAsFileTime(&Now);
+            EndTime.dwLowDateTime=pTicketResponse->Ticket.EndTime.LowPart;
+            EndTime.dwHighDateTime=pTicketResponse->Ticket.EndTime.HighPart;
+            FileTimeToLocalFileTime(&EndTime, &LocalEndTime);
+            temp = Now.dwHighDateTime;
+            temp <<= 32;
+            temp = Now.dwLowDateTime;
+            temp += 1200 * 10000;
+            MinLife.dwHighDateTime = (DWORD)((temp >> 32) & 0xFFFFFFFF);
+            MinLife.dwLowDateTime = (DWORD)(temp & 0xFFFFFFFF);
+            if (CompareFileTime(&MinLife, &LocalEndTime) >= 0) {
+#ifdef ENABLE_PURGING
+                purge_cache = 1;
+#else
+                ignore_cache = 1;
+#endif /* ENABLE_PURGING */
+            }
+            if (pTicketResponse->Ticket.TicketFlags & KERB_TICKET_FLAGS_invalid) {
+                ignore_cache = 1;   // invalid, need to attempt a TGT request
+            }
+            goto cleanup;           // we have a valid ticket, all done
+        } else {
+            // not supported
+            ignore_cache = 1;
+        }
+#endif /* PURGE_ALL */
+
+        Error = ConstructTicketRequest(pTicketResponse->Ticket.TargetDomainName,
+                                        &pTicketRequest, &RequestSize);
+        if ( Error ) {
+            goto cleanup;
+        }
+
+        //
+        // Free the previous response buffer so we can get the new response.
+        //
+
+        if ( pTicketResponse ) {
+            memset(pTicketResponse,0,sizeof(KERB_RETRIEVE_TKT_RESPONSE));
+            LsaFreeReturnBuffer(pTicketResponse);
+            pTicketResponse = NULL;
+        }
+
+#ifdef ENABLE_PURGING
+        if ( purge_cache ) {
+            //
+            // Purge the existing tickets which we cannot use so new ones can 
+            // be requested.  It is not possible to purge just the TGT.  All
+            // service tickets must be purged.
+            //
+            PurgeAllTickets(LogonHandle, PackageId);
+        }
+#endif /* ENABLE_PURGING */
+    }
+    
+    //
+    // Intialize the request of the request.
+    //
+
+    pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+    pTicketRequest->LogonId.LowPart = 0;
+    pTicketRequest->LogonId.HighPart = 0;
+    // Note: pTicketRequest->TargetName set up above
+#ifdef ENABLE_PURGING
+    pTicketRequest->CacheOptions = ((ignore_cache || !purge_cache) ? 
+                                     KERB_RETRIEVE_TICKET_DONT_USE_CACHE : 0L);
+#else
+    pTicketRequest->CacheOptions = (ignore_cache ? KERB_RETRIEVE_TICKET_DONT_USE_CACHE : 0L);
+#endif /* ENABLE_PURGING */
+    pTicketRequest->TicketFlags = 0L;
+    pTicketRequest->EncryptionType = 0L;
+
+    Status = LsaCallAuthenticationPackage( LogonHandle,
+                                           PackageId,
+                                           pTicketRequest,
+                                           RequestSize,
+                                           &pTicketResponse,
+                                           &ResponseSize,
+                                           &SubStatus
+                                           );
+
+    if (FAILED(Status) || FAILED(SubStatus))
+    {
+        bIsLsaError = TRUE;
+        goto cleanup;
+    }
+
+    //
+    // Check to make sure the new tickets we received are of a type we support
+    //
+
+    /* Check Supported Enctypes */
+    if ( !enforce_tgs_enctypes ||
+         krb5_is_permitted_tgs_enctype(context, NULL, pTicketResponse->Ticket.SessionKey.KeyType) ) {
+        goto cleanup;       // we have a valid ticket, all done
+    }
+
+    if (krb5_get_tgs_ktypes(context, NULL, &etype_list)) {
+        ptr = etype_list = NULL;
+        etype = ENCTYPE_DES_CBC_CRC;
+    } else {
+        ptr = etype_list + 1;
+        etype = *etype_list;
+    }
+
+    while ( etype ) {
+        // Try once more but this time specify the Encryption Type
+        // (This will not store the retrieved tickets in the LSA cache unless
+        // 0 is supported.)
+        pTicketRequest->EncryptionType = etype;
+        pTicketRequest->CacheOptions = 0;
+        if ( does_retrieve_ticket_cache_ticket() )
+            pTicketRequest->CacheOptions |= KERB_RETRIEVE_TICKET_CACHE_TICKET;
+
+        if ( pTicketResponse ) {
+            memset(pTicketResponse,0,sizeof(KERB_RETRIEVE_TKT_RESPONSE));
+            LsaFreeReturnBuffer(pTicketResponse);
+            pTicketResponse = NULL;
+        }
+
+        Status = LsaCallAuthenticationPackage( LogonHandle,
+                                               PackageId,
+                                               pTicketRequest,
+                                               RequestSize,
+                                               &pTicketResponse,
+                                               &ResponseSize,
+                                               &SubStatus
+                                               );
+
+        if (FAILED(Status) || FAILED(SubStatus))
+        {
+            bIsLsaError = TRUE;
+            goto cleanup;
+        }
+
+        if ( pTicketResponse->Ticket.SessionKey.KeyType == etype && 
+             (!enforce_tgs_enctypes ||
+             krb5_is_permitted_tgs_enctype(context, NULL, pTicketResponse->Ticket.SessionKey.KeyType)) ) {
+            goto cleanup;       // we have a valid ticket, all done
+        }
+
+        if ( ptr ) {
+            etype = *ptr++;
+        } else {
+            etype = 0;
+        }
+    }
+
+  cleanup:
+    if ( etype_list )
+        krb5_free_ktypes(context, etype_list);
+
+    if ( pTicketRequest )
+        LocalFree(pTicketRequest);
+
+    if (FAILED(Status) || FAILED(SubStatus))
+    {
+        if (bIsLsaError)
+        {
+            // XXX - Will be fixed later
+            if (FAILED(Status))
+                ShowLsaError("LsaCallAuthenticationPackage", Status);
+            if (FAILED(SubStatus))
+                ShowLsaError("LsaCallAuthenticationPackage", SubStatus);
+        }
+        else
+        {
+            ShowWinError("GetMSTGT", Status);
+        }
+
+        if (pTicketResponse) {
+            memset(pTicketResponse,0,sizeof(KERB_RETRIEVE_TKT_RESPONSE));
+            LsaFreeReturnBuffer(pTicketResponse);
+            pTicketResponse = NULL;
+        }
+        return(FALSE);
+    }
+
+    *ticket = &(pTicketResponse->Ticket);
+    return(TRUE);
+}
+
+static BOOL
+GetQueryTktCacheResponseW2K( HANDLE LogonHandle, ULONG PackageId,
+                             PKERB_QUERY_TKT_CACHE_RESPONSE * ppResponse)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+
+    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+    PKERB_QUERY_TKT_CACHE_RESPONSE pQueryResponse = NULL;
+    ULONG ResponseSize;
+    
+    CacheRequest.MessageType = KerbQueryTicketCacheMessage;
+    CacheRequest.LogonId.LowPart = 0;
+    CacheRequest.LogonId.HighPart = 0;
+
+    Status = LsaCallAuthenticationPackage(
+        LogonHandle,
+        PackageId,
+        &CacheRequest,
+        sizeof(CacheRequest),
+        &pQueryResponse,
+        &ResponseSize,
+        &SubStatus
+        );
+
+    if ( !(FAILED(Status) || FAILED(SubStatus)) ) {
+        *ppResponse = pQueryResponse;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static BOOL
+GetQueryTktCacheResponseXP( HANDLE LogonHandle, ULONG PackageId,
+                            PKERB_QUERY_TKT_CACHE_EX_RESPONSE * ppResponse)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+
+    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+    PKERB_QUERY_TKT_CACHE_EX_RESPONSE pQueryResponse = NULL;
+    ULONG ResponseSize;
+    
+    CacheRequest.MessageType = KerbQueryTicketCacheExMessage;
+    CacheRequest.LogonId.LowPart = 0;
+    CacheRequest.LogonId.HighPart = 0;
+
+    Status = LsaCallAuthenticationPackage(
+        LogonHandle,
+        PackageId,
+        &CacheRequest,
+        sizeof(CacheRequest),
+        &pQueryResponse,
+        &ResponseSize,
+        &SubStatus
+        );
+
+    if ( !(FAILED(Status) || FAILED(SubStatus)) ) {
+        *ppResponse = pQueryResponse;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+#ifdef HAVE_CACHE_INFO_EX2
+static BOOL
+GetQueryTktCacheResponseEX2( HANDLE LogonHandle, ULONG PackageId,
+                             PKERB_QUERY_TKT_CACHE_EX2_RESPONSE * ppResponse)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+
+    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+    PKERB_QUERY_TKT_CACHE_EX2_RESPONSE pQueryResponse = NULL;
+    ULONG ResponseSize;
+    
+    CacheRequest.MessageType = KerbQueryTicketCacheEx2Message;
+    CacheRequest.LogonId.LowPart = 0;
+    CacheRequest.LogonId.HighPart = 0;
+
+    Status = LsaCallAuthenticationPackage(
+        LogonHandle,
+        PackageId,
+        &CacheRequest,
+        sizeof(CacheRequest),
+        &pQueryResponse,
+        &ResponseSize,
+        &SubStatus
+        );
+
+    if ( !(FAILED(Status) || FAILED(SubStatus)) ) {
+        *ppResponse = pQueryResponse;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
+
+static BOOL
+GetMSCacheTicketFromMITCred( HANDLE LogonHandle, ULONG PackageId,
+                             krb5_context context, krb5_creds *creds, 
+                             PKERB_EXTERNAL_TICKET *ticket)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    ULONG RequestSize;
+    PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+    PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
+    ULONG ResponseSize;
+
+    RequestSize = sizeof(*pTicketRequest) + MAX_MSPRINC_SIZE;
+
+    pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+    if (!pTicketRequest)
+        return FALSE;
+
+    pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+    pTicketRequest->LogonId.LowPart = 0;
+    pTicketRequest->LogonId.HighPart = 0;
+
+    pTicketRequest->TargetName.Length = 0;
+    pTicketRequest->TargetName.MaximumLength = MAX_MSPRINC_SIZE;
+    pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
+    MITPrincToMSPrinc(context, creds->server, &pTicketRequest->TargetName);
+    pTicketRequest->CacheOptions = 0;
+    if ( does_retrieve_ticket_cache_ticket() )
+        pTicketRequest->CacheOptions |= KERB_RETRIEVE_TICKET_CACHE_TICKET;
+    pTicketRequest->TicketFlags = creds->ticket_flags;
+    pTicketRequest->EncryptionType = creds->keyblock.enctype;
+
+    Status = LsaCallAuthenticationPackage( LogonHandle,
+                                           PackageId,
+                                           pTicketRequest,
+                                           RequestSize,
+                                           &pTicketResponse,
+                                           &ResponseSize,
+                                           &SubStatus
+                                           );
+
+    LocalFree(pTicketRequest);
+
+    if (FAILED(Status) || FAILED(SubStatus))
+        return(FALSE);
+
+    /* otherwise return ticket */
+    *ticket = &(pTicketResponse->Ticket);
+    return(TRUE);
+}
+
+static BOOL
+GetMSCacheTicketFromCacheInfoW2K( HANDLE LogonHandle, ULONG PackageId,
+                  PKERB_TICKET_CACHE_INFO tktinfo, PKERB_EXTERNAL_TICKET *ticket)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    ULONG RequestSize;
+    PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+    PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
+    ULONG ResponseSize;
+
+    RequestSize = sizeof(*pTicketRequest) + tktinfo->ServerName.Length;
+
+    pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+    if (!pTicketRequest)
+        return FALSE;
+
+    pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+    pTicketRequest->LogonId.LowPart = 0;
+    pTicketRequest->LogonId.HighPart = 0;
+    pTicketRequest->TargetName.Length = tktinfo->ServerName.Length;
+    pTicketRequest->TargetName.MaximumLength = tktinfo->ServerName.Length;
+    pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
+    memcpy(pTicketRequest->TargetName.Buffer,tktinfo->ServerName.Buffer, tktinfo->ServerName.Length);
+    pTicketRequest->CacheOptions = 0;
+    if ( does_retrieve_ticket_cache_ticket() )
+        pTicketRequest->CacheOptions |= KERB_RETRIEVE_TICKET_CACHE_TICKET;
+    pTicketRequest->EncryptionType = tktinfo->EncryptionType;
+    pTicketRequest->TicketFlags = 0;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwardable )
+        pTicketRequest->TicketFlags |= KDC_OPT_FORWARDABLE;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwarded )
+        pTicketRequest->TicketFlags |= KDC_OPT_FORWARDED;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_proxiable )
+        pTicketRequest->TicketFlags |= KDC_OPT_PROXIABLE;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_renewable )
+        pTicketRequest->TicketFlags |= KDC_OPT_RENEWABLE;
+
+    Status = LsaCallAuthenticationPackage(
+        LogonHandle,
+        PackageId,
+        pTicketRequest,
+        RequestSize,
+        &pTicketResponse,
+        &ResponseSize,
+        &SubStatus
+        );
+
+    LocalFree(pTicketRequest);
+
+    if (FAILED(Status) || FAILED(SubStatus))
+        return(FALSE);
+    
+    /* otherwise return ticket */
+    *ticket = &(pTicketResponse->Ticket);
+
+    /* set the initial flag if we were attempting to retrieve one
+     * because Windows won't necessarily return the initial ticket
+     * to us.
+     */
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_initial )
+        (*ticket)->TicketFlags |= KERB_TICKET_FLAGS_initial;
+
+    return(TRUE);
+}
+
+static BOOL
+GetMSCacheTicketFromCacheInfoXP( HANDLE LogonHandle, ULONG PackageId,
+                  PKERB_TICKET_CACHE_INFO_EX tktinfo, PKERB_EXTERNAL_TICKET *ticket)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    ULONG RequestSize;
+    PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+    PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
+    ULONG ResponseSize;
+
+    RequestSize = sizeof(*pTicketRequest) + tktinfo->ServerName.Length;
+
+    pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+    if (!pTicketRequest)
+        return FALSE;
+
+    pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+    pTicketRequest->LogonId.LowPart = 0;
+    pTicketRequest->LogonId.HighPart = 0;
+    pTicketRequest->TargetName.Length = tktinfo->ServerName.Length;
+    pTicketRequest->TargetName.MaximumLength = tktinfo->ServerName.Length;
+    pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
+    memcpy(pTicketRequest->TargetName.Buffer,tktinfo->ServerName.Buffer, tktinfo->ServerName.Length);
+    pTicketRequest->CacheOptions = 0;
+    pTicketRequest->EncryptionType = tktinfo->EncryptionType;
+    pTicketRequest->TicketFlags = 0;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwardable )
+        pTicketRequest->TicketFlags |= KDC_OPT_FORWARDABLE;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwarded )
+        pTicketRequest->TicketFlags |= KDC_OPT_FORWARDED;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_proxiable )
+        pTicketRequest->TicketFlags |= KDC_OPT_PROXIABLE;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_renewable )
+        pTicketRequest->TicketFlags |= KDC_OPT_RENEWABLE;
+
+    Status = LsaCallAuthenticationPackage(
+        LogonHandle,
+        PackageId,
+        pTicketRequest,
+        RequestSize,
+        &pTicketResponse,
+        &ResponseSize,
+        &SubStatus
+        );
+
+    LocalFree(pTicketRequest);
+
+    if (FAILED(Status) || FAILED(SubStatus))
+        return(FALSE);
+    
+    /* otherwise return ticket */
+    *ticket = &(pTicketResponse->Ticket);
+    
+    /* set the initial flag if we were attempting to retrieve one
+     * because Windows won't necessarily return the initial ticket
+     * to us.
+     */
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_initial )
+        (*ticket)->TicketFlags |= KERB_TICKET_FLAGS_initial;
+
+    return(TRUE);
+}
+
+#ifdef HAVE_CACHE_INFO_EX2
+static BOOL
+GetMSCacheTicketFromCacheInfoEX2( HANDLE LogonHandle, ULONG PackageId,
+                  PKERB_TICKET_CACHE_INFO_EX2 tktinfo, PKERB_EXTERNAL_TICKET *ticket)
+{
+    NTSTATUS Status = 0;
+    NTSTATUS SubStatus = 0;
+    ULONG RequestSize;
+    PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+    PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
+    ULONG ResponseSize;
+
+    RequestSize = sizeof(*pTicketRequest) + tktinfo->ServerName.Length;
+
+    pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+    if (!pTicketRequest)
+        return FALSE;
+
+    pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+    pTicketRequest->LogonId.LowPart = 0;
+    pTicketRequest->LogonId.HighPart = 0;
+    pTicketRequest->TargetName.Length = tktinfo->ServerName.Length;
+    pTicketRequest->TargetName.MaximumLength = tktinfo->ServerName.Length;
+    pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
+    memcpy(pTicketRequest->TargetName.Buffer,tktinfo->ServerName.Buffer, tktinfo->ServerName.Length);
+    pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_CACHE_TICKET;
+    pTicketRequest->EncryptionType = tktinfo->SessionKeyType;
+    pTicketRequest->TicketFlags = 0;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwardable )
+        pTicketRequest->TicketFlags |= KDC_OPT_FORWARDABLE;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwarded )
+        pTicketRequest->TicketFlags |= KDC_OPT_FORWARDED;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_proxiable )
+        pTicketRequest->TicketFlags |= KDC_OPT_PROXIABLE;
+    if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_renewable )
+        pTicketRequest->TicketFlags |= KDC_OPT_RENEWABLE;
+
+    Status = LsaCallAuthenticationPackage(
+        LogonHandle,
+        PackageId,
+        pTicketRequest,
+        RequestSize,
+        &pTicketResponse,
+        &ResponseSize,
+        &SubStatus
+        );
+
+    LocalFree(pTicketRequest);
+
+    if (FAILED(Status) || FAILED(SubStatus))
+        return(FALSE);
+    
+    /* otherwise return ticket */
+    *ticket = &(pTicketResponse->Ticket);
+
+    
+    /* set the initial flag if we were attempting to retrieve one
+    * because Windows won't necessarily return the initial ticket
+    * to us.
+    */
+   if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_initial )
+       (*ticket)->TicketFlags |= KERB_TICKET_FLAGS_initial;
+
+    return(TRUE);
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_close
+        (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_destroy
+        (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_end_seq_get
+        (krb5_context, krb5_ccache id, krb5_cc_cursor *cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_generate_new
+        (krb5_context, krb5_ccache *id);
+
+static const char * KRB5_CALLCONV krb5_lcc_get_name
+        (krb5_context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_get_principal
+        (krb5_context, krb5_ccache id, krb5_principal *princ);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_initialize
+        (krb5_context, krb5_ccache id, krb5_principal princ);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_next_cred
+        (krb5_context, krb5_ccache id, krb5_cc_cursor *cursor,
+	 krb5_creds *creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_resolve
+        (krb5_context, krb5_ccache *id, const char *residual);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_retrieve
+        (krb5_context, krb5_ccache id, krb5_flags whichfields,
+	 krb5_creds *mcreds, krb5_creds *creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_start_seq_get
+        (krb5_context, krb5_ccache id, krb5_cc_cursor *cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_store
+        (krb5_context, krb5_ccache id, krb5_creds *creds);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_set_flags
+        (krb5_context, krb5_ccache id, krb5_flags flags);
+
+static krb5_error_code KRB5_CALLCONV krb5_lcc_get_flags
+        (krb5_context, krb5_ccache id, krb5_flags *flags);
+
+extern const krb5_cc_ops krb5_lcc_ops;
+
+krb5_error_code krb5_change_cache (void);
+
+krb5_boolean
+krb5int_cc_creds_match_request(krb5_context, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds);
+
+#define KRB5_OK 0
+
+typedef struct _krb5_lcc_data {
+    HANDLE LogonHandle;
+    ULONG  PackageId;
+    char * cc_name;
+    krb5_principal princ;
+    krb5_flags flags;
+} krb5_lcc_data;
+
+typedef struct _krb5_lcc_cursor {
+    union {
+        PKERB_QUERY_TKT_CACHE_RESPONSE w2k;
+        PKERB_QUERY_TKT_CACHE_EX_RESPONSE xp;
+#ifdef HAVE_CACHE_INFO_EX2
+        PKERB_QUERY_TKT_CACHE_EX2_RESPONSE ex2;
+#endif /* HAVE_CACHE_INFO_EX2 */
+    } response;
+    unsigned int index;
+    PKERB_EXTERNAL_TICKET mstgt;
+} krb5_lcc_cursor;
+
+
+/*
+ * Requires:
+ * residual is ignored
+ *
+ * Modifies:
+ * id
+ * 
+ * Effects:
+ * Acccess the MS Kerberos LSA cache in the current logon session
+ * Ignore the residual.
+ * 
+ * Returns:
+ * A filled in krb5_ccache structure "id".
+ *
+ * Errors:
+ * KRB5_CC_NOMEM - there was insufficient memory to allocate the
+ * 
+ * 		krb5_ccache.  id is undefined.
+ * permission errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
+{
+    krb5_ccache lid;
+    krb5_lcc_data *data;
+    HANDLE LogonHandle;
+    ULONG  PackageId;
+    KERB_EXTERNAL_TICKET *msticket;
+    krb5_error_code retval = KRB5_OK;
+
+    if (!is_windows_2000() || is_broken_wow64())
+        return KRB5_FCC_NOFILE;
+
+#ifdef COMMENT
+    /* In at least one case on Win2003 it appears that it is possible 
+     * for the logon session to be authenticated via NTLM and yet for
+     * there to be Kerberos credentials obtained by the LSA on behalf
+     * of the logged in user.  Therefore, we are removing this test
+     * which was meant to avoid the need to perform GetMSTGT() when
+     * there was no possibility of credentials being found.
+     */
+    if (!IsKerberosLogon())
+        return KRB5_FCC_NOFILE;
+#endif
+
+    if (!PackageConnectLookup(&LogonHandle, &PackageId))
+        return KRB5_FCC_NOFILE;
+
+    lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+    if (lid == NULL) {
+        CloseHandle(LogonHandle);
+        return KRB5_CC_NOMEM;
+    }
+
+    lid->ops = &krb5_lcc_ops;
+
+    lid->data = (krb5_pointer) malloc(sizeof(krb5_lcc_data));
+    if (lid->data == NULL) {
+        krb5_xfree(lid);
+        CloseHandle(LogonHandle);
+        return KRB5_CC_NOMEM;
+    }
+
+    lid->magic = KV5M_CCACHE;
+    data = (krb5_lcc_data *)lid->data;    
+    data->LogonHandle = LogonHandle;
+    data->PackageId = PackageId;
+    data->princ = 0;
+
+    data->cc_name = (char *)malloc(strlen(residual)+1);
+    if (data->cc_name == NULL) {
+        krb5_xfree(lid->data);
+        krb5_xfree(lid);
+        CloseHandle(LogonHandle);
+        return KRB5_CC_NOMEM;
+    }
+    strcpy(data->cc_name, residual);
+
+    /*
+     * we must obtain a tgt from the cache in order to determine the principal
+     */
+    if (GetMSTGT(context, data->LogonHandle, data->PackageId, &msticket, FALSE)) {
+        /* convert the ticket */
+        krb5_creds creds;
+        if (!MSCredToMITCred(msticket, msticket->DomainName, context, &creds))
+            retval = KRB5_FCC_INTERNAL;
+        LsaFreeReturnBuffer(msticket);
+
+        if (retval == KRB5_OK)
+            krb5_copy_principal(context, creds.client, &data->princ);
+        krb5_free_cred_contents(context,&creds);
+    } else if (!does_retrieve_ticket_cache_ticket()) {
+        krb5_xfree(data->cc_name);
+        krb5_xfree(lid->data);
+        krb5_xfree(lid);
+        CloseHandle(LogonHandle);
+        return KRB5_FCC_NOFILE;
+    }
+
+    /*
+     * other routines will get errors on open, and callers must expect them,
+     * if cache is non-existent/unusable 
+     */
+    *id = lid;
+    return retval;
+}
+
+/*
+*  return success although we do not do anything
+*  We should delete all tickets belonging to the specified principal
+*/
+
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_remove_cred(krb5_context context, krb5_ccache id, krb5_flags flags,
+                     krb5_creds *creds);
+
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
+{
+    krb5_cc_cursor cursor;
+    krb5_error_code code;
+    krb5_creds cred;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    code = krb5_cc_start_seq_get(context, id, &cursor);
+    if (code) {
+        if (code == KRB5_CC_NOTFOUND)
+            return KRB5_OK;
+        return code;
+    }
+
+    while ( !(code = krb5_cc_next_cred(context, id, &cursor, &cred)) )
+    {
+        if ( krb5_principal_compare(context, princ, cred.client) ) {
+            code = krb5_lcc_remove_cred(context, id, 0, &cred);
+        }
+        krb5_free_cred_contents(context, &cred);
+    }
+
+    if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND)
+    {
+        krb5_cc_end_seq_get(context, id, &cursor);
+        return KRB5_OK;
+    }
+    return code;
+}
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Closes the microsoft lsa cache, invalidates the id, and frees any resources
+ * associated with the cache.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_close(krb5_context context, krb5_ccache id)
+{
+    register int closeval = KRB5_OK;
+    register krb5_lcc_data *data;
+    
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    if (id) {
+        data = (krb5_lcc_data *) id->data;
+
+        if (data) {
+            CloseHandle(data->LogonHandle);
+            krb5_xfree(data);
+        }
+        krb5_xfree(id);
+    }
+    return closeval;
+}
+
+/*
+ * Effects:
+ * Destroys the contents of id.
+ *
+ * Errors:
+ * system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_destroy(krb5_context context, krb5_ccache id)
+{
+    register krb5_lcc_data *data;
+    
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    if (id) { 
+        data = (krb5_lcc_data *) id->data;
+
+        return PurgeAllTickets(data->LogonHandle, data->PackageId) ? KRB5_OK : KRB5_FCC_INTERNAL;
+    }   
+    return KRB5_FCC_INTERNAL;
+}
+
+/*
+ * Effects:
+ * Prepares for a sequential search of the credentials cache.
+ * Returns a krb5_cc_cursor to be used with krb5_lcc_next_cred and
+ * krb5_lcc_end_seq_get.
+ *
+ * If the cache is modified between the time of this call and the time
+ * of the final krb5_lcc_end_seq_get, the results are undefined.
+ *
+ * Errors:
+ * KRB5_CC_NOMEM
+ * KRB5_FCC_INTERNAL - system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
+{
+    krb5_lcc_cursor *lcursor;
+    krb5_lcc_data *data = (krb5_lcc_data *)id->data;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    lcursor = (krb5_lcc_cursor *) malloc(sizeof(krb5_lcc_cursor));
+    if (lcursor == NULL) {
+        *cursor = 0;
+        return KRB5_CC_NOMEM;
+    }
+
+    /*
+     * obtain a tgt to refresh the ccache in case the ticket is expired
+     */
+    if (!GetMSTGT(context, data->LogonHandle, data->PackageId, &lcursor->mstgt, TRUE)) {
+        free(lcursor);
+        *cursor = 0;
+        return KRB5_CC_NOTFOUND;
+    }
+
+#ifdef HAVE_CACHE_INFO_EX2
+    if ( does_query_ticket_cache_ex2() ) {
+        if ( !GetQueryTktCacheResponseEX2(data->LogonHandle, data->PackageId, &lcursor->response.ex2) ) {
+            LsaFreeReturnBuffer(lcursor->mstgt);
+            free(lcursor);
+            *cursor = 0;
+            return KRB5_FCC_INTERNAL;
+        }
+    } else 
+#endif /* HAVE_CACHE_INFO_EX2 */
+    if ( is_windows_xp() ) {
+        if ( !GetQueryTktCacheResponseXP(data->LogonHandle, data->PackageId, &lcursor->response.xp) ) {
+            LsaFreeReturnBuffer(lcursor->mstgt);
+            free(lcursor);
+            *cursor = 0;
+            return KRB5_FCC_INTERNAL;
+        }
+    } else {
+        if ( !GetQueryTktCacheResponseW2K(data->LogonHandle, data->PackageId, &lcursor->response.w2k) ) {
+            LsaFreeReturnBuffer(lcursor->mstgt);
+            free(lcursor);
+            *cursor = 0;
+            return KRB5_FCC_INTERNAL;
+        }
+    }
+    lcursor->index = 0;
+    *cursor = (krb5_cc_cursor) lcursor;
+    return KRB5_OK;
+}
+
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_lcc_start_seq_get.
+ *
+ * Modifes:
+ * cursor
+ * 
+ * Effects:
+ * Fills in creds with the TGT obtained from the MS LSA
+ *
+ * The cursor is updated to indicate TGT retrieval
+ *
+ * Errors:
+ * KRB5_CC_END
+ * KRB5_FCC_INTERNAL - system errors
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, krb5_creds *creds)
+{
+    krb5_lcc_cursor *lcursor = (krb5_lcc_cursor *) *cursor;
+    krb5_lcc_data *data;
+    KERB_EXTERNAL_TICKET *msticket;
+    krb5_error_code  retval = KRB5_OK;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    data = (krb5_lcc_data *)id->data;
+
+  next_cred:
+#ifdef HAVE_CACHE_INFO_EX2
+    if ( does_query_ticket_cache_ex2() ) {
+        if ( lcursor->index >= lcursor->response.ex2->CountOfTickets ) {
+            if (retval == KRB5_OK)
+                return KRB5_CC_END;
+            else {
+                LsaFreeReturnBuffer(lcursor->mstgt);
+                LsaFreeReturnBuffer(lcursor->response.ex2);
+                free(*cursor);
+                *cursor = 0;
+                return retval;
+            }
+        }
+
+        if ( data->flags & KRB5_TC_NOTICKET ) {
+	    if (!CacheInfoEx2ToMITCred( &lcursor->response.ex2->Tickets[lcursor->index++], 
+					context, creds)) {
+                retval = KRB5_FCC_INTERNAL;
+                goto next_cred;
+	    }
+            return KRB5_OK;
+        } else {
+            if (!GetMSCacheTicketFromCacheInfoEX2(data->LogonHandle, data->PackageId,
+                                                      &lcursor->response.ex2->Tickets[lcursor->index++],&msticket)) {
+                retval = KRB5_FCC_INTERNAL;
+                goto next_cred;
+            }
+        }
+    } else 
+#endif /* HAVE_CACHE_INFO_EX2 */
+    if ( is_windows_xp() ) {
+        if ( lcursor->index >= lcursor->response.xp->CountOfTickets ) {
+            if (retval == KRB5_OK)
+                return KRB5_CC_END;
+            else {
+                LsaFreeReturnBuffer(lcursor->mstgt);
+                LsaFreeReturnBuffer(lcursor->response.xp);
+                free(*cursor);
+                *cursor = 0;
+                return retval;
+            }
+        }
+
+        if (!GetMSCacheTicketFromCacheInfoXP(data->LogonHandle, data->PackageId,
+                                            &lcursor->response.xp->Tickets[lcursor->index++],&msticket)) {
+            retval = KRB5_FCC_INTERNAL;
+            goto next_cred;
+        }
+    } else {
+        if ( lcursor->index >= lcursor->response.w2k->CountOfTickets ) {
+            if (retval == KRB5_OK)
+                return KRB5_CC_END;
+            else {
+                LsaFreeReturnBuffer(lcursor->mstgt);
+                LsaFreeReturnBuffer(lcursor->response.w2k);
+                free(*cursor);
+                *cursor = 0;
+                return retval;
+            }
+        }
+
+        if (!GetMSCacheTicketFromCacheInfoW2K(data->LogonHandle, data->PackageId,
+                                            &lcursor->response.w2k->Tickets[lcursor->index++],&msticket)) {
+            retval = KRB5_FCC_INTERNAL;
+            goto next_cred;
+        }
+    }
+
+    /* Don't return tickets with NULL Session Keys */
+    if ( IsMSSessionKeyNull(&msticket->SessionKey) ) {
+        LsaFreeReturnBuffer(msticket);
+        goto next_cred;
+    }
+
+    /* convert the ticket */
+#ifdef HAVE_CACHE_INFO_EX2
+    if ( does_query_ticket_cache_ex2() ) {
+        if (!MSCredToMITCred(msticket, lcursor->response.ex2->Tickets[lcursor->index-1].ClientRealm, context, creds))
+            retval = KRB5_FCC_INTERNAL;
+    } else 
+#endif /* HAVE_CACHE_INFO_EX2 */
+    if ( is_windows_xp() ) {
+        if (!MSCredToMITCred(msticket, lcursor->response.xp->Tickets[lcursor->index-1].ClientRealm, context, creds))
+            retval = KRB5_FCC_INTERNAL;
+    } else {
+        if (!MSCredToMITCred(msticket, lcursor->mstgt->DomainName, context, creds))
+            retval = KRB5_FCC_INTERNAL;
+    }
+    LsaFreeReturnBuffer(msticket);
+    return retval;
+}
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_lcc_start_seq_get.
+ *
+ * Modifies:
+ * id, cursor
+ *
+ * Effects:
+ * Finishes sequential processing of the file credentials ccache id,
+ * and invalidates the cursor (it must never be used after this call).
+ */
+/* ARGSUSED */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
+{
+    krb5_lcc_cursor *lcursor = (krb5_lcc_cursor *) *cursor;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    if ( lcursor ) {
+        LsaFreeReturnBuffer(lcursor->mstgt);
+#ifdef HAVE_CACHE_INFO_EX2
+        if ( does_query_ticket_cache_ex2() )
+            LsaFreeReturnBuffer(lcursor->response.ex2);
+        else 
+#endif /* HAVE_CACHE_INFO_EX2 */
+        if ( is_windows_xp() )
+            LsaFreeReturnBuffer(lcursor->response.xp);
+        else
+            LsaFreeReturnBuffer(lcursor->response.w2k);
+        free(*cursor);
+    }
+    *cursor = 0;
+
+    return KRB5_OK;
+}
+
+
+/*
+ * Errors:
+ * KRB5_CC_READONLY - not supported
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_generate_new (krb5_context context, krb5_ccache *id)
+{
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    return KRB5_CC_READONLY;
+}
+
+/*
+ * Requires:
+ * id is a ms lsa credential cache
+ * 
+ * Returns:
+ *   The ccname specified during the krb5_lcc_resolve call
+ */
+static const char * KRB5_CALLCONV
+krb5_lcc_get_name (krb5_context context, krb5_ccache id)
+{
+
+    if (!is_windows_2000())
+        return "";
+
+    if ( !id )
+        return "";
+
+    return (char *) ((krb5_lcc_data *) id->data)->cc_name;
+}
+
+/*
+ * Modifies:
+ * id, princ
+ *
+ * Effects:
+ * Retrieves the primary principal from id, as set with
+ * krb5_lcc_initialize.  The principal is returned is allocated
+ * storage that must be freed by the caller via krb5_free_principal.
+ *
+ * Errors:
+ * system errors
+ * KRB5_CC_NOT_KTYPE
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ)
+{
+    krb5_lcc_data *data = (krb5_lcc_data *)id->data;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    /* obtain principal */
+    if (data->princ)
+        return krb5_copy_principal(context, data->princ, princ);
+    else {
+        /*
+         * we must obtain a tgt from the cache in order to determine the principal
+         */
+        KERB_EXTERNAL_TICKET *msticket;
+        if (GetMSTGT(context, data->LogonHandle, data->PackageId, &msticket, FALSE)) {
+            /* convert the ticket */
+            krb5_creds creds;
+            if (!MSCredToMITCred(msticket, msticket->DomainName, context, &creds))
+            {
+                LsaFreeReturnBuffer(msticket);
+                return KRB5_FCC_INTERNAL;
+            }
+            LsaFreeReturnBuffer(msticket);
+
+            krb5_copy_principal(context, creds.client, &data->princ);
+            krb5_free_cred_contents(context,&creds);
+            return krb5_copy_principal(context, data->princ, princ);
+        }    
+    }
+    return KRB5_CC_NOTFOUND;
+}
+
+     
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, 
+                  krb5_creds *mcreds, krb5_creds *creds)
+{
+    krb5_error_code kret = KRB5_OK;
+    krb5_lcc_data *data = (krb5_lcc_data *)id->data;
+    KERB_EXTERNAL_TICKET *msticket = 0, *mstgt = 0, *mstmp = 0;
+    krb5_creds * mcreds_noflags = 0;
+    krb5_creds   fetchcreds;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    memset(&fetchcreds, 0, sizeof(krb5_creds));
+
+    /* first try to find out if we have an existing ticket which meets the requirements */
+    kret = krb5_cc_retrieve_cred_default (context, id, whichfields, mcreds, creds);
+    if ( !kret )
+        return KRB5_OK;
+    
+    /* if not, we must try to get a ticket without specifying any flags or etypes */
+    kret = krb5_copy_creds(context, mcreds, &mcreds_noflags);
+    if (kret)
+        goto cleanup;
+    mcreds_noflags->ticket_flags = 0;
+    mcreds_noflags->keyblock.enctype = 0;
+
+    if (!GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, mcreds_noflags, &msticket)) {
+        kret = KRB5_CC_NOTFOUND;
+        goto cleanup;
+    }
+
+    /* try again to find out if we have an existing ticket which meets the requirements */
+    kret = krb5_cc_retrieve_cred_default (context, id, whichfields, mcreds, creds);
+    if ( !kret )
+        goto cleanup;
+
+    /* if not, obtain a ticket using the request flags and enctype even though it may not
+     * be stored in the LSA cache for future use.
+     */
+    if ( msticket ) {
+        LsaFreeReturnBuffer(msticket);
+        msticket = 0;
+    }
+
+    if (!GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, mcreds, &msticket)) {
+        kret = KRB5_CC_NOTFOUND;
+        goto cleanup;
+    }
+
+    /* convert the ticket */
+    if ( !is_windows_xp() || !does_retrieve_ticket_cache_ticket() ) {
+        if ( PreserveInitialTicketIdentity() )
+            GetMSTGT(context, data->LogonHandle, data->PackageId, &mstgt, FALSE);
+
+        if (!MSCredToMITCred(msticket, mstgt ? mstgt->DomainName : msticket->DomainName, context, &fetchcreds))
+        {
+            kret = KRB5_FCC_INTERNAL;
+            goto cleanup;
+        }
+    } else {
+        /* We can obtain the correct client realm for a ticket by walking the
+         * cache contents until we find the matching service ticket.
+         */
+        PKERB_QUERY_TKT_CACHE_EX_RESPONSE pResponse = 0;
+        unsigned int i;
+
+        if (!GetQueryTktCacheResponseXP( data->LogonHandle, data->PackageId, &pResponse)) {
+            kret = KRB5_FCC_INTERNAL;
+            goto cleanup;
+        }
+
+        for ( i=0; i<pResponse->CountOfTickets; i++ ) {
+            if (!GetMSCacheTicketFromCacheInfoXP(data->LogonHandle, data->PackageId,
+                                                  &pResponse->Tickets[i],&mstmp)) {
+                continue;
+            }
+
+            if ( KerbExternalTicketMatch(msticket,mstmp) )
+                break;
+
+            LsaFreeReturnBuffer(mstmp);
+            mstmp = 0;
+        }
+
+        if (!MSCredToMITCred(msticket, mstmp ? pResponse->Tickets[i].ClientRealm : msticket->DomainName, context, &fetchcreds))
+        {
+            LsaFreeReturnBuffer(pResponse);
+            kret = KRB5_FCC_INTERNAL;
+            goto cleanup;
+        }
+        LsaFreeReturnBuffer(pResponse);
+    }
+
+
+    /* check to see if this ticket matches the request using logic from
+     * krb5_cc_retrieve_cred_default()
+     */
+    if ( krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds) ) {
+        *creds = fetchcreds;
+    } else {
+        krb5_free_cred_contents(context, &fetchcreds);
+        kret = KRB5_CC_NOTFOUND;
+    }
+
+  cleanup:
+    if ( mstmp )
+        LsaFreeReturnBuffer(mstmp);
+    if ( mstgt )
+        LsaFreeReturnBuffer(mstgt);
+    if ( msticket )
+        LsaFreeReturnBuffer(msticket);
+    if ( mcreds_noflags )
+        krb5_free_creds(context, mcreds_noflags);
+    return kret;
+}
+
+
+/*
+ * We can't write to the MS LSA cache.  So we request the cache to obtain a ticket for the same
+ * principal in the hope that next time the application requires a ticket for the service it
+ * is attempt to store, the retrieved ticket will be good enough.
+ *
+ * Errors:
+ * KRB5_CC_READONLY - not supported
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
+{
+    krb5_error_code kret = KRB5_OK;
+    krb5_lcc_data *data = (krb5_lcc_data *)id->data;
+    KERB_EXTERNAL_TICKET *msticket = 0, *msticket2 = 0;
+    krb5_creds * creds_noflags = 0;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+#ifdef KERB_SUBMIT_TICKET
+    /* we can use the new KerbSubmitTicketMessage to store the ticket */
+    if (KerbSubmitTicket( data->LogonHandle, data->PackageId, context, creds ))
+        return KRB5_OK;
+#endif /* KERB_SUBMIT_TICKET */
+
+    /* If not, lets try to obtain a matching ticket from the KDC */
+    if ( creds->ticket_flags != 0 && creds->keyblock.enctype != 0 ) {
+        /* if not, we must try to get a ticket without specifying any flags or etypes */
+        kret = krb5_copy_creds(context, creds, &creds_noflags);
+        if (kret == 0) {
+            creds_noflags->ticket_flags = 0;
+            creds_noflags->keyblock.enctype = 0;
+
+            GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, creds_noflags, &msticket2);
+            krb5_free_creds(context, creds_noflags);
+        }
+    }
+
+    GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, creds, &msticket);
+    if (msticket || msticket2) {
+        if (msticket)
+            LsaFreeReturnBuffer(msticket);
+        if (msticket2)
+            LsaFreeReturnBuffer(msticket2);
+        return KRB5_OK;
+    }
+    return KRB5_CC_READONLY;
+}
+
+/* 
+ * Individual credentials can be implemented differently depending
+ * on the operating system version.  (undocumented.)
+ * 
+ * Errors:
+ *    KRB5_CC_READONLY: 
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_remove_cred(krb5_context context, krb5_ccache id, krb5_flags flags,
+                     krb5_creds *creds)
+{
+    krb5_lcc_data *data = (krb5_lcc_data *)id->data;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    if (!is_windows_xp()) {
+        if ( PurgeTicket2000( data->LogonHandle, data->PackageId, context, creds) )
+            return KRB5_OK;
+    } else {
+        if ( PurgeTicketXP( data->LogonHandle, data->PackageId, context, flags, creds) )
+            return KRB5_OK;
+    }
+
+    return KRB5_CC_READONLY;
+}
+
+
+/*
+ * Effects:
+ *   Set
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
+{
+    krb5_lcc_data *data = (krb5_lcc_data *)id->data;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    data->flags = flags;
+    return KRB5_OK;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_lcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags)
+{
+    krb5_lcc_data *data = (krb5_lcc_data *)id->data;
+
+    if (!is_windows_2000())
+        return KRB5_FCC_NOFILE;
+
+    *flags = data->flags;
+    return KRB5_OK;
+}
+
+const krb5_cc_ops krb5_lcc_ops = {
+     0,
+     "MSLSA",
+     krb5_lcc_get_name,
+     krb5_lcc_resolve,
+     krb5_lcc_generate_new,
+     krb5_lcc_initialize,
+     krb5_lcc_destroy,
+     krb5_lcc_close,
+     krb5_lcc_store,
+     krb5_lcc_retrieve,
+     krb5_lcc_get_principal,
+     krb5_lcc_start_seq_get,
+     krb5_lcc_next_cred,
+     krb5_lcc_end_seq_get,
+     krb5_lcc_remove_cred,
+     krb5_lcc_set_flags,
+     krb5_lcc_get_flags,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+};
+#endif /* _WIN32 */
diff --git a/krb5-1-6/src/lib/krb5/ccache/cc_retr.c b/krb5-1-6/src/lib/krb5/ccache/cc_retr.c
new file mode 100644
index 000000000..43c9da7d0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cc_retr.c
@@ -0,0 +1,388 @@
+/*
+ * lib/krb5/ccache/cc_retr.c
+ *
+ * Copyright 1990,1991,1999 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+#include "k5-int.h"
+#include "cc-int.h"
+
+#define KRB5_OK 0
+
+#define set(bits) (whichfields & bits)
+#define flags_match(a,b) (((a) & (b)) == (a))
+#define times_match_exact(t1,t2) (memcmp((char *)(t1), (char *)(t2), sizeof(*(t1))) == 0)
+
+static krb5_boolean
+times_match(const krb5_ticket_times *t1, const krb5_ticket_times *t2)
+{
+    if (t1->renew_till) {
+	if (t1->renew_till > t2->renew_till)
+	    return FALSE;		/* this one expires too late */
+    }
+    if (t1->endtime) {
+	if (t1->endtime > t2->endtime)
+	    return FALSE;		/* this one expires too late */
+    }
+    /* only care about expiration on a times_match */
+    return TRUE;
+}
+
+static krb5_boolean
+standard_fields_match(krb5_context context, const krb5_creds *mcreds, const krb5_creds *creds)
+{
+  return (krb5_principal_compare(context, mcreds->client,creds->client)
+	  && krb5_principal_compare(context, mcreds->server,creds->server));
+}
+
+/* only match the server name portion, not the server realm portion */
+
+static krb5_boolean
+srvname_match(krb5_context context, const krb5_creds *mcreds, const krb5_creds *creds)
+{
+    krb5_boolean retval;
+    krb5_principal_data p1, p2;
+    
+    retval = krb5_principal_compare(context, mcreds->client,creds->client);
+    if (retval != TRUE)
+	return retval;
+    /*
+     * Hack to ignore the server realm for the purposes of the compare.
+     */
+    p1 = *mcreds->server;
+    p2 = *creds->server;
+    p1.realm = p2.realm;
+    return krb5_principal_compare(context, &p1, &p2);
+}
+
+static krb5_boolean
+authdata_match(krb5_authdata *const *mdata, krb5_authdata *const *data)
+{
+    const krb5_authdata *mdatap, *datap;
+
+    if (mdata == data)
+      return TRUE;
+
+    if (mdata == NULL)
+	return *data == NULL;
+	
+    if (data == NULL)
+	return *mdata == NULL;
+    
+    while ((mdatap = *mdata) && (datap = *data)) {
+      if ((mdatap->ad_type != datap->ad_type) ||
+          (mdatap->length != datap->length) ||
+          (memcmp ((char *)mdatap->contents,
+		 (char *)datap->contents, (unsigned) mdatap->length) != 0))
+          return FALSE;
+      mdata++;
+      data++;
+    }
+    return (*mdata == NULL) && (*data == NULL);
+}
+
+static krb5_boolean
+data_match(const krb5_data *data1, const krb5_data *data2)
+{
+    if (!data1) {
+	if (!data2)
+	    return TRUE;
+	else
+	    return FALSE;
+    }
+    if (!data2) return FALSE;
+
+    if (data1->length != data2->length)
+	return FALSE;
+    else
+	return memcmp(data1->data, data2->data, (unsigned) data1->length) 
+	  ? FALSE : TRUE;
+}
+
+static int
+pref (krb5_enctype my_ktype, int nktypes, krb5_enctype *ktypes)
+{
+  int i;
+  for (i = 0; i < nktypes; i++)
+    if (my_ktype == ktypes[i])
+      return i;
+  return -1;
+}
+
+/*
+ * Effects:
+ * Searches the credentials cache for a credential matching mcreds,
+ * with the fields specified by whichfields.  If one if found, it is
+ * returned in creds, which should be freed by the caller with
+ * krb5_free_credentials().
+ * 
+ * The fields are interpreted in the following way (all constants are
+ * preceded by KRB5_TC_).  MATCH_IS_SKEY requires the is_skey field to
+ * match exactly.  MATCH_TIMES requires the requested lifetime to be
+ * at least as great as that specified; MATCH_TIMES_EXACT requires the
+ * requested lifetime to be exactly that specified.  MATCH_FLAGS
+ * requires only the set bits in mcreds be set in creds;
+ * MATCH_FLAGS_EXACT requires all bits to match.
+ *
+ * Flag SUPPORTED_KTYPES means check all matching entries that have
+ * any supported enctype (according to tgs_enctypes) and return the one
+ * with the enctype listed earliest.  Return CC_NOT_KTYPE if a match
+ * is found *except* for having a supported enctype.
+ *
+ * Errors:
+ * system errors
+ * permission errors
+ * KRB5_CC_NOMEM
+ * KRB5_CC_NOT_KTYPE
+ */
+
+krb5_boolean
+krb5int_cc_creds_match_request(krb5_context context, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds)
+{
+    if (((set(KRB5_TC_MATCH_SRV_NAMEONLY) &&
+		   srvname_match(context, mcreds, creds)) ||
+	       standard_fields_match(context, mcreds, creds))
+	      &&
+	      (! set(KRB5_TC_MATCH_IS_SKEY) ||
+	       mcreds->is_skey == creds->is_skey)
+	      &&
+	      (! set(KRB5_TC_MATCH_FLAGS_EXACT) ||
+	       mcreds->ticket_flags == creds->ticket_flags)
+	      &&
+	      (! set(KRB5_TC_MATCH_FLAGS) ||
+	       flags_match(mcreds->ticket_flags, creds->ticket_flags))
+	      &&
+	      (! set(KRB5_TC_MATCH_TIMES_EXACT) ||
+	       times_match_exact(&mcreds->times, &creds->times))
+	      &&
+	      (! set(KRB5_TC_MATCH_TIMES) ||
+	       times_match(&mcreds->times, &creds->times))
+	      &&
+	      ( ! set(KRB5_TC_MATCH_AUTHDATA) ||
+	       authdata_match(mcreds->authdata, creds->authdata))
+	      &&
+	      (! set(KRB5_TC_MATCH_2ND_TKT) ||
+	       data_match (&mcreds->second_ticket, &creds->second_ticket))
+	      &&
+	     ((! set(KRB5_TC_MATCH_KTYPE))||
+		(mcreds->keyblock.enctype == creds->keyblock.enctype)))
+        return TRUE;
+    return FALSE;
+}
+
+static krb5_error_code
+krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id,
+			   krb5_flags whichfields, krb5_creds *mcreds,
+			   krb5_creds *creds, int nktypes, krb5_enctype *ktypes)
+{
+     /* This function could be considerably faster if it kept indexing */
+     /* information.. sounds like a "next version" idea to me. :-) */
+
+     krb5_cc_cursor cursor;
+     krb5_error_code kret;
+     krb5_error_code nomatch_err = KRB5_CC_NOTFOUND;
+     struct {
+       krb5_creds creds;
+       int pref;
+     } fetched, best;
+     int have_creds = 0;
+     krb5_flags oflags = 0;
+#define fetchcreds (fetched.creds)
+
+     kret = krb5_cc_get_flags(context, id, &oflags);
+     if (kret != KRB5_OK)
+	  return kret;
+     if (oflags & KRB5_TC_OPENCLOSE)
+	 (void) krb5_cc_set_flags(context, id, oflags & ~KRB5_TC_OPENCLOSE);
+     kret = krb5_cc_start_seq_get(context, id, &cursor);
+     if (kret != KRB5_OK) {
+	  if (oflags & KRB5_TC_OPENCLOSE)
+	       krb5_cc_set_flags(context, id, oflags);
+	  return kret;
+     }
+
+     while ((kret = krb5_cc_next_cred(context, id, &cursor, &fetchcreds)) == KRB5_OK) {
+      if (krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds))
+      {
+	      if (ktypes) {
+		  fetched.pref = pref (fetchcreds.keyblock.enctype,
+				       nktypes, ktypes);
+		  if (fetched.pref < 0)
+		      nomatch_err = KRB5_CC_NOT_KTYPE;
+		  else if (!have_creds || fetched.pref < best.pref) {
+		      if (have_creds)
+			  krb5_free_cred_contents (context, &best.creds);
+		      else
+			  have_creds = 1;
+		      best = fetched;
+		      continue;
+		  }
+	      } else {
+		  krb5_cc_end_seq_get(context, id, &cursor);
+		  *creds = fetchcreds;
+		  if (oflags & KRB5_TC_OPENCLOSE)
+		      krb5_cc_set_flags(context, id, oflags);
+		  return KRB5_OK;
+	      }
+	  }
+
+	  /* This one doesn't match */
+	  krb5_free_cred_contents(context, &fetchcreds);
+     }
+
+     /* If we get here, a match wasn't found */
+     krb5_cc_end_seq_get(context, id, &cursor);
+     if (oflags & KRB5_TC_OPENCLOSE)
+	 krb5_cc_set_flags(context, id, oflags);
+     if (have_creds) {
+	 *creds = best.creds;
+	 return KRB5_OK;
+     } else
+	 return nomatch_err;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_retrieve_cred_default (krb5_context context, krb5_ccache id, krb5_flags flags, krb5_creds *mcreds, krb5_creds *creds)
+{
+    krb5_enctype *ktypes;
+    int nktypes;
+    krb5_error_code ret;
+
+    if (flags & KRB5_TC_SUPPORTED_KTYPES) {
+	ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes);
+	if (ret)
+	    return ret;
+	nktypes = 0;
+	while (ktypes[nktypes])
+	    nktypes++;
+
+	ret = krb5_cc_retrieve_cred_seq (context, id, flags, mcreds, creds,
+					 nktypes, ktypes);
+	free (ktypes);
+	return ret;
+    } else {
+	return krb5_cc_retrieve_cred_seq (context, id, flags, mcreds, creds,
+					  0, 0);
+    }
+}
+
+/* The following function duplicates some of the functionality above and */
+/* should probably be merged with it at some point.  It is used by the   */
+/* CCAPI krb5_cc_remove to figure out if the opaque credentials object   */
+/* returned by the CCAPI is the same creds as the caller passed in.      */
+/* Unlike the code above it requires that all structures be identical.   */
+
+krb5_boolean KRB5_CALLCONV 
+krb5_creds_compare (krb5_context in_context,
+                    krb5_creds *in_creds,
+                    krb5_creds *in_compare_creds)
+{
+    /* Set to 0 when we hit the first mismatch and then fall through */
+    int equal = 1;
+    
+    if (equal) {
+        equal = krb5_principal_compare (in_context, in_creds->client, 
+                                        in_compare_creds->client);
+    }
+    
+    if (equal) {
+        equal = krb5_principal_compare (in_context, in_creds->server, 
+                                        in_compare_creds->server);
+    }
+    
+    if (equal) {
+        equal = (in_creds->keyblock.enctype == in_compare_creds->keyblock.enctype &&
+                 in_creds->keyblock.length  == in_compare_creds->keyblock.length &&
+                 (!in_creds->keyblock.length ||
+                  !memcmp (in_creds->keyblock.contents, in_compare_creds->keyblock.contents,
+                           in_creds->keyblock.length)));
+    }
+    
+    if (equal) {   
+        equal = (in_creds->times.authtime   == in_compare_creds->times.authtime &&
+                 in_creds->times.starttime  == in_compare_creds->times.starttime &&
+                 in_creds->times.endtime    == in_compare_creds->times.endtime &&
+                 in_creds->times.renew_till == in_compare_creds->times.renew_till);
+    }
+    
+    if (equal) {
+        equal = (in_creds->is_skey == in_compare_creds->is_skey);
+    } 
+    
+    if (equal) {
+        equal = (in_creds->ticket_flags == in_compare_creds->ticket_flags);
+    }
+    
+    if (equal) {
+        krb5_address **addresses = in_creds->addresses;
+        krb5_address **compare_addresses = in_compare_creds->addresses;
+        unsigned int i;
+        
+        if (addresses && compare_addresses) {
+            for (i = 0; (equal && addresses[i] && compare_addresses[i]); i++) {
+                equal = krb5_address_compare (in_context, addresses[i],
+                                              compare_addresses[i]);
+            }
+            if (equal) { equal = (!addresses[i] && !compare_addresses[i]); }
+        } else {
+            if (equal) { equal = (!addresses && !compare_addresses); }
+        }
+    }
+    
+    if (equal) {
+        equal = (in_creds->ticket.length  == in_compare_creds->ticket.length &&
+                 (!in_creds->ticket.length ||
+                  !memcmp (in_creds->ticket.data, in_compare_creds->ticket.data,
+                           in_creds->ticket.length)));
+    }
+    
+    if (equal) {
+        equal = (in_creds->second_ticket.length  == in_compare_creds->second_ticket.length &&
+                 (!in_creds->second_ticket.length ||
+                  !memcmp (in_creds->second_ticket.data, in_compare_creds->second_ticket.data,
+                           in_creds->second_ticket.length)));
+    }
+    
+    if (equal) {
+        krb5_authdata **authdata = in_creds->authdata;
+        krb5_authdata **compare_authdata = in_compare_creds->authdata;
+        unsigned int i;
+        
+        if (authdata && compare_authdata) { 
+            for (i = 0; (equal && authdata[i] && compare_authdata[i]); i++) {
+                equal = (authdata[i]->ad_type == compare_authdata[i]->ad_type &&
+                         authdata[i]->length  == compare_authdata[i]->length &&
+                         (!authdata[i]->length || 
+                          !memcmp (authdata[i]->contents, compare_authdata[i]->contents,
+                                   authdata[i]->length)));
+            }
+            if (equal) { equal = (!authdata[i] && !compare_authdata[i]); }
+        } else {
+            if (equal) { equal = (!authdata && !compare_authdata); }
+        }
+    }
+    
+    return equal;
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccapi/Makefile.in b/krb5-1-6/src/lib/krb5/ccache/ccapi/Makefile.in
new file mode 100644
index 000000000..201555a55
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccapi/Makefile.in
@@ -0,0 +1,26 @@
+thisconfigdir=./../..
+myfulldir=lib/krb5/ccache/ccapi
+mydir=ccache/ccapi
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = $(WIN_INCLUDES)
+DEFS=
+
+##DOS##WIN_INCLUDES = -I$(SRCTOP)\windows\lib
+
+##DOS##BUILDTOP = ..\..\..\..
+##DOS##PREFIXDIR = ccache\file
+##DOS##OBJFILE = $(OUTPRE)file.lst
+
+STLIBOBJS 	= \
+	stdcc.o \
+	stdcc_util.o \
+	winccld.o
+
+OBJS 	= $(OUTPRE)stdcc.$(OBJEXT) $(OUTPRE)stdcc_util.$(OBJEXT) $(OUTPRE)winccld.$(OBJEXT)
+
+SRCS 	= $(srcdir)/stdcc.c $(srcdir)/stdcc_util.c $(srcdir)/winccld.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.c b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.c
new file mode 100644
index 000000000..36bc780e2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.c
@@ -0,0 +1,1613 @@
+/*
+ * stdcc.c - additions to the Kerberos 5 library to support the memory
+ *	 credentical cache API
+ *	
+ * Written by Frank Dabek July 1998
+ * Updated by Jeffrey Altman June 2006
+ *
+ * Copyright 1998, 1999, 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+#include "stdcc.h"
+#include "stdcc_util.h"
+#include "string.h"
+#include <stdio.h>
+
+#if defined(_WIN32)
+#include "winccld.h"	
+#endif
+
+#ifndef CC_API_VER2
+#define CC_API_VER2
+#endif
+
+#ifdef DEBUG
+#if defined(_WIN32)
+#include <io.h>
+#define SHOW_DEBUG(buf)   MessageBox((HWND)NULL, (buf), "ccapi debug", MB_OK)
+#endif
+	/* XXX need macintosh debugging statement if we want to debug */
+	/* on the mac */
+#else
+#define SHOW_DEBUG(buf)
+#endif
+
+#ifdef USE_CCAPI_V3
+cc_context_t gCntrlBlock = NULL;
+cc_int32 gCCVersion = 0;
+#else
+apiCB *gCntrlBlock = NULL;
+#endif
+
+/*
+ * declare our global object wanna-be
+ * must be installed in ccdefops.c
+ */
+
+krb5_cc_ops krb5_cc_stdcc_ops = {
+      0,
+      "API",
+#ifdef USE_CCAPI_V3
+      krb5_stdccv3_get_name,
+      krb5_stdccv3_resolve,
+      krb5_stdccv3_generate_new,
+      krb5_stdccv3_initialize,
+      krb5_stdccv3_destroy,
+      krb5_stdccv3_close,
+      krb5_stdccv3_store,
+      krb5_stdccv3_retrieve,
+      krb5_stdccv3_get_principal,
+      krb5_stdccv3_start_seq_get,
+      krb5_stdccv3_next_cred,
+      krb5_stdccv3_end_seq_get,
+      krb5_stdccv3_remove, 
+      krb5_stdccv3_set_flags,
+      krb5_stdccv3_get_flags,
+      krb5_stdccv3_ptcursor_new,
+      krb5_stdccv3_ptcursor_next,
+      krb5_stdccv3_ptcursor_free,
+      NULL,
+      NULL,
+      NULL,
+#else
+      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,
+      krb5_stdcc_get_flags,
+      NULL,
+      NULL,
+      NULL,
+      NULL,
+      NULL,
+      NULL,
+#endif
+};
+
+#if defined(_WIN32)
+/*
+ * cache_changed be called after the cache changes.
+ * A notification message is is posted out to all top level
+ * windows so that they may recheck the cache based on the
+ * changes made.  We register a unique message type with which
+ * we'll communicate to all other processes. 
+ */
+static void cache_changed()
+{
+	static unsigned int message = 0;
+	
+	if (message == 0)
+		message = RegisterWindowMessage(WM_KERBEROS5_CHANGED);
+
+	PostMessage(HWND_BROADCAST, message, 0, 0);
+}
+#else /* _WIN32 */
+
+static void cache_changed()
+{
+	return;
+}
+#endif /* _WIN32 */
+
+struct err_xlate
+{
+	int	cc_err;
+	krb5_error_code	krb5_err;
+};
+
+static const struct err_xlate err_xlate_table[] =
+{
+#ifdef USE_CCAPI_V3
+        { ccIteratorEnd,			KRB5_CC_END },
+        { ccErrBadParam,			KRB5_FCC_INTERNAL },
+        { ccErrNoMem, 				KRB5_CC_NOMEM },
+        { ccErrInvalidContext, 			KRB5_FCC_NOFILE },
+        { ccErrInvalidCCache,			KRB5_FCC_NOFILE },
+        { ccErrInvalidString,			KRB5_FCC_INTERNAL },
+        { ccErrInvalidCredentials,		KRB5_FCC_INTERNAL },
+        { ccErrInvalidCCacheIterator,		KRB5_FCC_INTERNAL },
+        { ccErrInvalidCredentialsIterator,	KRB5_FCC_INTERNAL },
+        { ccErrInvalidLock,			KRB5_FCC_INTERNAL },
+        { ccErrBadName,				KRB5_CC_BADNAME },
+        { ccErrBadCredentialsVersion,		KRB5_FCC_INTERNAL },
+        { ccErrBadAPIVersion,			KRB5_FCC_INTERNAL },
+        { ccErrContextLocked,			KRB5_FCC_INTERNAL },
+        { ccErrContextUnlocked,			KRB5_FCC_INTERNAL },
+        { ccErrCCacheLocked,			KRB5_FCC_INTERNAL },
+        { ccErrCCacheUnlocked,			KRB5_FCC_INTERNAL },
+        { ccErrBadLockType,			KRB5_FCC_INTERNAL },
+        { ccErrNeverDefault,			KRB5_FCC_INTERNAL },
+        { ccErrCredentialsNotFound,		KRB5_CC_NOTFOUND },
+        { ccErrCCacheNotFound,			KRB5_FCC_NOFILE },
+        { ccErrContextNotFound,			KRB5_FCC_NOFILE },
+        { ccErrServerUnavailable,		KRB5_CC_IO },
+        { ccErrServerInsecure,			KRB5_CC_IO },
+        { ccErrServerCantBecomeUID,		KRB5_CC_IO },
+        { ccErrTimeOffsetNotSet,		KRB5_FCC_INTERNAL },
+        { ccErrBadInternalMessage,		KRB5_FCC_INTERNAL },
+        { ccErrNotImplemented,			KRB5_FCC_INTERNAL },
+#else
+	{ CC_BADNAME,				KRB5_CC_BADNAME },
+	{ CC_NOTFOUND,				KRB5_CC_NOTFOUND },
+	{ CC_END,				KRB5_CC_END },
+	{ CC_IO,				KRB5_CC_IO },
+	{ CC_WRITE,				KRB5_CC_WRITE },
+	{ CC_NOMEM,				KRB5_CC_NOMEM },
+	{ CC_FORMAT,				KRB5_CC_FORMAT },
+	{ CC_WRITE,				KRB5_CC_WRITE },
+	{ CC_LOCKED,				KRB5_FCC_INTERNAL /* XXX */ },
+	{ CC_BAD_API_VERSION,			KRB5_FCC_INTERNAL /* XXX */ },
+	{ CC_NO_EXIST,				KRB5_FCC_NOFILE },
+	{ CC_NOT_SUPP,				KRB5_FCC_INTERNAL /* XXX */ },
+	{ CC_BAD_PARM,				KRB5_FCC_INTERNAL /* XXX */ },
+	{ CC_ERR_CACHE_ATTACH,			KRB5_FCC_INTERNAL /* XXX */ },
+	{ CC_ERR_CACHE_RELEASE,			KRB5_FCC_INTERNAL /* XXX */ },
+	{ CC_ERR_CACHE_FULL,			KRB5_FCC_INTERNAL /* XXX */ },
+	{ CC_ERR_CRED_VERSION,			KRB5_FCC_INTERNAL /* XXX */ },
+#endif
+	{ 0,					0 }
+};
+
+/* Note: cc_err_xlate is NOT idempotent.  Don't call it multiple times.  */
+static krb5_error_code cc_err_xlate(int err)
+{
+    const struct err_xlate *p;
+    
+#ifdef USE_CCAPI_V3
+    if (err == ccNoError)
+        return 0;
+#else
+    if (err == CC_NOERROR)
+        return 0;
+#endif
+    
+    for (p = err_xlate_table; p->cc_err; p++) {
+        if (err == p->cc_err)
+            return p->krb5_err;
+    }
+    
+    return KRB5_FCC_INTERNAL;
+}
+
+
+#ifdef USE_CCAPI_V3
+
+static krb5_error_code stdccv3_get_timeoffset (krb5_context in_context,
+                                               cc_ccache_t  in_ccache)
+{
+    krb5_error_code err = 0;
+    
+    if (gCCVersion >= ccapi_version_5) {
+        krb5_os_context os_ctx = (krb5_os_context) in_context->os_context;
+        cc_time_t time_offset = 0;
+    
+        err = cc_ccache_get_kdc_time_offset (in_ccache, cc_credentials_v5,
+                                             &time_offset);
+    
+        if (!err) {
+            os_ctx->time_offset = time_offset;
+            os_ctx->usec_offset = 0;
+            os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
+                                KRB5_OS_TOFFSET_VALID);
+        }
+        
+        if (err == ccErrTimeOffsetNotSet) {
+            err = 0;  /* okay if there is no time offset */
+        }
+    }
+    
+    return err; /* Don't translate.  Callers will translate for us */
+}
+
+static krb5_error_code stdccv3_set_timeoffset (krb5_context in_context,
+                                               cc_ccache_t  in_ccache)
+{
+    krb5_error_code err = 0;
+    
+    if (gCCVersion >= ccapi_version_5) {
+        krb5_os_context os_ctx = (krb5_os_context) in_context->os_context;
+        
+        if (!err && os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) {
+            err = cc_ccache_set_kdc_time_offset (in_ccache, 
+                                                 cc_credentials_v5,
+                                                 os_ctx->time_offset);
+        }
+    }
+    
+    return err; /* Don't translate.  Callers will translate for us */
+}
+
+static krb5_error_code stdccv3_setup (krb5_context context,
+                                      stdccCacheDataPtr ccapi_data)
+{
+    krb5_error_code err = 0;
+    
+    if (!err && !gCntrlBlock) {
+        err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL);
+    }
+    
+    if (!err && ccapi_data && !ccapi_data->NamedCache) {
+        /* ccache has not been opened yet.  open it. */  
+        err = cc_context_open_ccache (gCntrlBlock, ccapi_data->cache_name,
+                                      &ccapi_data->NamedCache);
+    }
+    
+    if (!err && ccapi_data && ccapi_data->NamedCache) {
+        err = stdccv3_get_timeoffset (context, ccapi_data->NamedCache);
+    }
+    
+    return err; /* Don't translate.  Callers will translate for us */
+}
+
+/* krb5_stdcc_shutdown is exported; use the old name */
+void krb5_stdcc_shutdown()
+{
+    if (gCntrlBlock) { cc_context_release(gCntrlBlock); }
+    gCntrlBlock = NULL;
+    gCCVersion = 0;
+}
+
+/*
+ * -- generate_new --------------------------------
+ * 
+ * create a new cache with a unique name, corresponds to creating a
+ * named cache initialize the API here if we have to.
+ */
+krb5_error_code KRB5_CALLCONV  
+krb5_stdccv3_generate_new (krb5_context context, krb5_ccache *id ) 
+{
+    krb5_error_code err = 0;
+    krb5_ccache newCache = NULL;
+    stdccCacheDataPtr ccapi_data = NULL;
+    cc_ccache_t ccache = NULL;
+    cc_string_t ccstring = NULL;
+    char *name = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup(context, NULL);
+    }
+    
+    if (!err) {
+        newCache = (krb5_ccache) malloc (sizeof (*newCache));
+        if (!newCache) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data));
+        if (!ccapi_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        err = cc_context_create_new_ccache (gCntrlBlock, cc_credentials_v5, "",
+                                            &ccache);
+    }
+    
+    if (!err) {
+        err = stdccv3_set_timeoffset (context, ccache);
+    }
+    
+    if (!err) {
+        err = cc_ccache_get_name (ccache, &ccstring);
+    }
+    
+    if (!err) {
+        name = (char *) malloc (sizeof (*name) * (strlen (ccstring->data) + 1));
+        if (!name) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        strcpy (name, ccstring->data);
+        ccapi_data->cache_name = name;
+        name = NULL; /* take ownership */
+        
+        ccapi_data->NamedCache = ccache;
+        ccache = NULL; /* take ownership */
+        
+        newCache->ops = &krb5_cc_stdcc_ops;
+        newCache->data = ccapi_data;
+        ccapi_data = NULL; /* take ownership */
+        
+        /* return a pointer to the new cache */
+        *id = newCache;
+        newCache = NULL;
+    }
+    
+    if (ccstring)   { cc_string_release (ccstring); }
+    if (name)       { free (name); }
+    if (ccache)     { cc_ccache_release (ccache); }
+    if (ccapi_data) { free (ccapi_data); }
+    if (newCache)   { free (newCache); }
+    
+    return cc_err_xlate (err);
+}
+  
+/*
+ * resolve
+ *
+ * create a new cache with the name stored in residual
+ */
+krb5_error_code KRB5_CALLCONV  
+krb5_stdccv3_resolve (krb5_context context, krb5_ccache *id , const char *residual ) 
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = NULL;
+    krb5_ccache ccache = NULL;
+    char *name = NULL;
+    
+    if (id == NULL) { err = KRB5_CC_NOMEM; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, NULL);
+    }
+    
+    if (!err) {
+        ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data));
+        if (!ccapi_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        ccache = (krb5_ccache ) malloc (sizeof (*ccache));
+        if (!ccache) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        name = malloc (strlen(residual) + 1);
+        if (!name) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        err = cc_context_open_ccache (gCntrlBlock, residual,
+                                      &ccapi_data->NamedCache);
+        if (err == ccErrCCacheNotFound) {
+            ccapi_data->NamedCache = NULL;
+            err = 0; /* ccache just doesn't exist yet */
+        }
+    }
+
+    if (!err) {
+	strcpy(name, residual);        
+	ccapi_data->cache_name = name;
+        name = NULL; /* take ownership */
+
+  	ccache->ops = &krb5_cc_stdcc_ops;
+	ccache->data = ccapi_data;
+        ccapi_data = NULL; /* take ownership */
+        
+        *id = ccache;
+        ccache = NULL; /* take ownership */
+    }
+    
+    if (ccache)     { free (ccache); }
+    if (ccapi_data) { free (ccapi_data); }
+    if (name)       { free (name); }
+    
+    return cc_err_xlate (err);
+}
+  
+/*
+ * 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_CALLCONV  
+krb5_stdccv3_initialize (krb5_context context, 
+                         krb5_ccache id,  
+                         krb5_principal princ) 
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    char *name = NULL;
+    cc_ccache_t ccache = NULL;
+    
+    if (id == NULL) { err = KRB5_CC_NOMEM; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, NULL);
+    }
+    
+    if (!err) {
+        err = krb5_unparse_name(context, princ, &name);
+    }
+    
+    if (!err) {
+        err = cc_context_create_ccache (gCntrlBlock, ccapi_data->cache_name, 
+                                        cc_credentials_v5, name,
+                                        &ccache);
+    }
+    
+    if (!err) {
+        err = stdccv3_set_timeoffset (context, ccache);
+    }
+    
+    if (!err) {
+        if (ccapi_data->NamedCache) {
+            err = cc_ccache_release (ccapi_data->NamedCache);
+        }
+        ccapi_data->NamedCache = ccache;
+        ccache = NULL; /* take ownership */
+        cache_changed ();
+    }
+    
+    if (ccache) { cc_ccache_release (ccache); }
+    if (name  ) { krb5_free_unparsed_name(context, name); }
+    
+    return cc_err_xlate(err);
+}
+
+/*
+ * store
+ *
+ * store some credentials in our cache
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_store (krb5_context context, krb5_ccache id, krb5_creds *creds )
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_union *cred_union = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    if (!err) {
+        /* copy the fields from the almost identical structures */
+        err = copy_krb5_creds_to_cc_cred_union (context, creds, &cred_union);
+    }
+    
+    if (!err) {
+        err = cc_ccache_store_credentials (ccapi_data->NamedCache, cred_union);
+    }
+    
+    if (!err) {
+        cache_changed();
+    }
+    
+    if (cred_union) { cred_union_release (cred_union); }
+    
+    return cc_err_xlate (err);
+}
+
+/*
+ * start_seq_get
+ *
+ * begin an iterator call to get all of the credentials in the cache
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_start_seq_get (krb5_context context, 
+                            krb5_ccache id, 
+                            krb5_cc_cursor *cursor )
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_iterator_t iterator = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    if (!err) {
+        err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache,
+                                                 &iterator);
+    }
+    
+    if (!err) {
+        *cursor = iterator;
+    }
+    
+    return cc_err_xlate (err);
+}
+
+/*
+ * 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_CALLCONV 
+krb5_stdccv3_next_cred (krb5_context context, 
+                        krb5_ccache id, 
+                        krb5_cc_cursor *cursor, 
+                        krb5_creds *creds)
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_t credentials = NULL;
+    cc_credentials_iterator_t iterator = *cursor;
+    
+    if (!iterator) { err = KRB5_CC_END; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    /* Note: CCAPI v3 ccaches can contain both v4 and v5 creds */
+    while (!err) {
+        err = cc_credentials_iterator_next (iterator, &credentials);
+
+        if (!err && (credentials->data->version == cc_credentials_v5)) {
+            copy_cc_cred_union_to_krb5_creds(context, credentials->data, creds);
+            break;
+        }
+    }
+    
+    if (credentials) { cc_credentials_release (credentials); }
+    if (err == ccIteratorEnd) {
+        cc_credentials_iterator_release (iterator);
+        *cursor = 0;
+    }    
+    
+    return cc_err_xlate (err);
+}
+
+
+/*
+ * retrieve
+ *
+ * - try to find a matching credential in the cache
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_stdccv3_retrieve (krb5_context context, 
+                       krb5_ccache id, 
+                       krb5_flags whichfields, 
+                       krb5_creds *mcreds, 
+                       krb5_creds *creds)
+{
+    return krb5_cc_retrieve_cred_default (context, id, whichfields,
+					  mcreds, creds);
+}
+
+/*
+ *  end seq
+ *
+ * just free up the storage assoicated with the cursor (if we can)
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_end_seq_get (krb5_context context, 
+                          krb5_ccache id, 
+                          krb5_cc_cursor *cursor)
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_iterator_t iterator = *cursor;
+    
+    if (!iterator) { return 0; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    if (!err) {
+        err = cc_credentials_iterator_release(iterator);
+    }
+    
+    return cc_err_xlate(err);
+}
+     
+/*
+ * close
+ *
+ * - free our pointers to the NC
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_close(krb5_context context, 
+                   krb5_ccache id)
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    if (!err) {
+        err = stdccv3_setup (context, NULL);
+    }
+    
+    if (!err) {
+	if (ccapi_data) {
+            if (ccapi_data->cache_name) { 
+                free (ccapi_data->cache_name); 
+            }
+            if (ccapi_data->NamedCache) { 
+                err = cc_ccache_release (ccapi_data->NamedCache); 
+            }
+            free (ccapi_data);
+            id->data = NULL;
+	}
+	free (id);        
+    }
+    
+    return cc_err_xlate(err);
+}
+
+/*
+ * destroy
+ *
+ * - free our storage and the cache
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_stdccv3_destroy (krb5_context context, 
+                      krb5_ccache id)
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+   
+    if (!err) {
+        err = stdccv3_setup(context, ccapi_data);
+    }
+    
+    if (!err) {
+	if (ccapi_data) {
+            if (ccapi_data->cache_name) { 
+                free(ccapi_data->cache_name); 
+            }
+            if (ccapi_data->NamedCache) {
+                /* destroy the named cache */
+                err = cc_ccache_destroy(ccapi_data->NamedCache);
+                if (err == ccErrCCacheNotFound) { 
+                    err = 0; /* ccache maybe already destroyed */
+                }
+                cache_changed();
+            }
+            free(ccapi_data);
+            id->data = NULL;
+	}
+	free(id);        
+    }
+    
+    return cc_err_xlate(err);
+}
+
+/*
+ *  getname
+ *
+ * - return the name of the named cache
+ */
+const char * KRB5_CALLCONV 
+krb5_stdccv3_get_name (krb5_context context, 
+                       krb5_ccache id )
+{
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    if (!ccapi_data) {
+        return NULL;
+    } else {
+        return (ccapi_data->cache_name);
+    }
+}
+
+
+/* get_principal
+ *
+ * - return the principal associated with the named cache
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_get_principal (krb5_context context, 
+                            krb5_ccache id , 
+                            krb5_principal *princ) 
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_string_t name = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup(context, ccapi_data);
+    }
+    
+    if (!err) {
+        err = cc_ccache_get_principal (ccapi_data->NamedCache, cc_credentials_v5, &name);
+    }
+    
+    if (!err) {
+        err = krb5_parse_name (context, name->data, princ);
+    }
+    
+    if (name) { cc_string_release (name); }
+    
+    return cc_err_xlate (err);
+}
+
+/*
+ * set_flags
+ *
+ * - currently a NOP since we don't store any flags in the NC
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_set_flags (krb5_context context, 
+                        krb5_ccache id, 
+                        krb5_flags flags)
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    err = stdccv3_setup (context, ccapi_data);
+    
+    return cc_err_xlate (err);
+}
+
+/*
+ * get_flags
+ *
+ * - currently a NOP since we don't store any flags in the NC
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_get_flags (krb5_context context, 
+                        krb5_ccache id, 
+                        krb5_flags *flags)
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    err = stdccv3_setup (context, ccapi_data);
+    
+    return cc_err_xlate (err);
+}
+
+/*
+ * remove
+ *
+ * - remove the specified credentials from the NC
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_remove (krb5_context context, 
+                     krb5_ccache id,
+                     krb5_flags flags, 
+                     krb5_creds *in_creds)
+{
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_iterator_t iterator = NULL;
+    int found = 0;
+    
+    if (!err) {
+        err = stdccv3_setup(context, ccapi_data);
+    }
+    
+    
+    if (!err) {
+        err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache,
+                                                 &iterator);
+    }
+
+    /* Note: CCAPI v3 ccaches can contain both v4 and v5 creds */
+    while (!err && !found) {
+        cc_credentials_t credentials = NULL;
+        
+        err = cc_credentials_iterator_next (iterator, &credentials);
+        
+        if (!err && (credentials->data->version == cc_credentials_v5)) {
+            krb5_creds creds;
+            
+            err = copy_cc_cred_union_to_krb5_creds(context, 
+                                                   credentials->data, &creds);
+
+            if (!err) {
+                found = krb5_creds_compare (context, in_creds, &creds);
+                krb5_free_cred_contents (context, &creds);
+            }
+            
+            if (!err && found) {
+                err = cc_ccache_remove_credentials (ccapi_data->NamedCache, credentials);
+            }
+        }
+        
+        if (credentials) { cc_credentials_release (credentials); }
+    }
+    if (err == ccIteratorEnd) { err = ccErrCredentialsNotFound; }    
+
+    if (!err) {
+        cache_changed ();
+    }
+    
+    return cc_err_xlate (err);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_stdccv3_ptcursor_new(krb5_context context,
+                          krb5_cc_ptcursor *cursor)
+{
+	krb5_error_code err = 0;
+	krb5_cc_ptcursor ptcursor = NULL;
+	cc_ccache_iterator_t iterator = NULL;
+	
+	ptcursor = malloc(sizeof(*ptcursor));
+	if (ptcursor == NULL) {
+		err = ENOMEM;
+	}
+	else {
+		memset(ptcursor, 0, sizeof(*ptcursor));
+	}
+	
+	if (!err) {
+		err = stdccv3_setup(context, NULL);
+	}
+	if (!err) {
+		ptcursor->ops = &krb5_cc_stdcc_ops;
+		err = cc_context_new_ccache_iterator(gCntrlBlock, &iterator);
+	}
+	
+	if (!err) {
+		ptcursor->data = iterator;
+	}
+	
+	if (err) {
+		if (ptcursor) { krb5_stdccv3_ptcursor_free(context, &ptcursor); }
+		// krb5_stdccv3_ptcursor_free sets ptcursor to NULL for us
+	}
+	
+	*cursor = ptcursor;
+	
+	return err;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_stdccv3_ptcursor_next(
+    krb5_context context,
+    krb5_cc_ptcursor cursor,
+    krb5_ccache *ccache)
+{
+	krb5_error_code err = 0;
+	cc_ccache_iterator_t iterator = NULL;
+	
+	krb5_ccache newCache = NULL;
+	stdccCacheDataPtr ccapi_data = NULL;
+	cc_ccache_t ccCache = NULL;
+	cc_string_t ccstring = NULL;
+	char *name = NULL;
+	
+	// TODO set proper errors, check context param
+	if (!cursor || !cursor->data) {
+		err = ccErrInvalidContext;
+	}
+	
+	*ccache = NULL;
+	
+	if (!err) {
+	    newCache = (krb5_ccache) malloc (sizeof (*newCache));
+	    if (!newCache) { err = KRB5_CC_NOMEM; }
+	}
+
+	if (!err) {
+	    ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data));
+	    if (!ccapi_data) { err = KRB5_CC_NOMEM; }
+	}
+	
+	if (!err) {
+		iterator = cursor->data;
+		err = cc_ccache_iterator_next(iterator, &ccCache);
+	}
+	
+	if (!err) {
+	    err = cc_ccache_get_name (ccCache, &ccstring);
+	}
+
+	if (!err) {
+	    name = (char *) malloc (sizeof (*name) * (strlen (ccstring->data) + 1));
+	    if (!name) { err = KRB5_CC_NOMEM; }
+	}
+	
+	if (!err) {
+	    strcpy (name, ccstring->data);
+	    ccapi_data->cache_name = name;
+	    name = NULL; /* take ownership */
+    
+	    ccapi_data->NamedCache = ccCache;
+	    ccCache = NULL; /* take ownership */
+    
+	    newCache->ops = &krb5_cc_stdcc_ops;
+	    newCache->data = ccapi_data;
+	    ccapi_data = NULL; /* take ownership */
+    
+	    /* return a pointer to the new cache */
+	    *ccache = newCache;
+	    newCache = NULL;
+	}
+ 
+	if (name)       { free (name); }
+	if (ccstring)   { cc_string_release (ccstring); }
+	if (ccCache)    { cc_ccache_release (ccCache); }
+	if (ccapi_data) { free (ccapi_data); }
+	if (newCache)   { free (newCache); }
+	
+	if (err == ccIteratorEnd) {
+		err = ccNoError;
+	}
+	
+	return err;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_stdccv3_ptcursor_free(
+    krb5_context context,
+    krb5_cc_ptcursor *cursor)
+{
+    if (*cursor != NULL) {
+		if ((*cursor)->data != NULL) {
+			cc_ccache_iterator_release((cc_ccache_iterator_t)((*cursor)->data));
+		}
+	    free(*cursor);
+	    *cursor = NULL;
+	}
+    return 0;
+}
+
+#else /* !USE_CCAPI_V3 */
+
+static krb5_error_code stdcc_setup(krb5_context context,
+				   stdccCacheDataPtr ccapi_data)
+{
+	int	err;
+
+  	/* make sure the API has been intialized */
+  	if (gCntrlBlock == NULL) {
+#ifdef CC_API_VER2
+		err = cc_initialize(&gCntrlBlock, CC_API_VER_2, NULL, NULL);
+#else
+		err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL);
+#endif
+		if (err != CC_NOERROR)
+			return cc_err_xlate(err);
+	}
+
+	/*
+	 * No ccapi_data structure, so we don't need to make sure the
+	 * ccache exists.
+	 */
+	if (!ccapi_data)
+		return 0;
+
+	/*
+	 * The ccache already exists
+	 */
+	if (ccapi_data->NamedCache)
+		return 0;
+
+	err = cc_open(gCntrlBlock, ccapi_data->cache_name,
+		      CC_CRED_V5, 0L, &ccapi_data->NamedCache);
+	if (err == CC_NOTFOUND)
+	  err = CC_NO_EXIST;
+	if (err == CC_NOERROR)
+		return 0;
+
+	ccapi_data->NamedCache = NULL;
+	return cc_err_xlate(err);
+}
+
+void krb5_stdcc_shutdown()
+{
+	if (gCntrlBlock)
+		cc_shutdown(&gCntrlBlock);
+	gCntrlBlock = NULL;
+}
+
+/*
+ * -- 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_CALLCONV  krb5_stdcc_generate_new 
+	(krb5_context context, krb5_ccache *id ) 
+{
+  	krb5_ccache 		newCache = NULL;
+	krb5_error_code		retval;
+	stdccCacheDataPtr	ccapi_data = NULL;
+	char 			*name = NULL;
+	cc_time_t 		change_time;
+	int 			err;
+
+	if ((retval = stdcc_setup(context, NULL)))
+		return retval;
+	
+	retval = KRB5_CC_NOMEM;
+	if (!(newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache))))
+		goto errout;
+  	if (!(ccapi_data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData))))
+		goto errout;
+	if (!(name = malloc(256)))
+		goto errout;
+	
+  	/* create a unique name */
+  	cc_get_change_time(gCntrlBlock, &change_time);
+  	sprintf(name, "gen_new_cache%d", change_time);
+  	
+  	/* create the new cache */
+  	err = cc_create(gCntrlBlock, name, name, CC_CRED_V5, 0L,
+			&ccapi_data->NamedCache);
+	if (err != CC_NOERROR) {
+		retval = cc_err_xlate(err);
+		goto errout;
+	}
+
+  	/* setup some fields */
+  	newCache->ops = &krb5_cc_stdcc_ops;
+  	newCache->data = ccapi_data;
+	ccapi_data->cache_name = name;
+  	
+  	/* return a pointer to the new cache */
+	*id = newCache;
+	  	
+	return 0;
+
+errout:
+	if (newCache)
+		free(newCache);
+	if (ccapi_data)
+		free(ccapi_data);
+	if (name)
+		free(name);
+	return retval;
+}
+  
+/*
+ * resolve
+ *
+ * create a new cache with the name stored in residual
+ */
+krb5_error_code KRB5_CALLCONV  krb5_stdcc_resolve 
+        (krb5_context context, krb5_ccache *id , const char *residual ) 
+{
+	krb5_ccache 		newCache = NULL;
+	stdccCacheDataPtr	ccapi_data = NULL;
+	int 			err;
+	krb5_error_code		retval;
+	char 			*cName = NULL;
+	
+	if ((retval = stdcc_setup(context, NULL)))
+		return retval;
+	
+	retval = KRB5_CC_NOMEM;
+	if (!(newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache))))
+		goto errout;
+  	
+  	if (!(ccapi_data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData))))
+		goto errout;
+
+	if (!(cName = malloc(strlen(residual)+1)))
+		goto errout;
+	
+  	newCache->ops = &krb5_cc_stdcc_ops;
+	newCache->data = ccapi_data;
+	ccapi_data->cache_name = cName;
+
+	strcpy(cName, residual);
+	
+ 	err = cc_open(gCntrlBlock, cName, CC_CRED_V5, 0L,
+		      &ccapi_data->NamedCache);
+        if (err != CC_NOERROR) {
+	        ccapi_data->NamedCache = NULL;
+	        if (err != CC_NO_EXIST) {
+	                retval = cc_err_xlate(err);
+	                goto errout;
+		}
+        }
+        
+  	/* return new cache structure */
+	*id = newCache;
+	
+  	return 0;
+	
+errout:
+	if (newCache)
+		free(newCache);
+	if (ccapi_data)
+		free(ccapi_data);
+	if (cName)
+		free(cName);
+	return retval;
+}
+  
+/*
+ * 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_CALLCONV  krb5_stdcc_initialize 
+       (krb5_context context, krb5_ccache id,  krb5_principal princ) 
+{
+	stdccCacheDataPtr	ccapi_data = NULL;
+  	int 			err;
+  	char 			*cName = NULL;
+	krb5_error_code		retval;
+  	
+	if ((retval = stdcc_setup(context, NULL)))
+		return retval;
+	
+  	/* test id for null */
+  	if (id == NULL) return KRB5_CC_NOMEM;
+  	
+	if ((retval = krb5_unparse_name(context, princ, &cName)))
+		return retval;
+
+	ccapi_data = id->data;
+
+
+	if (ccapi_data->NamedCache)
+		cc_close(gCntrlBlock, &ccapi_data->NamedCache);
+
+	err = cc_create(gCntrlBlock, ccapi_data->cache_name, cName,
+			CC_CRED_V5, 0L, &ccapi_data->NamedCache);
+	if (err != CC_NOERROR) {
+		krb5_free_unparsed_name(context, cName);
+		return cc_err_xlate(err);
+	}
+
+#if 0
+	/*
+	 * Some implementations don't set the principal name
+	 * correctly, so we force set it to the correct value.
+	 */
+	err = cc_set_principal(gCntrlBlock, ccapi_data->NamedCache,
+			       CC_CRED_V5, cName);
+#endif
+	krb5_free_unparsed_name(context, cName);
+	cache_changed();
+	
+	return cc_err_xlate(err);
+}
+
+/*
+ * store
+ *
+ * store some credentials in our cache
+ */
+krb5_error_code KRB5_CALLCONV krb5_stdcc_store 
+        (krb5_context context, krb5_ccache id, krb5_creds *creds )
+{
+	krb5_error_code	retval;
+	stdccCacheDataPtr	ccapi_data = id->data;
+	cred_union *cu = NULL;
+	int err;
+
+	if ((retval = stdcc_setup(context, ccapi_data)))
+		return retval;
+	
+	/* copy the fields from the almost identical structures */
+	dupK5toCC(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 cc_err_xlate(err);
+		
+	/* free the cred union using our local version of cc_free_creds()
+	   since we allocated it locally */
+	err = krb5int_free_cc_cred_union(&cu);
+		 
+	cache_changed();
+	return err;
+}
+
+/*
+ * start_seq_get
+ *
+ * begin an iterator call to get all of the credentials in the cache
+ */
+krb5_error_code KRB5_CALLCONV krb5_stdcc_start_seq_get 
+(krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor )
+{
+	stdccCacheDataPtr	ccapi_data = id->data;
+	krb5_error_code	retval;
+	int	err;
+	ccache_cit	*iterator;
+
+	if ((retval = stdcc_setup(context, ccapi_data)))
+		return retval;
+
+#ifdef CC_API_VER2
+	err = cc_seq_fetch_creds_begin(gCntrlBlock, ccapi_data->NamedCache,
+				       &iterator);
+	if (err != CC_NOERROR)
+		return cc_err_xlate(err);
+	*cursor = iterator;
+#else
+	/* all we have to do is initialize the cursor */
+	*cursor = NULL;
+#endif
+	return 0;
+}
+
+/*
+ * 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_CALLCONV krb5_stdcc_next_cred 
+        (krb5_context context, krb5_ccache id,  krb5_cc_cursor *cursor, 
+	 krb5_creds *creds)
+{
+	krb5_error_code	retval;
+	stdccCacheDataPtr	ccapi_data = id->data;
+	int err;
+	cred_union *credU = NULL;
+	ccache_cit	*iterator;
+	
+	if ((retval = stdcc_setup(context, ccapi_data)))
+		return retval;
+	
+#ifdef CC_API_VER2
+	iterator = *cursor;
+	if (iterator == 0)
+		return KRB5_CC_END;
+	err = cc_seq_fetch_creds_next(gCntrlBlock, &credU, iterator);
+
+	if (err == CC_END) {
+		cc_seq_fetch_creds_end(gCntrlBlock, &iterator);
+		*cursor = 0;
+	}
+#else
+	err = cc_seq_fetch_creds(gCntrlBlock, ccapi_data->NamedCache,
+				 &credU, (ccache_cit **)cursor); 
+#endif
+
+	if (err != CC_NOERROR)
+		return cc_err_xlate(err);
+	
+	/* copy data	(with translation) */
+	dupCCtoK5(context, credU->cred.pV5Cred, creds);
+	
+	/* free our version of the cred - okay to use cc_free_creds() here
+	   because we got it from the CCache library */
+	cc_free_creds(gCntrlBlock, &credU);
+	
+	return 0;
+}
+
+
+/*
+ * retreive
+ *
+ * - try to find a matching credential in the cache
+ */
+#if 0
+krb5_error_code KRB5_CALLCONV krb5_stdcc_retrieve 
+       		(krb5_context context, 
+		   krb5_ccache id, 
+		   krb5_flags whichfields, 
+		   krb5_creds *mcreds, 
+		   krb5_creds *creds )
+{
+	krb5_error_code	retval;
+	krb5_cc_cursor curs = NULL;
+	krb5_creds *fetchcreds;
+		
+	if ((retval = stdcc_setup(context, NULL)))
+		return retval;
+	
+	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)) {
+		/*
+		 * 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 0;
+		}
+		/* free copy allocated by next_cred */
+		krb5_free_cred_contents(context, fetchcreds);
+	}
+		
+	/* no luck, end get and exit */
+	krb5_stdcc_end_seq_get(context, id, &curs);
+	
+	/* we're not using this anymore so we should get rid of it! */
+	free(fetchcreds);
+	
+	return KRB5_CC_NOTFOUND;
+}
+#else
+
+krb5_error_code KRB5_CALLCONV
+krb5_stdcc_retrieve(context, id, whichfields, mcreds, creds)
+   krb5_context context;
+   krb5_ccache id;
+   krb5_flags whichfields;
+   krb5_creds *mcreds;
+   krb5_creds *creds;
+{
+    return krb5_cc_retrieve_cred_default (context, id, whichfields,
+					  mcreds, creds);
+}
+
+#endif
+
+/*
+ *  end seq
+ *
+ * just free up the storage assoicated with the cursor (if we could)
+ */
+krb5_error_code KRB5_CALLCONV krb5_stdcc_end_seq_get 
+        (krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
+{
+	krb5_error_code		retval;
+	stdccCacheDataPtr	ccapi_data = NULL;
+	int			err;
+#ifndef CC_API_VER2
+	cred_union 		*credU = NULL;
+#endif
+
+	ccapi_data = id->data;
+	
+	if ((retval = stdcc_setup(context, ccapi_data)))
+		return retval;
+
+	if (*cursor == NULL)
+		return 0;
+
+#ifdef CC_API_VER2
+	err = cc_seq_fetch_creds_end(gCntrlBlock, (ccache_cit **)cursor);
+	if (err != CC_NOERROR)
+		return cc_err_xlate(err);
+#else	
+	/*
+	 * Finish calling cc_seq_fetch_creds to clear out the cursor
+	 */
+	while (*cursor) {
+		err = cc_seq_fetch_creds(gCntrlBlock, ccapi_data->NamedCache,
+				 &credU, (ccache_cit **)cursor);
+		if (err)
+			break;
+		
+		/* okay to call cc_free_creds() here because we got credU from CCache lib */
+		cc_free_creds(gCntrlBlock, &credU);
+	}
+#endif
+	
+	return(0);
+}
+     
+/*
+ * close
+ *
+ * - free our pointers to the NC
+ */
+krb5_error_code KRB5_CALLCONV 
+krb5_stdcc_close(krb5_context context, krb5_ccache id)
+{
+	krb5_error_code	retval;
+	stdccCacheDataPtr	ccapi_data = id->data;
+
+	if ((retval = stdcc_setup(context, NULL)))
+		return retval;
+	
+	/* free it */
+	
+	if (ccapi_data) {
+		if (ccapi_data->cache_name)
+			free(ccapi_data->cache_name);
+		if (ccapi_data->NamedCache)
+			cc_close(gCntrlBlock, &ccapi_data->NamedCache);
+		free(ccapi_data);
+		id->data = NULL;
+	}
+	free(id);
+	
+	return 0;
+}
+
+/*
+ * destroy
+ *
+ * - free our storage and the cache
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_stdcc_destroy (krb5_context context, krb5_ccache id)
+{
+	int err;
+	krb5_error_code	retval;
+	stdccCacheDataPtr	ccapi_data = id->data;
+
+	if ((retval = stdcc_setup(context, ccapi_data))) {
+		return retval;
+	}
+
+	/* free memory associated with the krb5_ccache */
+	if (ccapi_data) {
+		if (ccapi_data->cache_name)
+			free(ccapi_data->cache_name);
+		if (ccapi_data->NamedCache) {
+			/* destroy the named cache */
+			err = cc_destroy(gCntrlBlock, &ccapi_data->NamedCache);
+			retval = cc_err_xlate(err);
+			cache_changed();
+		}
+		free(ccapi_data);
+		id->data = NULL;
+	}
+	free(id);
+
+	/* If the cache does not exist when we tried to destroy it,
+	   that's fine.  That means someone else destryoed it since
+	   we resolved it. */
+	if (retval == KRB5_FCC_NOFILE)
+		return 0;
+	return retval;
+}
+
+/*
+ *  getname
+ *
+ * - return the name of the named cache
+ */
+const char * KRB5_CALLCONV krb5_stdcc_get_name 
+        (krb5_context context, krb5_ccache id )
+{
+	stdccCacheDataPtr	ccapi_data = id->data;
+
+	if (!ccapi_data)
+		return 0;
+
+	return (ccapi_data->cache_name);
+}
+
+
+/* get_principal
+ *
+ * - return the principal associated with the named cache
+ */
+krb5_error_code KRB5_CALLCONV krb5_stdcc_get_principal
+	(krb5_context context, krb5_ccache id , krb5_principal *princ) 
+{
+	int 			err;
+	char 	  		*name = NULL;
+	stdccCacheDataPtr	ccapi_data = id->data;
+	krb5_error_code		retval;
+	
+	if ((retval = stdcc_setup(context, ccapi_data)))
+		return retval;
+
+	/* another wrapper */
+	err = cc_get_principal(gCntrlBlock, ccapi_data->NamedCache,
+			       &name);
+
+	if (err != CC_NOERROR) 
+		return cc_err_xlate(err);
+		
+	/* turn it into a krb principal */
+	err = krb5_parse_name(context, name, princ);
+
+	cc_free_principal(gCntrlBlock, &name);
+	
+	return err;	
+}
+
+/*
+ * set_flags
+ *
+ * - currently a NOP since we don't store any flags in the NC
+ */
+krb5_error_code KRB5_CALLCONV krb5_stdcc_set_flags 
+        (krb5_context context, krb5_ccache id , krb5_flags flags)
+{
+	stdccCacheDataPtr	ccapi_data = id->data;
+	krb5_error_code		retval;
+	
+	if ((retval = stdcc_setup(context, ccapi_data)))
+		return retval;
+
+	return 0;
+}
+
+/*
+ * get_flags
+ *
+ * - currently a NOP since we don't store any flags in the NC
+ */
+krb5_error_code KRB5_CALLCONV krb5_stdcc_get_flags 
+        (krb5_context context, krb5_ccache id , krb5_flags *flags)
+{
+	stdccCacheDataPtr	ccapi_data = id->data;
+	krb5_error_code		retval;
+	
+	if ((retval = stdcc_setup(context, ccapi_data)))
+		return retval;
+
+	return 0;
+}
+
+/*
+ * remove
+ *
+ * - remove the specified credentials from the NC
+ */
+krb5_error_code KRB5_CALLCONV krb5_stdcc_remove 
+        (krb5_context context, krb5_ccache id,
+	 krb5_flags flags, krb5_creds *creds)
+{
+    	cred_union *cu = NULL;
+    	int err;
+	stdccCacheDataPtr	ccapi_data = id->data;
+	krb5_error_code		retval;
+	
+	if ((retval = stdcc_setup(context, ccapi_data))) {
+		if (retval == KRB5_FCC_NOFILE)
+			return 0;
+		return retval;
+	}
+    	
+    	/* convert to a cred union */
+    	dupK5toCC(context, creds, &cu);
+    	
+    	/* remove it */
+    	err = cc_remove_cred(gCntrlBlock, ccapi_data->NamedCache, *cu);
+    	if (err != CC_NOERROR)
+		return cc_err_xlate(err);
+    	
+    	/* free the cred union using our local version of cc_free_creds()
+	       since we allocated it locally */
+    	err = krb5int_free_cc_cred_union(&cu);
+	cache_changed();
+    	if (err != CC_NOERROR)
+		return cc_err_xlate(err);
+
+        return 0;
+}
+#endif /* !USE_CCAPI_V3 */
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.h b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.h
new file mode 100644
index 000000000..4fe602799
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc.h
@@ -0,0 +1,155 @@
+#include "k5-int.h"	/* loads krb5.h */
+	
+#ifdef USE_CCAPI_V3
+#include <CredentialsCache.h>
+#else
+#ifdef USE_CCAPI
+#include <CredentialsCache2.h>
+#else
+#if defined(_WIN32)
+#include "cacheapi.h"
+#endif
+#endif
+#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
+ */
+typedef struct _stdccCacheData {
+     	char *cache_name;
+#ifdef USE_CCAPI_V3
+        cc_ccache_t NamedCache;
+#else
+	ccache_p *NamedCache;
+#endif
+} stdccCacheData, *stdccCacheDataPtr;
+
+
+/* function protoypes  */
+
+void krb5_stdcc_shutdown(void);
+
+#ifdef USE_CCAPI_V3
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_close
+        (krb5_context, krb5_ccache id );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_destroy 
+        (krb5_context, krb5_ccache id );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_end_seq_get 
+        (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_generate_new 
+        (krb5_context, krb5_ccache *id );
+
+const char * KRB5_CALLCONV krb5_stdccv3_get_name 
+        (krb5_context, krb5_ccache id );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_principal 
+        (krb5_context, krb5_ccache id , krb5_principal *princ );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_initialize 
+        (krb5_context, krb5_ccache id , krb5_principal princ );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_next_cred 
+        (krb5_context, 
+		   krb5_ccache id , 
+		   krb5_cc_cursor *cursor , 
+		   krb5_creds *creds );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_resolve 
+        (krb5_context, krb5_ccache *id , const char *residual );
+     
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_retrieve 
+        (krb5_context, 
+		   krb5_ccache id , 
+		   krb5_flags whichfields , 
+		   krb5_creds *mcreds , 
+		   krb5_creds *creds );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_start_seq_get 
+        (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_store 
+        (krb5_context, krb5_ccache id , krb5_creds *creds );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_set_flags 
+        (krb5_context, krb5_ccache id , krb5_flags flags );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_flags 
+        (krb5_context, krb5_ccache id , krb5_flags *flags );
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_remove 
+        (krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds);
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_new
+		(krb5_context context, krb5_cc_ptcursor *cursor);
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_next
+		(krb5_context context, krb5_cc_ptcursor cursor, krb5_ccache *ccache);
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_free
+		(krb5_context context, krb5_cc_ptcursor *cursor);
+
+
+#else
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_close
+        (krb5_context, krb5_ccache id );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_destroy 
+        (krb5_context, krb5_ccache id );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_end_seq_get 
+        (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_generate_new 
+        (krb5_context, krb5_ccache *id );
+
+const char * KRB5_CALLCONV krb5_stdcc_get_name 
+        (krb5_context, krb5_ccache id );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_get_principal 
+        (krb5_context, krb5_ccache id , krb5_principal *princ );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_initialize 
+        (krb5_context, krb5_ccache id , krb5_principal princ );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_next_cred 
+        (krb5_context, 
+		   krb5_ccache id , 
+		   krb5_cc_cursor *cursor , 
+		   krb5_creds *creds );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_resolve 
+        (krb5_context, krb5_ccache *id , const char *residual );
+     
+krb5_error_code KRB5_CALLCONV krb5_stdcc_retrieve 
+        (krb5_context, 
+		   krb5_ccache id , 
+		   krb5_flags whichfields , 
+		   krb5_creds *mcreds , 
+		   krb5_creds *creds );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_start_seq_get 
+        (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_store 
+        (krb5_context, krb5_ccache id , krb5_creds *creds );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_set_flags 
+        (krb5_context, krb5_ccache id , krb5_flags flags );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_get_flags 
+        (krb5_context, krb5_ccache id , krb5_flags *flags );
+
+krb5_error_code KRB5_CALLCONV krb5_stdcc_remove 
+        (krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds);
+#endif
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.c b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.c
new file mode 100644
index 000000000..58e72b33a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.c
@@ -0,0 +1,1066 @@
+/*
+ * 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 <errno.h>
+
+#if defined(_WIN32)
+#include <malloc.h>
+#endif
+
+#include "stdcc_util.h"
+#include "krb5.h"
+#include "kv5m_err.h"
+
+#define fieldSize 255
+
+#ifdef USE_CCAPI_V3
+
+
+static void 
+free_cc_array (cc_data **io_cc_array)
+{
+    if (io_cc_array) {
+        unsigned int i;
+        
+        for (i = 0; io_cc_array[i]; i++) {
+            if (io_cc_array[i]->data) { free (io_cc_array[i]->data); }
+            free (io_cc_array[i]);
+        }
+        free (io_cc_array);
+    }    
+}
+
+static krb5_error_code 
+copy_cc_array_to_addresses (krb5_context in_context, 
+                            cc_data **in_cc_array, 
+                            krb5_address ***out_addresses)
+{
+    krb5_error_code err = 0;
+    
+    if (in_cc_array == NULL) {
+        *out_addresses = NULL;
+        
+    } else {
+        unsigned int count, i;
+        krb5_address **addresses = NULL;
+
+        /* get length of array */
+        for (count = 0; in_cc_array[count]; count++);
+        addresses = (krb5_address **) malloc (sizeof (*addresses) * (count + 1));
+        if (!addresses) { err = KRB5_CC_NOMEM; }
+        
+        for (i = 0; !err && i < count; i++) { 
+            addresses[i] = (krb5_address *) malloc (sizeof (krb5_address));
+            if (!addresses[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                addresses[i]->contents = (krb5_octet *) malloc (sizeof (krb5_octet) * 
+                                                            in_cc_array[i]->length);
+                if (!addresses[i]->contents) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                addresses[i]->magic = KV5M_ADDRESS;
+                addresses[i]->addrtype = in_cc_array[i]->type;
+                addresses[i]->length = in_cc_array[i]->length;
+                memcpy (addresses[i]->contents, 
+                        in_cc_array[i]->data, in_cc_array[i]->length);
+            }
+        }
+        
+        if (!err) {
+            addresses[i] = NULL; /* terminator */
+            *out_addresses = addresses;
+            addresses = NULL;
+        }
+
+        if (addresses) { krb5_free_addresses (in_context, addresses); }
+    }
+    
+    return err;
+}
+
+static krb5_error_code 
+copy_cc_array_to_authdata (krb5_context in_context, 
+                           cc_data **in_cc_array, 
+                           krb5_authdata ***out_authdata)
+{
+    krb5_error_code err = 0;
+    
+    if (in_cc_array == NULL) {
+        *out_authdata = NULL;
+        
+    } else {
+        unsigned int count, i;
+        krb5_authdata **authdata = NULL;
+        
+        /* get length of array */
+        for (count = 0; in_cc_array[count]; count++);
+        authdata = (krb5_authdata **) malloc (sizeof (*authdata) * (count + 1));
+        if (!authdata) { err = KRB5_CC_NOMEM; }
+        
+        for (i = 0; !err && i < count; i++) { 
+            authdata[i] = (krb5_authdata *) malloc (sizeof (krb5_authdata));
+            if (!authdata[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                authdata[i]->contents = (krb5_octet *) malloc (sizeof (krb5_octet) * 
+                                                           in_cc_array[i]->length);
+                if (!authdata[i]->contents) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                authdata[i]->magic = KV5M_AUTHDATA;
+                authdata[i]->ad_type = in_cc_array[i]->type;
+                authdata[i]->length = in_cc_array[i]->length;
+                memcpy (authdata[i]->contents, 
+                        in_cc_array[i]->data, in_cc_array[i]->length);
+            }
+        }
+        
+        if (!err) {
+            authdata[i] = NULL; /* terminator */
+            *out_authdata = authdata;
+            authdata = NULL;
+        }
+        
+        if (authdata) { krb5_free_authdata (in_context, authdata); }
+    }
+    
+    return err;
+}
+
+static krb5_error_code 
+copy_addresses_to_cc_array (krb5_context in_context, 
+                            krb5_address **in_addresses, 
+                            cc_data ***out_cc_array)
+{
+    krb5_error_code err = 0;
+    
+    if (in_addresses == NULL) {
+        *out_cc_array = NULL;
+        
+    } else {
+        unsigned int count, i;
+        cc_data **cc_array = NULL;
+
+        /* get length of array */
+        for (count = 0; in_addresses[count]; count++);
+        cc_array = (cc_data **) malloc (sizeof (*cc_array) * (count + 1));
+        if (!cc_array) { err = KRB5_CC_NOMEM; }
+    
+        for (i = 0; !err && i < count; i++) { 
+            cc_array[i] = (cc_data *) malloc (sizeof (cc_data));
+            if (!cc_array[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                cc_array[i]->data = malloc (in_addresses[i]->length);
+                if (!cc_array[i]->data) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                cc_array[i]->type = in_addresses[i]->addrtype;
+                cc_array[i]->length = in_addresses[i]->length;
+                memcpy (cc_array[i]->data, in_addresses[i]->contents, in_addresses[i]->length);
+            }
+        }
+        
+        if (!err) {
+            cc_array[i] = NULL; /* terminator */
+            *out_cc_array = cc_array;
+            cc_array = NULL;
+        }
+
+        if (cc_array) { free_cc_array (cc_array); }
+    }
+    
+    
+    return err;
+}
+
+static krb5_error_code 
+copy_authdata_to_cc_array (krb5_context in_context, 
+                           krb5_authdata **in_authdata, 
+                           cc_data ***out_cc_array)
+{
+    krb5_error_code err = 0;
+    
+    if (in_authdata == NULL) {
+        *out_cc_array = NULL;
+
+    } else {
+        unsigned int count, i;
+        cc_data **cc_array = NULL;
+
+        /* get length of array */
+        for (count = 0; in_authdata[count]; count++);
+        cc_array = (cc_data **) malloc (sizeof (*cc_array) * (count + 1));
+        if (!cc_array) { err = KRB5_CC_NOMEM; }
+    
+        for (i = 0; !err && i < count; i++) { 
+            cc_array[i] = (cc_data *) malloc (sizeof (cc_data));
+            if (!cc_array[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                cc_array[i]->data = malloc (in_authdata[i]->length);
+                if (!cc_array[i]->data) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                cc_array[i]->type = in_authdata[i]->ad_type;
+                cc_array[i]->length = in_authdata[i]->length;
+                memcpy (cc_array[i]->data, in_authdata[i]->contents, in_authdata[i]->length);
+            }
+        }
+        
+        if (!err) {
+            cc_array[i] = NULL; /* terminator */
+            *out_cc_array = cc_array;
+            cc_array = NULL;
+        }
+
+        if (cc_array) { free_cc_array (cc_array); }
+    }
+    
+    
+    return err;
+}
+
+
+/*
+ * copy_cc_credentials_to_krb5_creds
+ * - allocate an empty k5 style ticket and copy info from the cc_creds ticket
+ */
+
+krb5_error_code 
+copy_cc_cred_union_to_krb5_creds (krb5_context in_context, 
+                                  const cc_credentials_union *in_cred_union, 
+                                  krb5_creds *out_creds)
+{
+    krb5_error_code err = 0;
+    cc_credentials_v5_t *cv5 = NULL;
+    krb5_int32 offset_seconds = 0, offset_microseconds = 0;
+    krb5_principal client = NULL;
+    krb5_principal server = NULL;
+    char *ticket_data = NULL;
+    char *second_ticket_data = NULL;
+    unsigned char *keyblock_contents = NULL;
+    krb5_address **addresses = NULL;
+    krb5_authdata **authdata = NULL;
+    
+    if (in_cred_union->version != cc_credentials_v5) { 
+	err = KRB5_CC_NOT_KTYPE;
+    } else {
+        cv5 = in_cred_union->credentials.credentials_v5;
+    }
+    
+#if TARGET_OS_MAC
+    if (!err) {
+        err = krb5_get_time_offsets (in_context, &offset_seconds, &offset_microseconds);
+    }
+#endif
+    
+    if (!err) {
+        err = krb5_parse_name (in_context, cv5->client, &client);
+    }
+    
+    if (!err) {
+        err = krb5_parse_name (in_context, cv5->server, &server);
+    }
+    
+    if (!err && cv5->keyblock.data) {
+        keyblock_contents = (unsigned char *) malloc (cv5->keyblock.length);
+        if (!keyblock_contents) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err && cv5->ticket.data) {
+        ticket_data = (char *) malloc (cv5->ticket.length);
+        if (!ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err && cv5->second_ticket.data) {
+        second_ticket_data = (char *) malloc (cv5->second_ticket.length);
+        if (!second_ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        /* addresses */
+        err = copy_cc_array_to_addresses (in_context, cv5->addresses, &addresses);
+    }
+ 
+    if (!err) {
+        /* authdata */
+        err = copy_cc_array_to_authdata (in_context, cv5->authdata, &authdata);
+    }
+    
+    if (!err) {
+        /* principals */
+        out_creds->client = client;
+        client = NULL;
+        out_creds->server = server;
+        server = NULL;
+        
+        /* copy keyblock */
+        if (cv5->keyblock.data) {
+            memcpy (keyblock_contents, cv5->keyblock.data, cv5->keyblock.length);
+        }
+        out_creds->keyblock.enctype = cv5->keyblock.type;
+        out_creds->keyblock.length = cv5->keyblock.length;
+        out_creds->keyblock.contents = keyblock_contents;
+        keyblock_contents = NULL;
+
+        /* copy times */
+        out_creds->times.authtime   = cv5->authtime     + offset_seconds;
+        out_creds->times.starttime  = cv5->starttime    + offset_seconds;
+        out_creds->times.endtime    = cv5->endtime      + offset_seconds;
+        out_creds->times.renew_till = cv5->renew_till   + offset_seconds;
+        out_creds->is_skey          = cv5->is_skey;
+        out_creds->ticket_flags     = cv5->ticket_flags;
+
+        /* first ticket */
+        if (cv5->ticket.data) {
+            memcpy(ticket_data, cv5->ticket.data, cv5->ticket.length);
+        }
+        out_creds->ticket.length = cv5->ticket.length;
+        out_creds->ticket.data = ticket_data;
+        ticket_data = NULL;
+        
+        /* second ticket */
+        if (cv5->second_ticket.data) {
+            memcpy(second_ticket_data, cv5->second_ticket.data, cv5->second_ticket.length);
+        }
+        out_creds->second_ticket.length = cv5->second_ticket.length;
+        out_creds->second_ticket.data = second_ticket_data;
+        second_ticket_data = NULL;
+        
+        out_creds->addresses = addresses;
+        addresses = NULL;
+
+        out_creds->authdata = authdata;
+        authdata = NULL;
+        
+        /* zero out magic number */
+        out_creds->magic = 0;
+    }
+    
+    if (addresses)          { krb5_free_addresses (in_context, addresses); }
+    if (authdata)           { krb5_free_authdata (in_context, authdata); }
+    if (keyblock_contents)  { free (keyblock_contents); }
+    if (ticket_data)        { free (ticket_data); }
+    if (second_ticket_data) { free (second_ticket_data); }
+    if (client)             { krb5_free_principal (in_context, client); }
+    if (server)             { krb5_free_principal (in_context, server); }
+    
+    return err;
+}
+
+/*
+ * copy_krb5_creds_to_cc_credentials
+ * - analagous to above but in the reverse direction
+ */
+krb5_error_code
+copy_krb5_creds_to_cc_cred_union (krb5_context in_context, 
+                                  krb5_creds *in_creds, 
+                                  cc_credentials_union **out_cred_union)
+{
+    krb5_error_code err = 0;
+    cc_credentials_union *cred_union = NULL;
+    cc_credentials_v5_t *cv5 = NULL;
+    char *client = NULL;
+    char *server = NULL;
+    unsigned char *ticket_data = NULL;
+    unsigned char *second_ticket_data = NULL;
+    unsigned char *keyblock_data = NULL;
+    krb5_int32 offset_seconds = 0, offset_microseconds = 0;
+    cc_data **cc_address_array = NULL;
+    cc_data **cc_authdata_array = NULL;
+    
+    if (out_cred_union == NULL) { err = KRB5_CC_NOMEM; }
+    
+#if TARGET_OS_MAC
+    if (!err) {
+        err = krb5_get_time_offsets (in_context, &offset_seconds, &offset_microseconds);
+    }
+#endif
+    
+    if (!err) {
+        cred_union = (cc_credentials_union *) malloc (sizeof (*cred_union));
+        if (!cred_union) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        cv5 = (cc_credentials_v5_t *) malloc (sizeof (*cv5));
+        if (!cv5) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        err = krb5_unparse_name (in_context, in_creds->client, &client);
+    }
+    
+    if (!err) {
+        err = krb5_unparse_name (in_context, in_creds->server, &server);
+    }
+    
+    if (!err && in_creds->keyblock.contents) {
+        keyblock_data = (unsigned char *) malloc (in_creds->keyblock.length);
+        if (!keyblock_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err && in_creds->ticket.data) {
+        ticket_data = (unsigned char *) malloc (in_creds->ticket.length);
+        if (!ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err && in_creds->second_ticket.data) {
+        second_ticket_data = (unsigned char *) malloc (in_creds->second_ticket.length);
+        if (!second_ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        err = copy_addresses_to_cc_array (in_context, in_creds->addresses, &cc_address_array);
+    }
+    
+    if (!err) {
+        err = copy_authdata_to_cc_array (in_context, in_creds->authdata, &cc_authdata_array);
+    }
+        
+    if (!err) {
+        /* principals */
+        cv5->client = client;
+        client = NULL;
+        cv5->server = server;
+        server = NULL;
+
+        /* copy more fields */
+        if (in_creds->keyblock.contents) {
+            memcpy(keyblock_data, in_creds->keyblock.contents, in_creds->keyblock.length);
+        }
+        cv5->keyblock.type = in_creds->keyblock.enctype;
+        cv5->keyblock.length = in_creds->keyblock.length;
+        cv5->keyblock.data = keyblock_data;
+        keyblock_data = NULL;
+        
+        cv5->authtime     = in_creds->times.authtime   - offset_seconds;
+        cv5->starttime    = in_creds->times.starttime  - offset_seconds;
+        cv5->endtime      = in_creds->times.endtime    - offset_seconds;
+        cv5->renew_till   = in_creds->times.renew_till - offset_seconds;
+        cv5->is_skey      = in_creds->is_skey;
+        cv5->ticket_flags = in_creds->ticket_flags;
+
+        if (in_creds->ticket.data) {
+            memcpy (ticket_data, in_creds->ticket.data, in_creds->ticket.length);
+        }
+        cv5->ticket.length = in_creds->ticket.length;
+        cv5->ticket.data = ticket_data;
+        ticket_data = NULL;
+        
+        if (in_creds->second_ticket.data) {
+            memcpy (second_ticket_data, in_creds->second_ticket.data, in_creds->second_ticket.length);
+        }
+        cv5->second_ticket.length = in_creds->second_ticket.length;
+        cv5->second_ticket.data = second_ticket_data;
+        second_ticket_data = NULL;
+        
+        cv5->addresses = cc_address_array;
+        cc_address_array = NULL;
+        
+        cv5->authdata = cc_authdata_array;
+        cc_authdata_array = NULL;       
+        
+        /* Set up the structures to return to the caller */
+        cred_union->version = cc_credentials_v5;
+        cred_union->credentials.credentials_v5 = cv5;
+        cv5 = NULL;
+        
+        *out_cred_union = cred_union;
+        cred_union = NULL;
+    }
+    
+    if (cc_address_array)   { free_cc_array (cc_address_array); }
+    if (cc_authdata_array)  { free_cc_array (cc_authdata_array); }
+    if (keyblock_data)      { free (keyblock_data); }
+    if (ticket_data)        { free (ticket_data); }
+    if (second_ticket_data) { free (second_ticket_data); }
+    if (client)             { krb5_free_unparsed_name (in_context, client); }
+    if (server)             { krb5_free_unparsed_name (in_context, server); }
+    if (cv5)                { free (cv5); }
+    if (cred_union)         { free (cred_union); }
+    
+    return err;
+}
+
+krb5_error_code 
+cred_union_release (cc_credentials_union *in_cred_union) 
+{
+    if (in_cred_union) {
+        if (in_cred_union->version == cc_credentials_v5 &&
+            in_cred_union->credentials.credentials_v5) {
+            cc_credentials_v5_t *cv5 = in_cred_union->credentials.credentials_v5;
+            
+            /* should use krb5_free_unparsed_name but we have no context */
+            if (cv5->client) { free (cv5->client); }
+            if (cv5->server) { free (cv5->server); }
+            
+            if (cv5->keyblock.data)      { free (cv5->keyblock.data); }
+            if (cv5->ticket.data)        { free (cv5->ticket.data); }
+            if (cv5->second_ticket.data) { free (cv5->second_ticket.data); }
+            
+            free_cc_array (cv5->addresses);
+            free_cc_array (cv5->authdata);
+            
+            free (cv5);
+            
+        } else if (in_cred_union->version == cc_credentials_v4 &&
+                   in_cred_union->credentials.credentials_v4) {
+            free (in_cred_union->credentials.credentials_v4);
+        }
+        free ((cc_credentials_union *) in_cred_union);
+    }
+    
+    return 0;
+}
+
+#else /* !USE_CCAPI_V3 */
+/*
+ * CopyCCDataArrayToK5
+ * - copy and translate the null terminated arrays of data records
+ * 	 used in k5 tickets
+ */
+int copyCCDataArrayToK5(cc_creds *ccCreds, krb5_creds *v5Creds, char whichArray) {
+
+    if (whichArray == kAddressArray) {
+	if (ccCreds->addresses == NULL) {
+	    v5Creds->addresses = NULL;
+	} else {
+
+	    krb5_address 	**addrPtr, *addr;
+	    cc_data			**dataPtr, *data;
+	    unsigned int		numRecords = 0;
+
+	    /* Allocate the array of pointers: */
+	    for (dataPtr = ccCreds->addresses; *dataPtr != NULL; numRecords++, dataPtr++) {}
+
+	    v5Creds->addresses = (krb5_address **) malloc (sizeof(krb5_address *) * (numRecords + 1));
+	    if (v5Creds->addresses == NULL)
+		return ENOMEM;
+
+	    /* Fill in the array, allocating the address structures: */
+	    for (dataPtr = ccCreds->addresses, addrPtr = v5Creds->addresses; *dataPtr != NULL; addrPtr++, dataPtr++) {
+
+		*addrPtr = (krb5_address *) malloc (sizeof(krb5_address));
+		if (*addrPtr == NULL)
+		    return ENOMEM;
+		data = *dataPtr;
+		addr = *addrPtr;
+
+		addr->addrtype = data->type;
+		addr->magic    = KV5M_ADDRESS;
+		addr->length   = data->length;
+		addr->contents = (krb5_octet *) malloc (sizeof(krb5_octet) * addr->length);
+		if (addr->contents == NULL)
+		    return ENOMEM;
+		memmove(addr->contents, data->data, addr->length); /* copy contents */
+	    }
+
+	    /* Write terminator: */
+	    *addrPtr = NULL;
+	}
+    }
+
+    if (whichArray == kAuthDataArray) {
+	if (ccCreds->authdata == NULL) {
+	    v5Creds->authdata = NULL;
+	} else {
+	    krb5_authdata 	**authPtr, *auth;
+	    cc_data			**dataPtr, *data;
+	    unsigned int		numRecords = 0;
+
+	    /* Allocate the array of pointers: */
+	    for (dataPtr = ccCreds->authdata; *dataPtr != NULL; numRecords++, dataPtr++) {}
+
+	    v5Creds->authdata = (krb5_authdata **) malloc (sizeof(krb5_authdata *) * (numRecords + 1));
+	    if (v5Creds->authdata == NULL)
+		return ENOMEM;
+
+	    /* Fill in the array, allocating the address structures: */
+	    for (dataPtr = ccCreds->authdata, authPtr = v5Creds->authdata; *dataPtr != NULL; authPtr++, dataPtr++) {
+
+		*authPtr = (krb5_authdata *) malloc (sizeof(krb5_authdata));
+		if (*authPtr == NULL)
+		    return ENOMEM;
+		data = *dataPtr;
+		auth = *authPtr;
+
+		auth->ad_type  = data->type;
+		auth->magic    = KV5M_AUTHDATA;
+		auth->length   = data->length;
+		auth->contents = (krb5_octet *) malloc (sizeof(krb5_octet) * auth->length);
+		if (auth->contents == NULL)
+		    return ENOMEM;
+		memmove(auth->contents, data->data, auth->length); /* copy contents */
+	    }
+
+	    /* Write terminator: */
+	    *authPtr = NULL;
+	}
+    }
+
+    return 0;
+}
+
+/*
+ * copyK5DataArrayToCC
+ * - analagous to above, but in the other direction
+ */
+int copyK5DataArrayToCC(krb5_creds *v5Creds, cc_creds *ccCreds, char whichArray)
+{
+    if (whichArray == kAddressArray) {
+	if (v5Creds->addresses == NULL) {
+	    ccCreds->addresses = NULL;
+	} else {
+
+	    krb5_address 	**addrPtr, *addr;
+	    cc_data			**dataPtr, *data;
+	    unsigned int			numRecords = 0;
+
+	    /* Allocate the array of pointers: */
+	    for (addrPtr = v5Creds->addresses; *addrPtr != NULL; numRecords++, addrPtr++) {}
+
+	    ccCreds->addresses = (cc_data **) malloc (sizeof(cc_data *) * (numRecords + 1));
+	    if (ccCreds->addresses == NULL)
+		return ENOMEM;
+
+	    /* Fill in the array, allocating the address structures: */
+	    for (dataPtr = ccCreds->addresses, addrPtr = v5Creds->addresses; *addrPtr != NULL; addrPtr++, dataPtr++) {
+
+		*dataPtr = (cc_data *) malloc (sizeof(cc_data));
+		if (*dataPtr == NULL)
+		    return ENOMEM;
+		data = *dataPtr;
+		addr = *addrPtr;
+
+		data->type   = addr->addrtype;
+		data->length = addr->length;
+		data->data   = malloc (sizeof(char) * data->length);
+		if (data->data == NULL)
+		    return ENOMEM;
+		memmove(data->data, addr->contents, data->length); /* copy contents */
+	    }
+
+	    /* Write terminator: */
+	    *dataPtr = NULL;
+	}
+    }
+
+    if (whichArray == kAuthDataArray) {
+	if (v5Creds->authdata == NULL) {
+	    ccCreds->authdata = NULL;
+	} else {
+	    krb5_authdata 	**authPtr, *auth;
+	    cc_data			**dataPtr, *data;
+	    unsigned int			numRecords = 0;
+
+	    /* Allocate the array of pointers: */
+	    for (authPtr = v5Creds->authdata; *authPtr != NULL; numRecords++, authPtr++) {}
+
+	    ccCreds->authdata = (cc_data **) malloc (sizeof(cc_data *) * (numRecords + 1));
+	    if (ccCreds->authdata == NULL)
+		return ENOMEM;
+
+	    /* Fill in the array, allocating the address structures: */
+	    for (dataPtr = ccCreds->authdata, authPtr = v5Creds->authdata; *authPtr != NULL; authPtr++, dataPtr++) {
+
+		*dataPtr = (cc_data *) malloc (sizeof(cc_data));
+		if (*dataPtr == NULL)
+		    return ENOMEM;
+		data = *dataPtr;
+		auth = *authPtr;
+
+		data->type   = auth->ad_type;
+		data->length = auth->length;
+		data->data   = malloc (sizeof(char) * data->length);
+		if (data->data == NULL)
+		    return ENOMEM;
+		memmove(data->data, auth->contents, data->length); /* copy contents */
+	    }
+
+	    /* Write terminator: */
+	    *dataPtr = NULL;
+	}
+    }
+
+    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)
+{
+    krb5_int32 offset_seconds = 0, offset_microseconds = 0;
+    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 */
+#if TARGET_OS_MAC
+    err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
+    if (err) return;
+#endif
+    dest->times.authtime   = src->authtime     + offset_seconds;
+    dest->times.starttime  = src->starttime    + offset_seconds;
+    dest->times.endtime    = src->endtime      + offset_seconds;
+    dest->times.renew_till = src->renew_till   + offset_seconds;
+    dest->is_skey          = src->is_skey;
+    dest->ticket_flags     = src->ticket_flags;
+
+    /* more branching fields */
+    err = copyCCDataArrayToK5(src, dest, kAddressArray);
+    if (err) return;
+
+    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;
+
+    /* authdata */
+    err = copyCCDataArrayToK5(src, dest, kAuthDataArray);
+    if (err) return;
+
+    return;
+}
+
+/*
+ * dupK5toCC
+ * - analagous to above but in the reverse direction
+ */
+void dupK5toCC(krb5_context context, krb5_creds *creds, cred_union **cu)
+{
+    cc_creds *c;
+    int err;
+    krb5_int32 offset_seconds = 0, offset_microseconds = 0;
+
+    if (cu == NULL) return;
+
+    /* allocate the cred_union */
+    *cu = (cred_union *)malloc(sizeof(cred_union));
+    if ((*cu) == NULL)
+	return;
+
+    (*cu)->cred_type = CC_CRED_V5;
+
+    /* allocate creds structure (and install) */
+    c  = (cc_creds *)malloc(sizeof(cc_creds));
+    if (c == NULL) return;
+    (*cu)->cred.pV5Cred = c;
+
+    /* convert krb5 principals to flat principals */
+    err = krb5_unparse_name(context, creds->client, &(c->client));
+    err = krb5_unparse_name(context, creds->server, &(c->server));
+    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 *)malloc(creds->keyblock.length);
+	memcpy(c->keyblock.data, creds->keyblock.contents, creds->keyblock.length);
+    } else {
+	c->keyblock.data = NULL;
+    }
+
+#if TARGET_OS_MAC
+    err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
+    if (err) return;
+#endif
+    c->authtime     = creds->times.authtime   - offset_seconds;
+    c->starttime    = creds->times.starttime  - offset_seconds;
+    c->endtime      = creds->times.endtime    - offset_seconds;
+    c->renew_till   = creds->times.renew_till - offset_seconds;
+    c->is_skey      = creds->is_skey;
+    c->ticket_flags = creds->ticket_flags;
+
+    err = copyK5DataArrayToCC(creds, c, kAddressArray);
+    if (err) return;
+
+    c->ticket.length = creds->ticket.length;
+    if (creds->ticket.data != NULL) {
+	c->ticket.data = (unsigned char *)malloc(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 *)malloc(creds->second_ticket.length);
+	memcpy(c->second_ticket.data, creds->second_ticket.data, creds->second_ticket.length);
+    } else {
+	c->second_ticket.data = NULL;
+    }
+
+    err = copyK5DataArrayToCC(creds, c, kAuthDataArray);
+    if (err) return;
+
+    return;
+}
+
+/* ----- free_cc_cred_union, etc -------------- */
+/*
+  Since the Kerberos5 library allocates a credentials cache structure
+  (in dupK5toCC() above) with its own memory allocation routines - which
+  may be different than how the CCache allocates memory - the Kerb5 library
+  must have its own version of cc_free_creds() to deallocate it.  These
+  functions do that.  The top-level function to substitue for cc_free_creds()
+  is krb5_free_cc_cred_union().
+
+  If the CCache library wants to use a cred_union structure created by
+  the Kerb5 library, it should make a deep copy of it to "translate" to its
+  own memory allocation space.
+*/
+static void deep_free_cc_data (cc_data data)
+{
+    if (data.data != NULL)
+	free (data.data);
+}
+
+static void deep_free_cc_data_array (cc_data** data) {
+
+    unsigned int i;
+
+    if (data == NULL)
+	return;
+
+    for (i = 0; data [i] != NULL; i++) {
+	deep_free_cc_data (*(data [i]));
+	free (data [i]);
+    }
+
+    free (data);
+}
+
+static void deep_free_cc_v5_creds (cc_creds* creds)
+{
+    if (creds == NULL)
+	return;
+
+    if (creds -> client != NULL)
+	free (creds -> client);
+    if (creds -> server != NULL)
+	free (creds -> server);
+
+    deep_free_cc_data (creds -> keyblock);
+    deep_free_cc_data (creds -> ticket);
+    deep_free_cc_data (creds -> second_ticket);
+
+    deep_free_cc_data_array (creds -> addresses);
+    deep_free_cc_data_array (creds -> authdata);
+
+    free(creds);
+}
+
+static void deep_free_cc_creds (cred_union creds)
+{
+    if (creds.cred_type == CC_CRED_V4) {
+	/* we shouldn't get this, of course */
+	free (creds.cred.pV4Cred);
+    } else if (creds.cred_type == CC_CRED_V5) {
+	deep_free_cc_v5_creds (creds.cred.pV5Cred);
+    }
+}
+
+/* top-level exported function */
+cc_int32 krb5int_free_cc_cred_union (cred_union** creds)
+{
+    if (creds == NULL)
+	return CC_BAD_PARM;
+
+    if (*creds != NULL) {
+	deep_free_cc_creds (**creds);
+	free (*creds);
+	*creds = NULL;
+    }
+
+    return CC_NOERROR;
+}
+#endif
+
+/*
+ * Utility functions...
+ */
+static krb5_boolean
+times_match(t1, t2)
+    register const krb5_ticket_times *t1;
+register const krb5_ticket_times *t2;
+{
+    if (t1->renew_till) {
+	if (t1->renew_till > t2->renew_till)
+	    return FALSE;		/* this one expires too late */
+    }
+    if (t1->endtime) {
+	if (t1->endtime > t2->endtime)
+	    return FALSE;		/* this one expires too late */
+    }
+    /* only care about expiration on a times_match */
+    return TRUE;
+}
+
+static krb5_boolean
+times_match_exact (t1, t2)
+    register const krb5_ticket_times *t1, *t2;
+{
+    return (t1->authtime == t2->authtime
+	    && t1->starttime == t2->starttime
+	    && t1->endtime == t2->endtime
+	    && t1->renew_till == t2->renew_till);
+}
+
+static krb5_boolean
+standard_fields_match(context, mcreds, creds)
+    krb5_context context;
+register const krb5_creds *mcreds, *creds;
+{
+    return (krb5_principal_compare(context, mcreds->client,creds->client) &&
+	    krb5_principal_compare(context, mcreds->server,creds->server));
+}
+
+/* only match the server name portion, not the server realm portion */
+
+static krb5_boolean
+srvname_match(context, mcreds, creds)
+    krb5_context context;
+register const krb5_creds *mcreds, *creds;
+{
+    krb5_boolean retval;
+    krb5_principal_data p1, p2;
+
+    retval = krb5_principal_compare(context, mcreds->client,creds->client);
+    if (retval != TRUE)
+	return retval;
+    /*
+     * Hack to ignore the server realm for the purposes of the compare.
+     */
+    p1 = *mcreds->server;
+    p2 = *creds->server;
+    p1.realm = p2.realm;
+    return krb5_principal_compare(context, &p1, &p2);
+}
+
+
+static krb5_boolean
+authdata_match(mdata, data)
+    krb5_authdata *const *mdata, *const *data;
+{
+    const krb5_authdata *mdatap, *datap;
+
+    if (mdata == data)
+	return TRUE;
+
+    if (mdata == NULL)
+	return *data == NULL;
+
+    if (data == NULL)
+	return *mdata == NULL;
+
+    while ((mdatap = *mdata)
+	   && (datap = *data)
+	   && mdatap->ad_type == datap->ad_type
+	   && mdatap->length == datap->length
+	   && !memcmp ((char *) mdatap->contents, (char *) datap->contents,
+		       datap->length)) {
+	mdata++;
+	data++;
+    }
+
+    return !*mdata && !*data;
+}
+
+static krb5_boolean
+data_match(data1, data2)
+    register const krb5_data *data1, *data2;
+{
+    if (!data1) {
+	if (!data2)
+	    return TRUE;
+	else
+	    return FALSE;
+    }
+    if (!data2) return FALSE;
+
+    if (data1->length != data2->length)
+	return FALSE;
+    else
+	return memcmp(data1->data, data2->data, data1->length) ? FALSE : TRUE;
+}
+
+#define MATCH_SET(bits) (whichfields & bits)
+#define flags_match(a,b) (((a) & (b)) == (a))
+
+/*  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)
+{
+    if (((MATCH_SET(KRB5_TC_MATCH_SRV_NAMEONLY) &&
+	  srvname_match(context, match, base)) ||
+	 standard_fields_match(context, match, base))
+	&&
+	(! MATCH_SET(KRB5_TC_MATCH_IS_SKEY) ||
+	 match->is_skey == base->is_skey)
+	&&
+	(! MATCH_SET(KRB5_TC_MATCH_FLAGS_EXACT) ||
+	 match->ticket_flags == base->ticket_flags)
+	&&
+	(! MATCH_SET(KRB5_TC_MATCH_FLAGS) ||
+	 flags_match(match->ticket_flags, base->ticket_flags))
+	&&
+	(! MATCH_SET(KRB5_TC_MATCH_TIMES_EXACT) ||
+	 times_match_exact(&match->times, &base->times))
+	&&
+	(! MATCH_SET(KRB5_TC_MATCH_TIMES) ||
+	 times_match(&match->times, &base->times))
+	&&
+	(! MATCH_SET(KRB5_TC_MATCH_AUTHDATA) ||
+	 authdata_match (match->authdata, base->authdata))
+	&&
+	(! MATCH_SET(KRB5_TC_MATCH_2ND_TKT) ||
+	 data_match (&match->second_ticket, &base->second_ticket))
+	&&
+	((! MATCH_SET(KRB5_TC_MATCH_KTYPE))||
+	 (match->keyblock.enctype == base->keyblock.enctype))
+	)
+	return TRUE;
+    return FALSE;
+}
+
+
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.h b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.h
new file mode 100644
index 000000000..c3a5e39cc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccapi/stdcc_util.h
@@ -0,0 +1,47 @@
+/* stdcc_util.h
+ *
+ * Frank Dabek, July 1998
+ */
+
+#include "autoconf.h"
+
+#if USE_CCAPI_V3
+#include <CredentialsCache.h>
+#else
+#if USE_CCAPI
+#include <CredentialsCache2.h>
+#endif
+
+#if defined(_WIN32)
+#include "cacheapi.h"
+#endif
+#endif
+
+#include "krb5.h"
+
+/* protoypes for private functions declared in stdcc_util.c */
+#ifdef USE_CCAPI_V3
+krb5_error_code 
+copy_cc_cred_union_to_krb5_creds (krb5_context in_context, 
+                                  const cc_credentials_union *in_cred_union, 
+                                  krb5_creds *out_creds);
+krb5_error_code
+copy_krb5_creds_to_cc_cred_union (krb5_context in_context, 
+                                  krb5_creds *in_creds, 
+                                  cc_credentials_union **out_cred_union);
+
+krb5_error_code 
+cred_union_release (cc_credentials_union *in_cred_union);
+#else
+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 dupK5toCC(krb5_context context, krb5_creds *creds, cred_union **cu);
+cc_int32 krb5int_free_cc_cred_union (cred_union** creds);
+#endif
+int stdccCredsMatch(krb5_context context, krb5_creds *base, krb5_creds *match, int whichfields);
+int bitTst(int var, int mask);
+
+#define kAddressArray 4 
+#define kAuthDataArray 5
+
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.c b/krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.c
new file mode 100644
index 000000000..22646e1ee
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.c
@@ -0,0 +1,100 @@
+#if defined(_WIN32)
+/*
+ * winccld.c --- routine for dynamically loading the ccache DLL if
+ * it's present.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include "k5-int.h"
+#include "stdcc.h"
+
+/* from fcc-proto.h */
+extern const krb5_cc_ops krb5_fcc_ops;
+
+#define KRB5_WINCCLD_C_
+#include "winccld.h"
+
+static int krb5_win_ccdll_loaded = 0;
+
+extern void krb5_win_ccdll_load();
+extern int krb5_is_ccdll_loaded();
+
+/*
+ * return codes
+ */
+#define LF_OK		0
+#define LF_NODLL	1
+#define LF_NOFUNC	2
+
+#ifdef _WIN64
+#define KRBCC_DLL      "krbcc64.dll"
+#else
+#define KRBCC_DLL      "krbcc32.dll"
+#endif
+
+static int LoadFuncs(const char* dll_name, FUNC_INFO fi[],
+		     HINSTANCE* ph, int debug);
+
+static int LoadFuncs(const char* dll_name, FUNC_INFO fi[],
+		     HINSTANCE* ph, int debug)
+{
+    HINSTANCE h;
+    int i, n;
+    int error = 0;
+
+    if (ph) *ph = 0;
+
+    for (n = 0; fi[n].func_ptr_var; n++) {
+	*(fi[n].func_ptr_var) = 0;
+    }
+
+    if (!(h = LoadLibrary(dll_name))) {
+	/* Get error for source debugging purposes. */
+	error = (int)GetLastError();
+	return LF_NODLL;
+    }
+
+    if (debug)
+	printf("Loaded %s\n", dll_name);
+    for (i = 0; !error && (i < n); i++) {
+	void* p = (void*)GetProcAddress(h, fi[i].func_name);
+	if (!p) {
+	    if (debug)
+		printf("Could not get function: %s\n", fi[i].func_name);
+	    error = 1;
+	} else {
+	    *(fi[i].func_ptr_var) = p;
+	    if (debug)
+		printf("Loaded function %s at 0x%08X\n", fi[i].func_name, p);
+	}
+    }
+    if (error) {
+	for (i = 0; i < n; i++) {
+	    *(fi[i].func_ptr_var) = 0;
+	}
+	FreeLibrary(h);
+	return LF_NOFUNC;
+    }
+    if (ph) *ph = h;
+    return LF_OK;
+}
+
+void krb5_win_ccdll_load(context)
+	krb5_context	context;
+{
+	krb5_cc_register(context, &krb5_fcc_ops, 0);
+	if (krb5_win_ccdll_loaded)
+		return;
+	if (LoadFuncs(KRBCC_DLL, krbcc_fi, 0, 0))
+		return;		/* Error, give up */
+	krb5_win_ccdll_loaded = 1;
+	krb5_cc_dfl_ops = &krb5_cc_stdcc_ops; /* Use stdcc! */
+}
+
+int krb5_is_ccdll_loaded()
+{
+	return krb5_win_ccdll_loaded;
+}
+
+#endif	/* Windows */
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.h b/krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.h
new file mode 100644
index 000000000..245ae245e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccapi/winccld.h
@@ -0,0 +1,203 @@
+/*
+ * winccld.h -- the dynamic loaded version of the ccache DLL
+ */
+
+
+#ifndef KRB5_WINCCLD_H_
+#define KRB5_WINCCLD_H_
+
+#ifdef USE_CCAPI_V3
+#include <CredentialsCache.h>
+#else
+
+#ifndef CC_API_VER2
+#define CC_API_VER2
+#endif
+
+#include "cacheapi.h"
+#endif
+
+#ifdef USE_CCAPI_V3
+typedef CCACHE_API cc_int32 (*FP_cc_initialize) (
+        cc_context_t*           outContext,
+        cc_int32                inVersion,
+        cc_int32*               outSupportedVersion,
+        char const**            outVendor);
+#else
+typedef cc_int32 (*FP_cc_initialize)(apiCB**, const cc_int32, 
+			cc_int32*, const char**);     
+typedef cc_int32 (*FP_cc_shutdown)(apiCB**);            
+typedef cc_int32 (*FP_cc_get_change_time)(apiCB*, cc_time_t*);    
+typedef cc_int32 (*FP_cc_create)(apiCB*, const char*, const char*,
+			const enum cc_cred_vers, const cc_int32, ccache_p**);
+typedef cc_int32 (*FP_cc_open)(apiCB*, const char*, const enum cc_cred_vers,
+			const cc_int32, ccache_p**);
+typedef cc_int32 (*FP_cc_close)(apiCB*, ccache_p**);
+typedef cc_int32 (*FP_cc_destroy)(apiCB*, ccache_p**);
+typedef cc_int32 (*FP_cc_seq_fetch_NCs)(apiCB*, ccache_p**, ccache_cit**);
+typedef cc_int32 (*FP_cc_seq_fetch_NCs_begin)(apiCB*, ccache_cit**);
+typedef cc_int32 (*FP_cc_seq_fetch_NCs_next)(apiCB*, ccache_p**, ccache_cit*);
+typedef cc_int32 (*FP_cc_seq_fetch_NCs_end)(apiCB*, ccache_cit**);
+typedef cc_int32 (*FP_cc_get_NC_info)(apiCB*, struct _infoNC***);
+typedef cc_int32 (*FP_cc_free_NC_info)(apiCB*, struct _infoNC***);
+typedef cc_int32 (*FP_cc_get_name)(apiCB*, const ccache_p*, char**);
+typedef cc_int32 (*FP_cc_set_principal)(apiCB*, const ccache_p*,
+			const enum cc_cred_vers, const char*);
+typedef cc_int32 (*FP_cc_get_principal)(apiCB*, ccache_p*, char**);
+typedef cc_int32 (*FP_cc_get_cred_version)(apiCB*, const ccache_p*,
+			enum cc_cred_vers*);
+typedef cc_int32 (*FP_cc_lock_request)(apiCB*, const ccache_p*,
+			const cc_int32);
+typedef cc_int32 (*FP_cc_store)(apiCB*, const ccache_p*, const cred_union);
+typedef cc_int32 (*FP_cc_remove_cred)(apiCB*, const ccache_p*,
+			const cred_union);
+typedef cc_int32 (*FP_cc_seq_fetch_creds)(apiCB*, const ccache_p*, 
+			cred_union**, ccache_cit**);
+typedef cc_int32 (*FP_cc_seq_fetch_creds_begin)(apiCB*, const ccache_p*, 
+			ccache_cit**);
+typedef cc_int32 (*FP_cc_seq_fetch_creds_next)(apiCB*, cred_union**, 
+			ccache_cit*);
+typedef cc_int32 (*FP_cc_seq_fetch_creds_end)(apiCB*, ccache_cit**);
+typedef cc_int32 (*FP_cc_free_principal)(apiCB*, char**);
+typedef cc_int32 (*FP_cc_free_name)(apiCB*, char** name);
+typedef cc_int32 (*FP_cc_free_creds)(apiCB*, cred_union** pCred);
+#endif
+
+#ifdef KRB5_WINCCLD_C_
+typedef struct _FUNC_INFO {
+    void** func_ptr_var;
+    char* func_name;
+} FUNC_INFO;
+
+#define DECL_FUNC_PTR(x) FP_##x p##x
+#define MAKE_FUNC_INFO(x) { (void**) &p##x, #x }
+#define END_FUNC_INFO { 0, 0 }
+#else
+#define DECL_FUNC_PTR(x) extern FP_##x p##x
+#endif
+
+DECL_FUNC_PTR(cc_initialize);
+#ifndef USE_CCAPI_V3
+DECL_FUNC_PTR(cc_shutdown);
+DECL_FUNC_PTR(cc_get_change_time);
+DECL_FUNC_PTR(cc_create);
+DECL_FUNC_PTR(cc_open);
+DECL_FUNC_PTR(cc_close);
+DECL_FUNC_PTR(cc_destroy);
+#if 0 /* Not used */
+#ifdef CC_API_VER2
+DECL_FUNC_PTR(cc_seq_fetch_NCs_begin);
+DECL_FUNC_PTR(cc_seq_fetch_NCs_next);
+DECL_FUNC_PTR(cc_seq_fetch_NCs_end);
+#else
+DECL_FUNC_PTR(cc_seq_fetch_NCs);
+#endif
+DECL_FUNC_PTR(cc_get_NC_info);
+DECL_FUNC_PTR(cc_free_NC_info);
+#endif
+DECL_FUNC_PTR(cc_get_name);
+DECL_FUNC_PTR(cc_set_principal);
+DECL_FUNC_PTR(cc_get_principal);
+DECL_FUNC_PTR(cc_get_cred_version);
+#if 0 /* Not used */
+DECL_FUNC_PTR(cc_lock_request);
+#endif
+DECL_FUNC_PTR(cc_store);
+DECL_FUNC_PTR(cc_remove_cred);
+#ifdef CC_API_VER2
+DECL_FUNC_PTR(cc_seq_fetch_creds_begin);
+DECL_FUNC_PTR(cc_seq_fetch_creds_next);
+DECL_FUNC_PTR(cc_seq_fetch_creds_end);
+#else
+DECL_FUNC_PTR(cc_seq_fetch_creds);
+#endif
+DECL_FUNC_PTR(cc_free_principal);
+DECL_FUNC_PTR(cc_free_name);
+DECL_FUNC_PTR(cc_free_creds);
+#endif
+
+#ifdef KRB5_WINCCLD_C_
+FUNC_INFO krbcc_fi[] = {
+    MAKE_FUNC_INFO(cc_initialize),
+#ifndef USE_CCAPI_V3
+    MAKE_FUNC_INFO(cc_shutdown),
+    MAKE_FUNC_INFO(cc_get_change_time),
+    MAKE_FUNC_INFO(cc_create),
+    MAKE_FUNC_INFO(cc_open),
+    MAKE_FUNC_INFO(cc_close),
+    MAKE_FUNC_INFO(cc_destroy),
+#if 0 /* Not used */
+    MAKE_FUNC_INFO(cc_seq_fetch_NCs),
+    MAKE_FUNC_INFO(cc_get_NC_info),
+    MAKE_FUNC_INFO(cc_free_NC_info),
+#endif
+    MAKE_FUNC_INFO(cc_get_name),
+    MAKE_FUNC_INFO(cc_set_principal),
+    MAKE_FUNC_INFO(cc_get_principal),
+    MAKE_FUNC_INFO(cc_get_cred_version),
+#if 0 /* Not used */
+    MAKE_FUNC_INFO(cc_lock_request),
+#endif
+    MAKE_FUNC_INFO(cc_store),
+    MAKE_FUNC_INFO(cc_remove_cred),
+#ifdef CC_API_VER2
+    MAKE_FUNC_INFO(cc_seq_fetch_creds_begin),
+    MAKE_FUNC_INFO(cc_seq_fetch_creds_next),
+    MAKE_FUNC_INFO(cc_seq_fetch_creds_end),
+#else
+    MAKE_FUNC_INFO(cc_seq_fetch_creds),
+#endif
+    MAKE_FUNC_INFO(cc_free_principal),
+    MAKE_FUNC_INFO(cc_free_name),
+    MAKE_FUNC_INFO(cc_free_creds),
+#endif
+    END_FUNC_INFO
+};
+#undef MAKE_FUNC_INFO
+#undef END_FUNC_INFO
+#else
+
+#define cc_initialize pcc_initialize
+#ifndef USE_CCAPI_V3
+#define cc_shutdown pcc_shutdown
+#define cc_get_change_time pcc_get_change_time
+#define cc_create pcc_create
+#define cc_open pcc_open
+#define cc_close pcc_close
+#define cc_destroy pcc_destroy
+#if 0 /* Not used */
+#ifdef CC_API_VER2
+#define cc_seq_fetch_NCs_begin pcc_seq_fetch_NCs_begin
+#define cc_seq_fetch_NCs_next pcc_seq_fetch_NCs_next
+#define cc_seq_fetch_NCs_end pcc_seq_fetch_NCs_end
+#else
+#define cc_seq_fetch_NCs pcc_seq_fetch_NCs
+#endif
+#define cc_get_NC_info pcc_get_NC_info
+#define cc_free_NC_info pcc_free_NC_info
+#endif /* End of Not used */
+#define cc_get_name pcc_get_name
+#define cc_set_principal pcc_set_principal
+#define cc_get_principal pcc_get_principal
+#define cc_get_cred_version pcc_get_cred_version
+#if 0 /* Not used */
+#define cc_lock_request pcc_lock_request
+#endif
+#define cc_store pcc_store
+#define cc_remove_cred pcc_remove_cred
+#ifdef CC_API_VER2
+#define cc_seq_fetch_creds_begin pcc_seq_fetch_creds_begin
+#define cc_seq_fetch_creds_next pcc_seq_fetch_creds_next
+#define cc_seq_fetch_creds_end pcc_seq_fetch_creds_end
+#else
+#define cc_seq_fetch_creds pcc_seq_fetch_creds
+#endif
+#define cc_free_principal pcc_free_principal
+#define cc_free_name pcc_free_name
+#define cc_free_creds pcc_free_creds
+#endif
+#endif
+
+#undef DECL_FUNC_PTR
+
+#endif /* KRB5_WINCCLD_H_ */
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccbase.c b/krb5-1-6/src/lib/krb5/ccache/ccbase.c
new file mode 100644
index 000000000..1a9f5afc5
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccbase.c
@@ -0,0 +1,346 @@
+/*
+ * lib/krb5/ccache/ccbase.c
+ *
+ * Copyright 1990,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Registration functions for ccache.
+ */
+
+#include "k5-int.h"
+#include "k5-thread.h"
+
+#include "fcc.h"
+#include "cc-int.h"
+
+struct krb5_cc_typelist {
+    const krb5_cc_ops *ops;
+    struct krb5_cc_typelist *next;
+};
+
+struct krb5_cc_typecursor {
+    struct krb5_cc_typelist *tptr;
+};
+/* typedef krb5_cc_typecursor in k5-int.h */
+
+extern const krb5_cc_ops krb5_mcc_ops;
+#ifdef USE_KEYRING_CCACHE
+extern const krb5_cc_ops krb5_krcc_ops;
+#endif
+
+#ifdef _WIN32
+extern const krb5_cc_ops krb5_lcc_ops;
+static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL };
+static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry };
+#else
+
+#ifdef USE_CCAPI_V3
+extern const krb5_cc_ops krb5_cc_stdcc_ops;
+static struct krb5_cc_typelist cc_stdcc_entry = { &krb5_cc_stdcc_ops, NULL };
+static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_stdcc_entry };
+#else
+
+static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL };
+#endif /* USE_CCAPI_V3 */
+
+#ifdef USE_KEYRING_CCACHE
+static struct krb5_cc_typelist cc_file_entry = { &krb5_cc_file_ops,
+						 &cc_mcc_entry };
+static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops,
+						 &cc_file_entry };
+#endif /* USE_KEYRING_CCACHE */
+#endif
+
+static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops,
+						&cc_mcc_entry };
+#ifdef USE_KEYRING_CCACHE
+#define INITIAL_TYPEHEAD (&cc_krcc_entry)
+#else
+#define INITIAL_TYPEHEAD (&cc_fcc_entry)
+#endif
+static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD;
+static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+static krb5_error_code
+krb5int_cc_getops(krb5_context, const char *, const krb5_cc_ops **);
+
+int
+krb5int_cc_initialize(void)
+{
+    int err;
+
+    err = k5_mutex_finish_init(&krb5int_mcc_mutex);
+    if (err)
+	return err;
+    err = k5_mutex_finish_init(&cc_typelist_lock);
+    if (err)
+	return err;
+    err = k5_mutex_finish_init(&krb5int_cc_file_mutex);
+    if (err)
+	return err;
+#ifdef USE_KEYRING_CCACHE
+    err = k5_mutex_finish_init(&krb5int_krcc_mutex);
+    if (err)
+	return err;
+#endif
+    return 0;
+}
+
+void
+krb5int_cc_finalize(void)
+{
+    struct krb5_cc_typelist *t, *t_next;
+    k5_mutex_destroy(&cc_typelist_lock);
+    k5_mutex_destroy(&krb5int_cc_file_mutex);
+    k5_mutex_destroy(&krb5int_mcc_mutex);
+#ifdef USE_KEYRING_CCACHE
+    k5_mutex_destroy(&krb5int_krcc_mutex);
+#endif
+    for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) {
+	t_next = t->next;
+	free(t);
+    }
+}
+
+
+/*
+ * Register a new credentials cache type
+ * If override is set, replace any existing ccache with that type tag
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override)
+{
+    struct krb5_cc_typelist *t;
+    krb5_error_code err;
+
+    err = k5_mutex_lock(&cc_typelist_lock);
+    if (err)
+	return err;
+    for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
+	;
+    if (t) {
+	if (override) {
+	    t->ops = ops;
+	    k5_mutex_unlock(&cc_typelist_lock);
+	    return 0;
+	} else {
+	    k5_mutex_unlock(&cc_typelist_lock);
+	    return KRB5_CC_TYPE_EXISTS;
+	}
+    }
+    if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) {
+	k5_mutex_unlock(&cc_typelist_lock);
+	return ENOMEM;
+    }
+    t->next = cc_typehead;
+    t->ops = ops;
+    cc_typehead = t;
+    k5_mutex_unlock(&cc_typelist_lock);
+    return 0;
+}
+
+/*
+ * Resolve a credential cache name into a cred. cache object.
+ *
+ * The name is currently constrained to be of the form "type:residual";
+ *
+ * The "type" portion corresponds to one of the predefined credential
+ * cache types, while the "residual" portion is specific to the
+ * particular cache type.
+ */
+
+#include <ctype.h>
+krb5_error_code KRB5_CALLCONV
+krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
+{
+    char *pfx, *cp;
+    const char *resid;
+    unsigned int pfxlen;
+    krb5_error_code err;
+    const krb5_cc_ops *ops;
+
+    pfx = NULL;
+    cp = strchr (name, ':');
+    if (!cp) {
+	if (krb5_cc_dfl_ops)
+	    return (*krb5_cc_dfl_ops->resolve)(context, cache, name);
+	else
+	    return KRB5_CC_BADNAME;
+    }
+
+    pfxlen = cp - name;
+
+    if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
+        /* We found a drive letter not a prefix - use FILE */
+        pfx = strdup("FILE");
+        if (!pfx)
+            return ENOMEM;
+
+        resid = name;
+    } else {
+        resid = name + pfxlen + 1;
+
+        pfx = malloc (pfxlen+1);
+        if (!pfx)
+            return ENOMEM;
+
+        memcpy (pfx, name, pfxlen);
+        pfx[pfxlen] = '\0';
+    }
+
+    *cache = (krb5_ccache) 0;
+
+    err = krb5int_cc_getops(context, pfx, &ops);
+    if (pfx != NULL)
+	free(pfx);
+    if (err)
+	return err;
+
+    return ops->resolve(context, cache, resid);
+}
+
+/*
+ * cc_getops
+ *
+ * Internal function to return the ops vector for a given ccache
+ * prefix string.
+ */
+static krb5_error_code
+krb5int_cc_getops(
+    krb5_context context,
+    const char *pfx,
+    const krb5_cc_ops **ops)
+{
+    krb5_error_code err;
+    struct krb5_cc_typelist *tlist;
+
+    err = k5_mutex_lock(&cc_typelist_lock);
+    if (err)
+	return err;
+
+    for (tlist = cc_typehead; tlist; tlist = tlist->next) {
+	if (strcmp (tlist->ops->prefix, pfx) == 0) {
+	    *ops = tlist->ops;
+	    k5_mutex_unlock(&cc_typelist_lock);
+	    return 0;
+	}
+    }
+    k5_mutex_unlock(&cc_typelist_lock);
+    if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) {
+	*ops = krb5_cc_dfl_ops;
+	return 0;
+    }
+    return KRB5_CC_UNKNOWN_TYPE;
+}
+
+/*
+ * cc_new_unique
+ *
+ * Generate a new unique ccache, given a ccache type and a hint
+ * string.  Ignores the hint string for now.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_cc_new_unique(
+    krb5_context context,
+    const char *type,
+    const char *hint,
+    krb5_ccache *id)
+{
+    const krb5_cc_ops *ops;
+    krb5_error_code err;
+
+    *id = NULL;
+
+    err = krb5int_cc_getops(context, type, &ops);
+    if (err)
+	return err;
+
+    return ops->gen_new(context, id);
+}
+
+/*
+ * cc_typecursor
+ *
+ * Note: to avoid copying the typelist at cursor creation time, among
+ * other things, we assume that the only additions ever occur to the
+ * typelist.
+ */
+krb5_error_code
+krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *t)
+{
+    krb5_error_code err = 0;
+    krb5_cc_typecursor n = NULL;
+
+    *t = NULL;
+    n = malloc(sizeof(*n));
+    if (n == NULL)
+	return ENOMEM;
+
+    err = k5_mutex_lock(&cc_typelist_lock);
+    if (err)
+	goto errout;
+    n->tptr = cc_typehead;
+    err = k5_mutex_unlock(&cc_typelist_lock);
+    if (err)
+	goto errout;
+
+    *t = n;
+errout:
+    if (err)
+	free(n);
+    return err;
+}
+
+krb5_error_code
+krb5int_cc_typecursor_next(
+    krb5_context context,
+    krb5_cc_typecursor t,
+    const krb5_cc_ops **ops)
+{
+    krb5_error_code err = 0;
+
+    *ops = NULL;
+    if (t->tptr == NULL)
+	return 0;
+
+    err = k5_mutex_lock(&cc_typelist_lock);
+    if (err)
+	goto errout;
+    *ops = t->tptr->ops;
+    t->tptr = t->tptr->next;
+    err = k5_mutex_unlock(&cc_typelist_lock);
+    if (err)
+	goto errout;
+
+errout:
+    return err;
+}
+
+krb5_error_code
+krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t)
+{
+    free(*t);
+    *t = NULL;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/cccopy.c b/krb5-1-6/src/lib/krb5/ccache/cccopy.c
new file mode 100644
index 000000000..a9a45b501
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cccopy.c
@@ -0,0 +1,62 @@
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_copy_creds(krb5_context context, krb5_ccache incc, krb5_ccache outcc)
+{
+    krb5_error_code code;
+    krb5_flags flags;
+    krb5_cc_cursor cur = 0;
+    krb5_creds creds;
+
+    flags = 0;				/* turns off OPENCLOSE mode */
+    if ((code = krb5_cc_set_flags(context, incc, flags)))
+	return(code);
+    /* the code for this will open the file for reading only, which
+       is not what I had in mind.  So I won't turn off OPENCLOSE
+       for the output ccache */
+#if 0
+    if ((code = krb5_cc_set_flags(context, outcc, flags)))
+	return(code);
+#endif
+
+    if ((code = krb5_cc_start_seq_get(context, incc, &cur)))
+	goto cleanup;
+
+    while (!(code = krb5_cc_next_cred(context, incc, &cur, &creds))) {
+	code = krb5_cc_store_cred(context, outcc, &creds);
+	krb5_free_cred_contents(context, &creds);
+	if (code)
+	    goto cleanup;
+    }
+
+    if (code != KRB5_CC_END)
+	goto cleanup;
+
+    code = krb5_cc_end_seq_get(context, incc, &cur);
+    cur = 0;
+    if (code)
+        goto cleanup;
+
+    code = 0;
+
+cleanup:
+    flags = KRB5_TC_OPENCLOSE;
+
+    /* If set then we are in an error pathway */
+    if (cur) 
+      krb5_cc_end_seq_get(context, incc, &cur);
+
+    if (code)
+	krb5_cc_set_flags(context, incc, flags);
+    else
+	code = krb5_cc_set_flags(context, incc, flags);
+
+#if 0
+    if (code)
+	krb5_cc_set_flags(context, outcc, flags);
+    else
+	code = krb5_cc_set_flags(context, outcc, flags);
+#endif
+
+    return(code);
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/cccursor.c b/krb5-1-6/src/lib/krb5/ccache/cccursor.c
new file mode 100644
index 000000000..ab6f2a971
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/cccursor.c
@@ -0,0 +1,330 @@
+/*
+ * lib/krb5/ccache/cccursor.c
+ *
+ * Copyright 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * cursor for sequential traversal of ccaches
+ */
+
+#include "k5-int.h"
+
+#include <assert.h>
+
+#define CCCURSOR_CONTEXT 1
+#define CCCURSOR_ENV 2
+#define CCCURSOR_OS 3
+#define CCCURSOR_PERTYPE 4
+
+#define NFULLNAMES 3
+
+/* Prefix and residual parts of a full ccache name. */
+struct cc_fullname {
+    char *pfx;
+    char *res;
+};
+
+struct _krb5_cccol_cursor {
+    int pos;
+    krb5_cc_typecursor typecursor;
+    const krb5_cc_ops *ops;
+    krb5_cc_ptcursor ptcursor;
+    int cur_fullname;
+    struct cc_fullname fullnames[NFULLNAMES]; /* previously seen ccaches */
+};
+/* typedef of krb5_cccol_cursor is in krb5.h */
+
+static int cccol_already(krb5_context, krb5_cccol_cursor, krb5_ccache *);
+
+static int cccol_cmpname(const char *, const char *, struct cc_fullname *);
+
+static krb5_error_code
+cccol_do_resolve(krb5_context, krb5_cccol_cursor, const char *, krb5_ccache *);
+
+static krb5_error_code
+cccol_pertype_next(krb5_context, krb5_cccol_cursor, krb5_ccache *);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_cursor_new(
+    krb5_context context,
+    krb5_cccol_cursor *cursor)
+{
+    krb5_error_code ret = 0;
+    krb5_cccol_cursor n = NULL;
+    int i;
+
+    *cursor = NULL;
+    n = malloc(sizeof(*n));
+    if (n == NULL)
+	return ENOMEM;
+
+    n->pos = CCCURSOR_CONTEXT;
+    n->typecursor = NULL;
+    n->ptcursor = NULL;
+    n->ops = NULL;
+
+    for (i = 0; i < NFULLNAMES; i++) {
+	n->fullnames[i].pfx = n->fullnames[i].res = NULL;
+    }
+    n->cur_fullname = 0;
+    ret = krb5int_cc_typecursor_new(context, &n->typecursor);
+    if (ret)
+	goto errout;
+
+    do {
+	/* Find first backend with ptcursor functionality. */
+	ret = krb5int_cc_typecursor_next(context, n->typecursor, &n->ops);
+	if (ret || n->ops == NULL)
+	    goto errout;
+    } while (n->ops->ptcursor_new == NULL);
+
+    ret = n->ops->ptcursor_new(context, &n->ptcursor);
+    if (ret)
+	goto errout;
+
+errout:
+    if (ret) {
+	krb5_cccol_cursor_free(context, &n);
+    }
+    *cursor = n;
+    return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_cursor_next(
+    krb5_context context,
+    krb5_cccol_cursor cursor,
+    krb5_ccache *ccache)
+{
+    krb5_error_code ret = 0;
+    char *name;
+    krb5_os_context os_ctx = NULL;
+
+    *ccache = NULL;
+    os_ctx = context->os_context;
+
+    switch (cursor->pos) {
+    case CCCURSOR_CONTEXT:
+	name = os_ctx->default_ccname;
+	if (name != NULL) {
+	    cursor->pos = CCCURSOR_ENV;
+	    ret = cccol_do_resolve(context, cursor, name, ccache);
+	    if (ret)
+		goto errout;
+	    if (*ccache != NULL)
+		break;
+	}
+	/* fall through */
+    case CCCURSOR_ENV:
+	name = getenv(KRB5_ENV_CCNAME);
+	if (name != NULL) {
+	    cursor->pos = CCCURSOR_OS;
+	    ret = cccol_do_resolve(context, cursor, name, ccache);
+	    if (ret)
+		goto errout;
+	    if (*ccache != NULL)
+		break;
+	}
+	/* fall through */
+    case CCCURSOR_OS:
+	ret = krb5int_cc_os_default_name(context, &name);
+	if (ret) goto errout;
+	if (name != NULL) {
+	    cursor->pos = CCCURSOR_PERTYPE;
+	    ret = cccol_do_resolve(context, cursor, name, ccache);
+	    free(name);
+	    if (ret)
+		goto errout;
+	    if (*ccache != NULL)
+		break;
+	}
+	/* fall through */
+    case CCCURSOR_PERTYPE:
+	cursor->pos = CCCURSOR_PERTYPE;
+	do {
+	    ret = cccol_pertype_next(context, cursor, ccache);
+	    if (ret)
+		goto errout;
+	} while (cccol_already(context, cursor, ccache));
+	break;
+    }
+errout:
+    return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_cursor_free(
+    krb5_context context,
+    krb5_cccol_cursor *cursor)
+{
+    krb5_cccol_cursor c = *cursor;
+    int i;
+
+    if (c == NULL)
+	return 0;
+
+    for (i = 0; i < NFULLNAMES; i++) {
+	if (c->fullnames[i].pfx != NULL)
+	    free(c->fullnames[i].pfx);
+	if (c->fullnames[i].res != NULL)
+	    free(c->fullnames[i].res);
+    }
+    if (c->ptcursor != NULL)
+	c->ops->ptcursor_free(context, &c->ptcursor);
+    if (c->typecursor != NULL)
+	krb5int_cc_typecursor_free(context, &c->typecursor);
+    free(c);
+
+    *cursor = NULL;
+    return 0;
+}
+
+/*
+ * Determine if a ccache from a per-type cursor was already one of the
+ * higher-priority defaults.
+ */
+static int
+cccol_already(
+    krb5_context context,
+    krb5_cccol_cursor c,
+    krb5_ccache *ccache)
+{
+    const char *name = NULL, *prefix = NULL;
+    int i;
+
+    if (*ccache == NULL)
+	return 0;
+    name = krb5_cc_get_name(context, *ccache);
+    if (name == NULL)
+	return 0;
+    prefix = krb5_cc_get_type(context, *ccache);
+
+    assert(c->cur_fullname < NFULLNAMES);
+    for (i = 0; i < c->cur_fullname; i++) {
+	if (cccol_cmpname(prefix, name, &c->fullnames[i])) {
+	    krb5_cc_close(context, *ccache);
+	    *ccache = NULL;
+	    return 1;
+	}
+    }
+    return 0;
+}
+
+/*
+ * Compare {prefix, name} against a cc_fullname.
+ */
+static int
+cccol_cmpname(
+    const char *prefix,
+    const char *name,
+    struct cc_fullname *fullname)
+{
+    if (fullname->pfx == NULL || fullname->res == NULL)
+	return 0;
+    if (strcmp(prefix, fullname->pfx))
+	return 0;
+    if (strcmp(name, fullname->res))
+	return 0;
+
+    return 1;
+}
+
+/*
+ * Resolve one of the high-precedence ccaches, and cache its full name
+ * {prefix, residual} for exclusion when doing per-type ccache
+ * iteration.  Also check to see if we've already seen the ccache
+ * name we're given.
+ */
+static krb5_error_code
+cccol_do_resolve(
+    krb5_context context,
+    krb5_cccol_cursor cursor,
+    const char *name,
+    krb5_ccache *ccache)
+{
+    krb5_error_code ret = 0;
+    struct cc_fullname *fullname;
+
+    assert(cursor->cur_fullname < NFULLNAMES);
+    ret = krb5_cc_resolve(context, name, ccache);
+    if (ret)
+	return ret;
+
+    if (cccol_already(context, cursor, ccache))
+	return 0;
+
+    fullname = &cursor->fullnames[cursor->cur_fullname];
+    fullname->pfx = strdup(krb5_cc_get_type(context, *ccache));
+    fullname->res = strdup(krb5_cc_get_name(context, *ccache));
+    cursor->cur_fullname++;
+    return ret;
+}
+
+/*
+ * Find next ccache in current backend, iterating through backends if
+ * ccache list of the current backend is exhausted.
+ */
+static krb5_error_code
+cccol_pertype_next(
+    krb5_context context,
+    krb5_cccol_cursor cursor,
+    krb5_ccache *ccache)
+{
+    krb5_error_code ret = 0;
+
+    *ccache = NULL;
+
+    /* Are we out of backends? */
+    if (cursor->ops == NULL)
+	return 0;
+    /*
+     * Loop in case there are multiple backends with empty ccache
+     * lists.
+     */
+    while (*ccache == NULL) {
+	ret = cursor->ops->ptcursor_next(context, cursor->ptcursor, ccache);
+	if (ret)
+	    goto errout;
+	if (*ccache != NULL)
+	    return 0;
+
+	ret = cursor->ops->ptcursor_free(context, &cursor->ptcursor);
+	if (ret)
+	    goto errout;
+
+	do {
+	    /* Find first backend with ptcursor functionality. */
+	    ret = krb5int_cc_typecursor_next(context, cursor->typecursor,
+					     &cursor->ops);
+	    if (ret)
+		goto errout;
+	    if (cursor->ops == NULL)
+		return 0;
+	} while (cursor->ops->ptcursor_new == NULL);
+
+	ret = cursor->ops->ptcursor_new(context, &cursor->ptcursor);
+	if (ret)
+	    goto errout;
+    }
+errout:
+    return ret;
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccdefault.c b/krb5-1-6/src/lib/krb5/ccache/ccdefault.c
new file mode 100644
index 000000000..d36b10474
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccdefault.c
@@ -0,0 +1,114 @@
+/*
+ * lib/krb5/ccache/ccdefault.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Find default credential cache
+ */
+
+#include "k5-int.h"
+
+#if defined(USE_LOGIN_LIBRARY)
+#include "KerberosLoginPrivate.h"
+#elif defined(USE_LEASH)
+static void (*pLeash_AcquireInitialTicketsIfNeeded)(krb5_context,krb5_principal,char*,int) = NULL;
+static HANDLE hLeashDLL = INVALID_HANDLE_VALUE;
+#ifdef _WIN64
+#define LEASH_DLL "leashw64.dll"
+#else
+#define LEASH_DLL "leashw32.dll"
+#endif
+#endif
+
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_default(krb5_context context, krb5_ccache *ccache)
+{
+	krb5_os_context	os_ctx;
+
+	if (!context || context->magic != KV5M_CONTEXT)
+		return KV5M_CONTEXT;
+	
+	os_ctx = context->os_context;
+	
+	return krb5_cc_resolve(context, krb5_cc_default_name(context), ccache);
+}
+
+/* This is the internal function which opens the default ccache.  On platforms supporting
+   the login library's automatic popup dialog to get tickets, this function also updated the
+   library's internal view of the current principal associated with this cache. 
+   
+   All krb5 and GSS functions which need to open a cache to get a tgt to obtain service tickets
+   should call this function, not krb5_cc_default() */
+
+krb5_error_code KRB5_CALLCONV
+krb5int_cc_default(krb5_context context, krb5_ccache *ccache)
+{
+    if (!context || context->magic != KV5M_CONTEXT) {
+        return KV5M_CONTEXT;
+    }
+
+#ifdef USE_LOGIN_LIBRARY
+    {
+        /* make sure the default cache has tix before you open it */
+        KLStatus err = klNoErr;
+        char *outCacheName = NULL;
+        
+        /* Try to make sure a krb5 tgt is in the cache */
+        err = __KLInternalAcquireInitialTicketsForCache (krb5_cc_default_name (context), kerberosVersion_V5, 
+                                                         NULL, NULL, &outCacheName);
+        if (err == klNoErr) {
+            /* This function tries to get tickets and put them in the specified 
+            cache, however, if the cache does not exist, it may choose to put 
+            them elsewhere (ie: the system default) so we set that here */
+            if (strcmp (krb5_cc_default_name (context), outCacheName) != 0) {
+                krb5_cc_set_default_name (context, outCacheName);
+            }
+            KLDisposeString (outCacheName);
+        }
+    }
+#else
+#ifdef USE_LEASH
+    if ( hLeashDLL == INVALID_HANDLE_VALUE ) {
+        hLeashDLL = LoadLibrary(LEASH_DLL);
+        if ( hLeashDLL != INVALID_HANDLE_VALUE ) {
+            (FARPROC) pLeash_AcquireInitialTicketsIfNeeded =
+            GetProcAddress(hLeashDLL, "not_an_API_Leash_AcquireInitialTicketsIfNeeded");
+        }
+    }
+    
+    if ( pLeash_AcquireInitialTicketsIfNeeded ) {
+	char ccname[256]="";
+        pLeash_AcquireInitialTicketsIfNeeded(context, NULL, ccname, sizeof(ccname));
+	if (ccname[0]) {
+            if (strcmp (krb5_cc_default_name (context),ccname) != 0) {
+                krb5_cc_set_default_name (context, ccname);
+            }
+	}
+    }
+#endif
+#endif
+
+    return krb5_cc_default (context, ccache);
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccdefops.c b/krb5-1-6/src/lib/krb5/ccache/ccdefops.c
new file mode 100644
index 000000000..cdeab0674
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccdefops.c
@@ -0,0 +1,50 @@
+/*
+ * lib/krb5/ccache/ccdefops.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Default credentials cache determination.  This is a separate file
+ * so that the user can more easily override it.
+ */
+
+#include "k5-int.h"
+
+#if defined(USE_CCAPI)
+
+/*
+ * Macs use the shared, memory based credentials cache
+ * Windows may also use the ccapi cache, but only if the Krbcc32.dll
+ * can be found; otherwise it falls back to using the old 
+ * file-based ccache.
+ */
+#include "stdcc.h" /* from ccapi subdir */
+
+const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_stdcc_ops;
+
+#else
+
+#include "fcc.h"
+const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_file_ops;
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/ccache/ccfns.c b/krb5-1-6/src/lib/krb5/ccache/ccfns.c
new file mode 100644
index 000000000..15bc87df6
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ccfns.c
@@ -0,0 +1,168 @@
+/*
+ * lib/krb5/ccache/ccfns.c
+ *
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Dispatch methods for credentials cache code.
+ */
+
+#include "k5-int.h"
+
+const char * KRB5_CALLCONV
+krb5_cc_get_name (krb5_context context, krb5_ccache cache)
+{
+    return cache->ops->get_name(context, cache);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_gen_new (krb5_context context, krb5_ccache *cache)
+{
+    return (*cache)->ops->gen_new(context, cache);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_initialize(krb5_context context, krb5_ccache cache,
+		   krb5_principal principal)
+{
+    return cache->ops->init(context, cache, principal);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_destroy (krb5_context context, krb5_ccache cache)
+{
+    return cache->ops->destroy(context, cache);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_close (krb5_context context, krb5_ccache cache)
+{
+    return cache->ops->close(context, cache);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_store_cred (krb5_context context, krb5_ccache cache,
+		    krb5_creds *creds)
+{
+    krb5_error_code ret;
+    krb5_ticket *tkt;
+    krb5_principal s1, s2;
+
+    ret = cache->ops->store(context, cache, creds);
+    if (ret) return ret;
+
+    /*
+     * If creds->server and the server in the decoded ticket differ,
+     * store both principals.
+     */
+    s1 = creds->server;
+    ret = decode_krb5_ticket(&creds->ticket, &tkt);
+    /* Bail out on errors in case someone is storing a non-ticket. */
+    if (ret) return 0;
+    s2 = tkt->server;
+    if (!krb5_principal_compare(context, s1, s2)) {
+	creds->server = s2;
+	ret = cache->ops->store(context, cache, creds);
+	creds->server = s1;
+    }
+    krb5_free_ticket(context, tkt);
+    return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_retrieve_cred (krb5_context context, krb5_ccache cache,
+		       krb5_flags flags, krb5_creds *mcreds,
+		       krb5_creds *creds)
+{
+    krb5_error_code ret;
+    krb5_data tmprealm;
+
+    ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+    if (ret != KRB5_CC_NOTFOUND)
+	return ret;
+    if (!krb5_is_referral_realm(&mcreds->server->realm))
+	return ret;
+
+    /*
+     * Retry using client's realm if service has referral realm.
+     */
+    tmprealm = mcreds->server->realm;
+    mcreds->server->realm = mcreds->client->realm;
+    ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+    mcreds->server->realm = tmprealm;
+    return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_get_principal (krb5_context context, krb5_ccache cache,
+		       krb5_principal *principal)
+{
+    return cache->ops->get_princ(context, cache, principal);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_start_seq_get (krb5_context context, krb5_ccache cache,
+		       krb5_cc_cursor *cursor)
+{
+    return cache->ops->get_first(context, cache, cursor);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_next_cred (krb5_context context, krb5_ccache cache,
+		   krb5_cc_cursor *cursor, krb5_creds *creds)
+{
+    return cache->ops->get_next(context, cache, cursor, creds);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_end_seq_get (krb5_context context, krb5_ccache cache,
+		     krb5_cc_cursor *cursor)
+{
+    return cache->ops->end_get(context, cache, cursor);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_remove_cred (krb5_context context, krb5_ccache cache, krb5_flags flags,
+		     krb5_creds *creds)
+{
+    return cache->ops->remove_cred(context, cache, flags, creds);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_set_flags (krb5_context context, krb5_ccache cache, krb5_flags flags)
+{
+    return cache->ops->set_flags(context, cache, flags);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_get_flags (krb5_context context, krb5_ccache cache, krb5_flags *flags)
+{
+    return cache->ops->get_flags(context, cache, flags);
+}
+
+const char * KRB5_CALLCONV
+krb5_cc_get_type (krb5_context context, krb5_ccache cache)
+{
+    return cache->ops->prefix;
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/fcc.h b/krb5-1-6/src/lib/krb5/ccache/fcc.h
new file mode 100644
index 000000000..f349da998
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/fcc.h
@@ -0,0 +1,36 @@
+/*
+ * lib/krb5/ccache/file/fcc.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This file contains constant and function declarations used in the
+ * file-based credential cache routines.
+ */
+
+#ifndef __KRB5_FILE_CCACHE__
+#define __KRB5_FILE_CCACHE__
+
+extern const krb5_cc_ops krb5_cc_file_ops;
+
+#endif /* __KRB5_FILE_CCACHE__ */
diff --git a/krb5-1-6/src/lib/krb5/ccache/scc.h b/krb5-1-6/src/lib/krb5/ccache/scc.h
new file mode 100644
index 000000000..98acbc25c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/scc.h
@@ -0,0 +1,101 @@
+/*
+ * lib/krb5/ccache/stdio/scc.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This file contains constant and function declarations used in the
+ * file-based credential cache routines.
+ */
+
+#ifndef __KRB5_FILE_CCACHE__
+#define __KRB5_FILE_CCACHE__
+
+#include "k5-int.h"
+#include <stdio.h>
+
+#define KRB5_OK 0
+
+#define KRB5_SCC_MAXLEN 100
+
+/*
+ * SCC version 2 contains type information for principals.  SCC
+ * version 1 does not.  The code will accept either, and depending on
+ * what KRB5_SCC_DEFAULT_FVNO is set to, it will create version 1 or
+ * version 2 SCC caches.
+ *
+ */
+
+#define KRB5_SCC_FVNO_1   0x0501	/* krb v5, scc v1 */
+#define KRB5_SCC_FVNO_2   0x0502	/* krb v5, scc v2 */
+#define KRB5_SCC_FVNO_3   0x0503	/* krb v5, scc v3 */
+#define KRB5_SCC_FVNO_4   0x0504	/* krb v5, scc v4 */
+
+#define	SCC_OPEN_AND_ERASE	1
+#define	SCC_OPEN_RDWR		2
+#define	SCC_OPEN_RDONLY		3
+
+/* Credential file header tags.
+ * The header tags are constructed as:
+ *     krb5_ui_2       tag
+ *     krb5_ui_2       len
+ *     krb5_octet      data[len]
+ * This format allows for older versions of the fcc processing code to skip
+ * past unrecognized tag formats.
+ */
+#define SCC_TAG_DELTATIME	1
+
+#ifndef TKT_ROOT
+#define TKT_ROOT "/tmp/tkt"
+#endif
+
+/* macros to make checking flags easier */
+#define OPENCLOSE(id) (((krb5_scc_data *)id->data)->flags & KRB5_TC_OPENCLOSE)
+
+typedef struct _krb5_scc_data {
+     char *filename;
+     FILE *file;
+     krb5_flags flags;
+     char stdio_buffer[BUFSIZ];
+     int version;
+} krb5_scc_data;
+
+/* An off_t can be arbitrarily complex */
+typedef struct _krb5_scc_cursor {
+    long pos;
+} krb5_scc_cursor;
+
+#define MAYBE_OPEN(context, ID, MODE) \
+{									\
+    if (OPENCLOSE (ID)) {						\
+	krb5_error_code maybe_open_ret = krb5_scc_open_file (context, ID,MODE);	\
+	if (maybe_open_ret) return maybe_open_ret; } }
+
+#define MAYBE_CLOSE(context, ID, RET) \
+{									\
+    if (OPENCLOSE (ID)) {						\
+	krb5_error_code maybe_close_ret = krb5_scc_close_file (context, ID);	\
+	if (!(RET)) RET = maybe_close_ret; } }
+
+/* DO NOT ADD ANYTHING AFTER THIS #endif */
+#endif /* __KRB5_FILE_CCACHE__ */
diff --git a/krb5-1-6/src/lib/krb5/ccache/ser_cc.c b/krb5-1-6/src/lib/krb5/ccache/ser_cc.c
new file mode 100644
index 000000000..a7d34f93d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/ser_cc.c
@@ -0,0 +1,202 @@
+/*
+ * lib/krb5/ccache/ser_rc.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_rcdfl.c - Serialize replay cache context.
+ */
+#include "k5-int.h"
+
+/*
+ * Routines to deal with externalizing krb5_ccache.
+ *	krb5_ccache_size();
+ *	krb5_ccache_externalize();
+ *	krb5_ccache_internalize();
+ */
+static krb5_error_code krb5_ccache_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_ccache_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_ccache_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/*
+ * Serialization entry for this type.
+ */
+static const krb5_ser_entry krb5_ccache_ser_entry = {
+    KV5M_CCACHE,			/* Type			*/
+    krb5_ccache_size,			/* Sizer routine	*/
+    krb5_ccache_externalize,		/* Externalize routine	*/
+    krb5_ccache_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_ccache_size()	- Determine the size required to externalize
+ *				  this krb5_ccache variant.
+ */
+static krb5_error_code
+krb5_ccache_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_ccache		ccache;
+    size_t		required;
+
+    kret = EINVAL;
+    if ((ccache = (krb5_ccache) arg)) {
+	/*
+	 * Saving FILE: variants of krb5_ccache requires at minimum:
+	 *	krb5_int32	for KV5M_CCACHE
+	 *	krb5_int32	for length of ccache name.
+	 *	krb5_int32	for KV5M_CCACHE
+	 */
+	required = sizeof(krb5_int32) * 3;
+	if (ccache->ops && ccache->ops->prefix)
+	    required += (strlen(ccache->ops->prefix)+1);
+
+	/*
+	 * The ccache name is formed as follows:
+	 *	<prefix>:<name>
+	 */
+	required += strlen(krb5_cc_get_name(kcontext, ccache));
+
+	kret = 0;
+	*sizep += required;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_ccache_externalize()	- Externalize the krb5_ccache.
+ */
+static krb5_error_code
+krb5_ccache_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_ccache		ccache;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    char		*ccname;
+    size_t		namelen;
+    const char		*fnamep;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((ccache = (krb5_ccache) arg)) {
+	kret = ENOMEM;
+	if (!krb5_ccache_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_CCACHE, &bp, &remain);
+
+	    /* Calculate the length of the name */
+	    namelen = (ccache->ops && ccache->ops->prefix) ?
+		strlen(ccache->ops->prefix)+1 : 0;
+	    fnamep = krb5_cc_get_name(kcontext, ccache);
+	    namelen += (strlen(fnamep)+1);
+
+	    if ((ccname = (char *) malloc(namelen))) {
+		/* Format the ccache name. */
+		if (ccache->ops && ccache->ops->prefix)
+		    sprintf(ccname, "%s:%s", ccache->ops->prefix, fnamep);
+		else
+		    strcpy(ccname, fnamep);
+
+		/* Put the length of the file name */
+		(void) krb5_ser_pack_int32((krb5_int32) strlen(ccname),
+					   &bp, &remain);
+		
+		/* Put the name */
+		(void) krb5_ser_pack_bytes((krb5_octet *) ccname,
+					   strlen(ccname),
+					   &bp, &remain);
+
+		/* Put the trailer */
+		(void) krb5_ser_pack_int32(KV5M_CCACHE, &bp, &remain);
+		kret = 0;
+		*buffer = bp;
+		*lenremain = remain;
+		free(ccname);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_ccache_internalize()	- Internalize the krb5_ccache.
+ */
+static krb5_error_code
+krb5_ccache_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_ccache		ccache;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    char		*ccname;
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KV5M_CCACHE) {
+	kret = ENOMEM;
+
+	/* Get the length of the ccache name */
+	kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+
+	if (!kret &&
+	    (ccname = (char *) malloc((size_t) (ibuf+1))) &&
+	    !(kret = krb5_ser_unpack_bytes((krb5_octet *) ccname,
+					   (size_t) ibuf,
+					   &bp, &remain))) {
+	    ccname[ibuf] = '\0';
+	    if (!(kret = krb5_cc_resolve(kcontext, ccname, &ccache)) &&
+		!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
+		(ibuf == KV5M_CCACHE)) {
+		*buffer = bp;
+		*lenremain = remain;
+		*argp = (krb5_pointer) ccache;
+	    }
+	    free(ccname);
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the ccache serializer.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_ccache_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_ccache_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/t_cc.c b/krb5-1-6/src/lib/krb5/ccache/t_cc.c
new file mode 100644
index 000000000..90a449753
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/t_cc.c
@@ -0,0 +1,338 @@
+/*
+ * lib/krb5/ccache/scc_test.c
+ *
+ * Copyright 2000 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+
+#include "krb5.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "com_err.h"
+
+#define KRB5_OK 0
+
+krb5_creds test_creds;
+
+int debug=0;
+
+static void init_structs(void)
+{
+  static int add=0x12345;
+
+  static krb5_address addr;
+
+  static krb5_address *addrs[] = {
+    &addr,
+    0,
+  };
+
+  addr.magic = KV5M_ADDRESS;
+  addr.addrtype = ADDRTYPE_INET;
+  addr.length = 4;
+  addr.contents = (krb5_octet *) &add;
+
+  test_creds.magic = KV5M_CREDS;
+  test_creds.client = NULL;
+  test_creds.server = NULL;
+
+  test_creds.keyblock.magic = KV5M_KEYBLOCK;
+  test_creds.keyblock.contents = 0;
+  test_creds.keyblock.enctype = 1;
+  test_creds.keyblock.length = 1;
+  test_creds.keyblock.contents = (unsigned char *) "1";
+  test_creds.times.authtime = 1111;
+  test_creds.times.starttime = 2222;
+  test_creds.times.endtime = 3333;
+  test_creds.times.renew_till = 4444;
+  test_creds.is_skey = 1;
+  test_creds.ticket_flags = 5555;
+  test_creds.addresses = addrs;
+  
+#define SET_TICKET(ent, str) {ent.magic = KV5M_DATA; ent.length = sizeof(str); ent.data = str;}
+  SET_TICKET(test_creds.ticket, "This is ticket 1");
+  SET_TICKET(test_creds.second_ticket, "This is ticket 2");
+  test_creds.authdata = NULL;
+}
+
+static void init_test_cred(krb5_context context)
+{
+#define REALM "REALM"
+  krb5_build_principal(context, &test_creds.client, sizeof(REALM), REALM,
+		       "client-comp1", "client-comp2", NULL);
+
+  krb5_build_principal(context, &test_creds.server, sizeof(REALM), REALM,
+		       "server-comp1", "server-comp2", NULL);
+}
+
+static void free_test_cred(krb5_context context)
+{
+  krb5_free_principal(context, test_creds.client);
+
+  krb5_free_principal(context, test_creds.server);
+
+}
+
+#define CHECK(kret,msg) \
+     if (kret != KRB5_OK) {\
+	  com_err(msg, kret, ""); \
+          fflush(stderr);\
+          exit(1);\
+     } else if(debug) printf("%s went ok\n", msg);
+
+#define CHECK_STR(str,msg) \
+     if (str == 0) {\
+	  com_err(msg, kret, "");\
+          exit(1);\
+     } else if(debug) printf("%s went ok\n", msg);
+
+#define CHECK_FAIL(experr, kret, msg) \
+     if (experr != kret) { CHECK(kret, msg);}
+
+static void cc_test(krb5_context context, const char *name, int flags)
+{
+     krb5_ccache id, id2;
+     krb5_creds creds;
+     krb5_error_code kret;
+     krb5_cc_cursor cursor;
+     const char *c_name;
+     char newcache[300];
+     char *save_type;
+
+     init_test_cred(context);
+
+     kret = krb5_cc_resolve(context, name, &id);
+     CHECK(kret, "resolve");
+     kret = krb5_cc_initialize(context, id, test_creds.client);
+     CHECK(kret, "initialize");
+     
+     c_name = krb5_cc_get_name(context, id);
+     CHECK_STR(c_name, "get_name");
+
+     c_name = krb5_cc_get_type(context, id);
+     CHECK_STR(c_name, "get_type");
+     save_type=strdup(c_name);
+     CHECK_STR(save_type, "copying type");
+
+     kret = krb5_cc_store_cred(context, id, &test_creds);
+     CHECK(kret, "store");
+
+     kret = krb5_cc_set_flags (context, id, flags);
+     CHECK(kret, "set_flags");
+     kret = krb5_cc_start_seq_get(context, id, &cursor);
+     CHECK(kret, "start_seq_get");
+     kret = 0;
+     while (kret != KRB5_CC_END) {
+	  if(debug) printf("Calling next_cred\n");
+	  kret = krb5_cc_next_cred(context, id, &cursor, &creds);
+	  if(kret == KRB5_CC_END) {
+	    if(debug) printf("next_cred: ok at end\n");
+	  }
+	  else {
+	    CHECK(kret, "next_cred");
+	    krb5_free_cred_contents(context, &creds);
+	  }
+
+     }
+     kret = krb5_cc_end_seq_get(context, id, &cursor);
+     CHECK(kret, "end_seq_get");
+
+     kret = krb5_cc_close(context, id);
+     CHECK(kret, "close");
+
+
+     /* ------------------------------------------------- */
+     kret = krb5_cc_resolve(context, name, &id);
+     CHECK(kret, "resolve2");
+
+     {
+       /* Copy the cache test*/
+       sprintf(newcache, "%s.new", name);
+       kret = krb5_cc_resolve(context, newcache, &id2);
+       CHECK(kret, "resolve of new cache");
+       
+       /* This should fail as the new creds are not initialized */
+       kret = krb5_cc_copy_creds(context, id, id2);
+       CHECK_FAIL(KRB5_FCC_NOFILE, kret, "copy_creds");
+       
+       kret = krb5_cc_initialize(context, id2, test_creds.client);
+       CHECK(kret, "initialize of id2");
+
+       kret = krb5_cc_copy_creds(context, id, id2);
+       CHECK(kret, "copy_creds");
+
+       kret = krb5_cc_destroy(context, id2);
+       CHECK(kret, "destroy new cache");
+     }
+
+     /* Destroy the first cache */
+     kret = krb5_cc_destroy(context, id);
+     CHECK(kret, "destroy");
+
+     /* ----------------------------------------------------- */
+     /* Tests the generate new code */
+     kret = krb5_cc_new_unique(context, save_type,
+			       NULL, &id2);
+     CHECK(kret, "new_unique");
+			       
+     kret = krb5_cc_initialize(context, id2, test_creds.client);
+     CHECK(kret, "initialize");
+
+     kret = krb5_cc_store_cred(context, id2, &test_creds);
+     CHECK(kret, "store");
+
+     kret = krb5_cc_destroy(context, id2);
+     CHECK(kret, "destroy id2");
+
+     free(save_type);
+     free_test_cred(context);
+
+}
+
+/*
+ * Checks if a credential type is registered with the library
+ */
+static int check_registered(krb5_context context, const char *prefix)
+{
+
+  char name[300];
+  krb5_error_code kret;
+  krb5_ccache id;
+
+  sprintf(name, "%s/tmp/cctest.%ld", prefix, (long) getpid());
+
+  kret = krb5_cc_resolve(context, name, &id);
+  if(kret != KRB5_OK) {
+    if(kret == KRB5_CC_UNKNOWN_TYPE)
+      return 0;
+    com_err("Checking on credential type", kret,prefix);
+    fflush(stderr);
+    return 0;
+  }
+
+  kret = krb5_cc_close(context, id);
+  if(kret != KRB5_OK) {
+    com_err("Checking on credential type - closing", kret,prefix);
+    fflush(stderr);
+  }
+
+  return 1;
+}
+
+
+static void do_test(krb5_context context, const char *prefix)
+{
+  char name[300];
+
+  sprintf(name, "%s/tmp/cctest.%ld", prefix, (long) getpid());
+  printf("Starting test on %s\n", name);
+  cc_test (context, name, 0);
+  cc_test (context, name, !0);
+  printf("Test on %s passed\n", name);
+}
+
+static void test_misc(krb5_context context)
+{
+  /* Tests for certain error returns */
+  krb5_error_code	kret;
+  krb5_ccache id;
+  extern krb5_cc_ops *krb5_cc_dfl_ops;
+  krb5_cc_ops *ops_save;
+
+  fprintf(stderr, "Testing miscellaneous error conditions\n");
+
+  kret = krb5_cc_resolve(context, "unknown_method_ep:/tmp/name", &id);
+  if (kret != KRB5_CC_UNKNOWN_TYPE) {
+    CHECK(kret, "resolve unknown type");
+  }
+
+  /* Test for not specifiying a cache type with no defaults */
+  ops_save = krb5_cc_dfl_ops;
+  krb5_cc_dfl_ops = 0;
+
+  kret = krb5_cc_resolve(context, "/tmp/e", &id);
+  if (kret != KRB5_CC_BADNAME) {
+    CHECK(kret, "resolve no builtin type");
+  }
+
+  krb5_cc_dfl_ops = ops_save;
+
+}
+extern const krb5_cc_ops krb5_mcc_ops;
+extern const krb5_cc_ops krb5_fcc_ops;
+
+int main (void)
+{
+    krb5_context context;
+    krb5_error_code	kret;
+
+    initialize_krb5_error_table ();
+
+    if ((kret = krb5_init_context(&context))) {
+	    printf("Couldn't initialize krb5 library: %s\n",
+		   error_message(kret));
+	    exit(1);
+    }
+
+    kret = krb5_cc_register(context, &krb5_mcc_ops,0);
+    if(kret && kret != KRB5_CC_TYPE_EXISTS) {
+      CHECK(kret, "register_mem");
+    }
+
+    kret = krb5_cc_register(context, &krb5_fcc_ops,0);
+    if(kret && kret != KRB5_CC_TYPE_EXISTS) {
+      CHECK(kret, "register_mem");
+    }
+
+    /* Registering a second time tests for error return */
+    kret = krb5_cc_register(context, &krb5_fcc_ops,0);
+    if(kret != KRB5_CC_TYPE_EXISTS) {
+      CHECK(kret, "register_mem");
+    }
+
+    /* Registering with override should work */
+    kret = krb5_cc_register(context, &krb5_fcc_ops,1);
+    CHECK(kret, "register_mem override");
+
+    init_structs();
+
+    test_misc(context);
+    do_test(context, "");
+
+    if(check_registered(context, "KEYRING:"))
+      do_test(context, "KEYRING:");
+    else 
+      printf("Skiping KEYRING: test - unregistered type\n");
+
+    do_test(context, "MEMORY:");
+    do_test(context, "FILE:");
+
+    krb5_free_context(context);
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/t_cccursor.c b/krb5-1-6/src/lib/krb5/ccache/t_cccursor.c
new file mode 100644
index 000000000..68e615329
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/t_cccursor.c
@@ -0,0 +1,265 @@
+/*
+ * lib/krb5/ccache/t_cccursor.c
+ *
+ * Copyright 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "autoconf.h"
+#include "krb5.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct crlist {
+    char *ccname;
+    char *pname;
+};
+
+struct crlist crlist[] = {
+    { "foo", NULL },
+    { "MEMORY:env", "env" },
+    { "MEMORY:0", "foo0" },
+    { "MEMORY:1", "foo1" },
+    { "MEMORY:2", "foo2" },
+};
+#define NCRLIST (sizeof(crlist)/sizeof(struct crlist))
+
+struct chklist {
+    char *pfx;
+    char *res;
+};
+
+struct chklist chklist0[] = {
+    { NULL, NULL },
+    { NULL, NULL },
+    { "MEMORY", "2" },
+    { "MEMORY", "1" },
+    { "MEMORY", "0" },
+    { "MEMORY", "env" },
+};
+#define NCHKLIST0 (sizeof(chklist0)/sizeof(struct chklist))
+
+struct chklist chklist1[] = {
+    { "MEMORY", "env" },
+    { NULL, NULL },
+    { "MEMORY", "2" },
+    { "MEMORY", "1" },
+    { "MEMORY", "0" },
+};
+#define NCHKLIST1 (sizeof(chklist1)/sizeof(struct chklist))
+
+struct chklist chklist2[] = {
+    { "MEMORY", "env" },
+    { NULL, NULL },
+    { "MEMORY", "2" },
+    { "MEMORY", "1" },
+    { "MEMORY", "0" },
+};
+#define NCHKLIST2 (sizeof(chklist2)/sizeof(struct chklist))
+
+krb5_error_code
+cr_cache(krb5_context, const char *, const char *);
+
+krb5_error_code
+dest_cache(krb5_context, const char *, const char *);
+
+krb5_error_code
+do_chk(krb5_context, struct chklist *, int nmax, int *);
+
+int
+do_chk_one(const char *, const char *, struct chklist *);
+
+krb5_error_code
+cr_cache(krb5_context context, const char *ccname, const char *pname)
+{
+    krb5_error_code ret;
+    krb5_principal princ = NULL;
+    krb5_ccache ccache = NULL;
+
+    ret = krb5_cc_resolve(context, ccname, &ccache);
+    if (ret)
+	goto errout;
+    if (pname != NULL) {
+	ret = krb5_parse_name(context, pname, &princ);
+	if (ret)
+	    return ret;
+	ret = krb5_cc_initialize(context, ccache, princ);
+	if (ret)
+	    goto errout;
+	printf("created cache %s with principal %s\n", ccname, pname);
+    } else
+	printf("created cache %s (uninitialized)\n", ccname);
+errout:
+    if (princ != NULL)
+	krb5_free_principal(context, princ);
+    if (ccache != NULL)
+	krb5_cc_close(context, ccache);
+    return ret;
+}
+
+krb5_error_code
+dest_cache(krb5_context context, const char *ccname, const char *pname)
+{
+    krb5_error_code ret;
+    krb5_ccache ccache = NULL;
+
+    ret = krb5_cc_resolve(context, ccname, &ccache);
+    if (ret)
+	goto errout;
+    if (pname != NULL) {
+	ret = krb5_cc_destroy(context, ccache);
+	if (ret)
+	    return ret;
+	printf("Destroyed cache %s\n", ccname);
+    } else {
+	printf("Closed cache %s (uninitialized)\n", ccname);
+	ret = krb5_cc_close(context, ccache);
+    }
+errout:
+    return ret;
+}
+
+int
+do_chk_one(const char *prefix, const char *name, struct chklist *chk)
+{
+
+    if (chk->pfx == NULL)
+	return 0;
+    if (strcmp(chk->pfx, prefix) || strcmp(chk->res, name)) {
+	fprintf(stderr, "MATCH FAILED: expected %s:%s\n",
+		chk->pfx, chk->res);
+	return 1;
+    }
+    return 0;
+}
+
+krb5_error_code
+do_chk(
+    krb5_context context,
+    struct chklist *chklist,
+    int nmax,
+    int *good)
+{
+    krb5_error_code ret = 0;
+    krb5_cccol_cursor cursor = NULL;
+    krb5_ccache ccache;
+    const char *prefix, *name;
+    int i;
+
+    ret = krb5_cccol_cursor_new(context, &cursor);
+    if (ret) goto errout;
+
+    i = 0;
+    printf(">>>\n");
+    for (i = 0; ; i++) {
+	ret = krb5_cccol_cursor_next(context, cursor, &ccache);
+	if (ret) goto errout;
+	if (ccache == NULL) {
+	    printf("<<< end of list\n");
+	    break;
+	}
+	prefix = krb5_cc_get_type(context, ccache);
+	name = krb5_cc_get_name(context, ccache);
+	printf("cursor: %s:%s\n", prefix, name);
+
+	if (i < nmax) {
+	    if (!do_chk_one(prefix, name, &chklist[i])) {
+		*good = 0;
+	    }
+	}
+	ret = krb5_cc_close(context, ccache);
+	if (ret) goto errout;
+    }
+
+    if (i != nmax) {
+	fprintf(stderr, "total ccaches %d != expected ccaches %d\n", i, nmax);
+	*good = 0;
+    }
+
+errout:
+    if (cursor != NULL)
+	krb5_cccol_cursor_free(context, &cursor);
+    return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+    krb5_error_code ret = 0;
+    krb5_context context;
+    int i, good = 1;
+
+    ret = krb5_init_context(&context);
+    if (ret) exit(1);
+
+    for (i = 0; i < NCRLIST; i++) {
+	ret = cr_cache(context, crlist[i].ccname, crlist[i].pname);
+	if (ret) goto errout;
+    }
+
+#ifdef HAVE_SETENV
+    setenv("KRB5CCNAME", "foo", 1);
+#else
+    putenv("KRB5CCNAME=foo");
+#endif
+    printf("KRB5CCNAME=foo\n");
+    ret = do_chk(context, chklist0, NCHKLIST0, &good);
+    if (ret)
+	goto errout;
+
+#ifdef HAVE_SETENV
+    setenv("KRB5CCNAME", "MEMORY:env", 1);
+#else
+    putenv("KRB5CCNAME=MEMORY:env");
+#endif
+    printf("KRB5CCNAME=MEMORY:env\n");
+    ret = do_chk(context, chklist1, NCHKLIST1, &good);
+    if (ret)
+	goto errout;
+
+    ret = krb5_cc_set_default_name(context, "MEMORY:env");
+    if (ret)
+	goto errout;
+
+    printf("KRB5CCNAME=MEMORY:env, ccdefname=MEMORY:env\n");
+    ret = do_chk(context, chklist2, NCHKLIST2, &good);
+    if (ret)
+	goto errout;
+
+    for (i = 0; i < NCRLIST; i++) {
+	ret = dest_cache(context, crlist[i].ccname, crlist[i].pname);
+	if (ret) goto errout;
+    }
+
+errout:
+    krb5_free_context(context);
+    if (ret) {
+	com_err("main", ret, "");
+	exit(1);
+    } else {
+	exit(!good);
+    }
+}
diff --git a/krb5-1-6/src/lib/krb5/ccache/t_memory.c b/krb5-1-6/src/lib/krb5/ccache/t_memory.c
new file mode 100644
index 000000000..b117aed33
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/t_memory.c
@@ -0,0 +1,140 @@
+/*
+ * lib/krb5/ccache/file/mcc_test.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+
+#include "mcc.h"
+
+krb5_data client1 = {
+#define DATA "client1-comp1"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+krb5_data client2 = {
+#define DATA "client1-comp2"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+krb5_data server1 = {
+#define DATA "server1-comp1"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+krb5_data server2 = {
+#define DATA "server1-comp2"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+krb5_creds test_creds = {
+     NULL,
+     NULL,
+     {
+	  1,
+	  1,
+	  (unsigned char *) "1"
+     },
+     {
+	  1111,
+	  2222,
+	  3333,
+	  4444
+     },
+     1,
+     5555,
+     {
+#define TICKET "This is ticket 1"
+     sizeof(TICKET),
+     TICKET,
+#undef TICKET
+     },
+     {
+#define TICKET "This is ticket 2"
+     sizeof(TICKET),
+     TICKET,
+#undef TICKET
+     },
+};
+
+void init_test_cred()
+{
+     test_creds.client = (krb5_principal) malloc(sizeof(krb5_data *)*3);
+     test_creds.client[0] = &client1;
+     test_creds.client[1] = &client2;
+     test_creds.client[2] = NULL;
+
+     test_creds.server = (krb5_principal) malloc(sizeof(krb5_data *)*3);
+     test_creds.server[0] = &server1;
+     test_creds.server[1] = &server2;
+     test_creds.server[2] = NULL;
+}
+
+#define CHECK(kret,msg) \
+     if (kret != KRB5_OK) {\
+	  printf("%s returned %d\n", msg, kret);\
+     };
+						   
+void mcc_test()
+{
+     krb5_ccache id;
+     krb5_creds creds;
+     krb5_error_code kret;
+     krb5_cc_cursor cursor;
+
+     init_test_cred();
+
+     kret = krb5_mcc_resolve(context, &id, "/tmp/tkt_test");
+     CHECK(kret, "resolve");
+     kret = krb5_mcc_initialize(context, id, test_creds.client);
+     CHECK(kret, "initialize");
+     kret = krb5_mcc_store(context, id, &test_creds);
+     CHECK(kret, "store");
+
+     kret = krb5_mcc_start_seq_get(context, id, &cursor);
+     CHECK(kret, "start_seq_get");
+     kret = 0;
+     while (kret != KRB5_CC_END) {
+	  printf("Calling next_cred\n");
+	  kret = krb5_mcc_next_cred(context, id, &cursor, &creds);
+	  CHECK(kret, "next_cred");
+     }
+     kret = krb5_mcc_end_seq_get(context, id, &cursor);
+     CHECK(kret, "end_seq_get");
+
+     kret = krb5_mcc_destroy(context, id);
+     CHECK(kret, "destroy");
+     kret = krb5_mcc_close(context, id);
+     CHECK(kret, "close");
+}
+
diff --git a/krb5-1-6/src/lib/krb5/ccache/t_stdio.c b/krb5-1-6/src/lib/krb5/ccache/t_stdio.c
new file mode 100644
index 000000000..a76d1fcd7
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/ccache/t_stdio.c
@@ -0,0 +1,169 @@
+/*
+ * lib/krb5/ccache/stdio/scc_test.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+
+#include "scc.h"
+
+krb5_data client1 = {
+#define DATA "client1-comp1"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+krb5_data client2 = {
+#define DATA "client1-comp2"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+krb5_data server1 = {
+#define DATA "server1-comp1"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+krb5_data server2 = {
+#define DATA "server1-comp2"
+     sizeof(DATA),
+     DATA,
+#undef DATA
+};
+
+int x = 0x12345;
+krb5_address addr = {
+    ADDRTYPE_INET,
+    4,
+    (krb5_octet *) &x,
+};
+
+krb5_address *addrs[] = {
+    &addr,
+    0,
+};
+
+krb5_creds test_creds = {
+     NULL,
+     NULL,
+     {
+	  1,
+	  1,
+	  (unsigned char *) "1"
+     },
+     {
+	  1111,
+	  2222,
+	  3333,
+	  4444,
+     },
+     1,
+     5555,
+     addrs,
+     {
+#define TICKET "This is ticket 1"
+     sizeof(TICKET),
+     TICKET,
+#undef TICKET
+     },
+     {
+#define TICKET "This is ticket 2"
+     sizeof(TICKET),
+     TICKET,
+#undef TICKET
+     },
+};
+
+void init_test_cred()
+{
+     test_creds.client = (krb5_principal) malloc(sizeof(krb5_data *)*3);
+     test_creds.client[0] = &client1;
+     test_creds.client[1] = &client2;
+     test_creds.client[2] = NULL;
+
+     test_creds.server = (krb5_principal) malloc(sizeof(krb5_data *)*3);
+     test_creds.server[0] = &server1;
+     test_creds.server[1] = &server2;
+     test_creds.server[2] = NULL;
+}
+
+#define CHECK(kret,msg) \
+     if (kret != KRB5_OK) {\
+	  com_err(msg, kret, "");\
+     } else printf("%s went ok\n", msg);
+						   
+int flags = 0;
+void scc_test()
+{
+     krb5_ccache id;
+     krb5_creds creds;
+     krb5_error_code kret;
+     krb5_cc_cursor cursor;
+
+     init_test_cred();
+
+     kret = krb5_scc_resolve(context, &id, "/tmp/tkt_test");
+     CHECK(kret, "resolve");
+     kret = krb5_scc_initialize(context, id, test_creds.client);
+     CHECK(kret, "initialize");
+     kret = krb5_scc_store(id, &test_creds);
+     CHECK(kret, "store");
+
+     kret = krb5_scc_set_flags (id, flags);
+     CHECK(kret, "set_flags");
+     kret = krb5_scc_start_seq_get(id, &cursor);
+     CHECK(kret, "start_seq_get");
+     kret = 0;
+     while (kret != KRB5_CC_END) {
+	  printf("Calling next_cred\n");
+	  kret = krb5_scc_next_cred(id, &cursor, &creds);
+	  CHECK(kret, "next_cred");
+     }
+     kret = krb5_scc_end_seq_get(id, &cursor);
+     CHECK(kret, "end_seq_get");
+
+     kret = krb5_scc_close(id);
+     CHECK(kret, "close");
+
+
+     kret = krb5_scc_resolve(&id, "/tmp/tkt_test");
+     CHECK(kret, "resolve");
+     kret = krb5_scc_destroy(id);
+     CHECK(kret, "destroy");
+}
+
+int remove (s) char*s; { return unlink(s); }
+int main () {
+    initialize_krb5_error_table ();
+    init_test_cred ();
+    scc_test ();
+    flags = !flags;
+    scc_test ();
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/error_tables/Makefile.in b/krb5-1-6/src/lib/krb5/error_tables/Makefile.in
new file mode 100644
index 000000000..323af4860
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/error_tables/Makefile.in
@@ -0,0 +1,82 @@
+thisconfigdir=../../..
+myfulldir=lib/krb5/error_tables
+mydir=lib/krb5/error_tables
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=error_tables
+##DOS##OBJFILE=..\$(OUTPRE)err_tbls.lst
+
+THDRDIR=$(BUILDTOP)$(S)include
+EHDRDIR=$(BUILDTOP)$(S)include
+
+STLIBOBJS= asn1_err.o kdb5_err.o krb5_err.o \
+      kv5m_err.o krb524_err.o
+
+HDRS= asn1_err.h kdb5_err.h krb5_err.h kv5m_err.h krb524_err.h
+OBJS= $(OUTPRE)asn1_err.$(OBJEXT) $(OUTPRE)kdb5_err.$(OBJEXT) $(OUTPRE)krb5_err.$(OBJEXT) \
+      $(OUTPRE)kv5m_err.$(OBJEXT) $(OUTPRE)krb524_err.$(OBJEXT)
+ETSRCS= asn1_err.c kdb5_err.c krb5_err.c kv5m_err.c krb524_err.c
+SRCS= asn1_err.c kdb5_err.c krb5_err.c kv5m_err.c krb524_err.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+all-libobjs: $(HDRS)
+
+includes:: $(HDRS)
+	for f in $(HDRS) ; do \
+		if cmp $$f $(THDRDIR)/$$f >/dev/null 2>&1; then :; \
+		else \
+			(set -x; $(RM) $(THDRDIR)/$$f; \
+			 $(CP) $$f $(THDRDIR)/$$f) ; \
+		fi ; \
+	done
+
+awk-windows:
+	$(AWK) -f $(SRCTOP)/util/et/et_h.awk outfile=asn1_err.h asn1_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_h.awk outfile=kdb5_err.h kdb5_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_h.awk outfile=krb5_err.h krb5_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_h.awk outfile=kv5m_err.h kv5m_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_h.awk outfile=krb524_err.h krb524_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_c.awk outfile=asn1_err.c asn1_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_c.awk outfile=kdb5_err.c kdb5_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_c.awk outfile=krb5_err.c krb5_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_c.awk outfile=kv5m_err.c kv5m_err.et
+	$(AWK) -f $(SRCTOP)/util/et/et_c.awk outfile=krb524_err.c krb524_err.et
+	if exist asn1_err.h copy asn1_err.h "$(EHDRDIR)"
+	if exist kdb5_err.h copy kdb5_err.h "$(EHDRDIR)"
+	if exist krb5_err.h copy krb5_err.h "$(EHDRDIR)"
+	if exist kv5m_err.h copy kv5m_err.h "$(EHDRDIR)"
+	if exist krb524_err.h copy krb524_err.h "$(EHDRDIR)"
+
+#
+# dependencies for traditional makes
+#
+$(OUTPRE)asn1_err.$(OBJEXT): asn1_err.c
+$(OUTPRE)kdb5_err.$(OBJEXT): kdb5_err.c
+$(OUTPRE)krb5_err.$(OBJEXT): krb5_err.c
+$(OUTPRE)kv5m_err.$(OBJEXT): kv5m_err.c
+$(OUTPRE)krb524_err.$(OBJEXT): krb524_err.c
+
+clean-unix:: clean-libobjs
+	$(RM) $(HDRS) $(ETSRCS)
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+asn1_err.so asn1_err.po $(OUTPRE)asn1_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) asn1_err.c
+kdb5_err.so kdb5_err.po $(OUTPRE)kdb5_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) kdb5_err.c
+krb5_err.so krb5_err.po $(OUTPRE)krb5_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) krb5_err.c
+kv5m_err.so kv5m_err.po $(OUTPRE)kv5m_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) kv5m_err.c
+krb524_err.so krb524_err.po $(OUTPRE)krb524_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) krb524_err.c
diff --git a/krb5-1-6/src/lib/krb5/error_tables/asn1_err.et b/krb5-1-6/src/lib/krb5/error_tables/asn1_err.et
new file mode 100644
index 000000000..06078ffbc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/error_tables/asn1_err.et
@@ -0,0 +1,15 @@
+error_table asn1
+error_code ASN1_BAD_TIMEFORMAT, "ASN.1 failed call to system time library"
+error_code ASN1_MISSING_FIELD, "ASN.1 structure is missing a required field"
+error_code ASN1_MISPLACED_FIELD, "ASN.1 unexpected field number"
+error_code ASN1_TYPE_MISMATCH, "ASN.1 type numbers are inconsistent"
+error_code ASN1_OVERFLOW, "ASN.1 value too large"
+error_code ASN1_OVERRUN, "ASN.1 encoding ended unexpectedly"
+error_code ASN1_BAD_ID, "ASN.1 identifier doesn't match expected value"
+error_code ASN1_BAD_LENGTH, "ASN.1 length doesn't match expected value"
+error_code ASN1_BAD_FORMAT, "ASN.1 badly-formatted encoding"
+error_code ASN1_PARSE_ERROR, "ASN.1 parse error"
+error_code ASN1_BAD_GMTIME, "ASN.1 bad return from gmtime"
+error_code ASN1_MISMATCH_INDEF, "ASN.1 non-constructed indefinite encoding"
+error_code ASN1_MISSING_EOC, "ASN.1 missing expected EOC"
+end
diff --git a/krb5-1-6/src/lib/krb5/error_tables/init_ets.c b/krb5-1-6/src/lib/krb5/error_tables/init_ets.c
new file mode 100644
index 000000000..56a750e75
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/error_tables/init_ets.c
@@ -0,0 +1,50 @@
+/*
+ * lib/krb5/error_tables/init_ets.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Initialize Kerberos library error tables.
+ */
+
+#include "k5-int.h"
+
+void
+krb5_init_ets (krb5_context context)
+{
+    static int inited = 0;
+
+    if (inited == 0) {
+	    initialize_krb5_error_table();
+	    initialize_kv5m_error_table();
+	    initialize_kdb5_error_table();
+	    initialize_asn1_error_table();
+	    initialize_k524_error_table();
+	    inited++;
+    }
+}
+
+void
+krb5_free_ets (krb5_context context)
+{
+}
diff --git a/krb5-1-6/src/lib/krb5/error_tables/kdb5_err.et b/krb5-1-6/src/lib/krb5/error_tables/kdb5_err.et
new file mode 100644
index 000000000..d6014acec
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/error_tables/kdb5_err.et
@@ -0,0 +1,80 @@
+#
+# lib/krb5/error_tables/kdb5_err.et
+#
+# 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.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+#
+# The Kerberos v5 database library error code table.
+#
+error_table kdb5
+
+ec KRB5_KDB_RCSID,	"$Id$"
+# /* From the server side routines */
+ec KRB5_KDB_INUSE,		"Entry already exists in database"
+ec KRB5_KDB_UK_SERROR,		"Database store error"
+ec KRB5_KDB_UK_RERROR,		"Database read error"
+ec KRB5_KDB_UNAUTH,		"Insufficient access to perform requested operation"
+# KRB5_KDB_DATA isn't really an error, but...
+ec KRB5_KDB_NOENTRY,		"No such entry in the database"
+
+ec KRB5_KDB_ILL_WILDCARD,	"Illegal use of wildcard"
+
+ec KRB5_KDB_DB_INUSE,		"Database is locked or in use--try again later"
+
+ec KRB5_KDB_DB_CHANGED,		"Database was modified during read"
+
+ec KRB5_KDB_TRUNCATED_RECORD,	"Database record is incomplete or corrupted"
+ec KRB5_KDB_RECURSIVELOCK,	"Attempt to lock database twice"
+ec KRB5_KDB_NOTLOCKED,		"Attempt to unlock database when not locked"
+ec KRB5_KDB_BADLOCKMODE,	"Invalid kdb lock mode"
+ec KRB5_KDB_DBNOTINITED,	"Database has not been initialized"
+ec KRB5_KDB_DBINITED,		"Database has already been initialized"
+
+ec KRB5_KDB_ILLDIRECTION,	"Bad direction for converting keys"
+
+ec KRB5_KDB_NOMASTERKEY,	"Cannot find master key record in database"
+ec KRB5_KDB_BADMASTERKEY,	"Master key does not match database"
+ec KRB5_KDB_INVALIDKEYSIZE,	"Key size in database is invalid"
+ec KRB5_KDB_CANTREAD_STORED,	"Cannot find/read stored master key"
+ec KRB5_KDB_BADSTORED_MKEY,	"Stored master key is corrupted"
+
+ec KRB5_KDB_CANTLOCK_DB,	"Insufficient access to lock database"
+
+ec KRB5_KDB_DB_CORRUPT,		"Database format error"
+ec KRB5_KDB_BAD_VERSION,	"Unsupported version in database entry"
+
+ec KRB5_KDB_BAD_SALTTYPE,	"Unsupported salt type"
+ec KRB5_KDB_BAD_ENCTYPE,	"Unsupported encryption type"
+ec KRB5_KDB_BAD_CREATEFLAGS,	"Bad database creation flags"
+ec KRB5_KDB_NO_PERMITTED_KEY,	"No matching key in entry having a permitted enctype"
+ec KRB5_KDB_NO_MATCHING_KEY,	"No matching key in entry"
+ec KRB5_KDB_DBTYPE_NOTFOUND,	"Unable to find requested database type"
+ec KRB5_KDB_DBTYPE_NOSUP,	"Database type not supported"
+ec KRB5_KDB_DBTYPE_INIT,	"Database library failed to initialize"
+ec KRB5_KDB_SERVER_INTERNAL_ERR,   "Server error"
+ec KRB5_KDB_ACCESS_ERROR,       "Unable to access Kerberos database"
+ec KRB5_KDB_INTERNAL_ERROR,     "Kerberos database internal error"
+ec KRB5_KDB_CONSTRAINT_VIOLATION,  "Kerberos database constraints violated"
+
+
+end
diff --git a/krb5-1-6/src/lib/krb5/error_tables/krb524_err.et b/krb5-1-6/src/lib/krb5/error_tables/krb524_err.et
new file mode 100644
index 000000000..5a4a004c7
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/error_tables/krb524_err.et
@@ -0,0 +1,34 @@
+# Copyright 1994 by OpenVision Technologies, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software
+# and its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appears in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of OpenVision not be used
+# in advertising or publicity pertaining to distribution of the software
+# without specific, written prior permission. OpenVision makes no
+# representations about the suitability of this software for any
+# purpose.  It is provided "as is" without express or implied warranty.
+# 
+# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+# 
+
+error_table k524
+
+error_code KRB524_BADKEY, "Cannot convert V5 keyblock"
+error_code KRB524_BADADDR, "Cannot convert V5 address information"
+error_code KRB524_BADPRINC, "Cannot convert V5 principal"
+error_code KRB524_BADREALM, "V5 realm name longer than V4 maximum"
+error_code KRB524_V4ERR, "Kerberos V4 error"
+error_code KRB524_ENCFULL, "Encoding too large"
+error_code KRB524_DECEMPTY, "Decoding out of data"
+error_code KRB524_NOTRESP, "Service not responding"
+error_code KRB524_KRB4_DISABLED,	"Kerberos version 4 support is disabled"
+
+end
diff --git a/krb5-1-6/src/lib/krb5/error_tables/krb5_err.et b/krb5-1-6/src/lib/krb5/error_tables/krb5_err.et
new file mode 100644
index 000000000..e16624287
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/error_tables/krb5_err.et
@@ -0,0 +1,348 @@
+#
+# lib/krb5/error_tables/krb5_err.et
+#
+# Copyright 1989,1990,1991,2007 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+#
+# The Kerberos v5 library error code table.
+# Protocol error codes are ERROR_TABLE_BASE_krb5 + the protocol error
+# code number; other error codes start at ERROR_TABLE_BASE_krb5 + 128.
+#
+error_table krb5
+
+
+#
+# Note: the first 128 error codes are hard-coded and must match the error
+# numbers defined in the Kerberos protocol specification, RFC-1510 or
+# its successors.
+#
+
+# vv 0
+error_code KRB5KDC_ERR_NONE,		"No error"
+error_code KRB5KDC_ERR_NAME_EXP,	"Client's entry in database has expired"
+error_code KRB5KDC_ERR_SERVICE_EXP,	"Server's entry in database has expired"
+error_code KRB5KDC_ERR_BAD_PVNO,	"Requested protocol version not supported"
+error_code KRB5KDC_ERR_C_OLD_MAST_KVNO,	"Client's key is encrypted in an old master key"
+error_code KRB5KDC_ERR_S_OLD_MAST_KVNO,	"Server's key is encrypted in an old master key"
+error_code KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "Client not found in Kerberos database"
+error_code KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "Server not found in Kerberos database"
+error_code KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "Principal has multiple entries in Kerberos database"
+error_code KRB5KDC_ERR_NULL_KEY,	"Client or server has a null key"
+error_code KRB5KDC_ERR_CANNOT_POSTDATE,	"Ticket is ineligible for postdating"
+error_code KRB5KDC_ERR_NEVER_VALID,	"Requested effective lifetime is negative or too short"
+error_code KRB5KDC_ERR_POLICY,		"KDC policy rejects request"
+error_code KRB5KDC_ERR_BADOPTION,	"KDC can't fulfill requested option"
+error_code KRB5KDC_ERR_ETYPE_NOSUPP,	"KDC has no support for encryption type"
+error_code KRB5KDC_ERR_SUMTYPE_NOSUPP,	"KDC has no support for checksum type"
+error_code KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KDC has no support for padata type"
+error_code KRB5KDC_ERR_TRTYPE_NOSUPP,	"KDC has no support for transited type"
+error_code KRB5KDC_ERR_CLIENT_REVOKED,	"Clients credentials have been revoked"
+error_code KRB5KDC_ERR_SERVICE_REVOKED,	"Credentials for server have been revoked"
+error_code KRB5KDC_ERR_TGT_REVOKED,	"TGT has been revoked"
+error_code KRB5KDC_ERR_CLIENT_NOTYET,	"Client not yet valid - try again later"
+error_code KRB5KDC_ERR_SERVICE_NOTYET,	"Server not yet valid - try again later"
+error_code KRB5KDC_ERR_KEY_EXP,  	"Password has expired"
+error_code KRB5KDC_ERR_PREAUTH_FAILED,  "Preauthentication failed"
+# ^^ 24
+error_code KRB5KDC_ERR_PREAUTH_REQUIRED, "Additional pre-authentication required"
+error_code KRB5KDC_ERR_SERVER_NOMATCH,	"Requested server and ticket don't match"
+error_code KRB5PLACEHOLD_27,		"KRB5 error code 27"
+error_code KRB5PLACEHOLD_28,		"KRB5 error code 28"
+error_code KRB5KDC_ERR_SVC_UNAVAILABLE, "A service is not available that is required to process the request"
+error_code KRB5PLACEHOLD_30,		"KRB5 error code 30"
+# vv 31
+error_code KRB5KRB_AP_ERR_BAD_INTEGRITY, "Decrypt integrity check failed"
+error_code KRB5KRB_AP_ERR_TKT_EXPIRED,	"Ticket expired"
+error_code KRB5KRB_AP_ERR_TKT_NYV,	"Ticket not yet valid"
+error_code KRB5KRB_AP_ERR_REPEAT,	"Request is a replay"
+error_code KRB5KRB_AP_ERR_NOT_US,	"The ticket isn't for us"
+error_code KRB5KRB_AP_ERR_BADMATCH,	"Ticket/authenticator don't match"
+error_code KRB5KRB_AP_ERR_SKEW,	"Clock skew too great"
+error_code KRB5KRB_AP_ERR_BADADDR,	"Incorrect net address"
+error_code KRB5KRB_AP_ERR_BADVERSION,	"Protocol version mismatch"
+error_code KRB5KRB_AP_ERR_MSG_TYPE,	"Invalid message type"
+error_code KRB5KRB_AP_ERR_MODIFIED,	"Message stream modified"
+error_code KRB5KRB_AP_ERR_BADORDER,	"Message out of order"
+error_code KRB5KRB_AP_ERR_ILL_CR_TKT, "Illegal cross-realm ticket"
+error_code KRB5KRB_AP_ERR_BADKEYVER,	"Key version is not available"
+error_code KRB5KRB_AP_ERR_NOKEY,	"Service key not available"
+error_code KRB5KRB_AP_ERR_MUT_FAIL,	"Mutual authentication failed"
+error_code KRB5KRB_AP_ERR_BADDIRECTION,	"Incorrect message direction"
+error_code KRB5KRB_AP_ERR_METHOD,	"Alternative authentication method required"
+error_code KRB5KRB_AP_ERR_BADSEQ,	"Incorrect sequence number in message"
+error_code KRB5KRB_AP_ERR_INAPP_CKSUM,	"Inappropriate type of checksum in message"
+#^^ 50
+error_code KRB5KRB_AP_PATH_NOT_ACCEPTED,	"Policy rejects transited path"
+error_code KRB5KRB_ERR_RESPONSE_TOO_BIG,	"Response too big for UDP, retry with TCP"
+error_code KRB5PLACEHOLD_53,	"KRB5 error code 53"
+error_code KRB5PLACEHOLD_54,	"KRB5 error code 54"
+error_code KRB5PLACEHOLD_55,	"KRB5 error code 55"
+error_code KRB5PLACEHOLD_56,	"KRB5 error code 56"
+error_code KRB5PLACEHOLD_57,	"KRB5 error code 57"
+error_code KRB5PLACEHOLD_58,	"KRB5 error code 58"
+error_code KRB5PLACEHOLD_59,	"KRB5 error code 59"
+error_code KRB5KRB_ERR_GENERIC,	"Generic error (see e-text)"
+error_code KRB5KRB_ERR_FIELD_TOOLONG,	"Field is too long for this implementation"
+error_code KRB5KDC_ERR_CLIENT_NOT_TRUSTED,		"Client not trusted"
+error_code KRB5KDC_ERR_KDC_NOT_TRUSTED,			"KDC not trusted"
+error_code KRB5KDC_ERR_INVALID_SIG,			"Invalid signature"
+error_code KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED,	"Key parameters not accepted"
+error_code KRB5KDC_ERR_CERTIFICATE_MISMATCH,		"Certificate mismatch"
+error_code KRB5PLACEHOLD_67,	"KRB5 error code 67"
+error_code KRB5PLACEHOLD_68,	"KRB5 error code 68"
+error_code KRB5PLACEHOLD_69,	"KRB5 error code 69"
+error_code KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE,		"Can't verify certificate"
+error_code KRB5KDC_ERR_INVALID_CERTIFICATE,		"Invalid certificate"
+error_code KRB5KDC_ERR_REVOKED_CERTIFICATE,		"Revoked certificate"
+error_code KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN,	"Revocation status unknown"
+error_code KRB5KDC_ERR_REVOCATION_STATUS_UNAVAILABLE,	"Revocation status unavailable"
+error_code KRB5KDC_ERR_CLIENT_NAME_MISMATCH,		"Client name mismatch"
+error_code KRB5KDC_ERR_KDC_NAME_MISMATCH,		"KDC name mismatch"
+error_code KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE,	"Inconsistent key purpose"
+error_code KRB5KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED,	"Digest in certificate not accepted"
+error_code KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED,	"Checksum must be included"
+error_code KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED,	"Digest in signed-data not accepted"
+error_code KRB5KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED,	"Public key encryption not supported"
+error_code KRB5PLACEHOLD_82,	"KRB5 error code 82"
+error_code KRB5PLACEHOLD_83,	"KRB5 error code 83"
+error_code KRB5PLACEHOLD_84,	"KRB5 error code 84"
+error_code KRB5PLACEHOLD_85,	"KRB5 error code 85"
+error_code KRB5PLACEHOLD_86,	"KRB5 error code 86"
+error_code KRB5PLACEHOLD_87,	"KRB5 error code 87"
+error_code KRB5PLACEHOLD_88,	"KRB5 error code 88"
+error_code KRB5PLACEHOLD_89,	"KRB5 error code 89"
+error_code KRB5PLACEHOLD_90,	"KRB5 error code 90"
+error_code KRB5PLACEHOLD_91,	"KRB5 error code 91"
+error_code KRB5PLACEHOLD_92,	"KRB5 error code 92"
+error_code KRB5PLACEHOLD_93,	"KRB5 error code 93"
+error_code KRB5PLACEHOLD_94,	"KRB5 error code 94"
+error_code KRB5PLACEHOLD_95,	"KRB5 error code 95"
+error_code KRB5PLACEHOLD_96,	"KRB5 error code 96"
+error_code KRB5PLACEHOLD_97,	"KRB5 error code 97"
+error_code KRB5PLACEHOLD_98,	"KRB5 error code 98"
+error_code KRB5PLACEHOLD_99,	"KRB5 error code 99"
+error_code KRB5PLACEHOLD_100,	"KRB5 error code 100"
+error_code KRB5PLACEHOLD_101,	"KRB5 error code 101"
+error_code KRB5PLACEHOLD_102,	"KRB5 error code 102"
+error_code KRB5PLACEHOLD_103,	"KRB5 error code 103"
+error_code KRB5PLACEHOLD_104,	"KRB5 error code 104"
+error_code KRB5PLACEHOLD_105,	"KRB5 error code 105"
+error_code KRB5PLACEHOLD_106,	"KRB5 error code 106"
+error_code KRB5PLACEHOLD_107,	"KRB5 error code 107"
+error_code KRB5PLACEHOLD_108,	"KRB5 error code 108"
+error_code KRB5PLACEHOLD_109,	"KRB5 error code 109"
+error_code KRB5PLACEHOLD_110,	"KRB5 error code 110"
+error_code KRB5PLACEHOLD_111,	"KRB5 error code 111"
+error_code KRB5PLACEHOLD_112,	"KRB5 error code 112"
+error_code KRB5PLACEHOLD_113,	"KRB5 error code 113"
+error_code KRB5PLACEHOLD_114,	"KRB5 error code 114"
+error_code KRB5PLACEHOLD_115,	"KRB5 error code 115"
+error_code KRB5PLACEHOLD_116,	"KRB5 error code 116"
+error_code KRB5PLACEHOLD_117,	"KRB5 error code 117"
+error_code KRB5PLACEHOLD_118,	"KRB5 error code 118"
+error_code KRB5PLACEHOLD_119,	"KRB5 error code 119"
+error_code KRB5PLACEHOLD_120,	"KRB5 error code 120"
+error_code KRB5PLACEHOLD_121,	"KRB5 error code 121"
+error_code KRB5PLACEHOLD_122,	"KRB5 error code 122"
+error_code KRB5PLACEHOLD_123,	"KRB5 error code 123"
+error_code KRB5PLACEHOLD_124,	"KRB5 error code 124"
+error_code KRB5PLACEHOLD_125,	"KRB5 error code 125"
+error_code KRB5PLACEHOLD_126,	"KRB5 error code 126"
+error_code KRB5PLACEHOLD_127,	"KRB5 error code 127"
+
+error_code KRB5_ERR_RCSID,	"$Id$"
+
+error_code KRB5_LIBOS_BADLOCKFLAG,	"Invalid flag for file lock mode"
+error_code KRB5_LIBOS_CANTREADPWD,	"Cannot read password"
+error_code KRB5_LIBOS_BADPWDMATCH,	"Password mismatch"
+error_code KRB5_LIBOS_PWDINTR,		"Password read interrupted"
+
+error_code KRB5_PARSE_ILLCHAR,		"Illegal character in component name"
+error_code KRB5_PARSE_MALFORMED,	"Malformed representation of principal"
+
+error_code KRB5_CONFIG_CANTOPEN,	"Can't open/find Kerberos configuration file"
+error_code KRB5_CONFIG_BADFORMAT,	"Improper format of Kerberos configuration file"
+error_code KRB5_CONFIG_NOTENUFSPACE,	"Insufficient space to return complete information"
+
+error_code KRB5_BADMSGTYPE,		"Invalid message type specified for encoding"
+
+error_code KRB5_CC_BADNAME,		"Credential cache name malformed"
+error_code KRB5_CC_UNKNOWN_TYPE,	"Unknown credential cache type" 
+error_code KRB5_CC_NOTFOUND,		"Matching credential not found"
+error_code KRB5_CC_END,			"End of credential cache reached"
+
+error_code KRB5_NO_TKT_SUPPLIED,	"Request did not supply a ticket"
+
+error_code KRB5KRB_AP_WRONG_PRINC,		"Wrong principal in request"
+error_code KRB5KRB_AP_ERR_TKT_INVALID,	"Ticket has invalid flag set"
+
+error_code KRB5_PRINC_NOMATCH,		"Requested principal and ticket don't match"
+error_code KRB5_KDCREP_MODIFIED,	"KDC reply did not match expectations"
+error_code KRB5_KDCREP_SKEW,		"Clock skew too great in KDC reply"
+error_code KRB5_IN_TKT_REALM_MISMATCH,	"Client/server realm mismatch in initial ticket request"
+
+error_code KRB5_PROG_ETYPE_NOSUPP,	"Program lacks support for encryption type"
+error_code KRB5_PROG_KEYTYPE_NOSUPP,	"Program lacks support for key type"
+error_code KRB5_WRONG_ETYPE,		"Requested encryption type not used in message"
+error_code KRB5_PROG_SUMTYPE_NOSUPP,	"Program lacks support for checksum type"
+
+error_code KRB5_REALM_UNKNOWN,		"Cannot find KDC for requested realm"
+error_code KRB5_SERVICE_UNKNOWN,	"Kerberos service unknown"
+error_code KRB5_KDC_UNREACH,		"Cannot contact any KDC for requested realm"
+error_code KRB5_NO_LOCALNAME,		"No local name found for principal name"
+
+error_code KRB5_MUTUAL_FAILED,		"Mutual authentication failed"
+
+# some of these should be combined/supplanted by system codes
+
+error_code KRB5_RC_TYPE_EXISTS,		"Replay cache type is already registered"
+error_code KRB5_RC_MALLOC,		"No more memory to allocate (in replay cache code)"
+error_code KRB5_RC_TYPE_NOTFOUND,	"Replay cache type is unknown"
+error_code KRB5_RC_UNKNOWN,		"Generic unknown RC error"
+error_code KRB5_RC_REPLAY,		"Message is a replay"
+error_code KRB5_RC_IO,			"Replay I/O operation failed XXX"
+error_code KRB5_RC_NOIO,		"Replay cache type does not support non-volatile storage"
+error_code KRB5_RC_PARSE,		"Replay cache name parse/format error"
+
+error_code KRB5_RC_IO_EOF,		"End-of-file on replay cache I/O"
+error_code KRB5_RC_IO_MALLOC,		"No more memory to allocate (in replay cache I/O code)"
+error_code KRB5_RC_IO_PERM,		"Permission denied in replay cache code"
+error_code KRB5_RC_IO_IO,		"I/O error in replay cache i/o code"
+error_code KRB5_RC_IO_UNKNOWN,		"Generic unknown RC/IO error"
+error_code KRB5_RC_IO_SPACE,		"Insufficient system space to store replay information"
+
+error_code KRB5_TRANS_CANTOPEN,		"Can't open/find realm translation file"
+error_code KRB5_TRANS_BADFORMAT,	"Improper format of realm translation file"
+
+error_code KRB5_LNAME_CANTOPEN,		"Can't open/find lname translation database"
+error_code KRB5_LNAME_NOTRANS,		"No translation available for requested principal"
+error_code KRB5_LNAME_BADFORMAT,	"Improper format of translation database entry"
+
+error_code KRB5_CRYPTO_INTERNAL,	"Cryptosystem internal error"
+
+error_code KRB5_KT_BADNAME,		"Key table name malformed"
+error_code KRB5_KT_UNKNOWN_TYPE,	"Unknown Key table type" 
+error_code KRB5_KT_NOTFOUND,		"Key table entry not found"
+error_code KRB5_KT_END,			"End of key table reached"
+error_code KRB5_KT_NOWRITE,		"Cannot write to specified key table"
+error_code KRB5_KT_IOERR,		"Error writing to key table"
+
+error_code KRB5_NO_TKT_IN_RLM,		"Cannot find ticket for requested realm"
+error_code KRB5DES_BAD_KEYPAR,		"DES key has bad parity"
+error_code KRB5DES_WEAK_KEY,		"DES key is a weak key"
+
+error_code KRB5_BAD_ENCTYPE,		"Bad encryption type"
+error_code KRB5_BAD_KEYSIZE,		"Key size is incompatible with encryption type"
+error_code KRB5_BAD_MSIZE,		"Message size is incompatible with encryption type"
+
+error_code KRB5_CC_TYPE_EXISTS,		"Credentials cache type is already registered."
+error_code KRB5_KT_TYPE_EXISTS,		"Key table type is already registered."
+
+error_code KRB5_CC_IO,			"Credentials cache I/O operation failed XXX"
+error_code KRB5_FCC_PERM,		"Credentials cache permissions incorrect"
+error_code KRB5_FCC_NOFILE,		"No credentials cache found"
+error_code KRB5_FCC_INTERNAL,		"Internal credentials cache error"
+error_code KRB5_CC_WRITE,		"Error writing to credentials cache"
+error_code KRB5_CC_NOMEM,		"No more memory to allocate (in credentials cache code)"
+error_code KRB5_CC_FORMAT,		"Bad format in credentials cache"
+error_code KRB5_CC_NOT_KTYPE,		"No credentials found with supported encryption types"
+
+# errors for dual tgt library calls
+error_code KRB5_INVALID_FLAGS,		"Invalid KDC option combination (library internal error)"
+error_code KRB5_NO_2ND_TKT,		"Request missing second ticket"
+
+error_code KRB5_NOCREDS_SUPPLIED,	"No credentials supplied to library routine"
+
+# errors for sendauth (and recvauth)
+
+error_code KRB5_SENDAUTH_BADAUTHVERS,	"Bad sendauth version was sent"
+error_code KRB5_SENDAUTH_BADAPPLVERS,	"Bad application version was sent (via sendauth)"
+error_code KRB5_SENDAUTH_BADRESPONSE,	"Bad response (during sendauth exchange)"
+error_code KRB5_SENDAUTH_REJECTED,	"Server rejected authentication (during sendauth exchange)"
+
+# errors for preauthentication
+
+error_code KRB5_PREAUTH_BAD_TYPE,	"Unsupported preauthentication type"
+error_code KRB5_PREAUTH_NO_KEY,		"Required preauthentication key not supplied"
+error_code KRB5_PREAUTH_FAILED,		"Generic preauthentication failure"
+
+# version number errors
+
+error_code KRB5_RCACHE_BADVNO,	"Unsupported replay cache format version number"
+error_code KRB5_CCACHE_BADVNO,	"Unsupported credentials cache format version number"
+error_code KRB5_KEYTAB_BADVNO,	"Unsupported key table format version number"
+
+#
+#
+
+error_code KRB5_PROG_ATYPE_NOSUPP,	"Program lacks support for address type"
+error_code KRB5_RC_REQUIRED,	"Message replay detection requires rcache parameter"
+error_code KRB5_ERR_BAD_HOSTNAME,	"Hostname cannot be canonicalized"
+error_code KRB5_ERR_HOST_REALM_UNKNOWN,	"Cannot determine realm for host"
+error_code KRB5_SNAME_UNSUPP_NAMETYPE,	"Conversion to service principal undefined for name type"
+
+error_code KRB5KRB_AP_ERR_V4_REPLY, "Initial Ticket response appears to be Version 4 error"
+error_code KRB5_REALM_CANT_RESOLVE,	"Cannot resolve network address for KDC in requested realm"
+error_code KRB5_TKT_NOT_FORWARDABLE,	"Requesting ticket can't get forwardable tickets"
+error_code KRB5_FWD_BAD_PRINCIPAL, "Bad principal name while trying to forward credentials"
+
+error_code KRB5_GET_IN_TKT_LOOP,  "Looping detected inside krb5_get_in_tkt"
+error_code KRB5_CONFIG_NODEFREALM,	"Configuration file does not specify default realm"
+
+error_code KRB5_SAM_UNSUPPORTED,  "Bad SAM flags in obtain_sam_padata"
+error_code KRB5_SAM_INVALID_ETYPE,	"Invalid encryption type in SAM challenge"
+error_code KRB5_SAM_NO_CHECKSUM,	"Missing checksum in SAM challenge"
+error_code KRB5_SAM_BAD_CHECKSUM,	"Bad checksum in SAM challenge"
+error_code KRB5_KT_NAME_TOOLONG,	"Keytab name too long"
+error_code KRB5_KT_KVNONOTFOUND,	"Key version number for principal in key table is incorrect"
+error_code KRB5_APPL_EXPIRED,	"This application has expired"
+error_code KRB5_LIB_EXPIRED,	"This Krb5 library has expired"
+
+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"
+error_code KRB5_CONFIG_ETYPE_NOSUPP,	"No supported encryption types (config file error?)"
+error_code KRB5_OBSOLETE_FN,	"Program called an obsolete, deleted function"
+
+# translated versions of getaddrinfo errors
+error_code KRB5_EAI_FAIL,	"unknown getaddrinfo failure"
+error_code KRB5_EAI_NODATA,	"no data available for host/domain name"
+error_code KRB5_EAI_NONAME,	"host/domain name not found"
+error_code KRB5_EAI_SERVICE,	"service name unknown"
+
+error_code KRB5_ERR_NUMERIC_REALM, "Cannot determine realm for numeric host address"
+
+error_code KRB5_ERR_BAD_S2K_PARAMS, "Invalid key generation parameters from KDC"
+
+error_code KRB5_ERR_NO_SERVICE,	"service not available"
+
+error_code KRB5_CC_READONLY,    "Ccache function not supported: read-only ccache type"
+error_code KRB5_CC_NOSUPP,      "Ccache function not supported: not implemented"
+
+error_code KRB5_DELTAT_BADFORMAT,	"Invalid format of Kerberos lifetime or clock skew string"
+
+error_code KRB5_PLUGIN_NO_HANDLE,	"Supplied data not handled by this plugin"
+error_code KRB5_PLUGIN_OP_NOTSUPP,  "Plugin does not support the operaton"
+end
diff --git a/krb5-1-6/src/lib/krb5/error_tables/kv5m_err.et b/krb5-1-6/src/lib/krb5/error_tables/kv5m_err.et
new file mode 100644
index 000000000..1b79de252
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/error_tables/kv5m_err.et
@@ -0,0 +1,90 @@
+#
+# src/lib/krb5/kv5m_err.et
+#
+# 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.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+#
+# The Kerberos v5 magic numbers errorcode table
+
+error_table kv5m
+
+error_code KV5M_NONE,		"Kerberos V5 magic number table"
+error_code KV5M_PRINCIPAL,	"Bad magic number for krb5_principal structure"
+error_code KV5M_DATA,		"Bad magic number for krb5_data structure"
+error_code KV5M_KEYBLOCK,	"Bad magic number for krb5_keyblock structure"
+error_code KV5M_CHECKSUM,	"Bad magic number for krb5_checksum structure"
+error_code KV5M_ENCRYPT_BLOCK,	"Bad magic number for krb5_encrypt_block structure"
+error_code KV5M_ENC_DATA,	"Bad magic number for krb5_enc_data structure"
+error_code KV5M_CRYPTOSYSTEM_ENTRY,	"Bad magic number for krb5_cryptosystem_entry structure"
+error_code KV5M_CS_TABLE_ENTRY,	"Bad magic number for krb5_cs_table_entry structure"
+error_code KV5M_CHECKSUM_ENTRY,	"Bad magic number for krb5_checksum_entry structure"
+
+error_code KV5M_AUTHDATA,	"Bad magic number for krb5_authdata structure"
+error_code KV5M_TRANSITED,	"Bad magic number for krb5_transited structure"
+error_code KV5M_ENC_TKT_PART,	"Bad magic number for krb5_enc_tkt_part structure"
+error_code KV5M_TICKET,		"Bad magic number for krb5_ticket structure"
+error_code KV5M_AUTHENTICATOR,	"Bad magic number for krb5_authenticator structure"
+error_code KV5M_TKT_AUTHENT,	"Bad magic number for krb5_tkt_authent structure"
+error_code KV5M_CREDS,		"Bad magic number for krb5_creds structure"
+error_code KV5M_LAST_REQ_ENTRY,	"Bad magic number for krb5_last_req_entry structure"
+error_code KV5M_PA_DATA,		"Bad magic number for krb5_pa_data structure"
+error_code KV5M_KDC_REQ,		"Bad magic number for krb5_kdc_req structure"
+error_code KV5M_ENC_KDC_REP_PART, "Bad magic number for krb5_enc_kdc_rep_part structure"
+error_code KV5M_KDC_REP,		"Bad magic number for krb5_kdc_rep structure"
+error_code KV5M_ERROR,		"Bad magic number for krb5_error structure"
+error_code KV5M_AP_REQ,		"Bad magic number for krb5_ap_req structure"
+error_code KV5M_AP_REP,		"Bad magic number for krb5_ap_rep structure"
+error_code KV5M_AP_REP_ENC_PART,	"Bad magic number for krb5_ap_rep_enc_part structure"
+error_code KV5M_RESPONSE,	"Bad magic number for krb5_response structure"
+error_code KV5M_SAFE,		"Bad magic number for krb5_safe structure"
+error_code KV5M_PRIV,		"Bad magic number for krb5_priv structure"
+error_code KV5M_PRIV_ENC_PART,	"Bad magic number for krb5_priv_enc_part structure"
+error_code KV5M_CRED,		"Bad magic number for krb5_cred structure"
+error_code KV5M_CRED_INFO,	"Bad magic number for krb5_cred_info structure"
+error_code KV5M_CRED_ENC_PART,	"Bad magic number for krb5_cred_enc_part structure"
+error_code KV5M_PWD_DATA,	"Bad magic number for krb5_pwd_data structure"
+error_code KV5M_ADDRESS,	"Bad magic number for krb5_address structure"
+error_code KV5M_KEYTAB_ENTRY,	"Bad magic number for krb5_keytab_entry structure"
+error_code KV5M_CONTEXT,	"Bad magic number for krb5_context structure"
+error_code KV5M_OS_CONTEXT,	"Bad magic number for krb5_os_context structure"
+error_code KV5M_ALT_METHOD,	"Bad magic number for krb5_alt_method structure"
+error_code KV5M_ETYPE_INFO_ENTRY, "Bad magic number for krb5_etype_info_entry structure"
+error_code KV5M_DB_CONTEXT,	"Bad magic number for krb5_db_context structure"
+error_code KV5M_AUTH_CONTEXT,	"Bad magic number for krb5_auth_context structure"
+error_code KV5M_KEYTAB,		"Bad magic number for krb5_keytab structure"
+error_code KV5M_RCACHE,		"Bad magic number for krb5_rcache structure"
+error_code KV5M_CCACHE,		"Bad magic number for krb5_ccache structure"
+error_code KV5M_PREAUTH_OPS,	"Bad magic number for krb5_preauth_ops"
+error_code KV5M_SAM_CHALLENGE,	"Bad magic number for krb5_sam_challenge"
+error_code KV5M_SAM_CHALLENGE_2,	"Bad magic number for krb5_sam_challenge_2"
+error_code KV5M_SAM_KEY,	"Bad magic number for krb5_sam_key"
+error_code KV5M_ENC_SAM_RESPONSE_ENC,	"Bad magic number for krb5_enc_sam_response_enc"
+error_code KV5M_ENC_SAM_RESPONSE_ENC_2,	"Bad magic number for krb5_enc_sam_response_enc"
+error_code KV5M_SAM_RESPONSE,	"Bad magic number for krb5_sam_response"
+error_code KV5M_SAM_RESPONSE_2,	"Bad magic number for krb5_sam_response 2"
+error_code KV5M_PREDICTED_SAM_RESPONSE,	"Bad magic number for krb5_predicted_sam_response"
+error_code KV5M_PASSWD_PHRASE_ELEMENT,	"Bad magic number for passwd_phrase_element"
+error_code KV5M_GSS_OID,	"Bad magic number for GSSAPI OID"
+error_code KV5M_GSS_QUEUE,	"Bad magic number for GSSAPI QUEUE"
+
+end
diff --git a/krb5-1-6/src/lib/krb5/keytab/Makefile.in b/krb5-1-6/src/lib/krb5/keytab/Makefile.in
new file mode 100644
index 000000000..62bcf90bd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/Makefile.in
@@ -0,0 +1,145 @@
+thisconfigdir=../../..
+myfulldir=lib/krb5/keytab
+mydir=lib/krb5/keytab
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=keytab
+##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst
+
+STLIBOBJS= \
+	ktadd.o		\
+	ktbase.o	\
+	ktdefault.o	\
+	ktfr_entry.o	\
+	ktremove.o	\
+	ktfns.o		\
+	kt_file.o	\
+	kt_srvtab.o	\
+	read_servi.o
+
+OBJS=	\
+	$(OUTPRE)ktadd.$(OBJEXT)		\
+	$(OUTPRE)ktbase.$(OBJEXT)	\
+	$(OUTPRE)ktdefault.$(OBJEXT)	\
+	$(OUTPRE)ktfr_entry.$(OBJEXT)	\
+	$(OUTPRE)ktremove.$(OBJEXT)	\
+	$(OUTPRE)ktfns.$(OBJEXT)	\
+	$(OUTPRE)kt_file.$(OBJEXT)	\
+	$(OUTPRE)kt_srvtab.$(OBJEXT)	\
+	$(OUTPRE)read_servi.$(OBJEXT)
+
+SRCS=	\
+	$(srcdir)/ktadd.c	\
+	$(srcdir)/ktbase.c	\
+	$(srcdir)/ktdefault.c	\
+	$(srcdir)/ktfr_entry.c	\
+	$(srcdir)/ktremove.c	\
+	$(srcdir)/ktfns.c	\
+	$(srcdir)/kt_file.c	\
+	$(srcdir)/kt_srvtab.c	\
+	$(srcdir)/read_servi.c
+
+all-windows:: $(OBJFILE)
+
+##DOS$(OBJFILE): $(OBJS)
+##DOS	$(RM) $(OBJFILE)
+##WIN32##	$(LIBECHO) -p $(PREFIXDIR)\ $(OUTPRE)*.obj > $(OBJFILE)
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+
+clean-windows::
+	@echo Making clean in krb5\keytab
+	$(RM) $(OBJFILE)
+
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+ktadd.so ktadd.po $(OUTPRE)ktadd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ktadd.c
+ktbase.so ktbase.po $(OUTPRE)ktbase.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  kt-int.h ktbase.c
+ktdefault.so ktdefault.po $(OUTPRE)ktdefault.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h ktdefault.c
+ktfr_entry.so ktfr_entry.po $(OUTPRE)ktfr_entry.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h ktfr_entry.c
+ktremove.so ktremove.po $(OUTPRE)ktremove.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h ktremove.c
+ktfns.so ktfns.po $(OUTPRE)ktfns.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ktfns.c
+kt_file.so kt_file.po $(OUTPRE)kt_file.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  kt_file.c
+kt_srvtab.so kt_srvtab.po $(OUTPRE)kt_srvtab.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kt_srvtab.c
+read_servi.so read_servi.po $(OUTPRE)read_servi.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h read_servi.c
diff --git a/krb5-1-6/src/lib/krb5/keytab/kt-int.h b/krb5-1-6/src/lib/krb5/keytab/kt-int.h
new file mode 100644
index 000000000..23bbc5505
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/kt-int.h
@@ -0,0 +1,39 @@
+/*
+ * lib/krb5/keytab/kt-int.h
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This file contains constant and function declarations used in the
+ * file-based credential cache routines.
+ */
+
+#ifndef __KRB5_KEYTAB_INT_H__
+#define __KRB5_KEYTAB_INT_H__
+
+
+int krb5int_kt_initialize(void);
+
+void krb5int_kt_finalize(void);
+
+#endif /* __KRB5_KEYTAB_INT_H__ */
diff --git a/krb5-1-6/src/lib/krb5/keytab/kt_file.c b/krb5-1-6/src/lib/krb5/keytab/kt_file.c
new file mode 100644
index 000000000..776727a01
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/kt_file.c
@@ -0,0 +1,1712 @@
+/*
+ * lib/krb5/keytab/kt_file.c
+ *
+ * Copyright 1990,1991,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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+
+/*
+ * Information needed by internal routines of the file-based ticket
+ * cache implementation.
+ */
+
+
+/*
+ * Constants
+ */
+#define IGNORE_VNO 0
+#define IGNORE_ENCTYPE 0
+
+#define KRB5_KT_VNO_1	0x0501	/* krb v5, keytab version 1 (DCE compat) */
+#define KRB5_KT_VNO	0x0502	/* krb v5, keytab version 2 (standard)  */
+
+#define KRB5_KT_DEFAULT_VNO KRB5_KT_VNO
+
+/* 
+ * Types
+ */
+typedef struct _krb5_ktfile_data {
+    char *name;			/* Name of the file */
+    FILE *openf;		/* open file, if any. */
+    char iobuf[BUFSIZ];		/* so we can zap it later */
+    int	version;		/* Version number of keytab */
+    k5_mutex_t lock;		/* Protect openf, version */
+} krb5_ktfile_data;
+
+/*
+ * Macros
+ */
+#define KTPRIVATE(id) ((krb5_ktfile_data *)(id)->data)
+#define KTFILENAME(id) (((krb5_ktfile_data *)(id)->data)->name)
+#define KTFILEP(id) (((krb5_ktfile_data *)(id)->data)->openf)
+#define KTFILEBUFP(id) (((krb5_ktfile_data *)(id)->data)->iobuf)
+#define KTVERSION(id) (((krb5_ktfile_data *)(id)->data)->version)
+#define KTLOCK(id) k5_mutex_lock(&((krb5_ktfile_data *)(id)->data)->lock)
+#define KTUNLOCK(id) k5_mutex_unlock(&((krb5_ktfile_data *)(id)->data)->lock)
+#define KTCHECKLOCK(id) k5_mutex_assert_locked(&((krb5_ktfile_data *)(id)->data)->lock)
+
+extern const struct _krb5_kt_ops krb5_ktf_ops;
+extern const struct _krb5_kt_ops krb5_ktf_writable_ops;
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_resolve 
+	(krb5_context,
+		   const char *,
+		   krb5_keytab *);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_wresolve 
+	(krb5_context,
+		   const char *,
+		   krb5_keytab *);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_get_name 
+	(krb5_context,
+		   krb5_keytab,
+		   char *,
+		   unsigned int);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_close 
+	(krb5_context,
+		   krb5_keytab);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_get_entry 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_const_principal,
+		   krb5_kvno,
+		   krb5_enctype,
+		   krb5_keytab_entry *);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_start_seq_get 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_kt_cursor *);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_get_next 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *,
+		   krb5_kt_cursor *);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_end_get 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_kt_cursor *);
+
+/* routines to be included on extended version (write routines) */
+krb5_error_code KRB5_CALLCONV krb5_ktfile_add 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *);
+
+krb5_error_code KRB5_CALLCONV krb5_ktfile_remove 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *);
+
+krb5_error_code krb5_ktfileint_openr 
+	(krb5_context,
+		   krb5_keytab);
+
+krb5_error_code krb5_ktfileint_openw 
+	(krb5_context,
+		   krb5_keytab);
+
+krb5_error_code krb5_ktfileint_close 
+	(krb5_context,
+		   krb5_keytab);
+
+krb5_error_code krb5_ktfileint_read_entry 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *);
+
+krb5_error_code krb5_ktfileint_write_entry 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *);
+
+krb5_error_code krb5_ktfileint_delete_entry 
+	(krb5_context,
+		   krb5_keytab,
+                   krb5_int32);
+
+krb5_error_code krb5_ktfileint_internal_read_entry 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *,
+                   krb5_int32 *);
+
+krb5_error_code krb5_ktfileint_size_entry 
+	(krb5_context,
+		   krb5_keytab_entry *,
+                   krb5_int32 *);
+
+krb5_error_code krb5_ktfileint_find_slot 
+	(krb5_context,
+		   krb5_keytab,
+                   krb5_int32 *,
+                   krb5_int32 *);
+
+
+/*
+ * This is an implementation specific resolver.  It returns a keytab id 
+ * initialized with file keytab routines.
+ */
+
+krb5_error_code KRB5_CALLCONV 
+krb5_ktfile_resolve(krb5_context context, const char *name, krb5_keytab *id)
+{
+    krb5_ktfile_data *data;
+    krb5_error_code err;
+
+    if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
+	return(ENOMEM);
+    
+    (*id)->ops = &krb5_ktf_ops;
+    if ((data = (krb5_ktfile_data *)malloc(sizeof(krb5_ktfile_data))) == NULL) {
+	krb5_xfree(*id);
+	return(ENOMEM);
+    }
+
+    err = k5_mutex_init(&data->lock);
+    if (err) {
+	krb5_xfree(data);
+	krb5_xfree(*id);
+	return err;
+    }
+
+    if ((data->name = (char *)calloc(strlen(name) + 1, sizeof(char))) == NULL) {
+	k5_mutex_destroy(&data->lock);
+	krb5_xfree(data);
+	krb5_xfree(*id);
+	return(ENOMEM);
+    }
+
+    (void) strcpy(data->name, name);
+    data->openf = 0;
+    data->version = 0;
+
+    (*id)->data = (krb5_pointer)data;
+    (*id)->magic = KV5M_KEYTAB;
+    return(0);
+}
+
+
+/*
+ * "Close" a file-based keytab and invalidate the id.  This means
+ * free memory hidden in the structures.
+ */
+
+krb5_error_code KRB5_CALLCONV 
+krb5_ktfile_close(krb5_context context, krb5_keytab id)
+  /*
+   * This routine is responsible for freeing all memory allocated 
+   * for this keytab.  There are no system resources that need
+   * to be freed nor are there any open files.
+   *
+   * This routine should undo anything done by krb5_ktfile_resolve().
+   */
+{
+    krb5_xfree(KTFILENAME(id));
+    zap(KTFILEBUFP(id), BUFSIZ);
+    k5_mutex_destroy(&((krb5_ktfile_data *)id->data)->lock);
+    krb5_xfree(id->data);
+    id->ops = 0;
+    krb5_xfree(id);
+    return (0);
+}
+
+/*
+ * This is the get_entry routine for the file based keytab implementation.
+ * It opens the keytab file, and either retrieves the entry or returns
+ * an error.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktfile_get_entry(krb5_context context, krb5_keytab id,
+		      krb5_const_principal principal, krb5_kvno kvno,
+		      krb5_enctype enctype, krb5_keytab_entry *entry)
+{
+    krb5_keytab_entry cur_entry, new_entry;
+    krb5_error_code kerror = 0;
+    int found_wrong_kvno = 0;
+    krb5_boolean similar;
+    int kvno_offset = 0;
+
+    kerror = KTLOCK(id);
+    if (kerror)
+	return kerror;
+
+    /* Open the keyfile for reading */
+    if ((kerror = krb5_ktfileint_openr(context, id))) {
+	KTUNLOCK(id);
+	return(kerror);
+    }
+    
+    /* 
+     * For efficiency and simplicity, we'll use a while true that 
+     * is exited with a break statement.
+     */
+    cur_entry.principal = 0;
+    cur_entry.vno = 0;
+    cur_entry.key.contents = 0;
+
+    while (TRUE) {
+	if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry)))
+	    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 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 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;
+	    }
+	    /*
+	     * Coerce the enctype of the output keyblock in case we
+	     * got an inexact match on the enctype.
+	     */
+	    new_entry.key.enctype = enctype;
+
+	}
+
+	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. */
+	    /* A 1.2.x keytab contains only the low 8 bits of the key
+	       version number.  Since it can be much bigger, and thus
+	       the 8-bit value can wrap, we need some heuristics to
+	       figure out the "highest" numbered key if some numbers
+	       close to 255 and some near 0 are used.
+
+	       The heuristic here:
+
+	       If we have any keys with versions over 240, then assume
+	       that all version numbers 0-127 refer to 256+N instead.
+	       Not perfect, but maybe good enough?  */
+
+#define M(VNO) (((VNO) - kvno_offset + 256) % 256)
+
+	    if (new_entry.vno > 240)
+		kvno_offset = 128;
+	    if (! cur_entry.principal ||
+		M(new_entry.vno) > M(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 */
+	    /* Yuck.  The krb5-1.2.x keytab format only stores one byte
+	       for the kvno, so we're toast if the kvno requested is
+	       higher than that.  Short-term workaround: only compare
+	       the low 8 bits.  */
+
+	    if (new_entry.vno == (kvno & 0xff)) {
+		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;
+	 else if (found_wrong_kvno)
+	      kerror = KRB5_KT_KVNONOTFOUND;
+	 else
+	      kerror = KRB5_KT_NOTFOUND;
+    }
+    if (kerror) {
+	(void) krb5_ktfileint_close(context, id);
+	KTUNLOCK(id);
+	krb5_kt_free_entry(context, &cur_entry);
+	return kerror;
+    }
+    if ((kerror = krb5_ktfileint_close(context, id)) != 0) {
+	KTUNLOCK(id);
+	krb5_kt_free_entry(context, &cur_entry);
+	return kerror;
+    }
+    KTUNLOCK(id);
+    *entry = cur_entry;
+    return 0;
+}
+
+/*
+ * Get the name of the file containing a file-based keytab.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktfile_get_name(krb5_context context, krb5_keytab id, char *name, unsigned int len)
+  /* 
+   * This routine returns the name of the name of the file associated with
+   * this file-based keytab.  name is zeroed and the filename is truncated
+   * to fit in name if necessary.  The name is prefixed with PREFIX:, so that
+   * trt will happen if the name is passed back to resolve.
+   */
+{
+    memset(name, 0, len);
+
+    if (len < strlen(id->ops->prefix)+2)
+	return(KRB5_KT_NAME_TOOLONG);
+    strcpy(name, id->ops->prefix);
+    name += strlen(id->ops->prefix);
+    name[0] = ':';
+    name++;
+    len -= strlen(id->ops->prefix)+1;
+
+    if (len < strlen(KTFILENAME(id)+1))
+	return(KRB5_KT_NAME_TOOLONG);
+    strcpy(name, KTFILENAME(id));
+    /* strcpy will NUL-terminate the destination */
+
+    return(0);
+}
+
+/*
+ * krb5_ktfile_start_seq_get()
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktfile_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursorp)
+{
+    krb5_error_code retval;
+    long *fileoff;
+
+    retval = KTLOCK(id);
+    if (retval)
+	return retval;
+
+    if ((retval = krb5_ktfileint_openr(context, id))) {
+	KTUNLOCK(id);
+	return retval;
+    }
+
+    if (!(fileoff = (long *)malloc(sizeof(*fileoff)))) {
+	krb5_ktfileint_close(context, id);
+	KTUNLOCK(id);
+	return ENOMEM;
+    }
+    *fileoff = ftell(KTFILEP(id));
+    *cursorp = (krb5_kt_cursor)fileoff;
+    KTUNLOCK(id);
+
+    return 0;
+}
+
+/*
+ * krb5_ktfile_get_next()
+ */
+
+krb5_error_code KRB5_CALLCONV 
+krb5_ktfile_get_next(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor)
+{
+    long *fileoff = (long *)*cursor;
+    krb5_keytab_entry cur_entry;
+    krb5_error_code kerror;
+
+    kerror = KTLOCK(id);
+    if (kerror)
+	return kerror;
+    if (KTFILEP(id) == NULL) {
+	KTUNLOCK(id);
+	return KRB5_KT_IOERR;
+    }
+    if (fseek(KTFILEP(id), *fileoff, 0) == -1) {
+	KTUNLOCK(id);
+	return KRB5_KT_END;
+    }
+    if ((kerror = krb5_ktfileint_read_entry(context, id, &cur_entry))) {
+	KTUNLOCK(id);
+	return kerror;
+    }
+    *fileoff = ftell(KTFILEP(id));
+    *entry = cur_entry;
+    KTUNLOCK(id);
+    return 0;
+}
+
+/*
+ * krb5_ktfile_end_get()
+ */
+
+krb5_error_code KRB5_CALLCONV 
+krb5_ktfile_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor)
+{
+    krb5_error_code kerror;
+
+    krb5_xfree(*cursor);
+    KTLOCK(id);
+    kerror = krb5_ktfileint_close(context, id);
+    KTUNLOCK(id);
+    return kerror;
+}
+
+/*
+ * ser_ktf.c - Serialize keytab file context for subsequent reopen.
+ */
+
+static const char ktfile_def_name[] = ".";
+
+/*
+ * Routines to deal with externalizing krb5_keytab for [WR]FILE: variants.
+ *	krb5_ktf_keytab_size();
+ *	krb5_ktf_keytab_externalize();
+ *	krb5_ktf_keytab_internalize();
+ */
+static krb5_error_code krb5_ktf_keytab_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_ktf_keytab_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_ktf_keytab_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/*
+ * Serialization entry for this type.
+ */
+const krb5_ser_entry krb5_ktfile_ser_entry = {
+    KV5M_KEYTAB,			/* Type			*/
+    krb5_ktf_keytab_size,		/* Sizer routine	*/
+    krb5_ktf_keytab_externalize,	/* Externalize routine	*/
+    krb5_ktf_keytab_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_ktf_keytab_size()	- Determine the size required to externalize
+ *				  this krb5_keytab variant.
+ */
+static krb5_error_code
+krb5_ktf_keytab_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_keytab		keytab;
+    size_t		required;
+    krb5_ktfile_data	*ktdata;
+
+    kret = EINVAL;
+    if ((keytab = (krb5_keytab) arg)) {
+	/*
+	 * Saving FILE: variants of krb5_keytab requires at minimum:
+	 *	krb5_int32	for KV5M_KEYTAB
+	 *	krb5_int32	for length of keytab name.
+	 *	krb5_int32	for file status.
+	 *	krb5_int32	for file position.
+	 *	krb5_int32	for file position.
+	 *	krb5_int32	for version.
+	 *	krb5_int32	for KV5M_KEYTAB
+	 */
+	required = sizeof(krb5_int32) * 7;
+	if (keytab->ops && keytab->ops->prefix)
+	    required += (strlen(keytab->ops->prefix)+1);
+
+	/*
+	 * The keytab name is formed as follows:
+	 *	<prefix>:<name>
+	 * If there's no name, we use a default name so that we have something
+	 * to call krb5_keytab_resolve with.
+	 */
+	ktdata = (krb5_ktfile_data *) keytab->data;
+	required += strlen((ktdata && ktdata->name) ?
+			   ktdata->name : ktfile_def_name);
+	kret = 0;
+
+	if (!kret)
+	    *sizep += required;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_ktf_keytab_externalize()	- Externalize the krb5_keytab.
+ */
+static krb5_error_code
+krb5_ktf_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_keytab		keytab;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    krb5_ktfile_data	*ktdata;
+    krb5_int32		file_is_open;
+    krb5_int64		file_pos;
+    char		*ktname;
+    size_t		namelen;
+    const char		*fnamep;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((keytab = (krb5_keytab) arg)) {
+	kret = ENOMEM;
+	if (!krb5_ktf_keytab_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_KEYTAB, &bp, &remain);
+
+	    ktdata = (krb5_ktfile_data *) keytab->data;
+	    file_is_open = 0;
+	    file_pos = 0;
+
+	    /* Calculate the length of the name */
+	    namelen = (keytab->ops && keytab->ops->prefix) ?
+		strlen(keytab->ops->prefix)+1 : 0;
+	    if (ktdata && ktdata->name)
+		fnamep = ktdata->name;
+	    else
+		fnamep = ktfile_def_name;
+	    namelen += (strlen(fnamep)+1);
+
+	    if ((ktname = (char *) malloc(namelen))) {
+		/* Format the keytab name. */
+		if (keytab->ops && keytab->ops->prefix)
+		    sprintf(ktname, "%s:%s", keytab->ops->prefix, fnamep);
+
+		else
+		    strcpy(ktname, fnamep);
+
+		/* Fill in the file-specific keytab information. */
+		if (ktdata) {
+		    if (ktdata->openf) {
+			long	fpos;
+			int	fflags = 0;
+
+			file_is_open = 1;
+#if !defined(_WIN32)
+			fflags = fcntl(fileno(ktdata->openf), F_GETFL, 0);
+			if (fflags > 0)
+			    file_is_open |= ((fflags & O_ACCMODE) << 1);
+#else
+			file_is_open = 0;
+#endif
+			fpos = ftell(ktdata->openf);
+			file_pos = fpos; /* XX range check? */
+		    }
+		}
+
+		/* Put the length of the file name */
+		(void) krb5_ser_pack_int32((krb5_int32) strlen(ktname),
+					   &bp, &remain);
+		
+		/* Put the name */
+		(void) krb5_ser_pack_bytes((krb5_octet *) ktname,
+					   strlen(ktname),
+					   &bp, &remain);
+
+		/* Put the file open flag */
+		(void) krb5_ser_pack_int32(file_is_open, &bp, &remain);
+
+		/* Put the file position */
+		(void) krb5_ser_pack_int64(file_pos, &bp, &remain);
+
+		/* Put the version */
+		(void) krb5_ser_pack_int32((krb5_int32) ((ktdata) ?
+							 ktdata->version : 0),
+					   &bp, &remain);
+
+		/* Put the trailer */
+		(void) krb5_ser_pack_int32(KV5M_KEYTAB, &bp, &remain);
+		kret = 0;
+		*buffer = bp;
+		*lenremain = remain;
+		free(ktname);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_ktf_keytab_internalize()	- Internalize the krb5_ktf_keytab.
+ */
+static krb5_error_code
+krb5_ktf_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_keytab		keytab;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    char		*ktname;
+    krb5_ktfile_data	*ktdata;
+    krb5_int32		file_is_open;
+    krb5_int64		foff;
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KV5M_KEYTAB) {
+	kret = ENOMEM;
+
+	/* Get the length of the keytab name */
+	kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+
+	if (!kret &&
+	    (ktname = (char *) malloc((size_t) (ibuf+1))) &&
+	    !(kret = krb5_ser_unpack_bytes((krb5_octet *) ktname,
+					   (size_t) ibuf,
+					   &bp, &remain))) {
+	    ktname[ibuf] = '\0';
+	    kret = krb5_kt_resolve(kcontext, ktname, &keytab);
+	    if (!kret) {
+		kret = ENOMEM;
+		ktdata = (krb5_ktfile_data *) keytab->data;
+		if (!ktdata) {
+		    /* XXX */
+		    keytab->data = (void *) malloc(sizeof(krb5_ktfile_data));
+		    ktdata = (krb5_ktfile_data *) keytab->data;
+		    memset(ktdata, 0, sizeof(krb5_ktfile_data));
+		    if (strchr(ktname, (int) ':'))
+			ktdata->name = strdup(strchr(ktname, (int) ':')+1);
+		    else
+			ktdata->name = strdup(ktname);
+		}
+		if (ktdata) {
+		    if (remain >= (sizeof(krb5_int32)*5)) {
+			(void) krb5_ser_unpack_int32(&file_is_open,
+						     &bp, &remain);
+			(void) krb5_ser_unpack_int64(&foff, &bp, &remain);
+			(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+			ktdata->version = (int) ibuf;
+
+			(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+			if (ibuf == KV5M_KEYTAB) {
+			    if (file_is_open) {
+				int 	fmode;
+				long	fpos;
+
+#if !defined(_WIN32)
+				fmode = (file_is_open >> 1) & O_ACCMODE;
+#else
+				fmode = 0;
+#endif
+				if (fmode)
+				    kret = krb5_ktfileint_openw(kcontext,
+								keytab);
+				else
+				    kret = krb5_ktfileint_openr(kcontext,
+								keytab);
+				if (!kret) {
+				    fpos = foff; /* XX range check? */
+				    fseek(KTFILEP(keytab), fpos, SEEK_SET);
+				}
+			    }
+			    kret = 0;
+			}
+			else
+			    kret = EINVAL;
+		    }
+		}
+		if (kret) {
+		    if (keytab->data) {
+			if (KTFILENAME(keytab))
+			    krb5_xfree(KTFILENAME(keytab));
+			krb5_xfree(keytab->data);
+		    }
+		    krb5_xfree(keytab);
+		}
+		else {
+		    *buffer = bp;
+		    *lenremain = remain;
+		    *argp = (krb5_pointer) keytab;
+		}
+	    }
+	    free(ktname);
+	}
+    }
+    return(kret);
+}
+
+/*
+ * This is an implementation specific resolver.  It returns a keytab id 
+ * initialized with file keytab routines.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktfile_wresolve(krb5_context context, const char *name, krb5_keytab *id)
+{
+    krb5_ktfile_data *data;
+    krb5_error_code err;
+
+    if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
+	return(ENOMEM);
+    
+    (*id)->ops = &krb5_ktf_writable_ops;
+    if ((data = (krb5_ktfile_data *)malloc(sizeof(krb5_ktfile_data))) == NULL) {
+	krb5_xfree(*id);
+	return(ENOMEM);
+    }
+
+    err = k5_mutex_init(&data->lock);
+    if (err) {
+	krb5_xfree(data);
+	krb5_xfree(*id);
+	return err;
+    }
+
+    if ((data->name = (char *)calloc(strlen(name) + 1, sizeof(char))) == NULL) {
+	k5_mutex_destroy(&data->lock);
+	krb5_xfree(data);
+	krb5_xfree(*id);
+	return(ENOMEM);
+    }
+
+    (void) strcpy(data->name, name);
+    data->openf = 0;
+    data->version = 0;
+
+    (*id)->data = (krb5_pointer)data;
+    (*id)->magic = KV5M_KEYTAB;
+    return(0);
+}
+
+
+/*
+ * krb5_ktfile_add()
+ */
+
+krb5_error_code KRB5_CALLCONV 
+krb5_ktfile_add(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
+{
+    krb5_error_code retval;
+
+    retval = KTLOCK(id);
+    if (retval)
+	return retval;
+    if ((retval = krb5_ktfileint_openw(context, id))) {
+	KTUNLOCK(id);
+	return retval;
+    }
+    if (fseek(KTFILEP(id), 0, 2) == -1) {
+	KTUNLOCK(id);
+	return KRB5_KT_END;
+    }
+    retval = krb5_ktfileint_write_entry(context, id, entry);
+    krb5_ktfileint_close(context, id);
+    KTUNLOCK(id);
+    return retval;
+}
+
+/*
+ * krb5_ktfile_remove()
+ */
+
+krb5_error_code KRB5_CALLCONV 
+krb5_ktfile_remove(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
+{
+    krb5_keytab_entry   cur_entry;
+    krb5_error_code     kerror;
+    krb5_int32          delete_point;
+
+    kerror = KTLOCK(id);
+    if (kerror)
+	return kerror;
+
+    if ((kerror = krb5_ktfileint_openw(context, id))) {
+	KTUNLOCK(id);
+	return kerror;
+    }
+
+    /* 
+     * For efficiency and simplicity, we'll use a while true that 
+     * is exited with a break statement.
+     */
+    while (TRUE) {
+	if ((kerror = krb5_ktfileint_internal_read_entry(context, id,
+							 &cur_entry,
+							 &delete_point)))
+  	    break;
+
+	if ((entry->vno == cur_entry.vno) &&
+            (entry->key.enctype == cur_entry.key.enctype) &&
+	    krb5_principal_compare(context, entry->principal, cur_entry.principal)) {
+	    /* found a match */
+            krb5_kt_free_entry(context, &cur_entry);
+	    break;
+	}
+	krb5_kt_free_entry(context, &cur_entry);
+    }
+
+    if (kerror == KRB5_KT_END)
+	kerror = KRB5_KT_NOTFOUND;
+
+    if (kerror) {
+	(void) krb5_ktfileint_close(context, id);
+	KTUNLOCK(id);
+	return kerror;
+    }
+
+    kerror = krb5_ktfileint_delete_entry(context, id, delete_point);
+
+    if (kerror) {
+	(void) krb5_ktfileint_close(context, id);
+    } else {
+        kerror = krb5_ktfileint_close(context, id);
+    }
+    KTUNLOCK(id);
+    return kerror;
+}
+
+/*
+ * krb5_ktf_ops
+ */
+
+const struct _krb5_kt_ops krb5_ktf_ops = {
+    0,
+    "FILE", 	/* Prefix -- this string should not appear anywhere else! */
+    krb5_ktfile_resolve,
+    krb5_ktfile_get_name, 
+    krb5_ktfile_close,
+    krb5_ktfile_get_entry,
+    krb5_ktfile_start_seq_get,
+    krb5_ktfile_get_next,
+    krb5_ktfile_end_get,
+    0,
+    0,
+    &krb5_ktfile_ser_entry
+};
+
+/*
+ * krb5_ktf_writable_ops
+ */
+
+const struct _krb5_kt_ops krb5_ktf_writable_ops = {
+    0,
+    "WRFILE", 	/* Prefix -- this string should not appear anywhere else! */
+    krb5_ktfile_wresolve,
+    krb5_ktfile_get_name, 
+    krb5_ktfile_close,
+    krb5_ktfile_get_entry,
+    krb5_ktfile_start_seq_get,
+    krb5_ktfile_get_next,
+    krb5_ktfile_end_get,
+    krb5_ktfile_add,
+    krb5_ktfile_remove,
+    &krb5_ktfile_ser_entry
+};
+
+/*
+ * krb5_kt_dfl_ops
+ */
+
+const krb5_kt_ops krb5_kt_dfl_ops = {
+    0,
+    "FILE", 	/* Prefix -- this string should not appear anywhere else! */
+    krb5_ktfile_resolve,
+    krb5_ktfile_get_name, 
+    krb5_ktfile_close,
+    krb5_ktfile_get_entry,
+    krb5_ktfile_start_seq_get,
+    krb5_ktfile_get_next,
+    krb5_ktfile_end_get,
+    0,
+    0,
+    &krb5_ktfile_ser_entry
+};
+
+/*
+ * lib/krb5/keytab/file/ktf_util.c
+ *
+ * Copyright (c) Hewlett-Packard Company 1991
+ * Released to the Massachusetts Institute of Technology for inclusion
+ * in the Kerberos source code distribution.
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This function contains utilities for the file based implementation of 
+ * the keytab.  There are no public functions in this file.
+ *
+ * This file is the only one that has knowledge of the format of a
+ * keytab file.
+ *
+ * The format is as follows:
+ * 
+ * <file format vno>
+ * <record length>
+ * principal timestamp vno key
+ * <record length>
+ * principal timestamp vno key
+ * ....
+ *
+ * A length field (sizeof(krb5_int32)) exists between entries.  When this
+ * length is positive it indicates an active entry, when negative a hole.
+ * The length indicates the size of the block in the file (this may be 
+ * larger than the size of the next record, since we are using a first
+ * fit algorithm for re-using holes and the first fit may be larger than
+ * the entry we are writing).  Another (compatible) implementation could
+ * break up holes when allocating them to smaller entries to minimize 
+ * wasted space.  (Such an implementation should also coalesce adjacent
+ * holes to reduce fragmentation).  This implementation does neither.
+ *
+ * There are no separators between fields of an entry.  
+ * A principal is a length-encoded array of length-encoded strings.  The
+ * length is a krb5_int16 in each case.  The specific format, then, is 
+ * multiple entries concatinated with no separators.  An entry has this 
+ * exact format:
+ *
+ * sizeof(krb5_int16) bytes for number of components in the principal; 
+ * then, each component listed in ordser.
+ * For each component, sizeof(krb5_int16) bytes for the number of bytes
+ * in the component, followed by the component.
+ * sizeof(krb5_int32) for the principal type (for KEYTAB V2 and higher)
+ * sizeof(krb5_int32) bytes for the timestamp
+ * sizeof(krb5_octet) bytes for the key version number
+ * sizeof(krb5_int16) bytes for the enctype
+ * sizeof(krb5_int32) bytes for the key length, followed by the key
+ */
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#endif
+
+typedef krb5_int16  krb5_kt_vno;
+
+#define krb5_kt_default_vno ((krb5_kt_vno)KRB5_KT_DEFAULT_VNO)
+
+#define xfwrite(a, b, c, d) fwrite((char *)a, b, (unsigned) c, d)
+#define xfread(a, b, c, d) fread((char *)a, b, (unsigned) c, d)
+
+#ifdef ANSI_STDIO
+static char *const fopen_mode_rbplus= "rb+";
+static char *const fopen_mode_rb = "rb";
+#else
+static char *const fopen_mode_rbplus= "r+";
+static char *const fopen_mode_rb = "r";
+#endif
+
+static krb5_error_code
+krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
+{
+    krb5_error_code kerror;
+    krb5_kt_vno kt_vno;
+    int writevno = 0;
+
+    KTCHECKLOCK(id);
+    errno = 0;
+    KTFILEP(id) = fopen(KTFILENAME(id),
+			(mode == KRB5_LOCKMODE_EXCLUSIVE) ?
+			  fopen_mode_rbplus : fopen_mode_rb);
+    if (!KTFILEP(id)) {
+	if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) {
+	    /* try making it first time around */
+            krb5_create_secure_file(context, KTFILENAME(id));
+	    errno = 0;
+	    KTFILEP(id) = fopen(KTFILENAME(id), fopen_mode_rbplus);
+	    if (!KTFILEP(id))
+		return errno ? errno : EMFILE;
+	    writevno = 1;
+	} else				/* some other error */
+	    return errno ? errno : EMFILE;
+    }
+    if ((kerror = krb5_lock_file(context, fileno(KTFILEP(id)), mode))) {
+	(void) fclose(KTFILEP(id));
+	KTFILEP(id) = 0;
+	return kerror;
+    }
+    /* assume ANSI or BSD-style stdio */
+    setbuf(KTFILEP(id), KTFILEBUFP(id));
+
+    /* get the vno and verify it */
+    if (writevno) {
+	kt_vno = htons(krb5_kt_default_vno);
+	KTVERSION(id) = krb5_kt_default_vno;
+	if (!xfwrite(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) {
+	    kerror = errno;
+	    (void) krb5_unlock_file(context, fileno(KTFILEP(id)));
+	    (void) fclose(KTFILEP(id));
+	    return kerror;
+	}
+    } else {
+	/* gotta verify it instead... */
+	if (!xfread(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) {
+	    if (feof(KTFILEP(id)))
+		kerror = KRB5_KEYTAB_BADVNO;
+	    else
+		kerror = errno;
+	    (void) krb5_unlock_file(context, fileno(KTFILEP(id)));
+	    (void) fclose(KTFILEP(id));
+	    return kerror;
+	}
+	kt_vno = KTVERSION(id) = ntohs(kt_vno);
+	if ((kt_vno != KRB5_KT_VNO) &&
+	    (kt_vno != KRB5_KT_VNO_1)) {
+	    (void) krb5_unlock_file(context, fileno(KTFILEP(id)));
+	    (void) fclose(KTFILEP(id));
+	    return KRB5_KEYTAB_BADVNO;
+	}
+    }
+    return 0;
+}
+
+krb5_error_code
+krb5_ktfileint_openr(krb5_context context, krb5_keytab id)
+{
+    return krb5_ktfileint_open(context, id, KRB5_LOCKMODE_SHARED);
+}
+
+krb5_error_code
+krb5_ktfileint_openw(krb5_context context, krb5_keytab id)
+{
+    return krb5_ktfileint_open(context, id, KRB5_LOCKMODE_EXCLUSIVE);
+}
+
+krb5_error_code
+krb5_ktfileint_close(krb5_context context, krb5_keytab id)
+{
+    krb5_error_code kerror;
+
+    KTCHECKLOCK(id);
+    if (!KTFILEP(id))
+	return 0;
+    kerror = krb5_unlock_file(context, fileno(KTFILEP(id)));
+    (void) fclose(KTFILEP(id));
+    KTFILEP(id) = 0;
+    return kerror;
+}
+
+krb5_error_code
+krb5_ktfileint_delete_entry(krb5_context context, krb5_keytab id, krb5_int32 delete_point)
+{
+    krb5_int32  size;
+    krb5_int32  len;
+    char        iobuf[BUFSIZ];
+
+    KTCHECKLOCK(id);
+    if (fseek(KTFILEP(id), delete_point, SEEK_SET)) {
+        return errno;
+    }
+    if (!xfread(&size, sizeof(size), 1, KTFILEP(id))) {
+        return KRB5_KT_END;
+    }
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+	size = ntohl(size);
+
+    if (size > 0) {
+        krb5_int32 minus_size = -size;
+	if (KTVERSION(id) != KRB5_KT_VNO_1)
+	    minus_size = htonl(minus_size);
+
+        if (fseek(KTFILEP(id), delete_point, SEEK_SET)) {
+            return errno;
+        }
+
+        if (!xfwrite(&minus_size, sizeof(minus_size), 1, KTFILEP(id))) {
+            return KRB5_KT_IOERR;
+        }
+
+        if (size < BUFSIZ) {
+            len = size;
+        } else {
+            len = BUFSIZ;
+        }
+
+        memset(iobuf, 0, (size_t) len);
+        while (size > 0) {
+            xfwrite(iobuf, 1, (size_t) len, KTFILEP(id));
+            size -= len;
+            if (size < len) {
+                len = size;
+            }
+        }
+
+        return krb5_sync_disk_file(context, KTFILEP(id));
+    }
+
+    return 0;
+}
+
+krb5_error_code
+krb5_ktfileint_internal_read_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *ret_entry, krb5_int32 *delete_point)
+{
+    krb5_octet vno;
+    krb5_int16 count;
+    unsigned int u_count, u_princ_size;
+    krb5_int16 enctype;
+    krb5_int16 princ_size;
+    register int i;
+    krb5_int32 size;
+    krb5_int32 start_pos;
+    krb5_error_code error;
+    char	*tmpdata;
+    krb5_data	*princ;
+
+    KTCHECKLOCK(id);
+    memset(ret_entry, 0, sizeof(krb5_keytab_entry));
+    ret_entry->magic = KV5M_KEYTAB_ENTRY;
+
+    /* fseek to synchronise buffered I/O on the key table. */
+
+    if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0)
+    {
+        return errno;
+    }
+
+    do {
+        *delete_point = ftell(KTFILEP(id));
+        if (!xfread(&size, sizeof(size), 1, KTFILEP(id))) {
+            return KRB5_KT_END;
+        }
+	if (KTVERSION(id) != KRB5_KT_VNO_1)
+		size = ntohl(size);
+
+        if (size < 0) {
+            if (fseek(KTFILEP(id), -size, SEEK_CUR)) {
+                return errno;
+            }
+        }
+    } while (size < 0);
+
+    if (size == 0) {
+        return KRB5_KT_END;
+    }
+
+    start_pos = ftell(KTFILEP(id));
+
+    /* deal with guts of parsing... */
+
+    /* first, int16 with #princ components */
+    if (!xfread(&count, sizeof(count), 1, KTFILEP(id)))
+	return KRB5_KT_END;
+    if (KTVERSION(id) == KRB5_KT_VNO_1) {
+	    count -= 1;		/* V1 includes the realm in the count */
+    } else {
+	    count = ntohs(count);
+    }
+    if (!count || (count < 0))
+	return KRB5_KT_END;
+    ret_entry->principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
+    if (!ret_entry->principal)
+        return ENOMEM;
+    
+    u_count = count;
+    ret_entry->principal->magic = KV5M_PRINCIPAL;
+    ret_entry->principal->length = u_count;
+    ret_entry->principal->data = (krb5_data *) 
+                                 calloc(u_count, sizeof(krb5_data));
+    if (!ret_entry->principal->data) {
+	free(ret_entry->principal);
+	ret_entry->principal = 0;
+	return ENOMEM;
+    }
+
+    /* Now, get the realm data */
+    if (!xfread(&princ_size, sizeof(princ_size), 1, KTFILEP(id))) {
+	    error = KRB5_KT_END;
+	    goto fail;
+    }
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+	    princ_size = ntohs(princ_size);
+    if (!princ_size || (princ_size < 0)) {
+	    error = KRB5_KT_END;
+	    goto fail;
+    }
+    u_princ_size = princ_size;
+
+    krb5_princ_set_realm_length(context, ret_entry->principal, u_princ_size);
+    tmpdata = malloc(u_princ_size+1);
+    if (!tmpdata) {
+	    error = ENOMEM;
+	    goto fail;
+    }
+    if (fread(tmpdata, 1, u_princ_size, KTFILEP(id)) != (size_t) princ_size) {
+	    free(tmpdata);
+	    error = KRB5_KT_END;
+	    goto fail;
+    }
+    tmpdata[princ_size] = 0;	/* Some things might be expecting null */
+				/* termination...  ``Be conservative in */
+				/* what you send out'' */
+    krb5_princ_set_realm_data(context, ret_entry->principal, tmpdata);
+    
+    for (i = 0; i < count; i++) {
+	princ = krb5_princ_component(context, ret_entry->principal, i);
+	if (!xfread(&princ_size, sizeof(princ_size), 1, KTFILEP(id))) {
+	    error = KRB5_KT_END;
+	    goto fail;
+        }
+	if (KTVERSION(id) != KRB5_KT_VNO_1)
+	    princ_size = ntohs(princ_size);
+	if (!princ_size || (princ_size < 0)) {
+	    error = KRB5_KT_END;
+	    goto fail;
+        }
+
+	u_princ_size = princ_size; 
+	princ->length = u_princ_size;
+	princ->data = malloc(u_princ_size+1);
+	if (!princ->data) {
+	    error = ENOMEM;
+	    goto fail;
+        }
+	if (!xfread(princ->data, sizeof(char), u_princ_size, KTFILEP(id))) {
+	    error = KRB5_KT_END;
+	    goto fail;
+        }
+	princ->data[princ_size] = 0; /* Null terminate */
+    }
+
+    /* read in the principal type, if we can get it */
+    if (KTVERSION(id) != KRB5_KT_VNO_1) {
+	    if (!xfread(&ret_entry->principal->type,
+			sizeof(ret_entry->principal->type), 1, KTFILEP(id))) {
+		    error = KRB5_KT_END;
+		    goto fail;
+	    }
+	    ret_entry->principal->type = ntohl(ret_entry->principal->type);
+    }
+    
+    /* read in the timestamp */
+    if (!xfread(&ret_entry->timestamp, sizeof(ret_entry->timestamp), 1, KTFILEP(id))) {
+	error = KRB5_KT_END;
+	goto fail;
+    }
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+	ret_entry->timestamp = ntohl(ret_entry->timestamp);
+    
+    /* read in the version number */
+    if (!xfread(&vno, sizeof(vno), 1, KTFILEP(id))) {
+	error = KRB5_KT_END;
+	goto fail;
+    }
+    ret_entry->vno = (krb5_kvno)vno;
+    
+    /* key type */
+    if (!xfread(&enctype, sizeof(enctype), 1, KTFILEP(id))) {
+	error = KRB5_KT_END;
+	goto fail;
+    }
+    ret_entry->key.enctype = (krb5_enctype)enctype;
+
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+	ret_entry->key.enctype = ntohs(ret_entry->key.enctype);
+    
+    /* key contents */
+    ret_entry->key.magic = KV5M_KEYBLOCK;
+    
+    if (!xfread(&count, sizeof(count), 1, KTFILEP(id))) {
+	error = KRB5_KT_END;
+	goto fail;
+    }
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+	count = ntohs(count);
+    if (!count || (count < 0)) {
+	error = KRB5_KT_END;
+	goto fail;
+    }
+
+    u_count = count;
+    ret_entry->key.length = u_count;
+    
+    ret_entry->key.contents = (krb5_octet *)malloc(u_count);
+    if (!ret_entry->key.contents) {
+	error = ENOMEM;
+	goto fail;
+    }		
+    if (!xfread(ret_entry->key.contents, sizeof(krb5_octet), count,
+		KTFILEP(id))) {
+	error = KRB5_KT_END;
+	goto fail;
+    }
+
+    /*
+     * Reposition file pointer to the next inter-record length field.
+     */
+    fseek(KTFILEP(id), start_pos + size, SEEK_SET);
+    return 0;
+fail:
+    
+    for (i = 0; i < krb5_princ_size(context, ret_entry->principal); i++) {
+	    princ = krb5_princ_component(context, ret_entry->principal, i);
+	    if (princ->data)
+		    free(princ->data);
+    }
+    free(ret_entry->principal->data);
+    ret_entry->principal->data = 0;
+    free(ret_entry->principal);
+    ret_entry->principal = 0;
+    return error;
+}
+
+krb5_error_code
+krb5_ktfileint_read_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entryp)
+{
+    krb5_int32 delete_point;
+
+    return krb5_ktfileint_internal_read_entry(context, id, entryp, &delete_point);
+}
+
+krb5_error_code
+krb5_ktfileint_write_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
+{
+    krb5_octet vno;
+    krb5_data *princ;
+    krb5_int16 count, size, enctype;
+    krb5_error_code retval = 0;
+    krb5_timestamp timestamp;
+    krb5_int32	princ_type;
+    krb5_int32  size_needed;
+    krb5_int32  commit_point;
+    int		i;
+
+    KTCHECKLOCK(id);
+    retval = krb5_ktfileint_size_entry(context, entry, &size_needed);
+    if (retval)
+        return retval;
+    retval = krb5_ktfileint_find_slot(context, id, &size_needed, &commit_point);
+    if (retval)
+        return retval;
+
+    /* fseek to synchronise buffered I/O on the key table. */
+    /* XXX Without the weird setbuf crock, can we get rid of this now?  */
+    if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0)
+    {
+        return errno;
+    }
+
+    if (KTVERSION(id) == KRB5_KT_VNO_1) {
+	    count = (krb5_int16) krb5_princ_size(context, entry->principal) + 1;
+    } else {
+	    count = htons((u_short) krb5_princ_size(context, entry->principal));
+    }
+    
+    if (!xfwrite(&count, sizeof(count), 1, KTFILEP(id))) {
+    abend:
+	return KRB5_KT_IOERR;
+    }
+    size = krb5_princ_realm(context, entry->principal)->length;
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+	    size = htons(size);
+    if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
+	    goto abend;
+    }
+    if (!xfwrite(krb5_princ_realm(context, entry->principal)->data, sizeof(char),
+		 krb5_princ_realm(context, entry->principal)->length, KTFILEP(id))) {
+	    goto abend;
+    }
+
+    count = (krb5_int16) krb5_princ_size(context, entry->principal);
+    for (i = 0; i < count; i++) {
+	princ = krb5_princ_component(context, entry->principal, i);
+	size = princ->length;
+	if (KTVERSION(id) != KRB5_KT_VNO_1)
+		size = htons(size);
+	if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
+	    goto abend;
+	}
+	if (!xfwrite(princ->data, sizeof(char), princ->length, KTFILEP(id))) {
+	    goto abend;
+	}
+    }
+
+    /*
+     * Write out the principal type
+     */
+    if (KTVERSION(id) != KRB5_KT_VNO_1) {
+	    princ_type = htonl(krb5_princ_type(context, entry->principal));
+	    if (!xfwrite(&princ_type, sizeof(princ_type), 1, KTFILEP(id))) {
+		    goto abend;
+	    }
+    }
+    
+    /*
+     * Fill in the time of day the entry was written to the keytab.
+     */
+    if (krb5_timeofday(context, &entry->timestamp)) {
+        entry->timestamp = 0;
+    }
+    if (KTVERSION(id) == KRB5_KT_VNO_1)
+	    timestamp = entry->timestamp;
+    else
+	    timestamp = htonl(entry->timestamp);
+    if (!xfwrite(×tamp, sizeof(timestamp), 1, KTFILEP(id))) {
+	goto abend;
+    }
+    
+    /* key version number */
+    vno = (krb5_octet)entry->vno;
+    if (!xfwrite(&vno, sizeof(vno), 1, KTFILEP(id))) {
+	goto abend;
+    }
+    /* key type */
+    if (KTVERSION(id) == KRB5_KT_VNO_1)
+	    enctype = entry->key.enctype;
+    else
+	    enctype = htons(entry->key.enctype);
+    if (!xfwrite(&enctype, sizeof(enctype), 1, KTFILEP(id))) {
+	goto abend;
+    }
+    /* key length */
+    if (KTVERSION(id) == KRB5_KT_VNO_1)
+	    size = entry->key.length;
+    else
+	    size = htons(entry->key.length);
+    if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
+	goto abend;
+    }
+    if (!xfwrite(entry->key.contents, sizeof(krb5_octet),
+		 entry->key.length, KTFILEP(id))) {
+	goto abend;
+    }	
+
+    if (fflush(KTFILEP(id)))
+	goto abend;
+
+    retval = krb5_sync_disk_file(context, KTFILEP(id));
+
+    if (retval) {
+        return retval;
+    }
+
+    if (fseek(KTFILEP(id), commit_point, SEEK_SET)) {
+        return errno;
+    }
+    if (KTVERSION(id) != KRB5_KT_VNO_1)
+	    size_needed = htonl(size_needed);
+    if (!xfwrite(&size_needed, sizeof(size_needed), 1, KTFILEP(id))) {
+        goto abend;
+    }
+    if (fflush(KTFILEP(id)))
+	goto abend;
+    retval = krb5_sync_disk_file(context, KTFILEP(id));
+
+    return retval;
+}
+
+/*
+ * Determine the size needed for a file entry for the given
+ * keytab entry.
+ */
+krb5_error_code
+krb5_ktfileint_size_entry(krb5_context context, krb5_keytab_entry *entry, krb5_int32 *size_needed)
+{
+    krb5_int16 count;
+    krb5_int32 total_size, i;
+    krb5_error_code retval = 0;
+
+    count = (krb5_int16) krb5_princ_size(context, entry->principal);
+        
+    total_size = sizeof(count);
+    total_size += krb5_princ_realm(context, entry->principal)->length + (sizeof(krb5_int16));
+    
+    for (i = 0; i < count; i++) {
+	    total_size += krb5_princ_component(context, entry->principal,i)->length
+		    + (sizeof(krb5_int16));
+    }
+
+    total_size += sizeof(entry->principal->type);
+    total_size += sizeof(entry->timestamp);
+    total_size += sizeof(krb5_octet);
+    total_size += sizeof(krb5_int16);
+    total_size += sizeof(krb5_int16) + entry->key.length;
+
+    *size_needed = total_size;
+    return retval;
+}
+
+/*
+ * Find and reserve a slot in the file for an entry of the needed size.
+ * The commit point will be set to the position in the file where the
+ * the length (sizeof(krb5_int32) bytes) of this node should be written
+ * when commiting the write.  The file position left as a result of this
+ * call is the position where the actual data should be written.
+ *
+ * The size_needed argument may be adjusted if we find a hole that is
+ * larger than the size needed.  (Recall that size_needed will be used
+ * to commit the write, but that this field must indicate the size of the
+ * block in the file rather than the size of the actual entry)  
+ */
+krb5_error_code
+krb5_ktfileint_find_slot(krb5_context context, krb5_keytab id, krb5_int32 *size_needed, krb5_int32 *commit_point)
+{
+    krb5_int32      size;
+    krb5_int32      remainder;
+    krb5_int32      zero_point;
+    krb5_kt_vno     kt_vno;
+    krb5_boolean    found = FALSE;
+    char            iobuf[BUFSIZ];
+
+    KTCHECKLOCK(id);
+    /*
+     * Skip over file version number
+     */
+    if (fseek(KTFILEP(id), 0, SEEK_SET)) {
+        return errno;
+    }
+    if (!xfread(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) {
+        return KRB5_KT_IOERR;
+    }
+
+    while (!found) {
+        *commit_point = ftell(KTFILEP(id));
+        if (!xfread(&size, sizeof(size), 1, KTFILEP(id))) {
+            /*
+             * Hit the end of file, reserve this slot.
+             */
+            size = 0;
+
+            /* fseek to synchronise buffered I/O on the key table. */
+	    /* XXX Without the weird setbuf hack, can we nuke this now?  */
+            if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0)
+            {
+                return errno;
+            }
+	    
+#ifdef notdef
+	    /* We don't have to do this because htonl(0) == 0 */
+	    if (KTVERSION(id) != KRB5_KT_VNO_1)
+		    size = htonl(size);
+#endif
+	    
+            if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
+                return KRB5_KT_IOERR;
+            }
+            found = TRUE;
+        }
+
+	if (KTVERSION(id) != KRB5_KT_VNO_1)
+		size = ntohl(size);
+
+        if (size > 0) {
+            if (fseek(KTFILEP(id), size, SEEK_CUR)) {
+                return errno;
+            }
+        } else if (!found) {
+            size = -size;
+            if (size >= *size_needed) {
+                *size_needed = size;
+                found = TRUE;	
+            } else if (size > 0) {
+                /*
+                 * The current hole is not large enough, so skip it
+                 */
+                if (fseek(KTFILEP(id), size, SEEK_CUR)) {
+                    return errno;
+                }
+            } else {
+
+                 /* fseek to synchronise buffered I/O on the key table. */
+
+                 if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0)
+                 {
+                     return errno;
+                 }
+
+                /*
+                 * Found the end of the file (marked by a 0 length buffer)
+                 * Make sure we zero any trailing data.
+                 */
+                zero_point = ftell(KTFILEP(id));
+                while ((size = xfread(iobuf, 1, sizeof(iobuf), KTFILEP(id)))) {
+                    if (size != sizeof(iobuf)) {
+                        remainder = size % sizeof(krb5_int32);
+                        if (remainder) {
+                            size += sizeof(krb5_int32) - remainder;
+                        }
+                    }
+
+                    if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0)
+                    {
+                        return errno;
+                    }
+
+                    memset(iobuf, 0, (size_t) size);
+                    xfwrite(iobuf, 1, (size_t) size, KTFILEP(id));
+		    fflush(KTFILEP(id));
+                    if (feof(KTFILEP(id))) {
+                        break;
+                    }
+
+                    if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0)
+                    {
+                        return errno;
+                    }
+
+                }
+                if (fseek(KTFILEP(id), zero_point, SEEK_SET)) {
+                    return errno;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/keytab/kt_srvtab.c b/krb5-1-6/src/lib/krb5/keytab/kt_srvtab.c
new file mode 100644
index 000000000..cb9d9c1bc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/kt_srvtab.c
@@ -0,0 +1,482 @@
+/*
+ * lib/krb5/keytab/srvtab/kts_resolv.c
+ *
+ * Copyright 1990,1991,2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+
+/*
+ * Constants
+ */
+#define IGNORE_VNO 0
+#define IGNORE_ENCTYPE 0
+
+#define KRB5_KT_VNO_1	0x0501	/* krb v5, keytab version 1 (DCE compat) */
+#define KRB5_KT_VNO	0x0502	/* krb v5, keytab version 2 (standard)  */
+
+#define KRB5_KT_DEFAULT_VNO KRB5_KT_VNO
+
+/* 
+ * Types
+ */
+typedef struct _krb5_ktsrvtab_data {
+    char *name;			/* Name of the file */
+    FILE *openf;		/* open file, if any. */
+} krb5_ktsrvtab_data;
+
+/*
+ * Macros
+ */
+#define KTPRIVATE(id) ((krb5_ktsrvtab_data *)(id)->data)
+#define KTFILENAME(id) (((krb5_ktsrvtab_data *)(id)->data)->name)
+#define KTFILEP(id) (((krb5_ktsrvtab_data *)(id)->data)->openf)
+
+extern const struct _krb5_kt_ops krb5_kts_ops;
+
+static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_resolve
+	(krb5_context,
+		   const char *,
+		   krb5_keytab *);
+
+static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_get_name
+	(krb5_context,
+		   krb5_keytab,
+		   char *,
+		   unsigned int);
+
+static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_close
+	(krb5_context,
+		   krb5_keytab);
+
+static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_get_entry
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_const_principal,
+		   krb5_kvno,
+		   krb5_enctype,
+		   krb5_keytab_entry *);
+
+static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_start_seq_get
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_kt_cursor *);
+
+static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_get_next
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *,
+		   krb5_kt_cursor *);
+
+static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_end_get
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_kt_cursor *);
+
+static krb5_error_code krb5_ktsrvint_open
+	(krb5_context,
+		   krb5_keytab);
+
+static krb5_error_code krb5_ktsrvint_close
+	(krb5_context,
+		   krb5_keytab);
+
+static krb5_error_code krb5_ktsrvint_read_entry 
+	(krb5_context,
+		   krb5_keytab,
+		   krb5_keytab_entry *);
+
+/*
+ * This is an implementation specific resolver.  It returns a keytab id 
+ * initialized with srvtab keytab routines.
+ */
+
+static krb5_error_code KRB5_CALLCONV
+krb5_ktsrvtab_resolve(krb5_context context, const char *name, krb5_keytab *id)
+{
+    krb5_ktsrvtab_data *data;
+    FILE *fp;
+
+    /* Make sure we can open the srvtab file for reading. */
+    fp = fopen(name, "r");
+    if (!fp)
+	return(errno);
+    fclose(fp);
+
+    if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
+	return(ENOMEM);
+    
+    (*id)->ops = &krb5_kts_ops;
+    data = (krb5_ktsrvtab_data *)malloc(sizeof(krb5_ktsrvtab_data));
+    if (data == NULL) {
+	krb5_xfree(*id);
+	return(ENOMEM);
+    }
+
+    data->name = (char *)malloc(strlen(name) + 1);
+    if (data->name == NULL) {
+	krb5_xfree(data);
+	krb5_xfree(*id);
+	return(ENOMEM);
+    }
+
+    (void) strcpy(data->name, name);
+    data->openf = 0;
+
+    (*id)->data = (krb5_pointer)data;
+    (*id)->magic = KV5M_KEYTAB;
+    return(0);
+}
+
+/*
+ * "Close" a file-based keytab and invalidate the id.  This means
+ * free memory hidden in the structures.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktsrvtab_close(krb5_context context, krb5_keytab id)
+  /*
+   * This routine is responsible for freeing all memory allocated 
+   * for this keytab.  There are no system resources that need
+   * to be freed nor are there any open files.
+   *
+   * This routine should undo anything done by krb5_ktsrvtab_resolve().
+   */
+{
+    krb5_xfree(KTFILENAME(id));
+    krb5_xfree(id->data);
+    id->ops = 0;
+    krb5_xfree(id);
+    return (0);
+}
+
+/*
+ * This is the get_entry routine for the file based keytab implementation.
+ * It opens the keytab file, and either retrieves the entry or returns
+ * an error.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktsrvtab_get_entry(krb5_context context, krb5_keytab id, krb5_const_principal principal, krb5_kvno kvno, krb5_enctype enctype, krb5_keytab_entry *entry)
+{
+    krb5_keytab_entry best_entry, ent;
+    krb5_error_code kerror = 0;
+    int found_wrong_kvno = 0;
+
+    /* Open the srvtab. */
+    if ((kerror = krb5_ktsrvint_open(context, id)))
+	return(kerror);
+
+    /* srvtab files only have DES_CBC_CRC keys. */
+    switch (enctype) {
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_RAW:
+    case IGNORE_ENCTYPE:
+	break;
+    default:
+	return KRB5_KT_NOTFOUND;
+    }
+
+    best_entry.principal = 0;
+    best_entry.vno = 0;
+    best_entry.key.contents = 0;
+    while ((kerror = krb5_ktsrvint_read_entry(context, id, &ent)) == 0) {
+	ent.key.enctype = enctype;
+	if (krb5_principal_compare(context, principal, ent.principal)) {
+	    if (kvno == IGNORE_VNO) {
+		if (!best_entry.principal || (best_entry.vno < ent.vno)) {
+		    krb5_kt_free_entry(context, &best_entry);
+		    best_entry = ent;
+		}
+	    } else {
+		if (ent.vno == kvno) {
+		    best_entry = ent;
+		    break;
+		} else {
+		    found_wrong_kvno = 1;
+		}
+	    }
+	} else {
+	    krb5_kt_free_entry(context, &ent);
+	}
+    }
+    if (kerror == KRB5_KT_END) {
+	 if (best_entry.principal)
+	      kerror = 0;
+	 else if (found_wrong_kvno)
+	      kerror = KRB5_KT_KVNONOTFOUND;
+	 else
+	      kerror = KRB5_KT_NOTFOUND;
+    }
+    if (kerror) {
+	(void) krb5_ktsrvint_close(context, id);
+	krb5_kt_free_entry(context, &best_entry);
+	return kerror;
+    }
+    if ((kerror = krb5_ktsrvint_close(context, id)) != 0) {
+	krb5_kt_free_entry(context, &best_entry);
+	return kerror;
+    }
+    *entry = best_entry;
+    return 0;
+}
+
+/*
+ * Get the name of the file containing a srvtab-based keytab.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktsrvtab_get_name(krb5_context context, krb5_keytab id, char *name, unsigned int len)
+  /* 
+   * This routine returns the name of the name of the file associated with
+   * this srvtab-based keytab.  The name is prefixed with PREFIX:, so that
+   * trt will happen if the name is passed back to resolve.
+   */
+{
+    memset(name, 0, len);
+
+    if (len < strlen(id->ops->prefix)+2)
+	return(KRB5_KT_NAME_TOOLONG);
+    strcpy(name, id->ops->prefix);
+    name += strlen(id->ops->prefix);
+    name[0] = ':';
+    name++;
+    len -= strlen(id->ops->prefix)+1;
+
+    if (len < strlen(KTFILENAME(id)+1))
+	return(KRB5_KT_NAME_TOOLONG);
+    strcpy(name, KTFILENAME(id));
+    /* strcpy will NUL-terminate the destination */
+
+    return(0);
+}
+
+/*
+ * krb5_ktsrvtab_start_seq_get()
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktsrvtab_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursorp)
+{
+    krb5_error_code retval;
+    long *fileoff;
+
+    if ((retval = krb5_ktsrvint_open(context, id)))
+	return retval;
+
+    if (!(fileoff = (long *)malloc(sizeof(*fileoff)))) {
+	krb5_ktsrvint_close(context, id);
+	return ENOMEM;
+    }
+    *fileoff = ftell(KTFILEP(id));
+    *cursorp = (krb5_kt_cursor)fileoff;
+
+    return 0;
+}
+
+/*
+ * krb5_ktsrvtab_get_next()
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktsrvtab_get_next(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor)
+{
+    long *fileoff = (long *)*cursor;
+    krb5_keytab_entry cur_entry;
+    krb5_error_code kerror;
+
+    if (fseek(KTFILEP(id), *fileoff, 0) == -1)
+	return KRB5_KT_END;
+    if ((kerror = krb5_ktsrvint_read_entry(context, id, &cur_entry)))
+	return kerror;
+    *fileoff = ftell(KTFILEP(id));
+    *entry = cur_entry;
+    return 0;
+}
+
+/*
+ * krb5_ktsrvtab_end_get()
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_ktsrvtab_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor)
+{
+    krb5_xfree(*cursor);
+    return krb5_ktsrvint_close(context, id);
+}
+
+/*
+ * krb5_kts_ops
+ */
+
+const struct _krb5_kt_ops krb5_kts_ops = {
+    0,
+    "SRVTAB", 	/* Prefix -- this string should not appear anywhere else! */
+    krb5_ktsrvtab_resolve,
+    krb5_ktsrvtab_get_name, 
+    krb5_ktsrvtab_close,
+    krb5_ktsrvtab_get_entry,
+    krb5_ktsrvtab_start_seq_get,
+    krb5_ktsrvtab_get_next,
+    krb5_ktsrvtab_end_get,
+    0,
+    0,
+    0
+};
+
+/*
+ * formerly: lib/krb5/keytab/srvtab/kts_util.c
+ *
+ * Copyright (c) Hewlett-Packard Company 1991
+ * Released to the Massachusetts Institute of Technology for inclusion
+ * in the Kerberos source code distribution.
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This function contains utilities for the srvtab based implementation
+ * of the keytab.  There are no public functions in this file.
+ */
+
+#include <stdio.h>
+
+#ifdef ANSI_STDIO
+#define		READ_MODE	"rb"
+#else
+#define		READ_MODE	"r"
+#endif
+
+/* The maximum sizes for V4 aname, realm, sname, and instance +1 */
+/* Taken from krb.h */
+#define 	ANAME_SZ	40
+#define		REALM_SZ	40
+#define		SNAME_SZ	40
+#define		INST_SZ		40
+
+static krb5_error_code
+read_field(FILE *fp, char *s, int len)
+{
+    int c;
+
+    while ((c = getc(fp)) != 0) {
+	if (c == EOF || len <= 1)
+	    return KRB5_KT_END;
+	*s = c;
+	s++;
+	len--;
+    }
+    *s = 0;
+    return 0;
+}
+
+krb5_error_code
+krb5_ktsrvint_open(krb5_context context, krb5_keytab id)
+{
+    KTFILEP(id) = fopen(KTFILENAME(id), READ_MODE);
+    if (!KTFILEP(id))
+	return errno;
+    return 0;
+}
+
+krb5_error_code
+krb5_ktsrvint_close(krb5_context context, krb5_keytab id)
+{
+    if (!KTFILEP(id))
+	return 0;
+    (void) fclose(KTFILEP(id));
+    KTFILEP(id) = 0;
+    return 0;
+}
+
+krb5_error_code
+krb5_ktsrvint_read_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *ret_entry)
+{
+    FILE *fp;
+    char name[SNAME_SZ], instance[INST_SZ], realm[REALM_SZ];
+    unsigned char key[8];
+    int vno;
+    krb5_error_code kerror;
+
+    /* Read in an entry from the srvtab file. */
+    fp = KTFILEP(id);
+    kerror = read_field(fp, name, sizeof(name));
+    if (kerror != 0)
+	return kerror;
+    kerror = read_field(fp, instance, sizeof(instance));
+    if (kerror != 0)
+	return kerror;
+    kerror = read_field(fp, realm, sizeof(realm));
+    if (kerror != 0)
+	return kerror;
+    vno = getc(fp);
+    if (vno == EOF)
+	return KRB5_KT_END;
+    if (fread(key, 1, sizeof(key), fp) != sizeof(key))
+	return KRB5_KT_END;
+
+    /* Fill in ret_entry with the data we read.  Everything maps well
+     * except for the timestamp, which we don't have a value for.  For
+     * now we just set it to 0. */
+    memset(ret_entry, 0, sizeof(*ret_entry));
+    ret_entry->magic = KV5M_KEYTAB_ENTRY;
+    kerror = krb5_425_conv_principal(context, name, instance, realm,
+				     &ret_entry->principal);
+    if (kerror != 0)
+	return kerror;
+    ret_entry->vno = vno;
+    ret_entry->timestamp = 0;
+    ret_entry->key.enctype = ENCTYPE_DES_CBC_CRC;
+    ret_entry->key.magic = KV5M_KEYBLOCK;
+    ret_entry->key.length = sizeof(key);
+    ret_entry->key.contents = malloc(sizeof(key));
+    if (!ret_entry->key.contents) {
+	krb5_free_principal(context, ret_entry->principal);
+	return ENOMEM;
+    }
+    memcpy(ret_entry->key.contents, key, sizeof(key));
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/keytab/ktadd.c b/krb5-1-6/src/lib/krb5/keytab/ktadd.c
new file mode 100644
index 000000000..b7c1b9216
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/ktadd.c
@@ -0,0 +1,39 @@
+/*
+ * lib/krb5/keytab/ktadd.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_kt_add_entry()
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_add_entry (krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
+{
+    if (id->ops->add)
+	return (*id->ops->add)(context, id, entry);
+    else
+	return KRB5_KT_NOWRITE;
+}
diff --git a/krb5-1-6/src/lib/krb5/keytab/ktbase.c b/krb5-1-6/src/lib/krb5/keytab/ktbase.c
new file mode 100644
index 000000000..79c9151ef
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/ktbase.c
@@ -0,0 +1,244 @@
+/*
+ * lib/krb5/keytab/ktbase.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Registration functions for keytab.
+ */
+
+#include "k5-int.h"
+#include "k5-thread.h"
+#include "kt-int.h"
+
+extern const krb5_kt_ops krb5_ktf_ops;
+extern const krb5_kt_ops krb5_ktf_writable_ops;
+extern const krb5_kt_ops krb5_kts_ops;
+
+struct krb5_kt_typelist {
+    const krb5_kt_ops *ops;
+    const struct krb5_kt_typelist *next;
+};
+const static struct krb5_kt_typelist krb5_kt_typelist_wrfile  = {
+    &krb5_ktf_writable_ops,
+    0
+};
+const static struct krb5_kt_typelist krb5_kt_typelist_file  = {
+    &krb5_ktf_ops,
+    &krb5_kt_typelist_wrfile
+};
+const static struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
+    &krb5_kts_ops,
+    &krb5_kt_typelist_file
+};
+static const struct krb5_kt_typelist *kt_typehead = &krb5_kt_typelist_srvtab;
+/* Lock for protecting the type list.  */
+static k5_mutex_t kt_typehead_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+int krb5int_kt_initialize(void)
+{
+    return k5_mutex_finish_init(&kt_typehead_lock);
+}
+
+void
+krb5int_kt_finalize(void)
+{
+    struct krb5_kt_typelist *t, *t_next;
+    k5_mutex_destroy(&kt_typehead_lock);
+    for (t = kt_typehead; t != &krb5_kt_typelist_srvtab; t = t_next) {
+	t_next = t->next;
+	free(t);
+    }
+}
+
+
+/*
+ * Register a new key table type
+ * don't replace if it already exists; return an error instead.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_register(krb5_context context, const krb5_kt_ops *ops)
+{
+    const struct krb5_kt_typelist *t;
+    struct krb5_kt_typelist *newt;
+    krb5_error_code err;
+
+    err = k5_mutex_lock(&kt_typehead_lock);
+    if (err)
+	return err;
+    for (t = kt_typehead; t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
+	;
+    if (t) {
+	k5_mutex_unlock(&kt_typehead_lock);
+	return KRB5_KT_TYPE_EXISTS;
+    }
+    if (!(newt = (struct krb5_kt_typelist *) malloc(sizeof(*t)))) {
+	k5_mutex_unlock(&kt_typehead_lock);
+	return ENOMEM;
+    }
+    newt->next = kt_typehead;
+    newt->ops = ops;
+    kt_typehead = newt;
+    k5_mutex_unlock(&kt_typehead_lock);
+    return 0;
+}
+
+/*
+ * Resolve a key table name into a keytab object.
+ *
+ * The name is currently constrained to be of the form "type:residual";
+ *
+ * The "type" portion corresponds to one of the registered key table
+ * types, while the "residual" portion is specific to the
+ * particular keytab type.
+ */
+
+#include <ctype.h>
+krb5_error_code KRB5_CALLCONV
+krb5_kt_resolve (krb5_context context, const char *name, krb5_keytab *ktid)
+{
+    const struct krb5_kt_typelist *tlist;
+    char *pfx;
+    unsigned int pfxlen;
+    const char *cp, *resid;
+    krb5_error_code err;
+    
+    cp = strchr (name, ':');
+    if (!cp) {
+	    return (*krb5_kt_dfl_ops.resolve)(context, name, ktid);
+    }
+
+    pfxlen = cp - name;
+
+    if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
+        /* We found a drive letter not a prefix - use FILE */
+        pfx = strdup("FILE");
+        if (!pfx)
+            return ENOMEM;
+
+        resid = name;
+    } else {
+        resid = name + pfxlen + 1;
+	
+        pfx = malloc (pfxlen+1);
+        if (!pfx)
+            return ENOMEM;
+
+        memcpy (pfx, name, pfxlen);
+        pfx[pfxlen] = '\0';
+    }
+
+    *ktid = (krb5_keytab) 0;
+
+    err = k5_mutex_lock(&kt_typehead_lock);
+    if (err)
+	return err;
+    tlist = kt_typehead;
+    /* Don't need to hold the lock, since entries are never modified
+       or removed once they're in the list.  Just need to protect
+       access to the list head variable itself.  */
+    k5_mutex_unlock(&kt_typehead_lock);
+    for (; tlist; tlist = tlist->next) {
+	if (strcmp (tlist->ops->prefix, pfx) == 0) {
+	    free(pfx);
+	    return (*tlist->ops->resolve)(context, resid, ktid);
+	}
+    }
+    free(pfx);
+    return KRB5_KT_UNKNOWN_TYPE;
+}
+
+/*
+ * Routines to deal with externalizingt krb5_keytab.
+ *	krb5_keytab_size();
+ *	krb5_keytab_externalize();
+ *	krb5_keytab_internalize();
+ */
+static krb5_error_code krb5_keytab_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_keytab_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_keytab_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/*
+ * Serialization entry for this type.
+ */
+static const krb5_ser_entry krb5_keytab_ser_entry = {
+    KV5M_KEYTAB,			/* Type			*/
+    krb5_keytab_size,			/* Sizer routine	*/
+    krb5_keytab_externalize,		/* Externalize routine	*/
+    krb5_keytab_internalize		/* Internalize routine	*/
+};
+
+static krb5_error_code
+krb5_keytab_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_keytab		keytab;
+    krb5_ser_handle	shandle;
+
+    kret = EINVAL;
+    if ((keytab = (krb5_keytab) arg) &&
+	keytab->ops &&
+	(shandle = (krb5_ser_handle) keytab->ops->serializer) &&
+	shandle->sizer)
+	kret = (*shandle->sizer)(kcontext, arg, sizep);
+    return(kret);
+}
+
+static krb5_error_code
+krb5_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_keytab		keytab;
+    krb5_ser_handle	shandle;
+
+    kret = EINVAL;
+    if ((keytab = (krb5_keytab) arg) &&
+	keytab->ops &&
+	(shandle = (krb5_ser_handle) keytab->ops->serializer) &&
+	shandle->externalizer)
+	kret = (*shandle->externalizer)(kcontext, arg, buffer, lenremain);
+    return(kret);
+}
+
+static krb5_error_code
+krb5_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_ser_handle	shandle;
+
+    kret = EINVAL;
+    if ((shandle = (krb5_ser_handle) krb5_kt_dfl_ops.serializer) &&
+	shandle->internalizer)
+	kret = (*shandle->internalizer)(kcontext, argp, buffer, lenremain);
+    return(kret);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_ser_keytab_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_keytab_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/keytab/ktdefault.c b/krb5-1-6/src/lib/krb5/keytab/ktdefault.c
new file mode 100644
index 000000000..971f29f59
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/ktdefault.c
@@ -0,0 +1,45 @@
+/*
+ * lib/krb5/keytab/ktdefault.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Get a default keytab.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_default(krb5_context context, krb5_keytab *id)
+{
+    char defname[BUFSIZ];
+    krb5_error_code retval;
+
+    if ((retval = krb5_kt_default_name(context, defname, sizeof(defname))))
+	return retval;
+    return krb5_kt_resolve(context, defname, id);
+}
+
+
+
diff --git a/krb5-1-6/src/lib/krb5/keytab/ktfns.c b/krb5-1-6/src/lib/krb5/keytab/ktfns.c
new file mode 100644
index 000000000..63fa6399b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/ktfns.c
@@ -0,0 +1,96 @@
+/*
+ * lib/krb5/keytab/ktfns.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Dispatch methods for keytab code.
+ */
+
+#include "k5-int.h"
+
+char * KRB5_CALLCONV
+krb5_kt_get_type (krb5_context context, krb5_keytab keytab)
+{
+    return keytab->ops->prefix;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_get_name(krb5_context context, krb5_keytab keytab, char *name,
+		 unsigned int namelen)
+{
+    return krb5_x((keytab)->ops->get_name,(context, keytab,name,namelen));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_close(krb5_context context, krb5_keytab keytab)
+{
+    return krb5_x((keytab)->ops->close,(context, keytab));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_get_entry(krb5_context context, krb5_keytab keytab,
+		  krb5_const_principal principal, krb5_kvno vno,
+		  krb5_enctype enctype, krb5_keytab_entry *entry)
+{
+    krb5_error_code err;
+    krb5_principal_data princ_data;
+
+    if (krb5_is_referral_realm(&principal->realm)) {
+	char *realm;
+	princ_data = *principal;
+	principal = &princ_data;
+	err = krb5_get_default_realm(context, &realm);
+	if (err)
+	    return err;
+	princ_data.realm.data = realm;
+	princ_data.realm.length = strlen(realm);
+    }
+    err = krb5_x((keytab)->ops->get,(context, keytab, principal, vno, enctype,
+				     entry));
+    if (principal == &princ_data)
+	krb5_free_default_realm(context, princ_data.realm.data);
+    return err;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_start_seq_get(krb5_context context, krb5_keytab keytab,
+		      krb5_kt_cursor *cursor)
+{
+    return krb5_x((keytab)->ops->start_seq_get,(context, keytab, cursor));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_next_entry(krb5_context context, krb5_keytab keytab,
+		   krb5_keytab_entry *entry, krb5_kt_cursor *cursor)
+{
+    return krb5_x((keytab)->ops->get_next,(context, keytab, entry, cursor));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab,
+		    krb5_kt_cursor *cursor)
+{
+    return krb5_x((keytab)->ops->end_get,(context, keytab, cursor));
+}
diff --git a/krb5-1-6/src/lib/krb5/keytab/ktfr_entry.c b/krb5-1-6/src/lib/krb5/keytab/ktfr_entry.c
new file mode 100644
index 000000000..a86b38bc2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/ktfr_entry.c
@@ -0,0 +1,50 @@
+/*
+ * lib/krb5/keytab/ktfr_entry.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_kt_free_entry()
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_free_keytab_entry_contents (krb5_context context, krb5_keytab_entry *entry)
+{
+    if (!entry)
+	return 0;
+    
+    krb5_free_principal(context, entry->principal);
+    if (entry->key.contents) {
+	memset((char *)entry->key.contents, 0, entry->key.length);
+	krb5_xfree(entry->key.contents);
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_free_entry (krb5_context context, krb5_keytab_entry *entry)
+{
+    return krb5_free_keytab_entry_contents (context, entry);
+}
diff --git a/krb5-1-6/src/lib/krb5/keytab/ktremove.c b/krb5-1-6/src/lib/krb5/keytab/ktremove.c
new file mode 100644
index 000000000..d101a7065
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/ktremove.c
@@ -0,0 +1,39 @@
+/*
+ * lib/krb5/keytab/ktremove.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_kt_remove_entry()
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_remove_entry (krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
+{
+    if (id->ops->remove)
+	return (*id->ops->remove)(context, id, entry);
+    else
+	return KRB5_KT_NOWRITE;
+}
diff --git a/krb5-1-6/src/lib/krb5/keytab/read_servi.c b/krb5-1-6/src/lib/krb5/keytab/read_servi.c
new file mode 100644
index 000000000..3455300ab
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/keytab/read_servi.c
@@ -0,0 +1,81 @@
+/*
+ * lib/krb5/keytab/read_servi.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This routine is designed to be passed to krb5_rd_req.  
+ * It is a convenience function that reads a key out of a keytab.
+ * It handles all of the opening and closing of the keytab 
+ * internally. 
+ */
+
+#include "k5-int.h"
+
+#define KSUCCESS 0
+
+/*
+ * effects: If keyprocarg is not NULL, it is taken to be the name of a 
+ *	keytab.  Otherwise, the default keytab will be used.  This 
+ *	routine opens the keytab and finds the principal associated with
+ *	principal, vno, and enctype and returns the resulting key in *key 
+ *	or returning an error code if it is not	found. 
+ * returns: Either KSUCCESS or error code.
+ * errors: error code if not found or keyprocarg is invalid.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key)
+{
+    krb5_error_code kerror = KSUCCESS;
+    char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */
+    krb5_keytab id;
+    krb5_keytab_entry entry;
+        
+    /*
+     * Get the name of the file that we should use. 
+     */
+    if (!keyprocarg) {
+	if ((kerror = krb5_kt_default_name(context, (char *)keytabname, 
+					   sizeof(keytabname) - 1))!= KSUCCESS)
+	    return (kerror);
+    } else {
+	memset(keytabname, 0, sizeof(keytabname));
+	(void) strncpy(keytabname, (char *)keyprocarg, 
+		       sizeof(keytabname) - 1);
+    }
+
+    if ((kerror = krb5_kt_resolve(context, (char *)keytabname, &id)))
+	return (kerror);
+
+    kerror = krb5_kt_get_entry(context, id, principal, vno, enctype, &entry);
+    krb5_kt_close(context, id);
+
+    if (kerror)
+	return(kerror);
+
+    krb5_copy_keyblock(context, &entry.key, key);
+
+    krb5_kt_free_entry(context, &entry);
+
+    return (KSUCCESS);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/Makefile.in b/krb5-1-6/src/lib/krb5/krb/Makefile.in
new file mode 100644
index 000000000..f797af96e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/Makefile.in
@@ -0,0 +1,1193 @@
+thisconfigdir=../../..
+myfulldir=lib/krb5/krb
+mydir=lib/krb5/krb
+BUILDTOP=$(REL)..$(S)..$(S)..
+RUN_SETUP = @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+LOCALINCLUDES = -I$(srcdir)/../os -I$(SRCTOP)
+DEFS=-DLIBDIR=\"$(KRB5_LIBDIR)\"
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=krb
+##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst
+
+STLIBOBJS= \
+	addr_comp.o	\
+	addr_order.o	\
+	addr_srch.o	\
+	appdefault.o	\
+	auth_con.o	\
+	bld_pr_ext.o	\
+	bld_princ.o	\
+	chk_trans.o	\
+	chpw.o		\
+	conv_creds.o	\
+	conv_princ.o	\
+	copy_addrs.o	\
+	copy_auth.o	\
+	copy_athctr.o	\
+	copy_cksum.o    \
+	copy_creds.o	\
+	copy_data.o	\
+	copy_key.o	\
+	copy_princ.o	\
+	copy_tick.o	\
+	cp_key_cnt.o	\
+	decode_kdc.o	\
+	decrypt_tk.o	\
+	deltat.o	\
+        enc_helper.o	\
+	encode_kdc.o	\
+	encrypt_tk.o	\
+	free_rtree.o	\
+	fwd_tgt.o	\
+	gc_frm_kdc.o	\
+	gc_via_tkt.o	\
+	gen_seqnum.o	\
+	gen_subkey.o	\
+	get_creds.o	\
+	get_in_tkt.o	\
+	gic_keytab.o	\
+	gic_opt.o	\
+	gic_pwd.o	\
+	in_tkt_sky.o	\
+	init_ctx.o	\
+	init_keyblock.o \
+	kdc_rep_dc.o	\
+	kerrs.o		\
+	kfree.o		\
+	mk_cred.o	\
+	mk_error.o	\
+	mk_priv.o	\
+	mk_rep.o	\
+	mk_req.o	\
+	mk_req_ext.o	\
+	mk_safe.o	\
+	parse.o		\
+	pr_to_salt.o	\
+	preauth.o	\
+	preauth2.o	\
+	princ_comp.o	\
+	rd_cred.o	\
+	rd_error.o	\
+	rd_priv.o	\
+	rd_rep.o	\
+	rd_req.o	\
+	rd_req_dec.o	\
+	rd_safe.o	\
+	recvauth.o	\
+	sendauth.o	\
+	send_tgs.o	\
+	ser_actx.o	\
+	ser_adata.o	\
+	ser_addr.o	\
+	ser_auth.o	\
+	ser_cksum.o	\
+	ser_ctx.o	\
+	ser_key.o	\
+	ser_princ.o	\
+	serialize.o	\
+	set_realm.o	\
+	srv_dec_tkt.o	\
+	srv_rcache.o	\
+	str_conv.o	\
+	tgtname.o	\
+	unparse.o	\
+	v4lifetime.o	\
+	valid_times.o	\
+	vfy_increds.o	\
+	vic_opt.o	\
+	walk_rtree.o
+
+OBJS=	$(OUTPRE)addr_comp.$(OBJEXT)	\
+	$(OUTPRE)addr_order.$(OBJEXT)	\
+	$(OUTPRE)addr_srch.$(OBJEXT)	\
+	$(OUTPRE)appdefault.$(OBJEXT)	\
+	$(OUTPRE)auth_con.$(OBJEXT)	\
+	$(OUTPRE)bld_pr_ext.$(OBJEXT)	\
+	$(OUTPRE)bld_princ.$(OBJEXT)	\
+	$(OUTPRE)chk_trans.$(OBJEXT)	\
+	$(OUTPRE)chpw.$(OBJEXT)		\
+	$(OUTPRE)conv_creds.$(OBJEXT)	\
+	$(OUTPRE)conv_princ.$(OBJEXT)	\
+	$(OUTPRE)copy_addrs.$(OBJEXT)	\
+	$(OUTPRE)copy_auth.$(OBJEXT)	\
+	$(OUTPRE)copy_athctr.$(OBJEXT)	\
+	$(OUTPRE)copy_cksum.$(OBJEXT)    \
+	$(OUTPRE)copy_creds.$(OBJEXT)	\
+	$(OUTPRE)copy_data.$(OBJEXT)	\
+	$(OUTPRE)copy_key.$(OBJEXT)	\
+	$(OUTPRE)copy_princ.$(OBJEXT)	\
+	$(OUTPRE)copy_tick.$(OBJEXT)	\
+	$(OUTPRE)cp_key_cnt.$(OBJEXT)	\
+	$(OUTPRE)decode_kdc.$(OBJEXT)	\
+	$(OUTPRE)decrypt_tk.$(OBJEXT)	\
+	$(OUTPRE)deltat.$(OBJEXT)	\
+        $(OUTPRE)enc_helper.$(OBJEXT)	\
+	$(OUTPRE)encode_kdc.$(OBJEXT)	\
+	$(OUTPRE)encrypt_tk.$(OBJEXT)	\
+	$(OUTPRE)free_rtree.$(OBJEXT)	\
+	$(OUTPRE)fwd_tgt.$(OBJEXT)	\
+	$(OUTPRE)gc_frm_kdc.$(OBJEXT)	\
+	$(OUTPRE)gc_via_tkt.$(OBJEXT)	\
+	$(OUTPRE)gen_seqnum.$(OBJEXT)	\
+	$(OUTPRE)gen_subkey.$(OBJEXT)	\
+	$(OUTPRE)get_creds.$(OBJEXT)	\
+	$(OUTPRE)get_in_tkt.$(OBJEXT)	\
+	$(OUTPRE)gic_keytab.$(OBJEXT)	\
+	$(OUTPRE)gic_opt.$(OBJEXT)	\
+	$(OUTPRE)gic_pwd.$(OBJEXT)	\
+	$(OUTPRE)in_tkt_sky.$(OBJEXT)	\
+	$(OUTPRE)init_ctx.$(OBJEXT)	\
+	$(OUTPRE)init_keyblock.$(OBJEXT) \
+	$(OUTPRE)kdc_rep_dc.$(OBJEXT)	\
+	$(OUTPRE)kerrs.$(OBJEXT)		\
+	$(OUTPRE)kfree.$(OBJEXT)	\
+	$(OUTPRE)mk_cred.$(OBJEXT)	\
+	$(OUTPRE)mk_error.$(OBJEXT)	\
+	$(OUTPRE)mk_priv.$(OBJEXT)	\
+	$(OUTPRE)mk_rep.$(OBJEXT)	\
+	$(OUTPRE)mk_req.$(OBJEXT)	\
+	$(OUTPRE)mk_req_ext.$(OBJEXT)	\
+	$(OUTPRE)mk_safe.$(OBJEXT)	\
+	$(OUTPRE)parse.$(OBJEXT)		\
+	$(OUTPRE)pr_to_salt.$(OBJEXT)	\
+	$(OUTPRE)preauth.$(OBJEXT)	\
+	$(OUTPRE)preauth2.$(OBJEXT)	\
+	$(OUTPRE)princ_comp.$(OBJEXT)	\
+	$(OUTPRE)rd_cred.$(OBJEXT)	\
+	$(OUTPRE)rd_error.$(OBJEXT)	\
+	$(OUTPRE)rd_priv.$(OBJEXT)	\
+	$(OUTPRE)rd_rep.$(OBJEXT)	\
+	$(OUTPRE)rd_req.$(OBJEXT)	\
+	$(OUTPRE)rd_req_dec.$(OBJEXT)	\
+	$(OUTPRE)rd_safe.$(OBJEXT)	\
+	$(OUTPRE)recvauth.$(OBJEXT)	\
+	$(OUTPRE)sendauth.$(OBJEXT)	\
+	$(OUTPRE)send_tgs.$(OBJEXT)	\
+	$(OUTPRE)ser_actx.$(OBJEXT)	\
+	$(OUTPRE)ser_adata.$(OBJEXT)	\
+	$(OUTPRE)ser_addr.$(OBJEXT)	\
+	$(OUTPRE)ser_auth.$(OBJEXT)	\
+	$(OUTPRE)ser_cksum.$(OBJEXT)	\
+	$(OUTPRE)ser_ctx.$(OBJEXT)	\
+	$(OUTPRE)ser_key.$(OBJEXT)	\
+	$(OUTPRE)ser_princ.$(OBJEXT)	\
+	$(OUTPRE)serialize.$(OBJEXT)	\
+	$(OUTPRE)set_realm.$(OBJEXT)	\
+	$(OUTPRE)srv_dec_tkt.$(OBJEXT)	\
+	$(OUTPRE)srv_rcache.$(OBJEXT)	\
+	$(OUTPRE)str_conv.$(OBJEXT)	\
+	$(OUTPRE)tgtname.$(OBJEXT)	\
+	$(OUTPRE)unparse.$(OBJEXT)	\
+	$(OUTPRE)v4lifetime.$(OBJEXT)	\
+	$(OUTPRE)valid_times.$(OBJEXT)	\
+	$(OUTPRE)vfy_increds.$(OBJEXT)	\
+	$(OUTPRE)vic_opt.$(OBJEXT)	\
+	$(OUTPRE)walk_rtree.$(OBJEXT)
+
+SRCS=	$(srcdir)/addr_comp.c	\
+	$(srcdir)/addr_order.c	\
+	$(srcdir)/addr_srch.c	\
+	$(srcdir)/appdefault.c	\
+	$(srcdir)/auth_con.c	\
+	$(srcdir)/bld_pr_ext.c	\
+	$(srcdir)/bld_princ.c	\
+	$(srcdir)/brand.c	\
+	$(srcdir)/chk_trans.c	\
+	$(srcdir)/chpw.c	\
+	$(srcdir)/conv_creds.c	\
+	$(srcdir)/conv_princ.c	\
+	$(srcdir)/copy_addrs.c	\
+	$(srcdir)/copy_auth.c	\
+	$(srcdir)/copy_athctr.c	\
+	$(srcdir)/copy_cksum.c   \
+	$(srcdir)/copy_creds.c	\
+	$(srcdir)/copy_data.c	\
+	$(srcdir)/copy_key.c	\
+	$(srcdir)/copy_princ.c	\
+	$(srcdir)/copy_tick.c	\
+	$(srcdir)/cp_key_cnt.c	\
+	$(srcdir)/decode_kdc.c	\
+	$(srcdir)/decrypt_tk.c	\
+	$(srcdir)/deltat.c	\
+	$(srcdir)/enc_helper.c	\
+	$(srcdir)/encode_kdc.c	\
+	$(srcdir)/encrypt_tk.c	\
+	$(srcdir)/free_rtree.c	\
+	$(srcdir)/fwd_tgt.c	\
+	$(srcdir)/gc_frm_kdc.c	\
+	$(srcdir)/gc_via_tkt.c	\
+	$(srcdir)/gen_seqnum.c	\
+	$(srcdir)/gen_subkey.c	\
+	$(srcdir)/get_creds.c	\
+	$(srcdir)/get_in_tkt.c	\
+	$(srcdir)/gic_keytab.c	\
+	$(srcdir)/gic_opt.c	\
+	$(srcdir)/gic_pwd.c	\
+	$(srcdir)/in_tkt_sky.c	\
+	$(srcdir)/init_ctx.c	\
+	$(srcdir)/init_keyblock.c \
+	$(srcdir)/kdc_rep_dc.c	\
+	$(srcdir)/kerrs.c	\
+	$(srcdir)/kfree.c	\
+	$(srcdir)/mk_cred.c	\
+	$(srcdir)/mk_error.c	\
+	$(srcdir)/mk_priv.c	\
+	$(srcdir)/mk_rep.c	\
+	$(srcdir)/mk_req.c	\
+	$(srcdir)/mk_req_ext.c	\
+	$(srcdir)/mk_safe.c	\
+	$(srcdir)/parse.c	\
+	$(srcdir)/pr_to_salt.c	\
+	$(srcdir)/preauth.c	\
+	$(srcdir)/preauth2.c	\
+	$(srcdir)/princ_comp.c	\
+	$(srcdir)/rd_cred.c	\
+	$(srcdir)/rd_error.c	\
+	$(srcdir)/rd_priv.c	\
+	$(srcdir)/rd_rep.c	\
+	$(srcdir)/rd_req.c	\
+	$(srcdir)/rd_req_dec.c	\
+	$(srcdir)/rd_safe.c	\
+	$(srcdir)/recvauth.c	\
+	$(srcdir)/sendauth.c	\
+	$(srcdir)/send_tgs.c	\
+	$(srcdir)/ser_actx.c	\
+	$(srcdir)/ser_adata.c	\
+	$(srcdir)/ser_addr.c	\
+	$(srcdir)/ser_auth.c	\
+	$(srcdir)/ser_cksum.c	\
+	$(srcdir)/ser_ctx.c	\
+	$(srcdir)/ser_key.c	\
+	$(srcdir)/ser_princ.c	\
+	$(srcdir)/serialize.c	\
+	$(srcdir)/set_realm.c	\
+	$(srcdir)/srv_dec_tkt.c	\
+	$(srcdir)/srv_rcache.c	\
+	$(srcdir)/str_conv.c	\
+	$(srcdir)/tgtname.c	\
+	$(srcdir)/unparse.c	\
+	$(srcdir)/v4lifetime.c	\
+	$(srcdir)/valid_times.c	\
+	$(srcdir)/vfy_increds.c \
+	$(srcdir)/vic_opt.c	\
+	$(srcdir)/walk_rtree.c	\
+	$(srcdir)/t_walk_rtree.c \
+	$(srcdir)/t_kerb.c	\
+	$(srcdir)/t_ser.c	\
+	$(srcdir)/t_deltat.c	\
+	$(srcdir)/t_expand.c
+
+# Someday, when we have a "maintainer mode", do this right:
+BISON=bison
+BISONFLAGS= # -v -> .output; -d -> .h
+DELTAT_DEP=@MAINT@ x-deltat.y
+##WIN32##DELTAT_DEP=
+
+$(srcdir)/deltat.c : $(DELTAT_DEP)
+	(cd $(srcdir) && $(BISON) $(BISONFLAGS) -o deltat.c x-deltat.y)
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+
+COMERRLIB=$(TOPLIBD)/libcom_err.a
+
+T_WALK_RTREE_OBJS= t_walk_rtree.o walk_rtree.o tgtname.o unparse.o \
+	free_rtree.o bld_pr_ext.o 
+
+T_KERB_OBJS= t_kerb.o conv_princ.o unparse.o set_realm.o str_conv.o
+
+T_SER_OBJS= t_ser.o ser_actx.o ser_adata.o ser_addr.o ser_auth.o ser_cksum.o \
+	ser_ctx.o ser_key.o ser_princ.o serialize.o 
+
+T_DELTAT_OBJS= t_deltat.o deltat.o
+
+t_walk_rtree: $(T_WALK_RTREE_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_walk_rtree $(T_WALK_RTREE_OBJS) $(KRB5_BASE_LIBS)
+
+t_kerb: $(T_KERB_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_kerb $(T_KERB_OBJS) $(KRB5_BASE_LIBS)
+
+t_ser: $(T_SER_OBJS) $(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_ser $(T_SER_OBJS) \
+		$(KDB5_LIBS) $(KRB5_BASE_LIBS) $(DL_LIB) $(THREAD_LINKOPTS)
+
+t_deltat : $(T_DELTAT_OBJS) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o t_deltat $(T_DELTAT_OBJS) $(SUPPORT_LIB)
+
+T_EXPAND_OBJS=t_expand.o
+t_expand.o : t_expand.c
+t_expand : $(T_EXPAND_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_expand $(T_EXPAND_OBJS) $(KRB5_BASE_LIBS)
+
+TEST_PROGS= t_walk_rtree t_kerb t_ser t_deltat t_expand
+
+check-unix:: $(TEST_PROGS)
+	KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\
+	$(RUN_SETUP) $(VALGRIND) ./t_kerb \
+		parse_name tytso \
+		parse_name tytso@SHAZAAM \
+		parse_name tytso/root@VEGGIE.COM \
+		parse_name tytso/tuber/carrot@VEGGIE.COM \
+		parse_name tytso/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t \
+		parse_name tytso/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t@FOO \
+		parse_name tytso\\\\0/\\0@B\\n\\t\\\\GAG \
+		parse_name tytso/\\n/\\b\\t@B\\0hacky-test \
+		parse_name \\/slash/\\@atsign/octa\\/thorpe@\\/slash\\@at\\/sign \
+		425_conv_principal rcmd e40-po ATHENA.MIT.EDU \
+		425_conv_principal rcmd mit ATHENA.MIT.EDU \
+		425_conv_principal rcmd lithium ATHENA.MIT.EDU \
+		425_conv_principal rcmd tweedledumb CYGNUS.COM \
+		425_conv_principal rcmd uunet UU.NET \
+		425_conv_principal zephyr zephyr ATHENA.MIT.EDU \
+		425_conv_principal kadmin ATHENA.MIT.EDU ATHENA.MIT.EDU \
+		524_conv_principal host/e40-po.mit.edu@ATHENA.MIT.EDU \
+		524_conv_principal host/foobar.stanford.edu@stanford.edu \
+		set_realm marc@MIT.EDU CYGNUS.COM \
+		> test.out
+	cmp test.out $(srcdir)/t_ref_kerb.out
+	$(RM) test.out
+	KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\
+		$(RUN_SETUP) $(VALGRIND) ./t_ser
+	$(RUN_SETUP) $(VALGRIND) ./t_deltat
+	$(RUN_SETUP) $(VALGRIND) sh $(srcdir)/transit-tests
+
+clean::
+	$(RM) $(OUTPRE)t_walk_rtree$(EXEEXT) $(OUTPRE)t_walk_rtree.$(OBJEXT) \
+		$(OUTPRE)t_kerb$(EXEEXT) $(OUTPRE)t_kerb.$(OBJEXT)	\
+		$(OUTPRE)t_ser$(EXEEXT) $(OUTPRE)t_ser.$(OBJEXT)	\
+		$(OUTPRE)t_deltat$(EXEEXT) $(OUTPRE)t_deltat.$(OBJEXT) \
+		$(OUTPRE)t_expand$(EXEEXT) $(OUTPRE)t_expand.$(OBJEXT)
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+addr_comp.so addr_comp.po $(OUTPRE)addr_comp.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h addr_comp.c
+addr_order.so addr_order.po $(OUTPRE)addr_order.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h addr_order.c
+addr_srch.so addr_srch.po $(OUTPRE)addr_srch.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h addr_srch.c
+appdefault.so appdefault.po $(OUTPRE)appdefault.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h appdefault.c
+auth_con.so auth_con.po $(OUTPRE)auth_con.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h auth_con.c auth_con.h
+bld_pr_ext.so bld_pr_ext.po $(OUTPRE)bld_pr_ext.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h bld_pr_ext.c
+bld_princ.so bld_princ.po $(OUTPRE)bld_princ.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h bld_princ.c
+brand.so brand.po $(OUTPRE)brand.$(OBJEXT): $(SRCTOP)/patchlevel.h \
+  brand.c
+chk_trans.so chk_trans.po $(OUTPRE)chk_trans.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h chk_trans.c
+chpw.so chpw.po $(OUTPRE)chpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/krb5_err.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h auth_con.h chpw.c
+conv_creds.so conv_creds.po $(OUTPRE)conv_creds.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/kerberosIV/krb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h conv_creds.c
+conv_princ.so conv_princ.po $(OUTPRE)conv_princ.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h conv_princ.c
+copy_addrs.so copy_addrs.po $(OUTPRE)copy_addrs.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_addrs.c
+copy_auth.so copy_auth.po $(OUTPRE)copy_auth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_auth.c
+copy_athctr.so copy_athctr.po $(OUTPRE)copy_athctr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_athctr.c
+copy_cksum.so copy_cksum.po $(OUTPRE)copy_cksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_cksum.c
+copy_creds.so copy_creds.po $(OUTPRE)copy_creds.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_creds.c
+copy_data.so copy_data.po $(OUTPRE)copy_data.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_data.c
+copy_key.so copy_key.po $(OUTPRE)copy_key.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_key.c
+copy_princ.so copy_princ.po $(OUTPRE)copy_princ.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_princ.c
+copy_tick.so copy_tick.po $(OUTPRE)copy_tick.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h copy_tick.c
+cp_key_cnt.so cp_key_cnt.po $(OUTPRE)cp_key_cnt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cp_key_cnt.c
+decode_kdc.so decode_kdc.po $(OUTPRE)decode_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h decode_kdc.c
+decrypt_tk.so decrypt_tk.po $(OUTPRE)decrypt_tk.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h decrypt_tk.c
+deltat.so deltat.po $(OUTPRE)deltat.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  deltat.c
+enc_helper.so enc_helper.po $(OUTPRE)enc_helper.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h enc_helper.c
+encode_kdc.so encode_kdc.po $(OUTPRE)encode_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h encode_kdc.c
+encrypt_tk.so encrypt_tk.po $(OUTPRE)encrypt_tk.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h encrypt_tk.c
+free_rtree.so free_rtree.po $(OUTPRE)free_rtree.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h free_rtree.c
+fwd_tgt.so fwd_tgt.po $(OUTPRE)fwd_tgt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  fwd_tgt.c
+gc_frm_kdc.so gc_frm_kdc.po $(OUTPRE)gc_frm_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gc_frm_kdc.c int-proto.h
+gc_via_tkt.so gc_via_tkt.po $(OUTPRE)gc_via_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gc_via_tkt.c int-proto.h
+gen_seqnum.so gen_seqnum.po $(OUTPRE)gen_seqnum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gen_seqnum.c
+gen_subkey.so gen_subkey.po $(OUTPRE)gen_subkey.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gen_subkey.c
+get_creds.so get_creds.po $(OUTPRE)get_creds.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h get_creds.c
+get_in_tkt.so get_in_tkt.po $(OUTPRE)get_in_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(srcdir)/../os/os-proto.h \
+  get_in_tkt.c int-proto.h
+gic_keytab.so gic_keytab.po $(OUTPRE)gic_keytab.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gic_keytab.c
+gic_opt.so gic_opt.po $(OUTPRE)gic_opt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  gic_opt.c int-proto.h
+gic_pwd.so gic_pwd.po $(OUTPRE)gic_pwd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  gic_pwd.c
+in_tkt_sky.so in_tkt_sky.po $(OUTPRE)in_tkt_sky.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h in_tkt_sky.c
+init_ctx.so init_ctx.po $(OUTPRE)init_ctx.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/patchlevel.h \
+  $(srcdir)/../krb5_libinit.h brand.c init_ctx.c
+init_keyblock.so init_keyblock.po $(OUTPRE)init_keyblock.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h init_keyblock.c
+kdc_rep_dc.so kdc_rep_dc.po $(OUTPRE)kdc_rep_dc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdc_rep_dc.c
+kerrs.so kerrs.po $(OUTPRE)kerrs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  kerrs.c
+kfree.so kfree.po $(OUTPRE)kfree.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  kfree.c
+mk_cred.so mk_cred.po $(OUTPRE)mk_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h cleanup.h mk_cred.c
+mk_error.so mk_error.po $(OUTPRE)mk_error.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h mk_error.c
+mk_priv.so mk_priv.po $(OUTPRE)mk_priv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h cleanup.h mk_priv.c
+mk_rep.so mk_rep.po $(OUTPRE)mk_rep.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h mk_rep.c
+mk_req.so mk_req.po $(OUTPRE)mk_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h mk_req.c
+mk_req_ext.so mk_req_ext.po $(OUTPRE)mk_req_ext.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h auth_con.h mk_req_ext.c
+mk_safe.so mk_safe.po $(OUTPRE)mk_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h cleanup.h mk_safe.c
+parse.so parse.po $(OUTPRE)parse.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  parse.c
+pr_to_salt.so pr_to_salt.po $(OUTPRE)pr_to_salt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h pr_to_salt.c
+preauth.so preauth.po $(OUTPRE)preauth.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  preauth.c
+preauth2.so preauth2.po $(OUTPRE)preauth2.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h preauth2.c
+princ_comp.so princ_comp.po $(OUTPRE)princ_comp.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h princ_comp.c
+rd_cred.so rd_cred.po $(OUTPRE)rd_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h cleanup.h rd_cred.c
+rd_error.so rd_error.po $(OUTPRE)rd_error.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h rd_error.c
+rd_priv.so rd_priv.po $(OUTPRE)rd_priv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h cleanup.h rd_priv.c
+rd_rep.so rd_rep.po $(OUTPRE)rd_rep.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h rd_rep.c
+rd_req.so rd_req.po $(OUTPRE)rd_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h rd_req.c
+rd_req_dec.so rd_req_dec.po $(OUTPRE)rd_req_dec.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h auth_con.h rd_req_dec.c
+rd_safe.so rd_safe.po $(OUTPRE)rd_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h cleanup.h rd_safe.c
+recvauth.so recvauth.po $(OUTPRE)recvauth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h auth_con.h recvauth.c
+sendauth.so sendauth.po $(OUTPRE)sendauth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h auth_con.h sendauth.c
+send_tgs.so send_tgs.po $(OUTPRE)send_tgs.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h send_tgs.c
+ser_actx.so ser_actx.po $(OUTPRE)ser_actx.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h auth_con.h int-proto.h \
+  ser_actx.c
+ser_adata.so ser_adata.po $(OUTPRE)ser_adata.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h ser_adata.c
+ser_addr.so ser_addr.po $(OUTPRE)ser_addr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h ser_addr.c
+ser_auth.so ser_auth.po $(OUTPRE)ser_auth.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h ser_auth.c
+ser_cksum.so ser_cksum.po $(OUTPRE)ser_cksum.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h ser_cksum.c
+ser_ctx.so ser_ctx.po $(OUTPRE)ser_ctx.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ser_ctx.c
+ser_key.so ser_key.po $(OUTPRE)ser_key.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  int-proto.h ser_key.c
+ser_princ.so ser_princ.po $(OUTPRE)ser_princ.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h ser_princ.c
+serialize.so serialize.po $(OUTPRE)serialize.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h serialize.c
+set_realm.so set_realm.po $(OUTPRE)set_realm.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h set_realm.c
+srv_dec_tkt.so srv_dec_tkt.po $(OUTPRE)srv_dec_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h srv_dec_tkt.c
+srv_rcache.so srv_rcache.po $(OUTPRE)srv_rcache.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h srv_rcache.c
+str_conv.so str_conv.po $(OUTPRE)str_conv.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h str_conv.c
+tgtname.so tgtname.po $(OUTPRE)tgtname.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  int-proto.h tgtname.c
+unparse.so unparse.po $(OUTPRE)unparse.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  unparse.c
+v4lifetime.so v4lifetime.po $(OUTPRE)v4lifetime.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h v4lifetime.c
+valid_times.so valid_times.po $(OUTPRE)valid_times.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h valid_times.c
+vfy_increds.so vfy_increds.po $(OUTPRE)vfy_increds.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h vfy_increds.c
+vic_opt.so vic_opt.po $(OUTPRE)vic_opt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  vic_opt.c
+walk_rtree.so walk_rtree.po $(OUTPRE)walk_rtree.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h int-proto.h walk_rtree.c
+t_walk_rtree.so t_walk_rtree.po $(OUTPRE)t_walk_rtree.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h t_walk_rtree.c
+t_kerb.so t_kerb.po $(OUTPRE)t_kerb.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(KRB_ERR_H_DEP) $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/des.h \
+  $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/krb5.h \
+  t_kerb.c
+t_ser.so t_ser.po $(OUTPRE)t_ser.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  auth_con.h t_ser.c
+t_deltat.so t_deltat.po $(OUTPRE)t_deltat.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h t_deltat.c
+t_expand.so t_expand.po $(OUTPRE)t_expand.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h chk_trans.c t_expand.c
diff --git a/krb5-1-6/src/lib/krb5/krb/addr_comp.c b/krb5-1-6/src/lib/krb5/krb/addr_comp.c
new file mode 100644
index 000000000..16ab03bbf
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/addr_comp.c
@@ -0,0 +1,48 @@
+/*
+ * lib/krb5/krb/addr_comp.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_address_compare()
+ */
+
+#include "k5-int.h"
+
+/*
+ * If the two addresses are the same, return TRUE, else return FALSE
+ */
+krb5_boolean KRB5_CALLCONV
+krb5_address_compare(krb5_context context, const krb5_address *addr1, const krb5_address *addr2)
+{
+    if (addr1->addrtype != addr2->addrtype)
+	return(FALSE);
+
+    if (addr1->length != addr2->length)
+	return(FALSE);
+    if (memcmp((char *)addr1->contents, (char *)addr2->contents,
+	       addr1->length))
+	return FALSE;
+    else
+	return TRUE;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/addr_order.c b/krb5-1-6/src/lib/krb5/krb/addr_order.c
new file mode 100644
index 000000000..2f01e1fbc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/addr_order.c
@@ -0,0 +1,63 @@
+/*
+ * lib/krb5/krb/addr_order.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_address_order()
+ */
+
+#include "k5-int.h"
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * Return an ordering on two addresses:  0 if the same,
+ * < 0 if first is less than 2nd, > 0 if first is greater than 2nd.
+ */
+int KRB5_CALLCONV
+krb5_address_order(krb5_context context, const krb5_address *addr1, const krb5_address *addr2)
+{
+    int dir;
+    register int i;
+    const int minlen = min(addr1->length, addr2->length);
+
+    if (addr1->addrtype != addr2->addrtype)
+	return(FALSE);
+
+    dir = addr1->length - addr2->length;
+
+    
+    for (i = 0; i < minlen; i++) {
+	if ((unsigned char) addr1->contents[i] <
+	    (unsigned char) addr2->contents[i])
+	    return -1;
+	else if ((unsigned char) addr1->contents[i] >
+		 (unsigned char) addr2->contents[i])
+	    return 1;
+    }
+    /* compared equal so far...which is longer? */
+    return dir;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/addr_srch.c b/krb5-1-6/src/lib/krb5/krb/addr_srch.c
new file mode 100644
index 000000000..efab59f8f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/addr_srch.c
@@ -0,0 +1,46 @@
+/*
+ * lib/krb5/krb/addr_srch.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_address_search()
+ */
+
+#include "k5-int.h"
+
+/*
+ * if addr is listed in addrlist, or addrlist is null, return TRUE.
+ * if not listed, return FALSE
+ */
+krb5_boolean
+krb5_address_search(krb5_context context, const krb5_address *addr, krb5_address *const *addrlist)
+{
+    if (!addrlist)
+	return TRUE;
+    for (; *addrlist; addrlist++) {
+	if (krb5_address_compare(context, addr, *addrlist))
+	    return TRUE;
+    }
+    return FALSE;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/appdefault.c b/krb5-1-6/src/lib/krb5/krb/appdefault.c
new file mode 100644
index 000000000..94788899b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/appdefault.c
@@ -0,0 +1,166 @@
+/*
+ * appdefault - routines designed to be called from applications to
+ *		 handle the [appdefaults] profile section
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "k5-int.h"
+
+
+
+ /*xxx Duplicating this is annoying; try to work on a better way.*/
+static const char *const conf_yes[] = {
+	"y", "yes", "true", "t", "1", "on",
+	0,
+};
+
+static const char *const conf_no[] = {
+	"n", "no", "false", "nil", "0", "off",
+	0,
+};
+
+static int conf_boolean(char *s)
+{
+	const char * const *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;
+	}
+	/* Default to "no" */
+	return 0;
+}
+
+static krb5_error_code appdefault_get(krb5_context context, const char *appname, const krb5_data *realm, const char *option, char **ret_value)
+{
+        profile_t profile;
+        const char *names[5];
+	char **nameval = NULL;
+	krb5_error_code retval;
+	const char * realmstr =  realm?realm->data:NULL;
+
+	    if (!context || (context->magic != KV5M_CONTEXT)) 
+	    return KV5M_CONTEXT;
+
+	    profile = context->profile;
+	    
+	/*
+	 * Try number one:
+	 *
+	 * [appdefaults]
+	 *	app = {
+	 *		SOME.REALM = {
+	 *			option = <boolean>
+	 *		}
+	 *	}
+	 */
+
+	names[0] = "appdefaults";
+	names[1] = appname;
+
+	if (realmstr) {
+		names[2] = realmstr;
+		names[3] = option;
+		names[4] = 0;
+		retval = profile_get_values(profile, names, &nameval);
+		if (retval == 0 && nameval && nameval[0]) {
+			*ret_value = strdup(nameval[0]);
+			goto goodbye;
+		}
+	}
+
+	/*
+	 * Try number two:
+	 *
+	 * [appdefaults]
+	 *	app = {
+	 *		option = <boolean>
+	 *      }
+	 */
+
+	names[2] = option;
+	names[3] = 0;
+	retval = profile_get_values(profile, names, &nameval);
+	if (retval == 0 && nameval && nameval[0]) {
+		*ret_value = strdup(nameval[0]);
+		goto goodbye;
+	}
+
+	/*
+	 * Try number three:
+	 *
+	 * [appdefaults]
+	 *	realm = {
+	 *		option = <boolean>
+	 */
+	
+	if (realmstr) {
+		names[1] = realmstr;
+		names[2] = option;
+		names[3] = 0;
+		retval = profile_get_values(profile, names, &nameval);
+		if (retval == 0 && nameval && nameval[0]) {
+			*ret_value = strdup(nameval[0]);
+			goto goodbye;
+		}
+	}
+
+	/*
+	 * Try number four:
+	 *
+	 * [appdefaults]
+	 *	option = <boolean>
+	 */
+
+	names[1] = option;
+	names[2] = 0;
+	retval = profile_get_values(profile, names, &nameval);
+	if (retval == 0 && nameval && nameval[0]) {
+		*ret_value = strdup(nameval[0]);
+	} else {
+		return retval;
+	}
+
+goodbye:
+	if (nameval) {
+		char **cpp;
+		for (cpp = nameval; *cpp; cpp++)
+			free(*cpp);
+		free(nameval);
+	}
+	return 0;
+}
+
+void KRB5_CALLCONV 
+krb5_appdefault_boolean(krb5_context context, const char *appname, const krb5_data *realm, const char *option, int default_value, int *ret_value)
+{
+	char *string = NULL;
+	krb5_error_code retval;
+
+	retval = appdefault_get(context, appname, realm, option, &string);
+
+	if (! retval && string) {
+		*ret_value = conf_boolean(string);
+		free(string);
+	} else
+		*ret_value = default_value;
+}
+
+void KRB5_CALLCONV 
+krb5_appdefault_string(krb5_context context, const char *appname, const krb5_data *realm, const char *option, const char *default_value, char **ret_value)
+{
+	krb5_error_code retval;
+	char *string;
+
+	retval = appdefault_get(context, appname, realm, option, &string);
+
+	if (! retval && string) {
+		*ret_value = string;
+	} else {
+		*ret_value = strdup(default_value);
+	}
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/auth_con.c b/krb5-1-6/src/lib/krb5/krb/auth_con.c
new file mode 100644
index 000000000..ca33862fd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/auth_con.c
@@ -0,0 +1,559 @@
+#include "k5-int.h"
+#include "auth_con.h"
+
+static krb5_boolean chk_heimdal_seqnum(krb5_ui_4, krb5_ui_4);
+
+static krb5_error_code
+actx_copy_addr(krb5_context context, const krb5_address *inad, krb5_address **outad)
+{
+    krb5_address *tmpad;
+
+    if (!(tmpad = (krb5_address *)malloc(sizeof(*tmpad))))
+	return ENOMEM;
+    *tmpad = *inad;
+    if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
+	krb5_xfree(tmpad);
+	return ENOMEM;
+    }
+    memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length);
+    *outad = tmpad;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context)
+{
+    *auth_context =
+            (krb5_auth_context)malloc(sizeof(struct _krb5_auth_context));
+    if (!*auth_context)
+	    return ENOMEM;
+    
+    memset(*auth_context, 0, sizeof(struct _krb5_auth_context));
+
+    /* Default flags, do time not seq */
+    (*auth_context)->auth_context_flags = 
+	    KRB5_AUTH_CONTEXT_DO_TIME |  KRB5_AUTH_CONN_INITIALIZED;
+
+    (*auth_context)->req_cksumtype = context->default_ap_req_sumtype;
+    (*auth_context)->safe_cksumtype = context->default_safe_sumtype;
+    (*auth_context) -> checksum_func = NULL;
+    (*auth_context)->checksum_func_data = NULL;
+    (*auth_context)->magic = KV5M_AUTH_CONTEXT;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context)
+{
+    if (auth_context->local_addr) 
+	krb5_free_address(context, auth_context->local_addr);
+    if (auth_context->remote_addr) 
+	krb5_free_address(context, auth_context->remote_addr);
+    if (auth_context->local_port) 
+	krb5_free_address(context, auth_context->local_port);
+    if (auth_context->remote_port) 
+	krb5_free_address(context, auth_context->remote_port);
+    if (auth_context->authentp) 
+	krb5_free_authenticator(context, auth_context->authentp);
+    if (auth_context->keyblock) 
+	krb5_free_keyblock(context, auth_context->keyblock);
+    if (auth_context->send_subkey) 
+	krb5_free_keyblock(context, auth_context->send_subkey);
+    if (auth_context->recv_subkey) 
+	krb5_free_keyblock(context, auth_context->recv_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;
+}
+
+krb5_error_code
+krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr)
+{
+    krb5_error_code	retval;
+
+    /* Free old addresses */
+    if (auth_context->local_addr)
+	(void) krb5_free_address(context, auth_context->local_addr);
+    if (auth_context->remote_addr)
+	(void) krb5_free_address(context, auth_context->remote_addr);
+
+    retval = 0;
+    if (local_addr)
+	retval = actx_copy_addr(context,
+				local_addr,
+				&auth_context->local_addr);
+    else
+	auth_context->local_addr = NULL;
+
+    if (!retval && remote_addr)
+	retval = actx_copy_addr(context,
+				remote_addr,
+				&auth_context->remote_addr);
+    else
+	auth_context->remote_addr = NULL;
+
+    return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr)
+{
+    krb5_error_code	retval;
+
+    retval = 0;
+    if (local_addr && auth_context->local_addr) {
+	retval = actx_copy_addr(context,
+				auth_context->local_addr,
+				local_addr);
+    }
+    if (!retval && (remote_addr) && auth_context->remote_addr) {
+	retval = actx_copy_addr(context,
+				auth_context->remote_addr,
+				remote_addr);
+    }
+    return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port)
+{
+    krb5_error_code	retval;
+
+    /* Free old addresses */
+    if (auth_context->local_port)
+	(void) krb5_free_address(context, auth_context->local_port);
+    if (auth_context->remote_port)
+	(void) krb5_free_address(context, auth_context->remote_port);
+
+    retval = 0;
+    if (local_port)
+	retval = actx_copy_addr(context,
+				local_port,
+				&auth_context->local_port);
+    else
+	auth_context->local_port = NULL;
+
+    if (!retval && remote_port)
+	retval = actx_copy_addr(context,
+				remote_port,
+				&auth_context->remote_port);
+    else
+	auth_context->remote_port = NULL;
+
+    return retval;
+}
+
+
+/*
+ * This function overloads the keyblock field. It is only useful prior to
+ * a krb5_rd_req_decode() call for user to user authentication where the
+ * server has the key and needs to use it to decrypt the incoming request.
+ * Once decrypted this key is no longer necessary and is then overwritten
+ * with the session key sent by the client.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock)
+{
+    if (auth_context->keyblock)
+	krb5_free_keyblock(context, auth_context->keyblock);
+    return(krb5_copy_keyblock(context, keyblock, &(auth_context->keyblock)));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
+{
+    if (auth_context->keyblock)
+    	return krb5_copy_keyblock(context, auth_context->keyblock, keyblock);
+    *keyblock = NULL;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
+{
+    return krb5_auth_con_getsendsubkey(context, auth_context, keyblock);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
+{
+    return krb5_auth_con_getrecvsubkey(context, auth_context, keyblock);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
+{
+    if (ac->send_subkey != NULL)
+	krb5_free_keyblock(ctx, ac->send_subkey);
+    ac->send_subkey = NULL;
+    if (keyblock !=NULL)
+	return krb5_copy_keyblock(ctx, keyblock, &ac->send_subkey);
+    else
+	return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
+{
+    if (ac->recv_subkey != NULL)
+	krb5_free_keyblock(ctx, ac->recv_subkey);
+    ac->recv_subkey = NULL;
+    if (keyblock != NULL)
+	return krb5_copy_keyblock(ctx, keyblock, &ac->recv_subkey);
+    else
+	return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
+{
+    if (ac->send_subkey != NULL)
+	return krb5_copy_keyblock(ctx, ac->send_subkey, keyblock);
+    *keyblock = NULL;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
+{
+    if (ac->recv_subkey != NULL)
+	return krb5_copy_keyblock(ctx, ac->recv_subkey, keyblock);
+    *keyblock = NULL;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
+{
+    auth_context->req_cksumtype = cksumtype;
+    return 0;
+}
+
+krb5_error_code
+krb5_auth_con_set_safe_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
+{
+    auth_context->safe_cksumtype = cksumtype;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
+{
+    *seqnumber = auth_context->local_seq_number;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, krb5_authenticator **authenticator)
+{
+    return (krb5_copy_authenticator(context, auth_context->authentp,
+				    authenticator));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
+{
+    *seqnumber = auth_context->remote_seq_number;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context)
+{
+    krb5_error_code ret;
+
+    if (auth_context->keyblock) {
+	size_t blocksize;
+
+	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;
+    }
+    return EINVAL; /* XXX need an error for no keyblock */
+}
+
+krb5_error_code
+krb5_auth_con_setivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer ivector)
+{
+    auth_context->i_vector = ivector;
+    return 0;
+}
+
+krb5_error_code
+krb5_auth_con_getivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer *ivector)
+{
+    *ivector = auth_context->i_vector;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags)
+{
+    auth_context->auth_context_flags = flags;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 *flags)
+{
+    *flags = auth_context->auth_context_flags;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache)
+{
+    auth_context->rcache = rcache;
+    return 0;
+}
+    
+krb5_error_code
+krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache *rcache)
+{
+    *rcache = auth_context->rcache;
+    return 0;
+}
+    
+krb5_error_code
+krb5_auth_con_setpermetypes(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(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);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_set_checksum_func( krb5_context context,
+				 krb5_auth_context  auth_context,
+				 krb5_mk_req_checksum_func func,
+				 void *data)
+{
+  auth_context->checksum_func = func;
+  auth_context->checksum_func_data = data;
+  return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_get_checksum_func( krb5_context context,
+				 krb5_auth_context auth_context,
+				 krb5_mk_req_checksum_func *func,
+				 void **data)
+{
+  *func = auth_context->checksum_func;
+  *data = auth_context->checksum_func_data;
+  return 0;
+}
+
+/*
+ * krb5int_auth_con_chkseqnum
+ *
+ * We use a somewhat complex heuristic for validating received
+ * sequence numbers.  We must accommodate both our older
+ * implementation, which sends negative sequence numbers, and the
+ * broken Heimdal implementation (at least as of 0.5.2), which
+ * violates X.690 BER for integer encodings.  The requirement of
+ * handling negative sequence numbers removes one of easier means of
+ * detecting a Heimdal implementation, so we resort to this mess
+ * here.
+ *
+ * X.690 BER (and consequently DER, which are the required encoding
+ * rules in RFC1510) encode all integer types as signed integers.
+ * This means that the MSB being set on the first octet of the
+ * contents of the encoding indicates a negative value.  Heimdal does
+ * not prepend the required zero octet to unsigned integer encodings
+ * which would otherwise have the MSB of the first octet of their
+ * encodings set.
+ *
+ * Our ASN.1 library implements a special decoder for sequence
+ * numbers, accepting both negative and positive 32-bit numbers but
+ * mapping them both into the space of positive unsigned 32-bit
+ * numbers in the obvious bit-pattern-preserving way.  This maintains
+ * compatibility with our older implementations.  This also means that
+ * encodings emitted by Heimdal are ambiguous.
+ *
+ * Heimdal counter value	received uint32 value
+ *
+ * 0x00000080			0xFFFFFF80
+ * 0x000000FF			0xFFFFFFFF
+ * 0x00008000			0xFFFF8000
+ * 0x0000FFFF			0xFFFFFFFF
+ * 0x00800000			0xFF800000
+ * 0x00FFFFFF			0xFFFFFFFF
+ * 0xFF800000			0xFF800000
+ * 0xFFFFFFFF			0xFFFFFFFF
+ *
+ * We use two auth_context flags, SANE_SEQ and HEIMDAL_SEQ, which are
+ * only set after we can unambiguously determine the sanity of the
+ * sending implementation.  Once one of these flags is set, we accept
+ * only the sequence numbers appropriate to the remote implementation
+ * type.  We can make the determination in two different ways.  The
+ * first is to note the receipt of a "negative" sequence number when a
+ * "positive" one was expected.  The second is to note the receipt of
+ * a sequence number that wraps through "zero" in a weird way.  The
+ * latter corresponds to the receipt of an initial sequence number in
+ * the ambiguous range.
+ *
+ * There are 2^7 + 2^15 + 2^23 + 2^23 = 16810112 total ambiguous
+ * initial Heimdal counter values, but we receive them as one of 2^23
+ * possible values.  There is a ~1/256 chance of a Heimdal
+ * implementation sending an intial sequence number in the ambiguous
+ * range.
+ *
+ * We have to do special treatment when receiving sequence numbers
+ * between 0xFF800000..0xFFFFFFFF, or when wrapping through zero
+ * weirdly (due to ambiguous initial sequence number).  If we are
+ * expecting a value corresponding to an ambiguous Heimdal counter
+ * value, and we receive an exact match, we can mark the remote end as
+ * sane.
+ */
+krb5_boolean
+krb5int_auth_con_chkseqnum(
+    krb5_context ctx,
+    krb5_auth_context ac,
+    krb5_ui_4 in_seq)
+{
+    krb5_ui_4 exp_seq;
+
+    exp_seq = ac->remote_seq_number;
+
+    /*
+     * If sender is known to be sane, accept _only_ exact matches.
+     */
+    if (ac->auth_context_flags & KRB5_AUTH_CONN_SANE_SEQ)
+	return in_seq == exp_seq;
+
+    /*
+     * If sender is not known to be sane, first check the ambiguous
+     * range of received values, 0xFF800000..0xFFFFFFFF.
+     */
+    if ((in_seq & 0xFF800000) == 0xFF800000) {
+	/*
+	 * If expected sequence number is in the range
+	 * 0xFF800000..0xFFFFFFFF, then we can't make any
+	 * determinations about the sanity of the sending
+	 * implementation.
+	 */
+	if ((exp_seq & 0xFF800000) == 0xFF800000 && in_seq == exp_seq)
+	    return 1;
+	/*
+	 * If sender is not known for certain to be a broken Heimdal
+	 * implementation, check for exact match.
+	 */
+	if (!(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)
+	    && in_seq == exp_seq)
+	    return 1;
+	/*
+	 * Now apply hairy algorithm for matching sequence numbers
+	 * sent by broken Heimdal implementations.  If it matches, we
+	 * know for certain it's a broken Heimdal sender.
+	 */
+	if (chk_heimdal_seqnum(exp_seq, in_seq)) {
+	    ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
+	    return 1;
+	}
+	return 0;
+    }
+
+    /*
+     * Received value not in the ambiguous range?  If the _expected_
+     * value is in the range of ambiguous Hemidal counter values, and
+     * it matches the received value, sender is known to be sane.
+     */
+    if (in_seq == exp_seq) {
+	if ((   exp_seq & 0xFFFFFF80) == 0x00000080
+	    || (exp_seq & 0xFFFF8000) == 0x00008000
+	    || (exp_seq & 0xFF800000) == 0x00800000)
+	    ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ;
+	return 1;
+    }
+
+    /*
+     * Magic wraparound for the case where the intial sequence number
+     * is in the ambiguous range.  This means that the sender's
+     * counter is at a different count than ours, so we correct ours,
+     * and mark the sender as being a broken Heimdal implementation.
+     */
+    if (exp_seq == 0
+	&& !(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)) {
+	switch (in_seq) {
+	case 0x100:
+	case 0x10000:
+	case 0x1000000:
+	    ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
+	    exp_seq = in_seq;
+	    return 1;
+	default:
+	    return 0;
+	}
+    }
+    return 0;
+}
+
+static krb5_boolean
+chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq)
+{
+    if (( exp_seq & 0xFF800000) == 0x00800000
+	&& (in_seq & 0xFF800000) == 0xFF800000
+	&& (in_seq & 0x00FFFFFF) == exp_seq)
+	return 1;
+    else if ((  exp_seq & 0xFFFF8000) == 0x00008000
+	     && (in_seq & 0xFFFF8000) == 0xFFFF8000
+	     && (in_seq & 0x0000FFFF) == exp_seq)
+	return 1;
+    else if ((  exp_seq & 0xFFFFFF80) == 0x00000080
+	     && (in_seq & 0xFFFFFF80) == 0xFFFFFF80
+	     && (in_seq & 0x000000FF) == exp_seq)
+	return 1;
+    else
+	return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/auth_con.h b/krb5-1-6/src/lib/krb5/krb/auth_con.h
new file mode 100644
index 000000000..9543de355
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/auth_con.h
@@ -0,0 +1,36 @@
+
+#ifndef KRB5_AUTH_CONTEXT
+#define KRB5_AUTH_CONTEXT
+
+struct _krb5_auth_context {
+    krb5_magic		magic;
+    krb5_address      *	remote_addr;
+    krb5_address      *	remote_port;
+    krb5_address      *	local_addr;
+    krb5_address      *	local_port;
+    krb5_keyblock     * keyblock;
+    krb5_keyblock     * send_subkey;
+    krb5_keyblock     * recv_subkey;
+
+    krb5_int32		auth_context_flags;
+    krb5_ui_4		remote_seq_number;
+    krb5_ui_4		local_seq_number;
+    krb5_authenticator *authentp;		/* mk_req, rd_req, mk_rep, ...*/
+    krb5_cksumtype	req_cksumtype;		/* mk_safe, ... */
+    krb5_cksumtype	safe_cksumtype;		/* mk_safe, ... */
+    krb5_pointer	i_vector;		/* mk_priv, rd_priv only */
+    krb5_rcache		rcache;
+    krb5_enctype      * permitted_etypes;	/* rd_req */
+  krb5_mk_req_checksum_func checksum_func;
+  void *checksum_func_data;
+};
+
+
+/* Internal auth_context_flags */
+#define KRB5_AUTH_CONN_INITIALIZED	0x00010000
+#define KRB5_AUTH_CONN_USED_W_MK_REQ	0x00020000
+#define KRB5_AUTH_CONN_USED_W_RD_REQ	0x00040000
+#define KRB5_AUTH_CONN_SANE_SEQ		0x00080000
+#define KRB5_AUTH_CONN_HEIMDAL_SEQ	0x00100000
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/krb/bld_pr_ext.c b/krb5-1-6/src/lib/krb5/krb/bld_pr_ext.c
new file mode 100644
index 000000000..c1af72616
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/bld_pr_ext.c
@@ -0,0 +1,102 @@
+/*
+ * lib/krb5/krb/bld_pr_ext.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Build a principal from a list of lengths and strings
+ */
+
+#include "k5-int.h"
+
+#include <stdarg.h>
+
+krb5_error_code KRB5_CALLCONV_C
+krb5_build_principal_ext(krb5_context context,  krb5_principal * princ,
+			 unsigned int rlen, const char * realm, ...)
+{
+    va_list ap;
+    register int i, count = 0;
+    register unsigned int size;
+    register char *next;
+    char *tmpdata;
+    krb5_data *princ_data;
+    krb5_principal princ_ret;
+
+    va_start(ap, realm);
+    /* count up */
+    while (va_arg(ap, int) != 0) {
+	(void)va_arg(ap, char *);		/* pass one up */
+	count++;
+    }
+    va_end(ap);
+
+    /* we do a 2-pass to avoid the need to guess on allocation needs
+       cf. bld_princ.c */
+    /* get space for array */
+    princ_data = (krb5_data *) malloc(sizeof(krb5_data) * count);
+    if (!princ_data)
+	return ENOMEM;
+    princ_ret = (krb5_principal) malloc(sizeof(krb5_principal_data));
+    if (!princ_ret) {
+	krb5_xfree(princ_data);
+	return ENOMEM;
+    }
+    princ_ret->data = princ_data;
+    princ_ret->length = count;
+    tmpdata = malloc(rlen+1);
+    if (!tmpdata) {
+	krb5_xfree(princ_data);
+	krb5_xfree(princ_ret);
+	return ENOMEM;
+    }	
+    krb5_princ_set_realm_length(context, princ_ret, rlen);
+    krb5_princ_set_realm_data(context, princ_ret, tmpdata);
+    memcpy(tmpdata, realm, rlen);
+    tmpdata[rlen] = 0;
+
+    /* process rest of components */
+    va_start(ap, realm);
+    for (i = 0; i < count; i++) {
+	size = va_arg(ap, unsigned int);
+	next = va_arg(ap, char *);
+	princ_data[i].length = size;
+	princ_data[i].data = malloc(size+1);
+	if (!princ_data[i].data)
+	    goto free_out;
+	memcpy(princ_data[i].data, next, size);
+	princ_data[i].data[size] = 0;
+    }
+    va_end(ap);
+    *princ = princ_ret;
+    krb5_princ_type(context, princ_ret) = KRB5_NT_UNKNOWN;
+    return 0;
+
+free_out:
+    while (i-- >= 0)
+	krb5_xfree(princ_data[i].data);
+    krb5_xfree(princ_data);
+    krb5_xfree(princ_ret);
+    va_end(ap);
+    return ENOMEM;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/bld_princ.c b/krb5-1-6/src/lib/krb5/krb/bld_princ.c
new file mode 100644
index 000000000..c6cb7af05
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/bld_princ.c
@@ -0,0 +1,110 @@
+/*
+ * lib/krb5/krb/bld_princ.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Build a principal from a list of strings
+ */
+
+#include <stdarg.h>
+#include "k5-int.h"
+
+krb5_error_code
+KRB5_CALLCONV
+krb5_build_principal_va(krb5_context context, krb5_principal princ, unsigned int rlen, const char *realm, va_list ap)
+{
+    register int i, count = 0;
+    register char *next;
+    char *tmpdata;
+    krb5_data *data;
+
+    /* guess at an initial sufficent count of 2 pieces */
+    count = 2;
+
+    /* get space for array and realm, and insert realm */
+    data = (krb5_data *) malloc(sizeof(krb5_data) * count);
+    if (data == 0)
+	return ENOMEM;
+    krb5_princ_set_realm_length(context, princ, rlen);
+    tmpdata = malloc(rlen);
+    if (!tmpdata) {
+	free (data);
+	return ENOMEM;
+    }
+    krb5_princ_set_realm_data(context, princ, tmpdata);
+    memcpy(tmpdata, realm, rlen);
+
+    /* process rest of components */
+
+    for (i = 0, next = va_arg(ap, char *);
+	 next;
+	 next = va_arg(ap, char *), i++) {
+	if (i == count) {
+	    /* not big enough.  realloc the array */
+	    krb5_data *p_tmp;
+	    p_tmp = (krb5_data *) realloc((char *)data,
+					  sizeof(krb5_data)*(count*2));
+	    if (!p_tmp) {
+	    free_out:
+		    while (--i >= 0)
+			krb5_xfree(data[i].data);
+		    krb5_xfree(data);
+		    krb5_xfree(tmpdata);
+		    return (ENOMEM);
+	    }
+	    count *= 2;
+	    data = p_tmp;
+	}
+
+	data[i].length = strlen(next);
+	data[i].data = strdup(next);
+	if (!data[i].data)
+	    goto free_out;
+    }
+    princ->data = data;
+    princ->length = i;
+    princ->type = KRB5_NT_UNKNOWN;
+    princ->magic = KV5M_PRINCIPAL;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV_C
+krb5_build_principal(krb5_context context,  krb5_principal * princ, 
+		     unsigned int rlen,
+		     const char * realm, ...)
+{
+    va_list ap;
+    krb5_error_code retval;
+    krb5_principal pr_ret = (krb5_principal)malloc(sizeof(krb5_principal_data));
+
+    if (!pr_ret)
+	return ENOMEM;
+
+    va_start(ap, realm);
+    retval = krb5_build_principal_va(context, pr_ret, rlen, realm, ap);
+    va_end(ap);
+    if (retval == 0)
+	*princ = pr_ret;
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/brand.c b/krb5-1-6/src/lib/krb5/krb/brand.c
new file mode 100644
index 000000000..7e4e0dbd0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/brand.c
@@ -0,0 +1,72 @@
+/*
+ * lib/krb5/krb/brand.c
+ *
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This file is used to put a "release brand" on a Krb5 library before
+ * it is released via some release engineering process.  This gives us
+ * an easy way to tell where a binary came from.
+ *
+ * It depends on patchlevel.h for the master version stamp info.
+ */
+
+/* Format: "KRB5_BRAND: <cvs_tag> <release_name> <date>" */
+
+#include "patchlevel.h"
+
+#define XSTR(x) #x
+#define STR(x) XSTR(x)
+
+#ifdef KRB5_RELTAG
+#define RELTAG KRB5_RELTAG
+#else
+#define RELTAG "[untagged]"
+#endif
+
+#define MAJOR_MINOR STR(KRB5_MAJOR_RELEASE) "." STR(KRB5_MINOR_RELEASE)
+
+#if KRB5_PATCHLEVEL != 0
+#define MAYBE_PATCH "." STR(KRB5_PATCHLEVEL)
+#else
+#define MAYBE_PATCH ""
+#endif
+
+#ifdef KRB5_RELTAIL
+#define RELTAIL "-" KRB5_RELTAIL
+#else
+#define RELTAIL ""
+#endif
+
+#define RELNAME MAJOR_MINOR MAYBE_PATCH RELTAIL
+
+#ifdef KRB5_RELDATE
+#define RELDATE KRB5_RELDATE
+#else
+#define RELDATE "[date unknown]"
+#endif
+
+#define BRANDSTR RELTAG " " RELNAME " " RELDATE
+
+static char krb5_brand[] = "KRB5_BRAND: " BRANDSTR;
diff --git a/krb5-1-6/src/lib/krb5/krb/chk_trans.c b/krb5-1-6/src/lib/krb5/krb/chk_trans.c
new file mode 100644
index 000000000..9fe73c878
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/chk_trans.c
@@ -0,0 +1,441 @@
+/*
+ * lib/krb5/krb/chk_trans.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_check_transited_list()
+ */
+#include "k5-int.h"
+#include <stdarg.h>
+
+#if defined (TEST) || defined (TEST2)
+# undef DEBUG
+# define DEBUG
+#endif
+
+#ifdef DEBUG
+#define verbose krb5int_chk_trans_verbose
+static int verbose = 0;
+# define Tprintf(ARGS) if (verbose) printf ARGS
+#else
+# define Tprintf(ARGS) (void)(0)
+#endif
+
+#define MAXLEN 512
+
+static krb5_error_code
+process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data,
+		       const krb5_data *n1, const krb5_data *n2) {
+    unsigned int len1, len2, i;
+    char *p1, *p2;
+
+    Tprintf (("process_intermediates(%.*s,%.*s)\n",
+	      (int) n1->length, n1->data, (int) n2->length, n2->data));
+
+    len1 = n1->length;
+    len2 = n2->length;
+
+    Tprintf (("(walking intermediates now)\n"));
+    /* Simplify...  */
+    if (len1 > len2) {
+	const krb5_data *p;
+	int tmp = len1;
+	len1 = len2;
+	len2 = tmp;
+	p = n1;
+	n1 = n2;
+	n2 = p;
+    }
+    /* Okay, now len1 is always shorter or equal.  */
+    if (len1 == len2) {
+	if (memcmp (n1->data, n2->data, len1)) {
+	    Tprintf (("equal length but different strings in path: '%.*s' '%.*s'\n",
+		      (int) n1->length, n1->data, (int) n2->length, n2->data));
+	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+	Tprintf (("(end intermediates)\n"));
+	return 0;
+    }
+    /* Now len1 is always shorter.  */
+    if (len1 == 0)
+	/* Shouldn't be possible.  Internal error?  */
+	return KRB5KRB_AP_ERR_ILL_CR_TKT;
+    p1 = n1->data;
+    p2 = n2->data;
+    if (p1[0] == '/') {
+	/* X.500 style names, with common prefix.  */
+	if (p2[0] != '/') {
+	    Tprintf (("mixed name formats in path: x500='%.*s' domain='%.*s'\n",
+		      (int) len1, p1, (int) len2, p2));
+	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+	if (memcmp (p1, p2, len1)) {
+	    Tprintf (("x500 names with different prefixes '%.*s' '%.*s'\n",
+		      (int) len1, p1, (int) len2, p2));
+	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+	for (i = len1 + 1; i < len2; i++)
+	    if (p2[i] == '/') {
+		krb5_data d;
+		krb5_error_code r;
+
+		d.data = p2;
+		d.length = i;
+		r = (*fn) (&d, data);
+		if (r)
+		    return r;
+	    }
+    } else {
+	/* Domain style names, with common suffix.  */
+	if (p2[0] == '/') {
+	    Tprintf (("mixed name formats in path: domain='%.*s' x500='%.*s'\n",
+		      (int) len1, p1, (int) len2, p2));
+	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+	if (memcmp (p1, p2 + (len2 - len1), len1)) {
+	    Tprintf (("domain names with different suffixes '%.*s' '%.*s'\n",
+		      (int) len1, p1, (int) len2, p2));
+	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+	for (i = len2 - len1 - 1; i > 0; i--) {
+	    Tprintf (("looking at '%.*s'\n", (int) (len2 - i), p2+i));
+	    if (p2[i-1] == '.') {
+		krb5_data d;
+		krb5_error_code r;
+
+		d.data = p2+i;
+		d.length = len2 - i;
+		r = (*fn) (&d, data);
+		if (r)
+		    return r;
+	    }
+	}
+    }
+    Tprintf (("(end intermediates)\n"));
+    return 0;
+}
+
+static krb5_error_code
+maybe_join (krb5_data *last, krb5_data *buf, int bufsiz)
+{
+    if (buf->length == 0)
+	return 0;
+    if (buf->data[0] == '/') {
+	if (last->length + buf->length > bufsiz) {
+	    Tprintf (("too big: last=%d cur=%d max=%d\n", last->length, buf->length, bufsiz));
+	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+	memmove (buf->data+last->length, buf->data, buf->length);
+	memcpy (buf->data, last->data, last->length);
+	buf->length += last->length;
+    } else if (buf->data[buf->length-1] == '.') {
+	/* We can ignore the case where the previous component was
+	   empty; the strcat will be a no-op.  It should probably
+	   be an error case, but let's be flexible.  */
+	if (last->length+buf->length > bufsiz) {
+	    Tprintf (("too big\n"));
+	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+	memcpy (buf->data + buf->length, last->data, last->length);
+	buf->length += last->length;
+    }
+    /* Otherwise, do nothing.  */
+    return 0;
+}
+
+/* The input strings cannot contain any \0 bytes, according to the
+   spec, but our API is such that they may not be \0 terminated
+   either.  Thus we keep on treating them as krb5_data objects instead
+   of C strings.  */
+static krb5_error_code
+foreach_realm (krb5_error_code (*fn)(krb5_data *comp,void *data), void *data,
+	       const krb5_data *crealm, const krb5_data *srealm,
+	       const krb5_data *transit)
+{
+    char buf[MAXLEN], last[MAXLEN];
+    char *p, *bufp;
+    int next_lit, intermediates, l;
+    krb5_data this_component;
+    krb5_error_code r;
+    krb5_data last_component;
+
+    /* Invariants:
+       - last_component points to last[]
+       - this_component points to buf[]
+       - last_component has length of last
+       - this_component has length of buf when calling out
+       Keep these consistent, and we should be okay.  */
+
+    next_lit = 0;
+    intermediates = 0;
+    memset (buf, 0, sizeof (buf));
+
+    this_component.data = buf;
+    last_component.data = last;
+    last_component.length = 0;
+
+#define print_data(fmt,d) Tprintf((fmt,(int)(d)->length,(d)->data))
+    print_data ("client realm: %.*s\n", crealm);
+    print_data ("server realm: %.*s\n", srealm);
+    print_data ("transit enc.: %.*s\n", transit);
+
+    if (transit->length == 0) {
+	Tprintf (("no other realms transited\n"));
+	return 0;
+    }
+
+    bufp = buf;
+    for (p = transit->data, l = transit->length; l; p++, l--) {
+	if (next_lit) {
+	    *bufp++ = *p;
+	    if (bufp == buf+sizeof(buf))
+		return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	    next_lit = 0;
+	} else if (*p == '\\') {
+	    next_lit = 1;
+	} else if (*p == ',') {
+	    if (bufp != buf) {
+		this_component.length = bufp - buf;
+		r = maybe_join (&last_component, &this_component, sizeof(buf));
+		if (r)
+		    return r;
+		r = (*fn) (&this_component, data);
+		if (r)
+		    return r;
+		if (intermediates) {
+		    if (p == transit->data)
+			r = process_intermediates (fn, data,
+						   &this_component, crealm);
+		    else {
+			r = process_intermediates (fn, data, &this_component,
+						   &last_component);
+		    }
+		    if (r)
+			return r;
+		}
+		intermediates = 0;
+		memcpy (last, buf, sizeof (buf));
+		last_component.length = this_component.length;
+		memset (buf, 0, sizeof (buf));
+		bufp = buf;
+	    } else {
+		intermediates = 1;
+		if (p == transit->data) {
+		    if (crealm->length >= MAXLEN)
+			return KRB5KRB_AP_ERR_ILL_CR_TKT;
+		    memcpy (last, crealm->data, crealm->length);
+		    last[crealm->length] = '\0';
+		    last_component.length = crealm->length;
+		}
+	    }
+	} else if (*p == ' ' && bufp == buf) {
+	    /* This next component stands alone, even if it has a
+	       trailing dot or leading slash.  */
+	    memset (last, 0, sizeof (last));
+	    last_component.length = 0;
+	} else {
+	    /* Not a special character; literal.  */
+	    *bufp++ = *p;
+	    if (bufp == buf+sizeof(buf))
+		return KRB5KRB_AP_ERR_ILL_CR_TKT;
+	}
+    }
+    /* At end.  Must be normal state.  */
+    if (next_lit)
+	Tprintf (("ending in next-char-literal state\n"));
+    /* Process trailing element or comma.  */
+    if (bufp == buf) {
+	/* Trailing comma.  */
+	r = process_intermediates (fn, data, &last_component, srealm);
+    } else {
+	/* Trailing component.  */
+	this_component.length = bufp - buf;
+	r = maybe_join (&last_component, &this_component, sizeof(buf));
+	if (r)
+	    return r;
+	r = (*fn) (&this_component, data);
+	if (r)
+	    return r;
+	if (intermediates)
+	    r = process_intermediates (fn, data, &this_component,
+				       &last_component);
+    }
+    if (r != 0)
+	return r;
+    return 0;
+}
+
+
+struct check_data {
+    krb5_context ctx;
+    krb5_principal *tgs;
+};
+
+static int
+same_data (krb5_data *d1, krb5_data *d2)
+{
+    return (d1->length == d2->length
+	    && !memcmp (d1->data, d2->data, d1->length));
+}
+
+static krb5_error_code
+check_realm_in_list (krb5_data *realm, void *data)
+{
+    struct check_data *cdata = data;
+    int i;
+
+    Tprintf ((".. checking '%.*s'\n", (int) realm->length, realm->data));
+    for (i = 0; cdata->tgs[i]; i++) {
+	if (same_data (krb5_princ_realm (cdata->ctx, cdata->tgs[i]), realm))
+	    return 0;
+    }
+    Tprintf (("BAD!\n"));
+    return KRB5KRB_AP_ERR_ILL_CR_TKT;
+}
+
+krb5_error_code
+krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in,
+			   const krb5_data *crealm, const krb5_data *srealm)
+{
+    krb5_data trans;
+    struct check_data cdata;
+    krb5_error_code r;
+
+    trans.length = trans_in->length;
+    trans.data = (char *) trans_in->data;
+    if (trans.length && (trans.data[trans.length-1] == '\0'))
+	trans.length--;
+
+    Tprintf (("krb5_check_transited_list(trans=\"%.*s\", crealm=\"%.*s\", srealm=\"%.*s\")\n",
+	      (int) trans.length, trans.data,
+	      (int) crealm->length, crealm->data,
+	      (int) srealm->length, srealm->data));
+    if (trans.length == 0)
+	return 0;
+    r = krb5_walk_realm_tree (ctx, crealm, srealm, &cdata.tgs,
+			      KRB5_REALM_BRANCH_CHAR);
+    if (r) {
+	Tprintf (("error %ld\n", (long) r));
+	return r;
+    }
+#ifdef DEBUG /* avoid compiler warning about 'd' unused */
+    {
+	int i;
+	Tprintf (("tgs list = {\n"));
+	for (i = 0; cdata.tgs[i]; i++) {
+	    char *name;
+	    r = krb5_unparse_name (ctx, cdata.tgs[i], &name);
+	    Tprintf (("\t'%s'\n", name));
+	    free (name);
+	}
+	Tprintf (("}\n"));
+    }
+#endif
+    cdata.ctx = ctx;
+    r = foreach_realm (check_realm_in_list, &cdata, crealm, srealm, &trans);
+    krb5_free_realm_tree (ctx, cdata.tgs);
+    return r;
+}
+
+#ifdef TEST
+
+static krb5_error_code
+print_a_realm (krb5_data *realm, void *data)
+{
+    printf ("%.*s\n", (int) realm->length, realm->data);
+    return 0;
+}
+
+int main (int argc, char *argv[]) {
+    const char *me;
+    krb5_data crealm, srealm, transit;
+    krb5_error_code r;
+    int expand_only = 0;
+
+    me = strrchr (argv[0], '/');
+    me = me ? me+1 : argv[0];
+
+    while (argc > 3 && argv[1][0] == '-') {
+	if (!strcmp ("-v", argv[1]))
+	    verbose++, argc--, argv++;
+	else if (!strcmp ("-x", argv[1]))
+	    expand_only++, argc--, argv++;
+	else
+	    goto usage;
+    }
+
+    if (argc != 4) {
+    usage:
+	printf ("usage: %s [-v] [-x] clientRealm serverRealm transitEncoding\n",
+		me);
+	return 1;
+    }
+
+    crealm.data = argv[1];
+    crealm.length = strlen(argv[1]);
+    srealm.data = argv[2];
+    srealm.length = strlen(argv[2]);
+    transit.data = argv[3];
+    transit.length = strlen(argv[3]);
+
+    if (expand_only) {
+
+	printf ("client realm: %s\n", argv[1]);
+	printf ("server realm: %s\n", argv[2]);
+	printf ("transit enc.: %s\n", argv[3]);
+
+	if (argv[3][0] == 0) {
+	    printf ("no other realms transited\n");
+	    return 0;
+	}
+
+	r = foreach_realm (print_a_realm, NULL, &crealm, &srealm, &transit);
+	if (r)
+	    printf ("--> returned error %ld\n", (long) r);
+	return r != 0;
+
+    } else {
+
+	/* Actually check the values against the supplied krb5.conf file.  */
+	krb5_context ctx;
+	r = krb5_init_context (&ctx);
+	if (r) {
+	    com_err (me, r, "initializing krb5 context");
+	    return 1;
+	}
+	r = krb5_check_transited_list (ctx, &transit, &crealm, &srealm);
+	if (r == KRB5KRB_AP_ERR_ILL_CR_TKT) {
+	    printf ("NO\n");
+	} else if (r == 0) {
+	    printf ("YES\n");
+	} else {
+	    printf ("kablooey!\n");
+	    com_err (me, r, "checking transited-realm list");
+	    return 1;
+	}
+	return 0;
+    }
+}
+
+#endif /* TEST */
diff --git a/krb5-1-6/src/lib/krb5/krb/chpw.c b/krb5-1-6/src/lib/krb5/krb/chpw.c
new file mode 100644
index 000000000..427ea39aa
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/chpw.c
@@ -0,0 +1,542 @@
+/*
+** set password functions added by Paul W. Nelson, Thursby Software Systems, Inc.
+*/
+#include <string.h>
+
+#include "k5-int.h"
+#include "krb5_err.h"
+#include "auth_con.h"
+
+
+krb5_error_code 
+krb5int_mk_chpw_req(
+	krb5_context context, 
+	krb5_auth_context auth_context, 
+	krb5_data *ap_req,
+	char *passwd, 
+	krb5_data *packet)
+{
+    krb5_error_code ret = 0;
+    krb5_data clearpw;
+    krb5_data cipherpw;
+    krb5_replay_data replay;
+    char *ptr;
+
+    cipherpw.data = NULL;
+
+    if ((ret = krb5_auth_con_setflags(context, auth_context,
+				      KRB5_AUTH_CONTEXT_DO_SEQUENCE)))
+	  goto cleanup;
+
+    clearpw.length = strlen(passwd);
+    clearpw.data = passwd;
+
+    if ((ret = krb5_mk_priv(context, auth_context,
+			    &clearpw, &cipherpw, &replay)))
+      goto cleanup;
+
+    packet->length = 6 + ap_req->length + cipherpw.length;
+    packet->data = (char *) malloc(packet->length);
+    if (packet->data == NULL)
+	{
+	    ret = ENOMEM;
+	    goto cleanup;
+	}
+    ptr = packet->data;
+
+    /* length */
+
+    *ptr++ = (packet->length>> 8) & 0xff;
+    *ptr++ = packet->length & 0xff;
+
+    /* version == 0x0001 big-endian */
+
+    *ptr++ = 0;
+    *ptr++ = 1;
+
+    /* ap_req length, big-endian */
+
+    *ptr++ = (ap_req->length>>8) & 0xff;
+    *ptr++ = ap_req->length & 0xff;
+
+    /* ap-req data */
+
+    memcpy(ptr, ap_req->data, ap_req->length);
+    ptr += ap_req->length;
+
+    /* krb-priv of password */
+
+    memcpy(ptr, cipherpw.data, cipherpw.length);
+
+cleanup:
+    if(cipherpw.data != NULL)  /* allocated by krb5_mk_priv */
+      free(cipherpw.data);
+      
+    return(ret);
+}
+
+krb5_error_code 
+krb5int_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *packet, int *result_code, krb5_data *result_data)
+{
+    char *ptr;
+    int plen, vno;
+    krb5_data ap_rep;
+    krb5_ap_rep_enc_part *ap_rep_enc;
+    krb5_error_code ret;
+    krb5_data cipherresult;
+    krb5_data clearresult;
+    krb5_error *krberror;
+    krb5_replay_data replay;
+    krb5_keyblock *tmp;
+
+    if (packet->length < 4)
+	/* either this, or the server is printing bad messages,
+	   or the caller passed in garbage */
+	return(KRB5KRB_AP_ERR_MODIFIED);
+
+    ptr = packet->data;
+
+    /* verify length */
+
+    plen = (*ptr++ & 0xff);
+    plen = (plen<<8) | (*ptr++ & 0xff);
+
+    if (plen != packet->length) 
+	{
+		/*
+		 * MS KDCs *may* send back a KRB_ERROR.  Although
+		 * not 100% correct via RFC3244, it's something
+		 * we can workaround here.
+		 */
+		if (krb5_is_krb_error(packet)) {
+
+			if ((ret = krb5_rd_error(context, packet, &krberror)))
+			return(ret);
+
+			if (krberror->e_data.data  == NULL) {
+				ret = ERROR_TABLE_BASE_krb5 + (krb5_error_code) krberror->error;
+				krb5_free_error(context, krberror);
+				return (ret);
+			}
+		}
+		else
+		{
+			return(KRB5KRB_AP_ERR_MODIFIED);
+		}
+	}
+	
+
+    /* verify version number */
+
+    vno = (*ptr++ & 0xff);
+    vno = (vno<<8) | (*ptr++ & 0xff);
+
+    if (vno != 1)
+	return(KRB5KDC_ERR_BAD_PVNO);
+
+    /* read, check ap-rep length */
+
+    ap_rep.length = (*ptr++ & 0xff);
+    ap_rep.length = (ap_rep.length<<8) | (*ptr++ & 0xff);
+
+    if (ptr + ap_rep.length >= packet->data + packet->length)
+	return(KRB5KRB_AP_ERR_MODIFIED);
+
+    if (ap_rep.length) {
+	/* verify ap_rep */
+	ap_rep.data = ptr;
+	ptr += ap_rep.length;
+
+	/*
+	 * Save send_subkey to later smash recv_subkey.
+	 */
+	ret = krb5_auth_con_getsendsubkey(context, auth_context, &tmp);
+	if (ret)
+	    return ret;
+
+	ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc);
+	if (ret) {
+	    krb5_free_keyblock(context, tmp);
+	    return(ret);
+	}
+
+	krb5_free_ap_rep_enc_part(context, ap_rep_enc);
+
+	/* extract and decrypt the result */
+
+	cipherresult.data = ptr;
+	cipherresult.length = (packet->data + packet->length) - ptr;
+
+	/*
+	 * Smash recv_subkey to be send_subkey, per spec.
+	 */
+	ret = krb5_auth_con_setrecvsubkey(context, auth_context, tmp);
+	krb5_free_keyblock(context, tmp);
+	if (ret)
+	    return ret;
+
+	ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
+			   &replay);
+
+	if (ret)
+	    return(ret);
+    } else {
+	cipherresult.data = ptr;
+	cipherresult.length = (packet->data + packet->length) - ptr;
+
+	if ((ret = krb5_rd_error(context, &cipherresult, &krberror)))
+	    return(ret);
+
+	clearresult = krberror->e_data;
+    }
+
+    if (clearresult.length < 2) {
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	goto cleanup;
+    }
+
+    ptr = clearresult.data;
+
+    *result_code = (*ptr++ & 0xff);
+    *result_code = (*result_code<<8) | (*ptr++ & 0xff);
+
+    if ((*result_code < KRB5_KPASSWD_SUCCESS) ||
+	(*result_code > KRB5_KPASSWD_INITIAL_FLAG_NEEDED)) {
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	goto cleanup;
+    }
+
+    /* all success replies should be authenticated/encrypted */
+
+    if ((ap_rep.length == 0) && (*result_code == KRB5_KPASSWD_SUCCESS)) {
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	goto cleanup;
+    }
+
+    result_data->length = (clearresult.data + clearresult.length) - ptr;
+
+    if (result_data->length) {
+	result_data->data = (char *) malloc(result_data->length);
+	if (result_data->data == NULL) {
+	    ret = ENOMEM;
+	    goto cleanup;
+	}
+	memcpy(result_data->data, ptr, result_data->length);
+    } else {
+	result_data->data = NULL;
+    }
+
+    ret = 0;
+
+cleanup:
+    if (ap_rep.length) {
+	krb5_xfree(clearresult.data);
+    } else {
+	krb5_free_error(context, krberror);
+    }
+
+    return(ret);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_chpw_result_code_string(krb5_context context, int result_code, char **code_string)
+{
+   switch (result_code) {
+   case KRB5_KPASSWD_MALFORMED:
+      *code_string = "Malformed request error";
+      break;
+   case KRB5_KPASSWD_HARDERROR:
+      *code_string = "Server error";
+      break;
+   case KRB5_KPASSWD_AUTHERROR:
+      *code_string = "Authentication error";
+      break;
+   case KRB5_KPASSWD_SOFTERROR:
+      *code_string = "Password change rejected";
+      break;
+   default:
+      *code_string = "Password change failed";
+      break;
+   }
+
+   return(0);
+}
+
+krb5_error_code 
+krb5int_mk_setpw_req(
+     krb5_context context,
+     krb5_auth_context auth_context,
+     krb5_data *ap_req,
+     krb5_principal targprinc,
+     char *passwd,
+     krb5_data *packet )
+{
+    krb5_error_code ret;
+    krb5_data	cipherpw;
+    krb5_data	*encoded_setpw;
+
+    char *ptr;
+
+     cipherpw.data = NULL;
+     cipherpw.length = 0;
+     
+    if ((ret = krb5_auth_con_setflags(context, auth_context,
+				      KRB5_AUTH_CONTEXT_DO_SEQUENCE)))
+		return(ret);
+
+    ret = encode_krb5_setpw_req(targprinc, passwd, &encoded_setpw);
+    if (ret) {
+	return ret;
+    }
+
+    if ( (ret = krb5_mk_priv(context, auth_context, encoded_setpw, &cipherpw, NULL)) != 0) {
+	krb5_free_data( context, encoded_setpw);
+	return(ret);
+    }
+    krb5_free_data( context, encoded_setpw);
+    
+
+    packet->length = 6 + ap_req->length + cipherpw.length;
+    packet->data = (char *) malloc(packet->length);
+    if (packet->data  == NULL) {
+	ret = ENOMEM;
+	goto cleanup;
+    }
+    ptr = packet->data;
+/*
+** build the packet -
+*/
+/* put in the length */
+    *ptr++ = (packet->length>>8) & 0xff;
+    *ptr++ = packet->length & 0xff;
+/* put in the version */
+    *ptr++ = (char)0xff;
+    *ptr++ = (char)0x80;
+/* the ap_req length is big endian */
+    *ptr++ = (ap_req->length>>8) & 0xff;
+    *ptr++ = ap_req->length & 0xff;
+/* put in the request data */
+    memcpy(ptr, ap_req->data, ap_req->length);
+    ptr += ap_req->length;
+/*
+** put in the "private" password data -
+*/
+    memcpy(ptr, cipherpw.data, cipherpw.length);
+    ret = 0;
+ cleanup:
+    if (cipherpw.data)
+	krb5_free_data_contents(context, &cipherpw);
+    if ((ret != 0) && packet->data) {
+	free( packet->data);
+	packet->data = NULL;
+    }
+    return ret;
+}
+
+krb5_error_code 
+krb5int_rd_setpw_rep( krb5_context context, krb5_auth_context auth_context, krb5_data *packet,
+     int *result_code, krb5_data *result_data )
+{
+    char *ptr;
+    unsigned int message_length, version_number;
+    krb5_data ap_rep;
+    krb5_ap_rep_enc_part *ap_rep_enc;
+    krb5_error_code ret;
+    krb5_data cipherresult;
+    krb5_data clearresult;
+    krb5_keyblock *tmpkey;
+/*
+** validate the packet length -
+*/
+    if (packet->length < 4)
+	return(KRB5KRB_AP_ERR_MODIFIED);
+
+    ptr = packet->data;
+
+/*
+** see if it is an error
+*/
+    if (krb5_is_krb_error(packet)) {
+	krb5_error *krberror;
+	if ((ret = krb5_rd_error(context, packet, &krberror)))
+	    return(ret);
+	if (krberror->e_data.data  == NULL) {
+	    ret = ERROR_TABLE_BASE_krb5 + (krb5_error_code) krberror->error;
+	    krb5_free_error(context, krberror);
+	    return (ret);
+	}
+	clearresult = krberror->e_data;
+	krberror->e_data.data  = NULL; /*So we can free it later*/
+	krberror->e_data.length = 0;
+	krb5_free_error(context, krberror);
+		
+    } else { /* Not an error*/
+
+/*
+** validate the message length -
+** length is big endian 
+*/
+	message_length = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+	ptr += 2;
+/*
+** make sure the message length and packet length agree -
+*/
+	if (message_length != packet->length)
+	    return(KRB5KRB_AP_ERR_MODIFIED);
+/*
+** get the version number -
+*/
+	version_number = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+	ptr += 2;
+/*
+** make sure we support the version returned -
+*/
+/*
+** set password version is 0xff80, change password version is 1
+*/
+	if (version_number != 1 && version_number != 0xff80)
+	    return(KRB5KDC_ERR_BAD_PVNO);
+/*
+** now fill in ap_rep with the reply -
+*/
+/*
+** get the reply length -
+*/
+	ap_rep.length = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+	ptr += 2;
+/*
+** validate ap_rep length agrees with the packet length -
+*/
+	if (ptr + ap_rep.length >= packet->data + packet->length)
+	    return(KRB5KRB_AP_ERR_MODIFIED);
+/*
+** if data was returned, set the ap_rep ptr -
+*/
+	if( ap_rep.length ) {
+	    ap_rep.data = ptr;
+	    ptr += ap_rep.length;
+
+	    /*
+	     * Save send_subkey to later smash recv_subkey.
+	     */
+	    ret = krb5_auth_con_getsendsubkey(context, auth_context, &tmpkey);
+	    if (ret)
+		return ret;
+
+	    ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc);
+	    if (ret) {
+		krb5_free_keyblock(context, tmpkey);
+		return(ret);
+	    }
+
+	    krb5_free_ap_rep_enc_part(context, ap_rep_enc);
+/*
+** now decrypt the result -
+*/
+	    cipherresult.data = ptr;
+	    cipherresult.length = (packet->data + packet->length) - ptr;
+
+	    /*
+	     * Smash recv_subkey to be send_subkey, per spec.
+	     */
+	    ret = krb5_auth_con_setrecvsubkey(context, auth_context, tmpkey);
+	    krb5_free_keyblock(context, tmpkey);
+	    if (ret)
+		return ret;
+
+	    ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
+			       NULL);
+	    if (ret)
+		return(ret);
+	} /*We got an ap_rep*/
+	else
+	    return (KRB5KRB_AP_ERR_MODIFIED);
+    } /*Response instead of error*/
+
+/*
+** validate the cleartext length 
+*/
+    if (clearresult.length < 2) {
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	goto cleanup;
+    }
+/*
+** now decode the result -
+*/
+    ptr = clearresult.data;
+
+    *result_code = (((ptr[0] << 8)&0xff) | (ptr[1]&0xff));
+    ptr += 2;
+
+/*
+** result code 5 is access denied
+*/
+    if ((*result_code < KRB5_KPASSWD_SUCCESS) || (*result_code > 5))
+    {
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	goto cleanup;
+    }
+/*
+** all success replies should be authenticated/encrypted
+*/
+    if( (ap_rep.length == 0) && (*result_code == KRB5_KPASSWD_SUCCESS) )
+    {
+	ret = KRB5KRB_AP_ERR_MODIFIED;
+	goto cleanup;
+    }
+
+    if (result_data) {
+	result_data->length = (clearresult.data + clearresult.length) - ptr;
+
+	if (result_data->length)
+	{
+	    result_data->data = (char *) malloc(result_data->length);
+	    if (result_data->data)
+		memcpy(result_data->data, ptr, result_data->length);
+	}
+	else
+	    result_data->data = NULL;
+    }
+    ret = 0;
+
+ cleanup:
+    krb5_free_data_contents(context, &clearresult);
+    return(ret);
+}
+
+krb5_error_code 
+krb5int_setpw_result_code_string( krb5_context context, int result_code, const char **code_string )
+{
+   switch (result_code)
+   {
+   case KRB5_KPASSWD_MALFORMED:
+      *code_string = "Malformed request error";
+      break;
+   case KRB5_KPASSWD_HARDERROR:
+      *code_string = "Server error";
+      break;
+   case KRB5_KPASSWD_AUTHERROR:
+      *code_string = "Authentication error";
+      break;
+   case KRB5_KPASSWD_SOFTERROR:
+      *code_string = "Password change rejected";
+      break;
+   case 5: /* access denied */
+      *code_string = "Access denied";
+      break;
+   case 6:	/* bad version */
+      *code_string = "Wrong protocol version";
+      break;
+   case 7: /* initial flag is needed */
+      *code_string = "Initial password required";
+      break;
+   case 0:
+	  *code_string = "Success";
+   default:
+      *code_string = "Password change failed";
+      break;
+   }
+
+   return(0);
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/cleanup.h b/krb5-1-6/src/lib/krb5/krb/cleanup.h
new file mode 100644
index 000000000..94b39f757
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/cleanup.h
@@ -0,0 +1,29 @@
+
+#ifndef KRB5_CLEANUP
+#define KRB5_CLEANUP
+
+struct cleanup {
+    void 		* arg;
+    void		(*func)(void *);
+};
+
+#define CLEANUP_INIT(x)							\
+    struct cleanup cleanup_data[x];					\
+    int cleanup_count = 0;		
+
+#define CLEANUP_PUSH(x, y)						\
+    cleanup_data[cleanup_count].arg = x;				\
+    cleanup_data[cleanup_count].func = y;				\
+    cleanup_count++;
+
+#define CLEANUP_POP(x)							\
+    if ((--cleanup_count) && x && (cleanup_data[cleanup_count].func)) 	\
+	cleanup_data[cleanup_count].func(cleanup_data[cleanup_count].arg); 
+	
+#define CLEANUP_DONE()							\
+    while(cleanup_count--) 						\
+	if (cleanup_data[cleanup_count].func)  				\
+	    cleanup_data[cleanup_count].func(cleanup_data[cleanup_count].arg); 
+    
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/krb/conv_creds.c b/krb5-1-6/src/lib/krb5/krb/conv_creds.c
new file mode 100644
index 000000000..68af73301
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/conv_creds.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "port-sockets.h"
+#include "socket-utils.h"
+
+#if defined(KRB5_KRB4_COMPAT) || defined(_WIN32) /* yuck */
+#include "kerberosIV/krb.h"
+
+#ifdef USE_CCAPI
+#include <CredentialsCache.h>
+#endif
+
+#define krb524_debug krb5int_krb524_debug
+int krb524_debug = 0;
+
+static krb5_error_code krb524_convert_creds_plain
+(krb5_context context, krb5_creds *v5creds, 
+		   CREDENTIALS *v4creds);
+
+static int decode_v4tkt
+	(struct ktext *v4tkt, char *buf, unsigned int *encoded_len);
+
+krb5_error_code KRB5_CALLCONV
+krb5_524_convert_creds(krb5_context context, krb5_creds *v5creds,
+		       CREDENTIALS *v4creds)
+{
+     krb5_error_code ret;
+     krb5_data reply;
+     char *p;
+     struct sockaddr_storage ss;
+     socklen_t slen = sizeof(ss);
+
+     ret = krb524_convert_creds_plain(context, v5creds, v4creds);
+     if (ret)
+	 return ret;
+
+     reply.data = NULL;
+     ret = krb5int_524_sendto_kdc(context, &v5creds->ticket,
+				  &v5creds->server->realm, &reply,
+				  ss2sa(&ss), &slen);
+     if (ret)
+	 return ret;
+
+#if TARGET_OS_MAC
+#ifdef USE_CCAPI
+     v4creds->stk_type = cc_v4_stk_des;
+#endif
+     if (slen == sizeof(struct sockaddr_in)
+	 && ss2sa(&ss)->sa_family == AF_INET) {
+	 v4creds->address = ss2sin(&ss)->sin_addr.s_addr;
+     }
+     /* Otherwise, leave it set to all-zero.  */
+#endif
+
+     p = reply.data;
+     ret = ntohl(*((krb5_error_code *) p));
+     p += sizeof(krb5_int32);
+     reply.length -= sizeof(krb5_int32);
+     if (ret)
+	 goto fail;
+
+     v4creds->kvno = ntohl(*((krb5_error_code *) p));
+     p += sizeof(krb5_int32);
+     reply.length -= sizeof(krb5_int32);
+     ret = decode_v4tkt(&v4creds->ticket_st, p, &reply.length);
+
+fail:
+     if (reply.data) 
+	 free(reply.data);
+     reply.data = NULL;
+     return ret;
+}
+
+static krb5_error_code
+krb524_convert_creds_plain(context, v5creds, v4creds)
+     krb5_context context;
+     krb5_creds *v5creds;
+     CREDENTIALS *v4creds;
+{
+     int ret;
+     krb5_timestamp endtime;
+     char dummy[REALM_SZ];
+     memset((char *) v4creds, 0, sizeof(CREDENTIALS));
+
+     if ((ret = krb5_524_conv_principal(context, v5creds->client,
+					v4creds->pname, v4creds->pinst,
+					dummy)))
+	 return ret;
+     if ((ret = krb5_524_conv_principal(context, v5creds->server,
+					v4creds->service, v4creds->instance,
+					v4creds->realm)))
+	 return ret;
+
+     /* Check enctype too */
+     if (v5creds->keyblock.length != sizeof(C_Block)) {
+	  if (krb524_debug)
+	       fprintf(stderr, "v5 session keyblock length %d != C_Block size %d\n",
+		       v5creds->keyblock.length,
+		       (int) sizeof(C_Block));
+	  return KRB524_BADKEY;
+     } else
+	  memcpy(v4creds->session, (char *) v5creds->keyblock.contents,
+		 sizeof(C_Block));
+
+     /* V4 has no concept of authtime or renew_till, so ignore them */
+     v4creds->issue_date = v5creds->times.starttime;
+     v4creds->lifetime = krb5int_krb_time_to_life(v5creds->times.starttime,
+						  v5creds->times.endtime);
+     endtime = krb5int_krb_life_to_time(v4creds->issue_date,
+					v4creds->lifetime);
+     /*
+      * Adjust start time backwards to deal with rounding up in
+      * krb_time_to_life(), to match code on server side.
+      */
+     if (endtime > v5creds->times.endtime)
+	 v4creds->issue_date -= endtime - v5creds->times.endtime;
+
+     return 0;
+}
+
+/* this used to be krb524/encode.c, under same copyright as above */
+/*
+ * I'm sure that this is reinventing the wheel, but I don't know where
+ * the wheel is hidden.
+ */
+
+int  encode_v4tkt (KTEXT_ST *, char *, unsigned int *);
+static int encode_bytes (char **, int *, char *, unsigned int),
+    encode_int32 (char **, int *, krb5_int32 *);
+
+static int decode_bytes (char **, int *, char *, unsigned int),
+    decode_int32 (char **, int *, krb5_int32 *);
+
+static int encode_bytes(out, outlen, in, len)
+     char **out;
+     int *outlen;
+     char *in;
+     unsigned int len;
+{
+     if (len > *outlen)
+	  return KRB524_ENCFULL;
+     memcpy(*out, in, len);
+     *out += len;
+     *outlen -= len;
+     return 0;
+}
+
+static int encode_int32(out, outlen, v)
+     char **out;
+     int *outlen;
+     krb5_int32 *v;
+{
+     krb5_int32 nv; /* Must be 4 bytes */
+
+     nv = htonl(*v);
+     return encode_bytes(out, outlen, (char *) &nv, sizeof(nv));
+}
+
+int krb5int_encode_v4tkt(v4tkt, buf, encoded_len)
+     KTEXT_ST *v4tkt;
+     char *buf;
+     unsigned int *encoded_len;
+{
+     int buflen, ret;
+     krb5_int32 temp;
+
+     buflen = *encoded_len;
+
+     if (v4tkt->length < MAX_KTXT_LEN)
+	  memset(v4tkt->dat + v4tkt->length, 0, 
+		 (unsigned int) (MAX_KTXT_LEN - v4tkt->length));
+     temp = v4tkt->length;
+     if ((ret = encode_int32(&buf, &buflen, &temp)))
+	  return ret;
+     if ((ret = encode_bytes(&buf, &buflen, (char *)v4tkt->dat, MAX_KTXT_LEN)))
+	  return ret;
+     temp = v4tkt->mbz;
+     if ((ret = encode_int32(&buf, &buflen, &temp)))
+	  return ret;
+
+     *encoded_len -= buflen;
+     return 0;
+}
+
+/* decode functions */
+
+static int decode_bytes(out, outlen, in, len)
+     char **out;
+     int *outlen;
+     char *in; 
+     unsigned int len;
+{
+     if (len > *outlen)
+	  return KRB524_DECEMPTY;
+     memcpy(in, *out, len);
+     *out += len;
+     *outlen -= len;
+     return 0;
+}
+
+static int decode_int32(out, outlen, v)
+     char **out;
+     int *outlen;
+     krb5_int32 *v;
+{
+     int ret;
+     krb5_int32 nv; /* Must be four bytes */
+
+     if ((ret = decode_bytes(out, outlen, (char *) &nv, sizeof(nv))))
+	  return ret;
+     *v = ntohl(nv);
+     return 0;
+}
+
+static int decode_v4tkt(v4tkt, buf, encoded_len)
+     KTEXT_ST *v4tkt;
+     char *buf;
+     unsigned int *encoded_len;
+{
+     int buflen, ret;
+     krb5_int32 temp;
+
+     buflen = *encoded_len;
+     if ((ret = decode_int32(&buf, &buflen, &temp)))
+	  return ret;
+     v4tkt->length = temp;
+     if ((ret = decode_bytes(&buf, &buflen, (char *)v4tkt->dat, MAX_KTXT_LEN)))
+	  return ret;
+     if ((ret = decode_int32(&buf, &buflen, &temp)))
+	  return ret;
+     v4tkt->mbz = temp;
+     *encoded_len -= buflen;
+     return 0;
+}
+
+#else /* no krb4 compat */
+
+krb5_error_code KRB5_CALLCONV
+krb5_524_convert_creds(krb5_context context, krb5_creds *v5creds,
+		       struct credentials *v4creds)
+{
+    return KRB524_KRB4_DISABLED;
+}
+
+#endif
+
+/* These may be needed for object-level backwards compatibility on Mac
+   OS and UNIX, but Windows should be okay.  */
+#ifndef _WIN32
+#undef krb524_convert_creds_kdc
+#undef krb524_init_ets
+
+/* Declarations ahead of the definitions will suppress some gcc
+   warnings.  */
+void KRB5_CALLCONV krb524_init_ets (void);
+krb5_error_code KRB5_CALLCONV
+krb524_convert_creds_kdc(krb5_context context, krb5_creds *v5creds,
+			 struct credentials *v4creds);
+
+krb5_error_code KRB5_CALLCONV
+krb524_convert_creds_kdc(krb5_context context, krb5_creds *v5creds,
+			 struct credentials *v4creds)
+{
+    return krb5_524_convert_creds(context, v5creds, v4creds);
+}
+
+void KRB5_CALLCONV krb524_init_ets ()
+{
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/krb/conv_princ.c b/krb5-1-6/src/lib/krb5/krb/conv_princ.c
new file mode 100644
index 000000000..b0abae360
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/conv_princ.c
@@ -0,0 +1,354 @@
+/*
+ * lib/krb5/krb/conv_princ.c
+ *
+ * Copyright 1992 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Build a principal from a V4 specification, or separate a V5
+ * principal into name, instance, and realm.
+ * 
+ * NOTE: This is highly site specific, and is only really necessary
+ * for sites who need to convert from V4 to V5.  It is used by both
+ * the KDC and the kdb5_convert program.  Since its use is highly
+ * specialized, the necesary information is just going to be
+ * hard-coded in this file.
+ */
+
+#include "k5-int.h"
+#include <string.h>
+#include <ctype.h>
+
+/* The maximum sizes for V4 aname, realm, sname, and instance +1 */
+/* Taken from krb.h */
+#define 	ANAME_SZ	40
+#define		REALM_SZ	40
+#define		SNAME_SZ	40
+#define		INST_SZ		40
+
+struct krb_convert {
+    char		*v4_str;
+    char		*v5_str;
+    unsigned int	flags : 8;
+    unsigned int	len : 8;
+};
+
+#define DO_REALM_CONVERSION 0x00000001
+
+/*
+ * Kadmin doesn't do realm conversion because it's currently
+ * kadmin/REALM.NAME.  Zephyr doesn't because it's just zephyr/zephyr.
+ *
+ * "Realm conversion" is a bit of a misnomer; really, the v5 name is
+ * using a FQDN or something that looks like it, where the v4 name is
+ * just using the first label.  Sometimes that second principal name
+ * component is a hostname, sometimes the realm name, sometimes it's
+ * neither.
+ *
+ * This list should probably be more configurable, and more than
+ * likely on a per-realm basis, so locally-defined services can be
+ * added, or not.
+ */
+static const struct krb_convert sconv_list[] = {
+    /* Realm conversion, Change service name */
+#define RC(V5NAME,V4NAME) { V5NAME, V4NAME, DO_REALM_CONVERSION, sizeof(V5NAME)-1 }
+    /* Realm conversion */
+#define R(NAME)		{ NAME, NAME, DO_REALM_CONVERSION, sizeof(NAME)-1 }
+    /* No Realm conversion */
+#define NR(NAME)	{ NAME, NAME, 0, sizeof(NAME)-1 }
+
+    NR("kadmin"),
+    RC("rcmd", "host"),
+    R("discuss"),
+    R("rvdsrv"),
+    R("sample"),
+    R("olc"),
+    R("pop"),
+    R("sis"),
+    R("rfs"),
+    R("imap"),
+    R("ftp"),
+    R("ecat"),
+    R("daemon"),
+    R("gnats"),
+    R("moira"),
+    R("prms"),
+    R("mandarin"),
+    R("register"),
+    R("changepw"),
+    R("sms"),
+    R("afpserver"),
+    R("gdss"),
+    R("news"),
+    R("abs"),
+    R("nfs"),
+    R("tftp"),
+    NR("zephyr"),
+    R("http"),
+    R("khttp"),
+    R("pgpsigner"),
+    R("irc"),
+    R("mandarin-agent"),
+    R("write"),
+    R("palladium"),
+    {0, 0, 0, 0},
+#undef R
+#undef RC
+#undef NR
+};
+
+/*
+ * char *strnchr(s, c, n)
+ *   char *s;
+ *   char c;
+ *   unsigned int n;
+ *
+ * returns a pointer to the first occurrence of character c in the
+ * string s, or a NULL pointer if c does not occur in in the string;
+ * however, at most the first n characters will be considered.
+ *
+ * This falls in the "should have been in the ANSI C library"
+ * category. :-)
+ */
+static char *strnchr(register char *s, register char c, 
+		     register unsigned int n)
+{
+     if (n < 1) 
+	  return 0;
+     
+     while (n-- && *s) {
+	  if (*s == c)
+	       return s;
+	  s++;
+     }
+     return 0;
+}
+
+
+/* XXX This calls for a new error code */
+#define KRB5_INVALID_PRINCIPAL KRB5_LNAME_BADFORMAT
+
+krb5_error_code KRB5_CALLCONV
+krb5_524_conv_principal(krb5_context context, krb5_const_principal princ,
+			char *name, char *inst, char *realm)
+{
+     const struct krb_convert *p;
+     const krb5_data *compo;
+     char *c, *tmp_realm, *tmp_prealm;
+     unsigned int tmp_realm_len;
+     int retval; 
+
+     *name = *inst = '\0';
+     switch (krb5_princ_size(context, princ)) {
+     case 2:
+	  /* Check if this principal is listed in the table */
+	  compo = krb5_princ_component(context, princ, 0);
+	  p = sconv_list;
+	  while (p->v4_str) {
+	       if (p->len == compo->length
+		   && memcmp(p->v5_str, compo->data, compo->length) == 0) {
+		   /*
+		    * It is, so set the new name now, and chop off
+		    * instance's domain name if requested.
+		    */
+		   if (strlen (p->v4_str) > ANAME_SZ - 1)
+		       return KRB5_INVALID_PRINCIPAL;
+		   strcpy(name, p->v4_str);
+		   if (p->flags & DO_REALM_CONVERSION) {
+		       compo = krb5_princ_component(context, princ, 1);
+		       c = strnchr(compo->data, '.', compo->length);
+		       if (!c || (c - compo->data) >= INST_SZ - 1)
+			   return KRB5_INVALID_PRINCIPAL;
+		       memcpy(inst, compo->data, (size_t) (c - compo->data));
+		       inst[c - compo->data] = '\0';
+		   }
+		   break;
+	       }
+	       p++;
+	  }
+	  /* If inst isn't set, the service isn't listed in the table, */
+	  /* so just copy it. */
+	  if (*inst == '\0') {
+	       compo = krb5_princ_component(context, princ, 1);
+	       if (compo->length >= INST_SZ - 1)
+		    return KRB5_INVALID_PRINCIPAL;
+	       memcpy(inst, compo->data, compo->length);
+	       inst[compo->length] = '\0';
+	  }
+	  /* fall through */
+     case 1:
+	  /* name may have been set above; otherwise, just copy it */
+	  if (*name == '\0') {
+	       compo = krb5_princ_component(context, princ, 0);
+	       if (compo->length >= ANAME_SZ)
+		    return KRB5_INVALID_PRINCIPAL;
+	       memcpy(name, compo->data, compo->length);
+	       name[compo->length] = '\0';
+	  }
+	  break;
+     default:
+	  return KRB5_INVALID_PRINCIPAL;
+     }
+
+     compo = krb5_princ_realm(context, princ);
+
+     tmp_prealm = malloc(compo->length + 1);
+     if (tmp_prealm == NULL)
+	 return ENOMEM;
+     strncpy(tmp_prealm, compo->data, compo->length);
+     tmp_prealm[compo->length] = '\0';
+
+     /* Ask for v4_realm corresponding to 
+	krb5 principal realm from krb5.conf realms stanza */
+
+     if (context->profile == 0)
+       return KRB5_CONFIG_CANTOPEN;
+     retval = profile_get_string(context->profile, "realms",
+				 tmp_prealm, "v4_realm", 0,
+				 &tmp_realm);
+     free(tmp_prealm);
+     if (retval) { 
+	 return retval;
+     } else {
+	 if (tmp_realm == 0) {
+	     if (compo->length > REALM_SZ - 1)
+		 return KRB5_INVALID_PRINCIPAL;
+	     strncpy(realm, compo->data, compo->length);
+	     realm[compo->length] = '\0';
+	 } else {
+	     tmp_realm_len =  strlen(tmp_realm);
+	     if (tmp_realm_len > REALM_SZ - 1)
+		 return KRB5_INVALID_PRINCIPAL;
+	     strncpy(realm, tmp_realm, tmp_realm_len);
+	     realm[tmp_realm_len] = '\0';
+	     profile_release_string(tmp_realm);
+	 }
+     }
+     return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_425_conv_principal(krb5_context context, const char *name,
+			const char *instance, const char *realm,
+			krb5_principal *princ)
+{
+     const struct krb_convert *p;
+     char buf[256];		/* V4 instances are limited to 40 characters */
+     krb5_error_code retval;
+     char *domain, *cp;
+     char **full_name = 0;
+     const char *names[5], *names2[2];
+     void*	iterator = NULL;
+     char** v4realms = NULL;
+     char* realm_name = NULL;
+     char* dummy_value = NULL;
+     
+     /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm
+        To do that, iterate over all the realms in the config file, looking for a matching 
+        v4_realm line */
+     names2 [0] = "realms";
+     names2 [1] = NULL;
+     retval = profile_iterator_create (context -> profile, names2, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator);
+     while (retval == 0) {
+     	retval = profile_iterator (&iterator, &realm_name, &dummy_value);
+     	if ((retval == 0) && (realm_name != NULL)) {
+     		names [0] = "realms";
+     		names [1] = realm_name;
+     		names [2] = "v4_realm";
+     		names [3] = NULL;
+
+     		retval = profile_get_values (context -> profile, names, &v4realms);
+     		if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) {
+     			realm = realm_name;
+     			break;
+     		} else if (retval == PROF_NO_RELATION) {
+     			/* If it's not found, just keep going */
+     			retval = 0;
+     		}
+     	} else if ((retval == 0) && (realm_name == NULL)) {
+     		break;
+     	}
+	if (v4realms != NULL) {
+	        profile_free_list(v4realms);
+		v4realms = NULL;
+	}
+     	if (realm_name != NULL) {
+     		profile_release_string (realm_name);
+     		realm_name = NULL;
+     	}
+     	if (dummy_value != NULL) {
+     		profile_release_string (dummy_value);
+     		dummy_value = NULL;
+     	}
+     }
+     
+     if (instance) {
+	  if (instance[0] == '\0') {
+	       instance = 0;
+	       goto not_service;
+	  }
+	  p = sconv_list;
+	  while (1) {
+	       if (!p->v4_str)
+		    goto not_service;
+	       if (!strcmp(p->v4_str, name))
+		    break;
+	       p++;
+	  }
+	  name = p->v5_str;
+	  if ((p->flags & DO_REALM_CONVERSION) && !strchr(instance, '.')) {
+	      names[0] = "realms";
+	      names[1] = realm;
+	      names[2] = "v4_instance_convert";
+	      names[3] = instance;
+	      names[4] = 0;
+	      retval = profile_get_values(context->profile, names, &full_name);
+	      if (retval == 0 && full_name && full_name[0]) {
+		  instance = full_name[0];
+	      } else {
+		  strncpy(buf, instance, sizeof(buf));
+		  buf[sizeof(buf) - 1] = '\0';
+		  retval = krb5_get_realm_domain(context, realm, &domain);
+		  if (retval)
+		      return retval;
+		  if (domain) {
+		      for (cp = domain; *cp; cp++)
+			  if (isupper((unsigned char) (*cp)))
+			      *cp = tolower((unsigned char) *cp);
+		      strncat(buf, ".", sizeof(buf) - 1 - strlen(buf));
+		      strncat(buf, domain, sizeof(buf) - 1 - strlen(buf));
+		      krb5_xfree(domain);
+		  }
+		  instance = buf;
+	      }
+	  }
+     }
+     
+not_service:
+     retval = krb5_build_principal(context, princ, strlen(realm), realm, name,
+				   instance, NULL);
+     if (iterator) profile_iterator_free (&iterator);
+     if (full_name) profile_free_list(full_name);
+     if (v4realms) profile_free_list(v4realms);
+     if (realm_name) profile_release_string (realm_name);
+     if (dummy_value) profile_release_string (dummy_value);
+     return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_addrs.c b/krb5-1-6/src/lib/krb5/krb/copy_addrs.c
new file mode 100644
index 000000000..28f19facc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_addrs.c
@@ -0,0 +1,139 @@
+/*
+ * lib/krb5/krb/copy_addrs.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_addresses()
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_copy_addr(krb5_context context, const krb5_address *inad, krb5_address **outad)
+{
+    krb5_address *tmpad;
+
+    if (!(tmpad = (krb5_address *)malloc(sizeof(*tmpad))))
+	return ENOMEM;
+    *tmpad = *inad;
+    if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
+	krb5_xfree(tmpad);
+	return ENOMEM;
+    }
+    memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length);
+    *outad = tmpad;
+    return 0;
+}
+
+/*
+ * Copy an address array, with fresh allocation.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_copy_addresses(krb5_context context, krb5_address *const *inaddr, krb5_address ***outaddr)
+{
+    krb5_error_code retval;
+    krb5_address ** tempaddr;
+    register unsigned int nelems = 0;
+
+    if (!inaddr) {
+	    *outaddr = 0;
+	    return 0;
+    }
+    
+    while (inaddr[nelems]) nelems++;
+
+    /* one more for a null terminated list */
+    if (!(tempaddr = (krb5_address **) calloc(nelems+1, sizeof(*tempaddr))))
+	return ENOMEM;
+
+    for (nelems = 0; inaddr[nelems]; nelems++) {
+	retval = krb5_copy_addr(context, inaddr[nelems], &tempaddr[nelems]);
+        if (retval) {
+	    krb5_free_addresses(context, tempaddr);
+	    return retval;
+	}
+    }
+
+    *outaddr = tempaddr;
+    return 0;
+}
+
+#if 0
+/*
+ * Append an address array, to another address array, with fresh allocation.
+ * Note that this function may change the value of *outaddr even if it
+ * returns failure, but it will not change the contents of the list.
+ */
+krb5_error_code
+krb5_append_addresses(context, inaddr, outaddr)
+    krb5_context context;
+	krb5_address * const * inaddr;
+	krb5_address ***outaddr;
+{
+    krb5_error_code retval;
+    krb5_address ** tempaddr;
+    krb5_address ** tempaddr2;
+    register unsigned int nelems = 0;
+    register int norigelems = 0;
+
+    if (!inaddr)
+	return 0;
+
+    tempaddr2 = *outaddr;
+
+    while (inaddr[nelems]) nelems++;
+    while (tempaddr2[norigelems]) norigelems++;
+
+    tempaddr = (krb5_address **) realloc((char *)*outaddr,
+		       (nelems + norigelems + 1) * sizeof(*tempaddr));
+    if (!tempaddr)
+	return ENOMEM;
+
+    /* The old storage has been freed.  */
+    *outaddr = tempaddr;
+
+
+    for (nelems = 0; inaddr[nelems]; nelems++) {
+	retval = krb5_copy_addr(context, inaddr[nelems],
+				&tempaddr[norigelems + nelems]);
+	if (retval)
+	    goto cleanup;
+    }
+
+    tempaddr[norigelems + nelems] = 0;
+    return 0;
+
+  cleanup:
+    while (--nelems >= 0)
+	krb5_free_address(context, tempaddr[norigelems + nelems]);
+
+    /* Try to allocate a smaller amount of memory for *outaddr.  */
+    tempaddr = (krb5_address **) realloc((char *)tempaddr,
+					 (norigelems + 1) * sizeof(*tempaddr));
+    if (tempaddr)
+	*outaddr = tempaddr;
+    return retval;
+}
+#endif
+
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_athctr.c b/krb5-1-6/src/lib/krb5/krb/copy_athctr.c
new file mode 100644
index 000000000..2694776c2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_athctr.c
@@ -0,0 +1,81 @@
+/*
+ * lib/krb5/krb/copy_athctr.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_authenticator()
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, krb5_authenticator **authto)
+{
+    krb5_error_code retval;
+    krb5_authenticator *tempto;
+
+    if (!(tempto = (krb5_authenticator *)malloc(sizeof(*tempto))))
+	return ENOMEM;
+    *tempto = *authfrom;
+
+    retval = krb5_copy_principal(context, authfrom->client, &tempto->client);
+    if (retval) {
+	krb5_xfree(tempto);
+	return retval;
+    }
+    
+    if (authfrom->checksum &&
+	(retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) {
+	    krb5_free_principal(context, tempto->client);    
+	    krb5_xfree(tempto);
+	    return retval;
+    }
+    
+    if (authfrom->subkey) {
+	    retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey);
+	    if (retval) {
+		    krb5_xfree(tempto->subkey);
+		    krb5_free_checksum(context, tempto->checksum);
+		    krb5_free_principal(context, tempto->client);    
+		    krb5_xfree(tempto);
+		    return retval;
+	    }
+    }
+    
+    if (authfrom->authorization_data) {
+		retval = krb5_copy_authdata(context, authfrom->authorization_data,
+				    &tempto->authorization_data);
+		if (retval) {
+		    krb5_xfree(tempto->subkey);
+		    krb5_free_checksum(context, tempto->checksum);
+		    krb5_free_principal(context, tempto->client);    
+		    krb5_free_authdata(context, tempto->authorization_data);
+		    krb5_xfree(tempto);
+		    return retval;
+		}
+    }
+
+    *authto = tempto;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_auth.c b/krb5-1-6/src/lib/krb5/krb/copy_auth.c
new file mode 100644
index 000000000..9c978cb6b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_auth.c
@@ -0,0 +1,82 @@
+/*
+ * lib/krb5/krb/copy_auth.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_authdata()
+ */
+
+#include "k5-int.h"
+
+static krb5_error_code
+krb5_copy_authdatum(krb5_context context, const krb5_authdata *inad, krb5_authdata **outad)
+{
+    krb5_authdata *tmpad;
+
+    if (!(tmpad = (krb5_authdata *)malloc(sizeof(*tmpad))))
+	return ENOMEM;
+    *tmpad = *inad;
+    if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
+	krb5_xfree(tmpad);
+	return ENOMEM;
+    }
+    memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length);
+    *outad = tmpad;
+    return 0;
+}
+
+/*
+ * Copy an authdata array, with fresh allocation.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_copy_authdata(krb5_context context, krb5_authdata *const *inauthdat, krb5_authdata ***outauthdat)
+{
+    krb5_error_code retval;
+    krb5_authdata ** tempauthdat;
+    register unsigned int nelems = 0;
+
+    if (!inauthdat) {
+	    *outauthdat = 0;
+	    return 0;
+    }
+
+    while (inauthdat[nelems]) nelems++;
+
+    /* one more for a null terminated list */
+    if (!(tempauthdat = (krb5_authdata **) calloc(nelems+1,
+						  sizeof(*tempauthdat))))
+	return ENOMEM;
+
+    for (nelems = 0; inauthdat[nelems]; nelems++) {
+	retval = krb5_copy_authdatum(context, inauthdat[nelems],
+				     &tempauthdat[nelems]);
+	if (retval) {
+	    krb5_free_authdata(context, tempauthdat);
+	    return retval;
+	}
+    }
+
+    *outauthdat = tempauthdat;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_cksum.c b/krb5-1-6/src/lib/krb5/krb/copy_cksum.c
new file mode 100644
index 000000000..ce7eb7aa7
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_cksum.c
@@ -0,0 +1,51 @@
+/*
+ * lib/krb5/krb/copy_cksum.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_checksum()
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_copy_checksum(krb5_context context, const krb5_checksum *ckfrom, krb5_checksum **ckto)
+{
+    krb5_checksum *tempto;
+
+    if (!(tempto = (krb5_checksum *)malloc(sizeof(*tempto))))
+	return ENOMEM;
+    *tempto = *ckfrom;
+
+    if (!(tempto->contents =
+	  (krb5_octet *)malloc(tempto->length))) {
+	krb5_xfree(tempto);
+	return ENOMEM;
+    }
+    memcpy((char *) tempto->contents, (char *) ckfrom->contents,
+	   ckfrom->length);
+
+    *ckto = tempto;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_creds.c b/krb5-1-6/src/lib/krb5/krb/copy_creds.c
new file mode 100644
index 000000000..9f1429c08
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_creds.c
@@ -0,0 +1,94 @@
+/*
+ * lib/krb5/krb/copy_creds.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_cred()
+ */
+
+#include "k5-int.h"
+
+/*
+ * Copy credentials, allocating fresh storage where needed.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred)
+{
+    krb5_creds *tempcred;
+    krb5_error_code retval;
+    krb5_data *scratch;
+
+    if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred))))
+	return ENOMEM;
+
+    *tempcred = *incred;
+    retval = krb5_copy_principal(context, incred->client, &tempcred->client);
+    if (retval)
+	goto cleanlast;
+    retval = krb5_copy_principal(context, incred->server, &tempcred->server);
+    if (retval)
+	goto cleanclient;
+    retval = krb5_copy_keyblock_contents(context, &incred->keyblock,
+					 &tempcred->keyblock);
+    if (retval)
+	goto cleanserver;
+    retval = krb5_copy_addresses(context, incred->addresses, &tempcred->addresses);
+    if (retval)
+	goto cleanblock;
+    retval = krb5_copy_data(context, &incred->ticket, &scratch);
+    if (retval)
+	goto cleanaddrs;
+    tempcred->ticket = *scratch;
+    krb5_xfree(scratch);
+    retval = krb5_copy_data(context, &incred->second_ticket, &scratch);
+    if (retval)
+	goto cleanticket;
+
+    tempcred->second_ticket = *scratch;
+    krb5_xfree(scratch);
+
+    retval = krb5_copy_authdata(context, incred->authdata,&tempcred->authdata);
+    if (retval)
+        goto clearticket;
+
+    *outcred = tempcred;
+    return 0;
+
+ clearticket:    
+    memset(tempcred->ticket.data,0,tempcred->ticket.length);
+ cleanticket:
+    free(tempcred->ticket.data);
+ cleanaddrs:
+    krb5_free_addresses(context, tempcred->addresses);
+ cleanblock:
+    krb5_xfree(tempcred->keyblock.contents);
+ cleanserver:
+    krb5_free_principal(context, tempcred->server);
+ cleanclient:
+    krb5_free_principal(context, tempcred->client);
+ cleanlast:
+    krb5_xfree(tempcred);
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_data.c b/krb5-1-6/src/lib/krb5/krb/copy_data.c
new file mode 100644
index 000000000..aed2e863b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_data.c
@@ -0,0 +1,80 @@
+/*
+ * lib/krb5/krb/copy_data.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_data()
+ */
+
+#include "k5-int.h"
+
+/*
+ * Copy a data structure, with fresh allocation.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_copy_data(krb5_context context, const krb5_data *indata, krb5_data **outdata)
+{
+    krb5_data *tempdata;
+
+    if (!indata) {
+	*outdata = 0;
+	return 0;
+    }
+    
+    if (!(tempdata = (krb5_data *)malloc(sizeof(*tempdata))))
+	return ENOMEM;
+
+    tempdata->length = indata->length;
+    if (tempdata->length) {
+	if (!(tempdata->data = malloc(tempdata->length))) {
+	    krb5_xfree(tempdata);
+	    return ENOMEM;
+	}
+	memcpy((char *)tempdata->data, (char *)indata->data, tempdata->length);
+    } else
+	tempdata->data = 0;
+    tempdata->magic = KV5M_DATA;
+    *outdata = tempdata;
+    return 0;
+}
+
+krb5_error_code 
+krb5int_copy_data_contents(krb5_context context, const krb5_data *indata, krb5_data *outdata)
+{
+    if (!indata) {
+	return EINVAL;
+    }
+
+    outdata->length = indata->length;
+    if (outdata->length) {
+	if (!(outdata->data = malloc(outdata->length))) {
+	    return ENOMEM;
+	}
+	memcpy((char *)outdata->data, (char *)indata->data, outdata->length);
+    } else
+	outdata->data = 0;
+    outdata->magic = KV5M_DATA;
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_key.c b/krb5-1-6/src/lib/krb5/krb/copy_key.c
new file mode 100644
index 000000000..1bb04c199
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_key.c
@@ -0,0 +1,51 @@
+/*
+ * lib/krb5/krb/copy_key.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_keyblock()
+ */
+
+#include "k5-int.h"
+
+/*
+ * Copy a keyblock, including alloc'ed storage.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_copy_keyblock(krb5_context context, const krb5_keyblock *from, krb5_keyblock **to)
+{
+	krb5_keyblock	*new_key;
+
+	if (!(new_key = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))))
+		return ENOMEM;
+	*new_key = *from;
+	if (!(new_key->contents = (krb5_octet *)malloc(new_key->length))) {
+		krb5_xfree(new_key);
+		return(ENOMEM);
+	}
+	memcpy((char *)new_key->contents, (char *)from->contents,
+	       new_key->length);
+	*to = new_key;
+	return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_princ.c b/krb5-1-6/src/lib/krb5/krb/copy_princ.c
new file mode 100644
index 000000000..85dc816ad
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_princ.c
@@ -0,0 +1,89 @@
+/*
+ * lib/krb5/krb/copy_princ.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_principal()
+ */
+
+#include "k5-int.h"
+
+/*
+ * Copy a principal structure, with fresh allocation.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc)
+{
+    register krb5_principal tempprinc;
+    register int i, nelems;
+
+    tempprinc = (krb5_principal)malloc(sizeof(krb5_principal_data));
+
+    if (tempprinc == 0)
+	return ENOMEM;
+
+    *tempprinc = *inprinc;
+
+    nelems = (int) krb5_princ_size(context, inprinc);
+    tempprinc->data = malloc(nelems * sizeof(krb5_data));
+
+    if (tempprinc->data == 0) {
+	free((char *)tempprinc);
+	return ENOMEM;
+    }
+
+    for (i = 0; i < nelems; i++) {
+	unsigned int len = krb5_princ_component(context, inprinc, i)->length;
+	krb5_princ_component(context, tempprinc, i)->length = len;
+        if (len) {
+            if (((krb5_princ_component(context, tempprinc, i)->data =
+                   malloc(len)) == 0)) {
+                while (--i >= 0)
+                    free(krb5_princ_component(context, tempprinc, i)->data);
+                free (tempprinc->data);
+                free (tempprinc);
+                return ENOMEM;
+            }
+	    memcpy(krb5_princ_component(context, tempprinc, i)->data,
+		   krb5_princ_component(context, inprinc, i)->data, len);
+        } else
+            krb5_princ_component(context, tempprinc, i)->data = 0;
+    }
+
+    tempprinc->realm.data =
+        malloc((tempprinc->realm.length = inprinc->realm.length) + 1);
+    if (!tempprinc->realm.data) {
+        for (i = 0; i < nelems; i++)
+	    free(krb5_princ_component(context, tempprinc, i)->data);
+	free(tempprinc->data);
+	free(tempprinc);
+	return ENOMEM;
+    }
+    memcpy(tempprinc->realm.data, inprinc->realm.data,
+	   inprinc->realm.length);
+    tempprinc->realm.data[tempprinc->realm.length] = 0;
+
+    *outprinc = tempprinc;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/copy_tick.c b/krb5-1-6/src/lib/krb5/krb/copy_tick.c
new file mode 100644
index 000000000..43268e50f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/copy_tick.c
@@ -0,0 +1,126 @@
+/*
+ * lib/krb5/krb/copy_tick.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_ticket()
+ */
+
+#include "k5-int.h"
+
+static krb5_error_code
+krb5_copy_enc_tkt_part(krb5_context context, const krb5_enc_tkt_part *partfrom, krb5_enc_tkt_part **partto)
+{
+    krb5_error_code retval;
+    krb5_enc_tkt_part *tempto;
+
+    if (!(tempto = (krb5_enc_tkt_part *)malloc(sizeof(*tempto))))
+	return ENOMEM;
+    *tempto = *partfrom;
+    retval = krb5_copy_keyblock(context, partfrom->session,
+				&tempto->session);
+    if (retval) {
+	krb5_xfree(tempto);
+	return retval;
+    }
+    retval = krb5_copy_principal(context, partfrom->client, &tempto->client);
+    if (retval) {
+	krb5_free_keyblock(context, tempto->session);
+	krb5_xfree(tempto);
+	return retval;
+    }
+    tempto->transited = partfrom->transited;
+    if (tempto->transited.tr_contents.length == 0) {
+	tempto->transited.tr_contents.data = 0;
+    } else {
+	tempto->transited.tr_contents.data =
+	  malloc(partfrom->transited.tr_contents.length);
+	if (!tempto->transited.tr_contents.data) {
+	    krb5_free_principal(context, tempto->client);
+	    krb5_free_keyblock(context, tempto->session);
+	    krb5_xfree(tempto);
+	    return ENOMEM;
+	}
+	memcpy((char *)tempto->transited.tr_contents.data,
+	       (char *)partfrom->transited.tr_contents.data,
+	       partfrom->transited.tr_contents.length);
+    }
+
+    retval = krb5_copy_addresses(context, partfrom->caddrs, &tempto->caddrs);
+    if (retval) {
+	krb5_xfree(tempto->transited.tr_contents.data);
+	krb5_free_principal(context, tempto->client);
+	krb5_free_keyblock(context, tempto->session);
+	krb5_xfree(tempto);
+	return retval;
+    }
+    if (partfrom->authorization_data) {
+	retval = krb5_copy_authdata(context, partfrom->authorization_data,
+				    &tempto->authorization_data);
+	if (retval) {
+	    krb5_free_addresses(context, tempto->caddrs);
+	    krb5_xfree(tempto->transited.tr_contents.data);
+	    krb5_free_principal(context, tempto->client);
+	    krb5_free_keyblock(context, tempto->session);
+	    krb5_xfree(tempto);
+	    return retval;
+	}
+    }
+    *partto = tempto;
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_copy_ticket(krb5_context context, const krb5_ticket *from, krb5_ticket **pto)
+{
+    krb5_error_code retval;
+    krb5_ticket *tempto;
+    krb5_data *scratch;
+
+    if (!(tempto = (krb5_ticket *)malloc(sizeof(*tempto))))
+	return ENOMEM;
+    *tempto = *from;
+    retval = krb5_copy_principal(context, from->server, &tempto->server);
+    if (retval) {
+	krb5_xfree(tempto);
+	return retval;
+    }
+    retval = krb5_copy_data(context, &from->enc_part.ciphertext, &scratch);
+    if (retval) {
+	krb5_free_principal(context, tempto->server);
+	krb5_xfree(tempto);
+	return retval;
+    }
+    tempto->enc_part.ciphertext = *scratch;
+    krb5_xfree(scratch);
+    retval = krb5_copy_enc_tkt_part(context, from->enc_part2, &tempto->enc_part2);
+    if (retval) {
+	krb5_xfree(tempto->enc_part.ciphertext.data);
+	krb5_free_principal(context, tempto->server);
+	krb5_xfree(tempto);
+	return retval;
+    }	
+    *pto = tempto;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/cp_key_cnt.c b/krb5-1-6/src/lib/krb5/krb/cp_key_cnt.c
new file mode 100644
index 000000000..150be0a57
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/cp_key_cnt.c
@@ -0,0 +1,47 @@
+/*
+ * lib/krb5/krb/cp_key_cnt.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_copy_keyblock()
+ */
+
+#include "k5-int.h"
+
+/*
+ * Copy a keyblock, including alloc'ed storage.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_copy_keyblock_contents(krb5_context context, const krb5_keyblock *from, krb5_keyblock *to)
+{
+    *to = *from;
+    if (to->length) {
+        to->contents = (krb5_octet *)malloc(to->length);
+        if (!to->contents)
+            return ENOMEM;
+        memcpy((char *)to->contents, (char *)from->contents, to->length);
+    } else 
+        to->contents = 0;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/decode_kdc.c b/krb5-1-6/src/lib/krb5/krb/decode_kdc.c
new file mode 100644
index 000000000..cdfc4ffbd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/decode_kdc.c
@@ -0,0 +1,77 @@
+/*
+ * lib/krb5/krb/decode_kdc.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_decode_kdc_rep() function.
+ */
+
+#include "k5-int.h"
+
+/*
+ Takes a KDC_REP message and decrypts encrypted part using etype and
+ *key, putting result in *rep.
+ dec_rep->client,ticket,session,last_req,server,caddrs
+ are all set to allocated storage which should be freed by the caller
+ when finished with the response.
+
+ If the response isn't a KDC_REP (tgs or as), it returns an error from
+ the decoding routines.
+
+ returns errors from encryption routines, system errors
+ */
+
+krb5_error_code
+krb5_decode_kdc_rep(krb5_context context, krb5_data *enc_rep, const krb5_keyblock *key, krb5_kdc_rep **dec_rep)
+{
+    krb5_error_code retval;
+    krb5_kdc_rep *local_dec_rep;
+    krb5_keyusage usage;
+
+    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)) {
+	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 {
+	return KRB5KRB_AP_ERR_MSG_TYPE;
+    }
+
+    if (retval)
+	return retval;
+
+    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;
+    return(retval);
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/decrypt_tk.c b/krb5-1-6/src/lib/krb5/krb/decrypt_tk.c
new file mode 100644
index 000000000..36ecbb45b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/decrypt_tk.c
@@ -0,0 +1,73 @@
+/*
+ * lib/krb5/krb/decrypt_tk.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_decrypt_tkt_part() function.
+ */
+
+#include "k5-int.h"
+
+/*
+ Decrypts dec_ticket->enc_part
+ using *srv_key, and places result in dec_ticket->enc_part2.
+ The storage of dec_ticket->enc_part2 will be allocated before return.
+
+ returns errors from encryption routines, system errors
+
+*/
+
+krb5_error_code KRB5_CALLCONV
+krb5_decrypt_tkt_part(krb5_context context, const krb5_keyblock *srv_key, register krb5_ticket *ticket)
+{
+    krb5_enc_tkt_part *dec_tkt_part;
+    krb5_data scratch;
+    krb5_error_code retval;
+
+    if (!krb5_c_valid_enctype(ticket->enc_part.enctype))
+	return KRB5_PROG_ETYPE_NOSUPP;
+
+    scratch.length = ticket->enc_part.ciphertext.length;
+    if (!(scratch.data = malloc(ticket->enc_part.ciphertext.length)))
+	return(ENOMEM);
+
+    /* call the encryption routine */
+    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);}
+
+    /*  now decode the decrypted stuff */
+    retval = decode_krb5_enc_tkt_part(&scratch, &dec_tkt_part);
+    if (!retval) {
+	ticket->enc_part2 = dec_tkt_part;
+    }
+    clean_scratch();
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/deltat.c b/krb5-1-6/src/lib/krb5/krb/deltat.c
new file mode 100644
index 000000000..2541591f8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/deltat.c
@@ -0,0 +1,1455 @@
+/* A Bison parser, made by GNU Bison 1.875d.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* Written by Richard Stallman by simplifying the original so called
+   ``semantic'' parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     NUM = 258,
+     LONGNUM = 259,
+     OVERFLOW = 260,
+     tok_WS = 261
+   };
+#endif
+#define NUM 258
+#define LONGNUM 259
+#define OVERFLOW 260
+#define tok_WS 261
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 38 "x-deltat.y"
+
+
+#include <ctype.h>
+#include <errno.h>
+#include "k5-int.h"
+
+struct param {
+    krb5_int32 delta;
+    char *p;
+};
+
+#define YYPARSE_PARAM tmv
+
+#define MAX_TIME KRB5_INT32_MAX
+#define MIN_TIME KRB5_INT32_MIN
+
+#define DAY (24 * 3600)
+#define HOUR 3600
+
+#define MAX_DAY (MAX_TIME / DAY)
+#define MIN_DAY (MIN_TIME / DAY)
+#define MAX_HOUR (MAX_TIME / HOUR)
+#define MIN_HOUR (MIN_TIME / HOUR)
+#define MAX_MIN (MAX_TIME / 60)
+#define MIN_MIN (MIN_TIME / 60)
+
+/* An explanation of the tests being performed. 
+   We do not want to overflow a 32 bit integer with out manipulations, 
+   even for testing for overflow. Therefore we rely on the following:
+
+   The lex parser will not return a number > MAX_TIME (which is out 32
+   bit limit).
+
+   Therefore, seconds (s) will require 
+       MIN_TIME < s < MAX_TIME
+
+   For subsequent tests, the logic is as follows:
+
+      If A < MAX_TIME and  B < MAX_TIME
+
+      If we want to test if A+B < MAX_TIME, there are two cases
+        if (A > 0) 
+         then A + B < MAX_TIME if B < MAX_TIME - A
+	else A + B < MAX_TIME  always.
+
+      if we want to test if MIN_TIME < A + B
+          if A > 0 - then nothing to test
+          otherwise, we test if MIN_TIME - A < B.
+
+   We of course are testing for:
+          MIN_TIME < A + B < MAX_TIME
+*/
+
+
+#define DAY_NOT_OK(d) (d) > MAX_DAY || (d) < MIN_DAY
+#define HOUR_NOT_OK(h) (h) > MAX_HOUR || (h) < MIN_HOUR
+#define MIN_NOT_OK(m) (m) > MAX_MIN || (m) < MIN_MIN
+#define SUM_OK(a, b) (((a) > 0) ? ( (b) <= MAX_TIME - (a)) : (MIN_TIME - (a) <= (b)))
+#define DO_SUM(res, a, b) if (!SUM_OK((a), (b))) YYERROR; \
+                          res = (a) + (b)
+
+
+#define OUT_D ((struct param *)tmv)->delta 
+#define DO(D,H,M,S) \
+ { \
+     /* Overflow testing - this does not handle negative values well.. */ \
+     if (DAY_NOT_OK(D) || HOUR_NOT_OK(H) || MIN_NOT_OK(M)) YYERROR; \
+     OUT_D = D * DAY; \
+     DO_SUM(OUT_D, OUT_D, H * HOUR); \
+     DO_SUM(OUT_D, OUT_D, M * 60); \
+     DO_SUM(OUT_D, OUT_D, S); \
+ }
+
+static int mylex (int *, char **);
+#define YYLEX_PARAM (&((struct param *)tmv)->p)
+#undef yylex
+#define yylex(U, P)    mylex (&(U)->val, (P))
+
+#undef yyerror
+#define yyerror(MSG)
+
+static int yyparse (void *);
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 125 "x-deltat.y"
+typedef union YYSTYPE { int val; } YYSTYPE;
+/* Line 191 of yacc.c.  */
+#line 175 "deltat.c"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 214 of yacc.c.  */
+#line 187 "deltat.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+# ifndef YYFREE
+#  define YYFREE free
+# endif
+# ifndef YYMALLOC
+#  define YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   define YYSTACK_ALLOC alloca
+#  endif
+# else
+#  if defined (alloca) || defined (_ALLOCA_H)
+#   define YYSTACK_ALLOC alloca
+#  else
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+	 || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short int yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short int) + sizeof (YYSTYPE))			\
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined (__GNUC__) && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  register YYSIZE_T yyi;		\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+   typedef signed char yysigned_char;
+#else
+   typedef short int yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL  6
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   37
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS  13
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS  10
+/* YYNRULES -- Number of rules. */
+#define YYNRULES  24
+/* YYNRULES -- Number of states. */
+#define YYNSTATES  42
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   261
+
+#define YYTRANSLATE(YYX) 						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const unsigned char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     6,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     7,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       8,     2,     2,     2,     9,     2,     2,     2,     2,    10,
+       2,     2,     2,     2,     2,    11,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,    12
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const unsigned char yyprhs[] =
+{
+       0,     0,     3,     5,     7,     9,    11,    14,    15,    17,
+      20,    23,    27,    31,    35,    38,    46,    52,    56,    58,
+      60,    64,    66,    70,    72
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+      14,     0,    -1,    19,    -1,     3,    -1,     4,    -1,    15,
+      -1,     6,    15,    -1,    -1,    12,    -1,    17,    16,    -1,
+      17,     5,    -1,    18,     8,    20,    -1,    18,     9,    21,
+      -1,    18,    10,    22,    -1,    18,    11,    -1,    18,     6,
+       3,     7,     3,     7,     3,    -1,    18,     7,     3,     7,
+       3,    -1,    18,     7,     3,    -1,    18,    -1,    21,    -1,
+      18,     9,    21,    -1,    22,    -1,    18,    10,    22,    -1,
+      17,    -1,    18,    11,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const unsigned char yyrline[] =
+{
+       0,   136,   136,   137,   137,   138,   138,   139,   139,   140,
+     141,   143,   144,   145,   146,   147,   148,   149,   150,   154,
+     155,   158,   159,   162,   163
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "NUM", "LONGNUM", "OVERFLOW", "'-'",
+  "':'", "'d'", "'h'", "'m'", "'s'", "tok_WS", "$accept", "start",
+  "posnum", "num", "ws", "wsnum", "deltat", "opt_hms", "opt_ms", "opt_s", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const unsigned short int yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,    45,    58,   100,   104,
+     109,   115,   261
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const unsigned char yyr1[] =
+{
+       0,    13,    14,    15,    15,    16,    16,    17,    17,    18,
+      18,    19,    19,    19,    19,    19,    19,    19,    19,    20,
+      20,    21,    21,    22,    22
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const unsigned char yyr2[] =
+{
+       0,     2,     1,     1,     1,     1,     2,     0,     1,     2,
+       2,     3,     3,     3,     2,     7,     5,     3,     1,     1,
+       3,     1,     3,     1,     2
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const unsigned char yydefact[] =
+{
+       7,     8,     0,     0,    18,     2,     1,     3,     4,    10,
+       0,     5,     9,     0,     0,     7,     7,     7,    14,     6,
+       0,    17,    23,     0,    11,    19,    21,     0,    12,     0,
+      13,     0,     0,     7,     7,    24,     0,    16,    20,    22,
+       0,    15
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yysigned_char yydefgoto[] =
+{
+      -1,     2,    11,    12,    22,    27,     5,    24,    25,    26
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -16
+static const yysigned_char yypact[] =
+{
+     -10,   -16,    14,     7,    -2,   -16,   -16,   -16,   -16,   -16,
+      21,   -16,   -16,    13,    25,   -10,   -10,   -10,   -16,   -16,
+      22,    23,     7,    12,   -16,   -16,   -16,    16,   -16,     8,
+     -16,    28,    29,   -10,   -10,   -16,    26,   -16,   -16,   -16,
+      32,   -16
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yysigned_char yypgoto[] =
+{
+     -16,   -16,    27,   -16,    36,     0,   -16,   -16,   -15,   -14
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -1
+static const unsigned char yytable[] =
+{
+       4,    28,     1,    30,    13,    14,    15,    16,    17,    18,
+       7,     8,     9,    10,     6,    23,    20,    29,    38,    35,
+      39,    33,    34,    35,     7,     8,    34,    35,    21,    31,
+      32,    36,    37,    40,    29,    41,     3,    19
+};
+
+static const unsigned char yycheck[] =
+{
+       0,    16,    12,    17,     6,     7,     8,     9,    10,    11,
+       3,     4,     5,     6,     0,    15,     3,    17,    33,    11,
+      34,     9,    10,    11,     3,     4,    10,    11,     3,     7,
+       7,     3,     3,     7,    34,     3,     0,    10
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const unsigned char yystos[] =
+{
+       0,    12,    14,    17,    18,    19,     0,     3,     4,     5,
+       6,    15,    16,     6,     7,     8,     9,    10,    11,    15,
+       3,     3,    17,    18,    20,    21,    22,    18,    21,    18,
+      22,     7,     7,     9,    10,    11,     3,     3,    21,    22,
+       7,     3
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { 								\
+      yyerror ("syntax error: cannot back up");\
+      YYERROR;							\
+    }								\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)		\
+   ((Current).first_line   = (Rhs)[1].first_line,	\
+    (Current).first_column = (Rhs)[1].first_column,	\
+    (Current).last_line    = (Rhs)[N].last_line,	\
+    (Current).last_column  = (Rhs)[N].last_column)
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval)
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (0)
+
+# define YYDSYMPRINT(Args)			\
+do {						\
+  if (yydebug)					\
+    yysymprint Args;				\
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location)		\
+do {								\
+  if (yydebug)							\
+    {								\
+      YYFPRINTF (stderr, "%s ", Title);				\
+      yysymprint (stderr, 					\
+                  Token, Value);	\
+      YYFPRINTF (stderr, "\n");					\
+    }								\
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    short int *bottom;
+    short int *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (/* Nothing. */; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+    int yyrule;
+#endif
+{
+  int yyi;
+  unsigned int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+             yyrule - 1, yylno);
+  /* Print the symbols being reduced, and their result.  */
+  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (Rule);		\
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  if (yytype < YYNTOKENS)
+    {
+      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+    }
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+  YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  switch (yytype)
+    {
+
+      default:
+        break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+  void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  /* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  short int yyssa[YYINITDEPTH];
+  short int *yyss = yyssa;
+  register short int *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule.  */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack. Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	short int *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyoverflowlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	short int *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyoverflowlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 6:
+#line 138 "x-deltat.y"
+    { yyval.val = - yyvsp[0].val; ;}
+    break;
+
+  case 9:
+#line 140 "x-deltat.y"
+    { yyval.val = yyvsp[0].val; ;}
+    break;
+
+  case 10:
+#line 141 "x-deltat.y"
+    { YYERROR; ;}
+    break;
+
+  case 11:
+#line 143 "x-deltat.y"
+    { DO (yyvsp[-2].val,  0,  0, yyvsp[0].val); ;}
+    break;
+
+  case 12:
+#line 144 "x-deltat.y"
+    { DO ( 0, yyvsp[-2].val,  0, yyvsp[0].val); ;}
+    break;
+
+  case 13:
+#line 145 "x-deltat.y"
+    { DO ( 0,  0, yyvsp[-2].val, yyvsp[0].val); ;}
+    break;
+
+  case 14:
+#line 146 "x-deltat.y"
+    { DO ( 0,  0,  0, yyvsp[-1].val); ;}
+    break;
+
+  case 15:
+#line 147 "x-deltat.y"
+    { DO (yyvsp[-6].val, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val); ;}
+    break;
+
+  case 16:
+#line 148 "x-deltat.y"
+    { DO ( 0, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val); ;}
+    break;
+
+  case 17:
+#line 149 "x-deltat.y"
+    { DO ( 0, yyvsp[-2].val, yyvsp[0].val,  0); ;}
+    break;
+
+  case 18:
+#line 150 "x-deltat.y"
+    { DO ( 0,  0,  0, yyvsp[0].val); ;}
+    break;
+
+  case 20:
+#line 155 "x-deltat.y"
+    { if (HOUR_NOT_OK(yyvsp[-2].val)) YYERROR;
+	                                  DO_SUM(yyval.val, yyvsp[-2].val * 3600, yyvsp[0].val); ;}
+    break;
+
+  case 22:
+#line 159 "x-deltat.y"
+    { if (MIN_NOT_OK(yyvsp[-2].val)) YYERROR;
+	                                  DO_SUM(yyval.val, yyvsp[-2].val * 60, yyvsp[0].val); ;}
+    break;
+
+  case 23:
+#line 162 "x-deltat.y"
+    { yyval.val = 0; ;}
+    break;
+
+
+    }
+
+/* Line 1010 of yacc.c.  */
+#line 1164 "deltat.c"
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+
+
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (YYPACT_NINF < yyn && yyn < YYLAST)
+	{
+	  YYSIZE_T yysize = 0;
+	  int yytype = YYTRANSLATE (yychar);
+	  const char* yyprefix;
+	  char *yymsg;
+	  int yyx;
+
+	  /* Start YYX at -YYN if negative to avoid negative indexes in
+	     YYCHECK.  */
+	  int yyxbegin = yyn < 0 ? -yyn : 0;
+
+	  /* Stay within bounds of both yycheck and yytname.  */
+	  int yychecklim = YYLAST - yyn;
+	  int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+	  int yycount = 0;
+
+	  yyprefix = ", expecting ";
+	  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	      {
+		yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+		yycount += 1;
+		if (yycount == 5)
+		  {
+		    yysize = 0;
+		    break;
+		  }
+	      }
+	  yysize += (sizeof ("syntax error, unexpected ")
+		     + yystrlen (yytname[yytype]));
+	  yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg != 0)
+	    {
+	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+	      yyp = yystpcpy (yyp, yytname[yytype]);
+
+	      if (yycount < 5)
+		{
+		  yyprefix = ", expecting ";
+		  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+		      {
+			yyp = yystpcpy (yyp, yyprefix);
+			yyp = yystpcpy (yyp, yytname[yyx]);
+			yyprefix = " or ";
+		      }
+		}
+	      yyerror (yymsg);
+	      YYSTACK_FREE (yymsg);
+	    }
+	  else
+	    yyerror ("syntax error; also virtual memory exhausted");
+	}
+      else
+#endif /* YYERROR_VERBOSE */
+	yyerror ("syntax error");
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* If at end of input, pop the error token,
+	     then the rest of the stack, then return failure.  */
+	  if (yychar == YYEOF)
+	     for (;;)
+	       {
+		 YYPOPSTACK;
+		 if (yyssp == yyss)
+		   YYABORT;
+		 YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+		 yydestruct (yystos[*yyssp], yyvsp);
+	       }
+        }
+      else
+	{
+	  YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+	  yydestruct (yytoken, &yylval);
+	  yychar = YYEMPTY;
+
+	}
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+  /* Pacify GCC when the user code never invokes YYERROR and the label
+     yyerrorlab therefore never appears in user code.  */
+  if (0)
+     goto yyerrorlab;
+#endif
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+      yydestruct (yystos[yystate], yyvsp);
+      YYPOPSTACK;
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here.  |
+`----------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+
+
+#line 165 "x-deltat.y"
+
+
+static int
+mylex (krb5_int32 *intp, char **pp)
+{
+    int num, c;
+#define P (*pp)
+    char *orig_p = P;
+
+#ifdef isascii
+    if (!isascii (*P))
+	return 0;
+#endif
+    switch (c = *P++) {
+    case '-':
+    case ':':
+    case 'd':
+    case 'h':
+    case 'm':
+    case 's':
+	return c;
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+	/* XXX assumes ASCII */
+	num = c - '0';
+	while (isdigit ((int) *P)) {
+	  if (num > MAX_TIME / 10) 
+	    return OVERFLOW;
+	    num *= 10;
+	    if (num > MAX_TIME - (*P - '0')) 
+	      return OVERFLOW;
+	    num += *P++ - '0';
+	}
+	*intp = num;
+	return (P - orig_p > 2) ? LONGNUM : NUM;
+    case ' ':
+    case '\t':
+    case '\n':
+	while (isspace ((int) *P))
+	    P++;
+	return tok_WS;
+    default:
+	return YYEOF;
+    }
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_deltat(char *string, krb5_deltat *deltatp)
+{
+    struct param p;
+    p.delta = 0;
+    p.p = string;
+    if (yyparse (&p))
+	return KRB5_DELTAT_BADFORMAT;
+    *deltatp = p.delta;
+    return 0;
+}
+
+
diff --git a/krb5-1-6/src/lib/krb5/krb/enc_helper.c b/krb5-1-6/src/lib/krb5/krb/enc_helper.c
new file mode 100644
index 000000000..63e3495da
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/enc_helper.c
@@ -0,0 +1,50 @@
+/*
+ * 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(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, 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);
+    ret = krb5_c_encrypt(context, key, usage, 0, plain, cipher);
+    if (ret) {
+	free(cipher->ciphertext.data);
+	cipher->ciphertext.data = NULL;
+    }
+
+    return(ret);
+}
+	
diff --git a/krb5-1-6/src/lib/krb5/krb/encode_kdc.c b/krb5-1-6/src/lib/krb5/krb/encode_kdc.c
new file mode 100644
index 000000000..8b879c015
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/encode_kdc.c
@@ -0,0 +1,128 @@
+/*
+ * lib/krb5/krb/encode_kdc.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_encode_kdc_rep() function.
+ */
+
+#include "k5-int.h"
+
+/*
+ Takes KDC rep parts in *rep and *encpart, and formats it into *enc_rep,
+ using message type type and encryption key client_key and encryption type
+ etype.
+
+ The string *enc_rep will be allocated before formatting; the caller should
+ free when finished.
+
+ returns system errors
+
+ dec_rep->enc_part.ciphertext is allocated and filled in.
+*/
+/* due to argument promotion rules, we need to use the DECLARG/OLDDECLARG
+   stuff... */
+krb5_error_code
+krb5_encode_kdc_rep(krb5_context context, 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)
+{
+    krb5_data *scratch;
+    krb5_error_code retval;
+    krb5_enc_kdc_rep_part tmp_encpart;
+    krb5_keyusage usage;
+
+    if (!krb5_c_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;
+    }
+
+    /*
+     * We don't want to modify encpart, but we need to be able to pass
+     * in the message type to the encoder, so it can set the ASN.1
+     * type correct.
+     * 
+     * Although note that it may be doing nothing with the message
+     * type, to be compatible with old versions of Kerberos that always
+     * encode this as a TGS_REP regardly of what it really should be;
+     * also note that the reason why we are passing it in a structure
+     * instead of as an argument to encode_krb5_enc_kdc_rep_part (the
+     * way we should) is for compatibility with the ISODE version of
+     * this fuction.  Ah, compatibility....
+     */
+    tmp_encpart = *encpart;
+    tmp_encpart.msg_type = type;
+    retval = encode_krb5_enc_kdc_rep_part(&tmp_encpart, &scratch);
+    if (retval) {
+	return retval;
+    }
+    memset(&tmp_encpart, 0, sizeof(tmp_encpart));
+
+#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
+krb5_free_data(context, 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, \
+	     dec_rep->enc_part.ciphertext.length); \
+free(dec_rep->enc_part.ciphertext.data); \
+dec_rep->enc_part.ciphertext.length = 0; \
+dec_rep->enc_part.ciphertext.data = 0;}
+
+    cleanup_scratch();
+
+    if (retval)
+	return(retval);
+
+    /* now it's ready to be encoded for the wire! */
+
+    switch (type) {
+    case KRB5_AS_REP:
+	retval = encode_krb5_as_rep(dec_rep, enc_rep);
+	break;
+    case KRB5_TGS_REP:
+	retval = encode_krb5_tgs_rep(dec_rep, enc_rep);
+	break;
+    }
+
+    if (retval)
+	cleanup_encpart();
+
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/encrypt_tk.c b/krb5-1-6/src/lib/krb5/krb/encrypt_tk.c
new file mode 100644
index 000000000..ed2b8c1b8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/encrypt_tk.c
@@ -0,0 +1,67 @@
+/*
+ * lib/krb5/krb/encrypt_tk.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_encrypt_tkt_part() routine.
+ */
+
+#include "k5-int.h"
+
+/*
+ Takes unencrypted dec_ticket & dec_tkt_part, encrypts with
+ dec_ticket->enc_part.etype
+ using *srv_key, and places result in dec_ticket->enc_part.
+ The string dec_ticket->enc_part.ciphertext will be allocated before
+ formatting.
+
+ returns errors from encryption routines, system errors
+
+ enc_part->ciphertext.data allocated & filled in with encrypted stuff
+*/
+
+krb5_error_code
+krb5_encrypt_tkt_part(krb5_context context, const krb5_keyblock *srv_key, register krb5_ticket *dec_ticket)
+{
+    krb5_data *scratch;
+    krb5_error_code retval;
+    register krb5_enc_tkt_part *dec_tkt_part = dec_ticket->enc_part2;
+
+    /*  start by encoding the to-be-encrypted part. */
+    if ((retval = encode_krb5_enc_tkt_part(dec_tkt_part, &scratch))) {
+	return retval;
+    }
+
+#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
+krb5_free_data(context, scratch); }
+
+    /* call the encryption routine */
+    retval = krb5_encrypt_helper(context, srv_key,
+				 KRB5_KEYUSAGE_KDC_REP_TICKET, scratch,
+				 &dec_ticket->enc_part);
+
+    cleanup_scratch();
+
+    return(retval);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/free_rtree.c b/krb5-1-6/src/lib/krb5/krb/free_rtree.c
new file mode 100644
index 000000000..7914d3f23
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/free_rtree.c
@@ -0,0 +1,41 @@
+/*
+ * lib/krb5/krb/free_rtree.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_free_realm_tree()
+ */
+
+#include "k5-int.h"
+
+void
+krb5_free_realm_tree(krb5_context context, krb5_principal *realms)
+{
+    register krb5_principal *nrealms = realms;
+    while (*nrealms) {
+	krb5_free_principal(context, *nrealms);
+	nrealms++;
+    }
+    krb5_xfree(realms);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/fwd_tgt.c b/krb5-1-6/src/lib/krb5/krb/fwd_tgt.c
new file mode 100644
index 000000000..2db2c9e00
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/fwd_tgt.c
@@ -0,0 +1,197 @@
+/*
+ * lib/krb5/krb/get_in_tkt.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+/* helper function: convert flags to necessary KDC options */
+#define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
+
+/* Get a TGT for use at the remote host */
+krb5_error_code KRB5_CALLCONV
+krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf)
+                         
+                                   
+                
+                          
+                          
+                   
+                          /* Should forwarded TGT also be forwardable? */
+                      
+{
+    krb5_replay_data replaydata;
+    krb5_data * scratch = 0;
+    krb5_address **addrs = NULL;
+    krb5_error_code retval;
+    krb5_creds creds, tgt;
+    krb5_creds *pcreds;
+    krb5_flags kdcoptions;
+    int close_cc = 0;
+    int free_rhost = 0;
+    krb5_enctype enctype = 0;
+    krb5_keyblock *session_key;
+    krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;
+
+    memset((char *)&creds, 0, sizeof(creds));
+    memset((char *)&tgt, 0, sizeof(creds));
+
+    if (cc == 0) {
+      if ((retval = krb5int_cc_default(context, &cc)))
+	goto errout;
+      close_cc = 1;
+    }
+    retval = krb5_auth_con_getkey (context, auth_context, &session_key);
+    if (retval)
+      goto errout;
+    if (session_key) {
+	enctype = session_key->enctype;
+	krb5_free_keyblock (context, session_key);
+	session_key = NULL;
+    } else if (server) { /* must server be non-NULL when rhost is given? */
+	/* Try getting credentials to see what the remote side supports.
+	   Not bulletproof, just a heuristic.  */
+	krb5_creds in, *out = 0;
+	memset (&in, 0, sizeof(in));
+
+	retval = krb5_copy_principal (context, server, &in.server);
+	if (retval)
+	    goto punt;
+	retval = krb5_copy_principal (context, client, &in.client);
+	if (retval)
+	    goto punt;
+	retval = krb5_get_credentials (context, 0, cc, &in, &out);
+	if (retval)
+	    goto punt;
+	/* Got the credentials.  Okay, now record the enctype and
+	   throw them away.  */
+	enctype = out->keyblock.enctype;
+	krb5_free_creds (context, out);
+    punt:
+	krb5_free_cred_contents (context, &in);
+    }
+
+    if ((retval = krb5_copy_principal(context, client, &creds.client)))
+	goto errout;
+    
+    if ((retval = krb5_build_principal_ext(context, &creds.server,
+					   client->realm.length,
+					   client->realm.data,
+					   KRB5_TGS_NAME_SIZE,
+					   KRB5_TGS_NAME,
+					   client->realm.length,
+					   client->realm.data,
+					   0)))
+	goto errout;
+	
+    /* fetch tgt directly from cache */
+    context->use_conf_ktypes = 1;
+    retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES,
+				    &creds, &tgt);
+    context->use_conf_ktypes = old_use_conf_ktypes;
+    if (retval)
+	goto errout;
+
+    /* tgt->client must be equal to creds.client */
+    if (!krb5_principal_compare(context, tgt.client, creds.client)) {
+	retval = KRB5_PRINC_NOMATCH;
+	goto errout;
+    }
+
+    if (!tgt.ticket.length) {
+	retval = KRB5_NO_TKT_SUPPLIED;
+	goto errout;
+    }
+    
+    if (tgt.addresses && *tgt.addresses) {
+      if (rhost == NULL) {
+	if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
+retval = KRB5_FWD_BAD_PRINCIPAL;
+ goto errout;
+	}
+
+	if (krb5_princ_size(context, server) < 2){
+	  retval = KRB5_CC_BADNAME;
+	  goto errout;
+	}
+	
+	rhost = malloc(server->data[1].length+1);
+	if (!rhost) {
+	  retval = ENOMEM;
+	  goto errout;
+	}
+	free_rhost = 1;
+	memcpy(rhost, server->data[1].data, server->data[1].length);
+	rhost[server->data[1].length] = '\0';
+      }
+
+	retval = krb5_os_hostaddr(context, rhost, &addrs);
+	if (retval)
+	    goto errout;
+    }
+    
+    creds.keyblock.enctype = enctype;
+    creds.times = tgt.times;
+    creds.times.starttime = 0;
+    kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;
+
+    if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
+      kdcoptions &= ~(KDC_OPT_FORWARDABLE);
+
+    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
+					addrs, &creds, &pcreds))) {
+	if (enctype) {
+	    creds.keyblock.enctype = 0;
+	    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
+						addrs, &creds, &pcreds))) 
+		goto errout;
+	}
+	else goto errout;
+    }
+    retval = krb5_mk_1cred(context, auth_context, pcreds,
+                           &scratch, &replaydata);
+    krb5_free_creds(context, pcreds);
+
+    if (retval) {
+	if (scratch)
+	    krb5_free_data(context, scratch);
+    } else {
+	*outbuf = *scratch;
+	krb5_xfree(scratch);
+    }
+        
+errout:
+    if (addrs)
+	krb5_free_addresses(context, addrs);
+    if (close_cc)
+	krb5_cc_close(context, cc);
+    if (free_rhost)
+	free(rhost);
+    krb5_free_cred_contents(context, &creds);
+    krb5_free_cred_contents(context, &tgt);
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/gc_frm_kdc.c b/krb5-1-6/src/lib/krb5/krb/gc_frm_kdc.c
new file mode 100644
index 000000000..987f2eb83
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/gc_frm_kdc.c
@@ -0,0 +1,1205 @@
+/*
+ * Copyright (c) 1994,2003,2005 by the Massachusetts Institute of Technology.
+ * Copyright (c) 1994 CyberSAFE Corporation
+ * Copyright (c) 1993 Open Computing Security Group
+ * Copyright (c) 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * Neither M.I.T., the Open Computing Security Group, nor 
+ * CyberSAFE Corporation make any representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * krb5_get_cred_from_kdc() and related functions:
+ *
+ * Get credentials from some KDC somewhere, possibly accumulating TGTs
+ * along the way.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include "int-proto.h"
+
+struct tr_state;
+
+/*
+ * Ring buffer abstraction for TGTs returned from a ccache; avoids
+ * lots of excess copying.
+ */
+
+#define NCC_TGTS 2
+struct cc_tgts {
+    krb5_creds cred[NCC_TGTS];
+    int dirty[NCC_TGTS];
+    unsigned int cur, nxt;
+};
+
+/* NOTE: This only checks if NXT_TGT is CUR_CC_TGT. */
+#define NXT_TGT_IS_CACHED(ts)			\
+	((ts)->nxt_tgt == (ts)->cur_cc_tgt)
+
+#define MARK_CUR_CC_TGT_CLEAN(ts)			\
+do {							\
+	(ts)->cc_tgts.dirty[(ts)->cc_tgts.cur] = 0;	\
+} while (0)
+
+static void init_cc_tgts(struct tr_state *);
+static void shift_cc_tgts(struct tr_state *);
+static void clean_cc_tgts(struct tr_state *);
+
+/*
+ * State struct for do_traversal() and helpers.
+ *
+ * CUR_TGT and NXT_TGT can each point either into CC_TGTS or into
+ * KDC_TGTS.
+ *
+ * CUR_TGT is the "working" TGT, which will be used to obtain new
+ * TGTs.  NXT_TGT will be CUR_TGT for the next iteration of the loop.
+ *
+ * Part of the baroqueness of this setup is to deal with annoying
+ * differences between krb5_cc_retrieve_cred() and
+ * krb5_get_cred_via_tkt(); krb5_cc_retrieve_cred() fills in a
+ * caller-allocated krb5_creds, while krb5_get_cred_via_tkt()
+ * allocates a krb5_creds for return.
+ */
+struct tr_state {
+    krb5_context ctx;
+    krb5_ccache ccache;
+    krb5_principal *kdc_list;
+    unsigned int nkdcs;
+    krb5_principal *cur_kdc;
+    krb5_principal *nxt_kdc;
+    krb5_principal *lst_kdc;
+    krb5_creds *cur_tgt;
+    krb5_creds *nxt_tgt;
+    krb5_creds **kdc_tgts;
+    struct cc_tgts cc_tgts;
+    krb5_creds *cur_cc_tgt;
+    krb5_creds *nxt_cc_tgt;
+    unsigned int ntgts;
+};
+
+/*
+ * Debug support
+ */
+#ifdef DEBUG_GC_FRM_KDC
+
+#define TR_DBG(ts, prog) tr_dbg(ts, prog)
+#define TR_DBG_RET(ts, prog, ret) tr_dbg_ret(ts, prog, ret)
+#define TR_DBG_RTREE(ts, prog, princ) tr_dbg_rtree(ts, prog, princ)
+
+static void tr_dbg(struct tr_state *, const char *);
+static void tr_dbg_ret(struct tr_state *, const char *, krb5_error_code);
+static void tr_dbg_rtree(struct tr_state *, const char *, krb5_principal);
+
+#else
+
+#define TR_DBG(ts, prog)
+#define TR_DBG_RET(ts, prog, ret)
+#define TR_DBG_RTREE(ts, prog, princ)
+
+#endif /* !DEBUG_GC_FRM_KDC */
+
+#ifdef DEBUG_REFERRALS
+
+#define DPRINTF(x) printf x
+#define DFPRINTF(x) fprintf x
+#define DUMP_PRINC(x, y) krb5int_dbgref_dump_principal((x), (y))
+
+#else
+
+#define DPRINTF(x)
+#define DFPRINTF(x)
+#define DUMP_PRINC(x, y)
+
+#endif
+
+/* Convert ticket flags to necessary KDC options */
+#define FLAGS2OPTS(flags) (flags & KDC_TKT_COMMON_MASK)
+
+/*
+ * Certain krb5_cc_retrieve_cred() errors are soft errors when looking
+ * for a cross-realm TGT.
+ */
+#define HARD_CC_ERR(r) ((r) && (r) != KRB5_CC_NOTFOUND &&	\
+	(r) != KRB5_CC_NOT_KTYPE)
+
+#define IS_TGS_PRINC(c, p)				\
+    ((krb5_princ_size((c), (p)) == 2) &&		\
+     (krb5_princ_component((c), (p), 0)->length ==	\
+      KRB5_TGS_NAME_SIZE) &&				\
+     (!memcmp(krb5_princ_component((c), (p), 0)->data,	\
+	      KRB5_TGS_NAME, KRB5_TGS_NAME_SIZE)))
+
+/*
+ * Flags for ccache lookups of cross-realm TGTs.
+ *
+ * A cross-realm TGT may be issued by some other intermediate realm's
+ * KDC, so we use KRB5_TC_MATCH_SRV_NAMEONLY.
+ */
+#define RETR_FLAGS (KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES)
+
+/*
+ * Prototypes of helper functions
+ */
+static krb5_error_code tgt_mcred(krb5_context, krb5_principal,
+    krb5_principal, krb5_principal, krb5_creds *);
+static krb5_error_code retr_local_tgt(struct tr_state *, krb5_principal);
+static krb5_error_code try_ccache(struct tr_state *, krb5_creds *);
+static krb5_error_code find_nxt_kdc(struct tr_state *);
+static krb5_error_code try_kdc(struct tr_state *, krb5_creds *);
+static krb5_error_code kdc_mcred(struct tr_state *, krb5_principal,
+    krb5_creds *mcreds);
+static krb5_error_code next_closest_tgt(struct tr_state *, krb5_principal);
+static krb5_error_code init_rtree(struct tr_state *,
+    krb5_principal, krb5_principal);
+static krb5_error_code do_traversal(krb5_context ctx, krb5_ccache,
+    krb5_principal client, krb5_principal server,
+    krb5_creds *out_cc_tgt, krb5_creds **out_tgt,
+    krb5_creds ***out_kdc_tgts);
+static krb5_error_code krb5_get_cred_from_kdc_opt(krb5_context, krb5_ccache,
+    krb5_creds *, krb5_creds **, krb5_creds ***, int);
+
+/*
+ * init_cc_tgts()
+ *
+ * Initialize indices for cached-TGT ring buffer.  Caller must zero
+ * CC_TGTS, CC_TGT_DIRTY arrays prior to calling.
+ */
+static void
+init_cc_tgts(struct tr_state *ts)
+{
+
+    ts->cc_tgts.cur = 0;
+    ts->cc_tgts.nxt = 1;
+    ts->cur_cc_tgt = &ts->cc_tgts.cred[0];
+    ts->nxt_cc_tgt = &ts->cc_tgts.cred[1];
+}
+
+/*
+ * shift_cc_tgts()
+ *
+ * Given a fresh assignment to NXT_CC_TGT, mark NXT_CC_TGT as dirty,
+ * and shift indices so old NXT_CC_TGT becomes new CUR_CC_TGT.  Clean
+ * the new NXT_CC_TGT.
+ */
+static void
+shift_cc_tgts(struct tr_state *ts)
+{
+    unsigned int i;
+    struct cc_tgts *rb;
+
+    rb = &ts->cc_tgts;
+    i = rb->cur = rb->nxt;
+    rb->dirty[i] = 1;
+    ts->cur_cc_tgt = ts->nxt_cc_tgt;
+
+    i = (i + 1) % NCC_TGTS;
+
+    rb->nxt = i;
+    ts->nxt_cc_tgt = &rb->cred[i];
+    if (rb->dirty[i]) {
+	krb5_free_cred_contents(ts->ctx, &rb->cred[i]);
+	rb->dirty[i] = 0;
+    }
+}
+
+/*
+ * clean_cc_tgts()
+ *
+ * Free CC_TGTS which were dirty, then mark them clean.
+ */
+static void
+clean_cc_tgts(struct tr_state *ts)
+{
+    unsigned int i;
+    struct cc_tgts *rb;
+
+    rb = &ts->cc_tgts;
+    for (i = 0; i < NCC_TGTS; i++) {
+	if (rb->dirty[i]) {
+	    krb5_free_cred_contents(ts->ctx, &rb->cred[i]);
+	    rb->dirty[i] = 0;
+	}
+    }
+}
+
+/*
+ * Debug support
+ */
+#ifdef DEBUG_GC_FRM_KDC
+static void
+tr_dbg(struct tr_state *ts, const char *prog)
+{
+    krb5_error_code retval;
+    char *cur_tgt_str, *cur_kdc_str, *nxt_kdc_str;
+
+    cur_tgt_str = cur_kdc_str = nxt_kdc_str = NULL;
+    retval = krb5_unparse_name(ts->ctx, ts->cur_tgt->server, &cur_tgt_str);
+    if (retval) goto cleanup;
+    retval = krb5_unparse_name(ts->ctx, *ts->cur_kdc, &cur_kdc_str);
+    if (retval) goto cleanup;
+    retval = krb5_unparse_name(ts->ctx, *ts->nxt_kdc, &nxt_kdc_str);
+    if (retval) goto cleanup;
+    fprintf(stderr, "%s: cur_tgt %s\n", prog, cur_tgt_str);
+    fprintf(stderr, "%s: cur_kdc %s\n", prog, cur_kdc_str);
+    fprintf(stderr, "%s: nxt_kdc %s\n", prog, nxt_kdc_str);
+cleanup:
+    if (cur_tgt_str)
+	krb5_free_unparsed_name(ts->ctx, cur_tgt_str);
+    if (cur_kdc_str)
+	krb5_free_unparsed_name(ts->ctx, cur_kdc_str);
+    if (nxt_kdc_str)
+	krb5_free_unparsed_name(ts->ctx, nxt_kdc_str);
+}
+
+static void
+tr_dbg_ret(struct tr_state *ts, const char *prog, krb5_error_code ret)
+{
+    fprintf(stderr, "%s: return %d (%s)\n", prog, (int)ret,
+	    error_message(ret));
+}
+
+static void
+tr_dbg_rtree(struct tr_state *ts, const char *prog, krb5_principal princ)
+{
+    char *str;
+
+    if (krb5_unparse_name(ts->ctx, princ, &str))
+	return;
+    fprintf(stderr, "%s: %s\n", prog, str);
+    krb5_free_unparsed_name(ts->ctx, str);
+}
+#endif /* DEBUG_GC_FRM_KDC */
+
+/*
+ * tgt_mcred()
+ *
+ * Return MCREDS for use as a match criterion.
+ *
+ * Resulting credential has CLIENT as the client principal, and
+ * krbtgt/realm_of(DST)@realm_of(SRC) as the server principal.  Zeroes
+ * MCREDS first, does not allocate MCREDS, and cleans MCREDS on
+ * failure.  The peculiar ordering of DST and SRC args is for
+ * consistency with krb5_tgtname().
+ */
+static krb5_error_code
+tgt_mcred(krb5_context ctx, krb5_principal client,
+	  krb5_principal dst, krb5_principal src,
+	  krb5_creds *mcreds)
+{
+    krb5_error_code retval;
+
+    retval = 0;
+    memset(mcreds, 0, sizeof(*mcreds));
+
+    retval = krb5_copy_principal(ctx, client, &mcreds->client);
+    if (retval)
+	goto cleanup;
+
+    retval = krb5_tgtname(ctx, krb5_princ_realm(ctx, dst),
+			  krb5_princ_realm(ctx, src), &mcreds->server);
+    if (retval)
+	goto cleanup;
+
+cleanup:
+    if (retval)
+	krb5_free_cred_contents(ctx, mcreds);
+
+    return retval;
+}
+
+/*
+ * init_rtree()
+ *
+ * Populate KDC_LIST with the output of krb5_walk_realm_tree().
+ */
+static krb5_error_code
+init_rtree(struct tr_state *ts,
+	   krb5_principal client, krb5_principal server)
+{
+    krb5_error_code retval;
+
+    ts->kdc_list = NULL;
+    retval = krb5_walk_realm_tree(ts->ctx, krb5_princ_realm(ts->ctx, client),
+				  krb5_princ_realm(ts->ctx, server),
+				  &ts->kdc_list, KRB5_REALM_BRANCH_CHAR);
+    if (retval)
+	return retval;
+
+    for (ts->nkdcs = 0; ts->kdc_list[ts->nkdcs]; ts->nkdcs++) {
+	assert(krb5_princ_size(ts->ctx, ts->kdc_list[ts->nkdcs]) == 2);
+	TR_DBG_RTREE(ts, "init_rtree", ts->kdc_list[ts->nkdcs]);
+    }
+    assert(ts->nkdcs > 1);
+    ts->lst_kdc = ts->kdc_list + ts->nkdcs - 1;
+
+    ts->kdc_tgts = calloc(ts->nkdcs + 1, sizeof(krb5_creds));
+    if (ts->kdc_tgts == NULL)
+	return ENOMEM;
+
+    return 0;
+}
+
+/*
+ * retr_local_tgt()
+ *
+ * Prime CUR_TGT with the cached TGT of the client's local realm.
+ */
+static krb5_error_code
+retr_local_tgt(struct tr_state *ts, krb5_principal client)
+{
+    krb5_error_code retval;
+    krb5_creds tgtq;
+
+    memset(&tgtq, 0, sizeof(tgtq));
+    retval = tgt_mcred(ts->ctx, client, client, client, &tgtq);
+    if (retval)
+	return retval;
+
+    /* Match realm, unlike other ccache retrievals here. */
+    retval = krb5_cc_retrieve_cred(ts->ctx, ts->ccache,
+				   KRB5_TC_SUPPORTED_KTYPES,
+				   &tgtq, ts->nxt_cc_tgt);
+    krb5_free_cred_contents(ts->ctx, &tgtq);
+    if (!retval) {
+	shift_cc_tgts(ts);
+	ts->nxt_tgt = ts->cur_tgt = ts->cur_cc_tgt;
+    }
+    return retval;
+}
+
+/*
+ * try_ccache()
+ *
+ * Attempt to retrieve desired NXT_TGT from ccache.  Point NXT_TGT to
+ * it if successful.
+ */
+static krb5_error_code
+try_ccache(struct tr_state *ts, krb5_creds *tgtq)
+{
+    krb5_error_code retval;
+
+    TR_DBG(ts, "try_ccache");
+    retval = krb5_cc_retrieve_cred(ts->ctx, ts->ccache, RETR_FLAGS,
+				   tgtq, ts->nxt_cc_tgt);
+    if (!retval) {
+	shift_cc_tgts(ts);
+	ts->nxt_tgt = ts->cur_cc_tgt;
+    }
+    TR_DBG_RET(ts, "try_ccache", retval);
+    return retval;
+}
+
+/*
+ * find_nxt_kdc()
+ *
+ * A NXT_TGT gotten from an intermediate KDC might actually be a
+ * referral.  Search KDC_LIST forward starting from CUR_KDC, looking
+ * for the KDC with the same remote realm as NXT_TGT.  If we don't
+ * find it, the intermediate KDC is leading us off the transit path.
+ *
+ * Match on CUR_KDC's remote realm, not local realm, because, among
+ * other reasons, we can get a referral to the final realm; e.g.,
+ * given
+ *
+ *     KDC_LIST == { krbtgt/R1@R1, krbtgt/R2@R1, krbtgt/R3@R2,
+ *                   krbtgt/R4@R3, NULL }
+ *     CUR_TGT->SERVER == krbtgt/R2@R1
+ *     NXT_TGT->SERVER == krbtgt/R4@R2
+ *
+ * i.e., we got a ticket issued by R2 with remote realm R4, we want to
+ * find krbtgt/R4@R3, not krbtgt/R3@R2, even though we have no TGT
+ * with R3 as its local realm.
+ *
+ * Set up for next iteration of do_traversal() loop by pointing
+ * NXT_KDC to one entry forward of the match.
+ */
+static krb5_error_code
+find_nxt_kdc(struct tr_state *ts)
+{
+    krb5_data *r1, *r2;
+    krb5_principal *kdcptr;
+
+    TR_DBG(ts, "find_nxt_kdc");
+    assert(ts->nxt_tgt == ts->kdc_tgts[ts->ntgts-1]);
+    if (krb5_princ_size(ts->ctx, ts->nxt_tgt->server) != 2)
+	return KRB5_KDCREP_MODIFIED;
+
+    r1 = krb5_princ_component(ts->ctx, ts->nxt_tgt->server, 1);
+
+    for (kdcptr = ts->cur_kdc + 1; *kdcptr != NULL; kdcptr++) {
+
+	r2 = krb5_princ_component(ts->ctx, *kdcptr, 1);
+
+	if (r1 != NULL && r2 != NULL &&
+	    r1->length == r2->length &&
+	    !memcmp(r1->data, r2->data, r1->length)) {
+	    break;
+	}
+    }
+    if (*kdcptr == NULL) {
+	/*
+	 * Not found; we probably got an unexpected realm referral.
+	 * Don't touch NXT_KDC, thus allowing next_closest_tgt() to
+	 * continue looping backwards.
+	 */
+	if (ts->ntgts > 0) {
+	    /* Punt NXT_TGT from KDC_TGTS if bogus. */
+	    krb5_free_creds(ts->ctx, ts->kdc_tgts[--ts->ntgts]);
+	    ts->kdc_tgts[ts->ntgts] = NULL;
+	}
+	TR_DBG_RET(ts, "find_nxt_kdc", KRB5_KDCREP_MODIFIED);
+	return KRB5_KDCREP_MODIFIED;
+    }
+    ts->nxt_kdc = kdcptr;
+    TR_DBG_RET(ts, "find_nxt_kdc", 0);
+    return 0;
+}
+
+/*
+ * try_kdc()
+ *
+ * Using CUR_TGT, attempt to get desired NXT_TGT.  Update NXT_KDC if
+ * successful.
+ */
+static krb5_error_code
+try_kdc(struct tr_state *ts, krb5_creds *tgtq)
+{
+    krb5_error_code retval;
+    krb5_creds ltgtq;
+
+    TR_DBG(ts, "try_kdc");
+    /* This check should probably be in gc_via_tkt. */
+    if (!krb5_c_valid_enctype(ts->cur_tgt->keyblock.enctype))
+	return KRB5_PROG_ETYPE_NOSUPP;
+
+    ltgtq = *tgtq;
+    ltgtq.is_skey = FALSE;
+    ltgtq.ticket_flags = ts->cur_tgt->ticket_flags;
+    retval = krb5_get_cred_via_tkt(ts->ctx, ts->cur_tgt,
+				   FLAGS2OPTS(ltgtq.ticket_flags),
+				   ts->cur_tgt->addresses,
+				   <gtq, &ts->kdc_tgts[ts->ntgts++]);
+    if (retval) {
+	ts->ntgts--;
+	ts->nxt_tgt = ts->cur_tgt;
+	TR_DBG_RET(ts, "try_kdc", retval);
+	return retval;
+    }
+    ts->nxt_tgt = ts->kdc_tgts[ts->ntgts-1];
+    retval = find_nxt_kdc(ts);
+    TR_DBG_RET(ts, "try_kdc", retval);
+    return retval;
+}
+
+/*
+ * kdc_mcred()
+ *
+ * Return MCREDS for use as a match criterion.
+ *
+ * Resulting credential has CLIENT as the client principal, and
+ * krbtgt/remote_realm(NXT_KDC)@local_realm(CUR_KDC) as the server
+ * principal.  Zeroes MCREDS first, does not allocate MCREDS, and
+ * cleans MCREDS on failure.
+ */
+static krb5_error_code
+kdc_mcred(struct tr_state *ts, krb5_principal client, krb5_creds *mcreds)
+{
+    krb5_error_code retval;
+    krb5_data *rdst, *rsrc;
+
+    retval = 0;
+    memset(mcreds, 0, sizeof(*mcreds));
+
+    rdst = krb5_princ_component(ts->ctx, *ts->nxt_kdc, 1);
+    rsrc = krb5_princ_component(ts->ctx, *ts->cur_kdc, 1);
+    retval = krb5_copy_principal(ts->ctx, client, &mcreds->client);
+    if (retval)
+	goto cleanup;
+
+    retval = krb5_tgtname(ts->ctx, rdst, rsrc, &mcreds->server);
+    if (retval)
+	goto cleanup;
+
+cleanup:
+    if (retval)
+	krb5_free_cred_contents(ts->ctx, mcreds);
+
+    return retval;
+}
+
+/*
+ * next_closest_tgt()
+ *
+ * Using CUR_TGT, attempt to get the cross-realm TGT having its remote
+ * realm closest to the target principal's.  Update NXT_TGT, NXT_KDC
+ * accordingly.
+ */
+static krb5_error_code
+next_closest_tgt(struct tr_state *ts, krb5_principal client)
+{
+    krb5_error_code retval;
+    krb5_creds tgtq;
+
+    retval = 0;
+    memset(&tgtq, 0, sizeof(tgtq));
+
+    for (ts->nxt_kdc = ts->lst_kdc;
+	 ts->nxt_kdc > ts->cur_kdc;
+	 ts->nxt_kdc--) {
+
+	krb5_free_cred_contents(ts->ctx, &tgtq);
+	retval = kdc_mcred(ts, client, &tgtq);
+	if (retval)
+	    goto cleanup;
+	/* Don't waste time retrying ccache for direct path. */
+	if (ts->cur_kdc != ts->kdc_list || ts->nxt_kdc != ts->lst_kdc) {
+	    retval = try_ccache(ts, &tgtq);
+	    if (!retval)
+		break;
+	    if (HARD_CC_ERR(retval))
+		goto cleanup;
+	}
+	/* Not in the ccache, so talk to a KDC. */
+	retval = try_kdc(ts, &tgtq);
+	if (!retval) {
+	    break;
+	}
+	/*
+	 * Because try_kdc() validates referral TGTs, it can return an
+	 * error indicating a bogus referral.  The loop continues when
+	 * it gets a bogus referral, which is arguably the right
+	 * thing.  (Previous implementation unconditionally failed.)
+	 */
+    }
+    /*
+     * If we have a non-zero retval, we either have a hard error or we
+     * failed to find a closer TGT.
+     */
+cleanup:
+    krb5_free_cred_contents(ts->ctx, &tgtq);
+    return retval;
+}
+
+/*
+ * do_traversal()
+ *
+ * Find final TGT needed to get CLIENT a ticket for SERVER.  Point
+ * OUT_TGT at the desired TGT, which may be an existing cached TGT
+ * (copied into OUT_CC_TGT) or one of the newly obtained TGTs
+ * (collected in OUT_KDC_TGTS).
+ *
+ * Get comfortable; this is somewhat complicated.
+ *
+ * Nomenclature: Cross-realm TGS principal names have the form:
+ *
+ *     krbtgt/REMOTE@LOCAL
+ *
+ * krb5_walk_realm_tree() returns a list like:
+ *
+ *     krbtgt/R1@R1, krbtgt/R2@R1, krbtgt/R3@R2, ...
+ *
+ * These are prinicpal names, not realm names.  We only really use the
+ * remote parts of the TGT principal names.
+ *
+ * The do_traversal loop calls next_closest_tgt() to find the next
+ * closest TGT to the destination realm.  next_closest_tgt() updates
+ * NXT_KDC for the following iteration of the do_traversal() loop.
+ *
+ * At the beginning of any given iteration of the do_traversal() loop,
+ * CUR_KDC's remote realm is the remote realm of CUR_TGT->SERVER.  The
+ * local realms of CUR_KDC and CUR_TGT->SERVER may not match due to
+ * short-circuit paths provided by intermediate KDCs, e.g., CUR_KDC
+ * might be krbtgt/D@C, while CUR_TGT->SERVER is krbtgt/D@B.
+ *
+ * For example, given KDC_LIST of
+ *
+ * krbtgt/R1@R1, krbtgt/R2@R1, krbtgt/R3@R2, krbtgt/R4@R3,
+ * krbtgt/R5@R4
+ *
+ * The next_closest_tgt() loop moves NXT_KDC to the left starting from
+ * R5, stopping before it reaches CUR_KDC.  When next_closest_tgt()
+ * returns, the do_traversal() loop updates CUR_KDC to be NXT_KDC, and
+ * calls next_closest_tgt() again.
+ *
+ * next_closest_tgt() at start of its loop:
+ *
+ *      CUR                 NXT
+ *       |                   |
+ *       V                   V
+ *     +----+----+----+----+----+
+ *     | R1 | R2 | R3 | R4 | R5 |
+ *     +----+----+----+----+----+
+ *
+ * next_closest_tgt() returns after finding a ticket for krbtgt/R3@R1:
+ *
+ *      CUR       NXT
+ *       |         |
+ *       V         V
+ *     +----+----+----+----+----+
+ *     | R1 | R2 | R3 | R4 | R5 |
+ *     +----+----+----+----+----+
+ *
+ * do_traversal() updates CUR_KDC:
+ *
+ *                NXT
+ *                CUR
+ *                 |
+ *                 V
+ *     +----+----+----+----+----+
+ *     | R1 | R2 | R3 | R4 | R5 |
+ *     +----+----+----+----+----+
+ *
+ * next_closest_tgt() at start of its loop:
+ *
+ *                CUR       NXT
+ *                 |         |
+ *                 V         V
+ *     +----+----+----+----+----+
+ *     | R1 | R2 | R3 | R4 | R5 |
+ *     +----+----+----+----+----+
+ *
+ * etc.
+ *
+ * The algorithm executes in n*(n-1)/2 (the sum of integers from 1 to
+ * n-1) attempts in the worst case, i.e., each KDC only has a
+ * cross-realm ticket for the immediately following KDC in the transit
+ * path.  Typically, short-circuit paths will cause execution occur
+ * faster than this worst-case scenario.
+ *
+ * When next_closest_tgt() updates NXT_KDC, it may not perform a
+ * simple increment from CUR_KDC, in part because some KDC may
+ * short-circuit pieces of the transit path.
+ */
+static krb5_error_code
+do_traversal(krb5_context ctx,
+	     krb5_ccache ccache,
+	     krb5_principal client,
+	     krb5_principal server,
+	     krb5_creds *out_cc_tgt,
+	     krb5_creds **out_tgt,
+	     krb5_creds ***out_kdc_tgts)
+{
+    krb5_error_code retval;
+    struct tr_state state, *ts;
+
+    *out_tgt = NULL;
+    *out_kdc_tgts = NULL;
+    ts = &state;
+    memset(ts, 0, sizeof(*ts));
+    ts->ctx = ctx;
+    ts->ccache = ccache;
+    init_cc_tgts(ts);
+
+    retval = init_rtree(ts, client, server);
+    if (retval)
+	goto cleanup;
+
+    retval = retr_local_tgt(ts, client);
+    if (retval)
+	goto cleanup;
+
+    for (ts->cur_kdc = ts->kdc_list, ts->nxt_kdc = NULL;
+	 ts->cur_kdc != NULL && ts->cur_kdc < ts->lst_kdc;
+	 ts->cur_kdc = ts->nxt_kdc, ts->cur_tgt = ts->nxt_tgt) {
+
+	retval = next_closest_tgt(ts, client);
+	if (retval)
+	    goto cleanup;
+	assert(ts->cur_kdc != ts->nxt_kdc);
+    }
+
+    if (NXT_TGT_IS_CACHED(ts)) {
+	*out_cc_tgt = *ts->cur_cc_tgt;
+	*out_tgt = out_cc_tgt;
+	MARK_CUR_CC_TGT_CLEAN(ts);
+    } else {
+	/* CUR_TGT is somewhere in KDC_TGTS; no need to copy. */
+	*out_tgt = ts->nxt_tgt;
+    }
+
+cleanup:
+    clean_cc_tgts(ts);
+    if (ts->kdc_list != NULL)
+	krb5_free_realm_tree(ctx, ts->kdc_list);
+    if (ts->ntgts == 0) {
+	*out_kdc_tgts = NULL;
+	if (ts->kdc_tgts != NULL)
+	    free(ts->kdc_tgts);
+    } else
+	*out_kdc_tgts = ts->kdc_tgts;
+    return retval;
+}
+
+/*
+ * krb5_get_cred_from_kdc_opt()
+ * krb5_get_cred_from_kdc()
+ * krb5_get_cred_from_kdc_validate()
+ * krb5_get_cred_from_kdc_renew()
+ *
+ * Retrieve credentials for client IN_CRED->CLIENT, server
+ * IN_CRED->SERVER, ticket flags IN_CRED->TICKET_FLAGS, possibly
+ * second_ticket if needed.
+ *
+ * Request credentials from the KDC for the server's realm.  Point
+ * TGTS to an allocated array of pointers to krb5_creds, containing
+ * any intermediate credentials obtained in the process of contacting
+ * the server's KDC; if no intermediate credentials were obtained,
+ * TGTS is a null pointer.  Return intermediate credentials if
+ * intermediate KDCs provided credentials, even if no useful end
+ * ticket results.
+ *
+ * Caller must free TGTS, regardless of whether this function returns
+ * success.
+ *
+ * This function does NOT cache the intermediate TGTs.
+ *
+ * Do not call this routine if desired credentials are already cached.
+ *
+ * On success, OUT_CRED contains the desired credentials; the caller
+ * must free them.
+ *
+ * Beware memory management issues if you have modifications in mind.
+ * With the addition of referral support, it is now the case that *tgts,
+ * referral_tgts, tgtptr, referral_tgts, and *out_creds all may point to
+ * the same credential at different times.
+ *
+ * Returns errors, system errors.
+ */
+
+static krb5_error_code
+krb5_get_cred_from_kdc_opt(krb5_context context, krb5_ccache ccache,
+			   krb5_creds *in_cred, krb5_creds **out_cred,
+			   krb5_creds ***tgts, int kdcopt)
+{
+    krb5_error_code retval, subretval;
+    krb5_principal client, server, supplied_server, out_supplied_server;
+    krb5_creds tgtq, cc_tgt, *tgtptr, *referral_tgts[KRB5_REFERRAL_MAXHOPS];
+    krb5_boolean old_use_conf_ktypes;
+    char **hrealms;
+    int referral_count, i;
+
+    /* 
+     * Set up client and server pointers.  Make a fresh and modifyable
+     * copy of the in_cred server and save the supplied version.
+     */
+    client = in_cred->client;
+    if ((retval=krb5_copy_principal(context, in_cred->server, &server)))
+        return retval;
+    /* We need a second copy for the output creds. */
+    if ((retval = krb5_copy_principal(context, server,
+				      &out_supplied_server)) != 0 ) {
+	krb5_free_principal(context, server);
+	return retval;
+    }
+    supplied_server = in_cred->server;
+    in_cred->server=server;
+
+    DUMP_PRINC("gc_from_kdc initial client", client);
+    DUMP_PRINC("gc_from_kdc initial server", server);
+    memset(&cc_tgt, 0, sizeof(cc_tgt));
+    memset(&tgtq, 0, sizeof(tgtq));
+    memset(&referral_tgts, 0, sizeof(referral_tgts));
+
+    tgtptr = NULL;
+    *tgts = NULL;
+    *out_cred=NULL;
+    old_use_conf_ktypes = context->use_conf_ktypes;
+
+    /* Copy client realm to server if no hint. */
+    if (krb5_is_referral_realm(&server->realm)) {
+        /* Use the client realm. */
+        DPRINTF(("gc_from_kdc: no server realm supplied, "
+		 "using client realm.\n"));
+	krb5_free_data_contents(context, &server->realm);
+	if (!( server->realm.data = (char *)malloc(client->realm.length+1)))
+	    return ENOMEM;
+	memcpy(server->realm.data, client->realm.data, client->realm.length);
+	server->realm.length = client->realm.length;
+	server->realm.data[server->realm.length] = 0;
+    }
+    /*
+     * Retreive initial TGT to match the specified server, either for the
+     * local realm in the default (referral) case or for the remote
+     * realm if we're starting someplace non-local.
+     */
+    retval = tgt_mcred(context, client, server, client, &tgtq);
+    if (retval)
+	goto cleanup;
+
+    /* Fast path: Is it in the ccache? */
+    context->use_conf_ktypes = 1;
+    retval = krb5_cc_retrieve_cred(context, ccache, RETR_FLAGS,
+				   &tgtq, &cc_tgt);
+    if (!retval) {
+	tgtptr = &cc_tgt;
+    } else if (!HARD_CC_ERR(retval)) {
+        DPRINTF(("gc_from_kdc: starting do_traversal to find "
+		 "initial TGT for referral\n"));
+	retval = do_traversal(context, ccache, client, server,
+			      &cc_tgt, &tgtptr, tgts);
+    }
+    if (retval) {
+        DPRINTF(("gc_from_kdc: failed to find initial TGT for referral\n"));
+        goto cleanup;
+    }
+
+    DUMP_PRINC("gc_from_kdc: server as requested", supplied_server);
+
+    /*
+     * Try requesting a service ticket from our local KDC with referrals
+     * turned on.  If the first referral succeeds, follow a referral-only
+     * path, otherwise fall back to old-style assumptions.
+     */
+
+    for (referral_count = 0;
+	 referral_count < KRB5_REFERRAL_MAXHOPS;
+	 referral_count++) {
+#if 0
+        DUMP_PRINC("gc_from_kdc: referral loop: tgt in use", tgtptr->server);
+        DUMP_PRINC("gc_from_kdc: referral loop: request is for", server);
+#endif
+        retval = krb5_get_cred_via_tkt(context, tgtptr,
+				       KDC_OPT_CANONICALIZE | 
+				       FLAGS2OPTS(tgtptr->ticket_flags) |  
+				       kdcopt |
+				       (in_cred->second_ticket.length ?
+					KDC_OPT_ENC_TKT_IN_SKEY : 0),
+				       tgtptr->addresses, in_cred, out_cred);
+	if (retval) {
+	    DPRINTF(("gc_from_kdc: referral TGS-REQ request failed: <%s>\n",
+		     error_message(retval)));
+	    /* If we haven't gone anywhere yet, fail through to the
+	       non-referral case. */
+	    if (referral_count==0) {
+	        DPRINTF(("gc_from_kdc: initial referral failed; "
+			 "punting to fallback.\n"));
+	        break;
+	    }
+	    /* Otherwise, try the same query without canonicalization
+	       set, and fail hard if that doesn't work. */
+	    DPRINTF(("gc_from_kdc: referral #%d failed; "
+		     "retrying without option.\n", referral_count + 1));
+	    retval = krb5_get_cred_via_tkt(context, tgtptr,
+					   FLAGS2OPTS(tgtptr->ticket_flags) |  
+					   kdcopt |
+					   (in_cred->second_ticket.length ?
+					    KDC_OPT_ENC_TKT_IN_SKEY : 0),
+					   tgtptr->addresses,
+					   in_cred, out_cred);
+	    /* Whether or not that succeeded, we're done. */
+	    goto cleanup;
+	}
+	    /* Referral request succeeded; let's see what it is. */
+	    if (krb5_principal_compare(context, in_cred->server,
+				       (*out_cred)->server)) {
+		DPRINTF(("gc_from_kdc: request generated ticket "
+			 "for requested server principal\n"));
+		DUMP_PRINC("gc_from_kdc final referred reply",
+			   in_cred->server);
+
+	    /*
+	     * Check if the return enctype is one that we requested if
+	     * needed.
+	     */
+	    if (old_use_conf_ktypes || context->tgs_ktype_count == 0)
+		goto cleanup;
+	    for (i = 0; i < context->tgs_ktype_count; i++) {
+		if ((*out_cred)->keyblock.enctype == context->tgs_ktypes[i]) {
+		    /* Found an allowable etype, so we're done */
+		    goto cleanup;
+		}
+	    }
+	    /*
+	     *  We need to try again, but this time use the
+	     *  tgs_ktypes in the context. At this point we should
+	     *  have all the tgts to succeed.
+	     */
+
+	    /* Free "wrong" credential */
+	    krb5_free_creds(context, *out_cred);
+	    *out_cred = NULL;
+	    /* Re-establish tgs etypes */
+	    context->use_conf_ktypes = old_use_conf_ktypes;
+	    retval = krb5_get_cred_via_tkt(context, tgtptr,
+					   KDC_OPT_CANONICALIZE | 
+					   FLAGS2OPTS(tgtptr->ticket_flags) |  
+					   kdcopt |
+					   (in_cred->second_ticket.length ?
+					    KDC_OPT_ENC_TKT_IN_SKEY : 0),
+					   tgtptr->addresses,
+					   in_cred, out_cred);
+		goto cleanup;
+	    }
+	    else if (IS_TGS_PRINC(context, (*out_cred)->server)) {
+		krb5_data *r1, *r2;
+
+		DPRINTF(("gc_from_kdc: request generated referral tgt\n"));
+		DUMP_PRINC("gc_from_kdc credential received",
+			   (*out_cred)->server);
+
+		if (referral_count == 0)
+		    r1 = &tgtptr->server->data[1];
+		else
+		    r1 = &referral_tgts[referral_count-1]->server->data[1];
+
+		r2 = &(*out_cred)->server->data[1];
+		if (r1->length == r2->length &&
+		    !memcmp(r1->data, r2->data, r1->length)) {
+		    DPRINTF(("gc_from_kdc: referred back to "
+			     "previous realm; fall back\n"));
+		    krb5_free_creds(context, *out_cred);
+		    *out_cred = NULL;
+		    break;
+		}
+		/* Check for referral routing loop. */
+		for (i=0;i<referral_count;i++) {
+#if 0
+		    DUMP_PRINC("gc_from_kdc: loop compare #1",
+			       (*out_cred)->server);
+		    DUMP_PRINC("gc_from_kdc: loop compare #2",
+			       referral_tgts[i]->server);
+#endif
+		    if (krb5_principal_compare(context,
+					       (*out_cred)->server,
+					       referral_tgts[i]->server)) {
+			DFPRINTF((stderr,
+				  "krb5_get_cred_from_kdc_opt: "
+				  "referral routing loop - "
+				  "got referral back to hop #%d\n", i));
+			retval=KRB5_KDC_UNREACH;
+			goto cleanup;
+		    }
+		}
+		/* Point current tgt pointer at newly-received TGT. */
+		if (tgtptr == &cc_tgt)
+		    krb5_free_cred_contents(context, tgtptr);
+		tgtptr=*out_cred;
+		/* Save pointer to tgt in referral_tgts. */
+		referral_tgts[referral_count]=*out_cred;
+		/* Copy krbtgt realm to server principal. */
+		krb5_free_data_contents(context, &server->realm);
+		retval = krb5int_copy_data_contents(context,
+						    &tgtptr->server->data[1],
+						    &server->realm);
+		if (retval)
+		    return retval;
+		/*
+		 * Future work: rewrite server principal per any
+		 * supplied padata.
+		 */
+	    } else {
+		/* Not a TGT; punt to fallback. */
+		krb5_free_creds(context, *out_cred);
+		*out_cred = NULL;
+		break;
+	}
+    }
+
+    DUMP_PRINC("gc_from_kdc client at fallback", client);
+    DUMP_PRINC("gc_from_kdc server at fallback", server);
+
+    /*
+     * At this point referrals have been tried and have failed.  Go
+     * back to the server principal as originally issued and try the
+     * conventional path.
+     */
+
+    /*
+     * Referrals have failed.  Look up fallback realm if not
+     * originally provided.
+     */
+    if (krb5_is_referral_realm(&supplied_server->realm)) {
+        if (server->length >= 2) {
+	    retval=krb5_get_fallback_host_realm(context, &server->data[1],
+						&hrealms);
+	    if (retval) goto cleanup;
+#if 0
+	    DPRINTF(("gc_from_kdc: using fallback realm of %s\n",
+		     hrealms[0]));
+#endif
+	    krb5_free_data_contents(context,&in_cred->server->realm);
+	    server->realm.data=hrealms[0];
+	    server->realm.length=strlen(hrealms[0]);
+	    free(hrealms);
+	}
+	else {
+	    /*
+	     * Problem case: Realm tagged for referral but apparently not
+	     * in a <type>/<host> format that
+	     * krb5_get_fallback_host_realm can deal with.
+	     */
+	    DPRINTF(("gc_from_kdc: referral specified "
+		     "but no fallback realm avaiable!\n"));
+	    return KRB5_ERR_HOST_REALM_UNKNOWN;
+	}
+    }
+
+    DUMP_PRINC("gc_from_kdc server at fallback after fallback rewrite",
+	       server);
+
+    /*
+     * Get a TGT for the target realm.
+     */
+
+    krb5_free_cred_contents(context, &tgtq);
+    retval = tgt_mcred(context, client, server, client, &tgtq);
+    if (retval)
+	goto cleanup;
+
+    /* Fast path: Is it in the ccache? */
+    /* Free tgtptr data if reused from above. */
+    if (tgtptr == &cc_tgt)
+	krb5_free_cred_contents(context, tgtptr);
+    /* Free TGTS if previously filled by do_traversal() */
+    if (*tgts != NULL) {
+	for (i = 0; (*tgts)[i] != NULL; i++) {
+	    krb5_free_creds(context, (*tgts)[i]);
+	}
+	free(*tgts);
+	*tgts = NULL;
+    }
+    context->use_conf_ktypes = 1;
+    retval = krb5_cc_retrieve_cred(context, ccache, RETR_FLAGS,
+				   &tgtq, &cc_tgt);
+    if (!retval) {
+	tgtptr = &cc_tgt;
+    } else if (!HARD_CC_ERR(retval)) {
+	retval = do_traversal(context, ccache, client, server,
+			      &cc_tgt, &tgtptr, tgts);
+    }
+    if (retval)
+	goto cleanup;
+
+    /*
+     * Finally have TGT for target realm!  Try using it to get creds.
+     */
+
+    if (!krb5_c_valid_enctype(tgtptr->keyblock.enctype)) {
+	retval = KRB5_PROG_ETYPE_NOSUPP;
+	goto cleanup;
+    }
+
+    context->use_conf_ktypes = old_use_conf_ktypes;
+    retval = krb5_get_cred_via_tkt(context, tgtptr,
+				   FLAGS2OPTS(tgtptr->ticket_flags) |
+				   kdcopt |
+				   (in_cred->second_ticket.length ?
+				    KDC_OPT_ENC_TKT_IN_SKEY : 0),
+				   tgtptr->addresses, in_cred, out_cred);
+
+cleanup:
+    krb5_free_cred_contents(context, &tgtq);
+    if (tgtptr == &cc_tgt)
+	krb5_free_cred_contents(context, tgtptr);
+    context->use_conf_ktypes = old_use_conf_ktypes;
+    /* Drop the original principal back into in_cred so that it's cached
+       in the expected format. */
+    DUMP_PRINC("gc_from_kdc: final hacked server principal at cleanup",
+	       server);
+    krb5_free_principal(context, server);
+    in_cred->server = supplied_server;
+    if (*out_cred && !retval) {
+        /* Success: free server, swap supplied server back in. */
+        krb5_free_principal (context, (*out_cred)->server);
+	(*out_cred)->server= out_supplied_server;
+    }
+    else {
+        /* 
+	 * Failure: free out_supplied_server.  Don't free out_cred here
+	 * since it's either null or a referral TGT that we free below,
+	 * and we may need it to return.
+	 */
+        krb5_free_principal (context, out_supplied_server);
+    }
+    DUMP_PRINC("gc_from_kdc: final server after reversion", in_cred->server);
+    /*
+     * Deal with ccache TGT management: If tgts has been set from
+     * initial non-referral TGT discovery, leave it alone.  Otherwise, if
+     * referral_tgts[0] exists return it as the only entry in tgts.
+     * (Further referrals are never cached, only the referral from the
+     * local KDC.)  This is part of cleanup because useful received TGTs
+     * should be cached even if the main request resulted in failure.
+     */
+
+    if (*tgts == NULL) {
+        if (referral_tgts[0]) {
+#if 0
+  	    /*
+	     * This should possibly be a check on the candidate return
+	     * credential against the cache, in the circumstance where we
+	     * don't want to clutter the cache with near-duplicate
+	     * credentials on subsequent iterations.  For now, it is
+	     * disabled.
+	     */
+	    subretval=...?;
+	    if (subretval) {
+#endif
+	        /* Allocate returnable TGT list. */
+	        if (!(*tgts=calloc(sizeof (krb5_creds *), 2)))
+		    return ENOMEM;
+		subretval=krb5_copy_creds(context, referral_tgts[0], &((*tgts)[0]));
+		if(subretval)
+		    return subretval;
+		(*tgts)[1]=NULL;
+		DUMP_PRINC("gc_from_kdc: returning referral TGT for ccache",
+			   (*tgts)[0]->server);
+#if 0
+	    }
+#endif
+	}
+    }
+
+    /* Free referral TGTs list. */
+    for (i=0;i<KRB5_REFERRAL_MAXHOPS;i++) {
+        if(referral_tgts[i]) {
+	    krb5_free_creds(context, referral_tgts[i]);
+	}
+    }
+    DPRINTF(("gc_from_kdc finishing with %s\n",
+	     retval ? error_message(retval) : "no error"));
+    return retval;
+}
+
+krb5_error_code
+krb5_get_cred_from_kdc(krb5_context context, krb5_ccache ccache,
+		       krb5_creds *in_cred, krb5_creds **out_cred,
+		       krb5_creds ***tgts)
+{
+    return krb5_get_cred_from_kdc_opt(context, ccache, in_cred, out_cred, tgts,
+				      0);
+}
+
+krb5_error_code
+krb5_get_cred_from_kdc_validate(krb5_context context, krb5_ccache ccache,
+				krb5_creds *in_cred, krb5_creds **out_cred,
+				krb5_creds ***tgts)
+{
+    return krb5_get_cred_from_kdc_opt(context, ccache, in_cred, out_cred, tgts,
+				      KDC_OPT_VALIDATE);
+}
+
+krb5_error_code
+krb5_get_cred_from_kdc_renew(krb5_context context, krb5_ccache ccache,
+			     krb5_creds *in_cred, krb5_creds **out_cred,
+			     krb5_creds ***tgts)
+{
+    return krb5_get_cred_from_kdc_opt(context, ccache, in_cred, out_cred, tgts,
+				      KDC_OPT_RENEW);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/gc_via_tkt.c b/krb5-1-6/src/lib/krb5/krb/gc_via_tkt.c
new file mode 100644
index 000000000..8ee5721a7
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/gc_via_tkt.c
@@ -0,0 +1,344 @@
+/*
+ * lib/krb5/krb/gc_via_tgt.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Given a tkt, and a target cred, get it.
+ * Assumes that the kdc_rep has been decrypted.
+ */
+
+#include "k5-int.h"
+#include "int-proto.h"
+
+#define in_clock_skew(date, now) (labs((date)-(now)) < context->clockskew)
+
+#define IS_TGS_PRINC(c, p)				\
+    ((krb5_princ_size((c), (p)) == 2) &&		\
+     (krb5_princ_component((c), (p), 0)->length ==	\
+      KRB5_TGS_NAME_SIZE) &&				\
+     (!memcmp(krb5_princ_component((c), (p), 0)->data,	\
+	      KRB5_TGS_NAME, KRB5_TGS_NAME_SIZE)))
+
+static krb5_error_code
+krb5_kdcrep2creds(krb5_context context, krb5_kdc_rep *pkdcrep, krb5_address *const *address, krb5_data *psectkt, krb5_creds **ppcreds)
+{
+    krb5_error_code retval;  
+    krb5_data *pdata;
+  
+    if ((*ppcreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
+        return ENOMEM;
+    }
+
+    memset(*ppcreds, 0, sizeof(krb5_creds));
+
+    if ((retval = krb5_copy_principal(context, pkdcrep->client,
+                                     &(*ppcreds)->client)))
+        goto cleanup;
+
+    if ((retval = krb5_copy_principal(context, pkdcrep->enc_part2->server,
+				      &(*ppcreds)->server)))
+        goto cleanup;
+
+    if ((retval = krb5_copy_keyblock_contents(context, 
+					      pkdcrep->enc_part2->session,
+					      &(*ppcreds)->keyblock)))
+        goto cleanup;
+
+    if ((retval = krb5_copy_data(context, psectkt, &pdata)))
+	goto cleanup;
+    (*ppcreds)->second_ticket = *pdata;
+    krb5_xfree(pdata);
+
+    (*ppcreds)->ticket_flags = pkdcrep->enc_part2->flags;
+    (*ppcreds)->times = pkdcrep->enc_part2->times;
+    (*ppcreds)->magic = KV5M_CREDS;
+
+    (*ppcreds)->authdata = NULL;   			/* not used */
+    (*ppcreds)->is_skey = psectkt->length != 0;
+
+    if (pkdcrep->enc_part2->caddrs) {
+	if ((retval = krb5_copy_addresses(context, pkdcrep->enc_part2->caddrs,
+					  &(*ppcreds)->addresses)))
+	    goto cleanup_keyblock;
+    } else {
+	/* no addresses in the list means we got what we had */
+	if ((retval = krb5_copy_addresses(context, address,
+					  &(*ppcreds)->addresses)))
+	    goto cleanup_keyblock;
+    }
+
+    if ((retval = encode_krb5_ticket(pkdcrep->ticket, &pdata)))
+	goto cleanup_keyblock;
+
+    (*ppcreds)->ticket = *pdata;
+    free(pdata);
+    return 0;
+
+cleanup_keyblock:
+    krb5_free_keyblock(context, &(*ppcreds)->keyblock);
+
+cleanup:
+    free (*ppcreds);
+    return retval;
+}
+ 
+static krb5_error_code
+check_reply_server(krb5_context context, krb5_flags kdcoptions,
+		   krb5_creds *in_cred, krb5_kdc_rep *dec_rep)
+{
+
+    if (!krb5_principal_compare(context, dec_rep->ticket->server,
+				dec_rep->enc_part2->server))
+	return KRB5_KDCREP_MODIFIED;
+
+    /* Reply is self-consistent. */
+
+    if (krb5_principal_compare(context, dec_rep->ticket->server,
+			       in_cred->server))
+	return 0;
+
+    /* Server in reply differs from what we requested. */
+
+    if (kdcoptions & KDC_OPT_CANONICALIZE) {
+	/* in_cred server differs from ticket returned, but ticket
+	   returned is consistent and we requested canonicalization. */
+#if 0
+#ifdef DEBUG_REFERRALS
+	printf("gc_via_tkt: in_cred and encoding don't match but referrals requested\n");
+	krb5int_dbgref_dump_principal("gc_via_tkt: in_cred",in_cred->server);
+	krb5int_dbgref_dump_principal("gc_via_tkt: encoded server",dec_rep->enc_part2->server);
+#endif
+#endif
+	return 0;
+    }
+
+    /* We didn't request canonicalization. */
+
+    if (!IS_TGS_PRINC(context, in_cred->server) ||
+	!IS_TGS_PRINC(context, dec_rep->ticket->server)) {
+	/* Canonicalization not requested, and not a TGS referral. */
+	return KRB5_KDCREP_MODIFIED;
+    }
+#if 0
+    /*
+     * Is this check needed?  find_nxt_kdc() in gc_frm_kdc.c already
+     * effectively checks this.
+     */
+    if (krb5_realm_compare(context, in_cred->client, in_cred->server) &&
+	in_cred->server->data[1].length == in_cred->client->realm.length &&
+	!memcmp(in_cred->client->realm.data, in_cred->server->data[1].data,
+		in_cred->client->realm.length)) {
+	/* Attempted to rewrite local TGS. */
+	return KRB5_KDCREP_MODIFIED;
+    }
+#endif
+    return 0;
+}
+
+krb5_error_code
+krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
+		       krb5_flags kdcoptions, krb5_address *const *address,
+		       krb5_creds *in_cred, krb5_creds **out_cred)
+{
+    krb5_error_code retval;
+    krb5_kdc_rep *dec_rep;
+    krb5_error *err_reply;
+    krb5_response tgsrep;
+    krb5_enctype *enctypes = 0;
+
+#ifdef DEBUG_REFERRALS
+    printf("krb5_get_cred_via_tkt starting; referral flag is %s\n", kdcoptions&KDC_OPT_CANONICALIZE?"on":"off");
+    krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt requested ticket", in_cred->server);
+    krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt TGT in use", tkt->server);
+#endif
+
+    /* tkt->client must be equal to in_cred->client */
+    if (!krb5_principal_compare(context, tkt->client, in_cred->client))
+	return KRB5_PRINC_NOMATCH;
+
+    if (!tkt->ticket.length)
+	return KRB5_NO_TKT_SUPPLIED;
+
+    if ((kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) && 
+	(!in_cred->second_ticket.length))
+        return(KRB5_NO_2ND_TKT);
+
+
+    /* check if we have the right TGT                    */
+    /* tkt->server must be equal to                      */
+    /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
+/*
+    {
+    krb5_principal tempprinc;
+        if (retval = krb5_tgtname(context, 
+		     krb5_princ_realm(context, in_cred->server),
+		     krb5_princ_realm(context, tkt->server), &tempprinc))
+    	    return(retval);
+
+        if (!krb5_principal_compare(context, tempprinc, tkt->server)) {
+            krb5_free_principal(context, tempprinc);
+	    return (KRB5_PRINC_NOMATCH);
+        }
+    krb5_free_principal(context, tempprinc);
+    }
+*/
+
+    if (in_cred->keyblock.enctype) {
+	enctypes = (krb5_enctype *) malloc(sizeof(krb5_enctype)*2);
+	if (!enctypes)
+	    return ENOMEM;
+	enctypes[0] = in_cred->keyblock.enctype;
+	enctypes[1] = 0;
+    }
+    
+    retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, enctypes, 
+			   in_cred->server, address, in_cred->authdata,
+			   0,		/* no padata */
+			   (kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) ? 
+			   &in_cred->second_ticket : NULL,
+			   tkt, &tgsrep);
+    if (enctypes)
+	free(enctypes);
+    if (retval) {
+#ifdef DEBUG_REFERRALS
+        printf("krb5_get_cred_via_tkt ending early after send_tgs with: %s\n",
+	       error_message(retval));
+#endif
+	return retval;
+    }
+
+    switch (tgsrep.message_type) {
+    case KRB5_TGS_REP:
+	break;
+    case KRB5_ERROR:
+    default:
+	if (krb5_is_krb_error(&tgsrep.response))
+	    retval = decode_krb5_error(&tgsrep.response, &err_reply);
+	else
+	    retval = KRB5KRB_AP_ERR_MSG_TYPE;
+
+	if (retval)			/* neither proper reply nor error! */
+	    goto error_4;
+
+	retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
+	if (err_reply->text.length > 0) {
+#if 0
+	    const char *m;
+#endif
+	    switch (err_reply->error) {
+	    case KRB_ERR_GENERIC:
+		krb5_set_error_message(context, retval,
+				       "KDC returned error string: %s",
+				       err_reply->text.data);
+		break;
+	    default:
+#if 0 /* We should stop the KDC from sending back this text, because
+	 if the local language doesn't match the KDC's language, we'd
+	 just wind up printing out the error message in two languages.
+	 Well, when we get some localization.  Which is already
+	 happening in KfM.  */
+		m = error_message(retval);
+		/* Special case: MIT KDC may return this same string
+		   in the e-text field.  */
+		if (strlen (m) == err_reply->text.length-1
+		    && !strcmp(m, err_reply->text.data))
+		    break;
+		krb5_set_error_message(context, retval,
+				       "%s (KDC supplied additional data: %s)",
+				       m, err_reply->text.data);
+#endif
+		break;
+	    }
+	}
+
+	krb5_free_error(context, err_reply);
+	goto error_4;
+    }
+
+    if ((retval = krb5_decode_kdc_rep(context, &tgsrep.response,
+				      &tkt->keyblock, &dec_rep)))
+	goto error_4;
+
+    if (dec_rep->msg_type != KRB5_TGS_REP) {
+	retval = KRB5KRB_AP_ERR_MSG_TYPE;
+	goto error_3;
+    }
+   
+    /* make sure the response hasn't been tampered with..... */
+    retval = 0;
+
+    if (!krb5_principal_compare(context, dec_rep->client, tkt->client))
+	retval = KRB5_KDCREP_MODIFIED;
+
+    if (retval == 0)
+	retval = check_reply_server(context, kdcoptions, in_cred, dec_rep);
+
+    if (dec_rep->enc_part2->nonce != tgsrep.expected_nonce)
+	retval = KRB5_KDCREP_MODIFIED;
+
+    if ((kdcoptions & KDC_OPT_POSTDATED) &&
+	(in_cred->times.starttime != 0) &&
+    	(in_cred->times.starttime != dec_rep->enc_part2->times.starttime))
+	retval = KRB5_KDCREP_MODIFIED;
+
+    if ((in_cred->times.endtime != 0) &&
+	(dec_rep->enc_part2->times.endtime > in_cred->times.endtime))
+	retval = KRB5_KDCREP_MODIFIED;
+
+    if ((kdcoptions & KDC_OPT_RENEWABLE) &&
+	(in_cred->times.renew_till != 0) &&
+	(dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till))
+	retval = KRB5_KDCREP_MODIFIED;
+
+    if ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
+	(dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
+	(in_cred->times.endtime != 0) &&
+	(dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
+ 	retval = KRB5_KDCREP_MODIFIED;
+
+    if (retval != 0)
+    	goto error_3;
+
+    if (!in_cred->times.starttime &&
+	!in_clock_skew(dec_rep->enc_part2->times.starttime,
+		       tgsrep.request_time)) {
+	retval = KRB5_KDCREP_SKEW;
+	goto error_3;
+    }
+    
+    retval = krb5_kdcrep2creds(context, dec_rep, address, 
+			       &in_cred->second_ticket,  out_cred);
+
+error_3:;
+    memset(dec_rep->enc_part2->session->contents, 0,
+	   dec_rep->enc_part2->session->length);
+    krb5_free_kdc_rep(context, dec_rep);
+
+error_4:;
+    free(tgsrep.response.data);
+#ifdef DEBUG_REFERRALS
+    printf("krb5_get_cred_via_tkt ending; %s\n", retval?error_message(retval):"no error");
+#endif
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/gen_seqnum.c b/krb5-1-6/src/lib/krb5/krb/gen_seqnum.c
new file mode 100644
index 000000000..373764097
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/gen_seqnum.c
@@ -0,0 +1,67 @@
+/*
+ * lib/krb5/krb/gen_seqnum.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Routine to automatically generate a starting sequence number.
+ * We do this by getting a random key and encrypting something with it,
+ * then taking the output and slicing it up.
+ */
+
+#include "k5-int.h"
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+krb5_error_code
+krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_ui_4 *seqno)
+{
+    krb5_data seed;
+    krb5_error_code retval;
+
+    seed.length = key->length;
+    seed.data = key->contents;
+    if ((retval = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
+	return(retval);
+
+    seed.length = sizeof(*seqno);
+    seed.data = (char *) seqno;
+    retval = krb5_c_random_make_octets(context, &seed);
+    if (retval)
+	return retval;
+    /*
+     * Work around implementation incompatibilities by not generating
+     * initial sequence numbers greater than 2^30.  Previous MIT
+     * implementations use signed sequence numbers, so initial
+     * sequence numbers 2^31 to 2^32-1 inclusive will be rejected.
+     * Letting the maximum initial sequence number be 2^30-1 allows
+     * for about 2^30 messages to be sent before wrapping into
+     * "negative" numbers.
+     */
+    *seqno &= 0x3fffffff;
+    if (*seqno == 0)
+	*seqno = 1;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/gen_subkey.c b/krb5-1-6/src/lib/krb5/krb/gen_subkey.c
new file mode 100644
index 000000000..7ffc91f13
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/gen_subkey.c
@@ -0,0 +1,52 @@
+/*
+ * lib/krb5/krb/gen_subkey.c
+ *
+ * Copyright 1991, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Routine to automatically generate a subsession key based on an input key.
+ */
+
+#include "k5-int.h"
+
+krb5_error_code
+krb5_generate_subkey(krb5_context context, const krb5_keyblock *key, krb5_keyblock **subkey)
+{
+    krb5_error_code retval;
+    krb5_data seed;
+
+    seed.length = key->length;
+    seed.data = key->contents;
+    if ((retval = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
+	return(retval);
+
+    if ((*subkey = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
+	return(ENOMEM);
+
+    if ((retval = krb5_c_make_random_key(context, key->enctype, *subkey))) {
+	krb5_xfree(*subkey);
+	return(retval);
+    }
+
+    return(0);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/get_creds.c b/krb5-1-6/src/lib/krb5/krb/get_creds.c
new file mode 100644
index 000000000..b3e94f4c6
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/get_creds.c
@@ -0,0 +1,329 @@
+/*
+ * lib/krb5/krb/get_creds.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_get_credentials()
+ */
+
+
+
+/*
+ Attempts to use the credentials cache or TGS exchange to get an additional
+ ticket for the
+ client identified by in_creds->client, the server identified by
+ in_creds->server, with options options, expiration date specified in
+ in_creds->times.endtime (0 means as long as possible), session key type
+ specified in in_creds->keyblock.enctype (if non-zero)
+
+ Any returned ticket and intermediate ticket-granting tickets are
+ stored in ccache.
+
+ returns errors from encryption routines, system errors
+ */
+
+#include "k5-int.h"
+
+static krb5_error_code
+krb5_get_credentials_core(krb5_context context, krb5_flags options,
+			  krb5_creds *in_creds, krb5_creds *mcreds,
+			  krb5_flags *fields)
+{
+    if (!in_creds || !in_creds->server || !in_creds->client)
+        return EINVAL;
+
+    memset((char *)mcreds, 0, sizeof(krb5_creds));
+    mcreds->magic = KV5M_CREDS;
+    if (in_creds->times.endtime != 0) {
+	mcreds->times.endtime = in_creds->times.endtime;
+    } else {
+	krb5_error_code retval;
+	retval = krb5_timeofday(context, &mcreds->times.endtime);
+	if (retval != 0) return retval;
+    }
+    mcreds->keyblock = in_creds->keyblock;
+    mcreds->authdata = in_creds->authdata;
+    mcreds->server = in_creds->server;
+    mcreds->client = in_creds->client;
+    
+    *fields = KRB5_TC_MATCH_TIMES /*XXX |KRB5_TC_MATCH_SKEY_TYPE */
+	| KRB5_TC_MATCH_AUTHDATA
+	| KRB5_TC_SUPPORTED_KTYPES;
+    if (mcreds->keyblock.enctype) {
+	krb5_enctype *ktypes;
+	krb5_error_code ret;
+	int i;
+
+	*fields |= KRB5_TC_MATCH_KTYPE;
+	ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes);
+	for (i = 0; ktypes[i]; i++)
+	    if (ktypes[i] == mcreds->keyblock.enctype)
+		break;
+	if (ktypes[i] == 0)
+	    ret = KRB5_CC_NOT_KTYPE;
+	free (ktypes);
+	if (ret)
+	    return ret;
+    }
+    if (options & KRB5_GC_USER_USER) {
+	/* also match on identical 2nd tkt and tkt encrypted in a
+	   session key */
+	*fields |= KRB5_TC_MATCH_2ND_TKT|KRB5_TC_MATCH_IS_SKEY;
+	mcreds->is_skey = TRUE;
+	mcreds->second_ticket = in_creds->second_ticket;
+	if (!in_creds->second_ticket.length)
+	    return KRB5_NO_2ND_TKT;
+    }
+
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_credentials(krb5_context context, krb5_flags options,
+		     krb5_ccache ccache, krb5_creds *in_creds,
+		     krb5_creds **out_creds)
+{
+    krb5_error_code retval;
+    krb5_creds mcreds;
+    krb5_creds *ncreds;
+    krb5_creds **tgts;
+    krb5_flags fields;
+    int not_ktype;
+
+    retval = krb5_get_credentials_core(context, options,
+				       in_creds,
+				       &mcreds, &fields);
+
+    if (retval) return retval;
+
+    if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL)
+	return ENOMEM;
+
+    memset((char *)ncreds, 0, sizeof(krb5_creds));
+    ncreds->magic = KV5M_CREDS;
+
+    /* The caller is now responsible for cleaning up in_creds */
+    if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds,
+					ncreds))) {
+	krb5_xfree(ncreds);
+	ncreds = in_creds;
+    } else {
+	*out_creds = ncreds;
+    }
+
+    if ((retval != KRB5_CC_NOTFOUND && retval != KRB5_CC_NOT_KTYPE)
+	|| options & KRB5_GC_CACHED)
+	return retval;
+
+    if (retval == KRB5_CC_NOT_KTYPE)
+	not_ktype = 1;
+    else
+	not_ktype = 0;
+
+    retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts);
+    if (tgts) {
+	register int i = 0;
+	krb5_error_code rv2;
+	while (tgts[i]) {
+	    if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i]))) {
+		retval = rv2;
+		break;
+	    }
+	    i++;
+	}
+	krb5_free_tgt_creds(context, tgts);
+    }
+    /*
+     * Translate KRB5_CC_NOTFOUND if we previously got
+     * KRB5_CC_NOT_KTYPE from krb5_cc_retrieve_cred(), in order to
+     * handle the case where there is no TGT in the ccache and the
+     * input enctype didn't match.  This handling is necessary because
+     * some callers, such as GSSAPI, iterate through enctypes and
+     * KRB5_CC_NOTFOUND passed through from the
+     * krb5_get_cred_from_kdc() is semantically incorrect, since the
+     * actual failure was the non-existence of a ticket of the correct
+     * enctype rather than the missing TGT.
+     */
+    if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE)
+	&& not_ktype)
+	retval = KRB5_CC_NOT_KTYPE;
+
+    if (!retval) {
+        /* the purpose of the krb5_get_credentials call is to 
+         * obtain a set of credentials for the caller.  the 
+         * krb5_cc_store_cred() call is to optimize performance
+         * for future calls.  Ignore any errors, since the credentials
+         * are still valid even if we fail to store them in the cache.
+         */
+	krb5_cc_store_cred(context, ccache, *out_creds);
+    }
+    return retval;
+}
+
+#define INT_GC_VALIDATE 1
+#define INT_GC_RENEW 2
+
+static krb5_error_code 
+krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
+				    krb5_ccache ccache, krb5_creds *in_creds,
+				    krb5_creds **out_creds, int which)
+{
+    krb5_error_code retval;
+    krb5_principal tmp;
+    krb5_creds **tgts = 0;
+
+    switch(which) {
+    case INT_GC_VALIDATE:
+	    retval = krb5_get_cred_from_kdc_validate(context, ccache, 
+					     in_creds, out_creds, &tgts);
+	    break;
+    case INT_GC_RENEW:
+	    retval = krb5_get_cred_from_kdc_renew(context, ccache, 
+					     in_creds, out_creds, &tgts);
+	    break;
+    default:
+	    /* Should never happen */
+	    retval = 255;
+	    break;
+    }
+    if (retval) return retval;
+    if (tgts) krb5_free_tgt_creds(context, tgts);
+
+    retval = krb5_cc_get_principal(context, ccache, &tmp);
+    if (retval) return retval;
+    
+    retval = krb5_cc_initialize(context, ccache, tmp);
+    if (retval) return retval;
+    
+    retval = krb5_cc_store_cred(context, ccache, *out_creds);
+    return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_credentials_validate(krb5_context context, krb5_flags options,
+			      krb5_ccache ccache, krb5_creds *in_creds,
+			      krb5_creds **out_creds)
+{
+    return(krb5_get_credentials_val_renew_core(context, options, ccache, 
+					       in_creds, out_creds, 
+					       INT_GC_VALIDATE));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_credentials_renew(krb5_context context, krb5_flags options,
+			   krb5_ccache ccache, krb5_creds *in_creds,
+			   krb5_creds **out_creds)
+{
+
+    return(krb5_get_credentials_val_renew_core(context, options, ccache, 
+					       in_creds, out_creds, 
+					       INT_GC_RENEW));
+}
+
+static krb5_error_code
+krb5_validate_or_renew_creds(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 = 0; /* for check before dereferencing below */
+    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 */
+    if (out_creds) {
+	*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_error_code KRB5_CALLCONV
+krb5_get_validated_creds(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_error_code KRB5_CALLCONV
+krb5_get_renewed_creds(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/krb5-1-6/src/lib/krb5/krb/get_in_tkt.c b/krb5-1-6/src/lib/krb5/krb/get_in_tkt.c
new file mode 100644
index 000000000..ee0a1127e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/get_in_tkt.c
@@ -0,0 +1,1308 @@
+/*
+ * lib/krb5/krb/get_in_tkt.c
+ *
+ * Copyright 1990,1991, 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_get_in_tkt()
+ */
+
+#include <string.h>
+
+#include "k5-int.h"
+#include "int-proto.h"
+#include "os-proto.h"
+
+/*
+ All-purpose initial ticket routine, usually called via
+ krb5_get_in_tkt_with_password or krb5_get_in_tkt_with_skey.
+
+ Attempts to get an initial ticket for creds->client to use server
+ creds->server, (realm is taken from creds->client), with options
+ options, and using creds->times.starttime, creds->times.endtime,
+ creds->times.renew_till as from, till, and rtime.  
+ creds->times.renew_till is ignored unless the RENEWABLE option is requested.
+
+ key_proc is called to fill in the key to be used for decryption.
+ keyseed is passed on to key_proc.
+
+ decrypt_proc is called to perform the decryption of the response (the
+ encrypted part is in dec_rep->enc_part; the decrypted part should be
+ allocated and filled into dec_rep->enc_part2
+ arg is passed on to decrypt_proc.
+
+ If addrs is non-NULL, it is used for the addresses requested.  If it is
+ null, the system standard addresses are used.
+
+ A succesful call will place the ticket in the credentials cache ccache
+ and fill in creds with the ticket information used/returned..
+
+ returns system errors, encryption errors
+
+ */
+
+
+/* some typedef's for the function args to make things look a bit cleaner */
+
+typedef krb5_error_code (*git_key_proc) (krb5_context,
+						   const krb5_enctype,
+						   krb5_data *,
+						   krb5_const_pointer,
+						   krb5_keyblock **);
+
+typedef krb5_error_code (*git_decrypt_proc) (krb5_context,
+						       const krb5_keyblock *,
+						       krb5_const_pointer,
+						       krb5_kdc_rep * );
+
+static krb5_error_code make_preauth_list (krb5_context, 
+						    krb5_preauthtype *,
+						    int, krb5_pa_data ***);
+static krb5_error_code sort_krb5_padata_sequence(krb5_context context,
+						 krb5_data *realm,
+						 krb5_pa_data **padata);
+
+/*
+ * This function performs 32 bit bounded addition so we can generate
+ * lifetimes without overflowing krb5_int32
+ */
+static krb5_int32 krb5int_addint32 (krb5_int32 x, krb5_int32 y)
+{
+    if ((x > 0) && (y > (KRB5_INT32_MAX - x))) {
+        /* sum will be be greater than KRB5_INT32_MAX */
+        return KRB5_INT32_MAX;
+    } else if ((x < 0) && (y < (KRB5_INT32_MIN - x))) {
+        /* sum will be less than KRB5_INT32_MIN */
+        return KRB5_INT32_MIN;
+    }
+    
+    return x + y;
+}
+
+/*
+ * This function sends a request to the KDC, and gets back a response;
+ * the response is parsed into ret_err_reply or ret_as_reply if the
+ * reponse is a KRB_ERROR or a KRB_AS_REP packet.  If it is some other
+ * unexpected response, an error is returned.
+ */
+static krb5_error_code
+send_as_request(krb5_context 		context,
+		krb5_kdc_req		*request,
+		krb5_error ** 		ret_err_reply,
+		krb5_kdc_rep ** 	ret_as_reply,
+		int 			    *use_master)
+{
+    krb5_kdc_rep *as_reply = 0;
+    krb5_error_code retval;
+    krb5_data *packet = 0;
+    krb5_data reply;
+    char k4_version;		/* same type as *(krb5_data::data) */
+    int tcp_only = 0;
+    krb5_timestamp time_now;
+
+    reply.data = 0;
+
+    /* set the nonce if the caller expects us to do it */
+    if (request->nonce == 0) {
+        if ((retval = krb5_timeofday(context, &time_now)))
+	    goto cleanup;
+        request->nonce = (krb5_int32) time_now;
+    }
+
+    /* encode & send to KDC */
+    if ((retval = encode_krb5_as_req(request, &packet)) != 0)
+	goto cleanup;
+
+    k4_version = packet->data[0];
+send_again:
+    retval = krb5_sendto_kdc(context, packet, 
+			     krb5_princ_realm(context, request->client),
+			     &reply, use_master, tcp_only);
+    if (retval)
+	goto cleanup;
+
+    /* now decode the reply...could be error or as_rep */
+    if (krb5_is_krb_error(&reply)) {
+	krb5_error *err_reply;
+
+	if ((retval = decode_krb5_error(&reply, &err_reply)))
+	    /* some other error code--??? */	    
+	    goto cleanup;
+    
+	if (ret_err_reply) {
+	    if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG
+		&& tcp_only == 0) {
+		tcp_only = 1;
+		krb5_free_error(context, err_reply);
+		free(reply.data);
+		reply.data = 0;
+		goto send_again;
+	    }
+	    *ret_err_reply = err_reply;
+	} else
+	    krb5_free_error(context, err_reply);
+	goto cleanup;
+    }
+
+    /*
+     * Check to make sure it isn't a V4 reply.
+     */
+    if (!krb5_is_as_rep(&reply)) {
+/* these are in <kerberosIV/prot.h> as well but it isn't worth including. */
+#define V4_KRB_PROT_VERSION	4
+#define V4_AUTH_MSG_ERR_REPLY	(5<<1)
+	/* check here for V4 reply */
+	unsigned int t_switch;
+
+	/* From v4 g_in_tkt.c: This used to be
+	   switch (pkt_msg_type(rpkt) & ~1) {
+	   but SCO 3.2v4 cc compiled that incorrectly.  */
+	t_switch = reply.data[1];
+	t_switch &= ~1;
+
+	if (t_switch == V4_AUTH_MSG_ERR_REPLY
+	    && (reply.data[0] == V4_KRB_PROT_VERSION
+		|| reply.data[0] == k4_version)) {
+	    retval = KRB5KRB_AP_ERR_V4_REPLY;
+	} else {
+	    retval = KRB5KRB_AP_ERR_MSG_TYPE;
+	}
+	goto cleanup;
+    }
+
+    /* It must be a KRB_AS_REP message, or an bad returned packet */
+    if ((retval = decode_krb5_as_rep(&reply, &as_reply)))
+	/* some other error code ??? */
+	goto cleanup;
+
+    if (as_reply->msg_type != KRB5_AS_REP) {
+	retval = KRB5KRB_AP_ERR_MSG_TYPE;
+	krb5_free_kdc_rep(context, as_reply);
+	goto cleanup;
+    }
+
+    if (ret_as_reply)
+	*ret_as_reply = as_reply;
+    else
+	krb5_free_kdc_rep(context, as_reply);
+
+cleanup:
+    if (packet)
+	krb5_free_data(context, packet);
+    if (reply.data)
+	free(reply.data);
+    return retval;
+}
+
+static krb5_error_code
+decrypt_as_reply(krb5_context 		context,
+		 krb5_kdc_req		*request,
+		 krb5_kdc_rep		*as_reply,
+		 git_key_proc 		key_proc,
+		 krb5_const_pointer 	keyseed,
+		 krb5_keyblock *	key,
+		 git_decrypt_proc 	decrypt_proc,
+		 krb5_const_pointer 	decryptarg)
+{
+    krb5_error_code		retval;
+    krb5_keyblock *		decrypt_key = 0;
+    krb5_data 			salt;
+    
+    if (as_reply->enc_part2)
+	return 0;
+
+    if (key)
+	    decrypt_key = key;
+    else {
+	if ((retval = krb5_principal2salt(context, request->client, &salt)))
+	    return(retval);
+    
+	retval = (*key_proc)(context, as_reply->enc_part.enctype,
+			     &salt, keyseed, &decrypt_key);
+	krb5_xfree(salt.data);
+	if (retval)
+	    goto cleanup;
+    }
+    
+    if ((retval = (*decrypt_proc)(context, decrypt_key, decryptarg, as_reply)))
+	goto cleanup;
+
+cleanup:
+    if (!key && decrypt_key)
+	krb5_free_keyblock(context, decrypt_key);
+    return (retval);
+}
+
+static krb5_error_code
+verify_as_reply(krb5_context 		context,
+		krb5_timestamp 		time_now,
+		krb5_kdc_req		*request,
+		krb5_kdc_rep		*as_reply)
+{
+    krb5_error_code		retval;
+    
+    /* check the contents for sanity: */
+    if (!as_reply->enc_part2->times.starttime)
+	as_reply->enc_part2->times.starttime =
+	    as_reply->enc_part2->times.authtime;
+    
+    if (!krb5_principal_compare(context, as_reply->client, request->client)
+	|| !krb5_principal_compare(context, as_reply->enc_part2->server, request->server)
+	|| !krb5_principal_compare(context, as_reply->ticket->server, request->server)
+	|| (request->nonce != as_reply->enc_part2->nonce)
+	/* XXX check for extraneous flags */
+	/* XXX || (!krb5_addresses_compare(context, addrs, as_reply->enc_part2->caddrs)) */
+	|| ((request->kdc_options & KDC_OPT_POSTDATED) &&
+	    (request->from != 0) &&
+	    (request->from != as_reply->enc_part2->times.starttime))
+	|| ((request->till != 0) &&
+	    (as_reply->enc_part2->times.endtime > request->till))
+	|| ((request->kdc_options & KDC_OPT_RENEWABLE) &&
+	    (request->rtime != 0) &&
+	    (as_reply->enc_part2->times.renew_till > request->rtime))
+	|| ((request->kdc_options & KDC_OPT_RENEWABLE_OK) &&
+	    !(request->kdc_options & KDC_OPT_RENEWABLE) &&
+	    (as_reply->enc_part2->flags & KDC_OPT_RENEWABLE) &&
+	    (request->till != 0) &&
+	    (as_reply->enc_part2->times.renew_till > request->till))
+	)
+	return KRB5_KDCREP_MODIFIED;
+
+    if (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) {
+	retval = krb5_set_real_time(context,
+				    as_reply->enc_part2->times.authtime, 0);
+	if (retval)
+	    return retval;
+    } else {
+	if ((request->from == 0) &&
+	    (labs(as_reply->enc_part2->times.starttime - time_now)
+	     > context->clockskew))
+	    return (KRB5_KDCREP_SKEW);
+    }
+    return 0;
+}
+
+static krb5_error_code
+stash_as_reply(krb5_context 		context,
+	       krb5_timestamp 		time_now,
+	       krb5_kdc_req		*request,
+	       krb5_kdc_rep		*as_reply,
+	       krb5_creds * 		creds,
+	       krb5_ccache 		ccache)
+{
+    krb5_error_code 		retval;
+    krb5_data *			packet;
+    krb5_principal		client;
+    krb5_principal		server;
+
+    client = NULL;
+    server = NULL;
+
+    if (!creds->client)
+        if ((retval = krb5_copy_principal(context, as_reply->client, &client)))
+	    goto cleanup;
+
+    if (!creds->server)
+	if ((retval = krb5_copy_principal(context, as_reply->enc_part2->server,
+					  &server)))
+	    goto cleanup;
+
+    /* fill in the credentials */
+    if ((retval = krb5_copy_keyblock_contents(context, 
+					      as_reply->enc_part2->session,
+					      &creds->keyblock)))
+	goto cleanup;
+
+    creds->times = as_reply->enc_part2->times;
+    creds->is_skey = FALSE;		/* this is an AS_REQ, so cannot
+					   be encrypted in skey */
+    creds->ticket_flags = as_reply->enc_part2->flags;
+    if ((retval = krb5_copy_addresses(context, as_reply->enc_part2->caddrs,
+				      &creds->addresses)))
+	goto cleanup;
+
+    creds->second_ticket.length = 0;
+    creds->second_ticket.data = 0;
+
+    if ((retval = encode_krb5_ticket(as_reply->ticket, &packet)))
+	goto cleanup;
+
+    creds->ticket = *packet;
+    krb5_xfree(packet);
+
+    /* store it in the ccache! */
+    if (ccache)
+	if ((retval = krb5_cc_store_cred(context, ccache, creds)))
+	    goto cleanup;
+
+    if (!creds->client)
+	creds->client = client;
+    if (!creds->server)
+	creds->server = server;
+
+cleanup:
+    if (retval) {
+	if (client)
+	    krb5_free_principal(context, client);
+	if (server)
+	    krb5_free_principal(context, server);
+	if (creds->keyblock.contents) {
+	    memset((char *)creds->keyblock.contents, 0,
+		   creds->keyblock.length);
+	    krb5_xfree(creds->keyblock.contents);
+	    creds->keyblock.contents = 0;
+	    creds->keyblock.length = 0;
+	}
+	if (creds->ticket.data) {
+	    krb5_xfree(creds->ticket.data);
+	    creds->ticket.data = 0;
+	}
+	if (creds->addresses) {
+	    krb5_free_addresses(context, creds->addresses);
+	    creds->addresses = 0;
+	}
+    }
+    return (retval);
+}
+
+static krb5_error_code
+make_preauth_list(krb5_context	context,
+		  krb5_preauthtype *	ptypes,
+		  int			nptypes,
+		  krb5_pa_data ***	ret_list)
+{
+    krb5_preauthtype *		ptypep;
+    krb5_pa_data **		preauthp;
+    int				i;
+
+    if (nptypes < 0) {
+ 	for (nptypes=0, ptypep = ptypes; *ptypep; ptypep++, nptypes++)
+ 	    ;
+    }
+ 
+    /* allocate space for a NULL to terminate the list */
+ 
+    if ((preauthp =
+ 	 (krb5_pa_data **) malloc((nptypes+1)*sizeof(krb5_pa_data *))) == NULL)
+ 	return(ENOMEM);
+ 
+    for (i=0; i<nptypes; i++) {
+ 	if ((preauthp[i] =
+ 	     (krb5_pa_data *) malloc(sizeof(krb5_pa_data))) == NULL) {
+ 	    for (; i>=0; i++)
+ 		free(preauthp[i]);
+ 	    free(preauthp);
+	    return (ENOMEM);
+	}
+ 	preauthp[i]->magic = KV5M_PA_DATA;
+ 	preauthp[i]->pa_type = ptypes[i];
+ 	preauthp[i]->length = 0;
+ 	preauthp[i]->contents = 0;
+    }
+     
+    /* fill in the terminating NULL */
+ 
+    preauthp[nptypes] = NULL;
+ 
+    *ret_list = preauthp;
+    return 0;
+}
+
+#define MAX_IN_TKT_LOOPS 16
+static const krb5_enctype get_in_tkt_enctypes[] = {
+    ENCTYPE_DES3_CBC_SHA1,
+    ENCTYPE_ARCFOUR_HMAC,
+    ENCTYPE_DES_CBC_MD5,
+    ENCTYPE_DES_CBC_MD4,
+    ENCTYPE_DES_CBC_CRC,
+    0
+};
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_in_tkt(krb5_context context,
+		const krb5_flags options,
+		krb5_address * const * addrs,
+		krb5_enctype * ktypes,
+		krb5_preauthtype * ptypes,
+		git_key_proc key_proc,
+		krb5_const_pointer keyseed,
+		git_decrypt_proc decrypt_proc,
+		krb5_const_pointer decryptarg,
+		krb5_creds * creds,
+		krb5_ccache ccache,
+		krb5_kdc_rep ** ret_as_reply)
+{
+    krb5_error_code	retval;
+    krb5_timestamp	time_now;
+    krb5_keyblock *	decrypt_key = 0;
+    krb5_kdc_req	request;
+    krb5_pa_data	**padata = 0;
+    krb5_error *	err_reply;
+    krb5_kdc_rep *	as_reply = 0;
+    krb5_pa_data  **	preauth_to_use = 0;
+    int			loopcount = 0;
+    krb5_int32		do_more = 0;
+    int             use_master = 0;
+
+    if (! krb5_realm_compare(context, creds->client, creds->server))
+	return KRB5_IN_TKT_REALM_MISMATCH;
+
+    if (ret_as_reply)
+	*ret_as_reply = 0;
+    
+    /*
+     * Set up the basic request structure
+     */
+    request.magic = KV5M_KDC_REQ;
+    request.msg_type = KRB5_AS_REQ;
+    request.addresses = 0;
+    request.ktype = 0;
+    request.padata = 0;
+    if (addrs)
+	request.addresses = (krb5_address **) addrs;
+    else
+	if ((retval = krb5_os_localaddr(context, &request.addresses)))
+	    goto cleanup;
+    request.kdc_options = options;
+    request.client = creds->client;
+    request.server = creds->server;
+    request.nonce = 0;
+    request.from = creds->times.starttime;
+    request.till = creds->times.endtime;
+    request.rtime = creds->times.renew_till;
+
+    request.ktype = malloc (sizeof(get_in_tkt_enctypes));
+    if (request.ktype == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    memcpy(request.ktype, get_in_tkt_enctypes, sizeof(get_in_tkt_enctypes));
+    for (request.nktypes = 0;request.ktype[request.nktypes];request.nktypes++);
+    if (ktypes) {
+	int i, req, next = 0;
+	for (req = 0; ktypes[req]; req++) {
+	    if (ktypes[req] == request.ktype[next]) {
+		next++;
+		continue;
+	    }
+	    for (i = next + 1; i < request.nktypes; i++)
+		if (ktypes[req] == request.ktype[i]) {
+		    /* Found the enctype we want, but not in the
+		       position we want.  Move it, but keep the old
+		       one from the desired slot around in case it's
+		       later in our requested-ktypes list.  */
+		    krb5_enctype t;
+		    t = request.ktype[next];
+		    request.ktype[next] = request.ktype[i];
+		    request.ktype[i] = t;
+		    next++;
+		    break;
+		}
+	    /* If we didn't find it, don't do anything special, just
+	       drop it.  */
+	}
+	request.ktype[next] = 0;
+	request.nktypes = next;
+    }
+    request.authorization_data.ciphertext.length = 0;
+    request.authorization_data.ciphertext.data = 0;
+    request.unenc_authdata = 0;
+    request.second_ticket = 0;
+
+    /*
+     * If a list of preauth types are passed in, convert it to a
+     * preauth_to_use list.
+     */
+    if (ptypes) {
+	retval = make_preauth_list(context, ptypes, -1, &preauth_to_use);
+	if (retval)
+	    goto cleanup;
+    }
+	    
+    while (1) {
+	if (loopcount++ > MAX_IN_TKT_LOOPS) {
+	    retval = KRB5_GET_IN_TKT_LOOP;
+	    goto cleanup;
+	}
+
+	if ((retval = krb5_obtain_padata(context, preauth_to_use, key_proc,
+					 keyseed, creds, &request)) != 0)
+	    goto cleanup;
+	if (preauth_to_use)
+	    krb5_free_pa_data(context, preauth_to_use);
+	preauth_to_use = 0;
+	
+	err_reply = 0;
+	as_reply = 0;
+
+        if ((retval = krb5_timeofday(context, &time_now)))
+	    goto cleanup;
+
+        /*
+         * XXX we know they are the same size... and we should do
+         * something better than just the current time
+         */
+	request.nonce = (krb5_int32) time_now;
+
+	if ((retval = send_as_request(context, &request, &err_reply,
+				      &as_reply, &use_master)))
+	    goto cleanup;
+
+	if (err_reply) {
+	    if (err_reply->error == KDC_ERR_PREAUTH_REQUIRED &&
+		err_reply->e_data.length > 0) {
+		retval = decode_krb5_padata_sequence(&err_reply->e_data,
+						     &preauth_to_use);
+		krb5_free_error(context, err_reply);
+		if (retval)
+		    goto cleanup;
+                retval = sort_krb5_padata_sequence(context,
+						   &request.server->realm,
+						   padata);
+		if (retval)
+		    goto cleanup;
+		continue;
+	    } else {
+		retval = (krb5_error_code) err_reply->error 
+		    + ERROR_TABLE_BASE_krb5;
+		krb5_free_error(context, err_reply);
+		goto cleanup;
+	    }
+	} else if (!as_reply) {
+	    retval = KRB5KRB_AP_ERR_MSG_TYPE;
+	    goto cleanup;
+	}
+	if ((retval = krb5_process_padata(context, &request, as_reply,
+					  key_proc, keyseed, decrypt_proc, 
+					  &decrypt_key, creds,
+					  &do_more)) != 0)
+	    goto cleanup;
+
+	if (!do_more)
+	    break;
+    }
+    
+    if ((retval = decrypt_as_reply(context, &request, as_reply, key_proc,
+				   keyseed, decrypt_key, decrypt_proc,
+				   decryptarg)))
+	goto cleanup;
+
+    if ((retval = verify_as_reply(context, time_now, &request, as_reply)))
+	goto cleanup;
+
+    if ((retval = stash_as_reply(context, time_now, &request, as_reply,
+				 creds, ccache)))
+	goto cleanup;
+
+cleanup:
+    if (request.ktype)
+	free(request.ktype);
+    if (!addrs && request.addresses)
+	krb5_free_addresses(context, request.addresses);
+    if (request.padata)
+	krb5_free_pa_data(context, request.padata);
+    if (padata)
+	krb5_free_pa_data(context, padata);
+    if (preauth_to_use)
+	krb5_free_pa_data(context, preauth_to_use);
+    if (decrypt_key)
+    	krb5_free_keyblock(context, decrypt_key);
+    if (as_reply) {
+	if (ret_as_reply)
+	    *ret_as_reply = as_reply;
+	else
+	    krb5_free_kdc_rep(context, as_reply);
+    }
+    return (retval);
+}
+
+/* begin libdefaults parsing code.  This should almost certainly move
+   somewhere else, but I don't know where the correct somewhere else
+   is yet. */
+
+/* XXX Duplicating this is annoying; try to work on a better way.*/
+static const char *const conf_yes[] = {
+    "y", "yes", "true", "t", "1", "on",
+    0,
+};
+
+static const char *const conf_no[] = {
+    "n", "no", "false", "nil", "0", "off",
+    0,
+};
+
+int
+_krb5_conf_boolean(const char *s)
+{
+    const char *const *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;
+    }
+
+    /* Default to "no" */
+    return 0;
+}
+
+static krb5_error_code
+krb5_libdefault_string(krb5_context context, const krb5_data *realm,
+		       const char *option, char **ret_value)
+{
+    profile_t profile;
+    const char *names[5];
+    char **nameval = NULL;
+    krb5_error_code retval;
+    char realmstr[1024];
+
+    if (realm->length > sizeof(realmstr)-1)
+	return(EINVAL);
+
+    strncpy(realmstr, realm->data, realm->length);
+    realmstr[realm->length] = '\0';
+
+    if (!context || (context->magic != KV5M_CONTEXT)) 
+	return KV5M_CONTEXT;
+
+    profile = context->profile;
+	    
+    names[0] = "libdefaults";
+
+    /*
+     * Try number one:
+     *
+     * [libdefaults]
+     *		REALM = {
+     *			option = <boolean>
+     *		}
+     */
+
+    names[1] = realmstr;
+    names[2] = option;
+    names[3] = 0;
+    retval = profile_get_values(profile, names, &nameval);
+    if (retval == 0 && nameval && nameval[0])
+	goto goodbye;
+
+    /*
+     * Try number two:
+     *
+     * [libdefaults]
+     *		option = <boolean>
+     */
+    
+    names[1] = option;
+    names[2] = 0;
+    retval = profile_get_values(profile, names, &nameval);
+    if (retval == 0 && nameval && nameval[0])
+	goto goodbye;
+
+goodbye:
+    if (!nameval) 
+	return(ENOENT);
+
+    if (!nameval[0]) {
+        retval = ENOENT;
+    } else {
+        *ret_value = malloc(strlen(nameval[0]) + 1);
+        if (!*ret_value)
+            retval = ENOMEM;
+        else
+            strcpy(*ret_value, nameval[0]);
+    }
+
+    profile_free_list(nameval);
+
+    return retval;
+}
+
+/* not static so verify_init_creds() can call it */
+/* as well as the DNS code */
+
+krb5_error_code
+krb5_libdefault_boolean(krb5_context context, const krb5_data *realm,
+			const char *option, int *ret_value)
+{
+    char *string = NULL;
+    krb5_error_code retval;
+
+    retval = krb5_libdefault_string(context, realm, option, &string);
+
+    if (retval)
+	return(retval);
+
+    *ret_value = _krb5_conf_boolean(string);
+    free(string);
+
+    return(0);
+}
+
+/* Sort a pa_data sequence so that types named in the "preferred_preauth_types"
+ * libdefaults entry are listed before any others. */
+static krb5_error_code
+sort_krb5_padata_sequence(krb5_context context, krb5_data *realm,
+			  krb5_pa_data **padata)
+{
+    int i, j, base;
+    krb5_error_code ret;
+    const char *p;
+    long l;
+    char *q, *preauth_types = NULL;
+    krb5_pa_data *tmp;
+    int need_free_string = 1;
+
+    if ((padata == NULL) || (padata[0] == NULL)) {
+	return 0;
+    }
+
+    ret = krb5_libdefault_string(context, realm, "preferred_preauth_types",
+				 &preauth_types);
+    if ((ret != 0) || (preauth_types == NULL)) {
+	/* Try to use PKINIT first. */
+	preauth_types = "17, 16, 15, 14";
+	need_free_string = 0;
+    }
+
+#ifdef DEBUG
+    fprintf (stderr, "preauth data types before sorting:");
+    for (i = 0; padata[i]; i++) {
+	fprintf (stderr, " %d", padata[i]->pa_type);
+    }
+    fprintf (stderr, "\n");
+#endif
+
+    base = 0;
+    for (p = preauth_types; *p != '\0';) {
+	/* skip whitespace to find an entry */
+	p += strspn(p, ", ");
+	if (*p != '\0') {
+	    /* see if we can extract a number */
+	    l = strtol(p, &q, 10);
+	    if ((q != NULL) && (q > p)) {
+		/* got a valid number; search for a matchin entry */
+		for (i = base; padata[i] != NULL; i++) {
+		    /* bubble the matching entry to the front of the list */
+		    if (padata[i]->pa_type == l) {
+			tmp = padata[i];
+			for (j = i; j > base; j--)
+			    padata[j] = padata[j - 1];
+			padata[base] = tmp;
+			base++;
+			break;
+		    }
+		}
+		p = q;
+	    } else {
+		break;
+	    }
+	}
+    }
+    if (need_free_string)
+	free(preauth_types);
+
+#ifdef DEBUG
+    fprintf (stderr, "preauth data types after sorting:");
+    for (i = 0; padata[i]; i++)
+	fprintf (stderr, " %d", padata[i]->pa_type);
+    fprintf (stderr, "\n");
+#endif
+
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds(krb5_context context,
+		    krb5_creds *creds,
+		    krb5_principal client,
+		    krb5_prompter_fct prompter,
+		    void *prompter_data,
+		    krb5_deltat start_time,
+		    char *in_tkt_service,
+		    krb5_gic_opt_ext *options,
+		    krb5_gic_get_as_key_fct gak_fct,
+		    void *gak_data,
+		    int  *use_master,
+		    krb5_kdc_rep **as_reply)
+{
+    krb5_error_code ret;
+    krb5_kdc_req request;
+    krb5_data *encoded_request_body, *encoded_previous_request;
+    krb5_pa_data **preauth_to_use, **kdc_padata;
+    int tempint;
+    char *tempstr;
+    krb5_deltat tkt_life;
+    krb5_deltat renew_life;
+    int loopcount;
+    krb5_data salt;
+    krb5_data s2kparams;
+    krb5_keyblock as_key;
+    krb5_error *err_reply;
+    krb5_kdc_rep *local_as_reply;
+    krb5_timestamp time_now;
+    krb5_enctype etype = 0;
+    krb5_preauth_client_rock get_data_rock;
+
+    /* initialize everything which will be freed at cleanup */
+
+    s2kparams.data = NULL;
+    s2kparams.length = 0;
+    request.server = NULL;
+    request.ktype = NULL;
+    request.addresses = NULL;
+    request.padata = NULL;
+    encoded_request_body = NULL;
+    encoded_previous_request = NULL;
+    preauth_to_use = NULL;
+    kdc_padata = NULL;
+    as_key.length = 0;
+    salt.length = 0;
+    salt.data = NULL;
+
+	local_as_reply = 0;
+
+    err_reply = NULL;
+
+    /*
+     * Set up the basic request structure
+     */
+    request.magic = KV5M_KDC_REQ;
+    request.msg_type = KRB5_AS_REQ;
+
+    /* request.nonce is filled in when we send a request to the kdc */
+    request.nonce = 0;
+
+    /* request.padata is filled in later */
+
+    request.kdc_options = context->kdc_default_options;
+
+    /* forwardable */
+
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE))
+	tempint = options->forwardable;
+    else if ((ret = krb5_libdefault_boolean(context, &client->realm,
+					    "forwardable", &tempint)) == 0)
+	    ;
+    else
+	tempint = 0;
+    if (tempint)
+	request.kdc_options |= KDC_OPT_FORWARDABLE;
+
+    /* proxiable */
+
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE))
+	tempint = options->proxiable;
+    else if ((ret = krb5_libdefault_boolean(context, &client->realm,
+					    "proxiable", &tempint)) == 0)
+	    ;
+    else
+	tempint = 0;
+    if (tempint)
+	request.kdc_options |= KDC_OPT_PROXIABLE;
+
+    /* allow_postdate */
+    
+    if (start_time > 0)
+	request.kdc_options |= (KDC_OPT_ALLOW_POSTDATE|KDC_OPT_POSTDATED);
+    
+    /* ticket lifetime */
+    
+    if ((ret = krb5_timeofday(context, &request.from)))
+	goto cleanup;
+    request.from = krb5int_addint32(request.from, start_time);
+    
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)) {
+        tkt_life = options->tkt_life;
+    } else if ((ret = krb5_libdefault_string(context, &client->realm,
+					     "ticket_lifetime", &tempstr))
+	       == 0) {
+	ret = krb5_string_to_deltat(tempstr, &tkt_life);
+	free(tempstr);
+	if (ret) {
+	    goto cleanup;
+	}
+    } else {
+	/* this used to be hardcoded in kinit.c */
+	tkt_life = 24*60*60;
+    }
+    request.till = krb5int_addint32(request.from, tkt_life);
+    
+    /* renewable lifetime */
+    
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)) {
+	renew_life = options->renew_life;
+    } else if ((ret = krb5_libdefault_string(context, &client->realm,
+					     "renew_lifetime", &tempstr))
+	       == 0) {
+	ret = krb5_string_to_deltat(tempstr, &renew_life);
+	free(tempstr);
+	if (ret) {
+	    goto cleanup;
+	}
+    } else {
+	renew_life = 0;
+    }
+    if (renew_life > 0)
+	request.kdc_options |= KDC_OPT_RENEWABLE;
+    
+    if (renew_life > 0) {
+	request.rtime = krb5int_addint32(request.from, renew_life);
+        if (request.rtime < request.till) {
+            /* don't ask for a smaller renewable time than the lifetime */
+            request.rtime = request.till;
+        }
+        /* we are already asking for renewable tickets so strip this option */
+	request.kdc_options &= ~(KDC_OPT_RENEWABLE_OK);
+    } else {
+	request.rtime = 0;
+    }
+    
+    /* client */
+
+    request.client = client;
+
+    /* service */
+    
+    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, &request.server)))
+	    goto cleanup;
+
+	/* stuff the client realm into the server principal.
+	   realloc if necessary */
+	if (request.server->realm.length < request.client->realm.length)
+	    if ((request.server->realm.data =
+		 (char *) realloc(request.server->realm.data,
+				  request.client->realm.length)) == NULL) {
+		ret = ENOMEM;
+		goto cleanup;
+	    }
+
+	request.server->realm.length = request.client->realm.length;
+	memcpy(request.server->realm.data, request.client->realm.data,
+	       request.client->realm.length);
+    } else {
+	if ((ret = krb5_build_principal_ext(context, &request.server,
+					   request.client->realm.length,
+					   request.client->realm.data,
+					   KRB5_TGS_NAME_SIZE,
+					   KRB5_TGS_NAME,
+					   request.client->realm.length,
+					   request.client->realm.data,
+					   0)))
+	    goto cleanup;
+    }
+
+    krb5_preauth_request_context_init(context);
+
+    /* nonce is filled in by send_as_request if we don't take care of it */
+
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST)) {
+	request.ktype = options->etype_list;
+	request.nktypes = options->etype_list_length;
+    } else if ((ret = krb5_get_default_in_tkt_ktypes(context,
+						     &request.ktype)) == 0) {
+	for (request.nktypes = 0;
+	     request.ktype[request.nktypes];
+	     request.nktypes++)
+	    ;
+    } else {
+	/* there isn't any useful default here.  ret is set from above */
+	goto cleanup;
+    }
+
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST)) {
+	request.addresses = options->address_list;
+    }
+    /* it would be nice if this parsed out an address list, but
+       that would be work. */
+    else if (((ret = krb5_libdefault_boolean(context, &client->realm,
+					    "noaddresses", &tempint)) != 0)
+	     || (tempint == 1)) {
+	    ;
+    } else {
+	if ((ret = krb5_os_localaddr(context, &request.addresses)))
+	    goto cleanup;
+    }
+
+    request.authorization_data.ciphertext.length = 0;
+    request.authorization_data.ciphertext.data = 0;
+    request.unenc_authdata = 0;
+    request.second_ticket = 0;
+
+    /* set up the other state.  */
+
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)) {
+	if ((ret = make_preauth_list(context, options->preauth_list,
+				     options->preauth_list_length,
+				     &preauth_to_use)))
+	    goto cleanup;
+    }
+
+    /* the salt is allocated from somewhere, unless it is from the caller,
+       then it is a reference */
+
+    if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)) {
+	salt = *options->salt;
+    } else {
+	salt.length = SALT_TYPE_AFS_LENGTH;
+	salt.data = NULL;
+    }
+
+
+    /* set the request nonce */
+    if ((ret = krb5_timeofday(context, &time_now)))
+	goto cleanup;
+    /*
+     * XXX we know they are the same size... and we should do
+     * something better than just the current time
+     */
+    request.nonce = (krb5_int32) time_now;
+
+    /* give the preauth plugins a chance to prep the request body */
+    krb5_preauth_prepare_request(context, options, &request);
+    ret = encode_krb5_kdc_req_body(&request, &encoded_request_body);
+    if (ret)
+        goto cleanup;
+
+    get_data_rock.magic = CLIENT_ROCK_MAGIC;
+    get_data_rock.as_reply = NULL;
+
+    /* now, loop processing preauth data and talking to the kdc */
+    for (loopcount = 0; loopcount < MAX_IN_TKT_LOOPS; loopcount++) {
+	if (request.padata) {
+	    krb5_free_pa_data(context, request.padata);
+	    request.padata = NULL;
+	}
+	if (!err_reply) {
+            /* either our first attempt, or retrying after PREAUTH_NEEDED */
+	    if ((ret = krb5_do_preauth(context,
+				       &request,
+				       encoded_request_body,
+				       encoded_previous_request,
+				       preauth_to_use, &request.padata,
+				       &salt, &s2kparams, &etype, &as_key,
+				       prompter, prompter_data,
+				       gak_fct, gak_data,
+				       &get_data_rock, options)))
+	        goto cleanup;
+	} else {
+	    if (preauth_to_use != NULL) {
+		/*
+		 * Retry after an error other than PREAUTH_NEEDED,
+		 * using e-data to figure out what to change.
+		 */
+		ret = krb5_do_preauth_tryagain(context,
+					       &request,
+					       encoded_request_body,
+					       encoded_previous_request,
+					       preauth_to_use, &request.padata,
+					       err_reply,
+					       &salt, &s2kparams, &etype,
+					       &as_key,
+					       prompter, prompter_data,
+					       gak_fct, gak_data,
+					       &get_data_rock, options);
+	    } else {
+		/* No preauth supplied, so can't query the plug-ins. */
+		ret = KRB5KRB_ERR_GENERIC;
+	    }
+	    if (ret) {
+		/* couldn't come up with anything better */
+		ret = err_reply->error + ERROR_TABLE_BASE_krb5;
+	    }
+	    krb5_free_error(context, err_reply);
+	    err_reply = NULL;
+	    if (ret)
+		goto cleanup;
+	}
+
+        if (encoded_previous_request != NULL) {
+	    krb5_free_data(context, encoded_previous_request);
+	    encoded_previous_request = NULL;
+        }
+        ret = encode_krb5_as_req(&request, &encoded_previous_request);
+	if (ret)
+	    goto cleanup;
+
+	err_reply = 0;
+	local_as_reply = 0;
+	if ((ret = send_as_request(context, &request, &err_reply,
+				   &local_as_reply, use_master)))
+	    goto cleanup;
+
+	if (err_reply) {
+	    if (err_reply->error == KDC_ERR_PREAUTH_REQUIRED &&
+		err_reply->e_data.length > 0) {
+		/* reset the list of preauth types to try */
+		if (preauth_to_use) {
+		    krb5_free_pa_data(context, preauth_to_use);
+		    preauth_to_use = NULL;
+		}
+		ret = decode_krb5_padata_sequence(&err_reply->e_data,
+						  &preauth_to_use);
+		krb5_free_error(context, err_reply);
+		err_reply = NULL;
+		if (ret)
+		    goto cleanup;
+		ret = sort_krb5_padata_sequence(context,
+						&request.server->realm,
+						preauth_to_use);
+		if (ret)
+		    goto cleanup;
+		/* continue to next iteration */
+	    } else {
+		if (err_reply->e_data.length > 0) {
+		    /* continue to next iteration */
+		} else {
+		    /* error + no hints = give up */
+		    ret = (krb5_error_code) err_reply->error
+		          + ERROR_TABLE_BASE_krb5;
+		    krb5_free_error(context, err_reply);
+		    goto cleanup;
+		}
+	    }
+	} else if (local_as_reply) {
+	    break;
+	} else {
+	    ret = KRB5KRB_AP_ERR_MSG_TYPE;
+	    goto cleanup;
+	}
+    }
+
+    if (loopcount == MAX_IN_TKT_LOOPS) {
+	ret = KRB5_GET_IN_TKT_LOOP;
+	goto cleanup;
+    }
+
+    /* process any preauth data in the as_reply */
+    krb5_clear_preauth_context_use_counts(context);
+    if ((ret = sort_krb5_padata_sequence(context, &request.server->realm,
+					 local_as_reply->padata)))
+	goto cleanup;
+    get_data_rock.as_reply = local_as_reply;
+    if ((ret = krb5_do_preauth(context,
+			       &request,
+			       encoded_request_body, encoded_previous_request,
+			       local_as_reply->padata, &kdc_padata,
+			       &salt, &s2kparams, &etype, &as_key, prompter,
+			       prompter_data, gak_fct, gak_data,
+			       &get_data_rock, options)))
+	goto cleanup;
+
+    /* XXX For 1.1.1 and prior KDC's, when SAM is used w/ USE_SAD_AS_KEY,
+       the AS_REP comes back encrypted in the user's longterm key
+       instead of in the SAD. If there was a SAM preauth, there
+       will be an as_key here which will be the SAD. If that fails,
+       use the gak_fct to get the password, and try again. */
+      
+    /* XXX because etypes are handled poorly (particularly wrt SAM,
+       where the etype is fixed by the kdc), we may want to try
+       decrypt_as_reply twice.  If there's an as_key available, try
+       it.  If decrypting the as_rep fails, or if there isn't an
+       as_key at all yet, then use the gak_fct to get one, and try
+       again.  */
+
+    if (as_key.length)
+	ret = decrypt_as_reply(context, NULL, local_as_reply, NULL,
+			       NULL, &as_key, krb5_kdc_rep_decrypt_proc,
+			       NULL);
+    else
+	ret = -1;
+	   
+    if (ret) {
+	/* if we haven't get gotten a key, get it now */
+
+	if ((ret = ((*gak_fct)(context, request.client,
+			       local_as_reply->enc_part.enctype,
+			       prompter, prompter_data, &salt, &s2kparams,
+			       &as_key, gak_data))))
+	    goto cleanup;
+
+	if ((ret = decrypt_as_reply(context, NULL, local_as_reply, NULL,
+				    NULL, &as_key, krb5_kdc_rep_decrypt_proc,
+				    NULL)))
+	    goto cleanup;
+    }
+
+    if ((ret = verify_as_reply(context, time_now, &request, local_as_reply)))
+	goto cleanup;
+
+    /* XXX this should be inside stash_as_reply, but as long as
+       get_in_tkt is still around using that arg as an in/out, I can't
+       do that */
+    memset(creds, 0, sizeof(*creds));
+
+    if ((ret = stash_as_reply(context, time_now, &request, local_as_reply,
+			      creds, NULL)))
+	goto cleanup;
+
+    /* success */
+
+    ret = 0;
+
+cleanup:
+    krb5_preauth_request_context_fini(context);
+    if (encoded_previous_request != NULL) {
+	krb5_free_data(context, encoded_previous_request);
+	encoded_previous_request = NULL;
+    }
+    if (encoded_request_body != NULL) {
+	krb5_free_data(context, encoded_request_body);
+	encoded_request_body = NULL;
+    }
+    if (request.server)
+	krb5_free_principal(context, request.server);
+    if (request.ktype &&
+	(!(options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))))
+	free(request.ktype);
+    if (request.addresses &&
+	(!(options &&
+	   (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST))))
+	krb5_free_addresses(context, request.addresses);
+    if (preauth_to_use)
+	krb5_free_pa_data(context, preauth_to_use);
+    if (kdc_padata)
+	krb5_free_pa_data(context, kdc_padata);
+    if (request.padata)
+	krb5_free_pa_data(context, request.padata);
+    if (as_key.length)
+	krb5_free_keyblock_contents(context, &as_key);
+    if (salt.data &&
+	(!(options && (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT))))
+	krb5_xfree(salt.data);
+    krb5_free_data_contents(context, &s2kparams);
+    if (as_reply)
+	*as_reply = local_as_reply;
+    else if (local_as_reply)
+	krb5_free_kdc_rep(context, local_as_reply);
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/gic_keytab.c b/krb5-1-6/src/lib/krb5/krb/gic_keytab.c
new file mode 100644
index 000000000..cae04955a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/gic_keytab.c
@@ -0,0 +1,219 @@
+/*
+ * lib/krb5/krb/gic_keytab.c
+ *
+ * Copyright (C) 2002, 2003 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+
+static krb5_error_code
+krb5_get_as_key_keytab(
+    krb5_context context,
+    krb5_principal client,
+    krb5_enctype etype,
+    krb5_prompter_fct prompter,
+    void *prompter_data,
+    krb5_data *salt,
+    krb5_data *params,
+    krb5_keyblock *as_key,
+    void *gak_data)
+{
+    krb5_keytab keytab = (krb5_keytab) gak_data;
+    krb5_error_code ret;
+    krb5_keytab_entry kt_ent;
+    krb5_keyblock *kt_key;
+
+    /* if there's already a key of the correct etype, we're done.
+       if the etype is wrong, free the existing key, and make
+       a new one. */
+
+    if (as_key->length) {
+	if (as_key->enctype == etype)
+	    return(0);
+
+	krb5_free_keyblock_contents(context, as_key);
+	as_key->length = 0;
+    }
+
+    if (!krb5_c_valid_enctype(etype))
+	return(KRB5_PROG_ETYPE_NOSUPP);
+
+    if ((ret = krb5_kt_get_entry(context, keytab, client,
+				 0, /* don't have vno available */
+				 etype, &kt_ent)))
+	return(ret);
+
+    ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key);
+
+    /* again, krb5's memory management is lame... */
+
+    *as_key = *kt_key;
+    krb5_xfree(kt_key);
+
+    (void) krb5_kt_free_entry(context, &kt_ent);
+
+    return(ret);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_keytab(krb5_context context,
+			   krb5_creds *creds,
+			   krb5_principal client,
+			   krb5_keytab arg_keytab,
+			   krb5_deltat start_time,
+			   char *in_tkt_service,
+			   krb5_get_init_creds_opt *options)
+{
+   krb5_error_code ret, ret2;
+   int use_master;
+   krb5_keytab keytab;
+   krb5_gic_opt_ext *opte = NULL;
+
+   if (arg_keytab == NULL) {
+       if ((ret = krb5_kt_default(context, &keytab)))
+	    return ret;
+   } else {
+       keytab = arg_keytab;
+   }
+
+   ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
+				 "krb5_get_init_creds_keytab");
+   if (ret)
+      return ret;
+
+   use_master = 0;
+
+   /* first try: get the requested tkt from any kdc */
+
+   ret = krb5_get_init_creds(context, creds, client, NULL, NULL,
+			     start_time, in_tkt_service, opte,
+			     krb5_get_as_key_keytab, (void *) keytab,
+			     &use_master,NULL);
+
+   /* check for success */
+
+   if (ret == 0)
+      goto cleanup;
+
+   /* If all the kdc's are unavailable fail */
+
+   if ((ret == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE))
+      goto cleanup;
+
+   /* if the reply did not come from the master kdc, try again with
+      the master kdc */
+
+   if (!use_master) {
+      use_master = 1;
+
+      ret2 = krb5_get_init_creds(context, creds, client, NULL, NULL,
+				 start_time, in_tkt_service, opte,
+				 krb5_get_as_key_keytab, (void *) keytab,
+				 &use_master, NULL);
+      
+      if (ret2 == 0) {
+	 ret = 0;
+	 goto cleanup;
+      }
+
+      /* if the master is unreachable, return the error from the
+	 slave we were able to contact */
+
+      if ((ret2 == KRB5_KDC_UNREACH) ||
+	  (ret2 == KRB5_REALM_CANT_RESOLVE) ||
+	  (ret2 == KRB5_REALM_UNKNOWN))
+	 goto cleanup;
+
+      ret = ret2;
+   }
+
+   /* at this point, we have a response from the master.  Since we don't
+      do any prompting or changing for keytabs, that's it. */
+
+cleanup:
+   if (opte && krb5_gic_opt_is_shadowed(opte))
+       krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
+   if (arg_keytab == NULL)
+       krb5_kt_close(context, keytab);
+
+   return(ret);
+}
+krb5_error_code KRB5_CALLCONV
+krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options,
+			      krb5_address *const *addrs, krb5_enctype *ktypes,
+			      krb5_preauthtype *pre_auth_types,
+			      krb5_keytab arg_keytab, krb5_ccache ccache,
+			      krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+{
+    krb5_error_code retval;
+    krb5_gic_opt_ext *opte;
+    char * server = NULL;
+    krb5_keytab keytab;
+    krb5_principal client_princ, server_princ;
+    int use_master = 0;
+    
+    retval = krb5int_populate_gic_opt(context, &opte,
+				      options, addrs, ktypes,
+				      pre_auth_types, creds);
+    if (retval)
+	return retval;
+
+    if (arg_keytab == NULL) {
+	retval = krb5_kt_default(context, &keytab);
+	if (retval)
+	    return retval;
+    }
+    else keytab = arg_keytab;
+    
+    retval = krb5_unparse_name( context, creds->server, &server);
+    if (retval)
+	goto cleanup;
+    server_princ = creds->server;
+    client_princ = creds->client;
+    retval = krb5_get_init_creds (context,
+				  creds, creds->client,  
+				  krb5_prompter_posix,  NULL,
+				  0, server, opte,
+				  krb5_get_as_key_keytab, (void *)keytab,
+				  &use_master, ret_as_reply);
+    krb5_free_unparsed_name( context, server);
+    krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
+    if (retval) {
+	goto cleanup;
+    }
+	if (creds->server)
+	    krb5_free_principal( context, creds->server);
+	if (creds->client)
+	    krb5_free_principal( context, creds->client);
+	creds->client = client_princ;
+	creds->server = server_princ;
+	
+    /* store it in the ccache! */
+    if (ccache)
+	if ((retval = krb5_cc_store_cred(context, ccache, creds)))
+	    goto cleanup;
+ cleanup:    if (arg_keytab == NULL)
+     krb5_kt_close(context, keytab);
+    return retval;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/gic_opt.c b/krb5-1-6/src/lib/krb5/krb/gic_opt.c
new file mode 100644
index 000000000..227391ae4
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/gic_opt.c
@@ -0,0 +1,447 @@
+#include "k5-int.h"
+#include "int-proto.h"
+
+static void
+init_common(krb5_get_init_creds_opt *opt)
+{
+    opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
+{
+    opt->flags = 0;
+    init_common(opt);
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, krb5_deltat tkt_life)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE;
+   opt->tkt_life = tkt_life;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, krb5_deltat renew_life)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE;
+   opt->renew_life = renew_life;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, int forwardable)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE;
+   opt->forwardable = forwardable;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, int proxiable)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE;
+   opt->proxiable = proxiable;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, krb5_enctype *etype_list, int etype_list_length)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST;
+   opt->etype_list = etype_list;
+   opt->etype_list_length = etype_list_length;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, krb5_address **addresses)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST;
+   opt->address_list = addresses;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, krb5_preauthtype *preauth_list, int preauth_list_length)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST;
+   opt->preauth_list = preauth_list;
+   opt->preauth_list_length = preauth_list_length;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, krb5_data *salt)
+{
+   opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT;
+   opt->salt = salt;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt *opt, int prompt)
+{
+   if (prompt)
+     opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
+   else
+     opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
+}
+
+/*
+ * Extending the krb5_get_init_creds_opt structure.  The original
+ * krb5_get_init_creds_opt structure is defined publicly.  The
+ * new extended version is private.  The original interface
+ * assumed a pre-allocated structure which was passed to
+ * krb5_get_init_creds_init().  The new interface assumes that
+ * the caller will call krb5_get_init_creds_alloc() and
+ * krb5_get_init_creds_free().
+ *
+ * Callers MUST NOT call krb5_get_init_creds_init() after allocating an
+ * opts structure using krb5_get_init_creds_alloc().  To do so will
+ * introduce memory leaks.  Unfortunately, there is no way to enforce
+ * this behavior.
+ *
+ * Two private flags are added for backward compatibility.
+ * KRB5_GET_INIT_CREDS_OPT_EXTENDED says that the structure was allocated
+ * with the new krb5_get_init_creds_opt_alloc() function.
+ * KRB5_GET_INIT_CREDS_OPT_SHADOWED is set to indicate that the extended
+ * structure is a shadow copy of an original krb5_get_init_creds_opt
+ * structure.  
+ * If KRB5_GET_INIT_CREDS_OPT_SHADOWED is set after a call to
+ * krb5int_gic_opt_to_opte(), the resulting extended structure should be
+ * freed (using krb5_get_init_creds_free).  Otherwise, the original
+ * structure was already extended and there is no need to free it.
+ */
+
+/* Forward prototype */
+static void
+free_gic_opt_ext_preauth_data(krb5_context context,
+			      krb5_gic_opt_ext *opte);
+
+static krb5_error_code
+krb5int_gic_opte_private_alloc(krb5_context context, krb5_gic_opt_ext *opte)
+{
+    if (NULL == opte || !krb5_gic_opt_is_extended(opte))
+	return EINVAL;
+
+    opte->opt_private = calloc(1, sizeof(*opte->opt_private));
+    if (NULL == opte->opt_private) {
+	return ENOMEM;
+    }
+    /* Allocate any private stuff */
+    opte->opt_private->num_preauth_data = 0;
+    opte->opt_private->preauth_data = NULL;
+    return 0;
+}
+
+static krb5_error_code
+krb5int_gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte)
+{
+    if (NULL == opte || !krb5_gic_opt_is_extended(opte))
+	return EINVAL;
+	
+    /* Free up any private stuff */
+    if (opte->opt_private->preauth_data != NULL)
+	free_gic_opt_ext_preauth_data(context, opte);
+    free(opte->opt_private);
+    opte->opt_private = NULL;
+    return 0;
+}
+
+static krb5_gic_opt_ext *
+krb5int_gic_opte_alloc(krb5_context context)
+{
+    krb5_gic_opt_ext *opte;
+    krb5_error_code code;
+
+    opte = calloc(1, sizeof(*opte));
+    if (NULL == opte)
+	return NULL;
+    opte->flags = KRB5_GET_INIT_CREDS_OPT_EXTENDED;
+
+    code = krb5int_gic_opte_private_alloc(context, opte);
+    if (code) {
+	krb5int_set_error(&context->err, code,
+		"krb5int_gic_opte_alloc: krb5int_gic_opte_private_alloc failed");
+	free(opte);
+	return NULL;
+    }
+    return(opte);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_alloc(krb5_context context,
+			      krb5_get_init_creds_opt **opt)
+{
+    krb5_gic_opt_ext *opte;
+
+    if (NULL == opt)
+	return EINVAL;
+    *opt = NULL;
+
+    /*
+     * We return a new extended structure cast as a krb5_get_init_creds_opt
+     */
+    opte = krb5int_gic_opte_alloc(context);
+    if (NULL == opte)
+	return ENOMEM;
+
+    *opt = (krb5_get_init_creds_opt *) opte;
+    init_common(*opt);
+    return 0;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free(krb5_context context,
+			     krb5_get_init_creds_opt *opt)
+{
+    krb5_gic_opt_ext *opte;
+
+    if (NULL == opt)
+	return;
+
+    /* Don't touch it if we didn't allocate it */
+    if (!krb5_gic_opt_is_extended(opt))
+	return;
+    
+    opte = (krb5_gic_opt_ext *)opt;
+    if (opte->opt_private)
+	krb5int_gic_opte_private_free(context, opte);
+
+    free(opte);
+}
+
+static krb5_error_code
+krb5int_gic_opte_copy(krb5_context context,
+		      krb5_get_init_creds_opt *opt,
+		      krb5_gic_opt_ext **opte)
+{
+    krb5_gic_opt_ext *oe;
+
+    oe = krb5int_gic_opte_alloc(context);
+    if (NULL == oe)
+	return ENOMEM;
+
+    if (opt)
+        memcpy(oe, opt, sizeof(*opt));
+
+    /*
+     * Fix the flags -- the EXTENDED flag would have been
+     * overwritten by the copy if there was one.  The
+     * SHADOWED flag is necessary to ensure that the
+     * krb5_gic_opt_ext structure that was allocated
+     * here will be freed by the library because the
+     * application is unaware of its existence.
+     */
+    oe->flags |= ( KRB5_GET_INIT_CREDS_OPT_EXTENDED |
+		   KRB5_GET_INIT_CREDS_OPT_SHADOWED);
+
+    *opte = oe;
+    return 0;
+}
+
+/*
+ * Convert a krb5_get_init_creds_opt pointer to a pointer to
+ * an extended, krb5_gic_opt_ext pointer.  If the original
+ * pointer already points to an extended structure, then simply
+ * return the original pointer.  Otherwise, if 'force' is non-zero,
+ * allocate an extended structure and copy the original over it.
+ * If the original pointer did not point to an extended structure
+ * and 'force' is zero, then return an error.  This is used in
+ * cases where the original *should* be an extended structure.
+ */
+krb5_error_code
+krb5int_gic_opt_to_opte(krb5_context context,
+			krb5_get_init_creds_opt *opt,
+			krb5_gic_opt_ext **opte,
+			unsigned int force,
+			const char *where)
+{
+    if (!krb5_gic_opt_is_extended(opt)) {
+	if (force) {
+	    return krb5int_gic_opte_copy(context, opt, opte);
+	} else {
+	    krb5int_set_error(&context->err, EINVAL,
+		    "%s: attempt to convert non-extended krb5_get_init_creds_opt",
+		    where);
+	    return EINVAL;
+	}
+    }
+    /* If it is already extended, just return it */
+    *opte = (krb5_gic_opt_ext *)opt;
+    return 0;
+}
+
+static void
+free_gic_opt_ext_preauth_data(krb5_context context,
+			      krb5_gic_opt_ext *opte)
+{
+    int i;
+
+    if (NULL == opte || !krb5_gic_opt_is_extended(opte))
+	return;
+    if (NULL == opte->opt_private || NULL == opte->opt_private->preauth_data)
+	return;
+
+    for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+	if (opte->opt_private->preauth_data[i].attr != NULL)
+	    free(opte->opt_private->preauth_data[i].attr);
+	if (opte->opt_private->preauth_data[i].value != NULL)
+	    free(opte->opt_private->preauth_data[i].value);
+    }
+    free(opte->opt_private->preauth_data);
+    opte->opt_private->preauth_data = NULL;
+    opte->opt_private->num_preauth_data = 0;
+}
+
+static krb5_error_code
+add_gic_opt_ext_preauth_data(krb5_context context,
+			     krb5_gic_opt_ext *opte,
+			     const char *attr,
+			     const char *value)
+{
+    size_t newsize;
+    int i;
+    krb5_gic_opt_pa_data *newpad;
+
+    newsize = opte->opt_private->num_preauth_data + 1;
+    newsize = newsize * sizeof(*opte->opt_private->preauth_data);
+    if (opte->opt_private->preauth_data == NULL)
+	newpad = malloc(newsize);
+    else
+	newpad = realloc(opte->opt_private->preauth_data, newsize);
+    if (newpad == NULL)
+	return ENOMEM;
+
+    i = opte->opt_private->num_preauth_data;
+    newpad[i].attr = strdup(attr);
+    if (newpad[i].attr == NULL)
+	return ENOMEM;
+    newpad[i].value = strdup(value);
+    if (newpad[i].value == NULL) {
+	free(newpad[i].attr);
+	return ENOMEM;
+    }
+    opte->opt_private->num_preauth_data += 1;
+    opte->opt_private->preauth_data = newpad;
+    return 0;
+}
+
+/*
+ * This function allows the caller to supply options to preauth
+ * plugins.  Preauth plugin modules are given a chance to look
+ * at each option at the time this function is called in ordre
+ * to check the validity of the option.
+ * The 'opt' pointer supplied to this function must have been
+ * obtained using krb5_get_init_creds_opt_alloc()
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_set_pa(krb5_context context,
+			       krb5_get_init_creds_opt *opt,
+			       const char *attr,
+			       const char *value)
+{
+    krb5_error_code retval;
+    krb5_gic_opt_ext *opte;
+
+    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
+				     "krb5_get_init_creds_opt_set_pa");
+    if (retval)
+	return retval;
+
+    /*
+     * Copy the option into the extended get_init_creds_opt structure
+     */
+    retval = add_gic_opt_ext_preauth_data(context, opte, attr, value);
+    if (retval)
+	return retval;
+
+    /*
+     * Give the plugins a chance to look at the option now.
+     */
+    retval = krb5_preauth_supply_preauth_data(context, opte, attr, value);
+    return retval;
+}
+
+/*
+ * This function allows a preauth plugin to obtain preauth
+ * options.  The preauth_data returned from this function
+ * should be freed by calling krb5_get_init_creds_opt_free_pa().
+ *
+ * The 'opt' pointer supplied to this function must have been
+ * obtained using krb5_get_init_creds_opt_alloc()
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_get_pa(krb5_context context,
+			       krb5_get_init_creds_opt *opt,
+			       int *num_preauth_data,
+			       krb5_gic_opt_pa_data **preauth_data)
+{
+    krb5_error_code retval;
+    krb5_gic_opt_ext *opte;
+    krb5_gic_opt_pa_data *p = NULL;
+    int i;
+    size_t allocsize;
+
+    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
+				     "krb5_get_init_creds_opt_get_pa");
+    if (retval)
+	return retval;
+
+    if (num_preauth_data == NULL || preauth_data == NULL)
+	return EINVAL;
+
+    *num_preauth_data = 0;
+    *preauth_data = NULL;
+
+    if (opte->opt_private->num_preauth_data == 0)
+	return 0;
+
+    allocsize =
+	    opte->opt_private->num_preauth_data * sizeof(krb5_gic_opt_pa_data);
+    p = malloc(allocsize);
+    if (p == NULL)
+	return ENOMEM;
+
+    /* Init these to make cleanup easier */
+    for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+	p[i].attr = NULL;
+	p[i].value = NULL;
+    }
+
+    for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+	p[i].attr = strdup(opte->opt_private->preauth_data[i].attr);
+	p[i].value = strdup(opte->opt_private->preauth_data[i].value);
+	if (p[i].attr == NULL || p[i].value == NULL)
+	    goto cleanup;
+    }
+    *num_preauth_data = i;
+    *preauth_data = p;
+    return 0;
+cleanup:
+    for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+	if (p[i].attr != NULL)
+	    free(p[i].attr);
+	if (p[i].value != NULL)
+	    free(p[i].value);
+    }
+    free(p);
+    return ENOMEM;
+}
+
+/*
+ * This function frees the preauth_data that was returned by 
+ * krb5_get_init_creds_opt_get_pa().
+ */
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free_pa(krb5_context context,
+				int num_preauth_data,
+				krb5_gic_opt_pa_data *preauth_data)
+{
+    int i;
+
+    if (num_preauth_data <= 0 || preauth_data == NULL)
+	return;
+
+    for (i = 0; i < num_preauth_data; i++) {
+	if (preauth_data[i].attr != NULL)
+	    free(preauth_data[i].attr);
+	if (preauth_data[i].value != NULL)
+	    free(preauth_data[i].value);
+    }
+    free(preauth_data);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/gic_pwd.c b/krb5-1-6/src/lib/krb5/krb/gic_pwd.c
new file mode 100644
index 000000000..02d344c5d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/gic_pwd.c
@@ -0,0 +1,532 @@
+#include "k5-int.h"
+#include "com_err.h"
+
+static krb5_error_code
+krb5_get_as_key_password(
+    krb5_context context,
+    krb5_principal client,
+    krb5_enctype etype,
+    krb5_prompter_fct prompter,
+    void *prompter_data,
+    krb5_data *salt,
+    krb5_data *params,
+    krb5_keyblock *as_key,
+    void *gak_data)
+{
+    krb5_data *password;
+    krb5_error_code ret;
+    krb5_data defsalt;
+    char *clientstr;
+    char promptstr[1024];
+    krb5_prompt prompt;
+    krb5_prompt_type prompt_type;
+
+    password = (krb5_data *) gak_data;
+
+    /* If there's already a key of the correct etype, we're done.
+       If the etype is wrong, free the existing key, and make
+       a new one.
+
+       XXX This was the old behavior, and was wrong in hw preauth
+       cases.  Is this new behavior -- always asking -- correct in all
+       cases?  */
+
+    if (as_key->length) {
+	if (as_key->enctype != etype) {
+	    krb5_free_keyblock_contents (context, as_key);
+	    as_key->length = 0;
+	}
+    }
+
+    if (password->data[0] == '\0') {
+	if (prompter == NULL)
+	    return(EIO);
+
+	if ((ret = krb5_unparse_name(context, client, &clientstr)))
+	  return(ret);
+
+	strcpy(promptstr, "Password for ");
+	strncat(promptstr, clientstr, sizeof(promptstr)-strlen(promptstr)-1);
+	promptstr[sizeof(promptstr)-1] = '\0';
+
+	free(clientstr);
+
+	prompt.prompt = promptstr;
+	prompt.hidden = 1;
+	prompt.reply = password;
+	prompt_type = KRB5_PROMPT_TYPE_PASSWORD;
+
+	/* PROMPTER_INVOCATION */
+	krb5int_set_prompt_types(context, &prompt_type);
+	if ((ret = (((*prompter)(context, prompter_data, NULL, NULL,
+				1, &prompt))))) {
+	    krb5int_set_prompt_types(context, 0);
+	    return(ret);
+	}
+	krb5int_set_prompt_types(context, 0);
+    }
+
+    if ((salt->length == -1 || salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
+	if ((ret = krb5_principal2salt(context, client, &defsalt)))
+	    return(ret);
+
+	salt = &defsalt;
+    } else {
+	defsalt.length = 0;
+    }
+
+    ret = krb5_c_string_to_key_with_params(context, etype, password, salt,
+					   params->data?params:NULL, as_key);
+
+    if (defsalt.length)
+	krb5_xfree(defsalt.data);
+
+    return(ret);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_password(krb5_context context,
+			     krb5_creds *creds,
+			     krb5_principal client,
+			     char *password,
+			     krb5_prompter_fct prompter,
+			     void *data,
+			     krb5_deltat start_time,
+			     char *in_tkt_service,
+			     krb5_get_init_creds_opt *options)
+{
+   krb5_error_code ret, ret2;
+   int use_master;
+   krb5_kdc_rep *as_reply;
+   int tries;
+   krb5_creds chpw_creds;
+   krb5_get_init_creds_opt *chpw_opts = NULL;
+   krb5_data pw0, pw1;
+   char banner[1024], pw0array[1024], pw1array[1024];
+   krb5_prompt prompt[2];
+   krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])];
+   krb5_gic_opt_ext *opte = NULL;
+   krb5_gic_opt_ext *chpw_opte = NULL;
+
+   use_master = 0;
+   as_reply = NULL;
+   memset(&chpw_creds, 0, sizeof(chpw_creds));
+
+   pw0.data = pw0array;
+
+   if (password && password[0]) {
+      if ((pw0.length = strlen(password)) > sizeof(pw0array)) {
+	 ret = EINVAL;
+	 goto cleanup;
+      }
+      strcpy(pw0.data, password);
+   } else {
+      pw0.data[0] = '\0';
+      pw0.length = sizeof(pw0array);
+   }
+
+   pw1.data = pw1array;
+   pw1.data[0] = '\0';
+   pw1.length = sizeof(pw1array);
+
+   ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
+				 "krb5_get_init_creds_password");
+   if (ret)
+      goto cleanup;
+
+   /* first try: get the requested tkt from any kdc */
+
+   ret = krb5_get_init_creds(context, creds, client, prompter, data,
+			     start_time, in_tkt_service, opte,
+			     krb5_get_as_key_password, (void *) &pw0,
+			     &use_master, &as_reply);
+
+   /* check for success */
+
+   if (ret == 0)
+      goto cleanup;
+
+   /* If all the kdc's are unavailable, or if the error was due to a
+      user interrupt, or preauth errored out, fail */
+
+   if ((ret == KRB5_KDC_UNREACH) ||
+       (ret == KRB5_PREAUTH_FAILED) ||
+       (ret == KRB5_LIBOS_PWDINTR) ||
+	   (ret == KRB5_REALM_CANT_RESOLVE))
+      goto cleanup;
+
+   /* if the reply did not come from the master kdc, try again with
+      the master kdc */
+
+   if (!use_master) {
+      use_master = 1;
+
+      if (as_reply) {
+	  krb5_free_kdc_rep( context, as_reply);
+	  as_reply = NULL;
+      }
+      ret2 = krb5_get_init_creds(context, creds, client, prompter, data,
+				 start_time, in_tkt_service, opte,
+				 krb5_get_as_key_password, (void *) &pw0,
+				 &use_master, &as_reply);
+      
+      if (ret2 == 0) {
+	 ret = 0;
+	 goto cleanup;
+      }
+
+      /* if the master is unreachable, return the error from the
+	 slave we were able to contact or reset the use_master flag */
+
+       if ((ret2 != KRB5_KDC_UNREACH) &&
+	    (ret2 != KRB5_REALM_CANT_RESOLVE) &&
+	    (ret2 != KRB5_REALM_UNKNOWN))
+	   ret = ret2;
+       else
+	   use_master = 0;
+   }
+
+#ifdef USE_LOGIN_LIBRARY
+	if (ret == KRB5KDC_ERR_KEY_EXP)
+		goto cleanup;	/* Login library will deal appropriately with this error */
+#endif
+
+   /* at this point, we have an error from the master.  if the error
+      is not password expired, or if it is but there's no prompter,
+      return this error */
+
+   if ((ret != KRB5KDC_ERR_KEY_EXP) ||
+       (prompter == NULL))
+      goto cleanup;
+
+    /* historically the default has been to prompt for password change.
+     * if the change password prompt option has not been set, we continue
+     * to prompt.  Prompting is only disabled if the option has been set
+     * and the value has been set to false.
+     */
+    if (!(options->flags & KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT))
+	goto cleanup;
+
+    /* ok, we have an expired password.  Give the user a few chances
+      to change it */
+
+   /* use a minimal set of options */
+
+   ret = krb5_get_init_creds_opt_alloc(context, &chpw_opts);
+   if (ret)
+      goto cleanup;
+   krb5_get_init_creds_opt_set_tkt_life(chpw_opts, 5*60);
+   krb5_get_init_creds_opt_set_renew_life(chpw_opts, 0);
+   krb5_get_init_creds_opt_set_forwardable(chpw_opts, 0);
+   krb5_get_init_creds_opt_set_proxiable(chpw_opts, 0);
+   ret = krb5int_gic_opt_to_opte(context, chpw_opts, &chpw_opte, 0,
+			"krb5_get_init_creds_password (changing password)");
+   if (ret)
+      goto cleanup;
+
+   if ((ret = krb5_get_init_creds(context, &chpw_creds, client,
+				  prompter, data,
+				  start_time, "kadmin/changepw", chpw_opte,
+				  krb5_get_as_key_password, (void *) &pw0,
+				  &use_master, NULL)))
+      goto cleanup;
+
+   prompt[0].prompt = "Enter new password";
+   prompt[0].hidden = 1;
+   prompt[0].reply = &pw0;
+   prompt_types[0] = KRB5_PROMPT_TYPE_NEW_PASSWORD;
+
+   prompt[1].prompt = "Enter it again";
+   prompt[1].hidden = 1;
+   prompt[1].reply = &pw1;
+   prompt_types[1] = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN;
+
+   strcpy(banner, "Password expired.  You must change it now.");
+
+   for (tries = 3; tries; tries--) {
+      pw0.length = sizeof(pw0array);
+      pw1.length = sizeof(pw1array);
+
+      /* PROMPTER_INVOCATION */
+      krb5int_set_prompt_types(context, prompt_types);
+      if ((ret = ((*prompter)(context, data, 0, banner,
+			      sizeof(prompt)/sizeof(prompt[0]), prompt))))
+	 goto cleanup;
+      krb5int_set_prompt_types(context, 0);
+
+
+      if (strcmp(pw0.data, pw1.data) != 0) {
+	 ret = KRB5_LIBOS_BADPWDMATCH;
+	 sprintf(banner, "%s.  Please try again.", error_message(ret));
+      } else if (pw0.length == 0) {
+	 ret = KRB5_CHPW_PWDNULL;
+	 sprintf(banner, "%s.  Please try again.", error_message(ret));
+      } else {
+	 int result_code;
+	 krb5_data code_string;
+	 krb5_data result_string;
+
+	 if ((ret = krb5_change_password(context, &chpw_creds, pw0array,
+					 &result_code, &code_string,
+					 &result_string)))
+	    goto cleanup;
+
+	 /* the change succeeded.  go on */
+
+	 if (result_code == 0) {
+	    krb5_xfree(result_string.data);
+	    break;
+	 }
+
+	 /* set this in case the retry loop falls through */
+
+	 ret = KRB5_CHPW_FAIL;
+
+	 if (result_code != KRB5_KPASSWD_SOFTERROR) {
+	    krb5_xfree(result_string.data);
+	    goto cleanup;
+	 }
+
+	 /* the error was soft, so try again */
+
+	 /* 100 is I happen to know that no code_string will be longer
+	    than 100 chars */
+
+	 if (result_string.length > (sizeof(banner)-100))
+	    result_string.length = sizeof(banner)-100;
+
+	 sprintf(banner, "%.*s%s%.*s.  Please try again.\n",
+		 (int) code_string.length, code_string.data,
+		 result_string.length ? ": " : "",
+		 (int) result_string.length,
+		 result_string.data ? result_string.data : "");
+
+	 krb5_xfree(code_string.data);
+	 krb5_xfree(result_string.data);
+      }
+   }
+
+   if (ret)
+      goto cleanup;
+
+   /* the password change was successful.  Get an initial ticket
+      from the master.  this is the last try.  the return from this
+      is final.  */
+
+   ret = krb5_get_init_creds(context, creds, client, prompter, data,
+			     start_time, in_tkt_service, opte,
+			     krb5_get_as_key_password, (void *) &pw0,
+			     &use_master, &as_reply);
+
+cleanup:
+   krb5int_set_prompt_types(context, 0);
+   /* if getting the password was successful, then check to see if the
+      password is about to expire, and warn if so */
+
+   if (ret == 0) {
+      krb5_timestamp now;
+      krb5_last_req_entry **last_req;
+      int hours;
+
+      /* XXX 7 days should be configurable.  This is all pretty ad hoc,
+	 and could probably be improved if I was willing to screw around
+	 with timezones, etc. */
+
+      if (prompter &&
+	  (!in_tkt_service ||
+	   (strcmp(in_tkt_service, "kadmin/changepw") != 0)) &&
+	  ((ret = krb5_timeofday(context, &now)) == 0) &&
+	  as_reply->enc_part2->key_exp &&
+	  ((hours = ((as_reply->enc_part2->key_exp-now)/(60*60))) <= 7*24) &&
+	  (hours >= 0)) {
+	 if (hours < 1)
+	    sprintf(banner,
+		    "Warning: Your password will expire in less than one hour.");
+	 else if (hours <= 48)
+	    sprintf(banner, "Warning: Your password will expire in %d hour%s.",
+		    hours, (hours == 1)?"":"s");
+	 else
+	    sprintf(banner, "Warning: Your password will expire in %d days.",
+		    hours/24);
+
+	 /* ignore an error here */
+         /* PROMPTER_INVOCATION */
+	 (*prompter)(context, data, 0, banner, 0, 0);
+      } else if (prompter &&
+		 (!in_tkt_service ||
+		  (strcmp(in_tkt_service, "kadmin/changepw") != 0)) &&
+		 as_reply->enc_part2 && as_reply->enc_part2->last_req) {
+	 /*
+	  * Check the last_req fields
+	  */
+
+	 for (last_req = as_reply->enc_part2->last_req; *last_req; last_req++)
+	    if ((*last_req)->lr_type == KRB5_LRQ_ALL_PW_EXPTIME ||
+		(*last_req)->lr_type == KRB5_LRQ_ONE_PW_EXPTIME) {
+	       krb5_deltat delta;
+	       char ts[256];
+
+	       if ((ret = krb5_timeofday(context, &now)))
+		  break;
+
+	       if ((ret = krb5_timestamp_to_string((*last_req)->value,
+						   ts, sizeof(ts))))
+		  break;
+
+	       delta = (*last_req)->value - now;
+
+	       if (delta < 3600)
+		  sprintf(banner,
+		    "Warning: Your password will expire in less than one "
+		     "hour on %s", ts);
+	       else if (delta < 86400*2)
+		  sprintf(banner,
+		     "Warning: Your password will expire in %d hour%s on %s",
+		     delta / 3600, delta < 7200 ? "" : "s", ts);
+	       else
+		  sprintf(banner,
+		     "Warning: Your password will expire in %d days on %s",
+		     delta / 86400, ts);
+	       /* ignore an error here */
+	       /* PROMPTER_INVOCATION */
+	       (*prompter)(context, data, 0, banner, 0, 0);
+	    }
+      }
+   }
+
+   if (chpw_opts)
+      krb5_get_init_creds_opt_free(context, chpw_opts);
+   if (opte && krb5_gic_opt_is_shadowed(opte))
+      krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
+   memset(pw0array, 0, sizeof(pw0array));
+   memset(pw1array, 0, sizeof(pw1array));
+   krb5_free_cred_contents(context, &chpw_creds);
+   if (as_reply)
+      krb5_free_kdc_rep(context, as_reply);
+
+   return(ret);
+}
+krb5_error_code krb5int_populate_gic_opt (
+    krb5_context context, krb5_gic_opt_ext **opte,
+    krb5_flags options, krb5_address * const *addrs, krb5_enctype *ktypes,
+    krb5_preauthtype *pre_auth_types, krb5_creds *creds)
+{
+  int i;
+  krb5_int32 starttime;
+  krb5_get_init_creds_opt *opt;
+  krb5_error_code retval;
+
+    retval = krb5_get_init_creds_opt_alloc(context, &opt);
+    if (retval)
+	return(retval);
+
+    if (addrs)
+      krb5_get_init_creds_opt_set_address_list(opt, (krb5_address **) addrs);
+    if (ktypes) {
+	for (i=0; ktypes[i]; i++);
+	if (i)
+	    krb5_get_init_creds_opt_set_etype_list(opt, ktypes, i);
+    }
+    if (pre_auth_types) {
+	for (i=0; pre_auth_types[i]; i++);
+	if (i)
+	    krb5_get_init_creds_opt_set_preauth_list(opt, pre_auth_types, i);
+    }
+    if (options&KDC_OPT_FORWARDABLE)
+	krb5_get_init_creds_opt_set_forwardable(opt, 1);
+    else krb5_get_init_creds_opt_set_forwardable(opt, 0);
+    if (options&KDC_OPT_PROXIABLE)
+	krb5_get_init_creds_opt_set_proxiable(opt, 1);
+    else krb5_get_init_creds_opt_set_proxiable(opt, 0);
+    if (creds && creds->times.endtime) {
+        krb5_timeofday(context, &starttime);
+        if (creds->times.starttime) starttime = creds->times.starttime;
+        krb5_get_init_creds_opt_set_tkt_life(opt, creds->times.endtime - starttime);
+    }
+    return krb5int_gic_opt_to_opte(context, opt, opte, 0,
+				   "krb5int_populate_gic_opt");
+}
+
+/*
+  Rewrites get_in_tkt in terms of newer get_init_creds API.
+ Attempts to get an initial ticket for creds->client to use server
+ creds->server, (realm is taken from creds->client), with options
+ options, and using creds->times.starttime, creds->times.endtime,
+ creds->times.renew_till as from, till, and rtime.  
+ creds->times.renew_till is ignored unless the RENEWABLE option is requested.
+
+ If addrs is non-NULL, it is used for the addresses requested.  If it is
+ null, the system standard addresses are used.
+
+ If password is non-NULL, it is converted using the cryptosystem entry
+ point for a string conversion routine, seeded with the client's name.
+ If password is passed as NULL, the password is read from the terminal,
+ and then converted into a key.
+
+ A succesful call will place the ticket in the credentials cache ccache.
+
+ returns system errors, encryption errors
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options,
+			      krb5_address *const *addrs, krb5_enctype *ktypes,
+			      krb5_preauthtype *pre_auth_types,
+			      const char *password, krb5_ccache ccache,
+			      krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+{
+    krb5_error_code retval;
+    krb5_data pw0;
+    char pw0array[1024];
+    char * server;
+    krb5_principal server_princ, client_princ;
+    int use_master = 0;
+    krb5_gic_opt_ext *opte = NULL;
+
+    pw0array[0] = '\0';
+    pw0.data = pw0array;
+    if (password) {
+	pw0.length = strlen(password);
+	if (pw0.length > sizeof(pw0array))
+	    return EINVAL;
+	strncpy(pw0.data, password, sizeof(pw0array));
+	if (pw0.length == 0)
+	    pw0.length = sizeof(pw0array);
+    } else {
+	pw0.length = sizeof(pw0array);
+    }
+    retval = krb5int_populate_gic_opt(context, &opte,
+				      options, addrs, ktypes,
+				      pre_auth_types, creds);
+    if (retval)
+      return (retval);
+    retval = krb5_unparse_name( context, creds->server, &server);
+    if (retval) {
+      return (retval);
+      krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
+    }
+    server_princ = creds->server;
+    client_princ = creds->client;
+        retval = krb5_get_init_creds (context,
+					   creds, creds->client,  
+					   krb5_prompter_posix,  NULL,
+					   0, server, opte,
+				      krb5_get_as_key_password, &pw0,
+				      &use_master, ret_as_reply);
+	  krb5_free_unparsed_name( context, server);
+	  krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
+	if (retval) {
+	  return (retval);
+	}
+	if (creds->server)
+	    krb5_free_principal( context, creds->server);
+	if (creds->client)
+	    krb5_free_principal( context, creds->client);
+	creds->client = client_princ;
+	creds->server = server_princ;
+	/* store it in the ccache! */
+	if (ccache)
+	  if ((retval = krb5_cc_store_cred(context, ccache, creds)))
+	    return (retval);
+	return retval;
+  }
+
diff --git a/krb5-1-6/src/lib/krb5/krb/in_tkt_sky.c b/krb5-1-6/src/lib/krb5/krb/in_tkt_sky.c
new file mode 100644
index 000000000..6de207550
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/in_tkt_sky.c
@@ -0,0 +1,112 @@
+/*
+ * lib/krb5/krb/in_tkt_sky.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_get_in_tkt_with_skey()
+ *	
+ */
+
+#include "k5-int.h"
+
+struct skey_keyproc_arg {
+    const krb5_keyblock *key;
+    krb5_principal client;		/* it's a pointer, really! */
+};
+
+/*
+ * Key-generator for in_tkt_skey, below.
+ * "keyseed" is actually a krb5_keyblock *, or NULL if we should fetch
+ * from system area.
+ */
+static krb5_error_code skey_keyproc
+    (krb5_context,
+               const krb5_enctype,
+               krb5_data *,
+               krb5_const_pointer,
+               krb5_keyblock **);
+
+static krb5_error_code
+skey_keyproc(krb5_context context, krb5_enctype type, krb5_data *salt,
+	     krb5_const_pointer keyseed, krb5_keyblock **key)
+{
+    krb5_keyblock *realkey;
+    krb5_error_code retval;
+    const krb5_keyblock * keyblock;
+
+    keyblock = (const krb5_keyblock *)keyseed;
+
+    if (!krb5_c_valid_enctype(type))
+	return KRB5_PROG_ETYPE_NOSUPP;
+
+    if ((retval = krb5_copy_keyblock(context, keyblock, &realkey)))
+	return retval;
+	
+    if (realkey->enctype != type) {
+	krb5_free_keyblock(context, realkey);
+	return KRB5_PROG_ETYPE_NOSUPP;
+    }	
+
+    *key = realkey;
+    return 0;
+}
+
+/*
+ Similar to krb5_get_in_tkt_with_password.
+
+ Attempts to get an initial ticket for creds->client to use server
+ creds->server, (realm is taken from creds->client), with options
+ options, and using creds->times.starttime, creds->times.endtime,
+ creds->times.renew_till as from, till, and rtime.  
+ creds->times.renew_till is ignored unless the RENEWABLE option is requested.
+
+ If addrs is non-NULL, it is used for the addresses requested.  If it is
+ null, the system standard addresses are used.
+
+ If keyblock is NULL, an appropriate key for creds->client is retrieved
+ from the system key store (e.g. /etc/srvtab).  If keyblock is non-NULL,
+ it is used as the decryption key.
+
+ A succesful call will place the ticket in the credentials cache ccache.
+
+ returns system errors, encryption errors
+
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options,
+			  krb5_address *const *addrs, krb5_enctype *ktypes,
+			  krb5_preauthtype *pre_auth_types,
+			  const krb5_keyblock *key, krb5_ccache ccache,
+			  krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+{
+    if (key) 
+    	return krb5_get_in_tkt(context, options, addrs, ktypes, pre_auth_types, 
+			       skey_keyproc, (krb5_const_pointer)key,
+			       krb5_kdc_rep_decrypt_proc, 0, creds,
+			       ccache, ret_as_reply);
+    else 
+	return krb5_get_in_tkt_with_keytab(context, options, addrs, ktypes,
+					   pre_auth_types, NULL, ccache,
+					   creds, ret_as_reply);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/init_ctx.c b/krb5-1-6/src/lib/krb5/krb/init_ctx.c
new file mode 100644
index 000000000..b80fd50fa
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/init_ctx.c
@@ -0,0 +1,579 @@
+/*
+ * lib/krb5/krb/init_ctx.c
+ *
+ * Copyright 1994,1999,2000, 2002, 2003  by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * 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"
+/* There has to be a better way for windows... */
+#if defined(unix) || TARGET_OS_MAC
+#include "../krb5_libinit.h"
+#endif
+
+/* The des-mdX entries are last for now, because it's easy to
+   configure KDCs to issue TGTs with des-mdX keys and then not accept
+   them.  This'll be fixed, but for better compatibility, let's prefer
+   des-crc for now.  */
+#define DEFAULT_ETYPE_LIST	\
+	"aes256-cts-hmac-sha1-96 " \
+	"aes128-cts-hmac-sha1-96 " \
+	"des3-cbc-sha1 arcfour-hmac-md5 " \
+	"des-cbc-crc des-cbc-md5 des-cbc-md4 "
+
+/* Not included:
+	"aes128-cts-hmac-sha1-96 " \
+ */
+
+#if (defined(_WIN32))
+extern krb5_error_code krb5_vercheck();
+extern void krb5_win_ccdll_load(krb5_context context);
+#endif
+
+static krb5_error_code init_common (krb5_context *, krb5_boolean, krb5_boolean);
+
+krb5_error_code KRB5_CALLCONV
+krb5_init_context(krb5_context *context)
+{
+
+	return init_common (context, FALSE, FALSE);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_init_secure_context(krb5_context *context)
+{
+
+        /* This is to make gcc -Wall happy */
+        if(0) krb5_brand[0] = krb5_brand[0];
+	return init_common (context, TRUE, FALSE);
+}
+
+krb5_error_code
+krb5int_init_context_kdc(krb5_context *context)
+{
+    return init_common (context, FALSE, TRUE);
+}
+
+static krb5_error_code
+init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
+{
+	krb5_context ctx = 0;
+	krb5_error_code retval;
+	struct {
+	    krb5_int32 now, now_usec;
+	    long pid;
+	} seed_data;
+	krb5_data seed;
+	int tmp;
+
+	/* Verify some assumptions.  If the assumptions hold and the
+	   compiler is optimizing, this should result in no code being
+	   executed.  If we're guessing "unsigned long long" instead
+	   of using uint64_t, the possibility does exist that we're
+	   wrong.  */
+	{
+	    krb5_ui_8 i64;
+	    assert(sizeof(i64) == 8);
+	    i64 = 0, i64--, i64 >>= 62;
+	    assert(i64 == 3);
+	    i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
+	    assert(i64 != 0);
+	    i64 <<= 1;
+	    assert(i64 == 0);
+	}
+
+	retval = krb5int_initialize_library();
+	if (retval)
+	    return retval;
+
+#if (defined(_WIN32))
+	/* 
+	 * Load the krbcc32.dll if necessary.  We do this here so that
+	 * we know to use API: later on during initialization.
+	 * The context being NULL is ok.
+	 */
+	krb5_win_ccdll_load(ctx);
+
+	/*
+	 * krb5_vercheck() is defined in win_glue.c, and this is
+	 * where we handle the timebomb and version server checks.
+	 */
+	retval = krb5_vercheck();
+	if (retval)
+		return retval;
+#endif
+
+	*context = 0;
+
+	ctx = malloc(sizeof(struct _krb5_context));
+	if (!ctx)
+		return ENOMEM;
+	memset(ctx, 0, sizeof(struct _krb5_context));
+	ctx->magic = KV5M_CONTEXT;
+
+	ctx->profile_secure = secure;
+
+	/* Set the default encryption types, possible defined in krb5/conf */
+	if ((retval = krb5_set_default_in_tkt_ktypes(ctx, NULL)))
+		goto cleanup;
+
+	if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL)))
+		goto cleanup;
+
+	if ((retval = krb5_os_init_context(ctx, kdc)))
+		goto cleanup;
+
+	/* initialize the prng (not well, but passable) */
+	if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) !=0)
+	  goto cleanup;
+	if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
+		goto cleanup;
+	seed_data.pid = getpid ();
+	seed.length = sizeof(seed_data);
+	seed.data = (char *) &seed_data;
+	if ((retval = krb5_c_random_add_entropy(ctx, KRB5_C_RANDSOURCE_TIMING, &seed)))
+		goto cleanup;
+
+	ctx->default_realm = 0;
+	profile_get_integer(ctx->profile, "libdefaults", "clockskew",
+			    0, 5 * 60, &tmp);
+	ctx->clockskew = tmp;
+
+#if 0
+	/* Default ticket lifetime is currently not supported */
+	profile_get_integer(ctx->profile, "libdefaults", "tkt_lifetime",
+			    0, 10 * 60 * 60, &tmp);
+	ctx->tkt_lifetime = tmp;
+#endif
+
+	/* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2)  */
+	/* DCE add kdc_req_checksum_type = 2 to krb5.conf */
+	profile_get_integer(ctx->profile, "libdefaults",
+			    "kdc_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, 
+			    &tmp);
+	ctx->kdc_req_sumtype = tmp;
+
+	profile_get_integer(ctx->profile, "libdefaults",
+			    "ap_req_checksum_type", 0, CKSUMTYPE_RSA_MD5,
+			    &tmp);
+	ctx->default_ap_req_sumtype = tmp;
+
+	profile_get_integer(ctx->profile, "libdefaults",
+			    "safe_checksum_type", 0,
+			    CKSUMTYPE_RSA_MD5_DES, &tmp);
+	ctx->default_safe_sumtype = tmp;
+
+	profile_get_integer(ctx->profile, "libdefaults",
+			    "kdc_default_options", 0,
+			    KDC_OPT_RENEWABLE_OK, &tmp);
+	ctx->kdc_default_options = tmp;
+#define DEFAULT_KDC_TIMESYNC 1
+	profile_get_integer(ctx->profile, "libdefaults",
+			    "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC,
+			    &tmp);
+	ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
+
+	/*
+	 * We use a default file credentials cache of 3.  See
+	 * lib/krb5/krb/ccache/file/fcc.h for a description of the
+	 * credentials cache types.
+	 *
+	 * Note: DCE 1.0.3a only supports a cache type of 1
+	 * 	DCE 1.1 supports a cache type of 2.
+	 */
+#define DEFAULT_CCACHE_TYPE 4
+	profile_get_integer(ctx->profile, "libdefaults", "ccache_type",
+			    0, DEFAULT_CCACHE_TYPE, &tmp);
+	ctx->fcc_default_format = tmp + 0x0500;
+	ctx->scc_default_format = tmp + 0x0500;
+	ctx->prompt_types = 0;
+	ctx->use_conf_ktypes = 0;
+
+	ctx->udp_pref_limit = -1;
+	*context = ctx;
+	return 0;
+
+cleanup:
+	krb5_free_context(ctx);
+	return retval;
+}
+
+void KRB5_CALLCONV
+krb5_free_context(krb5_context ctx)
+{
+     krb5_os_free_context(ctx);
+
+     if (ctx->in_tkt_ktypes) {
+          free(ctx->in_tkt_ktypes);
+	  ctx->in_tkt_ktypes = 0;
+     }
+
+     if (ctx->tgs_ktypes) {
+          free(ctx->tgs_ktypes);
+	  ctx->tgs_ktypes = 0;
+     }
+
+     if (ctx->default_realm) {
+	  free(ctx->default_realm);
+	  ctx->default_realm = 0;
+     }
+
+     if (ctx->ser_ctx_count && ctx->ser_ctx) {
+	  free(ctx->ser_ctx);
+	  ctx->ser_ctx = 0;
+     }
+
+     krb5_clear_error_message(ctx);
+
+     ctx->magic = 0;
+     free(ctx);
+}
+
+/*
+ * Set the desired default ktypes, making sure they are valid.
+ */
+krb5_error_code
+krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes)
+{
+    krb5_enctype * new_ktypes;
+    int i;
+
+    if (ktypes) {
+	for (i = 0; ktypes[i]; i++) {
+	    if (!krb5_c_valid_enctype(ktypes[i])) 
+		return KRB5_PROG_ETYPE_NOSUPP;
+	}
+
+	/* Now copy the default ktypes into the context pointer */
+	if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
+	    memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
+	else
+	    return ENOMEM;
+
+    } else {
+	i = 0;
+	new_ktypes = 0;
+    }
+
+    if (context->in_tkt_ktypes) 
+        free(context->in_tkt_ktypes);
+    context->in_tkt_ktypes = new_ktypes;
+    context->in_tkt_ktype_count = i;
+    return 0;
+}
+
+static krb5_error_code
+get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profstr,
+		       unsigned int ctx_count, krb5_enctype *ctx_list)
+{
+    krb5_enctype *old_ktypes;
+
+    if (ctx_count) {
+	/* 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 {
+        /*
+	   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;
+
+	code = profile_get_string(context->profile, "libdefaults", profstr,
+				  NULL, DEFAULT_ETYPE_LIST, &retval);
+	if (code)
+	    return code;
+
+	count = 0;
+	sp = retval;
+	while (*sp) {
+	    for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++)
+		;
+	    if (*ep) {
+		*ep++ = '\0';
+		while (isspace((int) (*ep)) || *ep == ',')
+		    *ep++ = '\0';
+	    }
+	    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 (i++ >= count)
+		break;
+
+	    /* skip to next token */
+	    while (*sp) sp++;
+	    while (! *sp) sp++;
+	}
+
+	old_ktypes[j] = (krb5_enctype) 0;
+	profile_release_string(retval);
+    }
+
+    if (old_ktypes[0] == 0) {
+	free (old_ktypes);
+	*ktypes = 0;
+	return KRB5_CONFIG_ETYPE_NOSUPP;
+    }
+
+    *ktypes = old_ktypes;
+    return 0;
+}
+
+krb5_error_code
+krb5_get_default_in_tkt_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_CALLCONV
+krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes)
+{
+    krb5_enctype * new_ktypes;
+    int i;
+
+    if (ktypes) {
+	for (i = 0; ktypes[i]; i++) {
+	    if (!krb5_c_valid_enctype(ktypes[i])) 
+		return KRB5_PROG_ETYPE_NOSUPP;
+	}
+
+	/* Now copy the default ktypes into the context pointer */
+	if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
+	    memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
+	else
+	    return ENOMEM;
+
+    } else {
+	i = 0;
+	new_ktypes = (krb5_enctype *)NULL;
+    }
+
+    if (context->tgs_ktypes) 
+        krb5_free_ktypes(context, context->tgs_ktypes);
+    context->tgs_ktypes = new_ktypes;
+    context->tgs_ktype_count = i;
+    return 0;
+}
+
+krb5_error_code krb5_set_default_tgs_ktypes
+(krb5_context context, const krb5_enctype *etypes)
+{
+  return (krb5_set_default_tgs_enctypes (context, etypes));
+}
+
+
+void
+KRB5_CALLCONV
+krb5_free_ktypes (krb5_context context, krb5_enctype *val)
+{
+    free (val);
+}
+
+krb5_error_code
+KRB5_CALLCONV
+krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes)
+{
+    if (context->use_conf_ktypes)
+	/* This one is set *only* by reading the config file; it's not
+	   set by the application.  */
+	return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
+				      0, NULL));
+    else
+	return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
+				      context->tgs_ktype_count,
+				      context->tgs_ktypes));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
+{
+    return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
+				  context->tgs_ktype_count,
+				  context->tgs_ktypes));
+}
+
+krb5_boolean
+krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
+{
+    krb5_enctype *list, *ptr;
+    krb5_boolean ret;
+
+    if (krb5_get_permitted_enctypes(context, &list))
+	return(0);
+
+    
+    ret = 0;
+
+    for (ptr = list; *ptr; ptr++)
+	if (*ptr == etype)
+	    ret = 1;
+
+    krb5_free_ktypes (context, list);
+
+    return(ret);
+}
+
+static krb5_error_code
+copy_ktypes(krb5_context ctx,
+	    unsigned int nktypes,
+	    krb5_enctype *oldktypes,
+	    krb5_enctype **newktypes)
+{
+    unsigned int i;
+
+    *newktypes = NULL;
+    if (!nktypes)
+	return 0;
+
+    *newktypes = malloc(nktypes * sizeof(krb5_enctype));
+    if (*newktypes == NULL)
+	return ENOMEM;
+    for (i = 0; i < nktypes; i++)
+	(*newktypes)[i] = oldktypes[i];
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_copy_context(krb5_context ctx, krb5_context *nctx_out)
+{
+    krb5_error_code ret;
+    krb5_context nctx;
+
+    *nctx_out = NULL;
+    if (ctx == NULL)
+	return EINVAL;		/* XXX */
+
+    nctx = malloc(sizeof(*nctx));
+    if (nctx == NULL)
+	return ENOMEM;
+
+    *nctx = *ctx;
+
+    nctx->in_tkt_ktypes = NULL;
+    nctx->in_tkt_ktype_count = 0;
+    nctx->tgs_ktypes = NULL;
+    nctx->tgs_ktype_count = 0;
+    nctx->default_realm = NULL;
+    nctx->profile = NULL;
+    nctx->db_context = NULL;
+    nctx->ser_ctx_count = 0;
+    nctx->ser_ctx = NULL;
+    nctx->prompt_types = NULL;
+    nctx->os_context->default_ccname = NULL;
+
+    memset(&nctx->preauth_plugins, 0, sizeof(nctx->preauth_plugins));
+    nctx->preauth_context = NULL;
+
+    memset(&nctx->libkrb5_plugins, 0, sizeof(nctx->libkrb5_plugins));
+    nctx->vtbl = NULL;
+    nctx->locate_fptrs = NULL;
+
+    memset(&nctx->err, 0, sizeof(nctx->err));
+
+    ret = copy_ktypes(nctx, ctx->in_tkt_ktype_count,
+		      ctx->in_tkt_ktypes, &nctx->in_tkt_ktypes);
+    if (ret)
+	goto errout;
+    nctx->in_tkt_ktype_count = ctx->in_tkt_ktype_count;
+
+    ret = copy_ktypes(nctx, ctx->tgs_ktype_count,
+		      ctx->tgs_ktypes, &nctx->in_tkt_ktypes);
+    if (ret)
+	goto errout;
+    nctx->tgs_ktype_count = ctx->tgs_ktype_count;
+
+    if (ctx->os_context->default_ccname != NULL) {
+	nctx->os_context->default_ccname =
+	    strdup(ctx->os_context->default_ccname);
+	if (nctx->os_context->default_ccname == NULL) {
+	    ret = ENOMEM;
+	    goto errout;
+	}
+    }
+    ret = krb5_get_profile(ctx, &nctx->profile);
+    if (ret)
+	goto errout;
+
+errout:
+    if (ret) {
+	krb5_free_context(nctx);
+    } else {
+	*nctx_out = nctx;
+    }
+    return ret;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/init_keyblock.c b/krb5-1-6/src/lib/krb5/krb/init_keyblock.c
new file mode 100644
index 000000000..3be842ac8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/init_keyblock.c
@@ -0,0 +1,41 @@
+/*
+ * lib/krb5/krb/init_keyblock.c
+ *
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 
+ *
+ * krb5_init_keyblock- a function to set up 
+ *  an empty keyblock
+ */
+
+
+#include "k5-int.h"
+#include <assert.h>
+
+krb5_error_code KRB5_CALLCONV  krb5_init_keyblock
+	(krb5_context context, krb5_enctype enctype,
+	 size_t length, krb5_keyblock **out)
+{
+  return krb5int_c_init_keyblock (context, enctype, length, out);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/int-proto.h b/krb5-1-6/src/lib/krb5/krb/int-proto.h
new file mode 100644
index 000000000..5c576c3fd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/int-proto.h
@@ -0,0 +1,58 @@
+/*
+ * lib/krb5/krb/int-proto.h
+ *
+ * Copyright 1990,1991 the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Function prototypes for Kerberos V5 library internal functions.
+ */
+
+
+#ifndef KRB5_INT_FUNC_PROTO__
+#define KRB5_INT_FUNC_PROTO__
+
+krb5_error_code krb5_tgtname
+    	(krb5_context context,
+	           const krb5_data *,
+	           const krb5_data *,
+	           krb5_principal *);
+
+krb5_error_code krb5_libdefault_boolean
+        (krb5_context, const krb5_data *, const char *,
+			int *);
+
+krb5_error_code krb5_ser_authdata_init (krb5_context);
+krb5_error_code krb5_ser_address_init (krb5_context);
+krb5_error_code krb5_ser_authenticator_init (krb5_context);
+krb5_error_code krb5_ser_checksum_init (krb5_context);
+krb5_error_code krb5_ser_keyblock_init (krb5_context);
+krb5_error_code krb5_ser_principal_init (krb5_context);
+
+krb5_error_code
+krb5_preauth_supply_preauth_data(krb5_context context,
+				 krb5_gic_opt_ext *opte,
+				 const char *attr,
+				 const char *value);
+
+#endif /* KRB5_INT_FUNC_PROTO__ */
+
diff --git a/krb5-1-6/src/lib/krb5/krb/kdc_rep_dc.c b/krb5-1-6/src/lib/krb5/krb/kdc_rep_dc.c
new file mode 100644
index 000000000..42559b2f1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/kdc_rep_dc.c
@@ -0,0 +1,80 @@
+/*
+ * lib/krb5/krb/kdc_rep_dc.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_kdc_rep_decrypt_proc()
+ */
+
+#include "k5-int.h"
+
+/*
+ * Decrypt the encrypted portion of the KDC_REP message, using the key
+ * passed.
+ *
+ */
+
+/*ARGSUSED*/
+krb5_error_code
+krb5_kdc_rep_decrypt_proc(krb5_context context, const krb5_keyblock *key, krb5_const_pointer decryptarg, krb5_kdc_rep *dec_rep)
+{
+    krb5_error_code retval;
+    krb5_data scratch;
+    krb5_enc_kdc_rep_part *local_encpart;
+    krb5_keyusage usage;
+
+    if (decryptarg) {
+	usage = *(const krb5_keyusage *) decryptarg;
+    } else {
+	usage = KRB5_KEYUSAGE_AS_REP_ENCPART;
+    }
+
+    /* set up scratch decrypt/decode area */
+
+    scratch.length = dec_rep->enc_part.ciphertext.length;
+    if (!(scratch.data = malloc(dec_rep->enc_part.ciphertext.length))) {
+	return(ENOMEM);
+    }
+
+    /*dec_rep->enc_part.enctype;*/
+
+    if ((retval = krb5_c_decrypt(context, key, usage, 0, &dec_rep->enc_part,
+				 &scratch))) {
+	free(scratch.data);
+	return(retval);
+    }
+
+#define clean_scratch() {memset(scratch.data, 0, scratch.length); \
+free(scratch.data);}
+
+    /* and do the decode */
+    retval = decode_krb5_enc_kdc_rep_part(&scratch, &local_encpart);
+    clean_scratch();
+    if (retval)
+	return retval;
+
+    dec_rep->enc_part2 = local_encpart;
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/kerrs.c b/krb5-1-6/src/lib/krb5/krb/kerrs.c
new file mode 100644
index 000000000..77f497688
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/kerrs.c
@@ -0,0 +1,112 @@
+/*
+ * lib/krb5/krb/kerrs.c
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * error-message functions
+ */
+#include <stdarg.h>
+#include "k5-int.h"
+
+#ifdef DEBUG
+static int error_message_debug = 0;
+#ifndef ERROR_MESSAGE_DEBUG
+#define ERROR_MESSAGE_DEBUG() (error_message_debug != 0)
+#endif
+#endif
+
+void KRB5_CALLCONV_C
+krb5_set_error_message (krb5_context ctx, krb5_error_code code,
+			const char *fmt, ...)
+{
+    va_list args;
+    if (ctx == NULL)
+	return;
+    va_start (args, fmt);
+#ifdef DEBUG
+    if (ERROR_MESSAGE_DEBUG())
+	fprintf(stderr,
+		"krb5_set_error_message(ctx=%p/err=%p, code=%ld, ...)\n",
+		ctx, &ctx->err, (long) code);
+#endif
+    krb5int_vset_error (&ctx->err, code, fmt, args);
+#ifdef DEBUG
+    if (ERROR_MESSAGE_DEBUG())
+	fprintf(stderr, "->%s\n", ctx->err.msg);
+#endif
+    va_end (args);
+}
+
+void KRB5_CALLCONV
+krb5_vset_error_message (krb5_context ctx, krb5_error_code code,
+			 const char *fmt, va_list args)
+{
+#ifdef DEBUG
+    if (ERROR_MESSAGE_DEBUG())
+	fprintf(stderr, "krb5_vset_error_message(ctx=%p, code=%ld, ...)\n",
+		ctx, (long) code);
+#endif
+    if (ctx == NULL)
+	return;
+    krb5int_vset_error (&ctx->err, code, fmt, args);
+#ifdef DEBUG
+    if (ERROR_MESSAGE_DEBUG())
+	fprintf(stderr, "->%s\n", ctx->err.msg);
+#endif
+}
+
+const char * KRB5_CALLCONV
+krb5_get_error_message (krb5_context ctx, krb5_error_code code)
+{
+#ifdef DEBUG
+    if (ERROR_MESSAGE_DEBUG())
+	fprintf(stderr, "krb5_get_error_message(%p, %ld)\n", ctx, (long) code);
+#endif
+    if (ctx == NULL)
+	return error_message(code);
+    return krb5int_get_error (&ctx->err, code);
+}
+
+void KRB5_CALLCONV
+krb5_free_error_message (krb5_context ctx, const char *msg)
+{
+#ifdef DEBUG
+    if (ERROR_MESSAGE_DEBUG())
+	fprintf(stderr, "krb5_free_error_message(%p, %p)\n", ctx, msg);
+#endif
+    if (ctx == NULL)
+	return;
+    krb5int_free_error (&ctx->err, msg);
+}
+
+void KRB5_CALLCONV
+krb5_clear_error_message (krb5_context ctx)
+{
+#ifdef DEBUG
+    if (ERROR_MESSAGE_DEBUG())
+	fprintf(stderr, "krb5_clear_error_message(%p)\n", ctx);
+#endif
+    if (ctx == NULL)
+	return;
+    krb5int_clear_error (&ctx->err);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/kfree.c b/krb5-1-6/src/lib/krb5/krb/kfree.c
new file mode 100644
index 000000000..39bb1f212
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/kfree.c
@@ -0,0 +1,715 @@
+/*
+ * lib/krb5/free/f_addr.c
+ *
+ * Copyright 1990-1998 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_free_address()
+ */
+
+#include "k5-int.h"
+
+void KRB5_CALLCONV
+krb5_free_address(krb5_context context, krb5_address *val)
+{
+    if (val->contents)
+	krb5_xfree(val->contents);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_addresses(krb5_context context, krb5_address **val)
+{
+    register krb5_address **temp;
+
+    for (temp = val; *temp; temp++) {
+	if ((*temp)->contents)
+	    krb5_xfree((*temp)->contents);
+	krb5_xfree(*temp);
+    }
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_ap_rep(krb5_context context, register krb5_ap_rep *val)
+{
+    if (val->enc_part.ciphertext.data)
+	krb5_xfree(val->enc_part.ciphertext.data);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_ap_req(krb5_context context, register krb5_ap_req *val)
+{
+    if (val->ticket)
+	krb5_free_ticket(context, val->ticket);
+    if (val->authenticator.ciphertext.data)
+	krb5_xfree(val->authenticator.ciphertext.data);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part *val)
+{
+    if (val->subkey)
+	krb5_free_keyblock(context, val->subkey);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_authenticator_contents(krb5_context context, krb5_authenticator *val)
+{
+    if (val->checksum) {
+	krb5_free_checksum(context, val->checksum);
+	val->checksum = 0;
+    }
+    if (val->client) {
+	krb5_free_principal(context, val->client);
+	val->client = 0;
+    }
+    if (val->subkey) {
+	krb5_free_keyblock(context, val->subkey);
+	val->subkey = 0;
+    }
+    if (val->authorization_data) {
+	krb5_free_authdata(context, val->authorization_data);
+	val->authorization_data = 0;
+    }
+}
+
+void KRB5_CALLCONV
+krb5_free_authdata(krb5_context context, krb5_authdata **val)
+{
+    register krb5_authdata **temp;
+
+    for (temp = val; *temp; temp++) {
+	if ((*temp)->contents)
+	    krb5_xfree((*temp)->contents);
+	krb5_xfree(*temp);
+    }
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_authenticator(krb5_context context, krb5_authenticator *val)
+{
+    krb5_free_authenticator_contents(context, val);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_checksum(krb5_context context, register krb5_checksum *val)
+{
+    krb5_free_checksum_contents(context, val);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_checksum_contents(krb5_context context, register krb5_checksum *val)
+{
+    if (val->contents) {
+	krb5_xfree(val->contents);
+	val->contents = 0;
+    }
+}
+
+void KRB5_CALLCONV
+krb5_free_cred(krb5_context context, register krb5_cred *val)
+{
+    if (val->tickets)
+        krb5_free_tickets(context, val->tickets);
+    if (val->enc_part.ciphertext.data)
+	krb5_xfree(val->enc_part.ciphertext.data);
+    krb5_xfree(val);
+}
+
+/*
+ * krb5_free_cred_contents zeros out the session key, and then frees
+ * the credentials structures 
+ */
+
+void KRB5_CALLCONV
+krb5_free_cred_contents(krb5_context context, krb5_creds *val)
+{
+    if (val->client) {
+	krb5_free_principal(context, val->client);
+	val->client = 0;
+    }
+    if (val->server) {
+	krb5_free_principal(context, val->server);
+	val->server = 0;
+    }
+    if (val->keyblock.contents) {
+	memset((char *)val->keyblock.contents, 0, val->keyblock.length);
+	krb5_xfree(val->keyblock.contents);
+	val->keyblock.contents = 0;
+    }
+    if (val->ticket.data) {
+	krb5_xfree(val->ticket.data);
+	val->ticket.data = 0;
+    }
+    if (val->second_ticket.data) {
+	krb5_xfree(val->second_ticket.data);
+	val->second_ticket.data = 0;
+    }
+    if (val->addresses) {
+	krb5_free_addresses(context, val->addresses);
+	val->addresses = 0;
+    }
+    if (val->authdata) {
+	krb5_free_authdata(context, val->authdata);
+	val->authdata = 0;
+    }
+}
+
+void KRB5_CALLCONV 
+krb5_free_cred_enc_part(krb5_context context, register krb5_cred_enc_part *val)
+{
+    register krb5_cred_info **temp;
+    
+    if (val->r_address) {
+	krb5_free_address(context, val->r_address);
+	val->r_address = 0;
+    }
+    if (val->s_address) {
+	krb5_free_address(context, val->s_address);
+	val->s_address = 0;
+    }
+
+    if (val->ticket_info) {
+	for (temp = val->ticket_info; *temp; temp++) {
+	    if ((*temp)->session)
+		krb5_free_keyblock(context, (*temp)->session);
+	    if ((*temp)->client)
+		krb5_free_principal(context, (*temp)->client);
+	    if ((*temp)->server)
+		krb5_free_principal(context, (*temp)->server);
+	    if ((*temp)->caddrs)
+		krb5_free_addresses(context, (*temp)->caddrs);
+	    krb5_xfree((*temp));
+	}
+	krb5_xfree(val->ticket_info);
+	val->ticket_info = 0;
+    }
+}
+
+
+void KRB5_CALLCONV
+krb5_free_creds(krb5_context context, krb5_creds *val)
+{
+    krb5_free_cred_contents(context, val);
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_data(krb5_context context, krb5_data *val)
+{
+    if (val->data)
+	krb5_xfree(val->data);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_data_contents(krb5_context context, krb5_data *val)
+{
+    if (val->data) {
+	krb5_xfree(val->data);
+	val->data = 0;
+    }
+}
+
+void krb5_free_etype_info(krb5_context context, krb5_etype_info info)
+{
+  int i;
+
+  for(i=0; info[i] != NULL; i++) {
+      if (info[i]->salt)
+	  free(info[i]->salt);
+      krb5_free_data_contents( context, &info[i]->s2kparams);
+      free(info[i]);
+  }
+  free(info);
+}
+    
+
+void KRB5_CALLCONV
+krb5_free_enc_kdc_rep_part(krb5_context context, register krb5_enc_kdc_rep_part *val)
+{
+    if (val->session)
+	krb5_free_keyblock(context, val->session);
+    if (val->last_req)
+	krb5_free_last_req(context, val->last_req);
+    if (val->server)
+	krb5_free_principal(context, val->server);
+    if (val->caddrs)
+	krb5_free_addresses(context, val->caddrs);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_enc_tkt_part(krb5_context context, krb5_enc_tkt_part *val)
+{
+    if (val->session)
+	krb5_free_keyblock(context, val->session);
+    if (val->client)
+	krb5_free_principal(context, val->client);
+    if (val->transited.tr_contents.data)
+	krb5_xfree(val->transited.tr_contents.data);
+    if (val->caddrs)
+	krb5_free_addresses(context, val->caddrs);
+    if (val->authorization_data)
+	krb5_free_authdata(context, val->authorization_data);
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_error(krb5_context context, register krb5_error *val)
+{
+    if (val->client)
+	krb5_free_principal(context, val->client);
+    if (val->server)
+	krb5_free_principal(context, val->server);
+    if (val->text.data)
+	krb5_xfree(val->text.data);
+    if (val->e_data.data)
+	krb5_xfree(val->e_data.data);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *val)
+{
+    if (val->padata)
+	krb5_free_pa_data(context, val->padata);
+    if (val->client)
+	krb5_free_principal(context, val->client);
+    if (val->ticket)
+	krb5_free_ticket(context, val->ticket);
+    if (val->enc_part.ciphertext.data)
+	krb5_xfree(val->enc_part.ciphertext.data);
+    if (val->enc_part2)
+	krb5_free_enc_kdc_rep_part(context, val->enc_part2);
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_kdc_req(krb5_context context, krb5_kdc_req *val)
+{
+    if (val->padata)
+	krb5_free_pa_data(context, val->padata);
+    if (val->client)
+	krb5_free_principal(context, val->client);
+    if (val->server)
+	krb5_free_principal(context, val->server);
+    if (val->ktype)
+	krb5_xfree(val->ktype);
+    if (val->addresses)
+	krb5_free_addresses(context, val->addresses);
+    if (val->authorization_data.ciphertext.data)
+	krb5_xfree(val->authorization_data.ciphertext.data);
+    if (val->unenc_authdata)
+	krb5_free_authdata(context, val->unenc_authdata);
+    if (val->second_ticket)
+	krb5_free_tickets(context, val->second_ticket);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_keyblock_contents(krb5_context context, register krb5_keyblock *key)
+{
+    krb5int_c_free_keyblock_contents (context, key);
+}
+
+void KRB5_CALLCONV
+krb5_free_keyblock(krb5_context context, register krb5_keyblock *val)
+{
+    krb5int_c_free_keyblock (context, val);
+}
+
+
+
+void KRB5_CALLCONV
+krb5_free_last_req(krb5_context context, krb5_last_req_entry **val)
+{
+    register krb5_last_req_entry **temp;
+
+    for (temp = val; *temp; temp++)
+	krb5_xfree(*temp);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_pa_data(krb5_context context, krb5_pa_data **val)
+{
+    register krb5_pa_data **temp;
+
+    for (temp = val; *temp; temp++) {
+	if ((*temp)->contents)
+	    krb5_xfree((*temp)->contents);
+	krb5_xfree(*temp);
+    }
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_principal(krb5_context context, krb5_principal val)
+{
+    register krb5_int32 i;
+
+    if (!val)
+	return;
+    
+    if (val->data) {
+	i = krb5_princ_size(context, val);
+	while(--i >= 0)
+	    free(krb5_princ_component(context, val, i)->data);
+	krb5_xfree(val->data);
+    }
+    if (val->realm.data)
+	krb5_xfree(val->realm.data);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_priv(krb5_context context, register krb5_priv *val)
+{
+    if (val->enc_part.ciphertext.data)
+	krb5_xfree(val->enc_part.ciphertext.data);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_priv_enc_part(krb5_context context, register krb5_priv_enc_part *val)
+{
+    if (val->user_data.data)
+	krb5_xfree(val->user_data.data);
+    if (val->r_address)
+	krb5_free_address(context, val->r_address);
+    if (val->s_address)
+	krb5_free_address(context, val->s_address);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_pwd_data(krb5_context context, krb5_pwd_data *val)
+{
+    if (val->element)
+	krb5_free_pwd_sequences(context, val->element);
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_pwd_sequences(krb5_context context, passwd_phrase_element **val)
+{
+    register passwd_phrase_element **temp;
+
+    for (temp = val; *temp; temp++) {
+	if ((*temp)->passwd) {
+	   krb5_free_data(context, (*temp)->passwd);
+	   (*temp)->passwd = 0;
+	}
+	if ((*temp)->phrase) {
+	   krb5_free_data(context, (*temp)->phrase);
+	   (*temp)->phrase = 0;
+	}
+	krb5_xfree(*temp);
+    }
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_safe(krb5_context context, register krb5_safe *val)
+{
+    if (val->user_data.data)
+	krb5_xfree(val->user_data.data);
+    if (val->r_address)
+	krb5_free_address(context, val->r_address);
+    if (val->s_address)
+	krb5_free_address(context, val->s_address);
+    if (val->checksum)
+	krb5_free_checksum(context, val->checksum);
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_ticket(krb5_context context, krb5_ticket *val)
+{
+    if (val->server)
+	krb5_free_principal(context, val->server);
+    if (val->enc_part.ciphertext.data)
+	krb5_xfree(val->enc_part.ciphertext.data);
+    if (val->enc_part2)
+	krb5_free_enc_tkt_part(context, val->enc_part2);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_tickets(krb5_context context, krb5_ticket **val)
+{
+    register krb5_ticket **temp;
+
+    for (temp = val; *temp; temp++)
+        krb5_free_ticket(context, *temp);
+    krb5_xfree(val);
+}
+
+
+void KRB5_CALLCONV
+krb5_free_tgt_creds(krb5_context context, krb5_creds **tgts)
+{
+    register krb5_creds **tgtpp;
+    for (tgtpp = tgts; *tgtpp; tgtpp++)
+	krb5_free_creds(context, *tgtpp);
+    krb5_xfree(tgts);
+}
+
+void KRB5_CALLCONV
+krb5_free_tkt_authent(krb5_context context, krb5_tkt_authent *val)
+{
+    if (val->ticket)
+	    krb5_free_ticket(context, val->ticket);
+    if (val->authenticator)
+	    krb5_free_authenticator(context, val->authenticator);
+    krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_unparsed_name(krb5_context context, char *val)
+{
+    if (val)
+	krb5_xfree(val);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge(krb5_context ctx, krb5_sam_challenge *sc)
+{
+    if (!sc)
+	return;
+    krb5_free_sam_challenge_contents(ctx, sc);
+    krb5_xfree(sc);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2(krb5_context ctx, krb5_sam_challenge_2 *sc2)
+{
+    if (!sc2)
+	return;
+    krb5_free_sam_challenge_2_contents(ctx, sc2);
+    krb5_xfree(sc2);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_contents(krb5_context ctx, krb5_sam_challenge *sc)
+{
+    if (!sc)
+	return;
+    if (sc->sam_type_name.data)
+	krb5_free_data_contents(ctx, &sc->sam_type_name);
+    if (sc->sam_track_id.data)
+	krb5_free_data_contents(ctx, &sc->sam_track_id);
+    if (sc->sam_challenge_label.data)
+	krb5_free_data_contents(ctx, &sc->sam_challenge_label);
+    if (sc->sam_challenge.data)
+	krb5_free_data_contents(ctx, &sc->sam_challenge);
+    if (sc->sam_response_prompt.data)
+	krb5_free_data_contents(ctx, &sc->sam_response_prompt);
+    if (sc->sam_pk_for_sad.data)
+	krb5_free_data_contents(ctx, &sc->sam_pk_for_sad);
+    if (sc->sam_cksum.contents) {
+	krb5_xfree(sc->sam_cksum.contents);
+	sc->sam_cksum.contents = 0;
+    }
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2_contents(krb5_context ctx,
+				   krb5_sam_challenge_2 *sc2)
+{
+    krb5_checksum **cksump;
+
+    if (!sc2)
+	return;
+    if (sc2->sam_challenge_2_body.data)
+	krb5_free_data_contents(ctx, &sc2->sam_challenge_2_body);
+    if (sc2->sam_cksum) {
+	cksump = sc2->sam_cksum;
+	while (*cksump) {
+	    krb5_free_checksum(ctx, *cksump);
+	    cksump++;
+	}
+	krb5_xfree(sc2->sam_cksum);
+	sc2->sam_cksum = 0;
+    }
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2_body(krb5_context ctx,
+			       krb5_sam_challenge_2_body *sc2)
+{
+    if (!sc2)
+	return;
+    krb5_free_sam_challenge_2_body_contents(ctx, sc2);
+    krb5_xfree(sc2);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_challenge_2_body_contents(krb5_context ctx,
+					krb5_sam_challenge_2_body *sc2)
+{
+    if (!sc2)
+	return;
+    if (sc2->sam_type_name.data) 
+	krb5_free_data_contents(ctx, &sc2->sam_type_name);
+    if (sc2->sam_track_id.data)
+	krb5_free_data_contents(ctx, &sc2->sam_track_id);
+    if (sc2->sam_challenge_label.data)
+	krb5_free_data_contents(ctx, &sc2->sam_challenge_label);
+    if (sc2->sam_challenge.data)
+	krb5_free_data_contents(ctx, &sc2->sam_challenge);
+    if (sc2->sam_response_prompt.data)
+	krb5_free_data_contents(ctx, &sc2->sam_response_prompt);
+    if (sc2->sam_pk_for_sad.data)
+	krb5_free_data_contents(ctx, &sc2->sam_pk_for_sad);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_response(krb5_context ctx, krb5_sam_response *sr)
+{
+    if (!sr)
+	return;
+    krb5_free_sam_response_contents(ctx, sr);
+    krb5_xfree(sr);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_response_2(krb5_context ctx, krb5_sam_response_2 *sr2)
+{
+    if (!sr2)
+	return;
+    krb5_free_sam_response_2_contents(ctx, sr2);
+    krb5_xfree(sr2);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_response_contents(krb5_context ctx, krb5_sam_response *sr)
+{
+    if (!sr)
+	return;
+    if (sr->sam_track_id.data)
+	krb5_free_data_contents(ctx, &sr->sam_track_id);
+    if (sr->sam_enc_key.ciphertext.data)
+	krb5_free_data_contents(ctx, &sr->sam_enc_key.ciphertext);
+    if (sr->sam_enc_nonce_or_ts.ciphertext.data)
+	krb5_free_data_contents(ctx, &sr->sam_enc_nonce_or_ts.ciphertext);
+}
+
+void KRB5_CALLCONV
+krb5_free_sam_response_2_contents(krb5_context ctx, krb5_sam_response_2 *sr2)
+{
+    if (!sr2)
+	return;
+    if (sr2->sam_track_id.data)
+	krb5_free_data_contents(ctx, &sr2->sam_track_id);
+    if (sr2->sam_enc_nonce_or_sad.ciphertext.data)
+	krb5_free_data_contents(ctx, &sr2->sam_enc_nonce_or_sad.ciphertext);
+}
+
+void KRB5_CALLCONV
+krb5_free_predicted_sam_response(krb5_context ctx,
+				 krb5_predicted_sam_response *psr)
+{
+    if (!psr)
+	return;
+    krb5_free_predicted_sam_response_contents(ctx, psr);
+    krb5_xfree(psr);
+}
+
+void KRB5_CALLCONV
+krb5_free_predicted_sam_response_contents(krb5_context ctx,
+				 krb5_predicted_sam_response *psr)
+{
+    if (!psr)
+	return;
+    if (psr->sam_key.contents)
+	krb5_free_keyblock_contents(ctx, &psr->sam_key);
+    if (psr->client) {
+	krb5_free_principal(ctx, psr->client);
+	psr->client = 0;
+    }
+    if (psr->msd.data)
+	krb5_free_data_contents(ctx, &psr->msd);
+}
+
+void KRB5_CALLCONV
+krb5_free_enc_sam_response_enc(krb5_context ctx,
+			       krb5_enc_sam_response_enc *esre)
+{
+    if (!esre)
+	return;
+    krb5_free_enc_sam_response_enc_contents(ctx, esre);
+    krb5_xfree(esre);
+}
+
+void KRB5_CALLCONV 
+krb5_free_enc_sam_response_enc_2(krb5_context ctx,
+				 krb5_enc_sam_response_enc_2 *esre2)
+{
+    if (!esre2)
+	return;
+    krb5_free_enc_sam_response_enc_2_contents(ctx, esre2);
+    krb5_xfree(esre2);
+}
+
+void KRB5_CALLCONV
+krb5_free_enc_sam_response_enc_contents(krb5_context ctx,
+			       krb5_enc_sam_response_enc *esre)
+{
+    if (!esre)
+	return;
+    if (esre->sam_sad.data)
+	krb5_free_data_contents(ctx, &esre->sam_sad);
+}
+
+void KRB5_CALLCONV
+krb5_free_enc_sam_response_enc_2_contents(krb5_context ctx,
+					  krb5_enc_sam_response_enc_2 *esre2)
+{
+    if (!esre2)
+	return;
+    if (esre2->sam_sad.data)
+	krb5_free_data_contents(ctx, &esre2->sam_sad);
+}
+
+void KRB5_CALLCONV
+krb5_free_pa_enc_ts(krb5_context ctx, krb5_pa_enc_ts *pa_enc_ts)
+{
+    if (!pa_enc_ts)
+	return;
+    krb5_xfree(pa_enc_ts);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/mk_cred.c b/krb5-1-6/src/lib/krb5/krb/mk_cred.c
new file mode 100644
index 000000000..04248c08d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/mk_cred.c
@@ -0,0 +1,307 @@
+/* 
+ * NAME
+ *    cred.c
+ * 
+ * DESCRIPTION
+ *    Provide an interface to assemble and disassemble krb5_cred
+ *    structures.
+ *
+ */
+#include "k5-int.h"
+#include "cleanup.h"
+#include "auth_con.h"
+
+#include <stddef.h>           /* NULL */
+#include <stdlib.h>           /* malloc */
+#include <errno.h>            /* ENOMEM */
+
+/*-------------------- encrypt_credencpart --------------------*/
+
+/*
+ * encrypt the enc_part of krb5_cred
+ */
+static krb5_error_code 
+encrypt_credencpart(krb5_context context, krb5_cred_enc_part *pcredpart, krb5_keyblock *pkeyblock, krb5_enc_data *pencdata)
+{
+    krb5_error_code 	  retval;
+    krb5_data 		* scratch;
+
+    /* start by encoding to-be-encrypted part of the message */
+    if ((retval = encode_krb5_enc_cred_part(pcredpart, &scratch)))
+    	return retval;
+
+    /*
+     * If the keyblock is NULL, just copy the data from the encoded
+     * data to the ciphertext area.
+     */
+    if (pkeyblock == NULL) {
+	    pencdata->ciphertext.data = scratch->data;
+	    pencdata->ciphertext.length = scratch->length;
+	    krb5_xfree(scratch);
+	    return 0;
+    }
+
+    /* call the encryption routine */
+    retval = krb5_encrypt_helper(context, pkeyblock,
+				 KRB5_KEYUSAGE_KRB_CRED_ENCPART,
+				 scratch, pencdata);
+
+    if (retval) {
+    	memset(pencdata->ciphertext.data, 0, pencdata->ciphertext.length);
+        free(pencdata->ciphertext.data);
+        pencdata->ciphertext.length = 0;
+        pencdata->ciphertext.data = 0;
+    }
+
+    memset(scratch->data, 0, scratch->length); 
+    krb5_free_data(context, scratch);
+
+    return retval;
+}
+
+/*----------------------- krb5_mk_ncred_basic -----------------------*/
+
+static krb5_error_code
+krb5_mk_ncred_basic(krb5_context context, krb5_creds **ppcreds, krb5_int32 nppcreds, krb5_keyblock *keyblock, krb5_replay_data *replaydata, krb5_address *local_addr, krb5_address *remote_addr, krb5_cred *pcred)
+{
+    krb5_cred_enc_part 	  credenc;
+    krb5_error_code	  retval;
+    size_t		  size;
+    int			  i;
+
+    credenc.magic = KV5M_CRED_ENC_PART;
+
+    credenc.s_address = 0;
+    credenc.r_address = 0;
+    if (local_addr) krb5_copy_addr(context, local_addr, &credenc.s_address);
+    if (remote_addr) krb5_copy_addr(context, remote_addr, &credenc.r_address);
+
+    credenc.nonce = replaydata->seq;
+    credenc.usec = replaydata->usec;
+    credenc.timestamp = replaydata->timestamp;
+
+    /* Get memory for creds and initialize it */
+    size = sizeof(krb5_cred_info *) * (nppcreds + 1);
+    credenc.ticket_info = (krb5_cred_info **) malloc(size);
+    if (credenc.ticket_info == NULL)
+	return ENOMEM;
+    memset(credenc.ticket_info, 0, size);
+    
+    /*
+     * For each credential in the list, initialize a cred info
+     * structure and copy the ticket into the ticket list.
+     */
+    for (i = 0; i < nppcreds; i++) {
+    	credenc.ticket_info[i] = malloc(sizeof(krb5_cred_info));
+	if (credenc.ticket_info[i] == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	credenc.ticket_info[i+1] = NULL;
+	
+        credenc.ticket_info[i]->magic = KV5M_CRED_INFO;
+        credenc.ticket_info[i]->times = ppcreds[i]->times;
+        credenc.ticket_info[i]->flags = ppcreds[i]->ticket_flags;
+
+    	if ((retval = decode_krb5_ticket(&ppcreds[i]->ticket, 
+					 &pcred->tickets[i])))
+	    goto cleanup;
+
+	if ((retval = krb5_copy_keyblock(context, &ppcreds[i]->keyblock,
+					 &credenc.ticket_info[i]->session)))
+            goto cleanup;
+
+        if ((retval = krb5_copy_principal(context, ppcreds[i]->client,
+					  &credenc.ticket_info[i]->client)))
+            goto cleanup;
+
+      	if ((retval = krb5_copy_principal(context, ppcreds[i]->server,
+					  &credenc.ticket_info[i]->server)))
+            goto cleanup;
+
+      	if ((retval = krb5_copy_addresses(context, ppcreds[i]->addresses,
+					  &credenc.ticket_info[i]->caddrs)))
+            goto cleanup;
+    }
+
+    /*
+     * NULL terminate the lists.
+     */
+    pcred->tickets[i] = NULL;
+
+    /* encrypt the credential encrypted part */
+    retval = encrypt_credencpart(context, &credenc, keyblock,
+				 &pcred->enc_part);
+
+cleanup:
+    krb5_free_cred_enc_part(context, &credenc);
+    return retval;
+}
+
+/*----------------------- krb5_mk_ncred -----------------------*/
+
+/*
+ * This functions takes as input an array of krb5_credentials, and
+ * outputs an encoded KRB_CRED message suitable for krb5_rd_cred
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds **ppcreds, krb5_data **ppdata, krb5_replay_data *outdata)
+{
+    krb5_address * premote_fulladdr = NULL;
+    krb5_address * plocal_fulladdr = NULL;
+    krb5_address remote_fulladdr;
+    krb5_address local_fulladdr;
+    krb5_error_code 	retval;
+    krb5_keyblock	 * keyblock;
+    krb5_replay_data    replaydata;
+    krb5_cred 		 * pcred;
+    krb5_int32		ncred;
+
+    local_fulladdr.contents = 0;
+    remote_fulladdr.contents = 0;
+    memset(&replaydata, 0, sizeof(krb5_replay_data));
+
+    if (ppcreds == NULL) {
+    	return KRB5KRB_AP_ERR_BADADDR;
+    }
+
+    /*
+     * Allocate memory for a NULL terminated list of tickets.
+     */
+    for (ncred = 0; ppcreds[ncred]; ncred++);
+
+    if ((pcred = (krb5_cred *)malloc(sizeof(krb5_cred))) == NULL) 
+        return ENOMEM;
+    memset(pcred, 0, sizeof(krb5_cred));
+
+    if ((pcred->tickets 
+      = (krb5_ticket **)malloc(sizeof(krb5_ticket *) * (ncred + 1))) == NULL) {
+	retval = ENOMEM;
+	free(pcred);
+    }
+    memset(pcred->tickets, 0, sizeof(krb5_ticket *) * (ncred +1));
+
+    /* Get keyblock */
+    if ((keyblock = auth_context->send_subkey) == NULL) 
+	keyblock = auth_context->keyblock;
+
+    /* Get replay info */
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
+      (auth_context->rcache == NULL))
+        return KRB5_RC_REQUIRED;
+
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+      (outdata == NULL))
+        /* Need a better error */
+        return KRB5_RC_REQUIRED;
+
+    if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
+				    &replaydata.usec)))
+	return retval;
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
+	outdata->timestamp = replaydata.timestamp;
+	outdata->usec = replaydata.usec;
+    }
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+        replaydata.seq = auth_context->local_seq_number;
+        if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+            auth_context->local_seq_number++;
+        } else {
+            outdata->seq = replaydata.seq;
+        }
+    }
+
+    if (auth_context->local_addr) {
+    	if (auth_context->local_port) {
+            if ((retval = krb5_make_fulladdr(context, auth_context->local_addr,
+					     auth_context->local_port, 
+					     &local_fulladdr)))
+		goto error;
+	    plocal_fulladdr = &local_fulladdr;
+	} else {
+            plocal_fulladdr = auth_context->local_addr;
+        }
+    }
+
+    if (auth_context->remote_addr) {
+    	if (auth_context->remote_port) {
+            if ((retval = krb5_make_fulladdr(context,auth_context->remote_addr,
+                                 	      auth_context->remote_port, 
+					      &remote_fulladdr)))
+		goto error;
+	    premote_fulladdr = &remote_fulladdr;
+	} else {
+            premote_fulladdr = auth_context->remote_addr;
+        }
+    }
+
+    /* Setup creds structure */
+    if ((retval = krb5_mk_ncred_basic(context, ppcreds, ncred, keyblock,
+				      &replaydata, plocal_fulladdr, 
+				      premote_fulladdr, pcred))) {
+	goto error;
+    }
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+        krb5_donot_replay replay;
+
+        if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
+					   "_forw", &replay.client)))
+            goto error;
+
+        replay.server = "";             /* XXX */
+        replay.cusec = replaydata.usec;
+        replay.ctime = replaydata.timestamp;
+        if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
+            /* should we really error out here? XXX */
+            krb5_xfree(replay.client);
+            goto error;
+        }
+        krb5_xfree(replay.client);
+    }
+
+    /* Encode creds structure */
+    retval = encode_krb5_cred(pcred, ppdata);
+
+error:
+    if (local_fulladdr.contents)
+	free(local_fulladdr.contents);
+    if (remote_fulladdr.contents)
+	free(remote_fulladdr.contents);
+    krb5_free_cred(context, pcred);
+
+    if (retval) {
+	if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) 
+	 || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+            auth_context->local_seq_number--;
+    }
+    return retval;
+}
+
+/*----------------------- krb5_mk_1cred -----------------------*/
+
+/*
+ * A convenience function that calls krb5_mk_ncred.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context, krb5_creds *pcreds, krb5_data **ppdata, krb5_replay_data *outdata)
+{
+    krb5_error_code retval;
+    krb5_creds **ppcreds;
+
+    if ((ppcreds = (krb5_creds **)malloc(sizeof(*ppcreds) * 2)) == NULL) {
+	return ENOMEM;
+    }
+
+    ppcreds[0] = pcreds;
+    ppcreds[1] = NULL;
+
+    retval = krb5_mk_ncred(context, auth_context, ppcreds,
+			   ppdata, outdata);
+    
+    free(ppcreds);
+    return retval;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/mk_error.c b/krb5-1-6/src/lib/krb5/krb/mk_error.c
new file mode 100644
index 000000000..0444a5d17
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/mk_error.c
@@ -0,0 +1,51 @@
+/*
+ * lib/krb5/krb/mk_error.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_mk_error() routine.
+ */
+
+#include "k5-int.h"
+
+/*
+ formats the error structure *dec_err into an error buffer *enc_err.
+
+ The error buffer storage is allocated, and should be freed by the
+ caller when finished.
+
+ returns system errors
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_mk_error(krb5_context context, const krb5_error *dec_err, krb5_data *enc_err)
+{
+    krb5_error_code retval;
+    krb5_data *new_enc_err;
+
+    if ((retval = encode_krb5_error(dec_err, &new_enc_err)))
+	return(retval);
+    *enc_err = *new_enc_err;
+    krb5_xfree(new_enc_err);
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/mk_priv.c b/krb5-1-6/src/lib/krb5/krb/mk_priv.c
new file mode 100644
index 000000000..efe254ac0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/mk_priv.c
@@ -0,0 +1,233 @@
+/*
+ * lib/krb5/krb/mk_priv.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_mk_priv()
+ */
+
+#include "k5-int.h"
+#include "cleanup.h"
+#include "auth_con.h"
+
+static krb5_error_code
+krb5_mk_priv_basic(krb5_context context, const krb5_data *userdata, const krb5_keyblock *keyblock, krb5_replay_data *replaydata, krb5_address *local_addr, krb5_address *remote_addr, krb5_pointer i_vector, krb5_data *outbuf)
+{
+    krb5_error_code 	retval;
+    krb5_priv 		privmsg;
+    krb5_priv_enc_part 	privmsg_enc_part;
+    krb5_data 		*scratch1, *scratch2, ivdata;
+    size_t		blocksize, enclen;
+
+    privmsg.enc_part.kvno = 0;	/* XXX allow user-set? */
+    privmsg.enc_part.enctype = keyblock->enctype; 
+
+    privmsg_enc_part.user_data = *userdata;
+    privmsg_enc_part.s_address = local_addr;
+    privmsg_enc_part.r_address = remote_addr;
+
+    /* We should check too make sure one exists. */
+    privmsg_enc_part.timestamp  = replaydata->timestamp;
+    privmsg_enc_part.usec 	= replaydata->usec;
+    privmsg_enc_part.seq_number = replaydata->seq;
+
+    /* start by encoding to-be-encrypted part of the message */
+    if ((retval = encode_krb5_enc_priv_part(&privmsg_enc_part, &scratch1)))
+	return retval;
+
+    /* put together an eblock for this encryption */
+    if ((retval = krb5_c_encrypt_length(context, keyblock->enctype,
+					scratch1->length, &enclen)))
+	goto clean_scratch;
+
+    privmsg.enc_part.ciphertext.length = enclen;
+    if (!(privmsg.enc_part.ciphertext.data =
+	  malloc(privmsg.enc_part.ciphertext.length))) {
+        retval = ENOMEM;
+        goto clean_scratch;
+    }
+
+    /* call the encryption routine */
+    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;
+
+    if ((retval = encode_krb5_priv(&privmsg, &scratch2)))
+        goto clean_encpart;
+
+    *outbuf = *scratch2;
+    krb5_xfree(scratch2);
+    retval = 0;
+
+clean_encpart:
+    memset(privmsg.enc_part.ciphertext.data, 0, 
+	   privmsg.enc_part.ciphertext.length); 
+    free(privmsg.enc_part.ciphertext.data); 
+    privmsg.enc_part.ciphertext.length = 0;
+    privmsg.enc_part.ciphertext.data = 0;
+
+clean_scratch:
+    memset(scratch1->data, 0, scratch1->length);
+    krb5_free_data(context, scratch1); 
+
+    return retval;
+}
+
+
+krb5_error_code KRB5_CALLCONV
+krb5_mk_priv(krb5_context context, krb5_auth_context auth_context,
+	     const krb5_data *userdata, krb5_data *outbuf,
+	     krb5_replay_data *outdata)
+{
+    krb5_error_code 	  retval;
+    krb5_keyblock       * keyblock;
+    krb5_replay_data      replaydata;
+
+    /* Clear replaydata block */
+    memset((char *) &replaydata, 0, sizeof(krb5_replay_data));
+
+    /* Get keyblock */
+    if ((keyblock = auth_context->send_subkey) == NULL)
+	keyblock = auth_context->keyblock;
+
+    /* Get replay info */
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
+      (auth_context->rcache == NULL))
+	return KRB5_RC_REQUIRED;
+
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+      (outdata == NULL))
+	/* Need a better error */
+	return KRB5_RC_REQUIRED;
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
+	(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
+	if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
+					&replaydata.usec)))
+	    return retval;
+	if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
+    	    outdata->timestamp = replaydata.timestamp;
+    	    outdata->usec = replaydata.usec;
+	}
+    }
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+	(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+	replaydata.seq = auth_context->local_seq_number;
+	if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+	    auth_context->local_seq_number++;
+	} else {
+    	    outdata->seq = replaydata.seq;
+	}
+    } 
+
+{
+    krb5_address * premote_fulladdr = NULL;
+    krb5_address * plocal_fulladdr = NULL;
+    krb5_address remote_fulladdr;
+    krb5_address local_fulladdr;
+    CLEANUP_INIT(2);
+
+    if (auth_context->local_addr) {
+	if (auth_context->local_port) {
+	    if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
+				  	      auth_context->local_port, 
+					      &local_fulladdr))) {
+	    	CLEANUP_PUSH(local_fulladdr.contents, free);
+	    	plocal_fulladdr = &local_fulladdr;
+            } else {
+    	    	goto error;
+            }
+	} else {
+	    plocal_fulladdr = auth_context->local_addr;
+	}
+    }
+
+    if (auth_context->remote_addr) {
+    	if (auth_context->remote_port) {
+	    if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
+				 	      auth_context->remote_port, 
+					      &remote_fulladdr))){
+	    	CLEANUP_PUSH(remote_fulladdr.contents, free);
+	    	premote_fulladdr = &remote_fulladdr;
+ 	    } else {
+	        CLEANUP_DONE();
+	        goto error;
+	    }
+	} else {
+	    premote_fulladdr = auth_context->remote_addr;
+	}
+    }
+
+    if ((retval = krb5_mk_priv_basic(context, userdata, keyblock, &replaydata, 
+				     plocal_fulladdr, premote_fulladdr,
+				     auth_context->i_vector, outbuf))) {
+	CLEANUP_DONE();
+	goto error;
+    }
+
+    CLEANUP_DONE();
+}
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+	krb5_donot_replay replay;
+
+	if ((retval = krb5_gen_replay_name(context, auth_context->local_addr, 
+					   "_priv", &replay.client))) {
+    	    krb5_xfree(outbuf);
+	    goto error;
+	}
+
+	replay.server = "";		/* XXX */
+	replay.cusec = replaydata.usec;
+	replay.ctime = replaydata.timestamp;
+	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
+	    /* should we really error out here? XXX */
+    	    krb5_xfree(replay.client);
+	    goto error;
+	}
+	krb5_xfree(replay.client);
+    }
+
+    return 0;
+
+error:
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+	auth_context->local_seq_number--;
+
+    return retval;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/mk_rep.c b/krb5-1-6/src/lib/krb5/krb/mk_rep.c
new file mode 100644
index 000000000..393f634bb
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/mk_rep.c
@@ -0,0 +1,96 @@
+/*
+ * lib/krb5/krb/mk_rep.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_mk_rep()
+ */
+
+#include "k5-int.h"
+#include "auth_con.h"
+
+/*
+ Formats a KRB_AP_REP message into outbuf.
+
+ The outbuf buffer storage is allocated, and should be freed by the
+ caller when finished.
+
+ returns system errors
+*/
+
+krb5_error_code KRB5_CALLCONV
+krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf)
+{
+    krb5_error_code 	  retval;
+    krb5_ap_rep_enc_part  repl;
+    krb5_ap_rep 	  reply;
+    krb5_data 		* scratch;
+    krb5_data 		* toutbuf;
+
+    /* Make the reply */
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+	(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+	(auth_context->local_seq_number == 0)) {
+	if ((retval = krb5_generate_seq_number(context, auth_context->keyblock,
+					       &auth_context->local_seq_number)))
+            return(retval);
+    }
+
+    repl.ctime = auth_context->authentp->ctime;    
+    repl.cusec = auth_context->authentp->cusec;    
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) {
+	retval = krb5int_generate_and_save_subkey (context, auth_context,
+						   auth_context->keyblock);
+	if (retval)
+	    return retval;
+	repl.subkey = auth_context->send_subkey;
+    } else
+	repl.subkey = auth_context->authentp->subkey;
+    repl.seq_number = auth_context->local_seq_number;
+
+    /* encode it before encrypting */
+    if ((retval = encode_krb5_ap_rep_enc_part(&repl, &scratch)))
+	return retval;
+
+    if ((retval = krb5_encrypt_helper(context, auth_context->keyblock,
+				      KRB5_KEYUSAGE_AP_REP_ENCPART,
+				      scratch, &reply.enc_part)))
+	goto cleanup_scratch;
+
+    if (!(retval = encode_krb5_ap_rep(&reply, &toutbuf))) {
+	*outbuf = *toutbuf;
+	krb5_xfree(toutbuf);
+    }
+
+    memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
+    free(reply.enc_part.ciphertext.data); 
+    reply.enc_part.ciphertext.length = 0; 
+    reply.enc_part.ciphertext.data = 0;
+
+cleanup_scratch:
+    memset(scratch->data, 0, scratch->length); 
+    krb5_free_data(context, scratch);
+
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/mk_req.c b/krb5-1-6/src/lib/krb5/krb/mk_req.c
new file mode 100644
index 000000000..2935e41b3
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/mk_req.c
@@ -0,0 +1,91 @@
+/*
+ * lib/krb5/krb/mk_req.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_mk_req() routine.
+ */
+
+#include "k5-int.h"
+#include "auth_con.h"
+
+/*
+ Formats a KRB_AP_REQ message into outbuf.
+
+ server specifies the principal of the server to receive the message; if
+ credentials are not present in the credentials cache for this server, the
+ TGS request with default parameters is used in an attempt to obtain
+ such credentials, and they are stored in ccache.
+
+ kdc_options specifies the options requested for the 
+ ap_req_options specifies the KRB_AP_REQ options desired.
+
+ checksum specifies the checksum to be used in the authenticator.
+
+ The outbuf buffer storage is allocated, and should be freed by the
+ caller when finished.
+
+ returns system errors
+*/
+
+krb5_error_code KRB5_CALLCONV
+krb5_mk_req(krb5_context context, krb5_auth_context *auth_context,
+	    krb5_flags ap_req_options, char *service, char *hostname,
+	    krb5_data *in_data, krb5_ccache ccache, krb5_data *outbuf)
+{
+    krb5_error_code 	  retval;
+    krb5_principal	  server;
+    krb5_creds 		* credsp;
+    krb5_creds 		  creds;
+
+    retval = krb5_sname_to_principal(context, hostname, service, 
+				     KRB5_NT_SRV_HST, &server);
+    if (retval)
+      return retval;
+
+    /* obtain ticket & session key */
+    memset((char *)&creds, 0, sizeof(creds));
+    if ((retval = krb5_copy_principal(context, server, &creds.server)))
+	goto cleanup_princ;
+
+    if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
+	goto cleanup_creds;
+
+    if ((retval = krb5_get_credentials(context, 0,
+				       ccache, &creds, &credsp)))
+	goto cleanup_creds;
+
+    retval = krb5_mk_req_extended(context, auth_context, ap_req_options, 
+				  in_data, credsp, outbuf);
+
+    krb5_free_creds(context, credsp);
+
+cleanup_creds:
+    krb5_free_cred_contents(context, &creds);
+
+cleanup_princ:
+    krb5_free_principal(context, server);
+
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/mk_req_ext.c b/krb5-1-6/src/lib/krb5/krb/mk_req_ext.c
new file mode 100644
index 000000000..e5cb43a52
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/mk_req_ext.c
@@ -0,0 +1,277 @@
+/*
+ * lib/krb5/krb/mk_req_ext.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_mk_req_extended()
+ */
+
+
+#include "k5-int.h"
+#include "auth_con.h"
+
+/*
+ Formats a KRB_AP_REQ message into outbuf, with more complete options than
+ krb_mk_req.
+
+ outbuf, ap_req_options, checksum, and ccache are used in the
+ same fashion as for krb5_mk_req.
+
+ creds is used to supply the credentials (ticket and session key) needed
+ to form the request.
+
+ if creds->ticket has no data (length == 0), then a ticket is obtained
+ from either the cache or the TGS, passing creds to krb5_get_credentials().
+ kdc_options specifies the options requested for the ticket to be used.
+ If a ticket with appropriate flags is not found in the cache, then these
+ options are passed on in a request to an appropriate KDC.
+
+ ap_req_options specifies the KRB_AP_REQ options desired.
+
+ if ap_req_options specifies AP_OPTS_USE_SESSION_KEY, then creds->ticket
+ must contain the appropriate ENC-TKT-IN-SKEY ticket.
+
+ checksum specifies the checksum to be used in the authenticator.
+
+ The outbuf buffer storage is allocated, and should be freed by the
+ caller when finished.
+
+ On an error return, the credentials pointed to by creds might have been
+ augmented with additional fields from the obtained credentials; the entire
+ credentials should be released by calling krb5_free_creds().
+
+ returns system errors
+*/
+
+static krb5_error_code 
+krb5_generate_authenticator (krb5_context,
+				       krb5_authenticator *, krb5_principal,
+				       krb5_checksum *, krb5_keyblock *,
+				       krb5_ui_4, krb5_authdata ** );
+
+krb5_error_code
+krb5int_generate_and_save_subkey (krb5_context context,
+				  krb5_auth_context auth_context,
+				  krb5_keyblock *keyblock)
+{
+    /* Provide some more fodder for random number code.
+       This isn't strong cryptographically; the point here is not
+       to guarantee randomness, but to make it less likely that multiple
+       sessions could pick the same subkey.  */
+    struct {
+	krb5_int32 sec, usec;
+    } rnd_data;
+    krb5_data d;
+    krb5_error_code retval;
+
+    krb5_crypto_us_timeofday (&rnd_data.sec, &rnd_data.usec);
+    d.length = sizeof (rnd_data);
+    d.data = (char *) &rnd_data;
+    (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_TIMING, &d);
+
+    if (auth_context->send_subkey)
+	krb5_free_keyblock(context, auth_context->send_subkey);
+    if ((retval = krb5_generate_subkey(context, keyblock, &auth_context->send_subkey)))
+	return retval;
+
+    if (auth_context->recv_subkey)
+	krb5_free_keyblock(context, auth_context->recv_subkey);
+    retval = krb5_copy_keyblock(context, auth_context->send_subkey,
+				&auth_context->recv_subkey);
+    if (retval) {
+	krb5_free_keyblock(context, auth_context->send_subkey);
+	auth_context->send_subkey = NULL;
+	return retval;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context,
+		     krb5_flags ap_req_options, krb5_data *in_data,
+		     krb5_creds *in_creds, krb5_data *outbuf)
+{
+    krb5_error_code 	  retval;
+    krb5_checksum	  checksum;
+    krb5_checksum	  *checksump = 0;
+    krb5_auth_context	  new_auth_context;
+
+    krb5_ap_req request;
+    krb5_data *scratch = 0;
+    krb5_data *toutbuf;
+
+    request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK;
+    request.authenticator.ciphertext.data = 0;
+    request.ticket = 0;
+    
+    if (!in_creds->ticket.length) 
+	return(KRB5_NO_TKT_SUPPLIED);
+
+    /* we need a native ticket */
+    if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket)))
+	return(retval);
+    
+    /* verify that the ticket is not expired */
+    if ((retval = krb5_validate_times(context, &in_creds->times)) != 0)
+	goto cleanup;
+
+    /* generate auth_context if needed */
+    if (*auth_context == NULL) {
+	if ((retval = krb5_auth_con_init(context, &new_auth_context)))
+	    goto cleanup;
+	*auth_context = new_auth_context;
+    }
+
+    if ((*auth_context)->keyblock != NULL) {
+	krb5_free_keyblock(context, (*auth_context)->keyblock);
+	(*auth_context)->keyblock = NULL;
+    }
+
+    /* set auth context keyblock */
+    if ((retval = krb5_copy_keyblock(context, &in_creds->keyblock, 
+				     &((*auth_context)->keyblock))))
+	goto cleanup;
+
+    /* generate seq number if needed */
+    if ((((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
+     || ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+      && ((*auth_context)->local_seq_number == 0)) 
+	if ((retval = krb5_generate_seq_number(context, &in_creds->keyblock,
+				     &(*auth_context)->local_seq_number)))
+	    goto cleanup;
+	
+
+    /* generate subkey if needed */
+    if (!in_data &&(*auth_context)->checksum_func) {
+	retval = (*auth_context)->checksum_func( context,
+						 *auth_context,
+						 (*auth_context)->checksum_func_data,
+						 &in_data);
+	if (retval)
+	    goto cleanup;
+    }
+
+    if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->send_subkey)) {
+	retval = krb5int_generate_and_save_subkey (context, *auth_context,
+						   &in_creds->keyblock);
+	if (retval)
+	    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 {
+	    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;
+    }
+
+    /* Generate authenticator */
+    if (((*auth_context)->authentp = (krb5_authenticator *)malloc(sizeof(
+					krb5_authenticator))) == NULL) {
+	retval = ENOMEM;
+	goto cleanup_cksum;
+    }
+
+    if ((retval = krb5_generate_authenticator(context,
+					      (*auth_context)->authentp,
+					      (in_creds)->client, checksump,
+					      (*auth_context)->send_subkey,
+					      (*auth_context)->local_seq_number,
+					      (in_creds)->authdata)))
+	goto cleanup_cksum;
+	
+    /* encode the authenticator */
+    if ((retval = encode_krb5_authenticator((*auth_context)->authentp,
+					    &scratch)))
+	goto cleanup_cksum;
+    
+    /* Null out these fields, to prevent pointer sharing problems;
+     * they were supplied by the caller
+     */
+    (*auth_context)->authentp->client = NULL;
+    (*auth_context)->authentp->checksum = NULL;
+    (*auth_context)->authentp->authorization_data = NULL;
+
+    /* call the encryption routine */
+    if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock,
+				      KRB5_KEYUSAGE_AP_REQ_AUTH,
+				      scratch, &request.authenticator)))
+	goto cleanup_cksum;
+
+    if ((retval = encode_krb5_ap_req(&request, &toutbuf)))
+	goto cleanup_cksum;
+    *outbuf = *toutbuf;
+
+    krb5_xfree(toutbuf);
+
+cleanup_cksum:
+    if (checksump && checksump->checksum_type != 0x8003)
+      free(checksump->contents);
+
+cleanup:
+    if (request.ticket)
+	krb5_free_ticket(context, request.ticket);
+    if (request.authenticator.ciphertext.data) {
+    	(void) memset(request.authenticator.ciphertext.data, 0,
+		      request.authenticator.ciphertext.length);
+	free(request.authenticator.ciphertext.data);
+    }
+    if (scratch) {
+	memset(scratch->data, 0, scratch->length);
+        krb5_xfree(scratch->data);
+	krb5_xfree(scratch);
+    }
+    return retval;
+}
+
+static krb5_error_code
+krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent, krb5_principal client, krb5_checksum *cksum, krb5_keyblock *key, krb5_ui_4 seq_number, krb5_authdata **authorization)
+{
+    krb5_error_code retval;
+    
+    authent->client = client;
+    authent->checksum = cksum;
+    if (key) {
+	retval = krb5_copy_keyblock(context, key, &authent->subkey);
+	if (retval)
+	    return retval;
+    } else
+	authent->subkey = 0;
+    authent->seq_number = seq_number;
+    authent->authorization_data = authorization;
+
+    return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec));
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/mk_safe.c b/krb5-1-6/src/lib/krb5/krb/mk_safe.c
new file mode 100644
index 000000000..eefcab7cd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/mk_safe.c
@@ -0,0 +1,259 @@
+/*
+ * lib/krb5/krb/mk_safe.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_mk_safe()
+ */
+
+#include "k5-int.h"
+#include "cleanup.h"
+#include "auth_con.h"
+
+/*
+ Formats a KRB_SAFE message into outbuf.
+
+ userdata is formatted as the user data in the message.
+ sumtype specifies the encryption type; key specifies the key which
+ might be used to seed the checksum; sender_addr and recv_addr specify
+ the full addresses (host and port) of the sender and receiver.
+ The host portion of sender_addr is used to form the addresses used in the
+ KRB_SAFE message.
+
+ The outbuf buffer storage is allocated, and should be freed by the
+ caller when finished.
+
+ returns system errors
+*/
+static krb5_error_code
+krb5_mk_safe_basic(krb5_context context, const krb5_data *userdata,
+		   const krb5_keyblock *keyblock, krb5_replay_data *replaydata,
+		   krb5_address *local_addr, krb5_address *remote_addr,
+		   krb5_cksumtype sumtype, krb5_data *outbuf)
+{
+    krb5_error_code retval;
+    krb5_safe safemsg;
+    krb5_octet zero_octet = 0;
+    krb5_checksum safe_checksum;
+    krb5_data *scratch1, *scratch2;
+
+    if (!krb5_c_valid_cksumtype(sumtype))
+	return KRB5_PROG_SUMTYPE_NOSUPP;
+    if (!krb5_c_is_coll_proof_cksum(sumtype)
+	|| !krb5_c_is_keyed_cksum(sumtype))
+	return KRB5KRB_AP_ERR_INAPP_CKSUM;
+
+    safemsg.user_data = *userdata;
+    safemsg.s_address = (krb5_address *) local_addr;
+    safemsg.r_address = (krb5_address *) remote_addr;
+
+    /* We should check too make sure one exists. */
+    safemsg.timestamp  = replaydata->timestamp;
+    safemsg.usec       = replaydata->usec;
+    safemsg.seq_number = replaydata->seq;
+
+    /* 
+     * To do the checksum stuff, we need to encode the message with a
+     * zero-length zero-type checksum, then checksum the encoding, then
+     * re-encode with the checksum. 
+     */
+
+    safe_checksum.length = 0;
+    safe_checksum.checksum_type = 0;
+    safe_checksum.contents = &zero_octet;
+
+    safemsg.checksum = &safe_checksum;
+
+    if ((retval = encode_krb5_safe(&safemsg, &scratch1)))
+	return retval;
+
+    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;
+    }
+    *outbuf = *scratch2;
+    krb5_xfree(scratch2);
+    retval = 0;
+
+cleanup_checksum:
+    krb5_xfree(safe_checksum.contents);
+
+    memset((char *)scratch1->data, 0, scratch1->length); 
+    krb5_free_data(context, scratch1);
+    return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, krb5_replay_data *outdata)
+{
+    krb5_error_code 	  retval;
+    krb5_keyblock       * keyblock;
+    krb5_replay_data      replaydata;
+
+    /* Clear replaydata block */
+    memset((char *) &replaydata, 0, sizeof(krb5_replay_data));
+
+    /* Get keyblock */
+    if ((keyblock = auth_context->send_subkey) == NULL)
+	keyblock = auth_context->keyblock;
+
+    /* Get replay info */
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
+      (auth_context->rcache == NULL))
+	return KRB5_RC_REQUIRED;
+
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+      (outdata == NULL))
+	/* Need a better error */
+	return KRB5_RC_REQUIRED;
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
+	(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
+	if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
+					&replaydata.usec)))
+	    return retval;
+	if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
+    	    outdata->timestamp = replaydata.timestamp;
+    	    outdata->usec = replaydata.usec;
+	}
+    }
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+	(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+	replaydata.seq = auth_context->local_seq_number++;
+	if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) {
+    	    outdata->seq = replaydata.seq;
+	}
+    } 
+
+{
+    krb5_address * premote_fulladdr = NULL;
+    krb5_address * plocal_fulladdr = NULL;
+    krb5_address remote_fulladdr;
+    krb5_address local_fulladdr;
+    krb5_cksumtype sumtype;
+
+    CLEANUP_INIT(2);
+
+    if (auth_context->local_addr) {
+    	if (auth_context->local_port) {
+            if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
+                                 	      auth_context->local_port, 
+					      &local_fulladdr))){
+            	CLEANUP_PUSH(local_fulladdr.contents, free);
+	    	plocal_fulladdr = &local_fulladdr;
+            } else {
+                goto error;
+            }
+	} else {
+            plocal_fulladdr = auth_context->local_addr;
+        }
+
+    }
+
+    if (auth_context->remote_addr) {
+    	if (auth_context->remote_port) {
+            if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
+                                 	      auth_context->remote_port, 
+					      &remote_fulladdr))){
+            	CLEANUP_PUSH(remote_fulladdr.contents, free);
+	    	premote_fulladdr = &remote_fulladdr;
+            } else {
+                CLEANUP_DONE();
+                goto error;
+            }
+	} else {
+            premote_fulladdr = auth_context->remote_addr;
+        }
+    }
+
+    {
+	unsigned int nsumtypes;
+	unsigned int i;
+	krb5_cksumtype *sumtypes;
+	retval = krb5_c_keyed_checksum_types (context, keyblock->enctype,
+					      &nsumtypes, &sumtypes);
+	if (retval) {
+	    CLEANUP_DONE ();
+	    goto error;
+	}
+	if (nsumtypes == 0) {
+		retval = KRB5_BAD_ENCTYPE;
+		krb5_free_cksumtypes (context, sumtypes);
+		CLEANUP_DONE ();
+		goto error;
+	}
+	for (i = 0; i < nsumtypes; i++)
+		if (auth_context->safe_cksumtype == sumtypes[i])
+			break;
+	if (i == nsumtypes)
+		i = 0;
+	sumtype = sumtypes[i];
+	krb5_free_cksumtypes (context, sumtypes);
+    }
+    if ((retval = krb5_mk_safe_basic(context, userdata, keyblock, &replaydata, 
+				     plocal_fulladdr, premote_fulladdr,
+				     sumtype, outbuf))) {
+	CLEANUP_DONE();
+	goto error;
+    }
+
+    CLEANUP_DONE();
+}
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+	krb5_donot_replay replay;
+
+	if ((retval = krb5_gen_replay_name(context, auth_context->local_addr, 
+					   "_safe", &replay.client))) {
+    	    krb5_xfree(outbuf);
+	    goto error;
+	}
+
+	replay.server = "";		/* XXX */
+	replay.cusec = replaydata.usec;
+	replay.ctime = replaydata.timestamp;
+	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
+	    /* should we really error out here? XXX */
+    	    krb5_xfree(outbuf);
+	    goto error;
+	}
+	krb5_xfree(replay.client);
+    }
+
+    return 0;
+
+error:
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) 
+	auth_context->local_seq_number--;
+
+    return retval;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/parse.c b/krb5-1-6/src/lib/krb5/krb/parse.c
new file mode 100644
index 000000000..fbcc49db0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/parse.c
@@ -0,0 +1,285 @@
+/*
+ * lib/krb5/krb/parse.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_parse_name() routine.
+ *
+ * Rewritten by Theodore Ts'o to properly handle arbitrary quoted
+ * characters in the principal name.
+ */
+
+
+#include "k5-int.h"
+
+/*
+ * converts a single-string representation of the name to the
+ * multi-part principal format used in the protocols.
+ *
+ * principal will point to allocated storage which should be freed by 
+ * the caller (using krb5_free_principal) after use.
+ * 
+ * Conventions:  / is used to separate components.  If @ is present in the
+ * string, then the rest of the string after it represents the realm name.
+ * Otherwise the local realm name is used.
+ * 
+ * error return:
+ *	KRB5_PARSE_MALFORMED	badly formatted string
+ *
+ * also returns system errors:
+ *	ENOMEM	malloc failed/out of memory
+ *
+ * get_default_realm() is called; it may return other errors.
+ */
+
+#define REALM_SEP	'@'
+#define	COMPONENT_SEP	'/'
+#define QUOTECHAR	'\\'
+
+#define FCOMPNUM	10
+
+
+/*
+ * May the fleas of a thousand camels infest the ISO, they who think
+ * that arbitrarily large multi-component names are a Good Thing.....
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincipal)
+{
+	register const char	*cp;
+	register char	*q;
+	register int    i,c,size;
+	int		components = 0;
+	const char	*parsed_realm = NULL;
+	int		fcompsize[FCOMPNUM];
+	unsigned int	realmsize = 0;
+	char		*default_realm = NULL;
+	int		default_realm_size = 0;
+	char		*tmpdata;
+	krb5_principal	principal;
+	krb5_error_code retval;
+	
+	/*
+	 * Pass 1.  Find out how many components there are to the name,
+	 * and get string sizes for the first FCOMPNUM components.
+	 */
+	size = 0;
+	for (i=0,cp = name; (c = *cp); cp++) {
+		if (c == QUOTECHAR) {
+			cp++;
+			if (!(c = *cp))
+				/*
+				 * QUOTECHAR can't be at the last
+				 * character of the name!
+				 */
+				return(KRB5_PARSE_MALFORMED);
+			size++;
+			continue;
+		} else if (c == COMPONENT_SEP) {
+			if (parsed_realm)
+				/*
+				 * Shouldn't see a component separator
+				 * after we've parsed out the realm name!
+				 */
+				return(KRB5_PARSE_MALFORMED);
+			if (i < FCOMPNUM) {
+				fcompsize[i] = size;
+			}
+			size = 0;
+			i++;
+		} else if (c == REALM_SEP) {
+			if (parsed_realm)
+				/*
+				 * Multiple realm separaters
+				 * not allowed; zero-length realms are.
+				 */
+				return(KRB5_PARSE_MALFORMED);
+			parsed_realm = cp+1;
+			if (i < FCOMPNUM) {
+				fcompsize[i] = size;
+			}
+			size = 0;
+		} else
+			size++;
+	}
+	if (parsed_realm)
+		realmsize = size;
+	else if (i < FCOMPNUM) 
+		fcompsize[i] = size;
+	components = i + 1;
+	/*
+	 * Now, we allocate the principal structure and all of its
+	 * component pieces
+	 */
+	principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
+	if (!principal) {
+		return(ENOMEM);
+	}
+	principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components);
+	if (!principal->data) {
+	    free((char *)principal);
+	    return ENOMEM;
+	}
+	principal->length = components;
+	/*
+	 * If a realm was not found, then use the defualt realm....
+	 */
+	if (!parsed_realm) {
+	    if (!default_realm) {
+		retval = krb5_get_default_realm(context, &default_realm);
+		if (retval) {
+		    krb5_xfree(principal->data);
+		    krb5_xfree((char *)principal);
+		    return(retval);
+		}
+		default_realm_size = strlen(default_realm);
+	    }
+	    realmsize = default_realm_size;
+	}
+	/*
+	 * Pass 2.  Happens only if there were more than FCOMPNUM
+	 * component; if this happens, someone should be shot
+	 * immediately.  Nevertheless, we will attempt to handle said
+	 * case..... <martyred sigh>
+	 */
+	if (components >= FCOMPNUM) {
+		size = 0;
+		parsed_realm = NULL;
+		for (i=0,cp = name; (c = *cp); cp++) {
+			if (c == QUOTECHAR) {
+				cp++;
+				size++;
+			} else if (c == COMPONENT_SEP) {
+				if (krb5_princ_size(context, principal) > i)
+					krb5_princ_component(context, principal, i)->length = size;
+				size = 0;
+				i++;
+			} else if (c == REALM_SEP) {
+				if (krb5_princ_size(context, principal) > i)
+					krb5_princ_component(context, principal, i)->length = size;
+				size = 0;
+				parsed_realm = cp+1;
+			} else
+				size++;
+		}
+		if (parsed_realm)
+			krb5_princ_realm(context, principal)->length = size;
+		else
+			if (krb5_princ_size(context, principal) > i)
+				krb5_princ_component(context, principal, i)->length = size;
+		if (i + 1 != components) {
+#if !defined(_WIN32)
+		    fprintf(stderr,
+			    "Programming error in krb5_parse_name!");
+#endif
+		    assert(i + 1 == components);
+		    abort();
+		}
+	} else {
+		/*
+		 * If there were fewer than FCOMPSIZE components (the
+		 * usual case), then just copy the sizes to the
+		 * principal structure
+		 */
+		for (i=0; i < components; i++)
+			krb5_princ_component(context, principal, i)->length = fcompsize[i];
+	}
+	/*	
+	 * Now, we need to allocate the space for the strings themselves.....
+	 */
+	tmpdata = malloc(realmsize+1);
+	if (tmpdata == 0) {
+		krb5_xfree(principal->data);
+		krb5_xfree(principal);
+		krb5_xfree(default_realm);
+		return ENOMEM;
+	}
+	krb5_princ_set_realm_length(context, principal, realmsize);
+	krb5_princ_set_realm_data(context, principal, tmpdata);
+	for (i=0; i < components; i++) {
+		char *tmpdata2 =
+		  malloc(krb5_princ_component(context, principal, i)->length + 1);
+		if (!tmpdata2) {
+			for (i--; i >= 0; i--)
+				krb5_xfree(krb5_princ_component(context, principal, i)->data);
+			krb5_xfree(krb5_princ_realm(context, principal)->data);
+			krb5_xfree(principal->data);
+			krb5_xfree(principal);
+			krb5_xfree(default_realm);
+			return(ENOMEM);
+		}
+		krb5_princ_component(context, principal, i)->data = tmpdata2;
+		krb5_princ_component(context, principal, i)->magic = KV5M_DATA;
+	}
+	
+	/*
+	 * Pass 3.  Now we go through the string a *third* time, this
+	 * time filling in the krb5_principal structure which we just
+	 * allocated.
+	 */
+	q = krb5_princ_component(context, principal, 0)->data;
+	for (i=0,cp = name; (c = *cp); cp++) {
+		if (c == QUOTECHAR) {
+			cp++;
+			switch (c = *cp) {
+			case 'n':
+				*q++ = '\n';
+				break;
+			case 't':
+				*q++ = '\t';
+				break;
+			case 'b':
+				*q++ = '\b';
+				break;
+			case '0':
+				*q++ = '\0';
+				break;
+			default:
+				*q++ = c;
+			}
+		} else if ((c == COMPONENT_SEP) || (c == REALM_SEP)) {
+			i++;
+			*q++ = '\0';
+			if (c == COMPONENT_SEP) 
+				q = krb5_princ_component(context, principal, i)->data;
+			else
+				q = krb5_princ_realm(context, principal)->data;
+		} else
+			*q++ = c;
+	}
+	*q++ = '\0';
+	if (!parsed_realm)
+		strcpy(krb5_princ_realm(context, principal)->data, default_realm);
+	/*
+	 * Alright, we're done.  Now stuff a pointer to this monstrosity
+	 * into the return variable, and let's get out of here.
+	 */
+	krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL;
+	principal->magic = KV5M_PRINCIPAL;
+	principal->realm.magic = KV5M_DATA;
+	*nprincipal = principal;
+
+	krb5_xfree(default_realm);
+	return(0);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/pr_to_salt.c b/krb5-1-6/src/lib/krb5/krb/pr_to_salt.c
new file mode 100644
index 000000000..545d86fb1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/pr_to_salt.c
@@ -0,0 +1,86 @@
+/*
+ * lib/krb5/krb/pr_to_salt.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_principal2salt()
+ */
+
+#include "k5-int.h"
+
+static krb5_error_code krb5_principal2salt_internal
+    (krb5_context, krb5_const_principal, krb5_data *ret, int);
+
+/*
+ * Convert a krb5_principal into the default salt for that principal.
+ */
+static krb5_error_code
+krb5_principal2salt_internal(krb5_context context, register krb5_const_principal pr, krb5_data *ret, int use_realm)
+{
+    unsigned int size = 0, offset=0;
+    krb5_int32 nelem;
+    register int i;
+
+    if (pr == 0) {
+	ret->length = 0;
+	ret->data = 0;
+	return 0;
+    }
+
+    nelem = krb5_princ_size(context, pr);
+
+    if (use_realm)
+	    size += krb5_princ_realm(context, pr)->length;
+
+    for (i = 0; i < (int) nelem; i++)
+	size += krb5_princ_component(context, pr, i)->length;
+
+    ret->length = size;
+    if (!(ret->data = malloc (size)))
+	return ENOMEM;
+
+    if (use_realm) {
+	    offset = krb5_princ_realm(context, pr)->length;
+	    memcpy(ret->data, krb5_princ_realm(context, pr)->data, offset);
+    }
+
+    for (i = 0; i < (int) nelem; i++) {
+	memcpy(&ret->data[offset], krb5_princ_component(context, pr, i)->data,
+	       krb5_princ_component(context, pr, i)->length);
+	offset += krb5_princ_component(context, pr, i)->length;
+    }
+    return 0;
+}
+
+krb5_error_code
+krb5_principal2salt(krb5_context context, register krb5_const_principal pr, krb5_data *ret)
+{
+	return krb5_principal2salt_internal(context, pr, ret, 1);
+}
+
+krb5_error_code
+krb5_principal2salt_norealm(krb5_context context, register krb5_const_principal pr, krb5_data *ret)
+{
+	return krb5_principal2salt_internal(context, pr, ret, 0);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/preauth.c b/krb5-1-6/src/lib/krb5/krb/preauth.c
new file mode 100644
index 000000000..0e7c279e1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/preauth.c
@@ -0,0 +1,581 @@
+/*
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * This file contains routines for establishing, verifying, and any other
+ * necessary functions, for utilizing the pre-authentication field of the 
+ * kerberos kdc request, with various hardware/software verification devices.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include <time.h>
+
+static krb5_error_code obtain_enc_ts_padata
+	(krb5_context,
+	 krb5_pa_data *,
+	 krb5_etype_info,
+	 krb5_keyblock *,
+	 krb5_error_code ( * )(krb5_context,
+			       const krb5_enctype,
+			       krb5_data *,
+			       krb5_const_pointer,
+			       krb5_keyblock **),
+	 krb5_const_pointer,
+	 krb5_creds *,
+	 krb5_kdc_req *,
+	 krb5_pa_data **);
+
+static krb5_error_code process_pw_salt
+	(krb5_context,
+	 krb5_pa_data *,
+	 krb5_kdc_req *,
+	 krb5_kdc_rep *,
+	 krb5_error_code ( * )(krb5_context,
+			       const krb5_enctype,
+			       krb5_data *,
+			       krb5_const_pointer,
+			       krb5_keyblock **),
+	 krb5_const_pointer,
+	 krb5_error_code ( * )(krb5_context,
+			       const krb5_keyblock *,
+			       krb5_const_pointer,
+			       krb5_kdc_rep * ),
+	 krb5_keyblock **,
+	 krb5_creds *,
+	 krb5_int32 *,
+	 krb5_int32 *);
+
+static krb5_error_code obtain_sam_padata
+	(krb5_context,
+	 krb5_pa_data *,
+	 krb5_etype_info,
+	 krb5_keyblock *, 
+	 krb5_error_code ( * )(krb5_context,
+			       const krb5_enctype,
+			       krb5_data *,
+			       krb5_const_pointer,
+			       krb5_keyblock **),
+	 krb5_const_pointer,
+	 krb5_creds *,
+	 krb5_kdc_req *,
+	 krb5_pa_data **);
+
+static const krb5_preauth_ops preauth_systems[] = {
+    {
+	KV5M_PREAUTH_OPS,
+	KRB5_PADATA_ENC_TIMESTAMP,
+        0,
+        obtain_enc_ts_padata,
+        0,
+    },
+    {
+	KV5M_PREAUTH_OPS,
+	KRB5_PADATA_PW_SALT,
+        0,
+        0,
+        process_pw_salt,
+    },
+    {
+	KV5M_PREAUTH_OPS,
+	KRB5_PADATA_AFS3_SALT,
+        0,
+        0,
+        process_pw_salt,
+    },
+    {
+	KV5M_PREAUTH_OPS,
+	KRB5_PADATA_SAM_CHALLENGE,
+        0,
+        obtain_sam_padata,
+        0,
+    },
+    { KV5M_PREAUTH_OPS, -1 }
+};
+
+static krb5_error_code find_pa_system
+    (krb5_preauthtype type, const krb5_preauth_ops **Preauth_proc);
+
+/* some typedef's for the function args to make things look a bit cleaner */
+
+typedef krb5_error_code (*git_key_proc) (krb5_context,
+					 const krb5_enctype,
+					 krb5_data *,
+					 krb5_const_pointer,
+					 krb5_keyblock **);
+
+typedef krb5_error_code (*git_decrypt_proc) (krb5_context,
+					     const krb5_keyblock *,
+					     krb5_const_pointer,
+					     krb5_kdc_rep *);
+
+krb5_error_code krb5_obtain_padata(krb5_context context, krb5_pa_data **preauth_to_use, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request)
+{
+    krb5_error_code		retval;
+    krb5_etype_info	    	etype_info = 0;
+    krb5_pa_data **		pa;
+    krb5_pa_data **		send_pa_list;
+    krb5_pa_data **		send_pa;
+    const krb5_preauth_ops	*ops;
+    krb5_keyblock *		def_enc_key = 0;
+    krb5_enctype 		enctype;
+    krb5_data 			salt;
+    krb5_data			scratch;
+    int				size;
+    int				f_salt = 0;
+
+    if (preauth_to_use == NULL)
+	return 0;
+
+    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);
+	    if (retval)
+		return retval;
+	    if (etype_info[0] == NULL) {
+		krb5_free_etype_info(context, etype_info);
+		etype_info = NULL;
+	    }
+	}
+    }
+
+    if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
+	return ENOMEM;
+
+    send_pa = send_pa_list;
+    *send_pa = 0;
+
+    enctype = request->ktype[0];
+    salt.data = 0;
+    salt.length = SALT_TYPE_NO_LENGTH;
+    if (etype_info) {
+	enctype = etype_info[0]->etype;
+	salt.data = (char *) etype_info[0]->salt;
+	if(etype_info[0]->length == KRB5_ETYPE_NO_SALT) 
+	  salt.length = SALT_TYPE_NO_LENGTH; /* XXX */
+	else 
+	  salt.length = etype_info[0]->length;
+    }
+    if (salt.length == SALT_TYPE_NO_LENGTH) {
+        /*
+	 * This will set the salt length 
+	 */
+	if ((retval = krb5_principal2salt(context, request->client, &salt)))
+	    return(retval);
+	f_salt = 1;
+    }
+    
+    if ((retval = (*key_proc)(context, enctype, &salt, key_seed,
+			      &def_enc_key)))
+	goto cleanup;
+    
+
+    for (pa = preauth_to_use; *pa; pa++) {
+	if (find_pa_system((*pa)->pa_type, &ops))
+	    continue;
+
+	if (ops->obtain == 0)
+	    continue;
+	
+	retval = ((ops)->obtain)(context, *pa, etype_info, def_enc_key,
+				 key_proc, key_seed, creds,
+				 request, send_pa);
+	if (retval)
+	    goto cleanup;
+
+	if (*send_pa)
+	    send_pa++;
+	*send_pa = 0;
+    }
+
+    retval = 0;
+
+    if (send_pa_list[0]) {
+	request->padata = send_pa_list;
+	send_pa_list = 0;
+    }
+
+cleanup:
+    if (etype_info)
+	krb5_free_etype_info(context, etype_info);
+    if (f_salt)
+	krb5_xfree(salt.data);
+    if (send_pa_list)
+	krb5_free_pa_data(context, send_pa_list);
+    if (def_enc_key)
+	krb5_free_keyblock(context, def_enc_key);
+    return retval;
+    
+}
+
+krb5_error_code
+krb5_process_padata(krb5_context context, krb5_kdc_req *request, krb5_kdc_rep *as_reply, git_key_proc key_proc, krb5_const_pointer keyseed, git_decrypt_proc decrypt_proc, krb5_keyblock **decrypt_key, krb5_creds *creds, krb5_int32 *do_more)
+{
+    krb5_error_code		retval = 0;
+    const krb5_preauth_ops * 	ops;
+    krb5_pa_data **		pa;
+    krb5_int32			done = 0;
+    
+    *do_more = 0;		/* By default, we don't need to repeat... */
+    if (as_reply->padata == 0)
+	return 0;
+
+    for (pa = as_reply->padata; *pa; pa++) {
+	if (find_pa_system((*pa)->pa_type, &ops))
+	    continue;
+
+	if (ops->process == 0)
+	    continue;
+	
+	retval = ((ops)->process)(context, *pa, request, as_reply,
+				  key_proc, keyseed, decrypt_proc,
+				  decrypt_key, creds, do_more, &done);
+	if (retval)
+	    goto cleanup;
+	if (done)
+	    break;
+    }
+
+cleanup:
+    return retval;
+}
+
+/*
+ * This routine is the "obtain" function for the ENC_TIMESTAMP
+ * preauthentication type.  It take the current time and encrypts it
+ * in the user's key.
+ */
+static krb5_error_code
+obtain_enc_ts_padata(krb5_context context, krb5_pa_data *in_padata, krb5_etype_info etype_info, krb5_keyblock *def_enc_key, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request, krb5_pa_data **out_padata)
+{
+    krb5_pa_enc_ts		pa_enc;
+    krb5_error_code		retval;
+    krb5_data *			scratch;
+    krb5_enc_data 		enc_data;
+    krb5_pa_data *		pa;
+
+    retval = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec);
+    if (retval)
+	return retval;
+
+    if ((retval = encode_krb5_pa_enc_ts(&pa_enc, &scratch)) != 0)
+	return retval;
+
+    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);
+    scratch = 0;
+    
+    if ((retval = encode_krb5_enc_data(&enc_data, &scratch)) != 0)
+	goto cleanup;
+
+    if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    pa->magic = KV5M_PA_DATA;
+    pa->pa_type = KRB5_PADATA_ENC_TIMESTAMP;
+    pa->length = scratch->length;
+    pa->contents = (krb5_octet *) scratch->data;
+
+    *out_padata = pa;
+
+    krb5_xfree(scratch);
+    scratch = 0;
+
+    retval = 0;
+    
+cleanup:
+    if (scratch)
+	krb5_free_data(context, scratch);
+    if (enc_data.ciphertext.data)
+	krb5_xfree(enc_data.ciphertext.data);
+    return retval;
+}
+
+static krb5_error_code
+process_pw_salt(krb5_context context, krb5_pa_data *padata, krb5_kdc_req *request, krb5_kdc_rep *as_reply, git_key_proc key_proc, krb5_const_pointer keyseed, git_decrypt_proc decrypt_proc, krb5_keyblock **decrypt_key, krb5_creds *creds, krb5_int32 *do_more, krb5_int32 *done)
+{
+    krb5_error_code	retval;
+    krb5_data		salt;
+    
+    if (*decrypt_key != 0)
+	return 0;
+
+    salt.data = (char *) padata->contents;
+    salt.length = 
+      (padata->pa_type == KRB5_PADATA_AFS3_SALT)?(SALT_TYPE_AFS_LENGTH):(padata->length);
+    
+    if ((retval = (*key_proc)(context, as_reply->enc_part.enctype,
+			      &salt, keyseed, decrypt_key))) {
+	*decrypt_key = 0;
+	return retval;
+    }
+
+    return 0;
+}
+    
+static krb5_error_code
+find_pa_system(krb5_preauthtype type, const krb5_preauth_ops **preauth)
+{
+    const krb5_preauth_ops *ap = preauth_systems;
+    
+    while ((ap->type != -1) && (ap->type != type))
+	ap++;
+    if (ap->type == -1)
+	return(KRB5_PREAUTH_BAD_TYPE);
+    *preauth = ap;
+    return 0;
+} 
+
+
+extern const char *krb5_default_pwd_prompt1;
+
+static krb5_error_code
+sam_get_pass_from_user(krb5_context context, krb5_etype_info etype_info, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_kdc_req *request, krb5_keyblock **new_enc_key, const char *prompt)
+{
+    krb5_enctype 		enctype;
+    krb5_error_code		retval;
+    const char *oldprompt;
+
+    /* enctype = request->ktype[0]; */
+    enctype = ENCTYPE_DES_CBC_MD5;
+/* hack with this first! */
+    oldprompt = krb5_default_pwd_prompt1;
+    krb5_default_pwd_prompt1 = prompt;
+    {
+      krb5_data newpw;
+      newpw.data = 0; newpw.length = 0;
+      /* we don't keep the new password, just the key... */
+      retval = (*key_proc)(context, enctype, 0, 
+			   (krb5_const_pointer)&newpw, new_enc_key);
+      krb5_xfree(newpw.data);
+    }
+    krb5_default_pwd_prompt1 = oldprompt;
+    return retval;
+}
+static 
+char *handle_sam_labels(krb5_sam_challenge *sc)
+{
+    char *label = sc->sam_challenge_label.data;
+    unsigned int label_len = sc->sam_challenge_label.length;
+    char *prompt = sc->sam_response_prompt.data;
+    unsigned int prompt_len = sc->sam_response_prompt.length;
+    char *challenge = sc->sam_challenge.data;
+    unsigned int challenge_len = sc->sam_challenge.length;
+    char *prompt1, *p;
+    char *sep1 = ": [";
+    char *sep2 = "]\n";
+    char *sep3 = ": ";
+
+    if (sc->sam_cksum.length == 0) {
+      /* or invalid -- but lets just handle presence now XXX */
+      switch (sc->sam_type) {
+      case PA_SAM_TYPE_ENIGMA:	/* Enigma Logic */
+	label = "Challenge for Enigma Logic mechanism";
+	break;
+      case PA_SAM_TYPE_DIGI_PATH: /*  Digital Pathways */
+      case PA_SAM_TYPE_DIGI_PATH_HEX: /*  Digital Pathways */
+	label = "Challenge for Digital Pathways mechanism";
+	break;
+      case PA_SAM_TYPE_ACTIVCARD_DEC: /*  Digital Pathways */
+      case PA_SAM_TYPE_ACTIVCARD_HEX: /*  Digital Pathways */
+	label = "Challenge for Activcard mechanism";
+	break;
+      case PA_SAM_TYPE_SKEY_K0:	/*  S/key where  KDC has key 0 */
+	label = "Challenge for Enhanced S/Key mechanism";
+	break;
+      case PA_SAM_TYPE_SKEY:	/*  Traditional S/Key */
+	label = "Challenge for Traditional S/Key mechanism";
+	break;
+      case PA_SAM_TYPE_SECURID:	/*  Security Dynamics */
+	label = "Challenge for Security Dynamics mechanism";
+	break;
+      case PA_SAM_TYPE_SECURID_PREDICT:	/* predictive Security Dynamics */
+	label = "Challenge for Security Dynamics mechanism";
+	break;
+      }
+      prompt = "Passcode";
+      label_len = strlen(label);
+      prompt_len = strlen(prompt);
+    }
+
+    /* example:
+       Challenge for Digital Pathways mechanism: [134591]
+       Passcode: 
+     */
+    p = prompt1 = malloc(label_len + strlen(sep1) +
+			 challenge_len + strlen(sep2) +
+			 prompt_len+ strlen(sep3) + 1);
+    if (p == NULL)
+	return NULL;
+    if (challenge_len) {
+	strncpy(p, label, label_len); p += label_len;
+	strcpy(p, sep1); p += strlen(sep1);
+	strncpy(p, challenge, challenge_len); p += challenge_len;
+	strcpy(p, sep2); p += strlen(sep2);
+    }
+    strncpy(p, prompt, prompt_len); p += prompt_len;
+    strcpy(p, sep3); /* p += strlen(sep3); */
+    return prompt1;
+}
+
+/*
+ * This routine is the "obtain" function for the SAM_CHALLENGE
+ * preauthentication type.  It presents the challenge...
+ */
+static krb5_error_code
+obtain_sam_padata(krb5_context context, krb5_pa_data *in_padata, krb5_etype_info etype_info, krb5_keyblock *def_enc_key, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request, krb5_pa_data **out_padata)
+{
+    krb5_error_code		retval;
+    krb5_data *			scratch;
+    krb5_data			tmpsam;
+    krb5_pa_data *		pa;
+    krb5_sam_challenge		*sam_challenge = 0;
+    krb5_sam_response		sam_response;
+    /* these two get encrypted and stuffed in to sam_response */
+    krb5_enc_sam_response_enc	enc_sam_response_enc;
+    krb5_keyblock *		sam_use_key = 0;
+    char * prompt;
+
+    tmpsam.length = in_padata->length;
+    tmpsam.data = (char *) in_padata->contents;
+    retval = decode_krb5_sam_challenge(&tmpsam, &sam_challenge);
+    if (retval)
+      return retval;
+
+    if (sam_challenge->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) {
+      return KRB5_SAM_UNSUPPORTED;
+    }
+
+    enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce;
+    if (!sam_challenge->sam_nonce) {
+      retval = krb5_us_timeofday(context,
+                                 &enc_sam_response_enc.sam_timestamp,
+                                 &enc_sam_response_enc.sam_usec);
+      sam_response.sam_patimestamp = enc_sam_response_enc.sam_timestamp;
+    }
+    if (retval)
+      return retval;
+    if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
+      /* encrypt passcode in key by stuffing it here */
+      unsigned int pcsize = 256;
+      char *passcode = malloc(pcsize+1);
+      if (passcode == NULL)
+	return ENOMEM;
+      prompt = handle_sam_labels(sam_challenge);
+      if (prompt == NULL) {
+	free(passcode);
+	return ENOMEM;
+      }
+      retval = krb5_read_password(context, prompt, 0, passcode, &pcsize);
+      free(prompt);
+
+      if (retval) {
+	free(passcode);
+	return retval;
+      }
+      enc_sam_response_enc.sam_sad.data = passcode;
+      enc_sam_response_enc.sam_sad.length = pcsize;
+    } else if (sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) {
+      prompt = handle_sam_labels(sam_challenge);
+      if (prompt == NULL)
+	return ENOMEM;
+      retval = sam_get_pass_from_user(context, etype_info, key_proc, 
+				      key_seed, request, &sam_use_key,
+				      prompt);
+      free(prompt);
+      if (retval)
+	return retval;      
+      enc_sam_response_enc.sam_sad.length = 0;
+    } else {
+      /* what *was* it? */
+      return KRB5_SAM_UNSUPPORTED;
+    }
+
+    /* so at this point, either sam_use_key is generated from the passcode
+     * or enc_sam_response_enc.sam_sad is set to it, and we use 
+     * def_enc_key instead. */
+    /* encode the encoded part of the response */
+    if ((retval = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc,
+						   &scratch)) != 0)
+      return retval;
+
+    if ((retval = krb5_encrypt_data(context, 
+				    sam_use_key?sam_use_key:def_enc_key, 
+				    0, scratch,
+				    &sam_response.sam_enc_nonce_or_ts)))
+      goto cleanup;
+
+    krb5_free_data(context, scratch);
+    scratch = 0;
+
+    /* sam_enc_key is reserved for future use */
+    sam_response.sam_enc_key.ciphertext.length = 0;
+
+    /* copy things from the challenge */
+    sam_response.sam_nonce = sam_challenge->sam_nonce;
+    sam_response.sam_flags = sam_challenge->sam_flags;
+    sam_response.sam_track_id = sam_challenge->sam_track_id;
+    sam_response.sam_type = sam_challenge->sam_type;
+    sam_response.magic = KV5M_SAM_RESPONSE;
+
+    if ((retval = encode_krb5_sam_response(&sam_response, &scratch)) != 0)
+	return retval;
+    
+    if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    pa->magic = KV5M_PA_DATA;
+    pa->pa_type = KRB5_PADATA_SAM_RESPONSE;
+    pa->length = scratch->length;
+    pa->contents = (krb5_octet *) scratch->data;
+    scratch = 0;		/* so we don't free it! */
+
+    *out_padata = pa;
+
+    retval = 0;
+    
+cleanup:
+    if (scratch)
+	krb5_free_data(context, scratch);
+    if (sam_challenge)
+        krb5_xfree(sam_challenge);
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/preauth2.c b/krb5-1-6/src/lib/krb5/krb/preauth2.c
new file mode 100644
index 000000000..9fe984355
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/preauth2.c
@@ -0,0 +1,1656 @@
+/*
+ * Copyright 1995, 2003 by the Massachusetts Institute of Technology.  All
+ * Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * This file contains routines for establishing, verifying, and any other
+ * necessary functions, for utilizing the pre-authentication field of the 
+ * kerberos kdc request, with various hardware/software verification devices.
+ */
+
+#include "k5-int.h"
+#include "osconf.h"
+#include <krb5/preauth_plugin.h>
+#include "int-proto.h"
+
+#if !defined(_WIN32)
+#include <unistd.h>
+#endif
+
+#if TARGET_OS_MAC
+static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/preauth", NULL }; /* should be a list */
+#else
+static const char *objdirs[] = { LIBDIR "/krb5/plugins/preauth", NULL };
+#endif
+
+typedef krb5_error_code (*pa_function)(krb5_context,
+				       krb5_kdc_req *request,
+				       krb5_pa_data *in_padata,
+				       krb5_pa_data **out_padata,
+				       krb5_data *salt, krb5_data *s2kparams,
+				       krb5_enctype *etype,
+				       krb5_keyblock *as_key,
+				       krb5_prompter_fct prompter_fct,
+				       void *prompter_data,
+				       krb5_gic_get_as_key_fct gak_fct,
+				       void *gak_data);
+				 
+typedef struct _pa_types_t {
+    krb5_preauthtype type;
+    pa_function fct;
+    int flags;
+} pa_types_t;
+
+/* Create the per-krb5_context context. This means loading the modules
+ * if we haven't done that yet (applications which never obtain initial
+ * credentials should never hit this routine), breaking up the module's
+ * list of support pa_types so that we can iterate over the modules more
+ * easily, and copying over the relevant parts of the module's table. */
+void KRB5_CALLCONV
+krb5_init_preauth_context(krb5_context kcontext)
+{
+    int n_modules, n_tables, i, j, k;
+    void **tables;
+    struct krb5plugin_preauth_client_ftable_v1 *table;
+    krb5_preauth_context *context = NULL;
+    void *plugin_context;
+    krb5_preauthtype pa_type;
+    void **rcpp;
+
+    /* Only do this once for each krb5_context */
+    if (kcontext->preauth_context != NULL)
+	return;
+
+    /* load the plugins for the current context */
+    if (PLUGIN_DIR_OPEN(&kcontext->preauth_plugins) == 0) {
+	if (krb5int_open_plugin_dirs(objdirs, NULL,
+				     &kcontext->preauth_plugins,
+				     &kcontext->err) != 0) {
+		return;
+	}
+    }
+
+    /* pull out the module function tables for all of the modules */
+    tables = NULL;
+    if (krb5int_get_plugin_dir_data(&kcontext->preauth_plugins,
+				    "preauthentication_client_1",
+				    &tables,
+				    &kcontext->err) != 0) {
+	return;
+    }
+    if (tables == NULL) {
+	return;
+    }
+
+    /* count how many modules we ended up loading, and how many preauth
+     * types we may claim to support as a result */
+    n_modules = 0;
+    for (n_tables = 0;
+         (tables != NULL) && (tables[n_tables] != NULL);
+         n_tables++) {
+	table = tables[n_tables];
+	if ((table->pa_type_list != NULL) && (table->process != NULL)) {
+	    for (j = 0; table->pa_type_list[j] > 0; j++) {
+		n_modules++;
+	    }
+	}
+    }
+
+    /* allocate the space we need */
+    context = malloc(sizeof(*context));
+    if (context == NULL) {
+	krb5int_free_plugin_dir_data(tables);
+        return;
+    }
+    context->modules = malloc(sizeof(context->modules[0]) * n_modules);
+    if (context->modules == NULL) {
+	krb5int_free_plugin_dir_data(tables);
+        free(context);
+        return;
+    }
+    memset(context->modules, 0, sizeof(context->modules[0]) * n_modules);
+    context->n_modules = n_modules;
+
+    /* fill in the structure */
+    k = 0;
+    for (i = 0; i < n_tables; i++) {
+        table = tables[i];
+        if ((table->pa_type_list != NULL) && (table->process != NULL)) {
+	    plugin_context = NULL;
+	    if ((table->init != NULL) &&
+		((*table->init)(kcontext, &plugin_context) != 0)) {
+#ifdef DEBUG
+		    fprintf (stderr, "init err, skipping module \"%s\"\n",
+			     table->name);
+#endif
+		    continue;
+	    }
+
+	    rcpp = NULL;
+	    for (j = 0; table->pa_type_list[j] > 0; j++) {
+		pa_type = table->pa_type_list[j];
+		context->modules[k].pa_type = pa_type;
+		context->modules[k].enctypes = table->enctype_list;
+		context->modules[k].plugin_context = plugin_context;
+		/* Only call client_fini once per plugin */
+		if (j == 0)
+		    context->modules[k].client_fini = table->fini;
+		else
+		    context->modules[k].client_fini = NULL;
+		context->modules[k].ftable = table;
+		context->modules[k].name = table->name;
+		context->modules[k].flags = (*table->flags)(kcontext, pa_type);
+		context->modules[k].use_count = 0;
+		context->modules[k].client_process = table->process;
+		context->modules[k].client_tryagain = table->tryagain;
+		if (j == 0)
+		    context->modules[k].client_supply_gic_opts = table->gic_opts;
+		else
+		    context->modules[k].client_supply_gic_opts = NULL;
+		context->modules[k].request_context = NULL;
+		/*
+		 * Only call request_init and request_fini once per plugin.
+		 * Only the first module within each plugin will ever
+		 * have request_context filled in.  Every module within
+		 * the plugin will have its request_context_pp pointing
+		 * to that entry's request_context.  That way all the
+		 * modules within the plugin share the same request_context
+		 */
+		if (j == 0) {
+		    context->modules[k].client_req_init = table->request_init;
+		    context->modules[k].client_req_fini = table->request_fini;
+		    rcpp = &context->modules[k].request_context;
+		} else {
+		    context->modules[k].client_req_init = NULL;
+		    context->modules[k].client_req_fini = NULL;
+		}
+		context->modules[k].request_context_pp = rcpp;
+#ifdef DEBUG
+		fprintf (stderr, "init module \"%s\", pa_type %d, flag %d\n",
+			 context->modules[k].name,
+			 context->modules[k].pa_type,
+			 context->modules[k].flags);
+#endif
+		k++;
+	    }
+	}
+    }
+    krb5int_free_plugin_dir_data(tables);
+
+    /* return the result */
+    kcontext->preauth_context = context;
+}
+
+/* Zero the use counts for the modules herein.  Usually used before we
+ * start processing any data from the server, at which point every module
+ * will again be able to take a crack at whatever the server sent. */
+void KRB5_CALLCONV
+krb5_clear_preauth_context_use_counts(krb5_context context)
+{
+    int i;
+    if (context->preauth_context != NULL) {
+	for (i = 0; i < context->preauth_context->n_modules; i++) {
+	    context->preauth_context->modules[i].use_count = 0;
+	}
+    }
+}
+
+/*
+ * Give all the preauth plugins a look at the preauth option which
+ * has just been set
+ */
+krb5_error_code
+krb5_preauth_supply_preauth_data(krb5_context context,
+				 krb5_gic_opt_ext *opte,
+				 const char *attr,
+				 const char *value)
+{
+    krb5_error_code retval;
+    int i;
+    void *pctx;
+    const char *emsg = NULL;
+
+    if (context->preauth_context == NULL)
+	krb5_init_preauth_context(context);
+    if (context->preauth_context == NULL) {
+	retval = EINVAL;
+	krb5int_set_error(&context->err, retval,
+		"krb5_preauth_supply_preauth_data: "
+		"Unable to initialize preauth context");
+	return retval;
+    }
+
+    /*
+     * Go down the list of preauth modules, and supply them with the
+     * attribute/value pair.
+     */
+    for (i = 0; i < context->preauth_context->n_modules; i++) {
+	if (context->preauth_context->modules[i].client_supply_gic_opts == NULL)
+	    continue;
+	pctx = context->preauth_context->modules[i].plugin_context;
+	retval = (*context->preauth_context->modules[i].client_supply_gic_opts)
+				(context, pctx,
+				 (krb5_get_init_creds_opt *)opte, attr, value); 
+	if (retval) {
+	    emsg = krb5_get_error_message(context, retval);
+	    krb5int_set_error(&context->err, retval, "Preauth plugin %s: %s",
+			      context->preauth_context->modules[i].name, emsg);
+	    break;
+	}
+    }
+    return retval;
+}
+
+/* Free the per-krb5_context preauth_context. This means clearing any
+ * plugin-specific context which may have been created, and then
+ * freeing the context itself. */
+void KRB5_CALLCONV
+krb5_free_preauth_context(krb5_context context)
+{
+    int i;
+    void *pctx;
+    if (context->preauth_context != NULL) {
+	for (i = 0; i < context->preauth_context->n_modules; i++) {
+	    pctx = context->preauth_context->modules[i].plugin_context;
+	    if (context->preauth_context->modules[i].client_fini != NULL) {
+	        (*context->preauth_context->modules[i].client_fini)(context, pctx);
+	    }
+	    memset(&context->preauth_context->modules[i], 0,
+	           sizeof(context->preauth_context->modules[i]));
+	}
+	if (context->preauth_context->modules != NULL) {
+	    free(context->preauth_context->modules);
+	    context->preauth_context->modules = NULL;
+	}
+	free(context->preauth_context);
+	context->preauth_context = NULL;
+    }
+}
+
+/* Initialize the per-AS-REQ context. This means calling the client_req_init
+ * function to give the plugin a chance to allocate a per-request context. */
+void KRB5_CALLCONV
+krb5_preauth_request_context_init(krb5_context context)
+{
+    int i;
+    void *rctx, *pctx;
+
+    /* Limit this to only one attempt per context? */
+    if (context->preauth_context == NULL)
+	krb5_init_preauth_context(context);
+    if (context->preauth_context != NULL) {
+	for (i = 0; i < context->preauth_context->n_modules; i++) {
+	    pctx = context->preauth_context->modules[i].plugin_context;
+	    if (context->preauth_context->modules[i].client_req_init != NULL) {
+		rctx = context->preauth_context->modules[i].request_context_pp;
+		(*context->preauth_context->modules[i].client_req_init) (context, pctx, rctx);
+	    }
+	}
+    }
+}
+
+/* Free the per-AS-REQ context. This means clearing any request-specific
+ * context which the plugin may have created. */
+void KRB5_CALLCONV
+krb5_preauth_request_context_fini(krb5_context context)
+{
+    int i;
+    void *rctx, *pctx;
+    if (context->preauth_context != NULL) {
+	for (i = 0; i < context->preauth_context->n_modules; i++) {
+	    pctx = context->preauth_context->modules[i].plugin_context;
+	    rctx = context->preauth_context->modules[i].request_context;
+	    if (rctx != NULL) {
+		if (context->preauth_context->modules[i].client_req_fini != NULL) {
+		    (*context->preauth_context->modules[i].client_req_fini)(context, pctx, rctx);
+		}
+		context->preauth_context->modules[i].request_context = NULL;
+	    }
+	}
+    }
+}
+
+/* Add the named encryption type to the existing list of ktypes. */
+static void
+grow_ktypes(krb5_enctype **out_ktypes, int *out_nktypes, krb5_enctype ktype)
+{
+    int i;
+    krb5_enctype *ktypes;
+    for (i = 0; i < *out_nktypes; i++) {
+	if ((*out_ktypes)[i] == ktype)
+	    return;
+    }
+    ktypes = malloc((*out_nktypes + 2) * sizeof(ktype));
+    if (ktypes) {
+	for (i = 0; i < *out_nktypes; i++)
+	    ktypes[i] = (*out_ktypes)[i];
+	ktypes[i++] = ktype;
+	ktypes[i] = 0;
+	free(*out_ktypes);
+	*out_ktypes = ktypes;
+	*out_nktypes = i;
+    }
+}
+
+/*
+ * Add the given list of pa_data items to the existing list of items.
+ * Factored out here to make reading the do_preauth logic easier to read.
+ */
+static int
+grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size,
+	     krb5_pa_data **addition, int num_addition)
+{
+    krb5_pa_data **pa_list;
+    int i, j;
+
+    if (out_pa_list == NULL || addition == NULL) {
+	return EINVAL;
+    }
+
+    if (*out_pa_list == NULL) {
+	/* Allocate room for the new additions and a NULL terminator. */
+	pa_list = malloc((num_addition + 1) * sizeof(krb5_pa_data *));
+	if (pa_list == NULL)
+	    return ENOMEM;
+	for (i = 0; i < num_addition; i++)
+	    pa_list[i] = addition[i];
+	pa_list[i] = NULL;
+	*out_pa_list = pa_list;
+	*out_pa_list_size = num_addition;
+    } else {
+	/*
+	 * Allocate room for the existing entries plus
+	 * the new additions and a NULL terminator.
+	 */
+	pa_list = malloc((*out_pa_list_size + num_addition + 1)
+						* sizeof(krb5_pa_data *));
+	if (pa_list == NULL)
+	    return ENOMEM;
+	for (i = 0; i < *out_pa_list_size; i++)
+	    pa_list[i] = (*out_pa_list)[i];
+	for (j = 0; j < num_addition;)
+	    pa_list[i++] = addition[j++];
+	pa_list[i] = NULL;
+	free(*out_pa_list);
+	*out_pa_list = pa_list;
+	*out_pa_list_size = i;
+    }
+    return 0;
+}
+
+/*
+ * Retrieve a specific piece of information required by the plugin and
+ * return it in a new krb5_data item.  There are separate request_types
+ * to obtain the data and free it.
+ *
+ * This may require massaging data into a contrived format, but it will
+ * hopefully keep us from having to reveal library-internal functions
+ * or data to the plugin modules.
+ */
+
+static krb5_error_code
+client_data_proc(krb5_context kcontext,
+		 krb5_preauth_client_rock *rock,
+		 krb5_int32 request_type,
+		 krb5_data **retdata)
+{
+    krb5_data *ret;
+    char *data;
+
+    if (rock->magic != CLIENT_ROCK_MAGIC)
+	return EINVAL;
+    if (retdata == NULL)
+	return EINVAL;
+
+    switch (request_type) {
+    case krb5plugin_preauth_client_get_etype:
+	{
+	    krb5_enctype *eptr;
+	    if (rock->as_reply == NULL)
+		return ENOENT;
+	    ret = malloc(sizeof(krb5_data));
+	    if (ret == NULL)
+		return ENOMEM;
+	    data = malloc(sizeof(krb5_enctype));
+	    if (data == NULL) {
+		free(ret);
+		return ENOMEM;
+	    }
+	    ret->data = data;
+	    ret->length = sizeof(krb5_enctype);
+	    eptr = (krb5_enctype *)data;
+	    *eptr = rock->as_reply->enc_part.enctype;
+	    *retdata = ret;
+	    return 0;
+	}
+	break;
+    case krb5plugin_preauth_client_free_etype:
+	ret = *retdata;
+	if (ret == NULL)
+	    return 0;
+	if (ret->data)
+	    free(ret->data);
+	free(ret);
+	return 0;
+	break;
+    default:
+	return EINVAL;
+    }
+}
+
+/* Tweak the request body, for now adding any enctypes which the module claims
+ * to add support for to the list, but in the future perhaps doing more
+ * involved things. */
+void KRB5_CALLCONV
+krb5_preauth_prepare_request(krb5_context kcontext,
+			     krb5_gic_opt_ext *opte,
+			     krb5_kdc_req *request)
+{
+    int i, j;
+
+    if (kcontext->preauth_context == NULL) {
+	return;
+    }
+    /* Add the module-specific enctype list to the request, but only if
+     * it's something we can safely modify. */
+    if (!(opte && (opte->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))) {
+	for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
+	    if (kcontext->preauth_context->modules[i].enctypes == NULL)
+		continue;
+	    for (j = 0; kcontext->preauth_context->modules[i].enctypes[j] != 0; j++) {
+		grow_ktypes(&request->ktype, &request->nktypes,
+			    kcontext->preauth_context->modules[i].enctypes[j]);
+	    }
+	}
+    }
+}
+
+/* Find the first module which provides for the named preauth type which also
+ * hasn't had a chance to run yet (INFO modules don't count, because as a rule
+ * they don't generate preauth data), and run it. */
+static krb5_error_code
+krb5_run_preauth_plugins(krb5_context kcontext,
+			 int module_required_flags,
+			 krb5_kdc_req *request,
+			 krb5_data *encoded_request_body,
+			 krb5_data *encoded_previous_request,
+			 krb5_pa_data *in_padata,
+			 krb5_prompter_fct prompter,
+			 void *prompter_data,
+			 preauth_get_as_key_proc gak_fct,
+			 krb5_data *salt,
+			 krb5_data *s2kparams,
+			 void *gak_data,
+			 krb5_preauth_client_rock *get_data_rock,
+			 krb5_keyblock *as_key,
+			 krb5_pa_data ***out_pa_list,
+			 int *out_pa_list_size,
+			 int *module_ret,
+			 int *module_flags,
+			 krb5_gic_opt_ext *opte)
+{
+    int i;
+    krb5_pa_data **out_pa_data;
+    krb5_error_code ret;
+    struct _krb5_preauth_context_module *module;
+
+    if (kcontext->preauth_context == NULL) {
+	return ENOENT;
+    }
+    /* iterate over all loaded modules */
+    for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
+	module = &kcontext->preauth_context->modules[i];
+	/* skip over those which don't match the preauth type */
+	if (module->pa_type != in_padata->pa_type)
+	    continue;
+	/* skip over those which don't match the flags (INFO vs REAL, mainly) */
+	if ((module->flags & module_required_flags) == 0)
+	    continue;
+	/* if it's a REAL module, try to call it only once per library call */
+	if (module_required_flags & PA_REAL) {
+	    if (module->use_count > 0) {
+#ifdef DEBUG
+		fprintf(stderr, "skipping already-used module \"%s\"(%d)\n",
+			module->name, module->pa_type);
+#endif
+		continue;
+	    }
+	    module->use_count++;
+	}
+	/* run the module's callback function */
+	out_pa_data = NULL;
+#ifdef DEBUG
+	fprintf(stderr, "using module \"%s\" (%d), flags = %d\n",
+		module->name, module->pa_type, module->flags);
+#endif
+	ret = module->client_process(kcontext,
+				     module->plugin_context,
+				     *module->request_context_pp,
+				     (krb5_get_init_creds_opt *)opte,
+				     client_data_proc,
+				     get_data_rock,
+				     request,
+				     encoded_request_body,
+				     encoded_previous_request,
+				     in_padata,
+				     prompter, prompter_data,
+				     gak_fct, gak_data, salt, s2kparams,
+				     as_key,
+				     &out_pa_data);
+	/* Make note of the module's flags and status. */
+	*module_flags = module->flags;
+	*module_ret = ret;
+	/* Save the new preauth data item. */
+	if (out_pa_data != NULL) {
+	    int j;
+	    for (j = 0; out_pa_data[j] != NULL; j++);
+	    ret = grow_pa_list(out_pa_list, out_pa_list_size, out_pa_data, j);
+	    free(out_pa_data);
+	    if (ret != 0)
+		return ret;
+	}
+	break;
+    }
+    if (i >= kcontext->preauth_context->n_modules) {
+	return ENOENT;
+    }
+    return 0;
+}
+
+static
+krb5_error_code pa_salt(krb5_context context,
+			krb5_kdc_req *request,
+			krb5_pa_data *in_padata,
+			krb5_pa_data **out_padata,
+			krb5_data *salt, krb5_data *s2kparams,
+			krb5_enctype *etype,
+			krb5_keyblock *as_key,
+			krb5_prompter_fct prompter, void *prompter_data,
+			krb5_gic_get_as_key_fct gak_fct, void *gak_data)
+{
+    krb5_data tmp;
+
+    tmp.data = in_padata->contents;
+    tmp.length = in_padata->length;
+    krb5_free_data_contents(context, salt);
+    krb5int_copy_data_contents(context, &tmp, salt);
+    
+
+    if (in_padata->pa_type == KRB5_PADATA_AFS3_SALT)
+	salt->length = SALT_TYPE_AFS_LENGTH;
+
+    return(0);
+}
+
+static
+krb5_error_code pa_enc_timestamp(krb5_context context,
+				 krb5_kdc_req *request,
+				 krb5_pa_data *in_padata,
+				 krb5_pa_data **out_padata,
+				 krb5_data *salt,
+				 krb5_data *s2kparams,
+				 krb5_enctype *etype,
+				 krb5_keyblock *as_key,
+				 krb5_prompter_fct prompter,
+				 void *prompter_data,
+				 krb5_gic_get_as_key_fct gak_fct,
+				 void *gak_data)
+{
+    krb5_error_code ret;
+    krb5_pa_enc_ts pa_enc;
+    krb5_data *tmp;
+    krb5_enc_data enc_data;
+    krb5_pa_data *pa;
+   
+    if (as_key->length == 0) {
+#ifdef DEBUG
+	fprintf (stderr, "%s:%d: salt len=%d", __FILE__, __LINE__,
+		 salt->length);
+	if ((int) salt->length > 0)
+	    fprintf (stderr, " '%.*s'", salt->length, salt->data);
+	fprintf (stderr, "; *etype=%d request->ktype[0]=%d\n",
+		 *etype, request->ktype[0]);
+#endif
+       if ((ret = ((*gak_fct)(context, request->client,
+			      *etype ? *etype : request->ktype[0],
+			      prompter, prompter_data,
+			      salt, s2kparams, as_key, gak_data))))
+           return(ret);
+    }
+
+    /* now get the time of day, and encrypt it accordingly */
+
+    if ((ret = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec)))
+	return(ret);
+
+    if ((ret = encode_krb5_pa_enc_ts(&pa_enc, &tmp)))
+	return(ret);
+
+#ifdef DEBUG
+    fprintf (stderr, "key type %d bytes %02x %02x ...\n",
+	     as_key->enctype,
+	     as_key->contents[0], as_key->contents[1]);
+#endif
+    ret = krb5_encrypt_helper(context, as_key,
+			      KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS,
+			      tmp, &enc_data);
+#ifdef DEBUG
+    fprintf (stderr, "enc data { type=%d kvno=%d data=%02x %02x ... }\n",
+	     enc_data.enctype, enc_data.kvno,
+	     0xff & enc_data.ciphertext.data[0],
+	     0xff & enc_data.ciphertext.data[1]);
+#endif
+
+    krb5_free_data(context, tmp);
+
+    if (ret) {
+	krb5_xfree(enc_data.ciphertext.data);
+	return(ret);
+    }
+
+    ret = encode_krb5_enc_data(&enc_data, &tmp);
+
+    krb5_xfree(enc_data.ciphertext.data);
+
+    if (ret)
+	return(ret);
+
+    if ((pa = (krb5_pa_data *) malloc(sizeof(krb5_pa_data))) == NULL) {
+	krb5_free_data(context, tmp);
+	return(ENOMEM);
+    }
+
+    pa->magic = KV5M_PA_DATA;
+    pa->pa_type = KRB5_PADATA_ENC_TIMESTAMP;
+    pa->length = tmp->length;
+    pa->contents = (krb5_octet *) tmp->data;
+
+    *out_padata = pa;
+
+    krb5_xfree(tmp);
+
+    return(0);
+}
+
+static 
+char *sam_challenge_banner(krb5_int32 sam_type)
+{
+    char *label;
+
+    switch (sam_type) {
+    case PA_SAM_TYPE_ENIGMA:	/* Enigma Logic */
+	label = "Challenge for Enigma Logic mechanism";
+	break;
+    case PA_SAM_TYPE_DIGI_PATH: /*  Digital Pathways */
+    case PA_SAM_TYPE_DIGI_PATH_HEX: /*  Digital Pathways */
+	label = "Challenge for Digital Pathways mechanism";
+	break;
+    case PA_SAM_TYPE_ACTIVCARD_DEC: /*  Digital Pathways */
+    case PA_SAM_TYPE_ACTIVCARD_HEX: /*  Digital Pathways */
+	label = "Challenge for Activcard mechanism";
+	break;
+    case PA_SAM_TYPE_SKEY_K0:	/*  S/key where  KDC has key 0 */
+	label = "Challenge for Enhanced S/Key mechanism";
+	break;
+    case PA_SAM_TYPE_SKEY:	/*  Traditional S/Key */
+	label = "Challenge for Traditional S/Key mechanism";
+	break;
+    case PA_SAM_TYPE_SECURID:	/*  Security Dynamics */
+	label = "Challenge for Security Dynamics mechanism";
+	break;
+    case PA_SAM_TYPE_SECURID_PREDICT:	/* predictive Security Dynamics */
+	label = "Challenge for Security Dynamics mechanism";
+	break;
+    default:
+	label = "Challenge from authentication server";
+	break;
+    }
+
+    return(label);
+}
+
+/* this macro expands to the int,ptr necessary for "%.*s" in an sprintf */
+
+#define SAMDATA(kdata, str, maxsize) \
+	(int)((kdata.length)? \
+	      ((((kdata.length)<=(maxsize))?(kdata.length):strlen(str))): \
+	      strlen(str)), \
+	(kdata.length)? \
+	((((kdata.length)<=(maxsize))?(kdata.data):(str))):(str)
+
+/* XXX Danger! This code is not in sync with the kerberos-password-02
+   draft.  This draft cannot be implemented as written.  This code is
+   compatible with earlier versions of mit krb5 and cygnus kerbnet. */
+
+static
+krb5_error_code pa_sam(krb5_context context,
+		       krb5_kdc_req *request,
+		       krb5_pa_data *in_padata,
+		       krb5_pa_data **out_padata,
+		       krb5_data *salt,
+		       krb5_data *s2kparams,
+		       krb5_enctype *etype,
+		       krb5_keyblock *as_key,
+		       krb5_prompter_fct prompter,
+		       void *prompter_data,
+		       krb5_gic_get_as_key_fct gak_fct,
+		       void *gak_data)
+{
+    krb5_error_code		ret;
+    krb5_data			tmpsam;
+    char			name[100], banner[100];
+    char			prompt[100], response[100];
+    krb5_data			response_data;
+    krb5_prompt			kprompt;
+    krb5_prompt_type		prompt_type;
+    krb5_data			defsalt;
+    krb5_sam_challenge		*sam_challenge = 0;
+    krb5_sam_response		sam_response;
+    /* these two get encrypted and stuffed in to sam_response */
+    krb5_enc_sam_response_enc	enc_sam_response_enc;
+    krb5_data *			scratch;
+    krb5_pa_data *		pa;
+
+    if (prompter == NULL)
+	return EIO;
+
+    tmpsam.length = in_padata->length;
+    tmpsam.data = (char *) in_padata->contents;
+    if ((ret = decode_krb5_sam_challenge(&tmpsam, &sam_challenge)))
+	return(ret);
+
+    if (sam_challenge->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) {
+	krb5_xfree(sam_challenge);
+	return(KRB5_SAM_UNSUPPORTED);
+    }
+
+    /* If we need the password from the user (USE_SAD_AS_KEY not set),	*/
+    /* then get it here.  Exception for "old" KDCs with CryptoCard 	*/
+    /* support which uses the USE_SAD_AS_KEY flag, but still needs pwd	*/ 
+
+    if (!(sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) ||
+	(sam_challenge->sam_type == PA_SAM_TYPE_CRYPTOCARD)) {
+
+	/* etype has either been set by caller or by KRB5_PADATA_ETYPE_INFO */
+	/* message from the KDC.  If it is not set, pick an enctype that we */
+	/* think the KDC will have for us.				    */
+
+	if (etype && *etype == 0)
+	   *etype = ENCTYPE_DES_CBC_CRC;
+
+	if ((ret = (gak_fct)(context, request->client, *etype, prompter,
+			prompter_data, salt, s2kparams, as_key, gak_data)))
+	   return(ret);
+    }
+    sprintf(name, "%.*s",
+	    SAMDATA(sam_challenge->sam_type_name, "SAM Authentication",
+		    sizeof(name) - 1));
+
+    sprintf(banner, "%.*s",
+	    SAMDATA(sam_challenge->sam_challenge_label,
+		    sam_challenge_banner(sam_challenge->sam_type),
+		    sizeof(banner)-1));
+
+    /* sprintf(prompt, "Challenge is [%s], %s: ", challenge, prompt); */
+    sprintf(prompt, "%s%.*s%s%.*s",
+	    sam_challenge->sam_challenge.length?"Challenge is [":"",
+	    SAMDATA(sam_challenge->sam_challenge, "", 20),
+	    sam_challenge->sam_challenge.length?"], ":"",
+	    SAMDATA(sam_challenge->sam_response_prompt, "passcode", 55));
+
+    response_data.data = response;
+    response_data.length = sizeof(response);
+
+    kprompt.prompt = prompt;
+    kprompt.hidden = 1;
+    kprompt.reply = &response_data;
+    prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+
+    /* PROMPTER_INVOCATION */
+    krb5int_set_prompt_types(context, &prompt_type);
+    if ((ret = ((*prompter)(context, prompter_data, name,
+			   banner, 1, &kprompt)))) {
+	krb5_xfree(sam_challenge);
+	krb5int_set_prompt_types(context, 0);
+	return(ret);
+    }
+    krb5int_set_prompt_types(context, 0);
+
+    enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce;
+    if (sam_challenge->sam_nonce == 0) {
+	if ((ret = krb5_us_timeofday(context, 
+				&enc_sam_response_enc.sam_timestamp,
+				&enc_sam_response_enc.sam_usec))) {
+		krb5_xfree(sam_challenge);
+		return(ret);
+	}
+
+	sam_response.sam_patimestamp = enc_sam_response_enc.sam_timestamp;
+    }
+
+    /* XXX What if more than one flag is set?  */
+    if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
+
+	/* Most of this should be taken care of before we get here.  We	*/
+	/* will need the user's password and as_key to encrypt the SAD	*/
+	/* and we want to preserve ordering of user prompts (first	*/
+	/* password, then SAM data) so that user's won't be confused.	*/
+
+	if (as_key->length) {
+	    krb5_free_keyblock_contents(context, as_key);
+	    as_key->length = 0;
+	}
+
+	/* generate a salt using the requested principal */
+
+	if ((salt->length == -1 || salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
+	    if ((ret = krb5_principal2salt(context, request->client,
+					  &defsalt))) {
+		krb5_xfree(sam_challenge);
+		return(ret);
+	    }
+
+	    salt = &defsalt;
+	} else {
+	    defsalt.length = 0;
+	}
+
+	/* generate a key using the supplied password */
+
+	ret = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
+				   (krb5_data *)gak_data, salt, as_key);
+
+	if (defsalt.length)
+	    krb5_xfree(defsalt.data);
+
+	if (ret) {
+	    krb5_xfree(sam_challenge);
+	    return(ret);
+	}
+
+	/* encrypt the passcode with the key from above */
+
+	enc_sam_response_enc.sam_sad = response_data;
+    } else if (sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) {
+
+	/* process the key as password */
+
+	if (as_key->length) {
+	    krb5_free_keyblock_contents(context, as_key);
+	    as_key->length = 0;
+	}
+
+#if 0
+	if ((salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
+	    if (ret = krb5_principal2salt(context, request->client,
+					  &defsalt)) {
+		krb5_xfree(sam_challenge);
+		return(ret);
+	    }
+
+	    salt = &defsalt;
+	} else {
+	    defsalt.length = 0;
+	}
+#else
+	defsalt.length = 0;
+	salt = NULL;
+#endif
+	    
+	/* XXX As of the passwords-04 draft, no enctype is specified,
+	   the server uses ENCTYPE_DES_CBC_MD5. In the future the
+	   server should send a PA-SAM-ETYPE-INFO containing the enctype. */
+
+	ret = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
+				   &response_data, salt, as_key);
+
+	if (defsalt.length)
+	    krb5_xfree(defsalt.data);
+
+	if (ret) {
+	    krb5_xfree(sam_challenge);
+	    return(ret);
+	}
+
+	enc_sam_response_enc.sam_sad.length = 0;
+    } else {
+	/* Eventually, combine SAD with long-term key to get
+	   encryption key.  */
+	return KRB5_PREAUTH_BAD_TYPE;
+    }
+
+    /* copy things from the challenge */
+    sam_response.sam_nonce = sam_challenge->sam_nonce;
+    sam_response.sam_flags = sam_challenge->sam_flags;
+    sam_response.sam_track_id = sam_challenge->sam_track_id;
+    sam_response.sam_type = sam_challenge->sam_type;
+    sam_response.magic = KV5M_SAM_RESPONSE;
+
+    krb5_xfree(sam_challenge);
+
+    /* encode the encoded part of the response */
+    if ((ret = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc,
+						&scratch)))
+	return(ret);
+
+    ret = krb5_encrypt_data(context, as_key, 0, scratch,
+			    &sam_response.sam_enc_nonce_or_ts);
+
+    krb5_free_data(context, scratch);
+
+    if (ret)
+	return(ret);
+
+    /* sam_enc_key is reserved for future use */
+    sam_response.sam_enc_key.ciphertext.length = 0;
+
+    if ((pa = malloc(sizeof(krb5_pa_data))) == NULL)
+	return(ENOMEM);
+
+    if ((ret = encode_krb5_sam_response(&sam_response, &scratch))) {
+	free(pa);
+	return(ret);
+    }
+
+    pa->magic = KV5M_PA_DATA;
+    pa->pa_type = KRB5_PADATA_SAM_RESPONSE;
+    pa->length = scratch->length;
+    pa->contents = (krb5_octet *) scratch->data;
+
+    *out_padata = pa;
+
+    return(0);
+}
+
+static
+krb5_error_code pa_sam_2(krb5_context context,
+				krb5_kdc_req *request,
+				krb5_pa_data *in_padata,
+				krb5_pa_data **out_padata,
+				krb5_data *salt,
+			 krb5_data *s2kparams,
+				krb5_enctype *etype,
+				krb5_keyblock *as_key,
+				krb5_prompter_fct prompter,
+				void *prompter_data,
+				krb5_gic_get_as_key_fct gak_fct,
+				void *gak_data) {
+
+   krb5_error_code retval;
+   krb5_sam_challenge_2 *sc2 = NULL;
+   krb5_sam_challenge_2_body *sc2b = NULL;
+   krb5_data tmp_data;
+   krb5_data response_data;
+   char name[100], banner[100], prompt[100], response[100];
+   krb5_prompt kprompt;
+   krb5_prompt_type prompt_type;
+   krb5_data defsalt;
+   krb5_checksum **cksum;
+   krb5_data *scratch = NULL;
+   krb5_boolean valid_cksum = 0;
+   krb5_enc_sam_response_enc_2 enc_sam_response_enc_2;
+   krb5_sam_response_2 sr2;
+   size_t ciph_len;
+   krb5_pa_data *sam_padata;
+
+   if (prompter == NULL)
+	return KRB5_LIBOS_CANTREADPWD;
+
+   tmp_data.length = in_padata->length;
+   tmp_data.data = (char *)in_padata->contents;
+
+   if ((retval = decode_krb5_sam_challenge_2(&tmp_data, &sc2)))
+	return(retval);
+
+   retval = decode_krb5_sam_challenge_2_body(&sc2->sam_challenge_2_body, &sc2b);
+
+   if (retval)
+	return(retval);
+
+   if (!sc2->sam_cksum || ! *sc2->sam_cksum) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	return(KRB5_SAM_NO_CHECKSUM);
+   }
+
+   if (sc2b->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	return(KRB5_SAM_UNSUPPORTED);
+   }
+
+   if (!valid_enctype(sc2b->sam_etype)) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	return(KRB5_SAM_INVALID_ETYPE);
+   }
+
+   /* All of the above error checks are KDC-specific, that is, they	*/
+   /* assume a failure in the KDC reply.  By returning anything other	*/
+   /* than KRB5_KDC_UNREACH, KRB5_PREAUTH_FAILED,		*/
+   /* KRB5_LIBOS_PWDINTR, or KRB5_REALM_CANT_RESOLVE, the client will	*/
+   /* most likely go on to try the AS_REQ against master KDC		*/
+
+   if (!(sc2b->sam_flags & KRB5_SAM_USE_SAD_AS_KEY)) {
+	/* We will need the password to obtain the key used for	*/
+	/* the checksum, and encryption of the sam_response.	*/
+	/* Go ahead and get it now, preserving the ordering of	*/
+	/* prompts for the user.				*/
+
+	retval = (gak_fct)(context, request->client,
+			sc2b->sam_etype, prompter,
+			prompter_data, salt, s2kparams, as_key, gak_data);
+	if (retval) {
+	   krb5_free_sam_challenge_2(context, sc2);
+	   krb5_free_sam_challenge_2_body(context, sc2b);
+	   return(retval);
+	}
+   }
+
+   sprintf(name, "%.*s",
+	SAMDATA(sc2b->sam_type_name, "SAM Authentication",
+	sizeof(name) - 1));
+
+   sprintf(banner, "%.*s",
+	SAMDATA(sc2b->sam_challenge_label,
+	sam_challenge_banner(sc2b->sam_type),
+	sizeof(banner)-1));
+
+   sprintf(prompt, "%s%.*s%s%.*s",
+	sc2b->sam_challenge.length?"Challenge is [":"",
+	SAMDATA(sc2b->sam_challenge, "", 20),
+	sc2b->sam_challenge.length?"], ":"",
+	SAMDATA(sc2b->sam_response_prompt, "passcode", 55));
+
+   response_data.data = response;
+   response_data.length = sizeof(response);
+   kprompt.prompt = prompt;
+   kprompt.hidden = 1;
+   kprompt.reply = &response_data;
+
+   prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+   krb5int_set_prompt_types(context, &prompt_type);
+
+   if ((retval = ((*prompter)(context, prompter_data, name,
+				banner, 1, &kprompt)))) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	krb5int_set_prompt_types(context, 0);
+	return(retval);
+   }
+
+   krb5int_set_prompt_types(context, (krb5_prompt_type *)NULL);
+
+   /* Generate salt used by string_to_key() */
+   if ((salt->length == -1) && (salt->data == NULL)) {
+	if ((retval = 
+	     krb5_principal2salt(context, request->client, &defsalt))) {
+	   krb5_free_sam_challenge_2(context, sc2);
+	   krb5_free_sam_challenge_2_body(context, sc2b);
+	   return(retval);
+	}
+	salt = &defsalt;
+   } else {
+	defsalt.length = 0;
+   }
+
+   /* Get encryption key to be used for checksum and sam_response */
+   if (!(sc2b->sam_flags & KRB5_SAM_USE_SAD_AS_KEY)) {
+	/* as_key = string_to_key(password) */
+
+	if (as_key->length) {
+	   krb5_free_keyblock_contents(context, as_key);
+	   as_key->length = 0;
+	}
+
+	/* generate a key using the supplied password */
+	retval = krb5_c_string_to_key(context, sc2b->sam_etype,
+                                   (krb5_data *)gak_data, salt, as_key);
+
+	if (retval) {
+	   krb5_free_sam_challenge_2(context, sc2);
+	   krb5_free_sam_challenge_2_body(context, sc2b);
+	   if (defsalt.length) krb5_xfree(defsalt.data);
+	   return(retval);
+	}
+
+	if (!(sc2b->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD)) {
+	   /* as_key = combine_key (as_key, string_to_key(SAD)) */
+	   krb5_keyblock tmp_kb;
+
+	   retval = krb5_c_string_to_key(context, sc2b->sam_etype,
+				&response_data, salt, &tmp_kb);
+
+	   if (retval) {
+		krb5_free_sam_challenge_2(context, sc2);
+	        krb5_free_sam_challenge_2_body(context, sc2b);
+		if (defsalt.length) krb5_xfree(defsalt.data);
+		return(retval);
+	   }
+
+	   /* This should be a call to the crypto library some day */
+	   /* key types should already match the sam_etype */
+	   retval = krb5int_c_combine_keys(context, as_key, &tmp_kb, as_key);
+
+	   if (retval) {
+		krb5_free_sam_challenge_2(context, sc2);
+	        krb5_free_sam_challenge_2_body(context, sc2b);
+		if (defsalt.length) krb5_xfree(defsalt.data);
+		return(retval);
+	   }
+	   krb5_free_keyblock_contents(context, &tmp_kb);
+	}
+
+	if (defsalt.length)
+	   krb5_xfree(defsalt.data);
+
+   } else {
+	/* as_key = string_to_key(SAD) */
+
+	if (as_key->length) {
+	   krb5_free_keyblock_contents(context, as_key);
+	   as_key->length = 0;
+	}
+
+	/* generate a key using the supplied password */
+	retval = krb5_c_string_to_key(context, sc2b->sam_etype,
+				&response_data, salt, as_key);
+
+	if (defsalt.length)
+	   krb5_xfree(defsalt.data);
+
+	if (retval) {
+	   krb5_free_sam_challenge_2(context, sc2);
+	   krb5_free_sam_challenge_2_body(context, sc2b);
+	   return(retval);
+	}
+   }
+
+   /* Now we have a key, verify the checksum on the sam_challenge */
+
+   cksum = sc2->sam_cksum;
+   
+   while (*cksum) {
+	/* Check this cksum */
+	retval = krb5_c_verify_checksum(context, as_key,
+			KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM,
+			&sc2->sam_challenge_2_body,
+			*cksum, &valid_cksum);
+	if (retval) {
+	   krb5_free_data(context, scratch);
+	   krb5_free_sam_challenge_2(context, sc2);
+	   krb5_free_sam_challenge_2_body(context, sc2b);
+	   return(retval);
+	}
+	if (valid_cksum)
+	   break;
+	cksum++;
+   }
+
+   if (!valid_cksum) {
+
+	/* If KRB5_SAM_SEND_ENCRYPTED_SAD is set, then password is only	*/
+	/* source for checksum key.  Therefore, a bad checksum means a	*/
+	/* bad password.  Don't give that direct feedback to someone	*/
+	/* trying to brute-force passwords.				*/
+
+	if (!(sc2b->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD))
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	/*
+	 * Note: We return AP_ERR_BAD_INTEGRITY so upper-level applications
+	 * can interpret that as "password incorrect", which is probably
+	 * the best error we can return in this situation.
+	 */
+	return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
+   }
+ 
+   /* fill in enc_sam_response_enc_2 */
+   enc_sam_response_enc_2.magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
+   enc_sam_response_enc_2.sam_nonce = sc2b->sam_nonce;
+   if (sc2b->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
+	enc_sam_response_enc_2.sam_sad = response_data;
+   } else {
+	enc_sam_response_enc_2.sam_sad.data = NULL;
+	enc_sam_response_enc_2.sam_sad.length = 0;
+   }
+
+   /* encode and encrypt enc_sam_response_enc_2 with as_key */
+   retval = encode_krb5_enc_sam_response_enc_2(&enc_sam_response_enc_2,
+		&scratch);
+   if (retval) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	return(retval);
+   }
+
+   /* Fill in sam_response_2 */
+   memset(&sr2, 0, sizeof(sr2));
+   sr2.sam_type = sc2b->sam_type;
+   sr2.sam_flags = sc2b->sam_flags;
+   sr2.sam_track_id = sc2b->sam_track_id;
+   sr2.sam_nonce = sc2b->sam_nonce;
+
+   /* Now take care of sr2.sam_enc_nonce_or_sad by encrypting encoded	*/
+   /* enc_sam_response_enc_2 from above */
+
+   retval = krb5_c_encrypt_length(context, as_key->enctype, scratch->length,
+				  &ciph_len);
+   if (retval) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	return(retval);
+   }
+   sr2.sam_enc_nonce_or_sad.ciphertext.length = ciph_len;
+
+   sr2.sam_enc_nonce_or_sad.ciphertext.data =
+	(char *)malloc(sr2.sam_enc_nonce_or_sad.ciphertext.length);
+
+   if (!sr2.sam_enc_nonce_or_sad.ciphertext.data) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	return(ENOMEM);
+   }
+
+   retval = krb5_c_encrypt(context, as_key, KRB5_KEYUSAGE_PA_SAM_RESPONSE,
+		NULL, scratch, &sr2.sam_enc_nonce_or_sad);
+   if (retval) {
+	krb5_free_sam_challenge_2(context, sc2);
+	krb5_free_sam_challenge_2_body(context, sc2b);
+	krb5_free_data(context, scratch);
+	krb5_free_data_contents(context, &sr2.sam_enc_nonce_or_sad.ciphertext);
+	return(retval);
+   }
+   krb5_free_data(context, scratch);
+   scratch = NULL;
+
+   /* Encode the sam_response_2 */
+   retval = encode_krb5_sam_response_2(&sr2, &scratch);
+   krb5_free_sam_challenge_2(context, sc2);
+   krb5_free_sam_challenge_2_body(context, sc2b);
+   krb5_free_data_contents(context, &sr2.sam_enc_nonce_or_sad.ciphertext);
+
+   if (retval) {
+	return (retval);
+   }
+
+   /* Almost there, just need to make padata !  */
+   sam_padata = malloc(sizeof(krb5_pa_data));
+   if (sam_padata == NULL) {
+	krb5_free_data(context, scratch);
+	return(ENOMEM);
+   }
+
+   sam_padata->magic = KV5M_PA_DATA;
+   sam_padata->pa_type = KRB5_PADATA_SAM_RESPONSE_2;
+   sam_padata->length = scratch->length;
+   sam_padata->contents = (krb5_octet *) scratch->data;
+
+   *out_padata = sam_padata;
+
+   return(0);
+}
+
+static const pa_types_t pa_types[] = {
+    {
+	KRB5_PADATA_PW_SALT,
+	pa_salt,
+	PA_INFO,
+    },
+    {
+	KRB5_PADATA_AFS3_SALT,
+	pa_salt,
+	PA_INFO,
+    },
+    {
+	KRB5_PADATA_ENC_TIMESTAMP,
+	pa_enc_timestamp,
+	PA_REAL,
+    },
+    {
+	KRB5_PADATA_SAM_CHALLENGE_2,
+	pa_sam_2,
+	PA_REAL,
+    },
+    {
+	KRB5_PADATA_SAM_CHALLENGE,
+	pa_sam,
+	PA_REAL,
+    },
+    {
+	-1,
+	NULL,
+	0,
+    },
+};
+
+/*
+ * If one of the modules can adjust its AS_REQ data using the contents of the
+ * err_reply, return 0.  If it's the sort of correction which requires that we
+ * ask the user another question, we let the calling application deal with it.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_do_preauth_tryagain(krb5_context kcontext,
+			 krb5_kdc_req *request,
+			 krb5_data *encoded_request_body,
+			 krb5_data *encoded_previous_request,
+			 krb5_pa_data **padata,
+			 krb5_pa_data ***return_padata,
+			 krb5_error *err_reply,
+			 krb5_data *salt, krb5_data *s2kparams,
+			 krb5_enctype *etype,
+			 krb5_keyblock *as_key,
+			 krb5_prompter_fct prompter, void *prompter_data,
+			 krb5_gic_get_as_key_fct gak_fct, void *gak_data,
+			 krb5_preauth_client_rock *get_data_rock,
+			 krb5_gic_opt_ext *opte)
+{
+    krb5_error_code ret;
+    krb5_pa_data **out_padata;
+    krb5_preauth_context *context;
+    struct _krb5_preauth_context_module *module;
+    int i, j;
+    int out_pa_list_size = 0;
+
+    ret = KRB5KRB_ERR_GENERIC;
+    if (kcontext->preauth_context == NULL) {
+       return KRB5KRB_ERR_GENERIC;
+    }
+    context = kcontext->preauth_context;
+    if (context == NULL) {
+       return KRB5KRB_ERR_GENERIC;
+    }
+
+    for (i = 0; padata[i] != NULL && padata[i]->pa_type != 0; i++) {
+	out_padata = NULL;
+	for (j = 0; j < context->n_modules; j++) {
+	    module = &context->modules[j];
+	    if (module->pa_type != padata[i]->pa_type) {
+		continue;
+	    }
+	    if (module->client_tryagain == NULL) {
+		continue;
+	    }
+	    if ((*module->client_tryagain)(kcontext,
+					   module->plugin_context,
+					   *module->request_context_pp,
+					   (krb5_get_init_creds_opt *)opte,
+					   client_data_proc,
+					   get_data_rock,
+					   request,
+					   encoded_request_body,
+					   encoded_previous_request,
+					   padata[i],
+					   err_reply,
+					   prompter, prompter_data,
+					   gak_fct, gak_data, salt, s2kparams,
+					   as_key,
+					   &out_padata) == 0) {
+		if (out_padata != NULL) {
+		    int k;
+		    for (k = 0; out_padata[k] != NULL; k++);
+		    grow_pa_list(return_padata, &out_pa_list_size,
+				 out_padata, k);
+		    free(out_padata);
+		    return 0;
+		}
+	    }
+	}
+    }
+    return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_do_preauth(krb5_context context,
+		krb5_kdc_req *request,
+		krb5_data *encoded_request_body,
+		krb5_data *encoded_previous_request,
+		krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
+		krb5_data *salt, krb5_data *s2kparams,
+		krb5_enctype *etype,
+		krb5_keyblock *as_key,
+		krb5_prompter_fct prompter, void *prompter_data,
+		krb5_gic_get_as_key_fct gak_fct, void *gak_data,
+		krb5_preauth_client_rock *get_data_rock,
+		krb5_gic_opt_ext *opte)
+{
+    int h, i, j, out_pa_list_size;
+    int seen_etype_info2 = 0;
+    krb5_pa_data *out_pa = NULL, **out_pa_list = NULL;
+    krb5_data scratch;
+    krb5_etype_info etype_info = NULL;
+    krb5_error_code ret;
+    static const int paorder[] = { PA_INFO, PA_REAL };
+    int realdone;
+
+    if (in_padata == NULL) {
+	*out_padata = NULL;
+	return(0);
+    }
+
+#ifdef DEBUG
+    fprintf (stderr, "salt len=%d", (int) salt->length);
+    if ((int) salt->length > 0)
+	fprintf (stderr, " '%.*s'", salt->length, salt->data);
+    fprintf (stderr, "; preauth data types:");
+    for (i = 0; in_padata[i]; i++) {
+	fprintf (stderr, " %d", in_padata[i]->pa_type);
+    }
+    fprintf (stderr, "\n");
+#endif
+
+    out_pa_list = NULL;
+    out_pa_list_size = 0;
+
+    /* first do all the informational preauths, then the first real one */
+
+    for (h=0; h<(sizeof(paorder)/sizeof(paorder[0])); h++) {
+	realdone = 0;
+	for (i=0; in_padata[i] && !realdone; i++) {
+	    int k, l, etype_found, valid_etype_found;
+	    /*
+	     * This is really gross, but is necessary to prevent
+	     * lossage when talking to a 1.0.x KDC, which returns an
+	     * erroneous PA-PW-SALT when it returns a KRB-ERROR
+	     * requiring additional preauth.
+	     */
+	    switch (in_padata[i]->pa_type) {
+	    case KRB5_PADATA_ETYPE_INFO:
+	    case KRB5_PADATA_ETYPE_INFO2:
+	    {
+		krb5_preauthtype pa_type = in_padata[i]->pa_type;
+		if (etype_info) {
+		    if (seen_etype_info2 || pa_type != KRB5_PADATA_ETYPE_INFO2)
+			continue;
+		    if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
+			krb5_free_etype_info( context, etype_info);
+			etype_info = NULL;
+		    }
+		}
+
+		scratch.length = in_padata[i]->length;
+		scratch.data = (char *) in_padata[i]->contents;
+		if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
+		    seen_etype_info2++;
+		    ret = decode_krb5_etype_info2(&scratch, &etype_info);
+		}
+		else ret = decode_krb5_etype_info(&scratch, &etype_info);
+		if (ret) {
+		    ret = 0; /*Ignore error and etype_info element*/
+		    if (etype_info) 
+		      krb5_free_etype_info( context, etype_info);
+		    etype_info = NULL;
+		    continue;
+		}
+		if (etype_info[0] == NULL) {
+		    krb5_free_etype_info(context, etype_info);
+		    etype_info = NULL;
+		    break;
+		}
+		/*
+		 * Select first etype in our request which is also in
+		 * etype-info (preferring client request ktype order).
+		 */
+		for (etype_found = 0, valid_etype_found = 0, k = 0;
+		     !etype_found && k < request->nktypes; k++) {
+		    for (l = 0; etype_info[l]; l++) {
+			if (etype_info[l]->etype == request->ktype[k]) {
+			    etype_found++;
+			    break;
+			}
+			/* check if program has support for this etype for more
+			 * precise error reporting.
+			 */
+			if (valid_enctype(etype_info[l]->etype))
+			    valid_etype_found++;
+		    }
+		}
+		if (!etype_found) {
+		  if (valid_etype_found) {
+			/* supported enctype but not requested */
+		    ret =  KRB5_CONFIG_ETYPE_NOSUPP;
+		    goto cleanup;
+		  }
+		  else {
+		    /* unsupported enctype */
+		    ret =  KRB5_PROG_ETYPE_NOSUPP;
+		    goto cleanup;
+		  }
+
+		}
+		scratch.data = (char *) etype_info[l]->salt;
+		scratch.length = etype_info[l]->length;
+		krb5_free_data_contents(context, salt);
+		if (scratch.length == KRB5_ETYPE_NO_SALT) 
+		  salt->data = NULL;
+		else
+		    if ((ret = krb5int_copy_data_contents( context, &scratch, salt)) != 0)
+		  goto cleanup;
+		*etype = etype_info[l]->etype;
+		krb5_free_data_contents(context, s2kparams);
+		if ((ret = krb5int_copy_data_contents(context,
+						      &etype_info[l]->s2kparams,
+						      s2kparams)) != 0)
+		  goto cleanup;
+#ifdef DEBUG
+		for (j = 0; etype_info[j]; j++) {
+		    krb5_etype_info_entry *e = etype_info[j];
+		    fprintf (stderr, "etype info %d: etype %d salt len=%d",
+			     j, e->etype, e->length);
+		    if (e->length > 0 && e->length != KRB5_ETYPE_NO_SALT)
+			fprintf (stderr, " '%.*s'", e->length, e->salt);
+		    fprintf (stderr, "\n");
+		}
+#endif
+		break;
+	    }
+	    case KRB5_PADATA_PW_SALT:
+	    case KRB5_PADATA_AFS3_SALT:
+		if (etype_info)
+		    continue;
+		break;
+	    default:
+		;
+	    }
+	    /* Try the internally-provided preauth type list. */
+	    if (!realdone) for (j=0; pa_types[j].type >= 0; j++) {
+		if ((in_padata[i]->pa_type == pa_types[j].type) &&
+		    (pa_types[j].flags & paorder[h])) {
+#ifdef DEBUG
+		    fprintf (stderr, "calling internal function for pa_type "
+			     "%d, flag %d\n", pa_types[j].type, paorder[h]);
+#endif
+		    out_pa = NULL;
+
+		    if ((ret = ((*pa_types[j].fct)(context, request,
+						   in_padata[i], &out_pa,
+						   salt, s2kparams, etype, as_key,
+						   prompter, prompter_data,
+						   gak_fct, gak_data)))) {
+		      goto cleanup;
+		    }
+
+		    ret = grow_pa_list(&out_pa_list, &out_pa_list_size,
+				       &out_pa, 1);
+		    if (ret != 0) {
+			    goto cleanup;
+		    }
+		    if (paorder[h] == PA_REAL)
+			realdone = 1;
+		}
+	    }
+
+	    /* Try to use plugins now. */
+	    if (!realdone) {
+		krb5_init_preauth_context(context);
+		if (context->preauth_context != NULL) {
+		    int module_ret, module_flags;
+#ifdef DEBUG
+		    fprintf (stderr, "trying modules for pa_type %d, flag %d\n",
+			     in_padata[i]->pa_type, paorder[h]);
+#endif
+		    ret = krb5_run_preauth_plugins(context,
+						   paorder[h],
+						   request,
+						   encoded_request_body,
+						   encoded_previous_request,
+						   in_padata[i],
+						   prompter,
+						   prompter_data,
+						   gak_fct,
+						   salt, s2kparams,
+						   gak_data,
+						   get_data_rock,
+						   as_key,
+						   &out_pa_list,
+						   &out_pa_list_size,
+						   &module_ret,
+						   &module_flags,
+						   opte);
+		    if (ret == 0) {
+			if (module_ret == 0) {
+		            if (paorder[h] == PA_REAL) {
+				realdone = 1;
+			    }
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+    *out_padata = out_pa_list;
+    if (etype_info)
+      krb5_free_etype_info(context, etype_info);
+    
+    return(0);
+ cleanup:
+    if (out_pa_list) {
+      out_pa_list[out_pa_list_size++] = NULL;
+      krb5_free_pa_data(context, out_pa_list);
+    }
+    if (etype_info)
+      krb5_free_etype_info(context, etype_info);
+    return (ret);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/princ_comp.c b/krb5-1-6/src/lib/krb5/krb/princ_comp.c
new file mode 100644
index 000000000..cb1a652bd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/princ_comp.c
@@ -0,0 +1,87 @@
+/*
+ * lib/krb5/krb/princ_comp.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * compare two principals, returning a krb5_boolean true if equal, false if
+ * not.
+ */
+
+#include "k5-int.h"
+
+krb5_boolean KRB5_CALLCONV
+krb5_realm_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2)
+{
+    if (krb5_princ_realm(context, princ1)->length != 
+	krb5_princ_realm(context, princ2)->length ||
+	memcmp (krb5_princ_realm(context, princ1)->data, 
+	 	krb5_princ_realm(context, princ2)->data,
+		krb5_princ_realm(context, princ2)->length))
+	return FALSE;
+
+    return TRUE;
+}
+
+krb5_boolean KRB5_CALLCONV
+krb5_principal_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2)
+{
+    register int i;
+    krb5_int32 nelem;
+
+    nelem = krb5_princ_size(context, princ1);
+    if (nelem != krb5_princ_size(context, princ2))
+	return FALSE;
+
+    if (! krb5_realm_compare(context, princ1, princ2))
+	return FALSE;
+
+    for (i = 0; i < (int) nelem; i++) {
+	register const krb5_data *p1 = krb5_princ_component(context, princ1, i);
+	register const krb5_data *p2 = krb5_princ_component(context, princ2, i);
+	if (p1->length != p2->length ||
+	    memcmp(p1->data, p2->data, p1->length))
+	    return FALSE;
+    }
+    return TRUE;
+}
+
+krb5_boolean KRB5_CALLCONV krb5_is_referral_realm(const krb5_data *r)
+{
+    /*
+     * Check for a match with KRB5_REFERRAL_REALM.  Currently this relies
+     * on that string constant being zero-length.  (Unlike principal realm
+     * names, KRB5_REFERRAL_REALM is known to be a string.)
+     */
+#ifdef DEBUG_REFERRALS
+#if 0
+    printf("krb5_is_ref_realm: checking <%s> for referralness: %s\n",
+	   r->data,(r->length==0)?"true":"false");
+#endif
+#endif
+    assert(strlen(KRB5_REFERRAL_REALM)==0);
+    if (r->length==0)
+        return TRUE;
+    else
+        return FALSE;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/rd_cred.c b/krb5-1-6/src/lib/krb5/krb/rd_cred.c
new file mode 100644
index 000000000..a29eb0522
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/rd_cred.c
@@ -0,0 +1,247 @@
+#include "k5-int.h"
+#include "cleanup.h"
+#include "auth_con.h"
+
+#include <stddef.h>           /* NULL */
+#include <stdlib.h>           /* malloc */
+#include <errno.h>            /* ENOMEM */
+
+/*-------------------- decrypt_credencdata --------------------*/
+
+/*
+ * decrypt the enc_part of a krb5_cred
+ */
+static krb5_error_code 
+decrypt_credencdata(krb5_context context, krb5_cred *pcred, krb5_keyblock *pkeyblock, krb5_cred_enc_part *pcredenc)
+{
+    krb5_cred_enc_part  * ppart = NULL;
+    krb5_error_code 	  retval;
+    krb5_data 		  scratch;
+
+    scratch.length = pcred->enc_part.ciphertext.length;
+    if (!(scratch.data = (char *)malloc(scratch.length))) 
+	return ENOMEM;
+
+    if (pkeyblock != NULL) {
+	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);
+    }
+
+    /*  now decode the decrypted stuff */
+    if ((retval = decode_krb5_enc_cred_part(&scratch, &ppart)))
+    	goto cleanup;
+
+    *pcredenc = *ppart;
+    retval = 0;
+
+cleanup:
+    if (ppart != NULL) {
+	memset(ppart, 0, sizeof(*ppart));
+	krb5_xfree(ppart);
+    }
+    memset(scratch.data, 0, scratch.length);
+    krb5_xfree(scratch.data);
+
+    return retval;
+}
+/*----------------------- krb5_rd_cred_basic -----------------------*/
+
+static krb5_error_code 
+krb5_rd_cred_basic(krb5_context context, krb5_data *pcreddata, krb5_keyblock *pkeyblock, krb5_replay_data *replaydata, krb5_creds ***pppcreds)
+{
+    krb5_error_code       retval;
+    krb5_cred 		* pcred;
+    krb5_int32 		  ncreds;
+    krb5_int32 		  i = 0;
+    krb5_cred_enc_part 	  encpart;
+
+    /* decode cred message */
+    if ((retval = decode_krb5_cred(pcreddata, &pcred)))
+    	return retval;
+
+    memset(&encpart, 0, sizeof(encpart));
+
+    if ((retval = decrypt_credencdata(context, pcred, pkeyblock, &encpart)))
+	goto cleanup_cred;
+
+
+    replaydata->timestamp = encpart.timestamp;
+    replaydata->usec = encpart.usec;
+    replaydata->seq = encpart.nonce;
+
+   /*
+    * Allocate the list of creds.  The memory is allocated so that
+    * krb5_free_tgt_creds can be used to free the list.
+    */
+    for (ncreds = 0; pcred->tickets[ncreds]; ncreds++);
+	
+    if ((*pppcreds = 
+        (krb5_creds **)malloc((size_t)(sizeof(krb5_creds *) *
+				       (ncreds + 1)))) == NULL) {
+        retval = ENOMEM;
+        goto cleanup_cred;
+    }
+    (*pppcreds)[0] = NULL;
+
+    /*
+     * For each credential, create a strcture in the list of
+     * credentials and copy the information.
+     */
+    while (i < ncreds) {
+        krb5_cred_info 	* pinfo;
+        krb5_creds 	* pcur;
+	krb5_data	* pdata;
+
+        if ((pcur = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+        }
+
+        (*pppcreds)[i] = pcur;
+        (*pppcreds)[i+1] = 0;
+        pinfo = encpart.ticket_info[i++];
+        memset(pcur, 0, sizeof(krb5_creds));
+
+        if ((retval = krb5_copy_principal(context, pinfo->client,
+					  &pcur->client)))
+	    goto cleanup;
+
+        if ((retval = krb5_copy_principal(context, pinfo->server,
+					  &pcur->server)))
+	    goto cleanup;
+
+      	if ((retval = krb5_copy_keyblock_contents(context, pinfo->session,
+						  &pcur->keyblock)))
+	    goto cleanup;
+
+        if ((retval = krb5_copy_addresses(context, pinfo->caddrs, 
+					  &pcur->addresses)))
+	    goto cleanup;
+
+        if ((retval = encode_krb5_ticket(pcred->tickets[i - 1], &pdata)))
+	    goto cleanup;
+
+	pcur->ticket = *pdata;
+	krb5_xfree(pdata);
+
+
+        pcur->is_skey = FALSE;
+        pcur->magic = KV5M_CREDS;
+        pcur->times = pinfo->times;
+        pcur->ticket_flags = pinfo->flags;
+        pcur->authdata = NULL;   /* not used */
+        memset(&pcur->second_ticket, 0, sizeof(pcur->second_ticket));
+    }
+
+    /*
+     * NULL terminate the list
+     */
+    (*pppcreds)[i] = NULL;
+
+cleanup:
+    if (retval)
+	krb5_free_tgt_creds(context, *pppcreds);
+
+cleanup_cred:
+    krb5_free_cred(context, pcred);
+    krb5_free_cred_enc_part(context, &encpart);
+
+    return retval;
+}
+
+/*----------------------- krb5_rd_cred -----------------------*/
+
+#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
+
+/*
+ * This functions takes as input an KRB_CRED message, validates it, and
+ * outputs the nonce and an array of the forwarded credentials.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, krb5_data *pcreddata, krb5_creds ***pppcreds, krb5_replay_data *outdata)
+{
+    krb5_error_code       retval;
+    krb5_keyblock       * keyblock;
+    krb5_replay_data      replaydata;
+
+    /* Get keyblock */
+    if ((keyblock = auth_context->recv_subkey) == NULL)
+	keyblock = auth_context->keyblock;
+
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+      (outdata == NULL))
+        /* Need a better error */
+        return KRB5_RC_REQUIRED;
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
+      (auth_context->rcache == NULL))
+        return KRB5_RC_REQUIRED;
+
+
+/* If decrypting with the first keyblock we try fails, perhaps the
+ * credentials are stored in the session key so try decrypting with
+    * that.
+*/
+    if ((retval = krb5_rd_cred_basic(context, pcreddata, keyblock,
+				     &replaydata, pppcreds))) {
+	if ((retval = krb5_rd_cred_basic(context, pcreddata,
+					 auth_context->keyblock,
+					 &replaydata, pppcreds))) {
+	    return retval;
+    }
+    }
+    
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+        krb5_donot_replay replay;
+        krb5_timestamp currenttime;
+
+        if ((retval = krb5_timeofday(context, ¤ttime)))
+            goto error;
+
+        if (!in_clock_skew(replaydata.timestamp)) {
+            retval =  KRB5KRB_AP_ERR_SKEW;
+            goto error;
+        }
+
+        if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
+					   "_forw", &replay.client)))
+            goto error;
+
+        replay.server = "";             /* XXX */
+        replay.cusec = replaydata.usec;
+        replay.ctime = replaydata.timestamp;
+        if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
+            krb5_xfree(replay.client);
+            goto error;
+        }
+        krb5_xfree(replay.client);
+    }
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+        if (auth_context->remote_seq_number != replaydata.seq) {
+            retval =  KRB5KRB_AP_ERR_BADORDER;
+            goto error;
+        }
+        auth_context->remote_seq_number++;
+    }
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+        outdata->timestamp = replaydata.timestamp;
+        outdata->usec = replaydata.usec;
+        outdata->seq = replaydata.seq;
+    }
+
+error:;
+    if (retval) {
+    	krb5_free_tgt_creds(context, *pppcreds);
+	*pppcreds = NULL;
+    }
+    return retval;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/rd_error.c b/krb5-1-6/src/lib/krb5/krb/rd_error.c
new file mode 100644
index 000000000..e81727c7c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/rd_error.c
@@ -0,0 +1,49 @@
+/*
+ * lib/krb5/krb/rd_error.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_rd_error() routine
+ */
+
+#include "k5-int.h"
+
+/*
+ *  Parses an error message from enc_errbuf and returns an allocated
+ * structure which contain the error message.
+ *
+ *  Upon return dec_error will point to allocated storage which the
+ * caller should free when finished.
+ * 
+ *  returns system errors
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf, krb5_error **dec_error)
+{
+    if (!krb5_is_krb_error(enc_errbuf))
+	return KRB5KRB_AP_ERR_MSG_TYPE;
+    return(decode_krb5_error(enc_errbuf, dec_error));
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/rd_priv.c b/krb5-1-6/src/lib/krb5/krb/rd_priv.c
new file mode 100644
index 000000000..cf7480779
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/rd_priv.c
@@ -0,0 +1,272 @@
+/*
+ * lib/krb5/krb/rd_priv.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_rd_priv()
+ */
+
+#include "k5-int.h"
+#include "cleanup.h"
+#include "auth_con.h"
+
+#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
+
+/*
+
+Parses a KRB_PRIV message from inbuf, placing the confidential user
+data in *outbuf.
+
+key specifies the key to be used for decryption of the message.
+ 
+remote_addr and local_addr specify the full
+addresses (host and port) of the sender and receiver.
+
+outbuf points to allocated storage which the caller should
+free when finished.
+
+i_vector is used as an initialization vector for the
+encryption, and if non-NULL its contents are replaced with the last
+block of the encrypted data upon exit.
+
+Returns system errors, integrity errors.
+
+*/
+
+static krb5_error_code
+krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyblock *keyblock, const krb5_address *local_addr, const krb5_address *remote_addr, krb5_pointer i_vector, krb5_replay_data *replaydata, krb5_data *outbuf)
+{
+    krb5_error_code 	  retval;
+    krb5_priv 		* privmsg;
+    krb5_data 		  scratch;
+    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;
+
+    /* decode private message */
+    if ((retval = decode_krb5_priv(inbuf, &privmsg)))
+	return retval;
+    
+    if (i_vector) {
+	if ((retval = krb5_c_block_size(context, keyblock->enctype,
+					&blocksize)))
+	    goto cleanup_privmsg;
+
+	ivdata.length = blocksize;
+	ivdata.data = i_vector;
+    }
+
+    scratch.length = privmsg->enc_part.ciphertext.length;
+    if (!(scratch.data = malloc(scratch.length))) {
+	retval = ENOMEM;
+	goto cleanup_privmsg;
+    }
+
+    if ((retval = krb5_c_decrypt(context, keyblock,
+				 KRB5_KEYUSAGE_KRB_PRIV_ENCPART, 
+				 i_vector?&ivdata:0,
+				 &privmsg->enc_part, &scratch)))
+	goto cleanup_scratch;
+
+    /*  now decode the decrypted stuff */
+    if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part)))
+        goto cleanup_scratch;
+
+    if (!krb5_address_compare(context,remote_addr,privmsg_enc_part->s_address)){
+	retval = KRB5KRB_AP_ERR_BADADDR;
+	goto cleanup_data;
+    }
+    
+    if (privmsg_enc_part->r_address) {
+	if (local_addr) {
+	    if (!krb5_address_compare(context, local_addr,
+				      privmsg_enc_part->r_address)) {
+		retval = KRB5KRB_AP_ERR_BADADDR;
+		goto cleanup_data;
+	    }
+	} else {
+	    krb5_address **our_addrs;
+	
+	    if ((retval = krb5_os_localaddr(context, &our_addrs))) {
+		goto cleanup_data;
+	    }
+	    if (!krb5_address_search(context, privmsg_enc_part->r_address, 
+				     our_addrs)) {
+		krb5_free_addresses(context, our_addrs);
+		retval =  KRB5KRB_AP_ERR_BADADDR;
+		goto cleanup_data;
+	    }
+	    krb5_free_addresses(context, our_addrs);
+	}
+    }
+
+    replaydata->timestamp = privmsg_enc_part->timestamp;
+    replaydata->usec = privmsg_enc_part->usec;
+    replaydata->seq = privmsg_enc_part->seq_number;
+
+    /* everything is ok - return data to the user */
+    *outbuf = privmsg_enc_part->user_data;
+    retval = 0;
+
+cleanup_data:;
+    if (retval == 0)
+	privmsg_enc_part->user_data.data = 0;
+    krb5_free_priv_enc_part(context, privmsg_enc_part);
+
+cleanup_scratch:;
+    memset(scratch.data, 0, scratch.length); 
+    krb5_xfree(scratch.data);
+
+cleanup_privmsg:;
+    krb5_xfree(privmsg->enc_part.ciphertext.data); 
+    krb5_xfree(privmsg);
+
+    return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata)
+{
+    krb5_error_code 	  retval;
+    krb5_keyblock       * keyblock;
+    krb5_replay_data	  replaydata;
+
+    /* Get keyblock */
+    if ((keyblock = auth_context->recv_subkey) == NULL)
+	keyblock = auth_context->keyblock;
+
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+      (outdata == NULL))
+	/* Need a better error */
+	return KRB5_RC_REQUIRED;
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
+      (auth_context->rcache == NULL))
+	return KRB5_RC_REQUIRED;
+
+{
+    krb5_address * premote_fulladdr = NULL;
+    krb5_address * plocal_fulladdr = NULL;
+    krb5_address remote_fulladdr;
+    krb5_address local_fulladdr;
+    CLEANUP_INIT(2);
+
+    if (auth_context->local_addr) {
+    	if (auth_context->local_port) {
+            if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
+                                 	      auth_context->local_port, 
+					      &local_fulladdr))){
+                CLEANUP_PUSH(local_fulladdr.contents, free);
+	        plocal_fulladdr = &local_fulladdr;
+            } else {
+	        return retval;
+            }
+	} else {
+            plocal_fulladdr = auth_context->local_addr;
+        }
+    }
+
+    if (auth_context->remote_addr) {
+    	if (auth_context->remote_port) {
+            if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
+                                 	      auth_context->remote_port, 
+					      &remote_fulladdr))){
+                CLEANUP_PUSH(remote_fulladdr.contents, free);
+	        premote_fulladdr = &remote_fulladdr;
+            } else {
+                CLEANUP_DONE();
+	        return retval;
+            }
+	} else {
+            premote_fulladdr = auth_context->remote_addr;
+        }
+    }
+
+    if ((retval = krb5_rd_priv_basic(context, inbuf, keyblock,
+				     plocal_fulladdr,
+				     premote_fulladdr,
+				     auth_context->i_vector,
+				     &replaydata, outbuf))) {
+	CLEANUP_DONE();
+	return retval;
+    }
+
+    CLEANUP_DONE();
+}
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+	krb5_donot_replay replay;
+    	krb5_timestamp currenttime;
+
+	if ((retval = krb5_timeofday(context, ¤ttime)))
+	    goto error;
+
+	if (!in_clock_skew(replaydata.timestamp)) {
+	    retval =  KRB5KRB_AP_ERR_SKEW;
+	    goto error;
+	}
+
+	if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, 
+					   "_priv", &replay.client)))
+	    goto error;
+
+	replay.server = "";		/* XXX */
+	replay.cusec = replaydata.usec;
+	replay.ctime = replaydata.timestamp;
+	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
+	    krb5_xfree(replay.client);
+	    goto error;
+	}
+	krb5_xfree(replay.client);
+    }
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+	if (!krb5int_auth_con_chkseqnum(context, auth_context,
+					replaydata.seq)) {
+	    retval =  KRB5KRB_AP_ERR_BADORDER;
+	    goto error;
+	}
+	auth_context->remote_seq_number++;
+    }
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+	outdata->timestamp = replaydata.timestamp;
+	outdata->usec = replaydata.usec;
+	outdata->seq = replaydata.seq;
+    }
+	
+    /* everything is ok - return data to the user */
+    return 0;
+
+error:;
+    krb5_xfree(outbuf->data);
+    return retval;
+
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/rd_rep.c b/krb5-1-6/src/lib/krb5/krb/rd_rep.c
new file mode 100644
index 000000000..6742d8a03
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/rd_rep.c
@@ -0,0 +1,115 @@
+/*
+ * lib/krb5/krb/rd_rep.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_rd_rep()
+ */
+
+#include "k5-int.h"
+#include "auth_con.h"
+
+/*
+ *  Parses a KRB_AP_REP message, returning its contents.
+ * 
+ *  repl is filled in with with a pointer to allocated memory containing
+ * the fields from the encrypted response. 
+ * 
+ *  the key in kblock is used to decrypt the message.
+ * 
+ *  returns system errors, encryption errors, replay errors
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
+{
+    krb5_error_code 	  retval;
+    krb5_ap_rep 	* reply;
+    krb5_data 	 	  scratch;
+
+    if (!krb5_is_ap_rep(inbuf))
+	return KRB5KRB_AP_ERR_MSG_TYPE;
+
+    /* decode it */
+
+    if ((retval = decode_krb5_ap_rep(inbuf, &reply)))
+	return retval;
+
+    /* put together an eblock for this encryption */
+
+    scratch.length = reply->enc_part.ciphertext.length;
+    if (!(scratch.data = malloc(scratch.length))) {
+	krb5_free_ap_rep(context, reply);
+	return(ENOMEM);
+    }
+
+    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 */
+    retval = decode_krb5_ap_rep_enc_part(&scratch, repl);
+    if (retval)
+	goto clean_scratch;
+
+    /* Check reply fields */
+    if (((*repl)->ctime != auth_context->authentp->ctime) ||
+      ((*repl)->cusec != auth_context->authentp->cusec)) {
+	retval = KRB5_MUTUAL_FAILED;
+	goto clean_scratch;
+    }
+
+    /* Set auth subkey */
+    if ((*repl)->subkey) {
+	if (auth_context->recv_subkey) {
+	    krb5_free_keyblock(context, auth_context->recv_subkey);
+	    auth_context->recv_subkey = NULL;
+	}
+	retval = krb5_copy_keyblock(context, (*repl)->subkey,
+				    &auth_context->recv_subkey);
+	if (retval)
+	    goto clean_scratch;
+	if (auth_context->send_subkey) {
+	    krb5_free_keyblock(context, auth_context->send_subkey);
+	    auth_context->send_subkey = NULL;
+	}
+	retval = krb5_copy_keyblock(context, (*repl)->subkey,
+				    &auth_context->send_subkey);
+	if (retval) {
+	    krb5_free_keyblock(context, auth_context->send_subkey);
+	    auth_context->send_subkey = NULL;
+	}
+    }
+
+    /* Get remote sequence number */
+    auth_context->remote_seq_number = (*repl)->seq_number;
+
+clean_scratch:
+    memset(scratch.data, 0, scratch.length); 
+
+    krb5_free_ap_rep(context, reply);
+    free(scratch.data);
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/rd_req.c b/krb5-1-6/src/lib/krb5/krb/rd_req.c
new file mode 100644
index 000000000..9a2f4589d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/rd_req.c
@@ -0,0 +1,117 @@
+/*
+ * lib/krb5/krb/rd_req.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_rd_req()
+ */
+
+#include "k5-int.h"
+#include "auth_con.h"
+
+/*
+ *  Parses a KRB_AP_REQ message, returning its contents.
+ * 
+ *  server specifies the expected server's name for the ticket.
+ * 
+ *  keyproc specifies a procedure to generate a decryption key for the
+ *  ticket.  If keyproc is non-NULL, keyprocarg is passed to it, and the result
+ *  used as a decryption key. If keyproc is NULL, then fetchfrom is checked;
+ *  if it is non-NULL, it specifies a parameter name from which to retrieve the
+ *  decryption key.  If fetchfrom is NULL, then the default key store is
+ *  consulted.
+ * 
+ *  returns system errors, encryption errors, replay errors
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket)
+                 	          
+                                     
+                    	         
+                                 	/* XXX do we really need this */
+               		         
+              		                  
+               	           
+{
+    krb5_error_code 	  retval;
+    krb5_ap_req 	* request;
+    krb5_auth_context	  new_auth_context;
+    krb5_keytab           new_keytab = NULL;
+
+    if (!krb5_is_ap_req(inbuf))
+	return KRB5KRB_AP_ERR_MSG_TYPE;
+    if ((retval = decode_krb5_ap_req(inbuf, &request))) {
+    	switch (retval) {
+	case KRB5_BADMSGTYPE:
+	    return KRB5KRB_AP_ERR_BADVERSION; 
+	default:
+	    return(retval);
+	}
+    }
+
+    /* Get an auth context if necessary. */
+    new_auth_context = NULL;
+    if (*auth_context == NULL) {
+	if ((retval = krb5_auth_con_init(context, &new_auth_context)))
+	    goto cleanup_request;
+        *auth_context = new_auth_context;
+    }
+
+    if (!server) {
+	server = request->ticket->server;
+    }
+    /* Get an rcache if necessary. */
+    if (((*auth_context)->rcache == NULL)
+	&& ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME)
+&& server) {
+	if ((retval = krb5_get_server_rcache(context,
+     krb5_princ_component(context,server,0), &(*auth_context)->rcache)))
+	    goto cleanup_auth_context;
+    }
+
+    /* Get a keytab if necessary. */
+    if (keytab == NULL) {
+	if ((retval = krb5_kt_default(context, &new_keytab)))
+	    goto cleanup_auth_context;
+	keytab = new_keytab;
+    }
+
+    retval = krb5_rd_req_decoded(context, auth_context, request, server, 
+				 keytab, ap_req_options, ticket);
+
+    if (new_keytab != NULL)
+        (void) krb5_kt_close(context, new_keytab);
+
+cleanup_auth_context:
+    if (new_auth_context && retval) {
+	krb5_auth_con_free(context, new_auth_context);
+	*auth_context = NULL;
+    }
+
+cleanup_request:
+    krb5_free_ap_req(context, request);
+    return retval;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/rd_req_dec.c b/krb5-1-6/src/lib/krb5/krb/rd_req_dec.c
new file mode 100644
index 000000000..d23ab6b10
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/rd_req_dec.c
@@ -0,0 +1,453 @@
+/*
+ * lib/krb5/krb/rd_req_dec.c
+ *
+ * Copyright (c) 1994 CyberSAFE Corporation.
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * Neither M.I.T., the Open Computing Security Group, nor
+ * CyberSAFE Corporation make any representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_rd_req_decoded()
+ */
+
+#include "k5-int.h"
+#include "auth_con.h"
+
+/*
+ * essentially the same as krb_rd_req, but uses a decoded AP_REQ as
+ * the input rather than an encoded input.
+ */
+/*
+ *  Parses a KRB_AP_REQ message, returning its contents.
+ * 
+ *  server specifies the expected server's name for the ticket; if NULL, then
+ *  any server will be accepted if the key can be found, and the caller should
+ *  verify that the principal is something it trusts.
+ * 
+ *  rcache specifies a replay detection cache used to store authenticators and
+ *  server names
+ * 
+ *  keyproc specifies a procedure to generate a decryption key for the
+ *  ticket.  If keyproc is non-NULL, keyprocarg is passed to it, and the result
+ *  used as a decryption key. If keyproc is NULL, then fetchfrom is checked;
+ *  if it is non-NULL, it specifies a parameter name from which to retrieve the
+ *  decryption key.  If fetchfrom is NULL, then the default key store is
+ *  consulted.
+ * 
+ *  authdat is set to point at allocated storage structures; the caller
+ *  should free them when finished. 
+ * 
+ *  returns system errors, encryption errors, replay errors
+ */
+
+static krb5_error_code decrypt_authenticator
+	(krb5_context, const krb5_ap_req *, krb5_authenticator **,
+		   int);
+
+#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
+
+static krb5_error_code
+krb5_rd_req_decrypt_tkt_part(krb5_context context, const krb5_ap_req *req, krb5_keytab keytab)
+{
+    krb5_error_code 	  retval;
+    krb5_enctype 	  enctype;
+    krb5_keytab_entry 	  ktent;
+
+    enctype = req->ticket->enc_part.enctype;
+
+    if ((retval = krb5_kt_get_entry(context, keytab, req->ticket->server,
+				    req->ticket->enc_part.kvno,
+				    enctype, &ktent)))
+	return retval;
+
+    retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket);
+    /* Upon error, Free keytab entry first, then return */
+
+    (void) krb5_kt_free_entry(context, &ktent);
+    return retval;
+}
+
+static krb5_error_code
+krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
+			const krb5_ap_req *req, krb5_const_principal server,
+			krb5_keytab keytab, krb5_flags *ap_req_options,
+			krb5_ticket **ticket, int check_valid_flag)
+{
+    krb5_error_code 	  retval = 0;
+    krb5_timestamp 	  currenttime;
+    krb5_principal_data princ_data;
+    
+    req->ticket->enc_part2 == NULL;
+    if (server && krb5_is_referral_realm(&server->realm)) {
+	char *realm;
+	princ_data = *server;
+	server = &princ_data;
+	retval = krb5_get_default_realm(context, &realm);
+	if (retval)
+	    return retval;
+	princ_data.realm.data = realm;
+	princ_data.realm.length = strlen(realm);
+    }
+    if (server && !krb5_principal_compare(context, server, req->ticket->server)) {
+	char *found_name = 0, *wanted_name = 0;
+	if (krb5_unparse_name(context, server, &wanted_name) == 0
+	    && krb5_unparse_name(context, req->ticket->server, &found_name) == 0)
+	    krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC,
+				   "Wrong principal in request (found %s, wanted %s)",
+				   found_name, wanted_name);
+	krb5_free_unparsed_name(context, wanted_name);
+	krb5_free_unparsed_name(context, found_name);
+	retval =  KRB5KRB_AP_WRONG_PRINC;
+	goto cleanup;
+    }
+
+    /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
+       do we need special processing here ?	*/
+
+    /* decrypt the ticket */
+    if ((*auth_context)->keyblock) { /* User to User authentication */
+    	if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock,
+					    req->ticket)))
+goto cleanup;
+	krb5_free_keyblock(context, (*auth_context)->keyblock);
+	(*auth_context)->keyblock = NULL;
+    } else {
+    	if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab)))
+	    goto cleanup;
+    }
+
+    /* 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),
+					check_valid_flag)))
+	goto cleanup;
+
+    if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
+				req->ticket->enc_part2->client)) {
+	retval = KRB5KRB_AP_ERR_BADMATCH;
+	goto cleanup;
+    }
+
+    if ((*auth_context)->remote_addr && 
+      !krb5_address_search(context, (*auth_context)->remote_addr, 
+			   req->ticket->enc_part2->caddrs)) {
+	retval = KRB5KRB_AP_ERR_BADADDR;
+	goto cleanup;
+    }
+
+    /* okay, now check cross-realm policy */
+
+#if defined(_SINGLE_HOP_ONLY)
+
+    /* Single hop cross-realm tickets only */
+
+    { 
+	krb5_transited *trans = &(req->ticket->enc_part2->transited);
+
+      	/* If the transited list is empty, then we have at most one hop */
+      	if (trans->tr_contents.data && trans->tr_contents.data[0])
+            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+    }
+
+#elif defined(_NO_CROSS_REALM)
+
+    /* No cross-realm tickets */
+
+    { 
+	char		* lrealm;
+      	krb5_data      	* realm;
+      	krb5_transited 	* trans;
+  
+	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
+	trans = &(req->ticket->enc_part2->transited);
+
+	/*
+      	 * If the transited list is empty, then we have at most one hop 
+      	 * So we also have to check that the client's realm is the local one 
+	 */
+      	krb5_get_default_realm(context, &lrealm);
+      	if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
+          strlen(lrealm) != realm->length ||
+          memcmp(lrealm, realm->data, strlen(lrealm))) {
+            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+      	}
+      	free(lrealm);
+    }
+
+#else
+
+    /* Hierarchical Cross-Realm */
+  
+    {
+      	krb5_data      * realm;
+      	krb5_transited * trans;
+  
+	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
+	trans = &(req->ticket->enc_part2->transited);
+
+	/*
+      	 * If the transited list is not empty, then check that all realms 
+      	 * transited are within the hierarchy between the client's realm  
+      	 * and the local realm.                                        
+  	 */
+	if (trans->tr_contents.data && trans->tr_contents.data[0]) {
+	    retval = krb5_check_transited_list(context, &(trans->tr_contents), 
+					       realm,
+					       krb5_princ_realm (context,
+								 server));
+      	}
+    }
+
+#endif
+
+    if (retval)  goto cleanup;
+
+    /* only check rcache if sender has provided one---some services
+       may not be able to use replay caches (such as datagram servers) */
+
+    if ((*auth_context)->rcache) {
+	krb5_donot_replay  rep;
+        krb5_tkt_authent   tktauthent;
+
+	tktauthent.ticket = req->ticket;	
+	tktauthent.authenticator = (*auth_context)->authentp;
+	if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
+	    retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
+	    krb5_xfree(rep.server);
+	    krb5_xfree(rep.client);
+	}
+
+	if (retval)
+	    goto cleanup;
+    }
+
+    retval = krb5_validate_times(context, &req->ticket->enc_part2->times);
+    if (retval != 0)
+	    goto cleanup;
+
+    if ((retval = krb5_timeofday(context, ¤ttime)))
+	goto cleanup;
+
+    if (!in_clock_skew((*auth_context)->authentp->ctime)) {
+	retval = KRB5KRB_AP_ERR_SKEW;
+	goto cleanup;
+    }
+
+    if (check_valid_flag) {
+      if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) {
+	retval = KRB5KRB_AP_ERR_TKT_INVALID;
+	goto cleanup;
+      }
+    }
+
+    /* 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) {
+	int etype;
+	/* check against the default set */
+	if ((!krb5_is_permitted_enctype(context,
+					etype = req->ticket->enc_part.enctype)) ||
+	    (!krb5_is_permitted_enctype(context,
+					etype = req->ticket->enc_part2->session->enctype)) ||
+	    (((*auth_context)->authentp->subkey) &&
+	     !krb5_is_permitted_enctype(context,
+					etype = (*auth_context)->authentp->subkey->enctype))) {
+	    char enctype_name[30];
+	    retval = KRB5_NOPERM_ETYPE;
+	    if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0)
+		krb5_set_error_message(context, retval,
+				       "Encryption type %s not permitted",
+				       enctype_name);
+	    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]) {
+	    char enctype_name[30];
+	    retval = KRB5_NOPERM_ETYPE;
+	    if (krb5_enctype_to_string(req->ticket->enc_part.enctype,
+				       enctype_name, sizeof(enctype_name)) == 0)
+		krb5_set_error_message(context, retval,
+				       "Encryption type %s not permitted",
+				       enctype_name);
+	    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]) {
+	    char enctype_name[30];
+	    retval = KRB5_NOPERM_ETYPE;
+	    if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype,
+				       enctype_name, sizeof(enctype_name)) == 0)
+		krb5_set_error_message(context, retval,
+				       "Encryption type %s not permitted",
+				       enctype_name);
+	    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]) {
+		char enctype_name[30];
+		retval = KRB5_NOPERM_ETYPE;
+		if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype,
+					   enctype_name,
+					   sizeof(enctype_name)) == 0)
+		    krb5_set_error_message(context, retval,
+					   "Encryption type %s not permitted",
+					   enctype_name);
+		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)->recv_subkey))))
+	    goto cleanup;
+	retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey,
+				    &((*auth_context)->send_subkey));
+	if (retval) {
+	    krb5_free_keyblock(context, (*auth_context)->recv_subkey);
+	    (*auth_context)->recv_subkey = NULL;
+	    goto cleanup;
+	}
+    } else {
+	(*auth_context)->recv_subkey = 0;
+	(*auth_context)->send_subkey = 0;
+    }
+
+    if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session,
+				     &((*auth_context)->keyblock))))
+	goto cleanup;
+
+    /*
+     * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used 
+     * then the default sequence number is the one's complement of the
+     * sequence number sent ot us.
+     */
+    if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && 
+      (*auth_context)->remote_seq_number) {
+	(*auth_context)->local_seq_number ^= 
+	  (*auth_context)->remote_seq_number;
+    }
+
+    if (ticket)
+   	if ((retval = krb5_copy_ticket(context, req->ticket, ticket)))
+	    goto cleanup;
+    if (ap_req_options)
+    	*ap_req_options = req->ap_options;
+    retval = 0;
+    
+cleanup:
+    if (server == &princ_data)
+	krb5_free_default_realm(context, princ_data.realm.data);
+    if (retval) {
+	/* only free if we're erroring out...otherwise some
+	   applications will need the output. */
+	if (req->ticket->enc_part2)
+	    krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
+	req->ticket->enc_part2 = NULL;
+    }
+    return retval;
+}
+
+krb5_error_code
+krb5_rd_req_decoded(krb5_context context, krb5_auth_context *auth_context,
+		    const krb5_ap_req *req, krb5_const_principal server,
+		    krb5_keytab keytab, krb5_flags *ap_req_options,
+		    krb5_ticket **ticket)
+{
+  krb5_error_code retval;
+  retval = krb5_rd_req_decoded_opt(context, auth_context,
+				   req, server, keytab, 
+				   ap_req_options, ticket,
+				   1); /* check_valid_flag */
+  return retval;
+}
+
+krb5_error_code
+krb5_rd_req_decoded_anyflag(krb5_context context,
+			    krb5_auth_context *auth_context,
+			    const krb5_ap_req *req,
+			    krb5_const_principal server, krb5_keytab keytab,
+			    krb5_flags *ap_req_options, krb5_ticket **ticket)
+{
+  krb5_error_code retval;
+  retval = krb5_rd_req_decoded_opt(context, auth_context,
+				   req, server, keytab, 
+				   ap_req_options, ticket,
+				   0); /* don't check_valid_flag */
+  return retval;
+}
+
+static krb5_error_code
+decrypt_authenticator(krb5_context context, const krb5_ap_req *request,
+		      krb5_authenticator **authpp, int is_ap_req)
+{
+    krb5_authenticator *local_auth;
+    krb5_error_code retval;
+    krb5_data scratch;
+    krb5_keyblock *sesskey;
+
+    sesskey = request->ticket->enc_part2->session;
+
+    scratch.length = request->authenticator.ciphertext.length;
+    if (!(scratch.data = malloc(scratch.length)))
+	return(ENOMEM);
+
+    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);
+    }
+
+#define clean_scratch() {memset(scratch.data, 0, scratch.length); \
+free(scratch.data);}
+
+    /*  now decode the decrypted stuff */
+    if (!(retval = decode_krb5_authenticator(&scratch, &local_auth))) {
+	*authpp = local_auth;
+    }
+    clean_scratch();
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/rd_safe.c b/krb5-1-6/src/lib/krb5/krb/rd_safe.c
new file mode 100644
index 000000000..15dc6dccc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/rd_safe.c
@@ -0,0 +1,275 @@
+/*
+ * lib/krb5/krb/rd_safe.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_rd_safe()
+ */
+
+#include "k5-int.h"
+#include "cleanup.h"
+#include "auth_con.h"
+
+#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
+
+/*
+ parses a KRB_SAFE message from inbuf, placing the integrity-protected user
+ data in *outbuf.
+
+ key specifies the key to be used for decryption of the message.
+ 
+ sender_addr and recv_addr specify the full addresses (host and port) of
+ the sender and receiver.
+
+ outbuf points to allocated storage which the caller should free when finished.
+
+ returns system errors, integrity errors
+ */
+static krb5_error_code
+krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyblock *keyblock, const krb5_address *recv_addr, const krb5_address *sender_addr, krb5_replay_data *replaydata, krb5_data *outbuf)
+{
+    krb5_error_code 	  retval;
+    krb5_safe 		* message;
+    krb5_data safe_body;
+    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;
+
+    if ((retval = decode_krb5_safe_with_body(inbuf, &message, &safe_body)))
+	return retval;
+
+    if (!krb5_c_valid_cksumtype(message->checksum->checksum_type)) {
+	retval = KRB5_PROG_SUMTYPE_NOSUPP;
+	goto cleanup;
+    }
+    if (!krb5_c_is_coll_proof_cksum(message->checksum->checksum_type) ||
+	!krb5_c_is_keyed_cksum(message->checksum->checksum_type)) {
+	retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
+	goto cleanup;
+    }
+
+    if (!krb5_address_compare(context, sender_addr, message->s_address)) {
+	retval = KRB5KRB_AP_ERR_BADADDR;
+	goto cleanup;
+    }
+
+    if (message->r_address) {
+	if (recv_addr) {
+	    if (!krb5_address_compare(context, recv_addr, message->r_address)) {
+		retval = KRB5KRB_AP_ERR_BADADDR;
+		goto cleanup;
+	    }
+	} else {
+	    krb5_address **our_addrs;
+	
+	    if ((retval = krb5_os_localaddr(context, &our_addrs)))
+		goto cleanup;
+	    
+	    if (!krb5_address_search(context, message->r_address, our_addrs)) {
+		krb5_free_addresses(context, our_addrs);
+		retval = KRB5KRB_AP_ERR_BADADDR;
+		goto cleanup;
+	    }
+	    krb5_free_addresses(context, our_addrs);
+	}
+    }
+
+    /* verify the checksum */
+    /*
+     * In order to recreate what was checksummed, we regenerate the message
+     * without checksum and then have the cryptographic subsystem verify
+     * the checksum for us.  This is because some checksum methods have
+     * a confounder encrypted as part of the checksum.
+     */
+    his_cksum = message->checksum;
+
+    our_cksum.length = 0;
+    our_cksum.checksum_type = 0;
+    our_cksum.contents = &zero_octet;
+
+    message->checksum = &our_cksum;
+
+    if ((retval = encode_krb5_safe_with_body(message, &safe_body, &scratch)))
+	goto cleanup;
+
+    message->checksum = his_cksum;
+			 
+    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 (!valid) {
+	/*
+	 * Checksum over only the KRB-SAFE-BODY, like RFC 1510 says, in
+	 * case someone actually implements it correctly.
+	 */
+	retval = krb5_c_verify_checksum(context, keyblock,
+					KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
+					&safe_body, his_cksum, &valid);
+	if (!valid) {
+	    retval = KRB5KRB_AP_ERR_MODIFIED;
+	    goto cleanup;
+	}
+    }
+
+    replaydata->timestamp = message->timestamp;
+    replaydata->usec = message->usec;
+    replaydata->seq = message->seq_number;
+
+    *outbuf = message->user_data;
+    message->user_data.data = NULL;
+    retval = 0;
+    
+cleanup:
+    krb5_free_safe(context, message);
+    return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata)
+{
+    krb5_error_code 	  retval;
+    krb5_keyblock	* keyblock;
+    krb5_replay_data	  replaydata;
+
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+      (outdata == NULL)) 
+	/* Need a better error */
+	return KRB5_RC_REQUIRED;
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
+      (auth_context->rcache == NULL)) 
+	return KRB5_RC_REQUIRED;
+
+    /* Get keyblock */
+    if ((keyblock = auth_context->recv_subkey) == NULL)
+	keyblock = auth_context->keyblock;
+
+{
+    krb5_address * premote_fulladdr = NULL;
+    krb5_address * plocal_fulladdr = NULL;
+    krb5_address remote_fulladdr;
+    krb5_address local_fulladdr;
+    CLEANUP_INIT(2);
+
+    if (auth_context->local_addr) {
+    	if (auth_context->local_port) {
+            if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
+                                 	      auth_context->local_port, 
+					      &local_fulladdr))){
+                CLEANUP_PUSH(local_fulladdr.contents, free);
+	        plocal_fulladdr = &local_fulladdr;
+            } else {
+	        return retval;
+            }
+	} else {
+            plocal_fulladdr = auth_context->local_addr;
+        }
+    }
+
+    if (auth_context->remote_addr) {
+    	if (auth_context->remote_port) {
+            if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
+                                 	      auth_context->remote_port, 
+					      &remote_fulladdr))){
+                CLEANUP_PUSH(remote_fulladdr.contents, free);
+	        premote_fulladdr = &remote_fulladdr;
+            } else {
+	        return retval;
+            }
+	} else {
+            premote_fulladdr = auth_context->remote_addr;
+        }
+    }
+
+    if ((retval = krb5_rd_safe_basic(context, inbuf, keyblock,
+				     plocal_fulladdr, premote_fulladdr,
+				     &replaydata, outbuf))) {
+	CLEANUP_DONE();
+	return retval;
+    }
+
+    CLEANUP_DONE();
+}
+
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+	krb5_donot_replay replay;
+    	krb5_timestamp currenttime;
+
+	if ((retval = krb5_timeofday(context, ¤ttime)))
+	    goto error;
+
+	if (!in_clock_skew(replaydata.timestamp)) {
+	    retval =  KRB5KRB_AP_ERR_SKEW;
+	    goto error;
+	}
+
+	if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, 
+					   "_safe", &replay.client)))
+	    goto error;
+
+	replay.server = "";		/* XXX */
+	replay.cusec = replaydata.usec;
+	replay.ctime = replaydata.timestamp;
+	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
+	    krb5_xfree(replay.client);
+	    goto error;
+	}
+	krb5_xfree(replay.client);
+    }
+
+    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+	if (!krb5int_auth_con_chkseqnum(context, auth_context,
+					replaydata.seq)) {
+	    retval =  KRB5KRB_AP_ERR_BADORDER;
+	    goto error;
+	}
+	auth_context->remote_seq_number++;
+    }
+
+    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+	outdata->timestamp = replaydata.timestamp;
+	outdata->usec = replaydata.usec;
+	outdata->seq = replaydata.seq;
+    }
+	
+    /* everything is ok - return data to the user */
+    return 0;
+
+error:
+    krb5_xfree(outbuf->data);
+    return retval;
+
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/recvauth.c b/krb5-1-6/src/lib/krb5/krb/recvauth.c
new file mode 100644
index 000000000..92bcad7a9
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/recvauth.c
@@ -0,0 +1,266 @@
+/*
+ * lib/krb5/krb/recvauth.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * convenience sendauth/recvauth functions
+ */
+
+#include "k5-int.h"
+#include "auth_con.h"
+#include "com_err.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+static const char sendauth_version[] = "KRB5_SENDAUTH_V1.0";
+
+static krb5_error_code
+recvauth_common(krb5_context context,
+		krb5_auth_context * auth_context,
+		/* IN */
+		krb5_pointer fd,
+		char *appl_version,
+		krb5_principal server,
+		krb5_int32 flags,
+		krb5_keytab keytab,
+		/* OUT */
+		krb5_ticket ** ticket,
+		krb5_data *version)
+{
+    krb5_auth_context	  new_auth_context;
+    krb5_flags		  ap_option;
+    krb5_error_code	  retval, problem;
+    krb5_data		  inbuf;
+    krb5_data		  outbuf;
+    krb5_rcache 	  rcache = 0;
+    krb5_octet		  response;
+    krb5_data		  null_server;
+    int                   need_error_free = 0;
+    int			  local_rcache = 0, local_authcon = 0;
+	
+	/*
+	 * Zero out problem variable.  If problem is set at the end of
+	 * the intial version negotiation section, it means that we
+	 * need to send an error code back to the client application
+	 * and exit.
+	 */
+	problem = 0;
+
+	if (!(flags & KRB5_RECVAUTH_SKIP_VERSION)) {
+	    /*
+	     * First read the sendauth version string and check it.
+	     */
+	    if ((retval = krb5_read_message(context, fd, &inbuf)))
+		return(retval);
+	    if (strcmp(inbuf.data, sendauth_version)) {
+		problem = KRB5_SENDAUTH_BADAUTHVERS;
+	    }
+	    krb5_xfree(inbuf.data);
+	}
+	if (flags & KRB5_RECVAUTH_BADAUTHVERS)
+	    problem = KRB5_SENDAUTH_BADAUTHVERS;
+	
+	/*
+	 * Do the same thing for the application version string.
+	 */
+	if ((retval = krb5_read_message(context, fd, &inbuf)))
+		return(retval);
+	if (appl_version && strcmp(inbuf.data, appl_version)) {
+		if (!problem)
+			problem = KRB5_SENDAUTH_BADAPPLVERS;
+	}
+	if (version && !problem)
+	    *version = inbuf;
+	else
+	    krb5_xfree(inbuf.data);
+	/*
+	 * OK, now check the problem variable.  If it's zero, we're
+	 * fine and we can continue.  Otherwise, we have to signal an
+	 * error to the client side and bail out.
+	 */
+	switch (problem) {
+	case 0:
+		response = 0;
+		break;
+	case KRB5_SENDAUTH_BADAUTHVERS:
+		response = 1;
+		break;
+	case KRB5_SENDAUTH_BADAPPLVERS:
+		response = 2;
+		break;
+	default:
+		/*
+		 * Should never happen!
+		 */
+		response = 255;
+#ifdef SENDAUTH_DEBUG
+		fprintf(stderr, "Programming botch in recvauth!  problem = %d",
+			problem);
+		abort();
+#endif
+		break;
+	}
+	/*
+	 * Now we actually write the response.  If the response is non-zero,
+	 * exit with a return value of problem
+	 */
+	if ((krb5_net_write(context, *((int *)fd), (char *)&response, 1)) < 0) {
+		return(problem); /* We'll return the top-level problem */
+	}
+	if (problem)
+	    return(problem);
+
+    /* We are clear of errors here */
+
+    /*
+     * Now, let's read the AP_REQ message and decode it
+     */
+    if ((retval = krb5_read_message(context, fd, &inbuf)))
+        return retval;
+
+    if (*auth_context == NULL) {
+	problem = krb5_auth_con_init(context, &new_auth_context);
+	*auth_context = new_auth_context;
+	local_authcon = 1;
+    }
+    krb5_auth_con_getrcache(context, *auth_context, &rcache);
+    if ((!problem) && rcache == NULL) {
+        /*
+         * Setup the replay cache.
+         */
+        if (server) {
+            problem = krb5_get_server_rcache(context, 
+			krb5_princ_component(context, server, 0), &rcache);
+        } else {
+    	    null_server.length = 7;
+    	    null_server.data = "default";
+    	    problem = krb5_get_server_rcache(context, &null_server, &rcache);
+        }
+        if (!problem) 
+	    problem = krb5_auth_con_setrcache(context, *auth_context, rcache);
+	local_rcache = 1;
+    }
+    if (!problem) {
+	problem = krb5_rd_req(context, auth_context, &inbuf, server,
+			      keytab, &ap_option, ticket);
+	krb5_xfree(inbuf.data);
+    }
+	
+    /*
+     * If there was a problem, send back a krb5_error message,
+     * preceeded by the length of the krb5_error message.  If
+     * everything's ok, send back 0 for the length.
+     */
+    if (problem) {
+	krb5_error	error;
+	const	char *message;
+
+	memset((char *)&error, 0, sizeof(error));
+	krb5_us_timeofday(context, &error.stime, &error.susec);
+	if(server) 
+		error.server = server;
+	else {
+		/* If this fails - ie. ENOMEM we are hosed
+		   we cannot even send the error if we wanted to... */
+		(void) krb5_parse_name(context, "????", &error.server);
+		need_error_free = 1;
+	}
+
+	error.error = problem - ERROR_TABLE_BASE_krb5;
+	if (error.error > 127)
+		error.error = KRB_ERR_GENERIC;
+	message = error_message(problem);
+	error.text.length  = strlen(message) + 1;
+	if (!(error.text.data = malloc(error.text.length))) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	strcpy(error.text.data, message);
+	if ((retval = krb5_mk_error(context, &error, &outbuf))) {
+	    free(error.text.data);
+	    goto cleanup;
+	}
+	free(error.text.data);
+	if(need_error_free) 
+		krb5_free_principal(context, error.server);
+
+    } else {
+	outbuf.length = 0;
+	outbuf.data = 0;
+    }
+
+    retval = krb5_write_message(context, fd, &outbuf);
+    if (outbuf.data) {
+	krb5_xfree(outbuf.data);
+    	/* We sent back an error, we need cleanup then return */
+    	retval = problem;
+    	goto cleanup;
+    }
+    if (retval)
+	goto cleanup;
+
+    /* Here lies the mutual authentication stuff... */
+    if ((ap_option & AP_OPTS_MUTUAL_REQUIRED)) {
+	if ((retval = krb5_mk_rep(context, *auth_context, &outbuf))) {
+	    return(retval);
+	}
+	retval = krb5_write_message(context, fd, &outbuf);
+	krb5_xfree(outbuf.data);
+    }
+
+cleanup:;
+    if (retval) {
+	if (local_authcon) {
+	    krb5_auth_con_free(context, *auth_context);
+	} else if (local_rcache && rcache != NULL) {
+	    krb5_rc_close(context, rcache);
+	    krb5_auth_con_setrcache(context, *auth_context, NULL);
+	}
+    }
+    return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_recvauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal server, krb5_int32 flags, krb5_keytab keytab, krb5_ticket **ticket)
+{
+    return recvauth_common (context, auth_context, fd, appl_version,
+			    server, flags, keytab, ticket, 0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_recvauth_version(krb5_context context,
+		      krb5_auth_context *auth_context,
+		      /* IN */
+		      krb5_pointer fd,
+		      krb5_principal server,
+		      krb5_int32 flags,
+		      krb5_keytab keytab,
+		      /* OUT */
+		      krb5_ticket **ticket,
+		      krb5_data *version)
+{
+    return recvauth_common (context, auth_context, fd, 0,
+			    server, flags, keytab, ticket, version);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/send_tgs.c b/krb5-1-6/src/lib/krb5/krb/send_tgs.c
new file mode 100644
index 000000000..aa881e16f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/send_tgs.c
@@ -0,0 +1,309 @@
+/*
+ * lib/krb5/krb/send_tgs.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_send_tgs()
+ */
+
+#include "k5-int.h"
+
+/*
+ Sends a request to the TGS and waits for a response.
+ options is used for the options in the KRB_TGS_REQ.
+ timestruct values are used for from, till, rtime " " "
+ enctype is used for enctype " " ", and to encrypt the authorization data, 
+ sname is used for sname " " "
+ addrs, if non-NULL, is used for addresses " " "
+ authorization_dat, if non-NULL, is used for authorization_dat " " "
+ second_ticket, if required by options, is used for the 2nd ticket in the req.
+ in_cred is used for the ticket & session key in the KRB_AP_REQ header " " "
+ (the KDC realm is extracted from in_cred->server's realm)
+ 
+ The response is placed into *rep.
+ rep->response.data is set to point at allocated storage which should be
+ freed by the caller when finished.
+
+ returns system errors
+ */
+static krb5_error_code 
+krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cred, krb5_data *outbuf)
+{   
+    krb5_error_code       retval;
+    krb5_checksum         checksum;
+    krb5_authenticator 	  authent;
+    krb5_ap_req 	  request;
+    krb5_data		* scratch;
+    krb5_data           * toutbuf;
+
+    /* Generate checksum */
+    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);
+    }
+
+    /* gen authenticator */
+    authent.subkey = 0;
+    authent.seq_number = 0;
+    authent.checksum = &checksum;
+    authent.client = in_cred->client;
+    authent.authorization_data = in_cred->authdata;
+    if ((retval = krb5_us_timeofday(context, &authent.ctime,
+				    &authent.cusec))) {
+        free(checksum.contents);
+	return(retval);
+    }
+
+    /* encode the authenticator */
+    if ((retval = encode_krb5_authenticator(&authent, &scratch))) {
+        free(checksum.contents);
+	return(retval);
+    }
+
+    free(checksum.contents);
+
+    request.authenticator.ciphertext.data = 0;
+    request.authenticator.kvno = 0;
+    request.ap_options = 0;
+    request.ticket = 0;
+
+    if ((retval = decode_krb5_ticket(&(in_cred)->ticket, &request.ticket)))
+	/* Cleanup scratch and scratch data */
+        goto cleanup_data;
+
+    /* call the encryption routine */ 
+    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;
+    krb5_xfree(toutbuf);
+
+
+    memset(request.authenticator.ciphertext.data, 0,
+           request.authenticator.ciphertext.length);
+    free(request.authenticator.ciphertext.data);
+
+cleanup_ticket:
+    krb5_free_ticket(context, request.ticket);
+
+cleanup_data:
+    memset(scratch->data, 0, scratch->length);
+    free(scratch->data);
+
+    free(scratch);
+
+    return retval;
+}
+
+krb5_error_code
+krb5_send_tgs(krb5_context context, krb5_flags kdcoptions,
+	      const krb5_ticket_times *timestruct, const krb5_enctype *ktypes,
+	      krb5_const_principal sname, krb5_address *const *addrs,
+	      krb5_authdata *const *authorization_data,
+	      krb5_pa_data *const *padata, const krb5_data *second_ticket,
+	      krb5_creds *in_cred, krb5_response *rep)
+{
+    krb5_error_code retval;
+    krb5_kdc_req tgsreq;
+    krb5_data *scratch, scratch2;
+    krb5_ticket *sec_ticket = 0;
+    krb5_ticket *sec_ticket_arr[2];
+    krb5_timestamp time_now;
+    krb5_pa_data **combined_padata;
+    krb5_pa_data ap_req_padata;
+    int tcp_only = 0, use_master;
+
+    /* 
+     * in_creds MUST be a valid credential NOT just a partially filled in
+     * place holder for us to get credentials for the caller.
+     */
+    if (!in_cred->ticket.length)
+        return(KRB5_NO_TKT_SUPPLIED);
+
+    memset((char *)&tgsreq, 0, sizeof(tgsreq));
+
+    tgsreq.kdc_options = kdcoptions;
+    tgsreq.server = (krb5_principal) sname;
+
+    tgsreq.from = timestruct->starttime;
+    tgsreq.till = timestruct->endtime ? timestruct->endtime :
+	    in_cred->times.endtime;
+    tgsreq.rtime = timestruct->renew_till;
+    if ((retval = krb5_timeofday(context, &time_now)))
+	return(retval);
+    /* XXX we know they are the same size... */
+    rep->expected_nonce = tgsreq.nonce = (krb5_int32) time_now;
+    rep->request_time = time_now;
+
+    tgsreq.addresses = (krb5_address **) addrs;
+
+    if (authorization_data) {
+	/* need to encrypt it in the request */
+
+	if ((retval = encode_krb5_authdata((const krb5_authdata**)authorization_data,
+					   &scratch)))
+	    return(retval);
+
+	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);
+    }
+
+    /* Get the encryption types list */
+    if (ktypes) {
+	/* Check passed ktypes and make sure they're valid. */
+   	for (tgsreq.nktypes = 0; ktypes[tgsreq.nktypes]; tgsreq.nktypes++) {
+    	    if (!krb5_c_valid_enctype(ktypes[tgsreq.nktypes]))
+		return KRB5_PROG_ETYPE_NOSUPP;
+	}
+    	tgsreq.ktype = (krb5_enctype *)ktypes;
+    } else {
+        /* Get the default ktypes */
+        krb5_get_tgs_ktypes(context, sname, &(tgsreq.ktype));
+	for(tgsreq.nktypes = 0; tgsreq.ktype[tgsreq.nktypes]; tgsreq.nktypes++);
+    }
+
+    if (second_ticket) {
+	if ((retval = decode_krb5_ticket(second_ticket, &sec_ticket)))
+	    goto send_tgs_error_1;
+	sec_ticket_arr[0] = sec_ticket;
+	sec_ticket_arr[1] = 0;
+	tgsreq.second_ticket = sec_ticket_arr;
+    } else
+	tgsreq.second_ticket = 0;
+
+    /* encode the body; then checksum it */
+    if ((retval = encode_krb5_kdc_req_body(&tgsreq, &scratch)))
+	goto send_tgs_error_2;
+
+    /*
+     * Get an ap_req.
+     */
+    if ((retval = krb5_send_tgs_basic(context, scratch, in_cred, &scratch2))) {
+        krb5_free_data(context, scratch);
+	goto send_tgs_error_2;
+    }
+    krb5_free_data(context, scratch);
+
+    ap_req_padata.pa_type = KRB5_PADATA_AP_REQ;
+    ap_req_padata.length = scratch2.length;
+    ap_req_padata.contents = (krb5_octet *)scratch2.data;
+
+    /* combine in any other supplied padata */
+    if (padata) {
+	krb5_pa_data * const * counter;
+	register unsigned int i = 0;
+	for (counter = padata; *counter; counter++, i++);
+	combined_padata = malloc((i+2) * sizeof(*combined_padata));
+	if (!combined_padata) {
+	    krb5_xfree(ap_req_padata.contents);
+	    retval = ENOMEM;
+	    goto send_tgs_error_2;
+	}
+	combined_padata[0] = &ap_req_padata;
+	for (i = 1, counter = padata; *counter; counter++, i++)
+	    combined_padata[i] = (krb5_pa_data *) *counter;
+	combined_padata[i] = 0;
+    } else {
+	combined_padata = (krb5_pa_data **)malloc(2*sizeof(*combined_padata));
+	if (!combined_padata) {
+	    krb5_xfree(ap_req_padata.contents);
+	    retval = ENOMEM;
+	    goto send_tgs_error_2;
+	}
+	combined_padata[0] = &ap_req_padata;
+	combined_padata[1] = 0;
+    }
+    tgsreq.padata = combined_padata;
+
+    /* the TGS_REQ is assembled in tgsreq, so encode it */
+    if ((retval = encode_krb5_tgs_req(&tgsreq, &scratch))) {
+	krb5_xfree(ap_req_padata.contents);
+	krb5_xfree(combined_padata);
+	goto send_tgs_error_2;
+    }
+    krb5_xfree(ap_req_padata.contents);
+    krb5_xfree(combined_padata);
+
+    /* now send request & get response from KDC */
+send_again:
+    use_master = 0;
+    retval = krb5_sendto_kdc(context, scratch, 
+			     krb5_princ_realm(context, sname),
+			     &rep->response, &use_master, tcp_only);
+    if (retval == 0) {
+	if (krb5_is_krb_error(&rep->response)) {
+	    if (!tcp_only) {
+		krb5_error *err_reply;
+		retval = decode_krb5_error(&rep->response, &err_reply);
+		if (retval)
+		    goto send_tgs_error_3;
+		if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG) {
+		    tcp_only = 1;
+		    krb5_free_error(context, err_reply);
+		    free(rep->response.data);
+		    rep->response.data = 0;
+		    goto send_again;
+		}
+		krb5_free_error(context, err_reply);
+	    send_tgs_error_3:
+		;
+	    }
+	    rep->message_type = KRB5_ERROR;
+	} else if (krb5_is_tgs_rep(&rep->response))
+	    rep->message_type = KRB5_TGS_REP;
+        else /* XXX: assume it's an error */
+	    rep->message_type = KRB5_ERROR;
+    }
+
+    krb5_free_data(context, scratch);
+    
+send_tgs_error_2:;
+    if (sec_ticket) 
+	krb5_free_ticket(context, sec_ticket);
+
+send_tgs_error_1:;
+    if (ktypes == NULL)
+	krb5_xfree(tgsreq.ktype);
+    if (tgsreq.authorization_data.ciphertext.data) {
+	memset(tgsreq.authorization_data.ciphertext.data, 0,
+               tgsreq.authorization_data.ciphertext.length); 
+	krb5_xfree(tgsreq.authorization_data.ciphertext.data);
+    }
+
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/sendauth.c b/krb5-1-6/src/lib/krb5/krb/sendauth.c
new file mode 100644
index 000000000..5b5634307
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/sendauth.c
@@ -0,0 +1,233 @@
+/*
+ * lib/krb5/krb/sendauth.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * convenience sendauth/recvauth functions
+ */
+
+
+#include "k5-int.h"
+#include "com_err.h"
+#include "auth_con.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+static const char sendauth_version[] = "KRB5_SENDAUTH_V1.0";
+
+krb5_error_code KRB5_CALLCONV
+krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds)
+{
+	krb5_octet		result;
+	krb5_creds 		creds;
+	krb5_creds		 * credsp = NULL;
+	krb5_creds		 * credspout = NULL;
+	krb5_error_code		retval = 0;
+	krb5_data		inbuf, outbuf;
+	int			len;
+	krb5_ccache		use_ccache = 0;
+
+	if (error)
+	    *error = 0;
+
+	/*
+	 * First, send over the length of the sendauth version string;
+	 * then, we send over the sendauth version.  Next, we send
+	 * over the length of the application version strings followed
+	 * by the string itself.  
+	 */
+	outbuf.length = strlen(sendauth_version) + 1;
+	outbuf.data = (char *) sendauth_version;
+	if ((retval = krb5_write_message(context, fd, &outbuf)))
+		return(retval);
+	outbuf.length = strlen(appl_version) + 1;
+	outbuf.data = appl_version;
+	if ((retval = krb5_write_message(context, fd, &outbuf)))
+		return(retval);
+	/*
+	 * Now, read back a byte: 0 means no error, 1 means bad sendauth
+	 * version, 2 means bad application version
+	 */
+    if ((len = krb5_net_read(context, *((int *) fd), (char *)&result, 1)) != 1)
+	return((len < 0) ? errno : ECONNABORTED);
+    if (result == 1)
+	return(KRB5_SENDAUTH_BADAUTHVERS);
+    else if (result == 2)
+	return(KRB5_SENDAUTH_BADAPPLVERS);
+    else if (result != 0)
+	return(KRB5_SENDAUTH_BADRESPONSE);
+	/*
+	 * We're finished with the initial negotiations; let's get and
+	 * send over the authentication header.  (The AP_REQ message)
+	 */
+
+	/*
+	 * If no credentials were provided, try getting it from the
+	 * credentials cache.
+	 */
+	memset((char *)&creds, 0, sizeof(creds));
+
+	/*
+	 * See if we need to access the credentials cache
+	 */
+	if (!in_creds || !in_creds->ticket.length) {
+		if (ccache)
+			use_ccache = ccache;
+		else if ((retval = krb5int_cc_default(context, &use_ccache)))
+			goto error_return;
+	}
+	if (!in_creds) {
+		if ((retval = krb5_copy_principal(context, server,
+						  &creds.server)))
+			goto error_return;
+		if (client)
+			retval = krb5_copy_principal(context, client, 
+						     &creds.client);
+		else
+			retval = krb5_cc_get_principal(context, use_ccache,
+						       &creds.client);
+		if (retval) {
+			krb5_free_principal(context, creds.server);
+			goto error_return;
+		}
+		/* creds.times.endtime = 0; -- memset 0 takes care of this
+					zero means "as long as possible" */
+		/* creds.keyblock.enctype = 0; -- as well as this.
+					zero means no session enctype
+					preference */
+		in_creds = &creds;
+	}
+	if (!in_creds->ticket.length) {
+	    if ((retval = krb5_get_credentials(context, 0,
+					       use_ccache, in_creds, &credsp)))
+		    goto error_return;
+	    credspout = credsp;
+	} else {
+	    credsp = in_creds;
+	}
+
+	if (ap_req_options & AP_OPTS_USE_SUBKEY) {
+	    /* Provide some more fodder for random number code.
+	       This isn't strong cryptographically; the point here is
+	       not to guarantee randomness, but to make it less likely
+	       that multiple sessions could pick the same subkey.  */
+	    char rnd_data[1024];
+	    GETPEERNAME_ARG3_TYPE len2;
+	    krb5_data d;
+	    d.length = sizeof (rnd_data);
+	    d.data = rnd_data;
+	    len2 = sizeof (rnd_data);
+	    if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data, 
+			     &len2) == 0) {
+		d.length = len2;
+		(void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d);
+	    }
+	    len2 = sizeof (rnd_data);
+	    if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data, 
+			     &len2) == 0) {
+		d.length = len2;
+		(void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d);
+	    }
+	}
+
+	if ((retval = krb5_mk_req_extended(context, auth_context,
+					   ap_req_options, in_data, credsp,
+					   &outbuf)))
+	    goto error_return;
+
+	/*
+	 * First write the length of the AP_REQ message, then write
+	 * the message itself.
+	 */
+	retval = krb5_write_message(context, fd, &outbuf);
+	free(outbuf.data);
+	if (retval)
+	    goto error_return;
+
+	/*
+	 * Now, read back a message.  If it was a null message (the
+	 * length was zero) then there was no error.  If not, we the
+	 * authentication was rejected, and we need to return the
+	 * error structure.
+	 */
+	if ((retval = krb5_read_message(context, fd, &inbuf)))
+	    goto error_return;
+
+	if (inbuf.length) {
+		if (error) {
+		    if ((retval = krb5_rd_error(context, &inbuf, error))) {
+			krb5_xfree(inbuf.data);
+			goto error_return;
+		    }
+		}
+		retval = KRB5_SENDAUTH_REJECTED;
+		krb5_xfree(inbuf.data);
+		goto error_return;
+	}
+	
+	/*
+	 * If we asked for mutual authentication, we should now get a
+	 * length field, followed by a AP_REP message
+	 */
+	if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) {
+	    krb5_ap_rep_enc_part	*repl = 0;
+		
+	    if ((retval = krb5_read_message(context, fd, &inbuf)))
+		goto error_return;
+
+	    if ((retval = krb5_rd_rep(context, *auth_context, &inbuf,
+				      &repl))) {
+		if (repl)
+		    krb5_free_ap_rep_enc_part(context, repl);
+	        krb5_xfree(inbuf.data);
+		goto error_return;
+	    }
+
+	    krb5_xfree(inbuf.data);
+	    /*
+	     * If the user wants to look at the AP_REP message,
+	     * copy it for him
+	     */
+	    if (rep_result) 
+		*rep_result = repl;
+	    else
+		krb5_free_ap_rep_enc_part(context, repl);
+	}
+	retval = 0;		/* Normal return */
+	if (out_creds) {
+	    *out_creds = credsp;
+	    credspout = NULL;
+	}
+
+error_return:
+    krb5_free_cred_contents(context, &creds);
+    if (credspout != NULL)
+	krb5_free_creds(context, credspout); 
+    if (!ccache && use_ccache)
+	krb5_cc_close(context, use_ccache);
+    return(retval);
+}
+
+
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_actx.c b/krb5-1-6/src/lib/krb5/krb/ser_actx.c
new file mode 100644
index 000000000..32519e19f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_actx.c
@@ -0,0 +1,563 @@
+/*
+ * lib/krb5/krb/ser_actx.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_actx.c - Serialize krb5_auth_context structure.
+ */
+#include "k5-int.h"
+#include "int-proto.h"
+#include "auth_con.h"
+
+#define	TOKEN_RADDR	950916
+#define	TOKEN_RPORT	950917
+#define	TOKEN_LADDR	950918
+#define	TOKEN_LPORT	950919
+#define	TOKEN_KEYBLOCK	950920
+#define	TOKEN_LSKBLOCK	950921
+#define	TOKEN_RSKBLOCK	950922
+
+/*
+ * Routines to deal with externalizing the krb5_auth_context:
+ *	krb5_auth_context_size();
+ *	krb5_auth_context_externalize();
+ *	krb5_auth_context_internalize();
+ */
+static krb5_error_code krb5_auth_context_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_auth_context_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_auth_context_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/*
+ * Other metadata serialization initializers.
+ */
+
+/* Local data */
+static const krb5_ser_entry krb5_auth_context_ser_entry = {
+    KV5M_AUTH_CONTEXT,			/* Type			*/
+    krb5_auth_context_size,		/* Sizer routine	*/
+    krb5_auth_context_externalize,	/* Externalize routine	*/
+    krb5_auth_context_internalize	/* Internalize routine	*/
+};
+
+/*
+ * krb5_auth_context_size()	- Determine the size required to externalize
+ *				  the krb5_auth_context.
+ */
+static krb5_error_code
+krb5_auth_context_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_auth_context	auth_context;
+    size_t		required;
+
+    /*
+     * krb5_auth_context requires at minimum:
+     *	krb5_int32		for KV5M_AUTH_CONTEXT
+     *	krb5_int32		for auth_context_flags
+     *	krb5_int32		for remote_seq_number
+     *	krb5_int32		for local_seq_number
+     *	krb5_int32		for req_cksumtype
+     *	krb5_int32		for safe_cksumtype
+     *	krb5_int32		for size of i_vector
+     *	krb5_int32		for KV5M_AUTH_CONTEXT
+     */
+    kret = EINVAL;
+    if ((auth_context = (krb5_auth_context) arg)) {
+	kret = 0;
+
+	/* Calculate size required by i_vector - ptooey */
+	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 (!kret && auth_context->remote_addr) {
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_ADDRESS,
+				    (krb5_pointer) auth_context->remote_addr,
+				    &required);
+	    if (!kret)
+		required += sizeof(krb5_int32);
+	}
+
+	/* Calculate size required by remote_port, if appropriate */
+	if (!kret && auth_context->remote_port) {
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_ADDRESS,
+				    (krb5_pointer) auth_context->remote_port,
+				    &required);
+	    if (!kret)
+		required += sizeof(krb5_int32);
+	}
+
+	/* Calculate size required by local_addr, if appropriate */
+	if (!kret && auth_context->local_addr) {
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_ADDRESS,
+				    (krb5_pointer) auth_context->local_addr,
+				    &required);
+	    if (!kret)
+		required += sizeof(krb5_int32);
+	}
+
+	/* Calculate size required by local_port, if appropriate */
+	if (!kret && auth_context->local_port) {
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_ADDRESS,
+				    (krb5_pointer) auth_context->local_port,
+				    &required);
+	    if (!kret)
+		required += sizeof(krb5_int32);
+	}
+
+	/* Calculate size required by keyblock, if appropriate */
+	if (!kret && auth_context->keyblock) {
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) auth_context->keyblock,
+				    &required);
+	    if (!kret)
+		required += sizeof(krb5_int32);
+	}
+
+	/* Calculate size required by send_subkey, if appropriate */
+	if (!kret && auth_context->send_subkey) {
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) auth_context->send_subkey,
+				    &required);
+	    if (!kret)
+		required += sizeof(krb5_int32);
+	}
+
+	/* Calculate size required by recv_subkey, if appropriate */
+	if (!kret && auth_context->recv_subkey) {
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) auth_context->recv_subkey,
+				    &required);
+	    if (!kret)
+		required += sizeof(krb5_int32);
+	}
+
+	/* Calculate size required by authentp, if appropriate */
+	if (!kret && auth_context->authentp)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_AUTHENTICATOR,
+				    (krb5_pointer) auth_context->authentp,
+				    &required);
+
+    }
+    if (!kret)
+	*sizep += required;
+    return(kret);
+}
+
+/*
+ * krb5_auth_context_externalize()	- Externalize the krb5_auth_context.
+ */
+static krb5_error_code
+krb5_auth_context_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_auth_context	auth_context;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    size_t              obuf;
+    krb5_int32		obuf32;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((auth_context = (krb5_auth_context) arg)) {
+	kret = ENOMEM;
+	if (!krb5_auth_context_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+
+	    /* Write fixed portion */
+	    (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain);
+	    (void) krb5_ser_pack_int32(auth_context->auth_context_flags,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32(auth_context->remote_seq_number,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32(auth_context->local_seq_number,
+				       &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) auth_context->req_cksumtype,
+				       &bp, &remain);
+	    (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 */
+	    if (auth_context->i_vector) {
+		kret = krb5_c_block_size(kcontext,
+					 auth_context->keyblock->enctype,
+					 &obuf);
+	    } else {
+		obuf = 0;
+	    }
+
+	    /* Convert to signed 32 bit integer */
+	    obuf32 = obuf;
+	    if (kret == 0 && obuf != obuf32)
+		kret = EINVAL;
+	    if (!kret)
+		(void) krb5_ser_pack_int32(obuf32, &bp, &remain);
+
+	    /* Now copy i_vector */
+	    if (!kret && auth_context->i_vector)
+		(void) krb5_ser_pack_bytes(auth_context->i_vector,
+					   obuf,
+					   &bp, &remain);
+
+	    /* Now handle remote_addr, if appropriate */
+	    if (!kret && auth_context->remote_addr) {
+		(void) krb5_ser_pack_int32(TOKEN_RADDR, &bp, &remain);
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_ADDRESS,
+					       (krb5_pointer)
+					       auth_context->remote_addr,
+					       &bp,
+					       &remain);
+	    }
+
+	    /* Now handle remote_port, if appropriate */
+	    if (!kret && auth_context->remote_port) {
+		(void) krb5_ser_pack_int32(TOKEN_RPORT, &bp, &remain);
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_ADDRESS,
+					       (krb5_pointer)
+					       auth_context->remote_addr,
+					       &bp,
+					       &remain);
+	    }
+
+	    /* Now handle local_addr, if appropriate */
+	    if (!kret && auth_context->local_addr) {
+		(void) krb5_ser_pack_int32(TOKEN_LADDR, &bp, &remain);
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_ADDRESS,
+					       (krb5_pointer)
+					       auth_context->local_addr,
+					       &bp,
+					       &remain);
+	    }
+
+	    /* Now handle local_port, if appropriate */
+	    if (!kret && auth_context->local_port) {
+		(void) krb5_ser_pack_int32(TOKEN_LPORT, &bp, &remain);
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_ADDRESS,
+					       (krb5_pointer)
+					       auth_context->local_addr,
+					       &bp,
+					       &remain);
+	    }
+
+	    /* Now handle keyblock, if appropriate */
+	    if (!kret && auth_context->keyblock) {
+		(void) krb5_ser_pack_int32(TOKEN_KEYBLOCK, &bp, &remain);
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer)
+					       auth_context->keyblock,
+					       &bp,
+					       &remain);
+	    }
+
+	    /* Now handle subkey, if appropriate */
+	    if (!kret && auth_context->send_subkey) {
+		(void) krb5_ser_pack_int32(TOKEN_LSKBLOCK, &bp, &remain);
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer)
+					       auth_context->send_subkey,
+					       &bp,
+					       &remain);
+	    }
+
+	    /* Now handle subkey, if appropriate */
+	    if (!kret && auth_context->recv_subkey) {
+		(void) krb5_ser_pack_int32(TOKEN_RSKBLOCK, &bp, &remain);
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer)
+					       auth_context->recv_subkey,
+					       &bp,
+					       &remain);
+	    }
+
+	    /* Now handle authentp, if appropriate */
+	    if (!kret && auth_context->authentp)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_AUTHENTICATOR,
+					       (krb5_pointer)
+					       auth_context->authentp,
+					       &bp,
+					       &remain);
+
+	    /*
+	     * If we were successful, write trailer then update the pointer and
+	     * remaining length;
+	     */
+	    if (!kret) {
+		/* Write our trailer */
+		(void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain);
+		*buffer = bp;
+		*lenremain = remain;
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_auth_context_internalize()	- Internalize the krb5_auth_context.
+ */
+static krb5_error_code
+krb5_auth_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_auth_context	auth_context;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    krb5_int32		ivlen;
+    krb5_int32		tag;
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KV5M_AUTH_CONTEXT) {
+	kret = ENOMEM;
+
+	/* Get memory for the auth_context */
+	if ((remain >= (5*sizeof(krb5_int32))) &&
+	    (auth_context = (krb5_auth_context)
+	     malloc(sizeof(struct _krb5_auth_context)))) {
+	    memset(auth_context, 0, sizeof(struct _krb5_auth_context));
+
+	    /* Get auth_context_flags */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    auth_context->auth_context_flags = ibuf;
+
+	    /* Get remote_seq_number */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    auth_context->remote_seq_number = ibuf;
+
+	    /* Get local_seq_number */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    auth_context->local_seq_number = ibuf;
+
+	    /* Get req_cksumtype */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    auth_context->req_cksumtype = (krb5_cksumtype) ibuf;
+
+	    /* Get safe_cksumtype */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    auth_context->safe_cksumtype = (krb5_cksumtype) ibuf;
+
+	    /* Get length of i_vector */
+	    (void) krb5_ser_unpack_int32(&ivlen, &bp, &remain);
+
+	    if (ivlen) {
+		if ((auth_context->i_vector =
+		     (krb5_pointer) malloc((size_t)ivlen)))
+		    kret = krb5_ser_unpack_bytes(auth_context->i_vector,
+						 (size_t) ivlen,
+						 &bp,
+						 &remain);
+		else
+		    kret = ENOMEM;
+	    }
+	    else
+		kret = 0;
+	    
+	    /* Peek at next token */
+	    tag = 0;
+	    if (!kret)
+		kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
+
+	    /* This is the remote_addr */
+	    if (!kret && (tag == TOKEN_RADDR)) {
+		if (!(kret = krb5_internalize_opaque(kcontext,
+						     KV5M_ADDRESS,
+						     (krb5_pointer *)
+						     &auth_context->
+						     remote_addr,
+						     &bp,
+						     &remain)))
+		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
+	    }
+
+	    /* This is the remote_port */
+	    if (!kret && (tag == TOKEN_RPORT)) {
+		if (!(kret = krb5_internalize_opaque(kcontext,
+						     KV5M_ADDRESS,
+						     (krb5_pointer *)
+						     &auth_context->
+						     remote_port,
+						     &bp,
+						     &remain)))
+		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
+	    }
+
+	    /* This is the local_addr */
+	    if (!kret && (tag == TOKEN_LADDR)) {
+		if (!(kret = krb5_internalize_opaque(kcontext,
+						     KV5M_ADDRESS,
+						     (krb5_pointer *)
+						     &auth_context->
+						     local_addr,
+						     &bp,
+						     &remain)))
+		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
+	    }
+
+	    /* This is the local_port */
+	    if (!kret && (tag == TOKEN_LPORT)) {
+		if (!(kret = krb5_internalize_opaque(kcontext,
+						     KV5M_ADDRESS,
+						     (krb5_pointer *)
+						     &auth_context->
+						     local_port,
+						     &bp,
+						     &remain)))
+		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
+	    }
+
+	    /* This is the keyblock */
+	    if (!kret && (tag == TOKEN_KEYBLOCK)) {
+		if (!(kret = krb5_internalize_opaque(kcontext,
+						     KV5M_KEYBLOCK,
+						     (krb5_pointer *)
+						     &auth_context->keyblock,
+						     &bp,
+						     &remain)))
+		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
+	    }
+
+	    /* This is the send_subkey */
+	    if (!kret && (tag == TOKEN_LSKBLOCK)) {
+		if (!(kret = krb5_internalize_opaque(kcontext,
+						     KV5M_KEYBLOCK,
+						     (krb5_pointer *)
+						     &auth_context->
+						     send_subkey,
+						     &bp,
+						     &remain)))
+		    kret = krb5_ser_unpack_int32(&tag, &bp, &remain);
+	    }
+
+	    /* This is the recv_subkey */
+	    if (!kret) {
+		if (tag == TOKEN_RSKBLOCK) {
+		    kret = krb5_internalize_opaque(kcontext,
+						   KV5M_KEYBLOCK,
+						   (krb5_pointer *)
+						   &auth_context->
+						   recv_subkey,
+						   &bp,
+						   &remain);
+		}
+		else {
+		    /*
+		     * We read the next tag, but it's not of any use here, so
+		     * we effectively 'unget' it here.
+		     */
+		    bp -= sizeof(krb5_int32);
+		    remain += sizeof(krb5_int32);
+		}
+	    }
+
+	    /* Now find the authentp */
+	    if (!kret) {
+		if ((kret = krb5_internalize_opaque(kcontext,
+						    KV5M_AUTHENTICATOR,
+						    (krb5_pointer *)
+						    &auth_context->authentp,
+						    &bp,
+						    &remain))) {
+		    if (kret == EINVAL)
+			kret = 0;
+		}
+	    }
+
+	    /* Finally, find the trailer */
+	    if (!kret) {
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+		if (!kret && (ibuf != KV5M_AUTH_CONTEXT))
+		    kret = EINVAL;
+	    }
+	    if (!kret) {
+		*buffer = bp;
+		*lenremain = remain;
+		auth_context->magic = KV5M_AUTH_CONTEXT;
+		*argp = (krb5_pointer) auth_context;
+	    }
+	    else
+		krb5_auth_con_free(kcontext, auth_context);
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the auth_context serializer.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_auth_context_init(krb5_context kcontext)
+{
+    krb5_error_code	kret;
+    kret = krb5_register_serializer(kcontext, &krb5_auth_context_ser_entry);
+    if (!kret)
+	kret = krb5_ser_authdata_init(kcontext);
+    if (!kret)
+	kret = krb5_ser_address_init(kcontext);
+    if (!kret)
+	kret = krb5_ser_authenticator_init(kcontext);
+    if (!kret)
+	kret = krb5_ser_checksum_init(kcontext);
+    if (!kret)
+	kret = krb5_ser_keyblock_init(kcontext);
+    if (!kret)
+	kret = krb5_ser_principal_init(kcontext);
+    return(kret);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_adata.c b/krb5-1-6/src/lib/krb5/krb/ser_adata.c
new file mode 100644
index 000000000..ebd4c3e10
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_adata.c
@@ -0,0 +1,199 @@
+/*
+ * lib/krb5/krb/ser_adata.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_adata.c - Serialize a krb5_authdata structure.
+ */
+#include "k5-int.h"
+#include "int-proto.h"
+
+/*
+ * Routines to deal with externalizing the krb5_authdata:
+ *	krb5_authdata_size();
+ *	krb5_authdata_externalize();
+ *	krb5_authdata_internalize();
+ */
+static krb5_error_code krb5_authdata_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_authdata_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_authdata_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_authdata_ser_entry = {
+    KV5M_AUTHDATA,			/* Type			*/
+    krb5_authdata_size,			/* Sizer routine	*/
+    krb5_authdata_externalize,		/* Externalize routine	*/
+    krb5_authdata_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_authdata_esize()	- Determine the size required to externalize
+ *				  the krb5_authdata.
+ */
+static krb5_error_code
+krb5_authdata_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_authdata	*authdata;
+
+    /*
+     * krb5_authdata requires:
+     *	krb5_int32		for KV5M_AUTHDATA
+     *	krb5_int32		for ad_type
+     *	krb5_int32		for length
+     *	authdata->length	for contents
+     *	krb5_int32		for KV5M_AUTHDATA
+     */
+    kret = EINVAL;
+    if ((authdata = (krb5_authdata *) arg)) {
+	*sizep += (sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   (size_t) authdata->length);
+	kret = 0;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_authdata_externalize()	- Externalize the krb5_authdata.
+ */
+static krb5_error_code
+krb5_authdata_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_authdata	*authdata;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((authdata = (krb5_authdata *) arg)) {
+	kret = ENOMEM;
+	if (!krb5_authdata_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_AUTHDATA, &bp, &remain);
+		
+	    /* Our ad_type */
+	    (void) krb5_ser_pack_int32((krb5_int32) authdata->ad_type,
+				       &bp, &remain);
+
+	    /* Our length */
+	    (void) krb5_ser_pack_int32((krb5_int32) authdata->length,
+				       &bp, &remain);
+
+	    /* Our contents */
+	    (void) krb5_ser_pack_bytes(authdata->contents,
+				       (size_t) authdata->length,
+				       &bp, &remain);
+
+	    /* Finally, our trailer */
+	    (void) krb5_ser_pack_int32(KV5M_AUTHDATA, &bp, &remain);
+	    kret = 0;
+	    *buffer = bp;
+	    *lenremain = remain;
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_authdata_internalize()	- Internalize the krb5_authdata.
+ */
+static krb5_error_code
+krb5_authdata_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_authdata	*authdata;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    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 == KV5M_AUTHDATA) {
+	kret = ENOMEM;
+
+	/* Get a authdata */
+	if ((remain >= (2*sizeof(krb5_int32))) &&
+	    (authdata = (krb5_authdata *) malloc(sizeof(krb5_authdata)))) {
+	    memset(authdata, 0, sizeof(krb5_authdata));
+
+	    /* Get the ad_type */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    authdata->ad_type = (krb5_authdatatype) ibuf;
+
+	    /* Get the length */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    authdata->length = (int) ibuf;
+
+	    /* Get the string */
+	    if ((authdata->contents = (krb5_octet *)
+		 malloc((size_t) (ibuf))) &&
+		!(kret = krb5_ser_unpack_bytes(authdata->contents,
+					       (size_t) ibuf,
+					       &bp, &remain))) {
+		if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+		    ibuf = 0;
+		if (ibuf == KV5M_AUTHDATA) {
+		    authdata->magic = KV5M_AUTHDATA;
+		    *buffer = bp;
+		    *lenremain = remain;
+		    *argp = (krb5_pointer) authdata;
+		}
+		else
+		    kret = EINVAL;
+	    }
+	    if (kret) {
+		if (authdata->contents)
+		    free(authdata->contents);
+		free(authdata);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the authdata serializer.
+ */
+krb5_error_code
+krb5_ser_authdata_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_authdata_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_addr.c b/krb5-1-6/src/lib/krb5/krb/ser_addr.c
new file mode 100644
index 000000000..079cc0fda
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_addr.c
@@ -0,0 +1,203 @@
+/*
+ * lib/krb5/krb/ser_addr.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_addr.c - Serialize a krb5_address structure.
+ */
+#include "k5-int.h"
+#include "int-proto.h"
+
+/*
+ * Routines to deal with externalizing the krb5_address:
+ *	krb5_address_size();
+ *	krb5_address_externalize();
+ *	krb5_address_internalize();
+ */
+static krb5_error_code krb5_address_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_address_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_address_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_address_ser_entry = {
+    KV5M_ADDRESS,			/* Type			*/
+    krb5_address_size,		/* Sizer routine	*/
+    krb5_address_externalize,		/* Externalize routine	*/
+    krb5_address_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_address_size()	- Determine the size required to externalize
+ *				  the krb5_address.
+ */
+static krb5_error_code
+krb5_address_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_address	*address;
+
+    /*
+     * krb5_address requires:
+     *	krb5_int32		for KV5M_ADDRESS
+     *	krb5_int32		for addrtype
+     *	krb5_int32		for length
+     *	address->length		for contents
+     *	krb5_int32		for KV5M_ADDRESS
+     */
+    kret = EINVAL;
+    if ((address = (krb5_address *) arg)) {
+	*sizep += (sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   (size_t) address->length);
+	kret = 0;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_address_externalize()	- Externalize the krb5_address.
+ */
+static krb5_error_code
+krb5_address_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_address	*address;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((address = (krb5_address *) arg)) {
+	kret = ENOMEM;
+	if (!krb5_address_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_ADDRESS, &bp, &remain);
+		
+	    /* Our addrtype */
+	    (void) krb5_ser_pack_int32((krb5_int32) address->addrtype,
+				       &bp, &remain);
+
+	    /* Our length */
+	    (void) krb5_ser_pack_int32((krb5_int32) address->length,
+				       &bp, &remain);
+
+	    /* Our contents */
+	    (void) krb5_ser_pack_bytes(address->contents,
+				       (size_t) address->length,
+				       &bp, &remain);
+
+	    /* Finally, our trailer */
+	    (void) krb5_ser_pack_int32(KV5M_ADDRESS, &bp, &remain);
+
+	    kret = 0;
+	    *buffer = bp;
+	    *lenremain = remain;
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_address_internalize()	- Internalize the krb5_address.
+ */
+static krb5_error_code
+krb5_address_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_address	*address;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    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 == KV5M_ADDRESS) {
+	kret = ENOMEM;
+
+	/* Get a address */
+	if ((remain >= (2*sizeof(krb5_int32))) &&
+	    (address = (krb5_address *) malloc(sizeof(krb5_address)))) {
+	    memset(address, 0, sizeof(krb5_address));
+
+	    address->magic = KV5M_ADDRESS;
+
+	    /* Get the addrtype */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    address->addrtype = (krb5_addrtype) ibuf;
+
+	    /* Get the length */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    address->length = (int) ibuf;
+
+	    /* Get the string */
+	    if ((address->contents = (krb5_octet *) malloc((size_t) (ibuf))) &&
+		!(kret = krb5_ser_unpack_bytes(address->contents,
+					       (size_t) ibuf,
+					       &bp, &remain))) {
+		/* Get the trailer */
+		if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+		    ibuf = 0;
+
+		if (!kret && (ibuf == KV5M_ADDRESS)) {
+		    address->magic = KV5M_ADDRESS;
+		    *buffer = bp;
+		    *lenremain = remain;
+		    *argp = (krb5_pointer) address;
+		}
+		else
+		    kret = EINVAL;
+	    }
+	    if (kret) {
+		if (address->contents)
+		    free(address->contents);
+		free(address);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the address serializer.
+ */
+krb5_error_code
+krb5_ser_address_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_address_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_auth.c b/krb5-1-6/src/lib/krb5/krb/ser_auth.c
new file mode 100644
index 000000000..814028e27
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_auth.c
@@ -0,0 +1,350 @@
+/*
+ * lib/krb5/krb/ser_auth.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_auth.c - Serialize krb5_authenticator structure.
+ */
+#include "k5-int.h"
+#include "int-proto.h"
+
+/*
+ * Routines to deal with externalizing the krb5_authenticator:
+ *	krb5_authenticator_size();
+ *	krb5_authenticator_externalize();
+ *	krb5_authenticator_internalize();
+ */
+static krb5_error_code krb5_authenticator_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_authenticator_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_authenticator_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_authenticator_ser_entry = {
+    KV5M_AUTHENTICATOR,			/* Type			*/
+    krb5_authenticator_size,		/* Sizer routine	*/
+    krb5_authenticator_externalize,	/* Externalize routine	*/
+    krb5_authenticator_internalize	/* Internalize routine	*/
+};
+
+/*
+ * krb5_authenticator_size()	- Determine the size required to externalize
+ *				  the krb5_authenticator.
+ */
+static krb5_error_code
+krb5_authenticator_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_authenticator	*authenticator;
+    size_t		required;
+
+    /*
+     * krb5_authenticator requires at minimum:
+     *	krb5_int32		for KV5M_AUTHENTICATOR
+     *	krb5_int32		for seconds
+     *	krb5_int32		for cusec
+     *	krb5_int32		for seq_number
+     *	krb5_int32		for number in authorization_data array.
+     *	krb5_int32		for KV5M_AUTHENTICATOR
+     */
+    kret = EINVAL;
+    if ((authenticator = (krb5_authenticator *) arg)) {
+	required = sizeof(krb5_int32)*6;
+
+	/* Calculate size required by client, if appropriate */
+	if (authenticator->client)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_PRINCIPAL,
+				    (krb5_pointer) authenticator->client,
+				    &required);
+	else
+	    kret = 0;
+
+	/* Calculate size required by checksum, if appropriate */
+	if (!kret && authenticator->checksum)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_CHECKSUM,
+				    (krb5_pointer) authenticator->checksum,
+				    &required);
+
+	/* Calculate size required by subkey, if appropriate */
+	if (!kret && authenticator->subkey)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) authenticator->subkey,
+				    &required);
+
+	/* Calculate size required by authorization_data, if appropriate */
+	if (!kret && authenticator->authorization_data) {
+	    int i;
+
+	    for (i=0; !kret && authenticator->authorization_data[i]; i++) {
+		kret = krb5_size_opaque(kcontext,
+					KV5M_AUTHDATA,
+					(krb5_pointer) authenticator->
+					authorization_data[i],
+					&required);
+	    }
+	}
+    }
+    if (!kret)
+	*sizep += required;
+    return(kret);
+}
+
+/*
+ * krb5_authenticator_externalize()	- Externalize the krb5_authenticator.
+ */
+static krb5_error_code
+krb5_authenticator_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_authenticator	*authenticator;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    int			i;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((authenticator = (krb5_authenticator *) arg)) {
+	kret = ENOMEM;
+	if (!krb5_authenticator_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* First write our magic number */
+	    (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
+	    
+	    /* Now ctime */
+	    (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime,
+				       &bp, &remain);
+
+	    /* Now cusec */
+	    (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec,
+				       &bp, &remain);
+
+	    /* Now seq_number */
+	    (void) krb5_ser_pack_int32(authenticator->seq_number,
+				       &bp, &remain);
+
+	    /* Now handle client, if appropriate */
+	    if (authenticator->client)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_PRINCIPAL,
+					       (krb5_pointer)
+					       authenticator->client,
+					       &bp,
+					       &remain);
+	    else
+		kret = 0;
+
+	    /* Now handle checksum, if appropriate */
+	    if (!kret && authenticator->checksum)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_CHECKSUM,
+					       (krb5_pointer)
+					       authenticator->checksum,
+					       &bp,
+					       &remain);
+
+	    /* Now handle subkey, if appropriate */
+	    if (!kret && authenticator->subkey)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer)
+					       authenticator->subkey,
+					       &bp,
+					       &remain);
+
+	    /* Now handle authorization_data, if appropriate */
+	    if (!kret) {
+		if (authenticator->authorization_data)
+		    for (i=0; authenticator->authorization_data[i]; i++);
+		else
+		    i = 0;
+		(void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain);
+
+		/* Now pound out the authorization_data */
+		if (authenticator->authorization_data) {
+		    for (i=0; !kret && authenticator->authorization_data[i];
+			 i++)
+			kret = krb5_externalize_opaque(kcontext,
+						       KV5M_AUTHDATA,
+						       (krb5_pointer)
+						       authenticator->
+						       authorization_data[i],
+						       &bp,
+						       &remain);
+		}
+	    }
+
+	    /*
+	     * If we were successful, write trailer then update the pointer and
+	     * remaining length;
+	     */
+	    if (!kret) {
+		/* Write our trailer */
+		(void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
+		*buffer = bp;
+		*lenremain = remain;
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_authenticator_internalize()	- Internalize the krb5_authenticator.
+ */
+static krb5_error_code
+krb5_authenticator_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_authenticator	*authenticator;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    int			i;
+    krb5_int32		nadata;
+    size_t		len;
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KV5M_AUTHENTICATOR) {
+	kret = ENOMEM;
+
+	/* Get memory for the authenticator */
+	if ((remain >= (3*sizeof(krb5_int32))) &&
+	    (authenticator = (krb5_authenticator *) 
+	     malloc(sizeof(krb5_authenticator)))) {
+	    memset(authenticator, 0, sizeof(krb5_authenticator));
+
+	    /* Get ctime */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    authenticator->ctime = (krb5_timestamp) ibuf;
+
+	    /* Get cusec */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    authenticator->cusec = ibuf;
+
+	    /* Get seq_number */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    authenticator->seq_number = ibuf;
+	    
+	    kret = 0;
+
+	    /* Attempt to read in the client */
+	    kret = krb5_internalize_opaque(kcontext,
+					   KV5M_PRINCIPAL,
+					   (krb5_pointer *)
+					   &authenticator->client,
+					   &bp,
+					   &remain);
+	    if (kret == EINVAL)
+		kret = 0;
+
+	    /* Attempt to read in the checksum */
+	    if (!kret) {
+		kret = krb5_internalize_opaque(kcontext,
+					       KV5M_CHECKSUM,
+					       (krb5_pointer *)
+					       &authenticator->checksum,
+					       &bp,
+					       &remain);
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+
+	    /* Attempt to read in the subkey */
+	    if (!kret) {
+		kret = krb5_internalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer *)
+					       &authenticator->subkey,
+					       &bp,
+					       &remain);
+		if (kret == EINVAL)
+		    kret = 0;
+	    }
+
+	    /* Attempt to read in the authorization data count */
+	    if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) {
+		nadata = ibuf;
+		len = (size_t) (nadata + 1);
+
+		/* Get memory for the authorization data pointers */
+		if ((authenticator->authorization_data = (krb5_authdata **)
+		     malloc(sizeof(krb5_authdata *) * len))) {
+		    memset(authenticator->authorization_data, 0,
+			   sizeof(krb5_authdata *) * len);
+
+		    for (i=0; !kret && (i<nadata); i++) {
+			kret = krb5_internalize_opaque(kcontext,
+						       KV5M_AUTHDATA,
+						       (krb5_pointer *)
+						       &authenticator->
+						       authorization_data[i],
+						       &bp,
+						       &remain);
+		    }
+
+		    /* Finally, find the trailer */
+		    if (!kret) {
+			kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+			if (!kret && (ibuf == KV5M_AUTHENTICATOR))
+			    authenticator->magic = KV5M_AUTHENTICATOR;
+			else
+			    kret = EINVAL;
+		    }
+		}
+	    }
+	    if (!kret) {
+		*buffer = bp;
+		*lenremain = remain;
+		*argp = (krb5_pointer) authenticator;
+	    }
+	    else
+		krb5_free_authenticator(kcontext, authenticator);
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the authenticator serializer.
+ */
+krb5_error_code
+krb5_ser_authenticator_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_authenticator_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_cksum.c b/krb5-1-6/src/lib/krb5/krb/ser_cksum.c
new file mode 100644
index 000000000..8fb1a80da
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_cksum.c
@@ -0,0 +1,202 @@
+/*
+ * lib/krb5/krb/ser_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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_cksum.c - Serialize a krb5_checksum structure.
+ */
+#include "k5-int.h"
+#include "int-proto.h"
+
+/*
+ * Routines to deal with externalizing the krb5_checksum:
+ *	krb5_checksum_esize();
+ *	krb5_checksum_externalize();
+ *	krb5_checksum_internalize();
+ */
+static krb5_error_code krb5_checksum_esize
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_checksum_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_checksum_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_checksum_ser_entry = {
+    KV5M_CHECKSUM,			/* Type			*/
+    krb5_checksum_esize,		/* Sizer routine	*/
+    krb5_checksum_externalize,		/* Externalize routine	*/
+    krb5_checksum_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_checksum_esize()	- Determine the size required to externalize
+ *				  the krb5_checksum.
+ */
+static krb5_error_code
+krb5_checksum_esize(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_checksum	*checksum;
+
+    /*
+     * krb5_checksum requires:
+     *	krb5_int32		for KV5M_CHECKSUM
+     *	krb5_int32		for checksum_type
+     *	krb5_int32		for length
+     *	krb5_int32		for KV5M_CHECKSUM
+     *	checksum->length	for contents
+     */
+    kret = EINVAL;
+    if ((checksum = (krb5_checksum *) arg)) {
+	*sizep += (sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   (size_t) checksum->length);
+	kret = 0;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_checksum_externalize()	- Externalize the krb5_checksum.
+ */
+static krb5_error_code
+krb5_checksum_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_checksum	*checksum;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((checksum = (krb5_checksum *) arg)) {
+	kret = ENOMEM;
+	if (!krb5_checksum_esize(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain);
+		
+	    /* Our checksum_type */
+	    (void) krb5_ser_pack_int32((krb5_int32) checksum->checksum_type,
+				       &bp, &remain);
+
+	    /* Our length */
+	    (void) krb5_ser_pack_int32((krb5_int32) checksum->length,
+				       &bp, &remain);
+
+	    /* Our contents */
+	    (void) krb5_ser_pack_bytes(checksum->contents,
+				       (size_t) checksum->length,
+				       &bp, &remain);
+
+	    /* Finally, our trailer */
+	    (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain);
+
+	    kret = 0;
+	    *buffer = bp;
+	    *lenremain = remain;
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_checksum_internalize()	- Internalize the krb5_checksum.
+ */
+static krb5_error_code
+krb5_checksum_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_checksum	*checksum;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    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 == KV5M_CHECKSUM) {
+	kret = ENOMEM;
+
+	/* Get a checksum */
+	if ((remain >= (2*sizeof(krb5_int32))) &&
+	    (checksum = (krb5_checksum *) malloc(sizeof(krb5_checksum)))) {
+	    memset(checksum, 0, sizeof(krb5_checksum));
+
+	    /* Get the checksum_type */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    checksum->checksum_type = (krb5_cksumtype) ibuf;
+
+	    /* Get the length */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    checksum->length = (int) ibuf;
+
+	    /* Get the string */
+	    if (!ibuf ||
+		((checksum->contents = (krb5_octet *)
+		  malloc((size_t) (ibuf))) &&
+		 !(kret = krb5_ser_unpack_bytes(checksum->contents,
+						(size_t) ibuf,
+						&bp, &remain)))) {
+
+		/* Get the trailer */
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+		if (!kret && (ibuf == KV5M_CHECKSUM)) {
+		    checksum->magic = KV5M_CHECKSUM;
+		    *buffer = bp;
+		    *lenremain = remain;
+		    *argp = (krb5_pointer) checksum;
+		}
+		else
+		    kret = EINVAL;
+	    }
+	    if (kret) {
+		if (checksum->contents)
+		    free(checksum->contents);
+		free(checksum);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the checksum serializer.
+ */
+krb5_error_code
+krb5_ser_checksum_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_checksum_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_ctx.c b/krb5-1-6/src/lib/krb5/krb/ser_ctx.c
new file mode 100644
index 000000000..d48f61e83
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_ctx.c
@@ -0,0 +1,637 @@
+/*
+ * lib/krb5/krb/ser_ctx.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_ctx.c	- Routines to deal with serializing the krb5_context and
+ *		  krb5_os_context structures.
+ */
+#include "k5-int.h"
+
+/*
+ * Routines to deal with externalizing the krb5_context:
+ *	krb5_context_size();
+ *	krb5_context_externalize();
+ *	krb5_context_internalize();
+ * 
+ * Routines to deal with externalizing the krb5_os_context:
+ *	krb5_oscontext_size();
+ *	krb5_oscontext_externalize();
+ *	krb5_oscontext_internalize();
+ *
+ * Routines to deal with externalizing the profile.
+ *	profile_ser_size();
+ *	profile_ser_externalize();
+ *	profile_ser_internalize();
+ *
+ * Interface to initialize serializing of krb5_context and krb5_os_context:
+ *	krb5_ser_context_init();
+ */
+static krb5_error_code krb5_context_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_context_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_context_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+static krb5_error_code krb5_oscontext_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_oscontext_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_oscontext_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+krb5_error_code profile_ser_size
+	(krb5_context, krb5_pointer, size_t *);
+krb5_error_code profile_ser_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+krb5_error_code profile_ser_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_context_ser_entry = {
+    KV5M_CONTEXT,			/* Type 		*/
+    krb5_context_size,			/* Sizer routine	*/
+    krb5_context_externalize,		/* Externalize routine	*/
+    krb5_context_internalize		/* Internalize routine	*/
+};
+static const krb5_ser_entry krb5_oscontext_ser_entry = {
+    KV5M_OS_CONTEXT,			/* Type			*/
+    krb5_oscontext_size,		/* Sizer routine	*/
+    krb5_oscontext_externalize,		/* Externalize routine	*/
+    krb5_oscontext_internalize		/* Internalize routine	*/
+};
+static const krb5_ser_entry krb5_profile_ser_entry = {
+    PROF_MAGIC_PROFILE,			/* Type			*/
+    profile_ser_size,			/* Sizer routine	*/
+    profile_ser_externalize,		/* Externalize routine	*/
+    profile_ser_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_context_size()	- Determine the size required to externalize the
+ *			  krb5_context.
+ */
+static krb5_error_code
+krb5_context_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    size_t		required;
+    krb5_context	context;
+
+    /*
+     * The KRB5 context itself requires:
+     *	krb5_int32			for KV5M_CONTEXT
+     *	krb5_int32			for sizeof(default_realm)
+     *	strlen(default_realm)		for default_realm.
+     *	krb5_int32			for n_in_tkt_ktypes*sizeof(krb5_int32)
+     *	nktypes*sizeof(krb5_int32)	for in_tkt_ktypes.
+     *	krb5_int32			for n_tgs_ktypes*sizeof(krb5_int32)
+     *	nktypes*sizeof(krb5_int32)	for tgs_ktypes.
+     *  krb5_int32			for clockskew
+     *  krb5_int32			for kdc_req_sumtype
+     *  krb5_int32			for ap_req_sumtype
+     *  krb5_int32			for safe_sumtype
+     *  krb5_int32			for kdc_default_options
+     *  krb5_int32			for library_options
+     *  krb5_int32			for profile_secure
+     * 	krb5_int32			for fcc_default_format
+     *  krb5_int32			for scc_default_format
+     *    <>				for os_context
+     *    <>				for db_context
+     *    <>				for profile
+     *	krb5_int32			for trailer.
+     */
+    kret = EINVAL;
+    if ((context = (krb5_context) arg)) {
+	/* Calculate base length */
+	required = (14 * sizeof(krb5_int32) +
+		    (context->in_tkt_ktype_count * sizeof(krb5_int32)) +
+		    (context->tgs_ktype_count * sizeof(krb5_int32)));
+
+	if (context->default_realm)
+	    required += strlen(context->default_realm);
+	/* Calculate size required by os_context, if appropriate */
+	if (context->os_context)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_OS_CONTEXT,
+				    (krb5_pointer) context->os_context,
+				    &required);
+
+	/* Calculate size required by db_context, if appropriate */
+	if (!kret && context->db_context)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_DB_CONTEXT,
+				    (krb5_pointer) context->db_context,
+				    &required);
+
+	/* Finally, calculate size required by profile, if appropriate */
+	if (!kret && context->profile)
+	    kret = krb5_size_opaque(kcontext,
+				    PROF_MAGIC_PROFILE,
+				    (krb5_pointer) context->profile,
+				    &required);
+    }
+    if (!kret)
+	*sizep += required;
+    return(kret);
+}
+
+/*
+ * krb5_context_externalize()	- Externalize the krb5_context.
+ */
+static krb5_error_code
+krb5_context_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_context	context;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    int			i;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    context = (krb5_context) arg;
+    if (!context)
+	    return (EINVAL);
+    KRB5_VERIFY_MAGIC(context, KV5M_CONTEXT);
+
+    if ((kret = krb5_context_size(kcontext, arg, &required)))
+	return (kret);
+
+    if (required > remain)
+	return (ENOMEM);
+    
+    /* First write our magic number */
+    kret = krb5_ser_pack_int32(KV5M_CONTEXT, &bp, &remain);
+    if (kret)
+	return (kret);
+    
+    /* Now sizeof default realm */
+    kret = krb5_ser_pack_int32((context->default_realm) ?
+			       (krb5_int32) strlen(context->default_realm) : 0,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+    
+    /* Now default_realm bytes */
+    if (context->default_realm) {
+	kret = krb5_ser_pack_bytes((krb5_octet *) context->default_realm,
+				   strlen(context->default_realm), 
+				   &bp, &remain);
+	if (kret)
+	    return (kret);
+    }
+
+    /* Now number of initial ticket ktypes */
+    kret = krb5_ser_pack_int32((krb5_int32) context->in_tkt_ktype_count,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+    
+    /* Now serialize ktypes */
+    for (i=0; i<context->in_tkt_ktype_count; i++) {
+	kret = krb5_ser_pack_int32((krb5_int32) context->in_tkt_ktypes[i],
+				   &bp, &remain);
+	if (kret)
+	    return (kret);
+    }
+    
+    /* Now number of default ktypes */
+    kret = krb5_ser_pack_int32((krb5_int32) context->tgs_ktype_count,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+	
+    /* Now serialize ktypes */
+    for (i=0; i<context->tgs_ktype_count; i++) {
+	kret = krb5_ser_pack_int32((krb5_int32) context->tgs_ktypes[i],
+				   &bp, &remain);
+	if (kret)
+	    return (kret);
+    }
+	
+    /* Now allowable clockskew */
+    kret = krb5_ser_pack_int32((krb5_int32) context->clockskew,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+	
+    /* Now kdc_req_sumtype */
+    kret = krb5_ser_pack_int32((krb5_int32) context->kdc_req_sumtype,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+	
+    /* Now default ap_req_sumtype */
+    kret = krb5_ser_pack_int32((krb5_int32) context->default_ap_req_sumtype,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+
+    /* Now default safe_sumtype */
+    kret = krb5_ser_pack_int32((krb5_int32) context->default_safe_sumtype,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+
+    /* Now kdc_default_options */
+    kret = krb5_ser_pack_int32((krb5_int32) context->kdc_default_options,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+
+    /* Now library_options */
+    kret = krb5_ser_pack_int32((krb5_int32) context->library_options,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+	
+    /* Now profile_secure */
+    kret = krb5_ser_pack_int32((krb5_int32) context->profile_secure,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+
+    /* Now fcc_default_format */
+    kret = krb5_ser_pack_int32((krb5_int32) context->fcc_default_format,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+
+    /* Now scc_default_format */
+    kret = krb5_ser_pack_int32((krb5_int32) context->scc_default_format,
+			       &bp, &remain);
+    if (kret)
+	return (kret);
+
+    /* Now handle os_context, if appropriate */
+    if (context->os_context) {
+	kret = krb5_externalize_opaque(kcontext, KV5M_OS_CONTEXT,
+				       (krb5_pointer) context->os_context,
+				       &bp, &remain);
+	if (kret)
+	    return (kret);
+    }
+	
+    /* Now handle database context, if appropriate */
+    if (context->db_context) {
+	kret = krb5_externalize_opaque(kcontext, KV5M_DB_CONTEXT,
+				       (krb5_pointer) context->db_context,
+				       &bp, &remain);
+	if (kret)
+	    return (kret);
+    }
+
+    /* Finally, handle profile, if appropriate */
+    if (context->profile) {
+	kret = krb5_externalize_opaque(kcontext, PROF_MAGIC_PROFILE,
+				       (krb5_pointer) context->profile,
+				       &bp, &remain);
+	if (kret)
+	    return (kret);
+    }
+	
+    /*
+     * If we were successful, write trailer then update the pointer and
+     * remaining length;
+     */
+    kret = krb5_ser_pack_int32(KV5M_CONTEXT, &bp, &remain);
+    if (kret)
+	return (kret);
+    
+    *buffer = bp;
+    *lenremain = remain;
+
+    return (0);
+}
+
+/*
+ * krb5_context_internalize()	- Internalize the krb5_context.
+ */
+static krb5_error_code
+krb5_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_context	context;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    int			i;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    /* Read our magic number */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	return (EINVAL);
+
+    if (ibuf != KV5M_CONTEXT)
+	return (EINVAL);
+
+    /* Get memory for the context */
+    context = (krb5_context) malloc(sizeof(struct _krb5_context));
+    if (!context)
+	return (ENOMEM);
+    memset(context, 0, sizeof(struct _krb5_context));
+
+    /* Get the size of the default realm */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+
+    if (ibuf) {
+	context->default_realm = (char *) malloc((size_t) ibuf+1);
+	if (!context->default_realm) {
+	    kret = ENOMEM;
+	    goto cleanup;
+	}
+
+	kret = krb5_ser_unpack_bytes((krb5_octet *) context->default_realm,
+				     (size_t) ibuf, &bp, &remain);
+	if (kret)
+	    goto cleanup;
+	
+	context->default_realm[ibuf] = '\0';
+    }
+	
+    /* Get the number of in_tkt_ktypes */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    
+    context->in_tkt_ktype_count = (int) ibuf;
+    context->in_tkt_ktypes = (krb5_enctype *) malloc(sizeof(krb5_enctype) *
+				     (context->in_tkt_ktype_count+1));
+    if (!context->in_tkt_ktypes) {
+	kret = ENOMEM;
+	goto cleanup;
+    }
+    memset(context->in_tkt_ktypes, 0, (sizeof(krb5_enctype) *
+				       (context->in_tkt_ktype_count + 1)));
+    
+    for (i=0; i<context->in_tkt_ktype_count; i++) {
+	if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	    goto cleanup;
+	context->in_tkt_ktypes[i] = (krb5_enctype) ibuf;
+    }
+
+    /* Get the number of tgs_ktypes */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    
+    context->tgs_ktype_count = (int) ibuf;
+    context->tgs_ktypes = (krb5_enctype *) malloc(sizeof(krb5_enctype) *
+				  (context->tgs_ktype_count+1));
+    if (!context->tgs_ktypes) {
+	kret = ENOMEM;
+	goto cleanup;
+    }
+    memset(context->tgs_ktypes, 0, (sizeof(krb5_enctype) *
+				    (context->tgs_ktype_count + 1)));
+    for (i=0; i<context->tgs_ktype_count; i++) {
+	if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	    goto cleanup;
+	context->tgs_ktypes[i] = (krb5_enctype) ibuf;
+    }
+
+    /* Allowable checksum */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->clockskew = (krb5_deltat) ibuf;
+    
+    /* kdc_req_sumtype */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->kdc_req_sumtype = (krb5_cksumtype) ibuf;
+    
+    /* default ap_req_sumtype */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->default_ap_req_sumtype = (krb5_cksumtype) ibuf;
+    
+    /* default_safe_sumtype */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->default_safe_sumtype = (krb5_cksumtype) ibuf;
+
+    /* kdc_default_options */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->kdc_default_options = (krb5_flags) ibuf;
+
+    /* library_options */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->library_options = (krb5_flags) ibuf;
+
+    /* profile_secure */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->profile_secure = (krb5_boolean) ibuf;
+
+    /* fcc_default_format */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->fcc_default_format = (int) ibuf;
+
+    /* scc_default_format */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+    context->scc_default_format = (int) ibuf;
+    
+    /* Attempt to read in the os_context.  It's an array now, but
+       we still treat it in most places as a separate object with
+       a pointer.  */
+    {
+	krb5_os_context osp = 0;
+	kret = krb5_internalize_opaque(kcontext, KV5M_OS_CONTEXT,
+				       (krb5_pointer *) &osp,
+				       &bp, &remain);
+	if (kret && (kret != EINVAL) && (kret != ENOENT))
+	    goto cleanup;
+	/* Put the newly allocated data into the krb5_context
+	   structure where we're really keeping it these days.  */
+	if (osp)
+	    *context->os_context = *osp;
+	free(osp);
+    }
+
+    /* Attempt to read in the db_context */
+    kret = krb5_internalize_opaque(kcontext, KV5M_DB_CONTEXT,
+				   (krb5_pointer *) &context->db_context,
+				   &bp, &remain);
+    if (kret && (kret != EINVAL) && (kret != ENOENT))
+	goto cleanup;
+    
+    /* Attempt to read in the profile */
+    kret = krb5_internalize_opaque(kcontext, PROF_MAGIC_PROFILE,
+				   (krb5_pointer *) &context->profile,
+				   &bp, &remain);
+    if (kret && (kret != EINVAL) && (kret != ENOENT))
+	goto cleanup;
+    
+    /* Finally, find the trailer */
+    if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)))
+	goto cleanup;
+
+    if (ibuf != KV5M_CONTEXT) {
+	kret = EINVAL;
+	goto cleanup;
+    }
+
+    context->magic = KV5M_CONTEXT;
+    *buffer = bp;
+    *lenremain = remain;
+    *argp = (krb5_pointer) context;
+
+    return 0;
+
+cleanup:
+    if (context)
+	krb5_free_context(context);
+    return(kret);
+}
+
+/*
+ * krb5_oscontext_size()	- Determine the size required to externalize
+ *				  the krb5_os_context.
+ */
+static krb5_error_code
+krb5_oscontext_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    /*
+     * We need five 32-bit integers:
+     *	two for header and trailer
+     *	one each for time_offset, usec_offset and os_flags
+     */
+    *sizep += (5*sizeof(krb5_int32));
+    return(0);
+}
+
+/*
+ * krb5_oscontext_externalize()	- Externalize the krb5_os_context.
+ */
+static krb5_error_code
+krb5_oscontext_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_os_context	os_ctx;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((os_ctx = (krb5_os_context) arg)) {
+	kret = ENOMEM;
+	if (!krb5_oscontext_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    (void) krb5_ser_pack_int32(KV5M_OS_CONTEXT, &bp, &remain);
+	    (void) krb5_ser_pack_int32(os_ctx->time_offset, &bp, &remain);
+	    (void) krb5_ser_pack_int32(os_ctx->usec_offset, &bp, &remain);
+	    (void) krb5_ser_pack_int32(os_ctx->os_flags, &bp, &remain);
+	    (void) krb5_ser_pack_int32(KV5M_OS_CONTEXT, &bp, &remain);
+
+	    /* Handle any other OS context here */
+	    kret = 0;
+	    if (!kret) {
+		*buffer = bp;
+		*lenremain = remain;
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_oscontext_internalize()	- Internalize the krb5_os_context.
+ */
+static krb5_error_code
+krb5_oscontext_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_os_context	os_ctx;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    os_ctx = (krb5_os_context) NULL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KV5M_OS_CONTEXT) {
+	kret = ENOMEM;
+
+	/* Get memory for the context */
+	if ((os_ctx = (krb5_os_context) 
+	     malloc(sizeof(struct _krb5_os_context))) &&
+	    (remain >= 4*sizeof(krb5_int32))) {
+	    memset(os_ctx, 0, sizeof(struct _krb5_os_context));
+	    os_ctx->magic = KV5M_OS_CONTEXT;
+
+	    /* Read out our context */
+	    (void) krb5_ser_unpack_int32(&os_ctx->time_offset, &bp, &remain);
+	    (void) krb5_ser_unpack_int32(&os_ctx->usec_offset, &bp, &remain);
+	    (void) krb5_ser_unpack_int32(&os_ctx->os_flags, &bp, &remain);
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+
+	    if (ibuf == KV5M_OS_CONTEXT) {
+		os_ctx->magic = KV5M_OS_CONTEXT;
+		kret = 0;
+		*buffer = bp;
+		*lenremain = remain;
+	    } else
+		kret = EINVAL;
+	}
+    }
+    if (!kret) {
+	*argp = (krb5_pointer) os_ctx;
+    }
+    else {
+	if (os_ctx)
+	    free(os_ctx);
+    }
+    return(kret);
+}
+
+/*
+ * Register the context serializers.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_context_init(krb5_context kcontext)
+{
+    krb5_error_code	kret;
+    kret = krb5_register_serializer(kcontext, &krb5_context_ser_entry);
+    if (!kret)
+	kret = krb5_register_serializer(kcontext, &krb5_oscontext_ser_entry);
+    if (!kret)
+	kret = krb5_register_serializer(kcontext, &krb5_profile_ser_entry);
+    return(kret);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_eblk.c b/krb5-1-6/src/lib/krb5/krb/ser_eblk.c
new file mode 100644
index 000000000..aed806ce1
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_eblk.c
@@ -0,0 +1,258 @@
+/*
+ * lib/krb5/krb/ser_eblk.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#if 0 /* i don't believe this is used anywhere --marc */
+
+/*
+ * ser_eblk.c - Serialize a krb5_encblock structure.
+ */
+#include "k5-int.h"
+
+/*
+ * Routines to deal with externalizing the krb5_encrypt_block:
+ *	krb5_encrypt_block_size();
+ *	krb5_encrypt_block_externalize();
+ *	krb5_encrypt_block_internalize();
+ */
+static krb5_error_code krb5_encrypt_block_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_encrypt_block_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_encrypt_block_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_encrypt_block_ser_entry = {
+    KV5M_ENCRYPT_BLOCK,			/* Type			*/
+    krb5_encrypt_block_size,		/* Sizer routine	*/
+    krb5_encrypt_block_externalize,	/* Externalize routine	*/
+    krb5_encrypt_block_internalize	/* Internalize routine	*/
+};
+
+/*
+ * krb5_encrypt_block_size()	- Determine the size required to externalize
+ *				  the krb5_encrypt_block.
+ */
+static krb5_error_code
+krb5_encrypt_block_size(kcontext, arg, sizep)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    size_t		*sizep;
+{
+    krb5_error_code	kret;
+    krb5_encrypt_block	*encrypt_block;
+    size_t		required;
+
+    /*
+     * NOTE: This ASSuMES that enctype are sufficient to recreate
+     * the _krb5_cryptosystem_entry.  If this is not true, then something else
+     * had better be encoded here.
+     * 
+     * krb5_encrypt_block base requirements:
+     *	krb5_int32			for KV5M_ENCRYPT_BLOCK
+     *	krb5_int32			for enctype
+     *	krb5_int32			for private length
+     *	encrypt_block->priv_size	for private contents
+     *	krb5_int32			for KV5M_ENCRYPT_BLOCK
+     */
+    kret = EINVAL;
+    if ((encrypt_block = (krb5_encrypt_block *) arg)) {
+	required = (sizeof(krb5_int32) +
+		    sizeof(krb5_int32) +
+		    sizeof(krb5_int32) +
+		    sizeof(krb5_int32) +
+		    sizeof(krb5_int32) +
+		    (size_t) encrypt_block->priv_size);
+	if (encrypt_block->key)
+	    kret = krb5_size_opaque(kcontext,
+				    KV5M_KEYBLOCK,
+				    (krb5_pointer) encrypt_block->key,
+				    &required);
+	else
+	    kret = 0;
+	if (!kret)
+	    *sizep += required;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_encrypt_block_externalize()	- Externalize the krb5_encrypt_block.
+ */
+static krb5_error_code
+krb5_encrypt_block_externalize(kcontext, arg, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	arg;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+    krb5_error_code	kret;
+    krb5_encrypt_block	*encrypt_block;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((encrypt_block = (krb5_encrypt_block *) arg)) {
+	kret = ENOMEM;
+	if (!krb5_encrypt_block_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_ENCRYPT_BLOCK, &bp, &remain);
+		
+	    /* Our enctype */
+	    (void) krb5_ser_pack_int32((krb5_int32) encrypt_block->
+				       crypto_entry->proto_enctype,
+				       &bp, &remain);
+
+	    /* Our length */
+	    (void) krb5_ser_pack_int32((krb5_int32) encrypt_block->priv_size,
+				       &bp, &remain);
+
+	    /* Our private data */
+	    (void) krb5_ser_pack_bytes(encrypt_block->priv,
+				       (size_t) encrypt_block->priv_size,
+				       &bp, &remain);
+
+	    /* Finally, the key data */
+	    if (encrypt_block->key)
+		kret = krb5_externalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer)
+					       encrypt_block->key,
+					       &bp,
+					       &remain);
+	    else
+		kret = 0;
+
+	    if (!kret) {
+		/* Write trailer */
+		(void) krb5_ser_pack_int32(KV5M_ENCRYPT_BLOCK, &bp, &remain);
+		*buffer = bp;
+		*lenremain = remain;
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_encrypt_block_internalize()	- Internalize the krb5_encrypt_block.
+ */
+static krb5_error_code
+krb5_encrypt_block_internalize(kcontext, argp, buffer, lenremain)
+    krb5_context	kcontext;
+    krb5_pointer	*argp;
+    krb5_octet		**buffer;
+    size_t		*lenremain;
+{
+    krb5_error_code	kret;
+    krb5_encrypt_block	*encrypt_block;
+    krb5_int32		ibuf;
+    krb5_enctype	ktype;
+    krb5_octet		*bp;
+    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 == KV5M_ENCRYPT_BLOCK) {
+	kret = ENOMEM;
+
+	/* Get an encrypt_block */
+	if ((remain >= (3*sizeof(krb5_int32))) &&
+	    (encrypt_block = (krb5_encrypt_block *)
+	     malloc(sizeof(krb5_encrypt_block)))) {
+	    memset(encrypt_block, 0, sizeof(krb5_encrypt_block));
+
+	    /* Get the enctype */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    ktype = (krb5_enctype) ibuf;
+
+	    /* Use the ktype to determine the crypto_system entry. */
+	    krb5_use_enctype(kcontext, encrypt_block, ktype);
+
+	    /* Get the length */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    encrypt_block->priv_size = (int) ibuf;
+
+	    /* Get the string */
+	    if (!ibuf ||
+		((encrypt_block->priv = (void *) malloc((size_t) (ibuf))) &&
+		 !(kret = krb5_ser_unpack_bytes((krb5_octet *)
+						encrypt_block->priv,
+						(size_t)
+						encrypt_block->priv_size,
+						&bp, &remain)))) {
+		kret = krb5_internalize_opaque(kcontext,
+					       KV5M_KEYBLOCK,
+					       (krb5_pointer *)
+					       &encrypt_block->key,
+					       &bp,
+					       &remain);
+		if (kret == EINVAL)
+		    kret = 0;
+
+		if (!kret) {
+		    kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+		    if (!kret && (ibuf == KV5M_ENCRYPT_BLOCK)) {
+			*buffer = bp;
+			*lenremain = remain;
+			encrypt_block->magic = KV5M_ENCRYPT_BLOCK;
+			*argp = (krb5_pointer) encrypt_block;
+		    }
+		    else
+			kret = EINVAL;
+		}
+	    }
+	    if (kret) {
+		if (encrypt_block->priv)
+		    free(encrypt_block->priv);
+		free(encrypt_block);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the encblock serializer.
+ */
+krb5_error_code
+krb5_ser_encrypt_block_init(kcontext)
+    krb5_context	kcontext;
+{
+    return(krb5_register_serializer(kcontext, &krb5_encrypt_block_ser_entry));
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_key.c b/krb5-1-6/src/lib/krb5/krb/ser_key.c
new file mode 100644
index 000000000..5249006fc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_key.c
@@ -0,0 +1,200 @@
+/*
+ * lib/krb5/krb/ser_key.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_key.c - Serialize a krb5_keyblock structure.
+ */
+#include "k5-int.h"
+#include "int-proto.h"
+
+/*
+ * Routines to deal with externalizing the krb5_keyblock:
+ *	krb5_keyblock_size();
+ *	krb5_keyblock_externalize();
+ *	krb5_keyblock_internalize();
+ */
+static krb5_error_code krb5_keyblock_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_keyblock_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_keyblock_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_keyblock_ser_entry = {
+    KV5M_KEYBLOCK,			/* Type			*/
+    krb5_keyblock_size,			/* Sizer routine	*/
+    krb5_keyblock_externalize,		/* Externalize routine	*/
+    krb5_keyblock_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_keyblock_size()	- Determine the size required to externalize
+ *				  the krb5_keyblock.
+ */
+static krb5_error_code
+krb5_keyblock_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_keyblock	*keyblock;
+
+    /*
+     * krb5_keyblock requires:
+     *	krb5_int32			for KV5M_KEYBLOCK
+     *	krb5_int32			for enctype
+     *	krb5_int32			for length
+     *	keyblock->length		for contents
+     *	krb5_int32			for KV5M_KEYBLOCK
+     */
+    kret = EINVAL;
+    if ((keyblock = (krb5_keyblock *) arg)) {
+	*sizep += (sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   sizeof(krb5_int32) +
+		   (size_t) keyblock->length);
+	kret = 0;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_keyblock_externalize()	- Externalize the krb5_keyblock.
+ */
+static krb5_error_code
+krb5_keyblock_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_keyblock	*keyblock;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((keyblock = (krb5_keyblock *) arg)) {
+	kret = ENOMEM;
+	if (!krb5_keyblock_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_KEYBLOCK, &bp, &remain);
+		
+	    /* Our enctype */
+	    (void) krb5_ser_pack_int32((krb5_int32) keyblock->enctype,
+				       &bp, &remain);
+
+	    /* Our length */
+	    (void) krb5_ser_pack_int32((krb5_int32) keyblock->length,
+				       &bp, &remain);
+
+	    /* Our contents */
+	    (void) krb5_ser_pack_bytes(keyblock->contents,
+				       (size_t) keyblock->length,
+				       &bp, &remain);
+
+	    /* Finally, our trailer */
+	    (void) krb5_ser_pack_int32(KV5M_KEYBLOCK, &bp, &remain);
+
+	    kret = 0;
+	    *buffer = bp;
+	    *lenremain = remain;
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_keyblock_internalize()	- Internalize the krb5_keyblock.
+ */
+static krb5_error_code
+krb5_keyblock_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_keyblock	*keyblock;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    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 == KV5M_KEYBLOCK) {
+	kret = ENOMEM;
+
+	/* Get a keyblock */
+	if ((remain >= (3*sizeof(krb5_int32))) &&
+	    (keyblock = (krb5_keyblock *) malloc(sizeof(krb5_keyblock)))) {
+	    memset(keyblock, 0, sizeof(krb5_keyblock));
+
+	    /* Get the enctype */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    keyblock->enctype = (krb5_enctype) ibuf;
+
+	    /* Get the length */
+	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+	    keyblock->length = (int) ibuf;
+
+	    /* Get the string */
+	    if ((keyblock->contents = (krb5_octet *) malloc((size_t) (ibuf)))&&
+		!(kret = krb5_ser_unpack_bytes(keyblock->contents,
+					       (size_t) ibuf,
+					       &bp, &remain))) {
+		kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+		if (!kret && (ibuf == KV5M_KEYBLOCK)) {
+		    kret = 0;
+		    *buffer = bp;
+		    *lenremain = remain;
+		    keyblock->magic = KV5M_KEYBLOCK;
+		    *argp = (krb5_pointer) keyblock;
+		}
+		else
+		    kret = EINVAL;
+	    }
+	    if (kret) {
+		if (keyblock->contents)
+		    free(keyblock->contents);
+		free(keyblock);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the keyblock serializer.
+ */
+krb5_error_code
+krb5_ser_keyblock_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_keyblock_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/ser_princ.c b/krb5-1-6/src/lib/krb5/krb/ser_princ.c
new file mode 100644
index 000000000..a4663c5f8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/ser_princ.c
@@ -0,0 +1,181 @@
+/*
+ * lib/krb5/krb/ser_princ.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_princ.c - Serialize a krb5_principal structure.
+ */
+#include "k5-int.h"
+#include "int-proto.h"
+
+/*
+ * Routines to deal with externalizing the krb5_principal:
+ *	krb5_principal_size();
+ *	krb5_principal_externalize();
+ *	krb5_principal_internalize();
+ */
+static krb5_error_code krb5_principal_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_principal_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_principal_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/* Local data */
+static const krb5_ser_entry krb5_principal_ser_entry = {
+    KV5M_PRINCIPAL,			/* Type			*/
+    krb5_principal_size,		/* Sizer routine	*/
+    krb5_principal_externalize,		/* Externalize routine	*/
+    krb5_principal_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_principal_size()	- Determine the size required to externalize
+ *				  the krb5_principal.
+ */
+static krb5_error_code
+krb5_principal_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_principal	principal;
+    char		*fname;
+
+    /*
+     * krb5_principal requires:
+     *	krb5_int32			for KV5M_PRINCIPAL
+     *	krb5_int32			for flattened name size
+     *	strlen(name)			for name.
+     *	krb5_int32			for KV5M_PRINCIPAL
+     */
+    kret = EINVAL;
+    if ((principal = (krb5_principal) arg) &&
+	!(kret = krb5_unparse_name(kcontext, principal, &fname))) {
+	*sizep += (3*sizeof(krb5_int32)) + strlen(fname);
+	krb5_xfree(fname);
+    }
+    return(kret);
+}
+
+/*
+ * krb5_principal_externalize()	- Externalize the krb5_principal.
+ */
+static krb5_error_code
+krb5_principal_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_principal	principal;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    char		*fname;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((principal = (krb5_principal) arg)) {
+	kret = ENOMEM;
+	if (!krb5_principal_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    if (!(kret = krb5_unparse_name(kcontext, principal, &fname))) {
+
+		(void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain);
+		(void) krb5_ser_pack_int32((krb5_int32) strlen(fname),
+					   &bp, &remain);
+		(void) krb5_ser_pack_bytes((krb5_octet *) fname,
+					   strlen(fname), &bp, &remain);
+		(void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain);
+		*buffer = bp;
+		*lenremain = remain;
+
+		krb5_xfree(fname);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_principal_internalize()	- Internalize the krb5_principal.
+ */
+static krb5_error_code
+krb5_principal_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_principal	principal;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    char		*tmpname;
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KV5M_PRINCIPAL) {
+	kret = ENOMEM;
+
+	/* See if we have enough data for the length */
+	if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) {
+	    /* Get the string */
+	    if ((tmpname = (char *) malloc((size_t) (ibuf+1))) &&
+		!(kret = krb5_ser_unpack_bytes((krb5_octet *) tmpname,
+					       (size_t) ibuf,
+					       &bp, &remain))) {
+		tmpname[ibuf] = '\0';
+
+		/* Parse the name to a principal structure */
+		principal = (krb5_principal) NULL;
+		kret = krb5_parse_name(kcontext, tmpname, &principal);
+		if (!kret) {
+		    kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+		    if (!kret && (ibuf == KV5M_PRINCIPAL)) {
+			*buffer = bp;
+			*lenremain = remain;
+			*argp = principal;
+		    }
+		    else
+			kret = EINVAL;
+		}
+		if (kret && principal)
+		    krb5_free_principal(kcontext, principal);
+		free(tmpname);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the context serializer.
+ */
+krb5_error_code
+krb5_ser_principal_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_principal_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/serialize.c b/krb5-1-6/src/lib/krb5/krb/serialize.c
new file mode 100644
index 000000000..9cbcef78d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/serialize.c
@@ -0,0 +1,278 @@
+/*
+ * lib/krb5/krb/serialize.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * Base routines to deal with serialization of Kerberos metadata.
+ */
+#include "k5-int.h"
+
+/*
+ * krb5_find_serializer()	- See if a particular type is registered.
+ */
+krb5_ser_handle
+krb5_find_serializer(krb5_context kcontext, krb5_magic odtype)
+{
+    krb5_ser_handle	res;
+    krb5_ser_handle	sctx;
+    int			i;
+
+    res = (krb5_ser_handle) NULL;
+    sctx = (krb5_ser_handle) kcontext->ser_ctx;
+    for (i=0; i<kcontext->ser_ctx_count; i++) {
+	if (sctx[i].odtype == odtype) {
+	    res = &sctx[i];
+	    break;
+	}
+    }
+    return(res);
+}
+
+/*
+ * krb5_register_serializer()	- Register a particular serializer.
+ */
+krb5_error_code
+krb5_register_serializer(krb5_context kcontext, const krb5_ser_entry *entry)
+{
+    krb5_error_code	kret;
+    krb5_ser_handle	stable;
+
+    kret = 0;
+    /* See if it's already there, if so, we're good to go. */
+    if (!(stable = krb5_find_serializer(kcontext, entry->odtype))) {
+	/*
+	 * Can't find our type.  Create a new entry.
+	 */
+	if ((stable = (krb5_ser_handle) malloc(sizeof(krb5_ser_entry) *
+					       (kcontext->ser_ctx_count+1)))) {
+	    /* Copy in old table */
+	    if (kcontext->ser_ctx_count)
+	         memcpy(stable, kcontext->ser_ctx,
+		        sizeof(krb5_ser_entry) * kcontext->ser_ctx_count);
+	    /* Copy in new entry */
+	    memcpy(&stable[kcontext->ser_ctx_count], entry,
+		   sizeof(krb5_ser_entry));
+	    if (kcontext->ser_ctx) krb5_xfree(kcontext->ser_ctx);
+	    kcontext->ser_ctx = (void *) stable;
+	    kcontext->ser_ctx_count++;
+	}
+	else
+	    kret = ENOMEM;
+    }
+    else
+	memcpy(stable, entry, sizeof(krb5_ser_entry));
+    return(kret);
+}
+
+/*
+ * krb5_size_opaque()	- Determine the size necessary to serialize a given
+ *			  piece of opaque data.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_size_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_ser_handle	shandle;
+
+    kret = ENOENT;
+    /* See if the type is supported, if so, do it */
+    if ((shandle = krb5_find_serializer(kcontext, odtype)))
+	kret = (shandle->sizer) ? (*shandle->sizer)(kcontext, arg, sizep) : 0;
+    return(kret);
+}
+
+/*
+ * krb5_externalize_opaque()	- Externalize a piece of opaque data.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_externalize_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer arg, krb5_octet **bufpp, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_ser_handle	shandle;
+
+    kret = ENOENT;
+    /* See if the type is supported, if so, do it */
+    if ((shandle = krb5_find_serializer(kcontext, odtype)))
+	kret = (shandle->externalizer) ?
+	    (*shandle->externalizer)(kcontext, arg, bufpp, sizep) : 0;
+    return(kret);
+}
+
+/*
+ * Externalize a piece of arbitrary data.
+ */
+krb5_error_code
+krb5_externalize_data(krb5_context kcontext, krb5_pointer arg, krb5_octet **bufpp, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_magic		*mp;
+    krb5_octet		*buffer, *bp;
+    size_t		bufsize, bsize;
+
+    mp = (krb5_magic *) arg;
+    bufsize = 0;
+    if (!(kret = krb5_size_opaque(kcontext, *mp, arg, &bufsize))) {
+	if ((buffer = (krb5_octet *) malloc(bufsize))) {
+	    bp = buffer;
+	    bsize = bufsize;
+	    if (!(kret = krb5_externalize_opaque(kcontext,
+						 *mp,
+						 arg,
+						 &bp,
+						 &bsize))) {
+		if (bsize != 0)
+		    bufsize -= bsize;
+		*bufpp = buffer;
+		*sizep = bufsize;
+	    }
+	}
+	else
+	    kret = ENOMEM;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_internalize_opaque()	- Convert external representation into a data
+ *				  structure.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_internalize_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer *argp, krb5_octet **bufpp, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_ser_handle	shandle;
+
+    kret = ENOENT;
+    /* See if the type is supported, if so, do it */
+    if ((shandle = krb5_find_serializer(kcontext, odtype)))
+	kret = (shandle->internalizer) ?
+	    (*shandle->internalizer)(kcontext, argp, bufpp, sizep) : 0;
+    return(kret);
+}
+
+/*
+ * krb5_ser_pack_int32()	- Pack a 4-byte integer if space is available.
+ *				  Update buffer pointer and remaining space.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_int32(krb5_int32 iarg, krb5_octet **bufp, size_t *remainp)
+{
+    if (*remainp >= sizeof(krb5_int32)) {
+	(*bufp)[0] = (krb5_octet) ((iarg >> 24) & 0xff);
+	(*bufp)[1] = (krb5_octet) ((iarg >> 16) & 0xff);
+	(*bufp)[2] = (krb5_octet) ((iarg >> 8) & 0xff);
+	(*bufp)[3] = (krb5_octet) (iarg & 0xff);
+	*bufp += sizeof(krb5_int32);
+	*remainp -= sizeof(krb5_int32);
+	return(0);
+    }
+    else
+	return(ENOMEM);
+}
+
+/*
+ * krb5_ser_pack_int64()	- Pack an 8-byte integer if space is available.
+ *				  Update buffer pointer and remaining space.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_int64(krb5_int64 iarg, krb5_octet **bufp, size_t *remainp)
+{
+    if (*remainp >= sizeof(krb5_int64)) {
+	store_64_be(iarg, (unsigned char *)*bufp);
+	*bufp += sizeof(krb5_int64);
+	*remainp -= sizeof(krb5_int64);
+	return(0);
+    }
+    else
+	return(ENOMEM);
+}
+
+/*
+ * krb5_ser_pack_bytes()	- Pack a string of bytes.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_pack_bytes(krb5_octet *ostring, size_t osize, krb5_octet **bufp, size_t *remainp)
+{
+    if (*remainp >= osize) {
+	memcpy(*bufp, ostring, osize);
+	*bufp += osize;
+	*remainp -= osize;
+	return(0);
+    }
+    else
+	return(ENOMEM);
+}
+
+/*
+ * krb5_ser_unpack_int32()	- Unpack a 4-byte integer if it's there.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_unpack_int32(krb5_int32 *intp, krb5_octet **bufp, size_t *remainp)
+{
+    if (*remainp >= sizeof(krb5_int32)) {
+	*intp = (((krb5_int32) ((unsigned char) (*bufp)[0]) << 24) |
+		 ((krb5_int32) ((unsigned char) (*bufp)[1]) << 16) |
+		 ((krb5_int32) ((unsigned char) (*bufp)[2]) << 8) |
+		 ((krb5_int32) ((unsigned char) (*bufp)[3])));
+	*bufp += sizeof(krb5_int32);
+	*remainp -= sizeof(krb5_int32);
+	return(0);
+    }
+    else
+	return(ENOMEM);
+}
+
+/*
+ * krb5_ser_unpack_int64()	- Unpack an 8-byte integer if it's there.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_unpack_int64(krb5_int64 *intp, krb5_octet **bufp, size_t *remainp)
+{
+    if (*remainp >= sizeof(krb5_int64)) {
+	*intp = load_64_be((unsigned char *)*bufp);
+	*bufp += sizeof(krb5_int64);
+	*remainp -= sizeof(krb5_int64);
+	return(0);
+    }
+    else
+	return(ENOMEM);
+}
+
+/*
+ * krb5_ser_unpack_bytes()	- Unpack a byte string if it's there.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_unpack_bytes(krb5_octet *istring, size_t isize, krb5_octet **bufp, size_t *remainp)
+{
+    if (*remainp >= isize) {
+	memcpy(istring, *bufp, isize);
+	*bufp += isize;
+	*remainp -= isize;
+	return(0);
+    }
+    else
+	return(ENOMEM);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/set_realm.c b/krb5-1-6/src/lib/krb5/krb/set_realm.c
new file mode 100644
index 000000000..16112a8da
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/set_realm.c
@@ -0,0 +1,52 @@
+/*
+ * lib/krb5/krb/set_realm.c
+ *
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_set_principal_realm(krb5_context context, krb5_principal principal, const char *realm)
+{
+	size_t	length;
+	char	*newrealm;
+	
+	if (!realm || !*realm)
+		return -EINVAL;
+
+	length = strlen(realm);
+	newrealm = malloc(length+1); /* Include room for the null */
+	if (!newrealm)
+		return -ENOMEM;
+	strcpy(newrealm, realm);
+	
+	(void) krb5_xfree(krb5_princ_realm(context,principal)->data);
+
+	krb5_princ_realm(context, principal)->length = length;
+	krb5_princ_realm(context, principal)->data = newrealm;
+
+	return 0;
+}
+
+
diff --git a/krb5-1-6/src/lib/krb5/krb/srv_dec_tkt.c b/krb5-1-6/src/lib/krb5/krb/srv_dec_tkt.c
new file mode 100644
index 000000000..e994ac995
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/srv_dec_tkt.c
@@ -0,0 +1,94 @@
+/*
+ * lib/krb5/krb/srv_dec_tkt.c
+ *
+ * Copyright 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * Server decrypt ticket via keytab or keyblock. 
+ *
+ * Different from krb5_rd_req_decoded. (krb5/src/lib/krb5/krb/rd_req_dec.c)
+ *   - No krb5_principal_compare or KRB5KRB_AP_ERR_BADMATCH error.
+ *   - No replay cache processing.
+ *   - No skew checking or KRB5KRB_AP_ERR_SKEW error.
+ *   - No address checking or KRB5KRB_AP_ERR_BADADDR error.
+ *   - No time validation.
+ *   - No permitted enctype validation or KRB5_NOPERM_ETYPE error.
+ *   - Does not free ticket->enc_part2 on error. 
+ */
+
+#include <k5-int.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5int_server_decrypt_ticket_keyblock(krb5_context context,
+				       const krb5_keyblock *key,
+				       krb5_ticket *ticket)
+{
+    krb5_error_code retval;
+    krb5_data *realm;
+    krb5_transited *trans;
+
+    retval = krb5_decrypt_tkt_part(context, key, ticket);
+    if (retval) 
+	goto done;
+
+    trans = &ticket->enc_part2->transited;
+    realm = &ticket->enc_part2->client->realm;
+    if (trans->tr_contents.data && *trans->tr_contents.data) {
+	retval = krb5_check_transited_list(context, &trans->tr_contents,
+					   realm, &ticket->server->realm);
+	goto done;
+    }
+
+    if (ticket->enc_part2->flags & TKT_FLG_INVALID) {	/* ie, KDC_OPT_POSTDATED */
+	retval = KRB5KRB_AP_ERR_TKT_INVALID;
+	goto done;
+    }
+
+  done:
+    return retval;
+}
+
+
+krb5_error_code	KRB5_CALLCONV
+krb5_server_decrypt_ticket_keytab(krb5_context context,
+				  const krb5_keytab kt,
+				  krb5_ticket *ticket)
+{
+    krb5_error_code       retval;
+    krb5_enctype          enctype;
+    krb5_keytab_entry     ktent;
+
+    enctype = ticket->enc_part.enctype;
+
+    if ((retval = krb5_kt_get_entry(context, kt, ticket->server,
+                                    ticket->enc_part.kvno,
+                                    enctype, &ktent)))
+        return retval;
+
+    retval = krb5int_server_decrypt_ticket_keyblock(context,
+						    &ktent.key, ticket);
+    /* Upon error, Free keytab entry first, then return */
+
+    (void) krb5_kt_free_entry(context, &ktent);
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/srv_rcache.c b/krb5-1-6/src/lib/krb5/krb/srv_rcache.c
new file mode 100644
index 000000000..f88df5ee5
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/srv_rcache.c
@@ -0,0 +1,134 @@
+/*
+ * lib/krb5/krb/srv_rcache.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Allocate & prepare a default replay cache for a server.
+ */
+
+#include "k5-int.h"
+#include <ctype.h>
+#include <stdio.h>
+
+/* Macro for valid RC name characters*/
+#define isvalidrcname(x) ((!ispunct(x))&&isgraph(x))
+krb5_error_code KRB5_CALLCONV
+krb5_get_server_rcache(krb5_context context, const krb5_data *piece,
+		       krb5_rcache *rcptr)
+{
+    krb5_rcache rcache = 0;
+    char *cachename = 0, *cachetype;
+    char tmp[4];
+    krb5_error_code retval;
+    int p, i;
+    unsigned int len;
+
+#ifdef HAVE_GETEUID
+    unsigned long tens;
+    unsigned long uid = geteuid();
+#endif
+    
+    if (piece == NULL)
+	return ENOMEM;
+    
+    cachetype = krb5_rc_default_type(context);
+
+    len = piece->length + 3 + 1;
+    for (i = 0; i < piece->length; i++) {
+	if (piece->data[i] == '-')
+	    len++;
+	else if (!isvalidrcname((int) piece->data[i]))
+	    len += 3;
+    }
+
+#ifdef HAVE_GETEUID
+    len += 2;	/* _<uid> */
+    for (tens = 1; (uid / tens) > 9 ; tens *= 10)
+	len++;
+#endif
+    
+    cachename = malloc(strlen(cachetype) + 5 + len);
+    if (!cachename) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    strcpy(cachename, cachetype);
+
+    p = strlen(cachename);
+    cachename[p++] = ':';
+    for (i = 0; i < piece->length; i++) {
+	if (piece->data[i] == '-') {
+	    cachename[p++] = '-';
+	    cachename[p++] = '-';
+	    continue;
+	}
+	if (!isvalidrcname((int) piece->data[i])) {
+	    sprintf(tmp, "%03o", piece->data[i]);
+	    cachename[p++] = '-';
+	    cachename[p++] = tmp[0];
+	    cachename[p++] = tmp[1];
+	    cachename[p++] = tmp[2];
+	    continue;
+	}
+	cachename[p++] = piece->data[i];
+    }
+
+#ifdef HAVE_GETEUID
+    cachename[p++] = '_';
+    while (tens) {
+	cachename[p++] = '0' + ((uid / tens) % 10);
+	tens /= 10;
+    }
+#endif
+
+    cachename[p++] = '\0';
+
+    retval = krb5_rc_resolve_full(context, &rcache, cachename);
+    if (retval) {
+	rcache = 0;
+	goto cleanup;
+    }
+
+    /*
+     * First try to recover the replay cache; if that doesn't work,
+     * initialize it.
+     */
+    retval = krb5_rc_recover_or_initialize(context, rcache, context->clockskew);
+    if (retval) {
+	krb5_rc_close(context, rcache);
+	rcache = 0;
+	goto cleanup;
+    }
+
+    *rcptr = rcache;
+    rcache = 0;
+    retval = 0;
+
+cleanup:
+    if (rcache)
+	krb5_xfree(rcache);
+    if (cachename)
+	krb5_xfree(cachename);
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/str_conv.c b/krb5-1-6/src/lib/krb5/krb/str_conv.c
new file mode 100644
index 000000000..f080c8f4f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/str_conv.c
@@ -0,0 +1,377 @@
+/*
+ * lib/kadm/str_conv.c
+ *
+ * Copyright 1995, 1999 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * str_conv.c - Convert between strings and Kerberos internal data.
+ */
+
+/*
+ * Table of contents:
+ *
+ * String decoding:
+ * ----------------
+ * krb5_string_to_salttype()	- Convert string to salttype (krb5_int32)
+ * krb5_string_to_timestamp()	- Convert string to krb5_timestamp.
+ * krb5_string_to_deltat()	- Convert string to krb5_deltat.
+ *
+ * String encoding:
+ * ----------------
+ * krb5_salttype_to_string()	- Convert salttype (krb5_int32) 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.
+ */
+
+#include "k5-int.h"
+#include <ctype.h>
+
+/* Salt type conversions */
+
+/*
+ * Local data structures.
+ */
+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	*/
+};
+
+/*
+ * Lookup tables.
+ */
+
+#include "kdb.h"
+static const struct salttype_lookup_entry salttype_table[] = {
+/* salt type			input specifier	output string  */
+/*-----------------------------	--------------- ---------------*/
+{ KRB5_KDB_SALTTYPE_NORMAL,	"normal",	"Version 5"	  },
+{ KRB5_KDB_SALTTYPE_V4,		"v4",		"Version 4"	  },
+{ KRB5_KDB_SALTTYPE_NOREALM,	"norealm",	"Version 5 - No Realm" },
+{ KRB5_KDB_SALTTYPE_ONLYREALM,	"onlyrealm",	"Version 5 - Realm Only" },
+{ KRB5_KDB_SALTTYPE_SPECIAL,	"special",	"Special" },
+{ KRB5_KDB_SALTTYPE_AFS3,	"afs3",		"AFS version 3"    }
+};
+static const int salttype_table_nents = sizeof(salttype_table)/
+					sizeof(salttype_table[0]);
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_salttype(char *string, krb5_int32 *salttypep)
+{
+    int i;
+    int found;
+
+    found = 0;
+    for (i=0; i<salttype_table_nents; i++) {
+	if (!strcasecmp(string, salttype_table[i].stt_specifier)) {
+	    found = 1;
+	    *salttypep = salttype_table[i].stt_enctype;
+	    break;
+	}
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+/*
+ * Internal datatype to string routines.
+ *
+ * These routines return 0 for success, EINVAL for invalid parameter, ENOMEM
+ * if the supplied buffer/length will not contain the output.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_salttype_to_string(krb5_int32 salttype, char *buffer, size_t buflen)
+{
+    int i;
+    const char *out;
+
+    out = (char *) NULL;
+    for (i=0; i<salttype_table_nents; i++) {
+	if (salttype ==  salttype_table[i].stt_enctype) {
+	    out = salttype_table[i].stt_output;
+	    break;
+	}
+    }
+    if (out) {
+	if (buflen > strlen(out))
+	    strcpy(buffer, out);
+	else
+	    out = (char *) NULL;
+	return((out) ? 0 : ENOMEM);
+    }
+    else
+	return(EINVAL);
+}
+
+/* (absolute) time conversions */
+
+#ifndef HAVE_STRFTIME
+#undef strftime
+#define strftime my_strftime
+static size_t strftime (char *, size_t, const char *, const struct tm *);
+#endif
+
+#ifdef HAVE_STRPTIME
+#ifdef NEED_STRPTIME_PROTO
+extern char *strptime (const char *, const char *,
+			    struct tm *)
+#ifdef __cplusplus
+    throw()
+#endif
+    ;
+#endif
+#else /* HAVE_STRPTIME */
+#undef strptime
+#define strptime my_strptime
+static char *strptime (const char *, const char *, struct tm *);
+#endif
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_timestamp(char *string, krb5_timestamp *timestampp)
+{
+    int i;
+    struct tm timebuf;
+    time_t now, ret_time;
+    char *s;
+    static const char * const atime_format_table[] = {
+	"%Y%m%d%H%M%S",		/* yyyymmddhhmmss		*/
+	"%Y.%m.%d.%H.%M.%S",	/* yyyy.mm.dd.hh.mm.ss		*/
+	"%y%m%d%H%M%S",		/* yymmddhhmmss			*/
+	"%y.%m.%d.%H.%M.%S",	/* yy.mm.dd.hh.mm.ss		*/
+	"%y%m%d%H%M",		/* yymmddhhmm			*/
+	"%H%M%S",		/* hhmmss			*/
+	"%H%M",			/* hhmm				*/
+	"%T",			/* hh:mm:ss			*/
+	"%R",			/* hh:mm			*/
+	/* The following not really supported unless native strptime present */
+	"%x:%X",		/* locale-dependent short format */
+	"%d-%b-%Y:%T",		/* dd-month-yyyy:hh:mm:ss	*/
+	"%d-%b-%Y:%R"		/* dd-month-yyyy:hh:mm		*/
+    };
+    static const int atime_format_table_nents =
+	sizeof(atime_format_table)/sizeof(atime_format_table[0]);
+
+
+    now = time((time_t *) NULL);
+    for (i=0; i<atime_format_table_nents; i++) {
+        /* We reset every time throughout the loop as the manual page
+	 * indicated that no guarantees are made as to preserving timebuf
+	 * when parsing fails
+	 */
+#ifdef HAVE_LOCALTIME_R
+	(void) localtime_r(&now, &timebuf);
+#else
+	memcpy(&timebuf, localtime(&now), sizeof(timebuf));
+#endif
+	if ((s = strptime(string, atime_format_table[i], &timebuf))
+	    && (s != string)) {
+ 	    /* See if at end of buffer - otherwise partial processing */
+	    while(*s != 0 && isspace((int) *s)) s++;
+	    if (*s != 0)
+	        continue;
+	    if (timebuf.tm_year <= 0)
+		continue;	/* clearly confused */
+	    ret_time = mktime(&timebuf);
+	    if (ret_time == (time_t) -1)
+		continue;	/* clearly confused */
+	    *timestampp = (krb5_timestamp) ret_time;
+	    return 0;
+	}
+    }
+    return(EINVAL);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_timestamp_to_string(krb5_timestamp timestamp, char *buffer, size_t buflen)
+{
+    int ret;
+    time_t timestamp2 = timestamp;
+    struct tm tmbuf;
+    const char *fmt = "%c"; /* This is to get around gcc -Wall warning that 
+			       the year returned might be two digits */
+
+#ifdef HAVE_LOCALTIME_R
+    (void) localtime_r(×tamp2, &tmbuf);
+#else
+    memcpy(&tmbuf, localtime(×tamp2), sizeof(tmbuf));
+#endif
+    ret = strftime(buffer, buflen, fmt, &tmbuf);
+    if (ret == 0 || ret == buflen)
+	return(ENOMEM);
+    return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, size_t buflen, char *pad)
+{
+    struct tm	*tmp;
+    size_t i;
+    size_t	ndone;
+    time_t timestamp2 = timestamp;
+    struct tm tmbuf;
+
+    static const char * const sftime_format_table[] = {
+	"%c",			/* Default locale-dependent date and time */
+	"%d %b %Y %T",		/* dd mon yyyy hh:mm:ss			*/
+	"%x %X",		/* locale-dependent short format	*/
+	"%d/%m/%Y %R"		/* dd/mm/yyyy hh:mm			*/
+    };
+    static const int sftime_format_table_nents =
+	sizeof(sftime_format_table)/sizeof(sftime_format_table[0]);
+
+#ifdef HAVE_LOCALTIME_R
+    tmp = localtime_r(×tamp2, &tmbuf);
+#else
+    memcpy((tmp = &tmbuf), localtime(×tamp2), sizeof(tmbuf));
+#endif
+    ndone = 0;
+    for (i=0; i<sftime_format_table_nents; i++) {
+	if ((ndone = strftime(buffer, buflen, sftime_format_table[i], tmp)))
+	    break;
+    }
+    if (!ndone) {
+#define sftime_default_len	2+1+2+1+4+1+2+1+2+1
+	if (buflen >= sftime_default_len) {
+	    sprintf(buffer, "%02d/%02d/%4d %02d:%02d",
+		    tmp->tm_mday, tmp->tm_mon+1, 1900+tmp->tm_year,
+		    tmp->tm_hour, tmp->tm_min);
+	    ndone = strlen(buffer);
+	}
+    }
+    if (ndone && pad) {
+	for (i=ndone; i<buflen-1; i++)
+	    buffer[i] = *pad;
+	buffer[buflen-1] = '\0';
+    }
+    return((ndone) ? 0 : ENOMEM);
+}
+
+/* relative time (delta-t) conversions */
+
+/* string->deltat is in deltat.y */
+
+krb5_error_code KRB5_CALLCONV
+krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen)
+{
+    int			days, hours, minutes, seconds;
+    krb5_deltat		dt;
+
+    /*
+     * We want something like ceil(log10(2**(nbits-1))) + 1.  That log
+     * value is log10(2)*(nbits-1) or log10(2**8)*(nbits-1)/8.  So,
+     * 2.4... is log10(256), rounded up.  Add one to handle leading
+     * minus, and one more to force int cast to round the value up.
+     * This doesn't include room for a trailing nul.
+     *
+     * This will break if bytes are more than 8 bits.
+     */
+#define MAX_CHARS_FOR_INT_TYPE(TYPE)	((int) (2 + 2.408241 * sizeof (TYPE)))
+    char tmpbuf[MAX_CHARS_FOR_INT_TYPE(int) * 4 + 8];
+
+    days = (int) (deltat / (24*3600L));
+    dt = deltat % (24*3600L);
+    hours = (int) (dt / 3600);
+    dt %= 3600;
+    minutes = (int) (dt / 60);
+    seconds = (int) (dt % 60);
+
+    memset (tmpbuf, 0, sizeof (tmpbuf));
+    if (days == 0)
+	sprintf(buffer, "%d:%02d:%02d", hours, minutes, seconds);
+    else if (hours || minutes || seconds)
+	sprintf(buffer, "%d %s %02d:%02d:%02d", days,
+		(days > 1) ? "days" : "day",
+		hours, minutes, seconds);
+    else
+	sprintf(buffer, "%d %s", days,
+		(days > 1) ? "days" : "day");
+    if (tmpbuf[sizeof(tmpbuf)-1] != 0)
+	/* Something must be very wrong with my math above, or the
+	   assumptions going into it...  */
+	abort ();
+    if (strlen (tmpbuf) > buflen)
+	return ENOMEM;
+    else
+	strncpy (buffer, tmpbuf, buflen);
+    return 0;
+}
+
+#undef __P
+#define __P(X) X
+
+#if !defined (HAVE_STRFTIME) || !defined (HAVE_STRPTIME)
+#undef _CurrentTimeLocale
+#define _CurrentTimeLocale (&dummy_locale_info)
+
+struct dummy_locale_info_t {
+    char d_t_fmt[15];
+    char t_fmt_ampm[12];
+    char t_fmt[9];
+    char d_fmt[9];
+    char day[7][10];
+    char abday[7][4];
+    char mon[12][10];
+    char abmon[12][4];
+    char am_pm[2][3];
+};
+static const struct dummy_locale_info_t dummy_locale_info = {
+    "%a %b %d %X %Y",		/* %c */
+    "%I:%M:%S %p",		/* %r */
+    "%H:%M:%S",			/* %X */
+    "%m/%d/%y",			/* %x */
+    { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+      "Saturday" },
+    { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
+    { "January", "February", "March", "April", "May", "June",
+      "July", "August", "September", "October", "November", "December" },
+    { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
+    { "AM", "PM" },
+};
+#undef  TM_YEAR_BASE
+#define TM_YEAR_BASE 1900
+#endif
+
+#ifndef HAVE_STRFTIME
+#undef  DAYSPERLYEAR
+#define DAYSPERLYEAR 366
+#undef  DAYSPERNYEAR
+#define DAYSPERNYEAR 365
+#undef  DAYSPERWEEK
+#define DAYSPERWEEK 7
+#undef  isleap
+#define isleap(N)	((N % 4) == 0 && (N % 100 != 0 || N % 400 == 0))
+#undef  tzname
+#define tzname my_tzname
+static const char *const tzname[2] = { 0, 0 };
+#undef  tzset
+#define tzset()
+
+#include "strftime.c"
+#endif
+
+#ifndef HAVE_STRPTIME
+#include "strptime.c"
+#endif
diff --git a/krb5-1-6/src/lib/krb5/krb/strftime.c b/krb5-1-6/src/lib/krb5/krb/strftime.c
new file mode 100644
index 000000000..f2a5cb719
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/strftime.c
@@ -0,0 +1,415 @@
+/*	$NetBSD: strftime.c,v 1.8 1999/02/07 17:33:30 augustss Exp $	*/
+
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char *sccsid = "@(#)strftime.c	5.11 (Berkeley) 2/24/91";
+#else
+__RCSID("$NetBSD: strftime.c,v 1.8 1999/02/07 17:33:30 augustss Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+#include <time.h>
+
+static	int _add __P((const char *, char **, const char *));
+static	int _conv __P((int, int, int, char **, const char *));
+static	int _secs __P((const struct tm *, char **, const char *));
+static	size_t _fmt __P((const char *, const struct tm *, char **,
+	    const char *));
+
+static size_t
+strftime(s, maxsize, format, t)
+	char *s;
+	size_t maxsize;
+	const char *format;
+	const struct tm *t;
+{
+	char *pt;
+
+	tzset();
+	if (maxsize < 1)
+		return (0);
+
+	pt = s;
+	if (_fmt(format, t, &pt, s + maxsize)) {
+		*pt = '\0';
+		return (pt - s);
+	} else
+		return (0);
+}
+
+#define SUN_WEEK(t)	(((t)->tm_yday + 7 - \
+				((t)->tm_wday)) / 7)
+#define MON_WEEK(t)	(((t)->tm_yday + 7 - \
+				((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
+
+static size_t
+_fmt(format, t, pt, ptlim)
+	const char *format;
+	const struct tm *t;
+	char **pt;
+	const char * const ptlim;
+{
+	for (; *format; ++format) {
+		if (*format == '%') {
+			++format;
+			if (*format == 'E') {
+				/* Alternate Era */
+				++format;
+			} else if (*format == 'O') {
+				/* Alternate numeric symbols */
+				++format;
+			}
+			switch (*format) {
+			case '\0':
+				--format;
+				break;
+			case 'A':
+				if (t->tm_wday < 0 || t->tm_wday > 6)
+					return (0);
+				if (!_add(_CurrentTimeLocale->day[t->tm_wday],
+				    pt, ptlim))
+					return (0);
+				continue;
+
+			case 'a':
+				if (t->tm_wday < 0 || t->tm_wday > 6)
+					return (0);
+				if (!_add(_CurrentTimeLocale->abday[t->tm_wday],
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'B':
+				if (t->tm_mon < 0 || t->tm_mon > 11)
+					return (0);
+				if (!_add(_CurrentTimeLocale->mon[t->tm_mon],
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'b':
+			case 'h':
+				if (t->tm_mon < 0 || t->tm_mon > 11)
+					return (0);
+				if (!_add(_CurrentTimeLocale->abmon[t->tm_mon],
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'C':
+				if (!_conv((t->tm_year + TM_YEAR_BASE) / 100,
+				    2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'c':
+				if (!_fmt(_CurrentTimeLocale->d_t_fmt, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'D':
+				if (!_fmt("%m/%d/%y", t, pt, ptlim))
+					return (0);
+				continue;
+			case 'd':
+				if (!_conv(t->tm_mday, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'e':
+				if (!_conv(t->tm_mday, 2, ' ', pt, ptlim))
+					return (0);
+				continue;
+			case 'H':
+				if (!_conv(t->tm_hour, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'I':
+				if (!_conv(t->tm_hour % 12 ?
+				    t->tm_hour % 12 : 12, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'j':
+				if (!_conv(t->tm_yday + 1, 3, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'k':
+				if (!_conv(t->tm_hour, 2, ' ', pt, ptlim))
+					return (0);
+				continue;
+			case 'l':
+				if (!_conv(t->tm_hour % 12 ?
+				    t->tm_hour % 12: 12, 2, ' ', pt, ptlim))
+					return (0);
+				continue;
+			case 'M':
+				if (!_conv(t->tm_min, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'm':
+				if (!_conv(t->tm_mon + 1, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'n':
+				if (!_add("\n", pt, ptlim))
+					return (0);
+				continue;
+			case 'p':
+				if (!_add(_CurrentTimeLocale->am_pm[t->tm_hour
+				    >= 12], pt, ptlim))
+					return (0);
+				continue;
+			case 'R':
+				if (!_fmt("%H:%M", t, pt, ptlim))
+					return (0);
+				continue;
+			case 'r':
+				if (!_fmt(_CurrentTimeLocale->t_fmt_ampm, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'S':
+				if (!_conv(t->tm_sec, 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 's':
+				if (!_secs(t, pt, ptlim))
+					return (0);
+				continue;
+			case 'T':
+				if (!_fmt("%H:%M:%S", t, pt, ptlim))
+					return (0);
+				continue;
+			case 't':
+				if (!_add("\t", pt, ptlim))
+					return (0);
+				continue;
+			case 'U':
+				if (!_conv(SUN_WEEK(t), 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'u':
+				if (!_conv(t->tm_wday ? t->tm_wday : 7, 1, '0',
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'V':	/* ISO 8601 week number */
+			case 'G':	/* ISO 8601 year (four digits) */
+			case 'g':	/* ISO 8601 year (two digits) */
+/*
+** From Arnold Robbins' strftime version 3.0:  "the week number of the
+** year (the first Monday as the first day of week 1) as a decimal number
+** (01-53)."
+** (ado, 1993-05-24)
+**
+** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** "Week 01 of a year is per definition the first week which has the
+** Thursday in this year, which is equivalent to the week which contains
+** the fourth day of January. In other words, the first week of a new year
+** is the week which has the majority of its days in the new year. Week 01
+** might also contain days from the previous year and the week before week
+** 01 of a year is the last week (52 or 53) of the previous year even if
+** it contains days from the new year. A week starts with Monday (day 1)
+** and ends with Sunday (day 7).  For example, the first week of the year
+** 1997 lasts from 1996-12-30 to 1997-01-05..."
+** (ado, 1996-01-02)
+*/
+				{
+					int	year;
+					int	yday;
+					int	wday;
+					int	w;
+
+					year = t->tm_year + TM_YEAR_BASE;
+					yday = t->tm_yday;
+					wday = t->tm_wday;
+					for ( ; ; ) {
+						int	len;
+						int	bot;
+						int	top;
+
+						len = isleap(year) ?
+							DAYSPERLYEAR :
+							DAYSPERNYEAR;
+						/*
+						** What yday (-3 ... 3) does
+						** the ISO year begin on?
+						*/
+						bot = ((yday + 11 - wday) %
+							DAYSPERWEEK) - 3;
+						/*
+						** What yday does the NEXT
+						** ISO year begin on?
+						*/
+						top = bot -
+							(len % DAYSPERWEEK);
+						if (top < -3)
+							top += DAYSPERWEEK;
+						top += len;
+						if (yday >= top) {
+							++year;
+							w = 1;
+							break;
+						}
+						if (yday >= bot) {
+							w = 1 + ((yday - bot) /
+								DAYSPERWEEK);
+							break;
+						}
+						--year;
+						yday += isleap(year) ?
+							DAYSPERLYEAR :
+							DAYSPERNYEAR;
+					}
+#ifdef XPG4_1994_04_09
+					if ((w == 52
+					     && t->tm_mon == TM_JANUARY)
+					    || (w == 1
+						&& t->tm_mon == TM_DECEMBER))
+						w = 53;
+#endif /* defined XPG4_1994_04_09 */
+					if (*format == 'V') {
+						if (!_conv(w, 2, '0',
+							pt, ptlim))
+							return (0);
+					} else if (*format == 'g') {
+						if (!_conv(year % 100, 2, '0',
+							pt, ptlim))
+							return (0);
+					} else	if (!_conv(year, 4, '0',
+							pt, ptlim))
+							return (0);
+				}
+				continue;
+			case 'W':
+				if (!_conv(MON_WEEK(t), 2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'w':
+				if (!_conv(t->tm_wday, 1, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'x':
+				if (!_fmt(_CurrentTimeLocale->d_fmt, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'X':
+				if (!_fmt(_CurrentTimeLocale->t_fmt, t, pt,
+				    ptlim))
+					return (0);
+				continue;
+			case 'y':
+				if (!_conv((t->tm_year + TM_YEAR_BASE) % 100,
+				    2, '0', pt, ptlim))
+					return (0);
+				continue;
+			case 'Y':
+				if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0',
+				    pt, ptlim))
+					return (0);
+				continue;
+			case 'Z':
+				if (tzname[t->tm_isdst ? 1 : 0] &&
+				    !_add(tzname[t->tm_isdst ? 1 : 0], pt,
+				    ptlim))
+					return (0);
+				continue;
+			case '%':
+			/*
+			 * X311J/88-090 (4.12.3.5): if conversion char is
+			 * undefined, behavior is undefined.  Print out the
+			 * character itself as printf(3) does.
+			 */
+			default:
+				break;
+			}
+		}
+		if (*pt == ptlim)
+			return (0);
+		*(*pt)++ = *format;
+	}
+	return (ptlim - *pt);
+}
+
+static int
+_secs(t, pt, ptlim)
+	const struct tm *t;
+	char **pt;
+	const char * const ptlim;
+{
+	char buf[15];
+	time_t s;
+	char *p;
+	struct tm tmp;
+
+	buf[sizeof (buf) - 1] = '\0';
+	/* Make a copy, mktime(3) modifies the tm struct. */
+	tmp = *t;
+	s = mktime(&tmp);
+	for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
+		*p-- = (char)(s % 10 + '0');
+	return (_add(++p, pt, ptlim));
+}
+
+static int
+_conv(n, digits, pad, pt, ptlim)
+	int n, digits;
+	int pad;
+	char **pt;
+	const char * const ptlim;
+{
+	char buf[10];
+	char *p;
+
+	buf[sizeof (buf) - 1] = '\0';
+	for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
+		*p-- = n % 10 + '0';
+	while (p > buf && digits-- > 0)
+		*p-- = pad;
+	return (_add(++p, pt, ptlim));
+}
+
+static int
+_add(str, pt, ptlim)
+	const char *str;
+	char **pt;
+	const char * const ptlim;
+{
+
+	for (;; ++(*pt)) {
+		if (*pt == ptlim)
+			return (0);
+		if ((**pt = *str++) == '\0')
+			return (1);
+	}
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/strptime.c b/krb5-1-6/src/lib/krb5/krb/strptime.c
new file mode 100644
index 000000000..ac52d5c22
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/strptime.c
@@ -0,0 +1,386 @@
+/*	$NetBSD: strptime.c,v 1.18 1999/04/29 02:58:30 tv Exp $	*/
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strptime.c,v 1.18 1999/04/29 02:58:30 tv Exp $");
+#endif
+
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+
+#undef _ctloc
+#define _ctloc(x)		_CurrentTimeLocale->x
+
+/*
+ * We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+#define ALT_E			0x01
+#define ALT_O			0x02
+#define	LEGAL_ALT(x)		{ if (alt_format & ~(x)) return (0); }
+
+
+static	int conv_num __P((const char **, int *, int, int));
+
+
+static char *
+strptime(buf, fmt, tm)
+	const char *buf, *fmt;
+	struct tm *tm;
+{
+	char c;
+	const char *bp;
+	size_t len = 0;
+	int alt_format, i, split_year = 0;
+
+	bp = buf;
+
+	while ((c = *fmt) != '\0') {
+		/* Clear `alternate' modifier prior to new conversion. */
+		alt_format = 0;
+
+		/* Eat up white-space. */
+		if (isspace(c)) {
+			while (isspace(*bp))
+				bp++;
+
+			fmt++;
+			continue;
+		}
+				
+		if ((c = *fmt++) != '%')
+			goto literal;
+
+
+again:		switch (c = *fmt++) {
+		case '%':	/* "%%" is converted to "%". */
+literal:
+			if (c != *bp++)
+				return (0);
+			break;
+
+		/*
+		 * "Alternative" modifiers. Just set the appropriate flag
+		 * and start over again.
+		 */
+		case 'E':	/* "%E?" alternative conversion modifier. */
+			LEGAL_ALT(0);
+			alt_format |= ALT_E;
+			goto again;
+
+		case 'O':	/* "%O?" alternative conversion modifier. */
+			LEGAL_ALT(0);
+			alt_format |= ALT_O;
+			goto again;
+			
+		/*
+		 * "Complex" conversion rules, implemented through recursion.
+		 */
+		case 'c':	/* Date and time, using the locale's format. */
+			LEGAL_ALT(ALT_E);
+			if (!(bp = strptime(bp, _ctloc(d_t_fmt), tm)))
+				return (0);
+			break;
+
+		case 'D':	/* The date as "%m/%d/%y". */
+			LEGAL_ALT(0);
+			if (!(bp = strptime(bp, "%m/%d/%y", tm)))
+				return (0);
+			break;
+
+		case 'R':	/* The time as "%H:%M". */
+			LEGAL_ALT(0);
+			if (!(bp = strptime(bp, "%H:%M", tm)))
+				return (0);
+			break;
+
+		case 'r':	/* The time in 12-hour clock representation. */
+			LEGAL_ALT(0);
+			if (!(bp = strptime(bp, _ctloc(t_fmt_ampm), tm)))
+				return (0);
+			break;
+
+		case 'T':	/* The time as "%H:%M:%S". */
+			LEGAL_ALT(0);
+			if (!(bp = strptime(bp, "%H:%M:%S", tm)))
+				return (0);
+			break;
+
+		case 'X':	/* The time, using the locale's format. */
+			LEGAL_ALT(ALT_E);
+			if (!(bp = strptime(bp, _ctloc(t_fmt), tm)))
+				return (0);
+			break;
+
+		case 'x':	/* The date, using the locale's format. */
+			LEGAL_ALT(ALT_E);
+			if (!(bp = strptime(bp, _ctloc(d_fmt), tm)))
+				return (0);
+			break;
+
+		/*
+		 * "Elementary" conversion rules.
+		 */
+		case 'A':	/* The day of week, using the locale's form. */
+		case 'a':
+			LEGAL_ALT(0);
+			for (i = 0; i < 7; i++) {
+				/* Full name. */
+				len = strlen(_ctloc(day[i]));
+				if (strncasecmp(_ctloc(day[i]), bp, len) == 0)
+					break;
+
+				/* Abbreviated name. */
+				len = strlen(_ctloc(abday[i]));
+				if (strncasecmp(_ctloc(abday[i]), bp, len) == 0)
+					break;
+			}
+
+			/* Nothing matched. */
+			if (i == 7)
+				return (0);
+
+			tm->tm_wday = i;
+			bp += len;
+			break;
+
+		case 'B':	/* The month, using the locale's form. */
+		case 'b':
+		case 'h':
+			LEGAL_ALT(0);
+			for (i = 0; i < 12; i++) {
+				/* Full name. */
+				len = strlen(_ctloc(mon[i]));
+				if (strncasecmp(_ctloc(mon[i]), bp, len) == 0)
+					break;
+
+				/* Abbreviated name. */
+				len = strlen(_ctloc(abmon[i]));
+				if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0)
+					break;
+			}
+
+			/* Nothing matched. */
+			if (i == 12)
+				return (0);
+
+			tm->tm_mon = i;
+			bp += len;
+			break;
+
+		case 'C':	/* The century number. */
+			LEGAL_ALT(ALT_E);
+			if (!(conv_num(&bp, &i, 0, 99)))
+				return (0);
+
+			if (split_year) {
+				tm->tm_year = (tm->tm_year % 100) + (i * 100);
+			} else {
+				tm->tm_year = i * 100;
+				split_year = 1;
+			}
+			break;
+
+		case 'd':	/* The day of month. */
+		case 'e':
+			LEGAL_ALT(ALT_O);
+			if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
+				return (0);
+			break;
+
+		case 'k':	/* The hour (24-hour clock representation). */
+			LEGAL_ALT(0);
+			/* FALLTHROUGH */
+		case 'H':
+			LEGAL_ALT(ALT_O);
+			if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
+				return (0);
+			break;
+
+		case 'l':	/* The hour (12-hour clock representation). */
+			LEGAL_ALT(0);
+			/* FALLTHROUGH */
+		case 'I':
+			LEGAL_ALT(ALT_O);
+			if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
+				return (0);
+			if (tm->tm_hour == 12)
+				tm->tm_hour = 0;
+			break;
+
+		case 'j':	/* The day of year. */
+			LEGAL_ALT(0);
+			if (!(conv_num(&bp, &i, 1, 366)))
+				return (0);
+			tm->tm_yday = i - 1;
+			break;
+
+		case 'M':	/* The minute. */
+			LEGAL_ALT(ALT_O);
+			if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
+				return (0);
+			break;
+
+		case 'm':	/* The month. */
+			LEGAL_ALT(ALT_O);
+			if (!(conv_num(&bp, &i, 1, 12)))
+				return (0);
+			tm->tm_mon = i - 1;
+			break;
+
+		case 'p':	/* The locale's equivalent of AM/PM. */
+			LEGAL_ALT(0);
+			/* AM? */
+			if (strcasecmp(_ctloc(am_pm[0]), bp) == 0) {
+				if (tm->tm_hour > 11)
+					return (0);
+
+				bp += strlen(_ctloc(am_pm[0]));
+				break;
+			}
+			/* PM? */
+			else if (strcasecmp(_ctloc(am_pm[1]), bp) == 0) {
+				if (tm->tm_hour > 11)
+					return (0);
+
+				tm->tm_hour += 12;
+				bp += strlen(_ctloc(am_pm[1]));
+				break;
+			}
+
+			/* Nothing matched. */
+			return (0);
+
+		case 'S':	/* The seconds. */
+			LEGAL_ALT(ALT_O);
+			if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
+				return (0);
+			break;
+
+		case 'U':	/* The week of year, beginning on sunday. */
+		case 'W':	/* The week of year, beginning on monday. */
+			LEGAL_ALT(ALT_O);
+			/*
+			 * XXX This is bogus, as we can not assume any valid
+			 * information present in the tm structure at this
+			 * point to calculate a real value, so just check the
+			 * range for now.
+			 */
+			 if (!(conv_num(&bp, &i, 0, 53)))
+				return (0);
+			 break;
+
+		case 'w':	/* The day of week, beginning on sunday. */
+			LEGAL_ALT(ALT_O);
+			if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
+				return (0);
+			break;
+
+		case 'Y':	/* The year. */
+			LEGAL_ALT(ALT_E);
+			if (!(conv_num(&bp, &i, 0, 9999)))
+				return (0);
+
+			tm->tm_year = i - TM_YEAR_BASE;
+			break;
+
+		case 'y':	/* The year within 100 years of the epoch. */
+			LEGAL_ALT(ALT_E | ALT_O);
+			if (!(conv_num(&bp, &i, 0, 99)))
+				return (0);
+
+			if (split_year) {
+				tm->tm_year = ((tm->tm_year / 100) * 100) + i;
+				break;
+			}
+			split_year = 1;
+			if (i <= 68)
+				tm->tm_year = i + 2000 - TM_YEAR_BASE;
+			else
+				tm->tm_year = i + 1900 - TM_YEAR_BASE;
+			break;
+
+		/*
+		 * Miscellaneous conversions.
+		 */
+		case 'n':	/* Any kind of white-space. */
+		case 't':
+			LEGAL_ALT(0);
+			while (isspace(*bp))
+				bp++;
+			break;
+
+
+		default:	/* Unknown/unsupported conversion. */
+			return (0);
+		}
+
+
+	}
+
+	/* LINTED functional specification */
+	return ((char *)bp);
+}
+
+
+static int
+conv_num(buf, dest, llim, ulim)
+	const char **buf;
+	int *dest;
+	int llim, ulim;
+{
+	int result = 0;
+
+	/* The limit also determines the number of valid digits. */
+	int rulim = ulim;
+
+	if (**buf < '0' || **buf > '9')
+		return (0);
+
+	do {
+		result *= 10;
+		result += *(*buf)++ - '0';
+		rulim /= 10;
+	} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+	if (result < llim || result > ulim)
+		return (0);
+
+	*dest = result;
+	return (1);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/t_deltat.c b/krb5-1-6/src/lib/krb5/krb/t_deltat.c
new file mode 100644
index 000000000..a07ba4232
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/t_deltat.c
@@ -0,0 +1,158 @@
+/*
+ * lib/krb5/krb/t_deltat.c
+ *
+ * Copyright 1999 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+
+int
+main (void)
+{
+    struct {
+	char *string;
+	krb5_deltat expected;
+	int is_error;
+#define GOOD(STR,VAL) { STR, VAL, 0 }
+#define BAD(STR) { STR, 0, 1 }
+#define DAY (24 * 3600)
+#define HOUR 3600
+#ifdef MIN
+#undef MIN
+#endif
+#define MIN 60
+    } values[] = {
+	/* d-h-m-s patterns */
+	GOOD ("3d", 3*DAY),
+	GOOD ("3h", 3*HOUR),
+	GOOD ("3m", 3*MIN),
+	GOOD ("3s", 3),
+	BAD ("3dd"),
+	GOOD ("3d4m    42s", 3 * DAY + 4 * MIN + 42),
+	GOOD ("3d-1h", 3 * DAY - 1 * HOUR),
+	GOOD ("3d -1h", 3 * DAY - HOUR),
+	GOOD ("3d4h5m6s", 3 * DAY + 4 * HOUR + 5 * MIN + 6),
+	BAD ("3d4m5h"),
+	GOOD ("12345s", 12345),
+	GOOD ("1m 12345s", MIN + 12345),
+	GOOD ("1m12345s", MIN + 12345),
+	GOOD ("3d 0m", 3 * DAY),
+	GOOD ("3d 0m  ", 3 * DAY),
+	GOOD ("3d \n\t 0m  ", 3 * DAY),
+	/* colon patterns */
+	GOOD ("42-13:42:47", 42 * DAY + 13 * HOUR + 42 * MIN + 47),
+	BAD ("3: 4"),
+	BAD ("13:0003"),
+	GOOD ("12:34", 12 * HOUR + 34 * MIN),
+	GOOD ("1:02:03", 1 * HOUR + 2 * MIN + 3),
+	BAD ("3:-4"),
+	/* XX We might want to require exactly two digits after a colon?  */
+	GOOD ("3:4", 3 * HOUR + 4 * MIN),
+	/* misc */
+	GOOD ("42", 42),
+	BAD ("1-2"),
+	/* Test overflow limitations */
+	GOOD ("2147483647s", 2147483647),
+	BAD ("2147483648s"), 
+	GOOD ("24855d", 24855 * DAY),
+	BAD ("24856d"),
+	BAD ("24855d 100000000h"),
+	GOOD ("24855d 3h", 24855 * DAY + 3 * HOUR),
+	BAD ("24855d 4h"),
+	GOOD ("24855d 11647s", 24855 * DAY + 11647),
+	BAD ("24855d 11648s"),
+	GOOD ("24855d 194m 7s", 24855 * DAY + 194 * MIN + 7),
+	BAD ("24855d 194m 8s"),
+	BAD ("24855d 195m"),
+	BAD ("24855d 19500000000m"),
+	GOOD ("24855d 3h 14m 7s", 24855 * DAY + 3 * HOUR + 14 * MIN + 7),
+	BAD ("24855d 3h 14m 8s"),
+	GOOD ("596523h", 596523 * HOUR),
+	BAD ("596524h"),
+	GOOD ("596523h 847s", 596523 * HOUR + 847),
+	BAD ("596523h 848s"),
+	GOOD ("596523h 14m 7s", 596523 * HOUR + 14 * MIN + 7),
+	BAD ("596523h 14m 8s"),
+	GOOD ("35791394m", 35791394 * MIN),
+	GOOD ("35791394m7s", 35791394 * MIN + 7),
+	BAD ("35791394m8s"),
+	/* Test underflow */
+	GOOD ("-2147483647s", -2147483647),
+	/* This should be valid, but isn't */
+	/*BAD ("-2147483648s"),*/
+	GOOD ("-24855d", -24855 * DAY),
+	BAD ("-24856d"),
+	BAD ("-24855d -100000000h"),
+	GOOD ("-24855d -3h", -24855 * DAY - 3 * HOUR),
+	BAD ("-24855d -4h"),
+	GOOD ("-24855d -11647s", -24855 * DAY - 11647),
+	BAD ("-24855d -11649s"),
+	GOOD ("-24855d -194m -7s", -24855 * DAY - 194 * MIN - 7),
+	BAD ("-24855d -194m -9s"),
+	BAD ("-24855d -195m"),
+	BAD ("-24855d -19500000000m"),
+	GOOD ("-24855d -3h -14m -7s", -24855 * DAY - 3 * HOUR - 14 * MIN - 7),
+	BAD ("-24855d -3h -14m -9s"),
+	GOOD ("-596523h", -596523 * HOUR),
+	BAD ("-596524h"),
+	GOOD ("-596523h -847s", -596523 * HOUR - 847),
+	GOOD ("-596523h -848s", -596523 * HOUR - 848),
+	BAD ("-596523h -849s"),
+	GOOD ("-596523h -14m -8s", -596523 * HOUR - 14 * MIN - 8),
+	BAD ("-596523h -14m -9s"),
+	GOOD ("-35791394m", -35791394 * MIN),
+	GOOD ("-35791394m7s", -35791394 * MIN + 7),
+	BAD ("-35791394m-9s"),
+	
+    };
+    int fail = 0;
+    int i;
+
+    for (i = 0; i < sizeof(values)/sizeof(values[0]); i++) {
+	krb5_deltat result;
+	krb5_error_code code;
+
+	code = krb5_string_to_deltat (values[i].string, &result);
+	if (code && !values[i].is_error) {
+	    fprintf (stderr, "unexpected error for `%s'\n", values[i].string);
+	    fail++;
+	} else if (!code && values[i].is_error) {
+	    fprintf (stderr, "expected but didn't get error for `%s'\n",
+		     values[i].string);
+	    fail++;
+	} else if (code && values[i].is_error) {
+	    /* do nothing */
+	} else if (result != values[i].expected) {
+	    fprintf (stderr, "got %ld instead of expected %ld for `%s'\n",
+		     (long) result, (long) values[i].expected,
+		     values[i].string);
+	    fail++;
+	}
+    }
+    if (fail == 0)
+	printf ("Passed all %d tests.\n", i);
+    else
+	printf ("Failed %d of %d tests.\n", fail, i);
+    return fail;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/t_expand.c b/krb5-1-6/src/lib/krb5/krb/t_expand.c
new file mode 100644
index 000000000..a8b2757df
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/t_expand.c
@@ -0,0 +1,2 @@
+#define TEST
+#include "chk_trans.c"
diff --git a/krb5-1-6/src/lib/krb5/krb/t_kerb.c b/krb5-1-6/src/lib/krb5/krb/t_kerb.c
new file mode 100644
index 000000000..9e3116170
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/t_kerb.c
@@ -0,0 +1,232 @@
+/*
+ * This driver routine is used to test many of the standard Kerberos library
+ * routines.
+ */
+
+#include "krb5.h"
+#include "autoconf.h"
+#ifdef KRB5_KRB4_COMPAT
+#include "kerberosIV/krb.h"
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "com_err.h"
+
+void test_string_to_timestamp (krb5_context, char *);
+void test_425_conv_principal (krb5_context, char *, char*, char *);
+void test_524_conv_principal (krb5_context, char *);
+void test_parse_name (krb5_context, const char *);
+void test_set_realm (krb5_context, const char *, const char *);
+void usage (char *);
+
+void test_string_to_timestamp(krb5_context ctx, char *ktime)
+{
+    krb5_timestamp	timestamp;
+    time_t		t;
+    krb5_error_code	retval;
+
+    retval = krb5_string_to_timestamp(ktime, ×tamp);
+    if (retval) {
+	com_err("krb5_string_to_timestamp", retval, 0);
+	return;
+    }
+    t = (time_t) timestamp;
+    printf("Parsed time was %s", ctime(&t));
+}
+
+void test_425_conv_principal(krb5_context ctx, char *name, char *inst, char *realm)
+{
+    krb5_error_code	retval;
+    krb5_principal	princ;
+    char		*out_name;
+
+    retval = krb5_425_conv_principal(ctx, name, inst, realm, &princ);
+    if (retval) {
+	com_err("krb5_425_conv_principal", retval, 0);
+	return;
+    }
+    retval = krb5_unparse_name(ctx, princ, &out_name);
+    if (retval) {
+	    com_err("krb5_unparse_name", retval, 0);
+	    return;
+    }
+    printf("425_converted principal(%s, %s, %s): '%s'\n",
+	   name, inst, realm, out_name);
+    free(out_name);
+    krb5_free_principal(ctx, princ);
+}
+
+void test_524_conv_principal(krb5_context ctx, char *name)
+{
+    krb5_principal princ = 0;
+    krb5_error_code retval;
+#ifndef KRB5_KRB4_COMPAT
+#define ANAME_SZ 40
+#define INST_SZ  40
+#define REALM_SZ  40
+#endif
+    char aname[ANAME_SZ+1], inst[INST_SZ+1], realm[REALM_SZ+1];
+
+    aname[ANAME_SZ] = inst[INST_SZ] = realm[REALM_SZ] = 0;
+    retval = krb5_parse_name(ctx, name, &princ);
+    if (retval) {
+	com_err("krb5_parse_name", retval, 0);
+	goto fail;
+    }
+    retval = krb5_524_conv_principal(ctx, princ, aname, inst, realm);
+    if (retval) {
+	com_err("krb5_524_conv_principal", retval, 0);
+	goto fail;
+    }
+    printf("524_converted_principal(%s): '%s' '%s' '%s'\n",
+	   name, aname, inst, realm);
+ fail:
+    if (princ)
+	krb5_free_principal (ctx, princ);
+}
+
+void test_parse_name(krb5_context ctx, const char *name)
+{
+	krb5_error_code	retval;
+	krb5_principal	princ = 0, princ2 = 0;
+	char		*outname = 0;
+
+	retval = krb5_parse_name(ctx, name, &princ);
+	if (retval) {
+		com_err("krb5_parse_name", retval, 0);
+		goto fail;
+	}
+	retval = krb5_copy_principal(ctx, princ, &princ2);
+	if (retval) {
+		com_err("krb5_copy_principal", retval, 0);
+		goto fail;
+	}
+	retval = krb5_unparse_name(ctx, princ2, &outname);
+	if (retval) {
+		com_err("krb5_unparse_name", retval, 0);
+		goto fail;
+	}
+	printf("parsed (and unparsed) principal(%s): ", name);
+	if (strcmp(name, outname) == 0)
+	    printf("MATCH\n");
+	else
+	    printf("'%s'\n", outname);
+fail:
+	if (outname)
+		free(outname);
+	if (princ)
+		krb5_free_principal(ctx, princ);
+	if (princ2)
+		krb5_free_principal(ctx, princ2);
+}
+
+void test_set_realm(krb5_context ctx, const char *name, const char *realm)
+{
+	krb5_error_code	retval;
+	krb5_principal	princ = 0;
+	char		*outname = 0;
+
+	retval = krb5_parse_name(ctx, name, &princ);
+	if (retval) {
+		com_err("krb5_parse_name", retval, 0);
+		goto fail;
+	}
+	retval = krb5_set_principal_realm(ctx, princ, realm);
+	if (retval) {
+		com_err("krb5_set_principal_realm", retval, 0);
+		goto fail;
+	}
+	retval = krb5_unparse_name(ctx, princ, &outname);
+	if (retval) {
+		com_err("krb5_unparse_name", retval, 0);
+		goto fail;
+	}
+	printf("old principal: %s, modified principal: %s\n", name,
+	       outname);
+fail:
+	if (outname)
+		free(outname);
+	if (princ)
+		krb5_free_principal(ctx, princ);
+}
+
+void usage(char *progname)
+{
+	fprintf(stderr, "%s: Usage: %s 425_conv_principal <name> <inst> <realm\n",
+		progname, progname);
+	fprintf(stderr, "\t%s 524_conv_principal <name>\n", progname);
+	fprintf(stderr, "\t%s parse_name <name>\n", progname);
+	fprintf(stderr, "\t%s set_realm <name> <realm>\n", progname);
+	fprintf(stderr, "\t%s string_to_timestamp <time>\n", progname);
+	exit(1);
+}
+
+int 
+main(int argc, char **argv)
+{
+    krb5_context ctx;
+    krb5_error_code retval;
+    char *progname;
+    char *name, *inst, *realm;
+
+    retval = krb5_init_context(&ctx);
+    if (retval) {
+	fprintf(stderr, "krb5_init_context returned error %ld\n",
+		(long) retval);
+	exit(1);
+    }
+    progname = argv[0];
+
+     /* Parse arguments. */
+     argc--; argv++;
+     while (argc) {
+	 if (strcmp(*argv, "425_conv_principal") == 0) {
+	     argc--; argv++;
+	     if (!argc) usage(progname);
+	     name = *argv;
+	     argc--; argv++;
+	     if (!argc) usage(progname);
+	     inst = *argv;
+	     argc--; argv++;
+	     if (!argc) usage(progname);
+	     realm = *argv;
+	     test_425_conv_principal(ctx, name, inst, realm);
+	  } else if (strcmp(*argv, "parse_name") == 0) {
+		  argc--; argv++;
+		  if (!argc) usage(progname);
+		  name = *argv;
+		  test_parse_name(ctx, name);
+	  } else if (strcmp(*argv, "set_realm") == 0) {
+		  argc--; argv++;
+		  if (!argc) usage(progname);
+		  name = *argv;
+		  argc--; argv++;
+		  if (!argc) usage(progname);
+		  realm = *argv;
+		  test_set_realm(ctx, name, realm);
+	  } else if (strcmp(*argv, "string_to_timestamp") == 0) {
+		  argc--; argv++;
+		  if (!argc) usage(progname);
+		  test_string_to_timestamp(ctx, *argv);
+	  } else if (strcmp(*argv, "524_conv_principal") == 0) {
+	      argc--; argv++;
+	      if (!argc) usage(progname);
+	      test_524_conv_principal(ctx, *argv);
+	  }
+	  else
+	      usage(progname);
+	  argc--; argv++;
+     }
+
+    krb5_free_context(ctx);
+
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/t_krb5.conf b/krb5-1-6/src/lib/krb5/krb/t_krb5.conf
new file mode 100644
index 000000000..b25b1d38a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/t_krb5.conf
@@ -0,0 +1,52 @@
+[libdefaults]
+	ticket_lifetime = 600
+	default_realm = ATHENA.MIT.EDU
+
+[realms]
+	ATHENA.MIT.EDU = {
+		kdc = KERBEROS-2.MIT.EDU:88
+		kdc = KERBEROS.MIT.EDU
+		kdc = KERBEROS-1.MIT.EDU
+		admin_server = KERBEROS.MIT.EDU
+		default_domain = MIT.EDU
+		v4_instance_convert = {
+			mit = mit.edu
+			lithium = lithium.lcs.mit.edu
+		}
+	}
+	CYGNUS.COM = {
+		kdc = KERBEROS-1.CYGNUS.COM
+		kdc = KERBEROS.CYGNUS.COM
+		admin_server = KERBEROS.MIT.EDU
+	}
+	stanford.edu = {
+		v4_realm = IR.STANFORD.EDU
+	}
+	LONGNAMES.COM = {
+		v4_realm = SOME-REALLY-LONG-REALM-NAME-V4-CANNOT-HANDLE.COM
+	}
+
+[capaths]
+	/COM/HP/APOLLO/FOO = {
+		/COM/DEC/CRL = /COM/DEC
+		/COM/DEC/CRL = /COM
+		/COM/DEC/CRL = /COM/HP
+		/COM/DEC/CRL = /COM/HP/APOLLO
+	}
+	ATHENA.MIT.EDU = {
+		KERBEROS.COM = .
+	}
+	LCS.MIT.EDU = {
+		KERBEROS.COM = ATHENA.MIT.EDU
+		ATHENA.MIT.EDU = .
+		KABLOOEY.KERBEROS.COM = ATHENA.MIT.EDU
+		KABLOOEY.KERBEROS.COM = KERBEROS.COM
+	}
+
+[domain_realm]
+	.mit.edu = ATHENA.MIT.EDU
+	mit.edu = ATHENA.MIT.EDU
+	.media.mit.edu = MEDIA-LAB.MIT.EDU
+	media.mit.edu = MEDIA-LAB.MIT.EDU
+	.ucsc.edu = CATS.UCSC.EDU
+
diff --git a/krb5-1-6/src/lib/krb5/krb/t_ref_kerb.out b/krb5-1-6/src/lib/krb5/krb/t_ref_kerb.out
new file mode 100644
index 000000000..08a53343f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/t_ref_kerb.out
@@ -0,0 +1,19 @@
+parsed (and unparsed) principal(tytso): 'tytso@ATHENA.MIT.EDU'
+parsed (and unparsed) principal(tytso@SHAZAAM): MATCH
+parsed (and unparsed) principal(tytso/root@VEGGIE.COM): MATCH
+parsed (and unparsed) principal(tytso/tuber/carrot@VEGGIE.COM): MATCH
+parsed (and unparsed) principal(tytso/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t): 'tytso/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t@ATHENA.MIT.EDU'
+parsed (and unparsed) principal(tytso/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t@FOO): MATCH
+parsed (and unparsed) principal(tytso\\0/\0@B\n\t\\GAG): MATCH
+parsed (and unparsed) principal(tytso/\n/\b\t@B\0hacky-test): MATCH
+parsed (and unparsed) principal(\/slash/\@atsign/octa\/thorpe@\/slash\@at\/sign): MATCH
+425_converted principal(rcmd, e40-po, ATHENA.MIT.EDU): 'host/e40-po.mit.edu@ATHENA.MIT.EDU'
+425_converted principal(rcmd, mit, ATHENA.MIT.EDU): 'host/mit.edu@ATHENA.MIT.EDU'
+425_converted principal(rcmd, lithium, ATHENA.MIT.EDU): 'host/lithium.lcs.mit.edu@ATHENA.MIT.EDU'
+425_converted principal(rcmd, tweedledumb, CYGNUS.COM): 'host/tweedledumb.cygnus.com@CYGNUS.COM'
+425_converted principal(rcmd, uunet, UU.NET): 'host/uunet.uu.net@UU.NET'
+425_converted principal(zephyr, zephyr, ATHENA.MIT.EDU): 'zephyr/zephyr@ATHENA.MIT.EDU'
+425_converted principal(kadmin, ATHENA.MIT.EDU, ATHENA.MIT.EDU): 'kadmin/ATHENA.MIT.EDU@ATHENA.MIT.EDU'
+524_converted_principal(host/e40-po.mit.edu@ATHENA.MIT.EDU): 'rcmd' 'e40-po' 'ATHENA.MIT.EDU'
+524_converted_principal(host/foobar.stanford.edu@stanford.edu): 'rcmd' 'foobar' 'IR.STANFORD.EDU'
+old principal: marc@MIT.EDU, modified principal: marc@CYGNUS.COM
diff --git a/krb5-1-6/src/lib/krb5/krb/t_ser.c b/krb5-1-6/src/lib/krb5/krb/t_ser.c
new file mode 100644
index 000000000..8ddcff7c0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/t_ser.c
@@ -0,0 +1,729 @@
+/*
+ * lib/krb5/krb/t_ser.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * t_ser.c - Test serialization.
+ */
+#include "k5-int.h"
+#include "com_err.h"
+#include "auth_con.h"
+
+#include <ctype.h>
+
+static const char stuff[]="You can't take a pointer to a function and convert \
+it to a pointer to char; ANSI doesn't say it'll work, and in fact on the HPPA \
+you can lose some bits of the function pointer, and get a pointer that you \
+can't safely dereference.  This test file used to make this mistake, often.";
+
+/*
+ * Dump an external representation.
+ */
+static void
+print_erep(krb5_octet *erep, size_t elen)
+{
+    int i, j;
+
+    for (i=0; i<elen; ) {
+	printf("%08d: ", i);
+	for (j=0; j<15; j++) {
+	    if ((i+j) < elen)
+		printf("%02x ", erep[i+j]);
+	    else
+		printf("-- ");
+	}
+	printf("\t");
+	for (j=0; j<15; j++) {
+	    if ((i+j) < elen) {
+		if (isprint(erep[i+j]) && (erep[i+j] != '\n'))
+		    printf("%c", erep[i+j]);
+		else
+		    printf(".");
+	    }
+	    else
+		printf("-");
+	}
+	printf("\n");
+	i += 15;
+    }
+}
+
+/*
+ * Do a serialization test.
+ */
+static krb5_error_code
+ser_data(int verbose, char *msg, krb5_pointer ctx, krb5_magic dtype)
+{
+    krb5_error_code	kret;
+    krb5_context	ser_ctx;
+    krb5_pointer	nctx;
+    krb5_octet		*outrep, *ibuf, *outrep2;
+    size_t		outlen, ilen, outlen2;
+
+    /* Initialize context and initialize all Kerberos serializers */
+    if ((kret = krb5_init_context(&ser_ctx))) {
+	    printf("Couldn't initialize krb5 library: %s\n",
+		   error_message(kret));
+	    exit(1);
+    }
+    krb5_ser_context_init(ser_ctx);
+    krb5_ser_auth_context_init(ser_ctx);
+    krb5_ser_ccache_init(ser_ctx);
+    krb5_ser_rcache_init(ser_ctx);
+    krb5_ser_keytab_init(ser_ctx);
+
+    /* Externalize the data */
+    kret = krb5_externalize_data(ser_ctx, ctx, &outrep, &outlen);
+    if (!kret) {
+	if (verbose) {
+	    printf("%s: externalized in %d bytes\n", msg, outlen);
+	    print_erep(outrep, outlen);
+	}
+
+	/* Now attempt to re-constitute it */
+	ibuf = outrep;
+	ilen = outlen;
+	kret = krb5_internalize_opaque(ser_ctx,
+				       dtype,
+				       (krb5_pointer *) &nctx,
+				       &ibuf,
+				       &ilen);
+	if (!kret) {
+	    if (ilen)
+		printf("%s: %d bytes left over after internalize\n",
+		       msg, ilen);
+	    /* Now attempt to re-externalize it */
+	    kret = krb5_externalize_data(ser_ctx, nctx, &outrep2, &outlen2);
+	    if (!kret) {
+		/* Compare the results. */
+		if ((outlen2 != outlen) ||
+		    memcmp(outrep, outrep2, outlen)) {
+		    printf("%s: comparison failed\n", msg);
+		    print_erep(outrep2, outlen2);
+		}
+		else {
+		    if (verbose)
+			printf("%s: compare succeeded\n", msg);
+		}
+		krb5_xfree(outrep2);
+	    }
+	    else
+		printf("%s: second externalize returned %d\n", msg, kret);
+
+	    /* Free the data */
+	    switch (dtype) {
+	    case KV5M_CONTEXT:
+		krb5_db_fini((krb5_context) nctx);
+		krb5_free_context((krb5_context) nctx);
+		break;
+	    case KV5M_AUTH_CONTEXT:
+		if (nctx) {
+		    krb5_auth_context	actx;
+
+		    actx = (krb5_auth_context) nctx;
+		    if (actx->i_vector)
+			krb5_xfree(actx->i_vector);
+		}
+		krb5_auth_con_free(ser_ctx, (krb5_auth_context) nctx);
+		break;
+	    case KV5M_CCACHE:
+		krb5_cc_close(ser_ctx, (krb5_ccache) nctx);
+		break;
+	    case KV5M_RCACHE:
+		krb5_rc_close(ser_ctx, (krb5_rcache) nctx);
+		break;
+	    case KV5M_KEYTAB:
+		krb5_kt_close(ser_ctx, (krb5_keytab) nctx);
+		break;
+	    case KV5M_ENCRYPT_BLOCK:
+		if (nctx) {
+		    krb5_encrypt_block *eblock;
+
+		    eblock = (krb5_encrypt_block *) nctx;
+#if 0
+		    if (eblock->priv && eblock->priv_size)
+			krb5_xfree(eblock->priv);
+#endif
+		    if (eblock->key)
+			krb5_free_keyblock(ser_ctx, eblock->key);
+		    krb5_xfree(eblock);
+		}
+		break;
+	    case KV5M_PRINCIPAL:
+		krb5_free_principal(ser_ctx, (krb5_principal) nctx);
+		break;
+	    case KV5M_CHECKSUM:
+		krb5_free_checksum(ser_ctx, (krb5_checksum *) nctx);
+		break;
+	    default:
+		printf("don't know how to free %d\n", dtype);
+		break;
+	    }
+	}
+	else
+	    printf("%s: internalize returned %d\n", msg, kret);
+	krb5_xfree(outrep);
+    }
+    else
+	printf("%s: externalize_data returned %d\n", msg, kret);
+    krb5_free_context(ser_ctx);
+    return(kret);
+}
+
+/*
+ * Serialize krb5_context.
+ */
+static krb5_error_code
+ser_kcontext_test(krb5_context kcontext, int verbose)
+{
+    krb5_error_code	kret;
+    profile_t		sprofile;
+    char		dbname[128];
+
+    sprintf(dbname, "temp_%d", (int) getpid());
+    sprofile = kcontext->profile;
+    kcontext->profile = (profile_t) NULL;
+    if (!(kret = ser_data(verbose, "> Context with no profile",
+			  (krb5_pointer) kcontext,
+			  KV5M_CONTEXT))) {
+	kcontext->profile = sprofile;
+	if (!(kret = ser_data(verbose, "> Context with no realm", 
+			      (krb5_pointer) kcontext,
+			      KV5M_CONTEXT)) &&
+	    !(kret = krb5_set_default_realm(kcontext, "this.is.a.test"))) {
+	    if (!(kret = ser_data(verbose, "> Context with default realm",
+				  (krb5_pointer) kcontext,
+				  KV5M_CONTEXT))) {
+		if (verbose)
+		    printf("* krb5_context test succeeded\n");
+	    }
+	}
+    }
+    if (kret)
+	printf("* krb5_context test failed\n");
+    return(kret);
+}
+
+/* 
+ * Serialize krb5_auth_context.
+ */
+static krb5_error_code
+ser_acontext_test(krb5_context kcontext, int verbose)
+{
+    krb5_error_code	kret;
+    krb5_auth_context	actx;
+    krb5_address	local_address;
+    krb5_address	remote_address;
+    krb5_octet		laddr_bytes[16];
+    krb5_octet		raddr_bytes[16];
+    krb5_keyblock	ukeyblock;
+    krb5_octet		keydata[8];
+    krb5_authenticator	aent;
+    char		clname[128];
+    krb5_authdata	*adatalist[3];
+    krb5_authdata	adataent;
+
+    actx = (krb5_auth_context) NULL;
+    if (!(kret = krb5_auth_con_init(kcontext, &actx)) &&
+	!(kret = ser_data(verbose, "> Vanilla auth context",
+			  (krb5_pointer) actx,
+			  KV5M_AUTH_CONTEXT))) {
+	memset(&local_address, 0, sizeof(local_address));
+	memset(&remote_address, 0, sizeof(remote_address));
+	memset(laddr_bytes, 0, sizeof(laddr_bytes));
+	memset(raddr_bytes, 0, sizeof(raddr_bytes));
+	local_address.addrtype = ADDRTYPE_INET;
+	local_address.length = sizeof(laddr_bytes);
+	local_address.contents = laddr_bytes;
+	laddr_bytes[0] = 6;
+	laddr_bytes[1] = 2;
+	laddr_bytes[2] = 69;
+	laddr_bytes[3] = 16;
+	laddr_bytes[4] = 1;
+	laddr_bytes[5] = 0;
+	laddr_bytes[6] = 0;
+	laddr_bytes[7] = 127;
+	remote_address.addrtype = ADDRTYPE_INET;
+	remote_address.length = sizeof(raddr_bytes);
+	remote_address.contents = raddr_bytes;
+	raddr_bytes[0] = 6;
+	raddr_bytes[1] = 2;
+	raddr_bytes[2] = 70;
+	raddr_bytes[3] = 16;
+	raddr_bytes[4] = 1;
+	raddr_bytes[5] = 0;
+	raddr_bytes[6] = 0;
+	raddr_bytes[7] = 127;
+	if (!(kret = krb5_auth_con_setaddrs(kcontext, actx,
+					    &local_address,
+					    &remote_address)) &&
+	    !(kret = krb5_auth_con_setports(kcontext, actx,
+					    &local_address,
+					    &remote_address)) &&
+	    !(kret = ser_data(verbose, "> Auth context with addrs/ports", 
+			      (krb5_pointer) actx,
+			      KV5M_AUTH_CONTEXT))) {
+	    memset(&ukeyblock, 0, sizeof(ukeyblock));
+	    memset(keydata, 0, sizeof(keydata));
+	    ukeyblock.enctype = ENCTYPE_DES_CBC_MD5;
+	    ukeyblock.length = sizeof(keydata);
+	    ukeyblock.contents = keydata;
+	    keydata[0] = 0xde;
+	    keydata[1] = 0xad;
+	    keydata[2] = 0xbe;
+	    keydata[3] = 0xef;
+	    keydata[4] = 0xfe;
+	    keydata[5] = 0xed;
+	    keydata[6] = 0xf0;
+	    keydata[7] = 0xd;
+	    if (!(kret = krb5_auth_con_setuseruserkey(kcontext, actx,
+						      &ukeyblock)) &&
+		!(kret = ser_data(verbose, "> Auth context with user key",
+				  (krb5_pointer) actx,
+				  KV5M_AUTH_CONTEXT)) &&
+		!(kret = krb5_auth_con_initivector(kcontext, actx)) &&
+		!(kret = ser_data(verbose, "> Auth context with new vector",
+				  (krb5_pointer) actx,
+				  KV5M_AUTH_CONTEXT)) &&
+		(krb5_xfree(actx->i_vector), actx->i_vector) &&
+		!(kret = krb5_auth_con_setivector(kcontext, actx,
+						  (krb5_pointer) print_erep)
+		  ) &&
+		!(kret = ser_data(verbose, "> Auth context with set vector",
+				  (krb5_pointer) actx,
+				  KV5M_AUTH_CONTEXT))) {
+		/*
+		 * Finally, add an authenticator.
+		 */
+		memset(&aent, 0, sizeof(aent));
+		aent.magic = KV5M_AUTHENTICATOR;
+		sprintf(clname, "help/me/%d@this.is.a.test", (int) getpid());
+		actx->authentp = &aent;
+		if (!(kret = krb5_parse_name(kcontext, clname,
+					     &aent.client)) &&
+		    !(kret = ser_data(verbose,
+				      "> Auth context with authenticator",
+				      (krb5_pointer) actx,
+				      KV5M_AUTH_CONTEXT))) {
+		    adataent.magic = KV5M_AUTHDATA;
+		    adataent.ad_type = 123;
+		    adataent.length = 128;
+		    adataent.contents = (krb5_octet *) stuff;
+		    adatalist[0] = &adataent;
+		    adatalist[1] = &adataent;
+		    adatalist[2] = (krb5_authdata *) NULL;
+		    aent.authorization_data = adatalist;
+		    if (!(kret = ser_data(verbose,
+					  "> Auth context with full auth",
+					  (krb5_pointer) actx,
+					  KV5M_AUTH_CONTEXT))) {
+			if (verbose)
+			    printf("* krb5_auth_context test succeeded\n");
+		    }
+		    krb5_free_principal(kcontext, aent.client);
+		}
+		actx->authentp = (krb5_authenticator *) NULL;
+	    }
+	}
+    }
+    if (actx)
+	krb5_auth_con_free(kcontext, actx);
+    if (kret)
+	printf("* krb5_auth_context test failed\n");
+    return(kret);
+}
+
+/*
+ * Serialize krb5_ccache
+ */
+static krb5_error_code
+ser_ccache_test(krb5_context kcontext, int verbose)
+{
+    krb5_error_code	kret;
+    char		ccname[128];
+    char		princname[256];
+    krb5_ccache		ccache;
+    krb5_principal	principal;
+
+    sprintf(ccname, "temp_cc_%d", (int) getpid());
+    sprintf(princname, "zowie%d/instance%d@this.is.a.test",
+	    (int) getpid(), (int) getpid());
+    if (!(kret = krb5_cc_resolve(kcontext, ccname, &ccache)) &&
+	!(kret = ser_data(verbose, "> Resolved default ccache",
+			  (krb5_pointer) ccache, KV5M_CCACHE)) &&
+	!(kret = krb5_parse_name(kcontext, princname, &principal)) &&
+	!(kret = krb5_cc_initialize(kcontext, ccache, principal)) &&
+	!(kret = ser_data(verbose, "> Initialized default ccache",
+			  (krb5_pointer) ccache, KV5M_CCACHE)) &&
+	!(kret = krb5_cc_destroy(kcontext, ccache))) {
+	krb5_free_principal(kcontext, principal);
+	sprintf(ccname, "FILE:temp_cc_%d", (int) getpid());
+	sprintf(princname, "xxx%d/i%d@this.is.a.test",
+		(int) getpid(), (int) getpid());
+	if (!(kret = krb5_cc_resolve(kcontext, ccname, &ccache)) &&
+	    !(kret = ser_data(verbose, "> Resolved FILE ccache",
+			      (krb5_pointer) ccache, KV5M_CCACHE)) &&
+	    !(kret = krb5_parse_name(kcontext, princname, &principal)) &&
+	    !(kret = krb5_cc_initialize(kcontext, ccache, principal)) &&
+	    !(kret = ser_data(verbose, "> Initialized FILE ccache",
+			      (krb5_pointer) ccache, KV5M_CCACHE)) &&
+	    !(kret = krb5_cc_destroy(kcontext, ccache))) {
+	    krb5_free_principal(kcontext, principal);
+
+	    if (verbose)
+		printf("* ccache test succeeded\n");
+	}
+    }
+    if (kret)
+	printf("* krb5_ccache test failed\n");
+    return(kret);
+}
+
+/*
+ * Serialize krb5_keytab.
+ */
+static krb5_error_code
+ser_keytab_test(krb5_context kcontext, int verbose)
+{
+    krb5_error_code	kret;
+    char		ccname[128];
+    krb5_keytab		keytab;
+    extern krb5_kt_ops	krb5_ktf_writable_ops;
+
+    sprintf(ccname, "temp_kt_%d", (int) getpid());
+    if (!(kret = krb5_kt_resolve(kcontext, ccname, &keytab)) &&
+	!(kret = ser_data(verbose, "> Resolved default keytab",
+			  (krb5_pointer) keytab, KV5M_KEYTAB)) &&
+	!(kret = krb5_kt_close(kcontext, keytab))) {
+	sprintf(ccname, "FILE:temp_kt_%d", (int) getpid());
+	if (!(kret = krb5_kt_resolve(kcontext, ccname, &keytab)) &&
+	    !(kret = ser_data(verbose, "> Resolved FILE keytab",
+			      (krb5_pointer) keytab, KV5M_KEYTAB)) &&
+	    !(kret = krb5_kt_close(kcontext, keytab))) {
+	    sprintf(ccname, "WRFILE:temp_kt_%d", (int) getpid());
+	    if ((kret = krb5_kt_resolve(kcontext, ccname, &keytab)))
+		kret = krb5_kt_register(kcontext, &krb5_ktf_writable_ops);
+	    else
+		kret = krb5_kt_close(kcontext, keytab);
+	    if (!kret &&
+		!(kret = krb5_kt_resolve(kcontext, ccname, &keytab)) &&
+		!(kret = ser_data(verbose, "> Resolved WRFILE keytab",
+				  (krb5_pointer) keytab, KV5M_KEYTAB)) &&
+		!(kret = krb5_kt_close(kcontext, keytab))) {
+		if (verbose)
+		    printf("* keytab test succeeded\n");
+	    }
+	}
+    }
+    if (kret)
+	printf("* krb5_keytab test failed\n");
+    return(kret);
+}
+
+/*
+ * Serialize krb5_rcache.
+ */
+static krb5_error_code
+ser_rcache_test(krb5_context kcontext, int verbose)
+{
+    krb5_error_code	kret;
+    char		rcname[128];
+    krb5_rcache		rcache;
+
+    sprintf(rcname, "dfl:temp_rc_%d", (int) getpid());
+    if (!(kret = krb5_rc_resolve_full(kcontext, &rcache, rcname)) &&
+	!(kret = ser_data(verbose, "> Resolved FILE rcache",
+			  (krb5_pointer) rcache, KV5M_RCACHE)) &&
+	!(kret = krb5_rc_initialize(kcontext, rcache, 3600*24)) &&
+	!(kret = ser_data(verbose, "> Initialized FILE rcache",
+			  (krb5_pointer) rcache, KV5M_RCACHE)) &&
+	!(kret = krb5_rc_destroy(kcontext, rcache))) {
+	if (verbose)
+	    printf("* rcache test succeeded\n");
+    }
+    if (kret)
+	printf("* krb5_rcache test failed\n");
+    return(kret);
+}
+
+#if 0
+/*
+ * Serialize krb5_encrypt_block.
+ */
+static krb5_error_code
+ser_eblock_test(kcontext, verbose)
+    krb5_context	kcontext;
+    int			verbose;
+{
+    krb5_error_code	kret;
+    krb5_encrypt_block	eblock;    
+    krb5_keyblock	ukeyblock;
+    krb5_octet		keydata[8];
+
+    memset(&eblock, 0, sizeof(krb5_encrypt_block));
+    eblock.magic = KV5M_ENCRYPT_BLOCK;
+    krb5_use_enctype(kcontext, &eblock, DEFAULT_KDC_ENCTYPE);
+    if (!(kret = ser_data(verbose, "> NULL eblock",
+			  (krb5_pointer) &eblock, KV5M_ENCRYPT_BLOCK))) {
+#if 0
+	eblock.priv = (krb5_pointer) stuff;
+	eblock.priv_size = 8;
+#endif
+	if (!(kret = ser_data(verbose, "> eblock with private data",
+			      (krb5_pointer) &eblock,
+			      KV5M_ENCRYPT_BLOCK))) {
+	    memset(&ukeyblock, 0, sizeof(ukeyblock));
+	    memset(keydata, 0, sizeof(keydata));
+	    ukeyblock.enctype = ENCTYPE_DES_CBC_MD5;
+	    ukeyblock.length = sizeof(keydata);
+	    ukeyblock.contents = keydata;
+	    keydata[0] = 0xde;
+	    keydata[1] = 0xad;
+	    keydata[2] = 0xbe;
+	    keydata[3] = 0xef;
+	    keydata[4] = 0xfe;
+	    keydata[5] = 0xed;
+	    keydata[6] = 0xf0;
+	    keydata[7] = 0xd;
+	    eblock.key = &ukeyblock;
+	    if (!(kret = ser_data(verbose, "> eblock with private key",
+				  (krb5_pointer) &eblock,
+				  KV5M_ENCRYPT_BLOCK))) {
+		if (verbose)
+		    printf("* eblock test succeeded\n");
+	    }
+	}
+    }
+    if (kret)
+	printf("* eblock test failed\n");
+    return(kret);
+}
+#endif
+
+/*
+ * Serialize krb5_principal
+ */
+static krb5_error_code
+ser_princ_test(krb5_context kcontext, int verbose)
+{
+    krb5_error_code	kret;
+    krb5_principal	princ;
+    char		pname[1024];
+
+    sprintf(pname, "the/quick/brown/fox/jumped/over/the/lazy/dog/%d@this.is.a.test", (int) getpid());
+    if (!(kret = krb5_parse_name(kcontext, pname, &princ))) {
+	if (!(kret = ser_data(verbose, "> Principal",
+			      (krb5_pointer) princ, KV5M_PRINCIPAL))) {
+	    if (verbose)
+		printf("* principal test succeeded\n");
+	}
+	krb5_free_principal(kcontext, princ);
+    }
+    if (kret)
+	printf("* principal test failed\n");
+    return(kret);
+}
+
+/*
+ * Serialize krb5_checksum.
+ */
+static krb5_error_code
+ser_cksum_test(krb5_context kcontext, int verbose)
+{
+    krb5_error_code	kret;
+    krb5_checksum	checksum;
+    krb5_octet		ckdata[24];
+
+    memset(&checksum, 0, sizeof(krb5_checksum));
+    checksum.magic = KV5M_CHECKSUM;
+    if (!(kret = ser_data(verbose, "> NULL checksum",
+			  (krb5_pointer) &checksum, KV5M_CHECKSUM))) {
+	checksum.checksum_type = 123;
+	checksum.length = sizeof(ckdata);
+	checksum.contents = ckdata;
+	memcpy(ckdata, (char *) &stuff, sizeof(ckdata)); 
+	if (!(kret = ser_data(verbose, "> checksum with data",
+			      (krb5_pointer) &checksum, KV5M_CHECKSUM))) {
+	    if (verbose)
+		printf("* checksum test succeeded\n");
+	}
+    }
+    if (kret)
+	printf("* checksum test failed\n");
+    return(kret);
+}
+
+/*
+ * Main procedure.
+ */
+int
+main(int argc, char **argv)
+{
+    krb5_error_code	kret;
+    krb5_context	kcontext;
+    int			do_atest, do_ctest, do_ktest, do_rtest, do_xtest;
+    int			do_etest, do_ptest, do_stest;
+    int			verbose;
+    int			option;
+    extern char		*optarg;
+    char		ch_err;
+
+    kret = 0;
+    verbose = 0;
+    do_atest = 1;
+    do_xtest = 1;
+    do_ctest = 1;
+    do_etest = 1;
+    do_ktest = 1;
+    do_ptest = 1;
+    do_rtest = 1;
+    do_stest = 1;
+    while ((option = getopt(argc, argv, "acekprsxvACEKPRSX")) != -1) {
+	switch (option) {
+	case 'a':
+	    do_atest = 0;
+	    break;
+	case 'c':
+	    do_ctest = 0;
+	    break;
+	case 'e':
+	    do_etest = 0;
+	    break;
+	case 'k':
+	    do_ktest = 0;
+	    break;
+	case 'p':
+	    do_ptest = 0;
+	    break;
+	case 'r':
+	    do_rtest = 0;
+	    break;
+	case 's':
+	    do_stest = 0;
+	    break;
+	case 'x':
+	    do_xtest = 0;
+	    break;
+	case 'v':
+	    verbose = 1;
+	    break;
+	case 'A':
+	    do_atest = 1;
+	    break;
+	case 'C':
+	    do_ctest = 1;
+	    break;
+#if 0
+	case 'E':
+	    do_etest = 1;
+	    break;
+#endif
+	case 'K':
+	    do_ktest = 1;
+	    break;
+	case 'P':
+	    do_ptest = 1;
+	    break;
+	case 'R':
+	    do_rtest = 1;
+	    break;
+	case 'S':
+	    do_stest = 1;
+	    break;
+	case 'X':
+	    do_xtest = 1;
+	    break;
+	default:
+	    fprintf(stderr,
+		    "%s: usage is %s [-acekprsxvACEKPRSX]\n",
+		    argv[0], argv[0]);
+	    exit(1);
+	    break;
+	}
+    }
+    if ((kret = krb5_init_context(&kcontext))) {
+	    com_err(argv[0], kret, "while initializing krb5");
+	    exit(1);
+    }
+    
+    if (do_xtest) {
+	    ch_err = 'x';
+	    kret = ser_kcontext_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+    if (do_atest) {
+	    ch_err = 'a';
+	    kret = ser_acontext_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+    if (do_ctest) {
+	    ch_err = 'c';
+	    kret = ser_ccache_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+    if (do_ktest) {
+	    ch_err = 'k';
+	    kret = ser_keytab_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+    if (do_rtest) {
+	    ch_err = 'r';
+	    kret = ser_rcache_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+#if 0 /* code to be tested is currently disabled */
+    if (do_etest) {
+	    ch_err = 'e';
+	    kret = ser_eblock_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+#endif
+    if (do_ptest) {
+	    ch_err = 'p';
+	    kret = ser_princ_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+    if (do_stest) {
+	    ch_err = 's';
+	    kret = ser_cksum_test(kcontext, verbose);
+	    if (kret)
+		    goto fail;
+    }
+    krb5_free_context(kcontext);
+    
+    exit(0);
+fail:
+    com_err(argv[0], kret, "--- test %cfailed", ch_err);
+    krb5_free_context(kcontext);
+    exit(1);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/t_walk_rtree.c b/krb5-1-6/src/lib/krb5/krb/t_walk_rtree.c
new file mode 100644
index 000000000..466118667
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/t_walk_rtree.c
@@ -0,0 +1,58 @@
+/*
+ * t_walk_rtree.c --- test krb5_walk_realm_tree
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include "com_err.h"
+
+int
+main(int argc, char **argv)
+{
+	krb5_data client, server;
+	char	realm_branch_char = '.';
+	krb5_principal *tree, *p;
+	char *name;
+	krb5_error_code	retval;
+	krb5_context context;
+	
+	krb5_init_context(&context);
+	
+	if (argc < 3 || argc > 4) {
+		fprintf(stderr,
+			"Usage: %s client-realm server-realm [sep_char]\n",
+			argv[0]);
+		exit(99);
+	}
+	client.data = argv[1];
+	client.length = strlen(client.data);
+
+	server.data = argv[2];
+	server.length = strlen(server.data);
+
+	if (argc == 4)
+		realm_branch_char = argv[3][0];
+
+	retval = krb5_walk_realm_tree(context, &client, &server, &tree,
+				      realm_branch_char);
+	if (retval) {
+		com_err("krb5_walk_realm_tree", retval, " ");
+		exit(1);
+	}
+
+	for (p = tree; *p; p++) {
+		retval = krb5_unparse_name(context, *p, &name);
+		if (retval) {
+			com_err("krb5_unprase_name", retval, " ");
+			exit(2);
+		}
+		printf("%s\n", name);
+		free(name);
+	}
+
+	krb5_free_realm_tree(context, tree);
+	krb5_free_context(context);
+
+	exit(0);
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/tgtname.c b/krb5-1-6/src/lib/krb5/krb/tgtname.c
new file mode 100644
index 000000000..4ca241623
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/tgtname.c
@@ -0,0 +1,42 @@
+/*
+ * lib/krb5/krb/tgtname.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_tgtname()
+ */
+
+#include "k5-int.h"
+#include "int-proto.h"
+
+/* This is an internal-only function, used by krb5_get_cred_from_kdc() */
+
+krb5_error_code
+krb5_tgtname(krb5_context context, const krb5_data *server, const krb5_data *client, krb5_principal *tgtprinc)
+{
+    return krb5_build_principal_ext(context, tgtprinc, client->length, client->data,
+				    KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, 
+				    server->length, server->data,
+				    0);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/transit-tests b/krb5-1-6/src/lib/krb5/krb/transit-tests
new file mode 100755
index 000000000..8ffb9c351
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/transit-tests
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# Test the chk_trans.c code.
+# BUG: Currently only tests expansion, not validation.
+
+trap "echo Failed. ; exit 1" 0
+
+check='echo Running test "($1) ($2) ($3)" ... ; ./t_expand -x >tmpout1 "$@" || exit 1 ; grep -v : <tmpout1 >tmpout2 && sort <tmpout2 >tmpout1 && echo Got: `cat tmpout1` && (for i in $expected ; do echo $i ; done) | sort > tmpout2 && echo Exp: `cat tmpout2` && echo "" && cmp >/dev/null 2>&1 tmpout1 tmpout2 || exit 1'
+checkerror='echo Running test "($1) ($2) ($3)", expecting error ... ; if ./t_expand -x >tmpout1 "$@" ; then echo Error was expected, but not reported. ; exit 1; else echo Expected error found. ; echo ""; fi'
+
+#
+# Note: Expected realm expansion order is not important; program output
+# and expected values will each be sorted before comparison.
+#
+
+set ATHENA.MIT.EDU HACK.FOOBAR.COM ,EDU,BLORT.COM,COM,
+expected="MIT.EDU EDU BLORT.COM COM FOOBAR.COM"
+eval $check
+
+set ATHENA.MIT.EDU EDU ,
+expected="MIT.EDU"
+eval $check
+
+set EDU ATHENA.MIT.EDU ,
+expected="MIT.EDU"
+eval $check
+
+set x x "/COM,/HP,/APOLLO, /COM/DEC"
+expected="/COM /COM/HP /COM/HP/APOLLO /COM/DEC"
+eval $check
+
+set x x EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.
+expected="EDU MIT.EDU ATHENA.MIT.EDU WASHINGTON.EDU CS.WASHINGTON.EDU"
+eval $check
+
+set ATHENA.MIT.EDU /COM/HP/APOLLO ,EDU,/COM,
+eval $checkerror
+
+set ATHENA.MIT.EDU /COM/HP/APOLLO ",EDU, /COM,"
+expected="EDU MIT.EDU /COM /COM/HP"
+eval $check
+
+set ATHENA.MIT.EDU CS.CMU.EDU ,EDU,
+expected="EDU MIT.EDU CMU.EDU"
+eval $check
+
+set XYZZY.ATHENA.MIT.EDU XYZZY.CS.CMU.EDU ,EDU,
+expected="EDU MIT.EDU ATHENA.MIT.EDU CMU.EDU CS.CMU.EDU"
+eval $check
+
+rm tmpout1 tmpout2
+trap "" 0
+echo Success.
+exit 0
diff --git a/krb5-1-6/src/lib/krb5/krb/unparse.c b/krb5-1-6/src/lib/krb5/krb/unparse.c
new file mode 100644
index 000000000..a67636641
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/unparse.c
@@ -0,0 +1,200 @@
+/*
+ * lib/krb5/krb/unparse.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_unparse_name() routine
+ *
+ * Rewritten by Theodore Ts'o to properly unparse principal names
+ * which have the component or realm separator as part of one of their
+ * components.
+ */
+
+
+#include "k5-int.h"
+#include <stdio.h>
+
+/*
+ * converts the multi-part principal format used in the protocols to a
+ * single-string representation of the name. 
+ *  
+ * The name returned is in allocated storage and should be freed by
+ * the caller when finished.
+ *
+ * Conventions: / is used to separate components; @ is used to
+ * separate the realm from the rest of the name.  If '/', '@', or '\0'
+ * appear in any the component, they will be representing using
+ * backslash encoding.  ("\/", "\@", or '\0', respectively)
+ *
+ * returns error
+ *	KRB_PARSE_MALFORMED	principal is invalid (does not contain
+ *				at least 2 components)
+ * also returns system errors
+ *	ENOMEM			unable to allocate memory for string
+ */
+
+#define REALM_SEP	'@'
+#define	COMPONENT_SEP	'/'
+
+krb5_error_code KRB5_CALLCONV
+krb5_unparse_name_ext(krb5_context context, krb5_const_principal principal, register char **name, unsigned int *size)
+{
+	register char *cp, *q;
+	register int i,j;
+	int	length;
+	krb5_int32 nelem;
+	register unsigned int totalsize = 0;
+
+	if (!principal || !name)
+		return KRB5_PARSE_MALFORMED;
+
+	cp = krb5_princ_realm(context, principal)->data;
+	length = krb5_princ_realm(context, principal)->length;
+	totalsize += length;
+	for (j = 0; j < length; j++,cp++)
+		if (*cp == REALM_SEP  || *cp == COMPONENT_SEP ||
+		    *cp == '\0' || *cp == '\\' || *cp == '\t' ||
+		    *cp == '\n' || *cp == '\b')
+			totalsize++;
+	totalsize++;		/* This is for the separator */
+
+	nelem = krb5_princ_size(context, principal);
+	for (i = 0; i < (int) nelem; i++) {
+		cp = krb5_princ_component(context, principal, i)->data;
+		length = krb5_princ_component(context, principal, i)->length;
+		totalsize += length;
+		for (j=0; j < length; j++,cp++)
+			if (*cp == REALM_SEP || *cp == COMPONENT_SEP ||
+			    *cp == '\0' || *cp == '\\' || *cp == '\t' ||
+			    *cp == '\n' || *cp == '\b')
+				totalsize++;
+		totalsize++;	/* This is for the separator */
+	}
+	if (nelem == 0)
+		totalsize++;
+
+	/*
+	 * Allocate space for the ascii string; if space has been
+	 * provided, use it, realloc'ing it if necessary.
+	 * 
+	 * We need only n-1 seperators for n components, but we need
+	 * an extra byte for the NULL at the end.
+	 */
+        if (size) {
+            if (*name && (*size < totalsize)) {
+                *name = realloc(*name, totalsize);
+            } else {
+                *name = malloc(totalsize);
+            }
+            *size = totalsize;
+        } else {
+            *name = malloc(totalsize);
+        }
+
+	if (!*name)
+		return ENOMEM;
+
+	q = *name;
+	
+	for (i = 0; i < (int) nelem; i++) {
+		cp = krb5_princ_component(context, principal, i)->data;
+		length = krb5_princ_component(context, principal, i)->length;
+		for (j=0; j < length; j++,cp++) {
+		    switch (*cp) {
+		    case COMPONENT_SEP:
+		    case REALM_SEP:
+		    case '\\':
+			*q++ = '\\';
+			*q++ = *cp;
+			break;
+		    case '\t':
+			*q++ = '\\';
+			*q++ = 't';
+			break;
+		    case '\n':
+			*q++ = '\\';
+			*q++ = 'n';
+			break;
+		    case '\b':
+			*q++ = '\\';
+			*q++ = 'b';
+			break;
+		    case '\0':
+			*q++ = '\\';
+			*q++ = '0';
+			break;
+		    default:
+			*q++ = *cp;
+		    }
+		}
+		*q++ = COMPONENT_SEP;
+	}
+
+	if (i > 0)
+	    q--;		/* Back up last component separator */
+	*q++ = REALM_SEP;
+	
+	cp = krb5_princ_realm(context, principal)->data;
+	length = krb5_princ_realm(context, principal)->length;
+	for (j=0; j < length; j++,cp++) {
+		switch (*cp) {
+		case COMPONENT_SEP:
+		case REALM_SEP:
+		case '\\':
+			*q++ = '\\';
+			*q++ = *cp;
+			break;
+		case '\t':
+			*q++ = '\\';
+			*q++ = 't';
+			break;
+		case '\n':
+			*q++ = '\\';
+			*q++ = 'n';
+			break;
+		case '\b':
+			*q++ = '\\';
+			*q++ = 'b';
+			break;
+		case '\0':
+			*q++ = '\\';
+			*q++ = '0';
+			break;
+		default:
+			*q++ = *cp;
+		}
+	}
+	*q++ = '\0';
+	
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_unparse_name(krb5_context context, krb5_const_principal principal, register char **name)
+{
+        if (name)                       /* name == NULL will return error from _ext */
+            *name = NULL;
+	return(krb5_unparse_name_ext(context, principal, name, NULL));
+}
+
diff --git a/krb5-1-6/src/lib/krb5/krb/v4lifetime.c b/krb5-1-6/src/lib/krb5/krb/v4lifetime.c
new file mode 100644
index 000000000..94bf5f6ab
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/v4lifetime.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2000, 2001, 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "k5-int.h"
+
+/*
+ * Only lifetime bytes values less than 128 are on a linear scale.
+ * The following table contains an exponential scale that covers the
+ * lifetime values 128 to 191 inclusive (a total of 64 values).
+ * Values greater than 191 get interpreted the same as 191, but they
+ * will never be generated by the functions in this file.
+ *
+ * The ratio is approximately 1.069144898 (actually exactly
+ * exp(log(67.5)/63), where 67.5 = 2592000/38400, and 259200 = 30
+ * days, and 38400 = 128*5 minutes.  This allows a lifetime byte of
+ * 191 to correspond to a ticket life of exactly 30 days and a
+ * lifetime byte of 128 to correspond to exactly 128*5 minutes, with
+ * the other values spread on an exponential curve fit in between
+ * them.  This table should correspond exactly to the set of extended
+ * ticket lifetime values used by AFS and CMU.
+ *
+ * The following awk script is sufficient to reproduce the table:
+ * BEGIN {
+ *     r = exp(log(2592000/38400)/63);
+ *     x = 38400;
+ *     for (i=0;i<64;i++) {
+ *         printf("%d\n",x+0.5);
+ *         x *= r;
+ *     }
+ * }
+ */
+#ifndef SHORT_LIFETIME
+#define NLIFETIMES 64
+static const krb5_int32 lifetimes[NLIFETIMES] = {
+    38400, 41055,		/* 00:10:40:00, 00:11:24:15 */
+    43894, 46929,		/* 00:12:11:34, 00:13:02:09 */
+    50174, 53643,		/* 00:13:56:14, 00:14:54:03 */
+    57352, 61318,		/* 00:15:55:52, 00:17:01:58 */
+    65558, 70091,		/* 00:18:12:38, 00:19:28:11 */
+    74937, 80119,		/* 00:20:48:57, 00:22:15:19 */
+    85658, 91581,		/* 00:23:47:38, 01:01:26:21 */
+    97914, 104684,		/* 01:03:11:54, 01:05:04:44 */
+    111922, 119661,		/* 01:07:05:22, 01:09:14:21 */
+    127935, 136781,		/* 01:11:32:15, 01:13:59:41 */
+    146239, 156350,		/* 01:16:37:19, 01:19:25:50 */
+    167161, 178720,		/* 01:22:26:01, 02:01:38:40 */
+    191077, 204289,		/* 02:05:04:37, 02:08:44:49 */
+    218415, 233517,		/* 02:12:40:15, 02:16:51:57 */
+    249664, 266926,		/* 02:21:21:04, 03:02:08:46 */
+    285383, 305116,		/* 03:07:16:23, 03:12:45:16 */
+    326213, 348769,		/* 03:18:36:53, 04:00:52:49 */
+    372885, 398668,		/* 04:07:34:45, 04:14:44:28 */
+    426234, 455705,		/* 04:22:23:54, 05:06:35:05 */
+    487215, 520904,		/* 05:15:20:15, 06:00:41:44 */
+    556921, 595430,		/* 06:10:42:01, 06:21:23:50 */
+    636601, 680618,		/* 07:08:50:01, 07:21:03:38 */
+    727680, 777995,		/* 08:10:08:00, 09:00:06:35 */
+    831789, 889303,		/* 09:15:03:09, 10:07:01:43 */
+    950794, 1016537,		/* 11:00:06:34, 11:18:22:17 */
+    1086825, 1161973,		/* 12:13:53:45, 13:10:46:13 */
+    1242318, 1328218,		/* 14:09:05:18, 15:08:56:58 */
+    1420057, 1518247,		/* 16:10:27:37, 17:13:44:07 */
+    1623226, 1735464,		/* 18:18:53:46, 20:02:04:24 */
+    1855462, 1983758,		/* 21:11:24:22, 22:23:02:38 */
+    2120925, 2267576,		/* 24:13:08:45, 26:05:52:56 */
+    2424367, 2592000		/* 28:01:26:07, 30:00:00:00 */
+};
+#define MINFIXED 0x80
+#define MAXFIXED (MINFIXED + NLIFETIMES - 1)
+#endif /* !SHORT_LIFETIME */
+
+/*
+ * krb_life_to_time
+ *
+ * Given a start date and a lifetime byte, compute the expiration
+ * date.
+ */
+krb5_int32
+krb5int_krb_life_to_time(krb5_int32 start, int life)
+{
+    if (life < 0 || life > 255)	/* possibly sign botch in caller */
+	return start;
+#ifndef SHORT_LIFETIME
+    if (life < MINFIXED)
+	return start + life * 5 * 60;
+    if (life > MAXFIXED)
+	return start + lifetimes[NLIFETIMES - 1];
+    return start + lifetimes[life - MINFIXED];
+#else  /* SHORT_LIFETIME */
+    return start + life * 5 * 60;
+#endif /* SHORT_LIFETIME */
+}
+
+/*
+ * krb_time_to_life
+ *
+ * Given the start date and the end date, compute the lifetime byte.
+ * Round up, since we can adjust the start date backwards if we are
+ * issuing the ticket to cause it to expire at the correct time.
+ */
+int
+krb5int_krb_time_to_life(krb5_int32 start, krb5_int32 end)
+{
+    krb5_int32 dt;
+#ifndef SHORT_LIFETIME
+    int i;
+#endif
+
+    dt = end - start;
+    if (dt <= 0)
+	return 0;
+#ifndef SHORT_LIFETIME
+    if (dt < lifetimes[0])
+	return (dt + 5 * 60 - 1) / (5 * 60);
+    /* This depends on the array being ordered. */
+    for (i = 0; i < NLIFETIMES; i++) {
+	if (lifetimes[i] >= dt)
+	    return i + MINFIXED;
+    }
+    return MAXFIXED;
+#else  /* SHORT_LIFETIME */
+    if (dt > 5 * 60 * 255)
+	return 255;
+    else
+	return (dt + 5 * 60 - 1) / (5 * 60);
+#endif /* SHORT_LIFETIME */
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/valid_times.c b/krb5-1-6/src/lib/krb5/krb/valid_times.c
new file mode 100644
index 000000000..9c53d7d91
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/valid_times.c
@@ -0,0 +1,64 @@
+/*
+ * lib/krb5/krb/valid_times.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_validate_times()
+ */
+
+#include "k5-int.h"
+
+#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
+
+/*
+ * This is an internal routine which validates the krb5_timestamps
+ * field in a krb5_ticket.
+ */
+
+krb5_error_code
+krb5_validate_times(krb5_context context, krb5_ticket_times *times)
+{
+	krb5_timestamp 	  	currenttime, starttime;
+	krb5_error_code		retval;
+
+	if ((retval = krb5_timeofday(context, ¤ttime)))
+		return retval;
+
+	/* if starttime is not in ticket, then treat it as authtime */
+	if (times->starttime != 0)
+		starttime = times->starttime;
+	else
+		starttime = times->authtime;
+
+	if (starttime - currenttime > context->clockskew)
+		return KRB5KRB_AP_ERR_TKT_NYV;	/* ticket not yet valid */
+
+	if ((currenttime - times->endtime) > context->clockskew)
+		return KRB5KRB_AP_ERR_TKT_EXPIRED; /* ticket expired */
+
+	return 0;
+}
+
+       
+
diff --git a/krb5-1-6/src/lib/krb5/krb/vfy_increds.c b/krb5-1-6/src/lib/krb5/krb/vfy_increds.c
new file mode 100644
index 000000000..37adb9b93
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/vfy_increds.c
@@ -0,0 +1,224 @@
+#include "k5-int.h"
+#include "int-proto.h"
+
+static krb5_error_code
+krb5_cc_copy_creds_except(krb5_context context, krb5_ccache incc, krb5_ccache outcc, krb5_principal princ)
+{
+   krb5_error_code code;
+   krb5_flags flags;
+   krb5_cc_cursor cur;
+   krb5_creds creds;
+
+   flags = 0;				/* turns off OPENCLOSE mode */
+   if ((code = krb5_cc_set_flags(context, incc, flags)))
+      return(code);
+   if ((code = krb5_cc_set_flags(context, outcc, flags)))
+      return(code);
+
+   if ((code = krb5_cc_start_seq_get(context, incc, &cur)))
+      goto cleanup;
+
+   while (!(code = krb5_cc_next_cred(context, incc, &cur, &creds))) {
+      if (krb5_principal_compare(context, princ, creds.server))
+	 continue;
+
+      code = krb5_cc_store_cred(context, outcc, &creds);
+      krb5_free_cred_contents(context, &creds);
+      if (code)
+	 goto cleanup;
+   }
+
+   if (code != KRB5_CC_END)
+      goto cleanup;
+
+   code = 0;
+
+cleanup:
+   flags = KRB5_TC_OPENCLOSE;
+
+   if (code)
+      krb5_cc_set_flags(context, incc, flags);
+   else
+      code = krb5_cc_set_flags(context, incc, flags);
+
+   if (code)
+      krb5_cc_set_flags(context, outcc, flags);
+   else
+      code = krb5_cc_set_flags(context, outcc, flags);
+
+   return(code);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_verify_init_creds(krb5_context context,
+		       krb5_creds *creds,
+		       krb5_principal server_arg,
+		       krb5_keytab keytab_arg,
+		       krb5_ccache *ccache_arg,
+		       krb5_verify_init_creds_opt *options)
+{
+   krb5_error_code ret;
+   krb5_principal server;
+   krb5_keytab keytab;
+   krb5_ccache ccache;
+   krb5_keytab_entry kte;
+   krb5_creds in_creds, *out_creds;
+   krb5_auth_context authcon;
+   krb5_data ap_req;
+   
+   /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */
+
+   server = NULL;
+   keytab = NULL;
+   ccache = NULL;
+   out_creds = NULL;
+   authcon = NULL;
+   ap_req.data = NULL;
+
+   if (server_arg) {
+      server = server_arg;
+   } else {
+      if ((ret = krb5_sname_to_principal(context, NULL, NULL, 
+					 KRB5_NT_SRV_HST, &server)))
+	 goto cleanup;
+   }
+      
+   /* first, check if the server is in the keytab.  If not, there's
+      no reason to continue.  rd_req does all this, but there's
+      no way to know that a given error is caused by a missing
+      keytab or key, and not by some other problem. */
+
+   if (keytab_arg) {
+      keytab = keytab_arg;
+   } else {
+     if ((ret = krb5_kt_default(context, &keytab)))
+	 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 */
+
+       int nofail;
+
+       if (options &&
+	   (options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL)) {
+	   if (options->ap_req_nofail)
+	       goto cleanup;
+       } else if (krb5_libdefault_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);
+
+   /* If the creds are for the server principal, we're set, just do
+      a mk_req.	 Otherwise, do a get_credentials first. */
+
+   if (krb5_principal_compare(context, server, creds->server)) {
+      /* make an ap_req */
+      if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds,
+				      &ap_req)))
+	 goto cleanup;
+   } else {
+      /* this is unclean, but it's the easiest way without ripping the
+	 library into very small pieces.  store the client's initial cred
+	 in a memory ccache, then call the library.  Later, we'll copy
+	 everything except the initial cred into the ccache we return to
+	 the user.  A clean implementation would involve library
+	 internals with a coherent idea of "in" and "out". */
+
+      /* insert the initial cred into the ccache */
+
+      if ((ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) {
+	  ccache = NULL;
+	  goto cleanup;
+      }
+
+      if ((ret = krb5_cc_initialize(context, ccache, creds->client)))
+	 goto cleanup;
+
+      if ((ret = krb5_cc_store_cred(context, ccache, creds)))
+	 goto cleanup;
+
+      /* set up for get_creds */
+      memset(&in_creds, 0, sizeof(in_creds));
+      in_creds.client = creds->client;
+      in_creds.server = server;
+      if ((ret = krb5_timeofday(context, &in_creds.times.endtime)))
+	 goto cleanup;
+      in_creds.times.endtime += 5*60;
+
+      if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds,
+				      &out_creds)))
+	 goto cleanup;
+
+      /* make an ap_req */
+      if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds,
+				      &ap_req)))
+	 goto cleanup;
+   }
+
+   /* wipe the auth context for mk_req */
+   if (authcon) {
+      krb5_auth_con_free(context, authcon);
+      authcon = NULL;
+   }
+
+   /* verify the ap_req */
+
+   if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab,
+			  NULL, NULL)))
+      goto cleanup;
+
+   /* 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;
+
+	   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 (retcc)
+		   krb5_cc_destroy(context, retcc);
+	   } else {
+	       *ccache_arg = retcc;
+	   }
+       } else {
+	   ret = krb5_cc_copy_creds_except(context, ccache, *ccache_arg,
+					   server);
+       }
+   }
+
+   /* 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 && keytab)
+      krb5_kt_close(context, keytab);
+   if (ccache)
+      krb5_cc_destroy(context, ccache);
+   if (out_creds)
+      krb5_free_creds(context, out_creds);
+   if (authcon)
+      krb5_auth_con_free(context, authcon);
+   if (ap_req.data)
+      krb5_xfree(ap_req.data);
+
+   return(ret);
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/vic_opt.c b/krb5-1-6/src/lib/krb5/krb/vic_opt.c
new file mode 100644
index 000000000..acdf49406
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/vic_opt.c
@@ -0,0 +1,14 @@
+#include "k5-int.h"
+
+void KRB5_CALLCONV
+krb5_verify_init_creds_opt_init(krb5_verify_init_creds_opt *opt)
+{
+   opt->flags = 0;
+}
+
+void KRB5_CALLCONV
+krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_verify_init_creds_opt *opt, int ap_req_nofail)
+{
+   opt->flags |= KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL;
+   opt->ap_req_nofail = ap_req_nofail;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb/walk_rtree.c b/krb5-1-6/src/lib/krb5/krb/walk_rtree.c
new file mode 100644
index 000000000..c4673caa8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/walk_rtree.c
@@ -0,0 +1,417 @@
+/*
+ * lib/krb5/krb/walk_rtree.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_walk_realm_tree()
+ */
+
+/* ANL - Modified to allow Configurable Authentication Paths.
+ * This modification removes the restriction on the choice of realm
+ * names, i.e. they nolonger have to be hierarchical. This
+ * is allowed by RFC 1510: "If a hierarchical orginization is not used
+ * it may be necessary to consult some database in order to construct
+ * an authentication path between realms."  The database is contained
+ * in the [capaths] section of the krb5.conf file.
+ * Client to server paths are defined. There are n**2 possible
+ * entries, but only those entries which are needed by the client
+ * or server need be present in its krb5.conf file. (n entries or 2*n
+ * entries if the same krb5.conf is used for clients and servers)
+ *
+ * for example: ESnet will be running a KDC which will share
+ * inter-realm keys with its many orginizations which include among
+ * other ANL, NERSC and PNL. Each of these orginizations wants to
+ * use its DNS name in the realm, ANL.GOV. In addition ANL wants
+ * to authenticatite to HAL.COM via a K5.MOON and K5.JUPITER
+ * A [capaths] section of the krb5.conf file for the ANL.GOV clients
+ * and servers would look like:
+ *
+ * [capaths]
+ * ANL.GOV = {
+ *		NERSC.GOV = ES.NET
+ *		PNL.GOV = ES.NET
+ *		ES.NET = .
+ * 		HAL.COM = K5.MOON
+ * 		HAL.COM = K5.JUPITER
+ * }
+ * NERSC.GOV = {
+ *		ANL.GOV = ES.NET
+ * }
+ * PNL.GOV = {
+ *		ANL.GOV = ES.NET
+ * }
+ * ES.NET = {
+ * 		ANL.GOV = .
+ * }
+ * HAL.COM = {
+ *		ANL.GOV = K5.JUPITER
+ *		ANL.GOV = K5.MOON
+ * }
+ *
+ * In the above a "." is used to mean directly connected since the
+ * the profile routines cannot handle a null entry.
+ *
+ * If no client-to-server path is found, the default hierarchical path
+ * is still generated.
+ *
+ * This version of the Configurable Authentication Path modification
+ * differs from the previous versions prior to K5 beta 5 in that
+ * the profile routines are used, and the explicite path from
+ * client's realm to server's realm must be given. The modifications
+ * will work together.
+ * DEE - 5/23/95
+ */
+#define CONFIGURABLE_AUTHENTICATION_PATH
+#include "k5-int.h"
+#include "int-proto.h"
+
+/* internal function, used by krb5_get_cred_from_kdc() */
+
+#ifndef min
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#define max(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+/*
+ * xxx The following function is very confusing to read and probably
+ * is buggy.  It should be documented better.  Here is what I've
+ * learned about it doing a quick bug fixing walk through.  The
+ * function takes a client and server realm name and returns the set
+ * of realms (in a field called tree) that you need to get tickets in
+ * in order to get from the source realm to the destination realm.  It
+ * takes a realm separater character (normally ., but presumably there
+ * for all those X.500 realms) .  There are two modes it runs in: the
+ * ANL krb5.conf mode and the hierarchy mode.  The ANL mode is
+ * fairly obvious.  The hierarchy mode looks for common components in
+ * both the client and server realms.  In general, the pointer scp and
+ * ccp are used to walk through the client and server realms.  The
+ * com_sdot and com_cdot pointers point to (I think) the beginning of
+ * the common part of the realm names.  I.E. strcmp(com_cdot,
+ * com_sdot) ==0 is roughly an invarient.  However, there are cases
+ * where com_sdot and com_cdot are set to point before the start of
+ * the client or server strings.  I think this only happens when there
+ * are no common components.  --hartmans 2002/03/14
+ */
+
+krb5_error_code
+krb5_walk_realm_tree(krb5_context context, const krb5_data *client, const krb5_data *server, krb5_principal **tree, int realm_branch_char)
+{
+    krb5_error_code retval;
+    krb5_principal *rettree;
+    register char *ccp, *scp;
+    register char *prevccp = 0, *prevscp = 0;
+    char *com_sdot = 0, *com_cdot = 0;
+    register int i, links = 0;
+    int clen, slen = -1;
+    krb5_data tmpcrealm, tmpsrealm;
+    int nocommon = 1;
+
+#ifdef CONFIGURABLE_AUTHENTICATION_PATH
+    const char *cap_names[4];
+    char *cap_client, *cap_server;
+    char **cap_nodes;
+    krb5_error_code cap_code;
+#endif
+
+#ifdef DEBUG_REFERRALS
+    printf("krb5_walk_realm_tree starting\n");
+    printf("  client is %s\n",client->data);
+    printf("  server is %s\n",server->data);
+#endif
+
+    if (!(client->data &&server->data))
+      return KRB5_NO_TKT_IN_RLM;
+#ifdef CONFIGURABLE_AUTHENTICATION_PATH
+    if ((cap_client = (char *)malloc(client->length + 1)) == NULL)
+	return ENOMEM;
+    strncpy(cap_client, client->data, client->length);
+    cap_client[client->length] = '\0';
+    if ((cap_server = (char *)malloc(server->length + 1)) == NULL) {
+	krb5_xfree(cap_client);
+	return ENOMEM;
+    }
+    strncpy(cap_server, server->data, server->length);
+    cap_server[server->length] = '\0';
+    cap_names[0] = "capaths";
+    cap_names[1] = cap_client;
+    cap_names[2] = cap_server;
+    cap_names[3] = 0;
+    cap_code = profile_get_values(context->profile, cap_names, &cap_nodes);
+    krb5_xfree(cap_client);  /* done with client string */
+    cap_names[1] = 0;
+    if (cap_code == 0) {     /* found a path, so lets use it */
+	links = 0;
+	if (*cap_nodes[0] != '.') { /* a link of . means direct */
+	    while(cap_nodes[links]) {
+		links++;
+	    }
+	}
+	if (cap_nodes[links] != NULL)
+	    krb5_xfree(cap_nodes[links]);
+
+	cap_nodes[links] = cap_server; /* put server on end of list */
+	/* this simplifies the code later and make */
+	/* cleanup eaiser as well */
+	links++;		/* count the null entry at end */
+    } else {			/* no path use hierarchical method */
+	krb5_xfree(cap_server); /* failed, don't need server string */
+	cap_names[2] = 0;
+#endif
+	clen = client->length;
+	slen = server->length;
+
+	for (com_cdot = ccp = client->data + clen - 1,
+		 com_sdot = scp = server->data + slen - 1;
+	     clen && slen && *ccp == *scp ;
+	     ccp--, scp--, 	clen--, slen--) {
+	    if (*ccp == realm_branch_char) {
+		com_cdot = ccp;
+		com_sdot = scp;
+		nocommon = 0;
+	    }
+	}
+
+	/* ccp, scp point to common root.
+	   com_cdot, com_sdot point to common components. */
+	/* handle case of one ran out */
+	if (!clen) {
+	    /* construct path from client to server, down the tree */
+	    if (!slen)
+		/* in the same realm--this means there is no ticket
+		   in this realm. */
+		return KRB5_NO_TKT_IN_RLM;
+	    if (*scp == realm_branch_char) {
+		/* one is a subdomain of the other */
+		com_cdot = client->data;
+		com_sdot = scp;
+		nocommon = 0;
+	    } /* else normal case of two sharing parents */
+	}
+	if (!slen) {
+	    /* construct path from client to server, up the tree */
+	    if (*ccp == realm_branch_char) {
+		/* one is a subdomain of the other */
+		com_sdot = server->data;
+		com_cdot = ccp;
+		nocommon = 0;
+	    } /* else normal case of two sharing parents */
+	}
+	/* determine #links to/from common ancestor */
+	if (nocommon)
+	    links = 1;
+	else
+	    links = 2;
+	/* if no common ancestor, artificially set up common root at the last
+	   component, then join with special code */
+	for (ccp = client->data; ccp < com_cdot; ccp++) {
+	    if (*ccp == realm_branch_char) {
+		links++;
+		if (nocommon)
+		    prevccp = ccp;
+	    }
+	}
+
+	for (scp = server->data; scp < com_sdot; scp++) {
+	    if (*scp == realm_branch_char) {
+		links++;
+		if (nocommon)
+		    prevscp = scp;
+	    }
+	}
+	if (nocommon) {
+	    if (prevccp)
+		com_cdot = prevccp;
+	    if (prevscp)
+		com_sdot = prevscp;
+
+	    if(com_cdot == client->data + client->length -1)
+		com_cdot = client->data - 1 ;
+	    if(com_sdot == server->data + server->length -1)
+		com_sdot = server->data - 1 ;
+	}
+#ifdef CONFIGURABLE_AUTHENTICATION_PATH
+    }		/* end of if use hierarchical method */
+#endif
+
+    if (!(rettree = (krb5_principal *)calloc(links+2,
+					     sizeof(krb5_principal)))) {
+	return ENOMEM;
+    }
+    i = 1;
+    if ((retval = krb5_tgtname(context, client, client, &rettree[0]))) {
+	krb5_xfree(rettree);
+	return retval;
+    }
+#ifdef CONFIGURABLE_AUTHENTICATION_PATH
+    links--;				/* dont count the null entry on end */
+    if (cap_code == 0) {    /* found a path above */
+	tmpcrealm.data = client->data;
+	tmpcrealm.length = client->length;
+	while( i-1 <= links) {
+			
+	    tmpsrealm.data = cap_nodes[i-1];
+	    /* don't count trailing whitespace from profile_get */
+	    tmpsrealm.length = strcspn(cap_nodes[i-1],"\t ");
+	    if ((retval = krb5_tgtname(context,
+				       &tmpsrealm,
+				       &tmpcrealm,
+				       &rettree[i]))) {
+		while (i) {
+		    krb5_free_principal(context, rettree[i-1]);
+		    i--;
+		}
+		krb5_xfree(rettree);
+				/* cleanup the cap_nodes from profile_get */
+		for (i = 0; i<=links; i++) {
+		    krb5_xfree(cap_nodes[i]);
+		}
+		krb5_xfree((char *)cap_nodes);
+		return retval;
+	    }
+	    tmpcrealm.data = tmpsrealm.data;	
+	    tmpcrealm.length = tmpsrealm.length;
+	    i++;
+	}
+	/* cleanup the cap_nodes from profile_get last one has server */
+	for (i = 0; i<=links; i++) {
+	    krb5_xfree(cap_nodes[i]);
+	}
+	krb5_xfree((char *)cap_nodes);
+    } else {  /* if not cap then use hierarchical method */
+#endif
+	for (prevccp = ccp = client->data;
+	     ccp <= com_cdot;
+	     ccp++) {
+	    if (*ccp != realm_branch_char)
+		continue;
+	    ++ccp;				/* advance past dot */
+	    tmpcrealm.data = prevccp;
+	    tmpcrealm.length = client->length -
+		(prevccp - client->data);
+	    tmpsrealm.data = ccp;
+	    tmpsrealm.length = client->length -
+		(ccp - client->data);
+	    if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm,
+				       &rettree[i]))) {
+		while (i) {
+		    krb5_free_principal(context, rettree[i-1]);
+		    i--;
+		}
+		krb5_xfree(rettree);
+		return retval;
+	    }
+	    prevccp = ccp;
+	    i++;
+	}
+	if (nocommon) {
+	    tmpcrealm.data = com_cdot + 1;
+	    tmpcrealm.length = client->length -
+		(com_cdot + 1 - client->data);
+	    tmpsrealm.data = com_sdot + 1;
+	    tmpsrealm.length = server->length -
+		(com_sdot + 1 - server->data);
+	    if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm,
+				       &rettree[i]))) {
+		while (i) {
+		    krb5_free_principal(context, rettree[i-1]);
+		    i--;
+		}
+		krb5_xfree(rettree);
+		return retval;
+	    }
+	    i++;
+	}
+
+	for (prevscp = com_sdot + 1, scp = com_sdot - 1;
+	     scp > server->data;
+	     scp--) {
+	    if (*scp != realm_branch_char)
+		continue;
+	    if (scp - 1 < server->data)
+		break;			/* XXX only if . starts realm? */
+	    tmpcrealm.data = prevscp;
+	    tmpcrealm.length = server->length -
+		(prevscp - server->data);
+	    tmpsrealm.data = scp + 1;
+	    tmpsrealm.length = server->length -
+		(scp + 1 - server->data);
+	    if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm,
+				       &rettree[i]))) {
+		while (i) {
+		    krb5_free_principal(context, rettree[i-1]);
+		    i--;
+		}
+		krb5_xfree(rettree);
+		return retval;
+	    }
+	    prevscp = scp + 1;
+	    i++;
+	}
+	if (slen && com_sdot >= server->data) {
+	    /* only necessary if building down tree from ancestor or client */
+	    /* however, we can get here if we have only one component
+	       in the server realm name, hence we make sure we found a component
+	       separator there... */
+	    tmpcrealm.data = prevscp;
+	    tmpcrealm.length = server->length -
+		(prevscp - server->data);
+	    if ((retval = krb5_tgtname(context, server, &tmpcrealm,
+				       &rettree[i]))) {
+		while (i) {
+		    krb5_free_principal(context, rettree[i-1]);
+		    i--;
+		}
+		krb5_xfree(rettree);
+		return retval;
+	    }
+	}
+#ifdef CONFIGURABLE_AUTHENTICATION_PATH
+    }
+#endif
+    *tree = rettree;
+
+#ifdef DEBUG_REFERRALS
+    printf("krb5_walk_realm_tree ending; tree (length %d) is:\n",links);
+    for(i=0;i<links+2;i++) {
+        if ((*tree)[i])
+	    krb5int_dbgref_dump_principal("krb5_walk_realm_tree tree",(*tree)[i]);
+	else
+	    printf("tree element %i null\n");
+    }
+#endif
+    return 0;
+}
+
+#ifdef DEBUG_REFERRALS
+void krb5int_dbgref_dump_principal(char *d, krb5_principal p)
+{
+    int n;
+	      
+    printf("  **%s: ",d);
+    for (n=0;n<p->length;n++)
+	printf("%s<%.*s>",(n>0)?"/":"",p->data[n].length,p->data[n].data);
+    printf("@<%.*s>  (length %d, type %d)\n",p->realm.length,p->realm.data,
+	   p->length, p->type);
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/krb/x-deltat.y b/krb5-1-6/src/lib/krb5/krb/x-deltat.y
new file mode 100644
index 000000000..ccd956d10
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb/x-deltat.y
@@ -0,0 +1,229 @@
+/*
+ * lib/krb5/krb/deltat.y
+ *
+ * Copyright 1999 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_string_to_deltat()
+ */
+
+/* For a clean, thread-safe interface, we must use the "pure parser"
+   facility of GNU Bison.  Unfortunately, standard YACC has no such
+   option.  */
+
+/* N.B.: For simplicity in dealing with the distribution, the
+   Makefile.in listing for deltat.c does *not* normally list this
+   file.  If you change this file, tweak the Makefile so it'll rebuild
+   deltat.c, or do it manually.  */
+%{
+
+#include <ctype.h>
+#include <errno.h>
+#include "k5-int.h"
+
+struct param {
+    krb5_int32 delta;
+    char *p;
+};
+
+#define YYPARSE_PARAM tmv
+
+#define MAX_TIME KRB5_INT32_MAX
+#define MIN_TIME KRB5_INT32_MIN
+
+#define DAY (24 * 3600)
+#define HOUR 3600
+
+#define MAX_DAY (MAX_TIME / DAY)
+#define MIN_DAY (MIN_TIME / DAY)
+#define MAX_HOUR (MAX_TIME / HOUR)
+#define MIN_HOUR (MIN_TIME / HOUR)
+#define MAX_MIN (MAX_TIME / 60)
+#define MIN_MIN (MIN_TIME / 60)
+
+/* An explanation of the tests being performed. 
+   We do not want to overflow a 32 bit integer with out manipulations, 
+   even for testing for overflow. Therefore we rely on the following:
+
+   The lex parser will not return a number > MAX_TIME (which is out 32
+   bit limit).
+
+   Therefore, seconds (s) will require 
+       MIN_TIME < s < MAX_TIME
+
+   For subsequent tests, the logic is as follows:
+
+      If A < MAX_TIME and  B < MAX_TIME
+
+      If we want to test if A+B < MAX_TIME, there are two cases
+        if (A > 0) 
+         then A + B < MAX_TIME if B < MAX_TIME - A
+	else A + B < MAX_TIME  always.
+
+      if we want to test if MIN_TIME < A + B
+          if A > 0 - then nothing to test
+          otherwise, we test if MIN_TIME - A < B.
+
+   We of course are testing for:
+          MIN_TIME < A + B < MAX_TIME
+*/
+
+
+#define DAY_NOT_OK(d) (d) > MAX_DAY || (d) < MIN_DAY
+#define HOUR_NOT_OK(h) (h) > MAX_HOUR || (h) < MIN_HOUR
+#define MIN_NOT_OK(m) (m) > MAX_MIN || (m) < MIN_MIN
+#define SUM_OK(a, b) (((a) > 0) ? ( (b) <= MAX_TIME - (a)) : (MIN_TIME - (a) <= (b)))
+#define DO_SUM(res, a, b) if (!SUM_OK((a), (b))) YYERROR; \
+                          res = (a) + (b)
+
+
+#define OUT_D ((struct param *)tmv)->delta 
+#define DO(D,H,M,S) \
+ { \
+     /* Overflow testing - this does not handle negative values well.. */ \
+     if (DAY_NOT_OK(D) || HOUR_NOT_OK(H) || MIN_NOT_OK(M)) YYERROR; \
+     OUT_D = D * DAY; \
+     DO_SUM(OUT_D, OUT_D, H * HOUR); \
+     DO_SUM(OUT_D, OUT_D, M * 60); \
+     DO_SUM(OUT_D, OUT_D, S); \
+ }
+
+static int mylex (int *, char **);
+#define YYLEX_PARAM (&((struct param *)tmv)->p)
+#undef yylex
+#define yylex(U, P)    mylex (&(U)->val, (P))
+
+#undef yyerror
+#define yyerror(MSG)
+
+static int yyparse (void *);
+
+%}
+
+%pure_parser
+
+%union { int val; }
+
+%token <val> NUM LONGNUM OVERFLOW
+%token '-' ':' 'd' 'h' 'm' 's' tok_WS
+
+%type <val> num opt_hms opt_ms opt_s wsnum posnum
+
+%start start
+
+%%
+
+start: deltat;
+posnum: NUM | LONGNUM ;
+num: posnum | '-' posnum { $$ = - $2; } ;
+ws: /* nothing */ | tok_WS ;
+wsnum: ws num { $$ = $2; }
+        | ws OVERFLOW { YYERROR; };
+deltat:
+	  wsnum 'd' opt_hms		{ DO ($1,  0,  0, $3); }
+	| wsnum 'h' opt_ms		{ DO ( 0, $1,  0, $3); }
+	| wsnum 'm' opt_s		{ DO ( 0,  0, $1, $3); }
+	| wsnum 's'			{ DO ( 0,  0,  0, $1); }
+	| wsnum '-' NUM ':' NUM ':' NUM	{ DO ($1, $3, $5, $7); }
+	| wsnum ':' NUM ':' NUM		{ DO ( 0, $1, $3, $5); }
+	| wsnum ':' NUM			{ DO ( 0, $1, $3,  0); }
+	| wsnum 			{ DO ( 0,  0,  0, $1); } /* default to 's' */
+	;
+
+opt_hms:
+	  opt_ms
+	  | wsnum 'h' opt_ms		{ if (HOUR_NOT_OK($1)) YYERROR;
+	                                  DO_SUM($$, $1 * 3600, $3); }; 
+opt_ms:
+	  opt_s
+	| wsnum 'm' opt_s		{ if (MIN_NOT_OK($1)) YYERROR;
+	                                  DO_SUM($$, $1 * 60, $3); }; 
+opt_s:
+	  ws				{ $$ = 0; }
+	| wsnum 's' ;
+
+%%
+
+static int
+mylex (krb5_int32 *intp, char **pp)
+{
+    int num, c;
+#define P (*pp)
+    char *orig_p = P;
+
+#ifdef isascii
+    if (!isascii (*P))
+	return 0;
+#endif
+    switch (c = *P++) {
+    case '-':
+    case ':':
+    case 'd':
+    case 'h':
+    case 'm':
+    case 's':
+	return c;
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+	/* XXX assumes ASCII */
+	num = c - '0';
+	while (isdigit ((int) *P)) {
+	  if (num > MAX_TIME / 10) 
+	    return OVERFLOW;
+	    num *= 10;
+	    if (num > MAX_TIME - (*P - '0')) 
+	      return OVERFLOW;
+	    num += *P++ - '0';
+	}
+	*intp = num;
+	return (P - orig_p > 2) ? LONGNUM : NUM;
+    case ' ':
+    case '\t':
+    case '\n':
+	while (isspace ((int) *P))
+	    P++;
+	return tok_WS;
+    default:
+	return YYEOF;
+    }
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_deltat(char *string, krb5_deltat *deltatp)
+{
+    struct param p;
+    p.delta = 0;
+    p.p = string;
+    if (yyparse (&p))
+	return KRB5_DELTAT_BADFORMAT;
+    *deltatp = p.delta;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/krb5_libinit.c b/krb5-1-6/src/lib/krb5/krb5_libinit.c
new file mode 100644
index 000000000..fce97ffb2
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb5_libinit.c
@@ -0,0 +1,112 @@
+#include <assert.h>
+
+#include "autoconf.h"
+#include "com_err.h"
+#include "k5-int.h"
+#include "krb5_err.h"
+#include "kv5m_err.h"
+#include "asn1_err.h"
+#include "kdb5_err.h"
+
+#if defined(_WIN32) || defined(USE_CCAPI)
+#include "stdcc.h"
+#endif
+
+#include "krb5_libinit.h"
+#include "k5-platform.h"
+#include "cc-int.h"
+#include "kt-int.h"
+#include "rc-int.h"
+#include "os-proto.h"
+
+/*
+ * Initialize the Kerberos v5 library.
+ */
+
+MAKE_INIT_FUNCTION(krb5int_lib_init);
+MAKE_FINI_FUNCTION(krb5int_lib_fini);
+
+/* Possibly load-time initialization -- mutexes, etc.  */
+int krb5int_lib_init(void)
+{
+    int err;
+
+    krb5int_set_error_info_callout_fn (error_message);
+
+#ifdef SHOW_INITFINI_FUNCS
+    printf("krb5int_lib_init\n");
+#endif
+
+#if !USE_BUNDLE_ERROR_STRINGS
+    add_error_table(&et_krb5_error_table);
+    add_error_table(&et_kv5m_error_table);
+    add_error_table(&et_kdb5_error_table);
+    add_error_table(&et_asn1_error_table);
+    add_error_table(&et_k524_error_table);
+#endif
+
+    err = krb5int_rc_finish_init();
+    if (err)
+	return err;
+    err = krb5int_kt_initialize();
+    if (err)
+	return err;
+    err = krb5int_cc_initialize();
+    if (err)
+	return err;
+    err = k5_mutex_finish_init(&krb5int_us_time_mutex);
+    if (err)
+	return err;
+
+    return 0;
+}
+
+/* Always-delayed initialization -- error table linkage, etc.  */
+krb5_error_code krb5int_initialize_library (void)
+{
+    return CALL_INIT_FUNCTION(krb5int_lib_init);
+}
+
+/*
+ * Clean up the Kerberos v5 library state
+ */
+
+void krb5int_lib_fini(void)
+{
+    if (!INITIALIZER_RAN(krb5int_lib_init) || PROGRAM_EXITING()) {
+#ifdef SHOW_INITFINI_FUNCS
+	printf("krb5int_lib_fini: skipping\n");
+#endif
+	return;
+    }
+
+#ifdef SHOW_INITFINI_FUNCS
+    printf("krb5int_lib_fini\n");
+#endif
+
+    k5_mutex_destroy(&krb5int_us_time_mutex);
+
+    krb5int_cc_finalize();
+    krb5int_kt_finalize();
+    krb5int_rc_terminate();
+
+#if defined(_WIN32) || defined(USE_CCAPI)
+    krb5_stdcc_shutdown();
+#endif
+
+#if !USE_BUNDLE_ERROR_STRINGS
+    remove_error_table(&et_krb5_error_table);
+    remove_error_table(&et_kv5m_error_table);
+    remove_error_table(&et_kdb5_error_table);
+    remove_error_table(&et_asn1_error_table);
+    remove_error_table(&et_k524_error_table);
+#endif
+    krb5int_set_error_info_callout_fn (0);
+}
+
+/* Still exists because it went into the export list on Windows.  But
+   since the above function should be invoked at unload time, we don't
+   actually want to do anything here.  */
+void krb5int_cleanup_library (void)
+{
+}
diff --git a/krb5-1-6/src/lib/krb5/krb5_libinit.h b/krb5-1-6/src/lib/krb5/krb5_libinit.h
new file mode 100644
index 000000000..11d7248fe
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/krb5_libinit.h
@@ -0,0 +1,9 @@
+#ifndef KRB5_LIBINIT_H
+#define KRB5_LIBINIT_H
+
+#include "krb5.h"
+
+krb5_error_code krb5int_initialize_library (void);
+void krb5int_cleanup_library (void);
+
+#endif /* KRB5_LIBINIT_H */
diff --git a/krb5-1-6/src/lib/krb5/libkrb5.exports b/krb5-1-6/src/lib/krb5/libkrb5.exports
new file mode 100644
index 000000000..22d2b4272
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/libkrb5.exports
@@ -0,0 +1,746 @@
+_krb5_conf_boolean
+_krb5_use_dns_kdc
+_krb5_use_dns_realm
+asn12krb5_buf
+asn1_decode_addrtype
+asn1_decode_ap_options
+asn1_decode_authdata_elt
+asn1_decode_authdatatype
+asn1_decode_authorization_data
+asn1_decode_charstring
+asn1_decode_checksum
+asn1_decode_cksumtype
+asn1_decode_enc_kdc_rep_part
+asn1_decode_enc_sam_key
+asn1_decode_enc_sam_response_enc
+asn1_decode_enc_sam_response_enc_2
+asn1_decode_encrypted_data
+asn1_decode_encryption_key
+asn1_decode_enctype
+asn1_decode_etype_info
+asn1_decode_etype_info2
+asn1_decode_generalstring
+asn1_decode_generaltime
+asn1_decode_host_address
+asn1_decode_host_addresses
+asn1_decode_ia5string
+asn1_decode_int
+asn1_decode_int32
+asn1_decode_integer
+asn1_decode_kdc_options
+asn1_decode_kdc_rep
+asn1_decode_kdc_req
+asn1_decode_kdc_req_body
+asn1_decode_kerberos_time
+asn1_decode_krb5_flags
+asn1_decode_krb_cred_info
+asn1_decode_krb_safe_body
+asn1_decode_kvno
+asn1_decode_last_req
+asn1_decode_last_req_entry
+asn1_decode_maybe_unsigned
+asn1_decode_msgtype
+asn1_decode_null
+asn1_decode_octet
+asn1_decode_octetstring
+asn1_decode_oid
+asn1_decode_pa_data
+asn1_decode_passwdsequence
+asn1_decode_predicted_sam_response
+asn1_decode_principal_name
+asn1_decode_printablestring
+asn1_decode_realm
+asn1_decode_sam_challenge
+asn1_decode_sam_challenge_2
+asn1_decode_sam_challenge_2_body
+asn1_decode_sam_flags
+asn1_decode_sam_response
+asn1_decode_sam_response_2
+asn1_decode_seqnum
+asn1_decode_sequence_of_checksum
+asn1_decode_sequence_of_enctype
+asn1_decode_sequence_of_krb_cred_info
+asn1_decode_sequence_of_pa_data
+asn1_decode_sequence_of_passwdsequence
+asn1_decode_sequence_of_ticket
+asn1_decode_ticket
+asn1_decode_ticket_flags
+asn1_decode_transited_encoding
+asn1_decode_ui_2
+asn1_decode_ui_4
+asn1_decode_unsigned_integer
+asn1_encode_ap_options
+asn1_encode_authorization_data
+asn1_encode_charstring
+asn1_encode_checksum
+asn1_encode_enc_kdc_rep_part
+asn1_encode_enc_sam_response_enc
+asn1_encode_enc_sam_response_enc_2
+asn1_encode_encrypted_data
+asn1_encode_encryption_key
+asn1_encode_enumerated
+asn1_encode_etype_info
+asn1_encode_etype_info_entry
+asn1_encode_generalstring
+asn1_encode_generaltime
+asn1_encode_host_address
+asn1_encode_host_addresses
+asn1_encode_ia5string
+asn1_encode_integer
+asn1_encode_kdc_options
+asn1_encode_kdc_rep
+asn1_encode_kdc_req
+asn1_encode_kdc_req_body
+asn1_encode_kerberos_time
+asn1_encode_krb5_authdata_elt
+asn1_encode_krb5_flags
+asn1_encode_krb_cred_info
+asn1_encode_krb_safe_body
+asn1_encode_krb_saved_safe_body
+asn1_encode_last_req
+asn1_encode_last_req_entry
+asn1_encode_null
+asn1_encode_octetstring
+asn1_encode_oid
+asn1_encode_pa_data
+asn1_encode_passwdsequence
+asn1_encode_predicted_sam_response
+asn1_encode_principal_name
+asn1_encode_printablestring
+asn1_encode_realm
+asn1_encode_sam_challenge
+asn1_encode_sam_challenge_2
+asn1_encode_sam_challenge_2_body
+asn1_encode_sam_flags
+asn1_encode_sam_key
+asn1_encode_sam_response
+asn1_encode_sam_response_2
+asn1_encode_sequence_of_checksum
+asn1_encode_sequence_of_enctype
+asn1_encode_sequence_of_krb_cred_info
+asn1_encode_sequence_of_pa_data
+asn1_encode_sequence_of_passwdsequence
+asn1_encode_sequence_of_ticket
+asn1_encode_ticket
+asn1_encode_ticket_flags
+asn1_encode_transited_encoding
+asn1_encode_ui_4
+asn1_encode_unsigned_integer
+asn1_get_sequence
+asn1_get_tag_2
+asn1_krb5_realm_copy
+asn1_make_etag
+asn1_make_id
+asn1_make_length
+asn1_make_sequence
+asn1_make_set
+asn1_make_string
+asn1_make_tag
+asn1buf_create
+asn1buf_destroy
+asn1buf_ensure_space
+asn1buf_expand
+asn1buf_free
+asn1buf_hex_unparse
+asn1buf_imbed
+asn1buf_insert_charstring
+asn1buf_insert_octet
+asn1buf_insert_octetstring
+asn1buf_len
+asn1buf_remains
+asn1buf_remove_charstring
+asn1buf_remove_octet
+asn1buf_remove_octetstring
+asn1buf_size
+asn1buf_skiptail
+asn1buf_sync
+asn1buf_unparse
+asn1buf_wrap_data
+decode_krb5_alt_method
+decode_krb5_ap_rep
+decode_krb5_ap_rep_enc_part
+decode_krb5_ap_req
+decode_krb5_as_rep
+decode_krb5_as_req
+decode_krb5_authdata
+decode_krb5_authenticator
+decode_krb5_cred
+decode_krb5_enc_cred_part
+decode_krb5_enc_data
+decode_krb5_enc_kdc_rep_part
+decode_krb5_enc_priv_part
+decode_krb5_enc_sam_key
+decode_krb5_enc_sam_response_enc
+decode_krb5_enc_sam_response_enc_2
+decode_krb5_enc_tkt_part
+decode_krb5_encryption_key
+decode_krb5_error
+decode_krb5_etype_info
+decode_krb5_etype_info2
+decode_krb5_kdc_req_body
+decode_krb5_pa_enc_ts
+decode_krb5_padata_sequence
+decode_krb5_predicted_sam_response
+decode_krb5_priv
+decode_krb5_pwd_data
+decode_krb5_pwd_sequence
+decode_krb5_safe
+decode_krb5_safe_with_body
+decode_krb5_sam_challenge
+decode_krb5_sam_challenge_2
+decode_krb5_sam_challenge_2_body
+decode_krb5_sam_response
+decode_krb5_sam_response_2
+decode_krb5_tgs_rep
+decode_krb5_tgs_req
+decode_krb5_ticket
+encode_krb5_alt_method
+encode_krb5_ap_rep
+encode_krb5_ap_rep_enc_part
+encode_krb5_ap_req
+encode_krb5_as_rep
+encode_krb5_as_req
+encode_krb5_authdata
+encode_krb5_authenticator
+encode_krb5_cred
+encode_krb5_enc_cred_part
+encode_krb5_enc_data
+encode_krb5_enc_kdc_rep_part
+encode_krb5_enc_priv_part
+encode_krb5_enc_sam_response_enc
+encode_krb5_enc_sam_response_enc_2
+encode_krb5_enc_tkt_part
+encode_krb5_encryption_key
+encode_krb5_error
+encode_krb5_etype_info
+encode_krb5_etype_info2
+encode_krb5_kdc_req_body
+encode_krb5_pa_enc_ts
+encode_krb5_padata_sequence
+encode_krb5_predicted_sam_response
+encode_krb5_priv
+encode_krb5_pwd_data
+encode_krb5_pwd_sequence
+encode_krb5_safe
+encode_krb5_safe_with_body
+encode_krb5_sam_challenge
+encode_krb5_sam_challenge_2
+encode_krb5_sam_challenge_2_body
+encode_krb5_sam_key
+encode_krb5_sam_response
+encode_krb5_sam_response_2
+encode_krb5_setpw_req
+encode_krb5_tgs_rep
+encode_krb5_tgs_req
+encode_krb5_ticket
+et_asn1_error_table
+et_k524_error_table
+et_kdb5_error_table
+et_krb5_error_table
+et_kv5m_error_table
+et_prof_error_table
+initialize_asn1_error_table
+initialize_k524_error_table
+initialize_kdb5_error_table
+initialize_krb5_error_table
+initialize_kv5m_error_table
+initialize_prof_error_table
+krb524_convert_creds_kdc
+krb524_init_ets
+krb5_425_conv_principal
+krb5_524_conv_principal
+krb5_524_convert_creds
+krb5_address_compare
+krb5_address_order
+krb5_address_search
+krb5_aname_to_localname
+krb5_appdefault_boolean
+krb5_appdefault_string
+krb5_auth_con_free
+krb5_auth_con_genaddrs
+krb5_auth_con_get_checksum_func
+krb5_auth_con_getaddrs
+krb5_auth_con_getauthenticator
+krb5_auth_con_getflags
+krb5_auth_con_getivector
+krb5_auth_con_getkey
+krb5_auth_con_getlocalseqnumber
+krb5_auth_con_getlocalsubkey
+krb5_auth_con_getpermetypes
+krb5_auth_con_getrcache
+krb5_auth_con_getrecvsubkey
+krb5_auth_con_getremoteseqnumber
+krb5_auth_con_getremotesubkey
+krb5_auth_con_getsendsubkey
+krb5_auth_con_init
+krb5_auth_con_initivector
+krb5_auth_con_set_checksum_func
+krb5_auth_con_set_req_cksumtype
+krb5_auth_con_set_safe_cksumtype
+krb5_auth_con_setaddrs
+krb5_auth_con_setflags
+krb5_auth_con_setivector
+krb5_auth_con_setpermetypes
+krb5_auth_con_setports
+krb5_auth_con_setrcache
+krb5_auth_con_setrecvsubkey
+krb5_auth_con_setsendsubkey
+krb5_auth_con_setuseruserkey
+krb5_auth_to_rep
+krb5_build_principal
+krb5_build_principal_ext
+krb5_build_principal_va
+krb5_cccol_cursor_free
+krb5_cccol_cursor_new
+krb5_cccol_cursor_next
+krb5_cc_close
+krb5_cc_copy_creds
+krb5_cc_default
+krb5_cc_default_name
+krb5_cc_destroy
+krb5_cc_dfl_ops
+krb5_cc_end_seq_get
+krb5_cc_file_ops
+krb5_cc_gen_new
+krb5_cc_get_name
+krb5_cc_get_principal
+krb5_cc_get_type
+krb5_cc_initialize
+krb5_cc_new_unique
+krb5_cc_next_cred
+krb5_cc_register
+krb5_cc_remove_cred
+krb5_cc_resolve
+krb5_cc_retrieve_cred
+krb5_cc_retrieve_cred_default
+krb5_cc_set_default_name
+krb5_cc_set_flags
+krb5_cc_start_seq_get
+krb5_cc_store_cred
+krb5_change_cache
+krb5_change_password
+krb5_change_set_password
+krb5_check_transited_list
+krb5_chpw_result_code_string
+krb5_copy_addr
+krb5_copy_addresses
+krb5_copy_authdata
+krb5_copy_authenticator
+krb5_copy_checksum
+krb5_copy_context
+krb5_copy_creds
+krb5_copy_data
+krb5_copy_keyblock
+krb5_copy_keyblock_contents
+krb5_copy_principal
+krb5_copy_ticket
+krb5_create_secure_file
+krb5_crypto_us_timeofday
+krb5_decode_kdc_rep
+krb5_decode_ticket
+krb5_decrypt_tkt_part
+krb5_default_pwd_prompt1
+krb5_default_pwd_prompt2
+krb5_defkeyname
+krb5_deltat_to_string
+krb5_do_preauth
+krb5_encode_kdc_rep
+krb5_encrypt_helper
+krb5_encrypt_tkt_part
+krb5_externalize_data
+krb5_externalize_opaque
+krb5_fcc_ops
+krb5_find_serializer
+krb5_free_address
+krb5_free_addresses
+krb5_free_ap_rep
+krb5_free_ap_rep_enc_part
+krb5_free_ap_req
+krb5_free_authdata
+krb5_free_authenticator
+krb5_free_authenticator_contents
+krb5_free_checksum
+krb5_free_checksum_contents
+krb5_free_config_files
+krb5_free_context
+krb5_free_cred
+krb5_free_cred_contents
+krb5_free_cred_enc_part
+krb5_free_creds
+krb5_free_data
+krb5_free_data_contents
+krb5_free_default_realm
+krb5_free_enc_kdc_rep_part
+krb5_free_enc_sam_response_enc
+krb5_free_enc_sam_response_enc_2
+krb5_free_enc_sam_response_enc_2_contents
+krb5_free_enc_sam_response_enc_contents
+krb5_free_enc_tkt_part
+krb5_free_error
+krb5_free_etype_info
+krb5_free_host_realm
+krb5_free_kdc_rep
+krb5_free_kdc_req
+krb5_free_keyblock
+krb5_free_keyblock_contents
+krb5_free_keytab_entry_contents
+krb5_free_krbhst
+krb5_free_ktypes
+krb5_free_last_req
+krb5_free_pa_data
+krb5_free_pa_enc_ts
+krb5_free_predicted_sam_response
+krb5_free_predicted_sam_response_contents
+krb5_free_principal
+krb5_free_priv
+krb5_free_priv_enc_part
+krb5_free_pwd_data
+krb5_free_pwd_sequences
+krb5_free_realm_string
+krb5_free_realm_tree
+krb5_free_safe
+krb5_free_sam_challenge
+krb5_free_sam_challenge_2
+krb5_free_sam_challenge_2_body
+krb5_free_sam_challenge_2_body_contents
+krb5_free_sam_challenge_2_contents
+krb5_free_sam_challenge_contents
+krb5_free_sam_response
+krb5_free_sam_response_2
+krb5_free_sam_response_2_contents
+krb5_free_sam_response_contents
+krb5_free_tgt_creds
+krb5_free_ticket
+krb5_free_tickets
+krb5_free_tkt_authent
+krb5_free_unparsed_name
+krb5_fwd_tgt_creds
+krb5_gen_portaddr
+krb5_gen_replay_name
+krb5_generate_seq_number
+krb5_generate_subkey
+krb5_get_cred_from_kdc
+krb5_get_cred_from_kdc_renew
+krb5_get_cred_from_kdc_validate
+krb5_get_cred_via_tkt
+krb5_get_credentials
+krb5_get_credentials_renew
+krb5_get_credentials_validate
+krb5_get_default_config_files
+krb5_get_default_in_tkt_ktypes
+krb5_get_default_realm
+krb5_get_host_realm
+krb5_get_in_tkt
+krb5_get_in_tkt_with_keytab
+krb5_get_in_tkt_with_password
+krb5_get_in_tkt_with_skey
+krb5_get_init_creds
+krb5_get_init_creds_keytab
+krb5_get_init_creds_opt_alloc
+krb5_get_init_creds_opt_free
+krb5_get_init_creds_opt_free_pa
+krb5_get_init_creds_opt_get_pa
+krb5_get_init_creds_opt_init
+krb5_get_init_creds_opt_set_address_list
+krb5_get_init_creds_opt_set_change_password_prompt
+krb5_get_init_creds_opt_set_etype_list
+krb5_get_init_creds_opt_set_forwardable
+krb5_get_init_creds_opt_set_pa
+krb5_get_init_creds_opt_set_preauth_list
+krb5_get_init_creds_opt_set_proxiable
+krb5_get_init_creds_opt_set_renew_life
+krb5_get_init_creds_opt_set_salt
+krb5_get_init_creds_opt_set_tkt_life
+krb5_get_init_creds_password
+krb5_get_krbhst
+krb5_get_notification_message
+krb5_get_permitted_enctypes
+krb5_get_profile
+krb5_get_prompt_types
+krb5_get_realm_domain
+krb5_get_renewed_creds
+krb5_get_server_rcache
+krb5_get_tgs_ktypes
+krb5_get_time_offsets
+krb5_get_validated_creds
+krb5_init_context
+krb5_init_keyblock
+krb5_init_secure_context
+krb5_internalize_opaque
+krb5_is_permitted_enctype
+krb5_is_referral_realm
+krb5_is_thread_safe
+krb5_kdc_rep_decrypt_proc
+krb5_kt_add_entry
+krb5_kt_close
+krb5_kt_default
+krb5_kt_default_name
+krb5_kt_dfl_ops
+krb5_kt_end_seq_get
+krb5_kt_free_entry
+krb5_kt_get_entry
+krb5_kt_get_name
+krb5_kt_get_type
+krb5_kt_next_entry
+krb5_kt_read_service_key
+krb5_kt_register
+krb5_kt_remove_entry
+krb5_kt_resolve
+krb5_kt_start_seq_get
+krb5_ktf_ops
+krb5_ktf_writable_ops
+krb5_ktfile_add
+krb5_ktfile_close
+krb5_ktfile_end_get
+krb5_ktfile_get_entry
+krb5_ktfile_get_name
+krb5_ktfile_get_next
+krb5_ktfile_remove
+krb5_ktfile_resolve
+krb5_ktfile_ser_entry
+krb5_ktfile_start_seq_get
+krb5_ktfile_wresolve
+krb5_ktfileint_close
+krb5_ktfileint_delete_entry
+krb5_ktfileint_find_slot
+krb5_ktfileint_internal_read_entry
+krb5_ktfileint_openr
+krb5_ktfileint_openw
+krb5_ktfileint_read_entry
+krb5_ktfileint_size_entry
+krb5_ktfileint_write_entry
+krb5_kts_ops
+krb5_kuserok
+krb5_libdefault_boolean
+krb5_locate_kdc
+krb5_lock_file
+krb5_make_full_ipaddr
+krb5_make_fulladdr
+krb5_max_dgram_size
+krb5_max_skdc_timeout
+krb5_mcc_ops
+krb5_mk_1cred
+krb5_mk_error
+krb5_mk_ncred
+krb5_mk_priv
+krb5_mk_rep
+krb5_mk_req
+krb5_mk_req_extended
+krb5_mk_safe
+krb5_net_read
+krb5_net_write
+krb5_obtain_padata
+krb5_os_free_context
+krb5_os_hostaddr
+krb5_os_init_context
+krb5_os_localaddr
+krb5_overridekeyname
+krb5_parse_name
+krb5_principal2salt
+krb5_principal2salt_norealm
+krb5_principal_compare
+krb5_process_padata
+krb5_prompter_posix
+krb5_rc_close
+krb5_rc_default
+krb5_rc_default_name
+krb5_rc_default_type
+krb5_rc_destroy
+krb5_rc_dfl_close
+krb5_rc_dfl_close_no_free
+krb5_rc_dfl_destroy
+krb5_rc_dfl_expunge
+krb5_rc_dfl_get_name
+krb5_rc_dfl_get_span
+krb5_rc_dfl_init
+krb5_rc_dfl_ops
+krb5_rc_dfl_recover
+krb5_rc_dfl_resolve
+krb5_rc_dfl_store
+krb5_rc_expunge
+krb5_rc_free_entry
+krb5_rc_get_lifespan
+krb5_rc_get_name
+krb5_rc_get_type
+krb5_rc_initialize
+krb5_rc_io_close
+krb5_rc_io_creat
+krb5_rc_io_destroy
+krb5_rc_io_mark
+krb5_rc_io_move
+krb5_rc_io_open
+krb5_rc_io_read
+krb5_rc_io_size
+krb5_rc_io_sync
+krb5_rc_io_unmark
+krb5_rc_io_write
+krb5_rc_recover
+krb5_rc_register_type
+krb5_rc_resolve
+krb5_rc_resolve_full
+krb5_rc_resolve_type
+krb5_rc_store
+krb5_rd_cred
+krb5_rd_error
+krb5_rd_priv
+krb5_rd_rep
+krb5_rd_req
+krb5_rd_req_decoded
+krb5_rd_req_decoded_anyflag
+krb5_rd_safe
+krb5_read_message
+krb5_read_password
+krb5_realm_compare
+krb5_realm_iterator
+krb5_realm_iterator_create
+krb5_realm_iterator_free
+krb5_recvauth
+krb5_recvauth_version
+krb5_register_serializer
+krb5_salttype_to_string
+krb5_secure_config_files
+krb5_send_tgs
+krb5_sendauth
+krb5_sendto_kdc
+krb5_ser_address_init
+krb5_ser_auth_context_init
+krb5_ser_authdata_init
+krb5_ser_authenticator_init
+krb5_ser_ccache_init
+krb5_ser_checksum_init
+krb5_ser_context_init
+krb5_ser_keyblock_init
+krb5_ser_keytab_init
+krb5_ser_pack_bytes
+krb5_ser_pack_int32
+krb5_ser_pack_int64
+krb5_ser_principal_init
+krb5_ser_rcache_init
+krb5_ser_unpack_bytes
+krb5_ser_unpack_int32
+krb5_ser_unpack_int64
+krb5_server_decrypt_ticket_keytab
+krb5_set_config_files
+krb5_set_debugging_time
+krb5_set_default_in_tkt_ktypes
+krb5_set_default_realm
+krb5_set_default_tgs_enctypes
+krb5_set_default_tgs_ktypes
+krb5_set_password
+krb5_set_password_using_ccache
+krb5_set_principal_realm
+krb5_set_real_time
+krb5_set_time_offsets
+krb5_size_opaque
+krb5_skdc_timeout_1
+krb5_skdc_timeout_shift
+krb5_sname_to_principal
+krb5_string_to_deltat
+krb5_string_to_salttype
+krb5_string_to_timestamp
+krb5_sync_disk_file
+krb5_tgtname
+krb5_timeofday
+krb5_timestamp_to_sfstring
+krb5_timestamp_to_string
+krb5_try_realm_txt_rr
+krb5_unlock_file
+krb5_unpack_full_ipaddr
+krb5_unparse_name
+krb5_unparse_name_ext
+krb5_us_timeofday
+krb5_use_natural_time
+krb5_validate_times
+krb5_verify_init_creds
+krb5_verify_init_creds_opt_init
+krb5_verify_init_creds_opt_set_ap_req_nofail
+krb5_walk_realm_tree
+krb5_write_message
+krb5int_524_sendto_kdc
+krb5int_accessor
+krb5int_add_host_to_list
+krb5int_auth_con_chkseqnum
+krb5int_cc_creds_match_request
+krb5int_cc_default
+krb5int_cleanup_library
+krb5int_cm_call_select
+krb5int_copy_data_contents
+krb5int_foreach_localaddr
+krb5int_free_addrlist
+krb5int_free_srv_dns_data
+krb5int_generate_and_save_subkey
+krb5int_get_fq_local_hostname
+krb5int_grow_addrlist
+krb5int_initialize_library
+krb5int_krb_life_to_time
+krb5int_krb_time_to_life
+krb5int_local_addresses
+krb5int_locate_server
+krb5int_make_srv_query_realm
+krb5int_mk_chpw_req
+krb5int_mk_setpw_req
+krb5int_populate_gic_opt
+krb5int_rd_chpw_rep
+krb5int_rd_setpw_rep
+krb5int_sendto
+krb5int_sendtokdc_debug_handler
+krb5int_set_prompt_types
+krb5int_setpw_result_code_string
+krb5int_translate_gai_error
+os_get_default_config_files
+profile_abandon
+profile_add_node
+profile_add_relation
+profile_clear_relation
+profile_close_file
+profile_create_node
+profile_dereference_data
+profile_find_node
+profile_find_node_relation
+profile_find_node_subsection
+profile_flush
+profile_flush_file_data
+profile_free_file
+profile_free_list
+profile_free_node
+profile_get_boolean
+profile_get_integer
+profile_get_node_name
+profile_get_node_parent
+profile_get_node_value
+profile_get_relation_names
+profile_get_string
+profile_get_subsection_names
+profile_get_value
+profile_get_values
+profile_init
+profile_init_path
+profile_is_node_final
+profile_iterator
+profile_iterator_create
+profile_iterator_free
+profile_make_node_final
+profile_node_iterator
+profile_node_iterator_create
+profile_node_iterator_free
+profile_open_file
+profile_parse_file
+profile_release
+profile_release_string
+profile_remove_node
+profile_rename_node
+profile_rename_section
+profile_ser_externalize
+profile_ser_internalize
+profile_ser_size
+profile_set_relation_value
+profile_update_file_data
+profile_update_relation
+profile_verify_node
+profile_write_tree_file
+krb5_set_error_message
+krb5_vset_error_message
+krb5_get_error_message
+krb5_free_error_message
+krb5_clear_error_message
+krb5int_init_context_kdc
diff --git a/krb5-1-6/src/lib/krb5/os/Makefile.in b/krb5-1-6/src/lib/krb5/os/Makefile.in
new file mode 100644
index 000000000..2ab448d86
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/Makefile.in
@@ -0,0 +1,672 @@
+thisconfigdir=../../..
+myfulldir=lib/krb5/os
+mydir=lib/krb5/os
+BUILDTOP=$(REL)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS=
+DEFINES=-DLIBDIR=\"$(KRB5_LIBDIR)\"
+LOCALINCLUDES=-I$(SRCTOP)/util/profile
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=os
+##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst
+
+STLIBOBJS= \
+	accessor.o	\
+	an_to_ln.o	\
+	c_ustime.o	\
+	def_realm.o	\
+	ccdefname.o	\
+	changepw.o	\
+	dnsglue.o	\
+	dnssrv.o	\
+	free_krbhs.o	\
+	free_hstrl.o	\
+	full_ipadr.o	\
+	get_krbhst.o	\
+	gen_port.o	\
+	genaddrs.o	\
+	gen_rname.o	\
+	hostaddr.o	\
+	hst_realm.o	\
+	init_os_ctx.o	\
+	krbfileio.o	\
+	ktdefname.o	\
+	kuserok.o	\
+	mk_faddr.o	\
+	localaddr.o	\
+	locate_kdc.o	\
+	lock_file.o	\
+	net_read.o	\
+	net_write.o	\
+	osconfig.o	\
+	port2ip.o	\
+	prompter.o	\
+	read_msg.o	\
+	read_pwd.o	\
+	realm_dom.o	\
+	realm_iter.o	\
+	send524.o	\
+	sendto_kdc.o	\
+	sn2princ.o	\
+        thread_safe.o   \
+	timeofday.o	\
+	toffset.o	\
+	unlck_file.o	\
+	ustime.o	\
+	write_msg.o
+
+OBJS= \
+	$(OUTPRE)accessor.$(OBJEXT)	\
+	$(OUTPRE)an_to_ln.$(OBJEXT)	\
+	$(OUTPRE)c_ustime.$(OBJEXT)	\
+	$(OUTPRE)def_realm.$(OBJEXT)	\
+	$(OUTPRE)ccdefname.$(OBJEXT)	\
+	$(OUTPRE)changepw.$(OBJEXT)	\
+	$(OUTPRE)dnsglue.$(OBJEXT)	\
+	$(OUTPRE)dnssrv.$(OBJEXT)	\
+	$(OUTPRE)free_krbhs.$(OBJEXT)	\
+	$(OUTPRE)free_hstrl.$(OBJEXT)	\
+	$(OUTPRE)full_ipadr.$(OBJEXT)	\
+	$(OUTPRE)get_krbhst.$(OBJEXT)	\
+	$(OUTPRE)gen_port.$(OBJEXT)	\
+	$(OUTPRE)genaddrs.$(OBJEXT)	\
+	$(OUTPRE)gen_rname.$(OBJEXT)	\
+	$(OUTPRE)hostaddr.$(OBJEXT)	\
+	$(OUTPRE)hst_realm.$(OBJEXT)	\
+	$(OUTPRE)init_os_ctx.$(OBJEXT)	\
+	$(OUTPRE)krbfileio.$(OBJEXT)	\
+	$(OUTPRE)ktdefname.$(OBJEXT)	\
+	$(OUTPRE)kuserok.$(OBJEXT)	\
+	$(OUTPRE)mk_faddr.$(OBJEXT)	\
+	$(OUTPRE)localaddr.$(OBJEXT)	\
+	$(OUTPRE)locate_kdc.$(OBJEXT)	\
+	$(OUTPRE)lock_file.$(OBJEXT)	\
+	$(OUTPRE)net_read.$(OBJEXT)	\
+	$(OUTPRE)net_write.$(OBJEXT)	\
+	$(OUTPRE)osconfig.$(OBJEXT)	\
+	$(OUTPRE)port2ip.$(OBJEXT)	\
+	$(OUTPRE)prompter.$(OBJEXT)	\
+	$(OUTPRE)read_msg.$(OBJEXT)	\
+	$(OUTPRE)read_pwd.$(OBJEXT)	\
+	$(OUTPRE)realm_dom.$(OBJEXT)	\
+	$(OUTPRE)realm_iter.$(OBJEXT)	\
+	$(OUTPRE)send524.$(OBJEXT)	\
+	$(OUTPRE)sendto_kdc.$(OBJEXT)	\
+	$(OUTPRE)sn2princ.$(OBJEXT)	\
+        $(OUTPRE)thread_safe.$(OBJEXT)  \
+	$(OUTPRE)timeofday.$(OBJEXT)	\
+	$(OUTPRE)toffset.$(OBJEXT)	\
+	$(OUTPRE)unlck_file.$(OBJEXT)	\
+	$(OUTPRE)ustime.$(OBJEXT)	\
+	$(OUTPRE)write_msg.$(OBJEXT)
+
+SRCS= \
+	$(srcdir)/accessor.c    \
+	$(srcdir)/an_to_ln.c	\
+	$(srcdir)/c_ustime.c	\
+	$(srcdir)/def_realm.c	\
+	$(srcdir)/ccdefname.c	\
+	$(srcdir)/changepw.c	\
+	$(srcdir)/dnsglue.c	\
+	$(srcdir)/dnssrv.c	\
+	$(srcdir)/free_krbhs.c	\
+	$(srcdir)/free_hstrl.c	\
+	$(srcdir)/full_ipadr.c	\
+	$(srcdir)/get_krbhst.c	\
+	$(srcdir)/gen_port.c	\
+	$(srcdir)/genaddrs.c	\
+	$(srcdir)/gen_rname.c	\
+	$(srcdir)/hostaddr.c	\
+	$(srcdir)/hst_realm.c	\
+	$(srcdir)/init_os_ctx.c	\
+	$(srcdir)/krbfileio.c	\
+	$(srcdir)/ktdefname.c	\
+	$(srcdir)/kuserok.c	\
+	$(srcdir)/mk_faddr.c	\
+	$(srcdir)/localaddr.c	\
+	$(srcdir)/locate_kdc.c	\
+	$(srcdir)/lock_file.c	\
+	$(srcdir)/net_read.c	\
+	$(srcdir)/net_write.c	\
+	$(srcdir)/osconfig.c	\
+	$(srcdir)/prompter.c	\
+	$(srcdir)/read_msg.c	\
+	$(srcdir)/read_pwd.c	\
+	$(srcdir)/realm_dom.c	\
+	$(srcdir)/realm_iter.c	\
+	$(srcdir)/port2ip.c	\
+	$(srcdir)/send524.c	\
+	$(srcdir)/sendto_kdc.c	\
+	$(srcdir)/sn2princ.c	\
+        $(srcdir)/thread_safe.c \
+	$(srcdir)/timeofday.c	\
+	$(srcdir)/toffset.c	\
+	$(srcdir)/unlck_file.c	\
+	$(srcdir)/ustime.c	\
+	$(srcdir)/write_msg.c
+
+EXTRADEPSRCS = \
+	t_an_to_ln.c t_gifconf.c t_locate_kdc.c t_realm_iter.c \
+	t_std_conf.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+
+shared:
+	mkdir shared
+
+TEST_PROGS= t_std_conf t_an_to_ln t_locate_kdc
+
+T_STD_CONF_OBJS= t_std_conf.o 
+
+T_AN_TO_LN_OBJS = t_an_to_ln.o an_to_ln.o 
+
+T_REALM_ITER_OBJS = t_realm_iter.o realm_iter.o
+
+t_std_conf: $(T_STD_CONF_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_std_conf $(T_STD_CONF_OBJS) $(KRB5_BASE_LIBS)
+
+t_an_to_ln: $(T_AN_TO_LN_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_an_to_ln $(T_AN_TO_LN_OBJS) $(KRB5_BASE_LIBS)
+
+t_realm_iter: $(T_REALM_ITER_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_realm_iter $(T_REALM_ITER_OBJS) $(KRB5_BASE_LIBS)
+
+t_localaddr: localaddr.c
+	$(CC_LINK) $(ALL_CFLAGS) -DTEST -o t_localaddr $(srcdir)/localaddr.c $(KRB5_BASE_LIBS) $(LIBS)
+
+t_locate_kdc: t_locate_kdc.o
+	$(CC_LINK) $(ALL_CFLAGS) -o t_locate_kdc t_locate_kdc.o \
+		$(KRB5_BASE_LIBS)
+t_locate_kdc.o: t_locate_kdc.c locate_kdc.c dnssrv.c dnsglue.c
+$(OUTPRE)t_locate_kdc.exe: $(OUTPRE)t_locate_kdc.obj \
+		$(KLIB) $(PLIB) $(CLIB) $(SLIB)
+	link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib $(DNSLIBS)
+
+LCLINT=lclint
+LCLINTOPTS= -warnposix \
+	-usedef +charintliteral +ignoresigns -predboolint +boolint \
+	-exportlocal -retvalint \
+	+mod-uncon +modinternalstrict +modfilesys
+lclint-localaddr: localaddr.c
+	$(LCLINT) $(LCLINTOPTS) $(CPPFLAGS) $(LOCALINCLUDES) $(DEFS) \
+		-DTEST $(srcdir)/localaddr.c
+
+check-unix:: $(TEST_PROGS)
+	KRB5_CONFIG=$(srcdir)/td_krb5.conf ; export KRB5_CONFIG ;\
+	$(KRB5_RUN_ENV) $(VALGRIND) ./t_std_conf  -d -s NEW.DEFAULT.REALM -d \
+		-k IGGY.ORG -k DEFAULT_REALM.TST \
+		-D DEFAULT_REALM.TST -r bad.idea -r itar.bad.idea \
+		-r really.BAD.IDEA. -r clipper.bad.idea -r KeYEsCrOW.BaD.IDea \
+		-r pgp.good.idea -r no_domain > test.out
+	cmp test.out $(srcdir)/ref_std_conf.out
+	$(RM) test.out
+	KRB5_CONFIG=$(srcdir)/td_krb5.conf ; export KRB5_CONFIG ;\
+	$(KRB5_RUN_ENV) $(VALGRIND) ./t_locate_kdc ATHENA.MIT.EDU
+
+#
+# Do some aname-to-lname testing.
+#
+check-unix::
+	echo '[libdefaults]' > ./t_an.conf
+	echo '	default_realm = r' >> ./t_an.conf
+	echo '[realms]' >> ./t_an.conf
+	echo 'r = {' >> ./t_an.conf
+#	if test -r ../../../admin/aname/kdb5_anadd ; then \
+#		$(KRB5_RUN_ENV) $(VALGRIND) ../../../admin/aname/kdb5_anadd -a -n ./t_an p/i/i/i@r piii; \
+#		../../../admin/aname/kdb5_anadd -a -n ./t_an p/a/b/c@r pabc; \
+#		echo 'auth_to_local = DB:./t_an' >> ./t_an.conf; \
+#	fi
+	echo 'auth_to_local = RULE:[3:$$1$$3$$2](rule.*)s/rule//g' \
+		>> ./t_an.conf
+	echo 'auth_to_local = DEFAULT' >> ./t_an.conf
+	echo '}' >> ./t_an.conf
+#	if test -r ../../../admin/aname/kdb5_anadd ; then \
+#		KRB5_CONFIG=./t_an.conf ; export KRB5_CONFIG ; \
+#		$(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln p/i/i/i@r p/a/b/c@r; \
+#	fi
+	KRB5_CONFIG=./t_an.conf ; export KRB5_CONFIG ; \
+	$(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln rul/helpme/e@r ru/123/le@r
+	KRB5_CONFIG=./t_an.conf ; export KRB5_CONFIG ; \
+	$(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln fred/r@r barney/r@r
+	$(RM) ./t_an.*
+
+clean:: 
+	$(RM) $(TEST_PROGS) test.out t_std_conf.o t_an_to_ln.o t_locate_kdc.o
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+accessor.so accessor.po $(OUTPRE)accessor.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h accessor.c os-proto.h
+an_to_ln.so an_to_ln.po $(OUTPRE)an_to_ln.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h an_to_ln.c
+c_ustime.so c_ustime.po $(OUTPRE)c_ustime.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h c_ustime.c
+def_realm.so def_realm.po $(OUTPRE)def_realm.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h def_realm.c os-proto.h
+ccdefname.so ccdefname.po $(OUTPRE)ccdefname.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h ccdefname.c
+changepw.so changepw.po $(OUTPRE)changepw.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/cm.h $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h changepw.c os-proto.h
+dnsglue.so dnsglue.po $(OUTPRE)dnsglue.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  dnsglue.c dnsglue.h os-proto.h
+dnssrv.so dnssrv.po $(OUTPRE)dnssrv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  dnsglue.h dnssrv.c os-proto.h
+free_krbhs.so free_krbhs.po $(OUTPRE)free_krbhs.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h free_krbhs.c
+free_hstrl.so free_hstrl.po $(OUTPRE)free_hstrl.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h free_hstrl.c
+full_ipadr.so full_ipadr.po $(OUTPRE)full_ipadr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h full_ipadr.c os-proto.h
+get_krbhst.so get_krbhst.po $(OUTPRE)get_krbhst.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h get_krbhst.c
+gen_port.so gen_port.po $(OUTPRE)gen_port.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gen_port.c os-proto.h
+genaddrs.so genaddrs.po $(OUTPRE)genaddrs.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h genaddrs.c os-proto.h
+gen_rname.so gen_rname.po $(OUTPRE)gen_rname.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gen_rname.c os-proto.h
+hostaddr.so hostaddr.po $(OUTPRE)hostaddr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  hostaddr.c
+hst_realm.so hst_realm.po $(OUTPRE)hst_realm.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  dnsglue.h hst_realm.c os-proto.h
+init_os_ctx.so init_os_ctx.po $(OUTPRE)init_os_ctx.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/util/profile/prof_int.h \
+  init_os_ctx.c os-proto.h
+krbfileio.so krbfileio.po $(OUTPRE)krbfileio.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h krbfileio.c
+ktdefname.so ktdefname.po $(OUTPRE)ktdefname.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h ktdefname.c
+kuserok.so kuserok.po $(OUTPRE)kuserok.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  kuserok.c
+mk_faddr.so mk_faddr.po $(OUTPRE)mk_faddr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h mk_faddr.c os-proto.h
+localaddr.so localaddr.po $(OUTPRE)localaddr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/foreachaddr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  localaddr.c
+locate_kdc.so locate_kdc.po $(OUTPRE)locate_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  locate_kdc.c os-proto.h
+lock_file.so lock_file.po $(OUTPRE)lock_file.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h lock_file.c
+net_read.so net_read.po $(OUTPRE)net_read.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h net_read.c
+net_write.so net_write.po $(OUTPRE)net_write.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h net_write.c
+osconfig.so osconfig.po $(OUTPRE)osconfig.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h osconfig.c
+prompter.so prompter.po $(OUTPRE)prompter.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h prompter.c
+read_msg.so read_msg.po $(OUTPRE)read_msg.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h read_msg.c
+read_pwd.so read_pwd.po $(OUTPRE)read_pwd.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h read_pwd.c
+realm_dom.so realm_dom.po $(OUTPRE)realm_dom.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h realm_dom.c
+realm_iter.so realm_iter.po $(OUTPRE)realm_iter.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h realm_iter.c
+port2ip.so port2ip.po $(OUTPRE)port2ip.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  os-proto.h port2ip.c
+send524.so send524.po $(OUTPRE)send524.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h os-proto.h send524.c
+sendto_kdc.so sendto_kdc.po $(OUTPRE)sendto_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/cm.h $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h os-proto.h sendto_kdc.c
+sn2princ.so sn2princ.po $(OUTPRE)sn2princ.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  os-proto.h sn2princ.c
+thread_safe.so thread_safe.po $(OUTPRE)thread_safe.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h thread_safe.c
+timeofday.so timeofday.po $(OUTPRE)timeofday.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h timeofday.c
+toffset.so toffset.po $(OUTPRE)toffset.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  toffset.c
+unlck_file.so unlck_file.po $(OUTPRE)unlck_file.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h unlck_file.c
+ustime.so ustime.po $(OUTPRE)ustime.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ustime.c
+write_msg.so write_msg.po $(OUTPRE)write_msg.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h write_msg.c
+t_an_to_ln.so t_an_to_ln.po $(OUTPRE)t_an_to_ln.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \
+  t_an_to_ln.c
+t_gifconf.so t_gifconf.po $(OUTPRE)t_gifconf.$(OBJEXT): \
+  t_gifconf.c
+t_locate_kdc.so t_locate_kdc.po $(OUTPRE)t_locate_kdc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  dnsglue.c dnsglue.h dnssrv.c locate_kdc.c os-proto.h \
+  t_locate_kdc.c
+t_realm_iter.so t_realm_iter.po $(OUTPRE)t_realm_iter.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \
+  t_realm_iter.c
+t_std_conf.so t_std_conf.po $(OUTPRE)t_std_conf.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  os-proto.h t_std_conf.c
diff --git a/krb5-1-6/src/lib/krb5/os/accessor.c b/krb5-1-6/src/lib/krb5/os/accessor.c
new file mode 100644
index 000000000..876ac9749
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/accessor.c
@@ -0,0 +1,119 @@
+/*
+ * lib/krb5/os/accessor.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+*/
+
+#include "k5-int.h"
+#include "os-proto.h"
+
+/* If this trick gets used elsewhere, move it to k5-platform.h.  */
+#ifndef DESIGNATED_INITIALIZERS
+#define DESIGNATED_INITIALIZERS				\
+  /* ANSI/ISO C 1999 supports this...  */		\
+  (__STDC_VERSION__ >= 199901L				\
+   /* ...as does GCC, since version 2.something.  */	\
+   || (!defined __cplusplus && __GNUC__ >= 3))
+#endif
+
+krb5_error_code KRB5_CALLCONV
+krb5int_accessor(krb5int_access *internals, krb5_int32 version)
+{
+    if (version == KRB5INT_ACCESS_VERSION) {
+#if DESIGNATED_INITIALIZERS
+#define S(FIELD, VAL)   .FIELD = VAL
+	static const krb5int_access internals_temp = {
+#else
+#define S(FIELD, VAL)   internals_temp.FIELD = VAL
+	    krb5int_access internals_temp;
+#endif
+	    S (free_addrlist, krb5int_free_addrlist),
+	    S (krb5_hmac, krb5_hmac),
+	    S (md5_hash_provider, &krb5int_hash_md5),
+	    S (arcfour_enc_provider, &krb5int_enc_arcfour),
+	    S (sendto_udp, &krb5int_sendto),
+	    S (add_host_to_list, krb5int_add_host_to_list),
+#ifdef KRB5_DNS_LOOKUP
+	    S (make_srv_query_realm, krb5int_make_srv_query_realm),
+	    S (free_srv_dns_data, krb5int_free_srv_dns_data),
+	    S (use_dns_kdc, _krb5_use_dns_kdc),
+#else
+	    S (make_srv_query_realm, 0),
+	    S (free_srv_dns_data, 0),
+	    S (use_dns_kdc, 0),
+#endif
+#ifdef KRB5_KRB4_COMPAT
+	    S (krb_life_to_time, krb5int_krb_life_to_time),
+	    S (krb_time_to_life, krb5int_krb_time_to_life),
+	    S (krb524_encode_v4tkt, krb5int_encode_v4tkt),
+#else
+	    S (krb_life_to_time, 0),
+	    S (krb_time_to_life, 0),
+	    S (krb524_encode_v4tkt, 0),
+#endif
+	    S (krb5int_c_mandatory_cksumtype, krb5int_c_mandatory_cksumtype),
+	    S (krb5_ser_pack_int64, krb5_ser_pack_int64),
+	    S (krb5_ser_unpack_int64, krb5_ser_unpack_int64),
+	    S (asn1_ldap_encode_sequence_of_keys, krb5int_ldap_encode_sequence_of_keys),
+	    S (asn1_ldap_decode_sequence_of_keys, krb5int_ldap_decode_sequence_of_keys),
+	    S (encode_krb5_pa_pk_as_req, encode_krb5_pa_pk_as_req),
+	    S (encode_krb5_pa_pk_as_req_draft9, encode_krb5_pa_pk_as_req_draft9),
+            S (encode_krb5_pa_pk_as_rep, encode_krb5_pa_pk_as_rep),
+	    S (encode_krb5_pa_pk_as_rep_draft9, encode_krb5_pa_pk_as_rep_draft9),
+	    S (encode_krb5_auth_pack, encode_krb5_auth_pack),
+	    S (encode_krb5_auth_pack_draft9, encode_krb5_auth_pack_draft9),
+	    S (encode_krb5_kdc_dh_key_info, encode_krb5_kdc_dh_key_info),
+	    S (encode_krb5_reply_key_pack, encode_krb5_reply_key_pack),
+	    S (encode_krb5_reply_key_pack_draft9, encode_krb5_reply_key_pack_draft9),
+	    S (encode_krb5_typed_data, encode_krb5_typed_data),
+	    S (encode_krb5_td_trusted_certifiers, encode_krb5_td_trusted_certifiers),
+	    S (encode_krb5_td_dh_parameters, encode_krb5_td_dh_parameters),
+	    S (decode_krb5_pa_pk_as_req, decode_krb5_pa_pk_as_req),
+	    S (decode_krb5_pa_pk_as_req_draft9, decode_krb5_pa_pk_as_req_draft9),
+	    S (decode_krb5_pa_pk_as_rep, decode_krb5_pa_pk_as_rep),
+	    S (decode_krb5_pa_pk_as_rep_draft9, decode_krb5_pa_pk_as_rep_draft9),
+	    S (decode_krb5_auth_pack, decode_krb5_auth_pack),
+	    S (decode_krb5_auth_pack_draft9, decode_krb5_auth_pack_draft9),
+	    S (decode_krb5_kdc_dh_key_info, decode_krb5_kdc_dh_key_info),
+	    S (decode_krb5_principal_name, decode_krb5_principal_name),
+	    S (decode_krb5_reply_key_pack, decode_krb5_reply_key_pack),
+	    S (decode_krb5_reply_key_pack_draft9, decode_krb5_reply_key_pack_draft9),
+	    S (decode_krb5_typed_data, decode_krb5_typed_data),
+	    S (decode_krb5_td_trusted_certifiers, decode_krb5_td_trusted_certifiers),
+	    S (decode_krb5_td_dh_parameters, decode_krb5_td_dh_parameters),
+	    S (decode_krb5_as_req, decode_krb5_as_req),
+	    S (encode_krb5_kdc_req_body, encode_krb5_kdc_req_body),
+	    S (krb5_free_kdc_req, krb5_free_kdc_req),
+	    S (krb5int_set_prompt_types, krb5int_set_prompt_types),
+	    S (encode_krb5_authdata_elt, encode_krb5_authdata_elt),
+#if DESIGNATED_INITIALIZERS
+	};
+#else
+	0;
+#endif
+	*internals = internals_temp;
+	return 0;
+    }
+    return KRB5_OBSOLETE_FN;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/an_to_ln.c b/krb5-1-6/src/lib/krb5/os/an_to_ln.c
new file mode 100644
index 000000000..73465d66c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/an_to_ln.c
@@ -0,0 +1,831 @@
+/*
+ * lib/krb5/os/an_to_ln.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_aname_to_localname()
+ */
+
+/*
+ * We're only to AN_TO_LN rules at this point, and not doing the
+ * database lookup  (moved from configure script)
+ */
+#define AN_TO_LN_RULES
+
+#include "k5-int.h"
+#include <ctype.h>
+#if	HAVE_REGEX_H
+#include <regex.h>
+#endif	/* HAVE_REGEX_H */
+#include <string.h>
+/*
+ * Use compile(3) if no regcomp present.
+ */
+#if	!defined(HAVE_REGCOMP) && defined(HAVE_REGEXPR_H) && defined(HAVE_COMPILE)
+#define	RE_BUF_SIZE	1024
+#include <regexpr.h>
+#endif	/* !HAVE_REGCOMP && HAVE_REGEXP_H && HAVE_COMPILE */
+
+#define	MAX_FORMAT_BUFFER	1024
+#ifndef	min
+#define	min(a,b)	((a>b) ? b : a)
+#endif	/* min */
+#ifdef ANAME_DB
+/*
+ * Use standard DBM code.
+ */
+#define	KDBM_OPEN(db, fl, mo)	dbm_open(db, fl, mo)
+#define	KDBM_CLOSE(db)		dbm_close(db)
+#define	KDBM_FETCH(db, key)	dbm_fetch(db, key)
+#endif /*ANAME_DB*/
+
+/*
+ * Find the portion of the flattened principal name that we use for mapping.
+ */
+static char *
+aname_full_to_mapping_name(char *fprincname)
+{
+    char	*atp;
+    size_t	mlen;
+    char	*mname;
+
+    mname = (char *) NULL;
+    if (fprincname) {
+	atp = strrchr(fprincname, '@');
+	if (!atp)
+	    atp = &fprincname[strlen(fprincname)];
+	mlen = (size_t) (atp - fprincname);
+	
+	if ((mname = (char *) malloc(mlen+1))) {
+	    strncpy(mname, fprincname, mlen);
+	    mname[mlen] = '\0';
+	}
+    }
+    return(mname);
+}
+
+#ifdef ANAME_DB
+/*
+ * Implementation:  This version uses a DBM database, indexed by aname,
+ * to generate a lname.
+ *
+ * The entries in the database are normal C strings, and include the trailing
+ * null in the DBM datum.size.
+ */
+static krb5_error_code
+db_an_to_ln(context, dbname, aname, lnsize, lname)
+    krb5_context context;
+    char *dbname;
+    krb5_const_principal aname;
+    const unsigned int lnsize;
+    char *lname;
+{
+#if !defined(_WIN32)
+    DBM *db;
+    krb5_error_code retval;
+    datum key, contents;
+    char *princ_name;
+
+    if ((retval = krb5_unparse_name(context, aname, &princ_name)))
+	return(retval);
+    key.dptr = princ_name;
+    key.dsize = strlen(princ_name)+1;	/* need to store the NULL for
+					   decoding */
+
+    db = KDBM_OPEN(dbname, O_RDONLY, 0600);
+    if (!db) {
+	krb5_xfree(princ_name);
+	return KRB5_LNAME_CANTOPEN;
+    }
+
+    contents = KDBM_FETCH(db, key);
+
+    krb5_xfree(princ_name);
+
+    if (contents.dptr == NULL) {
+	retval = KRB5_LNAME_NOTRANS;
+    } else {
+	strncpy(lname, contents.dptr, lnsize);
+	if (lnsize < contents.dsize)
+	    retval = KRB5_CONFIG_NOTENUFSPACE;
+	else if (lname[contents.dsize-1] != '\0')
+	    retval = KRB5_LNAME_BADFORMAT;
+	else
+	    retval = 0;
+    }
+    /* can't close until we copy the contents. */
+    (void) KDBM_CLOSE(db);
+    return retval;
+#else	/* !_WIN32 && !MACINTOSH */
+    /*
+     * If we don't have support for a database mechanism, then we can't
+     * translate this now, can we?
+     */
+    return KRB5_LNAME_NOTRANS;
+#endif	/* !_WIN32 && !MACINTOSH */
+}
+#endif /*ANAME_DB*/
+
+#ifdef	AN_TO_LN_RULES
+/*
+ * Format and transform a principal name to a local name.  This is particularly
+ * useful when Kerberos principals and local user names are formatted to
+ * some particular convention.
+ *
+ * There are three parts to each rule:
+ * First part - formulate the string to perform operations on:  If not present
+ * then the string defaults to the fully flattened principal minus the realm
+ * name.  Otherwise the syntax is as follows:
+ *	"[" <ncomps> ":" <format> "]"
+ *		Where:
+ *			<ncomps> is the number of expected components for this
+ *			rule.  If the particular principal does not have this
+ *			many components, then this rule does not apply.
+ *
+ *			<format> is a string of <component> or verbatim
+ *			characters to be inserted.
+ *
+ *			<component> is of the form "$"<number> to select the
+ *			<number>th component.  <number> begins from 1.
+ *
+ * Second part - select rule validity:  If not present, then this rule may
+ * apply to all selections.  Otherwise the syntax is as follows:
+ *	"(" <regexp> ")"
+ *		Where:	<regexp> is a selector regular expression.  If this
+ *			regular expression matches the whole pattern generated
+ *			from the first part, then this rule still applies.
+ *
+ * Last part - Transform rule:  If not present, then the selection string
+ * is passed verbatim and is matched.  Otherwise, the syntax is as follows:
+ *	<rule> ...
+ *		Where:	<rule> is of the form:
+ *			"s/" <regexp> "/" <text> "/" ["g"]
+ * 
+ * In order to be able to select rule validity, the native system must support
+ * one of compile(3), re_comp(3) or regcomp(3).  In order to be able to
+ * transform (e.g. substitute), the native system must support regcomp(3) or
+ * compile(3).
+ */
+
+/*
+ * aname_do_match() 	- Does our name match the parenthesized regular
+ *			  expression?
+ * 
+ * Chew up the match portion of the regular expression and update *contextp.
+ * If no re_comp() or regcomp(), then always return a match.
+ */
+static krb5_error_code
+aname_do_match(char *string, char **contextp)
+{
+    krb5_error_code	kret;
+    char		*regexp, *startp, *endp = 0;
+    size_t		regexlen;
+#if	HAVE_REGCOMP
+    regex_t		match_exp;
+    regmatch_t		match_match;
+#elif	HAVE_REGEXPR_H
+    char		regexp_buffer[RE_BUF_SIZE];
+#endif	/* HAVE_REGEXP_H */
+
+    kret = 0;
+    /*
+     * Is this a match expression?
+     */
+    if (**contextp == '(') {
+	kret = KRB5_CONFIG_BADFORMAT;
+	startp = (*contextp) + 1;
+	endp = strchr(startp, ')');
+	/* Find the end of the match expression. */
+	if (endp) {
+	    regexlen = (size_t) (endp - startp);
+	    regexp = (char *) malloc((size_t) regexlen+1);
+	    kret = ENOMEM;
+	    if (regexp) {
+		strncpy(regexp, startp, regexlen);
+		regexp[regexlen] = '\0';
+		kret = KRB5_LNAME_NOTRANS;
+		/*
+		 * Perform the match.
+		 */
+#if	HAVE_REGCOMP
+		if (!regcomp(&match_exp, regexp, REG_EXTENDED) &&
+		    !regexec(&match_exp, string, 1, &match_match, 0)) {
+		    if ((match_match.rm_so == 0) &&
+			(match_match.rm_eo == strlen(string)))
+			kret = 0;
+		}
+		regfree(&match_exp);
+#elif	HAVE_REGEXPR_H
+		compile(regexp,
+			regexp_buffer,
+			®exp_buffer[RE_BUF_SIZE]);
+		if (step(string, regexp_buffer)) {
+		    if ((loc1 == string) &&
+			(loc2 == &string[strlen(string)]))
+			kret = 0;
+		}
+#elif	HAVE_RE_COMP
+		if (!re_comp(regexp) && re_exec(string))
+		    kret = 0;
+#else	/* HAVE_RE_COMP */
+		kret = 0;
+#endif	/* HAVE_RE_COMP */
+		free(regexp);
+	    }
+	    endp++;
+	}
+	else
+	    endp = startp;
+    }
+    *contextp = endp;
+    return(kret);
+}
+
+/*
+ * do_replacement()	- Replace the regular expression with the specified
+ * 			  replacement.
+ *
+ * If "doall" is set, it's a global replacement, otherwise, just a oneshot
+ * deal.
+ * If no regcomp() then just return the input string verbatim in the output
+ * string.
+ */
+#define use_bytes(x) \
+    out_used += (x); \
+    if (out_used > MAX_FORMAT_BUFFER) goto mem_err
+
+static int
+do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
+{
+    size_t out_used = 0;
+#if	HAVE_REGCOMP
+    regex_t	match_exp;
+    regmatch_t	match_match;
+    int		matched;
+    char	*cp;
+    char	*op;
+
+    if (!regcomp(&match_exp, regexp, REG_EXTENDED)) {
+	cp = in;
+	op = out;
+	matched = 0;
+	do {
+	    if (!regexec(&match_exp, cp, 1, &match_match, 0)) {
+		if (match_match.rm_so) {
+		    use_bytes(match_match.rm_so);
+		    strncpy(op, cp, match_match.rm_so);
+		    op += match_match.rm_so;
+		}
+		use_bytes(strlen(repl));
+		strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
+		op += strlen(op);
+		cp += match_match.rm_eo;
+		if (!doall) {
+		    use_bytes(strlen(cp));
+		    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
+		}
+		matched = 1;
+	    }
+	    else {
+		use_bytes(strlen(cp));
+		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
+		matched = 0;
+	    }
+	} while (doall && matched);
+	regfree(&match_exp);
+    }
+#elif	HAVE_REGEXPR_H
+    int		matched;
+    char	*cp;
+    char	*op;
+    char	regexp_buffer[RE_BUF_SIZE];
+    size_t	sdispl, edispl;
+
+    compile(regexp,
+	    regexp_buffer,
+	    ®exp_buffer[RE_BUF_SIZE]);
+    cp = in;
+    op = out;
+    matched = 0;
+    do {
+	if (step(cp, regexp_buffer)) {
+	    sdispl = (size_t) (loc1 - cp);
+	    edispl = (size_t) (loc2 - cp);
+	    if (sdispl) {
+		use_bytes(sdispl);
+		strncpy(op, cp, sdispl);
+		op += sdispl;
+	    }
+	    use_bytes(strlen(repl));
+	    strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
+	    op += strlen(repl);
+	    cp += edispl;
+	    if (!doall) {
+		use_bytes(strlen(cp));
+		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
+	    }
+	    matched = 1;
+	}
+	else {
+	    use_bytes(strlen(cp));
+	    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
+	    matched = 0;
+	}
+    } while (doall && matched);
+#else	/* HAVE_REGEXP_H */
+    memcpy(out, in, MAX_FORMAT_BUFFER);
+#endif	/* HAVE_REGCOMP */
+    return 1;
+ mem_err:
+#ifdef HAVE_REGCMP
+    	regfree(&match_exp);
+#endif
+	return 0;
+	
+}
+#undef use_bytes
+
+/*
+ * aname_replacer()	- Perform the specified substitutions on the input
+ *			  string and return the result.
+ *
+ * This routine enforces the "s/<pattern>/<replacement>/[g]" syntax.
+ */
+static krb5_error_code
+aname_replacer(char *string, char **contextp, char **result)
+{
+    krb5_error_code	kret;
+    char		*in;
+    char		*out;
+    char		*cp, *ep, *tp;
+    char		*rule, *repl;
+    size_t		rule_size, repl_size;
+    int			doglobal;
+
+    kret = ENOMEM;
+    *result = (char *) NULL;
+    /* Allocate the formatting buffers */
+    if ((in = (char *) malloc(MAX_FORMAT_BUFFER)) &&
+	(out = (char *) malloc(MAX_FORMAT_BUFFER))) {
+	/*
+	 * Prime the buffers.  Copy input string to "out" to simulate it
+	 * being the result of an initial iteration.
+	 */
+	strncpy(out, string, MAX_FORMAT_BUFFER - 1);
+	out[MAX_FORMAT_BUFFER - 1] = '\0';
+	in[0] = '\0';
+	kret = 0;
+	/*
+	 * Pound through the expression until we're done.
+	 */
+	for (cp = *contextp; *cp; ) {
+	    /* Skip leading whitespace */
+	    while (isspace((int) (*cp)))
+		cp++;
+
+	    /*
+	     * Find our separators.  First two characters must be "s/"
+	     * We must also find another "/" followed by another "/".
+	     */
+	    if ((cp[0] == 's') &&
+		(cp[1] == '/') &&
+		(ep = strchr(&cp[2], '/')) &&
+		(tp = strchr(&ep[1], '/'))) {
+
+		/* Figure out sizes of strings and allocate them */
+		rule_size = (size_t) (ep - &cp[2]);
+		repl_size = (size_t) (tp - &ep[1]);
+		if ((rule = (char *) malloc(rule_size+1)) &&
+		    (repl = (char *) malloc(repl_size+1))) {
+
+		    /* Copy the strings */
+		    strncpy(rule, &cp[2], rule_size);
+		    strncpy(repl, &ep[1], repl_size);
+		    rule[rule_size] = repl[repl_size] = '\0';
+
+		    /* Check for trailing "g" */
+		    doglobal = (tp[1] == 'g') ? 1 : 0;
+		    if (doglobal)
+			tp++;
+
+		    /* Swap previous in and out buffers */
+		    ep = in;
+		    in = out;
+		    out = ep;
+
+		    /* Do the replacemenbt */
+		    memset(out, '\0', MAX_FORMAT_BUFFER);
+		    if (!do_replacement(rule, repl, doglobal, in, out)) {
+			free(rule);
+		    free(repl);
+			kret = KRB5_LNAME_NOTRANS;
+			break;
+		    }
+		    free(rule);
+		    free(repl);
+
+		    /* If we have no output buffer left, this can't be good */
+		    if (strlen(out) == 0) {
+			kret = KRB5_LNAME_NOTRANS;
+			break;
+		    }
+		}
+		else {
+		    /* No memory for copies */
+		    kret = ENOMEM;
+		    break;
+		}
+	    }
+	    else {
+		/* Bad syntax */
+		kret = KRB5_CONFIG_BADFORMAT;
+		break;
+	    }
+	    /* Advance past trailer */
+	    cp = &tp[1];
+	}
+	free(in);
+	if (!kret)
+	    *result = out;
+	else
+	    free(out);
+    }
+    return(kret);
+}
+
+/*
+ * rule_an_to_ln()	- Handle aname to lname translations for RULE rules.
+ *
+ * The initial part of this routine handles the formulation of the strings from
+ * the principal name.
+ */
+static krb5_error_code
+rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, const unsigned int lnsize, char *lname)
+{
+    krb5_error_code	kret;
+    char		*current;
+    char		*fprincname;
+    char		*selstring = 0;
+    int			num_comps, compind;
+    size_t selstring_used;
+    char		*cout;
+    krb5_const krb5_data *datap;
+    char		*outstring;
+
+    /*
+     * First flatten the name.
+     */
+    current = rule;
+    if (!(kret = krb5_unparse_name(context, aname, &fprincname))) {
+	/*
+	 * First part.
+	 */
+	if (*current == '[') {
+	    if (sscanf(current+1,"%d:", &num_comps) == 1) {
+		if (num_comps == aname->length) {
+		    /*
+		     * We have a match based on the number of components.
+		     */
+		    current = strchr(current, ':');
+		    selstring = (char *) malloc(MAX_FORMAT_BUFFER);
+		    selstring_used = 0;
+		    if (current && selstring) {
+			current++;
+			cout = selstring;
+			/*
+			 * Plow through the string.
+			 */
+			while ((*current != ']') &&
+			       (*current != '\0')) {
+			    /*
+			     * Expand to a component.
+			     */
+			    if (*current == '$') {
+				if ((sscanf(current+1, "%d", &compind) == 1) &&
+				    (compind <= num_comps) &&
+				    (datap =
+				     (compind > 0)
+				     ? krb5_princ_component(context, aname,
+							    compind-1)
+				     : krb5_princ_realm(context, aname))
+				    ) {
+				    if ((datap->length < MAX_FORMAT_BUFFER)
+					&&  (selstring_used+datap->length
+					     < MAX_FORMAT_BUFFER)) {
+					selstring_used += datap->length;
+				    } else {
+					kret = ENOMEM;
+					goto errout;
+				    }
+				    strncpy(cout,
+					    datap->data,
+					    (unsigned) datap->length);
+				    cout += datap->length;
+				    *cout = '\0';
+				    current++;
+				    /* Point past number */
+				    while (isdigit((int) (*current)))
+					current++;
+				}
+				else
+				    kret = KRB5_CONFIG_BADFORMAT;
+			    }
+			    else {
+				/* Copy in verbatim. */
+				*cout = *current;
+				cout++;
+				*cout = '\0';
+				current++;
+			    }
+			}
+
+			/*
+			 * Advance past separator if appropriate.
+			 */
+			if (*current == ']')
+			    current++;
+			else
+			    kret = KRB5_CONFIG_BADFORMAT;
+
+			errout: if (kret)
+			    free(selstring);
+		    }
+		}
+		else
+		    kret = KRB5_LNAME_NOTRANS;
+	    }
+	    else
+		kret = KRB5_CONFIG_BADFORMAT;
+	}
+	else {
+	    if (!(selstring = aname_full_to_mapping_name(fprincname)))
+		kret = ENOMEM;
+	}
+	krb5_xfree(fprincname);
+    }
+    if (!kret) {
+	/*
+	 * Second part
+	 */
+	if (*current == '(')
+	    kret = aname_do_match(selstring, ¤t);
+
+	/*
+	 * Third part.
+	 */
+	if (!kret) {
+	    outstring = (char *) NULL;
+	    kret = aname_replacer(selstring, ¤t, &outstring);
+	    if (outstring) {
+		/* Copy out the value if there's enough room */
+		if (strlen(outstring)+1 <= (size_t) lnsize)
+		    strcpy(lname, outstring);
+		else
+		    kret = KRB5_CONFIG_NOTENUFSPACE;
+		free(outstring);
+	    }
+	}
+	free(selstring);
+    }
+
+    return(kret);
+}
+#endif	/* AN_TO_LN_RULES */
+
+/*
+ * Implementation:  This version checks the realm to see if it is the local
+ * realm; if so, and there is exactly one non-realm component to the name,
+ * that name is returned as the lname.
+ */
+static krb5_error_code
+default_an_to_ln(krb5_context context, krb5_const_principal aname, const unsigned int lnsize, char *lname)
+{
+    krb5_error_code retval;
+    char *def_realm;
+    unsigned int realm_length;
+
+    realm_length = krb5_princ_realm(context, aname)->length;
+    
+    if ((retval = krb5_get_default_realm(context, &def_realm))) {
+	return(retval);
+    }
+    if (((size_t) realm_length != strlen(def_realm)) ||
+        (memcmp(def_realm, krb5_princ_realm(context, aname)->data, realm_length))) {
+        free(def_realm);
+        return KRB5_LNAME_NOTRANS;
+    }
+
+    if (krb5_princ_size(context, aname) != 1) {
+        if (krb5_princ_size(context, aname) == 2 ) {
+           /* Check to see if 2nd component is the local realm. */
+           if ( strncmp(krb5_princ_component(context, aname,1)->data,def_realm,
+                        realm_length) ||
+                realm_length != krb5_princ_component(context, aname,1)->length)
+                return KRB5_LNAME_NOTRANS;
+        }
+        else
+           /* no components or more than one component to non-realm part of name
+           --no translation. */
+            return KRB5_LNAME_NOTRANS;
+    }
+
+    free(def_realm);
+    strncpy(lname, krb5_princ_component(context, aname,0)->data, 
+	    min(krb5_princ_component(context, aname,0)->length,lnsize));
+    if (lnsize <= krb5_princ_component(context, aname,0)->length ) {
+	retval = KRB5_CONFIG_NOTENUFSPACE;
+    } else {
+	lname[krb5_princ_component(context, aname,0)->length] = '\0';
+	retval = 0;
+    }
+    return retval;
+}
+
+/*
+ Converts an authentication name to a local name suitable for use by
+ programs wishing a translation to an environment-specific name (e.g.
+ user account name).
+
+ lnsize specifies the maximum length name that is to be filled into
+ lname.
+ The translation will be null terminated in all non-error returns.
+
+ returns system errors, NOT_ENOUGH_SPACE
+*/
+
+krb5_error_code KRB5_CALLCONV
+krb5_aname_to_localname(krb5_context context, krb5_const_principal aname, const int lnsize_in, char *lname)
+{
+    krb5_error_code	kret;
+    char		*realm;
+    char		*pname;
+    char		*mname;
+    const char		*hierarchy[5];
+    char		**mapping_values;
+    int			i, nvalid;
+    char		*cp, *s;
+    char		*typep, *argp;
+    unsigned int        lnsize;
+
+    if (lnsize_in < 0)
+      return KRB5_CONFIG_NOTENUFSPACE;
+
+    lnsize = lnsize_in; /* Unsigned */
+
+    /*
+     * First get the default realm.
+     */
+    if (!(kret = krb5_get_default_realm(context, &realm))) {
+	/* Flatten the name */
+	if (!(kret = krb5_unparse_name(context, aname, &pname))) {
+	    if ((mname = aname_full_to_mapping_name(pname))) {
+		/*
+		 * Search first for explicit mappings of the form:
+		 *
+		 * [realms]->realm->"auth_to_local_names"->mapping_name
+		 */
+		hierarchy[0] = "realms";
+		hierarchy[1] = realm;
+		hierarchy[2] = "auth_to_local_names";
+		hierarchy[3] = mname;
+		hierarchy[4] = (char *) NULL;
+		if (!(kret = profile_get_values(context->profile,
+						hierarchy,
+						&mapping_values))) {
+		    /* We found one or more explicit mappings. */
+		    for (nvalid=0; mapping_values[nvalid]; nvalid++);
+
+		    /* Just use the last one. */
+		    /* Trim the value. */
+		    s = mapping_values[nvalid-1];
+		    cp = s + strlen(s);
+		    while (cp > s) {
+			cp--;
+			if (!isspace((int)(*cp)))
+			    break;
+			*cp = '\0';
+		    }
+
+		    /* Copy out the value if there's enough room */
+		    if (strlen(mapping_values[nvalid-1])+1 <= (size_t) lnsize)
+			strcpy(lname, mapping_values[nvalid-1]);
+		    else
+			kret = KRB5_CONFIG_NOTENUFSPACE;
+
+		    /* Free residue */
+		    profile_free_list(mapping_values);
+		}
+		else {
+		    /*
+		     * OK - There's no explicit mapping.  Now check for
+		     * general auth_to_local rules of the form:
+		     *
+		     * [realms]->realm->"auth_to_local"
+		     *
+		     * This can have one or more of the following kinds of
+		     * values:
+		     *	DB:<filename>	- Look up principal in aname database.
+		     *	RULE:<sed-exp>	- Formulate lname from sed-exp.
+		     *	DEFAULT		- Use default rule.
+		     * The first rule to find a match is used.
+		     */
+		    hierarchy[0] = "realms";
+		    hierarchy[1] = realm;
+		    hierarchy[2] = "auth_to_local";
+		    hierarchy[3] = (char *) NULL;
+		    if (!(kret = profile_get_values(context->profile,
+						    hierarchy,
+						    &mapping_values))) {
+			/*
+			 * Loop through all the mapping values.
+			 */
+			for (i=0; mapping_values[i]; i++) {
+			    typep = mapping_values[i];
+			    argp = strchr(typep, ':');
+			    if (argp) {
+				*argp = '\0';
+				argp++;
+			    }
+#ifdef ANAME_DB
+			    if (!strcmp(typep, "DB") && argp) {
+				kret = db_an_to_ln(context,
+						   argp,
+						   aname,
+						   lnsize,
+						   lname);
+				if (kret != KRB5_LNAME_NOTRANS)
+				    break;
+			    }
+			    else
+#endif
+#ifdef	AN_TO_LN_RULES
+			    if (!strcmp(typep, "RULE") && argp) {
+				kret = rule_an_to_ln(context,
+						     argp,
+						     aname,
+						     lnsize,
+						     lname);
+				if (kret != KRB5_LNAME_NOTRANS)
+				    break;
+			    }
+			    else
+#endif	/* AN_TO_LN_RULES */
+			    if (!strcmp(typep, "DEFAULT") && !argp) {
+				kret = default_an_to_ln(context,
+							aname,
+							lnsize,
+							lname);
+				if (kret != KRB5_LNAME_NOTRANS)
+				    break;
+			    }
+			    else {
+				kret = KRB5_CONFIG_BADFORMAT;
+				break;
+			    }
+			}
+
+			/* We're done, clean up the droppings. */
+			profile_free_list(mapping_values);
+		    }
+		    else {
+			/*
+			 * No profile relation found, try default mapping.
+			 */
+			kret = default_an_to_ln(context,
+						aname,
+						lnsize,
+						lname);
+		    }
+		}
+		free(mname);
+	    }
+	    else
+		kret = ENOMEM;
+	    krb5_xfree(pname);
+	}
+	krb5_xfree(realm);
+    }
+    return(kret);
+}
+
diff --git a/krb5-1-6/src/lib/krb5/os/c_ustime.c b/krb5-1-6/src/lib/krb5/os/c_ustime.c
new file mode 100644
index 000000000..c752a4ade
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/c_ustime.c
@@ -0,0 +1,117 @@
+/*
+ * lib/crypto/os/c_ustime.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_mstimeofday for BSD 4.3
+ */
+ 
+#include "k5-int.h"
+#include "k5-thread.h"
+
+k5_mutex_t krb5int_us_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+
+struct time_now { krb5_int32 sec, usec; };
+
+#if defined(_WIN32)
+
+   /* Microsoft Windows NT and 95   (32bit)  */
+   /* This one works for WOW (Windows on Windows, ntvdm on Win-NT) */
+
+#include <time.h>
+#include <sys/timeb.h>
+#include <string.h>
+
+static krb5_error_code
+get_time_now(struct time_now *n)
+{
+    struct _timeb timeptr;
+    _ftime(&timeptr);
+    n->sec = timeptr.time;
+    n->usec = timeptr.millitm * 1000;
+    return 0;
+}
+
+#else
+
+/* Everybody else is UNIX, right?  POSIX 1996 doesn't give us
+   gettimeofday, but what real OS doesn't?  */
+
+static krb5_error_code
+get_time_now(struct time_now *n)
+{
+    struct timeval tv;
+
+    if (gettimeofday(&tv, (struct timezone *)0) == -1)
+	return errno;
+
+    n->sec = tv.tv_sec;
+    n->usec = tv.tv_usec;
+    return 0;
+}
+
+#endif
+
+static struct time_now last_time;
+
+krb5_error_code
+krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
+{
+    struct time_now now;
+    krb5_error_code err;
+
+    err = get_time_now(&now);
+    if (err)
+	return err;
+
+    err = k5_mutex_lock(&krb5int_us_time_mutex);
+    if (err)
+	return err;
+    /* Just guessing: If the number of seconds hasn't changed, yet the
+       microseconds are moving backwards, we probably just got a third
+       instance of returning the same clock value from the system, so
+       the saved value was artificially incremented.
+
+       On Windows, where we get millisecond accuracy currently, that's
+       quite likely.  On UNIX, it appears that we always get new
+       microsecond values, so this case should never trigger.  */
+    if ((now.sec == last_time.sec) && (now.usec <= last_time.usec)) {
+	/* Same as last time??? */
+	now.usec = ++last_time.usec;
+	if (now.usec >= 1000000) {
+	    ++now.sec;
+	    now.usec = 0;
+	}
+	/* For now, we're not worrying about the case of enough
+	   returns of the same value that we roll over now.sec, and
+	   the next call still gets the previous now.sec value.  */
+    }
+    last_time.sec = now.sec;	/* Remember for next time */
+    last_time.usec = now.usec;
+    k5_mutex_unlock(&krb5int_us_time_mutex);
+
+    *seconds = now.sec;
+    *microseconds = now.usec;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/ccdefname.c b/krb5-1-6/src/lib/krb5/os/ccdefname.c
new file mode 100644
index 000000000..e5059a5e6
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/ccdefname.c
@@ -0,0 +1,327 @@
+/*
+ * lib/krb5/os/ccdefname.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Return default cred. cache name.
+ */
+
+#define NEED_WINDOWS
+#include "k5-int.h"
+#include <stdio.h>
+
+#if defined(USE_CCAPI)
+#include <CredentialsCache.h>
+#endif
+
+#if defined(_WIN32)
+static int get_from_registry_indirect(char *name_buf, int name_size)
+{
+	/* If the RegKRB5CCNAME variable is set, it will point to
+	 * the registry key that has the name of the cache to use.
+	 * The Gradient PC-DCE sets the registry key
+	 * [HKEY_CURRENT_USER\Software\Gradient\DCE\Default\KRB5CCNAME]
+	 * to point at the cache file name (including the FILE: prefix).
+	 * By indirecting with the RegKRB5CCNAME entry in kerberos.ini,
+	 * we can accomodate other versions that might set a registry
+	 * variable.
+	 */
+	char newkey[256];
+	    
+	LONG name_buf_size;
+	HKEY hkey;
+	int found = 0;
+	char *cp;
+
+        newkey[0] = 0;
+	GetPrivateProfileString(INI_FILES, "RegKRB5CCNAME", "", 
+				newkey, sizeof(newkey), KERBEROS_INI);
+	if (!newkey[0])
+		return 0;
+	
+        newkey[sizeof(newkey)-1] = 0;
+	cp = strrchr(newkey,'\\');
+	if (cp) {
+		*cp = '\0'; /* split the string */
+		cp++;
+	} else
+		cp = "";
+	
+	if (RegOpenKeyEx(HKEY_CURRENT_USER, newkey, 0,
+			 KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS)
+		return 0;
+	
+	name_buf_size = name_size;
+	if (RegQueryValueEx(hkey, cp, 0, 0, 
+			    name_buf, &name_buf_size) != ERROR_SUCCESS)
+	{
+		RegCloseKey(hkey);
+		return 0;
+	}
+
+	RegCloseKey(hkey);
+	return 1;
+}
+
+/*
+ * get_from_registry
+ *
+ * This will find the ccname in the registry.  Returns 0 on error, non-zero
+ * on success.
+ */
+
+static int
+get_from_registry(
+    HKEY hBaseKey,
+    char *name_buf, 
+    int name_size
+    )
+{
+    HKEY hKey;
+    DWORD name_buf_size = (DWORD)name_size;
+    const char *key_path = "Software\\MIT\\Kerberos5";
+    const char *value_name = "ccname";
+
+    if (RegOpenKeyEx(hBaseKey, key_path, 0, KEY_QUERY_VALUE, 
+                     &hKey) != ERROR_SUCCESS)
+        return 0;
+    if (RegQueryValueEx(hKey, value_name, 0, 0, 
+                        name_buf, &name_buf_size) != ERROR_SUCCESS)
+    {
+        RegCloseKey(hKey);
+        return 0;
+    }
+    RegCloseKey(hKey);
+    return 1;
+}
+
+#define APPEND_KRB5CC "\\krb5cc"
+
+static int
+try_dir(
+    char* dir,
+    char* buffer,
+    int buf_len
+    )
+{
+    struct _stat s;
+    if (!dir)
+        return 0;
+    if (_stat(dir, &s))
+        return 0;
+    if (!(s.st_mode & _S_IFDIR))
+        return 0;
+    if (buffer != dir) {
+        strncpy(buffer, dir, buf_len);
+        buffer[buf_len-1]='\0';
+    }
+    strncat(buffer, APPEND_KRB5CC, buf_len-strlen(buffer));
+    buffer[buf_len-1] = '\0';
+    return 1;
+}
+#endif
+
+#if defined(_WIN32)
+static krb5_error_code get_from_os(char *name_buf, int name_size)
+{
+	char *prefix = krb5_cc_dfl_ops->prefix;
+        int size;
+        char *p;
+        DWORD gle;
+
+	SetLastError(0);
+	GetEnvironmentVariable(KRB5_ENV_CCNAME, name_buf, name_size);
+	gle = GetLastError();
+	if (gle == 0)
+		return 0;
+	else if (gle != ERROR_ENVVAR_NOT_FOUND)
+		return ENOMEM;
+
+	if (get_from_registry(HKEY_CURRENT_USER,
+                              name_buf, name_size) != 0)
+		return 0;
+
+	if (get_from_registry(HKEY_LOCAL_MACHINE,
+                              name_buf, name_size) != 0)
+		return 0;
+
+	if (get_from_registry_indirect(name_buf, name_size) != 0)
+		return 0;
+
+        strncpy(name_buf, prefix, name_size - 1);
+        name_buf[name_size - 1] = 0;
+        size = name_size - strlen(prefix);
+        if (size > 0)
+            strcat(name_buf, ":");
+        size--;
+        p = name_buf + name_size - size;
+	if (!strcmp(prefix, "API")) {
+		strncpy(p, "krb5cc", size);
+	} else if (!strcmp(prefix, "FILE") || !strcmp(prefix, "STDIO")) {
+		if (!try_dir(getenv("TEMP"), p, size) &&
+		    !try_dir(getenv("TMP"), p, size))
+		{
+                    int len = GetWindowsDirectory(p, size);
+                    name_buf[name_size - 1] = 0;
+                    if (len < size - sizeof(APPEND_KRB5CC))
+			strcat(p, APPEND_KRB5CC);
+		}
+	} else {
+		strncpy(p, "default_cache_name", size);
+	}
+	name_buf[name_size - 1] = 0;
+	return 0;
+}
+#endif
+
+#if defined(USE_CCAPI)
+
+static krb5_error_code get_from_os(char *name_buf, int name_size)
+{
+	krb5_error_code result = 0;
+	cc_context_t cc_context = NULL;
+	cc_string_t default_name = NULL;
+
+	cc_int32 ccerr = cc_initialize (&cc_context, ccapi_version_3, NULL, NULL);
+	if (ccerr == ccNoError) {
+		ccerr = cc_context_get_default_ccache_name (cc_context, &default_name);
+	}
+	
+	if (ccerr == ccNoError) {
+		if (strlen (default_name -> data) + 5 > name_size) {
+			result = ENOMEM;
+			goto cleanup;
+		} else {
+			sprintf (name_buf, "API:%s", default_name -> data);
+		}
+	}
+	
+cleanup:
+	if (cc_context != NULL) {
+		cc_context_release (cc_context);
+	}
+	
+	if (default_name != NULL) {
+		cc_string_release (default_name);
+	}
+	
+	return result;
+}
+
+#else
+#if !(defined(_WIN32))
+static krb5_error_code get_from_os(char *name_buf, int name_size)
+{
+	sprintf(name_buf, "FILE:/tmp/krb5cc_%ld", (long) getuid());
+	return 0;
+}
+#endif
+#endif
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_set_default_name(krb5_context context, const char *name)
+{
+    krb5_error_code err = 0;
+    char *new_ccname = NULL;
+    
+    if (!context || context->magic != KV5M_CONTEXT) { err = KV5M_CONTEXT; }
+    
+    if (name != NULL) {
+        if (!err) {
+            /* If the name isn't NULL, make a copy of it */
+            new_ccname = malloc (strlen (name) + 1);
+            if (new_ccname == NULL) { err = ENOMEM; }
+        }
+        
+        if (!err) {
+            strcpy (new_ccname, name);
+        }
+    }
+    
+    if (!err) {
+        /* free the old ccname and store the new one */
+        krb5_os_context os_ctx = context->os_context;
+        if (os_ctx->default_ccname) { free (os_ctx->default_ccname); }
+        os_ctx->default_ccname = new_ccname;
+        new_ccname = NULL;  /* don't free */
+    }
+    
+    if (new_ccname != NULL) { free (new_ccname); }
+    
+    return err;
+}
+
+	
+const char * KRB5_CALLCONV
+krb5_cc_default_name(krb5_context context)
+{
+    krb5_error_code err = 0;
+    krb5_os_context os_ctx = NULL;
+    
+    if (!context || context->magic != KV5M_CONTEXT) { err = KV5M_CONTEXT; }
+    
+    if (!err) {
+        os_ctx = context->os_context;
+        
+        if (os_ctx->default_ccname == NULL) {
+            /* Default ccache name has not been set yet */
+            char *new_ccname = NULL;
+            char new_ccbuf[1024];
+            
+            /* try the environment variable first */
+            new_ccname = getenv(KRB5_ENV_CCNAME);
+            
+            if (new_ccname == NULL) {
+                /* fall back on the default ccache name for the OS */
+                new_ccname = new_ccbuf;
+                err = get_from_os (new_ccbuf, sizeof (new_ccbuf));
+            }
+            
+            if (!err) {
+                err = krb5_cc_set_default_name (context, new_ccname);
+            }
+        }
+    }
+    
+    return err ? NULL : os_ctx->default_ccname;
+}
+
+/*
+ * caller must free name
+ */
+krb5_error_code
+krb5int_cc_os_default_name(krb5_context context, char **name)
+{
+    krb5_error_code retval = 0;
+    char *tmpname = NULL;
+
+    *name = NULL;
+    tmpname = malloc(BUFSIZ);
+    if (tmpname == NULL)
+	return ENOMEM;
+
+    retval = get_from_os(tmpname, BUFSIZ);
+    *name = tmpname;
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/changepw.c b/krb5-1-6/src/lib/krb5/os/changepw.c
new file mode 100644
index 000000000..816713dc4
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/changepw.c
@@ -0,0 +1,400 @@
+/*
+ * lib/krb5/os/changepw.c
+ *
+ * Copyright 1990,1999,2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+/*
+ * krb5_set_password - Implements set password per RFC 3244
+ * Added by Paul W. Nelson, Thursby Software Systems, Inc.
+ * Modified by Todd Stecher, Isilon Systems, to use krb1.4 socket infrastructure
+ */
+
+#include "fake-addrinfo.h"
+#include "k5-int.h"
+#include "os-proto.h"
+#include "cm.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef GETSOCKNAME_ARG3_TYPE
+#define GETSOCKNAME_ARG3_TYPE int
+#endif
+
+struct sendto_callback_context {
+    krb5_context 	context;
+    krb5_auth_context 	auth_context;
+    krb5_principal 	set_password_for;
+    char 		*newpw;
+    krb5_data 		ap_req;
+};
+
+
+/*
+ * Wrapper function for the two backends
+ */
+
+static krb5_error_code
+krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
+		    struct addrlist *addrlist, krb5_boolean useTcp)
+{
+    krb5_error_code code;
+    int sockType = (useTcp ? SOCK_STREAM : SOCK_DGRAM);
+
+    code = krb5int_locate_server (context, realm, addrlist,
+				  locate_service_kpasswd, sockType, 0);
+
+    if (code == KRB5_REALM_CANT_RESOLVE || code == KRB5_REALM_UNKNOWN) {
+	code = krb5int_locate_server (context, realm, addrlist,
+				      locate_service_kadmin, SOCK_STREAM, 0);
+	if (!code) {
+	    /* Success with admin_server but now we need to change the
+	       port number to use DEFAULT_KPASSWD_PORT and the socktype.  */
+	    int i;
+	    for (i=0; i<addrlist->naddrs; i++) {
+		struct addrinfo *a = addrlist->addrs[i].ai;
+		if (a->ai_family == AF_INET)
+		    sa2sin (a->ai_addr)->sin_port = htons(DEFAULT_KPASSWD_PORT);
+		if (sockType != SOCK_STREAM)
+		    a->ai_socktype = sockType;
+	    }
+	}
+    }
+    return (code);
+}
+
+
+/**
+ * This routine is used for a callback in sendto_kdc.c code. Simply
+ * put, we need the client addr to build the krb_priv portion of the
+ * password request.
+ */  
+
+
+static void kpasswd_sendto_msg_cleanup (void* callback_context, krb5_data* message)
+{
+    struct sendto_callback_context *ctx = callback_context;
+    krb5_free_data_contents(ctx->context, message); 
+}
+ 
+
+static int kpasswd_sendto_msg_callback(struct conn_state *conn, void *callback_context, krb5_data* message)
+{
+    krb5_error_code 			code = 0;
+    struct sockaddr_storage 		local_addr;
+    krb5_address 			local_kaddr;
+    struct sendto_callback_context	*ctx = callback_context;
+    GETSOCKNAME_ARG3_TYPE 		addrlen;
+    krb5_data				output;
+
+    memset (message, 0, sizeof(krb5_data));
+
+    /*
+     * We need the local addr from the connection socket
+     */
+    addrlen = sizeof(local_addr);
+
+    if (getsockname(conn->fd, ss2sa(&local_addr), &addrlen) < 0) {
+	code = SOCKET_ERRNO;
+	goto cleanup;
+    }
+
+    /* some brain-dead OS's don't return useful information from
+     * the getsockname call.  Namely, windows and solaris.  */
+
+    if (ss2sin(&local_addr)->sin_addr.s_addr != 0) {
+	local_kaddr.addrtype = ADDRTYPE_INET;
+	local_kaddr.length = sizeof(ss2sin(&local_addr)->sin_addr);
+	local_kaddr.contents = (krb5_octet *) &ss2sin(&local_addr)->sin_addr;
+    } else {
+	krb5_address **addrs;
+
+	code = krb5_os_localaddr(ctx->context, &addrs);
+	if (code)
+	    goto cleanup;
+
+	local_kaddr.magic = addrs[0]->magic;
+	local_kaddr.addrtype = addrs[0]->addrtype;
+	local_kaddr.length = addrs[0]->length;
+	local_kaddr.contents = malloc(addrs[0]->length);
+	if (local_kaddr.contents == NULL && addrs[0]->length != 0) {
+	    code = errno;
+	    krb5_free_addresses(ctx->context, addrs);
+	    goto cleanup;
+	}
+	memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
+
+	krb5_free_addresses(ctx->context, addrs);
+    }
+
+
+    /*
+     * TBD:  Does this tamper w/ the auth context in such a way
+     * to break us?  Yes - provide 1 per conn-state / host...
+     */
+
+
+    if ((code = krb5_auth_con_setaddrs(ctx->context, ctx->auth_context,
+				       &local_kaddr, NULL))) 
+	goto cleanup;
+
+    if (ctx->set_password_for)
+	code = krb5int_mk_setpw_req(ctx->context, 
+				    ctx->auth_context, 
+				    &ctx->ap_req, 
+				    ctx->set_password_for, 
+				    ctx->newpw, 
+				    &output);
+    else
+	code = krb5int_mk_chpw_req(ctx->context, 
+				   ctx->auth_context, 
+				   &ctx->ap_req,
+				   ctx->newpw, 
+				   &output);
+    if (code)
+	goto cleanup;
+
+    message->length = output.length;
+    message->data = output.data;
+
+cleanup:
+    return code;
+}
+
+
+/*
+** The logic for setting and changing a password is mostly the same
+** krb5_change_set_password handles both cases 
+**	if set_password_for is NULL, then a password change is performed,
+**  otherwise, the password is set for the principal indicated in set_password_for
+*/
+krb5_error_code KRB5_CALLCONV
+krb5_change_set_password(krb5_context context, krb5_creds *creds, char *newpw,
+			 krb5_principal set_password_for,
+			 int *result_code, krb5_data *result_code_string,
+			 krb5_data *result_string)
+{
+    krb5_data 			chpw_rep;
+    krb5_address 		remote_kaddr;
+    krb5_boolean		useTcp = 0;
+    GETSOCKNAME_ARG3_TYPE 	addrlen;
+    krb5_error_code 		code = 0;
+    char 			*code_string;
+    int				local_result_code;
+    
+    struct sendto_callback_context  callback_ctx;
+    struct sendto_callback_info	callback_info;
+    struct sockaddr_storage	remote_addr;
+    struct addrlist 		al = ADDRLIST_INIT;
+
+    memset( &callback_ctx, 0, sizeof(struct sendto_callback_context));
+    callback_ctx.context = context;
+    callback_ctx.newpw = newpw;
+    callback_ctx.set_password_for = set_password_for;
+
+    if ((code = krb5_auth_con_init(callback_ctx.context, 
+				   &callback_ctx.auth_context)))
+	goto cleanup;
+
+    if ((code = krb5_mk_req_extended(callback_ctx.context, 
+				     &callback_ctx.auth_context,
+				     AP_OPTS_USE_SUBKEY,
+				     NULL, 
+				     creds, 
+				     &callback_ctx.ap_req)))
+	goto cleanup;
+
+    do {
+	if ((code = krb5_locate_kpasswd(callback_ctx.context,
+					krb5_princ_realm(callback_ctx.context,
+							 creds->server),
+					&al, useTcp)))
+	    break;
+
+	addrlen = sizeof(remote_addr);
+
+	callback_info.context = (void*) &callback_ctx;
+	callback_info.pfn_callback = kpasswd_sendto_msg_callback;
+	callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
+
+	if ((code = krb5int_sendto(callback_ctx.context, 
+				   NULL, 
+				   &al, 
+				   &callback_info,
+				   &chpw_rep,
+				   NULL,
+				   NULL,
+				   ss2sa(&remote_addr),
+                                   &addrlen,
+				   NULL,
+				   NULL,
+				   NULL
+		 ))) {
+
+	    /*
+	     * Here we may want to switch to TCP on some errors.
+	     * right?
+	     */
+	    break;
+	}
+
+	remote_kaddr.addrtype = ADDRTYPE_INET;
+	remote_kaddr.length = sizeof(ss2sin(&remote_addr)->sin_addr);
+	remote_kaddr.contents = (krb5_octet *) &ss2sin(&remote_addr)->sin_addr;
+
+	if ((code = krb5_auth_con_setaddrs(callback_ctx.context,  
+					   callback_ctx.auth_context,  
+					   NULL, 
+					   &remote_kaddr)))
+	    break;
+
+	if (set_password_for)
+	    code = krb5int_rd_setpw_rep(callback_ctx.context, 
+					callback_ctx.auth_context, 
+					&chpw_rep, 
+					&local_result_code, 
+					result_string);
+	else
+	    code = krb5int_rd_chpw_rep(callback_ctx.context, 
+				       callback_ctx.auth_context, 
+				       &chpw_rep, 
+				       &local_result_code, 
+				       result_string);
+
+	if (code) {
+	    if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) {
+		krb5int_free_addrlist (&al);
+		useTcp = 1;
+		continue;
+	    }
+
+	    break;
+	}
+
+	if (result_code)
+	    *result_code = local_result_code;
+	
+	if (result_code_string) {
+	    if (set_password_for)
+		code = krb5int_setpw_result_code_string(callback_ctx.context, 
+							local_result_code, 
+							(const char **)&code_string);
+	    else
+		code = krb5_chpw_result_code_string(callback_ctx.context, 
+						    local_result_code, 
+						    &code_string);
+	    if(code)
+		goto cleanup;
+
+	    result_code_string->length = strlen(code_string);
+	    result_code_string->data = malloc(result_code_string->length);
+	    if (result_code_string->data == NULL) {
+		code = ENOMEM;
+		goto cleanup;
+	    }
+	    strncpy(result_code_string->data, code_string, result_code_string->length);
+	}
+
+	if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) {
+	    krb5int_free_addrlist (&al);
+	    useTcp = 1;
+        } else {
+	    break;
+	} 
+    } while (TRUE);
+
+cleanup:
+    if (callback_ctx.auth_context != NULL)
+	krb5_auth_con_free(callback_ctx.context, callback_ctx.auth_context);
+
+    krb5int_free_addrlist (&al);
+    krb5_free_data_contents(callback_ctx.context, &callback_ctx.ap_req);
+
+    return(code);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_change_password(krb5_context context, krb5_creds *creds, char *newpw, int *result_code, krb5_data *result_code_string, krb5_data *result_string)
+{
+	return krb5_change_set_password(
+		context, creds, newpw, NULL, result_code, result_code_string, result_string );
+}
+
+/*
+ * krb5_set_password - Implements set password per RFC 3244
+ *
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_set_password(
+	krb5_context context,
+	krb5_creds *creds,
+	char *newpw,
+	krb5_principal change_password_for,
+	int *result_code, krb5_data *result_code_string, krb5_data *result_string
+	)
+{
+	return krb5_change_set_password(
+		context, creds, newpw, change_password_for, result_code, result_code_string, result_string );
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_set_password_using_ccache(
+	krb5_context context,
+	krb5_ccache ccache,
+	char *newpw,
+	krb5_principal change_password_for,
+	int *result_code, krb5_data *result_code_string, krb5_data *result_string
+	)
+{
+    krb5_creds		creds;
+    krb5_creds		*credsp;
+    krb5_error_code	code;
+
+    /*
+    ** get the proper creds for use with krb5_set_password -
+    */
+    memset (&creds, 0, sizeof(creds));
+    /*
+    ** first get the principal for the password service -
+    */
+    code = krb5_cc_get_principal (context, ccache, &creds.client);
+    if (!code) {
+	code = krb5_build_principal(context, &creds.server, 
+				    krb5_princ_realm(context, change_password_for)->length,
+				    krb5_princ_realm(context, change_password_for)->data,
+				    "kadmin", "changepw", NULL);
+	if (!code) {
+	    code = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
+	    if (!code) {
+		code = krb5_set_password(context, credsp, newpw, change_password_for,
+					 result_code, result_code_string,
+					 result_string);
+		krb5_free_creds(context, credsp);
+	    }
+	}
+	krb5_free_cred_contents(context, &creds);
+    }
+    return code;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/def_realm.c b/krb5-1-6/src/lib/krb5/os/def_realm.c
new file mode 100644
index 000000000..d63f1af63
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/def_realm.c
@@ -0,0 +1,193 @@
+/*
+ * lib/krb5/os/def_realm.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_get_default_realm(), krb5_set_default_realm(),
+ * krb5_free_default_realm() functions.
+ */
+
+#include "k5-int.h"
+#include "os-proto.h"
+#include <stdio.h>
+
+#ifdef KRB5_DNS_LOOKUP	     
+#ifdef WSHELPER
+#include <wshelper.h>
+#else /* WSHELPER */
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#endif /* WSHELPER */
+
+/* for old Unixes and friends ... */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1)
+
+#endif /* KRB5_DNS_LOOKUP */
+
+/*
+ * Retrieves the default realm to be used if no user-specified realm is
+ *  available.  [e.g. to interpret a user-typed principal name with the
+ *  realm omitted for convenience]
+ * 
+ *  returns system errors, NOT_ENOUGH_SPACE, KV5M_CONTEXT
+*/
+
+/*
+ * Implementation:  the default realm is stored in a configuration file,
+ * named by krb5_config_file;  the first token in this file is taken as
+ * the default local realm name.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_default_realm(krb5_context context, char **lrealm)
+{
+    char *realm = 0;
+    char *cp;
+    krb5_error_code retval;
+
+    if (!context || (context->magic != KV5M_CONTEXT)) 
+	    return KV5M_CONTEXT;
+
+    if (!context->default_realm) {
+        /*
+         * XXX should try to figure out a reasonable default based
+         * on the host's DNS domain.
+         */
+        context->default_realm = 0;
+        if (context->profile != 0) {
+            retval = profile_get_string(context->profile, "libdefaults",
+                                        "default_realm", 0, 0,
+                                        &realm);
+
+            if (!retval && realm) {
+                context->default_realm = malloc(strlen(realm) + 1);
+                if (!context->default_realm) {
+                    profile_release_string(realm);
+                    return ENOMEM;
+                }
+                strcpy(context->default_realm, realm);
+                profile_release_string(realm);
+            }
+        }
+#ifndef KRB5_DNS_LOOKUP
+        else 
+            return KRB5_CONFIG_CANTOPEN;
+#else /* KRB5_DNS_LOOKUP */
+        if (context->default_realm == 0) {
+            int use_dns =  _krb5_use_dns_realm(context);
+            if ( use_dns ) {
+		/*
+		 * Since this didn't appear in our config file, try looking
+		 * it up via DNS.  Look for a TXT records of the form:
+		 *
+		 * _kerberos.<localhost>
+		 * _kerberos.<domainname>
+		 * _kerberos.<searchlist>
+		 *
+		 */
+		char localhost[MAX_DNS_NAMELEN+1];
+		char * p;
+
+		krb5int_get_fq_local_hostname (localhost, sizeof(localhost));
+
+		if ( localhost[0] ) {
+		    p = localhost;
+		    do {
+			retval = krb5_try_realm_txt_rr("_kerberos", p, 
+						       &context->default_realm);
+			p = strchr(p,'.');
+			if (p)
+			    p++;
+		    } while (retval && p && p[0]);
+
+		    if (retval)
+			retval = krb5_try_realm_txt_rr("_kerberos", "", 
+						       &context->default_realm);
+		} else {
+		    retval = krb5_try_realm_txt_rr("_kerberos", "", 
+						   &context->default_realm);
+		}
+		if (retval) {
+		    return(KRB5_CONFIG_NODEFREALM);
+		}
+            }
+        }
+#endif /* KRB5_DNS_LOOKUP */
+    }
+
+    if (context->default_realm == 0)
+	return(KRB5_CONFIG_NODEFREALM);
+    if (context->default_realm[0] == 0) {
+        free (context->default_realm);
+        context->default_realm = 0;
+        return KRB5_CONFIG_NODEFREALM;
+    }
+
+    realm = context->default_realm;
+    
+    if (!(*lrealm = cp = malloc((unsigned int) strlen(realm) + 1)))
+        return ENOMEM;
+    strcpy(cp, realm);
+    return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_set_default_realm(krb5_context context, const char *lrealm)
+{
+    if (!context || (context->magic != KV5M_CONTEXT)) 
+	    return KV5M_CONTEXT;
+
+    if (context->default_realm) {
+	    free(context->default_realm);
+	    context->default_realm = 0;
+    }
+
+    /* Allow the user to clear the default realm setting by passing in 
+       NULL */
+    if (!lrealm) return 0;
+
+    context->default_realm = malloc(strlen (lrealm) + 1);
+
+    if (!context->default_realm)
+	    return ENOMEM;
+
+    strcpy(context->default_realm, lrealm);
+    return(0);
+
+}
+
+void KRB5_CALLCONV
+krb5_free_default_realm(krb5_context context, char *lrealm)
+{
+	free (lrealm);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/dnsglue.c b/krb5-1-6/src/lib/krb5/os/dnsglue.c
new file mode 100644
index 000000000..7a6583ca0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/dnsglue.c
@@ -0,0 +1,335 @@
+/*
+ * lib/krb5/os/dnsglue.c
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+#include "autoconf.h"
+#ifdef KRB5_DNS_LOOKUP
+
+#include "dnsglue.h"
+
+/*
+ * Only use res_ninit() if there's also a res_ndestroy(), to avoid
+ * memory leaks (Linux & Solaris) and outright corruption (AIX 4.x,
+ * 5.x).  While we're at it, make sure res_nsearch() is there too.
+ *
+ * In any case, it is probable that platforms having broken
+ * res_ninit() will have thread safety hacks for res_init() and _res.
+ */
+#if HAVE_RES_NINIT && HAVE_RES_NDESTROY && HAVE_RES_NSEARCH
+#define USE_RES_NINIT 1
+#endif
+
+/*
+ * Opaque handle
+ */
+struct krb5int_dns_state {
+    int nclass;
+    int ntype;
+    void *ansp;
+    int anslen;
+    int ansmax;
+#if HAVE_NS_INITPARSE
+    int cur_ans;
+    ns_msg msg;
+#else
+    unsigned char *ptr;
+    unsigned short nanswers;
+#endif
+};
+
+#if !HAVE_NS_INITPARSE
+static int initparse(struct krb5int_dns_state *);
+#endif
+
+/*
+ * krb5int_dns_init()
+ *
+ * Initialize an opaque handle.  Do name lookup and initial parsing of
+ * reply, skipping question section.  Prepare to iterate over answer
+ * section.  Returns -1 on error, 0 on success.
+ */
+int
+krb5int_dns_init(struct krb5int_dns_state **dsp,
+		 char *host, int nclass, int ntype)
+{
+#if USE_RES_NINIT
+    struct __res_state statbuf;
+#endif
+    struct krb5int_dns_state *ds;
+    int len, ret;
+    size_t nextincr, maxincr;
+    unsigned char *p;
+
+    *dsp = ds = malloc(sizeof(*ds));
+    if (ds == NULL)
+	return -1;
+
+    ret = -1;
+    ds->nclass = nclass;
+    ds->ntype = ntype;
+    ds->ansp = NULL;
+    ds->anslen = 0;
+    ds->ansmax = 0;
+    nextincr = 2048;
+    maxincr = INT_MAX;
+
+#if HAVE_NS_INITPARSE
+    ds->cur_ans = 0;
+#endif
+
+#if USE_RES_NINIT
+    memset(&statbuf, 0, sizeof(statbuf));
+    ret = res_ninit(&statbuf);
+#else
+    ret = res_init();
+#endif
+    if (ret < 0)
+	return -1;
+
+    do {
+	p = (ds->ansp == NULL)
+	    ? malloc(nextincr) : realloc(ds->ansp, nextincr);
+
+	if (p == NULL && ds->ansp != NULL) {
+	    ret = -1;
+	    goto errout;
+	}
+	ds->ansp = p;
+	ds->ansmax = nextincr;
+
+#if USE_RES_NINIT
+	len = res_nsearch(&statbuf, host, ds->nclass, ds->ntype,
+			  ds->ansp, ds->ansmax);
+#else
+	len = res_search(host, ds->nclass, ds->ntype,
+			 ds->ansp, ds->ansmax);
+#endif
+	if (len > maxincr) {
+	    ret = -1;
+	    goto errout;
+	}
+	while (nextincr < len)
+	    nextincr *= 2;
+	if (len < 0 || nextincr > maxincr) {
+	    ret = -1;
+	    goto errout;
+	}
+    } while (len > ds->ansmax);
+
+    ds->anslen = len;
+#if HAVE_NS_INITPARSE
+    ret = ns_initparse(ds->ansp, ds->anslen, &ds->msg);
+#else
+    ret = initparse(ds);
+#endif
+    if (ret < 0)
+	goto errout;
+
+    ret = 0;
+
+errout:
+#if USE_RES_NINIT
+    res_ndestroy(&statbuf);
+#endif
+    if (ret < 0) {
+	if (ds->ansp != NULL) {
+	    free(ds->ansp);
+	    ds->ansp = NULL;
+	}
+    }
+
+    return ret;
+}
+
+#if HAVE_NS_INITPARSE
+/*
+ * krb5int_dns_nextans - get next matching answer record
+ *
+ * Sets pp to NULL if no more records.  Returns -1 on error, 0 on
+ * success.
+ */
+int
+krb5int_dns_nextans(struct krb5int_dns_state *ds,
+		    const unsigned char **pp, int *lenp)
+{
+    int len;
+    ns_rr rr;
+
+    *pp = NULL;
+    *lenp = 0;
+    while (ds->cur_ans < ns_msg_count(ds->msg, ns_s_an)) {
+	len = ns_parserr(&ds->msg, ns_s_an, ds->cur_ans, &rr);
+	if (len < 0)
+	    return -1;
+	ds->cur_ans++;
+	if (ds->nclass == ns_rr_class(rr)
+	    && ds->ntype == ns_rr_type(rr)) {
+	    *pp = ns_rr_rdata(rr);
+	    *lenp = ns_rr_rdlen(rr);
+	    return 0;
+	}
+    }
+    return 0;
+}
+#endif
+
+/*
+ * krb5int_dns_expand - wrapper for dn_expand()
+ */
+int krb5int_dns_expand(struct krb5int_dns_state *ds,
+		       const unsigned char *p,
+		       char *buf, int len)
+{
+
+#if HAVE_NS_NAME_UNCOMPRESS
+    return ns_name_uncompress(ds->ansp,
+			      (unsigned char *)ds->ansp + ds->anslen,
+			      p, buf, (size_t)len);
+#else
+    return dn_expand(ds->ansp,
+		     (unsigned char *)ds->ansp + ds->anslen,
+		     p, buf, len);
+#endif
+}
+
+/*
+ * Free stuff.
+ */
+void
+krb5int_dns_fini(struct krb5int_dns_state *ds)
+{
+    if (ds == NULL)
+	return;
+    if (ds->ansp != NULL)
+	free(ds->ansp);
+    free(ds);
+}
+
+/*
+ * Compat routines for BIND 4
+ */
+#if !HAVE_NS_INITPARSE
+
+/*
+ * initparse
+ *
+ * Skip header and question section of reply.  Set a pointer to the
+ * beginning of the answer section, and prepare to iterate over
+ * answer records.
+ */
+static int
+initparse(struct krb5int_dns_state *ds)
+{
+    HEADER *hdr;
+    unsigned char *p;
+    unsigned short nqueries, nanswers;
+    int len;
+#if !HAVE_DN_SKIPNAME
+    char host[MAXDNAME];
+#endif
+
+    if (ds->anslen < sizeof(HEADER))
+	return -1;
+
+    hdr = (HEADER *)ds->ansp;
+    p = ds->ansp;
+    nqueries = ntohs((unsigned short)hdr->qdcount);
+    nanswers = ntohs((unsigned short)hdr->ancount);
+    p += sizeof(HEADER);
+
+    /*
+     * Skip query records.
+     */
+    while (nqueries--) {
+#if HAVE_DN_SKIPNAME
+	len = dn_skipname(p, (unsigned char *)ds->ansp + ds->anslen);
+#else
+	len = dn_expand(ds->ansp, (unsigned char *)ds->ansp + ds->anslen,
+			p, host, sizeof(host));
+#endif
+	if (len < 0 || !INCR_OK(ds->ansp, ds->anslen, p, len + 4))
+	    return -1;
+	p += len + 4;
+    }
+    ds->ptr = p;
+    ds->nanswers = nanswers;
+    return 0;
+}
+
+/*
+ * krb5int_dns_nextans() - get next answer record
+ *
+ * Sets pp to NULL if no more records.
+ */
+int
+krb5int_dns_nextans(struct krb5int_dns_state *ds,
+		    const unsigned char **pp, int *lenp)
+{
+    int len;
+    unsigned char *p;
+    unsigned short ntype, nclass, rdlen;
+#if !HAVE_DN_SKIPNAME
+    char host[MAXDNAME];
+#endif
+
+    *pp = NULL;
+    *lenp = 0;
+    p = ds->ptr;
+
+    while (ds->nanswers--) {
+#if HAVE_DN_SKIPNAME
+	len = dn_skipname(p, (unsigned char *)ds->ansp + ds->anslen);
+#else
+	len = dn_expand(ds->ansp, (unsigned char *)ds->ansp + ds->anslen,
+			p, host, sizeof(host));
+#endif
+	if (len < 0 || !INCR_OK(ds->ansp, ds->anslen, p, len))
+	    return -1;
+	p += len;
+	SAFE_GETUINT16(ds->ansp, ds->anslen, p, 2, ntype, out);
+	/* Also skip 4 bytes of TTL */
+	SAFE_GETUINT16(ds->ansp, ds->anslen, p, 6, nclass, out);
+	SAFE_GETUINT16(ds->ansp, ds->anslen, p, 2, rdlen, out);
+
+	if (!INCR_OK(ds->ansp, ds->anslen, p, rdlen))
+	    return -1;
+	if (rdlen > INT_MAX)
+	    return -1;
+	if (nclass == ds->nclass && ntype == ds->ntype) {
+	    *pp = p;
+	    *lenp = rdlen;
+	    ds->ptr = p + rdlen;
+	    return 0;
+	}
+	p += rdlen;
+    }
+    return 0;
+out:
+    return -1;
+}
+
+#endif
+
+#endif /* KRB5_DNS_LOOKUP */
diff --git a/krb5-1-6/src/lib/krb5/os/dnsglue.h b/krb5-1-6/src/lib/krb5/os/dnsglue.h
new file mode 100644
index 000000000..c73a43305
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/dnsglue.h
@@ -0,0 +1,157 @@
+/*
+ * lib/krb5/os/dnsglue.h
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Glue layer for DNS resolver, to make parsing of replies easier
+ * whether we are using BIND 4, 8, or 9.
+ */
+
+/*
+ * BIND 4 doesn't have the ns_initparse() API, so we need to do some
+ * manual parsing via the HEADER struct.  BIND 8 does have
+ * ns_initparse(), but has enums for the various protocol constants
+ * rather than the BIND 4 macros.  BIND 9 (at least on Mac OS X
+ * Panther) appears to disable res_nsearch() if BIND_8_COMPAT is
+ * defined (which is necessary to obtain the HEADER struct).
+ *
+ * We use ns_initparse() if available at all, and never define
+ * BIND_8_COMPAT.  If there is no ns_initparse(), we do manual parsing
+ * by using the HEADER struct.
+ */
+
+#ifndef KRB5_DNSGLUE_H
+#define KRB5_DNSGLUE_H
+
+#include "autoconf.h"
+#ifdef KRB5_DNS_LOOKUP
+
+#include "k5-int.h"
+#include "os-proto.h"
+#ifdef WSHELPER
+#include <wshelper.h>
+#else /* WSHELPER */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#endif /* WSHELPER */
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>		/* for MAXHOSTNAMELEN */
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64	/* if we can't find it elswhere */
+#endif
+
+#ifndef MAXDNAME
+
+#ifdef NS_MAXDNAME
+#define MAXDNAME NS_MAXDNAME
+#else
+#ifdef MAXLABEL
+#define MAXDNAME (16 * MAXLABEL)
+#else
+#define MAXDNAME (16 * MAXHOSTNAMELEN)
+#endif
+#endif
+
+#endif
+
+#if HAVE_NS_INITPARSE
+/*
+ * Solaris 7 has ns_rr_cl rather than ns_rr_class.
+ */
+#if !defined(ns_rr_class) && defined(ns_rr_cl)
+#define ns_rr_class ns_rr_cl
+#endif
+#endif
+
+#if HAVE_RES_NSEARCH
+/*
+ * Some BIND 8 / BIND 9 implementations disable the BIND 4 style
+ * constants.
+ */
+#ifndef C_IN
+#define C_IN ns_c_in
+#endif
+#ifndef T_SRV
+#define T_SRV ns_t_srv
+#endif
+#ifndef T_TXT
+#define T_TXT ns_t_txt
+#endif
+
+#else  /* !HAVE_RES_NSEARCH */
+
+/*
+ * Some BIND implementations might be old enough to lack these.
+ */
+#ifndef T_TXT
+#define T_TXT 15
+#endif
+#ifndef T_SRV
+#define T_SRV 33
+#endif
+
+#endif /* HAVE_RES_NSEARCH */
+
+/*
+ * INCR_OK
+ *
+ * Given moving pointer PTR offset from BASE, return true if adding
+ * INCR to PTR doesn't move it PTR than MAX bytes from BASE.
+ */
+#define INCR_OK(base, max, ptr, incr)				\
+    ((incr) <= (max) - ((const unsigned char *)(ptr)		\
+			- (const unsigned char *)(base)))
+
+/*
+ * SAFE_GETUINT16
+ *
+ * Given PTR offset from BASE, if at least INCR bytes are safe to
+ * read, get network byte order uint16 into S, and increment PTR.  On
+ * failure, goto LABEL.
+ */
+
+#define SAFE_GETUINT16(base, max, ptr, incr, s, label)	\
+    do {						\
+	if (!INCR_OK(base, max, ptr, incr)) goto label;	\
+	(s) = (unsigned short)(p)[0] << 8		\
+	    | (unsigned short)(p)[1];			\
+	(p) += (incr);					\
+    } while (0)
+
+struct krb5int_dns_state;
+
+int krb5int_dns_init(struct krb5int_dns_state **, char *, int, int);
+int krb5int_dns_nextans(struct krb5int_dns_state *,
+			const unsigned char **, int *);
+int krb5int_dns_expand(struct krb5int_dns_state *,
+		       const unsigned char *, char *, int);
+void krb5int_dns_fini(struct krb5int_dns_state *);
+
+#endif /* KRB5_DNS_LOOKUP */
+#endif /* !defined(KRB5_DNSGLUE_H) */
diff --git a/krb5-1-6/src/lib/krb5/os/dnssrv.c b/krb5-1-6/src/lib/krb5/os/dnssrv.c
new file mode 100644
index 000000000..d1c96b291
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/dnssrv.c
@@ -0,0 +1,185 @@
+/*
+ * lib/krb5/os/dnssrv.c
+ *
+ * Copyright 1990,2000,2001,2002,2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * do DNS SRV RR queries
+ */
+
+#include "autoconf.h"
+#ifdef KRB5_DNS_LOOKUP
+
+#include "dnsglue.h"
+
+/*
+ * Lookup a KDC via DNS SRV records
+ */
+
+void krb5int_free_srv_dns_data (struct srv_dns_entry *p)
+{
+    struct srv_dns_entry *next;
+    while (p) {
+	next = p->next;
+	free(p->host);
+	free(p);
+	p = next;
+    }
+}
+
+/* Do DNS SRV query, return results in *answers.
+
+   Make best effort to return all the data we can.  On memory or
+   decoding errors, just return what we've got.  Always return 0,
+   currently.  */
+
+krb5_error_code
+krb5int_make_srv_query_realm(const krb5_data *realm,
+			     const char *service,
+			     const char *protocol,
+			     struct srv_dns_entry **answers)
+{
+    const unsigned char *p = NULL, *base = NULL;
+    char host[MAXDNAME], *h;
+    int size, ret, rdlen, nlen;
+    unsigned short priority, weight, port;
+    struct krb5int_dns_state *ds = NULL;
+
+    struct srv_dns_entry *head = NULL;
+    struct srv_dns_entry *srv = NULL, *entry = NULL;
+
+    /*
+     * First off, build a query of the form:
+     *
+     * service.protocol.realm
+     *
+     * which will most likely be something like:
+     *
+     * _kerberos._udp.REALM
+     *
+     */
+
+    if (memchr(realm->data, 0, realm->length))
+	return 0;
+    if ( strlen(service) + strlen(protocol) + realm->length + 6 
+         > MAXDNAME )
+	return 0;
+    sprintf(host, "%s.%s.%.*s", service, protocol, (int) realm->length,
+	    realm->data);
+
+    /* Realm names don't (normally) end with ".", but if the query
+       doesn't end with "." and doesn't get an answer as is, the
+       resolv code will try appending the local domain.  Since the
+       realm names are absolutes, let's stop that.  
+
+       But only if a name has been specified.  If we are performing
+       a search on the prefix alone then the intention is to allow
+       the local domain or domain search lists to be expanded.  */
+
+    h = host + strlen (host);
+    if ((h[-1] != '.') && ((h - host + 1) < sizeof(host)))
+        strcpy (h, ".");
+
+#ifdef TEST
+    fprintf (stderr, "sending DNS SRV query for %s\n", host);
+#endif
+
+    size = krb5int_dns_init(&ds, host, C_IN, T_SRV);
+    if (size < 0)
+	goto out;
+
+    for (;;) {
+	ret = krb5int_dns_nextans(ds, &base, &rdlen);
+	if (ret < 0 || base == NULL)
+	    goto out;
+
+	p = base;
+
+	SAFE_GETUINT16(base, rdlen, p, 2, priority, out);
+	SAFE_GETUINT16(base, rdlen, p, 2, weight, out);
+	SAFE_GETUINT16(base, rdlen, p, 2, port, out);
+
+	/*
+	 * RFC 2782 says the target is never compressed in the reply;
+	 * do we believe that?  We need to flatten it anyway, though.
+	 */
+	nlen = krb5int_dns_expand(ds, p, host, sizeof(host));
+	if (nlen < 0 || !INCR_OK(base, rdlen, p, nlen))
+	    goto out;
+
+	/*
+	 * We got everything!  Insert it into our list, but make sure
+	 * it's in the right order.  Right now we don't do anything
+	 * with the weight field
+	 */
+
+	srv = (struct srv_dns_entry *) malloc(sizeof(struct srv_dns_entry));
+	if (srv == NULL)
+	    goto out;
+	
+	srv->priority = priority;
+	srv->weight = weight;
+	srv->port = port;
+	/* The returned names are fully qualified.  Don't let the
+	   local resolver code do domain search path stuff.  */
+	if (strlen(host) + 2 < sizeof(host))
+	    strcat(host, ".");
+	srv->host = strdup(host);
+	if (srv->host == NULL) {
+	    free(srv);
+	    goto out;
+	}
+
+	if (head == NULL || head->priority > srv->priority) {
+	    srv->next = head;
+	    head = srv;
+	} else {
+	    /*
+	     * This is confusing.  Only insert an entry into this
+	     * spot if:
+	     * The next person has a higher priority (lower priorities
+	     * are preferred).
+	     * Or
+	     * There is no next entry (we're at the end)
+	     */
+	    for (entry = head; entry != NULL; entry = entry->next) {
+		if ((entry->next &&
+		     entry->next->priority > srv->priority) ||
+		    entry->next == NULL) {
+		    srv->next = entry->next;
+		    entry->next = srv;
+		    break;
+		}
+	    }
+	}
+    }
+
+out:
+    if (ds != NULL) {
+	krb5int_dns_fini(ds);
+	ds = NULL;
+    }
+    *answers = head;
+    return 0;
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/os/free_hstrl.c b/krb5-1-6/src/lib/krb5/os/free_hstrl.c
new file mode 100644
index 000000000..4900fce9b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/free_hstrl.c
@@ -0,0 +1,42 @@
+/*
+ * lib/krb5/os/free_hstrl.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_free_host_realm()
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+
+/*
+ Frees the storage taken by a realm list returned by krb5_get_host_realm.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_free_host_realm(krb5_context context, char *const *realmlist)
+{
+    /* same format, so why duplicate code? */
+    return krb5_free_krbhst(context, realmlist);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/free_krbhs.c b/krb5-1-6/src/lib/krb5/os/free_krbhs.c
new file mode 100644
index 000000000..a10db910c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/free_krbhs.c
@@ -0,0 +1,45 @@
+/*
+ * lib/krb5/os/free_krbhs.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_free_krbhst() function
+ */
+
+#include "k5-int.h"
+
+/*
+ Frees the storage taken by a host list returned by krb5_get_krbhst.
+ */
+
+krb5_error_code
+krb5_free_krbhst(krb5_context context, char *const *hostlist)
+{
+    register char * const *cp;
+
+    for (cp = hostlist; *cp; cp++)
+	free(*cp);
+    krb5_xfree(hostlist);
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/full_ipadr.c b/krb5-1-6/src/lib/krb5/os/full_ipadr.c
new file mode 100644
index 000000000..c72daa8c9
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/full_ipadr.c
@@ -0,0 +1,86 @@
+/*
+ * lib/krb5/os/full_ipadr.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Take an IP addr & port and generate a full IP address.
+ */
+
+#include "k5-int.h"
+
+#ifdef HAVE_NETINET_IN_H
+
+#include "os-proto.h"
+
+krb5_error_code
+krb5_make_full_ipaddr(krb5_context context, krb5_int32 adr,
+		      /*krb5_int16*/int port, krb5_address **outaddr)
+{
+    unsigned long smushaddr = (unsigned long) adr; /* already in net order */
+    unsigned short smushport = (unsigned short) port; /* ditto */
+    register krb5_address *retaddr;
+    register krb5_octet *marshal;
+    krb5_addrtype temptype;
+    krb5_int32 templength;
+
+    if (!(retaddr = (krb5_address *)malloc(sizeof(*retaddr)))) {
+	return ENOMEM;
+    }
+    retaddr->magic = KV5M_ADDRESS;
+    retaddr->addrtype = ADDRTYPE_ADDRPORT;
+    retaddr->length = sizeof(smushaddr)+ sizeof(smushport) +
+	2*sizeof(temptype) + 2*sizeof(templength);
+
+    if (!(retaddr->contents = (krb5_octet *)malloc(retaddr->length))) {
+	krb5_xfree(retaddr);
+	return ENOMEM;
+    }
+    marshal = retaddr->contents;
+
+    temptype = htons(ADDRTYPE_INET);
+    (void) memcpy((char *)marshal, (char *)&temptype, sizeof(temptype));
+    marshal += sizeof(temptype);
+
+    templength = htonl(sizeof(smushaddr));
+    (void) memcpy((char *)marshal, (char *)&templength, sizeof(templength));
+    marshal += sizeof(templength);
+
+    (void) memcpy((char *)marshal, (char *)&smushaddr, sizeof(smushaddr));
+    marshal += sizeof(smushaddr);
+
+    temptype = htons(ADDRTYPE_IPPORT);
+    (void) memcpy((char *)marshal, (char *)&temptype, sizeof(temptype));
+    marshal += sizeof(temptype);
+
+    templength = htonl(sizeof(smushport));
+    (void) memcpy((char *)marshal, (char *)&templength, sizeof(templength));
+    marshal += sizeof(templength);
+
+    (void) memcpy((char *)marshal, (char *)&smushport, sizeof(smushport));
+    marshal += sizeof(smushport);
+
+    *outaddr = retaddr;
+    return 0;
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/os/gen_port.c b/krb5-1-6/src/lib/krb5/os/gen_port.c
new file mode 100644
index 000000000..4832cec19
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/gen_port.c
@@ -0,0 +1,49 @@
+/*
+ * lib/krb5/os/gen_port.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Take an IP addr & port and generate a full IP address.
+ */
+
+#include "k5-int.h"
+#include "os-proto.h"
+
+krb5_error_code
+krb5_gen_portaddr(krb5_context context, const krb5_address *addr, krb5_const_pointer ptr, krb5_address **outaddr)
+{
+#ifdef HAVE_NETINET_IN_H
+    krb5_int32 adr;
+    krb5_int16 port;
+
+    if (addr->addrtype != ADDRTYPE_INET)
+	return KRB5_PROG_ATYPE_NOSUPP;
+    port = *(const krb5_int16 *)ptr;
+    
+    memcpy((char *)&adr, (char *)addr->contents, sizeof(adr));
+    return krb5_make_full_ipaddr(context, adr, port, outaddr);
+#else
+    return KRB5_PROG_ATYPE_NOSUPP;
+#endif
+}
diff --git a/krb5-1-6/src/lib/krb5/os/gen_rname.c b/krb5-1-6/src/lib/krb5/os/gen_rname.c
new file mode 100644
index 000000000..7978a5dbc
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/gen_rname.c
@@ -0,0 +1,50 @@
+/*
+ * lib/krb5/os/gen_rname.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * take a port-style address and unique string, and return
+ * a replay cache tag string.
+ */
+
+#include "k5-int.h"
+#include "os-proto.h"
+
+krb5_error_code
+krb5_gen_replay_name(krb5_context context, const krb5_address *address, const char *uniq, char **string)
+{
+    char * tmp;
+    int i;
+
+    if ((*string = malloc(strlen(uniq) + (address->length * 2) + 1)) == NULL)
+	return ENOMEM;
+
+    sprintf(*string, "%s", uniq);
+    tmp = (*string) + strlen(uniq);
+    for (i = 0; i < address->length; i++) {
+	sprintf(tmp, "%.2x", address->contents[i] & 0xff);
+	tmp += 2;
+    }
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/genaddrs.c b/krb5-1-6/src/lib/krb5/os/genaddrs.c
new file mode 100644
index 000000000..f3e86a504
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/genaddrs.c
@@ -0,0 +1,130 @@
+/*
+ * lib/krb5/os/genaddrs.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Take an IP addr & port and generate a full IP address.
+ */
+
+#include "k5-int.h"
+#include "os-proto.h"
+
+#if !defined(_WINSOCKAPI_)
+#include <netinet/in.h>
+#endif
+
+struct addrpair {
+    krb5_address addr, port;
+};
+
+#define SET(TARG, THING, TYPE) \
+	((TARG).contents = (krb5_octet *) &(THING),	\
+	 (TARG).length = sizeof (THING),		\
+	 (TARG).addrtype = (TYPE))
+
+static void *cvtaddr (struct sockaddr_storage *a, struct addrpair *ap)
+{
+    switch (ss2sa(a)->sa_family) {
+    case AF_INET:
+	SET (ap->port, ss2sin(a)->sin_port, ADDRTYPE_IPPORT);
+	SET (ap->addr, ss2sin(a)->sin_addr, ADDRTYPE_INET);
+	return a;
+#ifdef KRB5_USE_INET6
+    case AF_INET6:
+	SET (ap->port, ss2sin6(a)->sin6_port, ADDRTYPE_IPPORT);
+	if (IN6_IS_ADDR_V4MAPPED (&ss2sin6(a)->sin6_addr)) {
+	    ap->addr.addrtype = ADDRTYPE_INET;
+	    ap->addr.contents = 12 + (krb5_octet *) &ss2sin6(a)->sin6_addr;
+	    ap->addr.length = 4;
+	} else
+	    SET (ap->addr, ss2sin6(a)->sin6_addr, ADDRTYPE_INET6);
+	return a;
+#endif
+    default:
+	return 0;
+    }
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, int infd, int flags)
+{
+    krb5_error_code 	  retval;
+    krb5_address	* laddr;
+    krb5_address	* lport;
+    krb5_address	* raddr;
+    krb5_address	* rport;
+    SOCKET		fd = (SOCKET) infd;
+    struct addrpair laddrs, raddrs;
+
+#ifdef HAVE_NETINET_IN_H
+    struct sockaddr_storage lsaddr, rsaddr;
+    GETSOCKNAME_ARG3_TYPE ssize;
+
+    ssize = sizeof(struct sockaddr_storage);
+    if ((flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) ||
+	(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR)) {
+    	if ((retval = getsockname(fd, (GETSOCKNAME_ARG2_TYPE *) &lsaddr, 
+				  &ssize)))
+	    return retval;
+
+	if (cvtaddr (&lsaddr, &laddrs)) {
+	    laddr = &laddrs.addr;
+	    if (flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)
+		lport = &laddrs.port;
+	    else
+		lport = 0;
+	} else
+	    return KRB5_PROG_ATYPE_NOSUPP;
+    } else {
+	laddr = NULL;
+	lport = NULL;
+    }
+
+    ssize = sizeof(struct sockaddr_storage);
+    if ((flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) ||
+	(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR)) {
+        if ((retval = getpeername(fd, (GETPEERNAME_ARG2_TYPE *) &rsaddr, 
+				  &ssize)))
+	    return errno;
+
+	if (cvtaddr (&rsaddr, &raddrs)) {
+	    raddr = &raddrs.addr;
+	    if (flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)
+		rport = &raddrs.port;
+	    else
+		rport = 0;
+	} else
+	    return KRB5_PROG_ATYPE_NOSUPP;
+    } else {
+	raddr = NULL;
+	rport = NULL;
+    }
+
+    if (!(retval = krb5_auth_con_setaddrs(context, auth_context, laddr, raddr)))
+    	return (krb5_auth_con_setports(context, auth_context, lport, rport));
+    return retval;
+#else
+    return KRB5_PROG_ATYPE_NOSUPP;
+#endif
+}
diff --git a/krb5-1-6/src/lib/krb5/os/get_krbhst.c b/krb5-1-6/src/lib/krb5/os/get_krbhst.c
new file mode 100644
index 000000000..31c77af6f
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/get_krbhst.c
@@ -0,0 +1,128 @@
+/*
+ * lib/krb5/os/get_krbhst.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_get_krbhst() function.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include <ctype.h>
+
+/*
+ Figures out the Kerberos server names for the given realm, filling in a
+ pointer to an argv[] style list of names, terminated with a null pointer.
+ 
+ If the realm is unknown, the filled-in pointer is set to NULL.
+
+ The pointer array and strings pointed to are all in allocated storage,
+ and should be freed by the caller when finished.
+
+ returns system errors
+*/
+
+/*
+ * Implementation:  the server names for given realms are stored in a
+ * configuration file, 
+ * named by krb5_config_file;  the first token (on the first line) in
+ * this file is taken as the default local realm name.
+ * 
+ * Each succeeding line has a realm name as the first token, and a server name
+ * as a second token.  Additional tokens may be present on the line, but
+ * are ignored by this function.
+ *
+ * All lines which begin with the desired realm name will have the
+ * hostname added to the list returned.
+ */
+
+krb5_error_code
+krb5_get_krbhst(krb5_context context, const krb5_data *realm, char ***hostlist)
+{
+    char	**values, **cpp, *cp;
+    const char	*realm_kdc_names[4];
+    krb5_error_code	retval;
+    int	i, count;
+    char **rethosts;
+
+    rethosts = 0;
+
+    realm_kdc_names[0] = "realms";
+    realm_kdc_names[1] = realm->data;
+    realm_kdc_names[2] = "kdc";
+    realm_kdc_names[3] = 0;
+
+    if (context->profile == 0)
+	return KRB5_CONFIG_CANTOPEN;
+
+    retval = profile_get_values(context->profile, realm_kdc_names, &values);
+    if (retval == PROF_NO_SECTION)
+	return KRB5_REALM_UNKNOWN;
+    if (retval == PROF_NO_RELATION)
+	return KRB5_CONFIG_BADFORMAT;
+    if (retval)
+	return retval;
+
+    /*
+     * Do cleanup over the list.  We allow for some extra field to be
+     * added to the kdc line later (maybe the port number)
+     */
+    for (cpp = values; *cpp; cpp++) {
+	cp = strchr(*cpp, ' ');
+	if (cp)
+	    *cp = 0;
+	cp = strchr(*cpp, '\t');
+	if (cp)
+	    *cp = 0;
+	cp = strchr(*cpp, ':');
+	if (cp)
+	    *cp = 0;
+    }
+    count = cpp - values;
+    rethosts = malloc(sizeof(char *) * (count + 1));
+    if (!rethosts) {
+        retval = ENOMEM;
+        goto cleanup;
+    }
+    for (i = 0; i < count; i++) {
+	unsigned int len = strlen (values[i]) + 1;
+        rethosts[i] = malloc(len);
+        if (!rethosts[i]) {
+            retval = ENOMEM;
+            goto cleanup;
+        }
+	memcpy (rethosts[i], values[i], len);
+    }
+    rethosts[count] = 0;
+ cleanup:
+    if (retval && rethosts) {
+        for (cpp = rethosts; *cpp; cpp++)
+            free(*cpp);
+        free(rethosts);
+	rethosts = 0;
+    }
+    profile_free_list(values);
+    *hostlist = rethosts;
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/hostaddr.c b/krb5-1-6/src/lib/krb5/os/hostaddr.c
new file mode 100644
index 000000000..76eb1273d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/hostaddr.c
@@ -0,0 +1,137 @@
+/*
+ * lib/krb5/os/hostaddr.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * This routine returns a list of krb5 addresses given a hostname.
+ *
+ */
+
+#include "k5-int.h"
+
+#include "fake-addrinfo.h"
+
+krb5_error_code
+krb5_os_hostaddr(krb5_context context, const char *name, krb5_address ***ret_addrs)
+{
+    krb5_error_code 	retval;
+    krb5_address 	**addrs;
+    int			i, j, r;
+    struct addrinfo hints, *ai, *aip;
+
+    if (!name)
+	return KRB5_ERR_BAD_HOSTNAME;
+
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_flags = AI_NUMERICHOST;
+    /* We don't care what kind at this point, really, but without
+       this, we can get back multiple sockaddrs per address, for
+       SOCK_DGRAM, SOCK_STREAM, and SOCK_RAW.  I haven't checked if
+       that's what the spec indicates.  */
+    hints.ai_socktype = SOCK_DGRAM;
+
+    r = getaddrinfo (name, 0, &hints, &ai);
+    if (r && AI_NUMERICHOST != 0) {
+	hints.ai_flags &= ~AI_NUMERICHOST;
+	r = getaddrinfo (name, 0, &hints, &ai);
+    }
+    if (r)
+	return KRB5_ERR_BAD_HOSTNAME;
+
+    for (i = 0, aip = ai; aip; aip = aip->ai_next) {
+	switch (aip->ai_addr->sa_family) {
+	case AF_INET:
+#ifdef KRB5_USE_INET6
+	case AF_INET6:
+#endif
+	    i++;
+	default:
+	    /* Ignore addresses of unknown families.  */
+	    ;
+	}
+    }
+
+    addrs = malloc ((i+1) * sizeof(*addrs));
+    if (!addrs)
+	return errno;
+
+    for (j = 0; j < i + 1; j++)
+	addrs[j] = 0;
+
+    for (i = 0, aip = ai; aip; aip = aip->ai_next) {
+	void *ptr;
+	size_t addrlen;
+	int atype;
+
+	switch (aip->ai_addr->sa_family) {
+	case AF_INET:
+	    addrlen = sizeof (struct in_addr);
+	    ptr = &((struct sockaddr_in *)aip->ai_addr)->sin_addr;
+	    atype = ADDRTYPE_INET;
+	    break;
+#ifdef KRB5_USE_INET6
+	case AF_INET6:
+	    addrlen = sizeof (struct in6_addr);
+	    ptr = &((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr;
+	    atype = ADDRTYPE_INET6;
+	    break;
+#endif
+	default:
+	    continue;
+	}
+	addrs[i] = (krb5_address *) malloc(sizeof(krb5_address));
+	if (!addrs[i]) {
+	    retval = ENOMEM;
+	    goto errout;
+	}
+	addrs[i]->magic = KV5M_ADDRESS;
+	addrs[i]->addrtype = atype;
+	addrs[i]->length = addrlen;
+	addrs[i]->contents = malloc(addrs[i]->length);
+	if (!addrs[i]->contents) {
+	    retval = ENOMEM;
+	    goto errout;
+	}
+	memcpy (addrs[i]->contents, ptr, addrs[i]->length);
+	i++;
+    }
+
+    *ret_addrs = addrs;
+    if (ai)
+	freeaddrinfo(ai);
+    return 0;
+
+errout:
+    if (addrs) {
+	for (i = 0; addrs[i]; i++) {
+	    free (addrs[i]->contents);
+	    free (addrs[i]);
+	}
+	krb5_free_addresses(context, addrs);
+    }
+    if (ai)
+	freeaddrinfo(ai);
+    return retval;
+	
+}
+
diff --git a/krb5-1-6/src/lib/krb5/os/hst_realm.c b/krb5-1-6/src/lib/krb5/os/hst_realm.c
new file mode 100644
index 000000000..7e24b8d6d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/hst_realm.c
@@ -0,0 +1,493 @@
+/*
+ * lib/krb5/os/hst_realm.c
+ *
+ * Copyright 1990,1991,2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_get_host_realm()
+ */
+
+
+/*
+ Figures out the Kerberos realm names for host, filling in a
+ pointer to an argv[] style list of names, terminated with a null pointer.
+ 
+ If host is NULL, the local host's realms are determined.
+
+ If there are no known realms for the host, the filled-in pointer is set
+ to NULL.
+
+ The pointer array and strings pointed to are all in allocated storage,
+ and should be freed by the caller when finished.
+
+ returns system errors
+*/
+
+/*
+ * Implementation notes:
+ *
+ * this implementation only provides one realm per host, using the same
+ * mapping file used in kerberos v4.
+
+ * Given a fully-qualified domain-style primary host name,
+ * return the name of the Kerberos realm for the host.
+ * If the hostname contains no discernable domain, or an error occurs,
+ * return the local realm name, as supplied by krb5_get_default_realm().
+ * If the hostname contains a domain, but no translation is found,
+ * the hostname's domain is converted to upper-case and returned.
+ *
+ * The format of each line of the translation file is:
+ * domain_name kerberos_realm
+ * -or-
+ * host_name kerberos_realm
+ *
+ * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
+ * host names should be in the usual form (e.g. FOO.BAR.BAZ)
+ */
+
+
+#include "k5-int.h"
+#include "os-proto.h"
+#include <ctype.h>
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include "fake-addrinfo.h"
+
+#ifdef KRB5_DNS_LOOKUP
+
+#include "dnsglue.h"
+/*
+ * Try to look up a TXT record pointing to a Kerberos realm
+ */
+
+krb5_error_code
+krb5_try_realm_txt_rr(const char *prefix, const char *name, char **realm)
+{
+    krb5_error_code retval = KRB5_ERR_HOST_REALM_UNKNOWN;
+    const unsigned char *p, *base;
+    char host[MAXDNAME], *h;
+    int ret, rdlen, len;
+    struct krb5int_dns_state *ds = NULL;
+
+    /*
+     * Form our query, and send it via DNS
+     */
+
+    if (name == NULL || name[0] == '\0') {
+	if (strlen (prefix) >= sizeof(host)-1)
+	    return KRB5_ERR_HOST_REALM_UNKNOWN;
+        strcpy(host,prefix);
+    } else {
+        if ( strlen(prefix) + strlen(name) + 3 > MAXDNAME )
+            return KRB5_ERR_HOST_REALM_UNKNOWN;
+        sprintf(host,"%s.%s", prefix, name);
+
+        /* Realm names don't (normally) end with ".", but if the query
+           doesn't end with "." and doesn't get an answer as is, the
+           resolv code will try appending the local domain.  Since the
+           realm names are absolutes, let's stop that.  
+
+           But only if a name has been specified.  If we are performing
+           a search on the prefix alone then the intention is to allow
+           the local domain or domain search lists to be expanded.
+        */
+
+        h = host + strlen (host);
+        if ((h > host) && (h[-1] != '.') && ((h - host + 1) < sizeof(host)))
+            strcpy (h, ".");
+    }
+    ret = krb5int_dns_init(&ds, host, C_IN, T_TXT);
+    if (ret < 0)
+	goto errout;
+
+    ret = krb5int_dns_nextans(ds, &base, &rdlen);
+    if (ret < 0 || base == NULL)
+	goto errout;
+
+    p = base;
+    if (!INCR_OK(base, rdlen, p, 1))
+	goto errout;
+    len = *p++;
+    *realm = malloc((size_t)len + 1);
+    if (*realm == NULL) {
+	retval = ENOMEM;
+	goto errout;
+    }
+    strncpy(*realm, (const char *)p, (size_t)len);
+    (*realm)[len] = '\0';
+    /* Avoid a common error. */
+    if ( (*realm)[len-1] == '.' )
+	(*realm)[len-1] = '\0';
+    retval = 0;
+
+errout:
+    if (ds != NULL) {
+	krb5int_dns_fini(ds);
+	ds = NULL;
+    }
+    return retval;
+}
+#else /* KRB5_DNS_LOOKUP */
+#ifndef MAXDNAME
+#define MAXDNAME (16 * MAXHOSTNAMELEN)
+#endif /* MAXDNAME */
+#endif /* KRB5_DNS_LOOKUP */
+
+krb5_error_code krb5int_translate_gai_error (int);
+
+static krb5_error_code
+krb5int_get_fq_hostname (char *buf, size_t bufsize, const char *name)
+{
+    struct addrinfo *ai, hints;
+    int err;
+
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_flags = AI_CANONNAME;
+    err = getaddrinfo (name, 0, &hints, &ai);
+    if (err)
+	return krb5int_translate_gai_error (err);
+    if (ai->ai_canonname == 0)
+	return KRB5_EAI_FAIL;
+    strncpy (buf, ai->ai_canonname, bufsize);
+    buf[bufsize-1] = 0;
+    freeaddrinfo (ai);
+    return 0;
+}
+
+/* Get the local host name, try to make it fully-qualified.
+   Always return a null-terminated string.
+   Might return an error if gethostname fails.  */
+krb5_error_code
+krb5int_get_fq_local_hostname (char *buf, size_t bufsiz)
+{
+    buf[0] = 0;
+    if (gethostname (buf, bufsiz) == -1)
+	return SOCKET_ERRNO;
+    buf[bufsiz - 1] = 0;
+    return krb5int_get_fq_hostname (buf, bufsiz, buf);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_host_realm(krb5_context context, const char *host, char ***realmsp)
+{
+    char **retrealms;
+    char *realm, *cp, *temp_realm;
+    krb5_error_code retval;
+    char local_host[MAXDNAME+1];
+
+#ifdef DEBUG_REFERRALS
+    printf("get_host_realm(host:%s) called\n",host);
+#endif
+
+    krb5int_clean_hostname(context, host, local_host, sizeof local_host);
+
+    /*
+       Search for the best match for the host or domain.
+       Example: Given a host a.b.c.d, try to match on:
+         1) A.B.C.D
+	 2) .B.C.D
+	 3) B.C.D
+	 4) .C.D
+	 5) C.D
+	 6) .D
+	 7) D
+     */
+
+    cp = local_host;
+#ifdef DEBUG_REFERRALS
+    printf("  local_host: %s\n",local_host);
+#endif
+    realm = (char *)NULL;
+    temp_realm = 0;
+    while (cp) {
+#ifdef DEBUG_REFERRALS
+        printf("  trying to look up %s in the domain_realm map\n",cp);
+#endif
+	retval = profile_get_string(context->profile, "domain_realm", cp,
+				    0, (char *)NULL, &temp_realm);
+	if (retval)
+	    return retval;
+	if (temp_realm != (char *)NULL)
+	    break;	/* Match found */
+
+	/* Setup for another test */
+	if (*cp == '.') {
+	    cp++;
+	} else {
+	    cp = strchr(cp, '.');
+	}
+    }
+#ifdef DEBUG_REFERRALS
+    printf("  done searching the domain_realm map\n");
+#endif
+    if (temp_realm) {
+#ifdef DEBUG_REFERRALS
+    printf("  temp_realm is %s\n",temp_realm);
+#endif
+        realm = malloc(strlen(temp_realm) + 1);
+        if (!realm) {
+            profile_release_string(temp_realm);
+            return ENOMEM;
+        }
+        strcpy(realm, temp_realm);
+        profile_release_string(temp_realm);
+    }
+
+    if (realm == (char *)NULL) {
+        if (!(cp = (char *)malloc(strlen(KRB5_REFERRAL_REALM)+1)))
+	    return ENOMEM;
+	strcpy(cp, KRB5_REFERRAL_REALM);
+	realm = cp;
+    }
+    
+    if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) {
+	if (realm != (char *)NULL)
+	    free(realm);
+	return ENOMEM;
+    }
+
+    retrealms[0] = realm;
+    retrealms[1] = 0;
+    
+    *realmsp = retrealms;
+    return 0;
+}
+
+#if defined(_WIN32) && !defined(__CYGWIN32__)
+# ifndef EAFNOSUPPORT
+#  define EAFNOSUPPORT WSAEAFNOSUPPORT
+# endif
+#endif
+
+krb5_error_code
+krb5int_translate_gai_error (int num)
+{
+    switch (num) {
+#ifdef EAI_ADDRFAMILY
+    case EAI_ADDRFAMILY:
+	return EAFNOSUPPORT;
+#endif
+    case EAI_AGAIN:
+	return EAGAIN;
+    case EAI_BADFLAGS:
+	return EINVAL;
+    case EAI_FAIL:
+	return KRB5_EAI_FAIL;
+    case EAI_FAMILY:
+	return EAFNOSUPPORT;
+    case EAI_MEMORY:
+	return ENOMEM;
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+    case EAI_NODATA:
+	return KRB5_EAI_NODATA;
+#endif
+    case EAI_NONAME:
+	return KRB5_EAI_NONAME;
+#if defined(EAI_OVERFLOW)
+    case EAI_OVERFLOW:
+	return EINVAL;		/* XXX */
+#endif
+    case EAI_SERVICE:
+	return KRB5_EAI_SERVICE;
+    case EAI_SOCKTYPE:
+	return EINVAL;
+#ifdef EAI_SYSTEM
+    case EAI_SYSTEM:
+	return errno;
+#endif
+    }
+    abort ();
+    return -1;
+}
+
+
+/*
+ * Ganked from krb5_get_host_realm; handles determining a fallback realm
+ * to try in the case where referrals have failed and it's time to go
+ * look at TXT records or make a DNS-based assumption.
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata, char ***realmsp)
+{
+    char **retrealms;
+    char *default_realm, *realm, *cp, *temp_realm;
+    krb5_error_code retval;
+    char local_host[MAXDNAME+1], host[MAXDNAME+1];
+
+    /* Convert what we hope is a hostname to a string. */
+    memcpy(host, hdata->data, hdata->length);
+    host[hdata->length]=0;
+
+#ifdef DEBUG_REFERRALS
+    printf("get_fallback_host_realm(host >%s<) called\n",host);
+#endif
+
+    krb5int_clean_hostname(context, host, local_host, sizeof local_host);
+
+    /* Scan hostname for DNS realm, and save as last-ditch realm
+       assumption. */
+    cp = local_host;
+#ifdef DEBUG_REFERRALS
+    printf("  local_host: %s\n",local_host);
+#endif
+    realm = default_realm = (char *)NULL;
+    temp_realm = 0;
+    while (cp && !default_realm) {
+	if (*cp == '.') {
+	    cp++;
+	    if (default_realm == (char *)NULL) {
+		/* If nothing else works, use the host's domain */
+		default_realm = cp;
+	    }
+	} else {
+	    cp = strchr(cp, '.');
+	}
+    }
+#ifdef DEBUG_REFERRALS
+    printf("  done finding DNS-based default realm: >%s<\n",default_realm);
+#endif
+
+#ifdef KRB5_DNS_LOOKUP
+    if (realm == (char *)NULL) {
+        int use_dns = _krb5_use_dns_realm(context);
+        if ( use_dns ) {
+            /*
+             * Since this didn't appear in our config file, try looking
+             * it up via DNS.  Look for a TXT records of the form:
+             *
+             * _kerberos.<hostname>
+             *
+             */
+            cp = local_host;
+            do {
+                retval = krb5_try_realm_txt_rr("_kerberos", cp, &realm);
+                cp = strchr(cp,'.');
+                if (cp) 
+                    cp++;
+            } while (retval && cp && cp[0]);
+        }
+    }
+#endif /* KRB5_DNS_LOOKUP */
+
+      
+    if (realm == (char *)NULL) {
+        if (default_realm != (char *)NULL) {
+            /* We are defaulting to the realm of the host */
+            if (!(cp = (char *)malloc(strlen(default_realm)+1)))
+                return ENOMEM;
+            strcpy(cp, default_realm);
+            realm = cp;
+
+            /* Assume the realm name is upper case */
+            for (cp = realm; *cp; cp++)
+                if (islower((int) (*cp)))
+                    *cp = toupper((int) *cp);
+        } else {    
+            /* We are defaulting to the local realm */
+            retval = krb5_get_default_realm(context, &realm);
+            if (retval) {
+                return retval;
+            }
+        }
+    }
+    if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) {
+	if (realm != (char *)NULL)
+	    free(realm);
+	return ENOMEM;
+    }
+
+    retrealms[0] = realm;
+    retrealms[1] = 0;
+    
+    *realmsp = retrealms;
+    return 0;
+}
+
+/*
+ * Common code for krb5_get_host_realm and krb5_get_fallback_host_realm
+ * to do basic sanity checks on supplied hostname.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5int_clean_hostname(krb5_context context, const char *host, char *local_host, size_t lhsize)
+{
+    char *cp;
+    krb5_error_code retval;
+    int l;
+
+    local_host[0]=0;
+#ifdef DEBUG_REFERRALS
+    printf("krb5int_clean_hostname called: host<%s>, local_host<%s>, size %d\n",host,local_host,lhsize);
+#endif
+    if (host) {
+	/* Filter out numeric addresses if the caller utterly failed to
+	   convert them to names.  */
+	/* IPv4 - dotted quads only */
+	if (strspn(host, "01234567890.") == strlen(host)) {
+	    /* All numbers and dots... if it's three dots, it's an
+	       IP address, and we reject it.  But "12345" could be
+	       a local hostname, couldn't it?  We'll just assume
+	       that a name with three dots is not meant to be an
+	       all-numeric hostname three all-numeric domains down
+	       from the current domain.  */
+	    int ndots = 0;
+	    const char *p;
+	    for (p = host; *p; p++)
+		if (*p == '.')
+		    ndots++;
+	    if (ndots == 3)
+		return KRB5_ERR_NUMERIC_REALM;
+	}
+	if (strchr(host, ':'))
+	    /* IPv6 numeric address form?  Bye bye.  */
+	    return KRB5_ERR_NUMERIC_REALM;
+
+	/* Should probably error out if strlen(host) > MAXDNAME.  */
+	strncpy(local_host, host, lhsize);
+	local_host[lhsize - 1] = '\0';
+    } else {
+        retval = krb5int_get_fq_local_hostname (local_host, lhsize);
+	if (retval)
+	    return retval;
+    }
+
+    /* fold to lowercase */
+    for (cp = local_host; *cp; cp++) {
+	if (isupper((unsigned char) (*cp)))
+	    *cp = tolower((unsigned char) *cp);
+    }
+    l = strlen(local_host);
+    /* strip off trailing dot */
+    if (l && local_host[l-1] == '.')
+	    local_host[l-1] = 0;
+
+#ifdef DEBUG_REFERRALS
+    printf("krb5int_clean_hostname ending: host<%s>, local_host<%s>, size %d\n",host,local_host,lhsize);
+#endif
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/init_os_ctx.c b/krb5-1-6/src/lib/krb5/os/init_os_ctx.c
new file mode 100644
index 000000000..88b5ed044
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/init_os_ctx.c
@@ -0,0 +1,507 @@
+/*
+ * lib/krb5/os/init_ctx.c
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * krb5_init_contex()
+ */
+
+#define NEED_WINDOWS
+
+#include "k5-int.h"
+#include "os-proto.h"
+#include "prof_int.h"		/* XXX for profile_copy, not public yet */
+
+#ifdef USE_LOGIN_LIBRARY
+#include "KerberosLoginPrivate.h"
+#endif
+
+#if defined(_WIN32)
+#include <winsock.h>
+
+static krb5_error_code
+get_from_windows_dir(
+    char **pname
+    )
+{
+    UINT size = GetWindowsDirectory(0, 0);
+    *pname = malloc(size + 1 +
+                    strlen(DEFAULT_PROFILE_FILENAME) + 1);
+    if (*pname)
+    {
+        GetWindowsDirectory(*pname, size);
+        strcat(*pname, "\\");
+        strcat(*pname, DEFAULT_PROFILE_FILENAME);
+        return 0;
+    } else {
+        return KRB5_CONFIG_CANTOPEN;
+    }
+}
+
+static krb5_error_code
+get_from_module_dir(
+    char **pname
+    )
+{
+    const DWORD size = 1024; /* fixed buffer */
+    int found = 0;
+    char *p;
+    char *name;
+    struct _stat s;
+
+    *pname = 0;
+
+    name = malloc(size);
+    if (!name)
+        return ENOMEM;
+
+    if (!GetModuleFileName(GetModuleHandle("krb5_32"), name, size))
+        goto cleanup;
+
+    p = name + strlen(name);
+    while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
+    if (p < name)
+        goto cleanup;
+    p++;
+    strncpy(p, DEFAULT_PROFILE_FILENAME, size - (p - name));
+    name[size - 1] = 0;
+    found = !_stat(name, &s);
+
+ cleanup:
+    if (found)
+        *pname = name;
+    else
+        if (name) free(name);
+    return 0;
+}
+
+/*
+ * get_from_registry
+ *
+ * This will find a profile in the registry.  *pbuffer != 0 if we
+ * found something.  Make sure to free(*pbuffer) when done.  It will
+ * return an error code if there is an error the user should know
+ * about.  We maintain the invariant: return value != 0 => 
+ * *pbuffer == 0.
+ */
+static krb5_error_code
+get_from_registry(
+    char** pbuffer,
+    HKEY hBaseKey
+    )
+{
+    HKEY hKey = 0;
+    LONG rc = 0;
+    DWORD size = 0;
+    krb5_error_code retval = 0;
+    const char *key_path = "Software\\MIT\\Kerberos5";
+    const char *value_name = "config";
+
+    /* a wannabe assertion */
+    if (!pbuffer)
+    {
+        /*
+         * We have a programming error!  For now, we segfault :)
+         * There is no good mechanism to deal.
+         */
+    }
+    *pbuffer = 0;
+
+    if ((rc = RegOpenKeyEx(hBaseKey, key_path, 0, KEY_QUERY_VALUE, 
+                           &hKey)) != ERROR_SUCCESS)
+    {
+        /* not a real error */
+        goto cleanup;
+    }
+    rc = RegQueryValueEx(hKey, value_name, 0, 0, 0, &size);
+    if ((rc != ERROR_SUCCESS) &&  (rc != ERROR_MORE_DATA))
+    {
+        /* not a real error */
+        goto cleanup;
+    }
+    *pbuffer = malloc(size);
+    if (!*pbuffer)
+    {
+        retval = ENOMEM;
+        goto cleanup;
+    }
+    if ((rc = RegQueryValueEx(hKey, value_name, 0, 0, *pbuffer, &size)) != 
+        ERROR_SUCCESS)
+    {
+        /*
+         * Let's not call it a real error in case it disappears, but
+         * we need to free so that we say we did not find anything.
+         */
+        free(*pbuffer);
+        *pbuffer = 0;
+        goto cleanup;
+    }
+ cleanup:
+    if (hKey)
+        RegCloseKey(hKey);
+    if (retval && *pbuffer)
+    {
+        free(*pbuffer);
+        /* Let's say we did not find anything: */
+        *pbuffer = 0;
+    }
+    return retval;
+}
+
+#endif /* _WIN32 */
+
+static void
+free_filespecs(profile_filespec_t *files)
+{
+    char **cp;
+
+    if (files == 0)
+        return;
+    
+    for (cp = files; *cp; cp++)
+	free(*cp);
+    free(files);
+}
+
+/* This function is needed by KfM's KerberosPreferences API 
+ * because it needs to be able to specify "secure" */
+krb5_error_code
+os_get_default_config_files(profile_filespec_t **pfiles, krb5_boolean secure)
+{
+    profile_filespec_t* files;
+#if defined(_WIN32)
+    krb5_error_code retval = 0;
+    char *name = 0;
+
+    if (!secure)
+    {
+        char *env = getenv("KRB5_CONFIG");
+        if (env)
+        {
+            name = malloc(strlen(env) + 1);
+            if (!name) return ENOMEM;
+            strcpy(name, env);
+        }
+    }
+    if (!name && !secure)
+    {
+        /* HKCU */
+        retval = get_from_registry(&name, HKEY_CURRENT_USER);
+        if (retval) return retval;
+    }
+    if (!name)
+    {
+        /* HKLM */
+        retval = get_from_registry(&name, HKEY_LOCAL_MACHINE);
+        if (retval) return retval;
+    }
+    if (!name && !secure)
+    {
+        /* module dir */
+        retval = get_from_module_dir(&name);
+        if (retval) return retval;
+    }
+    if (!name)
+    {
+        /* windows dir */
+        retval = get_from_windows_dir(&name);
+    }
+    if (retval)
+        return retval;
+    if (!name)
+        return KRB5_CONFIG_CANTOPEN; /* should never happen */
+    
+    files = malloc(2 * sizeof(char *));
+    files[0] = name;
+    files[1] = 0;
+#else /* !_WIN32 */
+    char* filepath = 0;
+    int n_entries, i;
+    unsigned int ent_len;
+    const char *s, *t;
+
+#ifdef USE_LOGIN_LIBRARY
+    /* If __KLAllowHomeDirectoryAccess() == FALSE, we are probably
+        trying to authenticate to a fileserver for the user's homedir. */
+    if (!__KLAllowHomeDirectoryAccess ())
+	secure = 1;
+#endif
+    if (secure) {
+	filepath = DEFAULT_SECURE_PROFILE_PATH;
+    } else { 
+        filepath = getenv("KRB5_CONFIG");
+        if (!filepath) filepath = DEFAULT_PROFILE_PATH;
+    }
+
+    /* count the distinct filename components */
+    for(s = filepath, n_entries = 1; *s; s++) {
+        if (*s == ':')
+            n_entries++;
+    }
+
+    /* the array is NULL terminated */
+    files = (char**) malloc((n_entries+1) * sizeof(char*));
+    if (files == 0)
+        return ENOMEM;
+
+    /* measure, copy, and skip each one */
+    for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++)
+    {
+        ent_len = t-s;
+        files[i] = (char*) malloc(ent_len + 1);
+        if (files[i] == 0) {
+            /* if malloc fails, free the ones that worked */
+            while(--i >= 0) free(files[i]);
+            free(files);
+            return ENOMEM;
+        }
+        strncpy(files[i], s, ent_len);
+        files[i][ent_len] = 0;
+        if (*t == 0) {
+            i++;
+            break;
+        }
+    }
+    /* cap the array */
+    files[i] = 0;
+#endif /* !_WIN32 */
+    *pfiles = (profile_filespec_t *)files;
+    return 0;
+}
+
+static krb5_error_code
+add_kdc_config_file(profile_filespec_t **pfiles)
+{
+    char *file;
+    size_t count;
+    profile_filespec_t *newfiles;
+
+    file = getenv(KDC_PROFILE_ENV);
+    if (file == NULL)
+	file = DEFAULT_KDC_PROFILE;
+
+    for (count = 0; (*pfiles)[count]; count++)
+	;
+    count += 2;
+    newfiles = malloc(count * sizeof(*newfiles));
+    if (newfiles == NULL)
+	return errno;
+    memcpy(newfiles + 1, *pfiles, (count-1) * sizeof(*newfiles));
+    newfiles[0] = strdup(file);
+    if (newfiles[0] == NULL) {
+	int e = errno;
+	free(newfiles);
+	return e;
+    }
+    free(*pfiles);
+    *pfiles = newfiles;
+    return 0;
+}
+
+
+/* Set the profile paths in the context.  If secure is set to TRUE
+   then do not include user paths (from environment variables, etc).
+   If kdc is TRUE, include kdc.conf from whereever we expect to find
+   it.  */
+static krb5_error_code
+os_init_paths(krb5_context ctx, krb5_boolean kdc)
+{
+    krb5_error_code	retval = 0;
+    profile_filespec_t *files = 0;
+    krb5_boolean secure = ctx->profile_secure;
+
+#ifdef KRB5_DNS_LOOKUP
+    ctx->profile_in_memory = 0;
+#endif /* KRB5_DNS_LOOKUP */
+
+    retval = os_get_default_config_files(&files, secure);
+
+    if (retval == 0 && kdc)
+	retval = add_kdc_config_file(&files);
+
+    if (!retval) {
+        retval = profile_init((const_profile_filespec_t *) files,
+			      &ctx->profile);
+
+#ifdef KRB5_DNS_LOOKUP
+        /* if none of the filenames can be opened use an empty profile */
+        if (retval == ENOENT) {
+            retval = profile_init(NULL, &ctx->profile);
+            if (!retval)
+                ctx->profile_in_memory = 1;
+        }   
+#endif /* KRB5_DNS_LOOKUP */
+    }
+
+    if (files)
+        free_filespecs(files);
+
+    if (retval)
+        ctx->profile = 0;
+
+    if (retval == ENOENT)
+        return KRB5_CONFIG_CANTOPEN;
+
+    if ((retval == PROF_SECTION_NOTOP) ||
+        (retval == PROF_SECTION_SYNTAX) ||
+        (retval == PROF_RELATION_SYNTAX) ||
+        (retval == PROF_EXTRA_CBRACE) ||
+        (retval == PROF_MISSING_OBRACE))
+        return KRB5_CONFIG_BADFORMAT;
+
+    return retval;
+}
+
+krb5_error_code
+krb5_os_init_context(krb5_context ctx, krb5_boolean kdc)
+{
+	krb5_os_context os_ctx;
+	krb5_error_code	retval = 0;
+#ifdef _WIN32
+    WORD wVersionRequested;
+    WSADATA wsaData;
+#endif /* _WIN32 */
+
+	os_ctx = ctx->os_context;
+	os_ctx->magic = KV5M_OS_CONTEXT;
+	os_ctx->time_offset = 0;
+	os_ctx->usec_offset = 0;
+	os_ctx->os_flags = 0;
+	os_ctx->default_ccname = 0;
+
+	ctx->vtbl = 0;
+	PLUGIN_DIR_INIT(&ctx->libkrb5_plugins);
+	PLUGIN_DIR_INIT(&ctx->preauth_plugins);
+	ctx->preauth_context = NULL;
+
+	retval = os_init_paths(ctx, kdc);
+	/*
+	 * If there's an error in the profile, return an error.  Just
+	 * ignoring the error is a Bad Thing (tm).
+	 */
+     
+        if (!retval) {
+                krb5_cc_set_default_name(ctx, NULL);
+
+#ifdef _WIN32
+                /* We initialize winsock to version 1.1 but 
+                 * we do not care if we succeed or fail.
+                 */
+                wVersionRequested = 0x0101;
+                WSAStartup (wVersionRequested, &wsaData);
+#endif /* _WIN32 */
+        }
+	return retval;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_profile (krb5_context ctx, profile_t *profile)
+{
+    return profile_copy (ctx->profile, profile);
+}	
+
+
+krb5_error_code
+krb5_set_config_files(krb5_context ctx, const char **filenames)
+{
+	krb5_error_code retval;
+	profile_t	profile;
+	
+	retval = profile_init(filenames, &profile);
+	if (retval)
+		return retval;
+
+	if (ctx->profile)
+		profile_release(ctx->profile);
+	ctx->profile = profile;
+
+	return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_default_config_files(char ***pfilenames)
+{
+    if (!pfilenames)
+        return EINVAL;
+    return os_get_default_config_files(pfilenames, FALSE);
+}
+
+void KRB5_CALLCONV
+krb5_free_config_files(char **filenames)
+{
+    free_filespecs(filenames);
+}
+
+
+krb5_error_code
+krb5_secure_config_files(krb5_context ctx)
+{
+	/* Obsolete interface; always return an error.
+
+	   This function should be removed next time a major version
+	   number change happens.  */
+	krb5_error_code retval;
+	
+	if (ctx->profile) {
+		profile_release(ctx->profile);
+		ctx->profile = 0;
+	}
+
+	ctx->profile_secure = TRUE;
+	retval = os_init_paths(ctx, FALSE);
+	if (retval)
+		return retval;
+
+	return KRB5_OBSOLETE_FN;
+}
+
+void
+krb5_os_free_context(krb5_context ctx)
+{
+	krb5_os_context os_ctx;
+
+	os_ctx = ctx->os_context;
+	
+	if (os_ctx->default_ccname) {
+		free(os_ctx->default_ccname);
+                os_ctx->default_ccname = 0;
+        }
+
+	os_ctx->magic = 0;
+
+	if (ctx->profile) {
+		profile_release(ctx->profile);
+	    ctx->profile = 0;
+	}
+
+	if (ctx->preauth_context) {
+		krb5_free_preauth_context(ctx);
+		ctx->preauth_context = NULL;
+	}
+	krb5int_close_plugin_dirs (&ctx->preauth_plugins);
+	krb5int_close_plugin_dirs (&ctx->libkrb5_plugins);
+
+#ifdef _WIN32
+        WSACleanup();
+#endif /* _WIN32 */
+}
diff --git a/krb5-1-6/src/lib/krb5/os/krbfileio.c b/krb5-1-6/src/lib/krb5/os/krbfileio.c
new file mode 100644
index 000000000..6ef16ebd0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/krbfileio.c
@@ -0,0 +1,103 @@
+/*
+ * lib/krb5/os/krbfileio.c
+ *
+ * Copyright (c) Hewlett-Packard Company 1991
+ * Released to the Massachusetts Institute of Technology for inclusion
+ * in the Kerberos source code distribution.
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_create_secure_file
+ * krb5_sync_disk_file
+ */
+
+#ifdef MODULE_VERSION_ID
+static char *VersionID = "@(#)krbfileio.c	2 - 08/22/91";
+#endif
+
+
+#include "k5-int.h"
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#include <fcntl.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef apollo
+#   define OPEN_MODE_NOT_TRUSTWORTHY
+#endif
+
+krb5_error_code
+krb5_create_secure_file(krb5_context context, const char *pathname)
+{
+    int fd;
+
+    /*
+     * Create the file with access restricted to the owner
+     */
+    fd = THREEPARAMOPEN(pathname, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
+
+#ifdef OPEN_MODE_NOT_TRUSTWORTHY
+    /*
+     * Some systems that support default acl inheritance do not 
+     * apply ownership information from the process - force the file
+     * to have the proper info.
+     */
+    if (fd > -1) {
+        uid_t   uid;
+        gid_t   gid;
+
+        uid = getuid();
+        gid = getgid();
+
+        fchown(fd, uid, gid);
+
+        fchmod(fd, 0600);
+    }
+#endif /* OPEN_MODE_NOT_TRUSTWORTHY */
+
+    if (fd > -1) {
+        close(fd);
+        return 0;
+    } else {
+        return errno;
+    }
+}
+
+krb5_error_code
+krb5_sync_disk_file(krb5_context context, FILE *fp)
+{
+    fflush(fp);
+#if !defined(MSDOS_FILESYSTEM)
+    if (fsync(fileno(fp))) {
+        return errno;
+    }
+#endif
+
+    return 0;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/os/ktdefname.c b/krb5-1-6/src/lib/krb5/os/ktdefname.c
new file mode 100644
index 000000000..62465f102
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/ktdefname.c
@@ -0,0 +1,83 @@
+/*
+ * lib/krb5/os/ktdefname.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Return default keytab file name.
+ */
+
+#define NEED_WINDOWS
+
+#include "k5-int.h"
+
+extern char *krb5_defkeyname;
+
+/* this is a an exceedinly gross thing. */
+char *krb5_overridekeyname = NULL;
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_default_name(krb5_context context, char *name, int namesize)
+{
+    char *cp = 0;
+    char *retval;
+
+    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"))) {
+	if ((size_t) namesize < (strlen(cp)+1))
+	    return KRB5_CONFIG_NOTENUFSPACE;
+	strcpy(name, cp);
+    } else if ((profile_get_string(context->profile,
+				   "libdefaults",
+				   "default_keytab_name", NULL, 
+				   NULL, &retval) == 0) &&
+	       retval) {
+	if ((size_t) namesize < (strlen(retval)+1))
+	    return KRB5_CONFIG_NOTENUFSPACE;
+	strcpy(name, retval);
+	profile_release_string(retval);
+    } else {
+#if defined(_WIN32)
+	{
+	    char    defname[160];
+	    int     len;
+
+	    len= GetWindowsDirectory( defname, sizeof(defname)-2 );
+	    defname[len]= '\0';
+	    if ( (len + strlen(krb5_defkeyname) + 1) > namesize )
+		return KRB5_CONFIG_NOTENUFSPACE;
+	    sprintf(name, krb5_defkeyname, defname);
+	}
+#else
+	if ((size_t) namesize < (strlen(krb5_defkeyname)+1))
+	    return KRB5_CONFIG_NOTENUFSPACE;
+	strcpy(name, krb5_defkeyname);
+#endif
+    }
+    return 0;
+}
+    
diff --git a/krb5-1-6/src/lib/krb5/os/kuserok.c b/krb5-1-6/src/lib/krb5/os/kuserok.c
new file mode 100644
index 000000000..1505c82cd
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/kuserok.c
@@ -0,0 +1,171 @@
+/*
+ * lib/krb5/os/kuserok.c
+ *
+ * Copyright 1990,1993 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_kuserok()
+ */
+
+#include "k5-int.h"
+#if !defined(_WIN32)		/* Not yet for Windows */
+#include <stdio.h>
+#include <pwd.h>
+
+#if defined(_AIX) && defined(_IBMR2)
+#include <sys/access.h>
+/* xlc has a bug with "const" */
+#define getpwnam(user) getpwnam((char *)user)
+#endif
+
+#define MAX_USERNAME 65
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <hfs/hfs_mount.h>	/* XXX */
+#define FILE_OWNER_OK(UID)  ((UID) == 0 || (UID) == UNKNOWNUID)
+#else
+#define FILE_OWNER_OK(UID)  ((UID) == 0)
+#endif
+
+/*
+ * Given a Kerberos principal "principal", and a local username "luser",
+ * determine whether user is authorized to login according to the
+ * authorization file ("~luser/.k5login" by default).  Returns TRUE
+ * if authorized, FALSE if not authorized.
+ *
+ * If there is no account for "luser" on the local machine, returns
+ * FALSE.  If there is no authorization file, and the given Kerberos
+ * name "server" translates to the same name as "luser" (using
+ * krb5_aname_to_lname()), returns TRUE.  Otherwise, if the authorization file
+ * can't be accessed, returns FALSE.  Otherwise, the file is read for
+ * a matching principal name, instance, and realm.  If one is found,
+ * returns TRUE, if none is found, returns FALSE.
+ *
+ * The file entries are in the format produced by krb5_unparse_name(),
+ * one entry per line.
+ *
+ */
+
+krb5_boolean KRB5_CALLCONV
+krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
+{
+    struct stat sbuf;
+    struct passwd *pwd;
+    char pbuf[MAXPATHLEN];
+    krb5_boolean isok = FALSE;
+    FILE *fp;
+    char kuser[MAX_USERNAME];
+    char *princname;
+    char linebuf[BUFSIZ];
+    char *newline;
+    int gobble;
+
+    /* no account => no access */
+    char pwbuf[BUFSIZ];
+    struct passwd pwx;
+    if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
+	return(FALSE);
+    (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
+    pbuf[sizeof(pbuf) - 1] = '\0';
+    (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));
+
+    if (access(pbuf, F_OK)) {	 /* not accessible */
+	/*
+	 * if he's trying to log in as himself, and there is no .k5login file,
+	 * let him.  To find out, call
+	 * krb5_aname_to_localname to convert the principal to a name
+	 * which we can string compare. 
+	 */
+	if (!(krb5_aname_to_localname(context, principal,
+				      sizeof(kuser), kuser))
+	    && (strcmp(kuser, luser) == 0)) {
+	    return(TRUE);
+	}
+    }
+    if (krb5_unparse_name(context, principal, &princname))
+	return(FALSE);			/* no hope of matching */
+
+    /* open ~/.k5login */
+    if ((fp = fopen(pbuf, "r")) == NULL) {
+	free(princname);
+	return(FALSE);
+    }
+    /*
+     * For security reasons, the .k5login file must be owned either by
+     * the user himself, or by root.  Otherwise, don't grant access.
+     */
+    if (fstat(fileno(fp), &sbuf)) {
+	fclose(fp);
+	free(princname);
+	return(FALSE);
+    }
+    if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) {
+	fclose(fp);
+	free(princname);
+	return(FALSE);
+    }
+
+    /* check each line */
+    while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
+	/* null-terminate the input string */
+	linebuf[BUFSIZ-1] = '\0';
+	newline = NULL;
+	/* nuke the newline if it exists */
+	if ((newline = strchr(linebuf, '\n')))
+	    *newline = '\0';
+	if (!strcmp(linebuf, princname)) {
+	    isok = TRUE;
+	    continue;
+	}
+	/* clean up the rest of the line if necessary */
+	if (!newline)
+	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
+    }
+    free(princname);
+    fclose(fp);
+    return(isok);
+}
+
+#else /* _WIN32 */
+
+/*
+ * If the given Kerberos name "server" translates to the same name as "luser"
+ * (using * krb5_aname_to_lname()), returns TRUE.
+ */
+krb5_boolean KRB5_CALLCONV
+krb5_kuserok(context, principal, luser)
+    krb5_context context;
+    krb5_principal principal;
+    const char *luser;
+{
+    char kuser[50];
+
+    if (krb5_aname_to_localname(context, principal, sizeof(kuser), kuser))
+        return FALSE;
+
+    if (strcmp(kuser, luser) == 0)
+	    return TRUE;
+
+    return FALSE;
+}
+#endif /* _WIN32 */
diff --git a/krb5-1-6/src/lib/krb5/os/localaddr.c b/krb5-1-6/src/lib/krb5/os/localaddr.c
new file mode 100644
index 000000000..75953b1f3
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/localaddr.c
@@ -0,0 +1,1565 @@
+/*
+ * lib/krb5/os/localaddr.c
+ *
+ * Copyright 1990,1991,2000,2001,2002,2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Return the protocol addresses supported by this host.
+ * Exports from this file:
+ *   krb5int_foreach_localaddr (does callbacks)
+ *   krb5int_local_addresses (includes krb5.conf extra_addresses)
+ *   krb5_os_localaddr (doesn't)
+ *
+ * XNS support is untested, but "Should just work".  (Hah!)
+ */
+
+#include "k5-int.h"
+
+#if !defined(_WIN32)
+
+/* needed for solaris, harmless elsewhere... */
+#define BSD_COMP
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <stddef.h>
+#include <ctype.h>
+
+#if defined(TEST) || defined(DEBUG)
+# include "fake-addrinfo.h"
+#endif
+
+#include "foreachaddr.h"
+
+/* Note: foreach_localaddr is exported from the library through
+   krb5int_accessor, for the KDC to use.
+
+   This function iterates over all the addresses it can find for the
+   local system, in one or two passes.  In each pass, and between the
+   two, it can invoke callback functions supplied by the caller.  The
+   two passes should operate on the same information, though not
+   necessarily in the same order each time.  Duplicate and local
+   addresses should be eliminated.  Storage passed to callback
+   functions should not be assumed to be valid after foreach_localaddr
+   returns.
+
+   The int return value is an errno value (XXX or krb5_error_code
+   returned for a socket error) if something internal to
+   foreach_localaddr fails.  If one of the callback functions wants to
+   indicate an error, it should store something via the 'data' handle.
+   If any callback function returns a non-zero value,
+   foreach_localaddr will clean up and return immediately.
+
+   Multiple definitions are provided below, dependent on various
+   system facilities for extracting the necessary information.  */
+
+/* Now, on to the implementations, and heaps of debugging code.  */
+
+#ifdef TEST
+# define Tprintf(X) printf X
+# define Tperror(X) perror(X)
+#else
+# define Tprintf(X) (void) X
+# define Tperror(X) (void)(X)
+#endif
+
+/*
+ * 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.
+ */
+
+
+#if defined(__linux__) && defined(KRB5_USE_INET6) && !defined(HAVE_IFADDRS_H)
+#define LINUX_IPV6_HACK
+#endif
+
+#include <errno.h>
+
+/*
+ * 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.
+ */
+
+/*
+ * 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*/
+
+#if defined(DEBUG) || defined(TEST)
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include "socket-utils.h"
+#include "fake-addrinfo.h"
+
+void printaddr (struct sockaddr *);
+
+void printaddr (struct sockaddr *sa)
+    /*@modifies fileSystem@*/
+{
+    char buf[NI_MAXHOST];
+    int err;
+
+    printf ("%p ", (void *) sa);
+    err = getnameinfo (sa, socklen (sa), buf, sizeof (buf), 0, 0,
+		       NI_NUMERICHOST);
+    if (err)
+	printf ("<getnameinfo error %d: %s> family=%d",
+		err, gai_strerror (err),
+		sa->sa_family);
+    else
+	printf ("%s", buf);
+}
+#endif
+
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+
+#ifdef DEBUG
+void printifaddr (struct ifaddrs *ifp)
+{
+    printf ("%p={\n", ifp);
+/*  printf ("\tnext=%p\n", ifp->ifa_next); */
+    printf ("\tname=%s\n", ifp->ifa_name);
+    printf ("\tflags=");
+    {
+	int ch, flags = ifp->ifa_flags;
+	printf ("%x", flags);
+	ch = '<';
+#define X(F) if (flags & IFF_##F) { printf ("%c%s", ch, #F); flags &= ~IFF_##F; ch = ','; }
+	X (UP); X (BROADCAST); X (DEBUG); X (LOOPBACK); X (POINTOPOINT);
+	X (NOTRAILERS); X (RUNNING); X (NOARP); X (PROMISC); X (ALLMULTI);
+#ifdef IFF_OACTIVE
+	X (OACTIVE);
+#endif
+#ifdef IFF_SIMPLE
+	X (SIMPLEX);
+#endif
+	X (MULTICAST);
+	printf (">");
+#undef X
+    }
+    if (ifp->ifa_addr)
+	printf ("\n\taddr="), printaddr (ifp->ifa_addr);
+    if (ifp->ifa_netmask)
+	printf ("\n\tnetmask="), printaddr (ifp->ifa_netmask);
+    if (ifp->ifa_broadaddr)
+	printf ("\n\tbroadaddr="), printaddr (ifp->ifa_broadaddr);
+    if (ifp->ifa_dstaddr)
+	printf ("\n\tdstaddr="), printaddr (ifp->ifa_dstaddr);
+    if (ifp->ifa_data)
+	printf ("\n\tdata=%p", ifp->ifa_data);
+    printf ("\n}\n");
+}
+#endif /* DEBUG */
+
+#include <string.h>
+#include <stdlib.h>
+
+static int
+addr_eq (const struct sockaddr *s1, const struct sockaddr *s2)
+{
+    if (s1->sa_family != s2->sa_family)
+	return 0;
+#ifdef HAVE_SA_LEN
+    if (s1->sa_len != s2->sa_len)
+	return 0;
+    return !memcmp (s1, s2, s1->sa_len);
+#else
+#define CMPTYPE(T,F) (!memcmp(&((const T*)s1)->F,&((const T*)s2)->F,sizeof(((const T*)s1)->F)))
+    switch (s1->sa_family) {
+    case AF_INET:
+	return CMPTYPE (struct sockaddr_in, sin_addr);
+    case AF_INET6:
+	return CMPTYPE (struct sockaddr_in6, sin6_addr);
+    default:
+	/* Err on side of duplicate listings.  */
+	return 0;
+    }
+#endif
+}
+#endif
+
+#ifndef HAVE_IFADDRS_H
+/*@-usereleased@*/ /* lclint doesn't understand realloc */
+static /*@null@*/ void *
+grow_or_free (/*@only@*/ void *ptr, size_t newsize)
+     /*@*/
+{
+    void *newptr;
+    newptr = realloc (ptr, newsize);
+    if (newptr == NULL && newsize != 0) {
+	free (ptr);		/* lclint complains but this is right */
+	return NULL;
+    }
+    return newptr;
+}
+/*@=usereleased@*/
+
+static int
+get_ifconf (int s, size_t *lenp, /*@out@*/ char *buf)
+    /*@modifies *buf,*lenp@*/
+{
+    int ret;
+    struct ifconf ifc;
+
+    /*@+matchanyintegral@*/
+    ifc.ifc_len = *lenp;
+    /*@=matchanyintegral@*/
+    ifc.ifc_buf = buf;
+    memset(buf, 0, *lenp);
+    /*@-moduncon@*/
+    ret = ioctl (s, SIOCGIFCONF, (char *)&ifc);
+    /*@=moduncon@*/
+    /*@+matchanyintegral@*/
+    *lenp = ifc.ifc_len;
+    /*@=matchanyintegral@*/
+    return ret;
+}
+
+/* Solaris uses SIOCGLIFCONF to return struct lifconf which is just
+   an extended version of struct ifconf.
+
+   HP-UX 11 also appears to have SIOCGLIFCONF, but uses struct
+   if_laddrconf, and struct if_laddrreq to be used with
+   SIOCGLIFADDR.  */
+#if defined(SIOCGLIFCONF) && defined(HAVE_STRUCT_LIFCONF)
+static int
+get_lifconf (int af, int s, size_t *lenp, /*@out@*/ char *buf)
+    /*@modifies *buf,*lenp@*/
+{
+    int ret;
+    struct lifconf lifc;
+
+    lifc.lifc_family = af;
+    lifc.lifc_flags = 0;
+    /*@+matchanyintegral@*/
+    lifc.lifc_len = *lenp;
+    /*@=matchanyintegral@*/
+    lifc.lifc_buf = buf;
+    memset(buf, 0, *lenp);
+    /*@-moduncon@*/
+    ret = ioctl (s, SIOCGLIFCONF, (char *)&lifc);
+    if (ret)
+	Tperror ("SIOCGLIFCONF");
+    /*@=moduncon@*/
+    /*@+matchanyintegral@*/
+    *lenp = lifc.lifc_len;
+    /*@=matchanyintegral@*/
+    return ret;
+}
+#endif
+#if defined(SIOCGLIFCONF) && defined(HAVE_STRUCT_IF_LADDRCONF) && 0
+/* I'm not sure if this is needed or if net/if.h will pull it in.  */
+/* #include <net/if6.h> */
+static int
+get_if_laddrconf (int af, int s, size_t *lenp, /*@out@*/ char *buf)
+    /*@modifies *buf,*lenp@*/
+{
+    int ret;
+    struct if_laddrconf iflc;
+
+    /*@+matchanyintegral@*/
+    iflc.iflc_len = *lenp;
+    /*@=matchanyintegral@*/
+    iflc.iflc_buf = buf;
+    memset(buf, 0, *lenp);
+    /*@-moduncon@*/
+    ret = ioctl (s, SIOCGLIFCONF, (char *)&iflc);
+    if (ret)
+	Tperror ("SIOCGLIFCONF");
+    /*@=moduncon@*/
+    /*@+matchanyintegral@*/
+    *lenp = iflc.iflc_len;
+    /*@=matchanyintegral@*/
+    return ret;
+}
+#endif
+#endif /* ! HAVE_IFADDRS_H */
+
+#ifdef LINUX_IPV6_HACK
+#include <stdio.h>
+/* Read IPv6 addresses out of /proc/net/if_inet6, since there isn't
+   (currently) any ioctl to return them.  */
+struct linux_ipv6_addr_list {
+    struct sockaddr_in6 addr;
+    struct linux_ipv6_addr_list *next;
+};
+static struct linux_ipv6_addr_list *
+get_linux_ipv6_addrs ()
+{
+    struct linux_ipv6_addr_list *lst = 0;
+    FILE *f;
+
+    /* _PATH_PROCNET_IFINET6 */
+    f = fopen("/proc/net/if_inet6", "r");
+    if (f) {
+	char ifname[21];
+	unsigned int idx, pfxlen, scope, dadstat;
+	struct in6_addr a6;
+	struct linux_ipv6_addr_list *nw;
+	int i;
+	unsigned int addrbyte[16];
+
+	while (fscanf(f,
+		      "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x"
+		      " %2x %2x %2x %2x %20s\n",
+		      &addrbyte[0], &addrbyte[1], &addrbyte[2], &addrbyte[3],
+		      &addrbyte[4], &addrbyte[5], &addrbyte[6], &addrbyte[7],
+		      &addrbyte[8], &addrbyte[9], &addrbyte[10], &addrbyte[11],
+		      &addrbyte[12], &addrbyte[13], &addrbyte[14],
+		      &addrbyte[15],
+		      &idx, &pfxlen, &scope, &dadstat, ifname) != EOF) {
+	    for (i = 0; i < 16; i++)
+		a6.s6_addr[i] = addrbyte[i];
+	    if (scope != 0)
+		continue;
+#if 0 /* These symbol names are as used by ifconfig, but none of the
+	 system header files export them.  Dig up the kernel versions
+	 someday and see if they're exported.  */
+	    switch (scope) {
+	    case 0:
+	    default:
+		break;
+	    case IPV6_ADDR_LINKLOCAL:
+	    case IPV6_ADDR_SITELOCAL:
+	    case IPV6_ADDR_COMPATv4:
+	    case IPV6_ADDR_LOOPBACK:
+		continue;
+	    }
+#endif
+	    nw = malloc (sizeof (struct linux_ipv6_addr_list));
+	    if (nw == 0)
+		continue;
+	    memset (nw, 0, sizeof (*nw));
+	    nw->addr.sin6_addr = a6;
+	    nw->addr.sin6_family = AF_INET6;
+	    /* Ignore other fields, we don't actually use them here.  */
+	    nw->next = lst;
+	    lst = nw;
+	}
+	fclose (f);
+    }
+    return lst;
+}
+#endif
+
+/* Return value is errno if internal stuff failed, otherwise zero,
+   even in the case where a called function terminated the iteration.
+
+   If one of the callback functions wants to pass back an error
+   indication, it should do it via some field pointed to by the DATA
+   argument.  */
+
+#ifdef HAVE_IFADDRS_H
+
+int
+foreach_localaddr (/*@null@*/ void *data,
+		   int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+		   /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+		   /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+					      struct sockaddr *) /*@*/)
+#if defined(DEBUG) || defined(TEST)
+     /*@modifies fileSystem@*/
+#endif
+{
+    struct ifaddrs *ifp_head, *ifp, *ifp2;
+    int match;
+
+    if (getifaddrs (&ifp_head) < 0)
+	return errno;
+    for (ifp = ifp_head; ifp; ifp = ifp->ifa_next) {
+#ifdef DEBUG
+	printifaddr (ifp);
+#endif
+	if ((ifp->ifa_flags & IFF_UP) == 0)
+	    continue;
+	if (ifp->ifa_flags & IFF_LOOPBACK) {
+	    /* Pretend it's not up, so the second pass will skip
+	       it.  */
+	    ifp->ifa_flags &= ~IFF_UP;
+	    continue;
+	}
+	if (ifp->ifa_addr == NULL) {
+	    /* Can't use an interface without an address.  Linux
+	       apparently does this sometimes.  [RT ticket 1770 from
+	       Maurice Massar, also Debian bug 206851, shows the
+	       problem with a PPP link on a newer kernel than I'm
+	       running.]
+
+	       Pretend it's not up, so the second pass will skip
+	       it.  */
+	    ifp->ifa_flags &= ~IFF_UP;
+	    continue;
+	}
+	/* If this address is a duplicate, punt.  */
+	match = 0;
+	for (ifp2 = ifp_head; ifp2 && ifp2 != ifp; ifp2 = ifp2->ifa_next) {
+	    if ((ifp2->ifa_flags & IFF_UP) == 0)
+		continue;
+	    if (ifp2->ifa_flags & IFF_LOOPBACK)
+		continue;
+	    if (addr_eq (ifp->ifa_addr, ifp2->ifa_addr)) {
+		match = 1;
+		ifp->ifa_flags &= ~IFF_UP;
+		break;
+	    }
+	}
+	if (match)
+	    continue;
+	if ((*pass1fn) (data, ifp->ifa_addr))
+	    goto punt;
+    }
+    if (betweenfn && (*betweenfn)(data))
+	goto punt;
+    if (pass2fn)
+	for (ifp = ifp_head; ifp; ifp = ifp->ifa_next) {
+	    if (ifp->ifa_flags & IFF_UP)
+		if ((*pass2fn) (data, ifp->ifa_addr))
+		    goto punt;
+	}
+ punt:
+    freeifaddrs (ifp_head);
+    return 0;
+}
+
+#elif defined (SIOCGLIFNUM) && defined(HAVE_STRUCT_LIFCONF) /* Solaris 8 and later; Sol 7? */
+
+int
+foreach_localaddr (/*@null@*/ void *data,
+		   int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+		   /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+		   /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+					      struct sockaddr *) /*@*/)
+#if defined(DEBUG) || defined(TEST)
+     /*@modifies fileSystem@*/
+#endif
+{
+    /* Okay, this is kind of odd.  We have to use each of the address
+       families we care about, because with an AF_INET socket, extra
+       interfaces like hme0:1 that have only AF_INET6 addresses will
+       cause errors.  Similarly, if hme0 has more AF_INET addresses
+       than AF_INET6 addresses, we won't be able to retrieve all of
+       the AF_INET addresses if we use an AF_INET6 socket.  Since
+       neither family is guaranteed to have the greater number of
+       addresses, we should use both.
+
+       If it weren't for this little quirk, we could use one socket of
+       any type, and ask for addresses of all types.  At least, it
+       seems to work that way.  */
+
+    static const int afs[] = { AF_INET, AF_NS, AF_INET6 };
+#define N_AFS (sizeof (afs) / sizeof (afs[0]))
+    struct {
+	int af;
+	int sock;
+	void *buf;
+	size_t buf_size;
+	struct lifnum lifnum;
+    } afp[N_AFS];
+    int code, i, j;
+    int retval = 0, afidx;
+    krb5_error_code sock_err = 0;
+    struct lifreq *lifr, lifreq, *lifr2;
+
+#define FOREACH_AF() for (afidx = 0; afidx < N_AFS; afidx++)
+#define P (afp[afidx])
+
+    /* init */
+    FOREACH_AF () {
+	P.af = afs[afidx];
+	P.sock = -1;
+	P.buf = 0;
+    }
+
+    /* first pass: get raw data, discard uninteresting addresses, callback */
+    FOREACH_AF () {
+	Tprintf (("trying af %d...\n", P.af));
+	P.sock = socket (P.af, USE_TYPE, USE_PROTO);
+	if (P.sock < 0) {
+	    sock_err = SOCKET_ERROR;
+	    Tperror ("socket");
+	    continue;
+	}
+
+	P.lifnum.lifn_family = P.af;
+	P.lifnum.lifn_flags = 0;
+	P.lifnum.lifn_count = 0;
+	code = ioctl (P.sock, SIOCGLIFNUM, &P.lifnum);
+	if (code) {
+	    Tperror ("ioctl(SIOCGLIFNUM)");
+	    retval = errno;
+	    goto punt;
+	}
+
+	P.buf_size = P.lifnum.lifn_count * sizeof (struct lifreq) * 2;
+	P.buf = malloc (P.buf_size);
+	if (P.buf == NULL) {
+	    retval = errno;
+	    goto punt;
+	}
+
+	code = get_lifconf (P.af, P.sock, &P.buf_size, P.buf);
+	if (code < 0) {
+	    retval = errno;
+	    goto punt;
+	}
+
+	for (i = 0; i + sizeof(*lifr) <= P.buf_size; i+= sizeof (*lifr)) {
+	    lifr = (struct lifreq *)((caddr_t) P.buf+i);
+
+	    strncpy(lifreq.lifr_name, lifr->lifr_name,
+		    sizeof (lifreq.lifr_name));
+	    Tprintf (("interface %s\n", lifreq.lifr_name));
+	    /*@-moduncon@*/ /* ioctl unknown to lclint */
+	    if (ioctl (P.sock, SIOCGLIFFLAGS, (char *)&lifreq) < 0) {
+		Tperror ("ioctl(SIOCGLIFFLAGS)");
+	    skip:
+		/* mark for next pass */
+		lifr->lifr_name[0] = '\0';
+		continue;
+	    }
+	    /*@=moduncon@*/
+
+#ifdef IFF_LOOPBACK
+	    /* None of the current callers want loopback addresses.  */
+	    if (lifreq.lifr_flags & IFF_LOOPBACK) {
+		Tprintf (("  loopback\n"));
+		goto skip;
+	    }
+#endif
+	    /* Ignore interfaces that are down.  */
+	    if ((lifreq.lifr_flags & IFF_UP) == 0) {
+		Tprintf (("  down\n"));
+		goto skip;
+	    }
+
+	    /* Make sure we didn't process this address already.  */
+	    for (j = 0; j < i; j += sizeof (*lifr2)) {
+		lifr2 = (struct lifreq *)((caddr_t) P.buf+j);
+		if (lifr2->lifr_name[0] == '\0')
+		    continue;
+		if (lifr2->lifr_addr.ss_family == lifr->lifr_addr.ss_family
+		    /* Compare address info.  If this isn't good enough --
+		       i.e., if random padding bytes turn out to differ
+		       when the addresses are the same -- then we'll have
+		       to do it on a per address family basis.  */
+		    && !memcmp (&lifr2->lifr_addr, &lifr->lifr_addr,
+				sizeof (*lifr))) {
+		    Tprintf (("  duplicate addr\n"));
+		    goto skip;
+		}
+	    }
+
+	    /*@-moduncon@*/
+	    if ((*pass1fn) (data, ss2sa (&lifr->lifr_addr)))
+		goto punt;
+	    /*@=moduncon@*/
+	}
+    }
+
+    /* Did we actually get any working sockets?  */
+    FOREACH_AF ()
+	if (P.sock != -1)
+	    goto have_working_socket;
+    retval = sock_err;
+    goto punt;
+have_working_socket:
+
+    /*@-moduncon@*/
+    if (betweenfn != NULL && (*betweenfn)(data))
+	goto punt;
+    /*@=moduncon@*/
+
+    if (pass2fn)
+	FOREACH_AF ()
+	    if (P.sock >= 0) {
+		for (i = 0; i + sizeof (*lifr) <= P.buf_size; i+= sizeof (*lifr)) {
+		    lifr = (struct lifreq *)((caddr_t) P.buf+i);
+
+		    if (lifr->lifr_name[0] == '\0')
+			/* Marked in first pass to be ignored.  */
+			continue;
+
+		    /*@-moduncon@*/
+		    if ((*pass2fn) (data, ss2sa (&lifr->lifr_addr)))
+			goto punt;
+		    /*@=moduncon@*/
+		}
+	    }
+punt:
+    FOREACH_AF () {
+	/*@-moduncon@*/
+	closesocket(P.sock);
+	/*@=moduncon@*/
+	free (P.buf);
+    }
+
+    return retval;
+}
+
+#elif defined (SIOCGLIFNUM) && defined(HAVE_STRUCT_IF_LADDRCONF) && 0 /* HP-UX 11 support being debugged */
+
+int
+foreach_localaddr (/*@null@*/ void *data,
+		   int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+		   /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+		   /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+					      struct sockaddr *) /*@*/)
+#if defined(DEBUG) || defined(TEST)
+     /*@modifies fileSystem@*/
+#endif
+{
+    /* Okay, this is kind of odd.  We have to use each of the address
+       families we care about, because with an AF_INET socket, extra
+       interfaces like hme0:1 that have only AF_INET6 addresses will
+       cause errors.  Similarly, if hme0 has more AF_INET addresses
+       than AF_INET6 addresses, we won't be able to retrieve all of
+       the AF_INET addresses if we use an AF_INET6 socket.  Since
+       neither family is guaranteed to have the greater number of
+       addresses, we should use both.
+
+       If it weren't for this little quirk, we could use one socket of
+       any type, and ask for addresses of all types.  At least, it
+       seems to work that way.  */
+
+    static const int afs[] = { AF_INET, AF_NS, AF_INET6 };
+#define N_AFS (sizeof (afs) / sizeof (afs[0]))
+    struct {
+	int af;
+	int sock;
+	void *buf;
+	size_t buf_size;
+	int if_num;
+    } afp[N_AFS];
+    int code, i, j;
+    int retval = 0, afidx;
+    krb5_error_code sock_err = 0;
+    struct if_laddrreq *lifr, lifreq, *lifr2;
+
+#define FOREACH_AF() for (afidx = 0; afidx < N_AFS; afidx++)
+#define P (afp[afidx])
+
+    /* init */
+    FOREACH_AF () {
+	P.af = afs[afidx];
+	P.sock = -1;
+	P.buf = 0;
+    }
+
+    /* first pass: get raw data, discard uninteresting addresses, callback */
+    FOREACH_AF () {
+	Tprintf (("trying af %d...\n", P.af));
+	P.sock = socket (P.af, USE_TYPE, USE_PROTO);
+	if (P.sock < 0) {
+	    sock_err = SOCKET_ERROR;
+	    Tperror ("socket");
+	    continue;
+	}
+
+	code = ioctl (P.sock, SIOCGLIFNUM, &P.if_num);
+	if (code) {
+	    Tperror ("ioctl(SIOCGLIFNUM)");
+	    retval = errno;
+	    goto punt;
+	}
+
+	P.buf_size = P.if_num * sizeof (struct if_laddrreq) * 2;
+	P.buf = malloc (P.buf_size);
+	if (P.buf == NULL) {
+	    retval = errno;
+	    goto punt;
+	}
+
+	code = get_if_laddrconf (P.af, P.sock, &P.buf_size, P.buf);
+	if (code < 0) {
+	    retval = errno;
+	    goto punt;
+	}
+
+	for (i = 0; i + sizeof(*lifr) <= P.buf_size; i+= sizeof (*lifr)) {
+	    lifr = (struct if_laddrreq *)((caddr_t) P.buf+i);
+
+	    strncpy(lifreq.iflr_name, lifr->iflr_name,
+		    sizeof (lifreq.iflr_name));
+	    Tprintf (("interface %s\n", lifreq.iflr_name));
+	    /*@-moduncon@*/ /* ioctl unknown to lclint */
+	    if (ioctl (P.sock, SIOCGLIFFLAGS, (char *)&lifreq) < 0) {
+		Tperror ("ioctl(SIOCGLIFFLAGS)");
+	    skip:
+		/* mark for next pass */
+		lifr->iflr_name[0] = '\0';
+		continue;
+	    }
+	    /*@=moduncon@*/
+
+#ifdef IFF_LOOPBACK
+	    /* None of the current callers want loopback addresses.  */
+	    if (lifreq.iflr_flags & IFF_LOOPBACK) {
+		Tprintf (("  loopback\n"));
+		goto skip;
+	    }
+#endif
+	    /* Ignore interfaces that are down.  */
+	    if ((lifreq.iflr_flags & IFF_UP) == 0) {
+		Tprintf (("  down\n"));
+		goto skip;
+	    }
+
+	    /* Make sure we didn't process this address already.  */
+	    for (j = 0; j < i; j += sizeof (*lifr2)) {
+		lifr2 = (struct if_laddrreq *)((caddr_t) P.buf+j);
+		if (lifr2->iflr_name[0] == '\0')
+		    continue;
+		if (lifr2->iflr_addr.sa_family == lifr->iflr_addr.sa_family
+		    /* Compare address info.  If this isn't good enough --
+		       i.e., if random padding bytes turn out to differ
+		       when the addresses are the same -- then we'll have
+		       to do it on a per address family basis.  */
+		    && !memcmp (&lifr2->iflr_addr, &lifr->iflr_addr,
+				sizeof (*lifr))) {
+		    Tprintf (("  duplicate addr\n"));
+		    goto skip;
+		}
+	    }
+
+	    /*@-moduncon@*/
+	    if ((*pass1fn) (data, ss2sa (&lifr->iflr_addr)))
+		goto punt;
+	    /*@=moduncon@*/
+	}
+    }
+
+    /* Did we actually get any working sockets?  */
+    FOREACH_AF ()
+	if (P.sock != -1)
+	    goto have_working_socket;
+    retval = sock_err;
+    goto punt;
+have_working_socket:
+
+    /*@-moduncon@*/
+    if (betweenfn != NULL && (*betweenfn)(data))
+	goto punt;
+    /*@=moduncon@*/
+
+    if (pass2fn)
+	FOREACH_AF ()
+	    if (P.sock >= 0) {
+		for (i = 0; i + sizeof(*lifr) <= P.buf_size; i+= sizeof (*lifr)) {
+		    lifr = (struct if_laddrreq *)((caddr_t) P.buf+i);
+
+		    if (lifr->iflr_name[0] == '\0')
+			/* Marked in first pass to be ignored.  */
+			continue;
+
+		    /*@-moduncon@*/
+		    if ((*pass2fn) (data, ss2sa (&lifr->iflr_addr)))
+			goto punt;
+		    /*@=moduncon@*/
+		}
+	    }
+punt:
+    FOREACH_AF () {
+	/*@-moduncon@*/
+	closesocket(P.sock);
+	/*@=moduncon@*/
+	free (P.buf);
+    }
+
+    return retval;
+}
+
+#else /* not defined (SIOCGLIFNUM) */
+
+#define SLOP (sizeof (struct ifreq) + 128)
+
+static int
+get_ifreq_array(char **bufp, size_t *np, int s)
+{
+    int code;
+    int est_if_count = 8;
+    size_t est_ifreq_size;
+    char *buf = 0;
+    size_t current_buf_size = 0, size, n;
+#ifdef SIOCGSIZIFCONF
+    int ifconfsize = -1;
+#endif
+#ifdef SIOCGIFNUM
+    int numifs = -1;
+#endif
+
+    /* At least on NetBSD, an ifreq can hold an IPv4 address, but
+       isn't big enough for an IPv6 or ethernet address.  So add a
+       little more space.  */
+    est_ifreq_size = sizeof (struct ifreq) + 8;
+#ifdef SIOCGSIZIFCONF
+    code = ioctl (s, SIOCGSIZIFCONF, &ifconfsize);
+    if (!code) {
+	current_buf_size = ifconfsize;
+	est_if_count = ifconfsize / est_ifreq_size;
+    }
+#elif defined (SIOCGIFNUM)
+    code = ioctl (s, SIOCGIFNUM, &numifs);
+    if (!code && numifs > 0)
+	est_if_count = numifs;
+#endif
+    if (current_buf_size == 0)
+	current_buf_size = est_ifreq_size * est_if_count + SLOP;
+    buf = malloc (current_buf_size);
+    if (buf == NULL)
+	return errno;
+
+ask_again:
+    size = current_buf_size;
+    code = get_ifconf (s, &size, buf);
+    if (code < 0) {
+	code = errno;
+	free (buf);
+	return code;
+    }
+    /* Test that the buffer was big enough that another ifreq could've
+       fit easily, if the OS wanted to provide one.  That seems to be
+       the only indication we get, complicated by the fact that the
+       associated address may make the required storage a little
+       bigger than the size of an ifreq.  */
+    if (current_buf_size - size < SLOP
+#ifdef SIOCGSIZIFCONF
+	/* Unless we hear SIOCGSIZIFCONF is broken somewhere, let's
+	   trust the value it returns.  */
+	&& ifconfsize <= 0
+#elif defined (SIOCGIFNUM)
+	&& numifs <= 0
+#endif
+	/* And we need *some* sort of bounds.  */
+	&& current_buf_size <= 100000
+	) {
+	size_t new_size;
+
+	est_if_count *= 2;
+	new_size = est_ifreq_size * est_if_count + SLOP;
+	buf = grow_or_free (buf, new_size);
+	if (buf == 0)
+	    return errno;
+	current_buf_size = new_size;
+	goto ask_again;
+    }
+
+    n = size;
+    if (n > current_buf_size)
+	n = current_buf_size;
+
+    *bufp = buf;
+    *np = n;
+    return 0;
+}
+
+int
+foreach_localaddr (/*@null@*/ void *data,
+		   int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+		   /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+		   /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+					      struct sockaddr *) /*@*/)
+#if defined(DEBUG) || defined(TEST)
+     /*@modifies fileSystem@*/
+#endif
+{
+    struct ifreq *ifr, ifreq, *ifr2;
+    int s, code;
+    char *buf = 0;
+    size_t size, n, i, j;
+    int retval = 0;
+#ifdef LINUX_IPV6_HACK
+    struct linux_ipv6_addr_list *linux_ipv6_addrs = get_linux_ipv6_addrs ();
+    struct linux_ipv6_addr_list *lx_v6;
+#endif
+
+    s = socket (USE_AF, USE_TYPE, USE_PROTO);
+    if (s < 0)
+	return SOCKET_ERRNO;
+
+    retval = get_ifreq_array(&buf, &n, s);
+    if (retval) {
+	/*@-moduncon@*/ /* close() unknown to lclint */
+	closesocket(s);
+	/*@=moduncon@*/
+	return retval;
+    }
+
+    /* Note: Apparently some systems put the size (used or wanted?)
+       into the start of the buffer, just none that I'm actually
+       using.  Fix this when there's such a test system available.
+       The Samba mailing list archives mention that NTP looks for the
+       size on these systems: *-fujitsu-uxp* *-ncr-sysv4*
+       *-univel-sysv*.  */
+    for (i = 0; i + sizeof(struct ifreq) <= n; i+= ifreq_size(*ifr) ) {
+	ifr = (struct ifreq *)((caddr_t) buf+i);
+	/* In case ifreq_size is more than sizeof().  */
+	if (i + ifreq_size(*ifr) > n)
+	  break;
+
+	strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
+	Tprintf (("interface %s\n", ifreq.ifr_name));
+	/*@-moduncon@*/ /* ioctl unknown to lclint */
+	if (ioctl (s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+	skip:
+	    /* mark for next pass */
+	    ifr->ifr_name[0] = '\0';
+	    continue;
+	}
+	/*@=moduncon@*/
+
+#ifdef IFF_LOOPBACK
+	/* None of the current callers want loopback addresses.  */
+	if (ifreq.ifr_flags & IFF_LOOPBACK) {
+	    Tprintf (("  loopback\n"));
+	    goto skip;
+	}
+#endif
+	/* Ignore interfaces that are down.  */
+	if ((ifreq.ifr_flags & IFF_UP) == 0) {
+	    Tprintf (("  down\n"));
+	    goto skip;
+	}
+
+	/* Make sure we didn't process this address already.  */
+	for (j = 0; j < i; j += ifreq_size(*ifr2)) {
+	    ifr2 = (struct ifreq *)((caddr_t) buf+j);
+	    if (ifr2->ifr_name[0] == '\0')
+		continue;
+	    if (ifr2->ifr_addr.sa_family == ifr->ifr_addr.sa_family
+		&& ifreq_size (*ifr) == ifreq_size (*ifr2)
+		/* Compare address info.  If this isn't good enough --
+		   i.e., if random padding bytes turn out to differ
+		   when the addresses are the same -- then we'll have
+		   to do it on a per address family basis.  */
+		&& !memcmp (&ifr2->ifr_addr.sa_data, &ifr->ifr_addr.sa_data,
+			    (ifreq_size (*ifr)
+			     - offsetof (struct ifreq, ifr_addr.sa_data)))) {
+		Tprintf (("  duplicate addr\n"));
+		goto skip;
+	    }
+	}
+
+	/*@-moduncon@*/
+	if ((*pass1fn) (data, &ifr->ifr_addr))
+	    goto punt;
+	/*@=moduncon@*/
+    }
+
+#ifdef LINUX_IPV6_HACK
+    for (lx_v6 = linux_ipv6_addrs; lx_v6; lx_v6 = lx_v6->next)
+	if ((*pass1fn) (data, (struct sockaddr *) &lx_v6->addr))
+	    goto punt;
+#endif
+
+    /*@-moduncon@*/
+    if (betweenfn != NULL && (*betweenfn)(data))
+	goto punt;
+    /*@=moduncon@*/
+
+    if (pass2fn) {
+	for (i = 0; i + sizeof(struct ifreq) <= n; i+= ifreq_size(*ifr) ) {
+	    ifr = (struct ifreq *)((caddr_t) buf+i);
+
+	    if (ifr->ifr_name[0] == '\0')
+		/* Marked in first pass to be ignored.  */
+		continue;
+
+	    /*@-moduncon@*/
+	    if ((*pass2fn) (data, &ifr->ifr_addr))
+		goto punt;
+	    /*@=moduncon@*/
+	}
+#ifdef LINUX_IPV6_HACK
+	for (lx_v6 = linux_ipv6_addrs; lx_v6; lx_v6 = lx_v6->next)
+	    if ((*pass2fn) (data, (struct sockaddr *) &lx_v6->addr))
+		goto punt;
+#endif
+    }
+ punt:
+    /*@-moduncon@*/
+    closesocket(s);
+    /*@=moduncon@*/
+    free (buf);
+#ifdef LINUX_IPV6_HACK
+    while (linux_ipv6_addrs) {
+	lx_v6 = linux_ipv6_addrs->next;
+	free (linux_ipv6_addrs);
+	linux_ipv6_addrs = lx_v6;
+    }
+#endif
+
+    return retval;
+}
+
+#endif /* not HAVE_IFADDRS_H and not SIOCGLIFNUM */
+
+static krb5_error_code
+get_localaddrs (krb5_context context, krb5_address ***addr, int use_profile);
+
+#ifdef TEST
+
+static int print_addr (/*@unused@*/ void *dataptr, struct sockaddr *sa)
+     /*@modifies fileSystem@*/
+{
+    char hostbuf[NI_MAXHOST];
+    int err;
+    socklen_t len;
+
+    printf ("  --> family %2d ", sa->sa_family);
+    len = socklen (sa);
+    err = getnameinfo (sa, len, hostbuf, (socklen_t) sizeof (hostbuf),
+		       (char *) NULL, 0, NI_NUMERICHOST);
+    if (err) {
+	int e = errno;
+	printf ("<getnameinfo error %d: %s>\n", err, gai_strerror (err));
+	if (err == EAI_SYSTEM)
+	    printf ("\t\t<errno is %d: %s>\n", e, strerror(e));
+    } else
+	printf ("addr %s\n", hostbuf);
+    return 0;
+}
+
+int main ()
+{
+    int r;
+
+    (void) setvbuf (stdout, (char *)NULL, _IONBF, 0);
+    r = foreach_localaddr (0, print_addr, NULL, NULL);
+    printf ("return value = %d\n", r);
+    return 0;
+}
+
+#else /* not TESTing */
+
+struct localaddr_data {
+    int count, mem_err, cur_idx, cur_size;
+    krb5_address **addr_temp;
+};
+
+static int
+count_addrs (void *P_data, struct sockaddr *a)
+     /*@*/
+{
+    struct localaddr_data *data = P_data;
+    switch (a->sa_family) {
+    case AF_INET:
+#ifdef KRB5_USE_INET6
+    case AF_INET6:
+#endif
+#ifdef KRB5_USE_NS
+    case AF_XNS:
+#endif
+	data->count++;
+	break;
+    default:
+	break;
+    }
+    return 0;
+}
+
+static int
+allocate (void *P_data)
+     /*@*/
+{
+    struct localaddr_data *data = P_data;
+    int i;
+    void *n;
+
+    n = realloc (data->addr_temp,
+		 (1 + data->count + data->cur_idx) * sizeof (krb5_address *));
+    if (n == 0) {
+	data->mem_err++;
+	return 1;
+    }
+    data->addr_temp = n;
+    data->cur_size = 1 + data->count + data->cur_idx;
+    for (i = data->cur_idx; i <= data->count + data->cur_idx; i++)
+	data->addr_temp[i] = 0;
+    return 0;
+}
+
+static /*@null@*/ krb5_address *
+make_addr (int type, size_t length, const void *contents)
+    /*@*/
+{
+    krb5_address *a;
+    void *data;
+
+    data = malloc (length);
+    if (data == NULL)
+	return NULL;
+    a = malloc (sizeof (krb5_address));
+    if (a == NULL) {
+	free (data);
+	return NULL;
+    }
+    memcpy (data, contents, length);
+    a->magic = KV5M_ADDRESS;
+    a->addrtype = type;
+    a->length = length;
+    a->contents = data;
+    return a;
+}
+
+static int
+add_addr (void *P_data, struct sockaddr *a)
+     /*@modifies *P_data@*/
+{
+    struct localaddr_data *data = P_data;
+    /*@null@*/ krb5_address *address = 0;
+
+    switch (a->sa_family) {
+#ifdef HAVE_NETINET_IN_H
+    case AF_INET:
+	address = make_addr (ADDRTYPE_INET, sizeof (struct in_addr),
+			     &((const struct sockaddr_in *) a)->sin_addr);
+	if (address == NULL)
+	    data->mem_err++;
+	break;
+
+#ifdef KRB5_USE_INET6
+    case AF_INET6:
+    {
+	const struct sockaddr_in6 *in = (const struct sockaddr_in6 *) a;
+	
+	if (IN6_IS_ADDR_LINKLOCAL (&in->sin6_addr))
+	    break;
+
+	address = make_addr (ADDRTYPE_INET6, sizeof (struct in6_addr),
+			     &in->sin6_addr);
+	if (address == NULL)
+	    data->mem_err++;
+	break;
+    }
+#endif /* KRB5_USE_INET6 */
+#endif /* netinet/in.h */
+
+#ifdef KRB5_USE_NS
+    case AF_XNS:
+	address = make_addr (ADDRTYPE_XNS, sizeof (struct ns_addr),
+			     &((const struct sockaddr_ns *)a)->sns_addr);
+	if (address == NULL)
+	    data->mem_err++;
+	break;
+#endif
+
+#ifdef AF_LINK
+	/* Some BSD-based systems (e.g. NetBSD 1.5) and AIX will
+	   include the ethernet address, but we don't want that, at
+	   least for now.  */
+    case AF_LINK:
+	break;
+#endif
+    /*
+     * Add more address families here..
+     */
+    default:
+	break;
+    }
+#ifdef __LCLINT__
+    /* Redundant but unconditional store un-confuses lclint.  */
+    data->addr_temp[data->cur_idx] = address;
+#endif
+    if (address) {
+	data->addr_temp[data->cur_idx++] = address;
+    }
+
+    return data->mem_err;
+}
+
+static krb5_error_code
+krb5_os_localaddr_profile (krb5_context context, struct localaddr_data *datap)
+{
+    krb5_error_code err;
+    static const char *const profile_name[] = {
+	"libdefaults", "extra_addresses", 0
+    };
+    char **values;
+    char **iter;
+    krb5_address **newaddrs;
+
+#ifdef DEBUG
+    fprintf (stderr, "looking up extra_addresses foo\n");
+#endif
+
+    err = profile_get_values (context->profile, profile_name, &values);
+    /* Ignore all errors for now?  */
+    if (err)
+	return 0;
+
+    for (iter = values; *iter; iter++) {
+	char *cp = *iter, *next, *current;
+	int i, count;
+
+#ifdef DEBUG
+	fprintf (stderr, "  found line: '%s'\n", cp);
+#endif
+
+	for (cp = *iter, next = 0; *cp; cp = next) {
+	    while (isspace ((int) *cp) || *cp == ',')
+		cp++;
+	    if (*cp == 0)
+		break;
+	    /* Start of an address.  */
+#ifdef DEBUG
+	    fprintf (stderr, "    addr found in '%s'\n", cp);
+#endif
+	    current = cp;
+	    while (*cp != 0 && !isspace((int) *cp) && *cp != ',')
+		cp++;
+	    if (*cp != 0) {
+		next = cp + 1;
+		*cp = 0;
+	    } else
+		next = cp;
+	    /* Got a single address, process it.  */
+#ifdef DEBUG
+	    fprintf (stderr, "    processing '%s'\n", current);
+#endif
+	    newaddrs = 0;
+	    err = krb5_os_hostaddr (context, current, &newaddrs);
+	    if (err)
+		continue;
+	    for (i = 0; newaddrs[i]; i++) {
+#ifdef DEBUG
+		fprintf (stderr, "    %d: family %d", i,
+			 newaddrs[i]->addrtype);
+		fprintf (stderr, "\n");
+#endif
+	    }
+	    count = i;
+#ifdef DEBUG
+	    fprintf (stderr, "    %d addresses\n", count);
+#endif
+	    if (datap->cur_idx + count >= datap->cur_size) {
+		krb5_address **bigger;
+		bigger = realloc (datap->addr_temp,
+				  sizeof (krb5_address *) * (datap->cur_idx + count));
+		if (bigger) {
+		    datap->addr_temp = bigger;
+		    datap->cur_size = datap->cur_idx + count;
+		}
+	    }
+	    for (i = 0; i < count; i++) {
+		if (datap->cur_idx < datap->cur_size)
+		    datap->addr_temp[datap->cur_idx++] = newaddrs[i];
+		else
+		    free (newaddrs[i]->contents), free (newaddrs[i]);
+	    }
+	    free (newaddrs);
+	}
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_os_localaddr(krb5_context context, krb5_address ***addr)
+{
+    return get_localaddrs(context, addr, 1);
+}
+
+krb5_error_code
+krb5int_local_addresses(krb5_context context, krb5_address ***addr)
+{
+    return get_localaddrs(context, addr, 0);
+}
+
+static krb5_error_code
+get_localaddrs (krb5_context context, krb5_address ***addr, int use_profile)
+{
+    struct localaddr_data data = { 0 };
+    int r;
+    krb5_error_code err;
+
+    if (use_profile) {
+	err = krb5_os_localaddr_profile (context, &data);
+	/* ignore err for now */
+    }
+
+    r = foreach_localaddr (&data, count_addrs, allocate, add_addr);
+    if (r != 0) {
+	int i;
+	if (data.addr_temp) {
+	    for (i = 0; i < data.count; i++)
+		krb5_xfree (data.addr_temp[i]);
+	    free (data.addr_temp);
+	}
+	if (data.mem_err)
+	    return ENOMEM;
+	else
+	    return r;
+    }
+
+    data.cur_idx++; /* null termination */
+    if (data.mem_err)
+	return ENOMEM;
+    else if (data.cur_idx == data.count)
+	*addr = data.addr_temp;
+    else {
+	/* This can easily happen if we have IPv6 link-local
+	   addresses.  Just shorten the array.  */
+	*addr = (krb5_address **) realloc (data.addr_temp,
+					   (sizeof (krb5_address *)
+					    * data.cur_idx));
+	if (*addr == 0)
+	    /* Okay, shortening failed, but the original should still
+	       be intact.  */
+	    *addr = data.addr_temp;
+    }
+
+#ifdef DEBUG
+    {
+	int j;
+	fprintf (stderr, "addresses:\n");
+	for (j = 0; addr[0][j]; j++) {
+	    struct sockaddr_storage ss;
+	    int err2;
+	    char namebuf[NI_MAXHOST];
+	    void *addrp = 0;
+
+	    fprintf (stderr, "%2d: ", j);
+	    fprintf (stderr, "addrtype %2d, length %2d", addr[0][j]->addrtype,
+		     addr[0][j]->length);
+	    memset (&ss, 0, sizeof (ss));
+	    switch (addr[0][j]->addrtype) {
+	    case ADDRTYPE_INET:
+	    {
+		struct sockaddr_in *sinp = ss2sin (&ss);
+		sinp->sin_family = AF_INET;
+		addrp = &sinp->sin_addr;
+#ifdef HAVE_SA_LEN
+		sinp->sin_len = sizeof (struct sockaddr_in);
+#endif
+		break;
+	    }
+#ifdef KRB5_USE_INET6
+	    case ADDRTYPE_INET6:
+	    {
+		struct sockaddr_in6 *sin6p = ss2sin6 (&ss);
+		sin6p->sin6_family = AF_INET6;
+		addrp = &sin6p->sin6_addr;
+#ifdef HAVE_SA_LEN
+		sin6p->sin6_len = sizeof (struct sockaddr_in6);
+#endif
+		break;
+	    }
+#endif
+	    default:
+		ss2sa(&ss)->sa_family = 0;
+		break;
+	    }
+	    if (addrp)
+		memcpy (addrp, addr[0][j]->contents, addr[0][j]->length);
+	    err2 = getnameinfo (ss2sa(&ss), socklen (ss2sa (&ss)),
+				namebuf, sizeof (namebuf), 0, 0,
+				NI_NUMERICHOST);
+	    if (err2 == 0)
+		fprintf (stderr, ": addr %s\n", namebuf);
+	    else
+		fprintf (stderr, ": getnameinfo error %d\n", err2);
+	}
+    }
+#endif
+
+    return 0;
+}
+
+#endif /* not TESTing */
+
+#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(_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 *) 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_CALLCONV
+krb5_os_localaddr (krb5_context context, krb5_address ***addr) {
+    char host[64];                              /* Name of local machine */
+    struct hostent *hostrec;
+    int err, count, i;
+    krb5_address ** paddr;
+
+    *addr = 0;
+    paddr = 0;
+    err = 0;
+    
+    if (gethostname (host, sizeof(host))) {
+        err = SOCKET_ERRNO;
+    }
+
+    if (!err) {
+	    hostrec = gethostbyname (host);
+	    if (hostrec == NULL) {
+		    err = SOCKET_ERRNO;
+	    }
+    }
+
+    if (err) {
+	    hostrec = local_addr_fallback_kludge();
+	    if (!hostrec)
+		    return err;
+		else
+			err = 0;  /* otherwise we will die at cleanup */
+    }
+
+    for (count = 0; hostrec->h_addr_list[count]; count++);
+
+
+    paddr = (krb5_address **)malloc(sizeof(krb5_address *) * (count+1));
+    if (!paddr) {
+        err = ENOMEM;
+        goto cleanup;
+    }
+
+    memset(paddr, 0, sizeof(krb5_address *) * (count+1));
+
+    for (i = 0; i < count; i++)
+    {
+        paddr[i] = (krb5_address *)malloc(sizeof(krb5_address));
+        if (paddr[i] == NULL) {
+            err = ENOMEM;
+            goto cleanup;
+        }
+
+        paddr[i]->magic = KV5M_ADDRESS;
+        paddr[i]->addrtype = hostrec->h_addrtype;
+        paddr[i]->length = hostrec->h_length;
+        paddr[i]->contents = (unsigned char *)malloc(paddr[i]->length);
+        if (!paddr[i]->contents) {
+            err = ENOMEM;
+            goto cleanup;
+        }
+        memcpy(paddr[i]->contents,
+               hostrec->h_addr_list[i],
+               paddr[i]->length);
+    }
+
+ cleanup:
+    if (err) {
+        if (paddr) {
+            for (i = 0; i < count; i++)
+            {
+                if (paddr[i]) {
+                    if (paddr[i]->contents)
+                        free(paddr[i]->contents);
+                    free(paddr[i]);
+                }
+            }
+            free(paddr);
+        }
+    }
+    else
+        *addr = paddr;
+
+    return(err);
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/os/locate_kdc.c b/krb5-1-6/src/lib/krb5/os/locate_kdc.c
new file mode 100644
index 000000000..30eac1b83
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/locate_kdc.c
@@ -0,0 +1,842 @@
+/*
+ * lib/krb5/os/locate_kdc.c
+ *
+ * Copyright 1990,2000,2001,2002,2003,2004,2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * get socket addresses for KDC.
+ */
+
+#include "fake-addrinfo.h"
+#include "k5-int.h"
+#include "os-proto.h"
+#include <stdio.h>
+#ifdef KRB5_DNS_LOOKUP
+#ifdef WSHELPER
+#include <wshelper.h>
+#else /* WSHELPER */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#endif /* WSHELPER */
+#ifndef T_SRV
+#define T_SRV 33
+#endif /* T_SRV */
+
+/* for old Unixes and friends ... */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1)
+
+#if KRB5_DNS_LOOKUP_KDC
+#define DEFAULT_LOOKUP_KDC 1
+#else
+#define DEFAULT_LOOKUP_KDC 0
+#endif
+#if KRB5_DNS_LOOKUP_REALM
+#define DEFAULT_LOOKUP_REALM 1
+#else
+#define DEFAULT_LOOKUP_REALM 0
+#endif
+
+static int
+maybe_use_dns (krb5_context context, const char *name, int defalt)
+{
+    krb5_error_code code;
+    char * value = NULL;
+    int use_dns = 0;
+
+    code = profile_get_string(context->profile, "libdefaults",
+                              name, 0, 0, &value);
+    if (value == 0 && code == 0)
+	code = profile_get_string(context->profile, "libdefaults",
+				  "dns_fallback", 0, 0, &value);
+    if (code)
+        return defalt;
+
+    if (value == 0)
+	return defalt;
+
+    use_dns = _krb5_conf_boolean(value);
+    profile_release_string(value);
+    return use_dns;
+}
+
+int
+_krb5_use_dns_kdc(krb5_context context)
+{
+    return maybe_use_dns (context, "dns_lookup_kdc", DEFAULT_LOOKUP_KDC);
+}
+
+int
+_krb5_use_dns_realm(krb5_context context)
+{
+    return maybe_use_dns (context, "dns_lookup_realm", DEFAULT_LOOKUP_REALM);
+}
+
+#endif /* KRB5_DNS_LOOKUP */
+
+int
+krb5int_grow_addrlist (struct addrlist *lp, int nmore)
+{
+    int i;
+    int newspace = lp->space + nmore;
+    size_t newsize = newspace * sizeof (*lp->addrs);
+    void *newaddrs;
+
+    newaddrs = realloc (lp->addrs, newsize);
+    if (newaddrs == NULL)
+	return errno;
+    lp->addrs = newaddrs;
+    for (i = lp->space; i < newspace; i++) {
+	lp->addrs[i].ai = NULL;
+	lp->addrs[i].freefn = NULL;
+	lp->addrs[i].data = NULL;
+    }
+    lp->space = newspace;
+    return 0;
+}
+#define grow_list krb5int_grow_addrlist
+
+/* Free up everything pointed to by the addrlist structure, but don't
+   free the structure itself.  */
+void
+krb5int_free_addrlist (struct addrlist *lp)
+{
+    int i;
+    for (i = 0; i < lp->naddrs; i++)
+	if (lp->addrs[i].freefn)
+	    (lp->addrs[i].freefn)(lp->addrs[i].data);
+    free (lp->addrs);
+    lp->addrs = NULL;
+    lp->naddrs = lp->space = 0;
+}
+#define free_list krb5int_free_addrlist
+
+static int translate_ai_error (int err)
+{
+    switch (err) {
+    case 0:
+	return 0;
+    case EAI_BADFLAGS:
+    case EAI_FAMILY:
+    case EAI_SOCKTYPE:
+    case EAI_SERVICE:
+	/* All of these indicate bad inputs to getaddrinfo.  */
+	return EINVAL;
+    case EAI_AGAIN:
+	/* Translate to standard errno code.  */
+	return EAGAIN;
+    case EAI_MEMORY:
+	/* Translate to standard errno code.  */
+	return ENOMEM;
+#ifdef EAI_ADDRFAMILY
+    case EAI_ADDRFAMILY:
+#endif
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+    case EAI_NODATA:
+#endif
+    case EAI_NONAME:
+	/* Name not known or no address data, but no error.  Do
+	   nothing more.  */
+	return 0;
+#ifdef EAI_OVERFLOW
+    case EAI_OVERFLOW:
+	/* An argument buffer overflowed.  */
+	return EINVAL;		/* XXX */
+#endif
+#ifdef EAI_SYSTEM
+    case EAI_SYSTEM:
+	/* System error, obviously.  */
+	return errno;
+#endif
+    default:
+	/* An error code we haven't handled?  */
+	return EINVAL;
+    }
+}
+
+#include <stdarg.h>
+static inline void Tprintf(const char *fmt, ...)
+{
+#ifdef TEST
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+#endif
+}
+
+#if 0
+extern void krb5int_debug_fprint(const char *, ...);
+#define dprint krb5int_debug_fprint
+#define print_addrlist krb5int_print_addrlist
+extern void print_addrlist (const struct addrlist *a);
+#else
+static inline void dprint(const char *fmt, ...) { }
+static inline void print_addrlist(const struct addrlist *a) { }
+#endif
+
+static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a,
+				 void (*freefn)(void *), void *data)
+{
+    int err;
+
+    dprint("\tadding %p=%A to %p (naddrs=%d space=%d)\n", a, a, lp,
+	   lp->naddrs, lp->space);
+
+    if (lp->naddrs == lp->space) {
+	err = grow_list (lp, 1);
+	if (err) {
+	    Tprintf ("grow_list failed %d\n", err);
+	    return err;
+	}
+    }
+    Tprintf("setting element %d\n", lp->naddrs);
+    lp->addrs[lp->naddrs].ai = a;
+    lp->addrs[lp->naddrs].freefn = freefn;
+    lp->addrs[lp->naddrs].data = data;
+    lp->naddrs++;
+    Tprintf ("\tcount is now %d: ", lp->naddrs);
+    print_addrlist(lp);
+    Tprintf("\n");
+    return 0;
+}
+
+#define add_host_to_list krb5int_add_host_to_list
+
+static void call_freeaddrinfo(void *data)
+{
+    /* Strict interpretation of the C standard says we can't assume
+       that the ABI for f(void*) and f(struct foo *) will be
+       compatible.  Use this stub just to be paranoid.  */
+    freeaddrinfo(data);
+}
+
+int
+krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
+			  int port, int secport,
+			  int socktype, int family)
+{
+    struct addrinfo *addrs, *a, *anext, hint;
+    int err;
+    char portbuf[10], secportbuf[10];
+    void (*freefn)(void *);
+
+    Tprintf ("adding hostname %s, ports %d,%d, family %d, socktype %d\n",
+	     hostname, ntohs (port), ntohs (secport),
+	     family, socktype);
+
+    memset(&hint, 0, sizeof(hint));
+    hint.ai_family = family;
+    hint.ai_socktype = socktype;
+#ifdef AI_NUMERICSERV
+    hint.ai_flags = AI_NUMERICSERV;
+#endif
+    sprintf(portbuf, "%d", ntohs(port));
+    sprintf(secportbuf, "%d", ntohs(secport));
+    err = getaddrinfo (hostname, portbuf, &hint, &addrs);
+    if (err) {
+	Tprintf ("\tgetaddrinfo(\"%s\", \"%s\", ...)\n\treturns %d: %s\n",
+		 hostname, portbuf, err, gai_strerror (err));
+	return translate_ai_error (err);
+    }
+    freefn = call_freeaddrinfo;
+    anext = 0;
+    for (a = addrs; a != 0 && err == 0; a = anext, freefn = 0) {
+	anext = a->ai_next;
+	err = add_addrinfo_to_list (lp, a, freefn, a);
+    }
+    if (err || secport == 0)
+	goto egress;
+    if (socktype == 0)
+	socktype = SOCK_DGRAM;
+    else if (socktype != SOCK_DGRAM)
+	goto egress;
+    hint.ai_family = AF_INET;
+    err = getaddrinfo (hostname, secportbuf, &hint, &addrs);
+    if (err) {
+	err = translate_ai_error (err);
+	goto egress;
+    }
+    freefn = call_freeaddrinfo;
+    for (a = addrs; a != 0 && err == 0; a = anext, freefn = 0) {
+	anext = a->ai_next;
+	err = add_addrinfo_to_list (lp, a, freefn, a);
+    }
+egress:
+    /* XXX Memory leaks possible here if add_addrinfo_to_list fails.  */
+    return err;
+}
+
+/*
+ * returns count of number of addresses found
+ * if master is non-NULL, it is filled in with the index of
+ * the master kdc
+ */
+
+static krb5_error_code
+krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
+		       const char * name, struct addrlist *addrlist,
+		       int get_masters, int socktype,
+		       int udpport, int sec_udpport, int family)
+{
+    const char	*realm_srv_names[4];
+    char **masterlist, **hostlist, *host, *port, *cp;
+    krb5_error_code code;
+    int i, j, count, ismaster;
+
+    Tprintf ("looking in krb5.conf for realm %s entry %s; ports %d,%d\n",
+	     realm->data, name, ntohs (udpport), ntohs (sec_udpport));
+
+    if ((host = malloc(realm->length + 1)) == NULL) 
+	return ENOMEM;
+
+    strncpy(host, realm->data, realm->length);
+    host[realm->length] = '\0';
+    hostlist = 0;
+
+    masterlist = NULL;
+
+    realm_srv_names[0] = "realms";
+    realm_srv_names[1] = host;
+    realm_srv_names[2] = name;
+    realm_srv_names[3] = 0;
+
+    code = profile_get_values(context->profile, realm_srv_names, &hostlist);
+
+    if (code) {
+	Tprintf ("config file lookup failed: %s\n",
+		 error_message(code));
+        if (code == PROF_NO_SECTION || code == PROF_NO_RELATION)
+	    code = KRB5_REALM_UNKNOWN;
+ 	krb5_xfree(host);
+  	return code;
+     }
+
+    count = 0;
+    while (hostlist && hostlist[count])
+	    count++;
+    Tprintf ("found %d entries under 'kdc'\n", count);
+    
+    if (count == 0) {
+        profile_free_list(hostlist);
+	krb5_xfree(host);
+	addrlist->naddrs = 0;
+	return 0;
+    }
+    
+    if (get_masters) {
+	realm_srv_names[0] = "realms";
+	realm_srv_names[1] = host;
+	realm_srv_names[2] = "admin_server";
+	realm_srv_names[3] = 0;
+
+	code = profile_get_values(context->profile, realm_srv_names,
+				  &masterlist);
+
+	krb5_xfree(host);
+
+	if (code == 0) {
+	    for (i=0; masterlist[i]; i++) {
+		host = masterlist[i];
+
+		/*
+		 * Strip off excess whitespace
+		 */
+		cp = strchr(host, ' ');
+		if (cp)
+		    *cp = 0;
+		cp = strchr(host, '\t');
+		if (cp)
+		    *cp = 0;
+		cp = strchr(host, ':');
+		if (cp)
+		    *cp = 0;
+	    }
+	}
+    } else {
+	krb5_xfree(host);
+    }
+
+    /* 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;
+#endif
+
+    for (i=0; hostlist[i]; i++) {
+	int p1, p2;
+
+	host = hostlist[i];
+	Tprintf ("entry %d is '%s'\n", i, host);
+	/*
+	 * Strip off excess whitespace
+	 */
+	cp = strchr(host, ' ');
+	if (cp)
+	    *cp = 0;
+	cp = strchr(host, '\t');
+	if (cp)
+	    *cp = 0;
+	port = strchr(host, ':');
+	if (port) {
+	    *port = 0;
+	    port++;
+	}
+
+	ismaster = 0;
+	if (masterlist) {
+	    for (j=0; masterlist[j]; j++) {
+		if (strcasecmp(hostlist[i], masterlist[j]) == 0) {
+		    ismaster = 1;
+		}
+	    }
+	}
+
+	if (get_masters && !ismaster)
+	    continue;
+
+	if (port) {
+	    unsigned long l;
+#ifdef HAVE_STROUL
+	    char *endptr;
+	    l = strtoul (port, &endptr, 10);
+	    if (endptr == NULL || *endptr != 0)
+		return EINVAL;
+#else
+	    l = atoi (port);
+#endif
+	    /* L is unsigned, don't need to check <0.  */
+	    if (l > 65535)
+		return EINVAL;
+	    p1 = htons (l);
+	    p2 = 0;
+	} else {
+	    p1 = udpport;
+	    p2 = sec_udpport;
+	}
+
+	if (socktype != 0)
+	    code = add_host_to_list (addrlist, hostlist[i], p1, p2,
+				     socktype, family);
+	else {
+	    code = add_host_to_list (addrlist, hostlist[i], p1, p2,
+				     SOCK_DGRAM, family);
+	    if (code == 0)
+		code = add_host_to_list (addrlist, hostlist[i], p1, p2,
+					 SOCK_STREAM, family);
+	}
+	if (code) {
+	    Tprintf ("error %d (%s) returned from add_host_to_list\n", code,
+		     error_message (code));
+	    if (hostlist)
+		profile_free_list (hostlist);
+	    if (masterlist)
+		profile_free_list (masterlist);
+	    return code;
+	}
+    }
+
+    if (hostlist)
+        profile_free_list(hostlist);
+    if (masterlist)
+        profile_free_list(masterlist);
+
+    return 0;
+}
+
+#ifdef TEST
+static krb5_error_code
+krb5_locate_srv_conf(krb5_context context, const krb5_data *realm,
+		     const char *name, struct addrlist *al, int get_masters,
+		     int udpport, int sec_udpport)
+{
+    krb5_error_code ret;
+
+    ret = krb5_locate_srv_conf_1 (context, realm, name, al,
+				  get_masters, 0, udpport, sec_udpport, 0);
+    if (ret)
+	return ret;
+    if (al->naddrs == 0)	/* Couldn't resolve any KDC names */
+	return KRB5_REALM_CANT_RESOLVE;
+    return 0;
+}
+#endif
+
+#ifdef KRB5_DNS_LOOKUP
+static krb5_error_code
+krb5_locate_srv_dns_1 (const krb5_data *realm,
+		       const char *service,
+		       const char *protocol,
+		       struct addrlist *addrlist,
+		       int family)
+{
+    struct srv_dns_entry *head = NULL;
+    struct srv_dns_entry *entry = NULL, *next;
+    krb5_error_code code = 0;
+
+    code = krb5int_make_srv_query_realm(realm, service, protocol, &head);
+    if (code)
+	return 0;
+
+    /*
+     * Okay!  Now we've got a linked list of entries sorted by
+     * priority.  Start looking up A records and returning
+     * addresses.
+     */
+
+    if (head == NULL)
+	return 0;
+
+    /* Check for the "." case indicating no support.  */
+    if (head->next == 0 && head->host[0] == 0) {
+	free(head->host);
+	free(head);
+	return KRB5_ERR_NO_SERVICE;
+    }
+
+    Tprintf ("walking answer list:\n");
+    for (entry = head; entry != NULL; entry = next) {
+	Tprintf ("\tport=%d host=%s\n", entry->port, entry->host);
+	next = entry->next;
+	code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0,
+				 (strcmp("_tcp", protocol)
+				  ? SOCK_DGRAM
+				  : SOCK_STREAM), family);
+	if (code) {
+	    break;
+	}
+	if (entry == head) {
+	    free(entry->host);
+	    free(entry);
+	    head = next;
+	    entry = 0;
+	}
+    }
+    Tprintf ("[end]\n");
+
+    krb5int_free_srv_dns_data(head);
+    return code;
+}
+#endif
+
+#include <krb5/locate_plugin.h>
+
+#if TARGET_OS_MAC
+static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/libkrb5", NULL }; /* should be a list */
+#else
+static const char *objdirs[] = { LIBDIR "/krb5/plugins/libkrb5", NULL };
+#endif
+
+struct module_callback_data {
+    int out_of_mem;
+    struct addrlist *lp;
+};
+
+static int
+module_callback (void *cbdata, int socktype, struct sockaddr *sa)
+{
+    struct module_callback_data *d = cbdata;
+    struct {
+	struct addrinfo ai;
+	union {
+	    struct sockaddr_in sin;
+	    struct sockaddr_in6 sin6;
+	} u;
+    } *x;
+
+    if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
+	return 0;
+    if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
+	return 0;
+    x = malloc (sizeof (*x));
+    if (x == 0) {
+	d->out_of_mem = 1;
+	return 1;
+    }
+    memset(x, 0, sizeof (*x));
+    x->ai.ai_addr = (struct sockaddr *) &x->u;
+    x->ai.ai_socktype = socktype;
+    x->ai.ai_family = sa->sa_family;
+    if (sa->sa_family == AF_INET) {
+	x->u.sin = *(struct sockaddr_in *)sa;
+	x->ai.ai_addrlen = sizeof(struct sockaddr_in);
+    }
+    if (sa->sa_family == AF_INET6) {
+	x->u.sin6 = *(struct sockaddr_in6 *)sa;
+	x->ai.ai_addrlen = sizeof(struct sockaddr_in6);
+    }
+    if (add_addrinfo_to_list (d->lp, &x->ai, free, x) != 0) {
+	/* Assumes only error is ENOMEM.  */
+	d->out_of_mem = 1;
+	return 1;
+    }
+    return 0;
+}
+
+static krb5_error_code
+module_locate_server (krb5_context ctx, const krb5_data *realm,
+		      struct addrlist *addrlist,
+		      enum locate_service_type svc, int socktype, int family)
+{
+    struct krb5plugin_service_locate_result *res = NULL;
+    krb5_error_code code;
+    struct krb5plugin_service_locate_ftable *vtbl = NULL;
+    void **ptrs;
+    int i;
+    struct module_callback_data cbdata = { 0, };
+
+    Tprintf("in module_locate_server\n");
+    cbdata.lp = addrlist;
+    if (!PLUGIN_DIR_OPEN (&ctx->libkrb5_plugins)) {
+        
+	code = krb5int_open_plugin_dirs (objdirs, NULL, &ctx->libkrb5_plugins,
+					 &ctx->err);
+	if (code)
+	    return KRB5_PLUGIN_NO_HANDLE;
+    }
+
+    code = krb5int_get_plugin_dir_data (&ctx->libkrb5_plugins,
+					"service_locator", &ptrs, &ctx->err);
+    if (code) {
+	Tprintf("error looking up plugin symbols: %s\n",
+		krb5_get_error_message(ctx, code));
+	return KRB5_PLUGIN_NO_HANDLE;
+    }
+
+    for (i = 0; ptrs[i]; i++) {
+	void *blob;
+
+	vtbl = ptrs[i];
+	Tprintf("element %d is %p\n", i, ptrs[i]);
+
+	/* For now, don't keep the plugin data alive.  For long-lived
+	   contexts, it may be desirable to change that later.  */
+	code = vtbl->init(ctx, &blob);
+	if (code)
+	    continue;
+
+	code = vtbl->lookup(blob, svc, realm->data, socktype, family,
+			    module_callback, &cbdata);
+	vtbl->fini(blob);
+	if (code == KRB5_PLUGIN_NO_HANDLE) {
+	    /* Module passes, keep going.  */
+	    /* XXX */
+	    Tprintf("plugin doesn't handle this realm (KRB5_PLUGIN_NO_HANDLE)\n");
+	    continue;
+	}
+	if (code != 0) {
+	    /* Module encountered an actual error.  */
+	    Tprintf("plugin lookup routine returned error %d: %s\n",
+		    code, error_message(code));
+	    krb5int_free_plugin_dir_data (ptrs);
+	    return code;
+	}
+	break;
+    }
+    if (ptrs[i] == NULL) {
+	Tprintf("ran off end of plugin list\n");
+	krb5int_free_plugin_dir_data (ptrs);
+	return KRB5_PLUGIN_NO_HANDLE;
+    }
+    Tprintf("stopped with plugin #%d, res=%p\n", i, res);
+
+    /* Got something back, yippee.  */
+    Tprintf("now have %d addrs in list %p\n", addrlist->naddrs, addrlist);
+    print_addrlist(addrlist);
+    krb5int_free_plugin_dir_data (ptrs);
+    return 0;
+}
+
+static krb5_error_code
+prof_locate_server (krb5_context context, const krb5_data *realm,
+		    struct addrlist *addrlist,
+		    enum locate_service_type svc, int socktype, int family)
+{
+    const char *profname;
+    int dflport1, dflport2 = 0;
+    struct servent *serv;
+
+    switch (svc) {
+    case locate_service_kdc:
+	profname = "kdc";
+	/* We used to use /etc/services for these, but enough systems
+	   have old, crufty, wrong settings that this is probably
+	   better.  */
+    kdc_ports:
+	dflport1 = htons(KRB5_DEFAULT_PORT);
+	dflport2 = htons(KRB5_DEFAULT_SEC_PORT);
+	break;
+    case locate_service_master_kdc:
+	profname = "master_kdc";
+	goto kdc_ports;
+    case locate_service_kadmin:
+	profname = "admin_server";
+	dflport1 = htons(DEFAULT_KADM5_PORT);
+	break;
+    case locate_service_krb524:
+	profname = "krb524_server";
+	serv = getservbyname(KRB524_SERVICE, "udp");
+	dflport1 = serv ? serv->s_port : htons (KRB524_PORT);
+	break;
+    case locate_service_kpasswd:
+	profname = "kpasswd_server";
+	dflport1 = htons(DEFAULT_KPASSWD_PORT);
+	break;
+    default:
+	return EBUSY;		/* XXX */
+    }
+
+    return krb5_locate_srv_conf_1 (context, realm, profname, addrlist,
+				   0, socktype,
+				   dflport1, dflport2, family);
+}
+
+static krb5_error_code
+dns_locate_server (krb5_context context, const krb5_data *realm,
+		   struct addrlist *addrlist,
+		   enum locate_service_type svc, int socktype, int family)
+{
+    const char *dnsname;
+    int use_dns = _krb5_use_dns_kdc(context);
+    krb5_error_code code;
+
+    if (!use_dns)
+	return KRB5_PLUGIN_NO_HANDLE;
+
+    switch (svc) {
+    case locate_service_kdc:
+	dnsname = "_kerberos";
+	break;
+    case locate_service_master_kdc:
+	dnsname = "_kerberos-master";
+	break;
+    case locate_service_kadmin:
+	dnsname = "_kerberos-adm";
+	break;
+    case locate_service_krb524:
+	dnsname = "_krb524";
+	break;
+    case locate_service_kpasswd:
+	dnsname = "_kpasswd";
+	break;
+    default:
+	return KRB5_PLUGIN_NO_HANDLE;
+    }
+
+    code = 0;
+    if (socktype == SOCK_DGRAM || socktype == 0) {
+	code = krb5_locate_srv_dns_1(realm, dnsname, "_udp", addrlist, family);
+	if (code)
+	    Tprintf("dns udp lookup returned error %d\n", code);
+    }
+    if ((socktype == SOCK_STREAM || socktype == 0) && code == 0) {
+	code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp", addrlist, family);
+	if (code)
+	    Tprintf("dns tcp lookup returned error %d\n", code);
+    }
+    return code;
+}
+
+/*
+ * Wrapper function for the various backends
+ */
+
+krb5_error_code
+krb5int_locate_server (krb5_context context, const krb5_data *realm,
+		       struct addrlist *addrlist,
+		       enum locate_service_type svc,
+		       int socktype, int family)
+{
+    krb5_error_code code;
+    struct addrlist al = ADDRLIST_INIT;
+
+    *addrlist = al;
+
+    code = module_locate_server(context, realm, &al, svc, socktype, family);
+    Tprintf("module_locate_server returns %d\n", code);
+    if (code == KRB5_PLUGIN_NO_HANDLE) {
+	/*
+	 * We always try the local file before DNS.  Note that there
+	 * is no way to indicate "service not available" via the
+	 * config file.
+	 */
+
+	code = prof_locate_server(context, realm, &al, svc, socktype, family);
+
+#ifdef KRB5_DNS_LOOKUP
+	if (code) {		/* Try DNS for all profile errors?  */
+	    krb5_error_code code2;
+	    code2 = dns_locate_server(context, realm, &al, svc, socktype,
+				      family);
+	    if (code2 != KRB5_PLUGIN_NO_HANDLE)
+		code = code2;
+	}
+#endif /* KRB5_DNS_LOOKUP */
+
+	/* We could put more heuristics here, like looking up a hostname
+	   of "kerberos."+REALM, etc.  */
+    }
+    if (code == 0)
+	Tprintf ("krb5int_locate_server found %d addresses\n",
+		 al.naddrs);
+    else
+	Tprintf ("krb5int_locate_server returning error code %d/%s\n",
+		 code, error_message(code));
+    if (code != 0) {
+	if (al.space)
+	    free_list (&al);
+	return code;
+    }
+    if (al.naddrs == 0) {	/* No good servers */
+	if (al.space)
+	    free_list (&al);
+	krb5_set_error_message(context, KRB5_REALM_CANT_RESOLVE,
+			       "Cannot resolve network address for KDC in realm %.*s",
+			       realm->length, realm->data);
+			       
+	return KRB5_REALM_CANT_RESOLVE;
+    }
+    *addrlist = al;
+    return 0;
+}
+
+krb5_error_code
+krb5_locate_kdc(krb5_context context, const krb5_data *realm,
+		struct addrlist *addrlist,
+		int get_masters, int socktype, int family)
+{
+    return krb5int_locate_server(context, realm, addrlist,
+				 (get_masters
+				  ? locate_service_master_kdc
+				  : locate_service_kdc),
+				 socktype, family);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/lock_file.c b/krb5-1-6/src/lib/krb5/os/lock_file.c
new file mode 100644
index 000000000..7bbd3e9d6
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/lock_file.c
@@ -0,0 +1,139 @@
+/*
+ * lib/krb5/os/lock_file.c
+ *
+ * Copyright 1990, 1998 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * libos: krb5_lock_file routine
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+
+#if !defined(_WIN32)
+
+/* Unix version...  */
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if defined(HAVE_FCNTL_H) && defined(F_SETLKW) && defined(F_RDLCK)
+#define POSIX_FILE_LOCKS
+#endif
+
+#ifdef HAVE_FLOCK
+#ifndef sysvimp
+#include <sys/file.h>
+#endif
+#else
+#ifndef LOCK_SH
+#define LOCK_SH 0
+#define LOCK_EX 0
+#define LOCK_UN 0
+#endif
+#endif
+
+/*ARGSUSED*/
+krb5_error_code
+krb5_lock_file(krb5_context context, int fd, int mode)
+{
+    int 		lock_flag = -1;
+    krb5_error_code	retval = 0;
+#ifdef POSIX_FILE_LOCKS
+    int lock_cmd = F_SETLKW;
+    struct flock lock_arg = { 0 };
+#endif
+
+    switch (mode & ~KRB5_LOCKMODE_DONTBLOCK) {
+    case KRB5_LOCKMODE_SHARED:
+#ifdef POSIX_FILE_LOCKS
+	lock_arg.l_type = F_RDLCK;
+#endif
+	lock_flag = LOCK_SH;
+	break;
+    case KRB5_LOCKMODE_EXCLUSIVE:
+#ifdef POSIX_FILE_LOCKS
+	lock_arg.l_type = F_WRLCK;
+#endif
+	lock_flag = LOCK_EX;
+	break;
+    case KRB5_LOCKMODE_UNLOCK:
+#ifdef POSIX_FILE_LOCKS
+	lock_arg.l_type = F_UNLCK;
+#endif
+	lock_flag = LOCK_UN;
+	break;
+    }
+
+    if (lock_flag == -1)
+	return(KRB5_LIBOS_BADLOCKFLAG);
+
+    if (mode & KRB5_LOCKMODE_DONTBLOCK) {
+#ifdef POSIX_FILE_LOCKS
+	lock_cmd = F_SETLK;
+#endif
+#ifdef HAVE_FLOCK
+	lock_flag |= LOCK_NB;
+#endif
+    }
+
+#ifdef POSIX_FILE_LOCKS
+    lock_arg.l_whence = 0;
+    lock_arg.l_start = 0;
+    lock_arg.l_len = 0;
+    if (fcntl(fd, lock_cmd, &lock_arg) == -1) {
+	if (errno == EACCES || errno == EAGAIN)	/* see POSIX/IEEE 1003.1-1988,
+						   6.5.2.4 */
+	    return(EAGAIN);
+	if (errno != EINVAL)	/* Fall back to flock if we get EINVAL */
+	    return(errno);
+	retval = errno;
+    } else
+	    return 0;		/* We succeeded.  Yay. */
+#endif
+    
+#ifdef HAVE_FLOCK
+    if (flock(fd, lock_flag) == -1)
+	retval = errno;
+#endif
+    
+    return retval;
+}
+#else   /* Windows or Macintosh */
+
+krb5_error_code
+krb5_lock_file(context, fd, mode)
+    krb5_context context;
+    int fd;
+    int mode;
+{
+    return 0;
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/os/mk_faddr.c b/krb5-1-6/src/lib/krb5/os/mk_faddr.c
new file mode 100644
index 000000000..2184f7220
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/mk_faddr.c
@@ -0,0 +1,88 @@
+/*
+ * lib/krb5/os/full_ipadr.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Take an IP addr & port and generate a full IP address.
+ */
+
+#include "k5-int.h"
+
+#ifdef HAVE_NETINET_IN_H
+   
+#include "os-proto.h"
+#if !defined(_WINSOCKAPI_)
+
+#include <netinet/in.h>
+#endif
+
+krb5_error_code
+krb5_make_fulladdr(krb5_context context, krb5_address *kaddr, krb5_address *kport, krb5_address *raddr)
+{
+    register krb5_octet * marshal;
+    krb5_int32 tmp32;
+    krb5_int16 tmp16;
+
+    if ((kport == NULL) || (kport == NULL)) 
+	return EINVAL;
+
+    raddr->length = kaddr->length + kport->length + (4 * sizeof(krb5_int32));
+    if (!(raddr->contents = (krb5_octet *)malloc(raddr->length)))
+	return ENOMEM;
+
+    raddr->addrtype = ADDRTYPE_ADDRPORT;
+    marshal = raddr->contents;
+
+    tmp16 = kaddr->addrtype;
+    *marshal++ = 0x00;
+    *marshal++ = 0x00;
+    *marshal++ = (krb5_octet) (tmp16 & 0xff);
+    *marshal++ = (krb5_octet) ((tmp16 >> 8) & 0xff);
+
+    tmp32 = kaddr->length;
+    *marshal++ = (krb5_octet) (tmp32 & 0xff);
+    *marshal++ = (krb5_octet) ((tmp32 >> 8) & 0xff);
+    *marshal++ = (krb5_octet) ((tmp32 >> 16) & 0xff);
+    *marshal++ = (krb5_octet) ((tmp32 >> 24) & 0xff);
+
+    (void) memcpy((char *)marshal, (char *)(kaddr->contents), kaddr->length);
+    marshal += kaddr->length;
+
+    tmp16 = kport->addrtype;
+    *marshal++ = 0x00;
+    *marshal++ = 0x00;
+    *marshal++ = (krb5_octet) (tmp16 & 0xff);
+    *marshal++ = (krb5_octet) ((tmp16 >> 8) & 0xff);
+
+    tmp32 = kport->length;
+    *marshal++ = (krb5_octet) (tmp32 & 0xff);
+    *marshal++ = (krb5_octet) ((tmp32 >> 8) & 0xff);
+    *marshal++ = (krb5_octet) ((tmp32 >> 16) & 0xff);
+    *marshal++ = (krb5_octet) ((tmp32 >> 24) & 0xff);
+
+    (void) memcpy((char *)marshal, (char *)(kport->contents), kport->length);
+    marshal += kport->length;
+    return 0;
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/os/net_read.c b/krb5-1-6/src/lib/krb5/os/net_read.c
new file mode 100644
index 000000000..1d07a95d9
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/net_read.c
@@ -0,0 +1,65 @@
+/*
+ * lib/krb5/os/net_read.c
+ *
+ * Copyright 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+
+/*
+ * krb5_net_read() reads from the file descriptor "fd" to the buffer
+ * "buf", until either 1) "len" bytes have been read or 2) cannot
+ * read anymore from "fd".  It returns the number of bytes read
+ * or a read() error.  (The calling interface is identical to
+ * read(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+
+int
+krb5_net_read(krb5_context context, int fd, register char *buf, register int len)
+{
+    int cc, len2 = 0;
+
+    do {
+	cc = SOCKET_READ((SOCKET)fd, buf, len);
+	if (cc < 0) {
+	    if (SOCKET_ERRNO == SOCKET_EINTR)
+		continue;
+		
+		/* XXX this interface sucks! */
+        errno = SOCKET_ERRNO;    
+               
+	    return(cc);		 /* errno is already set */
+	}		
+	else if (cc == 0) {
+	    return(len2);
+	} else {
+	    buf += cc;
+	    len2 += cc;
+	    len -= cc;
+	}
+    } while (len > 0);
+    return(len2);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/net_write.c b/krb5-1-6/src/lib/krb5/os/net_write.c
new file mode 100644
index 000000000..e4981543a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/net_write.c
@@ -0,0 +1,61 @@
+/*
+ * lib/krb5/os/net_write.c
+ *
+ * Copyright 1987, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+
+/*
+ * krb5_net_write() writes "len" bytes from "buf" to the file
+ * descriptor "fd".  It returns the number of bytes written or
+ * a write() error.  (The calling interface is identical to
+ * write(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+
+int
+krb5_net_write(krb5_context context, int fd, register const char *buf, int len)
+{
+    int cc;
+    register int wrlen = len;
+    do {
+	cc = SOCKET_WRITE((SOCKET)fd, buf, wrlen);
+	if (cc < 0) {
+	    if (SOCKET_ERRNO == SOCKET_EINTR)
+		continue;
+
+		/* XXX this interface sucks! */
+        errno = SOCKET_ERRNO;           
+
+	    return(cc);
+	}
+	else {
+	    buf += cc;
+	    wrlen -= cc;
+	}
+    } while (wrlen > 0);
+    return(len);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/os-proto.h b/krb5-1-6/src/lib/krb5/os/os-proto.h
new file mode 100644
index 000000000..33acd0c46
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/os-proto.h
@@ -0,0 +1,74 @@
+/*
+ * lib/krb5/os/os-proto.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * LIBOS internal function prototypes.
+ */
+
+#ifndef KRB5_LIBOS_INT_PROTO__
+#define KRB5_LIBOS_INT_PROTO__
+
+struct addrlist;
+krb5_error_code krb5_locate_kdc
+    (krb5_context, const krb5_data *, struct addrlist *, int, int, int);
+
+#ifdef HAVE_NETINET_IN_H
+krb5_error_code krb5_unpack_full_ipaddr
+	      (krb5_context,
+	       const krb5_address *,
+	       krb5_int32 *,
+	       krb5_int16 *);
+
+krb5_error_code krb5_make_full_ipaddr
+              (krb5_context,
+	       krb5_int32,
+	       int,			/* unsigned short promotes to signed
+					   int */
+	       krb5_address **);
+
+#endif /* HAVE_NETINET_IN_H */
+
+krb5_error_code krb5_try_realm_txt_rr(const char *, const char *, 
+				      char **realm);
+
+/* Obsolete interface - leave prototype here until code removed */
+krb5_error_code krb5_secure_config_files(krb5_context ctx);
+
+void krb5int_debug_fprint (const char *fmt, ...);
+
+int _krb5_use_dns_realm (krb5_context);
+int _krb5_use_dns_kdc (krb5_context);
+int _krb5_conf_boolean (const char *);
+
+#include "k5-thread.h"
+extern k5_mutex_t krb5int_us_time_mutex;
+
+extern unsigned int krb5_max_skdc_timeout;
+extern unsigned int krb5_skdc_timeout_shift;
+extern unsigned int krb5_skdc_timeout_1;
+extern unsigned int krb5_max_dgram_size;
+
+
+#endif /* KRB5_LIBOS_INT_PROTO__ */
diff --git a/krb5-1-6/src/lib/krb5/os/osconfig.c b/krb5-1-6/src/lib/krb5/os/osconfig.c
new file mode 100644
index 000000000..dec5cac77
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/osconfig.c
@@ -0,0 +1,46 @@
+/*
+ * lib/krb5/os/osconfig.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Definition of default configuration parameters.
+ *
+ * ***** WARNING *****
+ * These globals are internal library interfaces and are not
+ * supported.  Do not use them in any production code, as they will be
+ * removed from the library in the future.
+ */
+
+#include "k5-int.h"
+
+char *krb5_defkeyname  = DEFAULT_KEYTAB_NAME;
+
+unsigned int krb5_max_dgram_size = MAX_DGRAM_SIZE;
+unsigned int krb5_max_skdc_timeout = MAX_SKDC_TIMEOUT;
+unsigned int krb5_skdc_timeout_shift = SKDC_TIMEOUT_SHIFT;
+unsigned int krb5_skdc_timeout_1 = SKDC_TIMEOUT_1;
+
+char *krb5_default_pwd_prompt1 = DEFAULT_PWD_STRING1;
+char *krb5_default_pwd_prompt2 = DEFAULT_PWD_STRING2;
+
diff --git a/krb5-1-6/src/lib/krb5/os/port2ip.c b/krb5-1-6/src/lib/krb5/os/port2ip.c
new file mode 100644
index 000000000..6b5838b85
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/port2ip.c
@@ -0,0 +1,84 @@
+/*
+ * lib/krb5/os/port2ip.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Take an ADDRPORT address and split into IP addr & port.
+ */
+
+#include "k5-int.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include "os-proto.h"
+
+krb5_error_code
+krb5_unpack_full_ipaddr(krb5_context context, const krb5_address *inaddr, krb5_int32 *adr, krb5_int16 *port)
+{
+    unsigned long smushaddr;
+    unsigned short smushport;
+    register krb5_octet *marshal;
+    krb5_addrtype temptype;
+    krb5_ui_4 templength;
+
+    if (inaddr->addrtype != ADDRTYPE_ADDRPORT)
+	return KRB5_PROG_ATYPE_NOSUPP;
+
+    if (inaddr->length != sizeof(smushaddr)+ sizeof(smushport) +
+	2*sizeof(temptype) + 2*sizeof(templength))
+	return KRB5_PROG_ATYPE_NOSUPP;
+
+    marshal = inaddr->contents;
+
+    (void) memcpy((char *)&temptype, (char *)marshal, sizeof(temptype));
+    marshal += sizeof(temptype);
+    if (temptype != htons(ADDRTYPE_INET))
+	return KRB5_PROG_ATYPE_NOSUPP;
+
+    (void) memcpy((char *)&templength, (char *)marshal, sizeof(templength));
+    marshal += sizeof(templength);
+    if (templength != htonl(sizeof(smushaddr)))
+	return KRB5_PROG_ATYPE_NOSUPP;
+
+    (void) memcpy((char *)&smushaddr, (char *)marshal, sizeof(smushaddr));
+    /* leave in net order */
+    marshal += sizeof(smushaddr);
+
+    (void) memcpy((char *)&temptype, (char *)marshal, sizeof(temptype));
+    marshal += sizeof(temptype);
+    if (temptype != htons(ADDRTYPE_IPPORT))
+	return KRB5_PROG_ATYPE_NOSUPP;
+
+    (void) memcpy((char *)&templength, (char *)marshal, sizeof(templength));
+    marshal += sizeof(templength);
+    if (templength != htonl(sizeof(smushport)))
+	return KRB5_PROG_ATYPE_NOSUPP;
+
+    (void) memcpy((char *)&smushport, (char *)marshal, sizeof(smushport));
+    /* leave in net order */
+
+    *adr = (krb5_int32) smushaddr;
+    *port = (krb5_int16) smushport;
+    return 0;
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/os/prompter.c b/krb5-1-6/src/lib/krb5/os/prompter.c
new file mode 100644
index 000000000..739c8c747
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/prompter.c
@@ -0,0 +1,327 @@
+#include "k5-int.h"
+#if !defined(_WIN32) || (defined(_WIN32) && defined(__CYGWIN32__))
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <limits.h>
+/* Is vxworks broken w.r.t. termios? --tlyu */
+#ifdef __vxworks
+#define ECHO_PASSWORD
+#endif
+
+#include <termios.h>
+
+#ifdef POSIX_SIGNALS
+typedef struct sigaction osiginfo;
+#else
+typedef struct krb5_sigtype (*osiginfo)();
+#endif
+
+static void	catch_signals(osiginfo *);
+static void	restore_signals(osiginfo *);
+static krb5_sigtype	intrfunc(int sig);
+
+static krb5_error_code	setup_tty(FILE*, int, struct termios *, osiginfo *);
+static krb5_error_code	restore_tty(FILE*, struct termios *, osiginfo *);
+
+static volatile int got_int;	/* should be sig_atomic_t */
+
+krb5_error_code KRB5_CALLCONV
+krb5_prompter_posix(
+    krb5_context	context,
+    void		*data,
+    const char		*name,
+    const char		*banner,
+    int			num_prompts,
+    krb5_prompt		prompts[])
+{
+    int		fd, i, scratchchar;
+    FILE	*fp;
+    char	*retp;
+    krb5_error_code	errcode;
+    struct termios saveparm;
+    osiginfo osigint;
+
+    errcode = KRB5_LIBOS_CANTREADPWD;
+
+    if (name) {
+	fputs(name, stdout);
+	fputs("\n", stdout);
+    }
+    if (banner) {
+       fputs(banner, stdout);
+       fputs("\n", stdout);
+    }
+
+    /*
+     * Get a non-buffered stream on stdin.
+     */
+    fp = NULL;
+    fd = dup(STDIN_FILENO);
+    if (fd < 0)
+	return KRB5_LIBOS_CANTREADPWD;
+    fp = fdopen(fd, "r");
+    if (fp == NULL)
+	goto cleanup;
+    if (setvbuf(fp, NULL, _IONBF, 0))
+	goto cleanup;
+
+    for (i = 0; i < num_prompts; i++) {
+	errcode = KRB5_LIBOS_CANTREADPWD;
+	/* fgets() takes int, but krb5_data.length is unsigned. */
+	if (prompts[i].reply->length > INT_MAX)
+	    goto cleanup;
+
+	errcode = setup_tty(fp, prompts[i].hidden, &saveparm, &osigint);
+	if (errcode)
+	    break;
+
+	/* put out the prompt */
+	(void)fputs(prompts[i].prompt, stdout);
+	(void)fputs(": ", stdout);
+	(void)fflush(stdout);
+	(void)memset(prompts[i].reply->data, 0, prompts[i].reply->length);
+
+	got_int = 0;
+	retp = fgets(prompts[i].reply->data, (int)prompts[i].reply->length,
+		     fp);
+	if (prompts[i].hidden)
+	    putchar('\n');
+	if (retp == NULL) {
+	    if (got_int)
+		errcode = KRB5_LIBOS_PWDINTR;
+	    else
+		errcode = KRB5_LIBOS_CANTREADPWD;
+	    restore_tty(fp, &saveparm, &osigint);
+	    break;
+	}
+
+	/* replace newline with null */
+	retp = strchr(prompts[i].reply->data, '\n');
+	if (retp != NULL)
+	    *retp = '\0';
+	else {
+	    /* flush rest of input line */
+	    do {
+		scratchchar = getc(fp);
+	    } while (scratchchar != EOF && scratchchar != '\n');
+	}
+
+	errcode = restore_tty(fp, &saveparm, &osigint);
+	if (errcode)
+	    break;
+	prompts[i].reply->length = strlen(prompts[i].reply->data);
+    }
+cleanup:
+    if (fp != NULL)
+	fclose(fp);
+    else if (fd >= 0)
+	close(fd);
+
+    return errcode;
+}
+
+static krb5_sigtype intrfunc(int sig)
+{
+    got_int = 1;
+}
+
+static void
+catch_signals(osiginfo *osigint)
+{
+#ifdef POSIX_SIGNALS
+    struct sigaction sa;
+
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = intrfunc;
+    sigaction(SIGINT, &sa, osigint);
+#else
+    *osigint = signal(SIGINT, intrfunc);
+#endif
+}
+
+static void
+restore_signals(osiginfo *osigint)
+{
+#ifdef POSIX_SIGNALS
+    sigaction(SIGINT, osigint, NULL);
+#else
+    signal(SIGINT, *osigint);
+#endif
+}
+
+static krb5_error_code
+setup_tty(FILE *fp, int hidden, struct termios *saveparm, osiginfo *osigint)
+{
+    krb5_error_code	ret;
+    int			fd;
+    struct termios	tparm;
+
+    ret = KRB5_LIBOS_CANTREADPWD;
+    catch_signals(osigint);
+    fd = fileno(fp);
+    do {
+	if (!isatty(fd)) {
+	    ret = 0;
+	    break;
+	}
+	if (tcgetattr(fd, &tparm) < 0)
+	    break;
+	*saveparm = tparm;
+#ifndef ECHO_PASSWORD
+	if (hidden)
+	    tparm.c_lflag &= ~(ECHO|ECHONL);
+#endif
+	tparm.c_lflag |= ISIG|ICANON;
+	if (tcsetattr(STDIN_FILENO, TCSANOW, &tparm) < 0)
+	    break;
+	ret = 0;
+    } while (0);
+    /* If we're losing, restore signal handlers. */
+    if (ret)
+	restore_signals(osigint);
+    return ret;
+}
+
+static krb5_error_code
+restore_tty(FILE* fp, struct termios *saveparm, osiginfo *osigint)
+{
+    int ret, fd;
+
+    ret = 0;
+    fd = fileno(fp);
+    if (isatty(fd)) {
+	ret = tcsetattr(fd, TCSANOW, saveparm);
+	if (ret < 0)
+	    ret = KRB5_LIBOS_CANTREADPWD;
+	else
+	    ret = 0;
+    }
+    restore_signals(osigint);
+    return ret;
+}
+
+#else /* non-Cygwin Windows, or Mac */
+
+#if defined(_WIN32)
+
+#include <io.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5_prompter_posix(krb5_context context,
+		    void *data,
+		    const char *name,
+		    const char *banner,
+		    int num_prompts,
+		    krb5_prompt prompts[])
+{
+    HANDLE		handle;
+    DWORD		old_mode, new_mode;
+    char		*ptr;
+    int			scratchchar;
+    krb5_error_code	errcode = 0;
+    int			i;
+
+    handle = GetStdHandle(STD_INPUT_HANDLE);
+    if (handle == INVALID_HANDLE_VALUE)
+	return ENOTTY;
+    if (!GetConsoleMode(handle, &old_mode))
+	return ENOTTY;
+
+    new_mode = old_mode;
+    new_mode |=  ( ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT );
+    new_mode &= ~( ENABLE_ECHO_INPUT );
+
+    if (!SetConsoleMode(handle, new_mode))
+	return ENOTTY;
+
+    if (!SetConsoleMode(handle, old_mode))
+	return ENOTTY;
+
+    if (name) {
+	fputs(name, stdout);
+	fputs("\n", stdout);
+    }
+
+    if (banner) {
+       fputs(banner, stdout);
+       fputs("\n", stdout);
+    }
+
+    for (i = 0; i < num_prompts; i++) {
+	if (prompts[i].hidden) {
+	    if (!SetConsoleMode(handle, new_mode)) {
+		errcode = ENOTTY;
+		goto cleanup;
+	    }
+	}
+
+	fputs(prompts[i].prompt,stdout);
+	fputs(": ", stdout);
+	fflush(stdout);
+	memset(prompts[i].reply->data, 0, prompts[i].reply->length);
+
+	if (fgets(prompts[i].reply->data, prompts[i].reply->length, stdin)
+	    == NULL) {
+	    if (prompts[i].hidden)
+		putchar('\n');
+	    errcode = KRB5_LIBOS_CANTREADPWD;
+	    goto cleanup;
+	}
+	if (prompts[i].hidden)
+	    putchar('\n');
+	/* fgets always null-terminates the returned string */
+
+	/* replace newline with null */
+	if ((ptr = strchr(prompts[i].reply->data, '\n')))
+	    *ptr = '\0';
+	else /* flush rest of input line */
+	    do {
+		scratchchar = getchar();
+	    } while (scratchchar != EOF && scratchchar != '\n');
+    
+	prompts[i].reply->length = strlen(prompts[i].reply->data);
+
+	if (!SetConsoleMode(handle, old_mode)) {
+	    errcode = ENOTTY;
+	    goto cleanup;
+	}
+    }
+
+ cleanup:
+    if (errcode) {
+	for (i = 0; i < num_prompts; i++) {
+	    memset(prompts[i].reply->data, 0, prompts[i].reply->length);
+	}
+    }
+    return errcode;
+}
+
+#else /* !_WIN32 */
+
+krb5_error_code KRB5_CALLCONV
+krb5_prompter_posix(krb5_context context,
+		    void *data,
+		    const char *name,
+		    const char *banner,
+		    int num_prompts,
+		    krb5_prompt prompts[])
+{
+    return(EINVAL);
+}
+#endif /* !_WIN32 */
+#endif /* Windows or Mac */
+
+void
+krb5int_set_prompt_types(krb5_context context, krb5_prompt_type *types)
+{
+    context->prompt_types = types;
+}
+
+krb5_prompt_type*
+KRB5_CALLCONV
+krb5_get_prompt_types(krb5_context context)
+{
+    return context->prompt_types;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/promptusr.c b/krb5-1-6/src/lib/krb5/os/promptusr.c
new file mode 100644
index 000000000..68f8b14a0
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/promptusr.c
@@ -0,0 +1,160 @@
+/*
+ * promptusr.c --- prompt user for input/output
+ */
+
+#include "k5-int.h"
+#if !defined(_WIN32)
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <termios.h>
+#include <signal.h>
+#include <setjmp.h>
+
+typedef struct _krb5_uio {
+    krb5_magic		magic;
+    int 		flags;
+    char *		prompt;
+    char *		response;
+    struct _krb5_uio	*next;
+} *krb5_uio;
+
+#define KRB5_UIO_GETRESPONSE	0x0001
+#define KRB5_UIO_ECHORESPONSE	0x0002
+#define KRB5_UIO_FREE_PROMPT	0x0004
+
+static jmp_buf pwd_jump;
+
+static krb5_sigtype
+intr_routine(int signo)
+{
+    longjmp(pwd_jump, 1);
+    /*NOTREACHED*/
+}
+
+krb5_error_code
+krb5_os_get_tty_uio(krb5_context context, krb5_uio uio)
+{
+    volatile krb5_error_code 	retval;
+    krb5_sigtype	(*volatile ointrfunc)();
+    krb5_uio		p;
+    struct termios 	echo_control, save_control;
+    int 		fd;
+    char		read_string[BUFSIZ];
+    char		*cp;
+    int			ch;
+
+    /* get the file descriptor associated with stdin */
+    fd=fileno(stdin);
+
+    if (tcgetattr(fd, &echo_control) == -1)
+	return errno;
+
+    save_control = echo_control;
+    echo_control.c_lflag &= ~(ECHO|ECHONL);
+
+    if (setjmp(pwd_jump)) {
+	retval = KRB5_LIBOS_PWDINTR; 	/* we were interrupted... */
+	goto cleanup;
+    }
+    /* save intrfunc */
+    ointrfunc = signal(SIGINT, intr_routine);
+    
+    for (p = uio; p; p = p->next) {
+	if (p->prompt) {
+	    fputs(p->prompt, stdout);
+	    fflush(stdout);
+	}
+	if ((p->flags & KRB5_UIO_GETRESPONSE) == 0)
+	    continue;
+
+	if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0) 
+	    if (tcsetattr(fd, TCSANOW, &echo_control) == -1)
+		return errno;
+
+	if (fgets(read_string, sizeof(read_string), stdin) == NULL) {
+	    (void) putchar('\n');
+	    retval = KRB5_LIBOS_CANTREADPWD;
+	    goto cleanup;
+	}
+	
+	/* replace newline with null */
+	if ((cp = strchr(read_string, '\n')))
+	    *cp = '\0';
+	else /* flush rest of input line */
+	    do {
+		ch = getchar();
+	    } while (ch != EOF && ch != '\n');
+	read_string[sizeof(read_string)-1] = 0;
+
+	if ((p->response = malloc(strlen(read_string)+1)) == NULL) {
+	    errno = ENOMEM;
+	    goto cleanup;
+	}
+	strcpy(p->response, read_string);
+
+	if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0) {
+	    (void) putchar('\n');
+	    if (tcsetattr(fd, TCSANOW, &save_control) == -1) {
+		retval = errno;
+		goto cleanup;
+	    }
+	}
+    }
+    retval = 0;
+    
+ cleanup:
+    (void) signal(SIGINT, ointrfunc);
+    if (retval) {
+	for (p = uio; p; p = p->next) {
+	    if (p->response) {
+		memset(p->response, 0, strlen(p->response));
+		free(p->response);
+		p->response = 0;
+	    }
+	}
+    }
+    memset(read_string, 0, sizeof(read_string));
+    tcsetattr(fd, TCSANOW, &save_control);
+    return retval;
+}
+
+void
+krb5_free_uio(krb5_context context, krb5_uio uio)
+{
+    krb5_uio		p, next;
+
+    for (p = uio; p; p = next) {
+	next = p->next;
+	if (p->prompt && (p->flags & KRB5_UIO_FREE_PROMPT))
+	    free(p->prompt);
+	if (p->response)
+	    free(p->response);
+	free(p);
+    }
+}
+
+#ifdef TEST_DRIVER
+
+struct _krb5_uio uio_a = { 0, KRB5_UIO_GETRESPONSE, "Password 1: " };
+struct _krb5_uio uio_b = { 0, KRB5_UIO_GETRESPONSE |
+			       KRB5_UIO_ECHORESPONSE, "Password 2: " };
+struct _krb5_uio uio_c = { 0, KRB5_UIO_GETRESPONSE, "Password 3: " };
+
+
+void
+main(int argc, char **argv)
+{
+    uio_a.next = &uio_b;
+    uio_b.next = &uio_c;
+
+    krb5_os_get_tty_uio(0, &uio_a);
+    exit(0);
+}
+
+#endif
+	
+#endif /* !_MSODS */
diff --git a/krb5-1-6/src/lib/krb5/os/read_msg.c b/krb5-1-6/src/lib/krb5/os/read_msg.c
new file mode 100644
index 000000000..77cda8032
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/read_msg.c
@@ -0,0 +1,63 @@
+/*
+ * lib/krb5/os/read_msg.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Write a message to the network
+ */
+
+#include "k5-int.h"
+#include <errno.h>
+
+krb5_error_code
+krb5_read_message(krb5_context context, krb5_pointer fdp, krb5_data *inbuf)
+{
+	krb5_int32	len;
+	int		len2, ilen;
+	char		*buf = NULL;
+	int		fd = *( (int *) fdp);
+	
+	if ((len2 = krb5_net_read(context, fd, (char *)&len, 4)) != 4)
+		return((len2 < 0) ? errno : ECONNABORTED);
+	len = ntohl(len);
+
+	if ((len & VALID_UINT_BITS) != len)  /* Overflow size_t??? */
+		return ENOMEM;
+
+	inbuf->length = ilen = (int) len;
+	if (ilen) {
+		/*
+		 * We may want to include a sanity check here someday....
+		 */
+		if (!(buf = malloc(inbuf->length))) {
+			return(ENOMEM);
+		}
+		if ((len2 = krb5_net_read(context, fd, buf, ilen)) != ilen) {
+			krb5_xfree(buf);
+			return((len2 < 0) ? errno : ECONNABORTED);
+		}
+	}
+	inbuf->data = buf;
+	return(0);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/read_pwd.c b/krb5-1-6/src/lib/krb5/os/read_pwd.c
new file mode 100644
index 000000000..6f2868da7
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/read_pwd.c
@@ -0,0 +1,297 @@
+/*
+ * lib/krb5/os/read_pwd.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * libos: krb5_read_password for BSD 4.3
+ */
+
+#include "k5-int.h"
+
+#if !defined(_WIN32)
+#define DEFINED_KRB5_READ_PASSWORD
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#ifndef ECHO_PASSWORD
+#include <termios.h>
+#endif /* ECHO_PASSWORD */
+
+krb5_error_code
+krb5_read_password(krb5_context context, const char *prompt, const char *prompt2, char *return_pwd, unsigned int *size_return)
+{
+    krb5_data reply_data;      
+    krb5_prompt k5prompt;
+    krb5_error_code retval;
+    reply_data.length = *size_return; /* NB: size_return is also an input */
+    reply_data.data = return_pwd;
+    k5prompt.prompt = (char *)prompt;
+    k5prompt.hidden = 1;
+    k5prompt.reply = &reply_data;
+    retval =  krb5_prompter_posix(NULL,
+				  NULL, NULL, NULL, 1, &k5prompt);
+
+    if ((retval==0) && prompt2) {
+	krb5_data verify_data;
+	verify_data.data = malloc(*size_return);
+	verify_data.length = *size_return;
+	k5prompt.prompt = (char *)prompt2;
+	k5prompt.reply = &verify_data;
+	if (!verify_data.data)
+	    return ENOMEM;
+	retval = krb5_prompter_posix(NULL,
+				     NULL,NULL, NULL, 1, &k5prompt);
+	if (retval == 0) {
+	    /* compare */
+	    if (strncmp(return_pwd, (char *)verify_data.data, *size_return))
+		retval = KRB5_LIBOS_BADPWDMATCH;
+	}
+	free(verify_data.data);
+    }
+    if (!retval)
+	*size_return = k5prompt.reply->length;
+    else
+	memset(return_pwd, 0, *size_return);
+    return retval;
+}
+#endif
+
+#if defined(_WIN32)
+#define DEFINED_KRB5_READ_PASSWORD
+
+#include <io.h>
+
+typedef struct {
+    char *pwd_prompt;
+    char *pwd_prompt2;
+    char *pwd_return_pwd;
+    int  *pwd_size_return;
+} pwd_params;
+
+void center_dialog(HWND hwnd)
+{
+    int scrwidth, scrheight;
+    int dlgwidth, dlgheight;
+    RECT r;
+    HDC hdc;
+    
+    if (hwnd == NULL)
+	return;
+    
+    GetWindowRect(hwnd, &r);
+    dlgwidth = r.right  - r.left;
+    dlgheight = r.bottom - r.top ;
+    hdc = GetDC(NULL);
+    scrwidth = GetDeviceCaps(hdc, HORZRES);
+    scrheight = GetDeviceCaps(hdc, VERTRES);
+    ReleaseDC(NULL, hdc);
+    r.left = (scrwidth - dlgwidth) / 2;
+    r.top  = (scrheight - dlgheight) / 2;
+    MoveWindow(hwnd, r.left, r.top, dlgwidth, dlgheight, TRUE);
+}
+
+#ifdef _WIN32
+static krb5_error_code
+read_console_password(
+    krb5_context	context,
+    const char		* prompt,
+    const char		* prompt2,
+    char		* password,
+    int			* pwsize)
+{
+    HANDLE		handle;
+    DWORD		old_mode, new_mode;
+    char		*tmpstr = 0;
+    char		*ptr;
+    int			scratchchar;
+    krb5_error_code	errcode = 0;
+
+    handle = GetStdHandle(STD_INPUT_HANDLE);
+    if (handle == INVALID_HANDLE_VALUE)
+	return ENOTTY;
+    if (!GetConsoleMode(handle, &old_mode))
+	return ENOTTY;
+
+    new_mode = old_mode;
+    new_mode |=  ( ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT );
+    new_mode &= ~( ENABLE_ECHO_INPUT );
+
+    if (!SetConsoleMode(handle, new_mode))
+	return ENOTTY;
+
+    (void) fputs(prompt, stdout);
+    (void) fflush(stdout);
+    (void) memset(password, 0, *pwsize);
+
+    if (fgets(password, *pwsize, stdin) == NULL) {
+	(void) putchar('\n');
+	errcode = KRB5_LIBOS_CANTREADPWD;
+	goto cleanup;
+    }
+    (void) putchar('\n');
+
+    if ((ptr = strchr(password, '\n')))
+	*ptr = '\0';
+    else /* need to flush */
+	do {
+	    scratchchar = getchar();
+	} while (scratchchar != EOF && scratchchar != '\n');
+
+    if (prompt2) {
+	if (! (tmpstr = (char *)malloc(*pwsize))) {
+	    errcode = ENOMEM;
+	    goto cleanup;
+	}
+	(void) fputs(prompt2, stdout);
+	(void) fflush(stdout);
+	if (fgets(tmpstr, *pwsize, stdin) == NULL) {
+	    (void) putchar('\n');
+	    errcode = KRB5_LIBOS_CANTREADPWD;
+	    goto cleanup;
+	}
+	(void) putchar('\n');
+
+	if ((ptr = strchr(tmpstr, '\n')))
+	    *ptr = '\0';
+	else /* need to flush */
+	    do {
+		scratchchar = getchar();
+	    } while (scratchchar != EOF && scratchchar != '\n');
+
+	if (strncmp(password, tmpstr, *pwsize)) {
+	    errcode = KRB5_LIBOS_BADPWDMATCH;
+	    goto cleanup;
+	}
+    }
+
+cleanup:
+    (void) SetConsoleMode(handle, old_mode);
+    if (tmpstr) {
+	(void) memset(tmpstr, 0, *pwsize);
+	(void) free(tmpstr);
+    }
+    if (errcode)
+	(void) memset(password, 0, *pwsize);
+    else
+	*pwsize = strlen(password);
+    return errcode;
+}
+#endif
+
+static int CALLBACK
+read_pwd_proc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    pwd_params *dp;
+    
+    switch(msg) {
+    case WM_INITDIALOG:
+	dp = (pwd_params *) lParam;
+	SetWindowLongPtr(hdlg, DWLP_USER, lParam);
+	SetDlgItemText(hdlg, ID_READ_PWD_PROMPT, dp->pwd_prompt);
+	SetDlgItemText(hdlg, ID_READ_PWD_PROMPT2, dp->pwd_prompt2);
+	SetDlgItemText(hdlg, ID_READ_PWD_PWD, "");
+	center_dialog(hdlg);
+	return TRUE;
+
+    case WM_COMMAND:
+	dp = (pwd_params *) GetWindowLongPtr(hdlg, DWLP_USER);
+        switch (wParam) {
+	case IDOK:
+	    *(dp->pwd_size_return) =
+		GetDlgItemText(hdlg, ID_READ_PWD_PWD, 
+			       dp->pwd_return_pwd, *(dp->pwd_size_return));
+	    EndDialog(hdlg, TRUE);
+	    break;
+	    
+	case IDCANCEL:
+	    memset(dp->pwd_return_pwd, 0 , *(dp->pwd_size_return));
+	    *(dp->pwd_size_return) = 0;
+	    EndDialog(hdlg, FALSE);
+	    break;
+        }
+        return TRUE;
+ 
+    default:
+        return FALSE;
+    }
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_read_password(context, prompt, prompt2, return_pwd, size_return)
+    krb5_context context;
+    const char *prompt;
+    const char *prompt2;
+    char *return_pwd;
+    int *size_return;
+{
+    DLGPROC dlgproc;
+    HINSTANCE hinst;
+    pwd_params dps;
+    int rc;
+
+#ifdef _WIN32
+    if (_isatty(_fileno(stdin)))
+	return(read_console_password
+	       (context, prompt, prompt2, return_pwd, size_return));
+#endif
+
+    dps.pwd_prompt = prompt;
+    dps.pwd_prompt2 = prompt2;
+    dps.pwd_return_pwd = return_pwd;
+    dps.pwd_size_return = size_return;
+
+    hinst = get_lib_instance();
+#ifdef _WIN32
+    dlgproc = read_pwd_proc;
+#else
+    dlgproc = (FARPROC) MakeProcInstance(read_pwd_proc, hinst);
+#endif
+    rc = DialogBoxParam(hinst, MAKEINTRESOURCE(ID_READ_PWD_DIALOG), 0,
+			dlgproc, (LPARAM) &dps);
+#ifndef _WIN32
+    FreeProcInstance ((FARPROC) dlgproc);
+#endif
+    return 0;
+}
+#endif
+
+#ifndef DEFINED_KRB5_READ_PASSWORD
+#define DEFINED_KRB5_READ_PASSWORD
+/*
+ * Don't expect to be called, just define it for sanity and the linker.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_read_password(context, prompt, prompt2, return_pwd, size_return)
+    krb5_context context;
+    const char *prompt;
+    const char *prompt2;
+    char *return_pwd;
+    int *size_return;
+{
+   *size_return = 0;
+   return KRB5_LIBOS_CANTREADPWD;
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/os/realm_dom.c b/krb5-1-6/src/lib/krb5/os/realm_dom.c
new file mode 100644
index 000000000..d7a4be7db
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/realm_dom.c
@@ -0,0 +1,67 @@
+/*
+ * lib/krb5/os/realm_dom.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_get_realm_domain()
+ */
+
+
+/*
+ * Determines the proper domain name for a realm.  This is mainly so that
+ * a krb4 principal can be converted properly into a krb5 principal.
+ * Currently, the same style of mapping file used in krb4.
+ *
+ * If realm is NULL, this function will assume the default realm
+ * of the local host.
+ *
+ * The returned domain is allocated, and must be freed by the caller.
+ *
+ * This was hacked together from krb5_get_host_realm().
+ */
+
+#include "k5-int.h"
+#include <ctype.h>
+#include <stdio.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_realm_domain(krb5_context context, const char *realm, char **domain)
+{
+    krb5_error_code retval;
+    char *temp_domain = 0;
+
+    retval = profile_get_string(context->profile, "realms", realm,
+			       "default_domain", realm, &temp_domain);
+    if (!retval && temp_domain)
+    {
+        *domain = malloc(strlen(temp_domain) + 1);
+        if (!*domain) {
+            retval = ENOMEM;
+        } else {
+            strcpy(*domain, temp_domain);
+        }
+        profile_release_string(temp_domain);
+    }
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/realm_iter.c b/krb5-1-6/src/lib/krb5/os/realm_iter.c
new file mode 100644
index 000000000..0beaa2f46
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/realm_iter.c
@@ -0,0 +1,60 @@
+/*
+ * lib/krb5/os/realm_init.c
+ *
+ * Copyright 1998 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * krb5_realm_iterate()
+ */
+
+#include "k5-int.h"
+#include <ctype.h>
+#include <stdio.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5_realm_iterator_create(krb5_context context, void **iter_p)
+{
+    static const char *const names[] = { "realms", 0 };
+	
+    return profile_iterator_create(context->profile, names,
+				   PROFILE_ITER_LIST_SECTION |
+				   PROFILE_ITER_SECTIONS_ONLY,
+				   iter_p);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_realm_iterator(krb5_context context, void **iter_p, char **ret_realm)
+{
+    return profile_iterator(iter_p, ret_realm, 0);
+}
+
+void KRB5_CALLCONV
+krb5_realm_iterator_free(krb5_context context, void **iter_p)
+{
+    profile_iterator_free(iter_p);
+}
+
+void KRB5_CALLCONV
+krb5_free_realm_string(krb5_context context, char *str)
+{
+    profile_release_string(str);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/ref_std_conf.out b/krb5-1-6/src/lib/krb5/os/ref_std_conf.out
new file mode 100644
index 000000000..96349468c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/ref_std_conf.out
@@ -0,0 +1,13 @@
+krb5_get_default_realm() returned 'DEFAULT.REALM.TST'
+krb5_set_default_realm(NEW.DEFAULT.REALM)
+krb5_get_default_realm() returned 'NEW.DEFAULT.REALM'
+krb_get_krbhst(IGGY.ORG) returned: 'KERBEROS.IGGY.ORG' 'KERBEROS-B.IGGY.ORG'
+krb_get_krbhst(DEFAULT_REALM.TST) returned: 'FIRST.KDC.HOST' 'SECOND.KDC.HOST'
+krb5_get_realm_domain(DEFAULT_REALM.TST) returned 'MIT.EDU'
+krb_get_host_realm(bad.idea) returned: 'US.GOV'
+krb_get_host_realm(itar.bad.idea) returned: 'NSA.GOV'
+krb_get_host_realm(really.BAD.IDEA.) returned: 'NSA.GOV'
+krb_get_host_realm(clipper.bad.idea) returned: 'NIST.GOV'
+krb_get_host_realm(KeYEsCrOW.BaD.IDea) returned: 'NSA.GOV'
+krb_get_host_realm(pgp.good.idea) returned: ''
+krb_get_host_realm(no_domain) returned: ''
diff --git a/krb5-1-6/src/lib/krb5/os/send524.c b/krb5-1-6/src/lib/krb5/os/send524.c
new file mode 100644
index 000000000..1792b4930
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/send524.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 1990,1991,1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Send a packet to a service and await a reply, using an exponential
+ * backoff retry algorithm.  This is based on krb5_sendto_kdc.
+ */
+
+/* Grab socket stuff.  This might want to go away later. */
+#include "fake-addrinfo.h" /* for custom addrinfo if needed */
+#include "k5-int.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "os-proto.h"
+
+/*
+ * krb524_sendto_kdc:
+ *
+ * A slightly modified version of krb5_sendto_kdc.
+ *
+ * send the formatted request 'message' to a KDC for realm 'realm' and
+ * return the response (if any) in 'reply'.
+ *
+ * If the message is sent and a response is received, 0 is returned,
+ * otherwise an error code is returned.
+ *
+ * The storage for 'reply' is allocated and should be freed by the caller
+ * when finished.
+ */
+
+krb5_error_code
+krb5int_524_sendto_kdc (context, message, realm, reply, addr, addrlen)
+    krb5_context context;
+    const krb5_data * message;
+    const krb5_data * realm;
+    krb5_data * reply;
+    struct sockaddr *addr;
+    socklen_t *addrlen;
+{
+#if defined(KRB5_KRB4_COMPAT) || defined(_WIN32) /* yuck! */
+    int i;
+    struct addrlist al = ADDRLIST_INIT;
+    struct servent *serv;
+    krb5_error_code retval;
+    int port;
+
+    /*
+     * find KDC location(s) for realm
+     */
+
+    serv = getservbyname(KRB524_SERVICE, "udp");
+    port = serv ? serv->s_port : htons (KRB524_PORT);
+
+    retval = krb5int_locate_server(context, realm, &al, locate_service_krb524,
+				   SOCK_DGRAM, PF_INET);
+    if (retval == KRB5_REALM_CANT_RESOLVE || retval == KRB5_REALM_UNKNOWN) {
+	/* Fallback heuristic: Assume krb524 port on every KDC might
+	   work.  */
+	retval = krb5_locate_kdc(context, realm, &al, 0, SOCK_DGRAM, PF_INET);
+	/*
+	 * Bash the ports numbers.
+	 */
+	if (retval == 0)
+	    for (i = 0; i < al.naddrs; i++) {
+		al.addrs[i].ai->ai_socktype = SOCK_DGRAM;
+		if (al.addrs[i].ai->ai_family == AF_INET)
+		    sa2sin (al.addrs[i].ai->ai_addr)->sin_port = port;
+	    }
+    }
+    if (retval)
+	return retval;
+    if (al.naddrs == 0)
+	return KRB5_REALM_UNKNOWN;
+
+    retval = krb5int_sendto (context, message, &al, NULL, reply, addr, addrlen, NULL, 0, NULL, NULL, NULL);
+    krb5int_free_addrlist (&al);
+    return retval;
+#else
+    return KRB524_KRB4_DISABLED;
+#endif
+}
diff --git a/krb5-1-6/src/lib/krb5/os/sendto_kdc.c b/krb5-1-6/src/lib/krb5/os/sendto_kdc.c
new file mode 100644
index 000000000..4dfc1ef6a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/sendto_kdc.c
@@ -0,0 +1,1322 @@
+/*
+ * lib/krb5/os/sendto_kdc.c
+ *
+ * Copyright 1990,1991,2001,2002,2004,2005,2007 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Send packet to KDC for realm; wait for response, retransmitting
+ * as necessary.
+ */
+
+#include "fake-addrinfo.h"
+#include "k5-int.h"
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#include "os-proto.h"
+#ifdef _WIN32
+#include <sys/timeb.h>
+#endif
+
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+
+#ifndef _WIN32
+/* For FIONBIO.  */
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#endif
+
+#define MAX_PASS		    3
+#define DEFAULT_UDP_PREF_LIMIT	 1465
+#define HARD_UDP_LIMIT		32700 /* could probably do 64K-epsilon ? */
+
+#undef DEBUG
+
+#ifdef DEBUG
+int krb5int_debug_sendto_kdc = 0;
+#define debug krb5int_debug_sendto_kdc
+
+static void default_debug_handler (const void *data, size_t len)
+{
+#if 0
+    FILE *logfile;
+    logfile = fopen("/tmp/sendto_kdc.log", "a");
+    if (logfile == NULL)
+	return;
+    fwrite(data, 1, len, logfile);
+    fclose(logfile);
+#else
+    fwrite(data, 1, len, stderr);
+    /* stderr is unbuffered */
+#endif
+}
+
+void (*krb5int_sendtokdc_debug_handler) (const void *, size_t) = default_debug_handler;
+
+static void put(const void *ptr, size_t len)
+{
+    (*krb5int_sendtokdc_debug_handler)(ptr, len);
+}
+static void putstr(const char *str)
+{
+    put(str, strlen(str));
+}
+#else
+void (*krb5int_sendtokdc_debug_handler) (const void *, size_t) = 0;
+#endif
+
+#define dprint krb5int_debug_fprint
+ void
+krb5int_debug_fprint (const char *fmt, ...)
+{
+#ifdef DEBUG
+    va_list args;
+
+    /* Temporaries for variable arguments, etc.  */
+    krb5_error_code kerr;
+    int err;
+    fd_set *rfds, *wfds, *xfds;
+    int i;
+    int maxfd;
+    struct timeval *tv;
+    struct addrinfo *ai;
+    const krb5_data *d;
+    char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV];
+    const char *p;
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+    char tmpbuf[max(NI_MAXHOST + NI_MAXSERV + 30, 200)];
+
+    if (!krb5int_debug_sendto_kdc)
+	return;
+
+    va_start(args, fmt);
+
+#define putf(FMT,X)	(sprintf(tmpbuf,FMT,X),putstr(tmpbuf))
+
+    for (; *fmt; fmt++) {
+	if (*fmt != '%') {
+	    /* Possible optimization: Look for % and print all chars
+	       up to it in one call.  */
+	    put(fmt, 1);
+	    continue;
+	}
+	/* After this, always processing a '%' sequence.  */
+	fmt++;
+	switch (*fmt) {
+	case 0:
+	default:
+	    abort();
+	case 'E':
+	    /* %E => krb5_error_code */
+	    kerr = va_arg(args, krb5_error_code);
+	    sprintf(tmpbuf, "%lu/", (unsigned long) kerr);
+	    putstr(tmpbuf);
+	    p = error_message(kerr);
+	    putstr(p);
+	    break;
+	case 'm':
+	    /* %m => errno value (int) */
+	    /* Like syslog's %m except the errno value is passed in
+	       rather than the current value.  */
+	    err = va_arg(args, int);
+	    putf("%d/", err);
+	    p = NULL;
+#ifdef HAVE_STRERROR_R
+	    if (strerror_r(err, tmpbuf, sizeof(tmpbuf)) == 0)
+		p = tmpbuf;
+#endif
+	    if (p == NULL)
+		p = strerror(err);
+	    putstr(p);
+	    break;
+	case 'F':
+	    /* %F => fd_set *, fd_set *, fd_set *, int */
+	    rfds = va_arg(args, fd_set *);
+	    wfds = va_arg(args, fd_set *);
+	    xfds = va_arg(args, fd_set *);
+	    maxfd = va_arg(args, int);
+
+	    for (i = 0; i < maxfd; i++) {
+		int r = FD_ISSET(i, rfds);
+		int w = wfds && FD_ISSET(i, wfds);
+		int x = xfds && FD_ISSET(i, xfds);
+		if (r || w || x) {
+		    putf(" %d", i);
+		    if (r)
+			putstr("r");
+		    if (w)
+			putstr("w");
+		    if (x)
+			putstr("x");
+		}
+	    }
+	    putstr(" ");
+	    break;
+	case 's':
+	    /* %s => char * */
+	    p = va_arg(args, const char *);
+	    putstr(p);
+	    break;
+	case 't':
+	    /* %t => struct timeval * */
+	    tv = va_arg(args, struct timeval *);
+	    if (tv) {
+		sprintf(tmpbuf, "%ld.%06ld",
+			(long) tv->tv_sec, (long) tv->tv_usec);
+		putstr(tmpbuf);
+	    } else
+		putstr("never");
+	    break;
+	case 'd':
+	    /* %d => int */
+	    putf("%d", va_arg(args, int));
+	    break;
+	case 'p':
+	    /* %p => pointer */
+	    putf("%p", va_arg(args, void*));
+	    break;
+	case 'A':
+	    /* %A => addrinfo */
+	    ai = va_arg(args, struct addrinfo *);
+	    if (ai->ai_socktype == SOCK_DGRAM)
+		strcpy(tmpbuf, "dgram");
+	    else if (ai->ai_socktype == SOCK_STREAM)
+		strcpy(tmpbuf, "stream");
+	    else
+		sprintf(tmpbuf, "socktype%d", ai->ai_socktype);
+	    if (0 != getnameinfo (ai->ai_addr, ai->ai_addrlen,
+				  addrbuf, sizeof (addrbuf),
+				  portbuf, sizeof (portbuf),
+				  NI_NUMERICHOST | NI_NUMERICSERV)) {
+		if (ai->ai_addr->sa_family == AF_UNSPEC)
+		    strcpy(tmpbuf + strlen(tmpbuf), " AF_UNSPEC");
+		else
+		    sprintf(tmpbuf + strlen(tmpbuf), " af%d", ai->ai_addr->sa_family);
+	    } else
+		sprintf(tmpbuf + strlen(tmpbuf), " %s.%s", addrbuf, portbuf);
+	    putstr(tmpbuf);
+	    break;
+	case 'D':
+	    /* %D => krb5_data * */
+	    d = va_arg(args, krb5_data *);
+	    /* may not be nul-terminated */
+	    put(d->data, d->length);
+	    break;
+	}
+    }
+    va_end(args);
+#endif
+}
+
+#define print_addrlist krb5int_print_addrlist
+static void
+print_addrlist (const struct addrlist *a)
+{
+    int i;
+    dprint("%d{", a->naddrs);
+    for (i = 0; i < a->naddrs; i++)
+	dprint("%s%p=%A", i ? "," : "", (void*)a->addrs[i].ai, a->addrs[i].ai);
+    dprint("}");
+}
+
+static int
+merge_addrlists (struct addrlist *dest, struct addrlist *src)
+{
+    /* Wouldn't it be nice if we could filter out duplicates?  The
+       alloc/free handling makes that pretty difficult though.  */
+    int err, i;
+
+    dprint("merging addrlists:\n\tlist1: ");
+    for (i = 0; i < dest->naddrs; i++)
+	dprint(" %A", dest->addrs[i].ai);
+    dprint("\n\tlist2: ");
+    for (i = 0; i < src->naddrs; i++)
+	dprint(" %A", src->addrs[i].ai);
+    dprint("\n");
+
+    err = krb5int_grow_addrlist (dest, src->naddrs);
+    if (err)
+	return err;
+    for (i = 0; i < src->naddrs; i++) {
+	dest->addrs[dest->naddrs + i] = src->addrs[i];
+	src->addrs[i].ai = 0;
+	src->addrs[i].freefn = 0;
+    }
+    dest->naddrs += i;
+    src->naddrs = 0;
+
+    dprint("\tout:   ");
+    for (i = 0; i < dest->naddrs; i++)
+	dprint(" %A", dest->addrs[i].ai);
+    dprint("\n");
+
+    return 0;
+}
+
+static int
+in_addrlist (struct addrinfo *thisaddr, struct addrlist *list)
+{
+    int i;
+    for (i = 0; i < list->naddrs; i++) {
+	if (thisaddr->ai_addrlen == list->addrs[i].ai->ai_addrlen
+	    && !memcmp(thisaddr->ai_addr, list->addrs[i].ai->ai_addr,
+		       thisaddr->ai_addrlen))
+	    return 1;
+    }
+    return 0;
+}
+
+static int
+check_for_svc_unavailable (krb5_context context,
+			   const krb5_data *reply,
+			   void *msg_handler_data)
+{
+    krb5_error_code *retval = (krb5_error_code *)msg_handler_data;
+
+    *retval = 0;
+
+    if (krb5_is_krb_error(reply)) {
+	krb5_error *err_reply;
+
+	if (decode_krb5_error(reply, &err_reply) == 0) {
+	    *retval = err_reply->error;
+	    krb5_free_error(context, err_reply);
+
+	    /* Returning 0 means continue to next KDC */
+	    return (*retval != KDC_ERR_SVC_UNAVAILABLE);
+	}
+    }
+
+    return 1;
+}
+
+/*
+ * send the formatted request 'message' to a KDC for realm 'realm' and
+ * return the response (if any) in 'reply'.
+ *
+ * If the message is sent and a response is received, 0 is returned,
+ * otherwise an error code is returned.
+ *
+ * The storage for 'reply' is allocated and should be freed by the caller
+ * when finished.
+ */
+
+krb5_error_code
+krb5_sendto_kdc (krb5_context context, const krb5_data *message,
+		 const krb5_data *realm, krb5_data *reply,
+		 int *use_master, int tcp_only)
+{
+    krb5_error_code retval, retval2;
+    struct addrlist addrs;
+    int socktype1 = 0, socktype2 = 0, addr_used;
+
+    /*
+     * find KDC location(s) for realm
+     */
+
+    /*
+     * BUG: This code won't return "interesting" errors (e.g., out of mem,
+     * bad config file) from locate_kdc.  KRB5_REALM_CANT_RESOLVE can be
+     * ignored from one query of two, but if only one query is done, or
+     * both return that error, it should be returned to the caller.  Also,
+     * "interesting" errors (not KRB5_KDC_UNREACH) from sendto_{udp,tcp}
+     * should probably be returned as well.
+     */
+
+    dprint("krb5_sendto_kdc(%d@%p, \"%D\", use_master=%d, tcp_only=%d)\n",
+	   message->length, message->data, realm, *use_master, tcp_only);
+
+    if (!tcp_only && context->udp_pref_limit < 0) {
+	int tmp;
+	retval = profile_get_integer(context->profile,
+				     "libdefaults", "udp_preference_limit", 0,
+				     DEFAULT_UDP_PREF_LIMIT, &tmp);
+	if (retval)
+	    return retval;
+	if (tmp < 0)
+	    tmp = DEFAULT_UDP_PREF_LIMIT;
+	else if (tmp > HARD_UDP_LIMIT)
+	    /* In the unlikely case that a *really* big value is
+	       given, let 'em use as big as we think we can
+	       support.  */
+	    tmp = HARD_UDP_LIMIT;
+	context->udp_pref_limit = tmp;
+    }
+
+    retval = (*use_master ? KRB5_KDC_UNREACH : KRB5_REALM_UNKNOWN);
+
+    if (tcp_only)
+	socktype1 = SOCK_STREAM, socktype2 = 0;
+    else if (message->length <= context->udp_pref_limit)
+	socktype1 = SOCK_DGRAM, socktype2 = SOCK_STREAM;
+    else
+	socktype1 = SOCK_STREAM, socktype2 = SOCK_DGRAM;
+
+    retval = krb5_locate_kdc(context, realm, &addrs, *use_master, socktype1, 0);
+    if (socktype2) {
+	struct addrlist addrs2;
+
+	retval2 = krb5_locate_kdc(context, realm, &addrs2, *use_master,
+				  socktype2, 0);
+#if 0
+	if (retval2 == 0) {
+	    (void) merge_addrlists(&addrs, &addrs2);
+	    krb5int_free_addrlist(&addrs2);
+	    retval = 0;
+	} else if (retval == KRB5_REALM_CANT_RESOLVE) {
+	    retval = retval2;
+	}
+#else
+	retval = retval2;
+	if (retval == 0) {
+	    (void) merge_addrlists(&addrs, &addrs2);
+	    krb5int_free_addrlist(&addrs2);
+	}
+#endif
+    }
+
+    if (addrs.naddrs > 0) {
+	krb5_error_code err = 0;
+
+        retval = krb5int_sendto (context, message, &addrs, 0, reply, 0, 0,
+				 0, 0, &addr_used, check_for_svc_unavailable, &err);
+	switch (retval) {
+	case 0:
+            /*
+             * Set use_master to 1 if we ended up talking to a master when
+             * we didn't explicitly request to
+             */
+            if (*use_master == 0) {
+                struct addrlist addrs3;
+                retval = krb5_locate_kdc(context, realm, &addrs3, 1, 
+                                         addrs.addrs[addr_used].ai->ai_socktype,
+                                         addrs.addrs[addr_used].ai->ai_family);
+                if (retval == 0) {
+		    if (in_addrlist(addrs.addrs[addr_used].ai, &addrs3))
+			*use_master = 1;
+                    krb5int_free_addrlist (&addrs3);
+                }
+            }
+            krb5int_free_addrlist (&addrs);
+            return 0;
+	default:
+	    break;
+	    /* Cases here are for constructing useful error messages.  */
+	case KRB5_KDC_UNREACH:
+	    if (err == KDC_ERR_SVC_UNAVAILABLE) {
+		retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
+	    } else {
+		krb5_set_error_message(context, retval,
+				       "Cannot contact any KDC for realm '%.*s'",
+				       realm->length, realm->data);
+	    }
+	    break;
+	}
+        krb5int_free_addrlist (&addrs);
+    }
+    return retval;
+}
+
+#ifdef DEBUG
+
+#ifdef _WIN32
+#define dperror(MSG) \
+	 dprint("%s: an error occurred ... "			\
+		"\tline=%d errno=%m socketerrno=%m\n",		\
+		(MSG), __LINE__, errno, SOCKET_ERRNO)
+#else
+#define dperror(MSG) dprint("%s: %m\n", MSG, errno)
+#endif
+#define dfprintf(ARGLIST) (debug ? fprintf ARGLIST : 0)
+
+#else /* ! DEBUG */
+
+#define dperror(MSG) ((void)(MSG))
+#define dfprintf(ARGLIST) ((void)0)
+
+#endif
+
+/*
+ * Notes:
+ *
+ * Getting "connection refused" on a connected UDP socket causes
+ * select to indicate write capability on UNIX, but only shows up
+ * as an exception on Windows.  (I don't think any UNIX system flags
+ * the error as an exception.)  So we check for both, or make it
+ * system-specific.
+ *
+ * Always watch for responses from *any* of the servers.  Eventually
+ * fix the UDP code to do the same.
+ *
+ * To do:
+ * - TCP NOPUSH/CORK socket options?
+ * - error codes that don't suck
+ * - getsockopt(SO_ERROR) to check connect status
+ * - handle error RESPONSE_TOO_BIG from UDP server and use TCP
+ *   connections already in progress
+ */
+
+#include "cm.h"
+
+static int getcurtime (struct timeval *tvp)
+{
+#ifdef _WIN32
+    struct _timeb tb;
+    _ftime(&tb);
+    tvp->tv_sec = tb.time;
+    tvp->tv_usec = tb.millitm * 1000;
+    /* Can _ftime fail?  */
+    return 0;
+#else
+    if (gettimeofday(tvp, 0)) {
+	dperror("gettimeofday");
+	return errno;
+    }
+    return 0;
+#endif
+}
+
+/*
+ * Call select and return results.
+ * Input: interesting file descriptors and absolute timeout
+ * Output: select return value (-1 or num fds ready) and fd_sets
+ * Return: 0 (for i/o available or timeout) or error code.
+ */
+krb5_error_code
+krb5int_cm_call_select (const struct select_state *in,
+			struct select_state *out, int *sret)
+{
+    struct timeval now, *timo;
+    krb5_error_code e;
+
+    *out = *in;
+    e = getcurtime(&now);
+    if (e)
+	return e;
+    if (out->end_time.tv_sec == 0)
+	timo = 0;
+    else {
+	timo = &out->end_time;
+	out->end_time.tv_sec -= now.tv_sec;
+	out->end_time.tv_usec -= now.tv_usec;
+	if (out->end_time.tv_usec < 0) {
+	    out->end_time.tv_usec += 1000000;
+	    out->end_time.tv_sec--;
+	}
+	if (out->end_time.tv_sec < 0) {
+	    *sret = 0;
+	    return 0;
+	}
+    }
+    dprint("selecting on max=%d sockets [%F] timeout %t\n",
+	   out->max,
+	   &out->rfds, &out->wfds, &out->xfds, out->max,
+	   timo);
+    *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, timo);
+    e = SOCKET_ERRNO;
+
+    dprint("select returns %d", *sret);
+    if (*sret < 0)
+	dprint(", error = %E\n", e);
+    else if (*sret == 0)
+	dprint(" (timeout)\n");
+    else
+	dprint(":%F\n", &out->rfds, &out->wfds, &out->xfds, out->max);
+
+    if (*sret < 0)
+	return e;
+    return 0;
+}
+
+static int service_tcp_fd (struct conn_state *conn,
+			   struct select_state *selstate, int ssflags);
+static int service_udp_fd (struct conn_state *conn,
+			   struct select_state *selstate, int ssflags);
+
+static void
+set_conn_state_msg_length (struct conn_state *state, const krb5_data *message)
+{
+    if (!message || message->length == 0) 
+	return;
+
+    if (!state->is_udp) {
+
+	state->x.out.msg_len_buf[0] = (message->length >> 24) & 0xff;
+	state->x.out.msg_len_buf[1] = (message->length >> 16) & 0xff;
+	state->x.out.msg_len_buf[2] = (message->length >>  8) & 0xff;
+	state->x.out.msg_len_buf[3] =  message->length        & 0xff;
+
+	SG_SET(&state->x.out.sgbuf[0], state->x.out.msg_len_buf, 4);
+	SG_SET(&state->x.out.sgbuf[1], message->data, message->length);
+   	state->x.out.sg_count = 2;
+
+    } else {
+
+	SG_SET(&state->x.out.sgbuf[0], message->data, message->length);
+	SG_SET(&state->x.out.sgbuf[1], 0, 0);
+	state->x.out.sg_count = 1;
+
+    }
+}
+
+
+
+static int
+setup_connection (struct conn_state *state, struct addrinfo *ai,
+		  const krb5_data *message, char **udpbufp)
+{
+    state->state = INITIALIZING;
+    state->err = 0;
+    state->x.out.sgp = state->x.out.sgbuf;
+    state->addr = ai;
+    state->fd = INVALID_SOCKET;
+    SG_SET(&state->x.out.sgbuf[1], 0, 0);
+    if (ai->ai_socktype == SOCK_STREAM) {
+	/*
+	SG_SET(&state->x.out.sgbuf[0], message_len_buf, 4);
+	SG_SET(&state->x.out.sgbuf[1], message->data, message->length);
+	state->x.out.sg_count = 2;
+	*/
+	
+	state->is_udp = 0;
+	state->service = service_tcp_fd;
+	set_conn_state_msg_length (state, message);
+    } else {
+	/*
+	SG_SET(&state->x.out.sgbuf[0], message->data, message->length);
+	SG_SET(&state->x.out.sgbuf[1], 0, 0);
+	state->x.out.sg_count = 1;
+	*/
+
+	state->is_udp = 1;
+	state->service = service_udp_fd;
+	set_conn_state_msg_length (state, message);
+
+	if (*udpbufp == 0) {
+	    *udpbufp = malloc(krb5_max_dgram_size);
+	    if (*udpbufp == 0) {
+		dperror("malloc(krb5_max_dgram_size)");
+		(void) closesocket(state->fd);
+		state->fd = INVALID_SOCKET;
+		state->state = FAILED;
+		return 1;
+	    }
+	}
+	state->x.in.buf = *udpbufp;
+	state->x.in.bufsize = krb5_max_dgram_size;
+    }
+    return 0;
+}
+
+static int
+start_connection (struct conn_state *state, 
+		  struct select_state *selstate, 
+		  struct sendto_callback_info* callback_info,
+                  krb5_data* callback_buffer)
+{
+    int fd, e;
+    struct addrinfo *ai = state->addr;
+
+    dprint("start_connection(@%p)\ngetting %s socket in family %d...", state,
+	   ai->ai_socktype == SOCK_STREAM ? "stream" : "dgram", ai->ai_family);
+    fd = socket(ai->ai_family, ai->ai_socktype, 0);
+    if (fd == INVALID_SOCKET) {
+	state->err = SOCKET_ERRNO;
+	dprint("socket: %m creating with af %d\n", state->err, ai->ai_family);
+	return -1;		/* try other hosts */
+    }
+    /* Make it non-blocking.  */
+    if (ai->ai_socktype == SOCK_STREAM) {
+	static const int one = 1;
+	static const struct linger lopt = { 0, 0 };
+
+	if (ioctlsocket(fd, FIONBIO, (const void *) &one))
+	    dperror("sendto_kdc: ioctl(FIONBIO)");
+	if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lopt, sizeof(lopt)))
+	    dperror("sendto_kdc: setsockopt(SO_LINGER)");
+    }
+
+    /* Start connecting to KDC.  */
+    dprint(" fd %d; connecting to %A...\n", fd, ai);
+    e = connect(fd, ai->ai_addr, ai->ai_addrlen);
+    if (e != 0) {
+	/*
+	 * This is the path that should be followed for non-blocking
+	 * connections.
+	 */
+	if (SOCKET_ERRNO == EINPROGRESS || SOCKET_ERRNO == EWOULDBLOCK) {
+	    state->state = CONNECTING;
+	    state->fd = fd;
+	} else {
+	    dprint("connect failed: %m\n", SOCKET_ERRNO);
+	    (void) closesocket(fd);
+	    state->err = SOCKET_ERRNO;
+	    state->state = FAILED;
+	    return -2;
+	}
+    } else {
+	/*
+	 * Connect returned zero even though we tried to make it
+	 * non-blocking, which should have caused it to return before
+	 * finishing the connection.  Oh well.  Someone's network
+	 * stack is broken, but if they gave us a connection, use it.
+	 */
+	state->state = WRITING;
+	state->fd = fd;
+    }
+    dprint("new state = %s\n", state_strings[state->state]);
+
+
+    /*
+     * Here's where KPASSWD callback gets the socket information it needs for
+     * a kpasswd request
+     */
+    if (callback_info) {
+
+	e = callback_info->pfn_callback(state, 
+					callback_info->context, 
+					callback_buffer);
+	if (e != 0) {
+	    dprint("callback failed: %m\n", e);
+	    (void) closesocket(fd);
+	    state->err = e;
+	    state->fd = INVALID_SOCKET;
+	    state->state = FAILED;
+	    return -3;
+	}
+
+	dprint("callback %p (message=%d@%p)\n", 
+	       state,
+	       callback_buffer->length, 
+	       callback_buffer->data);
+
+	set_conn_state_msg_length( state, callback_buffer );
+    }
+
+    if (ai->ai_socktype == SOCK_DGRAM) {
+	/* Send it now.  */
+	int ret;
+	sg_buf *sg = &state->x.out.sgbuf[0];
+
+	dprint("sending %d bytes on fd %d\n", SG_LEN(sg), state->fd);
+	ret = send(state->fd, SG_BUF(sg), SG_LEN(sg), 0);
+	if (ret != SG_LEN(sg)) {
+	    dperror("sendto");
+	    (void) closesocket(state->fd);
+	    state->fd = INVALID_SOCKET;
+	    state->state = FAILED;
+	    return -4;
+	} else {
+	    state->state = READING;
+	}
+    }
+#ifdef DEBUG
+    if (debug) {
+	struct sockaddr_storage ss;
+	socklen_t sslen = sizeof(ss);
+	if (getsockname(state->fd, (struct sockaddr *)&ss, &sslen) == 0) {
+	    struct addrinfo hack_ai;
+	    memset(&hack_ai, 0, sizeof(hack_ai));
+	    hack_ai.ai_addr = (struct sockaddr *) &ss;
+	    hack_ai.ai_addrlen = sslen;
+	    hack_ai.ai_socktype = SOCK_DGRAM;
+	    hack_ai.ai_family = ai->ai_family;
+	    dprint("local socket address is %A\n", &hack_ai);
+	}
+    }
+#endif
+    FD_SET(state->fd, &selstate->rfds);
+    if (state->state == CONNECTING || state->state == WRITING)
+	FD_SET(state->fd, &selstate->wfds);
+    FD_SET(state->fd, &selstate->xfds);
+    if (selstate->max <= state->fd)
+	selstate->max = state->fd + 1;
+    selstate->nfds++;
+
+    dprint("new select vectors: %F\n",
+	   &selstate->rfds, &selstate->wfds, &selstate->xfds, selstate->max);
+
+    return 0;
+}
+
+/* Return 0 if we sent something, non-0 otherwise.
+   If 0 is returned, the caller should delay waiting for a response.
+   Otherwise, the caller should immediately move on to process the
+   next connection.  */
+static int
+maybe_send (struct conn_state *conn, 
+	    struct select_state *selstate, 
+	    struct sendto_callback_info* callback_info,
+	    krb5_data* callback_buffer)
+{
+    sg_buf *sg;
+
+    dprint("maybe_send(@%p) state=%s type=%s\n", conn,
+	   state_strings[conn->state],
+	   conn->is_udp ? "udp" : "tcp");
+    if (conn->state == INITIALIZING)
+	return start_connection(conn, selstate, callback_info, callback_buffer);
+
+    /* Did we already shut down this channel?  */
+    if (conn->state == FAILED) {
+	dprint("connection already closed\n");
+	return -1;
+    }
+
+    if (conn->addr->ai_socktype == SOCK_STREAM) {
+	dprint("skipping stream socket\n");
+	/* The select callback will handle flushing any data we
+	   haven't written yet, and we only write it once.  */
+	return -1;
+    }
+
+    /* UDP - Send message, possibly for the first time, possibly a
+       retransmit if a previous attempt timed out.  */
+    sg = &conn->x.out.sgbuf[0];
+    dprint("sending %d bytes on fd %d\n", SG_LEN(sg), conn->fd);
+    if (send(conn->fd, SG_BUF(sg), SG_LEN(sg), 0) != SG_LEN(sg)) {
+	dperror("send");
+	/* Keep connection alive, we'll try again next pass.
+
+	   Is this likely to catch any errors we didn't get from the
+	   select callbacks?  */
+	return -1;
+    }
+    /* Yay, it worked.  */
+    return 0;
+}
+
+static void
+kill_conn(struct conn_state *conn, struct select_state *selstate, int err)
+{
+    conn->state = FAILED;
+    shutdown(conn->fd, SHUTDOWN_BOTH);
+    FD_CLR(conn->fd, &selstate->rfds);
+    FD_CLR(conn->fd, &selstate->wfds);
+    FD_CLR(conn->fd, &selstate->xfds);
+    conn->err = err;
+    dprint("abandoning connection %d: %m\n", conn->fd, err);
+    /* Fix up max fd for next select call.  */
+    if (selstate->max == 1 + conn->fd) {
+	while (selstate->max > 0
+	       && ! FD_ISSET(selstate->max-1, &selstate->rfds)
+	       && ! FD_ISSET(selstate->max-1, &selstate->wfds)
+	       && ! FD_ISSET(selstate->max-1, &selstate->xfds))
+	    selstate->max--;
+	dprint("new max_fd + 1 is %d\n", selstate->max);
+    }
+    selstate->nfds--;
+}
+
+/* Check socket for error.  */
+static int
+get_so_error(int fd)
+{
+    int e, sockerr;
+    socklen_t sockerrlen;
+
+    sockerr = 0;
+    sockerrlen = sizeof(sockerr);
+    e = getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen);
+    if (e != 0) {
+	/* What to do now?  */
+	e = SOCKET_ERRNO;
+	dprint("getsockopt(SO_ERROR) on fd failed: %m\n", e);
+	return e;
+    }
+    return sockerr;
+}
+
+/* Return nonzero only if we're finished and the caller should exit
+   its loop.  This happens in two cases: We have a complete message,
+   or the socket has closed and no others are open.  */
+
+static int
+service_tcp_fd (struct conn_state *conn, struct select_state *selstate,
+		int ssflags)
+{
+    krb5_error_code e = 0;
+    int nwritten, nread;
+
+    if (!(ssflags & (SSF_READ|SSF_WRITE|SSF_EXCEPTION)))
+	abort();
+    switch (conn->state) {
+	SOCKET_WRITEV_TEMP tmp;
+
+    case CONNECTING:
+	if (ssflags & SSF_READ) {
+	    /* Bad -- the KDC shouldn't be sending to us first.  */
+	    e = EINVAL /* ?? */;
+	kill_conn:
+	    kill_conn(conn, selstate, e);
+	    if (e == EINVAL) {
+		closesocket(conn->fd);
+		conn->fd = INVALID_SOCKET;
+	    }
+	    return e == 0;
+	}
+	if (ssflags & SSF_EXCEPTION) {
+	handle_exception:
+	    e = get_so_error(conn->fd);
+	    if (e)
+		dprint("socket error on exception fd: %m", e);
+	    else
+		dprint("no socket error info available on exception fd");
+	    goto kill_conn;
+	}
+
+	/*
+	 * Connect finished -- but did it succeed or fail?
+	 * UNIX sets can_write if failed.
+	 * Call getsockopt to see if error pending.
+	 *
+	 * (For most UNIX systems it works to just try writing the
+	 * first time and detect an error.  But Bill Dodd at IBM
+	 * reports that some version of AIX, SIGPIPE can result.)
+	 */
+	e = get_so_error(conn->fd);
+	if (e) {
+	    dprint("socket error on write fd: %m", e);
+	    goto kill_conn;
+	}
+	conn->state = WRITING;
+	goto try_writing;
+
+    case WRITING:
+	if (ssflags & SSF_READ) {
+	    e = E2BIG;
+	    /* Bad -- the KDC shouldn't be sending anything yet.  */
+	    goto kill_conn;
+	}
+	if (ssflags & SSF_EXCEPTION)
+	    goto handle_exception;
+
+    try_writing:
+	dprint("trying to writev %d (%d bytes) to fd %d\n",
+	       conn->x.out.sg_count,
+	       ((conn->x.out.sg_count == 2 ? SG_LEN(&conn->x.out.sgp[1]) : 0)
+		+ SG_LEN(&conn->x.out.sgp[0])),
+	       conn->fd);
+	nwritten = SOCKET_WRITEV(conn->fd, conn->x.out.sgp,
+				 conn->x.out.sg_count, tmp);
+	if (nwritten < 0) {
+	    e = SOCKET_ERRNO;
+	    dprint("failed: %m\n", e);
+	    goto kill_conn;
+	}
+	dprint("wrote %d bytes\n", nwritten);
+	while (nwritten) {
+	    sg_buf *sgp = conn->x.out.sgp;
+	    if (nwritten < SG_LEN(sgp)) {
+		SG_ADVANCE(sgp, nwritten);
+		nwritten = 0;
+	    } else {
+		nwritten -= SG_LEN(conn->x.out.sgp);
+		conn->x.out.sgp++;
+		conn->x.out.sg_count--;
+		if (conn->x.out.sg_count == 0 && nwritten != 0)
+		    /* Wrote more than we wanted to?  */
+		    abort();
+	    }
+	}
+	if (conn->x.out.sg_count == 0) {
+	    /* Done writing, switch to reading.  */
+	    /* Don't call shutdown at this point because
+	     * some implementations cannot deal with half-closed connections.*/
+	    FD_CLR(conn->fd, &selstate->wfds);
+	    /* Q: How do we detect failures to send the remaining data
+	       to the remote side, since we're in non-blocking mode?
+	       Will we always get errors on the reading side?  */
+	    dprint("switching fd %d to READING\n", conn->fd);
+	    conn->state = READING;
+	    conn->x.in.bufsizebytes_read = 0;
+	    conn->x.in.bufsize = 0;
+	    conn->x.in.buf = 0;
+	    conn->x.in.pos = 0;
+	    conn->x.in.n_left = 0;
+	}
+	return 0;
+
+    case READING:
+	if (ssflags & SSF_EXCEPTION) {
+	    if (conn->x.in.buf) {
+		free(conn->x.in.buf);
+		conn->x.in.buf = 0;
+	    }
+	    goto handle_exception;
+	}
+
+	if (conn->x.in.bufsizebytes_read == 4) {
+	    /* Reading data.  */
+	    dprint("reading %d bytes of data from fd %d\n",
+		   (int) conn->x.in.n_left, conn->fd);
+	    nread = SOCKET_READ(conn->fd, conn->x.in.pos, conn->x.in.n_left);
+	    if (nread <= 0) {
+		e = nread ? SOCKET_ERRNO : ECONNRESET;
+		free(conn->x.in.buf);
+		conn->x.in.buf = 0;
+		goto kill_conn;
+	    }
+	    conn->x.in.n_left -= nread;
+	    conn->x.in.pos += nread;
+	    if (conn->x.in.n_left <= 0) {
+		/* We win!  */
+		return 1;
+	    }
+	} else {
+	    /* Reading length.  */
+	    nread = SOCKET_READ(conn->fd,
+				conn->x.in.bufsizebytes + conn->x.in.bufsizebytes_read,
+				4 - conn->x.in.bufsizebytes_read);
+	    if (nread < 0) {
+		e = SOCKET_ERRNO;
+		goto kill_conn;
+	    }
+	    conn->x.in.bufsizebytes_read += nread;
+	    if (conn->x.in.bufsizebytes_read == 4) {
+		unsigned long len;
+		len = conn->x.in.bufsizebytes[0];
+		len = (len << 8) + conn->x.in.bufsizebytes[1];
+		len = (len << 8) + conn->x.in.bufsizebytes[2];
+		len = (len << 8) + conn->x.in.bufsizebytes[3];
+		dprint("received length on fd %d is %d\n", conn->fd, (int)len);
+		/* Arbitrary 1M cap.  */
+		if (len > 1 * 1024 * 1024) {
+		    e = E2BIG;
+		    goto kill_conn;
+		}
+		conn->x.in.bufsize = conn->x.in.n_left = len;
+		conn->x.in.buf = conn->x.in.pos = malloc(len);
+		dprint("allocated %d byte buffer at %p\n", (int) len,
+		       conn->x.in.buf);
+		if (conn->x.in.buf == 0) {
+		    /* allocation failure */
+		    e = errno;
+		    goto kill_conn;
+		}
+	    }
+	}
+	break;
+
+    default:
+	abort();
+    }
+    return 0;
+}
+
+static int
+service_udp_fd(struct conn_state *conn, struct select_state *selstate,
+	       int ssflags)
+{
+    int nread;
+
+    if (!(ssflags & (SSF_READ|SSF_EXCEPTION)))
+	abort();
+    if (conn->state != READING)
+	abort();
+
+    nread = recv(conn->fd, conn->x.in.buf, conn->x.in.bufsize, 0);
+    if (nread < 0) {
+	kill_conn(conn, selstate, SOCKET_ERRNO);
+	return 0;
+    }
+    conn->x.in.pos = conn->x.in.buf + nread;
+    return 1;
+}
+
+static int
+service_fds (krb5_context context,
+	     struct select_state *selstate,
+	     struct conn_state *conns, size_t n_conns, int *winning_conn,
+	     struct select_state *seltemp,
+	     int (*msg_handler)(krb5_context, const krb5_data *, void *),
+	     void *msg_handler_data)
+{
+    int e, selret;
+
+    e = 0;
+    while (selstate->nfds > 0
+	   && (e = krb5int_cm_call_select(selstate, seltemp, &selret)) == 0) {
+	int i;
+
+	dprint("service_fds examining results, selret=%d\n", selret);
+
+	if (selret == 0)
+	    /* Timeout, return to caller.  */
+	    return 0;
+
+	/* Got something on a socket, process it.  */
+	for (i = 0; i <= selstate->max && selret > 0 && i < n_conns; i++) {
+	    int ssflags;
+
+	    if (conns[i].fd == INVALID_SOCKET)
+		continue;
+	    ssflags = 0;
+	    if (FD_ISSET(conns[i].fd, &seltemp->rfds))
+		ssflags |= SSF_READ, selret--;
+	    if (FD_ISSET(conns[i].fd, &seltemp->wfds))
+		ssflags |= SSF_WRITE, selret--;
+	    if (FD_ISSET(conns[i].fd, &seltemp->xfds))
+		ssflags |= SSF_EXCEPTION, selret--;
+	    if (!ssflags)
+		continue;
+
+	    dprint("handling flags '%s%s%s' on fd %d (%A) in state %s\n",
+		   (ssflags & SSF_READ) ? "r" : "",
+		   (ssflags & SSF_WRITE) ? "w" : "",
+		   (ssflags & SSF_EXCEPTION) ? "x" : "",
+		   conns[i].fd, conns[i].addr,
+		   state_strings[(int) conns[i].state]);
+
+	    if (conns[i].service (&conns[i], selstate, ssflags)) {
+		int stop = 1;
+
+		if (msg_handler != NULL) {
+		    krb5_data reply;
+
+		    reply.data = conns[i].x.in.buf;
+		    reply.length = conns[i].x.in.pos - conns[i].x.in.buf;
+
+		    stop = (msg_handler(context, &reply, msg_handler_data) != 0);
+		}
+
+		if (stop) {
+		    dprint("fd service routine says we're done\n");
+		    *winning_conn = i;
+		    return 1;
+		}
+	    }
+	}
+    }
+    if (e != 0) {
+	dprint("select returned %m\n", e);
+	*winning_conn = -1;
+	return 1;
+    }
+    return 0;
+}
+
+/*
+ * Current worst-case timeout behavior:
+ *
+ * First pass, 1s per udp or tcp server, plus 2s at end.
+ * Second pass, 1s per udp server, plus 4s.
+ * Third pass, 1s per udp server, plus 8s.
+ * Fourth => 16s, etc.
+ *
+ * Restated:
+ * Per UDP server, 1s per pass.
+ * Per TCP server, 1s.
+ * Backoff delay, 2**(P+1) - 2, where P is total number of passes.
+ *
+ * Total = 2**(P+1) + U*P + T - 2.
+ *
+ * If P=3, Total = 3*U + T + 14.
+ * If P=4, Total = 4*U + T + 30.
+ *
+ * Note that if you try to reach two ports (e.g., both 88 and 750) on
+ * one server, it counts as two.
+ */
+
+krb5_error_code
+krb5int_sendto (krb5_context context, const krb5_data *message,
+                const struct addrlist *addrs,
+		struct sendto_callback_info* callback_info, krb5_data *reply,
+		struct sockaddr *localaddr, socklen_t *localaddrlen,
+                struct sockaddr *remoteaddr, socklen_t *remoteaddrlen,
+		int *addr_used,
+		/* return 0 -> keep going, 1 -> quit */
+		int (*msg_handler)(krb5_context, const krb5_data *, void *),
+		void *msg_handler_data)
+{
+    int i, pass;
+    int delay_this_pass = 2;
+    krb5_error_code retval;
+    struct conn_state *conns;
+    krb5_data *callback_data = 0;
+    size_t n_conns, host;
+    struct select_state *sel_state;
+    struct timeval now;
+    int winning_conn = -1, e = 0;
+    char *udpbuf = 0;
+
+    if (message)
+	dprint("krb5int_sendto(message=%d@%p, addrlist=", message->length, message->data);
+    else
+	dprint("krb5int_sendto(callback=%p, addrlist=", callback_info);
+    print_addrlist(addrs);
+    dprint(")\n");
+
+    reply->data = 0;
+    reply->length = 0;
+
+    n_conns = addrs->naddrs;
+    conns = malloc(n_conns * sizeof(struct conn_state));
+    if (conns == NULL) {
+	return ENOMEM;
+    }
+
+    memset(conns, 0, n_conns * sizeof(struct conn_state));
+
+    if (callback_info) {
+	callback_data = malloc(n_conns * sizeof(krb5_data));
+	if (callback_data == NULL) {
+	    return ENOMEM;
+	}
+
+	memset(callback_data, 0, n_conns * sizeof(krb5_data));
+    }
+
+    for (i = 0; i < n_conns; i++) {
+	conns[i].fd = INVALID_SOCKET;
+    }
+
+    /* One for use here, listing all our fds in use, and one for
+       temporary use in service_fds, for the fds of interest.  */
+    sel_state = malloc(2 * sizeof(*sel_state));
+    if (sel_state == NULL) {
+	free(conns);
+	return ENOMEM;
+    }
+    sel_state->max = 0;
+    sel_state->nfds = 0;
+    sel_state->end_time.tv_sec = sel_state->end_time.tv_usec = 0;
+    FD_ZERO(&sel_state->rfds);
+    FD_ZERO(&sel_state->wfds);
+    FD_ZERO(&sel_state->xfds);
+
+
+    /* Set up connections.  */
+    for (host = 0; host < n_conns; host++) {
+	retval = setup_connection(&conns[host], 
+				  addrs->addrs[host].ai,
+				  message, 
+				  &udpbuf);
+	if (retval)
+	    continue;
+    }
+    for (pass = 0; pass < MAX_PASS; pass++) {
+	/* Possible optimization: Make only one pass if TCP only.
+	   Stop making passes if all UDP ports are closed down.  */
+	dprint("pass %d delay=%d\n", pass, delay_this_pass);
+	for (host = 0; host < n_conns; host++) {
+	    dprint("host %d\n", host);
+
+	    /* Send to the host, wait for a response, then move on. */
+	    if (maybe_send(&conns[host], 
+			   sel_state,
+			   callback_info,
+			   (callback_info ? &callback_data[host] : NULL)))
+		continue;
+
+	    retval = getcurtime(&now);
+	    if (retval)
+		goto egress;
+	    sel_state->end_time = now;
+	    sel_state->end_time.tv_sec += 1;
+	    e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+			    sel_state+1, msg_handler, msg_handler_data);
+	    if (e)
+		break;
+	    if (pass > 0 && sel_state->nfds == 0)
+		/*
+		 * After the first pass, if we close all fds, break
+		 * out right away.  During the first pass, it's okay,
+		 * we're probably about to open another connection.
+		 */
+		break;
+	}
+	if (e)
+	    break;
+	retval = getcurtime(&now);
+	if (retval)
+	    goto egress;
+	/* Possible optimization: Find a way to integrate this select
+	   call with the last one from the above loop, if the loop
+	   actually calls select.  */
+	sel_state->end_time.tv_sec += delay_this_pass;
+	e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+		        sel_state+1, msg_handler, msg_handler_data);
+	if (e)
+	    break;
+	if (sel_state->nfds == 0)
+	    break;
+	delay_this_pass *= 2;
+    }
+
+    if (sel_state->nfds == 0) {
+	/* No addresses?  */
+	retval = KRB5_KDC_UNREACH;
+	goto egress;
+    }
+    if (e == 0 || winning_conn < 0) {
+	retval = KRB5_KDC_UNREACH;
+	goto egress;
+    }
+    /* Success!  */
+    reply->data = conns[winning_conn].x.in.buf;
+    reply->length = (conns[winning_conn].x.in.pos
+		     - conns[winning_conn].x.in.buf);
+    dprint("returning %d bytes in buffer %p\n",
+	   (int) reply->length, reply->data);
+    retval = 0;
+    conns[winning_conn].x.in.buf = 0;
+    if (addr_used)
+        *addr_used = winning_conn;
+    if (localaddr != 0 && localaddrlen != 0 && *localaddrlen > 0)
+	(void) getsockname(conns[winning_conn].fd, localaddr, localaddrlen);
+
+	if (remoteaddr != 0 && remoteaddrlen != 0 && *remoteaddrlen > 0)
+	(void) getpeername(conns[winning_conn].fd, remoteaddr, remoteaddrlen);
+
+egress:
+    for (i = 0; i < n_conns; i++) {
+	if (conns[i].fd != INVALID_SOCKET)
+	    closesocket(conns[i].fd);
+	if (conns[i].state == READING
+	    && conns[i].x.in.buf != 0
+	    && conns[i].x.in.buf != udpbuf)
+	    free(conns[i].x.in.buf);
+	if (callback_info) {
+	    callback_info->pfn_cleanup( callback_info->context, &callback_data[i]);
+	}
+    }
+
+    if (callback_data) 
+	free(callback_data);
+
+    free(conns);
+    if (reply->data != udpbuf)
+	free(udpbuf);
+    free(sel_state);
+    return retval;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/sn2princ.c b/krb5-1-6/src/lib/krb5/os/sn2princ.c
new file mode 100644
index 000000000..8df591138
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/sn2princ.c
@@ -0,0 +1,214 @@
+/*
+ * lib/krb5/os/sn2princ.c
+ *
+ * Copyright 1991,2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Convert a hostname and service name to a principal in the "standard"
+ * form.
+ */
+
+#include "k5-int.h"
+#include "os-proto.h"
+#include "fake-addrinfo.h"
+#include <ctype.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#if !defined(DEFAULT_RDNS_LOOKUP)
+#define DEFAULT_RDNS_LOOKUP 1
+#endif
+
+static int
+maybe_use_reverse_dns (krb5_context context, int defalt)
+{
+    krb5_error_code code;
+    char * value = NULL;
+    int use_rdns = 0;
+
+    code = profile_get_string(context->profile, "libdefaults",
+                              "rdns", 0, 0, &value);
+    if (code)
+        return defalt;
+
+    if (value == 0)
+	return defalt;
+
+    use_rdns = _krb5_conf_boolean(value);
+    profile_release_string(value);
+    return use_rdns;
+}
+
+
+krb5_error_code KRB5_CALLCONV
+krb5_sname_to_principal(krb5_context context, const char *hostname, const char *sname, krb5_int32 type, krb5_principal *ret_princ)
+{
+    char **hrealms, *realm, *remote_host;
+    krb5_error_code retval;
+    register char *cp;
+    char localname[MAXHOSTNAMELEN];
+
+#ifdef DEBUG_REFERRALS
+    printf("krb5_sname_to_principal(host=%s, sname=%s, type=%d)\n",hostname,sname,type);
+    printf("      name types: 0=unknown, 3=srv_host\n");
+#endif
+
+    if ((type == KRB5_NT_UNKNOWN) ||
+	(type == KRB5_NT_SRV_HST)) {
+
+	/* if hostname is NULL, use local hostname */
+	if (! hostname) {
+	    if (gethostname(localname, MAXHOSTNAMELEN))
+		return SOCKET_ERRNO;
+	    hostname = localname;
+	}
+
+	/* if sname is NULL, use "host" */
+	if (! sname)
+	    sname = "host";
+
+	/* copy the hostname into non-volatile storage */
+
+	if (type == KRB5_NT_SRV_HST) {
+	    struct addrinfo *ai, hints;
+	    int err;
+	    char hnamebuf[NI_MAXHOST];
+
+	    /* Note that the old code would accept numeric addresses,
+	       and if the gethostbyaddr step could convert them to
+	       real hostnames, you could actually get reasonable
+	       results.  If the mapping failed, you'd get dotted
+	       triples as realm names.  *sigh*
+
+	       The latter has been fixed in hst_realm.c, but we should
+	       keep supporting numeric addresses if they do have
+	       hostnames associated.  */
+
+	    memset(&hints, 0, sizeof(hints));
+	    hints.ai_family = AF_INET;
+	try_getaddrinfo_again:
+	    err = getaddrinfo(hostname, 0, &hints, &ai);
+	    if (err) {
+#ifdef DEBUG_REFERRALS
+	        printf("sname_to_princ: probably punting due to bad hostname of %s\n",hostname);
+#endif
+		if (hints.ai_family == AF_INET) {
+		    /* Just in case it's an IPv6-only name.  */
+		    hints.ai_family = 0;
+		    goto try_getaddrinfo_again;
+		}
+		return KRB5_ERR_BAD_HOSTNAME;
+	    }
+	    remote_host = strdup(ai->ai_canonname ? ai->ai_canonname : hostname);
+	    if (!remote_host) {
+		freeaddrinfo(ai);
+		return ENOMEM;
+	    }
+
+            if (maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) {
+                /*
+                 * Do a reverse resolution to get the full name, just in
+                 * case there's some funny business going on.  If there
+                 * isn't an in-addr record, give up.
+                 */
+                /* XXX: This is *so* bogus.  There are several cases where
+                   this won't get us the canonical name of the host, but
+                   this is what we've trained people to expect.  We'll
+                   probably fix it at some point, but let's try to
+                   preserve the current behavior and only shake things up
+                   once when it comes time to fix this lossage.  */
+                err = getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                                   hnamebuf, sizeof(hnamebuf), 0, 0, NI_NAMEREQD);
+                freeaddrinfo(ai);
+                if (err == 0) {
+                    free(remote_host);
+                    remote_host = strdup(hnamebuf);
+                    if (!remote_host)
+                        return ENOMEM;
+                }
+            }
+	} else /* type == KRB5_NT_UNKNOWN */ {
+	    remote_host = strdup(hostname);
+	}
+	if (!remote_host)
+	    return ENOMEM;
+#ifdef DEBUG_REFERRALS
+ 	printf("sname_to_princ: hostname <%s> after rdns processing\n",remote_host);
+#endif
+
+	if (type == KRB5_NT_SRV_HST)
+	    for (cp = remote_host; *cp; cp++)
+		if (isupper((unsigned char) (*cp)))
+		    *cp = tolower((unsigned char) (*cp));
+
+	/*
+	 * Windows NT5's broken resolver gratuitously tacks on a
+	 * trailing period to the hostname (at least it does in
+	 * Beta2).  Find and remove it.
+	 */
+	if (remote_host[0]) {
+		cp = remote_host + strlen(remote_host)-1;
+		if (*cp == '.')
+			*cp = 0;
+	}
+	
+
+	if ((retval = krb5_get_host_realm(context, remote_host, &hrealms))) {
+	    free(remote_host);
+	    return retval;
+	}
+
+#ifdef DEBUG_REFERRALS
+	printf("sname_to_princ:  realm <%s> after krb5_get_host_realm\n",hrealms[0]);
+#endif
+
+	if (!hrealms[0]) {
+	    free(remote_host);
+	    krb5_xfree(hrealms);
+	    return KRB5_ERR_HOST_REALM_UNKNOWN;
+	}
+	realm = hrealms[0];
+
+	retval = krb5_build_principal(context, ret_princ, strlen(realm),
+				      realm, sname, remote_host,
+				      (char *)0);
+
+	krb5_princ_type(context, *ret_princ) = type;
+
+#ifdef DEBUG_REFERRALS
+	printf("krb5_sname_to_principal returning\n");
+	printf("realm: <%s>, sname: <%s>, remote_host: <%s>\n",
+	       realm,sname,remote_host);
+	krb5int_dbgref_dump_principal("krb5_sname_to_principal",*ret_princ);
+#endif
+
+	free(remote_host);
+
+	krb5_free_host_realm(context, hrealms);
+	return retval;
+    } else {
+	return KRB5_SNAME_UNSUPP_NAMETYPE;
+    }
+}
+
diff --git a/krb5-1-6/src/lib/krb5/os/t_an_to_ln.c b/krb5-1-6/src/lib/krb5/os/t_an_to_ln.c
new file mode 100644
index 000000000..93933a477
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/t_an_to_ln.c
@@ -0,0 +1,41 @@
+#include "krb5.h"
+
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code	kret;
+    krb5_context	kcontext;
+    krb5_principal	principal;
+    char		*programname;
+    int			i;
+    char		sbuf[1024];
+
+    programname = argv[0];
+    krb5_init_context(&kcontext);
+    for (i=1; i < argc; i++) {
+	if (!(kret = krb5_parse_name(kcontext, argv[i], &principal))) {
+	    if (!(kret = krb5_aname_to_localname(kcontext,
+						 principal,
+						 1024,
+						 sbuf))) {
+		printf("%s: aname_to_lname maps %s -> <%s>\n",
+		       programname, argv[i], sbuf);
+	    }
+	    else {
+		printf("%s: aname to lname returns %s for %s\n", programname,
+		       error_message(kret), argv[i]);
+	    }
+	    krb5_free_principal(kcontext, principal);
+	}
+	else {
+	    printf("%s: parse_name returns %s\n", programname,
+		   error_message(kret));
+	}
+	if (kret)
+	    break;
+    }
+    krb5_free_context(kcontext);
+    return((kret) ? 1 : 0);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/t_gifconf.c b/krb5-1-6/src/lib/krb5/os/t_gifconf.c
new file mode 100644
index 000000000..92a49123a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/t_gifconf.c
@@ -0,0 +1,134 @@
+/* SIOCGIFCONF:
+
+   The behavior of this ioctl varies across systems.
+
+   The "largest gap" values are the largest number of bytes I've seen
+   left unused at the end of the supplied buffer when there were more
+   entries to return.  These values may of coures be dependent on the
+   configurations of the particular systems I was testing with.
+
+   NetBSD 1.5-alpha: The returned ifc_len is the desired amount of
+   space, always.  The returned list may be truncated if there isn't
+   enough room; no overrun.  Largest gap: 43.  (NetBSD now has
+   getifaddrs.)
+
+   BSD/OS 4.0.1 (courtesy djm): The returned ifc_len is equal to or
+   less than the supplied ifc_len.  Sometimes the entire buffer is
+   used; sometimes N-1 bytes; occasionally, the buffer must have quite
+   a bit of extra room before the next structure will be added.
+   Largest gap: 39.
+
+   Solaris 7,8: Return EINVAL if the buffer space is too small for all
+   the data to be returned, including ifc_len==0.  Solaris is the only
+   system I've found so far that actually returns an error.  No gap.
+   However, SIOCGIFNUM may be used to query the number of interfaces.
+
+   Linux 2.2.12 (RH 6.1 dist, x86): The buffer is filled in with as
+   many entries as will fit, and the size used is returned in ifc_len.
+   The list is truncated if needed, with no indication.  Largest gap: 31.
+
+   IRIX 6.5: The buffer is filled in with as many entries as will fit
+   in N-1 bytes, and the size used is returned in ifc_len.  Providing
+   exactly the desired number of bytes is inadequate; the buffer must
+   be *bigger* than needed.  (E.g., 32->0, 33->32.)  The returned
+   ifc_len is always less than the supplied one.  Largest gap: 32.
+
+   AIX 4.3.3: Sometimes the returned ifc_len is bigger than the
+   supplied one, but it may not be big enough for *all* the
+   interfaces.  Sometimes it's smaller than the supplied value, even
+   if the returned list is truncated.  The list is filled in with as
+   many entries as will fit; no overrun.  Largest gap: 143.
+
+   Older AIX: We're told by W. David Shambroom <DShambroom@gte.com> in
+   PR krb5-kdc/919 that older versions of AIX have a bug in the
+   SIOCGIFCONF ioctl which can cause them to overrun the supplied
+   buffer.  However, we don't yet have details as to which version,
+   whether the overrun amount was bounded (e.g., one ifreq's worth) or
+   not, whether it's a real buffer overrun or someone assuming it was
+   because ifc_len was increased, etc.  Once we've got details, we can
+   try to work around the problem.
+
+   Digital UNIX 4.0F: If input ifc_len is zero, return an ifc_len
+   that's big enough to include all entries.  (Actually, on our
+   system, it appears to be larger than that by 32.)  If input ifc_len
+   is nonzero, fill in as many entries as will fit, and set ifc_len
+   accordingly.  (Tested only with INIT of zero.)
+
+   So... if the returned ifc_len is bigger than the supplied one,
+   we'll need at least that much space -- but possibly more -- to hold
+   all the results.  If the returned value is smaller or the same, we
+   may still need more space.
+
+   Using this ioctl is going to be messy.  Let's just hope that
+   getifaddrs() catches on quickly....  */
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
+#if (defined(sun) || defined(__sun__)) && !defined(SIOCGIFCONF)
+/* Sun puts socket ioctls in another file.  */
+#include <sys/sockio.h>
+#endif
+
+#define INIT 0xc3
+
+int main (void) {
+    char buffer[2048];
+    int i, sock, t, olen = -9, omod = -9;
+    struct ifconf ifc;
+    int gap = -1, lastgap = -1;
+
+    sock = socket (AF_INET, SOCK_DGRAM, 0);
+    if (sock < 0) {
+	perror ("socket");
+	exit (1);
+    }
+    printf ("sizeof(struct if_req)=%d\n", sizeof (struct ifreq));
+    for (t = 0; t < sizeof (buffer); t++) {
+	ifc.ifc_len = t;
+	ifc.ifc_buf = buffer;
+	memset (buffer, INIT, sizeof (buffer));
+	i = ioctl (sock, SIOCGIFCONF, (char *) &ifc);
+	if (i < 0) {
+	    /* Solaris returns "Invalid argument" if the buffer is too
+	       small.  AIX and Linux return no error indication.  */
+	    int e = errno;
+	    sprintf (buffer, "SIOCGIFCONF(%d)", t);
+	    errno = e;
+	    perror (buffer);
+	    if (e == EINVAL)
+		continue;
+	    fprintf (stderr, "exiting on unexpected error\n");
+	    exit (1);
+	}
+	i = sizeof (buffer) - 1;
+	while (buffer[i] == ((char)INIT) && i >= 0)
+	    i--;
+	if (omod != i) {
+	    /* Okay... the gap computed on the *last* iteration is the
+	       largest for that particular size of returned data.
+	       Save it, and then start computing gaps for the next
+	       bigger size of returned data.  If we never get anything
+	       bigger back, we discard the newer value and only keep
+	       LASTGAP because all we care about is how much slop we
+	       need to "prove" that there really weren't any more
+	       entries to be returned.  */
+	    if (gap > lastgap)
+		lastgap = gap;
+	}
+	gap = t - i - 1;
+	if (olen != ifc.ifc_len || omod != i) {
+	    printf ("ifc_len in = %4d, ifc_len out = %4d, last mod = %4d\n",
+		    t, ifc.ifc_len, i);
+	    olen = ifc.ifc_len;
+	    omod = i;
+	}
+    }
+    printf ("finished at ifc_len %d\n", t);
+    printf ("largest gap = %d\n", lastgap);
+    exit (0);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/t_locate_kdc.c b/krb5-1-6/src/lib/krb5/os/t_locate_kdc.c
new file mode 100644
index 000000000..165366f5b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/t_locate_kdc.c
@@ -0,0 +1,131 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "port-sockets.h"
+#include <com_err.h>
+
+#define TEST
+#include "dnsglue.c"
+#include "dnssrv.c"
+#include "locate_kdc.c"
+
+enum {
+    LOOKUP_CONF = 3,
+    LOOKUP_DNS,
+    LOOKUP_WHATEVER
+} how = LOOKUP_WHATEVER;
+
+const char *prog;
+
+struct addrlist al;
+
+void kfatal (krb5_error_code err)
+{
+    com_err (prog, err, "- exiting");
+    exit (1);
+}
+
+const char *stypename (int stype)
+{
+    static char buf[20];
+    switch (stype) {
+    case SOCK_STREAM:
+	return "stream";
+    case SOCK_DGRAM:
+	return "dgram";
+    case SOCK_RAW:
+	return "raw";
+    default:
+	sprintf(buf, "?%d", stype);
+	return buf;
+    }
+}
+
+void print_addrs (void)
+{
+    int i;
+
+    int naddrs = al.naddrs;
+
+    printf ("%d addresses:\n", naddrs);
+    for (i = 0; i < naddrs; i++) {
+	int err;
+	struct addrinfo *ai = al.addrs[i].ai;
+	char hostbuf[NI_MAXHOST], srvbuf[NI_MAXSERV];
+	err = getnameinfo (ai->ai_addr, ai->ai_addrlen,
+			   hostbuf, sizeof (hostbuf),
+			   srvbuf, sizeof (srvbuf),
+			   NI_NUMERICHOST | NI_NUMERICSERV);
+	if (err)
+	    printf ("%2d: getnameinfo returns error %d=%s\n",
+		    i, err, gai_strerror (err));
+	else
+	    printf ("%2d: address %s\t%s\tport %s\n", i, hostbuf,
+		    stypename (ai->ai_socktype), srvbuf);
+    }
+}
+
+int main (int argc, char *argv[])
+{
+    char *p, *realmname;
+    krb5_data realm;
+    krb5_context ctx;
+    krb5_error_code err;
+    int master = 0;
+
+    p = strrchr (argv[0], '/');
+    if (p)
+	prog = p+1;
+    else
+	prog = argv[0];
+
+    switch (argc) {
+    case 2:
+	/* foo $realm */
+	realmname = argv[1];
+	break;
+    case 3:
+	if (!strcmp (argv[1], "-c"))
+	    how = LOOKUP_CONF;
+	else if (!strcmp (argv[1], "-d"))
+	    how = LOOKUP_DNS;
+	else if (!strcmp (argv[1], "-m"))
+	    master = 1;
+	else
+	    goto usage;
+	realmname = argv[2];
+	break;
+    default:
+    usage:
+	fprintf (stderr, "%s: usage: %s [-c | -d | -m] realm\n", prog, prog);
+	return 1;
+    }
+
+    err = krb5_init_context (&ctx);
+    if (err)
+	kfatal (err);
+
+    realm.data = realmname;
+    realm.length = strlen (realmname);
+
+    switch (how) {
+    case LOOKUP_CONF:
+	err = krb5_locate_srv_conf (ctx, &realm, "kdc", &al, 0,
+				    htons (88), htons (750));
+	break;
+
+    case LOOKUP_DNS:
+	err = krb5_locate_srv_dns_1 (&realm, "_kerberos", "_udp", &al, 0);
+	break;
+
+    case LOOKUP_WHATEVER:
+	err = krb5_locate_kdc (ctx, &realm, &al, master, 0, 0);
+	break;
+    }
+    if (err) kfatal (err);
+    print_addrs ();
+
+    krb5int_free_addrlist (&al);
+    krb5_free_context (ctx);
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/t_realm_iter.c b/krb5-1-6/src/lib/krb5/os/t_realm_iter.c
new file mode 100644
index 000000000..b39693594
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/t_realm_iter.c
@@ -0,0 +1,44 @@
+#include "krb5.h"
+
+#include <stdio.h>
+
+void test_realm_iterator(int ctx)
+{
+    krb5_error_code retval;
+    char *realm;
+    void *iter;
+
+    if ((retval = krb5_realm_iterator_create(ctx, &iter))) {
+	com_err("krb5_realm_iterator_create", retval, 0);
+	return;
+    }
+    while (iter) {
+	if ((retval = krb5_realm_iterator(ctx, &iter, &realm))) {
+	    com_err("krb5_realm_iterator", retval, 0);
+	    krb5_realm_iterator_free(ctx, &iter);
+	    return;
+	}
+	if (realm) {
+	    printf("Realm: '%s'\n", realm);
+	    krb5_free_realm_string(ctx, realm);
+	}
+    }
+}
+
+int main(int argc, char **argv)
+{
+    krb5_context ctx;
+    krb5_error_code retval;
+
+    retval = krb5_init_context(&ctx);
+    if (retval) {
+	fprintf(stderr, "krb5_init_context returned error %ld\n",
+		retval);
+	exit(1);
+    }
+
+    test_realm_iterator(ctx);
+
+    krb5_free_context(ctx);
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/t_std_conf.c b/krb5-1-6/src/lib/krb5/os/t_std_conf.c
new file mode 100644
index 000000000..04b75d7b8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/t_std_conf.c
@@ -0,0 +1,247 @@
+/*
+ * t_std_conf.c --- This program tests standard Krb5 routines which pull 
+ * 	values from the krb5 config file(s).
+ */
+
+#include "fake-addrinfo.h"
+#include "k5-int.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "os-proto.h"
+
+static void test_get_default_realm(krb5_context ctx)
+{
+	char	*realm;
+	krb5_error_code	retval;
+	
+	retval = krb5_get_default_realm(ctx, &realm);
+	if (retval) {
+		com_err("krb5_get_default_realm", retval, 0);
+		return;
+	}
+	printf("krb5_get_default_realm() returned '%s'\n", realm);
+	free(realm);
+}
+
+static void test_set_default_realm(krb5_context ctx, char *realm)
+{
+	krb5_error_code	retval;
+	
+	retval = krb5_set_default_realm(ctx, realm);
+	if (retval) {
+		com_err("krb5_set_default_realm", retval, 0);
+		return;
+	}
+	printf("krb5_set_default_realm(%s)\n", realm);
+}
+
+static void test_get_default_ccname(krb5_context ctx)
+{
+	const char	*ccname;
+
+	ccname = krb5_cc_default_name(ctx);
+	if (ccname)
+		printf("krb5_cc_default_name() returned '%s'\n", ccname);
+	else
+		printf("krb5_cc_default_name() returned NULL\n");
+}
+
+static void test_set_default_ccname(krb5_context ctx, char *ccname)
+{
+	krb5_error_code	retval;
+	
+	retval = krb5_cc_set_default_name(ctx, ccname);
+	if (retval) {
+		com_err("krb5_set_default_ccname", retval, 0);
+		return;
+	}
+	printf("krb5_set_default_ccname(%s)\n", ccname);
+}
+
+static void test_get_krbhst(krb5_context ctx, char *realm)
+{
+	char **hostlist, **cpp;
+	krb5_data rlm;
+	krb5_error_code	retval;
+
+	rlm.data = realm;
+	rlm.length = strlen(realm);
+	retval = krb5_get_krbhst(ctx, &rlm, &hostlist);
+	if (retval) {
+		com_err("krb5_get_krbhst", retval, 0);
+		return;
+	}
+	printf("krb_get_krbhst(%s) returned:", realm);
+	if (hostlist == 0) {
+		printf(" (null)\n");
+		return;
+	}
+	if (hostlist[0] == 0) {
+		printf(" (none)\n");
+		krb5_free_krbhst(ctx, hostlist);
+		return;
+	}
+	for (cpp = hostlist; *cpp; cpp++) {
+		printf(" '%s'", *cpp);
+	}
+	krb5_free_krbhst(ctx, hostlist);
+	printf("\n");
+}
+
+static void test_locate_kdc(krb5_context ctx, char *realm)
+{
+    	struct addrlist addrs;
+	int	i;
+	int	get_masters=0;
+	krb5_data rlm;
+	krb5_error_code	retval;
+
+	rlm.data = realm;
+	rlm.length = strlen(realm);
+	retval = krb5_locate_kdc(ctx, &rlm, &addrs, get_masters, 0, 0);
+	if (retval) {
+		com_err("krb5_locate_kdc", retval, 0);
+		return;
+	}
+	printf("krb_locate_kdc(%s) returned:", realm);
+	for (i=0; i < addrs.naddrs; i++) {
+	    struct addrinfo *ai = addrs.addrs[i].ai;
+	    switch (ai->ai_family) {
+	    case AF_INET:
+	    {
+		struct sockaddr_in *s_sin;
+		s_sin = (struct sockaddr_in *) ai->ai_addr;
+		printf(" inet:%s/%d", inet_ntoa(s_sin->sin_addr), 
+		       ntohs(s_sin->sin_port));
+	    }
+	    break;
+#ifdef KRB5_USE_INET6
+	    case AF_INET6:
+	    {
+		struct sockaddr_in6 *s_sin6;
+		int j;
+		s_sin6 = (struct sockaddr_in6 *) ai->ai_addr;
+		printf(" inet6");
+		for (j = 0; j < 8; j++)
+		    printf(":%x",
+			   (s_sin6->sin6_addr.s6_addr[2*j] * 256
+			    + s_sin6->sin6_addr.s6_addr[2*j+1]));
+		printf("/%d", ntohs(s_sin6->sin6_port));
+		break;
+	    }
+#endif
+	    default:
+		printf(" unknown-af-%d", ai->ai_family);
+		break;
+	    }
+	}
+	krb5int_free_addrlist(&addrs);
+	printf("\n");
+}
+
+static void test_get_host_realm(krb5_context ctx, char *host)
+{
+	char **realms, **cpp;
+	krb5_error_code retval;
+
+	retval = krb5_get_host_realm(ctx, host, &realms);
+	if (retval) {
+		com_err("krb5_get_host_realm", retval, 0);
+		return;
+	}
+	printf("krb_get_host_realm(%s) returned:", host);
+	if (realms == 0) {
+		printf(" (null)\n");
+		return;
+	}
+	if (realms[0] == 0) {
+		printf(" (none)\n");
+		free(realms);
+		return;
+	}
+	for (cpp = realms; *cpp; cpp++) {
+		printf(" '%s'", *cpp);
+		free(*cpp);
+	}
+	free(realms);
+	printf("\n");
+}
+
+static void test_get_realm_domain(krb5_context ctx, char *realm)
+{
+	krb5_error_code	retval;
+	char	*domain;
+	
+	retval = krb5_get_realm_domain(ctx, realm, &domain);
+	if (retval) {
+		com_err("krb5_get_realm_domain", retval, 0);
+		return;
+	}
+	printf("krb5_get_realm_domain(%s) returned '%s'\n", realm, domain);
+	free(domain);
+}
+
+static void usage(char *progname)
+{
+	fprintf(stderr, "%s: Usage: %s [-dc] [-k realm] [-r host] [-C ccname] [-D realm]\n",
+		progname, progname);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int	c;
+	krb5_context	ctx;
+	krb5_error_code	retval;
+	extern char *optarg;
+
+	retval = krb5_init_context(&ctx);
+	if (retval) {
+		fprintf(stderr, "krb5_init_context returned error %u\n",
+			retval);
+		exit(1);
+	}
+
+	while ((c = getopt(argc, argv, "cdk:r:C:D:l:s:")) != -1) {
+	    switch (c) {
+	    case 'c':		/* Get default ccname */
+		test_get_default_ccname(ctx);
+		break;
+	    case 'd': /* Get default realm */
+		test_get_default_realm(ctx);
+		break;
+	    case 'k': /* Get list of KDC's */
+		test_get_krbhst(ctx, optarg);
+		break;
+	    case 'l':
+		test_locate_kdc(ctx, optarg);
+		break;
+	    case 'r':
+		test_get_host_realm(ctx, optarg);
+		break;
+	    case 's':
+		test_set_default_realm(ctx, optarg);
+		break;
+	    case 'C':
+		test_set_default_ccname(ctx, optarg);
+		break;
+	    case 'D':
+		test_get_realm_domain(ctx, optarg);
+		break;
+	    default:
+		usage(argv[0]);
+	    }
+	}
+
+
+	krb5_free_context(ctx);
+	exit(0);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/td_krb5.conf b/krb5-1-6/src/lib/krb5/os/td_krb5.conf
new file mode 100644
index 000000000..cdee60945
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/td_krb5.conf
@@ -0,0 +1,19 @@
+[libdefaults]
+	default_realm = DEFAULT.REALM.TST
+
+[realms]
+	DEFAULT_REALM.TST = {
+		kdc = FIRST.KDC.HOST:750
+		kdc = SECOND.KDC.HOST:88
+		admin_server = FIRST.KDC.HOST
+		default_domain = MIT.EDU
+	}
+	IGGY.ORG = {
+		kdc = KERBEROS.IGGY.ORG
+		kdc = KERBEROS-B.IGGY.ORG
+	}
+
+[domain_realm]
+	bad.idea = US.GOV
+	.bad.idea = NSA.GOV
+	clipper.bad.idea = NIST.GOV
diff --git a/krb5-1-6/src/lib/krb5/os/thread_safe.c b/krb5-1-6/src/lib/krb5/os/thread_safe.c
new file mode 100644
index 000000000..faac234f9
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/thread_safe.c
@@ -0,0 +1,40 @@
+/*
+ * lib/krb5/os/thread_safec
+ *
+ * Copyright 2005 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * krb5_is_thread_safe() function.
+ */
+
+#include "k5-int.h"
+
+krb5_boolean KRB5_CALLCONV
+krb5_is_thread_safe(void)
+{
+#if defined(ENABLE_THREADS)
+    return 1;
+#else
+    return 0;
+#endif
+}
diff --git a/krb5-1-6/src/lib/krb5/os/timeofday.c b/krb5-1-6/src/lib/krb5/os/timeofday.c
new file mode 100644
index 000000000..dcc75f566
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/timeofday.c
@@ -0,0 +1,52 @@
+/*
+ * lib/krb5/os/timeofday.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * libos: krb5_timeofday function for BSD 4.3 
+ */
+
+
+#include "k5-int.h"
+
+#include <time.h>
+
+krb5_error_code KRB5_CALLCONV
+krb5_timeofday(krb5_context context, register krb5_timestamp *timeret)
+{
+    krb5_os_context os_ctx = context->os_context;
+    time_t tval;
+
+    if (os_ctx->os_flags & KRB5_OS_TOFFSET_TIME) {
+	    *timeret = os_ctx->time_offset;
+	    return 0;
+    }
+    tval = time(0);
+    if (tval == (time_t) -1)
+	return (krb5_error_code) errno;
+    if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)
+	    tval += os_ctx->time_offset;
+    *timeret = tval;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/toffset.c b/krb5-1-6/src/lib/krb5/os/toffset.c
new file mode 100644
index 000000000..967b9d62b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/toffset.c
@@ -0,0 +1,115 @@
+/*
+ * lib/krb5/os/toffset.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * These routines manipulates the time offset fields in the os context.
+ */
+
+#include "k5-int.h"
+
+/*
+ * This routine takes the "real time" as input, and sets the time
+ * offset field in the context structure so that the krb5 time
+ * routines will return the correct time as corrected by difference
+ * between the system time and the "real time" as passed to this
+ * routine
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
+{
+    krb5_os_context os_ctx = context->os_context;
+    krb5_int32 sec, usec;
+    krb5_error_code retval;
+
+    retval = krb5_crypto_us_timeofday(&sec, &usec);
+    if (retval)
+	    return retval;
+    os_ctx->time_offset = seconds - sec;
+    os_ctx->usec_offset = microseconds - usec;
+    os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
+			KRB5_OS_TOFFSET_VALID);
+    return 0;
+}
+
+/*
+ * This routine sets the krb5 time routines so that they will return
+ * the seconds and microseconds value as input to this function.  This
+ * is useful for running the krb5 routines through test suites
+ */
+krb5_error_code 
+krb5_set_debugging_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
+{
+    krb5_os_context os_ctx = context->os_context;
+
+    os_ctx->time_offset = seconds;
+    os_ctx->usec_offset = microseconds;
+    os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_VALID) |
+			KRB5_OS_TOFFSET_TIME);
+    return 0;
+}
+
+/*
+ * This routine turns off the time correction fields, so that the krb5
+ * routines return the "natural" time.
+ */
+krb5_error_code 
+krb5_use_natural_time(krb5_context context)
+{
+    krb5_os_context os_ctx = context->os_context;
+
+    os_ctx->os_flags &= ~(KRB5_OS_TOFFSET_VALID|KRB5_OS_TOFFSET_TIME);
+
+    return 0;
+}
+
+/*
+ * This routine returns the current time offsets in use.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_time_offsets(krb5_context context, krb5_timestamp *seconds, krb5_int32 *microseconds)
+{
+    krb5_os_context os_ctx = context->os_context;
+
+    if (seconds)
+	*seconds = os_ctx->time_offset;
+    if (microseconds)
+	*microseconds = os_ctx->usec_offset;
+    return 0;
+}
+
+
+/*
+ * This routine sets the time offsets directly.
+ */
+krb5_error_code 
+krb5_set_time_offsets(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
+{
+    krb5_os_context os_ctx = context->os_context;
+
+    os_ctx->time_offset = seconds;
+    os_ctx->usec_offset = microseconds;
+    os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
+			KRB5_OS_TOFFSET_VALID);
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/unlck_file.c b/krb5-1-6/src/lib/krb5/os/unlck_file.c
new file mode 100644
index 000000000..0bbf7ce31
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/unlck_file.c
@@ -0,0 +1,37 @@
+/*
+ * lib/krb5/os/unlck_file.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * libos: krb5_lock_file routine
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+
+krb5_error_code
+krb5_unlock_file(krb5_context context, int fd)
+{
+    return krb5_lock_file(context, fd, KRB5_LOCKMODE_UNLOCK);
+}
diff --git a/krb5-1-6/src/lib/krb5/os/ustime.c b/krb5-1-6/src/lib/krb5/os/ustime.c
new file mode 100644
index 000000000..ef923d387
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/ustime.c
@@ -0,0 +1,66 @@
+/*
+ * lib/krb5/os/ustime.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * krb5_crypto_us_timeofday() does all of the real work; however, we
+ * handle the time offset adjustment here, since this is context
+ * specific, and the crypto version of this call doesn't have access
+ * to the context variable.  Fortunately the only user of
+ * krb5_crypto_us_timeofday in the crypto library doesn't require that
+ * this time adjustment be done.
+ */
+
+#include "k5-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_us_timeofday(krb5_context context, krb5_timestamp *seconds, krb5_int32 *microseconds)
+{
+    krb5_os_context os_ctx = context->os_context;
+    krb5_int32 sec, usec;
+    krb5_error_code retval;
+    
+    if (os_ctx->os_flags & KRB5_OS_TOFFSET_TIME) {
+	    *seconds = os_ctx->time_offset;
+	    *microseconds = os_ctx->usec_offset;
+	    return 0;
+    }
+    retval = krb5_crypto_us_timeofday(&sec, &usec);
+    if (retval)
+	    return retval;
+    if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) {
+	    usec += os_ctx->usec_offset;
+	    if (usec > 1000000) {
+		    usec -= 1000000;
+		    sec++;
+	    }
+	    if (usec < 0) {
+		usec += 1000000;
+		sec--;
+	    }
+	    sec += os_ctx->time_offset;
+    }
+    *seconds = sec;
+    *microseconds = usec;
+    return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/os/write_msg.c b/krb5-1-6/src/lib/krb5/os/write_msg.c
new file mode 100644
index 000000000..d75a32796
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/os/write_msg.c
@@ -0,0 +1,47 @@
+/*
+ * lib/krb5/os/write_msg.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * convenience sendauth/recvauth functions
+ */
+
+#include "k5-int.h"
+#include <errno.h>
+
+krb5_error_code
+krb5_write_message(krb5_context context, krb5_pointer fdp, krb5_data *outbuf)
+{
+	krb5_int32	len;
+	int		fd = *( (int *) fdp);
+
+	len = htonl(outbuf->length);
+	if (krb5_net_write(context, fd, (char *)&len, 4) < 0) {
+		return(errno);
+	}
+	if (outbuf->length && (krb5_net_write(context, fd, outbuf->data, outbuf->length) < 0)) {
+		return(errno);
+	}
+	return(0);
+}
diff --git a/krb5-1-6/src/lib/krb5/posix/Makefile.in b/krb5-1-6/src/lib/krb5/posix/Makefile.in
new file mode 100644
index 000000000..65a7b601d
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/posix/Makefile.in
@@ -0,0 +1,18 @@
+thisconfigdir=./..
+myfulldir=lib/krb5/posix
+mydir=posix
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=posix
+##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst
+
+STLIBOBJS= # empty... @LIBOBJS@
+OBJS = # empty... @LIBOBJS@
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+
+##WIN32##LIBOBJS = $(OUTPRE)syslog.obj
+@libobj_frag@
diff --git a/krb5-1-6/src/lib/krb5/posix/syslog.c b/krb5-1-6/src/lib/krb5/posix/syslog.c
new file mode 100644
index 000000000..e1318933e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/posix/syslog.c
@@ -0,0 +1,10 @@
+#if defined(_WIN32)
+/* Windows doesn't have the concept of a system log, so just
+** do nothing here.
+*/
+void
+syslog(int pri, const char *fmt, ...)
+{
+   return;
+}
+#endif
diff --git a/krb5-1-6/src/lib/krb5/rcache/Makefile.in b/krb5-1-6/src/lib/krb5/rcache/Makefile.in
new file mode 100644
index 000000000..874d9de25
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/Makefile.in
@@ -0,0 +1,124 @@
+thisconfigdir=../../..
+myfulldir=lib/krb5/rcache
+mydir=lib/krb5/rcache
+BUILDTOP=$(REL)..$(S)..$(S)..
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR=rcache
+##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst
+
+STLIBOBJS = \
+	rc_base.o	\
+	rc_dfl.o 	\
+	rc_io.o		\
+	rcdef.o		\
+	rc_none.o	\
+	rc_conv.o	\
+	ser_rc.o	\
+	rcfns.o
+
+OBJS=	\
+	$(OUTPRE)rc_base.$(OBJEXT)	\
+	$(OUTPRE)rc_dfl.$(OBJEXT) 	\
+	$(OUTPRE)rc_io.$(OBJEXT)	\
+	$(OUTPRE)rcdef.$(OBJEXT)	\
+	$(OUTPRE)rc_none.$(OBJEXT)	\
+	$(OUTPRE)rc_conv.$(OBJEXT)	\
+	$(OUTPRE)ser_rc.$(OBJEXT)	\
+	$(OUTPRE)rcfns.$(OBJEXT)
+
+SRCS=	\
+	$(srcdir)/rc_base.c	\
+	$(srcdir)/rc_dfl.c 	\
+	$(srcdir)/rc_io.c	\
+	$(srcdir)/rcdef.c	\
+	$(srcdir)/rc_none.c	\
+	$(srcdir)/rc_conv.c	\
+	$(srcdir)/ser_rc.c	\
+	$(srcdir)/rcfns.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+rc_base.so rc_base.po $(OUTPRE)rc_base.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc-int.h rc_base.c rc_base.h
+rc_dfl.so rc_dfl.po $(OUTPRE)rc_dfl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc-int.h rc_base.h rc_dfl.c rc_dfl.h rc_io.h
+rc_io.so rc_io.po $(OUTPRE)rc_io.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc_base.h rc_dfl.h rc_io.c rc_io.h
+rcdef.so rcdef.po $(OUTPRE)rcdef.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc-int.h rc_dfl.h rcdef.c
+rc_none.so rc_none.po $(OUTPRE)rc_none.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc-int.h rc_none.c
+rc_conv.so rc_conv.po $(OUTPRE)rc_conv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc_base.h rc_conv.c
+ser_rc.so ser_rc.po $(OUTPRE)ser_rc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc-int.h ser_rc.c
+rcfns.so rcfns.po $(OUTPRE)rcfns.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  rc-int.h rcfns.c
diff --git a/krb5-1-6/src/lib/krb5/rcache/README b/krb5-1-6/src/lib/krb5/rcache/README
new file mode 100644
index 000000000..13a45a1d8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/README
@@ -0,0 +1,82 @@
+/*
+Copyright 1990, Daniel J. Bernstein. All rights reserved.
+
+Please address any questions or comments to the author at brnstnd@acf10.nyu.edu.
+*/
+
+The #include's should be rewritten.
+
+All functions return 0 on success.
+
+Environment variables: KRB5RCACHETYPE, KRB5RCACHENAME, KRB5RCACHEDIR,
+and TMPDIR. Obsolete: KRB5RCACHE.
+
+All header files are both ANSI-compatible and K&R-compatible. The .c files
+are only ANSI compatible. Everything passes gcc -Wall -ansi -pedantic.
+
+Strings are freed using FREE(), which is defined in terms of free(). 
+
+The error header files should be redone.
+
+The header files don't use __ because that's reserved.
+
+Each .c file assumes <malloc.h>. rc_io.c assumes fsync() and a gaggle of
+error codes. These assumptions are not as portable as the code itself.
+
+
+rcache.c:
+
+The rcache.c compatibility interface's type registration is a no-op; it
+simply passes the type name on to rc_base.h. rcache.h is obsolete; use
+rc_base.h if possible.
+
+There are some slight differences between rcache.c and the prototypes I
+saw in krb/func-proto.h. Don't look at me, it's your interface.
+
+rcache.c's get_name doesn't fill with zeros unless strncpy does.
+
+
+rc_base.c:
+
+It doesn't take linker magic to preregister types. Just change the
+typehead initialization in rc_base.c, with an appropriate include file
+setting the ops.
+
+
+rc_dfl.c:
+
+If NOIOSTUFF is defined when rc_dfl.c is compiled, all dfl rcaches will
+be per-process. This is untested.
+
+Provided that separate threads use separate rcaches, rc_dfl.c is safe
+for multithreading.
+
+Getting the name of a cache is only valid after it is created and before
+it is closed. Recovering a cache is only valid after it has been created.
+
+krb5_unparse_name had better produce a zero-terminated string.
+
+rc_dfl.c isn't smart enough to try expunge/retry upon a malloc error.
+Then again, such an error indicates that the whole system's about to die;
+without real memory management there's no good solution.
+
+HASHSIZE can be defined at compile time. It defaults to 997 in rc_dfl.c.
+EXCESSREPS can be defined at compile time. It defaults to 30 in rc_dfl.c.
+
+Hopefully adding a deltat to a time to compare to another time cannot
+overflow.
+
+In rc_dfl's struct dfl_data, the name field is never freed, even though
+it may be malloced by io_creat on a generate-name call. This should not
+be a problem: a single process should not be opening and closing many
+rcaches. One fix would be another field to indicate whether the string
+was malloced or not; normally this is an unstated characteristic of a
+char pointer, but here it would have to be explicit.
+
+
+rc_io.c:
+
+rc_io.c assumes that siginterrupt() is not set. If siginterrupt() is set
+and a signal occurs during, say, close(), then the close will fail.
+
+On a machine without fsync() you might as well not use the disk at all.
diff --git a/krb5-1-6/src/lib/krb5/rcache/RELEASE b/krb5-1-6/src/lib/krb5/rcache/RELEASE
new file mode 100644
index 000000000..21a462472
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/RELEASE
@@ -0,0 +1,17 @@
+Text of Mr. Bernstein's release:
+
+"I" henceforth refers to Daniel J. Bernstein.
+
+"rcshar" henceforth refers to the attached document, as sent from Daniel
+J. Bernstein to Project Athena on 11 March 1990
+
+I am the author of and sole copyright holder upon rcshar.
+
+I hereby waive copyright upon rcshar.  rcshar is hereby public domain.
+
+I hereby also waive copyright upon any works that are (1) derived from
+rcshar and (2) prepared between 11 March 1990 and 1 January 1991.
+
+Daniel J. Bernstein
+
+<signature>, dated 7 July 1990
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc-int.h b/krb5-1-6/src/lib/krb5/rcache/rc-int.h
new file mode 100644
index 000000000..2f09d239a
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc-int.h
@@ -0,0 +1,77 @@
+/*
+ * lib/krb5/keytab/rc-int.h
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * This file contains constant and function declarations used in the
+ * file-based replay cache routines.
+ */
+
+#ifndef __KRB5_RCACHE_INT_H__
+#define __KRB5_RCACHE_INT_H__
+
+int krb5int_rc_finish_init(void);
+
+void krb5int_rc_terminate(void);
+
+struct krb5_rc_st {
+    krb5_magic magic;
+    const struct _krb5_rc_ops *ops;
+    krb5_pointer data;
+    k5_mutex_t lock;
+};
+
+struct _krb5_rc_ops {
+    krb5_magic magic;
+    char *type;
+    krb5_error_code (KRB5_CALLCONV *init)
+	(krb5_context, krb5_rcache,krb5_deltat); /* create */
+    krb5_error_code (KRB5_CALLCONV *recover)
+	(krb5_context, krb5_rcache); /* open */
+    krb5_error_code (KRB5_CALLCONV *recover_or_init)
+	(krb5_context, krb5_rcache,krb5_deltat);
+    krb5_error_code (KRB5_CALLCONV *destroy)
+	(krb5_context, krb5_rcache);
+    krb5_error_code (KRB5_CALLCONV *close)
+	(krb5_context, krb5_rcache);
+    krb5_error_code (KRB5_CALLCONV *store)
+	(krb5_context, krb5_rcache,krb5_donot_replay *);
+    krb5_error_code (KRB5_CALLCONV *expunge)
+	(krb5_context, krb5_rcache);
+    krb5_error_code (KRB5_CALLCONV *get_span)
+	(krb5_context, krb5_rcache,krb5_deltat *);
+    char *(KRB5_CALLCONV *get_name)
+	(krb5_context, krb5_rcache);
+    krb5_error_code (KRB5_CALLCONV *resolve)
+	(krb5_context, krb5_rcache, char *);
+};
+
+typedef struct _krb5_rc_ops krb5_rc_ops;
+
+krb5_error_code krb5_rc_register_type (krb5_context, const krb5_rc_ops *);
+
+extern const krb5_rc_ops krb5_rc_dfl_ops;
+extern const krb5_rc_ops krb5_rc_none_ops;
+
+#endif /* __KRB5_RCACHE_INT_H__ */
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_base.c b/krb5-1-6/src/lib/krb5/rcache/rc_base.c
new file mode 100644
index 000000000..ad5c4e93c
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_base.c
@@ -0,0 +1,171 @@
+/*
+ * lib/krb5/rcache/rc_base.c
+ *
+ * This file of the Kerberos V5 software is derived from public-domain code
+ * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
+ */
+
+
+/*
+ * Base "glue" functions for the replay cache.
+ */
+
+#include "rc_base.h"
+#include "rc-int.h"
+#include "k5-thread.h"
+
+#define FREE(x) ((void) free((char *) (x)))
+
+struct krb5_rc_typelist {
+    const krb5_rc_ops *ops;
+    struct krb5_rc_typelist *next;
+};
+static struct krb5_rc_typelist none = { &krb5_rc_none_ops, 0 };
+static struct krb5_rc_typelist krb5_rc_typelist_dfl = { &krb5_rc_dfl_ops, &none };
+static struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl;
+static k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+int krb5int_rc_finish_init(void)
+{
+    return k5_mutex_finish_init(&rc_typelist_lock);
+}
+void krb5int_rc_terminate(void)
+{
+    struct krb5_rc_typelist *t, *t_next;
+    k5_mutex_destroy(&rc_typelist_lock);
+    for (t = typehead; t != &krb5_rc_typelist_dfl; t = t_next) {
+	t_next = t->next;
+	free(t);
+    }
+}
+
+krb5_error_code krb5_rc_register_type(krb5_context context,
+				      const krb5_rc_ops *ops)
+{
+    struct krb5_rc_typelist *t;
+    krb5_error_code err;
+    err = k5_mutex_lock(&rc_typelist_lock);
+    if (err)
+	return err;
+    for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next)
+	;
+    if (t) {
+	k5_mutex_unlock(&rc_typelist_lock);
+	return KRB5_RC_TYPE_EXISTS;
+    }
+    t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist));
+    if (t == NULL) {
+	k5_mutex_unlock(&rc_typelist_lock);
+	return KRB5_RC_MALLOC;
+    }
+    t->next = typehead;
+    t->ops = ops;
+    typehead = t;
+    k5_mutex_unlock(&rc_typelist_lock);
+    return 0;
+}
+
+krb5_error_code krb5_rc_resolve_type(krb5_context context, krb5_rcache *id,
+				     char *type)
+{
+    struct krb5_rc_typelist *t;
+    krb5_error_code err;
+    err = k5_mutex_lock(&rc_typelist_lock);
+    if (err)
+	return err;
+    for (t = typehead;t && strcmp(t->ops->type,type);t = t->next)
+	;
+    if (!t) {
+	k5_mutex_unlock(&rc_typelist_lock);
+	return KRB5_RC_TYPE_NOTFOUND;
+    }
+    /* allocate *id? nah */
+    (*id)->ops = t->ops;
+    k5_mutex_unlock(&rc_typelist_lock);
+    return k5_mutex_init(&(*id)->lock);
+}
+
+char * krb5_rc_get_type(krb5_context context, krb5_rcache id)
+{
+    return id->ops->type;
+}
+
+char * krb5_rc_default_type(krb5_context context)
+{
+    char *s;
+    if ((s = getenv("KRB5RCACHETYPE")))
+	return s;
+    else
+	return "dfl";
+}
+
+char * krb5_rc_default_name(krb5_context context)
+{
+    char *s;
+    if ((s = getenv("KRB5RCACHENAME")))
+	return s;
+    else
+	return (char *) 0;
+}
+
+krb5_error_code
+krb5_rc_default(krb5_context context, krb5_rcache *id)
+{
+    krb5_error_code retval;
+
+    if (!(*id = (krb5_rcache )malloc(sizeof(**id))))
+	return KRB5_RC_MALLOC;
+
+    if ((retval = krb5_rc_resolve_type(context, id, 
+				       krb5_rc_default_type(context)))) {
+	FREE(*id);
+	return retval;
+    }
+    if ((retval = krb5_rc_resolve(context, *id, 
+				  krb5_rc_default_name(context)))) {
+	k5_mutex_destroy(&(*id)->lock);
+	FREE(*id);
+	return retval;
+    }
+    (*id)->magic = KV5M_RCACHE;
+    return retval;
+}
+
+
+krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name)
+{
+    char *type;
+    char *residual;
+    krb5_error_code retval;
+    unsigned int diff;
+
+    if (!(residual = strchr(string_name,':')))
+	return KRB5_RC_PARSE;
+ 
+    diff = residual - string_name;
+    if (!(type = malloc(diff + 1)))
+	return KRB5_RC_MALLOC;
+    (void) strncpy(type, string_name, diff);
+    type[residual - string_name] = '\0';
+
+    if (!(*id = (krb5_rcache) malloc(sizeof(**id)))) {
+	FREE(type);
+	return KRB5_RC_MALLOC;
+    }
+
+    if ((retval = krb5_rc_resolve_type(context, id,type))) {
+	FREE(type);
+	FREE(*id);
+	return retval;
+    }
+    FREE(type);
+    if ((retval = krb5_rc_resolve(context, *id,residual + 1))) {
+	k5_mutex_destroy(&(*id)->lock);
+	FREE(*id);
+	return retval;
+    }
+    (*id)->magic = KV5M_RCACHE;
+    return retval;
+}
+
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_base.h b/krb5-1-6/src/lib/krb5/rcache/rc_base.h
new file mode 100644
index 000000000..e2e27677e
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_base.h
@@ -0,0 +1,15 @@
+/*
+ * lib/krb5/rcache/rc_base.h
+ *
+ * This file of the Kerberos V5 software is derived from public-domain code
+ * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
+ */
+
+#ifndef KRB5_RC_H
+#define KRB5_RC_H
+#include "k5-int.h"
+
+/* all the stuff that was here is now in rcache.h, included by krb5/krb5.h */
+
+#endif
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_conv.c b/krb5-1-6/src/lib/krb5/rcache/rc_conv.c
new file mode 100644
index 000000000..8eb73ccbe
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_conv.c
@@ -0,0 +1,38 @@
+/*
+ * lib/krb5/rcache/rc_conv.c
+ *
+ * This file of the Kerberos V5 software is derived from public-domain code
+ * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
+ */
+
+
+/*
+ * An implementation for the default replay cache type.
+ */
+
+#define FREE(x) ((void) free((char *) (x)))
+
+#include "rc_base.h"
+
+/*
+Local stuff:
+ krb5_auth_to_replay(context, krb5_tkt_authent *auth,krb5_donot_replay *rep)
+  given auth, take important information and make rep; return -1 if failed
+*/
+
+krb5_error_code
+krb5_auth_to_rep(krb5_context context, krb5_tkt_authent *auth, krb5_donot_replay *rep)
+{
+ krb5_error_code retval;
+ rep->cusec = auth->authenticator->cusec;
+ rep->ctime = auth->authenticator->ctime;
+ if ((retval = krb5_unparse_name(context, auth->ticket->server, &rep->server)))
+   return retval; /* shouldn't happen */
+ if ((retval = krb5_unparse_name(context, auth->authenticator->client,
+				 &rep->client))) {
+     FREE(rep->server);
+     return retval; /* shouldn't happen. */
+ }
+ return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_dfl.c b/krb5-1-6/src/lib/krb5/rcache/rc_dfl.c
new file mode 100644
index 000000000..d3f9aa846
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_dfl.c
@@ -0,0 +1,711 @@
+/*
+ * lib/krb5/rcache/rc_dfl.c
+ *
+ * This file of the Kerberos V5 software is derived from public-domain code
+ * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
+ */
+
+
+/*
+ * An implementation for the default replay cache type.
+ */
+#define FREE(x) ((void) free((char *) (x)))
+#include "rc_base.h"
+#include "rc_dfl.h"
+#include "rc_io.h"
+#include "k5-int.h"
+#include "rc-int.h"
+
+/*
+ * If NOIOSTUFF is defined at compile time, dfl rcaches will be per-process.
+ */
+
+/*
+Local stuff:
+
+static int hash(krb5_donot_replay *rep, int hsize)
+  returns hash value of *rep, between 0 and hsize - 1
+HASHSIZE
+  size of hash table (constant), can be preset
+static int cmp(krb5_donot_replay *old, krb5_donot_replay *new, krb5_deltat t)
+  compare old and new; return CMP_REPLAY or CMP_HOHUM
+static int alive(krb5_context, krb5_donot_replay *new, krb5_deltat t)
+  see if new is still alive; return CMP_EXPIRED or CMP_HOHUM
+CMP_MALLOC, CMP_EXPIRED, CMP_REPLAY, CMP_HOHUM
+  return codes from cmp(), alive(), and store()
+struct dfl_data
+  data stored in this cache type, namely "dfl"
+struct authlist
+  multilinked list of reps
+static int rc_store(context, krb5_rcache id, krb5_donot_replay *rep)
+  store rep in cache id; return CMP_REPLAY if replay, else CMP_MALLOC/CMP_HOHUM
+
+*/
+
+#ifndef HASHSIZE
+#define HASHSIZE 997 /* a convenient prime */
+#endif
+
+#ifndef EXCESSREPS
+#define EXCESSREPS 30
+#endif
+
+/*
+ * The rcache will be automatically expunged when the number of
+ * expired krb5_donot_replays encountered incidentally in searching
+ * exceeds the number of live krb5_donot_replays by EXCESSREPS. With
+ * the defaults here, a typical cache might build up some 10K of
+ * expired krb5_donot_replays before an automatic expunge, with the
+ * waste basically independent of the number of stores per minute.
+ *
+ * The rcache will also automatically be expunged when it encounters
+ * more than EXCESSREPS expired entries when recovering a cache in
+ * dfl_recover.
+ */
+
+static int
+hash(krb5_donot_replay *rep, int hsize)
+{
+    return (int) ((((rep->cusec + rep->ctime + *rep->server + *rep->client)
+		    % hsize) + hsize) % hsize);
+    /* We take this opportunity to once again complain about C's idiotic %. */
+}
+
+#define CMP_MALLOC -3
+#define CMP_EXPIRED -2
+#define CMP_REPLAY -1
+#define CMP_HOHUM 0
+
+/*ARGSUSED*/
+static int
+cmp(krb5_donot_replay *old, krb5_donot_replay *new1, krb5_deltat t)
+{
+    if ((old->cusec == new1->cusec) && /* most likely to distinguish */
+	(old->ctime == new1->ctime) &&
+	(strcmp(old->client, new1->client) == 0) &&
+	(strcmp(old->server, new1->server) == 0)) /* always true */
+	return CMP_REPLAY;
+    return CMP_HOHUM;
+}
+
+static int
+alive(krb5_int32 mytime, krb5_donot_replay *new1, krb5_deltat t)
+{
+    if (mytime == 0)
+	return CMP_HOHUM; /* who cares? */
+    /* I hope we don't have to worry about overflow */
+    if (new1->ctime + t < mytime)
+	return CMP_EXPIRED;
+    return CMP_HOHUM;
+}
+
+struct dfl_data
+{
+    char *name;
+    krb5_deltat lifespan;
+    int hsize;
+    int numhits;
+    int nummisses;
+    struct authlist **h;
+    struct authlist *a;
+#ifndef NOIOSTUFF
+    krb5_rc_iostuff d;
+#endif
+    char recovering;
+};
+
+struct authlist
+{
+    krb5_donot_replay rep;
+    struct authlist *na;
+    struct authlist *nh;
+};
+
+/* of course, list is backwards from file */
+/* hash could be forwards since we have to search on match, but naaaah */
+
+static int
+rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep,
+	 krb5_int32 now)
+{
+    struct dfl_data *t = (struct dfl_data *)id->data;
+    int rephash;
+    struct authlist *ta;
+
+    rephash = hash(rep, t->hsize);
+
+    for (ta = t->h[rephash]; ta; ta = ta->nh) {
+	switch(cmp(&ta->rep, rep, t->lifespan))
+	{
+	case CMP_REPLAY:
+	    return CMP_REPLAY;
+	case CMP_HOHUM:
+	    if (alive(now, &ta->rep, t->lifespan) == CMP_EXPIRED)
+		t->nummisses++;
+	    else
+		t->numhits++;
+	    break;
+	default:
+	    ; /* wtf? */
+	}
+    }
+
+    if (!(ta = (struct authlist *) malloc(sizeof(struct authlist))))
+	return CMP_MALLOC;
+    ta->na = t->a; t->a = ta;
+    ta->nh = t->h[rephash]; t->h[rephash] = ta;
+    ta->rep = *rep;
+    if (!(ta->rep.client = strdup(rep->client))) {
+	FREE(ta);
+	return CMP_MALLOC;
+    }
+    if (!(ta->rep.server = strdup(rep->server))) {
+	FREE(ta->rep.client);
+	FREE(ta);
+	return CMP_MALLOC;
+    }
+
+    return CMP_HOHUM;
+}
+
+char * KRB5_CALLCONV
+krb5_rc_dfl_get_name(krb5_context context, krb5_rcache id)
+{
+    return ((struct dfl_data *) (id->data))->name;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_get_span(krb5_context context, krb5_rcache id,
+		     krb5_deltat *lifespan)
+{
+    krb5_error_code err;
+    struct dfl_data *t;
+
+    err = k5_mutex_lock(&id->lock);
+    if (err)
+	return err;
+    t = (struct dfl_data *) id->data;
+    *lifespan = t->lifespan;
+    k5_mutex_unlock(&id->lock);
+    return 0;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_init_locked(krb5_context context, krb5_rcache id, krb5_deltat lifespan)
+{
+    struct dfl_data *t = (struct dfl_data *)id->data;
+    krb5_error_code retval;
+
+    t->lifespan = lifespan ? lifespan : context->clockskew;
+    /* default to clockskew from the context */
+#ifndef NOIOSTUFF
+    if ((retval = krb5_rc_io_creat(context, &t->d, &t->name))) {
+	return retval;
+    }
+    if ((krb5_rc_io_write(context, &t->d,
+			  (krb5_pointer) &t->lifespan, sizeof(t->lifespan))
+	 || krb5_rc_io_sync(context, &t->d))) {
+	return KRB5_RC_IO;
+    }
+#endif
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_init(krb5_context context, krb5_rcache id, krb5_deltat lifespan)
+{
+    krb5_error_code retval;
+
+    retval = k5_mutex_lock(&id->lock);
+    if (retval)
+	return retval;
+    retval = krb5_rc_dfl_init_locked(context, id, lifespan);
+    k5_mutex_unlock(&id->lock);
+    return retval;
+}
+
+/* Called with the mutex already locked.  */
+krb5_error_code
+krb5_rc_dfl_close_no_free(krb5_context context, krb5_rcache id)
+{
+    struct dfl_data *t = (struct dfl_data *)id->data;
+    struct authlist *q;
+
+    FREE(t->h);
+    if (t->name)
+	FREE(t->name);
+    while ((q = t->a))
+    {
+	t->a = q->na;
+	FREE(q->rep.client);
+	FREE(q->rep.server);
+	FREE(q);
+    }
+#ifndef NOIOSTUFF
+    (void) krb5_rc_io_close(context, &t->d);
+#endif
+    FREE(t);
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_close(krb5_context context, krb5_rcache id)
+{
+    krb5_error_code retval;
+    retval = k5_mutex_lock(&id->lock);
+    if (retval)
+	return retval;
+    krb5_rc_dfl_close_no_free(context, id);
+    k5_mutex_unlock(&id->lock);
+    k5_mutex_destroy(&id->lock);
+    free(id);
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_destroy(krb5_context context, krb5_rcache id)
+{
+#ifndef NOIOSTUFF
+    if (krb5_rc_io_destroy(context, &((struct dfl_data *) (id->data))->d))
+	return KRB5_RC_IO;
+#endif
+    return krb5_rc_dfl_close(context, id);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_resolve(krb5_context context, krb5_rcache id, char *name)
+{
+    struct dfl_data *t = 0;
+    krb5_error_code retval;
+
+    /* allocate id? no */
+    if (!(t = (struct dfl_data *) malloc(sizeof(struct dfl_data))))
+	return KRB5_RC_MALLOC;
+    id->data = (krb5_pointer) t;
+    memset(t, 0, sizeof(struct dfl_data));
+    if (name) {
+	t->name = malloc(strlen(name)+1);
+	if (!t->name) {
+	    retval = KRB5_RC_MALLOC;
+	    goto cleanup;
+	}
+	strcpy(t->name, name);
+    } else
+	t->name = 0;
+    t->numhits = t->nummisses = 0;
+    t->hsize = HASHSIZE; /* no need to store---it's memory-only */
+    t->h = (struct authlist **) malloc(t->hsize*sizeof(struct authlist *));
+    if (!t->h) {
+	retval = KRB5_RC_MALLOC;
+	goto cleanup;
+    }
+    memset(t->h, 0, t->hsize*sizeof(struct authlist *));
+    t->a = (struct authlist *) 0;
+#ifndef NOIOSTUFF
+    t->d.fd = -1;
+#endif
+    t->recovering = 0;
+    return 0;
+
+cleanup:
+    if (t) {
+	if (t->name)
+	    krb5_xfree(t->name);
+	if (t->h)
+	    krb5_xfree(t->h);
+	krb5_xfree(t);
+    }
+    return retval;
+}
+
+void
+krb5_rc_free_entry(krb5_context context, krb5_donot_replay **rep)
+{
+    krb5_donot_replay *rp = *rep;
+
+    *rep = NULL;
+    if (rp)
+    {
+	if (rp->client)
+	    free(rp->client);
+
+	if (rp->server)
+	    free(rp->server);
+	rp->client = NULL;
+	rp->server = NULL;
+	free(rp);
+    }
+}
+
+static krb5_error_code
+krb5_rc_io_fetch(krb5_context context, struct dfl_data *t,
+		 krb5_donot_replay *rep, int maxlen)
+{
+    int len2;
+    unsigned int len;
+    krb5_error_code retval;
+
+    rep->client = rep->server = 0;
+
+    retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len2,
+			     sizeof(len2));
+    if (retval)
+	return retval;
+
+    if ((len2 <= 0) || (len2 >= maxlen))
+	return KRB5_RC_IO_EOF;
+
+    len = len2;
+    rep->client = malloc (len);
+    if (!rep->client)
+	return KRB5_RC_MALLOC;
+
+    retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) rep->client, len);
+    if (retval)
+	goto errout;
+
+    retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len2, 
+			     sizeof(len2));
+    if (retval)
+	goto errout;
+
+    if ((len2 <= 0) || (len2 >= maxlen)) {
+	retval = KRB5_RC_IO_EOF;
+	goto errout;
+    }
+    len = len2;
+
+    rep->server = malloc (len);
+    if (!rep->server) {
+	retval = KRB5_RC_MALLOC;
+	goto errout;
+    }
+
+    retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) rep->server, len);
+    if (retval)
+	goto errout;
+
+    retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &rep->cusec,
+			     sizeof(rep->cusec));
+    if (retval)
+	goto errout;
+
+    retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &rep->ctime,
+			     sizeof(rep->ctime));
+    if (retval)
+	goto errout;
+
+    return 0;
+
+errout:
+    if (rep->client)
+	krb5_xfree(rep->client);
+    if (rep->server)
+	krb5_xfree(rep->server);
+    rep->client = rep->server = 0;
+    return retval;
+}
+
+
+static krb5_error_code
+krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id);
+
+static krb5_error_code
+krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id)
+{
+#ifdef NOIOSTUFF
+    return KRB5_RC_NOIO;
+#else
+
+    struct dfl_data *t = (struct dfl_data *)id->data;
+    krb5_donot_replay *rep = 0;
+    krb5_error_code retval;
+    long max_size;
+    int expired_entries = 0;
+    krb5_int32 now;
+
+    if ((retval = krb5_rc_io_open(context, &t->d, t->name))) {
+	return retval;
+    }
+
+    t->recovering = 1;
+
+    max_size = krb5_rc_io_size(context, &t->d);
+
+    rep = NULL;
+    if (krb5_rc_io_read(context, &t->d, (krb5_pointer) &t->lifespan,
+			sizeof(t->lifespan))) {
+	retval = KRB5_RC_IO;
+	goto io_fail;
+    }
+
+    if (!(rep = (krb5_donot_replay *) malloc(sizeof(krb5_donot_replay)))) {
+	retval = KRB5_RC_MALLOC;
+	goto io_fail;
+    }
+    rep->client = NULL;
+    rep->server = NULL;
+
+    if (krb5_timeofday(context, &now))
+	now = 0;
+
+    /* now read in each auth_replay and insert into table */
+    for (;;) {
+	if (krb5_rc_io_mark(context, &t->d)) {
+	    retval = KRB5_RC_IO;
+	    goto io_fail;
+	}
+
+	retval = krb5_rc_io_fetch(context, t, rep, (int) max_size);
+
+	if (retval == KRB5_RC_IO_EOF)
+	    break;
+	else if (retval != 0)
+	    goto io_fail;
+
+
+	if (alive(now, rep, t->lifespan) != CMP_EXPIRED) {
+	    if (rc_store(context, id, rep, now) == CMP_MALLOC) {
+		retval = KRB5_RC_MALLOC; goto io_fail;
+	    }
+	} else {
+	    expired_entries++;
+	}
+	/*
+	 *  free fields allocated by rc_io_fetch
+	 */
+	FREE(rep->server);
+	FREE(rep->client);
+	rep->server = 0;
+	rep->client = 0;
+    }
+    retval = 0;
+    krb5_rc_io_unmark(context, &t->d);
+    /*
+     *  An automatic expunge here could remove the need for
+     *  mark/unmark but that would be inefficient.
+     */
+io_fail:
+    krb5_rc_free_entry(context, &rep);
+    if (retval)
+	krb5_rc_io_close(context, &t->d);
+    else if (expired_entries > EXCESSREPS)
+	retval = krb5_rc_dfl_expunge_locked(context, id);
+    t->recovering = 0;
+    return retval;
+
+#endif
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_recover(krb5_context context, krb5_rcache id)
+{
+    krb5_error_code ret;
+    ret = k5_mutex_lock(&id->lock);
+    if (ret)
+	return ret;
+    ret = krb5_rc_dfl_recover_locked(context, id);
+    k5_mutex_unlock(&id->lock);
+    return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_recover_or_init(krb5_context context, krb5_rcache id,
+			    krb5_deltat lifespan)
+{
+    krb5_error_code retval;
+
+    retval = k5_mutex_lock(&id->lock);
+    if (retval)
+	return retval;
+    retval = krb5_rc_dfl_recover_locked(context, id);
+    if (retval)
+	retval = krb5_rc_dfl_init_locked(context, id, lifespan);
+    k5_mutex_unlock(&id->lock);
+    return retval;
+}
+
+static krb5_error_code
+krb5_rc_io_store(krb5_context context, struct dfl_data *t,
+		 krb5_donot_replay *rep)
+{
+    unsigned int clientlen, serverlen, len;
+    char *buf, *ptr;
+    krb5_error_code ret;
+
+    clientlen = strlen(rep->client) + 1;
+    serverlen = strlen(rep->server) + 1;
+    len = sizeof(clientlen) + clientlen + sizeof(serverlen) + serverlen +
+	sizeof(rep->cusec) + sizeof(rep->ctime);
+    buf = malloc(len);
+    if (buf == 0)
+	return KRB5_RC_MALLOC;
+    ptr = buf;
+    memcpy(ptr, &clientlen, sizeof(clientlen)); ptr += sizeof(clientlen);
+    memcpy(ptr, rep->client, clientlen); ptr += clientlen;
+    memcpy(ptr, &serverlen, sizeof(serverlen)); ptr += sizeof(serverlen);
+    memcpy(ptr, rep->server, serverlen); ptr += serverlen;
+    memcpy(ptr, &rep->cusec, sizeof(rep->cusec)); ptr += sizeof(rep->cusec);
+    memcpy(ptr, &rep->ctime, sizeof(rep->ctime)); ptr += sizeof(rep->ctime);
+
+    ret = krb5_rc_io_write(context, &t->d, buf, len);
+    free(buf);
+    return ret;
+}
+
+static krb5_error_code krb5_rc_dfl_expunge_locked(krb5_context, krb5_rcache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
+{
+    krb5_error_code ret;
+    struct dfl_data *t;
+    krb5_int32 now;
+
+    ret = krb5_timeofday(context, &now);
+    if (ret)
+	return ret;
+
+    ret = k5_mutex_lock(&id->lock);
+    if (ret)
+	return ret;
+
+    switch(rc_store(context, id, rep, now)) {
+    case CMP_MALLOC:
+	k5_mutex_unlock(&id->lock);
+	return KRB5_RC_MALLOC;
+    case CMP_REPLAY:
+	k5_mutex_unlock(&id->lock);
+	return KRB5KRB_AP_ERR_REPEAT;
+    case 0: break;
+    default: /* wtf? */ ;
+    }
+    t = (struct dfl_data *)id->data;
+#ifndef NOIOSTUFF
+    ret = krb5_rc_io_store(context, t, rep);
+    if (ret) {
+	k5_mutex_unlock(&id->lock);
+	return ret;
+    }
+#endif
+    /* Shall we automatically expunge? */
+    if (t->nummisses > t->numhits + EXCESSREPS)
+    {
+	ret = krb5_rc_dfl_expunge_locked(context, id);
+	k5_mutex_unlock(&id->lock);
+	return ret;
+    }
+#ifndef NOIOSTUFF
+    else
+    {
+	if (krb5_rc_io_sync(context, &t->d)) {
+	    k5_mutex_unlock(&id->lock);
+	    return KRB5_RC_IO;
+	}
+    }
+#endif
+    k5_mutex_unlock(&id->lock);
+    return 0;
+}
+
+static krb5_error_code
+krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
+{
+    struct dfl_data *t = (struct dfl_data *)id->data;
+#ifdef NOIOSTUFF
+    int i;
+    struct authlist **q;
+    struct authlist **qt;
+    struct authlist *r;
+    struct authlist *rt;
+    krb5_int32 now;
+
+    if (krb5_timestamp(context, &now))
+	now = 0;
+
+    for (q = &t->a; *q; q = qt) {
+	qt = &(*q)->na;
+	if (alive(now, &(*q)->rep, t->lifespan) == CMP_EXPIRED) {
+	    FREE((*q)->rep.client);
+	    FREE((*q)->rep.server);
+	    FREE(*q);
+	    *q = *qt; /* why doesn't this feel right? */
+	}
+    }
+    for (i = 0; i < t->hsize; i++)
+	t->h[i] = (struct authlist *) 0;
+    for (r = t->a; r; r = r->na) {
+	i = hash(&r->rep, t->hsize);
+	rt = t->h[i];
+	t->h[i] = r;
+	r->nh = rt;
+    }
+    return 0;
+#else
+    struct authlist *q;
+    char *name;
+    krb5_error_code retval = 0;
+    krb5_rcache tmp;
+    krb5_deltat lifespan = t->lifespan;  /* save original lifespan */
+
+    if (! t->recovering) {
+	name = t->name;
+	t->name = 0;		/* Clear name so it isn't freed */
+	(void) krb5_rc_dfl_close_no_free(context, id);
+	retval = krb5_rc_dfl_resolve(context, id, name);
+	free(name);
+	if (retval)
+	    return retval;
+	retval = krb5_rc_dfl_recover_locked(context, id);
+	if (retval)
+	    return retval;
+	t = (struct dfl_data *)id->data; /* point to recovered cache */
+    }
+
+    tmp = (krb5_rcache) malloc(sizeof(*tmp));
+    if (!tmp)
+	return ENOMEM;
+    retval = krb5_rc_resolve_type(context, &tmp, "dfl");
+    if (retval) {
+        free(tmp);
+        return retval;
+    }
+    retval = krb5_rc_resolve(context, tmp, 0);
+    if (retval)
+        goto cleanup;
+    retval = krb5_rc_initialize(context, tmp, lifespan);
+    if (retval)
+        goto cleanup;
+    for (q = t->a; q; q = q->na) {
+	if (krb5_rc_io_store(context, (struct dfl_data *)tmp->data, &q->rep)) {
+            retval = KRB5_RC_IO;
+            goto cleanup;
+        }
+    }
+    /* NOTE: We set retval in case we have an error */
+    retval = KRB5_RC_IO;
+    if (krb5_rc_io_sync(context, &((struct dfl_data *)tmp->data)->d))
+        goto cleanup;
+    if (krb5_rc_io_sync(context, &t->d))
+        goto cleanup;
+    if (krb5_rc_io_move(context, &t->d, &((struct dfl_data *)tmp->data)->d))
+        goto cleanup;
+    retval = 0;
+ cleanup:
+    (void) krb5_rc_dfl_close(context, tmp);
+    return retval;
+#endif
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_dfl_expunge(krb5_context context, krb5_rcache id)
+{
+    krb5_error_code ret;
+    ret = k5_mutex_lock(&id->lock);
+    if (ret)
+	return ret;
+    ret = krb5_rc_dfl_expunge_locked(context, id);
+    k5_mutex_unlock(&id->lock);
+    return ret;
+}
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_dfl.h b/krb5-1-6/src/lib/krb5/rcache/rc_dfl.h
new file mode 100644
index 000000000..d5fdd1a69
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_dfl.h
@@ -0,0 +1,56 @@
+/*
+ * lib/krb5/rcache/rc_dfl.h
+ *
+ * This file of the Kerberos V5 software is derived from public-domain code
+ * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
+ */
+
+/*
+ * Declarations for the default replay cache implementation.
+ */
+
+#ifndef KRB5_RC_DFL_H
+#define KRB5_RC_DFL_H
+
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_init 
+    	(krb5_context,
+		   krb5_rcache,
+		   krb5_deltat);
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_recover 
+	(krb5_context,
+		   krb5_rcache); 
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_recover_or_init
+    	(krb5_context, krb5_rcache, krb5_deltat);
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_destroy 
+	(krb5_context,
+		   krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_close 
+	(krb5_context,
+		   krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_store 
+	(krb5_context,
+		   krb5_rcache,
+		   krb5_donot_replay *);
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_expunge 
+	(krb5_context,
+		   krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_get_span 
+	(krb5_context,
+		   krb5_rcache,
+		   krb5_deltat *);
+char * KRB5_CALLCONV krb5_rc_dfl_get_name 
+	(krb5_context,
+		   krb5_rcache);
+krb5_error_code KRB5_CALLCONV krb5_rc_dfl_resolve 
+	(krb5_context,
+		   krb5_rcache,
+		   char *);
+krb5_error_code krb5_rc_dfl_close_no_free
+	(krb5_context,
+		   krb5_rcache);
+void krb5_rc_free_entry 
+	(krb5_context,
+		   krb5_donot_replay **);
+#endif
+
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_io.c b/krb5-1-6/src/lib/krb5/rcache/rc_io.c
new file mode 100644
index 000000000..adc6a8c49
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_io.c
@@ -0,0 +1,499 @@
+/*
+ * lib/krb5/rcache/rc_io.c
+ *
+ * This file of the Kerberos V5 software is derived from public-domain code
+ * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
+ */
+
+
+/*
+ * I/O functions for the replay cache default implementation.
+ */
+
+#if defined(_WIN32)
+#  define PATH_SEPARATOR "\\"
+#else
+#  define PATH_SEPARATOR "/"
+#endif
+
+#define KRB5_RC_VNO	0x0501		/* krb5, rcache v 1 */
+
+#include "k5-int.h"
+#include <stdio.h> /* for P_tmpdir */
+#include "rc_base.h"
+#include "rc_dfl.h"
+#include "rc_io.h"
+
+#ifndef O_BINARY
+#define O_BINARY    0
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#if !defined(_WINSOCKAPI_)
+#include <netinet/in.h>
+#endif
+#else
+#error find some way to use net-byte-order file version numbers.
+#endif
+
+#define FREE(x) ((void) free((char *) (x)))
+#define UNIQUE getpid() /* hopefully unique number */
+
+#define GETDIR (dir = getdir(), dirlen = strlen(dir) + sizeof(PATH_SEPARATOR) - 1)
+
+static char *
+getdir(void)
+{
+    char *dir;
+
+    if (!(dir = getenv("KRB5RCACHEDIR"))) {
+#if defined(_WIN32)
+	if (!(dir = getenv("TEMP")))
+	    if (!(dir = getenv("TMP")))
+		dir = "C:";
+#else
+	if (!(dir = getenv("TMPDIR"))) {
+#ifdef RCTMPDIR
+	    dir = RCTMPDIR;
+#else
+	    dir = "/tmp";
+#endif
+	}
+#endif
+    }
+    return dir;
+}
+
+krb5_error_code
+krb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
+{
+    char *c;
+    krb5_int16 rc_vno = htons(KRB5_RC_VNO);
+    krb5_error_code retval = 0;
+    int do_not_unlink = 0;
+    char *dir;
+    size_t dirlen;
+
+    GETDIR;
+    if (fn && *fn)
+    {
+	if (!(d->fn = malloc(strlen(*fn) + dirlen + 1)))
+	    return KRB5_RC_IO_MALLOC;
+	(void) strcpy(d->fn, dir);
+	(void) strcat(d->fn, PATH_SEPARATOR);
+	(void) strcat(d->fn, *fn);
+	d->fd = THREEPARAMOPEN(d->fn, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL |
+			       O_BINARY, 0600);
+    }
+    else
+    {
+	/* %d is max 11 digits (-, 10 digits of 32-bit number)
+	 * 11 + /krb5_RC + aaa = 24, +6 for slop */
+	if (!(d->fn = malloc(30 + dirlen)))
+	    return KRB5_RC_IO_MALLOC;
+	if (fn)
+	    if (!(*fn = malloc(35))) {
+		FREE(d->fn);
+		return KRB5_RC_IO_MALLOC;
+	    }
+	(void) sprintf(d->fn, "%s%skrb5_RC%d", dir, PATH_SEPARATOR,
+		       (int) UNIQUE);
+	c = d->fn + strlen(d->fn);
+	(void) strcpy(c, "aaa");
+	while ((d->fd = THREEPARAMOPEN(d->fn, O_WRONLY | O_CREAT | O_TRUNC |
+				       O_EXCL | O_BINARY, 0600)) == -1)
+	{
+	    if ((c[2]++) == 'z')
+	    {
+		c[2] = 'a';
+		if ((c[1]++) == 'z')
+		{
+		    c[1] = 'a';
+		    if ((c[0]++) == 'z')
+			break; /* sigh */
+		}
+	    }
+	}
+	if (fn)
+	    (void) strcpy(*fn, d->fn + dirlen);
+    }
+    if (d->fd == -1)
+    {
+	switch(errno)
+	{
+	case EFBIG:
+#ifdef EDQUOT
+	case EDQUOT:
+#endif
+	case ENOSPC:
+	    retval = KRB5_RC_IO_SPACE;
+	    goto cleanup;
+
+	case EIO:
+	    retval = KRB5_RC_IO_IO;
+	    goto cleanup;
+
+	case EPERM:
+	case EACCES:
+	case EROFS:
+	case EEXIST:
+	    retval = KRB5_RC_IO_PERM;
+	    krb5_set_error_message(context, retval,
+				   "Cannot create replay cache: %s",
+				   strerror(errno));
+	    do_not_unlink = 1;
+	    goto cleanup;
+
+	default:
+	    retval = KRB5_RC_IO_UNKNOWN;
+	    krb5_set_error_message(context, retval,
+				   "Cannot create replay cache: %s",
+				   strerror(errno));
+	    goto cleanup;
+	}
+    }
+    retval = krb5_rc_io_write(context, d, (krb5_pointer)&rc_vno,
+			      sizeof(rc_vno));
+    if (retval)
+	goto cleanup;
+
+    retval = krb5_rc_io_sync(context, d);
+
+ cleanup:
+    if (retval) {
+	if (d->fn) {
+	    if (!do_not_unlink)
+		(void) unlink(d->fn);
+	    FREE(d->fn);
+	    d->fn = NULL;
+	}
+	if (d->fd != -1) {
+	  (void) close(d->fd);
+	}
+    }
+    return retval;
+}
+
+static krb5_error_code
+krb5_rc_io_open_internal(krb5_context context, krb5_rc_iostuff *d, char *fn,
+			 char* full_pathname)
+{
+    krb5_int16 rc_vno;
+    krb5_error_code retval = 0;
+    int do_not_unlink = 1;
+#ifndef NO_USERID
+    struct stat statb;
+#endif
+    char *dir;
+    size_t dirlen;
+
+    GETDIR;
+    if (full_pathname) {
+	if (!(d->fn = malloc(strlen(full_pathname) + 1)))
+	    return KRB5_RC_IO_MALLOC;
+	(void) strcpy(d->fn, full_pathname);
+    } else {
+	if (!(d->fn = malloc(strlen(fn) + dirlen + 1)))
+	    return KRB5_RC_IO_MALLOC;
+	(void) strcpy(d->fn, dir);
+	(void) strcat(d->fn, PATH_SEPARATOR);
+	(void) strcat(d->fn, fn);
+    }
+
+#ifdef NO_USERID
+    d->fd = THREEPARAMOPEN(d->fn, O_RDWR | O_BINARY, 0600);
+#else
+    if ((d->fd = stat(d->fn, &statb)) != -1) {
+	uid_t me;
+
+	me = geteuid();
+	/* must be owned by this user, to prevent some security problems with
+	 * other users modifying replay cache stufff */
+	if ((statb.st_uid != me) || ((statb.st_mode & S_IFMT) != S_IFREG)) {
+	    FREE(d->fn);
+	    return KRB5_RC_IO_PERM;
+	}
+	d->fd = THREEPARAMOPEN(d->fn, O_RDWR | O_BINARY, 0600);
+    }
+#endif
+    if (d->fd == -1) {
+	switch(errno)
+	{
+	case EFBIG:
+#ifdef EDQUOT
+	case EDQUOT:
+#endif
+	case ENOSPC:
+	    retval = KRB5_RC_IO_SPACE;
+	    goto cleanup;
+
+	case EIO:
+	    retval = KRB5_RC_IO_IO;
+	    goto cleanup;
+
+	case EPERM:
+	case EACCES:
+	case EROFS:
+	    retval = KRB5_RC_IO_PERM;
+	    krb5_set_error_message (context, retval,
+				    "Cannot open replay cache %s: %s",
+				    d->fn, strerror(errno));
+	    goto cleanup;
+
+	default:
+	    retval = KRB5_RC_IO_UNKNOWN;
+	    krb5_set_error_message (context, retval,
+				    "Cannot open replay cache %s: %s",
+				    d->fn, strerror(errno));
+	    goto cleanup;
+	}
+    }
+
+    do_not_unlink = 0;
+    retval = krb5_rc_io_read(context, d, (krb5_pointer) &rc_vno,
+			     sizeof(rc_vno));
+    if (retval)
+	goto cleanup;
+
+    if (ntohs(rc_vno) != KRB5_RC_VNO)
+	retval = KRB5_RCACHE_BADVNO;
+
+ cleanup:
+    if (retval) {
+	if (d->fn) {
+	    if (!do_not_unlink)
+		(void) unlink(d->fn);
+	    FREE(d->fn);
+	    d->fn = NULL;
+	}
+	if (d->fd >= 0) 
+	     (void) close(d->fd);
+    }
+    return retval;
+}
+
+krb5_error_code
+krb5_rc_io_open(krb5_context context, krb5_rc_iostuff *d, char *fn)
+{
+    return krb5_rc_io_open_internal(context, d, fn, NULL);
+}
+
+krb5_error_code
+krb5_rc_io_move(krb5_context context, krb5_rc_iostuff *new1,
+		krb5_rc_iostuff *old)
+{
+#if defined(_WIN32) || defined(__CYGWIN__)
+    char *new_fn = NULL;
+    char *old_fn = NULL;
+    off_t offset = 0;
+    krb5_error_code retval = 0;
+    /*
+     * Initial work around provided by Tom Sanfilippo to work around
+     * poor Windows emulation of POSIX functions.  Rename and dup has
+     * different semantics!
+     *
+     * Additional fixes and explanation provided by dalmeida@mit.edu:
+     *
+     * First, we save the offset of "old".  Then, we close and remove
+     * the "new" file so we can do the rename.  We also close "old" to
+     * make sure the rename succeeds (though that might not be
+     * necessary on some systems).
+     *
+     * Next, we do the rename.  If all goes well, we seek the "new"
+     * file to the position "old" was at.
+     *
+     * --- WARNING!!! ---
+     *
+     * Since "old" is now gone, we mourn its disappearance, but we
+     * cannot emulate that Unix behavior...  THIS BEHAVIOR IS
+     * DIFFERENT FROM UNIX.  However, it is ok because this function
+     * gets called such that "old" gets closed right afterwards.
+     */
+    offset = lseek(old->fd, 0, SEEK_CUR);
+
+    new_fn = new1->fn;
+    new1->fn = NULL;
+    close(new1->fd);
+    new1->fd = -1;
+
+    unlink(new_fn);
+
+    old_fn = old->fn;
+    old->fn = NULL;
+    close(old->fd);
+    old->fd = -1;
+
+    if (rename(old_fn, new_fn) == -1) { /* MUST be atomic! */
+	retval = KRB5_RC_IO_UNKNOWN;
+	goto cleanup;
+    }
+
+    retval = krb5_rc_io_open_internal(context, new1, 0, new_fn);
+    if (retval)
+	goto cleanup;
+
+    if (lseek(new1->fd, offset, SEEK_SET) == -1) {
+	retval = KRB5_RC_IO_UNKNOWN;
+	goto cleanup;
+    }
+
+ cleanup:
+    free(new_fn);
+    free(old_fn);
+    return retval;
+#else
+    char *fn = NULL;
+    if (rename(old->fn, new1->fn) == -1) /* MUST be atomic! */
+	return KRB5_RC_IO_UNKNOWN;
+    fn = new1->fn;
+    new1->fn = NULL;		/* avoid clobbering */
+    (void) krb5_rc_io_close(context, new1);
+    new1->fn = fn;
+    new1->fd = dup(old->fd);
+    return 0;
+#endif
+}
+
+krb5_error_code
+krb5_rc_io_write(krb5_context context, krb5_rc_iostuff *d, krb5_pointer buf,
+		 unsigned int num)
+{
+    if (write(d->fd, (char *) buf, num) == -1)
+	switch(errno)
+	{
+#ifdef EDQUOT
+	case EDQUOT:
+#endif
+	case EFBIG:
+	case ENOSPC:
+	    krb5_set_error_message (context, KRB5_RC_IO_SPACE,
+				    "Can't write to replay cache: %s",
+				    strerror(errno));
+	    return KRB5_RC_IO_SPACE;
+	case EIO:
+	    krb5_set_error_message (context, KRB5_RC_IO_IO,
+				    "Can't write to replay cache: %s",
+				    strerror(errno));
+	    return KRB5_RC_IO_IO;
+	case EBADF:
+	default:
+	    krb5_set_error_message (context, KRB5_RC_IO_UNKNOWN,
+				    "Can't write to replay cache: %s",
+				    strerror(errno));
+	    return KRB5_RC_IO_UNKNOWN;
+	}
+    return 0;
+}
+
+krb5_error_code
+krb5_rc_io_sync(krb5_context context, krb5_rc_iostuff *d)
+{
+#if defined(_WIN32)
+#ifndef fsync
+#define fsync _commit
+#endif
+#endif
+    if (fsync(d->fd) == -1) {
+	switch(errno)
+	{
+	case EBADF: return KRB5_RC_IO_UNKNOWN;
+	case EIO: return KRB5_RC_IO_IO;
+	default:
+	    krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
+				   "Cannot sync replay cache file: %s",
+				   strerror(errno));
+	    return KRB5_RC_IO_UNKNOWN;
+	}
+    }
+    return 0;
+}
+
+krb5_error_code
+krb5_rc_io_read(krb5_context context, krb5_rc_iostuff *d, krb5_pointer buf,
+		unsigned int num)
+{
+    int count;
+    if ((count = read(d->fd, (char *) buf, num)) == -1)
+	switch(errno)
+	{
+	case EIO: return KRB5_RC_IO_IO;
+	case EBADF:
+	default:
+	    krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
+				   "Can't read from replay cache: %s",
+				   strerror(errno));
+	    return KRB5_RC_IO_UNKNOWN;
+	}
+    if (count == 0)
+	return KRB5_RC_IO_EOF;
+    return 0;
+}
+
+krb5_error_code
+krb5_rc_io_close(krb5_context context, krb5_rc_iostuff *d)
+{
+    if (d->fn != NULL) {
+	FREE(d->fn);
+	d->fn = NULL;
+    }
+    if (d->fd != -1) {
+	if (close(d->fd) == -1) /* can't happen */
+	    return KRB5_RC_IO_UNKNOWN;
+	d->fd = -1;
+    }
+    return 0;
+}
+
+krb5_error_code
+krb5_rc_io_destroy(krb5_context context, krb5_rc_iostuff *d)
+{
+    if (unlink(d->fn) == -1)
+	switch(errno)
+	{
+	case EIO:
+	    krb5_set_error_message(context, KRB5_RC_IO_IO,
+				   "Can't destroy replay cache: %s",
+				   strerror(errno));
+	    return KRB5_RC_IO_IO;
+	case EPERM:
+	case EBUSY:
+	case EROFS:
+	    krb5_set_error_message(context, KRB5_RC_IO_PERM,
+				   "Can't destroy replay cache: %s",
+				   strerror(errno));
+	    return KRB5_RC_IO_PERM;
+	case EBADF:
+	default:
+	    krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
+				   "Can't destroy replay cache: %s",
+				   strerror(errno));
+	    return KRB5_RC_IO_UNKNOWN;
+	}
+    return 0;
+}
+
+krb5_error_code
+krb5_rc_io_mark(krb5_context context, krb5_rc_iostuff *d)
+{
+    d->mark = lseek(d->fd, (off_t) 0, SEEK_CUR); /* can't fail */
+    return 0;
+}
+
+krb5_error_code
+krb5_rc_io_unmark(krb5_context context, krb5_rc_iostuff *d)
+{
+    (void) lseek(d->fd, d->mark, SEEK_SET); /* if it fails, tough luck */
+    return 0;
+}
+
+long
+krb5_rc_io_size(krb5_context context, krb5_rc_iostuff *d)
+{
+    struct stat statb;
+
+    if (fstat(d->fd, &statb) == 0)
+	return statb.st_size;
+    else
+	return 0;
+}
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_io.h b/krb5-1-6/src/lib/krb5/rcache/rc_io.h
new file mode 100644
index 000000000..77eb34f0b
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_io.h
@@ -0,0 +1,70 @@
+/*
+ * lib/krb5/rcache/rc_io.h
+ *
+ * This file of the Kerberos V5 software is derived from public-domain code
+ * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
+ */
+
+/*
+ * Declarations for the I/O sub-package of the replay cache
+ */
+
+#ifndef KRB5_RC_IO_H
+#define KRB5_RC_IO_H
+
+typedef struct krb5_rc_iostuff
+ {
+  int fd;
+#ifdef MSDOS_FILESYSTEM
+  long mark;
+#else
+  off_t mark; /* on newer systems, should be pos_t */
+#endif
+  char *fn;
+ }
+krb5_rc_iostuff;
+
+/* first argument is always iostuff for result file */
+
+krb5_error_code krb5_rc_io_creat 
+	(krb5_context,
+		   krb5_rc_iostuff *,
+		   char **);
+krb5_error_code krb5_rc_io_open 
+	(krb5_context,
+		   krb5_rc_iostuff *,
+		   char *);
+krb5_error_code krb5_rc_io_move 
+	(krb5_context,
+		   krb5_rc_iostuff *,
+		   krb5_rc_iostuff *);
+krb5_error_code krb5_rc_io_write 
+	(krb5_context,
+		   krb5_rc_iostuff *,
+		   krb5_pointer,
+		   unsigned int);
+krb5_error_code krb5_rc_io_read 
+	(krb5_context,
+		   krb5_rc_iostuff *,
+		   krb5_pointer,
+		   unsigned int);
+krb5_error_code krb5_rc_io_close 
+	(krb5_context,
+		   krb5_rc_iostuff *);
+krb5_error_code krb5_rc_io_destroy 
+	(krb5_context,
+		   krb5_rc_iostuff *);
+krb5_error_code krb5_rc_io_mark 
+	(krb5_context,
+		   krb5_rc_iostuff *);
+krb5_error_code krb5_rc_io_unmark 
+	(krb5_context,
+		   krb5_rc_iostuff *);
+krb5_error_code krb5_rc_io_sync
+	(krb5_context,
+		   krb5_rc_iostuff *);
+long krb5_rc_io_size
+	(krb5_context,
+		   krb5_rc_iostuff *);
+#endif
diff --git a/krb5-1-6/src/lib/krb5/rcache/rc_none.c b/krb5-1-6/src/lib/krb5/rcache/rc_none.c
new file mode 100644
index 000000000..a306f86fe
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rc_none.c
@@ -0,0 +1,88 @@
+/*
+ * lib/krb5/rcache/rc_none.c
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * replay cache no-op implementation
+ */
+
+#include "k5-int.h"
+#include "rc-int.h"
+
+static krb5_error_code KRB5_CALLCONV
+krb5_rc_none_init(krb5_context ctx, krb5_rcache rc, krb5_deltat d)
+{
+    return 0;
+}
+#define krb5_rc_none_recover_or_init krb5_rc_none_init
+
+static krb5_error_code KRB5_CALLCONV
+krb5_rc_none_noargs(krb5_context ctx, krb5_rcache rc)
+{
+    return 0;
+}
+#define krb5_rc_none_recover	krb5_rc_none_noargs
+#define krb5_rc_none_destroy	krb5_rc_none_noargs
+#define krb5_rc_none_close	krb5_rc_none_noargs
+#define krb5_rc_none_expunge	krb5_rc_none_noargs
+
+static krb5_error_code KRB5_CALLCONV
+krb5_rc_none_store(krb5_context ctx, krb5_rcache rc, krb5_donot_replay *r)
+{
+    return 0;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_rc_none_get_span(krb5_context ctx, krb5_rcache rc, krb5_deltat *d)
+{
+    return 0;
+}
+
+static char * KRB5_CALLCONV
+krb5_rc_none_get_name(krb5_context ctx, krb5_rcache rc)
+{
+    return "";
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_rc_none_resolve(krb5_context ctx, krb5_rcache rc, char *name)
+{
+    rc->data = "none";
+    return 0;
+}
+
+const krb5_rc_ops krb5_rc_none_ops = {
+    0,
+    "none",
+    krb5_rc_none_init,
+    krb5_rc_none_recover,
+    krb5_rc_none_recover_or_init,
+    krb5_rc_none_destroy,
+    krb5_rc_none_close,
+    krb5_rc_none_store,
+    krb5_rc_none_expunge,
+    krb5_rc_none_get_span,
+    krb5_rc_none_get_name,
+    krb5_rc_none_resolve
+};
diff --git a/krb5-1-6/src/lib/krb5/rcache/rcdef.c b/krb5-1-6/src/lib/krb5/rcache/rcdef.c
new file mode 100644
index 000000000..0aa334fa8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rcdef.c
@@ -0,0 +1,49 @@
+/*
+ * lib/krb5/rcache/rcdef.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * replay cache default operations vector.
+ */
+
+#include "k5-int.h"
+#include "rc-int.h"
+#include "rc_dfl.h"
+
+const krb5_rc_ops krb5_rc_dfl_ops =
+ {
+  0,
+  "dfl",
+  krb5_rc_dfl_init,
+  krb5_rc_dfl_recover,
+  krb5_rc_dfl_recover_or_init,
+  krb5_rc_dfl_destroy,
+  krb5_rc_dfl_close,
+  krb5_rc_dfl_store,
+  krb5_rc_dfl_expunge,
+  krb5_rc_dfl_get_span,
+  krb5_rc_dfl_get_name,
+  krb5_rc_dfl_resolve
+ }
+;
diff --git a/krb5-1-6/src/lib/krb5/rcache/rcfns.c b/krb5-1-6/src/lib/krb5/rcache/rcfns.c
new file mode 100644
index 000000000..bcbcaf4be
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/rcfns.c
@@ -0,0 +1,95 @@
+/*
+ * lib/krb5/rcache/rcfns.c
+ *
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Dispatch methods for replay cache code.
+ */
+
+#include "k5-int.h"
+#include "rc-int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_initialize (krb5_context context, krb5_rcache id, krb5_deltat span)
+{
+    return krb5_x(id->ops->init,(context, id, span));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_recover_or_initialize (krb5_context context, krb5_rcache id,
+			       krb5_deltat span)
+{
+    return krb5_x(id->ops->recover_or_init,(context, id, span));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_recover (krb5_context context, krb5_rcache id)
+{
+    return krb5_x((id)->ops->recover,(context, id));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_destroy (krb5_context context, krb5_rcache id)
+{
+    return krb5_x((id)->ops->destroy,(context, id));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_close (krb5_context context, krb5_rcache id)
+{
+    return krb5_x((id)->ops->close,(context, id));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_store (krb5_context context, krb5_rcache id,
+	       krb5_donot_replay *dontreplay)
+{
+    return krb5_x((id)->ops->store,(context, id, dontreplay));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_expunge (krb5_context context, krb5_rcache id)
+{
+    return krb5_x((id)->ops->expunge,(context, id));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_get_lifespan (krb5_context context, krb5_rcache id,
+		      krb5_deltat *spanp)
+{
+    return krb5_x((id)->ops->get_span,(context, id, spanp));
+}
+
+char *KRB5_CALLCONV
+krb5_rc_get_name (krb5_context context, krb5_rcache id)
+{
+    return krb5_xc((id)->ops->get_name,(context, id));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_rc_resolve (krb5_context context, krb5_rcache id, char *name)
+{
+    return krb5_x((id)->ops->resolve,(context, id, name));
+}
diff --git a/krb5-1-6/src/lib/krb5/rcache/ser_rc.c b/krb5-1-6/src/lib/krb5/rcache/ser_rc.c
new file mode 100644
index 000000000..0b3d098a8
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5/rcache/ser_rc.c
@@ -0,0 +1,208 @@
+/*
+ * lib/krb5/rcache/ser_rc.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * ser_rcdfl.c - Serialize replay cache context.
+ */
+#include "k5-int.h"
+#include "rc-int.h"
+
+/*
+ * Routines to deal with externalizing krb5_rcache.
+ *	krb5_rcache_size();
+ *	krb5_rcache_externalize();
+ *	krb5_rcache_internalize();
+ */
+static krb5_error_code krb5_rcache_size
+	(krb5_context, krb5_pointer, size_t *);
+static krb5_error_code krb5_rcache_externalize
+	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
+static krb5_error_code krb5_rcache_internalize
+	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
+
+/*
+ * Serialization entry for this type.
+ */
+static const krb5_ser_entry krb5_rcache_ser_entry = {
+    KV5M_RCACHE,			/* Type			*/
+    krb5_rcache_size,			/* Sizer routine	*/
+    krb5_rcache_externalize,		/* Externalize routine	*/
+    krb5_rcache_internalize		/* Internalize routine	*/
+};
+
+/*
+ * krb5_rcache_size()	- Determine the size required to externalize
+ *				  this krb5_rcache variant.
+ */
+static krb5_error_code
+krb5_rcache_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
+{
+    krb5_error_code	kret;
+    krb5_rcache		rcache;
+    size_t		required;
+
+    kret = EINVAL;
+    if ((rcache = (krb5_rcache) arg)) {
+	/*
+	 * Saving FILE: variants of krb5_rcache requires at minimum:
+	 *	krb5_int32	for KV5M_RCACHE
+	 *	krb5_int32	for length of rcache name.
+	 *	krb5_int32	for KV5M_RCACHE
+	 */
+	required = sizeof(krb5_int32) * 3;
+	if (rcache->ops && rcache->ops->type)
+	    required += (strlen(rcache->ops->type)+1);
+
+	/*
+	 * The rcache name is formed as follows:
+	 *	<type>:<name>
+	 */
+	required += strlen(krb5_rc_get_name(kcontext, rcache));
+
+	kret = 0;
+	*sizep += required;
+    }
+    return(kret);
+}
+
+/*
+ * krb5_rcache_externalize()	- Externalize the krb5_rcache.
+ */
+static krb5_error_code
+krb5_rcache_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_rcache		rcache;
+    size_t		required;
+    krb5_octet		*bp;
+    size_t		remain;
+    char		*rcname;
+    size_t		namelen;
+    char		*fnamep;
+
+    required = 0;
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    if ((rcache = (krb5_rcache) arg)) {
+	kret = ENOMEM;
+	if (!krb5_rcache_size(kcontext, arg, &required) &&
+	    (required <= remain)) {
+	    /* Our identifier */
+	    (void) krb5_ser_pack_int32(KV5M_RCACHE, &bp, &remain);
+
+	    /* Calculate the length of the name */
+	    namelen = (rcache->ops && rcache->ops->type) ?
+		strlen(rcache->ops->type)+1 : 0;
+	    fnamep = krb5_rc_get_name(kcontext, rcache);
+	    namelen += (strlen(fnamep)+1);
+
+	    if ((rcname = (char *) malloc(namelen))) {
+		/* Format the rcache name. */
+		if (rcache->ops && rcache->ops->type)
+		    sprintf(rcname, "%s:%s", rcache->ops->type, fnamep);
+		else
+		    strcpy(rcname, fnamep);
+
+		/* Put the length of the file name */
+		(void) krb5_ser_pack_int32((krb5_int32) strlen(rcname),
+					   &bp, &remain);
+		
+		/* Put the name */
+		(void) krb5_ser_pack_bytes((krb5_octet *) rcname,
+					   strlen(rcname),
+					   &bp, &remain);
+
+		/* Put the trailer */
+		(void) krb5_ser_pack_int32(KV5M_RCACHE, &bp, &remain);
+		kret = 0;
+		*buffer = bp;
+		*lenremain = remain;
+		free(rcname);
+	    }
+	}
+    }
+    return(kret);
+}
+
+/*
+ * krb5_rcache_internalize()	- Internalize the krb5_rcache.
+ */
+static krb5_error_code
+krb5_rcache_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
+{
+    krb5_error_code	kret;
+    krb5_rcache		rcache;
+    krb5_int32		ibuf;
+    krb5_octet		*bp;
+    size_t		remain;
+    char		*rcname;
+
+    bp = *buffer;
+    remain = *lenremain;
+    kret = EINVAL;
+    /* Read our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+	ibuf = 0;
+    if (ibuf == KV5M_RCACHE) {
+	kret = ENOMEM;
+
+	/* Get the length of the rcache name */
+	kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+
+	if (!kret &&
+	    (rcname = (char *) malloc((size_t) (ibuf+1))) &&
+	    !(kret = krb5_ser_unpack_bytes((krb5_octet *) rcname,
+					   (size_t) ibuf,
+					   &bp, &remain))) {
+	    rcname[ibuf] = '\0';
+	    if (!(kret = krb5_rc_resolve_full(kcontext, &rcache, rcname))) {
+		(void) krb5_rc_recover(kcontext, rcache);
+		if (!kret && 
+		    !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
+		    (ibuf == KV5M_RCACHE)) {
+		    *buffer = bp;
+		    *lenremain = remain;
+		    *argp = (krb5_pointer) rcache;
+		}
+		else
+		    krb5_rc_close(kcontext, rcache);
+	    }
+	    free(rcname);
+	}
+    }
+    return(kret);
+}
+
+/*
+ * Register the rcache serializer.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_ser_rcache_init(krb5_context kcontext)
+{
+    return(krb5_register_serializer(kcontext, &krb5_rcache_ser_entry));
+}
diff --git a/krb5-1-6/src/lib/krb5_32.def b/krb5-1-6/src/lib/krb5_32.def
new file mode 100644
index 000000000..5a13ae638
--- /dev/null
+++ b/krb5-1-6/src/lib/krb5_32.def
@@ -0,0 +1,302 @@
+;----------------------------------------------------
+;   KRB5.DEF - KRB5.DLL module definition file
+;----------------------------------------------------
+
+; ****************************************************************************
+; Do not add any function to this file until you make sure the calling
+; convention for the exported function is KRB5_CALLCONV
+; ****************************************************************************
+
+; Key:
+;
+; PRIVATE   - Private entrypoint.  It should not be called by anything other
+;             than gssapi32.dll or krb4_32.dll.
+; GSSAPI    - Private entrypoint used by gssapi32.dll.
+; KRB4      - Private entrypoint used by krb4_32.dll.
+; KRB5_CALLCONV_WRONG - entrypoint that should have used KRB5_CALLCONV, but
+;                       did not due to developer error
+
+EXPORTS
+
+	krb5_425_conv_principal			@10
+	krb5_524_conv_principal			@11
+	krb5_address_compare			@13
+	krb5_address_order			@14
+	krb5_address_search			@15	; KRB5_CALLCONV_WRONG
+	krb5_aname_to_localname			@16
+	krb5_appdefault_boolean			@17
+	krb5_appdefault_string			@18
+	krb5_auth_con_free			@19
+	krb5_auth_con_genaddrs			@20
+	krb5_auth_con_getaddrs			@21
+	krb5_auth_con_getauthenticator		@22
+	krb5_auth_con_get_checksum_func		@23
+	krb5_auth_con_getflags			@24
+	krb5_auth_con_getkey			@25
+	krb5_auth_con_getlocalseqnumber		@26
+	krb5_auth_con_getlocalsubkey		@27
+	krb5_auth_con_getrcache			@28	; KRB5_CALLCONV_WRONG
+	krb5_auth_con_getrecvsubkey		@29	
+	krb5_auth_con_getremoteseqnumber	@30
+	krb5_auth_con_getremotesubkey		@31
+	krb5_auth_con_getsendsubkey		@32
+	krb5_auth_con_init			@33
+	krb5_auth_con_initivector		@34	; DEPRECATED
+	krb5_auth_con_set_checksum_func		@35
+	krb5_auth_con_setaddrs			@37	; KRB5_CALLCONV_WRONG
+	krb5_auth_con_setflags			@38
+	krb5_auth_con_setports			@39
+	krb5_auth_con_setrcache			@40
+	krb5_auth_con_setrecvsubkey		@41
+	krb5_auth_con_setsendsubkey		@42
+	krb5_auth_con_setuseruserkey		@43
+	krb5_build_principal			@44
+	krb5_build_principal_ext		@45
+	krb5_build_principal_va			@46
+	krb5_c_block_size			@47
+	krb5_c_checksum_length			@48
+	krb5_c_decrypt				@49
+	krb5_c_encrypt				@50
+	krb5_c_encrypt_length			@51
+	krb5_c_enctype_compare			@52
+	krb5_c_is_coll_proof_cksum		@53
+	krb5_c_is_keyed_cksum			@54
+	krb5_c_keyed_checksum_types		@55
+	krb5_c_make_checksum			@56
+	krb5_c_make_random_key			@57
+ 	krb5_c_prf				@58
+ 	krb5_c_prf_length			@59
+	krb5_c_random_make_octets		@60
+	krb5_c_random_seed			@61
+	krb5_c_string_to_key			@62
+ 	krb5_c_string_to_key_with_params	@63
+	krb5_c_valid_cksumtype			@64
+	krb5_c_valid_enctype			@65
+	krb5_c_verify_checksum			@66
+	krb5_calculate_checksum			@67
+	krb5_cc_close				@68
+	krb5_cc_copy_creds			@69
+	krb5_cc_default				@70
+	krb5_cc_default_name			@71
+	krb5_cc_destroy				@72
+	krb5_cc_end_seq_get			@73
+	krb5_cc_gen_new				@74
+	krb5_cc_get_name			@75
+	krb5_cc_get_principal			@76
+	krb5_cc_get_type			@77
+	krb5_cc_initialize			@78
+	krb5_cc_new_unique			@79
+	krb5_cc_next_cred			@80
+	krb5_cc_remove_cred			@81
+	krb5_cc_resolve				@82
+	krb5_cc_retrieve_cred			@83
+	krb5_cc_set_default_name		@84
+	krb5_cc_set_flags			@85
+	krb5_cc_start_seq_get			@86
+	krb5_cc_store_cred			@87
+	krb5_cccol_cursor_free			@88
+	krb5_cccol_cursor_new			@89
+	krb5_cccol_cursor_next			@90
+	krb5_change_password			@91
+	krb5_checksum_size			@92
+	krb5_cksumtype_to_string		@93
+	krb5_copy_addresses			@95 
+	krb5_copy_authdata			@96 
+	krb5_copy_authenticator			@97 
+	krb5_copy_checksum			@98 
+	krb5_copy_context			@99 
+	krb5_copy_creds				@100
+	krb5_copy_data				@101
+	krb5_copy_keyblock			@102
+	krb5_copy_keyblock_contents		@103
+	krb5_copy_principal			@104
+	krb5_copy_ticket			@105
+	krb5_decode_ticket			@106
+	krb5_decrypt				@107
+	krb5_deltat_to_string			@109
+	krb5_eblock_enctype			@110
+	krb5_encrypt				@111
+	krb5_encrypt_size			@112
+	krb5_enctype_to_string			@113
+	krb5_finish_key				@115
+	krb5_finish_random_key			@116
+	krb5_free_addresses			@117
+	krb5_free_ap_rep_enc_part		@118
+	krb5_free_authdata			@120
+	krb5_free_authenticator			@121
+	krb5_free_checksum			@122
+	krb5_free_checksum_contents		@123
+	krb5_free_cksumtypes			@124
+	krb5_free_config_files			@125
+	krb5_free_context			@126
+	krb5_free_cred_contents			@127
+	krb5_free_creds				@128
+	krb5_free_data				@129
+	krb5_free_data_contents			@130
+	krb5_free_default_realm			@131
+	krb5_free_error				@133
+	krb5_free_host_realm			@135
+	krb5_free_keyblock			@136
+	krb5_free_keyblock_contents		@137
+	krb5_free_keytab_entry_contents		@138
+	krb5_free_principal			@140
+	krb5_free_tgt_creds			@141
+	krb5_free_ticket			@142
+	krb5_free_unparsed_name			@143
+	krb5_fwd_tgt_creds			@144
+	krb5_get_credentials			@145
+	krb5_get_credentials_renew		@146
+	krb5_get_credentials_validate		@147
+	krb5_get_default_config_files		@148
+	krb5_get_default_realm			@149
+	krb5_get_host_realm			@151
+	krb5_get_in_tkt				@152	; DEPRECATED
+	krb5_get_in_tkt_with_keytab		@153	; DEPRECATED
+	krb5_get_in_tkt_with_password		@154	; DEPRECATED
+	krb5_get_in_tkt_with_skey		@155	; DEPRECATED
+	krb5_get_init_creds_keytab		@156
+	krb5_get_init_creds_opt_alloc		@157
+	krb5_get_init_creds_opt_free		@158
+	krb5_get_init_creds_opt_free_pa		@159
+	krb5_get_init_creds_opt_get_pa		@160
+	krb5_get_init_creds_opt_init		@161
+	krb5_get_init_creds_opt_set_address_list	    @162
+	krb5_get_init_creds_opt_set_change_password_prompt  @163
+	krb5_get_init_creds_opt_set_etype_list		    @164
+	krb5_get_init_creds_opt_set_forwardable		    @165
+	krb5_get_init_creds_opt_set_pa			    @166	    
+	krb5_get_init_creds_opt_set_preauth_list	    @167
+	krb5_get_init_creds_opt_set_proxiable		    @168
+	krb5_get_init_creds_opt_set_renew_life		    @169
+	krb5_get_init_creds_opt_set_salt		    @170
+	krb5_get_init_creds_opt_set_tkt_life		    @171
+	krb5_get_init_creds_password		@172
+	krb5_get_permitted_enctypes		@173
+	krb5_get_profile			@269
+	krb5_get_prompt_types			@174
+	krb5_get_renewed_creds			@175
+	krb5_get_server_rcache			@176
+	krb5_get_time_offsets			@178
+	krb5_get_validated_creds		@179
+	krb5_init_context			@180
+	krb5_init_keyblock			@181
+	krb5_init_random_key			@182
+	krb5_init_secure_context		@183
+	krb5_is_referral_realm			@185
+        krb5_is_thread_safe			@186
+	krb5_kt_add_entry			@187
+	krb5_kt_close				@188
+	krb5_kt_default				@189
+	krb5_kt_default_name			@190
+	krb5_kt_end_seq_get			@191
+	krb5_kt_get_entry			@193
+	krb5_kt_get_name			@194
+	krb5_kt_get_type			@195
+	krb5_kt_next_entry			@196
+	krb5_kt_read_service_key		@197
+	krb5_kt_remove_entry			@198
+	krb5_kt_resolve				@199
+	krb5_kt_start_seq_get			@200
+	krb5_kuserok				@201
+	krb5_mk_1cred				@202
+	krb5_mk_error				@203
+	krb5_mk_ncred				@204
+	krb5_mk_priv				@205
+	krb5_mk_rep				@206
+	krb5_mk_req				@207
+	krb5_mk_req_extended			@208
+	krb5_mk_safe				@209
+	krb5_os_localaddr			@210
+	krb5_parse_name				@211
+	krb5_principal2salt                     @212	; KRB5_CALLCONV_WRONG
+	krb5_principal_compare			@213
+	krb5_process_key			@214
+	krb5_prompter_posix			@215
+	krb5_random_key				@216
+	krb5_rd_cred				@218
+	krb5_rd_error				@219
+	krb5_rd_priv				@220
+	krb5_rd_rep				@221
+	krb5_rd_req				@222
+	krb5_rd_safe				@223
+	krb5_read_password			@224
+	krb5_realm_compare			@225
+	krb5_recvauth				@226
+	krb5_recvauth_version			@227
+	krb5_salttype_to_string			@228
+	krb5_sendauth				@229
+	krb5_server_decrypt_ticket_keytab	@239
+	krb5_set_default_realm			@240
+	krb5_set_default_tgs_enctypes		@241
+        krb5_set_password			@243
+        krb5_set_password_using_ccache		@244
+	krb5_set_principal_realm		@245
+	krb5_set_real_time			@246
+	krb5_sname_to_principal			@248
+	krb5_string_to_cksumtype		@249
+	krb5_string_to_deltat			@250
+	krb5_string_to_enctype			@251
+	krb5_string_to_key			@252
+	krb5_string_to_salttype			@253
+	krb5_string_to_timestamp		@254
+	krb5_timeofday				@255
+	krb5_timestamp_to_sfstring		@256
+	krb5_timestamp_to_string		@257
+	krb5_unparse_name			@258
+	krb5_unparse_name_ext			@259
+	krb5_us_timeofday			@260
+	krb5_use_enctype			@261
+	krb5_verify_checksum			@262
+	krb5_verify_init_creds			@263
+	krb5_verify_init_creds_opt_init		@264
+	krb5_verify_init_creds_opt_set_ap_req_nofail	@265
+
+	krb5_524_convert_creds			@12
+; Don't add krb524_convert_creds_kdc or krb524_init_ets here;
+; they've never been exported by this library, and are deprecated. -KR
+
+	krb5int_accessor			@267	; INTERNAL (to end all internals)
+
+
+; Temporary exports (DO NOT USE)
+
+; DO NOT USE -- Currently required for krb4_32.dll
+	des_ecb_encrypt				@3	; PRIVATE KRB4
+	des_new_random_key			@6	; PRIVATE KRB4
+	des_key_sched				@5 	; PRIVATE KRB4
+	des_pcbc_encrypt			@7	; PRIVATE KRB4
+	des_quad_cksum				@8	; PRIVATE KRB4
+	des_string_to_key			@9	; PRIVATE KRB4
+	des_init_random_number_generator	@4	; PRIVATE KRB4
+	afs_string_to_key			@1	; PRIVATE KRB4
+
+; DO NOT USE -- Currently required to implement gssapi32.dll
+	decode_krb5_ap_req			@2	; PRIVATE GSSAPI k5-int.h KRB5_CALLCONV_WRONG
+	krb5_externalize_opaque			@114	; PRIVATE GSSAPI k5-int.h
+	krb5_internalize_opaque			@184	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_auth_context_init		@230	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_ccache_init			@231	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_context_init			@232	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_keytab_init			@233	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_pack_bytes			@234	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_pack_int32			@235	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_rcache_init			@236	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_unpack_bytes			@237	; PRIVATE GSSAPI k5-int.h
+	krb5_ser_unpack_int32			@238	; PRIVATE GSSAPI k5-int.h
+	krb5_size_opaque			@247	; PRIVATE GSSAPI k5-int.h
+	krb5int_cc_default			@268	; PRIVATE GSSAPI k5-int.h
+
+	krb5_free_ap_req			@119	; PRIVATE GSSAPI krb5.hin
+	krb5_free_ktypes			@139	; PRIVATE GSSAPI krb5.hin
+	krb5_get_tgs_ktypes			@177	; PRIVATE GSSAPI krb5.hin
+	krb5_auth_con_set_req_cksumtype		@36	; PRIVATE GSSAPI krb5.hin
+	krb5_kt_free_entry			@192	; PRIVATE GSSAPI krb5.hin
+	krb5_rc_close				@217	; PRIVATE GSSAPI krb5.hin
+	krb5_free_enc_tkt_part			@132	; PRIVATE GSSAPI krb5.hin
+	krb5_decrypt_tkt_part			@108	; PRIVATE GSSAPI krb5.hin
+
+	krb5_set_error_message			@242
+	krb5_vset_error_message			@266
+	krb5_get_error_message			@150
+	krb5_free_error_message			@134
+	krb5_clear_error_message		@94
diff --git a/krb5-1-6/src/lib/rpc/Makefile.in b/krb5-1-6/src/lib/rpc/Makefile.in
new file mode 100644
index 000000000..729290ad6
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/Makefile.in
@@ -0,0 +1,549 @@
+thisconfigdir=../..
+myfulldir=lib/rpc
+mydir=lib/rpc
+BUILDTOP=$(REL)..$(S)..
+DEFINES = -DGSSAPI_KRB5 -DDEBUG_GSSAPI=0 -DGSSRPC__IMPL
+DEFS=
+
+SUBDIRS=unit-test
+
+##DOSBUILDTOP = ..\..
+##DOSLIBNAME=libgssrpc.lib
+
+LIBBASE=gssrpc
+LIBMAJOR=4
+LIBMINOR=0
+STOBJLISTS=OBJS.ST
+SHLIB_EXPDEPS= \
+	$(TOPLIBD)/libgssapi_krb5$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT) \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(COM_ERR_DEPLIB)
+SHLIB_EXPLIBS=-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+RELDIR=rpc
+
+SRCS = $(srcdir)/auth_none.c \
+	$(srcdir)/auth_unix.c \
+	$(srcdir)/authgss_prot.c \
+	$(srcdir)/authunix_prot.c \
+	$(srcdir)/auth_gss.c \
+	$(srcdir)/auth_gssapi.c \
+	$(srcdir)/auth_gssapi_misc.c \
+	$(srcdir)/bindresvport.c \
+	$(srcdir)/clnt_generic.c \
+	$(srcdir)/clnt_perror.c \
+	$(srcdir)/clnt_raw.c \
+	$(srcdir)/clnt_simple.c \
+	$(srcdir)/clnt_tcp.c \
+	$(srcdir)/clnt_udp.c \
+	$(srcdir)/dyn.c \
+	$(srcdir)/rpc_dtablesize.c \
+	$(srcdir)/get_myaddress.c \
+	$(srcdir)/getrpcport.c \
+	$(srcdir)/pmap_clnt.c \
+	$(srcdir)/pmap_getmaps.c \
+	$(srcdir)/pmap_getport.c \
+	$(srcdir)/pmap_prot.c \
+	$(srcdir)/pmap_prot2.c \
+	$(srcdir)/pmap_rmt.c \
+	$(srcdir)/rpc_prot.c \
+	$(srcdir)/rpc_commondata.c \
+	$(srcdir)/rpc_callmsg.c \
+	$(srcdir)/svc.c \
+	$(srcdir)/svc_auth.c \
+	$(srcdir)/svc_auth_gss.c \
+	$(srcdir)/svc_auth_none.c \
+	$(srcdir)/svc_auth_unix.c \
+	$(srcdir)/svc_auth_gssapi.c \
+	$(srcdir)/svc_raw.c \
+	$(srcdir)/svc_run.c \
+	$(srcdir)/svc_simple.c \
+	$(srcdir)/svc_tcp.c \
+	$(srcdir)/svc_udp.c \
+	$(srcdir)/xdr.c \
+	$(srcdir)/xdr_array.c \
+	$(srcdir)/xdr_float.c \
+	$(srcdir)/xdr_mem.c \
+	$(srcdir)/xdr_rec.c \
+	$(srcdir)/xdr_reference.c \
+	$(srcdir)/xdr_stdio.c \
+	$(srcdir)/xdr_alloc.c
+
+OBJS = auth_none.$(OBJEXT) \
+	auth_unix.$(OBJEXT) \
+	authunix_prot.$(OBJEXT) \
+	authgss_prot.$(OBJEXT) \
+	auth_gss.$(OBJEXT) \
+	auth_gssapi.$(OBJEXT) \
+	auth_gssapi_misc.$(OBJEXT) \
+	bindresvport.$(OBJEXT) \
+	clnt_generic.$(OBJEXT) \
+	clnt_perror.$(OBJEXT) \
+	clnt_raw.$(OBJEXT) \
+	clnt_simple.$(OBJEXT) \
+	clnt_tcp.$(OBJEXT) \
+	clnt_udp.$(OBJEXT) \
+	dyn.$(OBJEXT) \
+	rpc_dtablesize.$(OBJEXT) \
+	get_myaddress.$(OBJEXT) \
+	getrpcport.$(OBJEXT) \
+	pmap_clnt.$(OBJEXT) \
+	pmap_getmaps.$(OBJEXT) \
+	pmap_getport.$(OBJEXT) \
+	pmap_prot.$(OBJEXT) \
+	pmap_prot2.$(OBJEXT) \
+	pmap_rmt.$(OBJEXT) \
+	rpc_prot.$(OBJEXT) \
+	rpc_commondata.$(OBJEXT) \
+	rpc_callmsg.$(OBJEXT) \
+	svc.$(OBJEXT) \
+	svc_auth.$(OBJEXT) \
+	svc_auth_gss.$(OBJEXT) \
+	svc_auth_none.$(OBJEXT) \
+	svc_auth_unix.$(OBJEXT) \
+	svc_auth_gssapi.$(OBJEXT) \
+	svc_raw.$(OBJEXT) \
+	svc_run.$(OBJEXT) \
+	svc_simple.$(OBJEXT) \
+	svc_tcp.$(OBJEXT) \
+	svc_udp.$(OBJEXT) \
+	xdr.$(OBJEXT) \
+	xdr_array.$(OBJEXT) \
+	xdr_float.$(OBJEXT) \
+	xdr_mem.$(OBJEXT) \
+	xdr_rec.$(OBJEXT) \
+	xdr_reference.$(OBJEXT) \
+	xdr_stdio.$(OBJEXT) \
+	xdr_alloc.$(OBJEXT)
+
+STLIBOBJS = \
+	auth_none.o \
+	auth_unix.o \
+	authgss_prot.o \
+	authunix_prot.o \
+	auth_gss.o \
+	auth_gssapi.o \
+	auth_gssapi_misc.o \
+	bindresvport.o \
+	clnt_generic.o \
+	clnt_perror.o \
+	clnt_raw.o \
+	clnt_simple.o \
+	clnt_tcp.o \
+	clnt_udp.o \
+	dyn.o \
+	rpc_dtablesize.o \
+	get_myaddress.o \
+	getrpcport.o \
+	pmap_clnt.o \
+	pmap_getmaps.o \
+	pmap_getport.o \
+	pmap_prot.o \
+	pmap_prot2.o \
+	pmap_rmt.o \
+	rpc_prot.o \
+	rpc_commondata.o \
+	rpc_callmsg.o \
+	svc.o \
+	svc_auth.o \
+	svc_auth_gss.o \
+	svc_auth_gssapi.o \
+	svc_auth_none.o \
+	svc_auth_unix.o \
+	svc_raw.o \
+	svc_run.o \
+	svc_simple.o \
+	svc_tcp.o \
+	svc_udp.o \
+	xdr.o \
+	xdr_array.o \
+	xdr_float.o \
+	xdr_mem.o \
+	xdr_rec.o \
+	xdr_reference.o \
+	xdr_stdio.o \
+	xdr_alloc.o
+
+HDRDIR=$(BUILDTOP)/include/gssrpc
+
+all-prerecurse: all-liblinks
+
+all-windows:: $(OBJS)
+
+install-unix:: install-libs
+
+install-unix::
+	for i in $(SRC_HDRS); do \
+		(set -x; $(INSTALL_DATA) $(srcdir)/../../include/gssrpc/$$i $(DESTDIR)$(KRB5_INCDIR)$(S)gssrpc$(S)$$i) ; \
+	done
+	for i in $(BUILD_HDRS); do \
+		(set -x; $(INSTALL_DATA) ../../include/gssrpc/$$i $(DESTDIR)$(KRB5_INCDIR)$(S)gssrpc$(S)$$i) ; \
+	done
+
+BUILD_HDRS = types.h
+SRC_HDRS = auth.h auth_gss.h auth_gssapi.h auth_unix.h clnt.h \
+	netdb.h pmap_clnt.h pmap_prot.h pmap_rmt.h rename.h \
+	rpc.h rpc_msg.h svc.h svc_auth.h xdr.h
+
+check-windows::
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+clean-windows::
+
+# stuff picked up from old "dyn" library
+#check-unix:: run-dyntest
+run-dyntest: dyntest
+	./dyntest
+dyntest: dyntest.o dyn.o
+	$(CC) -o dyntest dyntest.o dyn.o
+clean-unix:: clean-dyntest
+clean-dyntest:
+	$(RM) dyntest dyntest.o
+
+LCLINT=		lclint
+# +posixlib     gets more complete errno list than ansilib
+# -usedef       turns off bogus warnings from poor dataflow analysis (should be
+#               redundant with gcc warnings anyways)
+# -warnposix
+# +charintliteral
+# +ignoresigns
+# -predboolint
+# -exportlocal
+# -retvalint    allow ignoring of int return values (e.g., fputs)
+LCLINTOPTS=+posixlib \
+        +ignoresigns -predboolint \
+        +mod-uncon +modinternalstrict +modfilesys \
+        -expect 2
+do-dyn-lclint::
+	$(LCLINT) $(LCLINTOPTS) $(LOCALINCLUDES) $(DEFS) dyn.c dyntest.c
+
+$(BUILDTOP)/include/gssrpc/types.h: types.stamp
+types.stamp: $(SRCTOP)/include/gssrpc/types.hin $(thisconfigdir)/config.status
+	cd $(thisconfigdir) && $(SHELL) config.status include/gssrpc/types.h
+	touch types.stamp
+
+clean-unix::
+	$(RM) types.stamp
+clean-windows::
+	$(RM) types.stamp
+
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+auth_none.so auth_none.po $(OUTPRE)auth_none.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  auth_none.c
+auth_unix.so auth_unix.po $(OUTPRE)auth_unix.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  auth_unix.c
+authgss_prot.so authgss_prot.po $(OUTPRE)authgss_prot.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  authgss_prot.c
+authunix_prot.so authunix_prot.po $(OUTPRE)authunix_prot.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h authunix_prot.c
+auth_gss.so auth_gss.po $(OUTPRE)auth_gss.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h auth_gss.c
+auth_gssapi.so auth_gssapi.po $(OUTPRE)auth_gssapi.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_gssapi.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/krb5.h auth_gssapi.c
+auth_gssapi_misc.so auth_gssapi_misc.po $(OUTPRE)auth_gssapi_misc.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_gssapi.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h auth_gssapi_misc.c
+bindresvport.so bindresvport.po $(OUTPRE)bindresvport.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  bindresvport.c
+clnt_generic.so clnt_generic.po $(OUTPRE)clnt_generic.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h clnt_generic.c
+clnt_perror.so clnt_perror.po $(OUTPRE)clnt_perror.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  clnt_perror.c
+clnt_raw.so clnt_raw.po $(OUTPRE)clnt_raw.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  clnt_raw.c
+clnt_simple.so clnt_simple.po $(OUTPRE)clnt_simple.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h clnt_simple.c
+clnt_tcp.so clnt_tcp.po $(OUTPRE)clnt_tcp.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h clnt_tcp.c
+clnt_udp.so clnt_udp.po $(OUTPRE)clnt_udp.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h clnt_udp.c
+dyn.so dyn.po $(OUTPRE)dyn.$(OBJEXT): dyn.c dyn.h dynP.h
+rpc_dtablesize.so rpc_dtablesize.po $(OUTPRE)rpc_dtablesize.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  rpc_dtablesize.c
+get_myaddress.so get_myaddress.po $(OUTPRE)get_myaddress.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/pmap_prot.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/krb5.h get_myaddress.c
+getrpcport.so getrpcport.po $(OUTPRE)getrpcport.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/pmap_clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  getrpcport.c
+pmap_clnt.so pmap_clnt.po $(OUTPRE)pmap_clnt.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/pmap_prot.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  pmap_clnt.c
+pmap_getmaps.so pmap_getmaps.po $(OUTPRE)pmap_getmaps.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/pmap_prot.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  pmap_getmaps.c
+pmap_getport.so pmap_getport.po $(OUTPRE)pmap_getport.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/pmap_prot.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  pmap_getport.c
+pmap_prot.so pmap_prot.po $(OUTPRE)pmap_prot.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/pmap_prot.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  pmap_prot.c
+pmap_prot2.so pmap_prot2.po $(OUTPRE)pmap_prot2.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/pmap_prot.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  pmap_prot2.c
+pmap_rmt.so pmap_rmt.po $(OUTPRE)pmap_rmt.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/pmap_prot.h \
+  $(SRCTOP)/include/gssrpc/pmap_rmt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h pmap_rmt.c
+rpc_prot.so rpc_prot.po $(OUTPRE)rpc_prot.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  rpc_prot.c
+rpc_commondata.so rpc_commondata.po $(OUTPRE)rpc_commondata.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  rpc_commondata.c
+rpc_callmsg.so rpc_callmsg.po $(OUTPRE)rpc_callmsg.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  rpc_callmsg.c
+svc.so svc.po $(OUTPRE)svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h svc.c
+svc_auth.so svc_auth.po $(OUTPRE)svc_auth.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  svc_auth.c
+svc_auth_gss.so svc_auth_gss.po $(OUTPRE)svc_auth_gss.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_gssapi.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  svc_auth_gss.c
+svc_auth_none.so svc_auth_none.po $(OUTPRE)svc_auth_none.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  svc_auth_none.c
+svc_auth_unix.so svc_auth_unix.po $(OUTPRE)svc_auth_unix.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  svc_auth_unix.c
+svc_auth_gssapi.so svc_auth_gssapi.po $(OUTPRE)svc_auth_gssapi.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_gssapi.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/krb5.h \
+  svc_auth_gssapi.c
+svc_raw.so svc_raw.po $(OUTPRE)svc_raw.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h svc_raw.c
+svc_run.so svc_run.po $(OUTPRE)svc_run.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h svc_run.c
+svc_simple.so svc_simple.po $(OUTPRE)svc_simple.$(OBJEXT): \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h svc_simple.c
+svc_tcp.so svc_tcp.po $(OUTPRE)svc_tcp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  svc_tcp.c
+svc_udp.so svc_udp.po $(OUTPRE)svc_udp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  svc_udp.c
+xdr.so xdr.po $(OUTPRE)xdr.$(OBJEXT): $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  xdr.c
+xdr_array.so xdr_array.po $(OUTPRE)xdr_array.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h xdr_array.c
+xdr_float.so xdr_float.po $(OUTPRE)xdr_float.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h xdr_float.c
+xdr_mem.so xdr_mem.po $(OUTPRE)xdr_mem.$(OBJEXT): $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  xdr_mem.c
+xdr_rec.so xdr_rec.po $(OUTPRE)xdr_rec.$(OBJEXT): $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  xdr_rec.c
+xdr_reference.so xdr_reference.po $(OUTPRE)xdr_reference.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h xdr_reference.c
+xdr_stdio.so xdr_stdio.po $(OUTPRE)xdr_stdio.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h xdr_stdio.c
+xdr_alloc.so xdr_alloc.po $(OUTPRE)xdr_alloc.$(OBJEXT): \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h dyn.h xdr_alloc.c
diff --git a/krb5-1-6/src/lib/rpc/auth_gss.c b/krb5-1-6/src/lib/rpc/auth_gss.c
new file mode 100644
index 000000000..d11c5e267
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/auth_gss.c
@@ -0,0 +1,632 @@
+/*
+  auth_gss.c
+
+  RPCSEC_GSS client routines.
+  
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of the University nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Id: auth_gss.c,v 1.35 2002/10/15 21:25:25 kwc Exp
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <gssrpc/auth.h>
+#include <gssrpc/auth_gss.h>
+#include <gssrpc/clnt.h>
+#include <netinet/in.h>
+#ifdef HAVE_HEIMDAL
+#include <gssapi.h>
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#else
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#endif
+
+#ifdef DEBUG_GSSAPI
+int auth_debug_gss = DEBUG_GSSAPI;
+int misc_debug_gss = DEBUG_GSSAPI;
+#endif
+
+static void	authgss_nextverf(AUTH *);
+static bool_t	authgss_marshal(AUTH *, XDR *);
+static bool_t	authgss_refresh(AUTH *, struct rpc_msg *);
+static bool_t	authgss_validate(AUTH *, struct opaque_auth *);
+static void	authgss_destroy(AUTH *);
+static void	authgss_destroy_context(AUTH *);
+static bool_t	authgss_wrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+static bool_t	authgss_unwrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+
+
+/*
+ * from mit-krb5-1.2.1 mechglue/mglueP.h:
+ * Array of context IDs typed by mechanism OID
+ */
+typedef struct gss_union_ctx_id_t {
+  gss_OID     mech_type;
+  gss_ctx_id_t    internal_ctx_id;
+} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
+
+static struct auth_ops authgss_ops = {
+	authgss_nextverf,
+	authgss_marshal,
+	authgss_validate,
+	authgss_refresh,
+	authgss_destroy,
+	authgss_wrap,
+	authgss_unwrap
+};
+
+#ifdef DEBUG
+
+/* useful as i add more mechanisms */
+void
+print_rpc_gss_sec(struct rpc_gss_sec *ptr)
+{
+	int i;
+	char *p;
+
+	log_debug("rpc_gss_sec:");
+	if(ptr->mech == NULL)
+		log_debug("NULL gss_OID mech");
+	else {
+		fprintf(stderr, "     mechanism_OID: {");
+		p = (char *)ptr->mech->elements;
+		for (i=0; i < ptr->mech->length; i++)
+			/* First byte of OIDs encoded to save a byte */
+			if (i == 0) {
+				int first, second;
+				if (*p < 40) {
+					first = 0;
+					second = *p;
+				}
+				else if (40 <= *p && *p < 80) {
+					first = 1;
+					second = *p - 40;
+				}
+				else if (80 <= *p && *p < 127) {
+					first = 2;
+					second = *p - 80;
+				}
+				else {
+					/* Invalid value! */
+					first = -1;
+					second = -1;
+				}
+				fprintf(stderr, " %u %u", first, second);
+				p++;
+			}
+			else {
+				fprintf(stderr, " %u", (unsigned char)*p++);
+			}
+		fprintf(stderr, " }\n");
+	}
+	fprintf(stderr, "     qop: %d\n", ptr->qop);
+	fprintf(stderr, "     service: %d\n", ptr->svc);
+	fprintf(stderr, "     cred: %p\n", ptr->cred);
+	fprintf(stderr, "     req_flags: 0x%08x", ptr->req_flags);
+}
+#endif /*DEBUG*/
+
+struct rpc_gss_data {
+	bool_t			 established;	/* context established */
+	bool_t			 inprogress;
+  gss_buffer_desc      gc_wire_verf; /* save GSS_S_COMPLETE NULL RPC verfier 
+                                   * to process at end of context negotiation*/
+	CLIENT			*clnt;		/* client handle */
+	gss_name_t		 name;		/* service name */
+	struct rpc_gss_sec	 sec;		/* security tuple */
+	gss_ctx_id_t		 ctx;		/* context id */
+	struct rpc_gss_cred	 gc;		/* client credentials */
+	uint32_t		 win;		/* sequence window */
+};
+
+#define	AUTH_PRIVATE(auth)	((struct rpc_gss_data *)auth->ah_private)
+
+static struct timeval AUTH_TIMEOUT = { 25, 0 };
+
+AUTH *
+authgss_create(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec)
+{
+	AUTH			*auth, *save_auth;
+	struct rpc_gss_data	*gd;
+	OM_uint32		min_stat = 0;
+
+	log_debug("in authgss_create()");
+	
+	memset(&rpc_createerr, 0, sizeof(rpc_createerr));
+	
+	if ((auth = calloc(sizeof(*auth), 1)) == NULL) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = ENOMEM;
+		return (NULL);
+	}
+	if ((gd = calloc(sizeof(*gd), 1)) == NULL) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = ENOMEM;
+		free(auth);
+		return (NULL);
+	}
+	if (name != GSS_C_NO_NAME) {
+		if (gss_duplicate_name(&min_stat, name, &gd->name)
+						!= GSS_S_COMPLETE) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = ENOMEM;
+			free(auth);
+			return (NULL);
+		}
+	}
+	else
+		gd->name = name;
+
+	gd->clnt = clnt;
+	gd->ctx = GSS_C_NO_CONTEXT;
+	gd->sec = *sec;
+
+	gd->gc.gc_v = RPCSEC_GSS_VERSION;
+	gd->gc.gc_proc = RPCSEC_GSS_INIT;
+	gd->gc.gc_svc = gd->sec.svc;
+	
+	auth->ah_ops = &authgss_ops;
+	auth->ah_private = (caddr_t)gd;
+	
+	save_auth = clnt->cl_auth;
+	clnt->cl_auth = auth;
+
+	if (!authgss_refresh(auth, NULL))
+		auth = NULL;
+	
+	clnt->cl_auth = save_auth;
+	
+	log_debug("authgss_create returning auth 0x%08x", auth);
+	return (auth);
+}
+
+AUTH *
+authgss_create_default(CLIENT *clnt, char *service, struct rpc_gss_sec *sec)
+{
+	AUTH			*auth;
+	OM_uint32		 maj_stat = 0, min_stat = 0;
+	gss_buffer_desc		 sname;
+	gss_name_t		 name;
+
+	log_debug("in authgss_create_default()");
+	
+
+	sname.value = service;
+	sname.length = strlen(service);
+	
+	maj_stat = gss_import_name(&min_stat, &sname,
+		(gss_OID)gss_nt_service_name,
+		&name);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_import_name", maj_stat, min_stat);
+		rpc_createerr.cf_stat = RPC_AUTHERROR;
+		return (NULL);
+	}
+
+	auth = authgss_create(clnt, name, sec);
+	
+ 	if (name != GSS_C_NO_NAME)
+ 		gss_release_name(&min_stat, &name);
+	
+	log_debug("authgss_create_default returning auth 0x%08x", auth);
+	return (auth);
+}
+
+bool_t
+authgss_get_private_data(AUTH *auth, struct authgss_private_data *pd)
+{
+	struct rpc_gss_data	*gd;
+
+	log_debug("in authgss_get_private_data()");
+
+	if (!auth || !pd)
+		return (FALSE);
+
+	gd = AUTH_PRIVATE(auth);
+
+	if (!gd || !gd->established)
+		return (FALSE);
+
+	pd->pd_ctx = gd->ctx;
+	pd->pd_ctx_hndl = gd->gc.gc_ctx;
+	pd->pd_seq_win = gd->win;
+
+	return (TRUE);
+}
+
+static void
+authgss_nextverf(AUTH *auth)
+{
+	log_debug("in authgss_nextverf()\n");
+	/* no action necessary */
+}
+
+static bool_t
+authgss_marshal(AUTH *auth, XDR *xdrs)
+{
+	XDR			 tmpxdrs;
+	char			 tmp[MAX_AUTH_BYTES];
+	struct rpc_gss_data	*gd;
+	gss_buffer_desc		 rpcbuf, checksum;
+	OM_uint32		 maj_stat, min_stat;
+	bool_t			 xdr_stat;
+	
+	log_debug("in authgss_marshal()");
+	
+	gd = AUTH_PRIVATE(auth);
+
+	if (gd->established)
+		gd->gc.gc_seq++;
+	
+	xdrmem_create(&tmpxdrs, tmp, sizeof(tmp), XDR_ENCODE);
+	
+	if (!xdr_rpc_gss_cred(&tmpxdrs, &gd->gc)) {
+		XDR_DESTROY(&tmpxdrs);
+		return (FALSE);
+	}
+	auth->ah_cred.oa_flavor = RPCSEC_GSS;
+	auth->ah_cred.oa_base = tmp;
+	auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs);
+	
+	XDR_DESTROY(&tmpxdrs);
+	
+	if (!xdr_opaque_auth(xdrs, &auth->ah_cred))
+		return (FALSE);
+	
+	if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
+	    gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
+		return (xdr_opaque_auth(xdrs, &gssrpc__null_auth));
+	}
+	/* Checksum serialized RPC header, up to and including credential. */
+	rpcbuf.length = XDR_GETPOS(xdrs);
+	XDR_SETPOS(xdrs, 0);
+	rpcbuf.value = XDR_INLINE(xdrs, (int)rpcbuf.length);
+	
+	maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
+			    &rpcbuf, &checksum);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_get_mic", maj_stat, min_stat);
+		if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+			gd->established = FALSE;
+			authgss_destroy_context(auth);
+		}
+		return (FALSE);
+	}
+	auth->ah_verf.oa_flavor = RPCSEC_GSS;
+	auth->ah_verf.oa_base = checksum.value;
+	auth->ah_verf.oa_length = checksum.length;
+	
+	xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf);
+	gss_release_buffer(&min_stat, &checksum);
+	
+	return (xdr_stat);
+}
+
+static bool_t
+authgss_validate(AUTH *auth, struct opaque_auth *verf)
+{
+	struct rpc_gss_data	*gd;
+	uint32_t		 num;
+	gss_qop_t		 qop_state;
+	gss_buffer_desc		 signbuf, checksum;
+	OM_uint32		 maj_stat, min_stat;
+
+	log_debug("in authgss_validate()");
+	
+	gd = AUTH_PRIVATE(auth);
+
+	if (gd->established == FALSE) {
+		/* would like to do this only on NULL rpc - gc->established is good enough.
+		 * save the on the wire verifier to validate last INIT phase packet
+		 * after decode if the major status is GSS_S_COMPLETE 
+		 */
+		if ((gd->gc_wire_verf.value = mem_alloc(verf->oa_length)) == NULL) {
+			fprintf(stderr, "gss_validate: out of memory\n");
+			return (FALSE);
+		}
+		memcpy(gd->gc_wire_verf.value, verf->oa_base, verf->oa_length);
+		gd->gc_wire_verf.length = verf->oa_length;
+		return (TRUE);
+  	}
+
+	if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
+	    gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
+		num = htonl(gd->win);
+	}
+	else num = htonl(gd->gc.gc_seq);
+	
+	signbuf.value = #
+	signbuf.length = sizeof(num);
+	
+	checksum.value = verf->oa_base;
+	checksum.length = verf->oa_length;
+	
+	maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf,
+				  &checksum, &qop_state);
+	if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) {
+		log_status("gss_verify_mic", maj_stat, min_stat);
+		if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+			gd->established = FALSE;
+			authgss_destroy_context(auth);
+		}
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+static bool_t
+authgss_refresh(AUTH *auth, struct rpc_msg *msg)
+{
+	struct rpc_gss_data	*gd;
+	struct rpc_gss_init_res	 gr;
+	gss_buffer_desc		*recv_tokenp, send_token;
+	OM_uint32		 maj_stat, min_stat, call_stat, ret_flags;
+
+	log_debug("in authgss_refresh()");
+	
+	gd = AUTH_PRIVATE(auth);
+	
+	if (gd->established || gd->inprogress)
+		return (TRUE);
+	
+	/* GSS context establishment loop. */
+	memset(&gr, 0, sizeof(gr));
+	recv_tokenp = GSS_C_NO_BUFFER;
+	
+#ifdef DEBUG
+	print_rpc_gss_sec(&gd->sec);
+#endif /*DEBUG*/
+
+	for (;;) {
+		gd->inprogress = TRUE;
+		maj_stat = gss_init_sec_context(&min_stat,
+						gd->sec.cred,
+						&gd->ctx,
+						gd->name,
+						gd->sec.mech,
+						gd->sec.req_flags,
+						0,		/* time req */
+						GSS_C_NO_CHANNEL_BINDINGS, 
+						recv_tokenp,
+						NULL,		/* used mech */
+						&send_token,
+						&ret_flags,
+						NULL);		/* time rec */
+		
+		log_status("gss_init_sec_context", maj_stat, min_stat);
+		if (recv_tokenp != GSS_C_NO_BUFFER) {
+			gss_release_buffer(&min_stat, &gr.gr_token);
+			recv_tokenp = GSS_C_NO_BUFFER;
+		}
+		if (maj_stat != GSS_S_COMPLETE &&
+		    maj_stat != GSS_S_CONTINUE_NEEDED) {
+			log_status("gss_init_sec_context (error)", maj_stat, min_stat);
+			break;
+		}
+		if (send_token.length != 0) {
+			memset(&gr, 0, sizeof(gr));
+			
+			call_stat = clnt_call(gd->clnt, NULLPROC,
+					      xdr_rpc_gss_init_args,
+					      &send_token,
+					      xdr_rpc_gss_init_res,
+					      (caddr_t)&gr, AUTH_TIMEOUT);
+			
+			gss_release_buffer(&min_stat, &send_token);
+
+			log_debug("authgss_refresh: call_stat=%d", call_stat);
+			log_debug("%s", clnt_sperror(gd->clnt, "authgss_refresh"));
+			if (call_stat != RPC_SUCCESS ||
+			    (gr.gr_major != GSS_S_COMPLETE &&
+			     gr.gr_major != GSS_S_CONTINUE_NEEDED))
+				break;
+			
+			if (gr.gr_ctx.length != 0) {
+				if (gd->gc.gc_ctx.value)
+					gss_release_buffer(&min_stat,
+							   &gd->gc.gc_ctx);
+				gd->gc.gc_ctx = gr.gr_ctx;
+			}
+			if (gr.gr_token.length != 0) {
+				if (maj_stat != GSS_S_CONTINUE_NEEDED)
+					break;
+				recv_tokenp = &gr.gr_token;
+			}
+			gd->gc.gc_proc = RPCSEC_GSS_CONTINUE_INIT;
+		}
+		
+		/* GSS_S_COMPLETE => check gss header verifier, usually checked in
+		 * gss_validate
+		 */
+		if (maj_stat == GSS_S_COMPLETE) {
+			gss_buffer_desc   bufin;
+			gss_buffer_desc   bufout;
+			uint32_t seq;
+			gss_qop_t qop_state = 0;
+
+			seq = htonl(gr.gr_win);
+			bufin.value = (u_char *)&seq;
+			bufin.length = sizeof(seq);
+			bufout.value = (u_char *)gd->gc_wire_verf.value;
+			bufout.length = gd->gc_wire_verf.length;
+
+			log_debug("authgss_refresh: GSS_S_COMPLETE: calling verify_mic");
+			maj_stat = gss_verify_mic(&min_stat,gd->ctx,
+				&bufin, &bufout, &qop_state);
+
+			if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) {
+				log_status("gss_verify_mic", maj_stat, min_stat);
+				gss_release_buffer(&min_stat, &gd->gc_wire_verf);
+				if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+					gd->established = FALSE;
+					authgss_destroy_context(auth);
+				}
+				return (FALSE);
+			}
+			gss_release_buffer(&min_stat, &gd->gc_wire_verf);
+			gd->established = TRUE;
+			gd->inprogress = FALSE;
+			gd->gc.gc_proc = RPCSEC_GSS_DATA;
+			gd->gc.gc_seq = 0;
+			gd->win = gr.gr_win;
+			break;
+		}
+	}
+	log_status("authgss_refresh: at end of context negotiation", maj_stat, min_stat);
+	/* End context negotiation loop. */
+	if (gd->gc.gc_proc != RPCSEC_GSS_DATA) {
+		log_debug("authgss_refresh: returning ERROR (gc_proc %d)", gd->gc.gc_proc);
+		if (gr.gr_token.length != 0)
+			gss_release_buffer(&min_stat, &gr.gr_token);
+		
+		authgss_destroy(auth);
+		auth = NULL;
+		rpc_createerr.cf_stat = RPC_AUTHERROR;
+		
+		return (FALSE);
+	}
+	log_debug("authgss_refresh: returning SUCCESS");
+	return (TRUE);
+}
+
+bool_t
+authgss_service(AUTH *auth, int svc)
+{
+	struct rpc_gss_data	*gd;
+
+	log_debug("in authgss_service()");
+
+	if (!auth)
+		return(FALSE);
+	gd = AUTH_PRIVATE(auth);
+	if (!gd || !gd->established)
+		return (FALSE);
+	gd->sec.svc = svc;
+	gd->gc.gc_svc = svc;
+	return (TRUE);
+}
+
+static void
+authgss_destroy_context(AUTH *auth)
+{
+	struct rpc_gss_data	*gd;
+	OM_uint32		 min_stat;
+	enum clnt_stat		 callstat;
+
+	log_debug("in authgss_destroy_context()");
+	
+	gd = AUTH_PRIVATE(auth);
+	
+	if (gd->gc.gc_ctx.length != 0) {
+		if (gd->established) {
+			gd->gc.gc_proc = RPCSEC_GSS_DESTROY;
+			callstat = clnt_call(gd->clnt, NULLPROC,
+					     xdr_void, NULL,
+					     xdr_void, NULL,
+					     AUTH_TIMEOUT);
+			log_debug("%s",
+				  clnt_sperror(gd->clnt,
+					       "authgss_destroy_context"));
+		}
+		gss_release_buffer(&min_stat, &gd->gc.gc_ctx);
+		/* XXX ANDROS check size of context  - should be 8 */
+		memset(&gd->gc.gc_ctx, 0, sizeof(gd->gc.gc_ctx));
+	}
+	if (gd->ctx != GSS_C_NO_CONTEXT) {
+		gss_delete_sec_context(&min_stat, &gd->ctx, NULL);
+		gd->ctx = GSS_C_NO_CONTEXT;
+	}
+	gd->established = FALSE;
+
+	log_debug("finished authgss_destroy_context()");
+}
+
+static void
+authgss_destroy(AUTH *auth)
+{
+	struct rpc_gss_data	*gd;
+	OM_uint32		 min_stat;
+	
+	log_debug("in authgss_destroy()");
+	
+	gd = AUTH_PRIVATE(auth);
+	
+	authgss_destroy_context(auth);
+	
+	if (gd->name != GSS_C_NO_NAME)
+		gss_release_name(&min_stat, &gd->name);
+
+	free(gd);
+	free(auth);
+}
+
+bool_t
+authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
+{
+	struct rpc_gss_data	*gd;
+
+	log_debug("in authgss_wrap()");
+	
+	gd = AUTH_PRIVATE(auth);
+
+	if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
+		return ((*xdr_func)(xdrs, xdr_ptr));
+	}
+	return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
+				 gd->ctx, gd->sec.qop,
+				 gd->sec.svc, gd->gc.gc_seq));
+}
+
+bool_t
+authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
+{
+	struct rpc_gss_data	*gd;
+
+	log_debug("in authgss_unwrap()");
+	
+	gd = AUTH_PRIVATE(auth);
+	
+	if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
+		return ((*xdr_func)(xdrs, xdr_ptr));
+	}
+	return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
+				 gd->ctx, gd->sec.qop,
+				 gd->sec.svc, gd->gc.gc_seq));
+}
diff --git a/krb5-1-6/src/lib/rpc/auth_gssapi.c b/krb5-1-6/src/lib/rpc/auth_gssapi.c
new file mode 100644
index 000000000..3d6e6fe63
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/auth_gssapi.c
@@ -0,0 +1,812 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/errno.h>
+
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#ifdef GSSAPI_KRB5
+#include <gssapi/gssapi_krb5.h>
+#endif
+
+#include <gssrpc/rpc.h>
+#include <gssrpc/auth_gssapi.h>
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int auth_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (auth_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+	if (auth_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+   
+static void 	auth_gssapi_nextverf(AUTH *);
+static bool_t 	auth_gssapi_marshall(AUTH *, XDR *);
+static bool_t	auth_gssapi_validate(AUTH *, struct opaque_auth *);
+static bool_t	auth_gssapi_refresh(AUTH *, struct rpc_msg *);
+static bool_t	auth_gssapi_wrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+static bool_t	auth_gssapi_unwrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+static void	auth_gssapi_destroy(AUTH *);
+   
+static bool_t	marshall_new_creds(AUTH *, bool_t, gss_buffer_t);
+
+static struct auth_ops auth_gssapi_ops = {
+     auth_gssapi_nextverf,
+     auth_gssapi_marshall,
+     auth_gssapi_validate,
+     auth_gssapi_refresh,
+     auth_gssapi_destroy,
+     auth_gssapi_wrap,
+     auth_gssapi_unwrap,
+};
+
+/*
+ * the ah_private data structure for an auth_handle
+ */
+struct auth_gssapi_data {
+     bool_t established;
+     CLIENT *clnt;
+     gss_ctx_id_t context;
+     gss_buffer_desc client_handle;
+     uint32_t seq_num;
+     int def_cred;
+     
+     /* pre-serialized ah_cred */
+     unsigned char cred_buf[MAX_AUTH_BYTES];
+     uint32_t cred_len;
+};
+#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
+
+/*
+ * Function: auth_gssapi_create_default
+ *
+ * Purpose:  Create a GSS-API style authenticator, with default
+ * options, and return the handle.
+ *
+ * Effects: See design document, section XXX.
+ */
+AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name)
+{
+     AUTH *auth;
+     OM_uint32 gssstat, minor_stat;
+     gss_buffer_desc input_name;
+     gss_name_t target_name;
+     
+     input_name.value = service_name;
+     input_name.length = strlen(service_name) + 1;
+     
+     gssstat = gss_import_name(&minor_stat, &input_name, 
+			       gss_nt_service_name, &target_name);
+     if (gssstat != GSS_S_COMPLETE) {
+	  AUTH_GSSAPI_DISPLAY_STATUS(("parsing name", gssstat,
+				      minor_stat));
+	  rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	  rpc_createerr.cf_error.re_errno = ENOMEM;
+	  return NULL;
+     }
+     
+     auth = auth_gssapi_create(clnt,
+			       &gssstat,
+			       &minor_stat,
+			       GSS_C_NO_CREDENTIAL,
+			       target_name,
+			       GSS_C_NULL_OID,
+			       GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+			       0,
+			       NULL,
+			       NULL,
+			       NULL);
+     
+     gss_release_name(&minor_stat, &target_name);
+     return auth;
+}
+
+/*
+ * Function: auth_gssapi_create
+ *
+ * Purpose: Create a GSS-API style authenticator, with all the
+ * options, and return the handle.
+ *
+ * Effects: See design document, section XXX.
+ */
+AUTH *auth_gssapi_create(
+     CLIENT *clnt,
+     OM_uint32 *gssstat,
+     OM_uint32 *minor_stat,
+     gss_cred_id_t claimant_cred_handle,
+     gss_name_t target_name,
+     gss_OID mech_type,
+     OM_uint32 req_flags,
+     OM_uint32 time_req,
+     gss_OID *actual_mech_type,
+     OM_uint32 *ret_flags,
+     OM_uint32 *time_rec)
+{
+     AUTH *auth, *save_auth;
+     struct auth_gssapi_data *pdata;
+     struct gss_channel_bindings_struct bindings, *bindp;
+     struct sockaddr_in laddr, raddr;
+     enum clnt_stat callstat;
+     struct timeval timeout;
+     int bindings_failed;
+     rpcproc_t init_func;
+     
+     auth_gssapi_init_arg call_arg;
+     auth_gssapi_init_res call_res;
+     gss_buffer_desc *input_token, isn_buf;
+     
+     memset(&rpc_createerr, 0, sizeof(rpc_createerr));
+     
+     /* this timeout is only used if clnt_control(clnt, CLSET_TIMEOUT) */
+     /* has not already been called.. therefore, we can just pick */
+     /* something reasonable-sounding.. */
+     timeout.tv_sec = 30;
+     timeout.tv_usec = 0;
+     
+     auth = NULL;
+     pdata = NULL;
+     
+     /* don't assume the caller will want to change clnt->cl_auth */
+     save_auth = clnt->cl_auth;
+
+     auth = (AUTH *) malloc(sizeof(*auth));
+     pdata = (struct auth_gssapi_data *) malloc(sizeof(*pdata));
+     if (auth == NULL || pdata == NULL) {
+	  rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	  rpc_createerr.cf_error.re_errno = ENOMEM;
+	  goto cleanup;
+     }
+     memset((char *) auth, 0, sizeof(*auth));
+     memset((char *) pdata, 0, sizeof(*pdata));
+     
+     auth->ah_ops = &auth_gssapi_ops;
+     auth->ah_private = (caddr_t) pdata;
+     
+     /* initial creds are auth_msg TRUE and no handle */
+     marshall_new_creds(auth, TRUE, NULL);
+     
+     /* initial verifier is empty */
+     auth->ah_verf.oa_flavor = AUTH_GSSAPI;
+     auth->ah_verf.oa_base = NULL;
+     auth->ah_verf.oa_length = 0;
+     
+     AUTH_PRIVATE(auth)->established = FALSE;
+     AUTH_PRIVATE(auth)->clnt = clnt;
+     AUTH_PRIVATE(auth)->def_cred = (claimant_cred_handle ==
+				     GSS_C_NO_CREDENTIAL);
+     
+     clnt->cl_auth = auth;
+
+     /* start by trying latest version */
+     call_arg.version = 4;
+     bindings_failed = 0;
+
+try_new_version:
+     /* set state for initial call to init_sec_context */
+     input_token = GSS_C_NO_BUFFER;
+     AUTH_PRIVATE(auth)->context = GSS_C_NO_CONTEXT;
+     init_func = AUTH_GSSAPI_INIT;
+
+#ifdef GSSAPI_KRB5
+     /*
+      * OV servers up to version 3 used the old mech id.  Beta 7
+      * servers used version 3 with the new mech id; however, the beta
+      * 7 gss-api accept_sec_context accepts either mech id.  Thus, if
+      * any server rejects version 4, we fall back to version 3 with
+      * the old mech id; for the OV server it will be right, and for
+      * the beta 7 server it will be accepted.  Not ideal, but it
+      * works.
+      */
+     if (call_arg.version < 4 && (mech_type == gss_mech_krb5 ||
+				  mech_type == GSS_C_NULL_OID))
+	  mech_type = (gss_OID) gss_mech_krb5_old;
+#endif
+
+     if (!bindings_failed && call_arg.version >= 3) {
+	  if (clnt_control(clnt, CLGET_LOCAL_ADDR, &laddr) == FALSE) {
+	       PRINTF(("gssapi_create: CLGET_LOCAL_ADDR failed"));
+	       goto cleanup;
+	  }
+	  if (clnt_control(clnt, CLGET_SERVER_ADDR, &raddr) == FALSE) {
+	       PRINTF(("gssapi_create: CLGET_SERVER_ADDR failed"));
+	       goto cleanup;
+	  }
+
+	  memset(&bindings, 0, sizeof(bindings));
+	  bindings.application_data.length = 0;
+	  bindings.initiator_addrtype = GSS_C_AF_INET;
+	  bindings.initiator_address.length = 4;
+	  bindings.initiator_address.value = &laddr.sin_addr.s_addr;
+	  
+	  bindings.acceptor_addrtype = GSS_C_AF_INET;
+	  bindings.acceptor_address.length = 4;
+	  bindings.acceptor_address.value = &raddr.sin_addr.s_addr;
+	  bindp = &bindings;
+     } else {
+	  bindp = NULL;
+     }
+     
+     memset((char *) &call_res, 0, sizeof(call_res));
+     
+next_token:
+     *gssstat = gss_init_sec_context(minor_stat,
+				     claimant_cred_handle,
+				     &AUTH_PRIVATE(auth)->context,
+				     target_name,
+				     mech_type,
+				     req_flags,
+				     time_req,
+				     bindp,
+				     input_token,
+				     actual_mech_type,
+				     &call_arg.token,
+				     ret_flags,
+				     time_rec);
+     
+     if (*gssstat != GSS_S_COMPLETE && *gssstat != GSS_S_CONTINUE_NEEDED) {
+	  AUTH_GSSAPI_DISPLAY_STATUS(("initializing context", *gssstat,
+				      *minor_stat));
+	  goto cleanup;
+     }
+     
+     /* if we got a token, pass it on */
+     if (call_arg.token.length != 0) {
+	  
+	  /*
+	   * sanity check: if we received a signed isn in the last
+	   * response then there *cannot* be another token to send
+	   */
+	  if (call_res.signed_isn.length != 0) {
+	       PRINTF(("gssapi_create: unexpected token from init_sec\n"));
+	       goto cleanup;
+	  }
+	  
+	  PRINTF(("gssapi_create: calling GSSAPI_INIT (%d)\n", init_func));
+	  
+	  memset((char *) &call_res, 0, sizeof(call_res));
+	  callstat = clnt_call(clnt, init_func,
+			       xdr_authgssapi_init_arg, &call_arg,
+			       xdr_authgssapi_init_res, &call_res,
+			       timeout);
+	  gss_release_buffer(minor_stat, &call_arg.token);
+	  
+	  if (callstat != RPC_SUCCESS) {
+	       struct rpc_err err;
+
+	       clnt_geterr(clnt, &err);
+	       if (callstat == RPC_AUTHERROR &&
+		   (err.re_why == AUTH_BADCRED || err.re_why == AUTH_FAILED)
+		   && call_arg.version >= 1) {
+		    L_PRINTF(1,
+			     ("call_arg protocol version %d rejected, trying %d.\n",
+			    call_arg.version, call_arg.version-1));
+		    call_arg.version--;
+		    goto try_new_version;
+	       } else {
+		    PRINTF(("gssapi_create: GSSAPI_INIT (%d) failed, stat %d\n",
+			    init_func, callstat));
+	       }
+	       
+	       goto cleanup;
+	  } else if (call_res.version != call_arg.version &&
+		     !(call_arg.version == 2 && call_res.version == 1)) {
+	       /*
+		* The Secure 1.1 servers always respond with version
+		* 1.  Thus, if we just tried a version >=3, fall all
+		* the way back to version 1 since that is all they
+		* understand
+		*/
+	       if (call_arg.version > 2 && call_res.version == 1) {
+		    L_PRINTF(1,
+			     ("Talking to Secure 1.1 server, using version 1.\n"));
+		    call_arg.version = 1;
+		    goto try_new_version;
+	       }
+
+	       PRINTF(("gssapi_create: invalid call_res vers %d\n",
+		       call_res.version));
+	       goto cleanup;
+	  } else if (call_res.gss_major != GSS_S_COMPLETE) {
+	       AUTH_GSSAPI_DISPLAY_STATUS(("in response from server",
+					   call_res.gss_major,
+					   call_res.gss_minor));
+	       goto cleanup;
+	  }
+	  
+	  PRINTF(("gssapi_create: GSSAPI_INIT (%d) succeeded\n", init_func));
+	  init_func = AUTH_GSSAPI_CONTINUE_INIT;
+	  
+	  /* check for client_handle */
+	  if (AUTH_PRIVATE(auth)->client_handle.length == 0) {
+	       if (call_res.client_handle.length == 0) {
+		    PRINTF(("gssapi_create: expected client_handle\n"));
+		    goto cleanup;
+	       } else {
+		    PRINTF(("gssapi_create: got client_handle %d\n",
+			    *((uint32_t *)call_res.client_handle.value)));
+		    
+		    GSS_DUP_BUFFER(AUTH_PRIVATE(auth)->client_handle,
+				   call_res.client_handle);
+		    
+		    /* auth_msg is TRUE; there may be more tokens */
+		    marshall_new_creds(auth, TRUE,
+				       &AUTH_PRIVATE(auth)->client_handle); 
+	       }
+	  } else if (!GSS_BUFFERS_EQUAL(AUTH_PRIVATE(auth)->client_handle,
+					call_res.client_handle)) {
+	       PRINTF(("gssapi_create: got different client_handle\n"));
+	       goto cleanup;
+	  }
+	  
+	  /* check for token */
+	  if (call_res.token.length==0 && *gssstat==GSS_S_CONTINUE_NEEDED) {
+	       PRINTF(("gssapi_create: expected token\n"));
+	       goto cleanup;
+	  } else if (call_res.token.length != 0) {
+	       if (*gssstat == GSS_S_COMPLETE) {
+		    PRINTF(("gssapi_create: got unexpected token\n"));
+		    goto cleanup;
+	       } else {
+		    /* assumes call_res is safe until init_sec_context */
+		    input_token = &call_res.token;
+		    PRINTF(("gssapi_create: got new token\n"));
+	       }
+	  }
+     }
+     
+     /* check for isn */
+     if (*gssstat == GSS_S_COMPLETE) {
+	  if (call_res.signed_isn.length == 0) {
+	       PRINTF(("gssapi_created: expected signed isn\n"));
+	       goto cleanup;
+	  } else {
+	       PRINTF(("gssapi_create: processing signed isn\n"));
+	       
+	       /* don't check conf (integ only) or qop (accpet default) */
+	       *gssstat = gss_unseal(minor_stat,
+				     AUTH_PRIVATE(auth)->context,
+				     &call_res.signed_isn,
+				     &isn_buf, NULL, NULL);
+	       
+	       if (*gssstat != GSS_S_COMPLETE) {
+		    AUTH_GSSAPI_DISPLAY_STATUS(("unsealing isn",
+						*gssstat, *minor_stat)); 
+		    goto cleanup;
+	       } else if (isn_buf.length != sizeof(uint32_t)) {
+		    PRINTF(("gssapi_create: gss_unseal gave %d bytes\n",
+			    (int) isn_buf.length));
+		    goto cleanup;
+	       }
+	       
+	       AUTH_PRIVATE(auth)->seq_num = (uint32_t)
+		    ntohl(*((uint32_t*)isn_buf.value)); 
+	       *gssstat = gss_release_buffer(minor_stat, &isn_buf);
+	       if (*gssstat != GSS_S_COMPLETE) {
+		    AUTH_GSSAPI_DISPLAY_STATUS(("releasing unsealed isn",
+						*gssstat, *minor_stat));
+		    goto cleanup;
+	       }
+	       
+	       PRINTF(("gssapi_create: isn is %d\n",
+		       AUTH_PRIVATE(auth)->seq_num));
+	       
+	       /* we no longer need these results.. */
+	       xdr_free(xdr_authgssapi_init_res, &call_res);
+	  }
+     } else if (call_res.signed_isn.length != 0) {
+	  PRINTF(("gssapi_create: got signed isn, can't check yet\n"));
+     }
+     
+     /* results were okay.. continue if necessary */
+     if (*gssstat == GSS_S_CONTINUE_NEEDED) {
+	  PRINTF(("gssapi_create: not done, continuing\n"));
+	  goto next_token;
+     }
+     
+     /*
+      * Done!  Context is established, we have client_handle and isn.
+      */
+     AUTH_PRIVATE(auth)->established = TRUE;
+     
+     marshall_new_creds(auth, FALSE,
+			&AUTH_PRIVATE(auth)->client_handle); 
+     
+     PRINTF(("gssapi_create: done. client_handle %#x, isn %d\n\n",
+	     *((uint32_t *)AUTH_PRIVATE(auth)->client_handle.value),
+	     AUTH_PRIVATE(auth)->seq_num));
+     
+     /* don't assume the caller will want to change clnt->cl_auth */
+     clnt->cl_auth = save_auth;
+     
+     return auth;
+     
+     /******************************************************************/
+     
+cleanup:
+     PRINTF(("gssapi_create: bailing\n\n"));
+     
+     if (AUTH_PRIVATE(auth))
+	  auth_gssapi_destroy(auth);
+     else if (auth)
+	  free(auth);
+     auth = NULL;
+     
+     /* don't assume the caller will want to change clnt->cl_auth */
+     clnt->cl_auth = save_auth;
+     
+     if (rpc_createerr.cf_stat == 0)
+	  rpc_createerr.cf_stat = RPC_AUTHERROR;
+     
+     return auth;
+}
+
+/*
+ * Function: marshall_new_creds
+ *
+ * Purpose: (pre-)serialize auth_msg and client_handle fields of
+ * auth_gssapi_creds into auth->cred_buf
+ *
+ * Arguments:
+ *
+ * 	auth		(r/w) the AUTH structure to modify
+ * 	auth_msg	(r) the auth_msg field to serialize
+ * 	client_handle	(r) the client_handle field to serialize, or
+ * 			NULL
+ *
+ * Returns: TRUE if successful, FALSE if not
+ *
+ * Requires: auth must point to a valid GSS-API auth structure, auth_msg
+ * must be TRUE or FALSE, client_handle must be a gss_buffer_t with a valid
+ * value and length field or NULL.
+ * 
+ * Effects: auth->ah_cred is set to the serialized auth_gssapi_creds
+ * version 2 structure (stored in the cred_buf field of private data)
+ * containing version, auth_msg and client_handle.
+ * auth->ah_cred.oa_flavor is set to AUTH_GSSAPI.  If cliend_handle is
+ * NULL, it is treated as if it had a length of 0 and a value of NULL.
+ *
+ * Modifies: auth
+ */
+static bool_t marshall_new_creds(
+     AUTH *auth,
+     bool_t auth_msg,
+     gss_buffer_t client_handle)
+{
+     auth_gssapi_creds creds;
+     XDR xdrs;
+     
+     PRINTF(("marshall_new_creds: starting\n"));
+
+     creds.version = 2;
+     
+     creds.auth_msg = auth_msg;
+     if (client_handle)
+	  GSS_COPY_BUFFER(creds.client_handle, *client_handle)
+     else {
+	  creds.client_handle.length = 0;
+	  creds.client_handle.value = NULL;
+     }
+     
+     xdrmem_create(&xdrs, (caddr_t) AUTH_PRIVATE(auth)->cred_buf,
+		   MAX_AUTH_BYTES, XDR_ENCODE);
+     if (! xdr_authgssapi_creds(&xdrs, &creds)) {
+	  PRINTF(("marshall_new_creds: failed encoding auth_gssapi_creds\n"));
+	  XDR_DESTROY(&xdrs);
+	  return FALSE;
+     }
+     AUTH_PRIVATE(auth)->cred_len = xdr_getpos(&xdrs);
+     XDR_DESTROY(&xdrs);
+     
+     PRINTF(("marshall_new_creds: auth_gssapi_creds is %d bytes\n",
+	     AUTH_PRIVATE(auth)->cred_len));
+     
+     auth->ah_cred.oa_flavor = AUTH_GSSAPI;
+     auth->ah_cred.oa_base = (char *) AUTH_PRIVATE(auth)->cred_buf;
+     auth->ah_cred.oa_length = AUTH_PRIVATE(auth)->cred_len;
+     
+     PRINTF(("marshall_new_creds: succeeding\n"));
+     
+     return TRUE;
+}
+
+
+/*
+ * Function: auth_gssapi_nextverf
+ *
+ * Purpose: None.
+ *
+ * Effects: None.  Never called.
+ */
+static void auth_gssapi_nextverf(AUTH *auth)
+{
+}
+
+/*
+ * Function: auth_gssapi_marhsall
+ *
+ * Purpose: Marshall RPC credentials and verifier onto xdr stream.
+ *
+ * Arguments:
+ *
+ * 	auth		(r/w) AUTH structure for client
+ * 	xdrs		(r/w) XDR stream to marshall to
+ *
+ * Returns: boolean indicating success/failure
+ *
+ * Effects:
+ * 
+ * The pre-serialized credentials in cred_buf are serialized.  If the
+ * context is established, the sealed sequence number is serialized as
+ * the verifier.  If the context is not established, an empty verifier
+ * is serialized.  The sequence number is *not* incremented, because
+ * this function is called multiple times if retransmission is required.
+ * 
+ * If this took all the header fields as arguments, it could sign
+ * them.
+ */
+static bool_t auth_gssapi_marshall(
+     AUTH *auth,
+     XDR *xdrs)
+{
+     OM_uint32 minor_stat;
+     gss_buffer_desc out_buf;
+     uint32_t seq_num;
+     
+     if (AUTH_PRIVATE(auth)->established == TRUE)  {
+	  PRINTF(("gssapi_marshall: starting\n"));
+	  
+	  seq_num = AUTH_PRIVATE(auth)->seq_num + 1;
+	  
+	  PRINTF(("gssapi_marshall: sending seq_num %d\n", seq_num));
+	  
+	  if (auth_gssapi_seal_seq(AUTH_PRIVATE(auth)->context, seq_num,
+				   &out_buf) == FALSE) {
+	       PRINTF(("gssapi_marhshall: seal failed\n"));
+	  }
+	  
+	  auth->ah_verf.oa_base = out_buf.value;
+	  auth->ah_verf.oa_length = out_buf.length;
+	  
+	  if (! xdr_opaque_auth(xdrs, &auth->ah_cred) ||
+	      ! xdr_opaque_auth(xdrs, &auth->ah_verf)) {
+	       (void) gss_release_buffer(&minor_stat, &out_buf);
+	       return FALSE;
+	  }
+	  (void) gss_release_buffer(&minor_stat, &out_buf);
+     } else {
+	  PRINTF(("gssapi_marshall: not established, sending null verf\n"));
+	  
+	  auth->ah_verf.oa_base = NULL;
+	  auth->ah_verf.oa_length = 0;
+	  
+	  if (! xdr_opaque_auth(xdrs, &auth->ah_cred) ||
+	      ! xdr_opaque_auth(xdrs, &auth->ah_verf)) {
+	       return FALSE;
+	  }
+     }
+     
+     return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_validate
+ *
+ * Purpose: Validate RPC response verifier from server.
+ *
+ * Effects: See design document, section XXX.
+ */
+static bool_t auth_gssapi_validate(
+     AUTH *auth,
+     struct opaque_auth *verf)
+{
+     gss_buffer_desc in_buf;
+     uint32_t seq_num;
+     
+     if (AUTH_PRIVATE(auth)->established == FALSE) {
+	  PRINTF(("gssapi_validate: not established, noop\n"));
+	  return TRUE;
+     }
+     
+     PRINTF(("gssapi_validate: starting\n"));
+     
+     in_buf.length = verf->oa_length;
+     in_buf.value = verf->oa_base;
+     if (auth_gssapi_unseal_seq(AUTH_PRIVATE(auth)->context, &in_buf,
+				&seq_num) == FALSE) {
+	  PRINTF(("gssapi_validate: failed unsealing verifier\n"));
+	  return FALSE;
+     }
+     
+     /* we sent seq_num+1, so we should get back seq_num+2 */
+     if (AUTH_PRIVATE(auth)->seq_num+2 != seq_num) {
+	  PRINTF(("gssapi_validate: expecting seq_num %d, got %d (%#x)\n",
+		  AUTH_PRIVATE(auth)->seq_num + 2, seq_num, seq_num));
+	  return FALSE;
+     }
+     PRINTF(("gssapi_validate: seq_num %d okay\n", seq_num));
+     
+     /* +1 for successful transmission, +1 for successful validation */
+     AUTH_PRIVATE(auth)->seq_num += 2;
+     
+     PRINTF(("gssapi_validate: succeeding\n"));
+     
+     return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_refresh
+ *
+ * Purpose: Attempts to resyncrhonize the sequence number.
+ *
+ * Effects:
+ * 
+ * When the server receives a properly authenticated RPC call, it
+ * increments the sequence number it is expecting from the client.
+ * But if the server's response is lost for any reason, the client
+ * can't know whether the server ever received it, assumes it didn't,
+ * and does *not* increment its sequence number.  Thus, the client's
+ * next call will fail with AUTH_REJECTEDCRED because the server will
+ * think it is a replay attack.
+ *
+ * When an AUTH_REJECTEDCRED error arrives, this function attempts to
+ * resyncrhonize by incrementing the client's sequence number and
+ * returning TRUE.  If any other error arrives, it returns FALSE.
+ */
+static bool_t auth_gssapi_refresh(
+     AUTH *auth,
+     struct rpc_msg *msg)
+{
+     if (msg->rm_reply.rp_rjct.rj_stat == AUTH_ERROR &&
+	 msg->rm_reply.rp_rjct.rj_why == AUTH_REJECTEDVERF) {
+	  PRINTF(("gssapi_refresh: rejected verifier, incrementing\n"));
+	  AUTH_PRIVATE(auth)->seq_num++;
+	  return TRUE;
+     } else {
+	  PRINTF(("gssapi_refresh: failing\n"));
+	  return FALSE;
+     }
+}
+
+/*
+ * Function: auth_gssapi_destroy
+ *
+ * Purpose: Destroy a GSS-API authentication structure.
+ *
+ * Effects:  This function destroys the GSS-API authentication
+ * context, and sends a message to the server instructing it to
+ * invokte gss_process_token() and thereby destroy its corresponding
+ * context.  Since the client doesn't really care whether the server
+ * gets this message, no failures are reported.
+ */
+static void auth_gssapi_destroy(AUTH *auth)
+{
+     struct timeval timeout;
+     OM_uint32 gssstat, minor_stat;
+     gss_cred_id_t cred;
+     int callstat;
+     
+     if (AUTH_PRIVATE(auth)->client_handle.length == 0) {
+	  PRINTF(("gssapi_destroy: no client_handle, not calling destroy\n"));
+	  goto skip_call;
+     }
+     
+     PRINTF(("gssapi_destroy: marshalling new creds\n"));
+     if (!marshall_new_creds(auth, TRUE, &AUTH_PRIVATE(auth)->client_handle)) {
+	  PRINTF(("gssapi_destroy: marshall_new_creds failed\n"));
+	  goto skip_call;
+     }
+     
+     PRINTF(("gssapi_destroy: calling GSSAPI_DESTROY\n"));
+     timeout.tv_sec = 1;
+     timeout.tv_usec = 0;
+     callstat = clnt_call(AUTH_PRIVATE(auth)->clnt, AUTH_GSSAPI_DESTROY,
+			  xdr_void, NULL, xdr_void, NULL, timeout);
+     if (callstat != RPC_SUCCESS)
+	  clnt_sperror(AUTH_PRIVATE(auth)->clnt,
+		       "gssapi_destroy: GSSAPI_DESTROY failed");
+     
+skip_call:
+     PRINTF(("gssapi_destroy: deleting context\n"));
+     gssstat = gss_delete_sec_context(&minor_stat,
+				      &AUTH_PRIVATE(auth)->context,
+				      NULL);
+     if (gssstat != GSS_S_COMPLETE)
+	  AUTH_GSSAPI_DISPLAY_STATUS(("deleting context", gssstat,
+				      minor_stat));
+     if (AUTH_PRIVATE(auth)->def_cred) {
+	  cred = GSS_C_NO_CREDENTIAL;
+	  gssstat = gss_release_cred(&minor_stat, &cred);
+	  if (gssstat != GSS_S_COMPLETE)
+	       AUTH_GSSAPI_DISPLAY_STATUS(("deleting default credential",
+					   gssstat, minor_stat));
+     }
+     
+     if (AUTH_PRIVATE(auth)->client_handle.length != 0)
+	  gss_release_buffer(&minor_stat,
+			     &AUTH_PRIVATE(auth)->client_handle);
+     
+#if 0
+     PRINTF(("gssapi_destroy: calling GSSAPI_EXIT\n"));
+     AUTH_PRIVATE(auth)->established = FALSE;
+     callstat = clnt_call(AUTH_PRIVATE(auth)->clnt, AUTH_GSSAPI_EXIT,
+			  xdr_void, NULL, xdr_void, NULL, timeout);
+#endif
+     
+     free(auth->ah_private);
+     free(auth);
+     PRINTF(("gssapi_destroy: done\n"));
+}
+
+/*
+ * Function: auth_gssapi_wrap
+ *
+ * Purpose: encrypt the serialized arguments from xdr_func applied to
+ * xdr_ptr and write the result to xdrs.
+ *
+ * Effects: See design doc, section XXX.
+ */
+static bool_t auth_gssapi_wrap(
+     AUTH *auth,
+     XDR *out_xdrs,
+     bool_t (*xdr_func)(),
+     caddr_t xdr_ptr)
+{
+     OM_uint32 gssstat, minor_stat;
+     
+     if (! AUTH_PRIVATE(auth)->established) {
+	  PRINTF(("gssapi_wrap: context not established, noop\n"));
+	  return (*xdr_func)(out_xdrs, xdr_ptr);
+     } else if (! auth_gssapi_wrap_data(&gssstat, &minor_stat,
+					AUTH_PRIVATE(auth)->context,
+					AUTH_PRIVATE(auth)->seq_num+1,
+					out_xdrs, xdr_func, xdr_ptr)) {
+	  if (gssstat != GSS_S_COMPLETE)
+	       AUTH_GSSAPI_DISPLAY_STATUS(("encrypting function arguments",
+					   gssstat, minor_stat));
+	  return FALSE;
+     } else
+	  return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_unwrap
+ *
+ * Purpose: read encrypted arguments from xdrs, decrypt, and
+ * deserialize with xdr_func into xdr_ptr.
+ *
+ * Effects: See design doc, section XXX.
+ */
+static bool_t auth_gssapi_unwrap(
+     AUTH *auth,
+     XDR *in_xdrs,
+     bool_t (*xdr_func)(),
+     caddr_t xdr_ptr)
+{
+     OM_uint32 gssstat, minor_stat;
+     
+     if (! AUTH_PRIVATE(auth)->established) {
+	  PRINTF(("gssapi_unwrap: context not established, noop\n"));
+	  return (*xdr_func)(in_xdrs, xdr_ptr);
+     } else if (! auth_gssapi_unwrap_data(&gssstat, &minor_stat,
+					  AUTH_PRIVATE(auth)->context,
+					  AUTH_PRIVATE(auth)->seq_num,
+					  in_xdrs, xdr_func, xdr_ptr)) {
+	  if (gssstat != GSS_S_COMPLETE)
+	       AUTH_GSSAPI_DISPLAY_STATUS(("decrypting function arguments",
+					   gssstat, minor_stat));
+	  return FALSE;
+     } else
+	  return TRUE;
+}
diff --git a/krb5-1-6/src/lib/rpc/auth_gssapi_misc.c b/krb5-1-6/src/lib/rpc/auth_gssapi_misc.c
new file mode 100644
index 000000000..3e878206b
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/auth_gssapi_misc.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ */
+
+#include <gssrpc/rpc.h>
+#include <stdio.h>
+
+#include <gssapi/gssapi.h>
+#include <gssrpc/auth_gssapi.h>
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int misc_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (misc_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+	if (misc_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+   
+static void auth_gssapi_display_status_1
+	(char *, OM_uint32, int, int);
+   
+bool_t xdr_gss_buf(
+     XDR *xdrs,
+     gss_buffer_t buf)
+{
+     /*
+      * On decode, xdr_bytes will only allocate buf->value if the
+      * length read in is < maxsize (last arg).  This is dumb, because
+      * the whole point of allocating memory is so that I don't *have*
+      * to know the maximum length.  -1 effectively disables this
+      * braindamage.
+      */
+     bool_t result;
+     /* Fix type mismatches between APIs.  */
+     unsigned int length = buf->length;
+     result = xdr_bytes(xdrs, (char **) &buf->value, &length,
+			(xdrs->x_op == XDR_DECODE && buf->value == NULL)
+			? (unsigned int) -1 : (unsigned int) buf->length);
+     buf->length = length;
+     return result;
+}
+
+bool_t xdr_authgssapi_creds(
+     XDR *xdrs,
+     auth_gssapi_creds *creds)
+{
+     if (! xdr_u_int32(xdrs, &creds->version) ||
+	 ! xdr_bool(xdrs, &creds->auth_msg) ||
+	 ! xdr_gss_buf(xdrs, &creds->client_handle))
+       return FALSE;
+     return TRUE;
+}
+
+bool_t xdr_authgssapi_init_arg(
+     XDR *xdrs,
+     auth_gssapi_init_arg *init_arg)
+{
+     if (! xdr_u_int32(xdrs, &init_arg->version) ||
+	 ! xdr_gss_buf(xdrs, &init_arg->token))
+	  return FALSE;
+     return TRUE;
+}
+
+bool_t xdr_authgssapi_init_res(
+     XDR *xdrs,
+     auth_gssapi_init_res *init_res)
+{
+     if (! xdr_u_int32(xdrs, &init_res->version) ||
+	 ! xdr_gss_buf(xdrs, &init_res->client_handle) ||
+	 ! xdr_u_int32(xdrs, &init_res->gss_major) ||
+	 ! xdr_u_int32(xdrs, &init_res->gss_minor) ||
+	 ! xdr_gss_buf(xdrs, &init_res->token) ||
+	 ! xdr_gss_buf(xdrs, &init_res->signed_isn))
+	  return FALSE;
+     return TRUE;
+}
+
+bool_t auth_gssapi_seal_seq(
+     gss_ctx_id_t context,
+     uint32_t seq_num,
+     gss_buffer_t out_buf)
+{
+     gss_buffer_desc in_buf;
+     OM_uint32 gssstat, minor_stat;
+     uint32_t nl_seq_num;
+     
+     nl_seq_num = htonl(seq_num);
+     
+     in_buf.length = sizeof(uint32_t);
+     in_buf.value = (char *) &nl_seq_num;
+     gssstat = gss_seal(&minor_stat, context, 0, GSS_C_QOP_DEFAULT,
+			&in_buf, NULL, out_buf);
+     if (gssstat != GSS_S_COMPLETE) {
+	  PRINTF(("gssapi_seal_seq: failed\n"));
+	  AUTH_GSSAPI_DISPLAY_STATUS(("sealing sequence number",
+				      gssstat, minor_stat));
+	  return FALSE;
+     }
+     return TRUE;
+}
+
+bool_t auth_gssapi_unseal_seq(
+     gss_ctx_id_t context,
+     gss_buffer_t in_buf,
+     uint32_t *seq_num)
+{
+     gss_buffer_desc out_buf;
+     OM_uint32 gssstat, minor_stat;
+     uint32_t nl_seq_num;
+     
+     gssstat = gss_unseal(&minor_stat, context, in_buf, &out_buf,
+			  NULL, NULL);
+     if (gssstat != GSS_S_COMPLETE) {
+	  PRINTF(("gssapi_unseal_seq: failed\n"));
+	  AUTH_GSSAPI_DISPLAY_STATUS(("unsealing sequence number",
+				      gssstat, minor_stat)); 
+	  return FALSE;
+     } else if (out_buf.length != sizeof(uint32_t)) {
+	  PRINTF(("gssapi_unseal_seq: unseal gave %d bytes\n",
+		  (int) out_buf.length));
+	  gss_release_buffer(&minor_stat, &out_buf);
+	  return FALSE;
+     }
+     
+     nl_seq_num = *((uint32_t *) out_buf.value);
+     *seq_num = (uint32_t) ntohl(nl_seq_num);
+     gss_release_buffer(&minor_stat, &out_buf);
+     
+     return TRUE;
+}
+
+void auth_gssapi_display_status(
+     char *msg,
+     OM_uint32 major,
+     OM_uint32 minor)
+{
+     auth_gssapi_display_status_1(msg, major, GSS_C_GSS_CODE, 0);
+     auth_gssapi_display_status_1(msg, minor, GSS_C_MECH_CODE, 0);
+}
+
+static void auth_gssapi_display_status_1(
+     char *m,
+     OM_uint32 code,
+     int type,
+     int rec)
+{
+     OM_uint32 gssstat, minor_stat;
+     gss_buffer_desc msg;
+     OM_uint32 msg_ctx;
+     
+     msg_ctx = 0;
+     while (1) {
+	  gssstat = gss_display_status(&minor_stat, code,
+				       type, GSS_C_NULL_OID,
+				       &msg_ctx, &msg);
+	  if (gssstat != GSS_S_COMPLETE) {
+ 	       if (!rec) {
+		    auth_gssapi_display_status_1(m,gssstat,GSS_C_GSS_CODE,1); 
+		    auth_gssapi_display_status_1(m, minor_stat,
+						 GSS_C_MECH_CODE, 1);
+	       } else {
+		   fputs ("GSS-API authentication error ", stderr);
+		   fwrite (msg.value, msg.length, 1, stderr);
+		   fputs (": recursive failure!\n", stderr);
+	       }
+	       return;
+	  }
+
+	  fprintf (stderr, "GSS-API authentication error %s: ", m);
+	  fwrite (msg.value, msg.length, 1, stderr);
+	  putc ('\n', stderr);
+	  (void) gss_release_buffer(&minor_stat, &msg);
+	  
+	  if (!msg_ctx)
+	       break;
+     }
+}
+
+bool_t auth_gssapi_wrap_data(
+     OM_uint32 *major,
+     OM_uint32 *minor,
+     gss_ctx_id_t context,
+     uint32_t seq_num,
+     XDR *out_xdrs,
+     bool_t (*xdr_func)(),
+     caddr_t xdr_ptr)
+{
+     gss_buffer_desc in_buf, out_buf;
+     XDR temp_xdrs;
+     int conf_state;
+     unsigned int length;
+     
+     PRINTF(("gssapi_wrap_data: starting\n"));
+     
+     *major = GSS_S_COMPLETE;
+     *minor = 0; /* assumption */
+     
+     xdralloc_create(&temp_xdrs, XDR_ENCODE);
+     
+     /* serialize the sequence number into local memory */
+     PRINTF(("gssapi_wrap_data: encoding seq_num %d\n", seq_num));
+     if (! xdr_u_int32(&temp_xdrs, &seq_num)) {
+	  PRINTF(("gssapi_wrap_data: serializing seq_num failed\n"));
+	  XDR_DESTROY(&temp_xdrs);
+	  return FALSE;
+     }
+     
+     /* serialize the arguments into local memory */
+     if (!(*xdr_func)(&temp_xdrs, xdr_ptr)) {
+	  PRINTF(("gssapi_wrap_data: serializing arguments failed\n"));
+	  XDR_DESTROY(&temp_xdrs);
+	  return FALSE;
+     }
+     
+     in_buf.length = xdr_getpos(&temp_xdrs);
+     in_buf.value = xdralloc_getdata(&temp_xdrs);
+     
+     *major = gss_seal(minor, context, 1,
+		       GSS_C_QOP_DEFAULT, &in_buf, &conf_state,
+		       &out_buf);
+     if (*major != GSS_S_COMPLETE) {
+	  XDR_DESTROY(&temp_xdrs);
+	  return FALSE;
+     }
+     
+     PRINTF(("gssapi_wrap_data: %d bytes data, %d bytes sealed\n",
+	     (int) in_buf.length, (int) out_buf.length));
+     
+     /* write the token */
+     length = out_buf.length;
+     if (! xdr_bytes(out_xdrs, (char **) &out_buf.value, 
+		     (unsigned int *) &length,
+		     out_buf.length)) {
+	  PRINTF(("gssapi_wrap_data: serializing encrypted data failed\n"));
+	  XDR_DESTROY(&temp_xdrs);
+	  return FALSE;
+     }
+     
+     *major = gss_release_buffer(minor, &out_buf);
+     
+     PRINTF(("gssapi_wrap_data: succeeding\n\n"));
+     XDR_DESTROY(&temp_xdrs);
+     return TRUE;
+}
+
+bool_t auth_gssapi_unwrap_data(
+     OM_uint32 *major,
+     OM_uint32 *minor,
+     gss_ctx_id_t context,
+     uint32_t seq_num,
+     XDR *in_xdrs,
+     bool_t (*xdr_func)(),
+     caddr_t xdr_ptr)
+{
+     gss_buffer_desc in_buf, out_buf;
+     XDR temp_xdrs;
+     uint32_t verf_seq_num;
+     int conf, qop;
+     unsigned int length;
+     
+     PRINTF(("gssapi_unwrap_data: starting\n"));
+     
+     *major = GSS_S_COMPLETE;
+     *minor = 0; /* assumption */
+     
+     in_buf.value = NULL;
+     out_buf.value = NULL;
+     if (! xdr_bytes(in_xdrs, (char **) &in_buf.value,
+		     &length, (unsigned int) -1)) {
+	 PRINTF(("gssapi_unwrap_data: deserializing encrypted data failed\n"));
+	 temp_xdrs.x_op = XDR_FREE;
+	 (void)xdr_bytes(&temp_xdrs, (char **) &in_buf.value, &length,
+			 (unsigned int) -1);
+	 return FALSE;
+     }
+     in_buf.length = length;
+     
+     *major = gss_unseal(minor, context, &in_buf, &out_buf, &conf,
+			 &qop);
+     free(in_buf.value);
+     if (*major != GSS_S_COMPLETE)
+	  return FALSE;
+     
+     PRINTF(("gssapi_unwrap_data: %d bytes data, %d bytes sealed\n",
+	     out_buf.length, in_buf.length));
+     
+     xdrmem_create(&temp_xdrs, out_buf.value, out_buf.length, XDR_DECODE);
+     
+     /* deserialize the sequence number */
+     if (! xdr_u_int32(&temp_xdrs, &verf_seq_num)) {
+	  PRINTF(("gssapi_unwrap_data: deserializing verf_seq_num failed\n"));
+	  gss_release_buffer(minor, &out_buf);
+	  XDR_DESTROY(&temp_xdrs);
+	  return FALSE;
+     }
+     if (verf_seq_num != seq_num) {
+	  PRINTF(("gssapi_unwrap_data: seq %d specified, read %d\n",
+		  seq_num, verf_seq_num));
+	  gss_release_buffer(minor, &out_buf);
+	  XDR_DESTROY(&temp_xdrs);
+	  return FALSE;
+     }
+     PRINTF(("gssapi_unwrap_data: unwrap seq_num %d okay\n", verf_seq_num));
+     
+     /* deserialize the arguments into xdr_ptr */
+     if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) {
+	  PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n"));
+	  gss_release_buffer(minor, &out_buf);
+	  xdr_free(xdr_func, xdr_ptr);
+	  XDR_DESTROY(&temp_xdrs);
+	  return FALSE;
+     }
+     
+     PRINTF(("gssapi_unwrap_data: succeeding\n\n"));
+     
+     gss_release_buffer(minor, &out_buf);
+     XDR_DESTROY(&temp_xdrs);
+     return TRUE;
+}
diff --git a/krb5-1-6/src/lib/rpc/auth_none.c b/krb5-1-6/src/lib/rpc/auth_none.c
new file mode 100644
index 000000000..f4869aa6a
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/auth_none.c
@@ -0,0 +1,145 @@
+/* @(#)auth_none.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null" 
+ * credentials and verifiers to remote systems. 
+ * 
+ * Copyright (C) 1984, Sun Microsystems, Inc. 
+ */
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <gssrpc/auth.h>
+#include <stdlib.h>
+#define MAX_MARSHEL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+static void	authnone_verf(AUTH *);
+static void	authnone_destroy(AUTH *);
+static bool_t	authnone_marshal(AUTH *, XDR *);
+static bool_t	authnone_validate(AUTH *, struct opaque_auth *);
+static bool_t	authnone_refresh(AUTH *, struct rpc_msg *);
+static bool_t	authnone_wrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+
+static struct auth_ops ops = {
+	authnone_verf,
+	authnone_marshal,
+	authnone_validate,
+	authnone_refresh,
+	authnone_destroy,
+	authnone_wrap,
+	authnone_wrap
+};
+
+static struct authnone_private {
+	AUTH	no_client;
+	char	marshalled_client[MAX_MARSHEL_SIZE];
+	u_int	mcnt;
+} *authnone_private;
+
+AUTH *
+authnone_create(void)
+{
+	register struct authnone_private *ap = authnone_private;
+	XDR xdr_stream;
+	register XDR *xdrs;
+
+	if (ap == 0) {
+		ap = (struct authnone_private *)calloc(1, sizeof (*ap));
+		if (ap == 0)
+			return (0);
+		authnone_private = ap;
+	}
+	if (!ap->mcnt) {
+		ap->no_client.ah_cred = ap->no_client.ah_verf = gssrpc__null_auth;
+		ap->no_client.ah_ops = &ops;
+		xdrs = &xdr_stream;
+		xdrmem_create(xdrs, ap->marshalled_client, (u_int)MAX_MARSHEL_SIZE,
+		    XDR_ENCODE);
+		(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
+		(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
+		ap->mcnt = XDR_GETPOS(xdrs);
+		XDR_DESTROY(xdrs);
+	}
+	return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_marshal(AUTH *client, XDR *xdrs)
+{
+	register struct authnone_private *ap = authnone_private;
+
+	if (ap == 0)
+		return (0);
+	return ((*xdrs->x_ops->x_putbytes)(xdrs,
+	    ap->marshalled_client, ap->mcnt));
+}
+
+/*ARGSUSED*/
+static void 
+authnone_verf(AUTH *auth)
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_validate(AUTH *auth, struct opaque_auth *verf)
+{
+
+	return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_refresh(AUTH *auth, struct rpc_msg *msg)
+{
+
+	return (FALSE);
+}
+
+/*ARGSUSED*/
+static void
+authnone_destroy(AUTH *auth)
+{
+}
+
+static bool_t
+authnone_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere)
+{
+	return ((*xfunc)(xdrs, xwhere));
+}
diff --git a/krb5-1-6/src/lib/rpc/auth_unix.c b/krb5-1-6/src/lib/rpc/auth_unix.c
new file mode 100644
index 000000000..eaa842732
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/auth_unix.c
@@ -0,0 +1,328 @@
+/* @(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * auth_unix.c, Implements UNIX style authentication parameters. 
+ *  
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The system is very weak.  The client uses no encryption for it's
+ * credentials and only sends null verifiers.  The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <gssrpc/auth.h>
+#include <gssrpc/auth_unix.h>
+
+#include "autoconf.h"
+
+/*
+ * Unix authenticator operations vector
+ */
+static void	authunix_nextverf(AUTH *);
+static bool_t	authunix_marshal(AUTH *, XDR *);
+static bool_t	authunix_validate(AUTH *, struct opaque_auth *);
+static bool_t	authunix_refresh(AUTH *, struct rpc_msg *);
+static void	authunix_destroy(AUTH *);
+static bool_t	authunix_wrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+
+static struct auth_ops auth_unix_ops = {
+	authunix_nextverf,
+	authunix_marshal,
+	authunix_validate,
+	authunix_refresh,
+	authunix_destroy,
+	authunix_wrap,
+	authunix_wrap
+};
+
+/*
+ * This struct is pointed to by the ah_private field of an auth_handle.
+ */
+struct audata {
+	struct opaque_auth	au_origcred;	/* original credentials */
+	struct opaque_auth	au_shcred;	/* short hand cred */
+	uint32_t		au_shfaults;	/* short hand cache faults */
+	char			au_marshed[MAX_AUTH_BYTES];
+	u_int			au_mpos;	/* xdr pos at end of marshed */
+};
+#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
+
+static void marshal_new_auth(AUTH *);
+
+
+/*
+ * Create a unix style authenticator.
+ * Returns an auth handle with the given stuff in it.
+ */
+AUTH *
+authunix_create(
+	char *machname,
+	int uid,
+	int gid,
+	register int len,
+	int *aup_gids)
+{
+	struct authunix_parms aup;
+	char mymem[MAX_AUTH_BYTES];
+	struct timeval now;
+	XDR xdrs;
+	register AUTH *auth;
+	register struct audata *au;
+
+	/*
+	 * Allocate and set up auth handle
+	 */
+	auth = (AUTH *)mem_alloc(sizeof(*auth));
+#ifndef KERNEL
+	if (auth == NULL) {
+		(void)fprintf(stderr, "authunix_create: out of memory\n");
+		return (NULL);
+	}
+#endif
+	au = (struct audata *)mem_alloc(sizeof(*au));
+#ifndef KERNEL
+	if (au == NULL) {
+		(void)fprintf(stderr, "authunix_create: out of memory\n");
+		return (NULL);
+	}
+#endif
+	auth->ah_ops = &auth_unix_ops;
+	auth->ah_private = (caddr_t)au;
+	auth->ah_verf = au->au_shcred = gssrpc__null_auth;
+	au->au_shfaults = 0;
+
+	/*
+	 * fill in param struct from the given params
+	 */
+	(void)gettimeofday(&now,  (struct timezone *)0);
+	aup.aup_time = now.tv_sec;
+	aup.aup_machname = machname;
+	aup.aup_uid = uid;
+	aup.aup_gid = gid;
+	aup.aup_len = (u_int)len;
+	aup.aup_gids = aup_gids;
+
+	/*
+	 * Serialize the parameters into origcred
+	 */
+	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
+	if (! xdr_authunix_parms(&xdrs, &aup)) 
+		abort();
+	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
+	au->au_origcred.oa_flavor = AUTH_UNIX;
+#ifdef KERNEL
+	au->au_origcred.oa_base = mem_alloc((u_int) len);
+#else
+	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
+		(void)fprintf(stderr, "authunix_create: out of memory\n");
+		return (NULL);
+	}
+#endif
+	memmove(au->au_origcred.oa_base, mymem, (u_int)len);
+
+	/*
+	 * set auth handle to reflect new cred.
+	 */
+	auth->ah_cred = au->au_origcred;
+	marshal_new_auth(auth);
+	return (auth);
+}
+
+/*
+ * Returns an auth handle with parameters determined by doing lots of
+ * syscalls.
+ */
+AUTH *
+authunix_create_default(void)
+{
+	register int len;
+	char machname[MAX_MACHINE_NAME + 1];
+	register int uid;
+	register int gid;
+	GETGROUPS_T gids[NGRPS];
+	int igids[NGRPS], i;
+
+	if (gethostname(machname, MAX_MACHINE_NAME) == -1)
+		abort();
+	machname[MAX_MACHINE_NAME] = 0;
+	uid = geteuid();
+	gid = getegid();
+	if ((len = getgroups(NGRPS, gids)) < 0)
+		abort();
+	for(i = 0; i < NGRPS; i++) {
+	        igids[i] = gids[i];
+	}
+	return (authunix_create(machname, uid, gid, len, igids));
+}
+
+/*
+ * authunix operations
+ */
+
+static void
+authunix_nextverf(AUTH *auth)
+{
+	/* no action necessary */
+}
+
+static bool_t
+authunix_marshal(AUTH *auth, XDR *xdrs)
+{
+	register struct audata *au = AUTH_PRIVATE(auth);
+
+	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+}
+
+static bool_t
+authunix_validate(register AUTH *auth, struct opaque_auth *verf)
+{
+	register struct audata *au;
+	XDR xdrs;
+
+	if (verf->oa_flavor == AUTH_SHORT) {
+		au = AUTH_PRIVATE(auth);
+		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, XDR_DECODE);
+
+		if (au->au_shcred.oa_base != NULL) {
+			mem_free(au->au_shcred.oa_base,
+			    au->au_shcred.oa_length);
+			au->au_shcred.oa_base = NULL;
+		}
+		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
+			auth->ah_cred = au->au_shcred;
+		} else {
+			xdrs.x_op = XDR_FREE;
+			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
+			au->au_shcred.oa_base = NULL;
+			auth->ah_cred = au->au_origcred;
+		}
+		marshal_new_auth(auth);
+	}
+	return (TRUE);
+}
+
+static bool_t
+authunix_refresh(register AUTH *auth, struct rpc_msg *msg)
+{
+	register struct audata *au = AUTH_PRIVATE(auth);
+	struct authunix_parms aup;
+	struct timeval now;
+	XDR xdrs;
+	register int stat;
+
+	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
+		/* there is no hope.  Punt */
+		return (FALSE);
+	}
+	au->au_shfaults ++;
+
+	/* first deserialize the creds back into a struct authunix_parms */
+	aup.aup_machname = NULL;
+	aup.aup_gids = (int *)NULL;
+	xdrmem_create(&xdrs, au->au_origcred.oa_base,
+	    au->au_origcred.oa_length, XDR_DECODE);
+	stat = xdr_authunix_parms(&xdrs, &aup);
+	if (! stat) 
+		goto done;
+
+	/* update the time and serialize in place */
+	(void)gettimeofday(&now, (struct timezone *)0);
+	aup.aup_time = now.tv_sec;
+	xdrs.x_op = XDR_ENCODE;
+	XDR_SETPOS(&xdrs, 0);
+	stat = xdr_authunix_parms(&xdrs, &aup);
+	if (! stat)
+		goto done;
+	auth->ah_cred = au->au_origcred;
+	marshal_new_auth(auth);
+done:
+	/* free the struct authunix_parms created by deserializing */
+	xdrs.x_op = XDR_FREE;
+	(void)xdr_authunix_parms(&xdrs, &aup);
+	XDR_DESTROY(&xdrs);
+	return (stat);
+}
+
+static void
+authunix_destroy(register AUTH *auth)
+{
+	register struct audata *au = AUTH_PRIVATE(auth);
+
+	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
+
+	if (au->au_shcred.oa_base != NULL)
+		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
+
+	mem_free(auth->ah_private, sizeof(struct audata));
+
+	if (auth->ah_verf.oa_base != NULL)
+		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
+
+	mem_free((caddr_t)auth, sizeof(*auth));
+}
+
+/*
+ * Marshals (pre-serializes) an auth struct.
+ * sets private data, au_marshed and au_mpos
+ */
+static void
+marshal_new_auth(register AUTH *auth)
+{
+	XDR		xdr_stream;
+	register XDR	*xdrs = &xdr_stream;
+	register struct audata *au = AUTH_PRIVATE(auth);
+
+	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
+	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
+	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
+		perror("auth_none.c - Fatal marshalling problem");
+	} else {
+		au->au_mpos = XDR_GETPOS(xdrs);
+	}
+	XDR_DESTROY(xdrs);
+}
+
+static bool_t
+authunix_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere)
+{
+	return ((*xfunc)(xdrs, xwhere));
+}
diff --git a/krb5-1-6/src/lib/rpc/authgss_prot.c b/krb5-1-6/src/lib/rpc/authgss_prot.c
new file mode 100644
index 000000000..ab6e7fea0
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/authgss_prot.c
@@ -0,0 +1,366 @@
+/*
+  authgss_prot.c
+  
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+  
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+  
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of the University nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Id: authgss_prot.c,v 1.18 2000/09/01 04:14:03 dugsong Exp
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <gssrpc/rpc.h>
+#ifdef HAVE_HEIMDAL
+#include <gssapi.h>
+#else
+#include <gssapi/gssapi.h>
+#endif
+
+bool_t
+xdr_rpc_gss_buf(XDR *xdrs, gss_buffer_t buf, u_int maxsize)
+{
+	bool_t xdr_stat;
+	u_int tmplen;
+
+	if (xdrs->x_op != XDR_DECODE) {
+		if (buf->length > UINT_MAX)
+			return (FALSE);
+		else
+			tmplen = buf->length;
+	}
+	xdr_stat = xdr_bytes(xdrs, (char **)&buf->value, &tmplen, maxsize);
+
+	if (xdr_stat && xdrs->x_op == XDR_DECODE)
+		buf->length = tmplen;
+
+	return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
+{
+	bool_t xdr_stat;
+
+	xdr_stat = (xdr_u_int(xdrs, &p->gc_v) &&
+		    xdr_enum(xdrs, (enum_t *)&p->gc_proc) &&
+		    xdr_u_int32(xdrs, &p->gc_seq) &&
+		    xdr_enum(xdrs, (enum_t *)&p->gc_svc) &&
+		    xdr_rpc_gss_buf(xdrs, &p->gc_ctx, MAX_AUTH_BYTES));
+
+	log_debug("xdr_rpc_gss_cred: %s %s "
+		  "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",
+		  (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
+		  (xdr_stat == TRUE) ? "success" : "failure",
+		  p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc,
+		  p->gc_ctx.value, p->gc_ctx.length);
+
+	return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p)
+{
+	bool_t xdr_stat;
+
+	xdr_stat = xdr_rpc_gss_buf(xdrs, p, MAX_NETOBJ_SZ);
+
+	log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",
+		  (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
+		  (xdr_stat == TRUE) ? "success" : "failure",
+		  p->value, p->length);
+	
+	return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
+{
+	bool_t xdr_stat;
+
+	xdr_stat = (xdr_rpc_gss_buf(xdrs, &p->gr_ctx, MAX_NETOBJ_SZ) &&
+		    xdr_u_int32(xdrs, &p->gr_major) &&
+		    xdr_u_int32(xdrs, &p->gr_minor) &&
+		    xdr_u_int32(xdrs, &p->gr_win) &&
+		    xdr_rpc_gss_buf(xdrs, &p->gr_token, MAX_NETOBJ_SZ));
+
+	log_debug("xdr_rpc_gss_init_res %s %s "
+		  "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",
+		  (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
+		  (xdr_stat == TRUE) ? "success" : "failure",
+		  p->gr_ctx.value, p->gr_ctx.length,
+		  p->gr_major, p->gr_minor, p->gr_win,
+		  p->gr_token.value, p->gr_token.length);
+	
+	return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
+		      gss_ctx_id_t ctx, gss_qop_t qop,
+		      rpc_gss_svc_t svc, uint32_t seq)
+{
+	XDR		tmpxdrs;
+	gss_buffer_desc	databuf, wrapbuf;
+	OM_uint32	maj_stat, min_stat;
+	int		conf_state;
+	bool_t		xdr_stat;
+
+	xdralloc_create(&tmpxdrs, XDR_ENCODE);
+
+	xdr_stat = FALSE;
+	
+	/* Marshal rpc_gss_data_t (sequence number + arguments). */
+	if (!xdr_u_int32(&tmpxdrs, &seq) || !(*xdr_func)(&tmpxdrs, xdr_ptr))
+		goto errout;
+
+	/* Set databuf to marshalled rpc_gss_data_t. */
+	databuf.length = xdr_getpos(&tmpxdrs);
+	databuf.value = xdralloc_getdata(&tmpxdrs);
+
+	if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
+		if (!xdr_rpc_gss_buf(xdrs, &databuf, (unsigned int)-1))
+			goto errout;
+
+		/* Checksum rpc_gss_data_t. */
+		maj_stat = gss_get_mic(&min_stat, ctx, qop,
+				       &databuf, &wrapbuf);
+		if (maj_stat != GSS_S_COMPLETE) {
+			log_debug("gss_get_mic failed");
+			goto errout;
+		}
+		/* Marshal checksum. */
+		xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1);
+		gss_release_buffer(&min_stat, &wrapbuf);
+	}		
+	else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
+		/* Encrypt rpc_gss_data_t. */
+		maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
+				    &conf_state, &wrapbuf);
+		if (maj_stat != GSS_S_COMPLETE) {
+			log_status("gss_wrap", maj_stat, min_stat);
+			goto errout;
+		}
+		/* Marshal databody_priv. */
+		xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1);
+		gss_release_buffer(&min_stat, &wrapbuf);
+	}
+errout:
+	xdr_destroy(&tmpxdrs);
+	return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
+			gss_ctx_id_t ctx, gss_qop_t qop,
+			rpc_gss_svc_t svc, uint32_t seq)
+{
+	XDR		tmpxdrs;
+	gss_buffer_desc	databuf, wrapbuf;
+	OM_uint32	maj_stat, min_stat;
+	uint32_t	seq_num;
+	int		conf_state;
+	gss_qop_t	qop_state;
+	bool_t		xdr_stat;
+
+	if (xdr_func == xdr_void || xdr_ptr == NULL)
+		return (TRUE);
+	
+	memset(&databuf, 0, sizeof(databuf));
+	memset(&wrapbuf, 0, sizeof(wrapbuf));
+	
+	if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
+		/* Decode databody_integ. */
+		if (!xdr_rpc_gss_buf(xdrs, &databuf, (unsigned int)-1)) {
+			log_debug("xdr decode databody_integ failed");
+			return (FALSE);
+		}
+		/* Decode checksum. */
+		if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1)) {
+			gss_release_buffer(&min_stat, &databuf);
+			log_debug("xdr decode checksum failed");
+			return (FALSE);
+		}
+		/* Verify checksum and QOP. */
+		maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
+					  &wrapbuf, &qop_state);
+		gss_release_buffer(&min_stat, &wrapbuf);
+		
+		if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
+			gss_release_buffer(&min_stat, &databuf);
+			log_status("gss_verify_mic", maj_stat, min_stat);
+			return (FALSE);
+		}
+	}
+	else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
+		/* Decode databody_priv. */
+		if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1)) {
+			log_debug("xdr decode databody_priv failed");
+			return (FALSE);
+		}
+		/* Decrypt databody. */
+		maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
+				      &conf_state, &qop_state);
+		
+		gss_release_buffer(&min_stat, &wrapbuf);
+		
+		/* Verify encryption and QOP. */
+		if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
+			conf_state != TRUE) {
+			gss_release_buffer(&min_stat, &databuf);
+			log_status("gss_unwrap", maj_stat, min_stat);
+			return (FALSE);
+		}
+	}
+	/* Decode rpc_gss_data_t (sequence number + arguments). */
+	xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
+	xdr_stat = (xdr_u_int32(&tmpxdrs, &seq_num) &&
+		    (*xdr_func)(&tmpxdrs, xdr_ptr));
+	XDR_DESTROY(&tmpxdrs);
+	gss_release_buffer(&min_stat, &databuf);
+	
+	/* Verify sequence number. */
+	if (xdr_stat == TRUE && seq_num != seq) {
+		log_debug("wrong sequence number in databody");
+		return (FALSE);
+	}
+	return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
+		 gss_ctx_id_t ctx, gss_qop_t qop,
+		 rpc_gss_svc_t svc, uint32_t seq)
+{
+	switch (xdrs->x_op) {
+		
+	case XDR_ENCODE:
+		return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr,
+					      ctx, qop, svc, seq));
+	case XDR_DECODE:
+		return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr,
+						ctx, qop,svc, seq));
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+#ifdef DEBUG
+#include <ctype.h>
+
+void
+log_debug(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fprintf(stderr, "rpcsec_gss: ");
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+void
+log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
+{
+	OM_uint32 min, msg_ctx;
+	gss_buffer_desc msgg, msgm;
+
+	msg_ctx = 0;
+	gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
+			   &msg_ctx, &msgg);
+	msg_ctx = 0;
+	gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID,
+			   &msg_ctx, &msgm);
+
+	log_debug("%s: %.*s - %.*s\n", m,
+		  msgg.length, (char *)msgg.value,
+		  msgm.length, (char *)msgm.value);
+
+	gss_release_buffer(&min, &msgg);
+	gss_release_buffer(&min, &msgm);
+}
+
+void
+log_hexdump(const u_char *buf, int len, int offset)
+{
+	u_int i, j, jm;
+	int c;
+	
+	fprintf(stderr, "\n");
+	for (i = 0; i < len; i += 0x10) {
+		fprintf(stderr, "  %04x: ", (u_int)(i + offset));
+		jm = len - i;
+		jm = jm > 16 ? 16 : jm;
+		
+		for (j = 0; j < jm; j++) {
+			if ((j % 2) == 1)
+				fprintf(stderr, "%02x ", (u_int) buf[i+j]);
+			else
+				fprintf(stderr, "%02x", (u_int) buf[i+j]);
+		}
+		for (; j < 16; j++) {
+			if ((j % 2) == 1) printf("   ");
+			else fprintf(stderr, "  ");
+		}
+		fprintf(stderr, " ");
+		
+		for (j = 0; j < jm; j++) {
+			c = buf[i+j];
+			c = isprint(c) ? c : '.';
+			fprintf(stderr, "%c", c);
+		}
+		fprintf(stderr, "\n");
+	}
+}
+
+#else
+
+void
+log_debug(const char *fmt, ...)
+{
+}
+
+void
+log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
+{
+}
+
+void
+log_hexdump(const u_char *buf, int len, int offset)
+{
+}
+
+#endif
+
+
diff --git a/krb5-1-6/src/lib/rpc/authunix_prot.c b/krb5-1-6/src/lib/rpc/authunix_prot.c
new file mode 100644
index 000000000..7eb47a4b4
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/authunix_prot.c
@@ -0,0 +1,64 @@
+/* @(#)authunix_prot.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * authunix_prot.c
+ * XDR for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <gssrpc/auth.h>
+#include <gssrpc/auth_unix.h>
+
+/*
+ * XDR for unix authentication parameters.
+ */
+bool_t
+xdr_authunix_parms(register XDR *xdrs, register struct authunix_parms *p)
+{
+
+	if (xdr_u_int32(xdrs, &(p->aup_time))
+	    && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
+	    && xdr_int(xdrs, &(p->aup_uid))
+	    && xdr_int(xdrs, &(p->aup_gid))
+	    && xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
+		    &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
diff --git a/krb5-1-6/src/lib/rpc/bindresvport.c b/krb5-1-6/src/lib/rpc/bindresvport.c
new file mode 100644
index 000000000..d1ec65452
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/bindresvport.c
@@ -0,0 +1,83 @@
+#if !defined(lint) && defined(SCCSIDS)
+static  char sccsid[] = "@(#)bindresvport.c	2.2 88/07/29 4.0 RPCSRC 1.8 88/02/08 SMI";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <gssrpc/rpc.h>
+#include <errno.h>
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport(int sd, struct sockaddr_in *sockin)
+{
+	int res;
+	static short port;
+	struct sockaddr_in myaddr;
+	int i;
+
+#define STARTPORT 600
+#define ENDPORT (IPPORT_RESERVED - 1)
+#define NPORTS	(ENDPORT - STARTPORT + 1)
+
+	if (sockin == (struct sockaddr_in *)0) {
+		sockin = &myaddr;
+		memset(sockin, 0, sizeof (*sockin));
+		sockin->sin_family = AF_INET;
+	} else if (sockin->sin_family != AF_INET) {
+		errno = EPFNOSUPPORT;
+		return (-1);
+	}
+	if (port == 0) {
+		port = (getpid() % NPORTS) + STARTPORT;
+	}
+	res = -1;
+	errno = EADDRINUSE;
+	for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) {
+		sockin->sin_port = htons(port++);
+		if (port > ENDPORT) {
+			port = STARTPORT;
+		}
+		res = bind(sd, (struct sockaddr *) sockin,
+			   sizeof(struct sockaddr_in));
+	}
+	return (res);
+}
diff --git a/krb5-1-6/src/lib/rpc/clnt_generic.c b/krb5-1-6/src/lib/rpc/clnt_generic.c
new file mode 100644
index 000000000..07490eeea
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/clnt_generic.c
@@ -0,0 +1,115 @@
+/* @(#)clnt_generic.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";
+#endif
+/*
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <string.h>
+#include <gssrpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <netdb.h>
+#include "autoconf.h"
+
+/*
+ * Generic client creation: takes (hostname, program-number, protocol) and
+ * returns client handle. Default options are set, which the user can 
+ * change using the rpc equivalent of ioctl()'s.
+ */
+CLIENT *
+clnt_create(
+	char *hostname,
+	rpcprog_t prog,
+	rpcvers_t vers,
+	char *proto)
+{
+	struct hostent *h;
+	struct protoent *p;
+	struct sockaddr_in sockin;
+	int sock;
+	struct timeval tv;
+	CLIENT *client;
+
+	h = gethostbyname(hostname);
+	if (h == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+		return (NULL);
+	}
+	if (h->h_addrtype != AF_INET) {
+		/*
+		 * Only support INET for now
+		 */
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = EAFNOSUPPORT; 
+		return (NULL);
+	}
+	memset(&sockin, 0, sizeof(sockin));
+#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+	sockin.sin_len = sizeof(sockin);
+#endif
+	sockin.sin_family = h->h_addrtype;
+	sockin.sin_port = 0;
+	memmove((char*)&sockin.sin_addr, h->h_addr, sizeof(sockin.sin_addr));
+	p = getprotobyname(proto);
+	if (p == NULL) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; 
+		return (NULL);
+	}
+	sock = RPC_ANYSOCK;
+	switch (p->p_proto) {
+	case IPPROTO_UDP:
+		tv.tv_sec = 5;
+		tv.tv_usec = 0;
+		client = clntudp_create(&sockin, prog, vers, tv, &sock);
+		if (client == NULL) {
+			return (NULL);
+		}
+		tv.tv_sec = 25;
+		clnt_control(client, CLSET_TIMEOUT, &tv);
+		break;
+	case IPPROTO_TCP:
+		client = clnttcp_create(&sockin, prog, vers, &sock, 0, 0);
+		if (client == NULL) {
+			return (NULL);
+		}
+		tv.tv_sec = 25;
+		tv.tv_usec = 0;
+		clnt_control(client, CLSET_TIMEOUT, &tv);
+		break;
+	default:
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT; 
+		return (NULL);
+	}
+	return (client);
+}
diff --git a/krb5-1-6/src/lib/rpc/clnt_perror.c b/krb5-1-6/src/lib/rpc/clnt_perror.c
new file mode 100644
index 000000000..85935a8b0
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/clnt_perror.c
@@ -0,0 +1,345 @@
+/* @(#)clnt_perror.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <gssrpc/types.h>
+#include <gssrpc/auth.h>
+#include <gssrpc/clnt.h>
+
+#include "autoconf.h"
+
+#ifndef HAVE_STRERROR
+#ifdef NEED_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+extern int sys_nerr;
+#undef strerror
+#define strerror(N) (((N) > 0 && (N) < sys_nerr) ? sys_errlist[N] : (char *)0)
+#endif /* HAVE_STRERROR */
+static char *auth_errmsg(enum auth_stat);
+
+
+
+static char *buf;
+
+static char *
+get_buf(void)
+{
+	if (buf == NULL)
+		buf = (char *)malloc(BUFSIZ);
+	return (buf);
+}
+
+/*
+ * Print reply error info
+ */
+char *
+clnt_sperror(CLIENT *rpch, char *s)
+{
+	struct rpc_err e;
+	void clnt_perrno();
+	char *err;
+	char *bufstart = get_buf();
+	char *str = bufstart;
+	char *strstart = str;
+
+	if (str == 0)
+		return (0);
+	CLNT_GETERR(rpch, &e);
+
+	strncpy (str, s, BUFSIZ - 1);
+	str[BUFSIZ - 1] = 0;
+	strncat (str, ": ", BUFSIZ - 1 - strlen (bufstart));
+	str += strlen(str);
+	strncat (str, clnt_sperrno(e.re_status), BUFSIZ - 1 - strlen (bufstart));
+	strstart[BUFSIZ - 1] = '\0';
+	str += strlen(str);
+
+	switch (e.re_status) {
+	case RPC_SUCCESS:
+	case RPC_CANTENCODEARGS:
+	case RPC_CANTDECODERES:
+	case RPC_TIMEDOUT:     
+	case RPC_PROGUNAVAIL:
+	case RPC_PROCUNAVAIL:
+	case RPC_CANTDECODEARGS:
+	case RPC_SYSTEMERROR:
+	case RPC_UNKNOWNHOST:
+	case RPC_UNKNOWNPROTO:
+	case RPC_PMAPFAILURE:
+	case RPC_PROGNOTREGISTERED:
+	case RPC_FAILED:
+		break;
+
+	case RPC_CANTSEND:
+	case RPC_CANTRECV:
+		/* 10 for the string */
+		if(str - bufstart + 10 + strlen(strerror(e.re_errno)) < BUFSIZ)
+		    (void) sprintf(str, "; errno = %s",
+				   strerror(e.re_errno)); 
+		str += strlen(str);
+		break;
+
+	case RPC_VERSMISMATCH:
+		/* 33 for the string, 22 for the numbers */
+		if(str - bufstart + 33 + 22 < BUFSIZ)
+		    (void) sprintf(str,
+				   "; low version = %lu, high version = %lu", 
+				   (u_long) e.re_vers.low,
+				   (u_long) e.re_vers.high);
+		str += strlen(str);
+		break;
+
+	case RPC_AUTHERROR:
+		err = auth_errmsg(e.re_why);
+		/* 8 for the string */
+		if(str - bufstart + 8 < BUFSIZ)
+		    (void) sprintf(str,"; why = ");
+		str += strlen(str);
+		if (err != NULL) {
+			if(str - bufstart + strlen(err) < BUFSIZ)
+			    (void) sprintf(str, "%s",err);
+		} else {
+		    /* 33 for the string, 11 for the number */
+		    if(str - bufstart + 33 + 11 < BUFSIZ)
+			(void) sprintf(str,
+				       "(unknown authentication error - %d)",
+				       (int) e.re_why);
+		}
+		str += strlen(str);
+		break;
+
+	case RPC_PROGVERSMISMATCH:
+		/* 33 for the string, 22 for the numbers */
+		if(str - bufstart + 33 + 22 < BUFSIZ)
+		    (void) sprintf(str,
+				   "; low version = %lu, high version = %lu",
+				   (u_long) e.re_vers.low,
+				   (u_long) e.re_vers.high);
+		str += strlen(str);
+		break;
+
+	default:	/* unknown */
+		/* 14 for the string, 22 for the numbers */
+		if(str - bufstart + 14 + 22 < BUFSIZ)
+		    (void) sprintf(str,
+				   "; s1 = %lu, s2 = %lu",
+				   (u_long) e.re_lb.s1,
+				   (u_long) e.re_lb.s2);
+		str += strlen(str);
+		break;
+	}
+	if(str - bufstart + 1 < BUFSIZ)
+	    (void) sprintf(str, "\n");
+	return(strstart) ;
+}
+
+void
+clnt_perror(CLIENT *rpch, char *s)
+{
+	(void) fprintf(stderr,"%s",clnt_sperror(rpch,s));
+}
+
+
+struct rpc_errtab {
+	enum clnt_stat status;
+	char *message;
+};
+
+static struct rpc_errtab  rpc_errlist[] = {
+	{ RPC_SUCCESS, 
+		"RPC: Success" }, 
+	{ RPC_CANTENCODEARGS, 
+		"RPC: Can't encode arguments" },
+	{ RPC_CANTDECODERES, 
+		"RPC: Can't decode result" },
+	{ RPC_CANTSEND, 
+		"RPC: Unable to send" },
+	{ RPC_CANTRECV, 
+		"RPC: Unable to receive" },
+	{ RPC_TIMEDOUT, 
+		"RPC: Timed out" },
+	{ RPC_VERSMISMATCH, 
+		"RPC: Incompatible versions of RPC" },
+	{ RPC_AUTHERROR, 
+		"RPC: Authentication error" },
+	{ RPC_PROGUNAVAIL, 
+		"RPC: Program unavailable" },
+	{ RPC_PROGVERSMISMATCH, 
+		"RPC: Program/version mismatch" },
+	{ RPC_PROCUNAVAIL, 
+		"RPC: Procedure unavailable" },
+	{ RPC_CANTDECODEARGS, 
+		"RPC: Server can't decode arguments" },
+	{ RPC_SYSTEMERROR, 
+		"RPC: Remote system error" },
+	{ RPC_UNKNOWNHOST, 
+		"RPC: Unknown host" },
+	{ RPC_UNKNOWNPROTO,
+		"RPC: Unknown protocol" },
+	{ RPC_PMAPFAILURE, 
+		"RPC: Port mapper failure" },
+	{ RPC_PROGNOTREGISTERED, 
+		"RPC: Program not registered"},
+	{ RPC_FAILED, 
+		"RPC: Failed (unspecified error)"}
+};
+
+
+/*
+ * This interface for use by clntrpc
+ */
+char *
+clnt_sperrno(enum clnt_stat stat)
+{
+	int i;
+
+	for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) {
+		if (rpc_errlist[i].status == stat) {
+			return (rpc_errlist[i].message);
+		}
+	}
+	return ("RPC: (unknown error code)");
+}
+
+void
+clnt_perrno(enum clnt_stat num)
+{
+	(void) fprintf(stderr,"%s",clnt_sperrno(num));
+}
+
+
+char *
+clnt_spcreateerror(char *s)
+{
+	char *str = get_buf();
+
+	if (str == 0)
+		return(0);
+	(void) sprintf(str, "%s: ", s);
+	str[BUFSIZ - 1] = '\0';
+	(void) strncat(str, clnt_sperrno(rpc_createerr.cf_stat), BUFSIZ - 1);
+	switch (rpc_createerr.cf_stat) {
+	case RPC_PMAPFAILURE:
+		(void) strncat(str, " - ", BUFSIZ - 1 - strlen(str));
+		(void) strncat(str,
+		    clnt_sperrno(rpc_createerr.cf_error.re_status),
+		    BUFSIZ - 1 - strlen(str));
+		break;
+
+	case RPC_SYSTEMERROR:
+		(void) strncat(str, " - ", BUFSIZ - 1 - strlen(str));
+		{
+		    const char *m = strerror(rpc_createerr.cf_error.re_errno);
+		    if (m)
+			(void) strncat(str, m, BUFSIZ - 1 - strlen(str));
+		    else
+			(void) sprintf(&str[strlen(str)], "Error %d",
+				       rpc_createerr.cf_error.re_errno);
+		}
+		break;
+
+	case RPC_CANTSEND:
+	case RPC_CANTDECODERES:
+	case RPC_CANTENCODEARGS:
+	case RPC_SUCCESS:
+	case RPC_UNKNOWNPROTO:
+	case RPC_PROGNOTREGISTERED:
+	case RPC_FAILED:
+	case RPC_UNKNOWNHOST:
+	case RPC_CANTDECODEARGS:
+	case RPC_PROCUNAVAIL:
+	case RPC_PROGVERSMISMATCH:
+	case RPC_PROGUNAVAIL:
+	case RPC_AUTHERROR:
+	case RPC_VERSMISMATCH:
+	case RPC_TIMEDOUT:
+	case RPC_CANTRECV:
+	default:
+	    break;
+	}
+	(void) strncat(str, "\n", BUFSIZ - 1 - strlen(str));
+	return (str);
+}
+
+void
+clnt_pcreateerror(char *s)
+{
+	(void) fprintf(stderr,"%s",clnt_spcreateerror(s));
+}
+
+struct auth_errtab {
+	enum auth_stat status;	
+	char *message;
+};
+
+static struct auth_errtab auth_errlist[] = {
+	{ AUTH_OK,
+		"Authentication OK" },
+	{ AUTH_BADCRED,
+		"Invalid client credential" },
+	{ AUTH_REJECTEDCRED,
+		"Server rejected credential" },
+	{ AUTH_BADVERF,
+		"Invalid client verifier" },
+	{ AUTH_REJECTEDVERF,
+		"Server rejected verifier" },
+	{ AUTH_TOOWEAK,
+		"Client credential too weak" },
+	{ AUTH_INVALIDRESP,
+		"Invalid server verifier" },
+	{ AUTH_FAILED,
+		"Failed (unspecified error)" },
+};
+
+static char *
+auth_errmsg(enum auth_stat stat)
+{
+	int i;
+
+	for (i = 0; i < sizeof(auth_errlist)/sizeof(struct auth_errtab); i++) {
+		if (auth_errlist[i].status == stat) {
+			return(auth_errlist[i].message);
+		}
+	}
+	return(NULL);
+}
diff --git a/krb5-1-6/src/lib/rpc/clnt_raw.c b/krb5-1-6/src/lib/rpc/clnt_raw.c
new file mode 100644
index 000000000..06b078e99
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/clnt_raw.c
@@ -0,0 +1,268 @@
+/* @(#)clnt_raw.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_raw.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Memory based rpc for simple testing and timing.
+ * Interface to create an rpc client and server in the same process.
+ * This lets us similate rpc and get round trip overhead, without
+ * any interference from the kernal.
+ */
+
+#include <gssrpc/rpc.h>
+
+#define MCALL_MSG_SIZE 24
+
+/*
+ * This is the "network" we will be moving stuff over.
+ */
+static struct clntraw_private {
+	CLIENT	client_object;
+	XDR	xdr_stream;
+	char	_raw_buf[UDPMSGSIZE];
+        union {
+	  struct rpc_msg    mashl_rpcmsg;
+	  char	            mashl_callmsg[MCALL_MSG_SIZE];
+	} u;
+	u_int	mcnt;
+} *clntraw_private;
+
+static enum clnt_stat	clntraw_call(CLIENT *, rpcproc_t, xdrproc_t, 
+				     void *, xdrproc_t, void *, 
+				     struct timeval);
+static void		clntraw_abort(CLIENT *);
+static void		clntraw_geterr(CLIENT *, struct rpc_err *);
+static bool_t		clntraw_freeres(CLIENT *, xdrproc_t, void *);
+static bool_t		clntraw_control(CLIENT *, int, void *);
+static void		clntraw_destroy(CLIENT *);
+
+static struct clnt_ops client_ops = {
+	clntraw_call,
+	clntraw_abort,
+	clntraw_geterr,
+	clntraw_freeres,
+	clntraw_destroy,
+	clntraw_control
+};
+
+void	svc_getreq();
+
+/*
+ * Create a client handle for memory based rpc.
+ */
+CLIENT *
+clntraw_create(
+	rpcprog_t prog,
+	rpcvers_t vers)
+{
+	register struct clntraw_private *clp = clntraw_private;
+	struct rpc_msg call_msg;
+	XDR *xdrs = &clp->xdr_stream;
+	CLIENT	*client = &clp->client_object;
+
+	if (clp == 0) {
+		clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
+		if (clp == 0)
+			return (0);
+		clntraw_private = clp;
+	}
+	/*
+	 * pre-serialize the staic part of the call msg and stash it away
+	 */
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = prog;
+	call_msg.rm_call.cb_vers = vers;
+	xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); 
+	if (! xdr_callhdr(xdrs, &call_msg)) {
+		perror("clnt_raw.c - Fatal header serialization error.");
+	}
+	clp->mcnt = XDR_GETPOS(xdrs);
+	XDR_DESTROY(xdrs);
+
+	/*
+	 * Set xdrmem for client/server shared buffer
+	 */
+	xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+
+	/*
+	 * create client handle
+	 */
+	client->cl_ops = &client_ops;
+	client->cl_auth = authnone_create();
+	return (client);
+}
+
+static enum clnt_stat 
+clntraw_call(
+	CLIENT *h,
+	rpcproc_t proc,
+	xdrproc_t xargs,
+	void * argsp,
+	xdrproc_t xresults,
+	void * resultsp,
+	struct timeval timeout)
+{
+	register struct clntraw_private *clp = clntraw_private;
+	register XDR *xdrs = &clp->xdr_stream;
+	struct rpc_msg msg;
+	enum clnt_stat status;
+	struct rpc_err error;
+	long procl = proc;
+
+	if (clp == 0)
+		return (RPC_FAILED);
+call_again:
+	/*
+	 * send request
+	 */
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, 0);
+	clp->u.mashl_rpcmsg.rm_xid ++ ;
+	if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
+	    (! XDR_PUTLONG(xdrs, &procl)) ||
+	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+	    (! (*xargs)(xdrs, argsp))) {
+		return (RPC_CANTENCODEARGS);
+	}
+	(void)XDR_GETPOS(xdrs);  /* called just to cause overhead */
+
+	/*
+	 * We have to call server input routine here because this is
+	 * all going on in one process. Yuk.
+	 */
+	svc_getreq(1);
+
+	/*
+	 * get results
+	 */
+	xdrs->x_op = XDR_DECODE;
+	XDR_SETPOS(xdrs, 0);
+	msg.acpted_rply.ar_verf = gssrpc__null_auth;
+	msg.acpted_rply.ar_results.where = resultsp;
+	msg.acpted_rply.ar_results.proc = xresults;
+	if (! xdr_replymsg(xdrs, &msg)) {
+		/*
+		 * It's possible for xdr_replymsg() to fail partway
+		 * through its attempt to decode the result from the
+		 * server. If this happens, it will leave the reply
+		 * structure partially populated with dynamically
+		 * allocated memory. (This can happen if someone uses
+		 * clntudp_bufcreate() to create a CLIENT handle and
+		 * specifies a receive buffer size that is too small.)
+		 * This memory must be free()ed to avoid a leak.
+		 */
+		enum xdr_op op = xdrs->x_op;
+		xdrs->x_op = XDR_FREE;
+		xdr_replymsg(xdrs, &msg);
+		xdrs->x_op = op;
+		return (RPC_CANTDECODERES);
+	}
+	gssrpc__seterr_reply(&msg, &error);
+	status = error.re_status;
+
+	if (status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+			status = RPC_AUTHERROR;
+		}
+	}  /* end successful completion */
+	else {
+		if (AUTH_REFRESH(h->cl_auth, &msg))
+			goto call_again;
+	}  /* end of unsuccessful completion */
+
+	if (status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+			status = RPC_AUTHERROR;
+		}
+		if (msg.acpted_rply.ar_verf.oa_base != NULL) {
+			xdrs->x_op = XDR_FREE;
+			(void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
+		}
+	}
+
+	return (status);
+}
+
+/*ARGSUSED*/
+static void
+clntraw_geterr(
+	CLIENT *cl,
+	struct rpc_err *err)
+{
+}
+
+
+static bool_t
+clntraw_freeres(
+	CLIENT *cl,
+	xdrproc_t xdr_res,
+	void *res_ptr)
+{
+	register struct clntraw_private *clp = clntraw_private;
+	register XDR *xdrs = &clp->xdr_stream;
+	bool_t rval;
+
+	if (clp == 0)
+	{
+		rval = (bool_t) RPC_FAILED;
+		return (rval);
+	}
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/*ARGSUSED*/
+static void
+clntraw_abort(CLIENT *cl)
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+clntraw_control(
+	CLIENT *cl,
+	int request,
+	void *info)
+{
+	return (FALSE);
+}
+
+/*ARGSUSED*/
+static void
+clntraw_destroy(CLIENT *cl)
+{
+}
diff --git a/krb5-1-6/src/lib/rpc/clnt_simple.c b/krb5-1-6/src/lib/rpc/clnt_simple.c
new file mode 100644
index 000000000..d2434a13c
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/clnt_simple.c
@@ -0,0 +1,129 @@
+/* @(#)clnt_simple.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/* 
+ * clnt_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+/* for close() */
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include "autoconf.h"
+
+static struct callrpc_private {
+	CLIENT	*client;
+	int	socket;
+	int	oldprognum, oldversnum, valid;
+	char	*oldhost;
+} *callrpc_private;
+
+int
+callrpc(
+	char *host,
+	rpcprog_t prognum,
+	rpcvers_t versnum,
+	rpcproc_t procnum,
+	xdrproc_t inproc,
+	char *in,
+	xdrproc_t outproc,
+	char *out)
+{
+	register struct callrpc_private *crp = callrpc_private;
+	struct sockaddr_in server_addr;
+	enum clnt_stat clnt_stat;
+	struct hostent *hp;
+	struct timeval timeout, tottimeout;
+
+	if (crp == 0) {
+		crp = (struct callrpc_private *)calloc(1, sizeof (*crp));
+		if (crp == 0)
+			return (0);
+		callrpc_private = crp;
+	}
+	if (crp->oldhost == NULL) {
+		crp->oldhost = mem_alloc(256);
+		if (crp->oldhost == 0)
+		    return 0;
+		crp->oldhost[0] = 0;
+		crp->socket = RPC_ANYSOCK;
+	}
+	if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
+		&& strcmp(crp->oldhost, host) == 0) {
+		/* reuse old client */		
+	} else {
+		crp->valid = 0;
+		(void)close(crp->socket);
+		crp->socket = RPC_ANYSOCK;
+		if (crp->client) {
+			clnt_destroy(crp->client);
+			crp->client = NULL;
+		}
+		if ((hp = gethostbyname(host)) == NULL)
+			return ((int) RPC_UNKNOWNHOST);
+		timeout.tv_usec = 0;
+		timeout.tv_sec = 5;
+		memset(&server_addr, 0, sizeof(server_addr));
+		memmove((char *)&server_addr.sin_addr, hp->h_addr, 
+			sizeof(server_addr.sin_addr));
+#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+		server_addr.sin_len = sizeof(server_addr);
+#endif
+		server_addr.sin_family = AF_INET;
+		server_addr.sin_port =  0;
+		if ((crp->client = clntudp_create(&server_addr, prognum,
+		    versnum, timeout, &crp->socket)) == NULL)
+			return ((int) rpc_createerr.cf_stat);
+		crp->valid = 1;
+		crp->oldprognum = prognum;
+		crp->oldversnum = versnum;
+		(void) strncpy(crp->oldhost, host, 255);
+		crp->oldhost[255] = '\0';
+	}
+	tottimeout.tv_sec = 25;
+	tottimeout.tv_usec = 0;
+	clnt_stat = clnt_call(crp->client, procnum, inproc, in,
+	    outproc, out, tottimeout);
+	/* 
+	 * if call failed, empty cache
+	 */
+	if (clnt_stat != RPC_SUCCESS)
+		crp->valid = 0;
+	return ((int) clnt_stat);
+}
diff --git a/krb5-1-6/src/lib/rpc/clnt_tcp.c b/krb5-1-6/src/lib/rpc/clnt_tcp.c
new file mode 100644
index 000000000..1f8de8276
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/clnt_tcp.c
@@ -0,0 +1,496 @@
+/* @(#)clnt_tcp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+#endif
+ 
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer.  The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message.  Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <gssrpc/pmap_clnt.h>
+/* FD_ZERO may need memset declaration (e.g., Solaris 9) */
+#include <string.h>
+
+#define MCALL_MSG_SIZE 24
+
+static enum clnt_stat	clnttcp_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+				     xdrproc_t, void *, struct timeval);
+static void		clnttcp_abort(CLIENT *);
+static void		clnttcp_geterr(CLIENT *, struct rpc_err *);
+static bool_t		clnttcp_freeres(CLIENT *, xdrproc_t, void *);
+static bool_t           clnttcp_control(CLIENT *, int, void *);
+static void		clnttcp_destroy(CLIENT *);
+
+static struct clnt_ops tcp_ops = {
+	clnttcp_call,
+	clnttcp_abort,
+	clnttcp_geterr,
+	clnttcp_freeres,
+	clnttcp_destroy,
+	clnttcp_control
+};
+
+struct ct_data {
+	int		ct_sock;
+	bool_t		ct_closeit;
+	struct timeval	ct_wait;
+	bool_t          ct_waitset;       /* wait set by clnt_control? */
+	struct sockaddr_in ct_addr; 
+	struct rpc_err	ct_error;
+	union {
+	  char		ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */
+	  uint32_t   ct_mcalli;
+	} ct_u;
+	u_int		ct_mpos;			/* pos after marshal */
+	XDR		ct_xdrs;
+};
+
+static int	readtcp(char *, caddr_t, int);
+static int	writetcp(char *, caddr_t, int);
+
+
+/*
+ * Create a client handle for a tcp/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr.  If *sockp non-negative then
+ * raddr is ignored.  The rpc/tcp package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clnttcp_create(
+	struct sockaddr_in *raddr,
+	rpcprog_t prog,
+	rpcvers_t vers,
+	register int *sockp,
+	u_int sendsz,
+	u_int recvsz)
+{
+	CLIENT *h;
+	register struct ct_data *ct = 0;
+	struct timeval now;
+	struct rpc_msg call_msg;
+
+	h  = (CLIENT *)mem_alloc(sizeof(*h));
+	if (h == NULL) {
+		(void)fprintf(stderr, "clnttcp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	ct = (struct ct_data *)mem_alloc(sizeof(*ct));
+	if (ct == NULL) {
+		(void)fprintf(stderr, "clnttcp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+
+	/*
+	 * If no port number given ask the pmap for one
+	 */
+	if (raddr->sin_port == 0) {
+		u_short port;
+		if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
+			mem_free((caddr_t)ct, sizeof(struct ct_data));
+			mem_free((caddr_t)h, sizeof(CLIENT));
+			return ((CLIENT *)NULL);
+		}
+		raddr->sin_port = htons(port);
+	}
+
+	/*
+	 * If no socket given, open one
+	 */
+	if (*sockp < 0) {
+		*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		(void)bindresvport(*sockp, (struct sockaddr_in *)0);
+		if ((*sockp < 0)
+		    || (connect(*sockp, (struct sockaddr *)raddr,
+		    sizeof(*raddr)) < 0)) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			(void)close(*sockp);
+			goto fooy;
+		}
+		ct->ct_closeit = TRUE;
+	} else {
+		ct->ct_closeit = FALSE;
+	}
+
+	/*
+	 * Set up private data struct
+	 */
+	ct->ct_sock = *sockp;
+	ct->ct_wait.tv_usec = 0;
+	ct->ct_waitset = FALSE;
+	ct->ct_addr = *raddr;
+
+	/*
+	 * Initialize call message
+	 */
+	(void)gettimeofday(&now, (struct timezone *)0);
+	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = prog;
+	call_msg.rm_call.cb_vers = vers;
+
+	/*
+	 * pre-serialize the staic part of the call msg and stash it away
+	 */
+	xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcall, MCALL_MSG_SIZE,
+	    XDR_ENCODE);
+	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+		if (ct->ct_closeit) {
+			(void)close(*sockp);
+		}
+		goto fooy;
+	}
+	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+	XDR_DESTROY(&(ct->ct_xdrs));
+
+	/*
+	 * Create a client handle which uses xdrrec for serialization
+	 * and authnone for authentication.
+	 */
+	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+	    (caddr_t)ct, readtcp, writetcp);
+	h->cl_ops = &tcp_ops;
+	h->cl_private = (caddr_t) ct;
+	h->cl_auth = authnone_create();
+	return (h);
+
+fooy:
+	/*
+	 * Something goofed, free stuff and barf
+	 */
+	mem_free((caddr_t)ct, sizeof(struct ct_data));
+	mem_free((caddr_t)h, sizeof(CLIENT));
+	return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnttcp_call(
+	register CLIENT *h,
+	rpcproc_t proc,
+	xdrproc_t xdr_args,
+	void * args_ptr,
+	xdrproc_t xdr_results,
+	void * results_ptr,
+	struct timeval timeout)
+{
+	register struct ct_data *ct = (struct ct_data *) h->cl_private;
+	register XDR *xdrs = &(ct->ct_xdrs);
+	struct rpc_msg reply_msg;
+	uint32_t x_id;
+	uint32_t *msg_x_id = &ct->ct_u.ct_mcalli;	/* yuk */
+	register bool_t shipnow;
+	int refreshes = 2;
+	long procl = proc;
+
+	if (!ct->ct_waitset) {
+		ct->ct_wait = timeout;
+	}
+
+	shipnow =
+	    (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
+	    && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+	xdrs->x_op = XDR_ENCODE;
+	ct->ct_error.re_status = RPC_SUCCESS;
+	x_id = ntohl(--(*msg_x_id));
+	if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcall, ct->ct_mpos)) ||
+	    (! XDR_PUTLONG(xdrs, &procl)) ||
+	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+	    (! AUTH_WRAP(h->cl_auth, xdrs, xdr_args, args_ptr))) {
+		if (ct->ct_error.re_status == RPC_SUCCESS)
+			ct->ct_error.re_status = RPC_CANTENCODEARGS;
+		(void)xdrrec_endofrecord(xdrs, TRUE);
+		return (ct->ct_error.re_status);
+	}
+	if (! xdrrec_endofrecord(xdrs, shipnow))
+		return (ct->ct_error.re_status = RPC_CANTSEND);
+	if (! shipnow)
+		return (RPC_SUCCESS);
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+		return(ct->ct_error.re_status = RPC_TIMEDOUT);
+	}
+
+
+	/*
+	 * Keep receiving until we get a valid transaction id
+	 */
+	xdrs->x_op = XDR_DECODE;
+	while (TRUE) {
+		reply_msg.acpted_rply.ar_verf = gssrpc__null_auth;
+		reply_msg.acpted_rply.ar_results.where = NULL;
+		reply_msg.acpted_rply.ar_results.proc = xdr_void;
+		if (! xdrrec_skiprecord(xdrs))
+			return (ct->ct_error.re_status);
+		/* now decode and validate the response header */
+		if (! xdr_replymsg(xdrs, &reply_msg)) {
+			/*
+			 * Free some stuff allocated by xdr_replymsg()
+			 * to avoid leaks, since it may allocate
+			 * memory from partially successful decodes.
+			 */
+			enum xdr_op op = xdrs->x_op;
+			xdrs->x_op = XDR_FREE;
+			xdr_replymsg(xdrs, &reply_msg);
+			xdrs->x_op = op;
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				continue;
+			return (ct->ct_error.re_status);
+		}
+		if (reply_msg.rm_xid == x_id)
+			break;
+	}
+
+	/*
+	 * process header
+	 */
+	gssrpc__seterr_reply(&reply_msg, &(ct->ct_error));
+	if (ct->ct_error.re_status == RPC_SUCCESS) {
+		if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
+			ct->ct_error.re_status = RPC_AUTHERROR;
+			ct->ct_error.re_why = AUTH_INVALIDRESP;
+		} else if (! AUTH_UNWRAP(h->cl_auth, xdrs,
+					 xdr_results, results_ptr)) {
+			if (ct->ct_error.re_status == RPC_SUCCESS)
+				ct->ct_error.re_status = RPC_CANTDECODERES;
+		}
+	}  /* end successful completion */
+	else {
+		/* maybe our credentials need to be refreshed ... */
+		if (refreshes-- && AUTH_REFRESH(h->cl_auth, &reply_msg))
+			goto call_again;
+	}  /* end of unsuccessful completion */
+	/* free verifier ... */
+	if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+	    (reply_msg.acpted_rply.ar_verf.oa_base != NULL)) {
+	    xdrs->x_op = XDR_FREE;
+	    (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
+	}
+	return (ct->ct_error.re_status);
+}
+
+static void
+clnttcp_geterr(
+	CLIENT *h,
+	struct rpc_err *errp)
+{
+	register struct ct_data *ct =
+	    (struct ct_data *) h->cl_private;
+
+	*errp = ct->ct_error;
+}
+
+static bool_t
+clnttcp_freeres(
+	CLIENT *cl,
+	xdrproc_t xdr_res,
+	void * res_ptr)
+{
+	register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+	register XDR *xdrs = &(ct->ct_xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/*ARGSUSED*/
+static void
+clnttcp_abort(CLIENT *cl)
+{
+}
+
+static bool_t
+clnttcp_control(
+	CLIENT *cl,
+	int request,
+	void *info)
+{
+	register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+	int len;
+	
+	switch (request) {
+	case CLSET_TIMEOUT:
+		ct->ct_wait = *(struct timeval *)info;
+		ct->ct_waitset = TRUE;
+		break;
+	case CLGET_TIMEOUT:
+		*(struct timeval *)info = ct->ct_wait;
+		break;
+	case CLGET_SERVER_ADDR:
+		*(struct sockaddr_in *)info = ct->ct_addr;
+		break;
+	case CLGET_LOCAL_ADDR:
+		len = sizeof(struct sockaddr);
+		if (getsockname(ct->ct_sock, (struct sockaddr*)info, &len) < 0)
+		     return FALSE;
+		else
+		     return TRUE;
+	default:
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+
+static void
+clnttcp_destroy(CLIENT *h)
+{
+	register struct ct_data *ct =
+	    (struct ct_data *) h->cl_private;
+
+	if (ct->ct_closeit) {
+		(void)close(ct->ct_sock);
+	}
+	XDR_DESTROY(&(ct->ct_xdrs));
+	mem_free((caddr_t)ct, sizeof(struct ct_data));
+	mem_free((caddr_t)h, sizeof(CLIENT));
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readtcp(
+        char *ctptr,
+	caddr_t buf,
+	register int len)
+{
+  register struct ct_data *ct = (struct ct_data *)(void *)ctptr;
+  struct timeval tout;
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+
+	if (len == 0)
+		return (0);
+	FD_ZERO(&mask);
+	FD_SET(ct->ct_sock, &mask);
+#else
+	register int mask = 1 << (ct->ct_sock);
+	int readfds;
+
+	if (len == 0)
+		return (0);
+
+#endif /* def FD_SETSIZE */
+	while (TRUE) {
+		readfds = mask;
+		tout = ct->ct_wait;
+		switch (select(gssrpc__rpc_dtablesize(), &readfds, (fd_set*)NULL, (fd_set*)NULL,
+			       &tout)) {
+		case 0:
+			ct->ct_error.re_status = RPC_TIMEDOUT;
+			return (-1);
+
+		case -1:
+			if (errno == EINTR)
+				continue;
+			ct->ct_error.re_status = RPC_CANTRECV;
+			ct->ct_error.re_errno = errno;
+			return (-1);
+		}
+		break;
+	}
+	switch (len = read(ct->ct_sock, buf, (size_t) len)) {
+
+	case 0:
+		/* premature eof */
+		ct->ct_error.re_errno = ECONNRESET;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		len = -1;  /* it's really an error */
+		break;
+
+	case -1:
+		ct->ct_error.re_errno = errno;
+		ct->ct_error.re_status = RPC_CANTRECV;
+		break;
+	}
+	return (len);
+}
+
+static int
+writetcp(
+        char *ctptr,
+	caddr_t buf,
+	int len)
+{
+	struct ct_data *ct = (struct ct_data *)(void *)ctptr;
+	register int i, cnt;
+
+	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+		if ((i = write(ct->ct_sock, buf, (size_t) cnt)) == -1) {
+			ct->ct_error.re_errno = errno;
+			ct->ct_error.re_status = RPC_CANTSEND;
+			return (-1);
+		}
+	}
+	return (len);
+}
diff --git a/krb5-1-6/src/lib/rpc/clnt_udp.c b/krb5-1-6/src/lib/rpc/clnt_udp.c
new file mode 100644
index 000000000..a8b59563f
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/clnt_udp.c
@@ -0,0 +1,484 @@
+/* @(#)clnt_udp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_udp.c, Implements a UDP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#if defined(sun)
+#include <sys/filio.h>
+#endif
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <gssrpc/pmap_clnt.h>
+#include <errno.h>
+
+
+/*
+ * UDP bases client side rpc operations
+ */
+static enum clnt_stat	clntudp_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+				     xdrproc_t, void *, struct timeval);
+static void		clntudp_abort(CLIENT *);
+static void		clntudp_geterr(CLIENT *, struct rpc_err *);
+static bool_t		clntudp_freeres(CLIENT *, xdrproc_t, void *);
+static bool_t           clntudp_control(CLIENT *, int, void *);
+static void		clntudp_destroy(CLIENT *);
+
+static struct clnt_ops udp_ops = {
+	clntudp_call,
+	clntudp_abort,
+	clntudp_geterr,
+	clntudp_freeres,
+	clntudp_destroy,
+	clntudp_control
+};
+
+/* 
+ * Private data kept per client handle
+ */
+struct cu_data {
+	int		   cu_sock;
+	bool_t		   cu_closeit;
+	struct sockaddr_in cu_raddr;
+	int		   cu_rlen;
+	struct sockaddr_in cu_laddr;
+	int		   cu_llen;
+	struct timeval	   cu_wait;
+	struct timeval     cu_total;
+	struct rpc_err	   cu_error;
+	XDR		   cu_outxdrs;
+	u_int		   cu_xdrpos;
+	u_int		   cu_sendsz;
+	char		   *cu_outbuf;
+	u_int		   cu_recvsz;
+	char		   cu_inbuf[1];
+};
+
+/*
+ * Create a UDP based client handle.
+ * If *sockp<0, *sockp is set to a newly created UPD socket.
+ * If raddr->sin_port is 0 a binder on the remote machine
+ * is consulted for the correct port number.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ *     Caller may wish to set this something more useful.
+ *
+ * wait is the amount of time used between retransmitting a call if
+ * no response has been heard;  retransmition occurs until the actual
+ * rpc call times out.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received.
+ */
+CLIENT *
+clntudp_bufcreate(
+	struct sockaddr_in *raddr,
+	rpcprog_t program,
+	rpcvers_t version,
+	struct timeval wait,
+	register int *sockp,
+	u_int sendsz,
+	u_int recvsz)
+{
+	CLIENT *cl;
+	register struct cu_data *cu = 0;
+	struct timeval now;
+	struct rpc_msg call_msg;
+
+	cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
+	if (cl == NULL) {
+		(void) fprintf(stderr, "clntudp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	sendsz = ((sendsz + 3) / 4) * 4;
+	recvsz = ((recvsz + 3) / 4) * 4;
+	cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
+	if (cu == NULL) {
+		(void) fprintf(stderr, "clntudp_create: out of memory\n");
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		goto fooy;
+	}
+	cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+
+	(void)gettimeofday(&now, (struct timezone *)0);
+	if (raddr->sin_port == 0) {
+		u_short port;
+		if ((port =
+		    pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
+			goto fooy;
+		}
+		raddr->sin_port = htons(port);
+	}
+	cl->cl_ops = &udp_ops;
+	cl->cl_private = (caddr_t)cu;
+	cu->cu_raddr = *raddr;
+	cu->cu_rlen = sizeof (cu->cu_raddr);
+	cu->cu_wait = wait;
+	cu->cu_total.tv_sec = -1;
+	cu->cu_total.tv_usec = -1;
+	cu->cu_sendsz = sendsz;
+	cu->cu_recvsz = recvsz;
+	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+	call_msg.rm_direction = CALL;
+	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	call_msg.rm_call.cb_prog = program;
+	call_msg.rm_call.cb_vers = version;
+	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
+	    sendsz, XDR_ENCODE);
+	if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
+		goto fooy;
+	}
+	cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+	if (*sockp < 0) {
+		int dontblock = 1;
+
+		*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+		if (*sockp < 0) {
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+			rpc_createerr.cf_error.re_errno = errno;
+			goto fooy;
+		}
+		/* attempt to bind to prov port */
+		(void)bindresvport(*sockp, (struct sockaddr_in *)0);
+		/* the sockets rpc controls are non-blocking */
+		(void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
+		cu->cu_closeit = TRUE;
+	} else {
+		cu->cu_closeit = FALSE;
+	}
+	if (connect(*sockp, (struct sockaddr *)raddr, sizeof(*raddr)) < 0)
+	     goto fooy;
+	     cu->cu_llen = sizeof(cu->cu_laddr);
+	if (getsockname(*sockp, (struct sockaddr *)&cu->cu_laddr, &cu->cu_llen) < 0)
+	     goto fooy;
+	
+	cu->cu_sock = *sockp;
+	cl->cl_auth = authnone_create();
+	return (cl);
+fooy:
+	if (cu)
+		mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
+	if (cl)
+		mem_free((caddr_t)cl, sizeof(CLIENT));
+	return ((CLIENT *)NULL);
+}
+
+CLIENT *
+clntudp_create(
+	struct sockaddr_in *raddr,
+	rpcprog_t program,
+	rpcvers_t version,
+	struct timeval wait,
+	register int *sockp)
+{
+
+	return(clntudp_bufcreate(raddr, program, version, wait, sockp,
+	    UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum clnt_stat 
+clntudp_call(
+	register CLIENT	*cl,		/* client handle */
+	rpcproc_t	proc,		/* procedure number */
+	xdrproc_t	xargs,		/* xdr routine for args */
+	void *		argsp,		/* pointer to args */
+	xdrproc_t	xresults,	/* xdr routine for results */
+	void *		resultsp,	/* pointer to results */
+	struct timeval	utimeout	/* seconds to wait before
+					 * giving up */
+	)
+{
+	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	register XDR *xdrs;
+	register int outlen;
+	register int inlen;
+	int fromlen;
+#ifdef FD_SETSIZE
+	fd_set readfds;
+	fd_set mask;
+#else
+	int readfds;
+	register int mask;
+#endif /* def FD_SETSIZE */
+	struct sockaddr_in from;
+	struct rpc_msg reply_msg;
+	XDR reply_xdrs;
+	struct timeval time_waited, seltimeout;
+	bool_t ok;
+	int nrefreshes = 2;	/* number of times to refresh cred */
+	struct timeval timeout;
+	long procl = proc;
+
+	if (cu->cu_total.tv_usec == -1) {
+		timeout = utimeout;     /* use supplied timeout */
+	} else {
+		timeout = cu->cu_total; /* use default timeout */
+	}
+
+	time_waited.tv_sec = 0;
+	time_waited.tv_usec = 0;
+call_again:
+	xdrs = &(cu->cu_outxdrs);
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, cu->cu_xdrpos);
+	/*
+	 * the transaction is the first thing in the out buffer
+	 */
+	(*(uint32_t *)(void *)(cu->cu_outbuf))++;
+	if ((! XDR_PUTLONG(xdrs, &procl)) ||
+	    (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+	    (! AUTH_WRAP(cl->cl_auth, xdrs, xargs, argsp)))
+		return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+	outlen = (int)XDR_GETPOS(xdrs);
+
+send_again:
+	if (send(cu->cu_sock, cu->cu_outbuf, (u_int)outlen, 0) != outlen) {
+		cu->cu_error.re_errno = errno;
+		return (cu->cu_error.re_status = RPC_CANTSEND);
+	}
+
+	/*
+	 * Hack to provide rpc-based message passing
+	 */
+	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+		return (cu->cu_error.re_status = RPC_TIMEDOUT);
+	}
+	/*
+	 * sub-optimal code appears here because we have
+	 * some clock time to spare while the packets are in flight.
+	 * (We assume that this is actually only executed once.)
+	 */
+	reply_msg.acpted_rply.ar_verf = gssrpc__null_auth;
+	reply_msg.acpted_rply.ar_results.where = NULL;
+	reply_msg.acpted_rply.ar_results.proc = xdr_void;
+#ifdef FD_SETSIZE
+	FD_ZERO(&mask);
+	FD_SET(cu->cu_sock, &mask);
+#else
+	mask = 1 << cu->cu_sock;
+#endif /* def FD_SETSIZE */
+	for (;;) {
+		readfds = mask;
+		seltimeout = cu->cu_wait;
+		switch (select(gssrpc__rpc_dtablesize(), &readfds, (fd_set *)NULL, 
+			       (fd_set *)NULL, &seltimeout)) {
+
+		case 0:
+			time_waited.tv_sec += cu->cu_wait.tv_sec;
+			time_waited.tv_usec += cu->cu_wait.tv_usec;
+			while (time_waited.tv_usec >= 1000000) {
+				time_waited.tv_sec++;
+				time_waited.tv_usec -= 1000000;
+			}
+			if ((time_waited.tv_sec < timeout.tv_sec) ||
+				((time_waited.tv_sec == timeout.tv_sec) &&
+				(time_waited.tv_usec < timeout.tv_usec)))
+				goto send_again;	
+			return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+		/*
+		 * buggy in other cases because time_waited is not being
+		 * updated.
+		 */
+		case -1:
+			if (errno == EINTR)
+				continue;	
+			cu->cu_error.re_errno = errno;
+			return (cu->cu_error.re_status = RPC_CANTRECV);
+		}
+		do {
+			fromlen = sizeof(struct sockaddr);
+			inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, 
+				cu->cu_recvsz, 0,
+				(struct sockaddr *)&from, &fromlen);
+		} while (inlen < 0 && errno == EINTR);
+		if (inlen < 0) {
+			if (errno == EWOULDBLOCK)
+				continue;	
+			cu->cu_error.re_errno = errno;
+			return (cu->cu_error.re_status = RPC_CANTRECV);
+		}
+		if (inlen < sizeof(uint32_t))
+			continue;	
+		/* see if reply transaction id matches sent id */
+		if (*((uint32_t *)(void *)(cu->cu_inbuf)) != 
+		    *((uint32_t *)(void *)(cu->cu_outbuf)))
+			continue;	
+		/* we now assume we have the proper reply */
+		break;
+	}
+
+	/*
+	 * now decode and validate the response
+	 */
+	xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
+	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+	/* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
+	if (ok) {
+		gssrpc__seterr_reply(&reply_msg, &(cu->cu_error));
+		if (cu->cu_error.re_status == RPC_SUCCESS) {
+			if (! AUTH_VALIDATE(cl->cl_auth,
+				&reply_msg.acpted_rply.ar_verf)) {
+				cu->cu_error.re_status = RPC_AUTHERROR;
+				cu->cu_error.re_why = AUTH_INVALIDRESP;
+			} else if (! AUTH_UNWRAP(cl->cl_auth, &reply_xdrs,
+						 xresults, resultsp)) {
+			     if (cu->cu_error.re_status == RPC_SUCCESS)
+				  cu->cu_error.re_status = RPC_CANTDECODERES;
+			}
+		}  /* end successful completion */
+		else {
+			/* maybe our credentials need to be refreshed ... */
+			if (nrefreshes > 0 &&
+			    AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
+				nrefreshes--;
+				goto call_again;
+			}
+		}  /* end of unsuccessful completion */
+		/* free verifier */
+		if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+		    (reply_msg.acpted_rply.ar_verf.oa_base != NULL)) {
+		    xdrs->x_op = XDR_FREE;
+		    (void)xdr_opaque_auth(xdrs,
+					  &(reply_msg.acpted_rply.ar_verf));
+		} 
+	}  /* end of valid reply message */
+	else {
+		/*
+		 * It's possible for xdr_replymsg() to fail partway
+		 * through its attempt to decode the result from the
+		 * server. If this happens, it will leave the reply
+		 * structure partially populated with dynamically
+		 * allocated memory. (This can happen if someone uses
+		 * clntudp_bufcreate() to create a CLIENT handle and
+		 * specifies a receive buffer size that is too small.)
+		 * This memory must be free()ed to avoid a leak.
+		 */
+		enum xdr_op op = reply_xdrs.x_op;
+		reply_xdrs.x_op = XDR_FREE;
+		xdr_replymsg(&reply_xdrs, &reply_msg);
+		reply_xdrs.x_op = op;
+		return (RPC_CANTDECODERES);
+		cu->cu_error.re_status = RPC_CANTDECODERES;
+	}
+	return (cu->cu_error.re_status);
+}
+
+static void
+clntudp_geterr(
+	CLIENT *cl,
+	struct rpc_err *errp)
+{
+	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	*errp = cu->cu_error;
+}
+
+
+static bool_t
+clntudp_freeres(
+	CLIENT *cl,
+	xdrproc_t xdr_res,
+	void *res_ptr)
+{
+	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	register XDR *xdrs = &(cu->cu_outxdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_res)(xdrs, res_ptr));
+}
+
+
+/*ARGSUSED*/
+static void 
+clntudp_abort(CLIENT *h)
+{
+}
+
+static bool_t
+clntudp_control(
+	CLIENT *cl,
+	int request,
+	void *info)
+{
+	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+	
+	switch (request) {
+	case CLSET_TIMEOUT:
+		cu->cu_total = *(struct timeval *)info;
+		break;
+	case CLGET_TIMEOUT:
+		*(struct timeval *)info = cu->cu_total;
+		break;
+	case CLSET_RETRY_TIMEOUT:
+		cu->cu_wait = *(struct timeval *)info;
+		break;
+	case CLGET_RETRY_TIMEOUT:
+		*(struct timeval *)info = cu->cu_wait;
+		break;
+	case CLGET_SERVER_ADDR:
+		*(struct sockaddr_in *)info = cu->cu_raddr;
+		break;
+	case CLGET_LOCAL_ADDR:
+		*(struct sockaddr_in *)info = cu->cu_laddr;
+		break;
+	default:
+		return (FALSE);
+	}
+	return (TRUE);
+}
+	
+static void
+clntudp_destroy(CLIENT *cl)
+{
+	register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+	if (cu->cu_closeit) {
+		(void)close(cu->cu_sock);
+	}
+	XDR_DESTROY(&(cu->cu_outxdrs));
+	mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
+	mem_free((caddr_t)cl, sizeof(CLIENT));
+}
diff --git a/krb5-1-6/src/lib/rpc/dyn.c b/krb5-1-6/src/lib/rpc/dyn.c
new file mode 100644
index 000000000..192095cbc
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/dyn.c
@@ -0,0 +1,555 @@
+/*
+ * This file is the collected implementation of libdyn.a, the C
+ * Dynamic Object library.  It contains everything.
+ *
+ * There are no restrictions on this code; however, if you make any
+ * changes, I request that you document them so that I do not get
+ * credit or blame for your modifications.
+ *
+ * Written by Barr3y Jaspan, Student Information Processing Board (SIPB)
+ * and MIT-Project Athena, 1989.
+ *
+ * 2002-07-17 Collected full implementation into one source file for
+ *            easy inclusion into the one library still dependent on
+ *            libdyn.  Assume memmove.  Old ChangeLog appended.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dynP.h"
+
+
+/* old dyn_append.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the function DynAppend().
+ */
+
+/*
+ * Made obsolete by DynInsert, now just a convenience function.
+ */
+int DynAppend(obj, els, num)
+   DynObjectP obj;
+   DynPtr els;
+   int num;
+{
+     return DynInsert(obj, DynSize(obj), els, num);
+}
+
+
+/* old dyn_create.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the functions DynCreate() and
+ * DynDestroy().
+ */
+
+#ifndef DEFAULT_INC
+#define DEFAULT_INC	100
+#endif
+
+static int default_increment = DEFAULT_INC;
+
+DynObjectP DynCreate(el_size, inc)
+   int	el_size, inc;
+{
+     DynObjectP obj;
+
+     obj = (DynObjectP) malloc(sizeof(DynObjectRecP));
+     if (obj == NULL)
+	  return NULL;
+
+     obj->array = (DynPtr) malloc(1);
+     if (obj->array == NULL) {
+	 free(obj);
+	 return NULL;
+     }
+     obj->array[0] = '\0';
+
+     obj->el_size = el_size;
+     obj->num_el = obj->size = 0;
+     obj->debug = obj->paranoid = 0;
+     obj->inc = (inc) ? inc : default_increment;
+     obj->initzero = 0;
+
+     return obj;
+}
+
+DynObjectP DynCopy(obj)
+   DynObjectP obj;
+{
+     DynObjectP obj1;
+     
+     obj1 = (DynObjectP) malloc(sizeof(DynObjectRecP));
+     if (obj1 == NULL)
+	  return NULL;
+
+     obj1->el_size = obj->el_size;
+     obj1->num_el = obj->num_el;
+     obj1->size = obj->size;
+     obj1->inc = obj->inc;
+     obj1->debug = obj->debug;
+     obj1->paranoid = obj->paranoid;
+     obj1->initzero = obj->initzero;
+     obj1->array = (char *) malloc((size_t) (obj1->el_size * obj1->size));
+     if (obj1->array == NULL) {
+	  free(obj1);
+	  return NULL;
+     }
+     memcpy(obj1->array, obj->array, 
+	    (size_t) (obj1->el_size * obj1->size));
+
+     return obj1;
+}
+
+int DynDestroy(obj)
+     /*@only@*/DynObjectP obj;
+{
+     if (obj->paranoid) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: destroy: zeroing %d bytes from %p.\n",
+		       obj->el_size * obj->size, obj->array);
+	  memset(obj->array, 0, (size_t) (obj->el_size * obj->size));
+     }
+     free(obj->array);
+     free(obj);
+     return DYN_OK;
+}
+
+int DynRelease(obj)
+   DynObjectP obj;
+{
+     if (obj->debug)
+	  fprintf(stderr, "dyn: release: freeing object structure.\n");
+     free(obj);
+     return DYN_OK;
+}
+
+
+/* old dyn_debug.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the function DynDebug().
+ */
+
+int DynDebug(obj, state)
+   DynObjectP obj;
+   int state;
+{
+     obj->debug = state;
+
+     fprintf(stderr, "dyn: debug: Debug state set to %d.\n", state);
+     return DYN_OK;
+}
+
+
+/* old dyn_delete.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the function DynDelete().
+ */
+
+/*
+ * Checkers!  Get away from that "hard disk erase" button!
+ *    (Stupid dog.  He almost did it to me again ...)
+ */                                 
+int DynDelete(obj, idx)
+   DynObjectP obj;
+   int idx;
+{
+     if (idx < 0) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: delete: bad index %d\n", idx);
+	  return DYN_BADINDEX;
+     }
+     
+     if (idx >= obj->num_el) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: delete: Highest index is %d.\n",
+		       obj->num_el);
+	  return DYN_BADINDEX;
+     }
+
+     if (idx == obj->num_el-1) {
+	  if (obj->paranoid) {
+	       if (obj->debug)
+		    fprintf(stderr, "dyn: delete: last element, zeroing.\n");
+	       memset(obj->array + idx*obj->el_size, 0, (size_t) obj->el_size);
+	  }
+	  else {
+	       if (obj->debug)
+		    fprintf(stderr, "dyn: delete: last element, punting.\n");
+	  }
+     }	  
+     else {
+	  if (obj->debug)
+	       fprintf(stderr,
+		       "dyn: delete: copying %d bytes from %p + %d to + %d.\n",
+		       obj->el_size*(obj->num_el - idx), obj->array,
+		       (idx+1)*obj->el_size, idx*obj->el_size);
+	  
+	  memmove(obj->array + idx*obj->el_size,
+		  obj->array + (idx+1)*obj->el_size,
+		  (size_t) obj->el_size*(obj->num_el - idx));
+	  if (obj->paranoid) {
+	       if (obj->debug)
+		    fprintf(stderr,
+			    "dyn: delete: zeroing %d bytes from %p + %d\n",
+			    obj->el_size, obj->array,
+			    obj->el_size*(obj->num_el - 1));
+	       memset(obj->array + obj->el_size*(obj->num_el - 1), 0,
+		     (size_t) obj->el_size);
+	  }
+     }
+     
+     --obj->num_el;
+     
+     if (obj->debug)
+	  fprintf(stderr, "dyn: delete: done.\n");
+
+     return DYN_OK;
+}
+
+
+/* old dyn_initzero.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the function DynInitZero().
+ */
+
+int DynInitzero(obj, state)
+   DynObjectP obj;
+   int state;
+{
+     obj->initzero = state;
+
+     if (obj->debug)
+	  fprintf(stderr, "dyn: initzero: initzero set to %d.\n", state);
+     return DYN_OK;
+}
+
+
+/* old dyn_insert.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the function DynInsert().
+ */
+
+int DynInsert(obj, idx, els_in, num)
+   DynObjectP obj;
+   void *els_in;
+   int idx, num;
+{
+     DynPtr els = (DynPtr) els_in;
+     int ret;
+     
+     if (idx < 0 || idx > obj->num_el) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: insert: index %d is not in [0,%d]\n",
+		       idx, obj->num_el);
+	  return DYN_BADINDEX;
+     }
+
+     if (num < 1) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: insert: cannot insert %d elements\n",
+		       num);
+	  return DYN_BADVALUE;
+     }
+
+     if (obj->debug)
+	  fprintf(stderr,"dyn: insert: Moving %d bytes from %p + %d to + %d\n",
+		  (obj->num_el-idx)*obj->el_size, obj->array,
+		  obj->el_size*idx, obj->el_size*(idx+num));
+
+     if ((ret = _DynResize(obj, obj->num_el + num)) != DYN_OK)
+	  return ret;
+     memmove(obj->array + obj->el_size*(idx + num),
+	     obj->array + obj->el_size*idx,
+	     (size_t) ((obj->num_el-idx)*obj->el_size));
+
+     if (obj->debug)
+	  fprintf(stderr, "dyn: insert: Copying %d bytes from %p to %p + %d\n",
+		  obj->el_size*num, els, obj->array, obj->el_size*idx);
+
+     memmove(obj->array + obj->el_size*idx, els, (size_t) (obj->el_size*num));
+     obj->num_el += num;
+
+     if (obj->debug)
+	  fprintf(stderr, "dyn: insert: done.\n");
+
+     return DYN_OK;
+}
+
+
+/* old dyn_paranoid.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the function DynDebug().
+ */
+
+int DynParanoid(obj, state)
+   DynObjectP obj;
+   int state;
+{
+     obj->paranoid = state;
+
+     if (obj->debug)
+	  fprintf(stderr, "dyn: paranoid: Paranoia set to %d.\n", state);
+     return DYN_OK;
+}
+
+
+/* old dyn_put.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the functions DynGet() and DynAdd().
+ */
+
+DynPtr DynArray(obj)
+   DynObjectP obj;
+{
+     if (obj->debug)
+	  fprintf(stderr, "dyn: array: returning array pointer %p.\n",
+		  obj->array);
+
+     return obj->array;
+}
+
+DynPtr DynGet(obj, num)
+   DynObjectP obj;
+   int num;
+{
+     if (num < 0) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: get: bad index %d\n", num);
+	  return NULL;
+     }
+     
+     if (num >= obj->num_el) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: get: highest element is %d.\n",
+		       obj->num_el);
+	  return NULL;
+     }
+     
+     if (obj->debug)
+	  fprintf(stderr, "dyn: get: Returning address %p + %d.\n",
+		  obj->array, obj->el_size*num);
+     
+     return (DynPtr) obj->array + obj->el_size*num;
+}
+
+int DynAdd(obj, el)
+   DynObjectP obj;
+   void *el;
+{
+     int	ret;
+     
+     ret = DynPut(obj, el, obj->num_el);
+     if (ret != DYN_OK)
+	  return ret;
+
+     ++obj->num_el;
+     return ret;
+}
+
+/*
+ * WARNING!  There is a reason this function is not documented in the
+ * man page.  If DynPut used to mutate already existing elements,
+ * everything will go fine.  If it is used to add new elements
+ * directly, however, the state within the object (such as
+ * obj->num_el) will not be updated properly and many other functions
+ * in the library will lose.  Have a nice day.
+ */
+int DynPut(obj, el_in, idx)
+   DynObjectP obj;
+   void *el_in;
+   int idx;
+{
+     DynPtr el = (DynPtr) el_in;
+     int ret;
+     
+     if (obj->debug)
+	  fprintf(stderr, "dyn: put: Writing %d bytes from %p to %p + %d\n",
+		  obj->el_size, el, obj->array, idx*obj->el_size);
+
+     if ((ret = _DynResize(obj, idx)) != DYN_OK)
+	  return ret;
+
+     memmove(obj->array + idx*obj->el_size, el, (size_t) obj->el_size);
+
+     if (obj->debug)
+	  fprintf(stderr, "dyn: put: done.\n");
+     
+     return DYN_OK;
+}
+
+
+/* old dyn_realloc.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the internal function _DynRealloc().
+ */
+
+/*
+ * Resize the array so that element req exists.
+ */
+int _DynResize(obj, req)
+   DynObjectP obj;
+   int req;
+{
+     int size;
+     
+     if (obj->size > req)
+	  return DYN_OK;
+     else if (obj->inc > 0)
+	  return _DynRealloc(obj, (req - obj->size) / obj->inc + 1);
+     else {
+	  if (obj->size == 0)
+	       size = -obj->inc;
+	  else 
+	       size = obj->size;
+	  
+	  /*@-shiftsigned@*/
+	  while (size <= req)
+	       size <<= 1;
+	  /*@=shiftsigned@*/
+
+	  return _DynRealloc(obj, size);
+     }
+}
+
+/*
+ * Resize the array by num_incs units.  If obj->inc is positive, this
+ * means make it obj->inc*num_incs elements larger.  If obj->inc is
+ * negative, this means make the array num_incs elements long.
+ * 
+ * Ideally, this function should not be called from outside the
+ * library.  However, nothing will break if it is.
+ */
+int _DynRealloc(obj, num_incs)
+   DynObjectP obj;
+   int num_incs;
+{
+     DynPtr temp;
+     int new_size_in_bytes;
+
+     if (obj->inc > 0)
+	  new_size_in_bytes = obj->el_size*(obj->size + obj->inc*num_incs);
+     else
+	  new_size_in_bytes = obj->el_size*num_incs;
+     
+     if (obj->debug)
+	  fprintf(stderr,
+		  "dyn: alloc: Increasing object by %d bytes (%d incs).\n",
+		  new_size_in_bytes - obj->el_size*obj->size,
+		  num_incs);
+     
+     temp = (DynPtr) realloc(obj->array, (size_t) new_size_in_bytes);
+     if (temp == NULL) {
+	  if (obj->debug)
+	       fprintf(stderr, "dyn: alloc: Out of memory.\n");
+	  return DYN_NOMEM;
+     }
+     else {
+	  obj->array = temp;
+	  if (obj->inc > 0)
+	       obj->size += obj->inc*num_incs;
+	  else
+	       obj->size = num_incs;
+     }
+
+     if (obj->debug)
+	  fprintf(stderr, "dyn: alloc: done.\n");
+	  
+     return DYN_OK;
+}
+
+
+/* old dyn_size.c */
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the source code for the function DynSize().
+ */
+
+int DynSize(obj)
+   DynObjectP obj;
+{
+     if (obj->debug)
+	  fprintf(stderr, "dyn: size: returning size %d.\n", obj->num_el);
+
+     return obj->num_el;
+}
+
+int DynCapacity(obj)
+   DynObjectP obj;
+{
+     if (obj->debug)
+	  fprintf(stderr, "dyn: capacity: returning cap of %d.\n", obj->size);
+
+     return obj->size;
+}
+
+/* Old change log, as it relates to source code; build system stuff
+   discarded.
+
+2001-10-09  Ken Raeburn  <raeburn@mit.edu>
+
+	* dyn.h, dynP.h: Make prototypes unconditional.  Don't define
+	P().
+
+2001-04-25  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn.h: Lclint annotate functions.
+
+	* dyn_create.c (DynCreate): Do not assume that malloc(0) is valid
+	and returns a valid pointer. Fix memory leak if malloc fails.
+
+	* dyn_realloc.c (_DynResize): Turn off warning of shifting a
+	signed variable.
+
+Thu Nov  9 15:31:31 2000  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn_create.c (DynCopy): Arguments to memcpy were reversed. Found
+ 	while playing with lclint.
+
+2000-11-09  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn_create.c, dyn_delete.c, dyn_insert.c, dyn_put.c,
+	dyn_realloc.c: Cast arguments to malloc(), realloc(), memmove() to
+	size_t.
+
+	* dynP.h: Provide full prototypes for _DynRealloc() and _DynResize().
+
+	* dyn.h: Add prototype for DynAppend.
+
+2000-06-29  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn_insert.c, dyn_put.c: Include string.h for memmove prototype.
+
+2000-06-28  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn_create.c, dyn_delete.c, dyn_insert.c, dyn_put.c: Use %p
+	format for displaying pointers.
+
+2000-06-26  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn_realloc.c: Remove unused variable.
+
+Sat Dec  6 22:50:03 1997  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn_delete.c: Include <string.h>
+
+Mon Jul 22 21:37:52 1996  Ezra Peisach  <epeisach@mit.edu>
+
+	* dyn.h: If __STDC__ is not defined, generate prototypes implying
+		functions and not variables. 
+
+Mon Jul 22 04:20:48 1996  Marc Horowitz  <marc@mit.edu>
+
+	* dyn_insert.c (DynInsert): what used to be #ifdef POSIX, should
+ 	be #ifdef HAVE_MEMMOVE
+*/
diff --git a/krb5-1-6/src/lib/rpc/dyn.h b/krb5-1-6/src/lib/rpc/dyn.h
new file mode 100644
index 000000000..a888b1d7b
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/dyn.h
@@ -0,0 +1,79 @@
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the public header file.
+ *
+ * There are no restrictions on this code; however, if you make any
+ * changes, I request that you document them so that I do not get
+ * credit or blame for your modifications.
+ *
+ * Written by Barr3y Jaspan, Student Information Processing Board (SIPB)
+ * and MIT-Project Athena, 1989.
+ *
+ * 2002-07-17 Moved here from util/dyn; for old changes see dyn.c.
+ *            Added macros to rename exposed symbols.  For newer changes
+ *            see ChangeLog in the current directory.
+ */
+
+
+/*
+ * dyn.h -- header file to be included by programs linking against
+ * libdyn.a.
+ */
+
+#ifndef _Dyn_h
+#define _Dyn_h
+
+typedef char *DynPtr;
+typedef struct _DynObject {
+     DynPtr	array;
+     int	el_size, num_el, size, inc;
+     int	debug, paranoid, initzero;
+} DynObjectRec, *DynObject;
+
+/* Function macros */
+#define DynHigh(obj)	(DynSize(obj) - 1)
+#define DynLow(obj)	(0)
+
+/* Return status codes */
+#define DYN_OK		-1000
+#define DYN_NOMEM	-1001
+#define DYN_BADINDEX	-1002
+#define DYN_BADVALUE	-1003
+     
+#define DynCreate	gssrpcint_DynCreate
+#define DynDestroy	gssrpcint_DynDestroy
+#define DynRelease	gssrpcint_DynRelease
+#define DynAdd		gssrpcint_DynAdd
+#define DynPut		gssrpcint_DynPut
+#define DynInsert	gssrpcint_DynInsert
+#define DynGet		gssrpcint_DynGet
+#define DynArray	gssrpcint_DynArray
+#define DynSize		gssrpcint_DynSize
+#define DynCopy		gssrpcint_DynCopy
+#define DynDelete	gssrpcint_DynDelete
+#define DynDebug	gssrpcint_DynDebug
+#define DynParanoid	gssrpcint_DynParanoid
+#define DynInitzero	gssrpcint_DynInitzero
+#define DynCapacity	gssrpcint_DynCapacity
+#define DynAppend	gssrpcint_DynAppend
+
+/*@null@*//*@only@*/ DynObject DynCreate (int el_size, int inc);
+/*@null@*//*@only@*/ DynObject DynCopy (DynObject obj);
+int DynDestroy (/*@only@*/DynObject obj), DynRelease (DynObject obj);
+int DynAdd (DynObject obj, void *el);
+int DynPut (DynObject obj, void *el, int idx);
+int DynInsert (DynObject obj, int idx, /*@observer@*/void *els, int num);
+int DynDelete (DynObject obj, int idx);
+/*@dependent@*//*@null@*/ DynPtr DynGet (DynObject obj, int num);
+/*@observer@*/ DynPtr DynArray (DynObject obj);
+int DynDebug (DynObject obj, int state);
+int DynParanoid (DynObject obj, int state);
+int DynInitzero (DynObject obj, int state);
+int DynSize (DynObject obj);
+int DynCapacity (DynObject obj);
+int DynAppend (DynObject obj, DynPtr els, int num);
+
+#undef P
+
+#endif /* _Dyn_h */
+/* DO NOT ADD ANYTHING AFTER THIS #endif */
diff --git a/krb5-1-6/src/lib/rpc/dynP.h b/krb5-1-6/src/lib/rpc/dynP.h
new file mode 100644
index 000000000..f2e1c3e88
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/dynP.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of libdyn.a, the C Dynamic Object library.  It
+ * contains the private header file.
+ *
+ * There are no restrictions on this code; however, if you make any
+ * changes, I request that you document them so that I do not get
+ * credit or blame for your modifications.
+ *
+ * Written by Barr3y Jaspan, Student Information Processing Board (SIPB)
+ * and MIT-Project Athena, 1989.
+ */
+
+
+/*
+ * dynP.h -- private header file included by source files for libdyn.a.
+ */
+
+#ifndef _DynP_h
+#define _DynP_h
+
+#include "dyn.h"
+#ifdef USE_DBMALLOC
+#include <sys/stdtypes.h>
+#include <malloc.h>
+#endif
+
+/*
+ * Rep invariant:
+ * 1) el_size is the number of bytes per element in the object
+ * 2) num_el is the number of elements currently in the object.  It is
+ * one higher than the highest index at which an element lives.
+ * 3) size is the number of elements the object can hold without
+ * resizing.  num_el <= index.
+ * 4) inc is a multiple of the number of elements the object grows by
+ * each time it is reallocated.
+ */
+
+typedef struct _DynObject DynObjectRecP, *DynObjectP;
+
+#define _DynRealloc	gssrpcint_DynRealloc
+#define _DynResize	gssrpcint_DynResize
+
+/* Internal functions */
+int _DynRealloc (DynObjectP obj, int req), 
+  _DynResize (DynObjectP obj, int req);
+
+#undef P
+
+#endif /* _DynP_h */
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/krb5-1-6/src/lib/rpc/dyntest.c b/krb5-1-6/src/lib/rpc/dyntest.c
new file mode 100644
index 000000000..2a80b4fa9
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/dyntest.c
@@ -0,0 +1,216 @@
+/*
+ * This file is a (rather silly) demonstration of the use of the
+ * C Dynamic Object library.  It is a also reasonably thorough test
+ * of the library (except that it only tests it with one data size).
+ *
+ * There are no restrictions on this code; however, if you make any
+ * changes, I request that you document them so that I do not get
+ * credit or blame for your modifications.
+ *
+ * Written by Barr3y Jaspan, Student Information Processing Board (SIPB)
+ * and MIT-Project Athena, 1989.
+ *
+ * 2002-07-17 Moved here from util/dyn/test.c.  Older changes described
+ *            at end of file; for newer changes see ChangeLog.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#ifdef USE_DBMALLOC
+#include <sys/stdtypes.h>
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+
+#include "dyn.h"
+
+static char random_string[] = "This is a random string.";
+static char insert1[] = "This will be put at the beginning.";
+static char insert2[] = "(parenthetical remark!) ";
+static char insert3[] = "  This follows the random string.";
+
+int
+main(argc, argv)
+/*@unused@*/int argc;
+/*@unused@*/char **argv;
+{
+     /*@-exitarg@*/
+     DynObject	obj;
+     int	i, s;
+     char	d, *data;
+
+#ifdef _DEBUG_MALLOC_INC
+     union dbmalloptarg arg;
+     unsigned long hist1, hist2, o_size, c_size;
+#endif
+
+#ifdef _DEBUG_MALLOC_INC
+     arg.i = 0;
+     dbmallopt(MALLOC_ZERO, &arg);
+     dbmallopt(MALLOC_REUSE, &arg);
+
+     o_size = malloc_inuse(&hist1);
+#endif 
+
+     /*@+matchanyintegral@*/
+     obj = DynCreate(sizeof(char), -8);
+     if (! obj) {
+	  fprintf(stderr, "test: create failed.\n");
+	  exit(1);
+     }
+     
+     if(DynDebug(obj, 1) != DYN_OK) {
+	  fprintf(stderr, "test: setting paranoid failed.\n");
+	  exit(1);
+     }
+     if(DynParanoid(obj, 1) != DYN_OK) {
+	  fprintf(stderr, "test: setting paranoid failed.\n");
+	  exit(1);
+     }
+       
+
+     if ((DynGet(obj, -5) != NULL) || 
+	 (DynGet(obj, 0) != NULL) || (DynGet(obj, 1000) != NULL)) {
+	  fprintf(stderr, "test: Get did not fail when it should have.\n");
+	  exit(1);
+     }
+
+     if (DynDelete(obj, -1) != DYN_BADINDEX ||
+	 DynDelete(obj, 0) != DYN_BADINDEX ||
+	 DynDelete(obj, 100) != DYN_BADINDEX) {
+	  fprintf(stderr, "test: Delete did not fail when it should have.\n");
+	  exit(1);
+     }
+
+     printf("Size of empty object: %d\n", DynSize(obj));
+
+     for (i=0; i<14; i++) {
+	  d = (char) i;
+	  if (DynAdd(obj, &d) != DYN_OK) {
+	       fprintf(stderr, "test: Adding %d failed.\n", i);
+	       exit(1);
+	  }
+     }
+
+     if (DynAppend(obj, random_string, strlen(random_string)+1) != DYN_OK) {
+	  fprintf(stderr, "test: appending array failed.\n");
+	  exit(1);
+     }
+     
+     if (DynDelete(obj, DynHigh(obj) / 2) != DYN_OK) {
+	  fprintf(stderr, "test: deleting element failed.\n");
+	  exit(1);
+     }
+
+     if (DynDelete(obj, DynHigh(obj) * 2) == DYN_OK) {
+	  fprintf(stderr, "test: delete should have failed here.\n");
+	  exit(1);
+     }
+
+     d = '\200';
+     if (DynAdd(obj, &d) != DYN_OK) {
+	  fprintf(stderr, "test: Adding %d failed.\n", i);
+	  exit(1);
+     }
+
+     data = (char *) DynGet(obj, 0);
+     if(data == NULL) {
+	 fprintf(stderr, "test: getting object 0 failed.\n");
+	 exit(1);
+     }
+     s = DynSize(obj);
+     for (i=0; i < s; i++)
+	  printf("Element %d is %d.\n", i, (int) data[i]);
+
+     data = (char *) DynGet(obj, 13);
+     if(data == NULL) {
+	 fprintf(stderr, "test: getting element 13 failed.\n");
+	 exit(1);
+     }
+     printf("Element 13 is %d.\n", (int) *data);
+
+     data = (char *) DynGet(obj, DynSize(obj));
+     if (data) {
+	  fprintf(stderr, "DynGet did not return NULL when it should have.\n");
+	  exit(1);
+     }
+
+     data = DynGet(obj, 14);
+     if(data == NULL) {
+	 fprintf(stderr, "test: getting element 13 failed.\n");
+	 exit(1);
+     }
+     printf("This should be the random string: \"%s\"\n", data);
+
+     if (DynInsert(obj, -1, "foo", 4) != DYN_BADINDEX ||
+	 DynInsert(obj, DynSize(obj) + 1, "foo", 4) != DYN_BADINDEX ||
+	 DynInsert(obj, 0, "foo", -1) != DYN_BADVALUE) {
+	  fprintf(stderr, "DynInsert did not fail when it should have.\n");
+	  exit(1);
+     }
+
+     if (DynInsert(obj, DynSize(obj) - 2, insert3, strlen(insert3) +
+		   1) != DYN_OK) {
+	  fprintf(stderr, "DynInsert to end failed.\n");
+	  exit(1);
+     }  
+
+     if (DynInsert(obj, 19, insert2, strlen(insert2)) != DYN_OK) {
+	  fprintf(stderr, "DynInsert to middle failed.\n");
+	  exit(1);
+     }
+     
+     if (DynInsert(obj, 0, insert1, strlen(insert1)+1) != DYN_OK) {
+	  fprintf(stderr, "DynInsert to start failed.\n");
+	  exit(1);
+     }	
+
+     data = DynGet(obj, 14 + strlen(insert1) + 1);
+     if (data == NULL) {
+	  fprintf(stderr, "DynGet of 14+strelen(insert1) failed.\n");
+	  exit(1);
+
+     }
+     printf("A new random string: \"%s\"\n", data);
+
+     data = DynGet(obj, 0);
+     if (data == NULL) {
+	  fprintf(stderr, "DynGet of 0 failed.\n");
+	  exit(1);
+
+     }
+     printf("This was put at the beginning: \"%s\"\n", data);
+
+     if(DynDestroy(obj) != DYN_OK) {
+	  fprintf(stderr, "test: destroy failed.\n");
+	  exit(1);
+     }
+
+#ifdef _DEBUG_MALLOC_INC
+     c_size = malloc_inuse(&hist2);
+     if (o_size != c_size) {
+	  printf("\n\nIgnore a single unfreed malloc segment "
+		 "(stdout buffer).\n\n");
+	  malloc_list(2, hist1, hist2);
+     }
+#endif
+     
+     printf("All tests pass\n");
+
+     return 0;
+}
+
+/* Old change log, as it relates to source code; build system stuff
+   discarded.
+
+2001-04-25  Ezra Peisach  <epeisach@mit.edu>
+
+	* test.c: Always include stdlib.h
+
+	* test.c: Check the return values of all library calls.
+
+2000-11-09  Ezra Peisach  <epeisach@mit.edu>
+
+	* test.c: Include string,h, stdlib.h.
+
+*/
diff --git a/krb5-1-6/src/lib/rpc/get_myaddress.c b/krb5-1-6/src/lib/rpc/get_myaddress.c
new file mode 100644
index 000000000..871c8fcb1
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/get_myaddress.c
@@ -0,0 +1,116 @@
+/* @(#)get_myaddress.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * get_myaddress.c
+ *
+ * Get client's IP address via ioctl.  This avoids using the yellowpages.
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifdef GSSAPI_KRB5
+#include <string.h>
+#include <gssrpc/types.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_prot.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <krb5.h>
+/* 
+ * don't use gethostbyname, which would invoke yellow pages
+ */
+int
+get_myaddress(struct sockaddr_in *addr)
+{
+	memset((void *) addr, 0, sizeof(*addr));
+	addr->sin_family = AF_INET;
+	addr->sin_port = htons(PMAPPORT);
+	addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	return (0);
+}
+#else /* !GSSAPI_KRB5 */
+#include <gssrpc/types.h>
+#include <gssrpc/pmap_prot.h>
+#include <sys/socket.h>
+#if defined(sun)
+#include <sys/sockio.h>
+#endif
+#include <stdio.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+/* 
+ * don't use gethostbyname, which would invoke yellow pages
+ */
+get_myaddress(struct sockaddr_in *addr)
+{
+	int s;
+	char buf[256 * sizeof (struct ifreq)];
+	struct ifconf ifc;
+	struct ifreq ifreq, *ifr;
+	int len;
+
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	    perror("get_myaddress: socket");
+	    exit(1);
+	}
+	ifc.ifc_len = sizeof (buf);
+	ifc.ifc_buf = buf;
+	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+		perror("get_myaddress: ioctl (get interface configuration)");
+		exit(1);
+	}
+	ifr = ifc.ifc_req;
+	for (len = ifc.ifc_len; len; len -= sizeof ifreq) {
+		ifreq = *ifr;
+		if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+			perror("get_myaddress: ioctl");
+			exit(1);
+		}
+		if ((ifreq.ifr_flags & IFF_UP) &&
+		    ifr->ifr_addr.sa_family == AF_INET) {
+			*addr = *((struct sockaddr_in *)&ifr->ifr_addr);
+			addr->sin_port = htons(PMAPPORT);
+			break;
+		}
+		ifr++;
+	}
+	(void) close(s);
+}
+#endif /* !GSSAPI_KRB5 */
diff --git a/krb5-1-6/src/lib/rpc/getrpcent.c b/krb5-1-6/src/lib/rpc/getrpcent.c
new file mode 100644
index 000000000..a91a7a5bb
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/getrpcent.c
@@ -0,0 +1,236 @@
+/* @(#)getrpcent.c	2.2 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static  char sccsid[] = "@(#)getrpcent.c 1.9 87/08/11  Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <gssrpc/rpc.h>
+#include <string.h>
+#include <sys/socket.h>
+
+SETRPCENT_TYPE setrpcent (int);
+ENDRPCENT_TYPE endrpcent (void);
+
+/*
+ * Internet version.
+ */
+struct rpcdata {
+	FILE	*rpcf;
+	char	*current;
+	int	currentlen;
+	int	stayopen;
+#define	MAXALIASES	35
+	char	*rpc_aliases[MAXALIASES];
+	struct	rpcent rpc;
+	char	line[BUFSIZ+1];
+	char	*domain;
+} *rpcdata;
+static struct rpcdata *get_rpcdata();
+
+static	struct rpcent *interpret();
+struct	hostent *gethostent();
+char	*inet_ntoa();
+
+static char RPCDB[] = "/etc/rpc";
+
+static struct rpcdata *
+get_rpcdata(void)
+{
+	register struct rpcdata *d = rpcdata;
+
+	if (d == 0) {
+		d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
+		rpcdata = d;
+	}
+	return (d);
+}
+
+struct rpcent *
+getrpcbynumber(register int number)
+{
+	register struct rpcdata *d = get_rpcdata();
+	register struct rpcent *p;
+	int reason;
+	char adrstr[16], *val = NULL;
+	int vallen;
+
+	if (d == 0)
+		return (0);
+	setrpcent(0);
+	while (p = getrpcent()) {
+		if (p->r_number == number)
+			break;
+	}
+	endrpcent();
+	return (p);
+}
+
+struct rpcent *
+getrpcbyname(const char *name)
+{
+	struct rpcent *rpc;
+	char **rp;
+
+	setrpcent(0);
+	while(rpc = getrpcent()) {
+		if (strcmp(rpc->r_name, name) == 0)
+			return (rpc);
+		for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+			if (strcmp(*rp, name) == 0)
+				return (rpc);
+		}
+	}
+	endrpcent();
+	return (NULL);
+}
+
+SETRPCENT_TYPE setrpcent(int f)
+{
+	register struct rpcdata *d = _rpcdata();
+
+	if (d == 0)
+		return;
+	if (d->rpcf == NULL)
+		d->rpcf = fopen(RPCDB, "r");
+	else
+		rewind(d->rpcf);
+	if (d->current)
+		free(d->current);
+	d->current = NULL;
+	d->stayopen |= f;
+}
+
+ENDRPCENT_TYPE endrpcent(void)
+{
+	register struct rpcdata *d = _rpcdata();
+
+	if (d == 0)
+		return;
+	if (d->current && !d->stayopen) {
+		free(d->current);
+		d->current = NULL;
+	}
+	if (d->rpcf && !d->stayopen) {
+		fclose(d->rpcf);
+		d->rpcf = NULL;
+	}
+}
+
+struct rpcent *
+getrpcent(void)
+{
+	struct rpcent *hp;
+	int reason;
+	char *key = NULL, *val = NULL;
+	int keylen, vallen;
+	register struct rpcdata *d = _rpcdata();
+
+	if (d == 0)
+		return(NULL);
+	if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
+		return (NULL);
+    if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
+		return (NULL);
+	return interpret(d->line, strlen(d->line));
+}
+
+static struct rpcent *
+interpret(char *val, int len)
+{
+	register struct rpcdata *d = _rpcdata();
+	char *p;
+	register char *cp, **q;
+
+	if (d == 0)
+		return;
+	strncpy(d->line, val, len);
+	p = d->line;
+	d->line[len] = '\n';
+	if (*p == '#')
+		return (getrpcent());
+	cp = strchr(p, '#');
+	if (cp == NULL)
+    {
+		cp = strchr(p, '\n');
+		if (cp == NULL)
+			return (getrpcent());
+	}
+	*cp = '\0';
+	cp = strchr(p, ' ');
+	if (cp == NULL)
+    {
+		cp = strchr(p, '\t');
+		if (cp == NULL)
+			return (getrpcent());
+	}
+	*cp++ = '\0';
+	/* THIS STUFF IS INTERNET SPECIFIC */
+	d->rpc.r_name = d->line;
+	while (*cp == ' ' || *cp == '\t')
+		cp++;
+	d->rpc.r_number = atoi(cp);
+	q = d->rpc.r_aliases = d->rpc_aliases;
+	cp = strchr(p, ' ');
+	if (cp != NULL)
+		*cp++ = '\0';
+	else
+    {
+		cp = strchr(p, '\t');
+		if (cp != NULL)
+			*cp++ = '\0';
+	}
+	while (cp && *cp) {
+		if (*cp == ' ' || *cp == '\t') {
+			cp++;
+			continue;
+		}
+		if (q < &(d->rpc_aliases[MAXALIASES - 1]))
+			*q++ = cp;
+		cp = strchr(p, ' ');
+		if (cp != NULL)
+			*cp++ = '\0';
+		else
+	    {
+			cp = strchr(p, '\t');
+			if (cp != NULL)
+				*cp++ = '\0';
+		}
+	}
+	*q = NULL;
+	return (&d->rpc);
+}
diff --git a/krb5-1-6/src/lib/rpc/getrpcport.c b/krb5-1-6/src/lib/rpc/getrpcport.c
new file mode 100644
index 000000000..8688df2ea
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/getrpcport.c
@@ -0,0 +1,66 @@
+/* @(#)getrpcport.c	2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static  char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_clnt.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include "autoconf.h"
+
+int
+gssrpc_getrpcport(
+	char *host,
+	rpcprog_t prognum,
+	rpcvers_t versnum,
+	rpcprot_t proto)
+{
+	struct sockaddr_in addr;
+	struct hostent *hp;
+
+	if ((hp = gethostbyname(host)) == NULL)
+		return (0);
+	memset(&addr, 0, sizeof(addr));
+	memmove((char *) &addr.sin_addr, hp->h_addr, sizeof(addr.sin_addr));
+#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+	addr.sin_len = sizeof(addr);
+#endif
+	addr.sin_family = AF_INET;
+	addr.sin_port =  0;
+	return (pmap_getport(&addr, prognum, versnum, proto));
+}
diff --git a/krb5-1-6/src/lib/rpc/libgssrpc.exports b/krb5-1-6/src/lib/rpc/libgssrpc.exports
new file mode 100644
index 000000000..1437b9661
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/libgssrpc.exports
@@ -0,0 +1,141 @@
+gssrpc_auth_debug_gss
+gssrpc_auth_debug_gssapi
+gssrpc_auth_gssapi_create
+gssrpc_auth_gssapi_create_default
+gssrpc_auth_gssapi_display_status
+gssrpc_auth_gssapi_seal_seq
+gssrpc_auth_gssapi_unseal_seq
+gssrpc_auth_gssapi_unwrap_data
+gssrpc_auth_gssapi_wrap_data
+gssrpc_authgss_create
+gssrpc_authgss_create_default
+gssrpc_authgss_get_private_data
+gssrpc_authgss_service
+gssrpc_authnone_create
+gssrpc_authunix_create
+gssrpc_authunix_create_default
+gssrpc_bindresvport
+gssrpc_callrpc
+gssrpc_clnt_broadcast
+gssrpc_clnt_create
+gssrpc_clnt_pcreateerror
+gssrpc_clnt_perrno
+gssrpc_clnt_perror
+gssrpc_clnt_spcreateerror
+gssrpc_clnt_sperrno
+gssrpc_clnt_sperror
+gssrpc_clntraw_create
+gssrpc_clnttcp_create
+gssrpc_clntudp_bufcreate
+gssrpc_clntudp_create
+gssrpc_get_myaddress
+gssrpc_getrpcport
+gssrpc_log_debug
+gssrpc_log_hexdump
+gssrpc_log_status
+gssrpc_misc_debug_gss
+gssrpc_misc_debug_gssapi
+gssrpc_pmap_getmaps
+gssrpc_pmap_getport
+gssrpc_pmap_rmtcall
+gssrpc_pmap_set
+gssrpc_pmap_unset
+gssrpc_registerrpc
+gssrpc_rpc_createrr
+gssrpc_svc_auth_gss_creds
+gssrpc_svc_auth_gss_ops
+gssrpc_svc_auth_gssapi_ops
+gssrpc_svc_auth_none
+gssrpc_svc_auth_none_ops
+gssrpc_svc_debug_gss
+gssrpc_svc_debug_gssapi
+gssrpc_svc_fdset
+gssrpc_svc_fdset_init
+gssrpc_svc_getreq
+gssrpc_svc_getreqset
+gssrpc_svc_maxfd
+gssrpc_svc_register
+gssrpc_svc_run
+gssrpc_svc_sendreply
+gssrpc_svc_unregister
+gssrpc_svcauth_gss_get_principal
+gssrpc_svcauth_gss_set_log_badauth_func
+gssrpc_svcauth_gss_set_log_badverf_func
+gssrpc_svcauth_gss_set_log_miscerr_func
+gssrpc_svcauth_gss_set_svc_name
+gssrpc_svcauth_gssapi_set_log_badauth_func
+gssrpc_svcauth_gssapi_set_log_badverf_func
+gssrpc_svcauth_gssapi_set_log_miscerr_func
+gssrpc_svcauth_gssapi_set_names
+gssrpc_svcauth_gssapi_unset_names
+gssrpc_svcerr_auth
+gssrpc_svcerr_decode
+gssrpc_svcerr_noproc
+gssrpc_svcerr_noprog
+gssrpc_svcerr_progvers
+gssrpc_svcerr_systemerr
+gssrpc_svcerr_weakauth
+gssrpc_svcfd_create
+gssrpc_svcraw_create
+gssrpc_svctcp_create
+gssrpc_svcudp_bufcreate
+gssrpc_svcudp_create
+gssrpc_svcudp_enablecache
+gssrpc_xdr_accepted_reply
+gssrpc_xdr_array
+gssrpc_xdr_authgssapi_creds
+gssrpc_xdr_authgssapi_init_arg
+gssrpc_xdr_authgssapi_init_res
+gssrpc_xdr_authunix_parms
+gssrpc_xdr_bool
+gssrpc_xdr_bytes
+gssrpc_xdr_callhdr
+gssrpc_xdr_callmsg
+gssrpc_xdr_char
+gssrpc_xdr_des_block
+gssrpc_xdr_enum
+gssrpc_xdr_free
+gssrpc_xdr_gss_buf
+gssrpc_xdr_int
+gssrpc_xdr_int32
+gssrpc_xdr_long
+gssrpc_xdr_netobj
+gssrpc_xdr_opaque
+gssrpc_xdr_opaque_auth
+gssrpc_xdr_pmap
+gssrpc_xdr_pmaplist
+gssrpc_xdr_pointer
+gssrpc_xdr_reference
+gssrpc_xdr_rejected_reply
+gssrpc_xdr_replymsg
+gssrpc_xdr_rmtcall_args
+gssrpc_xdr_rmtcallres
+gssrpc_xdr_rpc_gss_buf
+gssrpc_xdr_rpc_gss_cred
+gssrpc_xdr_rpc_gss_data
+gssrpc_xdr_rpc_gss_init_args
+gssrpc_xdr_rpc_gss_init_res
+gssrpc_xdr_rpc_gss_unwrap_data
+gssrpc_xdr_rpc_gss_wrap_data
+gssrpc_xdr_short
+gssrpc_xdr_string
+gssrpc_xdr_u_char
+gssrpc_xdr_u_int
+gssrpc_xdr_u_int32
+gssrpc_xdr_u_long
+gssrpc_xdr_u_short
+gssrpc_xdr_union
+gssrpc_xdr_vector
+gssrpc_xdr_void
+gssrpc_xdr_wrapstring
+gssrpc_xdralloc_create
+gssrpc_xdralloc_getdata
+gssrpc_xdralloc_release
+gssrpc_xdrmem_create
+gssrpc_xdrrec_create
+gssrpc_xdrrec_endofrecord
+gssrpc_xdrrec_eof
+gssrpc_xdrrec_skiprecord
+gssrpc_xdrstdio_create
+gssrpc_xprt_register
+gssrpc_xprt_unregister
diff --git a/krb5-1-6/src/lib/rpc/pmap_clnt.c b/krb5-1-6/src/lib/rpc/pmap_clnt.c
new file mode 100644
index 000000000..7951d2ea0
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/pmap_clnt.c
@@ -0,0 +1,115 @@
+/* @(#)pmap_clnt.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_clnt.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_prot.h>
+#include <gssrpc/pmap_clnt.h>
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+void clnt_perror();
+
+/*
+ * Set a mapping between program,version and port.
+ * Calls the pmap service remotely to do the mapping.
+ */
+bool_t
+pmap_set(
+	rpcprog_t program,
+	rpcvers_t version,
+	rpcprot_t protocol,
+	u_int port)
+{
+	struct sockaddr_in myaddress;
+	int socket = -1;
+	register CLIENT *client;
+	struct pmap parms;
+	bool_t rslt;
+
+	get_myaddress(&myaddress);
+	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (client == (CLIENT *)NULL)
+		return (FALSE);
+	parms.pm_prog = program;
+	parms.pm_vers = version;
+	parms.pm_prot = protocol;
+	parms.pm_port = port;
+	if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
+	    tottimeout) != RPC_SUCCESS) {
+		clnt_perror(client, "Cannot register service");
+		return (FALSE);
+	}
+	CLNT_DESTROY(client);
+	(void)close(socket);
+	return (rslt);
+}
+
+/*
+ * Remove the mapping between program,version and port.
+ * Calls the pmap service remotely to do the un-mapping.
+ */
+bool_t
+pmap_unset(
+	rpcprog_t program,
+	rpcvers_t version)
+{
+	struct sockaddr_in myaddress;
+	int socket = -1;
+	register CLIENT *client;
+	struct pmap parms;
+	bool_t rslt;
+
+	get_myaddress(&myaddress);
+	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (client == (CLIENT *)NULL)
+		return (FALSE);
+	parms.pm_prog = program;
+	parms.pm_vers = version;
+	parms.pm_port = parms.pm_prot = 0;
+	CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
+	    tottimeout);
+	CLNT_DESTROY(client);
+	(void)close(socket);
+	return (rslt);
+}
diff --git a/krb5-1-6/src/lib/rpc/pmap_getmaps.c b/krb5-1-6/src/lib/rpc/pmap_getmaps.c
new file mode 100644
index 000000000..36997c22a
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/pmap_getmaps.c
@@ -0,0 +1,87 @@
+/* @(#)pmap_getmaps.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_getmap.c
+ * Client interface to pmap rpc service.
+ * contains pmap_getmaps, which is only tcp service involved
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_prot.h>
+#include <gssrpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#define NAMELEN 255
+#define MAX_BROADCAST_SIZE 1400
+
+
+/*
+ * Get a copy of the current port maps.
+ * Calls the pmap service remotely to do get the maps.
+ */
+struct pmaplist *
+pmap_getmaps(struct sockaddr_in *address)
+{
+	struct pmaplist *head = (struct pmaplist *)NULL;
+	int sock = -1;
+	struct timeval minutetimeout;
+	register CLIENT *client;
+
+	minutetimeout.tv_sec = 60;
+	minutetimeout.tv_usec = 0;
+	address->sin_port = htons(PMAPPORT);
+	client = clnttcp_create(address, PMAPPROG,
+	    PMAPVERS, &sock, 50, 500);
+	if (client != (CLIENT *)NULL) {
+		if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
+		    &head, minutetimeout) != RPC_SUCCESS) {
+			clnt_perror(client, "pmap_getmaps rpc problem");
+		}
+		CLNT_DESTROY(client);
+	}
+	(void)close(sock);
+	address->sin_port = 0;
+	return (head);
+}
diff --git a/krb5-1-6/src/lib/rpc/pmap_getport.c b/krb5-1-6/src/lib/rpc/pmap_getport.c
new file mode 100644
index 000000000..998a08199
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/pmap_getport.c
@@ -0,0 +1,92 @@
+/* @(#)pmap_getport.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_prot.h>
+#include <gssrpc/pmap_clnt.h>
+#include <sys/socket.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+u_short
+pmap_getport(
+	struct sockaddr_in *address,
+	rpcprog_t program,
+	rpcvers_t version,
+	rpcprot_t protocol)
+{
+	unsigned short port = 0;
+	int sock = -1;
+	register CLIENT *client;
+	struct pmap parms;
+
+	address->sin_port = htons(PMAPPORT);
+	client = clntudp_bufcreate(address, PMAPPROG,
+	    PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (client != (CLIENT *)NULL) {
+		parms.pm_prog = program;
+		parms.pm_vers = version;
+		parms.pm_prot = protocol;
+		parms.pm_port = 0;  /* not needed or used */
+		if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms,
+		    xdr_u_short, &port, tottimeout) != RPC_SUCCESS){
+			rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+		} else if (port == 0) {
+			rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+		}
+		CLNT_DESTROY(client);
+	}
+	(void)close(sock);
+	address->sin_port = 0;
+	return (port);
+}
diff --git a/krb5-1-6/src/lib/rpc/pmap_prot.c b/krb5-1-6/src/lib/rpc/pmap_prot.c
new file mode 100644
index 000000000..0f39f91a4
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/pmap_prot.c
@@ -0,0 +1,55 @@
+/* @(#)pmap_prot.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_prot.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <gssrpc/pmap_prot.h>
+
+
+bool_t
+xdr_pmap(XDR *xdrs, struct pmap *regs)
+{
+
+	if (xdr_rpcprog(xdrs, ®s->pm_prog) && 
+		xdr_rpcvers(xdrs, ®s->pm_vers) && 
+		xdr_rpcprot(xdrs, ®s->pm_prot))
+		return (xdr_rpcport(xdrs, ®s->pm_port));
+	return (FALSE);
+}
diff --git a/krb5-1-6/src/lib/rpc/pmap_prot2.c b/krb5-1-6/src/lib/rpc/pmap_prot2.c
new file mode 100644
index 000000000..13dc1afb6
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/pmap_prot2.c
@@ -0,0 +1,114 @@
+/* @(#)pmap_prot2.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <gssrpc/pmap_prot.h>
+
+
+/* 
+ * What is going on with linked lists? (!)
+ * First recall the link list declaration from pmap_prot.h:
+ *
+ * struct pmaplist {
+ *	struct pmap pml_map;
+ *	struct pmaplist *pml_map;
+ * };
+ *
+ * Compare that declaration with a corresponding xdr declaration that 
+ * is (a) pointer-less, and (b) recursive:
+ *
+ * typedef union switch (bool_t) {
+ * 
+ *	case TRUE: struct {
+ *		struct pmap;
+ * 		pmaplist_t foo;
+ *	};
+ *
+ *	case FALSE: struct {};
+ * } pmaplist_t;
+ *
+ * Notice that the xdr declaration has no nxt pointer while
+ * the C declaration has no bool_t variable.  The bool_t can be
+ * interpreted as ``more data follows me''; if FALSE then nothing
+ * follows this bool_t; if TRUE then the bool_t is followed by
+ * an actual struct pmap, and then (recursively) by the 
+ * xdr union, pamplist_t.  
+ *
+ * This could be implemented via the xdr_union primitive, though this
+ * would cause a one recursive call per element in the list.  Rather than do
+ * that we can ``unwind'' the recursion
+ * into a while loop and do the union arms in-place.
+ *
+ * The head of the list is what the C programmer wishes to past around
+ * the net, yet is the data that the pointer points to which is interesting;
+ * this sounds like a job for xdr_reference!
+ */
+bool_t
+xdr_pmaplist(register XDR *xdrs, register struct pmaplist **rp)
+{
+	/*
+	 * more_elements is pre-computed in case the direction is
+	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
+	 * xdr_bool when the direction is XDR_DECODE.
+	 */
+	bool_t more_elements;
+	register int freeing = (xdrs->x_op == XDR_FREE);
+	register struct pmaplist **next = NULL;
+
+	while (TRUE) {
+		more_elements = (bool_t)(*rp != NULL);
+		if (! xdr_bool(xdrs, &more_elements))
+			return (FALSE);
+		if (! more_elements)
+			return (TRUE);  /* we are done */
+		/*
+		 * the unfortunate side effect of non-recursion is that in
+		 * the case of freeing we must remember the next object
+		 * before we free the current object ...
+		 */
+		if (freeing)
+			next = &((*rp)->pml_next); 
+		if (! xdr_reference(xdrs, (caddr_t *)rp,
+		    (u_int)sizeof(struct pmaplist), xdr_pmap))
+			return (FALSE);
+		rp = (freeing) ? next : &((*rp)->pml_next);
+	}
+}
diff --git a/krb5-1-6/src/lib/rpc/pmap_rmt.c b/krb5-1-6/src/lib/rpc/pmap_rmt.c
new file mode 100644
index 000000000..062a5e19f
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/pmap_rmt.c
@@ -0,0 +1,417 @@
+/* @(#)pmap_rmt.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_prot.h>
+#include <gssrpc/pmap_clnt.h>
+#include <gssrpc/pmap_rmt.h>
+#include <sys/socket.h>
+#ifdef sun
+#include <sys/sockio.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#define MAX_BROADCAST_SIZE 1400
+#include <string.h>
+
+static struct timeval timeout = { 3, 0 };
+
+
+/*
+ * pmapper remote-call-service interface.
+ * This routine is used to call the pmapper remote call service
+ * which will look up a service program in the port maps, and then
+ * remotely call that routine with the given parameters.  This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+pmap_rmtcall(
+	struct sockaddr_in *addr,
+	rpcprog_t prog,
+	rpcvers_t vers,
+	rpcproc_t proc,
+	xdrproc_t xdrargs,
+	caddr_t argsp,
+	xdrproc_t xdrres,
+	caddr_t resp,
+	struct timeval tout,
+	rpcport_t *port_ptr)
+{
+	int sock = -1;
+	register CLIENT *client;
+	struct rmtcallargs a;
+	struct rmtcallres r;
+	enum clnt_stat stat;
+
+	addr->sin_port = htons(PMAPPORT);
+	client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock);
+	if (client != (CLIENT *)NULL) {
+		a.prog = prog;
+		a.vers = vers;
+		a.proc = proc;
+		a.args_ptr = argsp;
+		a.xdr_args = xdrargs;
+		r.port_ptr = port_ptr;
+		r.results_ptr = resp;
+		r.xdr_results = xdrres;
+		stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
+		    xdr_rmtcallres, &r, tout);
+		CLNT_DESTROY(client);
+	} else {
+		stat = RPC_FAILED;
+	}
+	(void)close(sock);
+	addr->sin_port = 0;
+	return (stat);
+}
+
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rmtcall_args(
+	register XDR *xdrs,
+	register struct rmtcallargs *cap)
+{
+	u_int lenposition, argposition, position;
+
+	if (xdr_u_int32(xdrs, &(cap->prog)) &&
+	    xdr_u_int32(xdrs, &(cap->vers)) &&
+	    xdr_u_int32(xdrs, &(cap->proc))) {
+		lenposition = XDR_GETPOS(xdrs);
+		if (! xdr_u_int32(xdrs, &(cap->arglen)))
+		    return (FALSE);
+		argposition = XDR_GETPOS(xdrs);
+		if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
+		    return (FALSE);
+		position = XDR_GETPOS(xdrs);
+		cap->arglen = (uint32_t)position - (uint32_t)argposition;
+		XDR_SETPOS(xdrs, lenposition);
+		if (! xdr_u_int32(xdrs, &(cap->arglen)))
+		    return (FALSE);
+		XDR_SETPOS(xdrs, position);
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rmtcallres(
+	register XDR *xdrs,
+	register struct rmtcallres *crp)
+{
+	caddr_t port_ptr;
+
+	port_ptr = (caddr_t)(void *)crp->port_ptr;
+	if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
+	    xdr_u_int32) && xdr_u_int32(xdrs, &crp->resultslen)) {
+		crp->port_ptr = (uint32_t *)(void *)port_ptr;
+		return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+	}
+	return (FALSE);
+}
+
+
+/*
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these trivial 
+ * routines which only support udp/ip .
+ */
+
+#define GIFCONF_BUFSIZE (256 * sizeof (struct ifconf))
+
+static int
+getbroadcastnets(
+	struct in_addr *addrs,
+	int sock,  /* any valid socket will do */
+	char *buf  /* why allocxate more when we can use existing... */
+	)
+{
+	struct ifconf ifc;
+        struct ifreq ifreq, *ifr;
+	struct sockaddr_in *sockin;
+        int n, i;
+
+        ifc.ifc_len = GIFCONF_BUFSIZE;
+        ifc.ifc_buf = buf;
+	memset (buf, 0, GIFCONF_BUFSIZE);
+        if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+                perror("broadcast: ioctl (get interface configuration)");
+                return (0);
+        }
+        ifr = ifc.ifc_req;
+        for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
+                ifreq = *ifr;
+                if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+                        perror("broadcast: ioctl (get interface flags)");
+                        continue;
+                }
+                if ((ifreq.ifr_flags & IFF_BROADCAST) &&
+		    (ifreq.ifr_flags & IFF_UP) &&
+		    ifr->ifr_addr.sa_family == AF_INET) {
+			sockin = (struct sockaddr_in *)&ifr->ifr_addr;
+#ifdef SIOCGIFBRDADDR   /* 4.3BSD */
+			if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+				addrs[i++].s_addr = INADDR_ANY;
+#if 0 /* this is uuuuugly */
+				addrs[i++] = inet_makeaddr(inet_netof
+#if defined(hpux) || (defined(sun) && defined(__svr4__)) || defined(linux) || (defined(__osf__) && defined(__alpha__))
+							   (sockin->sin_addr),
+#else /* hpux or solaris */
+							   (sockin->sin_addr.s_addr),
+#endif				
+							   INADDR_ANY);
+#endif
+			} else {
+				addrs[i++] = ((struct sockaddr_in*)
+				  &ifreq.ifr_addr)->sin_addr;
+			}
+#else /* 4.2 BSD */
+			addrs[i++] = inet_makeaddr(inet_netof
+			  (sockin->sin_addr.s_addr), INADDR_ANY);
+#endif
+		}
+	}
+	return (i);
+}
+
+enum clnt_stat 
+clnt_broadcast(
+	rpcprog_t	prog,		/* program number */
+	rpcvers_t	vers,		/* version number */
+	rpcproc_t	proc,		/* procedure number */
+	xdrproc_t	xargs,		/* xdr routine for args */
+	caddr_t		argsp,		/* pointer to args */
+	xdrproc_t	xresults,	/* xdr routine for results */
+	caddr_t		resultsp,	/* pointer to results */
+	resultproc_t	eachresult	/* call with each result obtained */
+	)
+{
+	enum clnt_stat stat;
+	AUTH *unix_auth = authunix_create_default();
+	XDR xdr_stream;
+	register XDR *xdrs = &xdr_stream;
+	int outlen, inlen, fromlen, nets;
+	register int sock;
+	int on = 1;
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+#else
+	int readfds;
+	register int mask;
+#endif /* def FD_SETSIZE */
+	register int i;
+	bool_t done = FALSE;
+	register uint32_t xid;
+	rpcport_t port;
+	struct in_addr addrs[20];
+	struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
+	struct rmtcallargs a;
+	struct rmtcallres r;
+	struct rpc_msg msg;
+	struct timeval t, t2; 
+	char outbuf[MAX_BROADCAST_SIZE];
+#ifndef MAX
+#define MAX(A,B) ((A)<(B)?(B):(A))
+#endif
+	char inbuf[MAX (UDPMSGSIZE, GIFCONF_BUFSIZE)];
+
+	/*
+	 * initialization: create a socket, a broadcast address, and
+	 * preserialize the arguments into a send buffer.
+	 */
+	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+		perror("Cannot create socket for broadcast rpc");
+		stat = RPC_CANTSEND;
+		goto done_broad;
+	}
+#ifdef SO_BROADCAST
+	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &on,
+		       sizeof (on)) < 0) {
+		perror("Cannot set socket option SO_BROADCAST");
+		stat = RPC_CANTSEND;
+		goto done_broad;
+	}
+#endif /* def SO_BROADCAST */
+#ifdef FD_SETSIZE
+	FD_ZERO(&mask);
+	FD_SET(sock, &mask);
+#else
+	mask = (1 << sock);
+#endif /* def FD_SETSIZE */
+	nets = getbroadcastnets(addrs, sock, inbuf);
+	memset(&baddr, 0, sizeof (baddr));
+	baddr.sin_family = AF_INET;
+	baddr.sin_port = htons(PMAPPORT);
+	baddr.sin_addr.s_addr = htonl(INADDR_ANY);
+/*	baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
+	(void)gettimeofday(&t, (struct timezone *)0);
+	msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
+	t.tv_usec = 0;
+	msg.rm_direction = CALL;
+	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	msg.rm_call.cb_prog = PMAPPROG;
+	msg.rm_call.cb_vers = PMAPVERS;
+	msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+	msg.rm_call.cb_cred = unix_auth->ah_cred;
+	msg.rm_call.cb_verf = unix_auth->ah_verf;
+	a.prog = prog;
+	a.vers = vers;
+	a.proc = proc;
+	a.xdr_args = xargs;
+	a.args_ptr = argsp;
+	r.port_ptr = &port;
+	r.xdr_results = xresults;
+	r.results_ptr = resultsp;
+	xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
+	if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
+		stat = RPC_CANTENCODEARGS;
+		goto done_broad;
+	}
+	outlen = (int)xdr_getpos(xdrs);
+	xdr_destroy(xdrs);
+	/*
+	 * Basic loop: broadcast a packet and wait a while for response(s).
+	 * The response timeout grows larger per iteration.
+	 */
+	for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
+		for (i = 0; i < nets; i++) {
+			baddr.sin_addr = addrs[i];
+			if (sendto(sock, outbuf, outlen, 0,
+				(struct sockaddr *)&baddr,
+				sizeof (struct sockaddr)) != outlen) {
+				perror("Cannot send broadcast packet");
+				stat = RPC_CANTSEND;
+				goto done_broad;
+			}
+		}
+		if (eachresult == NULL) {
+			stat = RPC_SUCCESS;
+			goto done_broad;
+		}
+	recv_again:
+		msg.acpted_rply.ar_verf = gssrpc__null_auth;
+		msg.acpted_rply.ar_results.where = (caddr_t)&r;
+                msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
+		readfds = mask;
+		t2 = t;
+		switch (select(gssrpc__rpc_dtablesize(), &readfds, (fd_set *)NULL, 
+			       (fd_set *)NULL, &t2)) {
+
+		case 0:  /* timed out */
+			stat = RPC_TIMEDOUT;
+			continue;
+
+		case -1:  /* some kind of error */
+			if (errno == EINTR)
+				goto recv_again;
+			perror("Broadcast select problem");
+			stat = RPC_CANTRECV;
+			goto done_broad;
+
+		}  /* end of select results switch */
+	try_again:
+		fromlen = sizeof(struct sockaddr);
+		inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
+			(struct sockaddr *)&raddr, &fromlen);
+		if (inlen < 0) {
+			if (errno == EINTR)
+				goto try_again;
+			perror("Cannot receive reply to broadcast");
+			stat = RPC_CANTRECV;
+			goto done_broad;
+		}
+		if (inlen < sizeof(uint32_t))
+			goto recv_again;
+		/*
+		 * see if reply transaction id matches sent id.
+		 * If so, decode the results.
+		 */
+		xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
+		if (xdr_replymsg(xdrs, &msg)) {
+			if ((msg.rm_xid == xid) &&
+				(msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+				(msg.acpted_rply.ar_stat == SUCCESS)) {
+				raddr.sin_port = htons((u_short)port);
+				done = (*eachresult)(resultsp, &raddr);
+			}
+			/* otherwise, we just ignore the errors ... */
+		} else {
+#ifdef notdef
+			/* some kind of deserialization problem ... */
+			if (msg.rm_xid == xid)
+				fprintf(stderr, "Broadcast deserialization problem");
+			/* otherwise, just random garbage */
+#endif
+		}
+		xdrs->x_op = XDR_FREE;
+		msg.acpted_rply.ar_results.proc = xdr_void;
+		(void)xdr_replymsg(xdrs, &msg);
+		(void)(*xresults)(xdrs, resultsp);
+		xdr_destroy(xdrs);
+		if (done) {
+			stat = RPC_SUCCESS;
+			goto done_broad;
+		} else {
+			goto recv_again;
+		}
+	}
+done_broad:
+	(void)close(sock);
+	AUTH_DESTROY(unix_auth);
+	return (stat);
+}
+
diff --git a/krb5-1-6/src/lib/rpc/rpc_callmsg.c b/krb5-1-6/src/lib/rpc/rpc_callmsg.c
new file mode 100644
index 000000000..2e4789abb
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/rpc_callmsg.c
@@ -0,0 +1,194 @@
+/* @(#)rpc_callmsg.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include <sys/param.h>
+#include <string.h>
+#include <gssrpc/rpc.h>
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(register XDR *xdrs, register struct rpc_msg *cmsg)
+{
+	register rpc_inline_t *buf;
+	register struct opaque_auth *oa;
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
+			return (FALSE);
+		}
+		if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
+			return (FALSE);
+		}
+		buf = (rpc_inline_t *) XDR_INLINE(xdrs, (int) (
+		        8 * BYTES_PER_XDR_UNIT
+			+ RNDUP(cmsg->rm_call.cb_cred.oa_length)
+			+ 2 * BYTES_PER_XDR_UNIT
+			+ RNDUP(cmsg->rm_call.cb_verf.oa_length)));
+		if (buf != NULL) {
+			IXDR_PUT_LONG(buf, cmsg->rm_xid);
+			IXDR_PUT_ENUM(buf, cmsg->rm_direction);
+			if (cmsg->rm_direction != CALL) {
+				return (FALSE);
+			}
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
+			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+				return (FALSE);
+			}
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
+			IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
+			oa = &cmsg->rm_call.cb_cred;
+			IXDR_PUT_ENUM(buf, oa->oa_flavor);
+			IXDR_PUT_LONG(buf, oa->oa_length);
+			if (oa->oa_length) {
+				memmove((caddr_t)buf, oa->oa_base,
+					oa->oa_length);
+				buf += RNDUP(oa->oa_length) / BYTES_PER_XDR_UNIT;
+			}
+			oa = &cmsg->rm_call.cb_verf;
+			IXDR_PUT_ENUM(buf, oa->oa_flavor);
+			IXDR_PUT_LONG(buf, oa->oa_length);
+			if (oa->oa_length) {
+				memmove((caddr_t)buf, oa->oa_base,
+					oa->oa_length);
+				/* no real need....
+				buf += RNDUP(oa->oa_length) / BYTES_PER_XDR_UNIT;
+				*/
+			}
+			return (TRUE);
+		}
+	}
+	if (xdrs->x_op == XDR_DECODE) {
+		buf = (rpc_inline_t *) XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
+		if (buf != NULL) {
+			cmsg->rm_xid = IXDR_GET_LONG(buf);
+			cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
+			if (cmsg->rm_direction != CALL) {
+				return (FALSE);
+			}
+			cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf);
+			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+				return (FALSE);
+			}
+			cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf);
+			cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
+			cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
+			oa = &cmsg->rm_call.cb_cred;
+			oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+			oa->oa_length = IXDR_GET_LONG(buf);
+			if (oa->oa_length) {
+				if (oa->oa_length > MAX_AUTH_BYTES) {
+					return (FALSE);
+				}
+				if (oa->oa_base == NULL) {
+					oa->oa_base = (caddr_t)
+						mem_alloc(oa->oa_length);
+				}
+				buf = (rpc_inline_t *)
+				   XDR_INLINE(xdrs, (int)RNDUP(oa->oa_length));
+				if (buf == NULL) {
+					if (xdr_opaque(xdrs, oa->oa_base,
+					    oa->oa_length) == FALSE) {
+						return (FALSE);
+					}
+				} else {
+					memmove(oa->oa_base, (caddr_t)buf, 
+						oa->oa_length);
+					/* no real need....
+					buf += RNDUP(oa->oa_length) /
+						BYTES_PER_XDR_UNIT;
+					*/
+				}
+			}
+			oa = &cmsg->rm_call.cb_verf;
+			buf = (rpc_inline_t *)
+			   XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+			if (buf == NULL) {
+				if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
+				    xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
+					return (FALSE);
+				}
+			} else {
+				oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+				oa->oa_length = IXDR_GET_LONG(buf);
+			}
+			if (oa->oa_length) {
+				if (oa->oa_length > MAX_AUTH_BYTES) {
+					return (FALSE);
+				}
+				if (oa->oa_base == NULL) {
+					oa->oa_base = (caddr_t)
+						mem_alloc(oa->oa_length);
+				}
+				buf = (rpc_inline_t *)
+				   XDR_INLINE(xdrs, (int)RNDUP(oa->oa_length));
+				if (buf == NULL) {
+					if (xdr_opaque(xdrs, oa->oa_base,
+					    oa->oa_length) == FALSE) {
+						return (FALSE);
+					}
+				} else {
+					memmove(oa->oa_base, (caddr_t) buf, 
+					    oa->oa_length);
+					/* no real need...
+					buf += RNDUP(oa->oa_length) /
+						BYTES_PER_XDR_UNIT;
+					*/
+				}
+			}
+			return (TRUE);
+		}
+	}
+	if (
+	    xdr_u_int32(xdrs, &(cmsg->rm_xid)) &&
+	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+	    (cmsg->rm_direction == CALL) &&
+	    xdr_u_int32(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+	    (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+	    xdr_u_int32(xdrs, &(cmsg->rm_call.cb_prog)) &&
+	    xdr_u_int32(xdrs, &(cmsg->rm_call.cb_vers)) &&
+	    xdr_u_int32(xdrs, &(cmsg->rm_call.cb_proc)) &&
+	    xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
+	    return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
+	return (FALSE);
+}
+
diff --git a/krb5-1-6/src/lib/rpc/rpc_commondata.c b/krb5-1-6/src/lib/rpc/rpc_commondata.c
new file mode 100644
index 000000000..882b6a4ea
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/rpc_commondata.c
@@ -0,0 +1,47 @@
+/* @(#)rpc_commondata.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#include <gssrpc/rpc.h>
+/*
+ * This file should only contain common data (global data) that is exported
+ * by public interfaces.
+ *
+ * Actually initialized to prevent creation of common blocks, which
+ * can be problematic on some architectures.
+ */
+/* RENAMED: should be _null_auth */
+struct opaque_auth gssrpc__null_auth = {0};
+#ifdef FD_SETSIZE
+fd_set svc_fdset; /* Will be zeroed in data segment */
+int gssrpc_svc_fdset_init = 0;
+#else
+int svc_fds = 0;
+#endif /* def FD_SETSIZE */
+struct rpc_createerr rpc_createerr = {RPC_SUCCESS};
+int svc_maxfd = -1;
diff --git a/krb5-1-6/src/lib/rpc/rpc_dtablesize.c b/krb5-1-6/src/lib/rpc/rpc_dtablesize.c
new file mode 100644
index 000000000..c7d23296f
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/rpc_dtablesize.c
@@ -0,0 +1,62 @@
+/* @(#)rpc_dtablesize.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
+#endif
+
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+
+/*
+ * Cache the result of getdtablesize(), so we don't have to do an
+ * expensive system call every time.
+ */
+int 
+gssrpc__rpc_dtablesize(void)
+{
+	static int size;
+	
+	if (size == 0) {
+#ifdef _SC_OPEN_MAX
+	    size = (int) sysconf(_SC_OPEN_MAX);
+#else	    
+	    size = getdtablesize();
+#endif	    
+
+/* sysconf() can return a number larger than what will fit in an
+   fd_set.  we can't use fd's larger than this, anyway. */
+
+#ifdef FD_SETSIZE
+	    if (size >= FD_SETSIZE)
+		size = FD_SETSIZE-1;
+#endif
+	}
+	return (size);
+}
diff --git a/krb5-1-6/src/lib/rpc/rpc_prot.c b/krb5-1-6/src/lib/rpc/rpc_prot.c
new file mode 100644
index 000000000..17e26b101
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/rpc_prot.c
@@ -0,0 +1,293 @@
+/* @(#)rpc_prot.c	2.3 88/08/07 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_prot.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements the rpc message definition,
+ * its serializer and some common rpc utility routines.
+ * The routines are meant for various implementations of rpc -
+ * they are NOT for the rpc client or rpc service implementations!
+ * Because authentication stuff is easy and is part of rpc, the opaque
+ * routines are also in this program.
+ */
+
+#include <sys/param.h>
+
+#include <gssrpc/rpc.h>
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+/*
+ * XDR an opaque authentication struct
+ * (see auth.h)
+ */
+bool_t
+xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap)
+{
+
+	if (xdr_enum(xdrs, &(ap->oa_flavor)))
+		return (xdr_bytes(xdrs, &ap->oa_base,
+			&ap->oa_length, MAX_AUTH_BYTES));
+	return (FALSE);
+}
+
+/*
+ * XDR a DES block
+ */
+bool_t
+xdr_des_block(XDR *xdrs, des_block *blkp)
+{
+	return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
+}
+
+/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
+
+/*
+ * XDR the MSG_ACCEPTED part of a reply message union
+ */
+bool_t 
+xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar)
+{
+
+	/* personalized union, rather than calling xdr_union */
+	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
+		return (FALSE);
+	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
+		return (FALSE);
+	switch (ar->ar_stat) {
+
+	case SUCCESS:
+		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
+
+	case PROG_MISMATCH:
+		if (! xdr_rpcvers(xdrs, &(ar->ar_vers.low)))
+			return (FALSE);
+		return (xdr_rpcvers(xdrs, &(ar->ar_vers.high)));
+
+	case GARBAGE_ARGS:
+	case SYSTEM_ERR:
+	case PROC_UNAVAIL:
+	case PROG_UNAVAIL:
+		break;
+	}
+	return (TRUE);  /* TRUE => open ended set of problems */
+}
+
+/*
+ * XDR the MSG_DENIED part of a reply message union
+ */
+bool_t 
+xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr)
+{
+
+	/* personalized union, rather than calling xdr_union */
+	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
+		return (FALSE);
+	switch (rr->rj_stat) {
+
+	case RPC_MISMATCH:
+		if (! xdr_rpcvers(xdrs, &(rr->rj_vers.low)))
+			return (FALSE);
+		return (xdr_rpcvers(xdrs, &(rr->rj_vers.high)));
+
+	case AUTH_ERROR:
+		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
+	}
+	return (FALSE);
+}
+
+static struct xdr_discrim reply_dscrm[3] = {
+	{ (int)MSG_ACCEPTED, xdr_accepted_reply },
+	{ (int)MSG_DENIED, xdr_rejected_reply },
+	{ __dontcare__, NULL_xdrproc_t } };
+
+/*
+ * XDR a reply message
+ */
+bool_t
+xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
+{
+	if (
+	    xdr_u_int32(xdrs, &(rmsg->rm_xid)) && 
+	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
+	    (rmsg->rm_direction == REPLY) )
+		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
+		   (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
+	return (FALSE);
+}
+
+
+/*
+ * Serializes the "static part" of a call message header.
+ * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
+ * The rm_xid is not really static, but the user can easily munge on the fly.
+ */
+bool_t
+xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg)
+{
+
+	cmsg->rm_direction = CALL;
+	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+	if (
+	    (xdrs->x_op == XDR_ENCODE) &&
+	    xdr_u_int32(xdrs, &(cmsg->rm_xid)) &&
+	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+	    xdr_rpcvers(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+	    xdr_rpcprog(xdrs, &(cmsg->rm_call.cb_prog)) )
+	    return (xdr_rpcvers(xdrs, &(cmsg->rm_call.cb_vers)));
+	return (FALSE);
+}
+
+/* ************************** Client utility routine ************* */
+
+static void
+accepted(enum accept_stat acpt_stat, struct rpc_err *error)
+{
+
+	switch (acpt_stat) {
+
+	case PROG_UNAVAIL:
+		error->re_status = RPC_PROGUNAVAIL;
+		return;
+
+	case PROG_MISMATCH:
+		error->re_status = RPC_PROGVERSMISMATCH;
+		return;
+
+	case PROC_UNAVAIL:
+		error->re_status = RPC_PROCUNAVAIL;
+		return;
+
+	case GARBAGE_ARGS:
+		error->re_status = RPC_CANTDECODEARGS;
+		return;
+
+	case SYSTEM_ERR:
+		error->re_status = RPC_SYSTEMERROR;
+		return;
+
+	case SUCCESS:
+		error->re_status = RPC_SUCCESS;
+		return;
+	}
+	/* something's wrong, but we don't know what ... */
+	error->re_status = RPC_FAILED;
+	error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
+	error->re_lb.s2 = (int32_t)acpt_stat;
+}
+
+static void 
+rejected(enum reject_stat rjct_stat, struct rpc_err *error)
+{
+
+	switch (rjct_stat) {
+
+	case RPC_MISMATCH:
+		error->re_status = RPC_VERSMISMATCH;
+		return;
+
+	case AUTH_ERROR:
+		error->re_status = RPC_AUTHERROR;
+		return;
+	}
+	/* something's wrong, but we don't know what ... */
+	error->re_status = RPC_FAILED;
+	error->re_lb.s1 = (int32_t)MSG_DENIED;
+	error->re_lb.s2 = (int32_t)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+gssrpc__seterr_reply(struct rpc_msg *msg, struct rpc_err *error)
+{
+
+	/* optimized for normal, SUCCESSful case */
+	switch (msg->rm_reply.rp_stat) {
+
+	case MSG_ACCEPTED:
+		if (msg->acpted_rply.ar_stat == SUCCESS) {
+			error->re_status = RPC_SUCCESS;
+			return;
+		};
+		accepted(msg->acpted_rply.ar_stat, error);
+		break;
+
+	case MSG_DENIED:
+		rejected(msg->rjcted_rply.rj_stat, error);
+		break;
+
+	default:
+		error->re_status = RPC_FAILED;
+		error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
+		break;
+	}
+	switch (error->re_status) {
+
+	case RPC_VERSMISMATCH:
+		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
+		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
+		break;
+
+	case RPC_AUTHERROR:
+		error->re_why = msg->rjcted_rply.rj_why;
+		break;
+
+	case RPC_PROGVERSMISMATCH:
+		error->re_vers.low = msg->acpted_rply.ar_vers.low;
+		error->re_vers.high = msg->acpted_rply.ar_vers.high;
+		break;
+
+	case RPC_FAILED:
+	case RPC_SUCCESS:
+	case RPC_PROGNOTREGISTERED:
+	case RPC_PMAPFAILURE:
+	case RPC_UNKNOWNPROTO:
+	case RPC_UNKNOWNHOST:
+	case RPC_SYSTEMERROR:
+	case RPC_CANTDECODEARGS:
+	case RPC_PROCUNAVAIL:
+	case RPC_PROGUNAVAIL:
+	case RPC_TIMEDOUT:
+	case RPC_CANTRECV:
+	case RPC_CANTSEND:
+	case RPC_CANTDECODERES:
+	case RPC_CANTENCODEARGS:
+	default:
+		break;
+	}
+}
diff --git a/krb5-1-6/src/lib/rpc/svc.c b/krb5-1-6/src/lib/rpc/svc.c
new file mode 100644
index 000000000..93b4fd121
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc.c
@@ -0,0 +1,532 @@
+/* @(#)svc.c	2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc.c, Server-side remote procedure call interface.
+ *
+ * There are two sets of procedures here.  The xprt routines are
+ * for handling transport handles.  The svc routines handle the
+ * list of service routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "autoconf.h"
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_clnt.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef FD_SETSIZE
+static SVCXPRT **xports;
+extern int gssrpc_svc_fdset_init;
+#else
+
+#ifdef NBBY
+#define NOFILE (sizeof(int) * NBBY)
+#else
+#define NOFILE (sizeof(int) * 8)
+#endif
+
+static SVCXPRT *xports[NOFILE];
+#endif /* def FD_SETSIZE */
+
+#define NULL_SVC ((struct svc_callout *)0)
+#define	RQCRED_SIZE	1024		/* this size is excessive */
+
+/*
+ * The services list
+ * Each entry represents a set of procedures (an rpc program).
+ * The dispatch routine takes request structs and runs the
+ * apropriate procedure.
+ */
+static struct svc_callout {
+	struct svc_callout *sc_next;
+	rpcprog_t		    sc_prog;
+	rpcprog_t		    sc_vers;
+	void		    (*sc_dispatch)();
+} *svc_head;
+
+static struct svc_callout *svc_find(rpcprog_t, rpcvers_t,
+				    struct svc_callout **);
+
+static void svc_do_xprt(SVCXPRT *xprt);
+
+/* ***************  SVCXPRT related stuff **************** */
+
+/*
+ * Activate a transport handle.
+ */
+void
+xprt_register(SVCXPRT *xprt)
+{
+	register int sock = xprt->xp_sock;
+
+#ifdef FD_SETSIZE
+	if (gssrpc_svc_fdset_init == 0) {
+		FD_ZERO(&svc_fdset);
+		gssrpc_svc_fdset_init++;
+	}
+	if (xports == NULL) {
+		xports = (SVCXPRT **)
+			mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
+		memset(xports, 0, FD_SETSIZE * sizeof(SVCXPRT *));
+	}
+	if (sock < FD_SETSIZE) {
+		xports[sock] = xprt;
+		FD_SET(sock, &svc_fdset);
+	}
+#else
+	if (sock < NOFILE) {
+		xports[sock] = xprt;
+		svc_fds |= (1 << sock);
+	}
+#endif /* def FD_SETSIZE */
+	if (sock > svc_maxfd)
+		svc_maxfd = sock;
+}
+
+/*
+ * De-activate a transport handle. 
+ */
+void
+xprt_unregister(SVCXPRT *xprt)
+{ 
+	register int sock = xprt->xp_sock;
+
+#ifdef FD_SETSIZE
+	if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) {
+		xports[sock] = (SVCXPRT *)0;
+		FD_CLR(sock, &svc_fdset);
+	}
+#else
+	if ((sock < NOFILE) && (xports[sock] == xprt)) {
+		xports[sock] = (SVCXPRT *)0;
+		svc_fds &= ~(1 << sock);
+	}
+#endif /* def FD_SETSIZE */
+	if (svc_maxfd <= sock) {
+		while ((svc_maxfd > 0) && xports[svc_maxfd] == 0)
+			svc_maxfd--;
+	}
+}
+
+
+/* ********************** CALLOUT list related stuff ************* */
+
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_register(
+	SVCXPRT *xprt,
+	rpcprog_t prog,
+	rpcvers_t vers,
+	void (*dispatch)(),
+	int protocol)
+{
+	struct svc_callout *prev;
+	register struct svc_callout *s;
+
+	if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
+		if (s->sc_dispatch == dispatch)
+			goto pmap_it;  /* he is registering another xptr */
+		return (FALSE);
+	}
+	s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
+	if (s == (struct svc_callout *)0) {
+		return (FALSE);
+	}
+	s->sc_prog = prog;
+	s->sc_vers = vers;
+	s->sc_dispatch = dispatch;
+	s->sc_next = svc_head;
+	svc_head = s;
+pmap_it:
+	/* now register the information with the local binder service */
+	if (protocol) {
+		return (pmap_set(prog, vers, protocol, xprt->xp_port));
+	}
+	return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unregister(
+	rpcprog_t prog,
+	rpcvers_t vers)
+{
+	struct svc_callout *prev;
+	register struct svc_callout *s;
+
+	if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
+		return;
+	if (prev == NULL_SVC) {
+		svc_head = s->sc_next;
+	} else {
+		prev->sc_next = s->sc_next;
+	}
+	s->sc_next = NULL_SVC;
+	mem_free((char *) s, (u_int) sizeof(struct svc_callout));
+	/* now unregister the information with the local binder service */
+	(void)pmap_unset(prog, vers);
+}
+
+/*
+ * Search the callout list for a program number, return the callout
+ * struct.
+ */
+static struct svc_callout *
+svc_find(
+	rpcprog_t prog,
+	rpcvers_t vers,
+	struct svc_callout **prev)
+{
+	register struct svc_callout *s, *p;
+
+	p = NULL_SVC;
+	for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+		if ((s->sc_prog == prog) && (s->sc_vers == vers))
+			goto done;
+		p = s;
+	}
+done:
+	*prev = p;
+	return (s);
+}
+
+/* ******************* REPLY GENERATION ROUTINES  ************ */
+
+/*
+ * Send a reply to an rpc request
+ */
+bool_t
+svc_sendreply(
+	register SVCXPRT *xprt,
+	xdrproc_t xdr_results,
+	caddr_t xdr_location)
+{
+	struct rpc_msg rply; 
+
+	rply.rm_direction = REPLY;  
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf; 
+	rply.acpted_rply.ar_stat = SUCCESS;
+	rply.acpted_rply.ar_results.where = xdr_location;
+	rply.acpted_rply.ar_results.proc = xdr_results;
+	return (SVC_REPLY(xprt, &rply)); 
+}
+
+/*
+ * No procedure error reply
+ */
+void
+svcerr_noproc(register SVCXPRT *xprt)
+{
+	struct rpc_msg rply;
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = PROC_UNAVAIL;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Can't decode args error reply
+ */
+void
+svcerr_decode(register SVCXPRT *xprt)
+{
+	struct rpc_msg rply; 
+
+	rply.rm_direction = REPLY; 
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = GARBAGE_ARGS;
+	SVC_REPLY(xprt, &rply); 
+}
+
+/*
+ * Some system error
+ */
+void
+svcerr_systemerr(register SVCXPRT *xprt)
+{
+	struct rpc_msg rply; 
+
+	rply.rm_direction = REPLY; 
+	rply.rm_reply.rp_stat = MSG_ACCEPTED; 
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = SYSTEM_ERR;
+	SVC_REPLY(xprt, &rply); 
+}
+
+/*
+ * Authentication error reply
+ */
+void
+svcerr_auth(
+	SVCXPRT *xprt,
+	enum auth_stat why)
+{
+	struct rpc_msg rply;
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_DENIED;
+	rply.rjcted_rply.rj_stat = AUTH_ERROR;
+	rply.rjcted_rply.rj_why = why;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Auth too weak error reply
+ */
+void
+svcerr_weakauth(SVCXPRT *xprt)
+{
+
+	svcerr_auth(xprt, AUTH_TOOWEAK);
+}
+
+/*
+ * Program unavailable error reply
+ */
+void 
+svcerr_noprog(register SVCXPRT *xprt)
+{
+	struct rpc_msg rply;  
+
+	rply.rm_direction = REPLY;   
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;  
+	rply.acpted_rply.ar_verf = xprt->xp_verf;  
+	rply.acpted_rply.ar_stat = PROG_UNAVAIL;
+	SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Program version mismatch error reply
+ */
+void  
+svcerr_progvers(
+	register SVCXPRT *xprt,
+	rpcvers_t low_vers,
+	rpcvers_t high_vers)
+{
+	struct rpc_msg rply;
+
+	rply.rm_direction = REPLY;
+	rply.rm_reply.rp_stat = MSG_ACCEPTED;
+	rply.acpted_rply.ar_verf = xprt->xp_verf;
+	rply.acpted_rply.ar_stat = PROG_MISMATCH;
+	rply.acpted_rply.ar_vers.low = low_vers;
+	rply.acpted_rply.ar_vers.high = high_vers;
+	SVC_REPLY(xprt, &rply);
+}
+
+/* ******************* SERVER INPUT STUFF ******************* */
+
+/*
+ * Get server side input from some transport.
+ *
+ * Statement of authentication parameters management:
+ * This function owns and manages all authentication parameters, specifically
+ * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
+ * the "cooked" credentials (rqst->rq_clntcred).
+ * However, this function does not know the structure of the cooked
+ * credentials, so it make the following assumptions: 
+ *   a) the structure is contiguous (no pointers), and
+ *   b) the cred structure size does not exceed RQCRED_SIZE bytes. 
+ * In all events, all three parameters are freed upon exit from this routine.
+ * The storage is trivially management on the call stack in user land, but
+ * is mallocated in kernel land.
+ */
+
+void
+svc_getreq(int rdfds)
+{
+#ifdef FD_SETSIZE
+	fd_set readfds;
+	int	i, mask;
+
+	FD_ZERO(&readfds);
+	for (i=0, mask=1; rdfds; i++, mask <<=1) {
+		if (rdfds & mask)
+			FD_SET(i, &readfds);
+		rdfds &= ~mask;
+	}
+	svc_getreqset(&readfds);
+#else
+	int readfds = rdfds & svc_fds;
+
+	svc_getreqset(&readfds);
+#endif /* def FD_SETSIZE */
+}
+
+#ifdef FD_SETSIZE
+#define FDSET_TYPE fd_set
+#else
+#define FDSET_TYPE int
+#endif
+
+void
+svc_getreqset(FDSET_TYPE *readfds)
+{
+#ifndef FD_SETSIZE
+	int readfds_local = *readfds;
+#endif
+	register SVCXPRT *xprt;
+	register int sock;
+
+#ifdef FD_SETSIZE
+	for (sock = 0; sock <= svc_maxfd; sock++) {
+		if (!FD_ISSET(sock, readfds))
+			continue;
+		/* sock has input waiting */
+		xprt = xports[sock];
+		/* now receive msgs from xprtprt (support batch calls) */
+		svc_do_xprt(xprt);
+	}
+#else
+	for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
+		if ((readfds_local & 1) == 0)
+			continue;
+		/* sock has input waiting */
+		xprt = xports[sock];
+		/* now receive msgs from xprtprt (support batch calls) */
+		svc_do_xprt(xprt);
+	}
+#endif
+}
+
+extern struct svc_auth_ops svc_auth_gss_ops;
+
+static void
+svc_do_xprt(SVCXPRT *xprt)
+{
+	caddr_t rawcred, rawverf, cookedcred;
+	struct rpc_msg msg;
+	struct svc_req r;
+        bool_t no_dispatch;
+	int prog_found;
+	rpcvers_t low_vers;
+	rpcvers_t high_vers;
+	enum xprt_stat stat;
+
+	rawcred = mem_alloc(MAX_AUTH_BYTES);
+	rawverf = mem_alloc(MAX_AUTH_BYTES);
+	cookedcred = mem_alloc(RQCRED_SIZE);
+
+	if (rawcred == NULL || rawverf == NULL || cookedcred == NULL)
+		return;
+
+	msg.rm_call.cb_cred.oa_base = rawcred;
+	msg.rm_call.cb_verf.oa_base = rawverf;
+	r.rq_clntcred = cookedcred;
+
+	do {
+		register struct svc_callout *s;
+		enum auth_stat why;
+
+		if (!SVC_RECV(xprt, &msg))
+			goto call_done;
+
+		/* now find the exported program and call it */
+
+		r.rq_xprt = xprt;
+		r.rq_prog = msg.rm_call.cb_prog;
+		r.rq_vers = msg.rm_call.cb_vers;
+		r.rq_proc = msg.rm_call.cb_proc;
+		r.rq_cred = msg.rm_call.cb_cred;
+
+		no_dispatch = FALSE;
+
+		/* first authenticate the message */
+		why = gssrpc__authenticate(&r, &msg, &no_dispatch);
+		if (why != AUTH_OK) {
+			svcerr_auth(xprt, why);
+			goto call_done;
+		} else if (no_dispatch) {
+			goto call_done;
+		}
+
+		/* now match message with a registered service*/
+		prog_found = FALSE;
+		low_vers = (rpcvers_t) -1L;
+		high_vers = 0;
+		for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+			if (s->sc_prog == r.rq_prog) {
+				if (s->sc_vers == r.rq_vers) {
+					(*s->sc_dispatch)(&r, xprt);
+					goto call_done;
+				}  /* found correct version */
+				prog_found = TRUE;
+				if (s->sc_vers < low_vers)
+					low_vers = s->sc_vers;
+				if (s->sc_vers > high_vers)
+					high_vers = s->sc_vers;
+			}   /* found correct program */
+		}
+		/*
+		 * if we got here, the program or version
+		 * is not served ...
+		 */
+		if (prog_found)
+			svcerr_progvers(xprt,
+					low_vers, high_vers);
+		else
+			svcerr_noprog(xprt);
+		/* Fall through to ... */
+
+	call_done:
+		if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+			SVC_DESTROY(xprt);
+			break;
+		} else if ((xprt->xp_auth != NULL) &&
+			   (xprt->xp_auth->svc_ah_ops != &svc_auth_gss_ops)) {
+			xprt->xp_auth = NULL;
+		}
+	} while (stat == XPRT_MOREREQS);
+
+	mem_free(rawcred, MAX_AUTH_BYTES);
+	mem_free(rawverf, MAX_AUTH_BYTES);
+	mem_free(cookedcred, RQCRED_SIZE);
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_auth.c b/krb5-1-6/src/lib/rpc/svc_auth.c
new file mode 100644
index 000000000..8732619cb
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_auth.c
@@ -0,0 +1,109 @@
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth.c	2.1 88/08/07 4.0 RPCSRC; from 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * svc_auth_nodes.c, Server-side rpc authenticator interface,
+ * *WITHOUT* DES authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <gssrpc/rpc.h>
+
+/*
+ * Server side authenticators are called from authenticate by
+ * using the client auth struct flavor field to index into svcauthsw.
+ * The server auth flavors must implement a routine that looks  
+ * like: 
+ * 
+ *	enum auth_stat
+ *	flavorx_auth(rqst, msg)
+ *		register struct svc_req *rqst; 
+ *		register struct rpc_msg *msg;
+ *
+ */
+
+static struct svcauthsw_type {
+     u_int flavor;
+     enum auth_stat (*authenticator)(struct svc_req *, struct rpc_msg *,
+				     bool_t *);
+} svcauthsw[] = {
+     {AUTH_GSSAPI, gssrpc__svcauth_gssapi},	/* AUTH_GSSAPI */
+     {AUTH_NONE, gssrpc__svcauth_none},		/* AUTH_NONE */
+#if 0
+     {AUTH_GSSAPI_COMPAT, gssrpc__svcauth_gssapi}, /* AUTH_GSSAPI_COMPAT */
+#endif
+     {AUTH_UNIX, gssrpc__svcauth_unix},		/* AUTH_UNIX */
+     {AUTH_SHORT, gssrpc__svcauth_short},	/* AUTH_SHORT */
+     {RPCSEC_GSS, gssrpc__svcauth_gss}		/* RPCSEC_GSS */
+};
+static int svcauthnum = sizeof(svcauthsw) / sizeof(struct svcauthsw_type);
+
+/*
+ * The call rpc message, msg has been obtained from the wire.  The msg contains
+ * the raw form of credentials and verifiers.  authenticate returns AUTH_OK
+ * if the msg is successfully authenticated.  If AUTH_OK then the routine also
+ * does the following things:
+ * set rqst->rq_xprt->verf to the appropriate response verifier;
+ * sets rqst->rq_client_cred to the "cooked" form of the credentials.
+ *
+ * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * its length is set appropriately.
+ *
+ * The caller still owns and is responsible for msg->u.cmb.cred and
+ * msg->u.cmb.verf.  The authentication system retains ownership of
+ * rqst->rq_client_cred, the cooked credentials.
+ */
+enum auth_stat
+gssrpc__authenticate(
+	register struct svc_req *rqst,
+	struct rpc_msg *msg,
+	bool_t *no_dispatch)
+{
+	register int cred_flavor, i;
+
+	rqst->rq_cred = msg->rm_call.cb_cred;
+	rqst->rq_xprt->xp_verf.oa_flavor = gssrpc__null_auth.oa_flavor;
+	rqst->rq_xprt->xp_verf.oa_length = 0;
+	cred_flavor = rqst->rq_cred.oa_flavor;
+	*no_dispatch = FALSE;
+	for (i = 0; i < svcauthnum; i++) {
+	     if (cred_flavor == svcauthsw[i].flavor &&
+		 svcauthsw[i].authenticator != NULL) {
+		  return ((*(svcauthsw[i].authenticator))(rqst,
+							  msg,
+							  no_dispatch));
+	     }
+	}
+	
+	return (AUTH_REJECTEDCRED);
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_auth_gss.c b/krb5-1-6/src/lib/rpc/svc_auth_gss.c
new file mode 100644
index 000000000..83ab9754a
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_auth_gss.c
@@ -0,0 +1,732 @@
+/*
+  svc_auth_gss.c
+  
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of the University nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Id: svc_auth_gss.c,v 1.28 2002/10/15 21:29:36 kwc Exp
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/auth_gssapi.h>
+#ifdef HAVE_HEIMDAL
+#include <gssapi.h>
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#else
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#endif
+
+#ifdef DEBUG_GSSAPI
+int svc_debug_gss = DEBUG_GSSAPI;
+#endif
+
+#ifdef SPKM
+
+#ifndef OID_EQ
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    ((o1)->elements != 0) && ((o2)->elements != 0) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+#define OID_EQ 1
+#endif /* OID_EQ */
+
+extern const gss_OID_desc * const gss_mech_spkm3;
+
+#endif /* SPKM */
+
+extern SVCAUTH svc_auth_none;
+
+/*
+ * from mit-krb5-1.2.1 mechglue/mglueP.h:
+ * Array of context IDs typed by mechanism OID
+ */
+typedef struct gss_union_ctx_id_t {
+  gss_OID     mech_type;
+  gss_ctx_id_t    internal_ctx_id;
+} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
+
+
+static auth_gssapi_log_badauth_func log_badauth = NULL;
+static caddr_t log_badauth_data = NULL;
+static auth_gssapi_log_badverf_func log_badverf = NULL;
+static caddr_t log_badverf_data = NULL;
+static auth_gssapi_log_miscerr_func log_miscerr = NULL;
+static caddr_t log_miscerr_data = NULL;
+
+#define LOG_MISCERR(arg) if (log_miscerr) \
+        (*log_miscerr)(rqst, msg, arg, log_miscerr_data)
+
+static bool_t	svcauth_gss_destroy(SVCAUTH *);
+static bool_t   svcauth_gss_wrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
+static bool_t   svcauth_gss_unwrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
+
+static bool_t	svcauth_gss_nextverf(struct svc_req *, u_int);
+
+struct svc_auth_ops svc_auth_gss_ops = {
+	svcauth_gss_wrap,
+	svcauth_gss_unwrap,
+	svcauth_gss_destroy
+};
+
+struct svc_rpc_gss_data {
+	bool_t			established;	/* context established */
+	gss_ctx_id_t		ctx;		/* context id */
+	struct rpc_gss_sec	sec;		/* security triple */
+	gss_buffer_desc		cname;		/* GSS client name */
+	u_int			seq;		/* sequence number */
+	u_int			win;		/* sequence window */
+	u_int			seqlast;	/* last sequence number */
+	uint32_t		seqmask;	/* bitmask of seqnums */
+	gss_name_t		client_name;	/* unparsed name string */
+	gss_buffer_desc		checksum;	/* so we can free it */
+};
+
+#define SVCAUTH_PRIVATE(auth) \
+	(*(struct svc_rpc_gss_data **)&(auth)->svc_ah_private)
+
+/* Global server credentials. */
+gss_cred_id_t		svcauth_gss_creds;
+static gss_name_t	svcauth_gss_name = NULL;
+
+bool_t
+svcauth_gss_set_svc_name(gss_name_t name)
+{
+	OM_uint32	maj_stat, min_stat;
+
+	log_debug("in svcauth_gss_set_svc_name()");
+
+	if (svcauth_gss_name != NULL) {
+		maj_stat = gss_release_name(&min_stat, &svcauth_gss_name);
+
+		if (maj_stat != GSS_S_COMPLETE) {
+			log_status("gss_release_name", maj_stat, min_stat);
+			return (FALSE);
+		}
+		svcauth_gss_name = NULL;
+	}
+	if (svcauth_gss_name == GSS_C_NO_NAME)
+		return (TRUE);
+
+	maj_stat = gss_duplicate_name(&min_stat, name, &svcauth_gss_name);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_duplicate_name", maj_stat, min_stat);
+		return (FALSE);
+	}
+
+	return (TRUE);
+}
+
+static bool_t
+svcauth_gss_import_name(char *service)
+{
+	gss_name_t	name;
+	gss_buffer_desc	namebuf;
+	OM_uint32	maj_stat, min_stat;
+
+	log_debug("in svcauth_gss_import_name()");
+
+	namebuf.value = service;
+	namebuf.length = strlen(service);
+
+	maj_stat = gss_import_name(&min_stat, &namebuf,
+				   (gss_OID)gss_nt_service_name, &name);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_import_name", maj_stat, min_stat);
+		return (FALSE);
+	}
+	if (svcauth_gss_set_svc_name(name) != TRUE) {
+		gss_release_name(&min_stat, &name);
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+static bool_t
+svcauth_gss_acquire_cred(void)
+{
+	OM_uint32	maj_stat, min_stat;
+
+	log_debug("in svcauth_gss_acquire_cred()");
+
+	maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0,
+				    GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+				    &svcauth_gss_creds, NULL, NULL);
+	
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_acquire_cred", maj_stat, min_stat);
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+static bool_t
+svcauth_gss_release_cred(void)
+{
+	OM_uint32	maj_stat, min_stat;
+	
+	log_debug("in svcauth_gss_release_cred()");
+	
+	maj_stat = gss_release_cred(&min_stat, &svcauth_gss_creds);
+	
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_release_cred", maj_stat, min_stat);
+		return (FALSE);
+	}
+	
+	svcauth_gss_creds = NULL;
+	
+	return (TRUE);
+}
+
+static bool_t
+svcauth_gss_accept_sec_context(struct svc_req *rqst,
+			       struct rpc_gss_init_res *gr)
+{
+	struct svc_rpc_gss_data	*gd;
+	struct rpc_gss_cred	*gc;
+	gss_buffer_desc		 recv_tok, seqbuf;
+	gss_OID			 mech;
+	OM_uint32		 maj_stat = 0, min_stat = 0, ret_flags, seq;
+
+	log_debug("in svcauth_gss_accept_context()");
+	
+	gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
+	gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
+	memset(gr, 0, sizeof(*gr));
+
+	/* Deserialize arguments. */
+	memset(&recv_tok, 0, sizeof(recv_tok));
+	
+	if (!svc_getargs(rqst->rq_xprt, xdr_rpc_gss_init_args,
+			 (caddr_t)&recv_tok))
+		return (FALSE);
+
+	gr->gr_major = gss_accept_sec_context(&gr->gr_minor,
+					      &gd->ctx,
+					      svcauth_gss_creds,
+					      &recv_tok,
+					      GSS_C_NO_CHANNEL_BINDINGS,
+					      &gd->client_name,
+					      &mech,
+					      &gr->gr_token,
+					      &ret_flags,
+					      NULL,
+					      NULL);
+
+	svc_freeargs(rqst->rq_xprt, xdr_rpc_gss_init_args, (caddr_t)&recv_tok);
+
+	log_status("accept_sec_context", gr->gr_major, gr->gr_minor);
+	if (gr->gr_major != GSS_S_COMPLETE &&
+	    gr->gr_major != GSS_S_CONTINUE_NEEDED) {
+		if (log_badauth != NULL) {
+			(*log_badauth)(gr->gr_major,
+				       gr->gr_minor,
+				       &rqst->rq_xprt->xp_raddr,
+				       log_badauth_data);
+		}
+		gd->ctx = GSS_C_NO_CONTEXT;
+		goto errout;
+	}
+	/*
+	 * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, 
+	 * one to the mechanism oid, one to the internal_ctx_id
+	 */
+	if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) {
+		fprintf(stderr, "svcauth_gss_accept_context: out of memory\n");
+		goto errout;
+	}
+	memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
+	gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);
+
+	/* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version...  */
+	gr->gr_win = sizeof(gd->seqmask) * 8;
+	
+	/* Save client info. */
+	gd->sec.mech = mech;
+	gd->sec.qop = GSS_C_QOP_DEFAULT;
+	gd->sec.svc = gc->gc_svc;
+	gd->seq = gc->gc_seq;
+	gd->win = gr->gr_win;
+
+	if (gr->gr_major == GSS_S_COMPLETE) {
+#ifdef SPKM
+		/* spkm3: no src_name (anonymous) */
+		if(!g_OID_equal(gss_mech_spkm3, mech)) {
+#endif
+		    maj_stat = gss_display_name(&min_stat, gd->client_name,
+					    &gd->cname, &gd->sec.mech);
+#ifdef SPKM
+		}	
+#endif
+		if (maj_stat != GSS_S_COMPLETE) {
+			log_status("display_name", maj_stat, min_stat);
+			goto errout;
+		}
+#ifdef DEBUG
+#ifdef HAVE_HEIMDAL
+		log_debug("accepted context for %.*s with "
+			  "<mech {}, qop %d, svc %d>",
+			  gd->cname.length, (char *)gd->cname.value,
+			  gd->sec.qop, gd->sec.svc);
+#else
+		{
+			gss_buffer_desc mechname;
+
+			gss_oid_to_str(&min_stat, mech, &mechname);
+			
+			log_debug("accepted context for %.*s with "
+				  "<mech %.*s, qop %d, svc %d>",
+				  gd->cname.length, (char *)gd->cname.value,
+				  mechname.length, (char *)mechname.value,
+				  gd->sec.qop, gd->sec.svc);
+
+			gss_release_buffer(&min_stat, &mechname);
+		}
+#endif
+#endif /* DEBUG */
+		seq = htonl(gr->gr_win);
+		seqbuf.value = &seq;
+		seqbuf.length = sizeof(seq);
+
+		gss_release_buffer(&min_stat, &gd->checksum);
+		maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT,
+				    &seqbuf, &gd->checksum);
+
+		if (maj_stat != GSS_S_COMPLETE) {
+			goto errout;
+		}
+		
+		
+		rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
+		rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value;
+		rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length;
+	}
+	return (TRUE);
+errout:
+	gss_release_buffer(&min_stat, &gr->gr_token);
+	return (FALSE);
+}
+
+static bool_t
+svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct rpc_msg *msg)
+{
+	struct opaque_auth	*oa;
+	gss_buffer_desc		 rpcbuf, checksum;
+	OM_uint32		 maj_stat, min_stat, qop_state;
+	u_char			 rpchdr[128];
+	int32_t			*buf;
+
+	log_debug("in svcauth_gss_validate()");
+	
+	memset(rpchdr, 0, sizeof(rpchdr));
+
+	/* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */
+	oa = &msg->rm_call.cb_cred;
+	if (oa->oa_length > MAX_AUTH_BYTES)
+		return (FALSE);
+
+	/* 8 XDR units from the IXDR macro calls. */
+	if (sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT +
+			      RNDUP(oa->oa_length)))
+		return (FALSE);
+
+	buf = (int32_t *)(void *)rpchdr;
+	IXDR_PUT_LONG(buf, msg->rm_xid);
+	IXDR_PUT_ENUM(buf, msg->rm_direction);
+	IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers);
+	IXDR_PUT_LONG(buf, msg->rm_call.cb_prog);
+	IXDR_PUT_LONG(buf, msg->rm_call.cb_vers);
+	IXDR_PUT_LONG(buf, msg->rm_call.cb_proc);
+	IXDR_PUT_ENUM(buf, oa->oa_flavor);
+	IXDR_PUT_LONG(buf, oa->oa_length);
+	if (oa->oa_length) {
+		memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
+		buf += RNDUP(oa->oa_length) / sizeof(int32_t);
+	}
+	rpcbuf.value = rpchdr;
+	rpcbuf.length = (u_char *)buf - rpchdr;
+
+	checksum.value = msg->rm_call.cb_verf.oa_base;
+	checksum.length = msg->rm_call.cb_verf.oa_length;
+	
+	maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum,
+				  &qop_state);
+	
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_verify_mic", maj_stat, min_stat);
+		if (log_badverf != NULL)
+			(*log_badverf)(gd->client_name,
+			       svcauth_gss_name,
+			       rqst, msg, log_badverf_data);
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
+static bool_t
+svcauth_gss_nextverf(struct svc_req *rqst, u_int num)
+{
+	struct svc_rpc_gss_data	*gd;
+	gss_buffer_desc		 signbuf;
+	OM_uint32		 maj_stat, min_stat;
+
+	log_debug("in svcauth_gss_nextverf()");
+
+	if (rqst->rq_xprt->xp_auth == NULL)
+		return (FALSE);
+	
+	gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
+
+	gss_release_buffer(&min_stat, &gd->checksum);
+
+	signbuf.value = #
+	signbuf.length = sizeof(num);
+
+	maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
+			       &signbuf, &gd->checksum);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		log_status("gss_get_mic", maj_stat, min_stat);
+		return (FALSE);
+	}
+	rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
+	rqst->rq_xprt->xp_verf.oa_base = (caddr_t)gd->checksum.value;
+	rqst->rq_xprt->xp_verf.oa_length = (u_int)gd->checksum.length;
+	
+	return (TRUE);
+}
+
+enum auth_stat
+gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
+	bool_t *no_dispatch)
+{
+	enum auth_stat		 retstat;
+	XDR	 		 xdrs;
+	SVCAUTH			*auth;
+	struct svc_rpc_gss_data	*gd;
+	struct rpc_gss_cred	*gc;
+	struct rpc_gss_init_res	 gr;
+	int			 call_stat, offset;
+	OM_uint32		 min_stat;
+
+	log_debug("in svcauth_gss()");
+	
+	/* Initialize reply. */
+	rqst->rq_xprt->xp_verf = gssrpc__null_auth;
+
+	/* Allocate and set up server auth handle. */
+	if (rqst->rq_xprt->xp_auth == NULL ||
+	    rqst->rq_xprt->xp_auth == &svc_auth_none) {
+		if ((auth = calloc(sizeof(*auth), 1)) == NULL) {
+			fprintf(stderr, "svcauth_gss: out_of_memory\n");
+			return (AUTH_FAILED);
+		}
+		if ((gd = calloc(sizeof(*gd), 1)) == NULL) {
+			fprintf(stderr, "svcauth_gss: out_of_memory\n");
+			return (AUTH_FAILED);
+		}
+		auth->svc_ah_ops = &svc_auth_gss_ops;
+		SVCAUTH_PRIVATE(auth) = gd;
+		rqst->rq_xprt->xp_auth = auth;
+	}
+	else gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
+
+	log_debug("xp_auth=%p, gd=%p", rqst->rq_xprt->xp_auth, gd);
+
+	/* Deserialize client credentials. */
+	if (rqst->rq_cred.oa_length <= 0)
+		return (AUTH_BADCRED);
+	
+	gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
+	memset(gc, 0, sizeof(*gc));
+
+	log_debug("calling xdrmem_create()");
+	log_debug("oa_base=%p, oa_length=%u", rqst->rq_cred.oa_base,
+		  rqst->rq_cred.oa_length);
+	xdrmem_create(&xdrs, rqst->rq_cred.oa_base,
+		      rqst->rq_cred.oa_length, XDR_DECODE);
+	log_debug("xdrmem_create() returned");
+	
+	if (!xdr_rpc_gss_cred(&xdrs, gc)) {
+		log_debug("xdr_rpc_gss_cred() failed");
+		XDR_DESTROY(&xdrs);
+		return (AUTH_BADCRED);
+	}
+	XDR_DESTROY(&xdrs);
+
+	retstat = AUTH_FAILED;
+
+#define ret_freegc(code) do { retstat = code; goto freegc; } while (0)
+
+	/* Check version. */
+	if (gc->gc_v != RPCSEC_GSS_VERSION)
+		ret_freegc (AUTH_BADCRED);
+
+	/* Check RPCSEC_GSS service. */
+	if (gc->gc_svc != RPCSEC_GSS_SVC_NONE &&
+	    gc->gc_svc != RPCSEC_GSS_SVC_INTEGRITY &&
+	    gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY)
+		ret_freegc (AUTH_BADCRED);
+
+	/* Check sequence number. */
+	if (gd->established) {
+		if (gc->gc_seq > MAXSEQ)
+			ret_freegc (RPCSEC_GSS_CTXPROBLEM);
+
+		if ((offset = gd->seqlast - gc->gc_seq) < 0) {
+			gd->seqlast = gc->gc_seq;
+			offset = 0 - offset;
+			gd->seqmask <<= offset;
+			offset = 0;
+		}
+		else if (offset >= gd->win || (gd->seqmask & (1 << offset))) {
+			*no_dispatch = 1;
+			ret_freegc (RPCSEC_GSS_CTXPROBLEM);
+		}
+		gd->seq = gc->gc_seq;
+		gd->seqmask |= (1 << offset);
+	}
+	
+	if (gd->established) {
+		rqst->rq_clntname = (char *)gd->client_name;
+		rqst->rq_svccred = (char *)gd->ctx;
+	}
+
+	/* Handle RPCSEC_GSS control procedure. */
+	switch (gc->gc_proc) {
+
+	case RPCSEC_GSS_INIT:
+	case RPCSEC_GSS_CONTINUE_INIT:
+		if (rqst->rq_proc != NULLPROC)
+			ret_freegc (AUTH_FAILED);		/* XXX ? */
+
+		if (!svcauth_gss_acquire_cred())
+			ret_freegc (AUTH_FAILED);
+		
+		if (!svcauth_gss_accept_sec_context(rqst, &gr))
+			ret_freegc (AUTH_REJECTEDCRED);
+
+		if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) {
+			gss_release_buffer(&min_stat, &gr.gr_token);
+			mem_free(gr.gr_ctx.value,
+				 sizeof(gss_union_ctx_id_desc));
+			ret_freegc (AUTH_FAILED);
+		}
+		*no_dispatch = TRUE;
+		
+		call_stat = svc_sendreply(rqst->rq_xprt, xdr_rpc_gss_init_res,
+					  (caddr_t)&gr);
+
+		gss_release_buffer(&min_stat, &gr.gr_token);
+		gss_release_buffer(&min_stat, &gd->checksum);
+		mem_free(gr.gr_ctx.value, sizeof(gss_union_ctx_id_desc));
+		if (!call_stat)
+			ret_freegc (AUTH_FAILED);
+
+		if (gr.gr_major == GSS_S_COMPLETE)
+			gd->established = TRUE;
+		
+		break;
+		
+	case RPCSEC_GSS_DATA:
+		if (!svcauth_gss_validate(rqst, gd, msg))
+			ret_freegc (RPCSEC_GSS_CREDPROBLEM);
+		
+		if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq)))
+ 			ret_freegc (AUTH_FAILED);
+		break;
+		
+	case RPCSEC_GSS_DESTROY:
+		if (rqst->rq_proc != NULLPROC)
+			ret_freegc (AUTH_FAILED);		/* XXX ? */
+
+		if (!svcauth_gss_validate(rqst, gd, msg))
+			ret_freegc (RPCSEC_GSS_CREDPROBLEM);
+		
+		if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq)))
+			ret_freegc (AUTH_FAILED);
+
+		*no_dispatch = TRUE;
+
+		call_stat = svc_sendreply(rqst->rq_xprt,
+					  xdr_void, (caddr_t)NULL);
+
+		log_debug("sendreply in destroy: %d", call_stat);
+
+		if (!svcauth_gss_release_cred())
+			ret_freegc (AUTH_FAILED);
+			
+		SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth);
+		rqst->rq_xprt->xp_auth = &svc_auth_none;
+
+		break;
+
+	default:
+		ret_freegc (AUTH_REJECTEDCRED);
+		break;
+	}
+	retstat = AUTH_OK;
+freegc:
+	xdr_free(xdr_rpc_gss_cred, gc);
+	log_debug("returning %d from svcauth_gss()", retstat);
+	return (retstat);
+}
+
+static bool_t
+svcauth_gss_destroy(SVCAUTH *auth)
+{
+	struct svc_rpc_gss_data	*gd;
+	OM_uint32		 min_stat;
+
+	log_debug("in svcauth_gss_destroy()");
+	
+	gd = SVCAUTH_PRIVATE(auth);
+	
+	gss_delete_sec_context(&min_stat, &gd->ctx, GSS_C_NO_BUFFER);
+	gss_release_buffer(&min_stat, &gd->cname);
+	gss_release_buffer(&min_stat, &gd->checksum);
+
+	if (gd->client_name)
+		gss_release_name(&min_stat, &gd->client_name);
+
+	mem_free(gd, sizeof(*gd));
+	mem_free(auth, sizeof(*auth));
+	
+	return (TRUE);
+}
+
+static bool_t
+svcauth_gss_wrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
+{
+	struct svc_rpc_gss_data	*gd;
+	
+	log_debug("in svcauth_gss_wrap()");
+
+	gd = SVCAUTH_PRIVATE(auth);
+	
+	if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
+		return ((*xdr_func)(xdrs, xdr_ptr));
+	}
+	return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
+				 gd->ctx, gd->sec.qop,
+				 gd->sec.svc, gd->seq));
+}
+
+static bool_t
+svcauth_gss_unwrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
+{
+	struct svc_rpc_gss_data	*gd;
+
+	log_debug("in svcauth_gss_unwrap()");
+	
+	gd = SVCAUTH_PRIVATE(auth);
+
+	if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
+		return ((*xdr_func)(xdrs, xdr_ptr));
+	}
+	return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
+				 gd->ctx, gd->sec.qop,
+				 gd->sec.svc, gd->seq));
+}
+
+char *
+svcauth_gss_get_principal(SVCAUTH *auth)
+{
+	struct svc_rpc_gss_data *gd;
+	char *pname;
+
+	gd = SVCAUTH_PRIVATE(auth);
+
+	if (gd->cname.length == 0)
+		return (NULL);
+
+	if ((pname = malloc(gd->cname.length + 1)) == NULL)
+		return (NULL);
+
+	memcpy(pname, gd->cname.value, gd->cname.length);
+	pname[gd->cname.length] = '\0';
+
+	return (pname);
+}
+
+/*
+ * Function: svcauth_gss_set_log_badauth_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void svcauth_gss_set_log_badauth_func(
+	auth_gssapi_log_badauth_func func,
+	caddr_t data)
+{
+	log_badauth = func;
+	log_badauth_data = data;
+}
+
+/*
+ * Function: svcauth_gss_set_log_badverf_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void svcauth_gss_set_log_badverf_func(
+	auth_gssapi_log_badverf_func func,
+	caddr_t data)
+{
+	log_badverf = func;
+	log_badverf_data = data;
+}
+
+/*
+ * Function: svcauth_gss_set_log_miscerr_func
+ *
+ * Purpose: sets the logging function called when a miscellaneous
+ * AUTH_GSSAPI error occurs
+ *
+ * See functional specifications.
+ */
+void svcauth_gss_set_log_miscerr_func(
+	auth_gssapi_log_miscerr_func func,
+	caddr_t data)
+{
+	log_miscerr = func;
+	log_miscerr_data = data;
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_auth_gssapi.c b/krb5-1-6/src/lib/rpc/svc_auth_gssapi.c
new file mode 100644
index 000000000..a18ab6815
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_auth_gssapi.c
@@ -0,0 +1,1096 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ *
+ */
+
+/*
+ * svc_auth_gssapi.c
+ * Handles the GSS-API flavor authentication parameters on the service
+ * side of RPC.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <gssrpc/rpc.h>
+#include <sys/stat.h>
+
+#include <gssapi/gssapi_generic.h>
+#include <gssrpc/auth_gssapi.h>
+
+#ifdef GSS_BACKWARD_HACK
+#include <gssapi/gssapi_krb5.h>
+#endif
+
+#ifdef GSSAPI_KRB5
+/* This is here for the krb5_error_code typedef and the
+   KRB5KRB_AP_WRONG_PRINC #define.*/
+#include <krb5.h>
+#endif
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include <time.h>
+
+#define INITIATION_TIMEOUT 60*15 /* seconds until partially created */
+				 /* context is destroed */
+#define INDEF_EXPIRE 60*60*24	/* seconds until an context with no */
+                                /* expiration time is expired */
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int svc_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (svc_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+	if (svc_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+typedef struct _svc_auth_gssapi_data {
+     bool_t established;
+
+     gss_ctx_id_t context;
+     gss_name_t client_name, server_name;
+     gss_cred_id_t server_creds;
+
+     uint32_t expiration;
+     uint32_t seq_num;
+     uint32_t key;
+
+     SVCAUTH svcauth;
+
+     /* kludge to free verifiers on next call */
+     gss_buffer_desc prev_verf;
+} svc_auth_gssapi_data;
+
+#define SVCAUTH_PRIVATE(auth) \
+     ((svc_auth_gssapi_data *)(auth)->svc_ah_private)
+
+static bool_t	svc_auth_gssapi_wrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
+static bool_t	svc_auth_gssapi_unwrap(SVCAUTH *, XDR *, xdrproc_t, caddr_t);
+static bool_t	svc_auth_gssapi_destroy(SVCAUTH *);
+
+static svc_auth_gssapi_data *create_client(void);
+static svc_auth_gssapi_data *get_client
+       (gss_buffer_t client_handle);
+static void destroy_client
+       (svc_auth_gssapi_data *client_data);
+static void clean_client(void), cleanup(void);
+static void client_expire
+       (svc_auth_gssapi_data *client_data, uint32_t exp);
+static void dump_db (char *msg);
+
+struct svc_auth_ops svc_auth_gssapi_ops = {
+     svc_auth_gssapi_wrap,
+     svc_auth_gssapi_unwrap,
+     svc_auth_gssapi_destroy
+};
+
+/*
+ * Globals!  Eeek!  Run for the hills!
+ */
+static gss_cred_id_t *server_creds_list = NULL;
+static gss_name_t *server_name_list = NULL;
+static int server_creds_count = 0;
+
+static auth_gssapi_log_badauth_func log_badauth = NULL;
+static caddr_t log_badauth_data = NULL;
+static auth_gssapi_log_badverf_func log_badverf = NULL;
+static caddr_t log_badverf_data = NULL;
+static auth_gssapi_log_miscerr_func log_miscerr = NULL;
+static caddr_t log_miscerr_data = NULL;
+
+#define LOG_MISCERR(arg) if (log_miscerr) \
+	(*log_miscerr)(rqst, msg, arg, log_miscerr_data)
+
+typedef struct _client_list {
+     svc_auth_gssapi_data *client;
+     struct _client_list *next;
+} client_list;
+
+static client_list *clients = NULL;
+
+
+enum auth_stat gssrpc__svcauth_gssapi(
+     register struct svc_req *rqst,
+     register struct rpc_msg *msg,
+     bool_t *no_dispatch)
+{
+     XDR xdrs;
+     auth_gssapi_creds creds;
+     auth_gssapi_init_arg call_arg;
+     auth_gssapi_init_res call_res;
+     gss_buffer_desc output_token, in_buf, out_buf;
+     gss_cred_id_t server_creds;
+     struct gss_channel_bindings_struct bindings, *bindp;
+     OM_uint32 gssstat, minor_stat, time_rec;
+     struct opaque_auth *cred, *verf;
+     svc_auth_gssapi_data *client_data;
+     int i;
+     enum auth_stat ret;
+     OM_uint32 ret_flags;
+     uint32_t seq_num;
+
+     PRINTF(("svcauth_gssapi: starting\n"));
+     
+     /* clean up expired entries */
+     clean_client();
+
+     /* use AUTH_NONE until there is a client_handle */
+     rqst->rq_xprt->xp_auth = &svc_auth_none;
+     
+     memset((char *) &call_res, 0, sizeof(call_res));
+     creds.client_handle.length = 0;
+     creds.client_handle.value = NULL;
+     
+     cred = &msg->rm_call.cb_cred;
+     verf = &msg->rm_call.cb_verf;
+     
+     if (cred->oa_length == 0) {
+	  PRINTF(("svcauth_gssapi: empty creds, failing\n"));
+	  LOG_MISCERR("empty client credentials");
+	  ret = AUTH_BADCRED;
+	  goto error;
+     }
+
+     PRINTF(("svcauth_gssapi: decoding credentials\n"));
+     xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE); 
+     memset((char *) &creds, 0, sizeof(creds));
+     if (! xdr_authgssapi_creds(&xdrs, &creds)) {
+	  PRINTF(("svcauth_gssapi: failed decoding creds\n"));
+	  LOG_MISCERR("protocol error in client credentials");
+	  xdr_free(xdr_authgssapi_creds, &creds);
+	  XDR_DESTROY(&xdrs);
+	  ret = AUTH_BADCRED;
+	  goto error;
+     }
+     XDR_DESTROY(&xdrs);
+
+     PRINTF(("svcauth_gssapi: got credentials, version %d, client_handle len %d\n",
+	     creds.version, (int) creds.client_handle.length));
+
+     if (creds.version != 2) {
+ 	  PRINTF(("svcauth_gssapi: bad credential version\n"));
+ 	  LOG_MISCERR("unsupported client credentials version");
+ 	  ret = AUTH_BADCRED;
+ 	  goto error;
+     }
+
+#ifdef DEBUG_GSSAPI
+     if (svc_debug_gssapi) {
+	  if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_EXIT) {
+	       PRINTF(("svcauth_gssapi: GSSAPI_EXIT, cleaning up\n"));
+	       svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+	       xdr_free(xdr_authgssapi_creds, &creds);
+	       cleanup();
+	       exit(0);
+	  }
+     }
+#endif
+	  
+     /*
+      * If this is an auth_msg and proc is GSSAPI_INIT, then create a
+      * client handle for this client.  Otherwise, look up the
+      * existing handle.
+      */
+     if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_INIT) {
+	  if (creds.client_handle.length != 0) {
+	       PRINTF(("svcauth_gssapi: non-empty handle on GSSAPI_INIT\n"));
+	       LOG_MISCERR("protocol error in client handle");
+	       ret = AUTH_FAILED;
+	       goto error;
+	  }
+	       
+	  PRINTF(("svcauth_gssapi: GSSAPI_INIT, creating client.\n"));
+	  
+	  client_data = create_client();
+	  if (client_data == NULL) {
+	       PRINTF(("svcauth_gssapi: create_client failed\n"));
+	       LOG_MISCERR("internal error creating client record");
+	       ret = AUTH_FAILED;
+	       goto error;
+	  }
+     } else {
+	  if (creds.client_handle.length == 0) {
+	       PRINTF(("svcauth_gssapi: expected non-empty creds\n"));
+	       LOG_MISCERR("protocol error in client credentials");
+	       ret = AUTH_FAILED;
+	       goto error;
+	  }
+	  
+	  PRINTF(("svcauth_gssapi: incoming client_handle %d, len %d\n", 
+		  *((uint32_t *) creds.client_handle.value),
+		  (int) creds.client_handle.length));
+
+	  client_data = get_client(&creds.client_handle);
+	  if (client_data == NULL) {
+	       PRINTF(("svcauth_gssapi: client_handle lookup failed\n"));
+	       LOG_MISCERR("invalid client handle received");
+	       ret = AUTH_BADCRED;
+	       goto error;
+	  }
+	  PRINTF(("svcauth_gssapi: client_handle lookup succeeded\n"));
+     }
+
+     /* any response we send will use client_handle, so set it now */
+     call_res.client_handle.length = sizeof(client_data->key);
+     call_res.client_handle.value = (char *) &client_data->key;
+     
+     /* mark this call as using AUTH_GSSAPI via client_data's SVCAUTH */
+     rqst->rq_xprt->xp_auth = &client_data->svcauth;
+
+     if (client_data->established == FALSE) {
+	  PRINTF(("svcauth_gssapi: context is not established\n"));
+
+	  if (creds.auth_msg == FALSE) {
+	       PRINTF(("svcauth_gssapi: expected auth_msg TRUE\n"));
+	       LOG_MISCERR("protocol error on incomplete connection");
+	       ret = AUTH_REJECTEDCRED;
+	       goto error;
+	  }
+
+	  /*
+	   * If the context is not established, then only GSSAPI_INIT
+	   * and _CONTINUE requests are valid.
+	   */
+	  if (rqst->rq_proc != AUTH_GSSAPI_INIT && rqst->rq_proc !=
+	      AUTH_GSSAPI_CONTINUE_INIT) {
+	       PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
+		       rqst->rq_proc));
+	       LOG_MISCERR("protocol error on incomplete connection");
+	       ret = AUTH_FAILED;
+	       goto error;
+	  }
+
+	  /* call is for us, deserialize arguments */
+	  memset(&call_arg, 0, sizeof(call_arg));
+	  if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
+			    &call_arg)) {
+	       PRINTF(("svcauth_gssapi: cannot decode args\n"));
+	       LOG_MISCERR("protocol error in procedure arguments");
+	       ret = AUTH_BADCRED;
+	       goto error;
+	  }
+
+	  /*
+	   * Process the call arg version number.
+	   * 
+	   * Set the krb5_gss backwards-compatibility mode based on client
+	   * version.  This controls whether the AP_REP message is
+	   * encrypted with the session key (version 2+, correct) or the
+	   * session subkey (version 1, incorrect).  This function can
+	   * never fail, so we don't bother checking its return value.
+	   */
+	  switch (call_arg.version) {
+	  case 1:
+	  case 2:
+	       LOG_MISCERR("Warning: Accepted old RPC protocol request");
+	       call_res.version = 1;
+	       break;
+	  case 3:
+	  case 4:
+	       /* 3 and 4 are essentially the same, don't bother warning */
+	       call_res.version = call_arg.version;
+	       break;
+	  default:
+	       PRINTF(("svcauth_gssapi: bad GSSAPI_INIT version\n"));
+	       LOG_MISCERR("unsupported GSSAPI_INIT version");
+	       ret = AUTH_BADCRED;
+	       goto error;
+	  }
+
+#ifdef GSS_BACKWARD_HACK
+	  krb5_gss_set_backward_mode(&minor_stat, call_arg.version == 1);
+#endif
+
+	  if (call_arg.version >= 3) {
+	       memset(&bindings, 0, sizeof(bindings));
+	       bindings.application_data.length = 0;
+	       bindings.initiator_addrtype = GSS_C_AF_INET;
+	       bindings.initiator_address.length = 4;
+	       bindings.initiator_address.value =
+		    &svc_getcaller(rqst->rq_xprt)->sin_addr.s_addr;
+
+	       if (rqst->rq_xprt->xp_laddrlen > 0) {
+		    bindings.acceptor_addrtype = GSS_C_AF_INET;
+		    bindings.acceptor_address.length = 4;
+		    bindings.acceptor_address.value =
+			 &rqst->rq_xprt->xp_laddr.sin_addr.s_addr;
+	       } else {
+		    LOG_MISCERR("cannot get local address");
+		    ret = AUTH_FAILED;
+		    goto error;
+	       }
+
+
+	       bindp = &bindings;
+	  } else {
+	       bindp = GSS_C_NO_CHANNEL_BINDINGS;
+	  }
+
+	  /*
+	   * If the client's server_creds is already set, use it.
+	   * Otherwise, try each credential in server_creds_list until
+	   * one of them succeedes, then set the client server_creds
+	   * to that.  If all fail, the client's server_creds isn't
+	   * set (which is fine, because the client will be gc'ed
+	   * anyway).
+	   *
+	   * If accept_sec_context returns something other than
+	   * success and GSS_S_FAILURE, then assume different
+	   * credentials won't help and stop looping.
+	   * 
+	   * Note that there are really two cases here: (1) the client
+	   * has a server_creds already, and (2) it does not.  They
+	   * are both written in the same loop so that there is only
+	   * one textual call to gss_accept_sec_context; in fact, in
+	   * case (1), the loop is executed exactly once.
+	   */
+	  for (i = 0; i < server_creds_count; i++) {
+	       if (client_data->server_creds != NULL) {
+		    PRINTF(("svcauth_gssapi: using's clients server_creds\n"));
+		    server_creds = client_data->server_creds;
+	       } else {
+		    PRINTF(("svcauth_gssapi: trying creds %d\n", i));
+		    server_creds = server_creds_list[i];
+	       }
+	       
+	       /* Free previous output_token from loop */
+	       if(i != 0) gss_release_buffer(&minor_stat, &output_token);
+
+	       call_res.gss_major =
+		    gss_accept_sec_context(&call_res.gss_minor,
+					   &client_data->context,
+					   server_creds,
+					   &call_arg.token,
+					   bindp,
+					   &client_data->client_name,
+					   NULL,
+					   &output_token,
+					   &ret_flags,
+					   &time_rec,
+					   NULL);
+
+	       if (server_creds == client_data->server_creds)
+		    break;
+
+	       if (call_res.gss_major == GSS_S_COMPLETE ||
+		   call_res.gss_major == GSS_S_CONTINUE_NEEDED) {
+		    /* server_creds was right, set it! */
+		    PRINTF(("svcauth_gssapi: creds are correct, storing\n"));
+		    client_data->server_creds = server_creds;
+		    client_data->server_name = server_name_list[i];
+		    break;
+	       } else if (call_res.gss_major != GSS_S_FAILURE
+#ifdef GSSAPI_KRB5
+			  /*
+			   * hard-coded because there is no other way
+			   * to prevent all GSS_S_FAILURES from
+			   * returning a "wrong principal in request"
+			   * error
+			   */
+			  || ((krb5_error_code) call_res.gss_minor !=
+			      (krb5_error_code) KRB5KRB_AP_WRONG_PRINC)
+#endif
+			  ) {
+		    break;
+	       }
+	  }
+	  
+	  gssstat = call_res.gss_major;
+	  minor_stat = call_res.gss_minor;
+
+	  /* done with call args */
+	  xdr_free(xdr_authgssapi_init_arg, &call_arg);
+
+	  PRINTF(("svcauth_gssapi: accept_sec_context returned %#x\n",
+		  call_res.gss_major));
+	  if (call_res.gss_major != GSS_S_COMPLETE &&
+	      call_res.gss_major != GSS_S_CONTINUE_NEEDED) {
+	       AUTH_GSSAPI_DISPLAY_STATUS(("accepting context",
+					   call_res.gss_major,
+					   call_res.gss_minor));
+
+	       if (log_badauth != NULL)
+		    (*log_badauth)(call_res.gss_major,
+				   call_res.gss_minor,
+				   &rqst->rq_xprt->xp_raddr,
+				   log_badauth_data);
+	       
+	       gss_release_buffer(&minor_stat, &output_token);
+	       svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
+			     (caddr_t) &call_res);
+	       *no_dispatch = TRUE;
+	       ret = AUTH_OK;
+	       goto error;
+	  }
+	      
+	  if (output_token.length != 0) {
+	       PRINTF(("svcauth_gssapi: got new output token\n"));
+	       GSS_COPY_BUFFER(call_res.token, output_token);
+	  }
+
+	  if (gssstat == GSS_S_COMPLETE) {
+	       client_data->seq_num = rand();
+	       client_expire(client_data,
+			     (time_rec == GSS_C_INDEFINITE ?
+			      INDEF_EXPIRE : time_rec) + time(0));
+
+	       PRINTF(("svcauth_gssapi: context established, isn %d\n", 
+		       client_data->seq_num));
+
+	       if (auth_gssapi_seal_seq(client_data->context,
+					client_data->seq_num,
+					&call_res.signed_isn) ==
+		   FALSE) {
+		    ret = AUTH_FAILED;
+		    LOG_MISCERR("internal error sealing sequence number");
+		    gss_release_buffer(&minor_stat, &output_token);
+		    goto error;
+	       }
+	  }
+
+	  PRINTF(("svcauth_gssapi: sending reply\n"));
+	  svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
+			(caddr_t) &call_res);
+	  *no_dispatch = TRUE;
+
+	  /*
+	   * If appropriate, set established to TRUE *after* sending
+	   * response (otherwise, the client will receive the final
+	   * token encrypted)
+	   */
+	  if (gssstat == GSS_S_COMPLETE) {
+	       gss_release_buffer(&minor_stat, &call_res.signed_isn);
+	       client_data->established = TRUE;
+	  }
+	  gss_release_buffer(&minor_stat, &output_token);
+     } else {
+	  PRINTF(("svcauth_gssapi: context is established\n"));
+
+	  /* check the verifier */
+	  PRINTF(("svcauth_gssapi: checking verifier, len %d\n",
+		  verf->oa_length));
+	  
+	  in_buf.length = verf->oa_length;
+	  in_buf.value = verf->oa_base;
+	  
+	  if (auth_gssapi_unseal_seq(client_data->context, &in_buf,
+				     &seq_num) == FALSE) {
+	       ret = AUTH_BADVERF;
+	       LOG_MISCERR("internal error unsealing sequence number");
+	       goto error;
+	  }
+	  
+	  if (seq_num != client_data->seq_num + 1) {
+	       PRINTF(("svcauth_gssapi: expected isn %d, got %d\n",
+		       client_data->seq_num + 1, seq_num));
+	       if (log_badverf != NULL)
+		    (*log_badverf)(client_data->client_name,
+				   client_data->server_name,
+				   rqst, msg, log_badverf_data);
+	       
+	       ret = AUTH_REJECTEDVERF;
+	       goto error;
+	  }
+	  client_data->seq_num++;
+	  
+	  PRINTF(("svcauth_gssapi: seq_num %d okay\n", seq_num));
+
+	  /* free previous response verifier, if any */
+	  if (client_data->prev_verf.length != 0) {
+	       gss_release_buffer(&minor_stat, &client_data->prev_verf);
+	       client_data->prev_verf.length = 0;
+	  }
+	  
+	  /* prepare response verifier */
+	  seq_num = client_data->seq_num + 1;
+	  if (auth_gssapi_seal_seq(client_data->context, seq_num,
+				   &out_buf) == FALSE) {
+	       ret = AUTH_FAILED;
+	       LOG_MISCERR("internal error sealing sequence number");
+	       goto error;
+	  }
+	  
+	  client_data->seq_num++;
+	  
+	  PRINTF(("svcauth_gssapi; response seq_num %d\n", seq_num));
+	  
+	  rqst->rq_xprt->xp_verf.oa_flavor = AUTH_GSSAPI;
+	  rqst->rq_xprt->xp_verf.oa_base = out_buf.value; 
+	  rqst->rq_xprt->xp_verf.oa_length = out_buf.length;
+
+	  /* save verifier so it can be freed next time */
+	  client_data->prev_verf.value = out_buf.value; 
+	  client_data->prev_verf.length = out_buf.length;
+
+	  /*
+	   * Message is authentic.  If auth_msg if true, process the
+	   * call; otherwise, return AUTH_OK so it will be dispatched
+	   * to the application server.
+	   */
+
+	  if (creds.auth_msg == TRUE) {
+	       /*
+		* If process_token fails, then the token probably came
+		* from an attacker.  No response (error or otherwise)
+		* should be returned to the client, since it won't be
+		* accepting one.
+		*/
+
+	       switch (rqst->rq_proc) {
+	       case AUTH_GSSAPI_MSG:
+		    PRINTF(("svcauth_gssapi: GSSAPI_MSG, getting args\n"));
+		    memset(&call_arg, 0, sizeof(call_arg));
+		    if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
+				      &call_arg)) {
+			 PRINTF(("svcauth_gssapi: cannot decode args\n"));
+			 LOG_MISCERR("protocol error in call arguments");
+			 xdr_free(xdr_authgssapi_init_arg, &call_arg);
+			 ret = AUTH_BADCRED;
+			 goto error;
+		    }
+
+		    PRINTF(("svcauth_gssapi: processing token\n"));
+		    gssstat = gss_process_context_token(&minor_stat,
+							client_data->context,
+							&call_arg.token);
+
+		    /* done with call args */
+		    xdr_free(xdr_authgssapi_init_arg, &call_arg);
+		    
+		    if (gssstat != GSS_S_COMPLETE) {
+			 AUTH_GSSAPI_DISPLAY_STATUS(("processing token",
+						     gssstat, minor_stat));
+			 ret = AUTH_FAILED;
+			 goto error;
+		    }
+
+		    svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+		    *no_dispatch = TRUE;
+		    break;
+
+	       case AUTH_GSSAPI_DESTROY:
+		    PRINTF(("svcauth_gssapi: GSSAPI_DESTROY\n"));
+		    
+		    PRINTF(("svcauth_gssapi: sending reply\n"));
+		    svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+		    *no_dispatch = TRUE;
+
+		    destroy_client(client_data);
+		    rqst->rq_xprt->xp_auth = NULL;
+		    break;
+
+	       default:
+		    PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
+			    rqst->rq_proc));
+		    LOG_MISCERR("invalid call procedure number");
+		    ret = AUTH_FAILED;
+		    goto error;
+	       }
+	  } else {
+	       /* set credentials for app server; comment in svc.c */
+	       /* seems to imply this is incorrect, but I don't see */
+	       /* any problem with it... */
+	       rqst->rq_clntcred = (char *)client_data->client_name;
+	       rqst->rq_svccred = (char *)client_data->context;
+	  }
+     }
+
+     if (creds.client_handle.length != 0) {
+	  PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
+		  (int) creds.client_handle.length));
+	  xdr_free(xdr_authgssapi_creds, &creds);
+     }
+     
+     PRINTF(("\n"));
+     return AUTH_OK;
+
+error:
+     if (creds.client_handle.length != 0) {
+	  PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
+		  (int) creds.client_handle.length));
+	  xdr_free(xdr_authgssapi_creds, &creds);
+     }
+     
+     PRINTF(("\n"));
+     return ret;
+}
+
+static void cleanup(void)
+{
+     client_list *c, *c2;
+
+     PRINTF(("cleanup_and_exit: starting\n"));
+
+     c = clients;
+     while (c) {
+	  c2 = c;
+	  c = c->next;
+	  destroy_client(c2->client);
+	  free(c2);
+     }
+
+     exit(0);
+}     
+
+/*
+ * Function: create_client
+ *
+ * Purpose: Creates an new client_data structure and stores it in the
+ * database.
+ *
+ * Returns: the new client_data structure, or NULL on failure.
+ *
+ * Effects:
+ * 
+ * A new client_data is created and stored in the hash table and
+ * b-tree.  A new key that is unique in the current database is
+ * chosen; this key should be used as the client's client_handle.
+ */
+static svc_auth_gssapi_data *create_client(void)
+{
+     client_list *c;
+     svc_auth_gssapi_data *client_data;
+     static int client_key = 1;
+     
+     PRINTF(("svcauth_gssapi: empty creds, creating\n"));
+
+     client_data = (svc_auth_gssapi_data *) malloc(sizeof(*client_data));
+     if (client_data == NULL)
+	  return NULL;
+     memset((char *) client_data, 0, sizeof(*client_data));
+     L_PRINTF(2, ("create_client: new client_data = %p\n", 
+		  (void *) client_data));
+     
+     /* set up client data structure */
+     client_data->established = 0;
+     client_data->context = GSS_C_NO_CONTEXT;
+     client_data->expiration = time(0) + INITIATION_TIMEOUT;
+     
+     /* set up psycho-recursive SVCAUTH hack */
+     client_data->svcauth.svc_ah_ops = &svc_auth_gssapi_ops;
+     client_data->svcauth.svc_ah_private = (caddr_t) client_data;
+
+     client_data->key = client_key++;
+     
+     c = (client_list *) malloc(sizeof(client_list));
+     if (c == NULL)
+	  return NULL;
+     c->client = client_data;
+     c->next = NULL;
+     
+     
+     if (clients == NULL)
+	  clients = c;
+     else {
+	  c->next = clients;
+	  clients = c;
+     }
+     
+     PRINTF(("svcauth_gssapi: new handle %d\n", client_data->key));
+     L_PRINTF(2, ("create_client: done\n"));
+
+     return client_data;
+}
+
+/*
+ * Function: client_expire
+ *
+ * Purpose: change the expiration time of a client in the database
+ *
+ * Arguments:
+ *
+ * 	client_data	(r) the client_data to expire
+ * 	exp		(r) the new expiration time
+ *
+ * Effects:
+ *
+ * client_data->expiration = exp
+ *
+ * This function used to remove client_data from the database, change
+ * its expiration time, and re-add it, which was necessary because the
+ * database was sorted by expiration time so a simple modification
+ * would break the rep invariant.  Now the database is an unsorted
+ * linked list, so it doesn't matter.
+ */
+static void client_expire(
+     svc_auth_gssapi_data *client_data,
+     uint32_t exp)
+{
+     client_data->expiration = exp;
+}
+
+/*
+ * Function get_client
+ *
+ * Purpose: retrieve a client_data structure from the database based
+ * on its client handle (key)
+ *
+ * Arguments:
+ *
+ *	client_handle	(r) the handle (key) to retrieve
+ *
+ * Effects:
+ *
+ * Searches the list and returns the client_data whose key field
+ * matches the contents of client_handle, or returns NULL if none was
+ * found.
+ */
+static svc_auth_gssapi_data *get_client(gss_buffer_t client_handle)
+{
+     client_list *c;
+     uint32_t handle;
+     
+     memcpy(&handle, client_handle->value, 4);
+     
+     L_PRINTF(2, ("get_client: looking for client %d\n", handle));
+     
+     c = clients;
+     while (c) {
+	  if (c->client->key == handle)
+	       return c->client;
+	  c = c->next;
+     }
+     
+     L_PRINTF(2, ("get_client: client_handle lookup failed\n"));
+     return NULL;
+}
+
+/*
+ * Function: destroy_client
+ *
+ * Purpose: destroys a client entry and removes it from the database
+ *
+ * Arguments:
+ *
+ *	client_data	(r) the client to be destroyed
+ *
+ * Effects:
+ *
+ * client_data->context is deleted with gss_delete_sec_context.
+ * client_data's entry in the database is destroyed.  client_data is
+ * freed.
+ */
+static void destroy_client(svc_auth_gssapi_data *client_data)
+{
+     OM_uint32 gssstat, minor_stat;
+     gss_buffer_desc out_buf;
+     client_list *c, *c2;
+
+     PRINTF(("destroy_client: destroying client_data\n"));
+     L_PRINTF(2, ("destroy_client: client_data = %p\n", (void *) client_data));
+
+#ifdef DEBUG_GSSAPI
+     if (svc_debug_gssapi >= 3)
+	  dump_db("before frees");
+#endif
+
+     /* destroy client struct even if error occurs */
+
+     gssstat = gss_delete_sec_context(&minor_stat, &client_data->context,
+				      &out_buf);
+     if (gssstat != GSS_S_COMPLETE)
+	  AUTH_GSSAPI_DISPLAY_STATUS(("deleting context", gssstat,
+				      minor_stat));
+     
+     gss_release_buffer(&minor_stat, &out_buf);
+     gss_release_name(&minor_stat, &client_data->client_name);
+     if (client_data->prev_verf.length != 0)
+	  gss_release_buffer(&minor_stat, &client_data->prev_verf);
+
+     if (clients == NULL) {
+	  PRINTF(("destroy_client: called on empty database\n"));
+	  abort();
+     } else if (clients->client == client_data) {
+	  c = clients;
+	  clients = clients->next;
+	  free(c);
+     } else {
+	  c2 = clients;
+	  c = clients->next;
+	  while (c) {
+	       if (c->client == client_data) {
+		    c2->next = c->next;
+		    free(c);
+		    goto done;
+	       } else {
+		    c2 = c;
+		    c = c->next;
+	       }
+	  }
+	  PRINTF(("destroy_client: client_handle delete failed\n"));
+	  abort();
+     }
+     
+done:
+     
+     L_PRINTF(2, ("destroy_client: client %d destroyed\n", client_data->key));
+     
+     free(client_data);
+     
+#if 0 /*ifdef PURIFY*/
+     purify_watch_n(client_data, sizeof(*client_data), "rw");
+#endif
+}
+
+static void dump_db(char *msg)
+{
+     svc_auth_gssapi_data *client_data;
+     client_list *c;
+
+     L_PRINTF(3, ("dump_db: %s:\n", msg));
+
+     c = clients;
+     while (c) {
+	  client_data = c->client;
+	  L_PRINTF(3, ("\tclient_data = %p, exp = %d\n",
+		       (void *) client_data, client_data->expiration));
+	  c = c->next;
+     }
+
+     L_PRINTF(3, ("\n"));
+}
+
+static void clean_client(void)
+{
+     svc_auth_gssapi_data *client_data;
+     client_list *c;
+
+     PRINTF(("clean_client: starting\n"));
+
+     c = clients;
+     while (c) {
+	  client_data = c->client;
+	  
+	  L_PRINTF(2, ("clean_client: client_data = %p\n",
+		       (void *) client_data));
+	  
+	  if (client_data->expiration < time(0)) {
+	       PRINTF(("clean_client: client %d expired\n",
+		       client_data->key));
+	       destroy_client(client_data);
+	       c = clients; /* start over, just to be safe */
+	  } else {
+	       c = c->next;
+	  }
+     }
+
+     PRINTF(("clean_client: done\n"));
+}
+
+/*
+ * Function: svcauth_gssapi_set_names
+ *
+ * Purpose: Sets the list of service names for which incoming
+ * authentication requests should be honored.
+ *
+ * See functional specifications.
+ */
+bool_t svcauth_gssapi_set_names(
+     auth_gssapi_name *names,
+     int num)
+{
+     OM_uint32 gssstat, minor_stat;
+     gss_buffer_desc in_buf;
+     int i;
+     
+     if (num == 0)
+	  for (; names[num].name != NULL; num++)
+	       ;
+
+     server_creds_list = NULL;
+     server_name_list = NULL;
+     
+     server_creds_list = (gss_cred_id_t *) malloc(num*sizeof(gss_cred_id_t));
+     if (server_creds_list == NULL)
+	  goto fail;
+     server_name_list = (gss_name_t *) malloc(num*sizeof(gss_name_t));
+     if (server_name_list == NULL)
+	  goto fail;
+     
+     for (i = 0; i < num; i++) {
+	  server_name_list[i] = 0;
+	  server_creds_list[i] = 0;
+     }
+
+     server_creds_count = num;
+     
+     for (i = 0; i < num; i++) {
+	  in_buf.value = names[i].name;
+	  in_buf.length = strlen(in_buf.value) + 1;
+
+	  PRINTF(("svcauth_gssapi_set_names: importing %s\n", in_buf.value));
+
+	  gssstat = gss_import_name(&minor_stat, &in_buf, names[i].type,
+				    &server_name_list[i]); 
+     
+	  if (gssstat != GSS_S_COMPLETE) {
+	       AUTH_GSSAPI_DISPLAY_STATUS(("importing name", gssstat,
+					   minor_stat));
+	       goto fail;
+	  }
+
+	  gssstat = gss_acquire_cred(&minor_stat, server_name_list[i], 0,
+				     GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+				     &server_creds_list[i], NULL, NULL);
+	  if (gssstat != GSS_S_COMPLETE) {
+	       AUTH_GSSAPI_DISPLAY_STATUS(("acquiring credentials",
+					   gssstat, minor_stat));
+	       goto fail;
+	  }
+     }
+
+     return TRUE;
+
+fail:
+     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(void)
+{
+     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);
+	  server_creds_list = NULL;
+     }
+
+     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);
+	  server_name_list = NULL;
+     }
+     server_creds_count = 0;
+}
+
+
+/*
+ * Function: svcauth_gssapi_set_log_badauth_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void svcauth_gssapi_set_log_badauth_func(
+     auth_gssapi_log_badauth_func func,
+     caddr_t data)
+{
+     log_badauth = func;
+     log_badauth_data = data;
+}
+
+/*
+ * Function: svcauth_gssapi_set_log_badverf_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void svcauth_gssapi_set_log_badverf_func(
+     auth_gssapi_log_badverf_func func,
+     caddr_t data)
+{
+     log_badverf = func;
+     log_badverf_data = data;
+}
+
+/*
+ * Function: svcauth_gssapi_set_log_miscerr_func
+ *
+ * Purpose: sets the logging function called when a miscellaneous
+ * AUTH_GSSAPI error occurs
+ *
+ * See functional specifications.
+ */
+void svcauth_gssapi_set_log_miscerr_func(
+     auth_gssapi_log_miscerr_func func,
+     caddr_t data)
+{
+     log_miscerr = func;
+     log_miscerr_data = data;
+}
+
+/*
+ * Encrypt the serialized arguments from xdr_func applied to xdr_ptr
+ * and write the result to xdrs.
+ */
+static bool_t svc_auth_gssapi_wrap(
+     SVCAUTH *auth,
+     XDR *out_xdrs,
+     bool_t (*xdr_func)(),
+     caddr_t xdr_ptr)
+{
+     OM_uint32 gssstat, minor_stat;
+
+     if (! SVCAUTH_PRIVATE(auth)->established) {
+	  PRINTF(("svc_gssapi_wrap: not established, noop\n"));
+	  return (*xdr_func)(out_xdrs, xdr_ptr);
+     } else if (! auth_gssapi_wrap_data(&gssstat, &minor_stat,
+					SVCAUTH_PRIVATE(auth)->context,
+					SVCAUTH_PRIVATE(auth)->seq_num,
+					out_xdrs, xdr_func, xdr_ptr)) {
+	  if (gssstat != GSS_S_COMPLETE)
+	       AUTH_GSSAPI_DISPLAY_STATUS(("encrypting function arguments",
+					   gssstat, minor_stat));
+	  return FALSE;
+     } else
+	  return TRUE;
+}
+
+static bool_t svc_auth_gssapi_unwrap(
+     SVCAUTH *auth,
+     XDR *in_xdrs,
+     bool_t (*xdr_func)(),
+     caddr_t xdr_ptr)
+{
+     svc_auth_gssapi_data *client_data = SVCAUTH_PRIVATE(auth);
+     OM_uint32 gssstat, minor_stat;
+
+     if (! client_data->established) {
+	  PRINTF(("svc_gssapi_unwrap: not established, noop\n"));
+	  return (*xdr_func)(in_xdrs, (auth_gssapi_init_arg *)(void *) xdr_ptr);
+     } else if (! auth_gssapi_unwrap_data(&gssstat, &minor_stat,
+					  client_data->context,
+					  client_data->seq_num-1,
+					  in_xdrs, xdr_func, xdr_ptr)) {
+	  if (gssstat != GSS_S_COMPLETE)
+	       AUTH_GSSAPI_DISPLAY_STATUS(("decrypting function arguments",
+					   gssstat, minor_stat));
+	  return FALSE;
+     } else
+	  return TRUE;
+}
+
+static bool_t svc_auth_gssapi_destroy(SVCAUTH *auth)
+{
+     svc_auth_gssapi_data *client_data = SVCAUTH_PRIVATE(auth);
+
+     destroy_client(client_data);
+     return TRUE;
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_auth_none.c b/krb5-1-6/src/lib/rpc/svc_auth_none.c
new file mode 100644
index 000000000..2df9580a5
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_auth_none.c
@@ -0,0 +1,75 @@
+/*
+  svc_auth_none.c
+  
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of the University nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Id: svc_auth_none.c,v 1.1 2000/08/24 20:51:34 dugsong Exp
+ */
+
+#include <gssrpc/rpc.h>
+
+static bool_t	svcauth_none_destroy(SVCAUTH *);
+static bool_t   svcauth_none_wrap(SVCAUTH *, XDR *, xdrproc_t,
+				  caddr_t);
+
+struct svc_auth_ops svc_auth_none_ops = {
+	svcauth_none_wrap,
+	svcauth_none_wrap,
+	svcauth_none_destroy
+};
+
+SVCAUTH svc_auth_none = {
+	&svc_auth_none_ops,
+	NULL,
+};
+
+static bool_t
+svcauth_none_destroy(SVCAUTH *auth)
+{
+	return (TRUE);
+}
+
+static bool_t
+svcauth_none_wrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func,
+		  caddr_t xdr_ptr)
+{
+	return ((*xdr_func)(xdrs, xdr_ptr));
+}
+
+enum auth_stat
+gssrpc__svcauth_none(struct svc_req *rqst, struct rpc_msg *msg,
+		     bool_t *no_dispatch)
+{
+	rqst->rq_xprt->xp_auth = &svc_auth_none;
+	
+	return (AUTH_OK);
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_auth_unix.c b/krb5-1-6/src/lib/rpc/svc_auth_unix.c
new file mode 100644
index 000000000..016644b40
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_auth_unix.c
@@ -0,0 +1,141 @@
+/* @(#)svc_auth_unix.c	2.3 88/08/01 4.0 RPCSRC; from 1.28 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_auth_unix.c
+ * Handles UNIX flavor authentication parameters on the service side of rpc.
+ * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
+ * _svcauth_unix does full blown unix style uid,gid+gids auth,
+ * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
+ * Note: the shorthand has been gutted for efficiency.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <gssrpc/rpc.h>
+
+/*
+ * Unix longhand authenticator
+ */
+enum auth_stat
+gssrpc__svcauth_unix(
+	register struct svc_req *rqst,
+	register struct rpc_msg *msg,
+	bool_t *dispatch)
+{
+	register enum auth_stat stat;
+	XDR xdrs;
+	register struct authunix_parms *aup;
+	register rpc_inline_t *buf;
+	struct area {
+		struct authunix_parms area_aup;
+		char area_machname[MAX_MACHINE_NAME+1];
+		int area_gids[NGRPS];
+	} *area;
+	u_int auth_len, str_len, gid_len;
+	register int i;
+
+	rqst->rq_xprt->xp_auth = &svc_auth_none;
+	
+	area = (struct area *) rqst->rq_clntcred;
+	aup = &area->area_aup;
+	aup->aup_machname = area->area_machname;
+	aup->aup_gids = area->area_gids;
+	auth_len = msg->rm_call.cb_cred.oa_length;
+	if (auth_len > INT_MAX)
+		return AUTH_BADCRED;
+	xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
+	buf = XDR_INLINE(&xdrs, (int)auth_len);
+	if (buf != NULL) {
+		aup->aup_time = IXDR_GET_LONG(buf);
+		str_len = IXDR_GET_U_LONG(buf);
+		if (str_len > MAX_MACHINE_NAME) {
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+		memmove(aup->aup_machname, buf, str_len);
+		aup->aup_machname[str_len] = 0;
+		str_len = RNDUP(str_len);
+		buf += str_len / BYTES_PER_XDR_UNIT;
+		aup->aup_uid = IXDR_GET_LONG(buf);
+		aup->aup_gid = IXDR_GET_LONG(buf);
+		gid_len = IXDR_GET_U_LONG(buf);
+		if (gid_len > NGRPS) {
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+		aup->aup_len = gid_len;
+		for (i = 0; i < gid_len; i++) {
+			aup->aup_gids[i] = IXDR_GET_LONG(buf);
+		}
+		/*
+		 * five is the smallest unix credentials structure -
+		 * timestamp, hostname len (0), uid, gid, and gids len (0).
+		 */
+		if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
+			(void) printf("bad auth_len gid %u str %u auth %u\n",
+			    gid_len, str_len, auth_len);
+			stat = AUTH_BADCRED;
+			goto done;
+		}
+	} else if (! xdr_authunix_parms(&xdrs, aup)) {
+		xdrs.x_op = XDR_FREE;
+		(void)xdr_authunix_parms(&xdrs, aup);
+		stat = AUTH_BADCRED;
+		goto done;
+	}
+	rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
+	rqst->rq_xprt->xp_verf.oa_length = 0;
+	stat = AUTH_OK;
+done:
+	XDR_DESTROY(&xdrs);
+	return (stat);
+}
+
+
+/*
+ * Shorthand unix authenticator
+ * Looks up longhand in a cache.
+ */
+/*ARGSUSED*/
+enum auth_stat 
+gssrpc__svcauth_short(
+	struct svc_req *rqst,
+	struct rpc_msg *msg,
+	bool_t *dispatch)
+{
+	rqst->rq_xprt->xp_auth = &svc_auth_none;
+	return (AUTH_REJECTEDCRED);
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_raw.c b/krb5-1-6/src/lib/rpc/svc_raw.c
new file mode 100644
index 000000000..d2507ae8d
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_raw.c
@@ -0,0 +1,160 @@
+/* @(#)svc_raw.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_raw.c,   This a toy for simple testing and timing.
+ * Interface to create an rpc client and server in the same UNIX process.
+ * This lets us similate rpc and get rpc (round trip) overhead, without
+ * any interference from the kernal.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <gssrpc/rpc.h>
+
+
+/*
+ * This is the "network" that we will be moving data over
+ */
+static struct svcraw_private {
+	char	_raw_buf[UDPMSGSIZE];
+	SVCXPRT	server;
+	XDR	xdr_stream;
+	char	verf_body[MAX_AUTH_BYTES];
+} *svcraw_private;
+
+static bool_t		svcraw_recv(SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat 	svcraw_stat(SVCXPRT *);
+static bool_t		svcraw_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t		svcraw_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t		svcraw_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void		svcraw_destroy(SVCXPRT *);
+
+static struct xp_ops server_ops = {
+	svcraw_recv,
+	svcraw_stat,
+	svcraw_getargs,
+	svcraw_reply,
+	svcraw_freeargs,
+	svcraw_destroy
+};
+
+SVCXPRT *
+svcraw_create(void)
+{
+	register struct svcraw_private *srp = svcraw_private;
+
+	if (srp == 0) {
+		srp = (struct svcraw_private *)calloc(1, sizeof (*srp));
+		if (srp == 0)
+			return (0);
+	}
+	srp->server.xp_sock = 0;
+	srp->server.xp_port = 0;
+	srp->server.xp_ops = &server_ops;
+	srp->server.xp_verf.oa_base = srp->verf_body;
+	xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+	return (&srp->server);
+}
+
+static enum xprt_stat
+svcraw_stat(SVCXPRT *xprt)
+{
+
+	return (XPRT_IDLE);
+}
+
+static bool_t
+svcraw_recv(SVCXPRT *xprt, struct rpc_msg *msg)
+{
+	register struct svcraw_private *srp = svcraw_private;
+	register XDR *xdrs;
+
+	if (srp == 0)
+		return (0);
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_DECODE;
+	XDR_SETPOS(xdrs, 0);
+	if (! xdr_callmsg(xdrs, msg))
+	       return (FALSE);
+	return (TRUE);
+}
+
+static bool_t
+svcraw_reply(SVCXPRT *xprt, struct rpc_msg *msg)
+{
+	register struct svcraw_private *srp = svcraw_private;
+	register XDR *xdrs;
+
+	if (srp == 0)
+		return (FALSE);
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_ENCODE;
+	XDR_SETPOS(xdrs, 0);
+	if (! xdr_replymsg(xdrs, msg))
+	       return (FALSE);
+	(void)XDR_GETPOS(xdrs);  /* called just for overhead */
+	return (TRUE);
+}
+
+static bool_t
+svcraw_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
+{
+	register struct svcraw_private *srp = svcraw_private;
+
+	if (srp == 0)
+		return (FALSE);
+	if (! (*xdr_args)(&srp->xdr_stream, args_ptr)) {
+		(void)svcraw_freeargs(xprt, xdr_args, args_ptr);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static bool_t
+svcraw_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
+{ 
+	register struct svcraw_private *srp = svcraw_private;
+	register XDR *xdrs;
+
+	if (srp == 0)
+		return (FALSE);
+	xdrs = &srp->xdr_stream;
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_args)(xdrs, args_ptr));
+} 
+
+static void
+svcraw_destroy(SVCXPRT *xprt)
+{
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_run.c b/krb5-1-6/src/lib/rpc/svc_run.c
new file mode 100644
index 000000000..b661f88b3
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_run.c
@@ -0,0 +1,74 @@
+/* @(#)svc_run.c	2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+
+#include <gssrpc/rpc.h>
+#include <errno.h>
+
+extern int svc_maxfd;
+
+void
+svc_run(void)
+{
+#ifdef FD_SETSIZE
+	fd_set readfds;
+#else
+	int readfds;
+#endif /* def FD_SETSIZE */
+
+	for (;;) {
+#ifdef FD_SETSIZE
+		readfds = svc_fdset;
+#else
+		readfds = svc_fds;
+#endif /* def FD_SETSIZE */
+		switch (select(svc_maxfd + 1, &readfds, (fd_set *)0,
+			       (fd_set *)0, (struct timeval *)0)) {
+		case -1:
+			if (errno == EINTR) {
+				continue;
+			}
+			perror("svc_run: - select failed");
+			return;
+		case 0:
+			continue;
+		default:
+			svc_getreqset(&readfds);
+		}
+	}
+}
diff --git a/krb5-1-6/src/lib/rpc/svc_simple.c b/krb5-1-6/src/lib/rpc/svc_simple.c
new file mode 100644
index 000000000..6ae85ce52
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_simple.c
@@ -0,0 +1,149 @@
+/* @(#)svc_simple.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/* 
+ * svc_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+static struct proglst {
+	char *(*p_progname)();
+	int  p_prognum;
+	int  p_procnum;
+	xdrproc_t p_inproc, p_outproc;
+	struct proglst *p_nxt;
+} *proglst;
+static void universal(struct svc_req *, SVCXPRT *);
+static SVCXPRT *transp;
+
+int
+registerrpc(
+	rpcprog_t prognum,
+	rpcvers_t versnum,
+	rpcproc_t procnum,
+	char *(*progname)(),
+	xdrproc_t inproc,
+	xdrproc_t outproc)
+{
+        struct proglst *pl;
+	
+	if (procnum == NULLPROC) {
+		(void) fprintf(stderr,
+		    "can't reassign procedure number %d\n", NULLPROC);
+		return (-1);
+	}
+	if (transp == 0) {
+		transp = svcudp_create(RPC_ANYSOCK);
+		if (transp == NULL) {
+			(void) fprintf(stderr, "couldn't create an rpc server\n");
+			return (-1);
+		}
+	}
+	(void) pmap_unset(prognum, versnum);
+	if (!svc_register(transp, prognum, versnum, universal, IPPROTO_UDP)) {
+	    	(void) fprintf(stderr, "couldn't register prog %d vers %d\n",
+		    prognum, versnum);
+		return (-1);
+	}
+	pl = (struct proglst *)malloc(sizeof(struct proglst));
+	if (pl == NULL) {
+		(void) fprintf(stderr, "registerrpc: out of memory\n");
+		return (-1);
+	}
+	pl->p_progname = progname;
+	pl->p_prognum = prognum;
+	pl->p_procnum = procnum;
+	pl->p_inproc = inproc;
+	pl->p_outproc = outproc;
+	pl->p_nxt = proglst;
+	proglst = pl;
+	return (0);
+}
+
+static void
+universal(
+	struct svc_req *rqstp,
+	SVCXPRT *s_transp)
+{
+	int prog, proc;
+	char *outdata;
+	char xdrbuf[UDPMSGSIZE];
+	struct proglst *pl;
+
+	/* 
+	 * enforce "procnum 0 is echo" convention
+	 */
+	if (rqstp->rq_proc == NULLPROC) {
+		if (svc_sendreply(s_transp, xdr_void, (char *)NULL) == FALSE) {
+			(void) fprintf(stderr, "xxx\n");
+			exit(1);
+		}
+		return;
+	}
+	prog = rqstp->rq_prog;
+	proc = rqstp->rq_proc;
+	for (pl = proglst; pl != NULL; pl = pl->p_nxt)
+		if (pl->p_prognum == prog && pl->p_procnum == proc) {
+			/* decode arguments into a CLEAN buffer */
+			memset(xdrbuf, 0, sizeof(xdrbuf)); /* required ! */
+			if (!svc_getargs(s_transp, pl->p_inproc, xdrbuf)) {
+				svcerr_decode(s_transp);
+				return;
+			}
+			outdata = (*(pl->p_progname))(xdrbuf);
+			if (outdata == NULL && pl->p_outproc != xdr_void)
+				/* there was an error */
+				return;
+			if (!svc_sendreply(s_transp, pl->p_outproc, outdata)) {
+				(void) fprintf(stderr,
+				    "trouble replying to prog %d\n",
+				    pl->p_prognum);
+				exit(1);
+			}
+			/* free the decoded arguments */
+			(void)svc_freeargs(s_transp, pl->p_inproc, xdrbuf);
+			return;
+		}
+	(void) fprintf(stderr, "never registered prog %d\n", prog);
+	exit(1);
+}
+
diff --git a/krb5-1-6/src/lib/rpc/svc_tcp.c b/krb5-1-6/src/lib/rpc/svc_tcp.c
new file mode 100644
index 000000000..d49cf3672
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_tcp.c
@@ -0,0 +1,504 @@
+/* @(#)svc_tcp.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_tcp.c, Server side for TCP/IP based RPC. 
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "autoconf.h"
+/*extern bool_t abort();
+extern errno;
+*/
+
+/*
+ * Ops vector for TCP/IP based rpc service handle
+ */
+static bool_t		svctcp_recv(SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat	svctcp_stat(SVCXPRT *);
+static bool_t		svctcp_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t		svctcp_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t		svctcp_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void		svctcp_destroy(SVCXPRT *);
+
+static struct xp_ops svctcp_op = {
+	svctcp_recv,
+	svctcp_stat,
+	svctcp_getargs,
+	svctcp_reply,
+	svctcp_freeargs,
+	svctcp_destroy
+};
+
+/*
+ * Ops vector for TCP/IP rendezvous handler
+ */
+static bool_t		rendezvous_request(SVCXPRT *, struct rpc_msg *);
+static bool_t		abortx(void);
+static bool_t		abortx_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t		abortx_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t		abortx_freeargs(SVCXPRT *, xdrproc_t, void *);
+static enum xprt_stat	rendezvous_stat(SVCXPRT *);
+
+static struct xp_ops svctcp_rendezvous_op = {
+	rendezvous_request,
+	rendezvous_stat,
+	abortx_getargs,
+	abortx_reply,
+	abortx_freeargs,
+	svctcp_destroy
+};
+
+static int readtcp(char *, caddr_t, int), writetcp(char *, caddr_t, int);
+static SVCXPRT *makefd_xprt(int, u_int, u_int);
+
+struct tcp_rendezvous { /* kept in xprt->xp_p1 */
+	u_int sendsize;
+	u_int recvsize;
+};
+
+struct tcp_conn {  /* kept in xprt->xp_p1 */
+	enum xprt_stat strm_stat;
+	uint32_t x_id;
+	XDR xdrs;
+	char verf_body[MAX_AUTH_BYTES];
+};
+
+/*
+ * Usage:
+ *	xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) tcp based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register).  This routine returns
+ * a NULL if a problem occurred.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svctcp_create
+ * binds it to an arbitrary port.  The routine then starts a tcp
+ * listener on the socket's associated port.  In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since tcp streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svctcp_create(
+	register int sock,
+	u_int sendsize,
+	u_int recvsize)
+{
+	bool_t madesock = FALSE;
+	register SVCXPRT *xprt;
+	register struct tcp_rendezvous *r;
+	struct sockaddr_in addr;
+	int len = sizeof(struct sockaddr_in);
+
+	if (sock == RPC_ANYSOCK) {
+		if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+			perror("svctcp_.c - udp socket creation problem");
+			return ((SVCXPRT *)NULL);
+		}
+		madesock = TRUE;
+	}
+	memset((char *)&addr, 0, sizeof (addr));
+#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+	addr.sin_len = sizeof(addr);
+#endif
+	addr.sin_family = AF_INET;
+	if (bindresvport(sock, &addr)) {
+		addr.sin_port = 0;
+		(void)bind(sock, (struct sockaddr *)&addr, len);
+	}
+	if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
+		perror("svc_tcp.c - cannot getsockname");
+		if (madesock)
+			(void) close(sock);
+		return ((SVCXPRT *)NULL);
+	}
+	if (listen(sock, 2) != 0) {
+		perror("svctcp_.c - cannot listen");
+		if (madesock)
+			(void)close(sock);
+		return ((SVCXPRT *)NULL);
+	}
+	r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
+	if (r == NULL) {
+		(void) fprintf(stderr, "svctcp_create: out of memory\n");
+		return (NULL);
+	}
+	r->sendsize = sendsize;
+	r->recvsize = recvsize;
+	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+	if (xprt == NULL) {
+		(void) fprintf(stderr, "svctcp_create: out of memory\n");
+		return (NULL);
+	}
+	xprt->xp_p2 = NULL;
+	xprt->xp_p1 = (caddr_t)r;
+	xprt->xp_auth = NULL;
+	xprt->xp_verf = gssrpc__null_auth;
+	xprt->xp_ops = &svctcp_rendezvous_op;
+	xprt->xp_port = ntohs(addr.sin_port);
+	xprt->xp_sock = sock;
+	xprt->xp_laddrlen = 0;
+	xprt_register(xprt);
+	return (xprt);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcfd_create(
+	int fd,
+	u_int sendsize,
+	u_int recvsize)
+{
+
+	return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(
+	int fd,
+	u_int sendsize,
+	u_int recvsize)
+{
+	register SVCXPRT *xprt;
+	register struct tcp_conn *cd;
+ 
+	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+	if (xprt == (SVCXPRT *)NULL) {
+		(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+		goto done;
+	}
+	cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
+	if (cd == (struct tcp_conn *)NULL) {
+		(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+		mem_free((char *) xprt, sizeof(SVCXPRT));
+		xprt = (SVCXPRT *)NULL;
+		goto done;
+	}
+	cd->strm_stat = XPRT_IDLE;
+	xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+	    (caddr_t)xprt, readtcp, writetcp);
+	xprt->xp_p2 = NULL;
+	xprt->xp_p1 = (caddr_t)cd;
+	xprt->xp_auth = NULL;
+	xprt->xp_verf.oa_base = cd->verf_body;
+	xprt->xp_addrlen = 0;
+	xprt->xp_laddrlen = 0;
+	xprt->xp_ops = &svctcp_op;  /* truely deals with calls */
+	xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
+	xprt->xp_sock = fd;
+	xprt_register(xprt);
+    done:
+	return (xprt);
+}
+
+static bool_t
+rendezvous_request(
+	register SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+	int sock;
+	struct tcp_rendezvous *r;
+	struct sockaddr_in addr, laddr;
+	int len, llen;
+
+	r = (struct tcp_rendezvous *)xprt->xp_p1;
+    again:
+	len = llen = sizeof(struct sockaddr_in);
+	if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
+	    &len)) < 0) {
+		if (errno == EINTR)
+			goto again;
+	       return (FALSE);
+	}
+	if (getsockname(sock, &laddr, &llen) < 0)
+	     return (FALSE);
+	
+	/*
+	 * make a new transporter (re-uses xprt)
+	 */
+	xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+	xprt->xp_raddr = addr;
+	xprt->xp_addrlen = len;
+	xprt->xp_laddr = laddr;
+	xprt->xp_laddrlen = llen;
+	return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+static enum xprt_stat
+rendezvous_stat(register SVCXPRT *xprt)
+{
+
+	return (XPRT_IDLE);
+}
+
+static void
+svctcp_destroy(register SVCXPRT *xprt)
+{
+	register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
+
+	xprt_unregister(xprt);
+	(void)close(xprt->xp_sock);
+	if (xprt->xp_port != 0) {
+		/* a rendezvouser socket */
+		xprt->xp_port = 0;
+	} else {
+		/* an actual connection socket */
+		XDR_DESTROY(&(cd->xdrs));
+	}
+	if (xprt->xp_auth != NULL) {
+		SVCAUTH_DESTROY(xprt->xp_auth);
+		xprt->xp_auth = NULL;
+	}
+	mem_free((caddr_t)cd, sizeof(struct tcp_conn));
+	mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = { 35, 0 };
+
+/*
+ * reads data from the tcp conection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ */
+static int
+readtcp(
+        char *xprtptr,
+	caddr_t buf,
+	register int len)
+{
+	register SVCXPRT *xprt = (SVCXPRT *)(void *)xprtptr;
+	register int sock = xprt->xp_sock;
+	struct timeval tout;
+#ifdef FD_SETSIZE
+	fd_set mask;
+	fd_set readfds;
+
+	FD_ZERO(&mask);
+	FD_SET(sock, &mask);
+#else
+	register int mask = 1 << sock;
+	int readfds;
+#endif /* def FD_SETSIZE */
+#ifdef FD_SETSIZE
+#define loopcond (!FD_ISSET(sock, &readfds))
+#else
+#define loopcond (readfds != mask)
+#endif
+	do {
+		readfds = mask;
+		tout = wait_per_try;
+		if (select(sock + 1, &readfds, (fd_set*)NULL,
+			   (fd_set*)NULL, &tout) <= 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			goto fatal_err;
+		}
+	} while (loopcond);
+	if ((len = read(sock, buf, (size_t) len)) > 0) {
+		return (len);
+	}
+fatal_err:
+	((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+	return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writetcp(
+	char *xprtptr,
+	caddr_t buf,
+	int len)
+{
+	register SVCXPRT *xprt = (SVCXPRT *)(void *) xprtptr;
+	register int i, cnt;
+
+	for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+		if ((i = write(xprt->xp_sock, buf, (size_t) cnt)) < 0) {
+			((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
+			    XPRT_DIED;
+			return (-1);
+		}
+	}
+	return (len);
+}
+
+static enum xprt_stat
+svctcp_stat(SVCXPRT *xprt)
+{
+	register struct tcp_conn *cd =
+	    (struct tcp_conn *)(xprt->xp_p1);
+
+	if (cd->strm_stat == XPRT_DIED)
+		return (XPRT_DIED);
+	if (! xdrrec_eof(&(cd->xdrs)))
+		return (XPRT_MOREREQS);
+	return (XPRT_IDLE);
+}
+
+static bool_t
+svctcp_recv(
+	SVCXPRT *xprt,
+	register struct rpc_msg *msg)
+{
+	register struct tcp_conn *cd =
+	    (struct tcp_conn *)(xprt->xp_p1);
+	register XDR *xdrs = &(cd->xdrs);
+
+	xdrs->x_op = XDR_DECODE;
+	(void)xdrrec_skiprecord(xdrs);
+	if (xdr_callmsg(xdrs, msg)) {
+		cd->x_id = msg->rm_xid;
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+static bool_t
+svctcp_getargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void *args_ptr)
+{
+	if (! SVCAUTH_UNWRAP(xprt->xp_auth,
+			     &(((struct tcp_conn *)(xprt->xp_p1))->xdrs),
+			     xdr_args, args_ptr)) {
+		(void)svctcp_freeargs(xprt, xdr_args, args_ptr);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static bool_t
+svctcp_freeargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void * args_ptr)
+{
+	register XDR *xdrs =
+	    &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t svctcp_reply(
+	SVCXPRT *xprt,
+	register struct rpc_msg *msg)
+{
+	register struct tcp_conn *cd =
+		(struct tcp_conn *)(xprt->xp_p1);
+	register XDR *xdrs = &(cd->xdrs);
+	register bool_t stat;
+     
+	xdrproc_t xdr_results;
+	caddr_t xdr_location;
+	bool_t has_args;
+
+	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+		has_args = TRUE;
+		xdr_results = msg->acpted_rply.ar_results.proc;
+		xdr_location = msg->acpted_rply.ar_results.where;
+	  
+		msg->acpted_rply.ar_results.proc = xdr_void;
+		msg->acpted_rply.ar_results.where = NULL;
+	} else
+		has_args = FALSE;
+     
+	xdrs->x_op = XDR_ENCODE;
+	msg->rm_xid = cd->x_id;
+	stat = FALSE;
+	if (xdr_replymsg(xdrs, msg) &&
+	    (!has_args ||
+	     (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) {
+		stat = TRUE;
+	}
+	(void)xdrrec_endofrecord(xdrs, TRUE);
+	return (stat);
+}
+
+static bool_t abortx(void)
+{
+	abort();
+	return 1;
+}
+
+static bool_t abortx_getargs(
+	SVCXPRT *xprt,
+	xdrproc_t proc,
+	void *info)
+{
+	return abortx();
+}
+
+static bool_t abortx_reply(SVCXPRT *xprt, struct rpc_msg *msg)
+{
+	return abortx();
+}
+
+static bool_t abortx_freeargs(
+	SVCXPRT *xprt, xdrproc_t proc,
+	void * info)
+{
+	return abortx();
+}
+
diff --git a/krb5-1-6/src/lib/rpc/svc_udp.c b/krb5-1-6/src/lib/rpc/svc_udp.c
new file mode 100644
index 000000000..49c555fe2
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/svc_udp.c
@@ -0,0 +1,531 @@
+/* @(#)svc_udp.c	2.2 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_udp.c,
+ * Server side for UDP/IP based RPC.  (Does some caching in the hopes of
+ * achieving execute-at-most-once semantics.)
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <gssrpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include "autoconf.h"
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+#ifndef MAX
+#define MAX(a, b)     ((a > b) ? a : b)
+#endif
+
+static bool_t		svcudp_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t		svcudp_reply(SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat	svcudp_stat(SVCXPRT *);
+static bool_t		svcudp_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t		svcudp_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void		svcudp_destroy(SVCXPRT *);
+
+static void cache_set(SVCXPRT *, uint32_t);
+static int cache_get(SVCXPRT *, struct rpc_msg *, char **, uint32_t *);
+
+static struct xp_ops svcudp_op = {
+	svcudp_recv,
+	svcudp_stat,
+	svcudp_getargs,
+	svcudp_reply,
+	svcudp_freeargs,
+	svcudp_destroy
+};
+
+
+/*
+ * kept in xprt->xp_p2
+ */
+struct svcudp_data {
+	u_int   su_iosz;	/* byte size of send.recv buffer */
+	uint32_t	su_xid;		/* transaction id */
+	XDR	su_xdrs;	/* XDR handle */
+	char	su_verfbody[MAX_AUTH_BYTES];	/* verifier body */
+	void * 	su_cache;	/* cached data, NULL if no cache */
+};
+#define	su_data(xprt)	((struct svcudp_data *)(xprt->xp_p2))
+
+/*
+ * Usage:
+ *	xprt = svcudp_create(sock);
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcudp_create
+ * binds it to an arbitrary port.  In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ * Once *xprt is initialized, it is registered as a transporter;
+ * see (svc.h, xprt_register).
+ * The routines returns NULL if a problem occurred.
+ */
+SVCXPRT *
+svcudp_bufcreate(
+	register int sock,
+	u_int sendsz,
+	u_int recvsz)
+{
+	bool_t madesock = FALSE;
+	register SVCXPRT *xprt;
+	register struct svcudp_data *su;
+	struct sockaddr_in addr;
+	int len = sizeof(struct sockaddr_in);
+
+	if (sock == RPC_ANYSOCK) {
+		if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+			perror("svcudp_create: socket creation problem");
+			return ((SVCXPRT *)NULL);
+		}
+		madesock = TRUE;
+	}
+	memset((char *)&addr, 0, sizeof (addr));
+#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+	addr.sin_len = sizeof(addr);
+#endif
+	addr.sin_family = AF_INET;
+	if (bindresvport(sock, &addr)) {
+		addr.sin_port = 0;
+		(void)bind(sock, (struct sockaddr *)&addr, len);
+	}
+	if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
+		perror("svcudp_create - cannot getsockname");
+		if (madesock)
+			(void)close(sock);
+		return ((SVCXPRT *)NULL);
+	}
+	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+	if (xprt == NULL) {
+		(void)fprintf(stderr, "svcudp_create: out of memory\n");
+		return (NULL);
+	}
+	su = (struct svcudp_data *)mem_alloc(sizeof(*su));
+	if (su == NULL) {
+		(void)fprintf(stderr, "svcudp_create: out of memory\n");
+		return (NULL);
+	}
+	su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
+	if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
+		(void)fprintf(stderr, "svcudp_create: out of memory\n");
+		return (NULL);
+	}
+	xdrmem_create(
+	    &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE);
+	su->su_cache = NULL;
+	xprt->xp_p2 = (caddr_t)su;
+	xprt->xp_auth = NULL;
+	xprt->xp_verf.oa_base = su->su_verfbody;
+	xprt->xp_ops = &svcudp_op;
+	xprt->xp_port = ntohs(addr.sin_port);
+	xprt->xp_sock = sock;
+	xprt_register(xprt);
+	return (xprt);
+}
+
+SVCXPRT *
+svcudp_create(int sock)
+{
+
+	return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum xprt_stat
+svcudp_stat(SVCXPRT *xprt)
+{
+
+	return (XPRT_IDLE); 
+}
+
+static bool_t
+svcudp_recv(
+	register SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+        struct msghdr dummy;
+	struct iovec dummy_iov[1];
+	register struct svcudp_data *su = su_data(xprt);
+	register XDR *xdrs = &(su->su_xdrs);
+	register int rlen;
+	char *reply;
+	uint32_t replylen;
+
+    again:
+	memset((char *) &dummy, 0, sizeof(dummy));
+	dummy_iov[0].iov_base = rpc_buffer(xprt);
+	dummy_iov[0].iov_len = (int) su->su_iosz;
+	dummy.msg_iov = dummy_iov;
+	dummy.msg_iovlen = 1;
+	dummy.msg_namelen = xprt->xp_laddrlen = sizeof(struct sockaddr_in);
+	dummy.msg_name = (char *) &xprt->xp_laddr;
+	rlen = recvmsg(xprt->xp_sock, &dummy, MSG_PEEK);
+	if (rlen == -1) {
+	     if (errno == EINTR)
+		  goto again;
+	     else
+		  return (FALSE);
+	}
+	
+	xprt->xp_addrlen = sizeof(struct sockaddr_in);
+	rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
+	    0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
+	if (rlen == -1 && errno == EINTR)
+		goto again;
+	if (rlen < (int) 4*sizeof(uint32_t))
+		return (FALSE);
+	xdrs->x_op = XDR_DECODE;
+	XDR_SETPOS(xdrs, 0);
+	if (! xdr_callmsg(xdrs, msg))
+		return (FALSE);
+	su->su_xid = msg->rm_xid;
+	if (su->su_cache != NULL) {
+		if (cache_get(xprt, msg, &reply, &replylen)) {
+			(void) sendto(xprt->xp_sock, reply, (int) replylen, 0,
+			  (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen);
+			return (TRUE);
+		}
+	}
+	return (TRUE);
+}
+
+static bool_t svcudp_reply(
+	register SVCXPRT *xprt,
+	struct rpc_msg *msg)
+{
+     register struct svcudp_data *su = su_data(xprt);
+     register XDR *xdrs = &(su->su_xdrs);
+     register int slen;
+     register bool_t stat = FALSE;
+     
+     xdrproc_t xdr_results;
+     caddr_t xdr_location;
+     bool_t has_args;
+
+     if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+	 msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+	  has_args = TRUE;
+	  xdr_results = msg->acpted_rply.ar_results.proc;
+	  xdr_location = msg->acpted_rply.ar_results.where;
+	  
+	  msg->acpted_rply.ar_results.proc = xdr_void;
+	  msg->acpted_rply.ar_results.where = NULL;
+     } else
+	  has_args = FALSE;
+	  
+     xdrs->x_op = XDR_ENCODE;
+     XDR_SETPOS(xdrs, 0);
+     msg->rm_xid = su->su_xid;
+     if (xdr_replymsg(xdrs, msg) &&
+	 (!has_args ||
+	  (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) {
+	  slen = (int)XDR_GETPOS(xdrs);
+	  if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
+		     (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
+	      == slen) {
+	       stat = TRUE;
+	       if (su->su_cache && slen >= 0) {
+		    cache_set(xprt, (uint32_t) slen);
+	       }
+	  }
+     }
+     return (stat);
+}
+
+static bool_t
+svcudp_getargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void * args_ptr)
+{
+	if (! SVCAUTH_UNWRAP(xprt->xp_auth, &(su_data(xprt)->su_xdrs),
+			     xdr_args, args_ptr)) {
+		(void)svcudp_freeargs(xprt, xdr_args, args_ptr);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static bool_t
+svcudp_freeargs(
+	SVCXPRT *xprt,
+	xdrproc_t xdr_args,
+	void * args_ptr)
+{
+	register XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+	xdrs->x_op = XDR_FREE;
+	return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcudp_destroy(register SVCXPRT *xprt)
+{
+	register struct svcudp_data *su = su_data(xprt);
+
+	xprt_unregister(xprt);
+	if (xprt->xp_sock != -1)
+		(void)close(xprt->xp_sock);
+	xprt->xp_sock = -1;
+	if (xprt->xp_auth != NULL) {
+		SVCAUTH_DESTROY(xprt->xp_auth);
+		xprt->xp_auth = NULL;
+	}
+	XDR_DESTROY(&(su->su_xdrs));
+	mem_free(rpc_buffer(xprt), su->su_iosz);
+	mem_free((caddr_t)su, sizeof(struct svcudp_data));
+	mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+
+/***********this could be a separate file*********************/
+
+/*
+ * Fifo cache for udp server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define SPARSENESS 4	/* 75% sparse */
+
+#define CACHE_PERROR(msg)	\
+	(void) fprintf(stderr,"%s\n", msg)
+
+#define ALLOC(type, size)	\
+	(type *) mem_alloc((unsigned) (sizeof(type) * (size)))
+
+#define BZERO(addr, type, size)	 \
+	memset((char *) addr, 0, sizeof(type) * (int) (size)) 
+
+/*
+ * An entry in the cache
+ */
+typedef struct cache_node *cache_ptr;
+struct cache_node {
+	/*
+	 * Index into cache is xid, proc, vers, prog and address
+	 */
+	uint32_t cache_xid;
+	rpcproc_t cache_proc;
+	rpcvers_t cache_vers;
+	rpcprog_t cache_prog;
+	struct sockaddr_in cache_addr;
+	/*
+	 * The cached reply and length
+	 */
+	char * cache_reply;
+	uint32_t cache_replylen;
+	/*
+ 	 * Next node on the list, if there is a collision
+	 */
+	cache_ptr cache_next;	
+};
+
+
+
+/*
+ * The entire cache
+ */
+struct udp_cache {
+	uint32_t uc_size;		/* size of cache */
+	cache_ptr *uc_entries;	/* hash table of entries in cache */
+	cache_ptr *uc_fifo;	/* fifo list of entries in cache */
+	uint32_t uc_nextvictim;	/* points to next victim in fifo list */
+	rpcprog_t uc_prog;		/* saved program number */
+	rpcvers_t uc_vers;		/* saved version number */
+	rpcproc_t uc_proc;		/* saved procedure number */
+	struct sockaddr_in uc_addr; /* saved caller's address */
+};
+
+
+/*
+ * the hashing function
+ */
+#define CACHE_LOC(transp, xid)	\
+ (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))	
+
+
+/*
+ * Enable use of the cache. 
+ * Note: there is no disable.
+ */
+int
+svcudp_enablecache(
+	SVCXPRT *transp,
+	uint32_t size)
+{
+	struct svcudp_data *su = su_data(transp);
+	struct udp_cache *uc;
+
+	if (su->su_cache != NULL) {
+		CACHE_PERROR("enablecache: cache already enabled");
+		return(0);	
+	}
+	uc = ALLOC(struct udp_cache, 1);
+	if (uc == NULL) {
+		CACHE_PERROR("enablecache: could not allocate cache");
+		return(0);
+	}
+	uc->uc_size = size;
+	uc->uc_nextvictim = 0;
+	uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+	if (uc->uc_entries == NULL) {
+		CACHE_PERROR("enablecache: could not allocate cache data");
+		return(0);
+	}
+	BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+	uc->uc_fifo = ALLOC(cache_ptr, size);
+	if (uc->uc_fifo == NULL) {
+		CACHE_PERROR("enablecache: could not allocate cache fifo");
+		return(0);
+	}
+	BZERO(uc->uc_fifo, cache_ptr, size);
+	su->su_cache = (char *) uc;
+	return(1);
+}
+
+
+/*
+ * Set an entry in the cache
+ */
+static void
+cache_set(
+	SVCXPRT *xprt,
+	uint32_t replylen)
+{
+	register cache_ptr victim;	
+	register cache_ptr *vicp;
+	register struct svcudp_data *su = su_data(xprt);
+	struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+	u_int loc;
+	char *newbuf;
+
+	/*
+ 	 * Find space for the new entry, either by
+	 * reusing an old entry, or by mallocing a new one
+	 */
+	victim = uc->uc_fifo[uc->uc_nextvictim];
+	if (victim != NULL) {
+		loc = CACHE_LOC(xprt, victim->cache_xid);
+		for (vicp = &uc->uc_entries[loc]; 
+		  *vicp != NULL && *vicp != victim; 
+		  vicp = &(*vicp)->cache_next) 
+				;
+		if (*vicp == NULL) {
+			CACHE_PERROR("cache_set: victim not found");
+			return;
+		}
+		*vicp = victim->cache_next;	/* remote from cache */
+		newbuf = victim->cache_reply;
+	} else {
+		victim = ALLOC(struct cache_node, 1);
+		if (victim == NULL) {
+			CACHE_PERROR("cache_set: victim alloc failed");
+			return;
+		}
+		newbuf = mem_alloc(su->su_iosz);
+		if (newbuf == NULL) {
+			CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
+			return;
+		}
+	}
+
+	/*
+	 * Store it away
+	 */
+	victim->cache_replylen = replylen;
+	victim->cache_reply = rpc_buffer(xprt);
+	rpc_buffer(xprt) = newbuf;
+	xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE);
+	victim->cache_xid = su->su_xid;
+	victim->cache_proc = uc->uc_proc;
+	victim->cache_vers = uc->uc_vers;
+	victim->cache_prog = uc->uc_prog;
+	victim->cache_addr = uc->uc_addr;
+	loc = CACHE_LOC(xprt, victim->cache_xid);
+	victim->cache_next = uc->uc_entries[loc];	
+	uc->uc_entries[loc] = victim;
+	uc->uc_fifo[uc->uc_nextvictim++] = victim;
+	uc->uc_nextvictim %= uc->uc_size;
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found
+ */
+static int
+cache_get(
+	SVCXPRT *xprt,
+	struct rpc_msg *msg,
+	char **replyp,
+	uint32_t *replylenp)
+{
+	u_int loc;
+	register cache_ptr ent;
+	register struct svcudp_data *su = su_data(xprt);
+	register struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+
+#	define EQADDR(a1, a2) (memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
+
+	loc = CACHE_LOC(xprt, su->su_xid);
+	for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
+		if (ent->cache_xid == su->su_xid &&
+		  ent->cache_proc == uc->uc_proc &&
+		  ent->cache_vers == uc->uc_vers &&
+		  ent->cache_prog == uc->uc_prog &&
+		  EQADDR(ent->cache_addr, uc->uc_addr)) {
+			*replyp = ent->cache_reply;
+			*replylenp = ent->cache_replylen;
+			return(1);
+		}
+	}
+	/*
+	 * Failed to find entry
+	 * Remember a few things so we can do a set later
+	 */
+	uc->uc_proc = msg->rm_call.cb_proc;
+	uc->uc_vers = msg->rm_call.cb_vers;
+	uc->uc_prog = msg->rm_call.cb_prog;
+	uc->uc_addr = xprt->xp_raddr;
+	return(0);
+}
+
diff --git a/krb5-1-6/src/lib/rpc/unit-test/Makefile.in b/krb5-1-6/src/lib/rpc/unit-test/Makefile.in
new file mode 100644
index 000000000..fb527fd6a
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/Makefile.in
@@ -0,0 +1,108 @@
+thisconfigdir=../../..
+myfulldir=lib/rpc/unit-test
+mydir=lib/rpc/unit-test
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I.
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS=
+
+OBJS= client.o rpc_test_clnt.o rpc_test_svc.o server.o
+SRCS= client.c rpc_test_clnt.c rpc_test_svc.c server.c
+
+all:: client server
+
+client: client.o rpc_test_clnt.o $(GSSRPC_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o client client.o rpc_test_clnt.o \
+		$(GSSRPC_LIBS) $(KRB5_BASE_LIBS)
+
+server: server.o rpc_test_svc.o $(GSSRPC_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o server server.o rpc_test_svc.o \
+		$(GSSRPC_LIBS) $(KRB5_BASE_LIBS)
+
+client.o server.o: rpc_test.h
+
+# If rpc_test.h and rpc_test_*.c do not work on your system, you can
+# try using rpcgen by uncommenting these lines (be sure to uncomment
+# then in the generated not Makefile.in).
+# rpc_test.h rpc_test_clnt.c rpc_test_svc.c: rpc_test.x
+# 	-rm -f rpc_test_clnt.c rpc_test_svc.c rpc_test.h
+# 	-ln -s $(srcdir)/rpc_test.x .
+# 	rpcgen -l rpc_test.x -o rpc_test_clnt.c
+# 	rpcgen -m rpc_test.x -o rpc_test_svc.c
+# 	rpcgen -h rpc_test.x -o rpc_test.h
+# 
+# clean::
+# 	rm -f rpc_test.h rpc_test_clnt.c rpc_test_svc.c
+# 
+
+check unit-test:: unit-test-@DO_TEST@
+
+unit-test-:
+	@echo "+++"
+	@echo "+++ WARNING: lib/rpc unit tests not run."
+	@echo "+++ Either tcl, runtest, or Perl is unavailable."
+	@echo "+++"
+
+unit-test-ok:: unit-test-body
+
+PASS=@PASS@
+unit-test-body:
+	$(RM) krb5cc_rpc_test_*
+	$(ENV_SETUP) $(START_SERVERS)
+	RPC_TEST_SRVTAB=/tmp/rpc_test_v5srvtab.$$$$ ; export RPC_TEST_SRVTAB ; \
+	trap "echo Failed, cleaning up... ; rm -f $$RPC_TEST_SRVTAB ; $(ENV_SETUP) $(STOP_SERVERS) ; trap '' 0 ; exit 1" 0 1 2 3 14 15 ; \
+	if $(ENV_SETUP) \
+		$(RUNTEST) SERVER=./server CLIENT=./client \
+		KINIT=$(BUILDTOP)/clients/kinit/kinit \
+		KDESTROY=$(BUILDTOP)/clients/kdestroy/kdestroy \
+		PRIOCNTL_HACK=@PRIOCNTL_HACK@ \
+		PASS="$(PASS)" --tool rpc_test $(RUNTESTFLAGS) ; \
+	then \
+		echo Cleaning up... ; \
+		rm -f $$RPC_TEST_SRVTAB krb5cc_rpc_test_* ; \
+		$(ENV_SETUP) $(STOP_SERVERS) ; \
+		trap 0 ; exit 0 ; \
+	else exit 1 ; fi
+
+clean::
+	$(RM) server client
+	$(RM) dbg.log rpc_test.log rpc_test.sum
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)client.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_gssapi.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h client.c rpc_test.h
+$(OUTPRE)rpc_test_clnt.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h rpc_test.h rpc_test_clnt.c
+$(OUTPRE)rpc_test_svc.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/syslog.h \
+  rpc_test.h rpc_test_svc.c
+$(OUTPRE)server.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_gssapi.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/pmap_clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h rpc_test.h server.c
diff --git a/krb5-1-6/src/lib/rpc/unit-test/client.c b/krb5-1-6/src/lib/rpc/unit-test/client.c
new file mode 100644
index 000000000..e66f040a0
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/client.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <gssrpc/rpc.h>
+#include <gssapi/gssapi.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/auth_gssapi.h>
+#include "rpc_test.h"
+
+#define BIG_BUF 4096
+/* copied from auth_gssapi.c for hackery */
+struct auth_gssapi_data {
+     bool_t established;
+     CLIENT *clnt;
+     gss_ctx_id_t context;
+     gss_buffer_desc client_handle;
+     OM_uint32 seq_num;
+     int def_cred;
+
+     /* pre-serialized ah_cred */
+     u_char cred_buf[MAX_AUTH_BYTES];
+     int32_t cred_len;
+};
+#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
+
+extern int auth_debug_gssapi;
+char *whoami;
+
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+static void usage()
+{
+     fprintf(stderr, "usage: %s {-t|-u} [-a] [-s num] [-m num] host service [count]\n",
+	     whoami);
+     exit(1);
+}
+
+int
+main(argc, argv)
+   int argc;
+   char **argv;
+{
+     char        *host, *target, *echo_arg, **echo_resp, buf[BIG_BUF];
+     char	 *prot;
+     CLIENT      *clnt;
+     AUTH	 *tmp_auth;
+     struct rpc_err e;
+     int i, auth_once;
+     unsigned int count;
+     extern int optind;
+     extern char *optarg;
+     extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi;
+     int c;
+
+     extern int krb5_gss_dbg_client_expcreds;
+     krb5_gss_dbg_client_expcreds = 1;
+
+     whoami = argv[0];
+     count = 1026;
+     auth_once = 0;
+     prot = NULL;
+     
+     while ((c = getopt(argc, argv, "a:m:os:tu")) != -1) {
+	  switch (c) {
+	  case 'a':
+	       auth_debug_gssapi = atoi(optarg);
+	       break;
+	  case 'm':
+	       misc_debug_gssapi = atoi(optarg);
+	       break;
+	  case 'o':
+	       auth_once++;
+	       break;
+	  case 's':
+	       svc_debug_gssapi = atoi(optarg);
+	       break;
+	  case 't':
+	       prot = "tcp";
+	       break;
+	  case 'u':
+	       prot = "udp";
+	       break;
+	  case '?':
+	       usage();
+	       break;
+	  }
+     }
+     if (prot == NULL)
+	  usage();
+
+     argv += optind;
+     argc -= optind;
+
+     switch (argc) {
+     case 3:
+	  count = atoi(argv[2]);
+	  if (count > BIG_BUF-1) {
+	    fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF-1);
+	    usage();
+	  }
+     case 2:
+	  host = argv[0];
+	  target = argv[1];
+	  break;
+     default:
+	  usage();
+     }
+     
+     /* client handle to rstat */
+     clnt = clnt_create(host, RPC_TEST_PROG, RPC_TEST_VERS_1, prot);
+     if (clnt == NULL) {
+	  clnt_pcreateerror(whoami);
+	  exit(1);
+     }
+     
+     clnt->cl_auth = auth_gssapi_create_default(clnt, target);
+     if (clnt->cl_auth == NULL) {
+	  clnt_pcreateerror(whoami);
+	  exit(2);
+     }
+     
+     /*
+      * Call the echo service multiple times.
+      */
+     echo_arg = buf;
+     for (i = 0; i < 3; i++) {
+	  sprintf(buf, "testing %d\n", i);
+
+	  echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+	  if (echo_resp == NULL) {
+	       fprintf(stderr, "RPC_TEST_ECHO call %d%s", i,
+		       clnt_sperror(clnt, ""));
+	  }
+	  if (strncmp(*echo_resp, "Echo: ", 6) &&
+	      strcmp(echo_arg, (*echo_resp) + 6) != 0)
+	       fprintf(stderr, "RPC_TEST_ECHO call %d response wrong: "
+		       "arg = %s, resp = %s\n", i, echo_arg, *echo_resp);
+	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
+     }
+
+     /*
+      * Make a call with an invalid verifier and check for error;
+      * server should log error message.  It is important to
+      *increment* seq_num here, since a decrement would be fixed (see
+      * below).  Note that seq_num will be incremented (by
+      * authg_gssapi_refresh) twice, so we need to decrement by three
+      * to reset.
+      */
+     AUTH_PRIVATE(clnt->cl_auth)->seq_num++;
+
+     echo_arg = "testing with bad verf";
+
+     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+     if (echo_resp == NULL) {
+	  CLNT_GETERR(clnt, &e);
+	  if (e.re_status != RPC_AUTHERROR || e.re_why != AUTH_REJECTEDVERF)
+	       clnt_perror(clnt, whoami);
+     } else {
+	  fprintf(stderr, "bad seq didn't cause failure\n");
+     }
+
+     AUTH_PRIVATE(clnt->cl_auth)->seq_num -= 3;
+
+     /*
+      * Make sure we're resyncronized.
+      */
+     echo_arg = "testing for reset";
+     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+     if (echo_resp == NULL)
+	  clnt_perror(clnt, "Sequence number improperly reset");
+     
+     /*
+      * Now simulate a lost server response, and see if
+      * auth_gssapi_refresh recovers.
+      */
+     AUTH_PRIVATE(clnt->cl_auth)->seq_num--;
+     echo_arg = "forcing auto-resynchronization";
+     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+     if (echo_resp == NULL)
+	  clnt_perror(clnt, "Auto-resynchronization failed");
+     
+     /*
+      * Now make sure auto-resyncrhonization actually worked
+      */
+     echo_arg = "testing for resynchronization";
+     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+     if (echo_resp == NULL)
+	  clnt_perror(clnt, "Auto-resynchronization did not work");
+
+     /*
+      * Test fix for secure-rpc/586, part 1: btree keys must be
+      * unique.  Create another context from the same credentials; it
+      * should have the same expiration time and will cause the server
+      * to abort if the clients are not differentiated.
+      * 
+      * Test fix for secure-rpc/586, part 2: btree keys cannot be
+      * mutated in place.  To test this: a second client, *with a
+      * later expiration time*, must be run.  The second client should
+      * destroy itself *after* the first one; if the key-mutating bug
+      * is not fixed, the second client_data will be in the btree
+      * before the first, but its key will be larger; thus, when the
+      * first client calls AUTH_DESTROY, the server won't find it in
+      * the btree and call abort.
+      *
+      * For unknown reasons, running just a second client didn't
+      * tickle the bug; the btree code seemed to guess which node to
+      * look at first.  Running a total of three clients does ticket
+      * the bug.  Thus, the full test sequence looks like this:
+      *
+      * 	kinit -l 20m user && client server test@ddn 200
+      * 	sleep 1
+      * 	kini -l 30m user && client server test@ddn 300
+      * 	sleep 1
+      * 	kinit -l 40m user && client server test@ddn 400
+      */
+     if (! auth_once) {
+	  tmp_auth = clnt->cl_auth;
+	  clnt->cl_auth = auth_gssapi_create_default(clnt, target);
+	  if (clnt->cl_auth == NULL) {
+	       clnt_pcreateerror(whoami);
+	       exit(2);
+	  }
+	  AUTH_DESTROY(clnt->cl_auth);
+	  clnt->cl_auth = tmp_auth;
+     }
+     
+     /*
+      * Try RPC calls with argument/result lengths [0, 1025].  Do
+      * this last, since it takes a while..
+      */
+     echo_arg = buf;
+     memset(buf, 0, count+1);
+     for (i = 0; i < count; i++) {
+	  echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+	  if (echo_resp == NULL) {
+	       fprintf(stderr, "RPC_TEST_LENGTHS call %d%s", i,
+		       clnt_sperror(clnt, ""));
+	       break;
+	  } else {
+	       if (strncmp(*echo_resp, "Echo: ", 6) &&
+		   strcmp(echo_arg, (*echo_resp) + 6) != 0)
+		    fprintf(stderr,
+			    "RPC_TEST_LENGTHS call %d response wrong\n", i);
+	       gssrpc_xdr_free(xdr_wrapstring, echo_resp);
+	  }
+	  
+	  /* cycle from 1 to 255 */
+	  buf[i] = (i % 255) + 1;
+
+	  if (i % 100 == 0) {
+	       fputc('.', stdout);
+	       fflush(stdout);
+	  }
+     }
+     fputc('\n', stdout);
+
+     AUTH_DESTROY(clnt->cl_auth);
+     CLNT_DESTROY(clnt);
+     exit(0);
+}
+
diff --git a/krb5-1-6/src/lib/rpc/unit-test/config/unix.exp b/krb5-1-6/src/lib/rpc/unit-test/config/unix.exp
new file mode 100644
index 000000000..495472e67
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/config/unix.exp
@@ -0,0 +1,125 @@
+#
+# $Id$
+#
+
+set kill /bin/kill
+set sleep /bin/sleep
+set kinit $KINIT
+set kdestroy $KDESTROY
+
+set hostname [exec hostname]
+
+# Hack around Solaris 9 kernel race condition that causes last output
+# from a pty to get dropped.
+if { $PRIOCNTL_HACK } {
+    catch {exec priocntl -s -c FX -m 30 -p 30 -i pid [getpid]}
+    rename spawn oldspawn
+    proc spawn { args } {
+	upvar 1 spawn_id spawn_id
+	set newargs {}
+	set inflags 1
+	set eatnext 0
+	foreach arg $args {
+	    if { $arg == "-ignore" \
+		     || $arg == "-open" \
+		     || $arg == "-leaveopen" } {
+		lappend newargs $arg
+		set eatnext 1
+		continue
+	    }
+	    if [string match "-*" $arg] {
+		lappend newargs $arg
+		continue
+	    }
+	    if { $eatnext } {
+		set eatnext 0
+		lappend newargs $arg
+		continue
+	    }
+	    if { $inflags } {
+		set inflags 0
+		set newargs [concat $newargs {priocntl -e -c FX -p 0}]
+	    }
+	    lappend newargs $arg
+	}
+	set pid [eval oldspawn $newargs]
+	return $pid
+    }
+}
+
+# this will initialize the database and keytab
+load_lib "helpers.exp"
+
+proc rpc_test_version {} {
+	global CLIENT
+	global SERVER
+
+	clone_output "$CLIENT version <unknown>"
+	clone_output "$SERVER version <unknown>"
+}
+
+proc rpc_test_load {} {
+	#
+}
+
+# rpc_test_exit -- clean up and exit
+proc rpc_test_exit {} {
+	global server_id
+	global server_pid
+	global server_started
+	global kill
+
+ 	if {[catch {
+		expect {
+			-i $server_id
+			eof { 
+				fail "server exited!"
+				verbose $expect_out(buffer) 1
+			}
+			timeout { pass "server survived" }
+		}
+	} tmp]} {
+		fail "server exited! (expect failed)"
+	}
+}
+
+#
+# rpc_test_start -- start the rpc_test server running
+#
+proc rpc_test_start { } {
+ 	global SERVER PROT
+	global server_id
+	global server_pid
+	global server_started
+	global env
+
+	if [info exists server_pid] { rpc_test_exit }
+
+	set env(KRB5_KTNAME) FILE:$env(RPC_TEST_SRVTAB)
+
+ 	verbose "% $SERVER" 1
+	set server_pid [spawn $SERVER $PROT]
+	set server_id $spawn_id
+
+	unset env(KRB5_KTNAME)
+
+	set timeout 30
+
+	expect {
+		"running" { }
+		eof { 
+			send_error "server exited!"
+			verbose $expect_out(buffer) 1
+		}
+		timeout { 
+			send_error "server didn't start in $timeout seconds"
+			verbose $expect_out(buffer) 1
+		}
+	}
+
+}
+
+set MULTIPASS {
+    {tcp PROT=-t dummy=[rpc_test_start]}
+    {udp PROT=-u dummy=[rpc_test_start]}
+}
diff --git a/krb5-1-6/src/lib/rpc/unit-test/lib/helpers.exp b/krb5-1-6/src/lib/rpc/unit-test/lib/helpers.exp
new file mode 100644
index 000000000..b69be5b6b
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/lib/helpers.exp
@@ -0,0 +1,236 @@
+if {[info commands exp_version] != {}} {
+	set exp_version_4 [regexp {^4} [exp_version]]
+} else {
+	set exp_version_4 [regexp {^4} [expect_version]]
+}
+
+# Backward compatibility until we're using expect 5 everywhere
+if {$exp_version_4} {
+	global wait_error_index wait_errno_index wait_status_index
+	set wait_error_index 0
+	set wait_errno_index 1
+	set wait_status_index 1
+} else {
+	set wait_error_index 2
+	set wait_errno_index 3
+	set wait_status_index 3
+}
+				
+proc set_from_env {varname default_value} {
+    global env
+    upvar $varname v
+
+    if [info exists env($varname)] {
+	set v $env($varname)
+    } else {
+	set v $default_value
+    }
+}
+proc expect_tcl_prompt {} {
+    global kadmin_tcl_spawn_id
+    expect {
+	-i $kadmin_tcl_spawn_id
+	-re "^% $" { }
+	-re . { perror "unexpected output {$expect_out(buffer)} from subprocess, expecting tcl prompt" }
+	timeout { perror "timeout waiting for tcl prompt" }
+	eof { perror "eof from subprocess when expecting tcl prompt" }
+    }
+}
+proc send_tcl_cmd_await_echo {cmd} {
+    global kadmin_tcl_spawn_id
+    send -i $kadmin_tcl_spawn_id "$cmd\n"
+    expect {
+	-i $kadmin_tcl_spawn_id
+	-ex "$cmd\r\n" { }
+	timeout { perror "timeout waiting for tcl subprocess to echo input" }
+	eof { perror "eof waiting for tcl subprocess to echo input" }
+    }
+}
+proc expect_kadm_ok {} {
+    global kadmin_tcl_spawn_id
+    expect {
+	-i $kadmin_tcl_spawn_id
+	-re "^OK OVSEC_KADM_OK \[^\n\]*\n" {}
+	-re "^ERROR \[^\n\]*\n" { perror "kadmin tcl subprocess reported unexpected error" }
+	-re "^marshall_new_creds: \[^\n\]*\n" { exp_continue }
+	-re "^gssapi_\[^\n\]*\n" { exp_continue }
+	-re "^\r?\n" { exp_continue }
+	eof	{ perror "kadmin tcl subprocess died" }
+	default { perror "didn't get ok back" }
+    }
+}
+# trying to translate rpc_test_setup.sh into inline tcl...
+proc setup_database {} {
+    global env spawn_id kadmin_tcl_spawn_id TESTDIR MAKE_KEYTAB CANON_HOST
+
+    # XXXXX
+    set_from_env TOP {/x/x/x/x/x}
+    send_user "TOP=$TOP\n"
+
+    set_from_env TESTDIR $env(TOP)/testing
+    set_from_env CLNTTCL $TESTDIR/util/ovsec_kadm_clnt_tcl
+    set_from_env TCLUTIL $TESTDIR/tcl/util.t
+    set env(TCLUTIL) $TCLUTIL
+    set_from_env MAKE_KEYTAB $TESTDIR/scripts/make-host-keytab.pl
+    set env(PATH) "$TOP/install/admin:$env(PATH)"
+
+    # $VERBOSE ?
+
+    if [info exists spawn_id] { set x $spawn_id }
+    spawn $CLNTTCL
+    set kadmin_tcl_spawn_id $spawn_id
+    if [info exists x] { set spawn_id $x }
+
+    expect_tcl_prompt
+    # tcl 8.4 for some reason screws up autodetection of output EOL
+    # translation.  Work around it for now.
+    send_tcl_cmd_await_echo "if { \[info commands fconfigure\] != \"\" } { fconfigure stdout -translation lf }"
+    expect_tcl_prompt
+    send_tcl_cmd_await_echo "source {$TCLUTIL}"
+    expect_tcl_prompt
+    send_tcl_cmd_await_echo "set h {$CANON_HOST}"
+    expect {
+	-ex "$CANON_HOST\r\n" { }
+	timeout { perror "timeout waiting for subprocess" }
+	eof { perror "eof from subprocess" }
+    }
+    expect_tcl_prompt
+
+    send_tcl_cmd_await_echo {ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
+    expect_kadm_ok
+    expect "^% "
+    send_tcl_cmd_await_echo {ovsec_kadm_create_principal $server_handle [simple_principal server/$h] {OVSEC_KADM_PRINCIPAL} admin}
+    expect_kadm_ok
+    expect "^% "
+    send_tcl_cmd_await_echo {ovsec_kadm_randkey_principal $server_handle server/$h key}
+    expect_kadm_ok
+    expect "^% "
+    send_tcl_cmd_await_echo {ovsec_kadm_create_principal $server_handle [simple_principal notserver/$h] {OVSEC_KADM_PRINCIPAL} admin}
+    expect_kadm_ok
+    expect "^% "
+    send_tcl_cmd_await_echo {ovsec_kadm_randkey_principal $server_handle notserver/$h key}
+    expect_kadm_ok
+    expect "^% "
+    send_tcl_cmd_await_echo {ovsec_kadm_destroy $server_handle}
+    expect_kadm_ok
+    expect "^% "
+    wait -nowait -i $spawn_id
+    close -i $spawn_id
+}
+
+if ![info exists CANON_HOST] {
+    set CANON_HOST [exec $env(QUALNAME)]
+    setup_database
+    file delete $env(RPC_TEST_SRVTAB)
+    exec $env(MAKE_KEYTAB) -princ "server/$CANON_HOST" $env(RPC_TEST_SRVTAB)
+}
+
+
+proc kinit {princ pass lifetime} {
+	global kinit
+	global wait_error_index wait_errno_index wait_status_index
+
+	spawn -noecho $kinit -5 -l $lifetime $princ
+	expect {
+		-re "Password for $princ.*: " { send "$pass\n"; expect eof }
+		timeout { perror "Timeout waiting for kinit"; close }
+		eof
+	}
+
+	set ret [wait]
+	if {[lindex $ret $wait_error_index] == -1} {
+	 	perror \
+	    "wait(kinit $princ) returned error [lindex $ret $wait_errno_index]"
+	} else {
+		if {[lindex $ret $wait_status_index] != 0} {
+			perror \
+		    "kinit $princ failed with [lindex $ret $wait_status_index]"
+		}
+	}
+}
+
+proc flush_server {} {
+	global server_id
+	global expect_out
+
+	verbose "flushing server output" 1
+
+	while {1} {
+		set timeout 5
+
+		expect {
+			-i $server_id
+			-re "^.+$" {
+			    verbose "server output: $expect_out(buffer)"
+			}
+			timeout { break }
+		}
+	}
+}
+
+proc start_client {testname ccname user password lifetime count
+		  {target ""}} {
+	global env CLIENT PROT hostname spawn_id verbose
+
+	if {$target == ""} {
+		set target "server@$hostname"
+	}
+
+	set env(KRB5CCNAME) FILE:[pwd]/krb5cc_rpc_test_$ccname
+	kinit $user $password $lifetime
+
+	if {$verbose > 0} {
+		spawn $CLIENT -a 1 -s 1 -m 1 $PROT $hostname $target $count
+	} else {
+		spawn $CLIENT $PROT $hostname $target $count
+	}
+
+	verbose "$testname: client $ccname started"
+
+	unset env(KRB5CCNAME)
+}
+
+proc eof_client {testname ccname id status} {
+	verbose "$testname: eof'ing for client $ccname" 1
+
+	expect {
+		-i $id
+		-re "^marshall_new_creds\[^\n\]*\n" { exp_continue }
+		-re "^gssapi_\[^\n\]*\n" { exp_continue }
+		-re "^\r?\n" { exp_continue }
+		eof { verbose $expect_out(buffer) 1 }
+		timeout { 
+			fail "$testname: timeout waiting for client $ccname to exit"
+		}
+	}
+	wait_client $testname $ccname $id $status
+}
+
+
+proc wait_client {testname ccname id status} {
+	global env
+	global kill
+	global kdestroy
+	global wait_error_index wait_errno_index wait_status_index
+
+	verbose "$testname: waiting for client $ccname" 1
+
+	set ret [wait -i $id]
+	if {[lindex $ret $wait_error_index] == -1} {
+		fail \
+       "$testname: wait $ccname returned error [lindex $ret $wait_errno_index]"
+	} else {
+		if {[lindex $ret $wait_status_index] == $status} {
+			pass "$testname: client $ccname"
+		} else {
+			fail "$testname: client $ccname: unexpected return status [lindex $ret $wait_status_index], should be $status."
+		}
+	}
+
+	set env(KRB5CCNAME) FILE:[pwd]/krb5cc_rpc_test_$ccname
+ 	if {[catch "exec $kdestroy -5"] != 0} {
+ 		perror "$testname: cannot destroy client $ccname ccache"
+ 	}
+
+	unset env(KRB5CCNAME)
+}
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/expire.exp b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/expire.exp
new file mode 100644
index 000000000..f5841011f
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/expire.exp
@@ -0,0 +1,46 @@
+set timeout 40
+
+load_lib "helpers.exp"
+
+global spawn_id
+
+proc expired {} {
+    global spawn_id server_id
+
+    start_client expired expired testuser notathena -1m 100
+    eof_client expired expired $spawn_id 2
+
+    expect {
+	-i $server_id
+	-re "rpc_test server: Authen.*failed:.*credential.*expired" { pass "expired" }
+	timeout { fail "expired: timeout waiting for expired creds error" }
+    }
+
+    flush_server
+}
+expired
+
+proc overlap {} {
+    global spawn_id
+
+    start_client expire 1 testuser notathena 20m 100
+    set client1_id $spawn_id
+    flush_server
+    
+    start_client expire 2 testuser notathena 40m 300
+    set client2_id $spawn_id
+    flush_server
+    
+    start_client expire 3 testuser notathena 60m 500
+    set client3_id $spawn_id
+    flush_server
+    
+    eof_client expire 1 $client1_id 0
+    eof_client expire 2 $client2_id 0
+    eof_client expire 3 $client3_id 0
+
+    flush_server
+}
+overlap
+
+
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp
new file mode 100644
index 000000000..7cdda8af1
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp
@@ -0,0 +1,95 @@
+set timeout 120
+
+load_lib "helpers.exp"
+
+global spawn_id
+global server_id
+
+# Start the client and do a full run
+start_client "full run" fullrun testuser notathena 8h 1026
+set client_id $spawn_id
+
+#
+# test: did we get 11 dots?
+#
+verbose "Starting RPC echo test.  This will take about 50 seconds.\n"
+
+set ver_line "rpc_test server: bad verifier\[^\r\n\]*\[\r\n]+"
+
+set dots 0
+set server_lines 0
+while {1} {
+	set oldtimeout $timeout
+	set timeout 5
+	while {1} {
+		expect {
+			-i $server_id
+			-re $ver_line {
+				verbose "Got line from server."
+				incr server_lines
+			}
+			default {
+				break
+			}
+		}
+	}
+	set timeout $oldtimeout
+	expect {
+		-i $client_id
+		. { 
+			incr dots
+			verbose "$expect_out(buffer)" 1
+			if ($dots==11) { break }
+		}
+		eof {
+			#
+			# test: was the exit status right?
+			#
+			wait_client "full run" fullrun $client_id 0
+			break
+		}
+
+		timeout { 
+			verbose "Timeout waiting for dot\n" 1
+			fail "full run: timeout waiting for dot"
+			break
+		}
+
+	}
+}
+if {$dots==11} {
+	pass "fullrun: echo test"
+} else {
+	fail "fullrun: echo test: expected 11 dots, got $dots"
+}
+
+#
+# test: server logged four bad verifiers?
+#
+verbose "full run: checking server output"
+
+# Small timeout, since the server should have already printed everything
+set timeout 5
+
+while {$server_lines < 4} {
+	expect {
+		-i $server_id
+		-re $ver_line {
+			incr server_lines
+		}
+		-re ".+\r\n" {
+			verbose "Unexpected server output: $expect_out(buffer)"
+		}
+		default {
+			break
+		}
+	}
+}
+
+if {$server_lines == 4} {
+	pass "fullrun: bad verifiers"
+} else {
+	fail "fullrun: expected four bad verifiers, got $server_lines"
+}
+
+flush_server
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp
new file mode 100644
index 000000000..2bb936ab5
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp
@@ -0,0 +1,27 @@
+set timeout 30
+
+load_lib "helpers.exp"
+
+global spawn_id
+global server_id
+global hostname
+
+start_client "gss err" gsserr testuser notathena 8h 1026 notserver@$hostname
+
+eof_client "gss err" gsserr $spawn_id 2
+
+#
+# test: server logged an authentication attempted failed?
+#
+verbose "gss err: checking server output"
+
+expect {
+	-i $server_id
+	-re "rpc_test server: Authent.*failed: .* Wrong princ" {
+		pass "gss err: server logged auth error"
+	}
+	eof { fail "gss err: server exited" }
+	timeout { fail "gss err: timeout waiting for server output" }
+}
+
+flush_server
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test.h b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.h
new file mode 100644
index 000000000..2ad039955
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.h
@@ -0,0 +1,13 @@
+#ifndef _RPC_TEST_H_RPCGEN
+#define	_RPC_TEST_H_RPCGEN
+
+#include <gssrpc/rpc.h>
+
+#define	RPC_TEST_PROG ((unsigned long)(1000001))
+#define	RPC_TEST_VERS_1 ((unsigned long)(1))
+#define	RPC_TEST_ECHO ((unsigned long)(1))
+extern char ** rpc_test_echo_1_svc(char **, struct svc_req *);
+extern char ** rpc_test_echo_1(char **, CLIENT *);
+extern void rpc_test_prog_1_svc(struct svc_req *, SVCXPRT *);
+
+#endif /* !_RPC_TEST_H_RPCGEN */
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test.x b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.x
new file mode 100644
index 000000000..e9ae27c97
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test.x
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ * 
+ * $Log$
+ * Revision 1.2  1996/07/22 20:41:42  marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches.  This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964.  before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.1.4.1  1996/07/18 04:20:04  marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+# Revision 1.1.2.1  1996/06/20  23:42:06  marc
+# File added to the repository on a branch
+#
+# Revision 1.1  1993/11/03  23:53:58  bjaspan
+# Initial revision
+#
+ */
+
+program RPC_TEST_PROG {
+	version RPC_TEST_VERS_1 {
+		string RPC_TEST_ECHO(string) = 1;
+	} = 1;
+} = 1000001;
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test_clnt.c b/krb5-1-6/src/lib/rpc/unit-test/rpc_test_clnt.c
new file mode 100644
index 000000000..736392551
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test_clnt.c
@@ -0,0 +1,22 @@
+#include "rpc_test.h"
+#include <string.h>
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+char **
+rpc_test_echo_1(argp, clnt)
+	char **argp;
+	CLIENT *clnt;
+{
+	static char *clnt_res;
+
+	memset((char *)&clnt_res, 0, sizeof (clnt_res));
+	if (clnt_call(clnt, RPC_TEST_ECHO,
+		(xdrproc_t) xdr_wrapstring, (caddr_t) argp,
+		(xdrproc_t) xdr_wrapstring, (caddr_t) &clnt_res,
+		TIMEOUT) != RPC_SUCCESS) {
+		return (NULL);
+	}
+	return (&clnt_res);
+}
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test_setup.sh b/krb5-1-6/src/lib/rpc/unit-test/rpc_test_setup.sh
new file mode 100755
index 000000000..0f8ca9d93
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test_setup.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# This script performs additional setup for the RPC unit test.  It
+# assumes that gmake has put TOP and RPC_TEST_SRVTAB into the
+# environment. 
+#
+# $Id$
+# $Source$
+
+DUMMY=${TESTDIR=$TOP/testing}
+DUMMY=${CLNTTCL=$TESTDIR/util/ovsec_kadm_clnt_tcl}
+DUMMY=${TCLUTIL=$TESTDIR/tcl/util.t}; export TCLUTIL
+DUMMY=${MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl}
+
+if $VERBOSE; then
+	REDIRECT=
+else
+	REDIRECT='>/dev/null'
+fi
+
+PATH=$TOP/install/admin:$PATH; export PATH
+
+CANON_HOST=`$QUALNAME`
+export CANON_HOST
+
+cat - > /tmp/rpc_test_setup$$ <<\EOF
+source $env(TCLUTIL)
+set h $env(CANON_HOST)
+puts stdout [ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle]
+if ![info exists server_handle] { exit 1 }
+puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal server/$h] {OVSEC_KADM_PRINCIPAL} admin]
+puts stdout [ovsec_kadm_randkey_principal $server_handle server/$h key]
+puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal notserver/$h] {OVSEC_KADM_PRINCIPAL} admin]
+puts stdout [ovsec_kadm_randkey_principal $server_handle notserver/$h key]
+puts stdout [ovsec_kadm_destroy $server_handle]
+EOF
+eval "$CLNTTCL $REDIRECT < /tmp/rpc_test_setup$$"
+if test $? != 0 ; then
+    rm /tmp/rpc_test_setup$$
+    echo 1>&2 error setting up database for tests
+    exit 1
+fi
+rm /tmp/rpc_test_setup$$
+
+rm -f $RPC_TEST_SRVTAB
+
+eval $MAKE_KEYTAB -princ server/$CANON_HOST $RPC_TEST_SRVTAB $REDIRECT
+
+# grep -s "$CANON_HOST SECURE-TEST.OV.COM" /etc/krb.realms
+# if [ $? != 0 ]; then
+# 	eval echo \"Adding \$CANON_HOST SECURE-TEST.OV.COM to /etc/krb.realms\" $REDIRECT
+# 	ed /etc/krb.realms <<EOF >/dev/null
+# 1i
+# $CANON_HOST SECURE-TEST.OV.COM
+# .
+# w
+# q
+# EOF
+# fi
diff --git a/krb5-1-6/src/lib/rpc/unit-test/rpc_test_svc.c b/krb5-1-6/src/lib/rpc/unit-test/rpc_test_svc.c
new file mode 100644
index 000000000..4200d955c
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/rpc_test_svc.c
@@ -0,0 +1,74 @@
+#include "rpc_test.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* getenv, exit */
+#include <sys/types.h>
+#include <syslog.h>
+
+/* States a server can be in wrt request */
+
+#define	_IDLE 0
+#define	_SERVED 1
+
+static int _rpcsvcstate = _IDLE;	/* Set when a request is serviced */
+static int _rpcsvccount = 0;		/* Number of requests being serviced */
+
+static
+void _msgout(msg)
+	char *msg;
+{
+	syslog(LOG_ERR, msg);
+}
+
+void
+rpc_test_prog_1_svc(rqstp, transp)
+	struct svc_req *rqstp;
+	register SVCXPRT *transp;
+{
+	union {
+		char *rpc_test_echo_1_arg;
+	} argument;
+	char *result;
+	bool_t (*xdr_argument)(), (*xdr_result)();
+	char *(*local)();
+
+	_rpcsvccount++;
+	switch (rqstp->rq_proc) {
+	case NULLPROC:
+		(void) svc_sendreply(transp, xdr_void,
+			(char *)NULL);
+		_rpcsvccount--;
+		_rpcsvcstate = _SERVED;
+		return;
+
+	case RPC_TEST_ECHO:
+		xdr_argument = xdr_wrapstring;
+		xdr_result = xdr_wrapstring;
+		local = (char *(*)()) rpc_test_echo_1_svc;
+		break;
+
+	default:
+		svcerr_noproc(transp);
+		_rpcsvccount--;
+		_rpcsvcstate = _SERVED;
+		return;
+	}
+	(void) memset((char *)&argument, 0, sizeof (argument));
+	if (!svc_getargs(transp, xdr_argument, &argument)) {
+		svcerr_decode(transp);
+		_rpcsvccount--;
+		_rpcsvcstate = _SERVED;
+		return;
+	}
+	result = (*local)(&argument, rqstp);
+	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+		svcerr_systemerr(transp);
+	}
+	if (!svc_freeargs(transp, xdr_argument, &argument)) {
+		_msgout("unable to free arguments");
+		exit(1);
+	}
+	_rpcsvccount--;
+	_rpcsvcstate = _SERVED;
+	return;
+}
diff --git a/krb5-1-6/src/lib/rpc/unit-test/server.c b/krb5-1-6/src/lib/rpc/unit-test/server.c
new file mode 100644
index 000000000..d4f0d8c6a
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/unit-test/server.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <signal.h>
+#include <gssrpc/rpc.h>
+#include <gssrpc/pmap_clnt.h>
+#include <arpa/inet.h>  /* inet_ntoa */
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssrpc/auth_gssapi.h>
+#include <sys/param.h>	/* MAXHOSTNAMELEN */
+#include "rpc_test.h"
+
+extern int svc_debug_gssapi, misc_debug_gssapi;
+
+void rpc_test_badauth(OM_uint32 major, OM_uint32 minor,
+		 struct sockaddr_in *addr, caddr_t data);
+void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char
+		 *error, char *data);
+void log_badauth_display_status(OM_uint32 major, OM_uint32 minor);
+void log_badauth_display_status_1(OM_uint32 code, int type, int rec);
+static void rpc_test_badverf(gss_name_t client, gss_name_t server,
+			     struct svc_req *rqst, struct rpc_msg *msg,
+			     caddr_t data);
+
+#ifndef SERVICE_NAME
+#define SERVICE_NAME "server"
+#endif
+
+static void usage()
+{
+     fprintf(stderr, "Usage: server {-t|-u} [svc-debug] [misc-debug]\n");
+     exit(1);
+}
+
+#ifdef POSIX_SIGNALS
+static void handlesig(int dummy)
+#else
+static void handlesig(void)
+#endif
+{
+    exit(0);
+}
+
+int
+main(int argc, char **argv)
+{
+     int c, prot;
+     auth_gssapi_name names[2];
+     register SVCXPRT *transp;
+     extern int optind;
+#ifdef POSIX_SIGNALS
+     struct sigaction sa;
+#endif     
+
+     names[0].name = SERVICE_NAME;
+     names[0].type = (gss_OID) gss_nt_service_name;
+     names[1].name = 0;
+     names[1].type = 0;
+
+     prot = 0;
+     while ((c = getopt(argc, argv, "tu")) != -1) {
+	  switch (c) {
+	  case 't':
+	       prot = IPPROTO_TCP;
+	       break;
+	  case 'u':
+	       prot = IPPROTO_UDP;
+	       break;
+	  case '?':
+	       usage();
+	       break;
+	  }
+     }
+     if (prot == 0)
+	  usage();
+
+     argv += optind;
+     argc -= optind;
+
+     switch (argc) {
+     case 2:
+	  misc_debug_gssapi = atoi(argv[1]);
+     case 1:
+	  svc_debug_gssapi = atoi(argv[0]);
+     case 0:
+	  break;
+     default:
+	  usage();
+	  exit(1);
+     }
+
+     (void) pmap_unset(RPC_TEST_PROG, RPC_TEST_VERS_1);
+
+     if (prot == IPPROTO_TCP)
+	  transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+     else
+	  transp = svcudp_create(RPC_ANYSOCK);
+     if (transp == NULL) {
+	  fprintf(stderr, "cannot create tcp service.");
+	  exit(1);
+     }
+     if (!svc_register(transp, RPC_TEST_PROG, RPC_TEST_VERS_1,
+		       rpc_test_prog_1_svc, prot)) { 
+	  fprintf(stderr,
+		  "unable to register (RPC_TEST_PROG, RPC_TEST_VERS_1, %s).",
+		  prot == IPPROTO_TCP ? "tcp" : "udp");
+	  exit(1);
+     }
+     
+     if (svcauth_gssapi_set_names(names, 0) == FALSE) {
+	  fprintf(stderr, "unable to set gssapi names\n");
+	  exit(1);
+     }
+
+     svcauth_gssapi_set_log_badauth_func(rpc_test_badauth, NULL);
+     svcauth_gssapi_set_log_badverf_func(rpc_test_badverf, NULL);
+     svcauth_gssapi_set_log_miscerr_func(log_miscerr, NULL);
+
+#ifdef POSIX_SIGNALS
+     (void) sigemptyset(&sa.sa_mask);
+     sa.sa_flags = 0;
+     sa.sa_handler = handlesig;
+     (void) sigaction(SIGHUP, &sa, NULL);
+     (void) sigaction(SIGINT, &sa, NULL);
+     (void) sigaction(SIGTERM, &sa, NULL);
+#else
+     signal(SIGHUP, handlesig);
+     signal(SIGINT, handlesig);
+     signal(SIGTERM, handlesig);
+#endif
+     printf("running\n");
+     
+     svc_run();
+     fprintf(stderr, "svc_run returned");
+     exit(1);
+     /* NOTREACHED */
+}
+
+char **rpc_test_echo_1_svc(char **arg, struct svc_req *h)
+{
+     static char *res = NULL;
+
+     if (res)
+	  free(res);
+     res = (char *) malloc(strlen(*arg) + strlen("Echo: ") + 1);
+     sprintf(res, "Echo: %s", *arg);
+     return &res;
+}
+
+static void rpc_test_badverf(gss_name_t client, gss_name_t server,
+			     struct svc_req *rqst, struct rpc_msg *msg,
+			     caddr_t data)
+{
+     OM_uint32 minor_stat;
+     gss_OID type;
+     gss_buffer_desc client_name, server_name;
+
+     (void) gss_display_name(&minor_stat, client, &client_name, &type);
+     (void) gss_display_name(&minor_stat, server, &server_name, &type);
+
+     printf("rpc_test server: bad verifier from %.*s at %s:%d for %.*s\n",
+	    (int) client_name.length, (char *) client_name.value,
+	    inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr), 
+	    ntohs(rqst->rq_xprt->xp_raddr.sin_port),
+	    (int) server_name.length, (char *) server_name.value);
+
+     (void) gss_release_buffer(&minor_stat, &client_name);
+     (void) gss_release_buffer(&minor_stat, &server_name);
+}
+
+/*
+ * Function: log_badauth
+ *
+ * Purpose: Callback from GSS-API Sun RPC for authentication
+ * failures/errors.
+ *
+ * Arguments:
+ * 	major 		(r) GSS-API major status
+ * 	minor		(r) GSS-API minor status
+ * 	addr		(r) originating address
+ * 	data		(r) arbitrary data (NULL), not used
+ *
+ * Effects:
+ *
+ * Logs the GSS-API error to stdout.
+ */
+void rpc_test_badauth(OM_uint32 major, OM_uint32 minor,
+		 struct sockaddr_in *addr, caddr_t data)
+{
+     char *a;
+     
+     /* Authentication attempt failed: <IP address>, <GSS-API error */
+     /* strings> */
+
+     a = inet_ntoa(addr->sin_addr);
+
+     printf("rpc_test server: Authentication attempt failed: %s", a);
+     log_badauth_display_status(major, minor);
+     printf("\n");
+}
+
+void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg,
+		 char *error, char *data)
+{
+     char *a;
+     
+     a = inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr);
+     printf("Miscellaneous RPC error: %s, %s\n", a, error);
+}
+
+void log_badauth_display_status(OM_uint32 major, OM_uint32 minor)
+{
+     log_badauth_display_status_1(major, GSS_C_GSS_CODE, 0);
+     log_badauth_display_status_1(minor, GSS_C_MECH_CODE, 0);
+}
+
+void log_badauth_display_status_1(OM_uint32 code, int type, int rec)
+{
+     OM_uint32 gssstat, minor_stat, msg_ctx;
+     gss_buffer_desc msg;
+
+     msg_ctx = 0;
+     while (1) {
+	  gssstat = gss_display_status(&minor_stat, code,
+				       type, GSS_C_NULL_OID,
+				       &msg_ctx, &msg);
+	  if (gssstat != GSS_S_COMPLETE) {
+ 	       if (!rec) {
+		    log_badauth_display_status_1(gssstat,GSS_C_GSS_CODE,1); 
+		    log_badauth_display_status_1(minor_stat,
+						 GSS_C_MECH_CODE, 1);
+	       } else
+		    printf("GSS-API authentication error %.*s: "
+			   "recursive failure!\n", (int) msg.length, 
+			   (char *)msg.value);
+	       return;
+	  }
+	  
+	  printf(", %.*s", (int) msg.length, (char *)msg.value); 
+	  (void) gss_release_buffer(&minor_stat, &msg);
+	  
+	  if (!msg_ctx)
+	       break;
+     }
+}
diff --git a/krb5-1-6/src/lib/rpc/xdr.c b/krb5-1-6/src/lib/rpc/xdr.c
new file mode 100644
index 000000000..ec0d27717
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr.c
@@ -0,0 +1,637 @@
+/* @(#)xdr.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
+#endif
+
+/*
+ * xdr.c, Generic XDR routines implementation.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ *
+ * These are the "generic" xdr routines used to serialize and de-serialize
+ * most common data items.  See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+
+/*
+ * constants specific to the xdr "protocol"
+ */
+#define XDR_FALSE	((long) 0)
+#define XDR_TRUE	((long) 1)
+#define LASTUNSIGNED	((u_int) 0-1)
+
+/*
+ * for unit alignment
+ */
+static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+
+/*
+ * Free a data structure using XDR
+ * Not a filter, but a convenient utility nonetheless
+ */
+void
+xdr_free(xdrproc_t proc, void *objp)
+{
+	XDR x;
+	
+	x.x_op = XDR_FREE;
+	(*proc)(&x, objp);
+}
+
+/*
+ * XDR nothing
+ */
+bool_t
+xdr_void(XDR *xdrs, void *addr)
+{
+
+	return (TRUE);
+}
+
+/*
+ * XDR integers
+ */
+bool_t
+xdr_int(XDR *xdrs, int *ip)
+{
+	long l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		if (*ip > 0x7fffffffL || *ip < -0x7fffffffL - 1L)
+			return (FALSE);
+
+		l = (long) *ip;
+		return (XDR_PUTLONG(xdrs, &l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, &l))
+			return (FALSE);
+
+		if (l > INT_MAX || l < INT_MIN)
+			return (FALSE);
+
+		*ip = (int) l;
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	/*NOTREACHED*/
+	return(FALSE);
+}
+
+/*
+ * XDR unsigned integers
+ */
+bool_t
+xdr_u_int(XDR *xdrs, u_int *up)
+{
+	u_long l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		if (*up > 0xffffffffUL)
+			return (FALSE);
+
+		l = (u_long)*up;
+		return (XDR_PUTLONG(xdrs, (long *) &l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, (long *) &l))
+			return (FALSE);
+
+		if (l > UINT_MAX)
+			return (FALSE);
+
+		*up = (u_int) l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	/*NOTREACHED*/
+	return(FALSE);
+}
+
+/*
+ * XDR long integers
+ */
+bool_t
+xdr_long(XDR *xdrs, long *lp)
+{
+
+	switch (xdrs->x_op) {
+	case XDR_ENCODE:
+		if (*lp > 0x7fffffffL || *lp < -0x7fffffffL - 1L)
+			return (FALSE);
+
+		return (XDR_PUTLONG(xdrs, lp));
+
+	case XDR_DECODE:
+		return (XDR_GETLONG(xdrs, lp));
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR unsigned long integers
+ */
+bool_t
+xdr_u_long(XDR *xdrs, u_long *ulp)
+{
+
+	switch (xdrs->x_op) {
+	case XDR_ENCODE:
+		if (*ulp > 0xffffffffUL)
+			return (FALSE);
+
+		return (XDR_PUTLONG(xdrs, (long *) ulp));
+
+	case XDR_DECODE:
+		return (XDR_GETLONG(xdrs, (long *) ulp));
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR short integers
+ */
+bool_t
+xdr_short(register XDR *xdrs, short *sp)
+{
+	long l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		l = (long) *sp;
+		return (XDR_PUTLONG(xdrs, &l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, &l)) {
+			return (FALSE);
+		}
+		if (l > SHRT_MAX || l < SHRT_MIN)
+			return (FALSE);
+
+		*sp = (short) l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short(register XDR *xdrs, u_short *usp)
+{
+	u_long l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		l = (u_long) *usp;
+		return (XDR_PUTLONG(xdrs, (long *) &l));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, (long *) &l)) {
+			return (FALSE);
+		}
+		*usp = (u_short) l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+
+/*
+ * XDR a char
+ */
+bool_t
+xdr_char(XDR *xdrs, char *cp)
+{
+	int i;
+
+	i = (*cp);
+	if (!xdr_int(xdrs, &i)) {
+		return (FALSE);
+	}
+	*cp = i;
+	return (TRUE);
+}
+
+/*
+ * XDR an unsigned char
+ */
+bool_t
+xdr_u_char(XDR *xdrs, u_char *cp)
+{
+	u_int u;
+
+	u = (*cp);
+	if (!xdr_u_int(xdrs, &u)) {
+		return (FALSE);
+	}
+	*cp = u;
+	return (TRUE);
+}
+
+/*
+ * XDR booleans
+ */
+bool_t
+xdr_bool(register XDR *xdrs, bool_t *bp)
+{
+	long lb;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		lb = *bp ? XDR_TRUE : XDR_FALSE;
+		return (XDR_PUTLONG(xdrs, &lb));
+
+	case XDR_DECODE:
+		if (!XDR_GETLONG(xdrs, &lb)) {
+			return (FALSE);
+		}
+		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR enumerations
+ */
+bool_t
+xdr_enum(XDR *xdrs, enum_t *ep)
+{
+#ifndef lint
+	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
+
+	/*
+	 * enums are treated as ints
+	 */
+	if (sizeof (enum sizecheck) == sizeof (long)) {
+		return (xdr_long(xdrs, (long *)ep));
+	} else if (sizeof (enum sizecheck) == sizeof (int)) {
+		return (xdr_int(xdrs, (int *)ep));
+	} else if (sizeof (enum sizecheck) == sizeof (short)) {
+		return (xdr_short(xdrs, (short *)ep));
+	} else {
+		return (FALSE);
+	}
+#else
+	(void) (xdr_short(xdrs, (short *)ep));
+	return (xdr_long(xdrs, (long *)ep));
+#endif
+}
+
+/*
+ * XDR opaque data
+ * Allows the specification of a fixed size sequence of opaque bytes.
+ * cp points to the opaque object and cnt gives the byte length.
+ */
+bool_t
+xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt)
+{
+	register u_int rndup;
+	static int crud[BYTES_PER_XDR_UNIT];
+
+	/*
+	 * if no data we are done
+	 */
+	if (cnt == 0)
+		return (TRUE);
+
+	/*
+	 * round byte count to full xdr units
+	 */
+	rndup = cnt % BYTES_PER_XDR_UNIT;
+	if (rndup > 0)
+		rndup = BYTES_PER_XDR_UNIT - rndup;
+
+	if (xdrs->x_op == XDR_DECODE) {
+		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
+			return (FALSE);
+		}
+		if (rndup == 0)
+			return (TRUE);
+		return (XDR_GETBYTES(xdrs, (caddr_t) (void *)crud, rndup));
+	}
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
+			return (FALSE);
+		}
+		if (rndup == 0)
+			return (TRUE);
+		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
+	}
+
+	if (xdrs->x_op == XDR_FREE) {
+		return (TRUE);
+	}
+
+	return (FALSE);
+}
+
+/*
+ * XDR counted bytes
+ * *cpp is a pointer to the bytes, *sizep is the count.
+ * If *cpp is NULL maxsize bytes are allocated
+ */
+bool_t
+xdr_bytes(
+	XDR *xdrs,
+	char **cpp,
+	u_int *sizep,
+	u_int maxsize)
+{
+	register char *sp = *cpp;  /* sp is the actual string pointer */
+	register u_int nodesize;
+
+	/*
+	 * first deal with the length since xdr bytes are counted
+	 */
+	if (! xdr_u_int(xdrs, sizep)) {
+		return (FALSE);
+	}
+	nodesize = *sizep;
+	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
+		return (FALSE);
+	}
+
+	/*
+	 * now deal with the actual bytes
+	 */
+	switch (xdrs->x_op) {
+
+	case XDR_DECODE:
+		if (nodesize == 0) {
+			return (TRUE);
+		}
+		if (sp == NULL) {
+			*cpp = sp = (char *)mem_alloc(nodesize);
+		}
+		if (sp == NULL) {
+			(void) fprintf(stderr, "xdr_bytes: out of memory\n");
+			return (FALSE);
+		}
+		/* fall into ... */
+
+	case XDR_ENCODE:
+		return (xdr_opaque(xdrs, sp, nodesize));
+
+	case XDR_FREE:
+		if (sp != NULL) {
+			mem_free(sp, nodesize);
+			*cpp = NULL;
+		}
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * Implemented here due to commonality of the object.
+ */
+bool_t
+xdr_netobj(XDR *xdrs, struct netobj *np)
+{
+
+	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
+}
+
+bool_t
+xdr_int32(XDR *xdrs, int32_t *ip)
+{
+	long l;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		l = *ip;
+		return (xdr_long(xdrs, &l));    
+
+	case XDR_DECODE:
+		if (!xdr_long(xdrs, &l)) {
+			return (FALSE);
+		}
+		*ip = l;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);    
+	}
+	return (FALSE);
+}
+
+bool_t
+xdr_u_int32(XDR *xdrs, uint32_t *up)
+{
+	u_long ul;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		ul = *up;
+		return (xdr_u_long(xdrs, &ul));    
+
+	case XDR_DECODE:
+		if (!xdr_u_long(xdrs, &ul)) {
+			return (FALSE);
+		}
+		*up = ul;
+		return (TRUE);
+
+	case XDR_FREE:
+		return (TRUE);    
+	}
+	return (FALSE);
+}
+
+/*
+ * XDR a descriminated union
+ * Support routine for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * an entry with a null procedure pointer.  The routine gets
+ * the discriminant value and then searches the array of xdrdiscrims
+ * looking for that value.  It calls the procedure given in the xdrdiscrim
+ * to handle the discriminant.  If there is no specific routine a default
+ * routine may be called.
+ * If there is no specific or default routine an error is returned.
+ */
+bool_t
+xdr_union(
+	XDR *xdrs,
+	enum_t *dscmp,		/* enum to decide which arm to work on */
+	char *unp,		/* the union itself */
+	struct xdr_discrim *choices,	/* [value, xdr proc] for each arm */
+	xdrproc_t dfault	/* default xdr routine */
+	)
+{
+	register enum_t dscm;
+
+	/*
+	 * we deal with the discriminator;  it's an enum
+	 */
+	if (! xdr_enum(xdrs, dscmp)) {
+		return (FALSE);
+	}
+	dscm = *dscmp;
+
+	/*
+	 * search choices for a value that matches the discriminator.
+	 * if we find one, execute the xdr routine for that value.
+	 */
+	for (; choices->proc != NULL_xdrproc_t; choices++) {
+		if (choices->value == dscm)
+			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
+	}
+
+	/*
+	 * no match - execute the default xdr routine if there is one
+	 */
+	return ((dfault == NULL_xdrproc_t) ? FALSE :
+	    (*dfault)(xdrs, unp, LASTUNSIGNED));
+}
+
+
+/*
+ * Non-portable xdr primitives.
+ * Care should be taken when moving these routines to new architectures.
+ */
+
+
+/*
+ * XDR null terminated ASCII strings
+ * xdr_string deals with "C strings" - arrays of bytes that are
+ * terminated by a NULL character.  The parameter cpp references a
+ * pointer to storage; If the pointer is null, then the necessary
+ * storage is allocated.  The last parameter is the max allowed length
+ * of the string as specified by a protocol.
+ */
+bool_t
+xdr_string(XDR *xdrs, char **cpp, u_int maxsize)
+{
+	register char *sp = *cpp;  /* sp is the actual string pointer */
+	u_int size;
+	u_int nodesize;
+
+	/*
+	 * first deal with the length since xdr strings are counted-strings
+	 */
+	switch (xdrs->x_op) {
+	case XDR_FREE:
+		if (sp == NULL) {
+			return(TRUE);	/* already free */
+		}
+		/* fall through... */
+	case XDR_ENCODE:
+		size = strlen(sp);
+		break;
+	case XDR_DECODE:
+		break;
+	}
+	if (! xdr_u_int(xdrs, &size)) {
+		return (FALSE);
+	}
+	if (size >= maxsize) {
+		return (FALSE);
+	}
+	nodesize = size + 1;
+
+	/*
+	 * now deal with the actual bytes
+	 */
+	switch (xdrs->x_op) {
+
+	case XDR_DECODE:
+		if (nodesize == 0) {
+			return (TRUE);
+		}
+		if (sp == NULL)
+			*cpp = sp = (char *)mem_alloc(nodesize);
+		if (sp == NULL) {
+			(void) fprintf(stderr, "xdr_string: out of memory\n");
+			return (FALSE);
+		}
+		sp[size] = 0;
+		/* fall into ... */
+
+	case XDR_ENCODE:
+		return (xdr_opaque(xdrs, sp, size));
+
+	case XDR_FREE:
+		mem_free(sp, nodesize);
+		*cpp = NULL;
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/* 
+ * Wrapper for xdr_string that can be called directly from 
+ * routines like clnt_call
+ */
+bool_t
+xdr_wrapstring(XDR *xdrs, char **cpp)
+{
+	if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
+		return (TRUE);
+	}
+	return (FALSE);
+}
diff --git a/krb5-1-6/src/lib/rpc/xdr_alloc.c b/krb5-1-6/src/lib/rpc/xdr_alloc.c
new file mode 100644
index 000000000..b0aa032c6
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr_alloc.c
@@ -0,0 +1,151 @@
+/* @(#)xdr_mem.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ */
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include "dyn.h"
+
+static bool_t	xdralloc_putlong(XDR *, long *);
+static bool_t	xdralloc_putbytes(XDR *, caddr_t, unsigned int);
+static unsigned int	xdralloc_getpos(XDR *);
+static rpc_inline_t *	xdralloc_inline(XDR *, int);
+static void	xdralloc_destroy(XDR *);
+static bool_t	xdralloc_notsup_getlong(XDR *, long *);
+static bool_t	xdralloc_notsup_getbytes(XDR *, caddr_t, unsigned int);
+static bool_t	xdralloc_notsup_setpos(XDR *, unsigned int);
+static struct	xdr_ops xdralloc_ops = {
+     xdralloc_notsup_getlong,
+     xdralloc_putlong,
+     xdralloc_notsup_getbytes,
+     xdralloc_putbytes,
+     xdralloc_getpos,
+     xdralloc_notsup_setpos,
+     xdralloc_inline,
+     xdralloc_destroy,
+};
+
+/*
+ * The procedure xdralloc_create initializes a stream descriptor for a
+ * memory buffer.  
+ */
+void xdralloc_create(XDR *xdrs, enum xdr_op op)
+{
+     xdrs->x_op = op;
+     xdrs->x_ops = &xdralloc_ops;
+     xdrs->x_private = (caddr_t) DynCreate(sizeof(char), -4);
+     /* not allowed to fail */
+}
+
+caddr_t xdralloc_getdata(XDR *xdrs)
+{
+     return (caddr_t) DynGet((DynObject) xdrs->x_private, 0);
+}
+
+void xdralloc_release(XDR *xdrs)
+{
+     DynRelease((DynObject) xdrs->x_private);
+}
+
+static void xdralloc_destroy(XDR *xdrs)
+{
+     DynDestroy((DynObject) xdrs->x_private);
+}
+
+static bool_t xdralloc_notsup_getlong(
+     register XDR *xdrs,
+     long *lp)
+{
+     return FALSE;
+}
+
+static bool_t xdralloc_putlong(
+     register XDR *xdrs,
+     long *lp)
+{
+     int l = htonl((uint32_t) *lp); /* XXX need bounds checking */
+
+     /* XXX assumes sizeof(int)==4 */
+     if (DynInsert((DynObject) xdrs->x_private,
+		   DynSize((DynObject) xdrs->x_private), &l,
+		   sizeof(int)) != DYN_OK)
+	  return FALSE;
+     return (TRUE);
+}
+
+
+static bool_t xdralloc_notsup_getbytes(
+     register XDR *xdrs,
+     caddr_t addr,
+     register unsigned int len)
+{
+     return FALSE;
+}
+
+
+static bool_t xdralloc_putbytes(
+     register XDR *xdrs,
+     caddr_t addr,
+     register unsigned int len)
+{
+     if (DynInsert((DynObject) xdrs->x_private,
+		   DynSize((DynObject) xdrs->x_private),
+		   addr, (int) len) != DYN_OK)
+	  return FALSE;
+     return TRUE;
+}
+
+static unsigned int xdralloc_getpos(XDR *xdrs)
+{
+     return DynSize((DynObject) xdrs->x_private);
+}
+
+static bool_t xdralloc_notsup_setpos(
+     register XDR *xdrs,
+     unsigned int lp)
+{
+     return FALSE;
+}
+
+
+
+static rpc_inline_t *xdralloc_inline(
+     register XDR *xdrs,
+     int len)
+{
+     return (rpc_inline_t *) 0;
+}
diff --git a/krb5-1-6/src/lib/rpc/xdr_array.c b/krb5-1-6/src/lib/rpc/xdr_array.c
new file mode 100644
index 000000000..7d5745d4e
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr_array.c
@@ -0,0 +1,158 @@
+/* @(#)xdr_array.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_array.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * arrays.  See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+
+#define LASTUNSIGNED	((u_int)0-1)
+
+
+/*
+ * XDR an array of arbitrary elements
+ * *addrp is a pointer to the array, *sizep is the number of elements.
+ * If addrp is NULL (*sizep * elsize) bytes are allocated.
+ * elsize is the size (in bytes) of each element, and elproc is the
+ * xdr procedure to call to handle each element of the array.
+ */
+bool_t
+xdr_array(
+	register XDR *xdrs,
+	caddr_t *addrp,		/* array pointer */
+	u_int *sizep,		/* number of elements */
+	u_int maxsize,		/* max numberof elements */
+	u_int elsize,		/* size in bytes of each element */
+	xdrproc_t elproc	/* xdr routine to handle each element */
+	)
+{
+	register u_int i;
+	register caddr_t target = *addrp;
+	register u_int c;  /* the actual element count */
+	register bool_t stat = TRUE;
+	register u_int nodesize;
+
+	/* like strings, arrays are really counted arrays */
+	if (! xdr_u_int(xdrs, sizep)) {
+		return (FALSE);
+	}
+	c = *sizep;
+	if ((c > maxsize || c > LASTUNSIGNED / elsize)
+	    && (xdrs->x_op != XDR_FREE)) {
+		return (FALSE);
+	}
+	nodesize = c * elsize;
+
+	/*
+	 * if we are deserializing, we may need to allocate an array.
+	 * We also save time by checking for a null array if we are freeing.
+	 */
+	if (target == NULL)
+		switch (xdrs->x_op) {
+		case XDR_DECODE:
+			if (c == 0)
+				return (TRUE);
+			*addrp = target = mem_alloc(nodesize);
+			if (target == NULL) {
+				(void) fprintf(stderr, 
+					"xdr_array: out of memory\n");
+				return (FALSE);
+			}
+			memset(target, 0, nodesize);
+			break;
+
+		case XDR_FREE:
+			return (TRUE);
+
+		case XDR_ENCODE:
+			break;
+	}
+	
+	/*
+	 * now we xdr each element of array
+	 */
+	for (i = 0; (i < c) && stat; i++) {
+		stat = (*elproc)(xdrs, target, LASTUNSIGNED);
+		target += elsize;
+	}
+
+	/*
+	 * the array may need freeing
+	 */
+	if (xdrs->x_op == XDR_FREE) {
+		mem_free(*addrp, nodesize);
+		*addrp = NULL;
+	}
+	return (stat);
+}
+
+/*
+ * xdr_vector():
+ *
+ * XDR a fixed length array. Unlike variable-length arrays,
+ * the storage of fixed length arrays is static and unfreeable.
+ * > basep: base of the array
+ * > size: size of the array
+ * > elemsize: size of each element
+ * > xdr_elem: routine to XDR each element
+ */
+bool_t
+xdr_vector(
+	register XDR *xdrs,
+	register char *basep,
+	register u_int nelem,
+	register u_int elemsize,
+	register xdrproc_t xdr_elem)
+{
+	register u_int i;
+	register char *elptr;
+
+	elptr = basep;
+	for (i = 0; i < nelem; i++) {
+		if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
+			return(FALSE);
+		}
+		elptr += elemsize;
+	}
+	return(TRUE);	
+}
+
diff --git a/krb5-1-6/src/lib/rpc/xdr_float.c b/krb5-1-6/src/lib/rpc/xdr_float.c
new file mode 100644
index 000000000..3e4805d97
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr_float.c
@@ -0,0 +1,289 @@
+/* @(#)xdr_float.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_float.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "floating point" xdr routines used to (de)serialize
+ * most common data items.  See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+
+/*
+ * NB: Not portable.
+ * This routine works on Suns (Sky / 68000's) and Vaxen.
+ */
+#ifdef IGNORE
+
+#ifdef vax
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct	ieee_single {
+	unsigned int	mantissa: 23;
+	unsigned int	exp     : 8;
+	unsigned int	sign    : 1;
+};
+
+/* Vax single precision floating point */
+struct	vax_single {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS	0x81
+#define IEEE_SNG_BIAS	0x7f
+
+static struct sgl_limits {
+	struct vax_single s;
+	struct ieee_single ieee;
+} sgl_limits[2] = {
+	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
+	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
+	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
+};
+#endif /* vax */
+
+bool_t
+xdr_float(XDR *xdrs, float *fp)
+{
+#if defined(vax)
+	struct ieee_single is;
+	struct vax_single vs, *vsp;
+	struct sgl_limits *lim;
+	int i;
+#endif
+	long lg;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+#if !defined(vax)
+	        lg = * (int_32 *) fp;
+		return (XDR_PUTLONG(xdrs, &lg));
+#else
+		vs = *((struct vax_single *)fp);
+		for (i = 0, lim = sgl_limits;
+			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+			i++, lim++) {
+			if ((vs.mantissa2 == lim->s.mantissa2) &&
+				(vs.exp == lim->s.exp) &&
+				(vs.mantissa1 == lim->s.mantissa1)) {
+				is = lim->ieee;
+				goto shipit;
+			}
+		}
+		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
+	shipit:
+		is.sign = vs.sign;
+		return (XDR_PUTLONG(xdrs, (int32_t *)&is));
+#endif
+
+	case XDR_DECODE:
+#if !defined(vax)
+	        if (!(XDR_GETLONG(xdrs, &lg))) {
+	                return (FALSE);
+		}
+		*fp = (float) ((int) lg);
+		return (TRUE);
+#else
+		vsp = (struct vax_single *)fp;
+		if (!XDR_GETLONG(xdrs, (int32_t *)&is))
+			return (FALSE);
+		for (i = 0, lim = sgl_limits;
+			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+			i++, lim++) {
+			if ((is.exp == lim->ieee.exp) &&
+				(is.mantissa == lim->ieee.mantissa)) {
+				*vsp = lim->s;
+				goto doneit;
+			}
+		}
+		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+		vsp->mantissa2 = is.mantissa;
+		vsp->mantissa1 = (is.mantissa >> 16);
+	doneit:
+		vsp->sign = is.sign;
+		return (TRUE);
+#endif
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+/*
+ * This routine works on Suns (Sky / 68000's) and Vaxen.
+ */
+
+#ifdef vax
+/* What IEEE double precision floating point looks like on a Vax */
+struct	ieee_double {
+	unsigned int	mantissa1 : 20;
+	unsigned int	exp       : 11;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 32;
+};
+
+/* Vax double precision floating point */
+struct  vax_double {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+	unsigned int	mantissa3 : 16;
+	unsigned int	mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS	0x81
+#define IEEE_DBL_BIAS	0x3ff
+#define MASK(nbits)	((1 << nbits) - 1)
+
+static struct dbl_limits {
+	struct	vax_double d;
+	struct	ieee_double ieee;
+} dbl_limits[2] = {
+	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
+	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
+	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
+};
+
+#endif /* vax */
+
+
+bool_t
+xdr_double(XDR *xdrs, double *dp)
+{
+	register int32_t *lp;
+#if defined(vax)
+	struct	ieee_double id;
+	struct	vax_double vd;
+	register struct dbl_limits *lim;
+	int i;
+#endif
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+#if !defined(vax)
+		lp = (int32_t *)dp;
+		if (sizeof(int32_t) == sizeof(long)) {
+		  return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+		} else {
+		  long lg1 = *lp++;;
+		  long lg2 = *lp;
+		  return (XDR_PUTLONG(xdrs, &lg1) && XDR_PUTLONG(xdrs, &lg2));
+		}
+#else
+		vd = *((struct vax_double *)dp);
+		for (i = 0, lim = dbl_limits;
+			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			i++, lim++) {
+			if ((vd.mantissa4 == lim->d.mantissa4) &&
+				(vd.mantissa3 == lim->d.mantissa3) &&
+				(vd.mantissa2 == lim->d.mantissa2) &&
+				(vd.mantissa1 == lim->d.mantissa1) &&
+				(vd.exp == lim->d.exp)) {
+				id = lim->ieee;
+				goto shipit;
+			}
+		}
+		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
+		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
+				(vd.mantissa3 << 13) |
+				((vd.mantissa4 >> 3) & MASK(13));
+	shipit:
+		id.sign = vd.sign;
+		lp = (int32_t *)&id;
+		return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+#endif
+
+	case XDR_DECODE:
+#if !defined(vax)
+		lp = (int32_t *)dp;
+		if (sizeof(int32_t) == sizeof(long)) {
+		  return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
+		} else {
+		  long lg1, lg2;
+		  bool_t flag =
+		   (XDR_GETLONG(xdrs, &lg1) && XDR_GETLONG(xdrs, &lg2));
+		  *lp++ = lg1;
+		  *lp = lg2;
+		  return flag;
+		}
+#else
+		lp = (int32_t *)&id;
+		if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
+			return (FALSE);
+		for (i = 0, lim = dbl_limits;
+			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			i++, lim++) {
+			if ((id.mantissa2 == lim->ieee.mantissa2) &&
+				(id.mantissa1 == lim->ieee.mantissa1) &&
+				(id.exp == lim->ieee.exp)) {
+				vd = lim->d;
+				goto doneit;
+			}
+		}
+		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+		vd.mantissa1 = (id.mantissa1 >> 13);
+		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
+				(id.mantissa2 >> 29);
+		vd.mantissa3 = (id.mantissa2 >> 13);
+		vd.mantissa4 = (id.mantissa2 << 3);
+	doneit:
+		vd.sign = id.sign;
+		*dp = *((double *)&vd);
+		return (TRUE);
+#endif
+
+	case XDR_FREE:
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+#endif /* IGNORE */
diff --git a/krb5-1-6/src/lib/rpc/xdr_mem.c b/krb5-1-6/src/lib/rpc/xdr_mem.c
new file mode 100644
index 000000000..6908aa8a3
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr_mem.c
@@ -0,0 +1,182 @@
+/* @(#)xdr_mem.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_mem.h, XDR implementation using memory buffers.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * If you have some data to be interpreted as external data representation
+ * or to be converted to external data representation in a memory buffer,
+ * then this is the package for you.
+ *
+ */
+
+
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+static bool_t	xdrmem_getlong(XDR *, long *);
+static bool_t	xdrmem_putlong(XDR *, long *);
+static bool_t	xdrmem_getbytes(XDR *, caddr_t, u_int);
+static bool_t	xdrmem_putbytes(XDR *, caddr_t, u_int);
+static u_int	xdrmem_getpos(XDR *);
+static bool_t	xdrmem_setpos(XDR *, u_int);
+static rpc_inline_t *	xdrmem_inline(XDR *, int);
+static void	xdrmem_destroy(XDR *);
+
+static struct	xdr_ops xdrmem_ops = {
+	xdrmem_getlong,
+	xdrmem_putlong,
+	xdrmem_getbytes,
+	xdrmem_putbytes,
+	xdrmem_getpos,
+	xdrmem_setpos,
+	xdrmem_inline,
+	xdrmem_destroy
+};
+
+/*
+ * The procedure xdrmem_create initializes a stream descriptor for a
+ * memory buffer.  
+ */
+void
+xdrmem_create(
+	XDR *xdrs,
+	caddr_t addr,
+	u_int size,
+	enum xdr_op op)
+{
+
+	xdrs->x_op = op;
+	xdrs->x_ops = &xdrmem_ops;
+	xdrs->x_private = xdrs->x_base = addr;
+	xdrs->x_handy = (size > INT_MAX) ? INT_MAX : size; /* XXX */
+}
+
+static void
+xdrmem_destroy(XDR *xdrs)
+{
+}
+
+static bool_t
+xdrmem_getlong(XDR *xdrs, long *lp)
+{
+
+	if (xdrs->x_handy < BYTES_PER_XDR_UNIT)
+		return (FALSE);
+	else
+		xdrs->x_handy -= BYTES_PER_XDR_UNIT;
+	*lp = (long)(int32_t)ntohl(*((uint32_t *)(xdrs->x_private)));
+	xdrs->x_private = (char *)xdrs->x_private + BYTES_PER_XDR_UNIT;
+	return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong(XDR *xdrs, long *lp)
+{
+
+	if (xdrs->x_handy < BYTES_PER_XDR_UNIT)
+		return (FALSE);
+	else
+		xdrs->x_handy -= BYTES_PER_XDR_UNIT;
+	*(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*lp));
+	xdrs->x_private = (char *)xdrs->x_private + BYTES_PER_XDR_UNIT;
+	return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(XDR *xdrs, caddr_t addr, u_int len)
+{
+
+	if (xdrs->x_handy < len)
+		return (FALSE);
+	else
+		xdrs->x_handy -= len;
+	memmove(addr, xdrs->x_private, len);
+	xdrs->x_private = (char *)xdrs->x_private + len;
+	return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(XDR *xdrs, caddr_t addr, u_int len)
+{
+
+	if (xdrs->x_handy < len)
+		return (FALSE);
+	else
+		xdrs->x_handy -= len;
+	memmove(xdrs->x_private, addr, len);
+	xdrs->x_private = (char *)xdrs->x_private + len;
+	return (TRUE);
+}
+
+static u_int
+xdrmem_getpos(XDR *xdrs)
+{
+/*
+ * 11/3/95 - JRG - Rather than recast everything for 64 bit, just convert
+ * pointers to longs, then cast to int.
+ */
+	return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(XDR *xdrs, u_int pos)
+{
+	register caddr_t newaddr = xdrs->x_base + pos;
+	register caddr_t lastaddr = (char *) xdrs->x_private + xdrs->x_handy;
+
+	if ((long)newaddr > (long)lastaddr)
+		return (FALSE);
+	xdrs->x_private = newaddr;
+	xdrs->x_handy = (int)((long)lastaddr - (long)newaddr);
+	return (TRUE);
+}
+
+static rpc_inline_t *
+xdrmem_inline(XDR *xdrs, int len)
+{
+	rpc_inline_t *buf = 0;
+
+	if (len >= 0 && xdrs->x_handy >= len) {
+		xdrs->x_handy -= len;
+		buf = (rpc_inline_t *) xdrs->x_private;
+		xdrs->x_private = (char *)xdrs->x_private + len;
+	}
+	return (buf);
+}
diff --git a/krb5-1-6/src/lib/rpc/xdr_rec.c b/krb5-1-6/src/lib/rpc/xdr_rec.c
new file mode 100644
index 000000000..38e1f6323
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr_rec.c
@@ -0,0 +1,570 @@
+/* @(#)xdr_rec.c	2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
+ * layer above tcp (for rpc's use).
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These routines interface XDRSTREAMS to a tcp/ip connection.
+ * There is a record marking layer between the xdr stream
+ * and the tcp transport level.  A record is composed on one or more
+ * record fragments.  A record fragment is a thirty-two bit header followed
+ * by n bytes of data, where n is contained in the header.  The header
+ * is represented as a htonl(uint32_t).  Thegh order bit encodes
+ * whether or not the fragment is the last fragment of the record
+ * (1 => fragment is last, 0 => more fragments to follow. 
+ * The other 31 bits encode the byte length of the fragment.
+ */
+
+#include <stdio.h>
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+#include <string.h>
+
+static bool_t	xdrrec_getlong(XDR *, long *);
+static bool_t	xdrrec_putlong(XDR *, long *);
+static bool_t	xdrrec_getbytes(XDR *, caddr_t, u_int);
+static bool_t	xdrrec_putbytes(XDR *, caddr_t, u_int);
+static u_int	xdrrec_getpos(XDR *);
+static bool_t	xdrrec_setpos(XDR *, u_int);
+static rpc_inline_t *	xdrrec_inline(XDR *, int);
+static void	xdrrec_destroy(XDR *);
+
+static struct  xdr_ops xdrrec_ops = {
+	xdrrec_getlong,
+	xdrrec_putlong,
+	xdrrec_getbytes,
+	xdrrec_putbytes,
+	xdrrec_getpos,
+	xdrrec_setpos,
+	xdrrec_inline,
+	xdrrec_destroy
+};
+
+/*
+ * A record is composed of one or more record fragments.
+ * A record fragment is a four-byte header followed by zero to
+ * 2**31-1 bytes.  The header is treated as an unsigned 32 bit integer and is
+ * encode/decoded to the network via htonl/ntohl.  The low order 31 bits
+ * are a byte count of the fragment.  The highest order bit is a boolean:
+ * 1 => this fragment is the last fragment of the record,
+ * 0 => this fragment is followed by more fragment(s).
+ *
+ * The fragment/record machinery is not general;  it is constructed to
+ * meet the needs of xdr and rpc based on tcp.
+ */
+
+#define LAST_FRAG ((uint32_t)(1L << 31))
+
+typedef struct rec_strm {
+	caddr_t tcp_handle;
+	caddr_t the_buffer;
+	/*
+	 * out-goung bits
+	 */
+	int (*writeit)();
+	caddr_t out_base;	/* output buffer (points to frag header) */
+	caddr_t out_finger;	/* next output position */
+	caddr_t out_boundry;	/* data cannot up to this address */
+	uint32_t *frag_header;	/* beginning of curren fragment */
+	bool_t frag_sent;	/* true if buffer sent in middle of record */
+	/*
+	 * in-coming bits
+	 */
+	int (*readit)();
+	uint32_t in_size;	/* fixed size of the input buffer */
+	caddr_t in_base;
+	caddr_t in_finger;	/* location of next byte to be had */
+	caddr_t in_boundry;	/* can read up to this location */
+	int32_t fbtbc;		/* fragment bytes to be consumed */
+	bool_t last_frag;
+	u_int sendsize;
+	u_int recvsize;
+} RECSTREAM;
+
+static u_int	fix_buf_size(u_int);
+static bool_t   flush_out(RECSTREAM *, bool_t);
+static bool_t   get_input_bytes(RECSTREAM *, caddr_t, int);
+static bool_t   set_input_fragment(RECSTREAM *);
+static bool_t   skip_input_bytes(RECSTREAM *, int32_t);
+
+/*
+ * Create an xdr handle for xdrrec
+ * xdrrec_create fills in xdrs.  Sendsize and recvsize are
+ * send and recv buffer sizes (0 => use default).
+ * tcp_handle is an opaque handle that is passed as the first parameter to
+ * the procedures readit and writeit.  Readit and writeit are read and
+ * write respectively.   They are like the system
+ * calls expect that they take an opaque handle rather than an fd.
+ */
+void
+xdrrec_create(
+	XDR *xdrs,
+	u_int sendsize,
+	u_int recvsize,
+	caddr_t tcp_handle,
+	int (*readit)(), /* like read, but pass it a tcp_handle, not sock */
+	int (*writeit)() /* like write, but pass it a tcp_handle, not sock */
+	)
+{
+	register RECSTREAM *rstrm =
+		(RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
+
+	if (rstrm == NULL) {
+		(void)fprintf(stderr, "xdrrec_create: out of memory\n");
+		/* 
+		 *  This is bad.  Should rework xdrrec_create to 
+		 *  return a handle, and in this case return NULL
+		 */
+		return;
+	}
+	/*
+	 * adjust sizes and allocate buffer quad byte aligned
+	 */
+	rstrm->sendsize = sendsize = fix_buf_size(sendsize);
+	rstrm->recvsize = recvsize = fix_buf_size(recvsize);
+	rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
+	if (rstrm->the_buffer == NULL) {
+		(void)fprintf(stderr, "xdrrec_create: out of memory\n");
+		return;
+	}
+	for (rstrm->out_base = rstrm->the_buffer;
+	     /* Pointer arithmetic - long cast allowed... */
+		(u_long)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
+		rstrm->out_base++);
+	rstrm->in_base = rstrm->out_base + sendsize;
+	/*
+	 * now the rest ...
+	 */
+	xdrs->x_ops = &xdrrec_ops;
+	xdrs->x_private = (caddr_t)rstrm;
+	rstrm->tcp_handle = tcp_handle;
+	rstrm->readit = readit;
+	rstrm->writeit = writeit;
+	rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
+	rstrm->frag_header = (uint32_t *)(void *)rstrm->out_base;
+	rstrm->out_finger += BYTES_PER_XDR_UNIT;
+	rstrm->out_boundry += sendsize;
+	rstrm->frag_sent = FALSE;
+	rstrm->in_size = recvsize;
+	rstrm->in_boundry = rstrm->in_base;
+	rstrm->in_finger = (rstrm->in_boundry += recvsize);
+	rstrm->fbtbc = 0;
+	rstrm->last_frag = TRUE;
+}
+
+
+/*
+ * The reoutines defined below are the xdr ops which will go into the
+ * xdr handle filled in by xdrrec_create.
+ */
+
+static bool_t
+xdrrec_getlong(XDR *xdrs, long *lp)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	register int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger);
+	uint32_t mylong;
+
+	/* first try the inline, fast case */
+	if ((rstrm->fbtbc >= BYTES_PER_XDR_UNIT) &&
+		(((long)rstrm->in_boundry - (long)buflp) >=
+		 BYTES_PER_XDR_UNIT)) {
+		*lp = (long)ntohl((uint32_t)(*buflp));
+		rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
+		rstrm->in_finger += BYTES_PER_XDR_UNIT;
+	} else {
+		if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong,
+				      BYTES_PER_XDR_UNIT))
+			return (FALSE);
+		*lp = (long)(int32_t)ntohl(mylong);
+	}
+	return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(XDR *xdrs, long *lp)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	register int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
+
+	if (rstrm->out_boundry - rstrm->out_finger < BYTES_PER_XDR_UNIT) {
+		/*
+		 * this case should almost never happen so the code is
+		 * inefficient
+		 */
+		rstrm->frag_sent = TRUE;
+		if (! flush_out(rstrm, FALSE))
+			return (FALSE);
+		dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
+	}
+	rstrm->out_finger += BYTES_PER_XDR_UNIT;
+	*dest_lp = (int32_t)htonl((uint32_t)(*lp));
+	return (TRUE);
+}
+
+static bool_t  /* must manage buffers, fragments, and records */
+xdrrec_getbytes(XDR *xdrs, caddr_t addr, u_int len)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	register int current;
+
+	while (len > 0) {
+		current = rstrm->fbtbc;
+		if (current == 0) {
+			if (rstrm->last_frag)
+				return (FALSE);
+			if (! set_input_fragment(rstrm))
+				return (FALSE);
+			continue;
+		}
+		current = (len < current) ? len : current;
+		if (! get_input_bytes(rstrm, addr, current))
+			return (FALSE);
+		addr += current; 
+		rstrm->fbtbc -= current;
+		len -= current;
+	}
+	return (TRUE);
+}
+
+static bool_t
+xdrrec_putbytes(XDR *xdrs, caddr_t addr, u_int len)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	register size_t current;
+
+	while (len > 0) {
+		current = (size_t) ((long)rstrm->out_boundry - 
+				 (long)rstrm->out_finger);
+		current = (len < current) ? len : current;
+		memmove(rstrm->out_finger, addr, current);
+		rstrm->out_finger += current;
+		addr += current;
+		len -= current;
+		if (rstrm->out_finger == rstrm->out_boundry) {
+			rstrm->frag_sent = TRUE;
+			if (! flush_out(rstrm, FALSE))
+				return (FALSE);
+		}
+	}
+	return (TRUE);
+}
+
+static u_int
+xdrrec_getpos(XDR *xdrs)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+	register int pos;
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		pos = rstrm->out_finger - rstrm->out_base
+			- BYTES_PER_XDR_UNIT;
+		break;
+
+	case XDR_DECODE:
+		pos = rstrm->in_boundry - rstrm->in_finger
+			- BYTES_PER_XDR_UNIT;
+		break;
+
+	default:
+		pos = -1;
+		break;
+	}
+	return ((u_int) pos);
+}
+
+static bool_t
+xdrrec_setpos(XDR *xdrs, u_int pos)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+	u_int currpos = xdrrec_getpos(xdrs);
+	int delta = currpos - pos;
+	caddr_t newpos;
+
+	if ((int)currpos != -1)
+		switch (xdrs->x_op) {
+
+		case XDR_ENCODE:
+			newpos = rstrm->out_finger - delta;
+			if ((newpos > (caddr_t)(rstrm->frag_header)) &&
+				(newpos < rstrm->out_boundry)) {
+				rstrm->out_finger = newpos;
+				return (TRUE);
+			}
+			break;
+
+		case XDR_DECODE:
+			newpos = rstrm->in_finger - delta;
+			if ((delta < (int)(rstrm->fbtbc)) &&
+				(newpos <= rstrm->in_boundry) &&
+				(newpos >= rstrm->in_base)) {
+				rstrm->in_finger = newpos;
+				rstrm->fbtbc -= delta;
+				return (TRUE);
+			}
+			break;
+
+		case XDR_FREE:
+			break;
+		}
+	return (FALSE);
+}
+
+static rpc_inline_t *
+xdrrec_inline(XDR *xdrs, int len)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+	rpc_inline_t * buf = NULL;
+
+	if (len < 0)
+		return (FALSE);
+
+	switch (xdrs->x_op) {
+
+	case XDR_ENCODE:
+		if (len <= (rstrm->out_boundry - rstrm->out_finger)) {
+			buf = (rpc_inline_t *)(void *) rstrm->out_finger;
+			rstrm->out_finger += len;
+		}
+		break;
+
+	case XDR_DECODE:
+		if ((len <= rstrm->fbtbc) &&
+			(len <= (rstrm->in_boundry - rstrm->in_finger))) {
+			buf = (rpc_inline_t *)(void *) rstrm->in_finger;
+			rstrm->fbtbc -= len;
+			rstrm->in_finger += len;
+		}
+		break;
+
+	case XDR_FREE:
+	        break;
+	}
+	return (buf);
+}
+
+static void
+xdrrec_destroy(XDR *xdrs)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+
+	mem_free(rstrm->the_buffer,
+		rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
+	mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
+}
+
+
+/*
+ * Exported routines to manage xdr records
+ */
+
+/*
+ * Before reading (deserializing from the stream, one should always call
+ * this procedure to guarantee proper record alignment.
+ */
+bool_t
+xdrrec_skiprecord(XDR *xdrs)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+	while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+		if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+			return (FALSE);
+		rstrm->fbtbc = 0;
+		if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+			return (FALSE);
+	}
+	rstrm->last_frag = FALSE;
+	return (TRUE);
+}
+
+/*
+ * Look ahead fuction.
+ * Returns TRUE iff there is no more input in the buffer 
+ * after consuming the rest of the current record.
+ */
+bool_t
+xdrrec_eof(XDR *xdrs)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+	while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+		if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+			return (TRUE);
+		rstrm->fbtbc = 0;
+		if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+			return (TRUE);
+	}
+	if (rstrm->in_finger == rstrm->in_boundry)
+		return (TRUE);
+	return (FALSE);
+}
+
+/*
+ * The client must tell the package when an end-of-record has occurred.
+ * The second paraemters tells whether the record should be flushed to the
+ * (output) tcp stream.  (This let's the package support batched or
+ * pipelined procedure calls.)  TRUE => immmediate flush to tcp connection.
+ */
+bool_t
+xdrrec_endofrecord(XDR *xdrs, bool_t sendnow)
+{
+	register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+	register uint32_t len;  /* fragment length */
+
+	if (sendnow || rstrm->frag_sent ||
+		((long)rstrm->out_finger + BYTES_PER_XDR_UNIT >=
+		(long)rstrm->out_boundry)) {
+		rstrm->frag_sent = FALSE;
+		return (flush_out(rstrm, TRUE));
+	}
+	len = (long)(rstrm->out_finger) - (long)(rstrm->frag_header) -
+	   BYTES_PER_XDR_UNIT;
+	*(rstrm->frag_header) = htonl((uint32_t)len | LAST_FRAG);
+	rstrm->frag_header = (uint32_t *)(void *)rstrm->out_finger;
+	rstrm->out_finger += BYTES_PER_XDR_UNIT;
+	return (TRUE);
+}
+
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(RECSTREAM *rstrm, bool_t eor)
+{
+	register uint32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
+	register uint32_t len = (u_long)(rstrm->out_finger) - 
+		(u_long)(rstrm->frag_header) - BYTES_PER_XDR_UNIT;
+
+	*(rstrm->frag_header) = htonl(len | eormask);
+	len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
+	if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
+		!= (int)len)
+		return (FALSE);
+	rstrm->frag_header = (uint32_t *)(void *)rstrm->out_base;
+	rstrm->out_finger = (caddr_t)rstrm->out_base + BYTES_PER_XDR_UNIT;
+	return (TRUE);
+}
+
+static bool_t  /* knows nothing about records!  Only about input buffers */
+fill_input_buf(RECSTREAM *rstrm)
+{
+	register caddr_t where;
+	u_int i;
+	register int len;
+
+	where = rstrm->in_base;
+	i = (u_int)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
+	where += i;
+	len = rstrm->in_size - i;
+	if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
+		return (FALSE);
+	rstrm->in_finger = where;
+	where += len;
+	rstrm->in_boundry = where;
+	return (TRUE);
+}
+
+static bool_t  /* knows nothing about records!  Only about input buffers */
+get_input_bytes(RECSTREAM *rstrm, caddr_t addr, int len)
+{
+	register size_t current;
+
+	while (len > 0) {
+		current = (size_t)((long)rstrm->in_boundry - 
+				(long)rstrm->in_finger);
+		if (current == 0) {
+			if (! fill_input_buf(rstrm))
+				return (FALSE);
+			continue;
+		}
+		current = (len < current) ? len : current;
+		memmove(addr, rstrm->in_finger, current);
+		rstrm->in_finger += current;
+		addr += current;
+		len -= current;
+	}
+	return (TRUE);
+}
+
+static bool_t  /* next four bytes of input stream are treated as a header */
+set_input_fragment(rstrm)
+	register RECSTREAM *rstrm;
+{
+	uint32_t header;
+
+	if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
+		return (FALSE);
+	header = ntohl(header);
+	rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
+	rstrm->fbtbc = header & (~LAST_FRAG);
+	return (TRUE);
+}
+
+static bool_t  /* consumes input bytes; knows nothing about records! */
+skip_input_bytes(RECSTREAM *rstrm, int32_t cnt)
+{
+	register int current;
+
+	while (cnt > 0) {
+		current = (int)((long)rstrm->in_boundry - 
+				(long)rstrm->in_finger);
+		if (current == 0) {
+			if (! fill_input_buf(rstrm))
+				return (FALSE);
+			continue;
+		}
+		current = (cnt < current) ? cnt : current;
+		rstrm->in_finger += current;
+		cnt -= current;
+	}
+	return (TRUE);
+}
+
+static u_int
+fix_buf_size(u_int s)
+{
+
+	if (s < 100)
+		s = 4000;
+	return (RNDUP(s));
+}
diff --git a/krb5-1-6/src/lib/rpc/xdr_reference.c b/krb5-1-6/src/lib/rpc/xdr_reference.c
new file mode 100644
index 000000000..50a4fe4ae
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr_reference.c
@@ -0,0 +1,137 @@
+/* @(#)xdr_reference.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
+#endif
+
+/*
+ * xdr_reference.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * "pointers".  See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+
+#define LASTUNSIGNED	((u_int)0-1)
+
+/*
+ * XDR an indirect pointer
+ * xdr_reference is for recursively translating a structure that is
+ * referenced by a pointer inside the structure that is currently being
+ * translated.  pp references a pointer to storage. If *pp is null
+ * the  necessary storage is allocated.
+ * size is the sizeof the referneced structure.
+ * proc is the routine to handle the referenced structure.
+ */
+bool_t
+xdr_reference(
+	XDR *xdrs,
+	caddr_t *pp,		/* the pointer to work on */
+	u_int size,		/* size of the object pointed to */
+	xdrproc_t proc		/* xdr routine to handle the object */
+	)
+{
+	register caddr_t loc = *pp;
+	register bool_t stat;
+
+	if (loc == NULL)
+		switch (xdrs->x_op) {
+		case XDR_FREE:
+			return (TRUE);
+
+		case XDR_DECODE:
+			*pp = loc = (caddr_t) mem_alloc(size);
+			if (loc == NULL) {
+				(void) fprintf(stderr,
+				    "xdr_reference: out of memory\n");
+				return (FALSE);
+			}
+			memset(loc, 0, size);
+			break;
+
+		case XDR_ENCODE:
+			break;
+	}
+
+	stat = (*proc)(xdrs, loc, LASTUNSIGNED);
+
+	if (xdrs->x_op == XDR_FREE) {
+		mem_free(loc, size);
+		*pp = NULL;
+	}
+	return (stat);
+}
+
+
+/*
+ * xdr_pointer():
+ *
+ * XDR a pointer to a possibly recursive data structure. This
+ * differs with xdr_reference in that it can serialize/deserialiaze
+ * trees correctly.
+ *
+ *  What's sent is actually a union:
+ *
+ *  union object_pointer switch (boolean b) {
+ *  case TRUE: object_data data;
+ *  case FALSE: void nothing;
+ *  }
+ *
+ * > objpp: Pointer to the pointer to the object.
+ * > obj_size: size of the object.
+ * > xdr_obj: routine to XDR an object.
+ *
+ */
+bool_t
+xdr_pointer(
+	XDR *xdrs,
+	char **objpp,
+	u_int obj_size,
+	xdrproc_t xdr_obj)
+{
+
+	bool_t more_data;
+
+	more_data = (*objpp != NULL);
+	if (! xdr_bool(xdrs,&more_data)) {
+		return (FALSE);
+	}
+	if (! more_data) {
+		*objpp = NULL;
+		return (TRUE);
+	}
+	return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
+}
diff --git a/krb5-1-6/src/lib/rpc/xdr_stdio.c b/krb5-1-6/src/lib/rpc/xdr_stdio.c
new file mode 100644
index 000000000..471d9f2ee
--- /dev/null
+++ b/krb5-1-6/src/lib/rpc/xdr_stdio.c
@@ -0,0 +1,170 @@
+/* @(#)xdr_stdio.c	2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_stdio.c, XDR implementation on standard i/o file.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements a XDR on a stdio stream.
+ * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
+ * from the stream.
+ */
+
+#include <gssrpc/types.h>
+#include <stdio.h>
+#include <gssrpc/xdr.h>
+
+static bool_t	xdrstdio_getlong(XDR *, long *);
+static bool_t	xdrstdio_putlong(XDR *, long *);
+static bool_t	xdrstdio_getbytes(XDR *, caddr_t, u_int);
+static bool_t	xdrstdio_putbytes(XDR *, caddr_t, u_int);
+static u_int	xdrstdio_getpos(XDR *);
+static bool_t	xdrstdio_setpos(XDR *, u_int);
+static rpc_inline_t *	xdrstdio_inline(XDR *, int);
+static void	xdrstdio_destroy(XDR *);
+
+/*
+ * Ops vector for stdio type XDR
+ */
+static struct xdr_ops	xdrstdio_ops = {
+	xdrstdio_getlong,	/* deseraialize a long int */
+	xdrstdio_putlong,	/* seraialize a long int */
+	xdrstdio_getbytes,	/* deserialize counted bytes */
+	xdrstdio_putbytes,	/* serialize counted bytes */
+	xdrstdio_getpos,	/* get offset in the stream */
+	xdrstdio_setpos,	/* set offset in the stream */
+	xdrstdio_inline,	/* prime stream for inline macros */
+	xdrstdio_destroy	/* destroy stream */
+};
+
+/*
+ * Initialize a stdio xdr stream.
+ * Sets the xdr stream handle xdrs for use on the stream file.
+ * Operation flag is set to op.
+ */
+void
+xdrstdio_create(XDR *xdrs, FILE *file, enum xdr_op op)
+{
+
+	xdrs->x_op = op;
+	xdrs->x_ops = &xdrstdio_ops;
+	xdrs->x_private = (caddr_t)file;
+	xdrs->x_handy = 0;
+	xdrs->x_base = 0;
+}
+
+/*
+ * Destroy a stdio xdr stream.
+ * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
+ */
+static void
+xdrstdio_destroy(XDR *xdrs)
+{
+	(void)fflush((FILE *)xdrs->x_private);
+	/* xx should we close the file ?? */
+}
+
+static bool_t
+xdrstdio_getlong(XDR *xdrs, long *lp)
+{
+        uint32_t tmp;
+	if (fread((caddr_t)&tmp,
+		  sizeof(uint32_t), 1, (FILE *)xdrs->x_private) != 1)
+		return (FALSE);
+
+	*lp = (long)ntohl(tmp);
+
+	return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(XDR *xdrs, long *lp)
+{
+	uint32_t mycopy = htonl((uint32_t)*lp);
+
+	if (fwrite((caddr_t)&mycopy, sizeof(uint32_t), 1, (FILE *)xdrs->x_private) != 1)
+		return (FALSE);
+	return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(XDR *xdrs, caddr_t addr, u_int len)
+{
+
+	if ((len != 0) && (fread(addr, (size_t)len, 1, 
+				 (FILE *)xdrs->x_private) != 1))
+		return (FALSE);
+	return (TRUE);
+}
+
+static bool_t
+xdrstdio_putbytes(XDR *xdrs, caddr_t addr, u_int len)
+{
+
+	if ((len != 0) && (fwrite(addr, (size_t)len, 1, 
+			   (FILE *)xdrs->x_private) != 1))
+		return (FALSE);
+	return (TRUE);
+}
+
+static u_int
+xdrstdio_getpos(XDR *xdrs)
+{
+
+	return ((u_int) ftell((FILE *)xdrs->x_private));
+}
+
+static bool_t
+xdrstdio_setpos(XDR *xdrs, u_int pos)
+{ 
+
+	return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
+		FALSE : TRUE);
+}
+
+static rpc_inline_t *
+xdrstdio_inline(XDR *xdrs, int len)
+{
+
+	/*
+	 * Must do some work to implement this: must insure
+	 * enough data in the underlying stdio buffer,
+	 * that the buffer is aligned so that we can indirect through a
+	 * long *, and stuff this pointer in xdrs->x_buf.  Doing
+	 * a fread or fwrite to a scratch buffer would defeat
+	 * most of the gains to be had here and require storage
+	 * management on this buffer, so we don't do this.
+	 */
+	return (NULL);
+}
diff --git a/krb5-1-6/src/lib/win_glue.c b/krb5-1-6/src/lib/win_glue.c
new file mode 100644
index 000000000..3b2cbc599
--- /dev/null
+++ b/krb5-1-6/src/lib/win_glue.c
@@ -0,0 +1,489 @@
+#ifdef KRB4
+#include <kerberosIV/krb.h>
+#endif
+#include "k5-int.h"
+
+#ifdef KRB4
+#include <kerberosIV/krb_err.h>
+#include <kerberosIV/kadm_err.h>
+#endif
+#ifdef KRB5
+#include "krb5_err.h"
+#include "kv5m_err.h"
+#include "asn1_err.h"
+#include "kdb5_err.h"
+#include "profile.h"
+extern void krb5_stdcc_shutdown();
+#endif
+#ifdef GSSAPI
+#include "gssapi/generic/gssapi_err_generic.h"
+#include "gssapi/krb5/gssapi_err_krb5.h"
+#endif
+
+
+/*
+ * #defines for MIT-specific time-based timebombs and/or version
+ * server for the Kerberos DLL.
+ */
+
+#ifdef SAP_TIMEBOMB
+#define TIMEBOMB 865141200	/* 1-Jun-97 */
+#define TIMEBOMB_PRODUCT "SAPGUI"
+#define TIMEBOMB_WARN  15
+#define TIMEBOMB_INFO "  Please see the web page at:\nhttp://web.mit.edu/reeng/www/saphelp for more information"
+#define TIMEBOMB_ERROR KRB5_APPL_EXPIRED
+#endif
+
+#ifdef KRB_TIMEBOMB
+#define TIMEBOMB 865141200	/* 1-Jun-97 */
+#define TIMEBOMB_PRODUCT "Kerberos V5"
+#define TIMEBOMB_WARN 15
+#define TIMEBOMB_INFO "  Please see the web page at:\nhttp://web.mit.edu/reeng/www/saphelp for more information"
+#define TIMEBOMB_ERROR KRB5_LIB_EXPIRED
+#endif
+
+/*
+ * #defines for using MIT's version server DLL
+ */
+#ifdef SAP_VERSERV
+#define APP_TITLE "KRB5-SAP"
+#define APP_VER "3.0f"
+#define APP_INI "krb5sap.ini"
+#define VERSERV_ERROR 	KRB5_APPL_EXPIRED
+#endif
+
+#ifdef VERSERV
+#define WINDOWS
+#include <ver.h>
+#include <vs.h>
+#include <v.h>
+
+
+/*
+ * This function will get the version resource information from the
+ * application using the DLL.  This allows us to Version Serve
+ * arbitrary third party applications.  If there is an error, or we
+ * decide that we should not version check the calling application
+ * then VSflag will be FALSE when the function returns.
+ *
+ * The buffers passed into this function must be at least
+ * APPVERINFO_SIZE bytes long.
+ */
+
+#define APPVERINFO_SIZE 256
+
+void GetCallingAppVerInfo( char *AppTitle, char *AppVer, char *AppIni,
+			  BOOL *VSflag)
+{
+	char CallerFilename[_MAX_PATH];
+	LONG *lpLangInfo;
+	DWORD hVersionInfoID, size;
+	GLOBALHANDLE hVersionInfo;
+	LPSTR lpVersionInfo;
+	int dumint, retval;
+	char *cp;
+	char *revAppTitle;
+	char szVerQ[90];
+	LPBYTE locAppTitle;
+	LPBYTE locAppVer;
+	char locAppIni[_MAX_PATH];
+#ifndef _WIN32
+	WORD wStackSeg;
+#endif /* !_WIN32 */
+
+	/* first we need to get the calling module's filename */
+#ifndef _WIN32
+	_asm {
+		mov wStackSeg, ss
+	};
+	retval = GetModuleFileName((HMODULE)wStackSeg, CallerFilename,
+		_MAX_PATH);
+#else
+	/*
+	 * Note: this may only work for single threaded applications,
+	 * we'll live and learn ...
+	 */
+        retval = GetModuleFileName( NULL, CallerFilename, _MAX_PATH);
+#endif
+
+	if ( retval == 0 ) {
+		VSflag = FALSE;
+		return;
+	}
+
+	size = GetFileVersionInfoSize( CallerFilename, &hVersionInfoID);
+
+	if( size == 0 ) {
+		/*
+		 * hey , I bet we don't have a version resource, let's
+		 * punt
+		 */
+#if 0
+		/* let's see what we have? (1813 means no resource) */
+		size = GetLastError(); 		/*  WIN32 only */
+#endif
+		*VSflag = FALSE;
+		return;
+	}
+
+	hVersionInfo = GlobalAlloc(GHND, size);
+	lpVersionInfo = GlobalLock(hVersionInfo);
+
+	retval = GetFileVersionInfo( CallerFilename, hVersionInfoID, size,
+				    lpVersionInfo);
+
+	retval = VerQueryValue(lpVersionInfo, "\\VarFileInfo\\Translation",
+			       (LPSTR *)&lpLangInfo, &dumint);
+	wsprintf(szVerQ,
+		 "\\StringFileInfo\\%04x%04x\\",
+		 LOWORD(*lpLangInfo), HIWORD(*lpLangInfo));
+	
+	cp = szVerQ + lstrlen(szVerQ);
+
+	lstrcpy(cp, "ProductName");
+
+
+	/* try a localAppTitle and then a strcpy 4/2/97 */
+
+	locAppTitle = 0;
+	locAppVer = 0;
+
+	retval = VerQueryValue(lpVersionInfo, szVerQ, &locAppTitle,
+			       &dumint);
+
+	lstrcpy(cp, "ProductVersion");
+
+
+	retval = VerQueryValue(lpVersionInfo, szVerQ, &locAppVer,
+			       &dumint);
+
+	if (!locAppTitle || !locAppVer) {
+	  	/* Punt, we don't have the right version resource records */
+		*VSflag = FALSE;
+		return;
+	}
+
+	/*
+	 * We don't have a way to determine that INI file of the
+	 * application at the moment so let's just use krb5.ini
+	 */
+	strncpy( locAppIni, KERBEROS_INI, sizeof(locAppIni) - 1 );
+	locAppIni[ sizeof(locAppIni) - 1 ] = '\0';
+
+	strncpy( AppTitle, locAppTitle, APPVERINFO_SIZE);
+	AppTitle[APPVERINFO_SIZE - 1] = '\0';
+	strncpy( AppVer, locAppVer, APPVERINFO_SIZE);
+	AppVer[APPVERINFO_SIZE - 1] = '\0';
+	strncpy( AppIni, locAppIni, APPVERINFO_SIZE);
+	AppIni[APPVERINFO_SIZE - 1] = '\0';
+
+	/*
+	 * We also need to determine if we want to suppress version
+	 * checking of this application.  Does the tail of the
+	 * AppTitle end in a "-v" ?
+	 */
+	revAppTitle = _strrev( _strdup(AppTitle));
+	if( revAppTitle[0] == 'v' || revAppTitle[0] == 'V'  &&
+	   revAppTitle[1] == '-' ) {
+		VSflag = FALSE;
+	}
+	return;
+}
+
+
+/*
+ * Use the version server to give us some control on distribution and usage
+ * We're going to test track as well
+ */
+static int CallVersionServer(app_title, app_version, app_ini, code_cover)
+	char *app_title;
+	char *app_version;
+	char *app_ini;
+	char *code_cover;
+{
+	VS_Request vrequest;
+	VS_Status  vstatus;
+
+	SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+	/*
+	 * We should be able to pass in code_cover below, but things
+	 * are breaking under Windows 16 for no good reason.
+	 */
+	vrequest = VSFormRequest((LPSTR) app_title, (LPSTR) app_version,
+				 (LPSTR) app_ini,
+				 NULL /* code_cover */, NULL,
+				 V_CHECK_AND_LOG);
+
+	SetCursor(LoadCursor(NULL, IDC_ARROW));
+	/*
+	 * If the user presses cancel when registering the test
+	 * tracker, we'll let them continue.
+	 */
+	if (ReqStatus(vrequest) == V_E_CANCEL) {
+		VSDestroyRequest(vrequest);
+		return 0;
+	}
+	vstatus = VSProcessRequest(vrequest);
+	/*
+	 * Only complain periodically, if the test tracker isn't
+	 * working... 
+	 */
+	if (v_complain(vstatus, app_ini)) {
+		WinVSReportRequest(vrequest, NULL, 
+				   "Version Server Status Report");
+	}                                                         
+	if (vstatus == V_REQUIRED) {
+		SetCursor(LoadCursor(NULL, IDC_WAIT));
+		VSDestroyRequest(vrequest);
+		return( -1 );
+	}
+	VSDestroyRequest(vrequest);
+	return (0);
+}   
+#endif
+
+#ifdef TIMEBOMB
+static krb5_error_code do_timebomb()
+{
+	char buf[1024];
+	long timeleft;
+	static first_time = 1;
+
+	timeleft = TIMEBOMB - time(0);
+	if (timeleft <= 0) {
+		if (first_time) {
+			sprintf(buf, "Your version of %s has expired.\n",
+				TIMEBOMB_PRODUCT);
+			buf[sizeof(buf) - 1] = '\0';
+			strncat(buf, "Please upgrade it.", sizeof(buf) - 1 - strlen(buf));
+#ifdef TIMEBOMB_INFO
+			strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf));
+#endif
+			MessageBox(NULL, buf, "", MB_OK);
+			first_time = 0;
+		}
+		return TIMEBOMB_ERROR;
+	}
+	timeleft = timeleft / ((long) 60*60*24);
+	if (timeleft < TIMEBOMB_WARN) {
+		if (first_time) {
+			sprintf(buf, "Your version of %s will expire in %ld days.\n",
+				TIMEBOMB_PRODUCT, timeleft);
+			strncat(buf, "Please upgrade it soon.", sizeof(buf) - 1 - strlen(buf));
+#ifdef TIMEBOMB_INFO
+			strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf));
+#endif
+			MessageBox(NULL, buf, "", MB_OK);
+			first_time = 0;
+		}
+	}
+	return 0;
+}
+#endif
+
+/*
+ * This was originally called from LibMain; unfortunately, Windows 3.1
+ * doesn't allow you to make messaging calls from LibMain.  So, we now
+ * do the timebomb/version server stuff from krb5_init_context().
+ */
+krb5_error_code krb5_vercheck()
+{
+	static int verchecked = 0;
+	if (verchecked)
+		return 0;
+#ifdef TIMEBOMB
+	krb5_error_code retval = do_timebomb();
+	if (retval)
+		return retval;
+#endif
+#ifdef VERSERV
+#if 0
+	/* Check library ? */
+	if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL))
+		return KRB5_LIB_EXPIRED;
+#endif
+	{
+#ifdef APP_TITLE
+		if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL))
+			return VERSERV_ERROR;
+#else
+		char AppTitle[APPVERINFO_SIZE];
+		char AppVer[APPVERINFO_SIZE];
+		char AppIni[APPVERINFO_SIZE];
+		BOOL VSflag=TRUE;
+
+		GetCallingAppVerInfo( AppTitle, AppVer, AppIni, &VSflag);
+
+		if (VSflag) {
+			if (CallVersionServer(AppTitle, AppVer, AppIni, NULL))
+				return KRB5_APPL_EXPIRED;
+		}
+#endif
+		
+	}
+#endif
+        verchecked = 1;
+	return 0;
+}
+
+
+static HINSTANCE hlibinstance;
+
+HINSTANCE get_lib_instance()
+{
+    return hlibinstance;
+}
+
+#define DLL_STARTUP 0
+#define DLL_SHUTDOWN 1
+
+static int
+control(int mode)
+{
+    switch(mode) {
+    case DLL_STARTUP:
+	break;
+
+    case DLL_SHUTDOWN:
+#ifdef KRB5
+	krb5_stdcc_shutdown();
+#endif
+	break;
+
+#if defined(ENABLE_THREADS) && defined(SUPPORTLIB)
+    case DLL_THREAD_DETACH:
+	krb5int_thread_detach_hook();
+	return 0;
+#endif
+
+    default:
+	return -1;
+    }
+
+#if defined KRB5
+    switch (mode) {
+    case DLL_STARTUP:
+	profile_library_initializer__auxinit();
+	cryptoint_initialize_library__auxinit();
+	krb5int_lib_init__auxinit();
+	break;
+    case DLL_SHUTDOWN:
+	krb5int_lib_fini();
+	cryptoint_cleanup_library();
+	profile_library_finalizer();
+	break;
+    }
+#elif defined KRB4
+    switch (mode){ 
+    case DLL_STARTUP:
+      add_error_table(&et_krb_error_table);
+      add_error_table(&et_kadm_error_table);
+      break;
+    case DLL_SHUTDOWN:
+      remove_error_table(&et_krb_error_table);
+      remove_error_table(&et_kadm_error_table);
+      break;
+    }
+#elif defined GSSAPI
+    switch (mode) {
+    case DLL_STARTUP:
+	gssint_lib_init__auxinit();
+	break;
+    case DLL_SHUTDOWN:
+	gssint_lib_fini();
+	break;
+    }
+#elif defined COMERR
+    switch (mode) {
+    case DLL_STARTUP:
+	com_err_initialize__auxinit();
+	break;
+    case DLL_SHUTDOWN:
+	com_err_terminate();
+	break;
+    }
+#elif defined PROFILELIB
+    switch (mode) {
+    case DLL_STARTUP:
+	profile_library_initializer__auxinit();
+	break;
+    case DLL_SHUTDOWN:
+	profile_library_finalizer();
+	break;
+    }
+#elif defined SUPPORTLIB
+    switch (mode) {
+    case DLL_STARTUP:
+      krb5int_thread_support_init__auxinit();
+      break;
+    case DLL_SHUTDOWN:
+      krb5int_thread_support_fini();
+      break;
+    }
+#else
+# error "Don't know the init/fini functions for this library."
+#endif
+
+    return 0;
+}
+
+#ifdef _WIN32
+
+BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
+{
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+	    hlibinstance = (HINSTANCE) hModule;
+	    if (control(DLL_STARTUP))
+		return FALSE;
+	    break;
+
+        case DLL_THREAD_ATTACH:
+	    break;
+
+        case DLL_THREAD_DETACH:
+	    if (control(DLL_THREAD_DETACH))
+		return FALSE;
+	    break;
+
+        case DLL_PROCESS_DETACH:
+	    if (control(DLL_SHUTDOWN))
+		return FALSE;
+	    break;
+
+        default:
+	    return FALSE;
+    }
+ 
+    return TRUE;   // successful DLL_PROCESS_ATTACH
+}
+
+#else
+
+BOOL CALLBACK
+LibMain (hInst, wDataSeg, cbHeap, CmdLine)
+HINSTANCE hInst;
+WORD wDataSeg;
+WORD cbHeap;
+LPSTR CmdLine;
+{
+    hlibinstance = hInst;
+    if (control(DLL_STARTUP))
+	return 0;
+    else 
+	return 1;
+}
+
+int CALLBACK __export
+WEP(nParam)
+	int nParam;
+{
+    if (control(DLL_SHUTDOWN))
+	return 0;
+    else
+	return 1;
+}
+
+#endif
diff --git a/krb5-1-6/src/lib/xpprof32.def b/krb5-1-6/src/lib/xpprof32.def
new file mode 100644
index 000000000..c487a637b
--- /dev/null
+++ b/krb5-1-6/src/lib/xpprof32.def
@@ -0,0 +1,28 @@
+;----------------------------------------------------
+;   XPPROF32.DEF - XPPROF32.DLL 
+;----------------------------------------------------
+
+;LIBRARY		XPPROF32.DLL
+DESCRIPTION	'Cross Platform Profile DLL'
+HEAPSIZE	8192
+
+EXPORTS
+         profile_abandon		  @1
+         profile_add_relation		  @2
+         profile_clear_relation		  @3
+         profile_flush			  @4
+         profile_free_list		  @5
+         profile_get_integer		  @6
+         profile_get_relation_names	  @7
+         profile_get_string		  @8
+         profile_get_subsection_names	  @9
+         profile_get_values		 @10
+         profile_init			 @11
+         profile_init_path		 @12
+         profile_iterator		 @13
+         profile_iterator_create	 @14
+         profile_iterator_free		 @15
+         profile_release		 @16
+         profile_release_string		 @17
+         profile_rename_section		 @18
+         profile_update_relation	 @19
diff --git a/krb5-1-6/src/patchlevel.h b/krb5-1-6/src/patchlevel.h
new file mode 100644
index 000000000..6e890c28b
--- /dev/null
+++ b/krb5-1-6/src/patchlevel.h
@@ -0,0 +1,58 @@
+/*
+ * patchlevel.h
+ *
+ * Copyright (C) 2004-2006 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This is the master file for version stamping purposes.  The
+ * checked-in version will contain the correct version information at
+ * all times.  Prior to an official release x.y.z,
+ * KRB5_MAJOR_RELEASE=x, KRB5_MINOR_RELEASE=y, and KRB5_PATCHLEVEL=z.
+ * KRB5_RELTAIL will reflect the release state.  It will be
+ * "prerelease" for unreleased code either on the trunk or on a
+ * release branch.  It will be undefined for a final release.
+ *
+ * Immediately following a final release, the release version numbers
+ * will be incremented, and KRB5_RELTAIL will revert to "prerelease".
+ *
+ * KRB5_RELTAG contains the CVS tag name corresponding to the release.
+ * KRB5_RELDATE identifies the date of the release.  They should
+ * normally be undefined for checked-in code.
+ */
+
+/*
+ * ==========
+ * IMPORTANT:
+ * ==========
+ *
+ * If you are a vendor supplying modified code derived from MIT
+ * Kerberos, you SHOULD update KRB5_RELTAIL to identify your
+ * organization.
+ */
+#define KRB5_MAJOR_RELEASE 1
+#define KRB5_MINOR_RELEASE 6
+#define KRB5_PATCHLEVEL 3
+#define KRB5_RELTAIL "beta2-kfw-3.2.2-beta1"
+/* #undef KRB5_RELDATE */
+#define KRB5_RELTAG "tags/kfw-3_2_2-beta1"
diff --git a/krb5-1-6/src/plugins/kdb/db2/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/Makefile.in
new file mode 100644
index 000000000..21528aa02
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/Makefile.in
@@ -0,0 +1,159 @@
+thisconfigdir=.
+myfulldir=plugins/kdb/db2
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+MODULE_INSTALL_DIR = $(KRB5_DB_MODULE_DIR)
+DEFS=
+
+LOCALINCLUDES = -I../../../lib/kdb -I$(srcdir)/../../../lib/kdb
+DEFINES = -DPLUGIN
+
+DB_VERSION	= @DB_VERSION@
+DB_DEPS		= $(DB_DEPS-@DB_HEADER_VERSION@)
+DB_DEPS-sys	=
+DB_DEPS-k5	= $(BUILDTOP)/include/db.h $(BUILDTOP)/include/db-config.h
+DB_DEPS-redirect = $(BUILDTOP)/include/db.h
+DB_LIB		= @DB_LIB@
+KDB5_DB_LIB	= @KDB5_DB_LIB@
+DB_DEPLIB	= $(DB_DEPLIB-@DB_VERSION@)
+DB_DEPLIB-k5	= $(TOPLIBD)/libdb$(DEPLIBEXT)
+DB_DEPLIB-sys	=
+
+LIBBASE=db2
+LIBMAJOR=0
+LIBMINOR=0
+SO_EXT=.so
+RELDIR=../plugins/kdb/db2
+# Depends on libk5crypto and libkrb5
+# Also on gssrpc, for xdr stuff.
+SHLIB_EXPDEPS = \
+	$(GSSRPC_DEPLIBS) \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lcom_err -lk5crypto $(KDB5_DB_LIB) $(SUPPORT_LIB) $(LIBS)
+
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+DBDIR = libdb2
+DBOBJLISTS = $(DBOBJLISTS-@DB_VERSION@)
+DBOBJLISTS-sys =
+DBOBJLISTS-k5 = $(DBDIR)/hash/OBJS.ST $(DBDIR)/btree/OBJS.ST \
+	$(DBDIR)/db/OBJS.ST $(DBDIR)/mpool/OBJS.ST $(DBDIR)/recno/OBJS.ST \
+	$(DBDIR)/clib/OBJS.ST
+DBSHOBJLISTS = $(DBOBJLISTS:.ST=.SH)
+
+SRCS= \
+	$(srcdir)/kdb_xdr.c \
+	$(srcdir)/adb_openclose.c \
+	$(srcdir)/adb_policy.c \
+	$(srcdir)/kdb_db2.c \
+	$(srcdir)/pol_xdr.c \
+	$(srcdir)/db2_exp.c
+
+STOBJLISTS=OBJS.ST $(DBOBJLISTS)
+STLIBOBJS= \
+	kdb_xdr.o \
+	adb_openclose.o \
+	adb_policy.o \
+	kdb_db2.o \
+	pol_xdr.o \
+	db2_exp.o
+
+all-unix:: $(LIBBASE)$(SO_EXT)
+install-unix:: install-libs
+clean-unix:: clean-libs clean-libobjs
+
+$(DB_DEPS) $(DBOBJLISTS-k5) $(DBSHOBJLISTS): all-recurse
+
+#lib$(LIBBASE)$(SO_EXT): db2_exp.o
+#	$(CC) -shared -o $@ -L$(TOPLIBD) $^ -ldb $(SHLIB_EXPLIBS)
+
+clean::
+	$(RM) lib$(LIBBASE)$(SO_EXT) db2_exp.o
+
+@libnover_frag@
+@libobj_frag@
+
+.depend-verify-db: depend-verify-db-$(DB_VERSION)
+depend-verify-db-k5:
+	@if test -r .depend-verify-db; then :; \
+		else (set -x; touch .depend-verify-db); fi
+depend-verify-db-sys:
+	@echo 1>&2 error: cannot build dependencies using system db package
+	@exit 1
+
+.d: .depend-verify-db
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+kdb_xdr.so kdb_xdr.po $(OUTPRE)kdb_xdr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb_xdr.c kdb_xdr.h
+adb_openclose.so adb_openclose.po $(OUTPRE)adb_openclose.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(BUILDTOP)/lib/kdb/adb_err.h \
+  $(COM_ERR_DEPS) $(DB_DEPS) $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h adb_openclose.c policy_db.h
+adb_policy.so adb_policy.po $(OUTPRE)adb_policy.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/lib/kdb/adb_err.h \
+  $(COM_ERR_DEPS) $(DB_DEPS) $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h adb_policy.c policy_db.h
+kdb_db2.so kdb_db2.po $(OUTPRE)kdb_db2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(BUILDTOP)/lib/kdb/adb_err.h $(COM_ERR_DEPS) $(DB_DEPS) \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_db2.c kdb_db2.h kdb_xdr.h policy_db.h
+pol_xdr.so pol_xdr.po $(OUTPRE)pol_xdr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/lib/kdb/adb_err.h \
+  $(COM_ERR_DEPS) $(DB_DEPS) $(SRCTOP)/include/gssrpc/auth.h \
+  $(SRCTOP)/include/gssrpc/auth_gss.h $(SRCTOP)/include/gssrpc/auth_unix.h \
+  $(SRCTOP)/include/gssrpc/clnt.h $(SRCTOP)/include/gssrpc/rename.h \
+  $(SRCTOP)/include/gssrpc/rpc.h $(SRCTOP)/include/gssrpc/rpc_msg.h \
+  $(SRCTOP)/include/gssrpc/svc.h $(SRCTOP)/include/gssrpc/svc_auth.h \
+  $(SRCTOP)/include/gssrpc/xdr.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h pol_xdr.c policy_db.h
+db2_exp.so db2_exp.po $(OUTPRE)db2_exp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(BUILDTOP)/lib/kdb/adb_err.h $(COM_ERR_DEPS) $(DB_DEPS) \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  db2_exp.c kdb_db2.h kdb_xdr.h policy_db.h
diff --git a/krb5-1-6/src/plugins/kdb/db2/adb_openclose.c b/krb5-1-6/src/plugins/kdb/db2/adb_openclose.c
new file mode 100644
index 000000000..ce963e0da
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/adb_openclose.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$ 
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include	<sys/file.h>
+#include	<fcntl.h>
+#include	<unistd.h>
+#include        <k5-int.h>
+#include	"policy_db.h"
+#include	<stdlib.h>
+#include        <db.h>
+
+#define MAX_LOCK_TRIES 5
+
+struct _locklist {
+     osa_adb_lock_ent lockinfo;
+     struct _locklist *next;
+};
+
+krb5_error_code osa_adb_create_db(char *filename, char *lockfilename,
+				  int magic)
+{
+     int lf;
+     DB *db;
+     BTREEINFO btinfo;
+     
+     memset(&btinfo, 0, sizeof(btinfo));
+     btinfo.flags = 0;
+     btinfo.cachesize = 0;
+     btinfo.psize = 4096;
+     btinfo.lorder = 0;
+     btinfo.minkeypage = 0;
+     btinfo.compare = NULL;
+     btinfo.prefix = NULL;
+     db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_BTREE, &btinfo);
+     if (db == NULL)
+	  return errno;
+     if (db->close(db) < 0)
+	  return errno;
+
+     /* only create the lock file if we successfully created the db */
+     lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
+     if (lf == -1)
+	  return errno;
+     (void) close(lf);
+     
+     return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_destroy_db(char *filename, char *lockfilename,
+				 int magic)
+{
+     /* the admin databases do not contain security-critical data */
+     if (unlink(filename) < 0 ||
+	 unlink(lockfilename) < 0)
+	  return errno;
+     return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_rename_db(char *filefrom, char *lockfrom,
+				char *fileto, char *lockto, int magic)
+{
+     osa_adb_db_t fromdb, todb;
+     krb5_error_code ret;
+
+     /* make sure todb exists */
+     if ((ret = osa_adb_create_db(fileto, lockto, magic)) &&
+	 ret != EEXIST)
+	  return ret;
+
+     if ((ret = osa_adb_init_db(&fromdb, filefrom, lockfrom, magic)))
+	  return ret;
+     if ((ret = osa_adb_init_db(&todb, fileto, lockto, magic))) {
+	  (void) osa_adb_fini_db(fromdb, magic);
+	  return ret;
+     }
+     if ((ret = osa_adb_get_lock(fromdb, KRB5_DB_LOCKMODE_PERMANENT))) {
+	  (void) osa_adb_fini_db(fromdb, magic);
+	  (void) osa_adb_fini_db(todb, magic);
+	  return ret;
+     }
+     if ((ret = osa_adb_get_lock(todb, KRB5_DB_LOCKMODE_PERMANENT))) {
+	  (void) osa_adb_fini_db(fromdb, magic);
+	  (void) osa_adb_fini_db(todb, magic);
+	  return ret;
+     }
+     if ((rename(filefrom, fileto) < 0)) {
+	  (void) osa_adb_fini_db(fromdb, magic);
+	  (void) osa_adb_fini_db(todb, magic);
+	  return errno;
+     }
+     /*
+      * Do not release the lock on fromdb because it is being renamed
+      * out of existence; no one can ever use it again.
+      */
+     if ((ret = osa_adb_release_lock(todb))) {
+	  (void) osa_adb_fini_db(fromdb, magic);
+	  (void) osa_adb_fini_db(todb, magic);
+	  return ret;
+     }
+	  
+     (void) osa_adb_fini_db(fromdb, magic);
+     (void) osa_adb_fini_db(todb, magic);
+     return 0;
+}
+
+krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
+			      char *lockfilename, int magic)
+{
+     osa_adb_db_t db;
+     static struct _locklist *locklist = NULL;
+     struct _locklist *lockp;
+     krb5_error_code code;
+     
+     if (dbp == NULL || filename == NULL)
+	  return EINVAL;
+
+     db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent));
+     if (db == NULL)
+	  return ENOMEM;
+
+     memset(db, 0, sizeof(*db));
+     db->info.hash = NULL;
+     db->info.bsize = 256;
+     db->info.ffactor = 8;
+     db->info.nelem = 25000;
+     db->info.lorder = 0;
+
+     db->btinfo.flags = 0;
+     db->btinfo.cachesize = 0;
+     db->btinfo.psize = 4096;
+     db->btinfo.lorder = 0;
+     db->btinfo.minkeypage = 0;
+     db->btinfo.compare = NULL;
+     db->btinfo.prefix = NULL;
+     /*
+      * A process is allowed to open the same database multiple times
+      * and access it via different handles.  If the handles use
+      * distinct lockinfo structures, things get confused: lock(A),
+      * lock(B), release(B) will result in the kernel unlocking the
+      * lock file but handle A will still think the file is locked.
+      * Therefore, all handles using the same lock file must share a
+      * single lockinfo structure.
+      *
+      * It is not sufficient to have a single lockinfo structure,
+      * however, because a single process may also wish to open
+      * multiple different databases simultaneously, with different
+      * lock files.  This code used to use a single static lockinfo
+      * structure, which means that the second database opened used
+      * the first database's lock file.  This was Bad.
+      *
+      * We now maintain a linked list of lockinfo structures, keyed by
+      * lockfilename.  An entry is added when this function is called
+      * with a new lockfilename, and all subsequent calls with that
+      * lockfilename use the existing entry, updating the refcnt.
+      * When the database is closed with fini_db(), the refcnt is
+      * decremented, and when it is zero the lockinfo structure is
+      * freed and reset.  The entry in the linked list, however, is
+      * never removed; it will just be reinitialized the next time
+      * init_db is called with the right lockfilename.
+      */
+
+     /* find or create the lockinfo structure for lockfilename */
+     lockp = locklist;
+     while (lockp) {
+	  if (strcmp(lockp->lockinfo.filename, lockfilename) == 0)
+	       break;
+	  else
+	       lockp = lockp->next;
+     }
+     if (lockp == NULL) {
+	  /* doesn't exist, create it, add to list */
+	  lockp = (struct _locklist *) malloc(sizeof(*lockp));
+	  if (lockp == NULL) {
+	       free(db);
+	       return ENOMEM;
+	  }
+	  memset(lockp, 0, sizeof(*lockp));
+	  lockp->next = locklist;
+	  locklist = lockp;
+     }
+
+     /* now initialize lockp->lockinfo if necessary */
+     if (lockp->lockinfo.lockfile == NULL) {
+	  if ((code = krb5int_init_context_kdc(&lockp->lockinfo.context))) {
+	       free(db);
+	       return((krb5_error_code) code);
+	  }
+
+	  /*
+	   * needs be open read/write so that write locking can work with
+	   * POSIX systems
+	   */
+	  lockp->lockinfo.filename = strdup(lockfilename);
+	  if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
+	       /*
+		* maybe someone took away write permission so we could only
+		* get shared locks?
+		*/
+	       if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r"))
+		   == NULL) {
+		    free(db);
+		    return OSA_ADB_NOLOCKFILE;
+	       }
+	  }
+	  lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0;
+     }
+
+     /* lockp is set, lockinfo is initialized, update the reference count */
+     db->lock = &lockp->lockinfo;
+     db->lock->refcnt++;
+
+     db->opencnt = 0;
+     db->filename = strdup(filename);
+     db->magic = magic;
+
+     *dbp = db;
+     
+     return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_fini_db(osa_adb_db_t db, int magic)
+{
+     if (db->magic != magic)
+	  return EINVAL;
+     if (db->lock->refcnt == 0) {
+	  /* barry says this can't happen */
+	  return OSA_ADB_FAILURE;
+     } else {
+	  db->lock->refcnt--;
+     }
+
+     if (db->lock->refcnt == 0) {
+	  /*
+	   * Don't free db->lock->filename, it is used as a key to
+	   * find the lockinfo entry in the linked list.  If the
+	   * lockfile doesn't exist, we must be closing the database
+	   * after trashing it.  This has to be allowed, so don't
+	   * generate an error.
+	   */
+	  if (db->lock->lockmode != KRB5_DB_LOCKMODE_PERMANENT)
+	       (void) fclose(db->lock->lockfile);
+	  db->lock->lockfile = NULL;
+	  krb5_free_context(db->lock->context);
+     }
+
+     db->magic = 0;
+     free(db->filename);
+     free(db);
+     return OSA_ADB_OK;
+}     
+     
+krb5_error_code osa_adb_get_lock(osa_adb_db_t db, int mode)
+{
+     int tries, gotlock, perm, krb5_mode, ret = 0;
+
+     if (db->lock->lockmode >= mode) {
+	  /* No need to upgrade lock, just incr refcnt and return */
+	  db->lock->lockcnt++;
+	  return(OSA_ADB_OK);
+     }
+
+     perm = 0;
+     switch (mode) {
+	case KRB5_DB_LOCKMODE_PERMANENT:
+	  perm = 1;
+	case KRB5_DB_LOCKMODE_EXCLUSIVE:
+	  krb5_mode = KRB5_LOCKMODE_EXCLUSIVE;
+	  break;
+	case KRB5_DB_LOCKMODE_SHARED:
+	  krb5_mode = KRB5_LOCKMODE_SHARED;
+	  break;
+	default:
+	  return(EINVAL);
+     }
+
+     for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
+	  if ((ret = krb5_lock_file(db->lock->context,
+				    fileno(db->lock->lockfile),
+				    krb5_mode|KRB5_LOCKMODE_DONTBLOCK)) == 0) {
+	       gotlock++;
+	       break;
+	  } else if (ret == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
+	       /* tried to exclusive-lock something we don't have */
+	       /* write access to */
+	       return OSA_ADB_NOEXCL_PERM;
+
+	  sleep(1);
+     }
+
+     /* test for all the likely "can't get lock" error codes */
+     if (ret == EACCES || ret == EAGAIN || ret == EWOULDBLOCK)
+	  return OSA_ADB_CANTLOCK_DB;
+     else if (ret != 0)
+	  return ret;
+
+     /*
+      * If the file no longer exists, someone acquired a permanent
+      * lock.  If that process terminates its exclusive lock is lost,
+      * but if we already had the file open we can (probably) lock it
+      * even though it has been unlinked.  So we need to insist that
+      * it exist.
+      */
+     if (access(db->lock->filename, F_OK) < 0) {
+	  (void) krb5_lock_file(db->lock->context,
+				fileno(db->lock->lockfile),
+				KRB5_LOCKMODE_UNLOCK);
+	  return OSA_ADB_NOLOCKFILE;
+     }
+     
+     /* we have the shared/exclusive lock */
+     
+     if (perm) {
+	  if (unlink(db->lock->filename) < 0) {
+	       /* somehow we can't delete the file, but we already */
+	       /* have the lock, so release it and return */
+
+	       ret = errno;
+	       (void) krb5_lock_file(db->lock->context,
+				     fileno(db->lock->lockfile),
+				     KRB5_LOCKMODE_UNLOCK);
+	       
+	       /* maybe we should return CANTLOCK_DB.. but that would */
+	       /* look just like the db was already locked */
+	       return ret;
+	  }
+
+	  /* this releases our exclusive lock.. which is okay because */
+	  /* now no one else can get one either */
+	  (void) fclose(db->lock->lockfile);
+     }
+     
+     db->lock->lockmode = mode;
+     db->lock->lockcnt++;
+     return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_release_lock(osa_adb_db_t db)
+{
+     int ret, fd;
+     
+     if (!db->lock->lockcnt)		/* lock already unlocked */
+	  return OSA_ADB_NOTLOCKED;
+
+     if (--db->lock->lockcnt == 0) {
+	  if (db->lock->lockmode == KRB5_DB_LOCKMODE_PERMANENT) {
+	       /* now we need to create the file since it does not exist */
+               fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL,
+                                   0600);
+	       if ((db->lock->lockfile = fdopen(fd, "w+")) == NULL)
+		    return OSA_ADB_NOLOCKFILE;
+	  } else if ((ret = krb5_lock_file(db->lock->context,
+					  fileno(db->lock->lockfile),
+					  KRB5_LOCKMODE_UNLOCK)))
+	       return ret;
+	  
+	  db->lock->lockmode = 0;
+     }
+     return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype)
+{
+     int ret;
+
+     ret = osa_adb_get_lock(db, locktype);
+     if (ret != OSA_ADB_OK)
+	  return ret;
+     if (db->opencnt)
+	  goto open_ok;
+
+     db->db = dbopen(db->filename, O_RDWR, 0600, DB_BTREE, &db->btinfo);
+     if (db->db != NULL)
+	 goto open_ok;
+     switch (errno) {
+#ifdef EFTYPE
+     case EFTYPE:
+#endif
+     case EINVAL:
+	  db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info);
+	  if (db->db != NULL)
+	       goto open_ok;
+     default:
+	  (void) osa_adb_release_lock(db);
+	  if (errno == EINVAL)
+	       return OSA_ADB_BAD_DB;
+	  return errno;
+     }
+open_ok:
+     db->opencnt++;
+     return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db)
+{
+     if (--db->opencnt)
+	  return osa_adb_release_lock(db);
+     if(db->db != NULL && db->db->close(db->db) == -1) {
+	  (void) osa_adb_release_lock(db);
+	  return OSA_ADB_FAILURE;
+     }
+
+     db->db = NULL;
+
+     return(osa_adb_release_lock(db));
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/adb_policy.c b/krb5-1-6/src/plugins/kdb/db2/adb_policy.c
new file mode 100644
index 000000000..e338cbbd0
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/adb_policy.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include	<sys/file.h>
+#include	<fcntl.h>
+#include	"policy_db.h"
+#include	<stdlib.h>
+#include	<string.h>
+#include <errno.h>
+
+#define OPENLOCK(db, mode) \
+{ \
+       int olret; \
+	    if (db == NULL) \
+		 return EINVAL; \
+	    else if (db->magic != OSA_ADB_POLICY_DB_MAGIC) \
+		 return OSA_ADB_DBINIT; \
+	    else if ((olret = osa_adb_open_and_lock(db, mode)) != OSA_ADB_OK) \
+		 return olret; \
+	    }
+
+#define CLOSELOCK(db) \
+{ \
+     int cl_ret; \
+     if ((cl_ret = osa_adb_close_and_unlock(db)) != OSA_ADB_OK) \
+	  return cl_ret; \
+}
+
+
+/*
+ * Function: osa_adb_create_policy
+ * 
+ * Purpose: create a policy entry in the policy db.
+ *
+ * Arguments:
+ *	entry		(input) pointer to the entry to be added
+ * 	<return value>	OSA_ADB_OK on success, else error code.
+ *
+ * Requires:
+ *	entry have a valid name.
+ * 
+ * Effects:
+ *	creates the entry in the db
+ *
+ * Modifies:
+ *	the policy db.
+ * 
+ */
+krb5_error_code
+osa_adb_create_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
+{
+    DBT			dbkey;
+    DBT			dbdata;
+    XDR			xdrs;
+    int			ret;
+
+    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
+
+    if(entry->name == NULL) {
+	 ret = EINVAL;
+	 goto error;
+    }
+    dbkey.data = entry->name;
+    dbkey.size = (strlen(entry->name) + 1);
+		
+    switch(db->db->get(db->db, &dbkey, &dbdata, 0)) {
+    case 0:
+	 ret = OSA_ADB_DUP;
+	 goto error;
+    case 1:
+	break;
+    default:
+	 ret = errno;
+	 goto error;
+    }
+    xdralloc_create(&xdrs, XDR_ENCODE);
+    if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+	xdr_destroy(&xdrs);
+	ret = OSA_ADB_XDR_FAILURE;
+	goto error;
+    }
+    dbdata.data = xdralloc_getdata(&xdrs);
+    dbdata.size = xdr_getpos(&xdrs);
+    switch(db->db->put(db->db, &dbkey, &dbdata, R_NOOVERWRITE)) {
+    case 0:
+	if((db->db->sync(db->db, 0)) == -1)
+	    ret = OSA_ADB_FAILURE;
+	ret = OSA_ADB_OK;
+	break;
+    case 1:
+	ret = OSA_ADB_DUP;
+	break;
+    default:
+	ret = OSA_ADB_FAILURE;
+	break;
+    }
+    xdr_destroy(&xdrs);
+
+error:
+    CLOSELOCK(db);
+    return ret;
+}
+
+/*
+ * Function: osa_adb_destroy_policy
+ * 
+ * Purpose: destroy a policy entry
+ *
+ * Arguments:
+ *	db		(input) database handle
+ *	name		(input) name of policy
+ * 	<return value>	OSA_ADB_OK on success, or error code.
+ *
+ * Requires:
+ *	db being valid.
+ *	name being non-null.
+ * Effects:
+ *	deletes policy from db.
+ *
+ * Modifies:
+ *	policy db.
+ * 
+ */
+krb5_error_code
+osa_adb_destroy_policy(osa_adb_policy_t db, char *name)
+{
+    DBT	    dbkey;
+    int	    status, ret;
+
+    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
+    
+    if(name == NULL) {
+	 ret = EINVAL;
+	 goto error;
+    }
+    dbkey.data = name;
+    dbkey.size = (strlen(name) + 1);
+
+    status = db->db->del(db->db, &dbkey, 0);
+    switch(status) {
+    case 1:
+	 ret = OSA_ADB_NOENT;
+	 goto error;
+    case 0:
+	 if ((db->db->sync(db->db, 0)) == -1) {
+	      ret = OSA_ADB_FAILURE;
+	      goto error;
+	 }
+	 ret = OSA_ADB_OK;
+	 break;
+    default:
+	 ret = OSA_ADB_FAILURE;
+	 goto error;
+    }
+
+error:
+    CLOSELOCK(db);
+    return ret;
+}
+
+/*
+ * Function: osa_adb_get_policy
+ * 
+ * Purpose: retrieve policy
+ *
+ * Arguments:
+ *	db		(input) db handle
+ *	name		(input) name of policy
+ *	entry		(output) policy entry
+ *      cnt             (inout) Number of entries
+ * 	<return value>	0 on success, error code on failure.
+ *
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+krb5_error_code
+osa_adb_get_policy(osa_adb_policy_t db, char *name,
+		   osa_policy_ent_t *entry, int *cnt)
+{
+    DBT			dbkey;
+    DBT			dbdata;
+    XDR			xdrs;
+    int			ret;
+    char		*aligned_data;
+
+    OPENLOCK(db, KRB5_DB_LOCKMODE_SHARED);
+
+    *cnt = 1;
+
+    if(name == NULL) {
+	 ret = EINVAL;
+	 goto error;
+    }
+    dbkey.data = name;
+    dbkey.size = (strlen(dbkey.data) + 1);
+    dbdata.data = NULL;
+    dbdata.size = 0;
+    switch((db->db->get(db->db, &dbkey, &dbdata, 0))) {
+    case 1:
+	 ret = 0;
+	 *cnt = 0;
+	 goto error;
+    case 0:
+	break;
+    default:
+	 ret = OSA_ADB_FAILURE;
+	 goto error;
+    }
+    if (!(*(entry) = (osa_policy_ent_t)malloc(sizeof(osa_policy_ent_rec)))) {
+	 ret = ENOMEM;
+	 goto error;
+    }
+    if (!(aligned_data = (char *) malloc(dbdata.size))) {
+	 ret = ENOMEM;
+	 goto error;
+    }
+    memcpy(aligned_data, dbdata.data, dbdata.size);	
+    memset(*entry, 0, sizeof(osa_policy_ent_rec));
+    xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+    if (!xdr_osa_policy_ent_rec(&xdrs, *entry)) 
+	ret =  OSA_ADB_FAILURE;
+    else ret = OSA_ADB_OK;
+    xdr_destroy(&xdrs);
+    free(aligned_data);
+
+error:
+    CLOSELOCK(db);
+    return ret;
+}
+
+/*
+ * Function: osa_adb_put_policy
+ * 
+ * Purpose: update a policy in the dababase
+ *
+ * Arguments:
+ *	db		(input) db handle
+ *	entry		(input) policy entry
+ * 	<return value>	0 on success error code on failure.
+ *
+ * Requires:
+ *	[requires]
+ * 
+ * Effects:
+ *	[effects]
+ *
+ * Modifies:
+ *	[modifies]
+ * 
+ */
+krb5_error_code
+osa_adb_put_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
+{
+    DBT			dbkey;
+    DBT			dbdata;
+    DBT			tmpdb;
+    XDR			xdrs;
+    int			ret;
+
+    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
+    
+    if(entry->name == NULL) {
+	 ret = EINVAL;
+	 goto error;
+    }
+    dbkey.data = entry->name;
+    dbkey.size = (strlen(entry->name) + 1);
+    switch(db->db->get(db->db, &dbkey, &tmpdb, 0)) {
+    case 0:
+	break;
+    case 1:
+	ret = OSA_ADB_NOENT;
+	goto error;
+    default:
+	ret = OSA_ADB_FAILURE;
+	goto error;
+    }
+    xdralloc_create(&xdrs, XDR_ENCODE);
+    if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+	xdr_destroy(&xdrs);
+	ret = OSA_ADB_XDR_FAILURE;
+	goto error;
+    }
+    dbdata.data = xdralloc_getdata(&xdrs);
+    dbdata.size = xdr_getpos(&xdrs);
+    switch(db->db->put(db->db, &dbkey, &dbdata, 0)) {
+    case 0:
+	if((db->db->sync(db->db, 0)) == -1)
+	    ret = OSA_ADB_FAILURE;
+	ret = OSA_ADB_OK;
+	break;
+    default:
+	ret = OSA_ADB_FAILURE;
+	break;
+    }
+    xdr_destroy(&xdrs);
+
+error:
+    CLOSELOCK(db);
+    return ret;
+}
+
+/*
+ * Function: osa_adb_iter_policy
+ * 
+ * Purpose: iterate over the policy database.
+ *
+ * Arguments:
+ *	db		(input) db handle
+ *	func		(input) fucntion pointer to call
+ *	data		opaque data type
+ * 	<return value>	0 on success error code on failure
+ *
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+krb5_error_code
+osa_adb_iter_policy(osa_adb_policy_t db, osa_adb_iter_policy_func func,
+		    void *data)
+{
+    DBT			    dbkey,
+			    dbdata;
+    XDR			    xdrs;
+    int			    ret;
+    osa_policy_ent_t	    entry;
+    char		    *aligned_data;
+
+    OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE); /* hmmm */
+
+    if((ret = db->db->seq(db->db, &dbkey, &dbdata, R_FIRST)) == -1) {
+	 ret = errno;
+	 goto error;
+    }
+
+    while (ret == 0) {
+	if (!(entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)))) {
+	     ret = ENOMEM;
+	     goto error;
+	}
+
+	if(!(aligned_data = (char *) malloc(dbdata.size))) {
+	     ret = ENOMEM;
+	     goto error;
+	}
+	memcpy(aligned_data, dbdata.data, dbdata.size);
+	
+	memset(entry, 0, sizeof(osa_policy_ent_rec));
+	xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+	if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+	    xdr_destroy(&xdrs);
+	    free(aligned_data);
+	    ret = OSA_ADB_FAILURE;
+	    goto error;
+	}
+	(*func)(data, entry);
+	xdr_destroy(&xdrs);
+	free(aligned_data);	
+	osa_free_policy_ent(entry);
+	ret = db->db->seq(db->db, &dbkey, &dbdata, R_NEXT);
+    }
+    if(ret == -1)
+	 ret = errno;
+    else ret = OSA_ADB_OK;
+
+error:
+    CLOSELOCK(db);
+    return ret;
+}
+
+void
+osa_free_policy_ent(osa_policy_ent_t val)
+{
+  XDR xdrs;
+
+  xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+
+  xdr_osa_policy_ent_rec(&xdrs, val);
+
+  free(val);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/configure.in b/krb5-1-6/src/plugins/kdb/db2/configure.in
new file mode 100644
index 000000000..9f958db12
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/configure.in
@@ -0,0 +1,27 @@
+K5_AC_INIT(configure.in)
+enable_shared=yes
+build_dynobj=yes
+CONFIG_RULES
+AC_CHECK_HEADERS(unistd.h)
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+
+AC_CHECK_FUNCS(srand48 srand srandom umask)
+
+dnl AIX is unusual in that it wants all symbols resolved at link time
+dnl  Fortunately, it will allow us to link the kdb library now, even if
+dnl it is linked again later.
+case $krb5_cv_host in
+*-*-aix*)
+	LIBS="$LIBS -ldb"
+	;;
+esac
+KRB5_RUN_FLAGS
+dnl The following is for check...
+KRB5_BUILD_PROGRAM
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+if test "$DB_VERSION" = k5 ; then
+  AC_CONFIG_SUBDIRS(libdb2)
+fi
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/plugins/kdb/db2/db2.exports b/krb5-1-6/src/plugins/kdb/db2/db2.exports
new file mode 100644
index 000000000..f2b7c1119
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/db2.exports
@@ -0,0 +1 @@
+kdb_function_table
diff --git a/krb5-1-6/src/plugins/kdb/db2/db2_exp.c b/krb5-1-6/src/plugins/kdb/db2/db2_exp.c
new file mode 100644
index 000000000..9b6a58abd
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/db2_exp.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/**********************************************************************
+*
+*	C %name:		db2_exp.c %
+*	Instance:		idc_sec_2
+*	Description:	
+*	%created_by:	spradeep %
+*	%date_created:	Tue Apr  5 11:44:00 2005 %
+*
+**********************************************************************/
+#ifndef lint
+static char *_csrc = "@(#) %filespec: db2_exp.c~5 %  (%full_filespec: db2_exp.c~5:csrc:idc_sec#2 %)";
+#endif
+
+#include "k5-int.h"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <db.h>
+#include <stdio.h>
+#include <errno.h>
+#include <utime.h>
+#include "kdb5.h"
+#include "kdb_db2.h"
+#include "kdb_xdr.h"
+#include "policy_db.h"
+
+/* Quick and dirty wrapper functions to provide for thread safety
+   within the plugin, instead of making the kdb5 library do it.  Eventually
+   these should be integrated into the real functions.
+
+   Some of the functions wrapped here are also called directly from
+   within this library (e.g., create calls open), so simply dropping
+   locking code into the top and bottom of each referenced function
+   won't do.  (We aren't doing recursive locks, currently.)  */
+
+static k5_mutex_t *krb5_db2_mutex;
+
+#define WRAP(NAME,TYPE,ARGLIST,ARGNAMES,ERROR_RESULT)	\
+	static TYPE wrap_##NAME ARGLIST			\
+	{						\
+	    TYPE result;				\
+	    int code = k5_mutex_lock (krb5_db2_mutex);	\
+	    if (code) { return ERROR_RESULT; }		\
+	    result = NAME ARGNAMES;			\
+	    k5_mutex_unlock (krb5_db2_mutex);		\
+	    return result;				\
+	}						\
+	/* hack: decl to allow a following ";" */	\
+	static TYPE wrap_##NAME ()
+
+/* Two special cases: void (can't assign result), and krb5_error_code
+   (return error from locking code).  */
+
+#define WRAP_VOID(NAME,ARGLIST,ARGNAMES)		\
+	static void wrap_##NAME ARGLIST			\
+	{						\
+	    int code = k5_mutex_lock (krb5_db2_mutex);	\
+	    if (code) { return; }			\
+	    NAME ARGNAMES;				\
+	    k5_mutex_unlock (krb5_db2_mutex);		\
+	}						\
+	/* hack: decl to allow a following ";" */	\
+	static void wrap_##NAME ()
+
+#define WRAP_K(NAME,ARGLIST,ARGNAMES)			\
+	WRAP(NAME,krb5_error_code,ARGLIST,ARGNAMES,code)
+
+WRAP_K (krb5_db2_open,
+	( krb5_context kcontext,
+	  char *conf_section,
+	  char **db_args,
+	  int mode ),
+	(kcontext, conf_section, db_args, mode));
+WRAP_K (krb5_db2_db_fini, (krb5_context ctx), (ctx));
+WRAP_K (krb5_db2_create,
+	( krb5_context kcontext, char *conf_section, char **db_args ),
+	(kcontext, conf_section, db_args));
+WRAP_K (krb5_db2_destroy,
+	( krb5_context kcontext, char *conf_section, char **db_args ),
+	(kcontext, conf_section, db_args));
+WRAP_K (krb5_db2_db_get_age,
+	(krb5_context ctx,
+		   char *s,
+	 time_t *t),
+	(ctx, s, t));
+WRAP_K (krb5_db2_db_set_option,
+	( krb5_context kcontext, 
+	  int option, 
+	  void *value ),
+	(kcontext, option, value));
+
+WRAP_K (krb5_db2_db_lock,
+	( krb5_context 	  context,
+	  int 	 	  in_mode),
+	(context, in_mode));
+WRAP_K (krb5_db2_db_unlock, (krb5_context ctx), (ctx));
+
+WRAP_K (krb5_db2_db_get_principal,
+	(krb5_context ctx,
+		   krb5_const_principal p,
+		   krb5_db_entry *d,
+		   int * i,
+	 krb5_boolean *b),
+	(ctx, p, d, i, b));
+WRAP_K (krb5_db2_db_free_principal,
+	(krb5_context ctx,
+		   krb5_db_entry *d,
+	 int i),
+	(ctx, d, i));
+WRAP_K (krb5_db2_db_put_principal,
+	(krb5_context ctx,
+	 krb5_db_entry *d,
+	 int *i,
+	 char **db_args),
+	(ctx, d, i, db_args));
+WRAP_K (krb5_db2_db_delete_principal,
+	(krb5_context context,
+	 krb5_const_principal searchfor,
+	 int *nentries),
+	(context, searchfor, nentries));
+
+WRAP_K (krb5_db2_db_iterate,
+	(krb5_context ctx, char *s,
+	 krb5_error_code (*f) (krb5_pointer,
+			      krb5_db_entry *),
+	 krb5_pointer p),
+	(ctx, s, f, p));
+
+WRAP_K (krb5_db2_create_policy,
+	(krb5_context context, osa_policy_ent_t entry),
+	(context, entry));
+WRAP_K (krb5_db2_get_policy,
+	( krb5_context kcontext,
+	  char *name,
+	  osa_policy_ent_t *policy,
+	  int *cnt),
+	(kcontext, name, policy, cnt));
+WRAP_K (krb5_db2_put_policy,
+	( krb5_context kcontext, osa_policy_ent_t policy ),
+	(kcontext, policy));
+WRAP_K (krb5_db2_iter_policy,
+	( krb5_context kcontext,
+	  char *match_entry,
+	  osa_adb_iter_policy_func func,
+	  void *data ),
+	(kcontext, match_entry, func, data));
+WRAP_K (krb5_db2_delete_policy,
+	( krb5_context kcontext, char *policy ),
+	(kcontext, policy));
+WRAP_VOID (krb5_db2_free_policy,
+	   ( krb5_context kcontext, osa_policy_ent_t entry ),
+	   (kcontext, entry));
+
+WRAP (krb5_db2_alloc, void *,
+      ( krb5_context kcontext,  
+	void *ptr, 
+	size_t size ),
+      (kcontext, ptr, size), NULL);
+WRAP_VOID (krb5_db2_free,
+	   ( krb5_context kcontext, void *ptr ),
+	   (kcontext, ptr));
+
+WRAP_K (krb5_db2_set_master_key_ext,
+	( krb5_context kcontext, char *pwd, krb5_keyblock *key),
+	(kcontext, pwd, key));
+WRAP_K (krb5_db2_db_get_mkey,
+	( krb5_context context, krb5_keyblock **key),
+	(context, key));
+WRAP_K (krb5_db2_promote_db,
+	( krb5_context kcontext, char *conf_section, char **db_args ),
+	(kcontext, conf_section, db_args));
+
+static krb5_error_code
+hack_init ()
+{
+    krb5_error_code c;
+    c = krb5int_mutex_alloc (&krb5_db2_mutex);
+    if (c)
+	return c;
+    return krb5_db2_lib_init ();
+}
+
+static krb5_error_code
+hack_cleanup (void)
+{
+    krb5int_mutex_free (krb5_db2_mutex);
+    krb5_db2_mutex = NULL;
+    return krb5_db2_lib_cleanup();
+}
+
+
+/*
+ *      Exposed API
+ */
+
+kdb_vftabl kdb_function_table = {
+  1,                                      /* major version number 1 */
+  0,                                      /* minor version number 0 */
+  /* init_library */			       hack_init,
+  /* fini_library */			       hack_cleanup,
+  /* init_module */			       wrap_krb5_db2_open,
+  /* fini_module */			       wrap_krb5_db2_db_fini,
+  /* db_create */			       wrap_krb5_db2_create,
+  /* db_destroy */			       wrap_krb5_db2_destroy,
+  /* db_get_age */                             wrap_krb5_db2_db_get_age,
+  /* db_set_option */			       wrap_krb5_db2_db_set_option,
+  /* db_lock */				       wrap_krb5_db2_db_lock,
+  /* db_unlock */			       wrap_krb5_db2_db_unlock,
+  /* db_get_principal */		       wrap_krb5_db2_db_get_principal,
+  /* db_free_principal */		       wrap_krb5_db2_db_free_principal,
+  /* db_put_principal */		       wrap_krb5_db2_db_put_principal,
+  /* db_delete_principal */		       wrap_krb5_db2_db_delete_principal,
+  /* db_iterate */			       wrap_krb5_db2_db_iterate,
+  /* db_create_policy */                       wrap_krb5_db2_create_policy,
+  /* db_get_policy */                          wrap_krb5_db2_get_policy,
+  /* db_put_policy */                          wrap_krb5_db2_put_policy,
+  /* db_iter_policy */                         wrap_krb5_db2_iter_policy,
+  /* db_delete_policy */                       wrap_krb5_db2_delete_policy,
+  /* db_free_policy */                         wrap_krb5_db2_free_policy,
+  /* db_supported_realms */		       NULL,
+  /* db_free_supported_realms */	       NULL,
+  /* errcode_2_string */                       NULL,
+  /* release_errcode_string */		       NULL,
+  /* db_alloc */                               wrap_krb5_db2_alloc,
+  /* db_free */                                wrap_krb5_db2_free,
+  /* set_master_key */			       wrap_krb5_db2_set_master_key_ext,
+  /* get_master_key */			       wrap_krb5_db2_db_get_mkey,
+  /* blah blah blah */ 0,0,0,0,0,0,
+  /* promote_db */			       wrap_krb5_db2_promote_db,
+};
diff --git a/krb5-1-6/src/plugins/kdb/db2/kdb_compat.h b/krb5-1-6/src/plugins/kdb/db2/kdb_compat.h
new file mode 100644
index 000000000..540d4a249
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/kdb_compat.h
@@ -0,0 +1,81 @@
+/*
+ * lib/kdb/kdb_compat.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * KDC Database interface definitions.
+ */
+
+
+typedef struct _old_krb5_encrypted_keyblock {
+    krb5_enctype enctype;
+    int length;
+    krb5_octet *contents;
+} old_krb5_encrypted_keyblock;
+
+typedef struct old_krb5_principal_data {
+    krb5_magic magic;
+    krb5_data realm;
+    krb5_data *data;		/* An array of strings */
+    krb5_int32 length;
+    krb5_int32 type;
+} old_krb5_principal_data;
+
+typedef	old_krb5_principal_data *old_krb5_principal;
+
+
+/*
+ * Note --- this structure cannot be modified without changing the
+ * database version number in libkdb.a
+ */
+typedef struct _old_krb5_db_entry {
+    old_krb5_principal principal;
+    old_krb5_encrypted_keyblock key;
+    krb5_kvno kvno;
+    krb5_deltat	max_life;
+    krb5_deltat	max_renewable_life;
+    krb5_kvno mkvno;			/* master encryption key vno */
+    
+    krb5_timestamp expiration;		/* This is when the client expires */
+    krb5_timestamp pw_expiration; 	/* This is when its password does */
+    krb5_timestamp last_pwd_change; 	/* Last time of password change  */
+    krb5_timestamp last_success;	/* Last successful password */
+    
+    krb5_timestamp last_failed;		/* Last failed password attempt */
+    krb5_kvno fail_auth_count; 		/* # of failed password attempts */
+    
+    old_krb5_principal mod_name;
+    krb5_timestamp mod_date;
+    krb5_flags attributes;
+    krb5_int32 salt_type:8,
+ 	       salt_length:24;
+    krb5_octet *salt;
+    old_krb5_encrypted_keyblock alt_key;
+    krb5_int32 alt_salt_type:8,
+ 	       alt_salt_length:24;
+    krb5_octet *alt_salt;
+    
+    krb5_int32 expansion[8];
+} old_krb5_db_entry;
+
diff --git a/krb5-1-6/src/plugins/kdb/db2/kdb_db2.c b/krb5-1-6/src/plugins/kdb/db2/kdb_db2.c
new file mode 100644
index 000000000..d438171cb
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/kdb_db2.c
@@ -0,0 +1,1761 @@
+/*
+ * lib/kdb/kdb_db2.c
+ *
+ * Copyright 1997,2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * Copyright (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"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <db.h>
+#include <stdio.h>
+#include <errno.h>
+#include <utime.h>
+#include "kdb5.h"
+#include "kdb_db2.h"
+#include "kdb_xdr.h"
+#include "policy_db.h"
+
+#define KDB_DB2_DATABASE_NAME "database_name"
+
+#include "kdb_db2.h"
+
+static char *gen_dbsuffix(char *, char *);
+
+static krb5_error_code krb5_db2_db_start_update(krb5_context);
+static krb5_error_code krb5_db2_db_end_update(krb5_context);
+
+static krb5_error_code krb5_db2_db_set_name(krb5_context, char *, int);
+
+krb5_error_code krb5_db2_db_lock(krb5_context, int);
+
+static krb5_error_code krb5_db2_db_set_hashfirst(krb5_context, int);
+
+static char default_db_name[] = DEFAULT_KDB_FILE;
+
+/*
+ * Locking:
+ *
+ * There are two distinct locking protocols used.  One is designed to
+ * lock against processes (the admin_server, for one) which make
+ * incremental changes to the database; the other is designed to lock
+ * against utilities (kdb5_edit, kpropd, kdb5_convert) which replace the
+ * entire database in one fell swoop.
+ *
+ * The first locking protocol is implemented using flock() in the
+ * krb_dbl_lock() and krb_dbl_unlock routines.
+ *
+ * The second locking protocol is necessary because DBM "files" are
+ * actually implemented as two separate files, and it is impossible to
+ * atomically rename two files simultaneously.  It assumes that the
+ * database is replaced only very infrequently in comparison to the time
+ * needed to do a database read operation.
+ *
+ * A third file is used as a "version" semaphore; the modification
+ * time of this file is the "version number" of the database.
+ * At the start of a read operation, the reader checks the version
+ * number; at the end of the read operation, it checks again.  If the
+ * version number changed, or if the semaphore was nonexistant at
+ * either time, the reader sleeps for a second to let things
+ * stabilize, and then tries again; if it does not succeed after
+ * KRB5_DBM_MAX_RETRY attempts, it gives up.
+ *
+ * On update, the semaphore file is deleted (if it exists) before any
+ * update takes place; at the end of the update, it is replaced, with
+ * a version number strictly greater than the version number which
+ * existed at the start of the update.
+ *
+ * If the system crashes in the middle of an update, the semaphore
+ * file is not automatically created on reboot; this is a feature, not
+ * a bug, since the database may be inconsistant.  Note that the
+ * absence of a semaphore file does not prevent another _update_ from
+ * taking place later.  Database replacements take place automatically
+ * only on slave servers; a crash in the middle of an update will be
+ * fixed by the next slave propagation.  A crash in the middle of an
+ * update on the master would be somewhat more serious, but this would
+ * likely be noticed by an administrator, who could fix the problem and
+ * retry the operation.
+ */
+
+#define free_dbsuffix(name) free(name)
+
+/*
+ * Routines to deal with context.
+ */
+#define	k5db2_inited(c)	(c && c->db_context \
+			 && ((kdb5_dal_handle*)c->db_context)->db_context \
+                         && ((krb5_db2_context *) ((kdb5_dal_handle*)c->db_context)->db_context)->db_inited)
+
+static krb5_error_code
+krb5_db2_get_db_opt(char *input, char **opt, char **val)
+{
+    char   *pos = strchr(input, '=');
+    if (pos == NULL) {
+	*opt = NULL;
+	*val = strdup(input);
+	if (*val == NULL) {
+	    return ENOMEM;
+	}
+    } else {
+	*opt = malloc((pos - input) + 1);
+	*val = strdup(pos + 1);
+	if (!*opt || !*val) {
+	    return ENOMEM;
+	}
+	memcpy(*opt, input, pos - input);
+	(*opt)[pos - input] = '\0';
+    }
+    return (0);
+
+}
+
+/*
+ * Restore the default context.
+ */
+static void
+k5db2_clear_context(krb5_db2_context *dbctx)
+{
+    /*
+     * Free any dynamically allocated memory.  File descriptors and locks
+     * are the caller's problem.
+     */
+    if (dbctx->db_lf_name)
+	free(dbctx->db_lf_name);
+    if (dbctx->db_name && (dbctx->db_name != default_db_name))
+	free(dbctx->db_name);
+    /*
+     * Clear the structure and reset the defaults.
+     */
+    memset((char *) dbctx, 0, sizeof(krb5_db2_context));
+    dbctx->db_name = default_db_name;
+    dbctx->db_nb_locks = FALSE;
+    dbctx->tempdb = FALSE;
+}
+
+static krb5_error_code
+k5db2_init_context(krb5_context context)
+{
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+
+    if (dal_handle->db_context == NULL) {
+	db_ctx = (krb5_db2_context *) malloc(sizeof(krb5_db2_context));
+	if (db_ctx == NULL)
+	    return ENOMEM;
+	else {
+	    memset((char *) db_ctx, 0, sizeof(krb5_db2_context));
+	    k5db2_clear_context((krb5_db2_context *) db_ctx);
+	    dal_handle->db_context = (void *) db_ctx;
+	}
+    }
+    return (0);
+}
+
+/*
+ * Utility routine: generate name of database file.
+ */
+
+static char *
+gen_dbsuffix(char *db_name, char *sfx)
+{
+    char   *dbsuffix;
+
+    if (sfx == NULL)
+	return ((char *) NULL);
+
+    dbsuffix = malloc(strlen(db_name) + strlen(sfx) + 1);
+    if (!dbsuffix)
+	return (0);
+    (void) strcpy(dbsuffix, db_name);
+    (void) strcat(dbsuffix, sfx);
+    return dbsuffix;
+}
+
+static DB *
+k5db2_dbopen(krb5_db2_context *dbc, char *fname, int flags, int mode, int tempdb)
+{
+    DB     *db;
+    BTREEINFO bti;
+    HASHINFO hashi;
+    bti.flags = 0;
+    bti.cachesize = 0;
+    bti.psize = 4096;
+    bti.lorder = 0;
+    bti.minkeypage = 0;
+    bti.compare = NULL;
+    bti.prefix = NULL;
+
+    if (tempdb) {
+	fname = gen_dbsuffix(fname, "~");
+    } else {
+	fname = strdup(fname);
+    }
+    if (fname == NULL)
+    {
+	errno = ENOMEM;
+	return NULL;
+    }
+    
+
+    hashi.bsize = 4096;
+    hashi.cachesize = 0;
+    hashi.ffactor = 40;
+    hashi.hash = NULL;
+    hashi.lorder = 0;
+    hashi.nelem = 1;
+
+    db = dbopen(fname, flags, mode,
+		dbc->hashfirst ? DB_HASH : DB_BTREE,
+		dbc->hashfirst ? (void *) &hashi : (void *) &bti);
+    if (db != NULL) {
+	free(fname);
+	return db;
+    }
+    switch (errno) {
+#ifdef EFTYPE
+    case EFTYPE:
+#endif
+    case EINVAL:
+	db = dbopen(fname, flags, mode,
+		    dbc->hashfirst ? DB_BTREE : DB_HASH,
+		    dbc->hashfirst ? (void *) &bti : (void *) &hashi);
+	if (db != NULL)
+	    dbc->hashfirst = !dbc->hashfirst;
+    default:
+	free(fname);
+	return db;
+    }
+}
+
+static krb5_error_code
+krb5_db2_db_set_hashfirst(krb5_context context, int hashfirst)
+{
+    krb5_db2_context *dbc;
+    kdb5_dal_handle *dal_handle;
+
+    if (k5db2_inited(context))
+	return KRB5_KDB_DBNOTINITED;
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    dbc = (krb5_db2_context *) dal_handle->db_context;
+    dbc->hashfirst = hashfirst;
+    return 0;
+}
+
+/*
+ * initialization for data base routines.
+ */
+
+krb5_error_code
+krb5_db2_db_init(krb5_context context)
+{
+    char   *filename = NULL;
+    krb5_db2_context *db_ctx;
+    krb5_error_code retval;
+    kdb5_dal_handle *dal_handle;
+    char    policy_db_name[1024], policy_lock_name[1024];
+
+    if (k5db2_inited(context))
+	return 0;
+
+    /* Check for presence of our context, if not present, allocate one. */
+    if ((retval = k5db2_init_context(context)))
+	return (retval);
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = dal_handle->db_context;
+    db_ctx->db = NULL;
+
+    if (!(filename = gen_dbsuffix(db_ctx->db_name, db_ctx->tempdb
+				  ?KDB2_TEMP_LOCK_EXT:KDB2_LOCK_EXT)))
+	return ENOMEM;
+    db_ctx->db_lf_name = filename;	/* so it gets freed by clear_context */
+
+    /*
+     * should be opened read/write so that write locking can work with
+     * POSIX systems
+     */
+    if ((db_ctx->db_lf_file = open(filename, O_RDWR, 0666)) < 0) {
+	if ((db_ctx->db_lf_file = open(filename, O_RDONLY, 0666)) < 0) {
+	    retval = errno;
+	    goto err_out;
+	}
+    }
+    db_ctx->db_inited++;
+
+    if ((retval = krb5_db2_db_get_age(context, NULL, &db_ctx->db_lf_time)))
+	goto err_out;
+
+    sprintf(policy_db_name, db_ctx->tempdb ? "%s~.kadm5" : "%s.kadm5",
+	    db_ctx->db_name);
+    sprintf(policy_lock_name, "%s.lock", policy_db_name);
+
+    if ((retval = osa_adb_init_db(&db_ctx->policy_db, policy_db_name,
+				  policy_lock_name, OSA_ADB_POLICY_DB_MAGIC)))
+    {
+	goto err_out;
+    }
+    return 0;
+
+  err_out:
+    db_ctx->db = NULL;
+    k5db2_clear_context(db_ctx);
+    return (retval);
+}
+
+/*
+ * gracefully shut down database--must be called by ANY program that does
+ * a krb5_db2_db_init
+ */
+krb5_error_code
+krb5_db2_db_fini(krb5_context context)
+{
+    krb5_error_code retval = 0;
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    if (dal_handle == NULL) {
+	return 0;
+    }
+
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+    if (k5db2_inited(context)) {
+	if (close(db_ctx->db_lf_file))
+	    retval = errno;
+	else
+	    retval = 0;
+    }
+    if (db_ctx) {
+	if (db_ctx->policy_db) {
+	    retval =
+		osa_adb_fini_db(db_ctx->policy_db, OSA_ADB_POLICY_DB_MAGIC);
+	    if (retval)
+		return retval;
+	}
+
+	k5db2_clear_context(db_ctx);
+	/*      free(dal_handle->db_context); */
+	dal_handle->db_context = NULL;
+    }
+    return retval;
+}
+
+/*
+ * Set/Get the master key associated with the database
+ */
+krb5_error_code
+krb5_db2_db_set_mkey(krb5_context context, krb5_keyblock *key)
+{
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+
+    if (!k5db2_inited(context))
+	return (KRB5_KDB_DBNOTINITED);
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = dal_handle->db_context;
+    db_ctx->db_master_key = key;
+    return 0;
+}
+
+krb5_error_code
+krb5_db2_db_get_mkey(krb5_context context, krb5_keyblock **key)
+{
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+
+    if (!k5db2_inited(context))
+	return (KRB5_KDB_DBNOTINITED);
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = dal_handle->db_context;
+    *key = db_ctx->db_master_key;
+
+    return 0;
+}
+
+/*
+ * Set the "name" of the current database to some alternate value.
+ *
+ * Passing a null pointer as "name" will set back to the default.
+ * If the alternate database doesn't exist, nothing is changed.
+ *
+ * XXX rethink this
+ */
+
+static krb5_error_code
+krb5_db2_db_set_name(krb5_context context, char *name, int tempdb)
+{
+    DB     *db;
+    krb5_db2_context *db_ctx;
+    krb5_error_code kret;
+    kdb5_dal_handle *dal_handle;
+
+    if (k5db2_inited(context))
+	return KRB5_KDB_DBINITED;
+
+    /* Check for presence of our context, if not present, allocate one. */
+    if ((kret = k5db2_init_context(context)))
+	return (kret);
+
+    if (name == NULL)
+	name = default_db_name;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = dal_handle->db_context;
+    db_ctx->tempdb = tempdb;
+    db = k5db2_dbopen(db_ctx, name, O_RDONLY, 0, tempdb);
+    if (db == NULL)
+	return errno;
+
+    db_ctx->db_name = strdup(name);
+    (*db->close) (db);
+    return 0;
+}
+
+/*
+ * Return the last modification time of the database.
+ *
+ * Think about using fstat.
+ */
+
+krb5_error_code
+krb5_db2_db_get_age(krb5_context context, char *db_name, time_t *age)
+{
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+    struct stat st;
+
+    if (!k5db2_inited(context))
+	return (KRB5_KDB_DBNOTINITED);
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+    if (fstat(db_ctx->db_lf_file, &st) < 0)
+	*age = -1;
+    else
+	*age = st.st_mtime;
+    return 0;
+}
+
+/*
+ * Remove the semaphore file; indicates that database is currently
+ * under renovation.
+ *
+ * This is only for use when moving the database out from underneath
+ * the server (for example, during slave updates).
+ */
+
+static krb5_error_code
+krb5_db2_db_start_update(krb5_context context)
+{
+    return 0;
+}
+
+static krb5_error_code
+krb5_db2_db_end_update(krb5_context context)
+{
+    krb5_error_code retval;
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+    struct stat st;
+    time_t  now;
+    struct utimbuf utbuf;
+
+    if (!k5db2_inited(context))
+	return (KRB5_KDB_DBNOTINITED);
+
+    retval = 0;
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = dal_handle->db_context;
+    now = time((time_t *) NULL);
+    if (fstat(db_ctx->db_lf_file, &st) == 0) {
+	if (st.st_mtime >= now) {
+	    utbuf.actime = st.st_mtime + 1;
+	    utbuf.modtime = st.st_mtime + 1;
+	    if (utime(db_ctx->db_lf_name, &utbuf))
+		retval = errno;
+	} else {
+	    if (utime(db_ctx->db_lf_name, (struct utimbuf *) NULL))
+		retval = errno;
+	}
+    } else
+	retval = errno;
+    if (!retval) {
+	if (fstat(db_ctx->db_lf_file, &st) == 0)
+	    db_ctx->db_lf_time = st.st_mtime;
+	else
+	    retval = errno;
+    }
+    return (retval);
+}
+
+#define MAX_LOCK_TRIES 5
+
+krb5_error_code
+krb5_db2_db_lock(krb5_context context, int in_mode)
+{
+    krb5_db2_context *db_ctx;
+    int     krb5_lock_mode;
+    DB     *db;
+    krb5_error_code retval;
+    time_t  mod_time;
+    kdb5_dal_handle *dal_handle;
+    int     mode, gotlock, tries;
+
+    switch (in_mode) {
+    case KRB5_DB_LOCKMODE_PERMANENT:
+	mode = KRB5_DB_LOCKMODE_EXCLUSIVE;
+	break;
+    case KRB5_DB_LOCKMODE_EXCLUSIVE:
+	mode = KRB5_LOCKMODE_EXCLUSIVE;
+	break;
+
+    case KRB5_DB_LOCKMODE_SHARED:
+	mode = KRB5_LOCKMODE_SHARED;
+	break;
+    default:
+	return EINVAL;
+    }
+
+    if (!k5db2_inited(context))
+	return KRB5_KDB_DBNOTINITED;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+    if (db_ctx->db_locks_held && (db_ctx->db_lock_mode >= mode)) {
+	/* No need to upgrade lock, just return */
+	db_ctx->db_locks_held++;
+	goto policy_lock;
+    }
+
+    if ((mode != KRB5_LOCKMODE_SHARED) && (mode != KRB5_LOCKMODE_EXCLUSIVE))
+	return KRB5_KDB_BADLOCKMODE;
+
+    krb5_lock_mode = mode | KRB5_LOCKMODE_DONTBLOCK;
+    for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
+	retval = krb5_lock_file(context, db_ctx->db_lf_file, krb5_lock_mode);
+	if (retval == 0) {
+	    gotlock++;
+	    break;
+	} else if (retval == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
+	    /* tried to exclusive-lock something we don't have */
+	    /* write access to */
+	    return KRB5_KDB_CANTLOCK_DB;
+	sleep(1);
+    }
+    if (retval == EACCES)
+	return KRB5_KDB_CANTLOCK_DB;
+    else if (retval == EAGAIN || retval == EWOULDBLOCK)
+	return OSA_ADB_CANTLOCK_DB;
+    else if (retval != 0)
+	return retval;
+
+    if ((retval = krb5_db2_db_get_age(context, NULL, &mod_time)))
+	goto lock_error;
+
+    db = k5db2_dbopen(db_ctx, db_ctx->db_name,
+		      mode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR, 0600, db_ctx->tempdb);
+    if (db) {
+	db_ctx->db_lf_time = mod_time;
+	db_ctx->db = db;
+    } else {
+	retval = errno;
+	db_ctx->db = NULL;
+	goto lock_error;
+    }
+
+    db_ctx->db_lock_mode = mode;
+    db_ctx->db_locks_held++;
+
+  policy_lock:
+    if ((retval = osa_adb_get_lock(db_ctx->policy_db, in_mode))) {
+	krb5_db2_db_unlock(context);
+    }
+    return retval;
+
+  lock_error:;
+    db_ctx->db_lock_mode = 0;
+    db_ctx->db_locks_held = 0;
+    krb5_db2_db_unlock(context);
+    return retval;
+}
+
+krb5_error_code
+krb5_db2_db_unlock(krb5_context context)
+{
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+    DB     *db;
+    krb5_error_code retval;
+
+    if (!k5db2_inited(context))
+	return KRB5_KDB_DBNOTINITED;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+    if ((retval = osa_adb_release_lock(db_ctx->policy_db))) {
+	return retval;
+    }
+
+    if (!db_ctx->db_locks_held)	/* lock already unlocked */
+	return KRB5_KDB_NOTLOCKED;
+    db = db_ctx->db;
+    if (--(db_ctx->db_locks_held) == 0) {
+	(*db->close) (db);
+	db_ctx->db = NULL;
+
+	retval = krb5_lock_file(context, db_ctx->db_lf_file,
+				KRB5_LOCKMODE_UNLOCK);
+	db_ctx->db_lock_mode = 0;
+	return (retval);
+    }
+    return 0;
+}
+
+/*
+ * Create the database, assuming it's not there.
+ */
+krb5_error_code
+krb5_db2_db_create(krb5_context context, char *db_name, krb5_int32 flags)
+{
+    register krb5_error_code retval = 0;
+    kdb5_dal_handle *dal_handle;
+    char   *okname;
+    char   *db_name2 = NULL;
+    int     fd;
+    krb5_db2_context *db_ctx;
+    DB     *db;
+    char    policy_db_name[1024], policy_lock_name[1024];
+
+    if ((retval = k5db2_init_context(context)))
+	return (retval);
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+    switch (flags) {
+    case KRB5_KDB_CREATE_HASH:
+	if ((retval = krb5_db2_db_set_hashfirst(context, TRUE)))
+	    return retval;
+	break;
+    case KRB5_KDB_CREATE_BTREE:
+    case 0:
+	if ((retval = krb5_db2_db_set_hashfirst(context, FALSE)))
+	    return retval;
+	break;
+    default:
+	return KRB5_KDB_BAD_CREATEFLAGS;
+    }
+    db = k5db2_dbopen(db_ctx, db_name, O_RDWR | O_CREAT | O_EXCL, 0600, db_ctx->tempdb);
+    if (db == NULL)
+	return errno;
+    (*db->close) (db);
+
+    db_name2 = db_ctx->tempdb ? gen_dbsuffix(db_name, "~") : strdup(db_name);
+    if (db_name2 == NULL)
+	return ENOMEM;
+    okname = gen_dbsuffix(db_name2, KDB2_LOCK_EXT);
+    if (!okname)
+	retval = ENOMEM;
+    else {
+	fd = open(okname, O_CREAT | O_RDWR | O_TRUNC, 0600);
+	if (fd < 0)
+	    retval = errno;
+	else
+	    close(fd);
+	free_dbsuffix(okname);
+    }
+
+    sprintf(policy_db_name, "%s.kadm5", db_name2);
+    sprintf(policy_lock_name, "%s.lock", policy_db_name);
+
+    retval = osa_adb_create_db(policy_db_name,
+			       policy_lock_name, OSA_ADB_POLICY_DB_MAGIC);
+    free(db_name2);
+    return retval;
+}
+
+/*
+ * Destroy the database.  Zero's out all of the files, just to be sure.
+ */
+static krb5_error_code
+destroy_file_suffix(char *dbname, char *suffix)
+{
+    char   *filename;
+    struct stat statb;
+    int     nb, fd;
+    unsigned int j;
+    off_t   pos;
+    char    buf[BUFSIZ];
+    char    zbuf[BUFSIZ];
+    int     dowrite;
+
+    filename = gen_dbsuffix(dbname, suffix);
+    if (filename == 0)
+	return ENOMEM;
+    if ((fd = open(filename, O_RDWR, 0)) < 0) {
+	free(filename);
+	return errno;
+    }
+    /* fstat() will probably not fail unless using a remote filesystem
+     * (which is inappropriate for the kerberos database) so this check
+     * is mostly paranoia.  */
+    if (fstat(fd, &statb) == -1) {
+	int     retval = errno;
+	free(filename);
+	return retval;
+    }
+    /*
+     * Stroll through the file, reading in BUFSIZ chunks.  If everything
+     * is zero, then we're done for that block, otherwise, zero the block.
+     * We would like to just blast through everything, but some DB
+     * implementations make holey files and writing data to the holes
+     * causes actual blocks to be allocated which is no good, since
+     * we're just about to unlink it anyways.
+     */
+    memset(zbuf, 0, BUFSIZ);
+    pos = 0;
+    while (pos < statb.st_size) {
+	dowrite = 0;
+	nb = read(fd, buf, BUFSIZ);
+	if (nb < 0) {
+	    int     retval = errno;
+	    free(filename);
+	    return retval;
+	}
+	for (j = 0; j < nb; j++) {
+	    if (buf[j] != '\0') {
+		dowrite = 1;
+		break;
+	    }
+	}
+	/* For signedness */
+	j = nb;
+	if (dowrite) {
+	    lseek(fd, pos, SEEK_SET);
+	    nb = write(fd, zbuf, j);
+	    if (nb < 0) {
+		int     retval = errno;
+		free(filename);
+		return retval;
+	    }
+	}
+	pos += nb;
+    }
+    /* ??? Is fsync really needed?  I don't know of any non-networked
+     * filesystem which will discard queued writes to disk if a file
+     * is deleted after it is closed.  --jfc */
+#ifndef NOFSYNC
+    fsync(fd);
+#endif
+    close(fd);
+
+    if (unlink(filename)) {
+	free(filename);
+	return (errno);
+    }
+    free(filename);
+    return (0);
+}
+
+/*
+ * Since the destroy operation happens outside the init/fini bracket, we
+ * have some tomfoolery to undergo here.  If we're operating under no
+ * database context, then we initialize with the default.  If the caller
+ * wishes a different context (e.g. different dispatch table), it's their
+ * responsibility to call kdb5_db_set_dbops() before this call.  That will
+ * set up the right dispatch table values (e.g. name extensions).
+ *
+ * Not quite valid due to ripping out of dbops...
+ */
+krb5_error_code
+krb5_db2_db_destroy(krb5_context context, char *dbname)
+{
+    krb5_error_code retval1, retval2;
+    krb5_boolean tmpcontext;
+    char    policy_db_name[1024], policy_lock_name[1024];
+
+    tmpcontext = 0;
+    if (!context->db_context
+	|| !((kdb5_dal_handle *) context->db_context)->db_context) {
+	tmpcontext = 1;
+	if ((retval1 = k5db2_init_context(context)))
+	    return (retval1);
+    }
+
+    retval1 = retval2 = 0;
+    retval1 = destroy_file_suffix(dbname, "");
+    retval2 = destroy_file_suffix(dbname, KDB2_LOCK_EXT);
+
+    if (tmpcontext) {
+	k5db2_clear_context((krb5_db2_context *) ((kdb5_dal_handle *) context->
+						  db_context)->db_context);
+	free(((kdb5_dal_handle *) context->db_context)->db_context);
+	((kdb5_dal_handle *) context->db_context)->db_context = NULL;
+    }
+
+    if (retval1 || retval2)
+	return (retval1 ? retval1 : retval2);
+
+    sprintf(policy_db_name, "%s.kadm5", dbname);
+    sprintf(policy_lock_name, "%s.lock", policy_db_name);
+
+    retval1 = osa_adb_destroy_db(policy_db_name,
+				 policy_lock_name, OSA_ADB_POLICY_DB_MAGIC);
+
+    return retval1;
+}
+
+/*
+ * look up a principal in the data base.
+ * returns number of entries found, and whether there were
+ * more than requested.
+ */
+
+krb5_error_code
+krb5_db2_db_get_principal(krb5_context context,
+			  krb5_const_principal searchfor,
+			  krb5_db_entry *entries, /* filled in */
+			  int *nentries, /* how much room/how many found */
+			  krb5_boolean *more) /* are there more? */
+{
+    krb5_db2_context *db_ctx;
+    krb5_error_code retval;
+    DB     *db;
+    DBT     key, contents;
+    krb5_data keydata, contdata;
+    int     trynum, dbret;
+    kdb5_dal_handle *dal_handle;
+
+    *more = FALSE;
+    *nentries = 0;
+
+    if (!k5db2_inited(context))
+	return KRB5_KDB_DBNOTINITED;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+    for (trynum = 0; trynum < KRB5_DB2_MAX_RETRY; trynum++) {
+	if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_SHARED))) {
+	    if (db_ctx->db_nb_locks)
+		return (retval);
+	    sleep(1);
+	    continue;
+	}
+	break;
+    }
+    if (trynum == KRB5_DB2_MAX_RETRY)
+	return KRB5_KDB_DB_INUSE;
+
+    /* XXX deal with wildcard lookups */
+    retval = krb5_encode_princ_dbkey(context, &keydata, searchfor);
+    if (retval)
+	goto cleanup;
+    key.data = keydata.data;
+    key.size = keydata.length;
+
+    db = db_ctx->db;
+    dbret = (*db->get) (db, &key, &contents, 0);
+    retval = errno;
+    krb5_free_data_contents(context, &keydata);
+    switch (dbret) {
+    case 1:
+	retval = 0;
+    case -1:
+    default:
+	*nentries = 0;
+	goto cleanup;
+    case 0:
+	contdata.data = contents.data;
+	contdata.length = contents.size;
+	retval = krb5_decode_princ_contents(context, &contdata, entries);
+	if (!retval)
+	    *nentries = 1;
+	break;
+    }
+
+  cleanup:
+    (void) krb5_db2_db_unlock(context);	/* unlock read lock */
+    return retval;
+}
+
+/*
+  Free stuff returned by krb5_db2_db_get_principal.
+ */
+krb5_error_code
+krb5_db2_db_free_principal(krb5_context context, krb5_db_entry *entries,
+			   int nentries)
+{
+    register int i;
+    for (i = 0; i < nentries; i++)
+	krb5_dbe_free_contents(context, &entries[i]);
+    return 0;
+}
+
+/*
+  Stores the *"nentries" entry structures pointed to by "entries" in the
+  database.
+
+  *"nentries" is updated upon return to reflect the number of records
+  acutally stored; the first *"nstored" records will have been stored in the
+  database (even if an error occurs).
+
+ */
+
+krb5_error_code
+krb5_db2_db_put_principal(krb5_context context,
+			  krb5_db_entry *entries,
+			  int *nentries, /* number of entry structs to update */
+			  char **db_args)
+{
+    int     i, n, dbret;
+    DB     *db;
+    DBT     key, contents;
+    krb5_data contdata, keydata;
+    krb5_error_code retval;
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+
+    krb5_clear_error_message (context);
+    if (db_args) {
+	/* DB2 does not support db_args DB arguments for principal */
+	krb5_set_error_message(context, EINVAL,
+			       "Unsupported argument \"%s\" for db2",
+			       db_args[0]);
+	return EINVAL;
+    }
+
+    n = *nentries;
+    *nentries = 0;
+    if (!k5db2_inited(context))
+	return KRB5_KDB_DBNOTINITED;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+    if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
+	return retval;
+
+    db = db_ctx->db;
+    if ((retval = krb5_db2_db_start_update(context))) {
+	(void) krb5_db2_db_unlock(context);
+	return retval;
+    }
+
+    /* for each one, stuff temps, and do replace/append */
+    for (i = 0; i < n; i++) {
+	retval = krb5_encode_princ_contents(context, &contdata, entries);
+	if (retval)
+	    break;
+	contents.data = contdata.data;
+	contents.size = contdata.length;
+	retval = krb5_encode_princ_dbkey(context, &keydata, entries->princ);
+	if (retval) {
+	    krb5_free_data_contents(context, &contdata);
+	    break;
+	}
+
+	key.data = keydata.data;
+	key.size = keydata.length;
+	dbret = (*db->put) (db, &key, &contents, 0);
+	retval = dbret ? errno : 0;
+	krb5_free_data_contents(context, &keydata);
+	krb5_free_data_contents(context, &contdata);
+	if (retval)
+	    break;
+	entries++;		/* bump to next struct */
+    }
+
+    (void) krb5_db2_db_end_update(context);
+    (void) krb5_db2_db_unlock(context);	/* unlock database */
+    *nentries = i;
+    return (retval);
+}
+
+/*
+ * delete a principal from the data base.
+ * returns number of entries removed
+ */
+
+krb5_error_code
+krb5_db2_db_delete_principal(krb5_context context,
+			     krb5_const_principal searchfor,
+			     int *nentries) /* how many found & deleted */
+{
+    krb5_error_code retval;
+    krb5_db_entry entry;
+    krb5_db2_context *db_ctx;
+    DB     *db;
+    DBT     key, contents;
+    krb5_data keydata, contdata;
+    int     i, dbret;
+    kdb5_dal_handle *dal_handle;
+
+    if (!k5db2_inited(context))
+	return KRB5_KDB_DBNOTINITED;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+    if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
+	return (retval);
+
+    if ((retval = krb5_db2_db_start_update(context))) {
+	(void) krb5_db2_db_unlock(context);	/* unlock write lock */
+	return (retval);
+    }
+
+    if ((retval = krb5_encode_princ_dbkey(context, &keydata, searchfor)))
+	goto cleanup;
+    key.data = keydata.data;
+    key.size = keydata.length;
+
+    db = db_ctx->db;
+    dbret = (*db->get) (db, &key, &contents, 0);
+    retval = errno;
+    switch (dbret) {
+    case 1:
+	retval = KRB5_KDB_NOENTRY;
+    case -1:
+    default:
+	*nentries = 0;
+	goto cleankey;
+    case 0:
+	;
+    }
+    memset((char *) &entry, 0, sizeof(entry));
+    contdata.data = contents.data;
+    contdata.length = contents.size;
+    retval = krb5_decode_princ_contents(context, &contdata, &entry);
+    if (retval)
+	goto cleankey;
+    *nentries = 1;
+
+    /* Clear encrypted key contents */
+    for (i = 0; i < entry.n_key_data; i++) {
+	if (entry.key_data[i].key_data_length[0]) {
+	    memset((char *) entry.key_data[i].key_data_contents[0], 0,
+		   (unsigned) entry.key_data[i].key_data_length[0]);
+	}
+    }
+
+    retval = krb5_encode_princ_contents(context, &contdata, &entry);
+    krb5_dbe_free_contents(context, &entry);
+    if (retval)
+	goto cleankey;
+
+    contents.data = contdata.data;
+    contents.size = contdata.length;
+    dbret = (*db->put) (db, &key, &contents, 0);
+    retval = dbret ? errno : 0;
+    krb5_free_data_contents(context, &contdata);
+    if (retval)
+	goto cleankey;
+    dbret = (*db->del) (db, &key, 0);
+    retval = dbret ? errno : 0;
+  cleankey:
+    krb5_free_data_contents(context, &keydata);
+
+  cleanup:
+    (void) krb5_db2_db_end_update(context);
+    (void) krb5_db2_db_unlock(context);	/* unlock write lock */
+    return retval;
+}
+
+krb5_error_code
+krb5_db2_db_iterate_ext(krb5_context context,
+			krb5_error_code(*func) (krb5_pointer, krb5_db_entry *),
+			krb5_pointer func_arg,
+			int backwards, int recursive)
+{
+    krb5_db2_context *db_ctx;
+    DB     *db;
+    DBT     key, contents;
+    krb5_data contdata;
+    krb5_db_entry entries;
+    krb5_error_code retval;
+    kdb5_dal_handle *dal_handle;
+    int     dbret;
+    void   *cookie;
+
+    cookie = NULL;
+    if (!k5db2_inited(context))
+	return KRB5_KDB_DBNOTINITED;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+    retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_SHARED);
+
+    if (retval)
+	return retval;
+
+    db = db_ctx->db;
+    if (recursive && db->type != DB_BTREE) {
+	(void) krb5_db2_db_unlock(context);
+	return KRB5_KDB_UK_RERROR;	/* Not optimal, but close enough. */
+    }
+
+    if (!recursive) {
+	dbret = (*db->seq) (db, &key, &contents, backwards ? R_LAST : R_FIRST);
+    } else {
+#ifdef HAVE_BT_RSEQ
+	dbret = bt_rseq(db, &key, &contents, &cookie,
+			backwards ? R_LAST : R_FIRST);
+#else
+	(void) krb5_db2_db_unlock(context);
+	return KRB5_KDB_UK_RERROR;	/* Not optimal, but close enough. */
+#endif
+    }
+    while (dbret == 0) {
+	contdata.data = contents.data;
+	contdata.length = contents.size;
+	retval = krb5_decode_princ_contents(context, &contdata, &entries);
+	if (retval)
+	    break;
+	retval = (*func) (func_arg, &entries);
+	krb5_dbe_free_contents(context, &entries);
+	if (retval)
+	    break;
+	if (!recursive) {
+	    dbret = (*db->seq) (db, &key, &contents,
+				backwards ? R_PREV : R_NEXT);
+	} else {
+#ifdef HAVE_BT_RSEQ
+	    dbret = bt_rseq(db, &key, &contents, &cookie,
+			    backwards ? R_PREV : R_NEXT);
+#else
+	    (void) krb5_db2_db_unlock(context);
+	    return KRB5_KDB_UK_RERROR;	/* Not optimal, but close enough. */
+#endif
+	}
+    }
+    switch (dbret) {
+    case 1:
+    case 0:
+	break;
+    case -1:
+    default:
+	retval = errno;
+    }
+    (void) krb5_db2_db_unlock(context);
+    return retval;
+}
+
+krb5_error_code
+krb5_db2_db_iterate(krb5_context context,
+		    char *match_expr,
+		    krb5_error_code(*func) (krb5_pointer, krb5_db_entry *),
+		    krb5_pointer func_arg)
+{
+    return krb5_db2_db_iterate_ext(context, func, func_arg, 0, 0);
+}
+
+krb5_boolean
+krb5_db2_db_set_lockmode(krb5_context context, krb5_boolean mode)
+{
+    krb5_boolean old;
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    old = mode;
+    if (dal_handle && (db_ctx = (krb5_db2_context *) dal_handle->db_context)) {
+	old = db_ctx->db_nb_locks;
+	db_ctx->db_nb_locks = mode;
+    }
+    return old;
+}
+
+/*
+ *     DAL API functions
+ */
+krb5_error_code
+krb5_db2_lib_init()
+{
+    return 0;
+}
+
+krb5_error_code
+krb5_db2_lib_cleanup()
+{
+    /* right now, no cleanup required */
+    return 0;
+}
+
+krb5_error_code
+krb5_db2_open(krb5_context kcontext,
+	      char *conf_section, char **db_args, int mode)
+{
+    krb5_error_code status = 0;
+    char  **t_ptr = db_args;
+    int     db_name_set = 0, tempdb=0;
+    char *dbname = NULL;
+
+    krb5_clear_error_message (kcontext);
+
+    if (k5db2_inited(kcontext))
+	return 0;
+
+    while (t_ptr && *t_ptr) {
+	char   *opt = NULL, *val = NULL;
+
+	krb5_db2_get_db_opt(*t_ptr, &opt, &val);
+	if (opt && !strcmp(opt, "dbname")) {
+	    if (dbname) free(dbname);
+	    dbname = strdup(val);
+	}
+	else if (!opt && !strcmp(val, "temporary") ) {
+	    tempdb = 1;
+	}
+	/* ignore hash argument. Might have been passed from create */
+	else if (!opt || strcmp(opt, "hash")) {
+	    krb5_set_error_message(kcontext, EINVAL,
+				   "Unsupported argument \"%s\" for db2",
+				   opt ? opt : val);
+	    free(opt);
+	    free(val);
+	    return EINVAL;
+	}
+
+	free(opt);
+	free(val);
+	t_ptr++;
+    }
+
+    if(dbname) {
+	status = krb5_db2_db_set_name(kcontext, dbname, tempdb);
+	free(dbname);
+	if (status) {
+	    goto clean_n_exit;
+	}
+	db_name_set = 1;
+    }
+    if (!db_name_set) {
+	char   *value = NULL;
+	status = profile_get_string(KRB5_DB_GET_PROFILE(kcontext), KDB_MODULE_SECTION, conf_section, KDB_DB2_DATABASE_NAME,	/* under given conf section */
+				    NULL, &value);
+
+	if (value == NULL) {
+	    /* special case for db2. We might actually be looking at old type config file where database is specified as part of realm */
+	    status = profile_get_string(KRB5_DB_GET_PROFILE(kcontext), KDB_REALM_SECTION, KRB5_DB_GET_REALM(kcontext), KDB_DB2_DATABASE_NAME,	/* under given realm */
+					default_db_name, &value);
+	    if (status) {
+		goto clean_n_exit;
+	    }
+	}
+
+	status = krb5_db2_db_set_name(kcontext, value, tempdb);
+	profile_release_string(value);
+	if (status) {
+	    goto clean_n_exit;
+	}
+
+    }
+
+    status = krb5_db2_db_init(kcontext);
+
+  clean_n_exit:
+    return status;
+}
+
+krb5_error_code
+krb5_db2_create(krb5_context kcontext, char *conf_section, char **db_args)
+{
+    krb5_error_code status = 0;
+    char  **t_ptr = db_args;
+    int     db_name_set = 0, tempdb=0;
+    krb5_int32 flags = KRB5_KDB_CREATE_BTREE;
+    char   *db_name = NULL;
+
+    krb5_clear_error_message (kcontext);
+
+    if (k5db2_inited(kcontext))
+	return 0;
+
+    while (t_ptr && *t_ptr) {
+	char   *opt = NULL, *val = NULL;
+
+	krb5_db2_get_db_opt(*t_ptr, &opt, &val);
+	if (opt && !strcmp(opt, "dbname")) {
+	    db_name = strdup(val);
+	}
+	else if (!opt && !strcmp(val, "temporary")) {
+	    tempdb = 1;
+	}
+	else if (opt && !strcmp(opt, "hash")) {
+	    flags = KRB5_KDB_CREATE_HASH;
+	} else {
+	    krb5_set_error_message(kcontext, EINVAL,
+				   "Unsupported argument \"%s\" for db2",
+				   opt ? opt : val);
+	    free(opt);
+	    free(val);
+	    return EINVAL;
+	}
+
+	free(opt);
+	free(val);
+	t_ptr++;
+    }
+    if (db_name) {
+	    status = krb5_db2_db_set_name(kcontext, db_name, tempdb);
+	    if (!status) {
+		status = EEXIST;
+		goto clean_n_exit;
+	    }
+	    db_name_set = 1;
+    }
+    if (!db_name_set) {
+	char   *value = NULL;
+	status = profile_get_string(KRB5_DB_GET_PROFILE(kcontext),
+				    KDB_MODULE_SECTION, conf_section,
+				    /* under given conf section */
+				    KDB_DB2_DATABASE_NAME, NULL, &value);
+
+	if (value == NULL) {
+	    /* Special case for db2.  We might actually be looking at
+	     * old type config file where database is specified as
+	     * part of realm.  */
+	    status = profile_get_string(KRB5_DB_GET_PROFILE(kcontext),
+					KDB_REALM_SECTION,
+					KRB5_DB_GET_REALM(kcontext),
+					/* under given realm */
+					KDB_DB2_DATABASE_NAME,
+					default_db_name, &value);
+	    if (status) {
+		goto clean_n_exit;
+	    }
+	}
+
+	db_name = strdup(value);
+	status = krb5_db2_db_set_name(kcontext, value, tempdb);
+	profile_release_string(value);
+	if (!status) {
+	    status = EEXIST;
+	    goto clean_n_exit;
+	}
+
+    }
+
+    status = krb5_db2_db_create(kcontext, db_name, flags);
+    if (status)
+	goto clean_n_exit;
+    /* db2 has a problem of needing to close and open the database again. This removes that need */
+    status = krb5_db2_db_fini(kcontext);
+    if (status)
+	goto clean_n_exit;
+
+    status = krb5_db2_open(kcontext, conf_section, db_args, KRB5_KDB_OPEN_RW);
+
+  clean_n_exit:
+    if (db_name)
+	free(db_name);
+    return status;
+}
+
+krb5_error_code
+krb5_db2_destroy(krb5_context kcontext, char *conf_section, char **db_args)
+{
+    krb5_error_code status = 0;
+    char  **t_ptr = db_args;
+    int     db_name_set = 0, tempdb=0;
+    char   *db_name = NULL;
+
+    while (t_ptr && *t_ptr) {
+	char   *opt = NULL, *val = NULL;
+
+	krb5_db2_get_db_opt(*t_ptr, &opt, &val);
+	if (opt && !strcmp(opt, "dbname")) {
+	    db_name = strdup(val);
+	}
+	else if (!opt && !strcmp(val, "temporary")) {
+	    tempdb = 1;
+	}
+	/* ignore hash argument. Might have been passed from create */
+	else if (!opt || strcmp(opt, "hash")) {
+	    free(opt);
+	    free(val);
+	    return EINVAL;
+	}
+
+	free(opt);
+	free(val);
+	t_ptr++;
+    }
+
+    if (db_name) {
+	status = krb5_db2_db_set_name(kcontext, db_name, tempdb);
+	if (status) {
+	    goto clean_n_exit;
+	}
+	db_name_set = 1;
+    }
+    if (!db_name_set) {
+	char   *value = NULL;
+	status = profile_get_string(KRB5_DB_GET_PROFILE(kcontext), KDB_MODULE_SECTION, conf_section, KDB_DB2_DATABASE_NAME,	/* under given conf section */
+				    NULL, &value);
+
+	if (value == NULL) {
+	    /* special case for db2. We might actually be looking at old type config file where database is specified as part of realm */
+	    status = profile_get_string(KRB5_DB_GET_PROFILE(kcontext), KDB_REALM_SECTION, KRB5_DB_GET_REALM(kcontext), KDB_DB2_DATABASE_NAME,	/* under given realm */
+					default_db_name, &value);
+	    if (status) {
+		goto clean_n_exit;
+	    }
+	}
+
+	db_name = strdup(value);
+	status = krb5_db2_db_set_name(kcontext, value, tempdb);
+	profile_release_string(value);
+	if (status) {
+	    goto clean_n_exit;
+	}
+
+    }
+
+    status = krb5_db2_db_destroy(kcontext, db_name);
+
+  clean_n_exit:
+    if (db_name)
+	free(db_name);
+    return status;
+}
+
+krb5_error_code
+krb5_db2_set_master_key_ext(krb5_context kcontext,
+			    char *pwd, krb5_keyblock * key)
+{
+    return krb5_db2_db_set_mkey(kcontext, key);
+}
+
+krb5_error_code
+krb5_db2_db_set_option(krb5_context kcontext, int option, void *value)
+{
+    krb5_error_code status = 0;
+    krb5_boolean oldval;
+    krb5_db2_context *db_ctx;
+    kdb5_dal_handle *dal_handle;
+
+        if (!k5db2_inited(kcontext))
+	return KRB5_KDB_DBNOTINITED;
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+
+    switch (option) {
+    case KRB5_KDB_OPT_SET_DB_NAME:
+	status = krb5_db2_db_set_name(kcontext, (char *) value, db_ctx->tempdb);
+	break;
+
+    case KRB5_KDB_OPT_SET_LOCK_MODE:
+	oldval = krb5_db2_db_set_lockmode(kcontext, *((krb5_boolean *) value));
+	*((krb5_boolean *) value) = oldval;
+	break;
+
+    default:
+	status = -1;		/* TBD */
+	break;
+    }
+
+    return status;
+}
+
+void   *
+krb5_db2_alloc(krb5_context kcontext, void *ptr, size_t size)
+{
+    return realloc(ptr, size);
+}
+
+void
+krb5_db2_free(krb5_context kcontext, void *ptr)
+{
+    free(ptr);
+}
+
+/* policy functions */
+krb5_error_code
+krb5_db2_create_policy(krb5_context kcontext, osa_policy_ent_t policy)
+{
+    kdb5_dal_handle *dal_handle;
+    krb5_db2_context *dbc;
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    dbc = (krb5_db2_context *) dal_handle->db_context;
+
+    return osa_adb_create_policy(dbc->policy_db, policy);
+}
+
+krb5_error_code
+krb5_db2_get_policy(krb5_context kcontext,
+		    char *name, osa_policy_ent_t * policy, int *cnt)
+{
+    kdb5_dal_handle *dal_handle;
+    krb5_db2_context *dbc;
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    dbc = (krb5_db2_context *) dal_handle->db_context;
+
+    return osa_adb_get_policy(dbc->policy_db, name, policy, cnt);
+}
+
+krb5_error_code
+krb5_db2_put_policy(krb5_context kcontext, osa_policy_ent_t policy)
+{
+    kdb5_dal_handle *dal_handle;
+    krb5_db2_context *dbc;
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    dbc = (krb5_db2_context *) dal_handle->db_context;
+
+    return osa_adb_put_policy(dbc->policy_db, policy);
+}
+
+krb5_error_code
+krb5_db2_iter_policy(krb5_context kcontext,
+		     char *match_entry,
+		     osa_adb_iter_policy_func func, void *data)
+{
+    kdb5_dal_handle *dal_handle;
+    krb5_db2_context *dbc;
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    dbc = (krb5_db2_context *) dal_handle->db_context;
+
+    return osa_adb_iter_policy(dbc->policy_db, func, data);
+}
+
+krb5_error_code
+krb5_db2_delete_policy(krb5_context kcontext, char *policy)
+{
+    kdb5_dal_handle *dal_handle;
+    krb5_db2_context *dbc;
+
+    dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+    dbc = (krb5_db2_context *) dal_handle->db_context;
+
+    return osa_adb_destroy_policy(dbc->policy_db, policy);
+}
+
+void
+krb5_db2_free_policy(krb5_context kcontext, osa_policy_ent_t entry)
+{
+    osa_free_policy_ent(entry);
+}
+
+
+/* */
+
+krb5_error_code
+krb5_db2_promote_db(krb5_context kcontext, char *conf_section, char **db_args)
+{
+    krb5_error_code status = 0;
+    char *db_name = NULL;
+    char *temp_db_name = NULL;
+
+    krb5_clear_error_message (kcontext);
+
+    {
+	kdb5_dal_handle *dal_handle = kcontext->db_context;
+	krb5_db2_context *db_ctx = dal_handle->db_context;
+	db_name = strdup(db_ctx->db_name);
+    }
+
+    assert(kcontext->db_context != NULL);
+    temp_db_name = gen_dbsuffix(db_name, "~");
+    if (temp_db_name == NULL) {
+	status = ENOMEM;
+	goto clean_n_exit;
+    }
+
+    status = krb5_db2_db_rename (kcontext, temp_db_name, db_name);
+    if (status)
+	goto clean_n_exit;
+
+clean_n_exit:
+    if (db_name)
+	free(db_name);
+    if (temp_db_name)
+	free(temp_db_name);
+    return status;
+}
+
+/* Retrieved from pre-DAL code base.  */
+/*
+ * "Atomically" rename the database in a way that locks out read
+ * access in the middle of the rename.
+ *
+ * Not perfect; if we crash in the middle of an update, we don't
+ * necessarily know to complete the transaction the rename, but...
+ *
+ * Since the rename operation happens outside the init/fini bracket, we
+ * have to go through the same stuff that we went through up in db_destroy.
+ */
+krb5_error_code
+krb5_db2_db_rename(context, from, to)
+    krb5_context context;
+    char *from;
+    char *to;
+{
+    DB *db;
+    char *fromok;
+    krb5_error_code retval;
+    krb5_db2_context *s_context, *db_ctx;
+    kdb5_dal_handle *dal_handle = context->db_context;
+
+    s_context = dal_handle->db_context;
+    dal_handle->db_context = NULL;
+    if ((retval = k5db2_init_context(context)))
+	return retval;
+    db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+    /*
+     * Create the database if it does not already exist; the
+     * files must exist because krb5_db2_db_lock, called below,
+     * will fail otherwise.
+     */
+    db = k5db2_dbopen(db_ctx, to, O_RDWR|O_CREAT, 0600, 0);
+    if (db == NULL) {
+	retval = errno;
+	goto errout;
+    }
+    else
+	(*db->close)(db);
+    /*
+     * Set the database to the target, so that other processes sharing
+     * the target will stop their activity, and notice the new database.
+     */
+    retval = krb5_db2_db_set_name(context, to, 0);
+    if (retval)
+	goto errout;
+
+    retval = krb5_db2_db_init(context);
+    if (retval)
+	goto errout;
+
+    {
+	/* Ugly brute force hack.
+
+	   Should be going through nice friendly helper routines for
+	   this, but it's a mess of jumbled so-called interfaces right
+	   now.  */
+	char    policy[2048], new_policy[2048];
+	assert (strlen(db_ctx->db_name) < 2000);
+	sprintf(policy, "%s.kadm5", db_ctx->db_name);
+	sprintf(new_policy, "%s~.kadm5", db_ctx->db_name);
+	if (0 != rename(new_policy, policy)) {
+	    retval = errno;
+	    goto errout;
+	}
+	strcat(new_policy, ".lock");
+	(void) unlink(new_policy);
+    }
+
+    db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, KDB2_LOCK_EXT);
+    if (db_ctx->db_lf_name == NULL) {
+	retval = ENOMEM;
+	goto errout;
+    }
+    db_ctx->db_lf_file = open(db_ctx->db_lf_name, O_RDWR|O_CREAT, 0600);
+    if (db_ctx->db_lf_file < 0) {
+	retval = errno;
+	goto errout;
+    }
+
+    db_ctx->db_inited = 1;
+
+    retval = krb5_db2_db_get_age(context, NULL, &db_ctx->db_lf_time);
+    if (retval)
+	goto errout;
+
+    fromok = gen_dbsuffix(from, KDB2_LOCK_EXT);
+    if (fromok == NULL) {
+	retval = ENOMEM;
+	goto errout;
+    }
+
+    if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
+	goto errfromok;
+
+    if ((retval = krb5_db2_db_start_update(context)))
+	goto errfromok;
+
+    if (rename(from, to)) {
+	retval = errno;
+	goto errfromok;
+    }
+    if (unlink(fromok)) {
+	retval = errno;
+	goto errfromok;
+    }
+    retval = krb5_db2_db_end_update(context);
+errfromok:
+    free_dbsuffix(fromok);
+errout:
+    if (dal_handle->db_context) {
+	if (db_ctx->db_lf_file >= 0) {
+	    krb5_db2_db_unlock(context);
+	    close(db_ctx->db_lf_file);
+	}
+	k5db2_clear_context((krb5_db2_context *) dal_handle->db_context);
+	free(dal_handle->db_context);
+    }
+
+    dal_handle->db_context = s_context;
+    (void) krb5_db2_db_unlock(context);	/* unlock saved context db */
+
+    return retval;
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/kdb_db2.h b/krb5-1-6/src/plugins/kdb/db2/kdb_db2.h
new file mode 100644
index 000000000..d6cb1e881
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/kdb_db2.h
@@ -0,0 +1,211 @@
+/*
+ * lib/kdb/kdb_db2.h
+ *
+ * Copyright 1997 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * KDC Database backend definitions for Berkely DB.
+ */
+#ifndef KRB5_KDB_DB2_H
+#define KRB5_KDB_DB2_H
+
+#include "policy_db.h"
+
+typedef struct _krb5_db2_context {
+    krb5_boolean        db_inited;      /* Context initialized          */
+    char *              db_name;        /* Name of database             */
+    DB *		db;		/* DB handle			*/
+    krb5_boolean	hashfirst;	/* Try hash database type first	*/
+    char *              db_lf_name;     /* Name of lock file            */
+    int                 db_lf_file;     /* File descriptor of lock file */
+    time_t              db_lf_time;     /* Time last updated            */
+    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_keyblock      *db_master_key;  /* Master key of database       */
+    osa_adb_policy_t    policy_db;
+    krb5_boolean tempdb;
+} krb5_db2_context;
+
+#define KRB5_DB2_MAX_RETRY 5
+
+#define KDB2_LOCK_EXT ".ok"
+#define KDB2_TEMP_LOCK_EXT "~.ok"
+
+krb5_error_code krb5_db2_db_init 
+	(krb5_context);
+krb5_error_code krb5_db2_db_fini 
+	(krb5_context);
+krb5_error_code krb5_db2_db_get_age 
+	(krb5_context,
+		   char *,
+		   time_t * );
+krb5_error_code krb5_db2_db_create 
+	(krb5_context,
+		   char *,
+		   krb5_int32);
+krb5_error_code krb5_db2_db_destroy 
+	(krb5_context,
+		   char * );
+krb5_error_code krb5_db2_db_rename 
+	(krb5_context,
+		   char *,
+		   char * );
+krb5_error_code krb5_db2_db_get_principal 
+	(krb5_context,
+		   krb5_const_principal,
+		   krb5_db_entry *,
+		   int *,
+		   krb5_boolean * );
+krb5_error_code krb5_db2_db_free_principal 
+	(krb5_context,
+		   krb5_db_entry *,
+		   int );
+krb5_error_code krb5_db2_db_put_principal 
+	(krb5_context,
+	 krb5_db_entry *,
+	 int *,
+	 char **db_args
+	 );
+krb5_error_code krb5_db2_db_iterate_ext
+    	(krb5_context,
+		   krb5_error_code (*) (krb5_pointer,
+					          krb5_db_entry *),
+	           krb5_pointer, int, int );
+krb5_error_code krb5_db2_db_iterate
+(krb5_context,char *,
+		   krb5_error_code (*) (krb5_pointer,
+					          krb5_db_entry *),
+	           krb5_pointer );
+krb5_error_code krb5_db2_db_set_nonblocking 
+	(krb5_context,
+		   krb5_boolean,
+		   krb5_boolean * );
+krb5_boolean krb5_db2_db_set_lockmode
+	(krb5_context,
+		   krb5_boolean );
+krb5_error_code krb5_db2_db_open_database 
+	(krb5_context);
+krb5_error_code krb5_db2_db_close_database 
+	(krb5_context);
+
+krb5_error_code 
+krb5_db2_set_master_key_ext ( krb5_context kcontext, 
+			      char *pwd, 
+			      krb5_keyblock *key);
+
+krb5_error_code
+krb5_db2_db_set_mkey( krb5_context context,
+		      krb5_keyblock *key);
+
+krb5_error_code
+krb5_db2_db_get_mkey( krb5_context context,
+		      krb5_keyblock **key);
+
+krb5_error_code
+krb5_db2_db_put_principal( krb5_context context,
+			   krb5_db_entry *entries,
+			   register int *nentries,
+			   char **db_args);
+
+krb5_error_code
+krb5_db2_db_delete_principal(krb5_context context,
+			     krb5_const_principal searchfor,
+			     int *nentries);
+
+krb5_error_code krb5_db2_lib_init(void);
+
+krb5_error_code krb5_db2_lib_cleanup(void);
+
+krb5_error_code 
+krb5_db2_db_unlock(krb5_context);
+
+krb5_error_code
+krb5_db2_promote_db(krb5_context kcontext,
+		    char *conf_section,
+		    char **db_args);
+
+krb5_error_code 
+krb5_db2_db_set_option ( krb5_context kcontext, 
+			 int option, 
+			 void *value );
+
+krb5_error_code
+krb5_db2_db_lock( krb5_context 	  context,
+		  int 	 	  in_mode);
+
+
+krb5_error_code 
+krb5_db2_open( krb5_context kcontext,
+			       char *conf_section,
+			       char **db_args,
+			       int mode );
+
+krb5_error_code krb5_db2_create( krb5_context kcontext,
+				 char *conf_section,
+				 char **db_args );
+
+krb5_error_code krb5_db2_destroy( krb5_context kcontext,
+				  char *conf_section,
+				  char **db_args );
+
+const char * krb5_db2_err2str( krb5_context kcontext,
+			       long err_code );
+
+void * 
+krb5_db2_alloc( krb5_context kcontext,  
+		void *ptr, 
+		size_t size );
+
+void 
+krb5_db2_free( krb5_context kcontext, 
+		    void *ptr );
+
+
+
+
+
+/* policy management functions */
+krb5_error_code
+krb5_db2_create_policy(krb5_context context, osa_policy_ent_t entry);
+
+krb5_error_code krb5_db2_get_policy ( krb5_context kcontext,
+				      char *name,
+				      osa_policy_ent_t *policy,
+				      int *cnt);
+
+krb5_error_code krb5_db2_put_policy ( krb5_context kcontext,
+				      osa_policy_ent_t policy );
+
+krb5_error_code krb5_db2_iter_policy ( krb5_context kcontext,
+				       char *match_entry,
+				       osa_adb_iter_policy_func func,
+				       void *data );
+
+krb5_error_code krb5_db2_delete_policy ( krb5_context kcontext,
+					 char *policy );
+
+void krb5_db2_free_policy( krb5_context kcontext,
+			   osa_policy_ent_t entry );
+
+#endif /* KRB5_KDB_DB2_H */
diff --git a/krb5-1-6/src/plugins/kdb/db2/kdb_xdr.c b/krb5-1-6/src/plugins/kdb/db2/kdb_xdr.c
new file mode 100644
index 000000000..396350d76
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/kdb_xdr.c
@@ -0,0 +1,493 @@
+/*
+ * lib/kdb/kdb_xdr.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include "kdb_xdr.h"
+
+krb5_error_code
+krb5_encode_princ_dbkey(context, key, principal)
+    krb5_context context;
+    krb5_data  *key;
+    krb5_const_principal principal;
+{
+    char *princ_name;
+    krb5_error_code retval;
+
+    if (!(retval = krb5_unparse_name(context, principal, &princ_name))) {
+        /* need to store the NULL for decoding */
+        key->length = strlen(princ_name)+1;	
+        key->data = princ_name;
+    }
+    return(retval);
+}
+
+void
+krb5_free_princ_dbkey(context, key)
+    krb5_context context;
+    krb5_data  *key;
+{
+    (void) krb5_free_data_contents(context, key);
+}
+
+krb5_error_code
+krb5_encode_princ_contents(context, content, entry)
+    krb5_context 	  context;
+    krb5_data  		* content;
+    krb5_db_entry 	* entry;
+{
+    int 		  i, j;
+    unsigned int	  unparse_princ_size;
+    char 		* unparse_princ;
+    char		* nextloc;
+    krb5_tl_data	* tl_data;
+    krb5_error_code 	  retval;
+    krb5_int16		  psize16;
+
+    /*
+     * Generate one lump of data from the krb5_db_entry.
+     * This data must be independent of byte order of the machine,
+     * compact and extensible.
+     */
+
+    /* 
+     * First allocate enough space for all the data. 
+     * Need  2 bytes for the length of the base structure
+     * then 36 [ 8 * 4 + 2 * 2] bytes for the base information
+     *         [ attributes, max_life, max_renewable_life, expiration,
+     *	  	 pw_expiration, last_success, last_failed, fail_auth_count ]
+     *         [ n_key_data, n_tl_data ]
+     * then XX bytes [ e_length ] for the extra data [ e_data ]
+     * then XX bytes [ 2 for length + length for string ] for the principal,
+     * then (4 [type + length] + tl_data_length) bytes per tl_data
+     * then (4 + (4 + key_data_length) per key_data_contents) bytes per key_data
+     */
+    content->length = entry->len + entry->e_length;
+
+    if ((retval = krb5_unparse_name(context, entry->princ, &unparse_princ)))
+	return(retval);
+
+    unparse_princ_size = strlen(unparse_princ) + 1;
+    content->length += unparse_princ_size;
+    content->length += 2;		
+
+    i = 0;
+    /* tl_data is a linked list */
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
+	content->length += tl_data->tl_data_length;
+	content->length += 4; /* type, length */
+	i++;
+    }
+
+    if (i != entry->n_tl_data) {
+	retval = KRB5_KDB_TRUNCATED_RECORD;
+	goto epc_error;
+    }
+
+    /* key_data is an array */
+    for (i = 0; i < entry->n_key_data; i++) {
+	content->length += 4; /* Version, KVNO */
+	for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+	    content->length += entry->key_data[i].key_data_length[j];
+	    content->length += 4; /* type + length */
+	}
+    }
+	
+    if ((content->data = malloc(content->length)) == NULL) {
+	retval = ENOMEM;
+	goto epc_error;
+    }
+
+    /* 
+     * Now we go through entry again, this time copying data 
+     * These first entries are always saved regardless of version
+     */
+    nextloc = content->data;
+
+	/* Base Length */
+    krb5_kdb_encode_int16(entry->len, nextloc);
+    nextloc += 2;
+
+	/* Attributes */
+    krb5_kdb_encode_int32(entry->attributes, nextloc);
+    nextloc += 4;
+  
+	/* Max Life */
+    krb5_kdb_encode_int32(entry->max_life, nextloc);
+    nextloc += 4;
+  
+	/* Max Renewable Life */
+    krb5_kdb_encode_int32(entry->max_renewable_life, nextloc);
+    nextloc += 4;
+  
+	/* When the client expires */
+    krb5_kdb_encode_int32(entry->expiration, nextloc);
+    nextloc += 4;
+  
+	/* When its passwd expires */
+    krb5_kdb_encode_int32(entry->pw_expiration, nextloc);
+    nextloc += 4;
+  
+	/* Last successful passwd */
+    krb5_kdb_encode_int32(entry->last_success, nextloc);
+    nextloc += 4;
+  
+	/* Last failed passwd attempt */
+    krb5_kdb_encode_int32(entry->last_failed, nextloc);
+    nextloc += 4;
+  
+	/* # of failed passwd attempt */
+    krb5_kdb_encode_int32(entry->fail_auth_count, nextloc);
+    nextloc += 4;
+
+	/* # tl_data strutures */
+    krb5_kdb_encode_int16(entry->n_tl_data, nextloc);
+    nextloc += 2;
+  
+	/* # key_data strutures */
+    krb5_kdb_encode_int16(entry->n_key_data, nextloc);
+    nextloc += 2;
+  
+    	/* Put extended fields here */
+    if (entry->len != KRB5_KDB_V1_BASE_LENGTH)
+	abort();
+
+	/* Any extra data that this version doesn't understand. */
+    if (entry->e_length) {
+	memcpy(nextloc, entry->e_data, entry->e_length);
+	nextloc += entry->e_length;
+    }
+  
+	/* 
+	 * Now we get to the principal.
+	 * To squeze a few extra bytes out it is always assumed to come
+	 * after the base type.
+	 */
+    psize16 = (krb5_int16) unparse_princ_size;
+    krb5_kdb_encode_int16(psize16, nextloc);
+    nextloc += 2;
+    (void) memcpy(nextloc, unparse_princ, unparse_princ_size);
+    nextloc += unparse_princ_size;
+
+    	/* tl_data is a linked list, of type, legth, contents */
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
+	krb5_kdb_encode_int16(tl_data->tl_data_type, nextloc);
+	nextloc += 2;
+	krb5_kdb_encode_int16(tl_data->tl_data_length, nextloc);
+	nextloc += 2;
+
+	memcpy(nextloc, tl_data->tl_data_contents, tl_data->tl_data_length);
+	nextloc += tl_data->tl_data_length;
+    }
+
+    	/* key_data is an array */
+    for (i = 0; i < entry->n_key_data; i++) {
+	krb5_kdb_encode_int16(entry->key_data[i].key_data_ver, nextloc);
+	nextloc += 2;
+	krb5_kdb_encode_int16(entry->key_data[i].key_data_kvno, nextloc);
+	nextloc += 2;
+
+	for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+	    krb5_int16 type = entry->key_data[i].key_data_type[j];
+	    krb5_ui_2  length = entry->key_data[i].key_data_length[j];
+
+    	    krb5_kdb_encode_int16(type, nextloc);
+	    nextloc += 2;
+    	    krb5_kdb_encode_int16(length, nextloc);
+	    nextloc += 2;
+
+	    if (length) {
+	        memcpy(nextloc, entry->key_data[i].key_data_contents[j],length);
+	        nextloc += length;
+	    }
+	}
+    }
+	
+epc_error:;
+    free(unparse_princ);
+    return retval;
+}
+
+void
+krb5_free_princ_contents(context, contents)
+    krb5_context 	  context;
+    krb5_data *contents;
+{
+    krb5_free_data_contents(context, contents);
+    return;
+}
+
+krb5_error_code
+krb5_decode_princ_contents(context, content, entry)
+    krb5_context 	  context;
+    krb5_data  		* content;
+    krb5_db_entry 	* entry;
+{
+    int			  sizeleft, i;
+    char 		* nextloc;
+    krb5_tl_data       ** tl_data;
+    krb5_int16		  i16;
+
+    krb5_error_code retval;
+
+    /* Zero out entry and NULL pointers */
+    memset(entry, 0, sizeof(krb5_db_entry));
+
+    /*
+     * undo the effects of encode_princ_contents.
+     *
+     * The first part is decoding the base type. If the base type is
+     * bigger than the original base type then the additional fields
+     * need to be filled in. If the base type is larger than any
+     * known base type the additional data goes in e_data.
+     */
+
+    /* First do the easy stuff */
+    nextloc = content->data;
+    sizeleft = content->length;
+    if ((sizeleft -= KRB5_KDB_V1_BASE_LENGTH) < 0) 
+	return KRB5_KDB_TRUNCATED_RECORD;
+
+	/* Base Length */
+    krb5_kdb_decode_int16(nextloc, entry->len);
+    nextloc += 2;
+
+	/* Attributes */
+    krb5_kdb_decode_int32(nextloc, entry->attributes);
+    nextloc += 4;
+
+	/* Max Life */
+    krb5_kdb_decode_int32(nextloc, entry->max_life);
+    nextloc += 4;
+
+	/* Max Renewable Life */
+    krb5_kdb_decode_int32(nextloc, entry->max_renewable_life);
+    nextloc += 4;
+
+	/* When the client expires */
+    krb5_kdb_decode_int32(nextloc, entry->expiration);
+    nextloc += 4;
+
+	/* When its passwd expires */
+    krb5_kdb_decode_int32(nextloc, entry->pw_expiration);
+    nextloc += 4;
+
+	/* Last successful passwd */
+    krb5_kdb_decode_int32(nextloc, entry->last_success);
+    nextloc += 4;
+
+	/* Last failed passwd attempt */
+    krb5_kdb_decode_int32(nextloc, entry->last_failed);
+    nextloc += 4;
+
+	/* # of failed passwd attempt */
+    krb5_kdb_decode_int32(nextloc, entry->fail_auth_count);
+    nextloc += 4;
+
+	/* # tl_data strutures */
+    krb5_kdb_decode_int16(nextloc, entry->n_tl_data);
+    nextloc += 2;
+
+    if (entry->n_tl_data < 0)
+	return KRB5_KDB_TRUNCATED_RECORD;
+
+	/* # key_data strutures */
+    krb5_kdb_decode_int16(nextloc, entry->n_key_data);
+    nextloc += 2;
+
+    if (entry->n_key_data < 0)
+	return KRB5_KDB_TRUNCATED_RECORD;
+
+	/* Check for extra data */
+    if (entry->len > KRB5_KDB_V1_BASE_LENGTH) {
+	entry->e_length = entry->len - KRB5_KDB_V1_BASE_LENGTH;
+	if ((entry->e_data = (krb5_octet *)malloc(entry->e_length))) {
+	    memcpy(entry->e_data, nextloc, entry->e_length);
+	    nextloc += entry->e_length;
+	} else {
+	    return ENOMEM;
+	}
+    }
+
+    /*
+     * Get the principal name for the entry 
+     * (stored as a string which gets unparsed.)
+     */
+    if ((sizeleft -= 2) < 0) {
+	retval = KRB5_KDB_TRUNCATED_RECORD;
+	goto error_out;
+    }
+
+    i = 0;
+    krb5_kdb_decode_int16(nextloc, i16);
+    i = (int) i16;
+    nextloc += 2;
+
+    if ((retval = krb5_parse_name(context, nextloc, &(entry->princ))))
+	goto error_out;
+    if (((size_t) i != (strlen(nextloc) + 1)) || (sizeleft < i)) {
+	retval = KRB5_KDB_TRUNCATED_RECORD;
+	goto error_out;
+    }
+    sizeleft -= i;
+    nextloc += i;
+
+    	/* tl_data is a linked list */
+    tl_data = &entry->tl_data;
+    for (i = 0; i < entry->n_tl_data; i++) {
+    	if ((sizeleft -= 4) < 0) {
+	    retval = KRB5_KDB_TRUNCATED_RECORD;
+	    goto error_out;
+	}
+	if ((*tl_data = (krb5_tl_data *)
+	  malloc(sizeof(krb5_tl_data))) == NULL) {
+	    retval = ENOMEM;
+	    goto error_out;
+	}
+	(*tl_data)->tl_data_next = NULL;
+	(*tl_data)->tl_data_contents = NULL;
+	krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_type);
+	nextloc += 2;
+	krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_length);
+	nextloc += 2;
+
+    	if ((sizeleft -= (*tl_data)->tl_data_length) < 0) {
+	    retval = KRB5_KDB_TRUNCATED_RECORD;
+	    goto error_out;
+	}
+	if (((*tl_data)->tl_data_contents = (krb5_octet *)
+	  malloc((*tl_data)->tl_data_length)) == NULL) {
+	    retval = ENOMEM;
+	    goto error_out;
+	}
+	memcpy((*tl_data)->tl_data_contents,nextloc,(*tl_data)->tl_data_length);
+	nextloc += (*tl_data)->tl_data_length;
+	tl_data = &((*tl_data)->tl_data_next);
+    }
+
+    	/* key_data is an array */
+    if (entry->n_key_data && ((entry->key_data = (krb5_key_data *)
+      malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL)) {
+        retval = ENOMEM;
+	goto error_out;
+    }
+    for (i = 0; i < entry->n_key_data; i++) {
+	krb5_key_data * key_data;
+        int j;
+
+    	if ((sizeleft -= 4) < 0) {
+	    retval = KRB5_KDB_TRUNCATED_RECORD;
+	    goto error_out;
+	}
+	key_data = entry->key_data + i;
+	memset(key_data, 0, sizeof(krb5_key_data));
+	krb5_kdb_decode_int16(nextloc, key_data->key_data_ver);
+	nextloc += 2;
+	krb5_kdb_decode_int16(nextloc, key_data->key_data_kvno);
+	nextloc += 2;
+
+	/* key_data_ver determins number of elements and how to unparse them. */
+	if (key_data->key_data_ver <= KRB5_KDB_V1_KEY_DATA_ARRAY) {
+	    for (j = 0; j < key_data->key_data_ver; j++) {
+    	        if ((sizeleft -= 4) < 0) {
+	            retval = KRB5_KDB_TRUNCATED_RECORD;
+	            goto error_out;
+	        }
+		krb5_kdb_decode_int16(nextloc, key_data->key_data_type[j]);
+		nextloc += 2;
+		krb5_kdb_decode_int16(nextloc, key_data->key_data_length[j]);
+		nextloc += 2;
+
+    	        if ((sizeleft -= key_data->key_data_length[j]) < 0) {
+	            retval = KRB5_KDB_TRUNCATED_RECORD;
+	            goto error_out;
+	        }
+	        if (key_data->key_data_length[j]) {
+	    	    if ((key_data->key_data_contents[j] = (krb5_octet *)
+	    	      malloc(key_data->key_data_length[j])) == NULL) {
+	                retval = ENOMEM;
+	                goto error_out;
+	            }
+	            memcpy(key_data->key_data_contents[j], nextloc, 
+		           key_data->key_data_length[j]);
+	            nextloc += key_data->key_data_length[j];
+		}
+	    }
+	} else {
+	    /* This isn't right. I'll fix it later */
+	    abort();
+	}
+    }
+    return 0;
+
+error_out:;
+    krb5_dbe_free_contents(context, entry);
+    return retval;
+}
+	    
+void
+krb5_dbe_free_contents(context, entry)
+     krb5_context 	  context; 
+     krb5_db_entry 	* entry;
+{
+    krb5_tl_data 	* tl_data_next;
+    krb5_tl_data 	* tl_data;
+    int i, j;
+
+    if (entry->e_data)
+	free(entry->e_data);
+    if (entry->princ)
+	krb5_free_principal(context, entry->princ);
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
+	tl_data_next = tl_data->tl_data_next;
+	if (tl_data->tl_data_contents)
+	    free(tl_data->tl_data_contents);
+	free(tl_data);
+    }
+    if (entry->key_data) {
+    	for (i = 0; i < entry->n_key_data; i++) {
+	    for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+	    	if (entry->key_data[i].key_data_length[j]) {
+		    if (entry->key_data[i].key_data_contents[j]) {
+		        memset(entry->key_data[i].key_data_contents[j], 
+			       0, 
+			       (unsigned) entry->key_data[i].key_data_length[j]);
+		    	free (entry->key_data[i].key_data_contents[j]);
+		    }
+		}
+		entry->key_data[i].key_data_contents[j] = NULL;
+		entry->key_data[i].key_data_length[j] = 0;
+		entry->key_data[i].key_data_type[j] = 0;
+	    }
+	}
+	free(entry->key_data);
+    }
+    memset(entry, 0, sizeof(*entry));
+    return;
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/kdb_xdr.h b/krb5-1-6/src/plugins/kdb/db2/kdb_xdr.h
new file mode 100644
index 000000000..bd01ead27
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/kdb_xdr.h
@@ -0,0 +1,34 @@
+#ifndef _KDB2_XDR_H
+#define _KDB2_XDR_H
+
+#include "kdb.h"
+
+krb5_error_code
+krb5_encode_princ_dbkey( krb5_context context,
+			 krb5_data  *key,
+			 krb5_const_principal principal);
+
+krb5_error_code
+krb5_decode_princ_contents( krb5_context 	  context,
+			    krb5_data  		* content,
+			    krb5_db_entry 	* entry);
+
+void
+krb5_dbe_free_contents( krb5_context 	  context,
+			krb5_db_entry 	* entry);
+
+krb5_error_code
+krb5_encode_princ_contents( krb5_context 	  context,
+			    krb5_data  		* content,
+			    krb5_db_entry 	* entry);
+
+
+void
+krb5_free_princ_dbkey( krb5_context context,
+		       krb5_data  *key);
+
+void
+krb5_free_princ_contents( krb5_context context,
+			  krb5_data *contents);
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/CHANGELOG.db2 b/krb5-1-6/src/plugins/kdb/db2/libdb2/CHANGELOG.db2
new file mode 100644
index 000000000..abd05f95d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/CHANGELOG.db2
@@ -0,0 +1,123 @@
+db2-alpha.0 -> db2-alpha.1
+		This fixes a number of bugs in the alpha release.
+		1. 64-bit functionality.  The test suite now runs on alphas.
+		Memory leak fixed.
+		Pairs no longer disappear when pages are exactly full.
+		Flush meta-data correctly on sync.
+1.86 -> db2-alpha.0
+		This is an interim release.  We are in the process of
+		adding logging, locking, and transaction support to all
+		the db access methods.  This will necessitate database
+		format changes, interface changes, and major upheaval.
+		In the meantime, this PRELIMINARY release is to correct
+		some known bugs in the hash pacakge.  This release uses
+		a different page format from 1.86, so you will need to
+		dump and reload any existing databases if you upgrade
+		to this (and may have to do it again when 2.0 becomes
+		available.
+1.85 -> 1.86
+	btree:	Fix to split code for single large record at the end of a
+		page.
+1.84 -> 1.85
+	recno:	#ifdef out use of mmap, it's not portable enough.
+
+1.83 -> 1.84	Thu Aug 18 15:46:07 EDT 1994
+	recno:	Rework fixed-length records so that closing and reopening
+		the file now works.  Pad short records on input.  Never do
+		signed comparison in recno input reading functions.
+
+1.82 -> 1.83	Tue Jul 26 15:33:44 EDT 1994
+	btree:	Rework cursor deletion code yet again; bugs with
+		deleting empty pages that only contained the cursor
+		record.
+
+1.81 -> 1.82	Sat Jul 16 11:01:50 EDT 1994
+	btree:	Fix bugs introduced by new cursor/deletion code.
+		Replace return kbuf/dbuf with real DBT's.
+
+1.80 -> 1.81
+	btree:	Fix bugs introduced by new cursor/deletion code.
+	all:	Add #defines for Purify.
+
+1.79 -> 1.80	Wed Jul 13 22:41:54 EDT 1994
+	btree	Change deletion to coalesce empty pages.  This is a major
+		change, cursors and duplicate pages all had to be reworked.
+		Return to a fixed stack.
+	recno:	Affected by cursor changes.  New cursor structures should
+		permit multiple cursors in the future.
+
+1.78 -> 1.79	Mon Jun 20 17:36:47 EDT 1994
+	all:	Minor cleanups of 1.78 for porting reasons; only
+		major change was inlining check of NULL pointer
+		so that __fix_realloc goes away.
+
+1.77 -> 1.78	Thu Jun 16 19:06:43 EDT 1994
+	all:	Move "standard" size typedef's into db.h.
+
+1.76 -> 1.77	Thu Jun 16 16:48:38 EDT 1994
+	hash:	Delete __init_ routine, has special meaning to OSF 2.0.
+
+1.74 -> 1.76
+	all:	Finish up the port to the Alpha.
+
+1.73 -> 1.74
+	recno:	Don't put the record if rec_search fails, in rec_rdelete.
+		Create fixed-length intermediate records past "end" of DB
+		correctly.
+		Realloc bug when reading in fixed records.
+	all:	First cut at port to Alpha (64-bit architecture) using
+		4.4BSD basic integral types typedef's.
+		Cast allocation pointers to shut up old compilers.
+		Rework PORT directory into OS/machine directories.
+
+1.72 -> 1.73
+	btree:	If enough duplicate records were inserted and then deleted
+		that internal pages had references to empty pages of the
+		duplicate keys, the search function ended up on the wrong
+		page.
+
+1.7  -> 1.72	12 Oct 1993
+	hash:	Support NET/2 hash formats.
+
+1.7  -> 1.71	16 Sep 1993
+	btree/recno:
+		Fix bug in internal search routines that caused
+		return of invalid pointers.
+
+1.6  -> 1.7	07 Sep 1993
+	hash:	Fixed big key overflow bugs.
+	test:	Portability hacks, rewrite test script, Makefile.
+	btree/recno:
+		Stop copying non-overflow key/data pairs.
+	PORT:	Break PORT directory up into per architecture/OS
+		subdirectories.
+
+1.5  -> 1.6	06 Jun 1993
+	hash:	In PAIRFITS, the first comparison should look at (P)[2].
+		The hash_realloc function was walking off the end of memory.
+		The overflow page number was wrong when bumping splitpoint.
+
+1.4  -> 1.5	23 May 1993
+	hash:	Set hash default fill factor dynamically.
+	recno:	Fixed bug in sorted page splits.
+		Add page size parameter support.
+		Allow recno to specify the name of the underlying btree;
+			used for vi recovery.
+	btree/recno:
+		Support 64K pages.
+	btree/hash/recno:
+		Provide access to an underlying file descriptor.
+		Change sync routines to take a flag argument, recno
+			uses this to sync out the underlying btree.
+
+1.3  -> 1.4	10 May 1993
+	recno:	Delete the R_CURSORLOG flag from the recno interface.
+		Zero-length record fix for non-mmap reads.
+		Try and make SIZE_T_MAX test in open portable.
+
+1.2  -> 1.3	01 May 1993
+	btree:	Ignore user byte-order setting when reading already
+		existing database.  Fixes to byte-order conversions.
+
+1.1  -> 1.2	15 Apr 1993
+		No bug fixes, only compatibility hacks.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.in
new file mode 100644
index 000000000..c993f34a7
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.in
@@ -0,0 +1,43 @@
+thisconfigdir=.
+myfulldir=plugins/kdb/db2/libdb2
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+LOCAL_SUBDIRS=hash btree db mpool recno clib test
+
+LIBBASE=db
+LIBMAJOR=1
+LIBMINOR=1
+STOBJLISTS=hash/OBJS.ST btree/OBJS.ST db/OBJS.ST mpool/OBJS.ST \
+	recno/OBJS.ST clib/OBJS.ST
+SUBDIROBJLISTS=$(STOBJLISTS)
+RELDIR=../plugins/kdb/db2/libdb2
+
+HDRDIR=$(BUILDTOP)/include
+HDRS =	$(HDRDIR)/db.h $(HDRDIR)/db-config.h $(HDRDIR)/db-ndbm.h
+
+AUTOCONF_HEADER=$(srcdir)/include/config.h.in
+
+all-unix:: includes all-libs
+all-prerecurse: include/config.h include/db-config.h
+clean-unix:: clean-libs clean-includes
+
+includes:: $(HDRS)
+
+$(HDRDIR)/db.h: $(srcdir)/include/db.h
+	$(CP) $(srcdir)/include/db.h $@
+$(HDRDIR)/db-config.h: include/db-config.h
+	$(CP) include/db-config.h $@
+$(HDRDIR)/db-ndbm.h: $(srcdir)/include/db-ndbm.h
+	$(CP) $(srcdir)/include/db-ndbm.h $@
+
+include/config.h include/db-config.h: include/generated.stmp
+include/generated.stmp: $(srcdir)/include/config.h.in $(srcdir)/include/db-config.h.in
+	cd $(thisconfigdir) && $(SHELL) config.status
+$(srcdir)/include/config.h.in: @MAINT@ $(srcdir)/include/autoconf.stmp
+$(srcdir)/include/autoconf.stmp: $(srcdir)/configure.in $(SRCTOP)/aclocal.m4
+	cd $(srcdir) && $(AUTOHEADER) --include=$(CONFIG_RELTOPDIR) $(AUTOHEADERFLAGS)
+	touch $(srcdir)/include/autoconf.stmp
+
+clean-includes::
+	$(RM) $(HDRS) include/*.stmp
+@lib_frag@
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.inc b/krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.inc
new file mode 100644
index 000000000..77af9c512
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/Makefile.inc
@@ -0,0 +1,10 @@
+#	@(#)Makefile.inc	8.2 (Berkeley) 2/21/94
+#
+CFLAGS+=-D__DBINTERFACE_PRIVATE
+
+.include "${.CURDIR}/db/btree/Makefile.inc"
+.include "${.CURDIR}/db/db/Makefile.inc"
+.include "${.CURDIR}/db/hash/Makefile.inc"
+.include "${.CURDIR}/db/man/Makefile.inc"
+.include "${.CURDIR}/db/mpool/Makefile.inc"
+.include "${.CURDIR}/db/recno/Makefile.inc"
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/README b/krb5-1-6/src/plugins/kdb/db2/libdb2/README
new file mode 100644
index 000000000..70118bef5
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/README
@@ -0,0 +1,17 @@
+			  IMPORTANT NOTICE:
+
+This directory contains code of somewhat unknown origin that is
+INCOMPATIBLE with both Berkeley DB 1.85 and Sleepycat DB 2.x.  Do NOT
+contact Sleepycat regarding bugs in code found here; they do not
+appreciate it.  All bug reports about this code should go to the MIT
+Kerberos team via krb5-send-pr or email to krb5-bugs@mit.edu, as
+usual.
+
+It is believed that this "db" code originated from Berkeley DB 1.85
+and was further modified by Cygnus and the MIT Kerberos team.  Some
+significant changes to the hash code occured at some point.
+
+The file README.db2 contains the README file provided with the
+2.0-alpha release of Berkeley/Sleepycat DB, which may contain
+marginally useful information.  It is not known at this time how well
+this code matches that of the 2.0-alpha release.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB b/krb5-1-6/src/plugins/kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB
new file mode 100644
index 000000000..112454e94
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB
@@ -0,0 +1,2 @@
+THIS IS NOT THE SLEEPYCAT DB.
+Please see the README file for more information.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/README.db2 b/krb5-1-6/src/plugins/kdb/db2/libdb2/README.db2
new file mode 100644
index 000000000..5700b7393
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/README.db2
@@ -0,0 +1,41 @@
+#	@(#)README	8.28 (Berkeley) 11/2/95
+
+This is version 2.0-ALPHA of the Berkeley DB code.
+THIS IS A PRELIMINARY RELEASE.
+
+For information on compiling and installing this software, see the file
+PORT/README.
+
+Newer versions of this software will periodically be made available by
+anonymous ftp from ftp.cs.berkeley.edu:ucb/4bsd/db.tar.{Z,gz} and from
+ftp.harvard.edu:margo/db.tar.{Z,gz}.  If you want to receive announcements
+of future releases of this software, send email to the contact address
+below.
+
+Email questions may be addressed to dbinfo@eecs.harvard.edu.
+
+============================================
+Distribution contents:
+
+README		This file.
+CHANGELOG	List of changes, per version.
+btree		B+tree access method.
+db		The db_open interface routine.
+docs		Various USENIX papers, and the formatted manual pages.
+hash		Extended linear hashing access method.
+lock		Lock manager.
+log		Log manager.
+man		The unformatted manual pages.
+mpool		The buffer manager support.
+mutex		Mutex support.
+recno		The fixed/variable length record access method.
+test		Test package.
+txn		Transaction support.
+
+============================================
+Debugging:
+
+If you're running a memory checker (e.g. Purify) on DB, make sure that
+you recompile it with "-DPURIFY" in the CFLAGS, first.  By default,
+allocated pages are not initialized by the DB code, and they will show
+up as reads of uninitialized memory in the buffer write routines.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.in
new file mode 100644
index 000000000..eb166d37b
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.in
@@ -0,0 +1,14 @@
+thisconfigdir=./..
+myfulldir=plugins/kdb/db2/libdb2/btree
+mydir=btree
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+STLIBOBJS=	bt_close.o bt_conv.o bt_debug.o bt_delete.o bt_get.o \
+		bt_open.o bt_overflow.o bt_page.o bt_put.o bt_search.o \
+		bt_seq.o bt_split.o bt_utils.o
+
+LOCALINCLUDES=	-I. -I$(srcdir)/../include -I../include -I$(srcdir)/../mpool \
+		-I$(srcdir)/../db
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.inc b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.inc
new file mode 100644
index 000000000..8ed76494a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/Makefile.inc
@@ -0,0 +1,7 @@
+#	@(#)Makefile.inc	8.2 (Berkeley) 7/14/94
+
+.PATH: ${.CURDIR}/db/btree
+
+SRCS+=	bt_close.c bt_conv.c bt_debug.c bt_delete.c bt_get.c bt_open.c \
+	bt_overflow.c bt_page.c bt_put.c bt_search.c bt_seq.c bt_split.c \
+	bt_utils.c
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_close.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_close.c
new file mode 100644
index 000000000..11be13411
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_close.c
@@ -0,0 +1,183 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_close.c	8.7 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+static int bt_meta __P((BTREE *));
+
+/*
+ * BT_CLOSE -- Close a btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_close(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	int fd;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Sync the tree. */
+	if (__bt_sync(dbp, 0) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Close the memory pool. */
+	if (mpool_close(t->bt_mp) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Free random memory. */
+	if (t->bt_cursor.key.data != NULL) {
+		free(t->bt_cursor.key.data);
+		t->bt_cursor.key.size = 0;
+		t->bt_cursor.key.data = NULL;
+	}
+	if (t->bt_rkey.data) {
+		free(t->bt_rkey.data);
+		t->bt_rkey.size = 0;
+		t->bt_rkey.data = NULL;
+	}
+	if (t->bt_rdata.data) {
+		free(t->bt_rdata.data);
+		t->bt_rdata.size = 0;
+		t->bt_rdata.data = NULL;
+	}
+
+	fd = t->bt_fd;
+	free(t);
+	free(dbp);
+	return (close(fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * BT_SYNC -- sync the btree to disk.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_sync(dbp, flags)
+	const DB *dbp;
+	u_int flags;
+{
+	BTREE *t;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Sync doesn't currently take any flags. */
+	if (flags != 0) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (F_ISSET(t, B_INMEM | B_RDONLY)
+	    || !F_ISSET(t, B_MODIFIED | B_METADIRTY))
+		return (RET_SUCCESS);
+
+	if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
+		return (RET_ERROR);
+
+	if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
+		F_CLR(t, B_MODIFIED);
+
+	return (status);
+}
+
+/*
+ * BT_META -- write the tree meta data to disk.
+ *
+ * Parameters:
+ *	t:	tree
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_meta(t)
+	BTREE *t;
+{
+	BTMETA m;
+	void *p;
+
+	if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
+		return (RET_ERROR);
+
+	/* Fill in metadata. */
+	m.magic = BTREEMAGIC;
+	m.version = BTREEVERSION;
+	m.psize = t->bt_psize;
+	m.free = t->bt_free;
+	m.nrecs = t->bt_nrecs;
+	m.flags = F_ISSET(t, SAVEMETA);
+
+	memmove(p, &m, sizeof(BTMETA));
+	mpool_put(t->bt_mp, p, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_conv.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_conv.c
new file mode 100644
index 000000000..6cfa216ca
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_conv.c
@@ -0,0 +1,221 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_conv.c	8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+static void mswap __P((PAGE *));
+
+/*
+ * __BT_BPGIN, __BT_BPGOUT --
+ *	Convert host-specific number layout to/from the host-independent
+ *	format stored on disk.
+ *
+ * Parameters:
+ *	t:	tree
+ *	pg:	page number
+ *	h:	page to convert
+ */
+void
+__bt_pgin(t, pg, pp)
+	void *t;
+	db_pgno_t pg;
+	void *pp;
+{
+	PAGE *h;
+	indx_t i, top;
+	u_char flags;
+	char *p;
+
+	if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+		return;
+	if (pg == P_META) {
+		mswap(pp);
+		return;
+	}
+
+	h = pp;
+	M_32_SWAP(h->pgno);
+	M_32_SWAP(h->prevpg);
+	M_32_SWAP(h->nextpg);
+	M_32_SWAP(h->flags);
+	M_16_SWAP(h->lower);
+	M_16_SWAP(h->upper);
+
+	top = NEXTINDEX(h);
+	if ((h->flags & P_TYPE) == P_BINTERNAL)
+		for (i = 0; i < top; i++) {
+			M_16_SWAP(h->linp[i]);
+			p = (char *)GETBINTERNAL(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(db_pgno_t);
+			if (*(u_char *)p & P_BIGKEY) {
+				p += sizeof(u_char);
+				P_32_SWAP(p);
+				p += sizeof(db_pgno_t);
+				P_32_SWAP(p);
+			}
+		}
+	else if ((h->flags & P_TYPE) == P_BLEAF)
+		for (i = 0; i < top; i++) {
+			M_16_SWAP(h->linp[i]);
+			p = (char *)GETBLEAF(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			flags = *(u_char *)p;
+			if (flags & (P_BIGKEY | P_BIGDATA)) {
+				p += sizeof(u_char);
+				if (flags & P_BIGKEY) {
+					P_32_SWAP(p);
+					p += sizeof(db_pgno_t);
+					P_32_SWAP(p);
+				}
+				if (flags & P_BIGDATA) {
+					p += sizeof(u_int32_t);
+					P_32_SWAP(p);
+					p += sizeof(db_pgno_t);
+					P_32_SWAP(p);
+				}
+			}
+		}
+}
+
+void
+__bt_pgout(t, pg, pp)
+	void *t;
+	db_pgno_t pg;
+	void *pp;
+{
+	PAGE *h;
+	indx_t i, top;
+	u_char flags;
+	char *p;
+
+	if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+		return;
+	if (pg == P_META) {
+		mswap(pp);
+		return;
+	}
+
+	h = pp;
+	top = NEXTINDEX(h);
+	if ((h->flags & P_TYPE) == P_BINTERNAL)
+		for (i = 0; i < top; i++) {
+			p = (char *)GETBINTERNAL(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(db_pgno_t);
+			if (*(u_char *)p & P_BIGKEY) {
+				p += sizeof(u_char);
+				P_32_SWAP(p);
+				p += sizeof(db_pgno_t);
+				P_32_SWAP(p);
+			}
+			M_16_SWAP(h->linp[i]);
+		}
+	else if ((h->flags & P_TYPE) == P_BLEAF)
+		for (i = 0; i < top; i++) {
+			p = (char *)GETBLEAF(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			flags = *(u_char *)p;
+			if (flags & (P_BIGKEY | P_BIGDATA)) {
+				p += sizeof(u_char);
+				if (flags & P_BIGKEY) {
+					P_32_SWAP(p);
+					p += sizeof(db_pgno_t);
+					P_32_SWAP(p);
+				}
+				if (flags & P_BIGDATA) {
+					p += sizeof(u_int32_t);
+					P_32_SWAP(p);
+					p += sizeof(db_pgno_t);
+					P_32_SWAP(p);
+				}
+			}
+			M_16_SWAP(h->linp[i]);
+		}
+
+	M_32_SWAP(h->pgno);
+	M_32_SWAP(h->prevpg);
+	M_32_SWAP(h->nextpg);
+	M_32_SWAP(h->flags);
+	M_16_SWAP(h->lower);
+	M_16_SWAP(h->upper);
+}
+
+/*
+ * MSWAP -- Actually swap the bytes on the meta page.
+ *
+ * Parameters:
+ *	p:	page to convert
+ */
+static void
+mswap(pg)
+	PAGE *pg;
+{
+	char *p;
+
+	p = (char *)pg;
+	P_32_SWAP(p);		/* magic */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* version */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* psize */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* free */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* nrecs */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* flags */
+	p += sizeof(u_int32_t);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_debug.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_debug.c
new file mode 100644
index 000000000..d36256b3a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_debug.c
@@ -0,0 +1,377 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_debug.c	8.6 (Berkeley) 1/9/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+#if defined(DEBUG) || defined(STATISTICS)
+
+static FILE *tracefp;
+
+/*
+ * __bt_dinit --
+ *	initialize debugging.
+ */
+static void
+__bt_dinit()
+{
+	static int first = 1;
+	char buf[1024];
+
+	if (!first)
+		return;
+	first = 0;
+
+#ifndef TRACE_TO_STDERR
+	if ((tracefp = fopen("/tmp/__bt_debug", "w")) != NULL)
+		return;
+#endif
+	tracefp = stderr;
+}
+#endif
+
+#ifdef DEBUG
+/*
+ * __bt_dump --
+ *	dump the tree
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB
+ */
+int
+__bt_dump(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	PAGE *h;
+	db_pgno_t i;
+	char *sep;
+
+	__bt_dinit();
+
+	t = dbp->internal;
+	(void)fprintf(tracefp, "%s: pgsz %d",
+	    F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
+	if (F_ISSET(t, R_RECNO))
+		(void)fprintf(tracefp, " keys %lu", t->bt_nrecs);
+#undef X
+#define	X(flag, name) \
+	if (F_ISSET(t, flag)) { \
+		(void)fprintf(tracefp, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	if (t->flags != 0) {
+		sep = " flags (";
+		X(R_FIXLEN,	"FIXLEN");
+		X(B_INMEM,	"INMEM");
+		X(B_NODUPS,	"NODUPS");
+		X(B_RDONLY,	"RDONLY");
+		X(R_RECNO,	"RECNO");
+		X(B_METADIRTY,"METADIRTY");
+		(void)fprintf(tracefp, ")\n");
+	}
+#undef X
+	for (i = P_ROOT; i < t->bt_mp->npages &&
+	    (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
+		__bt_dpage(dbp, h);
+	(void)fflush(tracefp);
+	return (0);
+}
+
+/*
+ * BT_DMPAGE -- Dump the meta page
+ *
+ * Parameters:
+ *	h:	pointer to the PAGE
+ */
+int
+__bt_dmpage(h)
+	PAGE *h;
+{
+	BTMETA *m;
+	char *sep;
+
+	__bt_dinit();
+
+	m = (BTMETA *)h;
+	(void)fprintf(tracefp, "magic %lx\n", m->magic);
+	(void)fprintf(tracefp, "version %lu\n", m->version);
+	(void)fprintf(tracefp, "psize %lu\n", m->psize);
+	(void)fprintf(tracefp, "free %lu\n", m->free);
+	(void)fprintf(tracefp, "nrecs %lu\n", m->nrecs);
+	(void)fprintf(tracefp, "flags %lu", m->flags);
+#undef X
+#define	X(flag, name) \
+	if (m->flags & flag) { \
+		(void)fprintf(tracefp, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	if (m->flags) {
+		sep = " (";
+		X(B_NODUPS,	"NODUPS");
+		X(R_RECNO,	"RECNO");
+		(void)fprintf(tracefp, ")");
+	}
+	(void)fprintf(tracefp, "\n");
+	(void)fflush(tracefp);
+	return (0);
+}
+
+/*
+ * BT_DNPAGE -- Dump the page
+ *
+ * Parameters:
+ *	n:	page number to dump.
+ */
+int
+__bt_dnpage(dbp, pgno)
+	DB *dbp;
+	db_pgno_t pgno;
+{
+	BTREE *t;
+	PAGE *h;
+
+	__bt_dinit();
+
+	t = dbp->internal;
+	if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL)
+		__bt_dpage(dbp, h);
+	(void)fflush(tracefp);
+	return (0);
+}
+
+/*
+ * BT_DPAGE -- Dump the page
+ *
+ * Parameters:
+ *	h:	pointer to the PAGE
+ */
+int
+__bt_dpage(dbp, h)
+	DB *dbp;
+	PAGE *h;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	RINTERNAL *ri;
+	RLEAF *rl;
+	u_long pgsize;
+	indx_t cur, top, lim;
+	char *sep;
+
+	__bt_dinit();
+
+	(void)fprintf(tracefp, "    page %d: (", h->pgno);
+#undef X
+#define	X(flag, name)							\
+	if (h->flags & flag) {						\
+		(void)fprintf(tracefp, "%s%s", sep, name);		\
+		sep = ", ";						\
+	}
+	sep = "";
+	X(P_BINTERNAL,	"BINTERNAL")		/* types */
+	X(P_BLEAF,	"BLEAF")
+	X(P_RINTERNAL,	"RINTERNAL")		/* types */
+	X(P_RLEAF,	"RLEAF")
+	X(P_OVERFLOW,	"OVERFLOW")
+	X(P_PRESERVE,	"PRESERVE");
+	(void)fprintf(tracefp, ")\n");
+#undef X
+
+	(void)fprintf(tracefp, "\tprev %2d next %2d", h->prevpg, h->nextpg);
+	if (h->flags & P_OVERFLOW)
+		return;
+
+	pgsize = ((BTREE *)dbp->internal)->bt_mp->pagesize;
+	lim = (pgsize - BTDATAOFF) / sizeof(indx_t);
+	top = NEXTINDEX(h);
+	lim = top > lim ? lim : top;
+	(void)fprintf(tracefp, " lower %3d upper %3d nextind %d\n",
+	    h->lower, h->upper, top);
+	for (cur = 0; cur < lim; cur++) {
+		(void)fprintf(tracefp, "\t[%03d] %4d ", cur, h->linp[cur]);
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+			bi = GETBINTERNAL(h, cur);
+			(void)fprintf(tracefp,
+			    "size %03d pgno %03d", bi->ksize, bi->pgno);
+			if (bi->flags & P_BIGKEY)
+				(void)fprintf(tracefp, " (indirect)");
+			else if (bi->ksize)
+				(void)fprintf(tracefp,
+				    " {%.*s}", (int)bi->ksize, bi->bytes);
+			break;
+		case P_RINTERNAL:
+			ri = GETRINTERNAL(h, cur);
+			(void)fprintf(tracefp, "entries %03d pgno %03d",
+				ri->nrecs, ri->pgno);
+			break;
+		case P_BLEAF:
+			bl = GETBLEAF(h, cur);
+			if (bl->flags & P_BIGKEY)
+				(void)fprintf(tracefp,
+				    "big key page %lu size %u/",
+				    *(db_pgno_t *)bl->bytes,
+				    *(u_int32_t *)(bl->bytes + sizeof(db_pgno_t)));
+			else if (bl->ksize)
+				(void)fprintf(tracefp, "%s/", bl->bytes);
+			if (bl->flags & P_BIGDATA)
+				(void)fprintf(tracefp,
+				    "big data page %lu size %u",
+				    *(db_pgno_t *)(bl->bytes + bl->ksize),
+				    *(u_int32_t *)(bl->bytes + bl->ksize +
+				    sizeof(db_pgno_t)));
+			else if (bl->dsize)
+				(void)fprintf(tracefp, "%.*s",
+				    (int)bl->dsize, bl->bytes + bl->ksize);
+			break;
+		case P_RLEAF:
+			rl = GETRLEAF(h, cur);
+			if (rl->flags & P_BIGDATA)
+				(void)fprintf(tracefp,
+				    "big data page %lu size %u",
+				    *(db_pgno_t *)rl->bytes,
+				    *(u_int32_t *)(rl->bytes + sizeof(db_pgno_t)));
+			else if (rl->dsize)
+				(void)fprintf(tracefp,
+				    "%.*s", (int)rl->dsize, rl->bytes);
+			break;
+		}
+		(void)fprintf(tracefp, "\n");
+	}
+	(void)fflush(tracefp);
+	return (0);
+}
+#endif
+
+#ifdef STATISTICS
+/*
+ * bt_stat --
+ *	Gather/print the tree statistics
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB
+ */
+int
+__bt_stat(dbp)
+	DB *dbp;
+{
+	extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit;
+	extern u_long bt_sortsplit, bt_split;
+	BTREE *t;
+	PAGE *h;
+	db_pgno_t i, pcont, pinternal, pleaf;
+	u_long ifree, lfree, nkeys;
+	int levels;
+
+	__bt_dinit();
+
+	t = dbp->internal;
+	pcont = pinternal = pleaf = 0;
+	nkeys = ifree = lfree = 0;
+	for (i = P_ROOT; i < t->bt_mp->npages &&
+	    (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+		case P_RINTERNAL:
+			++pinternal;
+			ifree += h->upper - h->lower;
+			break;
+		case P_BLEAF:
+		case P_RLEAF:
+			++pleaf;
+			lfree += h->upper - h->lower;
+			nkeys += NEXTINDEX(h);
+			break;
+		case P_OVERFLOW:
+			++pcont;
+			break;
+		}
+
+	/* Count the levels of the tree. */
+	for (i = P_ROOT, levels = 0 ;; ++levels) {
+		h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN);
+		if (h->flags & (P_BLEAF|P_RLEAF)) {
+			if (levels == 0)
+				levels = 1;
+			break;
+		}
+		i = F_ISSET(t, R_RECNO) ?
+		    GETRINTERNAL(h, 0)->pgno :
+		    GETBINTERNAL(h, 0)->pgno;
+	}
+
+	(void)fprintf(tracefp, "%d level%s with %ld keys",
+	    levels, levels == 1 ? "" : "s", nkeys);
+	if (F_ISSET(t, R_RECNO))
+		(void)fprintf(tracefp, " (%ld header count)", t->bt_nrecs);
+	(void)fprintf(tracefp,
+	    "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n",
+	    pinternal + pleaf + pcont, pleaf, pinternal, pcont);
+	(void)fprintf(tracefp, "%ld cache hits, %ld cache misses\n",
+	    bt_cache_hit, bt_cache_miss);
+	(void)fprintf(tracefp,
+	    "%ld splits (%ld root splits, %ld sort splits)\n",
+	    bt_split, bt_rootsplit, bt_sortsplit);
+	pleaf *= t->bt_psize - BTDATAOFF;
+	if (pleaf)
+		(void)fprintf(tracefp,
+		    "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n",
+		    ((double)(pleaf - lfree) / pleaf) * 100,
+		    pleaf - lfree, lfree);
+	pinternal *= t->bt_psize - BTDATAOFF;
+	if (pinternal)
+		(void)fprintf(tracefp,
+		    "%.0f%% internal fill (%ld bytes used, %ld bytes free\n",
+		    ((double)(pinternal - ifree) / pinternal) * 100,
+		    pinternal - ifree, ifree);
+	if (bt_pfxsaved)
+		(void)fprintf(tracefp, "prefix checking removed %lu bytes.\n",
+		    bt_pfxsaved);
+	(void)fflush(tracefp);
+	return (0);
+}
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_delete.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_delete.c
new file mode 100644
index 000000000..d002a66ed
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_delete.c
@@ -0,0 +1,657 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_delete.c	8.13 (Berkeley) 7/28/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+static int __bt_bdelete __P((BTREE *, const DBT *));
+static int __bt_curdel __P((BTREE *, const DBT *, PAGE *, u_int));
+static int __bt_pdelete __P((BTREE *, PAGE *));
+static int __bt_relink __P((BTREE *, PAGE *));
+static int __bt_stkacq __P((BTREE *, PAGE **, CURSOR *));
+
+/*
+ * __bt_delete
+ *	Delete the item(s) referenced by a key.
+ *
+ * Return RET_SPECIAL if the key is not found.
+ */
+int
+__bt_delete(dbp, key, flags)
+	const DB *dbp;
+	const DBT *key;
+	u_int flags;
+{
+	BTREE *t;
+	CURSOR *c;
+	PAGE *h;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Check for change to a read-only tree. */
+	if (F_ISSET(t, B_RDONLY)) {
+		errno = EPERM;
+		return (RET_ERROR);
+	}
+
+	switch (flags) {
+	case 0:
+		status = __bt_bdelete(t, key);
+		break;
+	case R_CURSOR:
+		/*
+		 * If flags is R_CURSOR, delete the cursor.  Must already
+		 * have started a scan and not have already deleted it.
+		 */
+		c = &t->bt_cursor;
+		if (F_ISSET(c, CURS_INIT)) {
+			if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+				return (RET_ERROR);
+
+			/*
+			 * If the page is about to be emptied, we'll need to
+			 * delete it, which means we have to acquire a stack.
+			 */
+			if (NEXTINDEX(h) == 1)
+				if (__bt_stkacq(t, &h, &t->bt_cursor))
+					return (RET_ERROR);
+
+			status = __bt_dleaf(t, NULL, h, c->pg.index);
+
+			if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
+				if (__bt_pdelete(t, h))
+					return (RET_ERROR);
+			} else
+				mpool_put(t->bt_mp,
+				    h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
+			break;
+		}
+		/* FALLTHROUGH */
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+	if (status == RET_SUCCESS)
+		F_SET(t, B_MODIFIED);
+	return (status);
+}
+
+/*
+ * __bt_stkacq --
+ *	Acquire a stack so we can delete a cursor entry.
+ *
+ * Parameters:
+ *	  t:	tree
+ *	 hp:	pointer to current, pinned PAGE pointer
+ *	  c:	pointer to the cursor
+ *
+ * Returns:
+ *	0 on success, 1 on failure
+ */
+static int
+__bt_stkacq(t, hp, c)
+	BTREE *t;
+	PAGE **hp;
+	CURSOR *c;
+{
+	BINTERNAL *bi;
+	EPG *e;
+	EPGNO *parent;
+	PAGE *h;
+	indx_t idx;
+	db_pgno_t pgno;
+	recno_t nextpg, prevpg;
+	int exact, level;
+	
+	/*
+	 * Find the first occurrence of the key in the tree.  Toss the
+	 * currently locked page so we don't hit an already-locked page.
+	 */
+	h = *hp;
+	mpool_put(t->bt_mp, h, 0);
+	if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+		return (1);
+	h = e->page;
+
+	/* See if we got it in one shot. */
+	if (h->pgno == c->pg.pgno)
+		goto ret;
+
+	/*
+	 * Move right, looking for the page.  At each move we have to move
+	 * up the stack until we don't have to move to the next page.  If
+	 * we have to change pages at an internal level, we have to fix the
+	 * stack back up.
+	 */
+	while (h->pgno != c->pg.pgno) {
+		if ((nextpg = h->nextpg) == P_INVALID)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Move up the stack. */
+		for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+			/* Get the parent page. */
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				return (1);
+
+			/* Move to the next index. */
+			if (parent->index != NEXTINDEX(h) - 1) {
+				idx = parent->index + 1;
+				BT_PUSH(t, h->pgno, idx);
+				break;
+			}
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		/* Restore the stack. */
+		while (level--) {
+			/* Push the next level down onto the stack. */
+			bi = GETBINTERNAL(h, idx);
+			pgno = bi->pgno;
+			BT_PUSH(t, pgno, 0);
+
+			/* Lose the currently pinned page. */
+			mpool_put(t->bt_mp, h, 0);
+
+			/* Get the next level down. */
+			if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+				return (1);
+			idx = 0;
+		}
+		mpool_put(t->bt_mp, h, 0);
+		if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
+			return (1);
+	}
+
+	if (h->pgno == c->pg.pgno)
+		goto ret;
+
+	/* Reacquire the original stack. */
+	mpool_put(t->bt_mp, h, 0);
+	if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+		return (1);
+	h = e->page;
+
+	/*
+	 * Move left, looking for the page.  At each move we have to move
+	 * up the stack until we don't have to change pages to move to the
+	 * next page.  If we have to change pages at an internal level, we
+	 * have to fix the stack back up.
+	 */
+	while (h->pgno != c->pg.pgno) {
+		if ((prevpg = h->prevpg) == P_INVALID)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Move up the stack. */
+		for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+			/* Get the parent page. */
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				return (1);
+
+			/* Move to the next index. */
+			if (parent->index != 0) {
+				idx = parent->index - 1;
+				BT_PUSH(t, h->pgno, idx);
+				break;
+			}
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		/* Restore the stack. */
+		while (level--) {
+			/* Push the next level down onto the stack. */
+			bi = GETBINTERNAL(h, idx);
+			pgno = bi->pgno;
+
+			/* Lose the currently pinned page. */
+			mpool_put(t->bt_mp, h, 0);
+
+			/* Get the next level down. */
+			if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+				return (1);
+
+			idx = NEXTINDEX(h) - 1;
+			BT_PUSH(t, pgno, idx);
+		}
+		mpool_put(t->bt_mp, h, 0);
+		if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
+			return (1);
+	}
+	
+
+ret:	mpool_put(t->bt_mp, h, 0);
+	return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
+}
+
+/*
+ * __bt_bdelete --
+ *	Delete all key/data pairs matching the specified key.
+ *
+ * Parameters:
+ *	  t:	tree
+ *	key:	key to delete
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+__bt_bdelete(t, key)
+	BTREE *t;
+	const DBT *key;
+{
+	EPG *e;
+	PAGE *h;
+	int deleted, exact, redo;
+
+	deleted = 0;
+
+	/* Find any matching record; __bt_search pins the page. */
+loop:	if ((e = __bt_search(t, key, &exact)) == NULL)
+		return (deleted ? RET_SUCCESS : RET_ERROR);
+	if (!exact) {
+		mpool_put(t->bt_mp, e->page, 0);
+		return (deleted ? RET_SUCCESS : RET_SPECIAL);
+	}
+
+	/*
+	 * Delete forward, then delete backward, from the found key.  If
+	 * there are duplicates and we reach either side of the page, do
+	 * the key search again, so that we get them all.
+	 */
+	redo = 0;
+	h = e->page;
+	do {
+		if (__bt_dleaf(t, key, h, e->index)) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		if (F_ISSET(t, B_NODUPS)) {
+			if (NEXTINDEX(h) == 0) {
+				if (__bt_pdelete(t, h))
+					return (RET_ERROR);
+			} else
+				mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			return (RET_SUCCESS);
+		}
+		deleted = 1;
+	} while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
+
+	/* Check for right-hand edge of the page. */
+	if (e->index == NEXTINDEX(h))
+		redo = 1;
+
+	/* Delete from the key to the beginning of the page. */
+	while (e->index-- > 0) {
+		if (__bt_cmp(t, key, e) != 0)
+			break;
+		if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		if (e->index == 0)
+			redo = 1;
+	}
+
+	/* Check for an empty page. */
+	if (NEXTINDEX(h) == 0) {
+		if (__bt_pdelete(t, h))
+			return (RET_ERROR);
+		goto loop;
+	}
+
+	/* Put the page. */
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	if (redo)
+		goto loop;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_pdelete --
+ *	Delete a single page from the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	leaf page
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ *
+ * Side-effects:
+ *	mpool_put's the page
+ */
+static int
+__bt_pdelete(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	BINTERNAL *bi;
+	PAGE *pg;
+	EPGNO *parent;
+	indx_t cnt, idx, *ip, offset;
+	u_int32_t nksize;
+	char *from;
+
+	/*
+	 * Walk the parent page stack -- a LIFO stack of the pages that were
+	 * traversed when we searched for the page where the delete occurred.
+	 * Each stack entry is a page number and a page index offset.  The
+	 * offset is for the page traversed on the search.  We've just deleted
+	 * a page, so we have to delete the key from the parent page.
+	 *
+	 * If the delete from the parent page makes it empty, this process may
+	 * continue all the way up the tree.  We stop if we reach the root page
+	 * (which is never deleted, it's just not worth the effort) or if the
+	 * delete does not empty the page.
+	 */
+	while ((parent = BT_POP(t)) != NULL) {
+		/* Get the parent page. */
+		if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			return (RET_ERROR);
+		
+		idx = parent->index;
+		bi = GETBINTERNAL(pg, idx);
+
+		/* Free any overflow pages. */
+		if (bi->flags & P_BIGKEY &&
+		    __ovfl_delete(t, bi->bytes) == RET_ERROR) {
+			mpool_put(t->bt_mp, pg, 0);
+			return (RET_ERROR);
+		}
+
+		/*
+		 * Free the parent if it has only the one key and it's not the
+		 * root page. If it's the rootpage, turn it back into an empty
+		 * leaf page.
+		 */
+		if (NEXTINDEX(pg) == 1)
+			if (pg->pgno == P_ROOT) {
+				pg->lower = BTDATAOFF;
+				pg->upper = t->bt_psize;
+				pg->flags = P_BLEAF;
+			} else {
+				if (__bt_relink(t, pg) || __bt_free(t, pg))
+					return (RET_ERROR);
+				continue;
+			}
+		else {
+			/* Pack remaining key items at the end of the page. */
+			nksize = NBINTERNAL(bi->ksize);
+			from = (char *)pg + pg->upper;
+			memmove(from + nksize, from, (char *)bi - from);
+			pg->upper += nksize;
+
+			/* Adjust indices' offsets, shift the indices down. */
+			offset = pg->linp[idx];
+			for (cnt = idx, ip = &pg->linp[0]; cnt--; ++ip)
+				if (ip[0] < offset)
+					ip[0] += nksize;
+			for (cnt = NEXTINDEX(pg) - idx; --cnt; ++ip)
+				ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
+			pg->lower -= sizeof(indx_t);
+		}
+
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+		break;
+	}
+
+	/* Free the leaf page, as long as it wasn't the root. */
+	if (h->pgno == P_ROOT) {
+		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+		return (RET_SUCCESS);
+	}
+	return (__bt_relink(t, h) || __bt_free(t, h));
+}
+
+/*
+ * __bt_dleaf --
+ *	Delete a single record from a leaf page.
+ *
+ * Parameters:
+ *	t:	tree
+ *    key:	referenced key
+ *	h:	page
+ *	idx:	index on page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_dleaf(t, key, h, idx)
+	BTREE *t;
+	const DBT *key;
+	PAGE *h;
+	u_int idx;
+{
+	BLEAF *bl;
+	indx_t cnt, *ip, offset;
+	u_int32_t nbytes;
+	void *to;
+	char *from;
+
+	/* If this record is referenced by the cursor, delete the cursor. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == idx &&
+	    __bt_curdel(t, key, h, idx))
+		return (RET_ERROR);
+
+	/* If the entry uses overflow pages, make them available for reuse. */
+	to = bl = GETBLEAF(h, idx);
+	if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
+		return (RET_ERROR);
+	if (bl->flags & P_BIGDATA &&
+	    __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Pack the remaining key/data items at the end of the page. */
+	nbytes = NBLEAF(bl);
+	from = (char *)h + h->upper;
+	memmove(from + nbytes, from, (char *)to - from);
+	h->upper += nbytes;
+
+	/* Adjust the indices' offsets, shift the indices down. */
+	offset = h->linp[idx];
+	for (cnt = idx, ip = &h->linp[0]; cnt--; ++ip)
+		if (ip[0] < offset)
+			ip[0] += nbytes;
+	for (cnt = NEXTINDEX(h) - idx; --cnt; ++ip)
+		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+	h->lower -= sizeof(indx_t);
+
+	/* If the cursor is on this page, adjust it as necessary. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > idx)
+		--t->bt_cursor.pg.index;
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_curdel --
+ *	Delete the cursor.
+ *
+ * Parameters:
+ *	t:	tree
+ *    key:	referenced key (or NULL)
+ *	h:	page
+ *  idx:	idx on page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+static int
+__bt_curdel(t, key, h, idx)
+	BTREE *t;
+	const DBT *key;
+	PAGE *h;
+	u_int idx;
+{
+	CURSOR *c;
+	EPG e;
+	PAGE *pg;
+	int curcopy, status;
+
+	/*
+	 * If there are duplicates, move forward or backward to one.
+	 * Otherwise, copy the key into the cursor area.
+	 */
+	c = &t->bt_cursor;
+	F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
+
+	curcopy = 0;
+	if (!F_ISSET(t, B_NODUPS)) {
+		/*
+		 * We're going to have to do comparisons.  If we weren't
+		 * provided a copy of the key, i.e. the user is deleting
+		 * the current cursor position, get one.
+		 */
+		if (key == NULL) {
+			e.page = h;
+			e.index = idx;
+			if ((status = __bt_ret(t, &e,
+			    &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
+				return (status);
+			curcopy = 1;
+			key = &c->key;
+		}
+		/* Check previous key, if not at the beginning of the page. */
+		if (idx > 0) { 
+			e.page = h;
+			e.index = idx - 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_BEFORE);
+				goto dup2;
+			}
+		}
+		/* Check next key, if not at the end of the page. */
+		if (idx < NEXTINDEX(h) - 1) {
+			e.page = h;
+			e.index = idx + 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_AFTER);
+				goto dup2;
+			}
+		}
+		/* Check previous key if at the beginning of the page. */
+		if (idx == 0 && h->prevpg != P_INVALID) {
+			if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+				return (RET_ERROR);
+			e.page = pg;
+			e.index = NEXTINDEX(pg) - 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_BEFORE);
+				goto dup1;
+			}
+			mpool_put(t->bt_mp, pg, 0);
+		}
+		/* Check next key if at the end of the page. */
+		if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
+			if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+				return (RET_ERROR);
+			e.page = pg;
+			e.index = 0;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_AFTER);
+dup1:				mpool_put(t->bt_mp, pg, 0);
+dup2:				c->pg.pgno = e.page->pgno;
+				c->pg.index = e.index;
+				return (RET_SUCCESS);
+			}
+			mpool_put(t->bt_mp, pg, 0);
+		}
+	}
+	e.page = h;
+	e.index = idx;
+	if (curcopy || (status =
+	    __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
+		F_SET(c, CURS_ACQUIRE);
+		return (RET_SUCCESS);
+	}
+	return (status);
+}
+
+/*
+ * __bt_relink --
+ *	Link around a deleted page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to be deleted
+ */
+static int
+__bt_relink(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	PAGE *pg;
+
+	if (h->nextpg != P_INVALID) {
+		if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+			return (RET_ERROR);
+		pg->prevpg = h->prevpg;
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+	}
+	if (h->prevpg != P_INVALID) {
+		if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+			return (RET_ERROR);
+		pg->nextpg = h->nextpg;
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+	}
+	return (0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_get.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_get.c
new file mode 100644
index 000000000..b6318211a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_get.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_get.c	8.6 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+/*
+ * __BT_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to find
+ *	data:	data to return
+ *	flag:	currently unused
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__bt_get(dbp, key, data, flags)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	int exact, status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Get currently doesn't take any flags. */
+	if (flags) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if ((e = __bt_search(t, key, &exact)) == NULL)
+		return (RET_ERROR);
+	if (!exact) {
+		mpool_put(t->bt_mp, e->page, 0);
+		return (RET_SPECIAL);
+	}
+
+	status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0);
+
+	/*
+	 * If the user is doing concurrent access, we copied the
+	 * key/data, toss the page.
+	 */
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_open.c
new file mode 100644
index 000000000..3e4c67a4b
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_open.c
@@ -0,0 +1,476 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_open.c	8.11 (Berkeley) 11/2/95";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Implementation of btree access method for 4.4BSD.
+ *
+ * The design here was originally based on that of the btree access method
+ * used in the Postgres database system at UC Berkeley.  This implementation
+ * is wholly independent of the Postgres code.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+#ifdef DEBUG
+#undef	MINPSIZE
+#define	MINPSIZE	128
+#endif
+
+static int byteorder __P((void));
+static int nroot __P((BTREE *));
+static int tmp __P((void));
+
+/*
+ * __BT_OPEN -- Open a btree.
+ *
+ * Creates and fills a DB struct, and calls the routine that actually
+ * opens the btree.
+ *
+ * Parameters:
+ *	fname:	filename (NULL for in-memory trees)
+ *	flags:	open flag bits
+ *	mode:	open permission bits
+ *	b:	BTREEINFO pointer
+ *
+ * Returns:
+ *	NULL on failure, pointer to DB on success.
+ *
+ */
+DB *
+__bt_open(fname, flags, mode, openinfo, dflags)
+	const char *fname;
+	int flags, mode, dflags;
+	const BTREEINFO *openinfo;
+{
+	struct stat sb;
+	BTMETA m;
+	BTREE *t;
+	BTREEINFO b;
+	DB *dbp;
+	db_pgno_t ncache;
+	ssize_t nr;
+	int machine_lorder;
+
+	t = NULL;
+
+	/*
+	 * Intention is to make sure all of the user's selections are okay
+	 * here and then use them without checking.  Can't be complete, since
+	 * we don't know the right page size, lorder or flags until the backing
+	 * file is opened.  Also, the file's page size can cause the cachesize
+	 * to change.
+	 */
+	machine_lorder = byteorder();
+	if (openinfo) {
+		b = *openinfo;
+
+		/* Flags: R_DUP. */
+		if (b.flags & ~(R_DUP))
+			goto einval;
+
+		/*
+		 * Page size must be indx_t aligned and >= MINPSIZE.  Default
+		 * page size is set farther on, based on the underlying file
+		 * transfer size.
+		 */
+		if (b.psize &&
+		    (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
+		    b.psize & (sizeof(indx_t) - 1)))
+			goto einval;
+
+		/* Minimum number of keys per page; absolute minimum is 2. */
+		if (b.minkeypage) {
+			if (b.minkeypage < 2)
+				goto einval;
+		} else
+			b.minkeypage = DEFMINKEYPAGE;
+
+		/* If no comparison, use default comparison and prefix. */
+		if (b.compare == NULL) {
+			b.compare = __bt_defcmp;
+			if (b.prefix == NULL)
+				b.prefix = __bt_defpfx;
+		}
+
+		if (b.lorder == 0)
+			b.lorder = machine_lorder;
+	} else {
+		b.compare = __bt_defcmp;
+		b.cachesize = 0;
+		b.flags = 0;
+		b.lorder = machine_lorder;
+		b.minkeypage = DEFMINKEYPAGE;
+		b.prefix = __bt_defpfx;
+		b.psize = 0;
+	}
+
+	/* Check for the ubiquitous PDP-11. */
+	if (b.lorder != DB_BIG_ENDIAN && b.lorder != DB_LITTLE_ENDIAN)
+		goto einval;
+
+	/* Allocate and initialize DB and BTREE structures. */
+	if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL)
+		goto err;
+	memset(t, 0, sizeof(BTREE));
+	t->bt_fd = -1;			/* Don't close unopened fd on error. */
+	t->bt_lorder = b.lorder;
+	t->bt_order = NOT;
+	t->bt_cmp = b.compare;
+	t->bt_pfx = b.prefix;
+	t->bt_rfd = -1;
+
+	if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL)
+		goto err;
+	memset(t->bt_dbp, 0, sizeof(DB));
+	if (t->bt_lorder != machine_lorder)
+		F_SET(t, B_NEEDSWAP);
+
+	dbp->type = DB_BTREE;
+	dbp->internal = t;
+	dbp->close = __bt_close;
+	dbp->del = __bt_delete;
+	dbp->fd = __bt_fd;
+	dbp->get = __bt_get;
+	dbp->put = __bt_put;
+	dbp->seq = __bt_seq;
+	dbp->sync = __bt_sync;
+
+	/*
+	 * If no file name was supplied, this is an in-memory btree and we
+	 * open a backing temporary file.  Otherwise, it's a disk-based tree.
+	 */
+	if (fname) {
+		switch (flags & O_ACCMODE) {
+		case O_RDONLY:
+			F_SET(t, B_RDONLY);
+			break;
+		case O_RDWR:
+			break;
+		case O_WRONLY:
+		default:
+			goto einval;
+		}
+		
+		if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0)
+			goto err;
+
+	} else {
+		if ((flags & O_ACCMODE) != O_RDWR)
+			goto einval;
+		if ((t->bt_fd = tmp()) == -1)
+			goto err;
+		F_SET(t, B_INMEM);
+	}
+
+	if (fcntl(t->bt_fd, F_SETFD, 1) == -1)
+		goto err;
+
+	if (fstat(t->bt_fd, &sb))
+		goto err;
+	if (sb.st_size) {
+		if ((nr = read(t->bt_fd, &m, sizeof(BTMETA))) < 0)
+			goto err;
+		if (nr != sizeof(BTMETA))
+			goto eftype;
+
+		/*
+		 * Read in the meta-data.  This can change the notion of what
+		 * the lorder, page size and flags are, and, when the page size
+		 * changes, the cachesize value can change too.  If the user
+		 * specified the wrong byte order for an existing database, we
+		 * don't bother to return an error, we just clear the NEEDSWAP
+		 * bit.
+		 */
+		if (m.magic == BTREEMAGIC)
+			F_CLR(t, B_NEEDSWAP);
+		else {
+			F_SET(t, B_NEEDSWAP);
+			M_32_SWAP(m.magic);
+			M_32_SWAP(m.version);
+			M_32_SWAP(m.psize);
+			M_32_SWAP(m.free);
+			M_32_SWAP(m.nrecs);
+			M_32_SWAP(m.flags);
+		}
+		if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
+			goto eftype;
+		if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
+		    m.psize & (sizeof(indx_t) - 1))
+			goto eftype;
+		if (m.flags & ~SAVEMETA)
+			goto eftype;
+		b.psize = m.psize;
+		F_SET(t, m.flags);
+		t->bt_free = m.free;
+		t->bt_nrecs = m.nrecs;
+	} else {
+		/*
+		 * Set the page size to the best value for I/O to this file.
+		 * Don't overflow the page offset type.
+		 */
+		if (b.psize == 0) {
+			b.psize = sb.st_blksize;
+			if (b.psize < MINPSIZE)
+				b.psize = MINPSIZE;
+			if (b.psize > MAX_PAGE_OFFSET + 1)
+				b.psize = MAX_PAGE_OFFSET + 1;
+		}
+
+		/* Set flag if duplicates permitted. */
+		if (!(b.flags & R_DUP))
+			F_SET(t, B_NODUPS);
+
+		t->bt_free = P_INVALID;
+		t->bt_nrecs = 0;
+		F_SET(t, B_METADIRTY);
+	}
+
+	t->bt_psize = b.psize;
+
+	/* Set the cache size; must be a multiple of the page size. */
+	if (b.cachesize && b.cachesize & (b.psize - 1))
+		b.cachesize += (~b.cachesize & (b.psize - 1)) + 1;
+	if (b.cachesize < b.psize * MINCACHE)
+		b.cachesize = b.psize * MINCACHE;
+
+	/* Calculate number of pages to cache. */
+	ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;
+
+	/*
+	 * The btree data structure requires that at least two keys can fit on
+	 * a page, but other than that there's no fixed requirement.  The user
+	 * specified a minimum number per page, and we translated that into the
+	 * number of bytes a key/data pair can use before being placed on an
+	 * overflow page.  This calculation includes the page header, the size
+	 * of the index referencing the leaf item and the size of the leaf item
+	 * structure.  Also, don't let the user specify a minkeypage such that
+	 * a key/data pair won't fit even if both key and data are on overflow
+	 * pages.
+	 */
+	t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
+	    (sizeof(indx_t) + NBLEAFDBT(0, 0));
+	if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
+		t->bt_ovflsize =
+		    NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);
+
+	/* Initialize the buffer pool. */
+	if ((t->bt_mp =
+	    mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
+		goto err;
+	if (!F_ISSET(t, B_INMEM))
+		mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
+
+	/* Create a root page if new tree. */
+	if (nroot(t) == RET_ERROR)
+		goto err;
+
+	/* Global flags. */
+	if (dflags & DB_LOCK)
+		F_SET(t, B_DB_LOCK);
+	if (dflags & DB_SHMEM)
+		F_SET(t, B_DB_SHMEM);
+	if (dflags & DB_TXN)
+		F_SET(t, B_DB_TXN);
+
+	return (dbp);
+
+einval:	errno = EINVAL;
+	goto err;
+
+eftype:	errno = EFTYPE;
+	goto err;
+
+err:	if (t) {
+		if (t->bt_dbp)
+			free(t->bt_dbp);
+		if (t->bt_fd != -1)
+			(void)close(t->bt_fd);
+		free(t);
+	}
+	return (NULL);
+}
+
+/*
+ * NROOT -- Create the root of a new tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+nroot(t)
+	BTREE *t;
+{
+	PAGE *meta, *root;
+	db_pgno_t npg;
+
+	if ((root = mpool_get(t->bt_mp, 1, 0)) != NULL) {
+		if (root->lower == 0 &&
+		    root->pgno == 0 &&
+		    root->linp[0] == 0) {
+			mpool_delete(t->bt_mp, root);
+			errno = EINVAL;
+		} else {
+			mpool_put(t->bt_mp, root, 0);
+			return (RET_SUCCESS);
+		}
+	}
+	if (errno != EINVAL)		/* It's OK to not exist. */
+		return (RET_ERROR);
+	errno = 0;
+
+	if ((meta = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
+		return (RET_ERROR);
+
+	if ((root = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
+		return (RET_ERROR);
+
+	if (npg != P_ROOT)
+		return (RET_ERROR);
+	root->pgno = npg;
+	root->prevpg = root->nextpg = P_INVALID;
+	root->lower = BTDATAOFF;
+	root->upper = t->bt_psize;
+	root->flags = P_BLEAF;
+	memset(meta, 0, t->bt_psize);
+	mpool_put(t->bt_mp, meta, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, root, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+static int
+tmp()
+{
+#ifdef SIG_BLOCK
+	sigset_t set, oset;
+#else
+	int oset;
+#endif
+	int fd;
+	char *envtmp;
+	char path[MAXPATHLEN];
+	static char fn[] = "/bt.XXXXXX";
+
+	envtmp = getenv("TMPDIR");
+
+	/* this used to be done with snprintf(), but since snprintf
+	   isn't in most operating systems, and overflow checking in
+	   this case is easy, this is what is done */
+
+	if (envtmp && ((strlen(envtmp)+sizeof(fn)+1) > sizeof(path)))
+	    return(-1);
+
+	(void)sprintf(path, "%s%s", (envtmp ? envtmp : "/tmp"), fn);
+
+#ifdef SIG_BLOCK
+	(void)sigfillset(&set);
+	(void)sigprocmask(SIG_BLOCK, &set, &oset);
+#else
+	oset = sigblock(~0);
+#endif
+	if ((fd = mkstemp(path)) != -1)
+		(void)unlink(path);
+#ifdef SIG_BLOCK
+	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
+#else
+	sigsetmask(oset);
+#endif
+#ifdef __CYGWIN32__
+      /* Ensure the fd is in binary mode. */
+      setmode(fd, O_BINARY);
+#endif /* __CYGWIN32__ */
+
+	return(fd);
+}
+
+static int
+byteorder()
+{
+	u_int32_t x;
+	u_char *p;
+
+	x = 0x01020304;
+	p = (u_char *)&x;
+	switch (*p) {
+	case 1:
+		return (DB_BIG_ENDIAN);
+	case 4:
+		return (DB_LITTLE_ENDIAN);
+	default:
+		return (0);
+	}
+}
+
+int
+__bt_fd(dbp)
+        const DB *dbp;
+{
+	BTREE *t;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* In-memory database can't have a file descriptor. */
+	if (F_ISSET(t, B_INMEM)) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (t->bt_fd);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_overflow.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_overflow.c
new file mode 100644
index 000000000..8b1f59791
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_overflow.c
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_overflow.c	8.5 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+/*
+ * Big key/data code.
+ *
+ * Big key and data entries are stored on linked lists of pages.  The initial
+ * reference is byte string stored with the key or data and is the page number
+ * and size.  The actual record is stored in a chain of pages linked by the
+ * nextpg field of the PAGE header.
+ *
+ * The first page of the chain has a special property.  If the record is used
+ * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
+ * in the header.
+ *
+ * XXX
+ * A single DBT is written to each chain, so a lot of space on the last page
+ * is wasted.  This is a fairly major bug for some data sets.
+ */
+
+/*
+ * __OVFL_GET -- Get an overflow key/data item.
+ *
+ * Parameters:
+ *	t:	tree
+ *	p:	pointer to { db_pgno_t, u_int32_t }
+ *	buf:	storage address
+ *	bufsz:	storage size
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_get(t, p, ssz, buf, bufsz)
+	BTREE *t;
+	void *p;
+	size_t *ssz;
+	void **buf;
+	size_t *bufsz;
+{
+	PAGE *h;
+	db_pgno_t pg;
+	size_t nb, plen;
+	u_int32_t sz;
+
+	memmove(&pg, p, sizeof(db_pgno_t));
+	memmove(&sz, (char *)p + sizeof(db_pgno_t), sizeof(u_int32_t));
+	*ssz = sz;
+
+#ifdef DEBUG
+	if (pg == P_INVALID || sz == 0)
+		abort();
+#endif
+	/* Make the buffer bigger as necessary. */
+	if (*bufsz < sz) {
+		*buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz));
+		if (*buf == NULL)
+			return (RET_ERROR);
+		*bufsz = sz;
+	}
+
+	/*
+	 * Step through the linked list of pages, copying the data on each one
+	 * into the buffer.  Never copy more than the data's length.
+	 */
+	plen = t->bt_psize - BTDATAOFF;
+	for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+
+		nb = MIN(sz, plen);
+		memmove(p, (char *)h + BTDATAOFF, nb);
+		mpool_put(t->bt_mp, h, 0);
+
+		if ((sz -= nb) == 0)
+			break;
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_PUT -- Store an overflow key/data item.
+ *
+ * Parameters:
+ *	t:	tree
+ *	data:	DBT to store
+ *	pgno:	storage page number
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_put(t, dbt, pg)
+	BTREE *t;
+	const DBT *dbt;
+	db_pgno_t *pg;
+{
+	PAGE *h, *last;
+	void *p;
+	db_pgno_t npg;
+	size_t nb, plen;
+	u_int32_t sz;
+
+	/*
+	 * Allocate pages and copy the key/data record into them.  Store the
+	 * number of the first page in the chain.
+	 */
+	plen = t->bt_psize - BTDATAOFF;
+	for (last = NULL, p = dbt->data, sz = dbt->size;;
+	    p = (char *)p + plen, last = h) {
+		if ((h = __bt_new(t, &npg)) == NULL)
+			return (RET_ERROR);
+
+		h->pgno = npg;
+		h->nextpg = h->prevpg = P_INVALID;
+		h->flags = P_OVERFLOW;
+		h->lower = h->upper = 0;
+
+		nb = MIN(sz, plen);
+		memmove((char *)h + BTDATAOFF, p, nb);
+
+		if (last) {
+			last->nextpg = h->pgno;
+			mpool_put(t->bt_mp, last, MPOOL_DIRTY);
+		} else
+			*pg = h->pgno;
+
+		if ((sz -= nb) == 0) {
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		}
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_DELETE -- Delete an overflow chain.
+ *
+ * Parameters:
+ *	t:	tree
+ *	p:	pointer to { db_pgno_t, u_int32_t }
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_delete(t, p)
+	BTREE *t;
+	void *p;
+{
+	PAGE *h;
+	db_pgno_t pg;
+	size_t plen;
+	u_int32_t sz;
+
+	memmove(&pg, p, sizeof(db_pgno_t));
+	memmove(&sz, (char *)p + sizeof(db_pgno_t), sizeof(u_int32_t));
+
+#ifdef DEBUG
+	if (pg == P_INVALID || sz == 0)
+		abort();
+#endif
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+		return (RET_ERROR);
+
+	/* Don't delete chains used by internal pages. */
+	if (h->flags & P_PRESERVE) {
+		mpool_put(t->bt_mp, h, 0);
+		return (RET_SUCCESS);
+	}
+
+	/* Step through the chain, calling the free routine for each page. */
+	for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
+		pg = h->nextpg;
+		__bt_free(t, h);
+		if (sz <= plen)
+			break;
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+	}
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_page.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_page.c
new file mode 100644
index 000000000..3663cf7f9
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_page.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_page.c	8.4 (Berkeley) 11/2/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+/*
+ * __bt_free --
+ *	Put a page on the freelist.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to free
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ *
+ * Side-effect:
+ *	mpool_put's the page.
+ */
+int
+__bt_free(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	/* Insert the page at the head of the free list. */
+	h->prevpg = P_INVALID;
+	h->nextpg = t->bt_free;
+	t->bt_free = h->pgno;
+	F_SET(t, B_METADIRTY);
+
+	/* Make sure the page gets written back. */
+	return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
+}
+
+/*
+ * __bt_new --
+ *	Get a new page, preferably from the freelist.
+ *
+ * Parameters:
+ *	t:	tree
+ *	npg:	storage for page number.
+ *
+ * Returns:
+ *	Pointer to a page, NULL on error.
+ */
+PAGE *
+__bt_new(t, npg)
+	BTREE *t;
+	db_pgno_t *npg;
+{
+	PAGE *h;
+
+	if (t->bt_free != P_INVALID &&
+	    (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
+		*npg = t->bt_free;
+		t->bt_free = h->nextpg;
+		F_SET(t, B_METADIRTY);
+		return (h);
+	}
+	return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT));
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_put.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_put.c
new file mode 100644
index 000000000..f75ca9295
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_put.c
@@ -0,0 +1,328 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_put.c	8.8 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+static EPG *bt_fast __P((BTREE *, const DBT *, const DBT *, int *));
+
+/*
+ * __BT_PUT -- Add a btree item to the tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key
+ *	data:	data
+ *	flag:	R_NOOVERWRITE
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
+ *	tree and R_NOOVERWRITE specified.
+ */
+int
+__bt_put(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	DBT tkey, tdata;
+	EPG *e = 0;
+	PAGE *h;
+	indx_t idx, nxtindex;
+	db_pgno_t pg;
+	u_int32_t nbytes;
+	int dflags, exact, status;
+	char *dest, db[NOVFLSIZE], kb[NOVFLSIZE];
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Check for change to a read-only tree. */
+	if (F_ISSET(t, B_RDONLY)) {
+		errno = EPERM;
+		return (RET_ERROR);
+	}
+
+	switch (flags) {
+	case 0:
+	case R_NOOVERWRITE:
+		break;
+	case R_CURSOR:
+		/*
+		 * If flags is R_CURSOR, put the cursor.  Must already
+		 * have started a scan and not have already deleted it.
+		 */
+		if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+		    !F_ISSET(&t->bt_cursor,
+		        CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+			break;
+		/* FALLTHROUGH */
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * If the key/data pair won't fit on a page, store it on overflow
+	 * pages.  Only put the key on the overflow page if the pair are
+	 * still too big after moving the data to an overflow page.
+	 *
+	 * XXX
+	 * If the insert fails later on, the overflow pages aren't recovered.
+	 */
+	dflags = 0;
+	if (key->size + data->size > t->bt_ovflsize) {
+		if (key->size > t->bt_ovflsize) {
+			u_int32_t yuck_this_is_gross_code;
+storekey:		if (__ovfl_put(t, key, &pg) == RET_ERROR)
+				return (RET_ERROR);
+			tkey.data = kb;
+			tkey.size = NOVFLSIZE;
+			memmove(kb, &pg, sizeof(db_pgno_t));
+			yuck_this_is_gross_code = key->size;
+			if (yuck_this_is_gross_code != key->size)
+				abort ();
+			memmove(kb + sizeof(db_pgno_t),
+				&yuck_this_is_gross_code, sizeof(u_int32_t));
+			dflags |= P_BIGKEY;
+			key = &tkey;
+		}
+		if (key->size + data->size > t->bt_ovflsize) {
+			u_int32_t yuck_this_is_gross_code = data->size;
+			if (__ovfl_put(t, data, &pg) == RET_ERROR)
+				return (RET_ERROR);
+			tdata.data = db;
+			tdata.size = NOVFLSIZE;
+			memmove(db, &pg, sizeof(db_pgno_t));
+			if (yuck_this_is_gross_code != data->size)
+				abort ();
+			memmove(db + sizeof(db_pgno_t),
+				&yuck_this_is_gross_code, sizeof(u_int32_t));
+			dflags |= P_BIGDATA;
+			data = &tdata;
+		}
+		if (key->size + data->size > t->bt_ovflsize)
+			goto storekey;
+	}
+
+	/* Replace the cursor. */
+	if (flags == R_CURSOR) {
+		if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
+			return (RET_ERROR);
+		idx = t->bt_cursor.pg.index;
+		goto delete;
+	}
+
+	/*
+	 * Find the key to delete, or, the location at which to insert.
+	 * Bt_fast and __bt_search both pin the returned page.
+	 */
+	if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL)
+		if ((e = __bt_search(t, key, &exact)) == NULL)
+			return (RET_ERROR);
+	h = e->page;
+	idx = e->index;
+
+	/*
+	 * Add the key/data pair to the tree.  If an identical key is already
+	 * in the tree, and R_NOOVERWRITE is set, an error is returned.  If
+	 * R_NOOVERWRITE is not set, the key is either added (if duplicates are
+	 * permitted) or an error is returned.
+	 */
+	switch (flags) {
+	case R_NOOVERWRITE:
+		if (!exact)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+		return (RET_SPECIAL);
+	default:
+		if (!exact || !F_ISSET(t, B_NODUPS))
+			break;
+		/*
+		 * !!!
+		 * Note, the delete may empty the page, so we need to put a
+		 * new entry into the page immediately.
+		 */
+delete:		if (__bt_dleaf(t, key, h, idx) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		break;
+	}
+
+	/*
+	 * If not enough room, or the user has put a ceiling on the number of
+	 * keys permitted in the page, split the page.  The split code will
+	 * insert the key and data and unpin the current page.  If inserting
+	 * into the offset array, shift the pointers up.
+	 */
+	nbytes = NBLEAFDBT(key->size, data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+		if ((status = __bt_split(t, h, key,
+		    data, dflags, nbytes, idx)) != RET_SUCCESS)
+			return (status);
+		goto success;
+	}
+
+	if (idx < (nxtindex = NEXTINDEX(h)))
+		memmove(h->linp + idx + 1, h->linp + idx,
+		    (nxtindex - idx) * sizeof(indx_t));
+	h->lower += sizeof(indx_t);
+
+	h->linp[idx] = h->upper -= nbytes;
+	dest = (char *)h + h->upper;
+	WR_BLEAF(dest, key, data, dflags);
+
+	/* If the cursor is on this page, adjust it as necessary. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= idx)
+		++t->bt_cursor.pg.index;
+
+	if (t->bt_order == NOT) {
+		if (h->nextpg == P_INVALID) {
+			if (idx == NEXTINDEX(h) - 1) {
+				t->bt_order = FORWARD;
+				t->bt_last.index = idx;
+				t->bt_last.pgno = h->pgno;
+			}
+		} else if (h->prevpg == P_INVALID) {
+			if (idx == 0) {
+				t->bt_order = BACK;
+				t->bt_last.index = 0;
+				t->bt_last.pgno = h->pgno;
+			}
+		}
+	}
+
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+success:
+	if (flags == R_SETCURSOR)
+		__bt_setcur(t, e->page->pgno, e->index);
+
+	F_SET(t, B_MODIFIED);
+	return (RET_SUCCESS);
+}
+
+#ifdef STATISTICS
+u_long bt_cache_hit, bt_cache_miss;
+#endif
+
+/*
+ * BT_FAST -- Do a quick check for sorted data.
+ *
+ * Parameters:
+ *	t:	tree
+ *	key:	key to insert
+ *
+ * Returns:
+ * 	EPG for new record or NULL if not found.
+ */
+static EPG *
+bt_fast(t, key, data, exactp)
+	BTREE *t;
+	const DBT *key, *data;
+	int *exactp;
+{
+	PAGE *h;
+	u_int32_t nbytes;
+	int cmp;
+
+	if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) {
+		t->bt_order = NOT;
+		return (NULL);
+	}
+	t->bt_cur.page = h;
+	t->bt_cur.index = t->bt_last.index;
+
+	/*
+	 * If won't fit in this page or have too many keys in this page,
+	 * have to search to get split stack.
+	 */
+	nbytes = NBLEAFDBT(key->size, data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t))
+		goto miss;
+
+	if (t->bt_order == FORWARD) {
+		if (t->bt_cur.page->nextpg != P_INVALID)
+			goto miss;
+		if (t->bt_cur.index != NEXTINDEX(h) - 1)
+			goto miss;
+		if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0)
+			goto miss;
+		t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index;
+	} else {
+		if (t->bt_cur.page->prevpg != P_INVALID)
+			goto miss;
+		if (t->bt_cur.index != 0)
+			goto miss;
+		if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0)
+			goto miss;
+		t->bt_last.index = 0;
+	}
+	*exactp = cmp == 0;
+#ifdef STATISTICS
+	++bt_cache_hit;
+#endif
+	return (&t->bt_cur);
+
+miss:
+#ifdef STATISTICS
+	++bt_cache_miss;
+#endif
+	t->bt_order = NOT;
+	mpool_put(t->bt_mp, h, 0);
+	return (NULL);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_search.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_search.c
new file mode 100644
index 000000000..de7ab126f
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_search.c
@@ -0,0 +1,297 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_search.c	8.9 (Berkeley) 10/26/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+static int __bt_snext __P((BTREE *, PAGE *, const DBT *, int *));
+static int __bt_sprev __P((BTREE *, PAGE *, const DBT *, int *));
+
+/*
+ * __bt_search --
+ *	Search a btree for a key.
+ *
+ * Parameters:
+ *	t:	tree to search
+ *	key:	key to find
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	The EPG for matching record, if any, or the EPG for the location
+ *	of the key, if it were inserted into the tree, is entered into
+ *	the bt_cur field of the tree.  A pointer to the field is returned.
+ */
+EPG *
+__bt_search(t, key, exactp)
+	BTREE *t;
+	const DBT *key;
+	int *exactp;
+{
+	PAGE *h;
+	indx_t base, idx, lim;
+	db_pgno_t pg;
+	int cmp;
+
+	BT_CLR(t);
+	for (pg = P_ROOT;;) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (NULL);
+
+		/* Do a binary search on the current page. */
+		t->bt_cur.page = h;
+		for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
+			t->bt_cur.index = idx = base + (lim >> 1);
+			if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
+				if (h->flags & P_BLEAF) {
+					*exactp = 1;
+					return (&t->bt_cur);
+				}
+				goto next;
+			}
+			if (cmp > 0) {
+				base = idx + 1;
+				--lim;
+			}
+		}
+
+		/*
+		 * If it's a leaf page, we're almost done.  If no duplicates
+		 * are allowed, or we have an exact match, we're done.  Else,
+		 * it's possible that there were matching keys on this page,
+		 * which later deleted, and we're on a page with no matches
+		 * while there are matches on other pages.  If at the start or
+		 * end of a page, check the adjacent page.
+		 */
+		if (h->flags & P_BLEAF) {
+			if (!F_ISSET(t, B_NODUPS)) {
+				if (base == 0 &&
+				    h->prevpg != P_INVALID &&
+				    __bt_sprev(t, h, key, exactp))
+					return (&t->bt_cur);
+				if (base == NEXTINDEX(h) &&
+				    h->nextpg != P_INVALID &&
+				    __bt_snext(t, h, key, exactp))
+					return (&t->bt_cur);
+			}
+			*exactp = 0;
+			t->bt_cur.index = base;
+			return (&t->bt_cur);
+		}
+
+		/*
+		 * No match found.  Base is the smallest index greater than
+		 * key and may be zero or a last + 1 index.  If it's non-zero,
+		 * decrement by one, and record the internal page which should
+		 * be a parent page for the key.  If a split later occurs, the
+		 * inserted page will be to the right of the saved page.
+		 */
+		idx = base ? base - 1 : base;
+
+next:		BT_PUSH(t, h->pgno, idx);
+		pg = GETBINTERNAL(h, idx)->pgno;
+		mpool_put(t->bt_mp, h, 0);
+	}
+}
+
+/*
+ * __bt_snext --
+ *	Check for an exact match after the key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	current page
+ *	key:	key
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	If an exact match found.
+ */
+static int
+__bt_snext(t, h, key, exactp)
+	BTREE *t;
+	PAGE *h;
+	const DBT *key;
+	int *exactp;
+{
+	BINTERNAL *bi;
+	EPG e;
+	EPGNO *parent;
+	indx_t idx;
+	db_pgno_t pgno;
+	int level;
+
+	/*
+	 * Get the next page.  The key is either an exact
+	 * match, or not as good as the one we already have.
+	 */
+	if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+		return (0);
+	e.index = 0;
+	if (__bt_cmp(t, key, &e) != 0) {
+		mpool_put(t->bt_mp, e.page, 0);
+		return (0);
+	}
+	mpool_put(t->bt_mp, h, 0);
+	t->bt_cur = e;
+	*exactp = 1;
+
+	/*
+	 * Adjust the stack for the movement.
+	 *
+	 * Move up the stack.
+	 */
+	for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+		/* Get the parent page. */
+		if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			return (0);
+
+		/* Move to the next index. */
+		if (parent->index != NEXTINDEX(h) - 1) {
+			idx = parent->index + 1;
+			BT_PUSH(t, h->pgno, idx);
+			break;
+		}
+		mpool_put(t->bt_mp, h, 0);
+	}
+
+	/* Restore the stack. */
+	while (level--) {
+		/* Push the next level down onto the stack. */
+		bi = GETBINTERNAL(h, idx);
+		pgno = bi->pgno;
+		BT_PUSH(t, pgno, 0);
+
+		/* Lose the currently pinned page. */
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Get the next level down. */
+		if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+			return (0);
+		idx = 0;
+	}
+	mpool_put(t->bt_mp, h, 0);
+	return (1);
+}
+
+/*
+ * __bt_sprev --
+ *	Check for an exact match before the key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	current page
+ *	key:	key
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	If an exact match found.
+ */
+static int
+__bt_sprev(t, h, key, exactp)
+	BTREE *t;
+	PAGE *h;
+	const DBT *key;
+	int *exactp;
+{
+	BINTERNAL *bi;
+	EPG e;
+	EPGNO *parent;
+	indx_t idx;
+	db_pgno_t pgno;
+	int level;
+
+	/*
+	 * Get the previous page.  The key is either an exact
+	 * match, or not as good as the one we already have.
+	 */
+	if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+		return (0);
+	e.index = NEXTINDEX(e.page) - 1;
+	if (__bt_cmp(t, key, &e) != 0) {
+		mpool_put(t->bt_mp, e.page, 0);
+		return (0);
+	}
+
+	mpool_put(t->bt_mp, h, 0);
+	t->bt_cur = e;
+	*exactp = 1;
+
+	/*
+	 * Adjust the stack for the movement.
+	 *
+	 * Move up the stack.
+	 */
+	for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+		/* Get the parent page. */
+		if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			return (1);
+
+		/* Move to the next index. */
+		if (parent->index != 0) {
+			idx = parent->index - 1;
+			BT_PUSH(t, h->pgno, idx);
+			break;
+		}
+		mpool_put(t->bt_mp, h, 0);
+	}
+
+	/* Restore the stack. */
+	while (level--) {
+		/* Push the next level down onto the stack. */
+		bi = GETBINTERNAL(h, idx);
+		pgno = bi->pgno;
+
+		/* Lose the currently pinned page. */
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Get the next level down. */
+		if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+			return (1);
+
+		idx = NEXTINDEX(h) - 1;
+		BT_PUSH(t, pgno, idx);
+	}
+	mpool_put(t->bt_mp, h, 0);
+	return (1);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_seq.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_seq.c
new file mode 100644
index 000000000..bbfb9c6c6
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_seq.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_seq.c	8.9 (Berkeley) 6/20/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+static int __bt_first __P((BTREE *, const DBT *, EPG *, int *));
+static int __bt_seqadv __P((BTREE *, EPG *, int));
+static int __bt_seqset __P((BTREE *, EPG *, DBT *, int));
+
+/*
+ * Sequential scan support.
+ *
+ * The tree can be scanned sequentially, starting from either end of the
+ * tree or from any specific key.  A scan request before any scanning is
+ * done is initialized as starting from the least node.
+ */
+
+/*
+ * __bt_seq --
+ *	Btree sequential scan interface.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key for positioning and return value
+ *	data:	data return value
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__bt_seq(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG e;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/*
+	 * If scan unitialized as yet, or starting at a specific record, set
+	 * the scan to a specific key.  Both __bt_seqset and __bt_seqadv pin
+	 * the page the cursor references if they're successful.
+	 */
+	switch (flags) {
+	case R_NEXT:
+	case R_PREV:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			status = __bt_seqadv(t, &e, flags);
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_FIRST:
+	case R_LAST:
+	case R_CURSOR:
+		status = __bt_seqset(t, &e, key, flags);
+		break;
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (status == RET_SUCCESS) {
+		__bt_setcur(t, e.page->pgno, e.index);
+
+		status =
+		    __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
+
+		/*
+		 * If the user is doing concurrent access, we copied the
+		 * key/data, toss the page.
+		 */
+		if (F_ISSET(t, B_DB_LOCK))
+			mpool_put(t->bt_mp, e.page, 0);
+		else
+			t->bt_pinned = e.page;
+	}
+	return (status);
+}
+
+/*
+ * __bt_seqset --
+ *	Set the sequential scan to a specific key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	ep:	storage for returned key
+ *	key:	key for initial scan position
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the cursor references.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqset(t, ep, key, flags)
+	BTREE *t;
+	EPG *ep;
+	DBT *key;
+	int flags;
+{
+	PAGE *h;
+	db_pgno_t pg;
+	int exact;
+
+	/*
+	 * Find the first, last or specific key in the tree and point the
+	 * cursor at it.  The cursor may not be moved until a new key has
+	 * been found.
+	 */
+	switch (flags) {
+	case R_CURSOR:				/* Keyed scan. */
+		/*
+		 * Find the first instance of the key or the smallest key
+		 * which is greater than or equal to the specified key.
+		 */
+		if (key->data == NULL || key->size == 0) {
+			errno = EINVAL;
+			return (RET_ERROR);
+		}
+		return (__bt_first(t, key, ep, &exact));
+	case R_FIRST:				/* First record. */
+	case R_NEXT:
+		/* Walk down the left-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, 0)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+		}
+		ep->page = h;
+		ep->index = 0;
+		break;
+	case R_LAST:				/* Last record. */
+	case R_PREV:
+		/* Walk down the right-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		ep->page = h;
+		ep->index = NEXTINDEX(h) - 1;
+		break;
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_seqadvance --
+ *	Advance the sequential scan.
+ *
+ * Parameters:
+ *	t:	tree
+ *	flags:	R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the new key/data record is on.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqadv(t, ep, flags)
+	BTREE *t;
+	EPG *ep;
+	int flags;
+{
+	CURSOR *c;
+	PAGE *h;
+	indx_t idx;
+	db_pgno_t pg;
+	int exact, rval;
+
+	/*
+	 * There are a couple of states that we can be in.  The cursor has
+	 * been initialized by the time we get here, but that's all we know.
+	 */
+	c = &t->bt_cursor;
+
+	/*
+	 * The cursor was deleted and there weren't any duplicate records,
+	 * so the cursor's key was saved.  Find out where that key would
+	 * be in the current tree.  If the returned key is an exact match,
+	 * it means that a key/data pair was inserted into the tree after
+	 * the delete.  We could reasonably return the key, but the problem
+	 * is that this is the access pattern we'll see if the user is
+	 * doing seq(..., R_NEXT)/put(..., 0) pairs, i.e. the put deletes
+	 * the cursor record and then replaces it, so the cursor was saved,
+	 * and we'll simply return the same "new" record until the user
+	 * notices and doesn't do a put() of it.  Since the key is an exact
+	 * match, we could as easily put the new record before the cursor,
+	 * and we've made no guarantee to return it.  So, move forward or
+	 * back a record if it's an exact match.
+	 *
+	 * XXX
+	 * In the current implementation, put's to the cursor are done with
+	 * delete/add pairs.  This has two consequences.  First, it means
+	 * that seq(..., R_NEXT)/put(..., R_CURSOR) pairs are going to exhibit
+	 * the same behavior as above.  Second, you can return the same key
+	 * twice if you have duplicate records.  The scenario is that the
+	 * cursor record is deleted, moving the cursor forward or backward
+	 * to a duplicate.  The add then inserts the new record at a location
+	 * ahead of the cursor because duplicates aren't sorted in any way,
+	 * and the new record is later returned.  This has to be fixed at some
+	 * point.
+	 */
+	if (F_ISSET(c, CURS_ACQUIRE)) {
+		if ((rval = __bt_first(t, &c->key, ep, &exact)) == RET_ERROR)
+			return (RET_ERROR);
+		if (!exact)
+			return (rval);
+		/*
+		 * XXX
+		 * Kluge -- get, release, get the page.
+		 */
+		c->pg.pgno = ep->page->pgno;
+		c->pg.index = ep->index;
+		mpool_put(t->bt_mp, ep->page, 0);
+	}
+
+	/* Get the page referenced by the cursor. */
+	if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+		return (RET_ERROR);
+
+	/*
+ 	 * Find the next/previous record in the tree and point the cursor at
+	 * it.  The cursor may not be moved until a new key has been found.
+	 */
+	switch (flags) {
+	case R_NEXT:			/* Next record. */
+		/*
+		 * The cursor was deleted in duplicate records, and moved
+		 * forward to a record that has yet to be returned.  Clear
+		 * that flag, and return the record.
+		 */
+		if (F_ISSET(c, CURS_AFTER))
+			goto usecurrent;
+		idx = c->pg.index;
+		if (++idx == NEXTINDEX(h)) {
+			pg = h->nextpg;
+			mpool_put(t->bt_mp, h, 0);
+			if (pg == P_INVALID)
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			idx = 0;
+		}
+		break;
+	case R_PREV:			/* Previous record. */
+		/*
+		 * The cursor was deleted in duplicate records, and moved
+		 * backward to a record that has yet to be returned.  Clear
+		 * that flag, and return the record.
+		 */
+		if (F_ISSET(c, CURS_BEFORE)) {
+usecurrent:		F_CLR(c, CURS_AFTER | CURS_BEFORE);
+			ep->page = h;
+			ep->index = c->pg.index;
+			return (RET_SUCCESS);
+		}
+		idx = c->pg.index;
+		if (idx == 0) {
+			pg = h->prevpg;
+			mpool_put(t->bt_mp, h, 0);
+			if (pg == P_INVALID)
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			idx = NEXTINDEX(h) - 1;
+		} else
+			--idx;
+		break;
+	}
+
+	ep->page = h;
+	ep->index = idx;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_first --
+ *	Find the first entry.
+ *
+ * Parameters:
+ *	t:	the tree
+ *    key:	the key
+ *  erval:	return EPG
+ * exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	The first entry in the tree greater than or equal to key,
+ *	or RET_SPECIAL if no such key exists.
+ */
+static int
+__bt_first(t, key, erval, exactp)
+	BTREE *t;
+	const DBT *key;
+	EPG *erval;
+	int *exactp;
+{
+	PAGE *h;
+	EPG *ep, save;
+	db_pgno_t pg;
+
+	/*
+	 * Find any matching record; __bt_search pins the page.
+	 *
+	 * If it's an exact match and duplicates are possible, walk backwards
+	 * in the tree until we find the first one.  Otherwise, make sure it's
+	 * a valid key (__bt_search may return an index just past the end of a
+	 * page) and return it.
+	 */
+	if ((ep = __bt_search(t, key, exactp)) == NULL)
+		return (RET_SPECIAL);
+	if (*exactp) {
+		if (F_ISSET(t, B_NODUPS)) {
+			*erval = *ep;
+			return (RET_SUCCESS);
+		}
+			
+		/*
+		 * Walk backwards, as long as the entry matches and there are
+		 * keys left in the tree.  Save a copy of each match in case
+		 * we go too far.
+		 */
+		save = *ep;
+		h = ep->page;
+		do {
+			if (save.page->pgno != ep->page->pgno) {
+				mpool_put(t->bt_mp, save.page, 0);
+				save = *ep;
+			} else
+				save.index = ep->index;
+
+			/*
+			 * Don't unpin the page the last (or original) match
+			 * was on, but make sure it's unpinned if an error
+			 * occurs.
+			 */
+			if (ep->index == 0) {
+				if (h->prevpg == P_INVALID)
+					break;
+				if (h->pgno != save.page->pgno)
+					mpool_put(t->bt_mp, h, 0);
+				if ((h = mpool_get(t->bt_mp,
+				    h->prevpg, 0)) == NULL) {
+					if (h->pgno == save.page->pgno)
+						mpool_put(t->bt_mp,
+						    save.page, 0);
+					return (RET_ERROR);
+				}
+				ep->page = h;
+				ep->index = NEXTINDEX(h);
+			}
+			--ep->index;
+		} while (__bt_cmp(t, key, ep) == 0);
+
+		/*
+		 * Reach here with the last page that was looked at pinned,
+		 * which may or may not be the same as the last (or original)
+		 * match page.  If it's not useful, release it.
+		 */
+		if (h->pgno != save.page->pgno)
+			mpool_put(t->bt_mp, h, 0);
+
+		*erval = save;
+		return (RET_SUCCESS);
+	}
+
+	/* If at the end of a page, find the next entry. */
+	if (ep->index == NEXTINDEX(ep->page)) {
+		h = ep->page;
+		pg = h->nextpg;
+		mpool_put(t->bt_mp, h, 0);
+		if (pg == P_INVALID)
+			return (RET_SPECIAL);
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+		ep->index = 0;
+		ep->page = h;
+	}
+	*erval = *ep;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_setcur --
+ *	Set the cursor to an entry in the tree.
+ *
+ * Parameters:
+ *	t:	the tree
+ *   pgno:	page number
+ *  index:	page index
+ */
+void
+__bt_setcur(t, pgno, idx)
+	BTREE *t;
+	db_pgno_t pgno;
+	u_int idx;
+{
+	/* Lose any already deleted key. */
+	if (t->bt_cursor.key.data != NULL) {
+		free(t->bt_cursor.key.data);
+		t->bt_cursor.key.size = 0;
+		t->bt_cursor.key.data = NULL;
+	}
+	F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+
+	/* Update the cursor. */
+	t->bt_cursor.pg.pgno = pgno;
+	t->bt_cursor.pg.index = idx;
+	F_SET(&t->bt_cursor, CURS_INIT);
+}
+
+/* Recursive descent cursor. */
+typedef struct rcursor_ {
+	CURSOR	cursor;
+	size_t	ssize;
+	EPGNO	*stack;
+	EPGNO	*sp;
+} RCURSOR;
+#define RCURSOR_MINSS	64
+
+static int	 bt_rcinit(void **);
+static void	 bt_rcdestroy(void **);
+static int	 bt_rcpush(RCURSOR *, db_pgno_t, u_int);
+static EPGNO	*bt_rcpop(RCURSOR *);
+static void	 bt_rcclr(RCURSOR *);
+static int	 bt_rcgrowstk(RCURSOR *);
+static int	 bt_rseqset(BTREE *, EPG *, DBT *, RCURSOR *, int);
+static int	 bt_rseqadv(BTREE *, EPG *, RCURSOR *, int);
+
+static int
+bt_rcinit(curs)
+	void **curs;
+{
+	RCURSOR *rc;
+
+	rc = *curs = malloc(sizeof(RCURSOR));
+	if (rc == NULL) {
+		errno = ENOMEM;
+		return RET_ERROR;
+	}
+	memset(rc, 0, sizeof(*rc));
+
+	rc->ssize = RCURSOR_MINSS;
+	rc->stack = malloc(rc->ssize * sizeof(EPGNO));
+	if (rc->stack == NULL) {
+		free(rc);
+		errno = ENOMEM;
+		return RET_ERROR;
+	}
+	bt_rcclr(rc);
+	return RET_SUCCESS;
+}
+
+static void
+bt_rcdestroy(curs)
+	void **curs;
+{
+	RCURSOR *rc;
+
+	rc = *curs;
+	free(rc->stack);
+	free(rc);
+	*curs = NULL;
+}
+
+static int
+bt_rcpush(rc, p, i)
+	RCURSOR *rc;
+	db_pgno_t p;
+	u_int i;
+{
+	int status;
+
+	rc->sp->pgno = p;
+	rc->sp->index = i;
+	if (++rc->sp > rc->stack + rc->ssize) {
+		status = bt_rcgrowstk(rc);
+		if (status != RET_SUCCESS)
+			return status;
+	}
+	return RET_SUCCESS;
+}
+
+static EPGNO *
+bt_rcpop(rc)
+	RCURSOR *rc;
+{
+	return (rc->sp == rc->stack) ? NULL : --rc->sp;
+}
+
+static void
+bt_rcclr(rc)
+	RCURSOR *rc;
+{
+	rc->sp = rc->stack;
+}
+
+static int
+bt_rcgrowstk(rc)
+	RCURSOR *rc;
+{
+	size_t osize;
+	EPGNO *e;
+
+	osize = rc->ssize;
+	rc->ssize *= 2;
+	e = realloc(rc->stack, rc->ssize * sizeof(EPGNO));
+	if (e == NULL) {
+		rc->ssize = osize;
+		errno = ENOMEM;
+		return RET_ERROR;
+	}
+	rc->stack = e;
+	return RET_SUCCESS;
+}
+
+/*
+ * bt_rseq --
+ *	Like __bt_seq but does recursive descent tree traversal
+ *	instead of using the prev/next pointers.
+ */
+int
+bt_rseq(dbp, key, data, curs, flags)
+	const DB *dbp;
+	DBT *key, *data;
+	void **curs;
+	u_int flags;
+{
+	RCURSOR *rc;
+	BTREE *t;
+	EPG e;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	if (curs == NULL) {
+		errno = EINVAL;
+		return RET_ERROR;
+	}
+	if (*curs == NULL) {
+		status = bt_rcinit(curs);
+		if (status != RET_SUCCESS)
+			return RET_ERROR;
+	}
+	rc = *curs;
+
+	/*
+	 * If scan unitialized as yet, or starting at a specific record, set
+	 * the scan to a specific key.  Both bt_rseqset and bt_rseqadv pin
+	 * the page the cursor references if they're successful.
+	 */
+	switch (flags) {
+	case R_NEXT:
+	case R_PREV:
+		if (F_ISSET(&rc->cursor, CURS_INIT)) {
+			status = bt_rseqadv(t, &e, rc, flags);
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_FIRST:
+	case R_LAST:
+	case R_CURSOR:
+		status = bt_rseqset(t, &e, key, rc, flags);
+		break;
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (status == RET_SUCCESS) {
+		status =
+		    __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
+
+		/*
+		 * If the user is doing concurrent access, we copied the
+		 * key/data, toss the page.
+		 */
+		if (F_ISSET(t, B_DB_LOCK))
+			mpool_put(t->bt_mp, e.page, 0);
+		else
+			t->bt_pinned = e.page;
+	} else if (status == RET_SPECIAL)
+		bt_rcdestroy(curs);
+	return (status);
+}
+
+/*
+ * bt_rseqset --
+ *	Set the sequential scan to a specific key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	ep:	storage for returned key
+ *	key:	key for initial scan position
+ *	rc:	recursion cursor
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the cursor references.
+ *	Updates rc's stack and cursor.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+bt_rseqset(t, ep, key, rc, flags)
+	BTREE *t;
+	EPG *ep;
+	DBT *key;
+	RCURSOR *rc;
+	int flags;
+{
+	PAGE *h;
+	db_pgno_t pg;
+	int status;
+
+	/*
+	 * Find the first, last or specific key in the tree and point the
+	 * cursor at it.  The cursor may not be moved until a new key has
+	 * been found.
+	 */
+	switch (flags) {
+	case R_CURSOR:		/* Not implemented. */
+		errno = EINVAL;
+		return RET_ERROR;
+	case R_FIRST:				/* First record. */
+	case R_NEXT:
+		bt_rcclr(rc);
+		/* Walk down the left-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, 0)->pgno;
+			status = bt_rcpush(rc, h->pgno, 0);
+			mpool_put(t->bt_mp, h, 0);
+			if (status != RET_SUCCESS)
+				return status;
+		}
+		ep->page = h;
+		ep->index = 0;
+		break;
+	case R_LAST:				/* Last record. */
+	case R_PREV:
+		bt_rcclr(rc);
+		/* Walk down the right-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
+			status = bt_rcpush(rc, h->pgno, NEXTINDEX(h) - 1);
+			mpool_put(t->bt_mp, h, 0);
+			if (status != RET_SUCCESS)
+				return status;
+		}
+		ep->page = h;
+		ep->index = NEXTINDEX(h) - 1;
+		break;
+	}
+	rc->cursor.pg.pgno = ep->page->pgno;
+	rc->cursor.pg.index = ep->index;
+	F_CLR(&rc->cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+	F_SET(&rc->cursor, CURS_INIT);
+	return (RET_SUCCESS);
+}
+
+/*
+ * bt_rseqadvance --
+ *	Advance the sequential scan.
+ *
+ * Parameters:
+ *	t:	tree
+ *	ep:	return page
+ *	rc:	recursion cursor
+ *	flags:	R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the new key/data record is on.
+ *	Updates rc's stack and cursor.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+bt_rseqadv(t, ep, rc, flags)
+	BTREE *t;
+	EPG *ep;
+	RCURSOR *rc;
+	int flags;
+{
+	CURSOR *c;
+	PAGE *h;
+	indx_t idx;
+	db_pgno_t pg;
+	int status;
+	EPGNO *e;
+
+	/*
+	 * There are a couple of states that we can be in.  The cursor has
+	 * been initialized by the time we get here, but that's all we know.
+	 */
+	c = &rc->cursor;
+
+	/* Get the page referenced by the cursor. */
+	if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+		return (RET_ERROR);
+
+	/*
+ 	 * Find the next/previous record in the tree and point the cursor at
+	 * it.  The cursor may not be moved until a new key has been found.
+	 */
+	switch (flags) {
+	case R_NEXT:			/* Next record. */
+		idx = c->pg.index;
+		while (++idx == NEXTINDEX(h)) {
+			/* Crawl up if we hit the right edge. */
+			e = bt_rcpop(rc);
+			mpool_put(t->bt_mp, h, 0);
+			if (e == NULL) /* Hit the right edge of root. */
+				return RET_SPECIAL;
+			idx = e->index;
+			pg = e->pgno;
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+		}
+		while (!(h->flags & (P_BLEAF | P_RLEAF))) {
+			/* Crawl down the left until we hit a leaf. */
+			status = bt_rcpush(rc, h->pgno, idx);
+			pg = GETBINTERNAL(h, idx)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+			if (status != RET_SUCCESS)
+				return status;
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			idx = 0;
+		}
+		break;
+	case R_PREV:			/* Previous record. */
+		idx = c->pg.index;
+		while (!idx) {
+			/* Crawl up if we hit the left edge. */
+			e = bt_rcpop(rc);
+			mpool_put(t->bt_mp, h, 0);
+			if (e == NULL) /* Hit the left edge of root. */
+				return RET_SPECIAL;
+			idx = e->index;
+			pg = e->pgno;
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+		}
+		idx--;
+		while (!(h->flags & (P_BLEAF | P_RLEAF))) {
+			/* Crawl down the right until we hit a leaf. */
+			status = bt_rcpush(rc, h->pgno, idx);
+			pg = GETBINTERNAL(h, idx)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+			if (status != RET_SUCCESS)
+				return status;
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			idx = NEXTINDEX(h) - 1;
+		}
+		break;
+	}
+
+	ep->page = h;
+	ep->index = idx;
+	c->pg.pgno = h->pgno;
+	c->pg.index = idx;
+	F_CLR(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+	F_SET(c, CURS_INIT);
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_split.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_split.c
new file mode 100644
index 000000000..62ec823a1
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_split.c
@@ -0,0 +1,828 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_split.c	8.10 (Berkeley) 1/9/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+static int	 bt_broot __P((BTREE *, PAGE *, PAGE *, PAGE *));
+static PAGE	*bt_page
+		    __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t));
+static int	 bt_preserve __P((BTREE *, db_pgno_t));
+static PAGE	*bt_psplit
+		    __P((BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t));
+static PAGE	*bt_root
+		    __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t));
+static int	 bt_rroot __P((BTREE *, PAGE *, PAGE *, PAGE *));
+static recno_t	 rec_total __P((PAGE *));
+
+#ifdef STATISTICS
+u_long	bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
+#endif
+
+/*
+ * __BT_SPLIT -- Split the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	sp:	page to split
+ *	key:	key to insert
+ *	data:	data to insert
+ *	flags:	BIGKEY/BIGDATA flags
+ *	ilen:	insert length
+ *	skip:	index to leave open
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_split(t, sp, key, data, flags, ilen, argskip)
+	BTREE *t;
+	PAGE *sp;
+	const DBT *key, *data;
+	int flags;
+	size_t ilen;
+	u_int32_t argskip;
+{
+	BINTERNAL *bi;
+	BLEAF *bl, *tbl;
+	DBT a, b;
+	EPGNO *parent;
+	PAGE *h, *l, *r, *lchild, *rchild;
+	indx_t nxtindex;
+	u_int16_t skip;
+	u_int32_t n, nbytes, nksize;
+	int parentsplit;
+	char *dest;
+
+	/*
+	 * Split the page into two pages, l and r.  The split routines return
+	 * a pointer to the page into which the key should be inserted and with
+	 * skip set to the offset which should be used.  Additionally, l and r
+	 * are pinned.
+	 */
+	skip = argskip;
+	h = sp->pgno == P_ROOT ?
+	    bt_root(t, sp, &l, &r, &skip, ilen) :
+	    bt_page(t, sp, &l, &r, &skip, ilen);
+	if (h == NULL)
+		return (RET_ERROR);
+
+	/*
+	 * Insert the new key/data pair into the leaf page.  (Key inserts
+	 * always cause a leaf page to split first.)
+	 */
+	h->linp[skip] = h->upper -= ilen;
+	dest = (char *)h + h->upper;
+	if (F_ISSET(t, R_RECNO))
+		WR_RLEAF(dest, data, flags)
+	else
+		WR_BLEAF(dest, key, data, flags)
+
+	/* If the root page was split, make it look right. */
+	if (sp->pgno == P_ROOT &&
+	    (F_ISSET(t, R_RECNO) ?
+	    bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+		goto err2;
+
+	/*
+	 * Now we walk the parent page stack -- a LIFO stack of the pages that
+	 * were traversed when we searched for the page that split.  Each stack
+	 * entry is a page number and a page index offset.  The offset is for
+	 * the page traversed on the search.  We've just split a page, so we
+	 * have to insert a new key into the parent page.
+	 *
+	 * If the insert into the parent page causes it to split, may have to
+	 * continue splitting all the way up the tree.  We stop if the root
+	 * splits or the page inserted into didn't have to split to hold the
+	 * new key.  Some algorithms replace the key for the old page as well
+	 * as the new page.  We don't, as there's no reason to believe that the
+	 * first key on the old page is any better than the key we have, and,
+	 * in the case of a key being placed at index 0 causing the split, the
+	 * key is unavailable.
+	 *
+	 * There are a maximum of 5 pages pinned at any time.  We keep the left
+	 * and right pages pinned while working on the parent.   The 5 are the
+	 * two children, left parent and right parent (when the parent splits)
+	 * and the root page or the overflow key page when calling bt_preserve.
+	 * This code must make sure that all pins are released other than the
+	 * root page or overflow page which is unlocked elsewhere.
+	 */
+	while ((parent = BT_POP(t)) != NULL) {
+		lchild = l;
+		rchild = r;
+
+		/* Get the parent page. */
+		if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			goto err2;
+
+	 	/*
+		 * The new key goes ONE AFTER the index, because the split
+		 * was to the right.
+		 */
+		skip = parent->index + 1;
+
+		/*
+		 * Calculate the space needed on the parent page.
+		 *
+		 * Prefix trees: space hack when inserting into BINTERNAL
+		 * pages.  Retain only what's needed to distinguish between
+		 * the new entry and the LAST entry on the page to its left.
+		 * If the keys compare equal, retain the entire key.  Note,
+		 * we don't touch overflow keys, and the entire key must be
+		 * retained for the next-to-left most key on the leftmost
+		 * page of each level, or the search will fail.  Applicable
+		 * ONLY to internal pages that have leaf pages as children.
+		 * Further reduction of the key between pairs of internal
+		 * pages loses too much information.
+		 */
+		switch (rchild->flags & P_TYPE) {
+		case P_BINTERNAL:
+			bi = GETBINTERNAL(rchild, 0);
+			nbytes = NBINTERNAL(bi->ksize);
+			break;
+		case P_BLEAF:
+			bl = GETBLEAF(rchild, 0);
+			nbytes = NBINTERNAL(bl->ksize);
+			if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
+			    (h->prevpg != P_INVALID || skip > 1)) {
+				tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
+				a.size = tbl->ksize;
+				a.data = tbl->bytes;
+				b.size = bl->ksize;
+				b.data = bl->bytes;
+				nksize = t->bt_pfx(&a, &b);
+				n = NBINTERNAL(nksize);
+				if (n < nbytes) {
+#ifdef STATISTICS
+					bt_pfxsaved += nbytes - n;
+#endif
+					nbytes = n;
+				} else
+					nksize = 0;
+			} else
+				nksize = 0;
+			break;
+		case P_RINTERNAL:
+		case P_RLEAF:
+			nbytes = NRINTERNAL;
+			break;
+		default:
+			abort();
+		}
+
+		/* Split the parent page if necessary or shift the indices. */
+		if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+			sp = h;
+			h = h->pgno == P_ROOT ?
+			    bt_root(t, h, &l, &r, &skip, nbytes) :
+			    bt_page(t, h, &l, &r, &skip, nbytes);
+			if (h == NULL)
+				goto err1;
+			parentsplit = 1;
+		} else {
+			if (skip < (nxtindex = NEXTINDEX(h)))
+				memmove(h->linp + skip + 1, h->linp + skip,
+				    (nxtindex - skip) * sizeof(indx_t));
+			h->lower += sizeof(indx_t);
+			parentsplit = 0;
+		}
+
+		/* Insert the key into the parent page. */
+		switch (rchild->flags & P_TYPE) {
+		case P_BINTERNAL:
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			memmove(dest, bi, nbytes);
+			((BINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		case P_BLEAF:
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
+			    rchild->pgno, bl->flags & P_BIGKEY);
+			memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
+			if (bl->flags & P_BIGKEY &&
+			    bt_preserve(t, *(db_pgno_t *)bl->bytes) == RET_ERROR)
+				goto err1;
+			break;
+		case P_RINTERNAL:
+			/*
+			 * Update the left page count.  If split
+			 * added at index 0, fix the correct page.
+			 */
+			if (skip > 0)
+				dest = (char *)h + h->linp[skip - 1];
+			else
+				dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+			((RINTERNAL *)dest)->nrecs = rec_total(lchild);
+			((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+			/* Update the right page count. */
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			((RINTERNAL *)dest)->nrecs = rec_total(rchild);
+			((RINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		case P_RLEAF:
+			/*
+			 * Update the left page count.  If split
+			 * added at index 0, fix the correct page.
+			 */
+			if (skip > 0)
+				dest = (char *)h + h->linp[skip - 1];
+			else
+				dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+			((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
+			((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+			/* Update the right page count. */
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
+			((RINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		default:
+			abort();
+		}
+
+		/* Unpin the held pages. */
+		if (!parentsplit) {
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		}
+
+		/* If the root page was split, make it look right. */
+		if (sp->pgno == P_ROOT &&
+		    (F_ISSET(t, R_RECNO) ?
+		    bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+			goto err1;
+
+		mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+		mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+	}
+
+	/* Unpin the held pages. */
+	mpool_put(t->bt_mp, l, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, r, MPOOL_DIRTY);
+
+	/* Clear any pages left on the stack. */
+	return (RET_SUCCESS);
+
+	/*
+	 * If something fails in the above loop we were already walking back
+	 * up the tree and the tree is now inconsistent.  Nothing much we can
+	 * do about it but release any memory we're holding.
+	 */
+err1:	mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+
+err2:	mpool_put(t->bt_mp, l, 0);
+	mpool_put(t->bt_mp, r, 0);
+	__dbpanic(t->bt_dbp);
+	return (RET_ERROR);
+}
+
+/*
+ * BT_PAGE -- Split a non-root page of a btree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	lp:	pointer to left page pointer
+ *	rp:	pointer to right page pointer
+ *	skip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_page(t, h, lp, rp, skip, ilen)
+	BTREE *t;
+	PAGE *h, **lp, **rp;
+	indx_t *skip;
+	size_t ilen;
+{
+	PAGE *l, *r, *tp;
+	db_pgno_t npg;
+
+#ifdef STATISTICS
+	++bt_split;
+#endif
+	/* Put the new right page for the split into place. */
+	if ((r = __bt_new(t, &npg)) == NULL)
+		return (NULL);
+	r->pgno = npg;
+	r->lower = BTDATAOFF;
+	r->upper = t->bt_psize;
+	r->nextpg = h->nextpg;
+	r->prevpg = h->pgno;
+	r->flags = h->flags & P_TYPE;
+
+	/*
+	 * If we're splitting the last page on a level because we're appending
+	 * a key to it (skip is NEXTINDEX()), it's likely that the data is
+	 * sorted.  Adding an empty page on the side of the level is less work
+	 * and can push the fill factor much higher than normal.  If we're
+	 * wrong it's no big deal, we'll just do the split the right way next
+	 * time.  It may look like it's equally easy to do a similar hack for
+	 * reverse sorted data, that is, split the tree left, but it's not.
+	 * Don't even try.
+	 */
+	if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
+#ifdef STATISTICS
+		++bt_sortsplit;
+#endif
+		h->nextpg = r->pgno;
+		r->lower = BTDATAOFF + sizeof(indx_t);
+		*skip = 0;
+		*lp = h;
+		*rp = r;
+		return (r);
+	}
+
+	/* Put the new left page for the split into place. */
+	if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) {
+		mpool_put(t->bt_mp, r, 0);
+		return (NULL);
+	}
+#if 1 /* def PURIFY */
+	memset(l, 0xff, t->bt_psize);
+#endif
+	l->pgno = h->pgno;
+	l->nextpg = r->pgno;
+	l->prevpg = h->prevpg;
+	l->lower = BTDATAOFF;
+	l->upper = t->bt_psize;
+	l->flags = h->flags & P_TYPE;
+
+	/* Fix up the previous pointer of the page after the split page. */
+	if (h->nextpg != P_INVALID) {
+		if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
+			free(l);
+			/* XXX mpool_free(t->bt_mp, r->pgno); */
+			return (NULL);
+		}
+		tp->prevpg = r->pgno;
+		mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
+	}
+
+	/*
+	 * Split right.  The key/data pairs aren't sorted in the btree page so
+	 * it's simpler to copy the data from the split page onto two new pages
+	 * instead of copying half the data to the right page and compacting
+	 * the left page in place.  Since the left page can't change, we have
+	 * to swap the original and the allocated left page after the split.
+	 */
+	tp = bt_psplit(t, h, l, r, skip, ilen);
+
+	/* Move the new left page onto the old left page. */
+	memmove(h, l, t->bt_psize);
+	if (tp == l)
+		tp = h;
+	free(l);
+
+	*lp = h;
+	*rp = r;
+	return (tp);
+}
+
+/*
+ * BT_ROOT -- Split the root page of a btree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	lp:	pointer to left page pointer
+ *	rp:	pointer to right page pointer
+ *	skip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_root(t, h, lp, rp, skip, ilen)
+	BTREE *t;
+	PAGE *h, **lp, **rp;
+	indx_t *skip;
+	size_t ilen;
+{
+	PAGE *l, *r, *tp;
+	db_pgno_t lnpg, rnpg;
+
+#ifdef STATISTICS
+	++bt_split;
+	++bt_rootsplit;
+#endif
+	/* Put the new left and right pages for the split into place. */
+	if ((l = __bt_new(t, &lnpg)) == NULL ||
+	    (r = __bt_new(t, &rnpg)) == NULL)
+		return (NULL);
+	l->pgno = lnpg;
+	r->pgno = rnpg;
+	l->nextpg = r->pgno;
+	r->prevpg = l->pgno;
+	l->prevpg = r->nextpg = P_INVALID;
+	l->lower = r->lower = BTDATAOFF;
+	l->upper = r->upper = t->bt_psize;
+	l->flags = r->flags = h->flags & P_TYPE;
+
+	/* Split the root page. */
+	tp = bt_psplit(t, h, l, r, skip, ilen);
+
+	*lp = l;
+	*rp = r;
+	return (tp);
+}
+
+/*
+ * BT_RROOT -- Fix up the recno root page after it has been split.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	l:	left page
+ *	r:	right page
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_rroot(t, h, l, r)
+	BTREE *t;
+	PAGE *h, *l, *r;
+{
+	char *dest;
+
+	/* Insert the left and right keys, set the header information. */
+	h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
+	dest = (char *)h + h->upper;
+	WR_RINTERNAL(dest,
+	    l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
+
+	h->linp[1] = h->upper -= NRINTERNAL;
+	dest = (char *)h + h->upper;
+	WR_RINTERNAL(dest,
+	    r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
+
+	h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+	/* Unpin the root page, set to recno internal page. */
+	h->flags &= ~P_TYPE;
+	h->flags |= P_RINTERNAL;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * BT_BROOT -- Fix up the btree root page after it has been split.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	l:	left page
+ *	r:	right page
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_broot(t, h, l, r)
+	BTREE *t;
+	PAGE *h, *l, *r;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	u_int32_t nbytes;
+	char *dest;
+
+	/*
+	 * If the root page was a leaf page, change it into an internal page.
+	 * We copy the key we split on (but not the key's data, in the case of
+	 * a leaf page) to the new root page.
+	 *
+	 * The btree comparison code guarantees that the left-most key on any
+	 * level of the tree is never used, so it doesn't need to be filled in.
+	 */
+	nbytes = NBINTERNAL(0);
+	h->linp[0] = h->upper = t->bt_psize - nbytes;
+	dest = (char *)h + h->upper;
+	WR_BINTERNAL(dest, 0, l->pgno, 0);
+
+	switch (h->flags & P_TYPE) {
+	case P_BLEAF:
+		bl = GETBLEAF(r, 0);
+		nbytes = NBINTERNAL(bl->ksize);
+		h->linp[1] = h->upper -= nbytes;
+		dest = (char *)h + h->upper;
+		WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
+		memmove(dest, bl->bytes, bl->ksize);
+
+		/*
+		 * If the key is on an overflow page, mark the overflow chain
+		 * so it isn't deleted when the leaf copy of the key is deleted.
+		 */
+		if (bl->flags & P_BIGKEY &&
+		    bt_preserve(t, *(db_pgno_t *)bl->bytes) == RET_ERROR)
+			return (RET_ERROR);
+		break;
+	case P_BINTERNAL:
+		bi = GETBINTERNAL(r, 0);
+		nbytes = NBINTERNAL(bi->ksize);
+		h->linp[1] = h->upper -= nbytes;
+		dest = (char *)h + h->upper;
+		memmove(dest, bi, nbytes);
+		((BINTERNAL *)dest)->pgno = r->pgno;
+		break;
+	default:
+		abort();
+	}
+
+	/* There are two keys on the page. */
+	h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+	/* Unpin the root page, set to btree internal page. */
+	h->flags &= ~P_TYPE;
+	h->flags |= P_BINTERNAL;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * BT_PSPLIT -- Do the real work of splitting the page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to be split
+ *	l:	page to put lower half of data
+ *	r:	page to put upper half of data
+ *	pskip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert.
+ */
+static PAGE *
+bt_psplit(t, h, l, r, pskip, ilen)
+	BTREE *t;
+	PAGE *h, *l, *r;
+	indx_t *pskip;
+	size_t ilen;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	CURSOR *c;
+	RLEAF *rl;
+	PAGE *rval;
+	void *src;
+	indx_t full, half, nxt, off, skip, top, used;
+	u_int32_t nbytes;
+	int bigkeycnt, isbigkey;
+
+	/*
+	 * Split the data to the left and right pages.  Leave the skip index
+	 * open.  Additionally, make some effort not to split on an overflow
+	 * key.  This makes internal page processing faster and can save
+	 * space as overflow keys used by internal pages are never deleted.
+	 */
+	bigkeycnt = 0;
+	skip = *pskip;
+	full = t->bt_psize - BTDATAOFF;
+	half = full / 2;
+	used = 0;
+	for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
+		if (skip == off) {
+			nbytes = ilen;
+			isbigkey = 0;		/* XXX: not really known. */
+		} else
+			switch (h->flags & P_TYPE) {
+			case P_BINTERNAL:
+				src = bi = GETBINTERNAL(h, nxt);
+				nbytes = NBINTERNAL(bi->ksize);
+				isbigkey = bi->flags & P_BIGKEY;
+				break;
+			case P_BLEAF:
+				src = bl = GETBLEAF(h, nxt);
+				nbytes = NBLEAF(bl);
+				isbigkey = bl->flags & P_BIGKEY;
+				break;
+			case P_RINTERNAL:
+				src = GETRINTERNAL(h, nxt);
+				nbytes = NRINTERNAL;
+				isbigkey = 0;
+				break;
+			case P_RLEAF:
+				src = rl = GETRLEAF(h, nxt);
+				nbytes = NRLEAF(rl);
+				isbigkey = 0;
+				break;
+			default:
+				abort();
+			}
+
+		/*
+		 * If the key/data pairs are substantial fractions of the max
+		 * possible size for the page, it's possible to get situations
+		 * where we decide to try and copy too much onto the left page.
+		 * Make sure that doesn't happen.
+		 */
+		if ((skip <= off && used + nbytes + sizeof(indx_t) >= full)
+		    || nxt == top - 1) {
+			--off;
+			break;
+		}
+
+		/* Copy the key/data pair, if not the skipped index. */
+		if (skip != off) {
+			++nxt;
+
+			l->linp[off] = l->upper -= nbytes;
+			memmove((char *)l + l->upper, src, nbytes);
+		}
+
+		used += nbytes + sizeof(indx_t);
+		if (used >= half) {
+			if (!isbigkey || bigkeycnt == 3)
+				break;
+			else
+				++bigkeycnt;
+		}
+	}
+
+	/*
+	 * Off is the last offset that's valid for the left page.
+	 * Nxt is the first offset to be placed on the right page.
+	 */
+	l->lower += (off + 1) * sizeof(indx_t);
+
+	/*
+	 * If splitting the page that the cursor was on, the cursor has to be
+	 * adjusted to point to the same record as before the split.  If the
+	 * cursor is at or past the skipped slot, the cursor is incremented by
+	 * one.  If the cursor is on the right page, it is decremented by the
+	 * number of records split to the left page.
+	 */
+	c = &t->bt_cursor;
+	if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) {
+		if (c->pg.index >= skip)
+			++c->pg.index;
+		if (c->pg.index < nxt)			/* Left page. */
+			c->pg.pgno = l->pgno;
+		else {					/* Right page. */
+			c->pg.pgno = r->pgno;
+			c->pg.index -= nxt;
+		}
+	}
+
+	/*
+	 * If the skipped index was on the left page, just return that page.
+	 * Otherwise, adjust the skip index to reflect the new position on
+	 * the right page.
+	 */
+	if (skip <= off) {
+		skip = 0;
+		rval = l;
+	} else {
+		rval = r;
+		*pskip -= nxt;
+	}
+
+	for (off = 0; nxt < top; ++off) {
+		if (skip == nxt) {
+			++off;
+			skip = 0;
+		}
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+			src = bi = GETBINTERNAL(h, nxt);
+			nbytes = NBINTERNAL(bi->ksize);
+			break;
+		case P_BLEAF:
+			src = bl = GETBLEAF(h, nxt);
+			nbytes = NBLEAF(bl);
+			break;
+		case P_RINTERNAL:
+			src = GETRINTERNAL(h, nxt);
+			nbytes = NRINTERNAL;
+			break;
+		case P_RLEAF:
+			src = rl = GETRLEAF(h, nxt);
+			nbytes = NRLEAF(rl);
+			break;
+		default:
+			abort();
+		}
+		++nxt;
+		r->linp[off] = r->upper -= nbytes;
+		memmove((char *)r + r->upper, src, nbytes);
+	}
+	r->lower += off * sizeof(indx_t);
+
+	/* If the key is being appended to the page, adjust the index. */
+	if (skip == top)
+		r->lower += sizeof(indx_t);
+
+	return (rval);
+}
+
+/*
+ * BT_PRESERVE -- Mark a chain of pages as used by an internal node.
+ *
+ * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
+ * record that references them gets deleted.  Chains pointed to by internal
+ * pages never get deleted.  This routine marks a chain as pointed to by an
+ * internal page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	pg:	page number of first page in the chain.
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+static int
+bt_preserve(t, pg)
+	BTREE *t;
+	db_pgno_t pg;
+{
+	PAGE *h;
+
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+		return (RET_ERROR);
+	h->flags |= P_PRESERVE;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+/*
+ * REC_TOTAL -- Return the number of recno entries below a page.
+ *
+ * Parameters:
+ *	h:	page
+ *
+ * Returns:
+ *	The number of recno entries below a page.
+ *
+ * XXX
+ * These values could be set by the bt_psplit routine.  The problem is that the
+ * entry has to be popped off of the stack etc. or the values have to be passed
+ * all the way back to bt_split/bt_rroot and it's not very clean.
+ */
+static recno_t
+rec_total(h)
+	PAGE *h;
+{
+	recno_t recs;
+	indx_t nxt, top;
+
+	for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
+		recs += GETRINTERNAL(h, nxt)->nrecs;
+	return (recs);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_utils.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_utils.c
new file mode 100644
index 000000000..1a34598ad
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/bt_utils.c
@@ -0,0 +1,260 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_utils.c	8.8 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "btree.h"
+
+/*
+ * __bt_ret --
+ *	Build return key/data pair.
+ *
+ * Parameters:
+ *	t:	tree
+ *	e:	key/data pair to be returned
+ *	key:	user's key structure (NULL if not to be filled in)
+ *	rkey:	memory area to hold key
+ *	data:	user's data structure (NULL if not to be filled in)
+ *	rdata:	memory area to hold data
+ *       copy:	always copy the key/data item
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_ret(t, e, key, rkey, data, rdata, copy)
+	BTREE *t;
+	EPG *e;
+	DBT *key, *rkey, *data, *rdata;
+	int copy;
+{
+	BLEAF *bl;
+	void *p;
+
+	bl = GETBLEAF(e->page, e->index);
+
+	/*
+	 * We must copy big keys/data to make them contigous.  Otherwise,
+	 * leave the page pinned and don't copy unless the user specified
+	 * concurrent access.
+	 */
+	if (key == NULL)
+		goto dataonly;
+
+	if (bl->flags & P_BIGKEY) {
+		if (__ovfl_get(t, bl->bytes,
+		    &key->size, &rkey->data, &rkey->size))
+			return (RET_ERROR);
+		key->data = rkey->data;
+	} else if (copy || F_ISSET(t, B_DB_LOCK)) {
+		if (bl->ksize > rkey->size) {
+			p = (void *)(rkey->data == NULL ?
+			    malloc(bl->ksize) : realloc(rkey->data, bl->ksize));
+			if (p == NULL)
+				return (RET_ERROR);
+			rkey->data = p;
+			rkey->size = bl->ksize;
+		}
+		memmove(rkey->data, bl->bytes, bl->ksize);
+		key->size = bl->ksize;
+		key->data = rkey->data;
+	} else {
+		key->size = bl->ksize;
+		key->data = bl->bytes;
+	}
+
+dataonly:
+	if (data == NULL)
+		return (RET_SUCCESS);
+
+	if (bl->flags & P_BIGDATA) {
+		if (__ovfl_get(t, bl->bytes + bl->ksize,
+		    &data->size, &rdata->data, &rdata->size))
+			return (RET_ERROR);
+		data->data = rdata->data;
+	} else if (copy || F_ISSET(t, B_DB_LOCK)) {
+		/* Use +1 in case the first record retrieved is 0 length. */
+		if (bl->dsize + 1 > rdata->size) {
+			p = (void *)(rdata->data == NULL ?
+			    malloc(bl->dsize + 1) :
+			    realloc(rdata->data, bl->dsize + 1));
+			if (p == NULL)
+				return (RET_ERROR);
+			rdata->data = p;
+			rdata->size = bl->dsize + 1;
+		}
+		memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);
+		data->size = bl->dsize;
+		data->data = rdata->data;
+	} else {
+		data->size = bl->dsize;
+		data->data = bl->bytes + bl->ksize;
+	}
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * __BT_CMP -- Compare a key to a given record.
+ *
+ * Parameters:
+ *	t:	tree
+ *	k1:	DBT pointer of first arg to comparison
+ *	e:	pointer to EPG for comparison
+ *
+ * Returns:
+ *	< 0 if k1 is < record
+ *	= 0 if k1 is = record
+ *	> 0 if k1 is > record
+ */
+int
+__bt_cmp(t, k1, e)
+	BTREE *t;
+	const DBT *k1;
+	EPG *e;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	DBT k2;
+	PAGE *h;
+	void *bigkey;
+
+	/*
+	 * The left-most key on internal pages, at any level of the tree, is
+	 * guaranteed by the following code to be less than any user key.
+	 * This saves us from having to update the leftmost key on an internal
+	 * page when the user inserts a new key in the tree smaller than
+	 * anything we've yet seen.
+	 */
+	h = e->page;
+	if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
+		return (1);
+
+	bigkey = NULL;
+	if (h->flags & P_BLEAF) {
+		bl = GETBLEAF(h, e->index);
+		if (bl->flags & P_BIGKEY)
+			bigkey = bl->bytes;
+		else {
+			k2.data = bl->bytes;
+			k2.size = bl->ksize;
+		}
+	} else {
+		bi = GETBINTERNAL(h, e->index);
+		if (bi->flags & P_BIGKEY)
+			bigkey = bi->bytes;
+		else {
+			k2.data = bi->bytes;
+			k2.size = bi->ksize;
+		}
+	}
+
+	if (bigkey) {
+		if (__ovfl_get(t, bigkey,
+		    &k2.size, &t->bt_rdata.data, &t->bt_rdata.size))
+			return (RET_ERROR);
+		k2.data = t->bt_rdata.data;
+	}
+	return ((*t->bt_cmp)(k1, &k2));
+}
+
+/*
+ * __BT_DEFCMP -- Default comparison routine.
+ *
+ * Parameters:
+ *	a:	DBT #1
+ *	b: 	DBT #2
+ *
+ * Returns:
+ *	< 0 if a is < b
+ *	= 0 if a is = b
+ *	> 0 if a is > b
+ */
+int
+__bt_defcmp(a, b)
+	const DBT *a, *b;
+{
+	register size_t len;
+	register u_char *p1, *p2;
+
+	/*
+	 * XXX
+	 * If a size_t doesn't fit in an int, this routine can lose.
+	 * What we need is a integral type which is guaranteed to be
+	 * larger than a size_t, and there is no such thing.
+	 */
+	len = MIN(a->size, b->size);
+	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
+		if (*p1 != *p2)
+			return ((int)*p1 - (int)*p2);
+	return ((int)a->size - (int)b->size);
+}
+
+/*
+ * __BT_DEFPFX -- Default prefix routine.
+ *
+ * Parameters:
+ *	a:	DBT #1
+ *	b: 	DBT #2
+ *
+ * Returns:
+ *	Number of bytes needed to distinguish b from a.
+ */
+size_t
+__bt_defpfx(a, b)
+	const DBT *a, *b;
+{
+	register u_char *p1, *p2;
+	register size_t cnt, len;
+
+	cnt = 1;
+	len = MIN(a->size, b->size);
+	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
+		if (*p1 != *p2)
+			return (cnt);
+
+	/* a->size must be <= b->size, or they wouldn't be in this order. */
+	return (a->size < b->size ? a->size + 1 : a->size);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/btree.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/btree.h
new file mode 100644
index 000000000..171712749
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/btree.h
@@ -0,0 +1,383 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)btree.h	8.11 (Berkeley) 8/17/94
+ */
+
+/* Macros to set/clear/test flags. */
+#define	F_SET(p, f)	(p)->flags |= (f)
+#define	F_CLR(p, f)	(p)->flags &= ~(f)
+#define	F_ISSET(p, f)	((p)->flags & (f))
+
+#include "mpool.h"
+
+#define	DEFMINKEYPAGE	(2)		/* Minimum keys per page */
+#define	MINCACHE	(5)		/* Minimum cached pages */
+#define	MINPSIZE	(512)		/* Minimum page size */
+
+/*
+ * Page 0 of a btree file contains a copy of the meta-data.  This page is also
+ * used as an out-of-band page, i.e. page pointers that point to nowhere point
+ * to page 0.  Page 1 is the root of the btree.
+ */
+#define	P_INVALID	 0		/* Invalid tree page number. */
+#define	P_META		 0		/* Tree metadata page number. */
+#define	P_ROOT		 1		/* Tree root page number. */
+
+/*
+ * There are five page layouts in the btree: btree internal pages (BINTERNAL),
+ * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages
+ * (RLEAF) and overflow pages.  All five page types have a page header (PAGE).
+ * This implementation requires that values within structures NOT be padded.
+ * (ANSI C permits random padding.)  If your compiler pads randomly you'll have
+ * to do some work to get this package to run.
+ */
+typedef struct _page {
+	db_pgno_t	pgno;			/* this page's page number */
+	db_pgno_t	prevpg;			/* left sibling */
+	db_pgno_t	nextpg;			/* right sibling */
+
+#define	P_BINTERNAL	0x01		/* btree internal page */
+#define	P_BLEAF		0x02		/* leaf page */
+#define	P_OVERFLOW	0x04		/* overflow page */
+#define	P_RINTERNAL	0x08		/* recno internal page */
+#define	P_RLEAF		0x10		/* leaf page */
+#define P_TYPE		0x1f		/* type mask */
+#define	P_PRESERVE	0x20		/* never delete this chain of pages */
+	u_int32_t flags;
+
+	indx_t	lower;			/* lower bound of free space on page */
+	indx_t	upper;			/* upper bound of free space on page */
+	indx_t	linp[1];		/* indx_t-aligned VAR. LENGTH DATA */
+} PAGE;
+
+/* First and next index. */
+#define	BTDATAOFF							\
+	(sizeof(db_pgno_t) + sizeof(db_pgno_t) + sizeof(db_pgno_t) +		\
+	    sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t))
+#define	NEXTINDEX(p)	(((p)->lower - BTDATAOFF) / sizeof(indx_t))
+
+/*
+ * For pages other than overflow pages, there is an array of offsets into the
+ * rest of the page immediately following the page header.  Each offset is to
+ * an item which is unique to the type of page.  The h_lower offset is just
+ * past the last filled-in index.  The h_upper offset is the first item on the
+ * page.  Offsets are from the beginning of the page.
+ *
+ * If an item is too big to store on a single page, a flag is set and the item
+ * is a { page, size } pair such that the page is the first page of an overflow
+ * chain with size bytes of item.  Overflow pages are simply bytes without any
+ * external structure.
+ *
+ * The page number and size fields in the items are db_pgno_t-aligned so they can
+ * be manipulated without copying.  (This presumes that 32 bit items can be
+ * manipulated on this system.)
+ */
+#define	LALIGN(n)	(((n) + sizeof(db_pgno_t) - 1) & ~(sizeof(db_pgno_t) - 1))
+#define	NOVFLSIZE	(sizeof(db_pgno_t) + sizeof(u_int32_t))
+
+/*
+ * For the btree internal pages, the item is a key.  BINTERNALs are {key, pgno}
+ * pairs, such that the key compares less than or equal to all of the records
+ * on that page.  For a tree without duplicate keys, an internal page with two
+ * consecutive keys, a and b, will have all records greater than or equal to a
+ * and less than b stored on the page associated with a.  Duplicate keys are
+ * somewhat special and can cause duplicate internal and leaf page records and
+ * some minor modifications of the above rule.
+ */
+typedef struct _binternal {
+	u_int32_t ksize;		/* key size */
+	db_pgno_t	pgno;			/* page number stored on */
+#define	P_BIGDATA	0x01		/* overflow data */
+#define	P_BIGKEY	0x02		/* overflow key */
+	u_char	flags;
+	char	bytes[1];		/* data */
+} BINTERNAL;
+
+/* Get the page's BINTERNAL structure at index indx. */
+#define	GETBINTERNAL(pg, indx)						\
+	((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBINTERNAL(len)							\
+	LALIGN(sizeof(u_int32_t) + sizeof(db_pgno_t) + sizeof(u_char) + (len))
+
+/* Copy a BINTERNAL entry to the page. */
+#define	WR_BINTERNAL(p, size, pgno, flags) {				\
+	*(u_int32_t *)p = size;						\
+	p += sizeof(u_int32_t);						\
+	*(db_pgno_t *)p = pgno;						\
+	p += sizeof(db_pgno_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+}
+
+/*
+ * For the recno internal pages, the item is a page number with the number of
+ * keys found on that page and below.
+ */
+typedef struct _rinternal {
+	recno_t	nrecs;			/* number of records */
+	db_pgno_t	pgno;			/* page number stored below */
+} RINTERNAL;
+
+/* Get the page's RINTERNAL structure at index indx. */
+#define	GETRINTERNAL(pg, indx)						\
+	((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRINTERNAL							\
+	LALIGN(sizeof(recno_t) + sizeof(db_pgno_t))
+
+/* Copy a RINTERAL entry to the page. */
+#define	WR_RINTERNAL(p, nrecs, pgno) {					\
+	*(recno_t *)p = nrecs;						\
+	p += sizeof(recno_t);						\
+	*(db_pgno_t *)p = pgno;						\
+}
+
+/* For the btree leaf pages, the item is a key and data pair. */
+typedef struct _bleaf {
+	u_int32_t	ksize;		/* size of key */
+	u_int32_t	dsize;		/* size of data */
+	u_char	flags;			/* P_BIGDATA, P_BIGKEY */
+	char	bytes[1];		/* data */
+} BLEAF;
+
+/* Get the page's BLEAF structure at index indx. */
+#define	GETBLEAF(pg, indx)						\
+	((BLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBLEAF(p)	NBLEAFDBT((p)->ksize, (p)->dsize)
+
+/* Get the number of bytes in the user's key/data pair. */
+#define NBLEAFDBT(ksize, dsize)						\
+	LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) +	\
+	    (ksize) + (dsize))
+
+/* Copy a BLEAF entry to the page. */
+#define	WR_BLEAF(p, key, data, flags) {					\
+	*(u_int32_t *)p = key->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_int32_t *)p = data->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+	memmove(p, key->data, key->size);				\
+	p += key->size;							\
+	memmove(p, data->data, data->size);				\
+}
+
+/* For the recno leaf pages, the item is a data entry. */
+typedef struct _rleaf {
+	u_int32_t	dsize;		/* size of data */
+	u_char	flags;			/* P_BIGDATA */
+	char	bytes[1];
+} RLEAF;
+
+/* Get the page's RLEAF structure at index indx. */
+#define	GETRLEAF(pg, indx)						\
+	((RLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRLEAF(p)	NRLEAFDBT((p)->dsize)
+
+/* Get the number of bytes from the user's data. */
+#define	NRLEAFDBT(dsize)						\
+	LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize))
+
+/* Copy a RLEAF entry to the page. */
+#define	WR_RLEAF(p, data, flags) {					\
+	*(u_int32_t *)p = data->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+	memmove(p, data->data, data->size);				\
+}
+
+/*
+ * A record in the tree is either a pointer to a page and an index in the page
+ * or a page number and an index.  These structures are used as a cursor, stack
+ * entry and search returns as well as to pass records to other routines.
+ *
+ * One comment about searches.  Internal page searches must find the largest
+ * record less than key in the tree so that descents work.  Leaf page searches
+ * must find the smallest record greater than key so that the returned index
+ * is the record's correct position for insertion.
+ */
+typedef struct _epgno {
+	db_pgno_t	pgno;			/* the page number */
+	indx_t	index;			/* the index on the page */
+} EPGNO;
+
+typedef struct _epg {
+	PAGE	*page;			/* the (pinned) page */
+	indx_t	 index;			/* the index on the page */
+} EPG;
+
+/*
+ * About cursors.  The cursor (and the page that contained the key/data pair
+ * that it referenced) can be deleted, which makes things a bit tricky.  If
+ * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set
+ * or there simply aren't any duplicates of the key) we copy the key that it
+ * referenced when it's deleted, and reacquire a new cursor key if the cursor
+ * is used again.  If there are duplicates keys, we move to the next/previous
+ * key, and set a flag so that we know what happened.  NOTE: if duplicate (to
+ * the cursor) keys are added to the tree during this process, it is undefined
+ * if they will be returned or not in a cursor scan.
+ *
+ * The flags determine the possible states of the cursor:
+ *
+ * CURS_INIT	The cursor references *something*.
+ * CURS_ACQUIRE	The cursor was deleted, and a key has been saved so that
+ *		we can reacquire the right position in the tree.
+ * CURS_AFTER, CURS_BEFORE
+ *		The cursor was deleted, and now references a key/data pair
+ *		that has not yet been returned, either before or after the
+ *		deleted key/data pair.
+ * XXX
+ * This structure is broken out so that we can eventually offer multiple
+ * cursors as part of the DB interface.
+ */
+typedef struct _cursor {
+	EPGNO	 pg;			/* B: Saved tree reference. */
+	DBT	 key;			/* B: Saved key, or key.data == NULL. */
+	recno_t	 rcursor;		/* R: recno cursor (1-based) */
+
+#define	CURS_ACQUIRE	0x01		/*  B: Cursor needs to be reacquired. */
+#define	CURS_AFTER	0x02		/*  B: Unreturned cursor after key. */
+#define	CURS_BEFORE	0x04		/*  B: Unreturned cursor before key. */
+#define	CURS_INIT	0x08		/* RB: Cursor initialized. */
+	u_int8_t flags;
+} CURSOR;
+
+/*
+ * The metadata of the tree.  The nrecs field is used only by the RECNO code.
+ * This is because the btree doesn't really need it and it requires that every
+ * put or delete call modify the metadata.
+ */
+typedef struct _btmeta {
+	u_int32_t	magic;		/* magic number */
+	u_int32_t	version;	/* version */
+	u_int32_t	psize;		/* page size */
+	u_int32_t	free;		/* page number of first free page */
+	u_int32_t	nrecs;		/* R: number of records */
+
+#define	SAVEMETA	(B_NODUPS | R_RECNO)
+	u_int32_t	flags;		/* bt_flags & SAVEMETA */
+} BTMETA;
+
+/* The in-memory btree/recno data structure. */
+typedef struct _btree {
+	MPOOL	 *bt_mp;		/* memory pool cookie */
+
+	DB	 *bt_dbp;		/* pointer to enclosing DB */
+
+	EPG	  bt_cur;		/* current (pinned) page */
+	PAGE	 *bt_pinned;		/* page pinned across calls */
+
+	CURSOR	  bt_cursor;		/* cursor */
+
+#define	BT_PUSH(t, p, i) {						\
+	t->bt_sp->pgno = p; 						\
+	t->bt_sp->index = i; 						\
+	++t->bt_sp;							\
+}
+#define	BT_POP(t)	(t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
+#define	BT_CLR(t)	(t->bt_sp = t->bt_stack)
+	EPGNO	  bt_stack[50];		/* stack of parent pages */
+	EPGNO	 *bt_sp;		/* current stack pointer */
+
+	DBT	  bt_rkey;		/* returned key */
+	DBT	  bt_rdata;		/* returned data */
+
+	int	  bt_fd;		/* tree file descriptor */
+
+	db_pgno_t	  bt_free;		/* next free page */
+	u_int32_t bt_psize;		/* page size */
+	indx_t	  bt_ovflsize;		/* cut-off for key/data overflow */
+	int	  bt_lorder;		/* byte order */
+					/* sorted order */
+	enum { NOT, BACK, FORWARD } bt_order;
+	EPGNO	  bt_last;		/* last insert */
+
+					/* B: key comparison function */
+	int	(*bt_cmp) __P((const DBT *, const DBT *));
+					/* B: prefix comparison function */
+	size_t	(*bt_pfx) __P((const DBT *, const DBT *));
+					/* R: recno input function */
+	int	(*bt_irec) __P((struct _btree *, recno_t));
+
+	FILE	 *bt_rfp;		/* R: record FILE pointer */
+	int	  bt_rfd;		/* R: record file descriptor */
+
+	caddr_t	  bt_cmap;		/* R: current point in mapped space */
+	caddr_t	  bt_smap;		/* R: start of mapped space */
+	caddr_t   bt_emap;		/* R: end of mapped space */
+	size_t	  bt_msize;		/* R: size of mapped region. */
+
+	recno_t	  bt_nrecs;		/* R: number of records */
+	size_t	  bt_reclen;		/* R: fixed record length */
+	u_char	  bt_bval;		/* R: delimiting byte/pad character */
+
+/*
+ * NB:
+ * B_NODUPS and R_RECNO are stored on disk, and may not be changed.
+ */
+#define	B_INMEM		0x00001		/* in-memory tree */
+#define	B_METADIRTY	0x00002		/* need to write metadata */
+#define	B_MODIFIED	0x00004		/* tree modified */
+#define	B_NEEDSWAP	0x00008		/* if byte order requires swapping */
+#define	B_RDONLY	0x00010		/* read-only tree */
+
+#define	B_NODUPS	0x00020		/* no duplicate keys permitted */
+#define	R_RECNO		0x00080		/* record oriented tree */
+
+#define	R_CLOSEFP	0x00040		/* opened a file pointer */
+#define	R_EOF		0x00100		/* end of input file reached. */
+#define	R_FIXLEN	0x00200		/* fixed length records */
+#define	R_MEMMAPPED	0x00400		/* memory mapped file. */
+#define	R_INMEM		0x00800		/* in-memory file */
+#define	R_MODIFIED	0x01000		/* modified file */
+#define	R_RDONLY	0x02000		/* read-only file */
+
+#define	B_DB_LOCK	0x04000		/* DB_LOCK specified. */
+#define	B_DB_SHMEM	0x08000		/* DB_SHMEM specified. */
+#define	B_DB_TXN	0x10000		/* DB_TXN specified. */
+	u_int32_t flags;
+} BTREE;
+
+#include "extern.h"
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/extern.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/extern.h
new file mode 100644
index 000000000..3aa88417e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/btree/extern.h
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)extern.h	8.11 (Berkeley) 1/9/95
+ */
+
+#define __bt_close	__kdb2_bt_close
+#define __bt_cmp	__kdb2_bt_cmp
+#define __bt_crsrdel	__kdb2_bt_crsrdel
+#define __bt_defcmp	__kdb2_bt_defcmp
+#define __bt_defpfx	__kdb2_bt_defpfx
+#define __bt_delete	__kdb2_bt_delete
+#define __bt_dleaf	__kdb2_bt_deleaf
+#define __bt_fd		__kdb2_bt_fd
+#define __bt_free	__kdb2_bt_free
+#define __bt_get	__kdb2_bt_get
+#define __bt_new	__kdb2_bt_new
+#define __bt_pgin	__kdb2_bt_pgin
+#define __bt_pgout	__kdb2_bt_pgout
+#define __bt_push	__kdb2_bt_push
+#define __bt_put	__kdb2_bt_put
+#define __bt_ret	__kdb2_bt_ret
+#define __bt_search	__kdb2_bt_search
+#define __bt_seq	__kdb2_bt_seq
+#define __bt_setcur	__kdb2_bt_setcur
+#define __bt_split	__kdb2_bt_split
+#define __bt_sync	__kdb2_bt_sync
+#define __ovfl_delete	__kdb2_ovfl_delete
+#define __ovfl_get	__kdb2_ovfl_get
+#define __ovfl_put	__kdb2_ovfl_put
+#define __bt_dnpage	__kdb2_bt_dnpage
+#define __bt_dmpage	__kdb2_bt_dmpage
+#define __bt_dpage	__kdb2_bt_dpage
+#define __bt_dump	__kdb2_bt_dump
+#define __bt_stat	__kdb2_bt_stat
+
+#define bt_rcinit	kdb2_bt_rcinit
+#define bt_rcdestroy	kdb2_bt_rcdestroy
+#define bt_rcpush	kdb2_bt_rcpush
+#define bt_rcpop	kdb2_bt_rcpop
+#define bt_rcclr	kdb2_bt_rcclr
+#define bt_rcgrowstk	kdb2_bt_rcgrowstk
+#define bt_rseqset	kdb2_bt_rseqset
+#define bt_rseqadv	kdb2_bt_rseqadv
+
+int	 __bt_close __P((DB *));
+int	 __bt_cmp __P((BTREE *, const DBT *, EPG *));
+int	 __bt_crsrdel __P((BTREE *, EPGNO *));
+int	 __bt_defcmp __P((const DBT *, const DBT *));
+size_t	 __bt_defpfx __P((const DBT *, const DBT *));
+int	 __bt_delete __P((const DB *, const DBT *, u_int));
+int	 __bt_dleaf __P((BTREE *, const DBT *, PAGE *, u_int));
+int	 __bt_fd __P((const DB *));
+int	 __bt_free __P((BTREE *, PAGE *));
+int	 __bt_get __P((const DB *, const DBT *, DBT *, u_int));
+PAGE	*__bt_new __P((BTREE *, db_pgno_t *));
+void	 __bt_pgin __P((void *, db_pgno_t, void *));
+void	 __bt_pgout __P((void *, db_pgno_t, void *));
+int	 __bt_push __P((BTREE *, db_pgno_t, int));
+int	 __bt_put __P((const DB *dbp, DBT *, const DBT *, u_int));
+int	 __bt_ret __P((BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int));
+EPG	*__bt_search __P((BTREE *, const DBT *, int *));
+int	 __bt_seq __P((const DB *, DBT *, DBT *, u_int));
+void	 __bt_setcur __P((BTREE *, db_pgno_t, u_int));
+int	 __bt_split __P((BTREE *, PAGE *,
+	    const DBT *, const DBT *, int, size_t, u_int32_t));
+int	 __bt_sync __P((const DB *, u_int));
+
+int	 __ovfl_delete __P((BTREE *, void *));
+int	 __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *));
+int	 __ovfl_put __P((BTREE *, const DBT *, db_pgno_t *));
+
+#ifdef DEBUG
+int	 __bt_dnpage __P((DB *, db_pgno_t));
+int	 __bt_dpage __P((DB *, PAGE *));
+int	 __bt_dmpage __P((PAGE *));
+int	 __bt_dump __P((DB *));
+#endif
+#ifdef STATISTICS
+int	 __bt_stat __P((DB *));
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/Makefile.in
new file mode 100644
index 000000000..8ea1ec8d6
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/Makefile.in
@@ -0,0 +1,11 @@
+thisconfigdir=./..
+myfulldir=plugins/kdb/db2/libdb2/clib
+mydir=clib
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+STLIBOBJS=@MEMMOVE_OBJ@ @MKSTEMP_OBJ@ @STRERROR_OBJ@
+
+LOCALINCLUDES=-I../include
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/memmove.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/memmove.c
new file mode 100644
index 000000000..f9bf650a3
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/memmove.c
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bcopy.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+/*
+ * sizeof(word) MUST BE A POWER OF TWO
+ * SO THAT wmask BELOW IS ALL ONES
+ */
+typedef	int word;		/* "word" used for optimal copy speed */
+
+#define	wsize	sizeof(word)
+#define	wmask	(wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+#ifdef MEMCOPY
+void *
+memcpy(dst0, src0, length)
+#else
+#ifdef MEMMOVE
+void *
+memmove(dst0, src0, length)
+#else
+void
+bcopy(src0, dst0, length)
+#endif
+#endif
+	void *dst0;
+	const void *src0;
+	register size_t length;
+{
+	register char *dst = dst0;
+	register const char *src = src0;
+	register size_t t;
+
+	if (length == 0 || dst == src)		/* nothing to do */
+		goto done;
+
+	/*
+	 * Macros: loop-t-times; and loop-t-times, t>0
+	 */
+#define	TLOOP(s) if (t) TLOOP1(s)
+#define	TLOOP1(s) do { s; } while (--t)
+
+	if ((unsigned long)dst < (unsigned long)src) {
+		/*
+		 * Copy forward.
+		 */
+		t = (int)src;	/* only need low bits */
+		if ((t | (int)dst) & wmask) {
+			/*
+			 * Try to align operands.  This cannot be done
+			 * unless the low bits match.
+			 */
+			if ((t ^ (int)dst) & wmask || length < wsize)
+				t = length;
+			else
+				t = wsize - (t & wmask);
+			length -= t;
+			TLOOP1(*dst++ = *src++);
+		}
+		/*
+		 * Copy whole words, then mop up any trailing bytes.
+		 */
+		t = length / wsize;
+		TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
+		t = length & wmask;
+		TLOOP(*dst++ = *src++);
+	} else {
+		/*
+		 * Copy backwards.  Otherwise essentially the same.
+		 * Alignment works as before, except that it takes
+		 * (t&wmask) bytes to align, not wsize-(t&wmask).
+		 */
+		src += length;
+		dst += length;
+		t = (int)src;
+		if ((t | (int)dst) & wmask) {
+			if ((t ^ (int)dst) & wmask || length <= wsize)
+				t = length;
+			else
+				t &= wmask;
+			length -= t;
+			TLOOP1(*--dst = *--src);
+		}
+		t = length / wsize;
+		TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
+		t = length & wmask;
+		TLOOP(*--dst = *--src);
+	}
+done:
+#if defined(MEMCOPY) || defined(MEMMOVE)
+	return (dst0);
+#else
+	return;
+#endif
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/mkstemp.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/mkstemp.c
new file mode 100644
index 000000000..71dc7d17a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/mkstemp.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static int _gettemp();
+
+mkstemp(path)
+	char *path;
+{
+	int fd;
+
+	return (_gettemp(path, &fd) ? fd : -1);
+}
+
+static
+_gettemp(path, doopen)
+	char *path;
+	register int *doopen;
+{
+	register char *start, *trv;
+	struct stat sbuf;
+	u_int pid;
+
+	pid = getpid();
+	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
+	while (*--trv == 'X') {
+		*trv = (pid % 10) + '0';
+		pid /= 10;
+	}
+
+	/*
+	 * check the target directory; if you have six X's and it
+	 * doesn't exist this runs for a *very* long time.
+	 */
+	for (start = trv + 1;; --trv) {
+		if (trv <= path)
+			break;
+		if (*trv == '/') {
+			*trv = '\0';
+			if (stat(path, &sbuf))
+				return(0);
+			if (!S_ISDIR(sbuf.st_mode)) {
+				errno = ENOTDIR;
+				return(0);
+			}
+			*trv = '/';
+			break;
+		}
+	}
+
+	for (;;) {
+		if (doopen) {
+			if ((*doopen =
+			    open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0)
+				return(1);
+			if (errno != EEXIST)
+				return(0);
+		}
+		else if (stat(path, &sbuf))
+			return(errno == ENOENT ? 1 : 0);
+
+		/* tricky little algorithm for backward compatibility */
+		for (trv = start;;) {
+			if (!*trv)
+				return(0);
+			if (*trv == 'z')
+				*trv++ = 'a';
+			else {
+				if (isdigit(*trv))
+					*trv = 'a';
+				else
+					++*trv;
+				break;
+			}
+		}
+	}
+	/*NOTREACHED*/
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/strerror.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/strerror.c
new file mode 100644
index 000000000..0a509f79f
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/clib/strerror.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strerror.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+char *
+strerror(num)
+	int num;
+{
+	extern int sys_nerr;
+	extern char *sys_errlist[];
+#define	UPREFIX	"Unknown error: "
+	static char ebuf[40] = UPREFIX;		/* 64-bit number + slop */
+	register unsigned int errnum;
+	register char *p, *t;
+	char tmp[40];
+
+	errnum = num;				/* convert to unsigned */
+	if (errnum < sys_nerr)
+		return(sys_errlist[errnum]);
+
+	/* Do this by hand, so we don't include stdio(3). */
+	t = tmp;
+	do {
+		*t++ = "0123456789"[errnum % 10];
+	} while (errnum /= 10);
+	for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+		*p++ = *--t;
+		if (t <= tmp)
+			break;
+	}
+	return(ebuf);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/configure.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/configure.in
new file mode 100644
index 000000000..5c0455e24
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/configure.in
@@ -0,0 +1,95 @@
+K5_AC_INIT(db/db.c)
+AC_CONFIG_HEADER(include/config.h include/db-config.h)
+build_dynobj=yes
+CONFIG_RULES
+
+AC_PATH_PROG(FALSE,false,:)
+AC_PATH_PROG(SH,sh,$FALSE)
+AC_PATH_PROG(SH5,sh5,$FALSE)
+AC_PATH_PROG(BASH,bash,$FALSE)
+
+AC_CACHE_CHECK([checking for shell with functions],local_cv_program_fctsh,
+[if $SH -c 'foo() { true; }; foo' > /dev/null 2>&1; then
+	local_cv_program_fctsh=$SH
+else
+	if $SH5 -c 'foo() { true; }; foo' > /dev/null 2>&1; then
+		local_cv_program_fctsh=$SH5
+	else
+		if $BASH -c 'foo() { true; }; foo' > /dev/null 2>&1; then
+			local_cv_program_fctsh=$BASH
+		else
+			local_cv_program_fctsh=$FALSE
+		fi
+	fi
+fi])
+
+FCTSH=$local_cv_program_fctsh
+AC_SUBST(FCTSH)
+
+dnl checks for libraries
+dnl checks for header files
+AC_CHECK_HEADERS(unistd.h stdint.h inttypes.h)
+dnl checks for typedefs
+AC_TYPE_SIZE_T
+
+dnl AC_COMPILE_TYPE(TYPE, DEFAULT)
+AC_DEFUN(AC_COMPILE_TYPE,
+[AC_REQUIRE([AC_HEADER_STDC])dnl
+AC_MSG_CHECKING(for $1)
+AC_CACHE_VAL(ac_cv_type_$1,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif], [$1 test_variable;], ac_cv_type_$1=yes, ac_cv_type_$1=no)])dnl
+AC_MSG_RESULT($ac_cv_type_$1)
+if test $ac_cv_type_$1 = no; then
+  AC_DEFINE($1, $2, [Define to \`$2' if not defined on system])
+fi
+])
+
+
+AC_CHECK_TYPE(ssize_t, int)
+
+AC_CHECK_TYPE(u_char, unsigned char)
+AC_CHECK_TYPE(u_int, unsigned int)
+AC_CHECK_TYPE(u_long, unsigned long)
+
+AC_CHECK_TYPE(int8_t, signed char)
+AC_CHECK_TYPE(u_int8_t, unsigned char)
+AC_CHECK_TYPE(int16_t, short)
+AC_CHECK_TYPE(u_int16_t, unsigned short)
+AC_COMPILE_TYPE(int32_t, int)
+AC_COMPILE_TYPE(u_int32_t, unsigned int)
+
+dnl checks for structures
+dnl checks for compiler characteristics
+dnl AC_C_BIGENDIAN - No, check at compile time; Darwin can build for multiple
+dnl                  targets in one tree.
+AC_CHECK_HEADERS(endian.h machine/endian.h sys/param.h)
+dnl sys/param.h for AIX 4.3.3 (actually sys/machine.h)
+dnl There's also sys/endian.h on IRIX, but we already check _MIPSE{L,B}.
+AC_C_CONST
+
+dnl checks for library functions
+AC_CHECK_FUNC(memmove, ,
+[MEMMOVE_OBJ=memmove.o
+AC_DEFINE(memmove, kdb2__memmove,[Define to kdb2__memmove to provide private memmove function])
+AC_DEFINE(MEMMOVE,1,[Define if memmove.o is compiled in])])
+AC_SUBST(MEMMOVE_OBJ)
+
+AC_CHECK_FUNC(mkstemp, ,
+[MKSTEMP_OBJ=mkstemp.o
+AC_DEFINE(mkstemp, kdb2__mkstemp,[Define to \`kdb2__mkstemp' to provide private mkstemp function])])
+AC_SUBST(MKSTEMP_OBJ)
+
+AC_CHECK_FUNC(strerror, ,
+[STRERROR_OBJ=strerror.o
+AC_DEFINE(strerror, kdb2__strerror,[Define to \`kdb2__strerror' to provide private strerror function])])
+AC_SUBST(STRERROR_OBJ)
+
+KRB5_BUILD_LIBRARY
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_PROGRAM
+KRB5_RUN_FLAGS
+AC_CONFIG_FILES(include/generated.stmp:Makefile.in)
+V5_AC_OUTPUT_MAKEFILE(. hash btree db mpool recno clib test)
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.in
new file mode 100644
index 000000000..e40c69186
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.in
@@ -0,0 +1,11 @@
+thisconfigdir=./..
+myfulldir=plugins/kdb/db2/libdb2/db
+mydir=db
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+STLIBOBJS=db.o
+
+LOCALINCLUDES=	-I. -I$(srcdir)/../include -I../include -I$(srcdir)/../mpool
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.inc b/krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.inc
new file mode 100644
index 000000000..59478ba19
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/db/Makefile.inc
@@ -0,0 +1,5 @@
+#       @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/db/db
+
+SRCS+=	db.c
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/db/db.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/db/db.c
new file mode 100644
index 000000000..fba779534
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/db/db.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)db.c	8.4 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "db-int.h"
+
+DB *
+kdb2_dbopen(fname, flags, mode, type, openinfo)
+	const char *fname;
+	int flags, mode;
+	DBTYPE type;
+	const void *openinfo;
+{
+
+#define	DB_FLAGS	(DB_LOCK | DB_SHMEM | DB_TXN)
+#define	USE_OPEN_FLAGS							\
+	(O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY |		\
+	 O_RDWR | O_SHLOCK | O_TRUNC | O_BINARY)
+
+	if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
+		switch (type) {
+		case DB_BTREE:
+			return (__bt_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		case DB_HASH:
+			return (__hash_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		case DB_RECNO:
+			return (__rec_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		}
+	errno = EINVAL;
+	return (NULL);
+}
+
+static int
+__dberr()
+{
+	return (RET_ERROR);
+}
+
+/*
+ * __DBPANIC -- Stop.
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB structure.
+ */
+void
+__dbpanic(dbp)
+	DB *dbp;
+{
+	/* The only thing that can succeed is a close. */
+	dbp->del = (int (*)())__dberr;
+	dbp->fd = (int (*)())__dberr;
+	dbp->get = (int (*)())__dberr;
+	dbp->put = (int (*)())__dberr;
+	dbp->seq = (int (*)())__dberr;
+	dbp->sync = (int (*)())__dberr;
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/btree.3.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/btree.3.ps
new file mode 100644
index 000000000..c79c97232
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/btree.3.ps
@@ -0,0 +1,366 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 132.34(BTREE\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 132.34(anual BTREE\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72 84 S
+(ME).18 E F0(btree \255 btree database access method)108 96 Q F1(SYNOPSIS)72
+112.8 Q/F2 10/Times-Bold@0 SF(#include <sys/types.h>)108 124.8 Q(#include <db)
+108 136.8 Q(.h>)-.4 E F1(DESCRIPTION)72 153.6 Q F0 .198(The routine)108 165.6 R
+/F3 10/Times-Italic@0 SF(dbopen)2.698 E F0 .198(is the library interf)2.698 F
+.198(ace to database \214les.)-.1 F .198
+(One of the supported \214le formats is btree \214les.)5.198 F .974
+(The general description of the database access methods is in)108 177.6 R F3
+(dbopen)3.475 E F0 .975(\(3\), this manual page describes only).24 F
+(the btree speci\214c information.)108 189.6 Q(The btree data structure is a s\
+orted, balanced tree structure storing associated k)108 206.4 Q -.15(ey)-.1 G
+(/data pairs.).15 E .504(The btree access method speci\214c data structure pro)
+108 223.2 R .504(vided to)-.15 F F3(dbopen)3.004 E F0 .503
+(is de\214ned in the <db)3.003 F .503(.h> include \214le as)-.4 F(follo)108
+235.2 Q(ws:)-.25 E(typedef struct {)108 252 Q(u_long \215ags;)144 264 Q
+(u_int cachesize;)144 276 Q(inde)144 288 Q(x_t psize;)-.15 E(int lorder;)144
+300 Q(int mink)144 312 Q -.15(ey)-.1 G(page;).15 E
+(int \(*compare\)\(const DBT *k)144 324 Q -.15(ey)-.1 G(1, const DBT *k).15 E
+-.15(ey)-.1 G(2\);).15 E(int \(*pre\214x\)\(const DBT *k)144 336 Q -.15(ey)-.1
+G(1, const DBT *k).15 E -.15(ey)-.1 G(2\);).15 E 2.5(}B)108 348 S(TREEINFO;)
+121.97 348 Q(The elements of this structure are as follo)108 364.8 Q(ws:)-.25 E
+14.61(\215ags The)108 381.6 R(\215ag v)2.5 E(alue is speci\214ed by)-.25 E F3
+(or)2.5 E F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)313.2 381.6 S(he follo)321.81
+381.6 Q(wing v)-.25 E(alues:)-.25 E(R_DUP)144 398.4 Q 1.296(Permit duplicate k)
+180 410.4 R -.15(ey)-.1 G 3.796(si).15 G 3.796(nt)275.578 410.4 S 1.296
+(he tree, i.e. permit insertion if the k)287.154 410.4 R 1.596 -.15(ey t)-.1 H
+3.796(ob).15 G 3.796(ei)466.878 410.4 S 1.296(nserted already)477.894 410.4 R
+-.15(ex)180 422.4 S 1.935(ists in the tree.).15 F 1.935(The def)6.935 F 1.935
+(ault beha)-.1 F(vior)-.2 E 4.435(,a)-.4 G 4.435(sd)358.215 422.4 S 1.935
+(escribed in)371.54 422.4 R F3(dbopen)4.435 E F0 1.935(\(3\), is to o).24 F
+-.15(ve)-.15 G 1.935(rwrite a).15 F .148(matching k)180 434.4 R .448 -.15(ey w)
+-.1 H .148(hen inserting a ne).15 F 2.649(wk)-.25 G .449 -.15(ey o)329.709
+434.4 T 2.649(rt).15 G 2.649(of)355.407 434.4 S .149(ail if the R_NOO)366.286
+434.4 R(VER)-.5 E .149(WRITE \215ag is speci-)-.55 F 5.972(\214ed. The)180
+446.4 R 3.472(R_DUP \215ag is o)5.972 F -.15(ve)-.15 G 3.472
+(rridden by the R_NOO).15 F(VER)-.5 E 3.471(WRITE \215ag, and if the)-.55 F
+(R_NOO)180 458.4 Q(VER)-.5 E .781
+(WRITE \215ag is speci\214ed, attempts to insert duplicate k)-.55 F -.15(ey)-.1
+G 3.282(si).15 G .782(nto the tree will)474.604 458.4 R -.1(fa)180 470.4 S(il.)
+.1 E 1.13(If the database contains duplicate k)180 487.2 R -.15(ey)-.1 G 1.129
+(s, the order of retrie).15 F -.25(va)-.25 G 3.629(lo).25 G 3.629(fk)439.644
+487.2 S -.15(ey)451.503 487.2 S 1.129(/data pairs is unde-).15 F .837
+(\214ned if the)180 499.2 R F3 -.1(ge)3.337 G(t).1 E F0 .837
+(routine is used, ho)3.337 F(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G F3(seq)3.737
+E F0 .838(routine calls with the R_CURSOR \215ag set)3.337 F(will al)180 511.2
+Q -.1(wa)-.1 G(ys return the logical `).1 E(`\214rst')-.74 E 2.5('o)-.74 G 2.5
+(fa)333.85 511.2 S .3 -.15(ny g)344.12 511.2 T(roup of duplicate k).15 E -.15
+(ey)-.1 G(s.).15 E(cachesize)108 528 Q 3.056(As)144 540 S .556
+(uggested maximum size \(in bytes\) of the memory cache.)158.166 540 R .555
+(This v)5.556 F .555(alue is)-.25 F F2(only)3.055 E F0(advisory)3.055 E 3.055
+(,a)-.65 G .555(nd the)514.725 540 R .759
+(access method will allocate more memory rather than f)144 552 R 3.259
+(ail. Since)-.1 F -2.15 -.25(ev e)3.259 H .76(ry search e).25 F .76
+(xamines the root)-.15 F .055
+(page of the tree, caching the most recently used pages substantially impro)144
+564 R -.15(ve)-.15 G 2.554(sa).15 G .054(ccess time.)459.578 564 R .054
+(In addi-)5.054 F .661(tion, ph)144 576 R .662(ysical writes are delayed as lo\
+ng as possible, so a moderate cache can reduce the number)-.05 F .601
+(of I/O operations signi\214cantly)144 588 R 5.601(.O)-.65 G -.15(bv)280.744
+588 S(iously).15 E 3.101(,u)-.65 G .601(sing a cache increases \(b)324.995 588
+R .6(ut only increases\) the lik)-.2 F(eli-)-.1 E .19(hood of corruption or lo\
+st data if the system crashes while a tree is being modi\214ed.)144 600 R(If)
+5.191 E F3(cac)2.691 E(hesize)-.15 E F0(is)2.691 E 2.5(0\()144 612 S
+(no size is speci\214ed\) a def)154.83 612 Q(ault cache is used.)-.1 E 12.95
+(psize P)108 628.8 R .45
+(age size is the size \(in bytes\) of the pages used for nodes in the tree.)
+-.15 F .449(The minimum page size is)5.449 F .442
+(512 bytes and the maximum page size is 64K.)144 640.8 R(If)5.442 E F3(psize)
+2.942 E F0 .442(is 0 \(no page size is speci\214ed\) a page size)2.942 F
+(is chosen based on the underlying \214le system I/O block size.)144 652.8 Q
+9.62(lorder The)108 669.6 R 1.597(byte order for inte)4.097 F 1.596
+(gers in the stored database metadata.)-.15 F 1.596
+(The number should represent the)6.596 F .688(order as an inte)144 681.6 R .689
+(ger; for e)-.15 F .689(xample, big endian order w)-.15 F .689
+(ould be the number 4,321.)-.1 F(If)5.689 E F3(lor)3.189 E(der)-.37 E F0 .689
+(is 0 \(no)3.189 F(order is speci\214ed\) the current host order is used.)144
+693.6 Q 174.135(4.4BSD June)72 732 R(4, 1993)2.5 E(1)535 732 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 132.34(BTREE\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 132.34(anual BTREE\(3\))340.17 48 R(mink)108 84 Q -.15(ey)-.1 G(page).15
+E 1.423(The minimum number of k)144 96 R -.15(ey)-.1 G 3.923(sw).15 G 1.422
+(hich will be stored on an)282.245 96 R 3.922(ys)-.15 G 1.422(ingle page.)
+400.618 96 R 1.422(This v)6.422 F 1.422(alue is used to)-.25 F .257
+(determine which k)144 108 R -.15(ey)-.1 G 2.757(sw).15 G .257
+(ill be stored on o)242.001 108 R -.15(ve)-.15 G(r\215o).15 E 2.757(wp)-.25 G
+.257(ages, i.e. if a k)348.006 108 R .558 -.15(ey o)-.1 H 2.758(rd).15 G .258
+(ata item is longer than the)435.11 108 R 1.102(pagesize di)144 120 R 1.102
+(vided by the mink)-.25 F -.15(ey)-.1 G 1.102(page v).15 F 1.102
+(alue, it will be stored on o)-.25 F -.15(ve)-.15 G(r\215o).15 E 3.602(wp)-.25
+G 1.102(ages instead of in the)451.164 120 R(page itself.)144 132 Q(If)5 E/F1
+10/Times-Italic@0 SF(mink)2.5 E -.3(ey)-.1 G(pa).3 E -.1(ge)-.1 G F0
+(is 0 \(no minimum number of k)2.6 E -.15(ey)-.1 G 2.5(si).15 G 2.5(ss)392.84
+132 S(peci\214ed\) a v)403.12 132 Q(alue of 2 is used.)-.25 E(compare)108 148.8
+Q .751(Compare is the k)144 160.8 R 1.051 -.15(ey c)-.1 H .751
+(omparison function.).15 F .751(It must return an inte)5.751 F .752
+(ger less than, equal to, or greater)-.15 F .913(than zero if the \214rst k)144
+172.8 R 1.213 -.15(ey a)-.1 H -.18(rg).15 G .913
+(ument is considered to be respecti).18 F -.15(ve)-.25 G .913
+(ly less than, equal to, or greater).15 F .352(than the second k)144 184.8 R
+.652 -.15(ey a)-.1 H -.18(rg).15 G 2.852(ument. The).18 F .353
+(same comparison function must be used on a gi)2.852 F -.15(ve)-.25 G 2.853(nt)
+.15 G .353(ree e)503.127 184.8 R -.15(ve)-.25 G(ry).15 E .817
+(time it is opened.)144 196.8 R(If)5.817 E F1(compar)3.317 E(e)-.37 E F0 .817
+(is NULL \(no comparison function is speci\214ed\), the k)3.317 F -.15(ey)-.1 G
+3.316(sa).15 G .816(re com-)508.364 196.8 R(pared le)144 208.8 Q(xically)-.15 E
+2.5(,w)-.65 G(ith shorter k)214.57 208.8 Q -.15(ey)-.1 G 2.5(sc).15 G
+(onsidered less than longer k)282.92 208.8 Q -.15(ey)-.1 G(s.).15 E 10.17
+(pre\214x Pre\214x)108 225.6 R .291(is the pre\214x comparison function.)2.791
+F .292(If speci\214ed, this routine must return the number of bytes)5.291 F
+.937(of the second k)144 237.6 R 1.237 -.15(ey a)-.1 H -.18(rg).15 G .937
+(ument which are necessary to determine that it is greater than the \214rst k)
+.18 F -.15(ey)-.1 G(ar)144 249.6 Q 3.477(gument. If)-.18 F .977(the k)3.477 F
+-.15(ey)-.1 G 3.477(sa).15 G .977(re equal, the k)241.898 249.6 R 1.277 -.15
+(ey l)-.1 H .978(ength should be returned.).15 F .978
+(Note, the usefulness of this)5.978 F .558(routine is v)144 261.6 R .558
+(ery data dependent, b)-.15 F .558
+(ut, in some data sets can produce signi\214cantly reduced tree sizes)-.2 F
+.354(and search times.)144 273.6 R(If)5.354 E F1(pr)2.854 E(e\214x)-.37 E F0
+.354(is NULL \(no pre\214x function is speci\214ed\),)2.854 F/F2 10
+/Times-Bold@0 SF(and)2.854 E F0 .354(no comparison function)2.854 F .193
+(is speci\214ed, a def)144 285.6 R .193(ault le)-.1 F .193
+(xical comparison routine is used.)-.15 F(If)5.192 E F1(pr)2.692 E(e\214x)-.37
+E F0 .192(is NULL and a comparison rou-)2.692 F
+(tine is speci\214ed, no pre\214x comparison is done.)144 297.6 Q .79
+(If the \214le already e)108 314.4 R .79(xists \(and the O_TR)-.15 F .79
+(UNC \215ag is not speci\214ed\), the v)-.4 F .79
+(alues speci\214ed for the parameters)-.25 F
+(\215ags, lorder and psize are ignored in f)108 326.4 Q -.2(avo)-.1 G 2.5(ro).2
+G 2.5(ft)284.4 326.4 S(he v)293.01 326.4 Q(alues used when the tree w)-.25 E
+(as created.)-.1 E -.15(Fo)108 343.2 S(rw).15 E
+(ard sequential scans of a tree are from the least k)-.1 E .3 -.15(ey t)-.1 H
+2.5(ot).15 G(he greatest.)348.55 343.2 Q 1.043(Space freed up by deleting k)108
+360 R -.15(ey)-.1 G 1.043(/data pairs from the tree is ne).15 F -.15(ve)-.25 G
+3.543(rr).15 G 1.043(eclaimed, although it is normally made)378.686 360 R -.2
+(av)108 372 S 1.394(ailable for reuse.)-.05 F 1.394
+(This means that the btree storage structure is gro)6.394 F(w-only)-.25 E 6.395
+(.T)-.65 G 1.395(he only solutions are to)441.09 372 R -.2(avo)108 384 S(id e)
+.2 E(xcessi)-.15 E .3 -.15(ve d)-.25 H
+(eletions, or to create a fresh tree periodically from a scan of an e).15 E
+(xisting one.)-.15 E .344(Searches, insertions, and deletions in a btree will \
+all complete in O lg base N where base is the a)108 400.8 R -.15(ve)-.2 G .343
+(rage \214ll).15 F -.1(fa)108 412.8 S(ctor).1 E 5.798(.O)-.55 G .799
+(ften, inserting ordered data into btrees results in a lo)146.188 412.8 R 3.299
+<778c>-.25 G .799(ll f)377.505 412.8 R(actor)-.1 E 5.799(.T)-.55 G .799
+(his implementation has been)423.443 412.8 R(modi\214ed to mak)108 424.8 Q 2.5
+(eo)-.1 G(rdered insertion the best case, resulting in a much better than norm\
+al page \214ll f)185.4 424.8 Q(actor)-.1 E(.)-.55 E/F3 9/Times-Bold@0 SF
+(SEE ALSO)72 441.6 Q F1(dbopen)108 453.6 Q F0(\(3\),).24 E F1(hash)2.5 E F0
+(\(3\),).28 E F1(mpool)2.5 E F0(\(3\),).51 E F1 -.37(re)2.5 G(cno).37 E F0
+(\(3\)).18 E F1(The Ubiquitous B-tr)108 477.6 Q(ee)-.37 E F0 2.5(,D).18 G
+(ouglas Comer)209.47 477.6 Q 2.5(,A)-.4 G(CM Comput. Surv)276.72 477.6 Q 2.5
+(.1)-.65 G(1, 2 \(June 1979\), 121-138.)360.25 477.6 Q F1(Pr)108 501.6 Q 1.588
+(e\214x B-tr)-.37 F(ees)-.37 E F0 4.088(,B).27 G 1.587(ayer and Unterauer)
+177.636 501.6 R 4.087(,A)-.4 G 1.587(CM T)270.447 501.6 R 1.587
+(ransactions on Database Systems, V)-.35 F 1.587(ol. 2, 1 \(March 1977\),)-1.29
+F(11-26.)108 513.6 Q F1(The Art of Computer Pr)108 537.6 Q -.1(og)-.45 G -.15
+(ra).1 G(mming V).15 E(ol. 3: Sorting and Sear)-1.11 E -.15(ch)-.37 G(ing).15 E
+F0 2.5(,D).22 G(.E. Knuth, 1968, pp 471-480.)382 537.6 Q F3 -.09(BU)72 554.4 S
+(GS).09 E F0(Only big and little endian byte order is supported.)108 566.4 Q
+174.135(4.4BSD June)72 732 R(4, 1993)2.5 E(2)535 732 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/dbopen.3.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/dbopen.3.ps
new file mode 100644
index 000000000..c621bef97
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/dbopen.3.ps
@@ -0,0 +1,508 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 4
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.01(DBOPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.01(anual DBOPEN\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72
+84 S(ME).18 E F0(dbopen \255 database access methods)108 96 Q F1(SYNOPSIS)72
+112.8 Q/F2 10/Times-Bold@0 SF(#include <sys/types.h>)108 124.8 Q
+(#include <limits.h>)108 136.8 Q(#include <db)108 148.8 Q(.h>)-.4 E(DB *)108
+172.8 Q(dbopen\(const char *\214le, int \215ags, int mode, DBTYPE type,)108
+184.8 Q(const v)158 196.8 Q(oid *openinf)-.1 E(o\);)-.25 E F1(DESCRIPTION)72
+213.6 Q/F3 10/Times-Italic@0 SF(Dbopen)108 225.6 Q F0 .032
+(is the library interf)2.532 F .031(ace to database \214les.)-.1 F .031
+(The supported \214le formats are btree, hashed and UNIX \214le)5.031 F 2.82
+(oriented. The)108 237.6 R .32
+(btree format is a representation of a sorted, balanced tree structure.)2.82 F
+.321(The hashed format is an)5.321 F -.15(ex)108 249.6 S .424
+(tensible, dynamic hashing scheme.).15 F .423
+(The \215at-\214le format is a byte stream \214le with \214x)5.423 F .423
+(ed or v)-.15 F .423(ariable length)-.25 F 2.906(records. The)108 261.6 R .407
+(formats and \214le format speci\214c information are described in detail in t\
+heir respecti)2.906 F .707 -.15(ve m)-.25 H(anual).15 E(pages)108 273.6 Q F3
+(btr)2.5 E(ee)-.37 E F0(\(3\),).18 E F3(hash)2.5 E F0(\(3\) and).28 E F3 -.37
+(re)2.5 G(cno).37 E F0(\(3\).).18 E .433(Dbopen opens)108 290.4 R F3(\214le)
+2.933 E F0 .433(for reading and/or writing.)2.933 F .433(Files ne)5.433 F -.15
+(ve)-.25 G 2.933(ri).15 G .433(ntended to be preserv)346.737 290.4 R .433
+(ed on disk may be created)-.15 F(by setting the \214le parameter to NULL.)108
+302.4 Q(The)108 319.2 Q F3<8d61>4.661 E(gs)-.1 E F0(and)4.661 E F3 2.161
+(mode ar)4.661 F(guments)-.37 E F0 2.161(are as speci\214ed to the)4.661 F F3
+(open)4.661 E F0 2.162(\(2\) routine, ho).24 F(we)-.25 E -.15(ve)-.25 G 2.962
+-.4(r, o).15 H 2.162(nly the O_CREA).4 F -.74(T,)-1.11 G .128
+(O_EXCL, O_EXLOCK, O_NONBLOCK, O_RDONL)108 331.2 R 2.708 -1.29(Y, O)-1 H(_RD)
+1.29 E .128(WR, O_SHLOCK and O_TR)-.3 F .127(UNC \215ags are)-.4 F 2.5
+(meaningful. \(Note,)108 343.2 R(opening a database \214le O_WR)2.5 E(ONL)-.4 E
+2.5(Yi)-1 G 2.5(sn)342.67 343.2 S(ot possible.\))354.06 343.2 Q(The)108 360 Q
+F3(type)5.337 E F0(ar)5.337 E 2.837
+(gument is of type DBTYPE \(as de\214ned in the <db)-.18 F 2.838
+(.h> include \214le\) and may be set to)-.4 F(DB_BTREE, DB_HASH or DB_RECNO.)
+108 372 Q(The)108 388.8 Q F3(openinfo)2.85 E F0(ar)2.85 E .349(gument is a poi\
+nter to an access method speci\214c structure described in the access method')
+-.18 F(s)-.55 E .03(manual page.)108 400.8 R(If)5.03 E F3(openinfo)2.53 E F0
+.031(is NULL, each access method will use def)2.53 F .031
+(aults appropriate for the system and the)-.1 F(access method.)108 412.8 Q F3
+(Dbopen)108 429.6 Q F0 .416
+(returns a pointer to a DB structure on success and NULL on error)2.917 F 5.416
+(.T)-.55 G .416(he DB structure is de\214ned in)423.21 429.6 R(the <db)108
+441.6 Q(.h> include \214le, and contains at least the follo)-.4 E
+(wing \214elds:)-.25 E(typedef struct {)108 465.6 Q(DBTYPE type;)144 477.6 Q
+(int \(*close\)\(const DB *db\);)144 489.6 Q
+(int \(*del\)\(const DB *db, const DBT *k)144 501.6 Q -.15(ey)-.1 G 2.5(,u)-.5
+G(_int \215ags\);)318.92 501.6 Q(int \(*fd\)\(const DB *db\);)144 513.6 Q
+(int \(*get\)\(const DB *db, DBT *k)144 525.6 Q -.15(ey)-.1 G 2.5(,D)-.5 G
+(BT *data, u_int \215ags\);)297.53 525.6 Q(int \(*put\)\(const DB *db, DBT *k)
+144 537.6 Q -.15(ey)-.1 G 2.5(,c)-.5 G(onst DBT *data,)295.31 537.6 Q
+(u_int \215ags\);)194 549.6 Q(int \(*sync\)\(const DB *db, u_int \215ags\);)144
+561.6 Q(int \(*seq\)\(const DB *db, DBT *k)144 573.6 Q -.15(ey)-.1 G 2.5(,D)-.5
+G(BT *data, u_int \215ags\);)298.64 573.6 Q 2.5(}D)108 585.6 S(B;)122.52 585.6
+Q .101
+(These elements describe a database type and a set of functions performing v)
+108 602.4 R .101(arious actions.)-.25 F .101(These functions)5.101 F(tak)108
+614.4 Q 3.039(eap)-.1 G .539(ointer to a structure as returned by)140.078 614.4
+R F3(dbopen)3.038 E F0 3.038(,a).24 G .538
+(nd sometimes one or more pointers to k)323.196 614.4 R -.15(ey)-.1 G .538
+(/data struc-).15 F(tures and a \215ag v)108 626.4 Q(alue.)-.25 E 16.28
+(type The)108 643.2 R
+(type of the underlying access method \(and \214le format\).)2.5 E 12.95
+(close A)108 660 R .988(pointer to a routine to \215ush an)3.488 F 3.489(yc)
+-.15 G .989(ached information to disk, free an)293.968 660 R 3.489(ya)-.15 G
+.989(llocated resources, and)446.662 660 R .112
+(close the underlying \214le\(s\).)144 672 R .111(Since k)5.112 F -.15(ey)-.1 G
+.111(/data pairs may be cached in memory).15 F 2.611(,f)-.65 G .111
+(ailing to sync the \214le)455.666 672 R .494(with a)144 684 R F3(close)2.994 E
+F0(or)2.994 E F3(sync)2.994 E F0 .495
+(function may result in inconsistent or lost information.)2.994 F F3(Close)
+5.495 E F0 .495(routines return)2.995 F(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15
+G(istrib)132.57 732 Q 89.875(ution September)-.2 F(13, 1993)2.5 E(1)535 732 Q
+EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.01(DBOPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.01(anual DBOPEN\(3\))340.17 48 R(-1 on error \(setting)144 84 Q
+/F1 10/Times-Italic@0 SF(errno)2.5 E F0 2.5(\)a).18 G(nd 0 on success.)254.43
+84 Q 21.28(del A)108 100.8 R(pointer to a routine to remo)2.5 E .3 -.15(ve k)
+-.15 H -.15(ey).05 G(/data pairs from the database.).15 E(The parameter)144
+117.6 Q F1<8d61>2.5 E(g)-.1 E F0(may be set to the follo)2.5 E(wing v)-.25 E
+(alue:)-.25 E(R_CURSOR)144 134.4 Q .289
+(Delete the record referenced by the cursor)180 146.4 R 5.288(.T)-.55 G .288
+(he cursor must ha)363.342 146.4 R .588 -.15(ve p)-.2 H(re).15 E .288
+(viously been initial-)-.25 F(ized.)180 158.4 Q F1(Delete)144 175.2 Q F0 .03
+(routines return -1 on error \(setting)2.53 F F1(errno)2.53 E F0 .03
+(\), 0 on success, and 1 if the speci\214ed).18 F F1 -.1(ke)2.53 G(y)-.2 E F0
+-.1(wa)2.53 G 2.53(sn).1 G .03(ot in)521.91 175.2 R(the \214le.)144 187.2 Q
+25.17(fd A)108 204 R .451
+(pointer to a routine which returns a \214le descriptor representati)2.951 F
+.75 -.15(ve o)-.25 H 2.95(ft).15 G .45(he underlying database.)431.73 204 R(A)
+5.45 E .942(\214le descriptor referencing the same \214le will be returned to \
+all processes which call)144 216 R F1(dbopen)3.442 E F0(with)3.442 E 1.629
+(the same)144 228 R F1(\214le)4.129 E F0 4.129(name. This)4.129 F 1.628
+(\214le descriptor may be safely used as a ar)4.128 F 1.628(gument to the)-.18
+F F1(fcntl)4.128 E F0 1.628(\(2\) and).51 F F1(\215oc)144 240 Q(k)-.2 E F0 .425
+(\(2\) locking functions.).67 F .425
+(The \214le descriptor is not necessarily associated with an)5.425 F 2.925(yo)
+-.15 G 2.925(ft)492.7 240 S .425(he under)501.735 240 R(-)-.2 E .198
+(lying \214les used by the access method.)144 252 R .198
+(No \214le descriptor is a)5.198 F -.25(va)-.2 G .198
+(ilable for in memory databases.).25 F F1(Fd)5.198 E F0
+(routines return -1 on error \(setting)144 264 Q F1(errno)2.5 E F0
+(\), and the \214le descriptor on success.).18 E 21.28(get A)108 280.8 R
+(pointer to a routine which is the interf)2.5 E .001(ace for k)-.1 F -.15(ey)
+-.1 G .001(ed retrie).15 F -.25(va)-.25 G 2.501(lf).25 G .001
+(rom the database.)399.755 280.8 R .001(The address and)5.001 F .061
+(length of the data associated with the speci\214ed)144 292.8 R F1 -.1(ke)2.561
+G(y)-.2 E F0 .06(are returned in the structure referenced by)2.561 F F1(data)
+2.56 E F0(.).26 E F1(Get)144 304.8 Q F0(routines return -1 on error \(setting)
+2.5 E F1(errno)2.5 E F0(\), 0 on success, and 1 if the).18 E F1 -.1(ke)2.5 G(y)
+-.2 E F0 -.1(wa)2.5 G 2.5(sn).1 G(ot in the \214le.)471.66 304.8 Q 20.72(put A)
+108 321.6 R(pointer to a routine to store k)2.5 E -.15(ey)-.1 G
+(/data pairs in the database.).15 E(The parameter)144 338.4 Q F1<8d61>2.5 E(g)
+-.1 E F0(may be set to one of the follo)2.5 E(wing v)-.25 E(alues:)-.25 E
+(R_CURSOR)144 355.2 Q .051(Replace the k)180 367.2 R -.15(ey)-.1 G .051
+(/data pair referenced by the cursor).15 F 5.052(.T)-.55 G .052
+(he cursor must ha)393.98 367.2 R .352 -.15(ve p)-.2 H(re).15 E .052
+(viously been)-.25 F(initialized.)180 379.2 Q(R_IAFTER)144 396 Q 1.165
+(Append the data immediately after the data referenced by)180 408 R F1 -.1(ke)
+3.664 G(y)-.2 E F0 3.664(,c).32 G 1.164(reating a ne)446.758 408 R 3.664(wk)
+-.25 G -.15(ey)511.27 408 S(/data).15 E(pair)180 420 Q 6.065(.T)-.55 G 1.065
+(he record number of the appended k)209.675 420 R -.15(ey)-.1 G 1.065
+(/data pair is returned in the).15 F F1 -.1(ke)3.565 G(y)-.2 E F0(structure.)
+3.565 E(\(Applicable only to the DB_RECNO access method.\))180 432 Q(R_IBEFORE)
+144 448.8 Q 1.293(Insert the data immediately before the data referenced by)180
+460.8 R F1 -.1(ke)3.793 G(y)-.2 E F0 3.793(,c).32 G 1.293(reating a ne)446.371
+460.8 R 3.793(wk)-.25 G -.15(ey)511.27 460.8 S(/data).15 E(pair)180 472.8 Q
+6.54(.T)-.55 G 1.54(he record number of the inserted k)210.15 472.8 R -.15(ey)
+-.1 G 1.541(/data pair is returned in the).15 F F1 -.1(ke)4.041 G(y)-.2 E F0
+(structure.)4.041 E(\(Applicable only to the DB_RECNO access method.\))180
+484.8 Q(R_NOO)144 501.6 Q(VER)-.5 E(WRITE)-.55 E(Enter the ne)180 513.6 Q 2.5
+(wk)-.25 G -.15(ey)242.69 513.6 S(/data pair only if the k).15 E .3 -.15(ey d)
+-.1 H(oes not pre).15 E(viously e)-.25 E(xist.)-.15 E(R_SETCURSOR)144 530.4 Q
+1.36(Store the k)180 542.4 R -.15(ey)-.1 G 1.36(/data pair).15 F 3.86(,s)-.4 G
+1.359(etting or initializing the position of the cursor to reference it.)283.94
+542.4 R(\(Applicable only to the DB_BTREE and DB_RECNO access methods.\))180
+554.4 Q .563(R_SETCURSOR is a)144 571.2 R -.25(va)-.2 G .564
+(ilable only for the DB_BTREE and DB_RECNO access methods because).25 F
+(it implies that the k)144 583.2 Q -.15(ey)-.1 G 2.5(sh).15 G -2.25 -.2(av e)
+241.81 583.2 T(an inherent order which does not change.)2.7 E .416
+(R_IAFTER and R_IBEFORE are a)144 600 R -.25(va)-.2 G .416
+(ilable only for the DB_RECNO access method because the).25 F(y)-.15 E 1.221
+(each imply that the access method is able to create ne)144 612 R 3.722(wk)-.25
+G -.15(ey)385.644 612 S 3.722(s. This).15 F 1.222(is only true if the k)3.722 F
+-.15(ey)-.1 G 3.722(sa).15 G(re)532.23 612 Q
+(ordered and independent, record numbers for e)144 624 Q(xample.)-.15 E .289
+(The def)144 640.8 R .289(ault beha)-.1 F .289(vior of the)-.2 F F1(put)2.789 E
+F0 .289(routines is to enter the ne)2.789 F 2.789(wk)-.25 G -.15(ey)388.998
+640.8 S .288(/data pair).15 F 2.788(,r)-.4 G .288(eplacing an)444.284 640.8 R
+2.788(yp)-.15 G(re)503.03 640.8 Q(viously)-.25 E -.15(ex)144 652.8 S(isting k)
+.15 E -.15(ey)-.1 G(.)-.5 E F1(Put)144 669.6 Q F0 .37
+(routines return -1 on error \(setting)2.87 F F1(errno)2.87 E F0 .37
+(\), 0 on success, and 1 if the R_NOO).18 F(VER)-.5 E(WRITE)-.55 E F1<8d61>2.87
+E(g)-.1 E F0 -.1(wa)144 681.6 S 2.5(ss).1 G(et and the k)165.84 681.6 Q .3 -.15
+(ey a)-.1 H(lready e).15 E(xists in the \214le.)-.15 E(4.4 Berk)72 732 Q(ele)
+-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 89.875(ution September)-.2 F(13, 1993)
+2.5 E(2)535 732 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.01(DBOPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.01(anual DBOPEN\(3\))340.17 48 R 20.17(seq A)108 84 R .002
+(pointer to a routine which is the interf)2.502 F .002
+(ace for sequential retrie)-.1 F -.25(va)-.25 G 2.502(lf).25 G .002
+(rom the database.)416.694 84 R .001(The address)5.001 F .219
+(and length of the k)144 96 R .519 -.15(ey a)-.1 H .219
+(re returned in the structure referenced by).15 F/F1 10/Times-Italic@0 SF -.1
+(ke)2.72 G(y)-.2 E F0 2.72(,a).32 G .22(nd the address and length of)426.42 96
+R(the data are returned in the structure referenced by)144 108 Q F1(data)2.5 E
+F0(.).26 E .937(Sequential k)144 124.8 R -.15(ey)-.1 G .937(/data pair retrie)
+.15 F -.25(va)-.25 G 3.437(lm).25 G .936(ay be)289.748 124.8 R .936(gin at an)
+-.15 F 3.436(yt)-.15 G .936(ime, and the position of the `)359.292 124.8 R
+(`cursor')-.74 E 3.436('i)-.74 G 3.436(sn)519.894 124.8 S(ot)532.22 124.8 Q(af)
+144 136.8 Q 1.585(fected by calls to the)-.25 F F1(del)4.085 E F0(,).51 E F1
+-.1(ge)4.085 G(t).1 E F0(,).68 E F1(put)4.086 E F0 4.086(,o).68 G(r)308.452
+136.8 Q F1(sync)4.086 E F0 4.086(routines. Modi\214cations)4.086 F 1.586
+(to the database during a)4.086 F 1.404(sequential scan will be re\215ected in\
+ the scan, i.e. records inserted behind the cursor will not be)144 148.8 R
+(returned while records inserted in front of the cursor will be returned.)144
+160.8 Q(The \215ag v)144 177.6 Q(alue)-.25 E/F2 10/Times-Bold@0 SF(must)2.5 E
+F0(be set to one of the follo)2.5 E(wing v)-.25 E(alues:)-.25 E(R_CURSOR)144
+194.4 Q .523(The data associated with the speci\214ed k)180 206.4 R .824 -.15
+(ey i)-.1 H 3.024(sr).15 G 3.024(eturned. This)367.236 206.4 R(dif)3.024 E .524
+(fers from the)-.25 F F1 -.1(ge)3.024 G(t).1 E F0(routines)3.024 E 1.143
+(in that it sets or initializes the cursor to the location of the k)180 218.4 R
+1.443 -.15(ey a)-.1 H 3.642(sw).15 G 3.642(ell. \(Note,)464.924 218.4 R 1.142
+(for the)3.642 F 1.275(DB_BTREE access method, the returned k)180 230.4 R 1.575
+-.15(ey i)-.1 H 3.775(sn).15 G 1.276(ot necessarily an e)386.425 230.4 R 1.276
+(xact match for the)-.15 F .598(speci\214ed k)180 242.4 R -.15(ey)-.1 G 5.598
+(.T)-.5 G .598(he returned k)246.396 242.4 R .898 -.15(ey i)-.1 H 3.098(st).15
+G .598(he smallest k)325.188 242.4 R .898 -.15(ey g)-.1 H .598
+(reater than or equal to the speci\214ed).15 F -.1(ke)180 254.4 S 1.3 -.65
+(y, p)-.05 H(ermitting partial k).65 E .3 -.15(ey m)-.1 H
+(atches and range searches.\)).15 E(R_FIRST)144 271.2 Q 1.043(The \214rst k)180
+283.2 R -.15(ey)-.1 G 1.044(/data pair of the database is returned, and the cu\
+rsor is set or initialized to).15 F(reference it.)180 295.2 Q(R_LAST)144 312 Q
+.085(The last k)180 324 R -.15(ey)-.1 G .085(/data pair of the database is ret\
+urned, and the cursor is set or initialized to ref-).15 F(erence it.)180 336 Q
+(\(Applicable only to the DB_BTREE and DB_RECNO access methods.\))5 E(R_NEXT)
+144 352.8 Q(Retrie)180 364.8 Q .604 -.15(ve t)-.25 H .304(he k).15 F -.15(ey)
+-.1 G .304(/data pair immediately after the cursor).15 F 5.304(.I)-.55 G 2.804
+(ft)410.622 364.8 S .305(he cursor is not yet set, this is)419.536 364.8 R
+(the same as the R_FIRST \215ag.)180 376.8 Q(R_PREV)144 393.6 Q(Retrie)180
+405.6 Q .755 -.15(ve t)-.25 H .455(he k).15 F -.15(ey)-.1 G .455
+(/data pair immediately before the cursor).15 F 5.455(.I)-.55 G 2.955(ft)419.05
+405.6 S .454(he cursor is not yet set, this)428.115 405.6 R .62
+(is the same as the R_LAST \215ag.)180 417.6 R .621
+(\(Applicable only to the DB_BTREE and DB_RECNO)5.621 F(access methods.\))180
+429.6 Q .911(R_LAST and R_PREV are a)144 446.4 R -.25(va)-.2 G .911
+(ilable only for the DB_BTREE and DB_RECNO access methods).25 F(because the)144
+458.4 Q 2.5(ye)-.15 G(ach imply that the k)202.16 458.4 Q -.15(ey)-.1 G 2.5(sh)
+.15 G -2.25 -.2(av e)302.18 458.4 T(an inherent order which does not change.)
+2.7 E F1(Seq)144 475.2 Q F0 .061(routines return -1 on error \(setting)2.561 F
+F1(errno)2.561 E F0 .061(\), 0 on success and 1 if there are no k).18 F -.15
+(ey)-.1 G .061(/data pairs less).15 F .35
+(than or greater than the speci\214ed or current k)144 487.2 R -.15(ey)-.1 G
+5.349(.I)-.5 G 2.849(ft)346.467 487.2 S .349
+(he DB_RECNO access method is being used,)355.426 487.2 R .025
+(and if the database \214le is a character special \214le and no complete k)144
+499.2 R -.15(ey)-.1 G .025(/data pairs are currently a).15 F -.25(va)-.2 G(il-)
+.25 E(able, the)144 511.2 Q F1(seq)2.5 E F0(routines return 2.)2.5 E 15.17
+(sync A)108 528 R .458(pointer to a routine to \215ush an)2.958 F 2.957(yc)-.15
+G .457(ached information to disk.)289.72 528 R .457
+(If the database is in memory only)5.457 F(,)-.65 E(the)144 540 Q F1(sync)2.5 E
+F0(routine has no ef)2.5 E(fect and will al)-.25 E -.1(wa)-.1 G(ys succeed.).1
+E(The \215ag v)144 556.8 Q(alue may be set to the follo)-.25 E(wing v)-.25 E
+(alue:)-.25 E(R_RECNOSYNC)144 573.6 Q .077(If the DB_RECNO access method is be\
+ing used, this \215ag causes the sync routine to apply)180 585.6 R .75(to the \
+btree \214le which underlies the recno \214le, not the recno \214le itself.)180
+597.6 R .75(\(See the)5.75 F F1(bfname)3.25 E F0(\214eld of the)180 609.6 Q F1
+-.37(re)2.5 G(cno).37 E F0(\(3\) manual page for more information.\)).18 E F1
+(Sync)144 626.4 Q F0(routines return -1 on error \(setting)2.5 E F1(errno)2.5 E
+F0 2.5(\)a).18 G(nd 0 on success.)336.91 626.4 Q/F3 9/Times-Bold@0 SF(KEY/D)72
+643.2 Q -1.35 -.855(AT A)-.315 H -.666(PA)3.105 G(IRS).666 E F0 .134
+(Access to all \214le types is based on k)108 655.2 R -.15(ey)-.1 G .134
+(/data pairs.).15 F .134(Both k)5.134 F -.15(ey)-.1 G 2.634(sa).15 G .134
+(nd data are represented by the follo)359.078 655.2 R .135(wing data)-.25 F
+(structure:)108 667.2 Q(typedef struct {)108 684 Q(4.4 Berk)72 732 Q(ele)-.1 E
+2.5(yD)-.15 G(istrib)132.57 732 Q 89.875(ution September)-.2 F(13, 1993)2.5 E
+(3)535 732 Q EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.01(DBOPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.01(anual DBOPEN\(3\))340.17 48 R -.2(vo)144 84 S(id *data;).2 E
+(size_t size;)144 96 Q 2.5(}D)108 108 S(BT)122.52 108 Q(;)-.55 E
+(The elements of the DBT structure are de\214ned as follo)108 124.8 Q(ws:)-.25
+E 16.84(data A)108 141.6 R(pointer to a byte string.)2.5 E 17.95(size The)108
+158.4 R(length of the byte string.)2.5 E -2.15 -.25(Ke y)108 175.2 T .829(and \
+data byte strings may reference strings of essentially unlimited length althou\
+gh an)3.579 F 3.328(yt)-.15 G 1.028 -.1(wo o)492.894 175.2 T 3.328(ft).1 G(hem)
+522.78 175.2 Q 1.133(must \214t into a)108 187.2 R -.25(va)-.2 G 1.134
+(ilable memory at the same time.).25 F 1.134
+(It should be noted that the access methods pro)6.134 F 1.134(vide no)-.15 F
+(guarantees about byte string alignment.)108 199.2 Q/F1 9/Times-Bold@0 SF(ERR)
+72 216 Q(ORS)-.27 E F0(The)108 228 Q/F2 10/Times-Italic@0 SF(dbopen)3.389 E F0
+.889(routine may f)3.389 F .889(ail and set)-.1 F F2(errno)3.388 E F0 .888
+(for an)3.388 F 3.388(yo)-.15 G 3.388(ft)324.376 228 S .888
+(he errors speci\214ed for the library routines)333.874 228 R F2(open)3.388 E
+F0(\(2\)).24 E(and)108 240 Q F2(malloc)2.5 E F0(\(3\) or the follo).31 E(wing:)
+-.25 E([EFTYPE])108 256.8 Q 2.5<418c>144 268.8 S(le is incorrectly formatted.)
+159.28 268.8 Q([EINV)108 285.6 Q(AL])-1.35 E 2.812(Ap)144 297.6 S .313(aramete\
+r has been speci\214ed \(hash function, pad byte etc.\) that is incompatible w\
+ith the current)159.032 297.6 R .406
+(\214le speci\214cation or which is not meaningful for the function \(for e)144
+309.6 R .405(xample, use of the cursor with-)-.15 F .099
+(out prior initialization\) or there is a mismatch between the v)144 321.6 R .1
+(ersion number of \214le and the softw)-.15 F(are.)-.1 E(The)108 338.4 Q F2
+(close)3.469 E F0 .969(routines may f)3.469 F .969(ail and set)-.1 F F2(errno)
+3.469 E F0 .969(for an)3.469 F 3.469(yo)-.15 G 3.469(ft)320.18 338.4 S .969
+(he errors speci\214ed for the library routines)329.759 338.4 R F2(close)3.468
+E F0(\(2\),).18 E F2 -.37(re)108 350.4 S(ad).37 E F0(\(2\),).77 E F2(write)2.5
+E F0(\(2\),).18 E F2(fr)2.5 E(ee)-.37 E F0(\(3\), or).18 E F2(fsync)2.5 E F0
+(\(2\).).31 E(The)108 367.2 Q F2(del)2.969 E F0(,).51 E F2 -.1(ge)2.969 G(t).1
+E F0(,).68 E F2(put)2.969 E F0(and)2.969 E F2(seq)2.969 E F0 .469
+(routines may f)2.969 F .469(ail and set)-.1 F F2(errno)2.97 E F0 .47(for an)
+2.97 F 2.97(yo)-.15 G 2.97(ft)377.59 367.2 S .47
+(he errors speci\214ed for the library rou-)386.67 367.2 R(tines)108 379.2 Q F2
+-.37(re)2.5 G(ad).37 E F0(\(2\),).77 E F2(write)2.5 E F0(\(2\),).18 E F2(fr)2.5
+E(ee)-.37 E F0(\(3\) or).18 E F2(malloc)2.5 E F0(\(3\).).31 E(The)108 396 Q F2
+(fd)2.5 E F0(routines will f)2.5 E(ail and set)-.1 E F2(errno)2.5 E F0
+(to ENOENT for in memory databases.)2.5 E(The)108 412.8 Q F2(sync)2.5 E F0
+(routines may f)2.5 E(ail and set)-.1 E F2(errno)2.5 E F0(for an)2.5 E 2.5(yo)
+-.15 G 2.5(ft)307.71 412.8 S(he errors speci\214ed for the library routine)
+316.32 412.8 Q F2(fsync)2.5 E F0(\(2\).).31 E F1(SEE ALSO)72 429.6 Q F2(btr)108
+441.6 Q(ee)-.37 E F0(\(3\),).18 E F2(hash)2.5 E F0(\(3\),).28 E F2(mpool)2.5 E
+F0(\(3\),).51 E F2 -.37(re)2.5 G(cno).37 E F0(\(3\)).18 E F2 .904(LIBTP: P)108
+465.6 R(ortable)-.8 E 3.404(,M)-.1 G .904(odular T)189.738 465.6 R -.15(ra)-.55
+G .904(nsactions for UNIX).15 F F0 3.404(,M).94 G(ar)328.884 465.6 Q .904
+(go Seltzer)-.18 F 3.403(,M)-.4 G .903(ichael Olson, USENIX proceedings,)
+392.041 465.6 R -.4(Wi)108 477.6 S(nter 1992.).4 E F1 -.09(BU)72 494.4 S(GS).09
+E F0 .399(The typedef DBT is a mnemonic for `)108 506.4 R .399
+(`data base thang')-.74 F .399(', and w)-.74 F .399
+(as used because noone could think of a rea-)-.1 F(sonable name that w)108
+518.4 Q(asn')-.1 E 2.5(ta)-.18 G(lready used.)216.03 518.4 Q
+(The \214le descriptor interf)108 535.2 Q
+(ace is a kluge and will be deleted in a future v)-.1 E(ersion of the interf)
+-.15 E(ace.)-.1 E(None of the access methods pro)108 552 Q(vide an)-.15 E 2.5
+(yf)-.15 G(orm of concurrent access, locking, or transactions.)275.16 552 Q
+(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 89.875
+(ution September)-.2 F(13, 1993)2.5 E(4)535 732 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.3.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.3.ps
new file mode 100644
index 000000000..18303cfb7
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.3.ps
@@ -0,0 +1,292 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 136.79(HASH\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 136.79(anual HASH\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72 84 S
+(ME).18 E F0(hash \255 hash database access method)108 96 Q F1(SYNOPSIS)72
+112.8 Q/F2 10/Times-Bold@0 SF(#include <sys/types.h>)108 124.8 Q(#include <db)
+108 136.8 Q(.h>)-.4 E F1(DESCRIPTION)72 153.6 Q F0 .29(The routine)108 165.6 R
+/F3 10/Times-Italic@0 SF(dbopen)2.79 E F0 .29(is the library interf)2.79 F .29
+(ace to database \214les.)-.1 F .29
+(One of the supported \214le formats is hash \214les.)5.29 F .974
+(The general description of the database access methods is in)108 177.6 R F3
+(dbopen)3.475 E F0 .975(\(3\), this manual page describes only).24 F
+(the hash speci\214c information.)108 189.6 Q(The hash data structure is an e)
+108 206.4 Q(xtensible, dynamic hashing scheme.)-.15 E .83
+(The access method speci\214c data structure pro)108 223.2 R .83(vided to)-.15
+F F3(dbopen)3.33 E F0 .83(is de\214ned in the <db)3.33 F .83
+(.h> include \214le as fol-)-.4 F(lo)108 235.2 Q(ws:)-.25 E(typedef struct {)
+108 259.2 Q(int bsize;)144 271.2 Q(int cachesize;)144 283.2 Q(int f)144 295.2 Q
+-.1(fa)-.25 G(ctor;).1 E(u_long \(*hash\)\(const v)144 307.2 Q
+(oid *, size_t\);)-.2 E(int lorder;)144 319.2 Q(int nelem;)144 331.2 Q 2.5(}H)
+108 343.2 S(ASHINFO;)122.52 343.2 Q
+(The elements of this structure are as follo)108 360 Q(ws:)-.25 E(bsize)108
+376.8 Q F3(Bsize)144 376.8 Q F0 1.393(de\214nes the hash table b)3.893 F(uck)
+-.2 E 1.393(et size, and is, by def)-.1 F 1.394(ault, 256 bytes.)-.1 F 1.394
+(It may be preferable to)6.394 F
+(increase the page size for disk-resident tables and tables with lar)144 388.8
+Q(ge data items.)-.18 E(cachesize)108 405.6 Q 3.16(As)144 417.6 S .66
+(uggested maximum size, in bytes, of the memory cache.)158.27 417.6 R .659
+(This v)5.659 F .659(alue is)-.25 F F2(only)3.159 E F0(advisory)3.159 E 3.159
+(,a)-.65 G .659(nd the)514.621 417.6 R
+(access method will allocate more memory rather than f)144 429.6 Q(ail.)-.1 E
+-2.1 -.25(ff a)108 446.4 T(ctor).25 E F3(Ffactor)9.7 E F0 .482
+(indicates a desired density within the hash table.)2.981 F .482
+(It is an approximation of the number of)5.482 F -.1(ke)144 458.4 S .429
+(ys allo)-.05 F .429(wed to accumulate in an)-.25 F 2.929(yo)-.15 G .429(ne b)
+291.454 458.4 R(uck)-.2 E .429(et, determining when the hash table gro)-.1 F
+.428(ws or shrinks.)-.25 F(The def)144 470.4 Q(ault v)-.1 E(alue is 8.)-.25 E
+(hash)108 487.2 Q F3(Hash)144 487.2 Q F0 .1(is a user de\214ned hash function.)
+2.6 F .1(Since no hash function performs equally well on all possible)5.1 F
+.924(data, the user may \214nd that the b)144 499.2 R .923
+(uilt-in hash function does poorly on a particular data set.)-.2 F(User)5.923 E
+1.408(speci\214ed hash functions must tak)144 511.2 R 3.909(et)-.1 G 1.609 -.1
+(wo a)293.431 511.2 T -.18(rg).1 G 1.409
+(uments \(a pointer to a byte string and a length\) and).18 F
+(return an u_long to be used as the hash v)144 523.2 Q(alue.)-.25 E 9.62
+(lorder The)108 540 R 1.597(byte order for inte)4.097 F 1.596
+(gers in the stored database metadata.)-.15 F 1.596
+(The number should represent the)6.596 F .688(order as an inte)144 552 R .689
+(ger; for e)-.15 F .689(xample, big endian order w)-.15 F .689
+(ould be the number 4,321.)-.1 F(If)5.689 E F3(lor)3.189 E(der)-.37 E F0 .689
+(is 0 \(no)3.189 F .822(order is speci\214ed\) the current host order is used.)
+144 564 R .822(If the)5.822 F .822(\214le already e)5.822 F .821
+(xists, the speci\214ed v)-.15 F .821(alue is)-.25 F(ignored and the v)144 576
+Q(alue speci\214ed when the tree w)-.25 E(as created is used.)-.1 E(nelem)108
+592.8 Q F3(Nelem)144 592.8 Q F0 .701
+(is an estimate of the \214nal size of the hash table.)3.2 F .701
+(If not set or set too lo)5.701 F 2.001 -.65(w, h)-.25 H .701(ash tables will)
+.65 F -.15(ex)144 604.8 S .448(pand gracefully as k).15 F -.15(ey)-.1 G 2.948
+(sa).15 G .448(re entered, although a slight performance de)255.912 604.8 R
+.447(gradation may be noticed.)-.15 F(The def)144 616.8 Q(ault v)-.1 E
+(alue is 1.)-.25 E .79(If the \214le already e)108 633.6 R .79
+(xists \(and the O_TR)-.15 F .79(UNC \215ag is not speci\214ed\), the v)-.4 F
+.79(alues speci\214ed for the parameters)-.25 F(bsize, f)108 645.6 Q -.1(fa)
+-.25 G(ctor).1 E 2.5(,l)-.4 G(order and nelem are ignored and the v)167.23
+645.6 Q(alues speci\214ed when the tree w)-.25 E(as created are used.)-.1 E
+1.232(If a hash function is speci\214ed,)108 662.4 R F3(hash_open)3.731 E F0
+1.231(will attempt to determine if the hash function speci\214ed is the)3.731 F
+(same as the one with which the database w)108 674.4 Q(as created, and will f)
+-.1 E(ail if it is not.)-.1 E(Backw)108 691.2 Q .861(ard compatible interf)-.1
+F .861(aces to the routines described in)-.1 F F3(dbm)3.362 E F0 .862
+(\(3\), and).32 F F3(ndbm)3.362 E F0 .862(\(3\) are pro).32 F .862(vided, ho)
+-.15 F(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G(4.4 Berk)72 732 Q(ele)-.1 E 2.5
+(yD)-.15 G(istrib)132.57 732 Q 96.815(ution August)-.2 F(17, 1993)2.5 E(1)535
+732 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 136.79(HASH\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 136.79(anual HASH\(3\))340.17 48 R(these interf)108 84 Q
+(aces are not compatible with pre)-.1 E(vious \214le formats.)-.25 E/F1 9
+/Times-Bold@0 SF(SEE ALSO)72 100.8 Q/F2 10/Times-Italic@0 SF(btr)108 112.8 Q
+(ee)-.37 E F0(\(3\),).18 E F2(dbopen)2.5 E F0(\(3\),).24 E F2(mpool)2.5 E F0
+(\(3\),).51 E F2 -.37(re)2.5 G(cno).37 E F0(\(3\)).18 E F2(Dynamic Hash T)108
+136.8 Q(ables)-.92 E F0 2.5(,P).27 G(er)206.79 136.8 Q(-Ak)-.2 E 2.5(eL)-.1 G
+(arson, Communications of the A)242.86 136.8 Q(CM, April 1988.)-.4 E F2 2.5(AN)
+108 160.8 S .3 -.15(ew H)123.28 160.8 T(ash P).15 E(ac)-.8 E(ka)-.2 E .2 -.1
+(ge f)-.1 H(or UNIX).1 E F0 2.5(,M).94 G(ar)248.41 160.8 Q(go Seltzer)-.18 E
+2.5(,U)-.4 G(SENIX Proceedings, W)308.09 160.8 Q(inter 1991.)-.4 E F1 -.09(BU)
+72 177.6 S(GS).09 E F0(Only big and little endian byte order is supported.)108
+189.6 Q(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 96.815
+(ution August)-.2 F(17, 1993)2.5 E(2)535 732 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.usenix.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.usenix.ps
new file mode 100644
index 000000000..acdea0992
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/hash.usenix.ps
@@ -0,0 +1,12209 @@
+%!PS-Adobe-1.0
+%%Creator: utopia:margo (& Seltzer,608-13E,8072,)
+%%Title: stdin (ditroff)
+%%CreationDate: Tue Dec 11 15:06:45 1990
+%%EndComments
+%	@(#)psdit.pro	1.3 4/15/88
+% lib/psdit.pro -- prolog for psdit (ditroff) files
+% Copyright (c) 1984, 1985 Adobe Systems Incorporated. All Rights Reserved.
+% last edit: shore Sat Nov 23 20:28:03 1985
+% RCSID: $Header$
+
+% Changed by Edward Wang (edward@ucbarpa.berkeley.edu) to handle graphics,
+% 17 Feb, 87.
+
+/$DITroff 140 dict def $DITroff begin
+/fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def
+/xi{0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto
+ /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F
+ /pagesave save def}def
+/PB{save /psv exch def currentpoint translate 
+ resolution 72 div dup neg scale 0 0 moveto}def
+/PE{psv restore}def
+/arctoobig 90 def /arctoosmall .05 def
+/m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def
+/tan{dup sin exch cos div}def
+/point{resolution 72 div mul}def
+/dround	{transform round exch round exch itransform}def
+/xT{/devname exch def}def
+/xr{/mh exch def /my exch def /resolution exch def}def
+/xp{}def
+/xs{docsave restore end}def
+/xt{}def
+/xf{/fontname exch def /slotno exch def fontnames slotno get fontname eq not
+ {fonts slotno fontname findfont put fontnames slotno fontname put}if}def
+/xH{/fontheight exch def F}def
+/xS{/fontslant exch def F}def
+/s{/fontsize exch def /fontheight fontsize def F}def
+/f{/fontnum exch def F}def
+/F{fontheight 0 le{/fontheight fontsize def}if
+ fonts fontnum get fontsize point 0 0 fontheight point neg 0 0 m1 astore
+ fontslant 0 ne{1 0 fontslant tan 1 0 0 m2 astore m3 concatmatrix}if
+ makefont setfont .04 fontsize point mul 0 dround pop setlinewidth}def
+/X{exch currentpoint exch pop moveto show}def
+/N{3 1 roll moveto show}def
+/Y{exch currentpoint pop exch moveto show}def
+/S{show}def
+/ditpush{}def/ditpop{}def
+/AX{3 -1 roll currentpoint exch pop moveto 0 exch ashow}def
+/AN{4 2 roll moveto 0 exch ashow}def
+/AY{3 -1 roll currentpoint pop exch moveto 0 exch ashow}def
+/AS{0 exch ashow}def
+/MX{currentpoint exch pop moveto}def
+/MY{currentpoint pop exch moveto}def
+/MXY{moveto}def
+/cb{pop}def	% action on unknown char -- nothing for now
+/n{}def/w{}def
+/p{pop showpage pagesave restore /pagesave save def}def
+/Dt{/Dlinewidth exch def}def 1 Dt
+/Ds{/Ddash exch def}def -1 Ds
+/Di{/Dstipple exch def}def 1 Di
+/Dsetlinewidth{2 Dlinewidth mul setlinewidth}def
+/Dsetdash{Ddash 4 eq{[8 12]}{Ddash 16 eq{[32 36]}
+ {Ddash 20 eq{[32 12 8 12]}{[]}ifelse}ifelse}ifelse 0 setdash}def
+/Dstroke{gsave Dsetlinewidth Dsetdash 1 setlinecap stroke grestore
+ currentpoint newpath moveto}def
+/Dl{rlineto Dstroke}def
+/arcellipse{/diamv exch def /diamh exch def oldmat currentmatrix pop
+ currentpoint translate 1 diamv diamh div scale /rad diamh 2 div def
+ currentpoint exch rad add exch rad -180 180 arc oldmat setmatrix}def
+/Dc{dup arcellipse Dstroke}def
+/De{arcellipse Dstroke}def
+/Da{/endv exch def /endh exch def /centerv exch def /centerh exch def
+ /cradius centerv centerv mul centerh centerh mul add sqrt def
+ /eradius endv endv mul endh endh mul add sqrt def
+ /endang endv endh atan def
+ /startang centerv neg centerh neg atan def
+ /sweep startang endang sub dup 0 lt{360 add}if def
+ sweep arctoobig gt
+ {/midang startang sweep 2 div sub def /midrad cradius eradius add 2 div def
+  /midh midang cos midrad mul def /midv midang sin midrad mul def
+  midh neg midv neg endh endv centerh centerv midh midv Da
+  Da}
+ {sweep arctoosmall ge
+  {/controldelt 1 sweep 2 div cos sub 3 sweep 2 div sin mul div 4 mul def
+   centerv neg controldelt mul centerh controldelt mul
+   endv neg controldelt mul centerh add endh add
+   endh controldelt mul centerv add endv add
+   centerh endh add centerv endv add rcurveto Dstroke}
+  {centerh endh add centerv endv add rlineto Dstroke}
+  ifelse}
+ ifelse}def
+/Dpatterns[
+[%cf[widthbits]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000103810000000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000001038100000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0042660000246600>]
+[8<0000990000990000>]
+[8<0804020180402010>]
+[8<2418814242811824>]
+[8<6699996666999966>]
+[8<8000000008000000>]
+[8<00001c3e363e1c00>]
+[8<0000000000000000>]
+[32<00000040000000c00000004000000040000000e0000000000000000000000000>]
+[32<00000000000060000000900000002000000040000000f0000000000000000000>]
+[32<000000000000000000e0000000100000006000000010000000e0000000000000>]
+[32<00000000000000002000000060000000a0000000f00000002000000000000000>]
+[32<0000000e0000000000000000000000000000000f000000080000000e00000001>]
+[32<0000090000000600000000000000000000000000000007000000080000000e00>]
+[32<00010000000200000004000000040000000000000000000000000000000f0000>]
+[32<0900000006000000090000000600000000000000000000000000000006000000>]]
+[%ug
+[8<0000020000000000>]
+[8<0000020000002000>]
+[8<0004020000002000>]
+[8<0004020000402000>]
+[8<0004060000402000>]
+[8<0004060000406000>]
+[8<0006060000406000>]
+[8<0006060000606000>]
+[8<00060e0000606000>]
+[8<00060e000060e000>]
+[8<00070e000060e000>]
+[8<00070e000070e000>]
+[8<00070e020070e000>]
+[8<00070e020070e020>]
+[8<04070e020070e020>]
+[8<04070e024070e020>]
+[8<04070e064070e020>]
+[8<04070e064070e060>]
+[8<06070e064070e060>]
+[8<06070e066070e060>]
+[8<06070f066070e060>]
+[8<06070f066070f060>]
+[8<060f0f066070f060>]
+[8<060f0f0660f0f060>]
+[8<060f0f0760f0f060>]
+[8<060f0f0760f0f070>]
+[8<0e0f0f0760f0f070>]
+[8<0e0f0f07e0f0f070>]
+[8<0e0f0f0fe0f0f070>]
+[8<0e0f0f0fe0f0f0f0>]
+[8<0f0f0f0fe0f0f0f0>]
+[8<0f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f1f9>]
+[8<bf8f1f9ff9f8f1f9>]
+[8<bf8f1f9ffbf8f1f9>]
+[8<bf8f1fdffbf8f1f9>]
+[8<bf8f1fdffbf8f1fd>]
+[8<ff8f1fdffbf8f1fd>]
+[8<ff8f1fdffff8f1fd>]
+[8<ff8f1ffffff8f1fd>]
+[8<ff8f1ffffff8f1ff>]
+[8<ff9f1ffffff8f1ff>]
+[8<ff9f1ffffff9f1ff>]
+[8<ff9f9ffffff9f1ff>]
+[8<ff9f9ffffff9f9ff>]
+[8<ffbf9ffffff9f9ff>]
+[8<ffbf9ffffffbf9ff>]
+[8<ffbfdffffffbf9ff>]
+[8<ffbfdffffffbfdff>]
+[8<ffffdffffffbfdff>]
+[8<ffffdffffffffdff>]
+[8<fffffffffffffdff>]
+[8<ffffffffffffffff>]]
+[%mg
+[8<8000000000000000>]
+[8<0822080080228000>]
+[8<0204081020408001>]
+[8<40e0400000000000>]
+[8<66999966>]
+[8<8001000010080000>]
+[8<81c36666c3810000>]
+[8<f0e0c08000000000>]
+[16<07c00f801f003e007c00f800f001e003c007800f001f003e007c00f801f003e0>]
+[16<1f000f8007c003e001f000f8007c003e001f800fc007e003f001f8007c003e00>]
+[8<c3c300000000c3c3>]
+[16<0040008001000200040008001000200040008000000100020004000800100020>]
+[16<0040002000100008000400020001800040002000100008000400020001000080>]
+[16<1fc03fe07df0f8f8f07de03fc01f800fc01fe03ff07df8f87df03fe01fc00f80>]
+[8<80>]
+[8<8040201000000000>]
+[8<84cc000048cc0000>]
+[8<9900009900000000>]
+[8<08040201804020100800020180002010>]
+[8<2418814242811824>]
+[8<66999966>]
+[8<8000000008000000>]
+[8<70f8d8f870000000>]
+[8<0814224180402010>]
+[8<aa00440a11a04400>]
+[8<018245aa45820100>]
+[8<221c224180808041>]
+[8<88000000>]
+[8<0855800080550800>]
+[8<2844004482440044>]
+[8<0810204080412214>]
+[8<00>]]]def
+/Dfill{
+ transform /maxy exch def /maxx exch def
+ transform /miny exch def /minx exch def
+ minx maxx gt{/minx maxx /maxx minx def def}if
+ miny maxy gt{/miny maxy /maxy miny def def}if
+ Dpatterns Dstipple 1 sub get exch 1 sub get
+ aload pop /stip exch def /stipw exch def /stiph 128 def
+ /imatrix[stipw 0 0 stiph 0 0]def
+ /tmatrix[stipw 0 0 stiph 0 0]def
+ /minx minx cvi stiph idiv stiph mul def
+ /miny miny cvi stipw idiv stipw mul def
+ gsave eoclip 0 setgray
+ miny stiph maxy{
+  tmatrix exch 5 exch put
+  minx stipw maxx{
+   tmatrix exch 4 exch put tmatrix setmatrix
+   stipw stiph true imatrix {stip} imagemask
+  }for
+ }for
+ grestore
+}def
+/Dp{Dfill Dstroke}def
+/DP{Dfill currentpoint newpath moveto}def
+end
+
+/ditstart{$DITroff begin
+ /nfonts 60 def			% NFONTS makedev/ditroff dependent!
+ /fonts[nfonts{0}repeat]def
+ /fontnames[nfonts{()}repeat]def
+/docsave save def
+}def
+
+% character outcalls
+/oc{
+ /pswid exch def /cc exch def /name exch def
+ /ditwid pswid fontsize mul resolution mul 72000 div def
+ /ditsiz fontsize resolution mul 72 div def
+ ocprocs name known{ocprocs name get exec}{name cb}ifelse
+}def
+/fractm [.65 0 0 .6 0 0] def
+/fraction{
+ /fden exch def /fnum exch def gsave /cf currentfont def
+ cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
+ fnum show rmoveto currentfont cf setfont(\244)show setfont fden show 
+ grestore ditwid 0 rmoveto
+}def
+/oce{grestore ditwid 0 rmoveto}def
+/dm{ditsiz mul}def
+/ocprocs 50 dict def ocprocs begin
+(14){(1)(4)fraction}def
+(12){(1)(2)fraction}def
+(34){(3)(4)fraction}def
+(13){(1)(3)fraction}def
+(23){(2)(3)fraction}def
+(18){(1)(8)fraction}def
+(38){(3)(8)fraction}def
+(58){(5)(8)fraction}def
+(78){(7)(8)fraction}def
+(sr){gsave 0 .06 dm rmoveto(\326)show oce}def
+(is){gsave 0 .15 dm rmoveto(\362)show oce}def
+(->){gsave 0 .02 dm rmoveto(\256)show oce}def
+(<-){gsave 0 .02 dm rmoveto(\254)show oce}def
+(==){gsave 0 .05 dm rmoveto(\272)show oce}def
+(uc){gsave currentpoint 400 .009 dm mul add translate
+     8 -8 scale ucseal oce}def
+end
+
+% an attempt at a PostScript FONT to implement ditroff special chars
+% this will enable us to 
+%	cache the little buggers
+%	generate faster, more compact PS out of psdit
+%	confuse everyone (including myself)!
+50 dict dup begin
+/FontType 3 def
+/FontName /DIThacks def
+/FontMatrix [.001 0 0 .001 0 0] def
+/FontBBox [-260 -260 900 900] def% a lie but ...
+/Encoding 256 array def
+0 1 255{Encoding exch /.notdef put}for
+Encoding
+ dup 8#040/space put %space
+ dup 8#110/rc put %right ceil
+ dup 8#111/lt put %left  top curl
+ dup 8#112/bv put %bold vert
+ dup 8#113/lk put %left  mid curl
+ dup 8#114/lb put %left  bot curl
+ dup 8#115/rt put %right top curl
+ dup 8#116/rk put %right mid curl
+ dup 8#117/rb put %right bot curl
+ dup 8#120/rf put %right floor
+ dup 8#121/lf put %left  floor
+ dup 8#122/lc put %left  ceil
+ dup 8#140/sq put %square
+ dup 8#141/bx put %box
+ dup 8#142/ci put %circle
+ dup 8#143/br put %box rule
+ dup 8#144/rn put %root extender
+ dup 8#145/vr put %vertical rule
+ dup 8#146/ob put %outline bullet
+ dup 8#147/bu put %bullet
+ dup 8#150/ru put %rule
+ dup 8#151/ul put %underline
+ pop
+/DITfd 100 dict def
+/BuildChar{0 begin
+ /cc exch def /fd exch def
+ /charname fd /Encoding get cc get def
+ /charwid fd /Metrics get charname get def
+ /charproc fd /CharProcs get charname get def
+ charwid 0 fd /FontBBox get aload pop setcachedevice
+ 2 setlinejoin 40 setlinewidth
+ newpath 0 0 moveto gsave charproc grestore
+ end}def
+/BuildChar load 0 DITfd put
+/CharProcs 50 dict def
+CharProcs begin
+/space{}def
+/.notdef{}def
+/ru{500 0 rls}def
+/rn{0 840 moveto 500 0 rls}def
+/vr{0 800 moveto 0 -770 rls}def
+/bv{0 800 moveto 0 -1000 rls}def
+/br{0 840 moveto 0 -1000 rls}def
+/ul{0 -140 moveto 500 0 rls}def
+/ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
+/bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
+/sq{80 0 rmoveto currentpoint dround newpath moveto
+    640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
+/bx{80 0 rmoveto currentpoint dround newpath moveto
+    640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
+/ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
+    50 setlinewidth stroke}def
+
+/lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
+/lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
+/rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
+/rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
+/lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
+    0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
+    0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
+/rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
+/lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
+/rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
+end
+
+/Metrics 50 dict def Metrics begin
+/.notdef 0 def
+/space 500 def
+/ru 500 def
+/br 0 def
+/lt 416 def
+/lb 416 def
+/rt 416 def
+/rb 416 def
+/lk 416 def
+/rk 416 def
+/rc 416 def
+/lc 416 def
+/rf 416 def
+/lf 416 def
+/bv 416 def
+/ob 350 def
+/bu 350 def
+/ci 750 def
+/bx 750 def
+/sq 750 def
+/rn 500 def
+/ul 500 def
+/vr 0 def
+end
+
+DITfd begin
+/s2 500 def /s4 250 def /s3 333 def
+/a4p{arcto pop pop pop pop}def
+/2cx{2 copy exch}def
+/rls{rlineto stroke}def
+/currx{currentpoint pop}def
+/dround{transform round exch round exch itransform} def
+end
+end
+/DIThacks exch definefont pop
+ditstart
+(psc)xT
+576 1 1 xr
+1(Times-Roman)xf 1 f
+2(Times-Italic)xf 2 f
+3(Times-Bold)xf 3 f
+4(Times-BoldItalic)xf 4 f
+5(Helvetica)xf 5 f
+6(Helvetica-Bold)xf 6 f
+7(Courier)xf 7 f
+8(Courier-Bold)xf 8 f
+9(Symbol)xf 9 f
+10(DIThacks)xf 10 f
+10 s
+1 f
+xi
+%%EndProlog
+
+%%Page: 1 1
+10 s 10 xH 0 xS 1 f
+3 f
+22 s
+1249 626(A)N
+1420(N)X
+1547(ew)X
+1796(H)X
+1933(ashing)X
+2467(P)X
+2574(ackage)X
+3136(for)X
+3405(U)X
+3532(N)X
+3659(IX)X
+2 f
+20 s
+3855 562(1)N
+1 f
+12 s
+1607 779(Margo)N
+1887(Seltzer)X
+9 f
+2179(-)X
+1 f
+2256(University)X
+2686(of)X
+2790(California,)X
+3229(Berkeley)X
+2015 875(Ozan)N
+2242(Yigit)X
+9 f
+2464(-)X
+1 f
+2541(York)X
+2762(University)X
+3 f
+2331 1086(ABSTRACT)N
+1 f
+10 s
+1152 1222(UNIX)N
+1385(support)X
+1657(of)X
+1756(disk)X
+1921(oriented)X
+2216(hashing)X
+2497(was)X
+2654(originally)X
+2997(provided)X
+3314(by)X
+2 f
+3426(dbm)X
+1 f
+3595([ATT79])X
+3916(and)X
+1152 1310(subsequently)N
+1595(improved)X
+1927(upon)X
+2112(in)X
+2 f
+2199(ndbm)X
+1 f
+2402([BSD86].)X
+2735(In)X
+2826(AT&T)X
+3068(System)X
+3327(V,)X
+3429(in-memory)X
+3809(hashed)X
+1152 1398(storage)N
+1420(and)X
+1572(access)X
+1814(support)X
+2090(was)X
+2251(added)X
+2479(in)X
+2577(the)X
+2 f
+2711(hsearch)X
+1 f
+3000(library)X
+3249(routines)X
+3542([ATT85].)X
+3907(The)X
+1152 1486(result)N
+1367(is)X
+1457(a)X
+1530(system)X
+1789(with)X
+1968(two)X
+2125(incompatible)X
+2580(hashing)X
+2865(schemes,)X
+3193(each)X
+3377(with)X
+3555(its)X
+3666(own)X
+3840(set)X
+3965(of)X
+1152 1574(shortcomings.)N
+1152 1688(This)N
+1316(paper)X
+1517(presents)X
+1802(the)X
+1922(design)X
+2152(and)X
+2289(performance)X
+2717(characteristics)X
+3198(of)X
+3286(a)X
+3343(new)X
+3498(hashing)X
+3768(package)X
+1152 1776(providing)N
+1483(a)X
+1539(superset)X
+1822(of)X
+1909(the)X
+2027(functionality)X
+2456(provided)X
+2761(by)X
+2 f
+2861(dbm)X
+1 f
+3019(and)X
+2 f
+3155(hsearch)X
+1 f
+3409(.)X
+3469(The)X
+3614(new)X
+3768(package)X
+1152 1864(uses)N
+1322(linear)X
+1537(hashing)X
+1818(to)X
+1912(provide)X
+2189(ef\256cient)X
+2484(support)X
+2755(of)X
+2853(both)X
+3026(memory)X
+3324(based)X
+3538(and)X
+3685(disk)X
+3849(based)X
+1152 1952(hash)N
+1319(tables)X
+1526(with)X
+1688(performance)X
+2115(superior)X
+2398(to)X
+2480(both)X
+2 f
+2642(dbm)X
+1 f
+2800(and)X
+2 f
+2936(hsearch)X
+1 f
+3210(under)X
+3413(most)X
+3588(conditions.)X
+3 f
+1380 2128(Introduction)N
+1 f
+892 2260(Current)N
+1196(UNIX)X
+1456(systems)X
+1768(offer)X
+1984(two)X
+2163(forms)X
+2409(of)X
+720 2348(hashed)N
+973(data)X
+1137(access.)X
+2 f
+1413(Dbm)X
+1 f
+1599(and)X
+1745(its)X
+1850(derivatives)X
+2231(provide)X
+720 2436(keyed)N
+939(access)X
+1171(to)X
+1259(disk)X
+1418(resident)X
+1698(data)X
+1858(while)X
+2 f
+2062(hsearch)X
+1 f
+2342(pro-)X
+720 2524(vides)N
+929(access)X
+1175(for)X
+1309(memory)X
+1616(resident)X
+1910(data.)X
+2124(These)X
+2356(two)X
+720 2612(access)N
+979(methods)X
+1302(are)X
+1453(incompatible)X
+1923(in)X
+2037(that)X
+2209(memory)X
+720 2700(resident)N
+1011(hash)X
+1195(tables)X
+1419(may)X
+1593(not)X
+1731(be)X
+1843(stored)X
+2075(on)X
+2191(disk)X
+2360(and)X
+720 2788(disk)N
+884(resident)X
+1169(tables)X
+1387(cannot)X
+1632(be)X
+1739(read)X
+1909(into)X
+2063(memory)X
+2360(and)X
+720 2876(accessed)N
+1022(using)X
+1215(the)X
+1333(in-memory)X
+1709(routines.)X
+2 f
+892 2990(Dbm)N
+1 f
+1091(has)X
+1241(several)X
+1512(shortcomings.)X
+2026(Since)X
+2247(data)X
+2423(is)X
+720 3078(assumed)N
+1032(to)X
+1130(be)X
+1242(disk)X
+1411(resident,)X
+1721(each)X
+1905(access)X
+2146(requires)X
+2440(a)X
+720 3166(system)N
+963(call,)X
+1120(and)X
+1257(almost)X
+1491(certainly,)X
+1813(a)X
+1869(disk)X
+2022(operation.)X
+2365(For)X
+720 3254(extremely)N
+1072(large)X
+1264(databases,)X
+1623(where)X
+1851(caching)X
+2131(is)X
+2214(unlikely)X
+720 3342(to)N
+810(be)X
+914(effective,)X
+1244(this)X
+1386(is)X
+1466(acceptable,)X
+1853(however,)X
+2177(when)X
+2378(the)X
+720 3430(database)N
+1022(is)X
+1100(small)X
+1298(\(i.e.)X
+1447(the)X
+1569(password)X
+1896(\256le\),)X
+2069(performance)X
+720 3518(improvements)N
+1204(can)X
+1342(be)X
+1443(obtained)X
+1744(through)X
+2018(caching)X
+2293(pages)X
+720 3606(of)N
+818(the)X
+947(database)X
+1255(in)X
+1348(memory.)X
+1685(In)X
+1782(addition,)X
+2 f
+2094(dbm)X
+1 f
+2262(cannot)X
+720 3694(store)N
+902(data)X
+1062(items)X
+1261(whose)X
+1492(total)X
+1660(key)X
+1802(and)X
+1943(data)X
+2102(size)X
+2252(exceed)X
+720 3782(the)N
+850(page)X
+1034(size)X
+1191(of)X
+1290(the)X
+1420(hash)X
+1599(table.)X
+1827(Similarly,)X
+2176(if)X
+2257(two)X
+2409(or)X
+720 3870(more)N
+907(keys)X
+1076(produce)X
+1357(the)X
+1477(same)X
+1664(hash)X
+1833(value)X
+2029(and)X
+2166(their)X
+2334(total)X
+720 3958(size)N
+876(exceeds)X
+1162(the)X
+1291(page)X
+1474(size,)X
+1650(the)X
+1779(table)X
+1966(cannot)X
+2210(store)X
+2396(all)X
+720 4046(the)N
+838(colliding)X
+1142(keys.)X
+892 4160(The)N
+1050(in-memory)X
+2 f
+1439(hsearch)X
+1 f
+1725(routines)X
+2015(have)X
+2199(different)X
+720 4248(shortcomings.)N
+1219(First,)X
+1413(the)X
+1539(notion)X
+1771(of)X
+1865(a)X
+1928(single)X
+2146(hash)X
+2320(table)X
+720 4336(is)N
+807(embedded)X
+1171(in)X
+1266(the)X
+1397(interface,)X
+1732(preventing)X
+2108(an)X
+2217(applica-)X
+720 4424(tion)N
+902(from)X
+1116(accessing)X
+1482(multiple)X
+1806(tables)X
+2050(concurrently.)X
+720 4512(Secondly,)N
+1063(the)X
+1186(routine)X
+1438(to)X
+1525(create)X
+1743(a)X
+1804(hash)X
+1976(table)X
+2157(requires)X
+2440(a)X
+720 4600(parameter)N
+1066(which)X
+1286(declares)X
+1573(the)X
+1694(size)X
+1842(of)X
+1932(the)X
+2053(hash)X
+2223(table.)X
+2422(If)X
+720 4688(this)N
+856(size)X
+1001(is)X
+1074(set)X
+1183(too)X
+1305(low,)X
+1465(performance)X
+1892(degradation)X
+2291(or)X
+2378(the)X
+720 4776(inability)N
+1008(to)X
+1092(add)X
+1230(items)X
+1425(to)X
+1509(the)X
+1628(table)X
+1805(may)X
+1964(result.)X
+2223(In)X
+2311(addi-)X
+720 4864(tion,)N
+2 f
+910(hsearch)X
+1 f
+1210(requires)X
+1515(that)X
+1681(the)X
+1825(application)X
+2226(allocate)X
+720 4952(memory)N
+1037(for)X
+1181(the)X
+1329(key)X
+1495(and)X
+1661(data)X
+1845(items.)X
+2108(Lastly,)X
+2378(the)X
+2 f
+720 5040(hsearch)N
+1 f
+1013(routines)X
+1310(provide)X
+1594(no)X
+1713(interface)X
+2034(to)X
+2135(store)X
+2329(hash)X
+720 5128(tables)N
+927(on)X
+1027(disk.)X
+16 s
+720 5593 MXY
+864 0 Dl
+2 f
+8 s
+760 5648(1)N
+1 f
+9 s
+5673(UNIX)Y
+990(is)X
+1056(a)X
+1106(registered)X
+1408(trademark)X
+1718(of)X
+1796(AT&T.)X
+10 s
+2878 2128(The)N
+3032(goal)X
+3199(of)X
+3295(our)X
+3431(work)X
+3625(was)X
+3779(to)X
+3870(design)X
+4108(and)X
+4253(imple-)X
+2706 2216(ment)N
+2900(a)X
+2970(new)X
+3138(package)X
+3436(that)X
+3590(provides)X
+3899(a)X
+3968(superset)X
+4264(of)X
+4364(the)X
+2706 2304(functionality)N
+3144(of)X
+3240(both)X
+2 f
+3411(dbm)X
+1 f
+3578(and)X
+2 f
+3723(hsearch)X
+1 f
+3977(.)X
+4045(The)X
+4198(package)X
+2706 2392(had)N
+2871(to)X
+2982(overcome)X
+3348(the)X
+3495(interface)X
+3826(shortcomings)X
+4306(cited)X
+2706 2480(above)N
+2930(and)X
+3078(its)X
+3185(implementation)X
+3719(had)X
+3867(to)X
+3961(provide)X
+4238(perfor-)X
+2706 2568(mance)N
+2942(equal)X
+3142(or)X
+3235(superior)X
+3524(to)X
+3612(that)X
+3758(of)X
+3851(the)X
+3975(existing)X
+4253(imple-)X
+2706 2656(mentations.)N
+3152(In)X
+3274(order)X
+3498(to)X
+3614(provide)X
+3913(a)X
+4003(compact)X
+4329(disk)X
+2706 2744(representation,)N
+3224(graceful)X
+3531(table)X
+3729(growth,)X
+4018(and)X
+4176(expected)X
+2706 2832(constant)N
+3033(time)X
+3234(performance,)X
+3720(we)X
+3873(selected)X
+4191(Litwin's)X
+2706 2920(linear)N
+2923(hashing)X
+3206(algorithm)X
+3551([LAR88,)X
+3872(LIT80].)X
+4178(We)X
+4324(then)X
+2706 3008(enhanced)N
+3037(the)X
+3161(algorithm)X
+3498(to)X
+3586(handle)X
+3826(page)X
+4004(over\257ows)X
+4346(and)X
+2706 3096(large)N
+2900(key)X
+3049(handling)X
+3362(with)X
+3537(a)X
+3606(single)X
+3830(mechanism,)X
+4248(named)X
+2706 3184(buddy-in-waiting.)N
+3 f
+2975 3338(Existing)N
+3274(UNIX)X
+3499(Hashing)X
+3802(Techniques)X
+1 f
+2878 3470(Over)N
+3076(the)X
+3210(last)X
+3357(decade,)X
+3637(several)X
+3901(dynamic)X
+4213(hashing)X
+2706 3558(schemes)N
+3000(have)X
+3174(been)X
+3348(developed)X
+3700(for)X
+3816(the)X
+3936(UNIX)X
+4159(timeshar-)X
+2706 3646(ing)N
+2856(system,)X
+3146(starting)X
+3433(with)X
+3622(the)X
+3767(inclusion)X
+4107(of)X
+2 f
+4221(dbm)X
+1 f
+4359(,)X
+4426(a)X
+2706 3734(minimal)N
+3008(database)X
+3321(library)X
+3571(written)X
+3834(by)X
+3950(Ken)X
+4120(Thompson)X
+2706 3822([THOM90],)N
+3141(in)X
+3248(the)X
+3391(Seventh)X
+3694(Edition)X
+3974(UNIX)X
+4220(system.)X
+2706 3910(Since)N
+2916(then,)X
+3106(an)X
+3214(extended)X
+3536(version)X
+3804(of)X
+3903(the)X
+4032(same)X
+4228(library,)X
+2 f
+2706 3998(ndbm)N
+1 f
+2884(,)X
+2933(and)X
+3078(a)X
+3142(public-domain)X
+3637(clone)X
+3839(of)X
+3934(the)X
+4060(latter,)X
+2 f
+4273(sdbm)X
+1 f
+4442(,)X
+2706 4086(have)N
+2902(been)X
+3098(developed.)X
+3491(Another)X
+3797 0.1645(interface-compatible)AX
+2706 4174(library)N
+2 f
+2950(gdbm)X
+1 f
+3128(,)X
+3178(was)X
+3333(recently)X
+3622(made)X
+3826(available)X
+4145(as)X
+4241(part)X
+4395(of)X
+2706 4262(the)N
+2829(Free)X
+2997(Software)X
+3312(Foundation's)X
+3759(\(FSF\))X
+3970(software)X
+4271(distri-)X
+2706 4350(bution.)N
+2878 4464(All)N
+3017(of)X
+3121(these)X
+3323(implementations)X
+3893(are)X
+4029(based)X
+4248(on)X
+4364(the)X
+2706 4552(idea)N
+2871(of)X
+2969(revealing)X
+3299(just)X
+3445(enough)X
+3711(bits)X
+3856(of)X
+3953(a)X
+4019(hash)X
+4196(value)X
+4400(to)X
+2706 4640(locate)N
+2920(a)X
+2978(page)X
+3151(in)X
+3234(a)X
+3291(single)X
+3503(access.)X
+3770(While)X
+2 f
+3987(dbm/ndbm)X
+1 f
+4346(and)X
+2 f
+2706 4728(sdbm)N
+1 f
+2908(map)X
+3079(the)X
+3210(hash)X
+3390(value)X
+3597(directly)X
+3874(to)X
+3968(a)X
+4036(disk)X
+4201(address,)X
+2 f
+2706 4816(gdbm)N
+1 f
+2921(uses)X
+3096(the)X
+3231(hash)X
+3414(value)X
+3624(to)X
+3722(index)X
+3936(into)X
+4096(a)X
+2 f
+4168(directory)X
+1 f
+2706 4904([ENB88])N
+3020(containing)X
+3378(disk)X
+3531(addresses.)X
+2878 5018(The)N
+2 f
+3033(hsearch)X
+1 f
+3317(routines)X
+3605(in)X
+3697(System)X
+3962(V)X
+4049(are)X
+4177(designed)X
+2706 5106(to)N
+2804(provide)X
+3085(memory-resident)X
+3669(hash)X
+3852(tables.)X
+4115(Since)X
+4328(data)X
+2706 5194(access)N
+2948(does)X
+3131(not)X
+3269(require)X
+3533(disk)X
+3702(access,)X
+3964(simple)X
+4213(hashing)X
+2706 5282(schemes)N
+3010(which)X
+3238(may)X
+3408(require)X
+3667(multiple)X
+3964(probes)X
+4209(into)X
+4364(the)X
+2706 5370(table)N
+2889(are)X
+3015(used.)X
+3209(A)X
+3294(more)X
+3486(interesting)X
+3851(version)X
+4114(of)X
+2 f
+4208(hsearch)X
+1 f
+2706 5458(is)N
+2784(a)X
+2845(public)X
+3070(domain)X
+3335(library,)X
+2 f
+3594(dynahash)X
+1 f
+3901(,)X
+3945(that)X
+4089(implements)X
+2706 5546(Larson's)N
+3036(in-memory)X
+3440(adaptation)X
+3822([LAR88])X
+4164(of)X
+4279(linear)X
+2706 5634(hashing)N
+2975([LIT80].)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+1 f
+4424(1)X
+
+2 p
+%%Page: 2 2
+10 s 10 xH 0 xS 1 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+2 f
+1074 538(dbm)N
+1 f
+1232(and)X
+2 f
+1368(ndbm)X
+1 f
+604 670(The)N
+2 f
+760(dbm)X
+1 f
+928(and)X
+2 f
+1074(ndbm)X
+1 f
+1282(library)X
+1526(implementations)X
+2089(are)X
+432 758(based)N
+667(on)X
+799(the)X
+949(same)X
+1166(algorithm)X
+1529(by)X
+1661(Ken)X
+1846(Thompson)X
+432 846([THOM90,)N
+824(TOR88,)X
+1113(WAL84],)X
+1452(but)X
+1582(differ)X
+1789(in)X
+1879(their)X
+2054(pro-)X
+432 934(grammatic)N
+801(interfaces.)X
+1160(The)X
+1311(latter)X
+1502(is)X
+1581(a)X
+1643(modi\256ed)X
+1952(version)X
+432 1022(of)N
+533(the)X
+665(former)X
+918(which)X
+1148(adds)X
+1328(support)X
+1601(for)X
+1728(multiple)X
+2027(data-)X
+432 1110(bases)N
+634(to)X
+724(be)X
+828(open)X
+1011(concurrently.)X
+1484(The)X
+1636(discussion)X
+1996(of)X
+2090(the)X
+432 1198(algorithm)N
+774(that)X
+925(follows)X
+1196(is)X
+1280(applicable)X
+1640(to)X
+1732(both)X
+2 f
+1904(dbm)X
+1 f
+2072(and)X
+2 f
+432 1286(ndbm)N
+1 f
+610(.)X
+604 1400(The)N
+760(basic)X
+956(structure)X
+1268(of)X
+2 f
+1366(dbm)X
+1 f
+1535(calls)X
+1712(for)X
+1836(\256xed-sized)X
+432 1488(disk)N
+612(blocks)X
+868(\(buckets\))X
+1214(and)X
+1377(an)X
+2 f
+1499(access)X
+1 f
+1755(function)X
+2068(that)X
+432 1576(maps)N
+623(a)X
+681(key)X
+819(to)X
+902(a)X
+959(bucket.)X
+1234(The)X
+1380(interface)X
+1683(routines)X
+1962(use)X
+2090(the)X
+2 f
+432 1664(access)N
+1 f
+673(function)X
+970(to)X
+1062(obtain)X
+1292(the)X
+1420(appropriate)X
+1816(bucket)X
+2060(in)X
+2152(a)X
+432 1752(single)N
+643(disk)X
+796(access.)X
+604 1866(Within)N
+869(the)X
+2 f
+1010(access)X
+1 f
+1263(function,)X
+1593(a)X
+1672(bit-randomizing)X
+432 1954(hash)N
+610(function)X
+2 f
+8 s
+877 1929(2)N
+1 f
+10 s
+940 1954(is)N
+1024(used)X
+1202(to)X
+1294(convert)X
+1565(a)X
+1631(key)X
+1777(into)X
+1931(a)X
+1997(32-bit)X
+432 2042(hash)N
+605(value.)X
+825(Out)X
+971(of)X
+1064(these)X
+1254(32)X
+1359(bits,)X
+1519(only)X
+1686(as)X
+1778(many)X
+1981(bits)X
+2121(as)X
+432 2130(necessary)N
+773(are)X
+900(used)X
+1075(to)X
+1165(determine)X
+1514(the)X
+1639(particular)X
+1974(bucket)X
+432 2218(on)N
+533(which)X
+750(a)X
+807(key)X
+944(resides.)X
+1228(An)X
+1347(in-memory)X
+1724(bitmap)X
+1967(is)X
+2041(used)X
+432 2306(to)N
+533(determine)X
+893(how)X
+1070(many)X
+1287(bits)X
+1441(are)X
+1579(required.)X
+1905(Each)X
+2104(bit)X
+432 2394(indicates)N
+746(whether)X
+1033(its)X
+1136(associated)X
+1494(bucket)X
+1736(has)X
+1871(been)X
+2051(split)X
+432 2482(yet)N
+562(\(a)X
+657(0)X
+728(indicating)X
+1079(that)X
+1230(the)X
+1359(bucket)X
+1604(has)X
+1742(not)X
+1875(yet)X
+2004(split\).)X
+432 2570(The)N
+590(use)X
+730(of)X
+830(the)X
+961(hash)X
+1141(function)X
+1441(and)X
+1590(the)X
+1720(bitmap)X
+1974(is)X
+2059(best)X
+432 2658(described)N
+769(by)X
+878(stepping)X
+1177(through)X
+1454(database)X
+1759(creation)X
+2046(with)X
+432 2746(multiple)N
+718(invocations)X
+1107(of)X
+1194(a)X
+2 f
+1250(store)X
+1 f
+1430(operation.)X
+604 2860(Initially,)N
+906(the)X
+1033(hash)X
+1209(table)X
+1394(contains)X
+1690(a)X
+1755(single)X
+1974(bucket)X
+432 2948(\(bucket)N
+711(0\),)X
+836(the)X
+972(bit)X
+1094(map)X
+1270(contains)X
+1575(a)X
+1649(single)X
+1878(bit)X
+2000(\(bit)X
+2148(0)X
+432 3036(corresponding)N
+913(to)X
+997(bucket)X
+1233(0\),)X
+1342(and)X
+1480(0)X
+1542(bits)X
+1699(of)X
+1788(a)X
+1846(hash)X
+2014(value)X
+432 3124(are)N
+560(examined)X
+901(to)X
+992(determine)X
+1342(where)X
+1568(a)X
+1633(key)X
+1778(is)X
+1860(placed)X
+2099(\(in)X
+432 3212(bucket)N
+670(0\).)X
+801(When)X
+1017(bucket)X
+1255(0)X
+1319(is)X
+1396(full,)X
+1551(its)X
+1650(bit)X
+1758(in)X
+1844(the)X
+1966(bitmap)X
+432 3300(\(bit)N
+564(0\))X
+652(is)X
+726(set,)X
+856(and)X
+993(its)X
+1089(contents)X
+1377(are)X
+1497(split)X
+1655(between)X
+1943(buckets)X
+432 3388(0)N
+499(and)X
+641(1,)X
+727(by)X
+833(considering)X
+1233(the)X
+1357(0)X
+2 f
+7 s
+3356(th)Y
+10 s
+1 f
+1480 3388(bit)N
+1590(\(the)X
+1741(lowest)X
+1976(bit)X
+2086(not)X
+432 3476(previously)N
+800(examined\))X
+1169(of)X
+1266(the)X
+1393(hash)X
+1569(value)X
+1772(for)X
+1895(each)X
+2072(key)X
+432 3564(within)N
+668(the)X
+798(bucket.)X
+1064(Given)X
+1292(a)X
+1359(well-designed)X
+1840(hash)X
+2018(func-)X
+432 3652(tion,)N
+613(approximately)X
+1112(half)X
+1273(of)X
+1376(the)X
+1510(keys)X
+1693(will)X
+1853(have)X
+2041(hash)X
+432 3740(values)N
+666(with)X
+837(the)X
+964(0)X
+2 f
+7 s
+3708(th)Y
+10 s
+1 f
+1090 3740(bit)N
+1203(set.)X
+1341(All)X
+1471(such)X
+1646(keys)X
+1821(and)X
+1965(associ-)X
+432 3828(ated)N
+586(data)X
+740(are)X
+859(moved)X
+1097(to)X
+1179(bucket)X
+1413(1,)X
+1493(and)X
+1629(the)X
+1747(rest)X
+1883(remain)X
+2126(in)X
+432 3916(bucket)N
+666(0.)X
+604 4030(After)N
+804(this)X
+949(split,)X
+1135(the)X
+1262(\256le)X
+1393(now)X
+1560(contains)X
+1856(two)X
+2005(buck-)X
+432 4118(ets,)N
+562(and)X
+699(the)X
+818(bitmap)X
+1061(contains)X
+1349(three)X
+1530(bits:)X
+1687(the)X
+1805(0)X
+2 f
+7 s
+4086(th)Y
+10 s
+1 f
+1922 4118(bit)N
+2026(is)X
+2099(set)X
+432 4206(to)N
+525(indicate)X
+810(a)X
+876(bucket)X
+1120(0)X
+1190(split)X
+1357(when)X
+1561(no)X
+1671(bits)X
+1816(of)X
+1913(the)X
+2041(hash)X
+432 4294(value)N
+648(are)X
+789(considered,)X
+1199(and)X
+1357(two)X
+1519(more)X
+1726(unset)X
+1937(bits)X
+2094(for)X
+432 4382(buckets)N
+706(0)X
+775(and)X
+920(1.)X
+1029(The)X
+1183(placement)X
+1542(of)X
+1638(an)X
+1742(incoming)X
+2072(key)X
+432 4470(now)N
+604(requires)X
+897(examination)X
+1327(of)X
+1428(the)X
+1560(0)X
+2 f
+7 s
+4438(th)Y
+10 s
+1 f
+1691 4470(bit)N
+1809(of)X
+1910(the)X
+2041(hash)X
+432 4558(value,)N
+667(and)X
+824(the)X
+963(key)X
+1119(is)X
+1212(placed)X
+1462(either)X
+1685(in)X
+1787(bucket)X
+2041(0)X
+2121(or)X
+432 4646(bucket)N
+674(1.)X
+782(If)X
+864(either)X
+1075(bucket)X
+1317(0)X
+1385(or)X
+1480(bucket)X
+1722(1)X
+1790(\256lls)X
+1937(up,)X
+2064(it)X
+2135(is)X
+432 4734(split)N
+598(as)X
+693(before,)X
+947(its)X
+1050(bit)X
+1162(is)X
+1243(set)X
+1360(in)X
+1450(the)X
+1576(bitmap,)X
+1846(and)X
+1990(a)X
+2054(new)X
+432 4822(set)N
+541(of)X
+628(unset)X
+817(bits)X
+952(are)X
+1071(added)X
+1283(to)X
+1365(the)X
+1483(bitmap.)X
+604 4936(Each)N
+791(time)X
+959(we)X
+1079(consider)X
+1376(a)X
+1437(new)X
+1596(bit)X
+1705(\(bit)X
+1841(n\),)X
+1953(we)X
+2072(add)X
+432 5024(2)N
+2 f
+7 s
+4992(n)Y
+9 f
+509(+)X
+1 f
+540(1)X
+10 s
+595 5024(bits)N
+737(to)X
+826(the)X
+951(bitmap)X
+1199(and)X
+1341(obtain)X
+1567(2)X
+2 f
+7 s
+4992(n)Y
+9 f
+1644(+)X
+1 f
+1675(1)X
+10 s
+1729 5024(more)N
+1920(address-)X
+432 5112(able)N
+595(buckets)X
+869(in)X
+960(the)X
+1087(\256le.)X
+1258(As)X
+1376(a)X
+1441(result,)X
+1668(the)X
+1795(bitmap)X
+2045(con-)X
+432 5200(tains)N
+618(the)X
+751(previous)X
+1062(2)X
+2 f
+7 s
+5168(n)Y
+9 f
+1139(+)X
+1 f
+1170(1)X
+2 f
+10 s
+9 f
+5200(-)Y
+1 f
+1242(1)X
+1317(bits)X
+1467(\(1)X
+2 f
+9 f
+1534(+)X
+1 f
+1578(2)X
+2 f
+9 f
+(+)S
+1 f
+1662(4)X
+2 f
+9 f
+(+)S
+1 f
+1746(...)X
+2 f
+9 f
+(+)S
+1 f
+1850(2)X
+2 f
+7 s
+5168(n)Y
+10 s
+1 f
+1931 5200(\))N
+1992(which)X
+432 5288(trace)N
+649(the)X
+807(entire)X
+2 f
+1050(split)X
+1247(history)X
+1 f
+1529(of)X
+1656(the)X
+1813(addressable)X
+16 s
+432 5433 MXY
+864 0 Dl
+2 f
+8 s
+472 5488(2)N
+1 f
+9 s
+523 5513(This)N
+670(bit-randomizing)X
+1153(property)X
+1416(is)X
+1482(important)X
+1780(to)X
+1854(obtain)X
+2052(radi-)X
+432 5593(cally)N
+599(different)X
+874(hash)X
+1033(values)X
+1244(for)X
+1355(nearly)X
+1562(identical)X
+1836(keys,)X
+2012(which)X
+432 5673(in)N
+506(turn)X
+640(avoids)X
+846(clustering)X
+1148(of)X
+1226(such)X
+1376(keys)X
+1526(in)X
+1600(a)X
+1650(single)X
+1840(bucket.)X
+10 s
+2418 538(buckets.)N
+2590 652(Given)N
+2809(a)X
+2868(key)X
+3007(and)X
+3146(the)X
+3267(bitmap)X
+3512(created)X
+3768(by)X
+3871(this)X
+4009(algo-)X
+2418 740(rithm,)N
+2638(we)X
+2759(\256rst)X
+2910(examine)X
+3209(bit)X
+3320(0)X
+3386(of)X
+3479(the)X
+3603(bitmap)X
+3851(\(the)X
+4002(bit)X
+4112(to)X
+2418 828(consult)N
+2673(when)X
+2871(0)X
+2934(bits)X
+3072(of)X
+3162(the)X
+3283(hash)X
+3453(value)X
+3650(are)X
+3772(being)X
+3973(exam-)X
+2418 916(ined\).)N
+2631(If)X
+2713(it)X
+2785(is)X
+2866(set)X
+2982(\(indicating)X
+3356(that)X
+3503(the)X
+3628(bucket)X
+3869(split\),)X
+4080(we)X
+2418 1004(begin)N
+2617(considering)X
+3012(the)X
+3131(bits)X
+3267(of)X
+3355(the)X
+3473(32-bit)X
+3684(hash)X
+3851(value.)X
+4085(As)X
+2418 1092(bit)N
+2525(n)X
+2587(is)X
+2662(revealed,)X
+2977(a)X
+3035(mask)X
+3226(equal)X
+3422(to)X
+3506(2)X
+2 f
+7 s
+1060(n)Y
+9 f
+3583(+)X
+1 f
+3614(1)X
+2 f
+10 s
+9 f
+1092(-)Y
+1 f
+3686(1)X
+3748(will)X
+3894(yield)X
+4076(the)X
+2418 1180(current)N
+2675(bucket)X
+2918(address.)X
+3228(Adding)X
+3496(2)X
+2 f
+7 s
+1148(n)Y
+9 f
+3573(+)X
+1 f
+3604(1)X
+2 f
+10 s
+9 f
+1180(-)Y
+1 f
+3676(1)X
+3744(to)X
+3834(the)X
+3960(bucket)X
+2418 1268(address)N
+2701(identi\256es)X
+3035(which)X
+3272(bit)X
+3397(in)X
+3500(the)X
+3639(bitmap)X
+3902(must)X
+4098(be)X
+2418 1356(checked.)N
+2743(We)X
+2876(continue)X
+3173(revealing)X
+3493(bits)X
+3628(of)X
+3715(the)X
+3833(hash)X
+4000(value)X
+2418 1444(until)N
+2591(all)X
+2698(set)X
+2814(bits)X
+2955(in)X
+3043(the)X
+3167(bitmap)X
+3415(are)X
+3540(exhausted.)X
+3907(The)X
+4058(fol-)X
+2418 1532(lowing)N
+2682(algorithm,)X
+3055(a)X
+3133(simpli\256cation)X
+3614(of)X
+3723(the)X
+3863(algorithm)X
+2418 1620(due)N
+2565(to)X
+2658(Ken)X
+2823(Thompson)X
+3196([THOM90,)X
+3590(TOR88],)X
+3908(uses)X
+4076(the)X
+2418 1708(hash)N
+2625(value)X
+2839(and)X
+2995(the)X
+3133(bitmap)X
+3395(to)X
+3497(calculate)X
+3823(the)X
+3960(bucket)X
+2418 1796(address)N
+2679(as)X
+2766(discussed)X
+3093(above.)X
+0(Courier)xf 0 f
+1 f
+0 f
+8 s
+2418 2095(hash)N
+2608(=)X
+2684 -0.4038(calchash\(key\);)AX
+2418 2183(mask)N
+2608(=)X
+2684(0;)X
+2418 2271(while)N
+2646 -0.4018(\(isbitset\(\(hash)AX
+3254(&)X
+3330(mask\))X
+3558(+)X
+3634(mask\)\))X
+2706 2359(mask)N
+2896(=)X
+2972(\(mask)X
+3200(<<)X
+3314(1\))X
+3428(+)X
+3504(1;)X
+2418 2447(bucket)N
+2684(=)X
+2760(hash)X
+2950(&)X
+3026(mask;)X
+2 f
+10 s
+3211 2812(sdbm)N
+1 f
+2590 2944(The)N
+2 f
+2738(sdbm)X
+1 f
+2930(library)X
+3167(is)X
+3243(a)X
+3302(public-domain)X
+3791(clone)X
+3987(of)X
+4076(the)X
+2 f
+2418 3032(ndbm)N
+1 f
+2638(library,)X
+2914(developed)X
+3286(by)X
+3408(Ozan)X
+3620(Yigit)X
+3826(to)X
+3929(provide)X
+2 f
+2418 3120(ndbm)N
+1 f
+2596('s)X
+2692(functionality)X
+3139(under)X
+3359(some)X
+3565(versions)X
+3869(of)X
+3973(UNIX)X
+2418 3208(that)N
+2559(exclude)X
+2830(it)X
+2894(for)X
+3008(licensing)X
+3317(reasons)X
+3578([YIG89].)X
+3895(The)X
+4040(pro-)X
+2418 3296(grammer)N
+2735(interface,)X
+3064(and)X
+3207(the)X
+3332(basic)X
+3524(structure)X
+3832(of)X
+2 f
+3926(sdbm)X
+1 f
+4121(is)X
+2418 3384(identical)N
+2733(to)X
+2 f
+2834(ndbm)X
+1 f
+3051(but)X
+3192(internal)X
+3476(details)X
+3723(of)X
+3828(the)X
+2 f
+3964(access)X
+1 f
+2418 3472(function,)N
+2726(such)X
+2894(as)X
+2982(the)X
+3101(calculation)X
+3474(of)X
+3561(the)X
+3679(bucket)X
+3913(address,)X
+2418 3560(and)N
+2563(the)X
+2690(use)X
+2825(of)X
+2920(different)X
+3225(hash)X
+3400(functions)X
+3726(make)X
+3928(the)X
+4054(two)X
+2418 3648(incompatible)N
+2856(at)X
+2934(the)X
+3052(database)X
+3349(level.)X
+2590 3762(The)N
+2 f
+2740(sdbm)X
+1 f
+2934(library)X
+3173(is)X
+3251(based)X
+3458(on)X
+3562(a)X
+3622(simpli\256ed)X
+3965(imple-)X
+2418 3850(mentation)N
+2778(of)X
+2885(Larson's)X
+3206(1978)X
+2 f
+3406(dynamic)X
+3717(hashing)X
+1 f
+4009(algo-)X
+2418 3938(rithm)N
+2616(including)X
+2943(the)X
+2 f
+3066(re\256nements)X
+3461(and)X
+3605(variations)X
+1 f
+3953(of)X
+4044(sec-)X
+2418 4026(tion)N
+2562(5)X
+2622([LAR78].)X
+2956(Larson's)X
+3257(original)X
+3526(algorithm)X
+3857(calls)X
+4024(for)X
+4138(a)X
+2418 4114(forest)N
+2635(of)X
+2736(binary)X
+2975(hash)X
+3156(trees)X
+3341(that)X
+3494(are)X
+3626(accessed)X
+3941(by)X
+4054(two)X
+2418 4202(hash)N
+2586(functions.)X
+2925(The)X
+3071(\256rst)X
+3216(hash)X
+3384(function)X
+3672(selects)X
+3907(a)X
+3964(partic-)X
+2418 4290(ular)N
+2571(tree)X
+2720(within)X
+2952(the)X
+3078(forest.)X
+3309(The)X
+3462(second)X
+3713(hash)X
+3887(function,)X
+2418 4378(which)N
+2659(is)X
+2757(required)X
+3070(to)X
+3177(be)X
+3297(a)X
+3377(boolean)X
+3675(pseudo-random)X
+2418 4466(number)N
+2687(generator)X
+3015(that)X
+3159(is)X
+3236(seeded)X
+3479(by)X
+3583(the)X
+3705(key,)X
+3865(is)X
+3942(used)X
+4112(to)X
+2418 4554(traverse)N
+2733(the)X
+2890(tree)X
+3070(until)X
+3275(internal)X
+3579(\(split\))X
+3829(nodes)X
+4075(are)X
+2418 4642(exhausted)N
+2763(and)X
+2903(an)X
+3003(external)X
+3286(\(non-split\))X
+3648(node)X
+3827(is)X
+3903(reached.)X
+2418 4730(The)N
+2571(bucket)X
+2813(addresses)X
+3149(are)X
+3276(stored)X
+3500(directly)X
+3772(in)X
+3861(the)X
+3986(exter-)X
+2418 4818(nal)N
+2536(nodes.)X
+2590 4932(Larson's)N
+2903(re\256nements)X
+3309(are)X
+3440(based)X
+3655(on)X
+3767(the)X
+3897(observa-)X
+2418 5020(tion)N
+2570(that)X
+2718(the)X
+2844(nodes)X
+3059(can)X
+3199(be)X
+3303(represented)X
+3702(by)X
+3809(a)X
+3872(single)X
+4090(bit)X
+2418 5108(that)N
+2569(is)X
+2653(set)X
+2773(for)X
+2898(internal)X
+3174(nodes)X
+3392(and)X
+3539(not)X
+3672(set)X
+3791(for)X
+3915(external)X
+2418 5196(nodes,)N
+2652(resulting)X
+2959(in)X
+3048(a)X
+3111(radix)X
+3303(search)X
+3536(trie.)X
+3709(Figure)X
+3944(1)X
+4010(illus-)X
+2418 5284(trates)N
+2621(this.)X
+2804(Nodes)X
+3037(A)X
+3123(and)X
+3267(B)X
+3348(are)X
+3475(internal)X
+3748(\(split\))X
+3967(nodes,)X
+2418 5372(thus)N
+2573(having)X
+2813(no)X
+2915(bucket)X
+3151(addresses)X
+3480(associated)X
+3831(with)X
+3994(them.)X
+2418 5460(Instead,)N
+2693(the)X
+2814(external)X
+3096(nodes)X
+3306(\(C,)X
+3429(D,)X
+3530(and)X
+3669(E\))X
+3768(each)X
+3938(need)X
+4112(to)X
+2418 5548(refer)N
+2594(to)X
+2679(a)X
+2738(bucket)X
+2975(address.)X
+3279(These)X
+3494(bucket)X
+3731(addresses)X
+4062(can)X
+2418 5636(be)N
+2529(stored)X
+2760(in)X
+2857(the)X
+2990(trie)X
+3132(itself)X
+3327(where)X
+3559(the)X
+3691(subtries)X
+3974(would)X
+3 f
+432 5960(2)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+3 p
+%%Page: 3 3
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(live)N
+862(if)X
+933(they)X
+1092(existed)X
+1340([KNU68].)X
+1709(For)X
+1841(example,)X
+2154(if)X
+2224(nodes)X
+2432(F)X
+720 626(and)N
+858(G)X
+938(were)X
+1117(the)X
+1237(children)X
+1522(of)X
+1610(node)X
+1787(C,)X
+1881(the)X
+2000(bucket)X
+2235(address)X
+720 714(L00)N
+886(could)X
+1101(reside)X
+1330(in)X
+1429(the)X
+1563(bits)X
+1714(that)X
+1870(will)X
+2030(eventually)X
+2400(be)X
+720 802(used)N
+887(to)X
+969(store)X
+1145(nodes)X
+1352(F)X
+1416(and)X
+1552(G)X
+1630(and)X
+1766(all)X
+1866(their)X
+2033(children.)X
+10 f
+720 890 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+1894 2247(L1)N
+784 1925(A)N
+1431(E)X
+1106 2247(D)N
+1428 1281(C)N
+1109 1603(B)N
+1884 1930(L01)N
+1879 1286(L00)N
+1221 1814(1)N
+903 2131(1)N
+1221 1402(0)N
+903 1714(0)N
+1 Dt
+1397 1821 MXY
+-8 -32 Dl
+-5 19 Dl
+-20 6 Dl
+33 7 Dl
+-187 -182 Dl
+1397 1322 MXY
+-33 7 Dl
+20 6 Dl
+5 19 Dl
+8 -32 Dl
+-187 182 Dl
+1069 1639 MXY
+-32 7 Dl
+20 6 Dl
+5 19 Dl
+7 -32 Dl
+-186 182 Dl
+1374 1891 MXY
+185 Dc
+1779 2133 MXY
+0 161 Dl
+322 0 Dl
+0 -161 Dl
+-322 0 Dl
+1811 MY
+0 161 Dl
+322 0 Dl
+0 -161 Dl
+-322 0 Dl
+1166 MY
+0 161 Dl
+322 0 Dl
+0 -161 Dl
+-322 0 Dl
+1052 2213 MXY
+185 Dc
+1569 MY
+185 Dc
+720 1881 MXY
+185 Dc
+1779 2213 MXY
+-28 -17 Dl
+10 17 Dl
+-10 18 Dl
+28 -18 Dl
+-543 0 Dl
+1769 1891 MXY
+-28 -18 Dl
+10 18 Dl
+-10 18 Dl
+28 -18 Dl
+-201 0 Dl
+1364 1247 MXY
+185 Dc
+1769 MX
+-28 -18 Dl
+10 18 Dl
+-10 18 Dl
+28 -18 Dl
+-201 0 Dl
+1064 2143 MXY
+-7 -32 Dl
+-5 19 Dl
+-20 6 Dl
+32 7 Dl
+-181 -181 Dl
+3 Dt
+-1 Ds
+8 s
+720 2482(Figure)N
+925(1:)X
+1 f
+1002(Radix)X
+1179(search)X
+1365(trie)X
+1474(with)X
+1612(internal)X
+1831(nodes)X
+2004(A)X
+2074(and)X
+2189(B,)X
+2271(external)X
+720 2570(nodes)N
+891(C,)X
+972(D,)X
+1056(and)X
+1170(E,)X
+1247(and)X
+1361(bucket)X
+1553(addresses)X
+1819(stored)X
+1997(in)X
+2069(the)X
+2168(unused)X
+2370(por-)X
+720 2658(tion)N
+836(of)X
+905(the)X
+999(trie.)X
+10 s
+10 f
+720 2922 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+892 3124(Further)N
+1153(simpli\256cations)X
+1647(of)X
+1738(the)X
+1860(above)X
+2076([YIG89])X
+2377(are)X
+720 3212(possible.)N
+1038(Using)X
+1265(a)X
+1337(single)X
+1564(radix)X
+1765(trie)X
+1908(to)X
+2006(avoid)X
+2219(the)X
+2352(\256rst)X
+720 3300(hash)N
+904(function,)X
+1227(replacing)X
+1562(the)X
+1696(pseudo-random)X
+2231(number)X
+720 3388(generator)N
+1052(with)X
+1222(a)X
+1286(well)X
+1452(designed,)X
+1785(bit-randomizing)X
+2329(hash)X
+720 3476(function,)N
+1053(and)X
+1215(using)X
+1434(the)X
+1578(portion)X
+1855(of)X
+1967(the)X
+2110(hash)X
+2302(value)X
+720 3564(exposed)N
+1021(during)X
+1268(the)X
+1404(trie)X
+1549(traversal)X
+1864(as)X
+1969(a)X
+2042(direct)X
+2262(bucket)X
+720 3652(address)N
+990(results)X
+1228(in)X
+1319(an)X
+2 f
+1424(access)X
+1 f
+1663(function)X
+1959(that)X
+2108(works)X
+2333(very)X
+720 3740(similar)N
+974(to)X
+1068(Thompson's)X
+1499(algorithm)X
+1841(above.)X
+2084(The)X
+2240(follow-)X
+720 3828(ing)N
+847(algorithm)X
+1183(uses)X
+1346(the)X
+1469(hash)X
+1641(value)X
+1840(to)X
+1927(traverse)X
+2206(a)X
+2266(linear-)X
+720 3916(ized)N
+874(radix)X
+1059(trie)X
+2 f
+8 s
+1166 3891(3)N
+1 f
+10 s
+1218 3916(starting)N
+1478(at)X
+1556(the)X
+1674(0)X
+2 f
+7 s
+3884(th)Y
+10 s
+1 f
+1791 3916(bit.)N
+0 f
+8 s
+720 4215(tbit)N
+910(=)X
+986(0;)X
+1296(/*)X
+1410(radix)X
+1638(trie)X
+1828(index)X
+2056(*/)X
+720 4303(hbit)N
+910(=)X
+986(0;)X
+1296(/*)X
+1410(hash)X
+1600(bit)X
+1752(index)X
+2056(*/)X
+720 4391(mask)N
+910(=)X
+986(0;)X
+720 4479(hash)N
+910(=)X
+986 -0.4038(calchash\(key\);)AX
+720 4655(for)N
+872(\(mask)X
+1100(=)X
+1176(0;)X
+910 4743 -0.4018(isbitset\(tbit\);)AN
+910 4831(mask)N
+1100(=)X
+1176(\(mask)X
+1404(<<)X
+1518(1\))X
+1632(+)X
+1708(1\))X
+1008 4919(if)N
+1122(\(hash)X
+1350(&)X
+1426(\(1)X
+1540(<<)X
+1654 -0.4219(hbit++\)\)\))AX
+1160 5007(/*)N
+1274(right)X
+1502(son)X
+1692(*/)X
+1160 5095(tbit)N
+1350(=)X
+1426(2)X
+1502(*)X
+1578(tbit)X
+1768(+)X
+1844(2;)X
+1008 5183(else)N
+1 f
+16 s
+720 5353 MXY
+864 0 Dl
+2 f
+8 s
+760 5408(3)N
+1 f
+9 s
+818 5433(A)N
+896(linearized)X
+1206(radix)X
+1380(trie)X
+1502(is)X
+1576(merely)X
+1802(an)X
+1895(array)X
+2068(representation)X
+720 5513(of)N
+800(the)X
+908(radix)X
+1076(search)X
+1280(trie)X
+1396(described)X
+1692(above.)X
+1920(The)X
+2052(children)X
+2308(of)X
+2388(the)X
+720 5593(node)N
+885(with)X
+1038(index)X
+1223(i)X
+1267(can)X
+1391(be)X
+1483(found)X
+1675(at)X
+1751(the)X
+1863(nodes)X
+2055(indexed)X
+2307(2*i+1)X
+720 5673(and)N
+842(2*i+2.)X
+0 f
+8 s
+3146 538(/*)N
+3260(left)X
+3450(son)X
+3678(*/)X
+3146 626(tbit)N
+3336(=)X
+3412(2)X
+3488(*)X
+3564(tbit)X
+3754(+)X
+3830(1;)X
+2706 802(bucket)N
+2972(=)X
+3048(hash)X
+3238(&)X
+3314(mask;)X
+2 f
+10 s
+3495 1167(gdbm)N
+1 f
+2878 1299(The)N
+3027(gdbm)X
+3233(\(GNU)X
+3458(data)X
+3616(base)X
+3783(manager\))X
+4111(library)X
+4349(is)X
+4426(a)X
+2706 1387(UNIX)N
+2933(database)X
+3236(manager)X
+3539(written)X
+3792(by)X
+3897(Philip)X
+4112(A.)X
+4215(Nelson,)X
+2706 1475(and)N
+2848(made)X
+3048(available)X
+3364(as)X
+3457(a)X
+3518(part)X
+3668(of)X
+3760(the)X
+3883(FSF)X
+4040(software)X
+4342(dis-)X
+2706 1563(tribution.)N
+3052(The)X
+3207(gdbm)X
+3419(library)X
+3663(provides)X
+3969(the)X
+4097(same)X
+4292(func-)X
+2706 1651(tionality)N
+3028(of)X
+3151(the)X
+2 f
+3304(dbm)X
+1 f
+3442(/)X
+2 f
+3464(ndbm)X
+1 f
+3697(libraries)X
+4015([NEL90])X
+4360(but)X
+2706 1739(attempts)N
+3018(to)X
+3121(avoid)X
+3340(some)X
+3550(of)X
+3658(their)X
+3846(shortcomings.)X
+4337(The)X
+2706 1827(gdbm)N
+2918(library)X
+3162(allows)X
+3401(for)X
+3525(arbitrary-length)X
+4059(data,)X
+4242(and)X
+4387(its)X
+2706 1915(database)N
+3027(is)X
+3124(a)X
+3203(singular,)X
+3524(non-sparse)X
+2 f
+8 s
+3872 1890(4)N
+1 f
+10 s
+3947 1915(\256le.)N
+4112(The)X
+4280(gdbm)X
+2706 2003(library)N
+2947(also)X
+3103(includes)X
+2 f
+3396(dbm)X
+1 f
+3560(and)X
+2 f
+3702(ndbm)X
+1 f
+3906(compatible)X
+4288(inter-)X
+2706 2091(faces.)N
+2878 2205(The)N
+3025(gdbm)X
+3229(library)X
+3465(is)X
+3540(based)X
+3745(on)X
+2 f
+3847(extensible)X
+4189(hashing)X
+1 f
+4442(,)X
+2706 2293(a)N
+2766(dynamic)X
+3066(hashing)X
+3339(algorithm)X
+3674(by)X
+3778(Fagin)X
+3984(et)X
+4066(al)X
+4148([FAG79].)X
+2706 2381(This)N
+2881(algorithm)X
+3225(differs)X
+3467(from)X
+3655(the)X
+3785(previously)X
+4155(discussed)X
+2706 2469(algorithms)N
+3069(in)X
+3152(that)X
+3293(it)X
+3358(uses)X
+3517(a)X
+2 f
+3574(directory)X
+1 f
+3889(that)X
+4030(is)X
+4103(a)X
+4159(collapsed)X
+2706 2557(representation)N
+3192([ENB88])X
+3517(of)X
+3615(the)X
+3744(radix)X
+3940(search)X
+4177(trie)X
+4315(used)X
+2706 2645(by)N
+2 f
+2806(sdbm)X
+1 f
+2975(.)X
+10 f
+2706 2733 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+7 s
+3572 3761(L1)N
+1 Dt
+3485 3738 MXY
+-20 -13 Dl
+7 13 Dl
+-7 13 Dl
+20 -13 Dl
+-400 0 Dl
+3180 3027 MXY
+136 Dc
+2706 3494 MXY
+136 Dc
+2950 3264 MXY
+136 Dc
+3738 MY
+136 Dc
+3485 2968 MXY
+0 118 Dl
+238 0 Dl
+0 -118 Dl
+-238 0 Dl
+3442 MY
+0 119 Dl
+238 0 Dl
+0 -119 Dl
+-238 0 Dl
+3679 MY
+0 119 Dl
+238 0 Dl
+0 -119 Dl
+-238 0 Dl
+3187 3501 MXY
+136 Dc
+2963 3316 MXY
+-24 5 Dl
+15 4 Dl
+4 15 Dl
+5 -24 Dl
+-137 134 Dl
+3204 3083 MXY
+-24 5 Dl
+15 4 Dl
+3 14 Dl
+6 -23 Dl
+-137 133 Dl
+3204 3450 MXY
+-6 -24 Dl
+-3 14 Dl
+-15 5 Dl
+24 5 Dl
+-137 -134 Dl
+2842 3369(0)N
+3075 3139(0)N
+2842 3676(1)N
+3075 3443(1)N
+3562 3054(L00)N
+3565 3528(L01)N
+4197 2968 MXY
+0 118 Dl
+237 0 Dl
+0 -118 Dl
+-237 0 Dl
+3205 MY
+0 119 Dl
+237 0 Dl
+0 -119 Dl
+-237 0 Dl
+3561 MY
+0 118 Dl
+237 0 Dl
+0 -118 Dl
+-237 0 Dl
+3960 2909 MXY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+3146 MY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+3383 MY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+3620 MY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+4197 3027 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-119 0 Dl
+4197 3264 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-119 0 Dl
+3501 MY
+59 0 Dl
+0 89 Dl
+4078 3738 MXY
+59 0 Dl
+0 -88 Dl
+4197 3590 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-60 0 Dl
+4197 3650 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-60 0 Dl
+3991 3050(00)N
+3991 3287(01)N
+3991 3524(10)N
+3991 3761(11)N
+4269 3050(L00)N
+4269 3287(L01)N
+4283 3643(L1)N
+3485 3501 MXY
+-20 -13 Dl
+7 13 Dl
+-7 13 Dl
+20 -13 Dl
+-155 0 Dl
+3485 3027 MXY
+-20 -13 Dl
+7 13 Dl
+-7 13 Dl
+20 -13 Dl
+-163 0 Dl
+2967 3687 MXY
+-5 -24 Dl
+-4 14 Dl
+-15 4 Dl
+24 6 Dl
+-141 -141 Dl
+3 Dt
+-1 Ds
+8 s
+2706 4033(Figure)N
+2903(2:)X
+1 f
+2972(A)X
+3034(radix)X
+3181(search)X
+3359(trie)X
+3460(and)X
+3568(a)X
+3612(directory)X
+3858(representing)X
+4189(the)X
+4283(trie.)X
+10 s
+10 f
+2706 4209 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+2878 4411(In)N
+2968(this)X
+3106(algorithm,)X
+3460(a)X
+3519(directory)X
+3832(consists)X
+4108(of)X
+4198(a)X
+4256(search)X
+2706 4499(trie)N
+2847(of)X
+2947(depth)X
+2 f
+3158(n)X
+1 f
+3211(,)X
+3264(containing)X
+3635(2)X
+2 f
+7 s
+4467(n)Y
+10 s
+1 f
+3749 4499(bucket)N
+3996(addresses)X
+4337(\(i.e.)X
+2706 4587(each)N
+2897(element)X
+3194(of)X
+3304(the)X
+3445(trie)X
+3594(is)X
+3689(a)X
+3767(bucket)X
+4023(address\).)X
+4373(To)X
+2706 4675(access)N
+2935(the)X
+3056(hash)X
+3226(table,)X
+3425(a)X
+3483(32-bit)X
+3696(hash)X
+3865(value)X
+4061(is)X
+4136(calculated)X
+2706 4763(and)N
+2 f
+2861(n)X
+1 f
+2953(bits)X
+3107(of)X
+3213(the)X
+3350(value)X
+3563(are)X
+3701(used)X
+3886(to)X
+3986(index)X
+4202(into)X
+4364(the)X
+2706 4851(directory)N
+3018(to)X
+3102(obtain)X
+3324(a)X
+3382(bucket)X
+3618(address.)X
+3921(It)X
+3992(is)X
+4067(important)X
+4400(to)X
+2706 4939(note)N
+2866(that)X
+3008(multiple)X
+3296(entries)X
+3532(of)X
+3620(this)X
+3756(directory)X
+4067(may)X
+4226(contain)X
+2706 5027(the)N
+2833(same)X
+3026(bucket)X
+3268(address)X
+3537(as)X
+3632(a)X
+3696(result)X
+3902(of)X
+3997(directory)X
+4315(dou-)X
+2706 5115(bling)N
+2903(during)X
+3145(bucket)X
+3392(splitting.)X
+3706(Figure)X
+3948(2)X
+4021(illustrates)X
+4364(the)X
+2706 5203(relationship)N
+3126(between)X
+3436(a)X
+3513(typical)X
+3772(\(skewed\))X
+4108(search)X
+4355(trie)X
+2706 5291(and)N
+2850(its)X
+2953(directory)X
+3271(representation.)X
+3774(The)X
+3927(formation)X
+4270(of)X
+4364(the)X
+2706 5379(directory)N
+3016(shown)X
+3245(in)X
+3327(the)X
+3445(\256gure)X
+3652(is)X
+3725(as)X
+3812(follows.)X
+16 s
+2706 5593 MXY
+864 0 Dl
+2 f
+8 s
+2746 5648(4)N
+1 f
+9 s
+2796 5673(It)N
+2858(does)X
+3008(not)X
+3118(contain)X
+3348(holes.)X
+3 f
+10 s
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(3)X
+
+4 p
+%%Page: 4 4
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+604 538(Initially,)N
+937(there)X
+1158(is)X
+1271(one)X
+1446(slot)X
+1620(in)X
+1741(the)X
+1898(directory)X
+432 626(addressing)N
+802(a)X
+865(single)X
+1083(bucket.)X
+1364(The)X
+1515(depth)X
+1719(of)X
+1812(the)X
+1936(trie)X
+2069(is)X
+2148(0)X
+432 714(and)N
+577(0)X
+646(bits)X
+790(of)X
+886(each)X
+1063(hash)X
+1239(value)X
+1442(are)X
+1570(examined)X
+1910(to)X
+2000(deter-)X
+432 802(mine)N
+624(in)X
+718(which)X
+946(bucket)X
+1192(to)X
+1286(place)X
+1488(a)X
+1556(key;)X
+1726(all)X
+1837(keys)X
+2015(go)X
+2126(in)X
+432 890(bucket)N
+682(0.)X
+797(When)X
+1024(this)X
+1174(bucket)X
+1423(is)X
+1511(full,)X
+1677(its)X
+1787(contents)X
+2089(are)X
+432 978(divided)N
+698(between)X
+992(L0)X
+1107(and)X
+1249(L1)X
+1363(as)X
+1455(was)X
+1605(done)X
+1786(in)X
+1873(the)X
+1996(previ-)X
+432 1066(ously)N
+664(discussed)X
+1030(algorithms.)X
+1471(After)X
+1700(this)X
+1874(split,)X
+2090(the)X
+432 1154(address)N
+710(of)X
+814(the)X
+948(second)X
+1207(bucket)X
+1457(must)X
+1648(be)X
+1760(stored)X
+1992(in)X
+2090(the)X
+432 1242(directory.)N
+796(To)X
+939(accommodate)X
+1438(the)X
+1589(new)X
+1776(address,)X
+2090(the)X
+432 1330(directory)N
+752(is)X
+835(split)X
+2 f
+8 s
+972 1305(5)N
+1 f
+10 s
+1330(,)Y
+1054(by)X
+1163(doubling)X
+1476(it,)X
+1569(thus)X
+1731(increasing)X
+2090(the)X
+432 1418(depth)N
+630(of)X
+717(the)X
+835(directory)X
+1145(by)X
+1245(one.)X
+604 1532(After)N
+813(this)X
+967(split,)X
+1163(a)X
+1237(single)X
+1466(bit)X
+1588(of)X
+1693(the)X
+1829(hash)X
+2014(value)X
+432 1620(needs)N
+663(to)X
+773(be)X
+896(examined)X
+1255(to)X
+1364(decide)X
+1621(whether)X
+1927(the)X
+2072(key)X
+432 1708(belongs)N
+711(to)X
+803(L0)X
+922(or)X
+1019(L1.)X
+1158(Once)X
+1358(one)X
+1504(of)X
+1601(these)X
+1795(buckets)X
+2069(\256lls)X
+432 1796(\(L0)N
+578(for)X
+702(example\),)X
+1051(it)X
+1125(is)X
+1208(split)X
+1375(as)X
+1472(before,)X
+1728(and)X
+1873(the)X
+2000(direc-)X
+432 1884(tory)N
+585(is)X
+662(split)X
+823(again)X
+1021(to)X
+1107(make)X
+1305(room)X
+1498(for)X
+1615(the)X
+1736(address)X
+2000(of)X
+2090(the)X
+432 1972(third)N
+618(bucket.)X
+927(This)X
+1104(splitting)X
+1400(causes)X
+1645(the)X
+1778(addresses)X
+2121(of)X
+432 2060(the)N
+567(non-splitting)X
+1012(bucket)X
+1263(\(L1\))X
+1443(to)X
+1541(be)X
+1653(duplicated.)X
+2063(The)X
+432 2148(directory)N
+766(now)X
+948(has)X
+1099(four)X
+1277(entries,)X
+1555(a)X
+1635(depth)X
+1857(of)X
+1968(2,)X
+2072(and)X
+432 2236(indexes)N
+700(the)X
+821(buckets)X
+1089(L00,)X
+1261(L01)X
+1413(and)X
+1552(L1,)X
+1684(as)X
+1774(shown)X
+2006(in)X
+2090(the)X
+432 2324(Figure)N
+661(2.)X
+604 2438(The)N
+756(crucial)X
+1002(part)X
+1154(of)X
+1247(the)X
+1371(algorithm)X
+1708(is)X
+1787(the)X
+1911(observa-)X
+432 2526(tion)N
+580(that)X
+724(L1)X
+837(is)X
+914(addressed)X
+1255(twice)X
+1453(in)X
+1539(the)X
+1661(directory.)X
+1995(If)X
+2073(this)X
+432 2614(bucket)N
+679(were)X
+869(to)X
+964(split)X
+1134(now,)X
+1324(the)X
+1454(directory)X
+1776(already)X
+2045(con-)X
+432 2702(tains)N
+611(room)X
+808(to)X
+898(hold)X
+1067(the)X
+1192(address)X
+1460(of)X
+1554(the)X
+1679(new)X
+1840(bucket.)X
+2121(In)X
+432 2790(general,)N
+711(the)X
+831(relationship)X
+1231(between)X
+1521(the)X
+1641(directory)X
+1953(and)X
+2090(the)X
+432 2878(number)N
+704(of)X
+798(bucket)X
+1039(addresses)X
+1374(contained)X
+1713(therein)X
+1962(is)X
+2041(used)X
+432 2966(to)N
+517(decide)X
+750(when)X
+947(to)X
+1031(split)X
+1190(the)X
+1310(directory.)X
+1662(Each)X
+1845(bucket)X
+2081(has)X
+432 3054(a)N
+505(depth,)X
+740(\()X
+2 f
+767(n)X
+7 s
+3070(b)Y
+10 s
+1 f
+848 3054(\),)N
+932(associated)X
+1299(with)X
+1478(it)X
+1558(and)X
+1710(appears)X
+1992(in)X
+2090(the)X
+432 3142(directory)N
+744(exactly)X
+998(2)X
+2 f
+7 s
+3106(n)Y
+9 f
+1075(-)X
+2 f
+1106(n)X
+4 s
+3110(b)Y
+7 s
+1 f
+10 s
+1181 3142(times.)N
+1396(When)X
+1610(a)X
+1668(bucket)X
+1904(splits,)X
+2113(its)X
+432 3230(depth)N
+638(increases)X
+961(by)X
+1069(one.)X
+1253(The)X
+1406(directory)X
+1724(must)X
+1907(split)X
+2072(any)X
+432 3318(time)N
+602(a)X
+665(bucket's)X
+964(depth)X
+1169(exceeds)X
+1451(the)X
+1576(depth)X
+1781(of)X
+1875(the)X
+2000(direc-)X
+432 3406(tory.)N
+630(The)X
+784(following)X
+1123(code)X
+1303(fragment)X
+1621(helps)X
+1818(to)X
+1908(illustrate)X
+432 3494(the)N
+554(extendible)X
+912(hashing)X
+1185(algorithm)X
+1520([FAG79])X
+1838(for)X
+1955(access-)X
+432 3582(ing)N
+554(individual)X
+898(buckets)X
+1163(and)X
+1299(maintaining)X
+1701(the)X
+1819(directory.)X
+0 f
+8 s
+432 3881(hash)N
+622(=)X
+698 -0.4038(calchash\(key\);)AX
+432 3969(mask)N
+622(=)X
+698 -0.4018(maskvec[depth];)AX
+432 4145(bucket)N
+698(=)X
+774 -0.4038(directory[hash)AX
+1344(&)X
+1420(mask];)X
+432 4321(/*)N
+546(Key)X
+698 -0.4219(Insertion)AX
+1078(*/)X
+432 4409(if)N
+546 -0.4038(\(store\(bucket,)AX
+1116(key,)X
+1306(data\))X
+1534(==)X
+1648(FAIL\))X
+1876({)X
+720 4497(newbl)N
+948(=)X
+1024 -0.4167(getpage\(\);)AX
+720 4585 -0.4000(bucket->depth++;)AN
+720 4673 -0.4091(newbl->depth)AN
+1214(=)X
+1290 -0.4038(bucket->depth;)AX
+720 4761(if)N
+834 -0.4038(\(bucket->depth)AX
+1404(>)X
+1480(depth\))X
+1746({)X
+1008 4849(/*)N
+1122(double)X
+1388 -0.4219(directory)AX
+1768(*/)X
+1008 4937(depth++;)N
+1 f
+16 s
+432 5033 MXY
+864 0 Dl
+2 f
+8 s
+472 5088(5)N
+1 f
+9 s
+534 5113(This)N
+692(decision)X
+962(to)X
+1048(split)X
+1202(the)X
+1319(directory)X
+1608(is)X
+1685(based)X
+1878(on)X
+1979(a)X
+2040(com-)X
+432 5193(parison)N
+666(of)X
+748(the)X
+858(depth)X
+1040(of)X
+1121(the)X
+1230(page)X
+1387(being)X
+1568(split)X
+1713(and)X
+1838(the)X
+1947(depth)X
+2128(of)X
+432 5273(the)N
+543(trie.)X
+698(In)X
+781(Figure)X
+992(2,)X
+1069(the)X
+1180(depths)X
+1390(of)X
+1472(both)X
+1622(L00)X
+1760(and)X
+1886(L01)X
+2024(are)X
+2134(2,)X
+432 5353(whereas)N
+689(the)X
+798(depth)X
+979(of)X
+1060(L1)X
+1161(is)X
+1230(1.)X
+1323(Therefore,)X
+1646(if)X
+1710(L1)X
+1810(were)X
+1970(to)X
+2046(split,)X
+432 5433(the)N
+543(directory)X
+826(would)X
+1029(not)X
+1144(need)X
+1303(to)X
+1382(split.)X
+1565(In)X
+1648(reality,)X
+1872(a)X
+1926(bucket)X
+2140(is)X
+432 5513(allocated)N
+727(for)X
+846(the)X
+969(directory)X
+1264(at)X
+1351(the)X
+1474(time)X
+1637(of)X
+1732(\256le)X
+1858(creation)X
+2124(so)X
+432 5593(although)N
+707(the)X
+818(directory)X
+1100(splits)X
+1274(logically,)X
+1566(physical)X
+1828(splits)X
+2002(do)X
+2096(not)X
+432 5673(occur)N
+610(until)X
+760(the)X
+866(\256le)X
+976(becomes)X
+1246(quite)X
+1408(large.)X
+0 f
+8 s
+2994 538 -0.4219(directory)AN
+3374(=)X
+3450 -0.3971(double\(directory\);)AX
+2706 626(})N
+2706 714 -0.3958(splitbucket\(bucket,)AN
+3466(newbl\))X
+2706 802(...)N
+2418 890(})N
+2 f
+10 s
+3169 1255(hsearch)N
+1 f
+2590 1387(Since)N
+2 f
+2807(hsearch)X
+1 f
+3100(does)X
+3286(not)X
+3427(have)X
+3617(to)X
+3717(translate)X
+4027(hash)X
+2418 1475(values)N
+2659(into)X
+2819(disk)X
+2988(addresses,)X
+3352(it)X
+3432(can)X
+3579(use)X
+3721(much)X
+3934(simpler)X
+2418 1563(algorithms)N
+2808(than)X
+2994(those)X
+3211(de\256ned)X
+3495(above.)X
+3775(System)X
+4058(V's)X
+2 f
+2418 1651(hsearch)N
+1 f
+2708(constructs)X
+3069(a)X
+3141(\256xed-size)X
+3489(hash)X
+3671(table)X
+3862(\(speci\256ed)X
+2418 1739(by)N
+2519(the)X
+2637(user)X
+2791(at)X
+2869(table)X
+3045(creation\).)X
+3391(By)X
+3504(default,)X
+3767(a)X
+3823(multiplica-)X
+2418 1827(tive)N
+2570(hash)X
+2748(function)X
+3046(based)X
+3260(on)X
+3371(that)X
+3522(described)X
+3861(in)X
+3954(Knuth,)X
+2418 1915(Volume)N
+2710(3,)X
+2804(section)X
+3065(6.4)X
+3199([KNU68])X
+3541(is)X
+3628(used)X
+3809(to)X
+3905(obtain)X
+4138(a)X
+2418 2003(primary)N
+2694(bucket)X
+2930(address.)X
+3233(If)X
+3309(this)X
+3446(bucket)X
+3681(is)X
+3755(full,)X
+3907(a)X
+3964(secon-)X
+2418 2091(dary)N
+2593(multiplicative)X
+3069(hash)X
+3248(value)X
+3454(is)X
+3538(computed)X
+3885(to)X
+3978(de\256ne)X
+2418 2179(the)N
+2542(probe)X
+2751(interval.)X
+3062(The)X
+3213(probe)X
+3422(interval)X
+3693(is)X
+3772(added)X
+3989(to)X
+4076(the)X
+2418 2267(original)N
+2712(bucket)X
+2971(address)X
+3257(\(modulo)X
+3573(the)X
+3716(table)X
+3916(size\))X
+4112(to)X
+2418 2355(obtain)N
+2658(a)X
+2734(new)X
+2908(bucket)X
+3162(address.)X
+3483(This)X
+3665(process)X
+3946(repeats)X
+2418 2443(until)N
+2588(an)X
+2688(empty)X
+2911(bucket)X
+3148(is)X
+3224(found.)X
+3474(If)X
+3551(no)X
+3654(bucket)X
+3891(is)X
+3967(found,)X
+2418 2531(an)N
+2514(insertion)X
+2814(fails)X
+2972(with)X
+3134(a)X
+3190(``table)X
+3420(full'')X
+3605(condition.)X
+2590 2645(The)N
+2768(basic)X
+2986(algorithm)X
+3350(may)X
+3541(be)X
+3670(modi\256ed)X
+4006(by)X
+4138(a)X
+2418 2733(number)N
+2705(of)X
+2813(compile)X
+3112(time)X
+3295(options)X
+3571(available)X
+3902(to)X
+4005(those)X
+2418 2821(users)N
+2604(with)X
+2767(AT&T)X
+3006(source)X
+3237(code.)X
+3450(First,)X
+3637(the)X
+3756(package)X
+4040(pro-)X
+2418 2909(vides)N
+2638(two)X
+2809(options)X
+3094(for)X
+3238(hash)X
+3435(functions.)X
+3803(Users)X
+4036(may)X
+2418 2997(specify)N
+2690(their)X
+2877(own)X
+3055(hash)X
+3242(function)X
+3549(by)X
+3669(compiling)X
+4032(with)X
+2418 3085(``USCR'')N
+2757(de\256ned)X
+3016(and)X
+3155(declaring)X
+3477(and)X
+3616(de\256ning)X
+3901(the)X
+4022(vari-)X
+2418 3173(able)N
+2 f
+2578(hcompar)X
+1 f
+2863(,)X
+2909(a)X
+2971(function)X
+3263(taking)X
+3488(two)X
+3633(string)X
+3840(arguments)X
+2418 3261(and)N
+2560(returning)X
+2880(an)X
+2982(integer.)X
+3271(Users)X
+3480(may)X
+3643(also)X
+3797(request)X
+4054(that)X
+2418 3349(hash)N
+2587(values)X
+2814(be)X
+2912(computed)X
+3250(simply)X
+3489(by)X
+3590(taking)X
+3811(the)X
+3930(modulo)X
+2418 3437(of)N
+2521(key)X
+2673(\(using)X
+2909(division)X
+3201(rather)X
+3424(than)X
+3597(multiplication)X
+4080(for)X
+2418 3525(hash)N
+2589(value)X
+2787(calculation\).)X
+3230(If)X
+3308(this)X
+3447(technique)X
+3783(is)X
+3859(used,)X
+4049(col-)X
+2418 3613(lisions)N
+2651(are)X
+2775(resolved)X
+3072(by)X
+3176(scanning)X
+3485(sequentially)X
+3896(from)X
+4076(the)X
+2418 3701(selected)N
+2702(bucket)X
+2941(\(linear)X
+3176(probing\).)X
+3517(This)X
+3684(option)X
+3913(is)X
+3991(avail-)X
+2418 3789(able)N
+2572(by)X
+2672(de\256ning)X
+2954(the)X
+3072(variable)X
+3351(``DIV'')X
+3622(at)X
+3700(compile)X
+3978(time.)X
+2590 3903(A)N
+2720(second)X
+3015(option,)X
+3311(based)X
+3565(on)X
+3716(an)X
+3863(algorithm)X
+2418 3991(discovered)N
+2787(by)X
+2888(Richard)X
+3163(P.)X
+3248(Brent,)X
+3466(rearranges)X
+3822(the)X
+3940(table)X
+4116(at)X
+2418 4079(the)N
+2549(time)X
+2724(of)X
+2824(insertion)X
+3137(in)X
+3232(order)X
+3434(to)X
+3528(speed)X
+3743(up)X
+3855(retrievals.)X
+2418 4167(The)N
+2571(basic)X
+2764(idea)X
+2926(is)X
+3007(to)X
+3097(shorten)X
+3361(long)X
+3531(probe)X
+3741(sequences)X
+4094(by)X
+2418 4255(lengthening)N
+2833(short)X
+3030(probe)X
+3249(sequences.)X
+3651(Once)X
+3857(the)X
+3991(probe)X
+2418 4343(chain)N
+2613(has)X
+2741(exceeded)X
+3062(some)X
+3252(threshold)X
+3571(\(Brent)X
+3796(suggests)X
+4087(2\),)X
+2418 4431(we)N
+2541(attempt)X
+2809(to)X
+2899(shuf\257e)X
+3145(any)X
+3289(colliding)X
+3601(keys)X
+3776(\(keys)X
+3978(which)X
+2418 4519(appeared)N
+2734(in)X
+2821(the)X
+2944(probe)X
+3152(sequence)X
+3471(of)X
+3562(the)X
+3684(new)X
+3842(key\).)X
+4049(The)X
+2418 4607(details)N
+2652(of)X
+2744(this)X
+2884(key)X
+3025(shuf\257ing)X
+3333(can)X
+3469(be)X
+3569(found)X
+3780(in)X
+3866([KNU68])X
+2418 4695(and)N
+2576([BRE73].)X
+2946(This)X
+3129(algorithm)X
+3481(may)X
+3660(be)X
+3777(obtained)X
+4094(by)X
+2418 4783(de\256ning)N
+2700(the)X
+2818(variable)X
+3097(``BRENT'')X
+3487(at)X
+3565(compile)X
+3843(time.)X
+2590 4897(A)N
+2698(third)X
+2899(set)X
+3038(of)X
+3154(options,)X
+3458(obtained)X
+3783(by)X
+3912(de\256ning)X
+2418 4985(``CHAINED'',)N
+2943(use)X
+3086(linked)X
+3321(lists)X
+3484(to)X
+3581(resolve)X
+3848(collisions.)X
+2418 5073(Either)N
+2647(of)X
+2747(the)X
+2878(primary)X
+3164(hash)X
+3343(function)X
+3642(described)X
+3982(above)X
+2418 5161(may)N
+2584(be)X
+2688(used,)X
+2882(but)X
+3011(all)X
+3118(collisions)X
+3451(are)X
+3577(resolved)X
+3876(by)X
+3983(build-)X
+2418 5249(ing)N
+2554(a)X
+2623(linked)X
+2856(list)X
+2986(of)X
+3086(entries)X
+3333(from)X
+3522(the)X
+3653(primary)X
+3940(bucket.)X
+2418 5337(By)N
+2542(default,)X
+2816(new)X
+2981(entries)X
+3226(will)X
+3381(be)X
+3488(added)X
+3711(to)X
+3804(a)X
+3871(bucket)X
+4116(at)X
+2418 5425(the)N
+2541(beginning)X
+2886(of)X
+2978(the)X
+3101(bucket)X
+3339(chain.)X
+3577(However,)X
+3916(compile)X
+2418 5513(options)N
+2706(``SORTUP'')X
+3173(or)X
+3293(``SORTDOWN'')X
+3908(may)X
+4098(be)X
+2418 5601(speci\256ed)N
+2723(to)X
+2805(order)X
+2995(the)X
+3113(hash)X
+3280(chains)X
+3505(within)X
+3729(each)X
+3897(bucket.)X
+3 f
+432 5960(4)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+5 p
+%%Page: 5 5
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+2 f
+1444 538(dynahash)N
+1 f
+892 670(The)N
+2 f
+1054(dynahash)X
+1 f
+1398(library,)X
+1669(written)X
+1932(by)X
+2048(Esmond)X
+2346(Pitt,)X
+720 758(implements)N
+1183(Larson's)X
+1554(linear)X
+1827(hashing)X
+2165(algorithm)X
+720 846([LAR88])N
+1097(with)X
+1302(an)X
+2 f
+1440(hsearch)X
+1 f
+1756(compatible)X
+2174(interface.)X
+720 934(Intuitively,)N
+1099(a)X
+1161(hash)X
+1334(table)X
+1516(begins)X
+1751(as)X
+1844(a)X
+1905(single)X
+2121(bucket)X
+2360(and)X
+720 1022(grows)N
+941(in)X
+1028(generations,)X
+1443(where)X
+1665(a)X
+1725(generation)X
+2088(corresponds)X
+720 1110(to)N
+815(a)X
+884(doubling)X
+1201(in)X
+1296(the)X
+1427(size)X
+1585(of)X
+1685(the)X
+1815(hash)X
+1994(table.)X
+2222(The)X
+2379(0)X
+2 f
+7 s
+1078(th)Y
+10 s
+1 f
+720 1198(generation)N
+1085(occurs)X
+1321(as)X
+1414(the)X
+1538(table)X
+1719(grows)X
+1940(from)X
+2121(one)X
+2262(bucket)X
+720 1286(to)N
+814(two.)X
+1006(In)X
+1105(the)X
+1235(next)X
+1405(generation)X
+1776(the)X
+1906(table)X
+2093(grows)X
+2320(from)X
+720 1374(two)N
+862(to)X
+946(four.)X
+1122(During)X
+1371(each)X
+1541(generation,)X
+1921(every)X
+2121(bucket)X
+2356(that)X
+720 1462(existed)N
+967(at)X
+1045(the)X
+1163(beginning)X
+1503(of)X
+1590(the)X
+1708(generation)X
+2067(is)X
+2140(split.)X
+892 1576(The)N
+1041(table)X
+1221(starts)X
+1414(as)X
+1505(a)X
+1565(single)X
+1780(bucket)X
+2018(\(numbered)X
+2389(0\),)X
+720 1664(the)N
+839(current)X
+1088(split)X
+1245(bucket)X
+1479(is)X
+1552(set)X
+1661(to)X
+1743(bucket)X
+1977(0,)X
+2057(and)X
+2193(the)X
+2311(max-)X
+720 1752(imum)N
+933(split)X
+1097(point)X
+1288(is)X
+1368(set)X
+1483(to)X
+1571(twice)X
+1771(the)X
+1895(current)X
+2149(split)X
+2312(point)X
+720 1840(\(0\).)N
+863(When)X
+1084(it)X
+1157(is)X
+1239(time)X
+1410(for)X
+1532(a)X
+1596(bucket)X
+1838(to)X
+1928(split,)X
+2113(the)X
+2239(keys)X
+2414(in)X
+720 1928(the)N
+872(current)X
+1154(split)X
+1345(bucket)X
+1612(are)X
+1764(divided)X
+2057(between)X
+2378(the)X
+720 2016(current)N
+981(split)X
+1151(bucket)X
+1397(and)X
+1545(a)X
+1613(new)X
+1779(bucket)X
+2025(whose)X
+2262(bucket)X
+720 2104(number)N
+1000(is)X
+1088(equal)X
+1297(to)X
+1394(1)X
+1469(+)X
+1549(current)X
+1812(split)X
+1984(bucket)X
+2232(+)X
+2311(max-)X
+720 2192(imum)N
+927(split)X
+1085(point.)X
+1310(We)X
+1442(can)X
+1574(determine)X
+1915(which)X
+2131(keys)X
+2298(move)X
+720 2280(to)N
+807(the)X
+929(new)X
+1087(bucket)X
+1325(by)X
+1429(examining)X
+1791(the)X
+2 f
+1913(n)X
+7 s
+1962 2248(th)N
+10 s
+1 f
+2043 2280(bit)N
+2151(of)X
+2242(a)X
+2302(key's)X
+720 2368(hash)N
+899(value)X
+1105(where)X
+1334(n)X
+1406(is)X
+1491(the)X
+1620(generation)X
+1990(number.)X
+2306(After)X
+720 2456(the)N
+846(bucket)X
+1088(at)X
+1174(the)X
+1300(maximum)X
+1651(split)X
+1815(point)X
+2006(has)X
+2140(been)X
+2319(split,)X
+720 2544(the)N
+839(generation)X
+1198(number)X
+1463(is)X
+1536(incremented,)X
+1973(the)X
+2091(current)X
+2339(split)X
+720 2632(point)N
+908(is)X
+985(set)X
+1098(back)X
+1274(to)X
+1360(zero,)X
+1543(and)X
+1683(the)X
+1805(maximum)X
+2152(split)X
+2312(point)X
+720 2720(is)N
+815(set)X
+946(to)X
+1050(the)X
+1190(number)X
+1477(of)X
+1586(the)X
+1725(last)X
+1877(bucket)X
+2132(in)X
+2235(the)X
+2374(\256le)X
+720 2808(\(which)N
+971(is)X
+1052(equal)X
+1253(to)X
+1342(twice)X
+1543(the)X
+1668(old)X
+1797(maximum)X
+2148(split)X
+2312(point)X
+720 2896(plus)N
+873(1\).)X
+892 3010(To)N
+1031(facilitate)X
+1361(locating)X
+1668(keys,)X
+1884(we)X
+2027(maintain)X
+2356(two)X
+720 3098(masks.)N
+989(The)X
+1143(low)X
+1291(mask)X
+1488(is)X
+1569(equal)X
+1771(to)X
+1861(the)X
+1987(maximum)X
+2339(split)X
+720 3186(bucket)N
+967(and)X
+1116(the)X
+1247(high)X
+1422(mask)X
+1624(is)X
+1710(equal)X
+1917(to)X
+2011(the)X
+2141(next)X
+2311(max-)X
+720 3274(imum)N
+931(split)X
+1093(bucket.)X
+1372(To)X
+1486(locate)X
+1703(a)X
+1764(speci\256c)X
+2033(key,)X
+2193(we)X
+2311(com-)X
+720 3362(pute)N
+881(a)X
+940(32-bit)X
+1154(hash)X
+1324(value)X
+1520(using)X
+1715(a)X
+1773(bit-randomizing)X
+2311(algo-)X
+720 3450(rithm)N
+932(such)X
+1118(as)X
+1224(the)X
+1361(one)X
+1516(described)X
+1862(in)X
+1962([LAR88].)X
+2334(This)X
+720 3538(hash)N
+893(value)X
+1093(is)X
+1172(then)X
+1336(masked)X
+1607(with)X
+1775(the)X
+1898(high)X
+2065(mask.)X
+2299(If)X
+2378(the)X
+720 3626(resulting)N
+1026(number)X
+1297(is)X
+1376(greater)X
+1626(than)X
+1790(the)X
+1913(maximum)X
+2262(bucket)X
+720 3714(in)N
+823(the)X
+962(table)X
+1159(\(current)X
+1455(split)X
+1633(bucket)X
+1888(+)X
+1974(maximum)X
+2339(split)X
+720 3802(point\),)N
+962(the)X
+1091(hash)X
+1269(value)X
+1474(is)X
+1558(masked)X
+1834(with)X
+2007(the)X
+2136(low)X
+2287(mask.)X
+720 3890(In)N
+825(either)X
+1046(case,)X
+1242(the)X
+1377(result)X
+1592(of)X
+1696(the)X
+1831(mask)X
+2037(is)X
+2127(the)X
+2262(bucket)X
+720 3978(number)N
+989(for)X
+1107(the)X
+1229(given)X
+1431(key.)X
+1611(The)X
+1759(algorithm)X
+2093(below)X
+2312(illus-)X
+720 4066(trates)N
+914(this)X
+1049(process.)X
+0 f
+8 s
+720 4365(h)N
+796(=)X
+872 -0.4038(calchash\(key\);)AX
+720 4453(bucket)N
+986(=)X
+1062(h)X
+1138(&)X
+1214 -0.4167(high_mask;)AX
+720 4541(if)N
+834(\()X
+910(bucket)X
+1176(>)X
+1252 -0.4167(max_bucket)AX
+1670(\))X
+1008 4629(bucket)N
+1274(=)X
+1350(h)X
+1426(&)X
+1502 -0.4219(low_mask;)AX
+720 4717 -0.4018(return\(bucket\);)AN
+1 f
+10 s
+892 5042(In)N
+1013(order)X
+1237(to)X
+1353(decide)X
+1617(when)X
+1845(to)X
+1961(split)X
+2152(a)X
+2242(bucket,)X
+2 f
+720 5130(dynahash)N
+1 f
+1050(uses)X
+2 f
+1210(controlled)X
+1561(splitting)X
+1 f
+1822(.)X
+1884(A)X
+1964(hash)X
+2133(table)X
+2311(has)X
+2440(a)X
+720 5218(\256ll)N
+837(factor)X
+1054(which)X
+1279(is)X
+1361(expressed)X
+1707(in)X
+1798(terms)X
+2004(of)X
+2099(the)X
+2225(average)X
+720 5306(number)N
+990(of)X
+1082(keys)X
+1253(in)X
+1339(each)X
+1511(bucket.)X
+1789(Each)X
+1974(time)X
+2140(the)X
+2262(table's)X
+720 5394(total)N
+885(number)X
+1153(of)X
+1243(keys)X
+1413(divided)X
+1676(by)X
+1778(its)X
+1875(number)X
+2142(of)X
+2231(buckets)X
+720 5482(exceeds)N
+995(this)X
+1130(\256ll)X
+1238(factor,)X
+1466(a)X
+1522(bucket)X
+1756(is)X
+1829(split.)X
+2878 538(Since)N
+3079(the)X
+2 f
+3200(hsearch)X
+1 f
+3477(create)X
+3693(interface)X
+3998(\()X
+2 f
+4025(hcreate)X
+1 f
+4266(\))X
+4315(calls)X
+2706 626(for)N
+2842(an)X
+2960(estimate)X
+3269(of)X
+3378(the)X
+3518(\256nal)X
+3702(size)X
+3869(of)X
+3978(the)X
+4118(hash)X
+4306(table)X
+2706 714(\()N
+2 f
+2733(nelem)X
+1 f
+2925(\),)X
+2 f
+3007(dynahash)X
+1 f
+3349(uses)X
+3522(this)X
+3672(information)X
+4085(to)X
+4182(initialize)X
+2706 802(the)N
+2848(table.)X
+3088(The)X
+3257(initial)X
+3486(number)X
+3774(of)X
+3884(buckets)X
+4172(is)X
+4268(set)X
+4400(to)X
+2 f
+2706 890(nelem)N
+1 f
+2926(rounded)X
+3217(to)X
+3306(the)X
+3431(next)X
+3596(higher)X
+3828(power)X
+4056(of)X
+4150(two.)X
+4337(The)X
+2706 978(current)N
+2958(split)X
+3118(point)X
+3305(is)X
+3381(set)X
+3493(to)X
+3578(0)X
+3641(and)X
+3780(the)X
+3901(maximum)X
+4248(bucket)X
+2706 1066(and)N
+2842(maximum)X
+3186(split)X
+3343(point)X
+3527(are)X
+3646(set)X
+3755(to)X
+3837(this)X
+3972(rounded)X
+4255(value.)X
+3 f
+3148 1220(The)N
+3301(New)X
+3473(Implementation)X
+1 f
+2878 1352(Our)N
+3042(implementation)X
+3583(is)X
+3675(also)X
+3842(based)X
+4063(on)X
+4181(Larson's)X
+2706 1440(linear)N
+2939(hashing)X
+3238([LAR88])X
+3582(algorithm)X
+3943(as)X
+4060(well)X
+4248(as)X
+4364(the)X
+2 f
+2706 1528(dynahash)N
+1 f
+3047(implementation.)X
+3623(The)X
+2 f
+3782(dbm)X
+1 f
+3954(family)X
+4197(of)X
+4297(algo-)X
+2706 1616(rithms)N
+2942(decide)X
+3184(dynamically)X
+3612(which)X
+3840(bucket)X
+4085(to)X
+4178(split)X
+4346(and)X
+2706 1704(when)N
+2914(to)X
+3010(split)X
+3180(it)X
+3257(\(when)X
+3491(it)X
+3568(over\257ows\))X
+3944(while)X
+2 f
+4155(dynahash)X
+1 f
+2706 1792(splits)N
+2933(in)X
+3054(a)X
+3149(prede\256ned)X
+3547(order)X
+3776(\(linearly\))X
+4134(and)X
+4309(at)X
+4426(a)X
+2706 1880(prede\256ned)N
+3116(time)X
+3328(\(when)X
+3599(the)X
+3767(table)X
+3993(\256ll)X
+4151(factor)X
+4409(is)X
+2706 1968(exceeded\).)N
+3121(We)X
+3280(use)X
+3434(a)X
+3517(hybrid)X
+3773(of)X
+3887(these)X
+4099(techniques.)X
+2706 2056(Splits)N
+2913(occur)X
+3118(in)X
+3206(the)X
+3330(prede\256ned)X
+3695(order)X
+3891(of)X
+3984(linear)X
+4193(hashing,)X
+2706 2144(but)N
+2845(the)X
+2980(time)X
+3159(at)X
+3253(which)X
+3485(pages)X
+3704(are)X
+3839(split)X
+4012(is)X
+4101(determined)X
+2706 2232(both)N
+2869(by)X
+2970(page)X
+3143(over\257ows)X
+3480(\()X
+2 f
+3507(uncontrolled)X
+3937(splitting)X
+1 f
+4198(\))X
+4246(and)X
+4382(by)X
+2706 2320(exceeding)N
+3052(the)X
+3170(\256ll)X
+3278(factor)X
+3486(\()X
+2 f
+3513(controlled)X
+3862(splitting)X
+1 f
+4123(\))X
+2878 2434(A)N
+2962(hash)X
+3135(table)X
+3317(is)X
+3395(parameterized)X
+3876(by)X
+3981(both)X
+4148(its)X
+4248(bucket)X
+2706 2522(size)N
+2904(\()X
+2 f
+2931(bsize)X
+1 f
+(\))S
+3191(and)X
+3380(\256ll)X
+3541(factor)X
+3801(\()X
+2 f
+3828(ffactor)X
+1 f
+4041(\).)X
+4180(Whereas)X
+2 f
+2706 2610(dynahash's)N
+1 f
+3095(buckets)X
+3364(can)X
+3500(be)X
+3599(represented)X
+3993(as)X
+4083(a)X
+4142(linked)X
+4365(list)X
+2706 2698(of)N
+2798(elements)X
+3108(in)X
+3195(memory,)X
+3507(our)X
+3639(package)X
+3928(needs)X
+4136(to)X
+4222(support)X
+2706 2786(disk)N
+2874(access,)X
+3135(and)X
+3286(must)X
+3476(represent)X
+3806(buckets)X
+4086(in)X
+4183(terms)X
+4395(of)X
+2706 2874(pages.)N
+2955(The)X
+2 f
+3106(bsize)X
+1 f
+3291(is)X
+3369(the)X
+3492(size)X
+3642(\(in)X
+3756(bytes\))X
+3977(of)X
+4069(these)X
+4259(pages.)X
+2706 2962(As)N
+2833(in)X
+2933(linear)X
+3154(hashing,)X
+3461(the)X
+3597(number)X
+3879(of)X
+3983(buckets)X
+4265(in)X
+4364(the)X
+2706 3050(table)N
+2906(is)X
+3003(equal)X
+3221(to)X
+3327(the)X
+3469(number)X
+3758(of)X
+3869(keys)X
+4060(in)X
+4165(the)X
+4306(table)X
+2706 3138(divided)N
+2988(by)X
+2 f
+3110(ffactor)X
+1 f
+3323(.)X
+2 f
+8 s
+3113(6)Y
+1 f
+10 s
+3417 3138(The)N
+3584(controlled)X
+3950(splitting)X
+4252(occurs)X
+2706 3226(each)N
+2878(time)X
+3044(the)X
+3166(number)X
+3435(of)X
+3526(keys)X
+3697(in)X
+3783(the)X
+3905(table)X
+4085(exceeds)X
+4364(the)X
+2706 3314(\256ll)N
+2814(factor)X
+3022(multiplied)X
+3370(by)X
+3470(the)X
+3588(number)X
+3853(of)X
+3940(buckets.)X
+2878 3428(Inserting)N
+3187(keys)X
+3358(and)X
+3498(splitting)X
+3783(buckets)X
+4051(is)X
+4127(performed)X
+2706 3516(precisely)N
+3018(as)X
+3107(described)X
+3437(previously)X
+3796(for)X
+2 f
+3911(dynahash)X
+1 f
+4218(.)X
+4279(How-)X
+2706 3604(ever,)N
+2897(since)X
+3094(buckets)X
+3371(are)X
+3502(now)X
+3671(comprised)X
+4036(of)X
+4134(pages,)X
+4368(we)X
+2706 3692(must)N
+2883(be)X
+2981(prepared)X
+3284(to)X
+3367(handle)X
+3602(cases)X
+3793(where)X
+4011(the)X
+4130(size)X
+4276(of)X
+4364(the)X
+2706 3780(keys)N
+2873(and)X
+3009(data)X
+3163(in)X
+3245(a)X
+3301(bucket)X
+3535(exceed)X
+3779(the)X
+3897(bucket)X
+4131(size.)X
+3 f
+3318 3934(Over\257ow)N
+3654(Pages)X
+1 f
+2878 4066(There)N
+3095(are)X
+3223(two)X
+3372(cases)X
+3571(where)X
+3797(a)X
+3862(key)X
+4007(may)X
+4174(not)X
+4305(\256t)X
+4400(in)X
+2706 4154(its)N
+2802(designated)X
+3166(bucket.)X
+3441(In)X
+3529(the)X
+3647(\256rst)X
+3791(case,)X
+3970(the)X
+4088(total)X
+4250(size)X
+4395(of)X
+2706 4242(the)N
+2833(key)X
+2978(and)X
+3123(data)X
+3286(may)X
+3453(exceed)X
+3706(the)X
+3833(bucket)X
+4076(size.)X
+4269(In)X
+4364(the)X
+2706 4330(second,)N
+3008(addition)X
+3328(of)X
+3453(a)X
+3547(new)X
+3739(key)X
+3913(could)X
+4149(cause)X
+4386(an)X
+2706 4418(over\257ow,)N
+3068(but)X
+3227(the)X
+3382(bucket)X
+3652(in)X
+3770(question)X
+4097(is)X
+4206(not)X
+4364(yet)X
+2706 4506(scheduled)N
+3049(to)X
+3133(be)X
+3230(split.)X
+3428(In)X
+3516(existing)X
+3790(implementations,)X
+4364(the)X
+2706 4594(second)N
+2953(case)X
+3115(never)X
+3317(arises)X
+3523(\(since)X
+3738(buckets)X
+4006(are)X
+4128(split)X
+4288(when)X
+2706 4682(they)N
+2871(over\257ow\))X
+3210(and)X
+3352(the)X
+3476(\256rst)X
+3626(case)X
+3791(is)X
+3870(not)X
+3998(handled)X
+4278(at)X
+4362(all.)X
+2706 4770(Although)N
+3036(large)X
+3225(key/data)X
+3525(pair)X
+3678(handling)X
+3986(is)X
+4066(dif\256cult)X
+4346(and)X
+2706 4858(expensive,)N
+3083(it)X
+3163(is)X
+3252(essential.)X
+3604(In)X
+3706(a)X
+3777(linear)X
+3995(hashed)X
+4253(imple-)X
+2706 4946(mentation,)N
+3087(over\257ow)X
+3413(pages)X
+3636(are)X
+3775(required)X
+4083(for)X
+4217(buckets)X
+2706 5034(which)N
+2935(over\257ow)X
+3253(before)X
+3492(they)X
+3662(are)X
+3793(split,)X
+3982(so)X
+4085(we)X
+4211(can)X
+4355(use)X
+2706 5122(the)N
+2833(same)X
+3027(mechanism)X
+3421(for)X
+3544(large)X
+3734(key/data)X
+4035(pairs)X
+4220(that)X
+4368(we)X
+2706 5210(use)N
+2837(for)X
+2955(over\257ow)X
+3264(pages.)X
+3511(Logically,)X
+3862(we)X
+3980(chain)X
+4177(over\257ow)X
+16 s
+2706 5353 MXY
+864 0 Dl
+2 f
+8 s
+2746 5408(6)N
+1 f
+9 s
+2801 5433(This)N
+2952(is)X
+3023(not)X
+3138(strictly)X
+3361(true.)X
+3532(The)X
+3667(\256le)X
+3782(does)X
+3937(not)X
+4052(contract)X
+4306(when)X
+2706 5513(keys)N
+2861(are)X
+2972(deleted,)X
+3221(so)X
+3308(the)X
+3419(number)X
+3662(of)X
+3744(buckets)X
+3986(is)X
+4056(actually)X
+4306(equal)X
+2706 5593(to)N
+2782(the)X
+2890(maximum)X
+3202(number)X
+3441(of)X
+3520(keys)X
+3671(ever)X
+3814(present)X
+4041(in)X
+4116(the)X
+4223(table)X
+4382(di-)X
+2706 5673(vided)N
+2884(by)X
+2974(the)X
+3080(\256ll)X
+3178(factor.)X
+3 f
+10 s
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(5)X
+
+6 p
+%%Page: 6 6
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+432 538(pages)N
+639(to)X
+725(the)X
+847(buckets)X
+1116(\(also)X
+1296(called)X
+1512(primary)X
+1789(pages\).)X
+2062(In)X
+2152(a)X
+432 626(memory)N
+730(based)X
+943(representation,)X
+1448(over\257ow)X
+1763(pages)X
+1976(do)X
+2086(not)X
+432 714(pose)N
+628(any)X
+792(special)X
+1063(problems)X
+1409(because)X
+1712(we)X
+1854(can)X
+2014(chain)X
+432 802(over\257ow)N
+776(pages)X
+1017(to)X
+1137(primary)X
+1449(pages)X
+1690(using)X
+1921(memory)X
+432 890(pointers.)N
+776(However,)X
+1137(mapping)X
+1463(these)X
+1674(over\257ow)X
+2005(pages)X
+432 978(into)N
+584(a)X
+648(disk)X
+809(\256le)X
+939(is)X
+1019(more)X
+1211(of)X
+1305(a)X
+1368(challenge,)X
+1723(since)X
+1915(we)X
+2036(need)X
+432 1066(to)N
+547(be)X
+675(able)X
+861(to)X
+975(address)X
+1268(both)X
+1462(bucket)X
+1728(pages,)X
+1983(whose)X
+432 1154(numbers)N
+729(are)X
+849(growing)X
+1137(linearly,)X
+1422(and)X
+1558(some)X
+1747(indeterminate)X
+432 1242(number)N
+715(of)X
+820(over\257ow)X
+1143(pages)X
+1364(without)X
+1646(reorganizing)X
+2090(the)X
+432 1330(\256le.)N
+604 1444(One)N
+789(simple)X
+1053(solution)X
+1361(would)X
+1612(be)X
+1739(to)X
+1852(allocate)X
+2152(a)X
+432 1532(separate)N
+737(\256le)X
+880(for)X
+1015(over\257ow)X
+1341(pages.)X
+1604(The)X
+1769(disadvantage)X
+432 1620(with)N
+605(such)X
+783(a)X
+850(technique)X
+1193(is)X
+1276(that)X
+1426(it)X
+1500(requires)X
+1789(an)X
+1895(extra)X
+2086(\256le)X
+432 1708(descriptor,)N
+794(an)X
+891(extra)X
+1073(system)X
+1316(call)X
+1453(on)X
+1554(open)X
+1731(and)X
+1867(close,)X
+2072(and)X
+432 1796(logically)N
+739(associating)X
+1122(two)X
+1269(independent)X
+1687(\256les.)X
+1886(For)X
+2023(these)X
+432 1884(reasons,)N
+728(we)X
+857(wanted)X
+1123(to)X
+1219(map)X
+1391(both)X
+1567(primary)X
+1855(pages)X
+2072(and)X
+432 1972(over\257ow)N
+737(pages)X
+940(into)X
+1084(the)X
+1202(same)X
+1387(\256le)X
+1509(space.)X
+604 2086(The)N
+799(buddy-in-waiting)X
+1425(algorithm)X
+1806(provides)X
+2152(a)X
+432 2174(mechanism)N
+851(to)X
+966(support)X
+1259(multiple)X
+1578(pages)X
+1814(per)X
+1970(logical)X
+432 2262(bucket)N
+685(while)X
+902(retaining)X
+1226(the)X
+1362(simple)X
+1613(split)X
+1788(sequence)X
+2121(of)X
+432 2350(linear)N
+681(hashing.)X
+1015(Over\257ow)X
+1383(pages)X
+1631(are)X
+1795(preallocated)X
+432 2438(between)N
+781(generations)X
+1232(of)X
+1379(primary)X
+1713(pages.)X
+1996(These)X
+432 2526(over\257ow)N
+759(pages)X
+984(are)X
+1125(used)X
+1314(by)X
+1436(any)X
+1594(bucket)X
+1850(containing)X
+432 2614(more)N
+646(keys)X
+842(than)X
+1029(\256t)X
+1144(on)X
+1273(the)X
+1420(primary)X
+1723(page)X
+1924(and)X
+2089(are)X
+432 2702(reclaimed,)N
+808(if)X
+896(possible,)X
+1217(when)X
+1430(the)X
+1567(bucket)X
+1819(later)X
+2000(splits.)X
+432 2790(Figure)N
+687(3)X
+773(depicts)X
+1045(the)X
+1188(layout)X
+1433(of)X
+1545(primary)X
+1844(pages)X
+2072(and)X
+432 2878(over\257ow)N
+752(pages)X
+970(within)X
+1209(the)X
+1342(same)X
+1542(\256le.)X
+1699(Over\257ow)X
+2036(page)X
+432 2966(use)N
+586(information)X
+1011(is)X
+1111(recorded)X
+1440(in)X
+1548(bitmaps)X
+1847(which)X
+2089(are)X
+432 3054(themselves)N
+819(stored)X
+1046(on)X
+1157(over\257ow)X
+1472(pages.)X
+1725(The)X
+1880(addresses)X
+432 3142(of)N
+520(the)X
+639(bitmap)X
+882(pages)X
+1086(and)X
+1223(the)X
+1342(number)X
+1608(of)X
+1695(pages)X
+1898(allocated)X
+432 3230(at)N
+515(each)X
+688(split)X
+850(point)X
+1039(are)X
+1163(stored)X
+1384(in)X
+1470(the)X
+1592(\256le)X
+1718(header.)X
+1997(Using)X
+432 3318(this)N
+577(information,)X
+1005(both)X
+1177(over\257ow)X
+1492(addresses)X
+1829(and)X
+1974(bucket)X
+432 3406(addresses)N
+764(can)X
+900(be)X
+999(mapped)X
+1276(to)X
+1361(disk)X
+1517(addresses)X
+1848(by)X
+1951(the)X
+2072(fol-)X
+432 3494(lowing)N
+674(calculation:)X
+0 f
+8 s
+432 3793(int)N
+736(bucket;)X
+1192(/*)X
+1306(bucket)X
+1572(address)X
+1876(*/)X
+432 3881(u_short)N
+736(oaddr;)X
+1192(/*)X
+1306(OVERFLOW)X
+1648(address)X
+1952(*/)X
+432 3969(int)N
+736 -0.4125(nhdr_pages;)AX
+1192(/*)X
+1306(npages)X
+1572(in)X
+1686 -112.4062(\256le)AX
+1838(header)X
+2104(*/)X
+432 4057(int)N
+736 -0.4125(spares[32];)AX
+1192(/*)X
+1306(npages)X
+1572(at)X
+1686(each)X
+1876(split)X
+2104(*/)X
+432 4145(int)N
+736(log2\(\);)X
+1198(/*)X
+1312(ceil\(log)X
+1654(base)X
+1844(2\))X
+1958(*/)X
+432 4321(#DEFINE)N
+736 -0.3929(BUCKET_TO_PAGE\(bucket\))AX
+1610(\\)X
+584 4409(bucket)N
+850(+)X
+926 -0.4167(nhdr_pages)AX
+1344(+)X
+1420(\\)X
+584 4497 -0.3894(\(bucket?spares[logs2\(bucket)AN
+1648(+)X
+1724(1\)-1]:0\))X
+432 4673(#DEFINE)N
+736 -0.3947(OADDR_TO_PAGE\(oaddr\))AX
+1534(\\)X
+584 4761 -0.3984(BUCKET_TO_PAGE\(\(1)AN
+1268(<<)X
+1382 -0.4091(\(oaddr>>11\)\))AX
+1876(-)X
+1952(1\))X
+2066(+)X
+2142(\\)X
+584 4849(oaddr)N
+812(&)X
+888(0x7ff;)X
+1 f
+10 s
+604 5262(An)N
+728(over\257ow)X
+1039(page)X
+1217(is)X
+1295(addressed)X
+1637(by)X
+1742(its)X
+1842(split)X
+2004(point,)X
+432 5350(identifying)N
+858(the)X
+1031(generations)X
+1476(between)X
+1819(which)X
+2090(the)X
+432 5438(over\257ow)N
+740(page)X
+915(is)X
+991(allocated,)X
+1324(and)X
+1463(its)X
+1561(page)X
+1736(number,)X
+2023(iden-)X
+432 5526(tifying)N
+665(the)X
+783(particular)X
+1111(page)X
+1283(within)X
+1507(the)X
+1625(split)X
+1782(point.)X
+1986(In)X
+2073(this)X
+432 5614(implementation,)N
+983(offsets)X
+1225(within)X
+1457(pages)X
+1668(are)X
+1795(16)X
+1903(bits)X
+2046(long)X
+432 5702(\(limiting)N
+732(the)X
+851(maximum)X
+1196(page)X
+1368(size)X
+1513(to)X
+1595(32K\),)X
+1800(so)X
+1891(we)X
+2005(select)X
+2418 538(an)N
+2535(over\257ow)X
+2860(page)X
+3052(addressing)X
+3435(algorithm)X
+3786(that)X
+3946(can)X
+4098(be)X
+2418 626(expressed)N
+2760(in)X
+2847(16)X
+2952(bits)X
+3091(and)X
+3231(which)X
+3451(allows)X
+3684(quick)X
+3886(retrieval.)X
+2418 714(The)N
+2568(top)X
+2695(\256ve)X
+2840(bits)X
+2980(indicate)X
+3258(the)X
+3380(split)X
+3541(point)X
+3729(and)X
+3869(the)X
+3991(lower)X
+2418 802(eleven)N
+2650(indicate)X
+2926(the)X
+3046(page)X
+3220(number)X
+3487(within)X
+3713(the)X
+3832(split)X
+3990(point.)X
+2418 890(Since)N
+2633(\256ve)X
+2789(bits)X
+2940(are)X
+3075(reserved)X
+3384(for)X
+3514(the)X
+3648(split)X
+3821(point,)X
+4041(\256les)X
+2418 978(may)N
+2578(split)X
+2737(32)X
+2839(times)X
+3034(yielding)X
+3318(a)X
+3376(maximum)X
+3721(\256le)X
+3844(size)X
+3990(of)X
+4078(2)X
+7 s
+946(32)Y
+10 s
+2418 1066(buckets)N
+2698(and)X
+2849(32)X
+2 f
+(*)S
+1 f
+2982(2)X
+7 s
+1034(11)Y
+10 s
+3113 1066(over\257ow)N
+3433(pages.)X
+3691(The)X
+3850(maximum)X
+2418 1154(page)N
+2597(size)X
+2749(is)X
+2829(2)X
+7 s
+1122(15)Y
+10 s
+1154(,)Y
+2971(yielding)X
+3259(a)X
+3321(maximum)X
+3671(\256le)X
+3799(size)X
+3950(greater)X
+2418 1242(than)N
+2601(131,000)X
+2906(GB)X
+3061(\(on)X
+3212(\256le)X
+3358(systems)X
+3655(supporting)X
+4041(\256les)X
+2418 1330(larger)N
+2626(than)X
+2784(4GB\).)X
+10 f
+2418 1418 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 Dt
+4014 2275 MXY
+0 133 Dl
+3881 2275 MXY
+0 133 Dl
+3748 2275 MXY
+0 133 Dl
+3083 2275 MXY
+0 133 Dl
+5 s
+1 f
+3523 2475(2/3)N
+3390(2/2)X
+3257(2/1)X
+2859(1/2)X
+2726(1/1)X
+5 Dt
+3814 1743 MXY
+0 133 Dl
+3282 1743 MXY
+0 133 Dl
+3017 1743 MXY
+0 133 Dl
+2884 1743 MXY
+0 133 Dl
+1 Dt
+3681 1743 MXY
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3548 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3415 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3282 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3150 MX
+0 133 Dl
+132 0 Dl
+0 -133 Dl
+-132 0 Dl
+3017 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+2884 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3 f
+8 s
+3017 2601(Over\257ow)N
+3285(Addresses)X
+3515 2833(Over\257ow)N
+3783(Pages)X
+2850(Buckets)X
+1 Di
+3349 2740 MXY
+ 3349 2740 lineto
+ 3482 2740 lineto
+ 3482 2873 lineto
+ 3349 2873 lineto
+ 3349 2740 lineto
+closepath 3 3349 2740 3482 2873 Dp
+2684 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+5 Dt
+4146 2275 MXY
+0 133 Dl
+3216 2275 MXY
+0 133 Dl
+2684 2275 MXY
+0 133 Dl
+2551 2275 MXY
+0 133 Dl
+1 f
+3798 1963(3)N
+3266 1980(2)N
+3001(1)X
+2868(0)X
+1 Dt
+2751 1743 MXY
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3548 2275 MXY
+-15 -22 Dl
+2 16 Dl
+-13 11 Dl
+26 -5 Dl
+-282 -117 Dl
+3432 2275 MXY
+-10 -25 Dl
+-2 16 Dl
+-15 8 Dl
+27 1 Dl
+-166 -117 Dl
+3282 2275 MXY
+12 -25 Dl
+-14 10 Dl
+-15 -6 Dl
+17 21 Dl
+-16 -117 Dl
+2884 2275 MXY
+26 7 Dl
+-12 -12 Dl
+3 -16 Dl
+-17 21 Dl
+382 -117 Dl
+2751 2275 MXY
+25 9 Dl
+-11 -12 Dl
+5 -17 Dl
+-19 20 Dl
+515 -117 Dl
+3 f
+3070 2152(Over\257ow)N
+3338(Pages)X
+3482 2275 MXY
+ 3482 2275 lineto
+ 3615 2275 lineto
+ 3615 2408 lineto
+ 3482 2408 lineto
+ 3482 2275 lineto
+closepath 3 3482 2275 3615 2408 Dp
+3349 MX
+ 3349 2275 lineto
+ 3482 2275 lineto
+ 3482 2408 lineto
+ 3349 2408 lineto
+ 3349 2275 lineto
+closepath 3 3349 2275 3482 2408 Dp
+3216 MX
+ 3216 2275 lineto
+ 3349 2275 lineto
+ 3349 2408 lineto
+ 3216 2408 lineto
+ 3216 2275 lineto
+closepath 3 3216 2275 3349 2408 Dp
+2817 MX
+ 2817 2275 lineto
+ 2950 2275 lineto
+ 2950 2408 lineto
+ 2817 2408 lineto
+ 2817 2275 lineto
+closepath 3 2817 2275 2950 2408 Dp
+2684 MX
+ 2684 2275 lineto
+ 2817 2275 lineto
+ 2817 2408 lineto
+ 2684 2408 lineto
+ 2684 2275 lineto
+closepath 3 2684 2275 2817 2408 Dp
+3615 MX
+0 133 Dl
+531 0 Dl
+0 -133 Dl
+-531 0 Dl
+2950 MX
+0 133 Dl
+266 0 Dl
+0 -133 Dl
+-266 0 Dl
+2551 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3798 1726 MXY
+-21 -18 Dl
+6 16 Dl
+-10 13 Dl
+25 -11 Dl
+-599 -99 Dl
+3266 1726 MXY
+-1 -27 Dl
+-7 15 Dl
+-17 1 Dl
+25 11 Dl
+-67 -99 Dl
+3033 1726 MXY
+27 1 Dl
+-14 -8 Dl
+-1 -17 Dl
+-12 24 Dl
+166 -99 Dl
+2900 1726 MXY
+27 7 Dl
+-13 -11 Dl
+3 -17 Dl
+-17 21 Dl
+299 -99 Dl
+3058 1621(Split)N
+3203(Points)X
+2418 2275 MXY
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3 Dt
+-1 Ds
+3137(Figure)Y
+2619(3:)X
+1 f
+2691(Split)X
+2832(points)X
+3008(occur)X
+3168(between)X
+3399(generations)X
+3712(and)X
+3823(are)X
+3919(numbered)X
+2418 3225(from)N
+2560(0.)X
+2642(In)X
+2713(this)X
+2824(\256gure)X
+2991(there)X
+3136(are)X
+3231(two)X
+3345(over\257ow)X
+3590(pages)X
+3753(allocated)X
+4000(at)X
+4063(split)X
+2418 3313(point)N
+2566(1)X
+2614(and)X
+2722(three)X
+2865(allocated)X
+3111(at)X
+3173(split)X
+3300(point)X
+3448(2.)X
+10 s
+10 f
+2418 3489 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+2949 3731(Buffer)N
+3192(Management)X
+1 f
+2590 3863(The)N
+2744(hash)X
+2920(table)X
+3105(is)X
+3187(stored)X
+3412(in)X
+3502(memory)X
+3797(as)X
+3892(a)X
+3956(logical)X
+2418 3951(array)N
+2633(of)X
+2749(bucket)X
+3012(pointers.)X
+3359(Physically,)X
+3761(the)X
+3907(array)X
+4121(is)X
+2418 4039(arranged)N
+2728(in)X
+2818(segments)X
+3144(of)X
+3239(256)X
+3387(pointers.)X
+3713(Initially,)X
+4013(there)X
+2418 4127(is)N
+2530(space)X
+2767(to)X
+2887(allocate)X
+3195(256)X
+3373(segments.)X
+3769(Reallocation)X
+2418 4215(occurs)N
+2651(when)X
+2847(the)X
+2967(number)X
+3234(of)X
+3323(buckets)X
+3590(exceeds)X
+3867(32K)X
+4027(\(256)X
+2418 4303(*)N
+2508(256\).)X
+2745(Primary)X
+3053(pages)X
+3286(may)X
+3473(be)X
+3598(accessed)X
+3929(directly)X
+2418 4391(through)N
+2711(the)X
+2853(array)X
+3062(by)X
+3185(bucket)X
+3442(number)X
+3730(and)X
+3889(over\257ow)X
+2418 4479(pages)N
+2628(are)X
+2754 0.4028(referenced)AX
+3122(logically)X
+3429(by)X
+3536(their)X
+3710(over\257ow)X
+4022(page)X
+2418 4567(address.)N
+2726(For)X
+2864(small)X
+3063(hash)X
+3236(tables,)X
+3469(it)X
+3539(is)X
+3618(desirable)X
+3934(to)X
+4022(keep)X
+2418 4655(all)N
+2525(pages)X
+2735(in)X
+2823(main)X
+3009(memory)X
+3302(while)X
+3506(on)X
+3612(larger)X
+3826(tables,)X
+4059(this)X
+2418 4743(is)N
+2523(probably)X
+2860(impossible.)X
+3298(To)X
+3438(satisfy)X
+3698(both)X
+3891(of)X
+4009(these)X
+2418 4831(requirements,)N
+2900(the)X
+3041(package)X
+3348(includes)X
+3658(buffer)X
+3897(manage-)X
+2418 4919(ment)N
+2598(with)X
+2760(LRU)X
+2940(\(least)X
+3134(recently)X
+3413(used\))X
+3607(replacement.)X
+2590 5033(By)N
+2730(default,)X
+3020(the)X
+3165(package)X
+3475(allocates)X
+3802(up)X
+3928(to)X
+4036(64K)X
+2418 5121(bytes)N
+2616(of)X
+2712(buffered)X
+3014(pages.)X
+3246(All)X
+3377(pages)X
+3589(in)X
+3680(the)X
+3807(buffer)X
+4032(pool)X
+2418 5209(are)N
+2542(linked)X
+2766(in)X
+2852(LRU)X
+3036(order)X
+3230(to)X
+3316(facilitate)X
+3621(fast)X
+3761(replacement.)X
+2418 5297(Whereas)N
+2724(ef\256cient)X
+3011(access)X
+3241(to)X
+3327(primary)X
+3605(pages)X
+3812(is)X
+3889(provided)X
+2418 5385(by)N
+2521(the)X
+2642(bucket)X
+2879(array,)X
+3087(ef\256cient)X
+3372(access)X
+3600(to)X
+3684(over\257ow)X
+3991(pages)X
+2418 5473(is)N
+2501(provided)X
+2816(by)X
+2926(linking)X
+3182(over\257ow)X
+3497(page)X
+3679(buffers)X
+3936(to)X
+4027(their)X
+2418 5561(predecessor)N
+2827(page)X
+3008(\(either)X
+3247(the)X
+3374(primary)X
+3657(page)X
+3838(or)X
+3933(another)X
+2418 5649(over\257ow)N
+2742(page\).)X
+3000(This)X
+3181(means)X
+3425(that)X
+3584(an)X
+3699(over\257ow)X
+4022(page)X
+3 f
+432 5960(6)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+7 p
+%%Page: 7 7
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(cannot)N
+955(be)X
+1052(present)X
+1305(in)X
+1388(the)X
+1507(buffer)X
+1724(pool)X
+1886(if)X
+1955(its)X
+2050(primary)X
+2324(page)X
+720 626(is)N
+804(not)X
+937(present.)X
+1240(This)X
+1413(does)X
+1591(not)X
+1724(impact)X
+1972(performance)X
+2409(or)X
+720 714(functionality,)N
+1209(because)X
+1524(an)X
+1660(over\257ow)X
+2005(page)X
+2217(will)X
+2400(be)X
+720 802(accessed)N
+1048(only)X
+1236(after)X
+1430(its)X
+1550(predecessor)X
+1975(page)X
+2172(has)X
+2324(been)X
+720 890(accessed.)N
+1068(Figure)X
+1303(4)X
+1369(depicts)X
+1622(the)X
+1746(data)X
+1905(structures)X
+2242(used)X
+2414(to)X
+720 978(manage)N
+990(the)X
+1108(buffer)X
+1325(pool.)X
+892 1092(The)N
+1040(in-memory)X
+1419(bucket)X
+1656(array)X
+1845(contains)X
+2134(pointers)X
+2414(to)X
+720 1180(buffer)N
+975(header)X
+1248(structures)X
+1617(which)X
+1870(represent)X
+2222(primary)X
+720 1268(pages.)N
+968(Buffer)X
+1203(headers)X
+1474(contain)X
+1735(modi\256ed)X
+2043(bits,)X
+2202(the)X
+2324(page)X
+720 1356(address)N
+995(of)X
+1096(the)X
+1228(buffer,)X
+1479(a)X
+1548(pointer)X
+1808(to)X
+1903(the)X
+2034(actual)X
+2259(buffer,)X
+720 1444(and)N
+875(a)X
+950(pointer)X
+1216(to)X
+1317(the)X
+1454(buffer)X
+1690(header)X
+1944(for)X
+2077(an)X
+2191(over\257ow)X
+720 1532(page)N
+901(if)X
+979(it)X
+1052(exists,)X
+1283(in)X
+1374(addition)X
+1665(to)X
+1756(the)X
+1883(LRU)X
+2072(links.)X
+2296(If)X
+2378(the)X
+720 1620(buffer)N
+950(corresponding)X
+1442(to)X
+1537(a)X
+1606(particular)X
+1947(bucket)X
+2194(is)X
+2280(not)X
+2414(in)X
+720 1708(memory,)N
+1048(its)X
+1164(pointer)X
+1432(is)X
+1526(NULL.)X
+1801(In)X
+1909(effect,)X
+2154(pages)X
+2377(are)X
+720 1796(linked)N
+950(in)X
+1042(three)X
+1233(ways.)X
+1468(Using)X
+1689(the)X
+1817(buffer)X
+2043(headers,)X
+2338(they)X
+720 1884(are)N
+851(linked)X
+1083(physically)X
+1444(through)X
+1725(the)X
+1854(LRU)X
+2045(links)X
+2231(and)X
+2378(the)X
+720 1972(over\257ow)N
+1036(links.)X
+1241(Using)X
+1462(the)X
+1590(pages)X
+1803(themselves,)X
+2209(they)X
+2377(are)X
+720 2060(linked)N
+943(logically)X
+1246(through)X
+1518(the)X
+1639(over\257ow)X
+1946(addresses)X
+2276(on)X
+2378(the)X
+720 2148(page.)N
+948(Since)X
+1162(over\257ow)X
+1482(pages)X
+1700(are)X
+1834(accessed)X
+2151(only)X
+2328(after)X
+720 2236(their)N
+904(predecessor)X
+1321(pages,)X
+1560(they)X
+1734(are)X
+1869(removed)X
+2186(from)X
+2378(the)X
+720 2324(buffer)N
+937(pool)X
+1099(when)X
+1293(their)X
+1460(primary)X
+1734(is)X
+1807(removed.)X
+10 f
+720 2412 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 Dt
+2309 3177 MXY
+24 15 Dl
+-8 -15 Dl
+8 -15 Dl
+-24 15 Dl
+52 0 Dl
+789 3160 MXY
+-35 0 Dl
+0 -156 Dl
+1607 0 Dl
+0 173 Dl
+789 3091 MXY
+-24 -15 Dl
+9 15 Dl
+-9 15 Dl
+24 -15 Dl
+-69 0 Dl
+2309 3125 MXY
+104 0 Dl
+0 -155 Dl
+-1693 0 Dl
+0 121 Dl
+927 3160 MXY
+24 15 Dl
+-9 -15 Dl
+9 -15 Dl
+-24 15 Dl
+553 0 Dl
+1618 3177 MXY
+8 27 Dl
+4 -17 Dl
+16 -6 Dl
+-28 -4 Dl
+138 121 Dl
+1895 3315 MXY
+28 3 Dl
+-15 -9 Dl
+1 -18 Dl
+-14 24 Dl
+276 -138 Dl
+3108 MY
+-28 -3 Dl
+15 10 Dl
+-1 17 Dl
+14 -24 Dl
+-276 138 Dl
+1756 3229 MXY
+-8 -27 Dl
+-3 17 Dl
+-16 6 Dl
+27 4 Dl
+-138 -121 Dl
+1480 MX
+-24 -15 Dl
+9 15 Dl
+-9 15 Dl
+24 -15 Dl
+-553 0 Dl
+3 f
+5 s
+1083 3073(LRU)N
+1178(chain)X
+4 Ds
+1402 3851 MXY
+ 1402 3851 lineto
+ 1471 3851 lineto
+ 1471 3920 lineto
+ 1402 3920 lineto
+ 1402 3851 lineto
+closepath 19 1402 3851 1471 3920 Dp
+1445 3747(Over\257ow)N
+1613(Address)X
+1549 3609 MXY
+0 69 Dl
+1756 MX
+-23 -15 Dl
+8 15 Dl
+-8 15 Dl
+23 -15 Dl
+-207 0 Dl
+-1 Ds
+3 Dt
+1756 3419 MXY
+-6 -28 Dl
+-4 17 Dl
+-17 5 Dl
+27 6 Dl
+-138 -138 Dl
+2240 3471 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+1826 3609 MXY
+15 -24 Dl
+-15 9 Dl
+-16 -9 Dl
+16 24 Dl
+0 -138 Dl
+1549 MX
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+858 3471 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+2240 3056 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+1549 3056 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+858 3056 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+1 Dt
+2171 3471 MXY
+ 2171 3471 lineto
+ 2448 3471 lineto
+ 2448 3609 lineto
+ 2171 3609 lineto
+ 2171 3471 lineto
+closepath 19 2171 3471 2448 3609 Dp
+1756 3609 MXY
+ 1756 3609 lineto
+ 2033 3609 lineto
+ 2033 3747 lineto
+ 1756 3747 lineto
+ 1756 3609 lineto
+closepath 3 1756 3609 2033 3747 Dp
+1480 3471 MXY
+ 1480 3471 lineto
+ 1756 3471 lineto
+ 1756 3609 lineto
+ 1480 3609 lineto
+ 1480 3471 lineto
+closepath 19 1480 3471 1756 3609 Dp
+789 MX
+ 789 3471 lineto
+ 1065 3471 lineto
+ 1065 3609 lineto
+ 789 3609 lineto
+ 789 3471 lineto
+closepath 19 789 3471 1065 3609 Dp
+962 3903(Buffer)N
+1083(Header)X
+849 3851 MXY
+ 849 3851 lineto
+ 918 3851 lineto
+ 918 3920 lineto
+ 849 3920 lineto
+ 849 3851 lineto
+closepath 14 849 3851 918 3920 Dp
+1756 3194 MXY
+ 1756 3194 lineto
+ 1895 3194 lineto
+ 1895 3471 lineto
+ 1756 3471 lineto
+ 1756 3194 lineto
+closepath 14 1756 3194 1895 3471 Dp
+2171 3056 MXY
+ 2171 3056 lineto
+ 2309 3056 lineto
+ 2309 3333 lineto
+ 2171 3333 lineto
+ 2171 3056 lineto
+closepath 14 2171 3056 2309 3333 Dp
+1480 MX
+ 1480 3056 lineto
+ 1618 3056 lineto
+ 1618 3333 lineto
+ 1480 3333 lineto
+ 1480 3056 lineto
+closepath 14 1480 3056 1618 3333 Dp
+789 MX
+ 789 3056 lineto
+ 927 3056 lineto
+ 927 3333 lineto
+ 789 3333 lineto
+ 789 3056 lineto
+closepath 14 789 3056 927 3333 Dp
+2780 MY
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+927 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1065 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1203 MX
+0 138 Dl
+139 0 Dl
+0 -138 Dl
+-139 0 Dl
+1342 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1480 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1618 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1756 MX
+0 138 Dl
+139 0 Dl
+0 -138 Dl
+-139 0 Dl
+1895 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+2033 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+2171 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+2309 MX
+0 138 Dl
+139 0 Dl
+0 -138 Dl
+-139 0 Dl
+13 s
+1048 2720(In)N
+1173(Memory)X
+1580(Bucket)X
+1918(Array)X
+867 3584(B0)N
+1558(B5)X
+2223(B10)X
+1788 3722(O1/1)N
+5 s
+1515 3903(Primay)N
+1651(Buffer)X
+4 Ds
+1990 3851 MXY
+ 1990 3851 lineto
+ 2059 3851 lineto
+ 2059 3920 lineto
+ 1990 3920 lineto
+ 1990 3851 lineto
+closepath 3 1990 3851 2059 3920 Dp
+2102 3903(Over\257ow)N
+2270(Buffer)X
+3 Dt
+-1 Ds
+8 s
+720 4184(Figure)N
+922(4:)X
+1 f
+996(Three)X
+1164(primary)X
+1386(pages)X
+1551(\(B0,)X
+1683(B5,)X
+1794(B10\))X
+1942(are)X
+2039(accessed)X
+2281(directly)X
+720 4272(from)N
+862(the)X
+958(bucket)X
+1146(array.)X
+1326(The)X
+1443(one)X
+1553(over\257ow)X
+1798(page)X
+1935(\(O1/1\))X
+2122(is)X
+2182(linked)X
+2359(phy-)X
+720 4360(sically)N
+915(from)X
+1067(its)X
+1155(primary)X
+1384(page's)X
+1577(buffer)X
+1759(header)X
+1955(as)X
+2035(well)X
+2172(as)X
+2252(logically)X
+720 4448(from)N
+860(its)X
+937(predecessor)X
+1253(page)X
+1389(buffer)X
+1560(\(B5\).)X
+10 s
+10 f
+720 4624 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+1191 4954(Table)N
+1406(Parameterization)X
+1 f
+892 5086(When)N
+1107(a)X
+1166(hash)X
+1336(table)X
+1515(is)X
+1590(created,)X
+1865(the)X
+1985(bucket)X
+2221(size,)X
+2388(\256ll)X
+720 5174(factor,)N
+953(initial)X
+1164(number)X
+1434(of)X
+1526(elements,)X
+1856(number)X
+2125(of)X
+2216(bytes)X
+2409(of)X
+720 5262(main)N
+919(memory)X
+1225(used)X
+1411(for)X
+1543(caching,)X
+1851(and)X
+2005(a)X
+2079(user-de\256ned)X
+720 5350(hash)N
+892(function)X
+1184(may)X
+1347(be)X
+1448(speci\256ed.)X
+1797(The)X
+1946(bucket)X
+2184(size)X
+2333(\(and)X
+720 5438(page)N
+906(size)X
+1064(for)X
+1191(over\257ow)X
+1509(pages\))X
+1752(defaults)X
+2039(to)X
+2134(256)X
+2287(bytes.)X
+720 5526(For)N
+858(tables)X
+1072(with)X
+1241(large)X
+1429(data)X
+1590(items,)X
+1810(it)X
+1881(may)X
+2046(be)X
+2149(preferable)X
+720 5614(to)N
+803(increase)X
+1088(the)X
+1207(page)X
+1380(size,)X
+1545(and,)X
+1701(conversely,)X
+2089(applications)X
+720 5702(storing)N
+1002(small)X
+1235(items)X
+1467(exclusively)X
+1891(in)X
+2012(memory)X
+2338(may)X
+2706 538(bene\256t)N
+2966(from)X
+3164(a)X
+3242(smaller)X
+3520(bucket)X
+3776(size.)X
+3983(A)X
+4082(bucket)X
+4337(size)X
+2706 626(smaller)N
+2962(than)X
+3120(64)X
+3220(bytes)X
+3409(is)X
+3482(not)X
+3604(recommended.)X
+2878 740(The)N
+3031(\256ll)X
+3147(factor)X
+3363(indicates)X
+3676(a)X
+3740(desired)X
+4000(density)X
+4258(within)X
+2706 828(the)N
+2833(hash)X
+3009(table.)X
+3234(It)X
+3312(is)X
+3394(an)X
+3499(approximation)X
+3995(of)X
+4091(the)X
+4217(number)X
+2706 916(of)N
+2815(keys)X
+3004(allowed)X
+3300(to)X
+3404(accumulate)X
+3811(in)X
+3914(any)X
+4071(one)X
+4228(bucket,)X
+2706 1004(determining)N
+3119(when)X
+3319(the)X
+3442(hash)X
+3614(table)X
+3795(grows.)X
+4056(Its)X
+4161(default)X
+4409(is)X
+2706 1092(eight.)N
+2953(If)X
+3054(the)X
+3199(user)X
+3380(knows)X
+3636(the)X
+3781(average)X
+4079(size)X
+4251(of)X
+4364(the)X
+2706 1180(key/data)N
+3008(pairs)X
+3194(being)X
+3402(stored)X
+3627(in)X
+3718(the)X
+3845(table,)X
+4050(near)X
+4218(optimal)X
+2706 1268(bucket)N
+2943(sizes)X
+3122(and)X
+3261(\256ll)X
+3372(factors)X
+3614(may)X
+3775(be)X
+3874(selected)X
+4155(by)X
+4257(apply-)X
+2706 1356(ing)N
+2828(the)X
+2946(equation:)X
+0 f
+8 s
+2706 1655(\(1\))N
+2994 -0.3938(\(\(average_pair_length)AX
+3830(+)X
+3906(4\))X
+4020(*)X
+3032 1743(ffactor\))N
+3374(>=)X
+3488(bsize)X
+1 f
+10 s
+2706 2042(For)N
+2859(highly)X
+3104(time)X
+3287(critical)X
+3551(applications,)X
+3999(experimenting)X
+2706 2130(with)N
+2919(different)X
+3266(bucket)X
+3550(sizes)X
+3776(and)X
+3962(\256ll)X
+4120(factors)X
+4409(is)X
+2706 2218(encouraged.)N
+2878 2332(Figures)N
+3144(5a,b,)X
+3326(and)X
+3468(c)X
+3530(illustrate)X
+3836(the)X
+3960(effects)X
+4200(of)X
+4292(vary-)X
+2706 2420(ing)N
+2841(page)X
+3026(sizes)X
+3215(and)X
+3363(\256ll)X
+3483(factors)X
+3734(for)X
+3860(the)X
+3990(same)X
+4187(data)X
+4353(set.)X
+2706 2508(The)N
+2864(data)X
+3031(set)X
+3152(consisted)X
+3482(of)X
+3581(24474)X
+3813(keys)X
+3992(taken)X
+4198(from)X
+4386(an)X
+2706 2596(online)N
+2931(dictionary.)X
+3301(The)X
+3451(data)X
+3609(value)X
+3807(for)X
+3925(each)X
+4097(key)X
+4237(was)X
+4386(an)X
+2706 2684(ASCII)N
+2938(string)X
+3143(for)X
+3260(an)X
+3359(integer)X
+3605(from)X
+3784(1)X
+3847(to)X
+3931(24474)X
+4153(inclusive.)X
+2706 2772(The)N
+2867(test)X
+3013(run)X
+3155(consisted)X
+3488(of)X
+3590(creating)X
+3884(a)X
+3955(new)X
+4124(hash)X
+4306(table)X
+2706 2860(\(where)N
+2966(the)X
+3100(ultimate)X
+3398(size)X
+3559(of)X
+3662(the)X
+3796(table)X
+3987(was)X
+4147(known)X
+4400(in)X
+2706 2948(advance\),)N
+3054(entering)X
+3354(each)X
+3539(key/data)X
+3848(pair)X
+4010(into)X
+4171(the)X
+4306(table)X
+2706 3036(and)N
+2849(then)X
+3014(retrieving)X
+3353(each)X
+3528(key/data)X
+3827(pair)X
+3979(from)X
+4162(the)X
+4286(table.)X
+2706 3124(Each)N
+2898(of)X
+2996(the)X
+3125(graphs)X
+3369(shows)X
+3599(the)X
+3727(timings)X
+3996(resulting)X
+4306(from)X
+2706 3212(varying)N
+2973(the)X
+3093(pagesize)X
+3392(from)X
+3570(128)X
+3712(bytes)X
+3903(to)X
+3986(1M)X
+4118(and)X
+4255(the)X
+4374(\256ll)X
+2706 3300(factor)N
+2929(from)X
+3120(1)X
+3195(to)X
+3292(128.)X
+3486(For)X
+3631(each)X
+3813(run,)X
+3974(the)X
+4106(buffer)X
+4337(size)X
+2706 3388(was)N
+2874(set)X
+3006(at)X
+3106(1M.)X
+3299(The)X
+3466(tests)X
+3650(were)X
+3849(all)X
+3971(run)X
+4120(on)X
+4242(an)X
+4360(HP)X
+2706 3476(9000/370)N
+3077(\(33.3)X
+3312(Mhz)X
+3527(MC68030\),)X
+3966(with)X
+4176(16M)X
+4395(of)X
+2706 3564(memory,)N
+3042(64K)X
+3228(physically)X
+3605(addressed)X
+3970(cache,)X
+4222(and)X
+4386(an)X
+2706 3652(HP7959S)N
+3055(disk)X
+3231(drive,)X
+3459(running)X
+3751(4.3BSD-Reno)X
+4244(single-)X
+2706 3740(user.)N
+2878 3854(Both)N
+3066(system)X
+3321(time)X
+3496(\(Figure)X
+3764(5a\))X
+3899(and)X
+4047(elapsed)X
+4320(time)X
+2706 3942(\(Figure)N
+2966(5b\))X
+3097(show)X
+3290(that)X
+3434(for)X
+3552(all)X
+3655(bucket)X
+3892(sizes,)X
+4091(the)X
+4212(greatest)X
+2706 4030(performance)N
+3137(gains)X
+3329(are)X
+3451(made)X
+3648(by)X
+3751(increasing)X
+4104(the)X
+4225(\256ll)X
+4336(fac-)X
+2706 4118(tor)N
+2822(until)X
+2995(equation)X
+3298(1)X
+3365(is)X
+3445(satis\256ed.)X
+3774(The)X
+3925(user)X
+4085(time)X
+4253(shown)X
+2706 4206(in)N
+2791(Figure)X
+3023(5c)X
+3122(gives)X
+3314(a)X
+3373(more)X
+3561(detailed)X
+3838(picture)X
+4083(of)X
+4172(how)X
+4332(per-)X
+2706 4294(formance)N
+3054(varies.)X
+3330(The)X
+3499(smaller)X
+3778(bucket)X
+4035(sizes)X
+4234(require)X
+2706 4382(fewer)N
+2921(keys)X
+3099(per)X
+3233(page)X
+3416(to)X
+3509(satisfy)X
+3749(equation)X
+4056(1)X
+4127(and)X
+4274(there-)X
+2706 4470(fore)N
+2860(incur)X
+3049(fewer)X
+3257(collisions.)X
+3607(However,)X
+3946(when)X
+4144(the)X
+4265(buffer)X
+2706 4558(pool)N
+2884(size)X
+3045(is)X
+3134(\256xed,)X
+3349(smaller)X
+3620(pages)X
+3838(imply)X
+4059(more)X
+4259(pages.)X
+2706 4646(An)N
+2830(increased)X
+3160(number)X
+3430(of)X
+3522(pages)X
+3730(means)X
+3960(more)X
+2 f
+4150(malloc\(3\))X
+1 f
+2706 4734(calls)N
+2879(and)X
+3021(more)X
+3212(overhead)X
+3533(in)X
+3621(the)X
+3745(hash)X
+3918(package's)X
+4265(buffer)X
+2706 4822(manager)N
+3003(to)X
+3085(manage)X
+3355(the)X
+3473(additional)X
+3813(pages.)X
+2878 4936(The)N
+3028(tradeoff)X
+3308(works)X
+3529(out)X
+3655(most)X
+3834(favorably)X
+4166(when)X
+4364(the)X
+2706 5024(page)N
+2886(size)X
+3039(is)X
+3120(256)X
+3268(and)X
+3412(the)X
+3538(\256ll)X
+3654(factor)X
+3870(is)X
+3950(8.)X
+4057(Similar)X
+4319(con-)X
+2706 5112(clusions)N
+3009(were)X
+3207(obtained)X
+3524(if)X
+3614(the)X
+3753(test)X
+3905(was)X
+4071(run)X
+4218(without)X
+2706 5200(knowing)N
+3007(the)X
+3126(\256nal)X
+3289(table)X
+3466(size)X
+3612(in)X
+3695(advance.)X
+4020(If)X
+4095(the)X
+4214(\256le)X
+4337(was)X
+2706 5288(closed)N
+2942(and)X
+3088(written)X
+3345(to)X
+3437(disk,)X
+3620(the)X
+3748(conclusions)X
+4156(were)X
+4343(still)X
+2706 5376(the)N
+2832(same.)X
+3065(However,)X
+3408(rereading)X
+3740(the)X
+3865(\256le)X
+3994(from)X
+4177(disk)X
+4337(was)X
+2706 5464(slightly)N
+2983(faster)X
+3199(if)X
+3285(a)X
+3358(larger)X
+3583(bucket)X
+3834(size)X
+3996(and)X
+4149(\256ll)X
+4274(factor)X
+2706 5552(were)N
+2898(used)X
+3079(\(1K)X
+3238(bucket)X
+3486(size)X
+3645(and)X
+3795(32)X
+3909(\256ll)X
+4031(factor\).)X
+4320(This)X
+2706 5640(follows)N
+2987(intuitively)X
+3356(from)X
+3553(the)X
+3691(improved)X
+4038(ef\256ciency)X
+4395(of)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(7)X
+
+8 p
+%%Page: 8 8
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+432 538(performing)N
+830(1K)X
+965(reads)X
+1172(from)X
+1365(the)X
+1500(disk)X
+1670(rather)X
+1894(than)X
+2068(256)X
+432 626(byte)N
+609(reads.)X
+857(In)X
+962(general,)X
+1257(performance)X
+1702(for)X
+1834(disk)X
+2005(based)X
+432 714(tables)N
+639(is)X
+712(best)X
+861(when)X
+1055(the)X
+1173(page)X
+1345(size)X
+1490(is)X
+1563(approximately)X
+2046(1K.)X
+10 f
+432 802 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+619 2380 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+629 2437 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+648 2504 MXY
+-12 25 Dl
+24 0 Dl
+-12 -25 Dl
+686 2515 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+762 2516 MXY
+-12 24 Dl
+25 0 Dl
+-13 -24 Dl
+916 2515 MXY
+-13 24 Dl
+25 0 Dl
+-12 -24 Dl
+1222 2516 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+1834 2515 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+1 Dt
+619 2392 MXY
+10 57 Dl
+19 67 Dl
+38 11 Dl
+76 1 Dl
+154 -1 Dl
+306 1 Dl
+612 -1 Dl
+8 s
+1 f
+1628 2522(128)N
+3 Dt
+607 2245 MXY
+24 Dc
+617 2375 MXY
+23 Dc
+635 2442 MXY
+24 Dc
+674 2525 MXY
+23 Dc
+750 2529 MXY
+24 Dc
+904 2527 MXY
+23 Dc
+1210 MX
+23 Dc
+1822 2528 MXY
+23 Dc
+20 Ds
+1 Dt
+619 2245 MXY
+10 130 Dl
+19 67 Dl
+38 83 Dl
+76 4 Dl
+154 -2 Dl
+306 0 Dl
+612 1 Dl
+678 2482(256)N
+-1 Ds
+3 Dt
+619 2127 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+629 2191 MXY
+0 25 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+648 2334 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+686 2409 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+762 2516 MXY
+0 25 Dl
+0 -12 Dl
+13 0 Dl
+-25 0 Dl
+916 2516 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-25 0 Dl
+1222 2515 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1834 2515 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+5 Dt
+619 2139 MXY
+10 65 Dl
+19 142 Dl
+38 75 Dl
+76 108 Dl
+154 -1 Dl
+306 -1 Dl
+612 0 Dl
+694 2401(512)N
+3 Dt
+631 2064 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+641 2077 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+660 2132 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+698 2292 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+775 2382 MXY
+-25 24 Dl
+12 -12 Dl
+-12 -12 Dl
+25 24 Dl
+928 2516 MXY
+-25 24 Dl
+13 -12 Dl
+-13 -12 Dl
+25 24 Dl
+1234 2516 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+1846 2516 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+16 Ds
+1 Dt
+619 2076 MXY
+10 14 Dl
+19 54 Dl
+38 160 Dl
+76 90 Dl
+154 134 Dl
+306 1 Dl
+612 -1 Dl
+694 2257(1024)N
+-1 Ds
+3 Dt
+619 1877 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+629 1855 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+648 1838 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+686 1860 MXY
+12 -25 Dl
+-24 0 Dl
+12 25 Dl
+762 1923 MXY
+13 -24 Dl
+-25 0 Dl
+12 24 Dl
+916 2087 MXY
+12 -24 Dl
+-25 0 Dl
+13 24 Dl
+1222 2256 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+1834 2541 MXY
+12 -25 Dl
+-24 0 Dl
+12 25 Dl
+619 1865 MXY
+10 -22 Dl
+19 -17 Dl
+38 21 Dl
+76 64 Dl
+154 164 Dl
+306 169 Dl
+612 285 Dl
+1645 2427(4096)N
+619 1243 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+629 1196 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+648 1146 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+686 1174 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+762 1249 MXY
+0 24 Dl
+0 -12 Dl
+13 0 Dl
+-25 0 Dl
+916 1371 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-25 0 Dl
+1222 1680 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1834 1999 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+619 1255 MXY
+10 -47 Dl
+19 -50 Dl
+38 28 Dl
+76 75 Dl
+154 122 Dl
+306 309 Dl
+612 319 Dl
+1741 1934(8192)N
+5 Dt
+609 2531 MXY
+1225 0 Dl
+609 MX
+0 -1553 Dl
+2531 MY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+593 2625(0)N
+-1 Ds
+5 Dt
+916 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+884 2625(32)N
+-1 Ds
+5 Dt
+1222 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+1190 2625(64)N
+-1 Ds
+5 Dt
+1528 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+1496 2625(96)N
+-1 Ds
+5 Dt
+1834 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+1786 2625(128)N
+-1 Ds
+5 Dt
+609 2531 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+545 2558(0)N
+-1 Ds
+5 Dt
+609 2013 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+481 2040(100)N
+-1 Ds
+5 Dt
+609 1496 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+481 1523(200)N
+-1 Ds
+5 Dt
+609 978 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+481 1005(300)N
+1088 2724(Fill)N
+1194(Factor)X
+422 1611(S)N
+426 1667(e)N
+426 1724(c)N
+424 1780(o)N
+424 1837(n)N
+424 1893(d)N
+428 1949(s)N
+3 Dt
+-1 Ds
+3 f
+432 2882(Figure)N
+636(5a:)X
+1 f
+744(System)X
+956(Time)X
+1113(for)X
+1209(dictionary)X
+1490(data)X
+1618(set)X
+1711(with)X
+1847(1M)X
+1958(of)X
+2033(buffer)X
+432 2970(space)N
+594(and)X
+707(varying)X
+923(bucket)X
+1114(sizes)X
+1259(and)X
+1372(\256ll)X
+1465(factors.)X
+1675(Each)X
+1823(line)X
+1940(is)X
+2004(labeled)X
+432 3058(with)N
+562(its)X
+639(bucket)X
+825(size.)X
+10 s
+10 f
+432 3234 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+8 s
+1 f
+428 4381(s)N
+424 4325(d)N
+424 4269(n)N
+424 4212(o)N
+426 4156(c)N
+426 4099(e)N
+422 4043(S)N
+1116 5156(Fill)N
+1222(Factor)X
+506 3437(3200)N
+4 Ds
+1 Dt
+666 3410 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+506 3825(2400)N
+4 Ds
+1 Dt
+666 3799 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+506 4214(1600)N
+4 Ds
+1 Dt
+666 4186 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+538 4602(800)N
+4 Ds
+1 Dt
+666 4575 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+602 4990(0)N
+4 Ds
+1 Dt
+666 4963 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+1786 5057(128)N
+4 Ds
+1 Dt
+1834 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+1510 5057(96)N
+4 Ds
+1 Dt
+1542 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+1218 5057(64)N
+4 Ds
+1 Dt
+1250 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+926 5057(32)N
+4 Ds
+1 Dt
+958 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+650 5057(0)N
+4 Ds
+1 Dt
+666 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+4963 MY
+0 -1553 Dl
+4963 MY
+1168 0 Dl
+1741 4752(8192)N
+3 Dt
+675 3732 MXY
+9 -172 Dl
+18 -118 Dl
+37 128 Dl
+73 -121 Dl
+146 623 Dl
+292 497 Dl
+584 245 Dl
+4802 MY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1250 4557 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+958 4060 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+812 3437 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+739 3558 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+702 3430 MXY
+0 25 Dl
+0 -13 Dl
+13 0 Dl
+-25 0 Dl
+684 3548 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+675 3720 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1637 4912(4096)N
+675 4307 MXY
+9 -58 Dl
+18 30 Dl
+37 89 Dl
+73 144 Dl
+146 235 Dl
+292 122 Dl
+584 89 Dl
+4970 MY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+1250 4881 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+958 4759 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+812 4524 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+739 4380 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+702 4291 MXY
+13 -24 Dl
+-25 0 Dl
+12 24 Dl
+684 4261 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+675 4319 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+734 4662(1024)N
+16 Ds
+1 Dt
+675 4352 MXY
+9 60 Dl
+18 134 Dl
+37 266 Dl
+73 117 Dl
+146 30 Dl
+292 0 Dl
+584 -1 Dl
+-1 Ds
+3 Dt
+1846 4946 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+1262 4946 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+970 4947 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+824 4917 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+751 4800 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+715 4534 MXY
+-25 25 Dl
+12 -13 Dl
+-12 -12 Dl
+25 25 Dl
+696 4400 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+687 4339 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+718 4792(512)N
+5 Dt
+675 4422 MXY
+9 137 Dl
+18 278 Dl
+37 105 Dl
+73 18 Dl
+146 -1 Dl
+292 0 Dl
+584 -1 Dl
+3 Dt
+4946 MY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1250 4946 MXY
+0 25 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+958 4947 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+812 4948 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+739 4930 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+702 4824 MXY
+0 25 Dl
+0 -12 Dl
+13 0 Dl
+-25 0 Dl
+684 4547 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+675 4410 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+750 4921(256)N
+20 Ds
+1 Dt
+675 4597 MXY
+9 246 Dl
+18 106 Dl
+37 10 Dl
+73 0 Dl
+146 0 Dl
+292 0 Dl
+584 -1 Dl
+-1 Ds
+3 Dt
+1822 MX
+23 Dc
+1238 4959 MXY
+23 Dc
+946 MX
+23 Dc
+800 MX
+23 Dc
+727 MX
+23 Dc
+691 4949 MXY
+23 Dc
+672 4843 MXY
+24 Dc
+663 4597 MXY
+24 Dc
+1395 4961(128)N
+1 Dt
+675 4855 MXY
+9 93 Dl
+18 10 Dl
+37 1 Dl
+73 0 Dl
+146 -1 Dl
+292 0 Dl
+584 0 Dl
+3 Dt
+4946 MY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+1250 MX
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+958 MX
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+812 MX
+-12 25 Dl
+24 0 Dl
+-12 -25 Dl
+739 4947 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+702 4946 MXY
+-12 24 Dl
+25 0 Dl
+-13 -24 Dl
+684 4936 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+675 4843 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+3 Dt
+-1 Ds
+3 f
+432 5314(Figure)N
+634(5b:)X
+1 f
+744(Elapsed)X
+967(Time)X
+1123(for)X
+1218(dictionary)X
+1498(data)X
+1625(set)X
+1717(with)X
+1851(1M)X
+1960(of)X
+2033(buffer)X
+432 5402(space)N
+593(and)X
+705(varying)X
+920(bucket)X
+1110(sizes)X
+1254(and)X
+1366(\256ll)X
+1457(factors.)X
+1681(Each)X
+1827(line)X
+1942(is)X
+2004(labeled)X
+432 5490(with)N
+562(its)X
+639(bucket)X
+825(size.)X
+10 s
+2590 538(If)N
+2677(an)X
+2785(approximation)X
+3284(of)X
+3383(the)X
+3513(number)X
+3790(of)X
+3889(elements)X
+2418 626(ultimately)N
+2773(to)X
+2866(be)X
+2973(stored)X
+3200(in)X
+3293(the)X
+3422(hash)X
+3599(table)X
+3785(is)X
+3868(known)X
+4116(at)X
+2418 714(the)N
+2564(time)X
+2754(of)X
+2869(creation,)X
+3196(the)X
+3342(hash)X
+3536(package)X
+3847(takes)X
+4059(this)X
+2418 802(number)N
+2688(as)X
+2779(a)X
+2839(parameter)X
+3185(and)X
+3325(uses)X
+3487(it)X
+3555(to)X
+3641(hash)X
+3812(entries)X
+4050(into)X
+2418 890(the)N
+2541(full)X
+2677(sized)X
+2867(table)X
+3048(rather)X
+3261(than)X
+3424(growing)X
+3716(the)X
+3838(table)X
+4018(from)X
+2418 978(a)N
+2477(single)X
+2691(bucket.)X
+2968(If)X
+3044(this)X
+3181(number)X
+3448(is)X
+3523(not)X
+3647(known,)X
+3907(the)X
+4027(hash)X
+2418 1066(table)N
+2632(starts)X
+2859(with)X
+3059(a)X
+3153(single)X
+3402(bucket)X
+3674(and)X
+3848(gracefully)X
+2418 1154(expands)N
+2707(as)X
+2800(elements)X
+3111(are)X
+3236(added,)X
+3474(although)X
+3780(a)X
+3842(slight)X
+4044(per-)X
+2418 1242(formance)N
+2747(degradation)X
+3151(may)X
+3313(be)X
+3413(noticed.)X
+3713(Figure)X
+3946(6)X
+4010(illus-)X
+2418 1330(trates)N
+2625(the)X
+2756(difference)X
+3116(in)X
+3211(performance)X
+3651(between)X
+3952(storing)X
+2418 1418(keys)N
+2588(in)X
+2673(a)X
+2732(\256le)X
+2857(when)X
+3054(the)X
+3174(ultimate)X
+3458(size)X
+3605(is)X
+3680(known)X
+3920(\(the)X
+4067(left)X
+2418 1506(bars)N
+2581(in)X
+2672(each)X
+2849(set\),)X
+3014(compared)X
+3360(to)X
+3450(building)X
+3744(the)X
+3870(\256le)X
+4000(when)X
+2418 1594(the)N
+2550(ultimate)X
+2846(size)X
+3005(is)X
+3091(unknown)X
+3422(\(the)X
+3580(right)X
+3764(bars)X
+3931(in)X
+4026(each)X
+2418 1682(set\).)N
+2609(Once)X
+2814(the)X
+2947(\256ll)X
+3069(factor)X
+3291(is)X
+3378(suf\256ciently)X
+3772(high)X
+3948(for)X
+4076(the)X
+2418 1770(page)N
+2596(size)X
+2747(\(8\),)X
+2887(growing)X
+3180(the)X
+3304(table)X
+3486(dynamically)X
+3908(does)X
+4081(lit-)X
+2418 1858(tle)N
+2518(to)X
+2600(degrade)X
+2875(performance.)X
+10 f
+2418 1946 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+9 s
+1 f
+2413 3238(s)N
+2409 3173(d)N
+2409 3108(n)N
+2409 3043(o)N
+2411 2979(c)N
+2411 2914(e)N
+2407 2849(S)N
+3143 4129(Fill)N
+3261(Factor)X
+2448 2152(15)N
+4 Ds
+1 Dt
+2557 2122 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+2448 2747(10)N
+4 Ds
+1 Dt
+2557 2717 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+2484 3343(5)N
+4 Ds
+1 Dt
+2557 3313 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+2484 3938(0)N
+4 Ds
+1 Dt
+2557 3908 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+3976 4015(128)N
+4 Ds
+1 Dt
+4030 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+3626 4015(96)N
+4 Ds
+1 Dt
+3662 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+3258 4015(64)N
+4 Ds
+1 Dt
+3294 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+2889 4015(32)N
+4 Ds
+1 Dt
+2925 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+2539 4015(0)N
+4 Ds
+1 Dt
+2557 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+3908 MY
+0 -1786 Dl
+3908 MY
+1473 0 Dl
+4053 2378(8192)N
+3 Dt
+2569 2277 MXY
+11 0 Dl
+23 48 Dl
+46 -167 Dl
+92 35 Dl
+184 12 Dl
+369 143 Dl
+736 0 Dl
+2334 MY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+3294 2334 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+2925 2192 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2741 2180 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2649 2144 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2603 2311 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-28 0 Dl
+2580 2263 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2569 2263 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+4053 2591(4096)N
+2569 2348 MXY
+11 -11 Dl
+23 -96 Dl
+46 71 Dl
+92 72 Dl
+184 226 Dl
+369 48 Dl
+736 -60 Dl
+2612 MY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+3294 2672 MXY
+13 -28 Dl
+-27 0 Dl
+14 28 Dl
+2925 2624 MXY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+2741 2398 MXY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+2649 2326 MXY
+14 -27 Dl
+-28 0 Dl
+14 27 Dl
+2603 2255 MXY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+2580 2350 MXY
+14 -27 Dl
+-28 0 Dl
+14 27 Dl
+2569 2362 MXY
+13 -28 Dl
+-27 0 Dl
+14 28 Dl
+4053 2681(1024)N
+16 Ds
+1 Dt
+2569 2300 MXY
+11 48 Dl
+23 96 Dl
+46 95 Dl
+92 274 Dl
+184 202 Dl
+369 -155 Dl
+736 -190 Dl
+-1 Ds
+3 Dt
+4044 2656 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+3307 2846 MXY
+-27 28 Dl
+14 -14 Dl
+-14 -14 Dl
+27 28 Dl
+2939 3001 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2755 2799 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2663 2525 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2617 2430 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2594 2334 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2582 2287 MXY
+-27 27 Dl
+14 -14 Dl
+-14 -13 Dl
+27 27 Dl
+4053 2851(512)N
+5 Dt
+2569 2372 MXY
+11 -24 Dl
+23 405 Dl
+46 83 Dl
+92 227 Dl
+184 -72 Dl
+369 -119 Dl
+736 -107 Dl
+3 Dt
+2751 MY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+3294 2858 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+2925 2977 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2741 3049 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-28 0 Dl
+2649 2823 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2603 2739 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2580 2334 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2569 2358 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+4053 2795(256)N
+20 Ds
+1 Dt
+2569 2456 MXY
+11 285 Dl
+23 95 Dl
+46 251 Dl
+92 -60 Dl
+184 -84 Dl
+369 -107 Dl
+736 -71 Dl
+-1 Ds
+3 Dt
+4016 MX
+27 Dc
+3280 2836 MXY
+27 Dc
+2912 2943 MXY
+27 Dc
+2728 3027 MXY
+27 Dc
+2635 3087 MXY
+28 Dc
+2589 2836 MXY
+28 Dc
+2566 2741 MXY
+27 Dc
+2554 2456 MXY
+28 Dc
+4053 2741(128)N
+1 Dt
+2569 2729 MXY
+11 203 Dl
+23 131 Dl
+46 -60 Dl
+92 -119 Dl
+184 -60 Dl
+369 -83 Dl
+736 -12 Dl
+3 Dt
+2716 MY
+-14 27 Dl
+28 0 Dl
+-14 -27 Dl
+3294 2727 MXY
+-14 28 Dl
+27 0 Dl
+-13 -28 Dl
+2925 2811 MXY
+-14 27 Dl
+28 0 Dl
+-14 -27 Dl
+2741 2870 MXY
+-14 28 Dl
+28 0 Dl
+-14 -28 Dl
+2649 2989 MXY
+-14 28 Dl
+28 0 Dl
+-14 -28 Dl
+2603 3049 MXY
+-14 27 Dl
+28 0 Dl
+-14 -27 Dl
+2580 2918 MXY
+-14 28 Dl
+28 0 Dl
+-14 -28 Dl
+2569 2716 MXY
+-14 27 Dl
+27 0 Dl
+-13 -27 Dl
+3 Dt
+-1 Ds
+3 f
+8 s
+2418 4286(Figure)N
+2628(5c:)X
+1 f
+2738(User)X
+2887(Time)X
+3051(for)X
+3154(dictionary)X
+3442(data)X
+3577(set)X
+3677(with)X
+3820(1M)X
+3938(of)X
+4019(buffer)X
+2418 4374(space)N
+2579(and)X
+2691(varying)X
+2906(bucket)X
+3096(sizes)X
+3240(and)X
+3352(\256ll)X
+3443(factors.)X
+3667(Each)X
+3813(line)X
+3928(is)X
+3990(labeled)X
+2418 4462(with)N
+2548(its)X
+2625(bucket)X
+2811(size.)X
+10 s
+10 f
+2418 4638 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+2590 4840(Since)N
+2796(no)X
+2904(known)X
+3150(hash)X
+3325(function)X
+3620(performs)X
+3938(equally)X
+2418 4928(well)N
+2589(on)X
+2702(all)X
+2815(possible)X
+3110(data,)X
+3297(the)X
+3428(user)X
+3595(may)X
+3766(\256nd)X
+3923(that)X
+4076(the)X
+2418 5016(built-in)N
+2678(hash)X
+2849(function)X
+3140(does)X
+3311(poorly)X
+3544(on)X
+3648(a)X
+3708(particular)X
+4040(data)X
+2418 5104(set.)N
+2548(In)X
+2636(this)X
+2771(case,)X
+2950(a)X
+3006(hash)X
+3173(function,)X
+3480(taking)X
+3700(two)X
+3840(arguments)X
+2418 5192(\(a)N
+2507(pointer)X
+2760(to)X
+2848(a)X
+2910(byte)X
+3074(string)X
+3282(and)X
+3424(a)X
+3486(length\))X
+3739(and)X
+3880(returning)X
+2418 5280(an)N
+2517(unsigned)X
+2829(long)X
+2993(to)X
+3077(be)X
+3175(used)X
+3344(as)X
+3433(the)X
+3553(hash)X
+3722(value,)X
+3938(may)X
+4098(be)X
+2418 5368(speci\256ed)N
+2731(at)X
+2817(hash)X
+2992(table)X
+3176(creation)X
+3463(time.)X
+3673(When)X
+3893(an)X
+3996(exist-)X
+2418 5456(ing)N
+2570(hash)X
+2767(table)X
+2973(is)X
+3076(opened)X
+3358(and)X
+3524(a)X
+3609(hash)X
+3805(function)X
+4121(is)X
+2418 5544(speci\256ed,)N
+2752(the)X
+2879(hash)X
+3054(package)X
+3346(will)X
+3498(try)X
+3615(to)X
+3705(determine)X
+4054(that)X
+2418 5632(the)N
+2546(hash)X
+2723(function)X
+3020(supplied)X
+3321(is)X
+3404(the)X
+3532(one)X
+3678(with)X
+3850(which)X
+4076(the)X
+2418 5720(table)N
+2630(was)X
+2811(created.)X
+3139(There)X
+3382(are)X
+3536(a)X
+3627(variety)X
+3905(of)X
+4027(hash)X
+3 f
+432 5960(8)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+9 p
+%%Page: 9 9
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(functions)N
+1065(provided)X
+1397(with)X
+1586(the)X
+1731(package.)X
+2082(The)X
+2253(default)X
+720 626(function)N
+1014(for)X
+1135(the)X
+1260(package)X
+1551(is)X
+1631(the)X
+1755(one)X
+1897(which)X
+2119(offered)X
+2378(the)X
+720 714(best)N
+875(performance)X
+1308(in)X
+1396(terms)X
+1600(of)X
+1693(cycles)X
+1920(executed)X
+2232(per)X
+2360(call)X
+720 802(\(it)N
+827(did)X
+965(not)X
+1103(produce)X
+1398(the)X
+1531(fewest)X
+1776(collisions)X
+2117(although)X
+2432(it)X
+720 890(was)N
+866(within)X
+1091(a)X
+1148(small)X
+1341(percentage)X
+1710(of)X
+1797(the)X
+1915(function)X
+2202(that)X
+2342(pro-)X
+720 978(duced)N
+947(the)X
+1080(fewest)X
+1324(collisions\).)X
+1731(Again,)X
+1981(in)X
+2077(time)X
+2253(critical)X
+720 1066(applications,)N
+1152(users)X
+1342(are)X
+1466(encouraged)X
+1862(to)X
+1949(experiment)X
+2334(with)X
+720 1154(a)N
+783(variety)X
+1032(of)X
+1125(hash)X
+1298(functions)X
+1622(to)X
+1710(achieve)X
+1982(optimal)X
+2252(perfor-)X
+720 1242(mance.)N
+10 f
+720 1330 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+7 s
+1038 2925(Full)N
+1149(size)X
+1251(table)X
+1384(\(left\))X
+1547 2718(Fill)N
+1643(Factor)X
+2268 2662(64)N
+1964(32)X
+1674(16)X
+1384(8)X
+1093(4)X
+4 Ds
+1 Dt
+900 2280 MXY
+1548 0 Dl
+900 1879 MXY
+1548 0 Dl
+900 1506 MXY
+1548 0 Dl
+1563 2902 MXY
+111 0 Dl
+-1 Ds
+900 MX
+110 0 Dl
+1425 2828(System)N
+983(User)X
+1895 2778 MXY
+ 1895 2778 lineto
+ 1950 2778 lineto
+ 1950 2833 lineto
+ 1895 2833 lineto
+ 1895 2778 lineto
+closepath 21 1895 2778 1950 2833 Dp
+1342 MX
+ 1342 2778 lineto
+ 1397 2778 lineto
+ 1397 2833 lineto
+ 1342 2833 lineto
+ 1342 2778 lineto
+closepath 14 1342 2778 1397 2833 Dp
+900 MX
+ 900 2778 lineto
+ 955 2778 lineto
+ 955 2833 lineto
+ 900 2833 lineto
+ 900 2778 lineto
+closepath 3 900 2778 955 2833 Dp
+5 Dt
+2283 2211 MXY
+96 0 Dl
+1992 MX
+97 0 Dl
+1702 MX
+97 0 Dl
+1411 2252 MXY
+97 0 Dl
+4 Ds
+1 Dt
+2283 2211 MXY
+ 2283 2211 lineto
+ 2379 2211 lineto
+ 2379 2252 lineto
+ 2283 2252 lineto
+ 2283 2211 lineto
+closepath 14 2283 2211 2379 2252 Dp
+1992 MX
+ 1992 2211 lineto
+ 2089 2211 lineto
+ 2089 2252 lineto
+ 1992 2252 lineto
+ 1992 2211 lineto
+closepath 14 1992 2211 2089 2252 Dp
+1702 MX
+ 1702 2211 lineto
+ 1799 2211 lineto
+ 1799 2252 lineto
+ 1702 2252 lineto
+ 1702 2211 lineto
+closepath 14 1702 2211 1799 2252 Dp
+1411 2252 MXY
+ 1411 2252 lineto
+ 1508 2252 lineto
+ 1508 2294 lineto
+ 1411 2294 lineto
+ 1411 2252 lineto
+closepath 14 1411 2252 1508 2294 Dp
+2283 MX
+ 2283 2252 lineto
+ 2379 2252 lineto
+ 2379 2612 lineto
+ 2283 2612 lineto
+ 2283 2252 lineto
+closepath 3 2283 2252 2379 2612 Dp
+1992 MX
+ 1992 2252 lineto
+ 2089 2252 lineto
+ 2089 2612 lineto
+ 1992 2612 lineto
+ 1992 2252 lineto
+closepath 3 1992 2252 2089 2612 Dp
+1702 MX
+ 1702 2252 lineto
+ 1799 2252 lineto
+ 1799 2612 lineto
+ 1702 2612 lineto
+ 1702 2252 lineto
+closepath 3 1702 2252 1799 2612 Dp
+1411 2294 MXY
+ 1411 2294 lineto
+ 1508 2294 lineto
+ 1508 2612 lineto
+ 1411 2612 lineto
+ 1411 2294 lineto
+closepath 3 1411 2294 1508 2612 Dp
+-1 Ds
+2158 2238 MXY
+ 2158 2238 lineto
+ 2255 2238 lineto
+ 2255 2252 lineto
+ 2158 2252 lineto
+ 2158 2238 lineto
+closepath 21 2158 2238 2255 2252 Dp
+1868 MX
+ 1868 2238 lineto
+ 1965 2238 lineto
+ 1965 2280 lineto
+ 1868 2280 lineto
+ 1868 2238 lineto
+closepath 21 1868 2238 1965 2280 Dp
+1577 MX
+ 1577 2238 lineto
+ 1674 2238 lineto
+ 1674 2308 lineto
+ 1577 2308 lineto
+ 1577 2238 lineto
+closepath 21 1577 2238 1674 2308 Dp
+1287 2308 MXY
+ 1287 2308 lineto
+ 1287 2280 lineto
+ 1384 2280 lineto
+ 1384 2308 lineto
+ 1287 2308 lineto
+closepath 21 1287 2280 1384 2308 Dp
+2158 2280 MXY
+ 2158 2280 lineto
+ 2158 2252 lineto
+ 2255 2252 lineto
+ 2255 2280 lineto
+ 2158 2280 lineto
+closepath 14 2158 2252 2255 2280 Dp
+1868 2308 MXY
+ 1868 2308 lineto
+ 1868 2280 lineto
+ 1965 2280 lineto
+ 1965 2308 lineto
+ 1868 2308 lineto
+closepath 14 1868 2280 1965 2308 Dp
+1577 2335 MXY
+ 1577 2335 lineto
+ 1577 2308 lineto
+ 1674 2308 lineto
+ 1674 2335 lineto
+ 1577 2335 lineto
+closepath 14 1577 2308 1674 2335 Dp
+1287 2363 MXY
+ 1287 2363 lineto
+ 1287 2308 lineto
+ 1384 2308 lineto
+ 1384 2363 lineto
+ 1287 2363 lineto
+closepath 14 1287 2308 1384 2363 Dp
+2158 2280 MXY
+ 2158 2280 lineto
+ 2255 2280 lineto
+ 2255 2612 lineto
+ 2158 2612 lineto
+ 2158 2280 lineto
+closepath 3 2158 2280 2255 2612 Dp
+1868 2308 MXY
+ 1868 2308 lineto
+ 1965 2308 lineto
+ 1965 2612 lineto
+ 1868 2612 lineto
+ 1868 2308 lineto
+closepath 3 1868 2308 1965 2612 Dp
+1577 2335 MXY
+ 1577 2335 lineto
+ 1674 2335 lineto
+ 1674 2612 lineto
+ 1577 2612 lineto
+ 1577 2335 lineto
+closepath 3 1577 2335 1674 2612 Dp
+1287 2363 MXY
+ 1287 2363 lineto
+ 1384 2363 lineto
+ 1384 2612 lineto
+ 1287 2612 lineto
+ 1287 2363 lineto
+closepath 3 1287 2363 1384 2612 Dp
+4 Ds
+1121 2066 MXY
+ 1121 2066 lineto
+ 1218 2066 lineto
+ 1224 2080 lineto
+ 1127 2080 lineto
+ 1121 2066 lineto
+closepath 21 1121 2066 1224 2080 Dp
+2080 MY
+ 1121 2080 lineto
+ 1218 2080 lineto
+ 1218 2273 lineto
+ 1121 2273 lineto
+ 1121 2080 lineto
+closepath 14 1121 2080 1218 2273 Dp
+2273 MY
+ 1121 2273 lineto
+ 1218 2273 lineto
+ 1218 2612 lineto
+ 1121 2612 lineto
+ 1121 2273 lineto
+closepath 3 1121 2273 1218 2612 Dp
+-1 Ds
+997 1589 MXY
+ 997 1589 lineto
+ 1093 1589 lineto
+ 1093 1644 lineto
+ 997 1644 lineto
+ 997 1589 lineto
+closepath 21 997 1589 1093 1644 Dp
+1644 MY
+ 997 1644 lineto
+ 1093 1644 lineto
+ 1093 2280 lineto
+ 997 2280 lineto
+ 997 1644 lineto
+closepath 14 997 1644 1093 2280 Dp
+2280 MY
+ 997 2280 lineto
+ 1093 2280 lineto
+ 1093 2612 lineto
+ 997 2612 lineto
+ 997 2280 lineto
+closepath 3 997 2280 1093 2612 Dp
+10 s
+719 2093(s)N
+712 2037(d)N
+712 1982(n)N
+714 1927(o)N
+716 1872(c)N
+716 1816(e)N
+712 1761(S)N
+804 2286(10)N
+804 1899(20)N
+804 1540(30)N
+3 Dt
+900 1506 MXY
+0 1106 Dl
+1548 0 Dl
+7 s
+1978 2828(Elapsed)N
+1701 2925(Dynamically)N
+2018(grown)X
+2184(table)X
+2317(\(right\))X
+3 Dt
+-1 Ds
+8 s
+720 3180(Figure)N
+934(6:)X
+1 f
+1020(The)X
+1152(total)X
+1299(regions)X
+1520(indicate)X
+1755(the)X
+1865(difference)X
+2154(between)X
+2398(the)X
+720 3268(elapsed)N
+931(time)X
+1065(and)X
+1177(the)X
+1275(sum)X
+1402(of)X
+1475(the)X
+1573(system)X
+1771(and)X
+1883(user)X
+2008(time.)X
+2173(The)X
+2291(left)X
+2395(bar)X
+720 3356(of)N
+798(each)X
+939(set)X
+1035(depicts)X
+1241(the)X
+1344(timing)X
+1537(of)X
+1615(the)X
+1718(test)X
+1831(run)X
+1940(when)X
+2102(the)X
+2204(number)X
+2423(of)X
+720 3444(entries)N
+910(is)X
+973(known)X
+1167(in)X
+1237(advance.)X
+1496(The)X
+1614(right)X
+1754(bars)X
+1879(depict)X
+2054(the)X
+2151(timing)X
+2338(when)X
+720 3532(the)N
+814(\256le)X
+912(is)X
+971(grown)X
+1150(from)X
+1290(a)X
+1334(single)X
+1503(bucket.)X
+10 s
+10 f
+720 3708 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+892 3910(Since)N
+1131(this)X
+1307(hashing)X
+1617(package)X
+1942(provides)X
+2279(buffer)X
+720 3998(management,)N
+1188(the)X
+1323(amount)X
+1600(of)X
+1704(space)X
+1920(allocated)X
+2247(for)X
+2378(the)X
+720 4086(buffer)N
+948(pool)X
+1121(may)X
+1290(be)X
+1397(speci\256ed)X
+1713(by)X
+1824(the)X
+1953(user.)X
+2157(Using)X
+2378(the)X
+720 4174(same)N
+910(data)X
+1069(set)X
+1183(and)X
+1324(test)X
+1459(procedure)X
+1805(as)X
+1896(used)X
+2067(to)X
+2153(derive)X
+2378(the)X
+720 4262(graphs)N
+962(in)X
+1052(Figures)X
+1320(5a-c,)X
+1507(Figure)X
+1744(7)X
+1812(shows)X
+2039(the)X
+2164(impact)X
+2409(of)X
+720 4350(varying)N
+997(the)X
+1126(size)X
+1282(of)X
+1380(the)X
+1509(buffer)X
+1737(pool.)X
+1950(The)X
+2106(bucket)X
+2351(size)X
+720 4438(was)N
+873(set)X
+989(to)X
+1078(256)X
+1225(bytes)X
+1421(and)X
+1564(the)X
+1689(\256ll)X
+1804(factor)X
+2019(was)X
+2171(set)X
+2287(to)X
+2376(16.)X
+720 4526(The)N
+869(buffer)X
+1090(pool)X
+1256(size)X
+1404(was)X
+1552(varied)X
+1776(from)X
+1955(0)X
+2018(\(the)X
+2166(minimum)X
+720 4614(number)N
+986(of)X
+1074(pages)X
+1277(required)X
+1565(to)X
+1647(be)X
+1743(buffered\))X
+2063(to)X
+2145(1M.)X
+2316(With)X
+720 4702(1M)N
+854(of)X
+944(buffer)X
+1164(space,)X
+1386(the)X
+1507(package)X
+1794(performed)X
+2151(no)X
+2253(I/O)X
+2382(for)X
+720 4790(this)N
+871(data)X
+1040(set.)X
+1204(As)X
+1328(Figure)X
+1572(7)X
+1647(illustrates,)X
+2013(increasing)X
+2378(the)X
+720 4878(buffer)N
+944(pool)X
+1113(size)X
+1265(can)X
+1404(have)X
+1583(a)X
+1646(dramatic)X
+1954(affect)X
+2165(on)X
+2271(result-)X
+720 4966(ing)N
+842(performance.)X
+2 f
+8 s
+1269 4941(7)N
+1 f
+16 s
+720 5353 MXY
+864 0 Dl
+2 f
+8 s
+760 5408(7)N
+1 f
+9 s
+826 5433(Some)N
+1024(allocators)X
+1338(are)X
+1460(extremely)X
+1782(inef\256cient)X
+2107(at)X
+2192(allocating)X
+720 5513(memory.)N
+1029(If)X
+1110(you)X
+1251(\256nd)X
+1396(that)X
+1536(applications)X
+1916(are)X
+2036(running)X
+2292(out)X
+2416(of)X
+720 5593(memory)N
+1005(before)X
+1234(you)X
+1386(think)X
+1578(they)X
+1746(should,)X
+2000(try)X
+2124(varying)X
+2388(the)X
+720 5673(pagesize)N
+986(to)X
+1060(get)X
+1166(better)X
+1348(utilization)X
+1658(from)X
+1816(the)X
+1922(memory)X
+2180(allocator.)X
+10 s
+2830 1975 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+2853 2004 MXY
+0 -27 Dl
+28 0 Dl
+0 27 Dl
+-28 0 Dl
+2876 2016 MXY
+0 -27 Dl
+27 0 Dl
+0 27 Dl
+-27 0 Dl
+2922 1998 MXY
+0 -27 Dl
+27 0 Dl
+0 27 Dl
+-27 0 Dl
+2967 2025 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+3013 2031 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+3059 MX
+0 -28 Dl
+27 0 Dl
+0 28 Dl
+-27 0 Dl
+3196 2052 MXY
+0 -28 Dl
+27 0 Dl
+0 28 Dl
+-27 0 Dl
+3561 2102 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+4292 2105 MXY
+0 -28 Dl
+27 0 Dl
+0 28 Dl
+-27 0 Dl
+4 Ds
+1 Dt
+2844 1961 MXY
+23 30 Dl
+23 12 Dl
+45 -18 Dl
+46 26 Dl
+46 6 Dl
+45 0 Dl
+137 21 Dl
+366 50 Dl
+730 3 Dl
+9 s
+4227 2158(User)N
+-1 Ds
+3 Dt
+2830 1211 MXY
+27 Dc
+2853 1261 MXY
+27 Dc
+2876 1267 MXY
+27 Dc
+2921 1341 MXY
+27 Dc
+2967 1385 MXY
+27 Dc
+3013 1450 MXY
+27 Dc
+3059 1497 MXY
+27 Dc
+3196 1686 MXY
+27 Dc
+3561 2109 MXY
+27 Dc
+4292 2295 MXY
+27 Dc
+20 Ds
+1 Dt
+2844 1211 MXY
+23 50 Dl
+23 6 Dl
+45 74 Dl
+46 44 Dl
+46 65 Dl
+45 47 Dl
+137 189 Dl
+366 423 Dl
+730 186 Dl
+4181 2270(System)N
+-1 Ds
+3 Dt
+2844 583 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2867 672 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2890 701 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+2935 819 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-27 0 Dl
+2981 849 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+3027 908 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-28 0 Dl
+3072 1026 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-27 0 Dl
+3209 1292 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-27 0 Dl
+3575 1823 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+4305 2059 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-27 0 Dl
+5 Dt
+2844 597 MXY
+23 88 Dl
+23 30 Dl
+45 118 Dl
+46 30 Dl
+46 59 Dl
+45 118 Dl
+137 265 Dl
+366 532 Dl
+730 236 Dl
+4328 2103(Total)N
+2844 2310 MXY
+1461 0 Dl
+2844 MX
+0 -1772 Dl
+2310 MY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+2826 2416(0)N
+-1 Ds
+5 Dt
+3209 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+3155 2416(256)N
+-1 Ds
+5 Dt
+3575 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+3521 2416(512)N
+-1 Ds
+5 Dt
+3940 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+3886 2416(768)N
+-1 Ds
+5 Dt
+4305 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+4233 2416(1024)N
+-1 Ds
+5 Dt
+2844 2310 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2771 2340(0)N
+-1 Ds
+5 Dt
+2844 2014 MXY
+-18 0 Dl
+2844 1719 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2735 1749(20)N
+-1 Ds
+5 Dt
+2844 1423 MXY
+-18 0 Dl
+2844 1128 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2735 1158(40)N
+-1 Ds
+5 Dt
+2844 833 MXY
+-18 0 Dl
+2844 538 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2735 568(60)N
+3239 2529(Buffer)N
+3445(Pool)X
+3595(Size)X
+3737(\(in)X
+3835(K\))X
+2695 1259(S)N
+2699 1324(e)N
+2699 1388(c)N
+2697 1452(o)N
+2697 1517(n)N
+2697 1581(d)N
+2701 1645(s)N
+3 Dt
+-1 Ds
+3 f
+8 s
+2706 2773(Figure)N
+2908(7:)X
+1 f
+2982(User)X
+3123(time)X
+3258(is)X
+3322(virtually)X
+3560(insensitive)X
+3854(to)X
+3924(the)X
+4022(amount)X
+4234(of)X
+4307(buffer)X
+2706 2861(pool)N
+2852(available,)X
+3130(however,)X
+3396(both)X
+3541(system)X
+3750(time)X
+3895(and)X
+4018(elapsed)X
+4240(time)X
+4385(are)X
+2706 2949(inversely)N
+2960(proportional)X
+3296(to)X
+3366(the)X
+3464(size)X
+3583(of)X
+3656(the)X
+3753(buffer)X
+3927(pool.)X
+4092(Even)X
+4242(for)X
+4335(large)X
+2706 3037(data)N
+2831(sets)X
+2946(where)X
+3120(one)X
+3230(expects)X
+3439(few)X
+3552(collisions,)X
+3832(specifying)X
+4116(a)X
+4162(large)X
+4307(buffer)X
+2706 3125(pool)N
+2836(dramatically)X
+3171(improves)X
+3425(performance.)X
+10 s
+10 f
+2706 3301 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+3175 3543(Enhanced)N
+3536(Functionality)X
+1 f
+2878 3675(This)N
+3046(hashing)X
+3320(package)X
+3609(provides)X
+3910(a)X
+3971(set)X
+4085(of)X
+4177(compati-)X
+2706 3763(bility)N
+2895(routines)X
+3174(to)X
+3257(implement)X
+3620(the)X
+2 f
+3739(ndbm)X
+1 f
+3937(interface.)X
+4279(How-)X
+2706 3851(ever,)N
+2893(when)X
+3095(the)X
+3220(native)X
+3443(interface)X
+3752(is)X
+3832(used,)X
+4026(the)X
+4151(following)X
+2706 3939(additional)N
+3046(functionality)X
+3475(is)X
+3548(provided:)X
+10 f
+2798 4071(g)N
+1 f
+2946(Inserts)X
+3197(never)X
+3413(fail)X
+3556(because)X
+3847(too)X
+3985(many)X
+4199(keys)X
+2946 4159(hash)N
+3113(to)X
+3195(the)X
+3313(same)X
+3498(value.)X
+10 f
+2798 4247(g)N
+1 f
+2946(Inserts)X
+3187(never)X
+3393(fail)X
+3527(because)X
+3808(key)X
+3950(and/or)X
+4181(asso-)X
+2946 4335(ciated)N
+3158(data)X
+3312(is)X
+3385(too)X
+3507(large)X
+10 f
+2798 4423(g)N
+1 f
+2946(Hash)X
+3131(functions)X
+3449(may)X
+3607(be)X
+3703(user-speci\256ed.)X
+10 f
+2798 4511(g)N
+1 f
+2946(Multiple)X
+3268(pages)X
+3498(may)X
+3683(be)X
+3806(cached)X
+4077(in)X
+4186(main)X
+2946 4599(memory.)N
+2706 4731(It)N
+2801(also)X
+2976(provides)X
+3298(a)X
+3380(set)X
+3514(of)X
+3626(compatibility)X
+4097(routines)X
+4400(to)X
+2706 4819(implement)N
+3087(the)X
+2 f
+3224(hsearch)X
+1 f
+3516(interface.)X
+3876(Again,)X
+4130(the)X
+4266(native)X
+2706 4907(interface)N
+3008(offers)X
+3216(enhanced)X
+3540(functionality:)X
+10 f
+2798 5039(g)N
+1 f
+2946(Files)X
+3121(may)X
+3279(grow)X
+3464(beyond)X
+2 f
+3720(nelem)X
+1 f
+3932(elements.)X
+10 f
+2798 5127(g)N
+1 f
+2946(Multiple)X
+3247(hash)X
+3420(tables)X
+3632(may)X
+3795(be)X
+3896(accessed)X
+4203(con-)X
+2946 5215(currently.)N
+10 f
+2798 5303(g)N
+1 f
+2946(Hash)X
+3134(tables)X
+3344(may)X
+3505(be)X
+3604(stored)X
+3823(and)X
+3962(accessed)X
+4266(on)X
+2946 5391(disk.)N
+10 f
+2798 5479(g)N
+1 f
+2946(Hash)X
+3155(functions)X
+3497(may)X
+3679(be)X
+3799(user-speci\256ed)X
+4288(at)X
+2946 5567(runtime.)N
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(9)X
+
+10 p
+%%Page: 10 10
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+459 538(Relative)N
+760(Performance)X
+1227(of)X
+1314(the)X
+1441(New)X
+1613(Implementation)X
+1 f
+604 670(The)N
+761(performance)X
+1200(testing)X
+1445(of)X
+1544(the)X
+1674(new)X
+1840(package)X
+2135(is)X
+432 758(divided)N
+711(into)X
+874(two)X
+1033(test)X
+1183(suites.)X
+1424(The)X
+1588(\256rst)X
+1751(suite)X
+1941(of)X
+2046(tests)X
+432 846(requires)N
+727(that)X
+882(the)X
+1015(tables)X
+1237(be)X
+1348(read)X
+1522(from)X
+1713(and)X
+1864(written)X
+2126(to)X
+432 934(disk.)N
+640(In)X
+742(these)X
+942(tests,)X
+1139(the)X
+1272(basis)X
+1467(for)X
+1595(comparison)X
+2003(is)X
+2090(the)X
+432 1022(4.3BSD-Reno)N
+908(version)X
+1169(of)X
+2 f
+1260(ndbm)X
+1 f
+1438(.)X
+1502(Based)X
+1722(on)X
+1826(the)X
+1948(designs)X
+432 1110(of)N
+2 f
+521(sdbm)X
+1 f
+712(and)X
+2 f
+850(gdbm)X
+1 f
+1028(,)X
+1070(they)X
+1230(are)X
+1351(expected)X
+1659(to)X
+1743(perform)X
+2024(simi-)X
+432 1198(larly)N
+605(to)X
+2 f
+693(ndbm)X
+1 f
+871(,)X
+917(and)X
+1059(we)X
+1179(do)X
+1285(not)X
+1413(show)X
+1608(their)X
+1781(performance)X
+432 1286(numbers.)N
+800(The)X
+977(second)X
+1252(suite)X
+1454(contains)X
+1772(the)X
+1921(memory)X
+432 1374(resident)N
+712(test)X
+849(which)X
+1071(does)X
+1243(not)X
+1370(require)X
+1623(that)X
+1768(the)X
+1891(\256les)X
+2049(ever)X
+432 1462(be)N
+533(written)X
+784(to)X
+870(disk,)X
+1047(only)X
+1213(that)X
+1357(hash)X
+1528(tables)X
+1739(may)X
+1901(be)X
+2001(mani-)X
+432 1550(pulated)N
+692(in)X
+778(main)X
+961(memory.)X
+1291(In)X
+1381(this)X
+1519(test,)X
+1673(we)X
+1790(compare)X
+2090(the)X
+432 1638(performance)N
+859(to)X
+941(that)X
+1081(of)X
+1168(the)X
+2 f
+1286(hsearch)X
+1 f
+1560(routines.)X
+604 1752(For)N
+760(both)X
+947(suites,)X
+1194(two)X
+1358(different)X
+1679(databases)X
+2031(were)X
+432 1840(used.)N
+656(The)X
+818(\256rst)X
+979(is)X
+1069(the)X
+1204(dictionary)X
+1566(database)X
+1880(described)X
+432 1928(previously.)N
+836(The)X
+987(second)X
+1236(was)X
+1386(constructed)X
+1781(from)X
+1962(a)X
+2023(pass-)X
+432 2016(word)N
+647(\256le)X
+799(with)X
+990(approximately)X
+1502(300)X
+1671(accounts.)X
+2041(Two)X
+432 2104(records)N
+700(were)X
+887(constructed)X
+1287(for)X
+1411(each)X
+1589(account.)X
+1909(The)X
+2064(\256rst)X
+432 2192(used)N
+604(the)X
+727(logname)X
+1028(as)X
+1120(the)X
+1243(key)X
+1384(and)X
+1525(the)X
+1648(remainder)X
+1999(of)X
+2090(the)X
+432 2280(password)N
+768(entry)X
+965(for)X
+1091(the)X
+1221(data.)X
+1427(The)X
+1584(second)X
+1839(was)X
+1996(keyed)X
+432 2368(by)N
+541(uid)X
+672(and)X
+817(contained)X
+1157(the)X
+1283(entire)X
+1494(password)X
+1825(entry)X
+2018(as)X
+2113(its)X
+432 2456(data)N
+589(\256eld.)X
+794(The)X
+942(tests)X
+1107(were)X
+1287(all)X
+1389(run)X
+1518(on)X
+1620(the)X
+1740(HP)X
+1864(9000)X
+2046(with)X
+432 2544(the)N
+574(same)X
+783(con\256guration)X
+1254(previously)X
+1636(described.)X
+2027(Each)X
+432 2632(test)N
+576(was)X
+734(run)X
+874(\256ve)X
+1027(times)X
+1232(and)X
+1380(the)X
+1510(timing)X
+1750(results)X
+1991(of)X
+2090(the)X
+432 2720(runs)N
+602(were)X
+791(averaged.)X
+1154(The)X
+1311(variance)X
+1616(across)X
+1849(the)X
+1979(5)X
+2050(runs)X
+432 2808(was)N
+591(approximately)X
+1088(1%)X
+1229(of)X
+1330(the)X
+1462(average)X
+1746(yielding)X
+2041(95%)X
+432 2896(con\256dence)N
+800(intervals)X
+1096(of)X
+1183(approximately)X
+1666(2%.)X
+3 f
+1021 3050(Disk)N
+1196(Based)X
+1420(Tests)X
+1 f
+604 3182(In)N
+693(these)X
+880(tests,)X
+1064(we)X
+1180(use)X
+1308(a)X
+1365(bucket)X
+1600(size)X
+1746(of)X
+1834(1024)X
+2015(and)X
+2152(a)X
+432 3270(\256ll)N
+540(factor)X
+748(of)X
+835(32.)X
+3 f
+432 3384(create)N
+663(test)X
+1 f
+547 3498(The)N
+703(keys)X
+881(are)X
+1011(entered)X
+1279(into)X
+1433(the)X
+1561(hash)X
+1738(table,)X
+1944(and)X
+2090(the)X
+547 3586(\256le)N
+669(is)X
+742(\257ushed)X
+993(to)X
+1075(disk.)X
+3 f
+432 3700(read)N
+608(test)X
+1 f
+547 3814(A)N
+640(lookup)X
+897(is)X
+984(performed)X
+1353(for)X
+1481(each)X
+1663(key)X
+1813(in)X
+1909(the)X
+2041(hash)X
+547 3902(table.)N
+3 f
+432 4016(verify)N
+653(test)X
+1 f
+547 4130(A)N
+640(lookup)X
+897(is)X
+984(performed)X
+1353(for)X
+1481(each)X
+1663(key)X
+1813(in)X
+1909(the)X
+2041(hash)X
+547 4218(table,)N
+759(and)X
+911(the)X
+1045(data)X
+1215(returned)X
+1519(is)X
+1608(compared)X
+1961(against)X
+547 4306(that)N
+687(originally)X
+1018(stored)X
+1234(in)X
+1316(the)X
+1434(hash)X
+1601(table.)X
+3 f
+432 4420(sequential)N
+798(retrieve)X
+1 f
+547 4534(All)N
+674(keys)X
+846(are)X
+970(retrieved)X
+1281(in)X
+1367(sequential)X
+1716(order)X
+1910(from)X
+2090(the)X
+547 4622(hash)N
+724(table.)X
+950(The)X
+2 f
+1105(ndbm)X
+1 f
+1313(interface)X
+1625(allows)X
+1863(sequential)X
+547 4710(retrieval)N
+848(of)X
+948(the)X
+1079(keys)X
+1259(from)X
+1448(the)X
+1578(database,)X
+1907(but)X
+2041(does)X
+547 4798(not)N
+701(return)X
+945(the)X
+1094(data)X
+1279(associated)X
+1660(with)X
+1853(each)X
+2052(key.)X
+547 4886(Therefore,)N
+929(we)X
+1067(compare)X
+1388(the)X
+1530(performance)X
+1980(of)X
+2090(the)X
+547 4974(new)N
+703(package)X
+989(to)X
+1073(two)X
+1215(different)X
+1514(runs)X
+1674(of)X
+2 f
+1763(ndbm)X
+1 f
+1941(.)X
+2002(In)X
+2090(the)X
+547 5062(\256rst)N
+697(case,)X
+2 f
+882(ndbm)X
+1 f
+1086(returns)X
+1335(only)X
+1503(the)X
+1627(keys)X
+1800(while)X
+2003(in)X
+2090(the)X
+547 5150(second,)N
+2 f
+823(ndbm)X
+1 f
+1034(returns)X
+1290(both)X
+1465(the)X
+1596(keys)X
+1776(and)X
+1924(the)X
+2054(data)X
+547 5238(\(requiring)N
+894(a)X
+956(second)X
+1204(call)X
+1345(to)X
+1432(the)X
+1555(library\).)X
+1861(There)X
+2074(is)X
+2152(a)X
+547 5326(single)N
+764(run)X
+897(for)X
+1017(the)X
+1141(new)X
+1300(library)X
+1539(since)X
+1729(it)X
+1798(returns)X
+2046(both)X
+547 5414(the)N
+665(key)X
+801(and)X
+937(the)X
+1055(data.)X
+3 f
+3014 538(In-Memory)N
+3431(Test)X
+1 f
+2590 670(This)N
+2757(test)X
+2892(uses)X
+3054(a)X
+3114(bucket)X
+3352(size)X
+3501(of)X
+3592(256)X
+3736(and)X
+3876(a)X
+3936(\256ll)X
+4048(fac-)X
+2418 758(tor)N
+2527(of)X
+2614(8.)X
+3 f
+2418 872(create/read)N
+2827(test)X
+1 f
+2533 986(In)N
+2627(this)X
+2769(test,)X
+2927(a)X
+2989(hash)X
+3162(table)X
+3344(is)X
+3423(created)X
+3682(by)X
+3788(inserting)X
+4094(all)X
+2533 1074(the)N
+2660(key/data)X
+2961(pairs.)X
+3186(Then)X
+3380(a)X
+3445(keyed)X
+3666(retrieval)X
+3963(is)X
+4044(per-)X
+2533 1162(formed)N
+2801(for)X
+2931(each)X
+3115(pair,)X
+3295(and)X
+3446(the)X
+3579(hash)X
+3761(table)X
+3952(is)X
+4040(des-)X
+2533 1250(troyed.)N
+3 f
+2938 1404(Performance)N
+3405(Results)X
+1 f
+2590 1536(Figures)N
+2866(8a)X
+2978(and)X
+3130(8b)X
+3246(show)X
+3451(the)X
+3585(user)X
+3755(time,)X
+3952(system)X
+2418 1624(time,)N
+2608(and)X
+2752(elapsed)X
+3021(time)X
+3191(for)X
+3312(each)X
+3487(test)X
+3625(for)X
+3746(both)X
+3915(the)X
+4040(new)X
+2418 1712(implementation)N
+2951(and)X
+3098(the)X
+3227(old)X
+3360(implementation)X
+3893(\()X
+2 f
+3920(hsearch)X
+1 f
+2418 1800(or)N
+2 f
+2528(ndbm)X
+1 f
+2706(,)X
+2769(whichever)X
+3147(is)X
+3243(appropriate\))X
+3678(as)X
+3787(well)X
+3967(as)X
+4076(the)X
+2418 1888(improvement.)N
+2929(The)X
+3098(improvement)X
+3569(is)X
+3666(expressed)X
+4027(as)X
+4138(a)X
+2418 1976(percentage)N
+2787(of)X
+2874(the)X
+2992(old)X
+3114(running)X
+3383(time:)X
+0 f
+8 s
+2418 2275(%)N
+2494(=)X
+2570(100)X
+2722(*)X
+2798 -0.4219(\(old_time)AX
+3178(-)X
+3254 -0.4219(new_time\))AX
+3634(/)X
+3710(old_time)X
+1 f
+10 s
+2590 2600(In)N
+2700(nearly)X
+2944(all)X
+3067(cases,)X
+3299(the)X
+3439(new)X
+3615(routines)X
+3915(perform)X
+2418 2688(better)N
+2628(than)X
+2793(the)X
+2918(old)X
+3047(routines)X
+3332(\(both)X
+2 f
+3527(hsearch)X
+1 f
+3807(and)X
+2 f
+3949(ndbm)X
+1 f
+4127(\).)X
+2418 2776(Although)N
+2755(the)X
+3 f
+2888(create)X
+1 f
+3134(tests)X
+3311(exhibit)X
+3567(superior)X
+3864(user)X
+4032(time)X
+2418 2864(performance,)N
+2869(the)X
+2991(test)X
+3126(time)X
+3292(is)X
+3369(dominated)X
+3731(by)X
+3834(the)X
+3955(cost)X
+4107(of)X
+2418 2952(writing)N
+2677(the)X
+2803(actual)X
+3023(\256le)X
+3153(to)X
+3243(disk.)X
+3444(For)X
+3583(the)X
+3709(large)X
+3897(database)X
+2418 3040(\(the)N
+2564(dictionary\),)X
+2957(this)X
+3093(completely)X
+3470(overwhelmed)X
+3927(the)X
+4045(sys-)X
+2418 3128(tem)N
+2570(time.)X
+2783(However,)X
+3129(for)X
+3254(the)X
+3383(small)X
+3587(data)X
+3752(base,)X
+3946(we)X
+4071(see)X
+2418 3216(that)N
+2569(differences)X
+2958(in)X
+3051(both)X
+3224(user)X
+3389(and)X
+3536(system)X
+3788(time)X
+3960(contri-)X
+2418 3304(bute)N
+2576(to)X
+2658(the)X
+2776(superior)X
+3059(performance)X
+3486(of)X
+3573(the)X
+3691(new)X
+3845(package.)X
+2590 3418(The)N
+3 f
+2764(read)X
+1 f
+2920(,)X
+3 f
+2989(verify)X
+1 f
+3190(,)X
+3259(and)X
+3 f
+3424(sequential)X
+1 f
+3818(results)X
+4075(are)X
+2418 3506(deceptive)N
+2758(for)X
+2883(the)X
+3012(small)X
+3216(database)X
+3524(since)X
+3720(the)X
+3849(entire)X
+4063(test)X
+2418 3594(ran)N
+2551(in)X
+2643(under)X
+2856(a)X
+2922(second.)X
+3215(However,)X
+3560(on)X
+3669(the)X
+3796(larger)X
+4013(data-)X
+2418 3682(base)N
+2590(the)X
+3 f
+2716(read)X
+1 f
+2900(and)X
+3 f
+3044(verify)X
+1 f
+3273(tests)X
+3443(bene\256t)X
+3689(from)X
+3873(the)X
+3999(cach-)X
+2418 3770(ing)N
+2546(of)X
+2639(buckets)X
+2910(in)X
+2998(the)X
+3122(new)X
+3282(package)X
+3571(to)X
+3658(improve)X
+3950(perfor-)X
+2418 3858(mance)N
+2666(by)X
+2784(over)X
+2965(80%.)X
+3169(Since)X
+3384(the)X
+3519(\256rst)X
+3 f
+3680(sequential)X
+1 f
+4063(test)X
+2418 3946(does)N
+2598(not)X
+2733(require)X
+2 f
+2994(ndbm)X
+1 f
+3205(to)X
+3299(return)X
+3523(the)X
+3653(data)X
+3819(values,)X
+4076(the)X
+2418 4034(user)N
+2573(time)X
+2735(is)X
+2808(lower)X
+3011(than)X
+3169(for)X
+3283(the)X
+3401(new)X
+3555(package.)X
+3879(However)X
+2418 4122(when)N
+2613(we)X
+2728(require)X
+2977(both)X
+3139(packages)X
+3454(to)X
+3536(return)X
+3748(data,)X
+3922(the)X
+4040(new)X
+2418 4210(package)N
+2702(excels)X
+2923(in)X
+3005(all)X
+3105(three)X
+3286(timings.)X
+2590 4324(The)N
+2773(small)X
+3003(database)X
+3337(runs)X
+3532(so)X
+3660(quickly)X
+3957(in)X
+4076(the)X
+2418 4412(memory-resident)N
+3000(case)X
+3173(that)X
+3326(the)X
+3457(results)X
+3699(are)X
+3831(uninterest-)X
+2418 4500(ing.)N
+2589(However,)X
+2933(for)X
+3056(the)X
+3183(larger)X
+3400(database)X
+3706(the)X
+3833(new)X
+3995(pack-)X
+2418 4588(age)N
+2567(pays)X
+2751(a)X
+2824(small)X
+3033(penalty)X
+3305(in)X
+3403(system)X
+3661(time)X
+3839(because)X
+4130(it)X
+2418 4676(limits)N
+2636(its)X
+2748(main)X
+2944(memory)X
+3247(utilization)X
+3607(and)X
+3759(swaps)X
+3991(pages)X
+2418 4764(out)N
+2550(to)X
+2642(temporary)X
+3002(storage)X
+3264(in)X
+3356(the)X
+3484(\256le)X
+3616(system)X
+3868(while)X
+4076(the)X
+2 f
+2418 4852(hsearch)N
+1 f
+2698(package)X
+2988(requires)X
+3273(that)X
+3419(the)X
+3543(application)X
+3924(allocate)X
+2418 4940(enough)N
+2692(space)X
+2909(for)X
+3041(all)X
+3159(key/data)X
+3468(pair.)X
+3670(However,)X
+4022(even)X
+2418 5028(with)N
+2600(the)X
+2738(system)X
+3000(time)X
+3182(penalty,)X
+3477(the)X
+3614(resulting)X
+3933(elapsed)X
+2418 5116(time)N
+2580(improves)X
+2898(by)X
+2998(over)X
+3161(50%.)X
+3 f
+432 5960(10)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+11 p
+%%Page: 11 11
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+10 f
+908 454(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+1379 546(hash)N
+1652(ndbm)X
+1950(%change)X
+1 f
+10 f
+908 550(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 642(CREATE)N
+10 f
+908 646(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 738(user)N
+1424(6.4)X
+1671(12.2)X
+2073(48)X
+1157 826(sys)N
+1384(32.5)X
+1671(34.7)X
+2113(6)X
+3 f
+1006 914(elapsed)N
+10 f
+1310 922(c)N
+890(c)Y
+810(c)Y
+730(c)Y
+3 f
+1384 914(90.4)N
+10 f
+1581 922(c)N
+890(c)Y
+810(c)Y
+730(c)Y
+3 f
+1671 914(99.6)N
+10 f
+1883 922(c)N
+890(c)Y
+810(c)Y
+730(c)Y
+3 f
+2113 914(9)N
+1 f
+10 f
+908 910(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 926(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 1010(READ)N
+10 f
+908 1014(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 1106(user)N
+1424(3.4)X
+1711(6.1)X
+2073(44)X
+1157 1194(sys)N
+1424(1.2)X
+1671(15.3)X
+2073(92)X
+3 f
+1006 1282(elapsed)N
+10 f
+1310 1290(c)N
+1258(c)Y
+1178(c)Y
+1098(c)Y
+3 f
+1424 1282(4.0)N
+10 f
+1581 1290(c)N
+1258(c)Y
+1178(c)Y
+1098(c)Y
+3 f
+1671 1282(21.2)N
+10 f
+1883 1290(c)N
+1258(c)Y
+1178(c)Y
+1098(c)Y
+3 f
+2073 1282(81)N
+1 f
+10 f
+908 1278(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 1294(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 1378(VERIFY)N
+10 f
+908 1382(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 1474(user)N
+1424(3.5)X
+1711(6.3)X
+2073(44)X
+1157 1562(sys)N
+1424(1.2)X
+1671(15.3)X
+2073(92)X
+3 f
+1006 1650(elapsed)N
+10 f
+1310 1658(c)N
+1626(c)Y
+1546(c)Y
+1466(c)Y
+3 f
+1424 1650(4.0)N
+10 f
+1581 1658(c)N
+1626(c)Y
+1546(c)Y
+1466(c)Y
+3 f
+1671 1650(21.2)N
+10 f
+1883 1658(c)N
+1626(c)Y
+1546(c)Y
+1466(c)Y
+3 f
+2073 1650(81)N
+1 f
+10 f
+908 1646(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 1662(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 1746(SEQUENTIAL)N
+10 f
+908 1750(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 1842(user)N
+1424(2.7)X
+1711(1.9)X
+2046(-42)X
+1157 1930(sys)N
+1424(0.7)X
+1711(3.9)X
+2073(82)X
+3 f
+1006 2018(elapsed)N
+10 f
+1310 2026(c)N
+1994(c)Y
+1914(c)Y
+1834(c)Y
+3 f
+1424 2018(3.0)N
+10 f
+1581 2026(c)N
+1994(c)Y
+1914(c)Y
+1834(c)Y
+3 f
+1711 2018(5.0)N
+10 f
+1883 2026(c)N
+1994(c)Y
+1914(c)Y
+1834(c)Y
+3 f
+2073 2018(40)N
+1 f
+10 f
+908 2014(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 2030(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 2114(SEQUENTIAL)N
+1467(\(with)X
+1656(data)X
+1810(retrieval\))X
+10 f
+908 2118(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 2210(user)N
+1424(2.7)X
+1711(8.2)X
+2073(67)X
+1157 2298(sys)N
+1424(0.7)X
+1711(4.3)X
+2073(84)X
+3 f
+1006 2386(elapsed)N
+1424(3.0)X
+1671(12.0)X
+2073(75)X
+1 f
+10 f
+908 2390(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+899 2394(c)N
+2378(c)Y
+2298(c)Y
+2218(c)Y
+2138(c)Y
+2058(c)Y
+1978(c)Y
+1898(c)Y
+1818(c)Y
+1738(c)Y
+1658(c)Y
+1578(c)Y
+1498(c)Y
+1418(c)Y
+1338(c)Y
+1258(c)Y
+1178(c)Y
+1098(c)Y
+1018(c)Y
+938(c)Y
+858(c)Y
+778(c)Y
+698(c)Y
+618(c)Y
+538(c)Y
+1310 2394(c)N
+2362(c)Y
+2282(c)Y
+2202(c)Y
+1581 2394(c)N
+2362(c)Y
+2282(c)Y
+2202(c)Y
+1883 2394(c)N
+2362(c)Y
+2282(c)Y
+2202(c)Y
+2278 2394(c)N
+2378(c)Y
+2298(c)Y
+2218(c)Y
+2138(c)Y
+2058(c)Y
+1978(c)Y
+1898(c)Y
+1818(c)Y
+1738(c)Y
+1658(c)Y
+1578(c)Y
+1498(c)Y
+1418(c)Y
+1338(c)Y
+1258(c)Y
+1178(c)Y
+1098(c)Y
+1018(c)Y
+938(c)Y
+858(c)Y
+778(c)Y
+698(c)Y
+618(c)Y
+538(c)Y
+905 2574(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+1318 2666(hash)N
+1585(hsearch)X
+1953(%change)X
+1 f
+10 f
+905 2670(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+945 2762(CREATE/READ)N
+10 f
+905 2766(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1064 2858(user)N
+1343(6.6)X
+1642(17.2)X
+2096(62)X
+1096 2946(sys)N
+1343(1.1)X
+1682(0.3)X
+2029(-266)X
+3 f
+945 3034(elapsed)N
+1343(7.8)X
+1642(17.0)X
+2096(54)X
+1 f
+10 f
+905 3038(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+896 3050(c)N
+2978(c)Y
+2898(c)Y
+2818(c)Y
+2738(c)Y
+2658(c)Y
+1249 3034(c)N
+3010(c)Y
+2930(c)Y
+2850(c)Y
+1520 3034(c)N
+3010(c)Y
+2930(c)Y
+2850(c)Y
+1886 3034(c)N
+3010(c)Y
+2930(c)Y
+2850(c)Y
+2281 3050(c)N
+2978(c)Y
+2898(c)Y
+2818(c)Y
+2738(c)Y
+2658(c)Y
+3 f
+720 3174(Figure)N
+967(8a:)X
+1 f
+1094(Timing)X
+1349(results)X
+1578(for)X
+1692(the)X
+1810(dictionary)X
+2155(database.)X
+10 f
+720 3262 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+1407 3504(Conclusion)N
+1 f
+892 3636(This)N
+1063(paper)X
+1271(has)X
+1407(presented)X
+1744(the)X
+1871(design,)X
+2129(implemen-)X
+720 3724(tation)N
+928(and)X
+1070(performance)X
+1503(of)X
+1596(a)X
+1658(new)X
+1818(hashing)X
+2093(package)X
+2382(for)X
+720 3812(UNIX.)N
+993(The)X
+1150(new)X
+1316(package)X
+1612(provides)X
+1919(a)X
+1986(superset)X
+2280(of)X
+2378(the)X
+720 3900(functionality)N
+1159(of)X
+1255(existing)X
+1537(hashing)X
+1815(packages)X
+2139(and)X
+2284(incor-)X
+720 3988(porates)N
+975(additional)X
+1318(features)X
+1596(such)X
+1766(as)X
+1855(large)X
+2038(key)X
+2176(handling,)X
+720 4076(user)N
+876(de\256ned)X
+1134(hash)X
+1302(functions,)X
+1641(multiple)X
+1928(hash)X
+2096(tables,)X
+2324(vari-)X
+720 4164(able)N
+894(sized)X
+1099(pages,)X
+1342(and)X
+1498(linear)X
+1721(hashing.)X
+2050(In)X
+2156(nearly)X
+2396(all)X
+720 4252(cases,)N
+954(the)X
+1096(new)X
+1274(package)X
+1582(provides)X
+1902(improved)X
+2252(perfor-)X
+720 4340(mance)N
+974(on)X
+1098(the)X
+1240(order)X
+1454(of)X
+1565(50-80%)X
+1863(for)X
+2001(the)X
+2142(workloads)X
+720 4428(shown.)N
+990(Applications)X
+1420(such)X
+1588(as)X
+1676(the)X
+1794(loader,)X
+2035(compiler,)X
+2360(and)X
+720 4516(mail,)N
+921(which)X
+1156(currently)X
+1485(implement)X
+1866(their)X
+2051(own)X
+2227(hashing)X
+720 4604(routines,)N
+1032(should)X
+1279(be)X
+1389(modi\256ed)X
+1706(to)X
+1801(use)X
+1941(the)X
+2072(generic)X
+2342(rou-)X
+720 4692(tines.)N
+892 4806(This)N
+1087(hashing)X
+1389(package)X
+1705(is)X
+1810(one)X
+1978(access)X
+2236(method)X
+720 4894(which)N
+953(is)X
+1043(part)X
+1205(of)X
+1309(a)X
+1382(generic)X
+1656(database)X
+1970(access)X
+2212(package)X
+720 4982(being)N
+955(developed)X
+1342(at)X
+1457(the)X
+1612(University)X
+2007(of)X
+2131(California,)X
+720 5070(Berkeley.)N
+1089(It)X
+1177(will)X
+1340(include)X
+1614(a)X
+1688(btree)X
+1887(access)X
+2131(method)X
+2409(as)X
+720 5158(well)N
+916(as)X
+1041(\256xed)X
+1259(and)X
+1433(variable)X
+1750(length)X
+2007(record)X
+2270(access)X
+720 5246(methods)N
+1024(in)X
+1119(addition)X
+1414(to)X
+1509(the)X
+1640(hashed)X
+1896(support)X
+2168(presented)X
+720 5334(here.)N
+948(All)X
+1099(of)X
+1215(the)X
+1361(access)X
+1615(methods)X
+1934(are)X
+2081(based)X
+2312(on)X
+2440(a)X
+720 5422(key/data)N
+1037(pair)X
+1207(interface)X
+1533(and)X
+1693(appear)X
+1952(identical)X
+2272(to)X
+2378(the)X
+720 5510(application)N
+1121(layer,)X
+1347(allowing)X
+1671(application)X
+2071(implementa-)X
+720 5598(tions)N
+906(to)X
+999(be)X
+1106(largely)X
+1360(independent)X
+1783(of)X
+1881(the)X
+2010(database)X
+2318(type.)X
+720 5686(The)N
+873(package)X
+1165(is)X
+1246(expected)X
+1560(to)X
+1650(be)X
+1754(an)X
+1858(integral)X
+2131(part)X
+2284(of)X
+2378(the)X
+2706 538(4.4BSD)N
+3006(system,)X
+3293(with)X
+3479(various)X
+3759(standard)X
+4075(applications)X
+2706 626(such)N
+2879(as)X
+2972(more\(1\),)X
+3277(sort\(1\))X
+3517(and)X
+3659(vi\(1\))X
+3841(based)X
+4050(on)X
+4156(it.)X
+4266(While)X
+2706 714(the)N
+2833(current)X
+3089(design)X
+3326(does)X
+3501(not)X
+3631(support)X
+3899(multi-user)X
+4256(access)X
+2706 802(or)N
+2804(transactions,)X
+3238(they)X
+3407(could)X
+3616(be)X
+3723(incorporated)X
+4159(relatively)X
+2706 890(easily.)N
+10 f
+2894 938(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+3365 1030(hash)N
+3638(ndbm)X
+3936(%change)X
+1 f
+10 f
+2894 1034(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 1126(CREATE)N
+10 f
+2894 1130(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 1222(user)N
+3390(0.2)X
+3677(0.4)X
+4079(50)X
+3143 1310(sys)N
+3390(0.1)X
+3677(1.0)X
+4079(90)X
+3 f
+2992 1398(elapsed)N
+10 f
+3296 1406(c)N
+1374(c)Y
+1294(c)Y
+1214(c)Y
+3 f
+3390 1398(0)N
+10 f
+3567 1406(c)N
+1374(c)Y
+1294(c)Y
+1214(c)Y
+3 f
+3677 1398(3.2)N
+10 f
+3869 1406(c)N
+1374(c)Y
+1294(c)Y
+1214(c)Y
+3 f
+4039 1398(100)N
+1 f
+10 f
+2894 1394(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 1410(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 1494(READ)N
+10 f
+2894 1498(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 1590(user)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3143 1678(sys)N
+3390(0.1)X
+3677(0.4)X
+4079(75)X
+3 f
+2992 1766(elapsed)N
+10 f
+3296 1774(c)N
+1742(c)Y
+1662(c)Y
+1582(c)Y
+3 f
+3390 1766(0.0)N
+10 f
+3567 1774(c)N
+1742(c)Y
+1662(c)Y
+1582(c)Y
+3 f
+3677 1766(0.0)N
+10 f
+3869 1774(c)N
+1742(c)Y
+1662(c)Y
+1582(c)Y
+3 f
+4119 1766(0)N
+1 f
+10 f
+2894 1762(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 1778(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 1862(VERIFY)N
+10 f
+2894 1866(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 1958(user)N
+3390(0.1)X
+3677(0.2)X
+4079(50)X
+3143 2046(sys)N
+3390(0.1)X
+3677(0.3)X
+4079(67)X
+3 f
+2992 2134(elapsed)N
+10 f
+3296 2142(c)N
+2110(c)Y
+2030(c)Y
+1950(c)Y
+3 f
+3390 2134(0.0)N
+10 f
+3567 2142(c)N
+2110(c)Y
+2030(c)Y
+1950(c)Y
+3 f
+3677 2134(0.0)N
+10 f
+3869 2142(c)N
+2110(c)Y
+2030(c)Y
+1950(c)Y
+3 f
+4119 2134(0)N
+1 f
+10 f
+2894 2130(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 2146(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 2230(SEQUENTIAL)N
+10 f
+2894 2234(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 2326(user)N
+3390(0.1)X
+3677(0.0)X
+4012(-100)X
+3143 2414(sys)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3 f
+2992 2502(elapsed)N
+10 f
+3296 2510(c)N
+2478(c)Y
+2398(c)Y
+2318(c)Y
+3 f
+3390 2502(0.0)N
+10 f
+3567 2510(c)N
+2478(c)Y
+2398(c)Y
+2318(c)Y
+3 f
+3677 2502(0.0)N
+10 f
+3869 2510(c)N
+2478(c)Y
+2398(c)Y
+2318(c)Y
+3 f
+4119 2502(0)N
+1 f
+10 f
+2894 2498(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 2514(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 2598(SEQUENTIAL)N
+3453(\(with)X
+3642(data)X
+3796(retrieval\))X
+10 f
+2894 2602(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 2694(user)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3143 2782(sys)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3 f
+2992 2870(elapsed)N
+3390(0.0)X
+3677(0.0)X
+4119(0)X
+1 f
+10 f
+2894 2874(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2885 2878(c)N
+2862(c)Y
+2782(c)Y
+2702(c)Y
+2622(c)Y
+2542(c)Y
+2462(c)Y
+2382(c)Y
+2302(c)Y
+2222(c)Y
+2142(c)Y
+2062(c)Y
+1982(c)Y
+1902(c)Y
+1822(c)Y
+1742(c)Y
+1662(c)Y
+1582(c)Y
+1502(c)Y
+1422(c)Y
+1342(c)Y
+1262(c)Y
+1182(c)Y
+1102(c)Y
+1022(c)Y
+3296 2878(c)N
+2846(c)Y
+2766(c)Y
+2686(c)Y
+3567 2878(c)N
+2846(c)Y
+2766(c)Y
+2686(c)Y
+3869 2878(c)N
+2846(c)Y
+2766(c)Y
+2686(c)Y
+4264 2878(c)N
+2862(c)Y
+2782(c)Y
+2702(c)Y
+2622(c)Y
+2542(c)Y
+2462(c)Y
+2382(c)Y
+2302(c)Y
+2222(c)Y
+2142(c)Y
+2062(c)Y
+1982(c)Y
+1902(c)Y
+1822(c)Y
+1742(c)Y
+1662(c)Y
+1582(c)Y
+1502(c)Y
+1422(c)Y
+1342(c)Y
+1262(c)Y
+1182(c)Y
+1102(c)Y
+1022(c)Y
+2891 3058(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+3304 3150(hash)N
+3571(hsearch)X
+3939(%change)X
+1 f
+10 f
+2891 3154(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2931 3246(CREATE/READ)N
+10 f
+2891 3250(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3050 3342(user)N
+3329(0.3)X
+3648(0.4)X
+4048(25)X
+3082 3430(sys)N
+3329(0.0)X
+3648(0.0)X
+4088(0)X
+3 f
+2931 3518(elapsed)N
+3329(0.0)X
+3648(0.0)X
+4088(0)X
+1 f
+10 f
+2891 3522(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2882 3534(c)N
+3462(c)Y
+3382(c)Y
+3302(c)Y
+3222(c)Y
+3142(c)Y
+3235 3518(c)N
+3494(c)Y
+3414(c)Y
+3334(c)Y
+3506 3518(c)N
+3494(c)Y
+3414(c)Y
+3334(c)Y
+3872 3518(c)N
+3494(c)Y
+3414(c)Y
+3334(c)Y
+4267 3534(c)N
+3462(c)Y
+3382(c)Y
+3302(c)Y
+3222(c)Y
+3142(c)Y
+3 f
+2706 3658(Figure)N
+2953(8b:)X
+1 f
+3084(Timing)X
+3339(results)X
+3568(for)X
+3682(the)X
+3800(password)X
+4123(database.)X
+10 f
+2706 3746 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+3396 3988(References)N
+1 f
+2706 4120([ATT79])N
+3058(AT&T,)X
+3358(DBM\(3X\),)X
+2 f
+3773(Unix)X
+3990(Programmer's)X
+2878 4208(Manual,)N
+3194(Seventh)X
+3491(Edition,)X
+3793(Volume)X
+4085(1)X
+1 f
+(,)S
+4192(January,)X
+2878 4296(1979.)N
+2706 4472([ATT85])N
+3027(AT&T,)X
+3296(HSEARCH\(BA_LIB\),)X
+2 f
+4053(Unix)X
+4239(System)X
+2878 4560(User's)N
+3112(Manual,)X
+3401(System)X
+3644(V.3)X
+1 f
+3753(,)X
+3793(pp.)X
+3913(506-508,)X
+4220(1985.)X
+2706 4736([BRE73])N
+3025(Brent,)X
+3253(Richard)X
+3537(P.,)X
+3651(``Reducing)X
+4041(the)X
+4168(Retrieval)X
+2878 4824(Time)N
+3071(of)X
+3162(Scatter)X
+3409(Storage)X
+3678(Techniques'',)X
+2 f
+4146(Commun-)X
+2878 4912(ications)N
+3175(of)X
+3281(the)X
+3422(ACM)X
+1 f
+3591(,)X
+3654(Volume)X
+3955(16,)X
+4098(No.)X
+4259(2,)X
+4362(pp.)X
+2878 5000(105-109,)N
+3185(February,)X
+3515(1973.)X
+2706 5176([BSD86])N
+3055(NDBM\(3\),)X
+2 f
+3469(4.3BSD)X
+3775(Unix)X
+3990(Programmer's)X
+2878 5264(Manual)N
+3155(Reference)X
+3505(Guide)X
+1 f
+3701(,)X
+3749(University)X
+4114(of)X
+4208(Califor-)X
+2878 5352(nia,)N
+3016(Berkeley,)X
+3346(1986.)X
+2706 5528([ENB88])N
+3025(Enbody,)X
+3319(R.)X
+3417(J.,)X
+3533(Du,)X
+3676(H.)X
+3779(C.,)X
+3897(``Dynamic)X
+4270(Hash-)X
+2878 5616(ing)N
+3034(Schemes'',)X
+2 f
+3427(ACM)X
+3630(Computing)X
+4019(Surveys)X
+1 f
+4269(,)X
+4322(Vol.)X
+2878 5704(20,)N
+2998(No.)X
+3136(2,)X
+3216(pp.)X
+3336(85-113,)X
+3603(June)X
+3770(1988.)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4384(11)X
+
+12 p
+%%Page: 12 12
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+432 538([FAG79])N
+776(Ronald)X
+1057(Fagin,)X
+1308(Jurg)X
+1495(Nievergelt,)X
+1903(Nicholas)X
+604 626(Pippenger,)N
+1003(H.)X
+1135(Raymond)X
+1500(Strong,)X
+1787(``Extendible)X
+604 714(Hashing)N
+901(--)X
+985(A)X
+1073(Fast)X
+1236(Access)X
+1493(Method)X
+1771(for)X
+1894(Dynamic)X
+604 802(Files'',)N
+2 f
+855(ACM)X
+1046(Transactions)X
+1485(on)X
+1586(Database)X
+1914(Systems)X
+1 f
+2168(,)X
+604 890(Volume)N
+882(4,)X
+962(No.)X
+1100(3.,)X
+1200(September)X
+1563(1979,)X
+1763(pp)X
+1863(315-34)X
+432 1066([KNU68],)N
+802(Knuth,)X
+1064(D.E.,)X
+2 f
+1273(The)X
+1434(Art)X
+1577(of)X
+1680(Computer)X
+2041(Pro-)X
+604 1154(gramming)N
+971(Vol.)X
+1140(3:)X
+1245(Sorting)X
+1518(and)X
+1676(Searching)X
+1 f
+2001(,)X
+2058(sec-)X
+604 1242(tions)N
+779(6.3-6.4,)X
+1046(pp)X
+1146(481-550.)X
+432 1418([LAR78])N
+747(Larson,)X
+1011(Per-Ake,)X
+1319(``Dynamic)X
+1687(Hashing'',)X
+2 f
+2048(BIT)X
+1 f
+(,)S
+604 1506(Vol.)N
+764(18,)X
+884(1978,)X
+1084(pp.)X
+1204(184-201.)X
+432 1682([LAR88])N
+752(Larson,)X
+1021(Per-Ake,)X
+1335(``Dynamic)X
+1709(Hash)X
+1900(Tables'',)X
+2 f
+604 1770(Communications)N
+1183(of)X
+1281(the)X
+1415(ACM)X
+1 f
+1584(,)X
+1640(Volume)X
+1934(31,)X
+2070(No.)X
+604 1858(4.,)N
+704(April)X
+893(1988,)X
+1093(pp)X
+1193(446-457.)X
+432 2034([LIT80])N
+731(Witold,)X
+1013(Litwin,)X
+1286(``Linear)X
+1590(Hashing:)X
+1939(A)X
+2036(New)X
+604 2122(Tool)N
+786(for)X
+911(File)X
+1065(and)X
+1211(Table)X
+1424(Addressing'',)X
+2 f
+1893(Proceed-)X
+604 2210(ings)N
+761(of)X
+847(the)X
+969(6th)X
+1095(International)X
+1540(Conference)X
+1933(on)X
+2036(Very)X
+604 2298(Large)N
+815(Databases)X
+1 f
+1153(,)X
+1193(1980.)X
+432 2474([NEL90])N
+743(Nelson,)X
+1011(Philip)X
+1222(A.,)X
+2 f
+1341(Gdbm)X
+1558(1.4)X
+1679(source)X
+1913(distribu-)X
+604 2562(tion)N
+748(and)X
+888(README)X
+1 f
+1209(,)X
+1249(August)X
+1500(1990.)X
+432 2738([THOM90])N
+840(Ken)X
+1011(Thompson,)X
+1410(private)X
+1670(communication,)X
+604 2826(Nov.)N
+782(1990.)X
+432 3002([TOR87])N
+790(Torek,)X
+1066(C.,)X
+1222(``Re:)X
+1470(dbm.a)X
+1751(and)X
+1950(ndbm.a)X
+604 3090(archives'',)N
+2 f
+966(USENET)X
+1279(newsgroup)X
+1650(comp.unix)X
+1 f
+2002(1987.)X
+432 3266([TOR88])N
+760(Torek,)X
+1006(C.,)X
+1133(``Re:)X
+1351(questions)X
+1686(regarding)X
+2027(data-)X
+604 3354(bases)N
+826(created)X
+1106(with)X
+1295(dbm)X
+1484(and)X
+1647(ndbm)X
+1876(routines'')X
+2 f
+604 3442(USENET)N
+937(newsgroup)X
+1328(comp.unix.questions)X
+1 f
+1982(,)X
+2041(June)X
+604 3530(1988.)N
+432 3706([WAL84])N
+773(Wales,)X
+1018(R.,)X
+1135(``Discussion)X
+1564(of)X
+1655("dbm")X
+1887(data)X
+2045(base)X
+604 3794(system'',)N
+2 f
+973(USENET)X
+1339(newsgroup)X
+1762(unix.wizards)X
+1 f
+2168(,)X
+604 3882(January,)N
+894(1984.)X
+432 4058([YIG89])N
+751(Ozan)X
+963(S.)X
+1069(Yigit,)X
+1294(``How)X
+1545(to)X
+1648(Roll)X
+1826(Your)X
+2032(Own)X
+604 4146(Dbm/Ndbm'',)N
+2 f
+1087(unpublished)X
+1504(manuscript)X
+1 f
+(,)S
+1910(Toronto,)X
+604 4234(July,)N
+777(1989)X
+3 f
+432 5960(12)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+13 p
+%%Page: 13 13
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(Margo)N
+960(I.)X
+1033(Seltzer)X
+1282(is)X
+1361(a)X
+1423(Ph.D.)X
+1631(student)X
+1887(in)X
+1974(the)X
+2097(Department)X
+720 626(of)N
+823(Electrical)X
+1167(Engineering)X
+1595(and)X
+1747(Computer)X
+2102(Sciences)X
+2418(at)X
+720 714(the)N
+850(University)X
+1220(of)X
+1318(California,)X
+1694(Berkeley.)X
+2055(Her)X
+2207(research)X
+720 802(interests)N
+1017(include)X
+1283(\256le)X
+1415(systems,)X
+1718(databases,)X
+2076(and)X
+2221(transac-)X
+720 890(tion)N
+896(processing)X
+1291(systems.)X
+1636(She)X
+1807(spent)X
+2027(several)X
+2306(years)X
+720 978(working)N
+1026(at)X
+1123(startup)X
+1380(companies)X
+1762(designing)X
+2112(and)X
+2267(imple-)X
+720 1066(menting)N
+1048(\256le)X
+1216(systems)X
+1535(and)X
+1716(transaction)X
+2133(processing)X
+720 1154(software)N
+1026(and)X
+1170(designing)X
+1509(microprocessors.)X
+2103(Ms.)X
+2253(Seltzer)X
+720 1242(received)N
+1057(her)X
+1223(AB)X
+1397(in)X
+1522(Applied)X
+1843(Mathematics)X
+2320(from)X
+720 1330 0.1953(Harvard/Radcliffe)AN
+1325(College)X
+1594(in)X
+1676(1983.)X
+720 1444(In)N
+810(her)X
+936(spare)X
+1129(time,)X
+1313(Margo)X
+1549(can)X
+1683(usually)X
+1936(be)X
+2034(found)X
+2243(prepar-)X
+720 1532(ing)N
+868(massive)X
+1171(quantities)X
+1527(of)X
+1639(food)X
+1831(for)X
+1970(hungry)X
+2242(hoards,)X
+720 1620(studying)N
+1022(Japanese,)X
+1355(or)X
+1449(playing)X
+1716(soccer)X
+1948(with)X
+2116(an)X
+2218(exciting)X
+720 1708(Bay)N
+912(Area)X
+1132(Women's)X
+1507(Soccer)X
+1788(team,)X
+2026(the)X
+2186(Berkeley)X
+720 1796(Bruisers.)N
+720 1910(Ozan)N
+915(\()X
+3 f
+942(Oz)X
+1 f
+1040(\))X
+1092(Yigit)X
+1281(is)X
+1358(currently)X
+1672(a)X
+1732(software)X
+2033(engineer)X
+2334(with)X
+720 1998(the)N
+886(Communications)X
+1499(Research)X
+1861(and)X
+2044(Development)X
+720 2086(group,)N
+948(Computing)X
+1328(Services,)X
+1641(York)X
+1826(University.)X
+2224(His)X
+2355(for-)X
+720 2174(mative)N
+967(years)X
+1166(were)X
+1352(also)X
+1510(spent)X
+1708(at)X
+1795(York,)X
+2009(where)X
+2234(he)X
+2338(held)X
+720 2262(system)N
+985(programmer)X
+1425(and)X
+1583(administrator)X
+2052(positions)X
+2382(for)X
+720 2350(various)N
+995(mixtures)X
+1314(of)X
+1420(of)X
+1526(UNIX)X
+1765(systems)X
+2056(starting)X
+2334(with)X
+720 2438(Berkeley)N
+1031(4.1)X
+1151(in)X
+1233(1982,)X
+1433(while)X
+1631(at)X
+1709(the)X
+1827(same)X
+2012(time)X
+2174(obtaining)X
+720 2526(a)N
+776(degree)X
+1011(in)X
+1093(Computer)X
+1433(Science.)X
+720 2640(In)N
+813(his)X
+931(copious)X
+1205(free)X
+1356(time,)X
+1543(Oz)X
+1662(enjoys)X
+1896(working)X
+2188(on)X
+2293(what-)X
+720 2728(ever)N
+890(software)X
+1197(looks)X
+1400(interesting,)X
+1788(which)X
+2014(often)X
+2209(includes)X
+720 2816(language)N
+1044(interpreters,)X
+1464(preprocessors,)X
+1960(and)X
+2110(lately,)X
+2342(pro-)X
+720 2904(gram)N
+905(generators)X
+1260(and)X
+1396(expert)X
+1617(systems.)X
+720 3018(Oz)N
+836(has)X
+964(authored)X
+1266(several)X
+1515(public-domain)X
+2003(software)X
+2301(tools,)X
+720 3106(including)N
+1069(an)X
+1191(nroff-like)X
+1545(text)X
+1711(formatter)X
+2 f
+2056(proff)X
+1 f
+2257(that)X
+2423(is)X
+720 3194(apparently)N
+1083(still)X
+1226(used)X
+1397(in)X
+1483(some)X
+1676(basement)X
+2002(PCs.)X
+2173(His)X
+2307(latest)X
+720 3282(obsessions)N
+1143(include)X
+1460(the)X
+1639(incredible)X
+2040(programming)X
+720 3370(language)N
+1030(Scheme,)X
+1324(and)X
+1460(Chinese)X
+1738(Brush)X
+1949(painting.)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4384(13)X
+
+14 p
+%%Page: 14 14
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 5960(14)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+14 p
+%%Trailer
+xt
+
+xs
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/libtp.usenix.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/libtp.usenix.ps
new file mode 100644
index 000000000..5b5ba6e1b
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/libtp.usenix.ps
@@ -0,0 +1,12340 @@
+%!PS-Adobe-1.0
+%%Creator: utopia:margo (& Seltzer,608-13E,8072,)
+%%Title: stdin (ditroff)
+%%CreationDate: Thu Dec 12 15:32:11 1991
+%%EndComments
+%	@(#)psdit.pro	1.3 4/15/88
+% lib/psdit.pro -- prolog for psdit (ditroff) files
+% Copyright (c) 1984, 1985 Adobe Systems Incorporated. All Rights Reserved.
+% last edit: shore Sat Nov 23 20:28:03 1985
+% RCSID: $Header$
+
+% Changed by Edward Wang (edward@ucbarpa.berkeley.edu) to handle graphics,
+% 17 Feb, 87.
+
+/$DITroff 140 dict def $DITroff begin
+/fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def
+/xi{0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto
+ /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F
+ /pagesave save def}def
+/PB{save /psv exch def currentpoint translate 
+ resolution 72 div dup neg scale 0 0 moveto}def
+/PE{psv restore}def
+/arctoobig 90 def /arctoosmall .05 def
+/m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def
+/tan{dup sin exch cos div}def
+/point{resolution 72 div mul}def
+/dround	{transform round exch round exch itransform}def
+/xT{/devname exch def}def
+/xr{/mh exch def /my exch def /resolution exch def}def
+/xp{}def
+/xs{docsave restore end}def
+/xt{}def
+/xf{/fontname exch def /slotno exch def fontnames slotno get fontname eq not
+ {fonts slotno fontname findfont put fontnames slotno fontname put}if}def
+/xH{/fontheight exch def F}def
+/xS{/fontslant exch def F}def
+/s{/fontsize exch def /fontheight fontsize def F}def
+/f{/fontnum exch def F}def
+/F{fontheight 0 le{/fontheight fontsize def}if
+ fonts fontnum get fontsize point 0 0 fontheight point neg 0 0 m1 astore
+ fontslant 0 ne{1 0 fontslant tan 1 0 0 m2 astore m3 concatmatrix}if
+ makefont setfont .04 fontsize point mul 0 dround pop setlinewidth}def
+/X{exch currentpoint exch pop moveto show}def
+/N{3 1 roll moveto show}def
+/Y{exch currentpoint pop exch moveto show}def
+/S{show}def
+/ditpush{}def/ditpop{}def
+/AX{3 -1 roll currentpoint exch pop moveto 0 exch ashow}def
+/AN{4 2 roll moveto 0 exch ashow}def
+/AY{3 -1 roll currentpoint pop exch moveto 0 exch ashow}def
+/AS{0 exch ashow}def
+/MX{currentpoint exch pop moveto}def
+/MY{currentpoint pop exch moveto}def
+/MXY{moveto}def
+/cb{pop}def	% action on unknown char -- nothing for now
+/n{}def/w{}def
+/p{pop showpage pagesave restore /pagesave save def}def
+/Dt{/Dlinewidth exch def}def 1 Dt
+/Ds{/Ddash exch def}def -1 Ds
+/Di{/Dstipple exch def}def 1 Di
+/Dsetlinewidth{2 Dlinewidth mul setlinewidth}def
+/Dsetdash{Ddash 4 eq{[8 12]}{Ddash 16 eq{[32 36]}
+ {Ddash 20 eq{[32 12 8 12]}{[]}ifelse}ifelse}ifelse 0 setdash}def
+/Dstroke{gsave Dsetlinewidth Dsetdash 1 setlinecap stroke grestore
+ currentpoint newpath moveto}def
+/Dl{rlineto Dstroke}def
+/arcellipse{/diamv exch def /diamh exch def oldmat currentmatrix pop
+ currentpoint translate 1 diamv diamh div scale /rad diamh 2 div def
+ currentpoint exch rad add exch rad -180 180 arc oldmat setmatrix}def
+/Dc{dup arcellipse Dstroke}def
+/De{arcellipse Dstroke}def
+/Da{/endv exch def /endh exch def /centerv exch def /centerh exch def
+ /cradius centerv centerv mul centerh centerh mul add sqrt def
+ /eradius endv endv mul endh endh mul add sqrt def
+ /endang endv endh atan def
+ /startang centerv neg centerh neg atan def
+ /sweep startang endang sub dup 0 lt{360 add}if def
+ sweep arctoobig gt
+ {/midang startang sweep 2 div sub def /midrad cradius eradius add 2 div def
+  /midh midang cos midrad mul def /midv midang sin midrad mul def
+  midh neg midv neg endh endv centerh centerv midh midv Da
+  Da}
+ {sweep arctoosmall ge
+  {/controldelt 1 sweep 2 div cos sub 3 sweep 2 div sin mul div 4 mul def
+   centerv neg controldelt mul centerh controldelt mul
+   endv neg controldelt mul centerh add endh add
+   endh controldelt mul centerv add endv add
+   centerh endh add centerv endv add rcurveto Dstroke}
+  {centerh endh add centerv endv add rlineto Dstroke}
+  ifelse}
+ ifelse}def
+/Dpatterns[
+[%cf[widthbits]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000103810000000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000001038100000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0042660000246600>]
+[8<0000990000990000>]
+[8<0804020180402010>]
+[8<2418814242811824>]
+[8<6699996666999966>]
+[8<8000000008000000>]
+[8<00001c3e363e1c00>]
+[8<0000000000000000>]
+[32<00000040000000c00000004000000040000000e0000000000000000000000000>]
+[32<00000000000060000000900000002000000040000000f0000000000000000000>]
+[32<000000000000000000e0000000100000006000000010000000e0000000000000>]
+[32<00000000000000002000000060000000a0000000f00000002000000000000000>]
+[32<0000000e0000000000000000000000000000000f000000080000000e00000001>]
+[32<0000090000000600000000000000000000000000000007000000080000000e00>]
+[32<00010000000200000004000000040000000000000000000000000000000f0000>]
+[32<0900000006000000090000000600000000000000000000000000000006000000>]]
+[%ug
+[8<0000020000000000>]
+[8<0000020000002000>]
+[8<0004020000002000>]
+[8<0004020000402000>]
+[8<0004060000402000>]
+[8<0004060000406000>]
+[8<0006060000406000>]
+[8<0006060000606000>]
+[8<00060e0000606000>]
+[8<00060e000060e000>]
+[8<00070e000060e000>]
+[8<00070e000070e000>]
+[8<00070e020070e000>]
+[8<00070e020070e020>]
+[8<04070e020070e020>]
+[8<04070e024070e020>]
+[8<04070e064070e020>]
+[8<04070e064070e060>]
+[8<06070e064070e060>]
+[8<06070e066070e060>]
+[8<06070f066070e060>]
+[8<06070f066070f060>]
+[8<060f0f066070f060>]
+[8<060f0f0660f0f060>]
+[8<060f0f0760f0f060>]
+[8<060f0f0760f0f070>]
+[8<0e0f0f0760f0f070>]
+[8<0e0f0f07e0f0f070>]
+[8<0e0f0f0fe0f0f070>]
+[8<0e0f0f0fe0f0f0f0>]
+[8<0f0f0f0fe0f0f0f0>]
+[8<0f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f1f9>]
+[8<bf8f1f9ff9f8f1f9>]
+[8<bf8f1f9ffbf8f1f9>]
+[8<bf8f1fdffbf8f1f9>]
+[8<bf8f1fdffbf8f1fd>]
+[8<ff8f1fdffbf8f1fd>]
+[8<ff8f1fdffff8f1fd>]
+[8<ff8f1ffffff8f1fd>]
+[8<ff8f1ffffff8f1ff>]
+[8<ff9f1ffffff8f1ff>]
+[8<ff9f1ffffff9f1ff>]
+[8<ff9f9ffffff9f1ff>]
+[8<ff9f9ffffff9f9ff>]
+[8<ffbf9ffffff9f9ff>]
+[8<ffbf9ffffffbf9ff>]
+[8<ffbfdffffffbf9ff>]
+[8<ffbfdffffffbfdff>]
+[8<ffffdffffffbfdff>]
+[8<ffffdffffffffdff>]
+[8<fffffffffffffdff>]
+[8<ffffffffffffffff>]]
+[%mg
+[8<8000000000000000>]
+[8<0822080080228000>]
+[8<0204081020408001>]
+[8<40e0400000000000>]
+[8<66999966>]
+[8<8001000010080000>]
+[8<81c36666c3810000>]
+[8<f0e0c08000000000>]
+[16<07c00f801f003e007c00f800f001e003c007800f001f003e007c00f801f003e0>]
+[16<1f000f8007c003e001f000f8007c003e001f800fc007e003f001f8007c003e00>]
+[8<c3c300000000c3c3>]
+[16<0040008001000200040008001000200040008000000100020004000800100020>]
+[16<0040002000100008000400020001800040002000100008000400020001000080>]
+[16<1fc03fe07df0f8f8f07de03fc01f800fc01fe03ff07df8f87df03fe01fc00f80>]
+[8<80>]
+[8<8040201000000000>]
+[8<84cc000048cc0000>]
+[8<9900009900000000>]
+[8<08040201804020100800020180002010>]
+[8<2418814242811824>]
+[8<66999966>]
+[8<8000000008000000>]
+[8<70f8d8f870000000>]
+[8<0814224180402010>]
+[8<aa00440a11a04400>]
+[8<018245aa45820100>]
+[8<221c224180808041>]
+[8<88000000>]
+[8<0855800080550800>]
+[8<2844004482440044>]
+[8<0810204080412214>]
+[8<00>]]]def
+/Dfill{
+ transform /maxy exch def /maxx exch def
+ transform /miny exch def /minx exch def
+ minx maxx gt{/minx maxx /maxx minx def def}if
+ miny maxy gt{/miny maxy /maxy miny def def}if
+ Dpatterns Dstipple 1 sub get exch 1 sub get
+ aload pop /stip exch def /stipw exch def /stiph 128 def
+ /imatrix[stipw 0 0 stiph 0 0]def
+ /tmatrix[stipw 0 0 stiph 0 0]def
+ /minx minx cvi stiph idiv stiph mul def
+ /miny miny cvi stipw idiv stipw mul def
+ gsave eoclip 0 setgray
+ miny stiph maxy{
+  tmatrix exch 5 exch put
+  minx stipw maxx{
+   tmatrix exch 4 exch put tmatrix setmatrix
+   stipw stiph true imatrix {stip} imagemask
+  }for
+ }for
+ grestore
+}def
+/Dp{Dfill Dstroke}def
+/DP{Dfill currentpoint newpath moveto}def
+end
+
+/ditstart{$DITroff begin
+ /nfonts 60 def			% NFONTS makedev/ditroff dependent!
+ /fonts[nfonts{0}repeat]def
+ /fontnames[nfonts{()}repeat]def
+/docsave save def
+}def
+
+% character outcalls
+/oc{
+ /pswid exch def /cc exch def /name exch def
+ /ditwid pswid fontsize mul resolution mul 72000 div def
+ /ditsiz fontsize resolution mul 72 div def
+ ocprocs name known{ocprocs name get exec}{name cb}ifelse
+}def
+/fractm [.65 0 0 .6 0 0] def
+/fraction{
+ /fden exch def /fnum exch def gsave /cf currentfont def
+ cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
+ fnum show rmoveto currentfont cf setfont(\244)show setfont fden show 
+ grestore ditwid 0 rmoveto
+}def
+/oce{grestore ditwid 0 rmoveto}def
+/dm{ditsiz mul}def
+/ocprocs 50 dict def ocprocs begin
+(14){(1)(4)fraction}def
+(12){(1)(2)fraction}def
+(34){(3)(4)fraction}def
+(13){(1)(3)fraction}def
+(23){(2)(3)fraction}def
+(18){(1)(8)fraction}def
+(38){(3)(8)fraction}def
+(58){(5)(8)fraction}def
+(78){(7)(8)fraction}def
+(sr){gsave 0 .06 dm rmoveto(\326)show oce}def
+(is){gsave 0 .15 dm rmoveto(\362)show oce}def
+(->){gsave 0 .02 dm rmoveto(\256)show oce}def
+(<-){gsave 0 .02 dm rmoveto(\254)show oce}def
+(==){gsave 0 .05 dm rmoveto(\272)show oce}def
+(uc){gsave currentpoint 400 .009 dm mul add translate
+     8 -8 scale ucseal oce}def
+end
+
+% an attempt at a PostScript FONT to implement ditroff special chars
+% this will enable us to 
+%	cache the little buggers
+%	generate faster, more compact PS out of psdit
+%	confuse everyone (including myself)!
+50 dict dup begin
+/FontType 3 def
+/FontName /DIThacks def
+/FontMatrix [.001 0 0 .001 0 0] def
+/FontBBox [-260 -260 900 900] def% a lie but ...
+/Encoding 256 array def
+0 1 255{Encoding exch /.notdef put}for
+Encoding
+ dup 8#040/space put %space
+ dup 8#110/rc put %right ceil
+ dup 8#111/lt put %left  top curl
+ dup 8#112/bv put %bold vert
+ dup 8#113/lk put %left  mid curl
+ dup 8#114/lb put %left  bot curl
+ dup 8#115/rt put %right top curl
+ dup 8#116/rk put %right mid curl
+ dup 8#117/rb put %right bot curl
+ dup 8#120/rf put %right floor
+ dup 8#121/lf put %left  floor
+ dup 8#122/lc put %left  ceil
+ dup 8#140/sq put %square
+ dup 8#141/bx put %box
+ dup 8#142/ci put %circle
+ dup 8#143/br put %box rule
+ dup 8#144/rn put %root extender
+ dup 8#145/vr put %vertical rule
+ dup 8#146/ob put %outline bullet
+ dup 8#147/bu put %bullet
+ dup 8#150/ru put %rule
+ dup 8#151/ul put %underline
+ pop
+/DITfd 100 dict def
+/BuildChar{0 begin
+ /cc exch def /fd exch def
+ /charname fd /Encoding get cc get def
+ /charwid fd /Metrics get charname get def
+ /charproc fd /CharProcs get charname get def
+ charwid 0 fd /FontBBox get aload pop setcachedevice
+ 2 setlinejoin 40 setlinewidth
+ newpath 0 0 moveto gsave charproc grestore
+ end}def
+/BuildChar load 0 DITfd put
+/CharProcs 50 dict def
+CharProcs begin
+/space{}def
+/.notdef{}def
+/ru{500 0 rls}def
+/rn{0 840 moveto 500 0 rls}def
+/vr{0 800 moveto 0 -770 rls}def
+/bv{0 800 moveto 0 -1000 rls}def
+/br{0 840 moveto 0 -1000 rls}def
+/ul{0 -140 moveto 500 0 rls}def
+/ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
+/bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
+/sq{80 0 rmoveto currentpoint dround newpath moveto
+    640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
+/bx{80 0 rmoveto currentpoint dround newpath moveto
+    640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
+/ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
+    50 setlinewidth stroke}def
+
+/lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
+/lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
+/rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
+/rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
+/lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
+    0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
+    0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
+/rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
+/lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
+/rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
+end
+
+/Metrics 50 dict def Metrics begin
+/.notdef 0 def
+/space 500 def
+/ru 500 def
+/br 0 def
+/lt 416 def
+/lb 416 def
+/rt 416 def
+/rb 416 def
+/lk 416 def
+/rk 416 def
+/rc 416 def
+/lc 416 def
+/rf 416 def
+/lf 416 def
+/bv 416 def
+/ob 350 def
+/bu 350 def
+/ci 750 def
+/bx 750 def
+/sq 750 def
+/rn 500 def
+/ul 500 def
+/vr 0 def
+end
+
+DITfd begin
+/s2 500 def /s4 250 def /s3 333 def
+/a4p{arcto pop pop pop pop}def
+/2cx{2 copy exch}def
+/rls{rlineto stroke}def
+/currx{currentpoint pop}def
+/dround{transform round exch round exch itransform} def
+end
+end
+/DIThacks exch definefont pop
+ditstart
+(psc)xT
+576 1 1 xr
+1(Times-Roman)xf 1 f
+2(Times-Italic)xf 2 f
+3(Times-Bold)xf 3 f
+4(Times-BoldItalic)xf 4 f
+5(Helvetica)xf 5 f
+6(Helvetica-Bold)xf 6 f
+7(Courier)xf 7 f
+8(Courier-Bold)xf 8 f
+9(Symbol)xf 9 f
+10(DIThacks)xf 10 f
+10 s
+1 f
+xi
+%%EndProlog
+
+%%Page: 1 1
+10 s 10 xH 0 xS 1 f
+3 f
+14 s
+1205 1206(LIBTP:)N
+1633(Portable,)X
+2100(M)X
+2206(odular)X
+2551(Transactions)X
+3202(for)X
+3374(UNIX)X
+1 f
+11 s
+3661 1162(1)N
+2 f
+12 s
+2182 1398(Margo)N
+2467(Seltzer)X
+2171 1494(Michael)N
+2511(Olson)X
+1800 1590(University)N
+2225(of)X
+2324(California,)X
+2773(Berkeley)X
+3 f
+2277 1878(Abstract)N
+1 f
+10 s
+755 2001(Transactions)N
+1198(provide)X
+1475(a)X
+1543(useful)X
+1771(programming)X
+2239(paradigm)X
+2574(for)X
+2700(maintaining)X
+3114(logical)X
+3364(consistency,)X
+3790(arbitrating)X
+4156(con-)X
+555 2091(current)N
+808(access,)X
+1059(and)X
+1200(managing)X
+1540(recovery.)X
+1886(In)X
+1977(traditional)X
+2330(UNIX)X
+2555(systems,)X
+2852(the)X
+2974(only)X
+3140(easy)X
+3307(way)X
+3465(of)X
+3556(using)X
+3753(transactions)X
+4160(is)X
+4237(to)X
+555 2181(purchase)N
+876(a)X
+947(database)X
+1258(system.)X
+1554(Such)X
+1748(systems)X
+2035(are)X
+2168(often)X
+2367(slow,)X
+2572(costly,)X
+2817(and)X
+2967(may)X
+3139(not)X
+3275(provide)X
+3554(the)X
+3686(exact)X
+3890(functionality)X
+555 2271(desired.)N
+848(This)X
+1011(paper)X
+1210(presents)X
+1493(the)X
+1611(design,)X
+1860(implementation,)X
+2402(and)X
+2538(performance)X
+2965(of)X
+3052(LIBTP,)X
+3314(a)X
+3370(simple,)X
+3623(non-proprietary)X
+4147(tran-)X
+555 2361(saction)N
+809(library)X
+1050(using)X
+1249(the)X
+1373(4.4BSD)X
+1654(database)X
+1957(access)X
+2189(routines)X
+2473(\()X
+3 f
+2500(db)X
+1 f
+2588(\(3\)\).)X
+2775(On)X
+2899(a)X
+2961(conventional)X
+3401(transaction)X
+3779(processing)X
+4148(style)X
+555 2451(benchmark,)N
+959(its)X
+1061(performance)X
+1495(is)X
+1575(approximately)X
+2065(85%)X
+2239(that)X
+2386(of)X
+2480(the)X
+2604(database)X
+2907(access)X
+3139(routines)X
+3423(without)X
+3693(transaction)X
+4071(protec-)X
+555 2541(tion,)N
+725(200%)X
+938(that)X
+1084(of)X
+1177(using)X
+3 f
+1376(fsync)X
+1 f
+1554(\(2\))X
+1674(to)X
+1761(commit)X
+2030(modi\256cations)X
+2490(to)X
+2577(disk,)X
+2755(and)X
+2896(125%)X
+3108(that)X
+3253(of)X
+3345(a)X
+3406(commercial)X
+3810(relational)X
+4138(data-)X
+555 2631(base)N
+718(system.)X
+3 f
+555 2817(1.)N
+655(Introduction)X
+1 f
+755 2940(Transactions)N
+1186(are)X
+1306(used)X
+1474(in)X
+1557(database)X
+1855(systems)X
+2129(to)X
+2212(enable)X
+2443(concurrent)X
+2807(users)X
+2992(to)X
+3074(apply)X
+3272(multi-operation)X
+3790(updates)X
+4055(without)X
+555 3030(violating)N
+863(the)X
+985(integrity)X
+1280(of)X
+1371(the)X
+1493(database.)X
+1814(They)X
+2003(provide)X
+2271(the)X
+2392(properties)X
+2736(of)X
+2826(atomicity,)X
+3171(consistency,)X
+3588(isolation,)X
+3906(and)X
+4045(durabil-)X
+555 3120(ity.)N
+701(By)X
+816(atomicity,)X
+1160(we)X
+1276(mean)X
+1472(that)X
+1614(the)X
+1734(set)X
+1845(of)X
+1934(updates)X
+2200(comprising)X
+2581(a)X
+2638(transaction)X
+3011(must)X
+3187(be)X
+3284(applied)X
+3541(as)X
+3629(a)X
+3686(single)X
+3898(unit;)X
+4085(that)X
+4226(is,)X
+555 3210(they)N
+714(must)X
+890(either)X
+1094(all)X
+1195(be)X
+1292(applied)X
+1549(to)X
+1632(the)X
+1751(database)X
+2049(or)X
+2137(all)X
+2238(be)X
+2335(absent.)X
+2601(Consistency)X
+3013(requires)X
+3293(that)X
+3434(a)X
+3491(transaction)X
+3864(take)X
+4019(the)X
+4138(data-)X
+555 3300(base)N
+725(from)X
+908(one)X
+1051(logically)X
+1358(consistent)X
+1704(state)X
+1877(to)X
+1965(another.)X
+2272(The)X
+2423(property)X
+2721(of)X
+2814(isolation)X
+3115(requires)X
+3400(that)X
+3546(concurrent)X
+3916(transactions)X
+555 3390(yield)N
+750(results)X
+994(which)X
+1225(are)X
+1358(indistinguishable)X
+1938(from)X
+2128(the)X
+2260(results)X
+2503(which)X
+2733(would)X
+2967(be)X
+3077(obtained)X
+3387(by)X
+3501(running)X
+3784(the)X
+3916(transactions)X
+555 3480(sequentially.)N
+1002(Finally,)X
+1268(durability)X
+1599(requires)X
+1878(that)X
+2018(once)X
+2190(transactions)X
+2593(have)X
+2765(been)X
+2937(committed,)X
+3319(their)X
+3486(results)X
+3715(must)X
+3890(be)X
+3986(preserved)X
+555 3570(across)N
+776(system)X
+1018(failures)X
+1279([TPCB90].)X
+755 3693(Although)N
+1080(these)X
+1268(properties)X
+1612(are)X
+1734(most)X
+1912(frequently)X
+2265(discussed)X
+2595(in)X
+2680(the)X
+2801(context)X
+3060(of)X
+3150(databases,)X
+3501(they)X
+3661(are)X
+3782(useful)X
+4000(program-)X
+555 3783(ming)N
+750(paradigms)X
+1114(for)X
+1238(more)X
+1433(general)X
+1700(purpose)X
+1984(applications.)X
+2441(There)X
+2659(are)X
+2788(several)X
+3046(different)X
+3353(situations)X
+3689(where)X
+3916(transactions)X
+555 3873(can)N
+687(be)X
+783(used)X
+950(to)X
+1032(replace)X
+1285(current)X
+1533(ad-hoc)X
+1772(mechanisms.)X
+755 3996(One)N
+910(situation)X
+1206(is)X
+1280(when)X
+1475(multiple)X
+1762(\256les)X
+1916(or)X
+2004(parts)X
+2181(of)X
+2269(\256les)X
+2422(need)X
+2594(to)X
+2676(be)X
+2772(updated)X
+3046(in)X
+3128(an)X
+3224(atomic)X
+3462(fashion.)X
+3758(For)X
+3889(example,)X
+4201(the)X
+555 4086(traditional)N
+907(UNIX)X
+1131(\256le)X
+1256(system)X
+1501(uses)X
+1661(ordering)X
+1955(constraints)X
+2324(to)X
+2408(achieve)X
+2676(recoverability)X
+3144(in)X
+3228(the)X
+3348(face)X
+3505(of)X
+3594(crashes.)X
+3893(When)X
+4107(a)X
+4165(new)X
+555 4176(\256le)N
+678(is)X
+752(created,)X
+1026(its)X
+1122(inode)X
+1321(is)X
+1395(written)X
+1642(to)X
+1724(disk)X
+1877(before)X
+2103(the)X
+2221(new)X
+2375(\256le)X
+2497(is)X
+2570(added)X
+2782(to)X
+2864(the)X
+2982(directory)X
+3292(structure.)X
+3633(This)X
+3795(guarantees)X
+4159(that,)X
+555 4266(if)N
+627(the)X
+748(system)X
+993(crashes)X
+1253(between)X
+1544(the)X
+1665(two)X
+1808(I/O's,)X
+2016(the)X
+2137(directory)X
+2450(does)X
+2620(not)X
+2744(contain)X
+3002(a)X
+3060 0.4531(reference)AX
+3383(to)X
+3467(an)X
+3565(invalid)X
+3809(inode.)X
+4049(In)X
+4138(actu-)X
+555 4356(ality,)N
+741(the)X
+863(desired)X
+1119(effect)X
+1326(is)X
+1402(that)X
+1545(these)X
+1733(two)X
+1876(updates)X
+2144(have)X
+2319(the)X
+2440(transactional)X
+2873(property)X
+3168(of)X
+3258(atomicity)X
+3583(\(either)X
+3816(both)X
+3981(writes)X
+4200(are)X
+555 4446(visible)N
+790(or)X
+879(neither)X
+1124(is\).)X
+1266(Rather)X
+1501(than)X
+1660(building)X
+1947(special)X
+2191(purpose)X
+2466(recovery)X
+2769(mechanisms)X
+3186(into)X
+3331(the)X
+3450(\256le)X
+3573(system)X
+3816(or)X
+3904(related)X
+4144(tools)X
+555 4536(\()N
+2 f
+582(e.g.)X
+3 f
+726(fsck)X
+1 f
+864(\(8\)\),)X
+1033(one)X
+1177(could)X
+1383(use)X
+1518(general)X
+1783(purpose)X
+2064(transaction)X
+2443(recovery)X
+2752(protocols)X
+3077(after)X
+3252(system)X
+3501(failure.)X
+3778(Any)X
+3943(application)X
+555 4626(that)N
+705(needs)X
+918(to)X
+1010(keep)X
+1192(multiple,)X
+1508(related)X
+1757(\256les)X
+1920(\(or)X
+2044(directories\))X
+2440(consistent)X
+2790(should)X
+3032(do)X
+3141(so)X
+3241(using)X
+3443(transactions.)X
+3895(Source)X
+4147(code)X
+555 4716(control)N
+805(systems,)X
+1101(such)X
+1271(as)X
+1361(RCS)X
+1534(and)X
+1673(SCCS,)X
+1910(should)X
+2146(use)X
+2276(transaction)X
+2651(semantics)X
+2990(to)X
+3075(allow)X
+3276(the)X
+3397(``checking)X
+3764(in'')X
+3903(of)X
+3992(groups)X
+4232(of)X
+555 4806(related)N
+801(\256les.)X
+1001(In)X
+1095(this)X
+1237(way,)X
+1418(if)X
+1493(the)X
+1617 0.2841(``check-in'')AX
+2028(fails,)X
+2212(the)X
+2336(transaction)X
+2714(may)X
+2878(be)X
+2980(aborted,)X
+3267(backing)X
+3547(out)X
+3675(the)X
+3799(partial)X
+4030(``check-)X
+555 4896(in'')N
+691(leaving)X
+947(the)X
+1065(source)X
+1295(repository)X
+1640(in)X
+1722(a)X
+1778(consistent)X
+2118(state.)X
+755 5019(A)N
+842(second)X
+1094(situation)X
+1398(where)X
+1624(transactions)X
+2036(can)X
+2177(be)X
+2282(used)X
+2458(to)X
+2549(replace)X
+2811(current)X
+3068(ad-hoc)X
+3316(mechanisms)X
+3741(is)X
+3822(in)X
+3912(applications)X
+555 5109(where)N
+776(concurrent)X
+1144(updates)X
+1413(to)X
+1499(a)X
+1559(shared)X
+1793(\256le)X
+1919(are)X
+2042(desired,)X
+2318(but)X
+2444(there)X
+2629(is)X
+2706(logical)X
+2948(consistency)X
+3345(of)X
+3435(the)X
+3556(data)X
+3713(which)X
+3932(needs)X
+4138(to)X
+4223(be)X
+555 5199(preserved.)N
+928(For)X
+1059(example,)X
+1371(when)X
+1565(the)X
+1683(password)X
+2006(\256le)X
+2128(is)X
+2201(updated,)X
+2495(\256le)X
+2617(locking)X
+2877(is)X
+2950(used)X
+3117(to)X
+3199(disallow)X
+3490(concurrent)X
+3854(access.)X
+4120(Tran-)X
+555 5289(saction)N
+804(semantics)X
+1142(on)X
+1244(the)X
+1364(password)X
+1689(\256les)X
+1844(would)X
+2066(allow)X
+2266(concurrent)X
+2632(updates,)X
+2919(while)X
+3119(preserving)X
+3479(the)X
+3598(logical)X
+3837(consistency)X
+4232(of)X
+555 5379(the)N
+681(password)X
+1012(database.)X
+1357(Similarly,)X
+1702(UNIX)X
+1930(utilities)X
+2196(which)X
+2419(rewrite)X
+2674(\256les)X
+2834(face)X
+2996(a)X
+3059(potential)X
+3366(race)X
+3528(condition)X
+3857(between)X
+4152(their)X
+555 5469(rewriting)N
+871(a)X
+929(\256le)X
+1053(and)X
+1191(another)X
+1453(process)X
+1715(reading)X
+1977(the)X
+2096(\256le.)X
+2259(For)X
+2391(example,)X
+2704(the)X
+2823(compiler)X
+3129(\(more)X
+3342(precisely,)X
+3673(the)X
+3792(assembler\))X
+4161(may)X
+8 s
+10 f
+555 5541(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5619(1)N
+8 s
+763 5644(To)N
+850(appear)X
+1035(in)X
+1101(the)X
+2 f
+1195(Proceedings)X
+1530(of)X
+1596(the)X
+1690(1992)X
+1834(Winter)X
+2024(Usenix)X
+1 f
+2201(,)X
+2233(San)X
+2345(Francisco,)X
+2625(CA,)X
+2746(January)X
+2960(1992.)X
+
+2 p
+%%Page: 2 2
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(have)N
+737(to)X
+829(rewrite)X
+1087(a)X
+1152(\256le)X
+1283(to)X
+1374(which)X
+1599(it)X
+1672(has)X
+1808(write)X
+2002(permission)X
+2382(in)X
+2473(a)X
+2538(directory)X
+2857(to)X
+2948(which)X
+3173(it)X
+3246(does)X
+3422(not)X
+3553(have)X
+3734(write)X
+3928(permission.)X
+555 720(While)N
+779(the)X
+904(``.o'')X
+1099(\256le)X
+1228(is)X
+1308(being)X
+1513(written,)X
+1787(another)X
+2055(utility)X
+2272(such)X
+2446(as)X
+3 f
+2540(nm)X
+1 f
+2651(\(1\))X
+2772(or)X
+3 f
+2866(ar)X
+1 f
+2942(\(1\))X
+3063(may)X
+3228(read)X
+3394(the)X
+3519(\256le)X
+3648(and)X
+3791(produce)X
+4077(invalid)X
+555 810(results)N
+790(since)X
+981(the)X
+1105(\256le)X
+1233(has)X
+1366(not)X
+1494(been)X
+1672(completely)X
+2054(written.)X
+2347(Currently,)X
+2700(some)X
+2895(utilities)X
+3160(use)X
+3293(special)X
+3542(purpose)X
+3821(code)X
+3998(to)X
+4085(handle)X
+555 900(such)N
+722(cases)X
+912(while)X
+1110(others)X
+1326(ignore)X
+1551(the)X
+1669(problem)X
+1956(and)X
+2092(force)X
+2278(users)X
+2463(to)X
+2545(live)X
+2685(with)X
+2847(the)X
+2965(consequences.)X
+755 1023(In)N
+845(this)X
+983(paper,)X
+1205(we)X
+1322(present)X
+1577(a)X
+1635(simple)X
+1870(library)X
+2106(which)X
+2324(provides)X
+2622(transaction)X
+2996(semantics)X
+3334(\(atomicity,)X
+3705(consistency,)X
+4121(isola-)X
+555 1113(tion,)N
+720(and)X
+857(durability\).)X
+1236(The)X
+1382(4.4BSD)X
+1658(database)X
+1956(access)X
+2182(methods)X
+2473(have)X
+2645(been)X
+2817(modi\256ed)X
+3121(to)X
+3203(use)X
+3330(this)X
+3465(library,)X
+3719(optionally)X
+4063(provid-)X
+555 1203(ing)N
+682(shared)X
+917(buffer)X
+1139(management)X
+1574(between)X
+1867(applications,)X
+2298(locking,)X
+2582(and)X
+2722(transaction)X
+3098(semantics.)X
+3478(Any)X
+3640(UNIX)X
+3865(program)X
+4161(may)X
+555 1293(transaction)N
+930(protect)X
+1176(its)X
+1274(data)X
+1430(by)X
+1532(requesting)X
+1888(transaction)X
+2262(protection)X
+2609(with)X
+2773(the)X
+3 f
+2893(db)X
+1 f
+2981(\(3\))X
+3097(library)X
+3333(or)X
+3422(by)X
+3524(adding)X
+3764(appropriate)X
+4152(calls)X
+555 1383(to)N
+646(the)X
+773(transaction)X
+1154(manager,)X
+1480(buffer)X
+1706(manager,)X
+2032(lock)X
+2199(manager,)X
+2525(and)X
+2670(log)X
+2801(manager.)X
+3147(The)X
+3301(library)X
+3543(routines)X
+3829(may)X
+3995(be)X
+4099(linked)X
+555 1473(into)N
+708(the)X
+834(host)X
+995(application)X
+1379(and)X
+1523(called)X
+1743(by)X
+1851(subroutine)X
+2217(interface,)X
+2547(or)X
+2642(they)X
+2808(may)X
+2974(reside)X
+3194(in)X
+3284(a)X
+3348(separate)X
+3640(server)X
+3865(process.)X
+4174(The)X
+555 1563(server)N
+772(architecture)X
+1172(provides)X
+1468(for)X
+1582(network)X
+1865(access)X
+2091(and)X
+2227(better)X
+2430(protection)X
+2775(mechanisms.)X
+3 f
+555 1749(2.)N
+655(Related)X
+938(Work)X
+1 f
+755 1872(There)N
+1000(has)X
+1164(been)X
+1373(much)X
+1608(discussion)X
+1998(in)X
+2117(recent)X
+2371(years)X
+2597(about)X
+2831(new)X
+3021(transaction)X
+3429(models)X
+3716(and)X
+3888(architectures)X
+555 1962 0.1172([SPEC88][NODI90][CHEN91][MOHA91].)AN
+2009(Much)X
+2220(of)X
+2310(this)X
+2448(work)X
+2636(focuses)X
+2900(on)X
+3003(new)X
+3160(ways)X
+3348(to)X
+3433(model)X
+3656(transactions)X
+4062(and)X
+4201(the)X
+555 2052(interactions)N
+953(between)X
+1245(them,)X
+1449(while)X
+1651(the)X
+1772(work)X
+1960(presented)X
+2291(here)X
+2453(focuses)X
+2717(on)X
+2820(the)X
+2941(implementation)X
+3466(and)X
+3605(performance)X
+4035(of)X
+4125(tradi-)X
+555 2142(tional)N
+757(transaction)X
+1129(techniques)X
+1492(\(write-ahead)X
+1919(logging)X
+2183(and)X
+2319(two-phase)X
+2669(locking\))X
+2956(on)X
+3056(a)X
+3112(standard)X
+3404(operating)X
+3727(system)X
+3969(\(UNIX\).)X
+755 2265(Such)N
+947(traditional)X
+1308(operating)X
+1643(systems)X
+1928(are)X
+2059(often)X
+2256(criticized)X
+2587(for)X
+2713(their)X
+2892(inability)X
+3190(to)X
+3283(perform)X
+3573(transaction)X
+3956(processing)X
+555 2355(adequately.)N
+971([STON81])X
+1342(cites)X
+1517(three)X
+1706(main)X
+1894(areas)X
+2088(of)X
+2183(inadequate)X
+2559(support:)X
+2849(buffer)X
+3074(management,)X
+3532(the)X
+3658(\256le)X
+3788(system,)X
+4058(and)X
+4201(the)X
+555 2445(process)N
+823(structure.)X
+1191(These)X
+1410(arguments)X
+1771(are)X
+1897(summarized)X
+2316(in)X
+2405(table)X
+2587(one.)X
+2769(Fortunately,)X
+3184(much)X
+3388(has)X
+3521(changed)X
+3815(since)X
+4006(1981.)X
+4232(In)X
+555 2535(the)N
+683(area)X
+848(of)X
+945(buffer)X
+1172(management,)X
+1632(most)X
+1817(UNIX)X
+2048(systems)X
+2331(provide)X
+2606(the)X
+2734(ability)X
+2968(to)X
+3060(memory)X
+3357(map)X
+3525(\256les,)X
+3708(thus)X
+3870(obviating)X
+4201(the)X
+555 2625(need)N
+734(for)X
+855(a)X
+918(copy)X
+1101(between)X
+1396(kernel)X
+1624(and)X
+1766(user)X
+1926(space.)X
+2171(If)X
+2251(a)X
+2313(database)X
+2616(system)X
+2864(is)X
+2943(going)X
+3151(to)X
+3239(use)X
+3372(the)X
+3496(\256le)X
+3624(system)X
+3872(buffer)X
+4095(cache,)X
+555 2715(then)N
+719(a)X
+781(system)X
+1029(call)X
+1171(is)X
+1250(required.)X
+1584(However,)X
+1924(if)X
+1998(buffering)X
+2322(is)X
+2400(provided)X
+2710(at)X
+2793(user)X
+2952(level)X
+3133(using)X
+3331(shared)X
+3566(memory,)X
+3878(as)X
+3970(in)X
+4057(LIBTP,)X
+555 2805(buffer)N
+776(management)X
+1210(is)X
+1287(only)X
+1452(as)X
+1542(slow)X
+1716(as)X
+1806(access)X
+2035(to)X
+2120(shared)X
+2353(memory)X
+2643(and)X
+2782(any)X
+2921(replacement)X
+3337(algorithm)X
+3671(may)X
+3832(be)X
+3931(used.)X
+4121(Since)X
+555 2895(multiple)N
+849(processes)X
+1185(can)X
+1325(access)X
+1559(the)X
+1685(shared)X
+1923(data,)X
+2105(prefetching)X
+2499(may)X
+2665(be)X
+2769(accomplished)X
+3238(by)X
+3346(separate)X
+3638(processes)X
+3973(or)X
+4067(threads)X
+555 2985(whose)N
+782(sole)X
+932(purpose)X
+1207(is)X
+1281(to)X
+1364(prefetch)X
+1649(pages)X
+1853(and)X
+1990(wait)X
+2149(on)X
+2250(them.)X
+2471(There)X
+2680(is)X
+2754(still)X
+2894(no)X
+2995(way)X
+3150(to)X
+3233(enforce)X
+3496(write)X
+3682(ordering)X
+3975(other)X
+4161(than)X
+555 3075(keeping)N
+829(pages)X
+1032(in)X
+1114(user)X
+1268(memory)X
+1555(and)X
+1691(using)X
+1884(the)X
+3 f
+2002(fsync)X
+1 f
+2180(\(3\))X
+2294(system)X
+2536(call)X
+2672(to)X
+2754(perform)X
+3033(synchronous)X
+3458(writes.)X
+755 3198(In)N
+845(the)X
+966(area)X
+1124(of)X
+1214(\256le)X
+1339(systems,)X
+1635(the)X
+1756(fast)X
+1895(\256le)X
+2020(system)X
+2265(\(FFS\))X
+2474([MCKU84])X
+2871(allows)X
+3103(allocation)X
+3442(in)X
+3527(units)X
+3704(up)X
+3806(to)X
+3890(64KBytes)X
+4232(as)X
+555 3288(opposed)N
+846(to)X
+932(the)X
+1054(4KByte)X
+1327(and)X
+1466(8KByte)X
+1738(\256gures)X
+1979(quoted)X
+2220(in)X
+2305([STON81].)X
+2711(The)X
+2859(measurements)X
+3341(in)X
+3426(this)X
+3564(paper)X
+3766(were)X
+3946(taken)X
+4143(from)X
+555 3378(an)N
+655(8KByte)X
+928(FFS,)X
+1104(but)X
+1230(as)X
+1320(LIBTP)X
+1565(runs)X
+1726(exclusively)X
+2114(in)X
+2199(user)X
+2356(space,)X
+2578(there)X
+2762(is)X
+2838(nothing)X
+3105(to)X
+3190(prevent)X
+3454(it)X
+3521(from)X
+3700(being)X
+3901(run)X
+4031(on)X
+4134(other)X
+555 3468(UNIX)N
+776(compatible)X
+1152(\256le)X
+1274(systems)X
+1547(\(e.g.)X
+1710(log-structured)X
+2180([ROSE91],)X
+2558(extent-based,)X
+3004(or)X
+3091(multi-block)X
+3484([SELT91]\).)X
+755 3591(Finally,)N
+1029(with)X
+1199(regard)X
+1433(to)X
+1523(the)X
+1648(process)X
+1916(structure,)X
+2244(neither)X
+2494(context)X
+2757(switch)X
+2993(time)X
+3162(nor)X
+3296(scheduling)X
+3670(around)X
+3920(semaphores)X
+555 3681(seems)N
+785(to)X
+881(affect)X
+1099(the)X
+1231(system)X
+1487(performance.)X
+1968(However,)X
+2317(the)X
+2449(implementation)X
+2984(of)X
+3084(semaphores)X
+3496(can)X
+3641(impact)X
+3892(performance)X
+555 3771(tremendously.)N
+1051(This)X
+1213(is)X
+1286(discussed)X
+1613(in)X
+1695(more)X
+1880(detail)X
+2078(in)X
+2160(section)X
+2407(4.3.)X
+755 3894(The)N
+908(Tuxedo)X
+1181(system)X
+1431(from)X
+1615(AT&T)X
+1861(is)X
+1941(a)X
+2004(transaction)X
+2383(manager)X
+2687(which)X
+2910(coordinates)X
+3307(distributed)X
+3676(transaction)X
+4055(commit)X
+555 3984(from)N
+738(a)X
+801(variety)X
+1051(of)X
+1145(different)X
+1449(local)X
+1632(transaction)X
+2011(managers.)X
+2386(At)X
+2493(this)X
+2634(time,)X
+2822(LIBTP)X
+3070(does)X
+3243(not)X
+3371(have)X
+3549(its)X
+3650(own)X
+3814(mechanism)X
+4205(for)X
+555 4074(distributed)N
+942(commit)X
+1231(processing,)X
+1639(but)X
+1786(could)X
+2009(be)X
+2130(used)X
+2322(as)X
+2434(a)X
+2515(local)X
+2716(transaction)X
+3113(agent)X
+3331(by)X
+3455(systems)X
+3752(such)X
+3943(as)X
+4054(Tuxedo)X
+555 4164([ANDR89].)N
+10 f
+863 4393(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+903 4483(Buffer)N
+1133(Management)X
+10 f
+1672(g)X
+1 f
+1720(Data)X
+1892(must)X
+2067(be)X
+2163(copied)X
+2397(between)X
+2685(kernel)X
+2906(space)X
+3105(and)X
+3241(user)X
+3395(space.)X
+10 f
+1672 4573(g)N
+1 f
+1720(Buffer)X
+1950(pool)X
+2112(access)X
+2338(is)X
+2411(too)X
+2533(slow.)X
+10 f
+1672 4663(g)N
+1 f
+1720(There)X
+1928(is)X
+2001(no)X
+2101(way)X
+2255(to)X
+2337(request)X
+2589(prefetch.)X
+10 f
+1672 4753(g)N
+1 f
+1720(Replacement)X
+2159(is)X
+2232(usually)X
+2483(LRU)X
+2663(which)X
+2879(may)X
+3037(be)X
+3133(suboptimal)X
+3508(for)X
+3622(databases.)X
+10 f
+1672 4843(g)N
+1 f
+1720(There)X
+1928(is)X
+2001(no)X
+2101(way)X
+2255(to)X
+2337(guarantee)X
+2670(write)X
+2855(ordering.)X
+10 f
+863 4853(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+903 4943(File)N
+1047(System)X
+10 f
+1672(g)X
+1 f
+1720(Allocation)X
+2078(is)X
+2151(done)X
+2327(in)X
+2409(small)X
+2602(blocks)X
+2831(\(usually)X
+3109(4K)X
+3227(or)X
+3314(8K\).)X
+10 f
+1672 5033(g)N
+1 f
+1720(Logical)X
+1985(organization)X
+2406(of)X
+2493(\256les)X
+2646(is)X
+2719(redundantly)X
+3122(expressed.)X
+10 f
+863 5043(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+903 5133(Process)N
+1168(Structure)X
+10 f
+1672(g)X
+1 f
+1720(Context)X
+1993(switching)X
+2324(and)X
+2460(message)X
+2752(passing)X
+3012(are)X
+3131(too)X
+3253(slow.)X
+10 f
+1672 5223(g)N
+1 f
+1720(A)X
+1798(process)X
+2059(may)X
+2217(be)X
+2313(descheduled)X
+2730(while)X
+2928(holding)X
+3192(a)X
+3248(semaphore.)X
+10 f
+863 5233(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+863(c)X
+5193(c)Y
+5113(c)Y
+5033(c)Y
+4953(c)Y
+4873(c)Y
+4793(c)Y
+4713(c)Y
+4633(c)Y
+4553(c)Y
+4473(c)Y
+3990 5233(c)N
+5193(c)Y
+5113(c)Y
+5033(c)Y
+4953(c)Y
+4873(c)Y
+4793(c)Y
+4713(c)Y
+4633(c)Y
+4553(c)Y
+4473(c)Y
+3 f
+1156 5446(Table)N
+1371(One:)X
+1560(Shortcomings)X
+2051(of)X
+2138(UNIX)X
+2363(transaction)X
+2770(support)X
+3056(cited)X
+3241(in)X
+3327([STON81].)X
+
+3 p
+%%Page: 3 3
+10 s 10 xH 0 xS 3 f
+1 f
+755 630(The)N
+901(transaction)X
+1274(architecture)X
+1675(presented)X
+2004(in)X
+2087([YOUN91])X
+2474(is)X
+2548(very)X
+2712(similar)X
+2955(to)X
+3038(that)X
+3179(implemented)X
+3618(in)X
+3701(the)X
+3820(LIBTP.)X
+4103(While)X
+555 720([YOUN91])N
+947(presents)X
+1236(a)X
+1298(model)X
+1524(for)X
+1644(providing)X
+1981(transaction)X
+2359(services,)X
+2663(this)X
+2803(paper)X
+3007(focuses)X
+3273(on)X
+3378(the)X
+3501(implementation)X
+4028(and)X
+4169(per-)X
+555 810(formance)N
+881(of)X
+970(a)X
+1028(particular)X
+1358(system.)X
+1642(In)X
+1731(addition,)X
+2034(we)X
+2149(provide)X
+2415(detailed)X
+2690(comparisons)X
+3116(with)X
+3279(alternative)X
+3639(solutions:)X
+3970(traditional)X
+555 900(UNIX)N
+776(services)X
+1055(and)X
+1191(commercial)X
+1590(database)X
+1887(management)X
+2317(systems.)X
+3 f
+555 1086(3.)N
+655(Architecture)X
+1 f
+755 1209(The)N
+906(library)X
+1146(is)X
+1224(designed)X
+1534(to)X
+1621(provide)X
+1891(well)X
+2054(de\256ned)X
+2315(interfaces)X
+2653(to)X
+2740(the)X
+2863(services)X
+3147(required)X
+3440(for)X
+3559(transaction)X
+3936(processing.)X
+555 1299(These)N
+777(services)X
+1066(are)X
+1195(recovery,)X
+1527(concurrency)X
+1955(control,)X
+2232(and)X
+2378(the)X
+2506(management)X
+2946(of)X
+3043(shared)X
+3283(data.)X
+3487(First)X
+3663(we)X
+3787(will)X
+3941(discuss)X
+4201(the)X
+555 1389(design)N
+795(tradeoffs)X
+1112(in)X
+1205(the)X
+1334(selection)X
+1650(of)X
+1748(recovery,)X
+2081(concurrency)X
+2510(control,)X
+2787(and)X
+2933(buffer)X
+3160(management)X
+3600(implementations,)X
+4183(and)X
+555 1479(then)N
+713(we)X
+827(will)X
+971(present)X
+1223(the)X
+1341(overall)X
+1584(library)X
+1818(architecture)X
+2218(and)X
+2354(module)X
+2614(descriptions.)X
+3 f
+555 1665(3.1.)N
+715(Design)X
+966(Tradeoffs)X
+1 f
+3 f
+555 1851(3.1.1.)N
+775(Crash)X
+1004(Recovery)X
+1 f
+755 1974(The)N
+909(recovery)X
+1220(protocol)X
+1516(is)X
+1598(responsible)X
+1992(for)X
+2115(providing)X
+2455(the)X
+2582(transaction)X
+2963(semantics)X
+3308(discussed)X
+3644(earlier.)X
+3919(There)X
+4136(are)X
+4263(a)X
+555 2064(wide)N
+739(range)X
+946(of)X
+1041(recovery)X
+1351(protocols)X
+1677(available)X
+1995([HAER83],)X
+2395(but)X
+2525(we)X
+2647(can)X
+2786(crudely)X
+3054(divide)X
+3281(them)X
+3468(into)X
+3619(two)X
+3766(main)X
+3953(categories.)X
+555 2154(The)N
+706(\256rst)X
+856(category)X
+1159(records)X
+1422(all)X
+1528(modi\256cations)X
+1989(to)X
+2077(the)X
+2201(database)X
+2504(in)X
+2592(a)X
+2653(separate)X
+2942(\256le,)X
+3089(and)X
+3230(uses)X
+3393(this)X
+3533(\256le)X
+3660(\(log\))X
+3841(to)X
+3928(back)X
+4105(out)X
+4232(or)X
+555 2244(reapply)N
+825(these)X
+1019(modi\256cations)X
+1483(if)X
+1561(a)X
+1626(transaction)X
+2007(aborts)X
+2232(or)X
+2328(the)X
+2455(system)X
+2706(crashes.)X
+3012(We)X
+3153(call)X
+3298(this)X
+3442(set)X
+3560(the)X
+3 f
+3687(logging)X
+3963(protocols)X
+1 f
+4279(.)X
+555 2334(The)N
+703(second)X
+949(category)X
+1249(avoids)X
+1481(the)X
+1602(use)X
+1732(of)X
+1822(a)X
+1881(log)X
+2006(by)X
+2109(carefully)X
+2418(controlling)X
+2792(when)X
+2989(data)X
+3146(are)X
+3268(written)X
+3518(to)X
+3603(disk.)X
+3799(We)X
+3934(call)X
+4073(this)X
+4210(set)X
+555 2424(the)N
+3 f
+673(non-logging)X
+1096(protocols)X
+1 f
+1412(.)X
+755 2547(Non-logging)N
+1185(protocols)X
+1504(hold)X
+1666(dirty)X
+1837(buffers)X
+2085(in)X
+2167(main)X
+2347(memory)X
+2634(or)X
+2721(temporary)X
+3071(\256les)X
+3224(until)X
+3390(commit)X
+3654(and)X
+3790(then)X
+3948(force)X
+4134(these)X
+555 2637(pages)N
+769(to)X
+862(disk)X
+1026(at)X
+1115(transaction)X
+1498(commit.)X
+1813(While)X
+2040(we)X
+2165(can)X
+2308(use)X
+2446(temporary)X
+2807(\256les)X
+2971(to)X
+3064(hold)X
+3237(dirty)X
+3418(pages)X
+3631(that)X
+3781(may)X
+3949(need)X
+4131(to)X
+4223(be)X
+555 2727(evicted)N
+810(from)X
+988(memory)X
+1277(during)X
+1508(a)X
+1566(long-running)X
+2006(transaction,)X
+2400(the)X
+2520(only)X
+2684(user-level)X
+3023(mechanism)X
+3410(to)X
+3494(force)X
+3682(pages)X
+3887(to)X
+3971(disk)X
+4126(is)X
+4201(the)X
+3 f
+555 2817(fsync)N
+1 f
+733(\(2\))X
+850(system)X
+1095(call.)X
+1274(Unfortunately,)X
+3 f
+1767(fsync)X
+1 f
+1945(\(2\))X
+2062(is)X
+2138(an)X
+2237(expensive)X
+2581(system)X
+2826(call)X
+2965(in)X
+3050(that)X
+3193(it)X
+3260(forces)X
+3480(all)X
+3583(pages)X
+3789(of)X
+3879(a)X
+3938(\256le)X
+4062(to)X
+4146(disk,)X
+555 2907(and)N
+691(transactions)X
+1094(that)X
+1234(manage)X
+1504(more)X
+1689(than)X
+1847(one)X
+1983(\256le)X
+2105(must)X
+2280(issue)X
+2460(one)X
+2596(call)X
+2732(per)X
+2855(\256le.)X
+755 3030(In)N
+853(addition,)X
+3 f
+1166(fsync)X
+1 f
+1344(\(2\))X
+1469(provides)X
+1776(no)X
+1887(way)X
+2051(to)X
+2143(control)X
+2400(the)X
+2528(order)X
+2728(in)X
+2820(which)X
+3046(dirty)X
+3227(pages)X
+3440(are)X
+3569(written)X
+3826(to)X
+3918(disk.)X
+4121(Since)X
+555 3120(non-logging)N
+976(protocols)X
+1304(must)X
+1489(sometimes)X
+1861(order)X
+2061(writes)X
+2287(carefully)X
+2603([SULL92],)X
+2987(they)X
+3155(are)X
+3284(dif\256cult)X
+3567(to)X
+3659(implement)X
+4030(on)X
+4139(Unix)X
+555 3210(systems.)N
+868(As)X
+977(a)X
+1033(result,)X
+1251(we)X
+1365(have)X
+1537(chosen)X
+1780(to)X
+1862(implement)X
+2224(a)X
+2280(logging)X
+2544(protocol.)X
+755 3333(Logging)N
+1050(protocols)X
+1372(may)X
+1534(be)X
+1634(categorized)X
+2029(based)X
+2236(on)X
+2340(how)X
+2502(information)X
+2904(is)X
+2981(logged)X
+3223(\(physically)X
+3602(or)X
+3692(logically\))X
+4022(and)X
+4161(how)X
+555 3423(much)N
+767(is)X
+854(logged)X
+1106(\(before)X
+1373(images,)X
+1654(after)X
+1836(images)X
+2097(or)X
+2198(both\).)X
+2441(In)X
+3 f
+2542(physical)X
+2855(logging)X
+1 f
+3103(,)X
+3157(images)X
+3417(of)X
+3517(complete)X
+3844(physical)X
+4144(units)X
+555 3513(\(pages)N
+786(or)X
+874(buffers\))X
+1150(are)X
+1270(recorded,)X
+1593(while)X
+1792(in)X
+3 f
+1875(logical)X
+2118(logging)X
+1 f
+2387(a)X
+2444(description)X
+2820(of)X
+2907(the)X
+3025(operation)X
+3348(is)X
+3421(recorded.)X
+3763(Therefore,)X
+4121(while)X
+555 3603(we)N
+675(may)X
+839(record)X
+1071(entire)X
+1280(pages)X
+1489(in)X
+1577(a)X
+1639(physical)X
+1932(log,)X
+2080(we)X
+2200(need)X
+2378(only)X
+2546(record)X
+2777(the)X
+2900(records)X
+3162(being)X
+3365(modi\256ed)X
+3674(in)X
+3761(a)X
+3822(logical)X
+4065(log.)X
+4232(In)X
+555 3693(fact,)N
+718(physical)X
+1006(logging)X
+1271(can)X
+1404(be)X
+1501(thought)X
+1766(of)X
+1854(as)X
+1942(a)X
+1999(special)X
+2243(case)X
+2403(of)X
+2491(logical)X
+2730(logging,)X
+3015(since)X
+3201(the)X
+3320 0.3125(``records'')AX
+3686(that)X
+3827(we)X
+3942(log)X
+4065(in)X
+4148(logi-)X
+555 3783(cal)N
+673(logging)X
+941(might)X
+1151(be)X
+1251(physical)X
+1542(pages.)X
+1789(Since)X
+1991(logical)X
+2233(logging)X
+2501(is)X
+2578(both)X
+2743(more)X
+2931(space-ef\256cient)X
+3423(and)X
+3562(more)X
+3750(general,)X
+4030(we)X
+4147(have)X
+555 3873(chosen)N
+798(it)X
+862(for)X
+976(our)X
+1103(logging)X
+1367(protocol.)X
+755 3996(In)N
+3 f
+843(before-image)X
+1315(logging)X
+1 f
+1563(,)X
+1604(we)X
+1719(log)X
+1842(a)X
+1899(copy)X
+2076(of)X
+2164(the)X
+2283(data)X
+2438(before)X
+2665(the)X
+2784(update,)X
+3039(while)X
+3238(in)X
+3 f
+3321(after-image)X
+3739(logging)X
+1 f
+3987(,)X
+4027(we)X
+4141(log)X
+4263(a)X
+555 4086(copy)N
+740(of)X
+836(the)X
+963(data)X
+1126(after)X
+1303(the)X
+1429(update.)X
+1711(If)X
+1793(we)X
+1915(log)X
+2045(only)X
+2215(before-images,)X
+2723(then)X
+2889(there)X
+3078(is)X
+3159(suf\256cient)X
+3485(information)X
+3891(in)X
+3981(the)X
+4107(log)X
+4237(to)X
+555 4176(allow)N
+761(us)X
+860(to)X
+3 f
+950(undo)X
+1 f
+1150(the)X
+1276(transaction)X
+1656(\(go)X
+1791(back)X
+1971(to)X
+2061(the)X
+2187(state)X
+2361(represented)X
+2759(by)X
+2866(the)X
+2991(before-image\).)X
+3514(However,)X
+3876(if)X
+3952(the)X
+4077(system)X
+555 4266(crashes)N
+814(and)X
+952(a)X
+1010(committed)X
+1374(transaction's)X
+1806(changes)X
+2087(have)X
+2261(not)X
+2385(reached)X
+2658(the)X
+2778(disk,)X
+2953(we)X
+3068(have)X
+3241(no)X
+3342(means)X
+3568(to)X
+3 f
+3651(redo)X
+1 f
+3828(the)X
+3947(transaction)X
+555 4356(\(reapply)N
+849(the)X
+973(updates\).)X
+1311(Therefore,)X
+1675(logging)X
+1945(only)X
+2113(before-images)X
+2599(necessitates)X
+3004(forcing)X
+3262(dirty)X
+3439(pages)X
+3648(at)X
+3732(commit)X
+4002(time.)X
+4210(As)X
+555 4446(mentioned)N
+913(above,)X
+1145(forcing)X
+1397(pages)X
+1600(at)X
+1678(commit)X
+1942(is)X
+2015(considered)X
+2383(too)X
+2505(costly.)X
+755 4569(If)N
+834(we)X
+953(log)X
+1080(only)X
+1247(after-images,)X
+1694(then)X
+1857(there)X
+2043(is)X
+2121(suf\256cient)X
+2444(information)X
+2847(in)X
+2934(the)X
+3057(log)X
+3184(to)X
+3271(allow)X
+3474(us)X
+3570(to)X
+3657(redo)X
+3825(the)X
+3947(transaction)X
+555 4659(\(go)N
+687(forward)X
+967(to)X
+1054(the)X
+1177(state)X
+1348(represented)X
+1743(by)X
+1847(the)X
+1969(after-image\),)X
+2411(but)X
+2537(we)X
+2655(do)X
+2759(not)X
+2885(have)X
+3061(the)X
+3183(information)X
+3585(required)X
+3877(to)X
+3963(undo)X
+4147(tran-)X
+555 4749(sactions)N
+845(which)X
+1073(aborted)X
+1346(after)X
+1526(dirty)X
+1709(pages)X
+1924(were)X
+2113(written)X
+2372(to)X
+2466(disk.)X
+2670(Therefore,)X
+3039(logging)X
+3314(only)X
+3487(after-images)X
+3920(necessitates)X
+555 4839(holding)N
+819(all)X
+919(dirty)X
+1090(buffers)X
+1338(in)X
+1420(main)X
+1600(memory)X
+1887(until)X
+2053(commit)X
+2317(or)X
+2404(writing)X
+2655(them)X
+2835(to)X
+2917(a)X
+2973(temporary)X
+3323(\256le.)X
+755 4962(Since)N
+956(neither)X
+1202(constraint)X
+1541(\(forcing)X
+1823(pages)X
+2029(on)X
+2132(commit)X
+2399(or)X
+2489(buffering)X
+2811(pages)X
+3016(until)X
+3184(commit\))X
+3477(was)X
+3624(feasible,)X
+3916(we)X
+4032(chose)X
+4237(to)X
+555 5052(log)N
+683(both)X
+851(before)X
+1083(and)X
+1225(after)X
+1399(images.)X
+1672(The)X
+1823(only)X
+1991(remaining)X
+2342(consideration)X
+2800(is)X
+2879(when)X
+3079(changes)X
+3363(get)X
+3486(written)X
+3738(to)X
+3825(disk.)X
+4023(Changes)X
+555 5142(affect)N
+764(both)X
+931(data)X
+1090(pages)X
+1298(and)X
+1438(the)X
+1560(log.)X
+1726(If)X
+1804(the)X
+1926(changed)X
+2218(data)X
+2376(page)X
+2552(is)X
+2629(written)X
+2880(before)X
+3110(the)X
+3232(log)X
+3358(page,)X
+3554(and)X
+3694(the)X
+3816(system)X
+4062(crashes)X
+555 5232(before)N
+787(the)X
+911(log)X
+1039(page)X
+1217(is)X
+1296(written,)X
+1569(the)X
+1693(log)X
+1820(will)X
+1969(contain)X
+2230(insuf\256cient)X
+2615(information)X
+3018(to)X
+3105(undo)X
+3290(the)X
+3413(change.)X
+3706(This)X
+3873(violates)X
+4147(tran-)X
+555 5322(saction)N
+803(semantics,)X
+1160(since)X
+1346(some)X
+1536(changed)X
+1825(data)X
+1980(pages)X
+2184(may)X
+2343(not)X
+2466(have)X
+2638(been)X
+2810(written,)X
+3077(and)X
+3213(the)X
+3331(database)X
+3628(cannot)X
+3862(be)X
+3958(restored)X
+4237(to)X
+555 5412(its)N
+650(pre-transaction)X
+1152(state.)X
+755 5535(The)N
+914(log)X
+1050(record)X
+1290(describing)X
+1658(an)X
+1768(update)X
+2016(must)X
+2205(be)X
+2315(written)X
+2576(to)X
+2672(stable)X
+2893(storage)X
+3159(before)X
+3398(the)X
+3529(modi\256ed)X
+3846(page.)X
+4071(This)X
+4246(is)X
+3 f
+555 5625(write-ahead)N
+992(logging)X
+1 f
+1240(.)X
+1307(If)X
+1388(log)X
+1517(records)X
+1781(are)X
+1907(safely)X
+2126(written)X
+2380(to)X
+2469(disk,)X
+2649(data)X
+2810(pages)X
+3020(may)X
+3185(be)X
+3288(written)X
+3542(at)X
+3627(any)X
+3770(time)X
+3939(afterwards.)X
+555 5715(This)N
+721(means)X
+950(that)X
+1094(the)X
+1216(only)X
+1382(\256le)X
+1508(that)X
+1652(ever)X
+1815(needs)X
+2022(to)X
+2108(be)X
+2208(forced)X
+2438(to)X
+2524(disk)X
+2681(is)X
+2758(the)X
+2880(log.)X
+3046(Since)X
+3248(the)X
+3370(log)X
+3495(is)X
+3571(append-only,)X
+4015(modi\256ed)X
+
+4 p
+%%Page: 4 4
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+555 630(pages)N
+760(always)X
+1005(appear)X
+1242(at)X
+1322(the)X
+1442(end)X
+1580(and)X
+1718(may)X
+1878(be)X
+1976(written)X
+2224(to)X
+2307(disk)X
+2461(ef\256ciently)X
+2807(in)X
+2890(any)X
+3027(\256le)X
+3150(system)X
+3393(that)X
+3534(favors)X
+3756(sequential)X
+4102(order-)X
+555 720(ing)N
+677(\()X
+2 f
+704(e.g.)X
+1 f
+820(,)X
+860(FFS,)X
+1032(log-structured)X
+1502(\256le)X
+1624(system,)X
+1886(or)X
+1973(an)X
+2069(extent-based)X
+2495(system\).)X
+3 f
+555 906(3.1.2.)N
+775(Concurrency)X
+1245(Control)X
+1 f
+755 1029(The)N
+918(concurrency)X
+1354(control)X
+1619(protocol)X
+1923(is)X
+2013(responsible)X
+2415(for)X
+2546(maintaining)X
+2965(consistency)X
+3376(in)X
+3475(the)X
+3610(presence)X
+3929(of)X
+4033(multiple)X
+555 1119(accesses.)N
+897(There)X
+1114(are)X
+1242(several)X
+1499(alternative)X
+1867(solutions)X
+2183(such)X
+2358(as)X
+2453(locking,)X
+2741(optimistic)X
+3088(concurrency)X
+3514(control)X
+3769([KUNG81],)X
+4183(and)X
+555 1209(timestamp)N
+912(ordering)X
+1208([BERN80].)X
+1619(Since)X
+1821(optimistic)X
+2164(methods)X
+2459(and)X
+2599(timestamp)X
+2956(ordering)X
+3252(are)X
+3374(generally)X
+3696(more)X
+3884(complex)X
+4183(and)X
+555 1299(restrict)N
+804(concurrency)X
+1228(without)X
+1498(eliminating)X
+1888(starvation)X
+2230(or)X
+2323(deadlocks,)X
+2690(we)X
+2810(chose)X
+3018(two-phase)X
+3373(locking)X
+3638(\(2PL\).)X
+3890(Strict)X
+4088(2PL)X
+4246(is)X
+555 1389(suboptimal)N
+935(for)X
+1054(certain)X
+1297(data)X
+1455(structures)X
+1791(such)X
+1962(as)X
+2053(B-trees)X
+2309(because)X
+2588(it)X
+2656(can)X
+2792(limit)X
+2966(concurrency,)X
+3408(so)X
+3503(we)X
+3621(use)X
+3752(a)X
+3812(special)X
+4059(locking)X
+555 1479(protocol)N
+842(based)X
+1045(on)X
+1145(one)X
+1281(described)X
+1609(in)X
+1691([LEHM81].)X
+755 1602(The)N
+901(B-tree)X
+1123(locking)X
+1384(protocol)X
+1672(we)X
+1787(implemented)X
+2226(releases)X
+2502(locks)X
+2691(at)X
+2769(internal)X
+3034(nodes)X
+3241(in)X
+3323(the)X
+3441(tree)X
+3582(as)X
+3669(it)X
+3733(descends.)X
+4083(A)X
+4161(lock)X
+555 1692(on)N
+658(an)X
+757(internal)X
+1025(page)X
+1200(is)X
+1276(always)X
+1522(released)X
+1808(before)X
+2036(a)X
+2094(lock)X
+2254(on)X
+2356(its)X
+2453(child)X
+2635(is)X
+2710(obtained)X
+3008(\(that)X
+3177(is,)X
+3272(locks)X
+3463(are)X
+3584(not)X
+3 f
+3708(coupled)X
+1 f
+3996([BAY77])X
+555 1782(during)N
+786(descent\).)X
+1116(When)X
+1330(a)X
+1388(leaf)X
+1531(\(or)X
+1647(internal\))X
+1941(page)X
+2115(is)X
+2190(split,)X
+2369(a)X
+2427(write)X
+2614(lock)X
+2774(is)X
+2849(acquired)X
+3148(on)X
+3250(the)X
+3370(parent)X
+3593(before)X
+3821(the)X
+3941(lock)X
+4100(on)X
+4201(the)X
+555 1872(just-split)N
+855(page)X
+1028(is)X
+1102(released)X
+1387(\(locks)X
+1604(are)X
+3 f
+1724(coupled)X
+1 f
+2011(during)X
+2241(ascent\).)X
+2530(Write)X
+2734(locks)X
+2924(on)X
+3025(internal)X
+3291(pages)X
+3495(are)X
+3615(released)X
+3899(immediately)X
+555 1962(after)N
+723(the)X
+841(page)X
+1013(is)X
+1086(updated,)X
+1380(but)X
+1502(locks)X
+1691(on)X
+1791(leaf)X
+1932(pages)X
+2135(are)X
+2254(held)X
+2412(until)X
+2578(the)X
+2696(end)X
+2832(of)X
+2919(the)X
+3037(transaction.)X
+755 2085(Since)N
+964(locks)X
+1164(are)X
+1294(released)X
+1589(during)X
+1828(descent,)X
+2119(the)X
+2247(structure)X
+2558(of)X
+2655(the)X
+2783(tree)X
+2934(may)X
+3102(change)X
+3360(above)X
+3582(a)X
+3648(node)X
+3834(being)X
+4042(used)X
+4219(by)X
+555 2175(some)N
+752(process.)X
+1061(If)X
+1143(that)X
+1291(process)X
+1560(must)X
+1743(later)X
+1914(ascend)X
+2161(the)X
+2287(tree)X
+2435(because)X
+2717(of)X
+2811(a)X
+2874(page)X
+3053(split,)X
+3237(any)X
+3380(such)X
+3554(change)X
+3809(must)X
+3991(not)X
+4120(cause)X
+555 2265(confusion.)N
+938(We)X
+1077(use)X
+1211(the)X
+1336(technique)X
+1675(described)X
+2010(in)X
+2099([LEHM81])X
+2487(which)X
+2710(exploits)X
+2989(the)X
+3113(ordering)X
+3411(of)X
+3504(data)X
+3664(on)X
+3770(a)X
+3832(B-tree)X
+4059(page)X
+4237(to)X
+555 2355(guarantee)N
+888(that)X
+1028(no)X
+1128(process)X
+1389(ever)X
+1548(gets)X
+1697(lost)X
+1832(as)X
+1919(a)X
+1975(result)X
+2173(of)X
+2260(internal)X
+2525(page)X
+2697(updates)X
+2962(made)X
+3156(by)X
+3256(other)X
+3441(processes.)X
+755 2478(If)N
+836(a)X
+899(transaction)X
+1278(that)X
+1425(updates)X
+1697(a)X
+1760(B-tree)X
+1988(aborts,)X
+2231(the)X
+2356(user-visible)X
+2757(changes)X
+3043(to)X
+3131(the)X
+3255(tree)X
+3402(must)X
+3583(be)X
+3685(rolled)X
+3898(back.)X
+4116(How-)X
+555 2568(ever,)N
+735(changes)X
+1015(to)X
+1097(the)X
+1215(internal)X
+1480(nodes)X
+1687(of)X
+1774(the)X
+1892(tree)X
+2033(need)X
+2205(not)X
+2327(be)X
+2423(rolled)X
+2630(back,)X
+2822(since)X
+3007(these)X
+3192(pages)X
+3395(contain)X
+3651(no)X
+3751(user-visible)X
+4145(data.)X
+555 2658(When)N
+771(rolling)X
+1008(back)X
+1184(a)X
+1244(transaction,)X
+1640(we)X
+1758(roll)X
+1893(back)X
+2069(all)X
+2173(leaf)X
+2318(page)X
+2494(updates,)X
+2783(but)X
+2909(no)X
+3013(internal)X
+3281(insertions)X
+3615(or)X
+3705(page)X
+3880(splits.)X
+4111(In)X
+4201(the)X
+555 2748(worst)N
+759(case,)X
+944(this)X
+1085(will)X
+1235(leave)X
+1431(a)X
+1493(leaf)X
+1640(page)X
+1818(less)X
+1964(than)X
+2128(half)X
+2279(full.)X
+2456(This)X
+2624(may)X
+2788(cause)X
+2993(poor)X
+3166(space)X
+3371(utilization,)X
+3741(but)X
+3869(does)X
+4042(not)X
+4170(lose)X
+555 2838(user)N
+709(data.)X
+755 2961(Holding)N
+1038(locks)X
+1228(on)X
+1329(leaf)X
+1471(pages)X
+1675(until)X
+1842(transaction)X
+2215(commit)X
+2480(guarantees)X
+2845(that)X
+2986(no)X
+3087(other)X
+3273(process)X
+3535(can)X
+3668(insert)X
+3866(or)X
+3953(delete)X
+4165(data)X
+555 3051(that)N
+711(has)X
+854(been)X
+1042(touched)X
+1332(by)X
+1448(this)X
+1598(process.)X
+1914(Rolling)X
+2188(back)X
+2375(insertions)X
+2721(and)X
+2872(deletions)X
+3196(on)X
+3311(leaf)X
+3467(pages)X
+3685(guarantees)X
+4064(that)X
+4219(no)X
+555 3141(aborted)N
+819(updates)X
+1087(are)X
+1209(ever)X
+1371(visible)X
+1607(to)X
+1692(other)X
+1880(transactions.)X
+2326(Leaving)X
+2612(page)X
+2787(splits)X
+2978(intact)X
+3179(permits)X
+3442(us)X
+3536(to)X
+3621(release)X
+3867(internal)X
+4134(write)X
+555 3231(locks)N
+744(early.)X
+965(Thus)X
+1145(transaction)X
+1517(semantics)X
+1853(are)X
+1972(preserved,)X
+2325(and)X
+2461(locks)X
+2650(are)X
+2769(held)X
+2927(for)X
+3041(shorter)X
+3284(periods.)X
+755 3354(The)N
+901(extra)X
+1083(complexity)X
+1464(introduced)X
+1828(by)X
+1929(this)X
+2065(locking)X
+2326(protocol)X
+2614(appears)X
+2881(substantial,)X
+3264(but)X
+3387(it)X
+3452(is)X
+3525(important)X
+3856(for)X
+3970(multi-user)X
+555 3444(execution.)N
+950(The)X
+1118(bene\256ts)X
+1410(of)X
+1520(non-two-phase)X
+2040(locking)X
+2323(on)X
+2446(B-trees)X
+2721(are)X
+2863(well)X
+3044(established)X
+3443(in)X
+3548(the)X
+3689(database)X
+4009(literature)X
+555 3534([BAY77],)N
+899([LEHM81].)X
+1320(If)X
+1394(a)X
+1450(process)X
+1711(held)X
+1869(locks)X
+2058(until)X
+2224(it)X
+2288(committed,)X
+2670(then)X
+2828(a)X
+2884(long-running)X
+3322(update)X
+3556(could)X
+3754(lock)X
+3912(out)X
+4034(all)X
+4134(other)X
+555 3624(transactions)N
+967(by)X
+1076(preventing)X
+1448(any)X
+1593(other)X
+1787(process)X
+2057(from)X
+2241(locking)X
+2509(the)X
+2635(root)X
+2792(page)X
+2972(of)X
+3067(the)X
+3193(tree.)X
+3382(The)X
+3535(B-tree)X
+3764(locking)X
+4032(protocol)X
+555 3714(described)N
+884(above)X
+1096(guarantees)X
+1460(that)X
+1600(locks)X
+1789(on)X
+1889(internal)X
+2154(pages)X
+2357(are)X
+2476(held)X
+2634(for)X
+2748(extremely)X
+3089(short)X
+3269(periods,)X
+3545(thereby)X
+3806(increasing)X
+4156(con-)X
+555 3804(currency.)N
+3 f
+555 3990(3.1.3.)N
+775(Management)X
+1245(of)X
+1332(Shared)X
+1596(Data)X
+1 f
+755 4113(Database)N
+1075(systems)X
+1353(permit)X
+1587(many)X
+1790(users)X
+1980(to)X
+2067(examine)X
+2364(and)X
+2505(update)X
+2744(the)X
+2866(same)X
+3055(data)X
+3213(concurrently.)X
+3683(In)X
+3774(order)X
+3968(to)X
+4054(provide)X
+555 4203(this)N
+702(concurrent)X
+1078(access)X
+1316(and)X
+1464(enforce)X
+1738(the)X
+1868(write-ahead)X
+2280(logging)X
+2556(protocol)X
+2855(described)X
+3195(in)X
+3289(section)X
+3548(3.1.1,)X
+3759(we)X
+3884(use)X
+4022(a)X
+4089(shared)X
+555 4293(memory)N
+848(buffer)X
+1071(manager.)X
+1414(Not)X
+1559(only)X
+1726(does)X
+1898(this)X
+2038(provide)X
+2308(the)X
+2431(guarantees)X
+2800(we)X
+2919(require,)X
+3192(but)X
+3319(a)X
+3380(user-level)X
+3722(buffer)X
+3944(manager)X
+4246(is)X
+555 4383(frequently)N
+916(faster)X
+1126(than)X
+1295(using)X
+1498(the)X
+1626(\256le)X
+1758(system)X
+2010(buffer)X
+2237(cache.)X
+2491(Reads)X
+2717(or)X
+2814(writes)X
+3040(involving)X
+3376(the)X
+3504(\256le)X
+3636(system)X
+3888(buffer)X
+4115(cache)X
+555 4473(often)N
+746(require)X
+1000(copying)X
+1284(data)X
+1444(between)X
+1738(user)X
+1898(and)X
+2040(kernel)X
+2266(space)X
+2470(while)X
+2673(a)X
+2734(user-level)X
+3076(buffer)X
+3298(manager)X
+3600(can)X
+3737(return)X
+3954(pointers)X
+4237(to)X
+555 4563(data)N
+709(pages)X
+912(directly.)X
+1217(Additionally,)X
+1661(if)X
+1730(more)X
+1915(than)X
+2073(one)X
+2209(process)X
+2470(uses)X
+2628(the)X
+2746(same)X
+2931(page,)X
+3123(then)X
+3281(fewer)X
+3485(copies)X
+3710(may)X
+3868(be)X
+3964(required.)X
+3 f
+555 4749(3.2.)N
+715(Module)X
+997(Architecture)X
+1 f
+755 4872(The)N
+913(preceding)X
+1262(sections)X
+1552(described)X
+1892(modules)X
+2195(for)X
+2321(managing)X
+2669(the)X
+2799(transaction)X
+3183(log,)X
+3337(locks,)X
+3558(and)X
+3706(a)X
+3774(cache)X
+3990(of)X
+4089(shared)X
+555 4962(buffers.)N
+847(In)X
+938(addition,)X
+1244(we)X
+1362(need)X
+1538(to)X
+1624(provide)X
+1893(functionality)X
+2326(for)X
+2444(transaction)X
+2 f
+2819(begin)X
+1 f
+2997(,)X
+2 f
+3040(commit)X
+1 f
+3276(,)X
+3319(and)X
+2 f
+3458(abort)X
+1 f
+3654(processing,)X
+4040(necessi-)X
+555 5052(tating)N
+769(a)X
+837(transaction)X
+1221(manager.)X
+1570(In)X
+1669(order)X
+1871(to)X
+1965(arbitrate)X
+2265(concurrent)X
+2641(access)X
+2879(to)X
+2973(locks)X
+3173(and)X
+3320(buffers,)X
+3599(we)X
+3724(include)X
+3991(a)X
+4058(process)X
+555 5142(management)N
+995(module)X
+1264(which)X
+1489(manages)X
+1799(a)X
+1864(collection)X
+2209(of)X
+2305(semaphores)X
+2713(used)X
+2889(to)X
+2980(block)X
+3187(and)X
+3332(release)X
+3585(processes.)X
+3962(Finally,)X
+4237(in)X
+555 5232(order)N
+752(to)X
+841(provide)X
+1113(a)X
+1176(simple,)X
+1436(standard)X
+1735(interface)X
+2044(we)X
+2165(have)X
+2344(modi\256ed)X
+2655(the)X
+2780(database)X
+3084(access)X
+3317(routines)X
+3602(\()X
+3 f
+3629(db)X
+1 f
+3717(\(3\)\).)X
+3904(For)X
+4041(the)X
+4165(pur-)X
+555 5322(poses)N
+758(of)X
+850(this)X
+990(paper)X
+1194(we)X
+1313(call)X
+1453(the)X
+1575(modi\256ed)X
+1883(package)X
+2171(the)X
+3 f
+2293(Record)X
+2567(Manager)X
+1 f
+2879(.)X
+2943(Figure)X
+3176(one)X
+3316(shows)X
+3540(the)X
+3662(main)X
+3846(interfaces)X
+4183(and)X
+555 5412(architecture)N
+955(of)X
+1042(LIBTP.)X
+
+5 p
+%%Page: 5 5
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+11 s
+1851 1520(log_commit)N
+2764 2077(buf_unpin)N
+2764 1987(buf_get)N
+3633 1408(buf_unpin)N
+3633 1319(buf_pin)N
+3633 1230(buf_get)N
+3 f
+17 s
+1163 960(Txn)N
+1430(M)X
+1559(anager)X
+2582(Record)X
+3040(M)X
+3169(anager)X
+1 Dt
+2363 726 MXY
+0 355 Dl
+1426 0 Dl
+0 -355 Dl
+-1426 0 Dl
+3255 1616 MXY
+0 535 Dl
+534 0 Dl
+0 -535 Dl
+-534 0 Dl
+2185 MX
+0 535 Dl
+535 0 Dl
+0 -535 Dl
+-535 0 Dl
+1116 MX
+0 535 Dl
+534 0 Dl
+0 -535 Dl
+-534 0 Dl
+726 MY
+0 355 Dl
+891 0 Dl
+0 -355 Dl
+-891 0 Dl
+1 f
+11 s
+2207 1297(lock)N
+2564 1386(log)N
+865(unlock_all)X
+1851 1609(log_unroll)N
+1650 2508 MXY
+0 178 Dl
+1605 0 Dl
+0 -178 Dl
+-1605 0 Dl
+1294 1616 MXY
+19 -30 Dl
+-19 11 Dl
+-20 -11 Dl
+20 30 Dl
+0 -535 Dl
+2319 2508 MXY
+-22 -30 Dl
+4 23 Dl
+-18 14 Dl
+36 -7 Dl
+-936 -357 Dl
+3277 2455(sleep_on)N
+1405 1616 MXY
+36 4 Dl
+-18 -13 Dl
+1 -22 Dl
+-19 31 Dl
+1070 -535 Dl
+2631 2508 MXY
+36 6 Dl
+-18 -14 Dl
+3 -22 Dl
+-21 30 Dl
+891 -357 Dl
+1426 2455(sleep_on)N
+3255 1884 MXY
+-31 -20 Dl
+11 20 Dl
+-11 19 Dl
+31 -19 Dl
+-535 0 Dl
+1554 2366(wake)N
+3277(wake)X
+2185 1884 MXY
+-31 -20 Dl
+12 20 Dl
+-12 19 Dl
+31 -19 Dl
+-356 0 Dl
+0 -803 Dl
+3 f
+17 s
+1236 1851(Lock)N
+1118 2030(M)N
+1247(anager)X
+2339 1851(Log)N
+2187 2030(M)N
+2316(anager)X
+3333 1851(Buffer)N
+3257 2030(M)N
+3386(anager)X
+3522 1616 MXY
+20 -30 Dl
+-20 11 Dl
+-20 -11 Dl
+20 30 Dl
+0 -535 Dl
+1950 2654(Process)N
+2424(M)X
+2553(anager)X
+2542 1616 MXY
+19 -30 Dl
+-19 11 Dl
+-20 -11 Dl
+20 30 Dl
+0 -535 Dl
+1 f
+11 s
+2207 1364(unlock)N
+2452 2508 MXY
+20 -31 Dl
+-20 11 Dl
+-19 -11 Dl
+19 31 Dl
+0 -357 Dl
+2497 2322(sleep_on)N
+2497 2233(wake)N
+3 Dt
+-1 Ds
+3 f
+10 s
+1790 2830(Figure)N
+2037(1:)X
+2144(Library)X
+2435(module)X
+2708(interfaces.)X
+1 f
+10 f
+555 3010(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+3 f
+555 3286(3.2.1.)N
+775(The)X
+928(Log)X
+1081(Manager)X
+1 f
+755 3409(The)N
+3 f
+907(Log)X
+1067(Manager)X
+1 f
+1406(enforces)X
+1706(the)X
+1831(write-ahead)X
+2238(logging)X
+2509(protocol.)X
+2843(Its)X
+2949(primitive)X
+3268(operations)X
+3628(are)X
+2 f
+3753(log)X
+1 f
+3855(,)X
+2 f
+3901(log_commit)X
+1 f
+4279(,)X
+2 f
+555 3499(log_read)N
+1 f
+844(,)X
+2 f
+889(log_roll)X
+1 f
+1171(and)X
+2 f
+1312(log_unroll)X
+1 f
+1649(.)X
+1714(The)X
+2 f
+1864(log)X
+1 f
+1991(call)X
+2132(performs)X
+2447(a)X
+2508(buffered)X
+2806(write)X
+2996(of)X
+3088(the)X
+3211(speci\256ed)X
+3520(log)X
+3646(record)X
+3876(and)X
+4016(returns)X
+4263(a)X
+555 3589(unique)N
+809(log)X
+947(sequence)X
+1278(number)X
+1559(\(LSN\).)X
+1840(This)X
+2017(LSN)X
+2203(may)X
+2376(then)X
+2549(be)X
+2660(used)X
+2842(to)X
+2939(retrieve)X
+3220(a)X
+3291(record)X
+3532(from)X
+3723(the)X
+3856(log)X
+3993(using)X
+4201(the)X
+2 f
+555 3679(log_read)N
+1 f
+865(call.)X
+1042(The)X
+2 f
+1188(log)X
+1 f
+1311(interface)X
+1614(knows)X
+1844(very)X
+2008(little)X
+2175(about)X
+2374(the)X
+2493(internal)X
+2759(format)X
+2993(of)X
+3080(the)X
+3198(log)X
+3320(records)X
+3577(it)X
+3641(receives.)X
+3965(Rather,)X
+4219(all)X
+555 3769(log)N
+681(records)X
+942(are)X
+1065 0.4028(referenced)AX
+1430(by)X
+1534(a)X
+1594(header)X
+1833(structure,)X
+2158(a)X
+2218(log)X
+2344(record)X
+2574(type,)X
+2756(and)X
+2896(a)X
+2956(character)X
+3276(buffer)X
+3497(containing)X
+3859(the)X
+3981(data)X
+4138(to)X
+4223(be)X
+555 3859(logged.)N
+834(The)X
+980(log)X
+1103(record)X
+1330(type)X
+1489(is)X
+1563(used)X
+1731(to)X
+1814(call)X
+1951(the)X
+2070(appropriate)X
+2457(redo)X
+2621(and)X
+2758(undo)X
+2939(routines)X
+3217(during)X
+2 f
+3446(abort)X
+1 f
+3639(and)X
+2 f
+3775(commit)X
+1 f
+4031(process-)X
+555 3949(ing.)N
+721(While)X
+941(we)X
+1059(have)X
+1235(used)X
+1406(the)X
+3 f
+1528(Log)X
+1684(Manager)X
+1 f
+2019(to)X
+2104(provide)X
+2372(before)X
+2601(and)X
+2740(after)X
+2911(image)X
+3130(logging,)X
+3417(it)X
+3484(may)X
+3645(also)X
+3797(be)X
+3896(used)X
+4066(for)X
+4183(any)X
+555 4039(of)N
+642(the)X
+760(logging)X
+1024(algorithms)X
+1386(discussed.)X
+755 4162(The)N
+2 f
+905(log_commit)X
+1 f
+1308(operation)X
+1636(behaves)X
+1920(exactly)X
+2177(like)X
+2322(the)X
+2 f
+2445(log)X
+1 f
+2572(operation)X
+2900(but)X
+3026(guarantees)X
+3394(that)X
+3538(the)X
+3660(log)X
+3786(has)X
+3917(been)X
+4093(forced)X
+555 4252(to)N
+643(disk)X
+802(before)X
+1034(returning.)X
+1394(A)X
+1478(discussion)X
+1837(of)X
+1930(our)X
+2063(commit)X
+2333(strategy)X
+2613(appears)X
+2884(in)X
+2971(the)X
+3094(implementation)X
+3621(section)X
+3873(\(section)X
+4152(4.2\).)X
+2 f
+555 4342(Log_unroll)N
+1 f
+935(reads)X
+1126(log)X
+1249(records)X
+1507(from)X
+1684(the)X
+1803(log,)X
+1946(following)X
+2278(backward)X
+2611(transaction)X
+2983(pointers)X
+3261(and)X
+3397(calling)X
+3635(the)X
+3753(appropriate)X
+4139(undo)X
+555 4432(routines)N
+839(to)X
+927(implement)X
+1295(transaction)X
+1673(abort.)X
+1904(In)X
+1997(a)X
+2059(similar)X
+2307(manner,)X
+2 f
+2594(log_roll)X
+1 f
+2877(reads)X
+3073(log)X
+3201(records)X
+3464(sequentially)X
+3877(forward,)X
+4178(cal-)X
+555 4522(ling)N
+699(the)X
+817(appropriate)X
+1203(redo)X
+1366(routines)X
+1644(to)X
+1726(recover)X
+1988(committed)X
+2350(transactions)X
+2753(after)X
+2921(a)X
+2977(system)X
+3219(crash.)X
+3 f
+555 4708(3.2.2.)N
+775(The)X
+928(Buffer)X
+1171(Manager)X
+1 f
+755 4831(The)N
+3 f
+912(Buffer)X
+1167(Manager)X
+1 f
+1511(uses)X
+1681(a)X
+1749(pool)X
+1923(of)X
+2022(shared)X
+2264(memory)X
+2563(to)X
+2657(provide)X
+2934(a)X
+3002(least-recently-used)X
+3641(\(LRU\))X
+3886(block)X
+4095(cache.)X
+555 4921(Although)N
+886(the)X
+1013(current)X
+1270(library)X
+1513(provides)X
+1818(an)X
+1923(LRU)X
+2112(cache,)X
+2345(it)X
+2418(would)X
+2647(be)X
+2752(simple)X
+2994(to)X
+3085(add)X
+3229(alternate)X
+3534(replacement)X
+3955(policies)X
+4232(as)X
+555 5011(suggested)N
+903(by)X
+1015([CHOU85])X
+1408(or)X
+1507(to)X
+1601(provide)X
+1878(multiple)X
+2176(buffer)X
+2405(pools)X
+2610(with)X
+2784(different)X
+3092(policies.)X
+3412(Transactions)X
+3853(request)X
+4116(pages)X
+555 5101(from)N
+736(the)X
+859(buffer)X
+1081(manager)X
+1383(and)X
+1524(keep)X
+1701(them)X
+3 f
+1886(pinned)X
+1 f
+2145(to)X
+2232(ensure)X
+2466(that)X
+2610(they)X
+2772(are)X
+2895(not)X
+3021(written)X
+3272(to)X
+3358(disk)X
+3515(while)X
+3717(they)X
+3879(are)X
+4002(in)X
+4088(a)X
+4148(logi-)X
+555 5191(cally)N
+732(inconsistent)X
+1135(state.)X
+1343(When)X
+1556(page)X
+1729(replacement)X
+2143(is)X
+2217(necessary,)X
+2571(the)X
+3 f
+2689(Buffer)X
+2932(Manager)X
+1 f
+3264(\256nds)X
+3439(an)X
+3535(unpinned)X
+3853(page)X
+4025(and)X
+4161(then)X
+555 5281(checks)N
+794(with)X
+956(the)X
+3 f
+1074(Log)X
+1227(Manager)X
+1 f
+1559(to)X
+1641(ensure)X
+1871(that)X
+2011(the)X
+2129(write-ahead)X
+2529(protocol)X
+2816(is)X
+2889(enforced.)X
+3 f
+555 5467(3.2.3.)N
+775(The)X
+928(Lock)X
+1121(Manager)X
+1 f
+755 5590(The)N
+3 f
+901(Lock)X
+1095(Manager)X
+1 f
+1428(supports)X
+1720(general)X
+1978(purpose)X
+2253(locking)X
+2514(\(single)X
+2753(writer,)X
+2986(multiple)X
+3273(readers\))X
+3553(which)X
+3769(is)X
+3842(currently)X
+4152(used)X
+555 5680(to)N
+638(provide)X
+904(two-phase)X
+1254(locking)X
+1514(and)X
+1650(high)X
+1812(concurrency)X
+2230(B-tree)X
+2451(locking.)X
+2751(However,)X
+3086(the)X
+3204(general)X
+3461(purpose)X
+3735(nature)X
+3956(of)X
+4043(the)X
+4161(lock)X
+
+6 p
+%%Page: 6 6
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+555 630(manager)N
+857(provides)X
+1158(the)X
+1281(ability)X
+1510(to)X
+1597(support)X
+1862(a)X
+1923(variety)X
+2171(of)X
+2263(locking)X
+2528(protocols.)X
+2890(Currently,)X
+3241(all)X
+3345(locks)X
+3538(are)X
+3661(issued)X
+3885(at)X
+3967(the)X
+4089(granu-)X
+555 720(larity)N
+747(of)X
+837(a)X
+896(page)X
+1071(\(the)X
+1219(size)X
+1367(of)X
+1457(a)X
+1516(buffer)X
+1736(in)X
+1821(the)X
+1942(buffer)X
+2161(pool\))X
+2352(which)X
+2570(is)X
+2645(identi\256ed)X
+2969(by)X
+3071(two)X
+3213(4-byte)X
+3440(integers)X
+3716(\(a)X
+3801(\256le)X
+3925(id)X
+4009(and)X
+4147(page)X
+555 810(number\).)N
+898(This)X
+1071(provides)X
+1378(the)X
+1507(necessary)X
+1851(information)X
+2259(to)X
+2351(extend)X
+2595(the)X
+3 f
+2723(Lock)X
+2926(Manager)X
+1 f
+3268(to)X
+3360(perform)X
+3649(hierarchical)X
+4059(locking)X
+555 900([GRAY76].)N
+982(The)X
+1133(current)X
+1387(implementation)X
+1915(does)X
+2088(not)X
+2216(support)X
+2482(locks)X
+2677(at)X
+2760(other)X
+2950(granularities)X
+3376(and)X
+3517(does)X
+3689(not)X
+3816(promote)X
+4108(locks;)X
+555 990(these)N
+740(are)X
+859(obvious)X
+1132(future)X
+1344(additions)X
+1657(to)X
+1739(the)X
+1857(system.)X
+755 1113(If)N
+831(an)X
+929(incoming)X
+1253(lock)X
+1413(request)X
+1667(cannot)X
+1903(be)X
+2001(granted,)X
+2284(the)X
+2404(requesting)X
+2760(process)X
+3023(is)X
+3098(queued)X
+3352(for)X
+3467(the)X
+3586(lock)X
+3745(and)X
+3882(descheduled.)X
+555 1203(When)N
+769(a)X
+827(lock)X
+987(is)X
+1062(released,)X
+1368(the)X
+1488(wait)X
+1647(queue)X
+1860(is)X
+1934(traversed)X
+2250(and)X
+2387(any)X
+2524(newly)X
+2741(compatible)X
+3118(locks)X
+3308(are)X
+3428(granted.)X
+3730(Locks)X
+3947(are)X
+4067(located)X
+555 1293(via)N
+680(a)X
+743(\256le)X
+872(and)X
+1015(page)X
+1194(hash)X
+1368(table)X
+1551(and)X
+1694(are)X
+1820(chained)X
+2097(both)X
+2266(by)X
+2373(object)X
+2595(and)X
+2737(by)X
+2843(transaction,)X
+3241(facilitating)X
+3614(rapid)X
+3805(traversal)X
+4108(of)X
+4201(the)X
+555 1383(lock)N
+713(table)X
+889(during)X
+1118(transaction)X
+1490(commit)X
+1754(and)X
+1890(abort.)X
+755 1506(The)N
+907(primary)X
+1188(interfaces)X
+1528(to)X
+1617(the)X
+1742(lock)X
+1907(manager)X
+2211(are)X
+2 f
+2337(lock)X
+1 f
+2471(,)X
+2 f
+2518(unlock)X
+1 f
+2732(,)X
+2779(and)X
+2 f
+2922(lock_unlock_all)X
+1 f
+3434(.)X
+2 f
+3500(Lock)X
+1 f
+3682(obtains)X
+3939(a)X
+4001(new)X
+4161(lock)X
+555 1596(for)N
+680(a)X
+747(speci\256c)X
+1023(object.)X
+1290(There)X
+1509(are)X
+1638(also)X
+1797(two)X
+1947(variants)X
+2231(of)X
+2328(the)X
+2 f
+2456(lock)X
+1 f
+2620(request,)X
+2 f
+2902(lock_upgrade)X
+1 f
+3373(and)X
+2 f
+3519(lock_downgrade)X
+1 f
+4053(,)X
+4103(which)X
+555 1686(allow)N
+755(the)X
+875(caller)X
+1076(to)X
+1160(atomically)X
+1519(trade)X
+1701(a)X
+1758(lock)X
+1917(of)X
+2005(one)X
+2142(type)X
+2301(for)X
+2416(a)X
+2473(lock)X
+2632(of)X
+2720(another.)X
+2 f
+3022(Unlock)X
+1 f
+3275(releases)X
+3551(a)X
+3608(speci\256c)X
+3874(mode)X
+4073(of)X
+4161(lock)X
+555 1776(on)N
+655(a)X
+711(speci\256c)X
+976(object.)X
+2 f
+1232(Lock_unlock_all)X
+1 f
+1786(releases)X
+2061(all)X
+2161(the)X
+2279(locks)X
+2468(associated)X
+2818(with)X
+2980(a)X
+3036(speci\256c)X
+3301(transaction.)X
+3 f
+555 1962(3.2.4.)N
+775(The)X
+928(Process)X
+1207(Manager)X
+1 f
+755 2085(The)N
+3 f
+900(Process)X
+1179(Manager)X
+1 f
+1511(acts)X
+1656(as)X
+1743(a)X
+1799(user-level)X
+2136(scheduler)X
+2464(to)X
+2546(make)X
+2740(processes)X
+3068(wait)X
+3226(on)X
+3326(unavailable)X
+3716(locks)X
+3905(and)X
+4041(pending)X
+555 2175(buffer)N
+778(cache)X
+988(I/O.)X
+1161(For)X
+1297(each)X
+1470(process,)X
+1756(a)X
+1817(semaphore)X
+2190(is)X
+2268(maintained)X
+2649(upon)X
+2834(which)X
+3055(that)X
+3200(process)X
+3466(waits)X
+3660(when)X
+3859(it)X
+3928(needs)X
+4136(to)X
+4223(be)X
+555 2265(descheduled.)N
+1014(When)X
+1228(a)X
+1286(process)X
+1549(needs)X
+1754(to)X
+1838(be)X
+1936(run,)X
+2084(its)X
+2180(semaphore)X
+2549(is)X
+2623(cleared,)X
+2897(and)X
+3034(the)X
+3153(operating)X
+3477(system)X
+3720(reschedules)X
+4116(it.)X
+4201(No)X
+555 2355(sophisticated)N
+1002(scheduling)X
+1378(algorithm)X
+1718(is)X
+1799(applied;)X
+2085(if)X
+2162(the)X
+2288(lock)X
+2454(for)X
+2576(which)X
+2800(a)X
+2864(process)X
+3133(was)X
+3286(waiting)X
+3554(becomes)X
+3863(available,)X
+4201(the)X
+555 2445(process)N
+824(is)X
+905(made)X
+1107(runnable.)X
+1456(It)X
+1533(would)X
+1761(have)X
+1941(been)X
+2121(possible)X
+2411(to)X
+2501(change)X
+2757(the)X
+2883(kernel's)X
+3170(process)X
+3439(scheduler)X
+3775(to)X
+3865(interact)X
+4134(more)X
+555 2535(ef\256ciently)N
+900(with)X
+1062(the)X
+1180(lock)X
+1338(manager,)X
+1655(but)X
+1777(doing)X
+1979(so)X
+2070(would)X
+2290(have)X
+2462(compromised)X
+2918(our)X
+3045(commitment)X
+3469(to)X
+3551(a)X
+3607(user-level)X
+3944(package.)X
+3 f
+555 2721(3.2.5.)N
+775(The)X
+928(Transaction)X
+1361(Manager)X
+1 f
+755 2844(The)N
+3 f
+901(Transaction)X
+1335(Manager)X
+1 f
+1668(provides)X
+1965(the)X
+2084(standard)X
+2377(interface)X
+2680(of)X
+2 f
+2768(txn_begin)X
+1 f
+3084(,)X
+2 f
+3125(txn_commit)X
+1 f
+3499(,)X
+3540(and)X
+2 f
+3676(txn_abort)X
+1 f
+3987(.)X
+4047(It)X
+4116(keeps)X
+555 2934(track)N
+742(of)X
+835(all)X
+941(active)X
+1159(transactions,)X
+1588(assigns)X
+1845(unique)X
+2089(transaction)X
+2467(identi\256ers,)X
+2833(and)X
+2974(directs)X
+3213(the)X
+3336(abort)X
+3526(and)X
+3667(commit)X
+3936(processing.)X
+555 3024(When)N
+772(a)X
+2 f
+833(txn_begin)X
+1 f
+1174(is)X
+1252(issued,)X
+1497(the)X
+3 f
+1620(Transaction)X
+2058(Manager)X
+1 f
+2395(assigns)X
+2651(the)X
+2773(next)X
+2935(available)X
+3249(transaction)X
+3625(identi\256er,)X
+3958(allocates)X
+4263(a)X
+555 3114(per-process)N
+948(transaction)X
+1322(structure)X
+1625(in)X
+1709(shared)X
+1941(memory,)X
+2249(increments)X
+2622(the)X
+2741(count)X
+2940(of)X
+3028(active)X
+3241(transactions,)X
+3665(and)X
+3802(returns)X
+4046(the)X
+4165(new)X
+555 3204(transaction)N
+937(identi\256er)X
+1256(to)X
+1348(the)X
+1476(calling)X
+1724(process.)X
+2034(The)X
+2188(in-memory)X
+2573(transaction)X
+2954(structure)X
+3264(contains)X
+3560(a)X
+3625(pointer)X
+3881(into)X
+4034(the)X
+4161(lock)X
+555 3294(table)N
+734(for)X
+851(locks)X
+1043(held)X
+1204(by)X
+1307(this)X
+1445(transaction,)X
+1840(the)X
+1961(last)X
+2095(log)X
+2220(sequence)X
+2538(number,)X
+2826(a)X
+2885(transaction)X
+3260(state)X
+3430(\()X
+2 f
+3457(idle)X
+1 f
+(,)S
+2 f
+3620(running)X
+1 f
+3873(,)X
+2 f
+3915(aborting)X
+1 f
+4190(,)X
+4232(or)X
+2 f
+555 3384(committing\))N
+1 f
+942(,)X
+982(an)X
+1078(error)X
+1255(code,)X
+1447(and)X
+1583(a)X
+1639(semaphore)X
+2007(identi\256er.)X
+755 3507(At)N
+859(commit,)X
+1147(the)X
+3 f
+1269(Transaction)X
+1706(Manager)X
+1 f
+2042(calls)X
+2 f
+2213(log_commit)X
+1 f
+2615(to)X
+2700(record)X
+2929(the)X
+3050(end)X
+3189(of)X
+3279(transaction)X
+3654(and)X
+3793(to)X
+3878(\257ush)X
+4056(the)X
+4177(log.)X
+555 3597(Then)N
+743(it)X
+810(directs)X
+1047(the)X
+3 f
+1168(Lock)X
+1364(Manager)X
+1 f
+1699(to)X
+1784(release)X
+2031(all)X
+2134(locks)X
+2325(associated)X
+2677(with)X
+2841(the)X
+2961(given)X
+3161(transaction.)X
+3575(If)X
+3651(a)X
+3709(transaction)X
+4083(aborts,)X
+555 3687(the)N
+3 f
+680(Transaction)X
+1120(Manager)X
+1 f
+1459(calls)X
+1633(on)X
+2 f
+1739(log_unroll)X
+1 f
+2102(to)X
+2190(read)X
+2355(the)X
+2479(transaction's)X
+2915(log)X
+3043(records)X
+3306(and)X
+3448(undo)X
+3634(any)X
+3776(modi\256cations)X
+4237(to)X
+555 3777(the)N
+673(database.)X
+1010(As)X
+1119(in)X
+1201(the)X
+1319(commit)X
+1583(case,)X
+1762(it)X
+1826(then)X
+1984(calls)X
+2 f
+2151(lock_unlock_all)X
+1 f
+2683(to)X
+2765(release)X
+3009(the)X
+3127(transaction's)X
+3557(locks.)X
+3 f
+555 3963(3.2.6.)N
+775(The)X
+928(Record)X
+1198(Manager)X
+1 f
+755 4086(The)N
+3 f
+919(Record)X
+1208(Manager)X
+1 f
+1559(supports)X
+1869(the)X
+2006(abstraction)X
+2397(of)X
+2503(reading)X
+2783(and)X
+2938(writing)X
+3208(records)X
+3484(to)X
+3585(a)X
+3660(database.)X
+3996(We)X
+4147(have)X
+555 4176(modi\256ed)N
+861(the)X
+981(the)X
+1101(database)X
+1399(access)X
+1626(routines)X
+3 f
+1905(db)X
+1 f
+1993(\(3\))X
+2108([BSD91])X
+2418(to)X
+2501(call)X
+2638(the)X
+2757(log,)X
+2900(lock,)X
+3079(and)X
+3216(buffer)X
+3434(managers.)X
+3803(In)X
+3891(order)X
+4082(to)X
+4165(pro-)X
+555 4266(vide)N
+718(functionality)X
+1152(to)X
+1239(perform)X
+1523(undo)X
+1708(and)X
+1849(redo,)X
+2037(the)X
+3 f
+2160(Record)X
+2434(Manager)X
+1 f
+2770(de\256nes)X
+3021(a)X
+3081(collection)X
+3421(of)X
+3512(log)X
+3638(record)X
+3868(types)X
+4061(and)X
+4201(the)X
+555 4356(associated)N
+920(undo)X
+1115(and)X
+1266(redo)X
+1444(routines.)X
+1777(The)X
+3 f
+1937(Log)X
+2105(Manager)X
+1 f
+2452(performs)X
+2777(a)X
+2848(table)X
+3039(lookup)X
+3296(on)X
+3411(the)X
+3543(record)X
+3783(type)X
+3955(to)X
+4051(call)X
+4201(the)X
+555 4446(appropriate)N
+951(routines.)X
+1299(For)X
+1440(example,)X
+1762(the)X
+1890(B-tree)X
+2121(access)X
+2356(method)X
+2625(requires)X
+2913(two)X
+3062(log)X
+3193(record)X
+3428(types:)X
+3648(insert)X
+3855(and)X
+4000(delete.)X
+4241(A)X
+555 4536(replace)N
+808(operation)X
+1131(is)X
+1204(implemented)X
+1642(as)X
+1729(a)X
+1785(delete)X
+1997(followed)X
+2302(by)X
+2402(an)X
+2498(insert)X
+2696(and)X
+2832(is)X
+2905(logged)X
+3143(accordingly.)X
+3 f
+555 4722(3.3.)N
+715(Application)X
+1134(Architectures)X
+1 f
+755 4845(The)N
+907(structure)X
+1215(of)X
+1309(LIBTP)X
+1558(allows)X
+1794(application)X
+2177(designers)X
+2507(to)X
+2596(trade)X
+2784(off)X
+2905(performance)X
+3339(and)X
+3481(protection.)X
+3872(Since)X
+4076(a)X
+4138(large)X
+555 4935(portion)N
+810(of)X
+901(LIBTP's)X
+1205(functionality)X
+1638(is)X
+1715(provided)X
+2024(by)X
+2128(managing)X
+2468(structures)X
+2804(in)X
+2889(shared)X
+3122(memory,)X
+3432(its)X
+3530(structures)X
+3865(are)X
+3987(subject)X
+4237(to)X
+555 5025(corruption)N
+926(by)X
+1043(applications)X
+1467(when)X
+1678(the)X
+1813(library)X
+2064(is)X
+2154(linked)X
+2391(directly)X
+2673(with)X
+2852(the)X
+2987(application.)X
+3420(For)X
+3568(this)X
+3720(reason,)X
+3987(LIBTP)X
+4246(is)X
+555 5115(designed)N
+864(to)X
+950(allow)X
+1152(compilation)X
+1558(into)X
+1706(a)X
+1766(separate)X
+2053(server)X
+2273(process)X
+2537(which)X
+2756(may)X
+2917(be)X
+3016(accessed)X
+3321(via)X
+3442(a)X
+3501(socket)X
+3729(interface.)X
+4094(In)X
+4184(this)X
+555 5205(way)N
+712(LIBTP's)X
+1015(data)X
+1172(structures)X
+1507(are)X
+1629(protected)X
+1951(from)X
+2130(application)X
+2509(code,)X
+2704(but)X
+2829(communication)X
+3349(overhead)X
+3666(is)X
+3741(increased.)X
+4107(When)X
+555 5295(applications)N
+975(are)X
+1107(trusted,)X
+1377(LIBTP)X
+1631(may)X
+1801(be)X
+1909(compiled)X
+2239(directly)X
+2516(into)X
+2672(the)X
+2802(application)X
+3190(providing)X
+3533(improved)X
+3872(performance.)X
+555 5385(Figures)N
+815(two)X
+955(and)X
+1091(three)X
+1272(show)X
+1461(the)X
+1579(two)X
+1719(alternate)X
+2016(application)X
+2392(architectures.)X
+755 5508(There)N
+964(are)X
+1084(potentially)X
+1447(two)X
+1588(modes)X
+1818(in)X
+1901(which)X
+2118(one)X
+2255(might)X
+2462(use)X
+2590(LIBTP)X
+2833(in)X
+2916(a)X
+2972(server)X
+3189(based)X
+3392(architecture.)X
+3832(In)X
+3919(the)X
+4037(\256rst,)X
+4201(the)X
+555 5598(server)N
+778(would)X
+1004(provide)X
+1275(the)X
+1399(capability)X
+1741(to)X
+1829(respond)X
+2109(to)X
+2197(requests)X
+2486(to)X
+2574(each)X
+2747(of)X
+2839(the)X
+2962(low)X
+3107(level)X
+3288(modules)X
+3584(\(lock,)X
+3794(log,)X
+3941(buffer,)X
+4183(and)X
+555 5688(transaction)N
+944(managers\).)X
+1356(Unfortunately,)X
+1863(the)X
+1998(performance)X
+2442(of)X
+2546(such)X
+2730(a)X
+2803(system)X
+3062(is)X
+3152(likely)X
+3371(to)X
+3470(be)X
+3583(blindingly)X
+3947(slow)X
+4134(since)X
+
+7 p
+%%Page: 7 7
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+1 Dt
+1864 1125 MXY
+15 -26 Dl
+-15 10 Dl
+-14 -10 Dl
+14 26 Dl
+0 -266 Dl
+1315 1125 MXY
+15 -26 Dl
+-15 10 Dl
+-14 -10 Dl
+14 26 Dl
+0 -266 Dl
+3 Dt
+1133 1125 MXY
+0 798 Dl
+931 0 Dl
+0 -798 Dl
+-931 0 Dl
+1 Dt
+1266 1257 MXY
+0 133 Dl
+665 0 Dl
+0 -133 Dl
+-665 0 Dl
+3 f
+8 s
+1513 1351(driver)N
+1502 1617(LIBTP)N
+1266 1390 MXY
+0 400 Dl
+665 0 Dl
+0 -400 Dl
+-665 0 Dl
+3 Dt
+1133 726 MXY
+0 133 Dl
+931 0 Dl
+0 -133 Dl
+-931 0 Dl
+1 f
+1029 1098(txn_abort)N
+964 1015(txn_commit)N
+1018 932(txn_begin)N
+1910 1015(db_ops)N
+3 f
+1308 820(Application)N
+1645(Program)X
+1398 1218(Server)N
+1594(Process)X
+1 f
+1390 986(socket)N
+1569(interface)X
+1 Dt
+1848 967 MXY
+-23 -14 Dl
+8 14 Dl
+-8 15 Dl
+23 -15 Dl
+-50 0 Dl
+1324 MX
+23 15 Dl
+-9 -15 Dl
+9 -14 Dl
+-23 14 Dl
+50 0 Dl
+3 Dt
+2862 859 MXY
+0 1064 Dl
+932 0 Dl
+0 -1064 Dl
+-932 0 Dl
+1 Dt
+3178 1390 MXY
+24 -12 Dl
+-17 0 Dl
+-8 -15 Dl
+1 27 Dl
+150 -265 Dl
+3494 1390 MXY
+0 -27 Dl
+-8 15 Dl
+-16 1 Dl
+24 11 Dl
+-166 -265 Dl
+3 f
+3232 1617(LIBTP)N
+2995 1390 MXY
+0 400 Dl
+666 0 Dl
+0 -400 Dl
+-666 0 Dl
+992 MY
+0 133 Dl
+666 0 Dl
+0 -133 Dl
+-666 0 Dl
+3168 1086(Application)N
+1 f
+2939 1201(txn_begin)N
+2885 1284(txn_commit)N
+2950 1368(txn_abort)N
+3465 1284(db_ops)N
+3 f
+3155 766(Single)N
+3339(Process)X
+3 Dt
+-1 Ds
+811 2100(Figure)N
+1023(2:)X
+1107(Server)X
+1318(Architecture.)X
+1 f
+1727(In)X
+1811(this)X
+1934(con\256guration,)X
+811 2190(the)N
+916(library)X
+1113(is)X
+1183(loaded)X
+1380(into)X
+1507(a)X
+1562(server)X
+1744(process)X
+1962(which)X
+2145(is)X
+2214(ac-)X
+811 2280(cessed)N
+993(via)X
+1087(a)X
+1131(socket)X
+1310(interface.)X
+3 f
+2563 2100(Figure)N
+2803(3:)X
+2914(Single)X
+3140(Process)X
+3403(Architecture.)X
+1 f
+3839(In)X
+3950(this)X
+2563 2190(con\256guration,)N
+2948(the)X
+3053(library)X
+3250(routines)X
+3483(are)X
+3587(loaded)X
+3784(as)X
+3864(part)X
+3990(of)X
+2563 2280(the)N
+2657(application)X
+2957(and)X
+3065(accessed)X
+3303(via)X
+3397(a)X
+3441(subroutine)X
+3727(interface.)X
+10 s
+10 f
+555 2403(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 f
+555 2679(modifying)N
+909(a)X
+966(piece)X
+1157(of)X
+1245(data)X
+1400(would)X
+1621(require)X
+1870(three)X
+2051(or)X
+2138(possibly)X
+2424(four)X
+2578(separate)X
+2862(communications:)X
+3433(one)X
+3569(to)X
+3651(lock)X
+3809(the)X
+3927(data,)X
+4101(one)X
+4237(to)X
+555 2769(obtain)N
+781(the)X
+905(data,)X
+1085(one)X
+1227(to)X
+1315(log)X
+1443(the)X
+1567(modi\256cation,)X
+2017(and)X
+2159(possibly)X
+2451(one)X
+2593(to)X
+2681(transmit)X
+2969(the)X
+3093(modi\256ed)X
+3403(data.)X
+3583(Figure)X
+3817(four)X
+3976(shows)X
+4201(the)X
+555 2859(relative)N
+826(performance)X
+1263(for)X
+1387(retrieving)X
+1728(a)X
+1793(single)X
+2013(record)X
+2248(using)X
+2450(the)X
+2577(record)X
+2812(level)X
+2997(call)X
+3142(versus)X
+3376(using)X
+3578(the)X
+3705(lower)X
+3917(level)X
+4102(buffer)X
+555 2949(management)N
+987(and)X
+1125(locking)X
+1387(calls.)X
+1616(The)X
+1763(2:1)X
+1887(ratio)X
+2056(observed)X
+2367(in)X
+2450(the)X
+2569(single)X
+2781(process)X
+3043(case)X
+3203(re\257ects)X
+3456(the)X
+3575(additional)X
+3916(overhead)X
+4232(of)X
+555 3039(parsing)N
+819(eight)X
+1006(commands)X
+1380(rather)X
+1595(than)X
+1760(one)X
+1903(while)X
+2108(the)X
+2233(3:1)X
+2362(ratio)X
+2536(observed)X
+2853(in)X
+2942(the)X
+3067(client/server)X
+3491(architecture)X
+3898(re\257ects)X
+4157(both)X
+555 3129(the)N
+679(parsing)X
+941(and)X
+1083(the)X
+1207(communication)X
+1731(overheard.)X
+2118(Although)X
+2445(there)X
+2631(may)X
+2794(be)X
+2895(applications)X
+3307(which)X
+3528(could)X
+3731(tolerate)X
+3997(such)X
+4169(per-)X
+555 3219(formance,)N
+904(it)X
+973(seems)X
+1194(far)X
+1309(more)X
+1499(feasible)X
+1774(to)X
+1861(support)X
+2126(a)X
+2187(higher)X
+2417(level)X
+2597(interface,)X
+2923(such)X
+3094(as)X
+3185(that)X
+3329(provided)X
+3638(by)X
+3742(a)X
+3802(query)X
+4009(language)X
+555 3309(\()N
+2 f
+582(e.g.)X
+1 f
+718(SQL)X
+889([SQL86]\).)X
+755 3432(Although)N
+1081(LIBTP)X
+1327(does)X
+1498(not)X
+1624(have)X
+1800(an)X
+1900(SQL)X
+2075(parser,)X
+2316(we)X
+2433(have)X
+2608(built)X
+2777(a)X
+2836(server)X
+3056(application)X
+3435(using)X
+3631(the)X
+3752(toolkit)X
+3983(command)X
+555 3522(language)N
+882(\(TCL\))X
+1124([OUST90].)X
+1544(The)X
+1706(server)X
+1940(supports)X
+2248(a)X
+2321(command)X
+2674(line)X
+2831(interface)X
+3150(similar)X
+3409(to)X
+3508(the)X
+3643(subroutine)X
+4017(interface)X
+555 3612(de\256ned)N
+811(in)X
+3 f
+893(db)X
+1 f
+981(\(3\).)X
+1135(Since)X
+1333(it)X
+1397(is)X
+1470(based)X
+1673(on)X
+1773(TCL,)X
+1964(it)X
+2028(provides)X
+2324(control)X
+2571(structures)X
+2903(as)X
+2990(well.)X
+3 f
+555 3798(4.)N
+655(Implementation)X
+1 f
+3 f
+555 3984(4.1.)N
+715(Locking)X
+1014(and)X
+1162(Deadlock)X
+1502(Detection)X
+1 f
+755 4107(LIBTP)N
+1007(uses)X
+1175(two-phase)X
+1535(locking)X
+1805(for)X
+1929(user)X
+2093(data.)X
+2297(Strictly)X
+2562(speaking,)X
+2897(the)X
+3024(two)X
+3173(phases)X
+3416(in)X
+3507(two-phase)X
+3866(locking)X
+4135(are)X
+4263(a)X
+3 f
+555 4197(grow)N
+1 f
+756(phase,)X
+986(during)X
+1221(which)X
+1443(locks)X
+1638(are)X
+1763(acquired,)X
+2086(and)X
+2228(a)X
+3 f
+2290(shrink)X
+1 f
+2537(phase,)X
+2766(during)X
+3001(which)X
+3223(locks)X
+3418(are)X
+3543(released.)X
+3873(No)X
+3997(lock)X
+4161(may)X
+555 4287(ever)N
+720(be)X
+822(acquired)X
+1124(during)X
+1358(the)X
+1481(shrink)X
+1706(phase.)X
+1954(The)X
+2104(grow)X
+2294(phase)X
+2502(lasts)X
+2669(until)X
+2840(the)X
+2963(\256rst)X
+3112(release,)X
+3381(which)X
+3602(marks)X
+3823(the)X
+3946(start)X
+4109(of)X
+4201(the)X
+555 4377(shrink)N
+780(phase.)X
+1028(In)X
+1120(practice,)X
+1420(the)X
+1543(grow)X
+1733(phase)X
+1941(lasts)X
+2108(for)X
+2227(the)X
+2350(duration)X
+2642(of)X
+2734(a)X
+2795(transaction)X
+3172(in)X
+3259(LIBTP)X
+3506(and)X
+3647(in)X
+3734(commercial)X
+4138(data-)X
+555 4467(base)N
+721(systems.)X
+1037(The)X
+1184(shrink)X
+1406(phase)X
+1611(takes)X
+1798(place)X
+1990(during)X
+2221(transaction)X
+2595(commit)X
+2861(or)X
+2950(abort.)X
+3177(This)X
+3341(means)X
+3568(that)X
+3710(locks)X
+3901(are)X
+4022(acquired)X
+555 4557(on)N
+655(demand)X
+929(during)X
+1158(the)X
+1276(lifetime)X
+1545(of)X
+1632(a)X
+1688(transaction,)X
+2080(and)X
+2216(held)X
+2374(until)X
+2540(commit)X
+2804(time,)X
+2986(at)X
+3064(which)X
+3280(point)X
+3464(all)X
+3564(locks)X
+3753(are)X
+3872(released.)X
+755 4680(If)N
+832(multiple)X
+1121(transactions)X
+1527(are)X
+1649(active)X
+1864(concurrently,)X
+2313(deadlocks)X
+2657(can)X
+2792(occur)X
+2994(and)X
+3133(must)X
+3311(be)X
+3410(detected)X
+3701(and)X
+3840(resolved.)X
+4174(The)X
+555 4770(lock)N
+715(table)X
+893(can)X
+1027(be)X
+1125(thought)X
+1391(of)X
+1480(as)X
+1569(a)X
+1627(representation)X
+2104(of)X
+2193(a)X
+2251(directed)X
+2532(graph.)X
+2777(The)X
+2924(nodes)X
+3133(in)X
+3216(the)X
+3335(graph)X
+3539(are)X
+3659(transactions.)X
+4103(Edges)X
+555 4860(represent)N
+878(the)X
+3 f
+1004(waits-for)X
+1 f
+1340(relation)X
+1613(between)X
+1909(transactions;)X
+2342(if)X
+2419(transaction)X
+2 f
+2799(A)X
+1 f
+2876(is)X
+2957(waiting)X
+3225(for)X
+3347(a)X
+3411(lock)X
+3577(held)X
+3743(by)X
+3851(transaction)X
+2 f
+4230(B)X
+1 f
+4279(,)X
+555 4950(then)N
+716(a)X
+775(directed)X
+1057(edge)X
+1232(exists)X
+1437(from)X
+2 f
+1616(A)X
+1 f
+1687(to)X
+2 f
+1771(B)X
+1 f
+1842(in)X
+1926(the)X
+2046(graph.)X
+2291(A)X
+2371(deadlock)X
+2683(exists)X
+2887(if)X
+2958(a)X
+3016(cycle)X
+3208(appears)X
+3476(in)X
+3560(the)X
+3680(graph.)X
+3925(By)X
+4040(conven-)X
+555 5040(tion,)N
+719(no)X
+819(transaction)X
+1191(ever)X
+1350(waits)X
+1539(for)X
+1653(a)X
+1709(lock)X
+1867(it)X
+1931(already)X
+2188(holds,)X
+2401(so)X
+2492(re\257exive)X
+2793(edges)X
+2996(are)X
+3115(impossible.)X
+755 5163(A)N
+836(distinguished)X
+1285(process)X
+1549(monitors)X
+1856(the)X
+1977(lock)X
+2138(table,)X
+2337(searching)X
+2668(for)X
+2785(cycles.)X
+3048(The)X
+3195(frequency)X
+3539(with)X
+3703(which)X
+3921(this)X
+4058(process)X
+555 5253(runs)N
+716(is)X
+792(user-settable;)X
+1243(for)X
+1360(the)X
+1481(multi-user)X
+1833(tests)X
+1998(discussed)X
+2328(in)X
+2413(section)X
+2663(5.1.2,)X
+2866(it)X
+2933(has)X
+3063(been)X
+3238(set)X
+3350(to)X
+3435(wake)X
+3628(up)X
+3731(every)X
+3932(second,)X
+4197(but)X
+555 5343(more)N
+742(sophisticated)X
+1182(schedules)X
+1516(are)X
+1636(certainly)X
+1938(possible.)X
+2261(When)X
+2474(a)X
+2531(cycle)X
+2722(is)X
+2796(detected,)X
+3105(one)X
+3242(of)X
+3330(the)X
+3449(transactions)X
+3853(in)X
+3936(the)X
+4055(cycle)X
+4246(is)X
+555 5433(nominated)N
+917(and)X
+1057(aborted.)X
+1362(When)X
+1578(the)X
+1700(transaction)X
+2076(aborts,)X
+2315(it)X
+2382(rolls)X
+2547(back)X
+2722(its)X
+2820(changes)X
+3102(and)X
+3241(releases)X
+3519(its)X
+3617(locks,)X
+3829(thereby)X
+4093(break-)X
+555 5523(ing)N
+677(the)X
+795(cycle)X
+985(in)X
+1067(the)X
+1185(graph.)X
+
+8 p
+%%Page: 8 8
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+4 Ds
+1 Dt
+1866 865 MXY
+1338 0 Dl
+1866 1031 MXY
+1338 0 Dl
+1866 1199 MXY
+1338 0 Dl
+1866 1366 MXY
+1338 0 Dl
+1866 1533 MXY
+1338 0 Dl
+1866 1701 MXY
+1338 0 Dl
+-1 Ds
+5 Dt
+1866 1868 MXY
+1338 0 Dl
+1 Dt
+1 Di
+2981 MX
+ 2981 1868 lineto
+ 2981 1575 lineto
+ 3092 1575 lineto
+ 3092 1868 lineto
+ 2981 1868 lineto
+closepath 21 2981 1575 3092 1868 Dp
+2646 MX
+ 2646 1868 lineto
+ 2646 949 lineto
+ 2758 949 lineto
+ 2758 1868 lineto
+ 2646 1868 lineto
+closepath 14 2646 949 2758 1868 Dp
+2312 MX
+ 2312 1868 lineto
+ 2312 1701 lineto
+ 2423 1701 lineto
+ 2423 1868 lineto
+ 2312 1868 lineto
+closepath 3 2312 1701 2423 1868 Dp
+1977 MX
+ 1977 1868 lineto
+ 1977 1512 lineto
+ 2089 1512 lineto
+ 2089 1868 lineto
+ 1977 1868 lineto
+closepath 19 1977 1512 2089 1868 Dp
+3 f
+2640 2047(Client/Server)N
+1957(Single)X
+2185(Process)X
+7 s
+2957 1957(record)N
+2570(component)X
+2289(record)X
+1890(components)X
+1733 1724(.1)N
+1733 1556(.2)N
+1733 1389(.3)N
+1733 1222(.4)N
+1733 1055(.5)N
+1733 889(.6)N
+1590 726(Elapsed)N
+1794(Time)X
+1613 782(\(in)N
+1693(seconds\))X
+3 Dt
+-1 Ds
+8 s
+555 2255(Figure)N
+756(4:)X
+829(Comparison)X
+1187(of)X
+1260(High)X
+1416(and)X
+1540(Low)X
+1681(Level)X
+1850(Interfaces.)X
+1 f
+2174(Elapsed)X
+2395(time)X
+2528(in)X
+2597(seconds)X
+2818(to)X
+2887(perform)X
+3111(a)X
+3158(single)X
+3330(record)X
+3511(retrieval)X
+3742(from)X
+3885(a)X
+3932(command)X
+4203(line)X
+555 2345(\(rather)N
+751(than)X
+888(a)X
+943(procedural)X
+1241(interface\))X
+1510(is)X
+1579(shown)X
+1772(on)X
+1862(the)X
+1966(y)X
+2024(axis.)X
+2185(The)X
+2310(``component'')X
+2704(numbers)X
+2950(re\257ect)X
+3135(the)X
+3239(timings)X
+3458(when)X
+3622(the)X
+3726(record)X
+3914(is)X
+3983(retrieved)X
+4235(by)X
+555 2435(separate)N
+785(calls)X
+924(to)X
+996(the)X
+1096(lock)X
+1228(manager)X
+1469(and)X
+1583(buffer)X
+1760(manager)X
+2001(while)X
+2165(the)X
+2264(``record'')X
+2531(timings)X
+2745(were)X
+2889(obtained)X
+3130(by)X
+3215(using)X
+3375(a)X
+3424(single)X
+3598(call)X
+3711(to)X
+3782(the)X
+3881(record)X
+4064(manager.)X
+555 2525(The)N
+674(2:1)X
+776(ratio)X
+913(observed)X
+1163(for)X
+1257(the)X
+1355(single)X
+1528(process)X
+1739(case)X
+1868(is)X
+1930(a)X
+1977(re\257ection)X
+2237(of)X
+2309(the)X
+2406(parsing)X
+2613(overhead)X
+2865(for)X
+2958(executing)X
+3225(eight)X
+3372(separate)X
+3599(commands)X
+3895(rather)X
+4062(than)X
+4191(one.)X
+555 2615(The)N
+673(additional)X
+948(factor)X
+1115(of)X
+1187(one)X
+1298(re\257ected)X
+1536(in)X
+1605(the)X
+1702(3:1)X
+1803(ratio)X
+1939(for)X
+2031(the)X
+2127(client/server)X
+2460(architecture)X
+2794(is)X
+2855(due)X
+2965(to)X
+3033(the)X
+3129(communication)X
+3545(overhead.)X
+3828(The)X
+3945(true)X
+4062(ratios)X
+4222(are)X
+555 2705(actually)N
+775(worse)X
+945(since)X
+1094(the)X
+1190(component)X
+1492(timings)X
+1703(do)X
+1785(not)X
+1884(re\257ect)X
+2060(the)X
+2155(search)X
+2334(times)X
+2490(within)X
+2671(each)X
+2804(page)X
+2941(or)X
+3011(the)X
+3106(time)X
+3237(required)X
+3466(to)X
+3533(transmit)X
+3760(the)X
+3855(page)X
+3992(between)X
+4221(the)X
+555 2795(two)N
+667(processes.)X
+10 s
+10 f
+555 2885(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+3 f
+555 3161(4.2.)N
+715(Group)X
+961(Commit)X
+1 f
+755 3284(Since)N
+959(the)X
+1083(log)X
+1211(must)X
+1392(be)X
+1494(\257ushed)X
+1751(to)X
+1839(disk)X
+1997(at)X
+2080(commit)X
+2349(time,)X
+2536(disk)X
+2694(bandwidth)X
+3057(fundamentally)X
+3545(limits)X
+3751(the)X
+3874(rate)X
+4020(at)X
+4103(which)X
+555 3374(transactions)N
+959(complete.)X
+1314(Since)X
+1513(most)X
+1688(transactions)X
+2091(write)X
+2276(only)X
+2438(a)X
+2494(few)X
+2635(small)X
+2828(records)X
+3085(to)X
+3167(the)X
+3285(log,)X
+3427(the)X
+3545(last)X
+3676(page)X
+3848(of)X
+3935(the)X
+4053(log)X
+4175(will)X
+555 3464(be)N
+658(\257ushed)X
+916(once)X
+1095(by)X
+1202(every)X
+1408(transaction)X
+1787(which)X
+2010(writes)X
+2233(to)X
+2322(it.)X
+2433(In)X
+2527(the)X
+2652(naive)X
+2853(implementation,)X
+3402(these)X
+3593(\257ushes)X
+3841(would)X
+4067(happen)X
+555 3554(serially.)N
+755 3677(LIBTP)N
+1008(uses)X
+3 f
+1177(group)X
+1412(commit)X
+1 f
+1702([DEWI84])X
+2077(in)X
+2170(order)X
+2371(to)X
+2464(amortize)X
+2775(the)X
+2903(cost)X
+3062(of)X
+3159(one)X
+3305(synchronous)X
+3740(disk)X
+3903(write)X
+4098(across)X
+555 3767(multiple)N
+851(transactions.)X
+1304(Group)X
+1539(commit)X
+1812(provides)X
+2117(a)X
+2182(way)X
+2345(for)X
+2468(a)X
+2533(group)X
+2749(of)X
+2845(transactions)X
+3257(to)X
+3348(commit)X
+3621(simultaneously.)X
+4174(The)X
+555 3857(\256rst)N
+709(several)X
+967(transactions)X
+1380(to)X
+1472(commit)X
+1745(write)X
+1939(their)X
+2115(changes)X
+2403(to)X
+2494(the)X
+2621(in-memory)X
+3006(log)X
+3137(page,)X
+3338(then)X
+3505(sleep)X
+3699(on)X
+3808(a)X
+3873(distinguished)X
+555 3947(semaphore.)N
+966(Later,)X
+1179(a)X
+1238(committing)X
+1629(transaction)X
+2004(\257ushes)X
+2249(the)X
+2370(page)X
+2545(to)X
+2630(disk,)X
+2805(and)X
+2943(wakes)X
+3166(up)X
+3268(all)X
+3370(its)X
+3467(sleeping)X
+3756(peers.)X
+3988(The)X
+4135(point)X
+555 4037(at)N
+635(which)X
+853(changes)X
+1134(are)X
+1255(actually)X
+1531(written)X
+1780(is)X
+1855(determined)X
+2238(by)X
+2340(three)X
+2523(thresholds.)X
+2914(The)X
+3061(\256rst)X
+3207(is)X
+3281(the)X
+2 f
+3400(group)X
+3612(threshold)X
+1 f
+3935(and)X
+4072(de\256nes)X
+555 4127(the)N
+674(minimum)X
+1005(number)X
+1271(of)X
+1359(transactions)X
+1763(which)X
+1979(must)X
+2154(be)X
+2250(active)X
+2462(in)X
+2544(the)X
+2662(system)X
+2904(before)X
+3130(transactions)X
+3533(are)X
+3652(forced)X
+3878(to)X
+3960(participate)X
+555 4217(in)N
+646(a)X
+711(group)X
+927(commit.)X
+1240(The)X
+1394(second)X
+1646(is)X
+1728(the)X
+2 f
+1855(wait)X
+2021(threshold)X
+1 f
+2352(which)X
+2577(is)X
+2658(expressed)X
+3003(as)X
+3098(the)X
+3224(percentage)X
+3601(of)X
+3696(active)X
+3916(transactions)X
+555 4307(waiting)N
+826(to)X
+919(be)X
+1026(committed.)X
+1439(The)X
+1595(last)X
+1737(is)X
+1821(the)X
+2 f
+1950(logdelay)X
+2257(threshold)X
+1 f
+2590(which)X
+2816(indicates)X
+3131(how)X
+3299(much)X
+3507(un\257ushed)X
+3848(log)X
+3980(should)X
+4223(be)X
+555 4397(allowed)N
+829(to)X
+911(accumulate)X
+1297(before)X
+1523(a)X
+1579(waiting)X
+1839(transaction's)X
+2289(commit)X
+2553(record)X
+2779(is)X
+2852(\257ushed.)X
+755 4520(Group)N
+981(commit)X
+1246(can)X
+1379(substantially)X
+1803(improve)X
+2090(performance)X
+2517(for)X
+2631(high-concurrency)X
+3218(environments.)X
+3714(If)X
+3788(only)X
+3950(a)X
+4006(few)X
+4147(tran-)X
+555 4610(sactions)N
+836(are)X
+957(running,)X
+1248(it)X
+1314(is)X
+1389(unlikely)X
+1673(to)X
+1757(improve)X
+2046(things)X
+2263(at)X
+2343(all.)X
+2485(The)X
+2632(crossover)X
+2962(point)X
+3148(is)X
+3223(the)X
+3343(point)X
+3529(at)X
+3609(which)X
+3827(the)X
+3947(transaction)X
+555 4700(commit)N
+823(rate)X
+968(is)X
+1045(limited)X
+1295(by)X
+1399(the)X
+1521(bandwidth)X
+1883(of)X
+1974(the)X
+2096(device)X
+2330(on)X
+2434(which)X
+2654(the)X
+2776(log)X
+2902(resides.)X
+3189(If)X
+3267(processes)X
+3599(are)X
+3722(trying)X
+3937(to)X
+4023(\257ush)X
+4201(the)X
+555 4790(log)N
+677(faster)X
+876(than)X
+1034(the)X
+1152(log)X
+1274(disk)X
+1427(can)X
+1559(accept)X
+1785(data,)X
+1959(then)X
+2117(group)X
+2324(commit)X
+2588(will)X
+2732(increase)X
+3016(the)X
+3134(commit)X
+3398(rate.)X
+3 f
+555 4976(4.3.)N
+715(Kernel)X
+971(Intervention)X
+1418(for)X
+1541(Synchronization)X
+1 f
+755 5099(Since)N
+954(LIBTP)X
+1197(uses)X
+1356(data)X
+1511(in)X
+1594(shared)X
+1825(memory)X
+2113(\()X
+2 f
+2140(e.g.)X
+1 f
+2277(the)X
+2395(lock)X
+2553(table)X
+2729(and)X
+2865(buffer)X
+3082(pool\))X
+3271(it)X
+3335(must)X
+3510(be)X
+3606(possible)X
+3888(for)X
+4002(a)X
+4058(process)X
+555 5189(to)N
+640(acquire)X
+900(exclusive)X
+1226(access)X
+1454(to)X
+1538(shared)X
+1770(data)X
+1926(in)X
+2010(order)X
+2202(to)X
+2286(prevent)X
+2549(corruption.)X
+2945(In)X
+3034(addition,)X
+3338(the)X
+3458(process)X
+3721(manager)X
+4020(must)X
+4197(put)X
+555 5279(processes)N
+886(to)X
+971(sleep)X
+1159(when)X
+1356(the)X
+1477(lock)X
+1638(or)X
+1728(buffer)X
+1948(they)X
+2109(request)X
+2364(is)X
+2440(in)X
+2525(use)X
+2655(by)X
+2758(some)X
+2950(other)X
+3138(process.)X
+3441(In)X
+3530(the)X
+3650(LIBTP)X
+3894(implementa-)X
+555 5385(tion)N
+705(under)X
+914(Ultrix)X
+1131(4.0)X
+7 s
+5353(2)Y
+10 s
+5385(,)Y
+1305(we)X
+1424(use)X
+1556(System)X
+1816(V)X
+1899(semaphores)X
+2303(to)X
+2390(provide)X
+2660(this)X
+2800(synchronization.)X
+3377(Semaphores)X
+3794(implemented)X
+4237(in)X
+555 5475(this)N
+701(fashion)X
+968(turn)X
+1128(out)X
+1261(to)X
+1354(be)X
+1461(an)X
+1568(expensive)X
+1920(choice)X
+2161(for)X
+2285(synchronization,)X
+2847(because)X
+3132(each)X
+3310(access)X
+3546(traps)X
+3732(to)X
+3824(the)X
+3952(kernel)X
+4183(and)X
+8 s
+10 f
+555 5547(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5625(2)N
+8 s
+763 5650(Ultrix)N
+932(and)X
+1040(DEC)X
+1184(are)X
+1277(trademarks)X
+1576(of)X
+1645(Digital)X
+1839(Equipment)X
+2136(Corporation.)X
+
+9 p
+%%Page: 9 9
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(executes)N
+852(atomically)X
+1210(there.)X
+755 753(On)N
+878(architectures)X
+1314(that)X
+1459(support)X
+1724(atomic)X
+1967(test-and-set,)X
+2382(a)X
+2443(much)X
+2646(better)X
+2854(choice)X
+3089(would)X
+3314(be)X
+3415(to)X
+3502(attempt)X
+3767(to)X
+3854(obtain)X
+4079(a)X
+4139(spin-)X
+555 843(lock)N
+714(with)X
+877(a)X
+934(test-and-set,)X
+1345(and)X
+1482(issue)X
+1663(a)X
+1720(system)X
+1963(call)X
+2100(only)X
+2263(if)X
+2333(the)X
+2452(spinlock)X
+2744(is)X
+2818(unavailable.)X
+3249(Since)X
+3447(virtually)X
+3738(all)X
+3838(semaphores)X
+4237(in)X
+555 933(LIBTP)N
+801(are)X
+924(uncontested)X
+1330(and)X
+1469(are)X
+1591(held)X
+1752(for)X
+1869(very)X
+2035(short)X
+2218(periods)X
+2477(of)X
+2567(time,)X
+2752(this)X
+2890(would)X
+3113(improve)X
+3403(performance.)X
+3873(For)X
+4007(example,)X
+555 1023(processes)N
+885(must)X
+1062(acquire)X
+1321(exclusive)X
+1646(access)X
+1874(to)X
+1958(buffer)X
+2177(pool)X
+2341(metadata)X
+2653(in)X
+2737(order)X
+2929(to)X
+3013(\256nd)X
+3159(and)X
+3297(pin)X
+3421(a)X
+3479(buffer)X
+3698(in)X
+3781(shared)X
+4012(memory.)X
+555 1113(This)N
+721(semaphore)X
+1093(is)X
+1170(requested)X
+1502(most)X
+1681(frequently)X
+2034(in)X
+2119(LIBTP.)X
+2404(However,)X
+2742(once)X
+2917(it)X
+2984(is)X
+3060(acquired,)X
+3380(only)X
+3545(a)X
+3604(few)X
+3748(instructions)X
+4144(must)X
+555 1203(be)N
+656(executed)X
+966(before)X
+1196(it)X
+1264(is)X
+1341(released.)X
+1669(On)X
+1791(one)X
+1931(architecture)X
+2335(for)X
+2453(which)X
+2673(we)X
+2791(were)X
+2972(able)X
+3130(to)X
+3216(gather)X
+3441(detailed)X
+3719(pro\256ling)X
+4018(informa-)X
+555 1293(tion,)N
+729(the)X
+857(cost)X
+1015(of)X
+1111(the)X
+1238(semaphore)X
+1615(calls)X
+1791(accounted)X
+2146(for)X
+2269(25%)X
+2445(of)X
+2541(the)X
+2668(total)X
+2839(time)X
+3010(spent)X
+3208(updating)X
+3517(the)X
+3644(metadata.)X
+4003(This)X
+4174(was)X
+555 1383(fairly)N
+749(consistent)X
+1089(across)X
+1310(most)X
+1485(of)X
+1572(the)X
+1690(critical)X
+1933(sections.)X
+755 1506(In)N
+848(an)X
+950(attempt)X
+1216(to)X
+1304(quantify)X
+1597(the)X
+1720(overhead)X
+2040(of)X
+2132(kernel)X
+2358(synchronization,)X
+2915(we)X
+3034(ran)X
+3162(tests)X
+3329(on)X
+3434(a)X
+3495(version)X
+3756(of)X
+3848(4.3BSD-Reno)X
+555 1596(which)N
+786(had)X
+937(been)X
+1123(modi\256ed)X
+1441(to)X
+1537(support)X
+1811(binary)X
+2050(semaphore)X
+2432(facilities)X
+2742(similar)X
+2998(to)X
+3094(those)X
+3297(described)X
+3639(in)X
+3735([POSIX91].)X
+4174(The)X
+555 1686(hardware)N
+880(platform)X
+1181(consisted)X
+1504(of)X
+1595(an)X
+1695(HP300)X
+1941(\(33MHz)X
+2237(MC68030\))X
+2612(workstation)X
+3014(with)X
+3180(16MBytes)X
+3537(of)X
+3628(main)X
+3812(memory,)X
+4123(and)X
+4263(a)X
+555 1776(600MByte)N
+920(HP7959)X
+1205(SCSI)X
+1396(disk)X
+1552(\(17)X
+1682(ms)X
+1798(average)X
+2072(seek)X
+2237(time\).)X
+2468(We)X
+2602(ran)X
+2727(three)X
+2910(sets)X
+3052(of)X
+3141(comparisons)X
+3568(which)X
+3786(are)X
+3907(summarized)X
+555 1866(in)N
+645(\256gure)X
+860(\256ve.)X
+1028(In)X
+1123(each)X
+1299(comparison)X
+1701(we)X
+1823(ran)X
+1954(two)X
+2102(tests,)X
+2292(one)X
+2436(using)X
+2637(hardware)X
+2965(spinlocks)X
+3295(and)X
+3438(the)X
+3563(other)X
+3755(using)X
+3955(kernel)X
+4183(call)X
+555 1956(synchronization.)N
+1135(Since)X
+1341(the)X
+1467(test)X
+1606(was)X
+1758(run)X
+1892(single-user,)X
+2291(none)X
+2474(of)X
+2568(the)X
+2693(the)X
+2818(locks)X
+3014(were)X
+3198(contested.)X
+3568(In)X
+3662(the)X
+3787(\256rst)X
+3938(two)X
+4085(sets)X
+4232(of)X
+555 2046(tests,)N
+743(we)X
+863(ran)X
+992(the)X
+1116(full)X
+1253(transaction)X
+1631(processing)X
+2000(benchmark)X
+2383(described)X
+2717(in)X
+2805(section)X
+3058(5.1.)X
+3223(In)X
+3315(one)X
+3456(case)X
+3620(we)X
+3739(ran)X
+3867(with)X
+4034(both)X
+4201(the)X
+555 2136(database)N
+854(and)X
+992(log)X
+1116(on)X
+1218(the)X
+1338(same)X
+1525(disk)X
+1680(\(1)X
+1769(Disk\))X
+1969(and)X
+2107(in)X
+2191(the)X
+2311(second,)X
+2576(we)X
+2692(ran)X
+2817(with)X
+2981(the)X
+3101(database)X
+3400(and)X
+3538(log)X
+3661(on)X
+3762(separate)X
+4047(disks)X
+4232(\(2)X
+555 2226(Disk\).)N
+800(In)X
+894(the)X
+1019(last)X
+1157(test,)X
+1315(we)X
+1436(wanted)X
+1695(to)X
+1784(create)X
+2004(a)X
+2067(CPU)X
+2249(bound)X
+2476(environment,)X
+2928(so)X
+3026(we)X
+3146(used)X
+3319(a)X
+3381(database)X
+3684(small)X
+3883(enough)X
+4145(to)X
+4233(\256t)X
+555 2316(completely)N
+941(in)X
+1033(the)X
+1161(cache)X
+1375(and)X
+1521(issued)X
+1751(read-only)X
+2089(transactions.)X
+2541(The)X
+2695(results)X
+2933(in)X
+3024(\256gure)X
+3240(\256ve)X
+3389(express)X
+3659(the)X
+3786(kernel)X
+4016(call)X
+4161(syn-)X
+555 2406(chronization)N
+980(performance)X
+1411(as)X
+1502(a)X
+1562(percentage)X
+1935(of)X
+2026(the)X
+2148(spinlock)X
+2443(performance.)X
+2914(For)X
+3049(example,)X
+3365(in)X
+3451(the)X
+3573(1)X
+3637(disk)X
+3794(case,)X
+3977(the)X
+4098(kernel)X
+555 2496(call)N
+697(implementation)X
+1225(achieved)X
+1537(4.4)X
+1662(TPS)X
+1824(\(transactions)X
+2259(per)X
+2387(second\))X
+2662(while)X
+2865(the)X
+2988(semaphore)X
+3361(implementation)X
+3888(achieved)X
+4199(4.6)X
+555 2586(TPS,)N
+735(and)X
+874(the)X
+995(relative)X
+1259(performance)X
+1689(of)X
+1779(the)X
+1900(kernel)X
+2123(synchronization)X
+2657(is)X
+2732(96%)X
+2901(that)X
+3043(of)X
+3132(the)X
+3252(spinlock)X
+3545(\(100)X
+3714(*)X
+3776(4.4)X
+3898(/)X
+3942(4.6\).)X
+4111(There)X
+555 2676(are)N
+674(two)X
+814(striking)X
+1078(observations)X
+1503(from)X
+1679(these)X
+1864(results:)X
+10 f
+635 2799(g)N
+1 f
+755(even)X
+927(when)X
+1121(the)X
+1239(system)X
+1481(is)X
+1554(disk)X
+1707(bound,)X
+1947(the)X
+2065(CPU)X
+2240(cost)X
+2389(of)X
+2476(synchronization)X
+3008(is)X
+3081(noticeable,)X
+3451(and)X
+10 f
+635 2922(g)N
+1 f
+755(when)X
+949(we)X
+1063(are)X
+1182(CPU)X
+1357(bound,)X
+1597(the)X
+1715(difference)X
+2062(is)X
+2135(dramatic)X
+2436(\(67%\).)X
+3 f
+555 3108(4.4.)N
+715(Transaction)X
+1148(Protected)X
+1499(Access)X
+1747(Methods)X
+1 f
+755 3231(The)N
+903(B-tree)X
+1127(and)X
+1266(\256xed)X
+1449(length)X
+1671(recno)X
+1872(\(record)X
+2127(number\))X
+2421(access)X
+2649(methods)X
+2942(have)X
+3116(been)X
+3290(modi\256ed)X
+3596(to)X
+3680(provide)X
+3947(transaction)X
+555 3321(protection.)N
+941(Whereas)X
+1244(the)X
+1363(previously)X
+1722(published)X
+2054(interface)X
+2357(to)X
+2440(the)X
+2559(access)X
+2786(routines)X
+3065(had)X
+3202(separate)X
+3487(open)X
+3664(calls)X
+3832(for)X
+3946(each)X
+4114(of)X
+4201(the)X
+10 f
+555 3507(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 Dt
+2978 5036 MXY
+ 2978 5036 lineto
+ 2978 4662 lineto
+ 3093 4662 lineto
+ 3093 5036 lineto
+ 2978 5036 lineto
+closepath 21 2978 4662 3093 5036 Dp
+2518 MX
+ 2518 5036 lineto
+ 2518 3960 lineto
+ 2633 3960 lineto
+ 2633 5036 lineto
+ 2518 5036 lineto
+closepath 3 2518 3960 2633 5036 Dp
+2059 MX
+ 2059 5036 lineto
+ 2059 3946 lineto
+ 2174 3946 lineto
+ 2174 5036 lineto
+ 2059 5036 lineto
+closepath 1 2059 3946 2174 5036 Dp
+3 f
+7 s
+2912 5141(Read-only)N
+1426 3767(of)N
+1487(Spinlock)X
+1710(Throughput)X
+1480 3710(Throughput)N
+1786(as)X
+1850(a)X
+1892(%)X
+11 s
+1670 4843(20)N
+1670 4614(40)N
+1670 4384(60)N
+1670 4155(80)N
+1648 3925(100)N
+7 s
+2041 5141(1)N
+2083(Disk)X
+2490(2)X
+2532(Disks)X
+5 Dt
+1829 5036 MXY
+1494 0 Dl
+4 Ds
+1 Dt
+1829 4806 MXY
+1494 0 Dl
+1829 4577 MXY
+1494 0 Dl
+1829 4347 MXY
+1494 0 Dl
+1829 4118 MXY
+1494 0 Dl
+1829 3888 MXY
+1494 0 Dl
+3 Dt
+-1 Ds
+8 s
+555 5360(Figure)N
+753(5:)X
+823(Kernel)X
+1028(Overhead)X
+1315(for)X
+1413(System)X
+1625(Call)X
+1756(Synchronization.)X
+1 f
+2254(The)X
+2370(performance)X
+2708(of)X
+2778(the)X
+2873(kernel)X
+3049(call)X
+3158(synchronization)X
+3583(is)X
+3643(expressed)X
+3911(as)X
+3980(a)X
+4024(percentage)X
+555 5450(of)N
+625(the)X
+720(spinlock)X
+954(synchronization)X
+1379(performance.)X
+1749(In)X
+1819(disk)X
+1943(bound)X
+2120(cases)X
+2271(\(1)X
+2341(Disk)X
+2479(and)X
+2588(2)X
+2637(Disks\),)X
+2837(we)X
+2928(see)X
+3026(that)X
+3139(4-6%)X
+3294(of)X
+3364(the)X
+3459(performance)X
+3797(is)X
+3857(lost)X
+3966(due)X
+4074(to)X
+4140(kernel)X
+555 5540(calls)N
+688(while)X
+846(in)X
+912(the)X
+1006(CPU)X
+1147(bound)X
+1323(case,)X
+1464(we)X
+1554(have)X
+1690(lost)X
+1799(67%)X
+1932(of)X
+2001(the)X
+2095(performance)X
+2432(due)X
+2540(to)X
+2606(kernel)X
+2781(calls.)X
+
+10 p
+%%Page: 10 10
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(access)N
+781(methods,)X
+1092(we)X
+1206(now)X
+1364(have)X
+1536(an)X
+1632(integrated)X
+1973(open)X
+2149(call)X
+2285(with)X
+2447(the)X
+2565(following)X
+2896(calling)X
+3134(conventions:)X
+7 f
+715 753(DB)N
+859(*dbopen)X
+1243(\(const)X
+1579(char)X
+1819(*file,)X
+2155(int)X
+2347(flags,)X
+2683(int)X
+2875(mode,)X
+3163(DBTYPE)X
+3499(type,)X
+1291 843(int)N
+1483(dbflags,)X
+1915(const)X
+2203(void)X
+2443(*openinfo\))X
+1 f
+555 966(where)N
+2 f
+774(\256le)X
+1 f
+894(is)X
+969(the)X
+1089(name)X
+1285(of)X
+1374(the)X
+1494(\256le)X
+1618(being)X
+1818(opened,)X
+2 f
+2092(\257ags)X
+1 f
+2265(and)X
+2 f
+2402(mode)X
+1 f
+2597(are)X
+2717(the)X
+2836(standard)X
+3129(arguments)X
+3484(to)X
+3 f
+3567(open)X
+1 f
+3731(\(2\),)X
+2 f
+3866(type)X
+1 f
+4021(is)X
+4095(one)X
+4232(of)X
+555 1056(the)N
+680(access)X
+913(method)X
+1180(types,)X
+2 f
+1396(db\257ags)X
+1 f
+1654(indicates)X
+1966(the)X
+2091(mode)X
+2296(of)X
+2390(the)X
+2515(buffer)X
+2739(pool)X
+2907(and)X
+3049(transaction)X
+3427(protection,)X
+3798(and)X
+2 f
+3940(openinfo)X
+1 f
+4246(is)X
+555 1146(the)N
+681(access)X
+915(method)X
+1183(speci\256c)X
+1456(information.)X
+1902(Currently,)X
+2257(the)X
+2383(possible)X
+2673(values)X
+2906(for)X
+2 f
+3028(db\257ags)X
+1 f
+3287(are)X
+3414(DB_SHARED)X
+3912(and)X
+4055(DB_TP)X
+555 1236(indicating)N
+895(that)X
+1035(buffers)X
+1283(should)X
+1516(be)X
+1612(kept)X
+1770(in)X
+1852(a)X
+1908(shared)X
+2138(buffer)X
+2355(pool)X
+2517(and)X
+2653(that)X
+2793(the)X
+2911(\256le)X
+3033(should)X
+3266(be)X
+3362(transaction)X
+3734(protected.)X
+755 1359(The)N
+900(modi\256cations)X
+1355(required)X
+1643(to)X
+1725(add)X
+1861(transaction)X
+2233(protection)X
+2578(to)X
+2660(an)X
+2756(access)X
+2982(method)X
+3242(are)X
+3361(quite)X
+3541(simple)X
+3774(and)X
+3910(localized.)X
+715 1482(1.)N
+795(Replace)X
+1074(\256le)X
+2 f
+1196(open)X
+1 f
+1372(with)X
+2 f
+1534(buf_open)X
+1 f
+1832(.)X
+715 1572(2.)N
+795(Replace)X
+1074(\256le)X
+2 f
+1196(read)X
+1 f
+1363(and)X
+2 f
+1499(write)X
+1 f
+1683(calls)X
+1850(with)X
+2012(buffer)X
+2229(manager)X
+2526(calls)X
+2693(\()X
+2 f
+2720(buf_get)X
+1 f
+(,)S
+2 f
+3000(buf_unpin)X
+1 f
+3324(\).)X
+715 1662(3.)N
+795(Precede)X
+1070(buffer)X
+1287(manager)X
+1584(calls)X
+1751(with)X
+1913(an)X
+2009(appropriate)X
+2395(\(read)X
+2581(or)X
+2668(write\))X
+2880(lock)X
+3038(call.)X
+715 1752(4.)N
+795(Before)X
+1034(updates,)X
+1319(issue)X
+1499(a)X
+1555(logging)X
+1819(operation.)X
+715 1842(5.)N
+795(After)X
+985(data)X
+1139(have)X
+1311(been)X
+1483(accessed,)X
+1805(release)X
+2049(the)X
+2167(buffer)X
+2384(manager)X
+2681(pin.)X
+715 1932(6.)N
+795(Provide)X
+1064(undo/redo)X
+1409(code)X
+1581(for)X
+1695(each)X
+1863(type)X
+2021(of)X
+2108(log)X
+2230(record)X
+2456(de\256ned.)X
+555 2071(The)N
+702(following)X
+1035(code)X
+1209(fragments)X
+1552(show)X
+1743(how)X
+1903(to)X
+1987(transaction)X
+2361(protect)X
+2606(several)X
+2856(updates)X
+3123(to)X
+3206(a)X
+3263(B-tree.)X
+7 s
+3484 2039(3)N
+10 s
+3533 2071(In)N
+3621(the)X
+3740(unprotected)X
+4140(case,)X
+555 2161(an)N
+652(open)X
+829(call)X
+966(is)X
+1040(followed)X
+1346(by)X
+1447(a)X
+1504(read)X
+1664(call)X
+1801(to)X
+1884(obtain)X
+2105(the)X
+2224(meta-data)X
+2562(for)X
+2677(the)X
+2796(B-tree.)X
+3058(Instead,)X
+3331(we)X
+3446(issue)X
+3627(an)X
+3724(open)X
+3901(to)X
+3984(the)X
+4102(buffer)X
+555 2251(manager)N
+852(to)X
+934(obtain)X
+1154(a)X
+1210(\256le)X
+1332(id)X
+1414(and)X
+1550(a)X
+1606(buffer)X
+1823(request)X
+2075(to)X
+2157(obtain)X
+2377(the)X
+2495(meta-data)X
+2832(as)X
+2919(shown)X
+3148(below.)X
+7 f
+715 2374(char)N
+955(*path;)X
+715 2464(int)N
+907(fid,)X
+1147(flags,)X
+1483(len,)X
+1723(mode;)X
+715 2644(/*)N
+859(Obtain)X
+1195(a)X
+1291(file)X
+1531(id)X
+1675(with)X
+1915(which)X
+2203(to)X
+2347(access)X
+2683(the)X
+2875(buffer)X
+3211(pool)X
+3451(*/)X
+715 2734(fid)N
+907(=)X
+1003(buf_open\(path,)X
+1723(flags,)X
+2059(mode\);)X
+715 2914(/*)N
+859(Read)X
+1099(the)X
+1291(meta)X
+1531(data)X
+1771(\(page)X
+2059(0\))X
+2203(for)X
+2395(the)X
+2587(B-tree)X
+2923(*/)X
+715 3004(if)N
+859(\(tp_lock\(fid,)X
+1531(0,)X
+1675(READ_LOCK\)\))X
+1003 3094(return)N
+1339(error;)X
+715 3184(meta_data_ptr)N
+1387(=)X
+1483(buf_get\(fid,)X
+2107(0,)X
+2251(BF_PIN,)X
+2635(&len\);)X
+1 f
+555 3307(The)N
+714(BF_PIN)X
+1014(argument)X
+1350(to)X
+2 f
+1445(buf_get)X
+1 f
+1718(indicates)X
+2036(that)X
+2189(we)X
+2316(wish)X
+2500(to)X
+2595(leave)X
+2798(this)X
+2946(page)X
+3131(pinned)X
+3382(in)X
+3477(memory)X
+3777(so)X
+3881(that)X
+4034(it)X
+4111(is)X
+4197(not)X
+555 3397(swapped)N
+862(out)X
+990(while)X
+1194(we)X
+1314(are)X
+1439(accessing)X
+1772(it.)X
+1881(The)X
+2031(last)X
+2167(argument)X
+2495(to)X
+2 f
+2582(buf_get)X
+1 f
+2847(returns)X
+3095(the)X
+3218(number)X
+3488(of)X
+3580(bytes)X
+3774(on)X
+3879(the)X
+4002(page)X
+4179(that)X
+555 3487(were)N
+732(valid)X
+912(so)X
+1003(that)X
+1143(the)X
+1261(access)X
+1487(method)X
+1747(may)X
+1905(initialize)X
+2205(the)X
+2323(page)X
+2495(if)X
+2564(necessary.)X
+755 3610(Next,)N
+955(consider)X
+1251(inserting)X
+1555(a)X
+1615(record)X
+1845(on)X
+1949(a)X
+2009(particular)X
+2341(page)X
+2517(of)X
+2608(a)X
+2668(B-tree.)X
+2932(In)X
+3022(the)X
+3143(unprotected)X
+3545(case,)X
+3727(we)X
+3844(read)X
+4006(the)X
+4127(page,)X
+555 3700(call)N
+2 f
+693(_bt_insertat)X
+1 f
+1079(,)X
+1121(and)X
+1258(write)X
+1444(the)X
+1563(page.)X
+1776(Instead,)X
+2049(we)X
+2164(lock)X
+2323(the)X
+2442(page,)X
+2635(request)X
+2888(the)X
+3007(buffer,)X
+3245(log)X
+3368(the)X
+3487(change,)X
+3756(modify)X
+4008(the)X
+4127(page,)X
+555 3790(and)N
+691(release)X
+935(the)X
+1053(buffer.)X
+7 f
+715 3913(int)N
+907(fid,)X
+1147(len,)X
+1387(pageno;)X
+1867(/*)X
+2011(Identifies)X
+2539(the)X
+2731(buffer)X
+3067(*/)X
+715 4003(int)N
+907(index;)X
+1867(/*)X
+2011(Location)X
+2443(at)X
+2587(which)X
+2875(to)X
+3019(insert)X
+3355(the)X
+3547(new)X
+3739(pair)X
+3979(*/)X
+715 4093(DBT)N
+907(*keyp,)X
+1243(*datap;)X
+1867(/*)X
+2011(Key/Data)X
+2443(pair)X
+2683(to)X
+2827(be)X
+2971(inserted)X
+3403(*/)X
+715 4183(DATUM)N
+1003(*d;)X
+1867(/*)X
+2011(Key/data)X
+2443(structure)X
+2923(to)X
+3067(insert)X
+3403(*/)X
+715 4363(/*)N
+859(Lock)X
+1099(and)X
+1291(request)X
+1675(the)X
+1867(buffer)X
+2203(*/)X
+715 4453(if)N
+859(\(tp_lock\(fid,)X
+1531(pageno,)X
+1915(WRITE_LOCK\)\))X
+1003 4543(return)N
+1339(error;)X
+715 4633(buffer_ptr)N
+1243(=)X
+1339(buf_get\(fid,)X
+1963(pageno,)X
+2347(BF_PIN,)X
+2731(&len\);)X
+715 4813(/*)N
+859(Log)X
+1051(and)X
+1243(perform)X
+1627(the)X
+1819(update)X
+2155(*/)X
+715 4903(log_insdel\(BTREE_INSERT,)N
+1915(fid,)X
+2155(pageno,)X
+2539(keyp,)X
+2827(datap\);)X
+715 4993(_bt_insertat\(buffer_ptr,)N
+1915(d,)X
+2059(index\);)X
+715 5083(buf_unpin\(buffer_ptr\);)N
+1 f
+555 5206(Succinctly,)N
+942(the)X
+1068(algorithm)X
+1407(for)X
+1529(turning)X
+1788(unprotected)X
+2195(code)X
+2375(into)X
+2527(protected)X
+2854(code)X
+3034(is)X
+3115(to)X
+3205(replace)X
+3466(read)X
+3633(operations)X
+3995(with)X
+2 f
+4165(lock)X
+1 f
+555 5296(and)N
+2 f
+691(buf_get)X
+1 f
+951(operations)X
+1305(and)X
+1441(write)X
+1626(operations)X
+1980(with)X
+2 f
+2142(log)X
+1 f
+2264(and)X
+2 f
+2400(buf_unpin)X
+1 f
+2744(operations.)X
+8 s
+10 f
+555 5458(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5536(3)N
+8 s
+766 5561(The)N
+884(following)X
+1152(code)X
+1291(fragments)X
+1565(are)X
+1661(examples,)X
+1937(but)X
+2038(do)X
+2120(not)X
+2220(de\256ne)X
+2394(the)X
+2490(\256nal)X
+2622(interface.)X
+2894(The)X
+3011(\256nal)X
+3143(interface)X
+3383(will)X
+3501(be)X
+3579(determined)X
+3884(after)X
+4018(LIBTP)X
+4214(has)X
+555 5633(been)N
+691(fully)X
+828(integrated)X
+1099(with)X
+1229(the)X
+1323(most)X
+1464(recent)X
+3 f
+1635(db)X
+1 f
+1707(\(3\))X
+1797(release)X
+1989(from)X
+2129(the)X
+2223(Computer)X
+2495(Systems)X
+2725(Research)X
+2974(Group)X
+3153(at)X
+3215(University)X
+3501(of)X
+3570(California,)X
+3861(Berkeley.)X
+
+11 p
+%%Page: 11 11
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+555 630(5.)N
+655(Performance)X
+1 f
+755 753(In)N
+845(this)X
+983(section,)X
+1253(we)X
+1370(present)X
+1625(the)X
+1746(results)X
+1978(of)X
+2067(two)X
+2209(very)X
+2374(different)X
+2673(benchmarks.)X
+3103(The)X
+3250(\256rst)X
+3396(is)X
+3471(an)X
+3569(online)X
+3791(transaction)X
+4165(pro-)X
+555 843(cessing)N
+824(benchmark,)X
+1234(similar)X
+1489(to)X
+1584(the)X
+1715(standard)X
+2020(TPCB,)X
+2272(but)X
+2407(has)X
+2547(been)X
+2732(adapted)X
+3015(to)X
+3110(run)X
+3250(in)X
+3345(a)X
+3414(desktop)X
+3696(environment.)X
+4174(The)X
+555 933(second)N
+798(emulates)X
+1103(a)X
+1159(computer-aided)X
+1683(design)X
+1912(environment)X
+2337(and)X
+2473(provides)X
+2769(more)X
+2954(complex)X
+3250(query)X
+3453(processing.)X
+3 f
+555 1119(5.1.)N
+715(Transaction)X
+1148(Processing)X
+1533(Benchmark)X
+1 f
+755 1242(For)N
+887(this)X
+1023(section,)X
+1291(all)X
+1392(performance)X
+1820(numbers)X
+2117(shown)X
+2346(except)X
+2576(for)X
+2690(the)X
+2808(commercial)X
+3207(database)X
+3504(system)X
+3746(were)X
+3923(obtained)X
+4219(on)X
+555 1332(a)N
+614(DECstation)X
+1009(5000/200)X
+1333(with)X
+1497(32MBytes)X
+1852(of)X
+1941(memory)X
+2230(running)X
+2501(Ultrix)X
+2714(V4.0,)X
+2914(accessing)X
+3244(a)X
+3302(DEC)X
+3484(RZ57)X
+3688(1GByte)X
+3959(disk)X
+4114(drive.)X
+555 1422(The)N
+720(commercial)X
+1139(relational)X
+1482(database)X
+1799(system)X
+2061(tests)X
+2242(were)X
+2438(run)X
+2584(on)X
+2703(a)X
+2778(comparable)X
+3192(machine,)X
+3523(a)X
+3598(Sparcstation)X
+4033(1+)X
+4157(with)X
+555 1512(32MBytes)N
+915(memory)X
+1209(and)X
+1352(a)X
+1415(1GByte)X
+1691(external)X
+1976(disk)X
+2135(drive.)X
+2366(The)X
+2517(database,)X
+2840(binaries)X
+3120(and)X
+3262(log)X
+3390(resided)X
+3648(on)X
+3754(the)X
+3878(same)X
+4069(device.)X
+555 1602(Reported)N
+869(times)X
+1062(are)X
+1181(the)X
+1299(means)X
+1524(of)X
+1611(\256ve)X
+1751(tests)X
+1913(and)X
+2049(have)X
+2221(standard)X
+2513(deviations)X
+2862(within)X
+3086(two)X
+3226(percent)X
+3483(of)X
+3570(the)X
+3688(mean.)X
+755 1725(The)N
+905(test)X
+1041(database)X
+1343(was)X
+1493(con\256gured)X
+1861(according)X
+2203(to)X
+2290(the)X
+2413(TPCB)X
+2637(scaling)X
+2889(rules)X
+3070(for)X
+3189(a)X
+3250(10)X
+3355(transaction)X
+3732(per)X
+3860(second)X
+4108(\(TPS\))X
+555 1815(system)N
+817(with)X
+999(1,000,000)X
+1359(account)X
+1649(records,)X
+1946(100)X
+2106(teller)X
+2311(records,)X
+2607(and)X
+2762(10)X
+2881(branch)X
+3139(records.)X
+3455(Where)X
+3709(TPS)X
+3885(numbers)X
+4200(are)X
+555 1905(reported,)N
+865(we)X
+981(are)X
+1102(running)X
+1373(a)X
+1431(modi\256ed)X
+1737(version)X
+1995(of)X
+2084(the)X
+2203(industry)X
+2486(standard)X
+2779(transaction)X
+3152(processing)X
+3516(benchmark,)X
+3914(TPCB.)X
+4174(The)X
+555 1995(TPCB)N
+780(benchmark)X
+1163(simulates)X
+1491(a)X
+1553(withdrawal)X
+1940(performed)X
+2301(by)X
+2407(a)X
+2469(hypothetical)X
+2891(teller)X
+3082(at)X
+3166(a)X
+3228(hypothetical)X
+3650(bank.)X
+3872(The)X
+4022(database)X
+555 2085(consists)N
+831(of)X
+921(relations)X
+1220(\(\256les\))X
+1430(for)X
+1547(accounts,)X
+1871(branches,)X
+2200(tellers,)X
+2439(and)X
+2578(history.)X
+2863(For)X
+2997(each)X
+3168(transaction,)X
+3563(the)X
+3684(account,)X
+3976(teller,)X
+4183(and)X
+555 2175(branch)N
+795(balances)X
+1093(must)X
+1269(be)X
+1366(updated)X
+1641(to)X
+1724(re\257ect)X
+1946(the)X
+2065(withdrawal)X
+2447(and)X
+2584(a)X
+2640(history)X
+2882(record)X
+3108(is)X
+3181(written)X
+3428(which)X
+3644(contains)X
+3931(the)X
+4049(account)X
+555 2265(id,)N
+657(branch)X
+896(id,)X
+998(teller)X
+1183(id,)X
+1285(and)X
+1421(the)X
+1539(amount)X
+1799(of)X
+1886(the)X
+2004(withdrawal)X
+2385([TPCB90].)X
+755 2388(Our)N
+914(implementation)X
+1450(of)X
+1551(the)X
+1683(benchmark)X
+2074(differs)X
+2317(from)X
+2506(the)X
+2637(speci\256cation)X
+3075(in)X
+3170(several)X
+3431(aspects.)X
+3736(The)X
+3894(speci\256cation)X
+555 2478(requires)N
+840(that)X
+985(the)X
+1108(database)X
+1410(keep)X
+1587(redundant)X
+1933(logs)X
+2091(on)X
+2196(different)X
+2498(devices,)X
+2784(but)X
+2911(we)X
+3030(use)X
+3162(a)X
+3223(single)X
+3439(log.)X
+3606(Furthermore,)X
+4052(all)X
+4157(tests)X
+555 2568(were)N
+734(run)X
+863(on)X
+965(a)X
+1023(single,)X
+1256(centralized)X
+1631(system)X
+1875(so)X
+1968(there)X
+2151(is)X
+2226(no)X
+2328(notion)X
+2553(of)X
+2641(remote)X
+2885(accesses.)X
+3219(Finally,)X
+3486(we)X
+3601(calculated)X
+3948(throughput)X
+555 2658(by)N
+662(dividing)X
+955(the)X
+1080(total)X
+1249(elapsed)X
+1517(time)X
+1686(by)X
+1793(the)X
+1918(number)X
+2190(of)X
+2284(transactions)X
+2694(processed)X
+3038(rather)X
+3253(than)X
+3418(by)X
+3525(computing)X
+3894(the)X
+4018(response)X
+555 2748(time)N
+717(for)X
+831(each)X
+999(transaction.)X
+755 2871(The)N
+912(performance)X
+1351(comparisons)X
+1788(focus)X
+1993(on)X
+2104(traditional)X
+2464(Unix)X
+2655(techniques)X
+3029(\(unprotected,)X
+3486(using)X
+3 f
+3690(\257ock)X
+1 f
+3854(\(2\))X
+3979(and)X
+4126(using)X
+3 f
+555 2961(fsync)N
+1 f
+733(\(2\)\))X
+884(and)X
+1030(a)X
+1096(commercial)X
+1504(relational)X
+1836(database)X
+2142(system.)X
+2433(Well-behaved)X
+2913(applications)X
+3329(using)X
+3 f
+3531(\257ock)X
+1 f
+3695(\(2\))X
+3818(are)X
+3946(guaranteed)X
+555 3051(that)N
+704(concurrent)X
+1077(processes')X
+1441(updates)X
+1715(do)X
+1824(not)X
+1955(interact)X
+2225(with)X
+2396(one)X
+2541(another,)X
+2831(but)X
+2962(no)X
+3070(guarantees)X
+3442(about)X
+3648(atomicity)X
+3978(are)X
+4105(made.)X
+555 3141(That)N
+731(is,)X
+833(if)X
+911(the)X
+1038(system)X
+1289(crashes)X
+1555(in)X
+1646(mid-transaction,)X
+2198(only)X
+2369(parts)X
+2554(of)X
+2649(that)X
+2797(transaction)X
+3177(will)X
+3329(be)X
+3433(re\257ected)X
+3738(in)X
+3828(the)X
+3954 0.3125(after-crash)AX
+555 3231(state)N
+725(of)X
+815(the)X
+936(database.)X
+1276(The)X
+1424(use)X
+1554(of)X
+3 f
+1643(fsync)X
+1 f
+1821(\(2\))X
+1937(at)X
+2017(transaction)X
+2391(commit)X
+2657(time)X
+2821(provides)X
+3119(guarantees)X
+3485(of)X
+3574(durability)X
+3907(after)X
+4077(system)X
+555 3321(failure.)N
+825(However,)X
+1160(there)X
+1341(is)X
+1414(no)X
+1514(mechanism)X
+1899(to)X
+1981(perform)X
+2260(transaction)X
+2632(abort.)X
+3 f
+555 3507(5.1.1.)N
+775(Single-User)X
+1191(Tests)X
+1 f
+755 3630(These)N
+978(tests)X
+1151(compare)X
+1459(LIBTP)X
+1712(in)X
+1804(a)X
+1870(variety)X
+2123(of)X
+2220(con\256gurations)X
+2708(to)X
+2800(traditional)X
+3159(UNIX)X
+3390(solutions)X
+3708(and)X
+3854(a)X
+3920(commercial)X
+555 3720(relational)N
+884(database)X
+1187(system)X
+1435(\(RDBMS\).)X
+1814(To)X
+1929(demonstrate)X
+2347(the)X
+2471(server)X
+2694(architecture)X
+3100(we)X
+3220(built)X
+3392(a)X
+3454(front)X
+3636(end)X
+3777(test)X
+3913(process)X
+4179(that)X
+555 3810(uses)N
+732(TCL)X
+922([OUST90])X
+1304(to)X
+1405(parse)X
+1614(database)X
+1930(access)X
+2175(commands)X
+2561(and)X
+2716(call)X
+2870(the)X
+3006(database)X
+3321(access)X
+3565(routines.)X
+3901(In)X
+4006(one)X
+4160(case)X
+555 3900(\(SERVER\),)N
+956(frontend)X
+1249(and)X
+1386(backend)X
+1675(processes)X
+2004(were)X
+2181(created)X
+2434(which)X
+2650(communicated)X
+3142(via)X
+3260(an)X
+3356(IP)X
+3447(socket.)X
+3712(In)X
+3799(the)X
+3917(second)X
+4160(case)X
+555 3990(\(TCL\),)N
+802(a)X
+860(single)X
+1073(process)X
+1336(read)X
+1497(queries)X
+1751(from)X
+1929(standard)X
+2223(input,)X
+2429(parsed)X
+2660(them,)X
+2861(and)X
+2998(called)X
+3211(the)X
+3330(database)X
+3628(access)X
+3855(routines.)X
+4174(The)X
+555 4080(performance)N
+987(difference)X
+1338(between)X
+1630(the)X
+1752(TCL)X
+1927(and)X
+2067(SERVER)X
+2397(tests)X
+2563(quanti\256es)X
+2898(the)X
+3020(communication)X
+3542(overhead)X
+3861(of)X
+3952(the)X
+4074(socket.)X
+555 4170(The)N
+732(RDBMS)X
+1063(implementation)X
+1617(used)X
+1816(embedded)X
+2198(SQL)X
+2401(in)X
+2515(C)X
+2620(with)X
+2814(stored)X
+3062(database)X
+3391(procedures.)X
+3835(Therefore,)X
+4224(its)X
+555 4260(con\256guration)N
+1003(is)X
+1076(a)X
+1132(hybrid)X
+1361(of)X
+1448(the)X
+1566(single)X
+1777(process)X
+2038(architecture)X
+2438(and)X
+2574(the)X
+2692(server)X
+2909(architecture.)X
+3349(The)X
+3494(graph)X
+3697(in)X
+3779(\256gure)X
+3986(six)X
+4099(shows)X
+555 4350(a)N
+611(comparison)X
+1005(of)X
+1092(the)X
+1210(following)X
+1541(six)X
+1654(con\256gurations:)X
+1126 4506(LIBTP)N
+1552(Uses)X
+1728(the)X
+1846(LIBTP)X
+2088(library)X
+2322(in)X
+2404(a)X
+2460(single)X
+2671(application.)X
+1126 4596(TCL)N
+1552(Uses)X
+1728(the)X
+1846(LIBTP)X
+2088(library)X
+2322(in)X
+2404(a)X
+2460(single)X
+2671(application,)X
+3067(requires)X
+3346(query)X
+3549(parsing.)X
+1126 4686(SERVER)N
+1552(Uses)X
+1728(the)X
+1846(LIBTP)X
+2088(library)X
+2322(in)X
+2404(a)X
+2460(server)X
+2677(con\256guration,)X
+3144(requires)X
+3423(query)X
+3626(parsing.)X
+1126 4776(NOTP)N
+1552(Uses)X
+1728(no)X
+1828(locking,)X
+2108(logging,)X
+2392(or)X
+2479(concurrency)X
+2897(control.)X
+1126 4866(FLOCK)N
+1552(Uses)X
+3 f
+1728(\257ock)X
+1 f
+1892(\(2\))X
+2006(for)X
+2120(concurrency)X
+2538(control)X
+2785(and)X
+2921(nothing)X
+3185(for)X
+3299(durability.)X
+1126 4956(FSYNC)N
+1552(Uses)X
+3 f
+1728(fsync)X
+1 f
+1906(\(2\))X
+2020(for)X
+2134(durability)X
+2465(and)X
+2601(nothing)X
+2865(for)X
+2979(concurrency)X
+3397(control.)X
+1126 5046(RDBMS)N
+1552(Uses)X
+1728(a)X
+1784(commercial)X
+2183(relational)X
+2506(database)X
+2803(system.)X
+755 5235(The)N
+902(results)X
+1133(show)X
+1324(that)X
+1466(LIBTP,)X
+1730(both)X
+1894(in)X
+1978(the)X
+2098(procedural)X
+2464(and)X
+2602(parsed)X
+2834(environments,)X
+3312(is)X
+3387(competitive)X
+3787(with)X
+3951(a)X
+4009(commer-)X
+555 5325(cial)N
+692(system)X
+935(\(comparing)X
+1326(LIBTP,)X
+1589(TCL,)X
+1781(and)X
+1917(RDBMS\).)X
+2263(Compared)X
+2617(to)X
+2699(existing)X
+2972(UNIX)X
+3193(solutions,)X
+3521(LIBTP)X
+3763(is)X
+3836(approximately)X
+555 5415(15%)N
+738(slower)X
+988(than)X
+1162(using)X
+3 f
+1371(\257ock)X
+1 f
+1535(\(2\))X
+1665(or)X
+1768(no)X
+1884(protection)X
+2245(but)X
+2383(over)X
+2562(80%)X
+2745(better)X
+2964(than)X
+3137(using)X
+3 f
+3345(fsync)X
+1 f
+3523(\(2\))X
+3652(\(comparing)X
+4057(LIBTP,)X
+555 5505(FLOCK,)N
+857(NOTP,)X
+1106(and)X
+1242(FSYNC\).)X
+
+12 p
+%%Page: 12 12
+10 s 10 xH 0 xS 1 f
+3 f
+8 s
+3500 2184(RDBMS)N
+1 Dt
+3553 2085 MXY
+ 3553 2085 lineto
+ 3676 2085 lineto
+ 3676 1351 lineto
+ 3553 1351 lineto
+ 3553 2085 lineto
+closepath 16 3553 1351 3676 2085 Dp
+2018 2184(SERVER)N
+1720 1168 MXY
+0 917 Dl
+122 0 Dl
+0 -917 Dl
+-122 0 Dl
+1715 2184(TCL)N
+2087 1534 MXY
+ 2087 1534 lineto
+ 2209 1534 lineto
+ 2209 2085 lineto
+ 2087 2085 lineto
+ 2087 1534 lineto
+closepath 12 2087 1534 2209 2085 Dp
+3187 MX
+ 3187 1534 lineto
+ 3309 1534 lineto
+ 3309 2085 lineto
+ 3187 2085 lineto
+ 3187 1534 lineto
+closepath 19 3187 1534 3309 2085 Dp
+3142 2184(FSYNC)N
+2425(NOTP)X
+2453 955 MXY
+ 2453 955 lineto
+ 2576 955 lineto
+ 2576 2085 lineto
+ 2453 2085 lineto
+ 2453 955 lineto
+closepath 21 2453 955 2576 2085 Dp
+2820 1000 MXY
+ 2820 1000 lineto
+ 2942 1000 lineto
+ 2942 2085 lineto
+ 2820 2085 lineto
+ 2820 1000 lineto
+closepath 14 2820 1000 2942 2085 Dp
+5 Dt
+1231 2085 MXY
+2567 0 Dl
+4 Ds
+1 Dt
+1231 1840 MXY
+2567 0 Dl
+1231 1596 MXY
+2567 0 Dl
+1231 1351 MXY
+2567 0 Dl
+1231 1108 MXY
+2567 0 Dl
+1231 863 MXY
+2567 0 Dl
+11 s
+1087 1877(2)N
+1087 1633(4)N
+1087 1388(6)N
+1087 1145(8)N
+1065 900(10)N
+1028 763(TPS)N
+-1 Ds
+1353 2085 MXY
+ 1353 2085 lineto
+ 1353 1151 lineto
+ 1476 1151 lineto
+ 1476 2085 lineto
+ 1353 2085 lineto
+closepath 3 1353 1151 1476 2085 Dp
+8 s
+1318 2184(LIBTP)N
+2767(FLOCK)X
+3 Dt
+-1 Ds
+10 s
+1597 2399(Figure)N
+1844(6:)X
+1931(Single-User)X
+2347(Performance)X
+2814(Comparison.)X
+1 f
+10 f
+555 2579(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+3 f
+555 2855(5.1.2.)N
+775(Multi-User)X
+1174(Tests)X
+1 f
+755 2978(While)N
+975(the)X
+1097(single-user)X
+1473(tests)X
+1639(form)X
+1819(a)X
+1878(basis)X
+2061(for)X
+2178(comparing)X
+2544(LIBTP)X
+2789(to)X
+2874(other)X
+3062(systems,)X
+3358(our)X
+3488(goal)X
+3649(in)X
+3734(multi-user)X
+4086(testing)X
+555 3068(was)N
+714(to)X
+810(analyze)X
+1089(its)X
+1197(scalability.)X
+1579(To)X
+1701(this)X
+1849(end,)X
+2018(we)X
+2145(have)X
+2330(run)X
+2470(the)X
+2601(benchmark)X
+2991(in)X
+3086(three)X
+3280(modes,)X
+3542(the)X
+3673(normal)X
+3933(disk)X
+4099(bound)X
+555 3158(con\256guration)N
+1010(\(\256gure)X
+1252(seven\),)X
+1510(a)X
+1573(CPU)X
+1755(bound)X
+1982(con\256guration)X
+2436(\(\256gure)X
+2677(eight,)X
+2884(READ-ONLY\),)X
+3426(and)X
+3569(lock)X
+3734(contention)X
+4099(bound)X
+555 3248(\(\256gure)N
+796(eight,)X
+1003(NO_FSYNC\).)X
+1510(Since)X
+1715(the)X
+1840(normal)X
+2094(con\256guration)X
+2548(is)X
+2628(completely)X
+3011(disk)X
+3171(bound)X
+3398(\(each)X
+3600(transaction)X
+3978(requires)X
+4263(a)X
+555 3354(random)N
+823(read,)X
+1005(a)X
+1064(random)X
+1332(write,)X
+1540(and)X
+1679(a)X
+1738(sequential)X
+2086(write)X
+7 s
+2251 3322(4)N
+10 s
+3354(\))Y
+2329(we)X
+2446(expect)X
+2679(to)X
+2764(see)X
+2890(little)X
+3059(performance)X
+3489(improvement)X
+3939(as)X
+4028(the)X
+4148(mul-)X
+555 3444(tiprogramming)N
+1064(level)X
+1249(increases.)X
+1613(In)X
+1709(fact,)X
+1879(\256gure)X
+2095(seven)X
+2307(reveals)X
+2564(that)X
+2713(we)X
+2836(are)X
+2964(able)X
+3127(to)X
+3218(overlap)X
+3487(CPU)X
+3670(and)X
+3814(disk)X
+3975(utilization)X
+555 3534(slightly)N
+825(producing)X
+1181(approximately)X
+1674(a)X
+1740(10%)X
+1917(performance)X
+2354(improvement)X
+2811(with)X
+2983(two)X
+3133(processes.)X
+3511(After)X
+3711(that)X
+3861(point,)X
+4075(perfor-)X
+555 3624(mance)N
+785(drops)X
+983(off,)X
+1117(and)X
+1253(at)X
+1331(a)X
+1387(multi-programming)X
+2038(level)X
+2214(of)X
+2301(4,)X
+2381(we)X
+2495(are)X
+2614(performing)X
+2995(worse)X
+3207(than)X
+3365(in)X
+3447(the)X
+3565(single)X
+3776(process)X
+4037(case.)X
+755 3747(Similar)N
+1021(behavior)X
+1333(was)X
+1489(reported)X
+1787(on)X
+1897(the)X
+2025(commercial)X
+2434(relational)X
+2767(database)X
+3074(system)X
+3326(using)X
+3529(the)X
+3657(same)X
+3852(con\256guration.)X
+555 3837(The)N
+707(important)X
+1045(conclusion)X
+1419(to)X
+1508(draw)X
+1696(from)X
+1879(this)X
+2021(is)X
+2101(that)X
+2248(you)X
+2395(cannot)X
+2636(attain)X
+2841(good)X
+3028(multi-user)X
+3384(scaling)X
+3638(on)X
+3745(a)X
+3808(badly)X
+4013(balanced)X
+555 3927(system.)N
+839(If)X
+915(multi-user)X
+1266(performance)X
+1695(on)X
+1797(applications)X
+2205(of)X
+2293(this)X
+2429(sort)X
+2570(is)X
+2644(important,)X
+2996(one)X
+3133(must)X
+3309(have)X
+3482(a)X
+3539(separate)X
+3824(logging)X
+4089(device)X
+555 4017(and)N
+697(horizontally)X
+1110(partition)X
+1407(the)X
+1531(database)X
+1834(to)X
+1921(allow)X
+2124(a)X
+2185(suf\256ciently)X
+2570(high)X
+2737(degree)X
+2977(of)X
+3069(multiprogramming)X
+3698(that)X
+3843(group)X
+4055(commit)X
+555 4107(can)N
+687(amortize)X
+988(the)X
+1106(cost)X
+1255(of)X
+1342(log)X
+1464(\257ushing.)X
+755 4230(By)N
+871(using)X
+1067(a)X
+1126(very)X
+1292(small)X
+1488(database)X
+1788(\(one)X
+1954(that)X
+2097(can)X
+2232(be)X
+2331(entirely)X
+2599(cached)X
+2846(in)X
+2930(main)X
+3112(memory\))X
+3428(and)X
+3566(read-only)X
+3896(transactions,)X
+555 4320(we)N
+670(generated)X
+1004(a)X
+1061(CPU)X
+1236(bound)X
+1456(environment.)X
+1921(By)X
+2034(using)X
+2227(the)X
+2345(same)X
+2530(small)X
+2723(database,)X
+3040(the)X
+3158(complete)X
+3472(TPCB)X
+3691(transaction,)X
+4083(and)X
+4219(no)X
+3 f
+555 4410(fsync)N
+1 f
+733(\(2\))X
+862(on)X
+977(the)X
+1110(log)X
+1247(at)X
+1340(commit,)X
+1639(we)X
+1768(created)X
+2036(a)X
+2107(lock)X
+2280(contention)X
+2652(bound)X
+2886(environment.)X
+3365(The)X
+3524(small)X
+3731(database)X
+4042(used)X
+4223(an)X
+555 4500(account)N
+828(\256le)X
+953(containing)X
+1314(only)X
+1479(1000)X
+1662(records)X
+1922(rather)X
+2133(than)X
+2294(the)X
+2415(full)X
+2549(1,000,000)X
+2891(records)X
+3150(and)X
+3288(ran)X
+3413(enough)X
+3671(transactions)X
+4076(to)X
+4160(read)X
+555 4590(the)N
+677(entire)X
+883(database)X
+1183(into)X
+1330(the)X
+1451(buffer)X
+1671(pool)X
+1836(\(2000\))X
+2073(before)X
+2302(beginning)X
+2645(measurements.)X
+3147(The)X
+3295(read-only)X
+3626(transaction)X
+4001(consisted)X
+555 4680(of)N
+646(three)X
+831(database)X
+1132(reads)X
+1326(\(from)X
+1533(the)X
+1655(1000)X
+1839(record)X
+2069(account)X
+2343(\256le,)X
+2489(the)X
+2611(100)X
+2754(record)X
+2983(teller)X
+3171(\256le,)X
+3316(and)X
+3455(the)X
+3576(10)X
+3679(record)X
+3908(branch)X
+4150(\256le\).)X
+555 4770(Since)N
+759(no)X
+865(data)X
+1025(were)X
+1208(modi\256ed)X
+1518(and)X
+1660(no)X
+1766(history)X
+2014(records)X
+2277(were)X
+2460(written,)X
+2733(no)X
+2839(log)X
+2966(records)X
+3228(were)X
+3410(written.)X
+3702(For)X
+3838(the)X
+3961(contention)X
+555 4860(bound)N
+780(con\256guration,)X
+1252(we)X
+1371(used)X
+1543(the)X
+1666(normal)X
+1918(TPCB)X
+2142(transaction)X
+2519(\(against)X
+2798(the)X
+2920(small)X
+3117(database\))X
+3445(and)X
+3585(disabled)X
+3876(the)X
+3998(log)X
+4124(\257ush.)X
+555 4950(Figure)N
+784(eight)X
+964(shows)X
+1184(both)X
+1346(of)X
+1433(these)X
+1618(results.)X
+755 5073(The)N
+902(read-only)X
+1231(test)X
+1363(indicates)X
+1669(that)X
+1810(we)X
+1925(barely)X
+2147(scale)X
+2329(at)X
+2408(all)X
+2509(in)X
+2592(the)X
+2711(CPU)X
+2887(bound)X
+3108(case.)X
+3308(The)X
+3454(explanation)X
+3849(for)X
+3964(that)X
+4105(is)X
+4179(that)X
+555 5163(even)N
+735(with)X
+905(a)X
+969(single)X
+1188(process,)X
+1477(we)X
+1599(are)X
+1726(able)X
+1888(to)X
+1978(drive)X
+2171(the)X
+2297(CPU)X
+2480(utilization)X
+2832(to)X
+2922(96%.)X
+3137(As)X
+3254(a)X
+3317(result,)X
+3542(that)X
+3689(gives)X
+3885(us)X
+3983(very)X
+4153(little)X
+555 5253(room)N
+753(for)X
+876(improvement,)X
+1352(and)X
+1497(it)X
+1570(takes)X
+1764(a)X
+1829(multiprogramming)X
+2462(level)X
+2647(of)X
+2743(four)X
+2906(to)X
+2997(approach)X
+3321(100%)X
+3537(CPU)X
+3721(saturation.)X
+4106(In)X
+4201(the)X
+555 5343(case)N
+718(where)X
+939(we)X
+1057(do)X
+1161(perform)X
+1444(writes,)X
+1684(we)X
+1802(are)X
+1925(interested)X
+2261(in)X
+2347(detecting)X
+2665(when)X
+2863(lock)X
+3025(contention)X
+3387(becomes)X
+3691(a)X
+3750(dominant)X
+4075(perfor-)X
+555 5433(mance)N
+787(factor.)X
+1037(Contention)X
+1414(will)X
+1560(cause)X
+1761(two)X
+1903(phenomena;)X
+2317(we)X
+2433(will)X
+2579(see)X
+2704(transactions)X
+3109(queueing)X
+3425(behind)X
+3665(frequently)X
+4017(accessed)X
+555 5523(data,)N
+731(and)X
+869(we)X
+985(will)X
+1131(see)X
+1256(transaction)X
+1629(abort)X
+1815(rates)X
+1988(increasing)X
+2339(due)X
+2476(to)X
+2559(deadlock.)X
+2910(Given)X
+3127(that)X
+3268(the)X
+3387(branch)X
+3627(\256le)X
+3750(contains)X
+4038(only)X
+4201(ten)X
+8 s
+10 f
+555 5595(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5673(4)N
+8 s
+763 5698(Although)N
+1021(the)X
+1115(log)X
+1213(is)X
+1272(written)X
+1469(sequentially,)X
+1810(we)X
+1900(do)X
+1980(not)X
+2078(get)X
+2172(the)X
+2266(bene\256t)X
+2456(of)X
+2525(sequentiality)X
+2868(since)X
+3015(the)X
+3109(log)X
+3207(and)X
+3315(database)X
+3550(reside)X
+3718(on)X
+3798(the)X
+3892(same)X
+4039(disk.)X
+
+13 p
+%%Page: 13 13
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+3187 2051 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3286 2028 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3384 1926 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3483 1910 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3581 1910 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3680 1832 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3778 1909 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3877 1883 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3975 1679 MXY
+0 17 Dl
+0 -8 Dl
+9 0 Dl
+-18 0 Dl
+4074 1487 MXY
+0 17 Dl
+0 -8 Dl
+9 0 Dl
+-18 0 Dl
+5 Dt
+3187 2060 MXY
+99 -24 Dl
+98 -101 Dl
+99 -16 Dl
+98 0 Dl
+99 -78 Dl
+98 77 Dl
+99 -26 Dl
+98 -204 Dl
+99 -192 Dl
+3 f
+6 s
+4088 1516(SMALL)N
+3 Dt
+3187 2051 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3286 2051 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3384 2041 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3483 1990 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3581 1843 MXY
+0 17 Dl
+0 -8 Dl
+9 0 Dl
+-18 0 Dl
+3680 1578 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3778 1496 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3877 1430 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3975 1269 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+4074 1070 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1 Dt
+3187 2060 MXY
+99 0 Dl
+98 -10 Dl
+99 -51 Dl
+98 -147 Dl
+99 -265 Dl
+98 -82 Dl
+99 -66 Dl
+98 -161 Dl
+99 -199 Dl
+4088 1099(LARGE)N
+5 Dt
+3089 2060 MXY
+985 0 Dl
+3089 MX
+0 -1174 Dl
+4 Ds
+1 Dt
+3581 2060 MXY
+0 -1174 Dl
+4074 2060 MXY
+0 -1174 Dl
+3089 1825 MXY
+985 0 Dl
+9 s
+2993 1855(25)N
+3089 1591 MXY
+985 0 Dl
+2993 1621(50)N
+3089 1356 MXY
+985 0 Dl
+2993 1386(75)N
+3089 1121 MXY
+985 0 Dl
+2957 1151(100)N
+3089 886 MXY
+985 0 Dl
+2957 916(125)N
+3281 2199(Multiprogramming)N
+3071 2152(0)N
+3569(5)X
+4038(10)X
+2859 787(Aborts)N
+3089(per)X
+3211(500)X
+2901 847(transactions)N
+-1 Ds
+3 Dt
+2037 1342 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2125 1358 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2213 1341 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2301 1191 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2388 1124 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-17 0 Dl
+2476 1157 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2564 1157 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2652 1161 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2740 1153 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2828 1150 MXY
+0 18 Dl
+0 -9 Dl
+8 0 Dl
+-17 0 Dl
+5 Dt
+2037 1351 MXY
+88 16 Dl
+88 -17 Dl
+88 -150 Dl
+87 -67 Dl
+88 33 Dl
+88 0 Dl
+88 4 Dl
+88 -8 Dl
+88 -3 Dl
+6 s
+2685 1234(READ-ONLY)N
+3 Dt
+2037 1464 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2125 1640 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2213 1854 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2301 1872 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2388 1871 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-17 0 Dl
+2476 1933 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2564 1914 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2652 1903 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2740 1980 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2828 2004 MXY
+0 18 Dl
+0 -9 Dl
+8 0 Dl
+-17 0 Dl
+1 Dt
+2037 1473 MXY
+88 176 Dl
+88 214 Dl
+88 18 Dl
+87 -2 Dl
+88 63 Dl
+88 -19 Dl
+88 -11 Dl
+88 77 Dl
+88 24 Dl
+2759 1997(NO-FSYNC)N
+5 Dt
+1949 2060 MXY
+879 0 Dl
+1949 MX
+0 -1174 Dl
+4 Ds
+1 Dt
+2388 2060 MXY
+0 -1174 Dl
+2828 2060 MXY
+0 -1174 Dl
+1949 1825 MXY
+879 0 Dl
+9 s
+1842 1855(40)N
+1949 1591 MXY
+879 0 Dl
+1842 1621(80)N
+1949 1356 MXY
+879 0 Dl
+1806 1386(120)N
+1949 1121 MXY
+879 0 Dl
+1806 1151(160)N
+1949 886 MXY
+879 0 Dl
+1806 916(200)N
+2088 2199(Multiprogramming)N
+1844 863(in)N
+1922(TPS)X
+1761 792(Throughput)N
+1931 2121(0)N
+2370 2133(5)N
+2792(10)X
+6 s
+1679 1833(LIBTP)N
+-1 Ds
+3 Dt
+837 1019 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+929 878 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1021 939 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1113 1043 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1205 1314 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1297 1567 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1389 1665 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1481 1699 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1573 1828 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1665 1804 MXY
+0 18 Dl
+0 -9 Dl
+8 0 Dl
+-17 0 Dl
+5 Dt
+837 1027 MXY
+92 -141 Dl
+92 62 Dl
+92 104 Dl
+92 271 Dl
+92 253 Dl
+92 98 Dl
+92 34 Dl
+92 129 Dl
+92 -24 Dl
+745 2060 MXY
+920 0 Dl
+745 MX
+0 -1174 Dl
+4 Ds
+1 Dt
+1205 2060 MXY
+0 -1174 Dl
+1665 2060 MXY
+0 -1174 Dl
+745 1766 MXY
+920 0 Dl
+9 s
+673 1796(3)N
+745 1473 MXY
+920 0 Dl
+673 1503(5)N
+745 1180 MXY
+920 0 Dl
+673 1210(8)N
+745 886 MXY
+920 0 Dl
+637 916(10)N
+905 2199(Multiprogramming)N
+622 851(in)N
+700(TPS)X
+575 792(Throughput)N
+733 2152(0)N
+1196(5)X
+1629(10)X
+3 Dt
+-1 Ds
+8 s
+655 2441(Figure)N
+872(7:)X
+960(Multi-user)X
+1286(Performance.)X
+1 f
+655 2531(Since)N
+825(the)X
+931(con\256guration)X
+1300(is)X
+1371(completely)X
+655 2621(disk)N
+790(bound,)X
+994(we)X
+1096(see)X
+1204(only)X
+1345(a)X
+1400(small)X
+1566(im-)X
+655 2711(provement)N
+964(by)X
+1064(adding)X
+1274(a)X
+1337(second)X
+1549(pro-)X
+655 2801(cess.)N
+849(Adding)X
+1081(any)X
+1213(more)X
+1383(concurrent)X
+655 2891(processes)N
+935(causes)X
+1137(performance)X
+1493(degra-)X
+655 2981(dation.)N
+3 f
+1927 2441(Figure)N
+2149(8:)X
+2243(Multi-user)X
+2574(Performance)X
+1927 2531(on)N
+2021(a)X
+2079(small)X
+2251(database.)X
+1 f
+2551(With)X
+2704(one)X
+2821(pro-)X
+1927 2621(cess,)N
+2075(we)X
+2174(are)X
+2276(driving)X
+2486(the)X
+2589(CPU)X
+2739(at)X
+2810(96%)X
+1927 2711(utilization)N
+2215(leaving)X
+2430(little)X
+2575(room)X
+2737(for)X
+2838(im-)X
+1927 2801(provement)N
+2238(as)X
+2328(the)X
+2443(multiprogramming)X
+1927 2891(level)N
+2091(increases.)X
+2396(In)X
+2489(the)X
+2607(NO-FSYNC)X
+1927 2981(case,)N
+2076(lock)X
+2209(contention)X
+2502(degrades)X
+2751(perfor-)X
+1927 3071(mance)N
+2117(as)X
+2194(soon)X
+2339(as)X
+2416(a)X
+2468(second)X
+2669(process)X
+2884(is)X
+1927 3161(added.)N
+3 f
+3199 2441(Figure)N
+3405(9:)X
+3482(Abort)X
+3669(rates)X
+3827(on)X
+3919(the)X
+4028(TPCB)X
+3199 2531(Benchmark.)N
+1 f
+3589(The)X
+3726(abort)X
+3895(rate)X
+4028(climbs)X
+3199 2621(more)N
+3366(quickly)X
+3594(for)X
+3704(the)X
+3818(large)X
+3980(database)X
+3199 2711(test)N
+3324(since)X
+3491(processes)X
+3771(are)X
+3884(descheduled)X
+3199 2801(more)N
+3409(frequently,)X
+3766(allowing)X
+4068(more)X
+3199 2891(processes)N
+3459(to)X
+3525(vie)X
+3619(for)X
+3709(the)X
+3803(same)X
+3950(locks.)X
+10 s
+10 f
+555 3284(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 f
+555 3560(records,)N
+835(we)X
+952(expect)X
+1185(contention)X
+1546(to)X
+1631(become)X
+1904(a)X
+1963(factor)X
+2174(quickly)X
+2437(and)X
+2576(the)X
+2697(NO-FSYNC)X
+3120(line)X
+3263(in)X
+3348(\256gure)X
+3557(eight)X
+3739(demonstrates)X
+4184(this)X
+555 3650(dramatically.)N
+1022(Each)X
+1209(additional)X
+1555(process)X
+1822(causes)X
+2058(both)X
+2226(more)X
+2417(waiting)X
+2682(and)X
+2823(more)X
+3013(deadlocking.)X
+3470(Figure)X
+3704(nine)X
+3867(shows)X
+4092(that)X
+4237(in)X
+555 3740(the)N
+681(small)X
+882(database)X
+1187(case)X
+1353(\(SMALL\),)X
+1725(waiting)X
+1992(is)X
+2072(the)X
+2197(dominant)X
+2526(cause)X
+2732(of)X
+2826(declining)X
+3151(performance)X
+3585(\(the)X
+3737(number)X
+4009(of)X
+4103(aborts)X
+555 3830(increases)N
+878(less)X
+1026(steeply)X
+1281(than)X
+1447(the)X
+1573(performance)X
+2008(drops)X
+2214(off)X
+2336(in)X
+2426(\256gure)X
+2641(eight\),)X
+2876(while)X
+3082(in)X
+3172(the)X
+3298(large)X
+3487(database)X
+3792(case)X
+3958(\(LARGE\),)X
+555 3920(deadlocking)N
+967(contributes)X
+1343(more)X
+1528(to)X
+1610(the)X
+1728(declining)X
+2046(performance.)X
+755 4043(Deadlocks)N
+1116(are)X
+1237(more)X
+1424(likely)X
+1628(to)X
+1712(occur)X
+1913(in)X
+1997(the)X
+2116(LARGE)X
+2404(test)X
+2536(than)X
+2695(in)X
+2778(the)X
+2897(SMALL)X
+3189(test)X
+3321(because)X
+3597(there)X
+3779(are)X
+3899(more)X
+4085(oppor-)X
+555 4133(tunities)N
+814(to)X
+900(wait.)X
+1082(In)X
+1173(the)X
+1295(SMALL)X
+1590(case,)X
+1773(processes)X
+2105(never)X
+2307(do)X
+2410(I/O)X
+2540(and)X
+2679(are)X
+2801(less)X
+2944(likely)X
+3149(to)X
+3234(be)X
+3333(descheduled)X
+3753(during)X
+3985(a)X
+4044(transac-)X
+555 4223(tion.)N
+740(In)X
+828(the)X
+947(LARGE)X
+1235(case,)X
+1415(processes)X
+1744(will)X
+1889(frequently)X
+2240(be)X
+2337(descheduled)X
+2755(since)X
+2941(they)X
+3100(have)X
+3273(to)X
+3356(perform)X
+3636(I/O.)X
+3804(This)X
+3967(provides)X
+4263(a)X
+555 4313(window)N
+837(where)X
+1058(a)X
+1118(second)X
+1365(process)X
+1630(can)X
+1766(request)X
+2022(locks)X
+2215(on)X
+2318(already)X
+2578(locked)X
+2815(pages,)X
+3041(thus)X
+3197(increasing)X
+3550(the)X
+3671(likelihood)X
+4018(of)X
+4108(build-)X
+555 4403(ing)N
+677(up)X
+777(long)X
+939(chains)X
+1164(of)X
+1251(waiting)X
+1511(processes.)X
+1879(Eventually,)X
+2266(this)X
+2401(leads)X
+2586(to)X
+2668(deadlock.)X
+3 f
+555 4589(5.2.)N
+715(The)X
+868(OO1)X
+1052(Benchmark)X
+1 f
+755 4712(The)N
+903(TPCB)X
+1125(benchmark)X
+1505(described)X
+1836(in)X
+1921(the)X
+2042(previous)X
+2341(section)X
+2591(measures)X
+2913(performance)X
+3343(under)X
+3549(a)X
+3608(conventional)X
+4044(transac-)X
+555 4802(tion)N
+706(processing)X
+1076(workload.)X
+1446(Other)X
+1656(application)X
+2039(domains,)X
+2357(such)X
+2531(as)X
+2625(computer-aided)X
+3156(design,)X
+3412(have)X
+3591(substantially)X
+4022(different)X
+555 4892(access)N
+786(patterns.)X
+1105(In)X
+1197(order)X
+1392(to)X
+1479(measure)X
+1772(the)X
+1895(performance)X
+2327(of)X
+2418(LIBTP)X
+2664(under)X
+2871(workloads)X
+3229(of)X
+3320(this)X
+3459(type,)X
+3641(we)X
+3759(implemented)X
+4201(the)X
+555 4982(OO1)N
+731(benchmark)X
+1108(described)X
+1436(in)X
+1518([CATT91].)X
+755 5105(The)N
+908(database)X
+1213(models)X
+1472(a)X
+1535(set)X
+1651(of)X
+1745(electronics)X
+2120(components)X
+2534(with)X
+2703(connections)X
+3113(among)X
+3358(them.)X
+3585(One)X
+3746(table)X
+3929(stores)X
+4143(parts)X
+555 5195(and)N
+696(another)X
+962(stores)X
+1174(connections.)X
+1622(There)X
+1835(are)X
+1959(three)X
+2145(connections)X
+2552(originating)X
+2927(at)X
+3009(any)X
+3149(given)X
+3351(part.)X
+3540(Ninety)X
+3782(percent)X
+4043(of)X
+4134(these)X
+555 5285(connections)N
+960(are)X
+1081(to)X
+1165(nearby)X
+1406(parts)X
+1584(\(those)X
+1802(with)X
+1966(nearby)X
+2 f
+2207(ids)X
+1 f
+2300(\))X
+2348(to)X
+2431(model)X
+2652(the)X
+2771(spatial)X
+3001(locality)X
+3262(often)X
+3448(exhibited)X
+3767(in)X
+3850(CAD)X
+4040(applica-)X
+555 5375(tions.)N
+779(Ten)X
+933(percent)X
+1198(of)X
+1293(the)X
+1419(connections)X
+1830(are)X
+1957(randomly)X
+2292(distributed)X
+2662(among)X
+2908(all)X
+3016(other)X
+3209(parts)X
+3393(in)X
+3483(the)X
+3609(database.)X
+3954(Every)X
+4174(part)X
+555 5465(appears)N
+829(exactly)X
+1089(three)X
+1278(times)X
+1479(in)X
+1569(the)X
+2 f
+1695(from)X
+1 f
+1874(\256eld)X
+2043(of)X
+2137(a)X
+2200(connection)X
+2579(record,)X
+2832(and)X
+2975(zero)X
+3141(or)X
+3235(more)X
+3427(times)X
+3627(in)X
+3716(the)X
+2 f
+3841(to)X
+1 f
+3930(\256eld.)X
+4139(Parts)X
+555 5555(have)N
+2 f
+727(x)X
+1 f
+783(and)X
+2 f
+919(y)X
+1 f
+975(locations)X
+1284(set)X
+1393(randomly)X
+1720(in)X
+1802(an)X
+1898(appropriate)X
+2284(range.)X
+
+14 p
+%%Page: 14 14
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+755 630(The)N
+900(intent)X
+1102(of)X
+1189(OO1)X
+1365(is)X
+1438(to)X
+1520(measure)X
+1808(the)X
+1926(overall)X
+2169(cost)X
+2318(of)X
+2405(a)X
+2461(query)X
+2664(mix)X
+2808(characteristic)X
+3257(of)X
+3344(engineering)X
+3743(database)X
+4040(applica-)X
+555 720(tions.)N
+770(There)X
+978(are)X
+1097(three)X
+1278(tests:)X
+10 f
+635 843(g)N
+2 f
+755(Lookup)X
+1 f
+1022(generates)X
+1353(1,000)X
+1560(random)X
+1832(part)X
+2 f
+1984(ids)X
+1 f
+2077(,)X
+2124(fetches)X
+2378(the)X
+2502(corresponding)X
+2987(parts)X
+3169(from)X
+3351(the)X
+3475(database,)X
+3798(and)X
+3940(calls)X
+4113(a)X
+4175(null)X
+755 933(procedure)N
+1097(in)X
+1179(the)X
+1297(host)X
+1450(programming)X
+1906(language)X
+2216(with)X
+2378(the)X
+2496(parts')X
+2 f
+2699(x)X
+1 f
+2755(and)X
+2 f
+2891(y)X
+1 f
+2947(positions.)X
+10 f
+635 1056(g)N
+2 f
+755(Traverse)X
+1 f
+1067(retrieves)X
+1371(a)X
+1434(random)X
+1706(part)X
+1858(from)X
+2041(the)X
+2166(database)X
+2470(and)X
+2613(follows)X
+2880(connections)X
+3290(from)X
+3473(it)X
+3544(to)X
+3632(other)X
+3823(parts.)X
+4045(Each)X
+4232(of)X
+755 1146(those)N
+947(parts)X
+1126(is)X
+1202(retrieved,)X
+1531(and)X
+1670(all)X
+1773(connections)X
+2179(from)X
+2358(it)X
+2424(followed.)X
+2771(This)X
+2935(procedure)X
+3279(is)X
+3354(repeated)X
+3649(depth-\256rst)X
+4000(for)X
+4116(seven)X
+755 1236(hops)N
+930(from)X
+1110(the)X
+1232(original)X
+1505(part,)X
+1674(for)X
+1792(a)X
+1852(total)X
+2018(of)X
+2109(3280)X
+2293(parts.)X
+2513(Backward)X
+2862(traversal)X
+3162(also)X
+3314(exists,)X
+3539(and)X
+3678(follows)X
+3941(all)X
+4044(connec-)X
+755 1326(tions)N
+930(into)X
+1074(a)X
+1130(given)X
+1328(part)X
+1473(to)X
+1555(their)X
+1722(origin.)X
+10 f
+635 1449(g)N
+2 f
+755(Insert)X
+1 f
+962(adds)X
+1129(100)X
+1269(new)X
+1423(parts)X
+1599(and)X
+1735(their)X
+1902(connections.)X
+755 1572(The)N
+913(benchmark)X
+1303(is)X
+1389(single-user,)X
+1794(but)X
+1929(multi-user)X
+2291(access)X
+2530(controls)X
+2821(\(locking)X
+3120(and)X
+3268(transaction)X
+3652(protection\))X
+4036(must)X
+4223(be)X
+555 1662(enforced.)N
+898(It)X
+968(is)X
+1042(designed)X
+1348(to)X
+1431(be)X
+1528(run)X
+1656(on)X
+1757(a)X
+1814(database)X
+2112(with)X
+2275(20,000)X
+2516(parts,)X
+2713(and)X
+2850(on)X
+2951(one)X
+3087(with)X
+3249(200,000)X
+3529(parts.)X
+3745(Because)X
+4033(we)X
+4147(have)X
+555 1752(insuf\256cient)N
+935(disk)X
+1088(space)X
+1287(for)X
+1401(the)X
+1519(larger)X
+1727(database,)X
+2044(we)X
+2158(report)X
+2370(results)X
+2599(only)X
+2761(for)X
+2875(the)X
+2993(20,000)X
+3233(part)X
+3378(database.)X
+3 f
+555 1938(5.2.1.)N
+775(Implementation)X
+1 f
+755 2061(The)N
+920(LIBTP)X
+1182(implementation)X
+1724(of)X
+1831(OO1)X
+2027(uses)X
+2205(the)X
+2342(TCL)X
+2532([OUST90])X
+2914(interface)X
+3235(described)X
+3582(earlier.)X
+3867(The)X
+4031(backend)X
+555 2151(accepts)N
+813(commands)X
+1181(over)X
+1345(an)X
+1442(IP)X
+1534(socket)X
+1760(and)X
+1897(performs)X
+2208(the)X
+2327(requested)X
+2656(database)X
+2954(actions.)X
+3242(The)X
+3387(frontend)X
+3679(opens)X
+3886(and)X
+4022(executes)X
+555 2241(a)N
+618(TCL)X
+796(script.)X
+1041(This)X
+1210(script)X
+1415(contains)X
+1709(database)X
+2013(accesses)X
+2313(interleaved)X
+2697(with)X
+2866(ordinary)X
+3165(program)X
+3463(control)X
+3716(statements.)X
+4120(Data-)X
+555 2331(base)N
+718(commands)X
+1085(are)X
+1204(submitted)X
+1539(to)X
+1621(the)X
+1739(backend)X
+2027(and)X
+2163(results)X
+2392(are)X
+2511(bound)X
+2731(to)X
+2813(program)X
+3105(variables.)X
+755 2454(The)N
+903(parts)X
+1082(table)X
+1261(was)X
+1409(stored)X
+1628(as)X
+1718(a)X
+1776(B-tree)X
+1999(indexed)X
+2275(by)X
+2 f
+2377(id)X
+1 f
+2439(.)X
+2501(The)X
+2648(connection)X
+3022(table)X
+3200(was)X
+3347(stored)X
+3565(as)X
+3654(a)X
+3712(set)X
+3823(of)X
+3912(\256xed-length)X
+555 2544(records)N
+824(using)X
+1029(the)X
+1159(4.4BSD)X
+1446(recno)X
+1657(access)X
+1895(method.)X
+2207(In)X
+2306(addition,)X
+2620(two)X
+2771(B-tree)X
+3003(indices)X
+3261(were)X
+3449(maintained)X
+3836(on)X
+3947(connection)X
+555 2634(table)N
+732(entries.)X
+1007(One)X
+1162(index)X
+1360(mapped)X
+1634(the)X
+2 f
+1752(from)X
+1 f
+1923(\256eld)X
+2085(to)X
+2167(a)X
+2223(connection)X
+2595(record)X
+2821(number,)X
+3106(and)X
+3242(the)X
+3360(other)X
+3545(mapped)X
+3819(the)X
+2 f
+3937(to)X
+1 f
+4019(\256eld)X
+4181(to)X
+4263(a)X
+555 2724(connection)N
+932(record)X
+1163(number.)X
+1473(These)X
+1690(indices)X
+1941(support)X
+2205(fast)X
+2345(lookups)X
+2622(on)X
+2726(connections)X
+3133(in)X
+3219(both)X
+3385(directions.)X
+3765(For)X
+3900(the)X
+4022(traversal)X
+555 2814(tests,)N
+743(the)X
+867(frontend)X
+1165(does)X
+1338(an)X
+1439(index)X
+1642(lookup)X
+1889(to)X
+1976(discover)X
+2273(the)X
+2396(connected)X
+2747(part's)X
+2 f
+2955(id)X
+1 f
+3017(,)X
+3062(and)X
+3203(then)X
+3366(does)X
+3538(another)X
+3804(lookup)X
+4051(to)X
+4138(fetch)X
+555 2904(the)N
+673(part)X
+818(itself.)X
+3 f
+555 3090(5.2.2.)N
+775(Performance)X
+1242(Measurements)X
+1766(for)X
+1889(OO1)X
+1 f
+755 3213(We)N
+888(compare)X
+1186(LIBTP's)X
+1487(OO1)X
+1664(performance)X
+2092(to)X
+2174(that)X
+2314(reported)X
+2602(in)X
+2684([CATT91].)X
+3087(Those)X
+3303(results)X
+3532(were)X
+3709(collected)X
+4019(on)X
+4119(a)X
+4175(Sun)X
+555 3303(3/280)N
+759(\(25)X
+888(MHz)X
+1075(MC68020\))X
+1448(with)X
+1612(16)X
+1714(MBytes)X
+1989(of)X
+2078(memory)X
+2367(and)X
+2505(two)X
+2647(Hitachi)X
+2904(892MByte)X
+3267(disks)X
+3452(\(15)X
+3580(ms)X
+3694(average)X
+3966(seek)X
+4130(time\))X
+555 3393(behind)N
+793(an)X
+889(SMD-4)X
+1149(controller.)X
+1521(Frontends)X
+1861(ran)X
+1984(on)X
+2084(an)X
+2180(8MByte)X
+2462(Sun)X
+2606(3/260.)X
+755 3516(In)N
+844(order)X
+1036(to)X
+1120(measure)X
+1410(performance)X
+1839(on)X
+1941(a)X
+1999(machine)X
+2293(of)X
+2382(roughly)X
+2653(equivalent)X
+3009(processor)X
+3339(power,)X
+3582(we)X
+3698(ran)X
+3822(one)X
+3959(set)X
+4069(of)X
+4157(tests)X
+555 3606(on)N
+666(a)X
+733(standalone)X
+1107(MC68030-based)X
+1671(HP300)X
+1923(\(33MHz)X
+2225(MC68030\).)X
+2646(The)X
+2801(database)X
+3108(was)X
+3263(stored)X
+3489(on)X
+3599(a)X
+3665(300MByte)X
+4037(HP7959)X
+555 3696(SCSI)N
+744(disk)X
+898(\(17)X
+1026(ms)X
+1139(average)X
+1410(seek)X
+1573(time\).)X
+1802(Since)X
+2000(this)X
+2135(machine)X
+2427(is)X
+2500(not)X
+2622(connected)X
+2968(to)X
+3050(a)X
+3106(network,)X
+3409(we)X
+3523(ran)X
+3646(local)X
+3822(tests)X
+3984(where)X
+4201(the)X
+555 3786(frontend)N
+855(and)X
+999(backend)X
+1295(run)X
+1430(on)X
+1538(the)X
+1664(same)X
+1856(machine.)X
+2195(We)X
+2334(compare)X
+2638(these)X
+2830(measurements)X
+3316(with)X
+3485(Cattell's)X
+3783(local)X
+3966(Sun)X
+4117(3/280)X
+555 3876(numbers.)N
+755 3999(Because)N
+1051(the)X
+1177(benchmark)X
+1562(requires)X
+1849(remote)X
+2100(access,)X
+2354(we)X
+2476(ran)X
+2607(another)X
+2876(set)X
+2993(of)X
+3088(tests)X
+3258(on)X
+3365(a)X
+3428(DECstation)X
+3828(5000/200)X
+4157(with)X
+555 4089(32M)N
+732(of)X
+825(memory)X
+1118(running)X
+1393(Ultrix)X
+1610(V4.0)X
+1794(and)X
+1936(a)X
+1998(DEC)X
+2184(1GByte)X
+2459(RZ57)X
+2666(SCSI)X
+2859(disk.)X
+3057(We)X
+3194(compare)X
+3496(the)X
+3619(local)X
+3800(performance)X
+4232(of)X
+555 4179(OO1)N
+734(on)X
+837(the)X
+958(DECstation)X
+1354(to)X
+1439(its)X
+1536(remote)X
+1781(performance.)X
+2250(For)X
+2383(the)X
+2503(remote)X
+2748(case,)X
+2929(we)X
+3045(ran)X
+3170(the)X
+3290(frontend)X
+3584(on)X
+3686(a)X
+3744(DECstation)X
+4139(3100)X
+555 4269(with)N
+717(16)X
+817(MBytes)X
+1090(of)X
+1177(main)X
+1357(memory.)X
+755 4392(The)N
+900(databases)X
+1228(tested)X
+1435(in)X
+1517([CATT91])X
+1880(are)X
+10 f
+635 4515(g)N
+1 f
+755(INDEX,)X
+1045(a)X
+1101(highly-optimized)X
+1672(access)X
+1898(method)X
+2158(package)X
+2442(developed)X
+2792(at)X
+2870(Sun)X
+3014(Microsystems.)X
+10 f
+635 4638(g)N
+1 f
+755(OODBMS,)X
+1137(a)X
+1193(beta)X
+1347(release)X
+1591(of)X
+1678(a)X
+1734(commercial)X
+2133(object-oriented)X
+2639(database)X
+2936(management)X
+3366(system.)X
+10 f
+635 4761(g)N
+1 f
+755(RDBMS,)X
+1076(a)X
+1133(UNIX-based)X
+1565(commercial)X
+1965(relational)X
+2289(data)X
+2444(manager)X
+2742(at)X
+2821(production)X
+3189(release.)X
+3474(The)X
+3620(OO1)X
+3797(implementation)X
+755 4851(used)N
+922(embedded)X
+1272(SQL)X
+1443(in)X
+1525(C.)X
+1638(Stored)X
+1867(procedures)X
+2240(were)X
+2417(de\256ned)X
+2673(to)X
+2755(reduce)X
+2990(client-server)X
+3412(traf\256c.)X
+755 4974(Table)N
+974(two)X
+1130(shows)X
+1366(the)X
+1500(measurements)X
+1995(from)X
+2187([CATT91])X
+2566(and)X
+2718(LIBTP)X
+2976(for)X
+3106(a)X
+3178(local)X
+3370(test)X
+3517(on)X
+3632(the)X
+3765(MC680x0-based)X
+555 5064(hardware.)N
+915(All)X
+1037(caches)X
+1272(are)X
+1391(cleared)X
+1644(before)X
+1870(each)X
+2038(test.)X
+2209(All)X
+2331(times)X
+2524(are)X
+2643(in)X
+2725(seconds.)X
+755 5187(Table)N
+960(two)X
+1102(shows)X
+1324(that)X
+1466(LIBTP)X
+1710(outperforms)X
+2123(the)X
+2242(commercial)X
+2642(relational)X
+2966(system,)X
+3229(but)X
+3352(is)X
+3426(slower)X
+3661(than)X
+3820(OODBMS)X
+4183(and)X
+555 5277(INDEX.)N
+872(Since)X
+1077(the)X
+1202(caches)X
+1444(were)X
+1628(cleared)X
+1888(at)X
+1973(the)X
+2098(start)X
+2263(of)X
+2356(each)X
+2530(test,)X
+2687(disk)X
+2846(throughput)X
+3223(is)X
+3302(critical)X
+3551(in)X
+3639(this)X
+3780(test.)X
+3957(The)X
+4108(single)X
+555 5367(SCSI)N
+749(HP)X
+877(drive)X
+1068(used)X
+1241(by)X
+1347(LIBTP)X
+1595(is)X
+1674(approximately)X
+2163(13%)X
+2336(slower)X
+2576(than)X
+2739(the)X
+2862(disks)X
+3051(used)X
+3223(in)X
+3310([CATT91])X
+3678(which)X
+3899(accounts)X
+4205(for)X
+555 5457(part)N
+700(of)X
+787(the)X
+905(difference.)X
+755 5580(OODBMS)N
+1118(and)X
+1255(INDEX)X
+1525(outperform)X
+1906(LIBTP)X
+2148(most)X
+2323(dramatically)X
+2744(on)X
+2844(traversal.)X
+3181(This)X
+3343(is)X
+3416(because)X
+3691(we)X
+3805(use)X
+3932(index)X
+4130(look-)X
+555 5670(ups)N
+689(to)X
+774(\256nd)X
+921(connections,)X
+1347(whereas)X
+1634(the)X
+1755(other)X
+1942(two)X
+2084(systems)X
+2359(use)X
+2488(a)X
+2546(link)X
+2692(access)X
+2920(method.)X
+3222(The)X
+3369(index)X
+3569(requires)X
+3850(us)X
+3943(to)X
+4027(examine)X
+
+15 p
+%%Page: 15 15
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+10 f
+555 679(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+2 f
+606 769(Measure)N
+1 f
+1019(INDEX)X
+1389(OODBMS)X
+1851(RDBMS)X
+2250(LIBTP)X
+10 f
+555 771(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+555 787(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+1 f
+595 869(Lookup)N
+1114(5.4)X
+1490(12.9)X
+1950(27)X
+2291(27.2)X
+595 959(Traversal)N
+1074(13)X
+1530(9.8)X
+1950(90)X
+2291(47.3)X
+595 1049(Insert)N
+1114(7.4)X
+1530(1.5)X
+1950(22)X
+2331(9.7)X
+10 f
+555 1059(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+555(c)X
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+959 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+1329 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+1791 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+2190 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+2512 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+2618 679(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+2829 769(Measure)N
+3401(Cache)X
+3726(Local)X
+4028(Remote)X
+1 f
+10 f
+2618 771(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2618 787(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 869(Lookup)N
+3401(cold)X
+3747(15.7)X
+4078(20.6)X
+3401 959(warm)N
+3787(7.8)X
+4078(12.4)X
+10 f
+2618 969(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 1059(Forward)N
+2950(traversal)X
+3401(cold)X
+3747(28.4)X
+4078(52.6)X
+3401 1149(warm)N
+3747(23.5)X
+4078(47.4)X
+10 f
+2618 1159(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 1249(Backward)N
+3004(traversal)X
+3401(cold)X
+3747(24.2)X
+4078(47.4)X
+3401 1339(warm)N
+3747(24.3)X
+4078(47.6)X
+10 f
+2618 1349(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 1439(Insert)N
+3401(cold)X
+3787(7.5)X
+4078(10.3)X
+3401 1529(warm)N
+3787(6.7)X
+4078(10.9)X
+10 f
+2618 1539(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2618(c)X
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3341 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3666 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3968 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+4309 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3 f
+587 1785(Table)N
+823(2:)X
+931(Local)X
+1163(MC680x0)X
+1538(Performance)X
+2026(of)X
+2133(Several)X
+587 1875(Systems)N
+883(on)X
+987(OO1.)X
+2667 1785(Table)N
+2909(3:)X
+3023(Local)X
+3260(vs.)X
+3397(Remote)X
+3707(Performance)X
+4200(of)X
+2667 1875(LIBTP)N
+2926(on)X
+3030(OO1.)X
+1 f
+10 f
+555 1998(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 f
+555 2274(two)N
+696(disk)X
+850(pages,)X
+1074(but)X
+1197(the)X
+1316(links)X
+1492(require)X
+1741(only)X
+1904(one,)X
+2061(regardless)X
+2408(of)X
+2496(database)X
+2794(size.)X
+2980(Cattell)X
+3214(reports)X
+3458(that)X
+3599(lookups)X
+3873(using)X
+4067(B-trees)X
+555 2364(instead)N
+808(of)X
+901(links)X
+1082(makes)X
+1313(traversal)X
+1616(take)X
+1776(twice)X
+1976(as)X
+2069(long)X
+2237(in)X
+2325(INDEX.)X
+2641(Adding)X
+2907(a)X
+2969(link)X
+3119(access)X
+3351(method)X
+3617(to)X
+3 f
+3704(db)X
+1 f
+3792(\(3\))X
+3911(or)X
+4003(using)X
+4201(the)X
+555 2454(existing)N
+828(hash)X
+995(method)X
+1255(would)X
+1475(apparently)X
+1834(be)X
+1930(a)X
+1986(good)X
+2166(idea.)X
+755 2577(Both)N
+936(OODBMS)X
+1304(and)X
+1446(INDEX)X
+1722(issue)X
+1908 0.1944(coarser-granularity)AX
+2545(locks)X
+2739(than)X
+2902(LIBTP.)X
+3189(This)X
+3356(limits)X
+3562(concurrency)X
+3985(for)X
+4104(multi-)X
+555 2667(user)N
+711(applications,)X
+1140(but)X
+1264(helps)X
+1455(single-user)X
+1829(applications.)X
+2278(In)X
+2367(addition,)X
+2671(the)X
+2791(fact)X
+2934(that)X
+3076(LIBTP)X
+3319(releases)X
+3595(B-tree)X
+3817(locks)X
+4007(early)X
+4189(is)X
+4263(a)X
+555 2757(drawback)N
+896(in)X
+986(OO1.)X
+1210(Since)X
+1416(there)X
+1605(is)X
+1686(no)X
+1793(concurrency)X
+2218(in)X
+2307(the)X
+2432(benchmark,)X
+2836(high-concurrency)X
+3430(strategies)X
+3760(only)X
+3929(show)X
+4125(up)X
+4232(as)X
+555 2847(increased)N
+882(locking)X
+1145(overhead.)X
+1503(Finally,)X
+1772(the)X
+1892(architecture)X
+2294(of)X
+2383(the)X
+2503(LIBTP)X
+2747(implementation)X
+3271(was)X
+3418(substantially)X
+3844(different)X
+4143(from)X
+555 2937(that)N
+702(of)X
+796(either)X
+1006(OODBMS)X
+1375(or)X
+1469(INDEX.)X
+1786(Both)X
+1968(of)X
+2062(those)X
+2258(systems)X
+2538(do)X
+2645(the)X
+2770(searches)X
+3070(in)X
+3159(the)X
+3284(user's)X
+3503(address)X
+3771(space,)X
+3997(and)X
+4139(issue)X
+555 3027(requests)N
+844(for)X
+964(pages)X
+1173(to)X
+1260(the)X
+1383(server)X
+1605(process.)X
+1911(Pages)X
+2123(are)X
+2247(cached)X
+2496(in)X
+2583(the)X
+2706(client,)X
+2929(and)X
+3070(many)X
+3273(queries)X
+3530(can)X
+3667(be)X
+3768(satis\256ed)X
+4055(without)X
+555 3117(contacting)N
+910(the)X
+1029(server)X
+1247(at)X
+1326(all.)X
+1467(LIBTP)X
+1710(submits)X
+1979(all)X
+2080(the)X
+2199(queries)X
+2452(to)X
+2535(the)X
+2653(server)X
+2870(process,)X
+3151(and)X
+3287(receives)X
+3571(database)X
+3868(records)X
+4125(back;)X
+555 3207(it)N
+619(does)X
+786(no)X
+886(client)X
+1084(caching.)X
+755 3330(The)N
+911(RDBMS)X
+1221(architecture)X
+1632(is)X
+1716(much)X
+1925(closer)X
+2148(to)X
+2241(that)X
+2392(of)X
+2490(LIBTP.)X
+2783(A)X
+2872(server)X
+3100(process)X
+3372(receives)X
+3667(queries)X
+3930(and)X
+4076(returns)X
+555 3420(results)N
+786(to)X
+870(a)X
+928(client.)X
+1168(The)X
+1315(timing)X
+1545(results)X
+1776(in)X
+1860(table)X
+2038(two)X
+2180(clearly)X
+2421(show)X
+2612(that)X
+2754(the)X
+2874(conventional)X
+3309(database)X
+3607(client/server)X
+4025(model)X
+4246(is)X
+555 3510(expensive.)N
+941(LIBTP)X
+1188(outperforms)X
+1605(the)X
+1728(RDBMS)X
+2032(on)X
+2136(traversal)X
+2437(and)X
+2577(insertion.)X
+2921(We)X
+3057(speculate)X
+3380(that)X
+3524(this)X
+3663(is)X
+3740(due)X
+3880(in)X
+3966(part)X
+4115(to)X
+4201(the)X
+555 3600(overhead)N
+870(of)X
+957(query)X
+1160(parsing,)X
+1436(optimization,)X
+1880(and)X
+2016(repeated)X
+2309(interpretation)X
+2761(of)X
+2848(the)X
+2966(plan)X
+3124(tree)X
+3265(in)X
+3347(the)X
+3465(RDBMS')X
+3791(query)X
+3994(executor.)X
+755 3723(Table)N
+962(three)X
+1147(shows)X
+1371(the)X
+1492(differences)X
+1873(between)X
+2164(local)X
+2343(and)X
+2482(remote)X
+2728(execution)X
+3063(of)X
+3153(LIBTP's)X
+3456(OO1)X
+3635(implementation)X
+4160(on)X
+4263(a)X
+555 3813(DECstation.)N
+989(We)X
+1122(measured)X
+1451(performance)X
+1879(with)X
+2042(a)X
+2099(populated)X
+2436(\(warm\))X
+2694(cache)X
+2899(and)X
+3036(an)X
+3133(empty)X
+3354(\(cold\))X
+3567(cache.)X
+3812(Reported)X
+4126(times)X
+555 3903(are)N
+681(the)X
+806(means)X
+1037(of)X
+1130(twenty)X
+1374(tests,)X
+1562(and)X
+1704(are)X
+1829(in)X
+1917(seconds.)X
+2237(Standard)X
+2548(deviations)X
+2903(were)X
+3086(within)X
+3316(seven)X
+3525(percent)X
+3788(of)X
+3881(the)X
+4005(mean)X
+4205(for)X
+555 3993(remote,)N
+818(and)X
+954(two)X
+1094(percent)X
+1351(of)X
+1438(the)X
+1556(mean)X
+1750(for)X
+1864(local.)X
+755 4116(The)N
+914(20ms)X
+1121(overhead)X
+1450(of)X
+1551(TCP/IP)X
+1824(on)X
+1938(an)X
+2048(Ethernet)X
+2354(entirely)X
+2633(accounts)X
+2948(for)X
+3076(the)X
+3207(difference)X
+3567(in)X
+3662(speed.)X
+3918(The)X
+4076(remote)X
+555 4206(traversal)N
+857(times)X
+1055(are)X
+1179(nearly)X
+1405(double)X
+1648(the)X
+1771(local)X
+1952(times)X
+2150(because)X
+2430(we)X
+2549(do)X
+2653(index)X
+2855(lookups)X
+3132(and)X
+3272(part)X
+3421(fetches)X
+3673(in)X
+3759(separate)X
+4047(queries.)X
+555 4296(It)N
+629(would)X
+854(make)X
+1053(sense)X
+1252(to)X
+1339(do)X
+1444(indexed)X
+1723(searches)X
+2021(on)X
+2126(the)X
+2248(server,)X
+2489(but)X
+2615(we)X
+2733(were)X
+2914(unwilling)X
+3244(to)X
+3330(hard-code)X
+3676(knowledge)X
+4052(of)X
+4143(OO1)X
+555 4386(indices)N
+803(into)X
+948(our)X
+1075(LIBTP)X
+1317(TCL)X
+1488(server.)X
+1745(Cold)X
+1920(and)X
+2056(warm)X
+2259(insertion)X
+2559(times)X
+2752(are)X
+2871(identical)X
+3167(since)X
+3352(insertions)X
+3683(do)X
+3783(not)X
+3905(bene\256t)X
+4143(from)X
+555 4476(caching.)N
+755 4599(One)N
+915(interesting)X
+1279(difference)X
+1632(shown)X
+1867(by)X
+1973(table)X
+2155(three)X
+2342(is)X
+2421(the)X
+2545(cost)X
+2700(of)X
+2793(forward)X
+3074(versus)X
+3305(backward)X
+3644(traversal.)X
+3987(When)X
+4205(we)X
+555 4689(built)N
+725(the)X
+847(database,)X
+1168(we)X
+1285(inserted)X
+1562(parts)X
+1741(in)X
+1826(part)X
+2 f
+1974(id)X
+1 f
+2059(order.)X
+2292(We)X
+2427(built)X
+2596(the)X
+2717(indices)X
+2967(at)X
+3048(the)X
+3169(same)X
+3357(time.)X
+3562(Therefore,)X
+3923(the)X
+4044(forward)X
+555 4779(index)N
+757(had)X
+897(keys)X
+1068(inserted)X
+1346(in)X
+1432(order,)X
+1646(while)X
+1848(the)X
+1970(backward)X
+2307(index)X
+2509(had)X
+2649(keys)X
+2820(inserted)X
+3098(more)X
+3286(randomly.)X
+3656(In-order)X
+3943(insertion)X
+4246(is)X
+555 4885(pessimal)N
+858(for)X
+975(B-tree)X
+1199(indices,)X
+1469(so)X
+1563(the)X
+1684(forward)X
+1962(index)X
+2163(is)X
+2239(much)X
+2440(larger)X
+2651(than)X
+2812(the)X
+2933(backward)X
+3269(one)X
+7 s
+3385 4853(5)N
+10 s
+4885(.)Y
+3476(This)X
+3640(larger)X
+3850(size)X
+3997(shows)X
+4219(up)X
+555 4975(as)N
+642(extra)X
+823(disk)X
+976(reads)X
+1166(in)X
+1248(the)X
+1366(cold)X
+1524(benchmark.)X
+3 f
+555 5161(6.)N
+655(Conclusions)X
+1 f
+755 5284(LIBTP)N
+1006(provides)X
+1311(the)X
+1438(basic)X
+1632(building)X
+1927(blocks)X
+2165(to)X
+2256(support)X
+2525(transaction)X
+2906(protection.)X
+3300(In)X
+3396(comparison)X
+3799(with)X
+3970(traditional)X
+555 5374(Unix)N
+746(libraries)X
+1040(and)X
+1187(commercial)X
+1597(systems,)X
+1900(it)X
+1974(offers)X
+2192(a)X
+2258(variety)X
+2511(of)X
+2608(tradeoffs.)X
+2964(Using)X
+3185(complete)X
+3509(transaction)X
+3891(protection)X
+4246(is)X
+555 5464(more)N
+747(complicated)X
+1166(than)X
+1331(simply)X
+1575(adding)X
+3 f
+1820(fsync)X
+1 f
+1998(\(2\))X
+2119(and)X
+3 f
+2262(\257ock)X
+1 f
+2426(\(2\))X
+2547(calls)X
+2721(to)X
+2810(code,)X
+3008(but)X
+3136(it)X
+3206(is)X
+3285(faster)X
+3490(in)X
+3578(some)X
+3773(cases)X
+3969(and)X
+4111(offers)X
+8 s
+10 f
+555 5536(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5614(5)N
+8 s
+763 5639(The)N
+878(next)X
+1004(release)X
+1196(of)X
+1265(the)X
+1359(4.4BSD)X
+1580(access)X
+1758(method)X
+1966(will)X
+2082(automatically)X
+2446(detect)X
+2614(and)X
+2722(compensate)X
+3039(for)X
+3129(in-order)X
+3350(insertion,)X
+3606(eliminating)X
+3914(this)X
+4023(problem.)X
+
+16 p
+%%Page: 16 16
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(stricter)N
+801(guarantees)X
+1168(\(atomicity,)X
+1540(consistency,)X
+1957(isolation,)X
+2275(and)X
+2414(durability\).)X
+2815(If)X
+2892(the)X
+3013(data)X
+3170(to)X
+3255(be)X
+3354(protected)X
+3676(are)X
+3798(already)X
+4058(format-)X
+555 720(ted)N
+675(\()X
+2 f
+702(i.e.)X
+1 f
+821(use)X
+949(one)X
+1086(of)X
+1174(the)X
+1293(database)X
+1591(access)X
+1818(methods\),)X
+2157(then)X
+2316(adding)X
+2555(transaction)X
+2928(protection)X
+3274(requires)X
+3554(no)X
+3655(additional)X
+3996(complex-)X
+555 810(ity,)N
+679(but)X
+801(incurs)X
+1017(a)X
+1073(performance)X
+1500(penalty)X
+1756(of)X
+1843(approximately)X
+2326(15%.)X
+755 933(In)N
+844(comparison)X
+1240(with)X
+1404(commercial)X
+1805(database)X
+2104(systems,)X
+2399(the)X
+2519(tradeoffs)X
+2827(are)X
+2948(more)X
+3135(complex.)X
+3473(LIBTP)X
+3717(does)X
+3886(not)X
+4009(currently)X
+555 1023(support)N
+825(a)X
+891(standard)X
+1193(query)X
+1406(language.)X
+1766(The)X
+1921(TCL-based)X
+2312(server)X
+2539(process)X
+2810(allows)X
+3049(a)X
+3115(certain)X
+3364(ease)X
+3533(of)X
+3630(use)X
+3767(which)X
+3993(would)X
+4223(be)X
+555 1113(enhanced)N
+882(with)X
+1047(a)X
+1106(more)X
+1294(user-friendly)X
+1732(interface)X
+2037(\()X
+2 f
+2064(e.g.)X
+1 f
+2203(a)X
+2261(windows)X
+2572(based)X
+2777(query-by-form)X
+3272(application\),)X
+3697(for)X
+3813(which)X
+4031(we)X
+4147(have)X
+555 1203(a)N
+620(working)X
+916(prototype.)X
+1292(When)X
+1513(accesses)X
+1815(do)X
+1924(not)X
+2055(require)X
+2312(sophisticated)X
+2758(query)X
+2969(processing,)X
+3360(the)X
+3486(TCL)X
+3665(interface)X
+3975(is)X
+4056(an)X
+4160(ade-)X
+555 1293(quate)N
+756(solution.)X
+1080(What)X
+1281(LIBTP)X
+1529(fails)X
+1693(to)X
+1781(provide)X
+2052(in)X
+2140(functionality,)X
+2595(it)X
+2665(makes)X
+2896(up)X
+3002(for)X
+3122(in)X
+3210(performance)X
+3643(and)X
+3785(\257exibility.)X
+4161(Any)X
+555 1383(application)N
+931(may)X
+1089(make)X
+1283(use)X
+1410(of)X
+1497(its)X
+1592(record)X
+1818(interface)X
+2120(or)X
+2207(the)X
+2325(more)X
+2510(primitive)X
+2823(log,)X
+2965(lock,)X
+3143(and)X
+3279(buffer)X
+3496(calls.)X
+755 1506(Future)N
+987(work)X
+1175(will)X
+1322(focus)X
+1519(on)X
+1621(overcoming)X
+2026(some)X
+2217(of)X
+2306(the)X
+2426(areas)X
+2614(in)X
+2698(which)X
+2916(LIBTP)X
+3160(is)X
+3235(currently)X
+3547(de\256cient)X
+3845(and)X
+3983(extending)X
+555 1596(its)N
+652(transaction)X
+1026(model.)X
+1288(The)X
+1435(addition)X
+1719(of)X
+1808(an)X
+1905(SQL)X
+2077(parser)X
+2295(and)X
+2432(forms)X
+2640(front)X
+2817(end)X
+2954(will)X
+3099(improve)X
+3387(the)X
+3506(system's)X
+3807(ease)X
+3967(of)X
+4055(use)X
+4183(and)X
+555 1686(make)N
+750(it)X
+815(more)X
+1001(competitive)X
+1400(with)X
+1563(commercial)X
+1963(systems.)X
+2277(In)X
+2365(the)X
+2484(long)X
+2647(term,)X
+2835(we)X
+2950(would)X
+3170(like)X
+3310(to)X
+3392(add)X
+3528(generalized)X
+3919(hierarchical)X
+555 1776(locking,)N
+836(nested)X
+1062(transactions,)X
+1486(parallel)X
+1748(transactions,)X
+2171(passing)X
+2431(of)X
+2518(transactions)X
+2921(between)X
+3209(processes,)X
+3557(and)X
+3693(distributed)X
+4055(commit)X
+555 1866(handling.)N
+900(In)X
+992(the)X
+1115(short)X
+1300(term,)X
+1492(the)X
+1614(next)X
+1776(step)X
+1929(is)X
+2006(to)X
+2092(integrate)X
+2397(LIBTP)X
+2643(with)X
+2809(the)X
+2931(most)X
+3110(recent)X
+3331(release)X
+3579(of)X
+3670(the)X
+3792(database)X
+4093(access)X
+555 1956(routines)N
+833(and)X
+969(make)X
+1163(it)X
+1227(freely)X
+1435(available)X
+1745(via)X
+1863(anonymous)X
+2252(ftp.)X
+3 f
+555 2142(7.)N
+655(Acknowledgements)X
+1 f
+755 2265(We)N
+888(would)X
+1109(like)X
+1250(to)X
+1332(thank)X
+1530(John)X
+1701(Wilkes)X
+1948(and)X
+2084(Carl)X
+2242(Staelin)X
+2484(of)X
+2571(Hewlett-Packard)X
+3131(Laboratories)X
+3557(and)X
+3693(Jon)X
+3824(Krueger.)X
+4148(John)X
+555 2355(and)N
+694(Carl)X
+855(provided)X
+1162(us)X
+1255(with)X
+1419(an)X
+1517(extra)X
+1700(disk)X
+1855(for)X
+1971(the)X
+2091(HP)X
+2215(testbed)X
+2464(less)X
+2606(than)X
+2766(24)X
+2868(hours)X
+3068(after)X
+3238(we)X
+3354(requested)X
+3684(it.)X
+3770(Jon)X
+3903(spent)X
+4094(count-)X
+555 2445(less)N
+699(hours)X
+901(helping)X
+1164(us)X
+1258(understand)X
+1633(the)X
+1754(intricacies)X
+2107(of)X
+2197(commercial)X
+2599(database)X
+2899(products)X
+3198(and)X
+3337(their)X
+3507(behavior)X
+3811(under)X
+4017(a)X
+4076(variety)X
+555 2535(of)N
+642(system)X
+884(con\256gurations.)X
+3 f
+555 2721(8.)N
+655(References)X
+1 f
+555 2901([ANDR89])N
+942(Andrade,)X
+1265(J.,)X
+1361(Carges,)X
+1629(M.,)X
+1765(Kovach,)X
+2060(K.,)X
+2183(``Building)X
+2541(an)X
+2642(On-Line)X
+2939(Transaction)X
+3343(Processing)X
+3715(System)X
+3975(On)X
+4098(UNIX)X
+727 2991(System)N
+982(V'',)X
+2 f
+1134(CommUNIXations)X
+1 f
+1725(,)X
+1765 0.2188(November/December)AX
+2477(1989.)X
+555 3171([BAY77])N
+878(Bayer,)X
+1110(R.,)X
+1223(Schkolnick,)X
+1623(M.,)X
+1754(``Concurrency)X
+2243(of)X
+2330(Operations)X
+2702(on)X
+2802(B-Trees'',)X
+2 f
+3155(Acta)X
+3322(Informatica)X
+1 f
+3700(,)X
+3740(1977.)X
+555 3351([BERN80])N
+936(Bernstein,)X
+1297(P.,)X
+1415(Goodman,)X
+1785(N.,)X
+1917(``Timestamp)X
+2365(Based)X
+2595(Algorithms)X
+2992(for)X
+3119(Concurrency)X
+3567(Control)X
+3844(in)X
+3939(Distributed)X
+727 3441(Database)N
+1042(Systems'',)X
+2 f
+1402(Proceedings)X
+1823(6th)X
+1945(International)X
+2387(Conference)X
+2777(on)X
+2877(Very)X
+3049(Large)X
+3260(Data)X
+3440(Bases)X
+1 f
+3627(,)X
+3667(October)X
+3946(1980.)X
+555 3621([BSD91])N
+864(DB\(3\),)X
+2 f
+1109(4.4BSD)X
+1376(Unix)X
+1552(Programmer's)X
+2044(Manual)X
+2313(Reference)X
+2655(Guide)X
+1 f
+2851(,)X
+2891(University)X
+3249(of)X
+3336(California,)X
+3701(Berkeley,)X
+4031(1991.)X
+555 3801([CATT91])N
+923(Cattell,)X
+1181(R.G.G.,)X
+1455(``An)X
+1632(Engineering)X
+2049(Database)X
+2369(Benchmark'',)X
+2 f
+2838(The)X
+2983(Benchmark)X
+3373(Handbook)X
+3731(for)X
+3848(Database)X
+4179(and)X
+727 3891(Transaction)N
+1133(Processing)X
+1509(Systems)X
+1 f
+1763(,)X
+1803(J.)X
+1874(Gray,)X
+2075(editor,)X
+2302(Morgan)X
+2576(Kaufman)X
+2895(1991.)X
+555 4071([CHEN91])N
+929(Cheng,)X
+1180(E.,)X
+1291(Chang,)X
+1542(E.,)X
+1653(Klein,)X
+1872(J.,)X
+1964(Lee,)X
+2126(D.,)X
+2245(Lu,)X
+2375(E.,)X
+2485(Lutgardo,)X
+2820(A.,)X
+2939(Obermarck,)X
+3342(R.,)X
+3456(``An)X
+3629(Open)X
+3824(and)X
+3961(Extensible)X
+727 4161(Event-Based)N
+1157(Transaction)X
+1556(Manager'',)X
+2 f
+1936(Proceedings)X
+2357(1991)X
+2537(Summer)X
+2820(Usenix)X
+1 f
+3043(,)X
+3083(Nashville,)X
+3430(TN,)X
+3577(June)X
+3744(1991.)X
+555 4341([CHOU85])N
+943(Chou,)X
+1163(H.,)X
+1288(DeWitt,)X
+1570(D.,)X
+1694(``An)X
+1872(Evaluation)X
+2245(of)X
+2338(Buffer)X
+2574(Management)X
+3019(Strategies)X
+3361(for)X
+3481(Relational)X
+3836(Database)X
+4157(Sys-)X
+727 4431(tems'',)N
+2 f
+972(Proceedings)X
+1393(of)X
+1475(the)X
+1593(11th)X
+1755(International)X
+2197(Conference)X
+2587(on)X
+2687(Very)X
+2859(Large)X
+3070(Databases)X
+1 f
+3408(,)X
+3448(1985.)X
+555 4611([DEWI84])N
+925(DeWitt,)X
+1207(D.,)X
+1331(Katz,)X
+1529(R.,)X
+1648(Olken,)X
+1890(F.,)X
+2000(Shapiro,)X
+2295(L.,)X
+2410(Stonebraker,)X
+2843(M.,)X
+2979(Wood,)X
+3220(D.,)X
+3343(``Implementation)X
+3929(Techniques)X
+727 4701(for)N
+841(Main)X
+1030(Memory)X
+1326(Database)X
+1641(Systems'',)X
+2 f
+2001(Proceedings)X
+2422(of)X
+2504(SIGMOD)X
+1 f
+2812(,)X
+2852(pp.)X
+2972(1-8,)X
+3119(June)X
+3286(1984.)X
+555 4881([GRAY76])N
+944(Gray,)X
+1153(J.,)X
+1252(Lorie,)X
+1474(R.,)X
+1595(Putzolu,)X
+1887(F.,)X
+1999(and)X
+2143(Traiger,)X
+2428(I.,)X
+2522(``Granularity)X
+2973(of)X
+3067(locks)X
+3263(and)X
+3406(degrees)X
+3679(of)X
+3773(consistency)X
+4174(in)X
+4263(a)X
+727 4971(large)N
+909(shared)X
+1140(data)X
+1295(base'',)X
+2 f
+1533(Modeling)X
+1861(in)X
+1944(Data)X
+2125(Base)X
+2301(Management)X
+2740(Systems)X
+1 f
+2994(,)X
+3034(Elsevier)X
+3317(North)X
+3524(Holland,)X
+3822(New)X
+3994(York,)X
+4199(pp.)X
+727 5061(365-394.)N
+555 5241([HAER83])N
+931(Haerder,)X
+1235(T.)X
+1348(Reuter,)X
+1606(A.)X
+1728(``Principles)X
+2126(of)X
+2217(Transaction-Oriented)X
+2928(Database)X
+3246(Recovery'',)X
+2 f
+3651(Computing)X
+4029(Surveys)X
+1 f
+4279(,)X
+727 5331(15\(4\);)N
+943(237-318,)X
+1250(1983.)X
+555 5511([KUNG81])N
+943(Kung,)X
+1162(H.)X
+1261(T.,)X
+1371(Richardson,)X
+1777(J.,)X
+1869(``On)X
+2042(Optimistic)X
+2400(Methods)X
+2701(for)X
+2816(Concurrency)X
+3252(Control'',)X
+2 f
+3591(ACM)X
+3781(Transactions)X
+4219(on)X
+727 5601(Database)N
+1054(Systems)X
+1 f
+1328(6\(2\);)X
+1504(213-226,)X
+1811(1981.)X
+
+17 p
+%%Page: 17 17
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+555 630([LEHM81])N
+939(Lehman,)X
+1245(P.,)X
+1352(Yao,)X
+1529(S.,)X
+1636(``Ef\256cient)X
+1989(Locking)X
+2279(for)X
+2396(Concurrent)X
+2780(Operations)X
+3155(on)X
+3258(B-trees'',)X
+2 f
+3587(ACM)X
+3779(Transactions)X
+4219(on)X
+727 720(Database)N
+1054(Systems)X
+1 f
+1308(,)X
+1348(6\(4\),)X
+1522(December)X
+1873(1981.)X
+555 900([MOHA91])N
+964(Mohan,)X
+1241(C.,)X
+1364(Pirahesh,)X
+1690(H.,)X
+1818(``ARIES-RRH:)X
+2366(Restricted)X
+2721(Repeating)X
+3076(of)X
+3173(History)X
+3442(in)X
+3533(the)X
+3660(ARIES)X
+3920(Transaction)X
+727 990(Recovery)N
+1055(Method'',)X
+2 f
+1398(Proceedings)X
+1819(7th)X
+1941(International)X
+2383(Conference)X
+2773(on)X
+2873(Data)X
+3053(Engineering)X
+1 f
+3449(,)X
+3489(Kobe,)X
+3703(Japan,)X
+3926(April)X
+4115(1991.)X
+555 1170([NODI90])N
+914(Nodine,)X
+1194(M.,)X
+1328(Zdonik,)X
+1602(S.,)X
+1709(``Cooperative)X
+2178(Transaction)X
+2580(Hierarchies:)X
+2996(A)X
+3077(Transaction)X
+3479(Model)X
+3711(to)X
+3796(Support)X
+4072(Design)X
+727 1260(Applications'',)N
+2 f
+1242(Proceedings)X
+1675(16th)X
+1849(International)X
+2303(Conference)X
+2704(on)X
+2815(Very)X
+2998(Large)X
+3220(Data)X
+3411(Bases)X
+1 f
+3598(,)X
+3649(Brisbane,)X
+3985(Australia,)X
+727 1350(August)N
+978(1990.)X
+555 1530([OUST90])N
+923(Ousterhout,)X
+1324(J.,)X
+1420(``Tcl:)X
+1648(An)X
+1771(Embeddable)X
+2197(Command)X
+2555(Language'',)X
+2 f
+2971(Proceedings)X
+3396(1990)X
+3580(Winter)X
+3822(Usenix)X
+1 f
+4045(,)X
+4089(Wash-)X
+727 1620(ington,)N
+971(D.C.,)X
+1162(January)X
+1432(1990.)X
+555 1800([POSIX91])N
+955(``Unapproved)X
+1441(Draft)X
+1645(for)X
+1773(Realtime)X
+2096(Extension)X
+2450(for)X
+2578(Portable)X
+2879(Operating)X
+3234(Systems'',)X
+3608(Draft)X
+3812(11,)X
+3946(October)X
+4239(7,)X
+727 1890(1991,)N
+927(IEEE)X
+1121(Computer)X
+1461(Society.)X
+555 2070([ROSE91])N
+925(Rosenblum,)X
+1341(M.,)X
+1484(Ousterhout,)X
+1892(J.,)X
+1995(``The)X
+2206(Design)X
+2464(and)X
+2611(Implementation)X
+3149(of)X
+3247(a)X
+3314(Log-Structured)X
+3835(File)X
+3990(System'',)X
+2 f
+727 2160(Proceedings)N
+1148(of)X
+1230(the)X
+1348(13th)X
+1510(Symposium)X
+1895(on)X
+1995(Operating)X
+2344(Systems)X
+2618(Principles)X
+1 f
+2947(,)X
+2987(1991.)X
+555 2340([SELT91])N
+904(Seltzer,)X
+1171(M.,)X
+1306(Stonebraker,)X
+1738(M.,)X
+1873(``Read)X
+2116(Optimized)X
+2478(File)X
+2626(Systems:)X
+2938(A)X
+3020(Performance)X
+3454(Evaluation'',)X
+2 f
+3898(Proceedings)X
+727 2430(7th)N
+849(Annual)X
+1100(International)X
+1542(Conference)X
+1932(on)X
+2032(Data)X
+2212(Engineering)X
+1 f
+2608(,)X
+2648(Kobe,)X
+2862(Japan,)X
+3085(April)X
+3274(1991.)X
+555 2610([SPEC88])N
+907(Spector,)X
+1200(Rausch,)X
+1484(Bruell,)X
+1732(``Camelot:)X
+2107(A)X
+2192(Flexible,)X
+2501(Distributed)X
+2888(Transaction)X
+3294(Processing)X
+3668(System'',)X
+2 f
+4004(Proceed-)X
+727 2700(ings)N
+880(of)X
+962(Spring)X
+1195(COMPCON)X
+1606(1988)X
+1 f
+(,)S
+1806(February)X
+2116(1988.)X
+555 2880([SQL86])N
+862(American)X
+1201(National)X
+1499(Standards)X
+1836(Institute,)X
+2139(``Database)X
+2509(Language)X
+2847(SQL'',)X
+3093(ANSI)X
+3301(X3.135-1986)X
+3747(\(ISO)X
+3924(9075\),)X
+4152(May)X
+727 2970(1986.)N
+555 3150([STON81])N
+919(Stonebraker,)X
+1348(M.,)X
+1480(``Operating)X
+1876(System)X
+2132(Support)X
+2406(for)X
+2520(Database)X
+2835(Management'',)X
+2 f
+3348(Communications)X
+3910(of)X
+3992(the)X
+4110(ACM)X
+1 f
+4279(,)X
+727 3240(1981.)N
+555 3420([SULL92])N
+925(Sullivan,)X
+1247(M.,)X
+1394(Olson,)X
+1641(M.,)X
+1788(``An)X
+1976(Index)X
+2195(Implementation)X
+2737(Supporting)X
+3127(Fast)X
+3295(Recovery)X
+3638(for)X
+3767(the)X
+3900(POSTGRES)X
+727 3510(Storage)N
+1014(System'',)X
+1365(to)X
+1469(appear)X
+1726(in)X
+2 f
+1830(Proceedings)X
+2272(8th)X
+2415(Annual)X
+2687(International)X
+3150(Conference)X
+3561(on)X
+3682(Data)X
+3883(Engineering)X
+1 f
+4279(,)X
+727 3600(Tempe,)N
+990(Arizona,)X
+1289(February)X
+1599(1992.)X
+555 3780([TPCB90])N
+914(Transaction)X
+1319(Processing)X
+1692(Performance)X
+2129(Council,)X
+2428(``TPC)X
+2653(Benchmark)X
+3048(B'',)X
+3200(Standard)X
+3510(Speci\256cation,)X
+3973(Waterside)X
+727 3870(Associates,)N
+1110(Fremont,)X
+1421(CA.,)X
+1592(1990.)X
+555 4050([YOUN91])N
+947(Young,)X
+1211(M.)X
+1328(W.,)X
+1470(Thompson,)X
+1858(D.)X
+1962(S.,)X
+2072(Jaffe,)X
+2274(E.,)X
+2388(``A)X
+2525(Modular)X
+2826(Architecture)X
+3253(for)X
+3372(Distributed)X
+3757(Transaction)X
+4161(Pro-)X
+727 4140(cessing'',)N
+2 f
+1057(Proceedings)X
+1478(1991)X
+1658(Winter)X
+1896(Usenix)X
+1 f
+2119(,)X
+2159(Dallas,)X
+2404(TX,)X
+2551(January)X
+2821(1991.)X
+3 f
+755 4263(Margo)N
+1008(I.)X
+1080(Seltzer)X
+1 f
+1338(is)X
+1411(a)X
+1467(Ph.D.)X
+1669(student)X
+1920(in)X
+2002(the)X
+2120(Department)X
+2519(of)X
+2606(Electrical)X
+2934(Engineering)X
+3346(and)X
+3482(Computer)X
+3822(Sciences)X
+4123(at)X
+4201(the)X
+555 4353(University)N
+919(of)X
+1012(California,)X
+1383(Berkeley.)X
+1739(Her)X
+1886(research)X
+2181(interests)X
+2474(include)X
+2735(\256le)X
+2862(systems,)X
+3160(databases,)X
+3513(and)X
+3654(transaction)X
+4031(process-)X
+555 4443(ing)N
+686(systems.)X
+1008(She)X
+1157(spent)X
+1355(several)X
+1612(years)X
+1811(working)X
+2107(at)X
+2194(startup)X
+2441(companies)X
+2813(designing)X
+3153(and)X
+3298(implementing)X
+3771(\256le)X
+3902(systems)X
+4183(and)X
+555 4533(transaction)N
+929(processing)X
+1294(software)X
+1592(and)X
+1729(designing)X
+2061(microprocessors.)X
+2648(Ms.)X
+2791(Seltzer)X
+3035(received)X
+3329(her)X
+3453(AB)X
+3585(in)X
+3668(Applied)X
+3947(Mathemat-)X
+555 4623(ics)N
+664(from)X
+840 0.1953(Harvard/Radcliffe)AX
+1445(College)X
+1714(in)X
+1796(1983.)X
+755 4746(In)N
+845(her)X
+971(spare)X
+1163(time,)X
+1347(Margo)X
+1583(can)X
+1717(usually)X
+1970(be)X
+2068(found)X
+2277(preparing)X
+2607(massive)X
+2887(quantities)X
+3220(of)X
+3309(food)X
+3478(for)X
+3594(hungry)X
+3843(hordes,)X
+4099(study-)X
+555 4836(ing)N
+677(Japanese,)X
+1003(or)X
+1090(playing)X
+1350(soccer)X
+1576(with)X
+1738(an)X
+1834(exciting)X
+2112(Bay)X
+2261(Area)X
+2438(Women's)X
+2770(Soccer)X
+3009(team,)X
+3205(the)X
+3323(Berkeley)X
+3633(Bruisers.)X
+3 f
+755 5049(Michael)N
+1056(A.)X
+1159(Olson)X
+1 f
+1383(is)X
+1461(a)X
+1522(Master's)X
+1828(student)X
+2084(in)X
+2170(the)X
+2292(Department)X
+2695(of)X
+2786(Electrical)X
+3118(Engineering)X
+3534(and)X
+3674(Computer)X
+4018(Sciences)X
+555 5139(at)N
+645(the)X
+774(University)X
+1143(of)X
+1241(California,)X
+1617(Berkeley.)X
+1978(His)X
+2120(primary)X
+2405(interests)X
+2703(are)X
+2833(database)X
+3141(systems)X
+3425(and)X
+3572(mass)X
+3763(storage)X
+4026(systems.)X
+555 5229(Mike)N
+759(spent)X
+963(two)X
+1118(years)X
+1323(working)X
+1625(for)X
+1754(a)X
+1825(commercial)X
+2239(database)X
+2551(system)X
+2808(vendor)X
+3066(before)X
+3307(joining)X
+3567(the)X
+3699(Postgres)X
+4004(Research)X
+555 5319(Group)N
+780(at)X
+858(Berkeley)X
+1168(in)X
+1250(1988.)X
+1470(He)X
+1584(received)X
+1877(his)X
+1990(B.A.)X
+2161(in)X
+2243(Computer)X
+2583(Science)X
+2853(from)X
+3029(Berkeley)X
+3339(in)X
+3421(May)X
+3588(1991.)X
+755 5442(Mike)N
+945(only)X
+1108(recently)X
+1388(transferred)X
+1758(into)X
+1903(Sin)X
+2030(City,)X
+2208(but)X
+2330(is)X
+2403(rapidly)X
+2650(adopting)X
+2950(local)X
+3126(customs)X
+3408(and)X
+3544(coloration.)X
+3929(In)X
+4016(his)X
+4129(spare)X
+555 5532(time,)N
+742(he)X
+843(organizes)X
+1176(informal)X
+1477(Friday)X
+1711(afternoon)X
+2043(study)X
+2240(groups)X
+2482(to)X
+2568(discuss)X
+2823(recent)X
+3044(technical)X
+3358(and)X
+3498(economic)X
+3834(developments.)X
+555 5622(Among)N
+815(his)X
+928(hobbies)X
+1197(are)X
+1316(Charles)X
+1581(Dickens,)X
+1884(Red)X
+2033(Rock,)X
+2242(and)X
+2378(speaking)X
+2683(Dutch)X
+2899(to)X
+2981(anyone)X
+3233(who)X
+3391(will)X
+3535(permit)X
+3764(it.)X
+
+17 p
+%%Trailer
+xt
+
+xs
+
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps
new file mode 100644
index 000000000..816c9243c
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps
@@ -0,0 +1,320 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 129.01(MPOOL\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 129.01(anual MPOOL\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72 84 S
+(ME).18 E F0(mpool \255 shared memory b)108 96 Q(uf)-.2 E(fer pool)-.25 E F1
+(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(#include <db)108 124.8 Q(.h>)-.4 E
+(#include <mpool.h>)108 136.8 Q(MPOOL *)108 160.8 Q(mpool_open \(DBT *k)108
+172.8 Q(ey)-.1 E 2.5(,i)-.55 G(nt fd, pgno_t pagesize, pgno_t maxcache\);)
+216.25 172.8 Q -.1(vo)108 196.8 S(id).1 E(mpool_\214lter \(MPOOL *mp, v)108
+208.8 Q(oid \(*pgin\)\(v)-.1 E(oid *, pgno_t, v)-.1 E(oid *\),)-.1 E -.1(vo)158
+220.8 S(id \(*pgout\)\(v).1 E(oid *, pgno_t, v)-.1 E(oid *\), v)-.1 E
+(oid *pgcookie\);)-.1 E -.1(vo)108 244.8 S(id *).1 E
+(mpool_new \(MPOOL *mp, pgno_t *pgnoaddr\);)108 256.8 Q -.1(vo)108 280.8 S
+(id *).1 E(mpool_get \(MPOOL *mp, pgno_t pgno, u_int \215ags\);)108 292.8 Q
+(int)108 316.8 Q(mpool_put \(MPOOL *mp, v)108 328.8 Q(oid *pgaddr)-.1 E 2.5(,u)
+-.92 G(_int \215ags\);)290.62 328.8 Q(int)108 352.8 Q
+(mpool_sync \(MPOOL *mp\);)108 364.8 Q(int)108 388.8 Q
+(mpool_close \(MPOOL *mp\);)108 400.8 Q F1(DESCRIPTION)72 417.6 Q/F3 10
+/Times-Italic@0 SF(Mpool)108 429.6 Q F0 1.013(is the library interf)3.513 F
+1.013(ace intended to pro)-.1 F 1.013(vide page oriented b)-.15 F(uf)-.2 E
+1.012(fer management of \214les.)-.25 F 1.012(The b)6.012 F(uf)-.2 E(fers)-.25
+E(may be shared between processes.)108 441.6 Q .416(The function)108 458.4 R F3
+(mpool_open)2.916 E F0 .417(initializes a memory pool.)2.917 F(The)5.417 E F3
+-.1(ke)2.917 G(y)-.2 E F0(ar)2.917 E .417(gument is the byte string used to ne)
+-.18 F(gotiate)-.15 E .697(between multiple processes wishing to share b)108
+470.4 R(uf)-.2 E 3.196(fers. If)-.25 F .696(the \214le b)3.196 F(uf)-.2 E .696
+(fers are mapped in shared memory)-.25 F 3.196(,a)-.65 G(ll)534.44 470.4 Q .894
+(processes using the same k)108 482.4 R 1.194 -.15(ey w)-.1 H .894
+(ill share the b).15 F(uf)-.2 E 3.394(fers. If)-.25 F F3 -.1(ke)3.394 G(y)-.2 E
+F0 .895(is NULL, the b)3.395 F(uf)-.2 E .895(fers are mapped into pri)-.25 F
+-.25(va)-.25 G(te).25 E(memory)108 494.4 Q 5.116(.T)-.65 G(he)154.406 494.4 Q
+F3(fd)2.616 E F0(ar)2.616 E .115(gument is a \214le descriptor for the underly\
+ing \214le, which must be seekable.)-.18 F(If)5.115 E F3 -.1(ke)2.615 G(y)-.2 E
+F0 .115(is non-)2.615 F(NULL and matches a \214le already being mapped, the)108
+506.4 Q F3(fd)2.5 E F0(ar)2.5 E(gument is ignored.)-.18 E(The)108 523.2 Q F3
+(pa)3.328 E -.1(ge)-.1 G(size).1 E F0(ar)3.329 E .829
+(gument is the size, in bytes, of the pages into which the \214le is brok)-.18
+F .829(en up.)-.1 F(The)5.829 E F3(maxcac)3.329 E(he)-.15 E F0(ar)108 535.2 Q
+.153(gument is the maximum number of pages from the underlying \214le to cache\
+ at an)-.18 F 2.653(yo)-.15 G .153(ne time.)451.308 535.2 R .153(This v)5.153 F
+.153(alue is)-.25 F .099(not relati)108 547.2 R .399 -.15(ve t)-.25 H 2.599(ot)
+.15 G .099(he number of processes which share a \214le')168.727 547.2 R 2.6(sb)
+-.55 G(uf)350.39 547.2 Q .1(fers, b)-.25 F .1(ut will be the lar)-.2 F .1
+(gest v)-.18 F .1(alue speci\214ed by)-.25 F(an)108 559.2 Q 2.5(yo)-.15 G 2.5
+(ft)129.79 559.2 S(he processes sharing the \214le.)138.4 559.2 Q(The)108 576 Q
+F3(mpool_\214lter)3.254 E F0 .754(function is intended to mak)3.254 F 3.254(et)
+-.1 G .754(ransparent input and output processing of the pages possi-)301.778
+576 R 3.095(ble. If)108 588 R(the)3.095 E F3(pgin)3.095 E F0 .596
+(function is speci\214ed, it is called each time a b)3.095 F(uf)-.2 E .596
+(fer is read into the memory pool from the)-.25 F .125(backing \214le.)108 600
+R .125(If the)5.125 F F3(pgout)2.625 E F0 .125
+(function is speci\214ed, it is called each time a b)2.625 F(uf)-.2 E .125
+(fer is written into the backing \214le.)-.25 F .276
+(Both functions are are called with the)108 612 R F3(pgcookie)2.777 E F0
+(pointer)2.777 E 2.777(,t)-.4 G .277
+(he page number and a pointer to the page to being)337.27 612 R
+(read or written.)108 624 Q .124(The function)108 640.8 R F3(mpool_ne)2.624 E
+(w)-.15 E F0(tak)2.624 E .123(es an MPOOL pointer and an address as ar)-.1 F
+2.623(guments. If)-.18 F 2.623(an)2.623 G .623 -.25(ew p)457.568 640.8 T .123
+(age can be allo-).25 F .944(cated, a pointer to the page is returned and the \
+page number is stored into the)108 652.8 R F3(pgnoaddr)3.445 E F0 3.445
+(address. Other)3.445 F(-)-.2 E(wise, NULL is returned and errno is set.)108
+664.8 Q 1.167(The function)108 681.6 R F3(mpool_g)3.667 E(et)-.1 E F0(tak)3.667
+E 1.167(es a MPOOL pointer and a page number as ar)-.1 F 3.666(guments. If)-.18
+F 1.166(the page e)3.666 F 1.166(xists, a)-.15 F .686
+(pointer to the page is returned.)108 693.6 R .687
+(Otherwise, NULL is returned and errno is set.)5.686 F .687
+(The \215ags parameter is not)5.687 F(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G
+(istrib)132.57 732 Q 104.595(ution June)-.2 F(4, 1993)2.5 E(1)535 732 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 129.01(MPOOL\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 129.01(anual MPOOL\(3\))340.17 48 R(currently used.)108 84 Q 1.463
+(The function)108 100.8 R/F1 10/Times-Italic@0 SF(mpool_put)3.963 E F0 1.462
+(unpins the page referenced by)3.962 F F1(pgaddr)3.962 E F0(.).73 E F1(Pgaddr)
+6.462 E F0 1.462(must be an address pre)3.962 F(viously)-.25 E(returned by)108
+112.8 Q F1(mpool_g)2.5 E(et)-.1 E F0(or)2.5 E F1(mpool_ne)2.5 E(w)-.15 E F0 5
+(.T).31 G(he \215ag v)271.65 112.8 Q(alue is speci\214ed by)-.25 E F1(or)2.5 E
+F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)434.74 112.8 S(he follo)443.35 112.8 Q
+(wing v)-.25 E(alues:)-.25 E(MPOOL_DIR)108 129.6 Q(TY)-.6 E
+(The page has been modi\214ed and needs to be written to the backing \214le.)
+144 141.6 Q F1(Mpool_put)108 158.4 Q F0
+(returns 0 on success and -1 if an error occurs.)2.5 E .247(The function)108
+175.2 R F1(mpool_sync)2.747 E F0 .247(writes all modi\214ed pages associated w\
+ith the MPOOL pointer to the backing \214le.)2.747 F F1(Mpool_sync)108 187.2 Q
+F0(returns 0 on success and -1 if an error occurs.)2.5 E(The)108 204 Q F1
+(mpool_close)2.698 E F0 .198(function free')2.698 F 2.698(su)-.55 G 2.698(pa)
+245.432 204 S .498 -.15(ny a)257.57 204 T .198
+(llocated memory associated with the memory pool cookie.).15 F(Modi-)5.197 E
+(\214ed pages are)108 216 Q/F2 10/Times-Bold@0 SF(not)2.5 E F0
+(written to the backing \214le.)2.5 E F1(Mpool_close)5 E F0
+(returns 0 on success and -1 if an error occurs.)2.5 E/F3 9/Times-Bold@0 SF
+(ERR)72 232.8 Q(ORS)-.27 E F0(The)108 244.8 Q F1(mpool_open)2.938 E F0 .438
+(function may f)2.938 F .438(ail and set)-.1 F F1(errno)2.938 E F0 .438(for an)
+2.938 F 2.938(yo)-.15 G 2.938(ft)344.87 244.8 S .439
+(he errors speci\214ed for the library routine)353.918 244.8 R F1(mal-)2.939 E
+(loc)108 256.8 Q F0(\(3\).).31 E(The)108 273.6 Q F1(mpool_g)2.5 E(et)-.1 E F0
+(function may f)2.5 E(ail and set)-.1 E F1(errno)2.5 E F0(for the follo)2.5 E
+(wing:)-.25 E([EINV)108 290.4 Q 29.98(AL] The)-1.35 F(requested record doesn')
+2.5 E 2.5(te)-.18 G(xist.)305.96 290.4 Q(The)108 307.2 Q F1(mpool_ne)4.073 E(w)
+-.15 E F0(and)4.073 E F1(mpool_g)4.073 E(et)-.1 E F0 1.573(functions may f)
+4.073 F 1.573(ail and set)-.1 F F1(errno)4.073 E F0 1.573(for an)4.073 F 4.073
+(yo)-.15 G 4.073(ft)421.336 307.2 S 1.573(he errors speci\214ed for the)431.519
+307.2 R(library routines)108 319.2 Q F1 -.37(re)2.5 G(ad).37 E F0(\(2\)).77 E
+F1 2.5(,w).54 G(rite)214.48 319.2 Q F0(\(2\)).18 E F1(,).54 E F0(and)2.5 E F1
+(malloc)2.5 E F0(\(3\).).31 E(The)108 336 Q F1(mpool_sync)4.287 E F0 1.787
+(function may f)4.287 F 1.787(ail and set)-.1 F F1(errno)4.288 E F0 1.788
+(for an)4.288 F 4.288(yo)-.15 G 4.288(ft)356.694 336 S 1.788
+(he errors speci\214ed for the library routine)367.092 336 R F1(write)108 348 Q
+F0(\(2\).).18 E(The)108 364.8 Q F1(mpool_close)4.125 E F0 1.624(function may f)
+4.125 F 1.624(ail and set)-.1 F F1(errno)4.124 E F0 1.624(for an)4.124 F 4.124
+(yo)-.15 G 4.124(ft)357.842 364.8 S 1.624
+(he errors speci\214ed for the library routine)368.076 364.8 R F1(fr)108 376.8
+Q(ee)-.37 E F0(\(3\).).18 E F3(SEE ALSO)72 393.6 Q F1(dbopen)108 405.6 Q F0
+(\(3\),).24 E F1(btr)2.5 E(ee)-.37 E F0(\(3\),).18 E F1(hash)2.5 E F0(\(3\),)
+.28 E F1 -.37(re)2.5 G(cno).37 E F0(\(3\)).18 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5
+(yD)-.15 G(istrib)132.57 732 Q 104.595(ution June)-.2 F(4, 1993)2.5 E(2)535 732
+Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/recno.3.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/recno.3.ps
new file mode 100644
index 000000000..8ffccfca9
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/docs/recno.3.ps
@@ -0,0 +1,341 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 130.12(RECNO\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 130.12(anual RECNO\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72 84 S
+(ME).18 E F0(recno \255 record number database access method)108 96 Q F1
+(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(#include <sys/types.h>)108 124.8 Q
+(#include <db)108 136.8 Q(.h>)-.4 E F1(DESCRIPTION)72 153.6 Q F0 1.158
+(The routine)108 165.6 R/F3 10/Times-Italic@0 SF(dbopen)3.658 E F0 1.158
+(is the library interf)3.658 F 1.158(ace to database \214les.)-.1 F 1.157
+(One of the supported \214le formats is record)6.158 F 1.159(number \214les.)
+108 177.6 R 1.159(The general description of the database access methods is in)
+6.159 F F3(dbopen)3.66 E F0 1.16(\(3\), this manual page).24 F
+(describes only the recno speci\214c information.)108 189.6 Q 1.944
+(The record number data structure is either v)108 206.4 R 1.944
+(ariable or \214x)-.25 F 1.944
+(ed-length records stored in a \215at-\214le format,)-.15 F 2.04
+(accessed by the logical record number)108 218.4 R 7.04(.T)-.55 G 2.04(he e)
+286.31 218.4 R 2.04(xistence of record number \214v)-.15 F 4.54(ei)-.15 G 2.04
+(mplies the e)442.1 218.4 R 2.04(xistence of)-.15 F .876
+(records one through four)108 230.4 R 3.376(,a)-.4 G .875
+(nd the deletion of record number one causes record number \214v)219.684 230.4
+R 3.375(et)-.15 G 3.375(ob)489.93 230.4 S 3.375(er)503.305 230.4 S(enum-)514.45
+230.4 Q .282(bered to record number four)108 242.4 R 2.782(,a)-.4 G 2.782(sw)
+231.19 242.4 S .283(ell as the cursor)245.082 242.4 R 2.783(,i)-.4 G 2.783(fp)
+316.633 242.4 S .283(ositioned after record number one, to shift do)327.746
+242.4 R .283(wn one)-.25 F(record.)108 254.4 Q .373
+(The recno access method speci\214c data structure pro)108 271.2 R .373
+(vided to)-.15 F F3(dbopen)2.873 E F0 .373(is de\214ned in the <db)2.873 F .373
+(.h> include \214le as)-.4 F(follo)108 283.2 Q(ws:)-.25 E(typedef struct {)108
+300 Q(u_long \215ags;)144 312 Q(u_int cachesize;)144 324 Q(u_int psize;)144 336
+Q(int lorder;)144 348 Q(size_t reclen;)144 360 Q(u_char b)144 372 Q -.25(va)
+-.15 G(l;).25 E(char *bfname;)144 384 Q 2.5(}R)108 396 S(ECNOINFO;)121.97 396 Q
+(The elements of this structure are de\214ned as follo)108 412.8 Q(ws:)-.25 E
+14.61(\215ags The)108 429.6 R(\215ag v)2.5 E(alue is speci\214ed by)-.25 E F3
+(or)2.5 E F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)313.2 429.6 S(he follo)321.81
+429.6 Q(wing v)-.25 E(alues:)-.25 E(R_FIXEDLEN)144 446.4 Q .962
+(The records are \214x)180 458.4 R .963(ed-length, not byte delimited.)-.15 F
+.963(The structure element)5.963 F F3 -.37(re)3.463 G(clen).37 E F0
+(speci\214es)3.463 E .345(the length of the record, and the structure element)
+180 470.4 R F3(bval)2.844 E F0 .344(is used as the pad character)2.844 F 5.344
+(.A)-.55 G -.15(ny)530.15 470.4 S .739
+(records, inserted into the database, that are less than)180 482.4 R F3 -.37
+(re)3.239 G(clen).37 E F0 .74(bytes long are automatically)3.239 F(padded.)180
+494.4 Q(R_NOKEY)144 511.2 Q 2.34(In the interf)180 523.2 R 2.34
+(ace speci\214ed by)-.1 F F3(dbopen)4.84 E F0 4.84(,t).24 G 2.34
+(he sequential record retrie)344.98 523.2 R -.25(va)-.25 G 4.84<6c8c>.25 G 2.34
+(lls in both the)478.25 523.2 R(caller')180 535.2 Q 3.556(sk)-.55 G 1.357 -.15
+(ey a)217.336 535.2 T 1.057(nd data structures.).15 F 1.057
+(If the R_NOKEY \215ag is speci\214ed, the)6.057 F F3(cur)3.557 E(sor)-.1 E F0
+(routines)3.557 E .029(are not required to \214ll in the k)180 547.2 R .329
+-.15(ey s)-.1 H 2.529(tructure. This).15 F .028(permits applications to retrie)
+2.529 F .328 -.15(ve r)-.25 H .028(ecords at).15 F
+(the end of \214les without reading all of the interv)180 559.2 Q
+(ening records.)-.15 E(R_SN)144 576 Q(APSHO)-.35 E(T)-.4 E .964
+(This \215ag requires that a snapshot of the \214le be tak)180 588 R .965
+(en when)-.1 F F3(dbopen)3.465 E F0 .965(is called, instead of)3.465 F
+(permitting an)180 600 Q 2.5(yu)-.15 G
+(nmodi\214ed records to be read from the original \214le.)245.96 600 Q
+(cachesize)108 616.8 Q 3.16(As)144 628.8 S .66
+(uggested maximum size, in bytes, of the memory cache.)158.27 628.8 R .659
+(This v)5.659 F .659(alue is)-.25 F F2(only)3.159 E F0(advisory)3.159 E 3.159
+(,a)-.65 G .659(nd the)514.621 628.8 R .046
+(access method will allocate more memory rather than f)144 640.8 R 2.546
+(ail. If)-.1 F F3(cac)2.546 E(hesize)-.15 E F0 2.546(is 0)2.546 F .046
+(\(no size is speci\214ed\) a)2.546 F(def)144 652.8 Q(ault cache is used.)-.1 E
+12.95(psize The)108 669.6 R .715
+(recno access method stores the in-memory copies of its records in a btree.)
+3.216 F .715(This v)5.715 F .715(alue is the)-.25 F .805
+(size \(in bytes\) of the pages used for nodes in that tree.)144 681.6 R(If)
+5.805 E F3(psize)3.305 E F0 .806(is 0 \(no page size is speci\214ed\) a)3.305 F
+1.468
+(page size is chosen based on the underlying \214le system I/O block size.)144
+693.6 R(See)6.467 E F3(btr)3.967 E(ee)-.37 E F0 1.467(\(3\) for more).18 F
+(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 96.815
+(ution August)-.2 F(18, 1994)2.5 E(1)535 732 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 130.12(RECNO\(3\) BSD)72 48 R(Programmer')2.5 E 2.5(sM)
+-.55 G 130.12(anual RECNO\(3\))340.17 48 R(information.)144 84 Q 9.62
+(lorder The)108 100.8 R 1.596(byte order for inte)4.096 F 1.596
+(gers in the stored database metadata.)-.15 F 1.597
+(The number should represent the)6.597 F .689(order as an inte)144 112.8 R .689
+(ger; for e)-.15 F .689(xample, big endian order w)-.15 F .689
+(ould be the number 4,321.)-.1 F(If)5.689 E/F1 10/Times-Italic@0 SF(lor)3.189 E
+(der)-.37 E F0 .688(is 0 \(no)3.189 F
+(order is speci\214ed\) the current host order is used.)144 124.8 Q 9.07
+(reclen The)108 141.6 R(length of a \214x)2.5 E(ed-length record.)-.15 E -.15
+(bv)108 158.4 S 16.68(al The)-.1 F .182
+(delimiting byte to be used to mark the end of a record for v)2.682 F .183
+(ariable-length records, and the pad)-.25 F .809(character for \214x)144 170.4
+R .809(ed-length records.)-.15 F .809(If no v)5.809 F .809
+(alue is speci\214ed, ne)-.25 F .809(wlines \(`)-.25 F(`\\n')-.74 E .808
+('\) are used to mark the)-.74 F(end of v)144 182.4 Q
+(ariable-length records and \214x)-.25 E
+(ed-length records are padded with spaces.)-.15 E 3.51(bfname The)108 199.2 R
+.505
+(recno access method stores the in-memory copies of its records in a btree.)
+3.005 F .506(If bfname is non-)5.506 F .065(NULL, it speci\214es the name of t\
+he btree \214le, as if speci\214ed as the \214le name for a dbopen of a btree)
+144 211.2 R(\214le.)144 223.2 Q .971(The data part of the k)108 240 R -.15(ey)
+-.1 G .972(/data pair used by the recno access method is the same as other acc\
+ess methods.).15 F .199(The k)108 252 R .499 -.15(ey i)-.1 H 2.699(sd).15 G(if)
+157.507 252 Q 2.699(ferent. The)-.25 F F1(data)2.699 E F0 .199
+(\214eld of the k)2.699 F .499 -.15(ey s)-.1 H .198
+(hould be a pointer to a memory location of type).15 F F1 -.37(re)2.698 G
+(cno_t).37 E F0 2.698(,a).68 G(s)536.11 252 Q .505(de\214ned in the <db)108 264
+R .506(.h> include \214le.)-.4 F .506(This type is normally the lar)5.506 F
+.506(gest unsigned inte)-.18 F .506(gral type a)-.15 F -.25(va)-.2 G .506
+(ilable to the).25 F 2.5(implementation. The)108 276 R F1(size)2.5 E F0
+(\214eld of the k)2.5 E .3 -.15(ey s)-.1 H(hould be the size of that type.).15
+E .706(Because there can be no meta-data associated with the underlying recno \
+access method \214les, an)108 292.8 R 3.206(yc)-.15 G(hanges)512.23 292.8 Q
+1.262(made to the def)108 304.8 R 1.262(ault v)-.1 F 1.262(alues \(e.g. \214x)
+-.25 F 1.263(ed record length or byte separator v)-.15 F 1.263
+(alue\) must be e)-.25 F 1.263(xplicitly speci\214ed)-.15 F
+(each time the \214le is opened.)108 316.8 Q .065(In the interf)108 333.6 R
+.065(ace speci\214ed by)-.1 F F1(dbopen)2.564 E F0 2.564(,u).24 G .064
+(sing the)261.548 333.6 R F1(put)2.564 E F0(interf)2.564 E .064
+(ace to create a ne)-.1 F 2.564(wr)-.25 G .064
+(ecord will cause the creation of)414.44 333.6 R .755(multiple, empty records \
+if the record number is more than one greater than the lar)108 345.6 R .755
+(gest record currently in)-.18 F(the database.)108 357.6 Q/F2 9/Times-Bold@0 SF
+(ERR)72 374.4 Q(ORS)-.27 E F0(The)108 386.4 Q F1 -.37(re)2.922 G(cno).37 E F0
+.421(access method routines may f)2.921 F .421(ail and set)-.1 F F1(errno)2.921
+E F0 .421(for an)2.921 F 2.921(yo)-.15 G 2.921(ft)377.933 386.4 S .421
+(he errors speci\214ed for the library rou-)386.964 386.4 R(tine)108 398.4 Q F1
+(dbopen)2.5 E F0(\(3\) or the follo).24 E(wing:)-.25 E([EINV)108 415.2 Q(AL])
+-1.35 E(An attempt w)144 427.2 Q(as made to add a record to a \214x)-.1 E
+(ed-length database that w)-.15 E(as too lar)-.1 E(ge to \214t.)-.18 E F2
+(SEE ALSO)72 444 Q F1(btr)108 456 Q(ee)-.37 E F0(\(3\)).18 E F1(dbopen)2.5 E F0
+(\(3\),).24 E F1(hash)2.5 E F0(\(3\),).28 E F1(mpool)2.5 E F0(\(3\),).51 E F1
+2.754(Document Pr)108 480 R 2.754(ocessing in a Relational Database System)-.45
+F F0 5.255(,M).32 G 2.755(ichael Stonebrak)362.13 480 R(er)-.1 E 5.255(,H)-.4 G
+2.755(eidi Stettner)454.06 480 R 5.255(,J)-.4 G(oseph)516.67 480 Q
+(Kalash, Antonin Guttman, Nadene L)108 492 Q
+(ynn, Memorandum No. UCB/ERL M82/32, May 1982.)-.55 E F2 -.09(BU)72 508.8 S(GS)
+.09 E F0(Only big and little endian byte order is supported.)108 520.8 Q
+(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 96.815
+(ution August)-.2 F(18, 1994)2.5 E(2)535 732 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.in
new file mode 100644
index 000000000..232376012
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.in
@@ -0,0 +1,13 @@
+thisconfigdir=./..
+myfulldir=plugins/kdb/db2/libdb2/hash
+mydir=hash
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+STLIBOBJS=	hash.o hash_bigkey.o hash_debug.o hash_func.o hash_log2.o \
+		hash_page.o hsearch.o dbm.o
+
+LOCALINCLUDES=	-I. -I$(srcdir)/../include -I../include -I$(srcdir)/../mpool \
+		-I$(srcdir)/../db
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.inc b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.inc
new file mode 100644
index 000000000..87746f721
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/Makefile.inc
@@ -0,0 +1,6 @@
+#       @(#)Makefile.inc	8.2 (Berkeley) 11/7/95
+
+.PATH: ${.CURDIR}/db/hash
+
+SRCS+=	hash.c hash_bigkey.c hash_buf.c hash_func.c hash_log2.c \
+	hash_page.c hsearch.c dbm.c
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/dbm.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/dbm.c
new file mode 100644
index 000000000..43eaf444a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/dbm.c
@@ -0,0 +1,359 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)dbm.c	8.6 (Berkeley) 11/7/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include "db-int.h"
+
+#include <sys/param.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "db-ndbm.h"
+#include "db-dbm.h"
+#include "hash.h"
+
+/* If the two size fields of datum and DBMT are not equal, then
+ * casting between structures will result in stack garbage being
+ * transfered. Has been observed for DEC Alpha OSF, but will handle
+ *  the general case.
+ */
+
+#define NEED_COPY
+
+/*
+ *
+ * This package provides dbm and ndbm compatible interfaces to DB.
+ * First are the DBM routines, which call the NDBM routines, and
+ * the NDBM routines, which call the DB routines.
+ */
+static DBM *__cur_db;
+
+static void no_open_db __P((void));
+
+int
+kdb2_dbminit(file)
+	char *file;
+{
+	if (__cur_db != NULL)
+		(void)kdb2_dbm_close(__cur_db);
+	if ((__cur_db = kdb2_dbm_open(file, O_RDWR|O_BINARY, 0)) != NULL)
+		return (0);
+	if ((__cur_db = kdb2_dbm_open(file, O_RDONLY|O_BINARY, 0)) != NULL)
+		return (0);
+	return (-1);
+}
+
+datum
+kdb2_fetch(key)
+	datum key;
+{
+	datum item;
+
+	if (__cur_db == NULL) {
+		no_open_db();
+		item.dptr = 0;
+		item.dsize = 0;
+		return (item);
+	}
+	return (kdb2_dbm_fetch(__cur_db, key));
+}
+
+datum
+kdb2_firstkey()
+{
+	datum item;
+
+	if (__cur_db == NULL) {
+		no_open_db();
+		item.dptr = 0;
+		item.dsize = 0;
+		return (item);
+	}
+	return (kdb2_dbm_firstkey(__cur_db));
+}
+
+datum
+kdb2_nextkey(key)
+	datum key;
+{
+	datum item;
+
+	if (__cur_db == NULL) {
+		no_open_db();
+		item.dptr = 0;
+		item.dsize = 0;
+		return (item);
+	}
+	return (kdb2_dbm_nextkey(__cur_db));
+}
+
+int
+kdb2_delete(key)
+	datum key;
+{
+	if (__cur_db == NULL) {
+		no_open_db();
+		return (-1);
+	}
+	return (kdb2_dbm_delete(__cur_db, key));
+}
+
+int
+kdb2_store(key, dat)
+	datum key, dat;
+{
+	if (__cur_db == NULL) {
+		no_open_db();
+		return (-1);
+	}
+	return (kdb2_dbm_store(__cur_db, key, dat, DBM_REPLACE));
+}
+
+static void
+no_open_db()
+{
+	(void)fprintf(stderr, "dbm: no open database.\n");
+}
+
+/*
+ * Returns:
+ * 	*DBM on success
+ *	 NULL on failure
+ */
+DBM *
+kdb2_dbm_open(file, flags, mode)
+	const char *file;
+	int flags, mode;
+{
+	HASHINFO info;
+	char path[MAXPATHLEN];
+
+	info.bsize = 4096;
+	info.ffactor = 40;
+	info.nelem = 1;
+	info.cachesize = 0;
+	info.hash = NULL;
+	info.lorder = 0;
+	(void)strncpy(path, file, sizeof(path) - 1);
+	path[sizeof(path) - 1] = '\0';
+	(void)strncat(path, DBM_SUFFIX, sizeof(path) - 1 - strlen(path));
+	return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+}
+
+/*
+ * Returns:
+ *	Nothing.
+ */
+void
+kdb2_dbm_close(db)
+	DBM *db;
+{
+	(void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+datum
+kdb2_dbm_fetch(db, key)
+	DBM *db;
+	datum key;
+{
+	datum retval;
+	int status;
+
+#ifdef NEED_COPY
+	DBT k, r;
+
+	k.data = key.dptr;
+	k.size = key.dsize;
+	status = (db->get)(db, &k, &r, 0);
+	retval.dptr = r.data;
+	retval.dsize = r.size;
+#else
+	status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+#endif
+	if (status) {
+		retval.dptr = NULL;
+		retval.dsize = 0;
+	}
+	return (retval);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+datum
+kdb2_dbm_firstkey(db)
+	DBM *db;
+{
+	int status;
+	datum retkey;
+
+#ifdef NEED_COPY
+	DBT k, r;
+
+	status = (db->seq)(db, &k, &r, R_FIRST);
+	retkey.dptr = k.data;
+	retkey.dsize = k.size;
+#else
+	datum retdata;
+
+	status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+#endif
+	if (status)
+		retkey.dptr = NULL;
+	return (retkey);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+datum
+kdb2_dbm_nextkey(db)
+	DBM *db;
+{
+	int status;
+	datum retkey;
+
+#ifdef NEED_COPY
+	DBT k, r;
+
+	status = (db->seq)(db, &k, &r, R_NEXT);
+	retkey.dptr = k.data;
+	retkey.dsize = k.size;
+#else
+	datum retdata;
+
+	status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+#endif
+	if (status)
+		retkey.dptr = NULL;
+	return (retkey);
+}
+
+/*
+ * Returns:
+ *	 0 on success
+ *	<0 failure
+ */
+int
+kdb2_dbm_delete(db, key)
+	DBM *db;
+	datum key;
+{
+	int status;
+
+#ifdef NEED_COPY
+	DBT k;
+
+	k.data = key.dptr;
+	k.size = key.dsize;
+	status = (db->del)(db, &k, 0);
+#else
+	status = (db->del)(db, (DBT *)&key, 0);
+#endif
+	if (status)
+		return (-1);
+	else
+		return (0);
+}
+
+/*
+ * Returns:
+ *	 0 on success
+ *	<0 failure
+ *	 1 if DBM_INSERT and entry exists
+ */
+int
+kdb2_dbm_store(db, key, content, flags)
+	DBM *db;
+	datum key, content;
+	int flags;
+{
+#ifdef NEED_COPY
+	DBT k, c;
+
+	k.data = key.dptr;
+	k.size = key.dsize;
+	c.data = content.dptr;
+	c.size = content.dsize;
+	return ((db->put)(db, &k, &c,
+	    (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
+#else
+	return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+	    (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
+#endif
+}
+
+int
+kdb2_dbm_error(db)
+	DBM *db;
+{
+	HTAB *hp;
+
+	hp = (HTAB *)db->internal;
+	return (hp->local_errno);
+}
+
+int
+kdb2_dbm_clearerr(db)
+	DBM *db;
+{
+	HTAB *hp;
+
+	hp = (HTAB *)db->internal;
+	hp->local_errno = 0;
+	return (0);
+}
+
+int
+kdb2_dbm_dirfno(db)
+	DBM *db;
+{
+	return(((HTAB *)db->internal)->fp);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/extern.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/extern.h
new file mode 100644
index 000000000..872b6b0fe
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/extern.h
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)extern.h	8.8 (Berkeley) 11/7/95
+ */
+
+#define __add_bigpage		__kdb2_add_bigpage
+#define __add_ovflpage		__kdb2_add_ovflpage
+#define __addel			__kdb2_addel
+#define __alloc_tmp		__kdb2_alloc_tmp
+#define __big_delete		__kdb2_big_delete
+#define __big_insert		__kdb2_big_insert
+#define __big_keydata		__kdb2_big_keydata
+#define __big_return		__kdb2_big_return
+#define __call_hash		__kdb2_call_hash
+#define __cursor_creat		__kdb2_cursor_creat
+#define __delete_page		__kdb2_delete_page
+#define __delpair		__kdb2_delpair
+#define __expand_table		__kdb2_expand_table
+#define __find_bigpair		__kdb2_find_bigpair
+#define __free_ovflpage		__kdb2_free_ovflpage
+#define __get_bigkey		__kdb2_get_bigkey
+#define __get_buf		__kdb2_get_buf
+#define __get_item		__kdb2_get_item
+#define __get_item_done		__kdb2_get_item_done
+#define __get_item_first	__kdb2_get_item_first
+#define __get_item_next		__kdb2_get_item_next
+#define __get_item_reset	__kdb2_get_item_reset
+#define __get_page		__kdb2_get_page
+#define __ibitmap		__kdb2_ibitmap
+#define __log2			__kdb2_log2
+#define __new_page		__kdb2_new_page
+#define __pgin_routine		__kdb2_pgin_routine
+#define __pgout_routine		__kdb2_pgout_routine
+#define __put_buf		__kdb2_put_buf
+#define __put_page		__kdb2_put_page
+#define __reclaim_tmp		__kdb2_reclaim_tmp
+#define __split_page		__kdb2_split_page
+
+PAGE16	 *__add_bigpage __P((HTAB *, PAGE16 *, indx_t, const u_int8_t));
+PAGE16	 *__add_ovflpage __P((HTAB *, PAGE16 *));
+int32_t	  __addel __P((HTAB *, ITEM_INFO *,
+		const DBT *, const DBT *, u_int32_t, const u_int8_t));
+u_int32_t __alloc_tmp __P((HTAB*));
+int32_t	  __big_delete __P((HTAB *, PAGE16 *, indx_t));
+int32_t	  __big_insert __P((HTAB *, PAGE16 *, const DBT *, const DBT *));
+int32_t	  __big_keydata __P((HTAB *, PAGE16 *, DBT *, DBT *, int32_t));
+int32_t	  __big_return __P((HTAB *, ITEM_INFO *, DBT *, int32_t));
+u_int32_t __call_hash __P((HTAB *, int8_t *, int32_t));
+CURSOR	 *__cursor_creat __P((const DB *));
+int32_t	  __delete_page __P((HTAB *, PAGE16 *, int32_t));
+int32_t	  __delpair __P((HTAB *, CURSOR *, ITEM_INFO *));
+int32_t	  __expand_table __P((HTAB *));
+int32_t	  __find_bigpair __P((HTAB *, CURSOR *, int8_t *, int32_t));
+void	  __free_ovflpage __P((HTAB *, PAGE16 *));
+int32_t	  __get_bigkey __P((HTAB *, PAGE16 *, indx_t, DBT *));
+PAGE16	 *__get_buf __P((HTAB *, u_int32_t, int32_t));
+u_int32_t __get_item __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *));
+u_int32_t __get_item_done __P((HTAB *, CURSOR *));
+u_int32_t __get_item_first __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *));
+u_int32_t __get_item_next __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *));
+u_int32_t __get_item_reset __P((HTAB *, CURSOR *));
+PAGE16	 *__get_page __P((HTAB *, u_int32_t, int32_t));
+int32_t	  __ibitmap __P((HTAB *, int32_t, int32_t, int32_t));
+u_int32_t __log2 __P((u_int32_t));
+int32_t	  __new_page __P((HTAB *, u_int32_t, int32_t));
+void	  __pgin_routine __P((void *, db_pgno_t, void *));
+void	  __pgout_routine __P((void *, db_pgno_t, void *));
+u_int32_t __put_buf __P((HTAB *, PAGE16 *, u_int32_t));
+int32_t	  __put_page __P((HTAB *, PAGE16 *, int32_t, int32_t));
+void	  __reclaim_tmp __P((HTAB *));
+int32_t	  __split_page __P((HTAB *, u_int32_t, u_int32_t));
+
+/* Default hash routine. */
+extern u_int32_t (*__default_hash) __P((const void *, size_t));
+
+#ifdef HASH_STATISTICS
+extern long hash_accesses, hash_bigpages, hash_collisions, hash_expansions;
+extern long hash_overflow;
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c
new file mode 100644
index 000000000..b68b1dc91
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c
@@ -0,0 +1,1068 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash.c	8.12 (Berkeley) 11/7/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include "db-int.h"
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int32_t flush_meta __P((HTAB *));
+static int32_t hash_access __P((HTAB *, ACTION, const DBT *, DBT *));
+static int32_t hash_close __P((DB *));
+static int32_t hash_delete __P((const DB *, const DBT *, u_int32_t));
+static int32_t hash_fd __P((const DB *));
+static int32_t hash_get __P((const DB *, const DBT *, DBT *, u_int32_t));
+static int32_t hash_put __P((const DB *, DBT *, const DBT *, u_int32_t));
+static int32_t hash_seq __P((const DB *, DBT *, DBT *, u_int32_t));
+static int32_t hash_sync __P((const DB *, u_int32_t));
+static int32_t hdestroy __P((HTAB *));
+static int32_t cursor_get __P((const DB *, CURSOR *, DBT *, DBT *, \
+	u_int32_t));
+static int32_t cursor_delete __P((const DB *, CURSOR *, u_int32_t));
+static HTAB *init_hash __P((HTAB *, const char *, const HASHINFO *));
+static int32_t init_htab __P((HTAB *, int32_t));
+#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN
+static void swap_header __P((HTAB *));
+static void swap_header_copy __P((HASHHDR *, HASHHDR *));
+#endif
+static u_int32_t hget_header __P((HTAB *, u_int32_t));
+static void hput_header __P((HTAB *));
+
+#define RETURN_ERROR(ERR, LOC)	{ save_errno = ERR; goto LOC; }
+
+/* Return values */
+#define	SUCCESS	 (0)
+#define	ERROR	(-1)
+#define	ABNORMAL (1)
+
+#ifdef HASH_STATISTICS
+u_int32_t hash_accesses, hash_collisions, hash_expansions, hash_overflows,
+	hash_bigpages;
+#endif
+
+/************************** INTERFACE ROUTINES ***************************/
+/* OPEN/CLOSE */
+
+extern DB *
+__kdb2_hash_open(file, flags, mode, info, dflags)
+	const char *file;
+	int flags, mode, dflags;
+	const HASHINFO *info;	/* Special directives for create */
+{
+	struct stat statbuf;
+	DB *dbp;
+	DBT mpool_key;
+	HTAB *hashp;
+	int32_t bpages, csize, new_table, save_errno, specified_file;
+
+	if ((flags & O_ACCMODE) == O_WRONLY) {
+		errno = EINVAL;
+		return (NULL);
+	}
+	if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
+		return (NULL);
+	hashp->fp = -1;
+
+	/* set this now, before file goes away... */
+	specified_file = (file != NULL);
+	if (!file) {
+		file = tmpnam(NULL);
+		/* store the file name so that we can unlink it later */
+		hashp->fname = file;
+#ifdef DEBUG
+		fprintf(stderr, "Using file name %s.\n", file);
+#endif
+	}
+	/*
+	 * Even if user wants write only, we need to be able to read
+	 * the actual file, so we need to open it read/write. But, the
+	 * field in the hashp structure needs to be accurate so that
+	 * we can check accesses.
+	 */
+	hashp->flags = flags;
+	hashp->save_file = specified_file && (hashp->flags & O_RDWR);
+
+	new_table = 0;
+	if (!file || (flags & O_TRUNC) ||
+	    (stat(file, &statbuf) && (errno == ENOENT))) {
+		if (errno == ENOENT)
+			errno = 0;	/* In case someone looks at errno. */
+		new_table = 1;
+	}
+	if (file) {
+		if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1)
+			RETURN_ERROR(errno, error0);
+		(void)fcntl(hashp->fp, F_SETFD, 1);
+	}
+
+	/* Process arguments to set up hash table header. */
+	if (new_table) {
+		if (!(hashp = init_hash(hashp, file, info)))
+			RETURN_ERROR(errno, error1);
+	} else {
+		/* Table already exists */
+		if (info && info->hash)
+			hashp->hash = info->hash;
+		else
+			hashp->hash = __default_hash;
+
+		/* copy metadata from page into header */
+		if (hget_header(hashp,
+		    (info && info->bsize ? info->bsize : DEF_BUCKET_SIZE)) !=
+		    sizeof(HASHHDR))
+			RETURN_ERROR(EFTYPE, error1);
+
+		/* Verify file type, versions and hash function */
+		if (hashp->hdr.magic != HASHMAGIC)
+			RETURN_ERROR(EFTYPE, error1);
+#define	OLDHASHVERSION	1
+		if (hashp->hdr.version != HASHVERSION &&
+		    hashp->hdr.version != OLDHASHVERSION)
+			RETURN_ERROR(EFTYPE, error1);
+		if (hashp->hash(CHARKEY, sizeof(CHARKEY))
+		    != hashp->hdr.h_charkey)
+			RETURN_ERROR(EFTYPE, error1);
+		/*
+		 * Figure out how many segments we need.  Max_Bucket is the
+		 * maximum bucket number, so the number of buckets is
+		 * max_bucket + 1.
+		 */
+
+		/* Read in bitmaps */
+		bpages = (hashp->hdr.spares[hashp->hdr.ovfl_point] +
+		    (hashp->hdr.bsize << BYTE_SHIFT) - 1) >>
+		    (hashp->hdr.bshift + BYTE_SHIFT);
+
+		hashp->nmaps = bpages;
+		(void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
+	}
+
+	/* start up mpool */
+	mpool_key.data = (u_int8_t *)file;
+	mpool_key.size = strlen(file);
+
+	if (info && info->cachesize)
+		csize = info->cachesize / hashp->hdr.bsize;
+	else
+		csize = DEF_CACHESIZE / hashp->hdr.bsize;
+	hashp->mp = mpool_open(&mpool_key, hashp->fp, hashp->hdr.bsize, csize);
+
+	if (!hashp->mp)
+		RETURN_ERROR(errno, error1);
+	mpool_filter(hashp->mp, __pgin_routine, __pgout_routine, hashp);
+
+	/*
+	 * For a new table, set up the bitmaps.
+	 */
+	if (new_table &&
+	   init_htab(hashp, info && info->nelem ? info->nelem : 1))
+		goto error2;
+
+	/* initialize the cursor queue */
+	TAILQ_INIT(&hashp->curs_queue);
+	hashp->seq_cursor = NULL;
+
+
+	/* get a chunk of memory for our split buffer */
+	hashp->split_buf = (PAGE16 *)malloc(hashp->hdr.bsize);
+	if (!hashp->split_buf)
+		goto error2;
+
+	hashp->new_file = new_table;
+
+	if (!(dbp = (DB *)malloc(sizeof(DB))))
+		goto error2;
+
+	dbp->internal = hashp;
+	dbp->close = hash_close;
+	dbp->del = hash_delete;
+	dbp->fd = hash_fd;
+	dbp->get = hash_get;
+	dbp->put = hash_put;
+	dbp->seq = hash_seq;
+	dbp->sync = hash_sync;
+	dbp->type = DB_HASH;
+
+#ifdef DEBUG
+	(void)fprintf(stderr,
+	    "%s\n%s%lx\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
+	    "init_htab:",
+	    "TABLE POINTER   ", (void *)hashp,
+	    "BUCKET SIZE     ", hashp->hdr.bsize,
+	    "BUCKET SHIFT    ", hashp->hdr.bshift,
+	    "FILL FACTOR     ", hashp->hdr.ffactor,
+	    "MAX BUCKET      ", hashp->hdr.max_bucket,
+	    "OVFL POINT      ", hashp->hdr.ovfl_point,
+	    "LAST FREED      ", hashp->hdr.last_freed,
+	    "HIGH MASK       ", hashp->hdr.high_mask,
+	    "LOW  MASK       ", hashp->hdr.low_mask,
+	    "NKEYS           ", hashp->hdr.nkeys);
+#endif
+#ifdef HASH_STATISTICS
+	hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
+	hash_bigpages = 0;
+#endif
+	return (dbp);
+
+error2:
+	save_errno = errno;
+	hdestroy(hashp);
+	errno = save_errno;
+	return (NULL);
+
+error1:
+	if (hashp != NULL)
+		(void)close(hashp->fp);
+
+error0:
+	free(hashp);
+	errno = save_errno;
+	return (NULL);
+}
+
+static int32_t
+hash_close(dbp)
+	DB *dbp;
+{
+	HTAB *hashp;
+	int32_t retval;
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	retval = hdestroy(hashp);
+	free(dbp);
+	return (retval);
+}
+
+static int32_t
+hash_fd(dbp)
+	const DB *dbp;
+{
+	HTAB *hashp;
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	if (hashp->fp == -1) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (hashp->fp);
+}
+
+/************************** LOCAL CREATION ROUTINES **********************/
+static HTAB *
+init_hash(hashp, file, info)
+	HTAB *hashp;
+	const char *file;
+	const HASHINFO *info;
+{
+	struct stat statbuf;
+	int32_t nelem;
+
+	nelem = 1;
+	hashp->hdr.nkeys = 0;
+	hashp->hdr.lorder = DB_BYTE_ORDER;
+	hashp->hdr.bsize = DEF_BUCKET_SIZE;
+	hashp->hdr.bshift = DEF_BUCKET_SHIFT;
+	hashp->hdr.ffactor = DEF_FFACTOR;
+	hashp->hash = __default_hash;
+	memset(hashp->hdr.spares, 0, sizeof(hashp->hdr.spares));
+	memset(hashp->hdr.bitmaps, 0, sizeof(hashp->hdr.bitmaps));
+
+	/* Fix bucket size to be optimal for file system */
+	if (file != NULL) {
+		if (stat(file, &statbuf))
+			return (NULL);
+		hashp->hdr.bsize = statbuf.st_blksize;
+		hashp->hdr.bshift = __log2(hashp->hdr.bsize);
+	}
+	if (info) {
+		if (info->bsize) {
+			/* Round pagesize up to power of 2 */
+			hashp->hdr.bshift = __log2(info->bsize);
+			hashp->hdr.bsize = 1 << hashp->hdr.bshift;
+			if (hashp->hdr.bsize > MAX_BSIZE) {
+				errno = EINVAL;
+				return (NULL);
+			}
+		}
+		if (info->ffactor)
+			hashp->hdr.ffactor = info->ffactor;
+		if (info->hash)
+			hashp->hash = info->hash;
+		if (info->lorder) {
+			if ((info->lorder != DB_BIG_ENDIAN) &&
+			    (info->lorder != DB_LITTLE_ENDIAN)) {
+				errno = EINVAL;
+				return (NULL);
+			}
+			hashp->hdr.lorder = info->lorder;
+		}
+	}
+	return (hashp);
+}
+
+/*
+ * Returns 0 on No Error
+ */
+static int32_t
+init_htab(hashp, nelem)
+	HTAB *hashp;
+	int32_t nelem;
+{
+	int32_t l2, nbuckets;
+
+	/*
+	 * Divide number of elements by the fill factor and determine a
+	 * desired number of buckets.  Allocate space for the next greater
+	 * power of two number of buckets.
+	 */
+	nelem = (nelem - 1) / hashp->hdr.ffactor + 1;
+
+	l2 = __log2(MAX(nelem, 2));
+	nbuckets = 1 << l2;
+
+	hashp->hdr.spares[l2] = l2 + 1;
+	hashp->hdr.spares[l2 + 1] = l2 + 1;
+	hashp->hdr.ovfl_point = l2;
+	hashp->hdr.last_freed = 2;
+
+	hashp->hdr.max_bucket = hashp->hdr.low_mask = nbuckets - 1;
+	hashp->hdr.high_mask = (nbuckets << 1) - 1;
+
+	/*
+	 * The number of header pages is the size of the header divided by
+	 * the amount of freespace on header pages (the page size - the
+	 * size of 1 integer where the length of the header info on that
+	 * page is stored) plus another page if it didn't divide evenly.
+	 */
+	hashp->hdr.hdrpages =
+	    (sizeof(HASHHDR) / (hashp->hdr.bsize - HEADER_OVERHEAD)) +
+	    (((sizeof(HASHHDR) % (hashp->hdr.bsize - HEADER_OVERHEAD)) == 0)
+	    ? 0 : 1);
+
+	/* Create pages for these buckets */
+	/*
+	for (i = 0; i <= hashp->hdr.max_bucket; i++) {
+		if (__new_page(hashp, (u_int32_t)i, A_BUCKET) != 0)
+			return (-1);
+	}
+	*/
+
+	/* First bitmap page is at: splitpoint l2 page offset 1 */
+	if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
+		return (-1);
+
+	return (0);
+}
+
+/*
+ * Functions to get/put hash header.  We access the file directly.
+ */
+static u_int32_t
+hget_header(hashp, page_size)
+	HTAB *hashp;
+	u_int32_t page_size;
+{
+	u_int32_t num_copied, i;
+	u_int8_t *hdr_dest;
+
+	num_copied = 0;
+	i = 0;
+
+	hdr_dest = (u_int8_t *)&hashp->hdr;
+
+	/* 
+	 * XXX
+	 * This should not be printing to stderr on a "normal" error case.
+	 */
+	lseek(hashp->fp, 0, SEEK_SET);
+	num_copied = read(hashp->fp, hdr_dest, sizeof(HASHHDR));
+	if (num_copied != sizeof(HASHHDR)) {
+		fprintf(stderr, "hash: could not retrieve header");
+		return (0);
+	}
+#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN
+	swap_header(hashp);
+#endif
+	return (num_copied);
+}
+
+static void
+hput_header(hashp)
+	HTAB *hashp;
+{
+	HASHHDR *whdrp;
+#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN
+	HASHHDR whdr;
+#endif
+	u_int32_t num_copied, i;
+
+	num_copied = i = 0;
+
+	whdrp = &hashp->hdr;
+#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN
+	whdrp = &whdr;
+	swap_header_copy(&hashp->hdr, whdrp);
+#endif
+
+	lseek(hashp->fp, 0, SEEK_SET);
+	num_copied = write(hashp->fp, whdrp, sizeof(HASHHDR));
+	if (num_copied != sizeof(HASHHDR))
+		(void)fprintf(stderr, "hash: could not write hash header");
+	return;
+}
+
+/********************** DESTROY/CLOSE ROUTINES ************************/
+
+/*
+ * Flushes any changes to the file if necessary and destroys the hashp
+ * structure, freeing all allocated space.
+ */
+static int32_t
+hdestroy(hashp)
+	HTAB *hashp;
+{
+	int32_t save_errno;
+
+	save_errno = 0;
+
+#ifdef HASH_STATISTICS
+	{ int i;
+	(void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
+	    hash_accesses, hash_collisions);
+	(void)fprintf(stderr,
+	    "hdestroy: expansions %ld\n", hash_expansions);
+	(void)fprintf(stderr,
+	    "hdestroy: overflows %ld\n", hash_overflows);
+	(void)fprintf(stderr,
+	    "hdestroy: big key/data pages %ld\n", hash_bigpages);
+	(void)fprintf(stderr,
+	    "keys %ld maxp %d\n", hashp->hdr.nkeys, hashp->hdr.max_bucket);
+
+	for (i = 0; i < NCACHED; i++)
+		(void)fprintf(stderr,
+		    "spares[%d] = %d\n", i, hashp->hdr.spares[i]);
+	}
+#endif
+
+	if (flush_meta(hashp) && !save_errno)
+		save_errno = errno;
+
+	/* Free the split page */
+	if (hashp->split_buf)
+		free(hashp->split_buf);
+
+	/* Free the big key and big data returns */
+	if (hashp->bigkey_buf)
+		free(hashp->bigkey_buf);
+	if (hashp->bigdata_buf)
+		free(hashp->bigdata_buf);
+ 
+	/* XXX This should really iterate over the cursor queue, but
+	   it's not clear how to do that, and the only cursor a hash
+	   table ever creates is the one used by hash_seq().  Passing
+	   NULL as the first arg is also a kludge, but I know that
+	   it's never used, so I do it.  The intent is to plug the
+	   memory leak.  Correctness can come later. */
+ 
+	if (hashp->seq_cursor)
+		hashp->seq_cursor->delete(NULL, hashp->seq_cursor, 0);
+
+	/* shut down mpool */
+	mpool_sync(hashp->mp);
+	mpool_close(hashp->mp);
+
+	if (hashp->fp != -1)
+		(void)close(hashp->fp);
+
+	/* 
+	 * *** This may cause problems if hashp->fname is set in any case
+	 * other than the case that we are generating a temporary file name.
+	 * Note that the new version of mpool should support temporary
+	 * files within mpool itself.
+	 */
+	if (hashp->fname && !hashp->save_file) {
+#ifdef DEBUG
+		fprintf(stderr, "Unlinking file %s.\n", hashp->fname);
+#endif
+		/* we need to chmod the file to allow it to be deleted... */
+		chmod(hashp->fname, 0700);
+		unlink(hashp->fname);
+		/* destroy the temporary name */
+		tmpnam(NULL);
+	}
+	free(hashp);
+
+	if (save_errno) {
+		errno = save_errno;
+		return (ERROR);
+	}
+	return (SUCCESS);
+}
+
+/*
+ * Write modified pages to disk
+ *
+ * Returns:
+ *	 0 == OK
+ *	-1 ERROR
+ */
+static int32_t
+hash_sync(dbp, flags)
+	const DB *dbp;
+	u_int32_t flags;
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+
+	/*
+	 * XXX
+	 * Check success/failure conditions.
+	 */
+	return (flush_meta(hashp) || mpool_sync(hashp->mp));
+}
+
+/*
+ * Returns:
+ *	 0 == OK
+ *	-1 indicates that errno should be set
+ */
+static int32_t
+flush_meta(hashp)
+	HTAB *hashp;
+{
+	int32_t i;
+
+	if (!hashp->save_file)
+		return (0);
+	hashp->hdr.magic = HASHMAGIC;
+	hashp->hdr.version = HASHVERSION;
+	hashp->hdr.h_charkey = hashp->hash(CHARKEY, sizeof(CHARKEY));
+
+	/* write out metadata */
+	hput_header(hashp);
+
+	for (i = 0; i < NCACHED; i++)
+		if (hashp->mapp[i]) {
+			if (__put_page(hashp,
+			    (PAGE16 *)hashp->mapp[i], A_BITMAP, 1))
+				return (-1);
+			hashp->mapp[i] = NULL;
+		}
+	return (0);
+}
+
+/*******************************SEARCH ROUTINES *****************************/
+/*
+ * All the access routines return
+ *
+ * Returns:
+ *	 0 on SUCCESS
+ *	 1 to indicate an external ERROR (i.e. key not found, etc)
+ *	-1 to indicate an internal ERROR (i.e. out of memory, etc)
+ */
+
+/* *** make sure this is true! */
+
+static int32_t
+hash_get(dbp, key, data, flag)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int32_t flag;
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag) {
+		hashp->local_errno = errno = EINVAL;
+		return (ERROR);
+	}
+	return (hash_access(hashp, HASH_GET, key, data));
+}
+
+static int32_t
+hash_put(dbp, key, data, flag)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int32_t flag;
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag && flag != R_NOOVERWRITE) {
+		hashp->local_errno = errno = EINVAL;
+		return (ERROR);
+	}
+	if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+		hashp->local_errno = errno = EPERM;
+		return (ERROR);
+	}
+	return (hash_access(hashp, flag == R_NOOVERWRITE ?
+		HASH_PUTNEW : HASH_PUT, key, (DBT *)data));
+}
+
+static int32_t
+hash_delete(dbp, key, flag)
+	const DB *dbp;
+	const DBT *key;
+	u_int32_t flag;		/* Ignored */
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag) {
+		hashp->local_errno = errno = EINVAL;
+		return (ERROR);
+	}
+	if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+		hashp->local_errno = errno = EPERM;
+		return (ERROR);
+	}
+
+	return (hash_access(hashp, HASH_DELETE, key, NULL));
+}
+
+/*
+ * Assume that hashp has been set in wrapper routine.
+ */
+static int32_t
+hash_access(hashp, action, key, val)
+	HTAB *hashp;
+	ACTION action;
+	const DBT *key;
+	DBT *val;
+{
+	DBT page_key, page_val;
+	CURSOR cursor;
+	ITEM_INFO item_info;
+	u_int32_t bucket;
+	u_int32_t num_items;
+
+#ifdef HASH_STATISTICS
+	hash_accesses++;
+#endif
+
+	num_items = 0;
+
+	/* 
+	 * Set up item_info so that we're looking for space to add an item
+	 * as we cycle through the pages looking for the key.
+	 */
+	if (action == HASH_PUT || action == HASH_PUTNEW) {
+		if (ISBIG(key->size + val->size, hashp))
+			item_info.seek_size = PAIR_OVERHEAD;
+		else
+			item_info.seek_size = key->size + val->size;
+	} else
+		item_info.seek_size = 0;
+	item_info.seek_found_page = 0;
+
+	bucket = __call_hash(hashp, (int8_t *)key->data, key->size);
+
+	cursor.pagep = NULL;
+	__get_item_reset(hashp, &cursor);
+
+	cursor.bucket = bucket;
+	while (1) {
+		__get_item_next(hashp, &cursor, &page_key, &page_val, &item_info);
+		if (item_info.status == ITEM_ERROR)
+			return (ABNORMAL);
+		if (item_info.status == ITEM_NO_MORE)
+			break;
+		num_items++;
+		if (item_info.key_off == BIGPAIR) {
+			/*
+			 * !!!
+			 * 0 is a valid index.
+			 */
+			if (__find_bigpair(hashp, &cursor, (int8_t *)key->data,
+			    key->size) > 0)
+				goto found;
+		} else if (key->size == page_key.size &&
+		    !memcmp(key->data, page_key.data, key->size))
+			goto found;
+	}
+#ifdef HASH_STATISTICS
+	hash_collisions++;
+#endif
+	__get_item_done(hashp, &cursor);
+
+	/*
+	 * At this point, item_info will list either the last page in
+	 * the chain, or the last page in the chain plus a pgno for where
+	 * to find the first page in the chain with space for the
+	 * item we wish to add.
+	 */
+
+	/* Not found */
+	switch (action) {
+	case HASH_PUT:
+	case HASH_PUTNEW:
+		if (__addel(hashp, &item_info, key, val, num_items, 0))
+			return (ERROR);
+		break;
+	case HASH_GET:
+	case HASH_DELETE:
+	default:
+		return (ABNORMAL);
+	}
+
+	if (item_info.caused_expand)
+		__expand_table(hashp);
+	return (SUCCESS);
+
+found:	__get_item_done(hashp, &cursor);
+
+	switch (action) {
+	case HASH_PUTNEW:
+		/* mpool_put(hashp->mp, pagep, 0); */
+		return (ABNORMAL);
+	case HASH_GET:
+		if (item_info.key_off == BIGPAIR) {
+			if (__big_return(hashp, &item_info, val, 0))
+				return (ERROR);
+		} else {
+			val->data = page_val.data;
+			val->size = page_val.size;
+		}
+		/* *** data may not be available! */
+		break;
+	case HASH_PUT:
+		if (__delpair(hashp, &cursor, &item_info) ||
+		    __addel(hashp, &item_info, key, val, UNKNOWN, 0))
+			return (ERROR);
+		__get_item_done(hashp, &cursor);
+		if (item_info.caused_expand)
+			__expand_table(hashp);
+		break;
+	case HASH_DELETE:
+		if (__delpair(hashp, &cursor, &item_info))
+			return (ERROR);
+		break;
+	default:
+		abort();
+	}
+	return (SUCCESS);
+}
+
+/* ****************** CURSORS ********************************** */
+CURSOR *
+__cursor_creat(dbp)
+	const DB *dbp;
+{
+	CURSOR *new_curs;
+	HTAB *hashp;
+
+	new_curs = (CURSOR *)malloc(sizeof(struct cursor_t));
+	if (!new_curs)
+		return NULL;
+	new_curs->internal =
+	    (struct item_info *)malloc(sizeof(struct item_info));
+	if (!new_curs->internal) {
+		free(new_curs);
+		return NULL;
+	}
+	new_curs->get = cursor_get;
+	new_curs->delete = cursor_delete;
+
+	new_curs->bucket = 0;
+	new_curs->pgno = INVALID_PGNO;
+	new_curs->ndx = 0;
+	new_curs->pgndx = 0;
+	new_curs->pagep = NULL;
+
+	/* place onto queue of cursors */
+	hashp = (HTAB *)dbp->internal;
+	TAILQ_INSERT_TAIL(&hashp->curs_queue, new_curs, queue);
+
+	return new_curs;
+}
+
+static int32_t
+cursor_get(dbp, cursorp, key, val, flags)
+	const DB *dbp;
+	CURSOR *cursorp;
+	DBT *key, *val;
+	u_int32_t flags;
+{
+	HTAB *hashp;
+	ITEM_INFO item_info;
+
+	hashp = (HTAB *)dbp->internal;
+
+	if (flags && flags != R_FIRST && flags != R_NEXT) {
+		hashp->local_errno = errno = EINVAL;
+		return (ERROR);
+	}
+#ifdef HASH_STATISTICS
+	hash_accesses++;
+#endif
+
+	item_info.seek_size = 0;
+
+	if (flags == R_FIRST)
+		__get_item_first(hashp, cursorp, key, val, &item_info);
+	else
+		__get_item_next(hashp, cursorp, key, val, &item_info);
+
+	/*
+	 * This needs to be changed around.  As is, get_item_next advances
+	 * the pointers on the page but this function actually advances
+	 * bucket pointers.  This works, since the only other place we 
+	 * use get_item_next is in hash_access which only deals with one
+	 * bucket at a time.  However, there is the problem that certain other
+	 * functions (such as find_bigpair and delpair) depend on the
+	 * pgndx member of the cursor.  Right now, they are using pngdx - 1
+	 * since indices refer to the __next__ item that is to be fetched
+	 * from the page.  This is ugly, as you may have noticed, whoever
+	 * you are.  The best solution would be to depend on item_infos to
+	 * deal with _current_ information, and have the cursors only
+	 * deal with _next_ information.  In that scheme, get_item_next
+	 * would also advance buckets.  Version 3...
+	 */
+
+
+	/*
+	 * Must always enter this loop to do error handling and
+	 * check for big key/data pair.
+	 */
+	while (1) {
+		if (item_info.status == ITEM_OK) {
+			if (item_info.key_off == BIGPAIR &&
+			    __big_keydata(hashp, cursorp->pagep, key, val,
+			    item_info.pgndx))
+				return (ABNORMAL);
+
+			break;
+		} else if (item_info.status != ITEM_NO_MORE)
+			return (ABNORMAL);
+
+		__put_page(hashp, cursorp->pagep, A_RAW, 0);
+		cursorp->ndx = cursorp->pgndx = 0;
+		cursorp->bucket++;
+		cursorp->pgno = INVALID_PGNO;
+		cursorp->pagep = NULL;
+		if (cursorp->bucket > hashp->hdr.max_bucket)
+			return (ABNORMAL);
+		__get_item_next(hashp, cursorp, key, val, &item_info);
+	}
+
+	__get_item_done(hashp, cursorp);
+	return (0);
+}
+
+static int32_t
+cursor_delete(dbp, cursor, flags)
+	const DB *dbp;
+	CURSOR *cursor;
+	u_int32_t flags;
+{
+	/* XXX this is empirically determined, so it might not be completely
+	   correct, but it seems to work.  At the very least it fixes
+	   a memory leak */
+ 
+	free(cursor->internal);
+	free(cursor);
+
+	return (0);
+}
+
+static int32_t
+hash_seq(dbp, key, val, flag)
+	const DB *dbp;
+	DBT *key, *val;
+	u_int32_t flag;
+{
+	HTAB *hashp;
+
+	/*
+	 * Seq just uses the default cursor to go sequecing through the
+	 * database.  Note that the default cursor is the first in the list. 
+	 */
+
+	hashp = (HTAB *)dbp->internal;
+	if (!hashp->seq_cursor)
+		hashp->seq_cursor = __cursor_creat(dbp);
+
+	return (hashp->seq_cursor->get(dbp, hashp->seq_cursor, key, val, flag));
+}
+
+/********************************* UTILITIES ************************/
+
+/*
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==> Error
+ */
+int32_t
+__expand_table(hashp)
+	HTAB *hashp;
+{
+	u_int32_t old_bucket, new_bucket;
+	int32_t spare_ndx;
+
+#ifdef HASH_STATISTICS
+	hash_expansions++;
+#endif
+	new_bucket = ++hashp->hdr.max_bucket;
+	old_bucket = (hashp->hdr.max_bucket & hashp->hdr.low_mask);
+
+	/* Get a page for this new bucket */
+	if (__new_page(hashp, new_bucket, A_BUCKET) != 0)
+		return (-1);
+
+	/*
+	 * If the split point is increasing (hdr.max_bucket's log base 2
+	 * increases), we need to copy the current contents of the spare
+	 * split bucket to the next bucket.
+	 */
+	spare_ndx = __log2(hashp->hdr.max_bucket + 1);
+	if (spare_ndx > hashp->hdr.ovfl_point) {
+		hashp->hdr.spares[spare_ndx] = hashp->hdr.spares[hashp->hdr.ovfl_point];
+		hashp->hdr.ovfl_point = spare_ndx;
+	}
+	if (new_bucket > hashp->hdr.high_mask) {
+		/* Starting a new doubling */
+		hashp->hdr.low_mask = hashp->hdr.high_mask;
+		hashp->hdr.high_mask = new_bucket | hashp->hdr.low_mask;
+	}
+	if (BUCKET_TO_PAGE(new_bucket) > MAX_PAGES(hashp)) {
+		fprintf(stderr, "hash: Cannot allocate new bucket.  Pages exhausted.\n");
+		return (-1);
+	}
+	/* Relocate records to the new bucket */
+	return (__split_page(hashp, old_bucket, new_bucket));
+}
+
+u_int32_t
+__call_hash(hashp, k, len)
+	HTAB *hashp;
+	int8_t *k;
+	int32_t len;
+{
+	int32_t n, bucket;
+
+	n = hashp->hash(k, len);
+	bucket = n & hashp->hdr.high_mask;
+	if (bucket > hashp->hdr.max_bucket)
+		bucket = bucket & hashp->hdr.low_mask;
+	return (bucket);
+}
+
+#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN
+/*
+ * Hashp->hdr needs to be byteswapped.
+ */
+static void
+swap_header_copy(srcp, destp)
+	HASHHDR *srcp, *destp;
+{
+	int32_t i;
+
+	P_32_COPY(srcp->magic, destp->magic);
+	P_32_COPY(srcp->version, destp->version);
+	P_32_COPY(srcp->lorder, destp->lorder);
+	P_32_COPY(srcp->bsize, destp->bsize);
+	P_32_COPY(srcp->bshift, destp->bshift);
+	P_32_COPY(srcp->ovfl_point, destp->ovfl_point);
+	P_32_COPY(srcp->last_freed, destp->last_freed);
+	P_32_COPY(srcp->max_bucket, destp->max_bucket);
+	P_32_COPY(srcp->high_mask, destp->high_mask);
+	P_32_COPY(srcp->low_mask, destp->low_mask);
+	P_32_COPY(srcp->ffactor, destp->ffactor);
+	P_32_COPY(srcp->nkeys, destp->nkeys);
+	P_32_COPY(srcp->hdrpages, destp->hdrpages);
+	P_32_COPY(srcp->h_charkey, destp->h_charkey);
+	for (i = 0; i < NCACHED; i++) {
+		P_32_COPY(srcp->spares[i], destp->spares[i]);
+		P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
+	}
+}
+
+static void
+swap_header(hashp)
+	HTAB *hashp;
+{
+	HASHHDR *hdrp;
+	int32_t i;
+
+	hdrp = &hashp->hdr;
+
+	M_32_SWAP(hdrp->magic);
+	M_32_SWAP(hdrp->version);
+	M_32_SWAP(hdrp->lorder);
+	M_32_SWAP(hdrp->bsize);
+	M_32_SWAP(hdrp->bshift);
+	M_32_SWAP(hdrp->ovfl_point);
+	M_32_SWAP(hdrp->last_freed);
+	M_32_SWAP(hdrp->max_bucket);
+	M_32_SWAP(hdrp->high_mask);
+	M_32_SWAP(hdrp->low_mask);
+	M_32_SWAP(hdrp->ffactor);
+	M_32_SWAP(hdrp->nkeys);
+	M_32_SWAP(hdrp->hdrpages);
+	M_32_SWAP(hdrp->h_charkey);
+	for (i = 0; i < NCACHED; i++) {
+		M_32_SWAP(hdrp->spares[i]);
+		M_16_SWAP(hdrp->bitmaps[i]);
+	}
+}
+#endif /* DB_BYTE_ORDER == DB_LITTLE_ENDIAN */
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c.patch b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c.patch
new file mode 100644
index 000000000..b72cc0d26
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.c.patch
@@ -0,0 +1,109 @@
+*** /tmp/,RCSt1a21714	Wed Apr  3 11:49:15 1996
+--- hash.c	Wed Apr  3 08:43:04 1996
+***************
+*** 399,405
+  	/* Create pages for these buckets */
+  	/*
+  	for (i = 0; i <= hashp->hdr.max_bucket; i++) {
+! 		if (__new_page(hashp, i, A_BUCKET) != 0)
+  			return (-1);
+  	}
+  	*/
+
+--- 399,405 -----
+  	/* Create pages for these buckets */
+  	/*
+  	for (i = 0; i <= hashp->hdr.max_bucket; i++) {
+! 		if (__new_page(hashp, (u_int32_t)i, A_BUCKET) != 0)
+  			return (-1);
+  	}
+  	*/
+***************
+*** 560,567
+  	 * XXX
+  	 * Check success/failure conditions.
+  	 */
+! 	mpool_sync(hashp->mp);
+! 	return (0);
+  }
+  
+  /*
+
+--- 560,566 -----
+  	 * XXX
+  	 * Check success/failure conditions.
+  	 */
+! 	return (flush_meta(hashp) || mpool_sync(hashp->mp));
+  }
+  
+  /*
+***************
+*** 585,591
+  	hput_header(hashp);
+  
+  	for (i = 0; i < NCACHED; i++)
+! 		if (hashp->mapp[i])
+  			if (__put_page(hashp,
+  			    (PAGE16 *)hashp->mapp[i], A_BITMAP, 1))
+  				return (-1);
+
+--- 584,590 -----
+  	hput_header(hashp);
+  
+  	for (i = 0; i < NCACHED; i++)
+! 		if (hashp->mapp[i]) {
+  			if (__put_page(hashp,
+  			    (PAGE16 *)hashp->mapp[i], A_BITMAP, 1))
+  				return (-1);
+***************
+*** 589,594
+  			if (__put_page(hashp,
+  			    (PAGE16 *)hashp->mapp[i], A_BITMAP, 1))
+  				return (-1);
+  	return (0);
+  }
+  
+
+--- 588,595 -----
+  			if (__put_page(hashp,
+  			    (PAGE16 *)hashp->mapp[i], A_BITMAP, 1))
+  				return (-1);
++ 			hashp->mapp[i] = NULL;
++ 		}
+  	return (0);
+  }
+  
+***************
+*** 726,732
+  #ifdef HASH_STATISTICS
+  	hash_collisions++;
+  #endif
+- 
+  	__get_item_done(hashp, &cursor);
+  
+  	/*
+
+--- 727,732 -----
+  #ifdef HASH_STATISTICS
+  	hash_collisions++;
+  #endif
+  	__get_item_done(hashp, &cursor);
+  
+  	/*
+***************
+*** 773,778
+  		if (__delpair(hashp, &cursor, &item_info) ||
+  		    __addel(hashp, &item_info, key, val, UNKNOWN, 0))
+  			return (ERROR);
+  		if (item_info.caused_expand)
+  			__expand_table(hashp);
+  		break;
+
+--- 773,779 -----
+  		if (__delpair(hashp, &cursor, &item_info) ||
+  		    __addel(hashp, &item_info, key, val, UNKNOWN, 0))
+  			return (ERROR);
++ 		__get_item_done(hashp, &cursor);
+  		if (item_info.caused_expand)
+  			__expand_table(hashp);
+  		break;
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.h
new file mode 100644
index 000000000..b202fc9f2
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash.h
@@ -0,0 +1,196 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)hash.h	8.4 (Berkeley) 11/2/95
+ */
+
+#include "mpool.h"
+#include "db-queue.h"
+
+/* Operations */
+typedef enum {
+	HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
+} ACTION;
+
+/* cursor structure */
+typedef struct cursor_t {
+	TAILQ_ENTRY(cursor_t) queue;
+	int (*get)	__P((const DB *, struct cursor_t *, DBT *, DBT *, \
+			     u_int32_t));
+	int (*delete) __P((const DB *, struct cursor_t *, u_int32_t));
+	db_pgno_t	bucket;
+	db_pgno_t	pgno;
+	indx_t	ndx;
+	indx_t	pgndx;
+	u_int16_t *pagep;
+	void *internal;
+} CURSOR;
+
+
+#define IS_BUCKET(X)	((X) & BUF_BUCKET)
+#define IS_VALID(X)     (!((X) & BUF_INVALID))
+
+/* Hash Table Information */
+typedef struct hashhdr {	/* Disk resident portion */
+	int32_t	magic;		/* Magic NO for hash tables */
+	int32_t	version;	/* Version ID */
+	int32_t	lorder;		/* Byte Order */
+	int32_t	bsize;		/* Bucket/Page Size */
+	int32_t	bshift;		/* Bucket shift */
+	int32_t	ovfl_point;	/* Where overflow pages are being allocated */
+	int32_t	last_freed;	/* Last overflow page freed */
+	int32_t	max_bucket;	/* ID of Maximum bucket in use */
+	int32_t	high_mask;	/* Mask to modulo into entire table */
+	int32_t	low_mask;	/* Mask to modulo into lower half of table */
+	int32_t	ffactor;	/* Fill factor */
+	int32_t	nkeys;		/* Number of keys in hash table */
+	int32_t	hdrpages;	/* Size of table header */
+	int32_t	h_charkey;	/* value of hash(CHARKEY) */
+#define NCACHED	32		/* number of bit maps and spare points */
+	int32_t	spares[NCACHED];/* spare pages for overflow */
+	u_int16_t	bitmaps[NCACHED];	/* address of overflow page bitmaps */
+} HASHHDR;
+
+typedef struct htab {		/* Memory resident data structure */
+	TAILQ_HEAD(_cursor_queue, cursor_t) curs_queue;
+	HASHHDR hdr;		/* Header */
+	u_int32_t (*hash) __P((const void *, size_t)); /* Hash Function */
+	int32_t	flags;		/* Flag values */
+	int32_t	fp;		/* File pointer */
+	const char *fname;        	/* File path */
+	u_int8_t *bigdata_buf;	/* Temporary Buffer for BIG data */
+	u_int8_t *bigkey_buf;	/* Temporary Buffer for BIG keys */
+	u_int16_t  *split_buf;	/* Temporary buffer for splits */
+	CURSOR	*seq_cursor;	/* Cursor used for hash_seq */
+	int32_t	local_errno;	/* Error Number -- for DBM compatability */
+	int32_t	new_file;	/* Indicates if fd is backing store or no */
+	int32_t	save_file;	/* Indicates whether we need to flush file at
+				 * exit */
+	u_int32_t *mapp[NCACHED];/* Pointers to page maps */
+	int32_t	nmaps;		/* Initial number of bitmaps */
+	MPOOL	*mp;		/* mpool for buffer management */
+} HTAB;
+
+/*
+ * Constants
+ */
+#define	MAX_BSIZE		65536		/* 2^16 */
+#define MIN_BUFFERS		6
+#define MINHDRSIZE		512
+#define DEF_CACHESIZE	65536
+#define DEF_BUCKET_SHIFT	12		/* log2(BUCKET) */
+#define DEF_BUCKET_SIZE		(1<<DEF_BUCKET_SHIFT)
+#define DEF_SEGSIZE_SHIFT	8		/* log2(SEGSIZE)	 */
+#define DEF_SEGSIZE		(1<<DEF_SEGSIZE_SHIFT)
+#define DEF_DIRSIZE		256
+#define DEF_FFACTOR		65536
+#define MIN_FFACTOR		4
+#define SPLTMAX			8
+#define CHARKEY			"%$sniglet^&"
+#define NUMKEY			1038583
+#define BYTE_SHIFT		3
+#define INT32_T_TO_BYTE		2
+#define INT32_T_BYTE_SHIFT		5
+#define ALL_SET			((u_int32_t)0xFFFFFFFF)
+#define ALL_CLEAR		0
+
+#define PTROF(X)	((BUFHEAD *)((ptr_t)(X)&~0x3))
+#define ISMOD(X)	((ptr_t)(X)&0x1)
+#define DOMOD(X)	((X) = (int8_t *)((ptr_t)(X)|0x1))
+#define ISDISK(X)	((ptr_t)(X)&0x2)
+#define DODISK(X)	((X) = (int8_t *)((ptr_t)(X)|0x2))
+
+#define BITS_PER_MAP	32
+
+/* Given the address of the beginning of a big map, clear/set the nth bit */
+#define CLRBIT(A, N)	((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
+#define SETBIT(A, N)	((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
+#define ISSET(A, N)	((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
+
+/* Overflow management */
+/*
+ * Overflow page numbers are allocated per split point.  At each doubling of
+ * the table, we can allocate extra pages.  So, an overflow page number has
+ * the top 5 bits indicate which split point and the lower 11 bits indicate
+ * which page at that split point is indicated (pages within split points are
+ * numberered starting with 1).
+ */
+
+#define SPLITSHIFT	11
+#define SPLITMASK	0x7FF
+#define SPLITNUM(N)	(((u_int32_t)(N)) >> SPLITSHIFT)
+#define OPAGENUM(N)	((N) & SPLITMASK)
+#define	OADDR_OF(S,O)	((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O))
+
+#define BUCKET_TO_PAGE(B) \
+	((B) + hashp->hdr.hdrpages + ((B) \
+	    ? hashp->hdr.spares[__log2((B)+1)-1] : 0))
+#define OADDR_TO_PAGE(B) 	\
+	(BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)))
+
+#define POW2(N)  (1 << (N))
+
+#define MAX_PAGES(H) (DB_OFF_T_MAX / (H)->hdr.bsize)
+
+/* Shorthands for accessing structure */
+#define METADATA_PGNO 0
+#define SPLIT_PGNO 0xFFFF
+
+typedef struct item_info {
+	db_pgno_t 		pgno;
+	db_pgno_t		bucket;
+	indx_t		ndx;
+	indx_t		pgndx;
+	u_int8_t	status;
+	int32_t		seek_size;
+	db_pgno_t		seek_found_page;
+	indx_t		key_off;
+	indx_t		data_off;
+	u_int8_t	caused_expand;
+} ITEM_INFO;
+
+
+#define	ITEM_ERROR	0
+#define	ITEM_OK		1
+#define	ITEM_NO_MORE	2
+
+#define	ITEM_GET_FIRST	0
+#define	ITEM_GET_NEXT	1
+#define	ITEM_GET_RESET	2
+#define	ITEM_GET_DONE	3
+#define	ITEM_GET_N	4
+
+#define	UNKNOWN		0xffffffff		/* for num_items */
+#define	NO_EXPAND	0xfffffffe 
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c
new file mode 100644
index 000000000..06210a57c
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c
@@ -0,0 +1,483 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_bigkey.c	8.5 (Berkeley) 11/2/95";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE: hash
+ * DESCRIPTION:
+ *	Big key/data handling for the hashing package.
+ *
+ * ROUTINES:
+ * External
+ *	__big_keydata
+ *	__big_split
+ *	__big_insert
+ *	__big_return
+ *	__big_delete
+ *	__find_last_page
+ * Internal
+ *	collect_key
+ *	collect_data
+ */
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include "db-int.h"
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int32_t collect_key __P((HTAB *, PAGE16 *, int32_t, db_pgno_t *));
+static int32_t collect_data __P((HTAB *, PAGE16 *, int32_t));
+
+/*
+ * Big_insert
+ *
+ * You need to do an insert and the key/data pair is greater than 
+ * MINFILL * the bucket size
+ *
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==> ERROR
+ */
+int32_t
+__big_insert(hashp, pagep, key, val)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	const DBT *key, *val;
+{
+	size_t  key_size, val_size;
+	indx_t  key_move_bytes, val_move_bytes;
+	int8_t *key_data, *val_data, base_page;
+
+	key_data = (int8_t *)key->data;
+	key_size = key->size;
+	val_data = (int8_t *)val->data;
+	val_size = val->size;
+
+	NUM_ENT(pagep) = NUM_ENT(pagep) + 1;
+
+	for (base_page = 1; key_size + val_size;) {
+		/* Add a page! */
+		pagep =
+		    __add_bigpage(hashp, pagep, NUM_ENT(pagep) - 1, base_page);
+		if (!pagep)
+			return (-1);
+
+		/* There's just going to be one entry on this page. */
+		NUM_ENT(pagep) = 1;
+
+		/* Move the key's data. */
+		key_move_bytes = MIN(FREESPACE(pagep), key_size);
+		/* Mark the page as to how much key & data is on this page. */
+		BIGKEYLEN(pagep) = key_move_bytes;
+		val_move_bytes =
+		    MIN(FREESPACE(pagep) - key_move_bytes, val_size);
+		BIGDATALEN(pagep) = val_move_bytes;
+
+		/* Note big pages build beginning --> end, not vice versa. */
+		if (key_move_bytes)
+			memmove(BIGKEY(pagep), key_data, key_move_bytes);
+		if (val_move_bytes)
+			memmove(BIGDATA(pagep), val_data, val_move_bytes);
+
+		key_size -= key_move_bytes;
+		key_data += key_move_bytes;
+		val_size -= val_move_bytes;
+		val_data += val_move_bytes;
+
+		base_page = 0;
+	}
+	__put_page(hashp, pagep, A_RAW, 1);
+	return (0);
+}
+
+/*
+ * Called when we need to delete a big pair.
+ *
+ * Returns:
+ *	 0 => OK
+ *	-1 => ERROR
+ */
+int32_t
+#ifdef __STDC__
+__big_delete(HTAB *hashp, PAGE16 *pagep, indx_t ndx)
+#else
+__big_delete(hashp, pagep, ndx)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	u_int32_t ndx;		/* Index of big pair on base page. */
+#endif
+{
+	PAGE16 *last_pagep;
+
+	/* Get first page with big key/data. */
+	pagep = __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW);
+	if (!pagep)
+		return (-1);
+
+	/*
+	 * Traverse through the pages, freeing the previous one (except
+	 * the first) at each new page.
+	 */
+	while (NEXT_PGNO(pagep) != INVALID_PGNO) {
+		last_pagep = pagep;
+		pagep = __get_page(hashp, NEXT_PGNO(pagep), A_RAW);
+		if (!pagep)
+			return (-1);
+		__delete_page(hashp, last_pagep, A_OVFL);
+	}
+
+	/* Free the last page in the chain. */
+	__delete_page(hashp, pagep, A_OVFL);
+	return (0);
+}
+
+/*
+ * Given a key, indicates whether the big key at cursorp matches the
+ * given key.
+ *
+ * Returns:
+ *	 1 = Found!
+ *	 0 = Key not found
+ *	-1 error
+ */
+int32_t
+__find_bigpair(hashp, cursorp, key, size)
+	HTAB *hashp;
+	CURSOR *cursorp;
+	int8_t *key;
+	int32_t size;
+{
+	PAGE16 *pagep, *hold_pagep;
+	db_pgno_t  next_pgno;
+	int32_t ksize;
+	u_int16_t bytes;
+	int8_t *kkey;
+
+	ksize = size;
+	kkey = key;
+	bytes = 0;
+
+	hold_pagep = NULL;
+	/* Chances are, hashp->cpage is the base page. */
+	if (cursorp->pagep)
+		pagep = hold_pagep = cursorp->pagep;
+	else {
+		pagep = __get_page(hashp, cursorp->pgno, A_RAW);
+		if (!pagep)
+			return (-1);
+	}
+
+	/*
+	 * Now, get the first page with the big stuff on it.
+	 *
+	 * XXX
+	 * KLUDGE: we know that cursor is looking at the _next_ item, so
+	 * we have to look at pgndx - 1.
+	 */
+	next_pgno = OADDR_TO_PAGE(DATA_OFF(pagep, (cursorp->pgndx - 1)));
+	if (!hold_pagep)
+		__put_page(hashp, pagep, A_RAW, 0);
+	pagep = __get_page(hashp, next_pgno, A_RAW);
+	if (!pagep)
+		return (-1);
+
+	/* While there are both keys to compare. */
+	while ((ksize > 0) && (BIGKEYLEN(pagep))) {
+		if (ksize < KEY_OFF(pagep, 0) ||
+		    memcmp(BIGKEY(pagep), kkey, BIGKEYLEN(pagep))) {
+			__put_page(hashp, pagep, A_RAW, 0);
+			return (0);
+		}
+		kkey += BIGKEYLEN(pagep);
+		ksize -= BIGKEYLEN(pagep);
+		if (NEXT_PGNO(pagep) != INVALID_PGNO) {
+			next_pgno = NEXT_PGNO(pagep);
+			__put_page(hashp, pagep, A_RAW, 0);
+			pagep = __get_page(hashp, next_pgno, A_RAW);
+			if (!pagep)
+				return (-1);
+		}
+	}
+	__put_page(hashp, pagep, A_RAW, 0);
+#ifdef DEBUG
+	assert(ksize >= 0);
+#endif
+	if (ksize != 0) {
+#ifdef HASH_STATISTICS
+		++hash_collisions;
+#endif
+		return (0);
+	} else
+		return (1);
+}
+
+/*
+ * Fill in the key and data for this big pair.
+ */
+int32_t
+__big_keydata(hashp, pagep, key, val, ndx)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	DBT *key, *val;
+	int32_t ndx;
+{
+	ITEM_INFO ii;
+	PAGE16 *key_pagep;
+	db_pgno_t last_page;
+
+	key_pagep =
+	    __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW);
+	if (!key_pagep)
+		return (-1);
+	key->size = collect_key(hashp, key_pagep, 0, &last_page);
+	key->data = hashp->bigkey_buf;
+	__put_page(hashp, key_pagep, A_RAW, 0);
+
+	if (key->size == -1)
+		return (-1);
+
+	/* Create an item_info to direct __big_return to the beginning pgno. */
+	ii.pgno = last_page;
+	return (__big_return(hashp, &ii, val, 1));
+}
+
+/*
+ * Return the big key on page, ndx.
+ */
+int32_t
+#ifdef __STDC__
+__get_bigkey(HTAB *hashp, PAGE16 *pagep, indx_t ndx, DBT *key)
+#else
+__get_bigkey(hashp, pagep, ndx, key)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	u_int32_t ndx;
+	DBT *key;
+#endif
+{
+	PAGE16 *key_pagep;
+
+	key_pagep =
+	    __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW);
+	if (!pagep)
+		return (-1);
+	key->size = collect_key(hashp, key_pagep, 0, NULL);
+	key->data = hashp->bigkey_buf;
+
+	__put_page(hashp, key_pagep, A_RAW, 0);
+
+	return (0);
+}
+
+/*
+ * Return the big key and data indicated in item_info.
+ */
+int32_t
+__big_return(hashp, item_info, val, on_bigkey_page)
+	HTAB *hashp;
+	ITEM_INFO *item_info;
+	DBT *val;
+	int32_t on_bigkey_page;
+{
+	PAGE16 *pagep;
+	db_pgno_t next_pgno;
+
+	if (!on_bigkey_page) {
+		/* Get first page with big pair on it. */
+		pagep = __get_page(hashp,
+		    OADDR_TO_PAGE(item_info->data_off), A_RAW);
+		if (!pagep)
+			return (-1);
+	} else {
+		pagep = __get_page(hashp, item_info->pgno, A_RAW);
+		if (!pagep)
+			return (-1);
+	}
+
+	/* Traverse through the bigkey pages until a page with data is found. */
+	while (!BIGDATALEN(pagep)) {
+		next_pgno = NEXT_PGNO(pagep);
+		__put_page(hashp, pagep, A_RAW, 0);
+		pagep = __get_page(hashp, next_pgno, A_RAW);
+		if (!pagep)
+			return (-1);
+	}
+
+	val->size = collect_data(hashp, pagep, 0);
+	if (val->size < 1)
+		return (-1);
+	val->data = (void *)hashp->bigdata_buf;
+
+	__put_page(hashp, pagep, A_RAW, 0);
+	return (0);
+}
+
+/*
+ * Given a page with a big key on it, traverse through the pages counting data
+ * length, and collect all of the data on the way up.  Store the key in
+ * hashp->bigkey_buf.  last_page indicates to the calling function what the
+ * last page with key on it is; this will help if you later want to retrieve
+ * the data portion.
+ *
+ * Does the work for __get_bigkey.
+ *
+ * Return total length of data; -1 if error.
+ */
+static int32_t
+collect_key(hashp, pagep, len, last_page)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	int32_t len;
+	db_pgno_t *last_page;
+{
+	PAGE16 *next_pagep;
+	int32_t totlen, retval;
+	db_pgno_t next_pgno;
+#ifdef DEBUG
+	db_pgno_t save_addr;
+#endif
+
+	/* If this is the last page with key. */
+	if (BIGDATALEN(pagep)) {
+		totlen = len + BIGKEYLEN(pagep);
+		if (hashp->bigkey_buf)
+			free(hashp->bigkey_buf);
+		hashp->bigkey_buf = (u_int8_t *)malloc(totlen);
+		if (!hashp->bigkey_buf)
+			return (-1);
+		memcpy(hashp->bigkey_buf + len,
+		    BIGKEY(pagep), BIGKEYLEN(pagep));
+		if (last_page)
+			*last_page = ADDR(pagep);
+		return (totlen);
+	}
+
+	/* Key filled up all of last key page, so we've gone 1 too far. */
+	if (BIGKEYLEN(pagep) == 0) {
+		if (hashp->bigkey_buf)
+			free(hashp->bigkey_buf);
+		hashp->bigkey_buf = (u_int8_t *)malloc(len);
+		return (hashp->bigkey_buf ? len : -1);
+	}
+	totlen = len + BIGKEYLEN(pagep);
+
+	/* Set pagep to the next page in the chain. */
+	if (last_page)
+		*last_page = ADDR(pagep);
+	next_pgno = NEXT_PGNO(pagep);
+	next_pagep = __get_page(hashp, next_pgno, A_RAW);
+	if (!next_pagep)
+		return (-1);
+#ifdef DEBUG
+	save_addr = ADDR(pagep);
+#endif
+	retval = collect_key(hashp, next_pagep, totlen, last_page);
+
+#ifdef DEBUG
+	assert(save_addr == ADDR(pagep));
+#endif
+	memcpy(hashp->bigkey_buf + len, BIGKEY(pagep), BIGKEYLEN(pagep));
+	__put_page(hashp, next_pagep, A_RAW, 0);
+
+	return (retval);
+}
+
+/*
+ * Given a page with big data on it, recur through the pages counting data
+ * length, and collect all of the data on the way up.  Store the data in
+ * hashp->bigdata_buf.
+ *
+ * Does the work for __big_return.
+ *
+ * Return total length of data; -1 if error.
+ */
+static int32_t
+collect_data(hashp, pagep, len)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	int32_t len;
+{
+	PAGE16 *next_pagep;
+	int32_t totlen, retval;
+	db_pgno_t next_pgno;
+#ifdef DEBUG
+	db_pgno_t save_addr;
+#endif
+
+	/* If there is no next page. */
+	if (NEXT_PGNO(pagep) == INVALID_PGNO) {
+		if (hashp->bigdata_buf)
+			free(hashp->bigdata_buf);
+		totlen = len + BIGDATALEN(pagep);
+		hashp->bigdata_buf = (u_int8_t *)malloc(totlen);
+		if (!hashp->bigdata_buf)
+			return (-1);
+		memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep),
+		    BIGDATA(pagep), BIGDATALEN(pagep));
+		return (totlen);
+	}
+	totlen = len + BIGDATALEN(pagep);
+
+	/* Set pagep to the next page in the chain. */
+	next_pgno = NEXT_PGNO(pagep);
+	next_pagep = __get_page(hashp, next_pgno, A_RAW);
+	if (!next_pagep)
+		return (-1);
+
+#ifdef DEBUG
+	save_addr = ADDR(pagep);
+#endif
+	retval = collect_data(hashp, next_pagep, totlen);
+#ifdef DEBUG
+	assert(save_addr == ADDR(pagep));
+#endif
+	memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep),
+	    BIGDATA(pagep), BIGDATALEN(pagep));
+	__put_page(hashp, next_pagep, A_RAW, 0);
+
+	return (retval);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_debug.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_debug.c
new file mode 100644
index 000000000..69229fc8d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_debug.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1995
+ *	The President and Fellows of Harvard University
+ *
+ * This code is derived from software contributed to Harvard by
+ * Jeremy Rassen.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_debug.c	8.4 (Berkeley) 11/7/95";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef DEBUG
+/*
+ * PACKAGE:  hashing
+ *
+ * DESCRIPTION:
+ *	Debug routines.
+ *
+ * ROUTINES:
+ *
+ * External
+ *	__dump_bucket
+ */
+#include <stdio.h>
+
+#include "db-int.h"
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+void
+__dump_bucket(hashp, bucket)
+	HTAB *hashp;
+	u_int32_t bucket;
+{
+	CURSOR cursor;
+	DBT key, val;
+	ITEM_INFO item_info;
+	int var;
+	char *cp;
+
+	cursor.pagep = NULL;
+	item_info.seek_size = 0;
+	item_info.seek_found_page = 0;
+
+	__get_item_reset(hashp, &cursor);
+
+	cursor.bucket = bucket;
+	for (;;) {
+		__get_item_next(hashp, &cursor, &key, &val, &item_info);
+		if (item_info.status == ITEM_ERROR) {
+			(void)printf("get_item_next returned error\n");
+			break;
+		} else if (item_info.status == ITEM_NO_MORE)
+			break;
+
+		if (item_info.key_off == BIGPAIR) {
+			if (__big_keydata(hashp, cursor.pagep, &key, &val,
+			    item_info.pgndx)) {
+				(void)printf("__big_keydata returned error\n");
+				break;
+			}
+		}
+
+		if (key.size == sizeof(int)) {
+			memcpy(&var, key.data, sizeof(int));
+			(void)printf("%d\n", var);
+		} else {
+			for (cp = (char *)key.data; key.size--; cp++)
+				(void)printf("%c", *cp);
+			(void)printf("\n");
+		}
+	}
+	__get_item_done(hashp, &cursor);
+}
+#endif /* DEBUG */
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_func.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_func.c
new file mode 100644
index 000000000..1dee69460
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_func.c
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_func.c	8.4 (Berkeley) 11/7/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include "db-int.h"
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+#if 0
+static u_int32_t hash1 __P((const void *, size_t));
+static u_int32_t hash2 __P((const void *, size_t));
+static u_int32_t hash3 __P((const void *, size_t));
+#endif
+static u_int32_t hash4 __P((const void *, size_t));
+
+/* Default hash function. */
+u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4;
+
+/*
+ * Assume that we've already split the bucket to which this key hashes,
+ * calculate that bucket, and check that in fact we did already split it.
+ *
+ * EJB's original hsearch hash.
+ */
+#define PRIME1		37
+#define PRIME2		1048583
+
+#if 0
+static u_int32_t
+hash1(key, len)
+	const void *key;
+	size_t len;
+{
+	u_int32_t h;
+	u_int8_t *k;
+
+	h = 0;
+	k = (u_int8_t *)key;
+	/* Convert string to integer */
+	while (len--)
+		h = h * PRIME1 ^ (*k++ - ' ');
+	h %= PRIME2;
+	return (h);
+}
+
+/*
+ * Phong Vo's linear congruential hash
+ */
+#define dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
+
+static u_int32_t
+hash2(key, len)
+	const void *key;
+	size_t len;
+{
+	u_int32_t h;
+	u_int8_t *e, c, *k;
+
+	k = (u_int8_t *)key;
+	e = k + len;
+	for (h = 0; k != e;) {
+		c = *k++;
+		if (!c && k > e)
+			break;
+		dcharhash(h, c);
+	}
+	return (h);
+}
+
+/*
+ * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
+ * units.  On the first time through the loop we get the "leftover bytes"
+ * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
+ * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
+ * this routine is heavily used enough, it's worth the ugly coding.
+ *
+ * Ozan Yigit's original sdbm hash.
+ */
+static u_int32_t
+hash3(key, len)
+	const void *key;
+	size_t len;
+{
+	u_int32_t n, loop;
+	u_int8_t *k;
+
+#define HASHC   n = *k++ + 65599 * n
+
+	n = 0;
+	k = (u_int8_t *)key;
+	if (len > 0) {
+		loop = (len + 8 - 1) >> 3;
+
+		switch (len & (8 - 1)) {
+		case 0:
+			do {	/* All fall throughs */
+				HASHC;
+		case 7:
+				HASHC;
+		case 6:
+				HASHC;
+		case 5:
+				HASHC;
+		case 4:
+				HASHC;
+		case 3:
+				HASHC;
+		case 2:
+				HASHC;
+		case 1:
+				HASHC;
+			} while (--loop);
+		}
+
+	}
+	return (n);
+}
+#endif
+
+
+/* Chris Torek's hash function. */
+static u_int32_t
+hash4(key, len)
+	const void *key;
+	size_t len;
+{
+	u_int32_t h, loop;
+	const u_int8_t *k;
+
+#define HASH4a   h = (h << 5) - h + *k++;
+#define HASH4b   h = (h << 5) + h + *k++;
+#define HASH4 HASH4b
+
+	h = 0;
+	k = (const u_int8_t *)key;
+	if (len > 0) {
+		loop = (len + 8 - 1) >> 3;
+
+		switch (len & (8 - 1)) {
+		case 0:
+			do {	/* All fall throughs */
+				HASH4;
+		case 7:
+				HASH4;
+		case 6:
+				HASH4;
+		case 5:
+				HASH4;
+		case 4:
+				HASH4;
+		case 3:
+				HASH4;
+		case 2:
+				HASH4;
+		case 1:
+				HASH4;
+			} while (--loop);
+		}
+
+	}
+	return (h);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_log2.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_log2.c
new file mode 100644
index 000000000..8c710e5d2
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_log2.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_log2.c	8.4 (Berkeley) 11/7/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include "db-int.h"
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+u_int32_t
+__kdb2_log2(num)
+	u_int32_t num;
+{
+	u_int32_t i, limit;
+
+	limit = 1;
+	for (i = 0; limit < num; limit = limit << 1, i++);
+	return (i);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_page.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_page.c
new file mode 100644
index 000000000..e25115d3f
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hash_page.c
@@ -0,0 +1,1387 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_page.c	8.11 (Berkeley) 11/7/95";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE:  hashing
+ *
+ * DESCRIPTION:
+ *      Page manipulation for hashing package.
+ *
+ * ROUTINES:
+ *
+ * External
+ *      __get_page
+ *      __add_ovflpage
+ * Internal
+ *      overflow_page
+ *      open_temp
+ */
+
+#include <sys/types.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int32_t	 add_bigptr __P((HTAB *, ITEM_INFO *, indx_t));
+static u_int32_t *fetch_bitmap __P((HTAB *, int32_t));
+static u_int32_t first_free __P((u_int32_t));
+static indx_t	 next_realkey __P((PAGE16 *, indx_t));
+static u_int16_t overflow_page __P((HTAB *));
+static void	 page_init __P((HTAB *, PAGE16 *, db_pgno_t, u_int8_t));
+static indx_t	 prev_realkey __P((PAGE16 *, indx_t));
+static void	 putpair __P((PAGE8 *, const DBT *, const DBT *));
+static void	 swap_page_header_in __P((PAGE16 *));
+static void	 swap_page_header_out __P((PAGE16 *));
+
+#ifdef DEBUG_SLOW
+static void	 account_page(HTAB *, db_pgno_t, int);
+#endif
+
+u_int32_t
+__get_item(hashp, cursorp, key, val, item_info)
+	HTAB *hashp;
+	CURSOR *cursorp;
+	DBT *key, *val;
+	ITEM_INFO *item_info;
+{
+	db_pgno_t next_pgno;
+	int32_t i;
+
+	/* Check if we need to get a page. */
+	if (!cursorp->pagep) {
+		if (cursorp->pgno == INVALID_PGNO) {
+			cursorp->pagep =
+			    __get_page(hashp, cursorp->bucket, A_BUCKET);
+			cursorp->pgno = ADDR(cursorp->pagep);
+			cursorp->ndx = 0;
+			cursorp->pgndx = 0;
+		} else 
+			cursorp->pagep =
+			    __get_page(hashp, cursorp->pgno, A_RAW);
+		if (!cursorp->pagep) {
+			item_info->status = ITEM_ERROR;
+			return (-1);
+		}
+	}
+	if (item_info->seek_size &&
+	    FREESPACE(cursorp->pagep) > item_info->seek_size)
+		item_info->seek_found_page = cursorp->pgno;
+
+	if (cursorp->pgndx == NUM_ENT(cursorp->pagep)) {
+		/* Fetch next page. */
+		if (NEXT_PGNO(cursorp->pagep) == INVALID_PGNO) {
+			item_info->status = ITEM_NO_MORE;
+			return (-1);
+		}
+		next_pgno = NEXT_PGNO(cursorp->pagep);
+		cursorp->pgndx = 0;
+		__put_page(hashp, cursorp->pagep, A_RAW, 0);
+		cursorp->pagep = __get_page(hashp, next_pgno, A_RAW);
+		if (!cursorp->pagep) {
+			item_info->status = ITEM_ERROR;
+			return (-1);
+		}
+		cursorp->pgno = next_pgno;
+	}
+	if (KEY_OFF(cursorp->pagep, cursorp->pgndx) != BIGPAIR) {
+		if ((i = prev_realkey(cursorp->pagep, cursorp->pgndx)) ==
+		    cursorp->pgndx)
+			key->size = hashp->hdr.bsize -
+			    KEY_OFF(cursorp->pagep, cursorp->pgndx);
+		else
+			key->size = DATA_OFF(cursorp->pagep, i) -
+			    KEY_OFF(cursorp->pagep, cursorp->pgndx);
+	}
+
+	/* 
+	 * All of this information will be set incorrectly for big keys, but
+	 * it will be ignored anyway.
+	 */
+	val->size = KEY_OFF(cursorp->pagep, cursorp->pgndx) -
+	    DATA_OFF(cursorp->pagep, cursorp->pgndx);
+	key->data = KEY(cursorp->pagep, cursorp->pgndx);
+	val->data = DATA(cursorp->pagep, cursorp->pgndx);
+	item_info->pgno = cursorp->pgno;
+	item_info->bucket = cursorp->bucket;
+	item_info->ndx = cursorp->ndx;
+	item_info->pgndx = cursorp->pgndx;
+	item_info->key_off = KEY_OFF(cursorp->pagep, cursorp->pgndx);
+	item_info->data_off = DATA_OFF(cursorp->pagep, cursorp->pgndx);
+	item_info->status = ITEM_OK;
+
+	return (0);
+}
+
+u_int32_t
+__get_item_reset(hashp, cursorp)
+	HTAB *hashp;
+	CURSOR *cursorp;
+{
+	if (cursorp->pagep)
+		__put_page(hashp, cursorp->pagep, A_RAW, 0);
+	cursorp->pagep = NULL;
+	cursorp->bucket = -1;
+	cursorp->ndx = 0;
+	cursorp->pgndx = 0;
+	cursorp->pgno = INVALID_PGNO;
+	return (0);
+}
+
+u_int32_t
+__get_item_done(hashp, cursorp)
+	HTAB *hashp;
+	CURSOR *cursorp;
+{
+	if (cursorp->pagep)
+		__put_page(hashp, cursorp->pagep, A_RAW, 0);
+	cursorp->pagep = NULL;
+
+	/* 
+	 * We don't throw out the page number since we might want to
+	 * continue getting on this page.
+	 */
+	return (0);
+}
+
+u_int32_t
+__get_item_first(hashp, cursorp, key, val, item_info)
+	HTAB *hashp;
+	CURSOR *cursorp;
+	DBT *key, *val;
+	ITEM_INFO *item_info;
+{
+	__get_item_reset(hashp, cursorp);
+	cursorp->bucket = 0;
+	return (__get_item_next(hashp, cursorp, key, val, item_info));
+}
+
+/*
+ * Returns a pointer to key/data pair on a page.  In the case of bigkeys,
+ * just returns the page number and index of the bigkey pointer pair.
+ */
+u_int32_t
+__get_item_next(hashp, cursorp, key, val, item_info)
+	HTAB *hashp;
+	CURSOR *cursorp;
+	DBT *key, *val;
+	ITEM_INFO *item_info;
+{
+	int status;
+
+	status = __get_item(hashp, cursorp, key, val, item_info);
+	cursorp->ndx++;
+	cursorp->pgndx++;
+	return (status);
+}
+
+/*
+ * Put a non-big pair on a page.
+ */
+static void
+putpair(p, key, val)
+	PAGE8 *p;
+	const DBT *key, *val;
+{
+	u_int16_t *pagep, n, off;
+
+	pagep = (PAGE16 *)p;
+
+	/* Items on the page are 0-indexed. */
+	n = NUM_ENT(pagep);
+	off = OFFSET(pagep) - key->size + 1;
+	memmove(p + off, key->data, key->size);
+	KEY_OFF(pagep, n) = off;
+
+	off -= val->size;
+	memmove(p + off, val->data, val->size);
+	DATA_OFF(pagep, n) = off;
+
+	/* Adjust page info. */
+	NUM_ENT(pagep) = n + 1;
+	OFFSET(pagep) = off - 1;
+}
+
+/*
+ * Returns the index of the next non-bigkey pair after n on the page.
+ * Returns -1 if there are no more non-big things on the page.
+ */
+static indx_t
+#ifdef __STDC__
+next_realkey(PAGE16 * pagep, indx_t n)
+#else
+next_realkey(pagep, n)
+	PAGE16 *pagep;
+	u_int32_t n;
+#endif
+{
+	indx_t i;
+
+	for (i = n + 1; i < NUM_ENT(pagep); i++)
+		if (KEY_OFF(pagep, i) != BIGPAIR)
+			return (i);
+	return (-1);
+}
+
+/*
+ * Returns the index of the previous non-bigkey pair after n on the page.
+ * Returns n if there are no previous non-big things on the page.
+ */
+static indx_t
+#ifdef __STDC__
+prev_realkey(PAGE16 * pagep, indx_t n)
+#else
+prev_realkey(pagep, n)
+	PAGE16 *pagep;
+	u_int32_t n;
+#endif
+{
+	int32_t i;
+
+	/* Need a signed value to do the compare properly. */
+	for (i = n - 1; i > -1; i--)
+		if (KEY_OFF(pagep, i) != BIGPAIR)
+			return (i);
+	return (n);
+}
+
+/*
+ * Returns:
+ *       0 OK
+ *      -1 error
+ */
+extern int32_t
+__delpair(hashp, cursorp, item_info)
+	HTAB *hashp;
+	CURSOR *cursorp;
+	ITEM_INFO *item_info;
+{
+	PAGE16 *pagep;
+	indx_t ndx;
+	short check_ndx;
+	int16_t delta, len, next_key;
+	int32_t n;
+	u_int8_t *src, *dest;
+
+	ndx = cursorp->pgndx;
+	if (!cursorp->pagep) {
+		pagep = __get_page(hashp, cursorp->pgno, A_RAW);
+		if (!pagep)
+			return (-1);
+		/*
+		 * KLUGE: pgndx has gone one too far, because cursor points
+		 * to the _next_ item.  Use pgndx - 1.
+		 */
+		--ndx;
+	} else
+		pagep = cursorp->pagep;
+#ifdef DEBUG
+	assert(ADDR(pagep) == cursorp->pgno);
+#endif
+
+	if (KEY_OFF(pagep, ndx) == BIGPAIR) {
+		delta = 0;
+		__big_delete(hashp, pagep, ndx);
+	} else {
+		/*
+		 * Compute "delta", the amount we have to shift all of the
+		 * offsets.  To find the delta, we need to make sure that
+		 * we aren't looking at the DATA_OFF of a big/keydata pair.
+		 */
+		for (check_ndx = (short)(ndx - 1);
+		    check_ndx >= 0 && KEY_OFF(pagep, check_ndx) == BIGPAIR;
+		    check_ndx--);
+		if (check_ndx < 0)
+			delta = hashp->hdr.bsize - DATA_OFF(pagep, ndx);
+		else
+			delta =
+			    DATA_OFF(pagep, check_ndx) - DATA_OFF(pagep, ndx);
+
+		/*
+		 * The hard case: we want to remove something other than
+		 * the last item on the page.  We need to shift data and
+		 * offsets down.
+		 */
+		if (ndx != NUM_ENT(pagep) - 1) {
+			/*
+			 * Move the data: src is the address of the last data
+			 * item on the page.
+			 */
+			src = (u_int8_t *)pagep + OFFSET(pagep) + 1;
+			/* 
+			 * Length is the distance between where to start
+			 * deleting and end of the data on the page.
+			 */
+			len = DATA_OFF(pagep, ndx) - (OFFSET(pagep) + 1);
+			/*
+			 * Dest is the location of the to-be-deleted item
+			 * occupied - length.
+			 */
+			if (check_ndx < 0)
+				dest =
+				    (u_int8_t *)pagep + hashp->hdr.bsize - len;
+			else
+				dest = (u_int8_t *)pagep +
+				    DATA_OFF(pagep, (check_ndx)) - len;
+			memmove(dest, src, len);
+		}
+	}
+
+	/* Adjust the offsets. */
+	for (n = ndx; n < NUM_ENT(pagep) - 1; n++)
+		if (KEY_OFF(pagep, (n + 1)) != BIGPAIR) {
+			next_key = next_realkey(pagep, n);
+#ifdef DEBUG
+			assert(next_key != -1);
+#endif
+			KEY_OFF(pagep, n) = KEY_OFF(pagep, (n + 1)) + delta;
+			DATA_OFF(pagep, n) = DATA_OFF(pagep, (n + 1)) + delta;
+		} else {
+			KEY_OFF(pagep, n) = KEY_OFF(pagep, (n + 1));
+			DATA_OFF(pagep, n) = DATA_OFF(pagep, (n + 1));
+		}
+
+	/* Adjust page metadata. */
+	OFFSET(pagep) = OFFSET(pagep) + delta;
+	NUM_ENT(pagep) = NUM_ENT(pagep) - 1;
+
+	--hashp->hdr.nkeys;
+
+	/* Is this page now an empty overflow page?  If so, free it. */
+	if (TYPE(pagep) == HASH_OVFLPAGE && NUM_ENT(pagep) == 0) {
+		PAGE16 *empty_page;
+		db_pgno_t to_find, next_pgno, link_page;
+
+		/*
+		 * We need to go back to the first page in the chain and 
+		 * look for this page so that we can update the previous
+		 * page's NEXT_PGNO field.
+		 */
+		to_find = ADDR(pagep);
+		empty_page = pagep;
+		link_page = NEXT_PGNO(empty_page);
+		pagep = __get_page(hashp, item_info->bucket, A_BUCKET);
+		if (!pagep)
+			return (-1);
+		while (NEXT_PGNO(pagep) != to_find) {
+			next_pgno = NEXT_PGNO(pagep);
+#ifdef DEBUG
+			assert(next_pgno != INVALID_PGNO);
+#endif
+			__put_page(hashp, pagep, A_RAW, 0);
+			pagep = __get_page(hashp, next_pgno, A_RAW);
+			if (!pagep)
+				return (-1);
+		}
+
+		/*
+		 * At this point, pagep should point to the page before the
+		 * page to be deleted.
+		 */
+		NEXT_PGNO(pagep) = link_page;
+		if (item_info->pgno == to_find) {
+			item_info->pgno = ADDR(pagep);
+			item_info->pgndx = NUM_ENT(pagep);
+			item_info->seek_found_page = ADDR(pagep);
+		}
+		__delete_page(hashp, empty_page, A_OVFL);
+	}
+	__put_page(hashp, pagep, A_RAW, 1);
+
+	return (0);
+}
+
+extern int32_t
+__split_page(hashp, obucket, nbucket)
+	HTAB *hashp;
+	u_int32_t obucket, nbucket;
+{
+	DBT key, val;
+	ITEM_INFO old_ii, new_ii;
+	PAGE16 *old_pagep, *temp_pagep;
+	db_pgno_t next_pgno;
+	int32_t off;
+	u_int16_t n;
+	int8_t base_page;
+
+	off = hashp->hdr.bsize;
+	old_pagep = __get_page(hashp, obucket, A_BUCKET);
+
+	base_page = 1;
+
+	temp_pagep = hashp->split_buf;
+	memcpy(temp_pagep, old_pagep, hashp->hdr.bsize);
+
+	page_init(hashp, old_pagep, ADDR(old_pagep), HASH_PAGE);
+	__put_page(hashp, old_pagep, A_RAW, 1);
+
+	old_ii.pgno = BUCKET_TO_PAGE(obucket);
+	new_ii.pgno = BUCKET_TO_PAGE(nbucket);
+	old_ii.bucket = obucket;
+	new_ii.bucket = nbucket;
+	old_ii.seek_found_page = new_ii.seek_found_page = 0;
+
+	while (temp_pagep != 0) {
+		off = hashp->hdr.bsize;
+		for (n = 0; n < NUM_ENT(temp_pagep); n++) {
+			if (KEY_OFF(temp_pagep, n) == BIGPAIR) {
+				__get_bigkey(hashp, temp_pagep, n, &key);
+				if (__call_hash(hashp,
+				    key.data, key.size) == obucket)
+					add_bigptr(hashp, &old_ii,
+					    DATA_OFF(temp_pagep, n));
+				else
+					add_bigptr(hashp, &new_ii,
+					    DATA_OFF(temp_pagep, n));
+			} else {
+				key.size = off - KEY_OFF(temp_pagep, n);
+				key.data = KEY(temp_pagep, n);
+				off = KEY_OFF(temp_pagep, n);
+				val.size = off - DATA_OFF(temp_pagep, n);
+				val.data = DATA(temp_pagep, n);
+				if (__call_hash(hashp,
+				    key.data, key.size) == obucket)
+					__addel(hashp, &old_ii, &key, &val,
+					    NO_EXPAND, 1);
+				else
+					__addel(hashp, &new_ii, &key, &val,
+					    NO_EXPAND, 1);
+				off = DATA_OFF(temp_pagep, n);
+			}
+		}
+		next_pgno = NEXT_PGNO(temp_pagep);
+
+		/* Clear temp_page; if it's an overflow page, free it. */
+		if (!base_page)
+			__delete_page(hashp, temp_pagep, A_OVFL);
+		else
+			base_page = 0;
+		if (next_pgno != INVALID_PGNO)
+			temp_pagep = __get_page(hashp, next_pgno, A_RAW);
+		else
+			break;
+	}
+	return (0);
+}
+
+/*
+ * Add the given pair to the page.  
+ *
+ *
+ * Returns:
+ *       0 ==> OK
+ *	-1 ==> failure
+ */
+extern  int32_t
+#ifdef __STDC__
+__addel(HTAB *hashp, ITEM_INFO *item_info, const DBT *key, const DBT *val,
+    u_int32_t num_items, const u_int8_t expanding)
+#else
+__addel(hashp, item_info, key, val, num_items, expanding)
+	HTAB *hashp;
+	ITEM_INFO *item_info;
+	const DBT *key, *val;
+	u_int32_t num_items;
+	const u_int32_t expanding;
+#endif
+{
+	PAGE16 *pagep;
+	int32_t do_expand;
+	db_pgno_t next_pgno;
+
+	do_expand = 0;
+
+	pagep = __get_page(hashp,
+	    item_info->seek_found_page != 0 ?
+	    item_info->seek_found_page : item_info->pgno, A_RAW);
+	if (!pagep)
+		return (-1);
+
+	/* Advance to first page in chain with room for item. */
+	while (NUM_ENT(pagep) && NEXT_PGNO(pagep) != INVALID_PGNO) {
+		/* 
+		 * This may not be the end of the chain, but the pair may fit
+		 * anyway.
+		 */
+		if (ISBIG(PAIRSIZE(key, val), hashp) && BIGPAIRFITS(pagep))
+			break;
+		if (PAIRFITS(pagep, key, val))
+			break;
+		next_pgno = NEXT_PGNO(pagep);
+		__put_page(hashp, pagep, A_RAW, 0);
+		pagep = (PAGE16 *)__get_page(hashp, next_pgno, A_RAW);
+		if (!pagep)
+			return (-1);
+	}
+
+	if ((ISBIG(PAIRSIZE(key, val), hashp) &&
+	     !BIGPAIRFITS(pagep)) ||
+	    (!ISBIG(PAIRSIZE(key, val), hashp) &&
+	     !PAIRFITS(pagep, key, val))) {
+		do_expand = 1;
+		pagep = __add_ovflpage(hashp, pagep);
+		if (!pagep)
+			return (-1);
+
+		if ((ISBIG(PAIRSIZE(key, val), hashp) &&
+		     !BIGPAIRFITS(pagep)) ||
+		    (!ISBIG(PAIRSIZE(key, val), hashp) &&
+		     !PAIRFITS(pagep, key, val))) {
+			__put_page(hashp, pagep, A_RAW, 0);
+			return (-1);
+		}
+	}
+ 
+	/* At this point, we know the page fits, so we just add it */
+ 
+	if (ISBIG(PAIRSIZE(key, val), hashp)) {
+		if (__big_insert(hashp, pagep, key, val))
+			return (-1);
+	} else {
+		putpair((PAGE8 *)pagep, key, val);
+	}
+
+	/*
+	 * For splits, we are going to update item_info's page number
+	 * field, so that we can easily return to the same page the
+	 * next time we come in here.  For other operations, this shouldn't
+	 * matter, since adds are the last thing that happens before we
+	 * return to the user program.
+	 */
+	item_info->pgno = ADDR(pagep);
+
+	if (!expanding)
+		hashp->hdr.nkeys++;
+
+	/* Kludge: if this is a big page, then it's already been put. */
+	if (!ISBIG(PAIRSIZE(key, val), hashp))
+		__put_page(hashp, pagep, A_RAW, 1);
+
+	if (expanding)
+		item_info->caused_expand = 0;
+	else
+		switch (num_items) {
+		case NO_EXPAND:
+			item_info->caused_expand = 0;
+			break;
+		case UNKNOWN:
+			item_info->caused_expand |=
+			    (hashp->hdr.nkeys / hashp->hdr.max_bucket) >
+			    hashp->hdr.ffactor ||
+			    item_info->pgndx > hashp->hdr.ffactor;
+			break;
+		default:
+			item_info->caused_expand =
+			    num_items > hashp->hdr.ffactor ? 1 : do_expand;
+			break;
+		}
+	return (0);
+}
+
+/* 
+ * Special __addel used in big splitting; this one just puts the pointer
+ * to an already-allocated big page in the appropriate bucket.
+ */
+static int32_t
+#ifdef __STDC__
+add_bigptr(HTAB * hashp, ITEM_INFO * item_info, indx_t big_pgno)
+#else
+add_bigptr(hashp, item_info, big_pgno)
+	HTAB *hashp;
+	ITEM_INFO *item_info;
+	u_int32_t big_pgno;
+#endif
+{
+	PAGE16 *pagep;
+	db_pgno_t next_pgno;
+
+	pagep = __get_page(hashp, item_info->bucket, A_BUCKET);
+	if (!pagep)
+		return (-1);
+
+	/*
+	 * Note: in __addel(), we used item_info->pgno for the beginning of
+	 * our search for space.  Now, we use item_info->bucket, since we
+	 * know that the space required by a big pair on the base page is
+	 * quite small, and we may very well find that space early in the
+	 * chain.
+	 */
+
+	/* Find first page in chain that has space for a big pair. */
+	while (NUM_ENT(pagep) && (NEXT_PGNO(pagep) != INVALID_PGNO)) {
+		if (BIGPAIRFITS(pagep))
+			break;
+		next_pgno = NEXT_PGNO(pagep);
+		__put_page(hashp, pagep, A_RAW, 0);
+		pagep = __get_page(hashp, next_pgno, A_RAW);
+		if (!pagep)
+			return (-1);
+	}
+	if (!BIGPAIRFITS(pagep)) {
+		pagep = __add_ovflpage(hashp, pagep);
+		if (!pagep)
+			return (-1);
+#ifdef DEBUG
+		assert(BIGPAIRFITS(pagep));
+#endif
+	}
+	KEY_OFF(pagep, NUM_ENT(pagep)) = BIGPAIR;
+	DATA_OFF(pagep, NUM_ENT(pagep)) = big_pgno;
+	NUM_ENT(pagep) = NUM_ENT(pagep) + 1;
+
+	__put_page(hashp, pagep, A_RAW, 1);
+
+	return (0);
+}
+
+/*
+ *
+ * Returns:
+ *      pointer on success
+ *      NULL on error
+ */
+extern PAGE16 *
+__add_ovflpage(hashp, pagep)
+	HTAB *hashp;
+	PAGE16 *pagep;
+{
+	PAGE16 *new_pagep;
+	u_int16_t ovfl_num;
+
+	/* Check if we are dynamically determining the fill factor. */
+	if (hashp->hdr.ffactor == DEF_FFACTOR) {
+		hashp->hdr.ffactor = NUM_ENT(pagep) >> 1;
+		if (hashp->hdr.ffactor < MIN_FFACTOR)
+			hashp->hdr.ffactor = MIN_FFACTOR;
+	}
+	ovfl_num = overflow_page(hashp);
+	if (!ovfl_num)
+		return (NULL);
+
+	if (__new_page(hashp, (u_int32_t)ovfl_num, A_OVFL) != 0)
+		return (NULL);
+
+	if (!ovfl_num || !(new_pagep = __get_page(hashp, ovfl_num, A_OVFL)))
+		return (NULL);
+
+	NEXT_PGNO(pagep) = (db_pgno_t)OADDR_TO_PAGE(ovfl_num);
+	TYPE(new_pagep) = HASH_OVFLPAGE;
+
+	__put_page(hashp, pagep, A_RAW, 1);
+
+#ifdef HASH_STATISTICS
+	hash_overflows++;
+#endif
+	return (new_pagep);
+}
+
+/*
+ *
+ * Returns:
+ *      pointer on success
+ *      NULL on error
+ */
+extern PAGE16 *
+#ifdef __STDC__
+__add_bigpage(HTAB * hashp, PAGE16 * pagep, indx_t ndx, const u_int8_t
+    is_basepage)
+#else
+__add_bigpage(hashp, pagep, ndx, is_basepage)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	u_int32_t ndx;
+	const u_int32_t is_basepage;
+#endif
+{
+	PAGE16 *new_pagep;
+	u_int16_t ovfl_num;
+
+	ovfl_num = overflow_page(hashp);
+	if (!ovfl_num)
+		return (NULL);
+
+	if (__new_page(hashp, (u_int32_t)ovfl_num, A_OVFL) != 0)
+		return (NULL);
+
+	if (!ovfl_num || !(new_pagep = __get_page(hashp, ovfl_num, A_OVFL)))
+		return (NULL);
+
+	if (is_basepage) {
+		KEY_OFF(pagep, ndx) = BIGPAIR;
+		DATA_OFF(pagep, ndx) = (indx_t)ovfl_num;
+	} else
+		NEXT_PGNO(pagep) = ADDR(new_pagep);
+
+	__put_page(hashp, pagep, A_RAW, 1);
+
+	TYPE(new_pagep) = HASH_BIGPAGE;
+
+#ifdef HASH_STATISTICS
+	hash_bigpages++;
+#endif
+	return (new_pagep);
+}
+
+static void
+#ifdef __STDC__
+page_init(HTAB * hashp, PAGE16 * pagep, db_pgno_t pgno, u_int8_t type)
+#else
+page_init(hashp, pagep, pgno, type)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	db_pgno_t pgno;
+	u_int32_t type;
+#endif
+{
+	NUM_ENT(pagep) = 0;
+	PREV_PGNO(pagep) = NEXT_PGNO(pagep) = INVALID_PGNO;
+	TYPE(pagep) = type;
+	OFFSET(pagep) = hashp->hdr.bsize - 1;
+	/*
+	 * Note: since in the current version ADDR(pagep) == PREV_PGNO(pagep),
+	 * make sure that ADDR(pagep) is set after resetting PREV_PGNO(pagep).
+	 * We reset PREV_PGNO(pagep) just in case the macros are changed.
+	 */
+	ADDR(pagep) = pgno;
+
+	return;
+}
+
+int32_t
+__new_page(hashp, addr, addr_type)
+	HTAB *hashp;
+	u_int32_t addr;
+	int32_t addr_type;
+{
+	db_pgno_t paddr;
+	PAGE16 *pagep;
+
+	switch (addr_type) {		/* Convert page number. */
+	case A_BUCKET:
+		paddr = BUCKET_TO_PAGE(addr);
+		break;
+	case A_OVFL:
+	case A_BITMAP:
+		paddr = OADDR_TO_PAGE(addr);
+		break;
+	default:
+		paddr = addr;
+		break;
+	}
+	pagep = mpool_new(hashp->mp, &paddr, MPOOL_PAGE_REQUEST);
+	if (!pagep)
+		return (-1);
+#if DEBUG_SLOW
+	account_page(hashp, paddr, 1);
+#endif
+
+	if (addr_type != A_BITMAP)
+		page_init(hashp, pagep, paddr, HASH_PAGE);
+
+	__put_page(hashp, pagep, addr_type, 1);
+
+	return (0);
+}
+
+int32_t
+__delete_page(hashp, pagep, page_type)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	int32_t page_type;
+{
+	if (page_type == A_OVFL)
+		__free_ovflpage(hashp, pagep);
+	return (mpool_delete(hashp->mp, pagep));
+}
+
+static u_int8_t
+is_bitmap_pgno(hashp, pgno)
+	HTAB *hashp;
+	db_pgno_t pgno;
+{
+	int32_t i;
+
+	for (i = 0; i < hashp->nmaps; i++)
+		if (OADDR_TO_PAGE(hashp->hdr.bitmaps[i]) == pgno)
+			return (1);
+	return (0);
+}
+
+void
+__pgin_routine(pg_cookie, pgno, page)
+	void *pg_cookie;
+	db_pgno_t pgno;
+	void *page;
+{
+	HTAB *hashp;
+	PAGE16 *pagep;
+	int32_t max, i;
+
+	pagep = (PAGE16 *)page;
+	hashp = (HTAB *)pg_cookie;
+
+	/* 
+	 * There are the following cases for swapping: 
+	 * 0) New page that may be unitialized.
+	 * 1) Bucket page or overflow page.  Either swap
+	 *	the header or initialize the page.
+	 * 2) Bitmap page.  Swap the whole page!
+	 * 3) Header pages.  Not handled here; these are written directly
+	 *    to the file.
+	 */
+
+	if (NUM_ENT(pagep) == 0 && NEXT_PGNO(pagep) == 0 &&
+	    !is_bitmap_pgno(hashp, pgno)) {
+		/* XXX check for !0 LSN */
+		page_init(hashp, pagep, pgno, HASH_PAGE);
+		return;
+	}
+
+	if (hashp->hdr.lorder == DB_BYTE_ORDER)
+		return;
+	if (is_bitmap_pgno(hashp, pgno)) {
+		max = hashp->hdr.bsize >> 2;	/* divide by 4 bytes */
+		for (i = 0; i < max; i++)
+			M_32_SWAP(((int32_t *)pagep)[i]);
+	} else
+		swap_page_header_in(pagep);
+}
+
+void
+__pgout_routine(pg_cookie, pgno, page)
+	void *pg_cookie;
+	db_pgno_t pgno;
+	void *page;
+{
+	HTAB *hashp;
+	PAGE16 *pagep;
+	int32_t i, max;
+
+	pagep = (PAGE16 *)page;
+	hashp = (HTAB *)pg_cookie;
+
+	/* 
+	 * There are the following cases for swapping: 
+	 * 1) Bucket page or overflow page.  Just swap the header.
+	 * 2) Bitmap page.  Swap the whole page!
+	 * 3) Header pages.  Not handled here; these are written directly
+	 *    to the file.
+	 */
+
+	if (hashp->hdr.lorder == DB_BYTE_ORDER)
+		return;
+	if (is_bitmap_pgno(hashp, pgno)) {
+		max = hashp->hdr.bsize >> 2;	/* divide by 4 bytes */
+		for (i = 0; i < max; i++)
+			M_32_SWAP(((int32_t *)pagep)[i]);
+	} else
+		swap_page_header_out(pagep);
+}
+
+/*
+ *
+ * Returns:
+ *       0 ==> OK
+ *      -1 ==>failure
+ */
+extern int32_t
+__put_page(hashp, pagep, addr_type, is_dirty)
+	HTAB *hashp;
+	PAGE16 *pagep;
+	int32_t addr_type, is_dirty;
+{
+#if DEBUG_SLOW
+	account_page(hashp,
+	    ((BKT *)((char *)pagep - sizeof(BKT)))->pgno, -1);
+#endif
+
+	return (mpool_put(hashp->mp, pagep, (is_dirty ? MPOOL_DIRTY : 0)));
+}
+
+/*
+ * Returns:
+ *       0 indicates SUCCESS
+ *      -1 indicates FAILURE
+ */
+extern PAGE16 *
+__get_page(hashp, addr, addr_type)
+	HTAB *hashp;
+	u_int32_t addr;
+	int32_t addr_type;
+{
+	PAGE16 *pagep;
+	db_pgno_t paddr;
+
+	switch (addr_type) {			/* Convert page number. */
+	case A_BUCKET:
+		paddr = BUCKET_TO_PAGE(addr);
+		break;
+	case A_OVFL:
+	case A_BITMAP:
+		paddr = OADDR_TO_PAGE(addr);
+		break;
+	default:
+		paddr = addr;
+		break;
+	}
+	pagep = (PAGE16 *)mpool_get(hashp->mp, paddr, 0);
+
+#if DEBUG_SLOW
+	account_page(hashp, paddr, 1);
+#endif
+#ifdef DEBUG
+	assert(ADDR(pagep) == paddr || ADDR(pagep) == 0 ||
+	    addr_type == A_BITMAP || addr_type == A_HEADER);
+#endif
+
+	return (pagep);
+}
+
+static void
+swap_page_header_in(pagep)
+	PAGE16 *pagep;
+{
+	u_int32_t i;
+
+	/* can leave type and filler alone, since they're 1-byte quantities */
+
+	M_32_SWAP(PREV_PGNO(pagep));
+	M_32_SWAP(NEXT_PGNO(pagep));
+	M_16_SWAP(NUM_ENT(pagep));
+	M_16_SWAP(OFFSET(pagep));
+
+	for (i = 0; i < NUM_ENT(pagep); i++) {
+		M_16_SWAP(KEY_OFF(pagep, i));
+		M_16_SWAP(DATA_OFF(pagep, i));
+	}
+}
+
+static void
+swap_page_header_out(pagep)
+	PAGE16 *pagep;
+{
+	u_int32_t i;
+
+	for (i = 0; i < NUM_ENT(pagep); i++) {
+		M_16_SWAP(KEY_OFF(pagep, i));
+		M_16_SWAP(DATA_OFF(pagep, i))
+	}
+
+	/* can leave type and filler alone, since they're 1-byte quantities */
+
+	M_32_SWAP(PREV_PGNO(pagep));
+	M_32_SWAP(NEXT_PGNO(pagep));
+	M_16_SWAP(NUM_ENT(pagep));
+	M_16_SWAP(OFFSET(pagep));
+}
+
+#define BYTE_MASK	((1 << INT32_T_BYTE_SHIFT) -1)
+/*
+ * Initialize a new bitmap page.  Bitmap pages are left in memory
+ * once they are read in.
+ */
+extern int32_t
+__ibitmap(hashp, pnum, nbits, ndx)
+	HTAB *hashp;
+	int32_t pnum, nbits, ndx;
+{
+	u_int32_t *ip;
+	int32_t clearbytes, clearints;
+
+	/* make a new bitmap page */
+	if (__new_page(hashp, pnum, A_BITMAP) != 0)
+		return (1);
+	if (!(ip = (u_int32_t *)__get_page(hashp, pnum, A_BITMAP)))
+		return (1);
+	hashp->nmaps++;
+	clearints = ((nbits - 1) >> INT32_T_BYTE_SHIFT) + 1;
+	clearbytes = clearints << INT32_T_TO_BYTE;
+	(void)memset((int8_t *)ip, 0, clearbytes);
+	(void)memset((int8_t *)ip + clearbytes,
+	    0xFF, hashp->hdr.bsize - clearbytes);
+	ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
+	SETBIT(ip, 0);
+	hashp->hdr.bitmaps[ndx] = (u_int16_t)pnum;
+	hashp->mapp[ndx] = ip;
+	return (0);
+}
+
+static u_int32_t
+first_free(map)
+	u_int32_t map;
+{
+	u_int32_t i, mask;
+
+	for (mask = 0x1, i = 0; i < BITS_PER_MAP; i++) {
+		if (!(mask & map))
+			return (i);
+		mask = mask << 1;
+	}
+	return (i);
+}
+
+/*
+ * returns 0 on error
+ */
+static u_int16_t
+overflow_page(hashp)
+	HTAB *hashp;
+{
+	u_int32_t *freep;
+	int32_t bit, first_page, free_bit, free_page, i, in_use_bits, j;
+	int32_t max_free, offset, splitnum;
+	u_int16_t addr;
+#ifdef DEBUG2
+	int32_t tmp1, tmp2;
+#endif
+
+	splitnum = hashp->hdr.ovfl_point;
+	max_free = hashp->hdr.spares[splitnum];
+
+	free_page = (max_free - 1) >> (hashp->hdr.bshift + BYTE_SHIFT);
+	free_bit = (max_free - 1) & ((hashp->hdr.bsize << BYTE_SHIFT) - 1);
+
+	/*
+	 * Look through all the free maps to find the first free block.
+ 	 * The compiler under -Wall will complain that freep may be used
+	 * before being set, however, this loop will ALWAYS get executed
+	 * at least once, so freep is guaranteed to be set.
+	 */
+	first_page = hashp->hdr.last_freed >> (hashp->hdr.bshift + BYTE_SHIFT);
+	for (i = first_page; i <= free_page; i++) {
+		if (!(freep = fetch_bitmap(hashp, i)))
+			return (0);
+		if (i == free_page)
+			in_use_bits = free_bit;
+		else
+			in_use_bits = (hashp->hdr.bsize << BYTE_SHIFT) - 1;
+
+		if (i == first_page) {
+			bit = hashp->hdr.last_freed &
+			    ((hashp->hdr.bsize << BYTE_SHIFT) - 1);
+			j = bit / BITS_PER_MAP;
+			bit = bit & ~(BITS_PER_MAP - 1);
+		} else {
+			bit = 0;
+			j = 0;
+		}
+		for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
+			if (freep[j] != ALL_SET)
+				goto found;
+	}
+
+	/* No Free Page Found */
+	hashp->hdr.last_freed = hashp->hdr.spares[splitnum];
+	hashp->hdr.spares[splitnum]++;
+	offset = hashp->hdr.spares[splitnum] -
+	    (splitnum ? hashp->hdr.spares[splitnum - 1] : 0);
+
+#define	OVMSG	"HASH: Out of overflow pages.  Increase page size\n"
+
+	if (offset > SPLITMASK) {
+		if (++splitnum >= NCACHED) {
+			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+			return (0);
+		}
+		hashp->hdr.ovfl_point = splitnum;
+		hashp->hdr.spares[splitnum] = hashp->hdr.spares[splitnum - 1];
+		hashp->hdr.spares[splitnum - 1]--;
+		offset = 1;
+	}
+	/* Check if we need to allocate a new bitmap page. */
+	if (free_bit == (hashp->hdr.bsize << BYTE_SHIFT) - 1) {
+		free_page++;
+		if (free_page >= NCACHED) {
+			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+			return (0);
+		}
+		/*
+		 * This is tricky.  The 1 indicates that you want the new page
+		 * allocated with 1 clear bit.  Actually, you are going to
+		 * allocate 2 pages from this map.  The first is going to be
+		 * the map page, the second is the overflow page we were
+		 * looking for.  The __ibitmap routine automatically, sets
+		 * the first bit of itself to indicate that the bitmap itself
+		 * is in use.  We would explicitly set the second bit, but
+		 * don't have to if we tell __ibitmap not to leave it clear
+		 * in the first place.
+		 */
+		if (__ibitmap(hashp,
+		    (int32_t)OADDR_OF(splitnum, offset), 1, free_page))
+			return (0);
+		hashp->hdr.spares[splitnum]++;
+#ifdef DEBUG2
+		free_bit = 2;
+#endif
+		offset++;
+		if (offset > SPLITMASK) {
+			if (++splitnum >= NCACHED) {
+				(void)write(STDERR_FILENO,
+				    OVMSG, sizeof(OVMSG) - 1);
+				return (0);
+			}
+			hashp->hdr.ovfl_point = splitnum;
+			hashp->hdr.spares[splitnum] =
+			    hashp->hdr.spares[splitnum - 1];
+			hashp->hdr.spares[splitnum - 1]--;
+			offset = 0;
+		}
+	} else {
+		/*
+		 * Free_bit addresses the last used bit.  Bump it to address
+		 * the first available bit.
+		 */
+		free_bit++;
+		SETBIT(freep, free_bit);
+	}
+
+	/* Calculate address of the new overflow page */
+	addr = OADDR_OF(splitnum, offset);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    addr, free_bit, free_page);
+#endif
+
+	if (OADDR_TO_PAGE(addr) > MAX_PAGES(hashp)) {
+		(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+		return (0);
+	}
+	return (addr);
+
+found:
+	bit = bit + first_free(freep[j]);
+	SETBIT(freep, bit);
+#ifdef DEBUG2
+	tmp1 = bit;
+	tmp2 = i;
+#endif
+	/*
+	 * Bits are addressed starting with 0, but overflow pages are addressed
+	 * beginning at 1. Bit is a bit address number, so we need to increment
+	 * it to convert it to a page number.
+	 */
+	bit = 1 + bit + (i * (hashp->hdr.bsize << BYTE_SHIFT));
+	if (bit >= hashp->hdr.last_freed)
+		hashp->hdr.last_freed = bit - 1;
+
+	/* Calculate the split number for this page */
+	for (i = 0; i < splitnum && (bit > hashp->hdr.spares[i]); i++);
+	offset = (i ? bit - hashp->hdr.spares[i - 1] : bit);
+	if (offset >= SPLITMASK)
+		return (0);	/* Out of overflow pages */
+	addr = OADDR_OF(i, offset);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    addr, tmp1, tmp2);
+#endif
+
+	if (OADDR_TO_PAGE(addr) > MAX_PAGES(hashp)) {
+		(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+		return (0);
+	}
+	/* Allocate and return the overflow page */
+	return (addr);
+}
+
+#ifdef DEBUG
+int
+bucket_to_page(hashp, n)
+	HTAB *hashp;
+	int n;
+{
+	int ret_val;
+
+	ret_val = n + hashp->hdr.hdrpages;
+	if (n != 0)
+		ret_val += hashp->hdr.spares[__log2(n + 1) - 1];
+	return (ret_val);
+}
+
+int32_t
+oaddr_to_page(hashp, n)
+	HTAB *hashp;
+	int n;
+{
+	int ret_val, temp;
+
+	temp = (1 << SPLITNUM(n)) - 1;
+	ret_val = bucket_to_page(hashp, temp);
+	ret_val += (n & SPLITMASK);
+
+	return (ret_val);
+}
+#endif /* DEBUG */
+
+static indx_t
+page_to_oaddr(hashp, pgno)
+	HTAB *hashp;
+	db_pgno_t pgno;
+{
+	int32_t sp, ret_val;
+
+	/*
+	 * To convert page number to overflow address:
+	 *
+	 * 1.  Find a starting split point -- use 0 since there are only
+	 *     32 split points.
+	 * 2.  Find the split point s.t. 2^sp + hdr.spares[sp] < pgno and
+	 *     2^(sp+1) = hdr.spares[sp+1] > pgno.  The overflow address will
+	 *     be located at sp.
+	 * 3.  return...
+	 */
+	pgno -= hashp->hdr.hdrpages;
+	for (sp = 0; sp < NCACHED; sp++)
+		if (POW2(sp) + hashp->hdr.spares[sp] < pgno &&
+		    (POW2(sp + 1) + hashp->hdr.spares[sp + 1]) > pgno)
+			break;
+
+	ret_val = OADDR_OF(sp + 1,
+	    pgno - ((POW2(sp + 1) - 1) + hashp->hdr.spares[sp]));
+#ifdef DEBUG
+	assert(OADDR_TO_PAGE(ret_val) == (pgno + hashp->hdr.hdrpages));
+#endif
+	return (ret_val);
+}
+
+/*
+ * Mark this overflow page as free.
+ */
+extern void
+__free_ovflpage(hashp, pagep)
+	HTAB *hashp;
+	PAGE16 *pagep;
+{
+	u_int32_t *freep;
+	int32_t bit_address, free_page, free_bit;
+	u_int16_t addr, ndx;
+
+	addr = page_to_oaddr(hashp, ADDR(pagep));
+
+#ifdef DEBUG2
+	(void)fprintf(stderr, "Freeing %d\n", addr);
+#endif
+	ndx = ((u_int16_t)addr) >> SPLITSHIFT;
+	bit_address =
+	    (ndx ? hashp->hdr.spares[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
+	if (bit_address < hashp->hdr.last_freed)
+		hashp->hdr.last_freed = bit_address;
+	free_page = (bit_address >> (hashp->hdr.bshift + BYTE_SHIFT));
+	free_bit = bit_address & ((hashp->hdr.bsize << BYTE_SHIFT) - 1);
+
+	freep = fetch_bitmap(hashp, free_page);
+#ifdef DEBUG
+	/*
+	 * This had better never happen.  It means we tried to read a bitmap
+	 * that has already had overflow pages allocated off it, and we
+	 * failed to read it from the file.
+	 */
+	if (!freep)
+		assert(0);
+#endif
+	CLRBIT(freep, free_bit);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    obufp->addr, free_bit, free_page);
+#endif
+}
+
+static u_int32_t *
+fetch_bitmap(hashp, ndx)
+	HTAB *hashp;
+	int32_t ndx;
+{
+	if (ndx >= hashp->nmaps)
+		return (NULL);
+	if (!hashp->mapp[ndx])
+	    hashp->mapp[ndx] = (u_int32_t *)__get_page(hashp,
+	        hashp->hdr.bitmaps[ndx], A_BITMAP);
+
+	return (hashp->mapp[ndx]);
+}
+
+#ifdef DEBUG_SLOW
+static void
+account_page(hashp, pgno, inout)
+	HTAB *hashp;
+	db_pgno_t pgno;
+	int inout;
+{
+	static struct {
+		db_pgno_t pgno;
+		int times;
+	} list[100];
+	static int last;
+	int i, j;
+
+	if (inout == -1)			/* XXX: Kluge */
+		inout = 0;
+
+	/* Find page in list. */
+	for (i = 0; i < last; i++)
+		if (list[i].pgno == pgno)
+			break;
+	/* Not found. */
+	if (i == last) {
+		list[last].times = inout;
+		list[last].pgno = pgno;
+		last++;
+	}
+	list[i].times = inout;
+	if (list[i].times == 0) {
+		for (j = i; j < last; j++)
+			list[j] = list[j + 1];
+		last--;
+	}
+	for (i = 0; i < last; i++, list[i].times++)
+		if (list[i].times > 20 && !is_bitmap_pgno(hashp, list[i].pgno))
+			(void)fprintf(stderr,
+			    "Warning: pg %d has been out for %d times\n",
+			    list[i].pgno, list[i].times);
+}
+#endif /* DEBUG_SLOW */
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hsearch.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hsearch.c
new file mode 100644
index 000000000..02ff7ef84
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/hsearch.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hsearch.c	8.5 (Berkeley) 9/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "search.h"
+
+static DB *dbp = NULL;
+static ENTRY retval;
+
+extern int
+hcreate(nel)
+	u_int nel;
+{
+	HASHINFO info;
+
+	info.nelem = nel;
+	info.bsize = 256;
+	info.ffactor = 8;
+	info.cachesize = 0;
+	info.hash = NULL;
+	info.lorder = 0;
+	dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR | O_BINARY, 0600, &info, 0);
+	return (dbp != NULL);
+}
+
+extern ENTRY *
+hsearch(item, action)
+	ENTRY item;
+	ACTION action;
+{
+	DBT key, val;
+	int status;
+
+	if (!dbp)
+		return (NULL);
+	key.data = (u_char *)item.key;
+	key.size = strlen(item.key) + 1;
+
+	if (action == ENTER) {
+		val.data = (u_char *)item.data;
+		val.size = strlen(item.data) + 1;
+		status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE);
+		if (status)
+			return (NULL);
+	} else {
+		/* FIND */
+		status = (dbp->get)(dbp, &key, &val, 0);
+		if (status)
+			return (NULL);
+		else
+			item.data = (char *)val.data;
+	}
+	retval.key = item.key;
+	retval.data = item.data;
+	return (&retval);
+}
+
+extern void
+hdestroy()
+{
+	if (dbp) {
+		(void)(dbp->close)(dbp);
+		dbp = NULL;
+	}
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h
new file mode 100644
index 000000000..8ef8a2e29
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)page.h	8.4 (Berkeley) 11/7/95
+ */
+
+#define HI_MASK 0xFFFF0000
+#define LO_MASK (~HI_MASK)
+
+#define HI(N) ((u_int16_t)(((N) & HI_MASK) >> 16))
+#define LO(N) ((u_int16_t)((N) & LO_MASK))
+
+/* Constants for big key page overhead information. */
+#define NUMSHORTS	0
+#define KEYLEN		1
+#define DATALEN 	2
+#define NEXTPAGE 	3
+
+/*
+ * Hash pages store meta-data beginning at the top of the page (offset 0)
+ * and key/data values beginning at the bottom of the page (offset pagesize).
+ * Fields are always accessed via macros so that we can change the page
+ * format without too much pain.  The only changes that will require massive
+ * code changes are if we no longer store key/data offsets next to each
+ * other (since we use that fact to compute key lengths).  In the accessor
+ * macros below, P means a pointer to the page, I means an index of the
+ * particular entry being accessed.
+ * 
+ * Hash base page format
+ * BYTE ITEM			NBYTES 	TYPE		ACCESSOR MACRO
+ * ---- ------------------	------	--------	--------------
+ * 0	previous page number 	4	db_pgno_t		PREV_PGNO(P)
+ * 4	next page number	4	db_pgno_t		NEXT_PGNO(P)
+ * 8	# pairs on page		2	indx_t		NUM_ENT(P)
+ * 10	page type		1	u_int8_t	TYPE(P)
+ * 11	padding			1	u_int8_t	none
+ * 12	highest free byte	2	indx_t		OFFSET(P)
+ * 14	key offset 0		2	indx_t		KEY_OFF(P, I)
+ * 16	data offset 0		2	indx_t		DATA_OFF(P, I)
+ * 18	key  offset 1		2	indx_t		KEY_OFF(P, I)
+ * 20	data offset 1		2	indx_t		DATA_OFF(P, I)
+ * ...etc...
+ */
+
+/* Indices (in bytes) of the beginning of each of these entries */
+#define I_PREV_PGNO	 0
+#define I_NEXT_PGNO	 4
+#define I_ENTRIES	 8
+#define I_TYPE		10
+#define I_HF_OFFSET	12
+
+/* Overhead is everything prior to the first key/data pair. */
+#define PAGE_OVERHEAD	(I_HF_OFFSET + sizeof(indx_t))
+
+/* To allocate a pair, we need room for one key offset and one data offset. */
+#define PAIR_OVERHEAD	((sizeof(indx_t) << 1))
+
+/* Use this macro to extract a value of type T from page P at offset O. */
+#define REFERENCE(P, T, O)  (((T *)((u_int8_t *)(P) + O))[0])
+
+/*
+ * Use these macros to access fields on a page; P is a PAGE16 *.
+ */
+#define NUM_ENT(P)	(REFERENCE((P), indx_t, I_ENTRIES))
+#define PREV_PGNO(P)	(REFERENCE((P), db_pgno_t, I_PREV_PGNO))
+#define NEXT_PGNO(P)	(REFERENCE((P), db_pgno_t, I_NEXT_PGNO))
+#define TYPE(P)		(REFERENCE((P), u_int8_t, I_TYPE))
+#define OFFSET(P)	(REFERENCE((P), indx_t, I_HF_OFFSET))
+/*
+ * We need to store a page's own address on each page (unlike the Btree
+ * access method which needs the previous page).  We use the PREV_PGNO
+ * field to store our own page number.
+ */
+#define ADDR(P)		(PREV_PGNO((P)))
+
+/* Extract key/data offsets and data for a given index. */
+#define DATA_OFF(P, N) \
+	REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD + sizeof(indx_t))
+#define KEY_OFF(P, N) \
+	REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD)
+
+#define KEY(P, N)	(((PAGE8 *)(P)) + KEY_OFF((P), (N)))
+#define DATA(P, N)	(((PAGE8 *)(P)) + DATA_OFF((P), (N)))
+
+/*
+ * Macros used to compute various sizes on a page.
+ */
+#define	PAIRSIZE(K, D)	(PAIR_OVERHEAD + (K)->size + (D)->size)
+#define BIGOVERHEAD	(4 * sizeof(u_int16_t))
+#define KEYSIZE(K)	(4 * sizeof(u_int16_t) + (K)->size);
+#define OVFLSIZE	(2 * sizeof(u_int16_t))
+#define BIGPAGEOVERHEAD (4 * sizeof(u_int16_t))
+#define BIGPAGEOFFSET   4
+#define BIGPAGESIZE(P)	((P)->BSIZE - BIGPAGEOVERHEAD)
+
+#define PAGE_META(N)	(((N) + 3) * sizeof(u_int16_t))
+#define MINFILL 0.75
+#define ISBIG(N, P)	(((N) > ((P)->hdr.bsize * MINFILL)) ? 1 : 0)
+
+#define ITEMSIZE(I)    (sizeof(u_int16_t) + (I)->size)
+
+/*
+ * Big key/data pages use a different page format.  They have a single
+ * key/data "pair" containing the length of the key and data instead
+ * of offsets.
+ */
+#define BIGKEYLEN(P)	(KEY_OFF((P), 0))
+#define BIGDATALEN(P)	(DATA_OFF((P), 0))
+#define BIGKEY(P)	(((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD)
+#define BIGDATA(P) \
+	(((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD + KEY_OFF((P), 0))
+
+
+#define OVFLPAGE	0
+#define BIGPAIR		0
+#define INVALID_PGNO	0xFFFFFFFF
+
+typedef unsigned short PAGE16;
+typedef unsigned char  PAGE8;
+
+#define A_BUCKET	0
+#define A_OVFL		1
+#define A_BITMAP	2
+#define A_RAW		4
+#define A_HEADER	5
+
+#define PAIRFITS(P,K,D)	((PAIRSIZE((K),(D))) <= FREESPACE((P)))
+#define BIGPAIRFITS(P)	((FREESPACE((P)) >= PAIR_OVERHEAD))
+/*
+ * Since these are all unsigned, we need to guarantee that we never go
+ * negative.  Offset values are 0-based and overheads are one based (i.e.
+ * one byte of overhead is 1, not 0), so we need to convert OFFSETs to
+ * 1-based counting before subtraction.
+ */
+#define FREESPACE(P) \
+	((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD)))
+
+/* 
+ * Overhead on header pages is just one word -- the length of the
+ * header info stored on that page.
+ */
+#define HEADER_OVERHEAD 4
+
+#define HASH_PAGE	2
+#define HASH_BIGPAGE	3
+#define HASH_OVFLPAGE	4
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h.patch b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h.patch
new file mode 100644
index 000000000..4a0311fea
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/page.h.patch
@@ -0,0 +1,42 @@
+*** /tmp/,RCSt1a21720	Wed Apr  3 11:49:55 1996
+--- page.h	Wed Apr  3 08:42:25 1996
+***************
+*** 158,163
+  
+  #define PAIRFITS(P,K,D)	((PAIRSIZE((K),(D))) <= FREESPACE((P)))
+  #define BIGPAIRFITS(P)	((FREESPACE((P)) >= PAIR_OVERHEAD))
+  #define FREESPACE(P) \
+  	((OFFSET((P)) - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD)))
+  
+
+--- 158,169 -----
+  
+  #define PAIRFITS(P,K,D)	((PAIRSIZE((K),(D))) <= FREESPACE((P)))
+  #define BIGPAIRFITS(P)	((FREESPACE((P)) >= PAIR_OVERHEAD))
++ /*
++  * Since these are all unsigned, we need to guarantee that we never go
++  * negative.  Offset values are 0-based and overheads are one based (i.e.
++  * one byte of overhead is 1, not 0), so we need to convert OFFSETs to
++  * 1-based counting before subtraction.
++  */
+  #define FREESPACE(P) \
+  	((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD)))
+  
+***************
+*** 159,165
+  #define PAIRFITS(P,K,D)	((PAIRSIZE((K),(D))) <= FREESPACE((P)))
+  #define BIGPAIRFITS(P)	((FREESPACE((P)) >= PAIR_OVERHEAD))
+  #define FREESPACE(P) \
+! 	((OFFSET((P)) - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD)))
+  
+  /* 
+   * Overhead on header pages is just one word -- the length of the
+
+--- 165,171 -----
+   * 1-based counting before subtraction.
+   */
+  #define FREESPACE(P) \
+! 	((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD)))
+  
+  /* 
+   * Overhead on header pages is just one word -- the length of the
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/search.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/search.h
new file mode 100644
index 000000000..6d6a0a82f
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/hash/search.h
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)search.h	8.1 (Berkeley) 6/4/93
+ */
+
+/* Backward compatibility to hsearch interface. */
+typedef struct entry {
+	char *key;
+	char *data;
+} ENTRY;
+
+typedef enum {
+	FIND, ENTER
+} ACTION;
+
+#define hcreate		kdb2_hcreate
+#define hdestroy	kdb2_hdestroy
+#define hsearch		kdb2_hsearch
+
+int	 hcreate __P((unsigned int));
+void	 hdestroy __P((void));
+ENTRY	*hsearch __P((ENTRY, ACTION));
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-config.h.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-config.h.in
new file mode 100644
index 000000000..bcd7991b3
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-config.h.in
@@ -0,0 +1,16 @@
+/* include/db-config.h.in.  Derived from autoconf-generated config.h.in. */
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+#undef u_char
+#undef u_int
+#undef u_long
+
+#undef u_int32_t
+
+/* The number of bytes in a int.  */
+#undef SIZEOF_INT
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-dbm.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-dbm.h
new file mode 100644
index 000000000..28c93786c
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-dbm.h
@@ -0,0 +1,23 @@
+#ifndef _DBM_H_
+#define	_DBM_H_
+
+#include "db.h"
+
+#define dbminit		kdb2_dbminit
+#define fetch		kdb2_fetch
+#define firstkey	kdb2_firstkey
+#define nextkey		kdb2_nextkey
+#define delete		kdb2_delete
+#define store		kdb2_store
+
+__BEGIN_DECLS
+int	 dbminit __P((char *));
+datum	 fetch __P((datum));
+datum	 firstkey __P((void));
+datum	 nextkey __P((datum));
+int	 delete __P((datum));
+int	 store __P((datum, datum));
+__END_DECLS
+
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-int.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-int.h
new file mode 100644
index 000000000..bbb22925a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-int.h
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)compat.h	8.13 (Berkeley) 2/21/94
+ */
+
+#ifndef	_DB_INT_H_
+#define	_DB_INT_H_
+
+#include "config.h"
+#include "db.h"
+
+/* deal with autoconf-based stuff */
+
+#define DB_LITTLE_ENDIAN 1234
+#define DB_BIG_ENDIAN 4321
+
+#include <stdlib.h>
+#ifdef HAVE_ENDIAN_H
+# include <endian.h>
+#endif
+#ifdef HAVE_MACHINE_ENDIAN_H
+# include <machine/endian.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+/* Handle both BIG and LITTLE defined and BYTE_ORDER matches one, or
+   just one defined; both with and without leading underscores.
+
+   Ignore "PDP endian" machines, this code doesn't support them
+   anyways.  */
+#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && !defined(BYTE_ORDER)
+# ifdef __LITTLE_ENDIAN__
+#  define LITTLE_ENDIAN __LITTLE_ENDIAN__
+# endif
+# ifdef __BIG_ENDIAN__
+#  define BIG_ENDIAN __BIG_ENDIAN__
+# endif
+#endif
+#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && !defined(BYTE_ORDER)
+# ifdef _LITTLE_ENDIAN
+#  define LITTLE_ENDIAN _LITTLE_ENDIAN
+# endif
+# ifdef _BIG_ENDIAN
+#  define BIG_ENDIAN _BIG_ENDIAN
+# endif
+# ifdef _BYTE_ORDER
+#  define BYTE_ORDER _BYTE_ORDER
+# endif
+#endif
+#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && !defined(BYTE_ORDER)
+# ifdef __LITTLE_ENDIAN
+#  define LITTLE_ENDIAN __LITTLE_ENDIAN
+# endif
+# ifdef __BIG_ENDIAN
+#  define BIG_ENDIAN __BIG_ENDIAN
+# endif
+# ifdef __BYTE_ORDER
+#  define BYTE_ORDER __BYTE_ORDER
+# endif
+#endif
+
+#if defined(_MIPSEL) && !defined(LITTLE_ENDIAN)
+# define LITTLE_ENDIAN
+#endif
+#if defined(_MIPSEB) && !defined(BIG_ENDIAN)
+# define BIG_ENDIAN
+#endif
+
+#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) && defined(BYTE_ORDER)
+# if LITTLE_ENDIAN == BYTE_ORDER
+#  define DB_BYTE_ORDER DB_LITTLE_ENDIAN
+# elif BIG_ENDIAN == BYTE_ORDER
+#  define DB_BYTE_ORDER DB_BIG_ENDIAN
+# else
+#  error "LITTLE_ENDIAN and BIG_ENDIAN defined, but can't determine byte order"
+# endif
+#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
+# define DB_BYTE_ORDER DB_LITTLE_ENDIAN
+#elif defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
+# define DB_BYTE_ORDER DB_BIG_ENDIAN
+#else
+# error "can't determine byte order from included system headers"
+#endif
+
+#if 0
+#ifdef WORDS_BIGENDIAN
+#define DB_BYTE_ORDER DB_BIG_ENDIAN
+#else
+#define DB_BYTE_ORDER DB_LITTLE_ENDIAN
+#endif
+#endif
+
+/* end autoconf-based stuff */
+
+/* include necessary system header files */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+/* Tru64 5.1: int8_t is defined here, and stdint.h doesn't exist.  */
+#include <inttypes.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+/* types and constants used for database structure */
+
+#define	MAX_PAGE_NUMBER	0xffffffff	/* >= # of pages in a file */
+typedef u_int32_t	db_pgno_t;
+#define	MAX_PAGE_OFFSET	65535		/* >= # of bytes in a page */
+typedef u_int16_t	indx_t;
+#define	MAX_REC_NUMBER	0xffffffff	/* >= # of records in a tree */
+typedef u_int32_t	recno_t;
+
+/*
+ * Little endian <==> big endian 32-bit swap macros.
+ *	M_32_SWAP	swap a memory location
+ *	P_32_SWAP	swap a referenced memory location
+ *	P_32_COPY	swap from one location to another
+ */
+#define	M_32_SWAP(a) {							\
+	u_int32_t _tmp = a;						\
+	((char *)&a)[0] = ((char *)&_tmp)[3];				\
+	((char *)&a)[1] = ((char *)&_tmp)[2];				\
+	((char *)&a)[2] = ((char *)&_tmp)[1];				\
+	((char *)&a)[3] = ((char *)&_tmp)[0];				\
+}
+#define	P_32_SWAP(a) {							\
+	u_int32_t _tmp = *(u_int32_t *)a;				\
+	((char *)a)[0] = ((char *)&_tmp)[3];				\
+	((char *)a)[1] = ((char *)&_tmp)[2];				\
+	((char *)a)[2] = ((char *)&_tmp)[1];				\
+	((char *)a)[3] = ((char *)&_tmp)[0];				\
+}
+#define	P_32_COPY(a, b) {						\
+	((char *)&(b))[0] = ((char *)&(a))[3];				\
+	((char *)&(b))[1] = ((char *)&(a))[2];				\
+	((char *)&(b))[2] = ((char *)&(a))[1];				\
+	((char *)&(b))[3] = ((char *)&(a))[0];				\
+}
+
+/*
+ * Little endian <==> big endian 16-bit swap macros.
+ *	M_16_SWAP	swap a memory location
+ *	P_16_SWAP	swap a referenced memory location
+ *	P_16_COPY	swap from one location to another
+ */
+#define	M_16_SWAP(a) {							\
+	u_int16_t _tmp = a;						\
+	((char *)&a)[0] = ((char *)&_tmp)[1];				\
+	((char *)&a)[1] = ((char *)&_tmp)[0];				\
+}
+#define	P_16_SWAP(a) {							\
+	u_int16_t _tmp = *(u_int16_t *)a;				\
+	((char *)a)[0] = ((char *)&_tmp)[1];				\
+	((char *)a)[1] = ((char *)&_tmp)[0];				\
+}
+#define	P_16_COPY(a, b) {						\
+	((char *)&(b))[0] = ((char *)&(a))[1];				\
+	((char *)&(b))[1] = ((char *)&(a))[0];				\
+}
+
+/* open functions for each database type, used in dbopen() */
+
+#define __bt_open	__kdb2_bt_open
+#define __hash_open	__kdb2_hash_open
+#define __rec_open	__kdb2_rec_open
+#define __dbpanic	__kdb2_dbpanic
+
+DB	*__bt_open __P((const char *, int, int, const BTREEINFO *, int));
+DB	*__hash_open __P((const char *, int, int, const HASHINFO *, int));
+DB	*__rec_open __P((const char *, int, int, const RECNOINFO *, int));
+void	 __dbpanic __P((DB *dbp));
+
+/*
+ * There is no portable way to figure out the maximum value of a file
+ * offset, so we put it here.
+ */
+#ifdef	OFF_T_MAX
+#define	DB_OFF_T_MAX	OFF_T_MAX
+#else
+#define	DB_OFF_T_MAX	LONG_MAX
+#endif
+
+#ifndef O_ACCMODE			/* POSIX 1003.1 access mode mask. */
+#define	O_ACCMODE	(O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
+/*
+ * If you can't provide lock values in the open(2) call.  Note, this
+ * allows races to happen.
+ */
+#ifndef O_EXLOCK			/* 4.4BSD extension. */
+#define	O_EXLOCK	0
+#endif
+
+#ifndef O_SHLOCK			/* 4.4BSD extension. */
+#define	O_SHLOCK	0
+#endif
+
+#ifndef EFTYPE
+#define	EFTYPE		EINVAL		/* POSIX 1003.1 format errno. */
+#endif
+
+#ifndef	STDERR_FILENO
+#define	STDIN_FILENO	0		/* ANSI C #defines */
+#define	STDOUT_FILENO	1
+#define	STDERR_FILENO	2
+#endif
+
+#ifndef SEEK_END
+#define	SEEK_SET	0		/* POSIX 1003.1 seek values */
+#define	SEEK_CUR	1
+#define	SEEK_END	2
+#endif
+
+#ifndef NULL				/* ANSI C #defines NULL everywhere. */
+#define	NULL		0
+#endif
+
+#ifndef	MAX				/* Usually found in <sys/param.h>. */
+#define	MAX(_a,_b)	((_a)<(_b)?(_b):(_a))
+#endif
+#ifndef	MIN				/* Usually found in <sys/param.h>. */
+#define	MIN(_a,_b)	((_a)<(_b)?(_a):(_b))
+#endif
+
+#ifndef S_ISDIR				/* POSIX 1003.1 file type tests. */
+#define	S_ISDIR(m)	((m & 0170000) == 0040000)	/* directory */
+#define	S_ISCHR(m)	((m & 0170000) == 0020000)	/* char special */
+#define	S_ISBLK(m)	((m & 0170000) == 0060000)	/* block special */
+#define	S_ISREG(m)	((m & 0170000) == 0100000)	/* regular file */
+#define	S_ISFIFO(m)	((m & 0170000) == 0010000)	/* fifo */
+#endif
+#ifndef S_ISLNK				/* BSD POSIX 1003.1 extensions */
+#define	S_ISLNK(m)	((m & 0170000) == 0120000)	/* symbolic link */
+#define	S_ISSOCK(m)	((m & 0170000) == 0140000)	/* socket */
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY	0		/* Needed for Win32 compiles */
+#endif
+#endif /* _DB_INT_H_ */
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-ndbm.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-ndbm.h
new file mode 100644
index 000000000..e99f46fdc
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-ndbm.h
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ndbm.h	8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _NDBM_H_
+#define	_NDBM_H_
+
+#include "db.h"
+
+/* Map dbm interface onto db(3). */
+#define DBM_RDONLY	O_RDONLY
+
+/* Flags to dbm_store(). */
+#define DBM_INSERT      0
+#define DBM_REPLACE     1
+
+/*
+ * The db(3) support for ndbm(3) always appends this suffix to the
+ * file name to avoid overwriting the user's original database.
+ */
+#define	DBM_SUFFIX	".db"
+
+typedef struct {
+	char *dptr;
+	int dsize;
+} datum;
+
+typedef DB DBM;
+#define	dbm_pagfno(a)	DBM_PAGFNO_NOT_AVAILABLE
+
+#define dbm_close	kdb2_dbm_close
+#define dbm_delete	kdb2_dbm_delete
+#define dbm_fetch	kdb2_dbm_fetch
+#define dbm_firstkey	kdb2_dbm_firstkey
+#define dbm_forder	kdb2_dbm_forder
+#define dbm_nextkey	kdb2_dbm_nextkey
+#define dbm_open	kdb2_dbm_open
+#define dbm_store	kdb2_dbm_store
+#define dbm_dirfno	kdb2_dbm_dirfno
+#define dbm_error	kdb2_dbm_error
+#define dbm_clearerr	kdb2_dbm_clearerr
+
+__BEGIN_DECLS
+void	 dbm_close __P((DBM *));
+int	 dbm_delete __P((DBM *, datum));
+datum	 dbm_fetch __P((DBM *, datum));
+datum	 dbm_firstkey __P((DBM *));
+long	 dbm_forder __P((DBM *, datum));
+datum	 dbm_nextkey __P((DBM *));
+DBM	*dbm_open __P((const char *, int, int));
+int	 dbm_store __P((DBM *, datum, datum, int));
+int	 dbm_dirfno __P((DBM *));
+int	 dbm_error __P((DBM *db));
+int	 dbm_clearerr __P((DBM *db));
+__END_DECLS
+
+#endif /* !_NDBM_H_ */
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-queue.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-queue.h
new file mode 100644
index 000000000..40d32ccb6
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db-queue.h
@@ -0,0 +1,245 @@
+/* 
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.3 (Berkeley) 12/13/93
+ */
+
+#ifndef	_QUEUE_H_
+#define	_QUEUE_H_
+
+/*
+ * This file defines three types of data structures: lists, tail queues,
+ * and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list after
+ * an existing element or at the head of the list. A list may only be
+ * traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A tail queue may only be traversed in the forward direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+#define	LIST_INIT(head) {						\
+	(head)->lh_first = NULL;					\
+}
+
+#define LIST_INSERT_AFTER(listelm, elm, field) {			\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+}
+
+#define LIST_INSERT_HEAD(head, elm, field) {				\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+}
+
+#define LIST_REMOVE(elm, field) {					\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev = 			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+}
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+
+#define TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_INIT(head) {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+}
+
+#define TAILQ_INSERT_HEAD(head, elm, field) {				\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+}
+
+#define TAILQ_INSERT_TAIL(head, elm, field) {				\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+}
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) {			\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+}
+
+#define TAILQ_REMOVE(head, elm, field) {				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+}
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) {						\
+	(head)->cqh_first = (void *)(head);				\
+	(head)->cqh_last = (void *)(head);				\
+}
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == (void *)(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+}
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == (void *)(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+}
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) {				\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = (void *)(head);				\
+	if ((head)->cqh_last == (void *)(head))				\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+}
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) {				\
+	(elm)->field.cqe_next = (void *)(head);				\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == (void *)(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+}
+
+#define	CIRCLEQ_REMOVE(head, elm, field) {				\
+	if ((elm)->field.cqe_next == (void *)(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == (void *)(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+}
+#endif	/* !_QUEUE_H_ */
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db.h
new file mode 100644
index 000000000..ad86d0af9
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/include/db.h
@@ -0,0 +1,175 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)db.h	8.8 (Berkeley) 11/2/95
+ */
+
+#ifndef _DB_H_
+#define	_DB_H_
+
+#include <db-config.h>
+
+#include <sys/types.h>
+
+#define	RET_ERROR	-1		/* Return values. */
+#define	RET_SUCCESS	 0
+#define	RET_SPECIAL	 1
+
+/* Key/data structure -- a Data-Base Thang. */
+typedef struct {
+	void	*data;			/* data */
+	size_t	 size;			/* data length */
+} DBT;
+
+/* Routine flags. */
+#define	R_CURSOR	1		/* del, put, seq */
+#define	__R_UNUSED	2		/* UNUSED */
+#define	R_FIRST		3		/* seq */
+#define	R_IAFTER	4		/* put (RECNO) */
+#define	R_IBEFORE	5		/* put (RECNO) */
+#define	R_LAST		6		/* seq (BTREE, RECNO) */
+#define	R_NEXT		7		/* seq */
+#define	R_NOOVERWRITE	8		/* put */
+#define	R_PREV		9		/* seq (BTREE, RECNO) */
+#define	R_SETCURSOR	10		/* put (RECNO) */
+#define	R_RECNOSYNC	11		/* sync (RECNO) */
+
+typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
+
+/*
+ * !!!
+ * The following flags are included in the dbopen(3) call as part of the
+ * open(2) flags.  In order to avoid conflicts with the open flags, start
+ * at the top of the 16 or 32-bit number space and work our way down.  If
+ * the open flags were significantly expanded in the future, it could be
+ * a problem.  Wish I'd left another flags word in the dbopen call.
+ *
+ * !!!
+ * None of this stuff is implemented yet.  The only reason that it's here
+ * is so that the access methods can skip copying the key/data pair when
+ * the DB_LOCK flag isn't set.
+ */
+#if UINT_MAX >= 0xffffffffUL
+#define	DB_LOCK		0x20000000	/* Do locking. */
+#define	DB_SHMEM	0x40000000	/* Use shared memory. */
+#define	DB_TXN		0x80000000	/* Do transactions. */
+#else
+#define	DB_LOCK		    0x2000	/* Do locking. */
+#define	DB_SHMEM	    0x4000	/* Use shared memory. */
+#define	DB_TXN		    0x8000	/* Do transactions. */
+#endif
+
+/* deal with turning prototypes on and off */
+
+#ifndef __P
+#if defined(__STDC__) || defined(__cplusplus)
+#define	__P(protos)	protos		/* full-blown ANSI C */
+#else	/* !(__STDC__ || __cplusplus) */
+#define	__P(protos)	()		/* traditional C preprocessor */
+#endif
+#endif /* no __P from system */
+
+/* Access method description structure. */
+typedef struct __db {
+	DBTYPE type;			/* Underlying db type. */
+	int (*close)	__P((struct __db *));
+	int (*del)	__P((const struct __db *, const DBT *, u_int));
+	int (*get)	__P((const struct __db *, const DBT *, DBT *, u_int));
+	int (*put)	__P((const struct __db *, DBT *, const DBT *, u_int));
+	int (*seq)	__P((const struct __db *, DBT *, DBT *, u_int));
+	int (*sync)	__P((const struct __db *, u_int));
+	void *internal;			/* Access method private. */
+	int (*fd)	__P((const struct __db *));
+} DB;
+
+#define	BTREEMAGIC	0x053162
+#define	BTREEVERSION	3
+
+/* Structure used to pass parameters to the btree routines. */
+typedef struct {
+#define	R_DUP		0x01	/* duplicate keys */
+	u_long	flags;
+	u_int	cachesize;	/* bytes to cache */
+	int	maxkeypage;	/* maximum keys per page */
+	int	minkeypage;	/* minimum keys per page */
+	u_int	psize;		/* page size */
+	int	(*compare)	/* comparison function */
+	    __P((const DBT *, const DBT *));
+	size_t	(*prefix)	/* prefix function */
+	    __P((const DBT *, const DBT *));
+	int	lorder;		/* byte order */
+} BTREEINFO;
+
+#define	HASHMAGIC	0x061561
+#define	HASHVERSION	3
+
+/* Structure used to pass parameters to the hashing routines. */
+typedef struct {
+	u_int	bsize;		/* bucket size */
+	u_int	ffactor;	/* fill factor */
+	u_int	nelem;		/* number of elements */
+	u_int	cachesize;	/* bytes to cache */
+	u_int32_t		/* hash function */
+		(*hash) __P((const void *, size_t));
+	int	lorder;		/* byte order */
+} HASHINFO;
+
+/* Structure used to pass parameters to the record routines. */
+typedef struct {
+#define	R_FIXEDLEN	0x01	/* fixed-length records */
+#define	R_NOKEY		0x02	/* key not required */
+#define	R_SNAPSHOT	0x04	/* snapshot the input */
+	u_long	flags;
+	u_int	cachesize;	/* bytes to cache */
+	u_int	psize;		/* page size */
+	int	lorder;		/* byte order */
+	size_t	reclen;		/* record length (fixed-length records) */
+	u_char	bval;		/* delimiting byte (variable-length records */
+	char	*bfname;	/* btree file name */ 
+} RECNOINFO;
+
+#if defined(__cplusplus)
+#define	__BEGIN_DECLS	extern "C" {
+#define	__END_DECLS	};
+#else
+#define	__BEGIN_DECLS
+#define	__END_DECLS
+#endif
+
+#define dbopen	kdb2_dbopen
+#define bt_rseq		kdb2_bt_rseq /* XXX kludge */
+__BEGIN_DECLS
+DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
+int	 bt_rseq(const DB*, DBT *, DBT *, void **, u_int); /* XXX kludge */
+__END_DECLS
+
+#endif /* !_DB_H_ */
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/libdb.exports b/krb5-1-6/src/plugins/kdb/db2/libdb2/libdb.exports
new file mode 100644
index 000000000..5dbc2e438
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/libdb.exports
@@ -0,0 +1,99 @@
+__default_hash
+__kdb2_add_bigpage
+__kdb2_add_ovflpage
+__kdb2_addel
+__kdb2_big_delete
+__kdb2_big_insert
+__kdb2_big_keydata
+__kdb2_big_return
+__kdb2_bt_close
+__kdb2_bt_cmp
+__kdb2_bt_defcmp
+__kdb2_bt_defpfx
+__kdb2_bt_deleaf
+__kdb2_bt_delete
+__kdb2_bt_fd
+__kdb2_bt_free
+__kdb2_bt_get
+__kdb2_bt_new
+__kdb2_bt_open
+__kdb2_bt_pgin
+__kdb2_bt_pgout
+__kdb2_bt_put
+__kdb2_bt_ret
+__kdb2_bt_search
+__kdb2_bt_seq
+__kdb2_bt_setcur
+__kdb2_bt_split
+__kdb2_bt_sync
+__kdb2_call_hash
+__kdb2_cursor_creat
+__kdb2_dbpanic
+__kdb2_delete_page
+__kdb2_delpair
+__kdb2_expand_table
+__kdb2_find_bigpair
+__kdb2_free_ovflpage
+__kdb2_get_bigkey
+__kdb2_get_item
+__kdb2_get_item_done
+__kdb2_get_item_first
+__kdb2_get_item_next
+__kdb2_get_item_reset
+__kdb2_get_page
+__kdb2_hash_open
+__kdb2_ibitmap
+__kdb2_log2
+__kdb2_new_page
+__kdb2_ovfl_delete
+__kdb2_ovfl_get
+__kdb2_ovfl_put
+__kdb2_pgin_routine
+__kdb2_pgout_routine
+__kdb2_put_page
+__kdb2_rec_close
+__kdb2_rec_delete
+__kdb2_rec_dleaf
+__kdb2_rec_fd
+__kdb2_rec_fmap
+__kdb2_rec_fpipe
+__kdb2_rec_get
+__kdb2_rec_iput
+__kdb2_rec_open
+__kdb2_rec_put
+__kdb2_rec_ret
+__kdb2_rec_search
+__kdb2_rec_seq
+__kdb2_rec_sync
+__kdb2_rec_vmap
+__kdb2_rec_vpipe
+__kdb2_split_page
+kdb2_bt_rseq
+kdb2_dbm_clearerr
+kdb2_dbm_close
+kdb2_dbm_delete
+kdb2_dbm_dirfno
+kdb2_dbm_error
+kdb2_dbm_fetch
+kdb2_dbm_firstkey
+kdb2_dbm_nextkey
+kdb2_dbm_open
+kdb2_dbm_store
+kdb2_dbminit
+kdb2_dbopen
+kdb2_delete
+kdb2_fetch
+kdb2_firstkey
+kdb2_hcreate
+kdb2_hdestroy
+kdb2_hsearch
+kdb2_mpool_close
+kdb2_mpool_delete
+kdb2_mpool_filter
+kdb2_mpool_get
+kdb2_mpool_new
+kdb2_mpool_open
+kdb2_mpool_put
+kdb2_mpool_sync
+kdb2_nextkey
+kdb2_store
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/Makefile.inc b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/Makefile.inc
new file mode 100644
index 000000000..f85cba1f8
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/Makefile.inc
@@ -0,0 +1,7 @@
+#       @(#)Makefile.inc	8.2 (Berkeley) 11/14/94
+
+.PATH: ${.CURDIR}/db/man
+
+MAN3+=	db_btree.0 db_hash.0 db_lock.0 db_log.0 db_mpool.0 db_open.0 \
+	db_recno.0
+MLINKS+=db_open.3 db.3 db_open.3 dbopen.3
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db.man.ps b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db.man.ps
new file mode 100644
index 000000000..23feea6e5
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db.man.ps
@@ -0,0 +1,2295 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 28
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 113.45(DB_BTREE\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 113.45(anual DB_BTREE\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)
+72 84 S(ME).18 E F0(db_btree \255 btree database access method)108 96 Q F1
+(DESCRIPTION)72 112.8 Q F0 .486(The DB library is a f)108 124.8 R .485
+(amily of groups of functions that pro)-.1 F .485
+(vides a modular programming interf)-.15 F .485(ace to trans-)-.1 F .822
+(actions and record-oriented \214le access.)108 136.8 R .822
+(The library includes support for transaction, locking, logging and)5.822 F
+.258(\214le b)108 148.8 R(uf)-.2 E .258(fering functionality)-.25 F 2.758(,a)
+-.65 G 2.758(sw)223.214 148.8 S .258(ell as v)237.082 148.8 R .258(arious inde)
+-.25 F -.15(xe)-.15 G 2.758(da).15 G .258(ccess methods.)331.434 148.8 R(Man)
+5.258 E 2.758(yo)-.15 G 2.758(ft)427.878 148.8 S .258
+(he functional groups \(e.g.)436.746 148.8 R .528(the memory pool functions\) \
+are useful independently of the rest of the DB functions, although some func-)
+108 160.8 R .306(tional groups are e)108 172.8 R .306
+(xplicitly based on other functional groups \(e.g.)-.15 F .306
+(transactions and logging\).)5.306 F -.15(Fo)5.306 G 2.806(rag).15 G(eneral)
+515.57 172.8 Q .245(description of transactions, see)108 184.8 R/F2 10
+/Times-Italic@0 SF(db_txn)2.745 E F0 2.745(\(3\). F).24 F .245
+(or a general description of the access methods, see)-.15 F F2(db_open)2.745 E
+F0(\(3\)).24 E .308(and then the indi)108 196.8 R .308
+(vidual access method manual pages:)-.25 F F2(db_btr)2.807 E(ee)-.37 E F0
+(\(3\),).18 E F2(db_hash)2.807 E F0(\(3\),).28 E F2(db_lo)2.807 E(g)-.1 E F0
+.307(\(3\) and).22 F F2(db_r)2.807 E(ecno)-.37 E F0(\(3\).).18 E -.15(Fo)108
+208.8 S 3.635(rag).15 G 1.135(eneral description of the lock manager)138.45
+208.8 R 3.635(,s)-.4 G(ee)307.32 208.8 Q F2(db_loc)3.635 E(k)-.2 E F0 3.635
+(\(3\). F).67 F 1.135(or a general description of the memory)-.15 F
+(pool manager)108 220.8 Q 2.5(,s)-.4 G(ee)171.2 220.8 Q F2(db_mpool)2.5 E F0
+(\(3\).).51 E
+(This manual page describes speci\214c details of the btree access method.)108
+237.6 Q 1.518(The btree data structure is a sorted, balanced tree structure st\
+oring associated k)108 254.4 R -.15(ey)-.1 G 1.517(/data pairs.).15 F
+(Searches,)6.517 E .598(insertions, and deletions in the btree will all comple\
+te in O lg base N where base is the a)108 266.4 R -.15(ve)-.2 G .598
+(rage \214ll f).15 F(actor)-.1 E(.)-.55 E .306
+(Often, inserting ordered data into btrees results in a lo)108 278.4 R 2.806
+<778c>-.25 G .305(ll f)341.61 278.4 R(actor)-.1 E 5.305(.T)-.55 G .305
+(his implementation has been modi\214ed)386.56 278.4 R(to mak)108 290.4 Q 2.5
+(eo)-.1 G(rdered insertion the best case, resulting in a much better than norm\
+al page \214ll f)147.34 290.4 Q(actor)-.1 E(.)-.55 E F1 -.495(AC)72 307.2 S
+(CESS METHOD SPECIFIC INFORMA).495 E(TION)-.855 E F0 .175
+(The btree access method speci\214c data structure pro)108 319.2 R .176
+(vided to)-.15 F F2(db_open)2.676 E F0 .176(is typedef)2.676 F 1.176 -.5('d a)
+.55 H .176(nd named BTREEINFO.).5 F 2.638(AB)108 331.2 S .138
+(TREEINFO structure has at least the follo)124.528 331.2 R .137
+(wing \214elds, which may be initialized before calling)-.25 F F2(db_open)2.637
+E F0(:).24 E(u_int cachesize;)108 348 Q 3.743(As)133 360 S 1.243
+(uggested maximum size \(in bytes\) of the memory cache.)147.853 360 R 1.243
+(This v)6.243 F 1.243(alue is)-.25 F/F3 10/Times-Bold@0 SF(only)3.743 E F0
+(advisory)3.743 E 3.744(,a)-.65 G 1.244(nd the)514.036 360 R .017
+(access method will allocate more memory rather than f)133 372 R 2.517
+(ail. Since)-.1 F -2.15 -.25(ev e)2.517 H .016(ry search e).25 F .016
+(xamines the root page)-.15 F 1.319
+(of the tree, caching the most recently used pages substantially impro)133 384
+R -.15(ve)-.15 G 3.82(sa).15 G 1.32(ccess time.)441.05 384 R 1.32(In addition,)
+6.32 F(ph)133 396 Q .911(ysical writes are delayed as long as possible, so a m\
+oderate cache can reduce the number of I/O)-.05 F 1.497
+(operations signi\214cantly)133 408 R 6.497(.O)-.65 G -.15(bv)243.674 408 S
+(iously).15 E 3.997(,u)-.65 G 1.497(sing a cache increases \(b)288.821 408 R
+1.498(ut only increases\) the lik)-.2 F 1.498(elihood of)-.1 F .336(corruption\
+ or lost data if the system crashes while a tree is being modi\214ed.)133 420 R
+(If)5.336 E F2(cac)2.836 E(hesize)-.15 E F0 .335(is 0 \(no size)2.835 F
+(is speci\214ed\) a def)133 432 Q(ault cache is used.)-.1 E
+(int \(*compare\)\(const DBT *, const DBT *\);)108 448.8 Q .194
+(Compare is the k)133 460.8 R .494 -.15(ey c)-.1 H .194(omparison function.).15
+F .194(It must return an inte)5.194 F .194
+(ger less than, equal to, or greater than)-.15 F .656(zero if the \214rst k)133
+472.8 R .956 -.15(ey a)-.1 H -.18(rg).15 G .656
+(ument is considered to be respecti).18 F -.15(ve)-.25 G .655
+(ly less than, equal to, or greater than the).15 F .798(second k)133 484.8 R
+1.098 -.15(ey a)-.1 H -.18(rg).15 G 3.298(ument. The).18 F .798
+(same comparison function must be used on a gi)3.298 F -.15(ve)-.25 G 3.298(nt)
+.15 G .799(ree e)462.774 484.8 R -.15(ve)-.25 G .799(ry time it is).15 F 2.79
+(opened. If)133 496.8 R F2(compar)2.79 E(e)-.37 E F0 .29
+(is NULL \(no comparison function is speci\214ed\), the k)2.79 F -.15(ey)-.1 G
+2.79(sa).15 G .29(re compared le)451.08 496.8 R(xically)-.15 E(,)-.65 E
+(with shorter k)133 508.8 Q -.15(ey)-.1 G 2.5(sc).15 G
+(onsidered less than longer k)208.57 508.8 Q -.15(ey)-.1 G(s.).15 E
+(u_long \215ags;)108 525.6 Q(The \215ag v)133 537.6 Q(alue is speci\214ed by)
+-.25 E F2(or)2.5 E F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)302.2 537.6 S
+(he follo)310.81 537.6 Q(wing v)-.25 E(alues:)-.25 E(R_DUP)133 554.4 Q .354
+(Permit duplicate k)158 566.4 R -.15(ey)-.1 G 2.854(si).15 G 2.854(nt)250.752
+566.4 S .355(he tree, i.e. permit insertion if the k)261.386 566.4 R .655 -.15
+(ey t)-.1 H 2.855(ob).15 G 2.855(ei)432.64 566.4 S .355(nserted already e)
+442.715 566.4 R .355(xists in)-.15 F 1.65(the tree.)158 578.4 R 1.65(The def)
+6.65 F 1.65(ault beha)-.1 F(vior)-.2 E 4.149(,a)-.4 G 4.149(sd)295.509 578.4 S
+1.649(escribed in)308.548 578.4 R F2(db_open)4.149 E F0 1.649(\(3\), is to o)
+.24 F -.15(ve)-.15 G 1.649(rwrite a matching k).15 F -.15(ey)-.1 G .783
+(when inserting a ne)158 590.4 R 3.283(wk)-.25 G 1.083 -.15(ey o)253.542 590.4
+T 3.283(rt).15 G 3.283(of)280.508 590.4 S .783(ail if the R_NOO)292.021 590.4 R
+(VER)-.5 E .784(WRITE \215ag is speci\214ed.)-.55 F .784(The R_DUP)5.784 F .129
+(\215ag is o)158 602.4 R -.15(ve)-.15 G .129(rridden by the R_NOO).15 F(VER)-.5
+E .128(WRITE \215ag, and if the R_NOO)-.55 F(VER)-.5 E .128
+(WRITE \215ag is spec-)-.55 F(i\214ed, attempts to insert duplicate k)158 614.4
+Q -.15(ey)-.1 G 2.5(si).15 G(nto the tree will f)314.69 614.4 Q(ail.)-.1 E .835
+(If the database contains duplicate k)158 631.2 R -.15(ey)-.1 G .835
+(s, the order of retrie).15 F -.25(va)-.25 G 3.335(lo).25 G 3.336(fk)414.7
+631.2 S -.15(ey)426.266 631.2 S .836(/data pairs is unde\214ned if).15 F(the)
+158 643.2 Q F2 -.1(ge)3.003 G(t).1 E F0 .503(function is used, ho)3.003 F(we)
+-.25 E -.15(ve)-.25 G -.4(r,).15 G F2(seq)3.403 E F0 .502
+(function calls with the R_CURSOR \215ag set will al)3.003 F -.1(wa)-.1 G(ys).1
+E(return the logical `)158 655.2 Q(`\214rst')-.74 E 2.5('o)-.74 G 2.5(fa)263.72
+655.2 S .3 -.15(ny g)273.99 655.2 T(roup of duplicate k).15 E -.15(ey)-.1 G(s.)
+.15 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315
+(ution August)-.2 F(1, 1995)2.5 E(1)535 732 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 113.45(DB_BTREE\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 113.45(anual DB_BTREE\(3\))340.17 48 R(int lorder;)108 84 Q .65
+(The byte order for inte)133 96 R .65(gers in the stored database metadata.)
+-.15 F .65(The number should represent the order)5.65 F .749(as an inte)133 108
+R .749(ger; for e)-.15 F .749(xample, big endian order w)-.15 F .749
+(ould be the number 4,321.)-.1 F(If)5.749 E/F1 10/Times-Italic@0 SF(lor)3.249 E
+(der)-.37 E F0 .749(is 0 \(no order is)3.249 F
+(speci\214ed\) the current host order is used.)133 120 Q(int maxk)108 136.8 Q
+-.15(ey)-.1 G(page;).15 E .073(The maximum number of k)133 148.8 R -.15(ey)-.1
+G 2.573(sw).15 G .073(hich will be stored on an)266.155 148.8 R 2.574(ys)-.15 G
+.074(ingle page.)376.436 148.8 R .074(This functionality is not cur)5.074 F(-)
+-.2 E(rently implemented.)133 160.8 Q(int mink)108 177.6 Q -.15(ey)-.1 G(page;)
+.15 E .532(The minimum number of k)133 189.6 R -.15(ey)-.1 G 3.031(sw).15 G
+.531(hich will be stored on an)266.787 189.6 R 3.031(ys)-.15 G .531
+(ingle page.)379.813 189.6 R .531(This v)5.531 F .531(alue is used to deter)
+-.25 F(-)-.2 E .558(mine which k)133 201.6 R -.15(ey)-.1 G 3.058(sw).15 G .558
+(ill be stored on o)211.914 201.6 R -.15(ve)-.15 G(r\215o).15 E 3.058(wp)-.25 G
+.558(ages, i.e. if a k)319.424 201.6 R .859 -.15(ey o)-.1 H 3.059(rd).15 G .559
+(ata item is longer than the page-)408.336 201.6 R .063(size di)133 213.6 R
+.063(vided by the mink)-.25 F -.15(ey)-.1 G .063(page v).15 F .063
+(alue, it will be stored on o)-.25 F -.15(ve)-.15 G(r\215o).15 E 2.563(wp)-.25
+G .062(ages instead of in the page itself.)408.816 213.6 R(If)133 225.6 Q F1
+(mink)2.5 E -.3(ey)-.1 G(pa).3 E -.1(ge)-.1 G F0(is 0 \(no minimum number of k)
+2.6 E -.15(ey)-.1 G 2.5(si).15 G 2.5(ss)332.96 225.6 S(peci\214ed\) a v)343.24
+225.6 Q(alue of 2 is used.)-.25 E
+(size_t \(*pre\214x\)\(const DBT *, const DBT *\);)108 242.4 Q .691
+(Pre\214x is the pre\214x comparison function.)133 254.4 R .692
+(If speci\214ed, this function must return the number of bytes)5.691 F .195
+(of the second k)133 266.4 R .495 -.15(ey a)-.1 H -.18(rg).15 G .195
+(ument which are necessary to determine that it is greater than the \214rst k)
+.18 F .495 -.15(ey a)-.1 H -.18(rg).15 G(u-).18 E 2.994(ment. If)133 278.4 R
+.494(the k)2.994 F -.15(ey)-.1 G 2.994(sa).15 G .494(re equal, the k)211.376
+278.4 R .794 -.15(ey l)-.1 H .494(ength should be returned.).15 F .494
+(Note, the usefulness of this function)5.494 F .327(is v)133 290.4 R .327
+(ery data dependent, b)-.15 F .326(ut, in some data sets can produce signi\214\
+cantly reduced tree sizes and search)-.2 F 2.789(times. If)133 302.4 R F1(pr)
+2.789 E(e\214x)-.37 E F0 .289(is NULL \(no pre\214x function is speci\214ed\),)
+2.789 F/F2 10/Times-Bold@0 SF(and)2.789 E F0 .29
+(no comparison function is speci\214ed, a)2.79 F(def)133 314.4 Q .902(ault le)
+-.1 F .902(xical comparison function is used.)-.15 F(If)5.901 E F1(pr)3.401 E
+(e\214x)-.37 E F0 .901(is NULL and a comparison function is speci-)3.401 F
+(\214ed, no pre\214x comparison is done.)133 326.4 Q(u_int psize;)108 343.2 Q
+-.15(Pa)133 355.2 S .118
+(ge size is the size \(in bytes\) of the pages used for nodes in the tree.).15
+F .119(The minimum page size is 512)5.119 F .377
+(bytes and the maximum page size is 64K.)133 367.2 R(If)5.376 E F1(psize)2.876
+E F0 .376(is 0 \(no page size is speci\214ed\) a page size is cho-)2.876 F
+(sen based on the underlying \214le system I/O block size.)133 379.2 Q .79
+(If the \214le already e)108 396 R .79(xists \(and the O_TR)-.15 F .79
+(UNC \215ag is not speci\214ed\), the v)-.4 F .79
+(alues speci\214ed for the parameters)-.25 F
+(\215ags, lorder and psize are ignored in f)108 408 Q -.2(avo)-.1 G 2.5(ro).2 G
+2.5(ft)284.4 408 S(he v)293.01 408 Q(alues used when the tree w)-.25 E
+(as created.)-.1 E/F3 9/Times-Bold@0 SF(DB OPERA)72 424.8 Q(TIONS)-.855 E F0
+1.037(The functions returned by)108 436.8 R F1(db_open)3.537 E F0 1.036
+(for the btree access method are as described in)3.536 F F1(db_open)3.536 E F0
+1.036(\(3\), with the).24 F(follo)108 448.8 Q(wing e)-.25 E
+(xceptions and additions:)-.15 E 5.28(type The)108 465.6 R(type is DB_BTREE.)
+2.5 E 10.28(del Space)108 482.4 R 1.681(freed up by deleting k)4.181 F -.15(ey)
+-.1 G 1.681(/data pairs from the tree is ne).15 F -.15(ve)-.25 G 4.181(rr).15 G
+1.682(eclaimed, although it is reused)411.342 482.4 R .734(where possible.)133
+494.4 R .734(This means that the btree storage structure is gro)5.734 F(w-only)
+-.25 E 5.734(.T)-.65 G .734(he only solutions are to)443.734 494.4 R -.2(avo)
+133 506.4 S(id e).2 E(xcessi)-.15 E .3 -.15(ve d)-.25 H
+(eletions, or to create a fresh tree periodically from a scan of an e).15 E
+(xisting one.)-.15 E 9.72(put The)108 523.2 R F1(put)2.5 E F0(function tak)2.5
+E(es the follo)-.1 E(wing additional \215ags:)-.25 E(R_SETCURSOR)133 540 Q
+(Store the k)158 552 Q -.15(ey)-.1 G(/data pair).15 E 2.5(,s)-.4 G
+(etting or initializing the position of the cursor to reference it.)256.5 552 Q
+9.17(seq F)108 568.8 R(orw)-.15 E
+(ard sequential scans of a tree are from the least k)-.1 E .3 -.15(ey t)-.1 H
+2.5(ot).15 G(he greatest.)373.55 568.8 Q .892(The returned k)133 585.6 R 1.192
+-.15(ey f)-.1 H .892(or the).15 F F1(seq)3.393 E F0 .893
+(function is not necessarily an e)3.393 F .893
+(xact match for the speci\214ed k)-.15 F 1.193 -.15(ey i)-.1 H 3.393(nt).15 G
+(he)530.56 585.6 Q .5(btree access method.)133 597.6 R .5(The returned k)5.5 F
+.8 -.15(ey i)-.1 H 3(st).15 G .499(he smallest k)307.04 597.6 R .799 -.15(ey g)
+-.1 H .499(reater than or equal to the speci\214ed k).15 F -.15(ey)-.1 G(,)-.5
+E(permitting partial k)133 609.6 Q .3 -.15(ey m)-.1 H
+(atches and range searches.).15 E(The)133 626.4 Q F1(seq)2.5 E F0(function tak)
+2.5 E(es the follo)-.1 E(wing additional \215ags:)-.25 E(R_LAST)133 643.2 Q .04
+(The last k)158 655.2 R -.15(ey)-.1 G .04(/data pair of the database is return\
+ed, and the cursor is set or initialized to reference).15 F(it.)158 667.2 Q
+(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315
+(ution August)-.2 F(1, 1995)2.5 E(2)535 732 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 113.45(DB_BTREE\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 113.45(anual DB_BTREE\(3\))340.17 48 R(R_PREV)133 84 Q(Retrie)158 96
+Q .59 -.15(ve t)-.25 H .29(he k).15 F -.15(ey)-.1 G .29
+(/data pair immediately before the cursor).15 F 5.29(.I)-.55 G 2.79(ft)395.73
+96 S .29(he cursor is not yet set, this is the)404.63 96 R
+(same as the R_LAST \215ag.)158 108 Q/F1 9/Times-Bold@0 SF(ERR)72 124.8 Q(ORS)
+-.27 E F0(The)108 136.8 Q/F2 10/Times-Italic@0 SF(btr)2.541 E(ee)-.37 E F0 .041
+(access method functions may f)2.541 F .041(ail and set)-.1 F F2(errno)2.541 E
+F0 .041(for an)2.541 F 2.541(yo)-.15 G 2.541(ft)376.152 136.8 S .041
+(he errors speci\214ed for the library func-)384.803 136.8 R(tion)108 148.8 Q
+F2(db_open)2.5 E F0(\(3\).).24 E F1(SEE ALSO)72 165.6 Q F2(db_hash)108 177.6 Q
+F0(\(3\),).28 E F2(db_loc)2.5 E(k)-.2 E F0(\(3\),).67 E F2(db_lo)2.5 E(g)-.1 E
+F0(\(3\),).22 E F2(db_mpool)2.5 E F0(\(3\),).51 E F2(db_open)2.5 E F0(\(3\),)
+.24 E F2(db_r)2.5 E(ecno)-.37 E F0(\(3\),).18 E F2(db_txn)2.5 E F0(\(3\)).24 E
+F2(The Ubiquitous B-tr)108 201.6 Q(ee)-.37 E F0 2.5(,D).18 G(ouglas Comer)
+209.47 201.6 Q 2.5(,A)-.4 G(CM Comput. Surv)276.72 201.6 Q 2.5(.1)-.65 G
+(1, 2 \(June 1979\), 121-138.)360.25 201.6 Q F2(Pr)108 225.6 Q 1.588
+(e\214x B-tr)-.37 F(ees)-.37 E F0 4.088(,B).27 G 1.587(ayer and Unterauer)
+177.636 225.6 R 4.087(,A)-.4 G 1.587(CM T)270.447 225.6 R 1.587
+(ransactions on Database Systems, V)-.35 F 1.587(ol. 2, 1 \(March 1977\),)-1.29
+F(11-26.)108 237.6 Q F2(The Art of Computer Pr)108 261.6 Q -.1(og)-.45 G -.15
+(ra).1 G(mming V).15 E(ol. 3: Sorting and Sear)-1.11 E -.15(ch)-.37 G(ing).15 E
+F0 2.5(,D).22 G(.E. Knuth, 1968, pp 471-480.)382 261.6 Q(4.4 Berk)72 732 Q(ele)
+-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E
+(3)535 732 Q EP
+%%Page: 1 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 117.9(DB_HASH\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 117.9(anual DB_HASH\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72
+84 S(ME).18 E F0(db_hash \255 hash database access method)108 96 Q F1
+(DESCRIPTION)72 112.8 Q F0 .485(The DB library is a f)108 124.8 R .485
+(amily of groups of functions that pro)-.1 F .486
+(vides a modular programming interf)-.15 F .486(ace to trans-)-.1 F .823
+(actions and record-oriented \214le access.)108 136.8 R .822
+(The library includes support for transaction, locking, logging and)5.822 F
+.258(\214le b)108 148.8 R(uf)-.2 E .258(fering functionality)-.25 F 2.758(,a)
+-.65 G 2.758(sw)223.214 148.8 S .258(ell as v)237.082 148.8 R .258(arious inde)
+-.25 F -.15(xe)-.15 G 2.758(da).15 G .258(ccess methods.)331.434 148.8 R(Man)
+5.258 E 2.758(yo)-.15 G 2.758(ft)427.878 148.8 S .258
+(he functional groups \(e.g.)436.746 148.8 R .528(the memory pool functions\) \
+are useful independently of the rest of the DB functions, although some func-)
+108 160.8 R .306(tional groups are e)108 172.8 R .306
+(xplicitly based on other functional groups \(e.g.)-.15 F .306
+(transactions and logging\).)5.306 F -.15(Fo)5.306 G 2.806(rag).15 G(eneral)
+515.57 172.8 Q .245(description of transactions, see)108 184.8 R/F2 10
+/Times-Italic@0 SF(db_txn)2.745 E F0 2.745(\(3\). F).24 F .245
+(or a general description of the access methods, see)-.15 F F2(db_open)2.745 E
+F0(\(3\)).24 E .307(and then the indi)108 196.8 R .307
+(vidual access method manual pages:)-.25 F F2(db_btr)2.808 E(ee)-.37 E F0
+(\(3\),).18 E F2(db_hash)2.808 E F0(\(3\),).28 E F2(db_lo)2.808 E(g)-.1 E F0
+.308(\(3\) and).22 F F2(db_r)2.808 E(ecno)-.37 E F0(\(3\).).18 E -.15(Fo)108
+208.8 S 3.635(rag).15 G 1.135(eneral description of the lock manager)138.45
+208.8 R 3.635(,s)-.4 G(ee)307.32 208.8 Q F2(db_loc)3.635 E(k)-.2 E F0 3.635
+(\(3\). F).67 F 1.135(or a general description of the memory)-.15 F
+(pool manager)108 220.8 Q 2.5(,s)-.4 G(ee)171.2 220.8 Q F2(db_mpool)2.5 E F0
+(\(3\).).51 E
+(This manual page describes speci\214c details of the hashing access method.)
+108 237.6 Q .59(The hash data structure is an e)108 254.4 R .591
+(xtensible, dynamic hashing scheme.)-.15 F(Backw)5.591 E .591
+(ard compatible interf)-.1 F .591(aces to the)-.1 F .209
+(functions described in)108 266.4 R F2(dbm)2.709 E F0 .209(\(3\), and).32 F F2
+(ndbm)2.709 E F0 .209(\(3\) are pro).32 F .209(vided, ho)-.15 F(we)-.25 E -.15
+(ve)-.25 G 2.708(rt).15 G .208(hese interf)382.71 266.4 R .208
+(aces are not compatible with)-.1 F(pre)108 278.4 Q(vious \214le formats.)-.25
+E F1 -.495(AC)72 295.2 S(CESS METHOD SPECIFIC INFORMA).495 E(TION)-.855 E F0
+.612(The hash access method speci\214c data structure pro)108 307.2 R .612
+(vided to)-.15 F F2(db_open)3.112 E F0 .612(is typedef)3.112 F 1.612 -.5('d a)
+.55 H .613(nd named HASHINFO.).5 F 2.5(AH)108 319.2 S
+(ASHINFO structure has at least the follo)124.94 319.2 Q
+(wing \214elds, which may be initialized before calling)-.25 E F2(db_open)2.5 E
+F0(:).24 E(u_int bsize;)108 336 Q F2(Bsize)133 348 Q F0 2.041
+(de\214nes the hash table b)4.541 F(uck)-.2 E 2.041(et size, and is, by def)-.1
+F 2.04(ault, 256 bytes.)-.1 F 2.04(It may be preferable to)7.04 F
+(increase the page size for disk-resident tables and tables with lar)133 360 Q
+(ge data items.)-.18 E(u_int cachesize;)108 376.8 Q 3.846(As)133 388.8 S 1.347
+(uggested maximum size, in bytes, of the memory cache.)147.956 388.8 R 1.347
+(This v)6.347 F 1.347(alue is)-.25 F/F3 10/Times-Bold@0 SF(only)3.847 E F0
+(advisory)3.847 E 3.847(,a)-.65 G 1.347(nd the)513.933 388.8 R
+(access method will allocate more memory rather than f)133 400.8 Q(ail.)-.1 E
+(u_int f)108 417.6 Q -.1(fa)-.25 G(ctor;).1 E F2(Ffactor)133 429.6 Q F0 1.17
+(indicates a desired density within the hash table.)3.67 F 1.169
+(It is an approximation of the number of)6.169 F -.1(ke)133 441.6 S 1.162
+(ys allo)-.05 F 1.162(wed to accumulate in an)-.25 F 3.662(yo)-.15 G 1.162
+(ne b)284.852 441.6 R(uck)-.2 E 1.162(et, determining when the hash table gro)
+-.1 F 1.162(ws or shrinks.)-.25 F(The def)133 453.6 Q(ault v)-.1 E(alue is 8.)
+-.25 E(u_int32_t \(*hash\)\(const v)108 470.4 Q(oid *, size_t\);)-.2 E F2(Hash)
+133 482.4 Q F0 .788(is a user de\214ned hash function.)3.288 F .787
+(Since no hash function performs equally well on all possible)5.788 F .017
+(data, the user may \214nd that the b)133 494.4 R .018
+(uilt-in hash function does poorly on a particular data set.)-.2 F .018
+(User speci-)5.018 F 1.154(\214ed hash functions must tak)133 506.4 R 3.654(et)
+-.1 G 1.354 -.1(wo a)260.61 506.4 T -.18(rg).1 G 1.154
+(uments \(a pointer to a byte string and a length\) and return a).18 F
+(32-bit quantity to be used as the hash v)133 518.4 Q(alue.)-.25 E .665
+(If a hash function is speci\214ed,)133 535.2 R F2(hash_open)3.165 E F0 .666
+(will attempt to determine if the hash function speci\214ed is)3.166 F
+(the same as the one with which the database w)133 547.2 Q
+(as created, and will f)-.1 E(ail if it is not.)-.1 E(int lorder;)108 564 Q .65
+(The byte order for inte)133 576 R .65(gers in the stored database metadata.)
+-.15 F .65(The number should represent the order)5.65 F .748(as an inte)133 588
+R .749(ger; for e)-.15 F .749(xample, big endian order w)-.15 F .749
+(ould be the number 4,321.)-.1 F(If)5.749 E F2(lor)3.249 E(der)-.37 E F0 .749
+(is 0 \(no order is)3.249 F .456(speci\214ed\) the current host order is used.)
+133 600 R .456(If the)5.456 F .456(\214le already e)5.456 F .456
+(xists, the speci\214ed v)-.15 F .455(alue is ignored and)-.25 F(the v)133 612
+Q(alue speci\214ed when the tree w)-.25 E(as created is used.)-.1 E
+(u_int nelem;)108 628.8 Q F2(Nelem)133 640.8 Q F0 1.225
+(is an estimate of the \214nal size of the hash table.)3.724 F 1.225
+(If not set or set too lo)6.225 F 2.525 -.65(w, h)-.25 H 1.225(ash tables will)
+.65 F -.15(ex)133 652.8 S 1.294(pand gracefully as k).15 F -.15(ey)-.1 G 3.794
+(sa).15 G 1.294(re entered, although a slight performance de)248.296 652.8 R
+1.293(gradation may be noticed.)-.15 F(The def)133 664.8 Q(ault v)-.1 E
+(alue is 1.)-.25 E .79(If the \214le already e)108 681.6 R .79
+(xists \(and the O_TR)-.15 F .79(UNC \215ag is not speci\214ed\), the v)-.4 F
+.79(alues speci\214ed for the parameters)-.25 F(bsize, f)108 693.6 Q -.1(fa)
+-.25 G(ctor).1 E 2.5(,l)-.4 G(order and nelem are ignored and the v)167.23
+693.6 Q(alues speci\214ed when the tree w)-.25 E(as created are used.)-.1 E
+(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315
+(ution August)-.2 F(1, 1995)2.5 E(1)535 732 Q EP
+%%Page: 2 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 117.9(DB_HASH\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 117.9(anual DB_HASH\(3\))340.17 48 R/F1 9/Times-Bold@0 SF(DB OPERA)
+72 84 Q(TIONS)-.855 E F0(The functions returned by)108 96 Q/F2 10
+/Times-Italic@0 SF(db_open)2.5 E F0
+(for the hash access method are as described in)2.5 E F2(db_open)2.5 E F0
+(\(3\).).24 E F1(ERR)72 112.8 Q(ORS)-.27 E F0(The)108 124.8 Q F2(hash)2.609 E
+F0 .109(access method functions may f)2.609 F .109(ail and set)-.1 F F2(errno)
+2.609 E F0 .109(for an)2.609 F 2.609(yo)-.15 G 2.609(ft)375.678 124.8 S .109
+(he errors speci\214ed for the library func-)384.397 124.8 R(tion)108 136.8 Q
+F2(db_open)2.5 E F0(\(3\).).24 E F1(SEE ALSO)72 153.6 Q F2(db_btr)108 165.6 Q
+(ee)-.37 E F0(\(3\),).18 E F2(db_loc)2.5 E(k)-.2 E F0(\(3\),).67 E F2(db_lo)2.5
+E(g)-.1 E F0(\(3\),).22 E F2(db_mpool)2.5 E F0(\(3\),).51 E F2(db_open)2.5 E F0
+(\(3\),).24 E F2(db_r)2.5 E(ecno)-.37 E F0(\(3\),).18 E F2(db_txn)2.5 E F0
+(\(3\)).24 E F2(Dynamic Hash T)108 189.6 Q(ables)-.92 E F0 2.5(,P).27 G(er)
+206.79 189.6 Q(-Ak)-.2 E 2.5(eL)-.1 G(arson, Communications of the A)242.86
+189.6 Q(CM, April 1988.)-.4 E F2 2.5(AN)108 213.6 S .3 -.15(ew H)123.28 213.6 T
+(ash P).15 E(ac)-.8 E(ka)-.2 E .2 -.1(ge f)-.1 H(or UNIX).1 E F0 2.5(,M).94 G
+(ar)248.41 213.6 Q(go Seltzer)-.18 E 2.5(,U)-.4 G(SENIX Proceedings, W)308.09
+213.6 Q(inter 1991.)-.4 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)
+132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(2)535 732 Q EP
+%%Page: 1 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 117.9(DB_LOCK\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 117.9(anual DB_LOCK\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72
+84 S(ME).18 E F0(db_lock \255 general purpose lock manager)108 96 Q F1
+(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(#include <db_lock.h>)108 124.8 Q
+(int)108 148.8 Q(lock_cr)108 160.8 Q(eate\(const char *path, mode_t mode,)-.18
+E(int lock_modes, const int8_t con\215icts[][], u_int maxlocks\);)158 172.8 Q
+(LOCK_T)108 196.8 Q(ABLE_T *)-.9 E(lock_open\(const char *path\);)108 208.8 Q
+(int)108 232.8 Q(lock_v)108 244.8 Q(ec\(LOCK_T)-.1 E(ABLE_T *lt, DBT *lock)-.9
+E(er)-.1 E 2.5(,s)-.92 G(truct timespec *timeout,)308.21 244.8 Q
+(LOCK_REQ_T list[], int nlist, LOCK_REQ_T **elistp, DBT *con\215ict\);)158
+256.8 Q(int)108 280.8 Q(lock_get\(LOCK_T)108 292.8 Q
+(ABLE_T *lt, const DBT *lock)-.9 E(er)-.1 E(,)-.92 E
+(const DBT *obj, const lock_mode_t lock_mode, LOCK_T **lockp\);)158 304.8 Q
+(int)108 328.8 Q(lock_put\(LOCK_T *lockp\);)108 340.8 Q(int)108 364.8 Q
+(lock_close\(LOCK_T)108 376.8 Q(ABLE_T *lt\);)-.9 E(int)108 400.8 Q
+(lock_unlink\(const char *path, int f)108 412.8 Q(or)-.25 E(ce\);)-.18 E F1
+(DESCRIPTION)72 429.6 Q F0 .485(The DB library is a f)108 441.6 R .485
+(amily of groups of functions that pro)-.1 F .486
+(vides a modular programming interf)-.15 F .486(ace to trans-)-.1 F .823
+(actions and record-oriented \214le access.)108 453.6 R .822
+(The library includes support for transaction, locking, logging and)5.822 F
+.258(\214le b)108 465.6 R(uf)-.2 E .258(fering functionality)-.25 F 2.758(,a)
+-.65 G 2.758(sw)223.214 465.6 S .258(ell as v)237.082 465.6 R .258(arious inde)
+-.25 F -.15(xe)-.15 G 2.758(da).15 G .258(ccess methods.)331.434 465.6 R(Man)
+5.258 E 2.758(yo)-.15 G 2.758(ft)427.878 465.6 S .258
+(he functional groups \(e.g.)436.746 465.6 R .528(the memory pool functions\) \
+are useful independently of the rest of the DB functions, although some func-)
+108 477.6 R .306(tional groups are e)108 489.6 R .306
+(xplicitly based on other functional groups \(e.g.)-.15 F .306
+(transactions and logging\).)5.306 F -.15(Fo)5.306 G 2.806(rag).15 G(eneral)
+515.57 489.6 Q .245(description of transactions, see)108 501.6 R/F3 10
+/Times-Italic@0 SF(db_txn)2.745 E F0 2.745(\(3\). F).24 F .245
+(or a general description of the access methods, see)-.15 F F3(db_open)2.745 E
+F0(\(3\)).24 E .307(and then the indi)108 513.6 R .307
+(vidual access method manual pages:)-.25 F F3(db_btr)2.808 E(ee)-.37 E F0
+(\(3\),).18 E F3(db_hash)2.808 E F0(\(3\),).28 E F3(db_lo)2.808 E(g)-.1 E F0
+.308(\(3\) and).22 F F3(db_r)2.808 E(ecno)-.37 E F0(\(3\).).18 E -.15(Fo)108
+525.6 S 3.635(rag).15 G 1.135(eneral description of the lock manager)138.45
+525.6 R 3.635(,s)-.4 G(ee)307.32 525.6 Q F3(db_loc)3.635 E(k)-.2 E F0 3.635
+(\(3\). F).67 F 1.135(or a general description of the memory)-.15 F
+(pool manager)108 537.6 Q 2.5(,s)-.4 G(ee)171.2 537.6 Q F3(db_mpool)2.5 E F0
+(\(3\).).51 E
+(This manual page describes speci\214c details of the locking interf)108 554.4
+Q(ace.)-.1 E F3(Db_loc)108 571.2 Q(k)-.2 E F0 .346(is the library interf)2.846
+F .346(ace intended to pro)-.1 F .346(vide general-purpose locking.)-.15 F .347
+(While designed to w)5.347 F .347(ork with)-.1 F .946(the other DB functions, \
+these functions are also useful for more general locking purposes.)108 583.2 R
+.946(Locks can be)5.946 F(shared between processes.)108 595.2 Q .682
+(The function)108 612 R F3(loc)3.182 E(k_cr)-.2 E(eate)-.37 E F0 .683
+(creates and initializes the lock table identi\214ed by the)3.182 F F3(path)
+3.183 E F0(directory)3.183 E 5.683(.T)-.65 G .683(his direc-)501.827 612 R .565
+(tory must already e)108 624 R .565(xist when)-.15 F F3(loc)3.065 E(k_cr)-.2 E
+(eate)-.37 E F0 .565(is called.)3.065 F .565(If the lock table identi\214ed by)
+5.565 F F3(path)3.064 E F0 .564(already e)3.064 F .564(xists, then)-.15 F F3
+(loc)108 636 Q(k_cr)-.2 E(eate)-.37 E F0 .974
+(returns success without further action.)3.474 F .974
+(The \214les associated with the lock table are created in)5.974 F 2.017
+(the directory speci\214ed by)108 648 R F3(path)4.517 E F0 7.017(.\().28 G
+2.017(The group of the created \214les is based on the system and directory)
+250.846 648 R(def)108 660 Q .076(aults, and is not further speci\214ed by)-.1 F
+F3(loc)2.576 E(k_cr)-.2 E(eate)-.37 E F0 2.576(.\) All).18 F .076
+(\214les created by)2.576 F F3(loc)2.576 E(k_cr)-.2 E(eate)-.37 E F0 .077
+(are created with mode)2.577 F F3(mode)108 672 Q F0(\(as described in)2.5 E F3
+-.15(ch)2.5 G(mod).15 E F0(\(2\)\) and modi\214ed by the process' umask v).77 E
+(alue \(see)-.25 E F3(umask)2.5 E F0(\(2\)\).).67 E .739(The parameter)108
+688.8 R F3(loc)3.239 E(k_modes)-.2 E F0 .739(is the number of lock modes to be\
+ recognized by the lock table \(including the)3.239 F(4.4 Berk)72 732 Q(ele)-.1
+E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(1)
+535 732 Q EP
+%%Page: 2 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 117.9(DB_LOCK\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 117.9(anual DB_LOCK\(3\))340.17 48 R -.74(``)108 84 S(not-granted')
+.74 E 2.5('m)-.74 G 2.5(ode\). The)176.22 84 R(parameter)2.5 E/F1 10
+/Times-Italic@0 SF(con\215icts)2.5 E F0(is an)2.5 E F1(loc)2.5 E(k_modes)-.2 E
+F0(by)2.5 E F1(loc)2.5 E(k_modes)-.2 E F0(array)2.5 E 5(.A)-.65 G(non-0 v)
+467.59 84 Q(alue for:)-.25 E(con\215icts[requested_mode][held_mode])158 108 Q
+.174(indicates that)108 132 R F1 -.37(re)2.674 G(quested_mode).37 E F0(and)
+2.674 E F1(held_mode)2.674 E F0 2.675(con\215ict. The)2.674 F -.74(``)2.675 G
+(not-granted').74 E 2.675('m)-.74 G .175(ode must be represented by 0.)419.705
+132 R(The include \214le <db_lock.h> declares tw)108 148.8 Q 2.5(oc)-.1 G
+(ommonly used con\215ict arrays:)283.87 148.8 Q(int lock_sx_n;)108 165.6 Q
+(const int8_t lock_sx_c[lock_sx_n][lock_sx_n];)108 177.6 Q(These v)133 189.6 Q
+(ariables specify a con\215ict array for a simple scheme using shared and e)
+-.25 E(xclusi)-.15 E .3 -.15(ve l)-.25 H(ock modes.).15 E(int lock_g_n;)108
+206.4 Q(const int8_t lock_g_c[lock_g_n][lock_g_n];)108 218.4 Q 1.071(These v)
+133 230.4 R 1.071(ariables specify a con\215ict array that in)-.25 F -.2(vo)-.4
+G(lv).2 E 1.071(es v)-.15 F 1.07
+(arious intent lock modes \(e.g. intent shared\))-.25 F
+(that are used for multigranularity locking.)133 242.4 Q 1.53
+(In addition, <db_lock.h> de\214nes the follo)108 259.2 R 1.531
+(wing macros that name lock modes for use with the standard)-.25 F(tables abo)
+108 271.2 Q -.15(ve)-.15 G(:).15 E(LOCK_IS)144 288 Q(intent shared)169 300 Q
+(LOCK_IX)144 312 Q(intent e)169 324 Q(xclusi)-.15 E -.15(ve)-.25 G(LOCK_NG)144
+336 Q(not granted \(al)169 348 Q -.1(wa)-.1 G(ys 0\)).1 E(LOCK_S)144 360 Q
+(shared)169 372 Q(LOCK_SIX)144 384 Q(shared/intent e)169 396 Q(xclusi)-.15 E
+-.15(ve)-.25 G(LOCK_X)144 408 Q -.15(ex)169 420 S(clusi).15 E -.15(ve)-.25 G F1
+(Maxloc)108 436.8 Q(ks)-.2 E F0 .442(is the maximum number of locks to be held\
+ or requested in the table, and is used by)2.942 F F1(loc)2.941 E(k_cr)-.2 E
+(eate)-.37 E F0(to estimate ho)108 448.8 Q 2.5(wm)-.25 G
+(uch space to allocate for v)181.36 448.8 Q(arious lock-table data structures.)
+-.25 E(The function)108 465.6 Q F1(loc)2.5 E(k_cr)-.2 E(eate)-.37 E F0
+(returns -1 on f)2.5 E(ailure, setting)-.1 E F1(errno)2.5 E F0 2.5(,a).18 G
+(nd 0 on success.)356.07 465.6 Q .202(The function)108 482.4 R F1(loc)2.703 E
+(k_open)-.2 E F0 .203(returns a pointer to the lock table identi\214ed by)2.703
+F F1(path)2.703 E F0 2.703(,w).28 G .203(hich must ha)425.678 482.4 R .503 -.15
+(ve a)-.2 H .203(lready been).15 F 1.162(created by a call to)108 494.4 R F1
+(loc)3.661 E(k_cr)-.2 E(eate)-.37 E F0 6.161(.T).18 G 1.161(he process must ha)
+252.869 494.4 R 1.461 -.15(ve p)-.2 H 1.161
+(ermission to read and write \214les with o).15 F(wners,)-.25 E .06
+(groups and permissions as described for)108 506.4 R F1(loc)2.56 E(k_cr)-.2 E
+(eate)-.37 E F0 5.06(.T).18 G(he)331.04 506.4 Q F1(loc)2.56 E(k_open)-.2 E F0
+.06(function returns NULL on f)2.56 F .06(ailure, set-)-.1 F(ting)108 518.4 Q
+F1(errno)2.5 E F0(.).18 E .986(The function)108 535.2 R F1(loc)3.486 E(k_vec)
+-.2 E F0 .986
+(atomically obtains and releases one or more locks from the designated table.)
+3.486 F(The)5.986 E(function)108 547.2 Q F1(loc)4.52 E(k_vec)-.2 E F0 2.02(is \
+intended to support acquisition or trading of multiple locks under one lock ta\
+ble)4.52 F(semaphore, as is needed for lock coupling or in multigranularity lo\
+cking for lock escalation.)108 559.2 Q .746(If an)108 576 R 3.246(yo)-.15 G
+3.246(ft)140.442 576 S .746(he requested locks cannot be acquired or an)149.798
+576 R 3.246(yo)-.15 G 3.246(ft)342.786 576 S .746
+(he locks to be released cannot be released, no)352.142 576 R .117
+(locks are acquired and no locks are released, and)108 588 R F1(loc)2.617 E
+(k_vec)-.2 E F0 .117(returns an error)2.617 F 5.117(.T)-.55 G .117(he function)
+419.211 588 R F1(loc)2.617 E(k_vec)-.2 E F0 .118(returns 0)2.617 F 1.143
+(on success.)108 600 R 1.143(If an error occurs,)6.143 F F1(loc)3.642 E(k_vec)
+-.2 E F0 1.142(returns one of the follo)3.642 F 1.142(wing v)-.25 F 3.642
+(alues. In)-.25 F 1.142(addition, if)3.642 F F1(elistp)3.642 E F0 1.142(is not)
+3.642 F(NULL, it is set to point to the LOCK_REQ_T entry which w)108 612 Q
+(as being processed when the error occurred.)-.1 E(LOCK_GET_DEADLOCK)108 628.8
+Q .431(The speci\214ed)133 640.8 R F1(loc)2.931 E -.1(ke)-.2 G(r).1 E F0 -.1
+(wa)2.931 G 2.931(ss).1 G .431(elected as a victim in order to resolv)239.854
+640.8 R 2.932(ead)-.15 G 2.932(eadlock. In)407.718 640.8 R .432
+(this case, if the)2.932 F F1(con-)2.932 E(\215ict)133 652.8 Q F0(ar)2.901 E
+.401(gument is non-NULL, it is set to reference the identity of a lock)-.18 F
+.4(er holding the lock referenced)-.1 F(by)133 664.8 Q F1(elistp)2.585 E F0
+.085(at the time the request w)2.585 F .085(as denied.)-.1 F .086
+(\(This identity resides in static memory and may be o)5.086 F -.15(ve)-.15 G
+-.2(r-).15 G(written by subsequent calls to)133 676.8 Q F1(loc)2.5 E(k_vec)-.2
+E F0(\).).31 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q
+99.315(ution August)-.2 F(1, 1995)2.5 E(2)535 732 Q EP
+%%Page: 3 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 117.9(DB_LOCK\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 117.9(anual DB_LOCK\(3\))340.17 48 R(LOCK_GET_ERR)108 84 Q(OR)-.4 E
+(An error occurred and the e)133 96 Q(xternal v)-.15 E(ariable)-.25 E/F1 10
+/Times-Italic@0 SF(errno)2.5 E F0(has been set to indicate the error)2.5 E(.)
+-.55 E(LOCK_GET_NO)108 112.8 Q(THELD)-.4 E
+(The lock cannot be released, as it w)133 124.8 Q(as not held by the)-.1 E F1
+(loc)2.5 E -.1(ke)-.2 G(r).1 E F0(.).73 E(LOCK_GET_RESOURCE)108 141.6 Q 2.311(\
+The lock manager is unable to grant the requested locks because of limited int\
+ernal resources.)133 153.6 R(\(Releasing locks may allo)133 165.6 Q 2.5(wf)-.25
+G(uture calls to)249.4 165.6 Q F1(loc)2.5 E(k_vec)-.2 E F0(to succeed.\))2.5 E
+(LOCK_GET_TIMEOUT)108 182.4 Q 3.204(At)133 194.4 S .704(imeout ar)146.204 194.4
+R .704(gument w)-.18 F .705(as speci\214ed, and the requested locks were not a)
+-.1 F -.25(va)-.2 G .705(ilable soon enough.).25 F .705(In this)5.705 F .625
+(case, if the)133 206.4 R F1(con\215ict)3.125 E F0(ar)3.125 E .624
+(gument is non-NULL, it is set to reference the identity of a lock)-.18 F .624
+(er holding the)-.1 F .551(lock referenced by)133 218.4 R F1(elistp)3.052 E F0
+.552(at the time the request w)3.052 F .552(as denied.)-.1 F .552
+(\(This identity resides in static memory)5.552 F(and may be o)133 230.4 Q -.15
+(ve)-.15 G(rwritten by subsequent calls to).15 E F1(loc)2.5 E(k_vec)-.2 E F0
+(\).).31 E(The)108 247.2 Q F1(loc)3.005 E -.1(ke)-.2 G(r).1 E F0(ar)3.005 E
+.504(gument speci\214ed to)-.18 F F1(loc)3.004 E(k_vec)-.2 E F0 .504
+(is a pointer to an untyped byte string which identi\214es the entity)3.004 F
+(requesting or releasing the lock.)108 259.2 Q(If)5 E F1(loc)2.5 E -.1(ke)-.2 G
+(r).1 E F0(is NULL, the calling process' pid is used instead.)2.5 E(The)108 276
+Q F1(timeout)4.628 E F0(ar)4.628 E 2.128(gument pro)-.18 F 2.128(vided to)-.15
+F F1(loc)4.628 E(k_vec)-.2 E F0 2.128(speci\214es a maximum interv)4.628 F
+2.128(al to w)-.25 F 2.128(ait for the locks to be)-.1 F 2.642(granted. If)108
+288 R F1(timeout)2.642 E F0 .142(is NULL, it is ignored, and)2.642 F F1(loc)
+2.642 E(k_vec)-.2 E F0 .141
+(will not return until all of the locks are acquired or)2.642 F
+(an error has occurred.)108 300 Q(The)108 316.8 Q F1(list)4.263 E F0 1.764
+(array pro)4.263 F 1.764(vided to)-.15 F F1(loc)4.264 E(k_vec)-.2 E F0 1.764
+(is typedef)4.264 F 2.764 -.5('d i).55 H 4.264(n<).5 G 1.764
+(db_lock.h> as LOCK_REQ_T)331.114 316.8 R 6.764(.A)-.74 G(LOCK_REQ_T)476.67
+316.8 Q(structure has at least the follo)108 328.8 Q
+(wing \214elds, which must be initialized before calling)-.25 E F1(loc)2.5 E
+(k_vec)-.2 E F0(:).31 E(enum lock)108 345.6 Q(op op;)-.1 E
+(The operation to be performed, which must be set to one of the follo)133 357.6
+Q(wing v)-.25 E(alues:)-.25 E(LOCK_GET)133 374.4 Q .201
+(Get a lock, as de\214ned by the v)158 386.4 R .201(alues of)-.25 F F1(loc)
+2.701 E -.1(ke)-.2 G(r).1 E F0(,).73 E F1(obj)2.701 E F0(and)2.7 E F1(loc)2.7 E
+(k_mode)-.2 E F0 5.2(.U).18 G .2(pon return from)435.99 386.4 R F1(loc)2.7 E
+(k_vec)-.2 E F0(,).31 E .161(if the)158 398.4 R F1(loc)2.661 E(kp)-.2 E F0 .162
+(\214eld is non-NULL, a reference to the acquired lock is stored there.)2.662 F
+.162(\(This reference)5.162 F(is in)158 410.4 Q -.25(va)-.4 G(lidated by an).25
+E 2.5(yc)-.15 G(all to)247.19 410.4 Q F1(loc)2.5 E(k_vec)-.2 E F0(or)2.5 E F1
+(loc)2.5 E(k_put)-.2 E F0(which releases the lock.\))2.5 E(LOCK_PUT)133 427.2 Q
+(The lock referenced by the contents of the)158 439.2 Q F1(loc)2.5 E(kp)-.2 E
+F0(\214eld is released.)2.5 E(LOCK_PUT_ALL)133 456 Q .759
+(All locks held by the)158 468 R F1(loc)3.259 E -.1(ke)-.2 G(r).1 E F0 .759
+(are released.)3.259 F(\(An)5.759 E 3.259(yl)-.15 G .759
+(ocks acquired as a part of the current call to)358.501 468 R F1(loc)158 480 Q
+(k_vec)-.2 E F0(are not considered for this operation\).)2.5 E(LOCK_PUT_OBJ)133
+496.8 Q 1.409(All locks held by the)158 508.8 R F1(loc)3.909 E -.1(ke)-.2 G(r)
+.1 E F0 3.909(,o).73 G 3.909(nt)287.704 508.8 S 1.409(he object)299.393 508.8 R
+F1(obj)3.909 E F0 3.909(,w).48 G 1.41(ith the mode speci\214ed by)367.98 508.8
+R F1(loc)3.91 E(k_mode)-.2 E F0 3.91(,a).18 G(re)532.23 508.8 Q 2.802
+(released. A)158 520.8 R F1(loc)2.802 E(k_mode)-.2 E F0 .301
+(of LOCK_NG indicates that all locks on the object should be released.)2.802 F
+(\(An)158 532.8 Q 3.053(yl)-.15 G .553
+(ocks acquired as a part of the current call to)184.233 532.8 R F1(loc)3.054 E
+(k_vec)-.2 E F0 .554(are not considered for this opera-)3.054 F(tion\).)158
+544.8 Q(const DBT obj;)108 561.6 Q
+(An untyped byte string which speci\214es the object to be lock)133 573.6 Q
+(ed or released.)-.1 E(const lock_mode_t lock_mode;)108 590.4 Q
+(The lock mode, used as an inde)133 602.4 Q 2.5(xi)-.15 G(nto)268.94 602.4 Q F1
+(lt)2.5 E F0 1.1 -.55('s c).68 H(on\215ict array).55 E(.)-.65 E
+(LOCK_T **lockp;)108 619.2 Q 2.5(Ap)133 631.2 S
+(ointer to a pointer to a lock reference.)147.72 631.2 Q(The)108 648 Q F1
+(nlist)2.5 E F0(ar)2.5 E(gument speci\214es the number of elements in the)-.18
+E F1(list)2.5 E F0(array)2.5 E(.)-.65 E 1.229(The function)108 664.8 R F1(loc)
+3.729 E(k_g)-.2 E(et)-.1 E F0 1.228(is a simple interf)3.728 F 1.228
+(ace to the)-.1 F F1(loc)3.728 E(k_vec)-.2 E F0(functionality)3.728 E 3.728(,a)
+-.65 G 1.228(nd is equi)416.31 664.8 R -.25(va)-.25 G 1.228
+(lent to calling the).25 F F1(loc)108 676.8 Q(k_vec)-.2 E F0 .123
+(function with the)2.623 F F1(lt)2.623 E F0(and)2.623 E F1(loc)2.623 E -.1(ke)
+-.2 G(r).1 E F0(ar)2.623 E .123(guments, NULL)-.18 F F1(timeout)2.623 E F0(,)
+.68 E F1(elistp)2.623 E F0(and)2.623 E F1(con\215ict)2.623 E F0(ar)2.623 E .124
+(guments, and a sin-)-.18 F .944(gle element)108 688.8 R F1(list)3.444 E F0
+(array)3.444 E 3.444(,f)-.65 G .944(or which the)203.606 688.8 R F1(op)3.444 E
+F0 .944(\214eld is LOCK_GET)3.444 F 3.444(,a)-.74 G .944(nd the)365.014 688.8 R
+F1(obj)3.444 E F0(,).48 E F1(loc)3.444 E(k_mode)-.2 E F0(and)3.444 E F1(loc)
+3.444 E(kp)-.2 E F0 .943(\214elds are)3.443 F(4.4 Berk)72 732 Q(ele)-.1 E 2.5
+(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(3)535
+732 Q EP
+%%Page: 4 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 117.9(DB_LOCK\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 117.9(anual DB_LOCK\(3\))340.17 48 R .509(represented by the ar)108
+84 R .509(guments of the same name.)-.18 F .51(Note that the type of the)5.509
+F/F1 10/Times-Italic@0 SF(obj)3.01 E F0(ar)3.01 E .51(gument to)-.18 F F1(loc)
+3.01 E(k_g)-.2 E(et)-.1 E F0 .51(is dif-)3.01 F .765(ferent from the)108 96 R
+F1(obj)3.265 E F0 .765(element found in the LOCK_REQ_T structure.)3.265 F(The)
+5.765 E F1(loc)3.265 E(k_g)-.2 E(et)-.1 E F0 .765(function returns success)
+3.265 F(and f)108 108 Q(ailure as described for the)-.1 E F1(loc)2.5 E(k_vec)
+-.2 E F0(function.)2.5 E 1.186(The function)108 124.8 R F1(loc)3.686 E(k_put)
+-.2 E F0 1.187(is a simple interf)3.687 F 1.187(ace to the)-.1 F F1(loc)3.687 E
+(k_vec)-.2 E F0(functionality)3.687 E 3.687(,a)-.65 G 1.187(nd is equi)416.515
+124.8 R -.25(va)-.25 G 1.187(lent to calling the).25 F F1(loc)108 136.8 Q
+(k_vec)-.2 E F0 .374(function with a single element)2.874 F F1(list)2.874 E F0
+(array)2.873 E 2.873(,f)-.65 G .373(or which the)314.82 136.8 R F1(op)2.873 E
+F0 .373(\214eld is LOCK_PUT and the)2.873 F F1(loc)2.873 E(kp)-.2 E F0(\214eld)
+2.873 E .631(is represented by the ar)108 148.8 R .631
+(gument of the same name.)-.18 F .632(Note that the type of the)5.632 F F1(loc)
+3.132 E(kp)-.2 E F0(ar)3.132 E .632(gument to)-.18 F F1(loc)3.132 E(k_put)-.2 E
+F0(is)3.132 E(dif)108 160.8 Q .275(ferent from the)-.25 F F1(loc)2.775 E(kp)-.2
+E F0 .274(element found in the LOCK_REQ_T structure.)2.775 F(The)5.274 E F1
+(loc)2.774 E(k_put)-.2 E F0 .274(function returns suc-)2.774 F(cess and f)108
+172.8 Q(ailure as described for the)-.1 E F1(loc)2.5 E(k_vec)-.2 E F0
+(function.)2.5 E .013(The function)108 189.6 R F1(loc)2.513 E(k_close)-.2 E F0
+.013(disassociates the calling process from the lock table)2.513 F F1(lt)2.513
+E F0 2.513(,a).68 G .013(fter releasing all locks held)431.636 189.6 R .228
+(or requested by that process.)108 201.6 R .228(The function)5.228 F F1(loc)
+2.728 E(k_close)-.2 E F0 .228(returns -1 on f)2.728 F .227(ailure, setting)-.1
+F F1(errno)2.727 E F0 2.727(,a).18 G .227(nd 0 on success.)474.329 201.6 R .433
+(The function)108 218.4 R F1(loc)2.933 E(k_unlink)-.2 E F0(destro)2.933 E .433
+(ys the lock table identi\214ed by the directory)-.1 F F1(path)2.933 E F0 2.933
+(,r).28 G(emo)440.636 218.4 Q .433(ving all \214les used to)-.15 F 1.005
+(implement the lock table.)108 230.4 R 1.005(\(The directory)6.005 F F1(path)
+3.505 E F0 1.005(is not remo)3.505 F -.15(ve)-.15 G 3.505(d.\) If).15 F 1.005
+(there are processes which ha)3.505 F 1.305 -.15(ve c)-.2 H(alled).15 E F1(loc)
+108 242.4 Q(k_open)-.2 E F0 .869(without calling)3.369 F F1(loc)3.369 E
+(k_close)-.2 E F0 .869
+(\(i.e., there are processes currently using the lock table\),)3.369 F F1(loc)
+3.37 E(k_unlink)-.2 E F0 .409(will f)108 254.4 R .408
+(ail without further action, unless the force \215ag is set, in which case)-.1
+F F1(loc)2.908 E(k_unlink)-.2 E F0 .408(will attempt to delete)2.908 F .807
+(the lock table \214les re)108 266.4 R -.05(ga)-.15 G .808(rdless of an).05 F
+3.308(yp)-.15 G .808(rocesses still using the lock table.)264.662 266.4 R(An)
+5.808 E 3.308(ya)-.15 G .808(ccesses to a remo)433.208 266.4 R -.15(ve)-.15 G
+3.308(dl).15 G(ock)525.56 266.4 Q .046(table will lik)108 278.4 R .046
+(ely result in une)-.1 F .045(xpected beha)-.15 F(vior)-.2 E 5.045(.T)-.55 G
+.045(he function)304.24 278.4 R F1(loc)2.545 E(k_unlink)-.2 E F0 .045
+(returns -1 on f)2.545 F .045(ailure, setting)-.1 F F1(errno)2.545 E F0(,).18 E
+(and 0 on success.)108 290.4 Q .798(In the case of catastrophic or system f)108
+307.2 R .798(ailure, it is possible to clean up a lock table by remo)-.1 F .799
+(ving all of the)-.15 F .38(\214les in the directory speci\214ed to the)108
+319.2 R F1(loc)2.88 E(k_cr)-.2 E(eate)-.37 E F0 .379
+(function, as lock table \214les are ne)2.88 F -.15(ve)-.25 G 2.879(rc).15 G
+.379(reated in an)461.543 319.2 R 2.879(yd)-.15 G(irec-)521.68 319.2 Q
+(tory other than the one speci\214ed to)108 331.2 Q F1(loc)2.5 E(k_cr)-.2 E
+(eate)-.37 E F0(.).18 E/F2 9/Times-Bold@0 SF(ERR)72 348 Q(ORS)-.27 E F0(The)108
+360 Q F1(loc)4.158 E(k_cr)-.2 E(eate)-.37 E F0 1.658(function may f)4.158 F
+1.658(ail and set)-.1 F F1(errno)4.158 E F0 1.658(for an)4.158 F 4.158(yo)-.15
+G 4.158(ft)353.71 360 S 1.659(he errors speci\214ed for the library routines)
+363.978 360 R F1(mmap)108 372 Q F0(\(2\),).19 E F1(open)2.5 E F0(\(2\) and).24
+E F1(malloc)2.5 E F0(\(3\).).31 E(The)108 388.8 Q F1(loc)4.692 E(k_open)-.2 E
+F0 2.192(function may f)4.692 F 2.192(ail and set)-.1 F F1(errno)4.692 E F0
+2.192(for an)4.692 F 4.692(yo)-.15 G 4.692(ft)353.87 388.8 S 2.191
+(he errors speci\214ed for the library routine)364.672 388.8 R F1(mmap)108
+400.8 Q F0(\(2\) and).19 E F1(open)2.5 E F0(\(2\).).24 E(The)108 417.6 Q F1
+(loc)2.57 E(k_close)-.2 E F0 .07(function may f)2.57 F .07(ail and set)-.1 F F1
+(errno)2.57 E F0 .07(for an)2.57 F 2.57(yo)-.15 G 2.57(ft)333.76 417.6 S .07
+(he errors speci\214ed for the library routine)342.44 417.6 R F1(close)2.57 E
+F0(\(2\)).18 E(and)108 429.6 Q F1(munmap)2.5 E F0(\(2\).).19 E(The)108 446.4 Q
+F1(loc)4.071 E(k_unlink)-.2 E F0 1.571(function may f)4.071 F 1.571
+(ail and set)-.1 F F1(errno)4.071 E F0 1.571(for an)4.071 F 4.071(yo)-.15 G
+4.07(ft)353.22 446.4 S 1.57(he errors speci\214ed for the library function)
+363.4 446.4 R F1(unlink)108 458.4 Q F0(\(2\) or the follo).67 E(wing:)-.25 E
+([EB)108 475.2 Q(USY])-.1 E(The lock table w)133 487.2 Q
+(as in use and the force \215ag w)-.1 E(as not set.)-.1 E F2(SEE ALSO)72 504 Q
+F1(db_btr)108 516 Q(ee)-.37 E F0(\(3\),).18 E F1(db_hash)2.5 E F0(\(3\),).28 E
+F1(db_lo)2.5 E(g)-.1 E F0(\(3\),).22 E F1(db_mpool)2.5 E F0(\(3\),).51 E F1
+(db_open)2.5 E F0(\(3\),).24 E F1(db_r)2.5 E(ecno)-.37 E F0(\(3\),).18 E F1
+(db_txn)2.5 E F0(\(3\)).24 E F2 -.09(BU)72 532.8 S(GS).09 E F0(The)108 544.8 Q
+F1(maxloc)2.656 E(ks)-.2 E F0 .156
+(parameter is a kluge, and should be deleted in f)2.656 F -.2(avo)-.1 G 2.657
+(ro).2 G 2.657(fd)381.055 544.8 S .157(ynamically e)392.042 544.8 R .157
+(xpanding the lock table.)-.15 F(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G
+(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(4)535 732 Q EP
+%%Page: 1 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.57(DB_LOG\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.57(anual DB_LOG\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72
+84 S(ME).18 E F0(db_log \255 log-manager access method)108 96 Q F1(DESCRIPTION)
+72 112.8 Q F0 .486(The DB library is a f)108 124.8 R .485
+(amily of groups of functions that pro)-.1 F .485
+(vides a modular programming interf)-.15 F .485(ace to trans-)-.1 F .822
+(actions and record-oriented \214le access.)108 136.8 R .822
+(The library includes support for transaction, locking, logging and)5.822 F
+.258(\214le b)108 148.8 R(uf)-.2 E .258(fering functionality)-.25 F 2.758(,a)
+-.65 G 2.758(sw)223.214 148.8 S .258(ell as v)237.082 148.8 R .258(arious inde)
+-.25 F -.15(xe)-.15 G 2.758(da).15 G .258(ccess methods.)331.434 148.8 R(Man)
+5.258 E 2.758(yo)-.15 G 2.758(ft)427.878 148.8 S .258
+(he functional groups \(e.g.)436.746 148.8 R .528(the memory pool functions\) \
+are useful independently of the rest of the DB functions, although some func-)
+108 160.8 R .306(tional groups are e)108 172.8 R .306
+(xplicitly based on other functional groups \(e.g.)-.15 F .306
+(transactions and logging\).)5.306 F -.15(Fo)5.306 G 2.806(rag).15 G(eneral)
+515.57 172.8 Q .245(description of transactions, see)108 184.8 R/F2 10
+/Times-Italic@0 SF(db_txn)2.745 E F0 2.745(\(3\). F).24 F .245
+(or a general description of the access methods, see)-.15 F F2(db_open)2.745 E
+F0(\(3\)).24 E .308(and then the indi)108 196.8 R .308
+(vidual access method manual pages:)-.25 F F2(db_btr)2.807 E(ee)-.37 E F0
+(\(3\),).18 E F2(db_hash)2.807 E F0(\(3\),).28 E F2(db_lo)2.807 E(g)-.1 E F0
+.307(\(3\) and).22 F F2(db_r)2.807 E(ecno)-.37 E F0(\(3\).).18 E -.15(Fo)108
+208.8 S 3.635(rag).15 G 1.135(eneral description of the lock manager)138.45
+208.8 R 3.635(,s)-.4 G(ee)307.32 208.8 Q F2(db_loc)3.635 E(k)-.2 E F0 3.635
+(\(3\). F).67 F 1.135(or a general description of the memory)-.15 F
+(pool manager)108 220.8 Q 2.5(,s)-.4 G(ee)171.2 220.8 Q F2(db_mpool)2.5 E F0
+(\(3\).).51 E
+(This manual page describes speci\214c details of the logging access method.)
+108 237.6 Q .03(These functions pro)108 254.4 R .03
+(vide a general-purpose logging f)-.15 F .03(acility suf)-.1 F .03
+(\214cient for transaction management.)-.25 F .03(Logs can)5.03 F
+(be shared by multiple processes.)108 266.4 Q 3.717(Al)108 283.2 S 1.217
+(og is represented by the directory)121.717 283.2 R(,)-.65 E F2 1.217
+(not the \214le)3.717 F F0 3.717(,n).18 G 1.217(amed by the \214rst ar)323
+283.2 R 1.218(gument to)-.18 F F2(db_open)3.718 E F0 3.718(\(3\). The).24 F
+(\214rst)3.718 E(ar)108 295.2 Q .26
+(gument must be non-NULL, and the directory must already e)-.18 F(xist)-.15 E
+F2(db_open)2.76 E F0 .26(is called.)2.76 F .26(In that directory)5.26 F 2.76
+(,t)-.65 G(he)530.56 295.2 Q 3.448
+(log is stored in one or more \214les named in the format `)108 307.2 R
+(`log.YYYY)-.74 E(.MM.DD.HH.MM.SS')-1.29 E 3.448(', where)-.74 F -.74(``)108
+319.2 S(YYYY).74 E(.MM.DD.HH.SS')-1.29 E 2.507('i)-.74 G 2.507(st)220.497 319.2
+S .007(he approximate creation time of the log \214le, and is guaranteed to be\
+ unique in)229.674 319.2 R(the directory)108 331.2 Q(.)-.65 E .465
+(The group of the created \214les is based on the system and directory def)108
+348 R .466(aults, and is not further speci\214ed by)-.1 F .073
+(the log access method.)108 360 R .072(All \214les are created with the)5.073 F
+F2(mode)2.572 E F0 .072(speci\214ed to)2.572 F F2(db_open)2.572 E F0 2.572(,\()
+.24 G .072(as described in)435.584 360 R F2 -.15(ch)2.572 G(mod).15 E F0
+(\(2\)\)).77 E(and modi\214ed by the process' umask v)108 372 Q(alue \(see)-.25
+E F2(umask)2.5 E F0(\(2\)\).).67 E(The)108 388.8 Q F2<8d61>2.5 E(gs)-.1 E F0
+(ar)2.5 E(gument to)-.18 E F2(db_open)2.5 E F0(must be 0 for the)2.5 E F2
+(db_lo)2.5 E(g)-.1 E F0(access method.)2.5 E F1 -.495(AC)72 405.6 S
+(CESS METHOD SPECIFIC INFORMA).495 E(TION)-.855 E F0 .571
+(The log access method speci\214c data structure pro)108 417.6 R .571(vided to)
+-.15 F F2(db_open)3.071 E F0 .572(is typedef)3.071 F 1.572 -.5('d a).55 H .572
+(nd named LOGINFO.).5 F(A)5.572 E(LOGINFO structure has at least the follo)108
+429.6 Q(wing \214elds, which may be initialized before calling)-.25 E F2
+(db_open)2.5 E F0(:).24 E(of)108 446.4 Q(f_t max_\214le_size;)-.25 E 1.585
+(The maximum size of a single \214le in the log.)133 458.4 R 1.584
+(If not speci\214ed, the maximum size def)6.584 F 1.584(aults to an)-.1 F
+(implementation-speci\214c v)133 470.4 Q(alue.)-.25 E(int lorder;)108 487.2 Q
+.65(The byte order for inte)133 499.2 R .65
+(gers in the stored database metadata.)-.15 F .65
+(The number should represent the order)5.65 F .749(as an inte)133 511.2 R .749
+(ger; for e)-.15 F .749(xample, big endian order w)-.15 F .749
+(ould be the number 4,321.)-.1 F(If)5.749 E F2(lor)3.249 E(der)-.37 E F0 .749
+(is 0 \(no order is)3.249 F(speci\214ed\) the current host order is used.)133
+523.2 Q 1.284(If the log already e)108 540 R 1.284(xists, the v)-.15 F 1.285(a\
+lues speci\214ed for the parameters max_\214le_size and lorder are ignored in)
+-.25 F -.1(fa)108 552 S -.2(vo)-.1 G 2.5(ro).2 G 2.5(ft)136.1 552 S(he v)144.71
+552 Q(alues used when the log w)-.25 E(as created.)-.1 E F1(DB OPERA)72 568.8 Q
+(TIONS)-.855 E F0 .687(The data part of the k)108 580.8 R -.15(ey)-.1 G .686(/\
+data pair used by the log access method is the same as for other access method\
+s.).15 F .837(The k)108 592.8 R 1.137 -.15(ey i)-.1 H 3.337(sd).15 G(if)159.421
+592.8 Q 3.337(ferent. Each)-.25 F .837(log record is identi\214ed by a log seq\
+uence number \(LSN\), which is stored in a)3.337 F(DBT)108 604.8 Q 2.702(,a)
+-.74 G .202(nd which is used as the)136.902 604.8 R F2 -.1(ke)2.702 G(y)-.2 E
+F0 .202(for all log functions that tak)2.702 F(e)-.1 E F2 -.1(ke)2.701 G(y)-.2
+E F0(ar)2.701 E 2.701(guments. Applications)-.18 F .201(cannot create)2.701 F
+(LSN')108 616.8 Q .539(s, and all LSN')-.55 F 3.039(sp)-.55 G(ro)203.216 616.8
+Q .539(vided to functions as ar)-.15 F .539(guments must \214rst be retrie)-.18
+F -.15(ve)-.25 G 3.04(du).15 G .54(sing the)440.37 616.8 R F2(put)3.04 E F0(or)
+3.04 E F2(seq)3.04 E F0(func-)3.04 E 2.783(tions. T)108 628.8 R 2.783(op)-.8 G
+(ro)153.326 628.8 Q .283(vide a distinguished v)-.15 F .282
+(alue for applications, it is guaranteed that no v)-.25 F .282(alid LSN will e)
+-.25 F -.15(ve)-.25 G 2.782(rh).15 G -2.25 -.2(av e)519.248 628.8 T(a)2.982 E
+(size of 0.)108 640.8 Q(Applications can compare LSN')108 657.6 Q 2.5(su)-.55 G
+(sing the)247.98 657.6 Q F2(lo)2.5 E(g_lsn_compar)-.1 E(e)-.37 E F0
+(function \(see belo)2.5 E(w\).)-.25 E .429(Applications can associate LSN')108
+674.4 R 2.929(sw)-.55 G .429(ith speci\214c log \214les.)253.586 674.4 R .429
+(The function)5.429 F F2(lo)2.929 E(g_lsn_\214le)-.1 E F0 .43(\(see belo)2.93 F
+.43(w\), returns the)-.25 F .214
+(name of the log \214le containing the record with a speci\214ed LSN.)108 686.4
+R .214(\(The mapping of LSN to \214le is needed for)5.214 F(4.4 Berk)72 732 Q
+(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(3, 1995)
+2.5 E(1)535 732 Q EP
+%%Page: 2 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.57(DB_LOG\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.57(anual DB_LOG\(3\))340.17 48 R .397(database administration.)
+108 84 R -.15(Fo)5.397 G 2.897(re).15 G .398
+(xample, a transaction manager typically records the earliest LSN needed for)
+231.931 84 R .519(restart, and the database administrator may w)108 96 R .519
+(ant to archi)-.1 F .819 -.15(ve l)-.25 H .519(og \214les to tape when the).15
+F 3.018(yc)-.15 G .518(ontain only LSN')465.624 96 R(s)-.55 E
+(before the earliest one needed for restart.\))108 108 Q
+(Applications can truncate the log \214le up to a speci\214c LSN using the)108
+124.8 Q/F1 10/Times-Italic@0 SF(lo)2.5 E(g_trunc)-.1 E F0(function \(see belo)
+2.5 E(w\).)-.25 E .221(The functions returned by)108 141.6 R F1(db_open)2.721 E
+F0 .221(for the log access method are as described in)2.721 F F1(db_open)2.721
+E F0 2.722(,w).24 G .222(ith the follo)482.586 141.6 R(w-)-.25 E(ing e)108
+153.6 Q(xceptions and additions:)-.15 E 5.28(type The)108 170.4 R
+(type is DB_LOG.)2.5 E 10.28(del The)108 187.2 R F1(del)3.505 E F0 1.005
+(function al)3.505 F -.1(wa)-.1 G 1.005
+(ys returns an error for the log-manager access method, setting).1 F F1(errno)
+3.504 E F0 1.004(to EIN-)3.504 F -1.35(VA)133 199.2 S(L.)1.35 E
+(int \(*log_\215ush\)\(const DB *db, const DBT *lsn\);)108 216 Q(The)133 228 Q
+F1(lo)2.866 E(g_\215ush)-.1 E F0 .367
+(function \215ushes the log up to and including the log record)2.866 F F1(lsn)
+2.867 E F0 5.367(.T).24 G .367(he function)454.926 228 R F1(lo)2.867 E
+(g_\215ush)-.1 E F0(returns -1 on f)133 240 Q(ailure, setting)-.1 E F1(errno)
+2.5 E F0 2.5(,a).18 G(nd 0 on success.)278.61 240 Q
+(int \(*log_lsn_compare\)\(const DB *,)108 256.8 Q .255
+(const DBT *lsn1, const DBT *lsn2\); A pointer to a function which is pro)183
+268.8 R .255(vided to permit)-.15 F .312(applications to compare LSN')133 280.8
+R 2.812(s. The)-.55 F F1(lo)2.812 E(g_lsn_compar)-.1 E(e)-.37 E F0 .312
+(function returns an inte)2.812 F .313(ger less than, equal to,)-.15 F .058
+(or greater than zero if the \214rst LSN is considered to be respecti)133 292.8
+R -.15(ve)-.25 G .058(ly less than, equal to, or greater than).15 F
+(the second LSN.)133 304.8 Q(int \(*log_lsn_\214le\)\(const DB *db,)108 321.6 Q
+(const DBT *lsn, char *name\);)183 333.6 Q(The)133 345.6 Q F1(lo)3.21 E
+(g_lsn_\214le)-.1 E F0 .71
+(function stores a pointer to the name of the \214le containing)3.21 F F1(lsn)
+3.211 E F0 .711(in the address refer)3.211 F(-)-.2 E .293(enced by)133 357.6 R
+F1(name)2.793 E(.)-.15 E F0 .293(This pointer is to an internal static object,\
+ and subsequent calls to the same function)5.293 F
+(will modify the same object.)133 369.6 Q(The function)133 386.4 Q F1(lo)2.5 E
+(g_lsn_\214le)-.1 E F0(returns -1 on f)2.5 E(ailure, setting)-.1 E F1(errno)2.5
+E F0 2.5(,a).18 G(nd 0 on success.)381.56 386.4 Q
+(int \(*log_unlink\)\(const char *path, int force\);)108 403.2 Q(The)133 415.2
+Q F1(lo)3.275 E(g_unlink)-.1 E F0 .775(function destro)3.275 F .775
+(ys the log represented by)-.1 F F1(path)3.275 E F0 5.775(.I).28 G 3.275(ft)
+394.745 415.2 S(he)404.13 415.2 Q F1(for)3.275 E(ce)-.37 E F0 .776
+(parameter is not set to 1)3.275 F .725
+(and there are other processes using the log, then)133 427.2 R F1(lo)3.224 E
+(g_unlink)-.1 E F0 .724(will return -1, setting)3.224 F F1(errno)3.224 E F0
+.724(to EB)3.224 F(USY)-.1 E(.)-1.29 E(If)133 439.2 Q F1(for)2.831 E .331
+(ce is not set or ther)-.37 F 2.831(ea)-.37 G 1.071 -.37(re n)244.287 439.2 T
+2.831(op).37 G -.45(ro)272.909 439.2 S .331(cesses using the lo).45 F .532 -.1
+(g, t)-.1 H .332(hen all \214les).1 F F0 .332(used by the log are destro)2.832
+F(yed.)-.1 E F1(lo)133 451.2 Q(g_unlink)-.1 E F0(will return -1 on f)2.5 E
+(ailure, setting)-.1 E F1(errno)2.5 E F0 2.5(,a).18 G(nd 0 on success.)337.96
+451.2 Q(int \(*log_trunc\)\(const DB *db, const DBT *lsn\);)108 468 Q(The)133
+480 Q F1(lo)2.601 E(g_trunc)-.1 E F0 .101
+(function truncates the log up to an LSN which is less than)2.601 F F1(lsn)2.6
+E F0 5.1(.T).24 G .1(he function)453.24 480 R F1(lo)2.6 E(g_trunc)-.1 E F0
+(returns -1 on f)133 492 Q(ailure, setting)-.1 E F1(errno)2.5 E F0 2.5(,a).18 G
+(nd 0 on success.)278.61 492 Q 9.72(put A)108 508.8 R .339
+(log record containing)2.839 F F1(data)2.839 E F0 .339(is appended to the log.)
+2.839 F(Unlik)5.339 E 2.84(et)-.1 G(he)382.44 508.8 Q F1(put)2.84 E F0 .34
+(functions for other access meth-)2.84 F .789(ods, the k)133 520.8 R 1.089 -.15
+(ey p)-.1 H .788(arameter is not initialized by the application, instead, the \
+LSN assigned to the data is).15 F(returned in the)133 532.8 Q F1 -.1(ke)2.5 G
+(y)-.2 E F0(parameter)2.5 E(.)-.55 E 1.157(The caller is responsible for pro)
+133 549.6 R 1.157(viding an)-.15 F 3.657(yn)-.15 G 1.157(ecessary structure to)
+318.267 549.6 R F1 1.157(data .)3.657 F F0(\(F)6.157 E 1.157(or e)-.15 F 1.157
+(xample, in a write-)-.15 F .267
+(ahead logging protocol, the application must understand what part of)133 561.6
+R F1(data)2.767 E F0 .266(is an operation code, what)2.766 F .622
+(part is redo information, and what part is undo information.)133 573.6 R .622
+(In addition, most transaction managers)5.622 F .985(will store in)133 585.6 R
+F1(data)3.485 E F0 .985(the LSN of the pre)3.485 F .984
+(vious log record for the same transaction, to support chaining)-.25 F
+(back through the transaction')133 597.6 Q 2.5(sl)-.55 G
+(og records during undo.\))258.54 597.6 Q(The parameter)133 614.4 Q F1<8d61>2.5
+E(g)-.1 E F0(must be set to 0 or e)2.5 E(xactly one of the follo)-.15 E(wing v)
+-.25 E(alues:)-.25 E(R_CHECKPOINT)133 631.2 Q .5(Specify the k)158 643.2 R -.15
+(ey)-.1 G .5(/data pair of the current call as the one to be returned when the)
+.15 F F1(seq)3 E F0 .5(function is)3 F(ne)158 655.2 Q
+(xt called with the R_CHECKPOINT \215ag.)-.15 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5
+(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(3, 1995)2.5 E(2)535
+732 Q EP
+%%Page: 3 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.57(DB_LOG\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.57(anual DB_LOG\(3\))340.17 48 R(R_FLUSH)133 84 Q
+(Flush immediately \(ignoring an)158 96 Q 2.5(yp)-.15 G
+(ossibility for group commit\).)296.74 96 Q 9.17(seq The)108 112.8 R/F1 10
+/Times-Italic@0 SF(seq)2.5 E F0(function tak)2.5 E(es the follo)-.1 E
+(wing additional \215ag:)-.25 E(R_CHECKPOINT)133 129.6 Q .184(The last k)158
+141.6 R -.15(ey)-.1 G .184(/data pair stored by the).15 F F1(put)2.684 E F0
+.183(function \(using the R_CHECKPOINT \215ag\) is returned,)2.684 F .216
+(and the cursor is set or initialized to reference it.)158 153.6 R .216(The e)
+5.216 F .216(xpected use of this \215ag is during restart)-.15 F .801
+(and to determine what part of the log must be a)158 165.6 R -.25(va)-.2 G .801
+(ilable for restart.).25 F .801(Therefore, the log record)5.801 F(retrie)158
+177.6 Q -.15(ve)-.25 G 3.352(dw).15 G .853
+(ith R_CHECKPOINT should contain all the information that the transaction man-)
+203.712 177.6 R(ager will need for this purpose.)158 189.6 Q 4.17(sync The)108
+206.4 R F1(sync)3.135 E F0 .635(function al)3.135 F -.1(wa)-.1 G .635
+(ys returns an error for the log-manager access method, setting).1 F F1(errno)
+3.134 E F0 .634(to EIN-)3.134 F -1.35(VA)133 218.4 S(L.)1.35 E/F2 9
+/Times-Bold@0 SF(SEE ALSO)72 235.2 Q F1(db_btr)108 247.2 Q(ee)-.37 E F0(\(3\),)
+.18 E F1(db_hash)2.5 E F0(\(3\),).28 E F1(db_loc)2.5 E(k)-.2 E F0(\(3\),).67 E
+F1(db_mpool)2.5 E F0(\(3\),).51 E F1(db_open)2.5 E F0(\(3\),).24 E F1(db_r)2.5
+E(ecno)-.37 E F0(\(3\),).18 E F1(db_txn)2.5 E F0(\(3\)).24 E(4.4 Berk)72 732 Q
+(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(3, 1995)
+2.5 E(3)535 732 Q EP
+%%Page: 1 13
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 110.12(DB_MPOOL\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 110.12(anual DB_MPOOL\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)
+72 84 S(ME).18 E F0(db_mpool \255 general purpose shared memory b)108 96 Q(uf)
+-.2 E(fer pool)-.25 E F1(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF
+(#include <db)108 124.8 Q(.h>)-.4 E(#include <mpool.h>)108 136.8 Q(int)108
+160.8 Q(mpool_cr)108 172.8 Q
+(eate\(char *path, mode_t mode, size_t cachesize, u_long \215ags\);)-.18 E
+(MPOOL *)108 196.8 Q(mpool_open\(char *path\);)108 208.8 Q(int)108 232.8 Q
+(mpool_close\(MPOOL *mp\);)108 244.8 Q(MPOOLFILE *)108 268.8 Q(mpool_f)108
+280.8 Q(open\(MPOOL *mp, char *path, size_t pagesize, v)-.25 E(oid *pgcookie,)
+-.1 E(int \(*pgin\)\(MPOOLFILE *mpf)158 292.8 Q(,)-.15 E(pgno_t pgno, v)188
+304.8 Q(oid *pgaddr)-.1 E 2.5(,v)-.92 G(oid *pgcookie\),)311.91 304.8 Q
+(int \(*pgout\)\(MPOOLFILE *mpf)158 316.8 Q(,)-.15 E(pgno_t pgno, v)188 328.8 Q
+(oid *pgaddr)-.1 E 2.5(,v)-.92 G(oid *pgcookie\);)311.91 328.8 Q(int)108 352.8
+Q(mpool_fclose\(MPOOLFILE *mpf\);)108 364.8 Q -.1(vo)108 388.8 S(id *).1 E
+(mpool_get\(MPOOLFILE *mpf)108 400.8 Q 2.5(,p)-.15 G(gno_t *pgnoaddr)252.02
+400.8 Q 2.5(,u)-.92 G(_long \215ags,)334.73 400.8 Q
+(int \(*callback\)\(MPOOLFILE *mpf)158 412.8 Q 2.5(,p)-.15 G(gno_t pgno\)\);)
+318.97 412.8 Q(int)108 436.8 Q(mpool_put\(MPOOLFILE *mpf)108 448.8 Q 2.5(,v)
+-.15 G(oid *pgaddr)253.04 448.8 Q 2.5(,u)-.92 G(_long \215ags\);)314.64 448.8 Q
+(int)108 472.8 Q(mpool_sync\(MPOOLFILE *mpf\);)108 484.8 Q(int)108 508.8 Q
+(mpool_unlink\(const char *path, int f)108 520.8 Q(or)-.25 E(ce\);)-.18 E -.1
+(vo)108 544.8 S(id).1 E(mpool_stat\(MPOOL *mp, FILE *fp\);)108 556.8 Q F1
+(DESCRIPTION)72 573.6 Q F0 .485(The DB library is a f)108 585.6 R .485
+(amily of groups of functions that pro)-.1 F .486
+(vides a modular programming interf)-.15 F .486(ace to trans-)-.1 F .823
+(actions and record-oriented \214le access.)108 597.6 R .822
+(The library includes support for transaction, locking, logging and)5.822 F
+.258(\214le b)108 609.6 R(uf)-.2 E .258(fering functionality)-.25 F 2.758(,a)
+-.65 G 2.758(sw)223.214 609.6 S .258(ell as v)237.082 609.6 R .258(arious inde)
+-.25 F -.15(xe)-.15 G 2.758(da).15 G .258(ccess methods.)331.434 609.6 R(Man)
+5.258 E 2.758(yo)-.15 G 2.758(ft)427.878 609.6 S .258
+(he functional groups \(e.g.)436.746 609.6 R .528(the memory pool functions\) \
+are useful independently of the rest of the DB functions, although some func-)
+108 621.6 R .306(tional groups are e)108 633.6 R .306
+(xplicitly based on other functional groups \(e.g.)-.15 F .306
+(transactions and logging\).)5.306 F -.15(Fo)5.306 G 2.806(rag).15 G(eneral)
+515.57 633.6 Q .245(description of transactions, see)108 645.6 R/F3 10
+/Times-Italic@0 SF(db_txn)2.745 E F0 2.745(\(3\). F).24 F .245
+(or a general description of the access methods, see)-.15 F F3(db_open)2.745 E
+F0(\(3\)).24 E .307(and then the indi)108 657.6 R .307
+(vidual access method manual pages:)-.25 F F3(db_btr)2.808 E(ee)-.37 E F0
+(\(3\),).18 E F3(db_hash)2.808 E F0(\(3\),).28 E F3(db_lo)2.808 E(g)-.1 E F0
+.308(\(3\) and).22 F F3(db_r)2.808 E(ecno)-.37 E F0(\(3\).).18 E -.15(Fo)108
+669.6 S 3.635(rag).15 G 1.135(eneral description of the lock manager)138.45
+669.6 R 3.635(,s)-.4 G(ee)307.32 669.6 Q F3(db_loc)3.635 E(k)-.2 E F0 3.635
+(\(3\). F).67 F 1.135(or a general description of the memory)-.15 F
+(pool manager)108 681.6 Q 2.5(,s)-.4 G(ee)171.2 681.6 Q F3(db_mpool)2.5 E F0
+(\(3\).).51 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q
+99.315(ution August)-.2 F(1, 1995)2.5 E(1)535 732 Q EP
+%%Page: 2 14
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 110.12(DB_MPOOL\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 110.12(anual DB_MPOOL\(3\))340.17 48 R
+(This manual page describes speci\214c details of the memory pool interf)108 84
+Q(ace.)-.1 E(The)108 100.8 Q/F1 10/Times-Italic@0 SF(db_mpool)3.682 E F0 1.182
+(function is the library interf)3.682 F 1.183(ace intended to pro)-.1 F 1.183
+(vide general-purpose, page-oriented b)-.15 F(uf)-.2 E(fer)-.25 E .16
+(management of one or more \214les.)108 112.8 R .16(While designed to w)5.16 F
+.16(ork with the other DB functions, these functions are)-.1 F .604
+(also useful for more general purposes.)108 124.8 R .604
+(The memory pools \(MPOOL)5.604 F -.55('s)-.92 G 3.104(\)a).55 G .605
+(re referred to in this document as)404.18 124.8 R .985(simply `)108 136.8 R
+(`pools')-.74 E 3.485('. Pools)-.74 F .985(may be shared between processes.)
+3.485 F .985(Pools are usually \214lled by pages from one or)5.985 F .673
+(more \214les \(MPOOLFILE')108 148.8 R 3.173(s\). P)-.55 F .674
+(ages in the pool are replaced in LR)-.15 F 3.174(U\()-.4 G .674
+(least-recently-used\) order)392.318 148.8 R 3.174(,w)-.4 G .674(ith each)
+507.946 148.8 R(ne)108 160.8 Q 4.243(wp)-.25 G 1.743
+(age replacing the page which has been unused the longest.)133.653 160.8 R -.15
+(Pa)6.742 G 1.742(ges retrie).15 F -.15(ve)-.25 G 4.242(df).15 G 1.742
+(rom the pool using)459.494 160.8 R F1(mpool_g)108 172.8 Q(et)-.1 E F0 1.255
+(are `)3.755 F(`pinned')-.74 E 3.755('i)-.74 G 3.755(nm)215.435 172.8 S(emory)
+231.97 172.8 Q 3.755(,b)-.65 G 3.755(yd)268.125 172.8 S(ef)281.88 172.8 Q 1.256
+(ault, until the)-.1 F 3.756(ya)-.15 G 1.256(re returned to the pool using the)
+358.168 172.8 R F1(mpool_put)3.756 E F0(function.)108 184.8 Q .934
+(The function)108 201.6 R F1(mpool_cr)3.434 E(eate)-.37 E F0 .934
+(creates and initializes the memory pool identi\214ed by the)3.434 F F1(path)
+3.433 E F0(directory)3.433 E 5.933(.T)-.65 G(his)528.33 201.6 Q .931
+(directory must already e)108 213.6 R .931(xist when)-.15 F F1(mpool_cr)3.431 E
+(eate)-.37 E F0 .931(is called.)3.431 F .932
+(If the memory pool identi\214ed by)5.931 F F1(path)3.432 E F0(already)3.432 E
+-.15(ex)108 225.6 S .045(ists, then).15 F F1(mpool_cr)2.545 E(eate)-.37 E F0
+.045(returns success without further action.)2.545 F .045
+(The \214les associated with the memory pool)5.045 F .87
+(are created in the directory speci\214ed by)108 237.6 R F1(path)3.37 E F0 5.87
+(.\().28 G .87(The group of the created \214les is based on the system and)
+304.08 237.6 R .258(directory def)108 249.6 R .258
+(aults, and is not further speci\214ed by)-.1 F F1(mpool_cr)2.758 E(eate)-.37 E
+F0 2.758(.\) All).18 F .258(\214les created by)2.758 F F1(mpool_cr)2.758 E
+(eate)-.37 E F0 .258(are cre-)2.758 F .048(ated with mode)108 261.6 R F1(mode)
+2.548 E F0 .049(\(as described in)2.548 F F1 -.15(ch)2.549 G(mod).15 E F0 .049
+(\(2\)\) and modi\214ed by the process' umask v).77 F .049(alue \(see)-.25 F F1
+(umask)2.549 E F0(\(2\)\).).67 E(The)108 278.4 Q F1(cac)2.544 E(hesize)-.15 E
+F0(ar)2.544 E .044(gument speci\214es the size of the pool in bytes, and shoul\
+d be the size of the normal w)-.18 F(orking)-.1 E .509(set of the application \
+with some small amount of additional memory for unusual situations.)108 290.4 R
+.509(If the number)5.509 F .362(of bytes currently `)108 302.4 R(`pinned')-.74
+E 2.862('i)-.74 G 2.862(nm)226.828 302.4 S .362(emory e)242.47 302.4 R(xceeds)
+-.15 E F1(cac)2.861 E(hesize)-.15 E F0 2.861(,t).18 G(he)351.734 302.4 Q F1
+(db_mpool)2.861 E F0 .361(functions will attempt to allocate)2.861 F
+(more memory and do not necessarily f)108 314.4 Q(ail, although the)-.1 E 2.5
+(ym)-.15 G(ay suf)341.61 314.4 Q(fer performance de)-.25 E(gradation.)-.15 E
+(The)108 331.2 Q F1<8d61>2.5 E(gs)-.1 E F0(ar)2.5 E(gument is set by)-.18 E F1
+(or)2.5 E F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)272.73 331.2 S(he follo)281.34
+331.2 Q(wing v)-.25 E(alues:)-.25 E(MPOOL_PRIV)108 348 Q -1.11(AT)-1.35 G(E)
+1.11 E(The pool is not shared by other processes or threads, so no locking of \
+pool resources is required.)144 360 Q .115(The function)108 376.8 R F1
+(mpool_open)2.615 E F0 .115
+(returns a pointer to the memory pool identi\214ed by)2.615 F F1(path)2.615 E
+F0 2.615(,w).28 G .115(hich must ha)447.525 376.8 R .415 -.15(ve a)-.2 H
+(lready).15 E .036(been created by a call to)108 388.8 R F1(mpool_cr)2.536 E
+(eate)-.37 E F0 5.036(.T).18 G .036(he process must ha)276.074 388.8 R .336
+-.15(ve p)-.2 H .036(ermission to read and write \214les with o).15 F(wn-)-.25
+E 1.157(ers, groups and permissions as described for)108 400.8 R F1(mpool_cr)
+3.657 E(eate)-.37 E F0 6.157(.T).18 G(he)365.075 400.8 Q F1(mpool_open)3.657 E
+F0 1.157(function returns NULL on)3.657 F -.1(fa)108 412.8 S(ilure, setting).1
+E F1(errno)2.5 E F0(.).18 E(The)108 429.6 Q F1(mpool_close)6.383 E F0 3.883
+(function closes the pool indicated by the MPOOL pointer)6.383 F F1(mp)6.383 E
+F0 6.383(,a).19 G 6.382(sr)480.026 429.6 S 3.882(eturned by)493.628 429.6 R F1
+(mpool_open)108 441.6 Q F0 5.047(.T).24 G .047(his function does)171.337 441.6
+R/F2 10/Times-Bold@0 SF(not)2.547 E F0 .047(imply a call to)2.547 F F1
+(mpool_sync)2.547 E F0 .047(\(or to)2.547 F F1(mpool_fclose)2.547 E F0 2.547
+(\)i).18 G .047(.e. no pages are writ-)455.951 441.6 R .404
+(ten to the source \214le as as a result of calling)108 453.6 R F1(mpool_close)
+2.904 E F0 5.404(.T).18 G .404(he function)354.658 453.6 R F1(mpool_close)2.904
+E F0 .403(returns -1 on f)2.904 F(ailure,)-.1 E(setting)108 465.6 Q F1(errno)
+2.5 E F0 2.5(,a).18 G(nd 0 on success.)169.01 465.6 Q .827(The function)108
+482.4 R F1(mpool_fopen)3.327 E F0 .827(opens a \214le for b)3.327 F(uf)-.2 E
+.828(fering in the pool speci\214ed by the MPOOL ar)-.25 F 3.328(gument. The)
+-.18 F F1(path)108 494.4 Q F0(ar)2.85 E .349
+(gument is the name of the \214le to be opened.)-.18 F(The)5.349 E F1(pa)2.849
+E -.1(ge)-.1 G(size).1 E F0(ar)2.849 E .349
+(gument is the size, in bytes, of the unit)-.18 F .738(of transfer between the\
+ application and the pool, although not necessarily the unit of transfer betwe\
+en the)108 506.4 R .12(pool and the source \214le.)108 518.4 R .12
+(Applications not kno)5.12 F .12
+(wing the page size of the source \214le should retrie)-.25 F .42 -.15(ve t)
+-.25 H .12(he meta-).15 F .234(data from the \214le using a page size that is \
+correct for the metadata, then close and reopen the \214le, or)108 530.4 R
+2.735(,o)-.4 G(ther)521.32 530.4 Q(-)-.2 E
+(wise determine the page size before calling)108 542.4 Q F1(mpool_fopen)2.5 E
+F0(.).24 E .416(If the)108 559.2 R F1(pgin)2.916 E F0 .416(function is speci\
+\214ed, it is called each time a page is read into the memory pool from the so\
+urce)2.916 F 2.835(\214le. If)108 571.2 R(the)2.835 E F1(pgout)2.835 E F0 .336
+(function is speci\214ed, it is called each time a page is written to the sour\
+ce \214le.)2.835 F .336(Both func-)5.336 F .834
+(tions are called with the MPOOLFILE pointer returned from)108 583.2 R F1
+(mpool_fopen)3.333 E F0 3.333(,t).24 G .833(he page number)421.815 583.2 R
+3.333(,ap)-.4 G .833(ointer to)505.557 583.2 R .014
+(the page being read or written, and the ar)108 595.2 R(gument)-.18 E F1
+(pgcookie)2.515 E F0 5.015(.I).18 G 2.515(fe)351.695 595.2 S .015
+(ither function f)361.98 595.2 R .015(ails, it should return non-zero)-.1 F
+(and set)108 607.2 Q F1(errno)2.5 E F0 2.5(,i).18 G 2.5(nw)168.73 607.2 S
+(hich case the)183.45 607.2 Q F1(db_mpool)2.5 E F0
+(function calling it will also f)2.5 E(ail, lea)-.1 E(ving)-.2 E F1(errno)2.5 E
+F0(intact.)2.5 E(The)108 624 Q F1(mpool_fclose)2.705 E F0 .204
+(function closes the source \214le indicated by the MPOOLFILE pointer)2.705 F
+F1(mpf)2.704 E F0 5.204(.T)1.96 G .204(his function)492.296 624 R(does)108 636
+Q F2(not)3.615 E F0 1.115(imply a call to)3.615 F F1(mpool_sync)3.615 E F0
+3.615(,i).31 G 1.115
+(.e. no pages are written to the source \214le as as a result of calling)
+268.885 636 R F1(mpool_fclose)108 648 Q F0 5(.T).18 G(he function)175.12 648 Q
+F1(mpool_fclose)2.5 E F0(returns -1 on f)2.5 E(ailure, setting)-.1 E F1(errno)
+2.5 E F0 2.5(,a).18 G(nd 0 on success.)424.33 648 Q .019(The function)108 664.8
+R F1(mpool_g)2.519 E(et)-.1 E F0 .019
+(returns a pointer to the page with the page number speci\214ed by)2.519 F F1
+(pgnoaddr)2.518 E F0 2.518(,f).73 G .018(rom the)509.152 664.8 R .986
+(source \214le speci\214ed by the MPOOLFILE pointer)108 676.8 R F1(mpf)3.486 E
+F0 5.986(.I)1.96 G 3.486(ft)342.268 676.8 S .987(he page does not e)351.864
+676.8 R .987(xist or cannot be retrie)-.15 F -.15(ve)-.25 G(d,).15 E F1
+(mpool_g)108 688.8 Q(et)-.1 E F0(returns NULL and sets errno.)2.5 E(4.4 Berk)72
+732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F
+(1, 1995)2.5 E(2)535 732 Q EP
+%%Page: 3 15
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 110.12(DB_MPOOL\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 110.12(anual DB_MPOOL\(3\))340.17 48 R(The)108 84 Q/F1 10
+/Times-Italic@0 SF<8d61>2.5 E(gs)-.1 E F0(ar)2.5 E(gument is set by)-.18 E F1
+(or)2.5 E F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)272.73 84 S(he follo)281.34 84
+Q(wing v)-.25 E(alues:)-.25 E(MPOOL_CALLB)108 100.8 Q -.4(AC)-.35 G(K).4 E 1.04
+(After the page number has been determined, b)133 112.8 R 1.04(ut before an)-.2
+F 3.54(yo)-.15 G 1.04(ther process or thread can access the)388.26 112.8 R .471
+(page, the function speci\214ed by the)133 124.8 R F1(callbac)2.971 E(k)-.2 E
+F0(ar)2.971 E .471(gument is called.)-.18 F .471(If the function f)5.471 F .472
+(ails, it should return)-.1 F 1.11(non-zero and set)133 136.8 R F1(errno)3.61 E
+F0 3.61(,i).18 G 3.61(nw)236.21 136.8 S 1.11(hich case)252.04 136.8 R F1
+(mpool_g)3.61 E(et)-.1 E F0 1.11(will also f)3.61 F 1.11(ail, lea)-.1 F(ving)
+-.2 E F1(errno)3.61 E F0 3.61(intact. The)3.61 F F1(callbac)3.61 E(k)-.2 E F0
+1.012(function is called with the MPOOLFILE pointer returned from)133 148.8 R
+F1(mpool_fopen)3.512 E F0 1.013(and the page number)3.513 F(.)-.55 E .228
+(This functionality is commonly used when page locking is required, b)133 160.8
+R .227(ut the page number of the page)-.2 F(being retrie)133 172.8 Q -.15(ve)
+-.25 G 2.5(di).15 G 2.5(sn)198.14 172.8 S(ot kno)209.53 172.8 Q(wn.)-.25 E
+(MPOOL_CREA)108 189.6 Q(TE)-1.11 E(If the speci\214ed page does not e)133 201.6
+Q(xist, create it.)-.15 E(MPOOL_LAST)108 218.4 Q 2.105
+(Return the last page of the source \214le and cop)133 230.4 R 4.605(yi)-.1 G
+2.106(ts page number to the location referenced by)347.25 230.4 R F1(pgnoaddr)
+133 242.4 Q F0(.).73 E(MPOOL_NEW)108 259.2 Q(Create a ne)133 271.2 Q 2.5(wp)
+-.25 G(age in the \214le and cop)192.45 271.2 Q 2.5(yi)-.1 G
+(ts page number to the location referenced by)290.67 271.2 Q F1(pgnoaddr)2.5 E
+F0(.).73 E(MPOOL_NOPIN)108 288 Q(Don')133 300 Q 2.918(tp)-.18 G .418
+(in the page into memory)164.068 300 R 5.418(.\()-.65 G .417
+(This \215ag is intended for deb)274.108 300 R .417(ugging purposes, when it')
+-.2 F 2.917(so)-.55 G .417(ften use-)504.873 300 R .972(ful to e)133 312 R .972
+(xamine pages which are currently held by other parts of the application.)-.15
+F -.15(Pa)5.973 G .973(ges retrie).15 F -.15(ve)-.25 G 3.473(di).15 G(n)535 312
+Q .529(this manner don')133 324 R 3.029(tn)-.18 G .528
+(eed to be returned to the memory pool, i.e. the)212.457 324 R 3.028(ys)-.15 G
+(hould)413.95 324 Q/F2 10/Times-Bold@0 SF(not)3.028 E F0 .528
+(be speci\214ed as ar)3.028 F(gu-)-.18 E(ments to the)133 336 Q F1(mpool_put)
+2.5 E F0(routine.\))2.5 E(Created pages ha)108 352.8 Q .3 -.15(ve a)-.2 H
+(ll their bytes set to 0.).15 E 2.078(All pages returned by)108 369.6 R F1
+(mpool_g)4.578 E(et)-.1 E F0 2.079
+(\(unless the MPOOL_NOPIN \215ag is speci\214ed\), will be retained \(i.e.)
+4.578 F -.74(``)108 381.6 S(pinned').74 E
+('\) in the pool until a subsequent call to)-.74 E F1(mpool_put)2.5 E F0(.).68
+E .077(The function)108 398.4 R F1(mpool_put)2.577 E F0 .076
+(indicates that the page referenced by)2.577 F F1(pgaddr)2.576 E F0 .076
+(can be e)2.576 F .076(victed from the pool.)-.25 F F1(Pgaddr)5.076 E F0
+(must be an address pre)108 410.4 Q(viously returned by)-.25 E F1(mpool_g)2.5 E
+(et)-.1 E F0(.).68 E(The \215ag v)108 427.2 Q(alue is speci\214ed by)-.25 E F1
+(or)2.5 E F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)277.2 427.2 S(he follo)285.81
+427.2 Q(wing v)-.25 E(alues:)-.25 E(MPOOL_DIR)108 444 Q(TY)-.6 E .052(The page\
+ has been modi\214ed and must be written to the source \214le before being e)
+133 456 R .052(victed from the pool.)-.25 F(MPOOL_DISCARD)108 472.8 Q .145
+(The page is unlik)133 484.8 R .144(ely to be useful in the near future, and s\
+hould be discarded before other pages in the)-.1 F(pool.)133 496.8 Q
+(The function)108 513.6 Q F1(mpool_put)2.5 E F0(returns -1 on f)2.5 E
+(ailure, setting)-.1 E F1(errno)2.5 E F0 2.5(,a).18 G(nd 0 on success.)352.77
+513.6 Q .027(The function)108 530.4 R F1(mpool_sync)2.527 E F0 .028
+(writes all pages associated with the MPOOLFILE pointer)2.528 F F1(mpf)2.528 E
+F0 2.528(,w)1.96 G .028(hich were speci-)474.414 530.4 R .431(\214ed as ar)108
+542.4 R .431(guments to the)-.18 F F1(mpool_put)2.931 E F0 .431
+(function with an associated \215ag of MPOOL_DIR)2.931 F(TY)-.6 E 2.93(,t)-1.29
+G 2.93(ot)472.61 542.4 S .43(he source \214le.)483.32 542.4 R(The function)108
+554.4 Q F1(mpool_sync)2.5 E F0(returns -1 on f)2.5 E(ailure, setting)-.1 E F1
+(errno)2.5 E F0 2.5(,a).18 G(nd 0 on success.)357.76 554.4 Q 1.075
+(The function)108 571.2 R F1(mpool_unlink)3.575 E F0(destro)3.575 E 1.075
+(ys the memory pool identi\214ed by the directory)-.1 F F1(path)3.575 E F0
+3.575(,r).28 G(emo)471.33 571.2 Q 1.075(ving all \214les)-.15 F 1.121
+(used to implement the memory pool.)108 583.2 R 1.121(\(The directory)6.121 F
+F1(path)3.621 E F0 1.121(is not remo)3.621 F -.15(ve)-.15 G 3.62(d.\) If).15 F
+1.12(there are processes which)3.62 F(ha)108 595.2 Q .871 -.15(ve c)-.2 H
+(alled).15 E F1(mpool_open)3.071 E F0 .571(without calling)3.071 F F1
+(mpool_close)3.071 E F0 .572
+(\(i.e., there are processes currently using the memory)3.071 F(pool\),)108
+607.2 Q F1(mpool_unlink)2.652 E F0 .152(will f)2.652 F .151
+(ail without further action, unless the force \215ag is set, in which case)-.1
+F F1(mpool_unlink)2.651 E F0 .524
+(will attempt to delete the memory pool \214les re)108 619.2 R -.05(ga)-.15 G
+.525(rdless of an).05 F 3.025(yp)-.15 G .525
+(rocesses still using the memory pool.)366.45 619.2 R(An)5.525 E(y)-.15 E .598
+(accesses to a remo)108 631.2 R -.15(ve)-.15 G 3.097(dm).15 G .597
+(emory pool will lik)208.95 631.2 R .597(ely result in une)-.1 F .597
+(xpected beha)-.15 F(vior)-.2 E 5.597(.T)-.55 G .597(he function)436.036 631.2
+R F1(mpool_unlink)3.097 E F0(returns -1 on f)108 643.2 Q(ailure, setting)-.1 E
+F1(errno)2.5 E F0 2.5(,a).18 G(nd 0 on success.)253.61 643.2 Q .11
+(In the case of catastrophic or system f)108 660 R .11
+(ailure, it is possible to clean up a memory pool by remo)-.1 F .11
+(ving all of the)-.15 F .569(\214les in the directory speci\214ed to the)108
+672 R F1(mpool_cr)3.068 E(eate)-.37 E F0 .568
+(function, as memory pool \214les are ne)3.068 F -.15(ve)-.25 G 3.068(rc).15 G
+.568(reated in an)487.364 672 R(y)-.15 E
+(directory other than the one speci\214ed to)108 684 Q F1(mpool_cr)2.5 E(eate)
+-.37 E F0(.).18 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q
+99.315(ution August)-.2 F(1, 1995)2.5 E(3)535 732 Q EP
+%%Page: 4 16
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 110.12(DB_MPOOL\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 110.12(anual DB_MPOOL\(3\))340.17 48 R .025(The function)108 84 R/F1
+10/Times-Italic@0 SF(mpool_stat)2.525 E F0 .026
+(writes statistics for the memory pool)2.526 F F1(mp)2.526 E F0 .026
+(to the \214le speci\214ed by)2.526 F F1(fp)2.526 E F0 5.026(.T).19 G .026
+(hese statistics)485.254 84 R .829
+(include the number of \214les participating in the pool, the acti)108 96 R
+1.129 -.15(ve p)-.25 H .829(ages in the pool, and numbers as to ho).15 F(w)-.25
+E(ef)108 108 Q(fecti)-.25 E .3 -.15(ve t)-.25 H(he cache has been.).15 E/F2 9
+/Times-Bold@0 SF(ERR)72 124.8 Q(ORS)-.27 E F0(The)108 136.8 Q F1(mpool_cr)3.852
+E(eate)-.37 E F0(,).18 E F1(mpool_open)3.852 E F0(and)3.852 E F1(mpool_fopen)
+3.852 E F0 1.353(functions may f)3.852 F 1.353(ail and set)-.1 F F1(errno)3.853
+E F0 1.353(for an)3.853 F 3.853(yo)-.15 G 3.853(ft)493.424 136.8 S 1.353
+(he errors)503.387 136.8 R(speci\214ed for the library functions)108 148.8 Q F1
+(open)2.5 E F0(\(2\),).24 E F1 -.37(re)2.5 G(ad).37 E F0(\(2\), and).77 E F1
+(malloc)2.5 E F0(\(3\).).31 E(The)108 165.6 Q F1(mpool_close)3.144 E F0(and)
+3.144 E F1(mpool_fclose)3.144 E F0 .644(functions may f)3.144 F .644
+(ail and set)-.1 F F1(errno)3.144 E F0 .643(for an)3.143 F 3.143(yo)-.15 G
+3.143(ft)425.985 165.6 S .643(he errors speci\214ed for the)435.238 165.6 R
+(library functions)108 177.6 Q F1(close)2.5 E F0(\(2\) and).18 E F1(fr)2.5 E
+(ee)-.37 E F0(\(3\).).18 E(The)108 194.4 Q F1(mpool_g)4.097 E(et)-.1 E F0 1.597
+(function may f)4.097 F 1.597(ail and set)-.1 F F1(errno)4.097 E F0 1.597
+(for an)4.097 F 4.097(yo)-.15 G 4.097(ft)349.14 194.4 S 1.597
+(he errors speci\214ed for the library functions)359.347 194.4 R F1 -.37(re)108
+206.4 S(ad).37 E F0(\(2\),).77 E F1(write)2.5 E F0(\(2\), and).18 E F1(malloc)
+2.5 E F0(\(3\) or the follo).31 E(wing:)-.25 E([EINV)108 223.2 Q(AL])-1.35 E
+(The requested page does not e)133 235.2 Q(xist and MPOOL_CREA)-.15 E(TE w)
+-1.11 E(as not set.)-.1 E(The)108 252 Q F1(mpool_put)4.288 E F0 1.787
+(function may f)4.287 F 1.787(ail and set)-.1 F F1(errno)4.287 E F0 1.787
+(for an)4.287 F 4.287(yo)-.15 G 4.287(ft)351.701 252 S 1.787
+(he errors speci\214ed for the library function)362.098 252 R F1(write)108 264
+Q F0(\(2\) or the follo).18 E(wing:)-.25 E([EA)108 280.8 Q(CCES])-.4 E
+(The source \214le w)133 292.8 Q(as not opened for writing.)-.1 E(The)108 309.6
+Q F1(mpool_sync)3.993 E F0 1.493(function may f)3.993 F 1.493(ail and set)-.1 F
+F1(errno)3.993 E F0 1.494(for an)3.993 F 3.994(yo)-.15 G 3.994(ft)353.752 309.6
+S 1.494(he errors speci\214ed for the library function)363.856 309.6 R F1
+(write)108 321.6 Q F0(\(2\).).18 E(The)108 338.4 Q F1(mpool_unlink)3.569 E F0
+1.069(function may f)3.569 F 1.068(ail and set)-.1 F F1(errno)3.568 E F0 1.068
+(for an)3.568 F 3.568(yo)-.15 G 3.568(ft)356.734 338.4 S 1.068
+(he errors speci\214ed for the library function)366.412 338.4 R F1(unlink)108
+350.4 Q F0(\(2\) or the follo).67 E(wing:)-.25 E([EB)108 367.2 Q(USY])-.1 E
+(The memory pool w)133 379.2 Q(as in use and the force \215ag w)-.1 E
+(as not set.)-.1 E F2(SEE ALSO)72 396 Q F1(db_btr)108 408 Q(ee)-.37 E F0
+(\(3\),).18 E F1(db_hash)2.5 E F0(\(3\),).28 E F1(db_loc)2.5 E(k)-.2 E F0
+(\(3\),).67 E F1(db_lo)2.5 E(g)-.1 E F0(\(3\),).22 E F1(db_open)2.5 E F0
+(\(3\),).24 E F1(db_r)2.5 E(ecno)-.37 E F0(\(3\),).18 E F1(db_txn)2.5 E F0
+(\(3\)).24 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q
+99.315(ution August)-.2 F(1, 1995)2.5 E(4)535 732 Q EP
+%%Page: 1 17
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 119.01(DB_OPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 119.01(anual DB_OPEN\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)
+72 84 S(ME).18 E F0(db_open \255 database access methods)108 96 Q F1(SYNOPSIS)
+72 112.8 Q/F2 10/Times-Bold@0 SF(#include <db)108 124.8 Q(.h>)-.4 E(DB *)108
+148.8 Q(db_open\(const char *\214le, int \215ags, int mode,)108 160.8 Q
+(DBTYPE type, DBINFO *dbinf)158 172.8 Q(o, const v)-.25 E(oid *openinf)-.1 E
+(o\);)-.25 E F1(DESCRIPTION)72 189.6 Q F0 .485(The DB library is a f)108 201.6
+R .485(amily of groups of functions that pro)-.1 F .486
+(vides a modular programming interf)-.15 F .486(ace to trans-)-.1 F .823
+(actions and record-oriented \214le access.)108 213.6 R .822
+(The library includes support for transaction, locking, logging and)5.822 F
+.258(\214le b)108 225.6 R(uf)-.2 E .258(fering functionality)-.25 F 2.758(,a)
+-.65 G 2.758(sw)223.214 225.6 S .258(ell as v)237.082 225.6 R .258(arious inde)
+-.25 F -.15(xe)-.15 G 2.758(da).15 G .258(ccess methods.)331.434 225.6 R(Man)
+5.258 E 2.758(yo)-.15 G 2.758(ft)427.878 225.6 S .258
+(he functional groups \(e.g.)436.746 225.6 R .528(the memory pool functions\) \
+are useful independently of the rest of the DB functions, although some func-)
+108 237.6 R .306(tional groups are e)108 249.6 R .306
+(xplicitly based on other functional groups \(e.g.)-.15 F .306
+(transactions and logging\).)5.306 F -.15(Fo)5.306 G 2.806(rag).15 G(eneral)
+515.57 249.6 Q .245(description of transactions, see)108 261.6 R/F3 10
+/Times-Italic@0 SF(db_txn)2.745 E F0 2.745(\(3\). F).24 F .245
+(or a general description of the access methods, see)-.15 F F3(db_open)2.745 E
+F0(\(3\)).24 E .307(and then the indi)108 273.6 R .307
+(vidual access method manual pages:)-.25 F F3(db_btr)2.808 E(ee)-.37 E F0
+(\(3\),).18 E F3(db_hash)2.808 E F0(\(3\),).28 E F3(db_lo)2.808 E(g)-.1 E F0
+.308(\(3\) and).22 F F3(db_r)2.808 E(ecno)-.37 E F0(\(3\).).18 E -.15(Fo)108
+285.6 S 3.635(rag).15 G 1.135(eneral description of the lock manager)138.45
+285.6 R 3.635(,s)-.4 G(ee)307.32 285.6 Q F3(db_loc)3.635 E(k)-.2 E F0 3.635
+(\(3\). F).67 F 1.135(or a general description of the memory)-.15 F
+(pool manager)108 297.6 Q 2.5(,s)-.4 G(ee)171.2 297.6 Q F3(db_mpool)2.5 E F0
+(\(3\).).51 E(This manual page describes the o)108 314.4 Q -.15(ve)-.15 G
+(rall structure of the a).15 E -.25(va)-.2 G(ilable access methods.).25 E .457
+(The currently supported \214le formats are btree, hashed, log and recno \(i.e\
+. \215at-\214le oriented\).)108 331.2 R .457(The btree for)5.457 F(-)-.2 E .974
+(mat is a representation of a sorted, balanced tree structure.)108 343.2 R .973
+(The hashed format is an e)5.974 F .973(xtensible, dynamic)-.15 F .801
+(hashing scheme.)108 355.2 R .802
+(The log format is a general-purpose logging f)5.801 F(acility)-.1 E 5.802(.T)
+-.65 G .802(he recno format is a byte stream)406.888 355.2 R .415
+(\214le with \214x)108 367.2 R .415(ed or v)-.15 F .415
+(ariable length records.)-.25 F .415(The formats and other)5.415 F 2.914(,f)-.4
+G .414(ormat speci\214c information are described)376.714 367.2 R
+(in detail in their respecti)108 379.2 Q .3 -.15(ve m)-.25 H(anual pages:).15 E
+F3(db_btr)2.5 E(ee)-.37 E F0(\(3\),).18 E F3(db_hash)2.5 E F0(\(3\),).28 E F3
+(db_lo)2.5 E(g)-.1 E F0(\(3\), and).22 E F3(db_r)2.5 E(ecno)-.37 E F0(\(3\).)
+.18 E .138(Db_open opens)108 396 R F3(\214le)2.638 E F0 .139
+(for reading and/or writing.)2.638 F .139(Files ne)5.139 F -.15(ve)-.25 G 2.639
+(ri).15 G .139(ntended to be preserv)349.088 396 R .139
+(ed on disk may be created)-.15 F .423
+(by setting the \214le parameter to NULL.)108 408 R .423
+(\(Note, while most of the access methods use)5.423 F F3(\214le)2.923 E F0 .423
+(as the name of an)2.923 F .429
+(underlying \214le on disk, this is not guaranteed.)108 420 R .43
+(See the manual pages for the indi)5.429 F .43(vidual access methods for)-.25 F
+(more information.\))108 432 Q(The)108 448.8 Q F3<8d61>4.328 E(gs)-.1 E F0(and)
+4.328 E F3 1.828(mode ar)4.328 F(guments)-.37 E F0 1.828
+(are as speci\214ed to the)4.328 F F3(open)4.328 E F0 1.828(\(2\) function, ho)
+.24 F(we)-.25 E -.15(ve)-.25 G 2.628 -.4(r, o).15 H 1.828(nly the O_CREA).4 F
+-.74(T,)-1.11 G .127(O_EXCL, O_EXLOCK, O_NONBLOCK, O_RDONL)108 460.8 R 2.708
+-1.29(Y, O)-1 H(_RD)1.29 E .128(WR, O_SHLOCK and O_TR)-.3 F .128
+(UNC \215ags are)-.4 F 2.5(meaningful. \(Note,)108 472.8 R
+(opening a database \214le O_WR)2.5 E(ONL)-.4 E 2.5(Yi)-1 G 2.5(sn)342.67 472.8
+S(ot possible.\))354.06 472.8 Q(The)108 489.6 Q F3(type)5.338 E F0(ar)5.338 E
+2.837(gument is of type DBTYPE \(as de\214ned in the <db)-.18 F 2.837
+(.h> include \214le\) and may be set to)-.4 F
+(DB_BTREE, DB_HASH, DB_LOG or DB_RECNO.)108 501.6 Q(The)108 518.4 Q F3(dbinfo)
+3.279 E F0(ar)3.279 E .779(gument is a pointer to a structure containing refer\
+ences to locking, logging, transaction, and)-.18 F 1.242(shared-memory b)108
+530.4 R(uf)-.2 E 1.242(fer pool information.)-.25 F(If)6.242 E F3(dbinfo)3.742
+E F0 1.241(is NULL, then the access method may still use these)3.741 F .667
+(subsystems, b)108 542.4 R .667(ut the usage will be pri)-.2 F -.25(va)-.25 G
+.668(te to the application and managed by DB.).25 F(If)5.668 E F3(dbinfo)3.168
+E F0 .668(is non-NULL,)3.168 F .481(then the module referenced by each of the \
+non-NULL \214elds is used by DB as necessary)108 554.4 R 5.48(.T)-.65 G .48
+(he \214elds of the)479.4 554.4 R(DBINFO structure are de\214ned as follo)108
+566.4 Q(ws:)-.25 E(const char *errpfx;)108 583.2 Q 2.5(Ap)133 595.2 S
+(re\214x to prepend to error messages; used only if)147.72 595.2 Q F3
+(err\214le)2.5 E F0(is non-NULL.)2.5 E(FILE *err\214le;)108 612 Q(The)133 624 Q
+F3(stdio)2.5 E F0(\(3\) \214le stream to which error messages are logged.).18 E
+.147(When an)133 648 R 2.647(ye)-.15 G .147(rror occurs in the)180.904 648 R F3
+(db_open)2.648 E F0 .148(function, or in an)2.648 F 2.648(yf)-.15 G .148
+(unction called using a \214eld of the returned)369.824 648 R .234
+(DB structure, an error v)133 660 R .234
+(alue is returned by the function, and the global v)-.25 F(ariable)-.25 E F3
+(errno)2.733 E F0 .233(is set appropri-)2.733 F(ately)133 672 Q 5.415(.I)-.65 G
+2.915(ns)163.035 672 S .416(ome cases, ho)174.84 672 R(we)-.25 E -.15(ve)-.25 G
+1.216 -.4(r, t).15 H(he).4 E F3(errno)2.916 E F0 -.25(va)2.916 G .416
+(lue may be insuf).25 F .416(\214cient to describe the cause of the error)-.25
+F(.)-.55 E .137(In these cases, if)133 684 R F3(err\214le)2.637 E F0 .137(is n\
+on-NULL, additional error information will be written to the \214le stream it)
+2.637 F(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315
+(ution August)-.2 F(1, 1995)2.5 E(1)535 732 Q EP
+%%Page: 2 18
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 119.01(DB_OPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 119.01(anual DB_OPEN\(3\))340.17 48 R .643
+(represents, preceded by the string, if an)133 84 R 1.943 -.65(y, s)-.15 H .643
+(peci\214ed by).65 F/F1 10/Times-Italic@0 SF(errpfx)3.143 E F0 5.643(.T).53 G
+.644(his error logging f)394.94 84 R .644(acility should not)-.1 F
+(be required for normal operation, b)133 96 Q(ut may be useful in deb)-.2 E
+(ugging applications.)-.2 E(char *errb)108 112.8 Q(uf;)-.2 E .03(The b)133
+124.8 R(uf)-.2 E .03(fer to which error messages are copied.)-.25 F .029
+(If non-NULL,)5.029 F F1(errb)2.529 E(uf)-.2 E F0(beha)2.529 E -.15(ve)-.2 G
+2.529(sa).15 G 2.529(sd)451.423 124.8 S .029(escribed for)462.842 124.8 R F1
+(err\214le)2.529 E F0(,).18 E -.15(ex)133 136.8 S .173(cept that the).15 F F1
+(errpfx)2.673 E F0 .174
+(\214eld is ignored and the error message is copied into the speci\214ed b)
+2.673 F(uf)-.2 E .174(fer instead)-.25 F 1.014
+(of being written to the FILE stream.)133 148.8 R 1.013
+(The DB routines assume that the associated b)6.014 F(uf)-.2 E 1.013
+(fer is at least)-.25 F(1024 bytes in length.)133 160.8 Q(LOCK_T)108 177.6 Q
+(ABLE_T *lockinfo;)-.93 E .265
+(If locking is required for the \214le being opened \(as in the case of b)133
+189.6 R(uf)-.2 E .266(fers being maintained in a shared)-.25 F 1.794(memory b)
+133 201.6 R(uf)-.2 E 1.794(fer pool\), the)-.25 F F1(loc)4.294 E(kinfo)-.2 E F0
+1.794(\214eld contains a return v)4.294 F 1.793(alue from the function)-.25 F
+F1(loc)4.293 E(k_open)-.2 E F0(that)4.293 E(should be used \(see)133 213.6 Q F1
+(db_loc)2.5 E(k)-.2 E F0 2.5(\(3\)\). If).67 F F1(loc)2.5 E(kinfo)-.2 E F0
+(is NULL, no locking is done.)2.5 E(DB *loginfo;)108 230.4 Q .93
+(If modi\214cations to the \214le being opened should be logged, the)133 242.4
+R F1(lo)3.43 E(ginfo)-.1 E F0 .93(\214eld contains a return v)3.43 F(alue)-.25
+E .063(from the function)133 254.4 R F1(dbopen)2.563 E F0 2.563(,w).24 G .062
+(hen opening a DB \214le of type DB_LOG.)247.642 254.4 R(If)5.062 E F1(lo)2.562
+E(ginfo)-.1 E F0 .062(is NULL, no logging)2.562 F(is done.)133 266.4 Q
+(MPOOL *mpoolinfo;)108 283.2 Q 1.129
+(If the cache for the \214le being opened should be maintained in a shared b)
+133 295.2 R(uf)-.2 E 1.129(fer pool, the)-.25 F F1(mpoolinfo)3.629 E F0 .102
+(\214eld contains a return v)133 307.2 R .102(alue from the function)-.25 F F1
+(mpool_open)2.602 E F0 .102(that should be used \(see)2.602 F F1(db_mpool)2.602
+E F0 2.602(\(3\)\). If).51 F F1(mpoolinfo)133 319.2 Q F0 .429
+(is NULL, a memory pool may still be created, b)2.929 F .43(ut it will be pri)
+-.2 F -.25(va)-.25 G .43(te to the application and).25 F(managed by DB.)133
+331.2 Q(TXNMGR *txninfo;)108 348 Q 1.161
+(If the accesses to the \214le being opened should tak)133 360 R 3.661(ep)-.1 G
+1.161(lace in the conte)354.474 360 R 1.161(xt of transactions \(pro)-.15 F
+(viding)-.15 E 1.239(atomicity and complete error reco)133 372 R -.15(ve)-.15 G
+1.239(ry\), the).15 F F1(txninfo)3.739 E F0 1.239(\214eld contains a return v)
+3.739 F 1.24(alue from the function)-.25 F F1(txn_open)133 384 Q F0(\(see)2.599
+E F1(db_txn)2.599 E F0 2.599(\(3\)\). If).24 F .098
+(transactions are speci\214ed, the application is responsible for making suit-)
+2.599 F 1.27(able calls to)133 396 R F1(txn_be)3.77 E(gin)-.4 E F0(,).24 E F1
+(txn_abort)3.77 E F0 3.77(,a).68 G(nd)282.91 396 Q F1(txn_commit)3.77 E F0 6.27
+(.I).68 G(f)356.12 396 Q F1(txninfo)3.77 E F0 1.27
+(is NULL, no transaction support is)3.77 F(done.)133 408 Q(The)108 424.8 Q F1
+(openinfo)2.85 E F0(ar)2.85 E .349(gument is a pointer to an access method spe\
+ci\214c structure described in the access method')-.18 F(s)-.55 E .03
+(manual page.)108 436.8 R(If)5.03 E F1(openinfo)2.53 E F0 .031
+(is NULL, each access method will use def)2.53 F .031
+(aults appropriate for the system and the)-.1 F(access method.)108 448.8 Q/F2 9
+/Times-Bold@0 SF(KEY/D)72 465.6 Q -1.35 -.855(AT A)-.315 H -.666(PA)3.105 G
+(IRS).666 E F0 .313(Access to all access methods is based on k)108 477.6 R -.15
+(ey)-.1 G .312(/data pairs.).15 F .312(Both k)5.312 F -.15(ey)-.1 G 2.812(sa)
+.15 G .312(nd data are represented by the follo)386.758 477.6 R(w-)-.25 E
+(ing data structure:)108 489.6 Q(typedef struct {)108 506.4 Q -.2(vo)144 518.4
+S(id *data;).2 E(size_t size;)144 530.4 Q 2.5(}D)108 542.4 S(BT)122.52 542.4 Q
+(;)-.55 E(The elements of the DBT structure are de\214ned as follo)108 559.2 Q
+(ws:)-.25 E 5.84(data A)108 576 R(pointer to a byte string.)2.5 E 6.95
+(size The)108 592.8 R(length of)2.5 E F1(data)2.5 E F0 2.5(,i).26 G 2.5(nb)
+215.2 592.8 S(ytes.)227.7 592.8 Q -2.15 -.25(Ke y)108 609.6 T .672(and data by\
+te strings may reference strings of essentially unlimited length, although an)
+3.422 F 3.173(yt)-.15 G .873 -.1(wo o)493.204 609.6 T 3.173(ft).1 G(hem)522.78
+609.6 Q(must \214t into a)108 621.6 Q -.25(va)-.2 G
+(ilable memory at the same time.).25 E .14(The access methods pro)108 638.4 R
+.139(vide no guarantees about byte string alignment, and applications are resp\
+onsible for)-.15 F(maintaining an)108 650.4 Q 2.5(yn)-.15 G
+(ecessary alignment.)180.07 650.4 Q F2(DB OPERA)72 667.2 Q(TIONS)-.855 E F1
+(Db_open)108 679.2 Q F0 .56
+(returns a pointer to a DB structure \(as de\214ned in the <db)3.06 F .56
+(.h> include \214le\) on success, and NULL)-.4 F 1.02(on error)108 691.2 R 6.02
+(.T)-.55 G 1.02(he DB structure describes a database type, and includes a set \
+of functions to perform v)155.03 691.2 R(arious)-.25 E(4.4 Berk)72 732 Q(ele)
+-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E
+(2)535 732 Q EP
+%%Page: 3 19
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 119.01(DB_OPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 119.01(anual DB_OPEN\(3\))340.17 48 R .241
+(actions, as described belo)108 84 R 4.041 -.65(w. E)-.25 H .241
+(ach of these functions tak).65 F .241
+(es a pointer to a DB structure, and may tak)-.1 F 2.741(eo)-.1 G .242(ne or)
+519.488 84 R .889(more DBT *')108 96 R 3.389(sa)-.55 G .889(nd a \215ag v)
+174.827 96 R .889(alue as well.)-.25 F(Indi)5.889 E .888
+(vidual access methods specify additional functions and \215ags)-.25 F
+(which are speci\214c to the method.)108 108 Q
+(The \214elds of the DB structure are as follo)5 E(ws:)-.25 E(DBTYPE type;)108
+124.8 Q(The type of the underlying access method \(and \214le format\).)133
+136.8 Q(int \(*close\)\(const DB *db\);)108 153.6 Q 3.863(Ap)133 165.6 S 1.363
+(ointer to a function to \215ush an)149.083 165.6 R 3.864(yc)-.15 G 1.364
+(ached information to disk, free an)290.968 165.6 R 3.864(ya)-.15 G 1.364
+(llocated resources, and)445.912 165.6 R .878(close an)133 177.6 R 3.378(yu)
+-.15 G .878(nderlying \214les.)179.596 177.6 R .878(Since k)5.878 F -.15(ey)-.1
+G .878(/data pairs are cached in memory).15 F 3.377(,f)-.65 G .877
+(ailing to sync the \214le with)431.445 177.6 R(the)133 189.6 Q/F1 10
+/Times-Italic@0 SF(close)2.5 E F0(or)2.5 E F1(sync)2.5 E F0
+(function may result in inconsistent or lost information.)2.5 E(The)133 206.4 Q
+F1(close)2.5 E F0(functions return -1 on f)2.5 E(ailure, setting)-.1 E F1
+(errno)2.5 E F0 2.5(,a).18 G(nd 0 on success.)355.54 206.4 Q
+(int \(*del\)\(const DB *db, TXN *txnid,)108 223.2 Q(const DBT *k)183 235.2 Q
+-.15(ey)-.1 G 2.5(,u)-.5 G(_int \215ags\);)257.65 235.2 Q 2.541(Ap)133 247.2 S
+.041(ointer to a function to remo)147.761 247.2 R .341 -.15(ve k)-.15 H -.15
+(ey).05 G .041(/data pairs from the database.).15 F .042(The k)5.041 F -.15(ey)
+-.1 G .042(/data pair associated with).15 F(the speci\214ed)133 259.2 Q F1 -.1
+(ke)2.5 G(y)-.2 E F0(are discarded from the database.)2.5 E(The)133 276 Q F1
+(txnid)3.317 E F0 .817(parameter contains a transaction ID returned from)3.317
+F F1(txn_be)3.317 E(gin)-.4 E F0 3.317(,i).24 G 3.316(ft)431.22 276 S .816
+(he \214le is being accessed)440.646 276 R
+(under transaction protection, or NULL if transactions are not in ef)133 288 Q
+(fect.)-.25 E(The parameter)133 304.8 Q F1<8d61>2.5 E(g)-.1 E F0
+(must be set to 0 or e)2.5 E(xactly one of the follo)-.15 E(wing v)-.25 E
+(alues:)-.25 E(R_CURSOR)133 321.6 Q(Delete the record referenced by the cursor)
+158 333.6 Q 5(.T)-.55 G(he cursor must ha)339.32 333.6 Q .3 -.15(ve p)-.2 H(re)
+.15 E(viously been initialized.)-.25 E(The)133 350.4 Q F1(delete)2.934 E F0
+.434(functions return -1 on error)2.934 F 2.934(,s)-.4 G(etting)297.818 350.4 Q
+F1(errno)2.934 E F0 2.934(,0o).18 G 2.934(ns)364.3 350.4 S .434
+(uccess, and 1 if the speci\214ed)376.124 350.4 R F1 -.1(ke)2.935 G(y)-.2 E F0
+.435(did not)2.935 F -.15(ex)133 362.4 S(ist in the \214le.).15 E
+(int \(*fd\)\(const DB *db\);)108 379.2 Q 3.351(Ap)133 391.2 S .851
+(ointer to a function which returns a \214le descriptor representati)148.571
+391.2 R 1.15 -.15(ve o)-.25 H 3.35(ft).15 G .85(he underlying database.)430.53
+391.2 R(A)5.85 E .338(\214le descriptor referencing the same \214le will be re\
+turned to all processes which call)133 403.2 R F1(db_open)2.838 E F0 .339
+(with the)2.839 F(same)133 415.2 Q F1(\214le)3.376 E F0 3.376(name. This)3.376
+F .876(\214le descriptor may be safely used as an ar)3.376 F .876
+(gument to the)-.18 F F1(fcntl)3.376 E F0 .875(\(2\) and).51 F F1(\215oc)3.375
+E(k)-.2 E F0(\(2\)).67 E .99(locking functions.)133 427.2 R .99
+(The \214le descriptor is not necessarily associated with an)5.99 F 3.49(yo)
+-.15 G 3.49(ft)453.98 427.2 S .99(he underlying \214les)463.58 427.2 R
+(used by the access method.)133 439.2 Q(No \214le descriptor is a)5 E -.25(va)
+-.2 G(ilable for in memory databases.).25 E(The)133 456 Q F1(fd)2.5 E F0
+(functions return -1 on error)2.5 E 2.5(,s)-.4 G(etting)278.68 456 Q F1(errno)
+2.5 E F0 2.5(,a).18 G(nd the \214le descriptor on success.)335.8 456 Q
+(int \(*get\)\(const DB *db, TXN *txnid,)108 472.8 Q(const DBT *k)183 484.8 Q
+-.15(ey)-.1 G 2.5(,D)-.5 G(BT *data, u_int \215ags\);)259.87 484.8 Q 2.854(Ap)
+133 496.8 S .354(ointer to a function which is the interf)148.074 496.8 R .354
+(ace for k)-.1 F -.15(ey)-.1 G .353(ed retrie).15 F -.25(va)-.25 G 2.853(lf).25
+G .353(rom the database.)397.995 496.8 R .353(The address and)5.353 F
+(length of the data associated with the speci\214ed)133 508.8 Q F1 -.1(ke)2.5 G
+(y)-.2 E F0(are returned in the structure referenced by)2.5 E F1(data)2.5 E F0
+(.).26 E(The)133 525.6 Q F1(txnid)3.316 E F0 .816
+(parameter contains a transaction ID returned from)3.316 F F1(txn_be)3.317 E
+(gin)-.4 E F0 3.317(,i).24 G 3.317(ft)431.215 525.6 S .817
+(he \214le is being accessed)440.642 525.6 R
+(under transaction protection, or NULL if transactions are not in ef)133 537.6
+Q(fect.)-.25 E(The)133 554.4 Q F1 -.1(ge)2.5 G(t).1 E F0
+(functions return -1 on error)2.5 E 2.5(,s)-.4 G(etting)283.02 554.4 Q F1
+(errno)2.5 E F0 2.5(,0o).18 G 2.5(ns)348.2 554.4 S(uccess, and 1 if the)359.59
+554.4 Q F1 -.1(ke)2.5 G(y)-.2 E F0 -.1(wa)2.5 G 2.5(sn).1 G(ot found.)476.83
+554.4 Q(int \(*put\)\(const DB *db, TXN *txnid,)108 571.2 Q(DBT *k)183 583.2 Q
+-.15(ey)-.1 G 2.5(,c)-.5 G(onst DBT *data, u_int \215ags\);)233.48 583.2 Q 2.5
+(Ap)133 595.2 S(ointer to a function to store k)147.72 595.2 Q -.15(ey)-.1 G
+(/data pairs in the database.).15 E(The)133 612 Q F1(txnid)3.317 E F0 .817
+(parameter contains a transaction ID returned from)3.317 F F1(txn_be)3.317 E
+(gin)-.4 E F0 3.317(,i).24 G 3.316(ft)431.22 612 S .816
+(he \214le is being accessed)440.646 612 R
+(under transaction protection, or NULL if transactions are not in ef)133 624 Q
+(fect.)-.25 E(The parameter)133 640.8 Q F1<8d61>2.5 E(g)-.1 E F0
+(must be set to 0 or e)2.5 E(xactly one of the follo)-.15 E(wing v)-.25 E
+(alues:)-.25 E(R_CURSOR)133 657.6 Q .448(Replace the k)158 669.6 R -.15(ey)-.1
+G .448(/data pair referenced by the cursor).15 F 5.449(.T)-.55 G .449
+(he cursor must ha)375.156 669.6 R .749 -.15(ve p)-.2 H(re).15 E .449
+(viously been ini-)-.25 F(tialized.)158 681.6 Q(4.4 Berk)72 732 Q(ele)-.1 E 2.5
+(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(3)535
+732 Q EP
+%%Page: 4 20
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 119.01(DB_OPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 119.01(anual DB_OPEN\(3\))340.17 48 R(R_NOO)133 84 Q(VER)-.5 E
+(WRITE)-.55 E(Enter the ne)158 96 Q 2.5(wk)-.25 G -.15(ey)220.69 96 S
+(/data pair only if the k).15 E .3 -.15(ey d)-.1 H(oes not pre).15 E(viously e)
+-.25 E(xist.)-.15 E .664(The def)133 112.8 R .664(ault beha)-.1 F .664
+(vior of the)-.2 F/F1 10/Times-Italic@0 SF(put)3.164 E F0 .664
+(functions is to enter the ne)3.164 F 3.164(wk)-.25 G -.15(ey)387.498 112.8 S
+.663(/data pair).15 F 3.163(,r)-.4 G .663(eplacing an)443.534 112.8 R 3.163(yp)
+-.15 G(re)503.03 112.8 Q(viously)-.25 E -.15(ex)133 124.8 S(isting k).15 E -.15
+(ey)-.1 G(.)-.5 E(The)133 141.6 Q F1(put)3.558 E F0 1.058
+(functions return -1 on error)3.558 F 3.559(,s)-.4 G(etting)291.089 141.6 Q F1
+(errno)3.559 E F0 3.559(,0o).18 G 3.559(ns)359.446 141.6 S 1.059
+(uccess, and 1 if the R_NOO)371.895 141.6 R(VER)-.5 E(WRITE)-.55 E F1<8d61>133
+153.6 Q(g)-.1 E F0 -.1(wa)2.5 G 2.5(ss).1 G(et and the k)172.24 153.6 Q .3 -.15
+(ey a)-.1 H(lready e).15 E(xists in the \214le.)-.15 E
+(int \(*seq\)\(const DB *db, TXN *txnid,)108 170.4 Q(DBT *k)183 182.4 Q -.15
+(ey)-.1 G 2.5(,D)-.5 G(BT *data, u_int \215ags\);)236.26 182.4 Q 2.877(Ap)133
+194.4 S .377(ointer to a function which is the interf)148.097 194.4 R .377
+(ace for sequential retrie)-.1 F -.25(va)-.25 G 2.877(lf).25 G .377
+(rom the database.)415.194 194.4 R .376(The address)5.376 F .012
+(and length of the k)133 206.4 R .312 -.15(ey a)-.1 H .012
+(re returned in the structure referenced by).15 F F1 -.1(ke)2.512 G(y)-.2 E F0
+2.512(,a).32 G .012(nd the address and length of the)412.726 206.4 R
+(data are returned in the structure referenced by)133 218.4 Q F1(data)2.5 E F0
+(.).26 E(The)133 235.2 Q F1(txnid)3.317 E F0 .817
+(parameter contains a transaction ID returned from)3.317 F F1(txn_be)3.317 E
+(gin)-.4 E F0 3.317(,i).24 G 3.316(ft)431.22 235.2 S .816
+(he \214le is being accessed)440.646 235.2 R
+(under transaction protection, or NULL if transactions are not in ef)133 247.2
+Q(fect.)-.25 E .721(Sequential k)133 264 R -.15(ey)-.1 G .721
+(/data pair retrie).15 F -.25(va)-.25 G 3.221(lm).25 G .721(ay be)277.884 264 R
+.721(gin at an)-.15 F 3.221(yt)-.15 G .721
+(ime, and the logical position of the `)346.568 264 R(`cursor')-.74 E 3.222('i)
+-.74 G(s)536.11 264 Q .947(not af)133 276 R .947(fected by calls to the)-.25 F
+F1(del)3.447 E F0(,).51 E F1 -.1(ge)3.447 G(t).1 E F0(,).68 E F1(put)3.447 E F0
+3.446(,o).68 G(r)308.572 276 Q F1(sync)3.446 E F0 3.446
+(functions. Modi\214cations)3.446 F .946(to the database during a)3.446 F 2.091
+(sequential scan will be re\215ected in the scan, i.e. records inserted behind\
+ the cursor will not be)133 288 R
+(returned while records inserted in front of the cursor will be returned.)133
+300 Q(The parameter)133 316.8 Q F1<8d61>2.5 E(g)-.1 E F0(must be set to 0 or e)
+2.5 E(xactly one of the follo)-.15 E(wing v)-.25 E(alues:)-.25 E(R_CURSOR)133
+333.6 Q .937(The data associated with the speci\214ed k)158 345.6 R 1.237 -.15
+(ey i)-.1 H 3.437(sr).15 G 3.437(eturned. This)348.546 345.6 R(dif)3.437 E .936
+(fers from the)-.25 F F1 -.1(ge)3.436 G(t).1 E F0 .936(functions in)3.436 F
+(that it sets or initializes the cursor to the location of the k)158 357.6 Q .3
+-.15(ey a)-.1 H 2.5(sw).15 G(ell.)415.5 357.6 Q(R_FIRST)133 374.4 Q .835
+(The \214rst k)158 386.4 R -.15(ey)-.1 G .835(/data pair of the database is re\
+turned, and the cursor is set or initialized to refer).15 F(-)-.2 E(ence it.)
+158 398.4 Q(R_NEXT)133 415.2 Q(Retrie)158 427.2 Q 1.015 -.15(ve t)-.25 H .715
+(he k).15 F -.15(ey)-.1 G .715(/data pair immediately after the cursor).15 F
+5.715(.I)-.55 G 3.215(ft)391.91 427.2 S .714
+(he cursor is not yet set, this is the)401.235 427.2 R
+(same as the R_FIRST \215ag.)158 439.2 Q(The)133 456 Q F1(seq)3.014 E F0 .514
+(functions return -1 on error)3.014 F 3.015(,s)-.4 G(etting)287.83 456 Q F1
+(errno)3.015 E F0 3.015(,0o).18 G 3.015(ns)354.555 456 S .515
+(uccess, and 1 if there are no k)366.46 456 R -.15(ey)-.1 G .515(/data pairs)
+.15 F(less than or greater than the speci\214ed or current k)133 468 Q -.15(ey)
+-.1 G(.)-.5 E(int \(*sync\)\(const DB *db, u_int \215ags\);)108 484.8 Q 3.291
+(Ap)133 496.8 S .791(ointer to a function to \215ush an)148.511 496.8 R 3.291
+(yc)-.15 G .791(ached information to disk.)286.388 496.8 R .79
+(If the database is in memory only)5.79 F(,)-.65 E(the)133 508.8 Q F1(sync)2.5
+E F0(function has no ef)2.5 E(fect and will al)-.25 E -.1(wa)-.1 G(ys succeed.)
+.1 E(The parameter)133 525.6 Q F1<8d61>2.5 E(g)-.1 E F0
+(must be set to 0 or a v)2.5 E
+(alue speci\214ed by an access method speci\214c manual page.)-.25 E(The)133
+542.4 Q F1(sync)2.5 E F0(functions return -1 on f)2.5 E(ailure, setting)-.1 E
+F1(errno)2.5 E F0 2.5(,a).18 G(nd 0 on success.)352.76 542.4 Q/F2 9
+/Times-Bold@0 SF(ERR)72 559.2 Q(ORS)-.27 E F0(The)108 571.2 Q F1(db_open)4.548
+E F0 2.048(function may f)4.548 F 2.049(ail and set)-.1 F F1(errno)4.549 E F0
+2.049(for an)4.549 F 4.549(yo)-.15 G 4.549(ft)345.977 571.2 S 2.049
+(he errors speci\214ed for the library functions)356.636 571.2 R F1(open)108
+583.2 Q F0(\(2\),).24 E F1(malloc)2.5 E F0(\(3\) or the follo).31 E(wing:)-.25
+E([EFTYPE])108 600 Q 2.5<418c>133 612 S(le is incorrectly formatted.)148.28 612
+Q([EINV)108 628.8 Q(AL])-1.35 E 2.557(Ap)133 640.8 S .056
+(arameter has been speci\214ed \(hash function, recno pad byte etc.\))147.777
+640.8 R .056(that is incompatible with the cur)5.056 F(-)-.2 E .725
+(rent \214le speci\214cation or)133 652.8 R 3.225(,a\215)-.4 G .725
+(ag to a function which is not meaningful for the function \(for e)248.435
+652.8 R(xample,)-.15 E .763(use of the cursor without prior initialization\) o\
+r there is a mismatch between the v)133 664.8 R .763(ersion number of)-.15 F
+(\214le and the softw)133 676.8 Q(are.)-.1 E(The)108 693.6 Q F1(close)2.913 E
+F0 .413(functions may f)2.913 F .413(ail and set)-.1 F F1(errno)2.913 E F0 .413
+(for an)2.913 F 2.913(yo)-.15 G 2.913(ft)319.62 693.6 S .414
+(he errors speci\214ed for the library functions)328.643 693.6 R F1(close)2.914
+E F0(\(2\),).18 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q
+99.315(ution August)-.2 F(1, 1995)2.5 E(4)535 732 Q EP
+%%Page: 5 21
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 119.01(DB_OPEN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 119.01(anual DB_OPEN\(3\))340.17 48 R/F1 10/Times-Italic@0 SF -.37
+(re)108 84 S(ad).37 E F0(\(2\),).77 E F1(write)2.5 E F0(\(2\),).18 E F1(fr)2.5
+E(ee)-.37 E F0(\(3\), or).18 E F1(fsync)2.5 E F0(\(2\).).31 E(The)108 100.8 Q
+F1(del)2.52 E F0(,).51 E F1 -.1(ge)2.52 G(t).1 E F0(,).68 E F1(put)2.52 E F0
+(and)2.52 E F1(seq)2.52 E F0 .02(functions may f)2.52 F .02(ail and set)-.1 F
+F1(errno)2.52 E F0 .02(for an)2.52 F 2.52(yo)-.15 G 2.52(ft)376.3 100.8 S .02
+(he errors speci\214ed for the library func-)384.93 100.8 R(tions)108 112.8 Q
+F1 -.37(re)2.5 G(ad).37 E F0(\(2\),).77 E F1(write)2.5 E F0(\(2\),).18 E F1(fr)
+2.5 E(ee)-.37 E F0(\(3\) or).18 E F1(malloc)2.5 E F0(\(3\).).31 E(The)108 129.6
+Q F1(fd)2.5 E F0(functions will f)2.5 E(ail and set)-.1 E F1(errno)2.5 E F0
+(to ENOENT for in memory databases.)2.5 E(The)108 146.4 Q F1(sync)2.5 E F0
+(functions may f)2.5 E(ail and set)-.1 E F1(errno)2.5 E F0(for an)2.5 E 2.5(yo)
+-.15 G 2.5(ft)312.71 146.4 S(he errors speci\214ed for the library function)
+321.32 146.4 Q F1(fsync)2.5 E F0(\(2\).).31 E/F2 9/Times-Bold@0 SF(SEE ALSO)72
+163.2 Q F1(db_btr)108 175.2 Q(ee)-.37 E F0(\(3\),).18 E F1(db_hash)2.5 E F0
+(\(3\),).28 E F1(db_loc)2.5 E(k)-.2 E F0(\(3\),).67 E F1(db_lo)2.5 E(g)-.1 E F0
+(\(3\),).22 E F1(db_mpool)2.5 E F0(\(3\),).51 E F1(db_r)2.5 E(ecno)-.37 E F0
+(\(3\),).18 E F1(db_txn)2.5 E F0(\(3\)).24 E F2 -.09(BU)72 192 S(GS).09 E F0
+.106(The name DBT is a mnemonic for `)108 204 R .106(`data base thang')-.74 F
+.106(', and w)-.74 F .107(as used because noone could think of a reason-)-.1 F
+(able name that w)108 216 Q(asn')-.1 E 2.5(ta)-.18 G(lready in use some)202.14
+216 Q(where else.)-.25 E(The)108 232.8 Q F1(fd)2.5 E F0(function interf)2.5 E
+(ace is a kluge, and will be deleted in a future v)-.1 E(ersion of the interf)
+-.15 E(ace.)-.1 E(Only big and little endian byte order is supported.)108 249.6
+Q(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315
+(ution August)-.2 F(1, 1995)2.5 E(5)535 732 Q EP
+%%Page: 1 22
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 111.23(DB_RECNO\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 111.23(anual DB_RECNO\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)
+72 84 S(ME).18 E F0(db_recno \255 record number database access method)108 96 Q
+F1(DESCRIPTION)72 112.8 Q F0(speci\214c details of the recno access method.)108
+124.8 Q F1 -.495(AC)72 141.6 S(CESS METHOD SPECIFIC INFORMA).495 E(TION)-.855 E
+F0 2.497(The recno access method speci\214c data structure pro)108 153.6 R
+2.497(vided to)-.15 F/F2 10/Times-Italic@0 SF(db_open)4.997 E F0 2.497
+(is typedef)4.997 F 3.497 -.5('d a).55 H 2.497(nd named REC-).5 F 2.765
+(NOINFO. A)108 165.6 R .265(RECNOINFO structure has at least the follo)2.765 F
+.266(wing \214elds, which may be initialized before call-)-.25 F(ing)108 177.6
+Q F2(db_open)2.5 E F0(:).24 E(u_int8_t b)108 194.4 Q -.25(va)-.15 G(l;).25 E
+.793(The delimiting byte to be used to mark the end of a record for v)133 206.4
+R .793(ariable-length records, and the pad)-.25 F .386(character for \214x)133
+218.4 R .387(ed-length records.)-.15 F .387(If no v)5.387 F .387
+(alue is speci\214ed, ne)-.25 F .387(wlines \(`)-.25 F(`\\n')-.74 E .387
+('\) are used to mark the end)-.74 F(of v)133 230.4 Q
+(ariable-length records and \214x)-.25 E
+(ed-length records are padded with spaces.)-.15 E(char *bfname;)108 247.2 Q
+1.152(The recno access method stores the in-memory copies of its records in a \
+btree.)133 259.2 R 1.152(If bfname is non-)6.152 F .35(NULL, it speci\214es th\
+e name of the btree \214le, as if speci\214ed as the \214le name for a)133
+271.2 R F2(db_open)2.851 E F0 .351(of a btree)2.851 F(\214le.)133 283.2 Q
+(u_int cachesize;)108 300 Q 3.847(As)133 312 S 1.347
+(uggested maximum size, in bytes, of the memory cache.)147.957 312 R 1.347
+(This v)6.347 F 1.347(alue is)-.25 F/F3 10/Times-Bold@0 SF(only)3.847 E F0
+(advisory)3.847 E 3.846(,a)-.65 G 1.346(nd the)513.934 312 R .693
+(access method will allocate more memory rather than f)133 324 R 3.193(ail. If)
+-.1 F F2(cac)3.193 E(hesize)-.15 E F0 3.193(is 0)3.193 F .693
+(\(no size is speci\214ed\) a)3.193 F(def)133 336 Q(ault size is used.)-.1 E
+(u_long \215ags;)108 352.8 Q(The \215ag v)133 364.8 Q(alue is speci\214ed by)
+-.25 E F2(or)2.5 E F0('ing an).73 E 2.5(yo)-.15 G 2.5(ft)302.2 364.8 S
+(he follo)310.81 364.8 Q(wing v)-.25 E(alues:)-.25 E(R_FIXEDLEN)133 381.6 Q
+1.49(The records are \214x)158 393.6 R 1.489(ed-length, not byte delimited.)
+-.15 F 1.489(The structure element)6.489 F F2 -.37(re)3.989 G(clen).37 E F0
+1.489(speci\214es the)3.989 F .487
+(length of the record, and the structure element)158 405.6 R F2(bval)2.987 E F0
+.488(is used as the pad character)2.988 F 5.488(.A)-.55 G .788 -.15(ny r)
+495.232 405.6 T(ecords,).15 E(inserted into the database, that are less than)
+158 417.6 Q F2 -.37(re)2.5 G(clen).37 E F0
+(bytes long are automatically padded.)2.5 E(R_NOKEY)133 434.4 Q 1.146
+(In the interf)158 446.4 R 1.146(ace speci\214ed by)-.1 F F2(db_open)3.646 E F0
+3.646(,t).24 G 1.146(he sequential record retrie)320.816 446.4 R -.25(va)-.25 G
+3.646<6c8c>.25 G 1.145(lls in both the caller')449.31 446.4 R(s)-.55 E -.1(ke)
+158 458.4 S 4.795(ya)-.05 G 2.295(nd data structures.)181.425 458.4 R 2.295
+(If the R_NOKEY \215ag is speci\214ed, the)7.295 F F2(cur)4.795 E(sor)-.1 E F0
+2.295(functions are not)4.795 F .621(required to \214ll in the k)158 470.4 R
+.921 -.15(ey s)-.1 H 3.121(tructure. This).15 F .621
+(permits applications to retrie)3.121 F .92 -.15(ve r)-.25 H .62
+(ecords at the end of).15 F(\214les without reading all of the interv)158 482.4
+Q(ening records.)-.15 E(R_SN)133 499.2 Q(APSHO)-.35 E(T)-.4 E .029
+(This \215ag requires that a snapshot of the \214le be tak)158 511.2 R .029
+(en when)-.1 F F2(db_open)2.529 E F0 .029(is called, instead of permit-)2.529 F
+(ting an)158 523.2 Q 2.5(yu)-.15 G
+(nmodi\214ed records to be read from the original \214le.)197.85 523.2 Q
+(int lorder;)108 540 Q .65(The byte order for inte)133 552 R .65
+(gers in the stored database metadata.)-.15 F .65
+(The number should represent the order)5.65 F .748(as an inte)133 564 R .749
+(ger; for e)-.15 F .749(xample, big endian order w)-.15 F .749
+(ould be the number 4,321.)-.1 F(If)5.749 E F2(lor)3.249 E(der)-.37 E F0 .749
+(is 0 \(no order is)3.249 F(speci\214ed\) the current host order is used.)133
+576 Q(u_int psize;)108 592.8 Q .284(The recno access method stores the in-memo\
+ry copies of its records in a btree.)133 604.8 R .284(This v)5.284 F .283
+(alue is the size)-.25 F .297
+(\(in bytes\) of the pages used for nodes in that tree.)133 616.8 R(If)5.297 E
+F2(psize)2.797 E F0 .297(is 0 \(no page size is speci\214ed\) a page size)2.797
+F(is chosen based on the underlying \214le system I/O block size.)133 628.8 Q
+(See)5 E F2(btr)2.5 E(ee)-.37 E F0(\(3\) for more information.).18 E
+(size_t reclen;)108 645.6 Q(The length of a \214x)133 657.6 Q
+(ed-length record.)-.15 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)
+132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(1)535 732 Q EP
+%%Page: 2 23
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 111.23(DB_RECNO\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 111.23(anual DB_RECNO\(3\))340.17 48 R/F1 9/Times-Bold@0 SF
+(DB OPERA)72 84 Q(TIONS)-.855 E F0 .972(The data part of the k)108 96 R -.15
+(ey)-.1 G .971(/data pair used by the recno access method is the same as other\
+ access methods.).15 F .198(The k)108 108 R .498 -.15(ey i)-.1 H 2.698(sd).15 G
+(if)157.504 108 Q 2.698(ferent. The)-.25 F/F2 10/Times-Italic@0 SF(data)2.698 E
+F0 .198(\214eld of the k)2.698 F .499 -.15(ey s)-.1 H .199
+(hould be a pointer to a memory location of type).15 F F2 -.37(re)2.699 G
+(cno_t).37 E F0 2.699(,a).68 G(s)536.11 108 Q .506(de\214ned in the <db)108 120
+R .506(.h> include \214le.)-.4 F .506(This type is normally the lar)5.506 F
+.506(gest unsigned inte)-.18 F .506(gral type a)-.15 F -.25(va)-.2 G .505
+(ilable to the).25 F 2.5(implementation. The)108 132 R F2(size)2.5 E F0
+(\214eld of the k)2.5 E .3 -.15(ey s)-.1 H(hould be the size of that type.).15
+E 1.944(The record number data structure is either v)108 148.8 R 1.944
+(ariable or \214x)-.25 F 1.944
+(ed-length records stored in a \215at-\214le format,)-.15 F 1.856
+(accessed by the logical record number)108 160.8 R 6.856(.T)-.55 G 1.856(he e)
+285.206 160.8 R 1.856(xistence of record number \214v)-.15 F 4.356(er)-.15 G
+1.856(equires the e)440.442 160.8 R 1.856(xistence of)-.15 F .875
+(records one through four)108 172.8 R 3.375(,a)-.4 G .875
+(nd the deletion of record number one causes record number \214v)219.68 172.8 R
+3.376(et)-.15 G 3.376(ob)489.928 172.8 S 3.376(er)503.304 172.8 S(enum-)514.45
+172.8 Q .283(bered to record number four)108 184.8 R 2.783(,a)-.4 G 2.783(sw)
+231.195 184.8 S .283(ell as the cursor)245.088 184.8 R 2.783(,i)-.4 G 2.783(fp)
+316.64 184.8 S .282(ositioned after record number one, to shift do)327.753
+184.8 R .282(wn one)-.25 F 3.18(record. The)108 196.8 R .68
+(creation of record number \214v)3.18 F 3.18(ew)-.15 G .681
+(hen records one through four do not e)295.05 196.8 R .681
+(xist causes the logical)-.15 F(creation of them with zero-length data.)108
+208.8 Q .372(Because there is no meta-data associated with the underlying recn\
+o access method \214les, an)108 225.6 R 2.872(yc)-.15 G .372(hanges made)
+487.698 225.6 R .191(to the def)108 237.6 R .191(ault v)-.1 F .191
+(alues \(e.g. \214x)-.25 F .192(ed record length or byte separator v)-.15 F
+.192(alue\) must be e)-.25 F .192(xplicitly speci\214ed each time)-.15 F
+(the \214le is opened.)108 249.6 Q 1.037(The functions returned by)108 266.4 R
+F2(db_open)3.537 E F0 1.036(for the btree access method are as described in)
+3.536 F F2(db_open)3.536 E F0 1.036(\(3\), with the).24 F(follo)108 278.4 Q
+(wing e)-.25 E(xceptions and additions:)-.15 E 5.28(type The)108 295.2 R
+(type is DB_RECNO.)2.5 E 9.72(put Using)108 312 R(the)2.558 E F2(put)2.558 E F0
+(interf)2.559 E .059(ace to create a ne)-.1 F 2.559(wr)-.25 G .059
+(ecord will cause the creation of multiple, empty records if the)293.07 312 R
+(record number is more than one greater than the lar)133 324 Q
+(gest record currently in the database.)-.18 E(The)133 340.8 Q F2(put)2.5 E F0
+(function tak)2.5 E(es the follo)-.1 E(wing additional \215ags:)-.25 E
+(R_IAFTER)133 357.6 Q 1.225
+(Append the data immediately after the data referenced by)158 369.6 R F2 -.1
+(ke)3.724 G(y)-.2 E F0 3.724(,c).32 G 1.224(reating a ne)425.354 369.6 R 3.724
+(wk)-.25 G -.15(ey)490.046 369.6 S 1.224(/data pair).15 F(.)-.55 E
+(The record number of the appended k)158 381.6 Q -.15(ey)-.1 G
+(/data pair is returned in the).15 E F2 -.1(ke)2.5 G(y)-.2 E F0(structure.)2.5
+E(R_IBEFORE)133 398.4 Q 1.343
+(Insert the data immediately before the data referenced by)158 410.4 R F2 -.1
+(ke)3.844 G(y)-.2 E F0 3.844(,c).32 G 1.344(reating a ne)424.874 410.4 R 3.844
+(wk)-.25 G -.15(ey)489.926 410.4 S 1.344(/data pair).15 F(.)-.55 E
+(The record number of the inserted k)158 422.4 Q -.15(ey)-.1 G
+(/data pair is returned in the).15 E F2 -.1(ke)2.5 G(y)-.2 E F0(structure.)2.5
+E(R_SETCURSOR)133 439.2 Q(Store the k)158 451.2 Q -.15(ey)-.1 G(/data pair).15
+E 2.5(,s)-.4 G
+(etting or initializing the position of the cursor to reference it.)256.5 451.2
+Q 9.17(seq The)108 468 R F2(seq)2.5 E F0(function tak)2.5 E(es the follo)-.1 E
+(wing additional \215ags:)-.25 E(R_LAST)133 484.8 Q .04(The last k)158 496.8 R
+-.15(ey)-.1 G .04(/data pair of the database is returned, and the cursor is se\
+t or initialized to reference).15 F(it.)158 508.8 Q(R_PREV)133 525.6 Q(Retrie)
+158 537.6 Q .59 -.15(ve t)-.25 H .29(he k).15 F -.15(ey)-.1 G .29
+(/data pair immediately before the cursor).15 F 5.29(.I)-.55 G 2.79(ft)395.73
+537.6 S .29(he cursor is not yet set, this is the)404.63 537.6 R
+(same as the R_LAST \215ag.)158 549.6 Q .749
+(If the database \214le is a character special \214le and no complete k)133
+566.4 R -.15(ey)-.1 G .748(/data pairs are currently a).15 F -.25(va)-.2 G
+(ilable,).25 E(the)133 578.4 Q F2(seq)2.5 E F0(function returns 2.)2.5 E 4.17
+(sync The)108 595.2 R F2(sync)2.5 E F0(function tak)2.5 E(es the follo)-.1 E
+(wing additional \215ag:)-.25 E(R_RECNOSYNC)133 612 Q .643
+(This \215ag causes the)158 624 R F2(sync)3.143 E F0 .644
+(function to apply to the btree \214le which underlies the recno \214le, not)
+3.143 F .09(the recno \214le itself.)158 636 R .09(\(See the)5.09 F F2(bfname)
+2.59 E F0 .09(\214eld of RECNOINFO structure, abo)2.59 F -.15(ve)-.15 G 2.59
+(,f).15 G .09(or more informa-)470.95 636 R(tion.\))158 648 Q F1(ERR)72 664.8 Q
+(ORS)-.27 E F0(The)108 676.8 Q F2 -.37(re)3.731 G(cno).37 E F0 1.231
+(access method functions may f)3.731 F 1.231(ail and set)-.1 F F2(errno)3.731 E
+F0 1.231(for an)3.731 F 3.731(yo)-.15 G 3.731(ft)392.652 676.8 S 1.231
+(he errors speci\214ed for the library)402.493 676.8 R(function)108 688.8 Q F2
+(db_open)2.5 E F0(\(3\) or the follo).24 E(wing:)-.25 E(4.4 Berk)72 732 Q(ele)
+-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E
+(2)535 732 Q EP
+%%Page: 3 24
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 111.23(DB_RECNO\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 111.23(anual DB_RECNO\(3\))340.17 48 R([EINV)108 84 Q(AL])-1.35 E
+(An attempt w)133 96 Q(as made to add a record to a \214x)-.1 E
+(ed-length database that w)-.15 E(as too lar)-.1 E(ge to \214t.)-.18 E/F1 9
+/Times-Bold@0 SF(SEE ALSO)72 112.8 Q/F2 10/Times-Italic@0 SF(db_btr)108 124.8 Q
+(ee)-.37 E F0(\(3\),).18 E F2(db_hash)2.5 E F0(\(3\),).28 E F2(db_loc)2.5 E(k)
+-.2 E F0(\(3\),).67 E F2(db_lo)2.5 E(g)-.1 E F0(\(3\),).22 E F2(db_mpool)2.5 E
+F0(\(3\),).51 E F2(db_open)2.5 E F0(\(3\),).24 E F2(db_txn)2.5 E F0(\(3\)).24 E
+F2 2.755(Document Pr)108 148.8 R 2.755
+(ocessing in a Relational Database System)-.45 F F0 5.254(,M).32 G 2.754
+(ichael Stonebrak)362.134 148.8 R(er)-.1 E 5.254(,H)-.4 G 2.754(eidi Stettner)
+454.062 148.8 R 5.254(,J)-.4 G(oseph)516.67 148.8 Q
+(Kalash, Antonin Guttman, Nadene L)108 160.8 Q
+(ynn, Memorandum No. UCB/ERL M82/32, May 1982.)-.55 E F1 -.09(BU)72 177.6 S(GS)
+.09 E F0(The)108 189.6 Q F2(sync)3.616 E F0(function')3.616 E 3.616(sR)-.55 G
+1.116(_RECNOSYNC interf)198.838 189.6 R 1.117
+(ace is a kluge, and will be deleted in a future v)-.1 F 1.117(ersion of the)
+-.15 F(interf)108 201.6 Q(ace.)-.1 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G
+(istrib)132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(3)535 732 Q EP
+%%Page: 1 25
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.57(DB_TXN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.57(anual DB_TXN\(3\))340.17 48 R/F1 9/Times-Bold@0 SF -.18(NA)72
+84 S(ME).18 E F0(db_txn \255 transaction management functions)108 96 Q F1
+(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(#include <db)108 124.8 Q(.h>)-.4 E
+(#include <db_lock.h>)108 136.8 Q(int)108 160.8 Q(txn_cr)108 172.8 Q
+(eate\(const char *path, mode_t mode, u_int maxtxns, u_int \215ags\);)-.18 E
+(TXNMGR *)108 196.8 Q(txn_open\(const char *path, DBT *logp, LOCK_T)108 208.8 Q
+(ABLE_T *lockp,)-.9 E(int \(*r)158 220.8 Q(eco)-.18 E -.1(ve)-.1 G
+(r\)\(DBT *lsn, DBT *log_entry).1 E 2.5(,i)-.55 G(nt isundo\)\);)340.11 220.8 Q
+(TXN *)108 244.8 Q(txn_begin\(TXNMGR *txnp\);)108 256.8 Q(int)108 280.8 Q
+(txn_commit\(TXN *tid\);)108 292.8 Q(int)108 316.8 Q(txn_pr)108 328.8 Q(epar)
+-.18 E(e\(TXN *tid\);)-.18 E(int)108 352.8 Q(txn_abort\(TXN *tid\);)108 364.8 Q
+(int)108 388.8 Q(txn_close\(TXNMGR *txnp\);)108 400.8 Q(int)108 424.8 Q
+(txn_unlink\(const char *path, int f)108 436.8 Q(or)-.25 E(ce\);)-.18 E F1
+(DESCRIPTION)72 453.6 Q F0(speci\214c details of the transaction support.)108
+465.6 Q/F3 10/Times-Italic@0 SF(Db_txn)108 482.4 Q F0 .034
+(is the library interf)2.534 F .034(ace that pro)-.1 F .034
+(vides transaction semantics.)-.15 F .034(Full transaction support is pro)5.034
+F .034(vided by a)-.15 F .722(collection of modules that pro)108 494.4 R .723
+(vide well de\214ned interf)-.15 F .723
+(aces to the services required for transaction process-)-.1 F 3.488(ing. These)
+108 506.4 R .988(services are reco)3.488 F -.15(ve)-.15 G .988(ry \(see).15 F
+F3(db_lo)3.488 E(g)-.1 E F0 .988(\(3\)\), concurrenc).22 F 3.488(yc)-.15 G .988
+(ontrol \(see)371.864 506.4 R F3(db_loc)3.487 E(k)-.2 E F0 .987
+(\(3\)\), and the manage-).67 F 2.201(ment of shared data \(see)108 518.4 R F3
+(db_mpool)4.701 E F0 4.701(\(3\)\). T).51 F 2.202
+(ransaction semantics can be applied to the access methods)-.35 F(described in)
+108 530.4 Q F3(db)2.5 E F0(\(3\) through function call parameters.).23 E .629(\
+The model intended for transactional use \(and that is used by the access meth\
+ods\) is that write-ahead log-)108 547.2 R .047(ging is pro)108 559.2 R .047
+(vided by)-.15 F F3(db_lo)2.547 E(g)-.1 E F0 .047
+(\(3\) to record both before- and after).22 F .048(-image logging.)-.2 F .048
+(Locking follo)5.048 F .048(ws a tw)-.25 F(o-phase)-.1 E
+(protocol and is implemented by)108 571.2 Q F3(db_loc)2.5 E(k)-.2 E F0(\(3\).)
+.67 E .549(The function)108 588 R F3(txn_cr)3.049 E(eate)-.37 E F0 .549
+(creates and initializes the transaction re)3.049 F .548
+(gion identi\214ed by the)-.15 F F3(path)3.048 E F0(directory)3.048 E 5.548(.T)
+-.65 G(his)528.33 588 Q .572(directory must already e)108 600 R .572(xist when)
+-.15 F F3(txn_cr)3.072 E(eate)-.37 E F0 .572(is called.)3.072 F .572
+(If the transaction re)5.572 F .572(gion identi\214ed by)-.15 F F3(path)3.072 E
+F0(already)3.072 E -.15(ex)108 612 S 1.78(ists, then).15 F F3(txn_cr)4.28 E
+(eate)-.37 E F0 1.78(returns success without further action.)4.28 F 1.78
+(The \214les associated with the transaction)6.78 F(re)108 624 Q .293
+(gion are created in the directory speci\214ed by)-.15 F F3(path)2.793 E F0
+5.293(.\().28 G .293(The group of the created \214les is based on the system)
+327.657 624 R .781(and directory def)108 636 R .781
+(aults, and is not further speci\214ed by)-.1 F F3(txn_cr)3.281 E(eate)-.37 E
+F0 3.281(.\) All).18 F .78(\214les created by)3.28 F F3(txn_cr)3.28 E(eate)-.37
+E F0 .78(are cre-)3.28 F .048(ated with mode)108 648 R F3(mode)2.548 E F0 .049
+(\(as described in)2.548 F F3 -.15(ch)2.549 G(mod).15 E F0 .049
+(\(2\)\) and modi\214ed by the process' umask v).77 F .049(alue \(see)-.25 F F3
+(umask)2.549 E F0(\(2\)\).).67 E(An)108 660 Q 2.5(yn)-.15 G(ecessary)132.57 660
+Q 2.5(,a)-.65 G(ssociated log and lock re)175.23 660 Q
+(gions are created as well \(see)-.15 E F3(db_lo)2.5 E(g)-.1 E F0(\(3\) and).22
+E F3(db_loc)2.5 E(k)-.2 E F0(\(3\)\).).67 E(The)108 676.8 Q F3(maxtxns)4.191 E
+F0(ar)4.191 E 1.691(gument speci\214es the maximum number of simultaneous tran\
+sactions that are supported.)-.18 F .229
+(This bounds the size of backing \214les and is used to deri)108 688.8 R .529
+-.15(ve l)-.25 H .229(imits for the size of the lock re).15 F .229
+(gion and log\214les.)-.15 F(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)
+132.57 732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(1)535 732 Q EP
+%%Page: 2 26
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.57(DB_TXN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.57(anual DB_TXN\(3\))340.17 48 R(When there are more than)108 84
+Q/F1 10/Times-Italic@0 SF(maxtxns)2.5 E F0(concurrent transactions, calls to)
+2.5 E F1(txn_be)2.5 E(gin)-.4 E F0(may f)2.5 E(ail.)-.1 E(Def)108 100.8 Q .847
+(ault locking and logging protocols are pro)-.1 F .846
+(vided only if the backing \214les e)-.15 F 3.346(xist. If)-.15 F .846
+(the backing \214les do)3.346 F 1.433(not e)108 112.8 R 1.433(xist, the)-.15 F
+F1<8d61>3.933 E(gs)-.1 E F0 1.434
+(parameter must indicate both a logging mode and locking mode speci\214ed by)
+3.933 F F1(or)3.934 E F0('ing).73 E(together at most one \215ag from each of t\
+he TXN_LOCK and TXN_LOG classes as follo)108 124.8 Q(ws:)-.25 E(TXN_LOCK_2PL)
+108 141.6 Q(Use tw)133 153.6 Q(o-phase locking.)-.1 E(TXN_LOCK_OPTIMISTIC)108
+170.4 Q(Use optimistic locking \(not currently implemented\).)133 182.4 Q
+(TXN_LOG_REDO)108 199.2 Q(Pro)133 211.2 Q
+(vide redo-only logging \(not currently implemented\).)-.15 E(TXN_LOG_UNDO)108
+228 Q(Pro)133 240 Q(vide undo-only logging \(not currently implemented\).)-.15
+E(TXN_LOG_UNDOREDO)108 256.8 Q(Pro)133 268.8 Q
+(vide undo/redo write-ahead logging.)-.15 E(The function)108 285.6 Q F1(txn_cr)
+2.5 E(eate)-.37 E F0(returns -1 on f)2.5 E(ailure, setting)-.1 E F1(errno)2.5 E
+F0 2.5(,a).18 G(nd 0 on success.)351.83 285.6 Q 1.892(The function)108 302.4 R
+F1(txn_open)4.392 E F0 1.892(returns a pointer to the transaction re)4.392 F
+1.892(gion identi\214ed by)-.15 F F1(path)4.392 E F0 4.392(,w).28 G 1.892
+(hich must ha)476.016 302.4 R -.15(ve)-.2 G .239
+(already been created by a call to)108 314.4 R F1(txn_cr)2.739 E(eate)-.37 E F0
+5.239(.T).18 G .239(he process must ha)296.88 314.4 R .539 -.15(ve p)-.2 H .239
+(ermission to read and write \214les with).15 F -.25(ow)108 326.4 S .327
+(ners, groups and permissions as described for).25 F F1(txn_cr)2.826 E(eate)
+-.37 E F0 5.326(.T).18 G(he)362.624 326.4 Q F1(txn_open)2.826 E F0 .326
+(function returns NULL on f)2.826 F(ail-)-.1 E(ure, setting)108 338.4 Q F1
+(errno)2.5 E F0(.).18 E(The)108 355.2 Q F1 -.37(re)3.181 G(co).37 E(ver)-.1 E
+F0(ar)3.181 E .681(gument speci\214es a function that is called by)-.18 F F1
+(txn_abort)3.181 E F0 .682(during transaction abort.)3.182 F .682(This func-)
+5.682 F(tion tak)108 367.2 Q(es three ar)-.1 E(guments:)-.18 E 10.83(lsn A)108
+384 R(log sequence number \(LSN\).)2.5 E(log_entry)108 400.8 Q 2.5(Al)133 412.8
+S(og record.)145.5 412.8 Q(isundo)108 429.6 Q(An undo \215ag set to 0 if the o\
+peration is a redo and set to 1 if the operation an undo.)133 441.6 Q 1.498
+(As discussed in the)108 458.4 R F1(db_lo)3.998 E 3.998(g\()-.1 G(3\))228.44
+458.4 Q F0 1.497(manual page, the application is responsible for pro)3.997 F
+1.497(viding an)-.15 F 3.997(yn)-.15 G(ecessary)506.13 458.4 Q .486
+(structure to the log record.)108 470.4 R -.15(Fo)5.486 G 2.986(re).15 G .487
+(xample, the application must understand what part of the log record is an)
+242.256 470.4 R(operation code, what part is redo information, and what part i\
+s undo information.)108 482.4 Q(The)108 499.2 Q F1(txn_be)2.785 E(gin)-.4 E F0
+.285(function creates a ne)2.785 F 2.784(wt)-.25 G .284
+(ransaction in the designated transaction manager)264.018 499.2 R 2.784(,r)-.4
+G .284(eturning a pointer)468.332 499.2 R
+(to a TXN that uniquely identi\214es it.)108 511.2 Q(The)108 528 Q F1
+(txn_commit)2.615 E F0 .115(function ends the transaction speci\214ed by the)
+2.615 F F1(tid)2.615 E F0(ar)2.615 E 2.615(gument. An)-.18 F 2.615(yl)-.15 G
+.115(ocks held by the transac-)440.12 528 R(tion are released.)108 540 Q
+(If logging is enabled, a commit log record is written and \215ushed to disk.)5
+E(The)108 556.8 Q F1(txn_abort)2.889 E F0 .389
+(function causes an abnormal termination of the transaction.)2.889 F .388
+(If logging is enabled, the log is)5.389 F 2.312(played backw)108 568.8 R 2.312
+(ards and an)-.1 F 4.812(yr)-.15 G(eco)228.628 568.8 Q -.15(ve)-.15 G 2.312
+(ry operations are initiated through the).15 F F1 -.37(re)4.813 G(co).37 E(ver)
+-.1 E F0 2.313(function speci\214ed to)4.813 F F1(txn_open)108 580.8 Q F0 5(.A)
+.24 G(fter reco)159.62 580.8 Q -.15(ve)-.15 G
+(ry is completed, all locks held by the transaction are released.).15 E(The)108
+597.6 Q F1(txn_close)3.824 E F0 1.323
+(function detaches a process from the transaction en)3.823 F 1.323
+(vironment speci\214ed by the TXNMGR)-.4 F(pointer)108 609.6 Q 5.261(.A)-.55 G
+.261(ll mapped re)150.761 609.6 R .261(gions are unmapped and an)-.15 F 2.761
+(ya)-.15 G .262(llocated resources are freed.)323.638 609.6 R(An)5.262 E 2.762
+(yu)-.15 G .262(ncommitted trans-)466.688 609.6 R(actions are aborted.)108
+621.6 Q .69(The function)108 638.4 R F1(txn_unlink)3.19 E F0(destro)3.19 E .69
+(ys the transaction re)-.1 F .69(gion identi\214ed by the directory)-.15 F F1
+(path)3.19 E F0 3.19(,r).28 G(emo)472.1 638.4 Q .69(ving all \214les)-.15 F
+1.78(used to implement the transaction re)108 650.4 R 4.28(gion. \(The)-.15 F
+(directory)4.28 E F1(path)4.28 E F0 1.78(is not remo)4.28 F -.15(ve)-.15 G 4.28
+(d.\) If).15 F 1.78(there are processes)4.28 F .553(which ha)108 662.4 R .853
+-.15(ve c)-.2 H(alled).15 E F1(txn_open)3.052 E F0 .552(without calling)3.052 F
+F1(txn_close)3.052 E F0 .552
+(\(i.e., there are processes currently using the transac-)3.052 F .135(tion re)
+108 674.4 R(gion\),)-.15 E F1(txn_unlink)2.635 E F0 .135(will f)2.635 F .135
+(ail without further action, unless the force \215ag is set, in which case)-.1
+F F1(txn_unlink)2.636 E F0 1.67(will attempt to delete the transaction re)108
+686.4 R 1.67(gion \214les re)-.15 F -.05(ga)-.15 G 1.67(rdless of an).05 F 4.17
+(yp)-.15 G 1.67(rocesses still using the transaction)397.22 686.4 R(4.4 Berk)72
+732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315(ution August)-.2 F
+(1, 1995)2.5 E(2)535 732 Q EP
+%%Page: 3 27
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.57(DB_TXN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.57(anual DB_TXN\(3\))340.17 48 R(re)108 84 Q 2.996(gion. An)-.15
+F 2.996(ya)-.15 G .496(ccesses to a remo)165.902 84 R -.15(ve)-.15 G 2.997(dt)
+.15 G .497(ransaction re)257.007 84 R .497(gion will lik)-.15 F .497
+(ely result in une)-.1 F .497(xpected beha)-.15 F(vior)-.2 E 5.497(.T)-.55 G
+.497(he func-)506.463 84 R(tion)108 96 Q/F1 10/Times-Italic@0 SF(txn_unlink)2.5
+E F0(returns -1 on f)2.5 E(ailure, setting)-.1 E F1(errno)2.5 E F0 2.5(,a).18 G
+(nd 0 on success.)316.39 96 Q .51(In the case of catastrophic or system f)108
+112.8 R .51(ailure, it is possible to clean up a transaction re)-.1 F .51
+(gion by remo)-.15 F .51(ving all)-.15 F .34
+(of the \214les in the directory speci\214ed to the)108 124.8 R F1(txn_cr)2.841
+E(eate)-.37 E F0 .341(function, as transaction re)2.841 F .341
+(gion \214les are ne)-.15 F -.15(ve)-.25 G 2.841(rc).15 G(reated)515.57 124.8 Q
+(in an)108 136.8 Q 2.5(yd)-.15 G(irectory other than the one speci\214ed to)
+140.07 136.8 Q F1(txn_cr)2.5 E(eate)-.37 E F0(.).18 E(The)108 153.6 Q F1
+(txn_pr)3.42 E(epar)-.37 E(e)-.37 E F0 .92(function initiates the be)3.42 F
+.919(ginning of a tw)-.15 F 3.419(op)-.1 G .919(hase commit.)352.206 153.6 R
+.919(In a distrib)5.919 F .919(uted transaction, the)-.2 F .185
+(prepare directi)108 165.6 R .485 -.15(ve s)-.25 H .185
+(hould be issued to all participating transaction managers.).15 F .185
+(Each manager must tak)5.185 F 2.685(ew)-.1 G(hat-)524.45 165.6 Q -2.15 -.25
+(ev e)108 177.6 T 2.5(ra).25 G
+(ction is necessary to guarantee that a future call to)131.75 177.6 Q F1
+(txn_commit)2.5 E F0(on the speci\214ed)2.5 E F1(tid)2.5 E F0(will succeed.)2.5
+E/F2 9/Times-Bold@0 SF(SYSTEM INTEGRA)72 194.4 Q(TION)-.855 E F0 .28
+(This model can be applied to data bases other than the pro)108 206.4 R .279
+(vided access methods.)-.15 F -.15(Fo)5.279 G 2.779(re).15 G .279
+(xample, consider an)459.182 206.4 R .15(application that pro)108 218.4 R .15
+(vides transaction semantics to data stored in re)-.15 F .15
+(gular \214les accessed using the)-.15 F F1 -.37(re)2.65 G(ad).37 E F0 .15
+(\(2\) and).77 F F1(write)108 230.4 Q F0 .708(\(2\) system calls.).18 F .707
+(The operations for which transaction protection is desired are brack)5.708 F
+.707(eted by calls to)-.1 F F1(txn_be)108 242.4 Q(gin)-.4 E F0(and)2.5 E F1
+(txn_commit)2.5 E F0(.).68 E .606
+(Before data are referenced, a call is made to the lock manager)108 259.2 R(,)
+-.4 E F1(db_loc)3.106 E(k)-.2 E F0 3.106(,f).67 G .606
+(or a lock of the appropriate type)408.064 259.2 R .719
+(\(e.g. read\) on the object being lock)108 271.2 R 3.218(ed. The)-.1 F .718
+(object might be a page in the \214le, a byte, a range of bytes, or)3.218 F
+.572(some k)108 283.2 R -.15(ey)-.1 G 5.572(.B)-.5 G .573
+(efore a write is performed, the application mak)160.464 283.2 R .573
+(es a call to the log manager)-.1 F(,)-.4 E F1(db_lo)3.073 E(g)-.1 E F0 3.073
+(,t).22 G 3.073(or)506.387 283.2 S(ecord)517.79 283.2 Q .522
+(enough information to redo the operation in case of f)108 295.2 R .522
+(ailure after commit and to undo the operation in case)-.1 F .609(of abort.)108
+307.2 R .609
+(After the log message is written, the write system calls are issued.)5.609 F
+.61(After all requests are issued,)5.61 F .518(the application calls)108 319.2
+R F1(txn_commit)3.017 E F0 5.517(.W).68 G(hen)256.84 319.2 Q F1(txn_commit)
+3.017 E F0 .517(returns, the caller is guaranteed that all necessary log)3.017
+F(writes ha)108 331.2 Q .3 -.15(ve b)-.2 H(een written to disk.).15 E 1.081
+(At an)108 348 R 3.581(yt)-.15 G 1.081(ime, the application may call)142.232
+348 R F1(txn_abort)3.581 E F0 3.581(,w).68 G 1.081
+(hich will result in the appropriate calls to the)318.828 348 R F1 -.37(re)
+3.582 G(co).37 E(ver)-.1 E F0 .278(routine to restore the `)108 360 R
+(`database')-.74 E 2.778('t)-.74 G 2.778(oac)246.48 360 S .278
+(onsistent pre-transaction state.)265.916 360 R .277(\(The reco)5.277 F -.15
+(ve)-.15 G 2.777(rr).15 G .277(outine must be able to)450.562 360 R
+(either reapply or undo the update depending on the conte)108 372 Q
+(xt, for each dif)-.15 E(ferent type of log record.\))-.25 E .746
+(If the application should crash, the reco)108 388.8 R -.15(ve)-.15 G .746
+(ry process uses the).15 F F1(db_lo)3.246 E(g)-.1 E F0(interf)3.246 E .746
+(ace to read the log and call the)-.1 F F1 -.37(re)108 400.8 S(co).37 E(ver)-.1
+E F0(routine to restore the database to a consistent state.)2.5 E(The)108 417.6
+Q F1(txn_pr)3.098 E(epar)-.37 E(e)-.37 E F0 .598(function pro)3.098 F .598
+(vides the core functionality to implement distrib)-.15 F .597
+(uted transactions, b)-.2 F .597(ut it does)-.2 F .36
+(not actually manage the noti\214cation of distrib)108 429.6 R .36
+(uted transaction managers.)-.2 F .36(The caller is responsible for issu-)5.36
+F(ing)108 441.6 Q F1(txn_pr)2.82 E(epar)-.37 E(e)-.37 E F0 .32
+(calls to all sites participating in the transaction.)2.82 F .319
+(If all responses are positi)5.319 F -.15(ve)-.25 G 2.819(,t).15 G .319
+(he caller can)488.832 441.6 R .822(issue a)108 453.6 R F1(txn_commit)3.322 E
+F0 5.822(.I).68 G 3.322(fa)198.076 453.6 S 1.122 -.15(ny o)209.168 453.6 T
+3.322(ft).15 G .822(he responses are ne)236.772 453.6 R -.05(ga)-.15 G(ti).05 E
+-.15(ve)-.25 G 3.322(,t).15 G .823(he caller should issue a)349.15 453.6 R F1
+(txn_abort)3.323 E F0 5.823(.I).68 G 3.323(ng)499.747 453.6 S(eneral,)513.07
+453.6 Q(the)108 465.6 Q F1(txn_pr)2.5 E(epar)-.37 E(e)-.37 E F0
+(call requires that the transaction log be \215ushed to disk.)2.5 E .821
+(The structure of the transaction support allo)108 482.4 R .821
+(ws application designers to trade of)-.25 F 3.32(fp)-.25 G .82
+(erformance and protec-)445.07 482.4 R 3.948(tion. Since)108 494.4 R 1.448
+(DB manages man)3.948 F 3.948(ys)-.15 G 1.448(tructures in shared memory)245.36
+494.4 R 3.948(,i)-.65 G 1.448(ts information is subject to corruption by)
+367.982 494.4 R 1.306(applications when the library is link)108 506.4 R 1.306
+(ed directly with the application.)-.1 F -.15(Fo)6.306 G 3.805(rt).15 G 1.305
+(his reason, DB is designed to)416.815 506.4 R(allo)108 518.4 Q 3.367(wc)-.25 G
+.867(ompilation into a separate serv)137.777 518.4 R .868
+(er process that may be accessed via a sock)-.15 F .868(et interf)-.1 F 3.368
+(ace. In)-.1 F .868(this w)3.368 F(ay)-.1 E(DB')108 530.4 Q 2.828(sd)-.55 G
+.328(ata structures are protected from application code, b)136.388 530.4 R .328
+(ut communication o)-.2 F -.15(ve)-.15 G .327(rhead is increased.).15 F(When)
+5.327 E(applications are trusted, DB may be compiled directly into the applica\
+tion for increased performance.)108 542.4 Q F2(ERR)72 559.2 Q(ORS)-.27 E F0
+(The)108 571.2 Q F1(txn_cr)4.113 E(eate)-.37 E F0 1.613(function may f)4.113 F
+1.613(ail and set)-.1 F F1(errno)4.113 E F0 1.614(for an)4.113 F 4.114(yo)-.15
+G 4.114(ft)349.022 571.2 S 1.614
+(he errors speci\214ed for the library functions)359.246 571.2 R F1(open)108
+583.2 Q F0(\(2\),).24 E F1(write)2.5 E F0(\(2\),).18 E F1(malloc)2.5 E F0
+(\(3\),).31 E F1(loc)2.5 E(k_cr)-.2 E(eate)-.37 E F0(\(3\), and).18 E F1(lo)2.5
+E(g_cr)-.1 E(eate)-.37 E F0(\(3\).).18 E(The)108 600 Q F1(txn_open)2.509 E F0
+.009(function may f)2.509 F .009(ail and set)-.1 F F1(errno)2.508 E F0 .008
+(to an)2.508 F 2.508(yo)-.15 G 2.508(ft)323.916 600 S .008
+(he errors speci\214ed for the library functions)332.534 600 R F1(open)2.508 E
+F0(\(2\),).24 E F1(write)108 612 Q F0(\(2\),).18 E F1(malloc)2.5 E F0(\(3\),)
+.31 E F1(loc)2.5 E(k_open)-.2 E F0(\(3\), and).24 E F1(lo)2.5 E(g_open)-.1 E F0
+(\(3\).).24 E(The)108 628.8 Q F1(txn_be)2.671 E(gin)-.4 E F0 .171
+(function may f)2.671 F .171(ail and set)-.1 F F1(errno)2.671 E F0 .171
+(to ENOSPC indicating that the maximum number of concur)2.671 F(-)-.2 E
+(rent transactions has been reached.)108 640.8 Q(The)108 657.6 Q F1(txn_commit)
+2.5 E F0(function may f)2.5 E(ail and set)-.1 E F1(errno)2.5 E F0(to EINV)2.5 E
+(AL indicating that the transaction w)-1.35 E(as aborted.)-.1 E(The)108 674.4 Q
+F1(txn_close)4.582 E F0 2.082(function may f)4.582 F 2.081(ail and set)-.1 F F1
+(errno)4.581 E F0 2.081(to an)4.581 F 4.581(yo)-.15 G 4.581(ft)345.753 674.4 S
+2.081(he errors speci\214ed for the library functions)356.444 674.4 R F1(close)
+108 686.4 Q F0(\(2\),).18 E F1 -.37(re)2.5 G(ad).37 E F0(\(2\),).77 E F1(write)
+2.5 E F0(\(2\),).18 E F1(fr)2.5 E(ee)-.37 E F0(\(3\),).18 E F1(fsync)2.5 E F0
+(\(2\),).31 E F1(loc)2.5 E(k_close)-.2 E F0(\(3\) or).18 E F1(lo)2.5 E(g_close)
+-.1 E F0(\(3\).).18 E(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57
+732 Q 99.315(ution August)-.2 F(1, 1995)2.5 E(3)535 732 Q EP
+%%Page: 4 28
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 124.57(DB_TXN\(3\) BSD)72 48 R(Programmer')2.5 E 2.5
+(sM)-.55 G 124.57(anual DB_TXN\(3\))340.17 48 R(The)108 84 Q/F1 10
+/Times-Italic@0 SF(txn_unlink)4.319 E F0 1.819(function may f)4.319 F 1.819
+(ail and set)-.1 F F1(errno)4.319 E F0 1.819(to an)4.319 F 4.319(yo)-.15 G 4.32
+(ft)347.58 84 S 1.82(he errors speci\214ed for the library functions)358.01 84
+R F1(unlink)108 96 Q F0(\(2\),).67 E F1(loc)2.5 E(k_unlink)-.2 E F0(\(3\), and)
+.67 E F1(lo)2.5 E(g_unlink)-.1 E F0(\(3\), or the follo).67 E(wing:)-.25 E([EB)
+108 112.8 Q(USY])-.1 E(The transaction re)133 124.8 Q(gion w)-.15 E
+(as in use and the force \215ag w)-.1 E(as not set.)-.1 E/F2 9/Times-Bold@0 SF
+(SEE ALSO)72 141.6 Q F1(db_btr)108 153.6 Q(ee)-.37 E F0(\(3\),).18 E F1
+(db_hash)2.5 E F0(\(3\),).28 E F1(db_loc)2.5 E(k)-.2 E F0(\(3\),).67 E F1
+(db_lo)2.5 E(g)-.1 E F0(\(3\),).22 E F1(db_mpool)2.5 E F0(\(3\),).51 E F1
+(db_open)2.5 E F0(\(3\),).24 E F1(db_r)2.5 E(ecno)-.37 E F0(\(3\)).18 E F1 .904
+(LIBTP: P)108 177.6 R(ortable)-.8 E 3.404(,M)-.1 G .904(odular T)189.738 177.6
+R -.15(ra)-.55 G .904(nsactions for UNIX).15 F F0 3.404(,M).94 G(ar)328.884
+177.6 Q .904(go Seltzer)-.18 F 3.403(,M)-.4 G .903
+(ichael Olson, USENIX proceedings,)392.041 177.6 R -.4(Wi)108 189.6 S
+(nter 1992.).4 E F2 -.09(BU)72 206.4 S(GS).09 E F0(The)108 218.4 Q F1(maxtxns)
+2.792 E F0 .292(parameter is a kluge, and should be deleted in f)2.792 F -.2
+(avo)-.1 G 2.793(ro).2 G 2.793(fd)378.448 218.4 S .293(ynamically e)389.571
+218.4 R .293(xpanding the transaction)-.15 F(re)108 230.4 Q(gion.)-.15 E
+(4.4 Berk)72 732 Q(ele)-.1 E 2.5(yD)-.15 G(istrib)132.57 732 Q 99.315
+(ution August)-.2 F(1, 1995)2.5 E(4)535 732 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_btree.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_btree.3
new file mode 100644
index 000000000..25e289f3c
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_btree.3
@@ -0,0 +1,246 @@
+.\" Copyright (c) 1990, 1993, 1994, 1995
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_btree.3	8.11 (Berkeley) 8/1/95
+.\"
+.TH DB_BTREE 3 "August 1, 1995"
+.UC 7
+.SH NAME
+db_btree \- btree database access method
+.SH DESCRIPTION
+.so db.so
+.GN
+specific details of the btree access method.
+.PP
+The btree data structure is a sorted, balanced tree structure storing
+associated key/data pairs.
+Searches, insertions, and deletions in the btree will all complete in
+O lg base N where base is the average fill factor.
+Often, inserting ordered data into btrees results in a low fill factor.
+This implementation has been modified to make ordered insertion the best
+case, resulting in a much better than normal page fill factor.
+.SH "ACCESS METHOD SPECIFIC INFORMATION"
+The btree access method specific data structure provided to
+.I db_open
+is typedef'd and named BTREEINFO.
+A BTREEINFO structure has at least the following fields,
+which may be initialized before calling
+.IR db_open :
+.TP 5
+u_int cachesize;
+A suggested maximum size (in bytes) of the memory cache.
+This value is
+.B only
+advisory, and the access method will allocate more memory rather than fail.
+Since every search examines the root page of the tree, caching the most
+recently used pages substantially improves access time.
+In addition, physical writes are delayed as long as possible, so a moderate
+cache can reduce the number of I/O operations significantly.
+Obviously, using a cache increases (but only increases) the likelihood of
+corruption or lost data if the system crashes while a tree is being modified.
+If
+.I cachesize
+is 0 (no size is specified) a default cache is used.
+.TP 5
+int (*compare)(const DBT *, const DBT *);
+Compare is the key comparison function.
+It must return an integer less than, equal to, or greater than zero if the
+first key argument is considered to be respectively less than, equal to,
+or greater than the second key argument.
+The same comparison function must be used on a given tree every time it
+is opened.
+If
+.I compare
+is NULL (no comparison function is specified), the keys are compared
+lexically, with shorter keys considered less than longer keys.
+.TP 5
+u_long flags;
+The flag value is specified by
+.IR or 'ing
+any of the following values:
+.RS
+.TP 5
+R_DUP
+Permit duplicate keys in the tree, i.e. permit insertion if the key to be
+inserted already exists in the tree.
+The default behavior, as described in
+.IR db_open (3),
+is to overwrite a matching key when inserting a new key or to fail if
+the R_NOOVERWRITE flag is specified.
+The R_DUP flag is overridden by the R_NOOVERWRITE flag, and if the
+R_NOOVERWRITE flag is specified, attempts to insert duplicate keys into
+the tree will fail.
+.IP
+If the database contains duplicate keys, the order of retrieval of
+key/data pairs is undefined if the
+.I get
+function is used, however,
+.I seq
+function calls with the R_CURSOR flag set will always return the logical
+``first'' of any group of duplicate keys.
+.RE
+.TP 5
+int lorder;
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example, 
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+.TP 5
+int maxkeypage;
+The maximum number of keys which will be stored on any single page.
+This functionality is not currently implemented.
+.\" The maximum number of keys which will be stored on any single page.
+.\" Because of the way the btree data structure works,
+.\" .I maxkeypage
+.\" must always be greater than or equal to 2.
+.\" If
+.\" .I maxkeypage
+.\" is 0 (no maximum number of keys is specified) the page fill factor is
+.\" made as large as possible (which is almost invariably what is wanted).
+.TP 5
+int minkeypage;
+The minimum number of keys which will be stored on any single page.
+This value is used to determine which keys will be stored on overflow
+pages, i.e. if a key or data item is longer than the pagesize divided
+by the minkeypage value, it will be stored on overflow pages instead
+of in the page itself.
+If
+.I minkeypage
+is 0 (no minimum number of keys is specified) a value of 2 is used.
+.TP 5
+size_t (*prefix)(const DBT *, const DBT *);
+Prefix is the prefix comparison function.
+If specified, this function must return the number of bytes of the second key
+argument which are necessary to determine that it is greater than the first
+key argument.
+If the keys are equal, the key length should be returned.
+Note, the usefulness of this function is very data dependent, but, in some
+data sets can produce significantly reduced tree sizes and search times.
+If
+.I prefix
+is NULL (no prefix function is specified),
+.B and
+no comparison function is specified, a default lexical comparison function
+is used.
+If
+.I prefix
+is NULL and a comparison function is specified, no prefix comparison is
+done.
+.TP 5
+u_int psize;
+Page size is the size (in bytes) of the pages used for nodes in the tree.
+The minimum page size is 512 bytes and the maximum page size is 64K.
+If
+.I psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+.PP
+If the file already exists (and the O_TRUNC flag is not specified), the
+values specified for the parameters flags, lorder and psize are ignored
+in favor of the values used when the tree was created.
+.SH "DB OPERATIONS"
+The functions returned by
+.I db_open
+for the btree access method are as described in
+.IR db_open (3),
+with the following exceptions and additions:
+.TP 5
+type
+The type is DB_BTREE.
+.TP 5
+del
+Space freed up by deleting key/data pairs from the tree is never reclaimed,
+although it is reused where possible.
+This means that the btree storage structure is grow-only.
+The only solutions are to avoid excessive deletions, or to create a fresh
+tree periodically from a scan of an existing one.
+.TP 5
+put
+The
+.I put
+function takes the following additional flags:
+.RS
+.TP 5
+R_SETCURSOR
+Store the key/data pair, setting or initializing the position of the
+cursor to reference it.
+.RE
+.TP 5
+seq
+Forward sequential scans of a tree are from the least key to the greatest.
+.IP
+The returned key for the
+.I seq
+function is not necessarily an exact match for the specified key in
+the btree access method.
+The returned key is the smallest key greater than or equal to the
+specified key, permitting partial key matches and range searches.
+.IP
+The
+.I seq
+function takes the following additional flags:
+.RS
+.TP 5
+R_LAST
+The last key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+.TP 5
+R_PREV
+Retrieve the key/data pair immediately before the cursor.
+If the cursor is not yet set, this is the same as the R_LAST flag.
+.RE
+.SH ERRORS
+The
+.I btree
+access method functions may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR db_open (3).
+.SH "SEE ALSO"
+.IR db_hash (3),
+.IR db_lock (3),
+.IR db_log (3),
+.IR db_mpool (3),
+.IR db_open (3),
+.IR db_recno (3),
+.IR db_txn (3)
+.sp
+.IR "The Ubiquitous B-tree" ,
+Douglas Comer, ACM Comput. Surv. 11, 2 (June 1979), 121-138.
+.sp
+.IR "Prefix B-trees" ,
+Bayer and Unterauer, ACM Transactions on Database Systems, Vol. 2, 1
+(March 1977), 11-26.
+.sp
+.IR "The Art of Computer Programming Vol. 3: Sorting and Searching" , 
+D.E. Knuth, 1968, pp 471-480.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_hash.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_hash.3
new file mode 100644
index 000000000..adb88fca7
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_hash.3
@@ -0,0 +1,138 @@
+.\" Copyright (c) 1990, 1993, 1994, 1995
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_hash.3	8.13 (Berkeley) 8/1/95
+.\"
+.TH DB_HASH 3 "August 1, 1995"
+.UC 7
+.SH NAME
+db_hash \- hash database access method
+.SH DESCRIPTION
+.so db.so
+.GN
+specific details of the hashing access method.
+.PP
+The hash data structure is an extensible, dynamic hashing scheme.
+Backward compatible interfaces to the functions described in
+.IR dbm (3),
+and
+.IR ndbm (3)
+are provided, however these interfaces are not compatible with
+previous file formats.
+.SH "ACCESS METHOD SPECIFIC INFORMATION"
+The hash access method specific data structure provided to
+.I db_open
+is typedef'd and named HASHINFO.
+A HASHINFO structure has at least the following fields,
+which may be initialized before calling
+.IR db_open :
+.TP 5
+u_int bsize;
+.I Bsize
+defines the hash table bucket size, and is, by default, 256 bytes.
+It may be preferable to increase the page size for disk-resident tables
+and tables with large data items.
+.TP 5
+u_int cachesize;
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.B only
+advisory, and the access method will allocate more memory rather
+than fail.
+.TP 5
+u_int ffactor;
+.I Ffactor
+indicates a desired density within the hash table.
+It is an approximation of the number of keys allowed to accumulate in any
+one bucket, determining when the hash table grows or shrinks.
+The default value is 8.
+.TP 5
+u_int32_t (*hash)(const void *, size_t);
+.I Hash
+is a user defined hash function.
+Since no hash function performs equally well on all possible data, the
+user may find that the built-in hash function does poorly on a particular
+data set.
+User specified hash functions must take two arguments (a pointer to a byte
+string and a length) and return a 32-bit quantity to be used as the hash
+value.
+.IP
+If a hash function is specified,
+.I hash_open
+will attempt to determine if the hash function specified is the same as
+the one with which the database was created, and will fail if it is not.
+.TP 5
+int lorder;
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example, 
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+If the  file already exists, the specified value is ignored and the
+value specified when the tree was created is used.
+.TP 5
+u_int nelem;
+.I Nelem
+is an estimate of the final size of the hash table.
+If not set or set too low, hash tables will expand gracefully as keys
+are entered, although a slight performance degradation may be noticed.
+The default value is 1.
+.PP
+If the file already exists (and the O_TRUNC flag is not specified), the
+values specified for the parameters bsize, ffactor, lorder and nelem are
+ignored and the values specified when the tree was created are used.
+.SH "DB OPERATIONS"
+The functions returned by
+.I db_open
+for the hash access method are as described in
+.IR db_open (3).
+.SH ERRORS
+The
+.I hash
+access method functions may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR db_open (3).
+.SH "SEE ALSO"
+.IR db_btree (3),
+.IR db_lock (3),
+.IR db_log (3),
+.IR db_mpool (3),
+.IR db_open (3),
+.IR db_recno (3),
+.IR db_txn (3)
+.sp
+.IR "Dynamic Hash Tables" ,
+Per-Ake Larson, Communications of the ACM, April 1988.
+.sp
+.IR "A New Hash Package for UNIX" ,
+Margo Seltzer, USENIX Proceedings, Winter 1991.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_lock.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_lock.3
new file mode 100644
index 000000000..b18a38c60
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_lock.3
@@ -0,0 +1,462 @@
+.\" Copyright (c) 1994, 1995
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_lock.3	8.14 (Berkeley) 8/1/95
+.\"
+.TH DB_LOCK 3 "August 1, 1995"
+.UC 7
+.SH NAME
+db_lock \- general purpose lock manager
+.SH SYNOPSIS
+.nf
+.ft B
+#include <db_lock.h>
+
+int
+lock_create(const char *path, mode_t mode,
+.ti +5
+int lock_modes, const int8_t conflicts[][], u_int maxlocks);
+
+LOCK_TABLE_T *
+lock_open(const char *path);
+
+int
+lock_vec(LOCK_TABLE_T *lt, DBT *locker, struct timespec *timeout,
+.ti +5
+LOCK_REQ_T list[], int nlist, LOCK_REQ_T **elistp, DBT *conflict);
+
+int
+lock_get(LOCK_TABLE_T *lt, const DBT *locker,
+.ti +5
+const DBT *obj, const lock_mode_t lock_mode, LOCK_T **lockp);
+
+int
+lock_put(LOCK_T *lockp);
+
+int
+lock_close(LOCK_TABLE_T *lt);
+
+int
+lock_unlink(const char *path, int force);
+.ft R
+.fi
+.SH DESCRIPTION
+.so db.so
+.GN
+specific details of the locking interface.
+.PP
+.I Db_lock
+is the library interface intended to provide general-purpose locking. 
+While designed to work with the other DB functions, these functions are
+also useful for more general locking purposes.
+Locks can be shared between processes.
+.PP
+.CR "lock table" lock
+.PP
+The parameter
+.I lock_modes
+is the number of lock modes to be recognized by the lock table
+(including the ``not-granted'' mode).
+The parameter
+.I conflicts
+is an
+.I lock_modes
+by
+.I lock_modes
+array.
+A non-0 value for:
+.sp
+.ti +5
+conflicts[requested_mode][held_mode]
+.sp
+indicates that
+.I requested_mode
+and
+.I held_mode
+conflict.
+The ``not-granted'' mode must be represented by 0.
+.PP
+The include file <db_lock.h> declares two commonly used conflict arrays:
+.TP 5
+int lock_sx_n;
+.br
+.ns
+.TP 5
+const int8_t lock_sx_c[lock_sx_n][lock_sx_n];
+These variables specify a conflict array
+for a simple scheme using shared and exclusive lock modes.
+.TP 5
+int lock_g_n;
+.br
+.ns
+.TP 5
+const int8_t lock_g_c[lock_g_n][lock_g_n];
+These variables specify a conflict array that involves various intent
+lock modes (e.g. intent shared) that are used for multigranularity locking.
+.PP
+In addition,
+<db_lock.h> defines the following macros that name lock modes for use with
+the standard tables above:
+.RS
+.TP 5
+LOCK_IS
+intent shared
+.br
+.ns
+.TP 5
+LOCK_IX
+intent exclusive
+.br
+.ns
+.TP 5
+LOCK_NG
+not granted (always 0)
+.br
+.ns
+.TP 5
+LOCK_S
+shared
+.br
+.ns
+.TP 5
+LOCK_SIX
+shared/intent exclusive
+.br
+.ns
+.TP 5
+LOCK_X
+exclusive
+.RE
+.PP
+.I Maxlocks
+is the maximum number of locks to be held or requested in the table,
+and is used by
+.I lock_create
+to estimate how much space to allocate for various lock-table data
+structures.
+.PP
+.RT lock_create
+.PP
+.OP "lock table" lock
+.PP
+The function
+.I lock_vec
+atomically obtains and releases one or more locks from the designated
+table.
+The function
+.I lock_vec
+is intended to support acquisition or trading of multiple locks
+under one lock table semaphore, as is needed for lock coupling or
+in multigranularity locking for lock escalation.
+.PP
+If any of the requested locks cannot be acquired
+or any of the locks to be released cannot be released,
+no locks are acquired and no locks are released, and
+.I lock_vec
+returns an error.
+The function
+.I lock_vec
+returns 0 on success.
+If an error occurs,
+.I lock_vec
+returns one of the following values.
+In addition, if
+.I elistp
+is not NULL, it is set to point to the LOCK_REQ_T entry which
+was being processed when the error occurred.
+.TP 5
+LOCK_GET_DEADLOCK
+The specified
+.I locker
+was selected as a victim in order to resolve a deadlock.
+In this case, if the
+.I conflict
+argument is non-NULL, it is set to reference the identity of a
+locker holding the lock referenced by
+.I elistp
+at the time the request was denied.
+(This identity resides in static memory and may be overwritten by
+subsequent calls to
+.IR lock_vec ).
+.TP 5
+LOCK_GET_ERROR
+An error occurred and the external variable
+.I errno
+has been set to indicate the error.
+.TP 5
+LOCK_GET_NOTHELD
+The lock cannot be released, as it was not held by the
+.IR locker .
+.TP 5
+LOCK_GET_RESOURCE
+The lock manager is unable to grant the requested locks because of
+limited internal resources.
+(Releasing locks may allow future calls to
+.I lock_vec
+to succeed.)
+.TP 5
+LOCK_GET_TIMEOUT
+A timeout argument was specified, and the requested locks were not
+available soon enough.
+In this case, if the
+.I conflict
+argument is non-NULL, it is set to reference the identity of a
+locker holding the lock referenced by
+.I elistp
+at the time the request was denied.
+(This identity resides in static memory and may be overwritten by
+subsequent calls to
+.IR lock_vec ).
+.PP
+The
+.I locker
+argument specified to
+.I lock_vec
+is a pointer to an untyped byte string which identifies the entity
+requesting or releasing the lock.
+If
+.I locker
+is NULL, the calling process' pid is used instead.
+.PP
+The
+.I timeout
+argument provided to
+.I lock_vec
+specifies a maximum interval to wait for the locks to be granted.
+If
+.I timeout
+is NULL, it is ignored, and
+.I lock_vec
+will not return until all of the locks are acquired or an error has
+occurred.
+.PP
+The
+.I list
+array provided to 
+.I lock_vec
+is typedef'd in <db_lock.h> as LOCK_REQ_T.
+A LOCK_REQ_T structure has at least the following fields,
+which must be initialized before calling
+.IR lock_vec :
+.TP 5
+enum lockop op;
+The operation to be performed, which must be set to one of the
+following values:
+.RS
+.TP 5
+LOCK_GET
+Get a lock, as defined by the values of
+.IR locker ,
+.I obj
+and
+.IR lock_mode .
+Upon return from
+.IR lock_vec ,
+if the
+.I lockp
+field is non-NULL, a reference to the acquired lock is stored there.
+(This reference is invalidated by any call to
+.I lock_vec
+or
+.I lock_put
+which releases the lock.)
+.TP 5
+LOCK_PUT
+The lock referenced by the contents of the
+.I lockp
+field is released.
+.TP 5
+LOCK_PUT_ALL
+All locks held by the
+.I locker
+are released.
+(Any locks acquired as a part of the current call to
+.I lock_vec
+are not considered for this operation).
+.TP 5
+LOCK_PUT_OBJ
+All locks held by the
+.IR locker ,
+on the object
+.IR obj ,
+with the mode specified by
+.IR lock_mode ,
+are released.
+A
+.I lock_mode
+of LOCK_NG indicates that all locks on the object should be released.
+(Any locks acquired as a part of the current call to
+.I lock_vec
+are not considered for this operation).
+.RE
+.TP 5
+const DBT obj;
+An untyped byte string which specifies the object to be locked or
+released.
+.TP 5
+const lock_mode_t lock_mode;
+The lock mode, used as an index into
+.IR lt 's
+conflict array.
+.TP 5
+LOCK_T **lockp;
+A pointer to a pointer to a lock reference.
+.PP
+The
+.I nlist
+argument specifies the number of elements in the
+.I list
+array.
+.PP
+The function
+.I lock_get
+is a simple interface to the
+.I lock_vec
+functionality, and is equivalent to calling the
+.I lock_vec
+function with the
+.I lt
+and
+.I locker
+arguments, NULL
+.IR timeout , 
+.I elistp
+and
+.I conflict
+arguments, and a single element
+.I list
+array, for which the
+.I op
+field is LOCK_GET, and the
+.IR obj ,
+.I lock_mode
+and
+.I lockp
+fields are represented by the arguments of the same name.
+Note that the type of the
+.I obj
+argument to
+.I lock_get
+is different from the
+.I obj
+element found in the LOCK_REQ_T structure.
+The
+.I lock_get
+function returns success and failure as described for the
+.I lock_vec
+function.
+.PP
+The function
+.I lock_put
+is a simple interface to the
+.I lock_vec
+functionality, and is equivalent to calling the
+.I lock_vec 
+function with a single element
+.I list
+array, for which the
+.I op
+field is LOCK_PUT and the
+.I lockp
+field is represented by the argument of the same name.
+Note that the type of the
+.I lockp
+argument to
+.I lock_put
+is different from the
+.I lockp
+element found in the LOCK_REQ_T structure.
+The
+.I lock_put
+function returns success and failure as described for the
+.I lock_vec
+function.
+.PP
+The function
+.I lock_close
+disassociates the calling process from the lock table
+.IR lt ,
+after releasing all locks held or requested by that process.
+.RT lock_close
+.PP
+.UN "lock table" lock
+.SH "ERRORS"
+The
+.I lock_create
+function may fail and set
+.I errno
+for any of the errors specified for the library routines
+.IR mmap (2),
+.IR open (2)
+and
+.IR malloc (3).
+.PP
+The
+.I lock_open
+function may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR mmap (2)
+and
+.IR open (2).
+.PP
+The
+.I lock_close
+function may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR close (2)
+and
+.IR munmap (2).
+.PP
+The
+.I lock_unlink
+function may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR unlink (2)
+or the following:
+.TP 5
+[EBUSY]
+The lock table was in use and the force flag was not set.
+.SH "SEE ALSO"
+.IR db_btree (3),
+.IR db_hash (3),
+.IR db_log (3),
+.IR db_mpool (3),
+.IR db_open (3),
+.IR db_recno (3),
+.IR db_txn (3)
+.SH BUGS
+The
+.I maxlocks
+parameter is a kluge, and should be deleted in favor of dynamically
+expanding the lock table.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_log.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_log.3
new file mode 100644
index 000000000..34c4d1f5d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_log.3
@@ -0,0 +1,290 @@
+.\" Copyright (c) 1990, 1993, 1994, 1995
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_log.3	8.15 (Berkeley) 8/3/95
+.\"
+.TH DB_LOG 3 "August 3, 1995"
+.UC 7
+.SH NAME
+db_log \- log-manager access method
+.SH DESCRIPTION
+.so db.so
+.GN
+specific details of the logging access method.
+.PP
+These functions provide a general-purpose logging facility sufficient
+for transaction management.
+Logs can be shared by multiple processes.
+.PP
+A log is represented by the directory,
+.IR "not the file" ,
+named by the first argument to
+.IR db_open (3).
+The first argument must be non-NULL,
+and the directory must already exist
+.I db_open
+is called.
+In that directory, the log is stored in one or more files named
+in the format ``log.YYYY.MM.DD.HH.MM.SS'', where ``YYYY.MM.DD.HH.SS''
+is the approximate creation time of the log file, and is guaranteed
+to be unique in the directory.
+.PP
+The group of the created files is based on the system and directory
+defaults, and is not further specified by the log access method.
+All files are created with the
+.I mode
+specified to
+.IR db_open ,
+(as described in
+.IR chmod (2))
+and modified by the process' umask value (see
+.IR umask (2)).
+.PP
+The
+.I flags
+argument to
+.I db_open
+must be 0 for the
+.I db_log
+access method.
+.SH "ACCESS METHOD SPECIFIC INFORMATION"
+The log access method specific data structure provided to
+.I db_open
+is typedef'd and named LOGINFO.
+A LOGINFO structure has at least the following fields,
+which may be initialized before calling
+.IR db_open :
+.TP 5
+off_t max_file_size;
+The maximum size of a single file in the log.
+If not specified, the maximum size defaults to an implementation-specific
+value.
+.TP 5
+int lorder;
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example, 
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+.PP
+If the log already exists, the values specified for the parameters
+max_file_size and lorder are ignored in favor of the values used
+when the log was created.
+.SH "DB OPERATIONS"
+The data part of the key/data pair used by the log access method
+is the same as for other access methods.
+The key is different.
+Each log record is identified by a log sequence number (LSN),
+which is stored in a DBT, and which is used as the
+.I key
+for all log functions that take
+.I key
+arguments.
+Applications cannot create LSN's, and all LSN's provided to functions
+as arguments must first be retrieved using the
+.I put
+or
+.I seq
+functions.
+To provide a distinguished value for applications, it is guaranteed that
+no valid LSN will ever have a size of 0.
+.PP
+Applications can compare LSN's using the
+.I log_lsn_compare
+function (see below).
+.PP
+Applications can associate LSN's with specific log files.
+The function
+.I log_lsn_file
+(see below), returns the name of the log file containing the
+record with a specified LSN.
+(The mapping of LSN to file is needed for database administration.
+For example, a transaction manager typically records the earliest LSN
+needed for restart, and the database administrator may want to archive
+log files to tape when they contain only LSN's before the earliest one
+needed for restart.)
+.PP
+Applications can truncate the log file up to a specific LSN using the 
+.I log_trunc
+function (see below).
+.PP
+The functions returned by
+.I db_open
+for the log access method are as described in
+.IR db_open ,
+with the following exceptions and additions:
+.TP 5
+type
+The type is DB_LOG.
+.TP 5
+del
+The
+.I del
+function always returns an error for the log-manager access method,
+setting
+.I errno
+to EINVAL.
+.TP 5
+int (*log_flush)(const DB *db, const DBT *lsn);
+The
+.I log_flush
+function flushes the log up to and including the log record
+.IR lsn .
+.RT log_flush
+.TP 5
+int (*log_lsn_compare)(const DB *,
+.ti +5
+const DBT *lsn1, const DBT *lsn2);
+A pointer to a function which is provided to permit applications to
+compare LSN's.
+The
+.I log_lsn_compare
+function returns an integer less than, equal to, or greater than zero
+if the first LSN is considered to be respectively less than, equal to,
+or greater than the second LSN.
+.TP 5
+int (*log_lsn_file)(const DB *db,
+.ti +5
+const DBT *lsn, char *name);
+.br
+The
+.I log_lsn_file
+function stores a pointer to the name of the file containing
+.I lsn
+in the address referenced by
+.IR name.
+This pointer is to an internal static object, and subsequent calls to
+the same function will modify the same object.
+.IP
+.RT log_lsn_file
+.TP 5
+int (*log_unlink)(const char *path, int force);
+The
+.I log_unlink
+function destroys the log represented by
+.IR path .
+If the
+.I force
+parameter is not set to 1 and there are other processes using the
+log, then
+.I log_unlink
+will return -1, setting
+.IR errno
+to EBUSY.
+If
+.I force is not set or there are no processes using the log, then all files
+used by the log are destroyed.
+.I log_unlink
+will return -1 on failure, setting
+.IR errno ,
+and 0 on success.
+.TP 5
+int (*log_trunc)(const DB *db, const DBT *lsn);
+The
+.I log_trunc
+function truncates the log up to an LSN which is less than
+.IR lsn .
+.RT log_trunc
+.TP 5
+put
+A log record containing
+.I data
+is appended to the log.
+Unlike the
+.I put
+functions for other access methods, the key parameter is not initialized
+by the application, instead, the LSN assigned to the data is returned in
+the
+.I key
+parameter.
+.IP
+The caller is responsible for providing any necessary structure to
+.I data .
+(For example, in a write-ahead logging protocol, the application must
+understand what part of
+.I data
+is an operation code, what part is redo information, and what part is
+undo information.
+In addition, most transaction managers will store in
+.I data
+the LSN of the previous log record for the same transaction,
+to support chaining back through the transaction's log records
+during undo.)
+.IP
+The parameter
+.I flag
+must be set to 0 or exactly one of the following values:
+.RS
+.TP 5
+R_CHECKPOINT
+Specify the key/data pair of the current call as the one to be returned
+when the
+.I seq
+function is next called with the R_CHECKPOINT flag.
+.TP 5
+R_FLUSH
+Flush immediately (ignoring any possibility for group commit).
+.RE
+.TP 5
+seq
+The
+.I seq
+function takes the following additional flag:
+.RS
+.TP 5
+R_CHECKPOINT
+The last key/data pair stored by the
+.I put
+function (using the R_CHECKPOINT flag) is returned,
+and the cursor is set or initialized to reference it.
+The expected use of this flag is during restart and to determine what
+part of the log must be available for restart.
+Therefore, the log record retrieved with R_CHECKPOINT should contain
+all the information that the transaction manager will need for this
+purpose.
+.RE
+.TP 5
+sync
+The
+.I sync
+function always returns an error for the log-manager access method,
+setting
+.I errno
+to EINVAL.
+.SH "SEE ALSO"
+.IR db_btree (3),
+.IR db_hash (3),
+.IR db_lock (3),
+.IR db_mpool (3),
+.IR db_open (3),
+.IR db_recno (3),
+.IR db_txn (3)
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_mpool.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_mpool.3
new file mode 100644
index 000000000..4b683b618
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_mpool.3
@@ -0,0 +1,403 @@
+.\" Copyright (c) 1990, 1993, 1994, 1995
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_mpool.3	8.14 (Berkeley) 8/1/95
+.\"
+.TH DB_MPOOL 3 "August 1, 1995"
+.UC 7
+.SH NAME
+db_mpool \- general purpose shared memory buffer pool
+.SH SYNOPSIS
+.nf
+.ft B
+#include <db.h>
+#include <mpool.h>
+
+int
+mpool_create(char *path, mode_t mode, size_t cachesize, u_long flags);
+
+MPOOL *
+mpool_open(char *path);
+
+int
+mpool_close(MPOOL *mp);
+
+MPOOLFILE *
+mpool_fopen(MPOOL *mp, char *path, size_t pagesize, void *pgcookie,
+.ti +5
+int (*pgin)(MPOOLFILE *mpf,
+.ti +8
+pgno_t pgno, void *pgaddr, void *pgcookie),
+.ti +5
+int (*pgout)(MPOOLFILE *mpf,
+.ti +8
+pgno_t pgno, void *pgaddr, void *pgcookie);
+
+int
+mpool_fclose(MPOOLFILE *mpf);
+
+void *
+mpool_get(MPOOLFILE *mpf, pgno_t *pgnoaddr, u_long flags,
+.ti +5
+int (*callback)(MPOOLFILE *mpf, pgno_t pgno));
+
+int
+mpool_put(MPOOLFILE *mpf, void *pgaddr, u_long flags);
+
+int
+mpool_sync(MPOOLFILE *mpf);
+
+int
+mpool_unlink(const char *path, int force);
+
+void
+mpool_stat(MPOOL *mp, FILE *fp);
+.ft R
+.fi
+.SH DESCRIPTION
+.so db.so
+.GN
+specific details of the memory pool interface.
+.PP
+The
+.I db_mpool
+function is the library interface intended to provide general-purpose,
+page-oriented buffer management of one or more files.
+While designed to work with the other DB functions, these functions are
+also useful for more general purposes.
+The memory pools (MPOOL's) are referred to in this document as
+simply ``pools''.
+Pools may be shared between processes.
+Pools are usually filled by pages from one or more files (MPOOLFILE's).
+Pages in the pool are replaced in LRU (least-recently-used) order,
+with each new page replacing the page which has been unused the longest.
+Pages retrieved from the pool using
+.I mpool_get
+are ``pinned'' in memory, by default,
+until they are returned to the pool using the
+.I mpool_put
+function.
+.PP
+.CR "memory pool" mpool
+.PP
+The
+.I cachesize
+argument specifies the size of the pool in bytes,
+and should be the size of the normal working set of the application with
+some small amount of additional memory for unusual situations.
+If the number of bytes currently ``pinned'' in memory exceeds
+.IR cachesize ,
+the
+.I db_mpool
+functions will attempt to allocate more memory and do not necessarily fail,
+although they may suffer performance degradation.
+.PP
+The
+.I flags
+argument is set by
+.IR or 'ing
+any of the following values:
+.TP
+MPOOL_PRIVATE
+The pool is not shared by other processes or threads,
+so no locking of pool resources is required.
+.PP
+.OP "memory pool" mpool
+.PP
+The
+.I mpool_close
+function closes the pool indicated by the MPOOL pointer
+.IR mp ,
+as returned by
+.IR mpool_open .
+This function does
+.B not
+imply a call to
+.I mpool_sync
+(or to
+.IR mpool_fclose )
+i.e. no pages are written to the source file as as a result of calling
+.IR mpool_close .
+.RT mpool_close
+.PP
+The function
+.I mpool_fopen
+opens a file for buffering in the pool specified by the MPOOL
+argument.
+The
+.I path
+argument is the name of the file to be opened.
+The
+.I pagesize
+argument is the size, in bytes, of the unit of transfer between the
+application and the pool, although not necessarily the unit of transfer
+between the pool and the source file.
+Applications not knowing the page size of the source file should
+retrieve the metadata from the file using a page size that is correct
+for the metadata, then close and reopen the file, or,
+otherwise determine the page size before calling
+.IR mpool_fopen .
+.PP
+If the
+.I pgin
+function is specified, it is called each time a page is read into
+the memory pool from the source file.
+If the
+.I pgout
+function is specified, it is called each time a page is written
+to the source file.
+Both functions are called with the MPOOLFILE pointer returned from
+.IR mpool_fopen ,
+the page number, a pointer to the page being read or written, and
+the argument
+.IR pgcookie .
+If either function fails, it should return non-zero and set
+.IR errno ,
+in which case the
+.I db_mpool
+function calling it will also fail, leaving
+.I errno
+intact.
+.PP
+The
+.I mpool_fclose
+function closes the source file indicated by the MPOOLFILE pointer
+.IR mpf .
+This function does
+.B not
+imply a call to
+.IR mpool_sync ,
+i.e. no pages are written to the source file as as a result of calling
+.IR mpool_fclose .
+.RT mpool_fclose
+.\"
+.\".PP
+.\"int
+.\"mpool_fd (MPOOLFILE *mpf);
+.\"
+.\".PP
+.\"The function
+.\".I mpool_fd
+.\"takes an MPOOLFILE pointer and returns the file descriptor being
+.\"used to read/write that file
+.\"to/from the pool.
+.PP
+The function
+.I mpool_get
+returns a pointer to the page with the page number specified by
+.IR pgnoaddr ,
+from the source file specified by the MPOOLFILE pointer
+.IR mpf .
+If the page does not exist or cannot be retrieved,
+.I mpool_get
+returns NULL and sets errno.
+.PP
+The
+.I flags
+argument is set by 
+.IR or 'ing
+any of the following values:
+.TP 5
+MPOOL_CALLBACK
+After the page number has been determined, but before any other
+process or thread can access the page, the function specified by
+the
+.I callback
+argument is called.
+If the function fails, it should return non-zero and set
+.IR errno ,
+in which case
+.I mpool_get
+will also fail, leaving
+.I errno
+intact.
+The
+.I callback
+function is called with the MPOOLFILE pointer returned from
+.I mpool_fopen
+and the page number.
+This functionality is commonly used when page locking is required,
+but the page number of the page being retrieved is not known.
+.TP 5
+MPOOL_CREATE
+If the specified page does not exist, create it.
+.TP 5
+MPOOL_LAST
+Return the last page of the source file and copy its page number
+to the location referenced by
+.IR pgnoaddr .
+.TP 5
+MPOOL_NEW
+Create a new page in the file and copy its page number to the location
+referenced by
+.IR pgnoaddr .
+.TP 5
+MPOOL_NOPIN
+Don't pin the page into memory.
+(This flag is intended for debugging purposes, when it's often useful
+to examine pages which are currently held by other parts of the
+application.
+Pages retrieved in this manner don't need to be returned to the
+memory pool, i.e. they should
+.B not
+be specified as arguments to the
+.IR mpool_put
+routine.)
+.PP
+Created pages have all their bytes set to 0.
+.PP
+All pages returned by
+.I mpool_get
+(unless the MPOOL_NOPIN flag is specified),
+will be retained (i.e. ``pinned'') in the pool until a subsequent
+call to
+.IR mpool_put .
+.PP
+The function
+.I mpool_put
+indicates that the page referenced by
+.I pgaddr
+can be evicted from the pool.
+.I Pgaddr
+must be an address previously returned by
+.IR mpool_get .
+.PP
+The flag value is specified by
+.IR or 'ing
+any of the following values:
+.TP 5
+MPOOL_DIRTY
+The page has been modified and must be written to the source file
+before being evicted from the pool.
+.TP 5
+MPOOL_DISCARD
+The page is unlikely to be useful in the near future, and should be
+discarded before other pages in the pool.
+.PP
+.RT mpool_put
+.PP
+The function
+.I mpool_sync
+writes all pages associated with the MPOOLFILE pointer
+.IR mpf ,
+which were specified as arguments to the
+.I mpool_put
+function with an associated flag of
+MPOOL_DIRTY,
+to the source file.
+.RT mpool_sync
+.PP
+.UN "memory pool" mpool
+.PP
+The function
+.I mpool_stat
+writes statistics for the memory pool
+.I mp
+to the file specified by
+.IR fp .
+These statistics include the number of files participating in the pool,
+the active pages in the pool, and numbers as to how effective the cache
+has been.
+.SH ERRORS
+The
+.IR mpool_create ,
+.I mpool_open
+and
+.I mpool_fopen
+functions may fail and set
+.I errno
+for any of the errors specified for the library functions
+.IR open (2),
+.IR read (2),
+and
+.IR malloc (3).
+.PP
+The
+.I mpool_close
+and
+.I mpool_fclose
+functions may fail and set
+.I errno
+for any of the errors specified for the library functions
+.IR close (2)
+and
+.IR free (3).
+.PP
+The
+.I mpool_get
+function may fail and set
+.I errno
+for any of the errors specified for the library functions
+.IR read (2),
+.IR write (2),
+and
+.IR malloc (3)
+or the following:
+.TP 5
+[EINVAL]
+The requested page does not exist and MPOOL_CREATE was not set.
+.PP
+The
+.I mpool_put
+function may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR write (2)
+or the following:
+.TP 5
+[EACCES]
+The source file was not opened for writing.
+.PP
+The
+.I mpool_sync
+function may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR write (2).
+.PP
+The
+.I mpool_unlink
+function may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR unlink (2)
+or the following:
+.TP 5
+[EBUSY]
+The memory pool was in use and the force flag was not set.
+.SH "SEE ALSO"
+.IR db_btree (3),
+.IR db_hash (3),
+.IR db_lock (3),
+.IR db_log (3),
+.IR db_open (3),
+.IR db_recno (3),
+.IR db_txn (3)
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_open.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_open.3
new file mode 100644
index 000000000..f988ef924
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_open.3
@@ -0,0 +1,574 @@
+.\" Copyright (c) 1990, 1993, 1994, 1995
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_open.3	8.15 (Berkeley) 8/1/95
+.\"
+.TH DB_OPEN 3 "August 1, 1995"
+.UC 7
+.SH NAME
+db_open \- database access methods
+.SH SYNOPSIS
+.nf
+.ft B
+#include <db.h>
+
+DB *
+db_open(const char *file, int flags, int mode,
+.ti +5
+DBTYPE type, DBINFO *dbinfo, const void *openinfo);
+.ft R
+.fi
+.SH DESCRIPTION
+.so db.so
+.GN
+the overall structure of the available access methods.
+.PP
+The currently supported file formats are btree, hashed, log and recno
+(i.e. flat-file oriented).
+The btree format is a representation of a sorted, balanced tree structure.
+The hashed format is an extensible, dynamic hashing scheme.
+The log format is a general-purpose logging facility.
+The recno format is a byte stream file with fixed or variable length
+records.
+The formats and other, format specific information are described in detail
+in their respective manual pages:
+.IR db_btree (3),
+.IR db_hash (3),
+.IR db_log (3),
+and
+.IR db_recno (3).
+.PP
+Db_open opens
+.I file
+for reading and/or writing.
+Files never intended to be preserved on disk may be created by setting
+the file parameter to NULL.
+(Note, while most of the access methods use
+.I file
+as the name of an underlying file on disk, this is not guaranteed.
+See the manual pages for the individual access methods for more
+information.)
+.PP
+The
+.I flags
+and
+.I mode arguments
+are as specified to the
+.IR open (2)
+function, however, only the O_CREAT, O_EXCL, O_EXLOCK, O_NONBLOCK,
+O_RDONLY, O_RDWR, O_SHLOCK and O_TRUNC flags are meaningful.
+(Note, opening a database file O_WRONLY is not possible.)
+.\"Three additional options may be specified by
+.\".IR or 'ing
+.\"them into the
+.\".I flags
+.\"argument.
+.\".TP
+.\"DB_LOCK
+.\"Do the necessary locking in the database to support concurrent access.
+.\"If concurrent access isn't needed or the database is read-only this
+.\"flag should not be set, as it tends to have an associated performance
+.\"penalty.
+.\".TP
+.\"DB_SHMEM
+.\"Place the underlying memory pool used by the database in shared
+.\"memory.
+.\"Necessary for concurrent access.
+.\".TP
+.\"DB_TXN
+.\"Support transactions in the database.
+.\"The DB_LOCK and DB_SHMEM flags must be set as well.
+.PP
+The
+.I type
+argument is of type DBTYPE (as defined in the <db.h> include file) and
+may be set to DB_BTREE, DB_HASH, DB_LOG or DB_RECNO.
+.PP
+The
+.I dbinfo 
+argument is a pointer to a structure containing references to locking,
+logging, transaction, and shared-memory buffer pool information.
+If 
+.I dbinfo
+is NULL, then the access method may still use these subsystems,
+but the usage will be private to the application and managed by DB.
+If
+.I dbinfo
+is non-NULL,
+then the module referenced by each of the non-NULL fields is used by DB
+as necessary.
+The fields of the DBINFO structure are defined as follows:
+.TP 5
+const char *errpfx;
+A prefix to prepend to error messages; used only if
+.I errfile
+is non-NULL.
+.TP 5
+FILE *errfile;
+The
+.IR stdio (3)
+file stream to which error messages are logged.
+.sp
+When any error occurs in the
+.I db_open
+function, or in any function called using a field of the returned DB
+structure, an error value is returned by the function,
+and the global variable
+.I errno
+is set appropriately.
+In some cases, however, the
+.I errno
+value may be insufficient to describe the cause of the error.
+In these cases, if
+.I errfile
+is non-NULL, additional error information will be written to the file
+stream it represents, preceded by the string, if any, specified by
+.IR errpfx .
+This error logging facility should not be required for normal operation,
+but may be useful in debugging applications.
+.TP 5
+char *errbuf;
+The buffer to which error messages are copied.
+If non-NULL,
+.I errbuf
+behaves as described for
+.IR errfile ,
+except that the
+.I errpfx
+field is ignored and the error message is copied into the specified
+buffer instead of being written to the FILE stream.
+The DB routines assume that the associated buffer is at least 1024 bytes
+in length.
+.TP 5
+LOCK_TABLE_T *lockinfo;
+If locking is required for the file being opened (as in the case of
+buffers being maintained in a shared memory buffer pool),
+the
+.I lockinfo
+field contains a return value from the function
+.I lock_open
+that should be used
+(see
+.IR db_lock (3)).
+If
+.I lockinfo
+is NULL, no locking is done.
+.TP 5
+DB *loginfo;
+If modifications to the file being opened should be logged, the
+.I loginfo
+field contains a return value from the function
+.IR dbopen ,
+when opening a DB file of type DB_LOG.
+If
+.I loginfo
+is NULL, no logging is done.
+.TP 5
+MPOOL *mpoolinfo;
+If the cache for the file being opened should be maintained in a shared
+buffer pool, the
+.I mpoolinfo
+field contains a return value from the function 
+.I mpool_open
+that should be used
+(see
+.IR db_mpool (3)).
+If
+.I mpoolinfo
+is NULL, a memory pool may still be created,
+but it will be private to the application and managed by DB.
+.TP 5
+TXNMGR *txninfo;
+If the accesses to the file being opened should take place in the context
+of transactions (providing atomicity and complete error recovery), the
+.I txninfo
+field contains a return value from the function
+.I txn_open
+(see
+.IR db_txn (3)).
+If transactions are specified,
+the application is responsible for making suitable calls to 
+.IR txn_begin ,
+.IR txn_abort ,
+and
+.IR txn_commit .
+If
+.I txninfo
+is NULL, no transaction support is done.
+.PP
+The
+.I openinfo
+argument is a pointer to an access method specific structure described
+in the access method's manual page.
+If
+.I openinfo
+is NULL, each access method will use defaults appropriate for the system
+and the access method.
+.SH "KEY/DATA PAIRS"
+Access to all access methods is based on key/data pairs.
+Both keys and data are represented by the following data structure:
+.PP
+typedef struct {
+.RS
+void *data;
+.br
+size_t size;
+.RE
+} DBT;
+.PP
+The elements of the DBT structure are defined as follows:
+.TP 5
+data
+A pointer to a byte string.
+.ns
+.br
+.TP 5
+size
+The length of
+.IR data ,
+in bytes.
+.PP
+Key and data byte strings may reference strings of essentially unlimited
+length, although any two of them must fit into available memory at the
+same time.
+.PP
+The access methods provide no guarantees about byte string alignment,
+and applications are responsible for maintaining any necessary alignment.
+.SH "DB OPERATIONS"
+.I Db_open
+returns a pointer to a DB structure (as defined in the <db.h> include file)
+on success, and NULL on error.
+The DB structure describes a database type, and includes a set of functions
+to perform various actions, as described below.
+Each of these functions takes a pointer to a DB structure, and may take
+one or more DBT *'s and a flag value as well.
+Individual access methods specify additional functions and flags which
+are specific to the method.
+The fields of the DB structure are as follows:
+.TP 5
+DBTYPE type;
+The type of the underlying access method (and file format).
+.TP 5
+int (*close)(const DB *db);
+A pointer to a function to flush any cached information to disk,
+free any allocated resources, and close any underlying files.
+Since key/data pairs are cached in memory, failing to sync the
+file with the
+.I close
+or
+.I sync
+function may result in inconsistent or lost information.
+.IP
+The
+.I close
+functions return -1 on failure, setting
+.IR errno ,
+and 0 on success.
+.TP 5
+int (*del)(const DB *db, TXN *txnid,
+.ti +5
+const DBT *key, u_int flags);
+.br
+A pointer to a function to remove key/data pairs from the database.
+The key/data pair associated with the specified
+.I key
+are discarded from the database.
+.IP
+The
+.I txnid
+parameter contains a transaction ID returned from
+.IR txn_begin ,
+if the file is being accessed under transaction protection,
+or NULL if transactions are not in effect.
+.IP
+The parameter
+.I flag
+must be set to 0 or exactly one of the following values:
+.RS
+.TP 5
+R_CURSOR
+Delete the record referenced by the cursor.
+The cursor must have previously been initialized.
+.RE
+.IP
+The
+.I delete
+functions return -1 on error, setting
+.IR errno ,
+0 on success, and 1 if the specified
+.I key
+did not exist in the file.
+.TP 5
+int (*fd)(const DB *db);
+A pointer to a function which returns a file descriptor representative
+of the underlying database.
+A file descriptor referencing the same file will be returned to all
+processes which call
+.I db_open
+with the same
+.I file
+name.
+This file descriptor may be safely used as an argument to the
+.IR fcntl (2)
+and
+.IR flock (2)
+locking functions.
+The file descriptor is not necessarily associated with any of the
+underlying files used by the access method.
+No file descriptor is available for in memory databases.
+.IP
+The
+.I fd
+functions return -1 on error, setting
+.IR errno ,
+and the file descriptor on success.
+.TP 5
+int (*get)(const DB *db, TXN *txnid,
+.ti +5
+const DBT *key, DBT *data, u_int flags);
+.br
+A pointer to a function which is the interface for keyed retrieval from
+the database.
+The address and length of the data associated with the specified
+.I key
+are returned in the structure referenced by
+.IR data .
+.IP
+The
+.I txnid
+parameter contains a transaction ID returned from
+.IR txn_begin ,
+if the file is being accessed under transaction protection,
+or NULL if transactions are not in effect.
+.IP
+The
+.I get
+functions return -1 on error, setting
+.IR errno ,
+0 on success, and 1 if the
+.I key
+was not found.
+.TP 5
+int (*put)(const DB *db, TXN *txnid,
+.ti +5
+DBT *key, const DBT *data, u_int flags);
+.br
+A pointer to a function to store key/data pairs in the database.
+.IP
+The
+.I txnid
+parameter contains a transaction ID returned from
+.IR txn_begin ,
+if the file is being accessed under transaction protection,
+or NULL if transactions are not in effect.
+.IP
+The parameter
+.I flag
+must be set to 0 or exactly one of the following values:
+.RS
+.TP 5
+R_CURSOR
+Replace the key/data pair referenced by the cursor.
+The cursor must have previously been initialized.
+.TP 5
+R_NOOVERWRITE
+Enter the new key/data pair only if the key does not previously exist.
+.RE
+.IP
+The default behavior of the
+.I put
+functions is to enter the new key/data pair, replacing any previously
+existing key.
+.IP
+The
+.I put
+functions return -1 on error, setting
+.IR errno ,
+0 on success, and 1 if the R_NOOVERWRITE
+.I flag
+was set and the key already exists in the file.
+.TP 5
+int (*seq)(const DB *db, TXN *txnid,
+.ti +5
+DBT *key, DBT *data, u_int flags);
+.br
+A pointer to a function which is the interface for sequential
+retrieval from the database.
+The address and length of the key are returned in the structure
+referenced by
+.IR key ,
+and the address and length of the data are returned in the
+structure referenced
+by
+.IR data .
+.IP
+The
+.I txnid
+parameter contains a transaction ID returned from
+.IR txn_begin ,
+if the file is being accessed under transaction protection,
+or NULL if transactions are not in effect.
+.IP
+Sequential key/data pair retrieval may begin at any time, and the
+logical position of the ``cursor'' is not affected by calls to the
+.IR del ,
+.IR get ,
+.IR put ,
+or
+.I sync
+functions.
+Modifications to the database during a sequential scan will be reflected
+in the scan, i.e. records inserted behind the cursor will not be returned
+while records inserted in front of the cursor will be returned.
+.IP
+The parameter
+.I flag
+must be set to 0 or exactly one of the following values:
+.RS
+.TP 5
+R_CURSOR
+The data associated with the specified key is returned.
+This differs from the
+.I get
+functions in that it sets or initializes the cursor to the location of
+the key as well.
+.TP 5
+R_FIRST
+The first key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+.TP 5
+R_NEXT
+Retrieve the key/data pair immediately after the cursor.
+If the cursor is not yet set, this is the same as the R_FIRST flag.
+.RE
+.IP
+The
+.I seq
+functions return -1 on error, setting
+.IR errno ,
+0 on success,
+and 1 if there are no key/data pairs less than or greater than the
+specified or current key.
+.TP 5
+int (*sync)(const DB *db, u_int flags);
+A pointer to a function to flush any cached information to disk.
+If the database is in memory only, the
+.I sync
+function has no effect and will always succeed.
+.IP
+The parameter
+.I flag
+must be set to 0 or a value specified by an access method specific
+manual page.
+.IP
+The
+.I sync
+functions return -1 on failure, setting
+.IR errno ,
+and 0 on success.
+.SH ERRORS
+The
+.I db_open
+function may fail and set
+.I errno
+for any of the errors specified for the library functions
+.IR open (2),
+.IR malloc (3)
+or the following:
+.TP 5
+[EFTYPE]
+A file is incorrectly formatted.
+.TP 5
+[EINVAL]
+A parameter has been specified (hash function, recno pad byte etc.)
+that is incompatible with the current file specification or, a flag
+to a function which is not meaningful for the function (for example,
+use of the cursor without prior initialization) or there is a mismatch
+between the version number of file and the software.
+.PP
+The
+.I close
+functions may fail and set
+.I errno
+for any of the errors specified for the library functions
+.IR close (2),
+.IR read (2),
+.IR write (2),
+.IR free (3),
+or
+.IR fsync (2).
+.PP
+The
+.IR del ,
+.IR get ,
+.I put
+and
+.I seq
+functions may fail and set
+.I errno
+for any of the errors specified for the library functions
+.IR read (2),
+.IR write (2),
+.IR free (3)
+or
+.IR malloc (3).
+.PP
+The
+.I fd
+functions will fail and set
+.I errno
+to ENOENT for in memory databases.
+.PP
+The
+.I sync
+functions may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR fsync (2).
+.SH "SEE ALSO"
+.IR db_btree (3),
+.IR db_hash (3),
+.IR db_lock (3),
+.IR db_log (3),
+.IR db_mpool (3),
+.IR db_recno (3),
+.IR db_txn (3)
+.SH BUGS
+The name DBT is a mnemonic for ``data base thang'', and was used
+because noone could think of a reasonable name that wasn't already
+in use somewhere else.
+.PP
+The
+.I fd
+function interface is a kluge,
+and will be deleted in a future version of the interface.
+.PP
+Only big and little endian byte order is supported.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_recno.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_recno.3
new file mode 100644
index 000000000..6b93b3f5a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_recno.3
@@ -0,0 +1,268 @@
+.\" Copyright (c) 1990, 1993, 1994, 1995
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_recno.3	8.12 (Berkeley) 8/1/95
+.\"
+.TH DB_RECNO 3 "August 1, 1995"
+.UC 7
+.SH NAME
+db_recno \- record number database access method
+.SH DESCRIPTION
+.so db.so
+specific details of the recno access method.
+.SH "ACCESS METHOD SPECIFIC INFORMATION"
+The recno access method specific data structure provided to
+.I db_open
+is typedef'd and named RECNOINFO.
+A RECNOINFO structure has at least the following fields,
+which may be initialized before calling
+.IR db_open :
+.TP 5
+u_int8_t bval;
+The delimiting byte to be used to mark the end of a record for
+variable-length records, and the pad character for fixed-length
+records.
+If no value is specified, newlines (``\en'') are used to mark the end
+of variable-length records and fixed-length records are padded with
+spaces.
+.TP 5
+char *bfname;
+The recno access method stores the in-memory copies of its records
+in a btree.
+If bfname is non-NULL, it specifies the name of the btree file,
+as if specified as the file name for a
+.I db_open
+of a btree file.
+.TP 5
+u_int cachesize;
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.B only
+advisory, and the access method will allocate more memory rather than fail.
+If
+.I cachesize
+is  0 (no size is specified) a default size is used.
+.TP 5
+u_long flags;
+The flag value is specified by
+.IR or 'ing
+any of the following values:
+.RS
+.TP 5
+R_FIXEDLEN
+The records are fixed-length, not byte delimited.
+The structure element
+.I reclen
+specifies the length of the record, and the structure element
+.I bval
+is used as the pad character.
+Any records, inserted into the database, that are less than
+.I reclen
+bytes long are automatically padded.
+.TP 5
+R_NOKEY
+In the interface specified by
+.IR db_open ,
+the sequential record retrieval fills in both the caller's key and
+data structures.
+If the R_NOKEY flag is specified, the
+.I cursor
+functions are not required to fill in the key structure.
+This permits applications to retrieve records at the end of files without
+reading all of the intervening records.
+.TP 5
+R_SNAPSHOT
+This flag requires that a snapshot of the file be taken when
+.I db_open
+is called, instead of permitting any unmodified records to be read from
+the original file.
+.RE
+.TP 5
+int lorder;
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+.TP 5
+u_int psize;
+The recno access method stores the in-memory copies of its records
+in a btree.
+This value is the size (in bytes) of the pages used for nodes in that tree.
+If
+.I psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+See
+.IR btree (3)
+for more information.
+.TP 5
+size_t reclen;
+The length of a fixed-length record.
+.SH "DB OPERATIONS"
+The data part of the key/data pair used by the recno access method
+is the same as other access methods.
+The key is different.
+The
+.I data
+field of the key should be a pointer to a memory location of type
+.IR recno_t ,
+as defined in the <db.h> include file.
+This type is normally the largest unsigned integral type available to
+the implementation.
+The
+.I size
+field of the key should be the size of that type.
+.PP
+The record number data structure is either variable or fixed-length
+records stored in a flat-file format, accessed by the logical record
+number.
+The existence of record number five requires the existence of records
+one through four, and the deletion of record number one causes
+record number five to be renumbered to record number four, as well
+as the cursor, if positioned after record number one, to shift down
+one record.
+The creation of record number five when records one through four do
+not exist causes the logical creation of them with zero-length data.
+.PP
+Because there is no meta-data associated with the underlying recno access
+method files, any changes made to the default values (e.g. fixed record
+length or byte separator value) must be explicitly specified each time the
+file is opened.
+.PP
+The functions returned by
+.I db_open
+for the btree access method are as described in
+.IR db_open (3),
+with the following exceptions and additions:
+.TP 5
+type
+The type is DB_RECNO.
+.TP 5
+put
+Using the
+.I put
+interface to create a new record will cause the creation of multiple,
+empty records if the record number is more than one greater than the
+largest record currently in the database.
+.IP
+The
+.I put
+function takes the following additional flags:
+.RS
+.TP 5
+R_IAFTER
+Append the data immediately after the data referenced by
+.IR key ,
+creating a new key/data pair.
+The record number of the appended key/data pair is returned in the
+.I key
+structure.
+.TP 5
+R_IBEFORE
+Insert the data immediately before the data referenced by
+.IR key ,
+creating a new key/data pair.
+The record number of the inserted key/data pair is returned in the
+.I key
+structure.
+.TP 5
+R_SETCURSOR
+Store the key/data pair, setting or initializing the position of the
+cursor to reference it.
+.RE
+.TP 5
+seq
+The
+.I seq
+function takes the following additional flags:
+.RS
+.TP 5
+R_LAST
+The last key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+.TP 5
+R_PREV
+Retrieve the key/data pair immediately before the cursor.
+If the cursor is not yet set, this is the same as the R_LAST flag.
+.RE
+.IP
+If the database file is a character special file and no complete
+key/data pairs are currently available, the
+.I seq
+function returns 2.
+.TP 5
+sync
+The
+.I sync
+function takes the following additional flag:
+.RS
+.TP 5
+R_RECNOSYNC
+This flag causes the
+.I sync
+function to apply to the btree file which underlies the recno file,
+not the recno file itself.
+(See the
+.I bfname
+field of RECNOINFO
+structure, above, for more information.)
+.RE
+.SH ERRORS
+The
+.I recno
+access method functions may fail and set
+.I errno
+for any of the errors specified for the library function
+.IR db_open (3)
+or the following:
+.TP 5
+[EINVAL]
+An attempt was made to add a record to a fixed-length database that
+was too large to fit.
+.SH "SEE ALSO"
+.IR db_btree (3),
+.IR db_hash (3),
+.IR db_lock (3),
+.IR db_log (3),
+.IR db_mpool (3),
+.IR db_open (3),
+.IR db_txn (3)
+.sp
+.IR "Document Processing in a Relational Database System" ,
+Michael Stonebraker, Heidi Stettner, Joseph Kalash, Antonin Guttman,
+Nadene Lynn, Memorandum No. UCB/ERL M82/32, May 1982.
+.SH BUGS
+The
+.I sync
+function's R_RECNOSYNC interface is a kluge,
+and will be deleted in a future version of the interface.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_txn.3 b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_txn.3
new file mode 100644
index 000000000..18ad64692
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/db_txn.3
@@ -0,0 +1,373 @@
+.\" Copyright (c) 1994, 1995
+.\"	The President and Fellows of Harvard University.  All rights reserved.
+.\" Copyright (c) 1994, 1995
+.\"	Margo I. Selzer.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"	@(#)db_txn.3	8.8 (Harvard) 8/1/95
+.\"
+.TH DB_TXN 3 "August 1, 1995"
+.UC 7
+.SH NAME
+db_txn \- transaction management functions
+.SH SYNOPSIS
+.nf
+.ft B
+#include <db.h>
+#include <db_lock.h>
+
+int
+txn_create(const char *path, mode_t mode, u_int maxtxns, u_int flags);
+
+TXNMGR *
+txn_open(const char *path, DBT *logp, LOCK_TABLE_T *lockp,
+.ti +5
+int (*recover)(DBT *lsn, DBT *log_entry, int isundo));
+
+TXN *
+txn_begin(TXNMGR *txnp);
+
+int
+txn_commit(TXN *tid);
+
+int
+txn_prepare(TXN *tid);
+
+int
+txn_abort(TXN *tid);
+
+int
+txn_close(TXNMGR *txnp);
+
+int
+txn_unlink(const char *path, int force);
+.ft R
+.fi
+.SH DESCRIPTION
+.so db.so
+specific details of the transaction support.
+.PP
+.I Db_txn
+is the library interface that provides transaction semantics.
+Full transaction support is provided by a collection of modules
+that provide well defined interfaces to the services required for
+transaction processing.
+These services are recovery (see
+.IR db_log (3)),
+concurrency control (see
+.IR db_lock (3)),
+and the management of shared data (see
+.IR db_mpool (3)).
+Transaction semantics can be applied to the access methods described in
+.IR db (3)
+through function call parameters.
+.PP
+The model intended for transactional use (and that is used by the
+access methods) is that write-ahead logging is provided by
+.IR db_log (3)
+to record both before- and after-image logging.
+Locking follows a two-phase protocol and is implemented by
+.IR db_lock (3).
+.PP
+.CR "transaction region" txn
+Any necessary,
+associated log and lock regions are created as well (see
+.IR db_log (3)
+and
+.IR db_lock (3)).
+.PP
+The
+.I maxtxns
+argument specifies the maximum number of simultaneous transactions that
+are supported.
+This bounds the size of backing files and is used to derive limits for
+the size of the lock region and logfiles.
+When there are more than
+.I maxtxns
+concurrent transactions, calls to
+.I txn_begin
+may fail.
+.PP
+Default locking and logging protocols are provided only if the
+backing files exist.
+If the backing files do not exist, the
+.I flags
+parameter must indicate both a logging mode and locking mode specified by 
+.IR or 'ing
+together at most one flag from each of the TXN_LOCK and TXN_LOG classes
+as follows:
+.TP 5
+TXN_LOCK_2PL
+Use two-phase locking.
+.TP 5
+TXN_LOCK_OPTIMISTIC
+Use optimistic locking (not currently implemented).
+.TP 5
+TXN_LOG_REDO
+Provide redo-only logging (not currently implemented).
+.TP 5
+TXN_LOG_UNDO
+Provide undo-only logging (not currently implemented).
+.TP 5
+TXN_LOG_UNDOREDO
+Provide undo/redo write-ahead logging.
+.PP
+.RT txn_create
+.PP
+.OP "transaction region" txn
+.PP
+The
+.I recover
+argument specifies a function that is called by
+.I txn_abort
+during transaction abort.
+This function takes three arguments:
+.TP 5
+lsn
+A log sequence number (LSN).
+.TP 5
+log_entry
+A log record.
+.TP 5
+isundo
+An undo flag set to 0 if the operation is a redo and set to 1 if the
+operation an undo.
+.PP
+As discussed in the
+.I db_log (3)
+manual page,
+the application is responsible for providing any necessary structure
+to the log record.
+For example, the application must understand what part of the log
+record is an operation code, what part is redo information, and what
+part is undo information.
+.PP
+The
+.I txn_begin 
+function creates a new transaction in the designated transaction
+manager, returning a pointer to a TXN that uniquely identifies it.
+.PP
+The
+.I txn_commit
+function ends the transaction specified by the
+.I tid
+argument.
+Any locks held by the transaction are released.
+If logging is enabled, a commit log record is written and flushed to disk.
+.PP
+The
+.I txn_abort
+function causes an abnormal termination of the transaction.
+If logging is enabled, the log is played backwards and any recovery
+operations are initiated through the
+.I recover
+function specified to
+.IR txn_open .
+After recovery is completed, all locks held by the transaction are released.
+.PP
+The 
+.I txn_close
+function detaches a process from the transaction environment specified
+by the TXNMGR pointer.
+All mapped regions are unmapped and any allocated resources are freed.
+Any uncommitted transactions are aborted.
+.PP
+.UN "transaction region" txn
+.PP
+The
+.I txn_prepare
+function initiates the beginning of a two phase commit.
+In a distributed transaction,
+the prepare directive should be issued to all participating
+transaction managers.
+Each manager must take whatever action is necessary to guarantee
+that a future call to
+.I txn_commit
+on the specified
+.I tid
+will succeed.
+.SH "SYSTEM INTEGRATION"
+This model can be applied to data bases other than the provided access
+methods.
+For example, consider an application that provides transaction semantics
+to data stored in regular files accessed using the 
+.IR read (2)
+and
+.IR write (2)
+system calls.
+The operations for which transaction protection is desired are bracketed
+by calls to
+.I txn_begin
+and
+.IR txn_commit .
+.PP
+Before data are referenced, a call is made to the lock manager,
+.IR db_lock ,
+for a lock of the appropriate type (e.g. read)
+on the object being locked.
+The object might be a page in the file, a byte, a range of bytes,
+or some key.
+Before a write is performed, the application makes a call to the
+log manager,
+.IR db_log ,
+to record enough information to redo the operation in case of
+failure after commit and to undo the operation in case of abort.
+After the log message is written, the write system calls are issued.
+After all requests are issued, the application calls
+.IR txn_commit .
+When
+.I txn_commit
+returns, the caller is guaranteed that all necessary log writes have
+been written to disk. 
+.PP
+At any time, the application may call
+.IR txn_abort ,
+which will result in the appropriate calls to the
+.I recover
+routine to restore the ``database'' to a consistent pre-transaction
+state.
+(The recover routine must be able to either reapply or undo the update
+depending on the context, for each different type of log record.)
+.PP
+If the application should crash, the recovery process uses the
+.I db_log
+interface to read the log and call the
+.I recover
+routine to restore the database to a consistent state.
+.PP
+The
+.I txn_prepare 
+function provides the core functionality to implement distributed
+transactions,
+but it does not actually manage the notification of distributed
+transaction managers.
+The caller is responsible for issuing 
+.I txn_prepare
+calls to all sites participating in the transaction.
+If all responses are positive, the caller can issue a
+.IR txn_commit .
+If any of the responses are negative, the caller should issue a
+.IR txn_abort .
+In general, the 
+.I txn_prepare
+call requires that the transaction log be flushed to disk.
+.PP
+The structure of the transaction support allows application designers
+to trade off performance and protection.
+Since DB manages many structures in shared memory,
+its information is subject to corruption by applications when the library
+is linked directly with the application.
+For this reason, DB is designed to allow compilation into a separate
+server process that may be accessed via a socket interface.
+In this way DB's data structures are protected from application code,
+but communication overhead is increased.
+When applications are trusted, DB may be compiled directly into the
+application for increased performance.
+.SH ERRORS
+The
+.I txn_create
+function may fail and set
+.I errno
+for any of the errors specified for the library functions
+.IR open (2),
+.IR write (2),
+.IR malloc (3),
+.IR lock_create (3),
+and
+.IR log_create (3).
+.PP
+The
+.I txn_open
+function may fail and set
+.I errno
+to any of the errors specified for the library functions
+.IR open (2),
+.IR write (2),
+.IR malloc (3),
+.IR lock_open (3),
+and
+.IR log_open (3).
+.PP
+The
+.I txn_begin
+function may fail and set
+.I errno
+to ENOSPC indicating that the maximum number of concurrent
+transactions has been reached.
+.PP
+The
+.I txn_commit
+function may fail and set
+.I errno
+to EINVAL indicating that the transaction was aborted.
+.PP
+The
+.I txn_close
+function may fail and set
+.I errno
+to any of the errors specified for the library functions
+.IR close (2),
+.IR read (2),
+.IR write (2),
+.IR free (3),
+.IR fsync (2),
+.IR lock_close (3)
+or
+.IR log_close (3).
+.PP
+The
+.I txn_unlink
+function may fail and set
+.I errno
+to any of the errors specified for the library functions
+.IR unlink (2),
+.IR lock_unlink (3),
+and
+.IR log_unlink (3),
+or the following:
+.TP 5
+[EBUSY]
+The transaction region was in use and the force flag was not set.
+.SH "SEE ALSO"
+.IR db_btree (3),
+.IR db_hash (3),
+.IR db_lock (3),
+.IR db_log (3),
+.IR db_mpool (3),
+.IR db_open (3),
+.IR db_recno (3)
+.sp
+.IR "LIBTP: Portable, Modular Transactions for UNIX" ,
+Margo Seltzer, Michael Olson, USENIX proceedings, Winter 1992.
+.SH BUGS
+The
+.I maxtxns
+parameter is a kluge, and should be deleted in favor of dynamically
+expanding the transaction region.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/man/spell.ok b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/spell.ok
new file mode 100644
index 000000000..794b00bf8
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/man/spell.ok
@@ -0,0 +1,170 @@
+Ake
+Antonin
+BTREE
+BTREEINFO
+Bsize
+CALLBACK
+Comput
+D.E
+DB
+DB's
+DBINFO
+DBT
+DBTYPE
+Db
+EACCES
+EBUSY
+EFTYPE
+EINVAL
+ENOENT
+ENOSPC
+ERL
+EXCL
+EXLOCK
+FIXEDLEN
+Ffactor
+Guttman
+HASHINFO
+Heidi
+IAFTER
+IBEFORE
+Kalash
+Knuth
+LIBTP
+LOGINFO
+LRU
+LSN
+LSN's
+MPOOL
+MPOOL's
+MPOOLFILE
+MPOOLFILE's
+Maxlocks
+Mpool
+NG
+NOKEY
+NOOVERWRITE
+NOPIN
+NOTHELD
+Nadene
+Nelem
+Nelems
+OBJ
+Pgaddr
+RDONLY
+RDWR
+RECNO
+RECNOINFO
+RECNOSYNC
+REQ
+SETCURSOR
+SHLOCK
+Stettner
+Stonebraker
+Surv
+TMPDIR
+TRUNC
+TXN
+TXNMGR
+Txn
+UCB
+UNDOREDO
+USENIX
+Unterauer
+Vol
+WAL
+WRONLY
+XACT
+YYYY.MM.DD.HH.SS
+al
+bfname
+bsize
+btree
+btrees
+bval
+cachesize
+callback
+const
+db
+db.h
+dbinfo
+dbopen
+del
+elistp
+endian
+enum
+errbuf
+errfile
+errno
+errpfx
+fd
+ffactor
+getv
+ing
+int
+int32
+int8
+isundo
+kluge
+lastlsn
+lg
+lock.h
+lockinfo
+lockop
+lockp
+log.YYYY.MM.DD.HH.MM.SS
+logfiles
+loginfo
+logp
+lreq
+lsn
+lsn1
+lsn2
+lt
+maxcache
+maxkeypage
+maxlocks
+maxtxns
+meta
+minkeypage
+mmap
+mpf
+mpool
+mpool.h
+mpoolinfo
+munmap
+nacquire
+nelem
+nelems
+nmodes
+noone
+nrelease
+obj
+op
+openinfo
+pathname
+pgaddr
+pgcookie
+pgin
+pgno
+pgnoaddr
+pgout
+pid
+pp
+psize
+queue.h
+reclen
+recno
+sx
+thang
+timespec
+tmp
+trunc
+txn
+txnid
+txninfo
+txnp
+typedef
+typedef'd
+vec
+writeable
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.in
new file mode 100644
index 000000000..d06b69a9c
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.in
@@ -0,0 +1,11 @@
+thisconfigdir=./..
+myfulldir=plugins/kdb/db2/libdb2/mpool
+mydir=mpool
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+STLIBOBJS=mpool.o
+
+LOCALINCLUDES=	-I. -I$(srcdir)/../include -I../include -I$(srcdir)/../db
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc
new file mode 100644
index 000000000..93210c89e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc
@@ -0,0 +1,5 @@
+#	@(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/db/mpool
+
+SRCS+=	mpool.c
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/README b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/README
new file mode 100644
index 000000000..0f01fbcdb
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/README
@@ -0,0 +1,7 @@
+#	@(#)README	8.1 (Berkeley) 6/4/93
+
+These are the current memory pool routines.
+They aren't ready for prime time, yet, and
+the interface is expected to change.
+
+--keith
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.c
new file mode 100644
index 000000000..56f2749a9
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.c
@@ -0,0 +1,513 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mpool.c	8.7 (Berkeley) 11/2/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#include "mpool.h"
+
+static BKT *mpool_bkt __P((MPOOL *));
+static BKT *mpool_look __P((MPOOL *, db_pgno_t));
+static int  mpool_write __P((MPOOL *, BKT *));
+
+/*
+ * mpool_open --
+ *	Initialize a memory pool.
+ */
+MPOOL *
+mpool_open(key, fd, pagesize, maxcache)
+	void *key;
+	int fd;
+	db_pgno_t pagesize, maxcache;
+{
+	struct stat sb;
+	MPOOL *mp;
+	int entry;
+
+	/*
+	 * Get information about the file.
+	 *
+	 * XXX
+	 * We don't currently handle pipes, although we should.
+	 */
+	if (fstat(fd, &sb))
+		return (NULL);
+	if (!S_ISREG(sb.st_mode)) {
+		errno = ESPIPE;
+		return (NULL);
+	}
+
+	/* Allocate and initialize the MPOOL cookie. */
+	if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
+		return (NULL);
+	CIRCLEQ_INIT(&mp->lqh);
+	for (entry = 0; entry < HASHSIZE; ++entry)
+		CIRCLEQ_INIT(&mp->hqh[entry]);
+	mp->maxcache = maxcache;
+	mp->npages = sb.st_size / pagesize;
+	mp->pagesize = pagesize;
+	mp->fd = fd;
+	return (mp);
+}
+
+/*
+ * mpool_filter --
+ *	Initialize input/output filters.
+ */
+void
+mpool_filter(mp, pgin, pgout, pgcookie)
+	MPOOL *mp;
+	void (*pgin) __P((void *, db_pgno_t, void *));
+	void (*pgout) __P((void *, db_pgno_t, void *));
+	void *pgcookie;
+{
+	mp->pgin = pgin;
+	mp->pgout = pgout;
+	mp->pgcookie = pgcookie;
+}
+	
+/*
+ * mpool_new --
+ *	Get a new page of memory.
+ */
+void *
+mpool_new(mp, pgnoaddr, flags)
+	MPOOL *mp;
+	db_pgno_t *pgnoaddr;
+	u_int flags;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	if (mp->npages == MAX_PAGE_NUMBER) {
+		(void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
+		abort();
+	}
+#ifdef STATISTICS
+	++mp->pagenew;
+#endif
+	/*
+	 * Get a BKT from the cache.  Assign a new page number, attach
+	 * it to the head of the hash chain, the tail of the lru chain,
+	 * and return.
+	 */
+	if ((bp = mpool_bkt(mp)) == NULL)
+		return (NULL);
+	if (flags == MPOOL_PAGE_REQUEST) {
+		mp->npages++;
+		bp->pgno = *pgnoaddr;
+	} else
+		bp->pgno = *pgnoaddr = mp->npages++;
+
+	bp->flags = MPOOL_PINNED | MPOOL_INUSE;
+
+	head = &mp->hqh[HASHKEY(bp->pgno)];
+	CIRCLEQ_INSERT_HEAD(head, bp, hq);
+	CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
+	return (bp->page);
+}
+
+int
+mpool_delete(mp, page)
+	MPOOL *mp;
+	void *page;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	bp = (BKT *)((char *)page - sizeof(BKT));
+
+#ifdef DEBUG
+	if (!(bp->flags & MPOOL_PINNED)) {
+		(void)fprintf(stderr,
+		    "mpool_delete: page %d not pinned\n", bp->pgno);
+		abort();
+	}
+#endif
+
+	/* Remove from the hash and lru queues. */
+	head = &mp->hqh[HASHKEY(bp->pgno)];
+	CIRCLEQ_REMOVE(head, bp, hq);
+	CIRCLEQ_REMOVE(&mp->lqh, bp, q);
+
+	free(bp);
+	return (RET_SUCCESS);
+}	
+	
+/*
+ * mpool_get
+ *	Get a page.
+ */
+void *
+mpool_get(mp, pgno, flags)
+	MPOOL *mp;
+	db_pgno_t pgno;
+	u_int flags;				/* XXX not used? */
+{
+	struct _hqh *head;
+	BKT *bp;
+	off_t off;
+	int nr;
+
+#ifdef STATISTICS
+	++mp->pageget;
+#endif
+
+	/* Check for a page that is cached. */
+	if ((bp = mpool_look(mp, pgno)) != NULL) {
+#ifdef DEBUG
+		if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) {
+			(void)fprintf(stderr,
+			    "mpool_get: page %d already pinned\n", bp->pgno);
+			abort();
+		}
+#endif
+		/*
+		 * Move the page to the head of the hash chain and the tail
+		 * of the lru chain.
+		 */
+		head = &mp->hqh[HASHKEY(bp->pgno)];
+		CIRCLEQ_REMOVE(head, bp, hq);
+		CIRCLEQ_INSERT_HEAD(head, bp, hq);
+		CIRCLEQ_REMOVE(&mp->lqh, bp, q);
+		CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+		/* Return a pinned page. */
+		bp->flags |= MPOOL_PINNED;
+		return (bp->page);
+	}
+
+	/* Get a page from the cache. */
+	if ((bp = mpool_bkt(mp)) == NULL)
+		return (NULL);
+
+	/* Read in the contents. */
+#ifdef STATISTICS
+	++mp->pageread;
+#endif
+	off = mp->pagesize * pgno;
+	if (off / mp->pagesize != pgno) {
+	    /* Run past the end of the file, or at least the part we
+	       can address without large-file support?  */
+	    errno = E2BIG;
+	    return NULL;
+	}
+	if (lseek(mp->fd, off, SEEK_SET) != off)
+		return (NULL);
+
+	if ((nr = read(mp->fd, bp->page, mp->pagesize)) != mp->pagesize) {
+		if (nr > 0) {
+			/* A partial read is definitely bad. */
+			errno = EINVAL;
+			return (NULL);
+		} else {
+			/*
+			 * A zero-length reads, means you need to create a
+			 * new page.
+			 */
+			memset(bp->page, 0, mp->pagesize);
+		}
+	}
+
+	/* Set the page number, pin the page. */
+	bp->pgno = pgno;
+	if (!(flags & MPOOL_IGNOREPIN))
+		bp->flags = MPOOL_PINNED;
+	bp->flags |= MPOOL_INUSE;
+
+	/*
+	 * Add the page to the head of the hash chain and the tail
+	 * of the lru chain.
+	 */
+	head = &mp->hqh[HASHKEY(bp->pgno)];
+	CIRCLEQ_INSERT_HEAD(head, bp, hq);
+	CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+	/* Run through the user's filter. */
+	if (mp->pgin != NULL)
+		(mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
+	return (bp->page);
+}
+
+/*
+ * mpool_put
+ *	Return a page.
+ */
+int
+mpool_put(mp, page, flags)
+	MPOOL *mp;
+	void *page;
+	u_int flags;
+{
+	BKT *bp;
+
+#ifdef STATISTICS
+	++mp->pageput;
+#endif
+	bp = (BKT *)((char *)page - sizeof(BKT));
+#ifdef DEBUG
+	if (!(bp->flags & MPOOL_PINNED)) {
+		(void)fprintf(stderr,
+		    "mpool_put: page %d not pinned\n", bp->pgno);
+		abort();
+	}
+#endif
+	bp->flags &= ~MPOOL_PINNED;
+	if (flags & MPOOL_DIRTY)
+		bp->flags |= flags & MPOOL_DIRTY;
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_close
+ *	Close the buffer pool.
+ */
+int
+mpool_close(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+
+	/* Free up any space allocated to the lru pages. */
+	while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) {
+		CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q);
+		free(bp);
+	}
+
+	/* Free the MPOOL cookie. */
+	free(mp);
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_sync
+ *	Sync the pool to disk.
+ */
+int
+mpool_sync(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+
+	/* Walk the lru chain, flushing any dirty pages to disk. */
+	for (bp = mp->lqh.cqh_first;
+	    bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
+		if (bp->flags & MPOOL_DIRTY &&
+		    mpool_write(mp, bp) == RET_ERROR)
+			return (RET_ERROR);
+
+	/* Sync the file descriptor. */
+	return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * mpool_bkt
+ *	Get a page from the cache (or create one).
+ */
+static BKT *
+mpool_bkt(mp)
+	MPOOL *mp;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	/* If under the max cached, always create a new page. */
+	if (mp->curcache < mp->maxcache)
+		goto new;
+
+	/*
+	 * If the cache is max'd out, walk the lru list for a buffer we
+	 * can flush.  If we find one, write it (if necessary) and take it
+	 * off any lists.  If we don't find anything we grow the cache anyway.
+	 * The cache never shrinks.
+	 */
+	for (bp = mp->lqh.cqh_first;
+	    bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
+		if (!(bp->flags & MPOOL_PINNED)) {
+			/* Flush if dirty. */
+			if (bp->flags & MPOOL_DIRTY &&
+			    mpool_write(mp, bp) == RET_ERROR)
+				return (NULL);
+#ifdef STATISTICS
+			++mp->pageflush;
+#endif
+			/* Remove from the hash and lru queues. */
+			head = &mp->hqh[HASHKEY(bp->pgno)];
+			CIRCLEQ_REMOVE(head, bp, hq);
+			CIRCLEQ_REMOVE(&mp->lqh, bp, q);
+#ifdef DEBUG
+			{ void *spage;
+				spage = bp->page;
+				memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+				bp->page = spage;
+			}
+#endif
+			bp->flags = 0;
+			return (bp);
+		}
+
+new:	if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
+		return (NULL);
+#ifdef STATISTICS
+	++mp->pagealloc;
+#endif
+#if defined(DEBUG) || defined(PURIFY) || 1
+	memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+#endif
+	bp->page = (char *)bp + sizeof(BKT);
+	bp->flags = 0;
+	++mp->curcache;
+	return (bp);
+}
+
+/*
+ * mpool_write
+ *	Write a page to disk.
+ */
+static int
+mpool_write(mp, bp)
+	MPOOL *mp;
+	BKT *bp;
+{
+	off_t off;
+
+#ifdef STATISTICS
+	++mp->pagewrite;
+#endif
+
+	/* Run through the user's filter. */
+	if (mp->pgout)
+		(mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
+
+	off = mp->pagesize * bp->pgno;
+	if (off / mp->pagesize != bp->pgno) {
+	    /* Run past the end of the file, or at least the part we
+	       can address without large-file support?  */
+	    errno = E2BIG;
+	    return RET_ERROR;
+	}
+	if (lseek(mp->fd, off, SEEK_SET) != off)
+		return (RET_ERROR);
+	if (write(mp->fd, bp->page, mp->pagesize) != mp->pagesize)
+		return (RET_ERROR);
+
+	bp->flags &= ~MPOOL_DIRTY;
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_look
+ *	Lookup a page in the cache.
+ */
+static BKT *
+mpool_look(mp, pgno)
+	MPOOL *mp;
+	db_pgno_t pgno;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	head = &mp->hqh[HASHKEY(pgno)];
+	for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next)
+		if ((bp->pgno == pgno) && (bp->flags & MPOOL_INUSE)) {
+#ifdef STATISTICS
+			++mp->cachehit;
+#endif
+			return (bp);
+		}
+#ifdef STATISTICS
+	++mp->cachemiss;
+#endif
+	return (NULL);
+}
+
+#ifdef STATISTICS
+/*
+ * mpool_stat
+ *	Print out cache statistics.
+ */
+void
+mpool_stat(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+	int cnt;
+	char *sep;
+
+	(void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
+	(void)fprintf(stderr,
+	    "page size %lu, cacheing %lu pages of %lu page max cache\n",
+	    mp->pagesize, mp->curcache, mp->maxcache);
+	(void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
+	    mp->pageput, mp->pageget, mp->pagenew);
+	(void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
+	    mp->pagealloc, mp->pageflush);
+	if (mp->cachehit + mp->cachemiss)
+		(void)fprintf(stderr,
+		    "%.0f%% cache hit rate (%lu hits, %lu misses)\n", 
+		    ((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
+		    * 100, mp->cachehit, mp->cachemiss);
+	(void)fprintf(stderr, "%lu page reads, %lu page writes\n",
+	    mp->pageread, mp->pagewrite);
+
+	sep = "";
+	cnt = 0;
+	for (bp = mp->lqh.cqh_first;
+	    bp != (void *)&mp->lqh; bp = bp->q.cqe_next) {
+		(void)fprintf(stderr, "%s%d", sep, bp->pgno);
+		if (bp->flags & MPOOL_DIRTY)
+			(void)fprintf(stderr, "d");
+		if (bp->flags & MPOOL_PINNED)
+			(void)fprintf(stderr, "P");
+		if (++cnt == 10) {
+			sep = "\n";
+			cnt = 0;
+		} else
+			sep = ", ";
+			
+	}
+	(void)fprintf(stderr, "\n");
+}
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.h
new file mode 100644
index 000000000..627ad5b36
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/mpool/mpool.h
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)mpool.h	8.4 (Berkeley) 11/2/95
+ */
+
+#include "db-queue.h"
+
+/*
+ * The memory pool scheme is a simple one.  Each in-memory page is referenced
+ * by a bucket which is threaded in up to two of three ways.  All active pages
+ * are threaded on a hash chain (hashed by page number) and an lru chain.
+ * Inactive pages are threaded on a free chain.  Each reference to a memory
+ * pool is handed an opaque MPOOL cookie which stores all of this information.
+ */
+#define	HASHSIZE	128
+#define	HASHKEY(pgno)	((pgno - 1) % HASHSIZE)
+
+/* The BKT structures are the elements of the queues. */
+typedef struct _bkt {
+	CIRCLEQ_ENTRY(_bkt) hq;		/* hash queue */
+	CIRCLEQ_ENTRY(_bkt) q;		/* lru queue */
+	void    *page;			/* page */
+	db_pgno_t   pgno;			/* page number */
+
+#define	MPOOL_DIRTY	0x01		/* page needs to be written */
+#define	MPOOL_PINNED	0x02		/* page is pinned into memory */
+#define	MPOOL_INUSE	0x04		/* page address is valid */
+	u_int8_t flags;			/* flags */
+} BKT;
+
+typedef struct MPOOL {
+	CIRCLEQ_HEAD(_lqh, _bkt) lqh;	/* lru queue head */
+					/* hash queue array */
+	CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE];
+	db_pgno_t	curcache;		/* current number of cached pages */
+	db_pgno_t	maxcache;		/* max number of cached pages */
+	db_pgno_t	npages;			/* number of pages in the file */
+	u_long	pagesize;		/* file page size */
+	int	fd;			/* file descriptor */
+					/* page in conversion routine */
+	void    (*pgin) __P((void *, db_pgno_t, void *));
+					/* page out conversion routine */
+	void    (*pgout) __P((void *, db_pgno_t, void *));
+	void	*pgcookie;		/* cookie for page in/out routines */
+#ifdef STATISTICS
+	u_long	cachehit;
+	u_long	cachemiss;
+	u_long	pagealloc;
+	u_long	pageflush;
+	u_long	pageget;
+	u_long	pagenew;
+	u_long	pageput;
+	u_long	pageread;
+	u_long	pagewrite;
+#endif
+} MPOOL;
+
+#define	MPOOL_IGNOREPIN	0x01		/* Ignore if the page is pinned. */
+#define	MPOOL_PAGE_REQUEST	0x01	/* Allocate a new page with a
+					   specific page number. */
+#define	MPOOL_PAGE_NEXT		0x02	/* Allocate a new page with the next
+					  page number. */
+
+#define mpool_open	kdb2_mpool_open
+#define mpool_filter	kdb2_mpool_filter
+#define mpool_new	kdb2_mpool_new
+#define mpool_get	kdb2_mpool_get
+#define mpool_delete	kdb2_mpool_delete
+#define mpool_put	kdb2_mpool_put
+#define mpool_sync	kdb2_mpool_sync
+#define mpool_close	kdb2_mpool_close
+#define mpool_stat	kdb2_mpool_stat
+
+__BEGIN_DECLS
+MPOOL	*mpool_open __P((void *, int, db_pgno_t, db_pgno_t));
+void	 mpool_filter __P((MPOOL *, void (*)(void *, db_pgno_t, void *),
+	    void (*)(void *, db_pgno_t, void *), void *));
+void	*mpool_new __P((MPOOL *, db_pgno_t *, u_int));
+void	*mpool_get __P((MPOOL *, db_pgno_t, u_int));
+int	 mpool_delete __P((MPOOL *, void *));
+int	 mpool_put __P((MPOOL *, void *, u_int));
+int	 mpool_sync __P((MPOOL *));
+int	 mpool_close __P((MPOOL *));
+#ifdef STATISTICS
+void	 mpool_stat __P((MPOOL *));
+#endif
+__END_DECLS
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.in
new file mode 100644
index 000000000..ba0697cb8
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.in
@@ -0,0 +1,13 @@
+thisconfigdir=./..
+myfulldir=plugins/kdb/db2/libdb2/recno
+mydir=recno
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+STLIBOBJS=	rec_close.o rec_delete.o rec_get.o rec_open.o rec_put.o \
+		rec_search.o rec_seq.o rec_utils.o
+
+LOCALINCLUDES=	-I. -I$(srcdir)/../include -I../include -I$(srcdir)/../mpool \
+		-I$(srcdir)/../db
+
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.inc b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.inc
new file mode 100644
index 000000000..e49e22552
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/Makefile.inc
@@ -0,0 +1,6 @@
+#       @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/db/recno
+
+SRCS+=	rec_close.c rec_delete.c rec_get.c rec_open.c rec_put.c rec_search.c \
+	rec_seq.c rec_utils.c
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/extern.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/extern.h
new file mode 100644
index 000000000..98e382c37
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/extern.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)extern.h	8.3 (Berkeley) 6/4/94
+ */
+
+#include "../btree/extern.h"
+
+#define __rec_close	__kdb2_rec_close
+#define __rec_delete	__kdb2_rec_delete
+#define __rec_dleaf	__kdb2_rec_dleaf
+#define __rec_fd	__kdb2_rec_fd
+#define __rec_fmap	__kdb2_rec_fmap
+#define __rec_fout	__kdb2_rec_fout
+#define __rec_fpipe	__kdb2_rec_fpipe
+#define __rec_get	__kdb2_rec_get
+#define __rec_iput	__kdb2_rec_iput
+#define __rec_put	__kdb2_rec_put
+#define __rec_ret	__kdb2_rec_ret
+#define __rec_search	__kdb2_rec_search
+#define __rec_seq	__kdb2_rec_seq
+#define __rec_sync	__kdb2_rec_sync
+#define __rec_vmap	__kdb2_rec_vmap
+#define __rec_vout	__kdb2_rec_vout
+#define __rec_vpipe	__kdb2_rec_vpipe
+
+int	 __rec_close __P((DB *));
+int	 __rec_delete __P((const DB *, const DBT *, u_int));
+int	 __rec_dleaf __P((BTREE *, PAGE *, u_int32_t));
+int	 __rec_fd __P((const DB *));
+int	 __rec_fmap __P((BTREE *, recno_t));
+int	 __rec_fout __P((BTREE *));
+int	 __rec_fpipe __P((BTREE *, recno_t));
+int	 __rec_get __P((const DB *, const DBT *, DBT *, u_int));
+int	 __rec_iput __P((BTREE *, recno_t, const DBT *, u_int));
+int	 __rec_put __P((const DB *dbp, DBT *, const DBT *, u_int));
+int	 __rec_ret __P((BTREE *, EPG *, recno_t, DBT *, DBT *));
+EPG	*__rec_search __P((BTREE *, recno_t, enum SRCHOP));
+int	 __rec_seq __P((const DB *, DBT *, DBT *, u_int));
+int	 __rec_sync __P((const DB *, u_int));
+int	 __rec_vmap __P((BTREE *, recno_t));
+int	 __rec_vout __P((BTREE *));
+int	 __rec_vpipe __P((BTREE *, recno_t));
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_close.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_close.c
new file mode 100644
index 000000000..ed3da6ea4
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_close.c
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_close.c	8.9 (Berkeley) 11/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#ifdef RECNO_USE_MMAP
+#include <sys/mman.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+/*
+ * __REC_CLOSE -- Close a recno tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_close(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	if (__rec_sync(dbp, 0) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Committed to closing. */
+	status = RET_SUCCESS;
+#ifdef	RECNO_USE_MMAP
+	if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
+		status = RET_ERROR;
+#endif
+
+	if (!F_ISSET(t, R_INMEM)) {
+		if (F_ISSET(t, R_CLOSEFP)) {
+			if (fclose(t->bt_rfp))
+				status = RET_ERROR;
+		} else
+			if (close(t->bt_rfd))
+				status = RET_ERROR;
+	}
+
+	if (__bt_close(dbp) == RET_ERROR)
+		status = RET_ERROR;
+
+	return (status);
+}
+
+/*
+ * __REC_SYNC -- sync the recno tree to disk.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_sync(dbp, flags)
+	const DB *dbp;
+	u_int flags;
+{
+	struct iovec iov[2];
+	BTREE *t;
+	DBT data, key;
+	off_t off;
+	recno_t scursor, trec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	if (flags == R_RECNOSYNC)
+		return (__bt_sync(dbp, 0));
+
+	if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
+		return (RET_SUCCESS);
+
+	/* Read any remaining records into the tree. */
+	if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Rewind the file descriptor. */
+	if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
+		return (RET_ERROR);
+
+	/* Save the cursor. */
+	scursor = t->bt_cursor.rcursor;
+
+	key.size = sizeof(recno_t);
+	key.data = &trec;
+
+	if (F_ISSET(t, R_FIXLEN)) {
+		/*
+		 * We assume that fixed length records are all fixed length.
+		 * Any that aren't are either EINVAL'd or corrected by the
+		 * record put code.
+		 */
+		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+		while (status == RET_SUCCESS) {
+			if (write(t->bt_rfd, data.data, data.size) != data.size)
+				return (RET_ERROR);
+			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+		}
+	} else {
+		iov[1].iov_base = &t->bt_bval;
+		iov[1].iov_len = 1;
+
+		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+		while (status == RET_SUCCESS) {
+			iov[0].iov_base = data.data;
+			iov[0].iov_len = data.size;
+			if (writev(t->bt_rfd, iov, 2) != data.size + 1)
+				return (RET_ERROR);
+			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+		}
+	}
+
+	/* Restore the cursor. */
+	t->bt_cursor.rcursor = scursor;
+
+	if (status == RET_ERROR)
+		return (RET_ERROR);
+	if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
+		return (RET_ERROR);
+	if (ftruncate(t->bt_rfd, off))
+		return (RET_ERROR);
+	F_CLR(t, R_MODIFIED);
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_delete.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_delete.c
new file mode 100644
index 000000000..b69c9ad74
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_delete.c
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_delete.c	8.7 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+static int rec_rdelete __P((BTREE *, recno_t));
+
+/*
+ * __REC_DELETE -- Delete the item(s) referenced by a key.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to delete
+ *	flags:	R_CURSOR if deleting what the cursor references
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_delete(dbp, key, flags)
+	const DB *dbp;
+	const DBT *key;
+	u_int flags;
+{
+	BTREE *t;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	switch(flags) {
+	case 0:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		if (nrec > t->bt_nrecs)
+			return (RET_SPECIAL);
+		--nrec;
+		status = rec_rdelete(t, nrec);
+		break;
+	case R_CURSOR:
+		if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+			goto einval;
+		if (t->bt_nrecs == 0)
+			return (RET_SPECIAL);
+		status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
+		if (status == RET_SUCCESS)
+			--t->bt_cursor.rcursor;
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (status == RET_SUCCESS)
+		F_SET(t, B_MODIFIED | R_MODIFIED);
+	return (status);
+}
+
+/*
+ * REC_RDELETE -- Delete the data matching the specified key.
+ *
+ * Parameters:
+ *	tree:	tree
+ *	nrec:	record to delete
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+rec_rdelete(t, nrec)
+	BTREE *t;
+	recno_t nrec;
+{
+	EPG *e;
+	PAGE *h;
+	int status;
+
+	/* Find the record; __rec_search pins the page. */
+	if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
+		return (RET_ERROR);
+
+	/* Delete the record. */
+	h = e->page;
+	status = __rec_dleaf(t, h, e->index);
+	if (status != RET_SUCCESS) {
+		mpool_put(t->bt_mp, h, 0);
+		return (status);
+	}
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_DLEAF -- Delete a single record from a recno leaf page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	idx:	index on current page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_dleaf(t, h, idx)
+	BTREE *t;
+	PAGE *h;
+	u_int32_t idx;
+{
+	RLEAF *rl;
+	indx_t *ip, cnt, offset;
+	u_int32_t nbytes;
+	char *from;
+	void *to;
+
+	/*
+	 * Delete a record from a recno leaf page.  Internal records are never
+	 * deleted from internal pages, regardless of the records that caused
+	 * them to be added being deleted.  Pages made empty by deletion are
+	 * not reclaimed.  They are, however, made available for reuse.
+	 *
+	 * Pack the remaining entries at the end of the page, shift the indices
+	 * down, overwriting the deleted record and its index.  If the record
+	 * uses overflow pages, make them available for reuse.
+	 */
+	to = rl = GETRLEAF(h, idx);
+	if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
+		return (RET_ERROR);
+	nbytes = NRLEAF(rl);
+
+	/*
+	 * Compress the key/data pairs.  Compress and adjust the [BR]LEAF
+	 * offsets.  Reset the headers.
+	 */
+	from = (char *)h + h->upper;
+	memmove(from + nbytes, from, (char *)to - from);
+	h->upper += nbytes;
+
+	offset = h->linp[idx];
+	for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip)
+		if (ip[0] < offset)
+			ip[0] += nbytes;
+	for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
+		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+	h->lower -= sizeof(indx_t);
+	--t->bt_nrecs;
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_get.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_get.c
new file mode 100644
index 000000000..230b2d4f5
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_get.c
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_get.c	8.9 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+/*
+ * __REC_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to find
+ *	data:	data to return
+ *	flag:	currently unused
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_get(dbp, key, data, flags)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Get currently doesn't take any flags, and keys of 0 are illegal. */
+	if (flags || (nrec = *(recno_t *)key->data) == 0) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * If we haven't seen this record yet, try to find it in the
+	 * original file.
+	 */
+	if (nrec > t->bt_nrecs) {
+		if (F_ISSET(t, R_EOF | R_INMEM))
+			return (RET_SPECIAL);
+		if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+			return (status);
+	}
+
+	--nrec;
+	if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	status = __rec_ret(t, e, 0, NULL, data);
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
+
+/*
+ * __REC_FPIPE -- Get fixed length records from a pipe.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fpipe(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	size_t len;
+	int ch;
+	u_char *p;
+
+	if (t->bt_rdata.size < t->bt_reclen) {
+		t->bt_rdata.data = t->bt_rdata.data == NULL ?
+		    malloc(t->bt_reclen) :
+		    realloc(t->bt_rdata.data, t->bt_reclen);
+		if (t->bt_rdata.data == NULL)
+			return (RET_ERROR);
+		t->bt_rdata.size = t->bt_reclen;
+	}
+	data.data = t->bt_rdata.data;
+	data.size = t->bt_reclen;
+
+	for (nrec = t->bt_nrecs; nrec < top;) {
+		len = t->bt_reclen;
+		for (p = t->bt_rdata.data;; *p++ = ch)
+			if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
+				if (ch != EOF)
+					*p = ch;
+				if (len != 0)
+					memset(p, t->bt_bval, len);
+				if (__rec_iput(t,
+				    nrec, &data, 0) != RET_SUCCESS)
+					return (RET_ERROR);
+				++nrec;
+				break;
+			}
+		if (ch == EOF)
+			break;
+	}
+	if (nrec < top) {
+		F_SET(t, R_EOF);
+		return (RET_SPECIAL);
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VPIPE -- Get variable length records from a pipe.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vpipe(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	indx_t len;
+	size_t sz;
+	int bval, ch;
+	u_char *p;
+
+	bval = t->bt_bval;
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		for (p = t->bt_rdata.data,
+		    sz = t->bt_rdata.size;; *p++ = ch, --sz) {
+			if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
+				data.data = t->bt_rdata.data;
+				data.size = p - (u_char *)t->bt_rdata.data;
+				if (ch == EOF && data.size == 0)
+					break;
+				if (__rec_iput(t, nrec, &data, 0)
+				    != RET_SUCCESS)
+					return (RET_ERROR);
+				break;
+			}
+			if (sz == 0) {
+				len = p - (u_char *)t->bt_rdata.data;
+				t->bt_rdata.size += (sz = 256);
+				t->bt_rdata.data = t->bt_rdata.data == NULL ?
+				    malloc(t->bt_rdata.size) :
+				    realloc(t->bt_rdata.data, t->bt_rdata.size);
+				if (t->bt_rdata.data == NULL)
+					return (RET_ERROR);
+				p = (u_char *)t->bt_rdata.data + len;
+			}
+		}
+		if (ch == EOF)
+			break;
+	}
+	if (nrec < top) {
+		F_SET(t, R_EOF);
+		return (RET_SPECIAL);
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_FMAP -- Get fixed length records from a file.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fmap(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	u_char *sp, *ep, *p;
+	size_t len;
+
+	if (t->bt_rdata.size < t->bt_reclen) {
+		t->bt_rdata.data = t->bt_rdata.data == NULL ?
+		    malloc(t->bt_reclen) :
+		    realloc(t->bt_rdata.data, t->bt_reclen);
+		if (t->bt_rdata.data == NULL)
+			return (RET_ERROR);
+		t->bt_rdata.size = t->bt_reclen;
+	}
+	data.data = t->bt_rdata.data;
+	data.size = t->bt_reclen;
+
+	sp = (u_char *)t->bt_cmap;
+	ep = (u_char *)t->bt_emap;
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		if (sp >= ep) {
+			F_SET(t, R_EOF);
+			return (RET_SPECIAL);
+		}
+		len = t->bt_reclen;
+		for (p = t->bt_rdata.data;
+		    sp < ep && len > 0; *p++ = *sp++, --len);
+		if (len != 0)
+			memset(p, t->bt_bval, len);
+		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+			return (RET_ERROR);
+	}
+	t->bt_cmap = (caddr_t)sp;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VMAP -- Get variable length records from a file.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vmap(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	u_char *sp, *ep;
+	recno_t nrec;
+	int bval;
+
+	sp = (u_char *)t->bt_cmap;
+	ep = (u_char *)t->bt_emap;
+	bval = t->bt_bval;
+
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		if (sp >= ep) {
+			F_SET(t, R_EOF);
+			return (RET_SPECIAL);
+		}
+		for (data.data = sp; sp < ep && *sp != bval; ++sp);
+		data.size = sp - (u_char *)data.data;
+		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+			return (RET_ERROR);
+		++sp;
+	}
+	t->bt_cmap = (caddr_t)sp;
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_open.c
new file mode 100644
index 000000000..f18a1cb02
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_open.c
@@ -0,0 +1,243 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_open.c	8.12 (Berkeley) 11/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#ifdef RECNO_USE_MMAP
+#include <sys/mman.h>
+#endif
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+DB *
+__rec_open(fname, flags, mode, openinfo, dflags)
+	const char *fname;
+	int flags, mode, dflags;
+	const RECNOINFO *openinfo;
+{
+	BTREE *t;
+	BTREEINFO btopeninfo;
+	DB *dbp;
+	PAGE *h;
+	struct stat sb;
+	int rfd, sverrno;
+
+	/* Open the user's file -- if this fails, we're done. */
+	if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0)
+		return (NULL);
+
+	/* Create a btree in memory (backed by disk). */
+	dbp = NULL;
+	if (openinfo) {
+		if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
+			goto einval;
+		btopeninfo.flags = 0;
+		btopeninfo.cachesize = openinfo->cachesize;
+		btopeninfo.maxkeypage = 0;
+		btopeninfo.minkeypage = 0;
+		btopeninfo.psize = openinfo->psize;
+		btopeninfo.compare = NULL;
+		btopeninfo.prefix = NULL;
+		btopeninfo.lorder = openinfo->lorder;
+		dbp = __bt_open(openinfo->bfname,
+		    O_RDWR | O_BINARY, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
+	} else
+		dbp = __bt_open(NULL, O_RDWR | O_BINARY, S_IRUSR | S_IWUSR, NULL, dflags);
+	if (dbp == NULL)
+		goto err;
+
+	/*
+	 * Some fields in the tree structure are recno specific.  Fill them
+	 * in and make the btree structure look like a recno structure.  We
+	 * don't change the bt_ovflsize value, it's close enough and slightly
+	 * bigger.
+	 */
+	t = dbp->internal;
+	if (openinfo) {
+		if (openinfo->flags & R_FIXEDLEN) {
+			F_SET(t, R_FIXLEN);
+			t->bt_reclen = openinfo->reclen;
+			if (t->bt_reclen == 0)
+				goto einval;
+		}
+		t->bt_bval = openinfo->bval;
+	} else
+		t->bt_bval = '\n';
+
+	F_SET(t, R_RECNO);
+	if (fname == NULL)
+		F_SET(t, R_EOF | R_INMEM);
+	else
+		t->bt_rfd = rfd;
+
+	if (fname != NULL) {
+		/*
+		 * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
+		 * Unfortunately, that's not portable, so we use lseek
+		 * and check the errno values.
+		 */
+		errno = 0;
+		if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
+			switch (flags & O_ACCMODE) {
+			case O_RDONLY:
+				F_SET(t, R_RDONLY);
+				break;
+			default:
+				goto einval;
+			}
+slow:			if ((t->bt_rfp = fdopen(rfd, "rb")) == NULL)
+				goto err;
+			F_SET(t, R_CLOSEFP);
+			t->bt_irec =
+			    F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
+		} else {
+			switch (flags & O_ACCMODE) {
+			case O_RDONLY:
+				F_SET(t, R_RDONLY);
+				break;
+			case O_RDWR:
+				break;
+			default:
+				goto einval;
+			}
+
+			if (fstat(rfd, &sb))
+				goto err;
+			/*
+			 * Kluge -- we'd like to test to see if the file is too
+			 * big to mmap.  Since, we don't know what size or type
+			 * off_t's or size_t's are, what the largest unsigned
+			 * integral type is, or what random insanity the local
+			 * C compiler will perpetrate, doing the comparison in
+			 * a portable way is flatly impossible.  Hope that mmap
+			 * fails if the file is too large.
+			 */
+			if (sb.st_size == 0)
+				F_SET(t, R_EOF);
+			else {
+#ifdef RECNO_USE_MMAP
+				/*
+				 * XXX
+				 * Mmap doesn't work correctly on many current
+				 * systems.  In particular, it can fail subtly,
+				 * with cache coherency problems.  Don't use it
+				 * for now.
+				 */
+				t->bt_msize = sb.st_size;
+				if ((t->bt_smap = mmap(NULL, t->bt_msize,
+				    PROT_READ, MAP_PRIVATE, rfd,
+				    (off_t)0)) == (caddr_t)-1)
+					goto slow;
+				t->bt_cmap = t->bt_smap;
+				t->bt_emap = t->bt_smap + sb.st_size;
+				t->bt_irec = F_ISSET(t, R_FIXLEN) ?
+				    __rec_fmap : __rec_vmap;
+				F_SET(t, R_MEMMAPPED);
+#else
+				goto slow;
+#endif
+			}
+		}
+	}
+
+	/* Use the recno routines. */
+	dbp->close = __rec_close;
+	dbp->del = __rec_delete;
+	dbp->fd = __rec_fd;
+	dbp->get = __rec_get;
+	dbp->put = __rec_put;
+	dbp->seq = __rec_seq;
+	dbp->sync = __rec_sync;
+
+	/* If the root page was created, reset the flags. */
+	if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
+		goto err;
+	if ((h->flags & P_TYPE) == P_BLEAF) {
+		F_CLR(h, P_TYPE);
+		F_SET(h, P_RLEAF);
+		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	} else
+		mpool_put(t->bt_mp, h, 0);
+
+	if (openinfo && openinfo->flags & R_SNAPSHOT &&
+	    !F_ISSET(t, R_EOF | R_INMEM) &&
+	    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+                goto err;
+	return (dbp);
+
+einval:	errno = EINVAL;
+err:	sverrno = errno;
+	if (dbp != NULL)
+		(void)__bt_close(dbp);
+	if (fname != NULL)
+		(void)close(rfd);
+	errno = sverrno;
+	return (NULL);
+}
+
+int
+__rec_fd(dbp)
+	const DB *dbp;
+{
+	BTREE *t;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* In-memory database can't have a file descriptor. */
+	if (F_ISSET(t, R_INMEM)) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (t->bt_rfd);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_put.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_put.c
new file mode 100644
index 000000000..e7fa75882
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_put.c
@@ -0,0 +1,280 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_put.c	8.7 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+/*
+ * __REC_PUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key
+ *	data:	data
+ *	flag:	R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
+ *	already in the tree and R_NOOVERWRITE specified.
+ */
+int
+__rec_put(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	DBT fdata, tdata;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/*
+	 * If using fixed-length records, and the record is long, return
+	 * EINVAL.  If it's short, pad it out.  Use the record data return
+	 * memory, it's only short-term.
+	 */
+	if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) {
+		if (data->size > t->bt_reclen)
+			goto einval;
+
+		if (t->bt_rdata.size < t->bt_reclen) {
+			t->bt_rdata.data = t->bt_rdata.data == NULL ?
+			    malloc(t->bt_reclen) :
+			    realloc(t->bt_rdata.data, t->bt_reclen);
+			if (t->bt_rdata.data == NULL)
+				return (RET_ERROR);
+			t->bt_rdata.size = t->bt_reclen;
+		}
+		memmove(t->bt_rdata.data, data->data, data->size);
+		memset((char *)t->bt_rdata.data + data->size,
+		    t->bt_bval, t->bt_reclen - data->size);
+		fdata.data = t->bt_rdata.data;
+		fdata.size = t->bt_reclen;
+	} else {
+		fdata.data = data->data;
+		fdata.size = data->size;
+	}
+
+	switch (flags) {
+	case R_CURSOR:
+		if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+			goto einval;
+		nrec = t->bt_cursor.rcursor;
+		break;
+	case R_SETCURSOR:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_IAFTER:
+		if ((nrec = *(recno_t *)key->data) == 0) {
+			nrec = 1;
+			flags = R_IBEFORE;
+		}
+		break;
+	case 0:
+	case R_IBEFORE:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_NOOVERWRITE:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		if (nrec <= t->bt_nrecs)
+			return (RET_SPECIAL);
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * Make sure that records up to and including the put record are
+	 * already in the database.  If skipping records, create empty ones.
+	 */
+	if (nrec > t->bt_nrecs) {
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    t->bt_irec(t, nrec) == RET_ERROR)
+			return (RET_ERROR);
+		if (nrec > t->bt_nrecs + 1) {
+			if (F_ISSET(t, R_FIXLEN)) {
+				if ((tdata.data =
+				    (void *)malloc(t->bt_reclen)) == NULL)
+					return (RET_ERROR);
+				tdata.size = t->bt_reclen;
+				memset(tdata.data, t->bt_bval, tdata.size);
+			} else {
+				tdata.data = NULL;
+				tdata.size = 0;
+			}
+			while (nrec > t->bt_nrecs + 1)
+				if (__rec_iput(t,
+				    t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
+					return (RET_ERROR);
+			if (F_ISSET(t, R_FIXLEN))
+				free(tdata.data);
+		}
+	}
+
+	if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
+		return (status);
+
+	if (flags == R_SETCURSOR)
+		t->bt_cursor.rcursor = nrec;
+	
+	F_SET(t, R_MODIFIED);
+	return (__rec_ret(t, NULL, nrec, key, NULL));
+}
+
+/*
+ * __REC_IPUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	nrec:	record number
+ *	data:	data
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_iput(t, nrec, data, flags)
+	BTREE *t;
+	recno_t nrec;
+	const DBT *data;
+	u_int flags;
+{
+	DBT tdata;
+	EPG *e;
+	PAGE *h;
+	indx_t idx, nxtindex;
+	db_pgno_t pg;
+	u_int32_t nbytes;
+	int dflags, status;
+	char *dest, db[NOVFLSIZE];
+
+	/*
+	 * If the data won't fit on a page, store it on indirect pages.
+	 *
+	 * XXX
+	 * If the insert fails later on, these pages aren't recovered.
+	 */
+	if (data->size > t->bt_ovflsize) {
+		if (__ovfl_put(t, data, &pg) == RET_ERROR)
+			return (RET_ERROR);
+		tdata.data = db;
+		tdata.size = NOVFLSIZE;
+		*(db_pgno_t *)db = pg;
+		*(u_int32_t *)(db + sizeof(db_pgno_t)) = data->size;
+		dflags = P_BIGDATA;
+		data = &tdata;
+	} else
+		dflags = 0;
+
+	/* __rec_search pins the returned page. */
+	if ((e = __rec_search(t, nrec,
+	    nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
+	    SINSERT : SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	h = e->page;
+	idx = e->index;
+
+	/*
+	 * Add the specified key/data pair to the tree.  The R_IAFTER and
+	 * R_IBEFORE flags insert the key after/before the specified key.
+	 *
+	 * Pages are split as required.
+	 */
+	switch (flags) {
+	case R_IAFTER:
+		++idx;
+		break;
+	case R_IBEFORE:
+		break;
+	default:
+		if (nrec < t->bt_nrecs &&
+		    __rec_dleaf(t, h, idx) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		break;
+	}
+
+	/*
+	 * If not enough room, split the page.  The split code will insert
+	 * the key and data and unpin the current page.  If inserting into
+	 * the offset array, shift the pointers up.
+	 */
+	nbytes = NRLEAFDBT(data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+		status = __bt_split(t, h, NULL, data, dflags, nbytes, idx);
+		if (status == RET_SUCCESS)
+			++t->bt_nrecs;
+		return (status);
+	}
+
+	if (idx < (nxtindex = NEXTINDEX(h)))
+		memmove(h->linp + idx + 1, h->linp + idx,
+		    (nxtindex - idx) * sizeof(indx_t));
+	h->lower += sizeof(indx_t);
+
+	h->linp[idx] = h->upper -= nbytes;
+	dest = (char *)h + h->upper;
+	WR_RLEAF(dest, data, dflags);
+
+	++t->bt_nrecs;
+	F_SET(t, B_MODIFIED);
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_search.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_search.c
new file mode 100644
index 000000000..a328f1be0
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_search.c
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_search.c	8.4 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+/*
+ * __REC_SEARCH -- Search a btree for a key.
+ *
+ * Parameters:
+ *	t:	tree to search
+ *	recno:	key to find
+ *	op: 	search operation
+ *
+ * Returns:
+ *	EPG for matching record, if any, or the EPG for the location of the
+ *	key, if it were inserted into the tree.
+ *
+ * Returns:
+ *	The EPG for matching record, if any, or the EPG for the location
+ *	of the key, if it were inserted into the tree, is entered into
+ *	the bt_cur field of the tree.  A pointer to the field is returned.
+ */
+EPG *
+__rec_search(t, recno, op)
+	BTREE *t;
+	recno_t recno;
+	enum SRCHOP op;
+{
+	register indx_t idx;
+	register PAGE *h;
+	EPGNO *parent;
+	RINTERNAL *r;
+	db_pgno_t pg;
+	indx_t top;
+	recno_t total;
+	int sverrno;
+
+	BT_CLR(t);
+	for (pg = P_ROOT, total = 0;;) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			goto err;
+		if (h->flags & P_RLEAF) {
+			t->bt_cur.page = h;
+			t->bt_cur.index = recno - total;
+			return (&t->bt_cur);
+		}
+		for (idx = 0, top = NEXTINDEX(h);;) {
+			r = GETRINTERNAL(h, idx);
+			if (++idx == top || total + r->nrecs > recno)
+				break;
+			total += r->nrecs;
+		}
+
+		BT_PUSH(t, pg, idx - 1);
+		
+		pg = r->pgno;
+		switch (op) {
+		case SDELETE:
+			--GETRINTERNAL(h, (idx - 1))->nrecs;
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		case SINSERT:
+			++GETRINTERNAL(h, (idx - 1))->nrecs;
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		case SEARCH:
+			mpool_put(t->bt_mp, h, 0);
+			break;
+		}
+
+	}
+	/* Try and recover the tree. */
+err:	sverrno = errno;
+	if (op != SEARCH)
+		while  ((parent = BT_POP(t)) != NULL) {
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				break;
+			if (op == SINSERT)
+				--GETRINTERNAL(h, parent->index)->nrecs;
+			else
+				++GETRINTERNAL(h, parent->index)->nrecs;
+                        mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+                }
+	errno = sverrno;
+	return (NULL);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_seq.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_seq.c
new file mode 100644
index 000000000..1edaa998e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_seq.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_seq.c	8.3 (Berkeley) 7/14/94";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+/*
+ * __REC_SEQ -- Recno sequential scan interface.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key for positioning and return value
+ *	data:	data return value
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__rec_seq(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	switch(flags) {
+	case R_CURSOR:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_NEXT:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			nrec = t->bt_cursor.rcursor + 1;
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_FIRST:
+		nrec = 1;
+		break;
+	case R_PREV:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			if ((nrec = t->bt_cursor.rcursor - 1) == 0)
+				return (RET_SPECIAL);
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_LAST:
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+			return (RET_ERROR);
+		nrec = t->bt_nrecs;
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+	
+	if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+			return (status);
+		if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
+			return (RET_SPECIAL);
+	}
+
+	if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	F_SET(&t->bt_cursor, CURS_INIT);
+	t->bt_cursor.rcursor = nrec;
+
+	status = __rec_ret(t, e, nrec, key, data);
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_utils.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_utils.c
new file mode 100644
index 000000000..f757a724f
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/rec_utils.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_utils.c	8.6 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db-int.h"
+#include "recno.h"
+
+/*
+ * __rec_ret --
+ *	Build return data.
+ *
+ * Parameters:
+ *	t:	tree
+ *	e:	key/data pair to be returned
+ *   nrec:	record number
+ *    key:	user's key structure
+ *	data:	user's data structure
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_ret(t, e, nrec, key, data)
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	DBT *key, *data;
+{
+	RLEAF *rl;
+	void *p;
+
+	if (key == NULL)
+		goto dataonly;
+
+	/* We have to copy the key, it's not on the page. */
+	if (sizeof(recno_t) > t->bt_rkey.size) {
+		p = (void *)(t->bt_rkey.data == NULL ?
+		    malloc(sizeof(recno_t)) :
+		    realloc(t->bt_rkey.data, sizeof(recno_t)));
+		if (p == NULL)
+			return (RET_ERROR);
+		t->bt_rkey.data = p;
+		t->bt_rkey.size = sizeof(recno_t);
+	}
+	memmove(t->bt_rkey.data, &nrec, sizeof(recno_t));
+	key->size = sizeof(recno_t);
+	key->data = t->bt_rkey.data;
+
+dataonly:
+	if (data == NULL)
+		return (RET_SUCCESS);
+
+	/*
+	 * We must copy big keys/data to make them contigous.  Otherwise,
+	 * leave the page pinned and don't copy unless the user specified
+	 * concurrent access.
+	 */
+	rl = GETRLEAF(e->page, e->index);
+	if (rl->flags & P_BIGDATA) {
+		if (__ovfl_get(t, rl->bytes,
+		    &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
+			return (RET_ERROR);
+		data->data = t->bt_rdata.data;
+	} else if (F_ISSET(t, B_DB_LOCK)) {
+		/* Use +1 in case the first record retrieved is 0 length. */
+		if (rl->dsize + 1 > t->bt_rdata.size) {
+			p = (void *)(t->bt_rdata.data == NULL ?
+			    malloc(rl->dsize + 1) :
+			    realloc(t->bt_rdata.data, rl->dsize + 1));
+			if (p == NULL)
+				return (RET_ERROR);
+			t->bt_rdata.data = p;
+			t->bt_rdata.size = rl->dsize + 1;
+		}
+		memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
+		data->size = rl->dsize;
+		data->data = t->bt_rdata.data;
+	} else {
+		data->size = rl->dsize;
+		data->data = rl->bytes;
+	}
+	return (RET_SUCCESS);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/recno.h b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/recno.h
new file mode 100644
index 000000000..bec772c2f
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/recno/recno.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)recno.h	8.1 (Berkeley) 6/4/93
+ */
+
+enum SRCHOP { SDELETE, SINSERT, SEARCH};	/* Rec_search operation. */
+
+#include "../btree/btree.h"
+#include "extern.h"
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/Makefile.in b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/Makefile.in
new file mode 100644
index 000000000..cd7538dcd
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/Makefile.in
@@ -0,0 +1,36 @@
+thisconfigdir=./..
+myfulldir=plugins/kdb/db2/libdb2/test
+mydir=test
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+
+FCTSH = @FCTSH@
+TMPDIR=.
+
+LOCALINCLUDES=	-I. -I$(srcdir)/../include -I../include -I$(srcdir)/../mpool \
+		-I$(srcdir)/../btree -I$(srcdir)/../hash -I$(srcdir)/../db
+
+PROG_LIBPATH=-L..
+PROG_RPATH=$(KRB5_LIBDIR)
+
+KRB5_RUN_ENV= @KRB5_RUN_ENV@
+
+DB_LIB		= -ldb
+DB_DEPLIB	= ../libdb$(DEPLIBEXT)
+
+all::
+
+dbtest: dbtest.o $(DB_DEPLIB)
+	$(CC_LINK) -o $@ dbtest.o $(STRERROR_OBJ) $(DB_LIB)
+
+check:: dbtest
+	$(KRB5_RUN_ENV) srcdir=$(srcdir) TMPDIR=$(TMPDIR) $(VALGRIND) $(FCTSH) $(srcdir)/run.test
+
+bttest.o: $(srcdir)/btree.tests/main.c
+	$(CC) $(ALL_CFLAGS) -c $(srcdir)/btree.tests/main.c -o $@
+
+bttest: bttest.o $(DB_DEPLIB)
+	$(CC_LINK) -o $@ bttest.o $(STRERROR_OBJ) $(DB_LIB)
+
+clean-unix::
+	$(RM) dbtest.o dbtest __dbtest
+	$(RM) bttest.o bttest
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/README b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/README
new file mode 100644
index 000000000..0c0cd13d8
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/README
@@ -0,0 +1,74 @@
+#	@(#)README	8.8 (Berkeley) 7/31/94
+
+To build this portably, try something like:
+
+    make PORTDIR="../PORT/MACH"
+
+where MACH is the machine, i.e. "sunos.4.1.1".
+
+To run the tests, enter "sh run.test".  If your system dictionary isn't
+in /usr/share/dict/words, edit run.test to reflect the correct place.
+
+Fairly large files (the command files) are built in this directory during
+the test runs, and even larger files (the database files) are created in
+"/var/tmp".  If the latter directory doesn't exist, set the environmental
+variable TMPDIR to a directory where the files can be built.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+The script file consists of lines with an initial character which is
+the command for that line, or an initial character indicating a key
+or data entry for a previous command.
+
+Legal command characters are as follows:
+
+c: compare a record
+	+ must be followed by [kK][dD]; the data value in the database
+	  associated with the specified key is compared to the specified
+	  data value.
+e: echo a string
+	+ writes out the rest of the line into the output file; if the
+	  last character is not a carriage-return, a newline is appended.
+f: set the flags for the next command
+	+ no value zero's the flags
+g: do a get command
+	+ must be followed by [kK]
+	+ writes out the retrieved data DBT.
+o [r]: dump [reverse]
+	+ dump the database out, if 'r' is set, in reverse order.
+p: do a put command
+	+ must be followed by [kK][dD]
+r: do a del command
+	+ must be followed by [kK] unless R_CURSOR flag set.
+S: sync the database
+s: do a seq command
+	+ must be followed by [kK] if R_CURSOR flag set.
+	+ writes out the retrieved data DBT.
+
+Legal key/data characters are as follows:
+
+D [file]: data file
+	+ set the current data value to the contents of the file
+d [data]:
+	+ set the current key value to the contents of the line.
+K [file]: key file
+	+ set the current key value to the contents of the file
+k [data]:
+	+ set the current key value to the contents of the line.
+
+Blank lines, lines with leading white space, and lines with leading
+hash marks (#) are ignored.
+
+Options to dbtest are as follows:
+
+	-d: Set the DB_LOCK flag.
+	-f: Use the file argument as the database file.
+	-i: Use the rest of the argument to set elements in the info
+	    structure.  If the type is btree, then "-i cachesize=10240"
+	    will set BTREEINFO.cachesize to 10240.
+	-o: The rest of the argument is the output file instead of
+	    using stdout.
+	-s: Don't delete the database file before opening it, i.e.
+	    use the database file from a previous run.
+
+Dbtest requires two arguments, the type of access "hash", "recno"
+or "btree", and the script name or "-" to indicate stdin.
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data
new file mode 100644
index 000000000..37a518537
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data
@@ -0,0 +1,8 @@
+A000027875A000135891
+A000059165A000130168
+A000060256A000133490
+A040025906A000136770
+A040027881A000135829
+A040028611A000137873
+A040032413A000056974
+A040050163A000126233
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox
new file mode 100644
index 000000000..9d5d49d07
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox
@@ -0,0 +1,399 @@
+From wiggans@aipl.arsusda.gov Mon Sep 12 11:05:58 1994
+Received: from vangogh.CS.Berkeley.EDU by python.bostic.com (8.6.9.Beta4/2.6)
+	id OAA16853; Mon, 12 Sep 1994 14:05:42 -0400
+From: wiggans@aipl.arsusda.gov
+Received: from hofmann.CS.Berkeley.EDU (hofmann.CS.Berkeley.EDU [128.32.34.35]) by vangogh.CS.Berkeley.EDU (8.7.Alpha.1/8.6.9.Beta0) with ESMTP id LAA15825 for <bostic@vangogh.CS.Berkeley.EDU>; Mon, 12 Sep 1994 11:05:20 -0700 (PDT)
+Received: from uu7.psi.com (uu7.psi.com [38.145.204.6]) by hofmann.CS.Berkeley.EDU (8.6.9/8.6.6.Beta11) with SMTP id LAA25681 for <bostic@cs.berkeley.edu>; Mon, 12 Sep 1994 11:05:44 -0700
+Received: from AIPL.ARSUSDA.GOV by uu7.psi.com (5.65b/4.0.071791-PSI/PSINet) via SMTP;
+        id AA00699 for bostic@cs.berkeley.edu; Mon, 12 Sep 94 14:06:15 -0400
+Received: by aipl.arsusda.gov (AIX 3.2/UCB 5.64/4.03)
+          id AA14802; Mon, 12 Sep 1994 14:05:48 -0400
+Message-Id: <9409121805.AA14802@aipl.arsusda.gov>
+Subject: db 1.85 problem
+To: bostic@cs.berkeley.edu (Keith Bostic)
+Date: Mon, 12 Sep 1994 14:05:47 -0400 (EDT)
+X-Mailer: ELM [version 2.4 PL22]
+Content-Type: text
+Content-Length: 2553      
+Status: RO
+
+In using the btree option to sequentially read and then write a file, we
+are having a problem with 1.85.  When compiled with 1.73 there is no
+problem.  The problem is that the seq call keeps reading the same record. 
+The code follows:
+
+/* chkseq.c  Check sequential read and write */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>    /* O_CREAT,  O_RDWR */
+#include <errno.h>    /* Error numbers */
+#include <db.h>
+ 
+extern int errno;
+extern char *sys_errlist[];
+ 
+typedef struct idst {
+  char id1[7];
+} id;
+
+void cvtid(char *, char *);
+ 
+void main() {
+  char anim10[11], datastor[212],keystor[10], *pc;
+  int i;
+  long in = 0L;
+  DB *dbp, *dbpo;
+  DBT key, data, keyo, datao;
+
+  if ((dbp = dbopen("bullxrf.db", O_RDWR, 0664
+       , DB_BTREE, NULL )) == NULL) {
+    printf("\n Error on dbopen %d %s\n",errno,strerror(errno));
+    exit(61);
+  }
+  key.size = 7;
+  keyo.size = 7;
+
+  while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) {
+    in++;
+     if (in > 20) break; 
+/*      pc = (char *) key.data; 
+for (i=0;i<key.size;i++) printf("%02x",pc[i]); printf("\n"); */
+      cvtid(anim10,key.data); printf("%s\n",anim10); 
+    memcpy(keystor,key.data,key.size);
+/* for (i=0;i<key.size;i++) printf("%02x",keystor[i]); printf("\n"); */
+    memcpy(datastor,data.data,data.size);
+/* for (i=0;i<8;i++) printf("%02x",datastor[i]); printf("\n"); */
+    keyo.data = keystor;
+    datao.data = datastor;
+    datao.size = data.size;
+/*
+    if (in % 1000 == 1) {
+        cvtid(anim10,key.data); printf("%5d %s\n",in,anim10);  */
+      if (dbp->put(dbp, &keyo, &datao,0) != 0) {
+        printf("Write failed at %d\n",in);
+        exit(85);
+      }
+/*  }
+ */
+  }  
+  printf("%d Records copied\n",in);
+  dbp->close(dbp);
+}
+
+I am running on an RS/6000 AIX 3.2.5.  The section of the make file
+follows:
+
+# Make file
+all: chkseq
+
+chkseq: chkseq.c 
+	cc -gO3 -lm -o chkseq\
+  -L /data6/hash/include/sys/lib -l db  -I /data6/hash/include \
+  chkseq.c cvtid.o ascii.o
+#  -L /data12/db.1.85 -l db  -I /data12/db.1.85/include \
+
+We would appreciate your help.
+Thanks,
+
+-- 
+George Wiggans           I================================================I
+                         |Animal Improvement Programs Laboratory          |
+Phone:   301-504-8407    |Bldg 263 Beltsville Agricultural Research Center|
+FAX:     301-504-8092    |Beltsville, MD 20705-2350  USA                  |
+wiggans@aipl.arsusda.gov |                                                |
+=========================I================================================I
+
+From wiggans@aipl.arsusda.gov Fri Sep 16 20:27:22 1994
+Received: from vangogh.CS.Berkeley.EDU by python.bostic.com (8.6.9.Beta4/2.6)
+	id XAA09260; Fri, 16 Sep 1994 23:27:09 -0400
+From: wiggans@aipl.arsusda.gov
+Received: from hofmann.CS.Berkeley.EDU (hofmann.CS.Berkeley.EDU [128.32.34.35]) by vangogh.CS.Berkeley.EDU (8.7.Alpha.1/8.6.9.Beta0) with ESMTP id UAA25674 for <bostic@vangogh.CS.Berkeley.EDU>; Fri, 16 Sep 1994 20:27:03 -0700 (PDT)
+Received: from uu7.psi.com (uu7.psi.com [38.145.204.6]) by hofmann.CS.Berkeley.EDU (8.6.9/8.6.6.Beta11) with SMTP id UAA15043 for <bostic@cs.berkeley.edu>; Fri, 16 Sep 1994 20:27:16 -0700
+Received: from AIPL.ARSUSDA.GOV by uu7.psi.com (5.65b/4.0.071791-PSI/PSINet) via SMTP;
+        id AA18737 for bostic@cs.berkeley.edu; Fri, 16 Sep 94 23:27:14 -0400
+Received: by aipl.arsusda.gov (AIX 3.2/UCB 5.64/4.03)
+          id AA10907; Fri, 16 Sep 1994 23:26:18 -0400
+Message-Id: <9409170326.AA10907@aipl.arsusda.gov>
+Subject: Test case
+To: bostic@cs.berkeley.edu (Keith Bostic)
+Date: Fri, 16 Sep 1994 23:26:16 -0400 (EDT)
+X-Mailer: ELM [version 2.4 PL22]
+Content-Type: text
+Content-Length: 3713      
+Status: RO
+
+The following program loads 2 10 character animal ID which are used to
+change an animal's ID.  After loading, it closes, then opens and
+sequentially reads and rewrites the file changing the first character of
+the 2nd ID to U.  Failure is observed when the update part gets stuck on
+the first record, rereading it.  The last step displays the updated file.
+The name of the data file is a command line argument.
+
+The data:
+A000027875A000135891
+A000059165A000130168
+A000060256A000133490
+A040025906A000136770
+A040027881A000135829
+A040028611A000137873
+A040032413A000056974
+A040050163A000126233
+A040050329A000126177
+A040050411A000119017
+A040050995A000116767
+A040051022A000126669
+A040051276A000127444
+A040051514A000120563
+A040051597A000127287
+A040051627A000127284
+A040051700A000126914
+A040051810A000127286
+A040051964A000118834
+A040052164A000135104
+A040052165A000127688
+A040052186A000126926
+A040052530A000126287
+A040052560A000119160
+A040052892A000125334
+A040053004A000127684
+A040053359A000128628
+A040053378A000137680
+A040053416A000128825
+A040053589A000120369
+A040053620A000128460
+A040053751A000123525
+A040053754A000126736
+A040054191A000126286
+A040054251A000121745
+A040054253A000127848
+A040054596A000130931
+A040054981A000128731
+A040055000A000127689
+
+The program:
+/* chkseq.c  Check sequential read and write */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>    /* O_CREAT,  O_RDWR */
+#include <errno.h>    /* Error numbers */
+#include <db.h>
+ 
+extern int errno;
+extern char *sys_errlist[];
+ 
+ 
+void main(int argc, char *argv[]) {
+  char id1[] = {"          "}, id2[] = {"          "};
+  int i;
+  long in = 0L, out = 0L;
+  DB *dbp, *dbpo;
+  DBT key, data, keyo, datao;
+  FILE *fopen(), *fin;
+
+  if ((fin = fopen(argv[1],"r")) == NULL) {
+    printf("Unable to open %s\n",argv[1]);
+    exit(25);
+  }
+  if ((dbp = dbopen("test.db",O_RDWR | O_CREAT, 0664
+       , DB_BTREE, NULL )) == NULL) {
+    printf("\n Open error on test.db %d %s\n",errno,strerror(errno));
+    exit(25);
+  }
+   
+  while (fscanf(fin," %10s%10s",id1,id2) > 0) {
+    key.size = 11;
+    data.size = 11;
+    key.data = id1;
+    data.data = id2;
+    printf("%10s %10s\n",key.data,data.data); 
+    if (dbp->put(dbp, &key, &data,R_NOOVERWRITE) != 0) {
+      printf("Error writing output\n");
+    }
+    out++;
+  }
+  printf("%d Records in\n",out);
+  dbp->close(dbp);
+  
+  if ((dbp = dbopen("test.db", O_RDWR, 0664
+       , DB_BTREE, NULL )) == NULL) {
+    printf("\n Error on dbopen %d %s\n",errno,strerror(errno));
+    exit(61);
+  }
+
+  while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) {
+    strcpy(id1,key.data);
+    keyo.size = 11;
+    datao.size = 11;
+    keyo.data = id1;
+    strcpy(id2,data.data);
+    id2[0] = 'U';
+    datao.data=id2;
+    printf("%10s %10s\n",key.data,data.data); 
+    in++;
+    if (in > 50) break;
+    if (dbp->put(dbp, &keyo, &datao,0) != 0) {
+        printf("Write failed at %d\n",in);
+        exit(85);
+    }
+  }
+  printf("%d Records copied\n",in);
+  in = 0;
+    dbp->seq(dbp, &key, &data,R_FIRST);
+    printf("%10s %10s\n",key.data,data.data); 
+    in++;
+  while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) {
+    in++;
+    printf("%10s %10s\n",key.data,data.data); 
+  }
+  printf("%d Records read\n",in);
+  dbp->close(dbp);
+}
+
+
+-- 
+George Wiggans           I================================================I
+                         |Animal Improvement Programs Laboratory          |
+Phone:   301-504-8407    |Bldg 263 Beltsville Agricultural Research Center|
+FAX:     301-504-8092    |Beltsville, MD 20705-2350  USA                  |
+wiggans@aipl.arsusda.gov |                                                |
+=========================I================================================I
+
+From bostic Fri Sep 23 08:44:56 1994
+To: wiggans@aipl.arsusda.gov /usr/src/local/db/test/SEQ_TEST/mbox
+Subject: Re: Test case
+
+
+OK, I've attached a tentative patch for the bug, that appears
+to fix it on my local system.  Please let me know if you have
+any further problems with this.
+
+There are a couple of issues here.  The first, is that to some
+extent, the btree code is correct.  You aren't replacing the
+cursor in your test program, you're adding a new key, which
+just happens to be where the cursor was.  So, the btree code
+is doing you a favor by returning the new key as part of the
+cursor walk, and it's not its fault.  ;-}
+
+However, because a put to the cursor record is done using a
+delete/add pair, doing it the "right" way will result in the
+exact same behavior as you saw doing it "wrong".
+
+Thinking about this further, there's another bug that's going to
+hit eventually -- if you have duplicate records, the current
+scheme of doing delete/add to replace the cursor record can result
+in a record being returned twice, which is tacky at best, if not
+actually wrong.
+
+I think I may have to revisit how duplicate records are stored.
+Which does not make me happy. ;-{
+
+--keith
+
+*** db/btree/bt_seq.c.orig	Fri Sep 23 08:35:06 1994
+--- db/btree/bt_seq.c	Fri Sep 23 08:34:58 1994
+***************
+*** 35,41 ****
+   */
+  
+  #if defined(LIBC_SCCS) && !defined(lint)
+! static char sccsid[] = "@(#)bt_seq.c	8.7 (Berkeley) 7/20/94";
+  #endif /* LIBC_SCCS and not lint */
+  
+  #include <sys/types.h>
+--- 35,41 ----
+   */
+  
+  #if defined(LIBC_SCCS) && !defined(lint)
+! static char sccsid[] = "@(#)bt_seq.c	8.8 (Berkeley) 9/23/94";
+  #endif /* LIBC_SCCS and not lint */
+  
+  #include <sys/types.h>
+***************
+*** 246,252 ****
+  	PAGE *h;
+  	indx_t index;
+  	pgno_t pg;
+! 	int exact;
+  
+  	/*
+  	 * There are a couple of states that we can be in.  The cursor has
+--- 246,252 ----
+  	PAGE *h;
+  	indx_t index;
+  	pgno_t pg;
+! 	int exact, rval;
+  
+  	/*
+  	 * There are a couple of states that we can be in.  The cursor has
+***************
+*** 255,269 ****
+  	c = &t->bt_cursor;
+  
+  	/*
+! 	 * The cursor was deleted where there weren't any duplicate records,
+! 	 * so the key was saved.  Find out where that key would go in the
+! 	 * current tree.  It doesn't matter if the returned key is an exact
+! 	 * match or not -- if it's an exact match, the record was added after
+! 	 * the delete so we can just return it.  If not, as long as there's
+! 	 * a record there, return it.
+  	 */
+! 	if (F_ISSET(c, CURS_ACQUIRE))
+! 		return (__bt_first(t, &c->key, ep, &exact));
+  
+  	/* Get the page referenced by the cursor. */
+  	if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+--- 255,299 ----
+  	c = &t->bt_cursor;
+  
+  	/*
+! 	 * The cursor was deleted and there weren't any duplicate records,
+! 	 * so the cursor's key was saved.  Find out where that key would
+! 	 * be in the current tree.  If the returned key is an exact match,
+! 	 * it means that a key/data pair was inserted into the tree after
+! 	 * the delete.  We could reasonably return the key, but the problem
+! 	 * is that this is the access pattern we'll see if the user is
+! 	 * doing seq(..., R_NEXT)/put(..., 0) pairs, i.e. the put deletes
+! 	 * the cursor record and then replaces it, so the cursor was saved,
+! 	 * and we'll simply return the same "new" record until the user
+! 	 * notices and doesn't do a put() of it.  Since the key is an exact
+! 	 * match, we could as easily put the new record before the cursor,
+! 	 * and we've made no guarantee to return it.  So, move forward or
+! 	 * back a record if it's an exact match.
+! 	 *
+! 	 * XXX
+! 	 * In the current implementation, put's to the cursor are done with
+! 	 * delete/add pairs.  This has two consequences.  First, it means
+! 	 * that seq(..., R_NEXT)/put(..., R_CURSOR) pairs are going to exhibit
+! 	 * the same behavior as above.  Second, you can return the same key
+! 	 * twice if you have duplicate records.  The scenario is that the
+! 	 * cursor record is deleted, moving the cursor forward or backward
+! 	 * to a duplicate.  The add then inserts the new record at a location
+! 	 * ahead of the cursor because duplicates aren't sorted in any way,
+! 	 * and the new record is later returned.  This has to be fixed at some
+! 	 * point.
+  	 */
+! 	if (F_ISSET(c, CURS_ACQUIRE)) {
+! 		if (rval = __bt_first(t, &c->key, ep, &exact))
+! 			return (RET_ERROR);
+! 		if (!exact)
+! 			return (rval);
+! 		/*
+! 		 * XXX
+! 		 * Kluge -- get, release, get the page.
+! 		 */
+! 		c->pg.pgno = ep->page->pgno;
+! 		c->pg.index = ep->index;
+! 		mpool_put(t->bt_mp, ep->page, 0);
+! 	}
+  
+  	/* Get the page referenced by the cursor. */
+  	if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+
+
+
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c
new file mode 100644
index 000000000..f77b676f1
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c
@@ -0,0 +1,85 @@
+/* chkseq.c  Check sequential read and write */
+
+#include <sys/stat.h>
+#include "db-int.h"
+#include <errno.h>    /* Error numbers */
+#include <fcntl.h>    /* O_CREAT,  O_RDWR */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+ 
+void main(int argc, char *argv[]) {
+  char id1[] = {"          "}, id2[] = {"          "};
+  int i;
+  long in = 0L, out = 0L;
+  DB *dbp, *dbpo;
+  DBT key, data, keyo, datao;
+  FILE *fopen(), *fin;
+
+  unlink("test.db");
+  if ((fin = fopen("data","r")) == NULL) {
+    printf("Unable to open %s\n","data");
+    exit(25);
+  }
+  if ((dbp = dbopen("test.db",O_RDWR | O_CREAT | O_BINARY, 0664
+       , DB_BTREE, NULL )) == NULL) {
+    printf("\n Open error on test.db %d %s\n",errno,strerror(errno));
+    exit(25);
+  }
+   
+  while (fscanf(fin," %10s%10s",id1,id2) > 0) {
+    key.size = 11;
+    data.size = 11;
+    key.data = id1;
+    data.data = id2;
+    printf("%10s %10s\n",key.data,data.data); 
+    if (dbp->put(dbp, &key, &data,R_NOOVERWRITE) != 0) {
+      printf("Error writing output\n");
+    }
+    out++;
+  }
+  printf("%d Records in\n",out);
+  dbp->close(dbp);
+  
+  if ((dbp = dbopen("test.db", O_RDWR | O_BINARY, 0664
+       , DB_BTREE, NULL )) == NULL) {
+    printf("\n Error on dbopen %d %s\n",errno,strerror(errno));
+    exit(61);
+  }
+
+  while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) {
+    strcpy(id1,key.data);
+    keyo.size = 11;
+    datao.size = 11;
+    keyo.data = id1;
+    strcpy(id2,data.data);
+    id2[0] = 'U';
+    datao.data=id2;
+    printf("%10s %10s\n",key.data,data.data); 
+    in++;
+    if (in > 10) break;
+#ifdef notdef
+    if (dbp->put(dbp, &keyo, &datao,0) != 0) {
+        printf("Write failed at %d\n",in);
+        exit(85);
+    }
+#else
+    if (dbp->put(dbp, &keyo, &datao,R_CURSOR) != 0) {
+        printf("Write failed at %d\n",in);
+        exit(85);
+    }
+#endif
+  }
+  printf("%d Records copied\n",in);
+  in = 0;
+    dbp->seq(dbp, &key, &data,R_FIRST);
+    printf("%10s %10s\n",key.data,data.data); 
+    in++;
+  while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) {
+    in++;
+    printf("%10s %10s\n",key.data,data.data); 
+  }
+  printf("%d Records read\n",in);
+  dbp->close(dbp);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c
new file mode 100644
index 000000000..06f02b3ad
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c
@@ -0,0 +1,832 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include "db-int.h"
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "btree.h"
+
+typedef struct cmd_table {
+	char *cmd;
+	int nargs;
+	int rconv;
+	void (*func) __P((DB *, char **));
+	char *usage, *descrip;
+} cmd_table;
+
+int stopstop;
+DB *globaldb;
+
+#if 0
+void append	__P((DB *, char **));
+#endif
+#ifdef STATISTICS
+void bstat	__P((DB *, char **));
+#endif
+void cursor	__P((DB *, char **));
+void delcur	__P((DB *, char **));
+void delete	__P((DB *, char **));
+#ifdef DEBUG
+void dump	__P((DB *, char **));
+#endif
+void first	__P((DB *, char **));
+void get	__P((DB *, char **));
+void help	__P((DB *, char **));
+void iafter	__P((DB *, char **));
+void ibefore	__P((DB *, char **));
+void icursor	__P((DB *, char **));
+void insert	__P((DB *, char **));
+void keydata	__P((DBT *, DBT *));
+void last	__P((DB *, char **));
+void list	__P((DB *, char **));
+#if 0
+void load	__P((DB *, char **));
+#endif
+#ifdef STATISTICS
+void mstat	__P((DB *, char **));
+#endif
+void next	__P((DB *, char **));
+int  parse	__P((char *, char **, int));
+void previous	__P((DB *, char **));
+#ifdef DEBUG
+void show	__P((DB *, char **));
+#endif
+void rlist	__P((DB *, char **));
+void usage	__P((void));
+void user	__P((DB *));
+
+cmd_table commands[] = {
+	"?",	0, 0, help, "help", NULL,
+#if 0
+	"a",	2, 1, append, "append key def", "append key with data def",
+#endif
+#ifdef STATISTICS
+	"b",	0, 0, bstat, "bstat", "stat btree",
+#endif
+	"c",	1, 1, cursor,  "cursor word", "move cursor to word",
+	"delc",	0, 0, delcur, "delcur", "delete key the cursor references",
+	"dele",	1, 1, delete, "delete word", "delete word",
+#ifdef DEBUG
+	"d",	0, 0, dump, "dump", "dump database",
+#endif
+	"f",	0, 0, first, "first", "move cursor to first record",
+	"g",	1, 1, get, "get key", "locate key",
+	"h",	0, 0, help, "help", "print command summary",
+	"ia",	2, 1, iafter, "iafter key data", "insert data after key",
+	"ib",	2, 1, ibefore, "ibefore key data", "insert data before key",
+	"ic",	2, 1, icursor, "icursor key data", "replace cursor",
+	"in",	2, 1, insert, "insert key def", "insert key with data def",
+	"la",	0, 0, last, "last", "move cursor to last record",
+	"li",	1, 1, list, "list file", "list to a file",
+#if 0
+	"loa",	1, 0, load, "load file", NULL,
+#endif
+	"loc",	1, 1, get, "get key", NULL,
+#ifdef STATISTICS
+	"m",	0, 0, mstat, "mstat", "stat memory pool",
+#endif
+	"n",	0, 0, next, "next", "move cursor forward one record",
+	"p",	0, 0, previous, "previous", "move cursor back one record",
+	"q",	0, 0, NULL, "quit", "quit",
+	"rli",	1, 1, rlist, "rlist file", "list to a file (recursive)",
+#ifdef DEBUG
+	"sh",	1, 0, show, "show page", "dump a page",
+#endif
+	{ NULL },
+};
+
+int recno;					/* use record numbers */
+char *dict = "words";				/* default dictionary */
+char *progname;
+
+int
+main(argc, argv)
+	int argc;
+	char **argv;
+{
+	int c;
+	int omode;
+	DB *db;
+	BTREEINFO b;
+
+	progname = *argv;
+
+	omode = O_RDONLY;
+	b.flags = 0;
+	b.cachesize = 0;
+	b.maxkeypage = 0;
+	b.minkeypage = 0;
+	b.psize = 0;
+	b.compare = NULL;
+	b.prefix = NULL;
+	b.lorder = 0;
+
+	while ((c = getopt(argc, argv, "bc:di:lp:ruw")) != -1) {
+		switch (c) {
+		case 'b':
+			b.lorder = DB_BIG_ENDIAN;
+			break;
+		case 'c':
+			b.cachesize = atoi(optarg);
+			break;
+		case 'd':
+			b.flags |= R_DUP;
+			break;
+		case 'i':
+			dict = optarg;
+			break;
+		case 'l':
+			b.lorder = DB_LITTLE_ENDIAN;
+			break;
+		case 'p':
+			b.psize = atoi(optarg);
+			break;
+		case 'r':
+			recno = 1;
+			break;
+		case 'u':
+			b.flags = 0;
+			break;
+		case 'w':
+			omode = O_RDWR;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (recno)
+		db = dbopen(*argv == NULL ? NULL : *argv, omode|O_BINARY,
+		    0, DB_RECNO, NULL);
+	else
+		db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|omode|O_BINARY,
+		    0600, DB_BTREE, &b);
+
+	if (db == NULL) {
+		(void)fprintf(stderr, "dbopen: %s\n", strerror(errno));
+		exit(1);
+	}
+	globaldb = db;
+	user(db);
+	exit(0);
+	/* NOTREACHED */
+}
+
+void
+user(db)
+	DB *db;
+{
+	FILE *ifp;
+	int argc, i, last;
+	char *lbuf, *argv[4], buf[512];
+
+	if ((ifp = fopen("/dev/tty", "r")) == NULL) {
+		(void)fprintf(stderr,
+		    "/dev/tty: %s\n", strerror(errno));
+		exit(1);
+	}
+	for (last = 0;;) {
+		(void)printf("> ");
+		(void)fflush(stdout);
+		if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL)
+			break;
+		if (lbuf[0] == '\n') {
+			i = last;
+			goto uselast;
+		}
+		lbuf[strlen(lbuf) - 1] = '\0';
+
+		if (lbuf[0] == 'q')
+			break;
+
+		argc = parse(lbuf, &argv[0], 3);
+		if (argc == 0)
+			continue;
+
+		for (i = 0; commands[i].cmd != NULL; i++)
+			if (strncmp(commands[i].cmd, argv[0],
+			    strlen(commands[i].cmd)) == 0)
+				break;
+
+		if (commands[i].cmd == NULL) {
+			(void)fprintf(stderr,
+			    "%s: command unknown ('help' for help)\n", lbuf);
+			continue;
+		}
+
+		if (commands[i].nargs != argc - 1) {
+			(void)fprintf(stderr, "usage: %s\n", commands[i].usage);
+			continue;
+		}
+
+		if (recno && commands[i].rconv) {
+			static recno_t nlong;
+			nlong = atoi(argv[1]);
+			argv[1] = (char *)&nlong;
+		}
+uselast:	last = i;
+		(*commands[i].func)(db, argv);
+	}
+	if ((db->sync)(db, 0) == RET_ERROR)
+		perror("dbsync");
+	else if ((db->close)(db) == RET_ERROR)
+		perror("dbclose");
+}
+
+int
+parse(lbuf, argv, maxargc)
+	char *lbuf, **argv;
+	int maxargc;
+{
+	int argc = 0;
+	char *c;
+
+	c = lbuf;
+	while (isspace(*c))
+		c++;
+	while (*c != '\0' && argc < maxargc) {
+		*argv++ = c;
+		argc++;
+		while (!isspace(*c) && *c != '\0') {
+			c++;
+		}
+		while (isspace(*c))
+			*c++ = '\0';
+	}
+	return (argc);
+}
+
+#if 0
+void
+append(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key, data;
+	int status;
+
+	if (!recno) {
+		(void)fprintf(stderr,
+		    "append only available for recno db's.\n");
+		return;
+	}
+	key.data = argv[1];
+	key.size = sizeof(recno_t);
+	data.data = argv[2];
+	data.size = strlen(data.data);
+	status = (db->put)(db, &key, &data, R_APPEND);
+	switch (status) {
+	case RET_ERROR:
+		perror("append/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+#endif
+
+void
+cursor(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+	status = (*db->seq)(db, &key, &data, R_CURSOR);
+	switch (status) {
+	case RET_ERROR:
+		perror("cursor/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("key not found\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+delcur(db, argv)
+	DB *db;
+	char **argv;
+{
+	int status;
+
+	status = (*db->del)(db, NULL, R_CURSOR);
+
+	if (status == RET_ERROR)
+		perror("delcur/del");
+}
+
+void
+delete(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key;
+	int status;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+
+	status = (*db->del)(db, &key, 0);
+	switch (status) {
+	case RET_ERROR:
+		perror("delete/del");
+		break;
+	case RET_SPECIAL:
+		(void)printf("key not found\n");
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+#ifdef DEBUG
+void
+dump(db, argv)
+	DB *db;
+	char **argv;
+{
+	__bt_dump(db);
+}
+#endif
+
+void
+first(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_FIRST);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("first/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+get(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+
+	status = (*db->get)(db, &key, &data, 0);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("get/get");
+		break;
+	case RET_SPECIAL:
+		(void)printf("key not found\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+help(db, argv)
+	DB *db;
+	char **argv;
+{
+	int i;
+
+	for (i = 0; commands[i].cmd; i++)
+		if (commands[i].descrip)
+			(void)printf("%s: %s\n",
+			    commands[i].usage, commands[i].descrip);
+}
+
+void
+iafter(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key, data;
+	int status;
+
+	if (!recno) {
+		(void)fprintf(stderr,
+		    "iafter only available for recno db's.\n");
+		return;
+	}
+	key.data = argv[1];
+	key.size = sizeof(recno_t);
+	data.data = argv[2];
+	data.size = strlen(data.data);
+	status = (db->put)(db, &key, &data, R_IAFTER);
+	switch (status) {
+	case RET_ERROR:
+		perror("iafter/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+ibefore(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT key, data;
+	int status;
+
+	if (!recno) {
+		(void)fprintf(stderr,
+		    "ibefore only available for recno db's.\n");
+		return;
+	}
+	key.data = argv[1];
+	key.size = sizeof(recno_t);
+	data.data = argv[2];
+	data.size = strlen(data.data);
+	status = (db->put)(db, &key, &data, R_IBEFORE);
+	switch (status) {
+	case RET_ERROR:
+		perror("ibefore/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+icursor(db, argv)
+	DB *db;
+	char **argv;
+{
+	int status;
+	DBT data, key;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+	data.data = argv[2];
+	data.size = strlen(argv[2]) + 1;
+
+	status = (*db->put)(db, &key, &data, R_CURSOR);
+	switch (status) {
+	case RET_ERROR:
+		perror("icursor/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+insert(db, argv)
+	DB *db;
+	char **argv;
+{
+	int status;
+	DBT data, key;
+
+	key.data = argv[1];
+	if (recno)
+		key.size = sizeof(recno_t);
+	else
+		key.size = strlen(argv[1]) + 1;
+	data.data = argv[2];
+	data.size = strlen(argv[2]) + 1;
+
+	status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
+	switch (status) {
+	case RET_ERROR:
+		perror("insert/put");
+		break;
+	case RET_SPECIAL:
+		(void)printf("%s (duplicate key)\n", argv[1]);
+		break;
+	case RET_SUCCESS:
+		break;
+	}
+}
+
+void
+last(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_LAST);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("last/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+list(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	FILE *fp;
+	int status;
+
+	if ((fp = fopen(argv[1], "w")) == NULL) {
+		(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+		return;
+	}
+	status = (*db->seq)(db, &key, &data, R_FIRST);
+	while (status == RET_SUCCESS) {
+		(void)fprintf(fp, "%s\n", key.data);
+		status = (*db->seq)(db, &key, &data, R_NEXT);
+	}
+	(void)fclose(fp);
+	if (status == RET_ERROR)
+		perror("list/seq");
+}
+
+void
+rlist(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	FILE *fp;
+	int status;
+	void *cookie;
+
+	cookie = NULL;
+	if ((fp = fopen(argv[1], "w")) == NULL) {
+		(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+		return;
+	}
+	status = bt_rseq(db, &key, &data, &cookie, R_FIRST);
+	while (status == RET_SUCCESS) {
+		(void)fprintf(fp, "%s\n", key.data);
+		status = bt_rseq(db, &key, &data, &cookie, R_NEXT);
+	}
+	(void)fclose(fp);
+	if (status == RET_ERROR)
+		perror("list/seq");
+}
+
+#if 0
+DB *BUGdb;
+void
+load(db, argv)
+	DB *db;
+	char **argv;
+{
+	register char *p, *t;
+	FILE *fp;
+	DBT data, key;
+	recno_t cnt;
+	size_t len;
+	int status;
+	char *lp, buf[16 * 1024];
+
+	BUGdb = db;
+	if ((fp = fopen(argv[1], "r")) == NULL) {
+		(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+		return;
+	}
+	(void)printf("loading %s...\n", argv[1]);
+
+	for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) {
+		if (recno) {
+			key.data = &cnt;
+			key.size = sizeof(recno_t);
+			data.data = lp;
+			data.size = len + 1;
+		} else { 
+			key.data = lp;
+			key.size = len + 1;
+			for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);
+			*t = '\0';
+			data.data = buf;
+			data.size = len + 1;
+		}
+
+		status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
+		switch (status) {
+		case RET_ERROR:
+			perror("load/put");
+			exit(1);
+		case RET_SPECIAL:
+			if (recno)
+				(void)fprintf(stderr,
+				    "duplicate: %ld {%s}\n", cnt, data.data);
+			else
+				(void)fprintf(stderr,
+				    "duplicate: %ld {%s}\n", cnt, key.data);
+			exit(1);
+		case RET_SUCCESS:
+			break;
+		}
+	}
+	(void)fclose(fp);
+}
+#endif
+
+void
+next(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_NEXT);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("next/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+void
+previous(db, argv)
+	DB *db;
+	char **argv;
+{
+	DBT data, key;
+	int status;
+
+	status = (*db->seq)(db, &key, &data, R_PREV);
+
+	switch (status) {
+	case RET_ERROR:
+		perror("previous/seq");
+		break;
+	case RET_SPECIAL:
+		(void)printf("no more keys\n");
+		break;
+	case RET_SUCCESS:
+		keydata(&key, &data);
+		break;
+	}
+}
+
+#ifdef DEBUG
+void
+show(db, argv)
+	DB *db;
+	char **argv;
+{
+	BTREE *t;
+	PAGE *h;
+	db_pgno_t pg;
+
+	pg = atoi(argv[1]);
+	t = db->internal;
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
+		(void)printf("getpage of %ld failed\n", pg);
+		return;
+	}
+	if (pg == 0)
+		__bt_dmpage(h);
+	else
+		__bt_dpage(db, h);
+	mpool_put(t->bt_mp, h, 0);
+}
+#endif
+
+#ifdef STATISTICS
+void
+bstat(db, argv)
+	DB *db;
+	char **argv;
+{
+	(void)printf("BTREE\n");
+	__bt_stat(db);
+}
+
+void
+mstat(db, argv)
+	DB *db;
+	char **argv;
+{
+	(void)printf("MPOOL\n");
+	mpool_stat(((BTREE *)db->internal)->bt_mp);
+}
+#endif
+
+void
+keydata(key, data)
+	DBT *key, *data;
+{
+	if (!recno && key->size > 0)
+		(void)printf("%s/", key->data);
+	if (data->size > 0)
+		(void)printf("%s", data->data);
+	(void)printf("\n");
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+	    "usage: %s [-bdluw] [-c cache] [-i file] [-p page] [file]\n",
+	    progname);
+	exit (1);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/dbtest.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/dbtest.c
new file mode 100644
index 000000000..10a89a6fa
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/dbtest.c
@@ -0,0 +1,768 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)dbtest.c	8.17 (Berkeley) 9/1/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "db-int.h"
+#ifdef STATISTICS
+#include "btree.h"
+#endif
+
+enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+#define ATTR(x) __attribute__(x)
+#else
+#define ATTR(x)
+#endif
+
+void	 compare __P((DBT *, DBT *));
+DBTYPE	 dbtype __P((char *));
+void	 dump __P((DB *, int));
+void	 err __P((const char *, ...)) ATTR ((__format__(__printf__,1,2))) ATTR ((__noreturn__));
+void	 get __P((DB *, DBT *));
+void	 getdata __P((DB *, DBT *, DBT *));
+void	 put __P((DB *, DBT *, DBT *));
+void	 rem __P((DB *, DBT *));
+char	*sflags __P((int));
+void	 synk __P((DB *));
+void	*rfile __P((char *, size_t *));
+void	 seq __P((DB *, DBT *));
+u_int	 setflags __P((char *));
+void	*setinfo __P((DBTYPE, char *));
+void	 usage __P((void));
+void	*xmalloc __P((char *, size_t));
+
+DBTYPE type;				/* Database type. */
+void *infop;				/* Iflags. */
+u_long lineno;				/* Current line in test script. */
+u_int flags;				/* Current DB flags. */
+int ofd = STDOUT_FILENO;		/* Standard output fd. */
+
+DB *XXdbp;				/* Global for gdb. */
+int XXlineno;				/* Fast breakpoint for gdb. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern int optind;
+	extern char *optarg;
+	enum S command, state;
+	DB *dbp;
+	DBT data, key, keydata;
+	size_t len;
+	int ch, oflags, sflag;
+	char *fname, *infoarg, *p, *t, buf[8 * 1024];
+
+	infoarg = NULL;
+	fname = NULL;
+	oflags = O_CREAT | O_RDWR | O_BINARY;
+	sflag = 0;
+	while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1)
+		switch (ch) {
+		case 'f':
+			fname = optarg;
+			break;
+		case 'i':
+			infoarg = optarg;
+			break;
+		case 'l':
+			oflags |= DB_LOCK;
+			break;
+		case 'o':
+			if ((ofd = open(optarg,
+			    O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+				err("%s: %s", optarg, strerror(errno));
+			break;
+		case 's':
+			sflag = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 2)
+		usage();
+
+	/* Set the type. */
+	type = dbtype(*argv++);
+
+	/* Open the descriptor file. */
+        if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
+	    err("%s: %s", *argv, strerror(errno));
+
+	/* Set up the db structure as necessary. */
+	if (infoarg == NULL)
+		infop = NULL;
+	else
+		for (p = strtok(infoarg, ",\t "); p != NULL;
+		    p = strtok(0, ",\t "))
+			if (*p != '\0')
+				infop = setinfo(type, p);
+
+	/*
+	 * Open the DB.  Delete any preexisting copy, you almost never
+	 * want it around, and it often screws up tests.
+	 */
+	if (fname == NULL) {
+		p = getenv("TMPDIR");
+		if (p == NULL)
+			p = "/var/tmp";
+		(void)sprintf(buf, "%s/__dbtest", p);
+		fname = buf;
+		(void)unlink(buf);
+	} else  if (!sflag)
+		(void)unlink(fname);
+
+	if ((dbp = dbopen(fname,
+	    oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
+		err("dbopen: %s", strerror(errno));
+	XXdbp = dbp;
+
+	state = COMMAND;
+	for (lineno = 1;
+	    (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
+		/* Delete the newline, displaying the key/data is easier. */
+		if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
+			*t = '\0';
+		if ((len = strlen(buf)) == 0 || isspace((int) *p) || *p == '#')
+			continue;
+
+		/* Convenient gdb break point. */
+		if (XXlineno == lineno)
+			XXlineno = 1;
+		switch (*p) {
+		case 'c':			/* compare */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = COMPARE;
+			break;
+		case 'e':			/* echo */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			/* Don't display the newline, if CR at EOL. */
+			if (p[len - 2] == '\r')
+				--len;
+			if (write(ofd, p + 1, len - 1) != len - 1 ||
+			    write(ofd, "\n", 1) != 1)
+				err("write: %s", strerror(errno));
+			break;
+		case 'g':			/* get */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = GET;
+			break;
+		case 'p':			/* put */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = PUT;
+			break;
+		case 'r':			/* remove */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+                        if (flags == R_CURSOR) {
+				rem(dbp, &key);
+				state = COMMAND;
+                        } else {
+				state = KEY;
+				command = REMOVE;
+			}
+			break;
+		case 'S':			/* sync */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			synk(dbp);
+			state = COMMAND;
+			break;
+		case 's':			/* seq */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			if (flags == R_CURSOR) {
+				state = KEY;
+				command = SEQ;
+			} else
+				seq(dbp, &key);
+			break;
+		case 'f':
+			flags = setflags(p + 1);
+			break;
+		case 'D':			/* data file */
+			if (state != DATA)
+				err("line %lu: not expecting data", lineno);
+			data.data = rfile(p + 1, &data.size);
+			goto ldata;
+		case 'd':			/* data */
+			if (state != DATA)
+				err("line %lu: not expecting data", lineno);
+			data.data = xmalloc(p + 1, len - 1);
+			data.size = len - 1;
+ldata:			switch (command) {
+			case COMPARE:
+				compare(&keydata, &data);
+				break;
+			case PUT:
+				put(dbp, &key, &data);
+				break;
+			default:
+				err("line %lu: command doesn't take data",
+				    lineno);
+			}
+			if (type != DB_RECNO)
+				free(key.data);
+			free(data.data);
+			state = COMMAND;
+			break;
+		case 'K':			/* key file */
+			if (state != KEY)
+				err("line %lu: not expecting a key", lineno);
+			if (type == DB_RECNO)
+				err("line %lu: 'K' not available for recno",
+				    lineno);
+			key.data = rfile(p + 1, &key.size);
+			goto lkey;
+		case 'k':			/* key */
+			if (state != KEY)
+				err("line %lu: not expecting a key", lineno);
+			if (type == DB_RECNO) {
+				static recno_t recno;
+				recno = atoi(p + 1);
+				key.data = &recno;
+				key.size = sizeof(recno);
+			} else {
+				key.data = xmalloc(p + 1, len - 1);
+				key.size = len - 1;
+			}
+lkey:			switch (command) {
+			case COMPARE:
+				getdata(dbp, &key, &keydata);
+				state = DATA;
+				break;
+			case GET:
+				get(dbp, &key);
+				if (type != DB_RECNO)
+					free(key.data);
+				state = COMMAND;
+				break;
+			case PUT:
+				state = DATA;
+				break;
+			case REMOVE:
+				rem(dbp, &key);
+				if ((type != DB_RECNO) && (flags != R_CURSOR))
+					free(key.data);
+				state = COMMAND;
+				break;
+			case SEQ:
+				seq(dbp, &key);
+				if ((type != DB_RECNO) && (flags != R_CURSOR))
+					free(key.data);
+				state = COMMAND;
+				break;
+			default:
+				err("line %lu: command doesn't take a key",
+				    lineno);
+			}
+			break;
+		case 'o':
+			dump(dbp, p[1] == 'r');
+			break;
+		default:
+			err("line %lu: %s: unknown command character",
+			    lineno, p);
+		}
+	}
+#ifdef STATISTICS
+	/*
+	 * -l must be used (DB_LOCK must be set) for this to be
+	 * used, otherwise a page will be locked and it will fail.
+	 */
+	if (type == DB_BTREE && oflags & DB_LOCK)
+		__bt_stat(dbp);
+#endif
+	if (dbp->close(dbp))
+		err("db->close: %s", strerror(errno));
+	(void)close(ofd);
+	exit(0);
+}
+
+#define	NOOVERWRITE	"put failed, would overwrite key\n"
+
+void
+compare(db1, db2)
+	DBT *db1, *db2;
+{
+	register size_t len;
+	register u_char *p1, *p2;
+
+	if (db1->size != db2->size) {
+		printf("compare failed: key->data len %lu != data len %lu\n",
+		    (u_long) db1->size, (u_long) db2->size);
+		exit (1);
+	}
+
+	len = MIN(db1->size, db2->size);
+	for (p1 = db1->data, p2 = db2->data; len--;)
+		if (*p1++ != *p2++) {
+			err("compare failed at offset %d\n",
+			    p1 - (u_char *)db1->data);
+			break;
+		}
+}
+
+void
+get(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	DBT data;
+
+	switch (dbp->get(dbp, kp, &data, flags)) {
+	case 0:
+		(void)write(ofd, data.data, data.size);
+		if (ofd == STDOUT_FILENO)
+			(void)write(ofd, "\n", 1);
+		break;
+	case -1:
+		err("line %lu: get: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"get failed, no such key\n"
+		if (ofd != STDOUT_FILENO) {
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+			exit(1);
+		} else
+			(void)fprintf(stderr, "%lu: %.*s: %s",
+			    lineno, (int) MIN(kp->size, 20), (char *) kp->data, 
+				      NOSUCHKEY);
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+getdata(dbp, kp, dp)
+	DB *dbp;
+	DBT *kp, *dp;
+{
+	switch (dbp->get(dbp, kp, dp, flags)) {
+	case 0:
+		return;
+	case -1:
+		err("line %lu: getdata: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+		err("line %lu: getdata failed, no such key", lineno);
+		/* NOTREACHED */
+	}
+}
+
+void
+put(dbp, kp, dp)
+	DB *dbp;
+	DBT *kp, *dp;
+{
+	switch (dbp->put(dbp, kp, dp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: put: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+		(void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
+		break;
+	}
+}
+
+void
+rem(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	switch (dbp->del(dbp, kp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: rem: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"rem failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else if (flags != R_CURSOR)
+			(void)fprintf(stderr, "%lu: %.*s: %s", 
+			    lineno, (int) MIN(kp->size, 20), (char *) kp->data, 
+				      NOSUCHKEY);
+		else
+			(void)fprintf(stderr,
+			    "%lu: rem of cursor failed\n", lineno);
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+synk(dbp)
+	DB *dbp;
+{
+	switch (dbp->sync(dbp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: synk: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	}
+}
+
+void
+seq(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	DBT data;
+
+	switch (dbp->seq(dbp, kp, &data, flags)) {
+	case 0:
+		(void)write(ofd, data.data, data.size);
+		if (ofd == STDOUT_FILENO)
+			(void)write(ofd, "\n", 1);
+		break;
+	case -1:
+		err("line %lu: seq: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"seq failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else if (flags == R_CURSOR)
+			(void)fprintf(stderr, "%lu: %.*s: %s", 
+			    lineno, (int) MIN(kp->size, 20), (char *) kp->data, 
+				      NOSUCHKEY);
+		else
+			(void)fprintf(stderr,
+			    "%lu: seq (%s) failed\n", lineno, sflags(flags));
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+dump(dbp, rev)
+	DB *dbp;
+	int rev;
+{
+	DBT key, data;
+	int lflags, nflags;
+
+	if (rev) {
+		lflags = R_LAST;
+		nflags = R_PREV;
+	} else {
+		lflags = R_FIRST;
+		nflags = R_NEXT;
+	}
+	for (;; lflags = nflags)
+		switch (dbp->seq(dbp, &key, &data, lflags)) {
+		case 0:
+			(void)write(ofd, data.data, data.size);
+			if (ofd == STDOUT_FILENO)
+				(void)write(ofd, "\n", 1);
+			break;
+		case 1:
+			goto done;
+		case -1:
+			err("line %lu: (dump) seq: %s",
+			    lineno, strerror(errno));
+			/* NOTREACHED */
+		}
+done:	return;
+}
+	
+u_int
+setflags(s)
+	char *s;
+{
+	char *p;
+
+	for (; isspace((int) *s); ++s);
+	if (*s == '\n' || *s == '\0')
+		return (0);
+	if ((p = strchr(s, '\n')) != NULL)
+		*p = '\0';
+	if (!strcmp(s, "R_CURSOR"))		return (R_CURSOR);
+	if (!strcmp(s, "R_FIRST"))		return (R_FIRST);
+	if (!strcmp(s, "R_IAFTER")) 		return (R_IAFTER);
+	if (!strcmp(s, "R_IBEFORE")) 		return (R_IBEFORE);
+	if (!strcmp(s, "R_LAST")) 		return (R_LAST);
+	if (!strcmp(s, "R_NEXT")) 		return (R_NEXT);
+	if (!strcmp(s, "R_NOOVERWRITE"))	return (R_NOOVERWRITE);
+	if (!strcmp(s, "R_PREV"))		return (R_PREV);
+	if (!strcmp(s, "R_SETCURSOR"))		return (R_SETCURSOR);
+
+	err("line %lu: %s: unknown flag", lineno, s);
+	/* NOTREACHED */
+}
+
+char *
+sflags(lflags)
+	int lflags;
+{
+	switch (lflags) {
+	case R_CURSOR:		return ("R_CURSOR");
+	case R_FIRST:		return ("R_FIRST");
+	case R_IAFTER:		return ("R_IAFTER");
+	case R_IBEFORE:		return ("R_IBEFORE");
+	case R_LAST:		return ("R_LAST");
+	case R_NEXT:		return ("R_NEXT");
+	case R_NOOVERWRITE:	return ("R_NOOVERWRITE");
+	case R_PREV:		return ("R_PREV");
+	case R_SETCURSOR:	return ("R_SETCURSOR");
+	}
+
+	return ("UNKNOWN!");
+}
+	
+DBTYPE
+dbtype(s)
+	char *s;
+{
+	if (!strcmp(s, "btree"))
+		return (DB_BTREE);
+	if (!strcmp(s, "hash"))
+		return (DB_HASH);
+	if (!strcmp(s, "recno"))
+		return (DB_RECNO);
+	err("%s: unknown type (use btree, hash or recno)", s);
+	/* NOTREACHED */
+}
+
+void *
+setinfo(db_type, s)
+	DBTYPE db_type;
+	char *s;
+{
+	static BTREEINFO ib;
+	static HASHINFO ih;
+	static RECNOINFO rh;
+	char *eq;
+
+	if ((eq = strchr(s, '=')) == NULL)
+		err("%s: illegal structure set statement", s);
+	*eq++ = '\0';
+	if (!isdigit((int) *eq))
+		err("%s: structure set statement must be a number", s);
+		
+	switch (db_type) {
+	case DB_BTREE:
+		if (!strcmp("flags", s)) {
+			ib.flags = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("cachesize", s)) {
+			ib.cachesize = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("maxkeypage", s)) {
+			ib.maxkeypage = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("minkeypage", s)) {
+			ib.minkeypage = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("lorder", s)) {
+			ib.lorder = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("psize", s)) {
+			ib.psize = atoi(eq);
+			return (&ib);
+		}
+		break;
+	case DB_HASH:
+		if (!strcmp("bsize", s)) {
+			ih.bsize = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("ffactor", s)) {
+			ih.ffactor = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("nelem", s)) {
+			ih.nelem = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("cachesize", s)) {
+			ih.cachesize = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("lorder", s)) {
+			ih.lorder = atoi(eq);
+			return (&ih);
+		}
+		break;
+	case DB_RECNO:
+		if (!strcmp("flags", s)) {
+			rh.flags = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("cachesize", s)) {
+			rh.cachesize = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("lorder", s)) {
+			rh.lorder = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("reclen", s)) {
+			rh.reclen = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("bval", s)) {
+			rh.bval = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("psize", s)) {
+			rh.psize = atoi(eq);
+			return (&rh);
+		}
+		break;
+	}
+	err("%s: unknown structure value", s);
+	/* NOTREACHED */
+}
+
+void *
+rfile(name, lenp)
+	char *name;
+	size_t *lenp;
+{
+	struct stat sb;
+	void *p;
+	int fd;
+	char *np;
+
+	for (; isspace((int) *name); ++name);
+	if ((np = strchr(name, '\n')) != NULL)
+		*np = '\0';
+	if ((fd = open(name, O_RDONLY, 0)) < 0 ||
+	    fstat(fd, &sb))
+		err("%s: %s\n", name, strerror(errno));
+#ifdef NOT_PORTABLE
+	if (sb.st_size > (off_t)SIZE_T_MAX)
+		err("%s: %s\n", name, strerror(E2BIG));
+#endif
+	if ((p = (void *)malloc((u_int)sb.st_size)) == NULL)
+		err("%s", strerror(errno));
+	(void)read(fd, p, (int)sb.st_size);
+	*lenp = sb.st_size;
+	(void)close(fd);
+	return (p);
+}
+
+void *
+xmalloc(text, len)
+	char *text;
+	size_t len;
+{
+	void *p;
+
+	if ((p = (void *)malloc(len)) == NULL)
+		err("%s", strerror(errno));
+	memmove(p, text, len);
+	return (p);
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+	    "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n");
+	exit(1);
+}
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#ifdef __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+	char *fmt;
+        va_dcl
+#endif
+{
+	va_list ap;
+#ifdef __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	(void)fprintf(stderr, "dbtest: ");
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	(void)fprintf(stderr, "\n");
+	exit(1);
+	/* NOTREACHED */
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/dictionary b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/dictionary
new file mode 100644
index 000000000..53640f016
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/dictionary
@@ -0,0 +1,308 @@
+abintrme
+ablatweo
+agdbevea
+aglamber
+aicehayt
+alerover
+anadanth
+ancmirtt
+ancthada
+angcther
+antasikt
+arathmsm
+arescofa
+arthatea
+asallyth
+asathedl
+ascelass
+athaneal
+atheneri
+atheryit
+athiopep
+athysidc
+atyhtiti
+auletard
+aytthepr
+bedthesa
+beiofttw
+bemofrda
+bertedud
+bessdide
+bestiemb
+blllanof
+bllssunt
+blstther
+bttelthh
+bulyousi
+bupedire
+buseatsd
+butritat
+byeditam
+cedvecur
+censaith
+centhfro
+centitar
+ceourire
+cetheaso
+chancora
+chavengl
+chederas
+chemsywh
+civadayo
+ckedacag
+ckstiptr
+colither
+congchin
+corepppl
+cronoria
+cthilath
+cthouthe
+ctofowon
+cumetbry
+dbethere
+degeerin
+detherai
+dingthin
+dryslyse
+dscesild
+ealecerm
+edftserh
+efosondi
+eherrreg
+emidesja
+ereananm
+estersns
+etedtili
+evermerh
+falsuran
+faringsi
+fawerist
+fcedethe
+fedhessh
+fedlerca
+feupbori
+ffeedift
+fllbasia
+foftabll
+fomehage
+fotsenki
+fwisudls
+ggeuptha
+gswofryt
+hedcecou
+hereacun
+huvedpth
+iabengre
+ianfovin
+iaresice
+iasmived
+idengedi
+ilftisut
+ilinefem
+imeorran
+imsstoft
+inararto
+indanrei
+ingelaly
+ingeored
+inmotiom
+inoatlfr
+inoviler
+insedihe
+intaspan
+intowade
+inyfeprt
+iobloinc
+ionepuse
+iourofig
+ireeingi
+irreland
+irsfandb
+isewhell
+isocisad
+isriacth
+istaverr
+ithmblet
+itoingri
+itongala
+itsgrint
+ivyttisa
+laltthea
+lanesmef
+lanonepi
+lerithay
+lllmeris
+lysatspa
+lysceert
+masishio
+mathmmat
+meastrei
+medengny
+medwindb
+membonam
+moronash
+mpeotlin
+msomirei
+msrmstri
+mstirtis
+nbempeef
+ncheckno
+nddtthec
+ndilymor
+nditheiv
+ndoncath
+nenkingo
+ngryasth
+nichelnd
+nndarrof
+nongeatt
+noviearc
+npecheca
+nsttmema
+nwiowhan
+oalsaldt
+obullury
+odtenens
+offorind
+ofoditin
+ogarofab
+olossofe
+olspooth
+omajorul
+omantrvi
+omawevat
+onotorit
+oorendbe
+oosarang
+othowong
+otinffte
+ouatheno
+ountshep
+ouputope
+owhesatu
+owiaindh
+padisath
+pangream
+pawicofa
+pendamam
+pepofond
+peroncti
+perysege
+petotith
+plocarov
+pomasbor
+powholyi
+ppllosof
+pptinoma
+psenesff
+puiondit
+reestand
+rendlabl
+rerathsy
+rewathat
+rirndiff
+ritricui
+samasome
+satameer
+sathecur
+sbespral
+sconbeis
+sedfinhe
+sharveon
+shhoftrd
+sianthem
+sieaveve
+simedera
+sinandff
+sinulsma
+sllobofl
+sndfermh
+soffatic
+soingris
+songiorb
+sthottsa
+suewemat
+swicales
+tagttisf
+tanalatt
+tancodbo
+tarethal
+tbisesia
+teftyall
+tengstwh
+tepeshth
+teranand
+tevinohi
+tgthehal
+thansirs
+thecequs
+thereaco
+therimut
+therorea
+thestiom
+theveame
+thhastth
+thiasatt
+thidirve
+thingbaa
+thithbed
+thovires
+thswenpe
+thublthe
+tiamarss
+tincthes
+tindtofo
+tinedave
+tisanwex
+tlarnste
+tleicorb
+tnymesie
+toftemal
+tombeasw
+torarsen
+totheheo
+toudanty
+tremywel
+treonove
+trhandfy
+trrhmont
+trysnter
+tssasofo
+ttemaith
+ttiserds
+ttorissa
+tuiabeoi
+twirfton
+tyhentha
+tyngorti
+tyoarich
+ucatbouc
+ungyconh
+untinore
+uopsaren
+upecmuit
+ureaidrb
+usinittr
+ussofedt
+usunochp
+utbapofo
+veveplel
+vimathea
+walondui
+wavairet
+waysioft
+wceempil
+wealttig
+wefondio
+werdtian
+weswevar
+whaclthe
+wheanler
+wheiforv
+whisurtr
+whrithat
+wiesulci
+wirofrec
+witthile
+wtserodr
+ybutherr
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile
new file mode 100644
index 000000000..348a8f818
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile
@@ -0,0 +1,43 @@
+#	@(#)Makefile	8.16 (Berkeley) 11/20/95
+
+ALL = driver2 tcreat3 tdel thash4 tread2 tseq tverify
+OBJ = driver2.o tcreat3.o tdel.o thash4.o tread2.o tseq.o tverify.o
+CC = gcc
+
+all: ${ALL}
+
+# Uncomment the STAT line get hash and btree statistical use info.  This
+# also forces ld to load the btree debug functions for use by gdb, which
+# is useful.  The db library has to be compiled with -DSTATISTICS as well.
+INC=	-I${PORTDIR}/include -I${PORTDIR}
+OORG=	-g
+#STAT=	-DSTATISTICS
+CFLAGS=	-D__DBINTERFACE_PRIVATE -DDEBUG ${STAT} ${OORG} ${INC}
+
+tcreat3: tcreat3.o ${PORTDIR}/libdb.a
+	${CC} -o $@ tcreat3.o ${PORTDIR}/libdb.a
+
+tdel: tdel.o ${PORTDIR}/libdb.a
+	${CC} -o $@ tdel.o ${PORTDIR}/libdb.a
+
+thash4: thash4.o ${PORTDIR}/libdb.a
+	${CC} -o $@ thash4.o ${PORTDIR}/libdb.a
+
+tread2: tread2.o ${PORTDIR}/libdb.a
+	${CC} -o $@ tread2.o ${PORTDIR}/libdb.a
+
+tseq: tseq.o ${PORTDIR}/libdb.a
+	${CC} -o $@ tseq.o ${PORTDIR}/libdb.a
+
+tverify: tverify.o ${PORTDIR}/libdb.a
+	${CC} -o $@ tverify.o ${PORTDIR}/libdb.a
+
+driver2: driver2.o ${PORTDIR}/libdb.a
+	${CC} -o $@ driver2.o ${PORTDIR}/libdb.a
+
+strerror.o: ${PORTDIR}/clib/strerror.c
+	${CC} -c ${PORTDIR}/clib/strerror.c
+
+clean:
+	rm -f *.core gmon.out ${ALL} ${OBJ} t1 t2 t3
+
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c
new file mode 100644
index 000000000..6a3b432cb
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)driver2.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * Test driver, to try to tackle the large ugly-split problem.
+ */
+
+#include <sys/file.h>
+#include <stdio.h>
+#include "ndbm.h"
+
+int my_hash(key, len)
+	char	*key;
+	int	len;
+{
+	return(17);		/* So I'm cruel... */
+}
+
+main(argc, argv)
+	int	argc;
+{
+	DB	*db;
+	DBT	key, content;
+	char	keybuf[2049];
+	char	contentbuf[2049];
+	char	buf[256];
+	int	i;
+	HASHINFO	info;
+
+	info.bsize = 1024;
+	info.ffactor = 5;
+	info.nelem = 1;
+	info.cachesize = NULL;
+#ifdef HASH_ID_PROGRAM_SPECIFIED
+	info.hash_id = HASH_ID_PROGRAM_SPECIFIED;
+	info.hash_func = my_hash;
+#else
+	info.hash = my_hash;
+#endif
+	info.lorder = 0;
+	if (!(db = dbopen("bigtest", O_RDWR | O_CREAT | O_BINARY, 0644, DB_HASH, &info))) {
+		sprintf(buf, "dbopen: failed on file bigtest");
+		perror(buf);
+		exit(1);
+	}
+	srand(17);
+	key.data = keybuf;
+	content.data = contentbuf;
+	memset(keybuf, '\0', sizeof(keybuf));
+	memset(contentbuf, '\0', sizeof(contentbuf));
+	for (i=1; i <= 500; i++) {
+		key.size = 128 + (rand()&1023);
+		content.size = 128 + (rand()&1023);
+/*		printf("%d: Key size %d, data size %d\n", i, key.size,
+		       content.size); */
+		sprintf(keybuf, "Key #%d", i);
+		sprintf(contentbuf, "Contents #%d", i);
+		if ((db->put)(db, &key, &content, R_NOOVERWRITE)) {
+			sprintf(buf, "dbm_store #%d", i);
+			perror(buf);
+		}
+	}
+	if ((db->close)(db)) {
+		perror("closing hash file");
+		exit(1);
+	}
+	exit(0);
+}
+
+	
+
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh
new file mode 100644
index 000000000..15901de19
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+#	@(#)makedb.sh	8.1 (Berkeley) 6/4/93
+
+awk '{i++; print $0; print i;}' /usr/local/lib/dict/words > WORDS
+ls /bin /usr/bin /usr/ucb /etc | egrep '^(...|....|.....|......)$' | \
+sort | uniq | \
+awk '{
+	printf "%s\n", $0
+	for (i = 0; i < 1000; i++)
+		printf "%s+", $0
+	printf "\n"
+}' > LONG.DATA
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c
new file mode 100644
index 000000000..f11487b32
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tcreat3.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include "db-int.h"
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key;
+	DB	*dbp;
+	HASHINFO ctl;
+	FILE *fp;
+	int	trash;
+
+	int i = 0;
+
+	argv++;
+	ctl.hash = NULL;
+	ctl.bsize = atoi(*argv++);
+	ctl.ffactor = atoi(*argv++);
+	ctl.nelem = atoi(*argv++);
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( "hashtest",
+	    O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0600, DB_HASH, &ctl))){
+		/* create table */
+		fprintf(stderr, "cannot create: hash table (size %d)\n",
+			INITIAL);
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+		if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+			fprintf(stderr, "cannot enter: key %s\n",
+				item.data);
+			exit(1);
+		}			
+	}
+
+	(dbp->close)(dbp);
+	exit(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c
new file mode 100644
index 000000000..826611486
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tdel.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include "db-int.h"
+#include <stdio.h>
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key;
+	DB	*dbp;
+	HASHINFO ctl;
+	FILE *fp;
+	int	stat;
+
+	int i = 0;
+
+	argv++;
+	ctl.nelem = INITIAL;
+	ctl.hash = NULL;
+	ctl.bsize = atoi(*argv++);
+	ctl.ffactor = atoi(*argv++);
+	ctl.cachesize = 1024 * 1024;	/* 1 MEG */
+	ctl.lorder = 0;
+	argc -= 2;
+	if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR|O_BINARY, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot create: hash table size %d)\n",
+			INITIAL);
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+		if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+			fprintf(stderr, "cannot enter: key %s\n",
+				item.data);
+			exit(1);
+		}			
+	}
+
+	if ( --argc ) {
+		fp = fopen ( argv[0], "r");
+		i = 0;
+		while ( fgets(wp1, 8192, fp) &&
+			fgets(wp2, 8192, fp) &&
+			i++ < MAXWORDS) {
+		    key.size = strlen(wp1);
+		    stat = (dbp->del)(dbp, &key, 0);
+		    if (stat) {
+			fprintf ( stderr, "Error retrieving %s\n", key.data );
+			exit(1);
+		    } 
+		}
+		fclose(fp);
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit
new file mode 100644
index 000000000..c80dc4e69
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit
@@ -0,0 +1,154 @@
+#!/bin/csh -f
+#
+#	@(#)testit	8.1 (Berkeley) 6/4/93
+#
+
+echo ""
+echo "PAGE FILL "
+set name=WORDS
+	set i = 256
+	foreach j ( 11 14 21 )
+	    echo "thash4 $i $j"
+	    ./thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 512
+	foreach j ( 21 28 43 )
+	    echo "thash4 $i $j"
+	    ./thash4 $i $j 25000 65536  $name < $name
+	end
+	set i = 1024
+	foreach j ( 43 57 85 )
+	    echo "thash4 $i $j"
+	    ./thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 2048
+	foreach j ( 85 114 171 )
+	    echo "thash4 $i $j"
+	    ./thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 4096
+	foreach j ( 171 228 341 )
+	    echo "thash4 $i $j"
+	    ./thash4 $i $j 25000 65536 $name < $name
+	end
+	set i = 8192
+	foreach j ( 341 455 683 )
+	    echo "thash4 $i $j"
+	    ./thash4 $i $j 25000 65536 $name < $name
+	end
+	echo "PAGE FILL "
+	set i = 256
+	foreach j ( 11 14 21 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 25000 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 512
+	foreach j ( 21 28 43 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 25000 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 1024
+	foreach j ( 43 57 85 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 25000 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 2048
+	foreach j ( 85 114 171 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 25000 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 4096
+	foreach j ( 171 228 341 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 25000 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 8192
+	foreach j ( 341 455 683 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 25000 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+set name=LONG.DATA
+	set i = 1024
+	foreach j ( 1 2 4 )
+	    echo ./thash4 $i $j 600 65536 $name 
+	    ./thash4 $i $j 600 65536 $name < $name
+	end
+
+	set i = 2048
+	foreach j ( 1 2 4 )
+	    echo ./thash4 $i $j 600 65536 $name 
+	    ./thash4 $i $j 600 65536 $name < $name
+	end
+	set i = 4096
+	foreach j ( 1 2 4 )
+	    echo ./thash4 $i $j 600 65536 $name 
+	    ./thash4 $i $j 600 65536 $name < $name
+	end
+	set i = 8192
+	foreach j ( 2 4 8 )
+	    echo ./thash4 $i $j 600 65536 $name 
+	    ./thash4 $i $j 600 65536 $name < $name
+	end
+	echo "PAGE FILL "
+	set i = 1024
+	foreach j ( 1 2 4 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 600 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 2048
+	foreach j ( 1 2 4 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 600 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 4096
+	foreach j ( 1 2 4 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 600 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+	set i = 8192
+	foreach j ( 2 4 8 )
+	    echo "$i"_"$j"
+	    ./tcreat3 $i $j 600 $name < $name
+	    ./tread2 65536 < $name
+	    ./tverify $name < $name
+	    ./tseq > /dev/null
+	    ./tdel $i $j  $name < $name
+	end
+
+./driver2
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c
new file mode 100644
index 000000000..b15b617bc
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)thash4.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <errno.h>
+#include "db-int.h"
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key, res;
+	DB *dbp;
+	HASHINFO ctl;
+	FILE *fp;
+	int	stat;
+	time_t	t;
+
+	int i = 0;
+
+	argv++;
+	ctl.hash = NULL;
+	ctl.bsize = atoi(*argv++);
+	ctl.ffactor = atoi(*argv++);
+	ctl.nelem = atoi(*argv++);
+	ctl.cachesize = atoi(*argv++);
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR|O_BINARY, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot create: hash table size %d)\n",
+			INITIAL);
+		fprintf(stderr, "\terrno: %d\n", errno);
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) && 
+		fgets(wp2, 8192, stdin) && 
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+		if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+			fprintf(stderr, "cannot enter: key %s\n",
+				item.data);
+			fprintf(stderr, "\terrno: %d\n", errno);
+			exit(1);
+		}			
+	}
+
+	if ( --argc ) {
+		fp = fopen ( argv[0], "r");
+		i = 0;
+		while ( fgets(wp1, 256, fp) && 
+			fgets(wp2, 8192, fp) && 
+			i++ < MAXWORDS) {
+
+		    key.size = strlen(wp1);
+		    stat = (dbp->get)(dbp, &key, &res, 0);
+		    if (stat < 0 ) {
+			fprintf ( stderr, "Error retrieving %s\n", key.data );
+			fprintf(stderr, "\terrno: %d\n", errno);
+			exit(1);
+		    } else if ( stat > 0 ) {
+			fprintf ( stderr, "%s not found\n", key.data );
+			fprintf(stderr, "\terrno: %d\n", errno);
+			exit(1);
+		    }
+		}
+		fclose(fp);
+	}
+	dbp->close(dbp);
+	exit(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c
new file mode 100644
index 000000000..1e2cc4c50
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tread2.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include "db-int.h"
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+typedef struct {		       /* info to be stored */
+	int num, siz;
+} info;
+
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key, res;
+	DB	*dbp;
+	HASHINFO ctl;
+	int	stat;
+
+	int i = 0;
+
+	ctl.nelem = INITIAL;
+	ctl.hash = NULL;
+	ctl.bsize = 64;
+	ctl.ffactor = 1;
+	ctl.cachesize = atoi(*argv++);
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( "hashtest", O_RDONLY|O_BINARY, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot open: hash table\n" );
+		exit(1);
+	}
+
+	key.data = wp1;
+	item.data = wp2;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+		item.size = strlen(wp2);
+
+		stat = (dbp->get)(dbp, &key, &res,0);
+		if (stat < 0) {
+		    fprintf ( stderr, "Error retrieving %s\n", key.data );
+		    exit(1);
+		} else if ( stat > 0 ) {
+		    fprintf ( stderr, "%s not found\n", key.data );
+		    exit(1);
+		}
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c
new file mode 100644
index 000000000..d2d36862d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tseq.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include "db-int.h"
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+
+char	wp[8192];
+char	cp[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT item, key, res;
+	DB	*dbp;
+	FILE *fp;
+	int	stat;
+
+	if (!(dbp = dbopen( "hashtest", O_RDONLY|O_BINARY, 0400, DB_HASH, NULL))) {
+		/* create table */
+		fprintf(stderr, "cannot open: hash table\n" );
+		exit(1);
+	}
+
+/*
+* put info in structure, and structure in the item
+*/
+	for ( stat = (dbp->seq) (dbp, &res, &item, 1 ); 
+	      stat == 0;
+	      stat = (dbp->seq) (dbp, &res, &item, 0 ) ) {
+
+	      memcpy ( wp, res.data, res.size );
+	      wp[res.size] = 0;
+	      memcpy ( cp, item.data, item.size );
+	      cp[item.size] = 0;
+
+	      printf ( "%s %s\n", wp, cp );
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c
new file mode 100644
index 000000000..4747804f7
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tverify.c	8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include "db-int.h"
+
+#define INITIAL	25000
+#define MAXWORDS    25000	       /* # of elements in search table */
+
+typedef struct {		       /* info to be stored */
+	int num, siz;
+} info;
+
+char	wp1[8192];
+char	wp2[8192];
+main(argc, argv)
+char **argv;
+{
+	DBT key, res;
+	DB	*dbp;
+	HASHINFO ctl;
+	int	trash;
+	int	stat;
+
+	int i = 0;
+
+	ctl.nelem = INITIAL;
+	ctl.hash = NULL;
+	ctl.bsize = 64;
+	ctl.ffactor = 1;
+	ctl.cachesize = 1024 * 1024;	/* 1 MEG */
+	ctl.lorder = 0;
+	if (!(dbp = dbopen( "hashtest", O_RDONLY|O_BINARY, 0400, DB_HASH, &ctl))) {
+		/* create table */
+		fprintf(stderr, "cannot open: hash table\n" );
+		exit(1);
+	}
+
+	key.data = wp1;
+	while ( fgets(wp1, 8192, stdin) &&
+		fgets(wp2, 8192, stdin) &&
+		i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+		key.size = strlen(wp1);
+
+		stat = (dbp->get)(dbp, &key, &res,0);
+		if (stat < 0) {
+		    fprintf ( stderr, "Error retrieving %s\n", key.data );
+		    exit(1);
+		} else if ( stat > 0 ) {
+		    fprintf ( stderr, "%s not found\n", key.data );
+		    exit(1);
+		}
+		if ( memcmp ( res.data, wp2, res.size ) ) {
+		    fprintf ( stderr, "data for %s is incorrect.  Data was %s.  Should have been %s\n", key.data, res.data, wp2 );
+		}
+	}
+	(dbp->close)(dbp);
+	exit(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/README b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/README
new file mode 100644
index 000000000..f29ccf7e1
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/README
@@ -0,0 +1,72 @@
+#	@(#)README	8.1 (Berkeley) 6/4/93
+
+This package implements a superset of the hsearch and dbm/ndbm libraries.
+
+Test Programs:
+	All test programs which need key/data pairs expect them entered
+	with key and data on separate lines
+
+	tcreat3.c	
+		Takes 
+			bucketsize (bsize), 
+			fill factor (ffactor), and
+			initial number of elements (nelem).  
+		Creates a hash table named hashtest containing the 
+		keys/data pairs entered from standard in.
+	thash4.c
+		Takes
+			bucketsize (bsize), 
+			fill factor (ffactor), 
+			initial number of elements (nelem)
+			bytes of cache (ncached), and
+			file from which to read data  (fname)
+		Creates a table from the key/data pairs on standard in and
+		then does a read of each key/data in fname
+	tdel.c
+		Takes
+			bucketsize (bsize), and
+			fill factor (ffactor).
+			file from which to read data (fname)
+		Reads each key/data pair from fname and deletes the
+		key from the hash table hashtest
+	tseq.c
+		Reads the key/data pairs in the file hashtest and writes them
+		to standard out.
+	tread2.c
+		Takes
+			butes of cache (ncached).
+		Reads key/data pairs from standard in and looks them up
+		in the file hashtest.
+	tverify.c
+		Reads key/data pairs from standard in, looks them up
+		in the file hashtest, and verifies that the data is
+		correct.
+
+NOTES:
+
+The file search.h is provided for using the hsearch compatible interface
+on BSD systems.  On System V derived systems, search.h should appear in 
+/usr/include.
+
+The man page ../man/db.3 explains the interface to the hashing system.
+The file hash.ps is a postscript copy of a paper explaining
+the history, implementation, and performance of the hash package.
+
+"bugs" or idiosyncracies
+
+If you have a lot of overflows, it is possible to run out of overflow
+pages.  Currently, this will cause a message to be printed on stderr.
+Eventually, this will be indicated by a return error code.
+
+If you are using the ndbm interface and exit without flushing or closing the
+file, you may lose updates since the package buffers all writes.  Also,
+the db interface only creates a single database file.  To avoid overwriting
+the user's original file, the suffix ".db" is appended to the file name
+passed to dbm_open.  Additionally, if your code "knows" about the historic
+.dir and .pag files, it will break.  
+
+There is a fundamental difference between this package and the old hsearch.
+Hsearch requires the user to maintain the keys and data in the application's
+allocated memory while hash takes care of all storage management.  The down
+side is that the byte strings passed in the ENTRY structure must be null
+terminated (both the keys and the data).
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c
new file mode 100644
index 000000000..81c559ad2
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c
@@ -0,0 +1,76 @@
+#include "db-int.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <stdlib.h>
+
+int
+main(void)
+{
+	HASHINFO info;
+	DB *db;
+	DBT key, value, returned;
+	int *data;
+	int n, i;
+
+	info.bsize = 512;
+	info.cachesize = 500;
+	info.lorder = 0;
+	info.ffactor = 4;
+	info.nelem = 0;
+	info.hash = NULL;
+
+	db = dbopen("big2.db", O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0664, DB_HASH, &info);
+	data = malloc(800 * sizeof(int));
+	for (n = 0; n < 800; n++)
+		data[n] = 0xDEADBEEF;
+	key.size = sizeof(int);
+	key.data = &n;
+	value.size = 800 * sizeof(int);
+	value.data = (void *)data;
+
+	for (n = 0; n < 200000; n++) {
+		returned.data = NULL;
+		if (n == 4627)
+			printf("");
+		if (n % 50 == 0) 
+			printf("put n = %d\n", n);
+		if (db->put(db, &key, &value, 0) != 0)	
+			printf("put error, n = %d\n", n);
+		if (db->get(db, &key, &returned, 0) != 0)
+			printf("Immediate get error, n = %d\n", n);
+		assert (returned.size == 3200);
+		for (i = 0; i < 800; i++)
+			if (((int *)returned.data)[i] != 0xDEADBEEF)
+				printf("ERRORRRRRR!!!\n");
+
+	}
+
+	for (n = 0; n < 200000; n++) {
+		if (n % 50 == 0) 
+			printf("seq n = %d\n", n);
+		if ((db->seq(db, &key, &returned, 0)) != 0)
+			printf("Seq error, n = %d\n", n);
+
+		assert(returned.size == 3200);
+
+		for (i = 0; i < 800; i++)
+			if (((int *)returned.data)[i] != 0xDEADBEEF)
+				printf("ERRORRRRRR!!! seq %d\n", n);
+	}		
+
+	for (n = 0; n < 2000; n++) {
+		if (n % 50 == 0) 
+			printf("get n = %d\n", n);
+		if (db->get(db, &key, &returned, 0) != 0)
+			printf("Late get error, n = %d\n", n);
+		assert(returned.size == 1200);
+		for (i = 0; i < 300; i++)
+			if (((int *)returned.data)[i] != 0xDEADBEEF)
+				printf("ERRORRRRRR!!!, get %d\n", n);
+	}
+   	db->close(db);
+	free(value.data);
+	return(0);
+}
+
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c
new file mode 100644
index 000000000..adb72c004
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c
@@ -0,0 +1,184 @@
+#include "db-int.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+extern int hash_expansions;
+
+int
+main(void)
+{
+    FILE *keys, *vals;
+    DB *db;
+    DBT key, val;
+    char *key_line, *val_line, *get_key, *get_val, *old, *key2;
+    HASHINFO passwd;
+    int n = 0, i = 0, expected;
+   
+    key_line = (char *)malloc(100);
+    val_line = (char *)malloc(300);
+    old = (char *)malloc(300);
+
+    keys = fopen("yp.keys", "rt");
+    vals = fopen("yp.total", "rt");
+
+    passwd.bsize =  1024;
+    passwd.cachesize = 1024 * 1024;
+    passwd.ffactor = 10;
+    passwd.hash = NULL;
+    passwd.nelem = 0;
+    passwd.lorder = 4321;
+	
+
+    db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0664, DB_HASH, 
+		&passwd);
+    if (!db) {
+	fprintf(stderr, "create_db: couldn't create database file\n");
+	exit(1);
+    }
+ 
+    while ((key_line = fgets(key_line, 100, keys)) != NULL) {
+	if (n % 1000 == 0)
+	  fprintf(stderr, "Putting #%d.\n", n);
+	n++;
+	fgets(val_line, 300, vals);
+	key.size = strlen(key_line);
+	key.data = (void *)key_line;
+	val.size = strlen(val_line);
+	val.data = (void *)val_line;
+	if (db->put(db, &key, &val, 0) != 0)
+	  fprintf(stderr, "Put error, n = %d\n", n);
+	if (db->get(db, &key, &val, 0) != 0)
+	  fprintf(stderr, "Immediate get error, n = %d\n", n);
+    }
+    fprintf(stderr, "Done with put!\n");
+    free(key_line);	
+    free(val_line);
+    fclose(keys);
+    fclose(vals);
+    db->close(db);
+
+
+
+	
+    keys = fopen("yp.keys", "rt");
+    vals = fopen("yp.total", "rt");
+    get_key = (char *)malloc(100);
+    get_val = (char *)malloc(300);
+
+    db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_BINARY, 0664, DB_HASH, &passwd);
+    if (!db)
+      fprintf(stderr, "Could not open db!\n");
+    n = 0;
+    while ((get_key = fgets(get_key, 100, keys)) != NULL) {
+	n++;
+	if (n % 1000 == 0)
+	  fprintf(stderr, "Getting #%d.\n", n);
+	key.size = strlen(get_key);
+	key.data = (void *)get_key;
+	if (db->get(db, &key, &val, 0) != 0)
+	  fprintf(stderr, "Retrieval error on %s\n", get_key);
+	fgets(get_val, 300, vals);
+	if (memcmp(val.data, (void *)get_val, val.size)) {
+	    fprintf(stderr, "Unmatched get on %s.\n", get_key);
+	    fprintf(stderr, "Input = %s\nOutput = %s\n", get_val, 
+		    (char *)val.data);
+	}
+    }
+    expected = n;
+    fclose(vals);
+    fclose(keys);
+    free(get_key);
+    free(get_val);
+    db->close(db);
+
+
+
+
+    get_key = (char *)malloc(100);
+    get_val = (char *)malloc(300);
+
+    db = dbopen("/usr/tmp/passwd.db", O_RDWR, 0664, DB_HASH, &passwd);
+    if (!db)
+      fprintf(stderr, "Could not open db!\n");
+    n = 0;
+    for (;;) {
+	n++;
+	if (n % 1000 == 0)
+	  fprintf(stderr, "Sequence getting #%d.\n", n);
+	if (db->seq(db, &key, &val, 0) != 0) {
+	    fprintf(stderr, 
+		    "Exiting sequence retrieve; n = %d, expected = %d\n",
+		    n - 1 , expected);
+	    break;
+	}
+    }
+    free(get_key);
+    free(get_val);
+    db->close(db);
+
+    get_key = (char *)malloc(100);
+    key2 = (char *)malloc(100);
+
+    keys = fopen("yp.keys", "rt");
+    vals = fopen("yp.total", "rt");
+
+    db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_BINARY, 0664, DB_HASH, &passwd);
+    n = 0;
+    while ((get_key = fgets(get_key, 100, keys)) != NULL) {
+	if (n % 1000 == 0)
+	  fprintf(stderr, "Deleting #%d.\n", n);
+	n+=2;
+	key2 = fgets(get_key, 100, keys);
+	if (!key2)
+	  break;	
+	key.data = (void *)key2;
+	key.size = strlen(key2);
+	if (db->del(db, &key, 0) != 0)
+	  fprintf(stderr, "Delete error on %d", n);
+    }
+
+    db->close(db);
+    free(get_key);
+    free(key2);
+    fclose(keys);
+    fclose(vals);
+
+    get_key = (char *)malloc(100);
+    key2 = (char *)malloc(100);
+    get_val = (char *)malloc(300);
+
+    keys = fopen("yp.keys", "rt");
+    vals = fopen("yp.total", "rt");
+	
+    db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_BINARY, 0664, DB_HASH, &passwd);
+    n = 0;
+    while ((get_key = fgets(get_key, 100, keys)) != NULL) {
+	n += 2;
+	if (n % 1000 == 0)
+	  fprintf(stderr, "Re-retrieving #%d.\n", n);
+	key2 = fgets(key2, 100, keys);
+	if (!key2)
+	  break;
+	key.data = (void *)get_key;	
+	key.size = strlen(get_key);
+	if (db->get(db, &key, &val, 0) != 0)	
+	  fprintf(stderr, "Retrieval after delete error on %d\n", n);
+	fgets(get_val, 300, vals);
+	if (memcmp(val.data, (void *)get_val, val.size)) {
+	    fprintf(stderr, "Unmatched get after delete on %s.\n", get_key);
+	    fprintf(stderr, "Input = %s\nOutput = %s\n", get_val, 
+		    (char *)val.data);
+	}
+	fgets(get_val, 300, vals);
+    }
+
+    db->close(db);
+    free(get_key);
+    free(key2);
+    free(get_val);
+    fclose(keys);
+    fclose(vals);
+
+    exit(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c
new file mode 100644
index 000000000..da3767687
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+main(int argc, char **argv)
+{
+	int i,j,n;
+	char *pass[8], r;
+	
+	n = atoi(argv[1]);
+
+	srandom(101173);
+	for (i = 0; i < n; i++) {
+		for (j = 0; j < 8; j++) {
+			r = random() % 122;
+			while (r < 48)
+				r += random() % (122 - r);
+			printf("%c", r);
+		}
+		printf("\n");
+	}
+}
+
diff --git a/krb5-1-6/src/plugins/kdb/db2/libdb2/test/run.test b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/run.test
new file mode 100644
index 000000000..48c3a63d0
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/libdb2/test/run.test
@@ -0,0 +1,746 @@
+#!/bin/sh -
+#
+#	@(#)run.test	8.13 (Berkeley) 11/2/95
+#
+
+# db regression tests
+main()
+{
+
+	PROG=./dbtest
+	TMP1=${TMPDIR-.}/t1
+	TMP2=${TMPDIR-.}/t2
+	TMP3=${TMPDIR-.}/t3
+
+	if [ \! -z "$WORDLIST" -a -f "$WORDLIST" ]; then
+		DICT=$WORDLIST
+	elif [ -f /usr/local/lib/dict/words ]; then
+		DICT=/usr/local/lib/dict/words
+	elif [ -f /usr/share/dict/words ]; then
+		DICT=/usr/share/dict/words
+	elif [ -f /usr/dict/words ]; then
+		DICT=/usr/dict/words
+	elif [ -f /usr/share/lib/dict/words ]; then
+		DICT=/usr/share/lib/dict/words
+	elif [ -f $srcdir/../test/dictionary ]; then
+		DICT=`cd $srcdir/../test && pwd`/dictionary
+	else
+		echo 'run.test: no dictionary'
+		exit 1
+	fi
+	
+	dictsize=`wc -l < $DICT`
+
+	bindir=/bin/.
+
+	if [ $# -eq 0 ]; then
+		for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
+			test$t
+		done
+	else
+		while [ $# -gt 0 ]
+			do case "$1" in
+			test*)
+				$1;;
+			[0-9]*)
+				test$1;;
+			btree)
+				for t in 1 2 3 7 8 9 10 12 13; do
+					test$t
+				done;;
+			hash)
+				for t in 1 2 3 8 13 20; do
+					test$t
+				done;;
+			recno)
+				for t in 1 2 3 4 5 6 7 10 11; do
+					test$t
+				done;;
+			*)
+				echo "run.test: unknown test $1"
+				echo "usage: run.test test# | type"
+				exit 1
+			esac
+			shift
+		done
+	fi
+	rm -f $TMP1 $TMP2 $TMP3
+	exit 0
+}
+
+getnwords() {
+	# Delete blank lines because the db code appears not to
+	# like empty keys.  On Debian Linux, $DICT appears to contain
+	# some non-ASCII characters, and "rev" chokes on them.
+	sed -e '/^$/d' < $DICT | cat -v | sed -e ${1}q
+}
+
+# Take the first hundred entries in the dictionary, and make them
+# be key/data pairs.
+test1()
+{
+	echo "Test 1: btree, hash: small key, small data pairs"
+	getnwords 200 > $TMP1
+	for type in btree hash; do
+		rm -f $TMP2 $TMP3
+		for i in `cat $TMP1`; do
+			echo p
+			echo k$i
+			echo d$i
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test1: type $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 1: recno: small key, small data pairs"
+	rm -f $TMP2 $TMP3
+	awk '{ 
+		++i;
+		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+	}' < $TMP1 > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test1: type recno: failed"
+		exit 1
+	fi
+}
+
+# Take the first 200 entries in the dictionary, and give them
+# each a medium size data entry.
+test2()
+{
+	echo "Test 2: btree, hash: small key, medium data pairs"
+	mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+	echo $mdata |
+	awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1
+	for type in hash btree; do
+		rm -f $TMP2 $TMP3
+		for i in `getnwords 200`; do
+			echo p
+			echo k$i
+			echo d$mdata
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test2: type $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 2: recno: small key, medium data pairs"
+	rm -f $TMP2 $TMP3
+	echo $mdata | 
+	awk '{  for (i = 1; i < 201; ++i)
+		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test2: type recno: failed"
+		exit 1
+	fi
+}
+
+# Insert the programs in $bindir with their paths as their keys.
+test3()
+{
+	echo "Test 3: hash: small key, big data pairs"
+	rm -f $TMP1
+	(find $bindir -type f -exec test -r {} \; -print | xargs cat) > $TMP1
+	for type in hash; do
+		rm -f $TMP2 $TMP3
+		for i in `find $bindir -type f -exec test -r {} \; -print`; do
+			echo p
+			echo k$i
+			echo D$i
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test3: $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 3: btree: small key, big data pairs"
+	for psize in 512 16384 65536; do
+		echo "    page size $psize"
+		for type in btree; do
+			rm -f $TMP2 $TMP3
+			for i in `find $bindir -type f -exec test -r {} \; -print`; do
+				echo p
+				echo k$i
+				echo D$i
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -i psize=$psize -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test3: $type: page size $psize: failed"
+				exit 1
+			fi
+		done
+	done
+	echo "Test 3: recno: big data pairs"
+	rm -f $TMP2 $TMP3
+	find $bindir -type f -exec test -r {} \; -print | 
+	awk '{
+		++i;
+		printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	for psize in 512 16384 65536; do
+		echo "    page size $psize"
+		$PROG -i psize=$psize -o $TMP3 recno $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test3: recno: page size $psize: failed"
+			exit 1
+		fi
+	done
+}
+
+# Do random recno entries.
+test4()
+{
+	echo "Test 4: recno: random entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 37; i <= 37 + 88 * 17; i += 17) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 1; i <= 15; ++i) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 37;
+			incr = 17;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			if (i == 19234 + 61 * 27)
+				exit;
+			if (i == 37 + 88 * 17) {
+				i = 1;
+				incr = 1;
+			} else if (i == 15) {
+				i = 19234;
+				incr = 27;
+			} else
+				i += incr;
+		}
+		END {
+			for (i = 37; i <= 37 + 88 * 17; i += 17)
+				printf("g\nk%d\n", i);
+			for (i = 1; i <= 15; ++i)
+				printf("g\nk%d\n", i);
+			for (i = 19234; i <= 19234 + 61 * 27; i += 27)
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test4: type recno: failed"
+		exit 1
+	fi
+}
+
+# Do reverse order recno entries.
+test5()
+{
+	echo "Test 5: recno: reverse order entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk ' {
+		for (i = 1500; i; --i) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 1500;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			--i;
+		}
+		END {
+			for (i = 1500; i; --i) 
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test5: type recno: failed"
+		exit 1
+	fi
+}
+		
+# Do alternating order recno entries.
+test6()
+{
+	echo "Test 6: recno: alternating order entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk ' {
+		for (i = 1; i < 1200; i += 2) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 2; i < 1200; i += 2) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 1;
+			even = 0;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			i += 2;
+			if (i >= 1200) {
+				if (even == 1)
+					exit;
+				even = 1;
+				i = 2;
+			}
+		}
+		END {
+			for (i = 1; i < 1200; ++i) 
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	sort -o $TMP1 $TMP1
+	sort -o $TMP3 $TMP3
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test6: type recno: failed"
+		exit 1
+	fi
+}
+
+# Delete cursor record
+test7()
+{
+	echo "Test 7: btree, recno: delete cursor record"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 120; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		printf("%05d: input key %d: %s\n", 120, 120, $0);
+		printf("seq failed, no such key\n");
+		printf("%05d: input key %d: %s\n", 1, 1, $0);
+		printf("%05d: input key %d: %s\n", 2, 2, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 120)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_NEXT\n");
+			for (i = 1; i <= 120; ++i)
+				printf("s\n");
+			printf("fR_CURSOR\ns\nk120\n");
+			printf("r\n");
+			printf("fR_NEXT\ns\n");
+			printf("fR_CURSOR\ns\nk1\n");
+			printf("r\n");
+			printf("fR_FIRST\ns\n");
+		}' > $TMP2
+		$PROG -o $TMP3 recno $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test7: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Make sure that overflow pages are reused.
+test8()
+{
+	echo "Test 8: btree: repeated small key, big data pairs"
+	rm -f $TMP1
+	echo "" | 
+	awk 'BEGIN {
+		for (i = 1; i <= 10; ++i) {
+			printf("p\nkkey1\nD/bin/sh\n");
+			printf("p\nkkey2\nD/bin/csh\n");
+			if (i % 8 == 0) {
+				printf("c\nkkey2\nD/bin/csh\n");
+				printf("c\nkkey1\nD/bin/sh\n");
+				printf("e\t%d of 10 (comparison)\n", i);
+			} else
+				printf("e\t%d of 10             \n", i);
+			printf("r\nkkey1\nr\nkkey2\n");
+		}
+	}' > $TMP1
+	if $PROG btree $TMP1 ; then
+	    true
+	else
+	    echo "test8: btree tests failed"
+	    exit 1
+	fi
+#	$PROG hash $TMP1
+	# No explicit test for success.
+}
+
+# Test btree duplicate keys
+test9()
+{
+	echo "Test 9: btree: duplicate keys"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 543; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in btree; do
+		cat $TMP1 | 
+		awk '{
+			if (i++ % 2)
+				printf("p\nkduplicatekey\nd%s\n", $0);
+			else
+				printf("p\nkunique%dkey\nd%s\n", i, $0);
+		}
+		END {
+				printf("o\n");
+		}' > $TMP2
+		$PROG -iflags=1 -o $TMP3 $type $TMP2
+		sort -o $TMP3 $TMP3
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test9: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Test use of cursor flags without initialization
+test10()
+{
+	echo "Test 10: btree, recno: test cursor flag use"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 20; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	# Test that R_CURSOR doesn't succeed before cursor initialized
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 10)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_CURSOR\nr\n");
+			printf("eR_CURSOR SHOULD HAVE FAILED\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+		if [ -s $TMP3 ] ; then
+			echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED"
+			exit 1
+		fi
+	done
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 10)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_CURSOR\np\nk1\ndsome data\n");
+			printf("eR_CURSOR SHOULD HAVE FAILED\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+		if [ -s $TMP3 ] ; then
+			echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED"
+			exit 1
+		fi
+	done
+}
+
+# Test insert in reverse order.
+test11()
+{
+	echo "Test 11: recno: reverse order insert"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 779; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 0) {
+				i = 1;
+				printf("p\nk1\nd%s\n", $0);
+				printf("%s\n", "fR_IBEFORE");
+			} else
+				printf("p\nk1\nd%s\n", $0);
+		}
+		END {
+				printf("or\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test11: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Take the first 20000 entries in the dictionary, reverse them, and give
+# them each a small size data entry.  Use a small page size to make sure
+# the btree split code gets hammered.
+test12()
+{
+	if ( rev < /dev/null ) > /dev/null 2>&1 ; then
+		:
+	else
+		echo "Test 12: skipped, rev not found"
+		return
+	fi
+	if test $dictsize -lt 20001 ; then
+		echo "Test 12: skipped, dictionary too small"
+		return
+	else
+		:
+	fi
+	echo "Test 12: btree: lots of keys, small page size"
+	mdata=abcdefghijklmnopqrstuvwxy
+	echo $mdata |
+	awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1
+	for type in btree; do
+		rm -f $TMP2 $TMP3
+		for i in `getnwords 20000 | rev`; do
+			echo p
+			echo k$i
+			echo d$mdata
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -i psize=512 -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test12: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Test different byte orders.
+test13()
+{
+	echo "Test 13: btree, hash: differing byte orders"
+	getnwords 50 > $TMP1
+	for order in 1234 4321; do
+		for type in btree hash; do
+			rm -f byte.file $TMP2 $TMP3
+			for i in `cat $TMP1`; do
+				echo p
+				echo k$i
+				echo d$i
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test13: $type/$order put failed"
+				exit 1
+			fi
+			for i in `cat $TMP1`; do
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -s \
+			    -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test13: $type/$order get failed"
+				exit 1
+			fi
+		done
+	done
+	rm -f byte.file
+}
+
+# Try a variety of bucketsizes and fill factors for hashing
+test20()
+{
+	if test $dictsize -lt 10001 ; then
+		echo "Test 20: skipped, dictionary too small"
+		return
+	else
+		:
+	fi
+	echo\
+    "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 10000; ++i) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("%s\n", s);
+		}
+		exit;
+	}' > $TMP1
+	getnwords 10000 |
+	awk 'BEGIN {
+		ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg"
+	}
+	{
+		if (++i % 34)
+			s = substr(ds, 1, i % 34);
+		else
+			s = substr(ds, 1);
+		printf("p\nk%s\nd%s\n", $0, s);
+	}' > $TMP2
+	getnwords 10000 |
+	awk '{
+		++i;
+		printf("g\nk%s\n", $0);
+	}' >> $TMP2
+	bsize=256
+	for ffactor in 11 14 21; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=512
+	for ffactor in 21 28 43; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=1024
+	for ffactor in 43 57 85; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=2048
+	for ffactor in 85 114 171; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=4096
+	for ffactor in 171 228 341; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=8192
+	for ffactor in 341 455 683; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+}
+
+main $*
diff --git a/krb5-1-6/src/plugins/kdb/db2/pol_xdr.c b/krb5-1-6/src/plugins/kdb/db2/pol_xdr.c
new file mode 100644
index 000000000..43eac32df
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/pol_xdr.c
@@ -0,0 +1,89 @@
+#include <sys/types.h>
+#include <krb5.h>
+#include <gssrpc/rpc.h>
+#include <kdb.h>
+#include "policy_db.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+static 
+bool_t xdr_nullstring(XDR *xdrs, char **objp)
+{
+     u_int size;
+                                                                                                                            
+     if (xdrs->x_op == XDR_ENCODE) {
+          if (*objp == NULL)
+               size = 0;
+          else
+               size = strlen(*objp) + 1;
+     }
+     if (! xdr_u_int(xdrs, &size)) {
+          return FALSE;
+        }
+     switch (xdrs->x_op) {
+     case XDR_DECODE:
+          if (size == 0) {
+               *objp = NULL;
+               return TRUE;
+          } else if (*objp == NULL) {
+               *objp = (char *) mem_alloc(size);
+               if (*objp == NULL) {
+                    errno = ENOMEM;
+                    return FALSE;
+               }
+          }
+          return (xdr_opaque(xdrs, *objp, size));
+                                                                                                                            
+     case XDR_ENCODE:
+          if (size != 0)
+               return (xdr_opaque(xdrs, *objp, size));
+          return TRUE;
+                                                                                                                            
+     case XDR_FREE:
+          if (*objp != NULL)
+               mem_free(*objp, size);
+          *objp = NULL;
+          return TRUE;
+     }
+                                                                                                                            
+     return FALSE;
+}
+                                                                                                                            
+
+
+bool_t
+xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp)
+{
+    switch (xdrs->x_op) {
+    case XDR_ENCODE:
+	 objp->version = OSA_ADB_POLICY_VERSION_1;
+	 /* fall through */
+    case XDR_FREE:
+	 if (!xdr_int(xdrs, &objp->version))
+	      return FALSE;
+	 break;
+    case XDR_DECODE:
+	 if (!xdr_int(xdrs, &objp->version))
+	      return FALSE;
+	 if (objp->version != OSA_ADB_POLICY_VERSION_1)
+	      return FALSE;
+	 break;
+    }
+    
+    if(!xdr_nullstring(xdrs, &objp->name))
+	return (FALSE);
+    if (!xdr_u_int32(xdrs, &objp->pw_min_life))
+	return (FALSE);
+    if (!xdr_u_int32(xdrs, &objp->pw_max_life))
+	return (FALSE);
+    if (!xdr_u_int32(xdrs, &objp->pw_min_length))
+	return (FALSE);
+    if (!xdr_u_int32(xdrs, &objp->pw_min_classes))
+	return (FALSE);
+    if (!xdr_u_int32(xdrs, &objp->pw_history_num))
+	return (FALSE);
+    if (!xdr_u_int32(xdrs, &objp->policy_refcnt))
+	return (FALSE);
+    return (TRUE);
+}
diff --git a/krb5-1-6/src/plugins/kdb/db2/policy_db.h b/krb5-1-6/src/plugins/kdb/db2/policy_db.h
new file mode 100644
index 000000000..11fece3df
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/db2/policy_db.h
@@ -0,0 +1,101 @@
+/*
+ * Data Types for policy and principal information that
+ * exists in the respective databases.
+ *
+ * $Header$
+ *
+ * This file was originally created with rpcgen.
+ * It has been hacked up since then.
+ */
+
+#ifndef __ADB_H__
+#define __ADB_H__
+#include <sys/types.h>
+#include <errno.h>
+#include <krb5.h>
+#include <kdb.h>
+/* Okay, this is a bit obscure.  The libdb2 configure script doesn't
+   detect it, but on Tru64 5.1, netinet/in.h causes sys/bittypes.h to
+   be included, and that has a typedef for u_int32_t.  Because the
+   configure script doesn't detect it, it causes db-config.h to have a
+   #define for u_int32_t, so including db.h and then netinet/in.h
+   causes compilation to fail.
+
+   Since gssrpc/types.h includes netinet/in.h, including that first
+   will cause the typedef to be seen before the macro definition,
+   which still isn't quite right, but is close enough for now.
+
+   A better fix might be for db.h to include netinet/in.h if that's
+   where we find u_int32_t.  */
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include <db.h>
+#include "adb_err.h"
+#include <com_err.h>
+
+typedef	long		osa_adb_ret_t;
+
+#define OSA_ADB_POLICY_DB_MAGIC	0x12345A00
+
+#define OSA_ADB_POLICY_VERSION_MASK	0x12345D00
+#define OSA_ADB_POLICY_VERSION_1	0x12345D01
+
+
+
+typedef struct _osa_adb_db_lock_ent_t {
+     FILE     *lockfile;
+     char     *filename;
+     int      refcnt, lockmode, lockcnt;
+     krb5_context context;
+} osa_adb_lock_ent, *osa_adb_lock_t;
+
+typedef struct _osa_adb_db_ent_t {
+     int        magic;
+     DB         *db;
+     HASHINFO   info;
+     BTREEINFO  btinfo;
+     char       *filename;
+     osa_adb_lock_t lock;
+     int        opencnt;
+} osa_adb_db_ent, *osa_adb_db_t, *osa_adb_princ_t, *osa_adb_policy_t;
+
+/*
+ * Return Code (the rest are in adb_err.h)
+ */
+ 
+#define OSA_ADB_OK		0
+
+/*
+ * Functions
+ */
+
+krb5_error_code	osa_adb_create_db(char *filename, char *lockfile, int magic);
+krb5_error_code	osa_adb_destroy_db(char *filename, char *lockfile, int magic);
+krb5_error_code   osa_adb_rename_db(char *filefrom, char *lockfrom,
+				  char *fileto, char *lockto, int magic);
+krb5_error_code	osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
+				char *lockfile, int magic);
+krb5_error_code	osa_adb_fini_db(osa_adb_db_t db, int magic);
+krb5_error_code	osa_adb_get_lock(osa_adb_db_t db, int mode);
+krb5_error_code	osa_adb_release_lock(osa_adb_db_t db);
+krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype);
+krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db);
+krb5_error_code	osa_adb_close_policy(osa_adb_policy_t db);
+krb5_error_code	osa_adb_create_policy(osa_adb_policy_t db,
+				      osa_policy_ent_t entry);
+krb5_error_code	osa_adb_destroy_policy(osa_adb_policy_t db,
+				       char * name);
+krb5_error_code	osa_adb_get_policy(osa_adb_policy_t db,
+				   char * name,
+				   osa_policy_ent_t *entry,
+				   int *cnt);
+krb5_error_code	osa_adb_put_policy(osa_adb_policy_t db,
+				   osa_policy_ent_t entry);
+krb5_error_code	osa_adb_iter_policy(osa_adb_policy_t db,
+				    osa_adb_iter_policy_func func,
+				    void * data);
+void		osa_free_policy_ent(osa_policy_ent_t val);
+
+bool_t  xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp);
+
+#endif /* __ADB_H__ */
diff --git a/krb5-1-6/src/plugins/kdb/ldap/Makefile.in b/krb5-1-6/src/plugins/kdb/ldap/Makefile.in
new file mode 100644
index 000000000..323d4a568
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/Makefile.in
@@ -0,0 +1,65 @@
+thisconfigdir=../../..
+myfulldir=plugins/kdb/ldap
+mydir=plugins/kdb/ldap
+BUILDTOP=$(REL)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS =
+MODULE_INSTALL_DIR = $(KRB5_DB_MODULE_DIR)
+
+LOCAL_SUBDIRS= libkdb_ldap ldap_util
+
+LOCALINCLUDES = -I../../../lib/kdb -I$(srcdir)/../../../lib/kdb \
+	-I$(srcdir)/libkdb_ldap
+
+LIBBASE=kldap
+LIBMAJOR=0
+LIBMINOR=0
+SO_EXT=.so
+RELDIR=../plugins/kdb/ldap
+# Depends on libk5crypto and libkrb5
+# Also on gssrpc, for xdr stuff.
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libkdb_ldap$(SHLIBEXT) \
+	$(GSSRPC_DEPLIBS) \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT) \
+	$(TOPLIBD)/lib$(SUPPORT_LIBNAME)$(SHLIBEXT)
+SHLIB_EXPLIBS= -lkdb_ldap $(GSSRPC_LIBS) -lkrb5 -lcom_err -lk5crypto -lkrb5support $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+$(TOPLIBD)/libkdb_ldap$(SHLIBEXT): all-recurse
+
+SRCS= 	$(srcdir)/ldap_exp.c
+
+STOBJLISTS=OBJS.ST
+STLIBOBJS= ldap_exp.o
+
+all-unix:: $(LIBBASE)$(SO_EXT)
+install-unix:: install-libs
+clean-unix:: clean-libs clean-libobjs
+
+@libnover_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+ldap_exp.so ldap_exp.po $(OUTPRE)ldap_exp.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  $(srcdir)/libkdb_ldap/kdb_ldap.h $(srcdir)/libkdb_ldap/ldap_krbcontainer.h \
+  $(srcdir)/libkdb_ldap/ldap_principal.h $(srcdir)/libkdb_ldap/ldap_pwd_policy.h \
+  $(srcdir)/libkdb_ldap/ldap_realm.h $(srcdir)/libkdb_ldap/ldap_tkt_policy.h \
+  ldap_exp.c
diff --git a/krb5-1-6/src/plugins/kdb/ldap/kldap.exports b/krb5-1-6/src/plugins/kdb/ldap/kldap.exports
new file mode 100644
index 000000000..f2b7c1119
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/kldap.exports
@@ -0,0 +1 @@
+kdb_function_table
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_exp.c b/krb5-1-6/src/plugins/kdb/ldap/ldap_exp.c
new file mode 100644
index 000000000..eaeef2a8c
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_exp.c
@@ -0,0 +1,88 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_exp.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <utime.h>
+#include <kdb5.h>
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "ldap_pwd_policy.h"
+
+
+/*
+ *      Exposed API
+ */
+
+kdb_vftabl kdb_function_table = {
+  1,                                      /* major version number 1 */
+  0,                                      /* minor version number 0 */
+  /* init_library */			       krb5_ldap_lib_init,
+  /* fini_library */			       krb5_ldap_lib_cleanup,
+  /* init_module */			       krb5_ldap_open,
+  /* fini_module */			       krb5_ldap_close,
+  /* db_create */			       krb5_ldap_create,
+  /* db_destroy */			       krb5_ldap_delete_realm_1,
+  /* db_get_age */                             krb5_ldap_db_get_age,
+  /* db_set_option */			       krb5_ldap_set_option,
+  /* db_lock */				       krb5_ldap_lock,
+  /* db_unlock */			       krb5_ldap_unlock,
+  /* db_get_principal */		       krb5_ldap_get_principal,
+  /* db_free_principal */		       krb5_ldap_free_principal,
+  /* db_put_principal */		       krb5_ldap_put_principal,
+  /* db_delete_principal */		       krb5_ldap_delete_principal,
+  /* db_iterate */			       krb5_ldap_iterate,
+  /* db_create_policy */                       krb5_ldap_create_password_policy,
+  /* db_get_policy */                          krb5_ldap_get_password_policy,
+  /* db_put_policy */                          krb5_ldap_put_password_policy,
+  /* db_iter_policy */                         krb5_ldap_iterate_password_policy,
+  /* db_delete_policy */                       krb5_ldap_delete_password_policy,
+  /* db_free_policy */                         krb5_ldap_free_password_policy,
+  /* db_supported_realms */		       krb5_ldap_supported_realms,
+  /* db_free_supported_realms */	       krb5_ldap_free_supported_realms,
+  /* errcode_2_string */                       krb5_ldap_errcode_2_string,
+  /* release_errcode_string */		       krb5_ldap_release_errcode_string,
+  /* db_alloc */                               krb5_ldap_alloc,
+  /* db_free */                                krb5_ldap_free,
+            /* optional functions */
+  /* set_master_key */			       krb5_ldap_set_mkey,
+  /* get_master_key */			       krb5_ldap_get_mkey,
+  /* setup_master_key_name */		       NULL,
+  /* store_master_key */		       NULL,
+  /* fetch_master_key */		       NULL /* krb5_ldap_fetch_mkey */,
+  /* verify_master_key */		       NULL /* krb5_ldap_verify_master_key */,
+  /* Search enc type */                        NULL,
+  /* Change pwd   */                           NULL
+
+};
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/ChangeLog b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/ChangeLog
new file mode 100644
index 000000000..b72a851c2
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/ChangeLog
@@ -0,0 +1,12 @@
+2006-04-08  Ken Raeburn  <raeburn@mit.edu>
+
+	* getdate.c: Deleted.
+	* Makefile.in ($(PROG)): Link against getdate.o from cli
+	directory.
+
+2006-03-17  Ken Raeburn  <raeburn@mit.edu>
+
+	* Makefile.in (LOCALINCLUDES): Look for kdb ldap headers in new
+	location.
+	(KDB_DEP_LIB): Refer to kdb ldap library under new name.
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/Makefile.in b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/Makefile.in
new file mode 100644
index 000000000..50b8ff452
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/Makefile.in
@@ -0,0 +1,29 @@
+thisconfigdir=../../../..
+myfulldir=plugins/kdb/ldap/ldap_util
+mydir=plugins/kdb/ldap/ldap_util
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+DEFINES = -DKDB4_DISABLE
+DEFS=
+LOCALINCLUDES = -I. @KRB4_INCLUDES@ -I$(srcdir)/../libkdb_ldap -I$(SRCTOP)/lib/kdb
+PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)
+#KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+KDB_DEP_LIB=$(DL_LIB) -lkdb_ldap $(THREAD_LINKOPTS)
+
+PROG = kdb5_ldap_util
+OBJS = kdb5_ldap_util.o kdb5_ldap_list.o kdb5_ldap_realm.o kdb5_ldap_policy.o kdb5_ldap_services.o
+
+GETDATE = ../../../../kadmin/cli/getdate.o
+
+all:: $(PROG)
+
+$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB4COMPAT_DEPLIBS) $(GETDATE)
+	$(CC_LINK) -o $(PROG) $(OBJS) $(GETDATE) \
+		$(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB4COMPAT_LIBS)
+
+install::
+	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
+	$(INSTALL_DATA) $(srcdir)/$(PROG).M ${DESTDIR}$(ADMIN_MANDIR)/$(PROG).8
+
+clean::
+	$(RM) $(PROG) $(OBJS) 
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c
new file mode 100644
index 000000000..835b2350b
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c
@@ -0,0 +1,287 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_list.c
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Miscellaneous functions for managing the string and integer lists
+ */
+
+#include <k5-int.h>
+#include "kdb5_ldap_list.h"
+
+/*
+ * Counts the number of entries in the given array of strings
+ */
+int list_count_str_array(char **list)
+{
+    int i = 0;
+
+    if (list == NULL)
+	return 0;
+
+    for (i = 0; *list != NULL; list++) {
+	i++;
+    }
+
+    return i;
+}
+
+
+/*
+ * Counts the number of entries in the given array of integers
+ */
+int list_count_int_array(int *list)
+{
+    int i = 0;
+
+    if (list == NULL)
+	return 0;
+
+    for (i = 0; *list != END_OF_LIST; list++) {
+	i++;
+    }
+
+    return i;
+}
+
+
+/*
+ * Frees the entries in a given list and not the list pointer
+ */
+void krb5_free_list_entries(list)
+    char **list;
+{
+    if (list == NULL)
+	return;
+    for (; *list != NULL; list++) {
+	free(*list);
+	*list = NULL;
+    }
+
+    return;
+}
+
+
+/*
+ * Tokenize the given string based on the delimiter provided
+ * and return the result as a list
+ */
+krb5_error_code
+krb5_parse_list(buffer, delimiter, list)
+    char *buffer;
+    char *delimiter;
+    char **list;
+{
+    char *str = NULL;
+    char *token = NULL;
+    char *ptrptr = NULL;
+    char **plist = list;
+    krb5_error_code retval = 0;
+    int count = 0;
+
+    if ((buffer == NULL) || (list == NULL) || (delimiter == NULL)) {
+	return EINVAL;
+    }
+
+    str = strdup(buffer);
+    if (str == NULL)
+	return ENOMEM;
+
+    token = strtok_r(str, delimiter, &ptrptr);
+    for (count = 1; ((token != NULL) && (count < MAX_LIST_ENTRIES));
+	 plist++, count++) {
+	*plist = strdup(token);
+	if (*plist == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	token = strtok_r(NULL, delimiter, &ptrptr);
+    }
+    *plist = NULL;
+
+cleanup:
+    if (str) {
+	free(str);
+	str = NULL;
+    }
+    if (retval)
+	krb5_free_list_entries(list);
+
+    return retval;
+}
+
+
+int compare_int(m1, m2)
+    const void *m1;
+    const void *m2;
+{
+    int mi1 = *(const int *)m1;
+    int mi2 = *(const int *)m2;
+
+    return (mi1 - mi2);
+}
+
+
+/*
+ * Modifies the destination list to contain or not to contain the
+ * entries present in the source list, depending on the mode
+ * (ADD or DELETE).
+ */
+void list_modify_str_array(destlist, sourcelist, mode)
+    char ***destlist;
+    const char **sourcelist;
+    int mode;
+{
+    char **dlist = NULL, **tmplist = NULL;
+    const char **slist = NULL;
+    int dcount = 0, scount = 0, copycount = 0;
+    int found = 0;
+
+    if ((destlist == NULL) || (*destlist == NULL) || (sourcelist == NULL))
+	return;
+
+    /* We need to add every entry present in the source list to
+     * the destination list */
+    if (mode == LIST_MODE_ADD) {
+	/* Traverse throught the end of destlist for appending */
+	for (dlist = *destlist, dcount = 0; *dlist != NULL;
+	     dlist++, dcount++) {
+	    ;   /* NULL statement */
+	}
+	/* Count the number of entries in the source list */
+	for (slist = sourcelist, scount = 0; *slist != NULL;
+	     slist++, scount++) {
+	    ;   /* NULL statement */
+	}
+	/* Reset the slist pointer to the start of source list */
+	slist = sourcelist;
+
+	/* Now append the source list to the existing destlist */
+	if ((dcount + scount) < MAX_LIST_ENTRIES)
+	    copycount = scount;
+	else
+	    /* Leave the last entry for list terminator(=NULL) */
+	    copycount = (MAX_LIST_ENTRIES -1) - dcount;
+
+	memcpy(dlist, slist, (sizeof(char *) * copycount));
+	dlist += copycount;
+	*dlist = NULL;
+    } else if (mode == LIST_MODE_DELETE) {
+	/* We need to delete every entry present in the source list
+	 * from the destination list */
+	for (slist = sourcelist; *slist != NULL; slist++) {
+	    for (dlist = *destlist; *dlist != NULL; dlist++) {
+		found = 0; /* value not found */
+		/* DN is case insensitive string */
+		if (strcasecmp(*dlist, *slist) == 0) {
+		    found = 1;
+		    free(*dlist);
+		    /* Advance the rest of the entries by one */
+		    for (tmplist = dlist; *tmplist != NULL; tmplist++) {
+			*tmplist = *(tmplist+1);
+		    }
+		    break;
+		}
+	    }
+	}
+    }
+
+    return;
+}
+
+
+/*
+ * Modifies the destination list to contain or not to contain the
+ * entries present in the source list, depending on the mode
+ * (ADD or DELETE). where the list is array of integers.
+ */
+int list_modify_int_array(destlist, sourcelist, mode)
+    int *destlist;
+    const int *sourcelist;
+    int mode;
+{
+    int *dlist = NULL, *tmplist = NULL;
+    const int *slist = NULL;
+    int dcount = 0, scount = 0, copycount = 0;
+    int tcount = 0;
+
+    if ((destlist == NULL) || (sourcelist == NULL))
+	return 0;
+
+    /* We need to add every entry present in the source list to the
+     * destination list */
+    if (mode == LIST_MODE_ADD) {
+	/* Traverse throught the end of destlist for appending */
+	for (dlist = destlist, dcount = 0; *dlist != END_OF_LIST;
+	     dlist++, dcount++)
+	    ;   /* NULL statement */
+
+	/* Count the number of entries in the source list */
+	for (slist = sourcelist, scount = 0; *slist != END_OF_LIST;
+	     slist++, scount++)
+	    ;   /* NULL statement */
+
+	/* Reset the slist pointer to the start of source list */
+	slist = sourcelist;
+
+	/* Now append the source list to the existing destlist */
+	if ((dcount + scount) < MAX_LIST_ENTRIES)
+	    copycount = scount;
+	else
+	    /* Leave the last entry for list terminator(=NULL) */
+	    copycount = (MAX_LIST_ENTRIES -1) - dcount;
+
+	memcpy(dlist, slist, (sizeof(int) * copycount));
+	dlist += copycount;
+	*dlist = END_OF_LIST;
+	tcount = dcount + copycount;
+    } else if (mode == LIST_MODE_DELETE) {
+	/* We need to delete every entry present in the source list from
+	 * the destination list */
+	for (slist = sourcelist; *slist != END_OF_LIST; slist++) {
+	    for (dlist = destlist; *dlist != END_OF_LIST; dlist++) {
+		if (*dlist == *slist) {
+		    /* Advance the rest of the entries by one */
+		    for (tmplist = dlist; *tmplist != END_OF_LIST; tmplist++) {
+			*tmplist = *(tmplist+1);
+		    }
+		    break;
+		}
+	    }
+	}
+	/* count the number of entries */
+	for (dlist = destlist, tcount = 0; *dlist != END_OF_LIST; dlist++) {
+	    tcount++;
+	}
+    }
+
+    return tcount;
+}
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h
new file mode 100644
index 000000000..b6402e592
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h
@@ -0,0 +1,47 @@
+
+/*
+ * kadmin/ldap_util/kdb5_ldap_list.h
+ */
+ 
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright 
+ *       notice, this list of conditions and the following disclaimer in the 
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+
+#define MAX_LIST_ENTRIES	64
+#define END_OF_LIST		-1      /* End of List */
+#define LIST_DELIMITER		":"     /* List entry separator */
+#define LIST_MODE_ADD 		0x701   /* Add to the List */
+#define LIST_MODE_DELETE 	0x702   /* Delete from the list */
+#define MAX_LEN_LIST_ENTRY 	512     /* Max len of an entry */
+
+extern krb5_error_code krb5_parse_list(char *buffer, char *delimiter, char **list);
+extern void krb5_free_list_entries(char **list);
+extern void list_modify_str_array(char ***destlist, const char **sourcelist, int mode);
+extern int list_modify_int_array(int *destlist, const int *sourcelist, int mode);
+extern int list_count_str_array(char **list);
+extern int list_count_int_array(int *list); 
+extern int compare_int(const void*, const void *);
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c
new file mode 100644
index 000000000..7a6c6411e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c
@@ -0,0 +1,881 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_policy.c
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Create / Delete / Modify / View / List policy objects.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+#include "ldap_tkt_policy.h"
+extern time_t get_date(char *); /* kadmin/cli/getdate.o */
+
+static void print_policy_params(krb5_ldap_policy_params *policyparams, int mask);
+static char *strdur(time_t duration);
+
+extern char *yes;
+extern kadm5_config_params global_params;
+                                                                                                                             
+static krb5_error_code init_ldap_realm (int argc, char *argv[]) {
+    /* This operation is being performed in the context of a realm. So,
+     * initialize the realm */
+    int mask = 0;
+    krb5_error_code retval = 0;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+                                                                                                                             
+    dal_handle = (kdb5_dal_handle *) util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    if (!ldap_context) {
+        retval = EINVAL;
+        goto cleanup;
+    }
+                                                                                                                             
+    if (ldap_context->krbcontainer == NULL) {
+        retval = krb5_ldap_read_krbcontainer_params (util_context,
+                &(ldap_context->krbcontainer));
+        if (retval != 0) {
+            com_err(argv[0], retval, "while reading kerberos container information");
+            goto cleanup;
+        }
+    }
+                                                                                                                             
+    if (ldap_context->lrparams == NULL) {
+        retval = krb5_ldap_read_realm_params(util_context,
+                global_params.realm,
+                &(ldap_context->lrparams),
+                &mask);
+                                                                                                                             
+        if (retval != 0) {
+            goto cleanup;
+        }
+    }
+cleanup:
+    return retval;
+}
+
+/*
+ * This function will create a ticket policy object with the
+ * specified attributes.
+ */
+void
+kdb5_ldap_create_policy(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_error_code retval = 0;
+    krb5_ldap_policy_params *policyparams = NULL;
+    krb5_boolean print_usage = FALSE;
+    krb5_boolean no_msg = FALSE;
+    int mask = 0;
+    time_t date = 0;
+    time_t now = 0;
+    int i = 0;
+
+    /* Check for number of arguments */
+    if ((argc < 2) || (argc > 16)) {
+	goto err_usage;
+    }
+
+    /* Allocate memory for policy parameters structure */
+    policyparams = (krb5_ldap_policy_params*) calloc(1, sizeof(krb5_ldap_policy_params));
+    if (policyparams == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    /* Get current time */
+    time (&now);
+
+    /* Parse all arguments */
+    for (i = 1; i < argc; i++) {
+	if (!strcmp(argv[i], "-maxtktlife")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    date = get_date(argv[i]);
+	    if (date == (time_t)(-1)) {
+		retval = EINVAL;
+		com_err (me, retval, "while providing time specification");
+		goto err_nomsg;
+	    }
+
+	    policyparams->maxtktlife = date - now;
+
+	    mask |= LDAP_POLICY_MAXTKTLIFE;
+	} else if (!strcmp(argv[i], "-maxrenewlife")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    date = get_date(argv[i]);
+	    if (date == (time_t)(-1)) {
+		retval = EINVAL;
+		com_err (me, retval, "while providing time specification");
+		goto err_nomsg;
+	    }
+
+	    policyparams->maxrenewlife = date - now;
+
+	    mask |= LDAP_POLICY_MAXRENEWLIFE;
+	} else if (!strcmp((argv[i] + 1), "allow_postdated")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_forwardable")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_renewable")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_proxiable")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_dup_skey")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "requires_preauth")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "requires_hwauth")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_svr")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_tgs_req")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_tix")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "needchange")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "password_changing_service")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
+	    else
+		goto err_usage;
+
+	    mask |= LDAP_POLICY_TKTFLAGS;
+	} else { /* Any other argument must be policy DN */
+	    /* First check if policy DN is already provided --
+	       if so, there's a usage error */
+            if (policyparams->policy != NULL)
+		goto err_usage;
+
+	    /* If not present already, fill up policy DN */
+            policyparams->policy = strdup(argv[i]);
+            if (policyparams->policy == NULL) {
+		retval = ENOMEM;
+		com_err(me, retval, "while creating policy object");
+		goto err_nomsg;
+	    }
+	}
+    }
+
+    /* policy DN is a mandatory argument. If not provided, print usage */
+    if (policyparams->policy == NULL)
+	goto err_usage;
+
+    if ((retval = init_ldap_realm (argc, argv))) {
+        com_err(me, retval, "while reading realm information");
+        goto err_nomsg;
+    }
+
+    /* Create object with all attributes provided */
+    if ((retval = krb5_ldap_create_policy(util_context, policyparams, mask)) != 0)
+	goto cleanup;
+
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+cleanup:
+    /* Clean-up structure */
+    krb5_ldap_free_policy (util_context, policyparams);
+
+    if (print_usage)
+	db_usage(CREATE_POLICY);
+
+    if (retval) {
+	if (!no_msg)
+	    com_err(me, retval, "while creating policy object");
+
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/*
+ * This function will destroy the specified ticket policy
+ * object interactively, unless forced through an option.
+ */
+void
+kdb5_ldap_destroy_policy(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_error_code retval = 0;
+    krb5_ldap_policy_params *policyparams = NULL;
+    krb5_boolean print_usage = FALSE;
+    krb5_boolean no_msg = FALSE;
+    char *policy = NULL;
+    int mask = 0;
+    int force = 0;
+    char buf[5] = {0};
+    int i = 0;
+
+    if ((argc < 2) || (argc > 3)) {
+	goto err_usage;
+    }
+
+    for (i = 1; i < argc; i++) {
+	if (strcmp(argv[i], "-force") == 0) {
+	    force++;
+	} else { /* Any other argument must be policy DN */
+	    /* First check if policy DN is already provided --
+	       if so, there's a usage error */
+            if (policy != NULL)
+		goto err_usage;
+
+	    /* If not present already, fill up policy DN */
+            policy = strdup(argv[i]);
+            if (policy == NULL) {
+		retval = ENOMEM;
+		com_err(me, retval, "while destroying policy object");
+		goto err_nomsg;
+	    }
+	}
+    }
+
+    if (policy == NULL)
+	goto err_usage;
+
+    if (!force) {
+        printf("This will delete the policy object '%s', are you sure?\n", policy);
+	printf("(type 'yes' to confirm)? ");
+
+	if (fgets(buf, sizeof(buf), stdin) == NULL) {
+	    retval = EINVAL;
+	    goto cleanup;
+	}
+
+	if (strcmp(buf, yes)) {
+	    exit_status++;
+	    goto cleanup;
+	}
+    }
+
+    if ((retval = init_ldap_realm (argc, argv)))
+        goto err_nomsg;
+
+    if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask)))
+	goto cleanup;
+
+
+    if ((retval = krb5_ldap_delete_policy(util_context, policy)))
+	goto cleanup;
+
+    printf("** policy object '%s' deleted.\n", policy);
+    goto cleanup;
+
+
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+cleanup:
+    /* Clean-up structure */
+    krb5_ldap_free_policy (util_context, policyparams);
+
+    if (policy) {
+	free (policy);
+    }
+
+    if (print_usage) {
+	db_usage(DESTROY_POLICY);
+    }
+
+    if (retval) {
+	if (!no_msg)
+	    com_err(me, retval, "while destroying policy object");
+
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/*
+ * This function will modify the attributes of a given ticket
+ * policy object.
+ */
+void
+kdb5_ldap_modify_policy(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_error_code retval = 0;
+    krb5_ldap_policy_params *policyparams = NULL;
+    krb5_boolean print_usage = FALSE;
+    krb5_boolean no_msg = FALSE;
+    char *policy = NULL;
+    int in_mask = 0, out_mask = 0;
+    time_t date = 0;
+    time_t now = 0;
+    int i = 0;
+
+    /* Check for number of arguments -- minimum is 3
+       since atleast one parameter should be given in
+       addition to 'modify_policy' and policy DN */
+    if ((argc < 3) || (argc > 16)) {
+	goto err_usage;
+    }
+
+    /* Parse all arguments, only to pick up policy DN (Pass 1) */
+    for (i = 1; i < argc; i++) {
+	/* Skip arguments next to 'maxtktlife'
+	   and 'maxrenewlife' arguments */
+	if (!strcmp(argv[i], "-maxtktlife")) {
+	    ++i;
+	} else if (!strcmp(argv[i], "-maxrenewlife")) {
+	    ++i;
+	}
+	/* Do nothing for ticket flag arguments */
+	else if (!strcmp((argv[i] + 1), "allow_postdated") ||
+		 !strcmp((argv[i] + 1), "allow_forwardable") ||
+		 !strcmp((argv[i] + 1), "allow_renewable") ||
+		 !strcmp((argv[i] + 1), "allow_proxiable") ||
+		 !strcmp((argv[i] + 1), "allow_dup_skey") ||
+		 !strcmp((argv[i] + 1), "requires_preauth") ||
+		 !strcmp((argv[i] + 1), "requires_hwauth") ||
+		 !strcmp((argv[i] + 1), "allow_svr") ||
+		 !strcmp((argv[i] + 1), "allow_tgs_req") ||
+		 !strcmp((argv[i] + 1), "allow_tix") ||
+		 !strcmp((argv[i] + 1), "needchange") ||
+		 !strcmp((argv[i] + 1), "password_changing_service")) {
+	} else { /* Any other argument must be policy DN */
+	    /* First check if policy DN is already provided --
+	       if so, there's a usage error */
+            if (policy != NULL)
+		goto err_usage;
+
+	    /* If not present already, fill up policy DN */
+            policy = strdup(argv[i]);
+            if (policy == NULL) {
+		retval = ENOMEM;
+		com_err(me, retval, "while modifying policy object");
+		goto err_nomsg;
+	    }
+	}
+    }
+
+    if (policy == NULL)
+	goto err_usage;
+
+    if ((retval = init_ldap_realm (argc, argv)))
+	goto cleanup;
+
+    retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &in_mask);
+    if (retval) {
+        com_err(me, retval, "while reading information of policy '%s'", policy);
+	goto err_nomsg;
+    }
+
+    /* Get current time */
+    time (&now);
+
+    /* Parse all arguments, but skip policy DN (Pass 2) */
+    for (i = 1; i < argc; i++) {
+	if (!strcmp(argv[i], "-maxtktlife")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    date = get_date(argv[i]);
+	    if (date == (time_t)(-1)) {
+		retval = EINVAL;
+		com_err (me, retval, "while providing time specification");
+		goto err_nomsg;
+	    }
+
+	    policyparams->maxtktlife = date - now;
+
+	    out_mask |= LDAP_POLICY_MAXTKTLIFE;
+	} else if (!strcmp(argv[i], "-maxrenewlife")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    date = get_date(argv[i]);
+	    if (date == (time_t)(-1)) {
+		retval = EINVAL;
+		com_err (me, retval, "while providing time specification");
+		goto err_nomsg;
+	    }
+
+	    policyparams->maxrenewlife = date - now;
+
+	    out_mask |= LDAP_POLICY_MAXRENEWLIFE;
+	} else if (!strcmp((argv[i] + 1), "allow_postdated")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_forwardable")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_renewable")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_proxiable")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_dup_skey")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "requires_preauth")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "requires_hwauth")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_svr")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_tgs_req")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "allow_tix")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "needchange")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else if (!strcmp((argv[i] + 1), "password_changing_service")) {
+	    if (*(argv[i]) == '+')
+		policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
+	    else if (*(argv[i]) == '-')
+		policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
+	    else
+		goto err_usage;
+
+	    out_mask |= LDAP_POLICY_TKTFLAGS;
+	} else {
+	    /* Any other argument must be policy DN
+	       -- skip it */
+	}
+    }
+
+    /* Modify attributes of object */
+    if ((retval = krb5_ldap_modify_policy(util_context, policyparams, out_mask)))
+	goto cleanup;
+
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+cleanup:
+    /* Clean-up structure */
+    krb5_ldap_free_policy (util_context, policyparams);
+
+    if (policy)
+        free (policy);
+
+    if (print_usage)
+	db_usage(MODIFY_POLICY);
+
+    if (retval) {
+	if (!no_msg)
+	    com_err(me, retval, "while modifying policy object");
+
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/*
+ * This function will display information about the given policy object,
+ * fetching the information from the LDAP Server.
+ */
+void
+kdb5_ldap_view_policy(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_ldap_policy_params *policyparams = NULL;
+    krb5_error_code retval = 0;
+    krb5_boolean print_usage = FALSE;
+    char *policy = NULL;
+    int mask = 0;
+
+    if (argc != 2) {
+	goto err_usage;
+    }
+
+    policy = strdup(argv[1]);
+    if (policy == NULL) {
+	com_err(me, ENOMEM, "while viewing policy");
+	exit_status++;
+	goto cleanup;
+    }
+
+    if ((retval = init_ldap_realm (argc, argv)))
+        goto cleanup;
+
+    if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask))) {
+	com_err(me, retval, "while viewing policy '%s'", policy);
+	exit_status++;
+	goto cleanup;
+    }
+
+    print_policy_params (policyparams, mask);
+
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+cleanup:
+    krb5_ldap_free_policy (util_context, policyparams);
+
+    if (policy)
+	free (policy);
+
+    if (print_usage) {
+	db_usage(VIEW_POLICY);
+    }
+
+    return;
+}
+
+
+/*
+ * This function will print the policy object information to the
+ * standard output.
+ */
+static void
+print_policy_params(policyparams, mask)
+    krb5_ldap_policy_params *policyparams;
+    int mask;
+{
+    /* Print the policy DN */
+    printf("%25s: %s\n", "Ticket policy", policyparams->policy);
+
+    /* Print max. ticket life and max. renewable life, if present */
+    if (mask & LDAP_POLICY_MAXTKTLIFE)
+	printf("%25s: %s\n", "Maximum ticket life", strdur(policyparams->maxtktlife));
+    if (mask & LDAP_POLICY_MAXRENEWLIFE)
+	printf("%25s: %s\n", "Maximum renewable life", strdur(policyparams->maxrenewlife));
+
+    /* Service flags are printed */
+    printf("%25s: ", "Ticket flags");
+    if (mask & LDAP_POLICY_TKTFLAGS) {
+	int ticketflags = policyparams->tktflags;
+
+	if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED)
+	    printf("%s ","DISALLOW_POSTDATED");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE)
+	    printf("%s ","DISALLOW_FORWARDABLE");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE)
+	    printf("%s ","DISALLOW_RENEWABLE");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE)
+	    printf("%s ","DISALLOW_PROXIABLE");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY)
+	    printf("%s ","DISALLOW_DUP_SKEY");
+
+	if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH)
+	    printf("%s ","REQUIRES_PRE_AUTH");
+
+	if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH)
+	    printf("%s ","REQUIRES_HW_AUTH");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_SVR)
+	    printf("%s ","DISALLOW_SVR");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED)
+	    printf("%s ","DISALLOW_TGT_BASED");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX)
+	    printf("%s ","DISALLOW_ALL_TIX");
+
+	if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE)
+	    printf("%s ","REQUIRES_PWCHANGE");
+
+	if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE)
+	    printf("%s ","PWCHANGE_SERVICE");
+    }
+    printf("\n");
+
+    return;
+}
+
+
+/*
+ * This function will list the DNs of policy objects under a specific
+ * sub-tree (entire tree by default)
+ */
+void kdb5_ldap_list_policies(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_error_code retval = 0;
+    krb5_boolean print_usage = FALSE;
+    char *basedn = NULL;
+    char **list = NULL;
+    char **plist = NULL;
+
+    /* Check for number of arguments */
+    if ((argc != 1) && (argc != 3)) {
+	goto err_usage;
+    }
+
+    if ((retval = init_ldap_realm (argc, argv)))
+	goto cleanup;
+
+    retval = krb5_ldap_list_policy(util_context, basedn, &list);
+    if ((retval != 0) || (list == NULL))
+	goto cleanup;
+
+    for (plist = list; *plist != NULL; plist++) {
+	printf("%s\n", *plist);
+    }
+
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+cleanup:
+    if (list != NULL) {
+	krb5_free_list_entries (list);
+	free (list);
+    }
+
+    if (basedn)
+	free (basedn);
+
+    if (print_usage) {
+	db_usage(LIST_POLICY);
+    }
+
+    if (retval) {
+	com_err(me, retval, "while listing policy objects");
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/* Reproduced from kadmin.c, instead of linking
+   the entire kadmin.o */
+static char *strdur(duration)
+    time_t duration;
+{
+    static char out[50];
+    int neg, days, hours, minutes, seconds;
+
+    if (duration < 0) {
+	duration *= -1;
+	neg = 1;
+    } else
+	neg = 0;
+    days = duration / (24 * 3600);
+    duration %= 24 * 3600;
+    hours = duration / 3600;
+    duration %= 3600;
+    minutes = duration / 60;
+    duration %= 60;
+    seconds = duration;
+    sprintf(out, "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
+	    days, days == 1 ? "day" : "days",
+	    hours, minutes, seconds);
+    return out;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h
new file mode 100644
index 000000000..105b0a06b
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h
@@ -0,0 +1,37 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_policy.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+extern void kdb5_ldap_create_policy(int argc, char **argv);
+extern void kdb5_ldap_destroy_policy(int argc, char **argv);
+extern void kdb5_ldap_modify_policy(int argc, char **argv);
+extern void kdb5_ldap_view_policy(int argc, char **argv);
+extern void kdb5_ldap_list_policies(int argc, char **argv);
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
new file mode 100644
index 000000000..1a0d9fa99
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
@@ -0,0 +1,2525 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_realm.c
+ *
+ * Copyright 1990,1991,2001, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Copyright (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.
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Create / Modify / Destroy / View / List realm(s)
+ */
+
+/* Needed for getting the definition of KRB5_TL_DB_ARGS */
+#define SECURID
+
+#include <stdio.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+#include <ldap_principal.h>
+#include <ldap_krbcontainer.h>
+extern time_t get_date(char *); /* kadmin/cli/getdate.o */
+
+char *yes = "yes\n"; /* \n to compare against result of fgets */
+krb5_key_salt_tuple def_kslist = {ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL};
+
+struct realm_info rblock = {
+    KRB5_KDB_MAX_LIFE,
+    KRB5_KDB_MAX_RLIFE,
+    KRB5_KDB_EXPIRATION,
+    KRB5_KDB_DEF_FLAGS,
+    (krb5_keyblock *) NULL,
+    1,
+    &def_kslist
+};
+
+krb5_data tgt_princ_entries[] = {
+    {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
+    {0, 0, 0} };
+
+krb5_data db_creator_entries[] = {
+    {0, sizeof("db_creation")-1, "db_creation"} };
+
+
+static krb5_principal_data db_create_princ = {
+    0,					/* magic number */
+    {0, 0, 0},				/* krb5_data realm */
+    db_creator_entries,			/* krb5_data *data */
+    1,					/* int length */
+    KRB5_NT_SRV_INST			/* int type */
+};
+
+extern char *mkey_password;
+extern char *progname;
+extern kadm5_config_params global_params;
+
+static void print_realm_params(krb5_ldap_realm_params *rparams, int mask);
+static int kdb_ldap_create_principal (krb5_context context, krb5_principal
+				      princ, enum ap_op op, struct realm_info *pblock);
+
+
+static char *strdur(time_t duration);
+static int get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],int argc);
+static krb5_error_code krb5_dbe_update_mod_princ_data_new (krb5_context context, krb5_db_entry *entry, krb5_timestamp mod_date, krb5_const_principal mod_princ);
+static krb5_error_code krb5_dbe_update_tl_data_new ( krb5_context context, krb5_db_entry *entry, krb5_tl_data *new_tl_data);
+
+#define ADMIN_LIFETIME 60*60*3 /* 3 hours */
+#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
+
+static int get_ticket_policy(rparams,i,argv,argc)
+    krb5_ldap_realm_params *rparams;
+    int *i;
+    char *argv[];
+    int argc;
+{
+    time_t date;
+    time_t now;
+    int mask = 0;
+    krb5_error_code retval = 0;
+    krb5_boolean no_msg = FALSE;
+
+    krb5_boolean print_usage = FALSE;
+    char *me = argv[0];
+
+    time(&now);
+    if (!strcmp(argv[*i], "-maxtktlife")) {
+	if (++(*i) > argc-1)
+	    goto err_usage;
+	date = get_date(argv[*i]);
+	if (date == (time_t)(-1)) {
+	    retval = EINVAL;
+	    com_err (me, retval, "while providing time specification");
+	    goto err_nomsg;
+	}
+	rparams->max_life = date-now;
+	mask |= LDAP_REALM_MAXTICKETLIFE;
+    }
+
+
+    else if (!strcmp(argv[*i], "-maxrenewlife")) {
+	if (++(*i) > argc-1)
+	    goto err_usage;
+
+	date = get_date(argv[*i]);
+	if (date == (time_t)(-1)) {
+	    retval = EINVAL;
+	    com_err (me, retval, "while providing time specification");
+	    goto err_nomsg;
+	}
+	rparams->max_renewable_life = date-now;
+	mask |= LDAP_REALM_MAXRENEWLIFE;
+    } else if (!strcmp((argv[*i] + 1), "allow_postdated")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "allow_forwardable")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
+
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "allow_renewable")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "allow_proxiable")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "allow_dup_skey")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    }
+
+    else if (!strcmp((argv[*i] + 1), "requires_preauth")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "requires_hwauth")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "allow_svr")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "allow_tgs_req")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "allow_tix")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "needchange")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
+	else
+	    goto err_usage;
+
+	mask |= LDAP_REALM_KRBTICKETFLAGS;
+    } else if (!strcmp((argv[*i] + 1), "password_changing_service")) {
+	if (*(argv[*i]) == '+')
+	    rparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
+	else if (*(argv[*i]) == '-')
+	    rparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
+	else
+	    goto err_usage;
+
+	mask |=LDAP_REALM_KRBTICKETFLAGS;
+    }
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+    return mask;
+}
+
+/*
+ * This function will create a realm on the LDAP Server, with
+ * the specified attributes.
+ */
+void kdb5_ldap_create(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval = 0;
+    krb5_keyblock master_keyblock;
+    krb5_ldap_realm_params *rparams = NULL;
+    krb5_principal master_princ = NULL;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+    krb5_boolean realm_obj_created = FALSE;
+    krb5_boolean create_complete = FALSE;
+    krb5_boolean print_usage = FALSE;
+    krb5_boolean no_msg = FALSE;
+    char *oldcontainerref=NULL;
+    char pw_str[1024];
+    int do_stash = 0;
+    int i = 0;
+    int mask = 0, ret_mask = 0;
+    char **list = NULL;
+#ifdef HAVE_EDIRECTORY
+    int rightsmask = 0;
+#endif
+
+    memset(&master_keyblock, 0, sizeof(master_keyblock));
+
+    rparams = (krb5_ldap_realm_params *)malloc(
+	sizeof(krb5_ldap_realm_params));
+    if (rparams == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    memset(rparams, 0, sizeof(krb5_ldap_realm_params));
+
+    /* Parse the arguments */
+    for (i = 1; i < argc; i++) {
+	if (!strcmp(argv[i], "-subtrees")) {
+	    if (++i > argc-1)
+		goto err_usage;
+
+	    if(strncmp(argv[i], "", strlen(argv[i]))!=0) {
+		list = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *));
+		if (list == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+		    free(list);
+		    list = NULL;
+		    goto cleanup;
+		}
+
+		rparams->subtreecount=0;
+		while(list[rparams->subtreecount]!=NULL)
+		    (rparams->subtreecount)++;
+		rparams->subtree = list;
+	    } else if(strncmp(argv[i], "", strlen(argv[i]))==0) {
+		 /* dont allow subtree value to be set at the root(NULL, "") of the tree */
+		 com_err(argv[0], EINVAL,
+			  "for subtree while creating realm '%s'",
+			   global_params.realm);
+		 goto err_nomsg;
+	    }
+	    rparams->subtree[rparams->subtreecount] = NULL;
+	    mask |= LDAP_REALM_SUBTREE;
+	} else if (!strcmp(argv[i], "-containerref")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    if(strncmp(argv[i], "", strlen(argv[i]))==0) {
+		 /* dont allow containerref value to be set at the root(NULL, "") of the tree */
+		 com_err(argv[0], EINVAL,
+			  "for container reference while creating realm '%s'",
+			   global_params.realm);
+		 goto err_nomsg;
+	    }
+	    rparams->containerref = strdup(argv[i]);
+	    if (rparams->containerref == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_CONTREF;
+	} else if (!strcmp(argv[i], "-sscope")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    /* Possible values for search scope are
+	     * one (or 1) and sub (or 2)
+	     */
+	    if (!strcasecmp(argv[i], "one")) {
+		rparams->search_scope = 1;
+	    } else if (!strcasecmp(argv[i], "sub")) {
+		rparams->search_scope = 2;
+	    } else {
+		rparams->search_scope = atoi(argv[i]);
+		if ((rparams->search_scope != 1) &&
+		    (rparams->search_scope != 2)) {
+		    com_err(argv[0], EINVAL,
+			    "invalid search scope while creating realm '%s'",
+			    global_params.realm);
+		    goto err_nomsg;
+		}
+	    }
+	    mask |= LDAP_REALM_SEARCHSCOPE;
+	}
+#ifdef HAVE_EDIRECTORY
+	else if (!strcmp(argv[i], "-kdcdn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    rparams->kdcservers = (char **)malloc(
+		sizeof(char *) * MAX_LIST_ENTRIES);
+	    if (rparams->kdcservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    memset(rparams->kdcservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  rparams->kdcservers))) {
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_KDCSERVERS;
+	} else if (!strcmp(argv[i], "-admindn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    rparams->adminservers = (char **)malloc(
+		sizeof(char *) * MAX_LIST_ENTRIES);
+	    if (rparams->adminservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    memset(rparams->adminservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  rparams->adminservers))) {
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_ADMINSERVERS;
+	} else if (!strcmp(argv[i], "-pwddn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    rparams->passwdservers = (char **)malloc(
+		sizeof(char *) * MAX_LIST_ENTRIES);
+	    if (rparams->passwdservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    memset(rparams->passwdservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  rparams->passwdservers))) {
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_PASSWDSERVERS;
+	}
+#endif
+	else if (!strcmp(argv[i], "-s")) {
+	    do_stash = 1;
+	} else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) {
+	    mask|=ret_mask;
+	}
+
+	else {
+	    printf("'%s' is an invalid option\n", argv[i]);
+	    goto err_usage;
+	}
+    }
+
+    /* If the default enctype/salttype is not provided, use the
+     * default values and also add to the list of supported
+     * enctypes/salttype
+     */
+
+    rblock.max_life = global_params.max_life;
+    rblock.max_rlife = global_params.max_rlife;
+    rblock.expiration = global_params.expiration;
+    rblock.flags = global_params.flags;
+    rblock.nkslist = global_params.num_keysalts;
+    rblock.kslist = global_params.keysalts;
+
+    krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm);
+    krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm));
+
+    printf("Initializing database for realm '%s'\n", global_params.realm);
+
+    if (!mkey_password) {
+	unsigned int pw_size;
+	printf("You will be prompted for the database Master Password.\n");
+	printf("It is important that you NOT FORGET this password.\n");
+	fflush(stdout);
+
+	pw_size = sizeof (pw_str);
+	memset(pw_str, 0, pw_size);
+
+	retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2,
+				    pw_str, &pw_size);
+	if (retval) {
+	    com_err(argv[0], retval, "while reading master key from keyboard");
+	    goto err_nomsg;
+	}
+	mkey_password = pw_str;
+    }
+
+    rparams->mkey.enctype = global_params.enctype;
+    /* We are sure that 'mkey_password' is a regular string ... */
+    rparams->mkey.length = strlen(mkey_password) + 1;
+    rparams->mkey.contents = (krb5_octet *)strdup(mkey_password);
+    if (rparams->mkey.contents == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    rparams->realm_name = strdup(global_params.realm);
+    if (rparams->realm_name == NULL) {
+	retval = ENOMEM;
+	com_err(argv[0], ENOMEM, "while creating realm '%s'",
+		global_params.realm);
+	goto err_nomsg;
+    }
+
+    dal_handle = (kdb5_dal_handle *) util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    if (!ldap_context) {
+	retval = EINVAL;
+	goto cleanup;
+    }
+
+    /* read the kerberos container */
+    if ((retval=krb5_ldap_read_krbcontainer_params (util_context,
+						    &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {
+	/* Prompt the user for entering the DN of Kerberos container */
+	char krb_location[MAX_KRB_CONTAINER_LEN];
+	krb5_ldap_krbcontainer_params kparams;
+	int krb_location_len = 0;
+	memset(&kparams, 0, sizeof(kparams));
+
+	/* Read the kerberos container location from configuration file */
+	if (ldap_context->conf_section) {
+	    if ((retval=profile_get_string(util_context->profile,
+					   KDB_MODULE_SECTION, ldap_context->conf_section,
+					   "ldap_kerberos_container_dn", NULL,
+					   &kparams.DN)) != 0) {
+		goto cleanup;
+	    }
+	}
+	if (kparams.DN == NULL) {
+	    if ((retval=profile_get_string(util_context->profile,
+					   KDB_MODULE_DEF_SECTION,
+					   "ldap_kerberos_container_dn", NULL,
+					   NULL, &kparams.DN)) != 0) {
+		goto cleanup;
+	    }
+	}
+
+	printf("\nKerberos container is missing. Creating now...\n");
+	if (kparams.DN == NULL) {
+#ifdef HAVE_EDIRECTORY
+	    printf("Enter DN of Kerberos container [cn=Kerberos,cn=Security]: ");
+#else
+	    printf("Enter DN of Kerberos container: ");
+#endif
+	    if (fgets(krb_location, MAX_KRB_CONTAINER_LEN, stdin) != NULL) {
+		/* Remove the newline character at the end */
+		krb_location_len = strlen(krb_location);
+		if ((krb_location[krb_location_len - 1] == '\n') ||
+		    (krb_location[krb_location_len - 1] == '\r')) {
+		    krb_location[krb_location_len - 1] = '\0';
+		    krb_location_len--;
+		}
+		/* If the user has not given any input, take the default location */
+		else if (krb_location[0] == '\0')
+		    kparams.DN = NULL;
+		else
+		    kparams.DN = krb_location;
+	    } else
+		kparams.DN = NULL;
+	}
+
+	/* create the kerberos container */
+	retval = krb5_ldap_create_krbcontainer(util_context,
+					       ((kparams.DN != NULL) ? &kparams : NULL));
+	if (retval)
+	    goto cleanup;
+
+	retval = krb5_ldap_read_krbcontainer_params(util_context,
+						    &(ldap_context->krbcontainer));
+	if (retval) {
+	    com_err(argv[0], retval, "while reading kerberos container information");
+	    goto cleanup;
+	}
+    } else if (retval) {
+	com_err(argv[0], retval, "while reading kerberos container information");
+	goto cleanup;
+    }
+
+    if ((retval = krb5_ldap_create_realm(util_context,
+					 /* global_params.realm, */ rparams, mask))) {
+	goto cleanup;
+    }
+
+    /* We just created the Realm container. Here starts our transaction tracking */
+    realm_obj_created = TRUE;
+
+    if ((retval = krb5_ldap_read_realm_params(util_context,
+					      global_params.realm,
+					      &(ldap_context->lrparams),
+					      &mask))) {
+	com_err(argv[0], retval, "while reading information of realm '%s'",
+		global_params.realm);
+	goto err_nomsg;
+    }
+    ldap_context->lrparams->realm_name = strdup(global_params.realm);
+    if (ldap_context->lrparams->realm_name == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    /* assemble & parse the master key name */
+    if ((retval = krb5_db_setup_mkey_name(util_context,
+					  global_params.mkey_name,
+					  global_params.realm,
+					  0, &master_princ))) {
+	com_err(argv[0], retval, "while setting up master key name");
+	goto err_nomsg;
+    }
+
+    /* Obtain master key from master password */
+    {
+	krb5_data master_salt, pwd;
+
+	pwd.data = mkey_password;
+	pwd.length = strlen(mkey_password);
+	retval = krb5_principal2salt(util_context, master_princ, &master_salt);
+	if (retval) {
+	    com_err(argv[0], retval, "while calculating master key salt");
+	    goto err_nomsg;
+	}
+
+	retval = krb5_c_string_to_key(util_context, rparams->mkey.enctype,
+				      &pwd, &master_salt, &master_keyblock);
+
+	if (master_salt.data)
+	    free(master_salt.data);
+
+	if (retval) {
+	    com_err(argv[0], retval, "while transforming master key from password");
+	    goto err_nomsg;
+	}
+
+    }
+
+    rblock.key = &master_keyblock;
+    ldap_context->lrparams->mkey = master_keyblock;
+    ldap_context->lrparams->mkey.contents = (krb5_octet *) malloc
+	(master_keyblock.length);
+    if (ldap_context->lrparams->mkey.contents == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    memcpy (ldap_context->lrparams->mkey.contents, master_keyblock.contents,
+	    master_keyblock.length);
+
+    /* Create special principals inside the realm subtree */
+    {
+	char princ_name[MAX_PRINC_SIZE];
+	krb5_principal_data tgt_princ = {
+	    0,					/* magic number */
+	    {0, 0, 0},				/* krb5_data realm */
+	    tgt_princ_entries,			/* krb5_data *data */
+	    2,					/* int length */
+	    KRB5_NT_SRV_INST			/* int type */
+	};
+	krb5_principal p, temp_p=NULL;
+
+	krb5_princ_set_realm_data(util_context, &tgt_princ, global_params.realm);
+	krb5_princ_set_realm_length(util_context, &tgt_princ, strlen(global_params.realm));
+	krb5_princ_component(util_context, &tgt_princ,1)->data = global_params.realm;
+	krb5_princ_component(util_context, &tgt_princ,1)->length = strlen(global_params.realm);
+	/* The container reference value is set to NULL, to avoid service principals
+	 * getting created within the container reference at realm creation */
+	if (ldap_context->lrparams->containerref != NULL) {
+	    oldcontainerref = ldap_context->lrparams->containerref;
+	    ldap_context->lrparams->containerref = NULL;
+	}
+
+	/* Create 'K/M' ... */
+	rblock.flags |= KRB5_KDB_DISALLOW_ALL_TIX;
+	if ((retval = kdb_ldap_create_principal(util_context, master_princ, MASTER_KEY, &rblock))) {
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+
+	/* Create 'krbtgt' ... */
+	rblock.flags = 0; /* reset the flags */
+	if ((retval = kdb_ldap_create_principal(util_context, &tgt_princ, TGT_KEY, &rblock))) {
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+
+	/* Create 'kadmin/admin' ... */
+	snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_ADMIN_SERVICE, global_params.realm);
+	if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+	rblock.max_life = ADMIN_LIFETIME;
+	rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
+	if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
+	    krb5_free_principal(util_context, p);
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+	krb5_free_principal(util_context, p);
+
+	/* Create 'kadmin/changepw' ... */
+	snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_CHANGEPW_SERVICE, global_params.realm);
+	if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+	rblock.max_life = CHANGEPW_LIFETIME;
+	rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED |
+	    KRB5_KDB_PWCHANGE_SERVICE;
+	if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
+	    krb5_free_principal(util_context, p);
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+	krb5_free_principal(util_context, p);
+
+	/* Create 'kadmin/history' ... */
+	snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_HIST_PRINCIPAL, global_params.realm);
+	if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+	rblock.max_life = global_params.max_life;
+	rblock.flags = 0;
+	if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
+	    krb5_free_principal(util_context, p);
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+	krb5_free_principal(util_context, p);
+
+	/* Create 'kadmin/<hostname>' ... */
+	if ((retval=krb5_sname_to_principal(util_context, NULL, "kadmin", KRB5_NT_SRV_HST, &p))) {
+	    com_err(argv[0], retval, "krb5_sname_to_principal, while adding entries to the database");
+	    goto err_nomsg;
+	}
+
+	if ((retval=krb5_copy_principal(util_context, p, &temp_p))) {
+	    com_err(argv[0], retval, "krb5_copy_principal, while adding entries to the database");
+	    goto err_nomsg;
+	}
+
+	/* change the realm portion to the default realm */
+	free(temp_p->realm.data);
+	temp_p->realm.length = strlen(util_context->default_realm);
+	temp_p->realm.data = strdup(util_context->default_realm);
+	if (temp_p->realm.data == NULL) {
+	    com_err(argv[0], ENOMEM, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+
+	rblock.max_life = ADMIN_LIFETIME;
+	rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
+	if ((retval = kdb_ldap_create_principal(util_context, temp_p, TGT_KEY, &rblock))) {
+	    krb5_free_principal(util_context, p);
+	    com_err(argv[0], retval, "while adding entries to the database");
+	    goto err_nomsg;
+	}
+	krb5_free_principal(util_context, temp_p);
+	krb5_free_principal(util_context, p);
+
+	if (oldcontainerref != NULL) {
+	    ldap_context->lrparams->containerref = oldcontainerref;
+	    oldcontainerref=NULL;
+	}
+    }
+
+#ifdef HAVE_EDIRECTORY
+    if ((mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
+	(mask & LDAP_REALM_PASSWDSERVERS)) {
+
+	printf("Changing rights for the service object. Please wait ... ");
+	fflush(stdout);
+
+	rightsmask =0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
+	    for (i=0; (rparams->kdcservers[i] != NULL); i++) {
+		if ((retval=krb5_ldap_add_service_rights(util_context,
+							 LDAP_KDC_SERVICE, rparams->kdcservers[i],
+							 rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    printf("failed\n");
+		    com_err(argv[0], retval, "while assigning rights to '%s'",
+			    rparams->realm_name);
+		    goto err_nomsg;
+		}
+	    }
+	}
+
+	rightsmask = 0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->adminservers != NULL)) {
+	    for (i=0; (rparams->adminservers[i] != NULL); i++) {
+		if ((retval=krb5_ldap_add_service_rights(util_context,
+							 LDAP_ADMIN_SERVICE, rparams->adminservers[i],
+							 rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    printf("failed\n");
+		    com_err(argv[0], retval, "while assigning rights to '%s'",
+			    rparams->realm_name);
+		    goto err_nomsg;
+		}
+	    }
+	}
+
+	rightsmask = 0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
+	    for (i=0; (rparams->passwdservers[i] != NULL); i++) {
+		if ((retval=krb5_ldap_add_service_rights(util_context,
+							 LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
+							 rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    printf("failed\n");
+		    com_err(argv[0], retval, "while assigning rights to '%s'",
+			    rparams->realm_name);
+		    goto err_nomsg;
+		}
+	    }
+	}
+
+	printf("done\n");
+    }
+#endif
+    /* The Realm creation is completed. Here is the end of transaction */
+    create_complete = TRUE;
+
+    /* Stash the master key only if '-s' option is specified */
+    if (do_stash || global_params.mask & KADM5_CONFIG_STASH_FILE) {
+	retval = krb5_def_store_mkey(util_context,
+				     global_params.stash_file,
+				     master_princ,
+				     &master_keyblock, NULL);
+	if (retval) {
+	    com_err(argv[0], errno, "while storing key");
+	    printf("Warning: couldn't stash master key.\n");
+	}
+    }
+
+    goto cleanup;
+
+
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+cleanup:
+    /* If the Realm creation is not complete, do the roll-back here */
+    if ((realm_obj_created) && (!create_complete))
+	krb5_ldap_delete_realm(util_context, global_params.realm);
+
+    if (rparams)
+	krb5_ldap_free_realm_params(rparams);
+
+    memset (pw_str, 0, sizeof (pw_str));
+
+    if (print_usage)
+	db_usage(CREATE_REALM);
+
+    if (retval) {
+	if (!no_msg) {
+	    com_err(argv[0], retval, "while creating realm '%s'",
+		    global_params.realm);
+	}
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/*
+ * This function will modify the attributes of a given realm object
+ */
+void kdb5_ldap_modify(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_error_code retval = 0;
+    krb5_ldap_realm_params *rparams = NULL;
+    krb5_boolean print_usage = FALSE;
+    krb5_boolean no_msg = FALSE;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+    int i = 0;
+    int mask = 0, rmask = 0, ret_mask = 0;
+    char **slist = {NULL};
+#ifdef HAVE_EDIRECTORY
+    int j = 0;
+    char *list[MAX_LIST_ENTRIES];
+    int existing_entries = 0, list_entries = 0;
+    int newkdcdn = 0, newadmindn = 0, newpwddn = 0;
+    char **tempstr = NULL;
+    char **oldkdcdns = NULL;
+    char **oldadmindns = NULL;
+    char **oldpwddns = NULL;
+    char **newkdcdns = NULL;
+    char **newsubtrees = NULL;
+    char **newadmindns = NULL;
+    char **newpwddns = NULL;
+    char **oldsubtrees = {NULL};
+    int rightsmask = 0;
+    int subtree_changed = 0;
+#endif
+
+    dal_handle = (kdb5_dal_handle *) util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    if (!(ldap_context)) {
+	retval = EINVAL;
+	goto cleanup;
+    }
+
+    if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+						     &(ldap_context->krbcontainer)))) {
+	com_err(argv[0], retval, "while reading Kerberos container information");
+	goto err_nomsg;
+    }
+
+    retval = krb5_ldap_read_realm_params(util_context,
+					 global_params.realm, &rparams, &rmask);
+    if (retval)
+	goto cleanup;
+    /* Parse the arguments */
+    for (i = 1; i < argc; i++) {
+	int k = 0;
+	if (!strcmp(argv[i], "-subtrees")) {
+	    if (++i > argc-1)
+		goto err_usage;
+
+	    if (rmask & LDAP_REALM_SUBTREE) {
+		if (rparams->subtree) {
+#ifdef HAVE_EDIRECTORY
+		    oldsubtrees =  (char **) calloc(rparams->subtreecount+1, sizeof(char *));
+		    if (oldsubtrees == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    for(k=0; rparams->subtree[k]!=NULL && rparams->subtreecount; k++) {
+			oldsubtrees[k] = strdup(rparams->subtree[k]);
+			if( oldsubtrees[k] == NULL ) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+#endif
+		    for(k=0; k<rparams->subtreecount && rparams->subtree[k]; k++)
+			free(rparams->subtree[k]);
+		    rparams->subtreecount=0;
+		}
+	    }
+	    if (strncmp(argv[i] ,"", strlen(argv[i]))!=0) {
+		slist =  (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *));
+		if (slist == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+		if (( retval = krb5_parse_list(argv[i], LIST_DELIMITER, slist))) {
+		    free(slist);
+		    slist = NULL;
+		    goto cleanup;
+		}
+
+		rparams->subtreecount=0;
+		while(slist[rparams->subtreecount]!=NULL)
+		    (rparams->subtreecount)++;
+		rparams->subtree =  slist;
+	    } else if(strncmp(argv[i], "", strlen(argv[i]))==0) {
+		 /* dont allow subtree value to be set at the root(NULL, "") of the tree */
+		    com_err(argv[0], EINVAL,
+			    "for subtree while modifying realm '%s'",
+			    global_params.realm);
+		    goto err_nomsg;
+	    }
+	    rparams->subtree[rparams->subtreecount] = NULL;
+	    mask |= LDAP_REALM_SUBTREE;
+	} else if (!strncmp(argv[i], "-containerref", strlen(argv[i]))) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    if(strncmp(argv[i], "", strlen(argv[i]))==0) {
+		 /* dont allow containerref value to be set at the root(NULL, "") of the tree */
+		 com_err(argv[0], EINVAL,
+			  "for container reference while modifying realm '%s'",
+			   global_params.realm);
+		 goto err_nomsg;
+	    }
+	    rparams->containerref = strdup(argv[i]);
+	    if (rparams->containerref == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_CONTREF;
+	} else if (!strcmp(argv[i], "-sscope")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    /* Possible values for search scope are
+	     * one (or 1) and sub (or 2)
+	     */
+	    if (strcasecmp(argv[i], "one") == 0) {
+		rparams->search_scope = 1;
+	    } else if (strcasecmp(argv[i], "sub") == 0) {
+		rparams->search_scope = 2;
+	    } else {
+		rparams->search_scope = atoi(argv[i]);
+		if ((rparams->search_scope != 1) &&
+		    (rparams->search_scope != 2)) {
+		    retval = EINVAL;
+		    com_err(argv[0], retval,
+			    "specified for search scope while modifying information of realm '%s'",
+			    global_params.realm);
+		    goto err_nomsg;
+		}
+	    }
+	    mask |= LDAP_REALM_SEARCHSCOPE;
+	}
+#ifdef HAVE_EDIRECTORY
+	else if (!strcmp(argv[i], "-kdcdn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+
+	    if ((rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers)) {
+		if (!oldkdcdns) {
+		    /* Store the old kdc dns list for removing rights */
+		    oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldkdcdns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->kdcservers[j] != NULL; j++) {
+			oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+			if (oldkdcdns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldkdcdns[j] = NULL;
+		}
+
+		krb5_free_list_entries(rparams->kdcservers);
+		free(rparams->kdcservers);
+	    }
+
+	    rparams->kdcservers = (char **)malloc(
+		sizeof(char *) * MAX_LIST_ENTRIES);
+	    if (rparams->kdcservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    memset(rparams->kdcservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  rparams->kdcservers))) {
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_KDCSERVERS;
+	    /* Going to replace the existing value by this new value. Hence
+	     * setting flag indicating that add or clear options will be ignored
+	     */
+	    newkdcdn = 1;
+	} else if (!strcmp(argv[i], "-clearkdcdn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    if ((!newkdcdn) && (rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers)) {
+		if (!oldkdcdns) {
+		    /* Store the old kdc dns list for removing rights */
+		    oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldkdcdns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->kdcservers[j] != NULL; j++) {
+			oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+			if (oldkdcdns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldkdcdns[j] = NULL;
+		}
+
+		memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+		    goto cleanup;
+		}
+		list_modify_str_array(&rparams->kdcservers, (const char **)list,
+				      LIST_MODE_DELETE);
+		mask |= LDAP_REALM_KDCSERVERS;
+		krb5_free_list_entries(list);
+	    }
+	} else if (!strcmp(argv[i], "-addkdcdn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    if (!newkdcdn) {
+		if ((rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers) && (!oldkdcdns)) {
+		    /* Store the old kdc dns list for removing rights */
+		    oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldkdcdns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j = 0; rparams->kdcservers[j] != NULL; j++) {
+			oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+			if (oldkdcdns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldkdcdns[j] = NULL;
+		}
+
+		memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+		    goto cleanup;
+		}
+		existing_entries = list_count_str_array(rparams->kdcservers);
+		list_entries = list_count_str_array(list);
+		if (rmask & LDAP_REALM_KDCSERVERS) {
+		    tempstr = (char **)realloc(
+			rparams->kdcservers,
+			sizeof(char *) * (existing_entries+list_entries+1));
+		    if (tempstr == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    rparams->kdcservers = tempstr;
+		} else {
+		    rparams->kdcservers = (char **)malloc(sizeof(char *) * (list_entries+1));
+		    if (rparams->kdcservers == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    memset(rparams->kdcservers, 0, sizeof(char *) * (list_entries+1));
+		}
+		list_modify_str_array(&rparams->kdcservers, (const char **)list,
+				      LIST_MODE_ADD);
+		mask |= LDAP_REALM_KDCSERVERS;
+	    }
+	} else if (!strcmp(argv[i], "-admindn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+
+	    if ((rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers)) {
+		if (!oldadmindns) {
+		    /* Store the old admin dns list for removing rights */
+		    oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldadmindns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->adminservers[j] != NULL; j++) {
+			oldadmindns[j] = strdup(rparams->adminservers[j]);
+			if (oldadmindns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldadmindns[j] = NULL;
+		}
+
+		krb5_free_list_entries(rparams->adminservers);
+		free(rparams->adminservers);
+	    }
+
+	    rparams->adminservers = (char **)malloc(
+		sizeof(char *) * MAX_LIST_ENTRIES);
+	    if (rparams->adminservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    memset(rparams->adminservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  rparams->adminservers))) {
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_ADMINSERVERS;
+	    /* Going to replace the existing value by this new value. Hence
+	     * setting flag indicating that add or clear options will be ignored
+	     */
+	    newadmindn = 1;
+	} else if (!strcmp(argv[i], "-clearadmindn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+
+	    if ((!newadmindn) && (rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers)) {
+		if (!oldadmindns) {
+		    /* Store the old admin dns list for removing rights */
+		    oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldadmindns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->adminservers[j] != NULL; j++) {
+			oldadmindns[j] = strdup(rparams->adminservers[j]);
+			if (oldadmindns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldadmindns[j] = NULL;
+		}
+
+		memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+		    goto cleanup;
+		}
+		list_modify_str_array(&rparams->adminservers, (const char **)list,
+				      LIST_MODE_DELETE);
+		mask |= LDAP_REALM_ADMINSERVERS;
+		krb5_free_list_entries(list);
+	    }
+	} else if (!strcmp(argv[i], "-addadmindn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    if (!newadmindn) {
+		if ((rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers) && (!oldadmindns)) {
+		    /* Store the old admin dns list for removing rights */
+		    oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldadmindns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->adminservers[j] != NULL; j++) {
+			oldadmindns[j] = strdup(rparams->adminservers[j]);
+			if (oldadmindns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldadmindns[j] = NULL;
+		}
+
+		memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+		    goto cleanup;
+		}
+		existing_entries = list_count_str_array(rparams->adminservers);
+		list_entries = list_count_str_array(list);
+		if (rmask & LDAP_REALM_ADMINSERVERS) {
+		    tempstr = (char **)realloc(
+			rparams->adminservers,
+			sizeof(char *) * (existing_entries+list_entries+1));
+		    if (tempstr == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    rparams->adminservers = tempstr;
+		} else {
+		    rparams->adminservers = (char **)malloc(sizeof(char *) * (list_entries+1));
+		    if (rparams->adminservers == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    memset(rparams->adminservers, 0, sizeof(char *) * (list_entries+1));
+		}
+		list_modify_str_array(&rparams->adminservers, (const char **)list,
+				      LIST_MODE_ADD);
+		mask |= LDAP_REALM_ADMINSERVERS;
+	    }
+	} else if (!strcmp(argv[i], "-pwddn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+
+	    if ((rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers)) {
+		if (!oldpwddns) {
+		    /* Store the old pwd dns list for removing rights */
+		    oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldpwddns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->passwdservers[j] != NULL; j++) {
+			oldpwddns[j] = strdup(rparams->passwdservers[j]);
+			if (oldpwddns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldpwddns[j] = NULL;
+		}
+
+		krb5_free_list_entries(rparams->passwdservers);
+		free(rparams->passwdservers);
+	    }
+
+	    rparams->passwdservers = (char **)malloc(
+		sizeof(char *) * MAX_LIST_ENTRIES);
+	    if (rparams->passwdservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    memset(rparams->passwdservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  rparams->passwdservers))) {
+		goto cleanup;
+	    }
+	    mask |= LDAP_REALM_PASSWDSERVERS;
+	    /* Going to replace the existing value by this new value. Hence
+	     * setting flag indicating that add or clear options will be ignored
+	     */
+	    newpwddn = 1;
+	} else if (!strcmp(argv[i], "-clearpwddn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+
+	    if ((!newpwddn) && (rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers)) {
+		if (!oldpwddns) {
+		    /* Store the old pwd dns list for removing rights */
+		    oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldpwddns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->passwdservers[j] != NULL; j++) {
+			oldpwddns[j] = strdup(rparams->passwdservers[j]);
+			if (oldpwddns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldpwddns[j] = NULL;
+		}
+
+		memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+		    goto cleanup;
+		}
+		list_modify_str_array(&rparams->passwdservers, (const char**)list,
+				      LIST_MODE_DELETE);
+		mask |= LDAP_REALM_PASSWDSERVERS;
+		krb5_free_list_entries(list);
+	    }
+	} else if (!strcmp(argv[i], "-addpwddn")) {
+	    if (++i > argc-1)
+		goto err_usage;
+	    if (!newpwddn) {
+		if ((rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers) && (!oldpwddns)) {
+		    /* Store the old pwd dns list for removing rights */
+		    oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldpwddns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j=0; rparams->passwdservers[j] != NULL; j++) {
+			oldpwddns[j] = strdup(rparams->passwdservers[j]);
+			if (oldpwddns[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldpwddns[j] = NULL;
+		}
+
+		memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+		    goto cleanup;
+		}
+		existing_entries = list_count_str_array(rparams->passwdservers);
+		list_entries = list_count_str_array(list);
+		if (rmask & LDAP_REALM_PASSWDSERVERS) {
+		    tempstr = (char **)realloc(
+			rparams->passwdservers,
+			sizeof(char *) * (existing_entries+list_entries+1));
+		    if (tempstr == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    rparams->passwdservers = tempstr;
+		} else {
+		    rparams->passwdservers = (char **)malloc(sizeof(char *) * (list_entries+1));
+		    if (rparams->passwdservers == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    memset(rparams->passwdservers, 0, sizeof(char *) * (list_entries+1));
+		}
+		list_modify_str_array(&rparams->passwdservers, (const char**)list,
+				      LIST_MODE_ADD);
+		mask |= LDAP_REALM_PASSWDSERVERS;
+	    }
+	}
+#endif
+	else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) {
+	    mask|=ret_mask;
+	} else {
+	    printf("'%s' is an invalid option\n", argv[i]);
+	    goto err_usage;
+	}
+    }
+
+    if ((retval = krb5_ldap_modify_realm(util_context,
+					 /* global_params.realm, */ rparams, mask))) {
+	goto cleanup;
+    }
+
+#ifdef HAVE_EDIRECTORY
+    if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_KDCSERVERS) ||
+	(mask & LDAP_REALM_ADMINSERVERS) || (mask & LDAP_REALM_PASSWDSERVERS)) {
+
+	printf("Changing rights for the service object. Please wait ... ");
+	fflush(stdout);
+
+	if (!(mask & LDAP_REALM_SUBTREE)) {
+	    if (rparams->subtree != NULL) {
+		for(i=0; rparams->subtree[i]!=NULL;i++) {
+		    oldsubtrees[i] = strdup(rparams->subtree[i]);
+		    if( oldsubtrees[i] == NULL ) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		}
+	    }
+	}
+
+	if ((mask & LDAP_REALM_SUBTREE)) {
+	    int check_subtree = 1;
+
+	    newsubtrees = (char**) calloc(rparams->subtreecount, sizeof(char*));
+
+	    if (newsubtrees == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ( (rparams != NULL) && (rparams->subtree != NULL) ) {
+		for (j=0; j<rparams->subtreecount && rparams->subtree[j]!= NULL; j++) {
+		    newsubtrees[j] = strdup(rparams->subtree[j]);
+		    if (newsubtrees[j] == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		}
+		newsubtrees[j] = NULL;
+	    }
+	    for(j=0;oldsubtrees[j]!=NULL;j++) {
+		check_subtree = 1;
+		for(i=0; ( (oldsubtrees[j] && !rparams->subtree[i]) ||
+			(!oldsubtrees[j] && rparams->subtree[i])); i++) {
+		    if(strcasecmp( oldsubtrees[j], rparams->subtree[i]) == 0) {
+			check_subtree = 0;
+			continue;
+		    }
+		}
+		if (check_subtree != 0) {
+		    subtree_changed=1;
+		    break;
+		}
+	    }
+	    /* this will return list of the disjoint members */
+	    disjoint_members( oldsubtrees, newsubtrees);
+	}
+
+	if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_KDCSERVERS)) {
+
+	    newkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+	    if (newkdcdns == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
+		for (j=0;  rparams->kdcservers[j]!= NULL; j++) {
+		    newkdcdns[j] = strdup(rparams->kdcservers[j]);
+		    if (newkdcdns[j] == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		}
+		newkdcdns[j] = NULL;
+	    }
+
+	    if (!subtree_changed) {
+		disjoint_members(oldkdcdns, newkdcdns);
+	    } else { /* Only the subtrees was changed. Remove the rights on the old subtrees. */
+		if (!(mask & LDAP_REALM_KDCSERVERS)) {
+
+		    oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldkdcdns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
+			for (j=0;  rparams->kdcservers[j]!= NULL; j++) {
+			    oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+			    if (oldkdcdns[j] == NULL) {
+				retval = ENOMEM;
+				goto cleanup;
+			    }
+			}
+			oldkdcdns[j] = NULL;
+		    }
+		}
+	    }
+
+	    rightsmask =0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+	    /* Remove the rights on the old subtrees */
+	    if (oldkdcdns) {
+		for (i=0; (oldkdcdns[i] != NULL); i++) {
+		    if ((retval=krb5_ldap_delete_service_rights(util_context,
+								LDAP_KDC_SERVICE, oldkdcdns[i],
+								rparams->realm_name, oldsubtrees, rightsmask)) != 0) {
+			printf("failed\n");
+			com_err(argv[0], retval, "while assigning rights '%s'",
+				rparams->realm_name);
+			goto err_nomsg;
+		    }
+		}
+	    }
+
+	    rightsmask =0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+	    if (newkdcdns) {
+		for (i=0; (newkdcdns[i] != NULL); i++) {
+
+		    if ((retval=krb5_ldap_add_service_rights(util_context,
+							     LDAP_KDC_SERVICE, newkdcdns[i], rparams->realm_name,
+							     rparams->subtree, rightsmask)) != 0) {
+			printf("failed\n");
+			com_err(argv[0], retval, "while assigning rights to '%s'",
+				rparams->realm_name);
+			goto err_nomsg;
+		    }
+		}
+	    }
+	}
+
+	if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_ADMINSERVERS)) {
+
+	    newadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+	    if (newadmindns == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ((rparams != NULL) && (rparams->adminservers != NULL)) {
+		for (j=0;  rparams->adminservers[j]!= NULL; j++) {
+		    newadmindns[j] = strdup(rparams->adminservers[j]);
+		    if (newadmindns[j] == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		}
+		newadmindns[j] = NULL;
+	    }
+
+	    if (!subtree_changed) {
+		disjoint_members(oldadmindns, newadmindns);
+	    } else { /* Only the subtrees was changed. Remove the rights on the old subtrees. */
+		if (!(mask & LDAP_REALM_ADMINSERVERS)) {
+
+		    oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldadmindns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    if ((rparams != NULL) && (rparams->adminservers != NULL)) {
+			for (j=0;  rparams->adminservers[j]!= NULL; j++) {
+			    oldadmindns[j] = strdup(rparams->adminservers[j]);
+			    if (oldadmindns[j] == NULL) {
+				retval = ENOMEM;
+				goto cleanup;
+			    }
+			}
+			oldadmindns[j] = NULL;
+		    }
+		}
+	    }
+
+	    rightsmask = 0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+	    /* Remove the rights on the old subtrees */
+	    if (oldadmindns) {
+		for (i=0; (oldadmindns[i] != NULL); i++) {
+
+		    if ((retval=krb5_ldap_delete_service_rights(util_context,
+								LDAP_ADMIN_SERVICE, oldadmindns[i],
+								rparams->realm_name, oldsubtrees, rightsmask)) != 0) {
+			printf("failed\n");
+			com_err(argv[0], retval, "while assigning rights '%s'",
+				rparams->realm_name);
+			goto err_nomsg;
+		    }
+		}
+	    }
+
+	    rightsmask = 0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+	    /* Add rights on the new subtree for all the kdc dns */
+	    if (newadmindns) {
+		for (i=0; (newadmindns[i] != NULL); i++) {
+
+		    if ((retval=krb5_ldap_add_service_rights(util_context,
+							     LDAP_ADMIN_SERVICE, newadmindns[i],
+							     rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+			printf("failed\n");
+			com_err(argv[0], retval, "while assigning rights to '%s'",
+				rparams->realm_name);
+			goto err_nomsg;
+		    }
+		}
+	    }
+	}
+
+
+	if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_PASSWDSERVERS)) {
+
+	    newpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+	    if (newpwddns == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
+		for (j=0;  rparams->passwdservers[j]!= NULL; j++) {
+		    newpwddns[j] = strdup(rparams->passwdservers[j]);
+		    if (newpwddns[j] == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		}
+		newpwddns[j] = NULL;
+	    }
+
+	    if (!subtree_changed) {
+		disjoint_members(oldpwddns, newpwddns);
+	    } else { /* Only the subtrees was changed. Remove the rights on the old subtrees. */
+		if (!(mask & LDAP_REALM_ADMINSERVERS)) {
+
+		    oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldpwddns == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
+			for (j=0;  rparams->passwdservers[j]!= NULL; j++) {
+			    oldpwddns[j] = strdup(rparams->passwdservers[j]);
+			    if (oldpwddns[j] == NULL) {
+				retval = ENOMEM;
+				goto cleanup;
+			    }
+			}
+			oldpwddns[j] = NULL;
+		    }
+		}
+	    }
+
+	    rightsmask =0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+	    /* Remove the rights on the old subtrees */
+	    if (oldpwddns) {
+		for (i=0; (oldpwddns[i] != NULL); i++) {
+		    if ((retval = krb5_ldap_delete_service_rights(util_context,
+								  LDAP_PASSWD_SERVICE, oldpwddns[i],
+								  rparams->realm_name, oldsubtrees, rightsmask))) {
+			printf("failed\n");
+			com_err(argv[0], retval, "while assigning rights '%s'",
+				rparams->realm_name);
+			goto err_nomsg;
+		    }
+		}
+	    }
+
+	    rightsmask =0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+	    /* Add rights on the new subtree for all the kdc dns */
+	    if (newpwddns) {
+		for (i=0; (newpwddns[i] != NULL); i++) {
+		    if ((retval = krb5_ldap_add_service_rights(util_context,
+							       LDAP_PASSWD_SERVICE, newpwddns[i],
+							       rparams->realm_name, rparams->subtree, rightsmask))) {
+			printf("failed\n");
+			com_err(argv[0], retval, "while assigning rights to '%s'",
+				rparams->realm_name);
+			goto err_nomsg;
+		    }
+		}
+	    }
+	}
+
+	printf("done\n");
+    }
+#endif
+
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+cleanup:
+    krb5_ldap_free_realm_params(rparams);
+
+
+#ifdef HAVE_EDIRECTORY
+    if (oldkdcdns) {
+	for (i=0; oldkdcdns[i] != NULL; i++)
+	    free(oldkdcdns[i]);
+	free(oldkdcdns);
+    }
+    if (oldpwddns) {
+	for (i=0; oldpwddns[i] != NULL; i++)
+	    free(oldpwddns[i]);
+	free(oldpwddns);
+    }
+    if (oldadmindns) {
+	for (i=0; oldadmindns[i] != NULL; i++)
+	    free(oldadmindns[i]);
+	free(oldadmindns);
+    }
+    if (newkdcdns) {
+	for (i=0; newkdcdns[i] != NULL; i++)
+	    free(newkdcdns[i]);
+	free(newkdcdns);
+    }
+    if (newpwddns) {
+	for (i=0; newpwddns[i] != NULL; i++)
+	    free(newpwddns[i]);
+	free(newpwddns);
+    }
+    if (newadmindns) {
+	for (i=0; newadmindns[i] != NULL; i++)
+	    free(newadmindns[i]);
+	free(newadmindns);
+    }
+    if (oldsubtrees) {
+	for (i=0;oldsubtrees[i]!=NULL; i++)
+	    free(oldsubtrees[i]);
+	free(oldsubtrees);
+    }
+    if (newsubtrees) {
+	for (i=0;newsubtrees[i]!=NULL; i++)
+	    free(newsubtrees[i]);
+	free(oldsubtrees);
+    }
+#endif
+    if (print_usage) {
+	db_usage(MODIFY_REALM);
+    }
+
+    if (retval) {
+	if (!no_msg)
+	    com_err(argv[0], retval, "while modifying information of realm '%s'",
+		    global_params.realm);
+	exit_status++;
+    }
+
+    return;
+}
+
+
+
+/*
+ * This function displays the attributes of a Realm
+ */
+void kdb5_ldap_view(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_ldap_realm_params *rparams = NULL;
+    krb5_error_code retval = 0;
+    kdb5_dal_handle *dal_handle=NULL;
+    krb5_ldap_context *ldap_context=NULL;
+    int mask = 0;
+
+    dal_handle = (kdb5_dal_handle *) util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    if (!(ldap_context)) {
+	retval = EINVAL;
+	com_err(argv[0], retval, "while initializing database");
+	exit_status++;
+	return;
+    }
+
+    /* Read the kerberos container information */
+    if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+						     &(ldap_context->krbcontainer))) != 0) {
+	com_err(argv[0], retval, "while reading kerberos container information");
+	exit_status++;
+	return;
+    }
+
+    if ((retval = krb5_ldap_read_realm_params(util_context,
+					      global_params.realm, &rparams, &mask)) || (!rparams)) {
+	com_err(argv[0], retval, "while reading information of realm '%s'",
+		global_params.realm);
+	exit_status++;
+	return;
+    }
+    print_realm_params(rparams, mask);
+    krb5_ldap_free_realm_params(rparams);
+
+    return;
+}
+
+static char *strdur(duration)
+    time_t duration;
+{
+    static char out[50];
+    int neg, days, hours, minutes, seconds;
+
+    if (duration < 0) {
+	duration *= -1;
+	neg = 1;
+    } else
+	neg = 0;
+    days = duration / (24 * 3600);
+    duration %= 24 * 3600;
+    hours = duration / 3600;
+    duration %= 3600;
+    minutes = duration / 60;
+    duration %= 60;
+    seconds = duration;
+    sprintf(out, "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
+	    days, days == 1 ? "day" : "days",
+	    hours, minutes, seconds);
+    return out;
+}
+
+/*
+ * This function prints the attributes of a given realm to the
+ * standard output.
+ */
+static void print_realm_params(krb5_ldap_realm_params *rparams, int mask)
+{
+    char **slist = NULL;
+    int num_entry_printed = 0, i = 0;
+
+    /* Print the Realm Attributes on the standard output */
+    printf("%25s: %-50s\n", "Realm Name", global_params.realm);
+    if (mask & LDAP_REALM_SUBTREE) {
+	for (i=0; rparams->subtree[i]!=NULL; i++)
+	    printf("%25s: %-50s\n", "Subtree", rparams->subtree[i]);
+    }
+    if (mask & LDAP_REALM_CONTREF)
+	printf("%25s: %-50s\n", "Principal Container Reference", rparams->containerref);
+    if (mask & LDAP_REALM_SEARCHSCOPE) {
+	if ((rparams->search_scope != 1) &&
+	    (rparams->search_scope != 2)) {
+	    printf("%25s: %-50s\n", "SearchScope", "Invalid !");
+	} else {
+	    printf("%25s: %-50s\n", "SearchScope",
+		   (rparams->search_scope == 1) ? "ONE" : "SUB");
+	}
+    }
+    if (mask & LDAP_REALM_KDCSERVERS) {
+	printf("%25s:", "KDC Services");
+	if (rparams->kdcservers != NULL) {
+	    num_entry_printed = 0;
+	    for (slist = rparams->kdcservers; *slist != NULL; slist++) {
+		if (num_entry_printed)
+		    printf(" %25s %-50s\n", " ", *slist);
+		else
+		    printf(" %-50s\n", *slist);
+		num_entry_printed++;
+	    }
+	}
+	if (num_entry_printed == 0)
+	    printf("\n");
+    }
+    if (mask & LDAP_REALM_ADMINSERVERS) {
+	printf("%25s:", "Admin Services");
+	if (rparams->adminservers != NULL) {
+	    num_entry_printed = 0;
+	    for (slist = rparams->adminservers; *slist != NULL; slist++) {
+		if (num_entry_printed)
+		    printf(" %25s %-50s\n", " ", *slist);
+		else
+		    printf(" %-50s\n", *slist);
+		num_entry_printed++;
+	    }
+	}
+	if (num_entry_printed == 0)
+	    printf("\n");
+    }
+    if (mask & LDAP_REALM_PASSWDSERVERS) {
+	printf("%25s:", "Passwd Services");
+	if (rparams->passwdservers != NULL) {
+	    num_entry_printed = 0;
+	    for (slist = rparams->passwdservers; *slist != NULL; slist++) {
+		if (num_entry_printed)
+		    printf(" %25s %-50s\n", " ", *slist);
+		else
+		    printf(" %-50s\n", *slist);
+		num_entry_printed++;
+	    }
+	}
+	if (num_entry_printed == 0)
+	    printf("\n");
+    }
+    if (mask & LDAP_REALM_MAXTICKETLIFE) {
+	printf("%25s:", "Maximum Ticket Life");
+	printf(" %s \n", strdur(rparams->max_life));
+    }
+
+    if (mask & LDAP_REALM_MAXRENEWLIFE) {
+	printf("%25s:", "Maximum Renewable Life");
+	printf(" %s \n", strdur(rparams->max_renewable_life));
+    }
+
+    if (mask & LDAP_REALM_KRBTICKETFLAGS) {
+	int ticketflags = rparams->tktflags;
+
+	printf("%25s: ", "Ticket flags");
+	if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED)
+	    printf("%s ","DISALLOW_POSTDATED");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE)
+	    printf("%s ","DISALLOW_FORWARDABLE");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE)
+	    printf("%s ","DISALLOW_RENEWABLE");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE)
+	    printf("%s ","DISALLOW_PROXIABLE");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY)
+	    printf("%s ","DISALLOW_DUP_SKEY");
+
+	if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH)
+	    printf("%s ","REQUIRES_PRE_AUTH");
+
+	if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH)
+	    printf("%s ","REQUIRES_HW_AUTH");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_SVR)
+	    printf("%s ","DISALLOW_SVR");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED)
+	    printf("%s ","DISALLOW_TGT_BASED");
+
+	if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX)
+	    printf("%s ","DISALLOW_ALL_TIX");
+
+	if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE)
+	    printf("%s ","REQUIRES_PWCHANGE");
+
+	if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE)
+	    printf("%s ","PWCHANGE_SERVICE");
+
+	printf("\n");
+    }
+
+
+    return;
+}
+
+
+
+/*
+ * This function lists the Realm(s) present under the Kerberos container
+ * on the LDAP Server.
+ */
+void kdb5_ldap_list(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char **list = NULL;
+    char **plist = NULL;
+    krb5_error_code retval = 0;
+    kdb5_dal_handle *dal_handle=NULL;
+    krb5_ldap_context *ldap_context=NULL;
+
+    dal_handle = (kdb5_dal_handle *)util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    if (!(ldap_context)) {
+	retval = EINVAL;
+	exit_status++;
+	return;
+    }
+
+    /* Read the kerberos container information */
+    if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+						     &(ldap_context->krbcontainer))) != 0) {
+	com_err(argv[0], retval, "while reading kerberos container information");
+	exit_status++;
+	return;
+    }
+
+    retval = krb5_ldap_list_realm(util_context, &list);
+    if (retval != 0) {
+	krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+	ldap_context->krbcontainer = NULL;
+	com_err (argv[0], retval, "while listing realms");
+	exit_status++;
+	return;
+    }
+    /* This is to handle the case of realm not present */
+    if (list == NULL) {
+	krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+	ldap_context->krbcontainer = NULL;
+	return;
+    }
+
+    for (plist = list; *plist != NULL; plist++) {
+	printf("%s\n", *plist);
+    }
+    krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+    ldap_context->krbcontainer = NULL;
+    krb5_free_list_entries(list);
+    free(list);
+
+    return;
+}
+
+/*
+ * Duplicating the following two functions here because
+ * 'krb5_dbe_update_tl_data' uses backend specific memory allocation. The catch
+ * here is that the backend is not initialized - kdb5_ldap_util doesn't go
+ * through DAL.
+ * 1. krb5_dbe_update_tl_data
+ * 2. krb5_dbe_update_mod_princ_data
+ */
+
+/* Start duplicate code ... */
+
+static krb5_error_code
+krb5_dbe_update_tl_data_new(context, entry, new_tl_data)
+    krb5_context context;
+    krb5_db_entry *entry;
+    krb5_tl_data *new_tl_data;
+{
+    krb5_tl_data *tl_data = NULL;
+    krb5_octet *tmp;
+
+    /* copy the new data first, so we can fail cleanly if malloc()
+     * fails */
+/*
+    if ((tmp =
+	 (krb5_octet *) krb5_db_alloc(context, NULL,
+				      new_tl_data->tl_data_length)) == NULL)
+*/
+    if ((tmp = (krb5_octet *) malloc (new_tl_data->tl_data_length)) == NULL)
+	return (ENOMEM);
+
+    /* Find an existing entry of the specified type and point at
+     * it, or NULL if not found */
+
+    if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) {	/* db_args can be multiple */
+	for (tl_data = entry->tl_data; tl_data;
+	     tl_data = tl_data->tl_data_next)
+	    if (tl_data->tl_data_type == new_tl_data->tl_data_type)
+		break;
+    }
+
+    /* if necessary, chain a new record in the beginning and point at it */
+
+    if (!tl_data) {
+/*
+	if ((tl_data =
+	     (krb5_tl_data *) krb5_db_alloc(context, NULL,
+					    sizeof(krb5_tl_data)))
+	    == NULL) {
+*/
+	if ((tl_data = (krb5_tl_data *) malloc (sizeof(krb5_tl_data))) == NULL) {
+	    free(tmp);
+	    return (ENOMEM);
+	}
+	memset(tl_data, 0, sizeof(krb5_tl_data));
+	tl_data->tl_data_next = entry->tl_data;
+	entry->tl_data = tl_data;
+	entry->n_tl_data++;
+    }
+
+    /* fill in the record */
+
+    if (tl_data->tl_data_contents)
+	krb5_db_free(context, tl_data->tl_data_contents);
+
+    tl_data->tl_data_type = new_tl_data->tl_data_type;
+    tl_data->tl_data_length = new_tl_data->tl_data_length;
+    tl_data->tl_data_contents = tmp;
+    memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
+
+    return (0);
+}
+
+static krb5_error_code
+krb5_dbe_update_mod_princ_data_new(context, entry, mod_date, mod_princ)
+    krb5_context	  context;
+    krb5_db_entry	* entry;
+    krb5_timestamp	  mod_date;
+    krb5_const_principal  mod_princ;
+{
+    krb5_tl_data          tl_data;
+
+    krb5_error_code 	  retval = 0;
+    krb5_octet		* nextloc = 0;
+    char		* unparse_mod_princ = 0;
+    unsigned int	unparse_mod_princ_size;
+
+    if ((retval = krb5_unparse_name(context, mod_princ,
+				    &unparse_mod_princ)))
+	return(retval);
+
+    unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
+
+    if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
+	== NULL) {
+	free(unparse_mod_princ);
+	return(ENOMEM);
+    }
+
+    tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
+    tl_data.tl_data_length = unparse_mod_princ_size + 4;
+    tl_data.tl_data_contents = nextloc;
+
+    /* Mod Date */
+    krb5_kdb_encode_int32(mod_date, nextloc);
+
+    /* Mod Princ */
+    memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);
+
+    retval = krb5_dbe_update_tl_data_new(context, entry, &tl_data);
+
+    free(unparse_mod_princ);
+    free(nextloc);
+
+    return(retval);
+}
+
+static krb5_error_code
+kdb_ldap_tgt_keysalt_iterate(ksent, ptr)
+    krb5_key_salt_tuple *ksent;
+    krb5_pointer        ptr;
+{
+    krb5_context        context;
+    krb5_error_code     kret;
+    struct iterate_args *iargs;
+    krb5_keyblock       key;
+    krb5_int32          ind;
+    krb5_data   pwd;
+    krb5_db_entry       *entry;
+
+    iargs = (struct iterate_args *) ptr;
+    kret = 0;
+
+    context = iargs->ctx;
+    entry = iargs->dbentp;
+
+    /*
+     * Convert the master key password into a key for this particular
+     * encryption system.
+     */
+    pwd.data = mkey_password;
+    pwd.length = strlen(mkey_password);
+    kret = krb5_c_random_seed(context, &pwd);
+    if (kret)
+	return kret;
+
+    /*if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {*/
+    if ((entry->key_data =
+	     (krb5_key_data *) realloc(entry->key_data,
+					    (sizeof(krb5_key_data) *
+					    (entry->n_key_data + 1)))) == NULL)
+	return (ENOMEM);
+
+    memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
+    ind = entry->n_key_data++;
+
+    if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype,
+					&key))) {
+	kret = krb5_dbekd_encrypt_key_data(context,
+					   iargs->rblock->key,
+					   &key,
+					   NULL,
+					   1,
+					   &entry->key_data[ind]);
+	krb5_free_keyblock_contents(context, &key);
+    }
+    /*}*/
+
+    return(kret);
+}
+/* End duplicate code */
+
+/*
+ * This function creates service principals when
+ * creating the realm object.
+ */
+static int
+kdb_ldap_create_principal (context, princ, op, pblock)
+    krb5_context context;
+    krb5_principal princ;
+    enum ap_op op;
+    struct realm_info *pblock;
+{
+    int              retval=0, currlen=0, princtype = 2 /* Service Principal */;
+    unsigned char    *curr=NULL;
+    krb5_tl_data     *tl_data=NULL;
+    krb5_db_entry    entry;
+    int              nentry=1;
+    long             mask = 0;
+    krb5_keyblock    key;
+    int              kvno = 0;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+    struct iterate_args   iargs;
+    krb5_data       *pdata;
+
+    if ((pblock == NULL) || (context == NULL)) {
+	retval = EINVAL;
+	goto cleanup;
+    }
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    if (!(ldap_context)) {
+	retval = EINVAL;
+	goto cleanup;
+    }
+
+    memset(&entry, 0, sizeof(entry));
+
+    tl_data = malloc(sizeof(*tl_data));
+    if (tl_data == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    memset(tl_data, 0, sizeof(*tl_data));
+    tl_data->tl_data_length = 1 + 2 + 2 + 1 + 2 + 4;
+    tl_data->tl_data_type = 7; /* KDB_TL_USER_INFO */
+    curr = tl_data->tl_data_contents = malloc(tl_data->tl_data_length);
+    if (tl_data->tl_data_contents == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    memset(curr, 1, 1); /* Passing the mask as principal type */
+    curr += 1;
+    currlen = 2;
+    STORE16_INT(curr, currlen);
+    curr += currlen;
+    STORE16_INT(curr, princtype);
+    curr += currlen;
+
+    mask |= KADM5_PRINCIPAL;
+    mask |= KADM5_ATTRIBUTES ;
+    mask |= KADM5_MAX_LIFE ;
+    mask |= KADM5_MAX_RLIFE ;
+    mask |= KADM5_PRINC_EXPIRE_TIME ;
+    mask |= KADM5_KEY_DATA;
+
+    entry.tl_data = tl_data;
+    entry.n_tl_data += 1;
+    /* Set the creator's name */
+    {
+	krb5_timestamp now;
+	if ((retval = krb5_timeofday(context, &now)))
+	    goto cleanup;
+	if ((retval = krb5_dbe_update_mod_princ_data_new(context, &entry,
+			now, &db_create_princ)))
+	    goto cleanup;
+    }
+    entry.attributes = pblock->flags;
+    entry.max_life = pblock->max_life;
+    entry.max_renewable_life = pblock->max_rlife;
+    entry.expiration = pblock->expiration;
+    entry.mask = mask;
+    if ((retval = krb5_copy_principal(context, princ, &entry.princ)))
+	goto cleanup;
+
+
+    switch (op) {
+    case TGT_KEY:
+	if ((pdata = krb5_princ_component(context, princ, 1)) &&
+	    pdata->length == strlen("history") &&
+	    !memcmp(pdata->data, "history", strlen("history"))) {
+
+	    /* Allocate memory for storing the key */
+	    if ((entry.key_data = (krb5_key_data *) malloc(
+					      sizeof(krb5_key_data))) == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    memset(entry.key_data, 0, sizeof(krb5_key_data));
+	    entry.n_key_data++;
+
+	    retval = krb5_c_make_random_key(context, global_params.enctype, &key);
+	    if (retval) {
+		goto cleanup;
+	    }
+	    kvno = 1; /* New key is getting set */
+	    retval = krb5_dbekd_encrypt_key_data(context,
+					&ldap_context->lrparams->mkey,
+					&key, NULL, kvno,
+					&entry.key_data[entry.n_key_data - 1]);
+	    krb5_free_keyblock_contents(context, &key);
+	    if (retval) {
+		goto cleanup;
+	    }
+	} else {
+	    /*retval = krb5_c_make_random_key(context, 16, &key) ;*/
+	    iargs.ctx = context;
+	    iargs.rblock = pblock;
+	    iargs.dbentp = &entry;
+
+	    /*
+	     * Iterate through the key/salt list, ignoring salt types.
+	     */
+	    if ((retval = krb5_keysalt_iterate(pblock->kslist,
+					       pblock->nkslist,
+					       1,
+					       kdb_ldap_tgt_keysalt_iterate,
+					       (krb5_pointer) &iargs)))
+		return retval;
+	}
+	break;
+
+    case MASTER_KEY:
+	/* Allocate memory for storing the key */
+	if ((entry.key_data = (krb5_key_data *) malloc(
+					      sizeof(krb5_key_data))) == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+
+	memset(entry.key_data, 0, sizeof(krb5_key_data));
+	entry.n_key_data++;
+	kvno = 1; /* New key is getting set */
+	retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
+					 &ldap_context->lrparams->mkey,
+					 NULL, kvno,
+					 &entry.key_data[entry.n_key_data - 1]);
+	if (retval) {
+	    goto cleanup;
+	}
+	break;
+
+    case NULL_KEY:
+    default:
+	break;
+    } /* end of switch */
+
+    retval = krb5_ldap_put_principal(context, &entry, &nentry, NULL);
+    if (retval) {
+	com_err(NULL, retval, "while adding entries to database");
+	goto cleanup;
+    }
+
+cleanup:
+    krb5_dbe_free_contents(context, &entry);
+    return retval;
+}
+
+
+/*
+ * This function destroys the realm object and the associated principals
+ */
+void
+kdb5_ldap_destroy(argc, argv)
+    int argc;
+    char *argv[];
+{
+    extern char *optarg;
+    extern int optind;
+    int optchar = 0;
+    char buf[5] = {0};
+    krb5_error_code retval = 0;
+    int force = 0;
+    int mask = 0;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context = NULL;
+#ifdef HAVE_EDIRECTORY
+    int i = 0, rightsmask = 0;
+    krb5_ldap_realm_params *rparams = NULL;
+#endif
+
+    optind = 1;
+    while ((optchar = getopt(argc, argv, "f")) != -1) {
+	switch (optchar) {
+	case 'f':
+	    force++;
+	    break;
+	case '?':
+	default:
+	    db_usage(DESTROY_REALM);
+	    return;
+	    /*NOTREACHED*/
+	}
+    }
+
+    if (!force) {
+	printf("Deleting KDC database of '%s', are you sure?\n", global_params.realm);
+	printf("(type 'yes' to confirm)? ");
+	if (fgets(buf, sizeof(buf), stdin) == NULL) {
+	    exit_status++;
+	    return;
+	}
+	if (strcmp(buf, yes)) {
+	    exit_status++;
+	    return;
+	}
+	printf("OK, deleting database of '%s'...\n", global_params.realm);
+    }
+
+    dal_handle = (kdb5_dal_handle *)util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    if (!(ldap_context)) {
+	com_err(argv[0], EINVAL, "while initializing database");
+	exit_status++;
+	return;
+    }
+
+    /* Read the kerberos container from the LDAP Server */
+    if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+						     &(ldap_context->krbcontainer))) != 0) {
+	com_err(argv[0], retval, "while reading kerberos container information");
+	exit_status++;
+	return;
+    }
+
+    /* Read the Realm information from the LDAP Server */
+    if ((retval = krb5_ldap_read_realm_params(util_context, global_params.realm,
+					      &(ldap_context->lrparams), &mask)) != 0) {
+	com_err(argv[0], retval, "while reading realm information");
+	exit_status++;
+	return;
+    }
+
+#ifdef HAVE_EDIRECTORY
+    if ((mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
+	(mask & LDAP_REALM_PASSWDSERVERS)) {
+
+	printf("Changing rights for the service object. Please wait ... ");
+	fflush(stdout);
+
+	rparams = ldap_context->lrparams;
+	rightsmask = 0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
+	    for (i=0; (rparams->kdcservers[i] != NULL); i++) {
+		if ((retval = krb5_ldap_delete_service_rights(util_context,
+							      LDAP_KDC_SERVICE, rparams->kdcservers[i],
+							      rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    printf("failed\n");
+		    com_err(argv[0], retval, "while assigning rights to '%s'",
+			    rparams->realm_name);
+		    return;
+		}
+	    }
+	}
+	rightsmask = 0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->adminservers != NULL)) {
+	    for (i=0; (rparams->adminservers[i] != NULL); i++) {
+		if ((retval = krb5_ldap_delete_service_rights(util_context,
+							      LDAP_ADMIN_SERVICE, rparams->adminservers[i],
+							      rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    printf("failed\n");
+		    com_err(argv[0], retval, "while assigning rights to '%s'",
+			    rparams->realm_name);
+		    return;
+		}
+	    }
+	}
+	rightsmask = 0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
+	    for (i=0; (rparams->passwdservers[i] != NULL); i++) {
+		if ((retval = krb5_ldap_delete_service_rights(util_context,
+							      LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
+							      rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    printf("failed\n");
+		    com_err(argv[0], retval, "while assigning rights to '%s'",
+			    rparams->realm_name);
+		    return;
+		}
+	    }
+	}
+	printf("done\n");
+    }
+#endif
+    /* Delete the realm container and all the associated principals */
+    retval = krb5_ldap_delete_realm(util_context, global_params.realm);
+    if (retval) {
+	com_err(argv[0], retval, "deleting database of '%s'", global_params.realm);
+	exit_status++;
+	return;
+    }
+
+    printf("** Database of '%s' destroyed.\n", global_params.realm);
+
+    return;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h
new file mode 100644
index 000000000..9a2972a5a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h
@@ -0,0 +1,61 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_realm.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define BUFF_LEN 		64      /* Max len of enctype string */
+#define MAX_PRINC_SIZE 		256
+
+enum ap_op {
+    NULL_KEY,	/* setup null keys */
+    MASTER_KEY,	/* use master key as new key */
+    TGT_KEY	/* special handling for tgt key */
+};
+
+struct realm_info {
+    krb5_deltat max_life;
+    krb5_deltat max_rlife;
+    krb5_timestamp expiration;
+    krb5_flags flags;
+    krb5_keyblock *key;
+    krb5_int32 nkslist;
+    krb5_key_salt_tuple *kslist;
+};
+
+struct iterate_args {
+    krb5_context	ctx;
+    struct realm_info	*rblock;
+    krb5_db_entry	*dbentp;
+};
+
+extern void kdb5_ldap_create (int argc, char **argv);
+extern void kdb5_ldap_destroy (int argc, char **argv);
+extern void kdb5_ldap_modify (int argc, char **argv);
+extern void kdb5_ldap_view (int argc, char **argv);
+extern void kdb5_ldap_list (int argc, char **argv);
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
new file mode 100644
index 000000000..80793b7ac
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
@@ -0,0 +1,2161 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_services.c
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Create / Delete / Modify / View / List service objects.
+ */
+
+/*
+ * Service objects have rights over realm objects and principals. The following
+ * functions manage the service objects.
+ */
+
+#include <stdio.h>
+#include <k5-int.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+
+#ifdef HAVE_EDIRECTORY
+
+krb5_error_code
+rem_service_entry_from_file(int argc,
+			    char *argv[],
+			    char *file_name,
+			    char *service_object);
+
+extern char *yes;
+extern krb5_boolean db_inited;
+
+static int process_host_list(char **host_list, int servicetype)
+{
+    krb5_error_code retval = 0;
+    char *pchr = NULL;
+    char host_str[MAX_LEN_LIST_ENTRY] = "", proto_str[PROTOCOL_STR_LEN + 1] = "", port_str[PORT_STR_LEN + 1] = "";
+    int j = 0;
+
+    /* Protocol and port number processing */
+    for (j = 0; host_list[j]; j++) {
+	/* Look for one hash */
+	if ((pchr = strchr(host_list[j], HOST_INFO_DELIMITER))) {
+	    unsigned int hostname_len = pchr - host_list[j];
+
+	    /* Check input for buffer overflow */
+	    if (hostname_len >= MAX_LEN_LIST_ENTRY) {
+		retval = EINVAL;
+		goto cleanup;
+	    }
+
+	    /* First copy off the host name portion */
+	    strncpy (host_str, host_list[j], hostname_len);
+
+	    /* Parse for the protocol string and translate to number */
+	    strncpy (proto_str, pchr + 1, PROTOCOL_STR_LEN);
+	    if (!strcmp(proto_str, "udp"))
+		sprintf (proto_str, "%d", PROTOCOL_NUM_UDP);
+	    else if (!strcmp(proto_str, "tcp"))
+		sprintf (proto_str, "%d", PROTOCOL_NUM_TCP);
+	    else
+		proto_str[0] = '\0'; /* Make the string null if invalid */
+
+	    /* Look for one more hash */
+	    if ((pchr = strchr(pchr + 1, HOST_INFO_DELIMITER))) {
+		/* Parse for the port string and check if it is numeric */
+		strncpy (port_str, pchr + 1, PORT_STR_LEN);
+		if (!strtol(port_str, NULL, 10)) /* Not a valid number */
+		    port_str[0] = '\0';
+	    } else
+		port_str[0] = '\0';
+	} else { /* We have only host name */
+	    strncpy (host_str, host_list[j], MAX_LEN_LIST_ENTRY - 1);
+	    proto_str[0] = '\0';
+	    port_str[0] = '\0';
+	}
+
+	/* Now, based on service type, fill in suitable protocol
+	   and port values if they are absent or not matching */
+	if (servicetype == LDAP_KDC_SERVICE) {
+	    if (proto_str[0] == '\0')
+		sprintf (proto_str, "%d", PROTOCOL_DEFAULT_KDC);
+
+	    if (port_str[0] == '\0')
+		sprintf (port_str, "%d", PORT_DEFAULT_KDC);
+	} else if (servicetype == LDAP_ADMIN_SERVICE) {
+	    if (proto_str[0] == '\0')
+		sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM);
+	    else if (strcmp(proto_str, "1")) {
+		sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM);
+
+		/* Print warning message */
+		printf ("Admin Server supports only TCP protocol, hence setting that\n");
+	    }
+
+	    if (port_str[0] == '\0')
+		sprintf (port_str, "%d", PORT_DEFAULT_ADM);
+	} else if (servicetype == LDAP_PASSWD_SERVICE) {
+	    if (proto_str[0] == '\0')
+		sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD);
+	    else if (strcmp(proto_str, "0")) {
+		sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD);
+
+		/* Print warning message */
+		printf ("Password Server supports only UDP protocol, hence setting that\n");
+	    }
+
+	    if (port_str[0] == '\0')
+		sprintf (port_str, "%d", PORT_DEFAULT_PWD);
+	}
+
+	/* Finally form back the string */
+	free (host_list[j]);
+	host_list[j] = (char*) malloc(sizeof(char) *
+				      (strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1));
+	if (host_list[j] == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	snprintf (host_list[j], strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1,
+		  "%s#%s#%s", host_str, proto_str, port_str);
+    }
+
+cleanup:
+    return retval;
+}
+
+
+/*
+ * Given a realm name, this function will convert it to a DN by appending the
+ * Kerberos container location.
+ */
+static krb5_error_code
+convert_realm_name2dn_list(list, krbcontainer_loc)
+    char **list;
+    const char *krbcontainer_loc;
+{
+    krb5_error_code retval = 0;
+    char temp_str[MAX_DN_CHARS] = "\0";
+    char *temp_node = NULL;
+    int i = 0;
+
+    if (list == NULL) {
+	return EINVAL;
+    }
+
+    for (i = 0; (list[i] != NULL) && (i < MAX_LIST_ENTRIES); i++) {
+	/* Restrict copying to max. length to avoid buffer overflow */
+	snprintf (temp_str, MAX_DN_CHARS, "cn=%s,%s", list[i], krbcontainer_loc);
+
+	/* Make copy of string to temporary node */
+	temp_node = strdup(temp_str);
+	if (list[i] == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+
+	/* On success, free list node and attach new one */
+	free (list[i]);
+	list[i] = temp_node;
+	temp_node = NULL;
+    }
+
+cleanup:
+    return retval;
+}
+
+
+/*
+ * This function will create a service object on the LDAP Server, with the
+ * specified attributes.
+ */
+void kdb5_ldap_create_service(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_error_code retval = 0;
+    krb5_ldap_service_params *srvparams = NULL;
+    krb5_boolean print_usage = FALSE;
+    krb5_boolean no_msg = FALSE;
+    int mask = 0;
+    char **extra_argv = NULL;
+    int extra_argc = 0;
+    int i = 0;
+    krb5_ldap_realm_params *rparams = NULL;
+    int rmask = 0;
+    int rightsmask =0;
+    char **temprdns = NULL;
+    char *realmName = NULL;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+    krb5_boolean service_obj_created = FALSE;
+
+    /* Check for number of arguments */
+    if ((argc < 3) || (argc > 10)) {
+	exit_status++;
+	goto err_usage;
+    }
+
+    /* Allocate memory for service parameters structure */
+    srvparams = (krb5_ldap_service_params*) calloc(1, sizeof(krb5_ldap_service_params));
+    if (srvparams == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    dal_handle = (kdb5_dal_handle *) util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+    /* Allocate memory for extra arguments to be used for setting
+       password -- it's OK to allocate as much as the total number
+       of arguments */
+    extra_argv = (char **) calloc((unsigned int)argc, sizeof(char*));
+    if (extra_argv == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    /* Set first of the extra arguments as the program name */
+    extra_argv[0] = me;
+    extra_argc++;
+
+    /* Read Kerberos container info, to construct realm DN from name
+     * and for assigning rights
+     */
+    if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+						     &(ldap_context->krbcontainer)))) {
+	com_err(me, retval, "while reading Kerberos container information");
+	goto cleanup;
+    }
+
+    /* Parse all arguments */
+    for (i = 1; i < argc; i++) {
+	if (!strcmp(argv[i], "-kdc")) {
+	    srvparams->servicetype = LDAP_KDC_SERVICE;
+	} else if (!strcmp(argv[i], "-admin")) {
+	    srvparams->servicetype = LDAP_ADMIN_SERVICE;
+	} else if (!strcmp(argv[i], "-pwd")) {
+	    srvparams->servicetype = LDAP_PASSWD_SERVICE;
+	} else if (!strcmp(argv[i], "-servicehost")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES,
+							sizeof(char *));
+	    if (srvparams->krbhostservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  srvparams->krbhostservers))) {
+		goto cleanup;
+	    }
+
+	    if ((retval = process_host_list (srvparams->krbhostservers,
+					     srvparams->servicetype))) {
+		goto cleanup;
+	    }
+
+	    mask |= LDAP_SERVICE_HOSTSERVER;
+	} else if (!strcmp(argv[i], "-realm")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES,
+							    sizeof(char *));
+	    if (srvparams->krbrealmreferences == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  srvparams->krbrealmreferences))) {
+		goto cleanup;
+	    }
+
+	    /* Convert realm names to realm DNs */
+	    if ((retval = convert_realm_name2dn_list(
+		     srvparams->krbrealmreferences,
+		     ldap_context->krbcontainer->DN))) {
+		goto cleanup;
+	    }
+
+	    mask |= LDAP_SERVICE_REALMREFERENCE;
+	}
+	/* If argument is none of the above and beginning with '-',
+	 * it must be related to password -- collect it
+	 * to pass onto kdb5_ldap_set_service_password()
+	 */
+	else if (*(argv[i]) == '-') {
+	    /* Checking for options of setting the password for the
+	     * service (by using 'setsrvpw') is not modular. --need to
+	     * have a common function that can be shared with 'setsrvpw'
+	     */
+	    if (!strcmp(argv[i], "-randpw")) {
+		extra_argv[extra_argc] = argv[i];
+		extra_argc++;
+	    } else if (!strcmp(argv[i], "-fileonly")) {
+		extra_argv[extra_argc] = argv[i];
+		extra_argc++;
+	    }
+	    /* For '-f' option alone, pick up the following argument too */
+	    else if (!strcmp(argv[i], "-f")) {
+		extra_argv[extra_argc] = argv[i];
+		extra_argc++;
+
+		if (++i > argc - 1)
+		    goto err_usage;
+
+		extra_argv[extra_argc] = argv[i];
+		extra_argc++;
+	    } else { /* Any other option is invalid */
+		exit_status++;
+		goto err_usage;
+	    }
+	} else { /* Any other argument must be service DN */
+	    /* First check if service DN is already provided --
+	     * if so, there's a usage error
+	     */
+	    if (srvparams->servicedn != NULL) {
+		com_err(me, EINVAL, "while creating service object");
+		goto err_usage;
+	    }
+
+	    /* If not present already, fill up service DN */
+	    srvparams->servicedn = strdup(argv[i]);
+	    if (srvparams->servicedn == NULL) {
+		com_err(me, ENOMEM, "while creating service object");
+		goto err_nomsg;
+	    }
+	}
+    }
+
+    /* No point in proceeding further if service DN value is not available */
+    if (srvparams->servicedn == NULL) {
+	com_err(me, EINVAL, "while creating service object");
+	goto err_usage;
+    }
+
+    if (srvparams->servicetype == 0) { /* Not provided and hence not set */
+	com_err(me, EINVAL, "while creating service object");
+	goto err_usage;
+    }
+
+    /* Create object with all attributes provided */
+    if ((retval = krb5_ldap_create_service(util_context, srvparams, mask)))
+	goto cleanup;
+
+    service_obj_created = TRUE;
+
+    /* ** NOTE ** srvparams structure should not be modified, as it is
+     * used for deletion of the service object in case of any failures
+     * from now on.
+     */
+
+    /* Set password too */
+    if (extra_argc >= 1) {
+	/* Set service DN as the last argument */
+	extra_argv[extra_argc] = strdup(srvparams->servicedn);
+	if (extra_argv[extra_argc] == NULL) {
+            retval = ENOMEM;
+            goto cleanup;
+        }
+	extra_argc++;
+
+	if ((retval = kdb5_ldap_set_service_password(extra_argc, extra_argv)) != 0) {
+	    goto err_nomsg;
+	}
+    }
+    /* Rights assignment */
+    if (mask & LDAP_SERVICE_REALMREFERENCE) {
+
+	printf("%s","Changing rights for the service object. Please wait ... ");
+	fflush(stdout);
+
+	rightsmask =0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+
+	if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) {
+	    for (i=0; (srvparams->krbrealmreferences[i] != NULL); i++) {
+
+		/* Get the realm name, not the dn */
+		temprdns = ldap_explode_dn(srvparams->krbrealmreferences[i], 1);
+
+		if (temprdns[0] == NULL) {
+		    retval = EINVAL;
+		    goto cleanup;
+		}
+
+		realmName = strdup(temprdns[0]);
+		if (realmName == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_ldap_read_realm_params(util_context,
+							  realmName, &rparams, &rmask))) {
+		    com_err(me, retval, "while reading information of realm '%s'",
+			    realmName);
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_ldap_add_service_rights(util_context,
+							   srvparams->servicetype, srvparams->servicedn,
+							   realmName, rparams->subtree, rightsmask))) {
+		    printf("failed\n");
+		    com_err(me, retval, "while assigning rights '%s'",
+			    srvparams->servicedn);
+		    goto cleanup;
+		}
+
+		if (rparams)
+		    krb5_ldap_free_realm_params(rparams);
+	    }
+	}
+	printf("done\n");
+    }
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+cleanup:
+
+    if ((retval != 0) && (service_obj_created == TRUE)) {
+	/* This is for deleting the service object if something goes
+	 * wrong in creating the service object
+	 */
+
+	/* srvparams is populated from the user input and should be correct as
+	 * we were successful in creating a service object. Reusing the same
+	 */
+	krb5_ldap_delete_service(util_context, srvparams, srvparams->servicedn);
+    }
+
+    /* Clean-up structure */
+    krb5_ldap_free_service (util_context, srvparams);
+
+    if (extra_argv) {
+	free (extra_argv);
+	extra_argv = NULL;
+    }
+    if (realmName) {
+	free(realmName);
+	realmName = NULL;
+    }
+    if (print_usage)
+	db_usage (CREATE_SERVICE);
+
+    if (retval) {
+	if (!no_msg)
+	    com_err(me, retval, "while creating service object");
+
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/*
+ * This function will modify the attributes of a given service
+ * object on the LDAP Server
+ */
+void kdb5_ldap_modify_service(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_error_code retval = 0;
+    krb5_ldap_service_params *srvparams = NULL;
+    krb5_boolean print_usage = FALSE;
+    krb5_boolean no_msg = FALSE;
+    char *servicedn = NULL;
+    int i = 0;
+    int in_mask = 0, out_mask = 0;
+    int srvhost_flag = 0, realmdn_flag = 0;
+    char **list = NULL;
+    int existing_entries = 0, new_entries = 0;
+    char **temp_ptr = NULL;
+    krb5_ldap_realm_params *rparams = NULL;
+    int j = 0;
+    int rmask = 0;
+    int rightsmask =0;
+    char **oldrealmrefs = NULL;
+    char **newrealmrefs = NULL;
+    char **temprdns = NULL;
+    char *realmName = NULL;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+
+    /* Check for number of arguments */
+    if ((argc < 3) || (argc > 10)) {
+	exit_status++;
+	goto err_usage;
+    }
+
+    dal_handle = (kdb5_dal_handle *) util_context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+    /* Parse all arguments, only to pick up service DN (Pass 1) */
+    for (i = 1; i < argc; i++) {
+	/* Skip arguments next to 'servicehost'
+	   and 'realmdn' arguments */
+	if (!strcmp(argv[i], "-servicehost")) {
+	    ++i;
+	} else if (!strcmp(argv[i], "-clearservicehost")) {
+	    ++i;
+	} else if (!strcmp(argv[i], "-addservicehost")) {
+	    ++i;
+	} else if (!strcmp(argv[i], "-realm")) {
+	    ++i;
+	} else if (!strcmp(argv[i], "-clearrealm")) {
+	    ++i;
+	} else if (!strcmp(argv[i], "-addrealm")) {
+	    ++i;
+	} else { /* Any other argument must be service DN */
+	    /* First check if service DN is already provided --
+	       if so, there's a usage error */
+	    if (servicedn != NULL) {
+		com_err(me, EINVAL, "while modifying service object");
+		goto err_usage;
+	    }
+
+	    /* If not present already, fill up service DN */
+	    servicedn = strdup(argv[i]);
+	    if (servicedn == NULL) {
+		com_err(me, ENOMEM, "while modifying service object");
+		goto err_nomsg;
+	    }
+	}
+    }
+
+    /* No point in proceeding further if service DN value is not available */
+    if (servicedn == NULL) {
+	com_err(me, EINVAL, "while modifying service object");
+	goto err_usage;
+    }
+
+    retval = krb5_ldap_read_service(util_context, servicedn, &srvparams, &in_mask);
+    if (retval) {
+	com_err(argv[0], retval, "while reading information of service '%s'",
+		servicedn);
+	goto err_nomsg;
+    }
+
+    /* Read Kerberos container info, to construct realm DN from name
+     * and for assigning rights
+     */
+    if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+						     &(ldap_context->krbcontainer)))) {
+	com_err(me, retval, "while reading Kerberos container information");
+	goto cleanup;
+    }
+
+    /* Parse all arguments, but skip the service DN (Pass 2) */
+    for (i = 1; i < argc; i++) {
+	if (!strcmp(argv[i], "-servicehost")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    /* Free the old list if available */
+	    if (srvparams->krbhostservers) {
+		krb5_free_list_entries (srvparams->krbhostservers);
+		free (srvparams->krbhostservers);
+	    }
+
+	    srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES,
+							sizeof(char *));
+	    if (srvparams->krbhostservers == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  srvparams->krbhostservers))) {
+		goto cleanup;
+	    }
+
+	    if ((retval = process_host_list (srvparams->krbhostservers,
+					     srvparams->servicetype))) {
+		goto cleanup;
+	    }
+
+	    out_mask |= LDAP_SERVICE_HOSTSERVER;
+
+	    /* Set flag to ignore 'add' and 'clear' */
+	    srvhost_flag = 1;
+	} else if (!strcmp(argv[i], "-clearservicehost")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    if (!srvhost_flag) {
+		/* If attribute doesn't exist, don't permit 'clear' option */
+		if ((in_mask & LDAP_SERVICE_HOSTSERVER) == 0) {
+		    /* Send out some proper error message here */
+		    com_err(me, EINVAL, "service host list is empty\n");
+		    goto err_nomsg;
+		}
+
+		/* Allocate list for processing */
+		list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		if (list == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+		    goto cleanup;
+
+		if ((retval = process_host_list (list, srvparams->servicetype))) {
+		    goto cleanup;
+		}
+
+		list_modify_str_array(&(srvparams->krbhostservers),
+				      (const char**)list, LIST_MODE_DELETE);
+
+		out_mask |= LDAP_SERVICE_HOSTSERVER;
+
+		/* Clean up */
+		free (list);
+		list = NULL;
+	    }
+	} else if (!strcmp(argv[i], "-addservicehost")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    if (!srvhost_flag) {
+		/* Allocate list for processing */
+		list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		if (list == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+		    goto cleanup;
+
+		if ((retval = process_host_list (list, srvparams->servicetype))) {
+		    goto cleanup;
+		}
+
+		/* Call list_modify_str_array() only if host server attribute
+		 * exists already --Actually, it's better to handle this
+		 * within list_modify_str_array()
+		 */
+		if (in_mask & LDAP_SERVICE_HOSTSERVER) {
+		    /* Re-size existing list */
+		    existing_entries = list_count_str_array(srvparams->krbhostservers);
+		    new_entries = list_count_str_array(list);
+		    temp_ptr = (char **) realloc(srvparams->krbhostservers,
+						 sizeof(char *) * (existing_entries + new_entries + 1));
+		    if (temp_ptr == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    srvparams->krbhostservers = temp_ptr;
+
+		    list_modify_str_array(&(srvparams->krbhostservers),
+					  (const char**)list, LIST_MODE_ADD);
+
+		    /* Clean up */
+		    free (list);
+		    list = NULL;
+		} else
+		    srvparams->krbhostservers = list;
+
+		out_mask |= LDAP_SERVICE_HOSTSERVER;
+	    }
+	} else if (!strcmp(argv[i], "-realm")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences)) {
+		if (!oldrealmrefs) {
+		    /* Store the old realm list for removing rights */
+		    oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldrealmrefs == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+			oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+			if (oldrealmrefs[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldrealmrefs[j] = NULL;
+		}
+
+		/* Free the old list if available */
+		krb5_free_list_entries (srvparams->krbrealmreferences);
+		free (srvparams->krbrealmreferences);
+	    }
+
+	    srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES,
+							    sizeof(char *));
+	    if (srvparams->krbrealmreferences == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+
+	    if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+					  srvparams->krbrealmreferences))) {
+		goto cleanup;
+	    }
+
+	    /* Convert realm names to realm DNs */
+	    if ((retval = convert_realm_name2dn_list(
+		     srvparams->krbrealmreferences,
+		     ldap_context->krbcontainer->DN))) {
+		goto cleanup;
+	    }
+
+	    out_mask |= LDAP_SERVICE_REALMREFERENCE;
+
+	    /* Set flag to ignore 'add' and 'clear' */
+	    realmdn_flag = 1;
+	} else if (!strcmp(argv[i], "-clearrealm")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    if (!realmdn_flag) {
+		/* If attribute doesn't exist, don't permit 'clear' option */
+		if (((in_mask & LDAP_SERVICE_REALMREFERENCE) == 0) || (srvparams->krbrealmreferences == NULL)) {
+		    /* Send out some proper error message here */
+		    goto err_nomsg;
+		}
+
+		if (!oldrealmrefs) {
+		    /* Store the old realm list for removing rights */
+		    oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldrealmrefs == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+			oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+			if (oldrealmrefs[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldrealmrefs[j] = NULL;
+		}
+
+		/* Allocate list for processing */
+		list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		if (list == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+		    goto cleanup;
+
+		/* Convert realm names to realm DNs */
+		if ((retval = convert_realm_name2dn_list(list,
+							 ldap_context->krbcontainer->DN))) {
+		    goto cleanup;
+		}
+
+		list_modify_str_array(&(srvparams->krbrealmreferences),
+				      (const char**)list, LIST_MODE_DELETE);
+
+		out_mask |= LDAP_SERVICE_REALMREFERENCE;
+
+		/* Clean up */
+		free (list);
+		list = NULL;
+	    }
+	} else if (!strcmp(argv[i], "-addrealm")) {
+	    if (++i > argc - 1)
+		goto err_usage;
+
+	    if (!realmdn_flag) {
+		/* Allocate list for processing */
+		list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		if (list == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+		    goto cleanup;
+
+		/* Convert realm names to realm DNs */
+		if ((retval = convert_realm_name2dn_list(list,
+							 ldap_context->krbcontainer->DN))) {
+		    goto cleanup;
+		}
+
+		if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences) && (!oldrealmrefs)) {
+		    /* Store the old realm list for removing rights */
+		    oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+		    if (oldrealmrefs == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+
+		    for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+			oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+			if (oldrealmrefs[j] == NULL) {
+			    retval = ENOMEM;
+			    goto cleanup;
+			}
+		    }
+		    oldrealmrefs[j] = NULL;
+		}
+
+		/* Call list_modify_str_array() only if realm DN attribute
+		 * exists already -- Actually, it's better to handle this
+		 * within list_modify_str_array() */
+		if (in_mask & LDAP_SERVICE_REALMREFERENCE) {
+		    /* Re-size existing list */
+		    existing_entries = list_count_str_array(
+			srvparams->krbrealmreferences);
+		    new_entries = list_count_str_array(list);
+		    temp_ptr = (char **) realloc(srvparams->krbrealmreferences,
+						 sizeof(char *) * (existing_entries + new_entries + 1));
+		    if (temp_ptr == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    srvparams->krbrealmreferences = temp_ptr;
+
+		    list_modify_str_array(&(srvparams->krbrealmreferences),
+					  (const char**)list, LIST_MODE_ADD);
+
+		    /* Clean up */
+		    free (list);
+		    list = NULL;
+		} else
+		    srvparams->krbrealmreferences = list;
+
+		out_mask |= LDAP_SERVICE_REALMREFERENCE;
+	    }
+	} else {
+	    /* Any other argument must be service DN
+	       -- skip it */
+	}
+    }
+
+    /* Modify attributes of object */
+    if ((retval = krb5_ldap_modify_service(util_context, srvparams, out_mask)))
+	goto cleanup;
+
+    /* Service rights modification code */
+    if (out_mask & LDAP_SERVICE_REALMREFERENCE) {
+
+	printf("%s","Changing rights for the service object. Please wait ... ");
+	fflush(stdout);
+
+	newrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+	if (newrealmrefs == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+
+	if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) {
+	    for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+		newrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+		if (newrealmrefs[j] == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+	    }
+	    newrealmrefs[j] = NULL;
+	}
+	disjoint_members(oldrealmrefs, newrealmrefs);
+
+	/* Delete the rights for the given service, on each of the realm
+	 * container & subtree in the old realm reference list.
+	 */
+	if (oldrealmrefs) {
+	    rightsmask = 0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+
+	    for (i = 0; (oldrealmrefs[i] != NULL); i++) {
+		/* Get the realm name, not the dn */
+		temprdns = ldap_explode_dn(oldrealmrefs[i], 1);
+
+		if (temprdns[0] == NULL) {
+		    retval = EINVAL;
+		    goto cleanup;
+		}
+
+		realmName = strdup(temprdns[0]);
+		if (realmName == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_ldap_read_realm_params(util_context,
+							  realmName, &rparams, &rmask))) {
+		    com_err(me, retval, "while reading information of realm '%s'",
+			    realmName);
+		    goto err_nomsg;
+		}
+
+		if ((retval = krb5_ldap_delete_service_rights(util_context,
+							      srvparams->servicetype, srvparams->servicedn,
+							      realmName, rparams->subtree, rightsmask))) {
+		    printf("failed\n");
+		    com_err(me, retval, "while assigning rights '%s'",
+			    srvparams->servicedn);
+		    goto err_nomsg;
+		}
+
+		if (rparams)
+		    krb5_ldap_free_realm_params(rparams);
+	    }
+	}
+
+	/* Add the rights for the given service, on each of the realm
+	 * container & subtree in the new realm reference list.
+	 */
+	if (newrealmrefs) {
+	    rightsmask = 0;
+	    rightsmask |= LDAP_REALM_RIGHTS;
+	    rightsmask |= LDAP_SUBTREE_RIGHTS;
+
+	    for (i = 0; (newrealmrefs[i] != NULL); i++) {
+		/* Get the realm name, not the dn */
+		temprdns = ldap_explode_dn(newrealmrefs[i], 1);
+
+		if (temprdns[0] == NULL) {
+		    retval = EINVAL;
+		    goto cleanup;
+		}
+
+		realmName = strdup(temprdns[0]);
+		if (realmName == NULL) {
+		    retval = ENOMEM;
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+								 &(ldap_context->krbcontainer)))) {
+		    com_err(me, retval,
+			    "while reading Kerberos container information");
+		    goto cleanup;
+		}
+
+		if ((retval = krb5_ldap_read_realm_params(util_context,
+							  realmName, &rparams, &rmask))) {
+		    com_err(me, retval, "while reading information of realm '%s'",
+			    realmName);
+		    goto err_nomsg;
+		}
+
+		if ((retval = krb5_ldap_add_service_rights(util_context,
+							   srvparams->servicetype, srvparams->servicedn,
+							   realmName, rparams->subtree, rightsmask))) {
+		    printf("failed\n");
+		    com_err(me, retval, "while assigning rights '%s'",
+			    srvparams->servicedn);
+		    goto err_nomsg;
+		}
+
+		if (rparams) {
+		    krb5_ldap_free_realm_params(rparams);
+		    rparams = NULL;
+		}
+	    }
+	    printf("done\n");
+	}
+    }
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+err_nomsg:
+    no_msg = TRUE;
+
+cleanup:
+    /* Clean-up structure */
+    krb5_ldap_free_service(util_context, srvparams);
+
+    if (servicedn)
+	free(servicedn);
+
+    if (list) {
+	free(list);
+	list = NULL;
+    }
+
+    if (oldrealmrefs) {
+	for (i = 0; oldrealmrefs[i] != NULL; i++)
+	    free(oldrealmrefs[i]);
+	free(oldrealmrefs);
+    }
+
+    if (newrealmrefs) {
+	for (i = 0; newrealmrefs[i] != NULL; i++)
+	    free(newrealmrefs[i]);
+	free(newrealmrefs);
+    }
+    if (realmName) {
+	free(realmName);
+	realmName = NULL;
+    }
+
+    if (print_usage)
+	db_usage(MODIFY_SERVICE);
+
+    if (retval) {
+	if (!no_msg)
+	    com_err(me, retval, "while modifying service object");
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/*
+ * This function will delete the entry corresponding to the service object
+ * from the service password file.
+ */
+static krb5_error_code
+rem_service_entry_from_file(argc, argv, file_name, service_object)
+    int argc;
+    char *argv[];
+    char *file_name;
+    char *service_object;
+{
+    int     st        = EINVAL;
+    char    *me       = argv[0];
+    char    *tmp_file = NULL;
+    int     tmpfd     = -1;
+    FILE    *pfile    = NULL;
+    unsigned int len  = 0;
+    char    line[MAX_LEN]={0};
+    mode_t  omask     = umask(077);
+
+    /* Check for permissions on the password file */
+    if (access(file_name, W_OK) == -1) {
+	/* If the specified file itself is not there, no need to show error */
+	if (errno == ENOENT) {
+	    st=0;
+	    goto cleanup;
+	} else {
+	    com_err(me, errno, "while deleting entry from file %s", file_name);
+	    goto cleanup;
+	}
+    }
+
+    /* Create a temporary file which contains all the entries except the
+       entry for the given service dn */
+    pfile = fopen(file_name, "r+");
+    if (pfile == NULL) {
+	com_err(me, errno, "while deleting entry from file %s", file_name);
+	goto cleanup;
+    }
+
+    /* Create a new file with the extension .tmp */
+    tmp_file = (char *)malloc(strlen(file_name) + 4 + 1);
+    if (tmp_file == NULL) {
+	com_err(me, ENOMEM, "while deleting entry from file");
+	fclose(pfile);
+	goto cleanup;
+    }
+    snprintf (tmp_file, strlen(file_name) + 4 + 1, "%s%s", file_name, ".tmp");
+
+
+    tmpfd = creat(tmp_file, S_IRUSR|S_IWUSR);
+    umask(omask);
+    if (tmpfd == -1) {
+	com_err(me, errno, "while deleting entry from file\n");
+	fclose(pfile);
+	goto cleanup;
+    }
+
+    /* Copy only those lines which donot have the specified service dn */
+    while (fgets(line, MAX_LEN, pfile) != NULL) {
+	if ((strstr(line, service_object) != NULL) &&
+	    (line[strlen(service_object)] == '#')) {
+	    continue;
+	} else {
+	    len = strlen(line);
+	    if (write(tmpfd, line, len) != len) {
+		com_err(me, errno, "while deleting entry from file\n");
+		close(tmpfd);
+		unlink(tmp_file);
+		fclose(pfile);
+		goto cleanup;
+	    }
+	}
+    }
+
+    fclose(pfile);
+    if (unlink(file_name) == 0) {
+	link(tmp_file, file_name);
+    } else {
+	com_err(me, errno, "while deleting entry from file\n");
+    }
+    unlink(tmp_file);
+
+    st=0;
+
+cleanup:
+
+    if (tmp_file)
+	free(tmp_file);
+
+    return st;
+}
+
+
+/*
+ * This function will delete the service object from the LDAP Server
+ * and unlink the references to the Realm objects (if any)
+ */
+void
+kdb5_ldap_destroy_service(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int i = 0;
+    char buf[5] = {0};
+    krb5_error_code retval = EINVAL;
+    int force = 0;
+    char *servicedn = NULL;
+    char *stashfilename = NULL;
+    int mask = 0;
+    krb5_ldap_service_params *lserparams = NULL;
+    krb5_boolean print_usage = FALSE;
+
+    if ((argc < 2) || (argc > 5)) {
+	exit_status++;
+	goto err_usage;
+    }
+
+    for (i=1; i < argc; i++) {
+
+	if (strcmp(argv[i],"-force")==0) {
+	    force++;
+	} else if (strcmp(argv[i],"-f")==0) {
+	    if (argv[i+1]) {
+		stashfilename=strdup(argv[i+1]);
+		if (stashfilename == NULL) {
+		    com_err(argv[0], ENOMEM, "while destroying service");
+		    exit_status++;
+		    goto cleanup;
+		}
+		i++;
+	    } else {
+		exit_status++;
+		goto err_usage;
+	    }
+	} else {
+	    if ((argv[i]) && (servicedn == NULL)) {
+		servicedn=strdup(argv[i]);
+		if (servicedn == NULL) {
+		    com_err(argv[0], ENOMEM, "while destroying service");
+		    exit_status++;
+		    goto cleanup;
+		}
+	    } else {
+		exit_status++;
+		goto err_usage;
+	    }
+	}
+    }
+
+    if (!servicedn) {
+	exit_status++;
+	goto err_usage;
+    }
+
+    if (!force) {
+	printf("This will delete the service object '%s', are you sure?\n", servicedn);
+	printf("(type 'yes' to confirm)? ");
+	if (fgets(buf, sizeof(buf), stdin) == NULL) {
+	    exit_status++;
+	    goto cleanup;;
+	}
+	if (strcmp(buf, yes)) {
+	    exit_status++;
+	    goto cleanup;
+	}
+    }
+
+    if ((retval = krb5_ldap_read_service(util_context, servicedn,
+					 &lserparams, &mask))) {
+	com_err(argv[0], retval, "while destroying service '%s'",servicedn);
+	exit_status++;
+	goto cleanup;
+    }
+
+    retval = krb5_ldap_delete_service(util_context, lserparams, servicedn);
+
+    if (retval) {
+	com_err(argv[0], retval, "while destroying service '%s'", servicedn);
+	exit_status++;
+	goto cleanup;
+    }
+
+    if (stashfilename == NULL) {
+	stashfilename = strdup(DEF_SERVICE_PASSWD_FILE);
+	if (stashfilename == NULL) {
+	    com_err(argv[0], ENOMEM, "while destroying service");
+	    exit_status++;
+	    goto cleanup;
+	}
+    }
+    printf("** service object '%s' deleted.\n", servicedn);
+    retval = rem_service_entry_from_file(argc, argv, stashfilename, servicedn);
+
+    if (retval)
+	printf("** error removing service object entry '%s' from password file.\n",
+	       servicedn);
+
+    goto cleanup;
+
+
+err_usage:
+    print_usage = TRUE;
+
+cleanup:
+
+    if (lserparams) {
+	krb5_ldap_free_service(util_context, lserparams);
+    }
+
+    if (servicedn) {
+	free(servicedn);
+    }
+
+    if (stashfilename) {
+	free(stashfilename);
+    }
+
+    if (print_usage) {
+	db_usage(DESTROY_SERVICE);
+    }
+
+    return;
+}
+
+
+/*
+ * This function will display information about the given service object
+ */
+void kdb5_ldap_view_service(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_ldap_service_params *lserparams = NULL;
+    krb5_error_code retval = 0;
+    char *servicedn = NULL;
+    int mask = 0;
+    krb5_boolean print_usage = FALSE;
+
+    if (!(argc == 2)) {
+	exit_status++;
+	goto err_usage;
+    }
+
+    servicedn=strdup(argv[1]);
+    if (servicedn == NULL) {
+	com_err(argv[0], ENOMEM, "while viewing service");
+	exit_status++;
+	goto cleanup;
+    }
+
+    if ((retval = krb5_ldap_read_service(util_context, servicedn, &lserparams, &mask))) {
+	com_err(argv[0], retval, "while viewing service '%s'",servicedn);
+	exit_status++;
+	goto cleanup;
+    }
+
+    print_service_params(lserparams, mask);
+
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+cleanup:
+
+    if (lserparams) {
+	krb5_ldap_free_service(util_context, lserparams);
+    }
+
+    if (servicedn)
+	free(servicedn);
+
+    if (print_usage) {
+	db_usage(VIEW_SERVICE);
+    }
+
+    return;
+}
+
+
+/*
+ * This function will list the DNs of kerberos services present on
+ * the LDAP Server under a specific sub-tree (entire tree by default)
+ */
+void kdb5_ldap_list_services(argc, argv)
+    int argc;
+    char *argv[];
+{
+    char *me = argv[0];
+    krb5_error_code retval = 0;
+    char *basedn = NULL;
+    char **list = NULL;
+    char **plist = NULL;
+    krb5_boolean print_usage = FALSE;
+
+    /* Check for number of arguments */
+    if ((argc != 1) && (argc != 3)) {
+	exit_status++;
+	goto err_usage;
+    }
+
+    /* Parse base DN argument if present */
+    if (argc == 3) {
+	if (strcmp(argv[1], "-basedn")) {
+	    retval = EINVAL;
+	    goto err_usage;
+	}
+
+	basedn = strdup(argv[2]);
+	if (basedn == NULL) {
+	    com_err(me, ENOMEM, "while listing services");
+	    exit_status++;
+	    goto cleanup;
+	}
+    }
+
+    retval = krb5_ldap_list_services(util_context, basedn, &list);
+    if ((retval != 0) || (list == NULL)) {
+	exit_status++;
+	goto cleanup;
+    }
+
+    for (plist = list; *plist != NULL; plist++) {
+	printf("%s\n", *plist);
+    }
+
+    goto cleanup;
+
+err_usage:
+    print_usage = TRUE;
+
+cleanup:
+    if (list != NULL) {
+	krb5_free_list_entries (list);
+	free (list);
+    }
+
+    if (basedn)
+	free (basedn);
+
+    if (print_usage) {
+	db_usage(LIST_SERVICE);
+    }
+
+    if (retval) {
+	com_err(me, retval, "while listing policy objects");
+	exit_status++;
+    }
+
+    return;
+}
+
+
+/*
+ * This function will print the service object information
+ * to the standard output
+ */
+static void
+print_service_params(lserparams, mask)
+    krb5_ldap_service_params *lserparams;
+    int mask;
+{
+    int            i=0;
+
+    /* Print the service dn */
+    printf("%20s%-20s\n","Service dn: ",lserparams->servicedn);
+
+    /* Print the service type of the object to be read */
+    if (lserparams->servicetype == LDAP_KDC_SERVICE) {
+	printf("%20s%-20s\n","Service type: ","kdc");
+    } else if (lserparams->servicetype == LDAP_ADMIN_SERVICE) {
+	printf("%20s%-20s\n","Service type: ","admin");
+    } else if (lserparams->servicetype == LDAP_PASSWD_SERVICE) {
+	printf("%20s%-20s\n","Service type: ","pwd");
+    }
+
+    /* Print the host server values */
+    printf("%20s\n","Service host list: ");
+    if (mask & LDAP_SERVICE_HOSTSERVER) {
+	for (i=0; lserparams->krbhostservers[i] != NULL; ++i) {
+	    printf("%20s%-50s\n","",lserparams->krbhostservers[i]);
+	}
+    }
+
+    /* Print the realm reference dn values */
+    printf("%20s\n","Realm DN list: ");
+    if (mask & LDAP_SERVICE_REALMREFERENCE) {
+	for (i=0; lserparams && lserparams->krbrealmreferences && lserparams->krbrealmreferences[i] != NULL; ++i) {
+	    printf("%20s%-50s\n","",lserparams->krbrealmreferences[i]);
+	}
+    }
+
+    return;
+}
+
+
+/*
+ * This function will generate random  password of length(RANDOM_PASSWD_LEN)
+ *
+ *
+ * INPUT:
+ *      ctxt - context
+ *
+ * OUTPUT:
+ *     RANDOM_PASSWD_LEN length random password
+ */
+static int generate_random_password(krb5_context ctxt, char **randpwd, unsigned int *passlen)
+{
+    char *random_pwd = NULL;
+    int ret = 0;
+    krb5_data data;
+    int i=0;
+    /*int len = 0;*/
+
+    /* setting random password length in the range 16-32 */
+    srand((unsigned int)(time(0) ^ getpid()));
+
+    data.length = RANDOM_PASSWD_LEN;
+    random_pwd = (char *)malloc(data.length + 1);
+    if (random_pwd == NULL) {
+	com_err("setsrvpw", ENOMEM, "while generating random password");
+	return ENOMEM;
+    }
+    memset(random_pwd, 0, data.length + 1);
+    data.data = random_pwd;
+
+    ret = krb5_c_random_make_octets(ctxt, &data);
+    if (ret) {
+	com_err("setsrvpw", ret, "Error generating random password");
+	free(random_pwd);
+	return ret;
+    }
+
+    for (i=0; i<data.length; i++) {
+	/* restricting to ascii chars. Need to change this when 8.8 supports */
+	if ((unsigned char)random_pwd[i] > 127) {
+	    random_pwd[i] = (unsigned char)random_pwd[i] % 128;
+	} else if (random_pwd[i] == 0) {
+	    random_pwd[i] = (rand()/(RAND_MAX/127 + 1))+1;
+	}
+    }
+
+    *randpwd = random_pwd;
+    *passlen = data.length;
+
+    return 0;
+}
+
+
+/*
+ * This function will set the password of the service object in the directory
+ * and/or the specified service password file.
+ *
+ *
+ * INPUT:
+ *      argc - contains the number of arguments for this sub-command
+ *      argv - array of arguments for this sub-command
+ *
+ * OUTPUT:
+ *      void
+ */
+int
+kdb5_ldap_set_service_password(argc, argv)
+    int argc;
+    char **argv;
+{
+    krb5_ldap_context *lparams = NULL;
+    char *file_name = NULL;
+    char *tmp_file = NULL;
+    char *me = argv[0];
+    int filelen = 0;
+    int random_passwd = 0;
+    int set_dir_pwd = 1;
+    krb5_boolean db_init_local = FALSE;
+    char *service_object = NULL;
+    char *passwd = NULL;
+    char *prompt1 = NULL;
+    char *prompt2 = NULL;
+    unsigned int passwd_len = 0;
+    krb5_error_code errcode = -1;
+    int retval = 0, i = 0;
+    unsigned int len = 0;
+    krb5_boolean print_usage = FALSE;
+    FILE *pfile = NULL;
+    char *str = NULL;
+    char line[MAX_LEN];
+    kdb5_dal_handle *dal_handle = NULL;
+    struct data encrypted_passwd = {0, NULL};
+
+    /* The arguments for setsrv password should contain the service object DN
+     * and options to specify whether the password should be updated in file only
+     * or both file and directory. So the possible combination of arguments are:
+     * setsrvpw servicedn				wherein argc is 2
+     * setsrvpw	-fileonly servicedn 			wherein argc is 3
+     * setsrvpw -randpw servicedn			wherein argc is 3
+     * setsrvpw -f filename servicedn			wherein argc is 4
+     * setsrvpw -fileonly -f filename servicedn 	wherein argc is 5
+     * setsrvpw -randpw -f filename servicedn 		wherein argc is 5
+     */
+    if ((argc < 2) || (argc > 5)) {
+	print_usage = TRUE;
+	goto cleanup;
+    }
+
+    dal_handle = (kdb5_dal_handle *)util_context->db_context;
+    lparams = (krb5_ldap_context *) dal_handle->db_context;
+
+    if (lparams == NULL) {
+	printf("%s: Invalid LDAP handle\n", me);
+	goto cleanup;
+    }
+
+    /* Parse the arguments */
+    for (i = 1; i < argc -1 ; i++) {
+	if (strcmp(argv[i], "-randpw") == 0) {
+	    random_passwd = 1;
+	} else if (strcmp(argv[i], "-fileonly") == 0) {
+	    set_dir_pwd = 0;
+	} else if (strcmp(argv[i], "-f") == 0) {
+	    if (argv[++i] == NULL) {
+		print_usage = TRUE;
+		goto cleanup;
+	    }
+
+	    file_name = strdup(argv[i]);
+	    if (file_name == NULL) {
+		com_err(me, ENOMEM, "while setting service object password");
+		goto cleanup;
+	    }
+	    /* Verify if the file location has the proper file name
+	     * for eg, if the file location is a directory like /home/temp/,
+	     * we reject it.
+	     */
+	    filelen = strlen(file_name);
+	    if ((filelen == 0) || (file_name[filelen-1] == '/')) {
+		printf("%s: Filename not specified for setting service object password\n", me);
+		print_usage = TRUE;
+		goto cleanup;
+	    }
+	} else {
+	    printf("%s: Invalid option specified for \"setsrvpw\" command\n", me);
+	    print_usage = TRUE;
+	    goto cleanup;
+	}
+    }
+
+    if (i != argc-1) {
+	print_usage = TRUE;
+	goto cleanup;
+    }
+
+    service_object = strdup(argv[i]);
+    if (service_object == NULL) {
+	com_err(me, ENOMEM, "while setting service object password");
+	goto cleanup;
+    }
+
+    if (strlen(service_object) == 0) {
+	printf("%s: Service object not specified for \"setsrvpw\" command\n", me);
+	print_usage = TRUE;
+	goto cleanup;
+    }
+
+    if (service_object[0] == '-') {
+	print_usage = TRUE;
+	goto cleanup;
+    }
+
+    if (file_name == NULL) {
+	file_name = strdup(DEF_SERVICE_PASSWD_FILE);
+	if (file_name == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    goto cleanup;
+	}
+    }
+
+    if (set_dir_pwd) {
+	if (db_inited == FALSE) {
+	    if ((errcode = krb5_ldap_db_init(util_context, lparams))) {
+		com_err(me, errcode, "while initializing database");
+		goto cleanup;
+	    }
+	    db_init_local = TRUE;
+	}
+    }
+
+    if (random_passwd) {
+	if (!set_dir_pwd) {
+	    printf("%s: Invalid option specified for \"setsrvpw\" command\n", me);
+	    print_usage = TRUE;
+	    goto cleanup;
+	} else {
+	    /* Generate random password */
+
+	    if ((errcode = generate_random_password(util_context, &passwd, &passwd_len))) {
+		printf("%s: Failed to set service object password\n", me);
+		goto cleanup;
+	    }
+	    passwd_len = strlen(passwd);
+	}
+    } else {
+	/* Get the service object password from the terminal */
+	passwd = (char *)malloc(MAX_SERVICE_PASSWD_LEN + 1);
+	if (passwd == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    goto cleanup;
+	}
+	memset(passwd, 0, MAX_SERVICE_PASSWD_LEN + 1);
+	passwd_len = MAX_SERVICE_PASSWD_LEN;
+
+	len = strlen(service_object);
+	/* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */
+	prompt1 = (char *)malloc(len + 20);
+	if (prompt1 == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    goto cleanup;
+	}
+	sprintf(prompt1, "Password for \"%s\"", service_object);
+
+	/* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */
+	prompt2 = (char *)malloc(len + 30);
+	if (prompt2 == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    free(prompt1);
+	    goto cleanup;
+	}
+	sprintf(prompt2, "Re-enter password for \"%s\"", service_object);
+
+	retval = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
+	free(prompt1);
+	free(prompt2);
+	if (retval) {
+	    com_err(me, retval, "while setting service object password");
+	    memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
+	    goto cleanup;
+	}
+	if (passwd_len == 0) {
+	    printf("%s: Invalid password\n", me);
+	    memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
+	    goto cleanup;
+	}
+	passwd_len = strlen(passwd);
+    }
+
+    /* Hex the password */
+    {
+	krb5_data pwd, hex;
+	pwd.length = passwd_len;
+	pwd.data = passwd;
+
+	errcode = tohex(pwd, &hex);
+	if (errcode != 0) {
+	    if (hex.length != 0) {
+		memset(hex.data, 0, hex.length);
+		free(hex.data);
+	    }
+	    com_err(me, errcode, "Failed to convert the password to hex");
+	    memset(passwd, 0, passwd_len);
+	    goto cleanup;
+	}
+	/* Password = {CRYPT}<encrypted password>:<encrypted key> */
+	encrypted_passwd.value = (unsigned char *)malloc(strlen(service_object) +
+							 1 + 5 + hex.length + 2);
+	if (encrypted_passwd.value == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    memset(passwd, 0, passwd_len);
+	    memset(hex.data, 0, hex.length);
+	    free(hex.data);
+	    goto cleanup;
+	}
+	encrypted_passwd.value[strlen(service_object) +
+			       1 + 5 + hex.length + 1] = '\0';
+	sprintf((char *)encrypted_passwd.value, "%s#{HEX}%s\n", service_object, hex.data);
+	encrypted_passwd.len = strlen((char *)encrypted_passwd.value);
+	memset(hex.data, 0, hex.length);
+	free(hex.data);
+    }
+
+    /* We should check if the file exists and we have permission to write into that file */
+    if (access(file_name, W_OK) == -1) {
+	if (errno == ENOENT) {
+	    mode_t omask;
+	    int fd = -1;
+
+	    printf("File does not exist. Creating the file %s...\n", file_name);
+	    omask = umask(077);
+	    fd = creat(file_name, S_IRUSR|S_IWUSR);
+	    umask(omask);
+	    if (fd == -1) {
+		com_err(me, errno, "Error creating file %s", file_name);
+		memset(passwd, 0, passwd_len);
+		goto cleanup;
+	    }
+	    close(fd);
+	} else {
+	    com_err(me, errno, "Unable to access the file %s", file_name);
+	    memset(passwd, 0, passwd_len);
+	    goto cleanup;
+	}
+    }
+
+    if (set_dir_pwd) {
+	if ((errcode = krb5_ldap_set_service_passwd(util_context, service_object, passwd)) != 0) {
+	    com_err(me, errcode, "Failed to set password for service object %s", service_object);
+	    memset(passwd, 0, passwd_len);
+	    goto cleanup;
+	}
+    }
+
+    memset(passwd, 0, passwd_len);
+
+
+    /* TODO: file lock for the service password file */
+    /* set password in the file */
+    pfile = fopen(file_name, "r+");
+    if (pfile == NULL) {
+	com_err(me, errno, "Failed to open file %s", file_name);
+	goto cleanup;
+    }
+
+    while (fgets(line, MAX_LEN, pfile) != NULL) {
+	if ((str = strstr(line, service_object)) != NULL) {
+	    if (line[strlen(service_object)] == '#') {
+		break;
+	    }
+	    str = NULL;
+	}
+    }
+    if (str == NULL) {
+	if (feof(pfile)) {
+	    /* If the service object dn is not present in the service password file */
+	    if (fwrite(encrypted_passwd.value, (unsigned int)encrypted_passwd.len, 1, pfile) != 1) {
+		com_err(me, errno, "Failed to write service object password to file");
+		goto cleanup;
+	    }
+	} else {
+	    com_err(me, errno, "Error reading service object password file");
+	    goto cleanup;
+	}
+	fclose(pfile);
+	pfile = NULL;
+    } else {
+	/* Password entry for the service object is already present in the file */
+	/* Delete the existing entry and add the new entry */
+	FILE *newfile = NULL;
+	mode_t omask;
+
+	/* Create a new file with the extension .tmp */
+	tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1));
+	if (tmp_file == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    goto cleanup;
+	}
+	sprintf(tmp_file,"%s.%s",file_name,"tmp");
+
+	omask = umask(077);
+	newfile = fopen(tmp_file, "w+");
+	umask(omask);
+	if (newfile == NULL) {
+	    com_err(me, errno, "Error creating file %s", tmp_file);
+	    goto cleanup;
+	}
+
+
+	fseek(pfile, 0, SEEK_SET);
+	while (fgets(line, MAX_LEN, pfile) != NULL) {
+	    if (((str = strstr(line, service_object)) != NULL) && (line[strlen(service_object)] == '#')) {
+		if (fprintf(newfile, "%s", encrypted_passwd.value) < 0) {
+		    com_err(me, errno, "Failed to write service object password to file");
+		    fclose(newfile);
+		    unlink(tmp_file);
+		    goto cleanup;
+		}
+	    } else {
+		len = strlen(line);
+		if (fprintf(newfile, "%s", line) < 0) {
+		    com_err(me, errno, "Failed to write service object password to file");
+		    fclose(newfile);
+		    unlink(tmp_file);
+		    goto cleanup;
+		}
+	    }
+	}
+
+	if (!feof(pfile)) {
+	    com_err(me, errno, "Error reading service object password file");
+	    fclose(newfile);
+	    unlink(tmp_file);
+	    goto cleanup;
+	}
+
+	/* TODO: file lock for the service password file */
+	fclose(pfile);
+	pfile = NULL;
+
+	fclose(newfile);
+	newfile = NULL;
+
+	if (unlink(file_name) == 0) {
+	    link(tmp_file, file_name);
+	} else {
+	    com_err(me, errno, "Failed to write service object password to file");
+	    unlink(tmp_file);
+	    goto cleanup;
+	}
+	unlink(tmp_file);
+    }
+    errcode = 0;
+
+cleanup:
+    if (db_init_local)
+	krb5_ldap_close(util_context);
+
+    if (service_object)
+	free(service_object);
+
+    if (file_name)
+	free(file_name);
+
+    if (passwd)
+	free(passwd);
+
+    if (encrypted_passwd.value) {
+	memset(encrypted_passwd.value, 0, encrypted_passwd.len);
+	free(encrypted_passwd.value);
+    }
+
+    if (pfile)
+	fclose(pfile);
+
+    if (tmp_file)
+	free(tmp_file);
+
+    if (print_usage)
+	db_usage(SET_SRV_PW);
+
+    return errcode;
+}
+
+#else /* #ifdef HAVE_EDIRECTORY */
+
+/*
+ * Convert the user supplied password into hexadecimal and stash it. Only a
+ * little more secure than storing plain password in the file ...
+ */
+void
+kdb5_ldap_stash_service_password(argc, argv)
+    int argc;
+    char **argv;
+{
+    int ret = 0;
+    unsigned int passwd_len = 0;
+    char *me = argv[0];
+    char *service_object = NULL;
+    char *file_name = NULL, *tmp_file = NULL;
+    char passwd[MAX_SERVICE_PASSWD_LEN];
+    char *str = NULL;
+    char line[MAX_LEN];
+    FILE *pfile = NULL;
+    krb5_boolean print_usage = FALSE;
+    krb5_data hexpasswd = {0, 0, NULL};
+    mode_t old_mode = 0;
+
+    /*
+     * Format:
+     *   stashsrvpw [-f filename] service_dn
+     * where
+     *   'service_dn' is the DN of the service object
+     *   'filename' is the path of the stash file
+     */
+    if (argc != 2 && argc != 4) {
+	print_usage = TRUE;
+	goto cleanup;
+    }
+
+    if (argc == 4) {
+	/* Find the stash file name */
+	if (strcmp (argv[1], "-f") == 0) {
+	    if (((file_name = strdup (argv[2])) == NULL) ||
+	        ((service_object = strdup (argv[3])) == NULL)) {
+	        com_err(me, ENOMEM, "while setting service object password");
+	        goto cleanup;
+	    }
+	} else if (strcmp (argv[2], "-f") == 0) {
+	    if (((file_name = strdup (argv[3])) == NULL) ||
+	        ((service_object = strdup (argv[1])) == NULL)) {
+	        com_err(me, ENOMEM, "while setting service object password");
+	        goto cleanup;
+	    }
+	} else {
+	    print_usage = TRUE;
+	    goto cleanup;
+	}
+	if (file_name == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    goto cleanup;
+	}
+    } else { /* argc == 2 */
+	char *section;
+
+	service_object = strdup (argv[1]);
+	if (service_object == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    goto cleanup;
+	}
+
+	/* Pick up the stash-file name from krb5.conf */
+	profile_get_string(util_context->profile, KDB_REALM_SECTION,
+			   util_context->default_realm, KDB_MODULE_POINTER, NULL, §ion);
+
+	if (section == NULL) {
+	    profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION,
+			       KDB_MODULE_POINTER, NULL, NULL, §ion);
+	    if (section == NULL) {
+		/* Stash file path neither in krb5.conf nor on command line */
+		file_name = strdup(DEF_SERVICE_PASSWD_FILE);
+	        if (file_name == NULL) {
+	            com_err(me, ENOMEM, "while setting service object password");
+	            goto cleanup;
+	        }
+		goto done;
+	    }
+	}
+
+	profile_get_string (util_context->profile, KDB_MODULE_SECTION, section,
+			    "ldap_service_password_file", NULL, &file_name);
+    }
+done:
+
+    /* Get password from user */
+    {
+	char prompt1[256], prompt2[256];
+
+	/* Get the service object password from the terminal */
+	memset(passwd, 0, sizeof (passwd));
+	passwd_len = sizeof (passwd);
+
+	/* size of prompt = strlen of servicedn + strlen("Password for \" \"") */
+	assert (sizeof (prompt1) > (strlen (service_object)
+				    + sizeof ("Password for \" \"")));
+	sprintf(prompt1, "Password for \"%s\"", service_object);
+
+	/* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */
+	assert (sizeof (prompt2) > (strlen (service_object)
+				    + sizeof ("Re-enter Password for \" \"")));
+	sprintf(prompt2, "Re-enter password for \"%s\"", service_object);
+
+	ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
+	if (ret != 0) {
+	    com_err(me, ret, "while setting service object password");
+	    memset(passwd, 0, sizeof (passwd));
+	    goto cleanup;
+	}
+
+	if (passwd_len == 0) {
+	    printf("%s: Invalid password\n", me);
+	    memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
+	    goto cleanup;
+	}
+    }
+
+    /* Convert the password to hexadecimal */
+    {
+	krb5_data pwd;
+
+	pwd.length = passwd_len;
+	pwd.data = passwd;
+
+	ret = tohex(pwd, &hexpasswd);
+	if (ret != 0) {
+	    com_err(me, ret, "Failed to convert the password to hexadecimal");
+	    memset(passwd, 0, passwd_len);
+	    goto cleanup;
+	}
+    }
+    memset(passwd, 0, passwd_len);
+
+    /* TODO: file lock for the service passowrd file */
+
+    /* set password in the file */
+    old_mode = umask(0177);
+    pfile = fopen(file_name, "a+");
+    if (pfile == NULL) {
+	com_err(me, errno, "Failed to open file %s: %s", file_name,
+		strerror (errno));
+	goto cleanup;
+    }
+    rewind (pfile);
+    umask(old_mode);
+
+    while (fgets (line, MAX_LEN, pfile) != NULL) {
+	if ((str = strstr (line, service_object)) != NULL) {
+	    /* White spaces not allowed */
+	    if (line [strlen (service_object)] == '#')
+		break;
+	    str = NULL;
+	}
+    }
+
+    if (str == NULL) {
+	if (feof(pfile)) {
+	    /* If the service object dn is not present in the service password file */
+	    if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
+		com_err(me, errno, "Failed to write service object password to file");
+		fclose(pfile);
+		goto cleanup;
+	    }
+	} else {
+	    com_err(me, errno, "Error reading service object password file");
+	    fclose(pfile);
+	    goto cleanup;
+	}
+	fclose(pfile);
+    } else {
+	/*
+	 * Password entry for the service object is already present in the file
+	 * Delete the existing entry and add the new entry
+	 */
+	FILE *newfile;
+
+	mode_t omask;
+
+	/* Create a new file with the extension .tmp */
+	tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1));
+	if (tmp_file == NULL) {
+	    com_err(me, ENOMEM, "while setting service object password");
+	    fclose(pfile);
+	    goto cleanup;
+	}
+	sprintf(tmp_file,"%s.%s",file_name,"tmp");
+
+	omask = umask(077);
+	newfile = fopen(tmp_file, "w");
+	umask (omask);
+	if (newfile == NULL) {
+	    com_err(me, errno, "Error creating file %s", tmp_file);
+	    fclose(pfile);
+	    goto cleanup;
+	}
+
+	fseek(pfile, 0, SEEK_SET);
+	while (fgets(line, MAX_LEN, pfile) != NULL) {
+	    if (((str = strstr(line, service_object)) != NULL) &&
+		(line[strlen(service_object)] == '#')) {
+		if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
+		    com_err(me, errno, "Failed to write service object password to file");
+		    fclose(newfile);
+		    unlink(tmp_file);
+		    fclose(pfile);
+		    goto cleanup;
+		}
+	    } else {
+		if (fprintf (newfile, "%s", line) < 0) {
+		    com_err(me, errno, "Failed to write service object password to file");
+		    fclose(newfile);
+		    unlink(tmp_file);
+		    fclose(pfile);
+		    goto cleanup;
+		}
+	    }
+	}
+
+	if (!feof(pfile)) {
+	    com_err(me, errno, "Error reading service object password file");
+	    fclose(newfile);
+	    unlink(tmp_file);
+	    fclose(pfile);
+	    goto cleanup;
+	}
+
+	/* TODO: file lock for the service passowrd file */
+
+	fclose(pfile);
+	fclose(newfile);
+
+	ret = rename(tmp_file, file_name);
+	if (ret != 0) {
+	    com_err(me, errno, "Failed to write service object password to "
+		    "file");
+	    goto cleanup;
+	}
+    }
+    ret = 0;
+
+cleanup:
+
+    if (hexpasswd.length != 0) {
+	memset(hexpasswd.data, 0, hexpasswd.length);
+	free(hexpasswd.data);
+    }
+
+    if (service_object)
+	free(service_object);
+
+    if (file_name)
+	free(file_name);
+
+    if (tmp_file)
+	free(tmp_file);
+
+    if (print_usage)
+	usage();
+/*	db_usage(STASH_SRV_PW); */
+
+    if (ret)
+	exit_status++;
+}
+
+#endif /* #ifdef HAVE_EDIRECTORY */
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
new file mode 100644
index 000000000..ac4ca8432
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
@@ -0,0 +1,71 @@
+/*
+ * kadmin/ldap_util/kdb5_services.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_misc.h"
+
+#define MAX_DN_CHARS 		256
+#define HOST_INFO_DELIMITER 	'#'
+#define PROTOCOL_STR_LEN 	3
+#define PROTOCOL_NUM_UDP 	0
+#define PROTOCOL_NUM_TCP 	1
+#define PROTOCOL_DEFAULT_KDC 	PROTOCOL_NUM_UDP
+#define PROTOCOL_DEFAULT_ADM 	PROTOCOL_NUM_TCP
+#define PROTOCOL_DEFAULT_PWD 	PROTOCOL_NUM_UDP
+#define PORT_STR_LEN 		5
+#define PORT_DEFAULT_KDC 	88
+#define PORT_DEFAULT_ADM 	749
+#define PORT_DEFAULT_PWD 	464
+
+#define MAX_LEN 		1024
+#define MAX_SERVICE_PASSWD_LEN 	256
+#define RANDOM_PASSWD_LEN 	128
+
+#define DEF_SERVICE_PASSWD_FILE "/usr/local/var/service_passwd"
+
+struct data{
+    int len;
+    unsigned char *value;
+};
+
+extern int enc_password(struct data pwd, struct data *enc_key, struct data *enc_pass);
+extern int tohex(krb5_data, krb5_data *);
+
+extern void kdb5_ldap_create_service (int argc, char **argv);
+extern void kdb5_ldap_modify_service (int argc, char **argv);
+extern void kdb5_ldap_destroy_service(int argc, char **argv);
+extern void kdb5_ldap_list_services(int argc, char **argv);
+extern void kdb5_ldap_view_service(int argc, char **argv);
+extern int  kdb5_ldap_set_service_password(int argc, char **argv);
+extern void kdb5_ldap_set_service_certificate(int argc, char **argv);
+extern void print_service_params(krb5_ldap_service_params *lserparams, int mask);
+extern krb5_error_code convert_realm_name2dn_list(char **list, const char *krbcontainer_loc);
+extern void kdb5_ldap_stash_service_password(int argc, char **argv);
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M
new file mode 100644
index 000000000..3fad89136
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M
@@ -0,0 +1,934 @@
+.TH KDB5_LDAP_UTIL 8
+.SH NAME
+kdb5_ldap_util \- Kerberos Configuration Utility
+.SH SYNOPSIS
+.B kdb5_ldap_util
+[\fB\-D\fP\ \fIuser_dn\fP [\fB\-w\fP\ \fIpasswd\fP]]
+[\fB\-H\fP\ \fIldapuri\fP]
+.I command
+.I [command_options]
+.SH DESCRIPTION
+.B kdb5_ldap_util
+allows an administrator to manage realms, Kerberos services and ticket policies.
+.SH COMMAND-LINE OPTIONS
+.TP
+\fB\-D\fP\ \fIuser_dn\fP
+Specifies the Distinguished name (DN) of the user who has sufficient rights to 
+perform the operation on the LDAP server.
+.TP
+\fB\-w\fP\ \fIpasswd\fP
+Specifies the password of 
+.IR user_dn .
+This option is not recommended.
+.TP
+\fB\-H\fP\ \fIldapuri\fP
+Specifies the URI of the LDAP server.
+.SH COMMANDS
+.TP
+\fBcreate\fP [\fB\-subtrees\fP\ \fIsubtree_dn_list\fP] [\fB\-sscope\fP\ \fIsearch_scope\fP] [\fB\-containerref\fP\ \fIcontainer_reference_dn\fP] [\fB\-k\fP\ \fImkeytype\fP] [\fB\-m\fP|\fB\-P\fP\ \fIpassword\fP|\fB\-sf\fP\ \fIstashfilename\fP] [\fB\-s\fP] [\fB\-r\fP\ \fIrealm\fP] [\fB\-kdcdn\fP\ \fIkdc_service_list\fP] [\fB\-admindn\fP\ \fIadmin_service_list\fP] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP]
+Creates realm in directory. Options:
+.RS
+.TP
+\fB\-subtrees\fP\ \fIsubtree_dn_list\fP
+Specifies the list of subtrees containing the principals of a realm. The list contains the DNs of the subtree
+objects separated by colon(:).
+.TP
+\fB\-sscope\fP\ \fIsearch_scope\fP
+Specifies the scope for searching the principals under the 
+.IR subtree .
+The possible values are 1 or one (one level), 2 or sub (subtrees).
+.TP
+\fB\-containerref\fP\ \fIcontainer_reference_dn\fP 
+Specifies the DN of the container object in which the principals of a realm will be created.
+If the container reference is not configured for a realm, the principals will be created in the realm container. 
+.TP
+\fB\-k\fP\ \fImkeytype\fP
+Specifies the key type of the master key in the database; the default is
+that given in
+.IR kdc.conf .
+.TP
+\fB\-m\fP
+Specifies that the master database password should be read from the TTY
+rather than fetched from a file on the disk.
+.TP
+\fB\-P\fP\ \fIpassword\fP
+Specifies the master database password. This option is not recommended.
+.TP
+\fB\-sf\fP\ \fIstashfilename\fP
+Specifies the stash file of the master database password.
+.TP
+\fB\-s\fP
+Specifies that the stash file is to be created.
+.TP
+\fB\-maxtktlife\fP\ \fImax_ticket_life\fP
+Specifies maximum ticket life for principals in this realm.
+.TP
+\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP
+Specifies maximum renewable life of tickets for principals in this realm.
+.TP
+\fIticket_flags\fP
+Specifies the ticket flags. If this option is not specified, by default, none of the flags are
+set. This means all the ticket options will be allowed and no restriction will be set.
+
+The various flags are:
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_postdated\fP
+.B -allow_postdated
+prohibits principals from obtaining postdated tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_POSTDATED
+flag.)
+.B +allow_postdated
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_forwardable\fP
+.B -allow_forwardable
+prohibits principals from obtaining forwardable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_FORWARDABLE
+flag.)
+.B +allow_forwardable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_renewable\fP
+.B -allow_renewable
+prohibits principals from obtaining renewable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_RENEWABLE
+flag.)
+.B +allow_renewable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_proxiable\fP
+.B -allow_proxiable
+prohibits principals from obtaining proxiable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_PROXIABLE
+flag.)
+.B +allow_proxiable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_dup_skey\fP
+.B -allow_dup_skey
+Disables user-to-user authentication for principals by prohibiting
+principals from obtaining a session key for another user. (Sets the
+.SM KRB5_KDB_DISALLOW_DUP_SKEY
+flag.)
+.B +allow_dup_skey
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_preauth\fP
+.B +requires_preauth
+requires principals to preauthenticate before being allowed to
+kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_PRE_AUTH
+flag.)
+.B -requires_preauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_hwauth\fP
+.B +requires_hwauth
+requires principals to preauthenticate using a hardware device
+before being allowed to kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_HW_AUTH
+flag.)
+.B -requires_hwauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_svr\fP
+.B -allow_svr
+prohibits the issuance of service tickets for principals.  (Sets the
+.SM KRB5_KDB_DISALLOW_SVR
+flag.)
+.B +allow_svr
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tgs_req\fP
+.B \-allow_tgs_req
+specifies that a Ticket-Granting Service (TGS) request for a service
+ticket for principals is not permitted.  This option is useless for
+most things.
+.B +allow_tgs_req
+clears this flag.  The default is
+.BR +allow_tgs_req .
+In effect,
+.B \-allow_tgs_req
+sets the
+.SM KRB5_KDB_DISALLOW_TGT_BASED
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tix\fP
+.B \-allow_tix
+forbids the issuance of any tickets for principals.
+.B +allow_tix
+clears this flag.  The default is
+.BR +allow_tix .
+In effect,
+.B \-allow_tix
+sets the
+.SM KRB5_KDB_DISALLOW_ALL_TIX
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBneedchange\fP
+.B +needchange
+sets a flag in attributes field to force a password change;
+.B \-needchange
+clears it. The default is
+.BR \-needchange .
+In effect,
+.B +needchange
+sets the
+.SM KRB5_KDB_REQUIRES_PWCHANGE
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBpassword_changing_service\fP
+.B +password_changing_service
+sets a flag in the attributes field marking principal as a password change
+service principal (useless for most things).
+.B \-password_changing_service
+clears the flag. This flag intentionally has a long name. The default
+is
+.BR \-password_changing_service .
+In effect,
+.B +password_changing_service
+sets the
+.SM KRB5_KDB_PWCHANGE_SERVICE
+flag on principals in the database.
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+.B Command Options Specific to eDirectory 
+.TP
+\fB\-kdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects serving the realm. The list contains the DNs of the KDC
+service objects separated by colon(:).
+.TP
+\fB\-admindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects serving the realm. The list contains the DNs
+of the Administration service objects separated by colon(:).
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu
+create -subtrees o=org -sscope SUB
+-r ATHENA.MIT.EDU\fP
+.nf
+Password for "cn=admin,o=org":
+Initializing database for realm 'ATHENA.MIT.EDU'
+You will be prompted for the database Master Password.
+It is important that you NOT FORGET this password.
+Enter KDC database master key:
+Re-enter KDC database master key to verify:
+.fi
+.RE
+
+.TP
+\fBmodify\fP [\fB\-subtrees\fP\ \fIsubtree_dn_list\fP] [\fB\-sscope\fP\ \fIsearch_scope\fP] [\fB\-containerref\fP\ \fIcontainer_reference_dn\fP] [\fB\-r\fP\ \fIrealm\fP] [\fB\-kdcdn\fP\ \fIkdc_service_list\fP | [\fB\-clearkdcdn\fP\ \fIkdc_service_list\fP] [\fB\-addkdcdn\fP\ \fIkdc_service_list\fP]] [\fB\-admindn\fP\ \fIadmin_service_list\fP | [\fB\-clearadmindn\fP\ \fIadmin_service_list\fP] [\fB\-addadmindn\fP\ \fIadmin_service_list\fP]] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP]
+
+Modifies the attributes of a realm. Options:
+.RS
+.TP
+\fB\-subtrees\fP\ \fIsubtree_dn_list\fP
+Specifies the list of subtrees containing the principals of a realm.
+The list contains the DNs of the subtree objects separated by 
+colon(:). This list replaces the existing list.
+.TP
+\fB\-sscope\fP\ \fIsearch_scope\fP
+Specifies the scope for searching the principals under the 
+.IR subtrees .
+The possible values are 1 or one (one level), 2 or sub (subtrees).
+.TP
+\fB\-containerref\fP\ \fIcontainer_reference_dn\fP 
+Specifies the DN of the container object in which the principals of a realm 
+will be created. 
+.TP
+\fB\-maxtktlife\fP\ \fImax_ticket_life\fP
+Specifies maximum ticket life for principals in this realm.
+.TP
+\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP
+Specifies maximum renewable life of tickets for principals in this realm.
+.TP
+\fIticket_flags\fP
+Specifies the ticket flags. If this option is not specified, by default, 
+none of the flags are set. This means all the ticket options will be allowed 
+and no restriction will be set.
+
+The various flags are:
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_postdated\fP
+.B -allow_postdated
+prohibits principals from obtaining postdated tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_POSTDATED
+flag.)
+.B +allow_postdated
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_forwardable\fP
+.B -allow_forwardable
+prohibits principals from obtaining forwardable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_FORWARDABLE
+flag.)
+.B +allow_forwardable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_renewable\fP
+.B -allow_renewable
+prohibits principals from obtaining renewable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_RENEWABLE
+flag.)
+.B +allow_renewable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_proxiable\fP
+.B -allow_proxiable
+prohibits principals from obtaining proxiable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_PROXIABLE
+flag.)
+.B +allow_proxiable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_dup_skey\fP
+.B -allow_dup_skey
+Disables user-to-user authentication for principals by prohibiting
+principals from obtaining a session key for another user. (Sets the
+.SM KRB5_KDB_DISALLOW_DUP_SKEY
+flag.)
+.B +allow_dup_skey
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_preauth\fP
+.B +requires_preauth
+requires principals to preauthenticate before being allowed to
+kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_PRE_AUTH
+flag.)
+.B -requires_preauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_hwauth\fP
+.B +requires_hwauth
+requires principals to preauthenticate using a hardware device
+before being allowed to kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_HW_AUTH
+flag.)
+.B -requires_hwauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_svr\fP
+.B -allow_svr
+prohibits the issuance of service tickets for principals.  (Sets the
+.SM KRB5_KDB_DISALLOW_SVR
+flag.)
+.B +allow_svr
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tgs_req\fP
+.B \-allow_tgs_req
+specifies that a Ticket-Granting Service (TGS) request for a service
+ticket for principals is not permitted.  This option is useless for
+most things.
+.B +allow_tgs_req
+clears this flag.  The default is
+.BR +allow_tgs_req .
+In effect,
+.B \-allow_tgs_req
+sets the
+.SM KRB5_KDB_DISALLOW_TGT_BASED
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tix\fP
+.B \-allow_tix
+forbids the issuance of any tickets for principals.
+.B +allow_tix
+clears this flag.  The default is
+.BR +allow_tix .
+In effect,
+.B \-allow_tix
+sets the
+.SM KRB5_KDB_DISALLOW_ALL_TIX
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBneedchange\fP
+.B +needchange
+sets a flag in attributes field to force a password change;
+.B \-needchange
+clears it. The default is
+.BR \-needchange .
+In effect,
+.B +needchange
+sets the
+.SM KRB5_KDB_REQUIRES_PWCHANGE
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBpassword_changing_service\fP
+.B +password_changing_service
+sets a flag in the attributes field marking principal as a password change
+service principal (useless for most things).
+.B \-password_changing_service
+clears the flag. This flag intentionally has a long name. The default
+is
+.BR \-password_changing_service .
+In effect,
+.B +password_changing_service
+sets the
+.SM KRB5_KDB_PWCHANGE_SERVICE
+flag on principals in the database.
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+.B Command Options Specific to eDirectory
+.TP
+\fB\-kdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects serving the realm. The list contains the DNs of the KDC
+service objects separated by a colon (:). This list replaces the existing list.
+.TP
+\fB\-clearkdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects that need to be removed from the existing list. The list contains
+the DNs of the KDC service objects separated by a colon (:).
+.TP
+\fB\-addkdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects that need to be added to the existing list. The list contains the
+DNs of the KDC service objects separated by a colon (:).
+.TP
+\fB\-admindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects serving the realm. The list contains the DNs
+of the Administration service objects separated by a colon (:). This list replaces the existing list.
+.TP
+\fB\-clearadmindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects that need to be removed from the existing list. The list
+contains the DNs of the Administration service objects separated by a colon (:).
+.TP
+\fB\-addadmindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects that need to be added to the existing list. The list
+contains the DNs of the Administration service objects separated by a colon (:).
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu modify 
++requires_preauth -r ATHENA.MIT.EDU \fP
+.nf
+Password for "cn=admin,o=org":
+.fi
+.RE
+.TP
+\fBview\fP [\fB\-r\fP\ \fIrealm\fP]
+Displays the attributes of a realm.  Options:
+.RS
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu view 
+-r ATHENA.MIT.EDU\fP
+.nf
+Password for "cn=admin,o=org":
+               Realm Name: ATHENA.MIT.EDU
+                  Subtree: ou=users,o=org
+                  Subtree: ou=servers,o=org
+              SearchScope: ONE
+      Maximum ticket life: 0 days 01:00:00
+   Maximum renewable life: 0 days 10:00:00
+             Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE
+.fi
+.RE
+.TP
+\fBdestroy\fP [\fB-f\fP] [\fB\-r\fP\ \fIrealm\fP]
+Destroys an existing realm. Options:
+.RS
+.TP
+\fB\-f\fP
+If specified, will not prompt the user for confirmation.  
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu destroy 
+-r ATHENA.MIT.EDU\fP
+.nf
+Password for "cn=admin,o=org":
+Deleting KDC database of 'ATHENA.MIT.EDU', are you sure?
+(type 'yes' to confirm)? yes
+OK, deleting database of 'ATHENA.MIT.EDU'...
+.fi
+.RE
+.TP
+\fBlist\fP
+
+Lists the name of realms.
+.RS
+.nf
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu list\fP
+Password for "cn=admin,o=org":
+ATHENA.MIT.EDU
+OPENLDAP.MIT.EDU
+MEDIA-LAB.MIT.EDU
+.fi
+.RE
+.TP
+\fBstashsrvpw\fP [\fB\-f\fP\ \fIfilename\fP] \fIservicedn\fP
+Allows an administrator to store the password for service object in a file so that KDC and Administration
+server can use it to authenticate to the LDAP server. Options:
+.RS
+.TP
+\fB\-f\fP\ \fIfilename\fP
+Specifies the complete path of the service password file. By default, /usr/local/var/service_passwd is used.
+.TP
+\fIservicedn\fP
+Specifies Distinguished name (DN) of the service object whose password is to be stored in file.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util stashsrvpw -f /home/andrew/conf_keyfile cn=service-kdc,o=org\fP
+.nf
+Password for "cn=service-kdc,o=org":
+Re-enter password for "cn=service-kdc,o=org":
+.fi
+.RE
+.TP
+\fBcreate_policy\fP [\fB\-r\fP\ \fIrealm\fP] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP] \fIpolicy_name\fP
+Creates a ticket policy in directory. Options:
+.RS
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+\fB\-maxtktlife\fP\ \fImax_ticket_life\fP
+Specifies maximum ticket life for principals.
+.TP
+\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP
+Specifies maximum renewable life of tickets for principals.
+.TP
+\fIticket_flags\fP
+Specifies the ticket flags. If this option is not specified, by default, none of the flags are
+set. This means all the ticket options will be allowed and no restriction will be set.
+
+The various flags are:
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_postdated\fP
+.B -allow_postdated
+prohibits principals from obtaining postdated tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_POSTDATED
+flag.)
+.B +allow_postdated
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_forwardable\fP
+.B -allow_forwardable
+prohibits principals from obtaining forwardable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_FORWARDABLE
+flag.)
+.B +allow_forwardable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_renewable\fP
+.B -allow_renewable
+prohibits principals from obtaining renewable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_RENEWABLE
+flag.)
+.B +allow_renewable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_proxiable\fP
+.B -allow_proxiable
+prohibits principals from obtaining proxiable tickets.  (Sets the
+.SM KRB5_KDB_DISALLOW_PROXIABLE
+flag.)
+.B +allow_proxiable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_dup_skey\fP
+.B -allow_dup_skey
+Disables user-to-user authentication for principals by prohibiting
+principals from obtaining a session key for another user. (Sets the
+.SM KRB5_KDB_DISALLOW_DUP_SKEY
+flag.)
+.B +allow_dup_skey
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_preauth\fP
+.B +requires_preauth
+requires principals to preauthenticate before being allowed to
+kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_PRE_AUTH
+flag.)
+.B -requires_preauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_hwauth\fP
+.B +requires_hwauth
+requires principals to preauthenticate using a hardware device
+before being allowed to kinit.  (Sets the
+.SM KRB5_KDB_REQUIRES_HW_AUTH
+flag.)
+.B -requires_hwauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_svr\fP
+.B -allow_svr
+prohibits the issuance of service tickets for principals.  (Sets the
+.SM KRB5_KDB_DISALLOW_SVR
+flag.)
+.B +allow_svr
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tgs_req\fP
+.B \-allow_tgs_req
+specifies that a Ticket-Granting Service (TGS) request for a service
+ticket for principals is not permitted.  This option is useless for
+most things.
+.B +allow_tgs_req
+clears this flag.  The default is
+.BR +allow_tgs_req .
+In effect,
+.B \-allow_tgs_req
+sets the
+.SM KRB5_KDB_DISALLOW_TGT_BASED
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tix\fP
+.B \-allow_tix
+forbids the issuance of any tickets for principals.
+.B +allow_tix
+clears this flag.  The default is
+.BR +allow_tix .
+In effect,
+.B \-allow_tix
+sets the
+.SM KRB5_KDB_DISALLOW_ALL_TIX
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBneedchange\fP
+.B +needchange
+sets a flag in attributes field to force a password change;
+.B \-needchange
+clears it. The default is
+.BR \-needchange .
+In effect,
+.B +needchange
+sets the
+.SM KRB5_KDB_REQUIRES_PWCHANGE
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBpassword_changing_service\fP
+.B +password_changing_service
+sets a flag in the attributes field marking principal as a password change
+service principal (useless for most things).
+.B \-password_changing_service
+clears the flag. This flag intentionally has a long name. The default
+is
+.BR \-password_changing_service .
+In effect,
+.B +password_changing_service
+sets the
+.SM KRB5_KDB_PWCHANGE_SERVICE
+flag on principals in the database.
+.TP
+\fIpolicy_name\fP
+Specifies the name of the ticket policy.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu create_policy -r ATHENA.MIT.EDU -maxtktlife "1 day" -maxrenewlife "1 week" -allow_postdated +needchange -allow_forwardable tktpolicy\fP
+.nf
+Password for "cn=admin,o=org":
+.fi
+.RE
+.TP
+\fBmodify_policy\fP [\fB\-r\fP\ \fIrealm\fP] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP] \fIpolicy_name\fP
+Modifies the attributes of a ticket policy. Options are same as 
+.B create_policy.
+.RS
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu modify_policy -r ATHENA.MIT.EDU -maxtktlife "60 minutes" -maxrenewlife "10 hours" +allow_postdated -requires_preauth tktpolicy\fP
+.nf
+Password for "cn=admin,o=org":
+.fi
+.RE
+.TP
+\fBview_policy\fP [\fB\-r\fP\ \fIrealm\fP] \fIpolicy_name\fP
+Displays the attributes of a ticket policy. Options:
+.RS
+.TP
+\fIpolicy_name\fP
+Specifies the name of the ticket policy.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu view_policy -r ATHENA.MIT.EDU tktpolicy\fP
+.nf
+Password for "cn=admin,o=org":
+            Ticket policy: tktpolicy
+      Maximum ticket life: 0 days 01:00:00
+   Maximum renewable life: 0 days 10:00:00
+             Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE
+.fi
+.RE
+.TP
+\fBdestroy_policy\fP [\fB\-r\fP\ \fIrealm\fP] [\fB\-force\fP] \fIpolicy_name\fP
+Destroys an existing ticket policy. Options:
+.RS
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+\fB\-force\fP
+Forces the deletion of the policy object. If not specified, will be prompted for confirmation while deleting the policy. Enter 
+.B yes
+to confirm the deletion.
+.TP
+\fIpolicy_name\fP
+Specifies the name of the ticket policy.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu destroy_policy -r ATHENA.MIT.EDU tktpolicy\fP
+.nf
+Password for "cn=admin,o=org":
+This will delete the policy object 'tktpolicy', are you sure?
+(type 'yes' to confirm)? yes
+** policy object 'tktpolicy' deleted.
+.fi
+.RE
+.TP
+\fBlist_policy\fP [\fB\-r\fP\ \fIrealm\fP]
+Lists the ticket policies in \fIrealm\fP if specified or in the default realm.  Options:
+.RS
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu list_policy -r ATHENA.MIT.EDU\fP
+.nf
+Password for "cn=admin,o=org":
+tktpolicy
+tmppolicy
+userpolicy
+.fi
+.RE
+
+.TP
+.B Commands Specific to eDirectory
+.TP
+\fBsetsrvpw\fP [\fB\-randpw\fP|\fB\-fileonly\fP] [\fB\-f\fP\ \fIfilename\fP] \fIservice_dn\fP
+Allows an administrator to set password for service objects such as KDC and Administration server in
+eDirectory and store them in a file. The 
+.I -fileonly 
+option stores the password in a file and not in the eDirectory object. Options:
+.RS
+.TP
+\fB\-randpw \fP
+Generates and sets a random password. This options can be specified to store the password both in eDirectory and a file. The 
+.I -fileonly 
+option can not be used if 
+.I -randpw
+option is already specified.
+.TP
+\fB\-fileonly\fP
+Stores the password only in a file and not in eDirectory. The 
+.I -randpw
+option can not be used when 
+.I -fileonly
+options is specified.
+.TP
+\fB\-f\fP\ \fIfilename\fP
+Specifies complete path of the service password file. By default, /usr/local/var/service_passwd is used.
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the service object whose password is to be set.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util setsrvpw -D cn=admin,o=org setsrvpw -fileonly -f /home/andrew/conf_keyfile
+cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+Password for "cn=service-kdc,o=org":
+Re-enter password for "cn=service-kdc,o=org":
+.fi
+.RE
+.TP
+\fBcreate_service\fP {\fB\-kdc|\-admin\fP} [\fB\-servicehost\fP\ \fIservice_host_list\fP] [\fB\-realm\fP\ \fIrealm_list\fP] [\fB\-randpw|\-fileonly\fP] [\fB\-f\fP\ \fIfilename\fP] \fIservice_dn\fP
+Creates a service in directory and assigns appropriate rights. Options:
+.RS
+.TP
+\fB\-kdc\fP 
+Specifies the service is a KDC service
+.TP
+\fB\-admin\fP
+Specifies the service is a Administration service
+.TP
+\fB\-servicehost\fP\ \fIservice_host_list\fP
+Specifies the list of entries separated by a colon (:). Each entry consists of the hostname or IP
+address of the server hosting the service, transport protocol, and the port number of
+the service separated by a pound sign (#). 
+For example,
+server1#tcp#88:server2#udp#89.
+.TP
+\fB\-realm\fP\ \fIrealm_list\fP
+Specifies the list of realms that are to be associated with this service. The list contains the name of the realms
+separated by a colon (:).
+.TP
+\fB\-randpw \fP
+Generates and sets a random password. This option is used to set the random password for the service object in directory and also to store it in the file. The 
+.I -fileonly 
+option can not be used if 
+.I -randpw
+option is specified.
+.TP
+\fB\-fileonly\fP
+Stores the password only in a file and not in eDirectory. The 
+.I -randpw
+option can not be used when 
+.I -fileonly
+option is specified.
+.TP
+\fB\-f\fP\ \fIfilename\fP
+Specifies the complete path of the file where the service object password is stashed.
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be created.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org create_service -kdc -randpw -f /home/andrew/conf_keyfile cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+File does not exist. Creating the file /home/andrew/conf_keyfile...
+.fi
+.RE
+.TP
+\fBmodify_service\fP [\fB\-servicehost\fP\ \fIservice_host_list\fP | [\fB\-clearservicehost\fP\ \fIservice_host_list\fP] [\fB\-addservicehost\fP\ \fIservice_host_list\fP]] [\fB\-realm\fP\ \fIrealm_list\fP | [\fB\-clearrealm\fP\ \fIrealm_list\fP] [\fB\-addrealm\fP\ \fIrealm_list\fP]] \fIservice_dn\fP
+Modifies the attributes of a service and assigns appropriate rights. Options:
+.RS
+.TP
+\fB\-servicehost\fP\ \fIservice_host_list\fP
+Specifies the list of entries separated by a colon (:). Each entry consists of a host name
+or IP Address of the Server hosting the service, transport protocol, and port
+number of the service separated by a pound sign (#). 
+For example,
+server1#tcp#88:server2#udp#89
+.TP
+\fB\-clearservicehost\fP\ \fIservice_host_list\fP
+Specifies the list of servicehost entries to be removed from the existing list separated by colon (:). Each entry consists of a host name or IP Address of the server
+hosting the service, transport protocol, and port number of the service separated
+by a pound sign (#).
+.TP
+\fB\-addservicehost\fP\ \fIservice_host_list\fP
+Specifies the list of servicehost entries to be added to the existing list separated by colon (:). Each entry consists of a host name or IP Address of the
+server hosting the service, transport protocol, and port number of the service
+separated by a pound sign (#).
+.TP
+\fB\-realm\fP\ \fIrealm_list\fP
+Specifies the list of realms that are to be associated with this service. The list contains the name of
+the realms separated by a colon (:). This list replaces the existing list.
+.TP
+\fB\-clearrealm\fP\ \fIrealm_list\fP
+Specifies the list of realms to be removed from the existing list. The list contains the name of
+the realms separated by a colon (:).
+.TP
+\fB\-addrealm\fP\ \fIrealm_list\fP
+Specifies the list of realms to be added to the existing list. The list contains the name of the
+realms separated by a colon (:).
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be modified.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org modify_service -realm ATHENA.MIT.EDU
+cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+Changing rights for the service object. Please wait ... done
+.fi
+.RE
+.TP
+\fBview_service\fP \fIservice_dn\fP
+Displays the attributes of a service.  Options:
+.RS
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be viewed.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org view_service cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+        Service dn: cn=service-kdc,o=org
+      Service type: kdc
+ Service host list:
+     Realm DN list: cn=ATHENA.MIT.EDU,cn=Kerberos,cn=Security
+.fi
+.RE
+.TP
+\fBdestroy_service\fP [\fB\-force\fP] [\fB\-f\fP\ \fIstashfilename\fP] \fIservice_dn\fP
+Destroys an existing service. Options:
+.RS
+.TP
+\fB\-force\fP
+If specified, will not prompt for user's confirmation, instead will force destruction of the service.
+.TP
+\fB\-f\fP\ \fIstashfilename\fP
+Specifies the complete path of the service password file from where the entry corresponding to the 
+.I service_dn
+needs to be removed.
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be destroyed.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org destroy_service cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+This will delete the service object 'cn=service-kdc,o=org', are you sure?
+(type 'yes' to confirm)? yes
+** service object 'cn=service-kdc,o=org' deleted.
+.fi
+.RE
+.TP
+\fBlist_service\fP [\fB\-basedn\fP\ \fIbase_dn\fP]
+Lists the name of services under a given base in directory. Options:
+.RS
+.TP
+\fB\-basedn\fP\ \fIbase_dn\fP
+Specifies the base DN for searching the service objects, limiting the search to a particular subtree. If this option
+is not provided, LDAP Server specific search base will be used. 
+For eg, in the case of OpenLDAP, value of 
+.B defaultsearchbase
+from 
+.I slapd.conf
+file will be used, where as in the case of eDirectory, the default value 
+for the base DN is 
+.B Root.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org list_service\fP
+.nf
+Password for "cn=admin,o=org":
+cn=service-kdc,o=org
+cn=service-adm,o=org
+cn=service-pwd,o=org
+.fi
+.RE
+.SH SEE ALSO
+kadmin(8)
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
new file mode 100644
index 000000000..9fcc7b79d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
@@ -0,0 +1,631 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_util.c
+ *
+ * (C) Copyright 1990,1991, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * 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.
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <time.h>
+
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#include "kdb5_ldap_util.h"
+
+typedef void (*cmd_func)(int, char **);
+int cmd_index(char *name);
+
+char *mkey_password = 0;
+int exit_status = 0;
+krb5_context util_context;
+kadm5_config_params global_params;
+krb5_boolean db_inited = FALSE;
+
+char *progname;
+krb5_boolean manual_mkey = FALSE;
+
+/*
+ * This function prints the usage of kdb5_ldap_util, which is
+ * the LDAP configuration utility.
+ */
+void usage()
+{
+    fprintf(stderr, "Usage: "
+"kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri]\n"
+"\tcmd [cmd_options]\n"
+
+/* Create realm */
+"create          [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\n"
+#ifdef HAVE_EDIRECTORY
+"\t\t[-kdcdn kdc_service_list] [-admindn admin_service_list]\n"
+"\t\t[-pwddn passwd_service_list]\n"
+#endif
+"\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-s]\n"
+"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
+"\t\t[ticket_flags] [-r realm]\n"
+
+/* modify realm */
+"modify          [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\n"
+#ifdef HAVE_EDIRECTORY
+"\t\t[-kdcdn kdc_service_list |\n"
+"\t\t[-clearkdcdn kdc_service_list] [-addkdcdn kdc_service_list]]\n"
+"\t\t[-admindn admin_service_list | [-clearadmindn admin_service_list]\n"
+"\t\t[-addadmindn admin_service_list]] [-pwddn passwd_service_list |\n"
+"\t\t[-clearpwddn passwd_service_list] [-addpwddn passwd_service_list]]\n"
+#endif
+"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
+"\t\t[ticket_flags] [-r realm]\n"
+/* View realm */
+"view            [-r realm]\n"
+
+/* Destroy realm */
+"destroy	        [-f] [-r realm]\n"
+
+/* List realms */
+"list\n"
+
+#ifdef HAVE_EDIRECTORY
+/* Create Service */
+"create_service  {-kdc|-admin|-pwd} [-servicehost service_host_list]\n"
+"\t\t[-realm realm_list] \n"
+"\t\t[-randpw|-fileonly] [-f filename] service_dn\n"
+
+/* Modify service */
+"modify_service  [-servicehost service_host_list |\n"
+"\t\t[-clearservicehost service_host_list]\n"
+"\t\t[-addservicehost service_host_list]]\n"
+"\t\t[-realm realm_list | [-clearrealm realm_list]\n"
+"\t\t[-addrealm realm_list]] service_dn\n"
+
+/* View Service */
+"view_service    service_dn\n"
+
+/* Destroy Service */
+"destroy_service [-force] [-f stashfilename] service_dn\n"
+
+/* List services */
+"list_service    [-basedn base_dn]\n"
+
+/* Set Service password */
+"setsrvpw        [-randpw|-fileonly] [-f filename] service_dn\n"
+
+#else
+
+/* Stash the service password */
+"stashsrvpw      [-f filename] service_dn\n"
+
+#endif
+
+/* Create policy */
+"create_policy   [-r realm] [-maxtktlife max_ticket_life]\n"
+"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
+
+/* Modify policy */
+"modify_policy   [-r realm] [-maxtktlife max_ticket_life]\n"
+"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
+
+/* View policy */
+"view_policy     [-r realm] policy\n"
+
+/* Destroy policy */
+"destroy_policy  [-r realm] [-force] policy\n"
+
+/* List policies */
+"list_policy     [-r realm]\n"
+
+	);
+}
+
+void db_usage (int type) {
+    /*
+     * This should print usage of 'type' command. For now, we will print usage
+     * of all commands.
+     */
+    usage ();
+}
+
+/* The help messages for all sub-commands should be in the
+ * same order as listed in this table.
+ */
+static struct _cmd_table {
+    char *name;
+    cmd_func func;
+    int opendb;
+} cmd_table[] = {
+    {"create", kdb5_ldap_create, 1},
+    {"modify", kdb5_ldap_modify, 1},
+    {"view", kdb5_ldap_view, 1},
+    {"destroy", kdb5_ldap_destroy, 1},
+    {"list", kdb5_ldap_list, 1},
+#ifdef HAVE_EDIRECTORY
+    {"create_service", kdb5_ldap_create_service, 1},
+    {"modify_service", kdb5_ldap_modify_service, 1},
+    {"view_service", kdb5_ldap_view_service, 1},
+    {"destroy_service", kdb5_ldap_destroy_service, 1},
+    {"list_service",kdb5_ldap_list_services,1},
+    {"setsrvpw", kdb5_ldap_set_service_password, 0},
+#else
+    {"stashsrvpw", kdb5_ldap_stash_service_password, 0},
+#endif
+    {"create_policy", kdb5_ldap_create_policy, 1},
+    {"modify_policy", kdb5_ldap_modify_policy, 1},
+    {"view_policy", kdb5_ldap_view_policy, 1},
+    {"destroy_policy", kdb5_ldap_destroy_policy, 1},
+    {"list_policy", kdb5_ldap_list_policies, 1},
+    {NULL, NULL, 0},
+};
+
+
+/*
+ * The function cmd_lookup returns the structure matching the
+ * command name and returns NULL if nothing matches.
+ */
+static struct _cmd_table *cmd_lookup(name)
+    char *name;
+{
+    int i;
+
+    for (i = 0; cmd_table[i].name != NULL; i++)
+	if (strcmp(cmd_table[i].name, name) == 0)
+	    return &cmd_table[i];
+
+    return NULL;
+}
+
+
+/*
+ * The function cmd_index provides the offset of the command
+ * in the command table, which can be used to get the corresponding
+ * help from the help message table.
+ */
+int cmd_index(name)
+    char *name;
+{
+    int i;
+
+    if (name == NULL)
+	return -1;
+
+    for (i = 0; cmd_table[i].name != NULL; i++)
+	if (strcmp(cmd_table[i].name, name) == 0)
+	    return i;
+
+    return -1;
+}
+
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+				 const char *fmt, va_list args)
+{
+    const char *emsg;
+    emsg = krb5_get_error_message (util_context, code);
+    fprintf (stderr, "%s: %s ", myprog, emsg);
+    krb5_free_error_message (util_context, emsg);
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+}
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    struct _cmd_table *cmd = NULL;
+    char *koptarg = NULL, **cmd_argv = NULL;
+    int cmd_argc = 0;
+    krb5_error_code retval;
+    int usage_print = 0;
+    int gp_is_static = 1;
+    krb5_error_code db_retval = 1;
+    char *bind_dn = NULL;
+    char *passwd = NULL;
+    char *ldap_server = NULL;
+    unsigned int ldapmask = 0;
+    unsigned int passwd_len = 0;
+    char *prompt = NULL;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+    char *value = NULL, *conf_section = NULL;
+    krb5_boolean realm_name_required = TRUE;
+    krb5_boolean print_help_message = FALSE;
+
+    retval = krb5_init_context(&util_context);
+    set_com_err_hook(extended_com_err_fn);
+    if (retval) {
+	com_err (progname, retval, "while initializing Kerberos code");
+	exit_status++;
+	goto cleanup;
+    }
+
+    progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+    cmd_argv = (char **) malloc(sizeof(char *)*argc);
+    if (cmd_argv == NULL) {
+	com_err(progname, ENOMEM, "while creating sub-command arguments");
+	exit_status++;
+	goto cleanup;
+    }
+    memset(cmd_argv, 0, sizeof(char *)*argc);
+    cmd_argc = 1;
+
+    memset(&global_params, 0, sizeof(kadm5_config_params));
+
+    argv++; argc--;
+    while (*argv) {
+	if (strcmp(*argv, "--help") == 0) {
+	    print_help_message = TRUE;
+	}
+	if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
+	    mkey_password = koptarg;
+	    manual_mkey = TRUE;
+	} else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
+	    global_params.realm = koptarg;
+	    global_params.mask |= KADM5_CONFIG_REALM;
+	    /* not sure this is really necessary */
+	    if ((retval = krb5_set_default_realm(util_context,
+						 global_params.realm))) {
+		com_err(progname, retval, "while setting default realm name");
+		exit_status++;
+		goto cleanup;
+	    }
+	} else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
+	    if (krb5_string_to_enctype(koptarg, &global_params.enctype))
+		com_err(argv[0], 0, "%s is an invalid enctype", koptarg);
+	    else
+		global_params.mask |= KADM5_CONFIG_ENCTYPE;
+	} else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
+	    global_params.mkey_name = koptarg;
+	    global_params.mask |= KADM5_CONFIG_MKEY_NAME;
+	} else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) {
+	    global_params.stash_file = koptarg;
+	    global_params.mask |= KADM5_CONFIG_STASH_FILE;
+	} else if (strcmp(*argv, "-m") == 0) {
+	    manual_mkey = TRUE;
+	    global_params.mkey_from_kbd = 1;
+	    global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+	} else if (strcmp(*argv, "-D") == 0 && ARG_VAL) {
+	    bind_dn = koptarg;
+	    if (bind_dn == NULL) {
+		com_err(progname, ENOMEM, "while reading ldap parameters");
+		exit_status++;
+		goto cleanup;
+	    }
+	    ldapmask |= CMD_LDAP_D;
+	} else if (strcmp(*argv, "-w") == 0 && ARG_VAL) {
+	    passwd = strdup(koptarg);
+	    if (passwd == NULL) {
+		com_err(progname, ENOMEM, "while reading ldap parameters");
+		exit_status++;
+		goto cleanup;
+	    }
+	    ldapmask |= CMD_LDAP_W;
+	} else if (strcmp(*argv, "-H") == 0 && ARG_VAL) {
+	    ldap_server = koptarg;
+	    if (ldap_server == NULL) {
+		com_err(progname, ENOMEM, "while reading ldap parameters");
+		exit_status++;
+		goto cleanup;
+	    }
+	    ldapmask |= CMD_LDAP_H;
+	} else if (cmd_lookup(*argv) != NULL) {
+	    if (cmd_argv[0] == NULL)
+		cmd_argv[0] = *argv;
+	    else {
+		free(cmd_argv);
+		cmd_argv = NULL;
+		usage();
+		goto cleanup;
+	    }
+	} else {
+	    cmd_argv[cmd_argc++] = *argv;
+	}
+	argv++; argc--;
+    }
+
+    if (cmd_argv[0] == NULL) {
+	free(cmd_argv);
+	cmd_argv = NULL;
+	usage();
+	goto cleanup;
+    }
+
+    /* if we need to print the help message (because of --help option)
+     * we will print the help corresponding to the sub-command.
+     */
+    if (print_help_message) {
+	char *cmd_name = cmd_argv[0];
+	free(cmd_argv);
+	cmd_argv = NULL;
+	usage();
+	goto cleanup;
+    }
+
+    /* We need to check for the presence of default realm name only in
+     * the case of realm related operations like create, destroy etc.
+     */
+    if ((strcmp(cmd_argv[0], "list") == 0) ||
+        (strcmp(cmd_argv[0], "stashsrvpw") == 0)) {
+        realm_name_required = FALSE;
+    }
+
+    if (!util_context->default_realm) {
+	char *temp = NULL;
+	retval = krb5_get_default_realm(util_context, &temp);
+	if (retval) {
+	    if (realm_name_required) {
+		com_err (progname, retval, "while getting default realm");
+		exit_status++;
+		goto cleanup;
+	    }
+	} else
+	    util_context->default_realm = temp;
+    }
+    /* If we have the realm name, we can safely say that
+     * realm_name is required so that we don't neglect any information.
+     */
+    else
+	realm_name_required = TRUE;
+
+    retval = profile_get_string(util_context->profile, KDB_REALM_SECTION,
+				util_context->default_realm, KDB_MODULE_POINTER,
+				NULL,
+				&value);
+
+    if (!(value)) {
+	retval = profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION,
+				    KDB_MODULE_POINTER, NULL,
+				    NULL,
+				    &value);
+	if (!(value)) {
+	    if (util_context->default_realm)
+		conf_section = strdup(util_context->default_realm);
+	} else {
+	    conf_section = strdup(value);
+	    free(value);
+	}
+    } else {
+	conf_section = strdup(value);
+	free(value);
+    }
+
+    if (realm_name_required) {
+	retval = kadm5_get_config_params(util_context, 1,
+					 &global_params, &global_params);
+	if (retval) {
+	    com_err(argv[0], retval, "while retreiving configuration parameters");
+	    exit_status++;
+	    goto cleanup;
+	}
+	gp_is_static = 0;
+    }
+
+    if ((retval = krb5_ldap_lib_init()) != 0) {
+	com_err(argv[0], retval, "while initializing error handling");
+	exit_status++;
+	goto cleanup;
+    }
+
+    /* Initialize the ldap context */
+    ldap_context = calloc(sizeof(krb5_ldap_context), 1);
+    if (ldap_context == NULL) {
+	com_err(argv[0], ENOMEM, "while initializing ldap handle");
+	exit_status++;
+	goto cleanup;
+    }
+
+    ldap_context->kcontext = util_context;
+
+    /* If LDAP parameters are specified, replace them with the values from config */
+    if (ldapmask & CMD_LDAP_D) {
+	/* If password is not specified, prompt for it */
+	if (passwd == NULL) {
+	    passwd = (char *)malloc(MAX_PASSWD_LEN);
+	    if (passwd == NULL) {
+		com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+		exit_status++;
+		goto cleanup;
+	    }
+	    prompt = (char *)malloc(MAX_PASSWD_PROMPT_LEN);
+	    if (prompt == NULL) {
+		free(passwd);
+		passwd = NULL;
+		com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+		exit_status++;
+		goto cleanup;
+	    }
+	    memset(passwd, 0, sizeof(passwd));
+	    passwd_len = MAX_PASSWD_LEN - 1;
+	    snprintf(prompt, MAX_PASSWD_PROMPT_LEN, "Password for \"%s\"", bind_dn);
+
+	    db_retval = krb5_read_password(util_context, prompt, NULL, passwd, &passwd_len);
+
+	    if ((db_retval) || (passwd_len == 0)) {
+		com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+		free(passwd);
+		passwd = NULL;
+		exit_status++;
+		goto cleanup;
+	    }
+	}
+
+	ldap_context->bind_pwd = passwd;
+    }
+
+    /* If ldaphost is specified, release entry filled by configuration & use this */
+    if (ldapmask & CMD_LDAP_H) {
+
+	ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (2, sizeof (krb5_ldap_server_info *)) ;
+	if (ldap_context->server_info_list == NULL) {
+	    com_err(argv[0], ENOMEM, "while initializing server list");
+	    exit_status++;
+	    goto cleanup;
+	}
+
+	ldap_context->server_info_list[0] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info));
+	if (ldap_context->server_info_list[0] == NULL) {
+	    com_err(argv[0], ENOMEM, "while initializing server list");
+	    exit_status++;
+	    goto cleanup;
+	}
+
+	ldap_context->server_info_list[0]->server_status = NOTSET;
+
+	ldap_context->server_info_list[0]->server_name = strdup(ldap_server);
+	if (ldap_context->server_info_list[0]->server_name == NULL) {
+	    com_err(argv[0], ENOMEM, "while initializing server list");
+	    exit_status++;
+	    goto cleanup;
+	}
+    }
+    if (bind_dn) {
+	ldap_context->bind_dn = strdup(bind_dn);
+	if (ldap_context->bind_dn == NULL) {
+	    com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+	    exit_status++;
+	    goto cleanup;
+	}
+    } else
+	ldap_context->bind_dn = NULL;
+
+    ldap_context->service_type = SERVICE_DN_TYPE_CLIENT;
+
+    if (realm_name_required) {
+	if ((global_params.enctype != ENCTYPE_UNKNOWN) &&
+	    (!krb5_c_valid_enctype(global_params.enctype))) {
+	    com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP,
+		    "while setting up enctype %d", global_params.enctype);
+	}
+    }
+
+    cmd = cmd_lookup(cmd_argv[0]);
+
+    /* Setup DAL handle to access the database */
+    dal_handle = calloc((size_t)1, sizeof(kdb5_dal_handle));
+    if (dal_handle == NULL) {
+	goto cleanup;
+    }
+    dal_handle->db_context = ldap_context;
+    util_context->db_context = (void *) dal_handle;
+
+    db_retval = krb5_ldap_read_server_params(util_context, conf_section, KRB5_KDB_SRV_TYPE_OTHER);
+    if (db_retval) {
+	com_err(argv[0], db_retval, "while reading ldap configuration");
+	exit_status++;
+	goto cleanup;
+    }
+
+    if (cmd->opendb) {
+	db_retval = krb5_ldap_db_init(util_context, ldap_context);
+	if (db_retval) {
+	    com_err(progname, db_retval, "while initializing database");
+	    exit_status++;
+	    goto cleanup;
+	}
+	db_inited = TRUE;
+    }
+    (*cmd->func)(cmd_argc, cmd_argv);
+
+    goto cleanup;
+
+cleanup:
+    if (passwd)
+	memset(passwd, 0, sizeof(passwd));
+    if (ldap_context && ldap_context->bind_pwd)
+	memset(ldap_context->bind_pwd, 0, sizeof(ldap_context->bind_pwd));
+
+    if (util_context) {
+	if (gp_is_static == 0)
+	    kadm5_free_config_params(util_context, &global_params);
+	krb5_ldap_close(util_context);
+	krb5_free_context(util_context);
+    }
+
+    if (cmd_argv)
+	free(cmd_argv);
+    if (prompt)
+	free(prompt);
+    if (conf_section)
+	free(conf_section);
+    if (dal_handle)
+	free(dal_handle);
+
+    if (usage_print) {
+	usage();
+    }
+
+    return exit_status;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h
new file mode 100644
index 000000000..f2c49a57e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h
@@ -0,0 +1,78 @@
+/* 
+ * kadmin/ldap_util/kdb5_ldap_util.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "kdb_ldap.h"
+#include "kdb5_ldap_realm.h"
+#include "kdb5_ldap_services.h"
+#include "kdb5_ldap_policy.h"
+
+#define MAIN_HELP            -1
+#define CREATE_REALM          1
+#define MODIFY_REALM          2
+#define VIEW_REALM            3
+#define DESTROY_REALM         4
+#define LIST_REALM            5
+
+#ifdef HAVE_EDIRECTORY
+# define CREATE_SERVICE        6 
+# define MODIFY_SERVICE        7
+# define VIEW_SERVICE          8
+# define DESTROY_SERVICE       9
+# define LIST_SERVICE          10
+# define SET_SRV_PW            16
+#else
+# define STASH_SRV_PW          17
+#endif
+
+#define CREATE_POLICY         11
+#define MODIFY_POLICY         12
+#define VIEW_POLICY           13
+#define DESTROY_POLICY        14
+#define LIST_POLICY           15
+
+extern int exit_status;
+extern krb5_context util_context;
+
+extern void usage();
+extern void db_usage(int);
+
+#define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(MAIN_HELP), NULL))
+
+/* Following are the bitmaps that indicate which of the options among -D, -w, -h, -p & -t
+ * were specified on the command line.
+ */
+#define CMD_LDAP_D	0x1     /* set if -D option is specified */
+#define CMD_LDAP_W	0x2     /* set if -w option is specified */
+#define CMD_LDAP_H	0x4     /* set if -h option is specified */
+#define CMD_LDAP_P	0x8     /* set if -p option is specified */
+
+#define MAX_PASSWD_LEN          1024
+#define MAX_PASSWD_PROMPT_LEN   276     /* max_dn_size(=256) + strlen("Password for \" \"")=20 */
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ChangeLog b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ChangeLog
new file mode 100644
index 000000000..d8553db18
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ChangeLog
@@ -0,0 +1,37 @@
+2006-04-08  Ken Raeburn  <raeburn@mit.edu>
+
+	* kdb_ldap.c, kdb_ldap_conn.c: Include autoconf.h before testing
+	HAVE_UNISTD_H.
+
+2006-03-22  Ken Raeburn  <raeburn@mit.edu>
+
+	* Makefile.in (DEFS): Define a bunch of macros for local renaming
+	of symbol names duplicated in libkdb5 and exported from there.
+
+2006-03-21  Ken Raeburn  <raeburn@mit.edu>
+
+	* Makefile.in (SHLIB_EXPDEPS, SHLIB_EXPLIBS): Add kdb5 library.
+	(LIBMAJOR): Bump to 1.
+
+2006-03-20  Ken Raeburn  <raeburn@mit.edu>
+
+	* ldap_misc.c (krb5_ldap_get_keysalt_tuples): Unused function
+	deleted.
+	(LDAP_DEFAULT_ENCTYPE, LDAP_DEFAULT_SALTTYPE): Macros deleted.
+	* kdb_ldap.h (krb5_ldap_get_keysalt_tuples): Don't declare it.
+
+2006-03-17  Ken Raeburn  <raeburn@mit.edu>
+
+	* configure.in, kdb_ldap.c, kdb_ldap_conn.c, kdb_xdr.c, kdb_xdr.h,
+	kerberos.ldif, kerberos.schema, ldap_err.c, ldap_err.h,
+	ldap_fetch_mkey.c, ldap_handle.c, ldap_handle.h,
+	ldap_krbcontainer.c, ldap_krbcontainer.h, ldap_main.h,
+	ldap_misc.c, ldap_misc.h, ldap_principal2.c, ldap_principal.c,
+	ldap_principal.h, ldap_pwd_policy.c, ldap_pwd_policy.h,
+	ldap_realm.c, ldap_realm.h, ldap_service_rights.c,
+	ldap_services.c, ldap_services.h, ldap_service_stash.c,
+	ldap_service_stash.h, ldap_tkt_policy.c, ldap_tkt_policy.h,
+	princ_xdr.c, princ_xdr.h: Moved from plugins/kdb/kdb_ldap.
+	* libkdb_ldap.exports: Copied and updated.
+	* Makefile.in: Copied and updated to build a shared library.
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
new file mode 100644
index 000000000..7fea15f1a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
@@ -0,0 +1,308 @@
+thisconfigdir=.
+myfulldir=plugins/kdb/ldap/libkdb_ldap
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+# Lots of ugliness here because of duplicated symbol names.
+# Can I just punt the duplicates and import from libkdb5, or
+# is keeping them separate important?
+DEFINES = \
+	-Dkrb5_dbe_lookup_last_pwd_change=kdb_ldap_dbe_lookup_last_pwd_change \
+	-Dkrb5_dbe_lookup_mod_princ_data=kdb_ldap_dbe_lookup_mod_princ_data \
+	-Dkrb5_dbe_lookup_tl_data=kdb_ldap_dbe_lookup_tl_data \
+	-Dkrb5_dbe_update_last_pwd_change=kdb_ldap_dbe_update_last_pwd_change \
+	-Dkrb5_dbe_update_mod_princ_data=kdb_ldap_dbe_update_mod_princ_data \
+	-Dkrb5_dbe_update_tl_data=kdb_ldap_dbe_update_tl_data
+DEFS=
+
+LOCALINCLUDES = -I$(SRCTOP)/lib/kdb -I$(SRCTOP)/lib/krb5/asn.1
+
+LIBBASE=kdb_ldap
+LIBMAJOR=1
+LIBMINOR=0
+RELDIR=../plugins/kdb/ldap/libkdb_ldap
+# Depends on libk5crypto and libkrb5
+# Also on gssrpc, for xdr stuff.
+SHLIB_EXPDEPS = \
+	$(GSSRPC_DEPLIBS) \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(SUPPORT_DEPLIB) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) @LDAP_LIBS@ $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+LIBINITFUNC= kldap_init_fn
+LIBFINIFUNC=
+
+SRCS= 	$(srcdir)/kdb_ldap.c \
+	$(srcdir)/kdb_ldap_conn.c \
+	$(srcdir)/ldap_realm.c \
+	$(srcdir)/ldap_create.c \
+	$(srcdir)/ldap_krbcontainer.c \
+	$(srcdir)/ldap_principal.c \
+	$(srcdir)/ldap_principal2.c \
+	$(srcdir)/ldap_pwd_policy.c \
+	$(srcdir)/ldap_misc.c \
+	$(srcdir)/ldap_handle.c \
+	$(srcdir)/ldap_tkt_policy.c \
+	$(srcdir)/ldap_services.c \
+	$(srcdir)/ldap_service_rights.c \
+	$(srcdir)/princ_xdr.c \
+	$(srcdir)/ldap_fetch_mkey.c \
+	$(srcdir)/ldap_service_stash.c \
+	$(srcdir)/kdb_xdr.c \
+	$(srcdir)/ldap_err.c
+
+STOBJLISTS=OBJS.ST
+STLIBOBJS= kdb_ldap.o \
+	kdb_ldap_conn.o \
+	ldap_realm.o \
+	ldap_create.o \
+	ldap_krbcontainer.o \
+	ldap_principal.o \
+	ldap_principal2.o \
+	ldap_pwd_policy.o \
+	ldap_misc.o \
+	ldap_handle.o \
+	ldap_tkt_policy.o \
+	ldap_services.o \
+	ldap_service_rights.o \
+	princ_xdr.o \
+	ldap_fetch_mkey.o \
+	ldap_service_stash.o \
+	kdb_xdr.o \
+	ldap_err.o
+
+all-unix:: all-liblinks
+install-unix:: install-libs
+clean-unix:: clean-liblinks clean-libobjs clean-libs
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+kdb_ldap.so kdb_ldap.po $(OUTPRE)kdb_ldap.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.c kdb_ldap.h ldap_err.h ldap_krbcontainer.h \
+  ldap_misc.h ldap_realm.h ldap_services.h
+kdb_ldap_conn.so kdb_ldap_conn.po $(OUTPRE)kdb_ldap_conn.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h kdb_ldap_conn.c ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_realm.h ldap_service_stash.h \
+  ldap_services.h
+ldap_realm.so ldap_realm.po $(OUTPRE)ldap_realm.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_principal.h ldap_realm.c \
+  ldap_realm.h ldap_services.h ldap_tkt_policy.h
+ldap_create.so ldap_create.po $(OUTPRE)ldap_create.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_create.c ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_principal.h ldap_realm.h \
+  ldap_services.h ldap_tkt_policy.h
+ldap_krbcontainer.so ldap_krbcontainer.po $(OUTPRE)ldap_krbcontainer.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.c \
+  ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h \
+  ldap_services.h
+ldap_principal.so ldap_principal.po $(OUTPRE)ldap_principal.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_principal.c ldap_principal.h \
+  ldap_realm.h ldap_services.h ldap_tkt_policy.h princ_xdr.h
+ldap_principal2.so ldap_principal2.po $(OUTPRE)ldap_principal2.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_principal.h ldap_principal2.c \
+  ldap_pwd_policy.h ldap_realm.h ldap_services.h ldap_tkt_policy.h \
+  princ_xdr.h
+ldap_pwd_policy.so ldap_pwd_policy.po $(OUTPRE)ldap_pwd_policy.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_pwd_policy.c ldap_pwd_policy.h \
+  ldap_realm.h ldap_services.h
+ldap_misc.so ldap_misc.po $(OUTPRE)ldap_misc.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_krbcontainer.h ldap_misc.c \
+  ldap_misc.h ldap_realm.h ldap_services.h
+ldap_handle.so ldap_handle.po $(OUTPRE)ldap_handle.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_handle.c ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_realm.h ldap_services.h
+ldap_tkt_policy.so ldap_tkt_policy.po $(OUTPRE)ldap_tkt_policy.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_realm.h ldap_services.h \
+  ldap_tkt_policy.c ldap_tkt_policy.h
+ldap_services.so ldap_services.po $(OUTPRE)ldap_services.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_realm.h ldap_services.c \
+  ldap_services.h
+ldap_service_rights.so ldap_service_rights.po $(OUTPRE)ldap_service_rights.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_realm.h ldap_service_rights.c \
+  ldap_services.h
+princ_xdr.so princ_xdr.po $(OUTPRE)princ_xdr.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/gssrpc/auth.h $(SRCTOP)/include/gssrpc/auth_gss.h \
+  $(SRCTOP)/include/gssrpc/auth_unix.h $(SRCTOP)/include/gssrpc/clnt.h \
+  $(SRCTOP)/include/gssrpc/rename.h $(SRCTOP)/include/gssrpc/rpc.h \
+  $(SRCTOP)/include/gssrpc/rpc_msg.h $(SRCTOP)/include/gssrpc/svc.h \
+  $(SRCTOP)/include/gssrpc/svc_auth.h $(SRCTOP)/include/gssrpc/xdr.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_krbcontainer.h ldap_principal.h ldap_realm.h \
+  ldap_tkt_policy.h princ_xdr.c princ_xdr.h
+ldap_fetch_mkey.so ldap_fetch_mkey.po $(OUTPRE)ldap_fetch_mkey.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_fetch_mkey.c ldap_handle.h ldap_krbcontainer.h \
+  ldap_main.h ldap_misc.h ldap_realm.h ldap_services.h
+ldap_service_stash.so ldap_service_stash.po $(OUTPRE)ldap_service_stash.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/kdb/kdb5.h \
+  kdb_ldap.h ldap_handle.h ldap_krbcontainer.h ldap_main.h \
+  ldap_misc.h ldap_realm.h ldap_service_stash.c ldap_service_stash.h \
+  ldap_services.h
+kdb_xdr.so kdb_xdr.po $(OUTPRE)kdb_xdr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h kdb_xdr.c kdb_xdr.h
+ldap_err.so ldap_err.po $(OUTPRE)ldap_err.$(OBJEXT): \
+  $(BUILDTOP)/include/kdb5_err.h $(COM_ERR_DEPS) ldap_err.c \
+  ldap_err.h
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/configure.in b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/configure.in
new file mode 100644
index 000000000..aee691607
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/configure.in
@@ -0,0 +1,36 @@
+K5_AC_INIT(configure.in)
+CONFIG_RULES
+AC_CHECK_HEADERS(unistd.h)
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+
+AC_CHECK_FUNCS(srand48 srand srandom umask)
+
+LDAP_OKAY=1
+AC_CHECK_HEADERS([ldap.h], :, [LDAP_OKAY=0; AC_MSG_WARN([ldap.h not found])])
+AC_CHECK_HEADERS([lber.h], :, [LDAP_OKAY=0; AC_MSG_WARN([lber.h not found])])
+AC_CHECK_LIB(ldap, ldap_init, :, [LDAP_OKAY=0; AC_MSG_WARN([libldap not found])])
+if test "$LDAP_OKAY" = "0"; then 
+    AC_ERROR("LDAP libraries missing - skipping LDAP database module")
+fi
+BER_OKAY=0
+AC_CHECK_LIB(ldap, ber_init, [BER_OKAY=1])
+if test "$BER_OKAY" = "1"; then 
+	LDAP_LIBS='-lldap'
+else
+	AC_CHECK_LIB(lber, ber_init, [BER_OKAY=1], [AC_MSG_WARN([libber not found])])
+	if test "$BER_OKAY" = "1"; then 
+		LDAP_LIBS='-lldap -llber'
+	else
+		AC_ERROR("BER library missing - skipping LDAP database module")
+	fi
+fi
+AC_SUBST(LDAP_LIBS)
+
+KRB5_RUN_FLAGS
+dnl The following is for check...
+KRB5_BUILD_PROGRAM
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+dnl
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
new file mode 100644
index 000000000..40bde9e21
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
@@ -0,0 +1,502 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_ldap.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "autoconf.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <ctype.h>
+#include "kdb_ldap.h"
+#include "ldap_misc.h"
+#include <kdb5.h>
+#include <kadm5/admin.h>
+
+krb5_error_code
+krb5_ldap_get_db_opt(char *input, char **opt, char **val)
+{
+    char *pos = strchr(input, '=');
+
+    *val = NULL;
+    if (pos == NULL) {
+	*opt = strdup(input);
+	if (*opt == NULL) {
+	    return ENOMEM;
+	}
+    } else {
+	int len = pos - input;
+	*opt = malloc((unsigned) len + 1);
+	if (!*opt) {
+	    return ENOMEM;
+	}
+	memcpy(*opt, input, (unsigned) len);
+	/* ignore trailing blanks */
+	while (isblank((*opt)[len-1]))
+	    --len;
+	(*opt)[len] = '\0';
+
+	pos += 1; /* move past '=' */
+	while (isblank(*pos))  /* ignore leading blanks */
+	    pos += 1;
+	if (*pos != '\0') {
+	    *val = strdup (pos);
+	    if (!*val) {
+		free (*opt);
+		return ENOMEM;
+	    }
+	}
+    }
+    return (0);
+
+}
+
+
+/*
+ * ldap get age
+ */
+krb5_error_code
+krb5_ldap_db_get_age(context, db_name, age)
+    krb5_context context;
+    char *db_name;
+    time_t *age;
+{
+    time (age);
+    return 0;
+}
+
+/*
+ * read startup information - kerberos and realm container
+ */
+krb5_error_code
+krb5_ldap_read_startup_information(krb5_context context)
+{
+    krb5_error_code      retval = 0;
+    kdb5_dal_handle      *dal_handle=NULL;
+    krb5_ldap_context    *ldap_context=NULL;
+    int                  mask = 0;
+                                                                                                                             
+    SETUP_CONTEXT();
+    if ((retval=krb5_ldap_read_krbcontainer_params(context, &(ldap_context->krbcontainer)))) {
+	prepend_err_str (context, "Unable to read Kerberos container", retval, retval);
+	goto cleanup;
+    }
+
+    if ((retval=krb5_ldap_read_realm_params(context, context->default_realm, &(ldap_context->lrparams), &mask))) {
+	prepend_err_str (context, "Unable to read Realm", retval, retval);
+	goto cleanup;
+    }
+
+    if (((mask & LDAP_REALM_MAXTICKETLIFE) == 0) || ((mask & LDAP_REALM_MAXRENEWLIFE) == 0)
+                                                 || ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0)) {
+        kadm5_config_params  params_in, params_out;
+
+        memset((char *) ¶ms_in, 0, sizeof(params_in));
+        memset((char *) ¶ms_out, 0, sizeof(params_out));
+
+        retval = kadm5_get_config_params(context, 1, ¶ms_in, ¶ms_out);
+        if (retval) {
+            if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
+                ldap_context->lrparams->max_life = 24 * 60 * 60; /* 1 day */
+            }
+            if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
+                ldap_context->lrparams->max_renewable_life = 0;
+            }
+            if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
+                ldap_context->lrparams->tktflags = KRB5_KDB_DEF_FLAGS;
+            }
+            retval = 0;
+            goto cleanup;
+        }
+
+        if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
+            if (params_out.mask & KADM5_CONFIG_MAX_LIFE)
+                ldap_context->lrparams->max_life = params_out.max_life;
+        }
+
+        if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
+            if (params_out.mask & KADM5_CONFIG_MAX_RLIFE)
+                ldap_context->lrparams->max_renewable_life = params_out.max_rlife;
+        }
+
+        if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
+            if (params_out.mask & KADM5_CONFIG_FLAGS)
+                ldap_context->lrparams->tktflags = params_out.flags;
+        }
+
+        kadm5_free_config_params(context, ¶ms_out);
+    }
+
+cleanup:
+    return retval;
+}
+
+
+/* Function to check if a LDAP server supports the SASL external mechanism
+ *Return values:
+ *   0 => supports
+ *   1 => does not support
+ *   2 => don't know
+ */
+#define ERR_MSG1 "Unable to check if SASL EXTERNAL mechanism is supported by LDAP server. Proceeding anyway ..."
+#define ERR_MSG2 "SASL EXTERNAL mechanism not supported by LDAP server. Can't perform certificate-based bind."
+
+int
+has_sasl_external_mech(context, ldap_server)
+    krb5_context     context;
+    char             *ldap_server;
+{
+    int               i=0, flag=0, ret=0, retval=0;
+    char              *attrs[]={"supportedSASLMechanisms", NULL}, **values=NULL;
+    LDAP              *ld=NULL;
+    LDAPMessage       *msg=NULL, *res=NULL;
+
+    retval = ldap_initialize(&ld, ldap_server);
+    if (retval != LDAP_SUCCESS) {
+	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+	ret = 2; /* Don't know */
+	goto cleanup;
+    }
+
+    /* Anonymous bind */
+    retval = ldap_sasl_bind_s(ld, NULL, NULL, NULL, NULL, NULL, NULL);
+    if (retval != LDAP_SUCCESS) {
+	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+	ret = 2; /* Don't know */
+	goto cleanup;
+    }
+
+    retval = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, NULL, NULL, NULL, 0, &res);
+    if (retval != LDAP_SUCCESS) {
+	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+	ret = 2; /* Don't know */
+	goto cleanup;
+    }
+
+    msg = ldap_first_message(ld, res);
+    if (msg == NULL) {
+	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+	ret = 2; /* Don't know */
+	goto cleanup;
+    }
+
+    values = ldap_get_values(ld, msg, "supportedSASLMechanisms");
+    if (values == NULL) {
+	krb5_set_error_message(context, 1, "%s", ERR_MSG2);
+	ret = 1; /* Not supported */
+	goto cleanup;
+    }
+
+    for (i = 0; values[i] != NULL; i++) {
+	if (strcmp(values[i], "EXTERNAL"))
+	    continue;
+	flag = 1;
+    }
+
+    if (flag != 1) {
+	krb5_set_error_message(context, 1, "%s", ERR_MSG2);
+	ret = 1; /* Not supported */
+	goto cleanup;
+    }
+
+cleanup:
+
+    if (values != NULL)
+	ldap_value_free(values);
+
+    if (res != NULL)
+	ldap_msgfree(res);
+
+    if (ld != NULL)
+	ldap_unbind_ext_s(ld, NULL, NULL);
+
+    return ret;
+}
+
+void * krb5_ldap_alloc(krb5_context context, void *ptr, size_t size)
+{
+    return realloc(ptr, size);
+}
+
+void krb5_ldap_free(krb5_context context, void *ptr)
+
+{
+    free(ptr);
+}
+
+krb5_error_code krb5_ldap_open(krb5_context context,
+			       char *conf_section,
+			       char **db_args,
+			       int mode)
+{
+    krb5_error_code status  = 0;
+    char **t_ptr = db_args;
+    krb5_ldap_context *ldap_context=NULL;
+    int srv_cnt = 0;
+    kdb5_dal_handle *dal_handle=NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    ldap_context = calloc(1, sizeof(krb5_ldap_context));
+    if (ldap_context == NULL) {
+	status = ENOMEM;
+	goto clean_n_exit;
+    }
+
+    ldap_context->kcontext = context;
+
+    while (t_ptr && *t_ptr) {
+	char *opt = NULL, *val = NULL;
+
+	if ((status = krb5_ldap_get_db_opt(*t_ptr, &opt, &val)) != 0) {
+	    goto clean_n_exit;
+	}
+	if (opt && !strcmp(opt, "binddn")) {
+	    if (ldap_context->bind_dn) {
+		free (opt);
+		free (val);
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'binddn' missing");
+		goto clean_n_exit;
+	    }
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'binddn' value missing");
+		free(opt);
+		goto clean_n_exit;
+	    }
+	    ldap_context->bind_dn = strdup(val);
+	    if (ldap_context->bind_dn == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto clean_n_exit;
+	    }
+	} else if (opt && !strcmp(opt, "nconns")) {
+	    if (ldap_context->max_server_conns) {
+		free (opt);
+		free (val);
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'nconns' missing");
+		goto clean_n_exit;
+	    }
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'nconns' value missing");
+		free(opt);
+		goto clean_n_exit;
+	    }
+	    ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER;
+	} else if (opt && !strcmp(opt, "bindpwd")) {
+	    if (ldap_context->bind_pwd) {
+		free (opt);
+		free (val);
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'bindpwd' missing");
+		goto clean_n_exit;
+	    }
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'bindpwd' value missing");
+		free(opt);
+		goto clean_n_exit;
+	    }
+	    ldap_context->bind_pwd = strdup(val);
+	    if (ldap_context->bind_pwd == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto clean_n_exit;
+	    }
+	} else if (opt && !strcmp(opt, "host")) {
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'host' value missing");
+		free(opt);
+		goto clean_n_exit;
+	    }
+	    if (ldap_context->server_info_list == NULL)
+		ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (SERV_COUNT+1, sizeof (krb5_ldap_server_info *)) ;
+
+	    if (ldap_context->server_info_list == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto clean_n_exit;
+	    }
+
+	    ldap_context->server_info_list[srv_cnt] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info));
+	    if (ldap_context->server_info_list[srv_cnt] == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto clean_n_exit;
+	    }
+
+	    ldap_context->server_info_list[srv_cnt]->server_status = NOTSET;
+
+	    ldap_context->server_info_list[srv_cnt]->server_name = strdup(val);
+	    if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto clean_n_exit;
+	    }
+
+	    srv_cnt++;
+#ifdef HAVE_EDIRECTORY
+	} else if (opt && !strcmp(opt, "cert")) {
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'cert' value missing");
+		free(opt);
+		goto clean_n_exit;
+	    }
+
+	    if (ldap_context->root_certificate_file == NULL) {
+		ldap_context->root_certificate_file = strdup(val);
+		if (ldap_context->root_certificate_file == NULL) {
+		    free (opt);
+		    free (val);
+		    status = ENOMEM;
+		    goto clean_n_exit;
+		}
+	    } else {
+		void *tmp=NULL;
+		char *oldstr = NULL;
+		unsigned int len=0;
+
+		oldstr = strdup(ldap_context->root_certificate_file);
+		if (oldstr == NULL) {
+		    free (opt);
+		    free (val);
+		    status = ENOMEM;
+		    goto clean_n_exit;
+		}
+
+		tmp = ldap_context->root_certificate_file;
+		len = strlen(ldap_context->root_certificate_file) + 2 + strlen(val);
+		ldap_context->root_certificate_file = realloc(ldap_context->root_certificate_file,
+							      len);
+		if (ldap_context->root_certificate_file == NULL) {
+		    free (tmp);
+		    free (opt);
+		    free (val);
+		    status = ENOMEM;
+		    goto clean_n_exit;
+		}
+		memset(ldap_context->root_certificate_file, 0, len);
+		sprintf(ldap_context->root_certificate_file,"%s %s", oldstr, val);
+		free (oldstr);
+	    }
+#endif
+	} else {
+	    /* ignore hash argument. Might have been passed from create */
+	    status = EINVAL;
+	    if (opt && !strcmp(opt, "temporary")) {
+		/* 
+		 * temporary is passed in when kdb5_util load without -update is done.
+		 * This is unsupported by the LDAP plugin.
+		 */
+		krb5_set_error_message (context, status,
+					"open of LDAP directory aborted, plugin requires -update argument");
+	    } else {
+		krb5_set_error_message (context, status, "unknown option \'%s\'",
+					opt?opt:val);
+	    }
+	    free(opt);
+	    free(val);
+	    goto clean_n_exit;
+	}
+
+	free(opt);
+	free(val);
+	t_ptr++;
+    }
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    dal_handle->db_context = ldap_context;
+    status = krb5_ldap_read_server_params(context, conf_section, mode & 0x0300);
+    if (status) {
+	if (ldap_context)
+	    krb5_ldap_free_ldap_context(ldap_context);
+	ldap_context = NULL;
+	dal_handle->db_context = NULL;
+	prepend_err_str (context, "Error reading LDAP server params: ", status, status);
+	goto clean_n_exit;
+    }
+    if ((status=krb5_ldap_db_init(context, ldap_context)) != 0) {
+	goto clean_n_exit;
+    }
+
+    if ((status=krb5_ldap_read_startup_information(context)) != 0) {
+	goto clean_n_exit;
+    }
+
+clean_n_exit:
+    /* may be clearing up is not required  db_fini might do it for us, check out */
+    if (status) {
+	krb5_ldap_close(context);
+    }
+    return status;
+}
+
+#include "ldap_err.h"
+int
+set_ldap_error (krb5_context ctx, int st, int op)
+{
+    int translated_st = translate_ldap_error(st, op);
+    krb5_set_error_message(ctx, translated_st, "%s", ldap_err2string(st));
+    return translated_st;
+}
+
+void
+prepend_err_str (krb5_context ctx, const char *str, krb5_error_code err,
+		 krb5_error_code oerr)
+{
+    const char *omsg;
+    if (oerr == 0) oerr = err;
+    omsg = krb5_get_error_message (ctx, err);
+    krb5_set_error_message (ctx, err, "%s %s", str, omsg);
+}
+
+extern krb5int_access accessor;
+MAKE_INIT_FUNCTION(kldap_init_fn);
+
+int kldap_init_fn(void)
+{
+    /* Global (per-module) initialization.  */
+    return krb5int_accessor (&accessor, KRB5INT_ACCESS_VERSION);
+}
+
+int kldap_ensure_initialized(void)
+{
+    return CALL_INIT_FUNCTION (kldap_init_fn);
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
new file mode 100644
index 000000000..b1ffd8497
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
@@ -0,0 +1,322 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_ldap.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* */
+#ifndef _KDB_LDAP_H
+#define _KDB_LDAP_H 1
+
+/* We want the interfaces marked "deprecated" in OpenLDAP.  */
+#define LDAP_DEPRECATED 1
+#include <ldap.h>
+
+/* Check for acceptable versions.
+
+   OpenLDAP version 2.2.6 is known to have some kind of problem that
+   is tickled by the use of multiple handles in this code.  Version
+   2.2.19 in Mac OS 10.4.7 seems to be buggy as well.  Version 2.2.24
+   doesn't have this problem.  Other in-between versions have not been
+   tested.  */
+#ifndef BUILD_WITH_BROKEN_LDAP
+# if defined(LDAP_API_FEATURE_X_OPENLDAP)
+#  if LDAP_VENDOR_VERSION < 20224
+#   error This code triggers bugs in old OpenLDAP implementations.  Please update to 2.2.24 or later.
+#  endif
+# endif
+#endif /* BUILD_WITH_BROKEN_LDAP */
+
+#include <k5-thread.h>
+#include <kdb5.h>
+#include "k5-int.h"
+#include "ldap_krbcontainer.h"
+#include "ldap_realm.h"
+
+extern struct timeval timelimit;
+
+#define  SERV_COUNT                  100
+#define  DEFAULT_CONNS_PER_SERVER    5
+#define  REALM_READ_REFRESH_INTERVAL (5 * 60)
+
+#ifdef HAVE_EDIRECTORY
+#define  SECURITY_CONTAINER "cn=Security"
+#define  KERBEROS_CONTAINER "cn=Kerberos,cn=Security"
+#endif
+
+#if !defined(LDAP_OPT_RESULT_CODE) && defined(LDAP_OPT_ERROR_NUMBER)
+#define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER
+#endif
+
+#define NEG(val)   (val <0) ? abs(val) : -val ;
+#define MAXINTLEN  10
+
+#define IGNORE_STATUS              0
+#define CHECK_STATUS               1
+
+#define SETUP_CONTEXT() if (context == NULL || context->db_context == NULL \
+            || ((kdb5_dal_handle *)context->db_context)->db_context == NULL) { \
+        return EINVAL; \
+    } \
+    dal_handle = (kdb5_dal_handle *)context->db_context; \
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context; \
+    if (ldap_context == NULL || ldap_context->server_info_list == NULL) \
+        return KRB5_KDB_DBNOTINITED;
+
+#define GET_HANDLE()  ld = NULL; \
+    st = krb5_ldap_request_handle_from_pool(ldap_context, &ldap_server_handle); \
+    if (st != 0) { \
+        prepend_err_str(context, "LDAP handle unavailable: ", KRB5_KDB_ACCESS_ERROR, st); \
+        st = KRB5_KDB_ACCESS_ERROR; \
+        goto cleanup; \
+    } \
+    ld = ldap_server_handle->ldap_handle;
+
+extern int set_ldap_error (krb5_context ctx, int st, int op);
+extern void prepend_err_str (krb5_context ctx, const char *s, krb5_error_code err, krb5_error_code oerr);
+
+#define LDAP_SEARCH(base, scope, filter, attrs)   LDAP_SEARCH_1(base, scope, filter, attrs, CHECK_STATUS)
+
+#define LDAP_SEARCH_1(base, scope, filter, attrs, status_check)        \
+      do { \
+	  st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, NULL, &timelimit, LDAP_NO_LIMIT, &result); \
+	  if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \
+              tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \
+	      if (ldap_server_handle) \
+		  ld = ldap_server_handle->ldap_handle; \
+	  } \
+      }while (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR && tempst == 0); \
+      \
+      if (status_check != IGNORE_STATUS) { \
+        if (tempst != 0) { \
+            prepend_err_str(context, "LDAP handle unavailable: ", KRB5_KDB_ACCESS_ERROR, st); \
+            st = KRB5_KDB_ACCESS_ERROR; \
+            goto cleanup; \
+        } \
+        if (st != LDAP_SUCCESS) { \
+	     st = set_ldap_error(context, st, OP_SEARCH); \
+	     goto cleanup; \
+        } \
+      }
+
+
+#define CHECK_CLASS_VALIDITY(st, mask, str) \
+	if (st != 0 || mask == 0) { \
+	    if (st == 0 && mask == 0) { \
+	       st = set_ldap_error(context, LDAP_OBJECT_CLASS_VIOLATION, OP_SEARCH); \
+	    } \
+	    prepend_err_str(context, str, st, st); \
+	    goto cleanup; \
+	 }
+
+#define CHECK_NULL(ptr) if (ptr == NULL) { \
+                            st = ENOMEM; \
+                            goto cleanup; \
+                        }
+
+#define  STORE16_INT(ptr, val)	store_16_be(val, ptr)
+#define  STORE32_INT(ptr, val)  store_32_be(val, ptr)
+#define UNSTORE16_INT(ptr, val) (val = load_16_be(ptr))
+#define UNSTORE32_INT(ptr, val) (val = load_32_be(ptr))
+
+#define KRB5_CONF_KDC_BIND_DN "ldap_kdc_dn"
+#define KRB5_CONF_ADMIN_BIND_DN "ldap_kadmind_dn"
+#define KRB5_CONF_PWD_BIND_DN "ldap_passwd_dn"
+
+#define  KDB_TL_USER_INFO      0x7ffe
+
+#define KDB_TL_PRINCTYPE          0x01
+#define KDB_TL_PRINCCOUNT         0x02
+#define KDB_TL_USERDN             0x03
+#define KDB_TL_KEYINFO            0x04
+#define KDB_TL_MASK               0x05
+#define KDB_TL_CONTAINERDN        0x06
+#define KDB_TL_LINKDN             0x07
+
+
+#define CHECK_LDAP_HANDLE(lcontext)     if (!(ldap_context \
+					      && ldap_context->server_info_list)) { \
+					  return KRB5_KDB_DBNOTINITED; \
+					}
+     
+#define HNDL_LOCK(lcontext) k5_mutex_lock(&lcontext->hndl_lock)
+#define HNDL_UNLOCK(lcontext) k5_mutex_unlock(&lcontext->hndl_lock)
+
+/* To be used later */
+typedef struct _krb5_ldap_certificates{
+    char *certificate;
+    int  certtype;
+}krb5_ldap_certificates;
+
+/* ldap server info structure */
+
+typedef enum _server_type {PRIMARY, SECONDARY} krb5_ldap_server_type;
+
+typedef enum _server_status {OFF, ON, NOTSET} krb5_ldap_server_status;
+
+typedef struct _krb5_ldap_server_info krb5_ldap_server_info;
+
+typedef struct  _krb5_ldap_server_handle {
+    int                              msgid;
+    LDAP                             *ldap_handle;
+    krb5_boolean                     server_info_update_pending;
+    krb5_ldap_server_info            *server_info;
+    struct _krb5_ldap_server_handle  *next;
+} krb5_ldap_server_handle;
+
+struct _krb5_ldap_server_info {
+    krb5_ldap_server_type	 server_type;
+    krb5_ldap_server_status      server_status;
+    krb5_ui_4                    num_conns;
+    krb5_ldap_server_handle      *ldap_server_handles;
+    time_t                       downtime;
+    char			*server_name;
+#ifdef HAVE_EDIRECTORY
+    char			*root_certificate_file;
+#endif
+    struct _krb5_ldap_server_info *next;
+};
+
+
+/* ldap server structure */
+
+typedef enum {SERVICE_DN_TYPE_SERVER, SERVICE_DN_TYPE_CLIENT} krb5_ldap_servicetype; 
+
+typedef struct _krb5_ldap_context {
+  krb5_ldap_servicetype         service_type;
+  krb5_ldap_server_info         **server_info_list;
+  krb5_ui_4                     max_server_conns;
+  char                          *conf_section;
+  char 		                *bind_dn;
+  char                          *bind_pwd;
+  char 		                *service_password_file;
+  char 		                *root_certificate_file;
+  char                          *service_cert_path;
+  char                          *service_cert_pass;
+  krb5_ldap_certificates        **certificates;
+  krb5_ui_4                     cert_count; /* certificate count */
+  k5_mutex_t                    hndl_lock;
+  krb5_ldap_krbcontainer_params *krbcontainer;
+  krb5_ldap_realm_params        *lrparams;
+  krb5_context                  kcontext;   /* to set the error code and message */
+} krb5_ldap_context;
+
+
+typedef struct {
+  int           nkey;
+  struct berval **keys;
+}KEY;
+
+#define k5ldap_inited(c) (c && c->db_context \
+                         && ((kdb5_dal_handle*)c->db_context)->db_context \
+                         && ((krb5_ldap_context *) ((kdb5_dal_handle*)c->db_context)->db_context))
+
+
+/* misc functions */
+
+krb5_error_code
+krb5_ldap_db_init(krb5_context, krb5_ldap_context *);
+
+krb5_error_code
+krb5_ldap_db_single_init(krb5_ldap_context *);
+
+krb5_error_code
+krb5_ldap_rebind(krb5_ldap_context *, krb5_ldap_server_handle **);
+
+krb5_error_code
+krb5_ldap_db_get_age(krb5_context, char *, time_t *);
+
+krb5_error_code 
+krb5_ldap_lib_init(void);
+
+krb5_error_code 
+krb5_ldap_lib_cleanup(void);
+
+void * 
+krb5_ldap_alloc( krb5_context kcontext,  void *ptr, size_t size );
+
+void 
+krb5_ldap_free( krb5_context kcontext, void *ptr );
+krb5_error_code
+krb5_ldap_get_mkey(krb5_context, krb5_keyblock **);
+
+krb5_error_code
+krb5_ldap_set_mkey(krb5_context, char *, krb5_keyblock *);
+
+krb5_error_code
+krb5_ldap_create(krb5_context , char *, char **);
+
+krb5_error_code 
+krb5_ldap_open( krb5_context , char *,
+		char **db_args,
+		int mode );
+krb5_error_code 
+krb5_ldap_close( krb5_context );
+
+krb5_error_code
+krb5_ldap_free_ldap_context(krb5_ldap_context *);
+
+krb5_error_code
+krb5_ldap_read_startup_information(krb5_context );
+
+int
+has_sasl_external_mech(krb5_context, char *);
+
+/* DAL functions */
+
+
+krb5_error_code
+krb5_ldap_set_option( krb5_context, int, void * );
+
+krb5_error_code
+krb5_ldap_lock( krb5_context, int );
+
+krb5_error_code
+krb5_ldap_unlock( krb5_context );
+
+krb5_error_code
+krb5_ldap_supported_realms( krb5_context, char ** );
+
+krb5_error_code
+krb5_ldap_free_supported_realms( krb5_context, char ** );
+
+const char *
+krb5_ldap_errcode_2_string( krb5_context, long );
+
+void
+krb5_ldap_release_errcode_string (krb5_context, const char *);
+
+#ifndef HAVE_LDAP_INITIALIZE
+int
+ldap_initialize(LDAP **, char *);
+#endif
+#ifndef HAVE_LDAP_UNBIND_EXT_S
+int
+ldap_unbind_ext_s(LDAP *, LDAPControl **, LDAPControl **);
+#endif
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
new file mode 100644
index 000000000..343705efc
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
@@ -0,0 +1,352 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_ldap_conn.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "autoconf.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ldap_main.h"
+#include "ldap_service_stash.h"
+#include <kdb5.h>
+
+static krb5_error_code
+krb5_validate_ldap_context(krb5_context context, krb5_ldap_context *ldap_context)
+{
+    krb5_error_code             st=0;
+    unsigned char               *password=NULL;
+
+    if (ldap_context->bind_dn == NULL) {
+	st = EINVAL;
+	krb5_set_error_message(context, st, "LDAP bind dn value missing ");
+	goto err_out;
+    }
+
+    if (ldap_context->bind_pwd == NULL && ldap_context->service_password_file == NULL) {
+	st = EINVAL;
+	krb5_set_error_message(context, st, "LDAP bind password value missing ");
+	goto err_out;
+    }
+
+    if (ldap_context->bind_pwd == NULL && ldap_context->service_password_file !=
+	NULL && ldap_context->service_cert_path == NULL) {
+	if ((st=krb5_ldap_readpassword(context, ldap_context, &password)) != 0) {
+	    prepend_err_str(context, "Error reading password from stash: ", st, st);
+	    goto err_out;
+	}
+
+	/* Check if the returned 'password' is actually the path of a certificate */
+	if (!strncmp("{FILE}", (char *)password, 6)) {
+	    /* 'password' format: <path>\0<password> */
+	    ldap_context->service_cert_path = strdup((char *)password + strlen("{FILE}"));
+	    if (password[strlen((char *)password) + 1] == '\0')
+		ldap_context->service_cert_pass = NULL;
+	    else
+		ldap_context->service_cert_pass = strdup((char *)password +
+							 strlen((char *)password) + 1);
+	    free(password);
+	} else {
+	    ldap_context->bind_pwd = (char *)password;
+	    if (ldap_context->bind_pwd == NULL) {
+		st = EINVAL;
+		krb5_set_error_message(context, st, "Error reading password from stash");
+		goto err_out;
+	    }
+	}
+    }
+
+    /* NULL password not allowed */
+    if (ldap_context->bind_pwd != NULL && strlen(ldap_context->bind_pwd) == 0) {
+	st = EINVAL;
+	krb5_set_error_message(context, st, "Service password length is zero");
+	goto err_out;
+    }
+
+err_out:
+    return st;
+}
+
+/*
+ * Internal Functions called by init functions.
+ */
+
+static krb5_error_code
+krb5_ldap_bind(ldap_context, ldap_server_handle)
+    krb5_ldap_context           *ldap_context;
+    krb5_ldap_server_handle     *ldap_server_handle;
+{
+    krb5_error_code             st=0;
+    struct berval               bv={0, NULL}, *servercreds=NULL;
+
+    if (ldap_context->service_cert_path != NULL) {
+	/* Certificate based bind (SASL EXTERNAL mechanism) */
+
+	st = ldap_sasl_bind_s(ldap_server_handle->ldap_handle,
+			      NULL,	   /* Authenticating dn */
+			      "EXTERNAL",  /* Method used for authentication */
+			      &bv,
+			      NULL,
+			      NULL,
+			      &servercreds);
+
+	if (st == LDAP_SASL_BIND_IN_PROGRESS) {
+	    st = ldap_sasl_bind_s(ldap_server_handle->ldap_handle,
+				  NULL,
+				  "EXTERNAL",
+				  servercreds,
+				  NULL,
+				  NULL,
+				  &servercreds);
+	}
+    } else {
+	/* password based simple bind */
+        bv.bv_val = ldap_context->bind_pwd;
+        bv.bv_len = strlen(ldap_context->bind_pwd);
+        st = ldap_sasl_bind_s(ldap_server_handle->ldap_handle, 
+                                ldap_context->bind_dn,
+                                NULL, &bv, NULL, 
+                                NULL, NULL);
+    }
+    return st;
+}
+
+static krb5_error_code
+krb5_ldap_initialize(ldap_context, server_info)
+    krb5_ldap_context *ldap_context;
+    krb5_ldap_server_info *server_info;
+{
+    krb5_error_code             st=0;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+
+    ldap_server_handle = calloc(1, sizeof(krb5_ldap_server_handle));
+    if (ldap_server_handle == NULL) {
+	st = ENOMEM;
+	goto err_out;
+    }
+
+    /* ldap init */
+    if ((st = ldap_initialize(&ldap_server_handle->ldap_handle, server_info->server_name)) != 0) {
+	if (ldap_context->kcontext)
+	    krb5_set_error_message (ldap_context->kcontext, KRB5_KDB_ACCESS_ERROR, "%s",
+				    ldap_err2string(st));
+	st = KRB5_KDB_ACCESS_ERROR;
+	goto err_out;
+    }
+
+    if ((st=krb5_ldap_bind(ldap_context, ldap_server_handle)) == 0) {
+	ldap_server_handle->server_info_update_pending = FALSE;
+	server_info->server_status = ON;
+	krb5_update_ldap_handle(ldap_server_handle, server_info);
+    } else {
+	if (ldap_context->kcontext)
+	    krb5_set_error_message (ldap_context->kcontext,
+				    KRB5_KDB_ACCESS_ERROR, "%s",
+				    ldap_err2string(st));
+	st = KRB5_KDB_ACCESS_ERROR;
+	server_info->server_status = OFF;
+	time(&server_info->downtime);
+	/* ldap_unbind_s(ldap_server_handle->ldap_handle); */
+	free(ldap_server_handle);
+    }
+
+err_out:
+    return st;
+}
+
+/*
+ * initialization for data base routines.
+ */
+
+krb5_error_code
+krb5_ldap_db_init(krb5_context context, krb5_ldap_context *ldap_context)
+{
+    krb5_error_code             st=0;
+    krb5_boolean                sasl_mech_supported=TRUE;
+    int                         cnt=0, version=LDAP_VERSION3;
+    struct timeval              local_timelimit = {10,0};
+
+    if ((st=krb5_validate_ldap_context(context, ldap_context)) != 0)
+	goto err_out;
+
+    ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &version);
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+    ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &local_timelimit);
+#elif defined LDAP_X_OPT_CONNECT_TIMEOUT
+    ldap_set_option(NULL, LDAP_X_OPT_CONNECT_TIMEOUT, &local_timelimit);
+#endif
+
+    HNDL_LOCK(ldap_context);
+    while (ldap_context->server_info_list[cnt] != NULL) {
+	krb5_ldap_server_info *server_info=NULL;
+
+	server_info = ldap_context->server_info_list[cnt];
+
+	if (server_info->server_status == NOTSET) {
+	    int conns=0;
+
+	    /*
+	     * Check if the server has to perform certificate-based authentication
+	     */
+	    if (ldap_context->service_cert_path != NULL) {
+		/* Find out if the server supports SASL EXTERNAL mechanism */
+		if (has_sasl_external_mech(context, server_info->server_name) == 1) {
+		    cnt++;
+		    sasl_mech_supported = FALSE;
+		    continue; /* Check the next LDAP server */
+		}
+		sasl_mech_supported = TRUE;
+	    }
+
+	    krb5_clear_error_message(context);
+
+	    for (conns=0; conns < ldap_context->max_server_conns; ++conns) {
+		if ((st=krb5_ldap_initialize(ldap_context, server_info)) != 0)
+		    break;
+	    } /* for (conn= ... */
+
+	    if (server_info->server_status == ON)
+		break;  /* server init successful, so break */
+	}
+	++cnt;
+    }
+    HNDL_UNLOCK(ldap_context);
+
+err_out:
+    if (sasl_mech_supported == FALSE) {
+	st = KRB5_KDB_ACCESS_ERROR;
+	krb5_set_error_message (context, st,
+				"Certificate based authentication requested but "
+				"not supported by LDAP servers");
+    }
+    return (st);
+}
+
+
+/*
+ * get a single handle. Do not lock the mutex
+ */
+
+krb5_error_code
+krb5_ldap_db_single_init(krb5_ldap_context *ldap_context)
+{
+    krb5_error_code             st=0;
+    int                         cnt=0;
+    krb5_ldap_server_info       *server_info=NULL;
+
+    while (ldap_context->server_info_list[cnt] != NULL) {
+	server_info = ldap_context->server_info_list[cnt];
+	if ((server_info->server_status == NOTSET || server_info->server_status == ON)) {
+	    if (server_info->num_conns < ldap_context->max_server_conns-1) {
+		st = krb5_ldap_initialize(ldap_context, server_info);
+		if (st == LDAP_SUCCESS)
+		    goto cleanup;
+	    }
+	}
+	++cnt;
+    }
+
+    /* If we are here, try to connect to all the servers */
+
+    cnt = 0;
+    while (ldap_context->server_info_list[cnt] != NULL) {
+	server_info = ldap_context->server_info_list[cnt];
+	st = krb5_ldap_initialize(ldap_context, server_info);
+	if (st == LDAP_SUCCESS)
+	    goto cleanup;
+	++cnt;
+    }
+cleanup:
+    return (st);
+}
+
+krb5_error_code
+krb5_ldap_rebind(ldap_context, ldap_server_handle)
+    krb5_ldap_context           *ldap_context;
+    krb5_ldap_server_handle     **ldap_server_handle;
+{
+    krb5_ldap_server_handle     *handle = *ldap_server_handle;
+
+    if ((ldap_initialize(&handle->ldap_handle, handle->server_info->server_name) != LDAP_SUCCESS)
+	|| (krb5_ldap_bind(ldap_context, handle) != LDAP_SUCCESS))
+	return krb5_ldap_request_next_handle_from_pool(ldap_context, ldap_server_handle);
+    return LDAP_SUCCESS;
+}
+
+/*
+ *     DAL API functions
+ */
+krb5_error_code krb5_ldap_lib_init()
+{
+    return 0;
+}
+
+krb5_error_code krb5_ldap_lib_cleanup()
+{
+    /* right now, no cleanup required */
+    return 0;
+}
+
+krb5_error_code
+krb5_ldap_free_ldap_context(krb5_ldap_context *ldap_context)
+{
+    if (ldap_context == NULL)
+	return 0;
+
+    krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+    ldap_context->krbcontainer = NULL;
+
+    krb5_ldap_free_realm_params(ldap_context->lrparams);
+    ldap_context->lrparams = NULL;
+
+    krb5_ldap_free_server_params(ldap_context);
+
+    return 0;
+}
+
+krb5_error_code
+krb5_ldap_close(krb5_context context)
+{
+    kdb5_dal_handle  *dal_handle=NULL;
+    krb5_ldap_context *ldap_context=NULL;
+
+    if (context == NULL ||
+	context->db_context == NULL ||
+	((kdb5_dal_handle *)context->db_context)->db_context == NULL)
+	return 0;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+    dal_handle->db_context = NULL;
+
+    krb5_ldap_free_ldap_context(ldap_context);
+
+    return 0;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c
new file mode 100644
index 000000000..d4c6ac832
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c
@@ -0,0 +1,228 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_xdr.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include <k5-int.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include "kdb_xdr.h"
+
+#define safe_realloc(p,n) ((p)?(realloc(p,n)):(malloc(n)))
+
+krb5_error_code
+krb5_dbe_update_tl_data(context, entry, new_tl_data)
+    krb5_context          context;
+    krb5_db_entry       * entry;
+    krb5_tl_data	* new_tl_data;
+{
+    krb5_tl_data        * tl_data;
+    krb5_octet          * tmp;
+
+    /* copy the new data first, so we can fail cleanly if malloc()
+       fails */
+
+    if ((tmp = (krb5_octet *) malloc(new_tl_data->tl_data_length)) == NULL)
+	return(ENOMEM);
+
+    /* Find an existing entry of the specified type and point at
+       it, or NULL if not found */
+
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next)
+	if (tl_data->tl_data_type == new_tl_data->tl_data_type)
+	    break;
+
+    /* if necessary, chain a new record in the beginning and point at it */
+
+    if (!tl_data) {
+	if ((tl_data = (krb5_tl_data *) calloc(1, sizeof(krb5_tl_data)))
+	    == NULL) {
+	    free(tmp);
+	    return(ENOMEM);
+	}
+	tl_data->tl_data_next = entry->tl_data;
+	entry->tl_data = tl_data;
+	entry->n_tl_data++;
+    }
+
+    /* fill in the record */
+
+    if (tl_data->tl_data_contents)
+	free(tl_data->tl_data_contents);
+
+    tl_data->tl_data_type = new_tl_data->tl_data_type;
+    tl_data->tl_data_length = new_tl_data->tl_data_length;
+    tl_data->tl_data_contents = tmp;
+    memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
+
+    return(0);
+}
+
+krb5_error_code
+krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
+    krb5_context          context;
+    krb5_db_entry       * entry;
+    krb5_tl_data        * ret_tl_data;
+{
+    krb5_tl_data *tl_data;
+
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
+	if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
+	    *ret_tl_data = *tl_data;
+	    return(0);
+	}
+    }
+
+    /* if the requested record isn't found, return zero bytes.
+       if it ever means something to have a zero-length tl_data,
+       this code and its callers will have to be changed */
+
+    ret_tl_data->tl_data_length = 0;
+    ret_tl_data->tl_data_contents = NULL;
+    return(0);
+}
+
+krb5_error_code
+krb5_dbe_update_last_pwd_change(context, entry, stamp)
+    krb5_context          context;
+    krb5_db_entry       * entry;
+    krb5_timestamp	  stamp;
+{
+    krb5_tl_data        tl_data;
+    krb5_octet          buf[4]; /* this is the encoded size of an int32 */
+
+    tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+    tl_data.tl_data_length = sizeof(buf);
+    krb5_kdb_encode_int32((krb5_int32) stamp, buf);
+    tl_data.tl_data_contents = buf;
+
+    return(krb5_dbe_update_tl_data(context, entry, &tl_data));
+}
+
+krb5_error_code
+krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
+    krb5_context          context;
+    krb5_db_entry       * entry;
+    krb5_timestamp	* stamp;
+{
+    krb5_tl_data        tl_data;
+    krb5_error_code	code;
+    krb5_int32		tmp;
+
+    tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+
+    if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
+	return(code);
+
+    if (tl_data.tl_data_length != 4) {
+	*stamp = 0;
+	return(0);
+    }
+
+    krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
+
+    *stamp = (krb5_timestamp) tmp;
+
+    return(0);
+}
+
+/* it seems odd that there's no function to remove a tl_data, but if
+   I need one, I'll add one */
+
+krb5_error_code
+krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
+    krb5_context	  context;
+    krb5_db_entry	* entry;
+    krb5_timestamp	  mod_date;
+    krb5_const_principal  mod_princ;
+{
+    krb5_tl_data          tl_data;
+
+    krb5_error_code 	  retval = 0;
+    krb5_octet		* nextloc = 0;
+    char		* unparse_mod_princ = 0;
+    unsigned int	unparse_mod_princ_size;
+
+    if ((retval = krb5_unparse_name(context, mod_princ,
+				    &unparse_mod_princ)))
+	return(retval);
+
+    unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
+
+    if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
+	== NULL) {
+	free(unparse_mod_princ);
+	return(ENOMEM);
+    }
+
+    tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
+    tl_data.tl_data_length = unparse_mod_princ_size + 4;
+    tl_data.tl_data_contents = nextloc;
+
+    /* Mod Date */
+    krb5_kdb_encode_int32(mod_date, nextloc);
+
+    /* Mod Princ */
+    memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);
+
+    retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
+
+    free(unparse_mod_princ);
+    free(nextloc);
+
+    return(retval);
+}
+
+krb5_error_code
+krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
+    krb5_context	  context;
+    krb5_db_entry	* entry;
+    krb5_timestamp	* mod_time;
+    krb5_principal	* mod_princ;
+{
+    krb5_tl_data        tl_data;
+    krb5_error_code	code;
+
+    tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
+
+    if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
+	return(code);
+
+    if ((tl_data.tl_data_length < 5) ||
+	(tl_data.tl_data_contents[tl_data.tl_data_length-1] != '\0'))
+	return(KRB5_KDB_TRUNCATED_RECORD);
+
+    /* Mod Date */
+    krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
+
+    /* Mod Princ */
+    if ((code = krb5_parse_name(context,
+				(const char *) (tl_data.tl_data_contents+4),
+				mod_princ)))
+	return(code);
+
+    return(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h
new file mode 100644
index 000000000..bd01ead27
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h
@@ -0,0 +1,34 @@
+#ifndef _KDB2_XDR_H
+#define _KDB2_XDR_H
+
+#include "kdb.h"
+
+krb5_error_code
+krb5_encode_princ_dbkey( krb5_context context,
+			 krb5_data  *key,
+			 krb5_const_principal principal);
+
+krb5_error_code
+krb5_decode_princ_contents( krb5_context 	  context,
+			    krb5_data  		* content,
+			    krb5_db_entry 	* entry);
+
+void
+krb5_dbe_free_contents( krb5_context 	  context,
+			krb5_db_entry 	* entry);
+
+krb5_error_code
+krb5_encode_princ_contents( krb5_context 	  context,
+			    krb5_data  		* content,
+			    krb5_db_entry 	* entry);
+
+
+void
+krb5_free_princ_dbkey( krb5_context context,
+		       krb5_data  *key);
+
+void
+krb5_free_princ_contents( krb5_context context,
+			  krb5_data *contents);
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
new file mode 100644
index 000000000..4b4f70a1a
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
@@ -0,0 +1,763 @@
+# Novell Kerberos Schema Definitions
+# Novell Inc.
+# 1800 South Novell Place
+# Provo, UT 84606
+#
+# VeRsIoN=1.0
+# CoPyRiGhT=(c) Copyright 2006, Novell, Inc.  All rights reserved
+#
+# OIDs:
+#    joint-iso-ccitt(2)
+#      country(16)
+#        us(840)
+#          organization(1)
+#            Novell(113719)
+#              applications(1)
+#                kerberos(301)
+#                 Kerberos Attribute Type(4) attr# version#
+#                    specific attribute definitions
+#                 Kerberos Attribute Syntax(5)
+#                    specific syntax definitions
+#                 Kerberos Object Class(6) class# version#
+#                    specific class definitions
+
+########################################################################
+
+
+########################################################################
+# 		      Attribute Type Definitions                       #
+########################################################################
+
+##### This is the principal name in the RFC 1964 specified format
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.1.1
+                NAME 'krbPrincipalName'
+                EQUALITY caseExactIA5Match
+		SUBSTR caseExactSubstringsMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
+
+
+##### This specifies the type of the principal, the types could be any of
+##### the types mentioned in section 6.2 of RFC 4120
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.3.1
+                NAME 'krbPrincipalType'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### This flag is used to find whether directory User Password has to be used
+##### as kerberos password.
+##### TRUE, if User Password is to be used as the kerberos password.
+##### FALSE, if User Password and the kerberos password are different.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.5.1
+                NAME 'krbUPEnabled'
+                DESC 'Boolean'
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+                SINGLE-VALUE)
+
+
+##### The time at which the principal expires
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.6.1
+                NAME 'krbPrincipalExpiration'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### The krbTicketFlags attribute holds information about the kerberos flags for a principal
+##### The values (0x00000001 - 0x00800000) are reserved for standards and 
+##### values (0x01000000 - 0x80000000) can be used for proprietary extensions.
+##### The flags and values as per RFC 4120 and MIT implementation are,
+##### DISALLOW_POSTDATED	0x00000001
+##### DISALLOW_FORWARDABLE	0x00000002
+##### DISALLOW_TGT_BASED        0x00000004
+##### DISALLOW_RENEWABLE        0x00000008
+##### DISALLOW_PROXIABLE        0x00000010
+##### DISALLOW_DUP_SKEY         0x00000020
+##### DISALLOW_ALL_TIX          0x00000040
+##### REQUIRES_PRE_AUTH         0x00000080
+##### REQUIRES_HW_AUTH          0x00000100
+##### REQUIRES_PWCHANGE         0x00000200
+##### DISALLOW_SVR              0x00001000
+##### PWCHANGE_SERVICE          0x00002000
+
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.8.1
+                NAME 'krbTicketFlags'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### The maximum ticket lifetime for a principal in seconds
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.9.1
+                NAME 'krbMaxTicketLife'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Maximum renewable lifetime for a principal's ticket in seconds
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.10.1
+                NAME 'krbMaxRenewableAge'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Forward reference to the Realm object.
+##### (FDN of the krbRealmContainer object).
+##### Example:   cn=ACME.COM, cn=Kerberos, cn=Security
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.14.1
+                NAME 'krbRealmReferences'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### List of LDAP servers that kerberos servers can contact.
+##### The attribute holds data in the ldap uri format,
+##### Example: ldaps://acme.com:636
+#####
+##### The values of this attribute need to be updated, when
+##### the LDAP servers listed here are renamed, moved or deleted.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.15.1
+                NAME 'krbLdapServers'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+
+##### A set of forward references to the KDC Service objects.
+##### (FDNs of the krbKdcService objects).
+##### Example:   cn=kdc - server 1, ou=uvw, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.17.1
+                NAME 'krbKdcServers'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### A set of forward references to the Password Service objects.
+##### (FDNs of the krbPwdService objects).
+##### Example:   cn=kpasswdd - server 1, ou=uvw, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.18.1
+                NAME 'krbPwdServers'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### This attribute holds the Host Name or the ip address, 
+##### transport protocol and ports of the kerberos service host
+##### The format is host_name-or-ip_address#protocol#port
+##### Protocol can be 0 or 1. 0 is for UDP. 1 is for TCP.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.24.1
+                NAME 'krbHostServer'
+                EQUALITY caseExactIA5Match
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
+
+
+##### This attribute holds the scope for searching the principals
+##### under krbSubTree attribute of krbRealmContainer
+##### The value can either be 1 (ONE) or 2 (SUB_TREE).
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.25.1
+                NAME 'krbSearchScope'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### FDNs pointing to Kerberos principals
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.26.1
+                NAME 'krbPrincipalReferences'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### This attribute specifies which attribute of the user objects  
+##### be used as the principal name component for Kerberos.
+##### The allowed values are cn, sn, uid, givenname, fullname.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.28.1
+                NAME 'krbPrincNamingAttr'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+                SINGLE-VALUE)
+
+
+##### A set of forward references to the Administration Service objects.
+##### (FDNs of the krbAdmService objects).
+##### Example:   cn=kadmindd - server 1, ou=uvw, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.29.1
+                NAME 'krbAdmServers'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### Maximum lifetime of a principal's password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.30.1
+                NAME 'krbMaxPwdLife'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Minimum lifetime of a principal's password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.31.1
+                NAME 'krbMinPwdLife'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Minimum number of character clases allowed in a password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.32.1
+                NAME 'krbPwdMinDiffChars' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Minimum length of the password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.33.1
+                NAME 'krbPwdMinLength' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Number of previous versions of passwords that are stored
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.34.1
+                NAME 'krbPwdHistoryLength' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### FDN pointing to a Kerberos Password Policy object
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.36.1
+                NAME 'krbPwdPolicyReference'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+                SINGLE-VALUE)
+
+
+##### The time at which the principal's password expires
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.37.1
+                NAME 'krbPasswordExpiration'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### This attribute holds the principal's key (krbPrincipalKey) that is encrypted with
+##### the master key (krbMKey). 
+##### The attribute is ASN.1 encoded.
+#####
+##### The format of the value for this attribute is explained below,
+##### KrbKeySet ::= SEQUENCE {
+##### attribute-major-vno       [0] UInt16,
+##### attribute-minor-vno       [1] UInt16,
+##### kvno                      [2] UInt32,
+##### mkvno                     [3] UInt32 OPTIONAL,
+##### keys                      [4] SEQUENCE OF KrbKey,
+##### ...
+##### }
+#####
+##### KrbKey ::= SEQUENCE {
+##### salt      [0] KrbSalt OPTIONAL,
+##### key       [1] EncryptionKey,
+##### s2kparams [2] OCTET STRING OPTIONAL,
+##### ...
+##### }
+#####
+##### KrbSalt ::= SEQUENCE {
+##### type      [0] Int32,
+##### salt      [1] OCTET STRING OPTIONAL
+##### }
+#####
+##### EncryptionKey ::= SEQUENCE {
+##### keytype   [0] Int32,
+##### keyvalue  [1] OCTET STRING
+##### }
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.39.1
+                NAME 'krbPrincipalKey'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### FDN pointing to a Kerberos Ticket Policy object.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.40.1
+                NAME 'krbTicketPolicyReference'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+                SINGLE-VALUE)
+
+
+##### Forward reference to an entry that starts sub-trees
+##### where principals and other kerberos objects in the realm are configured.
+##### Example:   ou=acme, ou=pq, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.41.1
+                NAME 'krbSubTrees'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### Holds the default encryption/salt type combinations of principals for
+##### the Realm. Stores in the form of key:salt strings.
+##### Example: des-cbc-crc:normal
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.42.1
+                NAME 'krbDefaultEncSaltTypes'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+
+##### Holds the Supported encryption/salt type combinations of principals for
+##### the Realm. Stores in the form of key:salt strings.
+##### The supported encryption types are mentioned in RFC 3961
+##### The supported salt types are,
+##### NORMAL          
+##### V4              
+##### NOREALM         
+##### ONLYREALM       
+##### SPECIAL         
+##### AFS3            
+##### Example: des-cbc-crc:normal
+#####
+##### This attribute obsoletes the krbSupportedEncTypes and krbSupportedSaltTypes
+##### attributes.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.43.1
+                NAME 'krbSupportedEncSaltTypes'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+
+##### This attribute holds the principal's old keys (krbPwdHistory) that is encrypted with
+##### the kadmin/history key.
+##### The attribute is ASN.1 encoded.
+#####
+##### The format of the value for this attribute is explained below,
+##### KrbKeySet ::= SEQUENCE {
+##### attribute-major-vno       [0] UInt16,
+##### attribute-minor-vno       [1] UInt16,
+##### kvno                      [2] UInt32,
+##### mkvno                     [3] UInt32 OPTIONAL -- actually kadmin/history key,
+##### keys                      [4] SEQUENCE OF KrbKey,
+##### ...
+##### }
+#####
+##### KrbKey ::= SEQUENCE {
+##### salt      [0] KrbSalt OPTIONAL,
+##### key       [1] EncryptionKey,
+##### s2kparams [2] OCTET STRING OPTIONAL,
+##### ...
+##### }
+#####
+##### KrbSalt ::= SEQUENCE {
+##### type      [0] Int32,
+##### salt      [1] OCTET STRING OPTIONAL
+##### }
+#####
+##### EncryptionKey ::= SEQUENCE {
+##### keytype   [0] Int32,
+##### keyvalue  [1] OCTET STRING
+##### }
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.44.1
+                NAME 'krbPwdHistory'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### The time at which the principal's password last password change happened.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.45.1
+                NAME 'krbLastPwdChange'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### This attribute holds the kerberos master key.
+##### This can be used to encrypt principal keys. 
+##### This attribute has to be secured in directory.
+#####
+##### This attribute is ASN.1 encoded.
+##### The format of the value for this attribute is explained below,
+##### KrbMKey ::= SEQUENCE {
+##### kvno    [0] UInt32,
+##### key     [1] MasterKey
+##### }
+#####
+##### MasterKey ::= SEQUENCE {
+##### keytype         [0] Int32,
+##### keyvalue        [1] OCTET STRING
+##### }
+
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.46.1
+                NAME 'krbMKey'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### This stores the alternate principal names for the principal in the RFC 1961 specified format
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.47.1
+                NAME 'krbPrincipalAliases'
+                EQUALITY caseExactIA5Match
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
+
+
+##### The time at which the principal's last successful authentication happened.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.48.1
+                NAME 'krbLastSuccessfulAuth'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### The time at which the principal's last failed authentication happened.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.49.1
+                NAME 'krbLastFailedAuth'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### This attribute stores the number of failed authentication attempts
+##### happened for the principal since the last successful authentication.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.50.1
+                NAME 'krbLoginFailedCount' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+
+##### This attribute holds the application specific data.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.51.1
+                NAME 'krbExtraData'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### This attributes holds references to the set of directory objects.
+##### This stores the DNs of the directory objects to which the 
+##### principal object belongs to.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.52.1
+                NAME 'krbObjectReferences'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### This attribute holds references to a Container object where 
+##### the additional principal objects and stand alone principal 
+##### objects (krbPrincipal) can be created.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.53.1
+                NAME 'krbPrincContainerRef'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+########################################################################
+########################################################################
+# 		        Object Class Definitions                       #
+########################################################################
+
+#### This is a kerberos container for all the realms in a tree.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.1.1
+                NAME 'krbContainer'
+                SUP top
+                MUST ( cn ) )
+
+
+##### The krbRealmContainer is created per realm and holds realm specific data.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.2.1
+                NAME 'krbRealmContainer'
+                SUP top
+                MUST ( cn )
+                MAY ( krbMKey $ krbUPEnabled $ krbSubTrees $ krbSearchScope $ krbLdapServers $ krbSupportedEncSaltTypes $ krbDefaultEncSaltTypes $ krbTicketPolicyReference $ krbKdcServers $ krbPwdServers $ krbAdmServers $ krbPrincNamingAttr $krbPwdPolicyReference $ krbPrincContainerRef ) )
+
+
+##### An instance of a class derived from krbService is created per
+##### kerberos authentication or administration server in an realm and holds
+##### references to the realm objects. These references is used to further read
+##### realm specific data to service AS/TGS requests. Additionally this object
+##### contains some server specific data like pathnames and ports that the
+##### server uses. This is the identity the kerberos server logs in with. A key
+##### pair for the same is created and the kerberos server logs in with the same.
+#####
+##### krbKdcService, krbAdmService and krbPwdService derive from this class.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.3.1
+                NAME 'krbService'
+                ABSTRACT
+                SUP ( top )
+                MUST ( cn )
+                MAY ( krbHostServer $ krbRealmReferences ) )
+
+
+##### Representative object for the KDC server to bind into a LDAP directory
+##### and have a connection to access Kerberos data with the required 
+##### access rights.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.4.1
+                NAME 'krbKdcService'
+                SUP ( krbService ) )
+
+
+##### Representative object for the Kerberos Password server to bind into a LDAP directory
+##### and have a connection to access Kerberos data with the required
+##### access rights.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.5.1
+                NAME 'krbPwdService'
+                SUP ( krbService ) )
+
+
+###### The principal data auxiliary class. Holds principal information
+###### and is used to store principal information for Person, Service objects.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.8.1
+                NAME 'krbPrincipalAux'
+                AUXILIARY
+                MAY ( krbPrincipalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData ) )
+
+
+###### This class is used to create additional principals and stand alone principals.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.9.1
+                NAME 'krbPrincipal'
+                SUP ( top )
+                MUST ( krbPrincipalName )
+		MAY ( krbObjectReferences ) )
+
+
+###### The principal references auxiliary class. Holds all principals referred
+###### from a service
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.11.1
+                NAME 'krbPrincRefAux'
+                SUP top
+                AUXILIARY
+                MAY krbPrincipalReferences )
+
+
+##### Representative object for the Kerberos Administration server to bind into a LDAP directory
+##### and have a connection Id to access Kerberos data with the required access rights.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.13.1
+                NAME 'krbAdmService'
+                SUP ( krbService ) )
+
+
+##### The krbPwdPolicy object is a template password policy that 
+##### can be applied to principals when they are created. 
+##### These policy attributes will be in effect, when the Kerberos
+##### passwords are different from users' passwords (UP).
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.14.1
+                NAME 'krbPwdPolicy' 
+                SUP top
+                MUST ( cn )
+                MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength ) )
+
+
+##### The krbTicketPolicyAux holds Kerberos ticket policy attributes.
+##### This class can be attached to a principal object or realm object.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.16.1
+                NAME 'krbTicketPolicyAux'
+                AUXILIARY
+                MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge ) )
+
+
+##### The krbTicketPolicy object is an effective ticket policy that is associated with a realm or a principal
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.17.1
+                NAME 'krbTicketPolicy'
+                SUP top
+                MUST ( cn ) )
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
new file mode 100644
index 000000000..851c23a92
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
@@ -0,0 +1,618 @@
+# Novell Kerberos Schema Definitions
+# Novell Inc.
+# 1800 South Novell Place
+# Provo, UT 84606
+#
+# VeRsIoN=1.0
+# CoPyRiGhT=(c) Copyright 2006, Novell, Inc.  All rights reserved
+#
+# OIDs:
+#    joint-iso-ccitt(2)
+#      country(16)
+#        us(840)
+#          organization(1)
+#            Novell(113719)
+#              applications(1)
+#                kerberos(301)
+#                 Kerberos Attribute Type(4) attr# version#
+#                    specific attribute definitions
+#                 Kerberos Attribute Syntax(5)
+#                    specific syntax definitions
+#                 Kerberos Object Class(6) class# version#
+#                    specific class definitions
+
+########################################################################
+
+
+########################################################################
+# 		      Attribute Type Definitions                       #
+########################################################################
+
+##### This is the principal name in the RFC 1964 specified format
+
+attributetype ( 2.16.840.1.113719.1.301.4.1.1
+                NAME 'krbPrincipalName'
+                EQUALITY caseExactIA5Match
+		SUBSTR caseExactSubstringsMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
+
+
+##### This specifies the type of the principal, the types could be any of
+##### the types mentioned in section 6.2 of RFC 4120
+
+attributetype ( 2.16.840.1.113719.1.301.4.3.1
+                NAME 'krbPrincipalType'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### This flag is used to find whether directory User Password has to be used
+##### as kerberos password.
+##### TRUE, if User Password is to be used as the kerberos password.
+##### FALSE, if User Password and the kerberos password are different.
+
+attributetype ( 2.16.840.1.113719.1.301.4.5.1
+                NAME 'krbUPEnabled'
+                DESC 'Boolean'
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+                SINGLE-VALUE)
+
+
+##### The time at which the principal expires
+
+attributetype ( 2.16.840.1.113719.1.301.4.6.1
+                NAME 'krbPrincipalExpiration'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### The krbTicketFlags attribute holds information about the kerberos flags for a principal
+##### The values (0x00000001 - 0x00800000) are reserved for standards and 
+##### values (0x01000000 - 0x80000000) can be used for proprietary extensions.
+##### The flags and values as per RFC 4120 and MIT implementation are,
+##### DISALLOW_POSTDATED	0x00000001
+##### DISALLOW_FORWARDABLE	0x00000002
+##### DISALLOW_TGT_BASED        0x00000004
+##### DISALLOW_RENEWABLE        0x00000008
+##### DISALLOW_PROXIABLE        0x00000010
+##### DISALLOW_DUP_SKEY         0x00000020
+##### DISALLOW_ALL_TIX          0x00000040
+##### REQUIRES_PRE_AUTH         0x00000080
+##### REQUIRES_HW_AUTH          0x00000100
+##### REQUIRES_PWCHANGE         0x00000200
+##### DISALLOW_SVR              0x00001000
+##### PWCHANGE_SERVICE          0x00002000
+
+
+attributetype ( 2.16.840.1.113719.1.301.4.8.1
+                NAME 'krbTicketFlags'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### The maximum ticket lifetime for a principal in seconds
+
+attributetype ( 2.16.840.1.113719.1.301.4.9.1
+                NAME 'krbMaxTicketLife'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Maximum renewable lifetime for a principal's ticket in seconds
+
+attributetype ( 2.16.840.1.113719.1.301.4.10.1
+                NAME 'krbMaxRenewableAge'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Forward reference to the Realm object.
+##### (FDN of the krbRealmContainer object).
+##### Example:   cn=ACME.COM, cn=Kerberos, cn=Security
+
+attributetype ( 2.16.840.1.113719.1.301.4.14.1
+                NAME 'krbRealmReferences'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### List of LDAP servers that kerberos servers can contact.
+##### The attribute holds data in the ldap uri format,
+##### Examples: acme.com#636, 164.164.164.164#1636, ldaps://acme.com:636
+#####
+##### The values of this attribute need to be updated, when
+##### the LDAP servers listed here are renamed, moved or deleted.
+
+attributetype ( 2.16.840.1.113719.1.301.4.15.1
+                NAME 'krbLdapServers'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+
+##### A set of forward references to the KDC Service objects.
+##### (FDNs of the krbKdcService objects).
+##### Example:   cn=kdc - server 1, ou=uvw, o=xyz
+
+attributetype ( 2.16.840.1.113719.1.301.4.17.1
+                NAME 'krbKdcServers'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### A set of forward references to the Password Service objects.
+##### (FDNs of the krbPwdService objects).
+##### Example:   cn=kpasswdd - server 1, ou=uvw, o=xyz
+
+attributetype ( 2.16.840.1.113719.1.301.4.18.1
+                NAME 'krbPwdServers'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### This attribute holds the Host Name or the ip address, 
+##### transport protocol and ports of the kerberos service host
+##### The format is host_name-or-ip_address#protocol#port
+##### Protocol can be 0 or 1. 0 is for UDP. 1 is for TCP.
+
+attributetype ( 2.16.840.1.113719.1.301.4.24.1
+                NAME 'krbHostServer'
+                EQUALITY caseExactIA5Match
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
+
+
+##### This attribute holds the scope for searching the principals
+##### under krbSubTree attribute of krbRealmContainer
+##### The value can either be 1 (ONE) or 2 (SUB_TREE).
+
+attributetype ( 2.16.840.1.113719.1.301.4.25.1
+                NAME 'krbSearchScope'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### FDNs pointing to Kerberos principals
+
+attributetype ( 2.16.840.1.113719.1.301.4.26.1
+                NAME 'krbPrincipalReferences'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### This attribute specifies which attribute of the user objects  
+##### be used as the principal name component for Kerberos.
+##### The allowed values are cn, sn, uid, givenname, fullname.
+
+attributetype ( 2.16.840.1.113719.1.301.4.28.1
+                NAME 'krbPrincNamingAttr'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+                SINGLE-VALUE)
+
+
+##### A set of forward references to the Administration Service objects.
+##### (FDNs of the krbAdmService objects).
+##### Example:   cn=kadmindd - server 1, ou=uvw, o=xyz
+
+attributetype ( 2.16.840.1.113719.1.301.4.29.1
+                NAME 'krbAdmServers'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### Maximum lifetime of a principal's password
+
+attributetype ( 2.16.840.1.113719.1.301.4.30.1
+                NAME 'krbMaxPwdLife'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Minimum lifetime of a principal's password
+
+attributetype ( 2.16.840.1.113719.1.301.4.31.1
+                NAME 'krbMinPwdLife'
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Minimum number of character clases allowed in a password
+
+attributetype ( 2.16.840.1.113719.1.301.4.32.1
+                NAME 'krbPwdMinDiffChars' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Minimum length of the password
+
+attributetype ( 2.16.840.1.113719.1.301.4.33.1
+                NAME 'krbPwdMinLength' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### Number of previous versions of passwords that are stored
+
+attributetype ( 2.16.840.1.113719.1.301.4.34.1
+                NAME 'krbPwdHistoryLength' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+##### FDN pointing to a Kerberos Password Policy object
+
+attributetype ( 2.16.840.1.113719.1.301.4.36.1
+                NAME 'krbPwdPolicyReference'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+                SINGLE-VALUE)
+
+
+##### The time at which the principal's password expires
+
+attributetype ( 2.16.840.1.113719.1.301.4.37.1
+                NAME 'krbPasswordExpiration'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### This attribute holds the principal's key (krbPrincipalKey) that is encrypted with
+##### the master key (krbMKey). 
+##### The attribute is ASN.1 encoded.
+#####
+##### The format of the value for this attribute is explained below,
+##### KrbKeySet ::= SEQUENCE {
+##### attribute-major-vno       [0] UInt16,
+##### attribute-minor-vno       [1] UInt16,
+##### kvno                      [2] UInt32,
+##### mkvno                     [3] UInt32 OPTIONAL,
+##### keys                      [4] SEQUENCE OF KrbKey,
+##### ...
+##### }
+#####
+##### KrbKey ::= SEQUENCE {
+##### salt      [0] KrbSalt OPTIONAL,
+##### key       [1] EncryptionKey,
+##### s2kparams [2] OCTET STRING OPTIONAL,
+##### ...
+##### }
+#####
+##### KrbSalt ::= SEQUENCE {
+##### type      [0] Int32,
+##### salt      [1] OCTET STRING OPTIONAL
+##### }
+#####
+##### EncryptionKey ::= SEQUENCE {
+##### keytype   [0] Int32,
+##### keyvalue  [1] OCTET STRING
+##### }
+
+attributetype ( 2.16.840.1.113719.1.301.4.39.1
+                NAME 'krbPrincipalKey'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### FDN pointing to a Kerberos Ticket Policy object.
+
+attributetype ( 2.16.840.1.113719.1.301.4.40.1
+                NAME 'krbTicketPolicyReference'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+                SINGLE-VALUE)
+
+
+##### Forward reference to an entry that starts sub-trees
+##### where principals and other kerberos objects in the realm are configured.
+##### Example:   ou=acme, ou=pq, o=xyz
+
+attributetype ( 2.16.840.1.113719.1.301.4.41.1
+                NAME 'krbSubTrees'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### Holds the default encryption/salt type combinations of principals for
+##### the Realm. Stores in the form of key:salt strings. This will be
+##### subset of the supported encryption/salt types.
+##### Example: des-cbc-crc:normal
+
+attributetype ( 2.16.840.1.113719.1.301.4.42.1
+                NAME 'krbDefaultEncSaltTypes'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+
+##### Holds the supported encryption/salt type combinations of principals for
+##### the Realm. Stores in the form of key:salt strings.
+##### The supported encryption types are mentioned in RFC 3961
+##### The supported salt types are,
+##### NORMAL          
+##### V4              
+##### NOREALM         
+##### ONLYREALM       
+##### SPECIAL         
+##### AFS3            
+##### Example: des-cbc-crc:normal
+
+attributetype ( 2.16.840.1.113719.1.301.4.43.1
+                NAME 'krbSupportedEncSaltTypes'
+                EQUALITY caseIgnoreMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+
+##### This attribute holds the principal's old keys (krbPwdHistory) that is encrypted with
+##### the kadmin/history key.
+##### The attribute is ASN.1 encoded.
+#####
+##### The format of the value for this attribute is explained below,
+##### KrbKeySet ::= SEQUENCE {
+##### attribute-major-vno       [0] UInt16,
+##### attribute-minor-vno       [1] UInt16,
+##### kvno                      [2] UInt32,
+##### mkvno                     [3] UInt32 OPTIONAL -- actually kadmin/history key,
+##### keys                      [4] SEQUENCE OF KrbKey,
+##### ...
+##### }
+#####
+##### KrbKey ::= SEQUENCE {
+##### salt      [0] KrbSalt OPTIONAL,
+##### key       [1] EncryptionKey,
+##### s2kparams [2] OCTET STRING OPTIONAL,
+##### ...
+##### }
+#####
+##### KrbSalt ::= SEQUENCE {
+##### type      [0] Int32,
+##### salt      [1] OCTET STRING OPTIONAL
+##### }
+#####
+##### EncryptionKey ::= SEQUENCE {
+##### keytype   [0] Int32,
+##### keyvalue  [1] OCTET STRING
+##### }
+
+attributetype ( 2.16.840.1.113719.1.301.4.44.1
+                NAME 'krbPwdHistory'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### The time at which the principal's password last password change happened.
+
+attributetype ( 2.16.840.1.113719.1.301.4.45.1
+                NAME 'krbLastPwdChange'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### This attribute holds the kerberos master key.
+##### This can be used to encrypt principal keys. 
+##### This attribute has to be secured in directory.
+#####
+##### This attribute is ASN.1 encoded.
+##### The format of the value for this attribute is explained below,
+##### KrbMKey ::= SEQUENCE {
+##### kvno    [0] UInt32,
+##### key     [1] MasterKey
+##### }
+#####
+##### MasterKey ::= SEQUENCE {
+##### keytype         [0] Int32,
+##### keyvalue        [1] OCTET STRING
+##### }
+
+
+attributetype ( 2.16.840.1.113719.1.301.4.46.1
+                NAME 'krbMKey'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### This stores the alternate principal names for the principal in the RFC 1961 specified format
+
+attributetype ( 2.16.840.1.113719.1.301.4.47.1
+                NAME 'krbPrincipalAliases'
+                EQUALITY caseExactIA5Match
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
+
+
+##### The time at which the principal's last successful authentication happened.
+
+attributetype ( 2.16.840.1.113719.1.301.4.48.1
+                NAME 'krbLastSuccessfulAuth'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### The time at which the principal's last failed authentication happened.
+
+attributetype ( 2.16.840.1.113719.1.301.4.49.1
+                NAME 'krbLastFailedAuth'
+                EQUALITY generalizedTimeMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+                SINGLE-VALUE)
+
+
+##### This attribute stores the number of failed authentication attempts
+##### happened for the principal since the last successful authentication.
+
+attributetype ( 2.16.840.1.113719.1.301.4.50.1
+                NAME 'krbLoginFailedCount' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 
+                SINGLE-VALUE)
+
+
+
+##### This attribute holds the application specific data.
+
+attributetype ( 2.16.840.1.113719.1.301.4.51.1
+                NAME 'krbExtraData'
+                EQUALITY octetStringMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### This attributes holds references to the set of directory objects.
+##### This stores the DNs of the directory objects to which the 
+##### principal object belongs to.
+
+attributetype ( 2.16.840.1.113719.1.301.4.52.1
+                NAME 'krbObjectReferences'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### This attribute holds references to a Container object where 
+##### the additional principal objects and stand alone principal 
+##### objects (krbPrincipal) can be created.
+
+attributetype ( 2.16.840.1.113719.1.301.4.53.1
+                NAME 'krbPrincContainerRef'
+                EQUALITY distinguishedNameMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+########################################################################
+########################################################################
+# 		        Object Class Definitions                       #
+########################################################################
+
+#### This is a kerberos container for all the realms in a tree.
+
+objectclass ( 2.16.840.1.113719.1.301.6.1.1
+                NAME 'krbContainer'
+                SUP top
+		STRUCTURAL
+                MUST ( cn ) )
+
+
+##### The krbRealmContainer is created per realm and holds realm specific data.
+
+objectclass ( 2.16.840.1.113719.1.301.6.2.1
+                NAME 'krbRealmContainer'
+                SUP top
+		STRUCTURAL
+                MUST ( cn )
+                MAY ( krbMKey $ krbUPEnabled $ krbSubTrees $ krbSearchScope $ krbLdapServers $ krbSupportedEncSaltTypes $ krbDefaultEncSaltTypes $ krbTicketPolicyReference $ krbKdcServers $ krbPwdServers $ krbAdmServers $ krbPrincNamingAttr $ krbPwdPolicyReference $ krbPrincContainerRef ) )
+
+
+##### An instance of a class derived from krbService is created per
+##### kerberos authentication or administration server in an realm and holds
+##### references to the realm objects. These references is used to further read
+##### realm specific data to service AS/TGS requests. Additionally this object
+##### contains some server specific data like pathnames and ports that the
+##### server uses. This is the identity the kerberos server logs in with. A key
+##### pair for the same is created and the kerberos server logs in with the same.
+#####
+##### krbKdcService, krbAdmService and krbPwdService derive from this class.
+
+objectclass ( 2.16.840.1.113719.1.301.6.3.1
+                NAME 'krbService'
+                SUP top
+                ABSTRACT
+                MUST ( cn )
+                MAY ( krbHostServer $ krbRealmReferences ) )
+
+
+##### Representative object for the KDC server to bind into a LDAP directory
+##### and have a connection to access Kerberos data with the required 
+##### access rights.
+
+objectclass ( 2.16.840.1.113719.1.301.6.4.1
+                NAME 'krbKdcService'
+                SUP krbService
+		STRUCTURAL )
+
+
+##### Representative object for the Kerberos Password server to bind into a LDAP directory
+##### and have a connection to access Kerberos data with the required
+##### access rights.
+
+objectclass ( 2.16.840.1.113719.1.301.6.5.1
+                NAME 'krbPwdService'
+                SUP krbService
+		STRUCTURAL )
+
+
+###### The principal data auxiliary class. Holds principal information
+###### and is used to store principal information for Person, Service objects.
+
+objectclass ( 2.16.840.1.113719.1.301.6.8.1
+                NAME 'krbPrincipalAux'
+		SUP top
+                AUXILIARY
+                MAY ( krbPrincipalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData ) )
+
+
+###### This class is used to create additional principals and stand alone principals.
+
+objectclass ( 2.16.840.1.113719.1.301.6.9.1
+                NAME 'krbPrincipal'
+                SUP top
+                MUST ( krbPrincipalName )
+		MAY ( krbObjectReferences ) )
+
+
+###### The principal references auxiliary class. Holds all principals referred
+###### from a service
+
+objectclass ( 2.16.840.1.113719.1.301.6.11.1
+                NAME 'krbPrincRefAux'
+                SUP top
+                AUXILIARY
+                MAY krbPrincipalReferences )
+
+
+##### Representative object for the Kerberos Administration server to bind into a LDAP directory
+##### and have a connection Id to access Kerberos data with the required access rights.
+
+objectclass ( 2.16.840.1.113719.1.301.6.13.1
+                NAME 'krbAdmService'
+                SUP krbService 
+		STRUCTURAL )
+
+
+##### The krbPwdPolicy object is a template password policy that 
+##### can be applied to principals when they are created. 
+##### These policy attributes will be in effect, when the Kerberos
+##### passwords are different from users' passwords (UP).
+
+objectclass ( 2.16.840.1.113719.1.301.6.14.1
+                NAME 'krbPwdPolicy' 
+                SUP top
+                MUST ( cn )
+                MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength ) )
+
+
+##### The krbTicketPolicyAux holds Kerberos ticket policy attributes.
+##### This class can be attached to a principal object or realm object.
+
+objectclass ( 2.16.840.1.113719.1.301.6.16.1
+                NAME 'krbTicketPolicyAux'
+                SUP top
+                AUXILIARY
+                MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge ) )
+
+
+##### The krbTicketPolicy object is an effective ticket policy that is associated with a realm or a principal
+
+objectclass ( 2.16.840.1.113719.1.301.6.17.1
+                NAME 'krbTicketPolicy'
+                SUP top
+                MUST ( cn ) )
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c
new file mode 100644
index 000000000..8c60c177d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c
@@ -0,0 +1,402 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_create.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "ldap_main.h"
+#include "ldap_realm.h"
+#include "ldap_principal.h"
+#include "ldap_krbcontainer.h"
+#include "ldap_err.h"
+
+/* 
+ * ******************************************************************************
+ * DAL functions
+ * ******************************************************************************
+ */
+
+/*
+ * This function will create a krbcontainer and realm on the LDAP Server, with
+ * the specified attributes.
+ */
+krb5_error_code
+krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
+{
+    krb5_error_code status = 0;
+    char  **t_ptr = db_args;
+    krb5_ldap_realm_params *rparams = NULL;
+    kdb5_dal_handle *dal_handle = NULL;
+    krb5_ldap_context *ldap_context=NULL;
+    krb5_boolean realm_obj_created = FALSE;
+    krb5_boolean krbcontainer_obj_created = FALSE;
+    krb5_ldap_krbcontainer_params kparams = {0};
+    int srv_cnt = 0;
+    int mask = 0;
+#ifdef HAVE_EDIRECTORY
+    int i = 0, rightsmask = 0;
+#endif
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    ldap_context = malloc(sizeof(krb5_ldap_context));
+    if (ldap_context == NULL) {
+	status = ENOMEM;
+	goto cleanup;
+    }
+    memset(ldap_context, 0, sizeof(*ldap_context));
+
+    ldap_context->kcontext = context;
+
+    /* populate ldap_context with ldap specific options */
+    while (t_ptr && *t_ptr) {
+	char *opt = NULL, *val = NULL;
+
+	if ((status = krb5_ldap_get_db_opt(*t_ptr, &opt, &val)) != 0) {
+	    goto cleanup;
+	}
+	if (opt && !strcmp(opt, "binddn")) {
+	    if (ldap_context->bind_dn) {
+		free (opt);
+		free (val);
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'binddn' missing");
+		goto cleanup;
+	    }
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'binddn' value missing");
+		free(opt);
+		goto cleanup;
+	    }
+	    ldap_context->bind_dn = strdup(val);
+	    if (ldap_context->bind_dn == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto cleanup;
+	    }
+	} else if (opt && !strcmp(opt, "nconns")) {
+	    if (ldap_context->max_server_conns) {
+		free (opt);
+		free (val);
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'nconns' missing");
+		goto cleanup;
+	    }
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'nconns' value missing");
+		free(opt);
+		goto cleanup;
+	    }
+	    ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER;
+	} else if (opt && !strcmp(opt, "bindpwd")) {
+	    if (ldap_context->bind_pwd) {
+		free (opt);
+		free (val);
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'bindpwd' missing");
+		goto cleanup;
+	    }
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'bindpwd' value missing");
+		free(opt);
+		goto cleanup;
+	    }
+	    ldap_context->bind_pwd = strdup(val);
+	    if (ldap_context->bind_pwd == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto cleanup;
+	    }
+	} else if (opt && !strcmp(opt, "host")) {
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'host' value missing");
+		free(opt);
+		goto cleanup;
+	    }
+	    if (ldap_context->server_info_list == NULL)
+		ldap_context->server_info_list =
+		    (krb5_ldap_server_info **) calloc(SERV_COUNT+1, sizeof(krb5_ldap_server_info *));
+
+	    if (ldap_context->server_info_list == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto cleanup;
+	    }
+
+	    ldap_context->server_info_list[srv_cnt] =
+		(krb5_ldap_server_info *) calloc(1, sizeof(krb5_ldap_server_info));
+	    if (ldap_context->server_info_list[srv_cnt] == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto cleanup;
+	    }
+
+	    ldap_context->server_info_list[srv_cnt]->server_status = NOTSET;
+
+	    ldap_context->server_info_list[srv_cnt]->server_name = strdup(val);
+	    if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) {
+		free (opt);
+		free (val);
+		status = ENOMEM;
+		goto cleanup;
+	    }
+
+	    srv_cnt++;
+#ifdef HAVE_EDIRECTORY
+	} else if (opt && !strcmp(opt, "cert")) {
+	    if (val == NULL) {
+		status = EINVAL;
+		krb5_set_error_message (context, status, "'cert' value missing");
+		free(opt);
+		goto cleanup;
+	    }
+
+	    if (ldap_context->root_certificate_file == NULL) {
+		ldap_context->root_certificate_file = strdup(val);
+		if (ldap_context->root_certificate_file == NULL) {
+		    free (opt);
+		    free (val);
+		    status = ENOMEM;
+		    goto cleanup;
+		}
+	    } else {
+		void *tmp=NULL;
+		char *oldstr = NULL;
+		unsigned int len=0;
+
+		oldstr = strdup(ldap_context->root_certificate_file);
+		if (oldstr == NULL) {
+		    free (opt);
+		    free (val);
+		    status = ENOMEM;
+		    goto cleanup;
+		}
+
+		tmp = ldap_context->root_certificate_file;
+		len = strlen(ldap_context->root_certificate_file) + 2 + strlen(val);
+		ldap_context->root_certificate_file = realloc(ldap_context->root_certificate_file,
+							      len);
+		if (ldap_context->root_certificate_file == NULL) {
+		    free (tmp);
+		    free (opt);
+		    free (val);
+		    status = ENOMEM;
+		    goto cleanup;
+		}
+		memset(ldap_context->root_certificate_file, 0, len);
+		sprintf(ldap_context->root_certificate_file,"%s %s", oldstr, val);
+		free (oldstr);
+	    }
+#endif
+	} else {
+	/* ignore hash argument. Might have been passed from create */
+	    status = EINVAL;
+	    if (opt && !strcmp(opt, "temporary")) {
+		/* 
+		 * temporary is passed in when kdb5_util load without -update is done.
+		 * This is unsupported by the LDAP plugin.
+		 */
+		krb5_set_error_message (context, status,
+		    "creation of LDAP entries aborted, plugin requires -update argument");
+	    } else {
+		krb5_set_error_message (context, status, "unknown option \'%s\'",
+					opt?opt:val);
+	    }
+	    free(opt);
+	    free(val);
+	    goto cleanup;
+	}
+
+	free(opt);
+	free(val);
+	t_ptr++;
+    }
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    dal_handle->db_context = (kdb5_dal_handle *) ldap_context;
+
+    status = krb5_ldap_read_server_params(context, conf_section, KRB5_KDB_SRV_TYPE_ADMIN);
+    if (status) {
+	dal_handle->db_context = NULL;
+	prepend_err_str (context, "Error reading LDAP server params: ", status, status);
+	goto cleanup;
+    }
+    status = krb5_ldap_db_init(context, ldap_context);
+    if (status) {
+	goto cleanup;
+    }
+
+    /* read the kerberos container */
+    if ((status = krb5_ldap_read_krbcontainer_params(context,
+			    &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {
+
+	/* Read the kerberos container location from configuration file */
+	if (ldap_context->conf_section) {
+	    if ((status = profile_get_string(context->profile,
+					   KDB_MODULE_SECTION, ldap_context->conf_section,
+					   "ldap_kerberos_container_dn", NULL,
+					   &kparams.DN)) != 0) {
+		goto cleanup;
+	    }
+	}
+	if (kparams.DN == NULL) {
+	    if ((status = profile_get_string(context->profile,
+					   KDB_MODULE_DEF_SECTION,
+					   "ldap_kerberos_container_dn", NULL,
+					   NULL, &kparams.DN)) != 0) {
+		goto cleanup;
+	    }
+	}
+
+	/* create the kerberos container */
+	status = krb5_ldap_create_krbcontainer(context,
+					       ((kparams.DN != NULL) ? &kparams : NULL));
+	if (status)
+	    goto cleanup;
+
+	krbcontainer_obj_created = TRUE;
+
+	status = krb5_ldap_read_krbcontainer_params(context,
+						    &(ldap_context->krbcontainer));
+	if (status) {
+	    krb5_set_error_message(context, status, "while reading kerberos container information");
+	    goto cleanup;
+	}
+
+    } else if (status) {
+	krb5_set_error_message(context, status, "while reading kerberos container information");
+	goto cleanup;
+    }
+
+    rparams = (krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
+    if (rparams == NULL) {
+	status = ENOMEM;
+	goto cleanup;
+    }
+    memset(rparams, 0, sizeof(*rparams));
+    rparams->realm_name = strdup(context->default_realm);
+    if (rparams->realm_name == NULL) {
+	status = ENOMEM;
+	goto cleanup;
+    }
+
+    if ((status = krb5_ldap_create_realm(context, rparams, mask))) {
+	krb5_set_error_message(context, status, "while creating realm object entry");
+	goto cleanup;
+    }
+
+    /* We just created the Realm container. Here starts our transaction tracking */
+    realm_obj_created = TRUE;
+
+    /* verify realm object */
+    if ((status = krb5_ldap_read_realm_params(context,
+					      rparams->realm_name,
+					      &(ldap_context->lrparams),
+					      &mask))) {
+	krb5_set_error_message(context, status, "while reading realm object entry");
+	goto cleanup;
+    }
+
+#ifdef HAVE_EDIRECTORY
+    if ((mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
+	(mask & LDAP_REALM_PASSWDSERVERS)) {
+
+	rightsmask =0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
+	    for (i=0; (rparams->kdcservers[i] != NULL); i++) {
+		if ((status=krb5_ldap_add_service_rights(context,
+				     LDAP_KDC_SERVICE, rparams->kdcservers[i],
+				     rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    goto cleanup;
+		}
+	    }
+	}
+
+	rightsmask = 0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->adminservers != NULL)) {
+	    for (i=0; (rparams->adminservers[i] != NULL); i++) {
+		if ((status=krb5_ldap_add_service_rights(context,
+				     LDAP_ADMIN_SERVICE, rparams->adminservers[i],
+				     rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    goto cleanup;
+		}
+	    }
+	}
+
+	rightsmask = 0;
+	rightsmask |= LDAP_REALM_RIGHTS;
+	rightsmask |= LDAP_SUBTREE_RIGHTS;
+	if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
+	    for (i=0; (rparams->passwdservers[i] != NULL); i++) {
+		if ((status=krb5_ldap_add_service_rights(context,
+				     LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
+				     rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
+		    goto cleanup;
+		}
+	    }
+	}
+    }
+#endif
+
+cleanup:
+
+    /* If the krbcontainer/realm creation is not complete, do the roll-back here */
+    if ((krbcontainer_obj_created) && (!realm_obj_created)) {
+	int rc;
+	rc = krb5_ldap_delete_krbcontainer(context,
+		    ((kparams.DN != NULL) ? &kparams : NULL));
+	krb5_set_error_message(context, rc,
+	    "could not complete roll-back, error deleting Kerberos Container");
+    }
+
+    /* should call krb5_ldap_free_krbcontainer_params() but can't */
+    if (kparams.DN != NULL)
+	krb5_xfree(kparams.DN);
+
+    if (rparams)
+	krb5_ldap_free_realm_params(rparams);
+
+    return(status);
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c
new file mode 100644
index 000000000..d14bc8e8e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c
@@ -0,0 +1,193 @@
+#include <ldap.h>
+#include <errno.h>
+#include <kdb5_err.h>
+#include "ldap_err.h"
+#ifndef LDAP_X_ERROR
+#define LDAP_X_ERROR(x) (0)
+#endif
+
+#ifndef LDAP_NAME_ERROR
+#ifdef NAME_ERROR
+#define LDAP_NAME_ERROR NAME_ERROR
+#else
+#define LDAP_NAME_ERROR(x) (0)
+#endif
+#endif
+ 
+#ifndef LDAP_SECURITY_ERROR
+#define LDAP_SECURITY_ERROR(x) (0)
+#endif
+
+#ifndef LDAP_SERVICE_ERROR
+#define LDAP_SERVICE_ERROR(x) (0)
+#endif
+
+#ifndef LDAP_API_ERROR
+#define LDAP_API_ERROR(x) (0)
+#endif
+
+#ifndef LDAP_UPDATE_ERROR
+#define LDAP_UPDATE_ERROR(x) (0)
+#endif
+
+/*
+ * The possible KDB errors are
+ * 1. KRB5_KDB_UK_RERROR
+ * 2. KRB5_KDB_UK_SERROR
+ * 3. KRB5_KDB_NOENTRY
+ * 4. KRB5_KDB_TRUNCATED_RECORD
+ * 5. KRB5_KDB_UNAUTH
+ * 6. KRB5_KDB_DB_CORRUPT
+ * 7. KRB5_KDB_ACCESS_ERROR             (NEW)
+ * 8. KRB5_KDB_INTERNAL_ERROR           (NEW)
+ * 9. KRB5_KDB_SERVER_INTERNAL_ERR      (NEW)
+ * 10. KRB5_KDB_CONSTRAINT_VIOLATION    (NEW)
+ *
+ */
+
+/*
+ * op :
+ *  0          => not specified
+ *  OP_INIT    => ldap_init
+ *  OP_BIND    => ldap_bind
+ *  OP_UNBIND  => ldap_unbind
+ *  OP_ADD     => ldap_add
+ *  OP_MOD     => ldap_modify
+ *  OP_DEL     => ldap_delete
+ *  OP_SEARCH  => ldap_search
+ *  OP_CMP     => ldap_compare
+ *  OP_ABANDON => ldap_abandon
+ */
+
+int translate_ldap_error(int err, int op) {
+
+    switch (err) {
+    case LDAP_SUCCESS:
+	return 0;
+
+    case LDAP_OPERATIONS_ERROR:
+	/* LDAP_OPERATIONS_ERROR: Indicates an internal error. The server is
+	 * unable to respond with a more specific error and is also unable
+	 * to properly respond to a request */
+    case LDAP_UNAVAILABLE_CRITICAL_EXTENSION:
+	/* LDAP server was unable to satisfy a request because one or more
+	 * critical extensions were not available */
+	/* This might mean that the schema was not extended ... */
+    case LDAP_UNDEFINED_TYPE:
+	/* The attribute specified in the modify or add operation does not
+	 * exist in the LDAP server's schema. */
+	return KRB5_KDB_INTERNAL_ERROR;
+
+
+    case LDAP_INAPPROPRIATE_MATCHING:
+	/* The matching rule specified in the search filter does not match a
+	 * rule defined for the attribute's syntax */
+	return KRB5_KDB_UK_RERROR;
+
+    case LDAP_CONSTRAINT_VIOLATION:
+	/* The attribute value specified in a modify, add, or modify DN
+	 * operation violates constraints placed on the attribute */
+    case LDAP_TYPE_OR_VALUE_EXISTS:
+	/* The attribute value specified in a modify or add operation
+	 * already exists as a value for that attribute */
+	return KRB5_KDB_UK_SERROR;
+
+    case LDAP_INVALID_SYNTAX:
+	/* The attribute value specified in an add, compare, or modify
+	 * operation is an unrecognized or invalid syntax for the attribute */
+	if (op == OP_ADD || op == OP_MOD)
+	    return KRB5_KDB_UK_SERROR;
+	else /* OP_CMP */
+	    return KRB5_KDB_UK_RERROR;
+
+	/* Ensure that the following don't occur in the DAL-LDAP code.
+	 * Don't rely on the LDAP server to catch it */
+    case LDAP_SASL_BIND_IN_PROGRESS:
+	/* This is not an error. So, this function should not be called */
+    case LDAP_COMPARE_FALSE:
+    case LDAP_COMPARE_TRUE:
+	/* LDAP_COMPARE_FALSE and LDAP_COMPARE_TRUE are not errors. This
+	 * function should not be invoked for them */
+    case LDAP_RESULTS_TOO_LARGE: /* CLDAP */
+    case LDAP_TIMELIMIT_EXCEEDED:
+    case LDAP_SIZELIMIT_EXCEEDED:
+	return KRB5_KDB_SERVER_INTERNAL_ERR;
+
+    case LDAP_INVALID_DN_SYNTAX:
+	/* The syntax of the DN is incorrect */
+	return EINVAL;
+
+    case LDAP_PROTOCOL_ERROR:
+	/* LDAP_PROTOCOL_ERROR: Indicates that the server has received an
+	 * invalid or malformed request from the client */
+    case LDAP_CONFIDENTIALITY_REQUIRED:
+
+	/* Bind problems ... */
+    case LDAP_AUTH_METHOD_NOT_SUPPORTED:
+/*	case LDAP_STRONG_AUTH_NOT_SUPPORTED: // Is this a bind error ? */
+    case LDAP_INAPPROPRIATE_AUTH:
+    case LDAP_INVALID_CREDENTIALS:
+    case LDAP_UNAVAILABLE:
+	return KRB5_KDB_ACCESS_ERROR;
+
+    case LDAP_STRONG_AUTH_REQUIRED:
+	if (op == OP_BIND) /* the LDAP server accepts only strong authentication. */
+	    return KRB5_KDB_ACCESS_ERROR;
+	else /* Client requested an operation such that requires strong authentication */
+	    return KRB5_KDB_CONSTRAINT_VIOLATION;
+
+    case LDAP_REFERRAL:
+	return KRB5_KDB_NOENTRY;
+
+    case LDAP_ADMINLIMIT_EXCEEDED:
+	/* An LDAP server limit set by an administrative authority has been
+	 * exceeded */
+	return KRB5_KDB_CONSTRAINT_VIOLATION;
+    case LDAP_UNWILLING_TO_PERFORM:
+	/* The LDAP server cannot process the request because of
+	 * server-defined restrictions */
+	return KRB5_KDB_CONSTRAINT_VIOLATION;
+
+
+    case LDAP_NO_SUCH_ATTRIBUTE:
+	/* Indicates that the attribute specified in the modify or compare
+	 * operation does not exist in the entry */
+	if (op == OP_MOD)
+	    return KRB5_KDB_UK_SERROR;
+	else /* OP_CMP */
+	    return KRB5_KDB_TRUNCATED_RECORD;
+
+
+    case LDAP_ALIAS_DEREF_PROBLEM:
+	/* Either the client does not have access rights to read the aliased
+	 * object's name or dereferencing is not allowed */
+#ifdef LDAP_PROXY_AUTHZ_FAILURE
+    case LDAP_PROXY_AUTHZ_FAILURE: // Is this correct ?
+#endif
+    case LDAP_INSUFFICIENT_ACCESS:
+	/* Caller does not have sufficient rights to perform the requested
+	 * operation */
+	return KRB5_KDB_UNAUTH;
+
+    case LDAP_LOOP_DETECT:
+	/* Client discovered an alias or referral loop */
+	return KRB5_KDB_DB_CORRUPT;
+
+    default:
+
+	if (LDAP_NAME_ERROR (err))
+	    return KRB5_KDB_NOENTRY;
+
+	if (LDAP_SECURITY_ERROR (err))
+	    return KRB5_KDB_UNAUTH;
+
+	if (LDAP_SERVICE_ERROR (err) || LDAP_API_ERROR (err) || LDAP_X_ERROR (err))
+	    return KRB5_KDB_ACCESS_ERROR;
+
+	if (LDAP_UPDATE_ERROR(err))
+	    return KRB5_KDB_UK_SERROR;
+
+	/* LDAP_OTHER */
+	return KRB5_KDB_SERVER_INTERNAL_ERR;
+    }
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h
new file mode 100644
index 000000000..f83e583dd
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h
@@ -0,0 +1,12 @@
+#define OP_INIT 1
+#define OP_BIND 2
+#define OP_UNBIND 3
+#define OP_ADD 4
+#define OP_MOD 5
+#define OP_DEL 6
+#define OP_SEARCH 7
+#define OP_CMP 8
+#define OP_ABANDON 9
+
+
+int translate_ldap_error(int err, int op);
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
new file mode 100644
index 000000000..c159f0014
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
@@ -0,0 +1,100 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_fetch_mkey.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+
+/*
+ * get the master key from the database specific context
+ */
+
+krb5_error_code
+krb5_ldap_get_mkey (context, key)
+    krb5_context               context;
+    krb5_keyblock              **key;
+
+{
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+    if (ldap_context == NULL || ldap_context->lrparams == NULL)
+	return KRB5_KDB_DBNOTINITED;
+
+    *key = &ldap_context->lrparams->mkey;
+    return 0;
+}
+
+
+/*
+ * set the master key into the database specific context
+ */
+
+krb5_error_code
+krb5_ldap_set_mkey (context, pwd, key)
+    krb5_context                context;
+    char                        *pwd;
+    krb5_keyblock               *key;
+{
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_realm_params      *r_params = NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+    if (ldap_context == NULL || ldap_context->lrparams == NULL)
+	return KRB5_KDB_DBNOTINITED;
+
+    r_params = ldap_context->lrparams;
+
+    if (r_params->mkey.contents) {
+	free (r_params->mkey.contents);
+	r_params->mkey.contents=NULL;
+    }
+
+    r_params->mkey.magic = key->magic;
+    r_params->mkey.enctype = key->enctype;
+    r_params->mkey.length = key->length;
+    r_params->mkey.contents = malloc(key->length);
+    if (r_params->mkey.contents == NULL)
+	return ENOMEM;
+
+    memcpy(r_params->mkey.contents, key->contents, key->length);
+    return 0;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c
new file mode 100644
index 000000000..6f8e73d0e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c
@@ -0,0 +1,274 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_handle.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+
+
+#ifdef ASYNC_BIND
+
+/*
+ * Update the server info structure. In case of an asynchronous bind,
+ * this function is called to check the bind status. A flag
+ * server_info_upate_pending is refered before calling this function.
+ * This function sets the server_status to either ON or OFF and
+ * sets the server_info_udpate_pending to OFF.
+ * Do not lock the mutex here. The caller should lock it
+ */
+
+static krb5_error_code
+krb5_update_server_info(ldap_server_handle, server_info)
+    krb5_ldap_server_handle    *ldap_server_handle;
+    krb5_ldap_server_info      *server_info;
+{
+    krb5_error_code            st=0;
+    struct timeval             ztime={0, 0};
+    LDAPMessage                *result=NULL;
+
+    if (ldap_server_handle == NULL || server_info == NULL)
+	return -1;
+
+    while (st == 0) {
+	st = ldap_result(ldap_server_handle->ldap_handle, ldap_server_handle->msgid,
+			 LDAP_MSG_ALL, &ztime, &result);
+	switch (st) {
+	case -1:
+	    server_info->server_status = OFF;
+	    time(&server_info->downtime);
+	    break;
+
+	case 0:
+	    continue;
+	    break;
+
+	case LDAP_RES_BIND:
+	    if ((st=ldap_result2error(ldap_server_handle->ldap_handle, result, 1)) == LDAP_SUCCESS) {
+		server_info->server_status = ON;
+	    } else {
+		/* ?? */	krb5_set_error_message(0, 0, "%s", ldap_err2string(st));
+		server_info->server_status = OFF;
+		time(&server_info->downtime);
+	    }
+	    ldap_msgfree(result);
+	    break;
+	default:
+	    ldap_msgfree(result);
+	    continue;
+	    break;
+	}
+    }
+    ldap_server_handle->server_info_update_pending = FALSE;
+    return 0;
+}
+#endif
+
+/*
+ * Return ldap server handle from the pool. If the pool is exhausted return NULL.
+ * Do not lock the mutex, caller should lock it
+ */
+
+static krb5_ldap_server_handle *
+krb5_get_ldap_handle(ldap_context)
+    krb5_ldap_context          *ldap_context;
+{
+    krb5_ldap_server_handle    *ldap_server_handle=NULL;
+    krb5_ldap_server_info      *ldap_server_info=NULL;
+    int                        cnt=0;
+
+    while (ldap_context->server_info_list[cnt] != NULL) {
+	ldap_server_info = ldap_context->server_info_list[cnt];
+	if (ldap_server_info->server_status != OFF) {
+	    if (ldap_server_info->ldap_server_handles != NULL) {
+		ldap_server_handle = ldap_server_info->ldap_server_handles;
+		ldap_server_info->ldap_server_handles = ldap_server_handle->next;
+		break;
+#ifdef ASYNC_BIND
+		if (ldap_server_handle->server_info_update_pending == TRUE) {
+		    krb5_update_server_info(context, ldap_server_handle,
+					    ldap_server_info);
+		}
+
+		if (ldap_server_info->server_status == ON) {
+		    ldap_server_info->ldap_server_handles = ldap_server_handle->next;
+		    break;
+		} else
+		    ldap_server_handle = NULL;
+#endif
+	    }
+	}
+	++cnt;
+    }
+    return ldap_server_handle;
+}
+
+/*
+ * This is called incase krb5_get_ldap_handle returns NULL.
+ * Try getting a single connection (handle) and return the same by
+ * calling krb5_get_ldap_handle function.
+ * Do not lock the mutex here. The caller should lock it
+ */
+
+static krb5_ldap_server_handle *
+krb5_retry_get_ldap_handle(ldap_context, st)
+    krb5_ldap_context          *ldap_context;
+    krb5_error_code            *st;
+{
+    krb5_ldap_server_handle    *ldap_server_handle=NULL;
+
+    if ((*st=krb5_ldap_db_single_init(ldap_context)) != 0)
+	return NULL;
+
+    ldap_server_handle = krb5_get_ldap_handle(ldap_context);
+    return ldap_server_handle;
+}
+
+/*
+ * Put back the ldap server handle to the front of the list of handles of the
+ * ldap server info structure.
+ * Do not lock the mutex here. The caller should lock it.
+ */
+
+static krb5_error_code
+krb5_put_ldap_handle(ldap_server_handle)
+    krb5_ldap_server_handle    *ldap_server_handle;
+{
+
+    if (ldap_server_handle == NULL)
+	return 0;
+
+    ldap_server_handle->next = ldap_server_handle->server_info->ldap_server_handles;
+    ldap_server_handle->server_info->ldap_server_handles = ldap_server_handle;
+    return 0;
+}
+
+/*
+ * Add a new ldap server handle structure to the server info structure.
+ * This function name can be changed to krb5_insert_ldap_handle.
+ * Do not lock the mutex here. The caller should lock it
+ */
+
+krb5_error_code
+krb5_update_ldap_handle(ldap_server_handle, server_info)
+    krb5_ldap_server_handle    *ldap_server_handle;
+    krb5_ldap_server_info      *server_info;
+{
+
+    if (ldap_server_handle == NULL || server_info == NULL)
+	return 0;
+
+    ldap_server_handle->next = server_info->ldap_server_handles;
+    server_info->ldap_server_handles = ldap_server_handle;
+    server_info->num_conns++;
+    ldap_server_handle->server_info = server_info;
+    return 0;
+}
+
+/*
+ * Free up all the ldap server handles of the server info.
+ * This function is called when the ldap server returns LDAP_SERVER_DOWN.
+ */
+
+static krb5_error_code
+krb5_ldap_cleanup_handles(ldap_server_info)
+    krb5_ldap_server_info      *ldap_server_info;
+{
+    krb5_ldap_server_handle    *ldap_server_handle = NULL;
+
+    while (ldap_server_info->ldap_server_handles != NULL) {
+	ldap_server_handle = ldap_server_info->ldap_server_handles;
+	ldap_server_info->ldap_server_handles = ldap_server_handle->next;
+	/* ldap_unbind_s(ldap_server_handle); */
+	free (ldap_server_handle);
+	ldap_server_handle = NULL;
+    }
+    return 0;
+}
+
+/*
+ * wrapper function called from outside to get a handle.
+ */
+
+krb5_error_code
+krb5_ldap_request_handle_from_pool(ldap_context, ldap_server_handle)
+    krb5_ldap_context          *ldap_context;
+    krb5_ldap_server_handle    **ldap_server_handle;
+{
+    krb5_error_code            st=0;
+
+    *ldap_server_handle = NULL;
+
+    HNDL_LOCK(ldap_context);
+    if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
+	(*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
+    HNDL_UNLOCK(ldap_context);
+    return st;
+}
+
+/*
+ * wrapper function wrapper called to get the next ldap server handle, when the current
+ * ldap server handle returns LDAP_SERVER_DOWN.
+ */
+
+krb5_error_code
+krb5_ldap_request_next_handle_from_pool(ldap_context, ldap_server_handle)
+    krb5_ldap_context          *ldap_context;
+    krb5_ldap_server_handle    **ldap_server_handle;
+{
+    krb5_error_code            st=0;
+
+    HNDL_LOCK(ldap_context);
+    (*ldap_server_handle)->server_info->server_status = OFF;
+    time(&(*ldap_server_handle)->server_info->downtime);
+    krb5_put_ldap_handle(*ldap_server_handle);
+    krb5_ldap_cleanup_handles((*ldap_server_handle)->server_info);
+
+    if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
+	(*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
+    HNDL_UNLOCK(ldap_context);
+    return st;
+}
+
+/*
+ * wrapper function to call krb5_put_ldap_handle.
+ */
+
+void
+krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle)
+    krb5_ldap_context          *ldap_context;
+    krb5_ldap_server_handle    *ldap_server_handle;
+{
+
+    if (ldap_server_handle != NULL) {
+	HNDL_LOCK(ldap_context);
+	krb5_put_ldap_handle(ldap_server_handle);
+	HNDL_UNLOCK(ldap_context);
+    }
+    return;
+}
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h
new file mode 100644
index 000000000..a3b0885f4
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h
@@ -0,0 +1,46 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_handle.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_HANDLE_H_
+#define _LDAP_HANDLE_H_
+
+krb5_error_code 
+krb5_update_ldap_handle(krb5_ldap_server_handle *, krb5_ldap_server_info *);
+
+krb5_error_code
+krb5_ldap_request_handle_from_pool(krb5_ldap_context *, krb5_ldap_server_handle **);
+
+krb5_error_code
+krb5_ldap_request_next_handle_from_pool(krb5_ldap_context *, krb5_ldap_server_handle **);
+
+void
+krb5_ldap_put_handle_to_pool(krb5_ldap_context *, krb5_ldap_server_handle *);
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c
new file mode 100644
index 000000000..6a9c6b6e2
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c
@@ -0,0 +1,203 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_krbcontainer.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_err.h"
+
+char    *policyrefattribute[] = {"krbTicketPolicyReference",NULL};
+char    *krbcontainerrefattr[] = {"krbContainerReference", NULL};
+
+/*
+ *  Free the krb5_ldap_krbcontainer_params
+ */
+
+void
+krb5_ldap_free_krbcontainer_params(krb5_ldap_krbcontainer_params *cparams)
+{
+    if (cparams == NULL)
+	return;
+
+    if (cparams->policyreference)
+	krb5_xfree(cparams->policyreference);
+
+    if (cparams->parent)
+	krb5_xfree(cparams->parent);
+
+    if (cparams->DN)
+	krb5_xfree(cparams->DN);
+
+    krb5_xfree(cparams);
+
+    return;
+}
+
+/*
+ * Read the kerberos container. Kerberos container dn is read from the krb5.conf file.
+ * In case of eDirectory, if the dn is not present in the conf file, refer Security Container
+ * to fetch the dn information.
+ *
+ * Reading kerberos container includes reading the policyreference attribute and the policy
+ * object to read the attributes associated with it.
+ */
+
+krb5_error_code
+krb5_ldap_read_krbcontainer_params(krb5_context	context,
+				   krb5_ldap_krbcontainer_params **cparamp)
+
+{
+    krb5_error_code                 st=0, tempst=0;
+    LDAP                            *ld=NULL;
+    LDAPMessage                     *result=NULL, *ent=NULL;
+    krb5_ldap_krbcontainer_params   *cparams=NULL;
+    kdb5_dal_handle                 *dal_handle=NULL;
+    krb5_ldap_context               *ldap_context=NULL;
+    krb5_ldap_server_handle         *ldap_server_handle=NULL;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    cparams =(krb5_ldap_krbcontainer_params *) malloc(sizeof(krb5_ldap_krbcontainer_params));
+    CHECK_NULL(cparams);
+    memset((char *) cparams, 0, sizeof(krb5_ldap_krbcontainer_params));
+
+    /* read kerberos containter location from [dbmodules] section of krb5.conf file */
+    if (ldap_context->conf_section) {
+	if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, ldap_context->conf_section,
+				   "ldap_kerberos_container_dn", NULL,
+				   &cparams->DN)) != 0) {
+	    krb5_set_error_message(context, st, "Error reading kerberos container location "
+				   "from krb5.conf");
+	    goto cleanup;
+	}
+    }
+
+    /* read kerberos containter location from [dbdefaults] section of krb5.conf file */
+    if (cparams->DN == NULL) {
+	if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION,
+				   "ldap_kerberos_container_dn", NULL,
+				   NULL, &cparams->DN)) != 0) {
+	    krb5_set_error_message(context, st, "Error reading kerberos container location "
+				   "from krb5.conf");
+	    goto cleanup;
+	}
+    }
+
+#ifndef HAVE_EDIRECTORY
+/*
+ * In case eDirectory, we can fall back to security container if the kerberos container location
+ * is missing in the conf file. In openldap we will have to return an error.
+ */
+    if (cparams->DN == NULL) {
+	st = KRB5_KDB_SERVER_INTERNAL_ERR;
+	krb5_set_error_message(context, st, "Kerberos container location not specified");
+	goto cleanup;
+    }
+#endif
+
+    if (cparams->DN != NULL) {
+	/* NOTE: krbmaxtktlife, krbmaxrenewableage ... present on Kerberos Container is
+	 * not read
+	 */
+	LDAP_SEARCH_1(cparams->DN, LDAP_SCOPE_BASE, "(objectclass=krbContainer)", policyrefattribute, IGNORE_STATUS);
+	if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_OBJECT) {
+	    st = set_ldap_error(context, st, OP_SEARCH);
+	    goto cleanup;
+	}
+
+	if (st == LDAP_NO_SUCH_OBJECT) {
+	    st = KRB5_KDB_NOENTRY;
+	    goto cleanup;
+	}
+    }
+
+#ifdef HAVE_EDIRECTORY
+    /*
+     * If the kerberos location in the conf file is missing or invalid, fall back to the
+     * security container. If the kerberos location in the security container is also missing
+     * then fall back to the default value
+     */
+    if ((cparams->DN == NULL) || (st == LDAP_NO_SUCH_OBJECT)) {
+	/*
+	 * kerberos container can be anywhere. locate it by reading the security
+	 * container to find the location.
+	 */
+	LDAP_SEARCH(SECURITY_CONTAINER, LDAP_SCOPE_BASE, NULL, krbcontainerrefattr);
+	if ((ent = ldap_first_entry(ld, result)) != NULL) {
+	    if ((st=krb5_ldap_get_string(ld, ent, "krbcontainerreference",
+					 &(cparams->DN), NULL)) != 0)
+		goto cleanup;
+	    if (cparams->DN == NULL) {
+		cparams->DN = strdup(KERBEROS_CONTAINER);
+		CHECK_NULL(cparams->DN);
+	    }
+	}
+	ldap_msgfree(result);
+
+	/* NOTE: krbmaxtktlife, krbmaxrenewableage ... attributes present on
+	 * Kerberos Container is not read
+	 */
+	LDAP_SEARCH(cparams->DN, LDAP_SCOPE_BASE, "(objectclass=krbContainer)", policyrefattribute);
+    }
+#endif
+
+    if ((ent = ldap_first_entry(ld, result))) {
+	if ((st=krb5_ldap_get_string(ld, ent, "krbticketpolicyreference",
+				     &(cparams->policyreference), NULL)) != 0)
+	    goto cleanup;
+    }
+    ldap_msgfree(result);
+
+    if (cparams->policyreference != NULL) {
+	LDAP_SEARCH_1(cparams->policyreference, LDAP_SCOPE_BASE, NULL, policy_attributes, IGNORE_STATUS);
+	if (st != LDAP_SUCCESS && st!= LDAP_NO_SUCH_OBJECT) {
+	    st = set_ldap_error(context, st, OP_SEARCH);
+	    goto cleanup;
+	}
+	st = LDAP_SUCCESS; /* reset the return status in case it is LDAP_NO_SUCH_OBJECT */
+
+	ent=ldap_first_entry(ld, result);
+	if (ent != NULL) {
+	    krb5_ldap_get_value(ld, ent, "krbmaxtktlife", &(cparams->max_life));
+	    krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &(cparams->max_renewable_life));
+	    krb5_ldap_get_value(ld, ent, "krbticketflags", &(cparams->tktflags));
+	}
+	ldap_msgfree(result);
+    }
+    *cparamp=cparams;
+
+cleanup:
+    if (st != 0) {
+	krb5_ldap_free_krbcontainer_params(cparams);
+	*cparamp=NULL;
+    }
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h
new file mode 100644
index 000000000..f4510d69c
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h
@@ -0,0 +1,60 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_krbcontainer.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_KRBCONTAINER_H_
+#define _LDAP_KRBCONTAINER_H_ 1
+
+#define MAX_KRB_CONTAINER_LEN	256
+
+/* kerberos container structure */
+
+typedef struct _krb5_ldap_krbcontainer_params {
+  char            *parent;
+  char            *DN;
+  char            *policyreference;
+  krb5_int32      max_life;
+  krb5_int32      max_renewable_life;
+  krb5_int32      tktflags;
+} krb5_ldap_krbcontainer_params;
+
+void
+krb5_ldap_free_krbcontainer_params(krb5_ldap_krbcontainer_params *);
+
+krb5_error_code
+krb5_ldap_read_krbcontainer_params(krb5_context , krb5_ldap_krbcontainer_params **);
+
+krb5_error_code
+krb5_ldap_create_krbcontainer(krb5_context, const krb5_ldap_krbcontainer_params *);
+
+krb5_error_code
+krb5_ldap_delete_krbcontainer(krb5_context,
+    const krb5_ldap_krbcontainer_params *);
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h
new file mode 100644
index 000000000..95a837929
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h
@@ -0,0 +1,38 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_main.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LDAP_MAIN_H
+#define LDAP_MAIN_H 1
+
+#include "kdb_ldap.h"
+#include "ldap_misc.h"
+#include "ldap_handle.h"
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
new file mode 100644
index 000000000..11c5caae3
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
@@ -0,0 +1,2255 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_misc.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <string.h>
+#include <time.h>
+#include "kdb_ldap.h"
+#include "ldap_misc.h"
+#include "ldap_handle.h"
+#include "ldap_err.h"
+#include "ldap_principal.h"
+#include "princ_xdr.h"
+#include "ldap_pwd_policy.h"
+
+#ifdef NEED_STRPTIME_PROTO
+extern char *strptime (const char *, const char *, struct tm *);
+#endif
+
+static krb5_error_code
+remove_overlapping_subtrees(char **listin, char **listop, int *subtcount,
+			    int sscope);
+
+/* Linux (GNU Libc) provides a length-limited variant of strdup.
+   But all the world's not Linux.  */
+#undef strndup
+#define strndup my_strndup
+#ifdef HAVE_LDAP_STR2DN
+static char *my_strndup (const char *input, size_t limit)
+{
+    size_t len = strlen(input);
+    char *result;
+    if (len > limit) {
+	result = malloc(1 + limit);
+	if (result != NULL) {
+	    memcpy(result, input, limit);
+	    result[limit] = 0;
+	}
+	return result;
+    } else
+	return strdup(input);
+}
+#endif
+
+/* Get integer or string values from the config section, falling back
+   to the default section, then to hard-coded values.  */
+static errcode_t
+prof_get_integer_def(krb5_context ctx, const char *conf_section,
+		     const char *name, int dfl, krb5_ui_4 *out)
+{
+    errcode_t err;
+    int out_temp = 0;
+
+    err = profile_get_integer (ctx->profile,
+			       KDB_MODULE_SECTION, conf_section, name,
+			       0, &out_temp);
+    if (err) {
+	krb5_set_error_message (ctx, err, "Error reading '%s' attribute: %s",
+				name, error_message(err));
+	return err;
+    }
+    if (out_temp != 0) {
+	*out = out_temp;
+	return 0;
+    }
+    err = profile_get_integer (ctx->profile,
+			       KDB_MODULE_DEF_SECTION, name, 0,
+			       dfl, &out_temp);
+    if (err) {
+	krb5_set_error_message (ctx, err, "Error reading '%s' attribute: %s",
+				name, error_message(err));
+	return err;
+    }
+    *out = out_temp;
+    return 0;
+}
+
+/* We don't have non-null defaults in any of our calls, so don't
+   bother with the extra argument.  */
+static errcode_t
+prof_get_string_def(krb5_context ctx, const char *conf_section,
+		    const char *name, char **out)
+{
+    errcode_t err;
+
+    err = profile_get_string (ctx->profile,
+			      KDB_MODULE_SECTION, conf_section, name,
+			      0, out);
+    if (err) {
+	krb5_set_error_message (ctx, err, "Error reading '%s' attribute: %s",
+				name, error_message(err));
+	return err;
+    }
+    if (*out != 0)
+	return 0;
+    err = profile_get_string (ctx->profile,
+			      KDB_MODULE_DEF_SECTION, name, 0,
+			      0, out);
+    if (err) {
+	krb5_set_error_message (ctx, err, "Error reading '%s' attribute: %s",
+				name, error_message(err));
+	return err;
+    }
+    return 0;
+}
+
+
+
+/*
+ * This function reads the parameters from the krb5.conf file. The
+ * parameters read here are DAL-LDAP specific attributes. Some of
+ * these are ldap_server ....
+ */
+krb5_error_code
+krb5_ldap_read_server_params(context, conf_section, srv_type)
+    krb5_context               context;
+    char                       *conf_section;
+    int                        srv_type;
+{
+    char                        *tempval=NULL, *save_ptr=NULL;
+    const char                  *delims="\t\n\f\v\r ,";
+    krb5_error_code             st=0;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_info       ***server_info=NULL;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+    /* copy the conf_section into ldap_context for later use */
+    if (conf_section) {
+	ldap_context->conf_section = strdup (conf_section);
+	if (ldap_context->conf_section == NULL) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+    }
+
+    /* initialize the mutexs and condition variable */
+    /* this portion logically doesn't fit here should be moved appropriately */
+
+    /* this mutex is used in ldap reconnection pool */
+    if (k5_mutex_init(&(ldap_context->hndl_lock)) != 0) {
+	st = KRB5_KDB_SERVER_INTERNAL_ERR;
+#if 0
+	st = -1;
+	krb5_ldap_dal_err_funcp(context, krb5_err_have_str, st,
+				"k5_mutex_init failed");
+#endif
+	goto cleanup;
+    }
+
+    /*
+     * If max_server_conns is not set read it from database module
+     * section of conf file this parameter defines maximum ldap
+     * connections per ldap server.
+     */
+    if (ldap_context->max_server_conns == 0) {
+	st = prof_get_integer_def (context, conf_section,
+				   "ldap_conns_per_server",
+				   DEFAULT_CONNS_PER_SERVER,
+				   &ldap_context->max_server_conns);
+	if (st)
+	    goto cleanup;
+    }
+
+    if (ldap_context->max_server_conns < 2) {
+	st = EINVAL;
+	krb5_set_error_message (context, st,
+				"Minimum connections required per server is 2");
+	goto cleanup;
+    }
+
+    /*
+     * If the bind dn is not set read it from the database module
+     * section of conf file this paramter is populated by one of the
+     * KDC, ADMIN or PASSWD dn to be used to connect to LDAP
+     * server.  The srv_type decides which dn to read.
+     */
+    if (ldap_context->bind_dn == NULL) {
+	char *name = 0;
+	if (srv_type == KRB5_KDB_SRV_TYPE_KDC)
+	    name = "ldap_kdc_dn";
+	else if (srv_type == KRB5_KDB_SRV_TYPE_ADMIN)
+	    name = "ldap_kadmind_dn";
+	else if (srv_type == KRB5_KDB_SRV_TYPE_PASSWD)
+	    name = "ldap_kpasswdd_dn";
+
+	if (name) {
+	    st = prof_get_string_def (context, conf_section, name,
+				      &ldap_context->bind_dn);
+	    if (st)
+		goto cleanup;
+	}
+    }
+
+    /*
+     * Read service_password_file parameter from database module
+     * section of conf file this file contains stashed passwords of
+     * the KDC, ADMIN and PASSWD dns.
+     */
+    if (ldap_context->service_password_file == NULL) {
+	st = prof_get_string_def (context, conf_section,
+				  "ldap_service_password_file",
+				  &ldap_context->service_password_file);
+	if (st)
+	    goto cleanup;
+    }
+
+#ifdef HAVE_EDIRECTORY
+    /*
+     * If root certificate file is not set read it from database
+     * module section of conf file this is the trusted root
+     * certificate of the Directory.
+     */
+    if (ldap_context->root_certificate_file == NULL) {
+	st = prof_get_string_def (context, conf_section,
+				  "ldap_root_certificate_file",
+				  &ldap_context->root_certificate_file);
+	if (st)
+	    goto cleanup;
+    }
+#endif
+
+    /*
+     * If the ldap server parameter is not set read the list of ldap
+     * servers from the database module section of the conf file.
+     */
+
+    if (ldap_context->server_info_list == NULL) {
+	unsigned int ele=0;
+
+	server_info = &(ldap_context->server_info_list);
+	*server_info = (krb5_ldap_server_info **) calloc (SERV_COUNT+1,
+							  sizeof (krb5_ldap_server_info *));
+
+	if (*server_info == NULL) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+
+	if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, conf_section,
+				   "ldap_servers", NULL, &tempval)) != 0) {
+	    krb5_set_error_message (context, st, "Error reading 'ldap_servers' attribute");
+	    goto cleanup;
+	}
+
+	if (tempval == NULL) {
+
+	    (*server_info)[ele] = (krb5_ldap_server_info *)calloc(1,
+								  sizeof(krb5_ldap_server_info));
+
+	    (*server_info)[ele]->server_name = strdup("ldapi://");
+	    if ((*server_info)[ele]->server_name == NULL) {
+		st = ENOMEM;
+		goto cleanup;
+	    }
+	    (*server_info)[ele]->server_status = NOTSET;
+	} else {
+	    char *item=NULL;
+
+	    item = strtok_r(tempval,delims,&save_ptr);
+	    while (item != NULL && ele<SERV_COUNT) {
+		(*server_info)[ele] = (krb5_ldap_server_info *)calloc(1,
+								      sizeof(krb5_ldap_server_info));
+		if ((*server_info)[ele] == NULL) {
+		    st = ENOMEM;
+		    goto cleanup;
+		}
+		(*server_info)[ele]->server_name = strdup(item);
+		if ((*server_info)[ele]->server_name == NULL) {
+		    st = ENOMEM;
+		    goto cleanup;
+		}
+
+		(*server_info)[ele]->server_status = NOTSET;
+		item = strtok_r(NULL,delims,&save_ptr);
+		++ele;
+	    }
+	    profile_release_string(tempval);
+	}
+    }
+
+cleanup:
+    return(st);
+}
+
+/*
+ * This function frees the krb5_ldap_context structure members.
+ */
+
+krb5_error_code
+krb5_ldap_free_server_params(ldap_context)
+    krb5_ldap_context           *ldap_context;
+{
+    int                         i=0;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL, *next_ldap_server_handle=NULL;
+
+    if (ldap_context == NULL)
+	return 0;
+
+    /* Free all ldap servers list and the ldap handles associated with
+       the ldap server.  */
+    if (ldap_context->server_info_list) {
+	while (ldap_context->server_info_list[i]) {
+	    if (ldap_context->server_info_list[i]->server_name) {
+		free (ldap_context->server_info_list[i]->server_name);
+	    }
+#ifdef HAVE_EDIRECTORY
+	    if (ldap_context->server_info_list[i]->root_certificate_file) {
+		free (ldap_context->server_info_list[i]->root_certificate_file);
+	    }
+#endif
+	    if (ldap_context->server_info_list[i]->ldap_server_handles) {
+		ldap_server_handle = ldap_context->server_info_list[i]->ldap_server_handles;
+		while (ldap_server_handle) {
+		    ldap_unbind_ext_s(ldap_server_handle->ldap_handle, NULL, NULL);
+		    ldap_server_handle->ldap_handle = NULL;
+		    next_ldap_server_handle = ldap_server_handle->next;
+		    krb5_xfree(ldap_server_handle);
+		    ldap_server_handle = next_ldap_server_handle;
+		}
+	    }
+	    krb5_xfree(ldap_context->server_info_list[i]);
+	    i++;
+	}
+	krb5_xfree(ldap_context->server_info_list);
+    }
+
+    if (ldap_context->conf_section != NULL) {
+	krb5_xfree(ldap_context->conf_section);
+	ldap_context->conf_section = NULL;
+    }
+
+    if (ldap_context->bind_dn != NULL) {
+	krb5_xfree(ldap_context->bind_dn);
+	ldap_context->bind_dn = NULL;
+    }
+
+    if (ldap_context->bind_pwd != NULL) {
+	krb5_xfree(ldap_context->bind_pwd);
+	ldap_context->bind_pwd = NULL;
+    }
+
+    if (ldap_context->service_password_file != NULL) {
+	krb5_xfree(ldap_context->service_password_file);
+	ldap_context->service_password_file = NULL;
+    }
+
+#ifdef HAVE_EDIRECTORY
+    if (ldap_context->root_certificate_file != NULL) {
+	krb5_xfree(ldap_context->root_certificate_file);
+	ldap_context->root_certificate_file = NULL;
+    }
+#endif
+
+    if (ldap_context->service_cert_path != NULL) {
+	krb5_xfree(ldap_context->service_cert_path);
+	ldap_context->service_cert_path = NULL;
+    }
+
+    if (ldap_context->service_cert_pass != NULL) {
+	krb5_xfree(ldap_context->service_cert_pass);
+	ldap_context->service_cert_pass = NULL;
+    }
+
+    if (ldap_context->certificates) {
+	i=0;
+	while (ldap_context->certificates[i] != NULL) {
+	    krb5_xfree(ldap_context->certificates[i]->certificate);
+	    krb5_xfree(ldap_context->certificates[i]);
+	    ++i;
+	}
+	krb5_xfree(ldap_context->certificates);
+    }
+
+    k5_mutex_destroy(&ldap_context->hndl_lock);
+
+    krb5_xfree(ldap_context);
+    return(0);
+}
+
+
+/*
+ * check to see if the principal belongs to the default realm.
+ * The default realm is present in the krb5_ldap_context structure.
+ * The principal has a realm portion. This realm portion is compared with the default realm
+ * to check whether the principal belong to the default realm.
+ * Return 0 if principal belongs to default realm else 1.
+ */
+
+krb5_error_code
+is_principal_in_realm(ldap_context, searchfor)
+    krb5_ldap_context          *ldap_context;
+    krb5_const_principal       searchfor;
+{
+    size_t                      defrealmlen=0;
+    char                        *defrealm=NULL;
+
+#define FIND_MAX(a,b) ((a) > (b) ? (a) : (b))
+
+    defrealmlen = strlen(ldap_context->lrparams->realm_name);
+    defrealm = ldap_context->lrparams->realm_name;
+
+    /*
+     * Care should be taken for inter-realm principals as the default
+     * realm can exist in the realm part of the principal name or can
+     * also exist in the second portion of the name part.  However, if
+     * the default realm exist in the second part of the principal
+     * portion, then the first portion of the principal name SHOULD be
+     * "krbtgt".  All this check is done in the immediate block.
+     */
+    if (searchfor->length == 2)
+	if ((strncasecmp(searchfor->data[0].data, "krbtgt",
+			 FIND_MAX(searchfor->data[0].length, strlen("krbtgt"))) == 0) &&
+	    (strncasecmp(searchfor->data[1].data, defrealm,
+			 FIND_MAX(searchfor->data[1].length, defrealmlen)) == 0))
+	    return 0;
+
+    /* first check the length, if they are not equal, then they are not same */
+    if (strlen(defrealm) != searchfor->realm.length)
+	return 1;
+
+    /* if the length is equal, check for the contents */
+    if (strncmp(defrealm, searchfor->realm.data,
+		searchfor->realm.length) != 0)
+	return 1;
+    /* if we are here, then the realm portions match, return 0 */
+    return 0;
+}
+
+
+/*
+ * Deduce the subtree information from the context. A realm can have
+ * multiple subtrees.
+ * 1. the Realm container
+ * 2. the actual subtrees associated with the Realm
+ *
+ * However, there are some conditions to be considered to deduce the
+ * actual subtree/s associated with the realm.  The conditions are as
+ * follows:
+ * 1. If the subtree information of the Realm is [Root] or NULL (that
+ *    is internal a [Root]) then the realm has only one subtree
+ *    i.e [Root], i.e. whole of the tree.
+ * 2. If the subtree information of the Realm is missing/absent, then the
+ *    realm has only one, i.e., the Realm container.  NOTE: In all cases
+ *    Realm container SHOULD be the one among the subtrees or the only
+ *    one subtree.
+ * 3. The subtree information of the realm is overlapping the realm
+ *    container of the realm, then the realm has only one subtree and
+ *    it is the subtree information associated with the realm.
+ */
+krb5_error_code
+krb5_get_subtree_info(ldap_context, subtreearr, ntree)
+    krb5_ldap_context           *ldap_context;
+    char                        ***subtreearr;
+    unsigned int                *ntree;
+{
+    int                         st=0, i=0, subtreecount=0;
+    int				ncount=0, search_scope=0;
+    char                        **subtree=NULL, *realm_cont_dn=NULL;
+    char                        **subtarr=NULL;
+    char                        *containerref=NULL;
+    char 			**newsubtree=NULL;
+
+    containerref = ldap_context->lrparams->containerref;
+    subtree = ldap_context->lrparams->subtree;
+    realm_cont_dn = ldap_context->lrparams->realmdn;
+    subtreecount = ldap_context->lrparams->subtreecount;
+    search_scope = ldap_context->lrparams->search_scope;
+
+    subtarr = (char **) malloc(sizeof(char *) * (subtreecount + 1 /*realm dn*/ + 1 /*containerref*/ + 1));
+    if (subtarr == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    memset(subtarr, 0, (sizeof(char *) * (subtreecount+1+1+1)));
+
+    /* get the complete subtree list */
+    for (i=0; i<subtreecount && subtree[i]!=NULL; i++) {
+	subtarr[i] = strdup(subtree[i]);
+	if (subtarr[i] == NULL) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+    }
+
+    subtarr[i] = strdup(realm_cont_dn);
+    if (subtarr[i++] == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    if (containerref != NULL) {
+	subtarr[i] = strdup(containerref);
+	if (subtarr[i++] == NULL) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+    }
+
+    ncount = i;
+    newsubtree = (char **) malloc(sizeof(char *) * (ncount + 1));
+    if (newsubtree == NULL) {
+        st = ENOMEM;
+        goto cleanup;
+    }
+    memset(newsubtree, 0, (sizeof(char *) * (ncount+1)));
+    if ((st = remove_overlapping_subtrees(subtarr, newsubtree, &ncount,
+		search_scope)) != 0) {
+        goto cleanup;
+    }
+
+    *ntree = ncount;
+    *subtreearr = newsubtree;
+
+cleanup:
+    if (subtarr != NULL) {
+	for (i=0; subtarr[i] != NULL; i++)
+	    free(subtarr[i]);
+	free(subtarr);
+    }
+
+    if (st != 0) {
+        if (newsubtree != NULL) {
+	    for (i=0; newsubtree[i] != NULL; i++)
+	        free(newsubtree[i]);
+	    free(newsubtree);
+        }
+    }
+    return st;
+}
+
+/*
+ * This function appends the content with a type into the tl_data
+ * structure.  Based on the type the length of the content is either
+ * pre-defined or computed from the content.  Returns 0 in case of
+ * success and 1 if the type associated with the content is undefined.
+ */
+
+krb5_error_code
+store_tl_data(tl_data, tl_type, value)
+    krb5_tl_data                *tl_data;
+    int                         tl_type;
+    void                        *value;
+{
+    unsigned int                currlen=0, tldatalen=0;
+    unsigned char               *curr=NULL;
+    void                        *reallocptr=NULL;
+
+    tl_data->tl_data_type = KDB_TL_USER_INFO;
+    switch (tl_type) {
+    case KDB_TL_PRINCCOUNT:
+    case KDB_TL_PRINCTYPE:
+    case KDB_TL_MASK:
+    {
+	int *iptr = (int *)value;
+	int ivalue = *iptr;
+
+	currlen = tl_data->tl_data_length;
+	tl_data->tl_data_length += 1 + 2 + 2;
+	/* allocate required memory */
+	reallocptr = tl_data->tl_data_contents;
+	tl_data->tl_data_contents = realloc(tl_data->tl_data_contents,
+					    tl_data->tl_data_length);
+	if (tl_data->tl_data_contents == NULL) {
+	    if (reallocptr)
+		free (reallocptr);
+	    return ENOMEM;
+	}
+	curr = (tl_data->tl_data_contents + currlen);
+
+	/* store the tl_type value */
+	memset(curr, tl_type, 1);
+	curr += 1;
+	/* store the content length */
+	tldatalen = 2;
+	STORE16_INT(curr, tldatalen);
+	curr += 2;
+	/* store the content */
+	STORE16_INT(curr, ivalue);
+	curr += 2;
+	break;
+    }
+
+    case KDB_TL_USERDN:
+    case KDB_TL_LINKDN:
+    {
+	char *cptr = (char *)value;
+
+	currlen = tl_data->tl_data_length;
+	tl_data->tl_data_length += 1 + 2 + strlen(cptr);
+	/* allocate required memory */
+	reallocptr = tl_data->tl_data_contents;
+	tl_data->tl_data_contents = realloc(tl_data->tl_data_contents,
+					    tl_data->tl_data_length);
+	if (tl_data->tl_data_contents == NULL) {
+	    if (reallocptr)
+		free (reallocptr);
+	    return ENOMEM;
+	}
+	curr = (tl_data->tl_data_contents + currlen);
+
+	/* store the tl_type value */
+	memset(curr, tl_type, 1);
+	curr += 1;
+	/* store the content length */
+	tldatalen = strlen(cptr);
+	STORE16_INT(curr, tldatalen);
+	curr += 2;
+	/* store the content */
+	memcpy(curr, cptr, tldatalen);
+	curr += tldatalen;
+	break;
+    }
+
+    default:
+	return 1;
+
+    }
+    return 0;
+}
+
+/*
+ * This function scans the tl_data structure to get the value of a
+ * type defined by the tl_type (second parameter).  The tl_data
+ * structure has all the data in the tl_data_contents member.  The
+ * format of the tl_data_contents is as follows.  The first byte
+ * defines the type of the content that follows.  The next 2 bytes
+ * define the size n (in terms of bytes) of the content that
+ * follows.  The next n bytes define the content itself.
+ */
+
+krb5_error_code
+decode_tl_data(tl_data, tl_type, data)
+    krb5_tl_data                *tl_data;
+    int                         tl_type;
+    void                        **data;
+{
+    int                         subtype=0, i=0, limit=10;
+    unsigned int                sublen=0;
+    unsigned char               *curr=NULL;
+    int                         *intptr=NULL;
+    long                        *longptr=NULL;
+    char                        *DN=NULL, **DNarr=NULL;
+    krb5_error_code             st=-1;
+
+    *data = NULL;
+
+    curr = tl_data->tl_data_contents;
+    while (curr < (tl_data->tl_data_contents + tl_data->tl_data_length)) {
+
+	/* get the type of the content */
+	subtype = (int) curr[0];
+	/* forward by 1 byte*/
+	curr += 1;
+
+	if (subtype == tl_type) {
+	    switch (subtype) {
+
+	    case KDB_TL_PRINCCOUNT:
+	    case KDB_TL_PRINCTYPE:
+	    case KDB_TL_MASK:
+		/* get the length of the content */
+		UNSTORE16_INT(curr, sublen);
+		/* forward by 2 bytes */
+		curr += 2;
+		/* get the actual content */
+		if (sublen == 2) {
+		    /* intptr = malloc(sublen);	  */
+		    intptr = malloc(sizeof(krb5_int32));
+		    if (intptr == NULL)
+			return ENOMEM;
+		    memset(intptr, 0, sublen);
+		    UNSTORE16_INT(curr, (*intptr));
+		    *data = intptr;
+		} else {
+		    longptr = malloc(sublen);
+		    if (longptr == NULL)
+			return ENOMEM;
+		    memset(longptr, 0, sublen);
+		    UNSTORE32_INT(curr, (*longptr));
+		    *data = longptr;
+		}
+		curr += sublen;
+		st = 0;
+		return st;
+		break;
+
+	    case KDB_TL_CONTAINERDN:
+	    case KDB_TL_USERDN:
+		/* get the length of the content */
+		UNSTORE16_INT(curr, sublen);
+		/* forward by 2 bytes */
+		curr += 2;
+		DN = malloc (sublen + 1);
+		if (DN == NULL)
+		    return ENOMEM;
+		memcpy(DN, curr, sublen);
+		DN[sublen] = 0;
+		*data = DN;
+		curr += sublen;
+		st = 0;
+		return st;
+		break;
+
+	    case KDB_TL_LINKDN:
+		if (DNarr == NULL) {
+		    DNarr = calloc(limit, sizeof(char *));
+		    if (DNarr == NULL)
+			return ENOMEM;
+		}
+		if (i == limit-1) {
+		    limit *= 2;
+		    DNarr = realloc(DNarr, sizeof(char *) * (limit));
+		    if (DNarr == NULL)
+			return ENOMEM;
+		}
+
+		/* get the length of the content */
+		UNSTORE16_INT(curr, sublen);
+		/* forward by 2 bytes */
+		curr += 2;
+		DNarr[i] = malloc (sublen + 1);
+		if (DNarr[i] == NULL)
+		    return ENOMEM;
+		memcpy(DNarr[i], curr, sublen);
+		DNarr[i][sublen] = 0;
+		++i;
+		curr += sublen;
+		*data = DNarr;
+		st=0;
+		break;
+	    }
+	} else {
+	    /* move to the current content block */
+	    UNSTORE16_INT(curr, sublen);
+	    curr += 2 + sublen;
+	}
+    }
+    return st;
+}
+
+/*
+ * wrapper routines for decode_tl_data
+ */
+static krb5_error_code
+krb5_get_int_from_tl_data(context, entries, type, intval)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    int                         type;
+    int                         *intval;
+{
+    krb5_error_code             st=0;
+    krb5_tl_data                tl_data;
+    void                        *voidptr=NULL;
+    int                         *intptr=NULL;
+
+    tl_data.tl_data_type = KDB_TL_USER_INFO;
+    if (((st=krb5_dbe_lookup_tl_data(context, entries, &tl_data)) != 0) || tl_data.tl_data_length == 0)
+	goto cleanup;
+
+    if (decode_tl_data(&tl_data, type, &voidptr) == 0) {
+	intptr = (int *) voidptr;
+	*intval = *intptr;
+	free(intptr);
+    }
+
+cleanup:
+    return st;
+}
+
+/*
+ * Get the mask representing the attributes set on the directory
+ * object (user, policy ...).
+ */
+krb5_error_code
+krb5_get_attributes_mask(context, entries, mask)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    int                         *mask;
+{
+    return krb5_get_int_from_tl_data(context, entries, KDB_TL_MASK, mask);
+}
+
+krb5_error_code
+krb5_get_princ_type(context, entries, ptype)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    int                         *ptype;
+{
+    return krb5_get_int_from_tl_data(context, entries, KDB_TL_PRINCTYPE, ptype);
+}
+
+krb5_error_code
+krb5_get_princ_count(context, entries, pcount)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    int                         *pcount;
+{
+    return krb5_get_int_from_tl_data(context, entries, KDB_TL_PRINCCOUNT, pcount);
+}
+
+krb5_error_code
+krb5_get_linkdn(context, entries, link_dn)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    char                        ***link_dn;
+{
+    krb5_error_code             st=0;
+    krb5_tl_data                tl_data;
+    void                        *voidptr=NULL;
+
+    *link_dn = NULL;
+    tl_data.tl_data_type = KDB_TL_USER_INFO;
+    if (((st=krb5_dbe_lookup_tl_data(context, entries, &tl_data)) != 0) || tl_data.tl_data_length == 0)
+	goto cleanup;
+
+    if (decode_tl_data(&tl_data, KDB_TL_LINKDN, &voidptr) == 0) {
+	*link_dn = (char **) voidptr;
+    }
+
+cleanup:
+    return st;
+}
+
+static krb5_error_code
+krb5_get_str_from_tl_data(context, entries, type, strval)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    int                         type;
+    char                        **strval;
+{
+    krb5_error_code             st=0;
+    krb5_tl_data                tl_data;
+    void                        *voidptr=NULL;
+
+    if (type != KDB_TL_USERDN && type != KDB_TL_CONTAINERDN) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    tl_data.tl_data_type = KDB_TL_USER_INFO;
+    if (((st=krb5_dbe_lookup_tl_data(context, entries, &tl_data)) != 0) || tl_data.tl_data_length == 0)
+	goto cleanup;
+
+    if (decode_tl_data(&tl_data, type, &voidptr) == 0) {
+	*strval = (char *) voidptr;
+    }
+
+cleanup:
+    return st;
+}
+
+krb5_error_code
+krb5_get_userdn(context, entries, userdn)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    char                        **userdn;
+{
+    *userdn = NULL;
+    return krb5_get_str_from_tl_data(context, entries, KDB_TL_USERDN, userdn);
+}
+
+krb5_error_code
+krb5_get_containerdn(context, entries, containerdn)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    char                        **containerdn;
+{
+    *containerdn = NULL;
+    return krb5_get_str_from_tl_data(context, entries, KDB_TL_CONTAINERDN, containerdn);
+}
+
+/*
+ * This function reads the attribute values (if the attribute is
+ * non-null) from the dn.  The read attribute values is compared
+ * aganist the attrvalues passed to the function and a bit mask is set
+ * for all the matching attributes (attributes existing in both list).
+ * The bit to be set is selected such that the index of the attribute
+ * in the attrvalues parameter is the position of the bit.  For ex:
+ * the first element in the attrvalues is present in both list shall
+ * set the LSB of the bit mask.
+ *
+ * In case if either the attribute or the attrvalues parameter to the
+ * function is NULL, then the existence of the object is considered
+ * and appropriate status is returned back.
+ */
+
+krb5_error_code
+checkattributevalue (ld, dn, attribute, attrvalues, mask)
+    LDAP                        *ld;
+    char                        *dn;
+    char                        *attribute;
+    char                        **attrvalues;
+    int                         *mask;
+{
+    int                         st=0, one=1;
+    char                        **values=NULL, *attributes[2] = {NULL};
+    LDAPMessage                 *result=NULL, *entry=NULL;
+
+    if (strlen(dn) == 0) {
+	st = set_ldap_error(0, LDAP_NO_SUCH_OBJECT, OP_SEARCH);
+	return st;
+    }
+
+    attributes[0] = attribute;
+
+    /* read the attribute values from the dn */
+    if ((st = ldap_search_ext_s(ld,
+				dn,
+				LDAP_SCOPE_BASE,
+				0,
+				attributes,
+				0,
+				NULL,
+				NULL,
+				&timelimit,
+				LDAP_NO_LIMIT,
+				&result)) != LDAP_SUCCESS) {
+	st = set_ldap_error(0, st, OP_SEARCH);
+	return st;
+    }
+
+    /*
+     * If the attribute/attrvalues is NULL, then check for the
+     * existence of the object alone.
+     */
+    if (attribute == NULL || attrvalues == NULL)
+	goto cleanup;
+
+    /* reset the bit mask */
+    *mask = 0;
+
+    if ((entry=ldap_first_entry(ld, result)) != NULL) {
+	/* read the attribute values */
+	if ((values=ldap_get_values(ld, entry, attribute)) != NULL) {
+	    int i,j;
+
+	    /*
+	     * Compare the read attribute values with the attrvalues
+	     * array and set the appropriate bit mask.
+	     */
+	    for (j=0; attrvalues[j]; ++j) {
+		for (i=0; values[i]; ++i) {
+		    if (strcasecmp(values[i], attrvalues[j]) == 0) {
+			*mask |= (one<<j);
+			break;
+		    }
+		}
+	    }
+	    ldap_value_free(values);
+	}
+    }
+
+cleanup:
+    ldap_msgfree(result);
+    return st;
+}
+
+
+/*
+ * This function updates a single attribute with a single value of a
+ * specified dn.  This function is mainly used to update
+ * krbRealmReferences, krbKdcServers, krbAdminServers... when KDC,
+ * ADMIN, PASSWD servers are associated with some realms or vice
+ * versa.
+ */
+
+krb5_error_code
+updateAttribute (ld, dn, attribute, value)
+    LDAP                        *ld;
+    char                        *dn;
+    char                        *attribute;
+    char                        *value;
+{
+    int                         st=0;
+    LDAPMod                     modAttr, *mods[2]={NULL};
+    char                        *values[2]={NULL};
+
+    values[0] = value;
+
+    /* data to update the {attr,attrval} combination */
+    memset(&modAttr, 0, sizeof(modAttr));
+    modAttr.mod_type = attribute;
+    modAttr.mod_op = LDAP_MOD_ADD;
+    modAttr.mod_values = values;
+    mods[0] = &modAttr;
+
+    /* ldap modify operation */
+    st = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
+
+    /* if the {attr,attrval} combination is already present return a success
+     * LDAP_ALREADY_EXISTS is for single-valued attribute
+     * LDAP_TYPE_OR_VALUE_EXISTS is for multi-valued attribute
+     */
+    if (st == LDAP_ALREADY_EXISTS || st == LDAP_TYPE_OR_VALUE_EXISTS)
+	st = 0;
+
+    if (st != 0) {
+	st = set_ldap_error (0, st, OP_MOD);
+    }
+
+    return st;
+}
+
+/*
+ * This function deletes a single attribute with a single value of a
+ * specified dn.  This function is mainly used to delete
+ * krbRealmReferences, krbKdcServers, krbAdminServers... when KDC,
+ * ADMIN, PASSWD servers are disassociated with some realms or vice
+ * versa.
+ */
+
+krb5_error_code
+deleteAttribute (ld, dn, attribute, value)
+    LDAP                        *ld;
+    char                        *dn;
+    char                        *attribute;
+    char                        *value;
+{
+    krb5_error_code             st=0;
+    LDAPMod                     modAttr, *mods[2]={NULL};
+    char                        *values[2]={NULL};
+
+    values[0] = value;
+
+    /* data to delete the {attr,attrval} combination */
+    memset(&modAttr, 0, sizeof(modAttr));
+    modAttr.mod_type = attribute;
+    modAttr.mod_op = LDAP_MOD_DELETE;
+    modAttr.mod_values = values;
+    mods[0] = &modAttr;
+
+    /* ldap modify operation */
+    st = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
+
+    /* if either the attribute or the attribute value is missing return a success */
+    if (st == LDAP_NO_SUCH_ATTRIBUTE || st == LDAP_UNDEFINED_TYPE)
+	st = 0;
+
+    if (st != 0) {
+	st = set_ldap_error (0, st, OP_MOD);
+    }
+
+    return st;
+}
+
+
+/*
+ * This function takes in 2 string arrays, compares them to remove the
+ * matching entries.  The first array is the original list and the
+ * second array is the modified list.  Removing the matching entries
+ * will result in a reduced array, where the left over first array
+ * elements are the deleted entries and the left over second array
+ * elements are the added entries.  These additions and deletions has
+ * resulted in the modified second array.
+ */
+
+krb5_error_code
+disjoint_members(src, dest)
+    char                        **src;
+    char                        **dest;
+{
+    int                         i=0, j=0, slen=0, dlen=0;
+
+    /* validate the input parameters */
+    if (src == NULL || dest == NULL)
+	return 0;
+
+    /* compute the first array length */
+    for (i=0;src[i]; ++i)
+	;
+
+    /* return if the length is 0 */
+    if (i==0)
+	return 0;
+
+    /* index of the last element and also the length of the array */
+    slen = i-1;
+
+    /* compute the second array length */
+    for (i=0;dest[i]; ++i)
+	;
+
+    /* return if the length is 0 */
+    if (i==0)
+	return 0;
+
+    /* index of the last element and also the length of the array */
+    dlen = i-1;
+
+    /* check for the similar elements and delete them from both the arrays */
+    for (i=0; src[i]; ++i) {
+
+	for (j=0; dest[j]; ++j) {
+
+	    /* if the element are same */
+	    if (strcasecmp(src[i], dest[j]) == 0) {
+		/*
+		 * If the matched element is in the middle, then copy
+		 * the last element to the matched index.
+		 */
+		if (i != slen) {
+		    free (src[i]);
+		    src[i] = src[slen];
+		    src[slen] = NULL;
+		} else {
+		    /*
+		     * If the matched element is the last, free it and
+		     * set it to NULL.
+		     */
+		    free (src[i]);
+		    src[i] = NULL;
+		}
+		/* reduce the array length by 1 */
+		slen -= 1;
+
+		/* repeat the same processing for the second array too */
+		if (j != dlen) {
+		    free(dest[j]);
+		    dest[j] = dest[dlen];
+		    dest[dlen] = NULL;
+		} else {
+		    free(dest[j]);
+		    dest[j] = NULL;
+		}
+		dlen -=1;
+
+		/*
+		 * The source array is reduced by 1, so reduce the
+		 * index variable used for source array by 1.  No need
+		 * to adjust the second array index variable as it is
+		 * reset while entering the inner loop.
+		 */
+		i -= 1;
+		break;
+	    }
+	}
+    }
+    return 0;
+}
+
+/*
+ * This function replicates the contents of the src array for later
+ * use. Mostly the contents of the src array is obtained from a
+ * ldap_search operation and the contents are required for later use.
+ */
+
+krb5_error_code
+copy_arrays(src, dest, count)
+    char                        **src;
+    char                        ***dest;
+    int                         count;
+{
+    krb5_error_code             st=0;
+    int                         i=0;
+
+    /* validate the input parameters */
+    if (src == NULL || dest == NULL)
+	return 0;
+
+    /* allocate memory for the dest array */
+    *dest = (char **) calloc((unsigned) count+1, sizeof(char *));
+    if (*dest == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    /* copy the members from src to dest array. */
+    for (i=0; i < count && src[i] != NULL; ++i) {
+	(*dest)[i] = strdup(src[i]);
+	if ((*dest)[i] == NULL) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+    }
+
+cleanup:
+    /* in case of error free up everything and return */
+    if (st != 0) {
+	if (*dest != NULL) {
+	    for (i=0; (*dest)[i]; ++i) {
+		free ((*dest)[i]);
+		(*dest)[i] = NULL;
+	    }
+	    free (*dest);
+	    *dest = NULL;
+	}
+    }
+    return st;
+}
+
+static krb5_error_code
+getepochtime(strtime, epochtime)
+    char              *strtime;
+    krb5_timestamp    *epochtime;
+{
+    struct tm           tme;
+
+    memset(&tme, 0, sizeof(tme));
+    if (strptime(strtime,"%Y%m%d%H%M%SZ", &tme) == NULL) {
+	*epochtime = 0;
+	return EINVAL;
+    }
+    *epochtime = krb5int_gmt_mktime(&tme);
+    return 0;
+}
+
+/*
+ * krb5_ldap_get_value() - get the integer value of the attribute
+ * Returns, 0 if the attribute is present, 1 if the attribute is missing.
+ * The retval is 0 if the attribute is missing.
+ */
+
+krb5_error_code
+krb5_ldap_get_value(ld, ent, attribute, retval)
+    LDAP                        *ld;
+    LDAPMessage                 *ent;
+    char                        *attribute;
+    int                         *retval;
+{
+    char                           **values=NULL;
+
+    *retval = 0;
+    values=ldap_get_values(ld, ent, attribute);
+    if (values != NULL) {
+	if (values[0] != NULL)
+	    *retval = atoi(values[0]);
+	ldap_value_free(values);
+	return 0;
+    }
+    return 1;
+}
+
+/*
+ * krb5_ldap_get_string() - Returns the first string of the
+ * attribute.  Intended to
+ *
+ *
+ */
+krb5_error_code
+krb5_ldap_get_string(ld, ent, attribute, retstr, attr_present)
+    LDAP                        *ld;
+    LDAPMessage                 *ent;
+    char                        *attribute;
+    char                        **retstr;
+    krb5_boolean                *attr_present;
+{
+    char                           **values=NULL;
+    krb5_error_code                st=0;
+
+    *retstr = NULL;
+    if (attr_present != NULL)
+	*attr_present = FALSE;
+
+    values=ldap_get_values(ld, ent, attribute);
+    if (values != NULL) {
+	if (values[0] != NULL) {
+	    if (attr_present!= NULL)
+		*attr_present = TRUE;
+	    *retstr = strdup(values[0]);
+	    if (*retstr == NULL)
+		st = ENOMEM;
+	}
+	ldap_value_free(values);
+    }
+    return st;
+}
+
+/*
+ * krb5_ldap_get_strings() - Returns all the values
+ * of the attribute.
+ */
+krb5_error_code
+krb5_ldap_get_strings(ld, ent, attribute, retarr, attr_present)
+    LDAP                        *ld;
+    LDAPMessage                 *ent;
+    char                        *attribute;
+    char                        ***retarr;
+    krb5_boolean                *attr_present;
+{
+    char                        **values=NULL;
+    krb5_error_code             st=0;
+    unsigned int                i=0, count=0;
+
+    *retarr = NULL;
+    if (attr_present != NULL)
+	*attr_present = FALSE;
+
+    values=ldap_get_values(ld, ent, attribute);
+    if (values != NULL) {
+	if (attr_present != NULL)
+	    *attr_present = TRUE;
+
+	count = ldap_count_values(values);
+	*retarr  = (char **) calloc(count+1, sizeof(char *));
+	if (*retarr == NULL) {
+	    st = ENOMEM;
+	    return st;
+	}
+	for (i=0; i< count; ++i) {
+	    (*retarr)[i] = strdup(values[i]);
+	    if ((*retarr)[i] == NULL) {
+		st = ENOMEM;
+		goto cleanup;
+	    }
+	}
+	ldap_value_free(values);
+    }
+
+cleanup:
+    if (st != 0) {
+	if (*retarr != NULL) {
+	    for (i=0; i< count; ++i)
+		if ((*retarr)[i] != NULL)
+		    free ((*retarr)[i]);
+	    free (*retarr);
+	}
+    }
+    return st;
+}
+
+krb5_error_code
+krb5_ldap_get_time(ld, ent, attribute, rettime, attr_present)
+    LDAP                        *ld;
+    LDAPMessage                 *ent;
+    char                        *attribute;
+    krb5_timestamp              *rettime;
+    krb5_boolean                *attr_present;
+{
+    char                         **values=NULL;
+    krb5_error_code              st=0;
+
+    *rettime = 0;
+    *attr_present = FALSE;
+
+    values=ldap_get_values(ld, ent, attribute);
+    if (values != NULL) {
+	if (values[0] != NULL) {
+	    *attr_present = TRUE;
+	    st = getepochtime(values[0], rettime);
+	}
+	ldap_value_free(values);
+    }
+    return st;
+}
+
+/*
+ * Function to allocate, set the values of LDAPMod structure. The
+ * LDAPMod structure is then added to the array at the ind
+ */
+
+krb5_error_code
+krb5_add_member(mods, count)
+    LDAPMod          ***mods;
+    int              *count;
+{
+    int i=0;
+    LDAPMod **lmods=NULL;
+
+    if ((*mods) != NULL) {
+	for (;(*mods)[i] != NULL; ++i)
+	    ;
+    }
+    lmods = (LDAPMod **) realloc((*mods), (2+i) * sizeof(LDAPMod *));
+    if (lmods == NULL)
+	return ENOMEM;
+
+    *mods = lmods;
+    (*mods)[i+1] = NULL;
+    (*mods)[i] = (LDAPMod *) calloc(1, sizeof (LDAPMod));
+    if ((*mods)[i] == NULL)
+	return ENOMEM;
+    *count = i;
+    return 0;
+}
+
+krb5_error_code
+krb5_add_str_mem_ldap_mod(mods, attribute, op, values)
+    LDAPMod  ***mods;
+    char     *attribute;
+    int      op;
+    char     **values;
+
+{
+    int i=0, j=0;
+    krb5_error_code   st=0;
+
+    if ((st=krb5_add_member(mods, &i)) != 0)
+	return st;
+
+    (*mods)[i]->mod_type = strdup(attribute);
+    if ((*mods)[i]->mod_type == NULL)
+	return ENOMEM;
+    (*mods)[i]->mod_op = op;
+
+    (*mods)[i]->mod_values = NULL;
+
+    if (values != NULL) {
+	for (j=0; values[j] != NULL; ++j)
+	    ;
+	(*mods)[i]->mod_values = malloc (sizeof(char *) * (j+1));
+	if ((*mods)[i]->mod_values == NULL)
+	    return ENOMEM;
+
+	for (j=0; values[j] != NULL; ++j) {
+	    (*mods)[i]->mod_values[j] = strdup(values[j]);
+	    if ((*mods)[i]->mod_values[j] == NULL)
+		return ENOMEM;
+	}
+	(*mods)[i]->mod_values[j] = NULL;
+    }
+    return 0;
+}
+
+krb5_error_code
+krb5_add_ber_mem_ldap_mod(mods, attribute, op, ber_values)
+    LDAPMod  ***mods;
+    char     *attribute;
+    int      op;
+    struct berval **ber_values;
+
+{
+    int i=0, j=0;
+    krb5_error_code   st=0;
+
+    if ((st=krb5_add_member(mods, &i)) != 0)
+	return st;
+
+    (*mods)[i]->mod_type = strdup(attribute);
+    if ((*mods)[i]->mod_type == NULL)
+	return ENOMEM;
+    (*mods)[i]->mod_op = op;
+
+    for (j=0; ber_values[j] != NULL; ++j)
+	;
+    (*mods)[i]->mod_bvalues = malloc (sizeof(struct berval *) * (j+1));
+    if ((*mods)[i]->mod_bvalues == NULL)
+	return ENOMEM;
+
+    for (j=0; ber_values[j] != NULL; ++j) {
+	(*mods)[i]->mod_bvalues[j] = calloc(1, sizeof(struct berval));
+	if ((*mods)[i]->mod_bvalues[j] == NULL)
+	    return ENOMEM;
+
+	(*mods)[i]->mod_bvalues[j]->bv_len = ber_values[j]->bv_len;
+	(*mods)[i]->mod_bvalues[j]->bv_val = malloc((*mods)[i]->mod_bvalues[j]->bv_len);
+	if ((*mods)[i]->mod_bvalues[j]->bv_val == NULL)
+	    return ENOMEM;
+
+	memcpy((*mods)[i]->mod_bvalues[j]->bv_val, ber_values[j]->bv_val,
+	       ber_values[j]->bv_len);
+    }
+    (*mods)[i]->mod_bvalues[j] = NULL;
+    return 0;
+}
+
+static inline char *
+format_d (int val)
+{
+    char tmpbuf[2+3*sizeof(val)];
+    sprintf(tmpbuf, "%d", val);
+    return strdup(tmpbuf);
+}
+
+krb5_error_code
+krb5_add_int_arr_mem_ldap_mod(mods, attribute, op, value)
+    LDAPMod  ***mods;
+    char     *attribute;
+    int      op;
+    int      *value;
+
+{
+    int i=0, j=0;
+    krb5_error_code   st=0;
+
+    if ((st=krb5_add_member(mods, &i)) != 0)
+	return st;
+
+    (*mods)[i]->mod_type = strdup(attribute);
+    if ((*mods)[i]->mod_type == NULL)
+	return ENOMEM;
+    (*mods)[i]->mod_op = op;
+
+    for (j=0; value[j] != -1; ++j)
+	;
+
+    (*mods)[i]->mod_values = malloc(sizeof(char *) * (j+1));
+
+    for (j=0; value[j] != -1; ++j) {
+	if (((*mods)[i]->mod_values[j] = format_d(value[j])) == NULL)
+	    return ENOMEM;
+    }
+    (*mods)[i]->mod_values[j] = NULL;
+    return 0;
+}
+
+krb5_error_code
+krb5_add_int_mem_ldap_mod(mods, attribute, op, value)
+    LDAPMod  ***mods;
+    char     *attribute;
+    int      op;
+    int      value;
+
+{
+    int i=0;
+    krb5_error_code      st=0;
+
+    if ((st=krb5_add_member(mods, &i)) != 0)
+	return st;
+
+    (*mods)[i]->mod_type = strdup(attribute);
+    if ((*mods)[i]->mod_type == NULL)
+	return ENOMEM;
+
+    (*mods)[i]->mod_op = op;
+    (*mods)[i]->mod_values = calloc (2, sizeof(char *));
+    if (((*mods)[i]->mod_values[0] = format_d(value)) == NULL)
+	return ENOMEM;
+    return 0;
+}
+
+krb5_error_code
+krb5_ldap_set_option(krb5_context kcontext, int option, void *value)
+{
+    krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
+    krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status));
+    return status;
+}
+
+krb5_error_code
+krb5_ldap_lock(krb5_context kcontext, int mode)
+{
+    krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
+    krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status));
+    return status;
+}
+
+krb5_error_code
+krb5_ldap_unlock(krb5_context kcontext)
+{
+    krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
+    krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status));
+    return status;
+}
+
+krb5_error_code
+krb5_ldap_supported_realms(krb5_context kcontext, char **realms)
+{
+    krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
+    krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status));
+    return status;
+}
+
+krb5_error_code
+krb5_ldap_free_supported_realms(krb5_context kcontext, char **realms)
+{
+    krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
+    krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status));
+    return status;
+}
+
+const char *
+krb5_ldap_errcode_2_string(krb5_context kcontext, long err_code)
+{
+    return krb5_get_error_message(kcontext, err_code);
+}
+
+void
+krb5_ldap_release_errcode_string(krb5_context kcontext, const char *msg)
+{
+    krb5_free_error_message(kcontext, msg);
+}
+
+
+/*
+ * Get the number of times an object has been referred to in a realm. this is
+ * needed to find out if deleting the attribute will cause dangling links.
+ *
+ * An LDAP handle may be optionally specified to prevent race condition - there
+ * are a limited number of LDAP handles.
+ */
+krb5_error_code
+krb5_ldap_get_reference_count (krb5_context context, char *dn, char *refattr,
+			       int *count, LDAP *ld)
+{
+    int                         st = 0, tempst = 0, gothandle = 0;
+    unsigned int		i, ntrees;
+    char                        *refcntattr[2];
+    char                        *filter = NULL;
+    char                        **subtree = NULL, *ptr = NULL;
+    kdb5_dal_handle             *dal_handle = NULL;
+    krb5_ldap_context           *ldap_context = NULL;
+    krb5_ldap_server_handle     *ldap_server_handle = NULL;
+    LDAPMessage                 *result = NULL;
+
+
+    if (dn == NULL || refattr == NULL) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+    if (ld == NULL) {
+	GET_HANDLE();
+	gothandle = 1;
+    }
+
+    refcntattr [0] = refattr;
+    refcntattr [1] = NULL;
+
+    ptr = ldap_filter_correct (dn);
+    if (ptr == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    filter = (char *) malloc (strlen (refattr) + strlen (ptr) + 2);
+    if (filter == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    sprintf (filter, "%s=%s", refattr, ptr);
+
+    if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees)) != 0)
+	goto cleanup;
+
+    for (i = 0, *count = 0; i < ntrees; i++) {
+	int n;
+
+	LDAP_SEARCH(subtree[i],
+		    LDAP_SCOPE_SUBTREE,
+		    filter,
+		    refcntattr);
+	n = ldap_count_entries (ld, result);
+	if (n == -1) {
+	    int ret, errcode = 0;
+	    ret = ldap_parse_result (ld, result, &errcode, NULL, NULL, NULL, NULL, 0);
+	    if (ret != LDAP_SUCCESS)
+		errcode = ret;
+	    st = translate_ldap_error (errcode, OP_SEARCH);
+	    goto cleanup;
+	}
+
+	ldap_msgfree(result);
+	result = NULL;
+
+	*count += n;
+    }
+
+cleanup:
+    if (filter != NULL)
+	free (filter);
+
+    if (result != NULL)
+	ldap_msgfree (result);
+
+    if (subtree != NULL) {
+	for (i = 0; i < ntrees; i++)
+	    free (subtree[i]);
+	free (subtree);
+    }
+
+    if (ptr != NULL)
+	free (ptr);
+
+    if (gothandle == 1)
+	krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+
+    return st;
+}
+
+/*
+ * For now, policy objects are expected to be directly under the realm
+ * container.
+ */
+krb5_error_code krb5_ldap_policydn_to_name (context, policy_dn, name)
+    krb5_context                context;
+    char                        *policy_dn;
+    char                        **name;
+{
+    int len1, len2;
+    krb5_error_code             st = 0;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+
+    SETUP_CONTEXT();
+
+    if (ldap_context->lrparams->realmdn == NULL) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    len1 = strlen (ldap_context->lrparams->realmdn);
+    len2 = strlen (policy_dn);
+    if (len1 == 0 || len2 == 0 || len1 > len2) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    if (strcmp (ldap_context->lrparams->realmdn, policy_dn + (len2 - len1)) != 0) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+#if defined HAVE_LDAP_STR2DN
+    {
+	char *rdn;
+	LDAPDN dn;
+	rdn = strndup(policy_dn, len2 - len1 - 1); /* 1 character for ',' */
+
+	if (ldap_str2dn (rdn, &dn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PEDANTIC) != 0) {
+	    st = EINVAL;
+	    goto cleanup;
+	}
+	if (dn[0] == NULL || dn[1] != NULL)
+	    st = EINVAL;
+	else if (strcasecmp (dn[0][0]->la_attr.bv_val, "cn") != 0)
+	    st = EINVAL;
+	else {
+	    *name = strndup(dn[0][0]->la_value.bv_val, dn[0][0]->la_value.bv_len);
+	    if (*name == NULL)
+		st = EINVAL;
+	}
+
+	ldap_memfree (dn);
+    }
+#elif defined HAVE_LDAP_EXPLODE_DN
+    {
+	char **parsed_dn;
+
+	/* 1 = return DN components without type prefix */
+	parsed_dn = ldap_explode_dn(policy_dn, 1);
+	if (parsed_dn == NULL) {
+	    st = EINVAL;
+	} else {
+	    *name = strdup(parsed_dn[0]);
+	    if (*name == NULL)
+		st = EINVAL;
+
+	    ldap_value_free(parsed_dn);
+	}
+    }
+#else
+    st = EINVAL;
+#endif
+
+cleanup:
+    return st;
+}
+
+krb5_error_code krb5_ldap_name_to_policydn (context, name, policy_dn)
+    krb5_context                context;
+    char                        *name;
+    char                        **policy_dn;
+{
+    int                         len;
+    char                        *ptr = NULL;
+    krb5_error_code             st = 0;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+
+    *policy_dn = NULL;
+
+    /* validate the input parameters */
+    if (name == NULL) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    /* Used for removing policy reference from an object */
+    if (name[0] == '\0') {
+	if ((*policy_dn = strdup ("")) == NULL)
+	    st = ENOMEM;
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+
+    if (ldap_context->lrparams->realmdn == NULL) {
+	st = EINVAL;
+	goto cleanup;
+    }
+    len = strlen (ldap_context->lrparams->realmdn);
+
+    ptr = ldap_filter_correct (name);
+    if (ptr == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    len += strlen (ptr);
+
+    len += sizeof ("cn=") + 3;
+
+    *policy_dn = (char *) malloc (len);
+    if (*policy_dn == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    sprintf (*policy_dn, "cn=%s,%s", ptr, ldap_context->lrparams->realmdn);
+
+cleanup:
+    if (ptr != NULL)
+	free (ptr);
+    return st;
+}
+
+/* remove overlapping and repeated subtree entries from the list of subtrees */
+static krb5_error_code
+remove_overlapping_subtrees(char **listin, char **listop, int *subtcount, int sscope)
+{
+    int     slen=0, k=0, j=0, lendiff=0;
+    int     count = *subtcount;
+    char    **subtree = listop;
+
+    slen = count-1;
+    for (k=0; k<=slen && listin[k]!=NULL ; k++) {
+	for (j=k+1; j<=slen && listin[j]!=NULL ;j++) {
+	    lendiff = strlen(listin[k]) - strlen(listin[j]);
+	    if (sscope == 2) {
+		if ((lendiff > 0) && (strcasecmp((listin[k])+lendiff, listin[j])==0)) {
+		    if (k != slen) {
+			free(listin[k]);
+			listin[k] = listin[slen];
+			listin[slen] = NULL;
+		    } else {
+			free(listin[k]);
+			listin[k] = NULL;
+		    }
+		    slen-=1;
+		    k-=1;
+		    break;
+		} else if ((lendiff < 0) && (strcasecmp((listin[j])+abs(lendiff), listin[k])==0)) {
+		    if (j != slen) {
+			free(listin[j]);
+			listin[j] = listin[slen];
+			listin[slen]=NULL;
+		    } else {
+			free(listin[j]);
+			listin[j] = NULL;
+		    }
+		    slen-=1;
+		    j-=1;
+		}
+	    }
+	    if ((lendiff == 0) && (strcasecmp(listin[j], listin[k])==0)) {
+		if (j != slen) {
+		    free(listin[j]);
+		    listin[j] = listin[slen];
+		    listin[slen]=NULL;
+		} else {
+		    free(listin[j]);
+		    listin[j] = NULL;
+		}
+		slen -=1;
+		j-=1;
+	    }
+	}
+    }
+    *subtcount=slen+1;
+    for (k=0; k<*subtcount && listin[k]!=NULL; k++) {
+	subtree[k] = strdup(listin[k]);
+	if (subtree[k] == NULL) {
+	    return ENOMEM;
+	}
+    }
+    return 0;
+}
+
+/*
+ * Fill out a krb5_db_entry princ entry struct given a LDAP message containing
+ * the results of a principal search of the directory.
+ */
+krb5_error_code
+populate_krb5_db_entry (krb5_context context,
+			krb5_ldap_context *ldap_context,
+			LDAP *ld,
+			LDAPMessage *ent,
+			krb5_const_principal princ,
+			krb5_db_entry *entry)
+{
+    krb5_error_code st = 0;
+    unsigned int    mask = 0;
+    krb5_boolean    attr_present = FALSE;
+    char            **values = NULL, *policydn = NULL, *pwdpolicydn = NULL;
+    char            *polname = NULL, *tktpolname = NULL;
+    struct berval   **bvalues = NULL;
+    krb5_tl_data    userinfo_tl_data = {0};
+    char            **link_references = NULL;
+    char *DN = NULL;
+
+    if (princ == NULL) {
+	/* XXX WAF probably should just extract princ from ldap result */
+	st = EINVAL;
+	goto cleanup;
+    } else {
+	if ((st=krb5_copy_principal(context, princ, &(entry->princ))) != 0)
+	    goto cleanup;
+    }
+    /* get the associated directory user information */
+    if ((values = ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
+	int i, pcount=0, kerberos_principal_object_type=0;
+	char *user;
+
+	if ((st=krb5_unparse_name(context, princ, &user)) != 0)
+	    goto cleanup;
+
+	for (i=0; values[i] != NULL; ++i) {
+	    if (strcasecmp(values[i], user) == 0) {
+		pcount = ldap_count_values(values);
+		break;
+	    }
+	}
+	ldap_value_free(values);
+	free(user);
+
+	if ((DN = ldap_get_dn(ld, ent)) == NULL) {
+	    ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &st);
+	    st = set_ldap_error(context, st, 0);
+	    goto cleanup;
+	}
+
+	if ((values=ldap_get_values(ld, ent, "objectclass")) != NULL) {
+	    for (i=0; values[i] != NULL; ++i)
+		if (strcasecmp(values[i], "krbprincipal") == 0) {
+		    kerberos_principal_object_type = KDB_STANDALONE_PRINCIPAL_OBJECT;
+		    if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCTYPE,
+				&kerberos_principal_object_type)) != 0)
+			goto cleanup;
+		    break;
+		}
+	    ldap_value_free(values);
+	}
+
+	/* add principalcount, DN and principaltype user information to tl_data */
+	if (((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCCOUNT, &pcount)) != 0) ||
+	    ((st=store_tl_data(&userinfo_tl_data, KDB_TL_USERDN, DN)) != 0))
+	    goto cleanup;
+    }
+
+    /* read all the kerberos attributes */
+
+    /* KRBLASTSUCCESSFULAUTH */
+    if ((st=krb5_ldap_get_time(ld, ent, "krbLastSuccessfulAuth",
+		&(entry->last_success), &attr_present)) != 0)
+	goto cleanup;
+    if (attr_present == TRUE)
+	mask |= KDB_LAST_SUCCESS_ATTR;
+
+    /* KRBLASTFAILEDAUTH */
+    if ((st=krb5_ldap_get_time(ld, ent, "krbLastFailedAuth",
+		&(entry->last_failed), &attr_present)) != 0)
+	goto cleanup;
+    if (attr_present == TRUE)
+	mask |= KDB_LAST_FAILED_ATTR;
+
+    /* KRBLOGINFAILEDCOUNT */
+    if (krb5_ldap_get_value(ld, ent, "krbLoginFailedCount",
+	    &(entry->fail_auth_count)) == 0)
+	mask |= KDB_FAIL_AUTH_COUNT_ATTR;
+
+    /* KRBMAXTICKETLIFE */
+    if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", &(entry->max_life)) == 0)
+	mask |= KDB_MAX_LIFE_ATTR;
+
+    /* KRBMAXRENEWABLEAGE */
+    if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage",
+	    &(entry->max_renewable_life)) == 0)
+	mask |= KDB_MAX_RLIFE_ATTR;
+
+    /* KRBTICKETFLAGS */
+    if (krb5_ldap_get_value(ld, ent, "krbticketflags", &(entry->attributes)) == 0)
+	mask |= KDB_TKT_FLAGS_ATTR;
+
+    /* PRINCIPAL EXPIRATION TIME */
+    if ((st=krb5_ldap_get_time(ld, ent, "krbprincipalexpiration", &(entry->expiration),
+		&attr_present)) != 0)
+	goto cleanup;
+    if (attr_present == TRUE)
+	mask |= KDB_PRINC_EXPIRE_TIME_ATTR;
+
+    /* PASSWORD EXPIRATION TIME */
+    if ((st=krb5_ldap_get_time(ld, ent, "krbpasswordexpiration", &(entry->pw_expiration),
+		&attr_present)) != 0)
+	goto cleanup;
+    if (attr_present == TRUE)
+	mask |= KDB_PWD_EXPIRE_TIME_ATTR;
+
+    /* KRBPOLICYREFERENCE */
+
+    if ((st=krb5_ldap_get_string(ld, ent, "krbticketpolicyreference", &policydn,
+		&attr_present)) != 0)
+	goto cleanup;
+    if (attr_present == TRUE) {
+	mask |= KDB_POL_REF_ATTR;
+	/* Ensure that the policy is inside the realm container */
+	if ((st = krb5_ldap_policydn_to_name (context, policydn, &tktpolname)) != 0)
+	    goto cleanup;
+    }
+
+    /* KRBPWDPOLICYREFERENCE */
+    if ((st=krb5_ldap_get_string(ld, ent, "krbpwdpolicyreference", &pwdpolicydn,
+		&attr_present)) != 0)
+	goto cleanup;
+    if (attr_present == TRUE) {
+	krb5_tl_data  kadm_tl_data;
+
+	mask |= KDB_PWD_POL_REF_ATTR;
+
+	/* Ensure that the policy is inside the realm container */
+	if ((st = krb5_ldap_policydn_to_name (context, pwdpolicydn, &polname)) != 0)
+	    goto cleanup;
+
+	if ((st = krb5_update_tl_kadm_data(polname, &kadm_tl_data)) != 0) {
+	    goto cleanup;
+	}
+	krb5_dbe_update_tl_data(context, entry, &kadm_tl_data);
+    }
+
+    /* KRBSECRETKEY */
+    if ((bvalues=ldap_get_values_len(ld, ent, "krbprincipalkey")) != NULL) {
+	mask |= KDB_SECRET_KEY_ATTR;
+	if ((st=krb5_decode_krbsecretkey(context, entry, bvalues, &userinfo_tl_data)) != 0)
+	    goto cleanup;
+    }
+
+    /* LAST PASSWORD CHANGE */
+    {
+	krb5_timestamp lstpwdchng=0;
+	if ((st=krb5_ldap_get_time(ld, ent, "krbLastPwdChange",
+		    &lstpwdchng, &attr_present)) != 0)
+	    goto cleanup;
+	if (attr_present == TRUE) {
+	    if ((st=krb5_dbe_update_last_pwd_change(context, entry,
+			lstpwdchng)))
+		goto cleanup;
+	    mask |= KDB_LAST_PWD_CHANGE_ATTR;
+	}
+    }
+
+    /* KRBOBJECTREFERENCES */
+    {
+	int i=0;
+
+	if ((st = krb5_ldap_get_strings(ld, ent, "krbobjectreferences",
+		    &link_references, &attr_present)) != 0)
+	    goto cleanup;
+	if (link_references != NULL) {
+	    for (i=0; link_references[i] != NULL; ++i) {
+		if ((st = store_tl_data(&userinfo_tl_data, KDB_TL_LINKDN,
+			    link_references[i])) != 0)
+		    goto cleanup;
+	    }
+	}
+    }
+
+    /* Set tl_data */
+    {
+	int i;
+	struct berval **ber_tl_data = NULL;
+	krb5_tl_data *ptr = NULL;
+
+	if ((ber_tl_data = ldap_get_values_len (ld, ent, "krbExtraData")) != NULL) {
+	    for (i = 0; ber_tl_data[i] != NULL; i++) {
+		if ((st = berval2tl_data (ber_tl_data[i] , &ptr)) != 0)
+		    break;
+		if ((st = krb5_dbe_update_tl_data(context, entry, ptr)) != 0)
+		    break;
+	    }
+	    ldap_value_free_len (ber_tl_data);
+	    if (st != 0)
+		goto cleanup;
+	    mask |= KDB_EXTRA_DATA_ATTR;
+	}
+    }
+
+    /* update the mask of attributes present on the directory object to the tl_data */
+    if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_MASK, &mask)) != 0)
+	goto cleanup;
+    if ((st=krb5_dbe_update_tl_data(context, entry, &userinfo_tl_data)) != 0)
+	goto cleanup;
+
+#ifdef HAVE_EDIRECTORY
+    {
+	krb5_timestamp              expiretime=0;
+	char                        *is_login_disabled=NULL;
+
+	/* LOGIN EXPIRATION TIME */
+	if ((st=krb5_ldap_get_time(ld, ent, "loginexpirationtime", &expiretime,
+		    &attr_present)) != 0)
+	    goto cleanup;
+
+	if (attr_present == TRUE) {
+	    if ((mask & KDB_PRINC_EXPIRE_TIME_ATTR) == 1) {
+		if (expiretime < entry->expiration)
+		    entry->expiration = expiretime;
+	    } else {
+		entry->expiration = expiretime;
+	    }
+	}
+
+	/* LOGIN DISABLED */
+	if ((st=krb5_ldap_get_string(ld, ent, "logindisabled", &is_login_disabled,
+		    &attr_present)) != 0)
+	    goto cleanup;
+	if (attr_present == TRUE) {
+	    if (strcasecmp(is_login_disabled, "TRUE")== 0)
+		entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+	    free (is_login_disabled);
+	}
+    }
+#endif
+
+    if ((st=krb5_read_tkt_policy (context, ldap_context, entry, tktpolname)) !=0)
+	goto cleanup;
+
+    /* We already know that the policy is inside the realm container. */
+    if (polname) {
+	osa_policy_ent_t   pwdpol;
+	int                cnt=0;
+	krb5_timestamp     last_pw_changed;
+	krb5_ui_4          pw_max_life;
+
+	memset(&pwdpol, 0, sizeof(pwdpol));
+
+	if ((st=krb5_ldap_get_password_policy(context, polname, &pwdpol, &cnt)) != 0)
+	    goto cleanup;
+	pw_max_life = pwdpol->pw_max_life;
+	free (pwdpol);
+
+	if (pw_max_life > 0) {
+	    if ((st=krb5_dbe_lookup_last_pwd_change(context, entry, &last_pw_changed)) != 0)
+		goto cleanup;
+
+	    if ((mask & KDB_PWD_EXPIRE_TIME_ATTR) == 1) {
+		if ((last_pw_changed + pw_max_life) < entry->pw_expiration)
+		    entry->pw_expiration = last_pw_changed + pw_max_life;
+	    } else
+		entry->pw_expiration = last_pw_changed + pw_max_life;
+	}
+    }
+    /* XXX so krb5_encode_princ_contents() will be happy */
+    entry->len = KRB5_KDB_V1_BASE_LENGTH;
+
+cleanup:
+
+    if (DN != NULL)
+	ldap_memfree(DN);
+
+    if (userinfo_tl_data.tl_data_contents != NULL)
+	free(userinfo_tl_data.tl_data_contents);
+
+    if (pwdpolicydn != NULL)
+	free(pwdpolicydn);
+
+    if (polname != NULL)
+	free(polname);
+
+    if (tktpolname != NULL)
+	free (tktpolname);
+
+    if (policydn != NULL)
+	free(policydn);
+
+    if (link_references) {
+        int i;
+        for (i=0; link_references[i] != NULL; ++i)
+            free (link_references[i]);
+        free (link_references);
+    }
+
+    return (st);
+}
+
+/*
+ * Solaris libldap does not provide the following functions which are in
+ * OpenLDAP.
+ */
+#ifndef HAVE_LDAP_INITIALIZE
+int
+ldap_initialize(LDAP **ldp, char *url)
+{
+    int rc = 0;
+    LDAP *ld = NULL;
+    LDAPURLDesc *ludp = NULL;
+
+    /* For now, we don't use any DN that may be provided.  And on
+       Solaris (based on Mozilla's LDAP client code), we need the
+       _nodn form to parse "ldap://host" without a trailing slash.
+
+       Also, this version won't handle an input string which contains
+       multiple URLs, unlike the OpenLDAP ldap_initialize.  See
+       https://bugzilla.mozilla.org/show_bug.cgi?id=353336#c1 .  */
+#ifdef HAVE_LDAP_URL_PARSE_NODN
+    rc = ldap_url_parse_nodn(url, &ludp);
+#else
+    rc = ldap_url_parse(url, &ludp);
+#endif
+    if (rc == 0) {
+
+	ld = ldap_init(ludp->lud_host, ludp->lud_port);
+	if (ld != NULL) {
+	    *ldp = ld;
+#if 0
+	    printf("lud_host %s lud_port %d\n", ludp->lud_host,
+		   ludp->lud_port);
+#endif
+	}
+	else
+	    rc = KRB5_KDB_ACCESS_ERROR;
+
+	ldap_free_urldesc(ludp);
+    }
+    return rc;
+}
+#endif /* HAVE_LDAP_INITIALIZE */
+
+#ifndef HAVE_LDAP_UNBIND_EXT_S
+int
+ldap_unbind_ext_s(LDAP *ld, LDAPControl **sctrls, LDAPControl **cctrls)
+{
+    return ldap_unbind_ext(ld, sctrls, cctrls);
+}
+#endif /* HAVE_LDAP_UNBIND_EXT_S */
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h
new file mode 100644
index 000000000..5fc969f46
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h
@@ -0,0 +1,153 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_misc.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _HAVE_LDAP_MISC_H
+#define _HAVE_LDAP_MISC_H 1
+
+#include "ldap_services.h"
+
+/* misc functions */
+
+krb5_error_code
+updateAttribute (LDAP *, char *, char *, char  *);
+
+krb5_error_code
+deleteAttribute (LDAP *, char *, char *, char *);
+
+krb5_error_code
+populateServers(LDAP *, char **, char ***, char *, char **);
+
+krb5_error_code
+disjoint_members(char **, char **);
+
+krb5_error_code
+is_principal_in_realm(krb5_ldap_context *, krb5_const_principal);
+
+krb5_error_code
+checkattributevalue(LDAP *, char *, char *, char **, int *);
+
+krb5_error_code
+krb5_get_attributes_mask(krb5_context, krb5_db_entry *, int *);
+
+krb5_error_code
+krb5_get_princ_type(krb5_context, krb5_db_entry *, int *);
+
+krb5_error_code
+krb5_get_princ_count(krb5_context, krb5_db_entry *, int *);
+
+krb5_error_code
+krb5_get_linkdn(krb5_context, krb5_db_entry *, char ***);
+
+krb5_error_code
+krb5_get_userdn(krb5_context, krb5_db_entry *, char **);
+
+krb5_error_code
+krb5_get_containerdn(krb5_context, krb5_db_entry *, char **);
+
+krb5_error_code
+store_tl_data(krb5_tl_data *, int, void *);
+
+krb5_error_code
+decode_tl_data(krb5_tl_data *, int, void **);
+
+krb5_error_code
+is_principal_in_realm(krb5_ldap_context *, krb5_const_principal);
+
+krb5_error_code
+krb5_get_subtree_info(krb5_ldap_context *, char ***, unsigned int *); 
+
+krb5_error_code
+krb5_ldap_read_server_params(krb5_context , char *, int);
+
+krb5_error_code
+krb5_ldap_free_server_params(krb5_ldap_context *);
+
+krb5_error_code
+copy_arrays(char **, char ***, int);
+
+krb5_error_code
+krb5_ldap_list(krb5_context, char ***, char *, char *);
+
+krb5_error_code 
+krb5_ldap_get_value(LDAP *, LDAPMessage *, char *, int *);
+
+krb5_error_code 
+krb5_ldap_get_string(LDAP *, LDAPMessage *, char *, char **, krb5_boolean *);
+
+krb5_error_code 
+krb5_ldap_get_strings(LDAP *, LDAPMessage *, char *, char ***, krb5_boolean *);
+
+krb5_error_code 
+krb5_ldap_get_time(LDAP *, LDAPMessage *, char *, krb5_timestamp *, krb5_boolean *);
+
+krb5_error_code
+krb5_add_member(LDAPMod ***, int *);
+
+krb5_error_code
+krb5_add_str_mem_ldap_mod(LDAPMod  ***, char *, int, char **);
+
+krb5_error_code
+krb5_add_ber_mem_ldap_mod(LDAPMod  ***, char *, int, struct berval **);
+
+krb5_error_code
+krb5_add_int_arr_mem_ldap_mod(LDAPMod  ***, char *, int, int *);
+
+krb5_error_code
+krb5_add_int_mem_ldap_mod(LDAPMod  ***, char *, int , int);
+
+krb5_error_code
+krb5_ldap_free_mod_array(LDAPMod **);
+
+krb5_error_code
+krb5_ldap_get_reference_count (krb5_context, char *, char *, int *, LDAP *);
+
+krb5_error_code
+krb5_ldap_policydn_to_name (krb5_context, char *, char **);
+
+krb5_error_code
+krb5_ldap_name_to_policydn (krb5_context, char *, char **);
+
+krb5_error_code
+krb5_ldap_get_db_opt(char *, char **, char **);
+
+krb5_error_code
+populate_krb5_db_entry(krb5_context context,
+    krb5_ldap_context *ldap_context,
+    LDAP *ld,
+    LDAPMessage *ent,
+    krb5_const_principal princ,
+    krb5_db_entry *entry);
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
new file mode 100644
index 000000000..77256482e
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
@@ -0,0 +1,517 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_principal.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "princ_xdr.h"
+#include "ldap_err.h"
+
+struct timeval timelimit = {300, 0};  /* 5 minutes */
+char     *principal_attributes[] = { "krbprincipalname",
+				     "objectclass",
+				     "krbprincipalkey",
+				     "krbmaxrenewableage",
+				     "krbmaxticketlife",
+				     "krbticketflags",
+				     "krbprincipalexpiration",
+				     "krbticketpolicyreference",
+				     "krbUpEnabled",
+				     "krbpwdpolicyreference",
+				     "krbpasswordexpiration",
+                                     "krbLastFailedAuth",
+                                     "krbLoginFailedCount",
+                                     "krbLastSuccessfulAuth",
+#ifdef HAVE_EDIRECTORY
+				     "loginexpirationtime",
+				     "logindisabled",
+#endif
+				     "loginexpirationtime",
+				     "logindisabled",
+				     "modifytimestamp",
+				     "krbLastPwdChange",
+				     "krbExtraData",
+				     "krbObjectReferences",
+				     NULL };
+
+/* Must match KDB_*_ATTR macros in ldap_principal.h.  */
+static char *attributes_set[] = { "krbmaxticketlife",
+				  "krbmaxrenewableage",
+				  "krbticketflags",
+				  "krbprincipalexpiration",
+				  "krbticketpolicyreference",
+				  "krbUpEnabled",
+				  "krbpwdpolicyreference",
+				  "krbpasswordexpiration",
+				  "krbprincipalkey",
+                                  "krblastpwdchange",
+                                  "krbextradata",
+                                  "krbLastSuccessfulAuth",
+                                  "krbLastFailedAuth",
+                                  "krbLoginFailedCount",
+				  NULL };
+
+void
+krb5_dbe_free_contents(context, entry)
+    krb5_context 	 context;
+    krb5_db_entry 	*entry;
+{
+    krb5_tl_data 	*tl_data_next=NULL;
+    krb5_tl_data 	*tl_data=NULL;
+    int i, j;
+
+    if (entry->e_data)
+	free(entry->e_data);
+    if (entry->princ)
+	krb5_free_principal(context, entry->princ);
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
+	tl_data_next = tl_data->tl_data_next;
+	if (tl_data->tl_data_contents)
+	    free(tl_data->tl_data_contents);
+	free(tl_data);
+    }
+    if (entry->key_data) {
+	for (i = 0; i < entry->n_key_data; i++) {
+	    for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+		if (entry->key_data[i].key_data_length[j]) {
+		    if (entry->key_data[i].key_data_contents[j]) {
+			memset(entry->key_data[i].key_data_contents[j],
+			       0,
+			       (unsigned) entry->key_data[i].key_data_length[j]);
+			free (entry->key_data[i].key_data_contents[j]);
+		    }
+		}
+		entry->key_data[i].key_data_contents[j] = NULL;
+		entry->key_data[i].key_data_length[j] = 0;
+		entry->key_data[i].key_data_type[j] = 0;
+	    }
+	}
+	free(entry->key_data);
+    }
+    memset(entry, 0, sizeof(*entry));
+    return;
+}
+
+
+krb5_error_code
+krb5_ldap_free_principal(kcontext , entries, nentries)
+    krb5_context  kcontext;
+    krb5_db_entry *entries;
+    int           nentries;
+{
+    register int i;
+    for (i = 0; i < nentries; i++)
+	krb5_dbe_free_contents(kcontext, &entries[i]);
+    return 0;
+}
+
+krb5_error_code
+krb5_ldap_iterate(context, match_expr, func, func_arg)
+    krb5_context           context;
+    char                   *match_expr;
+    krb5_error_code        (*func) (krb5_pointer, krb5_db_entry *);
+    krb5_pointer           func_arg;
+{
+    krb5_db_entry            entry;
+    krb5_principal           principal;
+    char                     **subtree=NULL, *princ_name=NULL, *realm=NULL, **values=NULL, *filter=NULL; 
+    unsigned int             filterlen=0, tree=0, ntree=1, i=0;
+    krb5_error_code          st=0, tempst=0;
+    LDAP                     *ld=NULL;
+    LDAPMessage              *result=NULL, *ent=NULL;
+    kdb5_dal_handle          *dal_handle=NULL;
+    krb5_ldap_context        *ldap_context=NULL;
+    krb5_ldap_server_handle  *ldap_server_handle=NULL;
+    char                     *default_match_expr = "*";
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    memset(&entry, 0, sizeof(krb5_db_entry));
+    SETUP_CONTEXT();
+
+    realm = ldap_context->lrparams->realm_name;
+    if (realm == NULL) {
+	realm = context->default_realm;
+	if (realm == NULL) {
+	    st = EINVAL;
+	    krb5_set_error_message(context, st, "Default realm not set");
+	    goto cleanup;
+	}
+    }
+
+    /* 
+     * If no match_expr then iterate through all krb princs like the db2 plugin
+     */
+    if (match_expr == NULL)
+	match_expr = default_match_expr;
+
+    filterlen = strlen(FILTER) + strlen(match_expr) + 2 + 1;  /* 2 for closing brackets */
+    filter = malloc (filterlen);
+    CHECK_NULL(filter);
+    memset(filter, 0, filterlen);
+    sprintf(filter, FILTER"%s))", match_expr);
+
+    if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntree)) != 0) 
+	goto cleanup;
+
+    GET_HANDLE();
+
+    for (tree=0; tree < ntree; ++tree) {
+
+	LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes);
+	for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
+	    if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
+		for (i=0; values[i] != NULL; ++i) {
+		    if (values[i])
+		    if (krb5_ldap_parse_principal_name(values[i], &princ_name) != 0)
+			continue;
+		    if (krb5_parse_name(context, princ_name, &principal) != 0)
+			continue;
+		    if (is_principal_in_realm(ldap_context, principal) == 0) {
+			if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, principal,
+				    &entry)) != 0)
+			    goto cleanup;
+			(*func)(func_arg, &entry);
+			krb5_dbe_free_contents(context, &entry);
+			(void) krb5_free_principal(context, principal);
+			if (princ_name)
+			    free(princ_name);
+			break;
+		    }
+		    (void) krb5_free_principal(context, principal);
+		    if (princ_name)
+			free(princ_name);
+		}
+		ldap_value_free(values);
+	    }
+	} /* end of for (ent= ... */
+	ldap_msgfree(result);
+    } /* end of for (tree= ... */
+
+cleanup:
+    if (filter)
+	free (filter);
+
+    for (;ntree; --ntree)
+	if (subtree[ntree-1])
+	    free (subtree[ntree-1]);
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * delete a principal from the directory.
+ */
+krb5_error_code
+krb5_ldap_delete_principal(context, searchfor, nentries)
+    krb5_context context;
+    krb5_const_principal searchfor;
+    int *nentries;		/* how many found & deleted */
+{
+    char                      *user=NULL, *DN=NULL, *strval[10] = {NULL};
+    LDAPMod                   **mods=NULL;
+    LDAP                      *ld=NULL;
+    int 	              j=0, ptype=0, pcount=0, attrsetmask=0;
+    krb5_error_code           st=0;
+    krb5_boolean              singleentry=FALSE;
+    KEY                       *secretkey=NULL;
+    kdb5_dal_handle           *dal_handle=NULL;
+    krb5_ldap_context         *ldap_context=NULL;
+    krb5_ldap_server_handle   *ldap_server_handle=NULL;
+    krb5_db_entry             entries;
+    krb5_boolean              more=0;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    SETUP_CONTEXT();
+    /* get the principal info */
+    if ((st=krb5_ldap_get_principal(context, searchfor, &entries, nentries, &more)) != 0 || *nentries == 0)
+	goto cleanup;
+
+    if (((st=krb5_get_princ_type(context, &entries, &(ptype))) != 0) ||
+	((st=krb5_get_attributes_mask(context, &entries, &(attrsetmask))) != 0) ||
+	((st=krb5_get_princ_count(context, &entries, &(pcount))) != 0) ||
+	((st=krb5_get_userdn(context, &entries, &(DN))) != 0))
+	goto cleanup;
+
+    if (DN == NULL) {
+	st = EINVAL;
+	krb5_set_error_message(context, st, "DN information missing");
+	goto cleanup;
+    }
+
+    GET_HANDLE();
+
+    if (ptype == KDB_STANDALONE_PRINCIPAL_OBJECT) {
+        st = ldap_delete_ext_s(ld, DN, NULL, NULL);
+        if (st != LDAP_SUCCESS) {
+            st = set_ldap_error (context, st, OP_DEL);
+            goto cleanup;
+        }
+    } else {
+	if (((st=krb5_unparse_name(context, searchfor, &user)) != 0)
+	    || ((st=krb5_ldap_unparse_principal_name(user)) != 0))
+	    goto cleanup;
+
+	memset(strval, 0, sizeof(strval));
+	strval[0] = user;
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_DELETE,
+					  strval)) != 0)
+	    goto cleanup;
+
+	singleentry = (pcount == 1) ? TRUE: FALSE;
+	if (singleentry == FALSE) {
+	    if (secretkey != NULL) {
+		if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", LDAP_MOD_DELETE | LDAP_MOD_BVALUES,
+						  secretkey->keys)) != 0)
+		    goto cleanup;
+	    }
+	} else {
+	    /*
+	     * If the Kerberos user principal to be deleted happens to be the last one associated
+	     * with the directory user object, then it is time to delete the other kerberos
+	     * specific attributes like krbmaxticketlife, i.e, unkerberize the directory user.
+	     * From the attrsetmask value, identify the attributes set on the directory user
+	     * object and delete them.
+	     * NOTE: krbsecretkey attribute has per principal entries. There can be chances that the
+	     * other principals' keys are exisiting/left-over. So delete all the values.
+	     */
+	    while (attrsetmask) {
+		if (attrsetmask & 1) {
+		    if ((st=krb5_add_str_mem_ldap_mod(&mods, attributes_set[j], LDAP_MOD_DELETE,
+						      NULL)) != 0)
+			goto cleanup;
+		}
+		attrsetmask >>= 1;
+		++j;
+	    }
+
+	    /* the same should be done with the objectclass attributes */
+	    {
+		char *attrvalues[] = {"krbticketpolicyaux", "krbprincipalaux", NULL};
+/*		char *attrvalues[] = {"krbpwdpolicyrefaux", "krbticketpolicyaux", "krbprincipalaux", NULL};  */
+		int p, q, r=0, amask=0;
+
+		if ((st=checkattributevalue(ld, DN, "objectclass", attrvalues, &amask)) != 0)
+		    goto cleanup;
+		memset(strval, 0, sizeof(strval));
+		for (p=1, q=0; p<=4; p<<=1, ++q)
+		    if (p & amask)
+			strval[r++] = attrvalues[q];
+		strval[r] = NULL;
+		if (r > 0) {
+		    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_DELETE,
+						      strval)) != 0)
+			goto cleanup;
+		}
+	    }
+	}
+	st=ldap_modify_ext_s(ld, DN, mods, NULL, NULL);
+	if (st != LDAP_SUCCESS) {
+	    st = set_ldap_error(context, st, OP_MOD);
+	    goto cleanup;
+	}
+    }
+
+cleanup:
+    if (user)
+	free (user);
+
+    if (DN)
+	free (DN);
+
+    if (secretkey != NULL) {
+	int i=0;
+	while (i < secretkey->nkey) {
+	    free (secretkey->keys[i]->bv_val);
+	    free (secretkey->keys[i]);
+	    ++i;
+	}
+	free (secretkey->keys);
+	free (secretkey);
+    }
+
+    if (st == 0)
+	krb5_ldap_free_principal(context, &entries, *nentries);
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * Function: krb5_ldap_unparse_principal_name
+ *
+ * Purpose: Removes '\\' that comes before every occurence of '@'
+ *          in the principal name component.
+ *
+ * Arguments:
+ *       user_name     (input/output)      Principal name
+ *
+ */
+
+krb5_error_code
+krb5_ldap_unparse_principal_name(char *user_name)
+{
+    char *tmp_princ_name=NULL, *princ_name=NULL, *tmp=NULL;
+    int l=0;
+    krb5_error_code st=0;
+
+    if (strstr(user_name, "\\@")) {
+
+	tmp_princ_name = strdup(user_name);
+	if (!tmp_princ_name) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+	tmp = tmp_princ_name;
+
+	princ_name = (char *) malloc (strlen(user_name));
+	if (!princ_name) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+	memset(princ_name, 0, strlen(user_name));
+
+	l = 0;
+	while (*tmp_princ_name) {
+	    if ((*tmp_princ_name == '\\') && (*(tmp_princ_name+1) == '@')) {
+		tmp_princ_name += 1;
+	    } else {
+		*(princ_name + l) = *tmp_princ_name++;
+		l++;
+	    }
+	}
+
+	memset(user_name, 0, strlen(user_name));
+	sprintf(user_name, "%s", princ_name);
+    }
+
+cleanup:
+    if (tmp) {
+	free(tmp);
+	tmp = NULL;
+    }
+
+    if (princ_name) {
+	free(princ_name);
+	princ_name = NULL;
+    }
+
+    return st;
+}
+
+
+/*
+ * Function: krb5_ldap_parse_principal_name
+ *
+ * Purpose: Inserts '\\' before every occurence of '@'
+ *          in the principal name component.
+ *
+ * Arguments:
+ *       i_princ_name     (input)      Principal name without '\\'
+ *       o_princ_name     (output)     Principal name with '\\'
+ *
+ * Note: The caller has to free the memory allocated for o_princ_name.
+ */
+
+krb5_error_code
+krb5_ldap_parse_principal_name(i_princ_name, o_princ_name)
+    char              *i_princ_name;
+    char              **o_princ_name;
+{
+    char *tmp_princ_name = NULL, *princ_name = NULL, *at_rlm_name = NULL;
+    int l = 0, m = 0, tmp_princ_name_len = 0, princ_name_len = 0, at_count = 0;
+    krb5_error_code st = 0;
+
+    at_rlm_name = strrchr(i_princ_name, '@');
+
+    if (!at_rlm_name) {
+	*o_princ_name = strdup(i_princ_name);
+	if (!o_princ_name) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+    } else {
+	tmp_princ_name_len = at_rlm_name - i_princ_name;
+
+	tmp_princ_name = (char *) malloc ((unsigned) tmp_princ_name_len + 1);
+	if (!tmp_princ_name) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+	memset(tmp_princ_name, 0, (unsigned) tmp_princ_name_len + 1);
+	memcpy(tmp_princ_name, i_princ_name, (unsigned) tmp_princ_name_len);
+
+	l = 0;
+	while (tmp_princ_name[l]) {
+	    if (tmp_princ_name[l++] == '@')
+		at_count++;
+	}
+
+	princ_name_len = strlen(i_princ_name) + at_count + 1;
+	princ_name = (char *) malloc ((unsigned) princ_name_len);
+	if (!princ_name) {
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+	memset(princ_name, 0, (unsigned) princ_name_len);
+
+	l = 0;
+	m = 0;
+	while (tmp_princ_name[l]) {
+	    if (tmp_princ_name[l] == '@') {
+		princ_name[m++]='\\';
+	    }
+	    princ_name[m++]=tmp_princ_name[l++];
+	}
+	strcat(princ_name, at_rlm_name);
+
+	*o_princ_name = princ_name;
+    }
+
+cleanup:
+
+    if (tmp_princ_name) {
+	free(tmp_princ_name);
+	tmp_princ_name = NULL;
+    }
+
+    return st;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h
new file mode 100644
index 000000000..ca8c80681
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h
@@ -0,0 +1,122 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_principal.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_PRINCIPAL_H
+#define _LDAP_PRINCIPAL_H 1
+
+#include "ldap_tkt_policy.h"
+
+#define  KEYHEADER  12
+
+#define  NOOFKEYS(ptr) 		((ptr[10]<<8) | ptr[11])
+
+#define  PRINCIPALLEN(ptr) 	((ptr[0]<<8) | ptr[1])
+#define  PRINCIPALNAME(ptr) 	(ptr + KEYHEADER + (NOOFKEYS(ptr) *8))
+
+#define  KEYBODY(ptr)		PRINCIPALNAME(ptr) + PRINCIPALLEN(ptr)
+
+#define  PKEYVER(ptr) 		((ptr[2]<<8) | ptr[3])
+#define  MKEYVER(ptr) 		((ptr[4]<<8) | ptr[5])
+
+#define  KEYTYPE(ptr,j) 	((ptr[KEYHEADER+(j*8)]<<8) | ptr[KEYHEADER+1+(j*8)])
+#define  KEYLENGTH(ptr,j) 	((ptr[KEYHEADER+2+(j*8)]<<8) | ptr[KEYHEADER+3+(j*8)])
+#define  SALTTYPE(ptr,j) 	((ptr[KEYHEADER+4+(j*8)]<<8) | ptr[KEYHEADER+5+(j*8)])
+#define  SALTLENGTH(ptr,j) 	((ptr[KEYHEADER+6+(j*8)]<<8) | ptr[KEYHEADER+7+(j*8)])
+
+#define MAX_KEY_LENGTH         1024
+#define CONTAINERDN_ARG        "containerdn"
+#define USERDN_ARG             "dn"
+#define TKTPOLICY_ARG          "tktpolicy"
+#define LINKDN_ARG             "linkdn"
+
+/* #define FILTER   "(&(objectclass=krbprincipalaux)(krbprincipalname=" */
+ #define FILTER   "(&(|(objectclass=krbprincipalaux)(objectclass=krbprincipal))(krbprincipalname="
+
+#define  KDB_USER_PRINCIPAL    0x01
+#define  KDB_SERVICE_PRINCIPAL 0x02
+#define KDB_STANDALONE_PRINCIPAL_OBJECT 0x01
+
+/* these will be consumed only by krb5_ldap_delete_principal*/
+/* these will be set by krb5_ldap_get_principal and fed into the tl_data */
+
+/* See also attributes_set[] in ldap_principal.c.  */
+#define KDB_MAX_LIFE_ATTR                    0x000001
+#define KDB_MAX_RLIFE_ATTR                   0x000002
+#define KDB_TKT_FLAGS_ATTR                   0x000004
+#define KDB_PRINC_EXPIRE_TIME_ATTR           0x000008
+#define KDB_POL_REF_ATTR                     0x000010
+#define KDB_UP_FLAG_ATTR                     0x000020
+#define KDB_PWD_POL_REF_ATTR                 0x000040
+#define KDB_PWD_EXPIRE_TIME_ATTR             0x000080
+#define KDB_SECRET_KEY_ATTR                  0x000100
+#define KDB_LAST_PWD_CHANGE_ATTR             0x000200
+#define KDB_EXTRA_DATA_ATTR                  0x000400
+#define KDB_LAST_SUCCESS_ATTR                0x000800
+#define KDB_LAST_FAILED_ATTR                 0x001000
+#define KDB_FAIL_AUTH_COUNT_ATTR             0x002000
+extern struct timeval timeout;
+extern char *policyclass[];
+
+krb5_error_code
+krb5_ldap_put_principal(krb5_context, krb5_db_entry *, int *, char **);
+
+krb5_error_code
+krb5_ldap_get_principal(krb5_context , krb5_const_principal ,
+                        krb5_db_entry *,int *, krb5_boolean *);
+
+krb5_error_code
+krb5_ldap_delete_principal(krb5_context, krb5_const_principal, int *);
+
+krb5_error_code
+krb5_ldap_free_principal(krb5_context, krb5_db_entry *, int );
+
+krb5_error_code
+krb5_ldap_iterate(krb5_context, char *, krb5_error_code (*) (krb5_pointer, krb5_db_entry *),
+                  krb5_pointer/*, int */);
+
+void
+krb5_dbe_free_contents(krb5_context, krb5_db_entry *);
+
+krb5_error_code
+krb5_ldap_unparse_principal_name(char *);
+
+krb5_error_code
+krb5_ldap_parse_principal_name(char *, char **);
+
+krb5_error_code
+krb5_decode_krbsecretkey(krb5_context, krb5_db_entry *, struct berval **,
+    krb5_tl_data *);
+
+krb5_error_code
+berval2tl_data(struct berval *in, krb5_tl_data **out);
+
+krb5_error_code
+krb5_read_tkt_policy (krb5_context, krb5_ldap_context *, krb5_db_entry *, char *);
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
new file mode 100644
index 000000000..7926484c7
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
@@ -0,0 +1,1288 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_principal2.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <time.h>
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "princ_xdr.h"
+#include "ldap_tkt_policy.h"
+#include "ldap_pwd_policy.h"
+#include "ldap_err.h"
+#include <kadm5/admin.h>
+
+extern char* principal_attributes[];
+extern char* max_pwd_life_attr[];
+
+static char *
+getstringtime(krb5_timestamp);
+
+krb5_error_code
+berval2tl_data(struct berval *in, krb5_tl_data **out)
+{
+    *out = (krb5_tl_data *) malloc (sizeof (krb5_tl_data));
+    if (*out == NULL)
+	return ENOMEM;
+
+    (*out)->tl_data_length = in->bv_len - 2;
+    (*out)->tl_data_contents =  (krb5_octet *) malloc
+	((*out)->tl_data_length * sizeof (krb5_octet));
+    if ((*out)->tl_data_contents == NULL) {
+	free (*out);
+	return ENOMEM;
+    }
+
+    UNSTORE16_INT (in->bv_val, (*out)->tl_data_type);
+    memcpy ((*out)->tl_data_contents, in->bv_val + 2, (*out)->tl_data_length);
+
+    return 0;
+}
+
+/*
+ * look up a principal in the directory.
+ */
+
+krb5_error_code
+krb5_ldap_get_principal(context, searchfor, entries, nentries, more)
+    krb5_context context;
+    krb5_const_principal searchfor;
+    krb5_db_entry *entries;	/* filled in */
+    int *nentries;		/* how much room/how many found */
+    krb5_boolean *more;		/* are there more? */
+{
+    char                        *user=NULL, *filter=NULL, **subtree=NULL;
+    unsigned int                tree=0, ntrees=1, princlen=0;
+    krb5_error_code	        tempst=0, st=0;
+    char                        **values=NULL;
+    LDAP	                *ld=NULL;
+    LDAPMessage	                *result=NULL, *ent=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    /* set initial values */
+    *nentries = 0;
+    *more = 0;
+    memset(entries, 0, sizeof(*entries));
+
+    if (searchfor == NULL)
+	return EINVAL;
+
+    dal_handle = (kdb5_dal_handle *) context->db_context;
+    ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+    CHECK_LDAP_HANDLE(ldap_context);
+
+    if (is_principal_in_realm(ldap_context, searchfor) != 0) {
+	*more = 0;
+	krb5_set_error_message (context, st, "Principal does not belong to realm");
+	goto cleanup;
+    }
+
+    if ((st=krb5_unparse_name(context, searchfor, &user)) != 0)
+	goto cleanup;
+
+    if ((st=krb5_ldap_unparse_principal_name(user)) != 0)
+	goto cleanup;
+
+    princlen = strlen(FILTER) + strlen(user) + 2 + 1;      /* 2 for closing brackets */
+    if ((filter = malloc(princlen)) == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    snprintf(filter, princlen, FILTER"%s))", user);
+
+    if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees)) != 0)
+	goto cleanup;
+
+    GET_HANDLE();
+    for (tree=0; tree < ntrees && *nentries == 0; ++tree) {
+
+	LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes);
+	for (ent=ldap_first_entry(ld, result); ent != NULL && *nentries == 0; ent=ldap_next_entry(ld, ent)) {
+
+	    /* get the associated directory user information */
+	    if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
+		int i;
+
+		/* a wild-card in a principal name can return a list of kerberos principals.
+		 * Make sure that the correct principal is returned.
+		 * NOTE: a principalname k* in ldap server will return all the principals starting with a k
+		 */
+		for (i=0; values[i] != NULL; ++i) {
+		    if (strcasecmp(values[i], user) == 0) {
+			*nentries = 1;
+			break;
+		    }
+		}
+		ldap_value_free(values);
+
+		if (*nentries == 0) /* no matching principal found */
+		    continue;
+	    }
+
+	    if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, searchfor,
+			entries)) != 0)
+		goto cleanup;
+	}
+	ldap_msgfree(result);
+	result = NULL;
+    } /* for (tree=0 ... */
+
+    /* once done, put back the ldap handle */
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    ldap_server_handle = NULL;
+
+cleanup:
+    ldap_msgfree(result);
+
+    if (*nentries == 0 || st != 0)
+	krb5_dbe_free_contents(context, entries);
+
+    if (filter)
+	free (filter);
+
+    if (subtree) {
+	for (; ntrees; --ntrees)
+	    if (subtree[ntrees-1])
+		free (subtree[ntrees-1]);
+	free (subtree);
+    }
+
+    if (ldap_server_handle)
+	krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+
+    if (user)
+	free(user);
+
+    return st;
+}
+
+typedef enum{ ADD_PRINCIPAL, MODIFY_PRINCIPAL } OPERATION;
+/*
+ * ptype is creating confusions. Additionally the logic
+ * surronding ptype is redundunt and can be achevied
+ * with the help of dn and containerdn members.
+ * so dropping the ptype member
+ */
+
+typedef struct _xargs_t {
+    char           *dn;
+    char           *linkdn;
+    krb5_boolean   dn_from_kbd;
+    char           *containerdn;
+    char           *tktpolicydn;
+}xargs_t;
+
+static void
+free_xargs(xargs)
+    xargs_t xargs;
+{
+    if (xargs.dn)
+	free (xargs.dn);
+    if (xargs.linkdn)
+	free(xargs.linkdn);
+    if (xargs.containerdn)
+	free (xargs.containerdn);
+    if (xargs.tktpolicydn)
+	free (xargs.tktpolicydn);
+}
+
+static krb5_error_code
+process_db_args(context, db_args, xargs, optype)
+    krb5_context   context;
+    char           **db_args;
+    xargs_t        *xargs;
+    OPERATION      optype;
+{
+    int                   i=0;
+    krb5_error_code       st=0;
+    char                  errbuf[1024];
+    char                  *arg=NULL, *arg_val=NULL;
+    char                  **dptr=NULL;
+    unsigned int          arg_val_len=0;
+
+    if (db_args) {
+	for (i=0; db_args[i]; ++i) {
+	    arg = strtok_r(db_args[i], "=", &arg_val);
+	    if (strcmp(arg, TKTPOLICY_ARG) == 0) {
+		dptr = &xargs->tktpolicydn;
+	    } else {
+		if (strcmp(arg, USERDN_ARG) == 0) {
+		    if (optype == MODIFY_PRINCIPAL || 
+			xargs->dn != NULL || xargs->containerdn != NULL || 
+			xargs->linkdn != NULL) {
+			st = EINVAL;
+			snprintf(errbuf, sizeof(errbuf), 
+				 "%s option not supported", arg);
+			krb5_set_error_message(context, st, "%s", errbuf);
+			goto cleanup;
+		    }
+		    dptr = &xargs->dn;
+		} else if (strcmp(arg, CONTAINERDN_ARG) == 0) {
+		    if (optype == MODIFY_PRINCIPAL ||
+			xargs->dn != NULL || xargs->containerdn != NULL) {
+			st = EINVAL;
+			snprintf(errbuf, sizeof(errbuf), 
+				 "%s option not supported", arg);
+			krb5_set_error_message(context, st, "%s", errbuf);
+			goto cleanup;
+		    }
+		    dptr = &xargs->containerdn;
+		} else if (strcmp(arg, LINKDN_ARG) == 0) {
+		    if (xargs->dn != NULL || xargs->linkdn != NULL) {
+			st = EINVAL;
+			snprintf(errbuf, sizeof(errbuf), 
+				 "%s option not supported", arg);
+			krb5_set_error_message(context, st, "%s", errbuf);
+			goto cleanup;
+		    }
+		    dptr = &xargs->linkdn;
+		} else {
+		    st = EINVAL;
+		    snprintf(errbuf, sizeof(errbuf), "unknown option: %s", arg);
+		    krb5_set_error_message(context, st, "%s", errbuf);
+		    goto cleanup;
+		}
+		
+		xargs->dn_from_kbd = TRUE;
+		if (arg_val == NULL || strlen(arg_val) == 0) {
+		    st = EINVAL;
+		    snprintf(errbuf, sizeof(errbuf), 
+			     "%s option value missing", arg);
+		    krb5_set_error_message(context, st, "%s", errbuf);
+		    goto cleanup;
+		}
+	    }
+
+	    if (arg_val == NULL) {
+		st = EINVAL;
+		snprintf(errbuf, sizeof(errbuf), 
+			 "%s option value missing", arg);
+		krb5_set_error_message(context, st, "%s", errbuf);
+		goto cleanup;
+	    }
+	    arg_val_len = strlen(arg_val) + 1;
+
+	    if (strcmp(arg, TKTPOLICY_ARG) == 0) {
+		if ((st = krb5_ldap_name_to_policydn (context, 
+						      arg_val, 
+						      dptr)) != 0)
+		    goto cleanup;
+	    } else {
+		*dptr = calloc (1, arg_val_len);
+		if (*dptr == NULL) {
+		    st = ENOMEM;
+		    goto cleanup;
+		}
+		memcpy(*dptr, arg_val, arg_val_len);
+	    }
+	}
+    }
+
+cleanup:
+    return st;
+}
+
+krb5int_access accessor;
+extern int kldap_ensure_initialized (void);
+
+static krb5_error_code
+asn1_encode_sequence_of_keys (krb5_key_data *key_data, krb5_int16 n_key_data,
+			      krb5_int32 mkvno, krb5_data **code)
+{
+    krb5_error_code err;
+
+    /*
+     * This should be pushed back into other library initialization
+     * code.
+     */
+    err = kldap_ensure_initialized ();
+    if (err)
+	return err;
+
+    return accessor.asn1_ldap_encode_sequence_of_keys(key_data, n_key_data,
+						      mkvno, code);
+}
+
+static krb5_error_code
+asn1_decode_sequence_of_keys (krb5_data *in, krb5_key_data **out,
+			      krb5_int16 *n_key_data, int *mkvno)
+{
+    krb5_error_code err;
+
+    /*
+     * This should be pushed back into other library initialization
+     * code.
+     */
+    err = kldap_ensure_initialized ();
+    if (err)
+	return err;
+
+    return accessor.asn1_ldap_decode_sequence_of_keys(in, out, n_key_data,
+						      mkvno);
+}
+
+
+/* Decoding ASN.1 encoded key */
+static struct berval **
+krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data) {
+    struct berval **ret = NULL;
+    int currkvno;
+    int num_versions = 1;
+    int i, j, last;
+    krb5_error_code err = 0;
+
+    if (n_key_data <= 0)
+	return NULL;
+
+    /* Find the number of key versions */
+    for (i = 0; i < n_key_data - 1; i++)
+	if (key_data[i].key_data_kvno != key_data[i + 1].key_data_kvno)
+	    num_versions++;
+
+    ret = (struct berval **) calloc (num_versions + 1, sizeof (struct berval *));
+    if (ret == NULL) {
+	err = ENOMEM;
+	goto cleanup;
+    }
+    for (i = 0, last = 0, j = 0, currkvno = key_data[0].key_data_kvno; i < n_key_data; i++) {
+	krb5_data *code;
+	if (i == n_key_data - 1 || key_data[i + 1].key_data_kvno != currkvno) {
+	    asn1_encode_sequence_of_keys (key_data+last,
+					  (krb5_int16) i - last + 1,
+					  0, /* For now, mkvno == 0*/
+					  &code);
+	    ret[j] = malloc (sizeof (struct berval));
+	    if (ret[j] == NULL) {
+		err = ENOMEM;
+		goto cleanup;
+	    }
+	    /*CHECK_NULL(ret[j]); */
+	    ret[j]->bv_len = code->length;
+	    ret[j]->bv_val = code->data;
+	    j++;
+	    last = i + 1;
+
+	    currkvno = key_data[i].key_data_kvno;
+	}
+    }
+    ret[num_versions] = NULL;
+
+cleanup:
+
+    if (err != 0) {
+	if (ret != NULL) {
+	    for (i = 0; i <= num_versions; i++)
+		if (ret[i] != NULL)
+		    free (ret[i]);
+	    free (ret);
+	    ret = NULL;
+	}
+    }
+
+    return ret;
+}
+
+static krb5_error_code tl_data2berval (krb5_tl_data *in, struct berval **out) {
+    *out = (struct berval *) malloc (sizeof (struct berval));
+    if (*out == NULL)
+	return ENOMEM;
+
+    (*out)->bv_len = in->tl_data_length + 2;
+    (*out)->bv_val =  (char *) malloc ((*out)->bv_len);
+    if ((*out)->bv_val == NULL) {
+	free (*out);
+	return ENOMEM;
+    }
+
+    STORE16_INT((*out)->bv_val, in->tl_data_type);
+    memcpy ((*out)->bv_val + 2, in->tl_data_contents, in->tl_data_length);
+
+    return 0;
+}
+
+krb5_error_code
+krb5_ldap_put_principal(context, entries, nentries, db_args)
+    krb5_context               context;
+    krb5_db_entry              *entries;
+    register int               *nentries;         /* number of entry structs to update */
+    char                       **db_args;
+{
+    int 		        i=0, l=0, kerberos_principal_object_type=0;
+    krb5_error_code 	        st=0, tempst=0;
+    LDAP  		        *ld=NULL;
+    LDAPMessage                 *result=NULL, *ent=NULL;
+    char                        *user=NULL, *subtree=NULL, *principal_dn=NULL;
+    char                        **values=NULL, *strval[10]={NULL}, errbuf[1024];
+    struct berval	        **bersecretkey=NULL;
+    LDAPMod 		        **mods=NULL;
+    krb5_boolean                create_standalone_prinicipal=FALSE;
+    krb5_boolean                krb_identity_exists=FALSE, establish_links=FALSE;
+    char                        *standalone_principal_dn=NULL;
+    krb5_tl_data                *tl_data=NULL;
+    krb5_key_data               **keys=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+    osa_princ_ent_rec 	        princ_ent;
+    xargs_t                     xargs = {0};
+    char                        *polname = NULL;
+    OPERATION optype;
+    krb5_boolean     		found_entry = FALSE;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    SETUP_CONTEXT();
+    if (ldap_context->lrparams == NULL || ldap_context->krbcontainer == NULL)
+	return EINVAL;
+
+    /* get ldap handle */
+    GET_HANDLE();
+
+    for (i=0; i < *nentries; ++i, ++entries) {
+	if (is_principal_in_realm(ldap_context, entries->princ) != 0) {
+	    st = EINVAL;
+	    krb5_set_error_message(context, st, "Principal does not belong to the default realm");
+	    goto cleanup;
+	}
+
+	/* get the principal information to act on */
+	if (entries->princ) {
+	    if (((st=krb5_unparse_name(context, entries->princ, &user)) != 0) ||
+		((st=krb5_ldap_unparse_principal_name(user)) != 0))
+		goto cleanup;
+	}
+
+	/* Identity the type of operation, it can be
+	 * add principal or modify principal.
+	 * hack if the entries->mask has KRB_PRINCIPAL flag set
+	 * then it is a add operation
+	 */
+	if (entries->mask & KADM5_PRINCIPAL)
+	    optype = ADD_PRINCIPAL;
+	else
+	    optype = MODIFY_PRINCIPAL;
+
+	if (((st=krb5_get_princ_type(context, entries, &kerberos_principal_object_type)) != 0) ||
+	    ((st=krb5_get_userdn(context, entries, &principal_dn)) != 0))
+	    goto cleanup;
+
+	if ((st=process_db_args(context, db_args, &xargs, optype)) != 0)
+	    goto cleanup;
+
+	if (entries->mask & KADM5_LOAD) {
+	    int              tree = 0, ntrees = 0, princlen = 0, numlentries = 0;
+	    char             **subtreelist = NULL, *filter = NULL;
+
+	    /*  A load operation is special, will do a mix-in (add krbprinc
+	     *  attrs to a non-krb object entry) if an object exists with a
+	     *  matching krbprincipalname attribute so try to find existing
+	     *  object and set principal_dn.  This assumes that the
+	     *  krbprincipalname attribute is unique (only one object entry has
+	     *  a particular krbprincipalname attribute).
+	     */
+	    if (user == NULL) {
+		/* must have principal name for search */
+		st = EINVAL;
+		krb5_set_error_message(context, st, "operation can not continue, principal name not found");
+		goto cleanup;
+	    }
+	    princlen = strlen(FILTER) + strlen(user) + 2 + 1;      /* 2 for closing brackets */
+	    if ((filter = malloc(princlen)) == NULL) {
+		st = ENOMEM;
+		goto cleanup;
+	    }
+	    snprintf(filter, princlen, FILTER"%s))", user);
+
+	    /* get the current subtree list */
+	    if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0)
+		goto cleanup;
+
+	    found_entry = FALSE;
+	    /* search for entry with matching krbprincipalname attribute */
+	    for (tree = 0; found_entry == FALSE && tree < ntrees; ++tree) {
+		result = NULL;
+		if (principal_dn == NULL) {
+		    LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS);
+		} else {
+		    /* just look for entry with principal_dn */
+		    LDAP_SEARCH_1(principal_dn, LDAP_SCOPE_BASE, filter, principal_attributes, IGNORE_STATUS);
+		}
+		if (st == LDAP_SUCCESS) {
+		    numlentries = ldap_count_entries(ld, result);
+		    if (numlentries > 1) {
+			ldap_msgfree(result);
+			free(filter);
+			st = EINVAL;
+			krb5_set_error_message(context, st,
+			    "operation can not continue, more than one entry with principal name \"%s\" found",
+			    user);
+			goto cleanup;
+		    } else if (numlentries == 1) {
+			found_entry = TRUE;
+			if (principal_dn == NULL) {
+			    ent = ldap_first_entry(ld, result);
+			    if (ent != NULL) {
+				/* setting principal_dn will cause that entry to be modified further down */
+				if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) {
+				    ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st);
+				    st = set_ldap_error (context, st, 0);
+				    ldap_msgfree(result);
+				    free(filter);
+				    goto cleanup;
+				}
+			    }
+			}
+		    }
+		    if (result)
+			ldap_msgfree(result);
+		} else if (st != LDAP_NO_SUCH_OBJECT) {
+		    /* could not perform search, return with failure */
+		    st = set_ldap_error (context, st, 0);
+		    free(filter);
+		    goto cleanup;
+		}
+		/* 
+		 * If it isn't found then assume a standalone princ entry is to
+		 * be created.
+		 */
+	    } /* end for (tree = 0; principal_dn == ... */
+
+	    free(filter);
+
+	    if (found_entry == FALSE && principal_dn != NULL) {
+		/* 
+		 * if principal_dn is null then there is code further down to
+		 * deal with setting standalone_principal_dn.  Also note that
+		 * this will set create_standalone_prinicipal true for
+		 * non-mix-in entries which is okay if loading from a dump.
+		 */
+		create_standalone_prinicipal = TRUE;
+		standalone_principal_dn = strdup(principal_dn);
+		CHECK_NULL(standalone_principal_dn);
+	    }
+	} /* end if (entries->mask & KADM5_LOAD */
+
+	/* time to generate the DN information with the help of
+	 * containerdn, principalcontainerreference or
+	 * realmcontainerdn information
+	 */
+	if (principal_dn == NULL && xargs.dn == NULL) { /* creation of standalone principal */
+	    /* get the subtree information */
+	    if (entries->princ->length == 2 && entries->princ->data[0].length == strlen("krbtgt") &&
+		strncmp(entries->princ->data[0].data, "krbtgt", entries->princ->data[0].length) == 0) {
+		/* if the principal is a inter-realm principal, always created in the realm container */
+		subtree = strdup(ldap_context->lrparams->realmdn);
+	    } else if (xargs.containerdn) {
+		if ((st=checkattributevalue(ld, xargs.containerdn, NULL, NULL, NULL)) != 0) {
+		    if (st == KRB5_KDB_NOENTRY || st == KRB5_KDB_CONSTRAINT_VIOLATION) {
+			int ost = st;
+			st = EINVAL;
+			sprintf(errbuf, "'%s' not found: ", xargs.containerdn);
+			prepend_err_str(context, errbuf, st, ost);
+		    }
+		    goto cleanup;
+		}
+		subtree = strdup(xargs.containerdn);
+	    } else if (ldap_context->lrparams->containerref && strlen(ldap_context->lrparams->containerref) != 0) {
+		/*
+		 * Here the subtree should be changed with
+		 * principalcontainerreference attribute value
+		 */
+		subtree = strdup(ldap_context->lrparams->containerref);
+	    } else {
+		subtree = strdup(ldap_context->lrparams->realmdn);
+	    }
+	    CHECK_NULL(subtree);
+
+	    standalone_principal_dn = malloc(strlen("krbprincipalname=") + strlen(user) + strlen(",") +
+					     strlen(subtree) + 1);
+	    CHECK_NULL(standalone_principal_dn);
+	    sprintf(standalone_principal_dn, "krbprincipalname=%s,%s", user, subtree);
+	    /*
+	     * free subtree when you are done using the subtree
+	     * set the boolean create_standalone_prinicipal to TRUE
+	     */
+	    create_standalone_prinicipal = TRUE;
+	    free(subtree);
+	    subtree = NULL;
+	}
+
+	/*
+	 * If the DN information is presented by the user, time to
+	 * validate the input to ensure that the DN falls under
+	 * any of the subtrees
+	 */
+	if (xargs.dn_from_kbd == TRUE) {
+	    /* make sure the DN falls in the subtree */
+	    int              tre=0, dnlen=0, subtreelen=0, ntrees=0;
+	    char             **subtreelist=NULL;
+	    char             *dn=NULL;
+	    krb5_boolean     outofsubtree=TRUE;
+
+	    if (xargs.dn != NULL) {
+		dn = xargs.dn;
+	    } else if (xargs.linkdn != NULL) {
+		dn = xargs.linkdn;
+	    } else if (standalone_principal_dn != NULL) {
+		/*
+		 * Even though the standalone_principal_dn is constructed
+		 * within this function, there is the containerdn input
+		 * from the user that can become part of the it.
+		 */
+		dn = standalone_principal_dn;
+	    }
+
+	    /* get the current subtree list */
+	    if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0)
+		goto cleanup;
+
+	    for (tre=0; tre<ntrees; ++tre) {
+		if (subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0) {
+		    outofsubtree = FALSE;
+		    break;
+		} else {
+		    dnlen = strlen (dn);
+		    subtreelen = strlen(subtreelist[tre]);
+		    if ((dnlen >= subtreelen) && (strcasecmp((dn + dnlen - subtreelen), subtreelist[tre]) == 0)) {
+			outofsubtree = FALSE;
+			break;
+		    }
+		}
+	    }
+
+	    for (tre=0; tre < ntrees; ++tre) {
+		free(subtreelist[tre]);
+	    }
+
+	    if (outofsubtree == TRUE) {
+		st = EINVAL;
+		krb5_set_error_message(context, st, "DN is out of the realm subtree");
+		goto cleanup;
+	    }
+
+	    /*
+	     * dn value will be set either by dn, linkdn or the standalone_principal_dn
+	     * In the first 2 cases, the dn should be existing and in the last case we
+	     * are supposed to create the ldap object. so the below should not be
+	     * executed for the last case.
+	     */
+
+	    if (standalone_principal_dn == NULL) {
+		/*
+		 * If the ldap object is missing, this results in an error.
+		 */
+
+		/*
+		 * Search for krbprincipalname attribute here.
+		 * This is to find if a kerberos identity is already present
+		 * on the ldap object, in which case adding a kerberos identity
+		 * on the ldap object should result in an error.
+		 */
+		char  *attributes[]={"krbticketpolicyreference", "krbprincipalname", NULL};
+
+		LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS);
+		if (st == LDAP_SUCCESS) {
+		    ent = ldap_first_entry(ld, result);
+		    if (ent != NULL) {
+			if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) {
+			    ldap_value_free(values);
+			}
+
+			if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
+			    krb_identity_exists = TRUE;
+			    ldap_value_free(values);
+			}
+		    }
+		    ldap_msgfree(result);
+		} else {
+		    st = set_ldap_error(context, st, OP_SEARCH);
+		    goto cleanup;
+		}
+	    }
+	}
+
+	/*
+	 * If xargs.dn is set then the request is to add a
+	 * kerberos principal on a ldap object, but if
+	 * there is one already on the ldap object this
+	 * should result in an error.
+	 */
+
+	if (xargs.dn != NULL && krb_identity_exists == TRUE) {
+	    st = EINVAL;
+	    snprintf(errbuf, sizeof(errbuf), "ldap object is already kerberized");
+	    krb5_set_error_message(context, st, "%s", errbuf);
+	    goto cleanup;
+	}
+
+	if (xargs.linkdn != NULL) {
+	    /*
+	     * link information can be changed using modprinc.
+	     * However, link information can be changed only on the
+	     * standalone kerberos principal objects. A standalone
+	     * kerberos principal object is of type krbprincipal
+	     * structural objectclass.
+	     *
+	     * NOTE: kerberos principals on an ldap object can't be
+	     * linked to other ldap objects.
+	     */
+	    if (optype == MODIFY_PRINCIPAL &&
+		kerberos_principal_object_type != KDB_STANDALONE_PRINCIPAL_OBJECT) {
+		st = EINVAL;
+		snprintf(errbuf, sizeof(errbuf),
+		    "link information can not be set/updated as the kerberos principal belongs to an ldap object");
+		krb5_set_error_message(context, st, "%s", errbuf);
+		goto cleanup;
+	    }
+            /*
+             * Check the link information. If there is already a link
+             * existing then this operation is not allowed.
+             */
+            {
+                char **linkdns=NULL;
+                int  j=0;
+
+                if ((st=krb5_get_linkdn(context, entries, &linkdns)) != 0) {
+                    snprintf(errbuf, sizeof(errbuf),
+                             "Failed getting object references");
+                    krb5_set_error_message(context, st, "%s", errbuf);
+                    goto cleanup;
+                }
+                if (linkdns != NULL) {
+                    st = EINVAL;
+                    snprintf(errbuf, sizeof(errbuf),
+                             "kerberos principal is already linked "
+                             "to a ldap object");
+                    krb5_set_error_message(context, st, "%s", errbuf);
+                    for (j=0; linkdns[j] != NULL; ++j)
+                        free (linkdns[j]);
+                    free (linkdns);
+                    goto cleanup;
+                }
+            }
+
+	    establish_links = TRUE;
+	}
+
+	if ((entries->last_success)!=0) {
+	    memset(strval, 0, sizeof(strval));
+	    if ((strval[0]=getstringtime(entries->last_success)) == NULL)
+		goto cleanup;
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastSuccessfulAuth", LDAP_MOD_REPLACE, strval)) != 0) {
+		free (strval[0]);
+		goto cleanup;
+	    }
+	    free (strval[0]);
+	}
+
+	if (entries->last_failed!=0) {
+	    memset(strval, 0, sizeof(strval));
+	    if ((strval[0]=getstringtime(entries->last_failed)) == NULL)
+		goto cleanup;
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastFailedAuth", LDAP_MOD_REPLACE, strval)) != 0) {
+		free (strval[0]);
+		goto cleanup;
+	    }
+	    free(strval[0]);
+	}
+
+	if (entries->fail_auth_count!=0) {
+	    if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_REPLACE, entries->fail_auth_count)) !=0)
+		goto cleanup;
+	}
+
+	if (entries->mask & KADM5_MAX_LIFE) {
+	    if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entries->max_life)) != 0)
+		goto cleanup;
+	}
+
+	if (entries->mask & KADM5_MAX_RLIFE) {
+	    if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE,
+					      entries->max_renewable_life)) != 0)
+		goto cleanup;
+	}
+
+	if (entries->mask & KADM5_ATTRIBUTES) {
+	    if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE,
+					      entries->attributes)) != 0)
+		goto cleanup;
+	}
+
+	if (entries->mask & KADM5_PRINCIPAL) {
+	    memset(strval, 0, sizeof(strval));
+	    strval[0] = user;
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_REPLACE, strval)) != 0)
+		goto cleanup;
+	}
+
+	if (entries->mask & KADM5_PRINC_EXPIRE_TIME) {
+	    memset(strval, 0, sizeof(strval));
+	    if ((strval[0]=getstringtime(entries->expiration)) == NULL)
+		goto cleanup;
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalexpiration", LDAP_MOD_REPLACE, strval)) != 0) {
+		free (strval[0]);
+		goto cleanup;
+	    }
+	    free (strval[0]);
+	}
+
+	if (entries->mask & KADM5_PW_EXPIRATION) {
+	    memset(strval, 0, sizeof(strval));
+	    if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL)
+		goto cleanup;
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration",
+					      LDAP_MOD_REPLACE,
+					      strval)) != 0) {
+		free (strval[0]);
+		goto cleanup;
+	    }
+	    free (strval[0]);
+	}
+
+	if (entries->mask & KADM5_POLICY) {
+	    memset(&princ_ent, 0, sizeof(princ_ent));
+	    for (tl_data=entries->tl_data; tl_data; tl_data=tl_data->tl_data_next) {
+		if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) {
+		    /* FIX ME: I guess the princ_ent should be freed after this call */
+		    if ((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) {
+			goto cleanup;
+		    }
+		}
+	    }
+
+	    if (princ_ent.aux_attributes & KADM5_POLICY) {
+		memset(strval, 0, sizeof(strval));
+		if ((st = krb5_ldap_name_to_policydn (context, princ_ent.policy, &polname)) != 0)
+		    goto cleanup;
+		strval[0] = polname;
+		if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, strval)) != 0)
+		    goto cleanup;
+	    } else {
+		st = EINVAL;
+		krb5_set_error_message(context, st, "Password policy value null");
+		goto cleanup;
+	    }
+	} else if (entries->mask & KADM5_LOAD && found_entry == TRUE) {
+	    /* 
+	     * a load is special in that existing entries must have attrs that
+	     * removed.
+	     */
+
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, NULL)) != 0)
+		goto cleanup;
+	}
+
+	if (entries->mask & KADM5_POLICY_CLR) {
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_DELETE, NULL)) != 0)
+		goto cleanup;
+	}
+
+	if (entries->mask & KADM5_KEY_DATA || entries->mask & KADM5_KVNO) {
+	    bersecretkey = krb5_encode_krbsecretkey (entries->key_data,
+						     entries->n_key_data);
+
+	    if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey",
+					      LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, bersecretkey)) != 0)
+		goto cleanup;
+
+	    if (!(entries->mask & KADM5_PRINCIPAL)) {
+		memset(strval, 0, sizeof(strval));
+		if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL)
+		    goto cleanup;
+		if ((st=krb5_add_str_mem_ldap_mod(&mods,
+						  "krbpasswordexpiration",
+						  LDAP_MOD_REPLACE, strval)) != 0) {
+		    free (strval[0]);
+		    goto cleanup;
+		}
+		free (strval[0]);
+	    }
+
+	    /* Update last password change whenever a new key is set */
+	    {
+		krb5_timestamp last_pw_changed;
+		if ((st=krb5_dbe_lookup_last_pwd_change(context, entries,
+							&last_pw_changed)) != 0)
+		    goto cleanup;
+
+		memset(strval, 0, sizeof(strval));
+		if ((strval[0] = getstringtime(last_pw_changed)) == NULL)
+		    goto cleanup;
+
+		if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastPwdChange",
+						  LDAP_MOD_REPLACE, strval)) != 0) {
+		    free (strval[0]);
+		    goto cleanup;
+		}
+		free (strval[0]);
+	    }
+
+	} /* Modify Key data ends here */
+
+	/* Set tl_data */
+	if (entries->tl_data != NULL) {
+	    int count = 0;
+	    struct berval **ber_tl_data = NULL;
+	    krb5_tl_data *ptr;
+	    for (ptr = entries->tl_data; ptr != NULL; ptr = ptr->tl_data_next) {
+		if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE
+#ifdef SECURID
+		    || ptr->tl_data_type == KRB5_TL_DB_ARGS
+#endif
+		    || ptr->tl_data_type == KRB5_TL_KADM_DATA
+		    || ptr->tl_data_type == KDB_TL_USER_INFO)
+		    continue;
+		count++;
+	    }
+	    if (count != 0) {
+		int j;
+		ber_tl_data = (struct berval **) calloc (count + 1,
+							 sizeof (struct berval*));
+		if (ber_tl_data == NULL) {
+		    st = ENOMEM;
+		    goto cleanup;
+		}
+		for (j = 0, ptr = entries->tl_data; ptr != NULL; ptr = ptr->tl_data_next) {
+		    /* Ignore tl_data that are stored in separate directory
+		     * attributes */
+		    if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE
+#ifdef SECURID
+			|| ptr->tl_data_type == KRB5_TL_DB_ARGS
+#endif
+			|| ptr->tl_data_type == KRB5_TL_KADM_DATA
+			|| ptr->tl_data_type == KDB_TL_USER_INFO)
+			continue;
+		    if ((st = tl_data2berval (ptr, &ber_tl_data[j])) != 0)
+			break;
+		    j++;
+		}
+		if (st != 0) {
+		    for (j = 0; ber_tl_data[j] != NULL; j++) {
+			free (ber_tl_data[j]->bv_val);
+			free (ber_tl_data[j]);
+		    }
+		    free (ber_tl_data);
+		    goto cleanup;
+		}
+		ber_tl_data[count] = NULL;
+		if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbExtraData",
+						  LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
+						  ber_tl_data)) != 0)
+		    goto cleanup;
+	    }
+	}
+
+	/* Directory specific attribute */
+	if (xargs.tktpolicydn != NULL) {
+	    int tmask=0;
+
+	    if (strlen(xargs.tktpolicydn) != 0) {
+		st = checkattributevalue(ld, xargs.tktpolicydn, "objectclass", policyclass, &tmask);
+		CHECK_CLASS_VALIDITY(st, tmask, "ticket policy object value: ");
+
+		strval[0] = xargs.tktpolicydn;
+		strval[1] = NULL;
+		if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_REPLACE, strval)) != 0)
+		    goto cleanup;
+
+	    } else {
+		/* if xargs.tktpolicydn is a empty string, then delete
+		 * already existing krbticketpolicyreference attr */
+		if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_DELETE, NULL)) != 0)
+		    goto cleanup;
+	    }
+
+	}
+
+	if (establish_links == TRUE) {
+	    memset(strval, 0, sizeof(strval));
+	    strval[0] = xargs.linkdn;
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbObjectReferences", LDAP_MOD_REPLACE, strval)) != 0)
+		goto cleanup;
+	}
+
+	/*
+	 * in case mods is NULL then return
+	 * not sure but can happen in a modprinc
+	 * so no need to return an error
+	 * addprinc will at least have the principal name
+	 * and the keys passed in
+	 */
+	if (mods == NULL)
+	    goto cleanup;
+
+	if (create_standalone_prinicipal == TRUE) {
+	    memset(strval, 0, sizeof(strval));
+	    strval[0] = "krbprincipal";
+	    strval[1] = "krbprincipalaux";
+	    strval[2] = "krbTicketPolicyAux";
+
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+		goto cleanup;
+
+	    st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL);
+	    if (st == LDAP_ALREADY_EXISTS && entries->mask & KADM5_LOAD) {
+		/* a load operation must replace an existing entry */
+		st = ldap_delete_ext_s(ld, standalone_principal_dn, NULL, NULL);
+		if (st != LDAP_SUCCESS) {
+		    sprintf(errbuf, "Principal delete failed (trying to replace entry): %s",
+			ldap_err2string(st));
+		    st = translate_ldap_error (st, OP_ADD);
+		    krb5_set_error_message(context, st, "%s", errbuf);
+		    goto cleanup;
+		} else {
+		    st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL);
+		}
+	    }
+	    if (st != LDAP_SUCCESS) {
+		sprintf(errbuf, "Principal add failed: %s", ldap_err2string(st));
+		st = translate_ldap_error (st, OP_ADD);
+		krb5_set_error_message(context, st, "%s", errbuf);
+		goto cleanup;
+	    }
+	} else {
+	    /*
+	     * Here existing ldap object is modified and can be related
+	     * to any attribute, so always ensure that the ldap
+	     * object is extended with all the kerberos related
+	     * objectclasses so that there are no constraint
+	     * violations.
+	     */
+	    {
+		char *attrvalues[] = {"krbprincipalaux", "krbTicketPolicyAux", NULL};
+		int p, q, r=0, amask=0;
+
+		if ((st=checkattributevalue(ld, (xargs.dn) ? xargs.dn : principal_dn,
+					    "objectclass", attrvalues, &amask)) != 0)
+		    goto cleanup;
+
+		memset(strval, 0, sizeof(strval));
+		for (p=1, q=0; p<=2; p<<=1, ++q) {
+		    if ((p & amask) == 0)
+			strval[r++] = attrvalues[q];
+		}
+		if (r != 0) {
+		    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+			goto cleanup;
+		}
+	    }
+	    if (xargs.dn != NULL)
+		st=ldap_modify_ext_s(ld, xargs.dn, mods, NULL, NULL);
+	    else
+		st = ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL);
+
+	    if (st != LDAP_SUCCESS) {
+		sprintf(errbuf, "User modification failed: %s", ldap_err2string(st));
+		st = translate_ldap_error (st, OP_MOD);
+		krb5_set_error_message(context, st, "%s", errbuf);
+		goto cleanup;
+	    }
+	}
+    }
+
+cleanup:
+    if (user)
+	free(user);
+
+    free_xargs(xargs);
+
+    if (standalone_principal_dn)
+	free(standalone_principal_dn);
+
+    if (principal_dn)
+	free (principal_dn);
+
+    if (polname != NULL)
+	free(polname);
+
+    if (subtree)
+	free (subtree);
+
+    if (bersecretkey) {
+	for (l=0; bersecretkey[l]; ++l) {
+	    if (bersecretkey[l]->bv_val)
+		free (bersecretkey[l]->bv_val);
+	    free (bersecretkey[l]);
+	}
+	free (bersecretkey);
+    }
+
+    if (keys)
+	free (keys);
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    *nentries = i;
+    return(st);
+}
+
+krb5_error_code
+krb5_read_tkt_policy (context, ldap_context, entries, policy)
+    krb5_context                context;
+    krb5_ldap_context           *ldap_context;
+    krb5_db_entry               *entries;
+    char                        *policy;
+{
+    krb5_error_code             st=0;
+    unsigned int                mask=0, omask=0;
+    int                         tkt_mask=(KDB_MAX_LIFE_ATTR | KDB_MAX_RLIFE_ATTR | KDB_TKT_FLAGS_ATTR);
+    krb5_ldap_policy_params     *tktpoldnparam=NULL;
+
+    if ((st=krb5_get_attributes_mask(context, entries, &mask)) != 0)
+	goto cleanup;
+
+    if ((mask & tkt_mask) == tkt_mask)
+	goto cleanup;
+
+    if (policy != NULL) {
+	st = krb5_ldap_read_policy(context, policy, &tktpoldnparam, &omask);
+	if (st && st != KRB5_KDB_NOENTRY) {
+	    prepend_err_str(context, "Error reading ticket policy. ", st, st);
+	    goto cleanup;
+	}
+
+	st = 0; /* reset the return status */
+    }
+
+    if ((mask & KDB_MAX_LIFE_ATTR) == 0) {
+	if ((omask & KDB_MAX_LIFE_ATTR) ==  KDB_MAX_LIFE_ATTR)
+	    entries->max_life = tktpoldnparam->maxtktlife;
+	else if (ldap_context->lrparams->max_life)
+	    entries->max_life = ldap_context->lrparams->max_life;
+    }
+
+    if ((mask & KDB_MAX_RLIFE_ATTR) == 0) {
+	if ((omask & KDB_MAX_RLIFE_ATTR) == KDB_MAX_RLIFE_ATTR)
+	    entries->max_renewable_life = tktpoldnparam->maxrenewlife;
+	else if (ldap_context->lrparams->max_renewable_life)
+	    entries->max_renewable_life = ldap_context->lrparams->max_renewable_life;
+    }
+
+    if ((mask & KDB_TKT_FLAGS_ATTR) == 0) {
+	if ((omask & KDB_TKT_FLAGS_ATTR) == KDB_TKT_FLAGS_ATTR)
+	    entries->attributes = tktpoldnparam->tktflags;
+	else if (ldap_context->lrparams->tktflags)
+	    entries->attributes |= ldap_context->lrparams->tktflags;
+    }
+    krb5_ldap_free_policy(context, tktpoldnparam);
+
+cleanup:
+    return st;
+}
+
+krb5_error_code
+krb5_decode_krbsecretkey(context, entries, bvalues, userinfo_tl_data)
+    krb5_context                context;
+    krb5_db_entry               *entries;
+    struct berval               **bvalues;
+    krb5_tl_data                *userinfo_tl_data;
+{
+    char                        *user=NULL;
+    int                         i=0, j=0, noofkeys=0;
+    krb5_key_data               *key_data=NULL, *tmp;
+    krb5_error_code             st=0;
+
+    if ((st=krb5_unparse_name(context, entries->princ, &user)) != 0)
+	goto cleanup;
+
+    for (i=0; bvalues[i] != NULL; ++i) {
+	int mkvno; /* Not used currently */
+	krb5_int16 n_kd;
+	krb5_key_data *kd;
+	krb5_data in;
+
+	if (bvalues[i]->bv_len == 0)
+	    continue;
+	in.length = bvalues[i]->bv_len;
+	in.data = bvalues[i]->bv_val;
+
+	st = asn1_decode_sequence_of_keys (&in,
+					   &kd,
+					   &n_kd,
+					   &mkvno);
+
+	if (st != 0) {
+	    const char *msg = error_message(st);
+	    st = -1; /* Something more appropriate ? */
+	    krb5_set_error_message (context, st,
+				    "unable to decode stored principal key data (%s)", msg);
+	    goto cleanup;
+	}
+	noofkeys += n_kd;
+	tmp = key_data;
+	key_data = realloc (key_data, noofkeys * sizeof (krb5_key_data));
+	if (key_data == NULL) {
+	    key_data = tmp;
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+	for (j = 0; j < n_kd; j++)
+	    key_data[noofkeys - n_kd + j] = kd[j];
+	free (kd);
+    }
+
+    entries->n_key_data = noofkeys;
+    entries->key_data = key_data;
+
+cleanup:
+    ldap_value_free_len(bvalues);
+    free (user);
+    return st;
+}
+
+static char *
+getstringtime(epochtime)
+    krb5_timestamp    epochtime;
+{
+    struct tm           tme;
+    char                *strtime=NULL;
+    time_t		posixtime = epochtime;
+
+    strtime = calloc (50, 1);
+    if (strtime == NULL)
+	return NULL;
+
+    if (gmtime_r(&posixtime, &tme) == NULL)
+	return NULL;
+
+    strftime(strtime, 50, "%Y%m%d%H%M%SZ", &tme);
+    return strtime;
+}
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c
new file mode 100644
index 000000000..6f8b3efd8
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c
@@ -0,0 +1,456 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_pwd_policy.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_pwd_policy.h"
+#include "ldap_err.h"
+
+static char *password_policy_attributes[] = { "cn", "krbmaxpwdlife", "krbminpwdlife",
+					      "krbpwdmindiffchars", "krbpwdminlength",
+					      "krbpwdhistorylength", NULL };
+
+/*
+ * Function to create password policy object.
+ */
+
+krb5_error_code
+krb5_ldap_create_password_policy (context, policy)
+    krb5_context                context;
+    osa_policy_ent_t            policy;
+{
+    krb5_error_code 	        st=0;
+    LDAP  		        *ld=NULL;
+    LDAPMod 		        **mods={NULL};
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+    char                        **rdns=NULL, *strval[2]={NULL}, *policy_dn;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    /* validate the input parameters */
+    if (policy == NULL || policy->name == NULL)
+	return EINVAL;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    st = krb5_ldap_name_to_policydn (context, policy->name, &policy_dn);
+    if (st != 0)
+	goto cleanup;
+
+    /* get the first component of the dn to set the cn attribute */
+    rdns = ldap_explode_dn(policy_dn, 1);
+    if (rdns == NULL) {
+	st = EINVAL;
+	krb5_set_error_message(context, st, "Invalid password policy DN syntax");
+	goto cleanup;
+    }
+
+    strval[0] = rdns[0];
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    strval[0] = "krbPwdPolicy";
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    if (((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxpwdlife", LDAP_MOD_ADD,
+				       (signed) policy->pw_max_life)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbminpwdlife", LDAP_MOD_ADD,
+					  (signed) policy->pw_min_life)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmindiffchars", LDAP_MOD_ADD,
+					  (signed) policy->pw_min_classes)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_ADD,
+					  (signed) policy->pw_min_length)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_ADD,
+					  (signed) policy->pw_history_num)) != 0))
+	goto cleanup;
+
+    /* password policy object creation */
+    if ((st=ldap_add_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_ADD);
+	goto cleanup;
+    }
+
+cleanup:
+    if (rdns)
+	ldap_value_free(rdns);
+
+    if (policy_dn != NULL)
+	free (policy_dn);
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return(st);
+}
+
+/*
+ * Function to modify password policy object.
+ */
+
+krb5_error_code
+krb5_ldap_put_password_policy (context, policy)
+    krb5_context                context;
+    osa_policy_ent_t            policy;
+{
+    char                        *policy_dn;
+    krb5_error_code 	        st=0;
+    LDAP  		        *ld=NULL;
+    LDAPMod 		        **mods=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    /* validate the input parameters */
+    if (policy == NULL || policy->name == NULL)
+	return EINVAL;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    st = krb5_ldap_name_to_policydn (context, policy->name, &policy_dn);
+    if (st != 0)
+	goto cleanup;
+
+    if (((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxpwdlife", LDAP_MOD_REPLACE,
+				       (signed) policy->pw_max_life)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbminpwdlife", LDAP_MOD_REPLACE,
+					  (signed) policy->pw_min_life)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmindiffchars", LDAP_MOD_REPLACE,
+					  (signed) policy->pw_min_classes)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_REPLACE,
+					  (signed) policy->pw_min_length)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_REPLACE,
+					  (signed) policy->pw_history_num)) != 0))
+	goto cleanup;
+
+    /* modify the password policy object. */
+    /*
+     * This will fail if the 'policy_dn' is anywhere other than under the realm
+     * container. This is correct behaviour. 'kdb5_ldap_util' will support
+     * management of only such policy objects.
+     */
+    if ((st=ldap_modify_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_MOD);
+	goto cleanup;
+    }
+
+cleanup:
+    if (policy_dn != NULL)
+	free (policy_dn);
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return(st);
+}
+
+krb5_error_code
+populate_policy(krb5_context context,
+    LDAP *ld,
+    LDAPMessage *ent,
+    char *pol_name,
+    osa_policy_ent_t pol_entry)
+{
+    int st = 0;
+    char *pol_dn;
+
+    pol_entry->name = strdup(pol_name);
+    CHECK_NULL(pol_entry->name);
+    pol_entry->version = 1;
+
+    krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &(pol_entry->pw_max_life));
+    krb5_ldap_get_value(ld, ent, "krbminpwdlife", &(pol_entry->pw_min_life));
+    krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &(pol_entry->pw_min_classes));
+    krb5_ldap_get_value(ld, ent, "krbpwdminlength", &(pol_entry->pw_min_length));
+    krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &(pol_entry->pw_history_num));
+
+    /* Get the reference count */
+    pol_dn = ldap_get_dn(ld, ent);
+    st = krb5_ldap_get_reference_count (context, pol_dn, "krbPwdPolicyReference",
+	    &(pol_entry->policy_refcnt), ld);
+    ldap_memfree(pol_dn);
+
+cleanup:
+    return st;
+}
+
+krb5_error_code
+krb5_ldap_get_password_policy_from_dn (krb5_context context,
+    char *pol_name,
+    char *pol_dn,
+    osa_policy_ent_t *policy,
+    int *cnt)
+{
+    krb5_error_code             st=0, tempst=0;
+    LDAP  		        *ld=NULL;
+    LDAPMessage                 *result=NULL,*ent=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    /* validate the input parameters */
+    if (pol_dn == NULL)
+	return EINVAL;
+
+    *policy = NULL;
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    *cnt = 0;
+    *(policy) = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec));
+    if (*policy == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    memset(*policy, 0, sizeof(osa_policy_ent_rec));
+
+    LDAP_SEARCH(pol_dn, LDAP_SCOPE_BASE, "(objectclass=krbPwdPolicy)", password_policy_attributes);
+    *cnt = 1;
+#if 0 /************** Begin IFDEF'ed OUT *******************************/
+    (*policy)->name = strdup(name);
+    CHECK_NULL((*policy)->name);
+    (*policy)->version = 1;
+#endif /**************** END IFDEF'ed OUT *******************************/
+
+    ent=ldap_first_entry(ld, result);
+    if (ent != NULL) {
+	if ((st = populate_policy(context, ld, ent, pol_name, *policy)) != 0)
+	    goto cleanup;
+#if 0 /************** Begin IFDEF'ed OUT *******************************/
+	krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &((*policy)->pw_max_life));
+	krb5_ldap_get_value(ld, ent, "krbminpwdlife", &((*policy)->pw_min_life));
+	krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &((*policy)->pw_min_classes));
+	krb5_ldap_get_value(ld, ent, "krbpwdminlength", &((*policy)->pw_min_length));
+	krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &((*policy)->pw_history_num));
+
+	/* Get the reference count */
+	st = krb5_ldap_get_reference_count (context,
+					    name,
+					    "krbPwdPolicyReference",
+					    &(*policy)->policy_refcnt,
+					    ld);
+#endif /**************** END IFDEF'ed OUT *******************************/
+    }
+
+cleanup:
+    ldap_msgfree(result);
+    if (st != 0) {
+	if (*policy != NULL) {
+	    krb5_ldap_free_password_policy(context, *policy);
+	    *policy = NULL;
+	}
+    }
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+/*
+ * Convert 'name' into a directory DN and call
+ * 'krb5_ldap_get_password_policy_from_dn'
+ */
+krb5_error_code
+krb5_ldap_get_password_policy (context, name, policy, cnt)
+    krb5_context                context;
+    char                        *name;
+    osa_policy_ent_t            *policy;
+    int                         *cnt;
+{
+    krb5_error_code             st = 0;
+    char                        *policy_dn = NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    /* validate the input parameters */
+    if (name == NULL) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    st = krb5_ldap_name_to_policydn(context, name, &policy_dn);
+    if (st != 0)
+	goto cleanup;
+
+    st = krb5_ldap_get_password_policy_from_dn(context, name, policy_dn, policy, cnt);
+
+cleanup:
+    if (policy_dn != NULL)
+	free (policy_dn);
+    return st;
+}
+
+krb5_error_code
+krb5_ldap_delete_password_policy (context, policy)
+    krb5_context                context;
+    char                        *policy;
+{
+    int                         mask = 0;
+    char                        *policy_dn = NULL, *class[] = {"krbpwdpolicy", NULL};
+    krb5_error_code             st=0;
+    LDAP                        *ld=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    /* validate the input parameters */
+    if (policy == NULL)
+	return EINVAL;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    st = krb5_ldap_name_to_policydn (context, policy, &policy_dn);
+    if (st != 0)
+	goto cleanup;
+
+    /* Ensure that the object is a password policy */
+    if ((st=checkattributevalue(ld, policy_dn, "objectclass", class, &mask)) != 0)
+	goto cleanup;
+
+    if (mask == 0) {
+	st = KRB5_KDB_NOENTRY;
+	goto cleanup;
+    }
+
+    if ((st=ldap_delete_ext_s(ld, policy_dn, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_DEL);
+	goto cleanup;
+    }
+
+cleanup:
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    if (policy_dn != NULL)
+	free (policy_dn);
+
+    return st;
+}
+
+krb5_error_code
+krb5_ldap_iterate_password_policy(context, match_expr, func, func_arg)
+    krb5_context                context;
+    char                        *match_expr;
+    void                        (*func) (krb5_pointer, osa_policy_ent_t);
+    krb5_pointer                func_arg;
+{
+    osa_policy_ent_rec          *entry=NULL;
+    char		        *policy=NULL;
+    krb5_error_code             st=0, tempst=0;
+    LDAP		        *ld=NULL;
+    LDAPMessage	                *result=NULL, *ent=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* Clear the global error string */
+    krb5_clear_error_message(context);
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if (ldap_context->lrparams->realmdn == NULL) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    LDAP_SEARCH(ldap_context->lrparams->realmdn, LDAP_SCOPE_ONELEVEL, "(objectclass=krbpwdpolicy)", password_policy_attributes);
+    for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
+	krb5_boolean attr_present;
+
+	st = krb5_ldap_get_string(ld, ent, "cn", &policy, &attr_present);
+	if (st != 0)
+	    goto cleanup;
+	if (attr_present == FALSE)
+	    continue;
+
+	entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec));
+	CHECK_NULL(entry);
+	memset(entry, 0, sizeof(osa_policy_ent_rec));
+	if ((st = populate_policy(context, ld, ent, policy, entry)) != 0)
+	    goto cleanup;
+#if 0 /************** Begin IFDEF'ed OUT *******************************/
+	entry->name = policy;
+	entry->version = 1;
+
+	krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &(entry->pw_max_life));
+	krb5_ldap_get_value(ld, ent, "krbminpwdlife", &(entry->pw_min_life));
+	krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &(entry->pw_min_classes));
+	krb5_ldap_get_value(ld, ent, "krbpwdminlength", &(entry->pw_min_length));
+	krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &(entry->pw_history_num));
+
+	/* Get the reference count */
+	st = krb5_ldap_get_reference_count (context,
+					    policy,
+					    "krbPwdPolicyReference",
+					    &(entry->policy_refcnt),
+					    ld);
+#endif /**************** END IFDEF'ed OUT *******************************/
+
+	(*func)(func_arg, entry);
+	/* XXX this will free policy so don't free it */
+	krb5_ldap_free_password_policy(context, entry);
+	entry = NULL;
+    }
+    ldap_msgfree(result);
+
+cleanup:
+    if (entry)
+	free (entry);
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+void
+krb5_ldap_free_password_policy (context, entry)
+    krb5_context                context;
+    osa_policy_ent_t            entry;
+{
+    if (entry) {
+	if (entry->name)
+	    free(entry->name);
+	free(entry);
+    }
+    return;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h
new file mode 100644
index 000000000..49fa85ecb
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h
@@ -0,0 +1,54 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_pwd_policy.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_KRBPWDPOLICY_H_
+#define _LDAP_KRBPWDPOLICY_H_
+ 
+krb5_error_code
+krb5_ldap_get_password_policy (krb5_context , char *, osa_policy_ent_t *, int *);
+
+krb5_error_code
+krb5_ldap_create_password_policy (krb5_context , osa_policy_ent_t );
+
+krb5_error_code
+krb5_ldap_put_password_policy ( krb5_context kcontext, osa_policy_ent_t policy );
+
+krb5_error_code
+krb5_ldap_delete_password_policy ( krb5_context kcontext, char *policy );
+
+krb5_error_code
+krb5_ldap_iterate_password_policy(krb5_context, char *, 
+				  void (*) (krb5_pointer, osa_policy_ent_t ),
+				  krb5_pointer);
+
+void
+krb5_ldap_free_password_policy( krb5_context kcontext, osa_policy_ent_t entry );
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
new file mode 100644
index 000000000..3ab49dbc1
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
@@ -0,0 +1,1490 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_realm.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "ldap_main.h"
+#include "ldap_realm.h"
+#include "ldap_principal.h"
+#include "ldap_pwd_policy.h"
+#include "ldap_err.h"
+
+#define END_OF_LIST -1
+char  *realm_attributes[] = {"krbSearchScope","krbSubTrees", "krbPrincContainerRef", 
+			     "krbMaxTicketLife", "krbMaxRenewableAge",
+			     "krbTicketFlags", "krbUpEnabled",
+			     "krbTicketPolicyReference",
+			     "krbLdapServers",
+			     "krbKdcServers",  "krbAdmServers",
+			     "krbPwdServers", NULL};
+
+
+char  *policy_attributes[] = { "krbMaxTicketLife",
+			       "krbMaxRenewableAge",
+			       "krbTicketFlags",
+			       NULL };
+
+
+
+char  *policyclass[] =     { "krbTicketPolicy", NULL };
+char  *kdcclass[] =        { "krbKdcService", NULL };
+char  *adminclass[] =      { "krbAdmService", NULL };
+char  *pwdclass[] =        { "krbPwdService", NULL };
+char  *subtreeclass[] =    { "Organization", "OrganizationalUnit", "Domain", "krbContainer",
+                             "krbRealmContainer", "Country", "Locality", NULL };
+
+
+char  *krbContainerRefclass[] = { "krbContainerRefAux", NULL};
+
+/*
+ * list realms from eDirectory
+ */
+
+/*
+ * Function to remove all special characters from a string (rfc2254).
+ * Use whenever exact matching is to be done ...
+ */
+char *ldap_filter_correct (char *in)
+{
+    size_t i, count;
+    char *out, *ptr;
+    size_t len = strlen(in);
+
+    for (i = 0, count = 0; i < len; i++)
+	switch (in[i]) {
+	case '*':
+	case '(':
+	case ')':
+	case '\\':
+	case '\0':
+	    count ++;
+	}
+
+    out = (char *)malloc((len + (count * 2) + 1) * sizeof (char));
+    assert (out != NULL);
+    memset(out, 0, len + (count * 2) + 1);
+
+    for (i = 0, ptr = out; i < len; i++)
+	switch (in[i]) {
+	case '*':
+	    ptr[0] = '\\';
+	    ptr[1] = '2';
+	    ptr[2] = 'a';
+	    ptr += 3;
+	    break;
+	case '(':
+	    ptr[0] = '\\';
+	    ptr[1] = '2';
+	    ptr[2] = '8';
+	    ptr += 3;
+	    break;
+	case ')':
+	    ptr[0] = '\\';
+	    ptr[1] = '2';
+	    ptr[2] = '9';
+	    ptr += 3;
+	    break;
+	case '\\':
+	    ptr[0] = '\\';
+	    ptr[1] = '5';
+	    ptr[2] = 'c';
+	    ptr += 3;
+	    break;
+	case '\0':
+	    ptr[0] = '\\';
+	    ptr[1] = '0';
+	    ptr[2] = '0';
+	    ptr += 3;
+	    break;
+	default:
+	    ptr[0] = in[i];
+	    ptr += 1;
+	    break;
+	}
+
+    /* ptr[count - 1] = '\0'; */
+
+    return out;
+}
+
+static int principal_in_realm_2(krb5_principal principal, char *realm) {
+    /* Cross realm trust ... */
+    if (principal->length == 2 &&
+	principal->data[0].length == sizeof ("krbtgt") &&
+	strncasecmp (principal->data[0].data, "krbtgt", sizeof ("krbtgt")) &&
+	principal->data[1].length == strlen (realm) &&
+	strncasecmp (principal->data[1].data, realm, strlen (realm)))
+	return 0;
+
+    if (strlen(realm) != principal->realm.length)
+	return 1;
+
+    if (strncasecmp(realm, principal->realm.data, principal->realm.length) != 0)
+	return 1;
+
+    return 0;
+}
+
+/*
+ * Lists the realms in the Directory.
+ */
+
+krb5_error_code
+krb5_ldap_list_realm(context, realms)
+    krb5_context	        context;
+    char                        ***realms;
+{
+    char                        **values = NULL;
+    unsigned int                i = 0;
+    int                		count = 0;
+    krb5_error_code             st = 0, tempst = 0;
+    LDAP                        *ld = NULL;
+    LDAPMessage                 *result = NULL, *ent = NULL;
+    kdb5_dal_handle             *dal_handle = NULL;
+    krb5_ldap_context           *ldap_context = NULL;
+    krb5_ldap_server_handle     *ldap_server_handle = NULL;
+
+    SETUP_CONTEXT ();
+
+    /* get the kerberos container DN information */
+    if (ldap_context->krbcontainer == NULL) {
+	if ((st = krb5_ldap_read_krbcontainer_params(context,
+						     &(ldap_context->krbcontainer))) != 0)
+	    goto cleanup;
+    }
+
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    {
+	char *cn[] = {"cn", NULL};
+	LDAP_SEARCH(ldap_context->krbcontainer->DN,
+		    LDAP_SCOPE_ONELEVEL,
+		    "(objectclass=krbRealmContainer)",
+		    cn);
+    }
+
+    *realms = NULL;
+
+    count = ldap_count_entries (ld, result);
+    if (count == -1) {
+	ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st);
+	st = set_ldap_error (context, st, OP_SEARCH);
+	goto cleanup;
+    }
+
+    *realms = calloc(count+1, sizeof (char *));
+    CHECK_NULL(*realms);
+
+    for (ent = ldap_first_entry(ld, result), count = 0; ent != NULL;
+	 ent = ldap_next_entry(ld, ent)) {
+
+	if ((values = ldap_get_values (ld, ent, "cn")) != NULL) {
+
+	    (*realms)[count] = strdup(values[0]);
+	    CHECK_NULL((*realms)[count]);
+	    count += 1;
+
+	    ldap_value_free(values);
+	}
+    } /* for (ent= ... */
+    ldap_msgfree(result);
+
+cleanup:
+
+    /* some error, free up all the memory */
+    if (st != 0) {
+	if (*realms) {
+	    for (i=0; (*realms)[i] != NULL; ++i) {
+		free ((*realms)[i]);
+	    }
+	    free (*realms);
+	    *realms = NULL;
+	}
+    }
+
+    /* If there are no elements, still return a NULL terminated array */
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+/*
+ * Delete the realm along with the principals belonging to the realm in the Directory.
+ */
+
+static void
+delete_password_policy (krb5_pointer ptr, osa_policy_ent_t pol)
+{
+    krb5_ldap_delete_password_policy ((krb5_context)ptr, pol->name);
+}
+
+krb5_error_code
+krb5_ldap_delete_realm (context, lrealm)
+    krb5_context                context;
+    char                        *lrealm;
+{
+    LDAP                        *ld = NULL;
+    krb5_error_code             st = 0, tempst=0;
+    char                        **values=NULL, **subtrees=NULL, **policy=NULL;
+    LDAPMessage                 **result_arr=NULL, *result = NULL, *ent = NULL;
+    krb5_principal              principal;
+    int                         l=0, ntree=0, i=0, j=0, mask=0;
+    kdb5_dal_handle             *dal_handle = NULL;
+    krb5_ldap_context           *ldap_context = NULL;
+    krb5_ldap_server_handle     *ldap_server_handle = NULL;
+    krb5_ldap_realm_params      *rparam=NULL;
+
+    SETUP_CONTEXT ();
+
+    if (lrealm == NULL) {
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Realm information not available");
+	goto cleanup;
+    }
+
+    if ((st=krb5_ldap_read_realm_params(context, lrealm, &rparam, &mask)) != 0)
+	goto cleanup;
+
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    /* delete all the principals belonging to the realm in the tree */
+    {
+	char *attr[] = {"krbprincipalname", NULL}, *realm=NULL, filter[256];
+	krb5_ldap_context lcontext;
+
+	realm = ldap_filter_correct (lrealm);
+	assert (sizeof (filter) >= sizeof ("(krbprincipalname=)") +
+		strlen (realm) + 2 /* "*@" */ + 1);
+
+	sprintf (filter, "(krbprincipalname=*@%s)", realm);
+	free (realm);
+
+	/* LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, filter, attr); */
+	memset(&lcontext, 0, sizeof(krb5_ldap_context));
+	lcontext.lrparams = rparam;
+	if ((st=krb5_get_subtree_info(&lcontext, &subtrees, &ntree)) != 0)
+	    goto cleanup;
+
+        result_arr = (LDAPMessage **)  calloc(ntree+1, sizeof(LDAPMessage *));
+        if (result_arr == NULL) {
+            st = ENOMEM;
+            goto cleanup;
+        }
+
+	for (l=0; l < ntree; ++l) {
+	    LDAP_SEARCH(subtrees[l], rparam->search_scope, filter, attr);
+	    result_arr[l] = result;
+	}
+    }
+
+    /* NOTE: Here all the principals should be cached and the ldap handle should be freed,
+     * as a DAL-LDAP interface is called right down here. Caching might be constrained by
+     * availability of the memory. The caching is not done, however there would be limit
+     * on the minimum number of handles for a server and it is 2. As the DAL-LDAP is not
+     * thread-safe this should suffice.
+     */
+    for (j=0; (result=result_arr[j]) != NULL; ++j) {
+	for (ent = ldap_first_entry (ld, result); ent != NULL;
+	     ent = ldap_next_entry (ld, ent)) {
+	    if ((values = ldap_get_values(ld, ent, "krbPrincipalName")) != NULL) {
+		for (i = 0; values[i] != NULL; ++i) {
+		    krb5_parse_name(context, values[i], &principal);
+		    if (principal_in_realm_2(principal, lrealm) == 0) {
+			int nent = 0;
+			if ((st=krb5_ldap_delete_principal(context, principal,
+							   &nent)) != LDAP_SUCCESS)
+			    goto cleanup;
+		    }
+		    krb5_free_principal(context, principal);
+		}
+		ldap_value_free(values);
+	    }
+	}
+	ldap_msgfree(result);
+    }
+
+    /* Delete all password policies */
+    krb5_ldap_iterate_password_policy (context, "*", delete_password_policy, context);
+
+    /* Delete all ticket policies */
+    {
+	if ((st = krb5_ldap_list_policy (context, ldap_context->lrparams->realmdn, &policy)) != 0) {
+	    prepend_err_str (context, "Error reading ticket policy: ", st, st);
+	    goto cleanup;
+	}
+
+	for (i = 0; policy [i] != NULL; i++)
+	    krb5_ldap_delete_policy(context, policy[i]);
+    }
+
+    /* Delete the realm object */
+    if ((st=ldap_delete_ext_s(ld, ldap_context->lrparams->realmdn, NULL, NULL)) != LDAP_SUCCESS) {
+	int ost = st;
+	st = translate_ldap_error (st, OP_DEL);
+	krb5_set_error_message (context, st, "Realm Delete FAILED: %s",
+				ldap_err2string(ost));
+    }
+
+cleanup:
+    if (subtrees) {
+	for (l=0; l < ntree; ++l) {
+	if (subtrees[l])
+	    free (subtrees[l]);
+        }
+	free (subtrees);
+    }
+
+    if (policy != NULL) {
+	for (i = 0; policy[i] != NULL; i++)
+	    free (policy[i]);
+	free (policy);
+    }
+
+    krb5_ldap_free_realm_params(rparam);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * Modify the realm attributes in the Directory.
+ */
+
+krb5_error_code
+krb5_ldap_modify_realm(context, rparams, mask)
+    krb5_context             context;
+    krb5_ldap_realm_params   *rparams;
+    int                      mask;
+{
+    LDAP                  *ld=NULL;
+    krb5_error_code       st=0;
+    char                  **strval=NULL, *strvalprc[5]={NULL};
+#ifdef HAVE_EDIRECTORY
+    char                  **values=NULL;
+    char                  **oldkdcservers=NULL, **oldadminservers=NULL, **oldpasswdservers=NULL;
+    LDAPMessage           *result=NULL, *ent=NULL;
+    int                   count=0;
+    char errbuf[1024];
+#endif
+    LDAPMod               **mods = NULL;
+#ifdef HAVE_EDIRECTORY
+    int                   i=0;
+#endif
+    int                   oldmask=0, objectmask=0,k=0;
+    kdb5_dal_handle       *dal_handle=NULL;
+    krb5_ldap_context     *ldap_context=NULL;
+    krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+    if (mask == 0)
+	return 0;
+
+    if (rparams == NULL) {
+	st = EINVAL;
+	return st;
+    }
+
+    SETUP_CONTEXT ();
+
+    /* Check validity of arguments */
+    if (ldap_context->krbcontainer == NULL ||
+	rparams->tl_data == NULL ||
+	rparams->tl_data->tl_data_contents == NULL ||
+	((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
+	((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) ||
+#ifdef HAVE_EDIRECTORY
+	((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) ||
+	((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) ||
+	((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) ||
+#endif
+	0) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    /* get the oldmask obtained from the krb5_ldap_read_realm_params */
+    {
+	void *voidptr=NULL;
+
+	if ((st=decode_tl_data(rparams->tl_data, KDB_TL_MASK, &voidptr)) == 0) {
+	    oldmask = *((int *) voidptr);
+	    free (voidptr);
+	} else {
+	    st = EINVAL;
+	    krb5_set_error_message (context, st, "tl_data not available");
+	    return st;
+	}
+    }
+
+
+    /* SUBTREE ATTRIBUTE */
+    if (mask & LDAP_REALM_SUBTREE) {
+        if ( rparams->subtree!=NULL)  {
+            /*replace the subtrees with the present if the subtrees are present*/
+            for(k=0;k<rparams->subtreecount && rparams->subtree[k]!=NULL;k++) {
+                    if (strlen(rparams->subtree[k]) != 0) {
+                        st = checkattributevalue(ld, rparams->subtree[k], "Objectclass", subtreeclass,
+                                &objectmask);
+                        CHECK_CLASS_VALIDITY(st, objectmask, "subtree value: ");
+                    }
+            }
+	    strval = rparams->subtree;
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_REPLACE,
+					    strval)) != 0) {
+	       goto cleanup;
+	    }
+        }
+    }
+
+    /* CONTAINERREF ATTRIBUTE */
+    if (mask & LDAP_REALM_CONTREF) {
+        if (strlen(rparams->containerref) != 0 ) {
+            st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
+                     &objectmask);
+            CHECK_CLASS_VALIDITY(st, objectmask, "container reference value: ");
+            strvalprc[0] = rparams->containerref;
+            strvalprc[1] = NULL;
+            if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_REPLACE,
+                            strvalprc)) != 0)
+                goto cleanup;
+        }
+    }
+
+    /* SEARCHSCOPE ATTRIBUTE */
+    if (mask & LDAP_REALM_SEARCHSCOPE) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE,
+					  (rparams->search_scope == LDAP_SCOPE_ONELEVEL
+					   || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
+					  rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_REALM_MAXRENEWLIFE) {
+
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE,
+					  rparams->max_renewable_life)) != 0)
+	    goto cleanup;
+    }
+
+    /* krbMaxTicketLife ATTRIBUTE */
+
+    if (mask & LDAP_REALM_MAXTICKETLIFE) {
+
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE,
+					  rparams->max_life)) != 0)
+	    goto cleanup;
+    }
+
+    /* krbTicketFlags ATTRIBUTE */
+
+    if (mask & LDAP_REALM_KRBTICKETFLAGS) {
+
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE,
+					  rparams->tktflags)) != 0)
+	    goto cleanup;
+    }
+
+
+#ifdef HAVE_EDIRECTORY
+
+    /* KDCSERVERS ATTRIBUTE */
+    if (mask & LDAP_REALM_KDCSERVERS) {
+	/* validate the server list */
+	for (i=0; rparams->kdcservers[i] != NULL; ++i) {
+	    st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass,
+				     &objectmask);
+	    CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: ");
+	}
+
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_REPLACE,
+					  rparams->kdcservers)) != 0)
+	    goto cleanup;
+    }
+
+    /* ADMINSERVERS ATTRIBUTE */
+    if (mask & LDAP_REALM_ADMINSERVERS) {
+	/* validate the server list */
+	for (i=0; rparams->adminservers[i] != NULL; ++i) {
+	    st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass,
+				     &objectmask);
+	    CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: ");
+	}
+
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_REPLACE,
+					  rparams->adminservers)) != 0)
+	    goto cleanup;
+    }
+
+    /* PASSWDSERVERS ATTRIBUTE */
+    if (mask & LDAP_REALM_PASSWDSERVERS) {
+	/* validate the server list */
+	for (i=0; rparams->passwdservers[i] != NULL; ++i) {
+	    st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass,
+				     &objectmask);
+	    CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: ");
+	}
+
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_REPLACE,
+					  rparams->passwdservers)) != 0)
+	    goto cleanup;
+    }
+
+    /*
+     * Read the old values of the krbkdcservers, krbadmservers and
+     * krbpwdservers.  This information is later used to decided the
+     * deletions/additions to the list.
+     */
+    if (mask & LDAP_REALM_KDCSERVERS || mask & LDAP_REALM_ADMINSERVERS ||
+	mask & LDAP_REALM_PASSWDSERVERS) {
+	char *servers[] = {"krbKdcServers", "krbAdmServers", "krbPwdServers", NULL};
+
+	if ((st= ldap_search_ext_s(ld,
+				   rparams->realmdn,
+				   LDAP_SCOPE_BASE,
+				   0,
+				   servers,
+				   0,
+				   NULL,
+				   NULL,
+				   NULL,
+				   0,
+				   &result)) != LDAP_SUCCESS) {
+	    st = set_ldap_error (context, st, OP_SEARCH);
+	    goto cleanup;
+	}
+
+	ent = ldap_first_entry(ld, result);
+	if (ent) {
+	    if ((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) {
+		count = ldap_count_values(values);
+		if ((st=copy_arrays(values, &oldkdcservers, count)) != 0)
+		    goto cleanup;
+		ldap_value_free(values);
+	    }
+
+	    if ((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) {
+		count = ldap_count_values(values);
+		if ((st=copy_arrays(values, &oldadminservers, count)) != 0)
+		    goto cleanup;
+		ldap_value_free(values);
+	    }
+
+	    if ((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) {
+		count = ldap_count_values(values);
+		if ((st=copy_arrays(values, &oldpasswdservers, count)) != 0)
+		    goto cleanup;
+		ldap_value_free(values);
+	    }
+	}
+	ldap_msgfree(result);
+    }
+#endif
+
+    /* Realm modify opearation */
+    if (mods != NULL) {
+        if ((st=ldap_modify_ext_s(ld, rparams->realmdn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	    st = set_ldap_error (context, st, OP_MOD);
+	    goto cleanup;
+        }
+    }
+
+#ifdef HAVE_EDIRECTORY
+    /* krbRealmReferences attribute is updated here, depending on the additions/deletions
+     * to the 4 servers' list.
+     */
+    if (mask & LDAP_REALM_KDCSERVERS) {
+	char **newkdcservers=NULL;
+
+	count = ldap_count_values(rparams->kdcservers);
+	if ((st=copy_arrays(rparams->kdcservers, &newkdcservers, count)) != 0)
+	    goto cleanup;
+
+	/* find the deletions and additions to the server list */
+	if (oldkdcservers && newkdcservers)
+	    disjoint_members(oldkdcservers, newkdcservers);
+
+	/* delete the krbRealmReferences attribute from the servers that are dis-associated. */
+	if (oldkdcservers)
+	    for (i=0; oldkdcservers[i]; ++i)
+		if ((st=deleteAttribute(ld, oldkdcservers[i], "krbRealmReferences",
+					rparams->realmdn)) != 0) {
+		    sprintf (errbuf, "Error removing 'krbRealmReferences' from %s: ",
+			     oldkdcservers[i]);
+		    prepend_err_str (context, errbuf, st, st);
+		    goto cleanup;
+		}
+
+	/* add the krbRealmReferences attribute from the servers that are associated. */
+	if (newkdcservers)
+	    for (i=0; newkdcservers[i]; ++i)
+		if ((st=updateAttribute(ld, newkdcservers[i], "krbRealmReferences",
+					rparams->realmdn)) != 0) {
+		    sprintf (errbuf, "Error adding 'krbRealmReferences' to %s: ",
+			     newkdcservers[i]);
+		    prepend_err_str (context, errbuf, st, st);
+		    goto cleanup;
+		}
+
+	if (newkdcservers)
+	    ldap_value_free(newkdcservers);
+    }
+
+    if (mask & LDAP_REALM_ADMINSERVERS) {
+	char **newadminservers=NULL;
+
+	count = ldap_count_values(rparams->adminservers);
+	if ((st=copy_arrays(rparams->adminservers, &newadminservers, count)) != 0)
+	    goto cleanup;
+
+	/* find the deletions and additions to the server list */
+	if (oldadminservers && newadminservers)
+	    disjoint_members(oldadminservers, newadminservers);
+
+	/* delete the krbRealmReferences attribute from the servers that are dis-associated. */
+	if (oldadminservers)
+	    for (i=0; oldadminservers[i]; ++i)
+		if ((st=deleteAttribute(ld, oldadminservers[i], "krbRealmReferences",
+					rparams->realmdn)) != 0) {
+		    sprintf(errbuf, "Error removing 'krbRealmReferences' from "
+			    "%s: ", oldadminservers[i]);
+		    prepend_err_str (context, errbuf, st, st);
+		    goto cleanup;
+		}
+
+	/* add the krbRealmReferences attribute from the servers that are associated. */
+	if (newadminservers)
+	    for (i=0; newadminservers[i]; ++i)
+		if ((st=updateAttribute(ld, newadminservers[i], "krbRealmReferences",
+					rparams->realmdn)) != 0) {
+		    sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+			    newadminservers[i]);
+		    prepend_err_str (context, errbuf, st, st);
+		    goto cleanup;
+		}
+	if (newadminservers)
+	    ldap_value_free(newadminservers);
+    }
+
+    if (mask & LDAP_REALM_PASSWDSERVERS) {
+	char **newpasswdservers=NULL;
+
+	count = ldap_count_values(rparams->passwdservers);
+	if ((st=copy_arrays(rparams->passwdservers, &newpasswdservers, count)) != 0)
+	    goto cleanup;
+
+	/* find the deletions and additions to the server list */
+	if (oldpasswdservers && newpasswdservers)
+	    disjoint_members(oldpasswdservers, newpasswdservers);
+
+	/* delete the krbRealmReferences attribute from the servers that are dis-associated. */
+	if (oldpasswdservers)
+	    for (i=0; oldpasswdservers[i]; ++i)
+		if ((st=deleteAttribute(ld, oldpasswdservers[i], "krbRealmReferences",
+					rparams->realmdn)) != 0) {
+		    sprintf(errbuf, "Error removing 'krbRealmReferences' from "
+			    "%s: ", oldpasswdservers[i]);
+		    prepend_err_str (context, errbuf, st, st);
+		    goto cleanup;
+		}
+
+	/* add the krbRealmReferences attribute from the servers that are associated. */
+	if (newpasswdservers)
+	    for (i=0; newpasswdservers[i]; ++i)
+		if ((st=updateAttribute(ld, newpasswdservers[i], "krbRealmReferences",
+					rparams->realmdn)) != 0) {
+		    sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+			    newpasswdservers[i]);
+		    prepend_err_str (context, errbuf, st, st);
+		    goto cleanup;
+		}
+	if (newpasswdservers)
+	    ldap_value_free(newpasswdservers);
+    }
+#endif
+
+cleanup:
+
+#ifdef HAVE_EDIRECTORY
+    if (oldkdcservers) {
+	for (i=0; oldkdcservers[i]; ++i)
+	    free(oldkdcservers[i]);
+	free(oldkdcservers);
+    }
+
+    if (oldadminservers) {
+	for (i=0; oldadminservers[i]; ++i)
+	    free(oldadminservers[i]);
+	free(oldadminservers);
+    }
+
+    if (oldpasswdservers) {
+	for (i=0; oldpasswdservers[i]; ++i)
+	    free(oldpasswdservers[i]);
+	free(oldpasswdservers);
+    }
+#endif
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+
+/*
+ * Create the Kerberos container in the Directory
+ */
+
+krb5_error_code
+krb5_ldap_create_krbcontainer(context, krbcontparams)
+    krb5_context                          context;
+    const krb5_ldap_krbcontainer_params   *krbcontparams;
+{
+    LDAP                        *ld=NULL;
+    char                        *strval[2]={NULL}, *kerberoscontdn=NULL, **rdns=NULL;
+    int                         pmask=0;
+    LDAPMod                     **mods = NULL;
+    krb5_error_code             st=0;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+#ifdef HAVE_EDIRECTORY
+    int                         crmask=0;
+#endif
+
+    SETUP_CONTEXT ();
+
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    if (krbcontparams != NULL && krbcontparams->DN != NULL) {
+	kerberoscontdn = krbcontparams->DN;
+    } else {
+	/* If the user has not given, use the default cn=Kerberos,cn=Security */
+#ifdef HAVE_EDIRECTORY
+	kerberoscontdn = KERBEROS_CONTAINER;
+#else
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Kerberos Container information is missing");
+	goto cleanup;
+#endif
+    }
+
+    strval[0] = "krbContainer";
+    strval[1] = NULL;
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    rdns = ldap_explode_dn(kerberoscontdn, 1);
+    if (rdns == NULL) {
+	st = EINVAL;
+	krb5_set_error_message(context, st, "Invalid Kerberos container DN");
+	goto cleanup;
+    }
+
+    strval[0] = rdns[0];
+    strval[1] = NULL;
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    /* check if the policy reference value exists and is of krbticketpolicyreference object class */
+    if (krbcontparams && krbcontparams->policyreference) {
+	st = checkattributevalue(ld, krbcontparams->policyreference, "objectclass", policyclass,
+				 &pmask);
+	CHECK_CLASS_VALIDITY(st, pmask, "ticket policy object value: ");
+
+	strval[0] = krbcontparams->policyreference;
+	strval[1] = NULL;
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_ADD,
+					  strval)) != 0)
+	    goto cleanup;
+    }
+
+    /* create the kerberos container */
+    if ((st = ldap_add_ext_s(ld, kerberoscontdn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	int ost = st;
+	st = translate_ldap_error (st, OP_ADD);
+	krb5_set_error_message (context, st, "Kerberos Container create FAILED: %s", ldap_err2string(ost));
+	goto cleanup;
+    }
+
+#ifdef HAVE_EDIRECTORY
+
+    /* free the mods array */
+    ldap_mods_free(mods, 1);
+    mods=NULL;
+
+    /* check whether the security container is bound to krbcontainerrefaux object class */
+    if ((st=checkattributevalue(ld, SECURITY_CONTAINER, "objectClass",
+				krbContainerRefclass, &crmask)) != 0) {
+	prepend_err_str (context, "Security Container read FAILED: ", st, st);
+	/* delete Kerberos Container, status ignored intentionally */
+	ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL);
+	goto cleanup;
+    }
+
+    if (crmask == 0) {
+	/* Security Container is extended with krbcontainerrefaux object class */
+	strval[0] = "krbContainerRefAux";
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+	    goto cleanup;
+    }
+
+    strval[0] = kerberoscontdn;
+    strval[1] = NULL;
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbcontainerreference", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    /* update the security container with krbContainerReference attribute */
+    if ((st=ldap_modify_ext_s(ld, SECURITY_CONTAINER, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	int ost = st;
+	st = translate_ldap_error (st, OP_MOD);
+	krb5_set_error_message (context, st, "Security Container update FAILED: %s", ldap_err2string(ost));
+	/* delete Kerberos Container, status ignored intentionally */
+	ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL);
+	goto cleanup;
+    }
+#endif
+
+cleanup:
+
+    if (rdns)
+	ldap_value_free (rdns);
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return(st);
+}
+
+/*
+ * Delete the Kerberos container in the Directory
+ */
+
+krb5_error_code
+krb5_ldap_delete_krbcontainer(krb5_context context,
+    const krb5_ldap_krbcontainer_params *krbcontparams)
+{
+    LDAP                        *ld=NULL;
+    char                        *kerberoscontdn=NULL;
+    krb5_error_code             st=0;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    SETUP_CONTEXT ();
+
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    if (krbcontparams != NULL && krbcontparams->DN != NULL) {
+	kerberoscontdn = krbcontparams->DN;
+    } else {
+	/* If the user has not given, use the default cn=Kerberos,cn=Security */
+#ifdef HAVE_EDIRECTORY
+	kerberoscontdn = KERBEROS_CONTAINER;
+#else
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Kerberos Container information is missing");
+	goto cleanup;
+#endif
+    }
+
+    /* delete the kerberos container */
+    if ((st = ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL)) != LDAP_SUCCESS) {
+	int ost = st;
+	st = translate_ldap_error (st, OP_ADD);
+	krb5_set_error_message (context, st, "Kerberos Container delete FAILED: %s", ldap_err2string(ost));
+	goto cleanup;
+    }
+
+cleanup:
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return(st);
+}
+
+
+/*
+ * Create Realm in eDirectory. This is used by kdb5_util
+ */
+
+krb5_error_code
+krb5_ldap_create_realm(context, rparams, mask)
+    krb5_context                context;
+    krb5_ldap_realm_params      *rparams;
+    int                         mask;
+{
+    LDAP                        *ld=NULL;
+    krb5_error_code             st=0;
+    char                        *dn=NULL;
+    char                        *strval[4]={NULL};
+    char		        *contref[2]={NULL}; 
+    LDAPMod                     **mods = NULL;
+    int                         i=0, objectmask=0, subtreecount=0; 
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+#ifdef HAVE_EDIRECTORY
+    char errbuf[1024];
+#endif
+    char                        *realm_name;
+
+    SETUP_CONTEXT ();
+
+    /* Check input validity ... */
+    if (ldap_context->krbcontainer == NULL ||
+	ldap_context->krbcontainer->DN == NULL ||
+	rparams == NULL ||
+	rparams->realm_name == NULL ||
+	((mask & LDAP_REALM_SUBTREE) && rparams->subtree  == NULL) ||
+	((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) || 
+	((mask & LDAP_REALM_POLICYREFERENCE) && rparams->policyreference == NULL) ||
+#ifdef HAVE_EDIRECTORY
+	((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) ||
+	((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) ||
+	((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) ||
+#endif
+	0) {
+	st = EINVAL;
+	return st;
+    }
+
+    if (ldap_context->krbcontainer == NULL) {
+	if ((st = krb5_ldap_read_krbcontainer_params(context,
+						     &(ldap_context->krbcontainer))) != 0)
+	    goto cleanup;
+    }
+
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    realm_name = rparams->realm_name;
+
+    dn = malloc(strlen("cn=") + strlen(realm_name) + strlen(ldap_context->krbcontainer->DN) + 2);
+    CHECK_NULL(dn);
+    sprintf(dn, "cn=%s,%s", realm_name, ldap_context->krbcontainer->DN);
+
+    strval[0] = realm_name;
+    strval[1] = NULL;
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    strval[0] = "top";
+    strval[1] = "krbrealmcontainer";
+    strval[2] = "krbticketpolicyaux"; 
+    strval[3] = NULL;
+
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    /* SUBTREE ATTRIBUTE */
+    if (mask & LDAP_REALM_SUBTREE) {
+        if ( rparams->subtree!=NULL)  {
+              subtreecount = rparams->subtreecount;
+	      for (i=0; rparams->subtree[i]!=NULL && i<subtreecount; i++) {
+	          if (strlen(rparams->subtree[i]) != 0) {
+                      st = checkattributevalue(ld, rparams->subtree[i], "Objectclass", subtreeclass,
+                             &objectmask);
+                      CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: ");
+		  }
+	      }
+	      if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_ADD,
+                              rparams->subtree)) != 0) {
+	         goto cleanup;
+	      }
+	}
+    }
+
+    /* CONTAINER REFERENCE ATTRIBUTE */
+    if (mask & LDAP_REALM_CONTREF) {
+        if (strlen(rparams->containerref) != 0 ) {
+            st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
+                             &objectmask);
+            CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: ");
+            contref[0] = rparams->containerref;
+            contref[1] = NULL;
+            if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_ADD,
+                                              contref)) != 0)
+                goto cleanup;
+        }
+    }
+
+    /* SEARCHSCOPE ATTRIBUTE */
+    if (mask & LDAP_REALM_SEARCHSCOPE) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD,
+					  (rparams->search_scope == LDAP_SCOPE_ONELEVEL
+					   || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
+					  rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
+	    goto cleanup;
+    }
+    if (mask & LDAP_REALM_MAXRENEWLIFE) {
+
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD,
+					  rparams->max_renewable_life)) != 0)
+	    goto cleanup;
+    }
+
+    /* krbMaxTicketLife ATTRIBUTE */
+
+    if (mask & LDAP_REALM_MAXTICKETLIFE) {
+
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD,
+					  rparams->max_life)) != 0)
+	    goto cleanup;
+    }
+
+    /* krbTicketFlags ATTRIBUTE */
+
+    if (mask & LDAP_REALM_KRBTICKETFLAGS) {
+
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD,
+					  rparams->tktflags)) != 0)
+	    goto cleanup;
+    }
+
+
+#ifdef HAVE_EDIRECTORY
+
+    /* KDCSERVERS ATTRIBUTE */
+    if (mask & LDAP_REALM_KDCSERVERS) {
+	/* validate the server list */
+	for (i=0; rparams->kdcservers[i] != NULL; ++i) {
+	    st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass,
+				     &objectmask);
+	    CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: ");
+
+	}
+
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_ADD,
+					  rparams->kdcservers)) != 0)
+	    goto cleanup;
+    }
+
+    /* ADMINSERVERS ATTRIBUTE */
+    if (mask & LDAP_REALM_ADMINSERVERS) {
+	/* validate the server list */
+	for (i=0; rparams->adminservers[i] != NULL; ++i) {
+	    st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass,
+				     &objectmask);
+	    CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: ");
+
+	}
+
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_ADD,
+					  rparams->adminservers)) != 0)
+	    goto cleanup;
+    }
+
+    /* PASSWDSERVERS ATTRIBUTE */
+    if (mask & LDAP_REALM_PASSWDSERVERS) {
+	/* validate the server list */
+	for (i=0; rparams->passwdservers[i] != NULL; ++i) {
+	    st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass,
+				     &objectmask);
+	    CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: ");
+
+	}
+
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_ADD,
+					  rparams->passwdservers)) != 0)
+	    goto cleanup;
+    }
+#endif
+
+    /* realm creation operation */
+    if ((st=ldap_add_ext_s(ld, dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_ADD);
+	goto cleanup;
+    }
+
+#ifdef HAVE_EDIRECTORY
+    if (mask & LDAP_REALM_KDCSERVERS)
+	for (i=0; rparams->kdcservers[i]; ++i)
+	    if ((st=updateAttribute(ld, rparams->kdcservers[i], "krbRealmReferences", dn)) != 0) {
+		sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+			rparams->kdcservers[i]);
+		prepend_err_str (context, errbuf, st, st);
+		/* delete Realm, status ignored intentionally */
+		ldap_delete_ext_s(ld, dn, NULL, NULL);
+		goto cleanup;
+	    }
+
+    if (mask & LDAP_REALM_ADMINSERVERS)
+	for (i=0; rparams->adminservers[i]; ++i)
+	    if ((st=updateAttribute(ld, rparams->adminservers[i], "krbRealmReferences", dn)) != 0) {
+		sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+			rparams->adminservers[i]);
+		prepend_err_str (context, errbuf, st, st);
+		/* delete Realm, status ignored intentionally */
+		ldap_delete_ext_s(ld, dn, NULL, NULL);
+		goto cleanup;
+	    }
+
+    if (mask & LDAP_REALM_PASSWDSERVERS)
+	for (i=0; rparams->passwdservers[i]; ++i)
+	    if ((st=updateAttribute(ld, rparams->passwdservers[i], "krbRealmReferences", dn)) != 0) {
+		sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+			rparams->passwdservers[i]);
+		prepend_err_str (context, errbuf, st, st);
+		/* delete Realm, status ignored intentionally */
+		ldap_delete_ext_s(ld, dn, NULL, NULL);
+		goto cleanup;
+	    }
+#endif
+
+cleanup:
+
+    if (dn)
+	free(dn);
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+/*
+ * Read the realm container configuration from eDirectory for the specified realm.
+ */
+
+krb5_error_code
+krb5_ldap_read_realm_params(context, lrealm, rlparamp, mask)
+    krb5_context	context;
+    char            *lrealm;
+    krb5_ldap_realm_params **rlparamp;
+    int             *mask;
+{
+    char                   **values=NULL, *krbcontDN=NULL /*, *curr=NULL */;
+#ifdef HAVE_EDIRECTORY
+    unsigned int           count=0;
+#endif
+    krb5_error_code        st=0, tempst=0;
+    LDAP                   *ld=NULL;
+    LDAPMessage            *result=NULL,*ent=NULL;
+    krb5_ldap_realm_params *rlparams=NULL;
+    kdb5_dal_handle        *dal_handle=NULL;
+    krb5_ldap_context      *ldap_context=NULL;
+    krb5_ldap_server_handle *ldap_server_handle=NULL;
+    int x=0;
+
+    SETUP_CONTEXT ();
+
+    /* validate the input parameter */
+    if (lrealm == NULL ||
+	ldap_context->krbcontainer == NULL ||
+	ldap_context->krbcontainer->DN == NULL) {
+	st = EINVAL;
+	goto cleanup;
+    }
+
+    /* read kerberos container, if not read already */
+    if (ldap_context->krbcontainer == NULL) {
+	if ((st = krb5_ldap_read_krbcontainer_params(context,
+						     &(ldap_context->krbcontainer))) != 0)
+	    goto cleanup;
+    }
+    /* get ldap handle */
+    GET_HANDLE ();
+
+    /* Initialize realm container structure */
+    rlparams =(krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
+    CHECK_NULL(rlparams);
+    memset((char *) rlparams, 0, sizeof(krb5_ldap_realm_params));
+
+    /* allocate tl_data structure to store MASK information */
+    rlparams->tl_data = malloc (sizeof(krb5_tl_data));
+    if (rlparams->tl_data == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    memset((char *) rlparams->tl_data, 0, sizeof(krb5_tl_data));
+    rlparams->tl_data->tl_data_type = KDB_TL_USER_INFO;
+
+    /* set the mask parameter to 0 */
+    *mask = 0;
+
+    /* set default values */
+    rlparams->search_scope = LDAP_SCOPE_SUBTREE;
+
+    krbcontDN = ldap_context->krbcontainer->DN;
+
+    rlparams->realmdn = (char *) malloc(strlen("cn=") + strlen(lrealm) + strlen(krbcontDN) + 2);
+    if (rlparams->realmdn == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    sprintf(rlparams->realmdn, "cn=%s,%s", lrealm, krbcontDN);
+
+    /* populate the realm name in the structure */
+    rlparams->realm_name = strdup(lrealm);
+    CHECK_NULL(rlparams->realm_name);
+
+    LDAP_SEARCH(rlparams->realmdn, LDAP_SCOPE_BASE, "(objectclass=krbRealmContainer)", realm_attributes);
+
+    if ((st = ldap_count_entries(ld, result)) <= 0) {
+        /* This could happen when the DN used to bind and read the realm object
+         * does not have sufficient rights to read its attributes
+         */
+        st = KRB5_KDB_ACCESS_ERROR; /* return some other error ? */
+        goto cleanup;
+    }
+
+    ent = ldap_first_entry (ld, result);
+    if (ent == NULL) {
+	ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st);
+#if 0
+	st = translate_ldap_error(st, OP_SEARCH);
+#endif
+	goto cleanup;
+    }
+
+    /* Read the attributes */
+    {
+	if ((values=ldap_get_values(ld, ent, "krbSubTrees")) != NULL) {
+            rlparams->subtreecount = ldap_count_values(values);
+            rlparams->subtree = (char **) malloc(sizeof(char *) * (rlparams->subtreecount + 1));
+	    if (rlparams->subtree == NULL) {
+		st = ENOMEM;
+		goto cleanup;
+	    }
+            for (x=0; x<rlparams->subtreecount; x++) {
+                rlparams->subtree[x] = strdup(values[x]);
+	        if (rlparams->subtree[x] == NULL) {
+		    st = ENOMEM;
+		    goto cleanup;
+	        }
+            }
+            rlparams->subtree[rlparams->subtreecount] = NULL;
+	    *mask |= LDAP_REALM_SUBTREE;
+	    ldap_value_free(values);
+	}
+
+        if((values=ldap_get_values(ld, ent, "krbPrincContainerRef")) != NULL) {
+            rlparams->containerref = strdup(values[0]);
+            if(rlparams->containerref == NULL) {
+                st = ENOMEM;
+                goto cleanup;
+            }
+            *mask |= LDAP_REALM_CONTREF;
+            ldap_value_free(values);
+        }
+
+	if ((values=ldap_get_values(ld, ent, "krbSearchScope")) != NULL) {
+	    rlparams->search_scope=atoi(values[0]);
+	    /* searchscope can be ONE-LEVEL or SUBTREE, else default to SUBTREE */
+	    if (!(rlparams->search_scope==1 || rlparams->search_scope==2))
+		rlparams->search_scope = LDAP_SCOPE_SUBTREE;
+	    *mask |= LDAP_REALM_SEARCHSCOPE;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "krbMaxTicketLife")) != NULL) {
+	    rlparams->max_life = atoi(values[0]);
+	    *mask |= LDAP_REALM_MAXTICKETLIFE;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "krbMaxRenewableAge")) != NULL) {
+	    rlparams->max_renewable_life = atoi(values[0]);
+	    *mask |= LDAP_REALM_MAXRENEWLIFE;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "krbTicketFlags")) != NULL) {
+	    rlparams->tktflags = atoi(values[0]);
+	    *mask |= LDAP_REALM_KRBTICKETFLAGS;
+	    ldap_value_free(values);
+	}
+
+#ifdef HAVE_EDIRECTORY
+
+	if ((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) {
+	    count = ldap_count_values(values);
+	    if ((st=copy_arrays(values, &(rlparams->kdcservers), (int) count)) != 0)
+		goto cleanup;
+	    *mask |= LDAP_REALM_KDCSERVERS;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) {
+	    count = ldap_count_values(values);
+	    if ((st=copy_arrays(values, &(rlparams->adminservers), (int) count)) != 0)
+		goto cleanup;
+	    *mask |= LDAP_REALM_ADMINSERVERS;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) {
+	    count = ldap_count_values(values);
+	    if ((st=copy_arrays(values, &(rlparams->passwdservers), (int) count)) != 0)
+		goto cleanup;
+	    *mask |= LDAP_REALM_PASSWDSERVERS;
+	    ldap_value_free(values);
+	}
+#endif
+    }
+    ldap_msgfree(result);
+
+    /*
+     * If all of maxtktlife, maxrenewlife and ticketflags are not directly
+     * available, use the policy dn from the policy reference attribute, if
+     * available, to fetch the missing.
+     */
+
+    if ((!(*mask & LDAP_REALM_MAXTICKETLIFE && *mask & LDAP_REALM_MAXRENEWLIFE &&
+	   *mask & LDAP_REALM_KRBTICKETFLAGS)) && rlparams->policyreference) {
+
+	LDAP_SEARCH_1(rlparams->policyreference, LDAP_SCOPE_BASE, NULL, policy_attributes, IGNORE_STATUS);
+	if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_OBJECT) {
+	    int ost = st;
+	    st = translate_ldap_error (st, OP_SEARCH);
+	    krb5_set_error_message (context, st, "Policy object read failed: %s", ldap_err2string(ost));
+	    goto cleanup;
+	}
+	ent = ldap_first_entry (ld, result);
+	if (ent != NULL) {
+	    if ((*mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
+		if ((values=ldap_get_values(ld, ent, "krbmaxticketlife")) != NULL) {
+		    rlparams->max_life = atoi(values[0]);
+		    *mask |= LDAP_REALM_MAXTICKETLIFE;
+		    ldap_value_free(values);
+		}
+	    }
+
+	    if ((*mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
+		if ((values=ldap_get_values(ld, ent, "krbmaxrenewableage")) != NULL) {
+		    rlparams->max_renewable_life = atoi(values[0]);
+		    *mask |= LDAP_REALM_MAXRENEWLIFE;
+		    ldap_value_free(values);
+		}
+	    }
+
+	    if ((*mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
+		if ((values=ldap_get_values(ld, ent, "krbticketflags")) != NULL) {
+		    rlparams->tktflags = atoi(values[0]);
+		    *mask |= LDAP_REALM_KRBTICKETFLAGS;
+		    ldap_value_free(values);
+		}
+	    }
+	}
+	ldap_msgfree(result);
+    }
+
+    rlparams->mask = *mask;
+    *rlparamp = rlparams;
+    st = store_tl_data(rlparams->tl_data, KDB_TL_MASK, mask);
+
+cleanup:
+
+    /* if there is an error, free allocated structures */
+    if (st != 0) {
+	krb5_ldap_free_realm_params(rlparams);
+	*rlparamp=NULL;
+    }
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+  Free the krb5_ldap_realm_params.
+*/
+void
+krb5_ldap_free_realm_params(rparams)
+    krb5_ldap_realm_params *rparams;
+{
+    int i=0;
+
+    if (rparams) {
+	if (rparams->realmdn)
+	    free(rparams->realmdn);
+
+	if (rparams->realm_name)
+	    krb5_xfree(rparams->realm_name);
+
+	if (rparams->subtree) {
+	    for (i=0; i<rparams->subtreecount && rparams->subtree[i] ; i++)
+	        krb5_xfree(rparams->subtree[i]);
+	    krb5_xfree(rparams->subtree);
+        }
+
+	if (rparams->kdcservers) {
+	    for (i=0; rparams->kdcservers[i]; ++i)
+		krb5_xfree(rparams->kdcservers[i]);
+	    krb5_xfree(rparams->kdcservers);
+	}
+
+	if (rparams->adminservers) {
+	    for (i=0; rparams->adminservers[i]; ++i)
+		krb5_xfree(rparams->adminservers[i]);
+	    krb5_xfree(rparams->adminservers);
+	}
+
+	if (rparams->passwdservers) {
+	    for (i=0; rparams->passwdservers[i]; ++i)
+		krb5_xfree(rparams->passwdservers[i]);
+	    krb5_xfree(rparams->passwdservers);
+	}
+
+	if (rparams->tl_data) {
+	    if (rparams->tl_data->tl_data_contents)
+		krb5_xfree(rparams->tl_data->tl_data_contents);
+	    krb5_xfree(rparams->tl_data);
+	}
+
+	if (rparams->mkey.contents) {
+	    memset(rparams->mkey.contents, 0, rparams->mkey.length);
+	    krb5_xfree(rparams->mkey.contents);
+	}
+
+	krb5_xfree(rparams);
+    }
+    return;
+}
+
+/* 
+ * ******************************************************************************
+ * DAL functions
+ * ******************************************************************************
+ */
+
+krb5_error_code
+krb5_ldap_delete_realm_1(krb5_context kcontext, char *conf_section, char **db_args)
+{
+    krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
+    krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status));
+    return status;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
new file mode 100644
index 000000000..ffe6c3665
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
@@ -0,0 +1,99 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_realm.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_REALM_H
+#define _LDAP_REALM_H 1
+
+/* realm specific mask */
+#define LDAP_REALM_SUBTREE            0x0001
+#define LDAP_REALM_SEARCHSCOPE        0x0002
+#define LDAP_REALM_POLICYREFERENCE    0x0004
+#define LDAP_REALM_UPENABLED          0x0008
+#define LDAP_REALM_LDAPSERVERS        0x0010
+#define LDAP_REALM_KDCSERVERS         0x0020
+#define LDAP_REALM_ADMINSERVERS       0x0040
+#define LDAP_REALM_PASSWDSERVERS      0x0080
+#define LDAP_REALM_MAXTICKETLIFE      0x0100
+#define LDAP_REALM_MAXRENEWLIFE       0x0200
+#define LDAP_REALM_KRBTICKETFLAGS     0x0400
+#define LDAP_REALM_CONTREF  	      0x0800 
+
+extern char *policy_attributes[];
+
+extern char *realm_attributes[];
+
+/* realm container structure */
+
+typedef struct _krb5_ldap_realm_params {
+  char          *realmdn;
+  char          *realm_name;
+  char          **subtree; 
+  char		*containerref;  
+  char          *policyreference;
+  int           search_scope;
+  int           upenabled;
+  int 		subtreecount;
+  krb5_int32    max_life;
+  krb5_int32    max_renewable_life;
+  krb5_int32    tktflags;
+  char          **kdcservers;
+  char          **adminservers;
+  char          **passwdservers;
+  krb5_tl_data  *tl_data;
+  krb5_keyblock mkey;
+  long          mask;
+} krb5_ldap_realm_params;
+
+
+krb5_error_code
+krb5_ldap_list_realm(krb5_context , char ***);
+
+krb5_error_code
+krb5_ldap_delete_realm(krb5_context, char *);
+
+krb5_error_code
+krb5_ldap_modify_realm(krb5_context, krb5_ldap_realm_params *, int);
+
+krb5_error_code
+krb5_ldap_create_realm(krb5_context, krb5_ldap_realm_params *, int);
+
+krb5_error_code
+krb5_ldap_read_realm_params(krb5_context , char *, krb5_ldap_realm_params **, int *);
+
+void
+krb5_ldap_free_realm_params(krb5_ldap_realm_params *);
+
+krb5_error_code
+krb5_ldap_delete_realm_1(krb5_context, char *, char **);
+
+char *
+ldap_filter_correct(char *);
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c
new file mode 100644
index 000000000..b32ba9186
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c
@@ -0,0 +1,839 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_service_rights.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "ldap_services.h"
+#include "ldap_err.h"
+
+/* NOTE: add appropriate rights for krbpasswordexpiration attribute */
+
+#ifdef HAVE_EDIRECTORY
+
+static char *kdcrights_subtree[][2] = {
+    {"1#subtree#","#[Entry Rights]"},
+    {"2#subtree#","#CN"},
+    {"6#subtree#","#ObjectClass"},
+    {"2#subtree#","#krbTicketPolicyReference"},
+    {"2#subtree#","#krbUPEnabled"},
+    {"2#subtree#","#krbHostServer"},
+    {"2#subtree#","#krbServiceFlags"},
+    {"2#subtree#","#krbRealmReferences"},
+    {"2#subtree#","#krbTicketFlags"},
+    {"2#subtree#","#krbMaxTicketLife"},
+    {"2#subtree#","#krbMaxRenewableAge"},
+    {"2#subtree#","#krbPrincipalName"},
+    {"6#subtree#","#krbPrincipalKey"},
+    {"2#subtree#","#krbPrincipalExpiration"},
+    {"2#subtree#","#krbPwdPolicyReference"},
+    {"2#subtree#","#krbMaxPwdLife"},
+    {"6#subtree#","#ModifiersName"},
+    {"2#subtree#","#PasswordExpirationTime"},
+    {"2#subtree#","#PasswordExpirationInterval"},
+    {"2#subtree#","#PasswordMinimumLength"},
+    {"2#subtree#","#PasswordAllowChange"},
+    {"2#subtree#","#LoginDisabled"},
+    {"6#subtree#","#LastLoginTime"},
+    {"2#subtree#","#LoginExpirationTime"},
+    {"6#subtree#","#LoginIntruderAttempts"},
+    {"2#subtree#","#IntruderAttemptResetInterval"},
+    {"2#subtree#","#LoginIntruderLimit"},
+    {"6#subtree#","#LoginIntruderResetTime"},
+    {"2#subtree#","#DetectIntruder"},
+    {"2#subtree#","#LockoutAfterDetection"},
+    {"6#subtree#","#LockedByIntruder"},
+    {"2#subtree#","#krbPrincipalReferences"},
+    { "", "" }
+};
+
+static char *adminrights_subtree[][2]={
+    {"15#subtree#","#[Entry Rights]"},
+    {"6#subtree#","#CN"},
+    {"6#subtree#","#ObjectClass"},
+    {"6#subtree#","#krbTicketPolicyReference"},
+    {"6#subtree#","#krbUPEnabled"},
+    {"2#subtree#","#krbHostServer"},
+    {"2#subtree#","#krbServiceFlags"},
+    {"2#subtree#","#krbRealmReferences"},
+    {"6#subtree#","#krbTicketFlags"},
+    {"6#subtree#","#krbMaxTicketLife"},
+    {"6#subtree#","#krbMaxRenewableAge"},
+    {"6#subtree#","#krbPrincipalName"},
+    {"6#subtree#","#krbPrincipalKey"},
+    {"6#subtree#","#krbPrincipalExpiration"},
+    {"6#subtree#","#ModifiersName"},
+    {"6#subtree#","#PasswordExpirationTime"},
+    {"2#subtree#","#PasswordExpirationInterval"},
+    {"6#subtree#","#PasswordMinimumLength"},
+    {"6#subtree#","#PasswordAllowChange"},
+    {"6#subtree#","#LoginDisabled"},
+    {"2#subtree#","#LastLoginTime"},
+    {"2#subtree#","#LoginExpirationTime"},
+    {"2#subtree#","#LoginIntruderAttempts"},
+    {"6#subtree#","#IntruderAttemptResetInterval"},
+    {"6#subtree#","#LoginIntruderLimit"},
+    {"6#subtree#","#LoginIntruderResetTime"},
+    {"6#subtree#","#DetectIntruder"},
+    {"6#subtree#","#LockoutAfterDetection"},
+    {"2#subtree#","#LockedByIntruder"},
+    {"2#subtree#","#krbPrincipalReferences"},
+    {"6#subtree#","#Surname"},
+    {"4#subtree#","#passwordManagement"},
+    {"6#subtree#","#krbPwdHistoryLength"},
+    {"6#subtree#","#krbMinPwdLife"},
+    {"6#subtree#","#krbMaxPwdLife"},
+    {"6#subtree#","#krbPwdMinDiffChars"},
+    {"6#subtree#","#krbPwdMinLength"},
+    {"6#subtree#","#krbPwdPolicyReference"},
+    { "","" }
+};
+
+static char *pwdrights_subtree[][2] = {
+    {"1#subtree#","#[Entry Rights]"},
+    {"2#subtree#","#CN"},
+    {"2#subtree#","#ObjectClass"},
+    {"2#subtree#","#krbTicketPolicyReference"},
+    {"2#subtree#","#krbUPEnabled"},
+    {"2#subtree#","#krbHostServer"},
+    {"2#subtree#","#krbServiceFlags"},
+    {"2#subtree#","#krbRealmReferences"},
+    {"6#subtree#","#krbTicketFlags"},
+    {"2#subtree#","#krbMaxTicketLife"},
+    {"2#subtree#","#krbMaxRenewableAge"},
+    {"2#subtree#","#krbPrincipalName"},
+    {"6#subtree#","#krbPrincipalKey"},
+    {"2#subtree#","#krbPrincipalExpiration"},
+    {"4#subtree#","#passwordManagement"},
+    {"6#subtree#","#ModifiersName"},
+    {"2#subtree#","#krbPwdHistoryLength"},
+    {"2#subtree#","#krbMinPwdLife"},
+    {"2#subtree#","#krbMaxPwdLife"},
+    {"2#subtree#","#krbPwdMinDiffChars"},
+    {"2#subtree#","#krbPwdMinLength"},
+    {"2#subtree#","#krbPwdPolicyReference"},
+    { "", "" }
+};
+
+static char *kdcrights_realmcontainer[][2]={
+    {"1#subtree#","#[Entry Rights]"},
+    {"2#subtree#","#CN"},
+    {"6#subtree#","#ObjectClass"},
+    {"2#subtree#","#krbTicketPolicyReference"},
+    {"2#subtree#","#krbMKey"},
+    {"2#subtree#","#krbUPEnabled"},
+    {"2#subtree#","#krbSubTrees"},
+    {"2#subtree#","#krbPrincContainerRef"}, 
+    {"2#subtree#","#krbSearchScope"},
+    {"2#subtree#","#krbLdapServers"},
+    {"2#subtree#","#krbSupportedEncSaltTypes"},
+    {"2#subtree#","#krbDefaultEncSaltTypes"},
+    {"2#subtree#","#krbKdcServers"},
+    {"2#subtree#","#krbPwdServers"},
+    {"2#subtree#","#krbTicketFlags"},
+    {"2#subtree#","#krbMaxTicketLife"},
+    {"2#subtree#","#krbMaxRenewableAge"},
+    {"2#subtree#","#krbPrincipalName"},
+    {"6#subtree#","#krbPrincipalKey"},
+    {"2#subtree#","#krbPrincipalExpiration"},
+    {"2#subtree#","#krbPwdPolicyReference"},
+    {"2#subtree#","#krbMaxPwdLife"},
+    {"6#subtree#","#ModifiersName"},
+    {"2#subtree#","#PasswordExpirationTime"},
+    {"2#subtree#","#PasswordExpirationInterval"},
+    {"2#subtree#","#PasswordMinimumLength"},
+    {"2#subtree#","#PasswordAllowChange"},
+    {"2#subtree#","#LoginDisabled"},
+    {"6#subtree#","#LastLoginTime"},
+    {"2#subtree#","#LoginExpirationTime"},
+    {"6#subtree#","#LoginIntruderAttempts"},
+    {"2#subtree#","#IntruderAttemptResetInterval"},
+    {"2#subtree#","#LoginIntruderLimit"},
+    {"6#subtree#","#LoginIntruderResetTime"},
+    {"2#subtree#","#DetectIntruder"},
+    {"2#subtree#","#LockoutAfterDetection"},
+    {"6#subtree#","#LockedByIntruder"},
+    { "", "" }
+};
+
+
+static char *adminrights_realmcontainer[][2]={
+    {"15#subtree#","#[Entry Rights]"},
+    {"6#subtree#","#CN"},
+    {"6#subtree#","#ObjectClass"},
+    {"6#subtree#","#krbTicketPolicyReference"},
+    {"2#subtree#","#krbMKey"},
+    {"6#subtree#","#krbUPEnabled"},
+    {"2#subtree#","#krbSubTrees"},
+    {"2#subtree#","#krbPrincContainerRef"}, 
+    {"2#subtree#","#krbSearchScope"},
+    {"2#subtree#","#krbLdapServers"},
+    {"2#subtree#","#krbSupportedEncSaltTypes"},
+    {"2#subtree#","#krbDefaultEncSaltTypes"},
+    {"2#subtree#","#krbKdcServers"},
+    {"2#subtree#","#krbPwdServers"},
+    {"6#subtree#","#krbTicketFlags"},
+    {"6#subtree#","#krbMaxTicketLife"},
+    {"6#subtree#","#krbMaxRenewableAge"},
+    {"6#subtree#","#krbPrincipalName"},
+    {"6#subtree#","#krbPrincipalKey"},
+    {"6#subtree#","#krbPrincipalExpiration"},
+    {"6#subtree#","#ModifiersName"},
+    {"6#subtree#","#PasswordExpirationTime"},
+    {"2#subtree#","#PasswordExpirationInterval"},
+    {"6#subtree#","#PasswordMinimumLength"},
+    {"6#subtree#","#PasswordAllowChange"},
+    {"6#subtree#","#LoginDisabled"},
+    {"2#subtree#","#LastLoginTime"},
+    {"2#subtree#","#LoginExpirationTime"},
+    {"2#subtree#","#LoginIntruderAttempts"},
+    {"6#subtree#","#IntruderAttemptResetInterval"},
+    {"6#subtree#","#LoginIntruderLimit"},
+    {"6#subtree#","#LoginIntruderResetTime"},
+    {"6#subtree#","#DetectIntruder"},
+    {"6#subtree#","#LockoutAfterDetection"},
+    {"2#subtree#","#LockedByIntruder"},
+    {"6#subtree#","#Surname"},
+    {"6#subtree#","#krbPwdHistoryLength"},
+    {"6#subtree#","#krbMinPwdLife"},
+    {"6#subtree#","#krbMaxPwdLife"},
+    {"6#subtree#","#krbPwdMinDiffChars"},
+    {"6#subtree#","#krbPwdMinLength"},
+    {"6#subtree#","#krbPwdPolicyReference"},
+    { "","" }
+};
+
+
+static char *pwdrights_realmcontainer[][2]={
+    {"1#subtree#","#[Entry Rights]"},
+    {"2#subtree#","#CN"},
+    {"2#subtree#","#ObjectClass"},
+    {"2#subtree#","#krbTicketPolicyReference"},
+    {"2#subtree#","#krbMKey"},
+    {"2#subtree#","#krbUPEnabled"},
+    {"2#subtree#","#krbSubTrees"},
+    {"2#subtree#","#krbPrincContainerRef"}, 
+    {"2#subtree#","#krbSearchScope"},
+    {"2#subtree#","#krbLdapServers"},
+    {"2#subtree#","#krbSupportedEncSaltTypes"},
+    {"2#subtree#","#krbDefaultEncSaltTypes"},
+    {"2#subtree#","#krbKdcServers"},
+    {"2#subtree#","#krbPwdServers"},
+    {"6#subtree#","#krbTicketFlags"},
+    {"2#subtree#","#krbMaxTicketLife"},
+    {"2#subtree#","#krbMaxRenewableAge"},
+    {"2#subtree#","#krbPrincipalName"},
+    {"6#subtree#","#krbPrincipalKey"},
+    {"2#subtree#","#krbPrincipalExpiration"},
+    {"6#subtree#","#ModifiersName"},
+    {"2#subtree#","#krbPwdHistoryLength"},
+    {"2#subtree#","#krbMinPwdLife"},
+    {"2#subtree#","#krbMaxPwdLife"},
+    {"2#subtree#","#krbPwdMinDiffChars"},
+    {"2#subtree#","#krbPwdMinLength"},
+    {"2#subtree#","#krbPwdPolicyReference"},
+    { "", "" }
+};
+
+static char *security_container[][2] = {
+    {"1#subtree#","#[Entry Rights]"},
+    {"2#subtree#","#krbContainerReference"},
+    { "", "" }
+};
+
+static char *kerberos_container[][2] = {
+    {"1#subtree#","#[Entry Rights]"},
+    {"2#subtree#","#krbTicketPolicyReference"},
+    { "", "" }
+};
+
+
+/*
+ * This will set the rights for the Kerberos service objects.
+ * The function will read the subtree attribute from the specified
+ * realm name and will the appropriate rights on both the realm
+ * container and the subtree. The kerberos context passed should
+ * have a valid ldap handle, with appropriate rights to write acl
+ * attributes.
+ *
+ * krb5_context - IN The Kerberos context with valid ldap handle
+ *
+ */
+
+krb5_error_code
+krb5_ldap_add_service_rights(context, servicetype, serviceobjdn, realmname, subtreeparam, mask)
+    krb5_context	context;
+    int                 servicetype;
+    char                *serviceobjdn;
+    char                *realmname;
+    char                **subtreeparam;                         
+    int                 mask;
+{
+
+    int                    st=0,i=0;
+    char                   *realmacls[2]={NULL}, *subtreeacls[2]={NULL}, *seccontacls[2]={NULL}, *krbcontacls[2]={NULL};
+    LDAP                   *ld;
+    LDAPMod                realmclass, subtreeclass, seccontclass, krbcontclass;
+    LDAPMod                *realmarr[3]={NULL}, *subtreearr[3]={NULL}, *seccontarr[3]={NULL}, *krbcontarr[3]={NULL};
+    char                   *realmdn=NULL, **subtree=NULL;
+    kdb5_dal_handle        *dal_handle=NULL;
+    krb5_ldap_context      *ldap_context=NULL;
+    krb5_ldap_server_handle *ldap_server_handle=NULL;
+    int                     subtreecount=0;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if ((serviceobjdn == NULL) || (realmname == NULL) || (servicetype < 0) || (servicetype > 4)
+	|| (ldap_context->krbcontainer->DN == NULL)) {
+	st=-1;
+	goto cleanup;
+    }
+
+    subtreecount=ldap_context->lrparams->subtreecount;
+    subtree = (char **) malloc(sizeof(char *) * (subtreecount + 1));
+    if(subtree == NULL) {
+        st = ENOMEM;
+        goto cleanup;
+    }
+
+    /* If the subtree is null, set the value to root */
+    if(subtreeparam == NULL) {
+        subtree[0] = strdup("");
+        if(subtree[0] == NULL) {
+            st = ENOMEM;
+            goto cleanup;
+        }
+    }
+    else {
+        for (i=0; subtree[i] != NULL && i<subtreecount; i++) {
+            subtree[i] = strdup(subtreeparam[i]);
+            if(subtree[i] == NULL) {
+                st = ENOMEM;
+                goto cleanup;
+            }
+        }
+    }
+
+    /* Set the rights for the service object on the security container */
+    seccontclass.mod_op = LDAP_MOD_ADD;
+    seccontclass.mod_type = "ACL";
+
+    for (i=0; strcmp(security_container[i][0], "") != 0; i++) {
+
+	seccontacls[0] = (char *)malloc(strlen(security_container[i][0]) +
+					strlen(serviceobjdn) +
+					strlen(security_container[i][1]) + 1);
+
+	sprintf(seccontacls[0], "%s%s%s", security_container[i][0], serviceobjdn,
+		security_container[i][1]);
+	seccontclass.mod_values = seccontacls;
+
+	seccontarr[0] = &seccontclass;
+
+	st = ldap_modify_ext_s(ld,
+			       SECURITY_CONTAINER,
+			       seccontarr,
+			       NULL,
+			       NULL);
+	if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+	    free(seccontacls[0]);
+	    st = set_ldap_error (context, st, OP_MOD);
+	    goto cleanup;
+	}
+	free(seccontacls[0]);
+    }
+
+
+    /* Set the rights for the service object on the kerberos container */
+    krbcontclass.mod_op = LDAP_MOD_ADD;
+    krbcontclass.mod_type = "ACL";
+
+    for (i=0; strcmp(kerberos_container[i][0], "") != 0; i++) {
+	krbcontacls[0] = (char *)malloc(strlen(kerberos_container[i][0]) + strlen(serviceobjdn)
+					+ strlen(kerberos_container[i][1]) + 1);
+	sprintf(krbcontacls[0], "%s%s%s", kerberos_container[i][0], serviceobjdn,
+		kerberos_container[i][1]);
+	krbcontclass.mod_values = krbcontacls;
+
+	krbcontarr[0] = &krbcontclass;
+
+	st = ldap_modify_ext_s(ld,
+			       ldap_context->krbcontainer->DN,
+			       krbcontarr,
+			       NULL,
+			       NULL);
+	if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+	    free(krbcontacls[0]);
+	    st = set_ldap_error (context, st, OP_MOD);
+	    goto cleanup;
+	}
+	free(krbcontacls[0]);
+    }
+
+    /* Set the rights for the realm */
+    if (mask & LDAP_REALM_RIGHTS) {
+
+	/* Construct the realm dn from realm name */
+	realmdn = (char *)malloc(strlen("cn=") + strlen(realmname) +
+				 strlen(ldap_context->krbcontainer->DN) + 2);
+	sprintf(realmdn,"cn=%s,%s", realmname, ldap_context->krbcontainer->DN);
+
+	realmclass.mod_op = LDAP_MOD_ADD;
+	realmclass.mod_type = "ACL";
+
+	if (servicetype == LDAP_KDC_SERVICE) {
+	    for (i=0; strcmp(kdcrights_realmcontainer[i][0], "") != 0; i++) {
+		realmacls[0] = (char *)malloc(strlen(kdcrights_realmcontainer[i][0])
+					      + strlen(serviceobjdn) +
+					      strlen(kdcrights_realmcontainer[i][1]) + 1);
+		sprintf(realmacls[0], "%s%s%s", kdcrights_realmcontainer[i][0], serviceobjdn,
+			kdcrights_realmcontainer[i][1]);
+		realmclass.mod_values = realmacls;
+
+		realmarr[0] = &realmclass;
+
+		st = ldap_modify_ext_s(ld,
+				       realmdn,
+				       realmarr,
+				       NULL,
+				       NULL);
+		if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+		    free(realmacls[0]);
+		    st = set_ldap_error (context, st, OP_MOD);
+		    goto cleanup;
+		}
+		free(realmacls[0]);
+	    }
+	} else if (servicetype == LDAP_ADMIN_SERVICE) {
+	    for (i=0; strcmp(adminrights_realmcontainer[i][0], "") != 0; i++) {
+		realmacls[0] = (char *) malloc(strlen(adminrights_realmcontainer[i][0]) +
+					       strlen(serviceobjdn) +
+					       strlen(adminrights_realmcontainer[i][1]) + 1);
+		sprintf(realmacls[0], "%s%s%s", adminrights_realmcontainer[i][0], serviceobjdn,
+			adminrights_realmcontainer[i][1]);
+		realmclass.mod_values = realmacls;
+
+		realmarr[0] = &realmclass;
+
+		st = ldap_modify_ext_s(ld,
+				       realmdn,
+				       realmarr,
+				       NULL,
+				       NULL);
+		if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+		    free(realmacls[0]);
+		    st = set_ldap_error (context, st, OP_MOD);
+		    goto cleanup;
+		}
+		free(realmacls[0]);
+	    }
+	} else if (servicetype == LDAP_PASSWD_SERVICE) {
+	    for (i=0; strcmp(pwdrights_realmcontainer[i][0], "")!=0; i++) {
+		realmacls[0] = (char *) malloc(strlen(pwdrights_realmcontainer[i][0]) +
+					       strlen(serviceobjdn) +
+					       strlen(pwdrights_realmcontainer[i][1]) + 1);
+		sprintf(realmacls[0], "%s%s%s", pwdrights_realmcontainer[i][0], serviceobjdn,
+			pwdrights_realmcontainer[i][1]);
+		realmclass.mod_values = realmacls;
+
+		realmarr[0] = &realmclass;
+
+
+		st = ldap_modify_ext_s(ld,
+				       realmdn,
+				       realmarr,
+				       NULL,
+				       NULL);
+		if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+		    free(realmacls[0]);
+		    st = set_ldap_error (context, st, OP_MOD);
+		    goto cleanup;
+		}
+		free(realmacls[0]);
+	    }
+	}
+    } /* Realm rights settings ends here */
+
+
+    /* Subtree rights to be set */
+    if (mask & LDAP_SUBTREE_RIGHTS) {
+	/* Populate the acl data to be added to the subtree */
+	subtreeclass.mod_op = LDAP_MOD_ADD;
+	subtreeclass.mod_type = "ACL";
+
+	if (servicetype == LDAP_KDC_SERVICE) {
+	    for (i=0; strcmp(kdcrights_subtree[i][0], "")!=0; i++) {
+		subtreeacls[0] = (char *) malloc(strlen(kdcrights_subtree[i][0]) +
+						 strlen(serviceobjdn) +
+						 strlen(kdcrights_subtree[i][1]) + 1);
+		sprintf(subtreeacls[0], "%s%s%s", kdcrights_subtree[i][0], serviceobjdn,
+			kdcrights_subtree[i][1]);
+		subtreeclass.mod_values = subtreeacls;
+
+		subtreearr[0] = &subtreeclass;
+
+                /* set rights to a list of subtrees */
+                for(i=0; subtree[i]!=NULL && i<subtreecount;i++) {
+		    st = ldap_modify_ext_s(ld,
+                                            subtree[i],
+                                            subtreearr,
+                                            NULL,
+                                            NULL);
+		    if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+		        free(subtreeacls[0]);
+		        st = set_ldap_error (context, st, OP_MOD);
+		        goto cleanup;
+		    }
+                }
+		free(subtreeacls[0]);
+	    }
+	} else if (servicetype == LDAP_ADMIN_SERVICE) {
+	    for (i=0; strcmp(adminrights_subtree[i][0], "")!=0; i++) {
+		subtreeacls[0] = (char *) malloc(strlen(adminrights_subtree[i][0])
+						 + strlen(serviceobjdn)
+						 + strlen(adminrights_subtree[i][1]) + 1);
+		sprintf(subtreeacls[0], "%s%s%s", adminrights_subtree[i][0], serviceobjdn,
+			adminrights_subtree[i][1]);
+		subtreeclass.mod_values = subtreeacls;
+
+		subtreearr[0] = &subtreeclass;
+
+                /* set rights to a list of subtrees */
+                for(i=0; subtree[i]!=NULL && i<subtreecount;i++) {
+		    st = ldap_modify_ext_s(ld,
+                                            subtree[i],
+                                            subtreearr,
+                                            NULL,
+                                            NULL);
+		    if (st != LDAP_SUCCESS && st !=LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+		        free(subtreeacls[0]);
+		        st = set_ldap_error (context, st, OP_MOD);
+		        goto cleanup;
+		    }
+                }
+		free(subtreeacls[0]);
+	    }
+	} else if (servicetype == LDAP_PASSWD_SERVICE) {
+	    for (i=0; strcmp(pwdrights_subtree[i][0], "") != 0; i++) {
+		subtreeacls[0] = (char *)malloc(strlen(pwdrights_subtree[i][0])
+						+ strlen(serviceobjdn)
+						+ strlen(pwdrights_subtree[i][1]) + 1);
+		sprintf(subtreeacls[0], "%s%s%s", pwdrights_subtree[i][0], serviceobjdn,
+			pwdrights_subtree[i][1]);
+		subtreeclass.mod_values = subtreeacls;
+
+		subtreearr[0] = &subtreeclass;
+
+                /* set rights to a list of subtrees */
+                for(i=0; subtree[i]!=NULL && i<subtreecount;i++) {
+		    st = ldap_modify_ext_s(ld,
+                                            subtree[i],
+                                            subtreearr,
+                                            NULL,
+                                            NULL);
+		    if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+		        free(subtreeacls[0]);
+		        st = set_ldap_error (context, st, OP_MOD);
+		        goto cleanup;
+		    }
+                }
+		free(subtreeacls[0]);
+	    }
+	}
+    } /* Subtree rights settings ends here */
+    st = 0;
+
+cleanup:
+
+    if (realmdn)
+	free(realmdn);
+
+    if (subtree)
+	free(subtree);
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+  This will set the rights for the Kerberos service objects.
+  The function will read the subtree attribute from the specified
+  realm name and will the appropriate rights on both the realm
+  container and the subtree. The kerberos context passed should
+  have a valid ldap handle, with appropriate rights to write acl
+  attributes.
+
+  krb5_context - IN The Kerberos context with valid ldap handle
+
+*/
+
+krb5_error_code
+krb5_ldap_delete_service_rights(context, servicetype, serviceobjdn, realmname, subtreeparam, mask)
+    krb5_context	context;
+    int             servicetype;
+    char            *serviceobjdn;
+    char            *realmname;
+    char            **subtreeparam; 
+    int             mask;
+{
+
+    int                    st=0,i=0;
+    char                   *realmacls[2] = { NULL }, *subtreeacls[2] = { NULL };
+    LDAP                   *ld;
+    LDAPMod                realmclass, subtreeclass;
+    LDAPMod                *realmarr[3] = { NULL }, *subtreearr[3] = { NULL };
+    char                   *realmdn=NULL;
+    char                   **subtree=NULL;
+    kdb5_dal_handle        *dal_handle=NULL;
+    krb5_ldap_context      *ldap_context=NULL;
+    krb5_ldap_server_handle *ldap_server_handle=NULL;
+    int                     subtreecount = 0;  
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if ((serviceobjdn == NULL) || (realmname == NULL) || (servicetype < 0) || (servicetype > 4)
+	|| (ldap_context->krbcontainer->DN == NULL)) {
+	st = -1;
+	goto cleanup;
+    }
+
+    subtreecount = 1;
+    while(subtreeparam[subtreecount])
+        subtreecount++;
+    subtree = (char **) malloc(sizeof(char *) * subtreecount + 1);
+    if(subtree == NULL) {
+        st = ENOMEM;
+        goto cleanup;
+    }
+
+    /* If the subtree is null, set the value to root */
+    if(subtreeparam == NULL) {
+        subtree[0] = strdup("");
+        if(subtree[0] == NULL) {
+            st = ENOMEM;
+            goto cleanup;
+        }
+    }
+    else {
+        for(i=0; subtreeparam[i]!=NULL && i<subtreecount; i++)
+        subtree[i] = strdup(subtreeparam[i]);
+        if(subtree[i] == NULL) {
+            st = ENOMEM;
+            goto cleanup;
+        }
+    }
+
+
+    /* Set the rights for the realm */
+    if (mask & LDAP_REALM_RIGHTS) {
+
+	/* Construct the realm dn from realm name */
+	realmdn = (char *) malloc(strlen("cn=") + strlen(realmname) +
+				  strlen(ldap_context->krbcontainer->DN) + 2);
+	sprintf(realmdn,"cn=%s,%s", realmname, ldap_context->krbcontainer->DN);
+
+	realmclass.mod_op=LDAP_MOD_DELETE;
+	realmclass.mod_type="ACL";
+
+	if (servicetype == LDAP_KDC_SERVICE) {
+	    for (i=0; strcmp(kdcrights_realmcontainer[i][0], "") != 0; i++) {
+		realmacls[0] = (char *) malloc(strlen(kdcrights_realmcontainer[i][0])
+					       + strlen(serviceobjdn) +
+					       strlen(kdcrights_realmcontainer[i][1]) + 1);
+		sprintf(realmacls[0], "%s%s%s", kdcrights_realmcontainer[i][0], serviceobjdn,
+			kdcrights_realmcontainer[i][1]);
+		realmclass.mod_values= realmacls;
+
+		realmarr[0]=&realmclass;
+
+		st = ldap_modify_ext_s(ld,
+				       realmdn,
+				       realmarr,
+				       NULL,
+				       NULL);
+		if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+		    free(realmacls[0]);
+		    st = set_ldap_error (context, st, OP_MOD);
+		    goto cleanup;
+		}
+		free(realmacls[0]);
+	    }
+	} else if (servicetype == LDAP_ADMIN_SERVICE) {
+	    for (i=0; strcmp(adminrights_realmcontainer[i][0], "") != 0; i++) {
+		realmacls[0] = (char *) malloc(strlen(adminrights_realmcontainer[i][0]) +
+					       strlen(serviceobjdn) +
+					       strlen(adminrights_realmcontainer[i][1]) + 1);
+		sprintf(realmacls[0], "%s%s%s", adminrights_realmcontainer[i][0], serviceobjdn,
+			adminrights_realmcontainer[i][1]);
+		realmclass.mod_values= realmacls;
+
+		realmarr[0]=&realmclass;
+
+		st = ldap_modify_ext_s(ld,
+				       realmdn,
+				       realmarr,
+				       NULL,
+				       NULL);
+		if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+		    free(realmacls[0]);
+		    st = set_ldap_error (context, st, OP_MOD);
+		    goto cleanup;
+		}
+		free(realmacls[0]);
+	    }
+	} else if (servicetype == LDAP_PASSWD_SERVICE) {
+	    for (i=0; strcmp(pwdrights_realmcontainer[i][0], "") != 0; i++) {
+		realmacls[0]=(char *)malloc(strlen(pwdrights_realmcontainer[i][0])
+					    + strlen(serviceobjdn)
+					    + strlen(pwdrights_realmcontainer[i][1]) + 1);
+		sprintf(realmacls[0], "%s%s%s", pwdrights_realmcontainer[i][0], serviceobjdn,
+			pwdrights_realmcontainer[i][1]);
+		realmclass.mod_values= realmacls;
+
+		realmarr[0]=&realmclass;
+
+		st = ldap_modify_ext_s(ld,
+				       realmdn,
+				       realmarr,
+				       NULL,
+				       NULL);
+		if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+		    free(realmacls[0]);
+		    st = set_ldap_error (context, st, OP_MOD);
+		    goto cleanup;
+		}
+		free(realmacls[0]);
+	    }
+	}
+
+    } /* Realm rights setting ends here */
+
+
+    /* Set the rights for the subtree */
+    if (mask & LDAP_SUBTREE_RIGHTS) {
+
+	/* Populate the acl data to be added to the subtree */
+	subtreeclass.mod_op=LDAP_MOD_DELETE;
+	subtreeclass.mod_type="ACL";
+
+	if (servicetype == LDAP_KDC_SERVICE) {
+	    for (i=0; strcmp(kdcrights_subtree[i][0], "")!=0; i++) {
+		subtreeacls[0] = (char *) malloc(strlen(kdcrights_subtree[i][0])
+						 + strlen(serviceobjdn)
+						 + strlen(kdcrights_subtree[i][1]) + 1);
+		sprintf(subtreeacls[0], "%s%s%s", kdcrights_subtree[i][0], serviceobjdn,
+			kdcrights_subtree[i][1]);
+		subtreeclass.mod_values= subtreeacls;
+
+		subtreearr[0]=&subtreeclass;
+
+                for(i=0; subtree[i]!=NULL && i<subtreecount; i++) {
+		    st = ldap_modify_ext_s(ld,
+                                            subtree[i],
+                                            subtreearr,
+                                            NULL,
+                                            NULL);
+		    if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+		        free(subtreeacls[0]);
+		        st = set_ldap_error (context, st, OP_MOD);
+		        goto cleanup;
+		    }
+                }
+		free(subtreeacls[0]);
+	    }
+	} else if (servicetype == LDAP_ADMIN_SERVICE) {
+	    for (i=0; strcmp(adminrights_subtree[i][0], "") != 0; i++) {
+		subtreeacls[0] = (char *) malloc(strlen(adminrights_subtree[i][0])
+						 + strlen(serviceobjdn)
+						 + strlen(adminrights_subtree[i][1]) + 1);
+		sprintf(subtreeacls[0], "%s%s%s", adminrights_subtree[i][0], serviceobjdn,
+			adminrights_subtree[i][1]);
+		subtreeclass.mod_values= subtreeacls;
+
+		subtreearr[0]=&subtreeclass;
+
+                for(i=0; subtree[i]!=NULL && i<subtreecount; i++) {
+		    st = ldap_modify_ext_s(ld,
+                                            subtree[i],
+                                            subtreearr,
+                                            NULL,
+                                            NULL);
+		    if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+		        free(subtreeacls[0]);
+		        st = set_ldap_error (context, st, OP_MOD);
+		        goto cleanup;
+		    }
+                }
+		free(subtreeacls[0]);
+	    }
+	} else if (servicetype == LDAP_PASSWD_SERVICE) {
+	    for (i=0; strcmp(pwdrights_subtree[i][0], "") != 0; i++) {
+		subtreeacls[0] = (char *) malloc(strlen(pwdrights_subtree[i][0])
+						 + strlen(serviceobjdn)
+						 + strlen(pwdrights_subtree[i][1]) + 1);
+		sprintf(subtreeacls[0], "%s%s%s", pwdrights_subtree[i][0], serviceobjdn,
+			pwdrights_subtree[i][1]);
+		subtreeclass.mod_values= subtreeacls;
+
+		subtreearr[0]=&subtreeclass;
+
+                for(i=0; subtree[i]!=NULL && i<subtreecount; i++) {
+		    st = ldap_modify_ext_s(ld,
+                                            subtree[i],
+                                            subtreearr,
+                                            NULL,
+                                            NULL);
+		    if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+		        free(subtreeacls[0]);
+		        st = set_ldap_error (context, st, OP_MOD);
+		        goto cleanup;
+		    }
+                }
+		free(subtreeacls[0]);
+	    }
+	}
+    } /* Subtree rights setting ends here */
+
+    st = 0;
+
+cleanup:
+
+    if (realmdn)
+	free(realmdn);
+
+    if (subtree)
+	free(subtree);
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c
new file mode 100644
index 000000000..4991e98be
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c
@@ -0,0 +1,280 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_service_stash.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_service_stash.h"
+
+krb5_error_code
+krb5_ldap_readpassword(context, ldap_context, password)
+    krb5_context                context;
+    krb5_ldap_context           *ldap_context;
+    unsigned char               **password;
+{
+    int                         entryfound=0;
+    krb5_error_code             st=0;
+    char                        line[RECORDLEN]="0", *start=NULL, *file=NULL;
+    char                        errbuf[1024];
+    FILE                        *fptr=NULL;
+
+    *password = NULL;
+
+    if (ldap_context->service_password_file)
+	file = ldap_context->service_password_file;
+
+#ifndef HAVE_STRERROR_R
+# undef strerror_r
+# define strerror_r(ERRNUM, BUF, SIZE) (strncpy(BUF, strerror(ERRNUM), SIZE), BUF[(SIZE)-1] = 0)
+#endif
+
+    /* check whether file exists */
+    if (access(file, F_OK) < 0) {
+	st = errno;
+	strerror_r(errno, errbuf, sizeof(errbuf));
+	krb5_set_error_message (context, st, "%s", errbuf);
+	goto rp_exit;
+    }
+
+    /* check read access */
+    if (access(file, R_OK) < 0) {
+	st = errno;
+	strerror_r(errno, errbuf, sizeof(errbuf));
+	krb5_set_error_message (context, st, "%s", errbuf);
+	goto rp_exit;
+    }
+
+    if ((fptr=fopen(file, "r")) == NULL) {
+	st = errno;
+	strerror_r(errno, errbuf, sizeof(errbuf));
+	krb5_set_error_message (context, st, "%s", errbuf);
+	goto rp_exit;
+    }
+
+    /* get the record from the file */
+    while (fgets(line, RECORDLEN, fptr)!= NULL) {
+	char tmp[RECORDLEN];
+
+	tmp[0] = '\0';
+	/* Handle leading white-spaces */
+	for (start = line; isspace(*start); ++start);
+
+	/* Handle comment lines */
+	if (*start == '!' || *start == '#')
+	    continue;
+	sscanf(line, "%*[ \t]%[^#]", tmp);
+	if (tmp[0] == '\0')
+	    sscanf(line, "%[^#]", tmp);
+	if (strcasecmp(tmp, ldap_context->bind_dn) == 0) {
+	    entryfound = 1; /* service_dn record found !!! */
+	    break;
+	}
+    }
+    fclose (fptr);
+
+    if (entryfound == 0)  {
+	st = KRB5_KDB_SERVER_INTERNAL_ERR;
+	krb5_set_error_message (context, st, "Bind DN entry missing in stash file");
+	goto rp_exit;
+    }
+    /* replace the \n with \0 */
+    start = strchr(line, '\n');
+    if (start)
+	*start = '\0';
+
+    start = strchr(line, '#');
+    if (start == NULL) {
+	/* password field missing */
+	st = KRB5_KDB_SERVER_INTERNAL_ERR;
+	krb5_set_error_message (context, st, "Stash file entry corrupt");
+	goto rp_exit;
+    }
+    ++ start;
+    /* Extract the plain password / certificate file information */
+    {
+	struct data PT, CT;
+
+	/* Check if the entry has the path of a certificate */
+	if (!strncmp(start, "{FILE}", strlen("{FILE}"))) {
+	    /* Set *password = {FILE}<path to cert>\0<cert password> */
+	    /*ptr = strchr(start, ':');
+	      if (ptr == NULL) { */
+	    *password = (unsigned char *)malloc(strlen(start) + 2);
+	    if (*password == NULL) {
+		st = ENOMEM;
+		goto rp_exit;
+	    }
+	    (*password)[strlen(start) + 1] = '\0';
+	    (*password)[strlen(start)] = '\0';
+	    strcpy((char *)(*password), start);
+	    goto got_password;
+	} else {
+	    CT.value = (unsigned char *)start;
+	    CT.len = strlen((char *)CT.value);
+	    st = dec_password(CT, &PT);
+	    if (st != 0) {
+		switch (st) {
+		case ERR_NO_MEM:
+		    st = ENOMEM;
+		    break;
+		case ERR_PWD_ZERO:
+		    st = EINVAL;
+		    krb5_set_error_message(context, st, "Password has zero length");
+		    break;
+		case ERR_PWD_BAD:
+		    st = EINVAL;
+		    krb5_set_error_message(context, st, "Password corrupted");
+		    break;
+		case ERR_PWD_NOT_HEX:
+		    st = EINVAL;
+		    krb5_set_error_message(context, st, "Not a hexadecimal password");
+		    break;
+		default:
+		    st = KRB5_KDB_SERVER_INTERNAL_ERR;
+		    break;
+		}
+		goto rp_exit;
+	    }
+	    *password = PT.value;
+	}
+    }
+got_password:
+
+rp_exit:
+    if (st) {
+	if (*password)
+	    free (*password);
+	*password = NULL;
+    }
+    return st;
+}
+
+/* Encodes a sequence of bytes in hexadecimal */
+
+int
+tohex(in, ret)
+    krb5_data         in;
+    krb5_data         *ret;
+{
+    int                i=0, err = 0;
+
+    ret->length = 0;
+    ret->data = NULL;
+
+    ret->data = malloc((unsigned int)in.length * 2 + 1 /*Null termination */);
+    if (ret->data == NULL) {
+	err = ENOMEM;
+	goto cleanup;
+    }
+    ret->length = in.length * 2;
+    ret->data[ret->length] = 0;
+
+    for (i = 0; i < in.length; i++)
+	sprintf(ret->data + 2 * i, "%02x", in.data[i] & 0xff);
+
+cleanup:
+
+    if (ret->length == 0) {
+	free(ret->data);
+	ret->data = NULL;
+    }
+
+    return err;
+}
+
+/* The entry in the password file will have the following format
+ * <FQDN of service> = <secret>
+ *   <secret> := {HEX}<password in hexadecimal>
+ *
+ * <password> is the actual eDirectory password of the service
+ * Return values:
+ * ERR_NO_MEM      - No Memory
+ * ERR_PWD_ZERO    - Password has zero length
+ * ERR_PWD_BAD     - Passowrd corrupted
+ * ERR_PWD_NOT_HEX - Not a hexadecimal password
+ */
+
+int dec_password(struct data pwd, struct data *ret) {
+    int err=0;
+    int i=0, j=0;
+
+    ret->len = 0;
+    ret->value = NULL;
+
+    if (pwd.len == 0) {
+	err = ERR_PWD_ZERO;
+	ret->len = 0;
+	goto cleanup;
+    }
+
+    /* Check if it is a hexadecimal encoded password */
+    if (pwd.len >= strlen("{HEX}") &&
+	strncmp((char *)pwd.value, "{HEX}", strlen("{HEX}")) == 0) {
+
+	if ((pwd.len - strlen("{HEX}")) % 2 != 0) {
+	    /* A hexadecimal encoded password should have even length */
+	    err = ERR_PWD_BAD;
+	    ret->len = 0;
+	    goto cleanup;
+	}
+	ret->value = (unsigned char *)malloc((pwd.len - strlen("{HEX}")) / 2 + 1);
+	if (ret->value == NULL) {
+	    err = ERR_NO_MEM;
+	    ret->len = 0;
+	    goto cleanup;
+	}
+	ret->len = (pwd.len - strlen("{HEX}")) / 2;
+	ret->value[ret->len] = '\0';
+	for (i = strlen("{HEX}"), j = 0; i < pwd.len; i += 2, j++) {
+	    unsigned int k;
+	    /* Check if it is a hexadecimal number */
+	    if (isxdigit(pwd.value[i]) == 0 || isxdigit(pwd.value[i + 1]) == 0) {
+		err = ERR_PWD_NOT_HEX;
+		ret->len = 0;
+		goto cleanup;
+	    }
+	    sscanf((char *)pwd.value + i, "%2x", &k);
+	    ret->value[j] = k;
+	}
+	goto cleanup;
+    } else {
+	err = ERR_PWD_NOT_HEX;
+	ret->len = 0;
+	goto cleanup;
+    }
+
+cleanup:
+
+    if (ret->len == 0) {
+	free(ret->value);
+	ret->value = NULL;
+    }
+    return(err);
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h
new file mode 100644
index 000000000..bd7e3dc63
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h
@@ -0,0 +1,55 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_service_stash.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LDAP_SERVICE_STASH_H
+#define LDAP_SERVICE_STASH_H 1
+
+#define RECORDLEN 1024
+struct data{
+    int           len;
+    unsigned char *value;
+};
+
+#define ERR_NO_MEM      1
+#define ERR_PWD_ZERO    2
+#define ERR_PWD_BAD     3
+#define ERR_PWD_NOT_HEX 4
+
+int 
+dec_password(struct data, struct data *);
+
+krb5_error_code
+krb5_ldap_readpassword(krb5_context, krb5_ldap_context *, unsigned char **);
+
+int 
+tohex(krb5_data, krb5_data *);
+
+#endif
+
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c
new file mode 100644
index 000000000..3bd5e9049
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c
@@ -0,0 +1,597 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_services.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_services.h"
+#include "ldap_err.h"
+
+#if defined(HAVE_EDIRECTORY)
+
+static char *realmcontclass[] = {"krbRealmContainer", NULL};
+
+/*
+ * create the service object from Directory
+ */
+
+krb5_error_code
+krb5_ldap_create_service(context, service, mask)
+    krb5_context	        context;
+    krb5_ldap_service_params    *service;
+    int                         mask;
+{
+    int                         i=0, j=0;
+    krb5_error_code             st=0;
+    LDAP                        *ld=NULL;
+    char                        **rdns=NULL, *realmattr=NULL, *strval[3]={NULL};
+    LDAPMod                     **mods=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+    char                        errbuf[1024];
+
+    /* validate the input parameter */
+    if (service == NULL || service->servicedn == NULL) {
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Service DN NULL");
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    /* identify the class that the object should belong to. This depends on the servicetype */
+    memset(strval, 0, sizeof(strval));
+    strval[0] = "krbService";
+    if (service->servicetype == LDAP_KDC_SERVICE) {
+	strval[1] = "krbKdcService";
+	realmattr = "krbKdcServers";
+    } else if (service->servicetype == LDAP_ADMIN_SERVICE) {
+	strval[1] = "krbAdmService";
+	realmattr = "krbAdmServers";
+    } else if (service->servicetype == LDAP_PASSWD_SERVICE) {
+	strval[1] = "krbPwdService";
+	realmattr = "krbPwdServers";
+    } else {
+	strval[1] = "krbKdcService";
+	realmattr = "krbKdcServers";
+    }
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    rdns = ldap_explode_dn(service->servicedn, 1);
+    if (rdns == NULL) {
+	st = LDAP_INVALID_DN_SYNTAX;
+	goto cleanup;
+    }
+    memset(strval, 0, sizeof(strval));
+    strval[0] = rdns[0];
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    if (mask & LDAP_SERVICE_SERVICEFLAG) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbserviceflags", LDAP_MOD_ADD,
+					  service->krbserviceflags)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_SERVICE_HOSTSERVER) {
+	if (service->krbhostservers != NULL) {
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbhostserver", LDAP_MOD_ADD,
+					      service->krbhostservers)) != 0)
+		goto cleanup;
+	} else {
+	    st = EINVAL;
+	    krb5_set_error_message (context, st, "'krbhostserver' argument invalid");
+	    goto cleanup;
+	}
+    }
+
+    if (mask & LDAP_SERVICE_REALMREFERENCE) {
+	if (service->krbrealmreferences != NULL) {
+	    unsigned int realmmask=0;
+
+	    /* check for the validity of the values */
+	    for (j=0; service->krbrealmreferences[j] != NULL; ++j) {
+		st = checkattributevalue(ld, service->krbrealmreferences[j], "ObjectClass",
+					 realmcontclass, &realmmask);
+		CHECK_CLASS_VALIDITY(st, realmmask, "realm object value: ");
+	    }
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbrealmreferences", LDAP_MOD_ADD,
+					      service->krbrealmreferences)) != 0)
+		goto cleanup;
+	} else {
+	    st = EINVAL;
+	    krb5_set_error_message (context, st, "Server has no 'krbrealmreferences'");
+	    goto cleanup;
+	}
+    }
+
+    /* ldap add operation */
+    if ((st=ldap_add_ext_s(ld, service->servicedn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_ADD);
+	goto cleanup;
+    }
+
+    /*
+     * If the service created has realm/s associated with it, then the realm should be updated
+     * to have a reference to the service object just created.
+     */
+    if (mask & LDAP_SERVICE_REALMREFERENCE) {
+	for (i=0; service->krbrealmreferences[i]; ++i) {
+	    if ((st=updateAttribute(ld, service->krbrealmreferences[i], realmattr,
+				    service->servicedn)) != 0) {
+		sprintf (errbuf, "Error adding 'krbRealmReferences' to %s: ",
+			 service->krbrealmreferences[i]);
+		prepend_err_str (context, errbuf, st, st);
+		/* delete service object, status ignored intentionally */
+		ldap_delete_ext_s(ld, service->servicedn, NULL, NULL);
+		goto cleanup;
+	    }
+	}
+    }
+
+cleanup:
+
+    if (rdns)
+	ldap_value_free (rdns);
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * modify the service object from Directory
+ */
+
+krb5_error_code
+krb5_ldap_modify_service(context, service, mask)
+    krb5_context	        context;
+    krb5_ldap_service_params    *service;
+    int                         mask;
+{
+    int                         i=0, j=0, count=0;
+    krb5_error_code             st=0;
+    LDAP                        *ld=NULL;
+    char                        **values=NULL, *attr[] = { "krbRealmReferences", NULL};
+    char                        *realmattr=NULL;
+    char                        **oldrealmrefs=NULL, **newrealmrefs=NULL;
+    LDAPMod                     **mods=NULL;
+    LDAPMessage                 *result=NULL, *ent=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* validate the input parameter */
+    if (service == NULL || service->servicedn == NULL) {
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Service DN is NULL");
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if (mask & LDAP_SERVICE_SERVICEFLAG) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbserviceflags", LDAP_MOD_REPLACE,
+					  service->krbserviceflags)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_SERVICE_HOSTSERVER) {
+	if (service->krbhostservers != NULL) {
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbhostserver", LDAP_MOD_REPLACE,
+					      service->krbhostservers)) != 0)
+		goto cleanup;
+	} else {
+	    st = EINVAL;
+	    krb5_set_error_message (context, st, "'krbhostserver' value invalid");
+	    goto cleanup;
+	}
+    }
+
+    if (mask & LDAP_SERVICE_REALMREFERENCE) {
+	if (service->krbrealmreferences != NULL) {
+	    unsigned int realmmask=0;
+
+	    /* check for the validity of the values */
+	    for (j=0; service->krbrealmreferences[j]; ++j) {
+		st = checkattributevalue(ld, service->krbrealmreferences[j], "ObjectClass",
+					 realmcontclass, &realmmask);
+		CHECK_CLASS_VALIDITY(st, realmmask, "realm object value: ");
+	    }
+	    if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbrealmreferences", LDAP_MOD_REPLACE,
+					      service->krbrealmreferences)) != 0)
+		goto cleanup;
+
+
+	    /* get the attribute of the realm to be set */
+	    if (service->servicetype == LDAP_KDC_SERVICE)
+		realmattr = "krbKdcServers";
+	    else if (service->servicetype == LDAP_ADMIN_SERVICE)
+		realmattr = "krbAdmservers";
+	    else if (service->servicetype == LDAP_PASSWD_SERVICE)
+		realmattr = "krbPwdServers";
+	    else
+		realmattr = "krbKdcServers";
+
+	    /* read the existing list of krbRealmreferences. this will needed  */
+	    if ((st = ldap_search_ext_s (ld,
+					 service->servicedn,
+					 LDAP_SCOPE_BASE,
+					 0,
+					 attr,
+					 0,
+					 NULL,
+					 NULL,
+					 NULL,
+					 0,
+					 &result)) != LDAP_SUCCESS) {
+		st = set_ldap_error (context, st, OP_SEARCH);
+		goto cleanup;
+	    }
+
+	    ent = ldap_first_entry(ld, result);
+	    if (ent) {
+		if ((values=ldap_get_values(ld, ent, "krbRealmReferences")) != NULL) {
+		    count = ldap_count_values(values);
+		    if ((st=copy_arrays(values, &oldrealmrefs, count)) != 0)
+			goto cleanup;
+		    ldap_value_free(values);
+		}
+	    }
+	    ldap_msgfree(result);
+	} else {
+	    st = EINVAL;
+	    krb5_set_error_message (context, st, "'krbRealmReferences' value invalid");
+	    goto cleanup;
+	}
+    }
+
+    /* ldap modify operation */
+    if ((st=ldap_modify_ext_s(ld, service->servicedn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_MOD);
+	goto cleanup;
+    }
+
+    /*
+     * If the service modified had realm/s associations changed, then the realm should be
+     * updated to reflect the changes.
+     */
+
+    if (mask & LDAP_SERVICE_REALMREFERENCE) {
+	/* get the count of the new list of krbrealmreferences */
+	for (i=0; service->krbrealmreferences[i]; ++i)
+	    ;
+
+	/* make a new copy of the krbrealmreferences */
+	if ((st=copy_arrays(service->krbrealmreferences, &newrealmrefs, i)) != 0)
+	    goto cleanup;
+
+	/* find the deletions/additions to the list of krbrealmreferences */
+	if (disjoint_members(oldrealmrefs, newrealmrefs) != 0)
+	    goto cleanup;
+
+	/* see if some of the attributes have to be deleted */
+	if (oldrealmrefs) {
+
+	    /* update the dn represented by the attribute that is to be deleted */
+	    for (i=0; oldrealmrefs[i]; ++i)
+		if ((st=deleteAttribute(ld, oldrealmrefs[i], realmattr, service->servicedn)) != 0) {
+		    prepend_err_str (context, "Error deleting realm attribute:", st, st);
+		    goto cleanup;
+		}
+	}
+
+	/* see if some of the attributes have to be added */
+	for (i=0; newrealmrefs[i]; ++i)
+	    if ((st=updateAttribute(ld, newrealmrefs[i], realmattr, service->servicedn)) != 0) {
+		prepend_err_str (context, "Error updating realm attribute: ", st, st);
+		goto cleanup;
+	    }
+    }
+
+cleanup:
+
+    if (oldrealmrefs) {
+	for (i=0; oldrealmrefs[i]; ++i)
+	    free (oldrealmrefs[i]);
+	free (oldrealmrefs);
+    }
+
+    if (newrealmrefs) {
+	for (i=0; newrealmrefs[i]; ++i)
+	    free (newrealmrefs[i]);
+	free (newrealmrefs);
+    }
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+krb5_error_code
+krb5_ldap_delete_service(context, service, servicedn)
+    krb5_context                context;
+    krb5_ldap_service_params    *service;
+    char                        *servicedn;
+{
+    krb5_error_code             st = 0;
+    LDAP                        *ld=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    st = ldap_delete_ext_s(ld, servicedn, NULL, NULL);
+    if (st != 0) {
+	st = set_ldap_error (context, st, OP_DEL);
+    }
+
+    /* NOTE: This should be removed now as the backlinks are going off in OpenLDAP */
+    /* time to delete krbrealmreferences. This is only for OpenLDAP */
+#ifndef HAVE_EDIRECTORY
+    {
+	int                         i=0;
+	char                        *attr=NULL;
+
+	if (service) {
+	    if (service->krbrealmreferences) {
+		if (service->servicetype == LDAP_KDC_SERVICE)
+		    attr = "krbkdcservers";
+		else if (service->servicetype == LDAP_ADMIN_SERVICE)
+		    attr = "krbadmservers";
+		else if (service->servicetype == LDAP_PASSWD_SERVICE)
+		    attr = "krbpwdservers";
+
+		for (i=0; service->krbrealmreferences[i]; ++i) {
+		    deleteAttribute(ld, service->krbrealmreferences[i], attr, servicedn);
+		}
+	    }
+	}
+    }
+#endif
+
+cleanup:
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * This function lists service objects from Directory
+ */
+
+krb5_error_code
+krb5_ldap_list_services(context, containerdn, services)
+    krb5_context	        context;
+    char                        *containerdn;
+    char                        ***services;
+{
+    return (krb5_ldap_list(context, services, "krbService", containerdn));
+}
+
+/*
+ * This function reads the service object from Directory
+ */
+krb5_error_code
+krb5_ldap_read_service(context, servicedn, service, omask)
+    krb5_context	        context;
+    char                        *servicedn;
+    krb5_ldap_service_params    **service;
+    int                         *omask;
+{
+    char                        **values=NULL;
+    int                         i=0, count=0, objectmask=0;
+    krb5_error_code             st=0, tempst=0;
+    LDAPMessage                 *result=NULL,*ent=NULL;
+    char                        *attributes[] = {"krbHostServer", "krbServiceflags",
+						 "krbRealmReferences", "objectclass", NULL};
+    char                        *attrvalues[] = {"krbService", NULL};
+    krb5_ldap_service_params    *lservice=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+    LDAP                        *ld = NULL;
+
+    /* validate the input parameter */
+    if (servicedn == NULL) {
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Service DN NULL");
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    *omask = 0;
+
+    /* the policydn object should be of the krbService object class */
+    st = checkattributevalue(ld, servicedn, "objectClass", attrvalues, &objectmask);
+    CHECK_CLASS_VALIDITY(st, objectmask, "service object value: ");
+
+    /* Initialize service structure */
+    lservice =(krb5_ldap_service_params *) calloc(1, sizeof(krb5_ldap_service_params));
+    if (lservice == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    /* allocate tl_data structure to store MASK information */
+    lservice->tl_data = calloc (1, sizeof(*lservice->tl_data));
+    if (lservice->tl_data == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    lservice->tl_data->tl_data_type = KDB_TL_USER_INFO;
+
+    LDAP_SEARCH(servicedn, LDAP_SCOPE_BASE, "(objectclass=krbService)", attributes);
+
+    lservice->servicedn = strdup(servicedn);
+    CHECK_NULL(lservice->servicedn);
+
+    ent=ldap_first_entry(ld, result);
+    if (ent != NULL) {
+
+	if ((values=ldap_get_values(ld, ent, "krbServiceFlags")) != NULL) {
+	    lservice->krbserviceflags = atoi(values[0]);
+	    *omask |= LDAP_SERVICE_SERVICEFLAG;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "krbHostServer")) != NULL) {
+	    count = ldap_count_values(values);
+	    if ((st=copy_arrays(values, &(lservice->krbhostservers), count)) != 0)
+		goto cleanup;
+	    *omask |= LDAP_SERVICE_HOSTSERVER;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "krbRealmReferences")) != NULL) {
+	    count = ldap_count_values(values);
+	    if ((st=copy_arrays(values, &(lservice->krbrealmreferences), count)) != 0)
+		goto cleanup;
+	    *omask |= LDAP_SERVICE_REALMREFERENCE;
+	    ldap_value_free(values);
+	}
+
+	if ((values=ldap_get_values(ld, ent, "objectClass")) != NULL) {
+	    for (i=0; values[i]; ++i) {
+		if (strcasecmp(values[i], "krbKdcService") == 0) {
+		    lservice->servicetype = LDAP_KDC_SERVICE;
+		    break;
+		}
+
+		if (strcasecmp(values[i], "krbAdmService") == 0) {
+		    lservice->servicetype = LDAP_ADMIN_SERVICE;
+		    break;
+		}
+
+		if (strcasecmp(values[i], "krbPwdService") == 0) {
+		    lservice->servicetype = LDAP_PASSWD_SERVICE;
+		    break;
+		}
+	    }
+	    ldap_value_free(values);
+	}
+    }
+    ldap_msgfree(result);
+
+cleanup:
+    if (st != 0) {
+	krb5_ldap_free_service(context, lservice);
+	*service = NULL;
+    } else {
+	store_tl_data(lservice->tl_data, KDB_TL_MASK, omask);
+	*service = lservice;
+    }
+
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+/*
+ * This function frees the krb5_ldap_service_params structure members.
+ */
+
+krb5_error_code
+krb5_ldap_free_service(context, service)
+    krb5_context                context;
+    krb5_ldap_service_params    *service;
+{
+    int                         i=0;
+
+    if (service == NULL)
+	return 0;
+
+    if (service->servicedn)
+	free (service->servicedn);
+
+    if (service->krbrealmreferences) {
+	for (i=0; service->krbrealmreferences[i]; ++i)
+	    free (service->krbrealmreferences[i]);
+	free (service->krbrealmreferences);
+    }
+
+    if (service->krbhostservers) {
+	for (i=0; service->krbhostservers[i]; ++i)
+	    free (service->krbhostservers[i]);
+	free (service->krbhostservers);
+    }
+
+    if (service->tl_data) {
+	if (service->tl_data->tl_data_contents)
+	    free (service->tl_data->tl_data_contents);
+	free (service->tl_data);
+    }
+
+    free (service);
+    return 0;
+}
+
+krb5_error_code
+krb5_ldap_set_service_passwd(context, service, passwd)
+    krb5_context                context;
+    char                        *service;
+    char                        *passwd;
+{
+    krb5_error_code             st=0;
+    LDAPMod                     **mods=NULL;
+    char                        *password[2] = {NULL};
+    LDAP                        *ld=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    password[0] = passwd;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "userPassword", LDAP_MOD_REPLACE, password)) != 0)
+	goto cleanup;
+
+    st = ldap_modify_ext_s(ld, service, mods, NULL, NULL);
+    if (st) {
+	st = set_ldap_error (context, st, OP_MOD);
+    }
+
+cleanup:
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h
new file mode 100644
index 000000000..d4bbb077d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h
@@ -0,0 +1,97 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_services.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_SERVICE_H
+#define _LDAP_SERVICE_H 1
+
+/* service specific mask */
+#define LDAP_SERVICE_SERVICEFLAG      0x0001
+#define LDAP_SERVICE_HOSTSERVER       0x0002
+#define LDAP_SERVICE_REALMREFERENCE   0x0004
+
+/* service type mask */
+#define LDAP_KDC_SERVICE              0x0001
+#define LDAP_ADMIN_SERVICE            0x0002
+#define LDAP_PASSWD_SERVICE           0x0004
+
+/* rights mask */
+#define LDAP_SUBTREE_RIGHTS           0x0001
+#define LDAP_REALM_RIGHTS             0x0002
+
+/* Types of service flags */
+#define SERVICE_FLAGS_AUTO_RESTART          0x0001
+#define SERVICE_FLAGS_CHECK_ADDRESSES       0x0002
+#define SERVICE_FLAGS_UNIXTIME_OLD_PATYPE   0x0004
+
+/* Service protocol type */
+#define SERVICE_PROTOCOL_TYPE_UDP     "0"
+#define SERVICE_PROTOCOL_TYPE_TCP     "1"
+
+typedef struct _krb5_ldap_service_params {
+        char            *servicedn;
+        int             servicetype;
+        int             krbserviceflags;
+        char            **krbhostservers;
+        char            **krbrealmreferences;
+        krb5_tl_data    *tl_data;
+} krb5_ldap_service_params;
+
+#ifdef HAVE_EDIRECTORY
+
+krb5_error_code
+krb5_ldap_read_service( krb5_context, char *, krb5_ldap_service_params **, int *);
+
+krb5_error_code
+krb5_ldap_create_service( krb5_context, krb5_ldap_service_params *,int);
+
+krb5_error_code
+krb5_ldap_modify_service( krb5_context, krb5_ldap_service_params *, int);
+
+krb5_error_code
+krb5_ldap_delete_service( krb5_context, krb5_ldap_service_params *, char *);
+
+krb5_error_code
+krb5_ldap_list_services( krb5_context, char *, char ***);
+
+krb5_error_code
+krb5_ldap_free_service( krb5_context, krb5_ldap_service_params *);
+
+
+krb5_error_code
+krb5_ldap_set_service_passwd( krb5_context, char *, char *);
+
+krb5_error_code 
+krb5_ldap_add_service_rights( krb5_context, int, char *, char *, char **, int);
+
+krb5_error_code
+krb5_ldap_delete_service_rights( krb5_context, int, char *, char *, char **, int);
+#endif
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
new file mode 100644
index 000000000..face03859
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
@@ -0,0 +1,501 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_tkt_policy.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_tkt_policy.h"
+#include "ldap_err.h"
+
+/* Ticket policy object management */
+
+/*
+ * create the Ticket policy object in Directory.
+ */
+krb5_error_code
+krb5_ldap_create_policy(context, policy, mask)
+    krb5_context	        context;
+    krb5_ldap_policy_params     *policy;
+    int                         mask;
+{
+    krb5_error_code             st=0;
+    LDAP                        *ld=NULL;
+    char                        *strval[3]={NULL}, *policy_dn = NULL;
+    LDAPMod                     **mods=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* validate the input parameters */
+    if (policy == NULL || policy->policy == NULL) {
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Ticket Policy Name missing");
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if ((st = krb5_ldap_name_to_policydn (context, policy->policy, &policy_dn)) != 0)
+	goto cleanup;
+
+    memset(strval, 0, sizeof(strval));
+    strval[0] = policy->policy;
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    memset(strval, 0, sizeof(strval));
+    strval[0] = "krbTicketPolicy";
+    strval[1] = "krbTicketPolicyaux";
+    if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+	goto cleanup;
+
+    if (mask & LDAP_POLICY_MAXTKTLIFE) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_ADD,
+					  policy->maxtktlife)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_POLICY_MAXRENEWLIFE) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_ADD,
+					  policy->maxrenewlife)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_POLICY_TKTFLAGS) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_ADD,
+					  policy->tktflags)) != 0)
+	    goto cleanup;
+    }
+
+    /* ldap add operation */
+    if ((st=ldap_add_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_ADD);
+	goto cleanup;
+    }
+
+cleanup:
+    if (policy_dn != NULL)
+	free(policy_dn);
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * modify the Ticket policy object in Directory.
+ */
+
+krb5_error_code
+krb5_ldap_modify_policy(context, policy, mask)
+    krb5_context	        context;
+    krb5_ldap_policy_params     *policy;
+    int                         mask;
+{
+    int                         objectmask=0;
+    krb5_error_code             st=0;
+    LDAP                        *ld=NULL;
+    char                        *attrvalues[]={"krbTicketPolicy", "krbTicketPolicyAux", NULL}, *strval[2]={NULL};
+    char                        *policy_dn = NULL;
+    LDAPMod                     **mods=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* validate the input parameters */
+    if (policy == NULL || policy->policy==NULL) {
+	st = EINVAL;
+	krb5_set_error_message (context, st, "Ticket Policy Name missing");
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if ((st = krb5_ldap_name_to_policydn (context, policy->policy, &policy_dn)) != 0)
+	goto cleanup;
+
+    /* the policydn object should be of the krbTicketPolicy object class */
+    st = checkattributevalue(ld, policy_dn, "objectClass", attrvalues, &objectmask);
+    CHECK_CLASS_VALIDITY(st, objectmask, "ticket policy object: ");
+
+    if ((objectmask & 0x02) == 0) { /* add krbticketpolicyaux to the object class list */
+	memset(strval, 0, sizeof(strval));
+	strval[0] = "krbTicketPolicyAux";
+	if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_POLICY_MAXTKTLIFE) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE,
+					  policy->maxtktlife)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_POLICY_MAXRENEWLIFE) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE,
+					  policy->maxrenewlife)) != 0)
+	    goto cleanup;
+    }
+
+    if (mask & LDAP_POLICY_TKTFLAGS) {
+	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE,
+					  policy->tktflags)) != 0)
+	    goto cleanup;
+    }
+
+    if ((st=ldap_modify_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
+	st = set_ldap_error (context, st, OP_MOD);
+	goto cleanup;
+    }
+
+cleanup:
+    if (policy_dn != NULL)
+        free(policy_dn);
+
+    ldap_mods_free(mods, 1);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * Read the policy object from the Directory and populate the krb5_ldap_policy_params
+ * structure.
+ */
+
+krb5_error_code
+krb5_ldap_read_policy(context, policyname, policy, omask)
+    krb5_context	        context;
+    char                        *policyname;
+    krb5_ldap_policy_params     **policy;
+    int                         *omask;
+{
+    krb5_error_code             st=0, tempst=0;
+    int                         objectmask=0;
+    LDAP                        *ld=NULL;
+    LDAPMessage                 *result=NULL,*ent=NULL;
+    char                        *attributes[] = { "krbMaxTicketLife", "krbMaxRenewableAge", "krbTicketFlags", NULL};
+    char                        *attrvalues[] = { "krbTicketPolicy", NULL}, *policy_dn = NULL;
+    krb5_ldap_policy_params     *lpolicy=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    /* validate the input parameters */
+    if (policyname == NULL  || policy == NULL) {
+	st = EINVAL;
+	krb5_set_error_message(context, st, "Ticket Policy Object information missing");
+	goto cleanup;
+    }
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if ((st = krb5_ldap_name_to_policydn (context, policyname, &policy_dn)) != 0)
+	goto cleanup;
+
+    /* the policydn object should be of the krbTicketPolicy object class */
+    st = checkattributevalue(ld, policy_dn, "objectClass", attrvalues, &objectmask);
+    CHECK_CLASS_VALIDITY(st, objectmask, "ticket policy object: ");
+
+    /* Initialize ticket policy structure */
+    lpolicy =(krb5_ldap_policy_params *) malloc(sizeof(krb5_ldap_policy_params));
+    CHECK_NULL(lpolicy);
+    memset(lpolicy, 0, sizeof(krb5_ldap_policy_params));
+
+    if ((lpolicy->policy = strdup (policyname)) == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    lpolicy->tl_data = calloc (1, sizeof(*lpolicy->tl_data));
+    CHECK_NULL(lpolicy->tl_data);
+    lpolicy->tl_data->tl_data_type = KDB_TL_USER_INFO;
+
+    LDAP_SEARCH(policy_dn, LDAP_SCOPE_BASE, "(objectclass=krbTicketPolicy)", attributes);
+
+    *omask = 0;
+
+    ent=ldap_first_entry(ld, result);
+    if (ent != NULL) {
+	if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", (int *) &(lpolicy->maxtktlife)) == 0)
+	    *omask |= LDAP_POLICY_MAXTKTLIFE;
+
+	if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", (int *) &(lpolicy->maxrenewlife)) == 0)
+	    *omask |= LDAP_POLICY_MAXRENEWLIFE;
+
+	if (krb5_ldap_get_value(ld, ent, "krbticketflags", (int *) &(lpolicy->tktflags)) == 0)
+	    *omask |= LDAP_POLICY_TKTFLAGS;
+    }
+    ldap_msgfree(result);
+
+    lpolicy->mask = *omask;
+    store_tl_data(lpolicy->tl_data, KDB_TL_MASK, omask);
+    *policy = lpolicy;
+
+cleanup:
+    if (st != 0) {
+	krb5_ldap_free_policy(context, lpolicy);
+	*policy = NULL;
+    }
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * Function to delete ticket policy object from the directory.  Before
+ * calling this function krb5_ldap_read_policy should be called to
+ * check the existence of the object.  This serves one major purpose,
+ * i.e., if the object to be is anything other than the ticket policy
+ * object then the krb5_ldap_read_policy returns an error and thus is
+ * not accidently deleted in this function.
+ *
+ * NOTE: Other kerberos objects (user/realm object) might be having
+ * references to the policy object to be deleted. This situation is
+ * not handled here, instead is taken care of at all the places where
+ * the deleted policy object is read, to ignore a return status of
+ * LDAP_NO_SUCH_OBJECT and continue.
+ */
+
+krb5_error_code
+krb5_ldap_delete_policy(context, policyname)
+    krb5_context                context;
+    char                        *policyname;
+{
+	int                         refcount = 0;
+	char                        *policy_dn = NULL;
+    krb5_error_code             st = 0;
+    LDAP                        *ld = NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+	if (policyname == NULL) {
+	st = EINVAL;
+	prepend_err_str (context,"Ticket Policy Object DN missing",st,st);
+	goto cleanup;
+    }
+
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    if ((st = krb5_ldap_name_to_policydn (context, policyname, &policy_dn)) != 0)
+        goto cleanup;
+
+    /* Checking for policy count for 0 and will not permit delete if
+     * it is greater than 0.  */
+
+    if ((st = krb5_ldap_get_reference_count (context, policy_dn,
+                    "krbTicketPolicyReference", &refcount, ld)) != 0)
+        goto cleanup;
+
+    if (refcount == 0) {
+	if ((st=ldap_delete_ext_s(ld, policy_dn, NULL, NULL)) != 0) {
+	    prepend_err_str (context,ldap_err2string(st),st,st);
+
+	    goto cleanup;
+	}
+    } else {
+	st = EINVAL;
+	prepend_err_str (context,"Delete Failed: One or more Principals associated with the Ticket Policy",st,st);
+	goto cleanup;
+    }
+
+cleanup:
+    if (policy_dn != NULL)
+        free (policy_dn);
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
+
+
+/*
+ * list policy objects from Directory
+ */
+
+krb5_error_code
+krb5_ldap_list_policy(context, containerdn, policy)
+    krb5_context	        context;
+    char                        *containerdn;
+    char                        ***policy;
+{
+    int                         i, j, count;
+    char                        **list = NULL;
+    char                        *policycontainerdn = containerdn;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_error_code             st=0;
+
+    SETUP_CONTEXT();
+    if (policycontainerdn == NULL) {
+        policycontainerdn = ldap_context->lrparams->realmdn;
+    }
+
+    if ((st = krb5_ldap_list(context, &list, "krbTicketPolicy", policycontainerdn)) != 0)
+	goto cleanup;
+
+    for (i = 0; list[i] != NULL; i++);
+
+    count = i;
+
+    *policy = (char **) calloc ((unsigned) count + 1, sizeof(char *));
+    if (*policy == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    for (i = 0, j = 0; list[i] != NULL; i++, j++) {
+	int ret;
+	ret = krb5_ldap_policydn_to_name (context, list[i], &(*policy)[i]);
+	if (ret != 0)
+	    j--;
+    }
+
+cleanup:
+    return st;
+}
+
+/*
+ * Function to free the ticket policy object structure.
+ * Note: this function assumes that memory of the policy structure is dynamically allocated and hence the whole
+ * structure is freed up. Care should be taken not to call this function on a static structure
+ */
+
+krb5_error_code
+krb5_ldap_free_policy(context, policy)
+    krb5_context                context;
+    krb5_ldap_policy_params    *policy;
+{
+
+    krb5_error_code st=0;
+
+    if (policy == NULL)
+	return st;
+
+    if (policy->policy)
+	free (policy->policy);
+
+    if (policy->tl_data) {
+	if (policy->tl_data->tl_data_contents)
+	    free (policy->tl_data->tl_data_contents);
+	free (policy->tl_data);
+    }
+    free (policy);
+
+    return st;
+}
+
+/*
+ * This function is general object listing routine.  It is currently
+ * used for ticket policy object listing.
+ */
+
+krb5_error_code
+krb5_ldap_list(context, list, objectclass, containerdn)
+    krb5_context	        context;
+    char                        ***list;
+    char                        *objectclass;
+    char                        *containerdn;
+{
+    char                        *filter=NULL, *dn=NULL;
+    krb5_error_code             st=0, tempst=0;
+    int                         i=0, count=0, filterlen=0;
+    LDAP                        *ld=NULL;
+    LDAPMessage                 *result=NULL,*ent=NULL;
+    kdb5_dal_handle             *dal_handle=NULL;
+    krb5_ldap_context           *ldap_context=NULL;
+    krb5_ldap_server_handle     *ldap_server_handle=NULL;
+
+    SETUP_CONTEXT();
+    GET_HANDLE();
+
+    /* check if the containerdn exists */
+    if (containerdn) {
+	if ((st=checkattributevalue(ld, containerdn, NULL, NULL, NULL)) != 0) {
+	    prepend_err_str (context, "Error reading container object: ", st, st);
+	    goto cleanup;
+	}
+    }
+
+    /* set the filter for the search operation */
+    filterlen = strlen("(objectclass=") + strlen(objectclass) + 1 + 1;
+    filter = malloc ((unsigned) filterlen);
+    if (filter == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+    snprintf(filter, (unsigned) filterlen,"(objectclass=%s)",objectclass);
+
+    LDAP_SEARCH(containerdn, LDAP_SCOPE_SUBTREE, filter, NULL);
+
+    count = ldap_count_entries(ld, result);
+    if (count == -1) {
+	ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st);
+	st = set_ldap_error(context, st, OP_SEARCH);
+	goto cleanup;
+    }
+    *list = (char **) calloc ((unsigned) count+1, sizeof(char *));
+    if (*list == NULL) {
+	st = ENOMEM;
+	goto cleanup;
+    }
+
+    for (ent=ldap_first_entry(ld, result), count=0; ent != NULL; ent=ldap_next_entry(ld, ent), ++count) {
+	if ((dn=ldap_get_dn(ld, ent)) == NULL)
+	    continue;
+	if (((*list)[count] = strdup(dn)) == NULL) {
+	    ldap_memfree (dn);
+	    st = ENOMEM;
+	    goto cleanup;
+	}
+	ldap_memfree(dn);
+    }
+    ldap_msgfree(result);
+
+cleanup:
+    if (filter)
+	free (filter);
+
+    /* some error, free up all the memory */
+    if (st != 0) {
+	if (*list) {
+	    for (i=0; (*list)[i]; ++i)
+		free ((*list)[i]);
+	    free (*list);
+	    *list = NULL;
+	}
+    }
+    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+    return st;
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h
new file mode 100644
index 000000000..9a1f2ea11
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h
@@ -0,0 +1,75 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_tkt_policy.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *   * The copyright holder's name is not used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_POLICY_H
+#define _LDAP_POLICY_H 1
+
+/* policy specific mask */
+
+#define LDAP_POLICY_MAXTKTLIFE        0x0001
+#define LDAP_POLICY_MAXRENEWLIFE      0x0002
+#define LDAP_POLICY_TKTFLAGS          0x0004
+#define LDAP_POLICY_COUNT             0x0008
+/* policy object structure */
+
+typedef struct _krb5_ldap_policy_params {
+  char                  *policy;
+  long                  mask;
+  long                  maxtktlife;
+  long                  maxrenewlife;
+  long                  tktflags;
+  krb5_tl_data          *tl_data;
+}krb5_ldap_policy_params;
+
+krb5_error_code
+krb5_ldap_create_policy(krb5_context, krb5_ldap_policy_params *, int);
+
+krb5_error_code
+krb5_ldap_modify_policy(krb5_context, krb5_ldap_policy_params *, int);
+
+krb5_error_code
+krb5_ldap_read_policy(krb5_context, char *, krb5_ldap_policy_params **, int *);
+
+krb5_error_code
+krb5_ldap_delete_policy(krb5_context, char *);
+
+krb5_error_code
+krb5_ldap_clear_policy(krb5_context, char *);
+
+krb5_error_code
+krb5_ldap_list_policy(krb5_context, char *, char ***);
+
+krb5_error_code
+krb5_ldap_free_policy(krb5_context, krb5_ldap_policy_params *);
+
+krb5_error_code
+krb5_ldap_change_count(krb5_context ,char * , int);
+
+#endif
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
new file mode 100644
index 000000000..bd55f0a5d
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
@@ -0,0 +1,50 @@
+tohex
+krb5_ldap_open
+krb5_ldap_close
+krb5_ldap_db_init
+krb5_ldap_lib_init
+krb5_ldap_lib_cleanup
+krb5_ldap_db_get_age
+krb5_ldap_read_server_params
+krb5_ldap_put_principal
+krb5_ldap_get_principal
+krb5_ldap_delete_principal
+krb5_ldap_free_principal
+krb5_ldap_iterate
+krb5_ldap_read_krbcontainer_params
+krb5_ldap_list_realm
+krb5_ldap_read_realm_params
+krb5_ldap_free_realm_params
+krb5_ldap_modify_realm
+krb5_ldap_create_krbcontainer
+krb5_ldap_create_realm
+krb5_ldap_delete_realm
+krb5_ldap_list_policy
+krb5_ldap_free_policy
+krb5_ldap_read_policy
+krb5_ldap_modify_policy
+krb5_ldap_delete_policy
+krb5_ldap_create_policy
+krb5_ldap_create_password_policy
+krb5_ldap_put_password_policy
+krb5_ldap_get_password_policy
+krb5_ldap_delete_password_policy
+krb5_ldap_free_password_policy
+krb5_ldap_iterate_password_policy
+krb5_dbe_free_contents
+krb5_ldap_free_server_params
+krb5_ldap_free_krbcontainer_params
+krb5_ldap_alloc
+krb5_ldap_free
+krb5_ldap_set_mkey
+krb5_ldap_get_mkey
+disjoint_members
+krb5_ldap_delete_realm_1
+krb5_ldap_set_option
+krb5_ldap_lock
+krb5_ldap_unlock
+krb5_ldap_supported_realms
+krb5_ldap_free_supported_realms
+krb5_ldap_errcode_2_string
+krb5_ldap_release_errcode_string
+krb5_ldap_create
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c
new file mode 100644
index 000000000..501d263b1
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c
@@ -0,0 +1,232 @@
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "princ_xdr.h"
+#include <kadm5/admin.h>
+
+bool_t
+ldap_xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp)
+{
+    unsigned int tmp;
+
+    tmp = (unsigned int) *objp;
+
+    if (!xdr_u_int(xdrs, &tmp))
+	return(FALSE);
+
+    *objp = (krb5_ui_2) tmp;
+    return(TRUE);
+}
+
+bool_t
+ldap_xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp)
+{
+    int tmp;
+
+    tmp = (int) *objp;
+
+    if (!xdr_int(xdrs, &tmp))
+	return(FALSE);
+
+    *objp = (krb5_int16) tmp;
+    return(TRUE);
+}
+
+bool_t
+ldap_xdr_nullstring(XDR *xdrs, char **objp)
+{
+    u_int size;
+
+    if (xdrs->x_op == XDR_ENCODE) {
+	if (*objp == NULL)
+	    size = 0;
+	else
+	    size = strlen(*objp) + 1;
+    }
+    if (! xdr_u_int(xdrs, &size)) {
+	return FALSE;
+    }
+    switch (xdrs->x_op) {
+    case XDR_DECODE:
+	if (size == 0) {
+	    *objp = NULL;
+	    return TRUE;
+	} else if (*objp == NULL) {
+	    *objp = (char *) mem_alloc(size);
+	    if (*objp == NULL) {
+		/*errno = ENOMEM;*/
+		return FALSE;
+	    }
+	}
+	return (xdr_opaque(xdrs, *objp, size));
+
+    case XDR_ENCODE:
+	if (size != 0)
+	    return (xdr_opaque(xdrs, *objp, size));
+	return TRUE;
+
+    case XDR_FREE:
+	if (*objp != NULL)
+	    mem_free(*objp, size);
+	*objp = NULL;
+	return TRUE;
+    }
+    return FALSE;
+}
+
+bool_t
+ldap_xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp)
+{
+    unsigned char tmp;
+
+    tmp = '\0'; /* for purify, else xdr_u_char performs a umr */
+
+    if (xdrs->x_op == XDR_ENCODE)
+	tmp = (unsigned char) *objp;
+
+    if (!xdr_u_char(xdrs, &tmp))
+	return (FALSE);
+
+    if (xdrs->x_op == XDR_DECODE)
+	*objp = (krb5_kvno) tmp;
+    return (TRUE);
+}
+
+bool_t
+ldap_xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp)
+{
+    unsigned int tmp;
+
+    if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_ver))
+	return(FALSE);
+    if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_kvno))
+	return(FALSE);
+    if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_type[0]))
+	return(FALSE);
+    if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_type[1]))
+	return(FALSE);
+    if (!ldap_xdr_krb5_ui_2(xdrs, &objp->key_data_length[0]))
+	return(FALSE);
+    if (!ldap_xdr_krb5_ui_2(xdrs, &objp->key_data_length[1]))
+	return(FALSE);
+
+    tmp = (unsigned int) objp->key_data_length[0];
+    if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
+		   &tmp, (unsigned int) ~0))
+	return FALSE;
+
+    tmp = (unsigned int) objp->key_data_length[1];
+    if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
+		   &tmp, (unsigned int) ~0))
+	return FALSE;
+
+    /* don't need to copy tmp out, since key_data_length will be set
+       by the above encoding. */
+    return(TRUE);
+}
+
+bool_t
+ldap_xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp)
+{
+    if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
+		   (u_int *) &objp->n_key_data, (unsigned int) ~0,
+		   sizeof(krb5_key_data),
+		   ldap_xdr_krb5_key_data))
+	return (FALSE);
+    return (TRUE);
+}
+
+bool_t
+ldap_xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp)
+{
+    switch (xdrs->x_op) {
+    case XDR_ENCODE:
+	objp->version = OSA_ADB_PRINC_VERSION_1;
+	/* fall through */
+    case XDR_FREE:
+	if (!xdr_int(xdrs, &objp->version))
+	    return FALSE;
+	break;
+    case XDR_DECODE:
+	if (!xdr_int(xdrs, &objp->version))
+	    return FALSE;
+	if (objp->version != OSA_ADB_PRINC_VERSION_1)
+	    return FALSE;
+	break;
+    }
+
+    if (!ldap_xdr_nullstring(xdrs, &objp->policy))
+	return (FALSE);
+    if (!xdr_long(xdrs, &objp->aux_attributes))
+	return (FALSE);
+    if (!xdr_u_int(xdrs, &objp->old_key_next))
+	return (FALSE);
+    if (!ldap_xdr_krb5_kvno(xdrs, &objp->admin_history_kvno))
+	return (FALSE);
+    if (!xdr_array(xdrs, (caddr_t *) &objp->old_keys,
+		   (unsigned int *) &objp->old_key_len, (unsigned int) ~0,
+		   sizeof(osa_pw_hist_ent),
+		   ldap_xdr_osa_pw_hist_ent))
+	return (FALSE);
+    return (TRUE);
+}
+
+void
+ldap_osa_free_princ_ent(osa_princ_ent_t val)
+{
+    XDR xdrs;
+
+    xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+
+    ldap_xdr_osa_princ_ent_rec(&xdrs, val);
+    free(val);
+}
+
+krb5_error_code
+krb5_lookup_tl_kadm_data(krb5_tl_data *tl_data, osa_princ_ent_rec *princ_entry)
+{
+
+    XDR xdrs;
+
+    xdrmem_create(&xdrs, tl_data->tl_data_contents,
+		  tl_data->tl_data_length, XDR_DECODE);
+    if (! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
+	xdr_destroy(&xdrs);
+	return(KADM5_XDR_FAILURE);
+    }
+    xdr_destroy(&xdrs);
+
+    return 0;
+
+}
+
+krb5_error_code
+krb5_update_tl_kadm_data(policy_dn, new_tl_data)
+    char	        * policy_dn;
+    krb5_tl_data        * new_tl_data;
+{
+    XDR xdrs;
+    osa_princ_ent_t princ_entry;
+
+    if ((princ_entry = (osa_princ_ent_t) malloc(sizeof(osa_princ_ent_rec))) == NULL)
+	return ENOMEM;
+
+    memset(princ_entry, 0, sizeof(osa_princ_ent_rec));
+    princ_entry->admin_history_kvno = 2;
+    princ_entry->aux_attributes = KADM5_POLICY;
+    princ_entry->policy = policy_dn;
+
+    xdralloc_create(&xdrs, XDR_ENCODE);
+    if (! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
+	xdr_destroy(&xdrs);
+	return(KADM5_XDR_FAILURE);
+    }
+    new_tl_data->tl_data_type = KRB5_TL_KADM_DATA;
+    new_tl_data->tl_data_length = xdr_getpos(&xdrs);
+    new_tl_data->tl_data_contents = (krb5_octet *)xdralloc_getdata(&xdrs);
+
+    /*
+      xdr_destroy(&xdrs);
+      ldap_osa_free_princ_ent(princ_entry);
+    */
+    return(0);
+}
diff --git a/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h
new file mode 100644
index 000000000..65a03f7dd
--- /dev/null
+++ b/krb5-1-6/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h
@@ -0,0 +1,61 @@
+#ifndef _PRINC_XDR_H
+#define _PRINC_XDR_H 1
+
+#include <sys/types.h>
+#include <krb5.h>
+#include <kdb.h>
+#include <gssrpc/rpc.h>
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+#define OSA_ADB_PRINC_VERSION_1  0x12345C01
+#define KADM5_XDR_FAILURE                        (43787575L)
+
+typedef struct _osa_pw_hist_t {
+  int n_key_data;
+  krb5_key_data *key_data;
+} osa_pw_hist_ent, *osa_pw_hist_t;
+
+typedef struct _osa_princ_ent_t {
+  int                         version;
+  char                        *policy;
+  long                        aux_attributes;
+  unsigned int                old_key_len;
+  unsigned int                old_key_next;
+  krb5_kvno                   admin_history_kvno;
+  osa_pw_hist_ent             *old_keys;
+} osa_princ_ent_rec, *osa_princ_ent_t;
+
+bool_t
+ldap_xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp);
+
+bool_t
+ldap_xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp);
+
+bool_t 
+ldap_xdr_nullstring(XDR *xdrs, char **objp);
+
+bool_t
+ldap_xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp);
+
+bool_t
+ldap_xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp);
+
+bool_t
+ldap_xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp);
+
+bool_t
+ldap_xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp);
+
+void
+ldap_osa_free_princ_ent(osa_princ_ent_t val);
+
+krb5_error_code
+krb5_lookup_tl_kadm_data(krb5_tl_data *tl_data, osa_princ_ent_rec *princ_entry);
+
+krb5_error_code
+krb5_update_tl_kadm_data(char *, krb5_tl_data *);
+
+#endif
diff --git a/krb5-1-6/src/plugins/locate/python/Makefile.in b/krb5-1-6/src/plugins/locate/python/Makefile.in
new file mode 100644
index 000000000..9915052aa
--- /dev/null
+++ b/krb5-1-6/src/plugins/locate/python/Makefile.in
@@ -0,0 +1,43 @@
+thisconfigdir=.
+myfulldir=plugins/locate/python
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..
+
+LIBBASE=python
+LIBMAJOR=0
+LIBMINOR=0
+SO_EXT=.so
+RELDIR=../plugins/locate/python
+MODULE_INSTALL_DIR = $(KRB5_LIBKRB5_MODULE_DIR)
+
+SHLIB_EXPDEPS= $(KRB5_DEPLIB)
+SHLIB_EXPLIBS= -lpython2.3 $(KRB5_LIB)
+
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+SRCS= \
+	$(srcdir)/py-locate.c
+STOBJLISTS=OBJS.ST
+STLIBOBJS= py-locate.o
+
+all-unix:: $(LIBBASE)$(SO_EXT)
+install-unix:: install-libs
+clean-unix:: clean-libs clean-libobjs
+
+@libnover_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+py-locate.so py-locate.po $(OUTPRE)py-locate.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h py-locate.c
diff --git a/krb5-1-6/src/plugins/locate/python/configure.in b/krb5-1-6/src/plugins/locate/python/configure.in
new file mode 100644
index 000000000..34f8306b5
--- /dev/null
+++ b/krb5-1-6/src/plugins/locate/python/configure.in
@@ -0,0 +1,10 @@
+K5_AC_INIT(configure.in)
+enable_shared=yes
+build_dynobj=yes
+CONFIG_RULES
+AC_CHECK_HEADERS(Python.h python2.3/Python.h)
+dnl AC_CHECK_LIB(python2.3)
+
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/plugins/locate/python/locate-service.py b/krb5-1-6/src/plugins/locate/python/locate-service.py
new file mode 100644
index 000000000..53153be77
--- /dev/null
+++ b/krb5-1-6/src/plugins/locate/python/locate-service.py
@@ -0,0 +1,77 @@
+# Copyright 2006 Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+# possible return values:
+#  False: request not handled by this script, try another means
+#  empty list: no server available, e.g., TCP KDC in realm with only UDP
+#  ordered list of (ip-addr-string, port-number-or-string, socket-type)
+#
+# Field ip-addr-string is a numeric representation of the IPv4 or IPv6
+# address.  Field port-number-or-string is, for example, "88" or 88.  The
+# socket type is also expressed numerically, SOCK_DGRAM or SOCK_STREAM.
+# It must agree with the supplied socktype value if that is non-zero, but
+# zero must not be used in the returned list.
+#
+# service enum values: kdc=1, master_kdc, kadmin, krb524, kpasswd
+
+from socket import getaddrinfo, SOCK_STREAM, SOCK_DGRAM, AF_INET, AF_INET6
+def locate1 (service, realm, socktype, family):
+   if (service == 1 or service == 2) and realm == "ATHENA.MIT.EDU":
+      if socktype == SOCK_STREAM: return []
+      socktype = SOCK_DGRAM
+      result = []
+      hlist = (("kerberos.mit.edu", 88), ("kerberos-1.mit.edu", 88),
+	       ("some-random-name-that-does-not-exist.mit.edu", 12345),
+	       ("kerberos.mit.edu", 750))
+      if service == 2: hlist = (hlist[0],)
+      for (hname,hport) in hlist:
+	 try:
+	    alist = getaddrinfo(hname, hport, family, socktype)
+	    for a in alist:
+	       (fam, stype, proto, canonname, sa) = a
+	       if fam == AF_INET or fam == AF_INET6:
+		  addr = sa[0]
+		  port = sa[1]
+		  result = result + [(addr, port, stype)]
+	 except Exception, inst:
+#           print "getaddrinfo error for " + hname + ":", inst
+	    pass  # Enh, this is just a demo.
+      return result
+   if realm == "BOBO.MIT.EDU": return []
+   return False
+
+verbose = 0
+servicenames = { 1: "kdc", 2: "master_kdc", 3: "kadmin", 4: "krb524", 5: "kpasswd" }
+socktypenames = { SOCK_STREAM: "STREAM", SOCK_DGRAM: "DGRAM" }
+familynames = { 0: "UNSPEC", AF_INET: "INET", AF_INET6: "INET6" }
+
+def locate (service, realm, socktype, family):
+   socktypename = socktype
+   if socktype in socktypenames: socktypename = "%s(%d)" % (socktypenames[socktype], socktype)
+   familyname = family
+   if family in familynames: familyname = "%s(%d)" % (familynames[family], family)
+   servicename = service
+   if service in servicenames: servicename = "%s(%d)" % (servicenames[service], service)
+   if verbose: print "locate called with service", servicename, "realm", realm, "socktype", socktypename, "family", familyname
+   result = locate1 (service, realm, socktype, family)
+   if verbose: print "locate result is", result
+   return result
diff --git a/krb5-1-6/src/plugins/locate/python/py-locate.c b/krb5-1-6/src/plugins/locate/python/py-locate.c
new file mode 100644
index 000000000..948e02818
--- /dev/null
+++ b/krb5-1-6/src/plugins/locate/python/py-locate.c
@@ -0,0 +1,313 @@
+/*
+ * plugins/locate/python/py-locate.c
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* This is a demo module.  The error checking is incomplete, there's
+   no exception handling, and it wouldn't surprise me in the least if
+   there are more bugs in the refcount maintenance.
+
+   But it will demonstrate (1) the plugin interface for locating a KDC
+   or other Kerberos-related service, and (2) that it's possible for
+   these plugins to call out to scripts in various languages for
+   prototyping or whatever.
+
+   Some notes:
+
+   If delayed initialization is not done, and the script is executed
+   when this module is loaded, loading other Python modules may not
+   work, if they include object code referencing the Python symbols.
+   Under glibc at least, it appears that the symbols of this module
+   aren't available to random dlopen/dlsym calls until loading
+   finishes, including the initialization routine.  It's completely
+   logical -- in fact, I'd be concerned if it were otherwise.  But not
+   obvious if you're not thinking about it.
+
+   This module seems rather sensitive to bugs in the Python code.  If
+   it's not correct, you may get core dumps, Python GC errors, etc.
+   Probably more signs of bugs in this code.
+
+   All of the -1 returns should be cleaned up and made to return
+   real error codes, with appropriate output if debugging is enabled.
+
+   Blah.  */
+
+/* Include Python.h before autoconf.h, because our autoconf.h seems
+   to confuse Python's headers.  */
+#if HAVE_PYTHON_H
+#include <Python.h>
+#elif HAVE_PYTHON2_3_PYTHON_H
+#include <python2.3/Python.h>
+#else
+#error "Where's the Python header file?"
+#endif
+#include <autoconf.h>
+#include <errno.h>
+#include "k5-platform.h"	/* for init/fini macros */
+#include "fake-addrinfo.h"
+
+#include <krb5/locate_plugin.h>
+
+#define LIBDIR			"/tmp" /* should be imported from configure */
+#define SCRIPT_PATH		LIBDIR "/krb5/locate-service.py"
+#define LOOKUP_FUNC_NAME	"locate"
+
+static PyObject *locatefn;
+
+MAKE_INIT_FUNCTION(my_init);
+MAKE_FINI_FUNCTION(my_fini);
+
+#define F	(strchr(__FILE__, '/') ? 1 + strrchr(__FILE__, '/') : __FILE__)
+
+static krb5_context sctx;	/* XXX ugly hack! */
+
+int
+my_init (void)
+{
+    PyObject *mainmodule;
+    FILE *f;
+
+    Py_Initialize ();
+//    fprintf(stderr, "trying to load %s\n", SCRIPT_PATH);
+    f = fopen(SCRIPT_PATH, "r");
+    if (f == NULL) {
+	if (sctx)
+	    krb5_set_error_message(sctx, -1,
+				   "couldn't open Python script %s (%s)",
+				   SCRIPT_PATH, strerror(errno));
+	return -1;
+    }
+    PyRun_SimpleFile (f, SCRIPT_PATH);
+    fclose(f);
+    mainmodule = PyModule_GetDict(PyImport_AddModule("__main__"));
+    if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; }
+    locatefn = PyDict_GetItemString (mainmodule, LOOKUP_FUNC_NAME);
+    if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; }
+    /* Don't DECREF mainmodule, it's sometimes causing crashes.  */
+    if (locatefn == 0)
+	return -1;
+    if (!PyCallable_Check (locatefn)) {
+	Py_DECREF (locatefn);
+	locatefn = 0;
+	return -1;
+    }
+    if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; }
+    return 0;
+}
+
+void
+my_fini (void)
+{
+//    fprintf(stderr, "%s:%d: Python module finalization\n", F, __LINE__);
+    if (! INITIALIZER_RAN (my_init))
+	return;
+    Py_DECREF (locatefn);
+    locatefn = 0;
+    Py_Finalize ();
+}
+
+static krb5_error_code
+ctxinit (krb5_context ctx, void **blobptr)
+{
+    /* If we wanted to create a separate Python interpreter instance,
+       look up the pathname of the script in the config file used for
+       the current krb5_context, and load the script in that
+       interpreter, this would be a good place for it; the blob could
+       be allocated to hold the reference to the interpreter
+       instance.  */
+    *blobptr = ctx;
+    return 0;
+}
+
+static void
+ctxfini (void *blob)
+{
+}
+
+/* Special return codes:
+
+   0: We set a (possibly empty) set of server locations in the result
+   field.  If the server location set is empty, that means there
+   aren't any servers, *not* that we should try the krb5.conf file or
+   DNS or something.
+
+   KRB5_PLUGIN_NO_HANDLE: This realm or service isn't handled here,
+   try some other means.
+
+   Other: Some error happened here.  It may be reported, if the
+   service can't be located by other means.  (In this implementation,
+   the catch-all error code returned in a bunch of places is -1, which
+   isn't going to be very useful to the caller.)  */
+
+static krb5_error_code
+lookup (void *blob, enum locate_service_type svc, const char *realm,
+	int socktype, int family,
+	int (*cbfunc)(void *, int, struct sockaddr *), void *cbdata)
+{
+    PyObject *py_result, *svcarg, *realmarg, *arglist;
+    int listsize, i, x;
+    struct addrinfo aihints, *airesult;
+    int thissocktype;
+
+//    fprintf(stderr, "%s:%d: lookup(%d,%s,%d,%d)\n", F, __LINE__,
+//	    svc, realm, socktype, family);
+    sctx = blob;		/* XXX: Not thread safe!  */
+    i = CALL_INIT_FUNCTION (my_init);
+    if (i) {
+#if 0
+	fprintf(stderr, "%s:%d: module initialization failed\n", F, __LINE__);
+#endif
+	return i;
+    }
+    if (locatefn == 0)
+	return KRB5_PLUGIN_NO_HANDLE;
+    svcarg = PyInt_FromLong (svc);
+    /* error? */
+    realmarg = PyString_FromString ((char *) realm);
+    /* error? */
+    arglist = PyTuple_New (4);
+    /* error? */
+
+    PyTuple_SetItem (arglist, 0, svcarg);
+    PyTuple_SetItem (arglist, 1, realmarg);
+    PyTuple_SetItem (arglist, 2, PyInt_FromLong (socktype));
+    PyTuple_SetItem (arglist, 3, PyInt_FromLong (family));
+    /* references handed off, no decref */
+
+    py_result = PyObject_CallObject (locatefn, arglist);
+    Py_DECREF (arglist);
+    if (PyErr_Occurred()) {
+	fprintf(stderr,"%s:%d: python error\n", F, __LINE__);
+	PyErr_Print();
+	krb5_set_error_message(blob, -1,
+			       "Python evaluation error, see stderr");
+	return -1;
+    }
+    if (py_result == 0) {
+	fprintf(stderr, "%s:%d: returned null object\n", F, __LINE__);
+	return -1;
+    }
+    if (py_result == Py_False)
+	return KRB5_PLUGIN_NO_HANDLE;
+    if (! PyList_Check (py_result)) {
+	Py_DECREF (py_result);
+	fprintf(stderr, "%s:%d: returned non-list, non-False\n", F, __LINE__);
+	krb5_set_error_message(blob, -1,
+			       "Python script error -- returned non-list, non-False result");
+	return -1;
+    }
+    listsize = PyList_Size (py_result);
+    /* allocate */
+    memset(&aihints, 0, sizeof(aihints));
+    aihints.ai_flags = AI_NUMERICHOST;
+    aihints.ai_family = family;
+    for (i = 0; i < listsize; i++) {
+	PyObject *answer, *field;
+	char *hoststr, *portstr, portbuf[3*sizeof(long) + 4];
+	int cbret;
+
+	answer = PyList_GetItem (py_result, i);
+	if (! PyTuple_Check (answer)) {
+	    krb5_set_error_message(blob, -1,
+				   "Python script error -- returned item %d not a tuple", i);
+	    /* leak?  */
+	    return -1;
+	}
+	if (PyTuple_Size (answer) != 3) {
+	    krb5_set_error_message(blob, -1,
+				   "Python script error -- returned tuple %d size %d should be 3",
+				   i, PyTuple_Size (answer));
+	    /* leak?  */
+	    return -1;
+	}
+	field = PyTuple_GetItem (answer, 0);
+	if (! PyString_Check (field)) {
+	    /* leak?  */
+	    krb5_set_error_message(blob, -1,
+				   "Python script error -- first component of tuple %d is not a string",
+				   i);
+	    return -1;
+	}
+	hoststr = PyString_AsString (field);
+	field = PyTuple_GetItem (answer, 1);
+	if (PyString_Check (field)) {
+	    portstr = PyString_AsString (field);
+	} else if (PyInt_Check (field)) {
+	    sprintf(portbuf, "%ld", PyInt_AsLong (field));
+	    portstr = portbuf;
+	} else {
+	    krb5_set_error_message(blob, -1,
+				   "Python script error -- second component of tuple %d neither a string nor an integer",
+				   i);
+	    /* leak?  */
+	    return -1;
+	}
+	field = PyTuple_GetItem (answer, 2);
+	if (! PyInt_Check (field)) {
+	    krb5_set_error_message(blob, -1,
+				   "Python script error -- third component of tuple %d not an integer",
+				   i);
+	    /* leak?  */
+	    return -1;
+	}
+	thissocktype = PyInt_AsLong (field);
+	switch (thissocktype) {
+	case SOCK_STREAM:
+	case SOCK_DGRAM:
+	    /* okay */
+	    if (socktype != 0 && socktype != thissocktype) {
+		krb5_set_error_message(blob, -1,
+				       "Python script error -- tuple %d has socket type %d, should only have %d",
+				       i, thissocktype, socktype);
+		/* leak?  */
+		return -1;
+	    }
+	    break;
+	default:
+	    /* 0 is not acceptable */
+	    krb5_set_error_message(blob, -1,
+				   "Python script error -- tuple %d has invalid socket type %d",
+				   i, thissocktype);
+	    /* leak?  */
+	    return -1;
+	}
+	aihints.ai_socktype = thissocktype;
+	x = getaddrinfo (hoststr, portstr, &aihints, &airesult);
+	if (x != 0)
+	    continue;
+	cbret = cbfunc(cbdata, airesult->ai_socktype, airesult->ai_addr);
+	freeaddrinfo(airesult);
+	if (cbret != 0)
+	    break;
+    }
+    Py_DECREF (py_result);
+    return 0;
+}
+
+const krb5plugin_service_locate_ftable service_locator = {
+    /* version */
+    0,
+    /* functions */
+    ctxinit, ctxfini, lookup,
+};
diff --git a/krb5-1-6/src/plugins/locate/python/python.exports b/krb5-1-6/src/plugins/locate/python/python.exports
new file mode 100644
index 000000000..60ff46e8d
--- /dev/null
+++ b/krb5-1-6/src/plugins/locate/python/python.exports
@@ -0,0 +1 @@
+service_locator
diff --git a/krb5-1-6/src/plugins/preauth/cksum_body/Makefile.in b/krb5-1-6/src/plugins/preauth/cksum_body/Makefile.in
new file mode 100644
index 000000000..83d7cdb5b
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/cksum_body/Makefile.in
@@ -0,0 +1,42 @@
+thisconfigdir=.
+myfulldir=plugins/preauth/cksum_body
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
+DEFS=@DEFS@
+
+LOCALINCLUDES = -I../../../include/krb5 -I.
+
+LIBBASE=cksum_body
+LIBMAJOR=0
+LIBMINOR=0
+SO_EXT=.so
+RELDIR=../plugins/preauth/cksum_body
+# Depends on libk5crypto and libkrb5
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS= -lkrb5 -lcom_err -lk5crypto $(SUPPORT_LIB) $(LIBS)
+
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+STOBJLISTS=OBJS.ST
+STLIBOBJS=cksum_body_main.o
+
+SRCS= $(srcdir)/cksum_body_main.c
+
+all-unix:: $(LIBBASE)$(SO_EXT)
+install-unix:: install-libs
+clean-unix:: clean-libs clean-libobjs
+
+clean::
+	$(RM) lib$(LIBBASE)$(SO_EXT)
+
+@libnover_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
diff --git a/krb5-1-6/src/plugins/preauth/cksum_body/cksum_body.exports b/krb5-1-6/src/plugins/preauth/cksum_body/cksum_body.exports
new file mode 100644
index 000000000..32e067ba9
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/cksum_body/cksum_body.exports
@@ -0,0 +1,2 @@
+preauthentication_client_0
+preauthentication_server_0
diff --git a/krb5-1-6/src/plugins/preauth/cksum_body/cksum_body_main.c b/krb5-1-6/src/plugins/preauth/cksum_body/cksum_body_main.c
new file mode 100644
index 000000000..4eb4aed39
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/cksum_body/cksum_body_main.c
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) 2006 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Red Hat, Inc., nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Checksum the request body with the user's long-term key.
+ *
+ * The e-data from the KDC is a list of network-byte-order 32-bit integers
+ * listing key types which the KDC has for the user.
+ *
+ * The client uses one of these key types to generate a checksum over the body
+ * of the request, and includes the checksum in the AS-REQ as preauthentication
+ * data.
+ *
+ * The AS-REP carries no preauthentication data for this scheme.
+ */
+
+#ident "$Id: cksum_body_main.c,v 1.4 2007/01/02 22:33:50 kwc Exp $"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <arpa/inet.h>
+#include <stdio.h>
+
+#include <krb5/krb5.h>
+#include <krb5/preauth_plugin.h>
+
+/* This is not a standardized value.  It's defined here only to make it easier
+ * to change in this module. */
+#define KRB5_PADATA_CKSUM_BODY_REQ 130
+
+struct server_stats{
+    int successes, failures;
+};
+
+typedef struct _test_svr_req_ctx {
+    int value1;
+    int value2;
+} test_svr_req_ctx;
+
+static int
+client_get_flags(krb5_context kcontext, krb5_preauthtype pa_type)
+{
+    return PA_REAL;
+}
+
+static krb5_error_code
+client_process(krb5_context kcontext,
+	       void *client_plugin_context,
+	       void *client_request_context,
+	       krb5_get_init_creds_opt *opt,
+	       preauth_get_client_data_proc client_get_data_proc,
+	       struct _krb5_preauth_client_rock *rock,
+	       krb5_kdc_req *request,
+	       krb5_data *encoded_request_body,
+	       krb5_data *encoded_previous_request,
+	       krb5_pa_data *pa_data,
+	       krb5_prompter_fct prompter,
+	       void *prompter_data,
+	       preauth_get_as_key_proc gak_fct,
+	       void *gak_data,
+	       krb5_data *salt, krb5_data *s2kparams,
+	       krb5_keyblock *as_key,
+	       krb5_pa_data ***out_pa_data)
+{
+    krb5_pa_data **send_pa;
+    krb5_checksum checksum;
+    krb5_enctype enctype;
+    krb5_cksumtype *cksumtypes;
+    krb5_error_code status = 0;
+    krb5_int32 cksumtype, *enctypes;
+    unsigned int i, n_enctypes, cksumtype_count;
+    int num_gic_info = 0;
+    krb5_gic_opt_pa_data *gic_info;
+
+    status = krb5_get_init_creds_opt_get_pa(kcontext, opt,
+					    &num_gic_info, &gic_info);
+    if (status && status != ENOENT) {
+#ifdef DEBUG
+	fprintf(stderr, "Error from krb5_get_init_creds_opt_get_pa: %s\n",
+		error_message(status));
+#endif
+	return status;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "(cksum_body) Got the following gic options:\n");
+#endif
+    for (i = 0; i < num_gic_info; i++) {
+#ifdef DEBUG
+	fprintf(stderr, "  '%s' = '%s'\n", gic_info[i].attr, gic_info[i].value);
+#endif
+    }
+    krb5_get_init_creds_opt_free_pa(kcontext, num_gic_info, gic_info);
+
+    memset(&checksum, 0, sizeof(checksum));
+
+    /* Get the user's long-term key if we haven't asked for it yet.  Try
+     * all of the encryption types which the server supports. */
+    if (as_key->length == 0) {
+	if ((pa_data != NULL) && (pa_data->length >= 4)) {
+#ifdef DEBUG
+	    fprintf(stderr, "%d bytes of preauth data.\n", pa_data->length);
+#endif
+	    n_enctypes = pa_data->length / 4;
+	    enctypes = (krb5_int32*) pa_data->contents;
+	} else {
+	    n_enctypes = request->nktypes;
+	}
+	for (i = 0; i < n_enctypes; i++) {
+	    if ((pa_data != NULL) && (pa_data->length >= 4)) {
+		memcpy(&enctype, pa_data->contents + 4 * i, 4);
+		enctype = ntohl(enctype);
+	    } else {
+		enctype = request->ktype[i];
+	    }
+#ifdef DEBUG
+	    fprintf(stderr, "Asking for AS key (type = %d).\n", enctype);
+#endif
+	    status = (*gak_fct)(kcontext, request->client, enctype,
+				prompter, prompter_data,
+				salt, s2kparams, as_key, gak_data);
+	    if (status == 0)
+		break;
+	}
+	if (status != 0)
+	    return status;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "Got AS key (type = %d).\n", as_key->enctype);
+#endif
+
+    /* Determine an appropriate checksum type for this key. */
+    cksumtype_count = 0;
+    cksumtypes = NULL;
+    status = krb5_c_keyed_checksum_types(kcontext, as_key->enctype,
+					 &cksumtype_count, &cksumtypes);
+    if (status != 0)
+	return status;
+
+    /* Generate the checksum. */
+    for (i = 0; i < cksumtype_count; i++) {
+	status = krb5_c_make_checksum(kcontext, cksumtypes[i], as_key,
+				      KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+				      encoded_request_body,
+				      &checksum);
+	if (status == 0) {
+#ifdef DEBUG
+	    fprintf(stderr, "Made checksum (type = %d, %d bytes).\n",
+		    checksum.checksum_type, encoded_request_body->length);
+#endif
+	    break;
+	}
+    }
+    cksumtype = htonl(cksumtypes[i]);
+    krb5_free_cksumtypes(kcontext, cksumtypes);
+    if (status != 0) {
+	if (checksum.length > 0)
+	    krb5_free_checksum_contents(kcontext, &checksum);
+	return status;
+    }
+
+    /* Allocate the preauth data structure. */
+    send_pa = malloc(2 * sizeof(krb5_pa_data *));
+    if (send_pa == NULL) {
+	krb5_free_checksum_contents(kcontext, &checksum);
+	return ENOMEM;
+    }
+    send_pa[1] = NULL;	/* Terminate list */
+    send_pa[0] = malloc(sizeof(krb5_pa_data));
+    if (send_pa[0] == NULL) {
+	krb5_free_checksum_contents(kcontext, &checksum);
+	free(send_pa);
+	return ENOMEM;
+    }
+    send_pa[0]->pa_type = KRB5_PADATA_CKSUM_BODY_REQ;
+    send_pa[0]->length = 4 + checksum.length;
+    send_pa[0]->contents = malloc(4 + checksum.length);
+    if (send_pa[0]->contents == NULL) {
+	krb5_free_checksum_contents(kcontext, &checksum);
+	free(send_pa[0]);
+	free(send_pa);
+	return ENOMEM;
+    }
+
+    /* Store the checksum. */
+    memcpy(send_pa[0]->contents, &cksumtype, 4);
+    memcpy(send_pa[0]->contents + 4, checksum.contents, checksum.length);
+    *out_pa_data = send_pa;
+
+    /* Clean up. */
+    krb5_free_checksum_contents(kcontext, &checksum);
+
+    return 0;
+}
+
+static krb5_error_code
+client_gic_opt(krb5_context kcontext,
+	       void *plugin_context,
+	       krb5_get_init_creds_opt *opt,
+	       const char *attr,
+	       const char *value)
+{
+#ifdef DEBUG
+    fprintf(stderr, "(cksum_body) client_gic_opt: received '%s' = '%s'\n",
+	    attr, value); 
+#endif
+    return 0;
+}
+
+/* Initialize and tear down the server-side module, and do stat tracking. */
+static krb5_error_code
+server_init(krb5_context kcontext, void **module_context, const char **realmnames)
+{
+    struct server_stats *stats;
+    stats = malloc(sizeof(struct server_stats));
+    if (stats == NULL)
+	return ENOMEM;
+    stats->successes = 0;
+    stats->failures = 0;
+    *module_context = stats;
+    return 0;
+}
+static void
+server_fini(krb5_context kcontext, void *module_context)
+{
+    struct server_stats *stats;
+    stats = module_context;
+    if (stats != NULL) {
+#ifdef DEBUG
+	fprintf(stderr, "Total: %d clients failed, %d succeeded.\n",
+		stats->failures, stats->successes);
+#endif
+	free(stats);
+    }
+}
+
+/* Obtain and return any preauthentication data (which is destined for the
+ * client) which matches type data->pa_type. */
+static krb5_error_code
+server_get_edata(krb5_context kcontext,
+		 krb5_kdc_req *request,
+		 struct _krb5_db_entry_new *client,
+		 struct _krb5_db_entry_new *server,
+		 preauth_get_entry_data_proc server_get_entry_data,
+		 void *pa_module_context,
+		 krb5_pa_data *data)
+{
+    krb5_data *key_data;
+    krb5_keyblock *keys, *key;
+    krb5_int32 *enctypes, enctype;
+    int i;
+
+    /* Retrieve the client's keys. */
+    key_data = NULL;
+    if ((*server_get_entry_data)(kcontext, request, client,
+				 krb5plugin_preauth_keys, &key_data) != 0) {
+#ifdef DEBUG
+	fprintf(stderr, "Error retrieving client keys.\n");
+#endif
+	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
+    }
+
+    /* Count which types of keys we've got, freeing the contents, which we
+     * don't need at this point. */
+    keys = (krb5_keyblock *) key_data->data;
+    key = NULL;
+    for (i = 0; keys[i].enctype != 0; i++)
+	krb5_free_keyblock_contents(kcontext, &keys[i]);
+
+    /* Return the list of encryption types. */
+    enctypes = malloc((unsigned)i * 4);
+    if (enctypes == NULL) {
+	krb5_free_data(kcontext, key_data);
+	return ENOMEM;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "Supported enctypes = {");
+#endif
+    for (i = 0; keys[i].enctype != 0; i++) {
+#ifdef DEBUG
+	fprintf(stderr, "%s%d", (i > 0) ? ", " : "", keys[i].enctype);
+#endif
+	enctype = htonl(keys[i].enctype);
+	memcpy(&enctypes[i], &enctype, 4);
+    }
+#ifdef DEBUG
+    fprintf(stderr, "}.\n");
+#endif
+    data->pa_type = KRB5_PADATA_CKSUM_BODY_REQ;
+    data->length = (i * 4);
+    data->contents = (unsigned char *) enctypes;
+    krb5_free_data(kcontext, key_data);
+    return 0;
+}
+
+/* Verify a request from a client. */
+static krb5_error_code
+server_verify(krb5_context kcontext,
+	      struct _krb5_db_entry_new *client,
+	      krb5_data *req_pkt,
+	      krb5_kdc_req *request,
+	      krb5_enc_tkt_part *enc_tkt_reply,
+	      krb5_pa_data *data,
+	      preauth_get_entry_data_proc server_get_entry_data,
+	      void *pa_module_context,
+	      void **pa_request_context,
+	      krb5_data **e_data,
+	      krb5_authdata ***authz_data)
+{
+    krb5_int32 cksumtype;
+    krb5_checksum checksum;
+    krb5_boolean valid;
+    krb5_data *key_data, *req_body;
+    krb5_keyblock *keys, *key;
+    size_t length;
+    int i;
+    unsigned int j, cksumtypes_count;
+    krb5_cksumtype *cksumtypes;
+    krb5_error_code status;
+    struct server_stats *stats;
+    krb5_data *test_edata;
+    test_svr_req_ctx *svr_req_ctx;
+    krb5_authdata **my_authz_data = NULL;
+
+    stats = pa_module_context;
+
+#ifdef DEBUG
+    fprintf(stderr, "cksum_body: server_verify\n");
+#endif
+    /* Verify the preauth data.  Start with the checksum type. */
+    if (data->length < 4) {
+	stats->failures++;
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    memcpy(&cksumtype, data->contents, 4);
+    memset(&checksum, 0, sizeof(checksum));
+    checksum.checksum_type = ntohl(cksumtype);
+
+    /* Verify that the amount of data we have left is what we expect. */
+    if (krb5_c_checksum_length(kcontext, checksum.checksum_type,
+			       &length) != 0) {
+#ifdef DEBUG
+	fprintf(stderr, "Error determining checksum size (type = %d). "
+		"Is it supported?\n", checksum.checksum_type);
+#endif
+	stats->failures++;
+	return KRB5KDC_ERR_SUMTYPE_NOSUPP;
+    }
+    if (data->length - 4 != length) {
+#ifdef DEBUG
+	fprintf(stderr, "Checksum size doesn't match client packet size.\n");
+#endif
+	stats->failures++;
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    checksum.length = length;
+
+    /* Pull up the client's keys. */
+    key_data = NULL;
+    if ((*server_get_entry_data)(kcontext, request, client,
+				 krb5plugin_preauth_keys, &key_data) != 0) {
+#ifdef DEBUG
+	fprintf(stderr, "Error retrieving client keys.\n");
+#endif
+	stats->failures++;
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    /* Find the key which would have been used to generate the checksum. */
+    keys = (krb5_keyblock *) key_data->data;
+    key = NULL;
+    for (i = 0; keys[i].enctype != 0; i++) {
+	key = &keys[i];
+	cksumtypes_count = 0;
+	cksumtypes = NULL;
+	if (krb5_c_keyed_checksum_types(kcontext, key->enctype,
+					&cksumtypes_count, &cksumtypes) != 0)
+	    continue;
+	for (j = 0; j < cksumtypes_count; j++) {
+	    if (cksumtypes[j] == checksum.checksum_type)
+		break;
+	}
+	if (cksumtypes != NULL)
+	    krb5_free_cksumtypes(kcontext, cksumtypes);
+	if (j < cksumtypes_count) {
+#ifdef DEBUG
+	    fprintf(stderr, "Found checksum key.\n");
+#endif
+	    break;
+	}
+    }
+    if ((key == NULL) || (key->enctype == 0)) {
+	for (i = 0; keys[i].enctype != 0; i++)
+	    krb5_free_keyblock_contents(kcontext, &keys[i]);
+	krb5_free_data(kcontext, key_data);
+	stats->failures++;
+	return KRB5KDC_ERR_SUMTYPE_NOSUPP;
+    }
+
+    /* Save a copy of the key. */
+    if (krb5_copy_keyblock(kcontext, &keys[i], &key) != 0) {
+	for (i = 0; keys[i].enctype != 0; i++)
+	    krb5_free_keyblock_contents(kcontext, &keys[i]);
+	krb5_free_data(kcontext, key_data);
+	stats->failures++;
+	return KRB5KDC_ERR_SUMTYPE_NOSUPP;
+    }
+    for (i = 0; keys[i].enctype != 0; i++)
+	krb5_free_keyblock_contents(kcontext, &keys[i]);
+    krb5_free_data(kcontext, key_data);
+
+    /* Rebuild a copy of the client's request-body.  If we were serious
+     * about doing this with any chance of working interoperability, we'd
+     * extract the structure directly from the req_pkt structure.  This
+     * will probably work if it's us on both ends, though. */
+    req_body = NULL;
+    if ((*server_get_entry_data)(kcontext, request, client,
+				 krb5plugin_preauth_request_body,
+				 &req_body) != 0) {
+	krb5_free_keyblock(kcontext, key);
+	stats->failures++;
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, "AS key type %d, checksum type %d, %d bytes.\n",
+	    key->enctype, checksum.checksum_type, req_body->length);
+#endif
+
+    /* Verify the checksum itself. */
+    checksum.contents = data->contents + 4;
+    valid = FALSE;
+    status = krb5_c_verify_checksum(kcontext, key,
+				    KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+				    req_body, &checksum, &valid);
+
+    /* Clean up. */
+    krb5_free_data(kcontext, req_body);
+    krb5_free_keyblock(kcontext, key);
+
+    /* Evaluate our results. */
+    if ((status != 0) || (!valid)) {
+#ifdef DEBUG
+	if (status != 0) {
+	    fprintf(stderr, "Error in checksum verification.\n");
+	} else {
+	    fprintf(stderr, "Checksum mismatch.\n");
+	}
+#endif
+	/* Return edata to exercise code that handles edata... */
+	test_edata = malloc(sizeof(*test_edata));
+	if (test_edata != NULL) {
+	    test_edata->data = malloc(20);
+	    if (test_edata->data == NULL) {
+		free(test_edata);
+	    } else {
+		test_edata->length = 20;
+		memset(test_edata->data, 'F', 20); /* fill it with junk */
+		*e_data = test_edata;
+	    }
+	}
+	stats->failures++;
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    /*
+     * Return some junk authorization data just to exercise the
+     * code path handling the returned authorization data.
+     *
+     * NOTE that this is NOT VALID authorization data!
+     */
+#ifdef DEBUG
+    fprintf(stderr, "cksum_body: doing authorization data!\n");
+#endif
+#if 1 /* USE_5000_AD */
+#define AD_ALLOC_SIZE 5000
+    /* ad_header consists of a sequence tag (0x30) and length (0x82 0x1384)
+     * followed by octet string tag (0x04) and length (0x82 0x1380) */
+    krb5_octet ad_header[] = {0x30, 0x82, 0x13, 0x84, 0x04, 0x82, 0x13, 0x80};
+#else
+#define AD_ALLOC_SIZE 100
+    /* ad_header consists of a sequence tag (0x30) and length (0x62)
+     * followed by octet string tag (0x04) and length (0x60) */
+    krb5_octet ad_header[] = {0x30, 0x62, 0x04, 0x60};
+#endif
+    my_authz_data = malloc(2 * sizeof(*my_authz_data));
+    if (my_authz_data != NULL) {
+	my_authz_data[1] = NULL;
+	my_authz_data[0] = malloc(sizeof(krb5_authdata));
+	if (my_authz_data[0] == NULL) {
+	    free(my_authz_data);
+	    return ENOMEM;
+	}
+	my_authz_data[0]->contents = malloc(AD_ALLOC_SIZE);
+	if (my_authz_data[0]->contents == NULL) {
+	    free(my_authz_data[0]);
+	    free(my_authz_data);
+	    return ENOMEM;
+	}
+	memset(my_authz_data[0]->contents, '\0', AD_ALLOC_SIZE);
+	my_authz_data[0]->magic = KV5M_AUTHDATA;
+	my_authz_data[0]->ad_type = 1;
+	my_authz_data[0]->length = AD_ALLOC_SIZE;
+	memcpy(my_authz_data[0]->contents, ad_header, sizeof(ad_header));
+	sprintf(my_authz_data[0]->contents + sizeof(ad_header),
+	       "cksum authorization data: %d bytes worth!\n", AD_ALLOC_SIZE);
+	*authz_data = my_authz_data;
+#ifdef DEBUG
+	fprintf(stderr, "Returning %d bytes of authorization data\n",
+		AD_ALLOC_SIZE);
+#endif
+    }
+
+    /* Return edata to exercise code that handles edata... */
+    test_edata = malloc(sizeof(*test_edata));
+    if (test_edata != NULL) {
+	test_edata->data = malloc(20);
+	if (test_edata->data == NULL) {
+	    free(test_edata);
+	} else {
+	    test_edata->length = 20;
+	    memset(test_edata->data, 'S', 20); /* fill it with junk */
+	    *e_data = test_edata;
+	}
+    }
+
+    /* Return a request context to exercise code that handles it */
+    svr_req_ctx = malloc(sizeof(*svr_req_ctx));
+    if (svr_req_ctx != NULL) {
+	svr_req_ctx->value1 = 111111;
+	svr_req_ctx->value2 = 222222;
+#ifdef DEBUG
+	fprintf(stderr, "server_verify: returning context at %p\n",
+		svr_req_ctx);
+#endif
+    }
+    *pa_request_context = svr_req_ctx;
+
+    /* Note that preauthentication succeeded. */
+    enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
+    stats->successes++;
+    return 0;
+}
+
+/* Create the response for a client. */
+static krb5_error_code
+server_return(krb5_context kcontext,
+	      krb5_pa_data *padata,
+	      struct _krb5_db_entry_new *client,
+	      krb5_data *req_pkt,
+	      krb5_kdc_req *request,
+	      krb5_kdc_rep *reply,
+	      struct _krb5_key_data *client_key,
+	      krb5_keyblock *encrypting_key,
+	      krb5_pa_data **send_pa,
+	      preauth_get_entry_data_proc server_get_entry_data,
+	      void *pa_module_context,
+	      void **pa_request_context)
+{
+    /* We don't need to send data back on the return trip. */
+    *send_pa = NULL;
+    return 0;
+}
+
+/* Test server request context freeing */
+static krb5_error_code
+server_free_reqctx(krb5_context kcontext,
+		   void *pa_module_context,
+		   void **pa_request_context)
+{
+    test_svr_req_ctx *svr_req_ctx;
+#ifdef DEBUG
+    fprintf(stderr, "server_free_reqctx: entered!\n");
+#endif
+    if (pa_request_context == NULL)
+	return 0;
+
+    svr_req_ctx = *pa_request_context;
+    if (svr_req_ctx == NULL)
+	return 0;
+
+    if (svr_req_ctx->value1 != 111111 || svr_req_ctx->value2 != 222222) {
+	fprintf(stderr, "server_free_reqctx: got invalid req context "
+		"at %p with values %d and %d\n",
+		svr_req_ctx, svr_req_ctx->value1, svr_req_ctx->value2);
+	return EINVAL;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "server_free_reqctx: freeing context at %p\n", svr_req_ctx);
+#endif
+    free(svr_req_ctx);
+    *pa_request_context = NULL;
+    return 0;
+}
+
+static int
+server_get_flags(krb5_context kcontext, krb5_preauthtype pa_type)
+{
+    return PA_SUFFICIENT;
+}
+
+static krb5_preauthtype supported_client_pa_types[] = {
+    KRB5_PADATA_CKSUM_BODY_REQ, 0,
+};
+static krb5_preauthtype supported_server_pa_types[] = {
+    KRB5_PADATA_CKSUM_BODY_REQ, 0,
+};
+
+struct krb5plugin_preauth_client_ftable_v1 preauthentication_client_1 = {
+    "cksum_body",			    /* name */
+    &supported_client_pa_types[0],	    /* pa_type_list */
+    NULL,				    /* enctype_list */
+    NULL,				    /* plugin init function */
+    NULL,				    /* plugin fini function */
+    client_get_flags,			    /* get flags function */
+    NULL,				    /* request init function */
+    NULL,				    /* request fini function */
+    client_process,			    /* process function */
+    NULL,				    /* try_again function */
+    client_gic_opt			    /* get init creds opt function */
+};
+
+struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = {
+    "cksum_body",
+    &supported_server_pa_types[0],
+    server_init,
+    server_fini,
+    server_get_flags,
+    server_get_edata,
+    server_verify,
+    server_return,
+    server_free_reqctx
+};
diff --git a/krb5-1-6/src/plugins/preauth/cksum_body/configure.in b/krb5-1-6/src/plugins/preauth/cksum_body/configure.in
new file mode 100644
index 000000000..868dfd594
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/cksum_body/configure.in
@@ -0,0 +1,14 @@
+K5_AC_INIT(configure.in)
+enable_shared=yes
+build_dynobj=yes
+CONFIG_RULES
+
+AC_CHECK_HEADERS(errno.h string.h)
+
+KRB5_RUN_FLAGS
+dnl The following is for check...
+KRB5_BUILD_PROGRAM
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+AC_CONFIG_HEADERS(config.h)
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/Makefile.in b/krb5-1-6/src/plugins/preauth/pkinit/Makefile.in
new file mode 100644
index 000000000..ffc005901
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/Makefile.in
@@ -0,0 +1,109 @@
+thisconfigdir=.
+myfulldir=plugins/preauth/pkinit
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
+DEFS=@DEFS@
+
+LOCALINCLUDES = -I../../../include/krb5 -I.
+
+LIBBASE=pkinit
+LIBMAJOR=0
+LIBMINOR=0
+SO_EXT=.so
+RELDIR=../plugins/preauth/pkinit
+# Depends on libk5crypto and libkrb5
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+LIBS+= -lcrypto
+SHLIB_EXPLIBS= -lkrb5 -lcom_err -lk5crypto -ldl $(SUPPORT_LIB) $(LIBS)
+
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+STOBJLISTS=OBJS.ST
+STLIBOBJS= \
+	pkinit_accessor.o \
+	pkinit_srv.o \
+	pkinit_lib.o \
+	pkinit_clnt.o \
+	pkinit_profile.o \
+	pkinit_identity.o \
+	pkinit_matching.o \
+	pkinit_crypto_openssl.o
+
+SRCS= \
+	$(srcdir)/pkinit_accessor.c \
+	$(srcdir)/pkinit_srv.c \
+	$(srcdir)/pkinit_lib.c \
+	$(srcdir)/pkinit_clnt.c \
+	$(srcdir)/pkinit_profile.c \
+	$(srcdir)/pkinit_identity.c \
+	$(srcdir)/pkinit_matching.c \
+	$(srcdir)/pkinit_crypto_openssl.c
+
+all-unix:: $(LIBBASE)$(SO_EXT)
+install-unix:: install-libs
+clean-unix:: clean-libs clean-libobjs
+
+clean::
+	$(RM) lib$(LIBBASE)$(SO_EXT)
+
+@libnover_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+pkinit_accessor.so pkinit_accessor.po $(OUTPRE)pkinit_accessor.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h pkinit_accessor.c \
+  pkinit_accessor.h
+pkinit_srv.so pkinit_srv.po $(OUTPRE)pkinit_srv.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_srv.c
+pkinit_lib.so pkinit_lib.po $(OUTPRE)pkinit_lib.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_lib.c
+pkinit_clnt.so pkinit_clnt.po $(OUTPRE)pkinit_clnt.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  pkinit.h pkinit_accessor.h pkinit_clnt.c pkinit_crypto.h
+pkinit_profile.so pkinit_profile.po $(OUTPRE)pkinit_profile.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int-pkinit.h \
+  $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h pkinit.h pkinit_accessor.h \
+  pkinit_crypto.h pkinit_profile.c
+pkinit_identity.so pkinit_identity.po $(OUTPRE)pkinit_identity.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_identity.c
+pkinit_matching.so pkinit_matching.po $(OUTPRE)pkinit_matching.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h pkinit.h pkinit_accessor.h \
+  pkinit_crypto.h pkinit_matching.c
+pkinit_crypto_openssl.so pkinit_crypto_openssl.po $(OUTPRE)pkinit_crypto_openssl.$(OBJEXT): \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_crypto_openssl.c \
+  pkinit_crypto_openssl.h
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/configure.in b/krb5-1-6/src/plugins/preauth/pkinit/configure.in
new file mode 100644
index 000000000..59ece38c2
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/configure.in
@@ -0,0 +1,19 @@
+K5_AC_INIT(configure.in)
+enable_shared=yes
+build_dynobj=yes
+CONFIG_RULES
+AC_CHECK_HEADERS(unistd.h)
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+
+AC_CHECK_FUNCS()
+
+# XXX This is incorrect, but should cause -lcrypto to be included by default
+AC_CHECK_LIB(crypto, PKCS7_get_signer_info)
+
+KRB5_RUN_FLAGS
+dnl The following is for check...
+KRB5_BUILD_PROGRAM
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkcs11.h b/krb5-1-6/src/plugins/preauth/pkinit/pkcs11.h
new file mode 100644
index 000000000..7d18f2318
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkcs11.h
@@ -0,0 +1,1357 @@
+/* pkcs11.h
+   Copyright 2006 g10 Code GmbH
+   Copyright 2006 Andreas Jellinghaus
+
+   This file is free software; as a special exception the author gives
+   unlimited permission to copy and/or distribute it, with or without
+   modifications, as long as this notice is preserved.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+   PURPOSE.  */
+
+/* Please submit changes back to the Scute project at
+   http://www.scute.org/ (or send them to marcus@g10code.com), so that
+   they can be picked up by other projects from there as well.  */
+
+/* This file is a modified implementation of the PKCS #11 standard by
+   RSA Security Inc.  It is mostly a drop-in replacement, with the
+   following change:
+
+   This header file does not require any macro definitions by the user
+   (like CK_DEFINE_FUNCTION etc).  In fact, it defines those macros
+   for you (if useful, some are missing, let me know if you need
+   more).
+
+   There is an additional API available that does comply better to the
+   GNU coding standard.  It can be switched on by defining
+   CRYPTOKI_GNU before including this header file.  For this, the
+   following changes are made to the specification:
+
+   All structure types are changed to a "struct ck_foo" where CK_FOO
+   is the type name in PKCS #11.
+
+   All non-structure types are changed to ck_foo_t where CK_FOO is the
+   lowercase version of the type name in PKCS #11.  The basic types
+   (CK_ULONG et al.) are removed without substitute.
+
+   All members of structures are modified in the following way: Type
+   indication prefixes are removed, and underscore characters are
+   inserted before words.  Then the result is lowercased.
+
+   Note that function names are still in the original case, as they
+   need for ABI compatibility.
+
+   CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute.  Use
+   <stdbool.h>.
+
+   If CRYPTOKI_COMPAT is defined before including this header file,
+   then none of the API changes above take place, and the API is the
+   one defined by the PKCS #11 standard.  */
+
+#ifndef PKCS11_H
+#define PKCS11_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The version of cryptoki we implement.  The revision is changed with
+   each modification of this file.  If you do not use the "official"
+   version of this file, please consider deleting the revision macro
+   (you may use a macro with a different name to keep track of your
+   versions).  */
+#define CRYPTOKI_VERSION_MAJOR		2
+#define CRYPTOKI_VERSION_MINOR		20
+#define CRYPTOKI_VERSION_REVISION	6
+
+
+/* Compatibility interface is default, unless CRYPTOKI_GNU is
+   given.  */
+#ifndef CRYPTOKI_GNU
+#ifndef CRYPTOKI_COMPAT
+#define CRYPTOKI_COMPAT 1
+#endif
+#endif
+
+/* System dependencies.  */
+
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+
+/* There is a matching pop below.  */
+#pragma pack(push, cryptoki, 1)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_SPEC __declspec(dllexport)
+#else
+#define CK_SPEC __declspec(dllimport)
+#endif
+
+#else
+
+#define CK_SPEC
+
+#endif
+
+
+#ifdef CRYPTOKI_COMPAT
+  /* If we are in compatibility mode, switch all exposed names to the
+     PKCS #11 variant.  There are corresponding #undefs below.  */
+
+#define ck_flags_t CK_FLAGS
+#define ck_version _CK_VERSION
+
+#define ck_info _CK_INFO
+#define cryptoki_version cryptokiVersion
+#define manufacturer_id manufacturerID
+#define library_description libraryDescription
+#define library_version libraryVersion
+
+#define ck_notification_t CK_NOTIFICATION
+#define ck_slot_id_t CK_SLOT_ID
+
+#define ck_slot_info _CK_SLOT_INFO
+#define slot_description slotDescription
+#define hardware_version hardwareVersion
+#define firmware_version firmwareVersion
+
+#define ck_token_info _CK_TOKEN_INFO
+#define serial_number serialNumber
+#define max_session_count ulMaxSessionCount
+#define session_count ulSessionCount
+#define max_rw_session_count ulMaxRwSessionCount
+#define rw_session_count ulRwSessionCount
+#define max_pin_len ulMaxPinLen
+#define min_pin_len ulMinPinLen
+#define total_public_memory ulTotalPublicMemory
+#define free_public_memory ulFreePublicMemory
+#define total_private_memory ulTotalPrivateMemory
+#define free_private_memory ulFreePrivateMemory
+#define utc_time utcTime
+
+#define ck_session_handle_t CK_SESSION_HANDLE
+#define ck_user_type_t CK_USER_TYPE
+#define ck_state_t CK_STATE
+
+#define ck_session_info _CK_SESSION_INFO
+#define slot_id slotID
+#define device_error ulDeviceError
+
+#define ck_object_handle_t CK_OBJECT_HANDLE
+#define ck_object_class_t CK_OBJECT_CLASS
+#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE
+#define ck_key_type_t CK_KEY_TYPE
+#define ck_certificate_type_t CK_CERTIFICATE_TYPE
+#define ck_attribute_type_t CK_ATTRIBUTE_TYPE
+
+#define ck_attribute _CK_ATTRIBUTE
+#define value pValue
+#define value_len ulValueLen
+
+#define ck_date _CK_DATE
+
+#define ck_mechanism_type_t CK_MECHANISM_TYPE
+
+#define ck_mechanism _CK_MECHANISM
+#define parameter pParameter
+#define parameter_len ulParameterLen
+
+#define ck_mechanism_info _CK_MECHANISM_INFO
+#define min_key_size ulMinKeySize
+#define max_key_size ulMaxKeySize
+
+#define ck_rv_t CK_RV
+#define ck_notify_t CK_NOTIFY
+
+#define ck_function_list _CK_FUNCTION_LIST
+
+#define ck_createmutex_t CK_CREATEMUTEX
+#define ck_destroymutex_t CK_DESTROYMUTEX
+#define ck_lockmutex_t CK_LOCKMUTEX
+#define ck_unlockmutex_t CK_UNLOCKMUTEX
+
+#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS
+#define create_mutex CreateMutex
+#define destroy_mutex DestroyMutex
+#define lock_mutex LockMutex
+#define unlock_mutex UnlockMutex
+#define reserved pReserved
+
+#endif	/* CRYPTOKI_COMPAT */
+
+
+
+typedef unsigned long ck_flags_t;
+
+struct ck_version
+{
+  unsigned char major;
+  unsigned char minor;
+};
+
+
+struct ck_info
+{
+  struct ck_version cryptoki_version;
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  unsigned char library_description[32];
+  struct ck_version library_version;
+};
+
+
+typedef unsigned long ck_notification_t;
+
+#define CKN_SURRENDER	(0)
+
+
+typedef unsigned long ck_slot_id_t;
+
+
+struct ck_slot_info
+{
+  unsigned char slot_description[64];
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+};
+
+
+#define CKF_TOKEN_PRESENT	(1 << 0)
+#define CKF_REMOVABLE_DEVICE	(1 << 1)
+#define CKF_HW_SLOT		(1 << 2)
+#define CKF_ARRAY_ATTRIBUTE	(1 << 30)
+
+
+struct ck_token_info
+{
+  unsigned char label[32];
+  unsigned char manufacturer_id[32];
+  unsigned char model[16];
+  unsigned char serial_number[16];
+  ck_flags_t flags;
+  unsigned long max_session_count;
+  unsigned long session_count;
+  unsigned long max_rw_session_count;
+  unsigned long rw_session_count;
+  unsigned long max_pin_len;
+  unsigned long min_pin_len;
+  unsigned long total_public_memory;
+  unsigned long free_public_memory;
+  unsigned long total_private_memory;
+  unsigned long free_private_memory;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+  unsigned char utc_time[16];
+};
+
+
+#define CKF_RNG					(1 << 0)
+#define CKF_WRITE_PROTECTED			(1 << 1)
+#define CKF_LOGIN_REQUIRED			(1 << 2)
+#define CKF_USER_PIN_INITIALIZED		(1 << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED		(1 << 5)
+#define CKF_CLOCK_ON_TOKEN			(1 << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH	(1 << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS		(1 << 9)
+#define CKF_TOKEN_INITIALIZED			(1 << 10)
+#define CKF_SECONDARY_AUTHENTICATION		(1 << 11)
+#define CKF_USER_PIN_COUNT_LOW			(1 << 16)
+#define CKF_USER_PIN_FINAL_TRY			(1 << 17)
+#define CKF_USER_PIN_LOCKED			(1 << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED		(1 << 19)
+#define CKF_SO_PIN_COUNT_LOW			(1 << 20)
+#define CKF_SO_PIN_FINAL_TRY			(1 << 21)
+#define CKF_SO_PIN_LOCKED			(1 << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED		(1 << 23)
+
+#define CK_UNAVAILABLE_INFORMATION	((unsigned long) -1)
+#define CK_EFFECTIVELY_INFINITE		(0)
+
+
+typedef unsigned long ck_session_handle_t;
+
+#define CK_INVALID_HANDLE	(0)
+
+
+typedef unsigned long ck_user_type_t;
+
+#define CKU_SO			(0)
+#define CKU_USER		(1)
+#define CKU_CONTEXT_SPECIFIC	(2)
+
+
+typedef unsigned long ck_state_t;
+
+#define CKS_RO_PUBLIC_SESSION	(0)
+#define CKS_RO_USER_FUNCTIONS	(1)
+#define CKS_RW_PUBLIC_SESSION	(2)
+#define CKS_RW_USER_FUNCTIONS	(3)
+#define CKS_RW_SO_FUNCTIONS	(4)
+
+
+struct ck_session_info
+{
+  ck_slot_id_t slot_id;
+  ck_state_t state;
+  ck_flags_t flags;
+  unsigned long device_error;
+};
+
+#define CKF_RW_SESSION		(1 << 1)
+#define CKF_SERIAL_SESSION	(1 << 2)
+
+
+typedef unsigned long ck_object_handle_t;
+
+
+typedef unsigned long ck_object_class_t;
+
+#define CKO_DATA		(0)
+#define CKO_CERTIFICATE		(1)
+#define CKO_PUBLIC_KEY		(2)
+#define CKO_PRIVATE_KEY		(3)
+#define CKO_SECRET_KEY		(4)
+#define CKO_HW_FEATURE		(5)
+#define CKO_DOMAIN_PARAMETERS	(6)
+#define CKO_MECHANISM		(7)
+#define CKO_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_hw_feature_type_t;
+
+#define CKH_MONOTONIC_COUNTER	(1)
+#define CKH_CLOCK		(2)
+#define CKH_USER_INTERFACE	(3)
+#define CKH_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_key_type_t;
+
+#define CKK_RSA			(0)
+#define CKK_DSA			(1)
+#define CKK_DH			(2)
+#define CKK_ECDSA		(3)
+#define CKK_EC			(3)
+#define CKK_X9_42_DH		(4)
+#define CKK_KEA			(5)
+#define CKK_GENERIC_SECRET	(0x10)
+#define CKK_RC2			(0x11)
+#define CKK_RC4			(0x12)
+#define CKK_DES			(0x13)
+#define CKK_DES2		(0x14)
+#define CKK_DES3		(0x15)
+#define CKK_CAST		(0x16)
+#define CKK_CAST3		(0x17)
+#define CKK_CAST128		(0x18)
+#define CKK_RC5			(0x19)
+#define CKK_IDEA		(0x1a)
+#define CKK_SKIPJACK		(0x1b)
+#define CKK_BATON		(0x1c)
+#define CKK_JUNIPER		(0x1d)
+#define CKK_CDMF		(0x1e)
+#define CKK_AES			(0x1f)
+#define CKK_BLOWFISH		(0x20)
+#define CKK_TWOFISH		(0x21)
+#define CKK_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_certificate_type_t;
+
+#define CKC_X_509		(0)
+#define CKC_X_509_ATTR_CERT	(1)
+#define CKC_WTLS		(2)
+#define CKC_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_attribute_type_t;
+
+#define CKA_CLASS			(0)
+#define CKA_TOKEN			(1)
+#define CKA_PRIVATE			(2)
+#define CKA_LABEL			(3)
+#define CKA_APPLICATION			(0x10)
+#define CKA_VALUE			(0x11)
+#define CKA_OBJECT_ID			(0x12)
+#define CKA_CERTIFICATE_TYPE		(0x80)
+#define CKA_ISSUER			(0x81)
+#define CKA_SERIAL_NUMBER		(0x82)
+#define CKA_AC_ISSUER			(0x83)
+#define CKA_OWNER			(0x84)
+#define CKA_ATTR_TYPES			(0x85)
+#define CKA_TRUSTED			(0x86)
+#define CKA_CERTIFICATE_CATEGORY	(0x87)
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN	(0x88)
+#define CKA_URL				(0x89)
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY	(0x8a)
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY	(0x8b)
+#define CKA_CHECK_VALUE			(0x90)
+#define CKA_KEY_TYPE			(0x100)
+#define CKA_SUBJECT			(0x101)
+#define CKA_ID				(0x102)
+#define CKA_SENSITIVE			(0x103)
+#define CKA_ENCRYPT			(0x104)
+#define CKA_DECRYPT			(0x105)
+#define CKA_WRAP			(0x106)
+#define CKA_UNWRAP			(0x107)
+#define CKA_SIGN			(0x108)
+#define CKA_SIGN_RECOVER		(0x109)
+#define CKA_VERIFY			(0x10a)
+#define CKA_VERIFY_RECOVER		(0x10b)
+#define CKA_DERIVE			(0x10c)
+#define CKA_START_DATE			(0x110)
+#define CKA_END_DATE			(0x111)
+#define CKA_MODULUS			(0x120)
+#define CKA_MODULUS_BITS		(0x121)
+#define CKA_PUBLIC_EXPONENT		(0x122)
+#define CKA_PRIVATE_EXPONENT		(0x123)
+#define CKA_PRIME_1			(0x124)
+#define CKA_PRIME_2			(0x125)
+#define CKA_EXPONENT_1			(0x126)
+#define CKA_EXPONENT_2			(0x127)
+#define CKA_COEFFICIENT			(0x128)
+#define CKA_PRIME			(0x130)
+#define CKA_SUBPRIME			(0x131)
+#define CKA_BASE			(0x132)
+#define CKA_PRIME_BITS			(0x133)
+#define CKA_SUB_PRIME_BITS		(0x134)
+#define CKA_VALUE_BITS			(0x160)
+#define CKA_VALUE_LEN			(0x161)
+#define CKA_EXTRACTABLE			(0x162)
+#define CKA_LOCAL			(0x163)
+#define CKA_NEVER_EXTRACTABLE		(0x164)
+#define CKA_ALWAYS_SENSITIVE		(0x165)
+#define CKA_KEY_GEN_MECHANISM		(0x166)
+#define CKA_MODIFIABLE			(0x170)
+#define CKA_ECDSA_PARAMS		(0x180)
+#define CKA_EC_PARAMS			(0x180)
+#define CKA_EC_POINT			(0x181)
+#define CKA_SECONDARY_AUTH		(0x200)
+#define CKA_AUTH_PIN_FLAGS		(0x201)
+#define CKA_ALWAYS_AUTHENTICATE		(0x202)
+#define CKA_WRAP_WITH_TRUSTED		(0x210)
+#define CKA_HW_FEATURE_TYPE		(0x300)
+#define CKA_RESET_ON_INIT		(0x301)
+#define CKA_HAS_RESET			(0x302)
+#define CKA_PIXEL_X			(0x400)
+#define CKA_PIXEL_Y			(0x401)
+#define CKA_RESOLUTION			(0x402)
+#define CKA_CHAR_ROWS			(0x403)
+#define CKA_CHAR_COLUMNS		(0x404)
+#define CKA_COLOR			(0x405)
+#define CKA_BITS_PER_PIXEL		(0x406)
+#define CKA_CHAR_SETS			(0x480)
+#define CKA_ENCODING_METHODS		(0x481)
+#define CKA_MIME_TYPES			(0x482)
+#define CKA_MECHANISM_TYPE		(0x500)
+#define CKA_REQUIRED_CMS_ATTRIBUTES	(0x501)
+#define CKA_DEFAULT_CMS_ATTRIBUTES	(0x502)
+#define CKA_SUPPORTED_CMS_ATTRIBUTES	(0x503)
+#define CKA_WRAP_TEMPLATE		(CKF_ARRAY_ATTRIBUTE | 0x211)
+#define CKA_UNWRAP_TEMPLATE		(CKF_ARRAY_ATTRIBUTE | 0x212)
+#define CKA_ALLOWED_MECHANISMS		(CKF_ARRAY_ATTRIBUTE | 0x600)
+#define CKA_VENDOR_DEFINED		((unsigned long) (1 << 31))
+
+
+struct ck_attribute
+{
+  ck_attribute_type_t type;
+  void *value;
+  unsigned long value_len;
+};
+
+
+struct ck_date
+{
+  unsigned char year[4];
+  unsigned char month[2];
+  unsigned char day[2];
+};
+
+
+typedef unsigned long ck_mechanism_type_t;
+
+#define CKM_RSA_PKCS_KEY_PAIR_GEN	(0)
+#define CKM_RSA_PKCS			(1)
+#define CKM_RSA_9796			(2)
+#define CKM_RSA_X_509			(3)
+#define CKM_MD2_RSA_PKCS		(4)
+#define CKM_MD5_RSA_PKCS		(5)
+#define CKM_SHA1_RSA_PKCS		(6)
+#define CKM_RIPEMD128_RSA_PKCS		(7)
+#define CKM_RIPEMD160_RSA_PKCS		(8)
+#define CKM_RSA_PKCS_OAEP		(9)
+#define CKM_RSA_X9_31_KEY_PAIR_GEN	(0xa)
+#define CKM_RSA_X9_31			(0xb)
+#define CKM_SHA1_RSA_X9_31		(0xc)
+#define CKM_RSA_PKCS_PSS		(0xd)
+#define CKM_SHA1_RSA_PKCS_PSS		(0xe)
+#define CKM_DSA_KEY_PAIR_GEN		(0x10)
+#define	CKM_DSA				(0x11)
+#define CKM_DSA_SHA1			(0x12)
+#define CKM_DH_PKCS_KEY_PAIR_GEN	(0x20)
+#define CKM_DH_PKCS_DERIVE		(0x21)
+#define	CKM_X9_42_DH_KEY_PAIR_GEN	(0x30)
+#define CKM_X9_42_DH_DERIVE		(0x31)
+#define CKM_X9_42_DH_HYBRID_DERIVE	(0x32)
+#define CKM_X9_42_MQV_DERIVE		(0x33)
+#define CKM_SHA256_RSA_PKCS		(0x40)
+#define CKM_SHA384_RSA_PKCS		(0x41)
+#define CKM_SHA512_RSA_PKCS		(0x42)
+#define CKM_SHA256_RSA_PKCS_PSS		(0x43)
+#define CKM_SHA384_RSA_PKCS_PSS		(0x44)
+#define CKM_SHA512_RSA_PKCS_PSS		(0x45)
+#define CKM_RC2_KEY_GEN			(0x100)
+#define CKM_RC2_ECB			(0x101)
+#define	CKM_RC2_CBC			(0x102)
+#define	CKM_RC2_MAC			(0x103)
+#define CKM_RC2_MAC_GENERAL		(0x104)
+#define CKM_RC2_CBC_PAD			(0x105)
+#define CKM_RC4_KEY_GEN			(0x110)
+#define CKM_RC4				(0x111)
+#define CKM_DES_KEY_GEN			(0x120)
+#define CKM_DES_ECB			(0x121)
+#define CKM_DES_CBC			(0x122)
+#define CKM_DES_MAC			(0x123)
+#define CKM_DES_MAC_GENERAL		(0x124)
+#define CKM_DES_CBC_PAD			(0x125)
+#define CKM_DES2_KEY_GEN		(0x130)
+#define CKM_DES3_KEY_GEN		(0x131)
+#define CKM_DES3_ECB			(0x132)
+#define CKM_DES3_CBC			(0x133)
+#define CKM_DES3_MAC			(0x134)
+#define CKM_DES3_MAC_GENERAL		(0x135)
+#define CKM_DES3_CBC_PAD		(0x136)
+#define CKM_CDMF_KEY_GEN		(0x140)
+#define CKM_CDMF_ECB			(0x141)
+#define CKM_CDMF_CBC			(0x142)
+#define CKM_CDMF_MAC			(0x143)
+#define CKM_CDMF_MAC_GENERAL		(0x144)
+#define CKM_CDMF_CBC_PAD		(0x145)
+#define CKM_MD2				(0x200)
+#define CKM_MD2_HMAC			(0x201)
+#define CKM_MD2_HMAC_GENERAL		(0x202)
+#define CKM_MD5				(0x210)
+#define CKM_MD5_HMAC			(0x211)
+#define CKM_MD5_HMAC_GENERAL		(0x212)
+#define CKM_SHA_1			(0x220)
+#define CKM_SHA_1_HMAC			(0x221)
+#define CKM_SHA_1_HMAC_GENERAL		(0x222)
+#define CKM_RIPEMD128			(0x230)
+#define CKM_RIPEMD128_HMAC		(0x231)
+#define CKM_RIPEMD128_HMAC_GENERAL	(0x232)
+#define CKM_RIPEMD160			(0x240)
+#define CKM_RIPEMD160_HMAC		(0x241)
+#define CKM_RIPEMD160_HMAC_GENERAL	(0x242)
+#define CKM_SHA256			(0x250)
+#define CKM_SHA256_HMAC			(0x251)
+#define CKM_SHA256_HMAC_GENERAL		(0x252)
+#define CKM_SHA384			(0x260)
+#define CKM_SHA384_HMAC			(0x261)
+#define CKM_SHA384_HMAC_GENERAL		(0x262)
+#define CKM_SHA512			(0x270)
+#define CKM_SHA512_HMAC			(0x271)
+#define CKM_SHA512_HMAC_GENERAL		(0x272)
+#define CKM_CAST_KEY_GEN		(0x300)
+#define CKM_CAST_ECB			(0x301)
+#define CKM_CAST_CBC			(0x302)
+#define CKM_CAST_MAC			(0x303)
+#define CKM_CAST_MAC_GENERAL		(0x304)
+#define CKM_CAST_CBC_PAD		(0x305)
+#define CKM_CAST3_KEY_GEN		(0x310)
+#define CKM_CAST3_ECB			(0x311)
+#define CKM_CAST3_CBC			(0x312)
+#define CKM_CAST3_MAC			(0x313)
+#define CKM_CAST3_MAC_GENERAL		(0x314)
+#define CKM_CAST3_CBC_PAD		(0x315)
+#define CKM_CAST5_KEY_GEN		(0x320)
+#define CKM_CAST128_KEY_GEN		(0x320)
+#define CKM_CAST5_ECB			(0x321)
+#define CKM_CAST128_ECB			(0x321)
+#define CKM_CAST5_CBC			(0x322)
+#define CKM_CAST128_CBC			(0x322)
+#define CKM_CAST5_MAC			(0x323)
+#define	CKM_CAST128_MAC			(0x323)
+#define CKM_CAST5_MAC_GENERAL		(0x324)
+#define CKM_CAST128_MAC_GENERAL		(0x324)
+#define CKM_CAST5_CBC_PAD		(0x325)
+#define CKM_CAST128_CBC_PAD		(0x325)
+#define CKM_RC5_KEY_GEN			(0x330)
+#define CKM_RC5_ECB			(0x331)
+#define CKM_RC5_CBC			(0x332)
+#define CKM_RC5_MAC			(0x333)
+#define CKM_RC5_MAC_GENERAL		(0x334)
+#define CKM_RC5_CBC_PAD			(0x335)
+#define CKM_IDEA_KEY_GEN		(0x340)
+#define CKM_IDEA_ECB			(0x341)
+#define	CKM_IDEA_CBC			(0x342)
+#define CKM_IDEA_MAC			(0x343)
+#define CKM_IDEA_MAC_GENERAL		(0x344)
+#define CKM_IDEA_CBC_PAD		(0x345)
+#define CKM_GENERIC_SECRET_KEY_GEN	(0x350)
+#define CKM_CONCATENATE_BASE_AND_KEY	(0x360)
+#define CKM_CONCATENATE_BASE_AND_DATA	(0x362)
+#define CKM_CONCATENATE_DATA_AND_BASE	(0x363)
+#define CKM_XOR_BASE_AND_DATA		(0x364)
+#define CKM_EXTRACT_KEY_FROM_KEY	(0x365)
+#define CKM_SSL3_PRE_MASTER_KEY_GEN	(0x370)
+#define CKM_SSL3_MASTER_KEY_DERIVE	(0x371)
+#define CKM_SSL3_KEY_AND_MAC_DERIVE	(0x372)
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH	(0x373)
+#define CKM_TLS_PRE_MASTER_KEY_GEN	(0x374)
+#define CKM_TLS_MASTER_KEY_DERIVE	(0x375)
+#define CKM_TLS_KEY_AND_MAC_DERIVE	(0x376)
+#define CKM_TLS_MASTER_KEY_DERIVE_DH	(0x377)
+#define CKM_SSL3_MD5_MAC		(0x380)
+#define CKM_SSL3_SHA1_MAC		(0x381)
+#define CKM_MD5_KEY_DERIVATION		(0x390)
+#define CKM_MD2_KEY_DERIVATION		(0x391)
+#define CKM_SHA1_KEY_DERIVATION		(0x392)
+#define CKM_PBE_MD2_DES_CBC		(0x3a0)
+#define CKM_PBE_MD5_DES_CBC		(0x3a1)
+#define CKM_PBE_MD5_CAST_CBC		(0x3a2)
+#define CKM_PBE_MD5_CAST3_CBC		(0x3a3)
+#define CKM_PBE_MD5_CAST5_CBC		(0x3a4)
+#define CKM_PBE_MD5_CAST128_CBC		(0x3a4)
+#define CKM_PBE_SHA1_CAST5_CBC		(0x3a5)
+#define CKM_PBE_SHA1_CAST128_CBC	(0x3a5)
+#define CKM_PBE_SHA1_RC4_128		(0x3a6)
+#define CKM_PBE_SHA1_RC4_40		(0x3a7)
+#define CKM_PBE_SHA1_DES3_EDE_CBC	(0x3a8)
+#define CKM_PBE_SHA1_DES2_EDE_CBC	(0x3a9)
+#define CKM_PBE_SHA1_RC2_128_CBC	(0x3aa)
+#define CKM_PBE_SHA1_RC2_40_CBC		(0x3ab)
+#define CKM_PKCS5_PBKD2			(0x3b0)
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC	(0x3c0)
+#define CKM_KEY_WRAP_LYNKS		(0x400)
+#define CKM_KEY_WRAP_SET_OAEP		(0x401)
+#define CKM_SKIPJACK_KEY_GEN		(0x1000)
+#define CKM_SKIPJACK_ECB64		(0x1001)
+#define CKM_SKIPJACK_CBC64		(0x1002)
+#define CKM_SKIPJACK_OFB64		(0x1003)
+#define CKM_SKIPJACK_CFB64		(0x1004)
+#define CKM_SKIPJACK_CFB32		(0x1005)
+#define CKM_SKIPJACK_CFB16		(0x1006)
+#define CKM_SKIPJACK_CFB8		(0x1007)
+#define CKM_SKIPJACK_WRAP		(0x1008)
+#define CKM_SKIPJACK_PRIVATE_WRAP	(0x1009)
+#define CKM_SKIPJACK_RELAYX		(0x100a)
+#define CKM_KEA_KEY_PAIR_GEN		(0x1010)
+#define CKM_KEA_KEY_DERIVE		(0x1011)
+#define CKM_FORTEZZA_TIMESTAMP		(0x1020)
+#define CKM_BATON_KEY_GEN		(0x1030)
+#define CKM_BATON_ECB128		(0x1031)
+#define CKM_BATON_ECB96			(0x1032)
+#define CKM_BATON_CBC128		(0x1033)
+#define CKM_BATON_COUNTER		(0x1034)
+#define CKM_BATON_SHUFFLE		(0x1035)
+#define CKM_BATON_WRAP			(0x1036)
+#define CKM_ECDSA_KEY_PAIR_GEN		(0x1040)
+#define CKM_EC_KEY_PAIR_GEN		(0x1040)
+#define CKM_ECDSA			(0x1041)
+#define CKM_ECDSA_SHA1			(0x1042)
+#define CKM_ECDH1_DERIVE		(0x1050)
+#define CKM_ECDH1_COFACTOR_DERIVE	(0x1051)
+#define CKM_ECMQV_DERIVE		(0x1052)
+#define CKM_JUNIPER_KEY_GEN		(0x1060)
+#define CKM_JUNIPER_ECB128		(0x1061)
+#define CKM_JUNIPER_CBC128		(0x1062)
+#define CKM_JUNIPER_COUNTER		(0x1063)
+#define CKM_JUNIPER_SHUFFLE		(0x1064)
+#define CKM_JUNIPER_WRAP		(0x1065)
+#define CKM_FASTHASH			(0x1070)
+#define CKM_AES_KEY_GEN			(0x1080)
+#define CKM_AES_ECB			(0x1081)
+#define CKM_AES_CBC			(0x1082)
+#define CKM_AES_MAC			(0x1083)
+#define CKM_AES_MAC_GENERAL		(0x1084)
+#define CKM_AES_CBC_PAD			(0x1085)
+#define CKM_DSA_PARAMETER_GEN		(0x2000)
+#define CKM_DH_PKCS_PARAMETER_GEN	(0x2001)
+#define CKM_X9_42_DH_PARAMETER_GEN	(0x2002)
+#define CKM_VENDOR_DEFINED		((unsigned long) (1 << 31))
+
+
+struct ck_mechanism
+{
+  ck_mechanism_type_t mechanism;
+  void *parameter;
+  unsigned long parameter_len;
+};
+
+
+struct ck_mechanism_info
+{
+  unsigned long min_key_size;
+  unsigned long max_key_size;
+  ck_flags_t flags;
+};
+
+#define CKF_HW			(1 << 0)
+#define CKF_ENCRYPT		(1 << 8)
+#define CKF_DECRYPT		(1 << 9)
+#define CKF_DIGEST		(1 << 10)
+#define CKF_SIGN		(1 << 11)
+#define CKF_SIGN_RECOVER	(1 << 12)
+#define CKF_VERIFY		(1 << 13)
+#define CKF_VERIFY_RECOVER	(1 << 14)
+#define CKF_GENERATE		(1 << 15)
+#define CKF_GENERATE_KEY_PAIR	(1 << 16)
+#define CKF_WRAP		(1 << 17)
+#define CKF_UNWRAP		(1 << 18)
+#define CKF_DERIVE		(1 << 19)
+#define CKF_EXTENSION		((unsigned long) (1 << 31))
+
+
+/* Flags for C_WaitForSlotEvent.  */
+#define CKF_DONT_BLOCK				(1)
+
+
+typedef unsigned long ck_rv_t;
+
+
+typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session,
+				ck_notification_t event, void *application);
+
+/* Forward reference.  */
+struct ck_function_list;
+
+#define _CK_DECLARE_FUNCTION(name, args)	\
+typedef ck_rv_t (*CK_ ## name) args;		\
+ck_rv_t CK_SPEC name args
+
+_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args));
+_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved));
+_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info));
+_CK_DECLARE_FUNCTION (C_GetFunctionList,
+		      (struct ck_function_list **function_list));
+
+_CK_DECLARE_FUNCTION (C_GetSlotList,
+		      (unsigned char token_present, ck_slot_id_t *slot_list,
+		       unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetSlotInfo,
+		      (ck_slot_id_t slot_id, struct ck_slot_info *info));
+_CK_DECLARE_FUNCTION (C_GetTokenInfo,
+		      (ck_slot_id_t slot_id, struct ck_token_info *info));
+_CK_DECLARE_FUNCTION (C_WaitForSlotEvent,
+		      (ck_flags_t flags, ck_slot_id_t *slot, void *reserved));
+_CK_DECLARE_FUNCTION (C_GetMechanismList,
+		      (ck_slot_id_t slot_id,
+		       ck_mechanism_type_t *mechanism_list,
+		       unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetMechanismInfo,
+		      (ck_slot_id_t slot_id, ck_mechanism_type_t type,
+		       struct ck_mechanism_info *info));
+_CK_DECLARE_FUNCTION (C_InitToken,
+		      (ck_slot_id_t slot_id, unsigned char *pin,
+		       unsigned long pin_len, unsigned char *label));
+_CK_DECLARE_FUNCTION (C_InitPIN,
+		      (ck_session_handle_t session, unsigned char *pin,
+		       unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_SetPIN,
+		      (ck_session_handle_t session, unsigned char *old_pin,
+		       unsigned long old_len, unsigned char *new_pin,
+		       unsigned long new_len));
+
+_CK_DECLARE_FUNCTION (C_OpenSession,
+		      (ck_slot_id_t slot_id, ck_flags_t flags,
+		       void *application, ck_notify_t notify,
+		       ck_session_handle_t *session));
+_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id));
+_CK_DECLARE_FUNCTION (C_GetSessionInfo,
+		      (ck_session_handle_t session,
+		       struct ck_session_info *info));
+_CK_DECLARE_FUNCTION (C_GetOperationState,
+		      (ck_session_handle_t session,
+		       unsigned char *operation_state,
+		       unsigned long *operation_state_len));
+_CK_DECLARE_FUNCTION (C_SetOperationState,
+		      (ck_session_handle_t session,
+		       unsigned char *operation_state,
+		       unsigned long operation_state_len,
+		       ck_object_handle_t encryption_key,
+		       ck_object_handle_t authentiation_key));
+_CK_DECLARE_FUNCTION (C_Login,
+		      (ck_session_handle_t session, ck_user_type_t user_type,
+		       unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_CreateObject,
+		      (ck_session_handle_t session,
+		       struct ck_attribute *templ,
+		       unsigned long count, ck_object_handle_t *object));
+_CK_DECLARE_FUNCTION (C_CopyObject,
+		      (ck_session_handle_t session, ck_object_handle_t object,
+		       struct ck_attribute *templ, unsigned long count,
+		       ck_object_handle_t *new_object));
+_CK_DECLARE_FUNCTION (C_DestroyObject,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object));
+_CK_DECLARE_FUNCTION (C_GetObjectSize,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       unsigned long *size));
+_CK_DECLARE_FUNCTION (C_GetAttributeValue,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_SetAttributeValue,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjectsInit,
+		      (ck_session_handle_t session,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjects,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t *object,
+		       unsigned long max_object_count,
+		       unsigned long *object_count));
+_CK_DECLARE_FUNCTION (C_FindObjectsFinal,
+		      (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_EncryptInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Encrypt,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *encrypted_data,
+		       unsigned long *encrypted_data_len));
+_CK_DECLARE_FUNCTION (C_EncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_EncryptFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *last_encrypted_part,
+		       unsigned long *last_encrypted_part_len));
+
+_CK_DECLARE_FUNCTION (C_DecryptInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Decrypt,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_data,
+		       unsigned long encrypted_data_len,
+		       unsigned char *data, unsigned long *data_len));
+_CK_DECLARE_FUNCTION (C_DecryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part, unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_DecryptFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *last_part,
+		       unsigned long *last_part_len));
+
+_CK_DECLARE_FUNCTION (C_DigestInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism));
+_CK_DECLARE_FUNCTION (C_Digest,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *digest,
+		       unsigned long *digest_len));
+_CK_DECLARE_FUNCTION (C_DigestUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_DigestKey,
+		      (ck_session_handle_t session, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_DigestFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *digest,
+		       unsigned long *digest_len));
+
+_CK_DECLARE_FUNCTION (C_SignInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Sign,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_SignFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignRecoverInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_SignRecover,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+
+_CK_DECLARE_FUNCTION (C_VerifyInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Verify,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_VerifyFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyRecoverInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_VerifyRecover,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long signature_len,
+		       unsigned char *data,
+		       unsigned long *data_len));
+
+_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part,
+		       unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_SignEncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part,
+		       unsigned long *part_len));
+
+_CK_DECLARE_FUNCTION (C_GenerateKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       struct ck_attribute *templ,
+		       unsigned long count,
+		       ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_GenerateKeyPair,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       struct ck_attribute *public_key_template,
+		       unsigned long public_key_attribute_count,
+		       struct ck_attribute *private_key_template,
+		       unsigned long private_key_attribute_count,
+		       ck_object_handle_t *public_key,
+		       ck_object_handle_t *private_key));
+_CK_DECLARE_FUNCTION (C_WrapKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t wrapping_key,
+		       ck_object_handle_t key,
+		       unsigned char *wrapped_key,
+		       unsigned long *wrapped_key_len));
+_CK_DECLARE_FUNCTION (C_UnwrapKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t unwrapping_key,
+		       unsigned char *wrapped_key,
+		       unsigned long wrapped_key_len,
+		       struct ck_attribute *templ,
+		       unsigned long attribute_count,
+		       ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_DeriveKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t base_key,
+		       struct ck_attribute *templ,
+		       unsigned long attribute_count,
+		       ck_object_handle_t *key));
+
+_CK_DECLARE_FUNCTION (C_SeedRandom,
+		      (ck_session_handle_t session, unsigned char *seed,
+		       unsigned long seed_len));
+_CK_DECLARE_FUNCTION (C_GenerateRandom,
+		      (ck_session_handle_t session,
+		       unsigned char *random_data,
+		       unsigned long random_len));
+
+_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session));
+
+
+struct ck_function_list
+{
+  struct ck_version version;
+  CK_C_Initialize C_Initialize;
+  CK_C_Finalize C_Finalize;
+  CK_C_GetInfo C_GetInfo;
+  CK_C_GetFunctionList C_GetFunctionList;
+  CK_C_GetSlotList C_GetSlotList;
+  CK_C_GetSlotInfo C_GetSlotInfo;
+  CK_C_GetTokenInfo C_GetTokenInfo;
+  CK_C_GetMechanismList C_GetMechanismList;
+  CK_C_GetMechanismInfo C_GetMechanismInfo;
+  CK_C_InitToken C_InitToken;
+  CK_C_InitPIN C_InitPIN;
+  CK_C_SetPIN C_SetPIN;
+  CK_C_OpenSession C_OpenSession;
+  CK_C_CloseSession C_CloseSession;
+  CK_C_CloseAllSessions C_CloseAllSessions;
+  CK_C_GetSessionInfo C_GetSessionInfo;
+  CK_C_GetOperationState C_GetOperationState;
+  CK_C_SetOperationState C_SetOperationState;
+  CK_C_Login C_Login;
+  CK_C_Logout C_Logout;
+  CK_C_CreateObject C_CreateObject;
+  CK_C_CopyObject C_CopyObject;
+  CK_C_DestroyObject C_DestroyObject;
+  CK_C_GetObjectSize C_GetObjectSize;
+  CK_C_GetAttributeValue C_GetAttributeValue;
+  CK_C_SetAttributeValue C_SetAttributeValue;
+  CK_C_FindObjectsInit C_FindObjectsInit;
+  CK_C_FindObjects C_FindObjects;
+  CK_C_FindObjectsFinal C_FindObjectsFinal;
+  CK_C_EncryptInit C_EncryptInit;
+  CK_C_Encrypt C_Encrypt;
+  CK_C_EncryptUpdate C_EncryptUpdate;
+  CK_C_EncryptFinal C_EncryptFinal;
+  CK_C_DecryptInit C_DecryptInit;
+  CK_C_Decrypt C_Decrypt;
+  CK_C_DecryptUpdate C_DecryptUpdate;
+  CK_C_DecryptFinal C_DecryptFinal;
+  CK_C_DigestInit C_DigestInit;
+  CK_C_Digest C_Digest;
+  CK_C_DigestUpdate C_DigestUpdate;
+  CK_C_DigestKey C_DigestKey;
+  CK_C_DigestFinal C_DigestFinal;
+  CK_C_SignInit C_SignInit;
+  CK_C_Sign C_Sign;
+  CK_C_SignUpdate C_SignUpdate;
+  CK_C_SignFinal C_SignFinal;
+  CK_C_SignRecoverInit C_SignRecoverInit;
+  CK_C_SignRecover C_SignRecover;
+  CK_C_VerifyInit C_VerifyInit;
+  CK_C_Verify C_Verify;
+  CK_C_VerifyUpdate C_VerifyUpdate;
+  CK_C_VerifyFinal C_VerifyFinal;
+  CK_C_VerifyRecoverInit C_VerifyRecoverInit;
+  CK_C_VerifyRecover C_VerifyRecover;
+  CK_C_DigestEncryptUpdate C_DigestEncryptUpdate;
+  CK_C_DecryptDigestUpdate C_DecryptDigestUpdate;
+  CK_C_SignEncryptUpdate C_SignEncryptUpdate;
+  CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate;
+  CK_C_GenerateKey C_GenerateKey;
+  CK_C_GenerateKeyPair C_GenerateKeyPair;
+  CK_C_WrapKey C_WrapKey;
+  CK_C_UnwrapKey C_UnwrapKey;
+  CK_C_DeriveKey C_DeriveKey;
+  CK_C_SeedRandom C_SeedRandom;
+  CK_C_GenerateRandom C_GenerateRandom;
+  CK_C_GetFunctionStatus C_GetFunctionStatus;
+  CK_C_CancelFunction C_CancelFunction;
+  CK_C_WaitForSlotEvent C_WaitForSlotEvent;
+};
+
+
+typedef ck_rv_t (*ck_createmutex_t) (void **mutex);
+typedef ck_rv_t (*ck_destroymutex_t) (void *mutex);
+typedef ck_rv_t (*ck_lockmutex_t) (void *mutex);
+typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex);
+
+
+struct ck_c_initialize_args
+{
+  ck_createmutex_t create_mutex;
+  ck_destroymutex_t destroy_mutex;
+  ck_lockmutex_t lock_mutex;
+  ck_unlockmutex_t unlock_mutex;
+  ck_flags_t flags;
+  void *reserved;
+};
+
+
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS	(1 << 0)
+#define CKF_OS_LOCKING_OK			(1 << 1)
+
+#define CKR_OK					(0)
+#define CKR_CANCEL				(1)
+#define CKR_HOST_MEMORY				(2)
+#define CKR_SLOT_ID_INVALID			(3)
+#define CKR_GENERAL_ERROR			(5)
+#define CKR_FUNCTION_FAILED			(6)
+#define CKR_ARGUMENTS_BAD			(7)
+#define CKR_NO_EVENT				(8)
+#define CKR_NEED_TO_CREATE_THREADS		(9)
+#define CKR_CANT_LOCK				(0xa)
+#define CKR_ATTRIBUTE_READ_ONLY			(0x10)
+#define CKR_ATTRIBUTE_SENSITIVE			(0x11)
+#define CKR_ATTRIBUTE_TYPE_INVALID		(0x12)
+#define CKR_ATTRIBUTE_VALUE_INVALID		(0x13)
+#define CKR_DATA_INVALID			(0x20)
+#define CKR_DATA_LEN_RANGE			(0x21)
+#define CKR_DEVICE_ERROR			(0x30)
+#define CKR_DEVICE_MEMORY			(0x31)
+#define CKR_DEVICE_REMOVED			(0x32)
+#define CKR_ENCRYPTED_DATA_INVALID		(0x40)
+#define CKR_ENCRYPTED_DATA_LEN_RANGE		(0x41)
+#define CKR_FUNCTION_CANCELED			(0x50)
+#define CKR_FUNCTION_NOT_PARALLEL		(0x51)
+#define CKR_FUNCTION_NOT_SUPPORTED		(0x54)
+#define CKR_KEY_HANDLE_INVALID			(0x60)
+#define CKR_KEY_SIZE_RANGE			(0x62)
+#define CKR_KEY_TYPE_INCONSISTENT		(0x63)
+#define CKR_KEY_NOT_NEEDED			(0x64)
+#define CKR_KEY_CHANGED				(0x65)
+#define CKR_KEY_NEEDED				(0x66)
+#define CKR_KEY_INDIGESTIBLE			(0x67)
+#define CKR_KEY_FUNCTION_NOT_PERMITTED		(0x68)
+#define CKR_KEY_NOT_WRAPPABLE			(0x69)
+#define CKR_KEY_UNEXTRACTABLE			(0x6a)
+#define CKR_MECHANISM_INVALID			(0x70)
+#define CKR_MECHANISM_PARAM_INVALID		(0x71)
+#define CKR_OBJECT_HANDLE_INVALID		(0x82)
+#define CKR_OPERATION_ACTIVE			(0x90)
+#define CKR_OPERATION_NOT_INITIALIZED		(0x91)
+#define CKR_PIN_INCORRECT			(0xa0)
+#define CKR_PIN_INVALID				(0xa1)
+#define CKR_PIN_LEN_RANGE			(0xa2)
+#define CKR_PIN_EXPIRED				(0xa3)
+#define CKR_PIN_LOCKED				(0xa4)
+#define CKR_SESSION_CLOSED			(0xb0)
+#define CKR_SESSION_COUNT			(0xb1)
+#define CKR_SESSION_HANDLE_INVALID		(0xb3)
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED	(0xb4)
+#define CKR_SESSION_READ_ONLY			(0xb5)
+#define CKR_SESSION_EXISTS			(0xb6)
+#define CKR_SESSION_READ_ONLY_EXISTS		(0xb7)
+#define CKR_SESSION_READ_WRITE_SO_EXISTS	(0xb8)
+#define CKR_SIGNATURE_INVALID			(0xc0)
+#define CKR_SIGNATURE_LEN_RANGE			(0xc1)
+#define CKR_TEMPLATE_INCOMPLETE			(0xd0)
+#define CKR_TEMPLATE_INCONSISTENT		(0xd1)
+#define CKR_TOKEN_NOT_PRESENT			(0xe0)
+#define CKR_TOKEN_NOT_RECOGNIZED		(0xe1)
+#define CKR_TOKEN_WRITE_PROTECTED		(0xe2)
+#define	CKR_UNWRAPPING_KEY_HANDLE_INVALID	(0xf0)
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE		(0xf1)
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT	(0xf2)
+#define CKR_USER_ALREADY_LOGGED_IN		(0x100)
+#define CKR_USER_NOT_LOGGED_IN			(0x101)
+#define CKR_USER_PIN_NOT_INITIALIZED		(0x102)
+#define CKR_USER_TYPE_INVALID			(0x103)
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN	(0x104)
+#define CKR_USER_TOO_MANY_TYPES			(0x105)
+#define CKR_WRAPPED_KEY_INVALID			(0x110)
+#define CKR_WRAPPED_KEY_LEN_RANGE		(0x112)
+#define CKR_WRAPPING_KEY_HANDLE_INVALID		(0x113)
+#define CKR_WRAPPING_KEY_SIZE_RANGE		(0x114)
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT	(0x115)
+#define CKR_RANDOM_SEED_NOT_SUPPORTED		(0x120)
+#define CKR_RANDOM_NO_RNG			(0x121)
+#define CKR_DOMAIN_PARAMS_INVALID		(0x130)
+#define CKR_BUFFER_TOO_SMALL			(0x150)
+#define CKR_SAVED_STATE_INVALID			(0x160)
+#define CKR_INFORMATION_SENSITIVE		(0x170)
+#define CKR_STATE_UNSAVEABLE			(0x180)
+#define CKR_CRYPTOKI_NOT_INITIALIZED		(0x190)
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED	(0x191)
+#define CKR_MUTEX_BAD				(0x1a0)
+#define CKR_MUTEX_NOT_LOCKED			(0x1a1)
+#define CKR_FUNCTION_REJECTED			(0x200)
+#define CKR_VENDOR_DEFINED			((unsigned long) (1 << 31))
+
+
+
+/* Compatibility layer.  */
+
+#ifdef CRYPTOKI_COMPAT
+
+#undef CK_DEFINE_FUNCTION
+#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name
+
+/* For NULL.  */
+#include <stddef.h>
+
+typedef unsigned char CK_BYTE;
+typedef unsigned char CK_CHAR;
+typedef unsigned char CK_UTF8CHAR;
+typedef unsigned char CK_BBOOL;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+typedef CK_BYTE *CK_BYTE_PTR;
+typedef CK_CHAR *CK_CHAR_PTR;
+typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR;
+typedef CK_ULONG *CK_ULONG_PTR;
+typedef void *CK_VOID_PTR;
+typedef void **CK_VOID_PTR_PTR;
+#define CK_FALSE 0
+#define CK_TRUE 1
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#endif
+
+typedef struct ck_version CK_VERSION;
+typedef struct ck_version *CK_VERSION_PTR;
+
+typedef struct ck_info CK_INFO;
+typedef struct ck_info *CK_INFO_PTR;
+
+typedef ck_slot_id_t *CK_SLOT_ID_PTR;
+
+typedef struct ck_slot_info CK_SLOT_INFO;
+typedef struct ck_slot_info *CK_SLOT_INFO_PTR;
+
+typedef struct ck_token_info CK_TOKEN_INFO;
+typedef struct ck_token_info *CK_TOKEN_INFO_PTR;
+
+typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR;
+
+typedef struct ck_session_info CK_SESSION_INFO;
+typedef struct ck_session_info *CK_SESSION_INFO_PTR;
+
+typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR;
+
+typedef ck_object_class_t *CK_OBJECT_CLASS_PTR;
+
+typedef struct ck_attribute CK_ATTRIBUTE;
+typedef struct ck_attribute *CK_ATTRIBUTE_PTR;
+
+typedef struct ck_date CK_DATE;
+typedef struct ck_date *CK_DATE_PTR;
+
+typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR;
+
+typedef struct ck_mechanism CK_MECHANISM;
+typedef struct ck_mechanism *CK_MECHANISM_PTR;
+
+typedef struct ck_mechanism_info CK_MECHANISM_INFO;
+typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR;
+
+typedef struct ck_function_list CK_FUNCTION_LIST;
+typedef struct ck_function_list *CK_FUNCTION_LIST_PTR;
+typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR;
+
+typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS;
+typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
+
+#define NULL_PTR NULL
+
+/* Delete the helper macros defined at the top of the file.  */
+#undef ck_flags_t
+#undef ck_version
+
+#undef ck_info
+#undef cryptoki_version
+#undef manufacturer_id
+#undef library_description
+#undef library_version
+
+#undef ck_notification_t
+#undef ck_slot_id_t
+
+#undef ck_slot_info
+#undef slot_description
+#undef hardware_version
+#undef firmware_version
+
+#undef ck_token_info
+#undef serial_number
+#undef max_session_count
+#undef session_count
+#undef max_rw_session_count
+#undef rw_session_count
+#undef max_pin_len
+#undef min_pin_len
+#undef total_public_memory
+#undef free_public_memory
+#undef total_private_memory
+#undef free_private_memory
+#undef utc_time
+
+#undef ck_session_handle_t
+#undef ck_user_type_t
+#undef ck_state_t
+
+#undef ck_session_info
+#undef slot_id
+#undef device_error
+
+#undef ck_object_handle_t
+#undef ck_object_class_t
+#undef ck_hw_feature_type_t
+#undef ck_key_type_t
+#undef ck_certificate_type_t
+#undef ck_attribute_type_t
+
+#undef ck_attribute
+#undef value
+#undef value_len
+
+#undef ck_date
+
+#undef ck_mechanism_type_t
+
+#undef ck_mechanism
+#undef parameter
+#undef parameter_len
+
+#undef ck_mechanism_info
+#undef min_key_size
+#undef max_key_size
+
+#undef ck_rv_t
+#undef ck_notify_t
+
+#undef ck_function_list
+
+#undef ck_createmutex_t
+#undef ck_destroymutex_t
+#undef ck_lockmutex_t
+#undef ck_unlockmutex_t
+
+#undef ck_c_initialize_args
+#undef create_mutex
+#undef destroy_mutex
+#undef lock_mutex
+#undef unlock_mutex
+#undef reserved
+
+#endif	/* CRYPTOKI_COMPAT */
+
+
+/* System dependencies.  */
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+#pragma pack(pop, cryptoki)
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif	/* PKCS11_H */
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit.exports b/krb5-1-6/src/plugins/preauth/pkinit/pkinit.exports
new file mode 100644
index 000000000..98e96c399
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit.exports
@@ -0,0 +1,2 @@
+preauthentication_client_1
+preauthentication_server_1
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit.h b/krb5-1-6/src/plugins/preauth/pkinit/pkinit.h
new file mode 100644
index 000000000..e18962e59
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit.h
@@ -0,0 +1,354 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _PKINIT_H
+#define _PKINIT_H
+
+#include <krb5/krb5.h>
+#include <krb5/preauth_plugin.h>
+#include <k5-int-pkinit.h>
+#include <profile.h>
+#include "pkinit_accessor.h"
+
+/*
+ * It is anticipated that all the special checks currently
+ * required when talking to a Longhorn server will go away
+ * by the time it is officially released and all references
+ * to the longhorn global can be removed and any code
+ * #ifdef'd with LONGHORN_BETA_COMPAT can be removed.
+ * And this #define!
+ */
+#define LONGHORN_BETA_COMPAT 1
+#ifdef LONGHORN_BETA_COMPAT
+extern int longhorn;	    /* XXX Talking to a Longhorn server? */
+#endif
+
+
+#ifndef WITHOUT_PKCS11
+#include "pkcs11.h"
+
+#define PKCS11_MODNAME "opensc-pkcs11.so"
+#define PK_SIGLEN_GUESS 1000
+#define PK_NOSLOT 999999
+#endif
+
+#define DH_PROTOCOL     1
+#define RSA_PROTOCOL    2
+
+#define TD_TRUSTED_CERTIFIERS 104
+#define TD_INVALID_CERTIFICATES 105
+#define TD_DH_PARAMETERS 109
+
+#define PKINIT_CTX_MAGIC	0x05551212
+#define PKINIT_REQ_CTX_MAGIC	0xdeadbeef
+
+#define PKINIT_DEFAULT_DH_MIN_BITS  2048
+
+/* Make pkiDebug(fmt,...) print, or not.  */
+#ifdef DEBUG
+#define pkiDebug	printf
+#else
+/* Still evaluates for side effects.  */
+static inline void pkiDebug (const char *fmt, ...) { }
+/* This is better if the compiler doesn't inline variadic functions
+   well, but gcc will warn about "left-hand operand of comma
+   expression has no effect".  Still evaluates for side effects.  */
+/* #define pkiDebug	(void) */
+#endif
+
+/* Solaris compiler doesn't grok __FUNCTION__ 
+ * hack for now.  Fix all the uses eventually. */
+#define __FUNCTION__ __func__
+
+/* Macros to deal with converting between various data types... */
+#define PADATA_TO_KRB5DATA(pad, k5d) \
+    (k5d)->length = (pad)->length; (k5d)->data = (char *)(pad)->contents;
+#define OCTETDATA_TO_KRB5DATA(octd, k5d) \
+    (k5d)->length = (octd)->length; (k5d)->data = (char *)(octd)->data;
+
+extern const krb5_octet_data dh_oid;
+
+/*
+ * notes about crypto contexts:
+ *
+ * the basic idea is that there are crypto contexts that live at
+ * both the plugin level and request level. the identity context (that
+ * keeps info about your own certs and such) is separate because
+ * it is needed at different levels for the kdc and and the client.
+ * (the kdc's identity is at the plugin level, the client's identity
+ * information could change per-request.)
+ * the identity context is meant to have the entity's cert,
+ * a list of trusted and intermediate cas, a list of crls, and any 
+ * pkcs11 information.  the req context is meant to have the
+ * received certificate and the DH related information. the plugin
+ * context is meant to have global crypto information, i.e., OIDs
+ * and constant DH parameter information.
+ */ 
+
+/*
+ * plugin crypto context should keep plugin common information, 
+ * eg., OIDs, known DHparams
+ */
+typedef struct _pkinit_plg_crypto_context *pkinit_plg_crypto_context;
+
+/*
+ * request crypto context should keep reqyest common information,
+ * eg., received credentials, DH parameters of this request
+ */
+typedef struct _pkinit_req_crypto_context *pkinit_req_crypto_context;
+
+/*
+ * identity context should keep information about credentials
+ * for the request, eg., my credentials, trusted ca certs,
+ * intermediate ca certs, crls, pkcs11 info
+ */
+typedef struct _pkinit_identity_crypto_context *pkinit_identity_crypto_context;
+
+/*
+ * this structure keeps information about the config options
+ */
+typedef struct _pkinit_plg_opts {
+    int require_eku;	    /* require EKU checking (default is true) */
+    int accept_secondary_eku;/* accept secondary EKU (default is false) */
+    int allow_upn;	    /* allow UPN-SAN instead of pkinit-SAN */
+    int dh_or_rsa;	    /* selects DH or RSA based pkinit */
+    int require_crl_checking; /* require CRL for a CA (default is false) */ 
+    int dh_min_bits;	    /* minimum DH modulus size allowed */
+} pkinit_plg_opts;
+
+/*
+ * this structure keeps options used for a given request
+ */
+typedef struct _pkinit_req_opts {
+    int require_eku;
+    int accept_secondary_eku;
+    int allow_upn;
+    int dh_or_rsa;
+    int require_crl_checking;
+    int dh_size;	    /* initial request DH modulus size (default=1024) */
+    int require_hostname_match;
+    int win2k_target;
+    int win2k_require_cksum;
+} pkinit_req_opts;
+
+/*
+ * information about identity from config file or command line
+ */
+
+#define PKINIT_ID_OPT_USER_IDENTITY	1
+#define PKINIT_ID_OPT_ANCHOR_CAS	2
+#define PKINIT_ID_OPT_INTERMEDIATE_CAS	3
+#define PKINIT_ID_OPT_CRLS		4
+#define PKINIT_ID_OPT_OCSP		5
+#define PKINIT_ID_OPT_DN_MAPPING	6   /* XXX ? */
+
+typedef struct _pkinit_identity_opts {
+    char *identity;
+    char **identity_alt;
+    char **anchors;
+    char **intermediates;
+    char **crls;
+    char *ocsp;
+    char *dn_mapping_file;
+    int  idtype;
+    char *cert_filename;
+    char *key_filename;
+#ifndef WITHOUT_PKCS11
+    char *p11_module_name;
+    CK_SLOT_ID slotid;
+    char *token_label;
+    char *cert_id_string;
+    char *cert_label;
+#endif
+} pkinit_identity_opts;
+
+
+/*
+ * Client's plugin context
+ */
+struct _pkinit_context {
+    int magic;
+    pkinit_plg_crypto_context cryptoctx;
+    pkinit_plg_opts *opts;
+    pkinit_identity_opts *idopts;
+};
+typedef struct _pkinit_context *pkinit_context;
+
+/*
+ * Client's per-request context
+ */
+struct _pkinit_req_context {
+    int magic;
+    pkinit_req_crypto_context cryptoctx;
+    pkinit_req_opts *opts;
+    pkinit_identity_crypto_context idctx;
+    pkinit_identity_opts *idopts;
+    krb5_preauthtype pa_type;
+};
+typedef struct _pkinit_kdc_context *pkinit_kdc_context;
+
+/*
+ * KDC's (per-realm) plugin context
+ */
+struct _pkinit_kdc_context {
+    int magic;
+    pkinit_plg_crypto_context cryptoctx;
+    pkinit_plg_opts *opts;
+    pkinit_identity_crypto_context idctx;
+    pkinit_identity_opts *idopts;
+    char *realmname;
+    unsigned int realmname_len;
+};
+typedef struct _pkinit_req_context *pkinit_req_context;
+
+/*
+ * KDC's per-request context
+ */
+struct _pkinit_kdc_req_context {
+    int magic;
+    pkinit_req_crypto_context cryptoctx;
+    krb5_auth_pack *rcv_auth_pack;
+    krb5_auth_pack_draft9 *rcv_auth_pack9;
+    krb5_preauthtype pa_type;
+};
+typedef struct _pkinit_kdc_req_context *pkinit_kdc_req_context;
+
+/*
+ * Functions in pkinit_lib.c
+ */ 
+
+krb5_error_code pkinit_init_req_opts(pkinit_req_opts **);
+void pkinit_fini_req_opts(pkinit_req_opts *);
+
+krb5_error_code pkinit_init_plg_opts(pkinit_plg_opts **);
+void pkinit_fini_plg_opts(pkinit_plg_opts *);
+
+krb5_error_code pkinit_init_identity_opts(pkinit_identity_opts **idopts);
+void pkinit_fini_identity_opts(pkinit_identity_opts *idopts);
+krb5_error_code pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
+					 pkinit_identity_opts **dest_opts);
+
+/*
+ * Functions in pkinit_identity.c
+ */
+char * idtype2string(int idtype);
+char * catype2string(int catype);
+
+krb5_error_code pkinit_identity_initialize
+	(krb5_context context,				/* IN */
+	 pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	 pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	 pkinit_identity_opts *idopts,			/* IN */
+	 pkinit_identity_crypto_context id_cryptoctx,	/* IN/OUT */
+	 int do_matching,				/* IN */
+	 krb5_principal princ);				/* IN (optional) */
+
+krb5_error_code pkinit_cert_matching
+	(krb5_context context,
+	pkinit_plg_crypto_context plg_cryptoctx,
+	pkinit_req_crypto_context req_cryptoctx,
+	pkinit_identity_crypto_context id_cryptoctx,
+	krb5_principal princ);
+
+/*
+ * initialization and free functions
+ */
+void init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
+void init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
+void init_krb5_reply_key_pack(krb5_reply_key_pack **in);
+void init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
+
+void init_krb5_auth_pack(krb5_auth_pack **in);
+void init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in);
+void init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
+void init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
+void init_krb5_typed_data(krb5_typed_data **in);
+void init_krb5_subject_pk_info(krb5_subject_pk_info **in);
+
+void free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
+void free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
+void free_krb5_reply_key_pack(krb5_reply_key_pack **in);
+void free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
+void free_krb5_auth_pack(krb5_auth_pack **in);
+void free_krb5_auth_pack_draft9(krb5_context, krb5_auth_pack_draft9 **in);
+void free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
+void free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
+void free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in);
+void free_krb5_trusted_ca(krb5_trusted_ca ***in);
+void free_krb5_typed_data(krb5_typed_data ***in);
+void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
+void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
+void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
+void free_krb5_subject_pk_info(krb5_subject_pk_info **in);
+krb5_error_code pkinit_copy_krb5_octet_data(krb5_octet_data *dst, const krb5_octet_data *src);
+
+
+/*
+ * Functions in pkinit_profile.c
+ */
+krb5_error_code pkinit_kdcdefault_strings
+	(krb5_context context, const char *realmname, const char *option,
+	 char ***ret_value);
+krb5_error_code pkinit_kdcdefault_string
+	(krb5_context context, const char *realmname, const char *option,
+	 char **ret_value);
+krb5_error_code pkinit_kdcdefault_boolean
+	(krb5_context context, const char *realmname, const char *option,
+	 int default_value, int *ret_value);
+krb5_error_code pkinit_kdcdefault_integer
+	(krb5_context context, const char *realmname, const char *option,
+	 int default_value, int *ret_value);
+
+
+krb5_error_code pkinit_libdefault_strings
+	(krb5_context context, const krb5_data *realm,
+	 const char *option, char ***ret_value);
+krb5_error_code pkinit_libdefault_string
+	(krb5_context context, const krb5_data *realm,
+	 const char *option, char **ret_value);
+krb5_error_code pkinit_libdefault_boolean
+	(krb5_context context, const krb5_data *realm, const char *option,
+	 int default_value, int *ret_value);
+krb5_error_code pkinit_libdefault_integer
+	(krb5_context context, const krb5_data *realm, const char *option,
+	 int default_value, int *ret_value);
+
+/*
+ * debugging functions
+ */
+void print_buffer(unsigned char *, unsigned int);
+void print_buffer_bin(unsigned char *, unsigned int, char *);
+
+/*
+ * Now get crypto function declarations
+ */
+#include "pkinit_crypto.h"
+
+#endif	/* _PKINIT_H */
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.c
new file mode 100644
index 000000000..e954ca361
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.c
@@ -0,0 +1,118 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <k5-int.h>
+#include "pkinit_accessor.h"
+
+#define DEF_FUNC_PTRS(type) \
+krb5_error_code (*k5int_encode_##type)(const type *, krb5_data **); \
+krb5_error_code (*k5int_decode_##type)(const krb5_data *, type **)
+
+#define DEF_FUNC_PTRS_ARRAY(type) \
+krb5_error_code (*k5int_encode_##type)(const type **, krb5_data **); \
+krb5_error_code (*k5int_decode_##type)(const krb5_data *, type ***)
+
+DEF_FUNC_PTRS(krb5_auth_pack);
+DEF_FUNC_PTRS(krb5_auth_pack_draft9);
+DEF_FUNC_PTRS(krb5_kdc_dh_key_info);
+DEF_FUNC_PTRS(krb5_pa_pk_as_rep);
+DEF_FUNC_PTRS(krb5_pa_pk_as_rep_draft9);
+DEF_FUNC_PTRS(krb5_pa_pk_as_req);
+DEF_FUNC_PTRS(krb5_pa_pk_as_req_draft9);
+DEF_FUNC_PTRS(krb5_reply_key_pack);
+DEF_FUNC_PTRS(krb5_reply_key_pack_draft9);
+DEF_FUNC_PTRS_ARRAY(krb5_typed_data);
+
+/* special cases... */
+krb5_error_code (*k5int_decode_krb5_principal_name)
+	(const krb5_data *, krb5_principal_data **);
+
+krb5_error_code (*k5int_encode_krb5_td_dh_parameters)
+	(const krb5_algorithm_identifier **, krb5_data **code);
+krb5_error_code (*k5int_decode_krb5_td_dh_parameters)
+	(const krb5_data *, krb5_algorithm_identifier ***);
+
+krb5_error_code (*k5int_encode_krb5_td_trusted_certifiers)
+	(const krb5_external_principal_identifier **, krb5_data **code);
+krb5_error_code (*k5int_decode_krb5_td_trusted_certifiers)
+	(const krb5_data *, krb5_external_principal_identifier ***);
+
+krb5_error_code (*k5int_decode_krb5_as_req)
+	(const krb5_data *output, krb5_kdc_req **rep);
+krb5_error_code (*k5int_encode_krb5_kdc_req_body)
+	(const krb5_kdc_req *rep, krb5_data **code);
+void KRB5_CALLCONV (*k5int_krb5_free_kdc_req)
+	(krb5_context, krb5_kdc_req * );
+void (*k5int_set_prompt_types)
+	(krb5_context, krb5_prompt_type *);
+krb5_error_code (*k5int_encode_krb5_authdata_elt)
+	(const krb5_authdata *rep, krb5_data **code);
+
+
+
+/*
+ * Grab internal function pointers from the krb5int_accessor
+ * structure and make them available
+ */
+krb5_error_code
+pkinit_accessor_init(void)
+{
+    krb5_error_code retval;
+    krb5int_access k5int;
+
+    retval = krb5int_accessor(&k5int, KRB5INT_ACCESS_VERSION);
+    if (retval)
+	return retval;
+#define SET_PTRS(type) \
+k5int_encode_##type = k5int.encode_##type; \
+k5int_decode_##type = k5int.decode_##type;
+
+    SET_PTRS(krb5_auth_pack);
+    SET_PTRS(krb5_auth_pack_draft9);
+    SET_PTRS(krb5_kdc_dh_key_info);
+    SET_PTRS(krb5_pa_pk_as_rep);
+    SET_PTRS(krb5_pa_pk_as_rep_draft9);
+    SET_PTRS(krb5_pa_pk_as_req);
+    SET_PTRS(krb5_pa_pk_as_req_draft9);
+    SET_PTRS(krb5_reply_key_pack);
+    SET_PTRS(krb5_reply_key_pack_draft9);
+    SET_PTRS(krb5_td_dh_parameters);
+    SET_PTRS(krb5_td_trusted_certifiers);
+    SET_PTRS(krb5_typed_data);
+
+    /* special cases... */
+    k5int_decode_krb5_principal_name = k5int.decode_krb5_principal_name;
+    k5int_decode_krb5_as_req = k5int.decode_krb5_as_req;
+    k5int_encode_krb5_kdc_req_body = k5int.encode_krb5_kdc_req_body;
+    k5int_krb5_free_kdc_req = k5int.krb5_free_kdc_req;
+    k5int_set_prompt_types = k5int.krb5int_set_prompt_types;
+    k5int_encode_krb5_authdata_elt = k5int.encode_krb5_authdata_elt;
+    return 0;
+}
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.h b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.h
new file mode 100644
index 000000000..ba82533c8
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_accessor.h
@@ -0,0 +1,83 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _PKINIT_ACCESSOR_H
+#define _PKINIT_ACCESSOR_H
+
+/*
+ * Function prototypes
+ */
+krb5_error_code pkinit_accessor_init(void);
+
+#define DEF_EXT_FUNC_PTRS(type) \
+extern krb5_error_code (*k5int_encode_##type)(const type *, krb5_data **); \
+extern krb5_error_code (*k5int_decode_##type)(const krb5_data *, type **)
+
+#define DEF_EXT_FUNC_PTRS_ARRAY(type) \
+extern krb5_error_code (*k5int_encode_##type)(const type **, krb5_data **); \
+extern krb5_error_code (*k5int_decode_##type)(const krb5_data *, type ***)
+
+DEF_EXT_FUNC_PTRS(krb5_auth_pack);
+DEF_EXT_FUNC_PTRS(krb5_auth_pack_draft9);
+DEF_EXT_FUNC_PTRS(krb5_kdc_dh_key_info);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_rep);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_rep_draft9);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_req);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_req_draft9);
+DEF_EXT_FUNC_PTRS(krb5_reply_key_pack);
+DEF_EXT_FUNC_PTRS(krb5_reply_key_pack_draft9);
+DEF_EXT_FUNC_PTRS_ARRAY(krb5_typed_data);
+
+/* special cases... */
+extern krb5_error_code (*k5int_decode_krb5_principal_name)
+	(const krb5_data *, krb5_principal_data **);
+
+extern krb5_error_code (*k5int_encode_krb5_td_dh_parameters)
+	(const krb5_algorithm_identifier **, krb5_data **code);
+extern krb5_error_code (*k5int_decode_krb5_td_dh_parameters)
+	(const krb5_data *, krb5_algorithm_identifier ***);
+
+extern krb5_error_code (*k5int_encode_krb5_td_trusted_certifiers)
+	(const krb5_external_principal_identifier **, krb5_data **code);
+extern krb5_error_code (*k5int_decode_krb5_td_trusted_certifiers)
+	(const krb5_data *, krb5_external_principal_identifier ***);
+
+extern krb5_error_code (*k5int_decode_krb5_as_req)
+	(const krb5_data *output, krb5_kdc_req **rep);
+extern krb5_error_code (*k5int_encode_krb5_kdc_req_body)
+	(const krb5_kdc_req *rep, krb5_data **code);
+extern void KRB5_CALLCONV (*k5int_krb5_free_kdc_req)
+	(krb5_context, krb5_kdc_req * );
+extern void (*k5int_set_prompt_types)
+	(krb5_context, krb5_prompt_type *);
+extern krb5_error_code (*k5int_encode_krb5_authdata_elt)
+	(const krb5_authdata *rep, krb5_data **code);
+
+#endif /* _PKINIT_ACCESSOR_H */
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_clnt.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_clnt.c
new file mode 100644
index 000000000..0d6da4dc5
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_clnt.c
@@ -0,0 +1,1492 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+#include "pkinit.h"
+
+#ifdef LONGHORN_BETA_COMPAT
+/*
+ * It is anticipated that all the special checks currently
+ * required when talking to a Longhorn server will go away
+ * by the time it is officially released and all references
+ * to the longhorn global can be removed and any code
+ * #ifdef'd with LONGHORN_BETA_COMPAT can be removed.
+ *
+ * Current testing (20070620) is against a patched Beta 3
+ * version of Longhorn.  Most, if not all, problems should
+ * be fixed in SP1 of Longhorn.
+ */
+int longhorn = 0;	/* Talking to a Longhorn server? */
+#endif
+
+krb5_error_code pkinit_client_process
+	(krb5_context context, void *plugin_context, void *request_context,
+		krb5_get_init_creds_opt *gic_opt,
+		preauth_get_client_data_proc get_data_proc,
+		struct _krb5_preauth_client_rock *rock,
+		krb5_kdc_req * request, krb5_data *encoded_request_body,
+		krb5_data *encoded_previous_request, krb5_pa_data *in_padata,
+		krb5_prompter_fct prompter, void *prompter_data,
+		preauth_get_as_key_proc gak_fct, void *gak_data,
+		krb5_data * salt, krb5_data * s2kparams,
+		krb5_keyblock * as_key, krb5_pa_data *** out_padata);
+
+krb5_error_code pkinit_client_tryagain
+	(krb5_context context, void *plugin_context, void *request_context,
+		krb5_get_init_creds_opt *gic_opt,
+		preauth_get_client_data_proc get_data_proc,
+		struct _krb5_preauth_client_rock *rock,
+		krb5_kdc_req * request, krb5_data *encoded_request_body,
+		krb5_data *encoded_previous_request,
+		krb5_pa_data *in_padata, krb5_error *err_reply,
+		krb5_prompter_fct prompter, void *prompter_data,
+		preauth_get_as_key_proc gak_fct, void *gak_data,
+		krb5_data * salt, krb5_data * s2kparams,
+		krb5_keyblock * as_key, krb5_pa_data *** out_padata);
+
+void pkinit_client_req_init
+	(krb5_context contex, void *plugin_context, void **request_context);
+
+void pkinit_client_req_fini
+	(krb5_context context, void *plugin_context, void *request_context);
+
+krb5_error_code pa_pkinit_gen_req
+	(krb5_context context, pkinit_context plgctx,
+		pkinit_req_context reqctx, krb5_kdc_req * request,
+		krb5_pa_data * in_padata, krb5_pa_data *** out_padata,
+		krb5_prompter_fct prompter, void *prompter_data,
+		krb5_get_init_creds_opt *gic_opt);
+
+krb5_error_code pkinit_as_req_create
+	(krb5_context context, pkinit_context plgctx,
+		pkinit_req_context reqctx, krb5_timestamp ctsec,
+		krb5_int32 cusec, krb5_ui_4 nonce,
+		const krb5_checksum * cksum, krb5_principal server,
+		krb5_data ** as_req);
+
+krb5_error_code pkinit_as_rep_parse
+	(krb5_context context, pkinit_context plgctx,
+		pkinit_req_context reqctx, krb5_preauthtype pa_type,
+		krb5_kdc_req * request, const krb5_data * as_rep,
+		krb5_keyblock * key_block, krb5_enctype etype, krb5_data *);
+
+krb5_error_code pa_pkinit_parse_rep
+	(krb5_context context, pkinit_context plgctx,
+		pkinit_req_context reqcxt, krb5_kdc_req * request,
+		krb5_pa_data * in_padata, krb5_enctype etype,
+		krb5_keyblock * as_key, krb5_data *);
+
+static int pkinit_client_plugin_init(krb5_context context, void **blob);
+static void pkinit_client_plugin_fini(krb5_context context, void *blob);
+
+krb5_error_code
+pa_pkinit_gen_req(krb5_context context,
+		  pkinit_context plgctx,
+		  pkinit_req_context reqctx,
+		  krb5_kdc_req * request,
+		  krb5_pa_data * in_padata,
+		  krb5_pa_data *** out_padata,
+		  krb5_prompter_fct prompter,
+		  void *prompter_data,
+		  krb5_get_init_creds_opt *gic_opt)
+{
+
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    krb5_data *out_data = NULL;
+    krb5_timestamp ctsec = 0;
+    krb5_int32 cusec = 0;
+    krb5_ui_4 nonce = 0;
+    krb5_checksum cksum;
+    krb5_data *der_req = NULL;
+    krb5_pa_data **return_pa_data = NULL;
+
+    cksum.contents = NULL;
+    reqctx->pa_type = in_padata->pa_type;
+
+    pkiDebug("kdc_options = 0x%x  till = %d\n",
+	     request->kdc_options, request->till);
+    /* If we don't have a client, we're done */
+    if (request->client == NULL) {
+	pkiDebug("No request->client; aborting PKINIT\n");
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    retval = pkinit_get_kdc_cert(context, plgctx->cryptoctx, reqctx->cryptoctx,
+				 reqctx->idctx, request->server);
+    if (retval) {
+	pkiDebug("pkinit_get_kdc_cert returned %d\n", retval);
+	goto cleanup;
+    }
+
+    /* checksum of the encoded KDC-REQ-BODY */
+    retval = k5int_encode_krb5_kdc_req_body(request, &der_req);
+    if (retval) {
+	pkiDebug("encode_krb5_kdc_req_body returned %d\n", (int) retval);
+	goto cleanup;
+    }
+
+    retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0,
+				  der_req, &cksum);
+    if (retval)
+	goto cleanup;
+#ifdef DEBUG_CKSUM
+    pkiDebug("calculating checksum on buf size (%d)\n", der_req->length);
+    print_buffer(der_req->data, der_req->length);
+#endif
+
+    retval = krb5_us_timeofday(context, &ctsec, &cusec);
+    if (retval)
+	goto cleanup;
+
+    /* XXX PKINIT RFC says that nonce in PKAuthenticator doesn't have be the
+     * same as in the AS_REQ. However, if we pick a different nonce, then we
+     * need to remember that info when AS_REP is returned. I'm choosing to
+     * reuse the AS_REQ nonce.
+     */
+    nonce = request->nonce;
+
+    retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec,
+				  nonce, &cksum, request->server, &out_data);
+    if (retval || !out_data->length) {
+	pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n",
+		 (int) retval);
+	goto cleanup;
+    }
+    retval = ENOMEM;
+    /*
+     * The most we'll return is two pa_data, normally just one.
+     * We need to make room for the NULL terminator.
+     */
+    return_pa_data = (krb5_pa_data **) malloc(3 * sizeof(krb5_pa_data *));
+    if (return_pa_data == NULL)
+	goto cleanup;
+
+    return_pa_data[1] = NULL;	/* in case of an early trip to cleanup */
+    return_pa_data[2] = NULL;	/* Terminate the list */
+
+    return_pa_data[0] = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
+    if (return_pa_data[0] == NULL)
+	goto cleanup;
+
+    return_pa_data[1] = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
+    if (return_pa_data[1] == NULL)
+	goto cleanup;
+
+    return_pa_data[0]->magic = KV5M_PA_DATA;
+
+    if (in_padata->pa_type == KRB5_PADATA_PK_AS_REQ_OLD)
+	return_pa_data[0]->pa_type = KRB5_PADATA_PK_AS_REP_OLD;
+    else
+	return_pa_data[0]->pa_type = in_padata->pa_type;
+    return_pa_data[0]->length = out_data->length;
+    return_pa_data[0]->contents = (krb5_octet *) out_data->data;
+
+#ifdef LONGHORN_BETA_COMPAT
+    /*
+     * LH Beta 3 requires the extra pa-data, even for RFC requests,
+     * in order to get the Checksum rather than a Nonce in the reply.
+     * This can be removed when LH SP1 is released.
+     */
+    if ((return_pa_data[0]->pa_type == KRB5_PADATA_PK_AS_REP_OLD
+	&& reqctx->opts->win2k_require_cksum) || (longhorn == 1)) {
+#else
+    if ((return_pa_data[0]->pa_type == KRB5_PADATA_PK_AS_REP_OLD
+	&& reqctx->opts->win2k_require_cksum)) {
+#endif
+	return_pa_data[1]->pa_type = 132;
+	return_pa_data[1]->length = 0;
+	return_pa_data[1]->contents = NULL;
+    } else {
+	free(return_pa_data[1]);
+	return_pa_data[1] = NULL;   /* Move the list terminator */
+    }
+    *out_padata = return_pa_data;
+    retval = 0;
+
+  cleanup:
+    if (der_req != NULL)
+	krb5_free_data(context, der_req);
+
+    if (out_data != NULL)
+	free(out_data);
+
+    if (retval) {
+	if (return_pa_data) {
+	    if (return_pa_data[0] != NULL)
+		free(return_pa_data[0]);
+	    if (return_pa_data[1] != NULL)
+		free(return_pa_data[1]);
+	    free(return_pa_data);
+	}
+	if (out_data) {
+	    free(out_data->data);
+	    free(out_data);
+	}
+    }
+    return retval;
+}
+
+krb5_error_code
+pkinit_as_req_create(krb5_context context,
+		     pkinit_context plgctx,
+		     pkinit_req_context reqctx,
+		     krb5_timestamp ctsec,
+		     krb5_int32 cusec,
+		     krb5_ui_4 nonce,
+		     const krb5_checksum * cksum,
+		     krb5_principal server,
+		     krb5_data ** as_req)
+{
+    krb5_error_code retval = ENOMEM;
+    krb5_subject_pk_info *info = NULL;
+    krb5_data *coded_auth_pack = NULL;
+    krb5_auth_pack *auth_pack = NULL;
+    krb5_pa_pk_as_req *req = NULL;
+    krb5_auth_pack_draft9 *auth_pack9 = NULL;
+    krb5_pa_pk_as_req_draft9 *req9 = NULL;
+    int protocol = reqctx->opts->dh_or_rsa;
+
+    pkiDebug("pkinit_as_req_create pa_type = %d\n", reqctx->pa_type);
+
+    /* Create the authpack */
+    switch((int)reqctx->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    protocol = RSA_PROTOCOL;
+	    init_krb5_auth_pack_draft9(&auth_pack9);
+	    if (auth_pack9 == NULL)
+		goto cleanup;
+	    auth_pack9->pkAuthenticator.ctime = ctsec;
+	    auth_pack9->pkAuthenticator.cusec = cusec;
+	    auth_pack9->pkAuthenticator.nonce = nonce;
+	    auth_pack9->pkAuthenticator.kdcName = server;
+	    auth_pack9->pkAuthenticator.kdcRealm.magic = 0;
+	    auth_pack9->pkAuthenticator.kdcRealm.data =
+					(unsigned char *)server->realm.data;
+	    auth_pack9->pkAuthenticator.kdcRealm.length = server->realm.length;
+	    free(cksum->contents);
+	    break;
+	case KRB5_PADATA_PK_AS_REQ:
+	    init_krb5_subject_pk_info(&info);
+	    if (info == NULL)
+		goto cleanup;
+	    init_krb5_auth_pack(&auth_pack);
+	    if (auth_pack == NULL)
+		goto cleanup;
+	    auth_pack->pkAuthenticator.ctime = ctsec;
+	    auth_pack->pkAuthenticator.cusec = cusec;
+	    auth_pack->pkAuthenticator.nonce = nonce;
+	    auth_pack->pkAuthenticator.paChecksum = *cksum;
+	    auth_pack->clientDHNonce.length = 0;
+	    auth_pack->clientPublicValue = info;
+
+	    /* add List of CMS algorithms */
+	    retval = create_krb5_supportedCMSTypes(context, plgctx->cryptoctx,
+			reqctx->cryptoctx, reqctx->idctx, 
+			&auth_pack->supportedCMSTypes);
+	    if (retval)
+		goto cleanup;
+	    break;
+	default:
+	    pkiDebug("as_req: unrecognized pa_type = %d\n",
+		    (int)reqctx->pa_type);
+	    retval = -1;
+	    goto cleanup;
+    }
+
+    switch(protocol) {
+	case DH_PROTOCOL:
+	    pkiDebug("as_req: DH key transport algorithm\n");
+	    retval = pkinit_copy_krb5_octet_data(&info->algorithm.algorithm, &dh_oid);
+	    if (retval) {
+		pkiDebug("failed to copy dh_oid\n");
+		goto cleanup;
+	    }
+
+	    /* create client-side DH keys */
+	    if ((retval = client_create_dh(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, reqctx->idctx, reqctx->opts->dh_size,
+		    &info->algorithm.parameters.data,
+		    &info->algorithm.parameters.length,
+		    &info->subjectPublicKey.data,
+		    &info->subjectPublicKey.length)) != 0) {
+		pkiDebug("failed to create dh parameters\n");
+		goto cleanup;
+	    }
+	    break;
+	case RSA_PROTOCOL:
+	    pkiDebug("as_req: RSA key transport algorithm\n");
+	    switch((int)reqctx->pa_type) {
+		case KRB5_PADATA_PK_AS_REQ_OLD:
+		    auth_pack9->clientPublicValue = NULL;
+		    break;
+		case KRB5_PADATA_PK_AS_REQ:
+		    free_krb5_subject_pk_info(&info);
+		    auth_pack->clientPublicValue = NULL;
+		    break;
+	    }
+	    break;
+	default:
+	    pkiDebug("as_req: unknown key transport protocol %d\n",
+		    protocol);
+	    retval = -1;
+	    goto cleanup;
+    }
+
+    /* Encode the authpack */
+    switch((int)reqctx->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    retval = k5int_encode_krb5_auth_pack(auth_pack, &coded_auth_pack);
+	    break;
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    retval = k5int_encode_krb5_auth_pack_draft9(auth_pack9,
+							&coded_auth_pack);
+	    break;
+    }
+    if (retval) {
+	pkiDebug("failed to encode the AuthPack %d\n", retval);
+	goto cleanup;
+    }
+#ifdef DEBUG_ASN1
+    print_buffer_bin((unsigned char *)coded_auth_pack->data,
+		     coded_auth_pack->length,
+		     "/tmp/client_auth_pack");
+#endif
+
+    /* create PKCS7 object from authpack */
+    switch((int)reqctx->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    init_krb5_pa_pk_as_req(&req);
+	    if (req == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    retval = cms_signeddata_create(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_CLIENT, 1,
+		(unsigned char *)coded_auth_pack->data, coded_auth_pack->length,
+		&req->signedAuthPack.data, &req->signedAuthPack.length);
+#ifdef DEBUG_ASN1
+	    print_buffer_bin((unsigned char *)req->signedAuthPack.data,
+			     req->signedAuthPack.length,
+			     "/tmp/client_signed_data");
+#endif
+	    break;
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    init_krb5_pa_pk_as_req_draft9(&req9);
+	    if (req9 == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    retval = cms_signeddata_create(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_DRAFT9, 1,
+		(unsigned char *)coded_auth_pack->data, coded_auth_pack->length,
+		&req9->signedAuthPack.data, &req9->signedAuthPack.length);
+	    break;
+#ifdef DEBUG_ASN1
+	    print_buffer_bin((unsigned char *)req9->signedAuthPack.data,
+			     req9->signedAuthPack.length,
+			     "/tmp/client_signed_data_draft9");
+#endif
+    }
+    krb5_free_data(context, coded_auth_pack);
+    if (retval) {
+	pkiDebug("failed to create pkcs7 signed data\n");
+	goto cleanup;
+    }
+
+    /* create a list of trusted CAs */
+    switch((int)reqctx->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    retval = create_krb5_trustedCertifiers(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, reqctx->idctx, &req->trustedCertifiers);
+	    if (retval)
+		goto cleanup;
+	    retval = create_issuerAndSerial(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, reqctx->idctx, &req->kdcPkId.data,
+		&req->kdcPkId.length);
+	    if (retval)
+		goto cleanup;
+
+	    /* Encode the as-req */
+	    retval = k5int_encode_krb5_pa_pk_as_req(req, as_req);
+	    break;
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+#if 0
+	    /* W2K3 KDC doesn't like this */
+	    retval = create_krb5_trustedCas(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, reqctx->idctx, 1, &req9->trustedCertifiers);
+	    if (retval)
+		goto cleanup;
+
+#endif
+	    retval = create_issuerAndSerial(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, reqctx->idctx, &req9->kdcCert.data,
+		&req9->kdcCert.length);
+	    if (retval)
+		goto cleanup;
+	    /* Encode the as-req */
+	    retval = k5int_encode_krb5_pa_pk_as_req_draft9(req9, as_req);
+	    break;
+    }
+#ifdef DEBUG_ASN1
+    if (!retval)
+	print_buffer_bin((unsigned char *)(*as_req)->data, (*as_req)->length,
+			 "/tmp/client_as_req");
+#endif
+
+cleanup:
+    switch((int)reqctx->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    free_krb5_auth_pack(&auth_pack);
+	    free_krb5_pa_pk_as_req(&req);
+	    break;
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    free_krb5_pa_pk_as_req_draft9(&req9);
+	    free(auth_pack9);
+	    break;
+    }
+	
+
+    pkiDebug("pkinit_as_req_create retval=%d\n", (int) retval);
+
+    return retval;
+}
+
+krb5_error_code
+pa_pkinit_parse_rep(krb5_context context,
+		    pkinit_context plgctx,
+		    pkinit_req_context reqctx,
+		    krb5_kdc_req * request,
+		    krb5_pa_data * in_padata,
+		    krb5_enctype etype,
+		    krb5_keyblock * as_key,
+		    krb5_data *encoded_request)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    krb5_data asRep = { 0, 0, NULL};
+
+    /*
+     * One way or the other - success or failure - no other PA systems can
+     * work if the server sent us a PKINIT reply, since only we know how to
+     * decrypt the key.
+     */
+    if ((in_padata == NULL) || (in_padata->length == 0)) {
+	pkiDebug("pa_pkinit_parse_rep: no in_padata\n");
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    asRep.data = (char *) in_padata->contents;
+    asRep.length = in_padata->length;
+
+    retval =
+	pkinit_as_rep_parse(context, plgctx, reqctx, in_padata->pa_type,
+			    request, &asRep, as_key, etype, encoded_request);
+    if (retval) {
+	pkiDebug("pkinit_as_rep_parse returned %d (%s)\n",
+		 retval, error_message(retval));
+	goto cleanup;
+    }
+
+    retval = 0;
+
+cleanup:
+
+    return retval;
+}
+
+static krb5_error_code
+verify_kdc_san(krb5_context context,
+	       pkinit_context plgctx,
+	       pkinit_req_context reqctx,
+	       krb5_principal kdcprinc,
+	       int *valid_san,
+	       int *need_eku_checking)
+{
+    krb5_error_code retval;
+    char **certhosts = NULL, **cfghosts = NULL;
+    krb5_principal *princs = NULL;
+    unsigned char ***get_dns;
+    int i, j;
+
+    *valid_san = 0;
+    *need_eku_checking = 1;
+
+    retval = pkinit_libdefault_strings(context,
+				       krb5_princ_realm(context, kdcprinc), 
+				       "pkinit_kdc_hostname",
+				       &cfghosts);
+    if (retval || cfghosts == NULL) {
+	pkiDebug("%s: No pkinit_kdc_hostname values found in config file\n",
+		 __FUNCTION__);
+	get_dns = NULL;
+    } else {
+	pkiDebug("%s: pkinit_kdc_hostname values found in config file\n",
+		 __FUNCTION__);
+	get_dns = (unsigned char ***)&certhosts;
+    }
+
+    retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
+				       reqctx->cryptoctx, reqctx->idctx,
+				       &princs, NULL, get_dns);
+    if (retval) {
+	pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+	retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+	goto out;
+    }
+#if 0
+    retval = call_san_checking_plugins(context, plgctx, reqctx, idctx,
+				       princs, hosts, &plugin_decision,
+				       need_eku_checking);
+    pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
+	     __FUNCTION__);
+    if (retval) {
+	retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+	goto out;
+    }
+    pkiDebug("%s: call_san_checking_plugins() returned decision %d and "
+	     "need_eku_checking %d\n",
+	     __FUNCTION__, plugin_decision, *need_eku_checking);
+    if (plugin_decision != NO_DECISION) {
+	retval = plugin_decision;
+	goto out;
+    }
+#endif
+
+    pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__);
+    for (i = 0; princs != NULL && princs[i] != NULL; i++) {
+	if (krb5_principal_compare(context, princs[i], kdcprinc)) {
+	    pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
+	    *valid_san = 1;
+	    *need_eku_checking = 0;
+	    retval = 0;
+	    goto out;
+	}
+    }
+    pkiDebug("%s: no pkinit san match found\n", __FUNCTION__);
+
+    if (certhosts == NULL) {
+	pkiDebug("%s: no certhosts (or we wouldn't accept them anyway)\n",
+		 __FUNCTION__);
+	retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+	goto out;
+    }
+
+    for (i = 0; certhosts[i] != NULL; i++) {
+	for (j = 0; cfghosts != NULL && cfghosts[j] != NULL; j++) {
+	    pkiDebug("%s: comparing cert name '%s' with config name '%s'\n",
+		     __FUNCTION__, certhosts[i], cfghosts[j]);
+	    if (strcmp(certhosts[i], cfghosts[j]) == 0) {
+		pkiDebug("%s: we have a dnsName match\n", __FUNCTION__);
+		*valid_san = 1;
+		retval = 0;
+		goto out;
+	    }
+	}
+    }
+    pkiDebug("%s: no dnsName san match found\n", __FUNCTION__);
+
+    /* We found no match */
+    retval = 0;
+
+out:
+    if (princs != NULL) {
+	for (i = 0; princs[i] != NULL; i++)
+	    krb5_free_principal(context, princs[i]);
+	free(princs);
+    }
+    if (certhosts != NULL) {
+	for (i = 0; certhosts[i] != NULL; i++)
+	    free(certhosts[i]);
+	free(certhosts);
+    }
+    if (cfghosts != NULL)
+	profile_free_list(cfghosts);
+
+    pkiDebug("%s: returning retval %d, valid_san %d, need_eku_checking %d\n",
+	     __FUNCTION__, retval, *valid_san, *need_eku_checking);
+    return retval;
+}
+ 
+static krb5_error_code
+verify_kdc_eku(krb5_context context,
+	       pkinit_context plgctx,
+	       pkinit_req_context reqctx,
+	       int *eku_accepted)
+{
+    krb5_error_code retval;
+
+    *eku_accepted = 0;
+
+    if (reqctx->opts->require_eku == 0) {
+	pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__);
+	*eku_accepted = 1;
+	retval = 0;
+	goto out;
+    }
+    retval = crypto_check_cert_eku(context, plgctx->cryptoctx,
+				   reqctx->cryptoctx, reqctx->idctx,
+				   1, /* kdc cert */
+				   reqctx->opts->accept_secondary_eku,
+				   eku_accepted);
+    if (retval) {
+	pkiDebug("%s: Error from crypto_check_cert_eku %d (%s)\n",
+		 __FUNCTION__, retval, error_message(retval));
+	goto out;
+    }
+
+out:
+    pkiDebug("%s: returning retval %d, eku_accepted %d\n",
+	     __FUNCTION__, retval, *eku_accepted);
+    return retval;
+}
+
+/*
+ * Parse PA-PK-AS-REP message. Optionally evaluates the message's
+ * certificate chain.
+ * Optionally returns various components.
+ */
+krb5_error_code
+pkinit_as_rep_parse(krb5_context context,
+		    pkinit_context plgctx,
+  		    pkinit_req_context reqctx,
+		    krb5_preauthtype pa_type,
+		    krb5_kdc_req *request,
+		    const krb5_data *as_rep,
+		    krb5_keyblock *key_block,
+		    krb5_enctype etype,
+		    krb5_data *encoded_request)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    krb5_pa_pk_as_rep *kdc_reply = NULL;
+    krb5_kdc_dh_key_info *kdc_dh = NULL;
+    krb5_reply_key_pack *key_pack = NULL;
+    krb5_reply_key_pack_draft9 *key_pack9 = NULL;
+    krb5_octet_data dh_data = { 0, 0, NULL };
+    unsigned char *client_key = NULL, *kdc_hostname = NULL;
+    unsigned int client_key_len = 0;
+    krb5_checksum cksum = {0, 0, 0, NULL};
+    krb5_data k5data;
+    int valid_san = 0;
+    int valid_eku = 0;
+    int need_eku_checking = 1;
+
+    assert((as_rep != NULL) && (key_block != NULL));
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin((unsigned char *)as_rep->data, as_rep->length,
+		     "/tmp/client_as_rep");
+#endif
+
+    if ((retval = k5int_decode_krb5_pa_pk_as_rep(as_rep, &kdc_reply))) {
+	pkiDebug("decode_krb5_as_rep failed %d\n", retval);
+	return retval;
+    }
+
+    switch(kdc_reply->choice) {
+	case choice_pa_pk_as_rep_dhInfo:
+	    pkiDebug("as_rep: DH key transport algorithm\n");
+#ifdef DEBUG_ASN1
+    print_buffer_bin(kdc_reply->u.dh_Info.dhSignedData.data,
+	kdc_reply->u.dh_Info.dhSignedData.length, "/tmp/client_kdc_signeddata");
+#endif
+	    if ((retval = cms_signeddata_verify(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_SERVER,
+		    reqctx->opts->require_crl_checking,
+		    kdc_reply->u.dh_Info.dhSignedData.data,
+		    kdc_reply->u.dh_Info.dhSignedData.length,
+		    &dh_data.data, &dh_data.length, NULL, NULL)) != 0) {
+		pkiDebug("failed to verify pkcs7 signed data\n");
+		goto cleanup;
+	    }
+
+	    break;
+	case choice_pa_pk_as_rep_encKeyPack:
+	    pkiDebug("as_rep: RSA key transport algorithm\n");
+	    if ((retval = cms_envelopeddata_verify(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, reqctx->idctx, pa_type,
+		    reqctx->opts->require_crl_checking,
+		    kdc_reply->u.encKeyPack.data,
+		    kdc_reply->u.encKeyPack.length,
+		    &dh_data.data, &dh_data.length)) != 0) {
+		pkiDebug("failed to verify pkcs7 enveloped data\n");
+		goto cleanup;
+	    }
+	    break;
+	default:
+	    pkiDebug("unknown as_rep type %d\n", kdc_reply->choice);
+	    retval = -1;
+	    goto cleanup;
+    }
+
+    retval = verify_kdc_san(context, plgctx, reqctx, request->server,
+			    &valid_san, &need_eku_checking);
+    if (retval)
+	    goto cleanup;
+    if (!valid_san) {
+	pkiDebug("%s: did not find an acceptable SAN in KDC certificate\n",
+		 __FUNCTION__);
+	retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+	goto cleanup;
+    }
+
+    if (need_eku_checking) {
+	retval = verify_kdc_eku(context, plgctx, reqctx, 
+				&valid_eku);
+	if (retval)
+	    goto cleanup;
+	if (!valid_eku) {
+	    pkiDebug("%s: did not find an acceptable EKU in KDC certificate\n",
+		     __FUNCTION__);
+	    retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+	    goto cleanup;
+	}
+    } else 
+	pkiDebug("%s: skipping EKU check\n", __FUNCTION__);
+
+    OCTETDATA_TO_KRB5DATA(&dh_data, &k5data);
+
+    switch(kdc_reply->choice) {
+	case choice_pa_pk_as_rep_dhInfo:
+#ifdef DEBUG_ASN1
+	    print_buffer_bin(dh_data.data, dh_data.length,
+			     "/tmp/client_dh_key");
+#endif
+	    if ((retval = k5int_decode_krb5_kdc_dh_key_info(&k5data,
+		    &kdc_dh)) != 0) {
+		pkiDebug("failed to decode kdc_dh_key_info\n");
+		goto cleanup;
+	    }
+
+	    /* client after KDC reply */
+	    if ((retval = client_process_dh(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, reqctx->idctx,
+		    kdc_dh->subjectPublicKey.data,
+		    kdc_dh->subjectPublicKey.length,
+		    &client_key, &client_key_len)) != 0) {
+		pkiDebug("failed to process dh params\n");
+		goto cleanup;
+	    }
+
+	    retval = pkinit_octetstring2key(context, etype, client_key,
+					  client_key_len, key_block);
+	    if (retval) {
+		pkiDebug("failed to create key pkinit_octetstring2key %s\n",
+			 error_message(retval));
+		goto cleanup;
+	    }
+
+	    break;
+	case choice_pa_pk_as_rep_encKeyPack:
+#ifdef DEBUG_ASN1
+	    print_buffer_bin(dh_data.data, dh_data.length,
+			     "/tmp/client_key_pack");
+#endif
+	    if ((retval = k5int_decode_krb5_reply_key_pack(&k5data,
+		    &key_pack)) != 0) {
+		pkiDebug("failed to decode reply_key_pack\n");
+#ifdef LONGHORN_BETA_COMPAT
+    /*
+     * LH Beta 3 requires the extra pa-data, even for RFC requests,
+     * in order to get the Checksum rather than a Nonce in the reply.
+     * This can be removed when LH SP1 is released.
+     */
+		if (pa_type == KRB5_PADATA_PK_AS_REP && longhorn == 0)
+#else
+		if (pa_type == KRB5_PADATA_PK_AS_REP)
+#endif
+		    goto cleanup;
+		else {
+		    if ((retval =
+			k5int_decode_krb5_reply_key_pack_draft9(&k5data,
+							  &key_pack9)) != 0) {
+			pkiDebug("failed to decode reply_key_pack_draft9\n");
+			goto cleanup;
+		    }
+		    pkiDebug("decode reply_key_pack_draft9\n");
+		    if (key_pack9->nonce != request->nonce) {
+			pkiDebug("nonce in AS_REP=%d doesn't match AS_REQ=%d\n",				 key_pack9->nonce, request->nonce);
+			retval = -1;
+			goto cleanup;
+		    }
+		    krb5_copy_keyblock_contents(context, &key_pack9->replyKey,
+						key_block);
+		    break;
+		}
+	    }
+	    /*
+	     * This is hack but Windows sends back SHA1 checksum
+	     * with checksum type of 14. There is currently no
+	     * checksum type of 14 defined.
+	     */
+	    if (key_pack->asChecksum.checksum_type == 14)
+		key_pack->asChecksum.checksum_type = CKSUMTYPE_NIST_SHA;
+	    retval = krb5_c_make_checksum(context,
+					  key_pack->asChecksum.checksum_type,
+					  &key_pack->replyKey,
+					  KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+					  encoded_request, &cksum);
+	    if (retval) {
+		pkiDebug("failed to make a checksum\n");
+		goto cleanup;
+	    }
+
+	    if ((cksum.length != key_pack->asChecksum.length) ||
+		memcmp(cksum.contents, key_pack->asChecksum.contents,
+			cksum.length)) {
+		pkiDebug("failed to match the checksums\n");
+#ifdef DEBUG_CKSUM
+	    pkiDebug("calculating checksum on buf size (%d)\n",
+		     encoded_request->length);
+	    print_buffer(encoded_request->data, encoded_request->length);
+	    pkiDebug("encrypting key (%d)\n", key_pack->replyKey.length);
+	    print_buffer(key_pack->replyKey.contents,
+			 key_pack->replyKey.length);
+	    pkiDebug("received checksum type=%d size=%d ",
+		     key_pack->asChecksum.checksum_type,
+		     key_pack->asChecksum.length);
+	    print_buffer(key_pack->asChecksum.contents,
+			 key_pack->asChecksum.length);
+	    pkiDebug("expected checksum type=%d size=%d ",
+		     cksum.checksum_type, cksum.length);
+	    print_buffer(cksum.contents, cksum.length);
+#endif
+		goto cleanup;
+	    } else
+		pkiDebug("checksums match\n");
+
+	    krb5_copy_keyblock_contents(context, &key_pack->replyKey,
+					key_block);
+
+	    break;
+	default:
+	    pkiDebug("unknow as_rep type %d\n", kdc_reply->choice);
+	    goto cleanup;
+    }
+
+    retval = 0;
+
+cleanup:
+    if (dh_data.data != NULL)
+	free(dh_data.data);
+    if (client_key != NULL)
+	free(client_key);
+    free_krb5_kdc_dh_key_info(&kdc_dh);
+    free_krb5_pa_pk_as_rep(&kdc_reply);
+
+    if (key_pack != NULL) {
+	free_krb5_reply_key_pack(&key_pack);
+	if (cksum.contents != NULL)
+	    free(cksum.contents);
+    } 
+    if (key_pack9 != NULL)
+	free_krb5_reply_key_pack_draft9(&key_pack9);
+
+    if (kdc_hostname != NULL)
+	free(kdc_hostname);
+
+    pkiDebug("pkinit_as_rep_parse returning %d (%s)\n",
+	     retval, error_message(retval));
+    return retval;
+}
+
+static void
+pkinit_client_profile(krb5_context context,
+		      pkinit_context plgctx,
+		      pkinit_req_context reqctx,
+		      krb5_kdc_req *request)
+{
+    char *eku_string = NULL;
+
+    pkiDebug("pkinit_client_profile %p %p %p %p\n",
+	     context, plgctx, reqctx, request);
+
+    pkinit_libdefault_boolean(context, &request->server->realm,
+			      "pkinit_win2k",
+			      reqctx->opts->win2k_target,
+			      &reqctx->opts->win2k_target);
+    pkinit_libdefault_boolean(context, &request->server->realm,
+			      "pkinit_win2k_require_binding",
+			      reqctx->opts->win2k_require_cksum,
+			      &reqctx->opts->win2k_require_cksum);
+    pkinit_libdefault_boolean(context, &request->server->realm,
+			      "pkinit_require_crl_checking",
+			      reqctx->opts->require_crl_checking,
+			      &reqctx->opts->require_crl_checking);
+    pkinit_libdefault_integer(context, &request->server->realm,
+			      "pkinit_dh_min_bits",
+			      reqctx->opts->dh_size,
+			      &reqctx->opts->dh_size);
+    if (reqctx->opts->dh_size != 1024 && reqctx->opts->dh_size != 2048
+        && reqctx->opts->dh_size != 4096) {
+	pkiDebug("%s: invalid value (%d) for pkinit_dh_min_bits, "
+		 "using default value (%d) instead\n", __FUNCTION__,
+		 reqctx->opts->dh_size, PKINIT_DEFAULT_DH_MIN_BITS);
+	reqctx->opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS;
+    }
+    pkinit_libdefault_string(context, &request->server->realm,
+			     "pkinit_eku_checking",
+			     &eku_string);
+    if (eku_string != NULL) {
+	if (strcasecmp(eku_string, "kpKDC") == 0) {
+	    reqctx->opts->require_eku = 1;
+	    reqctx->opts->accept_secondary_eku = 0;
+	} else if (strcasecmp(eku_string, "kpServerAuth") == 0) {
+	    reqctx->opts->require_eku = 1;
+	    reqctx->opts->accept_secondary_eku = 1;
+	} else if (strcasecmp(eku_string, "none") == 0) {
+	    reqctx->opts->require_eku = 0;
+	    reqctx->opts->accept_secondary_eku = 0;
+	} else {
+	    pkiDebug("%s: Invalid value for pkinit_eku_checking: '%s'\n",
+		     __FUNCTION__, eku_string);
+	}
+	free(eku_string);
+    }
+#ifdef LONGHORN_BETA_COMPAT
+    /* Temporarily just set global flag from config file */
+    pkinit_libdefault_boolean(context, &request->server->realm,
+			      "pkinit_longhorn",
+			      0,
+			      &longhorn);
+#endif
+
+    /* Only process anchors here if they were not specified on command line */
+    if (reqctx->idopts->anchors == NULL)
+	pkinit_libdefault_strings(context, &request->server->realm,
+				  "pkinit_anchors",
+				  &reqctx->idopts->anchors);
+    pkinit_libdefault_strings(context, &request->server->realm,
+			      "pkinit_pool",
+			      &reqctx->idopts->intermediates);
+    pkinit_libdefault_strings(context, &request->server->realm,
+			      "pkinit_revoke",
+			      &reqctx->idopts->crls);
+    pkinit_libdefault_strings(context, &request->server->realm,
+			      "pkinit_identities",
+			      &reqctx->idopts->identity_alt);
+}
+
+krb5_error_code
+pkinit_client_process(krb5_context context,
+		      void *plugin_context,
+		      void *request_context,
+		      krb5_get_init_creds_opt *gic_opt,
+		      preauth_get_client_data_proc get_data_proc,
+		      struct _krb5_preauth_client_rock *rock,
+		      krb5_kdc_req *request,
+		      krb5_data *encoded_request_body,
+		      krb5_data *encoded_previous_request,
+		      krb5_pa_data *in_padata,
+		      krb5_prompter_fct prompter,
+		      void *prompter_data,
+		      preauth_get_as_key_proc gak_fct,
+		      void *gak_data,
+		      krb5_data *salt,
+		      krb5_data *s2kparams,
+		      krb5_keyblock *as_key,
+		      krb5_pa_data ***out_padata)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    krb5_enctype enctype = -1;
+    krb5_data *cdata = NULL;
+    int processing_request = 0;
+    pkinit_context plgctx = (pkinit_context)plugin_context;
+    pkinit_req_context reqctx = (pkinit_req_context)request_context;
+
+    pkiDebug("pkinit_client_process %p %p %p %p\n",
+	     context, plgctx, reqctx, request);
+
+    if (plgctx == NULL || reqctx == NULL)
+	return EINVAL;
+
+    switch ((int) in_padata->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
+	    processing_request = 1;
+	    break;
+
+	case KRB5_PADATA_PK_AS_REP:
+	    pkiDebug("processing KRB5_PADATA_PK_AS_REP\n");
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    if (in_padata->length == 0) {
+		pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
+		in_padata->pa_type = KRB5_PADATA_PK_AS_REQ_OLD;
+		processing_request = 1;
+	    } else {
+		pkiDebug("processing KRB5_PADATA_PK_AS_REP_OLD\n");
+		in_padata->pa_type = KRB5_PADATA_PK_AS_REP_OLD;
+	    }
+	    break;
+	default:
+	    pkiDebug("unrecognized patype = %d for PKINIT\n",
+		    in_padata->pa_type);
+	    return EINVAL;
+    }
+
+    if (processing_request) {
+	pkinit_client_profile(context, plgctx, reqctx, request);
+	pkinit_identity_set_prompter(reqctx->idctx, prompter, prompter_data);
+	retval = pkinit_identity_initialize(context, plgctx->cryptoctx,
+					    reqctx->cryptoctx, reqctx->idopts,
+					    reqctx->idctx, 1, request->client);
+	if (retval) {
+	    pkiDebug("pkinit_identity_initialize returned %d (%s)\n",
+		     retval, error_message(retval));
+	    return retval;
+	}
+	retval = pa_pkinit_gen_req(context, plgctx, reqctx, request,
+				   in_padata, out_padata, prompter,
+				   prompter_data, gic_opt);
+    } else {
+	/*
+	 * Get the enctype of the reply.
+	 */
+	retval = (*get_data_proc)(context, rock,
+				krb5plugin_preauth_client_get_etype, &cdata);
+	if (retval) {
+	    pkiDebug("get_data_proc returned %d (%s)\n",
+		     retval, error_message(retval));
+	    return retval;
+	}
+	enctype = *((krb5_enctype *)cdata->data);
+	(*get_data_proc)(context, rock,
+			 krb5plugin_preauth_client_free_etype, &cdata);
+	retval = pa_pkinit_parse_rep(context, plgctx, reqctx, request,
+				     in_padata, enctype, as_key,
+				     encoded_previous_request);
+    }
+
+    pkiDebug("pkinit_client_process: returning %d (%s)\n",
+	     retval, error_message(retval));
+    return retval;
+}
+
+krb5_error_code
+pkinit_client_tryagain(krb5_context context,
+		       void *plugin_context,
+		       void *request_context,
+		       krb5_get_init_creds_opt *gic_opt,
+		       preauth_get_client_data_proc get_data_proc,
+		       struct _krb5_preauth_client_rock *rock,
+		       krb5_kdc_req *request,
+		       krb5_data *encoded_request_body,
+		       krb5_data *encoded_previous_request,
+		       krb5_pa_data *in_padata,
+		       krb5_error *err_reply,
+		       krb5_prompter_fct prompter,
+		       void *prompter_data,
+		       preauth_get_as_key_proc gak_fct,
+		       void *gak_data,
+		       krb5_data *salt,
+		       krb5_data *s2kparams,
+		       krb5_keyblock *as_key,
+		       krb5_pa_data ***out_padata)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    pkinit_context plgctx = (pkinit_context)plugin_context;
+    pkinit_req_context reqctx = (pkinit_req_context)request_context;
+    krb5_typed_data **typed_data = NULL;
+    krb5_data scratch;
+    krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
+    krb5_algorithm_identifier **algId = NULL;
+    int do_again = 0;
+
+    pkiDebug("pkinit_client_tryagain %p %p %p %p\n",
+	     context, plgctx, reqctx, request);
+
+    if (reqctx->pa_type != in_padata->pa_type)
+	return retval;
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin((unsigned char *)err_reply->e_data.data,
+		     err_reply->e_data.length, "/tmp/client_edata");
+#endif
+    retval = k5int_decode_krb5_typed_data(&err_reply->e_data, &typed_data);
+    if (retval) {
+	pkiDebug("decode_krb5_typed_data failed\n");
+	goto cleanup;
+    }
+#ifdef DEBUG_ASN1
+    print_buffer_bin(typed_data[0]->data, typed_data[0]->length,
+		     "/tmp/client_typed_data");
+#endif
+    OCTETDATA_TO_KRB5DATA(typed_data[0], &scratch);
+
+    switch(typed_data[0]->type) {
+	case TD_TRUSTED_CERTIFIERS:
+	case TD_INVALID_CERTIFICATES:
+	    retval = k5int_decode_krb5_td_trusted_certifiers(&scratch,
+		&krb5_trusted_certifiers);
+	    if (retval) {
+		pkiDebug("failed to decode sequence of trusted certifiers\n");
+		goto cleanup;
+	    }
+	    retval = pkinit_process_td_trusted_certifiers(context,
+		    plgctx->cryptoctx, reqctx->cryptoctx, reqctx->idctx,
+		    krb5_trusted_certifiers, typed_data[0]->type);
+	    if (!retval)
+		do_again = 1;
+	    break;
+	case TD_DH_PARAMETERS:
+	    retval = k5int_decode_krb5_td_dh_parameters(&scratch, &algId);
+	    if (retval) {
+		pkiDebug("failed to decode td_dh_parameters\n");
+		goto cleanup;
+	    }
+	    retval = pkinit_process_td_dh_params(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, reqctx->idctx, algId,
+		&reqctx->opts->dh_size);
+	    if (!retval)
+		do_again = 1;
+	    break;
+	default:
+	    break;
+    }
+
+    if (do_again) {
+	retval = pa_pkinit_gen_req(context, plgctx, reqctx, request, in_padata,
+				   out_padata, prompter, prompter_data, gic_opt);
+	if (retval)
+	    goto cleanup;
+    }
+	
+    retval = 0;
+cleanup:
+    if (krb5_trusted_certifiers != NULL)
+	free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
+
+    if (typed_data != NULL)
+	free_krb5_typed_data(&typed_data);
+
+    if (algId != NULL)
+	free_krb5_algorithm_identifiers(&algId);
+
+    pkiDebug("pkinit_client_tryagain: returning %d (%s)\n",
+	     retval, error_message(retval));
+    return retval;
+}
+
+static int
+pkinit_client_get_flags(krb5_context kcontext, krb5_preauthtype patype)
+{
+    return PA_REAL;
+}
+
+static krb5_preauthtype supported_client_pa_types[] = {
+    KRB5_PADATA_PK_AS_REP,
+    KRB5_PADATA_PK_AS_REQ,
+    KRB5_PADATA_PK_AS_REP_OLD,
+    KRB5_PADATA_PK_AS_REQ_OLD,
+    0
+};
+
+void
+pkinit_client_req_init(krb5_context context,
+		       void *plugin_context,
+		       void **request_context)
+{
+    krb5_error_code retval = ENOMEM;
+    struct _pkinit_req_context *reqctx = NULL;
+    struct _pkinit_context *plgctx = (struct _pkinit_context *)plugin_context;
+
+    *request_context = NULL;
+
+    reqctx = (struct _pkinit_req_context *) malloc(sizeof(*reqctx));
+    if (reqctx == NULL)
+	return;
+    memset(reqctx, 0, sizeof(*reqctx));
+
+    reqctx->magic = PKINIT_REQ_CTX_MAGIC;
+    reqctx->cryptoctx = NULL;
+    reqctx->opts = NULL;
+    reqctx->idctx = NULL;
+    reqctx->idopts = NULL;
+
+    retval = pkinit_init_req_opts(&reqctx->opts);
+    if (retval)
+	goto cleanup;
+	
+    reqctx->opts->require_eku = plgctx->opts->require_eku;
+    reqctx->opts->accept_secondary_eku = plgctx->opts->accept_secondary_eku;
+    reqctx->opts->dh_or_rsa = plgctx->opts->dh_or_rsa;
+    reqctx->opts->allow_upn = plgctx->opts->allow_upn;
+    reqctx->opts->require_crl_checking = plgctx->opts->require_crl_checking;
+
+    retval = pkinit_init_req_crypto(&reqctx->cryptoctx);
+    if (retval)
+	goto cleanup;
+
+    retval = pkinit_init_identity_crypto(&reqctx->idctx);
+    if (retval)
+	goto cleanup;
+
+    retval = pkinit_dup_identity_opts(plgctx->idopts, &reqctx->idopts);
+    if (retval)
+	goto cleanup;
+
+    *request_context = (void *) reqctx;
+    pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx);
+
+cleanup:
+    if (retval) {
+	if (reqctx->idctx != NULL)
+	    pkinit_fini_identity_crypto(reqctx->idctx);
+	if (reqctx->cryptoctx != NULL)
+	    pkinit_fini_req_crypto(reqctx->cryptoctx);
+	if (reqctx->opts != NULL)
+	    pkinit_fini_req_opts(reqctx->opts);
+	if (reqctx->idopts != NULL)
+	    pkinit_fini_identity_opts(reqctx->idopts);
+	free(reqctx);
+    }
+
+    return;
+}
+
+void
+pkinit_client_req_fini(krb5_context context,
+		      void *plugin_context,
+		      void *request_context)
+{
+    struct _pkinit_req_context *reqctx =
+	(struct _pkinit_req_context *)request_context;
+
+    pkiDebug("%s: received reqctx at %p\n", __FUNCTION__, reqctx);
+    if (reqctx == NULL)
+	return;
+    if (reqctx->magic != PKINIT_REQ_CTX_MAGIC) {
+	pkiDebug("%s: Bad magic value (%x) in req ctx\n",
+		 __FUNCTION__, reqctx->magic);
+	return;
+    }
+    if (reqctx->opts != NULL)
+	pkinit_fini_req_opts(reqctx->opts);
+
+    if (reqctx->cryptoctx != NULL)
+	pkinit_fini_req_crypto(reqctx->cryptoctx);
+
+    if (reqctx->idctx != NULL)
+	pkinit_fini_identity_crypto(reqctx->idctx);
+
+    if (reqctx->idopts != NULL)
+	pkinit_fini_identity_opts(reqctx->idopts);
+
+    free(reqctx);
+    return;
+}
+
+static void
+pkinit_fini_client_profile(krb5_context context, pkinit_context plgctx)
+{
+    /* This should clean up anything allocated in pkinit_init_client_profile */
+}
+
+static krb5_error_code
+pkinit_init_client_profile(krb5_context context, pkinit_context plgctx)
+{
+    return 0;
+}
+
+static int
+pkinit_client_plugin_init(krb5_context context, void **blob)
+{
+    krb5_error_code retval = ENOMEM;
+    struct _pkinit_context *ctx = NULL;
+
+    ctx = (struct _pkinit_context *)calloc(1, sizeof(*ctx));
+    if (ctx == NULL)
+	return ENOMEM;
+    memset(ctx, 0, sizeof(*ctx));
+    ctx->magic = PKINIT_CTX_MAGIC;
+    ctx->opts = NULL;
+    ctx->cryptoctx = NULL;
+    ctx->idopts = NULL;
+
+    retval = pkinit_accessor_init();
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_plg_opts(&ctx->opts);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_plg_crypto(&ctx->cryptoctx);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_identity_opts(&ctx->idopts);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_client_profile(context, ctx);
+    if (retval)
+	goto errout;
+
+    *blob = ctx;
+
+    pkiDebug("%s: returning plgctx at %p\n", __FUNCTION__, ctx);
+
+errout:
+    if (retval)
+	pkinit_client_plugin_fini(context, ctx);
+
+    return retval;
+}
+
+static void
+pkinit_client_plugin_fini(krb5_context context, void *blob)
+{
+    struct _pkinit_context *ctx = (struct _pkinit_context *)blob;
+
+    if (ctx == NULL || ctx->magic != PKINIT_CTX_MAGIC) {
+	pkiDebug("pkinit_lib_fini: got bad plgctx (%p)!\n", ctx);
+	return;
+    }
+    pkiDebug("%s: got plgctx at %p\n", __FUNCTION__, ctx);
+
+    pkinit_fini_client_profile(context, ctx);
+    pkinit_fini_identity_opts(ctx->idopts);
+    pkinit_fini_plg_crypto(ctx->cryptoctx);
+    pkinit_fini_plg_opts(ctx->opts);
+    free(ctx);
+
+}
+
+static krb5_error_code
+add_string_to_array(krb5_context context, char ***array, const char *addition)
+{
+    char **out = NULL;
+
+    if (*array == NULL) {
+	out = malloc(2 * sizeof(char *));
+	if (out == NULL)
+	    return ENOMEM;
+	out[1] = NULL;
+	out[0] = strdup(addition);
+	if (out[0] == NULL) {
+	    free(out);
+	    return ENOMEM;
+	}
+    } else {
+	int i;
+	char **a = *array;
+	for (i = 0; a[i] != NULL; i++);
+	out = malloc( (i + 2) * sizeof(char *));
+	if (out == NULL)
+	    return ENOMEM;
+	for (i = 0; a[i] != NULL; i++) {
+	    out[i] = a[i];
+	}
+	out[i++] = strdup(addition);
+	if (out == NULL) {
+	    free(out);
+	    return ENOMEM;
+	}
+	out[i] = NULL;
+	free(*array);
+    }
+    *array = out;
+	
+    return 0;
+}
+static krb5_error_code
+handle_gic_opt(krb5_context context,
+	       struct _pkinit_context *plgctx,
+	       const char *attr,
+	       const char *value)
+{
+    krb5_error_code retval;
+
+    if (strcmp(attr, "X509_user_identity") == 0) {
+	if (plgctx->idopts->identity != NULL) {
+	    krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
+		"X509_user_identity can not be given twice\n");
+	    return KRB5_PREAUTH_FAILED;
+	}
+	plgctx->idopts->identity = strdup(value);
+	if (plgctx->idopts->identity == NULL) {
+	    krb5_set_error_message(context, ENOMEM,
+		"Could not duplicate X509_user_identity value\n");
+	    return ENOMEM;
+	}
+    } else if (strcmp(attr, "X509_anchors") == 0) {
+	retval = add_string_to_array(context, &plgctx->idopts->anchors, value);
+	if (retval)
+	    return retval;
+    } else if (strcmp(attr, "flag_RSA_PROTOCOL") == 0) {
+	if (strcmp(value, "yes") == 0) {
+	    pkiDebug("Setting flag to use RSA_PROTOCOL\n");
+	    plgctx->opts->dh_or_rsa = RSA_PROTOCOL;
+	}
+    }
+    return 0;
+}
+
+static krb5_error_code
+pkinit_client_gic_opt(krb5_context context,
+		      void *plugin_context,
+		      krb5_get_init_creds_opt *gic_opt,
+		      const char *attr,
+		      const char *value)
+{
+    krb5_error_code retval;
+    struct _pkinit_context *plgctx = (struct _pkinit_context *)plugin_context;
+
+    pkiDebug("(pkinit) received '%s' = '%s'\n", attr, value);
+    retval = handle_gic_opt(context, plgctx, attr, value);
+    if (retval)
+	return retval;
+
+    return 0;
+}
+
+struct krb5plugin_preauth_client_ftable_v1 preauthentication_client_1 = {
+    "pkinit",			/* name */
+    supported_client_pa_types,	/* pa_type_list */
+    NULL,			/* enctype_list */
+    pkinit_client_plugin_init,	/* (*init) */
+    pkinit_client_plugin_fini,	/* (*fini) */
+    pkinit_client_get_flags,	/* (*flags) */
+    pkinit_client_req_init,     /* (*client_req_init) */
+    pkinit_client_req_fini,     /* (*client_req_fini) */
+    pkinit_client_process,	/* (*process) */
+    pkinit_client_tryagain,	/* (*tryagain) */
+    pkinit_client_gic_opt	/* (*gic_opt) */
+};
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto.h b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto.h
new file mode 100644
index 000000000..779c08cae
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto.h
@@ -0,0 +1,623 @@
+/*
+ * COPYRIGHT (C) 2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * This header defines the cryptographic interface
+ */
+
+#ifndef _PKINIT_CRYPTO_H
+#define _PKINIT_CRYPTO_H
+
+#include <krb5/krb5.h>
+#include <krb5/preauth_plugin.h>
+#include <k5-int-pkinit.h>
+#include <profile.h>
+#include "pkinit_accessor.h"
+
+/*
+ * these describe the CMS message types
+ */
+enum cms_msg_types {
+    CMS_SIGN_CLIENT,
+    CMS_SIGN_DRAFT9,
+    CMS_SIGN_SERVER,
+    CMS_ENVEL_SERVER
+};
+
+/*
+ * storage types for identity information
+ */
+#define IDTYPE_FILE     1
+#define IDTYPE_DIR      2
+#define IDTYPE_PKCS11   3
+#define IDTYPE_ENVVAR   4
+#define IDTYPE_PKCS12   5
+
+/*
+ * ca/crl types
+ */
+#define CATYPE_ANCHORS          1
+#define CATYPE_INTERMEDIATES    2
+#define CATYPE_CRLS             3
+
+/*
+ * The following represent Key Usage values that we
+ * may care about in a certificate
+ */
+#define PKINIT_KU_DIGITALSIGNATURE      0x80000000
+#define PKINIT_KU_KEYENCIPHERMENT       0x40000000
+
+/*
+ * The following represent Extended Key Usage oid values
+ * that we may care about in a certificate
+ */
+#define PKINIT_EKU_PKINIT               0x80000000
+#define PKINIT_EKU_MSSCLOGIN            0x40000000
+#define PKINIT_EKU_CLIENTAUTH           0x20000000
+#define PKINIT_EKU_EMAILPROTECTION      0x10000000
+
+
+/* Handle to cert, opaque above crypto interface */
+typedef struct _pkinit_cert_info *pkinit_cert_handle;
+
+/* Handle to cert iteration information, opaque above crypto interface */
+typedef struct _pkinit_cert_iter_info *pkinit_cert_iter_handle;
+
+#define PKINIT_ITER_NO_MORE	0x11111111  /* XXX */
+
+typedef struct _pkinit_cert_matching_data {
+    pkinit_cert_handle ch;  /* cert handle for this certificate */
+    char *subject_dn;	    /* rfc2253-style subject name string */
+    char *issuer_dn;	    /* rfc2253-style issuer name string */
+    unsigned int ku_bits;   /* key usage information */
+    unsigned int eku_bits;  /* extended key usage information */
+    krb5_principal *sans;   /* Null-terminated array of subject alternative
+			       name info (pkinit and ms-upn) */
+} pkinit_cert_matching_data;
+
+/*
+ * Functions to initialize and cleanup crypto contexts
+ */
+krb5_error_code pkinit_init_plg_crypto(pkinit_plg_crypto_context *);
+void pkinit_fini_plg_crypto(pkinit_plg_crypto_context);
+
+krb5_error_code pkinit_init_req_crypto(pkinit_req_crypto_context *);
+void pkinit_fini_req_crypto(pkinit_req_crypto_context);
+
+krb5_error_code pkinit_init_identity_crypto(pkinit_identity_crypto_context *);
+void pkinit_fini_identity_crypto(pkinit_identity_crypto_context);
+
+/*
+ * this function creates a CMS message where eContentType is SignedData
+ */
+krb5_error_code cms_signeddata_create
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	int cms_msg_type,				/* IN
+		    specifies CMS_SIGN_CLIENT for client-side CMS message
+		    and CMS_SIGN_SERVER for kdc-side */
+	int include_certchain,				/* IN
+		    specifies where certificates field in SignedData
+		    should contain certificate path */
+	unsigned char *auth_pack,			/* IN
+		    contains DER encoded AuthPack (CMS_SIGN_CLIENT)
+		    or DER encoded DHRepInfo (CMS_SIGN_SERVER) */
+	unsigned int auth_pack_len,			/* IN
+		    contains length of auth_pack */
+	unsigned char **signed_data,			/* OUT
+		    for CMS_SIGN_CLIENT receives DER encoded
+		    SignedAuthPack (CMS_SIGN_CLIENT) or DER
+		    encoded DHInfo (CMS_SIGN_SERVER) */ 
+	unsigned int *signed_data_len);			/* OUT
+		    receives length of signed_data */
+
+/*
+ * this function verifies a CMS message where eContentType is SignedData
+ */
+krb5_error_code cms_signeddata_verify
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	int cms_msg_type,				/* IN
+		    specifies CMS_SIGN_CLIENT for client-side
+		    CMS message and CMS_SIGN_SERVER for kdc-side */
+	int require_crl_checking,			/* IN
+		    specifies whether CRL checking should be
+		    strictly enforced, i.e. if no CRLs available
+		    for the CA then fail verification.
+		    note, if the value is 0, crls are still
+		    checked if present */
+	unsigned char *signed_data,			/* IN
+		    contains DER encoded SignedAuthPack (CMS_SIGN_CLIENT)
+		    or DER encoded DHInfo (CMS_SIGN_SERVER) */
+	unsigned int signed_data_len,			/* IN
+		    contains length of signed_data*/
+	unsigned char **auth_pack,			/* OUT
+		    receives DER encoded AuthPack (CMS_SIGN_CLIENT)
+		    or DER encoded DHRepInfo (CMS_SIGN_SERVER)*/
+	unsigned int *auth_pack_len,			/* OUT
+		    receives length of auth_pack */
+	unsigned char **authz_data,			/* OUT
+		    receives required authorization data that
+		    contains the verified certificate chain
+		    (only used by the KDC) */
+	unsigned int *authz_data_len);			/* OUT
+		    receives length of authz_data */
+
+/*
+ * this function creates a CMS message where eContentType is EnvelopedData
+ */
+krb5_error_code cms_envelopeddata_create	
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_preauthtype pa_type,			/* IN */ 
+	int include_certchain,				/* IN
+		    specifies whether the certificates field in
+		    SignedData should contain certificate path */
+	unsigned char *key_pack,			/* IN
+		    contains DER encoded ReplyKeyPack */
+	unsigned int key_pack_len,			/* IN
+		    contains length of key_pack */
+	unsigned char **envel_data,			/* OUT
+		    receives DER encoded encKeyPack */
+	unsigned int *envel_data_len);			/* OUT
+		    receives length of envel_data */
+
+/*
+ * this function creates a CMS message where eContentType is EnvelopedData
+ */
+krb5_error_code cms_envelopeddata_verify
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_preauthtype pa_type,			/* IN */
+	int require_crl_checking,			/* IN
+		    specifies whether CRL checking should be
+		    strictly enforced */
+	unsigned char *envel_data,			/* IN
+		    contains DER encoded encKeyPack */
+	unsigned int envel_data_len,			/* IN
+		    contains length of envel_data */ 
+	unsigned char **signed_data,			/* OUT
+		    receives ReplyKeyPack */
+	unsigned int *signed_data_len);			/* OUT
+		    receives length of signed_data */
+
+/*
+ * this function returns SAN information found in the
+ * received certificate.  at least one of pkinit_sans,
+ * upn_sans, or kdc_hostnames must be non-NULL.
+ */
+krb5_error_code crypto_retrieve_cert_sans
+	(krb5_context context,				/* IN */ 
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_principal **pkinit_sans,			/* OUT
+		    if non-NULL, a null-terminated array of
+		    id-pkinit-san values found in the certificate
+		    are returned */
+	krb5_principal **upn_sans,			/* OUT
+		    if non-NULL, a null-terminated array of
+		    id-ms-upn-san values found in the certificate
+		    are returned */
+	unsigned char ***kdc_hostname);			/* OUT
+		    if non-NULL, a null-terminated array of
+		    dNSName (hostname) SAN values found in the
+		    certificate are returned */ 
+
+/*
+ * this function checks for acceptable key usage values
+ * in the received certificate.
+ *
+ * when checking a received kdc certificate, it looks for
+ * the kpKdc key usage.  if allow_secondary_usage is
+ * non-zero, it will also accept kpServerAuth.
+ *
+ * when checking a received user certificate, it looks for
+ * kpClientAuth key usage.  if allow_secondary_usage is
+ * non-zero, it will also accept id-ms-sc-logon EKU.
+ *
+ * this function must also assert that the digitalSignature
+ * key usage is consistent.
+ */
+krb5_error_code crypto_check_cert_eku
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	int checking_kdc_cert,				/* IN
+		    specifies if the received certificate is
+		    a KDC certificate (non-zero),
+		    or a user certificate (zero) */
+	int allow_secondary_usage,			/* IN
+		    specifies if the secondary key usage
+		    should be accepted or not (see above) */
+	int *eku_valid);				/* OUT
+		    receives non-zero if an acceptable EKU was found */
+
+/*
+ * this functions takes in generated DH secret key and converts
+ * it in to a kerberos session key. it takes into the account the
+ * enc type and then follows the procedure specified in the RFC p 22.
+ */
+krb5_error_code pkinit_octetstring2key
+	(krb5_context context,				/* IN */
+	krb5_enctype etype,				/* IN
+		    specifies the enc type */
+	unsigned char *key,				/* IN
+		    contains the DH secret key */
+	unsigned int key_len,				/* IN
+		    contains length of key */
+	krb5_keyblock * krb5key);			/* OUT
+		    receives kerberos session key */
+
+/*
+ * this function implements clients first part of the DH protocol.
+ * client selects its DH parameters and pub key
+ */
+krb5_error_code client_create_dh
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	int dh_size,					/* IN
+		    specifies the DH modulous, eg 1024, 2048, or 4096 */
+	unsigned char **dh_paramas,			/* OUT
+		    contains DER encoded DH params */
+	unsigned int *dh_params_len,			/* OUT
+		    contains length of dh_parmas */
+	unsigned char **dh_pubkey,			/* OUT
+		    receives DER encoded DH pub key */ 
+	unsigned int *dh_pubkey_len);			/* OUT
+		    receives length of dh_pubkey */
+
+/*
+ * this function completes client's the DH protocol. client
+ * processes received DH pub key from the KDC and computes
+ * the DH secret key 
+ */
+krb5_error_code client_process_dh
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	unsigned char *dh_pubkey,			/* IN
+		    contains client's DER encoded DH pub key */
+	unsigned int dh_pubkey_len,			/* IN
+		    contains length of dh_pubkey */
+	unsigned char **dh_session_key,			/* OUT
+		    receives DH secret key */
+	unsigned int *dh_session_key_len);		/* OUT
+		    receives length of dh_session_key */
+
+/*
+ * this function implements the KDC first part of the DH protocol.
+ * it decodes the client's DH parameters and pub key and checks
+ * if they are acceptable.
+ */
+krb5_error_code server_check_dh
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_octet_data *dh_params,			/* IN
+		    ???? */
+	int minbits);					/* IN
+		    the mininum number of key bits acceptable */
+
+/*
+ * this function completes the KDC's DH protocol. The KDC generates
+ * its DH pub key and computes the DH secret key
+ */
+krb5_error_code server_process_dh
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	unsigned char *received_pubkey,			/* IN
+		    contains client's DER encoded DH pub key */
+	unsigned int received_pub_len,			/* IN
+		    contains length of received_pubkey */
+	unsigned char **dh_pubkey,			/* OUT
+		    receives KDC's DER encoded DH pub key */ 
+	unsigned int *dh_pubkey_len,			/* OUT
+		    receives length of dh_pubkey */
+	unsigned char **server_key,			/* OUT
+		    receives DH secret key */
+	unsigned int *server_key_len);			/* OUT
+		    receives length of server_key */
+
+/*
+ * this functions takes in crypto specific representation of
+ * supportedCMSTypes and creates a list of
+ * krb5_algorithm_identifier
+ */
+krb5_error_code create_krb5_supportedCMSTypes
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_algorithm_identifier ***supportedCMSTypes); /* OUT */
+
+/*
+ * this functions takes in crypto specific representation of
+ * trustedCertifiers and creates a list of
+ * krb5_external_principal_identifier
+ */
+krb5_error_code create_krb5_trustedCertifiers
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_external_principal_identifier ***trustedCertifiers); /* OUT */
+
+/*
+ * this functions takes in crypto specific representation of
+ * trustedCas (draft9) and creates a list of krb5_trusted_ca (draft9).
+ * draft9 trustedCAs is a CHOICE. we only support choices for
+ * [1] caName and [2] issuerAndSerial.  there is no config
+ * option available to select the choice yet. default = 1.
+ */
+krb5_error_code create_krb5_trustedCas
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	int flag,					/* IN
+		    specifies the tag of the CHOICE */
+	krb5_trusted_ca ***trustedCas);			/* OUT */
+
+/*
+ * this functions takes in crypto specific representation of the
+ * KDC's certificate and creates a DER encoded kdcPKId
+ */
+krb5_error_code create_issuerAndSerial
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	unsigned char **kdcId_buf,			/* OUT
+		    receives DER encoded kdcPKId */
+	unsigned int *kdcId_len);			/* OUT
+		    receives length of encoded kdcPKId */
+
+/*
+ * process the values from idopts and obtain the cert(s)
+ * specified by those options, populating the id_cryptoctx.
+ */
+krb5_error_code crypto_load_certs
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_opts *idopts,			/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN/OUT */
+	krb5_principal princ);				/* IN */
+
+/*
+ * Free up information held from crypto_load_certs()
+ */
+krb5_error_code crypto_free_cert_info
+	(krb5_context context,
+	pkinit_plg_crypto_context plg_cryptoctx,
+	pkinit_req_crypto_context req_cryptoctx,
+	pkinit_identity_crypto_context id_cryptoctx);
+
+
+/*
+ * Get number of certificates available after crypto_load_certs()
+ */
+krb5_error_code crypto_cert_get_count
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	int *cert_count);				/* OUT */
+
+/*
+ * Begin iteration over the certs loaded in crypto_load_certs()
+ */
+krb5_error_code crypto_cert_iteration_begin
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	pkinit_cert_iter_handle *iter_handle);		/* OUT */
+
+/*
+ * End iteration over the certs loaded in crypto_load_certs()
+ */
+krb5_error_code crypto_cert_iteration_end
+	(krb5_context context,				/* IN */
+	pkinit_cert_iter_handle iter_handle);		/* IN */
+
+/*
+ * Get next certificate handle
+ */
+krb5_error_code crypto_cert_iteration_next
+	(krb5_context context,				/* IN */
+	pkinit_cert_iter_handle iter_handle,		/* IN */
+	pkinit_cert_handle *cert_handle);		/* OUT */
+
+/*
+ * Release cert handle
+ */
+krb5_error_code crypto_cert_release
+	(krb5_context context,				/* IN */
+	pkinit_cert_handle cert_handle);		/* IN */
+
+/*
+ * Get certificate matching information
+ */
+krb5_error_code crypto_cert_get_matching_data
+	(krb5_context context,				/* IN */
+	pkinit_cert_handle cert_handle,			/* IN */
+	pkinit_cert_matching_data **ret_data);		/* OUT */
+
+/*
+ * Free certificate information
+ */
+krb5_error_code crypto_cert_free_matching_data
+	(krb5_context context,				/* IN */
+	pkinit_cert_matching_data *data);		/* IN */
+
+/*
+ * Make the given certificate "the chosen one"
+ */
+krb5_error_code crypto_cert_select
+	(krb5_context context,				/* IN */
+	pkinit_cert_matching_data *data);		/* IN */
+
+/*
+ * Select the default certificate as "the chosen one"
+ */
+krb5_error_code crypto_cert_select_default
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx);	/* IN */
+
+/*
+ * process the values from idopts and obtain the anchor or
+ * intermediate certificates, or crls specified by idtype,
+ * catype, and id
+ */
+krb5_error_code crypto_load_cas_and_crls
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_opts *idopts,			/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN/OUT */
+	int idtype,					/* IN 
+		    defines the storage type (file, directory, etc) */
+	int catype,					/* IN
+		    defines the ca type (anchor, intermediate, crls) */
+	char *id);					/* IN
+		    defines the location (filename, directory name, etc) */
+
+/*
+ * on the client, obtain the kdc's certificate to include
+ * in a request
+ */
+krb5_error_code pkinit_get_kdc_cert
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN/OUT */
+	krb5_principal princ);				/* IN */
+
+/*
+ * this function creates edata that contains TD-DH-PARAMETERS
+ */
+krb5_error_code pkinit_create_td_dh_parameters
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	pkinit_plg_opts *opts,				/* IN */
+	krb5_data **edata);				/* OUT */
+
+/*
+ * this function processes edata that contains TD-DH-PARAMETERS.
+ * the client processes the received acceptable by KDC DH
+ * parameters and picks the first acceptable to it. it matches
+ * them against the known DH parameters.
+ */
+krb5_error_code pkinit_process_td_dh_params
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_algorithm_identifier **algId,		/* IN */
+	int *new_dh_size);				/* OUT
+		    receives the new DH modulus to use in the new AS-REQ */
+
+/*
+ * this function creates edata that contains TD-INVALID-CERTIFICATES
+ */
+krb5_error_code pkinit_create_td_invalid_certificate
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */ 
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_data **edata);				/* OUT */
+
+/*
+ * this function creates edata that contains TD-TRUSTED-CERTIFIERS
+ */
+krb5_error_code pkinit_create_td_trusted_certifiers
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_data **edata);				/* OUT */
+
+/*
+ * this function processes edata that contains either 
+ * TD-TRUSTED-CERTIFICATES or TD-INVALID-CERTIFICATES.
+ * current implementation only decodes the received message
+ * but does not act on it
+ */
+krb5_error_code pkinit_process_td_trusted_certifiers
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_external_principal_identifier **trustedCertifiers, /* IN */
+	int td_type);					/* IN */
+
+/*
+ * this function checks if the received kdcPKId matches
+ * the KDC's certificate
+ */
+krb5_error_code pkinit_check_kdc_pkid
+	(krb5_context context,				/* IN */
+	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	unsigned char *pdid_buf,			/* IN
+		    contains DER encoded kdcPKId */
+	unsigned int pkid_len,				/* IN
+		    contains length of pdid_buf */
+	int *valid_kdcPkId);				/* OUT
+		    1 if kdcPKId matches, otherwise 0 */
+
+krb5_error_code pkinit_identity_set_prompter
+	(pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+	krb5_prompter_fct prompter,			/* IN */
+	void *prompter_data);				/* IN */
+
+#endif	/* _PKINIT_CRYPTO_H */
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
new file mode 100644
index 000000000..1859b4f1a
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -0,0 +1,5612 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <dirent.h>
+
+/*
+ * Q: What is this SILLYDECRYPT stuff about?
+ * A: When using the ActivCard Linux pkcs11 library (v2.0.1),
+ *    the decrypt function fails.  By inserting an extra
+ *    function call, which serves nothing but to change the
+ *    stack, we were able to work around the issue.  If the
+ *    ActivCard library is fixed in the future, this
+ *    definition and related code can be removed.
+ */
+#define SILLYDECRYPT
+
+#include "pkinit_crypto_openssl.h"
+
+static struct pkcs11_errstrings {
+    short code;
+    char *text;
+} pkcs11_errstrings[] = {
+    { 0x0,	"ok" },
+    { 0x1,	"cancel" },
+    { 0x2,	"host memory" },
+    { 0x3,	"slot id invalid" },
+    { 0x5,	"general error" },
+    { 0x6,	"function failed" },
+    { 0x7,	"arguments bad" },
+    { 0x8,	"no event" },
+    { 0x9,	"need to create threads" },
+    { 0xa,	"cant lock" },
+    { 0x10,	"attribute read only" },
+    { 0x11,	"attribute sensitive" },
+    { 0x12,	"attribute type invalid" },
+    { 0x13,	"attribute value invalid" },
+    { 0x20,	"data invalid" },
+    { 0x21,	"data len range" },
+    { 0x30,	"device error" },
+    { 0x31,	"device memory" },
+    { 0x32,	"device removed" },
+    { 0x40,	"encrypted data invalid" },
+    { 0x41,	"encrypted data len range" },
+    { 0x50,	"function canceled" },
+    { 0x51,	"function not parallel" },
+    { 0x54,	"function not supported" },
+    { 0x60,	"key handle invalid" },
+    { 0x62,	"key size range" },
+    { 0x63,	"key type inconsistent" },
+    { 0x64,	"key not needed" },
+    { 0x65,	"key changed" },
+    { 0x66,	"key needed" },
+    { 0x67,	"key indigestible" },
+    { 0x68,	"key function not permitted" },
+    { 0x69,	"key not wrappable" },
+    { 0x6a,	"key unextractable" },
+    { 0x70,	"mechanism invalid" },
+    { 0x71,	"mechanism param invalid" },
+    { 0x82,	"object handle invalid" },
+    { 0x90,	"operation active" },
+    { 0x91,	"operation not initialized" },
+    { 0xa0,	"pin incorrect" },
+    { 0xa1,	"pin invalid" },
+    { 0xa2,	"pin len range" },
+    { 0xa3,	"pin expired" },
+    { 0xa4,	"pin locked" },
+    { 0xb0,	"session closed" },
+    { 0xb1,	"session count" },
+    { 0xb3,	"session handle invalid" },
+    { 0xb4,	"session parallel not supported" },
+    { 0xb5,	"session read only" },
+    { 0xb6,	"session exists" },
+    { 0xb7,	"session read only exists" },
+    { 0xb8,	"session read write so exists" },
+    { 0xc0,	"signature invalid" },
+    { 0xc1,	"signature len range" },
+    { 0xd0,	"template incomplete" },
+    { 0xd1,	"template inconsistent" },
+    { 0xe0,	"token not present" },
+    { 0xe1,	"token not recognized" },
+    { 0xe2,	"token write protected" },
+    { 0xf0,	"unwrapping key handle invalid" },
+    { 0xf1,	"unwrapping key size range" },
+    { 0xf2,	"unwrapping key type inconsistent" },
+    { 0x100,	"user already logged in" },
+    { 0x101,	"user not logged in" },
+    { 0x102,	"user pin not initialized" },
+    { 0x103,	"user type invalid" },
+    { 0x104,	"user another already logged in" },
+    { 0x105,	"user too many types" },
+    { 0x110,	"wrapped key invalid" },
+    { 0x112,	"wrapped key len range" },
+    { 0x113,	"wrapping key handle invalid" },
+    { 0x114,	"wrapping key size range" },
+    { 0x115,	"wrapping key type inconsistent" },
+    { 0x120,	"random seed not supported" },
+    { 0x121,	"random no rng" },
+    { 0x130,	"domain params invalid" },
+    { 0x150,	"buffer too small" },
+    { 0x160,	"saved state invalid" },
+    { 0x170,	"information sensitive" },
+    { 0x180,	"state unsaveable" },
+    { 0x190,	"cryptoki not initialized" },
+    { 0x191,	"cryptoki already initialized" },
+    { 0x1a0,	"mutex bad" },
+    { 0x1a1,	"mutex not locked" },
+    { 0x200,	"function rejected" },
+    { -1,	NULL }
+};
+
+/* DH parameters */
+unsigned char pkinit_1024_dhprime[128] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+unsigned char pkinit_2048_dhprime[2048/8] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+    0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+    0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+    0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+unsigned char pkinit_4096_dhprime[4096/8] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+    0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+    0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+    0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+    0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+    0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+    0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+    0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+    0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+    0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+    0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+    0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+    0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+    0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+    0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+    0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+    0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+    0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+    0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+    0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+    0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+    0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+    0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+    0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+    0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+    0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static int pkinit_oids_refs = 0;
+
+krb5_error_code
+pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
+
+    krb5_error_code retval = ENOMEM;
+    pkinit_plg_crypto_context ctx = NULL;
+
+    /* initialize openssl routines */
+    openssl_init();
+
+    ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx));
+    if (ctx == NULL)
+	goto out;
+    memset(ctx, 0, sizeof(*ctx));
+
+    pkiDebug("%s: initializing openssl crypto context at %p\n",
+	     __FUNCTION__, ctx);
+    retval = pkinit_init_pkinit_oids(ctx);
+    if (retval)
+	goto out;
+
+    retval = pkinit_init_dh_params(ctx);
+    if (retval)
+	goto out;
+
+    *cryptoctx = ctx;
+
+out:
+    if (retval && ctx != NULL)
+	    pkinit_fini_plg_crypto(ctx);
+
+    return retval;
+}
+
+void
+pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)
+{
+    pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx);
+
+    if (cryptoctx == NULL)
+	return;
+    pkinit_fini_pkinit_oids(cryptoctx);
+    pkinit_fini_dh_params(cryptoctx);
+    free(cryptoctx);
+}
+
+krb5_error_code
+pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
+{
+    krb5_error_code retval = ENOMEM;
+    pkinit_identity_crypto_context ctx = NULL;
+
+    ctx = (pkinit_identity_crypto_context)malloc(sizeof(*ctx));
+    if (ctx == NULL)
+	goto out;
+    memset(ctx, 0, sizeof(*ctx));
+
+    retval = pkinit_init_certs(ctx);
+    if (retval)
+	goto out;
+
+    retval = pkinit_init_pkcs11(ctx);
+    if (retval)
+	goto out;
+
+    pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
+    *idctx = ctx;
+
+out:
+    if (retval) {
+	if (ctx)
+	    pkinit_fini_identity_crypto(ctx);
+    }
+
+    return retval;
+}
+
+void
+pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)
+{
+    if (idctx == NULL)
+	return;
+
+    pkiDebug("%s: freeing   ctx at %p\n", __FUNCTION__, idctx);
+    pkinit_fini_certs(idctx);
+    pkinit_fini_pkcs11(idctx);
+    free(idctx);
+}
+
+krb5_error_code
+pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
+{
+
+    krb5_error_code retval = ENOMEM;
+    pkinit_req_crypto_context ctx = NULL;
+
+    ctx = (pkinit_req_crypto_context)malloc(sizeof(*ctx));
+    if (ctx == NULL)
+	goto out;
+    memset(ctx, 0, sizeof(*ctx));
+
+    ctx->dh = NULL;
+    ctx->received_cert = NULL;
+
+    *cryptoctx = ctx;
+
+    pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
+    retval = 0;
+out:
+    if (retval)
+	free(ctx);
+
+    return retval;
+}
+
+void
+pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
+{
+    if (req_cryptoctx == NULL)
+	return;
+
+    pkiDebug("%s: freeing   ctx at %p\n", __FUNCTION__, req_cryptoctx);
+    if (req_cryptoctx->dh != NULL)
+      DH_free(req_cryptoctx->dh);
+    if (req_cryptoctx->received_cert != NULL)
+      X509_free(req_cryptoctx->received_cert);
+
+    free(req_cryptoctx);
+}
+
+static krb5_error_code
+pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
+{
+    krb5_error_code retval = ENOMEM;
+    int nid = 0;
+
+    /*
+     * If OpenSSL already knows about the OID, use the
+     * existing definition. Otherwise, create an OID object.
+     */
+    #define CREATE_OBJ_IF_NEEDED(oid, vn, sn, ln) \
+	nid = OBJ_txt2nid(oid); \
+	if (nid == NID_undef) { \
+	    nid = OBJ_create(oid, sn, ln); \
+	    if (nid == NID_undef) { \
+		pkiDebug("Error creating oid object for '%s'\n", oid); \
+		goto out; \
+	    } \
+	} \
+	ctx->vn = OBJ_nid2obj(nid);
+    
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.2", id_pkinit_san,
+			 "id-pkinit-san", "KRB5PrincipalName");
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.1", id_pkinit_authData,
+			 "id-pkinit-authdata", "PKINIT signedAuthPack");
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.2", id_pkinit_DHKeyData,
+			 "id-pkinit-DHKeyData", "PKINIT dhSignedData");
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.3", id_pkinit_rkeyData,
+			 "id-pkinit-rkeyData", "PKINIT encKeyPack");
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.4", id_pkinit_KPClientAuth,
+			 "id-pkinit-KPClientAuth", "PKINIT Client EKU");
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.5", id_pkinit_KPKdc,
+			 "id-pkinit-KPKdc", "KDC EKU");
+
+#if 0
+    CREATE_OBJ_IF_NEEDED("1.2.840.113549.1.7.1", id_pkinit_authData9,
+			 "id-pkcs7-data", "PKCS7 data");
+#else
+    /* See note in pkinit_pkcs7type2oid() */
+    ctx->id_pkinit_authData9 = NULL;
+#endif
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.2", id_ms_kp_sc_logon,
+			 "id-ms-kp-sc-logon EKU", "Microsoft SmartCard Login EKU");
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.3", id_ms_san_upn,
+			 "id-ms-san-upn", "Microsoft Universal Principal Name");
+
+    CREATE_OBJ_IF_NEEDED("1.3.6.1.5.5.7.3.1", id_kp_serverAuth,
+			 "id-kp-serverAuth EKU", "Server Authentication EKU");
+
+    /* Success */
+    retval = 0;
+    pkinit_oids_refs++;
+
+out:
+    return retval;
+}
+
+static krb5_error_code
+get_cert(char *filename, X509 **retcert)
+{
+    X509 *cert = NULL;
+    BIO *tmp = NULL;
+    int code;
+    krb5_error_code retval;
+
+    if (filename == NULL || retcert == NULL)
+	return EINVAL;
+
+    *retcert = NULL;
+
+    tmp = BIO_new(BIO_s_file());
+    if (tmp == NULL)
+	return ENOMEM;
+
+    code = BIO_read_filename(tmp, filename);
+    if (code == 0) {
+	retval = errno;
+	goto cleanup;
+    }
+
+    cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
+    if (cert == NULL) {
+	retval = EIO;
+	pkiDebug("failed to read certificate from %s\n", filename);
+	goto cleanup;
+    }
+    *retcert = cert;
+    retval = 0;
+cleanup:
+    if (tmp != NULL)
+	BIO_free(tmp);
+    return retval;
+}
+
+static krb5_error_code
+get_key(char *filename, EVP_PKEY **retkey)
+{
+    EVP_PKEY *pkey = NULL;
+    BIO *tmp = NULL;
+    int code;
+    krb5_error_code retval;
+
+    if (filename == NULL || retkey == NULL)
+	return EINVAL;
+
+    tmp = BIO_new(BIO_s_file());
+    if (tmp == NULL)
+	return ENOMEM;
+
+    code = BIO_read_filename(tmp, filename);
+    if (code == 0) {
+	retval = errno;
+	goto cleanup;
+    }
+    pkey = (EVP_PKEY *) PEM_read_bio_PrivateKey(tmp, NULL, NULL, NULL);
+    if (pkey == NULL) {
+	retval = EIO;
+	pkiDebug("failed to read private key from %s\n", filename);
+	goto cleanup;
+    }
+    *retkey = pkey;
+    retval = 0;
+cleanup:
+    if (tmp != NULL)
+	BIO_free(tmp);
+    return retval;
+}
+
+static void
+pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
+{
+    if (ctx == NULL)
+	return;
+
+    /* Only call OBJ_cleanup once! */
+    if (--pkinit_oids_refs == 0)
+	OBJ_cleanup();
+}
+
+static krb5_error_code
+pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
+{
+    krb5_error_code retval = ENOMEM;
+
+    plgctx->dh_1024 = DH_new();
+    if (plgctx->dh_1024 == NULL)
+	goto cleanup;
+    plgctx->dh_1024->p = BN_bin2bn(pkinit_1024_dhprime,
+	sizeof(pkinit_1024_dhprime), NULL);
+    if ((plgctx->dh_1024->g = BN_new()) == NULL ||
+	(plgctx->dh_1024->q = BN_new()) == NULL)
+	goto cleanup;
+    BN_set_word(plgctx->dh_1024->g, DH_GENERATOR_2);
+    BN_rshift1(plgctx->dh_1024->q, plgctx->dh_1024->p);
+
+    plgctx->dh_2048 = DH_new();
+    if (plgctx->dh_2048 == NULL)
+	goto cleanup;
+    plgctx->dh_2048->p = BN_bin2bn(pkinit_2048_dhprime,
+	sizeof(pkinit_2048_dhprime), NULL);
+    if ((plgctx->dh_2048->g = BN_new()) == NULL ||
+	(plgctx->dh_2048->q = BN_new()) == NULL)
+	goto cleanup;
+    BN_set_word(plgctx->dh_2048->g, DH_GENERATOR_2);
+    BN_rshift1(plgctx->dh_2048->q, plgctx->dh_2048->p);
+
+    plgctx->dh_4096 = DH_new();
+    if (plgctx->dh_4096 == NULL)
+	goto cleanup;
+    plgctx->dh_4096->p = BN_bin2bn(pkinit_4096_dhprime,
+	sizeof(pkinit_4096_dhprime), NULL);
+    if ((plgctx->dh_4096->g = BN_new()) == NULL ||
+	(plgctx->dh_4096->q = BN_new()) == NULL)
+	goto cleanup;
+    BN_set_word(plgctx->dh_4096->g, DH_GENERATOR_2);
+    BN_rshift1(plgctx->dh_4096->q, plgctx->dh_4096->p);
+
+    retval = 0;
+
+cleanup:
+    if (retval)
+	pkinit_fini_dh_params(plgctx);
+
+    return retval;
+}
+
+static void
+pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)
+{
+    if (plgctx->dh_1024 != NULL)
+	DH_free(plgctx->dh_1024);
+    if (plgctx->dh_2048 != NULL)
+	DH_free(plgctx->dh_2048);
+    if (plgctx->dh_4096 != NULL)
+	DH_free(plgctx->dh_4096);
+
+    plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL;
+}
+
+static krb5_error_code
+pkinit_init_certs(pkinit_identity_crypto_context ctx)
+{
+    krb5_error_code retval = ENOMEM;
+    int i;
+
+    for (i = 0; i < MAX_CREDS_ALLOWED; i++)
+	ctx->creds[i] = NULL;
+    ctx->my_certs = NULL;
+    ctx->cert_index = 0;
+    ctx->my_key = NULL;
+    ctx->trustedCAs = NULL;
+    ctx->intermediateCAs = NULL;
+    ctx->revoked = NULL;
+
+    retval = 0;
+    return retval;
+}
+
+static void
+pkinit_fini_certs(pkinit_identity_crypto_context ctx)
+{
+    if (ctx == NULL)
+	return;
+
+    if (ctx->my_certs != NULL)
+	sk_X509_pop_free(ctx->my_certs, X509_free);
+
+    if (ctx->my_key != NULL)
+	EVP_PKEY_free(ctx->my_key);
+
+    if (ctx->trustedCAs != NULL)
+	sk_X509_pop_free(ctx->trustedCAs, X509_free);
+
+    if (ctx->intermediateCAs != NULL)
+	sk_X509_pop_free(ctx->intermediateCAs, X509_free);
+
+    if (ctx->revoked != NULL)
+	sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free);
+}
+
+static krb5_error_code
+pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)
+{
+    krb5_error_code retval = ENOMEM;
+
+#ifndef WITHOUT_PKCS11
+    ctx->p11_module_name = strdup(PKCS11_MODNAME);
+    if (ctx->p11_module_name == NULL)
+	return retval;
+    ctx->p11_module = NULL;
+    ctx->slotid = PK_NOSLOT;
+    ctx->token_label = NULL;
+    ctx->cert_label = NULL;
+    ctx->session = CK_INVALID_HANDLE;
+    ctx->p11 = NULL;
+#endif
+    ctx->pkcs11_method = 0;
+
+    retval = 0;
+    return retval;
+}
+
+static void
+pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
+{
+#ifndef WITHOUT_PKCS11
+    if (ctx == NULL)
+	return;
+
+    if (ctx->p11 != NULL) {
+	if (ctx->session) {
+	    ctx->p11->C_CloseSession(ctx->session);
+	    ctx->session = CK_INVALID_HANDLE;
+	}
+	ctx->p11->C_Finalize(NULL_PTR);
+	ctx->p11 = NULL;
+    }
+    if (ctx->p11_module != NULL) {
+	pkinit_C_UnloadModule(ctx->p11_module);
+	ctx->p11_module = NULL;
+    }
+    if (ctx->p11_module_name != NULL)
+	free(ctx->p11_module_name);
+    if (ctx->token_label != NULL)
+	free(ctx->token_label);
+    if (ctx->cert_id != NULL)
+	free(ctx->cert_id);
+    if (ctx->cert_label != NULL)
+	free(ctx->cert_label);
+#endif
+}
+
+krb5_error_code
+pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
+			     krb5_prompter_fct prompter,
+			     void *prompter_data)
+{
+    id_cryptoctx->prompter = prompter;
+    id_cryptoctx->prompter_data = prompter_data;
+
+    return 0;
+}
+
+krb5_error_code
+cms_signeddata_create(krb5_context context,
+		      pkinit_plg_crypto_context plg_cryptoctx,
+		      pkinit_req_crypto_context req_cryptoctx,
+		      pkinit_identity_crypto_context id_cryptoctx,
+		      int cms_msg_type,
+		      int include_certchain,
+		      unsigned char *data,
+		      unsigned int data_len,
+		      unsigned char **signed_data,
+		      unsigned int *signed_data_len)
+{
+    krb5_error_code retval = ENOMEM;
+    PKCS7  *p7 = NULL, *inner_p7 = NULL;
+    PKCS7_SIGNED *p7s = NULL;
+    PKCS7_SIGNER_INFO *p7si = NULL;
+    unsigned char *p;
+    ASN1_TYPE *pkinit_data = NULL;
+    STACK_OF(X509) * cert_stack = NULL;
+    ASN1_OCTET_STRING *digest_attr = NULL;
+    EVP_MD_CTX ctx, ctx2;
+    const EVP_MD *md_tmp = NULL;
+    unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
+    unsigned char *digestInfo_buf = NULL, *abuf = NULL;
+    unsigned int md_len, md_len2, alen, digestInfo_len;
+    STACK_OF(X509_ATTRIBUTE) * sk;
+    unsigned char *sig = NULL;
+    unsigned int sig_len = 0;
+    X509_ALGOR *alg = NULL;
+    ASN1_OCTET_STRING *digest = NULL;
+    unsigned int alg_len = 0, digest_len = 0;
+    unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL;
+    X509 *cert = NULL;
+    ASN1_OBJECT *oid = NULL;
+
+    /* start creating PKCS7 data */
+    if ((p7 = PKCS7_new()) == NULL)
+	goto cleanup;
+    p7->type = OBJ_nid2obj(NID_pkcs7_signed);
+
+    if ((p7s = PKCS7_SIGNED_new()) == NULL)
+	goto cleanup;
+    p7->d.sign = p7s;
+    if (!ASN1_INTEGER_set(p7s->version, 3))
+	goto cleanup;
+
+    /* create a cert chain that has at least the signer's certificate */
+    if ((cert_stack = sk_X509_new_null()) == NULL)
+	goto cleanup;
+
+    cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
+    if (!include_certchain) {
+	pkiDebug("only including signer's certificate\n");
+	sk_X509_push(cert_stack, X509_dup(cert));
+    } else {
+	/* create a cert chain */
+	X509_STORE *certstore = NULL;
+	X509_STORE_CTX certctx;
+	STACK_OF(X509) *certstack = NULL;
+	char buf[DN_BUF_LEN];
+	int i = 0, size = 0;
+
+	if ((certstore = X509_STORE_new()) == NULL)
+	    goto cleanup;
+	pkiDebug("building certificate chain\n");
+	X509_STORE_set_verify_cb_func(certstore, openssl_callback);
+	X509_STORE_CTX_init(&certctx, certstore, cert,
+			    id_cryptoctx->intermediateCAs);
+	X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs);
+	if (!X509_verify_cert(&certctx)) {
+	    pkiDebug("failed to create a certificate chain: %s\n", 
+	    X509_verify_cert_error_string(X509_STORE_CTX_get_error(&certctx)));
+	    if (!sk_X509_num(id_cryptoctx->trustedCAs)) 
+		pkiDebug("No trusted CAs found. Check your X509_anchors\n");
+	    goto cleanup;
+	}
+	certstack = X509_STORE_CTX_get1_chain(&certctx);
+	size = sk_X509_num(certstack);
+	pkiDebug("size of certificate chain = %d\n", size);
+	for(i = 0; i < size - 1; i++) {
+	    X509 *x = sk_X509_value(certstack, i);
+	    X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
+	    pkiDebug("cert #%d: %s\n", i, buf);
+	    sk_X509_push(cert_stack, X509_dup(x));
+	}
+	X509_STORE_CTX_cleanup(&certctx);
+	X509_STORE_free(certstore);
+	sk_X509_pop_free(certstack, X509_free);
+    }
+    p7s->cert = cert_stack;
+
+    /* fill-in PKCS7_SIGNER_INFO */
+    if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
+	goto cleanup;
+    if (!ASN1_INTEGER_set(p7si->version, 1))
+	goto cleanup;
+    if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
+		       X509_get_issuer_name(cert)))
+	goto cleanup;
+    /* because ASN1_INTEGER_set is used to set a 'long' we will do
+     * things the ugly way. */
+    M_ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
+    if (!(p7si->issuer_and_serial->serial =
+	  M_ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
+	goto cleanup;
+
+    /* will not fill-out EVP_PKEY because it's on the smartcard */
+
+    /* Set digest algs */
+    p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
+
+    if (p7si->digest_alg->parameter != NULL)
+	ASN1_TYPE_free(p7si->digest_alg->parameter);
+    if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL)
+	goto cleanup;
+    p7si->digest_alg->parameter->type = V_ASN1_NULL;
+
+    /* Set sig algs */
+    if (p7si->digest_enc_alg->parameter != NULL)
+	ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
+    p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
+    if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
+	goto cleanup;
+    p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
+
+    /* pick the correct oid for the eContentInfo */
+    oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
+    if (oid == NULL)
+	goto cleanup;
+
+    if (cms_msg_type == CMS_SIGN_DRAFT9) {
+	/* don't include signed attributes for pa-type 15 request */
+	abuf = data;
+	alen = data_len;
+    } else {
+	/* add signed attributes */
+	/* compute sha1 digest over the EncapsulatedContentInfo */
+	EVP_MD_CTX_init(&ctx);
+	EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
+	EVP_DigestUpdate(&ctx, data, data_len);
+	md_tmp = EVP_MD_CTX_md(&ctx);
+	EVP_DigestFinal_ex(&ctx, md_data, &md_len);
+
+	/* create a message digest attr */
+	digest_attr = ASN1_OCTET_STRING_new();
+	ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
+	PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,
+				   V_ASN1_OCTET_STRING, (char *) digest_attr);
+
+	/* create a content-type attr */
+	PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, 
+				   V_ASN1_OBJECT, oid);
+
+	/* create the signature over signed attributes. get DER encoded value */
+	/* This is the place where smartcard signature needs to be calculated */
+	sk = p7si->auth_attr;
+	alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
+			     ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
+	if (abuf == NULL)
+	    goto cleanup2;
+    }
+
+#ifndef WITHOUT_PKCS11
+    /* Some tokens can only do RSAEncryption without sha1 hash */
+    /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
+     * function and the hash value into an ASN.1 value of type DigestInfo
+     * DigestInfo::=SEQUENCE {
+     *	digestAlgorithm  AlgorithmIdentifier,
+     *	digest OCTET STRING }
+     */
+    if (id_cryptoctx->pkcs11_method == 1 && 
+	    id_cryptoctx->mech == CKM_RSA_PKCS) {
+	pkiDebug("mech = CKM_RSA_PKCS\n");
+	EVP_MD_CTX_init(&ctx2);
+	/* if this is not draft9 request, include digest signed attribute */
+	if (cms_msg_type != CMS_SIGN_DRAFT9) 
+	    EVP_DigestInit_ex(&ctx2, md_tmp, NULL);
+	else
+	    EVP_DigestInit_ex(&ctx2, EVP_sha1(), NULL);
+	EVP_DigestUpdate(&ctx2, abuf, alen);
+	EVP_DigestFinal_ex(&ctx2, md_data2, &md_len2);
+
+	alg = X509_ALGOR_new();
+	if (alg == NULL)
+	    goto cleanup2;
+	alg->algorithm = OBJ_nid2obj(NID_sha1);
+	alg->parameter = NULL;
+	alg_len = i2d_X509_ALGOR(alg, NULL);
+	alg_buf = (unsigned char *)malloc(alg_len);
+	if (alg_buf == NULL)
+	    goto cleanup2;
+
+	digest = ASN1_OCTET_STRING_new();
+	if (digest == NULL)
+	    goto cleanup2;
+	ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
+	digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
+	digest_buf = (unsigned char *)malloc(digest_len);
+	if (digest_buf == NULL)
+	    goto cleanup2;
+
+	digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
+					  V_ASN1_SEQUENCE);
+	y = digestInfo_buf = (unsigned char *)malloc(digestInfo_len);
+	if (digestInfo_buf == NULL)
+	    goto cleanup2;
+	ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
+			V_ASN1_UNIVERSAL);
+	i2d_X509_ALGOR(alg, &y);
+	i2d_ASN1_OCTET_STRING(digest, &y);
+#ifdef DEBUG_SIG
+	pkiDebug("signing buffer\n");
+	print_buffer(digestInfo_buf, digestInfo_len);
+	print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
+#endif
+	retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
+				  digestInfo_len, &sig, &sig_len);
+    } else
+#endif
+    {
+	pkiDebug("mech = %s\n",
+	    id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
+	retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
+				  &sig, &sig_len);
+    }
+#ifdef DEBUG_SIG
+    print_buffer(sig, sig_len);
+#endif
+    if (cms_msg_type != CMS_SIGN_DRAFT9) 
+	free(abuf);
+    if (retval)
+	goto cleanup2;
+
+    /* Add signature */
+    if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
+			 (int)sig_len)) {
+	unsigned long err = ERR_peek_error();
+	retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	krb5_set_error_message(context, retval, "%s\n",
+			       ERR_error_string(err, NULL));
+	pkiDebug("failed to add a signed digest attribute\n");
+	goto cleanup2;
+    }
+    /* adder signer_info to pkcs7 signed */
+    if (!PKCS7_add_signer(p7, p7si))
+	goto cleanup2;
+
+    /* start on adding data to the pkcs7 signed */
+    if ((inner_p7 = PKCS7_new()) == NULL)
+	goto cleanup2;
+    if ((pkinit_data = ASN1_TYPE_new()) == NULL)
+	goto cleanup2;
+    pkinit_data->type = V_ASN1_OCTET_STRING;
+    if ((pkinit_data->value.octet_string = ASN1_OCTET_STRING_new()) == NULL)
+	goto cleanup2;
+    if (!ASN1_OCTET_STRING_set(pkinit_data->value.octet_string, data,
+			       (int)data_len)) {
+	unsigned long err = ERR_peek_error();
+	retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	krb5_set_error_message(context, retval, "%s\n",
+			       ERR_error_string(err, NULL));
+	pkiDebug("failed to add pkcs7 data\n");
+	goto cleanup2;
+    }
+
+    if (!PKCS7_set0_type_other(inner_p7, OBJ_obj2nid(oid), pkinit_data))
+	goto cleanup2;
+
+    if (p7s->contents != NULL)
+	PKCS7_free(p7s->contents);
+    p7s->contents = inner_p7;
+
+    *signed_data_len = i2d_PKCS7(p7, NULL);
+    if (!(*signed_data_len)) {
+	unsigned long err = ERR_peek_error();
+	retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	krb5_set_error_message(context, retval, "%s\n",
+			       ERR_error_string(err, NULL));
+	pkiDebug("failed to der encode pkcs7\n");
+	goto cleanup2;
+    }
+    if ((p = *signed_data =
+	 (unsigned char *) malloc((size_t)*signed_data_len)) == NULL)
+	goto cleanup2;
+
+    /* DER encode PKCS7 data */
+    retval = i2d_PKCS7(p7, &p);
+    if (!retval) {
+	unsigned long err = ERR_peek_error();
+	retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	krb5_set_error_message(context, retval, "%s\n",
+			       ERR_error_string(err, NULL));
+	pkiDebug("failed to der encode pkcs7\n");
+	goto cleanup2;
+    }
+    retval = 0;
+
+#ifdef DEBUG_ASN1
+    if (cms_msg_type == CMS_SIGN_CLIENT) {
+	print_buffer_bin(*signed_data, *signed_data_len,
+			 "/tmp/client_pkcs7_signeddata");
+    } else {
+	if (cms_msg_type == CMS_SIGN_SERVER) {
+	    print_buffer_bin(*signed_data, *signed_data_len,
+			     "/tmp/kdc_pkcs7_signeddata");
+	} else {
+	    print_buffer_bin(*signed_data, *signed_data_len,
+			     "/tmp/draft9_pkcs7_signeddata");
+	}
+    }
+#endif
+
+  cleanup2:
+    if (cms_msg_type != CMS_SIGN_DRAFT9) 
+	EVP_MD_CTX_cleanup(&ctx);
+#ifndef WITHOUT_PKCS11
+    if (id_cryptoctx->pkcs11_method == 1 && 
+	    id_cryptoctx->mech == CKM_RSA_PKCS) {
+	EVP_MD_CTX_cleanup(&ctx2);
+	if (digest_buf != NULL)
+	    free(digest_buf);
+	if (digestInfo_buf != NULL)
+	    free(digestInfo_buf);
+	if (alg_buf != NULL)
+	    free(alg_buf);
+	if (digest != NULL)
+	    ASN1_OCTET_STRING_free(digest);
+    }
+#endif
+    if (alg != NULL)
+	X509_ALGOR_free(alg);
+  cleanup:
+    if (p7 != NULL) 
+	PKCS7_free(p7);
+    if (sig != NULL)
+	free(sig);
+
+    return retval;
+}
+
+krb5_error_code
+cms_signeddata_verify(krb5_context context,
+		      pkinit_plg_crypto_context plgctx,
+		      pkinit_req_crypto_context reqctx,
+		      pkinit_identity_crypto_context idctx,
+		      int cms_msg_type,
+		      int require_crl_checking,
+		      unsigned char *signed_data,
+		      unsigned int signed_data_len,
+		      unsigned char **data,
+		      unsigned int *data_len,
+		      unsigned char **authz_data,
+		      unsigned int *authz_data_len)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    PKCS7 *p7 = NULL;
+    BIO *out = NULL;
+    int flags = PKCS7_NOVERIFY, i = 0;
+    unsigned int vflags = 0, size = 0;
+    const unsigned char *p = signed_data;
+    STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
+    PKCS7_SIGNER_INFO *si = NULL;
+    X509 *x = NULL;
+    X509_STORE *store = NULL;
+    X509_STORE_CTX cert_ctx;
+    STACK_OF(X509) *intermediateCAs = NULL;
+    STACK_OF(X509_CRL) *revoked = NULL;
+    STACK_OF(X509) *verified_chain = NULL;
+    ASN1_OBJECT *oid = NULL;
+    krb5_external_principal_identifier **krb5_verified_chain = NULL;
+    krb5_data *authz = NULL;
+    char buf[DN_BUF_LEN];
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin(signed_data, signed_data_len,
+		     "/tmp/client_received_pkcs7_signeddata");
+#endif
+
+    /* Do this early enough to create the shadow OID for pkcs7-data if needed */
+    oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
+    if (oid == NULL)
+	goto cleanup;
+
+    /* decode received PKCS7 message */
+    if ((p7 = d2i_PKCS7(NULL, &p, (int)signed_data_len)) == NULL) {
+	unsigned long err = ERR_peek_error();
+	krb5_set_error_message(context, retval, "%s\n",
+			       ERR_error_string(err, NULL));
+	pkiDebug("%s: failed to decode message: %s\n",
+		 __FUNCTION__, ERR_error_string(err, NULL));
+	goto cleanup;
+    }
+
+    /* verify that the received message is PKCS7 SignedData message */
+    if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
+	pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
+		 OBJ_obj2nid(p7->type));
+	krb5_set_error_message(context, retval, "wrong oid\n");
+	goto cleanup;
+    }
+
+    /* setup to verify X509 certificate used to sign PKCS7 message */
+    if (!(store = X509_STORE_new()))
+	goto cleanup;
+
+    /* check if we are inforcing CRL checking */
+    vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
+    if (require_crl_checking)
+	X509_STORE_set_verify_cb_func(store, openssl_callback);
+    else
+	X509_STORE_set_verify_cb_func(store, openssl_callback_ignore_crls);
+    X509_STORE_set_flags(store, vflags);
+
+    /* get the signer's information from the PKCS7 message */
+    if ((si_sk = PKCS7_get_signer_info(p7)) == NULL)
+	goto cleanup;
+    if ((si = sk_PKCS7_SIGNER_INFO_value(si_sk, 0)) == NULL)
+	goto cleanup;
+    if ((x = PKCS7_cert_from_signer_info(p7, si)) == NULL)
+	goto cleanup;
+
+    /* create available CRL information (get local CRLs and include CRLs
+     * received in the PKCS7 message
+     */
+    if (idctx->revoked == NULL)
+	revoked = p7->d.sign->crl;
+    else if (p7->d.sign->crl == NULL)
+	revoked = idctx->revoked;
+    else {
+	size = sk_X509_CRL_num(idctx->revoked);
+	revoked = sk_X509_CRL_new_null();
+	for (i = 0; i < size; i++)
+	    sk_X509_CRL_push(revoked, sk_X509_CRL_value(idctx->revoked, i));
+	size = sk_X509_num(p7->d.sign->crl);
+	for (i = 0; i < size; i++)
+	    sk_X509_CRL_push(revoked, sk_X509_CRL_value(p7->d.sign->crl, i));
+    }
+
+    /* create available intermediate CAs chains (get local intermediateCAs and
+     * include the CA chain received in the PKCS7 message
+     */
+    if (idctx->intermediateCAs == NULL)
+	intermediateCAs = p7->d.sign->cert;
+    else if (p7->d.sign->cert == NULL)
+	intermediateCAs = idctx->intermediateCAs;
+    else {
+	size = sk_X509_num(idctx->intermediateCAs);
+	intermediateCAs = sk_X509_new_null();
+	for (i = 0; i < size; i++) {
+	    sk_X509_push(intermediateCAs,
+		sk_X509_value(idctx->intermediateCAs, i));
+	}
+	size = sk_X509_num(p7->d.sign->cert);
+	for (i = 0; i < size; i++) {
+	    sk_X509_push(intermediateCAs, sk_X509_value(p7->d.sign->cert, i));
+	}
+    }
+
+    /* initialize x509 context with the received certificate and
+     * trusted and intermediate CA chains and CRLs
+     */
+    if (!X509_STORE_CTX_init(&cert_ctx, store, x, intermediateCAs))
+	goto cleanup;
+
+    X509_STORE_CTX_set0_crls(&cert_ctx, revoked);
+
+    /* add trusted CAs certificates for cert verification */
+    if (idctx->trustedCAs != NULL)
+	X509_STORE_CTX_trusted_stack(&cert_ctx, idctx->trustedCAs);
+    else {
+	pkiDebug("unable to find any trusted CAs\n");
+	goto cleanup;
+    }
+#ifdef DEBUG_CERTCHAIN
+    if (intermediateCAs != NULL) {
+	size = sk_X509_num(intermediateCAs);
+	pkiDebug("untrusted cert chain of size %d\n", size);
+	for (i = 0; i < size; i++) {
+	    X509_NAME_oneline(X509_get_subject_name(
+		sk_X509_value(intermediateCAs, i)), buf, sizeof(buf));
+	    pkiDebug("cert #%d: %s\n", i, buf);
+	}
+    }
+    if (idctx->trustedCAs != NULL) {
+	size = sk_X509_num(idctx->trustedCAs);
+	pkiDebug("trusted cert chain of size %d\n", size);
+	for (i = 0; i < size; i++) {
+	    X509_NAME_oneline(X509_get_subject_name(
+		sk_X509_value(idctx->trustedCAs, i)), buf, sizeof(buf));
+	    pkiDebug("cert #%d: %s\n", i, buf);
+	}
+    }
+    if (revoked != NULL) {
+	size = sk_X509_CRL_num(revoked);
+	pkiDebug("CRL chain of size %d\n", size);
+	for (i = 0; i < size; i++) {
+	    X509_CRL *crl = sk_X509_CRL_value(revoked, i);
+	    X509_NAME_oneline(X509_CRL_get_issuer(crl), buf, sizeof(buf));
+	    pkiDebug("crls by CA #%d: %s\n", i , buf);
+	}
+    }
+#endif
+
+    i = X509_verify_cert(&cert_ctx);
+    if (i <= 0) {
+	int j = X509_STORE_CTX_get_error(&cert_ctx);
+
+	reqctx->received_cert = X509_dup(cert_ctx.current_cert);
+	switch(j) {
+	    case X509_V_ERR_CERT_REVOKED:
+		retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
+		break;
+	    case X509_V_ERR_UNABLE_TO_GET_CRL:
+		retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN;
+		break;
+	    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+	    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+		retval = KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE;
+		break;
+	    default:
+		retval = KRB5KDC_ERR_INVALID_CERTIFICATE;
+	}
+	X509_NAME_oneline(X509_get_subject_name(
+	    reqctx->received_cert), buf, sizeof(buf));
+	pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf, j,
+		 X509_verify_cert_error_string(j));
+	krb5_set_error_message(context, retval, "%s\n",
+	    X509_verify_cert_error_string(j));
+#ifdef DEBUG_CERTCHAIN
+	size = sk_X509_num(p7->d.sign->cert);
+	pkiDebug("received cert chain of size %d\n", size);
+	for (j = 0; j < size; j++) {
+	    X509 *tmp_cert = sk_X509_value(p7->d.sign->cert, j);
+	    X509_NAME_oneline(X509_get_subject_name(tmp_cert), buf, sizeof(buf));
+	    pkiDebug("cert #%d: %s\n", j, buf);
+	}
+#endif
+    } else {
+	/* retrieve verified certificate chain */
+	if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) 
+	    verified_chain = X509_STORE_CTX_get1_chain(&cert_ctx);
+    }
+    X509_STORE_CTX_cleanup(&cert_ctx);
+    if (i <= 0)
+	goto cleanup;
+
+    out = BIO_new(BIO_s_mem());
+    if (cms_msg_type == CMS_SIGN_DRAFT9)
+	flags |= PKCS7_NOATTR;
+    if (PKCS7_verify(p7, NULL, store, NULL, out, flags)) {
+	int valid_oid = 0;
+
+	if (!OBJ_cmp(p7->d.sign->contents->type, oid)) 
+	    valid_oid = 1;
+	else if (cms_msg_type == CMS_SIGN_DRAFT9) {
+	    /*
+	     * Various implementations of the pa-type 15 request use
+	     * different OIDS.  We check that the returned object
+	     * has any of the acceptable OIDs
+	     */
+	    ASN1_OBJECT *client_oid = NULL, *server_oid = NULL, *rsa_oid = NULL;
+	    client_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_CLIENT);
+	    server_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_SERVER);
+	    rsa_oid = pkinit_pkcs7type2oid(plgctx, CMS_ENVEL_SERVER);
+	    if (!OBJ_cmp(p7->d.sign->contents->type, client_oid) ||
+		!OBJ_cmp(p7->d.sign->contents->type, server_oid) ||
+		!OBJ_cmp(p7->d.sign->contents->type, rsa_oid))
+		valid_oid = 1;
+	}
+
+	if (valid_oid) 
+	    pkiDebug("PKCS7 Verification successful\n");
+	else {
+	    pkiDebug("wrong oid in eContentType\n");
+	    print_buffer(p7->d.sign->contents->type->data, 
+		(unsigned int)p7->d.sign->contents->type->length);
+	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	    krb5_set_error_message(context, retval, "wrong oid\n");
+	    goto cleanup;
+	}
+    }
+    else {
+	unsigned long err = ERR_peek_error();
+	switch(ERR_GET_REASON(err)) {
+	    case PKCS7_R_DIGEST_FAILURE:
+		retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED;
+		break;
+	    case PKCS7_R_SIGNATURE_FAILURE:
+	    default:
+		retval = KRB5KDC_ERR_INVALID_SIG;
+	}
+	pkiDebug("PKCS7 Verification failure\n");
+	krb5_set_error_message(context, retval, "%s\n",
+			       ERR_error_string(err, NULL));
+	goto cleanup;
+    }
+
+    /* transfer the data from PKCS7 message into return buffer */
+    for (size = 0;;) {
+	if ((*data = realloc(*data, size + 1024 * 10)) == NULL)
+	    goto cleanup;
+	i = BIO_read(out, &((*data)[size]), 1024 * 10);
+	if (i <= 0)
+	    break;
+	else
+	    size += i;
+    }
+    *data_len = size;
+
+    reqctx->received_cert = X509_dup(x);
+
+    /* generate authorization data */
+    if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) {
+
+	if (authz_data == NULL || authz_data_len == NULL) 
+	    goto out;
+
+	*authz_data = NULL;
+	retval = create_identifiers_from_stack(verified_chain, 
+					       &krb5_verified_chain);
+	if (retval) {
+	    pkiDebug("create_identifiers_from_stack failed\n");
+	    goto cleanup;
+	}
+
+	retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_verified_chain, &authz);
+	if (retval) {
+	    pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
+	    goto cleanup;
+	}
+#ifdef DEBUG_ASN1
+	print_buffer_bin((unsigned char *)authz->data, authz->length,
+			 "/tmp/kdc_ad_initial_verified_cas");
+#endif
+	*authz_data = (unsigned char *)malloc(authz->length);
+	if (*authz_data == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	memcpy(*authz_data, authz->data, authz->length);
+	*authz_data_len = authz->length;
+    }
+  out:
+    retval = 0;
+
+  cleanup:
+    if (out != NULL)
+	BIO_free(out);
+    if (store != NULL)
+	X509_STORE_free(store);
+    if (p7 != NULL) {
+	if (idctx->intermediateCAs != NULL && p7->d.sign->cert)
+	    sk_X509_free(intermediateCAs);
+	if (idctx->revoked != NULL && p7->d.sign->crl)
+	    sk_X509_CRL_free(revoked);
+	PKCS7_free(p7);
+    }
+    if (verified_chain != NULL)
+	sk_X509_pop_free(verified_chain, X509_free);
+    if (krb5_verified_chain != NULL)
+	free_krb5_external_principal_identifier(&krb5_verified_chain);
+    if (authz != NULL)
+	krb5_free_data(context, authz);
+
+    return retval;
+}
+
+krb5_error_code
+cms_envelopeddata_create(krb5_context context,
+			 pkinit_plg_crypto_context plgctx,
+			 pkinit_req_crypto_context reqctx,
+			 pkinit_identity_crypto_context idctx,
+			 krb5_preauthtype pa_type,
+			 int include_certchain,
+			 unsigned char *key_pack,
+			 unsigned int key_pack_len,
+			 unsigned char **out,
+			 unsigned int *out_len)
+{
+
+    krb5_error_code retval = ENOMEM;
+    PKCS7 *p7 = NULL;
+    BIO *in = NULL;
+    unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL;
+    int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY;
+    STACK_OF(X509) *encerts = NULL;
+    const EVP_CIPHER *cipher = NULL;
+    int cms_msg_type;
+
+    /* create the PKCS7 SignedData portion of the PKCS7 EnvelopedData */
+    switch ((int)pa_type) {
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	    cms_msg_type = CMS_SIGN_DRAFT9;
+	    break;
+	case KRB5_PADATA_PK_AS_REQ:
+	    cms_msg_type = CMS_ENVEL_SERVER;
+	    break;
+	default:
+	    goto cleanup;
+    }
+
+    retval = cms_signeddata_create(context, plgctx, reqctx, idctx,
+	cms_msg_type, include_certchain, key_pack, key_pack_len,
+	&signed_data, (unsigned int *)&signed_data_len);
+    if (retval) {
+	pkiDebug("failed to create pkcs7 signed data\n");
+	goto cleanup;
+    }
+
+    /* check we have client's certificate */
+    if (reqctx->received_cert == NULL) {
+	retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	goto cleanup;
+    }
+    encerts = sk_X509_new_null();
+    sk_X509_push(encerts, reqctx->received_cert);
+
+    cipher = EVP_des_ede3_cbc();
+    in = BIO_new(BIO_s_mem());
+    switch (pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    prepare_enc_data(signed_data, signed_data_len, &enc_data,
+			     &enc_data_len);
+	    retval = BIO_write(in, enc_data, enc_data_len);
+	    if (retval != enc_data_len) {
+		pkiDebug("BIO_write only wrote %d\n", retval);
+		goto cleanup;
+	    }
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    retval = BIO_write(in, signed_data, signed_data_len);
+		if (retval != signed_data_len) {
+		    pkiDebug("BIO_write only wrote %d\n", retval);
+		    goto cleanup;
+	    }
+	    break;
+	default:
+	    retval = -1;
+	    goto cleanup;
+    }
+
+    p7 = PKCS7_encrypt(encerts, in, cipher, flags);
+    if (p7 == NULL) {
+	pkiDebug("failed to encrypt PKCS7 object\n");
+	retval = -1;
+	goto cleanup;
+    }
+    switch (pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    p7->d.enveloped->enc_data->content_type = 
+		OBJ_nid2obj(NID_pkcs7_signed);
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    p7->d.enveloped->enc_data->content_type = 
+		OBJ_nid2obj(NID_pkcs7_data);
+	    break;
+	break;
+    break;
+break;
+    } 
+
+    *out_len = i2d_PKCS7(p7, NULL);
+    if (!*out_len || (p = *out = (unsigned char *)malloc(*out_len)) == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    retval = i2d_PKCS7(p7, &p);
+    if (!retval) {
+	pkiDebug("unable to write pkcs7 object\n");
+	goto cleanup;
+    }
+    retval = 0;
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data");
+#endif
+
+cleanup:
+    if (p7 != NULL)
+	PKCS7_free(p7);
+    if (in != NULL)
+	BIO_free(in);
+    if (signed_data != NULL)
+	free(signed_data);
+    if (enc_data != NULL)
+	free(enc_data);
+    if (encerts != NULL)
+	sk_X509_free(encerts);
+	
+    return retval;
+}
+
+krb5_error_code
+cms_envelopeddata_verify(krb5_context context,
+			 pkinit_plg_crypto_context plg_cryptoctx,
+			 pkinit_req_crypto_context req_cryptoctx,
+			 pkinit_identity_crypto_context id_cryptoctx,
+			 krb5_preauthtype pa_type,
+			 int require_crl_checking,
+			 unsigned char *enveloped_data,
+			 unsigned int enveloped_data_len,
+			 unsigned char **data,
+			 unsigned int *data_len)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    PKCS7 *p7 = NULL;
+    BIO *out = NULL;
+    int i = 0;
+    unsigned int size = 0;
+    const unsigned char *p = enveloped_data;
+    unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0;
+    unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL;
+    int msg_type = 0;
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin(enveloped_data, enveloped_data_len,
+		     "/tmp/client_envelopeddata");
+#endif
+    /* decode received PKCS7 message */
+    if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) {
+	unsigned long err = ERR_peek_error();
+	pkiDebug("failed to decode pkcs7\n");
+	krb5_set_error_message(context, retval, "%s\n",
+			       ERR_error_string(err, NULL));
+	goto cleanup;
+    }
+
+    /* verify that the received message is PKCS7 EnvelopedData message */
+    if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped) {
+	pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n",
+		 OBJ_obj2nid(p7->type));
+	krb5_set_error_message(context, retval, "wrong oid\n");
+	goto cleanup;
+    }
+
+    /* decrypt received PKCS7 message */
+    out = BIO_new(BIO_s_mem());
+    if (pkcs7_decrypt(context, id_cryptoctx, p7, out)) {
+	pkiDebug("PKCS7 decryption successful\n");
+    } else {
+	unsigned long err = ERR_peek_error();
+	if (err != 0)
+	    krb5_set_error_message(context, retval, "%s\n",
+				   ERR_error_string(err, NULL));
+	pkiDebug("PKCS7 decryption failed\n");
+	goto cleanup;
+    }
+
+    /* transfer the decoded PKCS7 SignedData message into a separate buffer */
+    for (;;) {
+	if ((tmp_buf = realloc(tmp_buf, size + 1024 * 10)) == NULL)
+	    goto cleanup;
+	i = BIO_read(out, &(tmp_buf[size]), 1024 * 10);
+	if (i <= 0)
+	    break;
+	else
+	    size += i;
+    }
+    tmp_buf_len = size;
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack");
+#endif
+    /* verify PKCS7 SignedData message */
+    switch (pa_type) {
+	case KRB5_PADATA_PK_AS_REP:
+	    msg_type = CMS_ENVEL_SERVER;
+
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	    msg_type = CMS_SIGN_DRAFT9;
+	    break;
+	default:
+	    pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__, pa_type);
+	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	    goto cleanup;
+    }
+    /*
+     * If this is the RFC style, wrap the signed data to make
+     * decoding easier in the verify routine.
+     * For draft9-compatible, we don't do anything because it
+     * is already wrapped.
+     */
+#ifdef LONGHORN_BETA_COMPAT
+    /*
+     * The Longhorn server returns the expected RFC-style data, but
+     * it is missing the sequence tag and length, so it requires
+     * special processing when wrapping.
+     * This will hopefully be fixed before the final release and
+     * this can all be removed.
+     */
+    if (msg_type == CMS_ENVEL_SERVER || longhorn == 1) {
+	retval = wrap_signeddata(tmp_buf, tmp_buf_len,
+				 &tmp_buf2, &tmp_buf2_len, longhorn);
+	if (retval) {
+	    pkiDebug("failed to encode signeddata\n");
+	    goto cleanup;
+	}
+	vfy_buf = tmp_buf2;
+	vfy_buf_len = tmp_buf2_len;
+
+    } else {
+	vfy_buf = tmp_buf;
+	vfy_buf_len = tmp_buf_len;
+    }
+#else
+    if (msg_type == CMS_ENVEL_SERVER) {
+	retval = wrap_signeddata(tmp_buf, tmp_buf_len,
+				 &tmp_buf2, &tmp_buf2_len);
+	if (retval) {
+	    pkiDebug("failed to encode signeddata\n");
+	    goto cleanup;
+	}
+	vfy_buf = tmp_buf2;
+	vfy_buf_len = tmp_buf2_len;
+
+    } else {
+	vfy_buf = tmp_buf;
+	vfy_buf_len = tmp_buf_len;
+    }
+#endif
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2");
+#endif
+
+    retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx,
+				   id_cryptoctx, msg_type,
+				   require_crl_checking,
+				   vfy_buf, vfy_buf_len,
+				   data, data_len, NULL, NULL);
+
+    if (!retval)
+	pkiDebug("PKCS7 Verification Success\n");
+    else { 	
+	pkiDebug("PKCS7 Verification Failure\n");
+	goto cleanup;
+    }
+
+    retval = 0;
+
+  cleanup:
+
+    if (p7 != NULL)
+	PKCS7_free(p7);
+    if (out != NULL)
+	BIO_free(out);
+    if (tmp_buf != NULL)
+	free(tmp_buf);
+    if (tmp_buf2 != NULL)
+	free(tmp_buf2);
+
+    return retval;
+}
+
+static krb5_error_code
+crypto_retrieve_X509_sans(krb5_context context,
+			  pkinit_plg_crypto_context plgctx,
+			  pkinit_req_crypto_context reqctx,
+			  X509 *cert,
+			  krb5_principal **princs_ret,
+			  krb5_principal **upn_ret,
+			  unsigned char ***dns_ret)
+{
+    krb5_error_code retval = EINVAL;
+    char buf[DN_BUF_LEN];
+    int p = 0, u = 0, d = 0;
+    krb5_principal *princs = NULL;
+    krb5_principal *upns = NULL;
+    unsigned char **dnss = NULL;
+    int i, num_found = 0;
+
+    if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
+	pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
+	return retval;
+    }
+
+    if (cert == NULL) {
+	pkiDebug("%s: no certificate!\n", __FUNCTION__);
+	return retval;
+    }
+
+    X509_NAME_oneline(X509_get_subject_name(cert),
+		      buf, sizeof(buf));
+    pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
+
+    if ((i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) {
+	X509_EXTENSION *ext = NULL;
+	GENERAL_NAMES *ialt = NULL;
+	GENERAL_NAME *gen = NULL;
+	int ret = 0;
+	unsigned int num_sans = 0;
+
+	if (!(ext = X509_get_ext(cert, i)) || !(ialt = X509V3_EXT_d2i(ext))) {
+	    pkiDebug("%s: found no subject alt name extensions\n",
+		     __FUNCTION__);
+	    goto cleanup;
+	}
+	num_sans = sk_GENERAL_NAME_num(ialt);
+
+	pkiDebug("%s: found %d subject alt name extension(s)\n",
+		 __FUNCTION__, num_sans);
+
+	/* OK, we're likely returning something. Allocate return values */
+	if (princs_ret != NULL) {
+	    princs = calloc(num_sans + 1, sizeof(krb5_principal));
+	    if (princs == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	}
+	if (upn_ret != NULL) {
+	    upns = calloc(num_sans + 1, sizeof(krb5_principal));
+	    if (upns == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	}
+	if (dns_ret != NULL) {
+	    dnss = calloc(num_sans + 1, sizeof(*dnss));
+	    if (dnss == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	}
+
+	for (i = 0; i < num_sans; i++) {
+	    krb5_data name = { 0, 0, NULL };
+
+	    gen = sk_GENERAL_NAME_value(ialt, i);
+	    switch (gen->type) {
+	    case GEN_OTHERNAME:
+		name.length = gen->d.otherName->value->value.sequence->length;
+		name.data = (char *)gen->d.otherName->value->value.sequence->data;
+		if (princs != NULL
+		    && OBJ_cmp(plgctx->id_pkinit_san,
+			       gen->d.otherName->type_id) == 0) {
+#ifdef DEBUG_ASN1
+		    print_buffer_bin((unsigned char *)name.data, name.length,
+				     "/tmp/pkinit_san");
+#endif
+		    ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
+		    if (ret) {
+			pkiDebug("%s: failed decoding pkinit san value\n",
+				 __FUNCTION__);
+		    } else {
+			p++;
+			num_found++;
+		    }
+		} else if (upns != NULL
+			   && OBJ_cmp(plgctx->id_ms_san_upn,
+				      gen->d.otherName->type_id) == 0) {
+		    ret = krb5_parse_name(context, name.data, &upns[u]);
+		    if (ret) {
+			pkiDebug("%s: failed parsing ms-upn san value\n",
+				 __FUNCTION__);
+		    } else {
+			u++;
+			num_found++;
+		    }
+		} else {
+		    pkiDebug("%s: unrecognized othername oid in SAN\n",
+			     __FUNCTION__);
+		    continue;
+		}
+
+		break;
+	    case GEN_DNS:
+		if (dnss != NULL) {
+		    pkiDebug("%s: found dns name = %s\n",
+			     __FUNCTION__, gen->d.dNSName->data);
+		    dnss[d] = (unsigned char *)
+				    strdup((char *)gen->d.dNSName->data); 
+		    if (dnss[d] == NULL) {
+			pkiDebug("%s: failed to duplicate dns name\n",
+				 __FUNCTION__);
+		    } else {
+			d++;
+			num_found++;
+		    }
+		}
+		break;
+	    default:
+		pkiDebug("%s: SAN type = %d expecting %d\n",
+			 __FUNCTION__, gen->type, GEN_OTHERNAME);
+	    }
+	}
+	sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
+    }
+
+    retval = 0;
+    if (princs)
+	*princs_ret = princs;
+    if (upns)
+	*upn_ret = upns;
+    if (dnss)
+	*dns_ret = dnss;
+
+  cleanup:
+    if (retval) {
+	if (princs != NULL) {
+	    for (i = 0; princs[i] != NULL; i++)
+		krb5_free_principal(context, princs[i]);
+	    free(princs);
+	}
+	if (upns != NULL) {
+	    for (i = 0; upns[i] != NULL; i++)
+		krb5_free_principal(context, upns[i]);
+	    free(upns);
+	}
+	if (dnss != NULL) {
+	    for (i = 0; dnss[i] != NULL; i++)
+		free(dnss[i]);
+	    free(dnss);
+	}
+    }
+    return retval;
+}
+
+krb5_error_code
+crypto_retrieve_cert_sans(krb5_context context,
+			  pkinit_plg_crypto_context plgctx,
+			  pkinit_req_crypto_context reqctx,
+			  pkinit_identity_crypto_context idctx,
+			  krb5_principal **princs_ret,
+			  krb5_principal **upn_ret,
+			  unsigned char ***dns_ret)
+{
+    krb5_error_code retval = EINVAL;
+
+    if (reqctx->received_cert == NULL) {
+	pkiDebug("%s: No certificate!\n", __FUNCTION__);
+	return retval;
+    }
+
+    return crypto_retrieve_X509_sans(context, plgctx, reqctx,
+				     reqctx->received_cert, princs_ret,
+				     upn_ret, dns_ret);
+}
+
+krb5_error_code
+crypto_check_cert_eku(krb5_context context,
+		      pkinit_plg_crypto_context plgctx,
+		      pkinit_req_crypto_context reqctx,
+		      pkinit_identity_crypto_context idctx,
+		      int checking_kdc_cert,
+		      int allow_secondary_usage,
+		      int *valid_eku)
+{
+    char buf[DN_BUF_LEN];
+    int found_eku = 0;
+    krb5_error_code retval = EINVAL;
+    int i;
+
+    *valid_eku = 0;
+    if (reqctx->received_cert == NULL)
+	goto cleanup;
+
+    X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
+		      buf, sizeof(buf));
+    pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf);
+
+    if ((i = X509_get_ext_by_NID(reqctx->received_cert,
+				 NID_ext_key_usage, -1)) >= 0) {
+	EXTENDED_KEY_USAGE *extusage;
+
+	extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage,
+				    NULL, NULL);
+	if (extusage) {
+	    pkiDebug("%s: found eku info in the cert\n", __FUNCTION__);
+	    for (i = 0; found_eku == 0 && i < sk_ASN1_OBJECT_num(extusage); i++) {
+		ASN1_OBJECT *tmp_oid;
+
+		tmp_oid = sk_ASN1_OBJECT_value(extusage, i);
+		pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n",
+			 __FUNCTION__, i+1, sk_ASN1_OBJECT_num(extusage),
+			 allow_secondary_usage);
+		if (checking_kdc_cert) {
+		    if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPKdc) == 0)
+			 || (allow_secondary_usage
+			 && OBJ_cmp(tmp_oid, plgctx->id_kp_serverAuth) == 0))
+			found_eku = 1;
+		} else {
+		    if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPClientAuth) == 0)
+			 || (allow_secondary_usage
+			 && OBJ_cmp(tmp_oid, plgctx->id_ms_kp_sc_logon) == 0))
+			found_eku = 1;
+		}
+	    }
+	}
+	EXTENDED_KEY_USAGE_free(extusage);
+
+	if (found_eku) {
+	    ASN1_BIT_STRING *usage = NULL;
+	    pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__);
+
+	    /* check that digitalSignature KeyUsage is present */
+	    if ((usage = X509_get_ext_d2i(reqctx->received_cert,
+					  NID_key_usage, NULL, NULL))) {
+
+		if (!ku_reject(reqctx->received_cert,
+			       X509v3_KU_DIGITAL_SIGNATURE)) {
+		    pkiDebug("%s: found digitalSignature KU\n",
+			     __FUNCTION__);
+		    *valid_eku = 1;
+		} else
+		    pkiDebug("%s: didn't find digitalSignature KU\n",
+			     __FUNCTION__);
+	    }
+	    ASN1_BIT_STRING_free(usage);
+	}
+    }
+    retval = 0;
+cleanup:
+    pkiDebug("%s: returning retval %d, valid_eku %d\n",
+	     __FUNCTION__, retval, *valid_eku);
+    return retval;
+}
+
+krb5_error_code
+pkinit_octetstring2key(krb5_context context,
+		       krb5_enctype etype,
+		       unsigned char *key,
+		       unsigned int dh_key_len,
+		       krb5_keyblock * key_block)
+{
+    krb5_error_code retval;
+    unsigned char *buf = NULL;
+    unsigned char md[SHA_DIGEST_LENGTH];
+    unsigned char counter;
+    size_t keybytes, keylength, offset;
+    krb5_data random_data;
+
+
+    if ((buf = (unsigned char *) malloc(dh_key_len)) == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    memset(buf, 0, dh_key_len);
+
+    counter = 0;
+    offset = 0;
+    do {
+	SHA_CTX c;
+
+	SHA1_Init(&c);
+	SHA1_Update(&c, &counter, 1);
+	SHA1_Update(&c, key, dh_key_len);
+	SHA1_Final(md, &c);
+
+	if (dh_key_len - offset < sizeof(md))
+	    memcpy(buf + offset, md, dh_key_len - offset);
+	else
+	    memcpy(buf + offset, md, sizeof(md));
+
+	offset += sizeof(md);
+	counter++;
+    } while (offset < dh_key_len);
+
+    key_block->magic = 0;
+    key_block->enctype = etype;
+
+    retval = krb5_c_keylengths(context, etype, &keybytes, &keylength);
+    if (retval)
+	goto cleanup;
+
+    key_block->length = keylength;
+    key_block->contents = calloc(keylength, sizeof(unsigned char *));
+    if (key_block->contents == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    random_data.length = keybytes;
+    random_data.data = (char *)buf;
+
+    retval = krb5_c_random_to_key(context, etype, &random_data, key_block);
+
+  cleanup:
+    if (buf != NULL)
+	free(buf);
+    if (retval && key_block->contents != NULL && key_block->length != 0) {
+	memset(key_block->contents, 0, key_block->length);
+	key_block->length = 0;
+    }
+
+    return retval;
+}
+
+krb5_error_code
+client_create_dh(krb5_context context,
+		 pkinit_plg_crypto_context plg_cryptoctx,
+		 pkinit_req_crypto_context cryptoctx,
+		 pkinit_identity_crypto_context id_cryptoctx,
+		 int dh_size,
+		 unsigned char **dh_params,
+		 unsigned int *dh_params_len,
+		 unsigned char **dh_pubkey,
+		 unsigned int *dh_pubkey_len)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    unsigned char *buf = NULL;
+    int dh_err = 0;
+    ASN1_INTEGER *pub_key = NULL;
+
+    if (cryptoctx->dh == NULL) {
+	if ((cryptoctx->dh = DH_new()) == NULL)
+	    goto cleanup;
+	if ((cryptoctx->dh->g = BN_new()) == NULL ||
+	    (cryptoctx->dh->q = BN_new()) == NULL)
+	    goto cleanup;
+
+	switch(dh_size) {
+	    case 1024:
+		pkiDebug("client uses 1024 DH keys\n");
+		cryptoctx->dh->p = get_rfc2409_prime_1024(NULL);
+		break;
+	    case 2048:
+		pkiDebug("client uses 2048 DH keys\n");
+		cryptoctx->dh->p = BN_bin2bn(pkinit_2048_dhprime,
+		    sizeof(pkinit_2048_dhprime), NULL);
+		break;
+	    case 4096:
+		pkiDebug("client uses 4096 DH keys\n");
+		cryptoctx->dh->p = BN_bin2bn(pkinit_4096_dhprime,
+		    sizeof(pkinit_4096_dhprime), NULL);
+		break;
+	    default:
+		goto cleanup;
+	}
+
+	BN_set_word((cryptoctx->dh->g), DH_GENERATOR_2);
+	BN_rshift1(cryptoctx->dh->q, cryptoctx->dh->p);
+    }
+
+    DH_generate_key(cryptoctx->dh);
+    DH_check(cryptoctx->dh, &dh_err);
+    if (dh_err != 0) {
+	pkiDebug("Warning: dh_check failed with %d\n", dh_err);
+	if (dh_err & DH_CHECK_P_NOT_PRIME)
+	    pkiDebug("p value is not prime\n");
+	if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME)
+	    pkiDebug("p value is not a safe prime\n");
+	if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR)
+	    pkiDebug("unable to check the generator value\n");
+	if (dh_err & DH_NOT_SUITABLE_GENERATOR)
+	    pkiDebug("the g value is not a generator\n");
+    }
+#ifdef DEBUG_DH
+    print_dh(cryptoctx->dh, "client's DH params\n");
+    print_pubkey(cryptoctx->dh->pub_key, "client's pub_key=");
+#endif
+
+    DH_check_pub_key(cryptoctx->dh, cryptoctx->dh->pub_key, &dh_err);
+    if (dh_err != 0) {
+	pkiDebug("dh_check_pub_key failed with %d\n", dh_err);
+	goto cleanup;
+    }
+
+    /* pack DHparams */
+    /* aglo: usually we could just call i2d_DHparams to encode DH params
+     * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
+     */
+    retval = pkinit_encode_dh_params(cryptoctx->dh->p, cryptoctx->dh->g,
+	cryptoctx->dh->q, dh_params, dh_params_len);
+    if (retval)
+	goto cleanup;
+
+    /* pack DH public key */
+    /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
+     * encoding shall be used as the contents (the value) of the
+     * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
+     * data element
+     */
+    if ((pub_key = BN_to_ASN1_INTEGER(cryptoctx->dh->pub_key, NULL)) == NULL)
+	goto cleanup;
+    *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
+    if ((buf = *dh_pubkey = (unsigned char *)
+	    malloc((size_t) *dh_pubkey_len)) == NULL) {
+	retval  = ENOMEM;
+	goto cleanup;
+    }
+    i2d_ASN1_INTEGER(pub_key, &buf);
+
+    if (pub_key != NULL)
+	ASN1_INTEGER_free(pub_key);
+
+    retval = 0;
+    return retval;
+
+  cleanup:
+    if (cryptoctx->dh != NULL)
+	DH_free(cryptoctx->dh);
+    cryptoctx->dh = NULL;
+    if (*dh_params != NULL)
+	free(*dh_params);
+    *dh_params = NULL;
+    if (*dh_pubkey != NULL)
+	free(*dh_pubkey);
+    *dh_pubkey = NULL;
+    if (pub_key != NULL)
+	ASN1_INTEGER_free(pub_key);
+
+    return retval;
+}
+
+krb5_error_code
+client_process_dh(krb5_context context,
+		  pkinit_plg_crypto_context plg_cryptoctx,
+		  pkinit_req_crypto_context cryptoctx,
+		  pkinit_identity_crypto_context id_cryptoctx,
+		  unsigned char *subjectPublicKey_data,
+		  unsigned int subjectPublicKey_length,
+		  unsigned char **client_key,
+		  unsigned int *client_key_len)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    BIGNUM *server_pub_key = NULL;
+    ASN1_INTEGER *pub_key = NULL;
+    const unsigned char *p = NULL;
+    unsigned char *data = NULL;
+    long data_len;
+
+    /* decode subjectPublicKey (retrieve INTEGER from OCTET_STRING) */
+
+    if (der_decode_data(subjectPublicKey_data, (long)subjectPublicKey_length,
+			&data, &data_len) != 0) {
+	pkiDebug("failed to decode subjectPublicKey\n");
+	retval = -1;
+	goto cleanup;
+    }
+
+    *client_key_len = DH_size(cryptoctx->dh);
+    if ((*client_key = (unsigned char *)
+	    malloc((size_t) *client_key_len)) == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    p = data;
+    if ((pub_key = d2i_ASN1_INTEGER(NULL, &p, data_len)) == NULL)
+	goto cleanup;
+    if ((server_pub_key = ASN1_INTEGER_to_BN(pub_key, NULL)) == NULL)
+	goto cleanup;
+
+    DH_compute_key(*client_key, server_pub_key, cryptoctx->dh);
+#ifdef DEBUG_DH
+    print_pubkey(server_pub_key, "server's pub_key=");
+    pkiDebug("client secret key (%d)= ", *client_key_len);
+    print_buffer(*client_key, *client_key_len);
+#endif
+
+    retval = 0;
+    if (server_pub_key != NULL)
+	BN_free(server_pub_key);
+    if (pub_key != NULL)
+	ASN1_INTEGER_free(pub_key);
+    if (data != NULL)
+	free (data);
+
+    return retval;
+
+  cleanup:
+    if (*client_key != NULL)
+	free(*client_key);
+    *client_key = NULL;
+    if (pub_key != NULL)
+	ASN1_INTEGER_free(pub_key);
+    if (data != NULL)
+	free (data);
+
+    return retval;
+}
+
+krb5_error_code
+server_check_dh(krb5_context context,
+		pkinit_plg_crypto_context cryptoctx,
+		pkinit_req_crypto_context req_cryptoctx,
+		pkinit_identity_crypto_context id_cryptoctx,
+		krb5_octet_data *dh_params,
+		int minbits)
+{
+    DH *dh = NULL;
+    unsigned char *tmp = NULL;
+    int dh_prime_bits;
+    krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+
+    tmp = dh_params->data;
+    dh = DH_new();
+    dh = pkinit_decode_dh_params(&dh, &tmp, dh_params->length);
+    if (dh == NULL) {
+	pkiDebug("failed to decode dhparams\n");
+	goto cleanup;
+    }
+
+    /* KDC SHOULD check to see if the key parameters satisfy its policy */
+    dh_prime_bits = BN_num_bits(dh->p);
+    if (minbits && dh_prime_bits < minbits) {
+	pkiDebug("client sent dh params with %d bits, we require %d\n",
+		 dh_prime_bits, minbits);
+	goto cleanup;
+    }
+
+    /* check dhparams is group 2 */
+    if (pkinit_check_dh_params(cryptoctx->dh_1024->p,
+			       dh->p, dh->g, dh->q) == 0) {
+	retval = 0;
+	goto cleanup;
+    }
+
+    /* check dhparams is group 14 */
+    if (pkinit_check_dh_params(cryptoctx->dh_2048->p,
+			       dh->p, dh->g, dh->q) == 0) {
+	retval = 0;
+	goto cleanup;
+    }
+
+    /* check dhparams is group 16 */
+    if (pkinit_check_dh_params(cryptoctx->dh_4096->p,
+			       dh->p, dh->g, dh->q) == 0) {
+	retval = 0;
+	goto cleanup;
+    }
+
+  cleanup:
+    if (retval == 0)
+	req_cryptoctx->dh = dh;
+    else
+	DH_free(dh);
+
+    return retval;
+}
+
+/* kdc's dh function */
+krb5_error_code
+server_process_dh(krb5_context context,
+		  pkinit_plg_crypto_context plg_cryptoctx,
+		  pkinit_req_crypto_context cryptoctx,
+		  pkinit_identity_crypto_context id_cryptoctx,
+		  unsigned char *data,
+		  unsigned int data_len,
+		  unsigned char **dh_pubkey,
+		  unsigned int *dh_pubkey_len,
+		  unsigned char **server_key,
+		  unsigned int *server_key_len)
+{
+    krb5_error_code retval = ENOMEM;
+    DH *dh = NULL, *dh_server = NULL;
+    unsigned char *p = NULL;
+    ASN1_INTEGER *pub_key = NULL;
+
+    /* get client's received DH parameters that we saved in server_check_dh */
+    dh = cryptoctx->dh;
+
+    dh_server = DH_new();
+    if (dh_server == NULL)
+	goto cleanup;
+    dh_server->p = BN_dup(dh->p);
+    dh_server->g = BN_dup(dh->g);
+    dh_server->q = BN_dup(dh->q);
+
+    /* decode client's public key */
+    p = data;
+    pub_key = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&p, (int)data_len);
+    if (pub_key == NULL)
+	goto cleanup;
+    dh->pub_key = ASN1_INTEGER_to_BN(pub_key, NULL);
+    if (dh->pub_key == NULL)
+	goto cleanup;
+    ASN1_INTEGER_free(pub_key);
+
+    if (!DH_generate_key(dh_server))
+	goto cleanup;
+
+    /* generate DH session key */
+    *server_key_len = DH_size(dh_server);
+    if ((*server_key = (unsigned char *) malloc((size_t)*server_key_len)) == NULL)
+	goto cleanup;
+    DH_compute_key(*server_key, dh->pub_key, dh_server);
+
+#ifdef DEBUG_DH
+    print_dh(dh_server, "client&server's DH params\n");
+    print_pubkey(dh->pub_key, "client's pub_key=");
+    print_pubkey(dh_server->pub_key, "server's pub_key=");
+    pkiDebug("server secret key=");
+    print_buffer(*server_key, *server_key_len);
+#endif
+
+    /* KDC reply */
+    /* pack DH public key */
+    /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
+     * encoding shall be used as the contents (the value) of the
+     * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
+     * data element
+     */
+    if ((pub_key = BN_to_ASN1_INTEGER(dh_server->pub_key, NULL)) == NULL)
+	goto cleanup;
+    *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
+    if ((p = *dh_pubkey = (unsigned char *) malloc((size_t)*dh_pubkey_len)) == NULL)
+	goto cleanup;
+    i2d_ASN1_INTEGER(pub_key, &p);
+    if (pub_key != NULL)
+	ASN1_INTEGER_free(pub_key);
+
+    retval = 0;
+
+    if (dh_server != NULL)
+	DH_free(dh_server);
+    return retval;
+
+  cleanup:
+    if (dh_server != NULL)
+	DH_free(dh_server);
+    if (*dh_pubkey != NULL)
+	free(*dh_pubkey);
+    if (*server_key != NULL)
+	free(*server_key);
+
+    return retval;
+}
+
+static void
+openssl_init()
+{
+    static int did_init = 0;
+
+    if (!did_init) {
+	/* initialize openssl routines */
+	CRYPTO_malloc_init();
+	ERR_load_crypto_strings();
+	OpenSSL_add_all_algorithms();
+	did_init++;
+    }
+}
+
+static krb5_error_code
+pkinit_encode_dh_params(BIGNUM *p, BIGNUM *g, BIGNUM *q,
+			unsigned char **buf, unsigned int *buf_len)
+{
+    krb5_error_code retval = ENOMEM;
+    int bufsize = 0, r = 0;
+    unsigned char *tmp = NULL;
+    ASN1_INTEGER *ap = NULL, *ag = NULL, *aq = NULL;
+
+    if ((ap = BN_to_ASN1_INTEGER(p, NULL)) == NULL)
+	goto cleanup;
+    if ((ag = BN_to_ASN1_INTEGER(g, NULL)) == NULL)
+	goto cleanup;
+    if ((aq = BN_to_ASN1_INTEGER(q, NULL)) == NULL)
+	goto cleanup;
+    bufsize = i2d_ASN1_INTEGER(ap, NULL);
+    bufsize += i2d_ASN1_INTEGER(ag, NULL);
+    bufsize += i2d_ASN1_INTEGER(aq, NULL);
+
+    r = ASN1_object_size(1, bufsize, V_ASN1_SEQUENCE);
+
+    tmp = *buf = (unsigned char *)malloc((size_t) r);
+    if (tmp == NULL)
+	goto cleanup;
+
+    ASN1_put_object(&tmp, 1, bufsize, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+    i2d_ASN1_INTEGER(ap, &tmp);
+    i2d_ASN1_INTEGER(ag, &tmp);
+    i2d_ASN1_INTEGER(aq, &tmp);
+
+    *buf_len = r;
+
+    retval = 0;
+
+cleanup:
+    if (ap != NULL)
+	ASN1_INTEGER_free(ap);
+    if (ag != NULL)
+	ASN1_INTEGER_free(ag);
+    if (aq != NULL)
+	ASN1_INTEGER_free(aq);
+
+    return retval;
+}
+
+static DH *
+pkinit_decode_dh_params(DH ** a, unsigned char **pp, unsigned int len)
+{
+    ASN1_INTEGER ai, *aip = NULL;
+    long length = (long) len;
+
+    M_ASN1_D2I_vars(a, DH *, DH_new);
+
+    M_ASN1_D2I_Init();
+    M_ASN1_D2I_start_sequence();
+    aip = &ai;
+    ai.data = NULL;
+    ai.length = 0;
+    M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
+    if (aip == NULL)
+	return NULL;
+    else {
+	(*a)->p = ASN1_INTEGER_to_BN(aip, NULL);
+	if ((*a)->p == NULL)
+	    return NULL;
+	if (ai.data != NULL) {
+	    OPENSSL_free(ai.data);
+	    ai.data = NULL;
+	    ai.length = 0;
+	}
+    }
+    M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
+    if (aip == NULL)
+	return NULL;
+    else {
+	(*a)->g = ASN1_INTEGER_to_BN(aip, NULL);
+	if ((*a)->g == NULL)
+	    return NULL;
+	if (ai.data != NULL) {
+	    OPENSSL_free(ai.data);
+	    ai.data = NULL;
+	    ai.length = 0;
+	}
+
+    }
+    M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
+    if (aip == NULL)
+	return NULL;
+    else {
+	(*a)->q = ASN1_INTEGER_to_BN(aip, NULL);
+	if ((*a)->q == NULL)
+	    return NULL;
+	if (ai.data != NULL) {
+	    OPENSSL_free(ai.data);
+	    ai.data = NULL;
+	    ai.length = 0;
+	}
+
+    }
+    M_ASN1_D2I_end_sequence();
+    M_ASN1_D2I_Finish(a, DH_free, 0);
+
+}
+
+static krb5_error_code
+pkinit_create_sequence_of_principal_identifiers(
+    krb5_context context,
+    pkinit_plg_crypto_context plg_cryptoctx,
+    pkinit_req_crypto_context req_cryptoctx,
+    pkinit_identity_crypto_context id_cryptoctx,
+    int type,
+    krb5_data **out_data)
+{
+    krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+    krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
+    krb5_data *td_certifiers = NULL, *data = NULL;
+    krb5_typed_data **typed_data = NULL;
+
+    switch(type) {
+	case TD_TRUSTED_CERTIFIERS:
+	    retval = create_krb5_trustedCertifiers(context, plg_cryptoctx,
+		req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
+	    if (retval) {
+		pkiDebug("create_krb5_trustedCertifiers failed\n");
+		goto cleanup;
+    	    }
+	    break;
+	case TD_INVALID_CERTIFICATES:
+	    retval = create_krb5_invalidCertificates(context, plg_cryptoctx,
+		req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
+	    if (retval) {
+		pkiDebug("create_krb5_invalidCertificates failed\n");
+		goto cleanup;
+    	    }
+	    break;
+	default:
+	    retval = -1;
+	    goto cleanup;
+    }
+
+    retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_trusted_certifiers, &td_certifiers);
+    if (retval) {
+	pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
+	goto cleanup;
+    }
+#ifdef DEBUG_ASN1
+    print_buffer_bin((unsigned char *)td_certifiers->data,
+		     td_certifiers->length, "/tmp/kdc_td_certifiers");
+#endif
+    typed_data = malloc (2 * sizeof(krb5_typed_data *));
+    if (typed_data == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    typed_data[1] = NULL;
+    init_krb5_typed_data(&typed_data[0]);
+    if (typed_data[0] == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    typed_data[0]->type = type;
+    typed_data[0]->length = td_certifiers->length;
+    typed_data[0]->data = (unsigned char *)td_certifiers->data;
+    retval = k5int_encode_krb5_typed_data((const krb5_typed_data **)typed_data,
+					  &data);
+    if (retval) {
+	pkiDebug("encode_krb5_typed_data failed\n");
+	goto cleanup;
+    }
+#ifdef DEBUG_ASN1
+    print_buffer_bin((unsigned char *)data->data, data->length,
+		     "/tmp/kdc_edata");
+#endif
+    *out_data = (krb5_data *)malloc(sizeof(krb5_data));
+    (*out_data)->length = data->length;
+    (*out_data)->data = (char *)malloc(data->length);
+    memcpy((*out_data)->data, data->data, data->length);
+
+    retval = 0;
+
+cleanup:
+    if (krb5_trusted_certifiers != NULL)
+	free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
+
+    if (data != NULL) {
+	if (data->data != NULL)
+	    free(data->data);
+	free(data);
+    }
+
+    if (td_certifiers != NULL)
+	free(td_certifiers);
+
+    if (typed_data != NULL)
+	free_krb5_typed_data(&typed_data);
+
+    return retval;
+}
+
+krb5_error_code
+pkinit_create_td_trusted_certifiers(krb5_context context,
+				    pkinit_plg_crypto_context plg_cryptoctx,
+				    pkinit_req_crypto_context req_cryptoctx,
+				    pkinit_identity_crypto_context id_cryptoctx,
+				    krb5_data **out_data)
+{
+    krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+
+    retval = pkinit_create_sequence_of_principal_identifiers(context,
+	plg_cryptoctx, req_cryptoctx, id_cryptoctx,
+	TD_TRUSTED_CERTIFIERS, out_data);
+
+    return retval;
+}
+
+krb5_error_code
+pkinit_create_td_invalid_certificate(
+	krb5_context context,
+	pkinit_plg_crypto_context plg_cryptoctx,
+	pkinit_req_crypto_context req_cryptoctx,
+	pkinit_identity_crypto_context id_cryptoctx,
+	krb5_data **out_data)
+{
+    krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+
+    retval = pkinit_create_sequence_of_principal_identifiers(context,
+	plg_cryptoctx, req_cryptoctx, id_cryptoctx,
+	TD_INVALID_CERTIFICATES, out_data);
+
+    return retval;
+}
+
+krb5_error_code
+pkinit_create_td_dh_parameters(krb5_context context,
+			       pkinit_plg_crypto_context plg_cryptoctx,
+			       pkinit_req_crypto_context req_cryptoctx,
+			       pkinit_identity_crypto_context id_cryptoctx,
+			       pkinit_plg_opts *opts,
+			       krb5_data **out_data)
+{
+    krb5_error_code retval = ENOMEM;
+    unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0;
+    unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
+    krb5_typed_data **typed_data = NULL;
+    krb5_data *data = NULL, *encoded_algId = NULL;
+    krb5_algorithm_identifier **algId = NULL;
+
+    if (opts->dh_min_bits > 4096)
+	goto cleanup;
+
+    if (opts->dh_min_bits <= 1024) {
+	retval = pkinit_encode_dh_params(plg_cryptoctx->dh_1024->p,
+	    plg_cryptoctx->dh_1024->g, plg_cryptoctx->dh_1024->q,
+	    &buf1, &buf1_len);
+	if (retval)
+	    goto cleanup;
+    }
+    if (opts->dh_min_bits <= 2048) {
+	retval = pkinit_encode_dh_params(plg_cryptoctx->dh_2048->p,
+	    plg_cryptoctx->dh_2048->g, plg_cryptoctx->dh_2048->q,
+	    &buf2, &buf2_len);
+	if (retval)
+	    goto cleanup;
+    }
+    retval = pkinit_encode_dh_params(plg_cryptoctx->dh_4096->p,
+	plg_cryptoctx->dh_4096->g, plg_cryptoctx->dh_4096->q,
+	&buf3, &buf3_len);
+    if (retval)
+	goto cleanup;
+
+    if (opts->dh_min_bits <= 1024) {
+	algId = malloc(4 * sizeof(krb5_algorithm_identifier *));
+	if (algId == NULL)
+	    goto cleanup;
+	algId[3] = NULL;
+	algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+	if (algId[0] == NULL)
+	    goto cleanup;
+	algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
+	if (algId[0]->parameters.data == NULL)
+	    goto cleanup;
+	memcpy(algId[0]->parameters.data, buf2, buf2_len);
+	algId[0]->parameters.length = buf2_len;
+	algId[0]->algorithm = dh_oid;
+
+	algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+	if (algId[1] == NULL)
+	    goto cleanup;
+	algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
+	if (algId[1]->parameters.data == NULL)
+	    goto cleanup;
+	memcpy(algId[1]->parameters.data, buf3, buf3_len);
+	algId[1]->parameters.length = buf3_len;
+	algId[1]->algorithm = dh_oid;
+
+	algId[2] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+	if (algId[2] == NULL)
+	    goto cleanup;
+	algId[2]->parameters.data = (unsigned char *)malloc(buf1_len);
+	if (algId[2]->parameters.data == NULL)
+	    goto cleanup;
+	memcpy(algId[2]->parameters.data, buf1, buf1_len);
+	algId[2]->parameters.length = buf1_len;
+	algId[2]->algorithm = dh_oid;
+
+    } else if (opts->dh_min_bits <= 2048) {
+	algId = malloc(3 * sizeof(krb5_algorithm_identifier *));
+	if (algId == NULL)
+	    goto cleanup;
+	algId[2] = NULL;
+	algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+	if (algId[0] == NULL)
+	    goto cleanup;
+	algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
+	if (algId[0]->parameters.data == NULL)
+	    goto cleanup;
+	memcpy(algId[0]->parameters.data, buf2, buf2_len);
+	algId[0]->parameters.length = buf2_len;
+	algId[0]->algorithm = dh_oid;
+
+	algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+	if (algId[1] == NULL)
+	    goto cleanup;
+	algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
+	if (algId[1]->parameters.data == NULL)
+	    goto cleanup;
+	memcpy(algId[1]->parameters.data, buf3, buf3_len);
+	algId[1]->parameters.length = buf3_len;
+	algId[1]->algorithm = dh_oid;
+
+    } else if (opts->dh_min_bits <= 4096) {
+	algId = malloc(2 * sizeof(krb5_algorithm_identifier *));
+	if (algId == NULL)
+	    goto cleanup;
+	algId[1] = NULL;
+	algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+	if (algId[0] == NULL)
+	    goto cleanup;
+	algId[0]->parameters.data = (unsigned char *)malloc(buf3_len);
+	if (algId[0]->parameters.data == NULL)
+	    goto cleanup;
+	memcpy(algId[0]->parameters.data, buf3, buf3_len);
+	algId[0]->parameters.length = buf3_len;
+	algId[0]->algorithm = dh_oid;
+
+    }
+    retval = k5int_encode_krb5_td_dh_parameters((const krb5_algorithm_identifier **)algId, &encoded_algId);
+    if (retval)
+	goto cleanup;
+#ifdef DEBUG_ASN1
+    print_buffer_bin((unsigned char *)encoded_algId->data,
+		     encoded_algId->length, "/tmp/kdc_td_dh_params");
+#endif
+    typed_data = malloc (2 * sizeof(krb5_typed_data *));
+    if (typed_data == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    typed_data[1] = NULL;
+    init_krb5_typed_data(&typed_data[0]);
+    if (typed_data == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    typed_data[0]->type = TD_DH_PARAMETERS;
+    typed_data[0]->length = encoded_algId->length;
+    typed_data[0]->data = (unsigned char *)encoded_algId->data;
+    retval = k5int_encode_krb5_typed_data((const krb5_typed_data**)typed_data,
+					  &data);
+    if (retval) {
+	pkiDebug("encode_krb5_typed_data failed\n");
+	goto cleanup;
+    }
+#ifdef DEBUG_ASN1
+    print_buffer_bin((unsigned char *)data->data, data->length,
+		     "/tmp/kdc_edata");
+#endif
+    *out_data = (krb5_data *)malloc(sizeof(krb5_data));
+    if (*out_data == NULL)
+	goto cleanup;
+    (*out_data)->length = data->length;
+    (*out_data)->data = (char *)malloc(data->length);
+    if ((*out_data)->data == NULL) {
+	free(*out_data);
+	*out_data = NULL;
+	goto cleanup;
+    }
+    memcpy((*out_data)->data, data->data, data->length);
+
+    retval = 0;
+cleanup:
+
+    if (buf1 != NULL)
+	free(buf1);
+    if (buf2 != NULL)
+	free(buf2);
+    if (buf3 != NULL)
+	free(buf3);
+    if (data != NULL) {
+	if (data->data != NULL)
+	    free(data->data);
+	free(data);
+    }
+    if (typed_data != NULL)
+	free_krb5_typed_data(&typed_data);
+    if (encoded_algId != NULL)
+	free(encoded_algId);
+
+    if (algId != NULL) {
+	while(algId[i] != NULL) {
+	    if (algId[i]->parameters.data != NULL)
+		free(algId[i]->parameters.data);
+	    free(algId[i]);
+	    i++;
+	}
+	free(algId);
+    }
+
+    return retval;
+}
+
+krb5_error_code
+pkinit_check_kdc_pkid(krb5_context context,
+		      pkinit_plg_crypto_context plg_cryptoctx,
+		      pkinit_req_crypto_context req_cryptoctx,
+		      pkinit_identity_crypto_context id_cryptoctx,
+		      unsigned char *pdid_buf,
+		      unsigned int pkid_len,
+		      int *valid_kdcPkId)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    PKCS7_ISSUER_AND_SERIAL *is = NULL;
+    const unsigned char *p = pdid_buf;
+    int status = 1;
+    X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
+
+    *valid_kdcPkId = 0;
+    pkiDebug("found kdcPkId in AS REQ\n");
+    is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len);
+    if (is == NULL)
+	goto cleanup;
+
+    status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer);
+    if (!status) {
+	status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial);
+	if (!status)
+	    *valid_kdcPkId = 1;
+    }
+
+    retval = 0;
+cleanup:
+    X509_NAME_free(is->issuer);
+    ASN1_INTEGER_free(is->serial);
+    free(is);
+
+    return retval;
+}
+
+static int
+pkinit_check_dh_params(BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1)
+{
+    BIGNUM *g2 = NULL, *q2 = NULL;
+    int retval = -1;
+
+    if (!BN_cmp(p1, p2)) {
+	g2 = BN_new();
+	BN_set_word(g2, DH_GENERATOR_2);
+	if (!BN_cmp(g1, g2)) {
+	    q2 = BN_new();
+	    BN_rshift1(q2, p1);
+	    if (!BN_cmp(q1, q2)) {
+		pkiDebug("good %d dhparams\n", BN_num_bits(p1));
+		retval = 0;
+	    } else
+		pkiDebug("bad group 2 q dhparameter\n");
+	    BN_free(q2);
+	} else
+	    pkiDebug("bad g dhparameter\n");
+	BN_free(g2);
+    } else
+	pkiDebug("p is not well-known group 2 dhparameter\n");
+
+    return retval;
+}
+
+krb5_error_code
+pkinit_process_td_dh_params(krb5_context context,
+			    pkinit_plg_crypto_context cryptoctx,
+			    pkinit_req_crypto_context req_cryptoctx,
+			    pkinit_identity_crypto_context id_cryptoctx,
+			    krb5_algorithm_identifier **algId,
+			    int *new_dh_size)
+{
+    krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+    int i = 0, use_sent_dh = 0, ok = 0;
+
+    pkiDebug("dh parameters\n");
+
+    while (algId[i] != NULL) {
+	DH *dh = NULL;
+	unsigned char *tmp = NULL;
+	int dh_prime_bits = 0;
+
+	if (algId[i]->algorithm.length != dh_oid.length ||
+	    memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
+	    goto cleanup;
+
+	tmp = algId[i]->parameters.data;
+	dh = DH_new();
+	dh = pkinit_decode_dh_params(&dh, &tmp, algId[i]->parameters.length);
+	dh_prime_bits = BN_num_bits(dh->p);
+	pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
+		 *new_dh_size, dh_prime_bits);
+	switch(dh_prime_bits) {
+	    case 1024:
+		if (pkinit_check_dh_params(cryptoctx->dh_1024->p, dh->p,
+			dh->g, dh->q) == 0) {
+		    *new_dh_size = 1024;
+		    ok = 1;
+		}
+		break;
+	    case 2048:
+		if (pkinit_check_dh_params(cryptoctx->dh_2048->p, dh->p,
+			dh->g, dh->q) == 0) {
+		    *new_dh_size = 2048;
+		    ok = 1;
+		}
+		break;
+	    case 4096:
+		if (pkinit_check_dh_params(cryptoctx->dh_4096->p, dh->p,
+			dh->g, dh->q) == 0) {
+		    *new_dh_size = 4096;
+		    ok = 1;
+		}
+		break;
+	    default:
+		break;
+	}
+	if (!ok) {
+	    DH_check(dh, &retval);
+	    if (retval != 0) {
+		pkiDebug("DH parameters provided by server are unacceptable\n");
+		retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+	    }
+	    else {
+		use_sent_dh = 1;
+		ok = 1;
+	    }
+	}
+	if (!use_sent_dh)
+	    DH_free(dh);
+	if (ok) {
+	    if (req_cryptoctx->dh != NULL) {
+		DH_free(req_cryptoctx->dh);
+		req_cryptoctx->dh = NULL;
+	    }
+	    if (use_sent_dh)
+		req_cryptoctx->dh = dh;
+	    break;
+	}
+	i++;
+    }
+
+    if (ok)
+	retval = 0;
+
+cleanup:
+    return retval;
+}
+
+static int
+openssl_callback(int ok, X509_STORE_CTX * ctx)
+{
+#ifdef DEBUG
+    if (!ok) {
+	char buf[DN_BUF_LEN];
+
+	X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
+	pkiDebug("cert = %s\n", buf);
+	pkiDebug("callback function: %d (%s)\n", ctx->error,
+		X509_verify_cert_error_string(ctx->error));
+    }
+#endif
+    return ok;
+}
+
+static int
+openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
+{
+    if (!ok) {
+	switch (ctx->error) {
+	    case X509_V_ERR_UNABLE_TO_GET_CRL:
+		return 1;
+	    default:
+		return 0;
+	}
+    }
+    return ok;
+}
+
+static ASN1_OBJECT *
+pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
+{
+    int nid;
+
+    switch (pkcs7_type) {
+	case CMS_SIGN_CLIENT:
+	    return cryptoctx->id_pkinit_authData;
+	case CMS_SIGN_DRAFT9:
+	    /*
+	     * Delay creating this OID until we know we need it.
+	     * It shadows an existing OpenSSL oid.  If it
+	     * is created too early, it breaks things like
+	     * the use of pkcs12 (which uses pkcs7 structures).
+	     * We need this shadow version because our code
+	     * depends on the "other" type to be unknown to the
+	     * OpenSSL code.
+	     */ 
+	    if (cryptoctx->id_pkinit_authData9 == NULL) {
+		pkiDebug("%s: Creating shadow instance of pkcs7-data oid\n",
+			 __FUNCTION__);
+		nid = OBJ_create("1.2.840.113549.1.7.1", "id-pkcs7-data",
+				 "PKCS7 data");
+		if (nid == NID_undef)
+		    return NULL;
+		cryptoctx->id_pkinit_authData9 = OBJ_nid2obj(nid);
+	    }
+	    return cryptoctx->id_pkinit_authData9;
+	case CMS_SIGN_SERVER:
+	    return cryptoctx->id_pkinit_DHKeyData;
+	case CMS_ENVEL_SERVER:
+	    return cryptoctx->id_pkinit_rkeyData;
+	default:
+	    return NULL;
+    }
+
+}
+
+#ifdef LONGHORN_BETA_COMPAT
+#if 0
+/*
+ * This is a version that worked with Longhorn Beta 3.
+ */
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+		unsigned char **out, unsigned int *out_len,
+		int is_longhorn_server)
+{
+
+    unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
+    ASN1_OBJECT *oid = NULL;
+    unsigned char *p = NULL;
+
+    pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
+	     __FUNCTION__, is_longhorn_server);
+
+    /* Get length to wrap the original data with SEQUENCE tag */
+    tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
+
+    if (is_longhorn_server == 0) {
+	/* Add the signedData OID and adjust lengths */
+	oid = OBJ_nid2obj(NID_pkcs7_signed);
+	oid_len = i2d_ASN1_OBJECT(oid, NULL);
+
+	tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
+    }
+
+    p = *out = (unsigned char *)malloc(tot_len);
+    if (p == NULL) return -1;
+
+    if (is_longhorn_server == 0) {
+	ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
+			V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+	i2d_ASN1_OBJECT(oid, &p);
+
+	ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
+    } else {
+	ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+    }
+    memcpy(p, data, data_len);
+
+    *out_len = tot_len;
+
+    return 0;
+}
+#else
+/*
+ * This is a version that works with a patched Longhorn KDC.
+ * (Which should match SP1 ??).
+ */
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+	       unsigned char **out, unsigned int *out_len,
+	       int is_longhorn_server)
+{
+
+    unsigned int oid_len = 0, tot_len = 0, wrap_len = 0, tag_len = 0;
+    ASN1_OBJECT *oid = NULL;
+    unsigned char *p = NULL;
+
+    pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
+	     __FUNCTION__, is_longhorn_server);
+
+    /* New longhorn is missing another sequence */
+    if (is_longhorn_server == 1)
+       wrap_len = ASN1_object_size(1, (int)(data_len), V_ASN1_SEQUENCE);
+    else
+       wrap_len = data_len;
+
+    /* Get length to wrap the original data with SEQUENCE tag */
+    tag_len = ASN1_object_size(1, (int)wrap_len, V_ASN1_SEQUENCE);
+
+    /* Always add oid */
+    oid = OBJ_nid2obj(NID_pkcs7_signed);
+    oid_len = i2d_ASN1_OBJECT(oid, NULL);
+    oid_len += tag_len;
+
+    tot_len = ASN1_object_size(1, (int)(oid_len), V_ASN1_SEQUENCE);
+
+    p = *out = (unsigned char *)malloc(tot_len);
+    if (p == NULL)
+       return -1;
+
+    ASN1_put_object(&p, 1, (int)(oid_len),
+		    V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+    i2d_ASN1_OBJECT(oid, &p);
+
+    ASN1_put_object(&p, 1, (int)wrap_len, 0, V_ASN1_CONTEXT_SPECIFIC);
+
+    /* Wrap in extra seq tag */
+    if (is_longhorn_server == 1) {
+       ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+    }
+    memcpy(p, data, data_len);
+
+    *out_len = tot_len;
+
+    return 0;
+}
+
+#endif
+#else
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+		unsigned char **out, unsigned int *out_len)
+{
+
+    unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
+    ASN1_OBJECT *oid = NULL;
+    unsigned char *p = NULL;
+
+    /* Get length to wrap the original data with SEQUENCE tag */
+    tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
+
+    /* Add the signedData OID and adjust lengths */
+    oid = OBJ_nid2obj(NID_pkcs7_signed);
+    oid_len = i2d_ASN1_OBJECT(oid, NULL);
+
+    tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
+
+    p = *out = (unsigned char *)malloc(tot_len);
+    if (p == NULL) return -1;
+
+    ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
+		    V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+    i2d_ASN1_OBJECT(oid, &p);
+
+    ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
+    memcpy(p, data, data_len);
+
+    *out_len = tot_len;
+
+    return 0;
+}
+#endif
+
+static int
+prepare_enc_data(unsigned char *indata,
+		 int indata_len,
+		 unsigned char **outdata,
+		 int *outdata_len)
+{
+    int retval = -1;
+    ASN1_const_CTX c;
+    long length = indata_len;
+    int Ttag, Tclass;
+    long Tlen;
+
+    c.pp = (const unsigned char **)&indata;
+    c.q = *(const unsigned char **)&indata;
+    c.error = ERR_R_NESTED_ASN1_ERROR;
+    c.p= *(const unsigned char **)&indata;
+    c.max = (length == 0)?0:(c.p+length);
+
+    asn1_GetSequence(&c,&length);
+
+    ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
+    c.p += Tlen;
+    ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
+
+    asn1_const_Finish(&c);
+
+    *outdata = (unsigned char *)malloc((size_t)Tlen);
+    if (outdata == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    memcpy(*outdata, c.p, (size_t)Tlen);
+    *outdata_len = Tlen;
+
+    retval = 0;
+cleanup:
+
+    return retval;
+}
+
+#ifndef WITHOUT_PKCS11
+static void *
+pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p)
+{
+    void *handle;
+    CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
+
+    pkiDebug("loading module \"%s\"... ", modname);
+    handle = dlopen(modname, RTLD_NOW);
+    if (handle == NULL) {
+	pkiDebug("not found\n");
+	return NULL;
+    }
+    getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(handle, "C_GetFunctionList");
+    if (getflist == NULL || (*getflist)(p11p) != CKR_OK) {
+	dlclose(handle);
+	pkiDebug("failed\n");
+	return NULL;
+    }
+    pkiDebug("ok\n");
+    return handle;
+}
+
+static CK_RV
+pkinit_C_UnloadModule(void *handle)
+{
+    dlclose(handle);
+    return CKR_OK;
+}
+
+static krb5_error_code
+pkinit_login(krb5_context context,
+	     pkinit_identity_crypto_context id_cryptoctx,
+	     CK_TOKEN_INFO *tip)
+{
+    krb5_data rdat;
+    char *prompt;
+    krb5_prompt kprompt;
+    krb5_prompt_type prompt_type;
+    int r = 0;
+
+    if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
+	rdat.data = NULL;
+	rdat.length = 0;
+    } else {
+	if ((prompt = (char *) malloc(sizeof (tip->label) + 32)) == NULL)
+	    return ENOMEM;
+	sprintf(prompt, "%.*s PIN", sizeof (tip->label), tip->label);
+	if (tip->flags & CKF_USER_PIN_LOCKED)
+	    strcat(prompt, " (Warning: PIN locked)");
+	else if (tip->flags & CKF_USER_PIN_FINAL_TRY)
+	    strcat(prompt, " (Warning: PIN final try)");
+	else if (tip->flags & CKF_USER_PIN_COUNT_LOW)
+	    strcat(prompt, " (Warning: PIN count low)");
+	rdat.data = (char *)malloc(tip->ulMaxPinLen + 2);
+	rdat.length = tip->ulMaxPinLen + 1;
+
+	kprompt.prompt = prompt;
+	kprompt.hidden = 1;
+	kprompt.reply = &rdat;
+	prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+
+	/* PROMPTER_INVOCATION */
+	k5int_set_prompt_types(context, &prompt_type);
+	r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
+		NULL, NULL, 1, &kprompt);
+	k5int_set_prompt_types(context, 0);
+	free(prompt);
+    }
+
+    if (r == 0) {
+	r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
+		(u_char *) rdat.data, rdat.length);
+
+	if (r != CKR_OK) {
+	    pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r));
+	    r = KRB5KDC_ERR_PREAUTH_FAILED;
+	}
+    }
+    if (rdat.data)
+	free(rdat.data);
+
+    return r;
+}
+
+static krb5_error_code
+pkinit_open_session(krb5_context context,
+		    pkinit_identity_crypto_context cctx)
+{
+    int i, r;
+    unsigned char *cp;
+    CK_ULONG count = 0;
+    CK_SLOT_ID_PTR slotlist;
+    CK_TOKEN_INFO tinfo;
+
+    if (cctx->p11_module != NULL)
+	return 0; /* session already open */
+
+    /* Load module */
+    cctx->p11_module =
+	pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11);
+    if (cctx->p11_module == NULL)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+
+    /* Init */
+    if ((r = cctx->p11->C_Initialize(NULL)) != CKR_OK) {
+	pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r));
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    /* Get the list of available slots */
+    if (cctx->slotid != PK_NOSLOT) {
+	/* A slot was specified, so that's the only one in the list */
+	count = 1;
+	slotlist = (CK_SLOT_ID_PTR) malloc(sizeof (CK_SLOT_ID));
+	slotlist[0] = cctx->slotid;
+    } else {
+	if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK)
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	if (count == 0)
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	slotlist = (CK_SLOT_ID_PTR) malloc(count * sizeof (CK_SLOT_ID));
+	if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK)
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    /* Look for the given token label, or if none given take the first one */
+    for (i = 0; i < count; i++) {
+	/* Open session */
+	if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
+					  NULL, NULL, &cctx->session)) != CKR_OK) {
+	    pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r));
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	}
+
+	/* Get token info */
+	if ((r = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo)) != CKR_OK) {
+	    pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r));
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	}
+	for (cp = tinfo.label + sizeof (tinfo.label) - 1;
+	     *cp == '\0' || *cp == ' '; cp--)
+	    *cp = '\0';
+	pkiDebug("open_session: slotid %d token \"%s\"\n",
+		 (int) slotlist[i], tinfo.label);
+	if (cctx->token_label == NULL ||
+	    !strcmp((char *) cctx->token_label, (char *) tinfo.label))
+	    break;
+	cctx->p11->C_CloseSession(cctx->session);
+    }
+    if (i >= count) {
+	free(slotlist);
+	pkiDebug("open_session: no matching token found\n");
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    cctx->slotid = slotlist[i];
+    free(slotlist);
+    pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx->slotid,
+	     i + 1, (int) count);
+
+    /* Login if needed */
+    if (tinfo.flags & CKF_LOGIN_REQUIRED)
+	r = pkinit_login(context, cctx, &tinfo);
+
+    return r;
+}
+
+/*
+ * Look for a key that's:
+ * 1. private
+ * 2. capable of the specified operation (usually signing or decrypting)
+ * 3. RSA (this may be wrong but it's all we can do for now)
+ * 4. matches the id of the cert we chose
+ *
+ * You must call pkinit_get_certs before calling pkinit_find_private_key
+ * (that's because we need the ID of the private key)
+ *
+ * pkcs11 says the id of the key doesn't have to match that of the cert, but
+ * I can't figure out any other way to decide which key to use.
+ *
+ * We should only find one key that fits all the requirements.
+ * If there are more than one, we just take the first one.
+ */
+
+krb5_error_code
+pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
+			CK_ATTRIBUTE_TYPE usage,
+			CK_OBJECT_HANDLE *objp)
+{
+    CK_OBJECT_CLASS cls;
+    CK_ATTRIBUTE attrs[4];
+    CK_ULONG count;
+    CK_KEY_TYPE keytype;
+    unsigned int nattrs = 0;
+    int r;
+#ifdef PKINIT_USE_KEY_USAGE
+    CK_BBOOL true_false;
+#endif
+
+    cls = CKO_PRIVATE_KEY;
+    attrs[nattrs].type = CKA_CLASS;
+    attrs[nattrs].pValue = &cls;
+    attrs[nattrs].ulValueLen = sizeof cls;
+    nattrs++;
+
+#ifdef PKINIT_USE_KEY_USAGE
+    /*
+     * Some cards get confused if you try to specify a key usage,
+     * so don't, and hope for the best. This will fail if you have
+     * several keys with the same id and different usages but I have
+     * not seen this on real cards.
+     */
+    true_false = TRUE;
+    attrs[nattrs].type = usage;
+    attrs[nattrs].pValue = &true_false;
+    attrs[nattrs].ulValueLen = sizeof true_false;
+    nattrs++;
+#endif
+
+    keytype = CKK_RSA;
+    attrs[nattrs].type = CKA_KEY_TYPE;
+    attrs[nattrs].pValue = &keytype;
+    attrs[nattrs].ulValueLen = sizeof keytype;
+    nattrs++;
+
+    attrs[nattrs].type = CKA_ID;
+    attrs[nattrs].pValue = id_cryptoctx->cert_id;
+    attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
+    nattrs++;
+
+    r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
+    if (r != CKR_OK) {
+	pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
+		 pkinit_pkcs11_code_to_text(r));
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
+    id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
+    pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r));
+    if (r != CKR_OK || count < 1)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    return 0;
+}
+#endif
+
+static krb5_error_code
+pkinit_decode_data_fs(krb5_context context,
+		      pkinit_identity_crypto_context id_cryptoctx,
+		      unsigned char *data,
+		      unsigned int data_len,
+		      unsigned char **decoded_data,
+		      unsigned int *decoded_data_len)
+{
+    if (decode_data(decoded_data, decoded_data_len, data, data_len,
+		id_cryptoctx->my_key, sk_X509_value(id_cryptoctx->my_certs,
+		id_cryptoctx->cert_index)) <= 0) {
+	pkiDebug("failed to decode data\n");
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    return 0;
+}
+
+#ifndef WITHOUT_PKCS11
+#ifdef SILLYDECRYPT
+CK_RV
+pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,
+		 CK_BYTE_PTR pEncryptedData,
+		 CK_ULONG  ulEncryptedDataLen,
+		 CK_BYTE_PTR pData,
+		 CK_ULONG_PTR pulDataLen)
+{
+    CK_RV rv = CKR_OK;
+
+    rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData,
+	ulEncryptedDataLen, pData, pulDataLen);
+    if (rv == CKR_OK) {
+	pkiDebug("pData %x *pulDataLen %d\n", (int) pData, (int) *pulDataLen);
+    }
+    return rv;
+}
+#endif
+
+static krb5_error_code
+pkinit_decode_data_pkcs11(krb5_context context,
+			  pkinit_identity_crypto_context id_cryptoctx,
+			  unsigned char *data,
+			  unsigned int data_len,
+			  unsigned char **decoded_data,
+			  unsigned int *decoded_data_len)
+{
+    CK_OBJECT_HANDLE obj;
+    CK_ULONG len;
+    CK_MECHANISM mech;
+    unsigned char *cp;
+    int r;
+
+    if (pkinit_open_session(context, id_cryptoctx)) {
+	pkiDebug("can't open pkcs11 session\n");
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj);
+
+    mech.mechanism = CKM_RSA_PKCS;
+    mech.pParameter = NULL;
+    mech.ulParameterLen = 0;
+
+    if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech,
+	    obj)) != CKR_OK) {
+	pkiDebug("C_DecryptInit: 0x%x\n", (int) r);
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    pkiDebug("data_len = %d\n", data_len);
+    cp = (unsigned char *)malloc((size_t) data_len);
+    if (cp == NULL)
+	return ENOMEM;
+    len = data_len;
+#ifdef SILLYDECRYPT
+    pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n",
+	    (int) id_cryptoctx->session, (int) data, (int) data_len, (int) cp,
+	    (int) &len, (int) len);
+    if ((r = pkinit_C_Decrypt(id_cryptoctx, data, (CK_ULONG) data_len,
+	    cp, &len)) != CKR_OK) {
+#else
+    if ((r = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, data,
+	    (CK_ULONG) data_len, cp, &len)) != CKR_OK) {
+#endif
+	pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r));
+	if (r == CKR_BUFFER_TOO_SMALL)
+	    pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len);
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len);
+    *decoded_data_len = len;
+    *decoded_data = cp;
+
+    return 0;
+}
+#endif
+
+krb5_error_code
+pkinit_decode_data(krb5_context context,
+		   pkinit_identity_crypto_context id_cryptoctx,
+		   unsigned char *data,
+		   unsigned int data_len,
+		   unsigned char **decoded_data,
+		   unsigned int *decoded_data_len)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+    if (id_cryptoctx->pkcs11_method != 1)
+	retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len,
+	    decoded_data, decoded_data_len);
+#ifndef WITHOUT_PKCS11
+    else
+	retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data,
+	    data_len, decoded_data, decoded_data_len);
+#endif
+
+    return retval;
+}
+
+static krb5_error_code
+pkinit_sign_data_fs(krb5_context context,
+		 pkinit_identity_crypto_context id_cryptoctx,
+		 unsigned char *data,
+		 unsigned int data_len,
+		 unsigned char **sig,
+		 unsigned int *sig_len)
+{
+    if (create_signature(sig, sig_len, data, data_len,
+	    id_cryptoctx->my_key) != 0) {
+	    pkiDebug("failed to create the signature\n");
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    return 0;
+}
+
+#ifndef WITHOUT_PKCS11
+static krb5_error_code
+pkinit_sign_data_pkcs11(krb5_context context,
+			pkinit_identity_crypto_context id_cryptoctx,
+			unsigned char *data,
+			unsigned int data_len,
+			unsigned char **sig,
+			unsigned int *sig_len)
+{
+    CK_OBJECT_HANDLE obj;
+    CK_ULONG len;
+    CK_MECHANISM mech;
+    unsigned char *cp;
+    int r;
+
+    if (pkinit_open_session(context, id_cryptoctx)) {
+	pkiDebug("can't open pkcs11 session\n");
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
+
+    mech.mechanism = id_cryptoctx->mech;
+    mech.pParameter = NULL;
+    mech.ulParameterLen = 0;
+
+    if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech,
+	    obj)) != CKR_OK) {
+	pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r));
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    /*
+     * Key len would give an upper bound on sig size, but there's no way to
+     * get that. So guess, and if it's too small, re-malloc.
+     */
+    len = PK_SIGLEN_GUESS;
+    cp = (unsigned char *)malloc((size_t) len);
+    if (cp == NULL)
+	return ENOMEM;
+
+    r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
+				 (CK_ULONG) data_len, cp, &len);
+    if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) {
+	free(cp);
+	pkiDebug("C_Sign realloc %d\n", (int) len);
+	cp = (unsigned char *)malloc((size_t) len);
+	r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
+				     (CK_ULONG) data_len, cp, &len);
+    }
+    if (r != CKR_OK) {
+	pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r));
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    pkiDebug("sign %d -> %d\n", (int) data_len, (int) len);
+    *sig_len = len;
+    *sig = cp;
+
+    return 0;
+}
+#endif
+
+krb5_error_code
+pkinit_sign_data(krb5_context context,
+		 pkinit_identity_crypto_context id_cryptoctx,
+		 unsigned char *data,
+		 unsigned int data_len,
+		 unsigned char **sig,
+		 unsigned int *sig_len)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+    if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1)
+	retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len,
+				     sig, sig_len);
+#ifndef WITHOUT_PKCS11
+    else
+	retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len,
+					 sig, sig_len);
+#endif
+
+    return retval;
+}
+
+
+static krb5_error_code
+decode_data(unsigned char **out_data, unsigned int *out_data_len,
+	    unsigned char *data, unsigned int data_len,
+	    EVP_PKEY *pkey, X509 *cert)
+{
+    krb5_error_code retval = ENOMEM;
+    unsigned char *buf = NULL;
+    int buf_len = 0;
+
+    if (cert && !X509_check_private_key(cert, pkey)) {
+	pkiDebug("private key does not match certificate\n");
+	goto cleanup;
+    }
+
+    buf_len = EVP_PKEY_size(pkey);
+    buf = (unsigned char *)malloc((size_t) buf_len + 10);
+    if (buf == NULL)
+	goto cleanup;
+
+    retval = EVP_PKEY_decrypt(buf, data, (int)data_len, pkey);
+    if (retval <= 0) {
+	pkiDebug("unable to decrypt received data (len=%d)\n", data_len);
+	goto cleanup;
+    }
+    *out_data = buf;
+    *out_data_len = retval;
+
+  cleanup:
+    if (retval == ENOMEM)
+	free(buf);
+
+    return retval;
+}
+
+static krb5_error_code
+create_signature(unsigned char **sig, unsigned int *sig_len,
+		 unsigned char *data, unsigned int data_len, EVP_PKEY *pkey)
+{
+    krb5_error_code retval = ENOMEM;
+    EVP_MD_CTX md_ctx;
+
+    if (pkey == NULL)
+	return retval;
+
+    EVP_VerifyInit(&md_ctx, EVP_sha1());
+    EVP_SignUpdate(&md_ctx, data, data_len);
+    *sig_len = EVP_PKEY_size(pkey);
+    if ((*sig = (unsigned char *) malloc((size_t) *sig_len)) == NULL)
+	goto cleanup;
+    EVP_SignFinal(&md_ctx, *sig, sig_len, pkey);
+
+    retval = 0;
+
+  cleanup:
+    EVP_MD_CTX_cleanup(&md_ctx);
+
+    return retval;
+}
+
+/*
+ * Note:
+ * This is not the routine the KDC uses to get its certificate.
+ * This routine is intended to be called by the client
+ * to obtain the KDC's certificate from some local storage
+ * to be sent as a hint in its request to the KDC.
+ */
+krb5_error_code
+pkinit_get_kdc_cert(krb5_context context,
+		    pkinit_plg_crypto_context plg_cryptoctx,
+		    pkinit_req_crypto_context req_cryptoctx,
+		    pkinit_identity_crypto_context id_cryptoctx,
+		    krb5_principal princ)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+    req_cryptoctx->received_cert = NULL;
+    retval = 0;
+    return retval;
+}
+
+static krb5_error_code
+pkinit_get_certs_pkcs12(krb5_context context,
+			  pkinit_plg_crypto_context plg_cryptoctx,
+			  pkinit_req_crypto_context req_cryptoctx,
+			  pkinit_identity_opts *idopts,
+			  pkinit_identity_crypto_context id_cryptoctx,
+			  krb5_principal princ)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    X509 *x = NULL;
+    PKCS12 *p12 = NULL;
+    int ret;
+    FILE *fp;
+    EVP_PKEY *y = NULL;
+
+    if (idopts->cert_filename == NULL) {
+	pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
+	goto cleanup;
+    }
+
+    if (idopts->key_filename == NULL) {
+	pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__);
+	goto cleanup;
+    }
+
+    fp = fopen(idopts->cert_filename, "rb");
+    if (fp == NULL) {
+	pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
+		 idopts->cert_filename, errno);
+	goto cleanup;
+    }
+
+    p12 = d2i_PKCS12_fp(fp, NULL);
+    fclose(fp);
+    if (p12 == NULL) {
+	pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
+		 idopts->cert_filename);
+	goto cleanup;
+    }
+    /*
+     * Try parsing with no pass phrase first.  If that fails,
+     * prompt for the pass phrase and try again.
+     */
+    ret = PKCS12_parse(p12, NULL, &y, &x, NULL);
+    if (ret == 0) {
+	krb5_data rdat;
+	krb5_prompt kprompt;
+	krb5_prompt_type prompt_type;
+	int r = 0;
+	char prompt_string[128];
+	char prompt_reply[128];
+	char prompt_prefix[] = "Pass phrase for";
+
+	pkiDebug("Initial PKCS12_parse with no password failed\n");
+
+	memset(prompt_reply, '\0', sizeof(prompt_reply));
+	rdat.data = prompt_reply;
+	rdat.length = sizeof(prompt_reply);
+
+	r = snprintf(prompt_string, sizeof(prompt_string), "%s %s",
+		     prompt_prefix, idopts->cert_filename);
+	if (r >= sizeof(prompt_string)) {
+	    pkiDebug("Prompt string, '%s %s', is too long!\n",
+		     prompt_prefix, idopts->cert_filename);
+	    goto cleanup;
+	}
+	kprompt.prompt = prompt_string;
+	kprompt.hidden = 1;
+	kprompt.reply = &rdat;
+	prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+
+	/* PROMPTER_INVOCATION */
+	k5int_set_prompt_types(context, &prompt_type);
+	r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
+				      NULL, NULL, 1, &kprompt);
+	k5int_set_prompt_types(context, 0);
+
+	ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
+	if (ret == 0) {
+	    pkiDebug("Seconde PKCS12_parse with password failed\n");
+	    goto cleanup;
+	}
+    }
+    id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info));
+    if (id_cryptoctx->creds[0] == NULL)
+	goto cleanup;
+    id_cryptoctx->creds[0]->cert = x;
+#ifndef WITHOUT_PKCS11
+    id_cryptoctx->creds[0]->cert_id = NULL;
+    id_cryptoctx->creds[0]->cert_id_len = 0;
+#endif
+    id_cryptoctx->creds[0]->key = y;
+    id_cryptoctx->creds[1] = NULL;
+
+    retval = 0;
+
+cleanup:
+    if (p12)
+	PKCS12_free(p12);
+    if (retval) {
+	if (x != NULL)
+	    X509_free(x);
+	if (y != NULL)
+	    EVP_PKEY_free(y);
+    }
+    return retval;
+}
+
+static krb5_error_code
+pkinit_load_fs_cert_and_key(krb5_context context,
+			    pkinit_identity_crypto_context id_cryptoctx,
+			    char *certname,
+			    char *keyname,
+			    int cindex)
+{
+    krb5_error_code retval;
+    X509 *x = NULL;
+    EVP_PKEY *y = NULL;
+
+    /* load the certificate */
+    retval = get_cert(certname, &x);
+    if (retval != 0 || x == NULL) {
+	pkiDebug("failed to load user's certificate from '%s'\n", certname);
+	goto cleanup;
+    }
+    retval = get_key(keyname, &y);
+    if (retval != 0 || y == NULL) {
+	pkiDebug("failed to load user's private key from '%s'\n", keyname);
+	goto cleanup;
+    }
+
+    id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info));
+    if (id_cryptoctx->creds[cindex] == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    id_cryptoctx->creds[cindex]->cert = x;
+#ifndef WITHOUT_PKCS11
+    id_cryptoctx->creds[cindex]->cert_id = NULL;
+    id_cryptoctx->creds[cindex]->cert_id_len = 0;
+#endif
+    id_cryptoctx->creds[cindex]->key = y;
+    id_cryptoctx->creds[cindex+1] = NULL;
+
+    retval = 0;
+
+cleanup:
+    if (retval) {
+	if (x != NULL)
+	    X509_free(x);
+	if (y != NULL)
+	    EVP_PKEY_free(y);
+    }
+    return retval;
+}
+
+static krb5_error_code
+pkinit_get_certs_fs(krb5_context context,
+			  pkinit_plg_crypto_context plg_cryptoctx,
+			  pkinit_req_crypto_context req_cryptoctx,
+			  pkinit_identity_opts *idopts,
+			  pkinit_identity_crypto_context id_cryptoctx,
+			  krb5_principal princ)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+    if (idopts->cert_filename == NULL) {
+	pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
+	goto cleanup;
+    }
+
+    if (idopts->key_filename == NULL) {
+	pkiDebug("%s: failed to get user's private key location\n",
+		 __FUNCTION__);
+	goto cleanup;
+    }
+
+    retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
+					 idopts->cert_filename,
+					 idopts->key_filename, 0);
+cleanup:
+    return retval;
+}
+
+static krb5_error_code
+pkinit_get_certs_dir(krb5_context context,
+		     pkinit_plg_crypto_context plg_cryptoctx,
+		     pkinit_req_crypto_context req_cryptoctx,
+		     pkinit_identity_opts *idopts,
+		     pkinit_identity_crypto_context id_cryptoctx,
+		     krb5_principal princ)
+{
+    krb5_error_code retval = ENOMEM;
+    DIR *d = NULL;
+    struct dirent *dentry = NULL;
+    char certname[1024];
+    char keyname[1024];
+    int i = 0, len;
+    char *dirname, *suf;
+
+    if (idopts->cert_filename == NULL) {
+	pkiDebug("%s: failed to get user's certificate directory location\n",
+		 __FUNCTION__);
+	return ENOENT;
+    }
+
+    dirname = idopts->cert_filename;
+    d = opendir(dirname);
+    if (d == NULL)
+	return errno;
+
+    /*
+     * We'll assume that certs are named XXX.crt and the corresponding
+     * key is named XXX.key
+     */
+    while ((i < MAX_CREDS_ALLOWED) &&  (dentry = readdir(d)) != NULL) {
+	/* Ignore subdirectories and anything starting with a dot */
+#ifdef DT_DIR
+	if (dentry->d_type == DT_DIR)
+	    continue;
+#endif
+	if (dentry->d_name[0] == '.')
+	    continue;
+	len = strlen(dentry->d_name);
+	if (len < 5)
+	    continue;
+	suf = dentry->d_name + (len - 4);
+	if (strncmp(suf, ".crt", 4) != 0)
+	    continue;
+
+	/* Checked length */
+	if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) {
+	    pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
+		     __FUNCTION__, dirname, dentry->d_name);
+	    continue;
+	}
+	snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name);
+	snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name);
+	len = strlen(keyname);
+	keyname[len - 3] = 'k';
+	keyname[len - 2] = 'e';
+	keyname[len - 1] = 'y';
+
+	retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
+					     certname, keyname, i);
+	if (retval == 0) {
+	    pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
+		     __FUNCTION__, dentry->d_name);
+	    i++;
+	}
+	else
+	    continue;
+    }
+
+    if (i == 0) {
+	pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
+		 __FUNCTION__, idopts->cert_filename);
+	retval = ENOENT;
+	goto cleanup;
+    }
+
+    retval = 0;
+
+  cleanup:
+    if (d) 
+	closedir(d);
+
+    return retval;
+}
+
+#ifndef WITHOUT_PKCS11
+static krb5_error_code
+pkinit_get_certs_pkcs11(krb5_context context,
+			pkinit_plg_crypto_context plg_cryptoctx,
+			pkinit_req_crypto_context req_cryptoctx,
+			pkinit_identity_opts *idopts,
+			pkinit_identity_crypto_context id_cryptoctx,
+			krb5_principal princ)
+{
+#ifdef PKINIT_USE_MECH_LIST
+    CK_MECHANISM_TYPE_PTR mechp;
+    CK_MECHANISM_INFO info;
+#endif
+    CK_OBJECT_CLASS cls;
+    CK_OBJECT_HANDLE obj;
+    CK_ATTRIBUTE attrs[4];
+    CK_ULONG count;
+    CK_CERTIFICATE_TYPE certtype;
+    CK_BYTE_PTR cert = NULL, cert_id;
+    const unsigned char *cp;
+    int i, r;
+    unsigned int nattrs;
+    X509 *x = NULL;
+
+    /* Copy stuff from idopts -> id_cryptoctx */
+    if (idopts->p11_module_name != NULL) {
+	id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name);
+	if (id_cryptoctx->p11_module_name == NULL)
+	    return ENOMEM;
+    }
+    if (idopts->token_label != NULL) {
+	id_cryptoctx->token_label = strdup(idopts->token_label);
+	if (id_cryptoctx->token_label == NULL)
+	    return ENOMEM;
+    }
+    if (idopts->cert_label != NULL) {
+	id_cryptoctx->cert_label = strdup(idopts->cert_label);
+	if (id_cryptoctx->cert_label == NULL)
+	    return ENOMEM;
+    }
+    /* Convert the ascii cert_id string into a binary blob */
+    if (idopts->cert_id_string != NULL) {
+	BIGNUM *bn = NULL;
+	BN_hex2bn(&bn, idopts->cert_id_string);
+	if (bn == NULL)
+	    return ENOMEM;
+	id_cryptoctx->cert_id_len = BN_num_bytes(bn);
+	id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len);
+	if (id_cryptoctx->cert_id == NULL) {
+	    BN_free(bn);
+	    return ENOMEM;
+	}
+	BN_bn2bin(bn, id_cryptoctx->cert_id);
+	BN_free(bn);
+    }
+    id_cryptoctx->slotid = idopts->slotid;
+    id_cryptoctx->pkcs11_method = 1;
+
+
+
+    if (pkinit_open_session(context, id_cryptoctx)) {
+	pkiDebug("can't open pkcs11 session\n");
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+#ifndef PKINIT_USE_MECH_LIST
+    /*
+     * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
+     * many cards seems to be confused about whether they are capable of
+     * this or not. The safe thing seems to be to ignore the mechanism list,
+     * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
+     */
+
+    id_cryptoctx->mech = CKM_RSA_PKCS;
+#else
+    if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, NULL,
+	    &count)) != CKR_OK || count <= 0) {
+	pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r));
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+    mechp = (CK_MECHANISM_TYPE_PTR) malloc(count * sizeof (CK_MECHANISM_TYPE));
+    if (mechp == NULL)
+	return ENOMEM;
+    if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid,
+	    mechp, &count)) != CKR_OK)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    for (i = 0; i < count; i++) {
+	if ((r = id_cryptoctx->p11->C_GetMechanismInfo(id_cryptoctx->slotid,
+		mechp[i], &info)) != CKR_OK)
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+#ifdef DEBUG_MECHINFO
+	pkiDebug("mech %x flags %x\n", (int) mechp[i], (int) info.flags);
+	if ((info.flags & (CKF_SIGN|CKF_DECRYPT)) == (CKF_SIGN|CKF_DECRYPT))
+	    pkiDebug("  this mech is good for sign & decrypt\n");
+#endif
+	if (mechp[i] == CKM_RSA_PKCS) {
+	    /* This seems backwards... */
+	    id_cryptoctx->mech =
+		(info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS;
+	}
+    }
+    free(mechp);
+
+    pkiDebug("got %d mechs from card\n", (int) count);
+#endif
+
+    cls = CKO_CERTIFICATE;
+    attrs[0].type = CKA_CLASS;
+    attrs[0].pValue = &cls;
+    attrs[0].ulValueLen = sizeof cls;
+
+    certtype = CKC_X_509;
+    attrs[1].type = CKA_CERTIFICATE_TYPE;
+    attrs[1].pValue = &certtype;
+    attrs[1].ulValueLen = sizeof certtype;
+
+    nattrs = 2;
+
+    /* If a cert id and/or label were given, use them too */
+    if (id_cryptoctx->cert_id_len > 0) {
+	attrs[nattrs].type = CKA_ID;
+	attrs[nattrs].pValue = id_cryptoctx->cert_id;
+	attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
+	nattrs++;
+    }
+    if (id_cryptoctx->cert_label != NULL) {
+	attrs[nattrs].type = CKA_LABEL;
+	attrs[nattrs].pValue = id_cryptoctx->cert_label;
+	attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label);
+	nattrs++;
+    }
+
+    r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
+    if (r != CKR_OK) {
+	pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r));
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    for (i = 0; ; i++) {
+	if (i >= MAX_CREDS_ALLOWED) 
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+
+	/* Look for x.509 cert */
+	if ((r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session,
+		&obj, 1, &count)) != CKR_OK || count <= 0) {
+	    id_cryptoctx->creds[i] = NULL;
+	    break;
+	}
+
+	/* Get cert and id len */
+	attrs[0].type = CKA_VALUE;
+	attrs[0].pValue = NULL;
+	attrs[0].ulValueLen = 0;
+
+	attrs[1].type = CKA_ID;
+	attrs[1].pValue = NULL;
+	attrs[1].ulValueLen = 0;
+
+	if ((r = id_cryptoctx->p11->C_GetAttributeValue(id_cryptoctx->session,
+		obj, attrs, 2)) != CKR_OK && r != CKR_BUFFER_TOO_SMALL) {
+	    pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	}
+	cert = (CK_BYTE_PTR) malloc((size_t) attrs[0].ulValueLen + 1);
+	cert_id = (CK_BYTE_PTR) malloc((size_t) attrs[1].ulValueLen + 1);
+	if (cert == NULL || cert_id == NULL)
+	    return ENOMEM;
+
+	/* Read the cert and id off the card */
+
+	attrs[0].type = CKA_VALUE;
+	attrs[0].pValue = cert;
+
+	attrs[1].type = CKA_ID;
+	attrs[1].pValue = cert_id;
+
+	if ((r = id_cryptoctx->p11->C_GetAttributeValue(id_cryptoctx->session,
+		obj, attrs, 2)) != CKR_OK) {
+	    pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	}
+
+	pkiDebug("cert %d size %d id %d idlen %d\n", i,
+	    (int) attrs[0].ulValueLen, (int) cert_id[0],
+	    (int) attrs[1].ulValueLen);
+
+	cp = (unsigned char *) cert;
+	x = d2i_X509(NULL, &cp, (int) attrs[0].ulValueLen);
+	if (x == NULL)
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	id_cryptoctx->creds[i] = malloc(sizeof(struct _pkinit_cred_info));
+	if (id_cryptoctx->creds[i] == NULL)
+	    return KRB5KDC_ERR_PREAUTH_FAILED;
+	id_cryptoctx->creds[i]->cert = x;
+	id_cryptoctx->creds[i]->key = NULL;
+	id_cryptoctx->creds[i]->cert_id = cert_id;
+	id_cryptoctx->creds[i]->cert_id_len = attrs[1].ulValueLen;
+	free(cert);
+    }
+    id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
+    if (cert == NULL)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    return 0;
+}
+#endif
+
+
+static void
+free_cred_info(krb5_context context,
+	       pkinit_identity_crypto_context id_cryptoctx,
+	       struct _pkinit_cred_info *cred)
+{
+    if (cred != NULL) {
+	if (cred->cert != NULL)
+	    X509_free(cred->cert);
+	if (cred->key != NULL)
+	    EVP_PKEY_free(cred->key);
+#ifndef WITHOUT_PKCS11
+	if (cred->cert_id != NULL)
+	    free(cred->cert_id);
+#endif
+	free(cred);
+    }
+}
+
+krb5_error_code
+crypto_free_cert_info(krb5_context context,
+		      pkinit_plg_crypto_context plg_cryptoctx,
+		      pkinit_req_crypto_context req_cryptoctx,
+		      pkinit_identity_crypto_context id_cryptoctx)
+{
+    int i;
+
+    if (id_cryptoctx == NULL)
+	return EINVAL;
+
+    for (i = 0; i < MAX_CREDS_ALLOWED; i++) {
+	if (id_cryptoctx->creds[i] != NULL) {
+	    free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]);
+	    id_cryptoctx->creds[i] = NULL;
+	}
+    }
+    return 0;
+}
+
+krb5_error_code
+crypto_load_certs(krb5_context context,
+		  pkinit_plg_crypto_context plg_cryptoctx,
+		  pkinit_req_crypto_context req_cryptoctx,
+		  pkinit_identity_opts *idopts,
+		  pkinit_identity_crypto_context id_cryptoctx,
+		  krb5_principal princ)
+{
+    krb5_error_code retval;
+
+    switch(idopts->idtype) {
+	case IDTYPE_FILE:
+	    retval = pkinit_get_certs_fs(context, plg_cryptoctx,
+					 req_cryptoctx, idopts,
+					 id_cryptoctx, princ);
+	    break;
+	case IDTYPE_DIR:
+	    retval = pkinit_get_certs_dir(context, plg_cryptoctx,
+					  req_cryptoctx, idopts,
+					  id_cryptoctx, princ);
+	    break;
+#ifndef WITHOUT_PKCS11
+	case IDTYPE_PKCS11:
+	    retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx,
+					     req_cryptoctx, idopts,
+					     id_cryptoctx, princ);
+	    break;
+#endif
+	case IDTYPE_PKCS12:
+	    retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx,
+					     req_cryptoctx, idopts,
+					     id_cryptoctx, princ);
+		break;
+	default:
+	    retval = EINVAL;
+    }
+    if (retval)
+	goto cleanup;
+
+cleanup:
+    return retval;
+}
+
+/*
+ * Get number of certificates available after crypto_load_certs()
+ */
+krb5_error_code
+crypto_cert_get_count(krb5_context context,
+		      pkinit_plg_crypto_context plg_cryptoctx,
+		      pkinit_req_crypto_context req_cryptoctx,
+		      pkinit_identity_crypto_context id_cryptoctx,
+		      int *cert_count)
+{
+    int count;
+
+    if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
+	return EINVAL;
+
+    for (count = 0;
+	 count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
+	 count++);
+    *cert_count = count;
+    return 0;
+}
+
+
+/*
+ * Begin iteration over the certs loaded in crypto_load_certs()
+ */
+krb5_error_code
+crypto_cert_iteration_begin(krb5_context context,
+			    pkinit_plg_crypto_context plg_cryptoctx,
+			    pkinit_req_crypto_context req_cryptoctx,
+			    pkinit_identity_crypto_context id_cryptoctx,
+			    pkinit_cert_iter_handle *ih_ret)
+{
+    struct _pkinit_cert_iter_data *id;
+
+    if (id_cryptoctx == NULL || ih_ret == NULL)
+	return EINVAL;
+    if (id_cryptoctx->creds[0] == NULL)	/* No cred info available */
+	return ENOENT;
+
+    id = calloc(1, sizeof(*id));
+    if (id == NULL)
+	return ENOMEM;
+    id->magic = ITER_MAGIC;
+    id->plgctx = plg_cryptoctx,
+    id->reqctx = req_cryptoctx,
+    id->idctx = id_cryptoctx;
+    id->index = 0;
+    *ih_ret = (pkinit_cert_iter_handle) id;
+    return 0;
+}
+
+/*
+ * End iteration over the certs loaded in crypto_load_certs()
+ */
+krb5_error_code
+crypto_cert_iteration_end(krb5_context context,
+			  pkinit_cert_iter_handle ih)
+{
+    struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
+
+    if (id == NULL || id->magic != ITER_MAGIC)
+	return EINVAL;
+    free(ih);
+    return 0;
+}
+
+/*
+ * Get next certificate handle
+ */
+krb5_error_code
+crypto_cert_iteration_next(krb5_context context,
+			   pkinit_cert_iter_handle ih,
+			   pkinit_cert_handle *ch_ret)
+{
+    struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
+    struct _pkinit_cert_data *cd;
+    pkinit_identity_crypto_context id_cryptoctx;
+
+    if (id == NULL || id->magic != ITER_MAGIC)
+	return EINVAL;
+
+    if (ch_ret == NULL)
+	return EINVAL;
+
+    id_cryptoctx = id->idctx;
+    if (id_cryptoctx == NULL)
+	return EINVAL;
+
+    if (id_cryptoctx->creds[id->index] == NULL)
+	return PKINIT_ITER_NO_MORE;
+    
+    cd = calloc(1, sizeof(*cd));
+    if (cd == NULL)
+	return ENOMEM;
+
+    cd->magic = CERT_MAGIC;
+    cd->plgctx = id->plgctx;
+    cd->reqctx = id->reqctx;
+    cd->idctx = id->idctx;
+    cd->index = id->index;
+    cd->cred = id_cryptoctx->creds[id->index++];
+    *ch_ret = (pkinit_cert_handle)cd;
+    return 0;
+}
+
+/*
+ * Release cert handle
+ */
+krb5_error_code
+crypto_cert_release(krb5_context context,
+		    pkinit_cert_handle ch)
+{
+    struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
+    if (cd == NULL || cd->magic != CERT_MAGIC)
+	return EINVAL;
+    free(cd);
+    return 0;
+}
+
+/*
+ * Get certificate Key Usage and Extended Key Usage
+ */
+static krb5_error_code
+crypto_retieve_X509_key_usage(krb5_context context,
+			      pkinit_plg_crypto_context plgcctx,
+			      pkinit_req_crypto_context reqcctx,
+			      X509 *x,
+			      unsigned int *ret_ku_bits,
+			      unsigned int *ret_eku_bits)
+{
+    krb5_error_code retval = 0;
+    int i;
+    unsigned int eku_bits = 0, ku_bits = 0;
+    ASN1_BIT_STRING *usage = NULL;
+
+    if (ret_ku_bits == NULL && ret_eku_bits == NULL)
+	return EINVAL;
+
+    if (ret_eku_bits)
+	*ret_eku_bits = 0;
+    else {
+	pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__);
+	goto check_kus;
+    }
+    
+    /* Start with Extended Key usage */
+    i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
+    if (i >= 0) {
+	EXTENDED_KEY_USAGE *eku;
+
+	eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL);
+	if (eku) {
+	    for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
+		ASN1_OBJECT *certoid;
+		certoid = sk_ASN1_OBJECT_value(eku, i);
+		if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0)
+		    eku_bits |= PKINIT_EKU_PKINIT;
+		else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0)
+		    eku_bits |= PKINIT_EKU_MSSCLOGIN;
+		else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0)
+		    eku_bits |= PKINIT_EKU_CLIENTAUTH;
+		else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0)
+		    eku_bits |= PKINIT_EKU_EMAILPROTECTION;
+	    }
+	    EXTENDED_KEY_USAGE_free(eku);
+	}
+    }
+    pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits);
+    *ret_eku_bits = eku_bits;
+
+check_kus:
+    /* Now the Key Usage bits */
+    if (ret_ku_bits)
+	*ret_ku_bits = 0;
+    else {
+	pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__);
+	goto out;
+    }
+
+    /* Make sure usage exists before checking bits */
+    usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL);
+    if (usage) {
+	if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
+	    ku_bits |= PKINIT_KU_DIGITALSIGNATURE;
+	if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT))
+	    ku_bits |= PKINIT_KU_KEYENCIPHERMENT;
+	ASN1_BIT_STRING_free(usage);
+    }
+
+    pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits);
+    *ret_ku_bits = ku_bits;
+    retval = 0;
+out:
+    return retval;
+}
+
+/*
+ * Return a string format of an X509_NAME in buf where
+ * size is an in/out parameter.  On input it is the size
+ * of the buffer, and on output it is the actual length
+ * of the name.
+ * If buf is NULL, returns the length req'd to hold name
+ */
+static char *
+X509_NAME_oneline_ex(X509_NAME * a,
+		     char *buf,
+		     unsigned int *size,
+		     unsigned long flag)
+{
+  BIO *out = NULL;
+
+  out = BIO_new(BIO_s_mem ());
+  if (X509_NAME_print_ex(out, a, 0, flag) > 0) {
+    if (buf != NULL && *size > (int) BIO_number_written(out)) {
+      memset(buf, 0, *size);
+      BIO_read(out, buf, (int) BIO_number_written(out));
+    }
+    else {
+      *size = BIO_number_written(out);
+    }
+  }
+  BIO_free(out);
+  return (buf);
+}
+
+/*
+ * Get certificate information
+ */
+krb5_error_code
+crypto_cert_get_matching_data(krb5_context context,
+			      pkinit_cert_handle ch,
+			      pkinit_cert_matching_data **ret_md)
+{
+    krb5_error_code retval;
+    pkinit_cert_matching_data *md;
+    krb5_principal *pkinit_sans =NULL, *upn_sans = NULL;
+    struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
+    int i, j;
+    char buf[DN_BUF_LEN];
+    unsigned int bufsize = sizeof(buf);
+
+    if (cd == NULL || cd->magic != CERT_MAGIC)
+	return EINVAL;
+    if (ret_md == NULL)
+	return EINVAL;
+
+    md = calloc(1, sizeof(*md));
+    if (md == NULL)
+	return ENOMEM;
+
+    md->ch = ch;
+
+    /* get the subject name (in rfc2253 format) */
+    X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert),
+			 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
+    md->subject_dn = strdup(buf);
+    if (md->subject_dn == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    /* get the issuer name (in rfc2253 format) */
+    X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert),
+			 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
+    md->issuer_dn = strdup(buf);
+    if (md->issuer_dn == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    /* get the san data */
+    retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx,
+				       cd->cred->cert, &pkinit_sans,
+				       &upn_sans, NULL);
+    if (retval)
+	goto cleanup;
+
+    j = 0;
+    if (pkinit_sans != NULL) {
+	for (i = 0; pkinit_sans[i] != NULL; i++)
+	    j++;
+    }
+    if (upn_sans != NULL) {
+	for (i = 0; upn_sans[i] != NULL; i++)
+	    j++;
+    }
+    if (j != 0) {
+	md->sans = calloc((size_t)j+1, sizeof(*md->sans));
+	if (md->sans == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+	j = 0;
+	if (pkinit_sans != NULL) {
+	    for (i = 0; pkinit_sans[i] != NULL; i++)
+		md->sans[j++] = pkinit_sans[i];
+	    free(pkinit_sans);
+	}
+	if (upn_sans != NULL) {
+	    for (i = 0; upn_sans[i] != NULL; i++)
+		md->sans[j++] = upn_sans[i];
+	    free(upn_sans);
+	}
+	md->sans[j] = NULL;
+    } else
+	md->sans = NULL;
+
+    /* get the KU and EKU data */
+
+    retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx,
+					   cd->cred->cert,
+					   &md->ku_bits, &md->eku_bits);
+    if (retval)
+	goto cleanup;
+
+    *ret_md = md;
+    retval = 0;
+cleanup:
+    if (retval) {
+	if (md)
+	    crypto_cert_free_matching_data(context, md);
+    }
+    return retval;
+}
+
+/*
+ * Free certificate information
+ */
+krb5_error_code
+crypto_cert_free_matching_data(krb5_context context,
+		      pkinit_cert_matching_data *md)
+{
+    krb5_principal p;
+    int i;
+
+    if (md == NULL)
+	return EINVAL;
+    if (md->subject_dn)
+	free(md->subject_dn);
+    if (md->issuer_dn)
+	free(md->issuer_dn);
+    if (md->sans) {
+	for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i])
+	    krb5_free_principal(context, p);
+	free(md->sans);
+    }
+    free(md);
+    return 0;
+}
+
+/*
+ * Make this matching certificate "the chosen one"
+ */
+krb5_error_code
+crypto_cert_select(krb5_context context,
+		   pkinit_cert_matching_data *md)
+{
+    struct _pkinit_cert_data *cd;
+    if (md == NULL)
+	return EINVAL;
+
+    cd = (struct _pkinit_cert_data *)md->ch;
+    if (cd == NULL || cd->magic != CERT_MAGIC)
+	return EINVAL;
+    
+    /* copy the selected cert into our id_cryptoctx */ 
+    if (cd->idctx->my_certs != NULL) {
+	sk_X509_pop_free(cd->idctx->my_certs, X509_free);
+    }
+    cd->idctx->my_certs = sk_X509_new_null();	
+    sk_X509_push(cd->idctx->my_certs, cd->cred->cert);
+    cd->idctx->creds[cd->index]->cert = NULL;	    /* Don't free it twice */
+    cd->idctx->cert_index = 0;
+
+    if (cd->idctx->pkcs11_method != 1) {
+	cd->idctx->my_key = cd->cred->key;
+	cd->idctx->creds[cd->index]->key = NULL;    /* Don't free it twice */
+    } 
+#ifndef WITHOUT_PKCS11
+    else {
+	cd->idctx->cert_id = cd->cred->cert_id;
+	cd->idctx->creds[cd->index]->cert_id = NULL; /* Don't free it twice */
+	cd->idctx->cert_id_len = cd->cred->cert_id_len;
+    }
+#endif
+    return 0;
+}
+
+/*
+ * Choose the default certificate as "the chosen one"
+ */
+krb5_error_code
+crypto_cert_select_default(krb5_context context,
+			   pkinit_plg_crypto_context plg_cryptoctx,
+			   pkinit_req_crypto_context req_cryptoctx,
+			   pkinit_identity_crypto_context id_cryptoctx)
+{
+    krb5_error_code retval;
+    int cert_count = 0;
+
+    retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
+				   id_cryptoctx, &cert_count);
+    if (retval) {
+	pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
+		 __FUNCTION__, retval, error_message(retval));
+	goto errout;
+    }
+    if (cert_count != 1) {
+	pkiDebug("%s: ERROR: There are %d certs to choose from, "
+		 "but there must be exactly one.\n",
+		 __FUNCTION__, cert_count);
+	retval = EINVAL;
+	goto errout;
+    }
+    /* copy the selected cert into our id_cryptoctx */ 
+    if (id_cryptoctx->my_certs != NULL) {
+	sk_X509_pop_free(id_cryptoctx->my_certs, X509_free);
+    }
+    id_cryptoctx->my_certs = sk_X509_new_null();	
+    sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert);
+    id_cryptoctx->creds[0]->cert = NULL;	/* Don't free it twice */
+    id_cryptoctx->cert_index = 0;
+
+    if (id_cryptoctx->pkcs11_method != 1) {
+	id_cryptoctx->my_key = id_cryptoctx->creds[0]->key;
+	id_cryptoctx->creds[0]->key = NULL;	/* Don't free it twice */
+    } 
+#ifndef WITHOUT_PKCS11
+    else {
+	id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id;
+	id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */
+	id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len;
+    }
+#endif
+    retval = 0;
+errout:
+    return retval;
+}
+
+
+
+static krb5_error_code
+load_cas_and_crls(krb5_context context,
+		  pkinit_plg_crypto_context plg_cryptoctx,
+		  pkinit_req_crypto_context req_cryptoctx,
+		  pkinit_identity_crypto_context id_cryptoctx,
+		  int catype,
+		  char *filename)
+{
+    STACK_OF(X509_INFO) *sk = NULL;
+    STACK_OF(X509) *ca_certs = NULL;
+    STACK_OF(X509_CRL) *ca_crls = NULL;
+    BIO *in = NULL;
+    krb5_error_code retval = ENOMEM;
+    int i = 0;
+
+    /* If there isn't already a stack in the context,
+     * create a temporary one now */
+    switch(catype) {
+    case CATYPE_ANCHORS:
+	if (id_cryptoctx->trustedCAs != NULL)
+	    ca_certs = id_cryptoctx->trustedCAs;
+	else {
+	    ca_certs = sk_X509_new_null();
+	    if (ca_certs == NULL)
+		return ENOMEM;
+	}
+	break;
+    case CATYPE_INTERMEDIATES:
+	if (id_cryptoctx->intermediateCAs != NULL)
+	    ca_certs = id_cryptoctx->intermediateCAs;
+	else {
+	    ca_certs = sk_X509_new_null();
+	    if (ca_certs == NULL)
+		return ENOMEM;
+	}
+	break;
+    case CATYPE_CRLS:
+	if (id_cryptoctx->revoked != NULL)
+	    ca_crls = id_cryptoctx->revoked;
+	else {
+	    ca_crls = sk_X509_CRL_new_null();
+	    if (ca_crls == NULL)
+		return ENOMEM;
+	}
+	break;
+    default:
+	return ENOTSUP;
+    }
+
+    if (!(in = BIO_new_file(filename, "r"))) {
+	retval = errno;
+	pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__,
+		 filename, error_message(errno));
+	goto cleanup;
+    }
+
+    /* This loads from a file, a stack of x509/crl/pkey sets */
+    if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) {
+	pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename);
+	retval = EIO;
+	goto cleanup;
+    }
+
+    /* scan over the stack created from loading the file contents,
+     * weed out duplicates, and push new ones onto the return stack
+     */
+    for (i = 0; i < sk_X509_INFO_num(sk); i++) {
+	X509_INFO *xi = sk_X509_INFO_value(sk, i);
+	if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) { 
+	    int j = 0, size = sk_X509_num(ca_certs), flag = 0;
+
+	    if (!size) {
+		sk_X509_push(ca_certs, xi->x509);
+		xi->x509 = NULL;
+		continue;
+	    }
+	    for (j = 0; j < size; j++) {
+		X509 *x = sk_X509_value(ca_certs, j);
+		flag = X509_cmp(x, xi->x509);
+		if (flag == 0)
+		    break;
+		else 
+		    continue;
+	    }
+	    if (flag != 0) {
+		sk_X509_push(ca_certs, X509_dup(xi->x509));
+	    }
+	} else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) {
+	    int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0;
+	    if (!size) {
+		sk_X509_CRL_push(ca_crls, xi->crl);
+		xi->crl = NULL;
+		continue;
+	    }
+	    for (j = 0; j < size; j++) {
+		X509_CRL *x = sk_X509_CRL_value(ca_crls, j);
+		flag = X509_CRL_cmp(x, xi->crl);
+		if (flag == 0)
+		    break;
+		else
+		    continue;
+	    }
+	    if (flag != 0) {
+		sk_X509_push(ca_crls, X509_CRL_dup(xi->crl));
+	    }
+	}
+    }
+
+    /* If we added something and there wasn't a stack in the
+     * context before, add the temporary stack to the context.
+     */
+    switch(catype) {
+    case CATYPE_ANCHORS:
+	if (sk_X509_num(ca_certs) == 0) {
+	    pkiDebug("no anchors in file, %s\n", filename);
+	    if (id_cryptoctx->trustedCAs == NULL) 
+		sk_X509_free(ca_certs);
+	} else {
+	    if (id_cryptoctx->trustedCAs == NULL)
+		id_cryptoctx->trustedCAs = ca_certs;
+	}
+	break;
+    case CATYPE_INTERMEDIATES:
+	if (sk_X509_num(ca_certs) == 0) {
+	    pkiDebug("no intermediates in file, %s\n", filename);
+	    if (id_cryptoctx->intermediateCAs == NULL) 
+		sk_X509_free(ca_certs);
+	} else {
+	    if (id_cryptoctx->intermediateCAs == NULL)
+		id_cryptoctx->intermediateCAs = ca_certs;
+	}
+	break;
+    case CATYPE_CRLS:
+	if (sk_X509_num(ca_crls) == 0) {
+	    pkiDebug("no crls in file, %s\n", filename);
+	    if (id_cryptoctx->revoked == NULL)
+		sk_X509_CRL_free(ca_crls);
+	} else {
+	    if (id_cryptoctx->revoked == NULL)
+		id_cryptoctx->revoked = ca_crls;
+	}
+	break;
+    default:
+	/* Should have been caught above! */
+	retval = EINVAL;
+	goto cleanup;
+	break;
+    }
+
+    retval = 0;
+
+  cleanup:
+    if (in != NULL)
+	BIO_free(in);
+    if (sk != NULL)
+	sk_X509_INFO_pop_free(sk, X509_INFO_free);
+
+    return retval;
+}
+
+static krb5_error_code
+load_cas_and_crls_dir(krb5_context context,
+		      pkinit_plg_crypto_context plg_cryptoctx,
+		      pkinit_req_crypto_context req_cryptoctx,
+		      pkinit_identity_crypto_context id_cryptoctx,
+		      int catype,
+		      char *dirname) 
+{
+    krb5_error_code retval = EINVAL;
+    DIR *d = NULL;
+    struct dirent *dentry = NULL;
+    char filename[1024];
+
+    if (dirname == NULL)
+	return EINVAL;
+
+    d = opendir(dirname);
+    if (d == NULL) 
+	return ENOENT;
+
+    while ((dentry = readdir(d))) {
+	if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) {
+	    pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
+		     __FUNCTION__, dirname, dentry->d_name);
+	    goto cleanup;
+	}
+	/* Ignore subdirectories and anything starting with a dot */
+#ifdef DT_DIR
+	if (dentry->d_type == DT_DIR)
+	    continue;
+#endif
+	if (dentry->d_name[0] == '.')
+	    continue;
+	snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name);
+
+	retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
+				   id_cryptoctx, catype, filename);
+	if (retval)
+	    goto cleanup;
+    }
+
+    retval = 0;
+
+  cleanup:
+    if (d != NULL) 
+	closedir(d);
+
+    return retval;
+}
+
+krb5_error_code
+crypto_load_cas_and_crls(krb5_context context,
+			 pkinit_plg_crypto_context plg_cryptoctx,
+			 pkinit_req_crypto_context req_cryptoctx,
+			 pkinit_identity_opts *idopts,
+			 pkinit_identity_crypto_context id_cryptoctx,
+			 int idtype,
+			 int catype,
+			 char *id) 
+{
+    pkiDebug("%s: called with idtype %s and catype %s\n",
+	     __FUNCTION__, idtype2string(idtype), catype2string(catype));
+    switch (idtype) {
+    case IDTYPE_FILE:
+	return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
+				 id_cryptoctx, catype, id);
+	break;
+    case IDTYPE_DIR:
+	return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
+				     id_cryptoctx, catype, id);
+	break;
+    default:
+	return ENOTSUP;
+	break;
+    }
+}
+
+static krb5_error_code
+create_identifiers_from_stack(STACK_OF(X509) *sk,
+			      krb5_external_principal_identifier *** ids)
+{
+    krb5_error_code retval = ENOMEM;
+    int i = 0, sk_size = sk_X509_num(sk);
+    krb5_external_principal_identifier **krb5_cas = NULL;
+    X509 *x = NULL;
+    X509_NAME *xn = NULL;
+    unsigned char *p = NULL;
+    int len = 0;
+    PKCS7_ISSUER_AND_SERIAL *is = NULL;
+    char buf[DN_BUF_LEN];
+
+    *ids = NULL;
+
+    krb5_cas =
+	malloc((sk_size + 1) * sizeof(krb5_external_principal_identifier *));
+    if (krb5_cas == NULL)
+	return ENOMEM;
+    krb5_cas[sk_size] = NULL;
+
+    for (i = 0; i < sk_size; i++) {
+	krb5_cas[i] = (krb5_external_principal_identifier *)malloc(sizeof(krb5_external_principal_identifier));
+
+	x = sk_X509_value(sk, i);
+
+	X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
+	pkiDebug("#%d cert= %s\n", i, buf);
+
+	/* fill-in subjectName */
+	krb5_cas[i]->subjectName.magic = 0;
+	krb5_cas[i]->subjectName.length = 0;
+	krb5_cas[i]->subjectName.data = NULL;
+
+	xn = X509_get_subject_name(x);
+	len = i2d_X509_NAME(xn, NULL);
+	if ((p = krb5_cas[i]->subjectName.data = (unsigned char *)malloc((size_t) len)) == NULL)
+	    goto cleanup;
+	i2d_X509_NAME(xn, &p);
+	krb5_cas[i]->subjectName.length = len;
+
+	/* fill-in issuerAndSerialNumber */
+	krb5_cas[i]->issuerAndSerialNumber.length = 0;
+	krb5_cas[i]->issuerAndSerialNumber.magic = 0;
+	krb5_cas[i]->issuerAndSerialNumber.data = NULL;
+
+#ifdef LONGHORN_BETA_COMPAT
+if (longhorn == 0) { /* XXX Longhorn doesn't like this */
+#endif
+	is = PKCS7_ISSUER_AND_SERIAL_new();
+	X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
+	M_ASN1_INTEGER_free(is->serial);
+	is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x));
+	len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+	if ((p = krb5_cas[i]->issuerAndSerialNumber.data =
+	     (unsigned char *)malloc((size_t) len)) == NULL)
+	    goto cleanup;
+	i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
+	krb5_cas[i]->issuerAndSerialNumber.length = len;
+#ifdef LONGHORN_BETA_COMPAT
+}
+#endif
+
+	/* fill-in subjectKeyIdentifier */
+	krb5_cas[i]->subjectKeyIdentifier.length = 0;
+	krb5_cas[i]->subjectKeyIdentifier.magic = 0;
+	krb5_cas[i]->subjectKeyIdentifier.data = NULL;
+
+
+#ifdef LONGHORN_BETA_COMPAT
+if (longhorn == 0) {	/* XXX Longhorn doesn't like this */
+#endif
+	if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
+	    ASN1_OCTET_STRING *ikeyid = NULL;
+
+	    if ((ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
+					   NULL))) {
+		len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
+		if ((p = krb5_cas[i]->subjectKeyIdentifier.data =
+			(unsigned char *)malloc((size_t) len)) == NULL)
+		    goto cleanup;
+		i2d_ASN1_OCTET_STRING(ikeyid, &p);		
+		krb5_cas[i]->subjectKeyIdentifier.length = len;
+	    }
+	    if (ikeyid != NULL)
+		ASN1_OCTET_STRING_free(ikeyid);
+	}
+#ifdef LONGHORN_BETA_COMPAT
+}
+#endif
+	if (is != NULL) {
+	    if (is->issuer != NULL)
+		X509_NAME_free(is->issuer);
+	    if (is->serial != NULL)
+		ASN1_INTEGER_free(is->serial);
+	    free(is);
+	}
+    }
+
+    *ids = krb5_cas;
+
+    retval = 0;
+  cleanup:
+    if (retval)
+	free_krb5_external_principal_identifier(&krb5_cas);
+
+    return retval;
+}
+
+static krb5_error_code
+create_krb5_invalidCertificates(krb5_context context,
+				pkinit_plg_crypto_context plg_cryptoctx,
+				pkinit_req_crypto_context req_cryptoctx,
+				pkinit_identity_crypto_context id_cryptoctx,
+				krb5_external_principal_identifier *** ids)
+{
+
+    krb5_error_code retval = ENOMEM;
+    STACK_OF(X509) *sk = NULL;
+
+    *ids = NULL;
+    if (req_cryptoctx->received_cert == NULL)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+
+    sk = sk_X509_new_null();
+    if (sk == NULL) 
+	goto cleanup;
+    sk_X509_push(sk, req_cryptoctx->received_cert);
+
+    retval = create_identifiers_from_stack(sk, ids);
+
+    sk_X509_free(sk);
+cleanup:
+
+    return retval;
+}
+
+krb5_error_code
+create_krb5_supportedCMSTypes(krb5_context context,
+			      pkinit_plg_crypto_context plg_cryptoctx,
+			      pkinit_req_crypto_context req_cryptoctx,
+			      pkinit_identity_crypto_context id_cryptoctx,
+			      krb5_algorithm_identifier ***oids)
+{
+
+    krb5_error_code retval = ENOMEM;
+    krb5_algorithm_identifier **loids = NULL;
+    krb5_octet_data des3oid = {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
+
+    *oids = NULL;
+    loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
+    if (loids == NULL)
+	goto cleanup;
+    loids[1] = NULL;
+    loids[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+    if (loids[0] == NULL) {
+	free(loids);
+	goto cleanup;
+    }
+    retval = pkinit_copy_krb5_octet_data(&loids[0]->algorithm, &des3oid);
+    if (retval) {
+	free(loids[0]);
+	free(loids);
+	goto cleanup;
+    }
+    loids[0]->parameters.length = 0;
+    loids[0]->parameters.data = NULL;
+
+    *oids = loids;
+    retval = 0;
+cleanup:
+
+    return retval;
+}
+
+krb5_error_code
+create_krb5_trustedCertifiers(krb5_context context,
+			      pkinit_plg_crypto_context plg_cryptoctx,
+			      pkinit_req_crypto_context req_cryptoctx,
+			      pkinit_identity_crypto_context id_cryptoctx,
+			      krb5_external_principal_identifier *** ids)
+{
+
+    krb5_error_code retval = ENOMEM;
+    STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
+
+    *ids = NULL;
+    if (id_cryptoctx->trustedCAs == NULL)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+
+    retval = create_identifiers_from_stack(sk, ids);
+
+    return retval;
+}
+
+krb5_error_code
+create_krb5_trustedCas(krb5_context context,
+		       pkinit_plg_crypto_context plg_cryptoctx,
+		       pkinit_req_crypto_context req_cryptoctx,
+		       pkinit_identity_crypto_context id_cryptoctx,
+		       int flag,
+		       krb5_trusted_ca *** ids)
+{
+    krb5_error_code retval = ENOMEM;
+    STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
+    int i = 0, len = 0, sk_size = sk_X509_num(sk);
+    krb5_trusted_ca **krb5_cas = NULL;
+    X509 *x = NULL;
+    char buf[DN_BUF_LEN];
+    X509_NAME *xn = NULL;
+    unsigned char *p = NULL;
+    PKCS7_ISSUER_AND_SERIAL *is = NULL;
+
+    *ids = NULL;
+    if (id_cryptoctx->trustedCAs == NULL)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+
+    krb5_cas = malloc((sk_size + 1) * sizeof(krb5_trusted_ca *));
+    if (krb5_cas == NULL)
+	return ENOMEM;
+    krb5_cas[sk_size] = NULL;
+
+    for (i = 0; i < sk_size; i++) {
+	krb5_cas[i] = (krb5_trusted_ca *)malloc(sizeof(krb5_trusted_ca));
+	if (krb5_cas[i] == NULL)
+	    goto cleanup;
+	x = sk_X509_value(sk, i);
+
+	X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
+	pkiDebug("#%d cert= %s\n", i, buf);
+
+	switch (flag) {
+	    case choice_trusted_cas_principalName:
+		krb5_cas[i]->choice = choice_trusted_cas_principalName;
+		break;
+	    case choice_trusted_cas_caName:
+		krb5_cas[i]->choice = choice_trusted_cas_caName;
+		krb5_cas[i]->u.caName.data = NULL;
+		krb5_cas[i]->u.caName.length = 0;
+		xn = X509_get_subject_name(x);
+		len = i2d_X509_NAME(xn, NULL);
+		if ((p = krb5_cas[i]->u.caName.data =
+		    (unsigned char *)malloc((size_t) len)) == NULL)
+		    goto cleanup;
+		i2d_X509_NAME(xn, &p);
+		krb5_cas[i]->u.caName.length = len;
+		break;
+	    case choice_trusted_cas_issuerAndSerial:
+		krb5_cas[i]->choice = choice_trusted_cas_issuerAndSerial;
+		krb5_cas[i]->u.issuerAndSerial.data = NULL;
+		krb5_cas[i]->u.issuerAndSerial.length = 0;
+		is = PKCS7_ISSUER_AND_SERIAL_new();
+		X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
+		M_ASN1_INTEGER_free(is->serial);
+		is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x));
+		len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+		if ((p = krb5_cas[i]->u.issuerAndSerial.data =
+		    (unsigned char *)malloc((size_t) len)) == NULL)
+		    goto cleanup;
+		i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
+		krb5_cas[i]->u.issuerAndSerial.length = len;
+		if (is != NULL) {
+		    if (is->issuer != NULL)
+			X509_NAME_free(is->issuer);
+		    if (is->serial != NULL)
+			ASN1_INTEGER_free(is->serial);
+		    free(is);
+		}
+		break;
+	    default: break;
+	}
+    }
+    retval = 0;
+    *ids = krb5_cas;
+cleanup:
+    if (retval)
+	free_krb5_trusted_ca(&krb5_cas);
+
+    return retval;
+}
+
+krb5_error_code
+create_issuerAndSerial(krb5_context context,
+		       pkinit_plg_crypto_context plg_cryptoctx,
+		       pkinit_req_crypto_context req_cryptoctx,
+		       pkinit_identity_crypto_context id_cryptoctx,
+		       unsigned char **out,
+		       unsigned int *out_len)
+{
+    unsigned char *p = NULL;
+    PKCS7_ISSUER_AND_SERIAL *is = NULL;
+    int len = 0;
+    krb5_error_code retval = ENOMEM;
+    X509 *cert = req_cryptoctx->received_cert;
+
+    *out = NULL;
+    *out_len = 0;
+    if (req_cryptoctx->received_cert == NULL)
+	return 0;
+
+    is = PKCS7_ISSUER_AND_SERIAL_new();
+    X509_NAME_set(&is->issuer, X509_get_issuer_name(cert));
+    M_ASN1_INTEGER_free(is->serial);
+    is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
+    len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+    if ((p = *out = (unsigned char *)malloc((size_t) len)) == NULL)
+	goto cleanup;
+    i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
+    *out_len = len;
+    retval = 0;
+
+cleanup:
+    X509_NAME_free(is->issuer);
+    ASN1_INTEGER_free(is->serial);
+    free(is);
+
+    return retval;
+}
+
+static int
+pkcs7_decrypt(krb5_context context,
+	      pkinit_identity_crypto_context id_cryptoctx,
+	      PKCS7 *p7,
+	      BIO *data)
+{
+    BIO *tmpmem = NULL;
+    int retval = 0, i = 0;
+    char buf[4096];
+
+    if(p7 == NULL)
+	return 0;
+
+    if(!PKCS7_type_is_enveloped(p7)) {
+	pkiDebug("wrong pkcs7 content type\n");
+	return 0;
+    }
+
+    if(!(tmpmem = pkcs7_dataDecode(context, id_cryptoctx, p7))) {
+	pkiDebug("unable to decrypt pkcs7 object\n");
+	return 0;
+    }
+
+    for(;;) {
+	i = BIO_read(tmpmem, buf, sizeof(buf));
+	if (i <= 0) break;
+	BIO_write(data, buf, i);
+	BIO_free_all(tmpmem);
+	return 1;
+    }
+    return retval;
+}
+
+krb5_error_code
+pkinit_process_td_trusted_certifiers(
+    krb5_context context,
+    pkinit_plg_crypto_context plg_cryptoctx,
+    pkinit_req_crypto_context req_cryptoctx,
+    pkinit_identity_crypto_context id_cryptoctx,
+    krb5_external_principal_identifier **krb5_trusted_certifiers,
+    int td_type)
+{
+    krb5_error_code retval = ENOMEM;
+    STACK_OF(X509_NAME) *sk_xn = NULL;
+    X509_NAME *xn = NULL;
+    PKCS7_ISSUER_AND_SERIAL *is = NULL;
+    ASN1_OCTET_STRING *id = NULL;
+    const unsigned char *p = NULL;
+    char buf[DN_BUF_LEN];
+    int i = 0;
+
+    if (td_type == TD_TRUSTED_CERTIFIERS)
+	pkiDebug("received trusted certifiers\n");
+    else
+	pkiDebug("received invalid certificate\n");
+
+    sk_xn = sk_X509_NAME_new_null();
+    while(krb5_trusted_certifiers[i] != NULL) {
+	if (krb5_trusted_certifiers[i]->subjectName.data != NULL) {
+	    p = krb5_trusted_certifiers[i]->subjectName.data;
+	    xn = d2i_X509_NAME(NULL, &p,
+		(int)krb5_trusted_certifiers[i]->subjectName.length);
+	    if (xn == NULL)
+		goto cleanup;
+	    X509_NAME_oneline(xn, buf, sizeof(buf));
+	    if (td_type == TD_TRUSTED_CERTIFIERS)
+		pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf);
+	    else
+		pkiDebug("#%d cert = %s is invalid\n", i, buf);
+		sk_X509_NAME_push(sk_xn, xn);
+	}
+
+	if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) {
+	    p = krb5_trusted_certifiers[i]->issuerAndSerialNumber.data;
+	    is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p,
+		(int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length);
+	    if (is == NULL)
+		goto cleanup;
+	    X509_NAME_oneline(is->issuer, buf, sizeof(buf));
+	    if (td_type == TD_TRUSTED_CERTIFIERS)
+		pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i,
+			 buf, ASN1_INTEGER_get(is->serial));
+	    else
+		pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf,
+			 ASN1_INTEGER_get(is->serial));
+	    PKCS7_ISSUER_AND_SERIAL_free(is);
+	}
+
+	if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) {
+	    p = krb5_trusted_certifiers[i]->subjectKeyIdentifier.data;
+	    id = d2i_ASN1_OCTET_STRING(NULL, &p,
+		(int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length);
+	    if (id == NULL)
+		goto cleanup;
+	    /* XXX */
+	    ASN1_OCTET_STRING_free(id);
+	}
+	i++;
+    }
+    /* XXX Since we not doing anything with received trusted certifiers
+     * return an error. this is the place where we can pick a different
+     * client certificate based on the information in td_trusted_certifiers
+     */
+    retval = KRB5KDC_ERR_PREAUTH_FAILED;
+cleanup:
+    if (sk_xn != NULL)
+	sk_X509_NAME_pop_free(sk_xn, X509_NAME_free);
+
+    return retval;
+}
+
+static BIO *
+pkcs7_dataDecode(krb5_context context,
+		 pkinit_identity_crypto_context id_cryptoctx,
+		 PKCS7 *p7)
+{
+    int i = 0;
+    unsigned int jj = 0, tmp_len = 0;
+    BIO *out=NULL,*etmp=NULL,*bio=NULL;
+    unsigned char *tmp=NULL;
+    ASN1_OCTET_STRING *data_body=NULL;
+    const EVP_CIPHER *evp_cipher=NULL;
+    EVP_CIPHER_CTX *evp_ctx=NULL;
+    X509_ALGOR *enc_alg=NULL;
+    STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
+    X509_ALGOR *xalg=NULL;
+    PKCS7_RECIP_INFO *ri=NULL;
+    X509 *cert = sk_X509_value(id_cryptoctx->my_certs,
+	id_cryptoctx->cert_index);
+
+    p7->state=PKCS7_S_HEADER;
+
+    rsk=p7->d.enveloped->recipientinfo;
+    enc_alg=p7->d.enveloped->enc_data->algorithm;
+    data_body=p7->d.enveloped->enc_data->enc_data;
+    evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
+    if (evp_cipher == NULL) {
+	PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+	goto cleanup;
+    }
+    xalg=p7->d.enveloped->enc_data->algorithm;
+
+    if ((etmp=BIO_new(BIO_f_cipher())) == NULL) {
+	PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
+	goto cleanup;
+    }
+
+    /* It was encrypted, we need to decrypt the secret key
+     * with the private key */
+
+    /* Find the recipientInfo which matches the passed certificate
+     * (if any)
+     */
+
+    if (cert) {
+	for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+	    int tmp_ret = 0;
+	    ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
+	    tmp_ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
+				    cert->cert_info->issuer);
+	    if (!tmp_ret) {
+		tmp_ret = M_ASN1_INTEGER_cmp(cert->cert_info->serialNumber,
+					     ri->issuer_and_serial->serial);
+		if (!tmp_ret)
+		    break;
+	    }
+	    ri=NULL;
+	}
+	if (ri == NULL) {
+	    PKCS7err(PKCS7_F_PKCS7_DATADECODE,
+		     PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
+	    goto cleanup;
+	}
+	
+    }
+
+    /* If we haven't got a certificate try each ri in turn */
+
+    if (cert == NULL) {
+	for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+	    ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
+	    jj = pkinit_decode_data(context, id_cryptoctx,
+		M_ASN1_STRING_data(ri->enc_key),
+		(unsigned int) M_ASN1_STRING_length(ri->enc_key),
+		&tmp, &tmp_len);
+	    if (jj) {
+		PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
+		goto cleanup;
+	    }
+
+	    if (!jj && tmp_len > 0) {
+		jj = tmp_len;
+		break;
+	    }
+
+	    ERR_clear_error();
+	    ri = NULL;
+	}
+
+	if (ri == NULL) {
+	    PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
+	    goto cleanup;
+	}
+    }
+    else {
+	jj = pkinit_decode_data(context, id_cryptoctx,
+	    M_ASN1_STRING_data(ri->enc_key),
+	    (unsigned int) M_ASN1_STRING_length(ri->enc_key),
+	    &tmp, &tmp_len);
+	if (jj || tmp_len <= 0) {
+	    PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
+	    goto cleanup;
+	}
+	jj = tmp_len;
+    }
+
+    evp_ctx=NULL;
+    BIO_get_cipher_ctx(etmp,&evp_ctx);
+    if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
+	goto cleanup;
+    if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
+	goto cleanup;
+
+    if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
+	/* Some S/MIME clients don't use the same key
+	 * and effective key length. The key length is
+	 * determined by the size of the decrypted RSA key.
+	 */
+	if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)jj)) {
+	    PKCS7err(PKCS7_F_PKCS7_DATADECODE,
+		     PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
+	    goto cleanup;
+	}
+    }
+    if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
+	goto cleanup;
+
+    OPENSSL_cleanse(tmp,jj);
+
+    if (out == NULL)
+	out=etmp;
+    else
+	BIO_push(out,etmp);
+    etmp=NULL;
+
+    if (data_body->length > 0)
+	bio = BIO_new_mem_buf(data_body->data, data_body->length);
+    else {
+	bio=BIO_new(BIO_s_mem());
+	BIO_set_mem_eof_return(bio,0);
+    }
+    BIO_push(out,bio);
+    bio=NULL;
+
+    if (0) {
+cleanup:
+	if (out != NULL) BIO_free_all(out);
+	if (etmp != NULL) BIO_free_all(etmp);
+	if (bio != NULL) BIO_free_all(bio);
+	out=NULL;
+    }
+
+    if (tmp != NULL)
+	free(tmp);
+
+    return(out);
+}
+
+static krb5_error_code
+der_decode_data(unsigned char *data, long data_len,
+		unsigned char **out, long *out_len)
+{
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    ASN1_OCTET_STRING *s = NULL;
+    const unsigned char *p = data;
+
+    if ((s = d2i_ASN1_BIT_STRING(NULL, &p, data_len)) == NULL)
+	goto cleanup;
+    *out_len = s->length;
+    if ((*out = (unsigned char *) malloc((size_t) *out_len + 1)) == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+    memcpy(*out, s->data, (size_t) s->length);
+    (*out)[s->length] = '\0';
+
+    retval = 0;
+  cleanup:
+    if (s != NULL)
+	ASN1_OCTET_STRING_free(s);
+
+    return retval;
+}
+
+
+#ifdef DEBUG_DH
+static void
+print_dh(DH * dh, char *msg)
+{
+    BIO *bio_err = NULL;
+
+    bio_err = BIO_new(BIO_s_file());
+    BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+    if (msg)
+	BIO_puts(bio_err, (const char *)msg);
+    if (dh)
+	DHparams_print(bio_err, dh);
+
+    BN_print(bio_err, dh->q);
+    BIO_puts(bio_err, (const char *)"\n");
+    BIO_free(bio_err);
+
+}
+
+static void
+print_pubkey(BIGNUM * key, char *msg)
+{
+    BIO *bio_err = NULL;
+
+    bio_err = BIO_new(BIO_s_file());
+    BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+    if (msg)
+	BIO_puts(bio_err, (const char *)msg);
+    if (key)
+	BN_print(bio_err, key);
+    BIO_puts(bio_err, "\n");
+
+    BIO_free(bio_err);
+
+}
+#endif
+
+static char *
+pkinit_pkcs11_code_to_text(int err)
+{
+    int i;
+    static char uc[32];
+
+    for (i = 0; pkcs11_errstrings[i].text != NULL; i++)
+	if (pkcs11_errstrings[i].code == err)
+	    break;
+    if (pkcs11_errstrings[i].text != NULL)
+	return (pkcs11_errstrings[i].text);
+    sprintf(uc, "unknown code 0x%x", err);
+    return (uc);
+}
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
new file mode 100644
index 000000000..9c824c811
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
@@ -0,0 +1,265 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _PKINIT_CRYPTO_OPENSSL_H
+#define _PKINIT_CRYPTO_OPENSSL_H
+
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/obj_mac.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/asn1_mac.h>
+#include <openssl/sha.h>
+#include <openssl/asn1.h>
+#include <openssl/pem.h>
+
+#include "pkinit.h"
+
+#define DN_BUF_LEN  256
+#define MAX_CREDS_ALLOWED 20
+
+struct _pkinit_cred_info {
+    X509 *cert;
+    EVP_PKEY *key;
+#ifndef WITHOUT_PKCS11
+    CK_BYTE_PTR cert_id;
+    int cert_id_len;
+#endif
+};
+typedef struct _pkinit_cred_info * pkinit_cred_info;
+
+struct _pkinit_identity_crypto_context {
+    pkinit_cred_info creds[MAX_CREDS_ALLOWED+1];
+    STACK_OF(X509) *my_certs;   /* available user certs */
+    int cert_index;             /* cert to use out of available certs*/
+    EVP_PKEY *my_key;           /* available user keys if in filesystem */
+    STACK_OF(X509) *trustedCAs; /* available trusted ca certs */
+    STACK_OF(X509) *intermediateCAs;   /* available intermediate ca certs */
+    STACK_OF(X509_CRL) *revoked;    /* available crls */
+    int pkcs11_method;
+    krb5_prompter_fct prompter;
+    void *prompter_data;
+#ifndef WITHOUT_PKCS11
+    char *p11_module_name;
+    CK_SLOT_ID slotid;
+    char *token_label;
+    char *cert_label;
+    /* These are crypto-specific */
+    void *p11_module;
+    CK_SESSION_HANDLE session;
+    CK_FUNCTION_LIST_PTR p11;
+    CK_BYTE_PTR cert_id;
+    int cert_id_len;
+    CK_MECHANISM_TYPE mech;
+#endif
+};
+
+struct _pkinit_plg_crypto_context {
+    DH *dh_1024;
+    DH *dh_2048;
+    DH *dh_4096;
+    ASN1_OBJECT *id_pkinit_authData;
+    ASN1_OBJECT *id_pkinit_authData9;
+    ASN1_OBJECT *id_pkinit_DHKeyData;
+    ASN1_OBJECT *id_pkinit_rkeyData;
+    ASN1_OBJECT *id_pkinit_san;
+    ASN1_OBJECT *id_ms_san_upn;
+    ASN1_OBJECT *id_pkinit_KPClientAuth;
+    ASN1_OBJECT *id_pkinit_KPKdc;
+    ASN1_OBJECT *id_ms_kp_sc_logon;
+    ASN1_OBJECT *id_kp_serverAuth;
+};
+
+struct _pkinit_req_crypto_context {
+    X509 *received_cert;
+    DH *dh;
+};
+
+#define CERT_MAGIC 0x53534c43
+struct _pkinit_cert_data {
+    unsigned int magic;
+    pkinit_plg_crypto_context plgctx;
+    pkinit_req_crypto_context reqctx;
+    pkinit_identity_crypto_context idctx;
+    pkinit_cred_info cred;
+    unsigned int index;	    /* Index of this cred in the creds[] array */
+};
+
+#define ITER_MAGIC 0x53534c49
+struct _pkinit_cert_iter_data {
+    unsigned int magic;
+    pkinit_plg_crypto_context plgctx;
+    pkinit_req_crypto_context reqctx;
+    pkinit_identity_crypto_context idctx;
+    unsigned int index;
+};
+
+static void openssl_init(void);
+
+static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
+static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
+
+static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
+static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
+
+static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
+static void pkinit_fini_certs(pkinit_identity_crypto_context ctx);
+
+static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx);
+static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx);
+
+static krb5_error_code pkinit_encode_dh_params
+	(BIGNUM *, BIGNUM *, BIGNUM *, unsigned char **, unsigned int *);
+static DH *pkinit_decode_dh_params
+	(DH **, unsigned char **, unsigned int );
+static int pkinit_check_dh_params
+	(BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1);
+
+static krb5_error_code pkinit_sign_data
+	(krb5_context context, pkinit_identity_crypto_context cryptoctx,
+		unsigned char *data, unsigned int data_len,
+		unsigned char **sig, unsigned int *sig_len);
+
+static krb5_error_code create_signature
+	(unsigned char **, unsigned int *, unsigned char *, unsigned int,
+		EVP_PKEY *pkey);
+
+static krb5_error_code pkinit_decode_data
+	(krb5_context context, pkinit_identity_crypto_context cryptoctx,
+		unsigned char *data, unsigned int data_len,
+		unsigned char **decoded, unsigned int *decoded_len);
+
+static krb5_error_code decode_data
+	(unsigned char **, unsigned int *, unsigned char *, unsigned int,
+		EVP_PKEY *pkey, X509 *cert);
+
+#ifdef DEBUG_DH
+static void print_dh(DH *, char *);
+static void print_pubkey(BIGNUM *, char *);
+#endif
+
+static int prepare_enc_data
+	(unsigned char *indata, int indata_len, unsigned char **outdata,
+		int *outdata_len);
+
+static int openssl_callback (int, X509_STORE_CTX *);
+static int openssl_callback_ignore_crls (int, X509_STORE_CTX *);
+
+static int pkcs7_decrypt
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+		PKCS7 *p7, BIO *bio);
+
+static BIO * pkcs7_dataDecode
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+		PKCS7 *p7);
+
+static ASN1_OBJECT * pkinit_pkcs7type2oid
+	(pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type);
+
+static krb5_error_code pkinit_create_sequence_of_principal_identifiers
+	(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx,
+		pkinit_req_crypto_context req_cryptoctx,
+		pkinit_identity_crypto_context id_cryptoctx,
+		int type, krb5_data **out_data);
+
+#ifndef WITHOUT_PKCS11
+static krb5_error_code pkinit_find_private_key
+	(pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage,
+		CK_OBJECT_HANDLE *objp);
+static krb5_error_code pkinit_login
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+		CK_TOKEN_INFO *tip);
+static krb5_error_code pkinit_open_session
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx);
+static void * pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p);
+static CK_RV pkinit_C_UnloadModule(void *handle);
+#ifdef SILLYDECRYPT
+CK_RV pkinit_C_Decrypt
+	(pkinit_identity_crypto_context id_cryptoctx,
+		CK_BYTE_PTR pEncryptedData, CK_ULONG  ulEncryptedDataLen,
+		CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+#endif
+
+static krb5_error_code pkinit_sign_data_pkcs11
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+		unsigned char *data, unsigned int data_len,
+		unsigned char **sig, unsigned int *sig_len);
+static krb5_error_code pkinit_decode_data_pkcs11
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+		unsigned char *data, unsigned int data_len,
+		unsigned char **decoded_data, unsigned int *decoded_data_len);
+#endif	/* WITHOUT_PKCS11 */
+
+static krb5_error_code pkinit_sign_data_fs
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+		unsigned char *data, unsigned int data_len,
+		unsigned char **sig, unsigned int *sig_len);
+static krb5_error_code pkinit_decode_data_fs
+	(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+		unsigned char *data, unsigned int data_len,
+		unsigned char **decoded_data, unsigned int *decoded_data_len);
+
+static krb5_error_code der_decode_data
+	(unsigned char *, long, unsigned char **, long *);
+
+static krb5_error_code
+create_krb5_invalidCertificates(krb5_context context,
+				pkinit_plg_crypto_context plg_cryptoctx,
+				pkinit_req_crypto_context req_cryptoctx,
+				pkinit_identity_crypto_context id_cryptoctx,
+				krb5_external_principal_identifier *** ids);
+
+static krb5_error_code
+create_identifiers_from_stack(STACK_OF(X509) *sk,
+			      krb5_external_principal_identifier *** ids);
+#ifdef LONGHORN_BETA_COMPAT
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+		unsigned char **out, unsigned int *out_len,
+		int is_longhorn_server);
+#else
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+		unsigned char **out, unsigned int *out_len);
+#endif
+
+/* This handy macro borrowed from crypto/x509v3/v3_purp.c */
+#define ku_reject(x, usage) \
+	(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
+
+static char *
+pkinit_pkcs11_code_to_text(int err);
+
+#endif	/* _PKINIT_CRYPTO_OPENSSL_H */
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_identity.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_identity.c
new file mode 100644
index 000000000..227c55d0f
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_identity.c
@@ -0,0 +1,668 @@
+/*
+ * COPYRIGHT (C) 2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "pkinit.h"
+
+static void
+free_list(char **list)
+{
+    int i;
+
+    if (list == NULL)
+	return;
+
+    for (i = 0; list[i] != NULL; i++)
+	free(list[i]);
+     free(list);
+}
+
+static krb5_error_code
+copy_list(char ***dst, char **src)
+{
+    int i;
+    char **newlist;
+
+    if (dst == NULL)
+	return EINVAL;
+    *dst = NULL;
+
+    if (src == NULL)
+	return 0;
+
+    for (i = 0; src[i] != NULL; i++);
+
+    newlist = calloc(1, (i + 1) * sizeof(*newlist));
+    if (newlist == NULL)
+	return ENOMEM;
+
+    for (i = 0; src[i] != NULL; i++) {
+	newlist[i] = strdup(src[i]);
+	if (newlist[i] == NULL)
+	    goto cleanup;
+    }
+    newlist[i] = NULL;
+    *dst = newlist;
+    return 0;
+cleanup:
+    free_list(newlist);
+    return ENOMEM;
+}
+
+char *
+idtype2string(int idtype)
+{
+    switch(idtype) {
+    case IDTYPE_FILE: return "FILE"; break;
+    case IDTYPE_DIR: return "DIR"; break;
+    case IDTYPE_PKCS11: return "PKCS11"; break;
+    case IDTYPE_PKCS12: return "PKCS12"; break;
+    case IDTYPE_ENVVAR: return "ENV"; break;
+    default: return "INVALID"; break;
+    }
+}
+
+char *
+catype2string(int catype)
+{
+    switch(catype) {
+    case CATYPE_ANCHORS: return "ANCHORS"; break;
+    case CATYPE_INTERMEDIATES: return "INTERMEDIATES"; break;
+    case CATYPE_CRLS: return "CRLS"; break;
+    default: return "INVALID"; break;
+    }
+}
+
+krb5_error_code
+pkinit_init_identity_opts(pkinit_identity_opts **idopts)
+{
+    pkinit_identity_opts *opts = NULL;
+
+    *idopts = NULL;
+    opts = (pkinit_identity_opts *) calloc(1, sizeof(pkinit_identity_opts));
+    if (opts == NULL)
+	return ENOMEM;
+
+    opts->identity = NULL;
+    opts->anchors = NULL;
+    opts->intermediates = NULL;
+    opts->crls = NULL;
+    opts->ocsp = NULL;
+    opts->dn_mapping_file = NULL;
+
+    opts->cert_filename = NULL;
+    opts->key_filename = NULL;
+#ifndef WITHOUT_PKCS11
+    opts->p11_module_name = NULL;
+    opts->slotid = PK_NOSLOT;
+    opts->token_label = NULL;
+    opts->cert_id_string = NULL;
+    opts->cert_label = NULL;
+#endif
+
+    *idopts = opts;
+
+    return 0;
+}
+
+krb5_error_code
+pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
+			 pkinit_identity_opts **dest_opts)
+{
+    pkinit_identity_opts *newopts;
+    krb5_error_code retval;
+
+    *dest_opts = NULL;
+    retval = pkinit_init_identity_opts(&newopts);
+    if (retval)
+	return retval;
+
+    retval = ENOMEM;
+
+    if (src_opts->identity != NULL) {
+	newopts->identity = strdup(src_opts->identity);
+	if (newopts->identity == NULL)
+	    goto cleanup;
+    }
+
+    retval = copy_list(&newopts->anchors, src_opts->anchors);
+    if (retval)
+	goto cleanup;
+
+    retval = copy_list(&newopts->intermediates,src_opts->intermediates);
+    if (retval)
+	goto cleanup;
+
+    retval = copy_list(&newopts->crls, src_opts->crls);
+    if (retval)
+	goto cleanup;
+
+    if (src_opts->ocsp != NULL) {
+	newopts->ocsp = strdup(src_opts->ocsp);
+	if (newopts->ocsp == NULL)
+	    goto cleanup;
+    }
+
+    if (src_opts->cert_filename != NULL) {
+	newopts->cert_filename = strdup(src_opts->cert_filename);
+	if (newopts->cert_filename == NULL)
+	    goto cleanup;
+    }
+
+    if (src_opts->key_filename != NULL) {
+	newopts->key_filename = strdup(src_opts->key_filename);
+	if (newopts->key_filename == NULL)
+	    goto cleanup;
+    }
+
+#ifndef WITHOUT_PKCS11
+    if (src_opts->p11_module_name != NULL) {
+	newopts->p11_module_name = strdup(src_opts->p11_module_name);
+	if (newopts->p11_module_name == NULL)
+	    goto cleanup;
+    }
+
+    newopts->slotid = src_opts->slotid;
+
+    if (src_opts->token_label != NULL) {
+	newopts->token_label = strdup(src_opts->token_label);
+	if (newopts->token_label == NULL)
+	    goto cleanup;
+    }
+
+    if (src_opts->cert_id_string != NULL) {
+	newopts->cert_id_string = strdup(src_opts->cert_id_string);
+	if (newopts->cert_id_string == NULL)
+	    goto cleanup;
+    }
+
+    if (src_opts->cert_label != NULL) {
+	newopts->cert_label = strdup(src_opts->cert_label);
+	if (newopts->cert_label == NULL)
+	    goto cleanup;
+    }
+#endif
+
+
+    *dest_opts = newopts;
+    return 0;
+cleanup:
+    pkinit_fini_identity_opts(newopts);
+    return retval;
+}
+
+void
+pkinit_fini_identity_opts(pkinit_identity_opts *idopts)
+{
+    if (idopts == NULL)
+	return;
+
+    if (idopts->identity != NULL)
+	free(idopts->identity);
+    free_list(idopts->anchors);
+    free_list(idopts->intermediates);
+    free_list(idopts->crls);
+    free_list(idopts->identity_alt);
+
+    if (idopts->cert_filename != NULL)
+	free(idopts->cert_filename);
+    if (idopts->key_filename != NULL)
+	free(idopts->key_filename);
+#ifndef WITHOUT_PKCS11
+    if (idopts->p11_module_name != NULL)
+	free(idopts->p11_module_name);
+    if (idopts->token_label != NULL)
+	free(idopts->token_label);
+    if (idopts->cert_id_string != NULL)
+	free(idopts->cert_id_string);
+    if (idopts->cert_label != NULL)
+	free(idopts->cert_label);
+#endif
+    free(idopts);
+}
+
+#ifndef WITHOUT_PKCS11
+static krb5_error_code
+parse_pkcs11_options(krb5_context context,
+		     pkinit_identity_opts *idopts,
+		     const char *residual)
+{
+    char *s, *cp, *vp;
+    krb5_error_code retval = ENOMEM;
+
+    if (residual == NULL || residual[0] == '\0')
+	return 0;
+
+    /* Split string into attr=value substrings */
+    s = strdup(residual);
+    if (s == NULL)
+	return retval;
+
+    for ((cp = strtok(s, ":")); cp; (cp = strtok(NULL, ":"))) {
+	vp = strchr(cp, '=');
+
+	/* If there is no "=", this is a pkcs11 module name */
+	if (vp == NULL) {
+	    if (idopts->p11_module_name != NULL)
+		free(idopts->p11_module_name);
+	    idopts->p11_module_name = strdup(cp);
+	    if (idopts->p11_module_name == NULL)
+		goto cleanup;
+	    continue;
+	}
+	*vp++ = '\0';
+	if (!strcmp(cp, "module_name")) {
+	    if (idopts->p11_module_name != NULL)
+		free(idopts->p11_module_name);
+	    idopts->p11_module_name = strdup(vp);
+	    if (idopts->p11_module_name == NULL)
+		goto cleanup;
+	} else if (!strcmp(cp, "slotid")) {
+	    long slotid = strtol(vp, NULL, 10);
+	    if ((slotid == LONG_MIN || slotid == LONG_MAX) && errno != 0) {
+		retval = EINVAL;
+		goto cleanup;
+	    }
+	    if ((long) (int) slotid != slotid) {
+		retval = EINVAL;
+		goto cleanup;
+	    }
+	    idopts->slotid = slotid;
+	} else if (!strcmp(cp, "token")) {
+	    if (idopts->token_label != NULL)
+		free(idopts->token_label);
+	    idopts->token_label = strdup(vp);
+	    if (idopts->token_label == NULL)
+		goto cleanup;
+	} else if (!strcmp(cp, "certid")) {
+	    if (idopts->cert_id_string != NULL)
+		free(idopts->cert_id_string);
+	    idopts->cert_id_string = strdup(vp);
+	    if (idopts->cert_id_string == NULL)
+		goto cleanup;
+	} else if (!strcmp(cp, "certlabel")) {
+	    if (idopts->cert_label != NULL)
+		free(idopts->cert_label);
+	    idopts->cert_label = strdup(vp);
+	    if (idopts->cert_label == NULL)
+		goto cleanup;
+	}
+    }
+    retval = 0;
+cleanup:
+    free(s);
+    return retval;
+}
+#endif
+
+static krb5_error_code
+parse_fs_options(krb5_context context,
+		 pkinit_identity_opts *idopts,
+		 const char *residual)
+{
+    char *certname, *keyname;
+    krb5_error_code retval = ENOMEM;
+
+    if (residual == NULL || residual[0] == '\0')
+	return 0;
+
+    certname = strdup(residual);
+    if (certname == NULL)
+	goto cleanup;
+
+    certname = strtok(certname, ",");
+    keyname = strtok(NULL, ",");
+
+    idopts->cert_filename = strdup(certname);
+    if (idopts->cert_filename == NULL)
+	goto cleanup;
+
+    idopts->key_filename = strdup(keyname ? keyname : certname);
+    if (idopts->key_filename == NULL)
+	goto cleanup;
+
+    retval = 0;
+cleanup:
+    if (certname != NULL)
+	free(certname);
+    return retval;
+}
+
+static krb5_error_code
+parse_pkcs12_options(krb5_context context,
+		     pkinit_identity_opts *idopts,
+		     const char *residual)
+{
+    krb5_error_code retval = ENOMEM;
+
+    if (residual == NULL || residual[0] == '\0')
+	return 0;
+
+    idopts->cert_filename = strdup(residual);
+    if (idopts->cert_filename == NULL)
+	goto cleanup;
+
+    idopts->key_filename = strdup(residual);
+    if (idopts->key_filename == NULL)
+	goto cleanup;
+
+    pkiDebug("%s: cert_filename '%s' key_filename '%s'\n",
+	     __FUNCTION__, idopts->cert_filename,
+	     idopts->key_filename);
+    retval = 0;
+cleanup:
+    return retval;
+}
+
+static krb5_error_code
+process_option_identity(krb5_context context,
+			pkinit_plg_crypto_context plg_cryptoctx,
+			pkinit_req_crypto_context req_cryptoctx,
+			pkinit_identity_opts *idopts,
+			pkinit_identity_crypto_context id_cryptoctx,
+			const char *value)
+{
+    const char *residual;
+    int idtype;
+    krb5_error_code retval = 0;
+
+    pkiDebug("%s: processing value '%s'\n",
+	     __FUNCTION__, value ? value : "NULL");
+    if (value == NULL)
+	return EINVAL;
+
+    residual = strchr(value, ':');
+    if (residual != NULL) {
+	unsigned int typelen;
+	residual++; /* skip past colon */
+	typelen = residual - value;
+	if (strncmp(value, "FILE:", typelen) == 0) {
+	    idtype = IDTYPE_FILE;
+#ifndef WITHOUT_PKCS11
+	} else if (strncmp(value, "PKCS11:", typelen) == 0) {
+	    idtype = IDTYPE_PKCS11;
+#endif
+	} else if (strncmp(value, "PKCS12:", typelen) == 0) {
+	    idtype = IDTYPE_PKCS12;
+	} else if (strncmp(value, "DIR:", typelen) == 0) {
+	    idtype = IDTYPE_DIR;
+	} else if (strncmp(value, "ENV:", typelen) == 0) {
+	    idtype = IDTYPE_ENVVAR;
+	} else {
+	    pkiDebug("%s: Unsupported type while processing '%s'\n",
+		     __FUNCTION__, value);
+	    krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
+				   "Unsupported type while processing '%s'\n",
+				   value);
+	    return KRB5_PREAUTH_FAILED;
+	}
+    } else {
+	idtype = IDTYPE_FILE;
+	residual = value;
+    }
+
+    idopts->idtype = idtype;
+    pkiDebug("%s: idtype is %s\n", __FUNCTION__, idtype2string(idopts->idtype));
+    switch (idtype) {
+    case IDTYPE_ENVVAR:
+	return process_option_identity(context, plg_cryptoctx, req_cryptoctx,
+				       idopts, id_cryptoctx, getenv(residual));
+	break;
+    case IDTYPE_FILE:
+	retval = parse_fs_options(context, idopts, residual);
+	break;
+    case IDTYPE_PKCS12:
+	retval = parse_pkcs12_options(context, idopts, residual);
+	break;
+#ifndef WITHOUT_PKCS11
+    case IDTYPE_PKCS11:
+	retval = parse_pkcs11_options(context, idopts, residual);
+	break;
+#endif
+    case IDTYPE_DIR:
+	idopts->cert_filename = strdup(residual);
+	if (idopts->cert_filename == NULL)
+	    retval = ENOMEM;
+	break;
+    default:
+	krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
+			       "Internal error parsing X509_user_identity\n");
+	retval = EINVAL;
+	break;
+    }
+    return retval;
+}
+
+static krb5_error_code
+process_option_ca_crl(krb5_context context,
+		      pkinit_plg_crypto_context plg_cryptoctx,
+		      pkinit_req_crypto_context req_cryptoctx,
+		      pkinit_identity_opts *idopts, 
+		      pkinit_identity_crypto_context id_cryptoctx,
+		      const char *value,
+		      int catype)
+{
+    char *residual;
+    unsigned int typelen;
+    int idtype;
+
+    pkiDebug("%s: processing catype %s, value '%s'\n",
+	     __FUNCTION__, catype2string(catype), value);
+    residual = strchr(value, ':');
+    if (residual == NULL) {
+	pkiDebug("No type given for '%s'\n", value);
+	return EINVAL;
+    }
+    residual++; /* skip past colon */
+    typelen = residual - value;
+    if (strncmp(value, "FILE:", typelen) == 0) {
+	idtype = IDTYPE_FILE;
+    } else if (strncmp(value, "DIR:", typelen) == 0) {
+	idtype = IDTYPE_DIR;
+    } else {
+	return ENOTSUP;
+    }
+    return crypto_load_cas_and_crls(context,
+				    plg_cryptoctx,
+				    req_cryptoctx,
+				    idopts, id_cryptoctx,
+				    idtype, catype, residual);
+}
+
+static krb5_error_code
+pkinit_identity_process_option(krb5_context context,
+			       pkinit_plg_crypto_context plg_cryptoctx,
+			       pkinit_req_crypto_context req_cryptoctx,
+			       pkinit_identity_opts *idopts,
+			       pkinit_identity_crypto_context id_cryptoctx,
+			       int attr,
+			       const char *value)
+{
+    krb5_error_code retval = 0;
+
+    switch (attr) {
+	case PKINIT_ID_OPT_USER_IDENTITY:
+	    retval = process_option_identity(context, plg_cryptoctx,
+					     req_cryptoctx, idopts,
+					     id_cryptoctx, value);
+	    break;
+	case PKINIT_ID_OPT_ANCHOR_CAS:
+	    retval = process_option_ca_crl(context, plg_cryptoctx,
+					   req_cryptoctx, idopts,
+					   id_cryptoctx, value,
+					   CATYPE_ANCHORS);
+	    break;
+	case PKINIT_ID_OPT_INTERMEDIATE_CAS:
+	    retval = process_option_ca_crl(context, plg_cryptoctx,
+					   req_cryptoctx, idopts,
+					   id_cryptoctx,
+					   value, CATYPE_INTERMEDIATES);
+	    break;
+	case PKINIT_ID_OPT_CRLS:
+	    retval = process_option_ca_crl(context, plg_cryptoctx,
+					   req_cryptoctx, idopts,
+					   id_cryptoctx,
+					   value, CATYPE_CRLS);
+	    break;
+	case PKINIT_ID_OPT_OCSP:
+	    retval = ENOTSUP;
+	    break;
+	default:
+	    retval = EINVAL;
+	    break;
+    }
+    return retval;
+}
+
+krb5_error_code
+pkinit_identity_initialize(krb5_context context,
+			   pkinit_plg_crypto_context plg_cryptoctx,
+			   pkinit_req_crypto_context req_cryptoctx,
+			   pkinit_identity_opts *idopts,
+			   pkinit_identity_crypto_context id_cryptoctx,
+			   int do_matching,
+			   krb5_principal princ)
+{
+    krb5_error_code retval = EINVAL;
+    int i;
+
+    pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx);
+    if (idopts == NULL || id_cryptoctx == NULL)
+	goto errout;
+
+    /*
+     * If identity was specified, use that.  (For the kdc, this
+     * is specified as pkinit_identity in the kdc.conf.  For users,
+     * this is specified on the command line via X509_user_identity.)
+     * If a user did not specify identity on the command line,
+     * then we will try alternatives which may have been specified
+     * in the config file.
+     */
+    if (idopts->identity != NULL) {
+	retval = pkinit_identity_process_option(context, plg_cryptoctx,
+						req_cryptoctx, idopts,
+						id_cryptoctx,
+						PKINIT_ID_OPT_USER_IDENTITY,
+						idopts->identity);
+    } else if (idopts->identity_alt != NULL) {
+	for (i = 0; retval != 0 && idopts->identity_alt[i] != NULL; i++)
+		retval = pkinit_identity_process_option(context, plg_cryptoctx,
+						    req_cryptoctx, idopts,
+						    id_cryptoctx,
+						    PKINIT_ID_OPT_USER_IDENTITY,
+						    idopts->identity_alt[i]);
+    } else {
+	pkiDebug("%s: no user identity options specified\n", __FUNCTION__);
+	goto errout;
+    }
+    if (retval)
+	goto errout;
+
+    retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx,
+			       idopts, id_cryptoctx, princ);
+    if (retval)
+	goto errout;
+
+    if (do_matching) {
+	retval = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx,
+				      id_cryptoctx, princ);
+	if (retval) {
+	    pkiDebug("%s: No matching certificate found\n", __FUNCTION__);
+	    crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+				  id_cryptoctx);
+	    goto errout;
+	}
+    } else {
+	/* Tell crypto code to use the "default" */
+	retval = crypto_cert_select_default(context, plg_cryptoctx,
+					    req_cryptoctx, id_cryptoctx);
+	if (retval) {
+	    pkiDebug("%s: Failed while selecting default certificate\n",
+		     __FUNCTION__);
+	    crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+				  id_cryptoctx);
+	    goto errout;
+	}
+    }
+    
+    retval = crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+				   id_cryptoctx);
+    if (retval)
+	    goto errout;
+
+    for (i = 0; idopts->anchors != NULL && idopts->anchors[i] != NULL; i++) {
+	retval = pkinit_identity_process_option(context, plg_cryptoctx,
+						req_cryptoctx, idopts,
+						id_cryptoctx,
+						PKINIT_ID_OPT_ANCHOR_CAS,
+						idopts->anchors[i]);
+	if (retval)
+	    goto errout;
+    }
+    for (i = 0; idopts->intermediates != NULL
+		&& idopts->intermediates[i] != NULL; i++) {
+	retval = pkinit_identity_process_option(context, plg_cryptoctx,
+						req_cryptoctx, idopts,
+						id_cryptoctx,
+						PKINIT_ID_OPT_INTERMEDIATE_CAS,
+						idopts->intermediates[i]);
+	if (retval)
+	    goto errout;
+    }
+    for (i = 0; idopts->crls != NULL && idopts->crls[i] != NULL; i++) {
+	retval = pkinit_identity_process_option(context, plg_cryptoctx,
+						req_cryptoctx, idopts,
+						id_cryptoctx,
+						PKINIT_ID_OPT_CRLS,
+						idopts->crls[i]);
+	if (retval)
+	    goto errout;
+    }
+    if (idopts->ocsp != NULL) {
+	retval = pkinit_identity_process_option(context, plg_cryptoctx,
+						req_cryptoctx, idopts,
+						id_cryptoctx,
+						PKINIT_ID_OPT_OCSP,
+						idopts->ocsp);
+	if (retval)
+	    goto errout;
+    }
+
+errout:
+    return retval;
+}
+
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_lib.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_lib.c
new file mode 100644
index 000000000..f49ef5ebf
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_lib.c
@@ -0,0 +1,477 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "pkinit.h"
+
+#define FAKECERT
+
+const krb5_octet_data
+	dh_oid = { 0, 7, (unsigned char *)"\x2A\x86\x48\xce\x3e\x02\x01" };
+
+
+krb5_error_code
+pkinit_init_req_opts(pkinit_req_opts **reqopts)
+{
+    krb5_error_code retval = ENOMEM;
+    pkinit_req_opts *opts = NULL;
+
+    *reqopts = NULL;
+    opts = (pkinit_req_opts *) calloc(1, sizeof(pkinit_req_opts));
+    if (opts == NULL)
+	return retval;
+
+    opts->require_eku = 1;
+    opts->accept_secondary_eku = 0;
+    opts->allow_upn = 0;
+    opts->dh_or_rsa = DH_PROTOCOL;
+    opts->require_crl_checking = 0;
+    opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS;
+    opts->win2k_target = 0;
+    opts->win2k_require_cksum = 0;
+
+    *reqopts = opts;
+
+    return 0;
+}
+
+void
+pkinit_fini_req_opts(pkinit_req_opts *opts)
+{
+    if (opts != NULL)
+	free(opts);
+    return;
+}
+
+krb5_error_code
+pkinit_init_plg_opts(pkinit_plg_opts **plgopts)
+{
+    krb5_error_code retval = ENOMEM;
+    pkinit_plg_opts *opts = NULL;
+
+    *plgopts = NULL;
+    opts = (pkinit_plg_opts *) calloc(1, sizeof(pkinit_plg_opts));
+    if (opts == NULL)
+	return retval;
+
+    opts->require_eku = 1;
+    opts->accept_secondary_eku = 0;
+    opts->dh_or_rsa = DH_PROTOCOL;
+    opts->allow_upn = 0;
+    opts->require_crl_checking = 0;
+
+    opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS;
+
+    *plgopts = opts;
+
+    return 0;
+}
+
+void
+pkinit_fini_plg_opts(pkinit_plg_opts *opts)
+{
+    if (opts != NULL)
+	free(opts);
+    return;
+}
+
+void
+free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
+{
+    if (*in == NULL) return;
+    if ((*in)->signedAuthPack.data != NULL)
+	free((*in)->signedAuthPack.data);
+    if ((*in)->trustedCertifiers != NULL)
+	free_krb5_external_principal_identifier(&(*in)->trustedCertifiers);
+    if ((*in)->kdcPkId.data != NULL)
+	free((*in)->kdcPkId.data);
+    free(*in);
+}
+
+void
+free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in)
+{
+    if (*in == NULL) return;
+    if ((*in)->signedAuthPack.data != NULL)
+	free((*in)->signedAuthPack.data);
+    if ((*in)->kdcCert.data != NULL)
+	free((*in)->kdcCert.data);
+    if ((*in)->encryptionCert.data != NULL)
+	free((*in)->encryptionCert.data);
+    if ((*in)->trustedCertifiers != NULL)
+	free_krb5_trusted_ca(&(*in)->trustedCertifiers);
+    free(*in);
+}
+
+void
+free_krb5_reply_key_pack(krb5_reply_key_pack **in)
+{
+    if (*in == NULL) return;
+    if ((*in)->replyKey.contents != NULL)
+	free((*in)->replyKey.contents);
+    if ((*in)->asChecksum.contents != NULL)
+	free((*in)->asChecksum.contents);
+    free(*in);
+}
+
+void
+free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in)
+{
+    if (*in == NULL) return;
+    if ((*in)->replyKey.contents != NULL)
+	free((*in)->replyKey.contents);
+    free(*in);
+}
+
+void
+free_krb5_auth_pack(krb5_auth_pack **in)
+{
+    if ((*in) == NULL) return;
+    if ((*in)->clientPublicValue != NULL) {
+	if ((*in)->clientPublicValue->algorithm.algorithm.data != NULL)
+	    free((*in)->clientPublicValue->algorithm.algorithm.data);
+	if ((*in)->clientPublicValue->algorithm.parameters.data != NULL)
+	    free((*in)->clientPublicValue->algorithm.parameters.data);
+	if ((*in)->clientPublicValue->subjectPublicKey.data != NULL)
+	    free((*in)->clientPublicValue->subjectPublicKey.data);
+	free((*in)->clientPublicValue);
+    }
+    if ((*in)->pkAuthenticator.paChecksum.contents != NULL)
+	free((*in)->pkAuthenticator.paChecksum.contents);
+    if ((*in)->supportedCMSTypes != NULL)
+	free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes));
+    free(*in);
+}
+
+void
+free_krb5_auth_pack_draft9(krb5_context context,
+				krb5_auth_pack_draft9 **in)
+{
+    if ((*in) == NULL) return;
+    krb5_free_principal(context, (*in)->pkAuthenticator.kdcName);
+    free(*in);
+}
+
+void
+free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in)
+{
+    if (*in == NULL) return;
+    switch ((*in)->choice) {
+	case choice_pa_pk_as_rep_dhInfo:
+	    if ((*in)->u.dh_Info.dhSignedData.data != NULL)
+		free((*in)->u.dh_Info.dhSignedData.data);
+	    break;
+	case choice_pa_pk_as_rep_encKeyPack:
+	    if ((*in)->u.encKeyPack.data != NULL)
+		free((*in)->u.encKeyPack.data);
+	    break;
+	default:
+	    break;
+    }
+    free(*in);
+}
+
+void
+free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in)
+{
+    if (*in == NULL) return;
+    if ((*in)->u.encKeyPack.data != NULL)
+	free((*in)->u.encKeyPack.data);
+    free(*in);
+}
+
+void
+free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in)
+{
+    int i = 0;
+    if (*in == NULL) return;
+    while ((*in)[i] != NULL) {
+	if ((*in)[i]->subjectName.data != NULL)
+	    free((*in)[i]->subjectName.data);
+	if ((*in)[i]->issuerAndSerialNumber.data != NULL)
+	    free((*in)[i]->issuerAndSerialNumber.data);
+	if ((*in)[i]->subjectKeyIdentifier.data != NULL)
+	    free((*in)[i]->subjectKeyIdentifier.data);
+	free((*in)[i]);
+	i++;
+    }
+    free(*in);
+}
+
+void
+free_krb5_trusted_ca(krb5_trusted_ca ***in)
+{
+    int i = 0;
+    if (*in == NULL) return;
+    while ((*in)[i] != NULL) {
+	switch((*in)[i]->choice) {
+	    case choice_trusted_cas_principalName:
+		break;
+	    case choice_trusted_cas_caName:
+		if ((*in)[i]->u.caName.data != NULL)
+		    free((*in)[i]->u.caName.data);
+		break;
+	    case choice_trusted_cas_issuerAndSerial:
+		if ((*in)[i]->u.issuerAndSerial.data != NULL)
+		    free((*in)[i]->u.issuerAndSerial.data);
+		break;
+	    case choice_trusted_cas_UNKNOWN:
+		break;
+	}
+	free((*in)[i]);
+	i++;
+    }
+    free(*in);
+}
+
+void
+free_krb5_typed_data(krb5_typed_data ***in)
+{
+    int i = 0;
+    if (*in == NULL) return;
+    while ((*in)[i] != NULL) {
+	if ((*in)[i]->data != NULL)
+	    free((*in)[i]->data);
+	free((*in)[i]);
+	i++;
+    }
+    free(*in);
+}
+
+void
+free_krb5_algorithm_identifier(krb5_algorithm_identifier *in)
+{
+    if (in == NULL)
+	return;
+    if (in->algorithm.data != NULL)
+	free(in->algorithm.data);
+    if (in->parameters.data != NULL)
+	free(in->parameters.data);
+    free(in);
+}
+
+void
+free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in)
+{
+    int i;
+    if (in == NULL || *in == NULL)
+	return;
+    for (i = 0; (*in)[i] != NULL; i++) {
+	free_krb5_algorithm_identifier((*in)[i]);
+    }
+    free(*in);
+}
+
+void
+free_krb5_subject_pk_info(krb5_subject_pk_info **in)
+{
+    if ((*in) == NULL) return;
+    if ((*in)->algorithm.parameters.data != NULL)
+	free((*in)->algorithm.parameters.data);
+    if ((*in)->subjectPublicKey.data != NULL)
+	free((*in)->subjectPublicKey.data);
+    free(*in);
+}
+
+void
+free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in)
+{
+    if (*in == NULL) return;
+    if ((*in)->subjectPublicKey.data != NULL)
+	free((*in)->subjectPublicKey.data);
+    free(*in);
+}
+
+void
+init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
+{
+    (*in) = malloc(sizeof(krb5_pa_pk_as_req));
+    if ((*in) == NULL) return;
+    (*in)->signedAuthPack.data = NULL;
+    (*in)->signedAuthPack.length = 0;
+    (*in)->trustedCertifiers = NULL;
+    (*in)->kdcPkId.data = NULL;
+    (*in)->kdcPkId.length = 0;
+}
+
+void
+init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in)
+{
+    (*in) = malloc(sizeof(krb5_pa_pk_as_req_draft9));
+    if ((*in) == NULL) return;
+    (*in)->signedAuthPack.data = NULL;
+    (*in)->signedAuthPack.length = 0;
+    (*in)->trustedCertifiers = NULL;
+    (*in)->kdcCert.data = NULL;
+    (*in)->kdcCert.length = 0;
+    (*in)->encryptionCert.data = NULL;
+    (*in)->encryptionCert.length = 0;
+}
+
+void
+init_krb5_reply_key_pack(krb5_reply_key_pack **in)
+{
+    (*in) = malloc(sizeof(krb5_reply_key_pack));
+    if ((*in) == NULL) return;
+    (*in)->replyKey.contents = NULL;
+    (*in)->replyKey.length = 0;
+    (*in)->asChecksum.contents = NULL;
+    (*in)->asChecksum.length = 0;
+}
+
+void
+init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in)
+{
+    (*in) = malloc(sizeof(krb5_reply_key_pack_draft9));
+    if ((*in) == NULL) return;
+    (*in)->replyKey.contents = NULL;
+    (*in)->replyKey.length = 0;
+}
+
+void
+init_krb5_auth_pack(krb5_auth_pack **in)
+{
+    (*in) = malloc(sizeof(krb5_auth_pack));
+    if ((*in) == NULL) return;
+    (*in)->clientPublicValue = NULL;
+    (*in)->supportedCMSTypes = NULL;
+    (*in)->clientDHNonce.length = 0;
+    (*in)->clientDHNonce.data = NULL;
+    (*in)->pkAuthenticator.paChecksum.contents = NULL;
+}
+
+void
+init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in)
+{
+    (*in) = malloc(sizeof(krb5_auth_pack_draft9));
+    if ((*in) == NULL) return;
+    (*in)->clientPublicValue = NULL;
+}
+
+void
+init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in)
+{
+    (*in) = malloc(sizeof(krb5_pa_pk_as_rep));
+    if ((*in) == NULL) return;
+    (*in)->u.dh_Info.serverDHNonce.length = 0;
+    (*in)->u.dh_Info.serverDHNonce.data = NULL;
+    (*in)->u.dh_Info.dhSignedData.length = 0;
+    (*in)->u.dh_Info.dhSignedData.data = NULL;
+    (*in)->u.encKeyPack.length = 0;
+    (*in)->u.encKeyPack.data = NULL;
+}
+
+void
+init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in)
+{
+    (*in) = malloc(sizeof(krb5_pa_pk_as_rep_draft9));
+    if ((*in) == NULL) return;
+    (*in)->u.dhSignedData.length = 0;
+    (*in)->u.dhSignedData.data = NULL;
+    (*in)->u.encKeyPack.length = 0;
+    (*in)->u.encKeyPack.data = NULL;
+}
+
+void
+init_krb5_typed_data(krb5_typed_data **in)
+{
+    (*in) = malloc(sizeof(krb5_typed_data));
+    if ((*in) == NULL) return;
+    (*in)->type = 0;
+    (*in)->length = 0;
+    (*in)->data = NULL;
+}
+
+void
+init_krb5_subject_pk_info(krb5_subject_pk_info **in)
+{
+    (*in) = malloc(sizeof(krb5_subject_pk_info));
+    if ((*in) == NULL) return;
+    (*in)->algorithm.parameters.data = NULL;
+    (*in)->algorithm.parameters.length = 0;
+    (*in)->subjectPublicKey.data = NULL;
+    (*in)->subjectPublicKey.length = 0;
+}
+
+krb5_error_code
+pkinit_copy_krb5_octet_data(krb5_octet_data *dst, const krb5_octet_data *src)
+{
+    if (dst == NULL || src == NULL)
+	return EINVAL;
+    if (src->data == NULL) {
+	dst->data = NULL;
+	dst->length = 0;
+	return 0;
+    }
+    dst->data = malloc(src->length);
+    if (dst->data == NULL)
+	return ENOMEM;
+    memcpy(dst->data, src->data, src->length);
+    dst->length = src->length;
+    return 0;
+}
+
+/* debugging functions */
+void
+print_buffer(unsigned char *buf, unsigned int len)
+{
+    int i = 0;
+    if (len <= 0)
+	return;
+
+    for (i = 0; i < len; i++)
+	pkiDebug("%02x ", buf[i]);
+    pkiDebug("\n");
+}
+
+void
+print_buffer_bin(unsigned char *buf, unsigned int len, char *filename)
+{
+    FILE *f = NULL;
+    int i = 0;
+
+    if (len <= 0 || filename == NULL)
+	return;
+
+    if ((f = fopen(filename, "w")) == NULL)
+	return;
+
+    for (i = 0; i < len; i++)
+	fputc(buf[i], f);
+
+    fclose(f);
+}
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_matching.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_matching.c
new file mode 100644
index 000000000..b790c38f7
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_matching.c
@@ -0,0 +1,830 @@
+/*
+ * COPYRIGHT (C) 2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <regex.h>
+#include <krb5.h>
+#include "pkinit.h"
+
+typedef struct _pkinit_cert_info pkinit_cert_info;
+
+typedef enum {
+    kw_undefined = 0,
+    kw_subject = 1,
+    kw_issuer = 2,
+    kw_san = 3,
+    kw_eku = 4,
+    kw_ku = 5
+} keyword_type;
+
+static char *
+keyword2string(unsigned int kw)
+{
+    switch(kw) {
+    case kw_undefined: return "NONE"; break;
+    case kw_subject: return "SUBJECT"; break;
+    case kw_issuer: return "ISSUER"; break;
+    case kw_san: return "SAN"; break;
+    case kw_eku: return "EKU"; break;
+    case kw_ku: return "KU"; break;
+    default: return "INVALID"; break;
+    }
+}
+typedef enum {
+    relation_none = 0,
+    relation_and = 1,
+    relation_or = 2
+} relation_type;
+
+static char *
+relation2string(unsigned int rel)
+{
+    switch(rel) {
+    case relation_none: return "NONE"; break;
+    case relation_and: return "AND"; break;
+    case relation_or: return "OR"; break;
+    default: return "INVALID"; break;
+    }
+}
+
+typedef enum {
+    kwvaltype_undefined = 0,
+    kwvaltype_regexp = 1,
+    kwvaltype_list = 2
+} kw_value_type;
+
+static char *
+kwval2string(unsigned int kwval)
+{
+    switch(kwval) {
+    case kwvaltype_undefined: return "NONE"; break;
+    case kwvaltype_regexp: return "REGEXP"; break;
+    case kwvaltype_list: return "LIST"; break;
+    default: return "INVALID"; break;
+    }
+}
+
+struct keyword_desc {
+    const char *value;
+    size_t length;
+    keyword_type kwtype;
+    kw_value_type kwvaltype;
+} matching_keywords[] = {
+    { "<KU>",	    4, kw_ku, kwvaltype_list },
+    { "<EKU>",	    5, kw_eku, kwvaltype_list },
+    { "<SAN>",	    5, kw_san, kwvaltype_regexp },
+    { "<ISSUER>",   8, kw_issuer, kwvaltype_regexp },
+    { "<SUBJECT>",  9, kw_subject, kwvaltype_regexp },
+    { NULL, 0, kw_undefined, kwvaltype_undefined},
+};
+
+struct ku_desc {
+    const char *value;
+    size_t length;
+    unsigned int bitval;
+};
+
+struct ku_desc ku_keywords[] = {
+    { "digitalSignature",   16, PKINIT_KU_DIGITALSIGNATURE },
+    { "keyEncipherment",    15, PKINIT_KU_KEYENCIPHERMENT },
+    { NULL, 0, 0 },
+};
+
+struct ku_desc  eku_keywords[] = {
+    { "pkinit",		    6,  PKINIT_EKU_PKINIT },
+    { "msScLogin",	    9,  PKINIT_EKU_MSSCLOGIN },
+    { "clientAuth",	    10, PKINIT_EKU_CLIENTAUTH },
+    { "emailProtection",    15, PKINIT_EKU_EMAILPROTECTION },
+    { NULL, 0, 0 },
+};
+
+/* Rule component */
+typedef struct _rule_component {
+    struct _rule_component *next;
+    keyword_type kw_type;
+    kw_value_type kwval_type;
+    regex_t regexp;	    /* Compiled regular expression */
+    char *regsrc;	    /* The regular expression source (for debugging) */
+    unsigned int ku_bits;   
+    unsigned int eku_bits;
+} rule_component;
+ 
+/* Set rule components */
+typedef struct _rule_set {
+    relation_type relation;
+    int num_crs;
+    rule_component *crs;
+} rule_set;
+
+static krb5_error_code
+free_rule_component(krb5_context context,
+		    rule_component *rc)
+{
+    if (rc == NULL)
+	return 0;
+
+    if (rc->kwval_type == kwvaltype_regexp) {
+	if (rc->regsrc)
+	    free(rc->regsrc);
+	regfree(&rc->regexp);
+    }
+    free(rc);
+    return 0;
+}
+
+static krb5_error_code
+free_rule_set(krb5_context context,
+	      rule_set *rs)
+{
+    rule_component *rc, *trc;
+
+    if (rs == NULL)
+	return 0;
+    for (rc = rs->crs; rc != NULL;) {
+	trc = rc->next;
+	free_rule_component(context, rc);
+	rc = trc;
+    }
+    free(rs);
+    return 0;
+}
+
+static krb5_error_code
+parse_list_value(krb5_context context,
+		 keyword_type type, 
+		 char *value,
+		 rule_component *rc)
+{
+    krb5_error_code retval;
+    char *comma;
+    struct ku_desc *ku = NULL;
+    int found;
+    size_t len;
+    unsigned int *bitptr;
+
+
+    if (value == NULL || value[0] == '\0') {
+	pkiDebug("%s: Missing or empty value for list keyword type %d\n",
+		 __FUNCTION__, type);
+	retval = EINVAL;
+	goto out;
+    }
+
+    if (type == kw_eku) {
+	bitptr = &rc->eku_bits;
+    } else if (type == kw_ku) {
+	bitptr = &rc->ku_bits;
+    } else {
+	pkiDebug("%s: Unknown list keyword type %d\n", __FUNCTION__, type);
+	retval = EINVAL;
+	goto out;
+    }
+
+    do {
+	found = 0;
+	comma = strchr(value, ',');
+	if (comma != NULL)
+	    len = comma - value;
+	else
+	    len = strlen(value);
+
+	if (type == kw_eku) {
+	    ku = eku_keywords;
+	} else if (type == kw_ku) {
+	    ku = ku_keywords;
+	}
+
+	for (; ku->value != NULL; ku++) {
+	    if (strncasecmp(value, ku->value, len) == 0) {
+		*bitptr |= ku->bitval;
+		found = 1;
+		pkiDebug("%s: Found value '%s', bitfield is now 0x%x\n",
+			 __FUNCTION__, ku->value, *bitptr);
+		break;
+	    }
+	}
+	if (found) {
+	    value += ku->length;
+	    if (*value == ',')
+		value += 1;
+	} else {
+	    pkiDebug("%s: Urecognized value '%s'\n", __FUNCTION__, value);
+	    retval = EINVAL;
+	    goto out;
+	}
+    } while (found && *value != '\0');
+
+    retval = 0;
+out:
+    pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
+    return retval;
+}
+
+static krb5_error_code
+parse_rule_component(krb5_context context,
+		     const char **rule,
+		     int *remaining,
+		     rule_component **ret_rule)
+{
+    krb5_error_code retval;
+    rule_component *rc = NULL;
+    keyword_type kw_type;
+    kw_value_type kwval_type;
+    char err_buf[128];
+    int ret;
+    struct keyword_desc *kw, *nextkw;
+    char *nk;
+    int found_next_kw = 0;
+    char *value = NULL;
+    size_t len;
+
+    for (kw = matching_keywords; kw->value != NULL; kw++) {
+	if (strncmp(*rule, kw->value, kw->length) == 0) {
+	    kw_type = kw->kwtype;
+	    kwval_type = kw->kwvaltype;
+	    *rule += kw->length;
+	    *remaining -= kw->length;
+	    break;
+	}
+    }
+    if (kw->value == NULL) {
+	pkiDebug("%s: Missing or invalid keyword in rule '%s'\n",
+		 __FUNCTION__, *rule);
+	retval = ENOENT;
+	goto out;
+    }
+
+    pkiDebug("%s: found keyword '%s'\n", __FUNCTION__, kw->value);
+
+    rc = calloc(1, sizeof(*rc));
+    if (rc == NULL) {
+	retval = ENOMEM;
+	goto out;
+    }
+    rc->next = NULL;
+    rc->kw_type = kw_type;
+    rc->kwval_type = kwval_type;
+
+    /*
+     * Before procesing the value for this keyword,
+     * (compiling the regular expression or processing the list)
+     * we need to find the end of it.  That means parsing for the
+     * beginning of the next keyword (or the end of the rule).
+     */
+    nk = strchr(*rule, '<');
+    while (nk != NULL) {
+	/* Possibly another keyword, check it out */
+	for (nextkw = matching_keywords; nextkw->value != NULL; nextkw++) {
+	    if (strncmp(nk, nextkw->value, nextkw->length) == 0) {
+		/* Found a keyword, nk points to the beginning */
+		found_next_kw = 1;
+		break;	/* Need to break out of the while! */
+	    }
+	}
+	if (!found_next_kw)
+	    nk = strchr(nk+1, '<');	/* keep looking */
+	else
+	    break;
+    }
+
+    if (nk != NULL && found_next_kw)
+	len = (nk - *rule);
+    else
+	len = (*remaining);
+
+    if (len == 0) {
+	pkiDebug("%s: Missing value for keyword '%s'\n",
+		 __FUNCTION__, kw->value);
+	retval = EINVAL;
+	goto out;
+    }
+
+    value = calloc(1, len+1);
+    if (value == NULL) {
+	retval = ENOMEM;
+	goto out;
+    }
+    memcpy(value, *rule, len);
+    *remaining -= len;
+    *rule += len;
+    pkiDebug("%s: found value '%s'\n", __FUNCTION__, value);
+
+    if (kw->kwvaltype == kwvaltype_regexp) {
+	ret = regcomp(&rc->regexp, value, REG_EXTENDED);
+	if (ret) {
+	    regerror(ret, &rc->regexp, err_buf, sizeof(err_buf));
+	    pkiDebug("%s: Error compiling reg-exp '%s': %s\n",
+		     __FUNCTION__, value, err_buf);
+	    retval = ret;
+	    goto out;
+	}
+	rc->regsrc = strdup(value);
+	if (rc->regsrc == NULL) {
+	    retval = ENOMEM;
+	    goto out;
+	}
+    } else if (kw->kwvaltype == kwvaltype_list) {
+	retval = parse_list_value(context, rc->kw_type, value, rc);
+	if (retval) {
+	    pkiDebug("%s: Error %d, parsing list values for keyword %s\n",
+		     __FUNCTION__, retval, kw->value);
+	    goto out;
+	}
+    }
+
+    *ret_rule = rc;
+    retval = 0;
+out:
+    if (value != NULL)
+	free(value);
+    if (retval && rc != NULL)
+	free_rule_component(context, rc);
+    pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
+    return retval;
+}
+
+static krb5_error_code
+parse_rule_set(krb5_context context,
+	       const char *rule_in,
+	       rule_set **out_rs)
+{
+    const char *rule;
+    int remaining, totlen;
+    krb5_error_code ret, retval;
+    rule_component *rc = NULL, *trc;
+    rule_set *rs;
+
+
+    if (rule_in == NULL)
+	return EINVAL;
+    rule = rule_in;
+    totlen = remaining = strlen(rule);
+
+    rs = calloc(1, sizeof(*rs));
+    if (rs == NULL) {
+	retval = ENOMEM;
+	goto cleanup;
+    }
+
+    rs->relation = relation_none;
+    if (remaining > 1) {
+	if (rule[0] == '&' && rule[1] == '&') {
+	    rs->relation = relation_and;
+	    rule += 2;
+	    remaining -= 2;
+	} else if (rule_in[0] == '|' && rule_in[1] == '|') {
+	    rs->relation = relation_or;
+	    rule +=2;
+	    remaining -= 2;
+	}
+    }
+    rs->num_crs = 0;
+    while (remaining > 0) {
+	if (rs->relation == relation_none && rs->num_crs > 1) {
+	    pkiDebug("%s: Assuming AND relation for multiple components in rule '%s'\n",
+		     __FUNCTION__, rule_in);
+	    rs->relation = relation_and;
+	}
+	ret = parse_rule_component(context, &rule, &remaining, &rc);
+	if (ret) {
+	    retval = ret;
+	    goto cleanup;
+	}
+	pkiDebug("%s: After parse_rule_component, remaining %d, rule '%s'\n",
+		 __FUNCTION__, remaining, rule);
+	rs->num_crs++;
+
+	/*
+	 * Chain the new component on the end (order matters since
+	 * we can short-circuit an OR or an AND relation if an
+	 * earlier check passes
+	 */
+	for (trc = rs->crs; trc != NULL && trc->next != NULL; trc = trc->next);
+	if (trc == NULL)
+	    rs->crs = rc;
+	else {
+	    trc->next = rc;
+	}
+    }
+
+    *out_rs = rs;
+
+    retval = 0;
+cleanup:
+    if (retval && rs != NULL) {
+	free_rule_set(context, rs);
+    }
+    pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
+    return retval;
+}
+
+static int
+regexp_match(krb5_context context, rule_component *rc, char *value)
+{
+    int code;
+
+    pkiDebug("%s: checking %s rule '%s' with value '%s'\n",
+	     __FUNCTION__, keyword2string(rc->kw_type), rc->regsrc, value);
+
+    code = regexec(&rc->regexp, value, 0, NULL, 0);
+
+    pkiDebug("%s: the result is%s a match\n", __FUNCTION__,
+	     code == REG_NOMATCH ? " NOT" : "");
+
+    return (code == 0 ? 1: 0);
+}
+
+static int
+component_match(krb5_context context,
+		rule_component *rc,
+		pkinit_cert_matching_data *md)
+{
+    int match = 0;
+    int i;
+    krb5_principal p;
+    char *princ_string;
+
+    switch (rc->kwval_type) {
+    case kwvaltype_regexp:
+	switch (rc->kw_type) {
+	case kw_subject:
+	    match = regexp_match(context, rc, md->subject_dn);
+	    break;
+	case kw_issuer:
+	    match = regexp_match(context, rc, md->issuer_dn);
+	    break;
+	case kw_san:
+	    if (md->sans == NULL)
+		break;
+	    for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) {
+		krb5_unparse_name(context, p, &princ_string);
+		match = regexp_match(context, rc, princ_string);
+		krb5_free_unparsed_name(context, princ_string);
+		if (match)
+		    break;
+	    }
+	    break;
+	default:
+	    pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
+		     __FUNCTION__, keyword2string(rc->kw_type),
+		     kwval2string(kwvaltype_regexp));
+	    break;
+	}
+	break;
+    case kwvaltype_list:
+	switch(rc->kw_type) {
+	case kw_eku:
+	    pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
+		     __FUNCTION__, keyword2string(rc->kw_type),
+		     rc->eku_bits, md->eku_bits);
+	    if ((rc->eku_bits & md->eku_bits) == rc->eku_bits)
+		match = 1;
+	    break;
+	case kw_ku:
+	    pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
+		     __FUNCTION__, keyword2string(rc->kw_type),
+		     rc->ku_bits, md->ku_bits);
+	    if ((rc->ku_bits & md->ku_bits) == rc->ku_bits)
+		match = 1;
+	    break;
+	default:
+	    pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
+		     __FUNCTION__, keyword2string(rc->kw_type),
+		     kwval2string(kwvaltype_regexp));
+	    break;
+	}
+	break;
+    default:
+	pkiDebug("%s: unknown keyword value type %d\n",
+		 __FUNCTION__, rc->kwval_type);
+	break;
+    }
+    pkiDebug("%s: returning match = %d\n", __FUNCTION__, match);
+    return match;
+}
+/*
+ * Returns match_found == 1 only if exactly one certificate matches
+ * the given rule
+ */
+static krb5_error_code
+check_all_certs(krb5_context context,
+		pkinit_plg_crypto_context plg_cryptoctx,
+		pkinit_req_crypto_context req_cryptoctx,
+		pkinit_identity_crypto_context id_cryptoctx,
+		krb5_principal princ,
+		rule_set *rs,	/* rule to check */
+		pkinit_cert_matching_data **matchdata,
+		int *match_found,
+		pkinit_cert_matching_data **matching_cert)
+{
+    krb5_error_code retval;
+    pkinit_cert_matching_data *md;
+    int i;
+    int comp_match = 0;
+    int total_cert_matches = 0;
+    rule_component *rc;
+    int certs_checked = 0;
+    pkinit_cert_matching_data *save_match = NULL;
+
+    if (match_found == NULL || matching_cert == NULL)
+	return EINVAL;
+
+    *matching_cert = NULL;
+    *match_found = 0;
+
+    pkiDebug("%s: matching rule relation is %s with %d components\n",
+	     __FUNCTION__, relation2string(rs->relation), rs->num_crs);
+
+    /*
+     * Loop through all the certs available and count
+     * how many match the rule
+     */
+    for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) {
+	pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn);
+#if 0
+	pkiDebug("%s: issuer:  '%s'\n", __FUNCTION__, md->subject_dn);
+	for (j = 0, p = md->sans[j]; p != NULL; p = md->sans[++j]) {
+	    char *san_string;
+	    krb5_unparse_name(context, p, &san_string);
+	    pkiDebug("%s: san: '%s'\n", __FUNCTION__, san_string);
+	    krb5_free_unparsed_name(context, san_string);
+	}
+#endif
+	certs_checked++;
+	for (rc = rs->crs; rc != NULL; rc = rc->next) {
+	    comp_match = component_match(context, rc, md);
+	    if (comp_match) {
+		pkiDebug("%s: match for keyword type %s\n",
+			 __FUNCTION__, keyword2string(rc->kw_type));
+	    }
+	    if (comp_match && rs->relation == relation_or) {
+		pkiDebug("%s: cert matches rule (OR relation)\n",
+			 __FUNCTION__);
+		total_cert_matches++;
+		save_match = md;
+		goto nextcert;
+	    }
+	    if (!comp_match && rs->relation == relation_and) {
+		pkiDebug("%s: cert does not match rule (AND relation)\n",
+			 __FUNCTION__);
+		goto nextcert;
+	    }
+	}
+	if (rc == NULL && comp_match) {
+	    pkiDebug("%s: cert matches rule (AND relation)\n", __FUNCTION__);
+	    total_cert_matches++;
+	    save_match = md;
+	}
+nextcert:
+	continue;
+    }
+    pkiDebug("%s: After checking %d certs, we found %d matches\n",
+	     __FUNCTION__, certs_checked, total_cert_matches);
+    if (total_cert_matches == 1) {
+	*match_found = 1;	
+	*matching_cert = save_match;
+    }
+
+    retval = 0;
+
+    pkiDebug("%s: returning %d, match_found %d\n",
+	     __FUNCTION__, retval, *match_found);
+    return retval;
+}
+
+static krb5_error_code
+free_all_cert_matching_data(krb5_context context,
+			    pkinit_cert_matching_data **matchdata)
+{
+    krb5_error_code retval;
+    pkinit_cert_matching_data *md;
+    int i;
+
+    if (matchdata == NULL)
+	return EINVAL;
+
+    for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) {
+	pkinit_cert_handle ch = md->ch;
+	retval = crypto_cert_free_matching_data(context, md);
+	if (retval) {
+	    pkiDebug("%s: crypto_cert_free_matching_data error %d, %s\n",
+		     __FUNCTION__, retval, error_message(retval));
+	    goto cleanup;
+	}
+	retval = crypto_cert_release(context, ch);
+	if (retval) {
+	    pkiDebug("%s: crypto_cert_release error %d, %s\n",
+		     __FUNCTION__, retval, error_message(retval));
+	    goto cleanup;
+	}
+    }
+    free(matchdata);
+    retval = 0;
+
+cleanup:
+    return retval;
+}
+
+static krb5_error_code
+obtain_all_cert_matching_data(krb5_context context,
+			      pkinit_plg_crypto_context plg_cryptoctx,
+			      pkinit_req_crypto_context req_cryptoctx,
+			      pkinit_identity_crypto_context id_cryptoctx,
+			      pkinit_cert_matching_data ***all_matching_data)
+{
+    krb5_error_code retval;
+    int i, cert_count;
+    pkinit_cert_iter_handle ih = NULL;
+    pkinit_cert_handle ch;
+    pkinit_cert_matching_data **matchdata = NULL;
+
+    retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
+				   id_cryptoctx, &cert_count);
+    if (retval) {
+	pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
+		 __FUNCTION__, retval, error_message(retval));
+	goto cleanup;
+    }
+
+    pkiDebug("%s: crypto_cert_get_count says there are %d certs\n",
+	      __FUNCTION__, cert_count);
+
+    matchdata = calloc((size_t)cert_count + 1, sizeof(*matchdata));
+    if (matchdata == NULL)
+	return ENOMEM;
+
+    retval = crypto_cert_iteration_begin(context, plg_cryptoctx, req_cryptoctx,
+					 id_cryptoctx, &ih);
+    if (retval) {
+	pkiDebug("%s: crypto_cert_iteration_begin returned %d, %s\n",
+		 __FUNCTION__, retval, error_message(retval));
+	goto cleanup;
+    }
+
+    for (i = 0; i < cert_count; i++) {
+	retval = crypto_cert_iteration_next(context, ih, &ch);
+	if (retval) {
+	    if (retval == PKINIT_ITER_NO_MORE)
+		pkiDebug("%s: We thought there were %d certs, but "
+			 "crypto_cert_iteration_next stopped after %d?\n",
+			 __FUNCTION__, cert_count, i);
+	    else
+		pkiDebug("%s: crypto_cert_iteration_next error %d, %s\n",
+			 __FUNCTION__, retval, error_message(retval));
+	    goto cleanup;
+	}
+
+	retval = crypto_cert_get_matching_data(context, ch, &matchdata[i]);
+	if (retval) {
+	    pkiDebug("%s: crypto_cert_get_matching_data error %d, %s\n",
+		     __FUNCTION__, retval, error_message(retval));
+	    goto cleanup;
+	}
+
+    }
+
+    *all_matching_data = matchdata;
+    retval = 0;
+cleanup:
+    if (ih != NULL)
+	crypto_cert_iteration_end(context, ih);
+    if (retval) {
+	if (matchdata != NULL)
+	    free_all_cert_matching_data(context, matchdata);
+    }
+    pkiDebug("%s: returning %d, certinfo %p\n",
+	     __FUNCTION__, retval, *all_matching_data);
+    return retval;
+}
+
+krb5_error_code
+pkinit_cert_matching(krb5_context context,
+		     pkinit_plg_crypto_context plg_cryptoctx,
+		     pkinit_req_crypto_context req_cryptoctx,
+		     pkinit_identity_crypto_context id_cryptoctx,
+		     krb5_principal princ)
+{
+
+    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+    int x;
+    char **rules = NULL;
+    rule_set *rs = NULL;
+    int match_found = 0;
+    pkinit_cert_matching_data **matchdata = NULL;
+    pkinit_cert_matching_data *the_matching_cert = NULL;
+
+    /* If no matching rules, select the default cert and we're done */
+    pkinit_libdefault_strings(context, krb5_princ_realm(context, princ),
+			      "pkinit_cert_match", &rules);
+    if (rules == NULL) {
+	pkiDebug("%s: no matching rules found in config file\n", __FUNCTION__);
+	retval = crypto_cert_select_default(context, plg_cryptoctx,
+					    req_cryptoctx, id_cryptoctx);
+	goto cleanup;
+    }
+
+    /* parse each rule line one at a time and check all the certs against it */
+    for (x = 0; rules[x] != NULL; x++) {
+	pkiDebug("%s: Processing rule '%s'\n", __FUNCTION__, rules[x]);
+
+	/* Free rules from previous time through... */
+	if (rs != NULL) {
+	    free_rule_set(context, rs);
+	    rs = NULL;
+	}
+	retval = parse_rule_set(context, rules[x], &rs);
+	if (retval) {
+	    if (retval == EINVAL) {
+		pkiDebug("%s: Ignoring invalid rule pkinit_cert_match = '%s'\n",
+			 __FUNCTION__, rules[x]); 
+		continue;
+	    }
+	    goto cleanup;
+	}
+
+	/*
+	 * Optimize so that we do not get cert info unless we have
+	 * valid rules to check.  Once obtained, keep it around
+	 * until we are done.
+	 */
+	if (matchdata == NULL) {
+	    retval = obtain_all_cert_matching_data(context, plg_cryptoctx,
+						   req_cryptoctx, id_cryptoctx,
+						   &matchdata);
+	    if (retval || matchdata == NULL) {
+		pkiDebug("%s: Error %d obtaining certificate information\n",
+			 __FUNCTION__, retval);
+		retval = ENOENT;
+		goto cleanup;
+	    }
+	}
+
+	retval = check_all_certs(context, plg_cryptoctx, req_cryptoctx,
+				 id_cryptoctx, princ, rs, matchdata,
+				 &match_found, &the_matching_cert);
+	if (retval) {
+	    pkiDebug("%s: Error %d, checking certs against rule '%s'\n",
+		     __FUNCTION__, retval, rules[x]);
+	    goto cleanup;
+	}
+	if (match_found) {
+	    pkiDebug("%s: We have an exact match with rule '%s'\n",
+		     __FUNCTION__, rules[x]);
+	    break;
+	}
+    }
+
+    if (match_found && the_matching_cert != NULL) {
+	pkiDebug("%s: Selecting the matching cert!\n", __FUNCTION__);
+	retval = crypto_cert_select(context, the_matching_cert);
+	if (retval) {
+	    pkiDebug("%s: crypto_cert_select error %d, %s\n",
+		     __FUNCTION__, retval, error_message(retval));
+	    goto cleanup;
+	}
+    } else {
+	retval = ENOENT;    /* XXX */
+	goto cleanup;
+    }
+
+    retval = 0;
+cleanup:
+    if (rules != NULL)
+	profile_free_list(rules);
+    if (rs != NULL)
+	free_rule_set(context, rs);
+    if (matchdata != NULL)
+	free_all_cert_matching_data(context, matchdata);
+    return retval;
+}
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_profile.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_profile.c
new file mode 100644
index 000000000..403068a7d
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_profile.c
@@ -0,0 +1,376 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "k5-int.h"
+#include "pkinit.h"
+
+/*
+ * Routines for handling profile [config file] options
+ */
+
+/* Forward prototypes */
+static int _krb5_conf_boolean(const char *s);
+
+/*
+ * XXX
+ * The following is duplicated verbatim from src/lib/krb5/krb/get_in_tkt.c,
+ * which is duplicated from somewhere else. :-/
+ * XXX
+ */
+static const char *const conf_yes[] = {
+    "y", "yes", "true", "t", "1", "on",
+    0,
+};
+
+static const char *const conf_no[] = {
+    "n", "no", "false", "nil", "0", "off",
+    0,
+};
+
+static int
+_krb5_conf_boolean(const char *s)
+{
+    const char *const *p;
+
+    for(p=conf_yes; *p; p++) {
+	if (strcasecmp(*p,s) == 0)
+	    return 1;
+    }
+
+    for(p=conf_no; *p; p++) {
+	if (strcasecmp(*p,s) == 0)
+	    return 0;
+    }
+
+    /* Default to "no" */
+    return 0;
+}
+
+/*
+ * XXX
+ * End duplicated code from src/lib/krb5/krb/get_in_tkt.c
+ * XXX
+ */
+
+/*
+ * The following are based on krb5_libdefault_* functions in
+ * src/lib/krb5/krb/get_in_tkt.c
+ * N.B.  This assumes that context->default_realm has
+ * already been established.
+ */
+krb5_error_code
+pkinit_kdcdefault_strings(krb5_context context, const char *realmname,
+			  const char *option, char ***ret_value)
+{
+    profile_t profile = NULL;
+    const char *names[5];
+    char **values = NULL;
+    krb5_error_code retval;
+
+    if (context == NULL)
+	return KV5M_CONTEXT;
+
+    profile = context->profile;
+
+    if (realmname != NULL) {
+	/*
+	 * Try number one:
+	 *
+	 * [realms]
+	 *	    REALM = {
+	 *		option = <value>
+	 *	    }
+	 */
+
+	names[0] = "realms";
+	names[1] = realmname;
+	names[2] = option;
+	names[3] = 0;
+	retval = profile_get_values(profile, names, &values);
+	if (retval == 0 && values != NULL)
+	    goto goodbye;
+    }
+
+    /*
+     * Try number two:
+     *
+     * [kdcdefaults]
+     *	    option = <value>
+     */
+
+    names[0] = "kdcdefaults";
+    names[1] = option;
+    names[2] = 0;
+    retval = profile_get_values(profile, names, &values);
+    if (retval == 0 && values != NULL)
+	goto goodbye;
+
+goodbye:
+    if (values == NULL)
+	retval = ENOENT;
+
+    *ret_value = values;
+
+    return retval;
+
+}
+
+krb5_error_code
+pkinit_kdcdefault_string(krb5_context context, const char *realmname,
+			 const char *option, char **ret_value)
+{
+    krb5_error_code retval;
+    char **values = NULL;
+
+    retval = pkinit_kdcdefault_strings(context, realmname, option, &values);
+    if (retval)
+	return retval;
+
+    if (values[0] == NULL) {
+	retval = ENOENT;
+    } else {
+	*ret_value = malloc(strlen(values[0]) + 1);
+	if (*ret_value == NULL)
+	    retval = ENOMEM;
+	else
+	    strcpy(*ret_value, values[0]);
+    }
+
+    profile_free_list(values);
+    return retval;
+}
+
+krb5_error_code
+pkinit_kdcdefault_boolean(krb5_context context, const char *realmname,
+			  const char *option, int default_value, int *ret_value)
+{
+    char *string = NULL;
+    krb5_error_code retval;
+
+    retval = pkinit_kdcdefault_string(context, realmname, option, &string);
+
+    if (retval == 0) {
+	*ret_value = _krb5_conf_boolean(string);
+	free(string);
+    } else
+	*ret_value = default_value;
+
+    return 0;
+}
+
+krb5_error_code
+pkinit_kdcdefault_integer(krb5_context context, const char *realmname,
+			  const char *option, int default_value, int *ret_value)
+{
+    char *string = NULL;
+    krb5_error_code retval;
+
+    retval = pkinit_kdcdefault_string(context, realmname, option, &string);
+
+    if (retval == 0) {
+	char *endptr;
+	long l;
+	l = strtol(string, &endptr, 0);
+	if (endptr == string)
+	    *ret_value = default_value;
+	else
+	    *ret_value = l;
+	free(string);
+    } else
+	*ret_value = default_value;
+
+    return 0;
+}
+
+
+/*
+ * krb5_libdefault_string() is defined as static in
+ * src/lib/krb5/krb/get_in_tkt.c.  Create local versions of
+ * krb5_libdefault_* functions here.  We need a libdefaults_strings()
+ * function which is not currently supported there anyway.  Also,
+ * add the ability to supply a default value for the boolean and
+ * integer functions.
+ */
+
+krb5_error_code
+pkinit_libdefault_strings(krb5_context context, const krb5_data *realm,
+			  const char *option, char ***ret_value)
+{
+    profile_t profile;
+    const char *names[5];
+    char **values = NULL;
+    krb5_error_code retval;
+    char realmstr[1024];
+
+    if (realm != NULL && realm->length > sizeof(realmstr)-1)
+	return EINVAL;
+
+    if (realm != NULL) {
+	strncpy(realmstr, realm->data, realm->length);
+	realmstr[realm->length] = '\0';
+    }
+
+    if (!context || (context->magic != KV5M_CONTEXT))
+	return KV5M_CONTEXT;
+
+    profile = context->profile;
+
+
+    if (realm != NULL) {
+	/*
+	 * Try number one:
+	 *
+	 * [libdefaults]
+	 *	  REALM = {
+	 *		  option = <value>
+	 *	  }
+	 */
+
+	names[0] = "libdefaults";
+	names[1] = realmstr;
+	names[2] = option;
+	names[3] = 0;
+	retval = profile_get_values(profile, names, &values);
+	if (retval == 0 && values != NULL && values[0] != NULL)
+	    goto goodbye;
+
+	/*
+	 * Try number two:
+	 *
+	 * [realms]
+	 *	REALM = {
+	 *		option = <value>
+	 *	}
+	 */
+
+	names[0] = "realms";
+	names[1] = realmstr;
+	names[2] = option;
+	names[3] = 0;
+	retval = profile_get_values(profile, names, &values);
+	if (retval == 0 && values != NULL && values[0] != NULL)
+	    goto goodbye;
+    }
+
+    /*
+     * Try number three:
+     *
+     * [libdefaults]
+     *	      option = <value>
+     */
+
+    names[0] = "libdefaults";
+    names[1] = option;
+    names[2] = 0;
+    retval = profile_get_values(profile, names, &values);
+    if (retval == 0 && values != NULL && values[0] != NULL)
+	goto goodbye;
+
+goodbye:
+    if (values == NULL)
+	return ENOENT;
+
+    *ret_value = values;
+
+    return retval;
+}
+
+krb5_error_code
+pkinit_libdefault_string(krb5_context context, const krb5_data *realm,
+			 const char *option, char **ret_value)
+{
+    krb5_error_code retval;
+    char **values = NULL;
+
+    retval = pkinit_libdefault_strings(context, realm, option, &values);
+    if (retval)
+	return retval;
+
+    if (values[0] == NULL) {
+	retval = ENOENT;
+    } else {
+	*ret_value = malloc(strlen(values[0]) + 1);
+	if (*ret_value == NULL)
+	    retval = ENOMEM;
+	else
+	    strcpy(*ret_value, values[0]);
+    }
+
+    profile_free_list(values);
+    return retval;
+}
+
+krb5_error_code
+pkinit_libdefault_boolean(krb5_context context, const krb5_data *realm,
+			  const char *option, int default_value,
+			  int *ret_value)
+{
+    char *string = NULL;
+    krb5_error_code retval;
+
+    retval = pkinit_libdefault_string(context, realm, option, &string);
+
+   if (retval == 0) {
+	*ret_value = _krb5_conf_boolean(string);
+	free(string);
+    } else
+	*ret_value = default_value;
+
+    return 0;
+}
+
+krb5_error_code
+pkinit_libdefault_integer(krb5_context context, const krb5_data *realm,
+			  const char *option, int default_value,
+			  int *ret_value)
+{
+    char *string = NULL;
+    krb5_error_code retval;
+
+    retval = pkinit_libdefault_string(context, realm, option, &string);
+
+    if (retval == 0) {
+	char *endptr;
+	long l;
+	l = strtol(string, &endptr, 0);
+	if (endptr == string)
+	    *ret_value = default_value;
+	else
+	    *ret_value = l;
+	free(string);
+    }
+
+    return retval;
+}
diff --git a/krb5-1-6/src/plugins/preauth/pkinit/pkinit_srv.c b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_srv.c
new file mode 100644
index 000000000..595a3d04d
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -0,0 +1,1399 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "pkinit.h"
+
+static krb5_error_code
+pkinit_server_get_edata(krb5_context context,
+			krb5_kdc_req * request,
+			struct _krb5_db_entry_new * client,
+			struct _krb5_db_entry_new * server,
+			preauth_get_entry_data_proc server_get_entry_data,
+			void *pa_plugin_context,
+			krb5_pa_data * data);
+
+static krb5_error_code
+pkinit_server_verify_padata(krb5_context context,
+			    struct _krb5_db_entry_new * client,
+			    krb5_data *req_pkt,
+			    krb5_kdc_req * request,
+			    krb5_enc_tkt_part * enc_tkt_reply,
+			    krb5_pa_data * data,
+			    preauth_get_entry_data_proc server_get_entry_data,
+			    void *pa_plugin_context,
+			    void **pa_request_context,
+			    krb5_data **e_data,
+			    krb5_authdata ***authz_data);
+
+static krb5_error_code
+pkinit_server_return_padata(krb5_context context,
+			    krb5_pa_data * padata,
+			    struct _krb5_db_entry_new * client,
+			    krb5_data *req_pkt,
+			    krb5_kdc_req * request,
+			    krb5_kdc_rep * reply,
+			    struct _krb5_key_data * client_key,
+			    krb5_keyblock * encrypting_key,
+			    krb5_pa_data ** send_pa,
+			    preauth_get_entry_data_proc server_get_entry_data,
+			    void *pa_plugin_context,
+			    void **pa_request_context);
+
+static int pkinit_server_get_flags
+	(krb5_context kcontext, krb5_preauthtype patype);
+
+static krb5_error_code pkinit_init_kdc_req_context
+	(krb5_context, void **blob);
+
+static void pkinit_fini_kdc_req_context
+	(krb5_context context, void *blob);
+
+static int pkinit_server_plugin_init_realm
+	(krb5_context context, const char *realmname,
+	 pkinit_kdc_context *pplgctx);
+
+static void pkinit_server_plugin_fini_realm
+	(krb5_context context, pkinit_kdc_context plgctx);
+
+static int pkinit_server_plugin_init
+	(krb5_context context, void **blob, const char **realmnames);
+
+static void pkinit_server_plugin_fini
+	(krb5_context context, void *blob);
+
+static pkinit_kdc_context pkinit_find_realm_context
+	(krb5_context context, void *pa_plugin_context, krb5_principal princ);
+
+static krb5_error_code
+pkinit_create_edata(krb5_context context,
+		    pkinit_plg_crypto_context plg_cryptoctx,
+		    pkinit_req_crypto_context req_cryptoctx,
+		    pkinit_identity_crypto_context id_cryptoctx,
+		    pkinit_plg_opts *opts,
+		    krb5_error_code err_code,
+		    krb5_data **e_data)
+{
+    krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+
+    pkiDebug("pkinit_create_edata: creating edata for error %d (%s)\n",
+	     err_code, error_message(err_code));
+    switch(err_code) {
+	case KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE:
+	    retval = pkinit_create_td_trusted_certifiers(context,
+		plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
+	    break;
+	case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED:
+	    retval = pkinit_create_td_dh_parameters(context, plg_cryptoctx,
+		req_cryptoctx, id_cryptoctx, opts, e_data);
+	    break;
+	case KRB5KDC_ERR_INVALID_CERTIFICATE:
+	case KRB5KDC_ERR_REVOKED_CERTIFICATE:
+	    retval = pkinit_create_td_invalid_certificate(context,
+		plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
+	    break;
+	default:
+	    pkiDebug("no edata needed for error %d (%s)\n",
+		     err_code, error_message(err_code));
+	    retval = 0;
+	    goto cleanup;
+    }
+
+cleanup:
+
+    return retval;
+}
+
+static krb5_error_code
+pkinit_server_get_edata(krb5_context context,
+			krb5_kdc_req * request,
+			struct _krb5_db_entry_new * client,
+			struct _krb5_db_entry_new * server,
+			preauth_get_entry_data_proc server_get_entry_data,
+			void *pa_plugin_context,
+			krb5_pa_data * data)
+{
+    krb5_error_code retval = 0;
+    pkinit_kdc_context plgctx = NULL;
+
+    pkiDebug("pkinit_server_get_edata: entered!\n");
+
+    /*
+     * If we don't have a realm context for the given realm,
+     * don't tell the client that we support pkinit! 
+     */
+    plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+				       request->server);
+    if (plgctx == NULL)
+	retval = EINVAL;
+
+    return retval;
+}
+
+static krb5_error_code
+verify_client_san(krb5_context context,
+		  pkinit_kdc_context plgctx,
+		  pkinit_kdc_req_context reqctx,
+		  krb5_principal client,
+		  int *valid_san)
+{
+    krb5_error_code retval;
+    krb5_principal *princs = NULL;
+    krb5_principal *upns = NULL;
+    int i;
+#ifdef DEBUG_SAN_INFO
+    char *client_string = NULL, *san_string;
+#endif
+    
+    retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
+				       reqctx->cryptoctx, plgctx->idctx,
+				       &princs,
+				       plgctx->opts->allow_upn ? &upns : NULL,
+				       NULL);
+    if (retval) {
+	pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+	goto out;
+    }
+    /* XXX Verify this is consistent with client side XXX */
+#if 0
+    retval = call_san_checking_plugins(context, plgctx, reqctx, princs,
+				       upns, NULL, &plugin_decision, &ignore);
+    pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
+	     __FUNCTION__);
+    if (retval) {
+	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+	goto cleanup;
+    }
+    pkiDebug("%s: call_san_checking_plugins() returned decision %d\n",
+	     __FUNCTION__, plugin_decision);
+    if (plugin_decision != NO_DECISION) {
+	retval = plugin_decision;
+	goto out;
+    }
+#endif
+
+#ifdef DEBUG_SAN_INFO
+    krb5_unparse_name(context, client, &client_string);
+#endif
+    pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__);
+    for (i = 0; princs != NULL && princs[i] != NULL; i++) {
+#ifdef DEBUG_SAN_INFO
+	krb5_unparse_name(context, princs[i], &san_string);
+	pkiDebug("%s: Comparing client '%s' to pkinit san value '%s'\n",
+		 __FUNCTION__, client_string, san_string);
+	krb5_free_unparsed_name(context, san_string);
+#endif
+	if (krb5_principal_compare(context, princs[i], client)) {
+	    pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
+	    *valid_san = 1;
+	    retval = 0;
+	    goto out;
+	}
+    }
+    pkiDebug("%s: no pkinit san match found\n", __FUNCTION__);
+    /*
+     * XXX if cert has names but none match, should we
+     * be returning KRB5KDC_ERR_CLIENT_NAME_MISMATCH here?
+     */
+
+    if (upns == NULL) {
+	pkiDebug("%s: no upn sans (or we wouldn't accept them anyway)\n",
+		 __FUNCTION__);
+	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+	goto out;
+    }
+
+    pkiDebug("%s: Checking upn sans\n", __FUNCTION__);
+    for (i = 0; upns[i] != NULL; i++) {
+#ifdef DEBUG_SAN_INFO
+	krb5_unparse_name(context, upns[i], &san_string);
+	pkiDebug("%s: Comparing client '%s' to upn san value '%s'\n",
+		 __FUNCTION__, client_string, san_string);
+	krb5_free_unparsed_name(context, san_string);
+#endif
+	if (krb5_principal_compare(context, upns[i], client)) {
+	    pkiDebug("%s: upn san match found\n", __FUNCTION__);
+	    *valid_san = 1;
+	    retval = 0;
+	    goto out;
+	}
+    }
+    pkiDebug("%s: no upn san match found\n", __FUNCTION__);
+
+    /* We found no match */
+    if (princs != NULL || upns != NULL) {
+	*valid_san = 0;
+	/* XXX ??? If there was one or more name in the cert, but
+	 * none matched the client name, then return mismatch? */
+	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+    }
+    retval = 0;
+
+out:
+    if (princs != NULL) {
+	for (i = 0; princs[i] != NULL; i++)
+	    krb5_free_principal(context, princs[i]);
+	free(princs);
+    }
+    if (upns != NULL) {
+	for (i = 0; upns[i] != NULL; i++)
+	    krb5_free_principal(context, upns[i]);
+	free(upns);
+    }
+#ifdef DEBUG_SAN_INFO
+    if (client_string != NULL)
+	krb5_free_unparsed_name(context, client_string);
+#endif
+    pkiDebug("%s: returning retval %d, valid_san %d\n",
+	     __FUNCTION__, retval, *valid_san);
+    return retval;
+}
+
+static krb5_error_code
+verify_client_eku(krb5_context context,
+		  pkinit_kdc_context plgctx,
+		  pkinit_kdc_req_context reqctx,
+		  int *eku_accepted)
+{
+    krb5_error_code retval;
+
+    *eku_accepted = 0;
+
+    if (plgctx->opts->require_eku == 0) {
+	pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__);
+	*eku_accepted = 1;
+	retval = 0;
+	goto out;
+    }
+
+    retval = crypto_check_cert_eku(context, plgctx->cryptoctx,
+				   reqctx->cryptoctx, plgctx->idctx,
+				   0, /* kdc cert */
+				   plgctx->opts->accept_secondary_eku,
+				   eku_accepted);
+    if (retval) {
+	pkiDebug("%s: Error from crypto_check_cert_eku %d (%s)\n",
+		 __FUNCTION__, retval, error_message(retval));
+	goto out;
+    }
+
+out:
+    pkiDebug("%s: returning retval %d, eku_accepted %d\n",
+	     __FUNCTION__, retval, *eku_accepted);
+    return retval;
+}
+
+static krb5_error_code
+pkinit_server_verify_padata(krb5_context context,
+			    struct _krb5_db_entry_new * client,
+			    krb5_data *req_pkt,
+			    krb5_kdc_req * request,
+			    krb5_enc_tkt_part * enc_tkt_reply,
+			    krb5_pa_data * data,
+			    preauth_get_entry_data_proc server_get_entry_data,
+			    void *pa_plugin_context,
+			    void **pa_request_context,
+			    krb5_data **e_data,
+			    krb5_authdata ***authz_data)
+{
+    krb5_error_code retval = 0;	
+    krb5_octet_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL};
+    krb5_data *encoded_pkinit_authz_data = NULL;
+    krb5_pa_pk_as_req *reqp = NULL;
+    krb5_pa_pk_as_req_draft9 *reqp9 = NULL;
+    krb5_auth_pack *auth_pack = NULL;
+    krb5_auth_pack_draft9 *auth_pack9 = NULL;
+    pkinit_kdc_context plgctx = NULL;
+    pkinit_kdc_req_context reqctx;
+    krb5_preauthtype pa_type;
+    krb5_checksum cksum = {0, 0, 0, NULL};
+    krb5_data *der_req = NULL;
+    int valid_eku = 0, valid_san = 0;
+    krb5_authdata **my_authz_data = NULL, *pkinit_authz_data = NULL;
+    krb5_kdc_req *tmp_as_req = NULL;
+    krb5_data k5data;
+
+    pkiDebug("pkinit_verify_padata: entered!\n");
+    if (data == NULL || data->length <= 0 || data->contents == NULL)
+	return 0;
+
+    if (pa_plugin_context == NULL || e_data == NULL)
+	return EINVAL;
+
+    plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+				       request->server);
+    if (plgctx == NULL)
+	return 0;
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin(data->contents, data->length, "/tmp/kdc_as_req");
+#endif
+    /* create a per-request context */
+    retval = pkinit_init_kdc_req_context(context, (void **)&reqctx);
+    if (retval)
+	goto cleanup;
+    reqctx->pa_type = data->pa_type;
+
+    PADATA_TO_KRB5DATA(data, &k5data);
+
+    switch ((int)data->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
+	    pa_type = (int)data->pa_type;
+	    retval = k5int_decode_krb5_pa_pk_as_req(&k5data, &reqp);
+	    if (retval) {
+		pkiDebug("decode_krb5_pa_pk_as_req failed\n");
+		goto cleanup;
+	    }
+#ifdef DEBUG_ASN1
+	    print_buffer_bin(reqp->signedAuthPack.data,
+			     reqp->signedAuthPack.length,
+			     "/tmp/kdc_signed_data");
+#endif
+	    retval = cms_signeddata_verify(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_CLIENT,
+		plgctx->opts->require_crl_checking,
+		reqp->signedAuthPack.data, reqp->signedAuthPack.length,
+		&authp_data.data, &authp_data.length, &krb5_authz.data, 
+		&krb5_authz.length);
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
+	    pa_type = KRB5_PADATA_PK_AS_REQ_OLD;
+	    retval = k5int_decode_krb5_pa_pk_as_req_draft9(&k5data, &reqp9);
+	    if (retval) {
+		pkiDebug("decode_krb5_pa_pk_as_req_draft9 failed\n");
+		goto cleanup;
+	    }
+#ifdef DEBUG_ASN1
+	    print_buffer_bin(reqp9->signedAuthPack.data,
+			     reqp9->signedAuthPack.length,
+			     "/tmp/kdc_signed_data_draft9");
+#endif
+
+	    retval = cms_signeddata_verify(context, plgctx->cryptoctx,
+		reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_DRAFT9,
+		plgctx->opts->require_crl_checking,
+		reqp9->signedAuthPack.data, reqp9->signedAuthPack.length,
+		&authp_data.data, &authp_data.length, &krb5_authz.data, 
+		&krb5_authz.length);
+	    break;
+	default:
+	    pkiDebug("unrecognized pa_type = %d\n", data->pa_type);
+	    retval = EINVAL;
+	    goto cleanup;
+    }
+    if (retval) {
+	pkiDebug("pkcs7_signeddata_verify failed\n");
+	goto cleanup;
+    }
+
+    retval = verify_client_san(context, plgctx, reqctx, request->client,
+			       &valid_san);
+    if (retval)
+	goto cleanup;
+    if (!valid_san) {
+	pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
+		 __FUNCTION__);
+	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+	goto cleanup;
+    }
+    retval = verify_client_eku(context, plgctx, reqctx, &valid_eku);
+    if (retval)
+	goto cleanup;
+
+    if (!valid_eku) {
+	pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
+		 __FUNCTION__);
+	retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+	goto cleanup;
+    }
+
+#ifdef DEBUG_ASN1
+    print_buffer_bin(authp_data.data, authp_data.length, "/tmp/kdc_auth_pack");
+#endif
+
+    OCTETDATA_TO_KRB5DATA(&authp_data, &k5data);
+    switch ((int)data->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    retval = k5int_decode_krb5_auth_pack(&k5data, &auth_pack);
+	    if (retval) {
+		pkiDebug("failed to decode krb5_auth_pack\n");
+		goto cleanup;
+	    }
+
+	    /* check dh parameters */
+	    if (auth_pack->clientPublicValue != NULL) {	
+		retval = server_check_dh(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, plgctx->idctx,
+		    &auth_pack->clientPublicValue->algorithm.parameters,
+		    plgctx->opts->dh_min_bits);
+
+		if (retval) {
+		    pkiDebug("bad dh parameters\n");
+		    goto cleanup;
+		}
+	    }
+	    /*
+	     * The KDC may have modified the request after decoding it.
+	     * We need to compute the checksum on the data that
+	     * came from the client.  Therefore, we use the original
+	     * packet contents.
+	     */
+	    retval = k5int_decode_krb5_as_req(req_pkt, &tmp_as_req); 
+	    if (retval) {
+		pkiDebug("decode_krb5_as_req returned %d\n", (int)retval);
+		goto cleanup;
+	    }
+		
+	    retval = k5int_encode_krb5_kdc_req_body(tmp_as_req, &der_req);
+	    if (retval) {
+		pkiDebug("encode_krb5_kdc_req_body returned %d\n", (int) retval);
+		goto cleanup;
+	    }
+	    retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL,
+					  0, der_req, &cksum);
+	    if (retval) {
+		pkiDebug("unable to calculate AS REQ checksum\n");
+		goto cleanup;
+	    }
+	    if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length ||
+		memcmp(cksum.contents,
+		       auth_pack->pkAuthenticator.paChecksum.contents,
+		       cksum.length)) {
+		pkiDebug("failed to match the checksum\n");
+#ifdef DEBUG_CKSUM
+		pkiDebug("calculating checksum on buf size (%d)\n",
+			 req_pkt->length);
+		print_buffer(req_pkt->data, req_pkt->length);
+		pkiDebug("received checksum type=%d size=%d ",
+			auth_pack->pkAuthenticator.paChecksum.checksum_type,
+			auth_pack->pkAuthenticator.paChecksum.length);
+		print_buffer(auth_pack->pkAuthenticator.paChecksum.contents,
+			     auth_pack->pkAuthenticator.paChecksum.length);
+		pkiDebug("expected checksum type=%d size=%d ",
+			 cksum.checksum_type, cksum.length);
+		print_buffer(cksum.contents, cksum.length);
+#endif
+
+		retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;
+		goto cleanup;
+	    }
+
+	    /* check if kdcPkId present and match KDC's subjectIdentifier */
+	    if (reqp->kdcPkId.data != NULL) {
+		int valid_kdcPkId = 0;
+		retval = pkinit_check_kdc_pkid(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, plgctx->idctx,
+		    reqp->kdcPkId.data, reqp->kdcPkId.length, &valid_kdcPkId);
+		if (retval)
+		    goto cleanup;
+		if (!valid_kdcPkId)
+		    pkiDebug("kdcPkId in AS_REQ does not match KDC's cert"
+			     "RFC says to ignore and proceed\n");
+
+	    }
+	    /* remember the decoded auth_pack for verify_padata routine */
+	    reqctx->rcv_auth_pack = auth_pack;
+	    auth_pack = NULL;
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    retval = k5int_decode_krb5_auth_pack_draft9(&k5data, &auth_pack9);
+	    if (retval) {
+		pkiDebug("failed to decode krb5_auth_pack_draft9\n");
+		goto cleanup;
+	    }
+	    if (auth_pack9->clientPublicValue != NULL) {	
+		retval = server_check_dh(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, plgctx->idctx,
+		    &auth_pack9->clientPublicValue->algorithm.parameters,
+		    plgctx->opts->dh_min_bits);
+
+		if (retval) {
+		    pkiDebug("bad dh parameters\n");
+		    goto cleanup;
+		}
+	    }
+	    /* remember the decoded auth_pack for verify_padata routine */
+	    reqctx->rcv_auth_pack9 = auth_pack9;
+	    auth_pack9 = NULL;
+	    break;
+    }
+
+    /* return authorization data to be included in the ticket */
+    switch ((int)data->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    my_authz_data = malloc(2 * sizeof(*my_authz_data));
+	    if (my_authz_data == NULL) {
+		retval = ENOMEM;
+		pkiDebug("Couldn't allocate krb5_authdata ptr array\n");
+		goto cleanup;
+	    }
+	    my_authz_data[1] = NULL;
+	    my_authz_data[0] = malloc(sizeof(krb5_authdata));
+	    if (my_authz_data[0] == NULL) {
+		retval = ENOMEM;
+		pkiDebug("Couldn't allocate krb5_authdata\n");
+		free(my_authz_data);
+		goto cleanup;
+	    }
+	    /* AD-INITIAL-VERIFIED-CAS must be wrapped in AD-IF-RELEVANT */
+	    my_authz_data[0]->magic = KV5M_AUTHDATA;
+	    my_authz_data[0]->ad_type = KRB5_AUTHDATA_IF_RELEVANT;
+
+	    /* create an internal AD-INITIAL-VERIFIED-CAS data */
+	    pkinit_authz_data = malloc(sizeof(krb5_authdata));
+	    if (pkinit_authz_data == NULL) {
+		retval = ENOMEM;
+		pkiDebug("Couldn't allocate krb5_authdata\n");
+		free(my_authz_data[0]);
+		free(my_authz_data);
+		goto cleanup;
+	    }
+	    pkinit_authz_data->ad_type = KRB5_AUTHDATA_INITIAL_VERIFIED_CAS;
+	    /* content of this ad-type contains the certification
+	       path with which the client certificate was validated
+	     */
+	    pkinit_authz_data->contents = krb5_authz.data;
+	    pkinit_authz_data->length = krb5_authz.length;
+	    retval = k5int_encode_krb5_authdata_elt(pkinit_authz_data, 
+			    &encoded_pkinit_authz_data);
+#ifdef DEBUG_ASN1
+	    print_buffer_bin((unsigned char *)encoded_pkinit_authz_data->data,
+			     encoded_pkinit_authz_data->length,
+			     "/tmp/kdc_pkinit_authz_data");
+#endif
+	    free(pkinit_authz_data);
+	    if (retval) {
+		pkiDebug("k5int_encode_krb5_authdata_elt failed\n");
+		free(my_authz_data[0]);
+		free(my_authz_data);
+		goto cleanup;
+	    }
+
+	    my_authz_data[0]->contents =
+			    (krb5_octet *) encoded_pkinit_authz_data->data;
+	    my_authz_data[0]->length = encoded_pkinit_authz_data->length;
+	    *authz_data = my_authz_data;
+	    pkiDebug("Returning %d bytes of authorization data\n", 
+		     krb5_authz.length);
+	    encoded_pkinit_authz_data->data = NULL; /* Don't free during cleanup*/
+	    free(encoded_pkinit_authz_data);
+	    break;
+	default: 
+	    *authz_data = NULL;
+    }
+    /* remember to set the PREAUTH flag in the reply */
+    enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
+    *pa_request_context = reqctx;
+    reqctx = NULL;
+
+  cleanup:
+    if (retval && data->pa_type == KRB5_PADATA_PK_AS_REQ) {
+	pkiDebug("pkinit_verify_padata failed: creating e-data\n");
+	if (pkinit_create_edata(context, plgctx->cryptoctx, reqctx->cryptoctx,
+		plgctx->idctx, plgctx->opts, retval, e_data))
+	    pkiDebug("pkinit_create_edata failed\n");
+    }
+
+    switch ((int)data->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    free_krb5_pa_pk_as_req(&reqp);
+	    if (cksum.contents != NULL)
+		free(cksum.contents);
+	    if (der_req != NULL)
+		 krb5_free_data(context, der_req);
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    free_krb5_pa_pk_as_req_draft9(&reqp9);
+    }
+    if (tmp_as_req != NULL)
+	k5int_krb5_free_kdc_req(context, tmp_as_req); 
+    if (authp_data.data != NULL)
+	free(authp_data.data);
+    if (krb5_authz.data != NULL)
+	free(krb5_authz.data);
+    if (reqctx != NULL)
+	pkinit_fini_kdc_req_context(context, reqctx);
+    if (auth_pack != NULL)
+	free_krb5_auth_pack(&auth_pack);
+    if (auth_pack9 != NULL)
+	free_krb5_auth_pack_draft9(context, &auth_pack9);
+
+    return retval;
+}
+
+static krb5_error_code
+pkinit_server_return_padata(krb5_context context,
+			    krb5_pa_data * padata,
+			    struct _krb5_db_entry_new * client,
+			    krb5_data *req_pkt,
+			    krb5_kdc_req * request,
+			    krb5_kdc_rep * reply,
+			    struct _krb5_key_data * client_key,
+			    krb5_keyblock * encrypting_key,
+			    krb5_pa_data ** send_pa,
+			    preauth_get_entry_data_proc server_get_entry_data,
+			    void *pa_plugin_context,
+			    void **pa_request_context)
+{
+    krb5_error_code retval = 0;
+    krb5_data scratch = {0, 0, NULL};
+    krb5_pa_pk_as_req *reqp = NULL;
+    krb5_pa_pk_as_req_draft9 *reqp9 = NULL;
+    int i = 0;
+
+    unsigned char *subjectPublicKey = NULL;
+    unsigned char *dh_pubkey = NULL, *server_key = NULL;
+    unsigned int subjectPublicKey_len = 0;
+    unsigned int server_key_len = 0, dh_pubkey_len = 0;
+
+    krb5_kdc_dh_key_info dhkey_info;
+    krb5_data *encoded_dhkey_info = NULL;
+    krb5_pa_pk_as_rep *rep = NULL;
+    krb5_pa_pk_as_rep_draft9 *rep9 = NULL;
+    krb5_data *out_data = NULL;
+
+    krb5_enctype enctype = -1;
+
+    krb5_reply_key_pack *key_pack = NULL;
+    krb5_reply_key_pack_draft9 *key_pack9 = NULL;
+    krb5_data *encoded_key_pack = NULL;
+    unsigned int num_types;
+    krb5_cksumtype *cksum_types = NULL;
+
+    pkinit_kdc_context plgctx;
+    pkinit_kdc_req_context reqctx;
+
+    int fixed_keypack = 0;
+
+    *send_pa = NULL;
+    if (padata == NULL || padata->length <= 0 || padata->contents == NULL)
+	return 0;
+
+    if (pa_request_context == NULL || *pa_request_context == NULL) {
+	pkiDebug("missing request context \n");
+	return EINVAL;
+    }
+    
+    plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+				       request->server);
+    if (plgctx == NULL) {
+	pkiDebug("Unable to locate correct realm context\n");
+	return ENOENT;
+    }
+
+    pkiDebug("pkinit_return_padata: entered!\n");
+    reqctx = (pkinit_kdc_req_context)*pa_request_context;
+
+    if (encrypting_key->contents) {
+	free(encrypting_key->contents);
+	encrypting_key->length = 0;
+	encrypting_key->contents = NULL;
+    }
+
+    for(i = 0; i < request->nktypes; i++) {
+	enctype = request->ktype[i];
+	if (!krb5_c_valid_enctype(enctype))
+	    continue;
+	else {
+	    pkiDebug("KDC picked etype = %d\n", enctype);
+	    break;
+	}
+    }
+
+    if (i == request->nktypes) {
+	retval = KRB5KDC_ERR_ETYPE_NOSUPP;
+	goto cleanup;
+    }
+
+    switch((int)reqctx->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    init_krb5_pa_pk_as_rep(&rep);
+	    if (rep == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    /* let's assume it's RSA. we'll reset it to DH if needed */
+	    rep->choice = choice_pa_pk_as_rep_encKeyPack;
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    init_krb5_pa_pk_as_rep_draft9(&rep9);
+	    if (rep9 == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    rep9->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
+	    break;
+	default:
+	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	    goto cleanup;
+    }
+
+    if (reqctx->rcv_auth_pack != NULL &&
+	    reqctx->rcv_auth_pack->clientPublicValue != NULL) {
+	subjectPublicKey =
+	    reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.data;
+	subjectPublicKey_len =
+	    reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.length;
+	rep->choice = choice_pa_pk_as_rep_dhInfo;
+    } else if (reqctx->rcv_auth_pack9 != NULL &&
+		reqctx->rcv_auth_pack9->clientPublicValue != NULL) {
+	subjectPublicKey =
+	    reqctx->rcv_auth_pack9->clientPublicValue->subjectPublicKey.data;
+	subjectPublicKey_len =
+	    reqctx->rcv_auth_pack9->clientPublicValue->subjectPublicKey.length;
+	rep9->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
+    }
+
+    /* if this DH, then process finish computing DH key */
+    if (rep != NULL && (rep->choice == choice_pa_pk_as_rep_dhInfo ||
+	    rep->choice == choice_pa_pk_as_rep_draft9_dhSignedData)) {
+	pkiDebug("received DH key delivery AS REQ\n");
+	retval = server_process_dh(context, plgctx->cryptoctx,
+	    reqctx->cryptoctx, plgctx->idctx, subjectPublicKey,
+	    subjectPublicKey_len, &dh_pubkey, &dh_pubkey_len, 
+	    &server_key, &server_key_len);
+	if (retval) {
+	    pkiDebug("failed to process/create dh paramters\n");
+	    goto cleanup;
+	}
+    }
+	
+    if ((rep9 != NULL &&
+	    rep9->choice == choice_pa_pk_as_rep_draft9_dhSignedData) ||
+	(rep != NULL && rep->choice == choice_pa_pk_as_rep_dhInfo)) {
+	retval = pkinit_octetstring2key(context, enctype, server_key,
+					server_key_len, encrypting_key);
+	if (retval) {
+	    pkiDebug("pkinit_octetstring2key failed: %s\n",
+		     error_message(retval));
+	    goto cleanup;
+	}
+
+	dhkey_info.subjectPublicKey.length = dh_pubkey_len;
+	dhkey_info.subjectPublicKey.data = dh_pubkey;
+	dhkey_info.nonce = request->nonce;
+	dhkey_info.dhKeyExpiration = 0;
+
+	retval = k5int_encode_krb5_kdc_dh_key_info(&dhkey_info,
+						   &encoded_dhkey_info);
+	if (retval) {
+	    pkiDebug("encode_krb5_kdc_dh_key_info failed\n");
+	    goto cleanup;
+	}
+#ifdef DEBUG_ASN1
+	print_buffer_bin((unsigned char *)encoded_dhkey_info->data,
+			 encoded_dhkey_info->length,
+			 "/tmp/kdc_dh_key_info");
+#endif
+
+	switch ((int)padata->pa_type) {
+	    case KRB5_PADATA_PK_AS_REQ:
+		retval = cms_signeddata_create(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_SERVER, 1,
+		    (unsigned char *)encoded_dhkey_info->data,
+		    encoded_dhkey_info->length,
+		    &rep->u.dh_Info.dhSignedData.data,
+		    &rep->u.dh_Info.dhSignedData.length);
+		if (retval) {
+		    pkiDebug("failed to create pkcs7 signed data\n");
+		    goto cleanup;
+		}
+		break;
+	    case KRB5_PADATA_PK_AS_REP_OLD:
+	    case KRB5_PADATA_PK_AS_REQ_OLD:
+		retval = cms_signeddata_create(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_DRAFT9, 1,
+		    (unsigned char *)encoded_dhkey_info->data,
+		    encoded_dhkey_info->length,
+		    &rep9->u.dhSignedData.data,
+		    &rep9->u.dhSignedData.length);
+		if (retval) {
+		    pkiDebug("failed to create pkcs7 signed data\n");
+		    goto cleanup;
+		}
+		break;
+	}
+    } else {
+	pkiDebug("received RSA key delivery AS REQ\n");
+
+	retval = krb5_c_make_random_key(context, enctype, encrypting_key);
+	if (retval) {
+	    pkiDebug("unable to make a session key\n");
+	    goto cleanup;
+	}
+
+	/* check if PA_TYPE of 132 is present which means the client is
+	 * requesting that a checksum is send back instead of the nonce
+	 */
+	for (i = 0; request->padata[i] != NULL; i++) {
+	    pkiDebug("%s: Checking pa_type 0x%08x\n",
+		     __FUNCTION__, request->padata[i]->pa_type);
+	    if (request->padata[i]->pa_type == 132)
+		fixed_keypack = 1;
+	}
+	pkiDebug("%s: return checksum instead of nonce = %d\n",
+		 __FUNCTION__, fixed_keypack);
+
+	/* if this is an RFC reply or draft9 client requested a checksum 
+	 * in the reply instead of the nonce, create an RFC-style keypack
+	 */
+	if ((int)padata->pa_type == KRB5_PADATA_PK_AS_REQ || fixed_keypack) {
+	    init_krb5_reply_key_pack(&key_pack);
+	    if (key_pack == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	    }
+	    /* retrieve checksums for a given enctype of the reply key */
+	    retval = krb5_c_keyed_checksum_types(context,
+		encrypting_key->enctype, &num_types, &cksum_types);
+	    if (retval)
+		goto cleanup;
+
+	    /* pick the first of acceptable enctypes for the checksum */
+	    retval = krb5_c_make_checksum(context, cksum_types[0],
+		    encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+		    req_pkt, &key_pack->asChecksum);
+	    if (retval) {
+		pkiDebug("unable to calculate AS REQ checksum\n");
+		goto cleanup;
+	    }
+#ifdef DEBUG_CKSUM
+	    pkiDebug("calculating checksum on buf size = %d\n", req_pkt->length);
+	    print_buffer(req_pkt->data, req_pkt->length);
+	    pkiDebug("checksum size = %d\n", key_pack->asChecksum.length);
+	    print_buffer(key_pack->asChecksum.contents, 
+			 key_pack->asChecksum.length);
+	    pkiDebug("encrypting key (%d)\n", encrypting_key->length);
+	    print_buffer(encrypting_key->contents, encrypting_key->length);
+#endif
+
+	    krb5_copy_keyblock_contents(context, encrypting_key,
+					&key_pack->replyKey);
+
+	    retval = k5int_encode_krb5_reply_key_pack(key_pack,
+						      &encoded_key_pack);
+	    if (retval) {
+		pkiDebug("failed to encode reply_key_pack\n");
+		goto cleanup;
+	    }
+	}
+
+	switch ((int)padata->pa_type) {
+	    case KRB5_PADATA_PK_AS_REQ:
+		rep->choice = choice_pa_pk_as_rep_encKeyPack;
+		retval = cms_envelopeddata_create(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, plgctx->idctx, padata->pa_type, 1, 
+		    (unsigned char *)encoded_key_pack->data,
+		    encoded_key_pack->length,
+		    &rep->u.encKeyPack.data, &rep->u.encKeyPack.length);
+		break;
+	    case KRB5_PADATA_PK_AS_REP_OLD:
+	    case KRB5_PADATA_PK_AS_REQ_OLD:
+		/* if the request is from the broken draft9 client that
+		 * expects back a nonce, create it now 
+		 */
+		if (!fixed_keypack) {
+		    init_krb5_reply_key_pack_draft9(&key_pack9);
+		    if (key_pack9 == NULL) {
+			retval = ENOMEM;
+			goto cleanup;
+		    }
+		    key_pack9->nonce = reqctx->rcv_auth_pack9->pkAuthenticator.nonce;
+		    krb5_copy_keyblock_contents(context, encrypting_key,
+						&key_pack9->replyKey);
+
+		    retval = k5int_encode_krb5_reply_key_pack_draft9(key_pack9,
+							   &encoded_key_pack);
+		    if (retval) {
+			pkiDebug("failed to encode reply_key_pack\n");
+			goto cleanup;
+		    }
+		} 
+
+		rep9->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
+		retval = cms_envelopeddata_create(context, plgctx->cryptoctx,
+		    reqctx->cryptoctx, plgctx->idctx, padata->pa_type, 1, 
+		    (unsigned char *)encoded_key_pack->data,
+		    encoded_key_pack->length,
+		    &rep9->u.encKeyPack.data, &rep9->u.encKeyPack.length);
+		break;
+	}
+	if (retval) {
+	    pkiDebug("failed to create pkcs7 enveloped data: %s\n",
+		     error_message(retval));
+	    goto cleanup;
+	}
+#ifdef DEBUG_ASN1
+	print_buffer_bin((unsigned char *)encoded_key_pack->data,
+			 encoded_key_pack->length,
+			 "/tmp/kdc_key_pack");
+	switch ((int)padata->pa_type) {
+	    case KRB5_PADATA_PK_AS_REQ:
+		print_buffer_bin(rep->u.encKeyPack.data,
+				 rep->u.encKeyPack.length,
+				 "/tmp/kdc_enc_key_pack");
+		break;
+	    case KRB5_PADATA_PK_AS_REP_OLD:
+	    case KRB5_PADATA_PK_AS_REQ_OLD:
+		print_buffer_bin(rep9->u.encKeyPack.data,
+				 rep9->u.encKeyPack.length,
+				 "/tmp/kdc_enc_key_pack");
+		break;
+	}
+#endif
+    }
+
+    switch ((int)padata->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    retval = k5int_encode_krb5_pa_pk_as_rep(rep, &out_data);
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    retval = k5int_encode_krb5_pa_pk_as_rep_draft9(rep9, &out_data);
+	    break;
+    }
+    if (retval) {
+	pkiDebug("failed to encode AS_REP\n");
+	goto cleanup;
+    }
+#ifdef DEBUG_ASN1
+    if (out_data != NULL)
+	print_buffer_bin((unsigned char *)out_data->data, out_data->length,
+			 "/tmp/kdc_as_rep");
+#endif
+
+    *send_pa = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
+    if (*send_pa == NULL) {
+	retval = ENOMEM;
+	free(out_data->data);
+	free(out_data);
+	out_data = NULL;
+	goto cleanup;
+    }
+    (*send_pa)->magic = KV5M_PA_DATA;
+    switch ((int)padata->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP;
+	    break;
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	    (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP_OLD;
+	    break;
+    }
+    (*send_pa)->length = out_data->length;
+    (*send_pa)->contents = (krb5_octet *) out_data->data;
+
+
+  cleanup:
+    pkinit_fini_kdc_req_context(context, reqctx);
+    if (scratch.data != NULL)
+	free(scratch.data);
+    if (out_data != NULL)
+	free(out_data);
+    if (encoded_dhkey_info != NULL)
+	krb5_free_data(context, encoded_dhkey_info);
+    if (encoded_key_pack != NULL)
+	krb5_free_data(context, encoded_key_pack);
+    if (dh_pubkey != NULL)
+	free(dh_pubkey);
+    if (server_key != NULL)
+	free(server_key);
+    if (cksum_types != NULL)
+	free(cksum_types);
+
+    switch ((int)padata->pa_type) {
+	case KRB5_PADATA_PK_AS_REQ:
+	    free_krb5_pa_pk_as_req(&reqp);
+	    free_krb5_pa_pk_as_rep(&rep);
+	    free_krb5_reply_key_pack(&key_pack);
+	    break;
+	case KRB5_PADATA_PK_AS_REP_OLD:
+	case KRB5_PADATA_PK_AS_REQ_OLD:
+	    free_krb5_pa_pk_as_req_draft9(&reqp9);
+	    free_krb5_pa_pk_as_rep_draft9(&rep9);
+	    if (!fixed_keypack)
+		free_krb5_reply_key_pack_draft9(&key_pack9);
+	    else
+		free_krb5_reply_key_pack(&key_pack);
+	    break;
+    }
+
+    if (retval)
+	pkiDebug("pkinit_verify_padata failure");
+
+    return retval;
+}
+
+static int
+pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype)
+{
+    return PA_SUFFICIENT | PA_REPLACES_KEY;
+}
+
+static krb5_preauthtype supported_server_pa_types[] = {
+    KRB5_PADATA_PK_AS_REQ,
+    KRB5_PADATA_PK_AS_REQ_OLD,
+    KRB5_PADATA_PK_AS_REP_OLD,
+    0
+};
+
+static void
+pkinit_fini_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
+{
+    /*
+     * There is nothing currently allocated by pkinit_init_kdc_profile()
+     * which needs to be freed here.
+     */
+}
+
+static krb5_error_code
+pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
+{
+    krb5_error_code retval;
+    char *eku_string = NULL;
+
+    pkiDebug("%s: entered for realm %s\n", __FUNCTION__, plgctx->realmname);
+    retval = pkinit_kdcdefault_string(context, plgctx->realmname,
+				      "pkinit_identity",
+				      &plgctx->idopts->identity);
+    if (retval != 0 || NULL == plgctx->idopts->identity) {
+	retval = EINVAL;
+	krb5_set_error_message(context, retval,
+			       "No pkinit_identity supplied for realm %s",
+			       plgctx->realmname);
+	goto errout;
+    }
+
+    retval = pkinit_kdcdefault_strings(context, plgctx->realmname,
+				       "pkinit_anchors",
+				       &plgctx->idopts->anchors);
+    if (retval != 0 || NULL == plgctx->idopts->anchors) {
+	retval = EINVAL;
+	krb5_set_error_message(context, retval,
+			       "No pkinit_anchors supplied for realm %s",
+			       plgctx->realmname);
+	goto errout;
+    }
+
+    pkinit_kdcdefault_strings(context, plgctx->realmname,
+			      "pkinit_pool",
+			      &plgctx->idopts->intermediates);
+
+    pkinit_kdcdefault_strings(context, plgctx->realmname,
+			      "pkinit_revoke",
+			      &plgctx->idopts->crls);
+
+    pkinit_kdcdefault_string(context, plgctx->realmname,
+			     "pkinit_kdc_ocsp",
+			     &plgctx->idopts->ocsp);
+
+    pkinit_kdcdefault_string(context, plgctx->realmname,
+			     "pkinit_mappings_file",
+			     &plgctx->idopts->dn_mapping_file);
+
+    pkinit_kdcdefault_integer(context, plgctx->realmname,
+			      "pkinit_dh_min_bits",
+			      PKINIT_DEFAULT_DH_MIN_BITS,
+			      &plgctx->opts->dh_min_bits);
+    if (plgctx->opts->dh_min_bits < 1024) {
+	pkiDebug("%s: invalid value (%d) for pkinit_dh_min_bits, "
+		 "using default value (%d) instead\n", __FUNCTION__,
+		 plgctx->opts->dh_min_bits, PKINIT_DEFAULT_DH_MIN_BITS);
+	plgctx->opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS;
+    }
+
+    pkinit_kdcdefault_boolean(context, plgctx->realmname,
+			      "pkinit_allow_upn",
+			      0, &plgctx->opts->allow_upn);
+
+    pkinit_kdcdefault_boolean(context, plgctx->realmname,
+			      "pkinit_require_crl_checking",
+			      0, &plgctx->opts->require_crl_checking);
+
+    pkinit_kdcdefault_string(context, plgctx->realmname,
+			     "pkinit_eku_checking",
+			     &eku_string);
+    if (eku_string != NULL) {
+	if (strcasecmp(eku_string, "kpClientAuth") == 0) {
+	    plgctx->opts->require_eku = 1;
+	    plgctx->opts->accept_secondary_eku = 0;
+	} else if (strcasecmp(eku_string, "scLogin") == 0) {
+	    plgctx->opts->require_eku = 1;
+	    plgctx->opts->accept_secondary_eku = 1;
+	} else if (strcasecmp(eku_string, "none") == 0) {
+	    plgctx->opts->require_eku = 0;
+	    plgctx->opts->accept_secondary_eku = 0;
+	} else {
+	    pkiDebug("%s: Invalid value for pkinit_eku_checking: '%s'\n",
+		     __FUNCTION__, eku_string);
+	}
+	free(eku_string);
+    }
+
+
+    return 0;
+errout:
+    pkinit_fini_kdc_profile(context, plgctx);
+    return retval;
+}
+
+static pkinit_kdc_context
+pkinit_find_realm_context(krb5_context context, void *pa_plugin_context,
+			  krb5_principal princ)
+{
+    int i;
+    pkinit_kdc_context *realm_contexts = pa_plugin_context;
+
+    if (pa_plugin_context == NULL)
+	return NULL;
+
+    for (i = 0; realm_contexts[i] != NULL; i++) {
+	pkinit_kdc_context p = realm_contexts[i];
+
+	if ((p->realmname_len == princ->realm.length) &&
+	    (strncmp(p->realmname, princ->realm.data, p->realmname_len) == 0)) {
+	    pkiDebug("%s: returning context at %p for realm '%s'\n",
+		     __FUNCTION__, p, p->realmname);
+	    return p;
+	}
+    }
+    pkiDebug("%s: unable to find realm context for realm '%.*s'\n",
+	     __FUNCTION__, princ->realm.length, princ->realm.data);
+    return NULL;
+}
+
+static int
+pkinit_server_plugin_init_realm(krb5_context context, const char *realmname,
+				pkinit_kdc_context *pplgctx)
+{
+    krb5_error_code retval = ENOMEM;
+    pkinit_kdc_context plgctx = NULL;
+
+    *pplgctx = NULL;
+
+    plgctx = (pkinit_kdc_context) calloc(1, sizeof(*plgctx));
+    if (plgctx == NULL)
+	goto errout;
+
+    pkiDebug("%s: initializing context at %p for realm '%s'\n",
+	     __FUNCTION__, plgctx, realmname);
+    memset(plgctx, 0, sizeof(*plgctx));
+    plgctx->magic = PKINIT_CTX_MAGIC;
+
+    plgctx->realmname = strdup(realmname);
+    if (plgctx->realmname == NULL)
+	goto errout;
+    plgctx->realmname_len = strlen(plgctx->realmname);
+
+    retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_plg_opts(&plgctx->opts);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_identity_crypto(&plgctx->idctx);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_identity_opts(&plgctx->idopts);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_init_kdc_profile(context, plgctx);
+    if (retval)
+	goto errout;
+
+    retval = pkinit_identity_initialize(context, plgctx->cryptoctx, NULL,
+					plgctx->idopts, plgctx->idctx, 0, NULL);
+    if (retval)
+	goto errout;
+
+    pkiDebug("%s: returning context at %p for realm '%s'\n",
+	     __FUNCTION__, plgctx, realmname);
+    *pplgctx = plgctx;
+    retval = 0;
+
+errout:
+    if (retval)
+	pkinit_server_plugin_fini_realm(context, plgctx);
+
+    return retval;
+}
+
+static int
+pkinit_server_plugin_init(krb5_context context, void **blob,
+			  const char **realmnames)
+{
+    krb5_error_code retval = ENOMEM;
+    pkinit_kdc_context plgctx, *realm_contexts = NULL;
+    int i, j;
+    size_t numrealms;
+
+    retval = pkinit_accessor_init();
+    if (retval)
+	return retval;
+
+    /* Determine how many realms we may need to support */
+    for (i = 0; realmnames[i] != NULL; i++) {};
+    numrealms = i;
+
+    realm_contexts = (pkinit_kdc_context *)
+			calloc(numrealms+1, sizeof(pkinit_kdc_context));
+    if (realm_contexts == NULL)
+	return ENOMEM;
+
+    for (i = 0, j = 0; i < numrealms; i++) {
+	pkiDebug("%s: processing realm '%s'\n", __FUNCTION__, realmnames[i]);
+	retval = pkinit_server_plugin_init_realm(context, realmnames[i], &plgctx);
+	if (retval == 0 && plgctx != NULL)
+	    realm_contexts[j++] = plgctx;
+    }
+
+    if (j == 0) {
+	retval = EINVAL;
+	krb5_set_error_message(context, retval, "No realms configured "
+			       "correctly for pkinit support");
+	goto errout;
+    }
+
+    *blob = realm_contexts;
+    retval = 0;
+    pkiDebug("%s: returning context at %p\n", __FUNCTION__, realm_contexts);
+
+errout:
+    if (retval)
+	pkinit_server_plugin_fini(context, realm_contexts);
+
+    return retval;
+}
+
+static void
+pkinit_server_plugin_fini_realm(krb5_context context, pkinit_kdc_context plgctx)
+{
+    if (plgctx == NULL)
+	return;
+
+    pkinit_fini_kdc_profile(context, plgctx);
+    pkinit_fini_identity_opts(plgctx->idopts);
+    pkinit_fini_identity_crypto(plgctx->idctx);
+    pkinit_fini_plg_crypto(plgctx->cryptoctx);
+    pkinit_fini_plg_opts(plgctx->opts);
+    free(plgctx->realmname);
+    free(plgctx);
+}
+
+static void
+pkinit_server_plugin_fini(krb5_context context, void *blob)
+{
+    pkinit_kdc_context *realm_contexts = blob;
+    int i;
+
+    if (realm_contexts == NULL)
+	return;
+
+    for (i = 0; realm_contexts[i] != NULL; i++) {
+	pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
+    }
+    pkiDebug("%s: freeing   context at %p\n", __FUNCTION__, realm_contexts);
+    free(realm_contexts);
+}
+
+static krb5_error_code
+pkinit_init_kdc_req_context(krb5_context context, void **ctx)
+{
+    krb5_error_code retval = ENOMEM;
+    pkinit_kdc_req_context reqctx = NULL;
+
+    reqctx = (pkinit_kdc_req_context)malloc(sizeof(*reqctx));
+    if (reqctx == NULL)
+	return retval;
+    memset(reqctx, 0, sizeof(*reqctx));
+    reqctx->magic = PKINIT_CTX_MAGIC;
+
+    retval = pkinit_init_req_crypto(&reqctx->cryptoctx);
+    if (retval)
+	goto cleanup;
+    reqctx->rcv_auth_pack = NULL;
+    reqctx->rcv_auth_pack9 = NULL;
+
+    pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx);
+    *ctx = reqctx;
+    retval = 0;
+cleanup:
+    if (retval)
+	pkinit_fini_kdc_req_context(context, reqctx);
+
+    return retval;
+}
+
+static void
+pkinit_fini_kdc_req_context(krb5_context context, void *ctx)
+{
+    pkinit_kdc_req_context reqctx = (pkinit_kdc_req_context)ctx;
+
+    if (reqctx == NULL || reqctx->magic != PKINIT_CTX_MAGIC) {
+	pkiDebug("pkinit_fini_kdc_req_context: got bad reqctx (%p)!\n", reqctx);
+	return;
+    }
+    pkiDebug("%s: freeing   reqctx at %p\n", __FUNCTION__, reqctx);
+
+    pkinit_fini_req_crypto(reqctx->cryptoctx);
+    if (reqctx->rcv_auth_pack != NULL)
+	free_krb5_auth_pack(&reqctx->rcv_auth_pack);
+    if (reqctx->rcv_auth_pack9 != NULL)
+	free_krb5_auth_pack_draft9(context, &reqctx->rcv_auth_pack9);
+
+    free(reqctx);
+}
+
+struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = {
+    "pkinit",			/* name */
+    supported_server_pa_types,	/* pa_type_list */
+    pkinit_server_plugin_init,	/* (*init_proc) */
+    pkinit_server_plugin_fini,	/* (*fini_proc) */
+    pkinit_server_get_flags,	/* (*flags_proc) */
+    pkinit_server_get_edata,	/* (*edata_proc) */
+    pkinit_server_verify_padata,/* (*verify_proc) */
+    pkinit_server_return_padata,/* (*return_proc) */
+    NULL,			/* (*freepa_reqcontext_proc) */
+};
diff --git a/krb5-1-6/src/plugins/preauth/wpse/Makefile.in b/krb5-1-6/src/plugins/preauth/wpse/Makefile.in
new file mode 100644
index 000000000..6c2830f50
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/wpse/Makefile.in
@@ -0,0 +1,42 @@
+thisconfigdir=.
+myfulldir=plugins/preauth/wpse
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
+DEFS=@DEFS@
+
+LOCALINCLUDES = -I../../../include/krb5 -I.
+
+LIBBASE=wpse
+LIBMAJOR=0
+LIBMINOR=0
+SO_EXT=.so
+RELDIR=../plugins/preauth/wpse
+# Depends on libk5crypto and libkrb5
+SHLIB_EXPDEPS = \
+	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+	$(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS= -lkrb5 -lcom_err -lk5crypto $(SUPPORT_LIB) $(LIBS)
+
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+STOBJLISTS=OBJS.ST
+STLIBOBJS=wpse_main.o
+
+SRCS=wpse_main.c
+
+all-unix:: $(LIBBASE)$(SO_EXT)
+install-unix:: install-libs
+clean-unix:: clean-libs clean-libobjs
+
+clean::
+	$(RM) lib$(LIBBASE)$(SO_EXT)
+
+@libnover_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
diff --git a/krb5-1-6/src/plugins/preauth/wpse/configure.in b/krb5-1-6/src/plugins/preauth/wpse/configure.in
new file mode 100644
index 000000000..868dfd594
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/wpse/configure.in
@@ -0,0 +1,14 @@
+K5_AC_INIT(configure.in)
+enable_shared=yes
+build_dynobj=yes
+CONFIG_RULES
+
+AC_CHECK_HEADERS(errno.h string.h)
+
+KRB5_RUN_FLAGS
+dnl The following is for check...
+KRB5_BUILD_PROGRAM
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+AC_CONFIG_HEADERS(config.h)
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/plugins/preauth/wpse/wpse.exports b/krb5-1-6/src/plugins/preauth/wpse/wpse.exports
new file mode 100644
index 000000000..32e067ba9
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/wpse/wpse.exports
@@ -0,0 +1,2 @@
+preauthentication_client_0
+preauthentication_server_0
diff --git a/krb5-1-6/src/plugins/preauth/wpse/wpse_main.c b/krb5-1-6/src/plugins/preauth/wpse/wpse_main.c
new file mode 100644
index 000000000..0d8b4f2a6
--- /dev/null
+++ b/krb5-1-6/src/plugins/preauth/wpse/wpse_main.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2006 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Red Hat, Inc., nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Worst. Preauthentication. Scheme. Ever. */
+
+#ident "$Id: wpse_main.c,v 1.3 2007/01/02 22:33:51 kwc Exp $"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <arpa/inet.h>
+#include <stdio.h>
+
+#include <krb5/krb5.h>
+#include <krb5/preauth_plugin.h>
+
+/* This is not a standardized value.  It's defined here only to make it easier
+ * to change in this module. */
+#define KRB5_PADATA_WPSE_REQ 131
+
+static int
+client_get_flags(krb5_context kcontext, krb5_preauthtype pa_type)
+{
+    return PA_REAL;
+}
+
+static krb5_error_code
+client_init(krb5_context kcontext, void **ctx)
+{
+    int *pctx;
+
+    pctx = malloc(sizeof(int));
+    if (pctx == NULL)
+	return ENOMEM;
+    *pctx = 0;
+    *ctx = pctx;
+    return 0;
+}
+
+static void
+client_fini(krb5_context kcontext, void *ctx)
+{
+    int *pctx;
+
+    pctx = ctx;
+    if (pctx) {
+#ifdef DEBUG
+        fprintf(stderr, "wpse module called total of %d times\n", *pctx);
+#endif
+        free(pctx);
+    }
+}
+
+static krb5_error_code
+client_process(krb5_context kcontext,
+	       void *plugin_context,
+	       void *request_context,
+	       krb5_get_init_creds_opt *opt,
+	       preauth_get_client_data_proc client_get_data_proc,
+	       struct _krb5_preauth_client_rock *rock,
+	       krb5_kdc_req *request,
+	       krb5_data *encoded_request_body,
+	       krb5_data *encoded_previous_request,
+	       krb5_pa_data *pa_data,
+	       krb5_prompter_fct prompter,
+	       void *prompter_data,
+	       preauth_get_as_key_proc gak_fct,
+	       void *gak_data,
+	       krb5_data *salt, krb5_data *s2kparams,
+	       krb5_keyblock *as_key,
+	       krb5_pa_data ***out_pa_data)
+{
+    krb5_pa_data **send_pa;
+    krb5_int32 nnonce, enctype;
+    krb5_keyblock *kb;
+    krb5_error_code status;
+    int *pctx;
+
+#ifdef DEBUG
+    fprintf(stderr, "%d bytes of preauthentication data (type %d)\n",
+	    pa_data->length, pa_data->pa_type);
+#endif
+
+    pctx = plugin_context;
+    if (pctx) {
+	(*pctx)++;
+    }
+
+    if (pa_data->length == 0) {
+	/* Create preauth data. */
+	send_pa = malloc(2 * sizeof(krb5_pa_data *));
+	if (send_pa == NULL)
+	    return ENOMEM;
+	send_pa[1] = NULL;  /* Terminate list */
+	send_pa[0] = malloc(sizeof(krb5_pa_data));
+	if (send_pa[0] == NULL) {
+	    free(send_pa);
+	    return ENOMEM;
+	}
+	send_pa[0]->pa_type = KRB5_PADATA_WPSE_REQ;
+	send_pa[0]->length = 4;
+	send_pa[0]->contents = malloc(4);
+	if (send_pa[0]->contents == NULL) {
+	    free(send_pa[0]);
+	    free(send_pa);
+	    return ENOMEM;
+	}
+	/* Store the preauth data. */
+	nnonce = htonl(request->nonce);
+	memcpy(send_pa[0]->contents, &nnonce, 4);
+	*out_pa_data = send_pa;
+    } else {
+	/* A reply from the KDC.  Conventionally this would be
+	 * indicated by a different preauthentication type, but this
+	 * mechanism/implementation doesn't do that. */
+	if (pa_data->length > 4) {
+	    memcpy(&enctype, pa_data->contents, 4);
+	    kb = NULL;
+	    status = krb5_init_keyblock(kcontext, ntohl(enctype),
+					pa_data->length - 4, &kb);
+	    if (status != 0)
+		return status;
+	    memcpy(kb->contents, pa_data->contents + 4, pa_data->length - 4);
+#ifdef DEBUG
+	    fprintf(stderr, "Recovered key type=%d, length=%d.\n",
+		    kb->enctype, kb->length);
+#endif
+	    status = krb5_copy_keyblock_contents(kcontext, kb, as_key);
+	    krb5_free_keyblock(kcontext, kb);
+	    return status;
+	}
+	return KRB5KRB_ERR_GENERIC;
+    }
+    return 0;
+}
+
+#define WPSE_MAGIC 0x77707365
+typedef struct _wpse_req_ctx
+{
+    int magic;
+    int value;
+} wpse_req_ctx;
+
+static void
+client_req_init(krb5_context kcontext, void *plugin_context, void **req_context_p)
+{
+    wpse_req_ctx *ctx;
+
+    *req_context_p = NULL;
+
+    /* Allocate a request context. Useful for verifying that we do in fact
+     * do per-request cleanup. */
+    ctx = (wpse_req_ctx *) malloc(sizeof(*ctx));
+    if (ctx == NULL)
+	return;
+    ctx->magic = WPSE_MAGIC;
+    ctx->value = 0xc0dec0de;
+
+    *req_context_p = ctx;
+}
+
+static void
+client_req_cleanup(krb5_context kcontext, void *plugin_context, void *req_context)
+{
+    wpse_req_ctx *ctx = (wpse_req_ctx *)req_context;
+
+    if (ctx) {
+#ifdef DEBUG
+	fprintf(stderr, "client_req_cleanup: req_ctx at %p has magic %x and value %x\n",
+		ctx, ctx->magic, ctx->value);
+#endif
+	if (ctx->magic != WPSE_MAGIC) {
+#ifdef DEBUG
+	    fprintf(stderr, "client_req_cleanup: req_context at %p has bad magic value %x\n",
+		    ctx, ctx->magic);
+#endif
+	    return;
+	}
+	free(ctx);
+    }
+    return;
+}
+
+static krb5_error_code
+client_gic_opt(krb5_context kcontext,
+	       void *plugin_context,
+	       krb5_get_init_creds_opt *opt,
+	       const char *attr,
+	       const char *value)
+{
+#ifdef DEBUG
+    fprintf(stderr, "(wpse) client_gic_opt: received '%s' = '%s'\n",
+	    attr, value);
+#endif
+    return 0;
+}
+
+
+/* Free state. */
+static krb5_error_code
+server_free_pa_request_context(krb5_context kcontext, void *plugin_context,
+			       void **request_context)
+{
+    if (*request_context != NULL) {
+	free(*request_context);
+	*request_context = NULL;
+    }
+    return 0;
+}
+
+/* Obtain and return any preauthentication data (which is destined for the
+ * client) which matches type data->pa_type. */
+static krb5_error_code
+server_get_edata(krb5_context kcontext,
+		 krb5_kdc_req *request,
+		 struct _krb5_db_entry_new *client,
+		 struct _krb5_db_entry_new *server,
+		 preauth_get_entry_data_proc server_get_entry_data,
+		 void *pa_module_context,
+		 krb5_pa_data *data)
+{
+    /* Return zero bytes of data. */
+    data->length = 0;
+    data->contents = NULL;
+    return 0;
+}
+
+/* Verify a request from a client. */
+static krb5_error_code
+server_verify(krb5_context kcontext,
+	      struct _krb5_db_entry_new *client,
+	      krb5_data *req_pkt,
+	      krb5_kdc_req *request,
+	      krb5_enc_tkt_part *enc_tkt_reply,
+	      krb5_pa_data *data,
+	      preauth_get_entry_data_proc server_get_entry_data,
+	      void *pa_module_context,
+	      void **pa_request_context,
+	      krb5_data **e_data,
+	      krb5_authdata ***authz_data)
+{
+    krb5_int32 nnonce;
+    krb5_data *test_edata;
+    krb5_authdata **my_authz_data;
+
+#ifdef DEBUG
+    fprintf(stderr, "wpse: server_verify()!\n");
+#endif
+    /* Verify the preauth data. */
+    if (data->length != 4)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    memcpy(&nnonce, data->contents, 4);
+    nnonce = ntohl(nnonce);
+    if (memcmp(&nnonce, &request->nonce, 4) != 0)
+	return KRB5KDC_ERR_PREAUTH_FAILED;
+    /* Note that preauthentication succeeded. */
+    enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
+    enc_tkt_reply->flags |= TKT_FLG_HW_AUTH;
+    /* Allocate a context. Useful for verifying that we do in fact do
+     * per-request cleanup. */
+    if (*pa_request_context == NULL)
+	*pa_request_context = malloc(4);
+
+    /*
+     * Return some junk authorization data just to exercise the
+     * code path handling the returned authorization data.
+     *
+     * NOTE that this is NOT VALID authorization data!
+     */
+#ifdef DEBUG
+    fprintf(stderr, "wpse: doing authorization data!\n");
+#endif
+#if 1 /* USE_5000_AD */
+#define AD_ALLOC_SIZE 5000
+    /* ad_header consists of a sequence tag (0x30) and length (0x82 0x1384)
+     * followed by octet string tag (0x04) and length (0x82 0x1380) */
+    krb5_octet ad_header[] = {0x30, 0x82, 0x13, 0x84, 0x04, 0x82, 0x13, 0x80};
+#else
+#define AD_ALLOC_SIZE 100
+    /* ad_header consists of a sequence tag (0x30) and length (0x62)
+     * followed by octet string tag (0x04) and length (0x60) */
+    krb5_octet ad_header[] = {0x30, 0x62, 0x04, 0x60};
+#endif
+    my_authz_data = malloc(2 * sizeof(*my_authz_data));
+    if (my_authz_data != NULL) {
+        my_authz_data[1] = NULL;
+        my_authz_data[0] = malloc(sizeof(krb5_authdata));
+        if (my_authz_data[0] == NULL) {
+            free(my_authz_data);
+            return ENOMEM;
+        }
+        my_authz_data[0]->contents = malloc(AD_ALLOC_SIZE);
+        if (my_authz_data[0]->contents == NULL) {
+            free(my_authz_data[0]);
+            free(my_authz_data);
+            return ENOMEM;
+        }
+        memset(my_authz_data[0]->contents, '\0', AD_ALLOC_SIZE);
+        my_authz_data[0]->magic = KV5M_AUTHDATA;
+        my_authz_data[0]->ad_type = 1;
+        my_authz_data[0]->length = AD_ALLOC_SIZE;
+        memcpy(my_authz_data[0]->contents, ad_header, sizeof(ad_header));
+        sprintf(my_authz_data[0]->contents + sizeof(ad_header),
+               "wpse authorization data: %d bytes worth!\n", AD_ALLOC_SIZE);
+        *authz_data = my_authz_data;
+#ifdef DEBUG
+        fprintf(stderr, "Returning %d bytes of authorization data\n",
+                AD_ALLOC_SIZE);
+#endif
+    }
+
+    /* Return edata to exercise code that handles edata... */
+    test_edata = malloc(sizeof(*test_edata));
+    if (test_edata != NULL) {
+	test_edata->data = malloc(20);
+	if (test_edata->data == NULL) {
+	    free(test_edata);
+	} else {
+	    test_edata->length = 20;
+	    memset(test_edata->data, '#', 20); /* fill it with junk */
+	    *e_data = test_edata;
+	}
+    }
+    return 0;
+}
+
+/* Create the response for a client. */
+static krb5_error_code
+server_return(krb5_context kcontext,
+	      krb5_pa_data *padata,
+	      struct _krb5_db_entry_new *client,
+	      krb5_data *req_pkt,
+	      krb5_kdc_req *request,
+	      krb5_kdc_rep *reply,
+	      struct _krb5_key_data *client_key,
+	      krb5_keyblock *encrypting_key,
+	      krb5_pa_data **send_pa,
+	      preauth_get_entry_data_proc server_get_entry_data,
+	      void *pa_module_context,
+	      void **pa_request_context)
+{
+    /* This module does a couple of dumb things.  It tags its reply with
+     * the same type as the initial challenge (expecting the client to sort
+     * out whether there's anything useful in there).  Oh, and it replaces
+     * the AS reply key with one which is sent in the clear. */
+    krb5_keyblock *kb;
+    krb5_int32 enctype;
+    int i;
+
+    *send_pa = NULL;
+
+    /* We'll want a key with the first supported enctype. */
+    for (i = 0; i < request->nktypes; i++) {
+	kb = NULL;
+	if (krb5_init_keyblock(kcontext, request->ktype[i], 0, &kb) == 0) {
+	    break;
+	}
+    }
+    if (i >= request->nktypes) {
+	/* No matching cipher type found. */
+	return 0;
+    }
+
+    /* Randomize a key and save it for the client. */
+    if (krb5_c_make_random_key(kcontext, request->ktype[i], kb) != 0) {
+	krb5_free_keyblock(kcontext, kb);
+	return 0;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "Generated random key, type=%d, length=%d.\n",
+	    kb->enctype, kb->length);
+#endif
+
+    *send_pa = malloc(sizeof(krb5_pa_data));
+    if (*send_pa == NULL) {
+	krb5_free_keyblock(kcontext, kb);
+	return ENOMEM;
+    }
+    (*send_pa)->pa_type = KRB5_PADATA_WPSE_REQ;
+    (*send_pa)->length = 4 + kb->length;
+    (*send_pa)->contents = malloc(4 + kb->length);
+    if ((*send_pa)->contents == NULL) {
+	free(*send_pa);
+	*send_pa = NULL;
+	krb5_free_keyblock(kcontext, kb);
+	return ENOMEM;
+    }
+
+    /* Store the preauth data. */
+    enctype = htonl(kb->enctype);
+    memcpy((*send_pa)->contents, &enctype, 4);
+    memcpy((*send_pa)->contents + 4, kb->contents, kb->length);
+    krb5_free_keyblock_contents(kcontext, encrypting_key);
+    krb5_copy_keyblock_contents(kcontext, kb, encrypting_key);
+
+
+    /* Clean up. */
+    krb5_free_keyblock(kcontext, kb);
+
+    return 0;
+}
+
+static int
+server_get_flags(krb5_context kcontext, krb5_preauthtype pa_type)
+{
+    return PA_HARDWARE | PA_REPLACES_KEY | PA_SUFFICIENT;
+}
+
+static krb5_preauthtype supported_client_pa_types[] = {KRB5_PADATA_WPSE_REQ, 0};
+static krb5_preauthtype supported_server_pa_types[] = {KRB5_PADATA_WPSE_REQ, 0};
+
+struct krb5plugin_preauth_client_ftable_v1 preauthentication_client_1 = {
+    "wpse",				    /* name */
+    &supported_client_pa_types[0],	    /* pa_type_list */
+    NULL,				    /* enctype_list */
+    client_init,			    /* plugin init function */
+    client_fini,			    /* plugin fini function */
+    client_get_flags,			    /* get flags function */
+    client_req_init,			    /* request init function */
+    client_req_cleanup,			    /* request fini function */
+    client_process,			    /* process function */
+    NULL,				    /* try_again function */
+    client_gic_opt			    /* get init creds opts function */
+};
+
+struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = {
+    "wpse",
+    &supported_server_pa_types[0],
+    NULL,
+    NULL,
+    server_get_flags,
+    server_get_edata,
+    server_verify,
+    server_return,
+    server_free_pa_request_context,
+};
diff --git a/krb5-1-6/src/prototype/getopt.c b/krb5-1-6/src/prototype/getopt.c
new file mode 100644
index 000000000..935f0bf5f
--- /dev/null
+++ b/krb5-1-6/src/prototype/getopt.c
@@ -0,0 +1,29 @@
+extern int optind;
+extern char *optarg;
+
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    int c;
+    int errflg = 0;
+    
+    <<<other globals here>>>;
+	
+    while ((c = getopt(argc, argv, "<<<>>>")) != -1) {
+	switch (c) {
+	    <<<add cases for arguments here>>>;
+	case '?':
+	default:
+	    errflg++;
+	    break;
+	}
+    }
+    if (errflg) {
+	fprintf(stderr, "Usage: %s <<<args>>>", argv[0]);
+	exit(2);
+    }
+    for (; optind < argc; optind++) {
+	<<<process arg optind>>>;
+    }
+}
diff --git a/krb5-1-6/src/prototype/prototype.c b/krb5-1-6/src/prototype/prototype.c
new file mode 100644
index 000000000..83e6d3726
--- /dev/null
+++ b/krb5-1-6/src/prototype/prototype.c
@@ -0,0 +1,30 @@
+/*
+ * prototype/prototype.c
+ *
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 
+ *
+ * <<< Description >>>
+ */
+
diff --git a/krb5-1-6/src/prototype/prototype.h b/krb5-1-6/src/prototype/prototype.h
new file mode 100644
index 000000000..f85d0497e
--- /dev/null
+++ b/krb5-1-6/src/prototype/prototype.h
@@ -0,0 +1,33 @@
+/*
+ * prototype/prototype.h
+ *
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * <<< Description >>>
+ */
+
+#ifndef <<< include blocker>>>__
+#define <<< include blocker>>>__
+
+#endif /* __<<< include blocker>>>__ */
diff --git a/krb5-1-6/src/slave/Makefile.in b/krb5-1-6/src/slave/Makefile.in
new file mode 100644
index 000000000..bbfa1b904
--- /dev/null
+++ b/krb5-1-6/src/slave/Makefile.in
@@ -0,0 +1,62 @@
+thisconfigdir=..
+myfulldir=slave
+mydir=slave
+BUILDTOP=$(REL)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS=
+
+all::	kprop kpropd
+
+CLIENTSRCS= $(srcdir)/kprop.c 
+CLIENTOBJS= kprop.o 
+
+SERVERSRCS= $(srcdir)/kpropd.c 
+SERVEROBJS= kpropd.o
+
+SRCS= $(CLIENTSRCS) $(SERVERSRCS)
+
+
+kprop: $(CLIENTOBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o kprop $(CLIENTOBJS) $(KRB5_BASE_LIBS) @LIBUTIL@
+
+kpropd: $(SERVEROBJS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
+	$(CC_LINK) -o kpropd $(SERVEROBJS) $(KRB5_BASE_LIBS) $(APPUTILS_LIB) @LIBUTIL@
+
+install::
+	for f in kprop kpropd; do \
+	  $(INSTALL_PROGRAM) $$f \
+		$(DESTDIR)$(SERVER_BINDIR)/`echo $$f|sed '$(transform)'`; \
+	  $(INSTALL_DATA) $(srcdir)/$$f.M \
+		${DESTDIR}$(SERVER_MANDIR)/`echo $$f|sed '$(transform)'`.8; \
+	done
+
+clean::
+	$(RM) $(CLIENTOBJS) $(SERVEROBJS)
+
+clean::
+	$(RM) kprop kpropd
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kprop.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  kprop.c kprop.h
+$(OUTPRE)kpropd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/include/syslog.h kprop.h kpropd.c
diff --git a/krb5-1-6/src/slave/kprop.M b/krb5-1-6/src/slave/kprop.M
new file mode 100644
index 000000000..0a442a21e
--- /dev/null
+++ b/krb5-1-6/src/slave/kprop.M
@@ -0,0 +1,67 @@
+.\" slave/kprop.M
+.\"
+.\" Copyright 1992 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" 
+.\"
+.TH KPROP 8
+.SH NAME
+kprop \- propagate a Kerberos V5 principal database to a slave server
+.SH SYNOPSIS
+.B kprop
+[\fB\-r\fP \fIrealm\fP] [\fB\-f\fP \fIfile\fP] [\fB\-d\fP] [\fB\-P\fP
+\fIport\fP] [\fB\-s\fP \fIkeytab\fP] 
+.I slave_host
+.br
+.SH DESCRIPTION
+.I kprop
+is used to propagate a Kerberos V5 database dump file from the master
+Kerberos server to a slave Kerberos server, which is specfied by
+.IR slave_host .  
+This is done by transmitting the dumped database file to the slave
+server over an encrypted, secure channel.  The dump file must be created
+by kdb5_util, and is normally KPROP_DEFAULT_FILE
+(/usr/local/var/krb5kdc/slave_datatrans).
+.SH OPTIONS
+.TP
+\fB\-r\fP \fIrealm\fP
+specifies the realm of the master server; by default the realm returned
+by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+\fB\-f\fP \fIfile\fP
+specifies the filename where the dumped principal database file is to be
+found; by default the dumped database file is KPROP_DEFAULT_FILE
+(normally /usr/local/var/krb5kdc/slave_datatrans).
+.TP
+\fB\-P\fP \fIport\fP
+specifies the port to use to contact the
+.I kpropd
+server on the remote host.
+.TP
+.B \-d
+prints debugging information.
+.TP
+\fB\-s\fP \fIkeytab\fP
+specifies the location of the keytab file.
+.SH SEE ALSO
+kpropd(8), kdb5_util(8), krb5kdc(8)
diff --git a/krb5-1-6/src/slave/kprop.c b/krb5-1-6/src/slave/kprop.c
new file mode 100644
index 000000000..b2ea2c2b3
--- /dev/null
+++ b/krb5-1-6/src/slave/kprop.c
@@ -0,0 +1,756 @@
+/*
+ * slave/kprop.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include <fcntl.h>
+
+#include "k5-int.h"
+#include "com_err.h"
+#include "kprop.h"
+
+#ifndef GETSOCKNAME_ARG3_TYPE
+#define GETSOCKNAME_ARG3_TYPE unsigned int
+#endif
+
+static char *kprop_version = KPROP_PROT_VERSION;
+
+char	*progname = 0;
+int     debug = 0;
+char	*srvtab = 0;
+char	*slave_host;
+char	*realm = 0;
+char	*file = KPROP_DEFAULT_FILE;
+short	port = 0;
+
+krb5_principal	my_principal;		/* The Kerberos principal we'll be */
+				/* running under, initialized in */
+				/* get_tickets() */
+krb5_ccache	ccache;		/* Credentials cache which we'll be using */
+krb5_creds	creds;
+krb5_address	sender_addr;
+krb5_address	receiver_addr;
+
+void	PRS
+	(int, char **);
+void	get_tickets
+	(krb5_context);
+static void usage 
+	(void);
+krb5_error_code open_connection 
+	(char *, int *, char *, unsigned int);
+void	kerberos_authenticate 
+	(krb5_context, krb5_auth_context *, 
+		   int, krb5_principal, krb5_creds **);
+int	open_database 
+	(krb5_context, char *, int *);
+void	close_database 
+	(krb5_context, int);
+void	xmit_database 
+	(krb5_context, krb5_auth_context, krb5_creds *, 
+		   int, int, int);
+void	send_error 
+	(krb5_context, krb5_creds *, int, char *, krb5_error_code);
+void	update_last_prop_file 
+	(char *, char *);
+
+static void usage()
+{
+	fprintf(stderr, "\nUsage: %s [-r realm] [-f file] [-d] [-P port] [-s srvtab] slave_host\n\n",
+		progname);
+	exit(1);
+}
+
+int
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	int	fd, database_fd, database_size;
+	krb5_error_code	retval;
+	krb5_context context;
+	krb5_creds *my_creds;
+	krb5_auth_context auth_context;
+	char	Errmsg[256];
+	
+	retval = krb5_init_context(&context);
+	if (retval) {
+		com_err(argv[0], retval, "while initializing krb5");
+		exit(1);
+	}
+	PRS(argc, argv);
+	get_tickets(context);
+
+	database_fd = open_database(context, file, &database_size);
+	retval = open_connection(slave_host, &fd, Errmsg, sizeof(Errmsg));
+	if (retval) {
+		com_err(progname, retval, "%s while opening connection to %s",
+			Errmsg, slave_host);
+		exit(1);
+	}
+	if (fd < 0) {
+		fprintf(stderr, "%s: %s while opening connection to %s\n",
+			progname, Errmsg, slave_host);
+		exit(1);
+	}
+	kerberos_authenticate(context, &auth_context, fd, my_principal, 
+			      &my_creds);
+	xmit_database(context, auth_context, my_creds, fd, database_fd, 
+		      database_size);
+	update_last_prop_file(slave_host, file);
+	printf("Database propagation to %s: SUCCEEDED\n", slave_host);
+	krb5_free_cred_contents(context, my_creds);
+	close_database(context, database_fd);
+	exit(0);
+}
+
+void PRS(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	register char	*word, ch;
+	
+	progname = *argv++;
+	while (--argc && (word = *argv++)) {
+		if (*word == '-') {
+			word++;
+			while (word && (ch = *word++)) {
+				switch(ch){
+				case 'r':
+					if (*word)
+						realm = word;
+					else
+						realm = *argv++;
+					if (!realm)
+						usage();
+					word = 0;
+					break;
+				case 'f':
+					if (*word)
+						file = word;
+					else
+						file = *argv++;
+					if (!file)
+						usage();
+					word = 0;
+					break;
+				case 'd':
+					debug++;
+					break;
+				case 'P':
+					if (*word)
+						port = htons(atoi(word));
+					else
+						port = htons(atoi(*argv++));
+					if (!port)
+						usage();
+					word = 0;
+					break;
+				case 's':
+					if (*word)
+						srvtab = word;
+					else
+						srvtab = *argv++;
+					if (!srvtab)
+						usage();
+					word = 0;
+					break;
+				default:
+					usage();
+				}
+				
+			}
+		} else {
+			if (slave_host)
+				usage();
+			else
+				slave_host = word;
+		}
+	}
+	if (!slave_host)
+		usage();
+}
+
+void get_tickets(context)
+    krb5_context context;
+{
+	char   buf[BUFSIZ];
+	krb5_error_code retval;
+	static char tkstring[] = "/tmp/kproptktXXXXXX";
+	krb5_keytab keytab = NULL;
+
+	/*
+	 * Figure out what tickets we'll be using to send stuff
+	 */
+	retval = krb5_sname_to_principal(context, NULL, NULL,
+					 KRB5_NT_SRV_HST, &my_principal);
+	if (retval) {
+	    com_err(progname, errno, "while setting client principal name");
+	    exit(1);
+	}
+	if (realm) {
+	    retval = krb5_set_principal_realm(context, my_principal, realm);
+	    if (retval) {
+	        com_err(progname, errno, 
+			"while setting client principal realm");
+		exit(1);
+	    }
+	}
+#if 0
+	krb5_princ_type(context, my_principal) = KRB5_NT_PRINCIPAL;
+#endif
+
+	/*
+	 * Initialize cache file which we're going to be using
+	 */
+	(void) mktemp(tkstring);
+	sprintf(buf, "FILE:%s", tkstring);
+
+	retval = krb5_cc_resolve(context, buf, &ccache);
+	if (retval) {
+		com_err(progname, retval, "while opening credential cache %s",
+			buf);
+		exit(1);
+	}
+
+	retval = krb5_cc_initialize(context, ccache, my_principal);
+	if (retval) {
+		com_err (progname, retval, "when initializing cache %s",
+			 buf);
+		exit(1);
+	}
+
+	/*
+	 * Get the tickets we'll need.
+	 *
+	 * Construct the principal name for the slave host.
+	 */
+	memset((char *)&creds, 0, sizeof(creds));
+	retval = krb5_sname_to_principal(context,
+					 slave_host, KPROP_SERVICE_NAME,
+					 KRB5_NT_SRV_HST, &creds.server);
+	if (retval) {
+	    com_err(progname, errno, "while setting server principal name");
+	    (void) krb5_cc_destroy(context, ccache);
+	    exit(1);
+	}
+	if (realm) {
+	    retval = krb5_set_principal_realm(context, creds.server, realm);
+	    if (retval) {
+	        com_err(progname, errno, 
+			"while setting server principal realm");
+		exit(1);
+	    }
+	}
+
+	/*
+	 * Now fill in the client....
+	 */
+	retval = krb5_copy_principal(context, my_principal, &creds.client);
+	if (retval) {
+		com_err(progname, retval, "While copying client principal");
+		(void) krb5_cc_destroy(context, ccache);
+		exit(1);
+	}
+	if (srvtab) {
+	        retval = krb5_kt_resolve(context, srvtab, &keytab);
+		if (retval) {
+			com_err(progname, retval, "while resolving keytab");
+			(void) krb5_cc_destroy(context, ccache);
+			exit(1);
+		}
+	}
+
+	retval = krb5_get_in_tkt_with_keytab(context, 0, 0, NULL,
+					     NULL, keytab, ccache, &creds, 0);
+	if (retval) {
+		com_err(progname, retval, "while getting initial ticket\n");
+		(void) krb5_cc_destroy(context, ccache);
+		exit(1);
+	}
+
+	if (keytab)
+	    (void) krb5_kt_close(context, keytab);
+	
+	/*
+	 * Now destroy the cache right away --- the credentials we
+	 * need will be in my_creds.
+	 */
+	retval = krb5_cc_destroy(context, ccache);
+	if (retval) {
+		com_err(progname, retval, "while destroying ticket cache");
+		exit(1);
+	}
+}
+
+krb5_error_code
+open_connection(host, fd, Errmsg, ErrmsgSz)
+	char		*host;
+	int		*fd;
+	char		*Errmsg;
+	unsigned int	 ErrmsgSz;
+{
+	int	s;
+	krb5_error_code	retval;
+	
+	struct hostent	*hp;
+	register struct servent *sp;
+	struct sockaddr_in my_sin;
+	GETSOCKNAME_ARG3_TYPE socket_length;
+
+	hp = gethostbyname(host);
+	if (hp == NULL) {
+		(void) sprintf(Errmsg, "%s: unknown host", host);
+		*fd = -1;
+		return(0);
+	}
+	my_sin.sin_family = hp->h_addrtype;
+	memcpy((char *)&my_sin.sin_addr, hp->h_addr, sizeof(my_sin.sin_addr));
+	if(!port) {
+		sp = getservbyname(KPROP_SERVICE, "tcp");
+		if (sp == 0) {
+		    my_sin.sin_port = htons(KPROP_PORT);
+		} else {
+		    my_sin.sin_port = sp->s_port;
+		}
+	} else
+		my_sin.sin_port = port;
+	s = socket(AF_INET, SOCK_STREAM, 0);
+	
+	if (s < 0) {
+		(void) sprintf(Errmsg, "in call to socket");
+		return(errno);
+	}
+	if (connect(s, (struct sockaddr *)&my_sin, sizeof my_sin) < 0) {
+		retval = errno;
+		close(s);
+		(void) sprintf(Errmsg, "in call to connect");
+		return(retval);
+	}
+	*fd = s;
+
+	/*
+	 * Set receiver_addr and sender_addr.
+	 */
+	receiver_addr.addrtype = ADDRTYPE_INET;
+	receiver_addr.length = sizeof(my_sin.sin_addr);
+	receiver_addr.contents = (krb5_octet *) malloc(sizeof(my_sin.sin_addr));
+	memcpy((char *) receiver_addr.contents, (char *) &my_sin.sin_addr,
+	       sizeof(my_sin.sin_addr));
+
+	socket_length = sizeof(my_sin);
+	if (getsockname(s, (struct sockaddr *)&my_sin, &socket_length) < 0) {
+		retval = errno;
+		close(s);
+		(void) sprintf(Errmsg, "in call to getsockname");
+		return(retval);
+	}
+	sender_addr.addrtype = ADDRTYPE_INET;
+	sender_addr.length = sizeof(my_sin.sin_addr);
+	sender_addr.contents = (krb5_octet *) malloc(sizeof(my_sin.sin_addr));
+	memcpy((char *) sender_addr.contents, (char *) &my_sin.sin_addr,
+	       sizeof(my_sin.sin_addr));
+
+	return(0);
+}
+
+
+void kerberos_authenticate(context, auth_context, fd, me, new_creds)
+    krb5_context context;
+    krb5_auth_context *auth_context;
+    int	fd;
+    krb5_principal me;
+    krb5_creds ** new_creds;
+{
+	krb5_error_code	retval;
+	krb5_error	*error = NULL;
+	krb5_ap_rep_enc_part	*rep_result;
+
+    retval = krb5_auth_con_init(context, auth_context);
+    if (retval) 
+	exit(1);
+
+    krb5_auth_con_setflags(context, *auth_context, 
+			   KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+
+    retval = krb5_auth_con_setaddrs(context, *auth_context, &sender_addr,
+				    &receiver_addr);
+    if (retval) {
+	com_err(progname, retval, "in krb5_auth_con_setaddrs");
+	exit(1);
+    }
+
+    retval = krb5_sendauth(context, auth_context, (void *)&fd, 
+			   kprop_version, me, creds.server,
+			   AP_OPTS_MUTUAL_REQUIRED, NULL, &creds, NULL,
+			   &error, &rep_result, new_creds);
+    if (retval) {
+        com_err(progname, retval, "while authenticating to server");
+	if (error) {
+	    if (error->error == KRB_ERR_GENERIC) {
+	        if (error->text.data)
+		    fprintf(stderr,
+			    "Generic remote error: %s\n",
+			    error->text.data);
+	    } else if (error->error) {
+	        com_err(progname,
+			(krb5_error_code) error->error + ERROR_TABLE_BASE_krb5,
+			"signalled from server");
+		if (error->text.data)
+		    fprintf(stderr,
+			    "Error text from server: %s\n",
+			    error->text.data);
+	    }
+	    krb5_free_error(context, error);
+	}
+	exit(1);
+    }
+    krb5_free_ap_rep_enc_part(context, rep_result);
+}
+
+char * dbpathname;
+/*
+ * Open the Kerberos database dump file.  Takes care of locking it
+ * and making sure that the .ok file is more recent that the database
+ * dump file itself.
+ *
+ * Returns the file descriptor of the database dump file.  Also fills
+ * in the size of the database file.
+ */
+int
+open_database(context, data_fn, size)
+    krb5_context context;
+    char *data_fn;
+    int	*size;
+{
+	int		fd;
+	int		err;
+	struct stat 	stbuf, stbuf_ok;
+	char		*data_ok_fn;
+	static char ok[] = ".dump_ok";
+
+	dbpathname = strdup(data_fn);
+	if (!dbpathname) {
+ 	    com_err(progname, ENOMEM, "allocating database file name '%s'",
+ 		    data_fn);
+ 	    exit(1);
+ 	}
+	if ((fd = open(dbpathname, O_RDONLY)) < 0) {
+		com_err(progname, errno, "while trying to open %s",
+			dbpathname);
+		exit(1);
+	}
+
+	err = krb5_lock_file(context, fd,
+			     KRB5_LOCKMODE_SHARED|KRB5_LOCKMODE_DONTBLOCK);
+	if (err == EAGAIN || err == EWOULDBLOCK || errno == EACCES) {
+	    com_err(progname, 0, "database locked");
+	    exit(1);
+	} else if (err) {
+	    com_err(progname, err, "while trying to lock '%s'", dbpathname);
+	    exit(1);
+	}	    
+	if (fstat(fd, &stbuf)) {
+		com_err(progname, errno, "while trying to stat %s",
+			data_fn);
+		exit(1);
+	}
+	if ((data_ok_fn = (char *) malloc(strlen(data_fn)+strlen(ok)+1))
+	    == NULL) {
+		com_err(progname, ENOMEM, "while trying to malloc data_ok_fn");
+		exit(1);
+	}
+	strcpy(data_ok_fn, data_fn);
+	strcat(data_ok_fn, ok);
+	if (stat(data_ok_fn, &stbuf_ok)) {
+		com_err(progname, errno, "while trying to stat %s",
+			data_ok_fn);
+		free(data_ok_fn);
+		exit(1);
+	}
+	free(data_ok_fn);
+	if (stbuf.st_mtime > stbuf_ok.st_mtime) {
+		com_err(progname, 0, "'%s' more recent than '%s'.",
+			data_fn, data_ok_fn);
+		exit(1);
+	}
+	*size = stbuf.st_size;
+	return(fd);
+}
+
+void
+close_database(context, fd)
+    krb5_context context;
+    int fd;
+{
+    int err;
+    err = krb5_lock_file(context, fd, KRB5_LOCKMODE_UNLOCK);
+    if (err)
+	com_err(progname, err, "while unlocking database '%s'", dbpathname);
+    free(dbpathname);
+    (void)close(fd);
+    return;
+}
+  
+/*
+ * Now we send over the database.  We use the following protocol:
+ * Send over a KRB_SAFE message with the size.  Then we send over the
+ * database in blocks of KPROP_BLKSIZE, encrypted using KRB_PRIV.
+ * Then we expect to see a KRB_SAFE message with the size sent back.
+ * 
+ * At any point in the protocol, we may send a KRB_ERROR message; this
+ * will abort the entire operation.
+ */
+void
+xmit_database(context, auth_context, my_creds, fd, database_fd, 
+	      in_database_size)
+    krb5_context context;
+    krb5_auth_context auth_context;
+    krb5_creds *my_creds;
+    int	fd;
+    int	database_fd;
+    int	in_database_size;
+{
+	krb5_int32	sent_size, n;
+	krb5_data	inbuf, outbuf;
+	char		buf[KPROP_BUFSIZ];
+	krb5_error_code	retval;
+	krb5_error	*error;
+	/* These must be 4 bytes */
+	krb5_ui_4	database_size = in_database_size; 
+	krb5_ui_4	send_size;
+
+	/*
+	 * Send over the size
+	 */
+	send_size = htonl(database_size);
+	inbuf.data = (char *) &send_size;
+	inbuf.length = sizeof(send_size); /* must be 4, really */
+	/* KPROP_CKSUMTYPE */
+	retval = krb5_mk_safe(context, auth_context, &inbuf, 
+			      &outbuf, NULL);
+	if (retval) {
+		com_err(progname, retval, "while encoding database size");
+		send_error(context, my_creds, fd, "while encoding database size", retval);
+		exit(1);
+	}
+
+	retval = krb5_write_message(context, (void *) &fd, &outbuf);
+	if (retval) {
+		krb5_free_data_contents(context, &outbuf);
+		com_err(progname, retval, "while sending database size");
+		exit(1);
+	}
+	krb5_free_data_contents(context, &outbuf);
+	/*
+	 * Initialize the initial vector.
+	 */
+	retval = krb5_auth_con_initivector(context, auth_context);
+	if (retval) {
+	    send_error(context, my_creds, fd, 
+		       "failed while initializing i_vector", retval);
+	    com_err(progname, retval, "while allocating i_vector");
+	    exit(1);
+	}
+ 
+	/*
+	 * Send over the file, block by block....
+	 */
+	inbuf.data = buf;
+	sent_size = 0;
+	while ((n = read(database_fd, buf, sizeof(buf)))) {
+		inbuf.length = n;
+		retval = krb5_mk_priv(context, auth_context, &inbuf,
+				      &outbuf, NULL);
+		if (retval) {
+			sprintf(buf,
+				"while encoding database block starting at %d",
+				sent_size);
+			com_err(progname, retval, buf);
+			send_error(context, my_creds, fd, buf, retval);
+			exit(1);
+		}
+
+		retval = krb5_write_message(context, (void *)&fd,&outbuf);
+		if (retval) {
+			krb5_free_data_contents(context, &outbuf);
+			com_err(progname, retval,
+				"while sending database block starting at %d",
+				sent_size);
+			exit(1);
+		}
+		krb5_free_data_contents(context, &outbuf);
+		sent_size += n;
+		if (debug)
+			printf("%d bytes sent.\n", sent_size);
+	}
+	if (sent_size != database_size) {
+		com_err(progname, 0, "Premature EOF found for database file!");
+		send_error(context, my_creds, fd,"Premature EOF found for database file!",
+			   KRB5KRB_ERR_GENERIC);
+		exit(1);
+	}
+
+	/*
+	 * OK, we've sent the database; now let's wait for a success
+	 * indication from the remote end.
+	 */
+	retval = krb5_read_message(context, (void *) &fd, &inbuf);
+	if (retval) {
+		com_err(progname, retval,
+			"while reading response from server");
+		exit(1);
+	}
+	/*
+	 * If we got an error response back from the server, display
+	 * the error message
+	 */
+	if (krb5_is_krb_error(&inbuf)) {
+ 	        retval = krb5_rd_error(context, &inbuf, &error);
+		if (retval) {
+			com_err(progname, retval,
+				"while decoding error response from server");
+			exit(1);
+		}
+		if (error->error == KRB_ERR_GENERIC) {
+			if (error->text.data)
+				fprintf(stderr,
+					"Generic remote error: %s\n",
+					error->text.data);
+		} else if (error->error) {
+			com_err(progname, 
+				(krb5_error_code) error->error + 
+				  ERROR_TABLE_BASE_krb5,
+				"signalled from server");
+			if (error->text.data)
+				fprintf(stderr,
+					"Error text from server: %s\n",
+					error->text.data);
+		}
+		krb5_free_error(context, error);
+		exit(1);
+	}
+
+	retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL);
+	if (retval) {
+		com_err(progname, retval,
+			"while decoding final size packet from server");
+		exit(1);
+	}
+
+	memcpy((char *)&send_size, outbuf.data, sizeof(send_size));
+	send_size = ntohl(send_size);
+	if (send_size != database_size) {
+		com_err(progname, 0,
+			"Kpropd sent database size %d, expecting %d",
+			send_size, database_size);
+		exit(1);
+	}
+	free(outbuf.data);
+	free(inbuf.data);
+}
+
+void
+send_error(context, my_creds, fd, err_text, err_code)
+    krb5_context context;
+    krb5_creds *my_creds;
+    int	fd;
+    char	*err_text;
+    krb5_error_code	err_code;
+{
+	krb5_error	error;
+	const char	*text;
+	krb5_data	outbuf;
+
+	memset((char *)&error, 0, sizeof(error));
+	krb5_us_timeofday(context, &error.ctime, &error.cusec);
+	error.server = my_creds->server;
+	error.client = my_principal;
+	error.error = err_code - ERROR_TABLE_BASE_krb5;
+	if (error.error > 127)
+		error.error = KRB_ERR_GENERIC;
+	if (err_text)
+		text = err_text;
+	else
+		text = error_message(err_code);
+	error.text.length = strlen(text) + 1;
+	error.text.data = malloc((unsigned int) error.text.length);
+	if (error.text.data) {
+		strcpy(error.text.data, text);
+		if (!krb5_mk_error(context, &error, &outbuf)) {
+			(void) krb5_write_message(context, (void *)&fd,&outbuf);
+			krb5_free_data_contents(context, &outbuf);
+		}
+		free(error.text.data);
+	}
+}
+
+void update_last_prop_file(hostname, file_name)
+	char *hostname;
+	char *file_name;
+{
+	/* handle slave locking/failure stuff */
+	char *file_last_prop;
+	int fd;
+	static char last_prop[]=".last_prop";
+
+	if ((file_last_prop = (char *)malloc(strlen(file_name) +
+					     strlen(hostname) + 1 +
+					     strlen(last_prop) + 1)) == NULL) {
+		com_err(progname, ENOMEM,
+			"while allocating filename for update_last_prop_file");
+		return;
+	}
+	strcpy(file_last_prop, file_name);
+	strcat(file_last_prop, ".");
+	strcat(file_last_prop, hostname);
+	strcat(file_last_prop, last_prop);
+	if ((fd = THREEPARAMOPEN(file_last_prop, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
+		com_err(progname, errno,
+			"while creating 'last_prop' file, '%s'",
+			file_last_prop);
+		free(file_last_prop);
+		return;
+	}
+	write(fd, "", 1);
+	free(file_last_prop);
+	close(fd);
+	return;
+}
diff --git a/krb5-1-6/src/slave/kprop.h b/krb5-1-6/src/slave/kprop.h
new file mode 100644
index 000000000..bc601de54
--- /dev/null
+++ b/krb5-1-6/src/slave/kprop.h
@@ -0,0 +1,38 @@
+/*
+ * slave/kprop.h
+ *
+ * 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ */
+
+#define KPROP_SERVICE_NAME "host"
+#define TGT_SERVICE_NAME "krbtgt"
+#define KPROP_SERVICE "krb5_prop"
+#define KPROP_PORT 754
+
+#define KPROP_PROT_VERSION "kprop5_01"
+
+#define KPROP_BUFSIZ 32768
+
+/* pathnames are in osconf.h, included via k5-int.h */
diff --git a/krb5-1-6/src/slave/kpropd.M b/krb5-1-6/src/slave/kpropd.M
new file mode 100644
index 000000000..1d53b101b
--- /dev/null
+++ b/krb5-1-6/src/slave/kpropd.M
@@ -0,0 +1,138 @@
+.\" slave/kpropd.M
+.\"
+.\" Copyright 1992 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" 
+.\"
+.TH KPROPD 8
+.SH NAME
+kpropd \- Kerberos V5 slave KDC update server
+.SH SYNOPSIS
+.B kpropd
+[
+.B \-r
+.I realm
+] [
+.B \-f
+.I slave_dumpfile
+] [
+.B \-F
+.I principal_database
+] [
+.B \-p
+.I kdb5_util_prog
+] [
+.B \-d
+] [
+.B \-S
+] [
+.B \-P
+.I port
+]
+.br
+.SH DESCRIPTION
+.I kpropd 
+is the server which accepts connections from the 
+.IR kprop (8)
+program.  
+.I kpropd 
+accepts the dumped KDC database and places it in a file, and then runs 
+.IR kdb5_util (8)
+to load the dumped database into the active database which is used by 
+.IR krb5kdc (8).
+Thus, the master Kerberos server can use 
+.IR kprop (8)
+to propagate its database to the slave slavers.  Upon a successful download 
+of the KDC database file, the slave Kerberos server will have an
+up-to-date KDC database. 
+.PP
+Normally, kpropd is invoked out of 
+.I inetd(8).  
+This is done by adding a line to the inetd.conf file which looks like
+this:
+
+kprop	stream	tcp	nowait	root	/usr/local/sbin/kpropd	kpropd
+
+However, kpropd can also run as a standalone deamon, if the
+.B \-S
+option is turned on.  This is done for debugging purposes, or if for
+some reason the system administrator just doesn't want to run it out of
+.IR inetd (8).
+.SH OPTIONS
+.TP
+\fB\-r\fP \fIrealm\fP
+specifies the realm of the master server; by default the realm returned
+by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+\fB\-f\fP \fIfile\fP
+specifies the filename where the dumped principal database file is to be
+stored; by default the dumped database file is KPROPD_DEFAULT_FILE
+(normally /usr/local/var/krb5kdc/from_master).
+.TP
+.B \-p
+allows the user to specify the pathname to the
+.IR kdb5_util (8)
+program; by default the pathname used is KPROPD_DEFAULT_KDB5_UTIL
+(normally /usr/local/sbin/kdb5_util).
+.TP
+.B \-S
+turn on standalone mode.  Normally, kpropd is invoked out of
+.IR inetd (8)
+so it expects a network connection to be passed to it from
+.I inetd (8).
+If the 
+.B \-S 
+option is specified, kpropd will put itself into the background, and
+wait for connections to the KPROP_SERVICE port (normally krb5_prop).
+.TP
+.B \-d
+turn on debug mode.  In this mode, if the
+.B \-S 
+option is selected, 
+.I kpropd
+will not detach itself from the current job and run in the background.
+Instead, it will run in the foreground and print out debugging messages
+during the database propagation.
+.TP
+.B \-P
+allow for an alternate port number for
+.I kpropd
+to listen on. This is only useful if the program is run in standalone
+mode.
+.TP
+.B \-a
+allows the user to specify the path to the
+.KR kpropd.acl
+file; by default the path used is KPROPD_ACL_FILE
+(normally /usr/local/var/krb5kdc/kpropd.acl).
+.SH FILES
+.TP "\w'kpropd.acl\ \ 'u"
+kpropd.acl
+Access file for
+.BR kpropd ;
+the default location is KPROPD_ACL_FILE (normally
+/usr/local/var/krb5kdc/kpropd.acl).
+Each entry is a line containing the principal of a host from which the
+local machine will allow Kerberos database propagation via kprop.
+.SH SEE ALSO
+kprop(8), kdb5_util(8), krb5kdc(8), inetd(8)
diff --git a/krb5-1-6/src/slave/kpropd.c b/krb5-1-6/src/slave/kpropd.c
new file mode 100644
index 000000000..77c270391
--- /dev/null
+++ b/krb5-1-6/src/slave/kpropd.c
@@ -0,0 +1,992 @@
+/*
+ * 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.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * XXX We need to modify the protocol so that an acknowledge is set
+ * after each block, instead after the entire series is sent over.
+ * The reason for this is so that error packets can get interpreted
+ * right away.  If you don't do this, the sender may never get the
+ * error packet, because it will die an EPIPE trying to complete the
+ * write...
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include <syslog.h>
+
+#include "k5-int.h"
+#include "com_err.h"
+#include <errno.h>
+
+#include "kprop.h"
+
+#ifndef GETSOCKNAME_ARG3_TYPE
+#define GETSOCKNAME_ARG3_TYPE unsigned int
+#endif
+#ifndef GETPEERNAME_ARG3_TYPE
+#define GETPEERNAME_ARG3_TYPE unsigned int
+#endif
+
+#if defined(NEED_DAEMON_PROTO)
+extern int daemon(int, int);
+#endif
+
+#define SYSLOG_CLASS LOG_DAEMON
+
+static char *kprop_version = KPROP_PROT_VERSION;
+
+char	*progname;
+int     debug = 0;
+char	*srvtab = 0;
+int	standalone = 0;
+
+krb5_principal	server;		/* This is our server principal name */
+krb5_principal	client;		/* This is who we're talking to */
+krb5_context kpropd_context;
+krb5_auth_context auth_context;
+char	*realm = NULL;		/* Our realm */
+char	*file = KPROPD_DEFAULT_FILE;
+char	*temp_file_name;
+char	*kdb5_util = KPROPD_DEFAULT_KDB5_UTIL;
+char	*kerb_database = NULL;
+char	*acl_file_name = KPROPD_ACL_FILE;
+
+krb5_address	sender_addr;
+krb5_address	receiver_addr;
+short 		port = 0;
+
+void	PRS
+	(char**);
+void	do_standalone
+	(void);
+void	doit
+	(int);
+void	kerberos_authenticate
+	(krb5_context,
+		   int,
+		   krb5_principal *,
+		   krb5_enctype *,
+		   struct sockaddr_in);
+krb5_boolean authorized_principal
+	(krb5_context,
+    		   krb5_principal,
+		   krb5_enctype);
+void	recv_database
+	(krb5_context,
+		   int,
+		   int,
+		   krb5_data *);
+void	load_database
+	(krb5_context,
+    		   char *,
+    		   char *);
+void	send_error
+	(krb5_context,
+    		   int,
+		   krb5_error_code,
+    		   char	*);
+void	recv_error
+	(krb5_context,
+    		   krb5_data *);
+
+static void usage()
+{
+	fprintf(stderr,
+		"\nUsage: %s [-r realm] [-s srvtab] [-dS] [-f slave_file]\n",
+		progname);
+	fprintf(stderr, "\t[-F kerberos_db_file ] [-p kdb5_util_pathname]\n");
+	fprintf(stderr, "\t[-P port] [-a acl_file]\n");
+	exit(1);
+}
+
+int
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	PRS(argv);
+
+	if (standalone)
+		do_standalone();
+	else
+		doit(0);
+	exit(0);
+}
+
+void do_standalone()
+{
+	struct	sockaddr_in	my_sin, frominet;
+	struct servent *sp;
+	int	finet, s;
+	GETPEERNAME_ARG3_TYPE fromlen;
+	int	ret;
+	
+	finet = socket(AF_INET, SOCK_STREAM, 0);
+	if (finet < 0) {
+		com_err(progname, errno, "while obtaining socket");
+		exit(1);
+	}
+	memset((char *) &my_sin,0, sizeof(my_sin));
+	if(!port) {
+		sp = getservbyname(KPROP_SERVICE, "tcp");
+		if (sp == NULL) {
+			com_err(progname, 0, "%s/tcp: unknown service", KPROP_SERVICE);
+			my_sin.sin_port = htons(KPROP_PORT);
+		}
+		else my_sin.sin_port = sp->s_port;
+	} else {
+		my_sin.sin_port = port;
+	}
+	my_sin.sin_family = AF_INET;
+	if ((ret = bind(finet, (struct sockaddr *) &my_sin, sizeof(my_sin))) < 0) {
+	    if (debug) {
+		int on = 1;
+		fprintf(stderr,
+			"%s: attempting to rebind socket with SO_REUSEADDR\n",
+			progname);
+		if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
+			       (char *)&on, sizeof(on)) < 0)
+		    com_err(progname, errno, "in setsockopt(SO_REUSEADDR)");
+		ret = bind(finet, (struct sockaddr *) &my_sin, sizeof(my_sin));
+	    }
+	    if (ret < 0) {
+		perror("bind");
+		com_err(progname, errno, "while binding listener socket");
+		exit(1);
+	    }
+	}
+	if (!debug)
+		daemon(1, 0);	    
+#ifdef PID_FILE
+	if ((pidfile = fopen(PID_FILE, "w")) != NULL) {
+		fprintf(pidfile, "%d\n", getpid());
+		fclose(pidfile);
+	} else
+		com_err(progname, errno,
+			"while opening pid file %s for writing", PID_FILE);
+#endif
+	if (listen(finet, 5) < 0) {
+		com_err(progname, errno, "in listen call");
+		exit(1);
+	}
+	while (1) {
+		int child_pid;
+	    
+		memset((char *)&frominet, 0, sizeof(frominet));
+		fromlen = sizeof(frominet);
+		s = accept(finet, (struct sockaddr *) &frominet, &fromlen);
+
+		if (s < 0) {
+			if (errno != EINTR)
+				com_err(progname, errno,
+					"from accept system call");
+			continue;
+		}
+		if (debug)
+			child_pid = 0;
+		else
+			child_pid = fork();
+		switch (child_pid) {
+		case -1:
+			com_err(progname, errno, "while forking");
+			exit(1);
+		case 0:
+			(void) close(finet);
+
+			doit(s);
+			close(s);
+			_exit(0);
+		default:
+			wait(0);
+			close(s);
+			
+		}
+	}
+}
+
+void doit(fd)
+	int	fd;
+{
+	struct sockaddr_in from;
+	int on = 1;
+	GETPEERNAME_ARG3_TYPE fromlen;
+	struct hostent	*hp;
+	krb5_error_code	retval;
+	krb5_data confmsg;
+	int lock_fd;
+	mode_t omask;
+	krb5_enctype etype;
+	int database_fd;
+
+	fromlen = sizeof (from);
+	if (getpeername(fd, (struct sockaddr *) &from, &fromlen) < 0) {
+		fprintf(stderr, "%s: ", progname);
+		perror("getpeername");
+		exit(1);
+	}
+	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (caddr_t) &on,
+		       sizeof (on)) < 0) {
+		com_err(progname, errno,
+			"while attempting setsockopt (SO_KEEPALIVE)");
+	}
+
+	if (!(hp = gethostbyaddr((char *) &(from.sin_addr.s_addr), fromlen,
+				 AF_INET))) {
+		syslog(LOG_INFO, "Connection from %s",
+		       inet_ntoa(from.sin_addr));
+		if (debug)
+			printf("Connection from %s\n",
+			       inet_ntoa(from.sin_addr));
+	} else {
+		syslog(LOG_INFO, "Connection from %s", hp->h_name);
+		if (debug)
+			printf("Connection from %s\n", hp->h_name);
+	}
+
+	/*
+	 * Now do the authentication
+	 */
+	kerberos_authenticate(kpropd_context, fd, &client, &etype, from);
+
+	if (!authorized_principal(kpropd_context, client, etype)) {
+		char	*name;
+
+		retval = krb5_unparse_name(kpropd_context, client, &name);
+		if (retval) {
+			com_err(progname, retval,
+				"While unparsing client name");
+			exit(1);
+		}
+		syslog(LOG_WARNING,
+		       "Rejected connection from unauthorized principal %s",
+		       name);
+		free(name);
+		exit(1);
+	}
+	omask = umask(077);
+	lock_fd = open(temp_file_name, O_RDWR|O_CREAT, 0600);
+	(void) umask(omask);
+	retval = krb5_lock_file(kpropd_context, lock_fd, 
+				KRB5_LOCKMODE_EXCLUSIVE|KRB5_LOCKMODE_DONTBLOCK);
+	if (retval) {
+	    com_err(progname, retval, "while trying to lock '%s'",
+		    temp_file_name);
+	    exit(1);
+	}
+	if ((database_fd = open(temp_file_name,
+				O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
+		com_err(progname, errno,
+			"while opening database file, '%s'",
+			temp_file_name);
+		exit(1);
+	}
+	recv_database(kpropd_context, fd, database_fd, &confmsg);
+	if (rename(temp_file_name, file)) {
+		com_err(progname, errno, "While renaming %s to %s",
+			temp_file_name, file);
+		exit(1);
+	}
+	retval = krb5_lock_file(kpropd_context, lock_fd, KRB5_LOCKMODE_SHARED);
+	if (retval) {
+	    com_err(progname, retval, "while downgrading lock on '%s'",
+		    temp_file_name);
+	    exit(1);
+	}
+	load_database(kpropd_context, kdb5_util, file);
+	retval = krb5_lock_file(kpropd_context, lock_fd, KRB5_LOCKMODE_UNLOCK);
+	if (retval) {
+	    com_err(progname, retval, "while unlocking '%s'", temp_file_name);
+	    exit(1);
+	}
+	(void)close(lock_fd);
+
+	/*
+	 * Send the acknowledgement message generated in
+	 * recv_database, then close the socket.
+	 */
+	retval = krb5_write_message(kpropd_context, (void *) &fd, &confmsg);
+	if (retval) { 
+		krb5_free_data_contents(kpropd_context, &confmsg);
+		com_err(progname, retval,
+			"while sending # of received bytes");
+		exit(1);
+	}
+	krb5_free_data_contents(kpropd_context, &confmsg);
+	if (close(fd) < 0) {
+		com_err(progname, errno,
+			"while trying to close database file");
+		exit(1);
+	}
+	
+	exit(0);
+}
+
+static void
+kpropd_com_err_proc(whoami, code, fmt, args)
+	const char	*whoami;
+	long		code;
+	const char	*fmt;
+	va_list		args;
+{
+	char	error_buf[8096];
+
+	error_buf[0] = '\0';
+	if (fmt)
+		vsprintf(error_buf, fmt, args);
+	syslog(LOG_ERR, "%s%s%s%s%s", whoami ? whoami : "", whoami ? ": " : "",
+	       code ? error_message(code) : "", code ? " " : "", error_buf);
+}
+
+void PRS(argv)
+	char	**argv;
+{
+	register char	*word, ch;
+	krb5_error_code	retval;
+	static const char	tmp[] = ".temp";
+	
+	retval = krb5_init_context(&kpropd_context);
+	if (retval) {
+		com_err(argv[0], retval, "while initializing krb5");
+		exit(1);
+	}
+
+	progname = *argv++;
+	while ((word = *argv++)) {
+		if (*word == '-') {
+			word++;
+			while (word && (ch = *word++)) {
+				switch(ch){
+				case 'f':
+					if (*word)
+						file = word;
+					else
+						file = *argv++;
+					if (!file)
+						usage();
+					word = 0;
+					break;
+				case 'F':
+					if (*word)
+						kerb_database = word;
+					else
+						kerb_database = *argv++;
+					if (!kerb_database)
+						usage();
+					word = 0;
+					break;
+				case 'p':
+					if (*word)
+						kdb5_util = word;
+					else
+						kdb5_util = *argv++;
+					if (!kdb5_util)
+						usage();
+					word = 0;
+					break;
+				case 'P':
+					if (*word)
+						port = htons(atoi(word));
+					else
+						port = htons(atoi(*argv++));
+					if (!port)
+						usage();
+					word = 0;
+					break;
+				case 'r':
+					if (*word)
+						realm = word;
+					else
+						realm = *argv++;
+					if (!realm)
+						usage();
+					word = 0;
+					break;
+				case 's':
+					if (*word)
+						srvtab = word;
+					else
+						srvtab = *argv++;
+					if (!srvtab)
+						usage();
+					word = 0;
+					break;
+				case 'd':
+					debug++;
+					break;
+				case 'S':
+					standalone++;
+					break;
+				case 'a':
+					if (*word)
+					     acl_file_name = word;
+					else
+					     acl_file_name = *argv++;
+					if (!acl_file_name)
+					     usage();
+					word = 0;
+					break;
+				default:
+					usage();
+				}
+				
+			}
+		} else
+			/* We don't take any arguments, only options */
+			usage();
+	}
+	/*
+	 * If not in debug mode, switch com_err reporting to syslog
+	 */
+	if (! debug) {
+	    openlog("kpropd", LOG_PID | LOG_ODELAY, SYSLOG_CLASS);
+	    set_com_err_hook(kpropd_com_err_proc);
+	}
+	/*
+	 * Get my hostname, so we can construct my service name
+	 */
+	retval = krb5_sname_to_principal(kpropd_context,
+					 NULL, KPROP_SERVICE_NAME,
+					 KRB5_NT_SRV_HST, &server);
+	if (retval) {
+		com_err(progname, retval,
+			"While trying to construct my service name");
+		exit(1);
+	}
+	if (realm) {
+	    retval = krb5_set_principal_realm(kpropd_context, server, realm);
+	    if (retval) {
+	        com_err(progname, errno, 
+			"while constructing my service realm");
+		exit(1);
+	    }
+	}
+	/*
+	 * Construct the name of the temporary file.
+	 */
+	if ((temp_file_name = (char *) malloc(strlen(file) +
+					       strlen(tmp) + 1)) == NULL) {
+		com_err(progname, ENOMEM,
+			"while allocating filename for temp file");
+		exit(1);
+	}
+	strcpy(temp_file_name, file);
+	strcat(temp_file_name, tmp);
+}
+
+/*
+ * Figure out who's calling on the other end of the connection....
+ */
+void
+kerberos_authenticate(context, fd, clientp, etype, my_sin)
+    krb5_context 	  context;
+    int		 	  fd;
+    krb5_principal	* clientp;
+    krb5_enctype	* etype;
+    struct sockaddr_in	  my_sin;
+{
+    krb5_error_code	  retval;
+    krb5_ticket		* ticket;
+    struct sockaddr_in	  r_sin;
+    GETSOCKNAME_ARG3_TYPE sin_length;
+    krb5_keytab		  keytab = NULL;
+
+    /*
+     * Set recv_addr and send_addr
+     */
+    sender_addr.addrtype = ADDRTYPE_INET;
+    sender_addr.length = sizeof(my_sin.sin_addr);
+    sender_addr.contents = (krb5_octet *) malloc(sizeof(my_sin.sin_addr));
+    memcpy((char *) sender_addr.contents, (char *) &my_sin.sin_addr,
+           sizeof(my_sin.sin_addr));
+
+    sin_length = sizeof(r_sin);
+    if (getsockname(fd, (struct sockaddr *) &r_sin, &sin_length)) {
+	com_err(progname, errno, "while getting local socket address");
+	exit(1);
+    }
+
+    receiver_addr.addrtype = ADDRTYPE_INET;
+    receiver_addr.length = sizeof(r_sin.sin_addr);
+    receiver_addr.contents = (krb5_octet *) malloc(sizeof(r_sin.sin_addr));
+    memcpy((char *) receiver_addr.contents, (char *) &r_sin.sin_addr,
+           sizeof(r_sin.sin_addr));
+
+    if (debug) {
+	char *name;
+
+	retval = krb5_unparse_name(context, server, &name);
+	if (retval) {
+	    com_err(progname, retval, "While unparsing client name");
+	    exit(1);
+	}
+	printf("krb5_recvauth(%d, %s, %s, ...)\n", fd, kprop_version, name);
+	free(name);
+    }
+
+    retval = krb5_auth_con_init(context, &auth_context);
+    if (retval) {
+	syslog(LOG_ERR, "Error in krb5_auth_con_ini: %s",
+	       error_message(retval));
+    	exit(1);
+    }
+
+    retval = krb5_auth_con_setflags(context, auth_context, 
+				    KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+    if (retval) {
+	syslog(LOG_ERR, "Error in krb5_auth_con_setflags: %s",
+	       error_message(retval));
+	exit(1);
+    }
+
+    retval = krb5_auth_con_setaddrs(context, auth_context, &receiver_addr,
+				    &sender_addr);
+    if (retval) {
+	syslog(LOG_ERR, "Error in krb5_auth_con_setaddrs: %s",
+	       error_message(retval));
+	exit(1);
+    }
+
+    if (srvtab) {
+        retval = krb5_kt_resolve(context, srvtab, &keytab);
+	if (retval) {
+	  syslog(LOG_ERR, "Error in krb5_kt_resolve: %s", error_message(retval));
+	  exit(1);
+	}
+    }
+
+    retval = krb5_recvauth(context, &auth_context, (void *) &fd,
+			   kprop_version, server, 0, keytab, &ticket);
+    if (retval) {
+	syslog(LOG_ERR, "Error in krb5_recvauth: %s", error_message(retval));
+	exit(1);
+    }
+
+    retval = krb5_copy_principal(context, ticket->enc_part2->client, clientp);
+    if (retval) {
+	syslog(LOG_ERR, "Error in krb5_copy_prinicpal: %s", 
+	       error_message(retval));
+	exit(1);
+    }
+
+    *etype = ticket->enc_part.enctype;
+
+    if (debug) {
+	char * name;
+	char etypebuf[100];
+
+	retval = krb5_unparse_name(context, *clientp, &name);
+	if (retval) {
+	    com_err(progname, retval, "While unparsing client name");
+	    exit(1);
+	}
+
+	retval = krb5_enctype_to_string(*etype, etypebuf, sizeof(etypebuf));
+	if (retval) {
+	    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, auth_etype)
+    krb5_context context;
+    krb5_principal p;
+    krb5_enctype auth_etype;
+{
+    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)
+	return FALSE;
+
+    acl_file = fopen(acl_file_name, "r");
+    if (!acl_file)
+	return FALSE;
+
+    while (!feof(acl_file)) {
+	if (!fgets(buf, sizeof(buf), acl_file))
+	    break;
+	end = strlen(buf) - 1;
+	if (buf[end] == '\n')
+	    buf[end] = '\0';
+	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((int) *ptr))
+		continue;
+
+	    /* otherwise, skip trailing whitespace */
+	    for (; *ptr && isspace((int) *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;
+	}
+    }
+    free(name);
+    fclose(acl_file);
+    return FALSE;
+}
+
+void
+recv_database(context, fd, database_fd, confmsg)
+    krb5_context context;
+    int	fd;
+    int	database_fd;
+    krb5_data *confmsg;
+{
+	krb5_ui_4	database_size; /* This must be 4 bytes */
+	int	received_size, n;
+	char		buf[1024];
+	krb5_data	inbuf, outbuf;
+	krb5_error_code	retval;
+
+	/*
+	 * Receive and decode size from client
+	 */
+	retval = krb5_read_message(context, (void *) &fd, &inbuf);
+	if (retval) {
+		send_error(context, fd, retval, "while reading database size");
+		com_err(progname, retval,
+			"while reading size of database from client");
+		exit(1);
+	}
+	if (krb5_is_krb_error(&inbuf))
+		recv_error(context, &inbuf);
+	retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL);
+	if (retval) {
+		send_error(context, fd, retval, 
+			   "while decoding database size");
+		krb5_free_data_contents(context, &inbuf);
+		com_err(progname, retval,
+			"while decoding database size from client");
+		exit(1);
+	}
+	memcpy((char *) &database_size, outbuf.data, sizeof(database_size));
+	krb5_free_data_contents(context, &inbuf);
+	krb5_free_data_contents(context, &outbuf);
+	database_size = ntohl(database_size);
+
+	/*
+	 * Initialize the initial vector.
+	 */
+	retval = krb5_auth_con_initivector(context, auth_context);
+	if (retval) {
+	  send_error(context, fd, retval, 
+		     "failed while initializing i_vector");
+	  com_err(progname, retval, "while initializing i_vector");
+	  exit(1);
+	}
+
+	/*
+	 * Now start receiving the database from the net
+	 */
+	received_size = 0;
+	while (received_size < database_size) {
+	        retval = krb5_read_message(context, (void *) &fd, &inbuf);
+		if (retval) {
+			sprintf(buf,
+				"while reading database block starting at offset %d",
+				received_size);
+			com_err(progname, retval, buf);
+			send_error(context, fd, retval, buf);
+			exit(1);
+		}
+		if (krb5_is_krb_error(&inbuf))
+			recv_error(context, &inbuf);
+		retval = krb5_rd_priv(context, auth_context, &inbuf, 
+				      &outbuf, NULL);
+		if (retval) {
+			sprintf(buf,
+				"while decoding database block starting at offset %d",
+				received_size);
+			com_err(progname, retval, buf);
+			send_error(context, fd, retval, buf);
+			krb5_free_data_contents(context, &inbuf);
+			exit(1);
+		}
+		n = write(database_fd, outbuf.data, outbuf.length);
+		krb5_free_data_contents(context, &inbuf);
+		krb5_free_data_contents(context, &outbuf);
+		if (n < 0) {
+			sprintf(buf,
+				"while writing database block starting at offset %d",
+				received_size);
+			send_error(context, fd, errno, buf);
+		} else if (n != outbuf.length) {
+			sprintf(buf,
+				"incomplete write while writing database block starting at \noffset %d (%d written, %d expected)",
+				received_size, n, outbuf.length);
+			send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
+		}
+		received_size += outbuf.length;
+	}
+	/*
+	 * OK, we've seen the entire file.  Did we get too many bytes?
+	 */
+	if (received_size > database_size) {
+		sprintf(buf,
+			"Received %d bytes, expected %d bytes for database file",
+			received_size, database_size);
+		send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
+	}
+	/*
+	 * Create message acknowledging number of bytes received, but
+	 * don't send it until kdb5_util returns successfully.
+	 */
+	database_size = htonl(database_size);
+	inbuf.data = (char *) &database_size;
+	inbuf.length = sizeof(database_size);
+	retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL);
+	if (retval) {
+		com_err(progname, retval,
+			"while encoding # of receieved bytes");
+		send_error(context, fd, retval,
+			   "while encoding # of received bytes");
+		exit(1);
+	}
+}
+
+
+void
+send_error(context, fd, err_code, err_text)
+    krb5_context context;
+    int	fd;
+    krb5_error_code	err_code;
+    char	*err_text;
+{
+	krb5_error	error;
+	const char	*text;
+	krb5_data	outbuf;
+	char		buf[1024];
+
+	memset((char *)&error, 0, sizeof(error));
+	krb5_us_timeofday(context, &error.stime, &error.susec);
+	error.server = server;
+	error.client = client;
+	
+	if (err_text)
+		text = err_text;
+	else
+		text = error_message(err_code);
+	
+	error.error = err_code - ERROR_TABLE_BASE_krb5;
+	if (error.error > 127) {
+		error.error = KRB_ERR_GENERIC;
+		if (err_text) {
+			sprintf(buf, "%s %s", error_message(err_code),
+				err_text);
+			text = buf;
+		}
+	} 
+	error.text.length = strlen(text) + 1;
+	error.text.data = malloc(error.text.length);
+	if (error.text.data) {
+		strcpy(error.text.data, text);
+		if (!krb5_mk_error(context, &error, &outbuf)) {
+			(void) krb5_write_message(context, (void *)&fd,&outbuf);
+			krb5_free_data_contents(context, &outbuf);
+		}
+		free(error.text.data);
+	}
+}
+
+void
+recv_error(context, inbuf)
+    krb5_context context;
+    krb5_data	*inbuf;
+{
+	krb5_error	*error;
+	krb5_error_code	retval;
+
+	retval = krb5_rd_error(context, inbuf, &error);
+	if (retval) {
+		com_err(progname, retval,
+			"while decoding error packet from client");
+		exit(1);
+	}
+	if (error->error == KRB_ERR_GENERIC) {
+		if (error->text.data)
+			fprintf(stderr,
+				"Generic remote error: %s\n",
+				error->text.data);
+	} else if (error->error) {
+		com_err(progname, 
+			(krb5_error_code) error->error + ERROR_TABLE_BASE_krb5,
+			"signalled from server");
+		if (error->text.data)
+			fprintf(stderr,
+				"Error text from client: %s\n",
+				error->text.data);
+	}
+	krb5_free_error(context, error);
+	exit(1);
+}
+
+void
+load_database(context, kdb_util, database_file_name)
+    krb5_context context;
+    char *kdb_util;
+    char *database_file_name;
+{
+	static char	*edit_av[10];
+	int	error_ret, save_stderr = -1;
+	int	child_pid;
+	int 	count;
+
+	/* <sys/param.h> has been included, so BSD will be defined on
+	   BSD systems */
+#if BSD > 0 && BSD <= 43
+#ifndef WEXITSTATUS
+#define	WEXITSTATUS(w) (w).w_retcode
+#endif
+	union wait	waitb;
+#else
+	int	waitb;
+#endif
+	krb5_error_code	retval;
+
+	if (debug)
+		printf("calling kdb5_util to load database\n");
+
+	edit_av[0] = kdb_util;
+	count = 1;
+	if (realm) {
+		edit_av[count++] = "-r";	
+		edit_av[count++] = realm;	
+	}
+	edit_av[count++] = "load";
+	if (kerb_database) {
+		edit_av[count++] = "-d";
+		edit_av[count++] = kerb_database;
+	}
+	edit_av[count++] = database_file_name;
+	edit_av[count++] = NULL;
+
+	switch(child_pid = fork()) {
+	case -1:
+		com_err(progname, errno, "while trying to fork %s",
+			kdb_util);
+		exit(1);
+	case 0:
+		if (!debug) {
+			save_stderr = dup(2);
+			close(0);
+			close(1);
+			close(2);
+			open("/dev/null", O_RDWR);
+			dup(0);
+			dup(0);
+		}
+
+		execv(kdb_util, edit_av);
+		retval = errno;
+		if (!debug)
+			dup2(save_stderr, 2);
+		com_err(progname, retval, "while trying to exec %s",
+			kdb_util);
+		_exit(1);
+		/*NOTREACHED*/
+	default:
+		if (debug)
+		    printf("Child PID is %d\n", child_pid);
+		if (wait(&waitb) < 0) {
+			com_err(progname, errno, "while waiting for %s",
+				kdb_util);
+			exit(1);
+		}
+	}
+	
+	error_ret = WEXITSTATUS(waitb);
+	if (error_ret) {
+		com_err(progname, 0, "%s returned a bad exit status (%d)",
+			kdb_util, error_ret);
+		exit(1);
+	}
+	return;
+}
diff --git a/krb5-1-6/src/slave/kslave_update b/krb5-1-6/src/slave/kslave_update
new file mode 100644
index 000000000..a4da274ff
--- /dev/null
+++ b/krb5-1-6/src/slave/kslave_update
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Propagate if database (principal.db) has been modified since last dump
+# (dumpfile.dump_ok) or if database has been dumped since last successful
+# propagation (dumpfile.<slave machine>.last_prop)
+
+KDB_DIR=/usr/local/var/krb5kdc
+
+KDB_FILE=$KDB_DIR/principal.db
+DUMPFILE=$KDB_DIR/slave_datatrans
+KDB5_UTIL=/usr/local/sbin/kdb5_util
+KPROP=/usr/local/sbin/kprop
+
+SLAVE=$1
+if [ -z "${SLAVE}" ]
+then 
+  echo "Usage $0 slave_server"
+fi
+
+if [ "`ls -t $DUMPFILE.dump_ok $KDB_FILE | sed -n 1p`"  = "$KDB_FILE" -o \
+     "`ls -t $DUMPFILE.${SLAVE}.last_prop $DUMPFILE.dump_ok | \
+		sed -n 1p`"  = "$DUMPFILE.dump_ok" ]
+then
+
+	date
+	$KDB5_EDIT dump $DUMPFILE > /dev/null
+
+	$KPROP -d -f $DUMPFILE ${SLAVE}
+	rm $DUMPFILE
+fi
diff --git a/krb5-1-6/src/t_krbconf b/krb5-1-6/src/t_krbconf
new file mode 100644
index 000000000..caca81d03
--- /dev/null
+++ b/krb5-1-6/src/t_krbconf
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Copyright 2003 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+echo "Testing if krb5-config outputs shell variables"
+echo "  Testing --libs argument"
+if `./krb5-config --libs kdb | egrep -s '\\$'`; then 
+	echo "Error './krb5-config --libs kdb' contains shell variables"; 
+	exit 1; 
+fi
+
+echo "  Testing --cflags argument"
+if `./krb5-config --cflags | egrep -s '\\$'`; then \
+	echo "Error './krb5-config --cflags' contains shell variables"; \
+	exit 1; \
+fi
+echo "krb5-config tests pass"
+exit 0
diff --git a/krb5-1-6/src/tests/Makefile.in b/krb5-1-6/src/tests/Makefile.in
new file mode 100644
index 000000000..89cbb042b
--- /dev/null
+++ b/krb5-1-6/src/tests/Makefile.in
@@ -0,0 +1,68 @@
+thisconfigdir=.
+mydir=.
+myfulldir=tests
+BUILDTOP=$(REL)..
+LOCAL_SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \
+	gss-threads misc
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf
+KRB5_RUN_ENV= @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+TEST_DB = ./testdb
+TEST_REALM = FOO.TEST.REALM
+TEST_MKEY = footes
+TEST_NUM = 65
+TEST_DEPTH = 5
+TEST_PREFIX = "foo bar"
+
+KADMIN_OPTS= -d $(TEST_DB) -r $(TEST_REALM) -P $(TEST_MKEY)
+KTEST_OPTS= $(KADMIN_OPTS) -p $(TEST_PREFIX) -n $(TEST_NUM) -D $(TEST_DEPTH)
+
+check-unix:: kdb_check
+
+kdc.conf: Makefile
+	rm -rf kdc.conf
+	@echo "[realms]" > kdc.conf
+	@echo "$(TEST_REALM) = {" >> kdc.conf
+	@echo "  key_stash_file = `pwd`/stash_file" >> kdc.conf
+	@echo "}" >> kdc.conf
+
+krb5.conf: Makefile
+	cat $(SRCTOP)/config-files/krb5.conf > krb5.new
+	echo "[dbmodules]" >> krb5.new
+	echo " db_module_dir = `pwd`/../util/fakedest$(KRB5_DB_MODULE_DIR)" >> krb5.new
+	mv krb5.new krb5.conf
+
+kdb_check: kdc.conf krb5.conf
+	$(RM) $(TEST_DB)*
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) create
+	$(RUN_SETUP) $(VALGRIND) ../tests/create/kdb5_mkdums $(KTEST_OPTS) 
+	$(RUN_SETUP) $(VALGRIND) ../tests/verify/kdb5_verify $(KTEST_OPTS) 
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) dump $(TEST_DB).dump
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) dump -ov $(TEST_DB).ovdump
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f
+	@echo "====> NOTE!"
+	@echo "The following 'create' command is needed due to a change"
+	@echo "in functionality caused by DAL integration.  See ticket 3973."
+	@echo ====
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) create
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) load $(TEST_DB).dump 
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) load -update -ov $(TEST_DB).ovdump 
+	$(RUN_SETUP) $(VALGRIND) ../tests/verify/kdb5_verify $(KTEST_OPTS) 
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) dump $(TEST_DB).dump2
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) dump -ov $(TEST_DB).ovdump2
+	sort $(TEST_DB).dump > $(TEST_DB).sort
+	sort $(TEST_DB).dump2 > $(TEST_DB).sort2
+	sort $(TEST_DB).ovdump > $(TEST_DB).ovsort
+	sort $(TEST_DB).ovdump2 > $(TEST_DB).ovsort2
+	cmp $(TEST_DB).sort $(TEST_DB).sort2
+	cmp $(TEST_DB).ovsort $(TEST_DB).ovsort2
+	$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f
+	$(RM) $(TEST_DB)* stash_file
+
+clean::
+	$(RM) kdc.conf
+
+
diff --git a/krb5-1-6/src/tests/asn.1/Makefile.in b/krb5-1-6/src/tests/asn.1/Makefile.in
new file mode 100644
index 000000000..ef9f9720f
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/Makefile.in
@@ -0,0 +1,106 @@
+thisconfigdir=./..
+myfulldir=tests/asn.1
+mydir=asn.1
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@
+
+SRCS= $(srcdir)/krb5_encode_test.c $(srcdir)/krb5_encode_test.c \
+	$(srcdir)/ktest.c $(srcdir)/ktest_equal.c $(srcdir)/utility.c \
+	$(srcdir)/trval.c
+
+all:: krb5_encode_test krb5_decode_test trval
+
+LOCALINCLUDES = -I$(srcdir)/../../lib/krb5/asn.1
+
+ENCOBJS = krb5_encode_test.o ktest.o ktest_equal.o utility.o trval.o
+
+krb5_encode_test: $(ENCOBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o krb5_encode_test $(ENCOBJS) $(KRB5_BASE_LIBS)
+
+DECOBJS = krb5_decode_test.o ktest.o ktest_equal.o utility.o
+
+krb5_decode_test: $(DECOBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o krb5_decode_test $(DECOBJS) $(KRB5_BASE_LIBS)
+
+trval: $(srcdir)/trval.c
+	$(CC) -o trval $(ALL_CFLAGS) -DSTANDALONE $(srcdir)/trval.c
+
+check:: krb5_decode_test krb5_encode_test
+	KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; \
+		export KRB5_CONFIG ;\
+		$(RUN_SETUP) $(VALGRIND) ./krb5_decode_test
+	$(RM) test.out
+	KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; \
+		export KRB5_CONFIG ;\
+		$(RUN_SETUP) $(VALGRIND) ./krb5_encode_test > test.out
+	cmp test.out $(srcdir)/reference_encode.out
+	KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; \
+		export KRB5_CONFIG ;\
+		$(RUN_SETUP) $(VALGRIND) ./krb5_encode_test -t > test.out
+	cmp test.out $(srcdir)/trval_reference.out
+	$(RM) test.out	
+
+install::
+
+clean::
+	rm -f *~ *.o krb5_encode_test krb5_decode_test test.out trval
+
+
+################ Dependencies ################
+krb5_decode_test.o: ktest.h utility.h ktest_equal.h debug.h
+krb5_encode_test.o: utility.h ktest.h debug.h
+trval.o: trval.c
+ktest.o: ktest.h utility.h
+ktest_equal.o: ktest_equal.h
+#utility.o: utility.h
+#utility.h: krbasn1.h asn1buf.h
+##############################################
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)krb5_encode_test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/lib/krb5/asn.1/asn1buf.h $(SRCTOP)/lib/krb5/asn.1/krbasn1.h \
+  debug.h krb5_encode_test.c ktest.h utility.h
+$(OUTPRE)ktest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/lib/krb5/asn.1/asn1buf.h $(SRCTOP)/lib/krb5/asn.1/krbasn1.h \
+  ktest.c ktest.h utility.h
+$(OUTPRE)ktest_equal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  ktest_equal.c ktest_equal.h
+$(OUTPRE)utility.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  $(SRCTOP)/lib/krb5/asn.1/asn1buf.h $(SRCTOP)/lib/krb5/asn.1/krbasn1.h \
+  utility.c utility.h
+$(OUTPRE)trval.$(OBJEXT): trval.c
diff --git a/krb5-1-6/src/tests/asn.1/README b/krb5-1-6/src/tests/asn.1/README
new file mode 100644
index 000000000..2c0c09809
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/README
@@ -0,0 +1,28 @@
+krb5_encode_test runs through all the functions declared in
+ src/include/krb5/asn.1/krb5_encode.h.  It passes various sample
+ inputs to each function and prints the result to standard
+ output.  This output should match the contents of the file
+ "reference_encode.out".
+
+ Each function is first run with a relatively simple, contrived
+ sample structure.  Then if the structure has any optional parts,
+ these parts are cleared and another run is made.
+
+ Some structures (namely, those containing a krb5_kdc_req_body)
+ have a third run, due to the fact that two of the kdc_req_body's
+ optional fields have mutually exclusive conditions under which
+ they may be omitted.
+
+
+krb5_decode_test runs through all the functions declared in
+ src/include/krb5/asn.1/krb5_decode.h.  It has the encodings in
+ reference_encode.out hard-coded into itself.  It sets up the
+ krb5 structures the same way krb5_encode_test does, then passes
+ its hard-coded encoding strings through the krb5 decoders.
+ 
+ The outputs of these functions are compared to the previously
+ set-up structures in memory, and the results are reported to
+ standard output.  If every line comes out prefixed by "OK: ",
+ then the decoders are working properly.  If any decoder produces
+ an anomalous output, then its output line will be prefixed by
+ "ERROR: "
diff --git a/krb5-1-6/src/tests/asn.1/debug.h b/krb5-1-6/src/tests/asn.1/debug.h
new file mode 100644
index 000000000..0929962e7
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/debug.h
@@ -0,0 +1,20 @@
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+/*
+   assert utility macro for test programs:
+   If the predicate (pred) is true, then
+   OK: <message> is printed.  Otherwise,
+   ERROR: <message> is printed.
+
+   message should be a printf format string.
+*/
+
+#include <stdio.h>
+
+#define test(pred,message)\
+  if(pred) printf("OK: ");\
+  else { printf("ERROR: "); error_count++; }\
+  printf(message);
+
+#endif
diff --git a/krb5-1-6/src/tests/asn.1/krb5_decode_test.c b/krb5-1-6/src/tests/asn.1/krb5_decode_test.c
new file mode 100644
index 000000000..0ff934354
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/krb5_decode_test.c
@@ -0,0 +1,904 @@
+#include "k5-int.h"
+#include "ktest.h"
+#include "com_err.h"
+#include "utility.h"
+#include "ktest_equal.h"
+
+#include "debug.h"
+#include <string.h>
+
+krb5_context test_context;
+int error_count = 0;
+
+void krb5_ktest_free_alt_method(krb5_context context, krb5_alt_method *val);
+void krb5_ktest_free_pwd_sequence(krb5_context context, 
+				  passwd_phrase_element *val);
+void krb5_ktest_free_enc_data(krb5_context context, krb5_enc_data *val);
+
+int main(argc, argv)
+	int argc;
+	char **argv;
+{
+  krb5_data code;
+  krb5_error_code retval;
+  
+  retval = krb5_init_context(&test_context);
+  if (retval) {
+	  com_err(argv[0], retval, "while initializing krb5");
+	  exit(1);
+  }
+  
+
+#define setup(type,typestring,constructor)\
+  type ref, *var;\
+  retval = constructor(&ref);\
+  if(retval){\
+    com_err("krb5_decode_test", retval, "while making sample %s", typestring);\
+    exit(1);\
+  }
+
+#define decode_run(typestring,description,encoding,decoder,comparator,cleanup)\
+    retval = krb5_data_hex_parse(&code,encoding);\
+    if(retval){\
+      com_err("krb5_decode_test", retval, "while parsing %s", typestring);\
+      exit(1);\
+    }\
+    retval = decoder(&code,&var);\
+    if(retval){\
+      com_err("krb5_decode_test", retval, "while decoding %s", typestring);\
+      error_count++;\
+    }\
+    test(comparator(&ref,var),typestring);\
+    printf("%s\n",description);\
+    krb5_free_data_contents(test_context, &code);\
+    cleanup(test_context, var);
+
+  /****************************************************************/
+  /* decode_krb5_authenticator */
+  {
+    setup(krb5_authenticator,"krb5_authenticator",ktest_make_sample_authenticator);
+
+    decode_run("authenticator","","62 81 A1 30 81 9E A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A7 03 02 01 11 A8 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72",decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xffffff80;
+    decode_run("authenticator","(80 -> seq-number 0xffffff80)",
+	       "62 81 A1 30 81 9E"
+	       "   A0 03 02 01 05"
+	       "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+	       "   A2 1A 30 18"
+	       "      A0 03 02 01 01"
+	       "      A1 11 30 0F"
+	       "         1B 06 68 66 74 73 61 69"
+	       "         1B 05 65 78 74 72 61"
+	       "   A3 0F 30 0D"
+	       "      A0 03 02 01 01"
+	       "      A1 06 04 04 31 32 33 34"
+	       "   A4 05 02 03 01 E2 40"
+	       "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+	       "   A6 13 30 11"
+	       "      A0 03 02 01 01"
+	       "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+	       "   A7 03 02 01 80"
+	       "   A8 24 30 22"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xffffffff;
+    decode_run("authenticator","(FF -> seq-number 0xffffffff)",
+	       "62 81 A1 30 81 9E"
+	       "   A0 03 02 01 05"
+	       "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+	       "   A2 1A 30 18"
+	       "      A0 03 02 01 01"
+	       "      A1 11 30 0F"
+	       "         1B 06 68 66 74 73 61 69"
+	       "         1B 05 65 78 74 72 61"
+	       "   A3 0F 30 0D"
+	       "      A0 03 02 01 01"
+	       "      A1 06 04 04 31 32 33 34"
+	       "   A4 05 02 03 01 E2 40"
+	       "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+	       "   A6 13 30 11"
+	       "      A0 03 02 01 01"
+	       "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+	       "   A7 03 02 01 FF"
+	       "   A8 24 30 22"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xff;
+    decode_run("authenticator","(00FF -> seq-number 0xff)",
+	       "62 81 A2 30 81 9F"
+	       "   A0 03 02 01 05"
+	       "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+	       "   A2 1A 30 18"
+	       "      A0 03 02 01 01"
+	       "      A1 11 30 0F"
+	       "         1B 06 68 66 74 73 61 69"
+	       "         1B 05 65 78 74 72 61"
+	       "   A3 0F 30 0D"
+	       "      A0 03 02 01 01"
+	       "      A1 06 04 04 31 32 33 34"
+	       "   A4 05 02 03 01 E2 40"
+	       "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+	       "   A6 13 30 11"
+	       "      A0 03 02 01 01"
+	       "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+	       "   A7 04 02 02 00 FF"
+	       "   A8 24 30 22"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xffffffff;
+    decode_run("authenticator","(00FFFFFFFF -> seq-number 0xffffffff)",
+	       "62 81 A5 30 81 A2"
+	       "   A0 03 02 01 05"
+	       "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+	       "   A2 1A 30 18"
+	       "      A0 03 02 01 01"
+	       "      A1 11 30 0F"
+	       "         1B 06 68 66 74 73 61 69"
+	       "         1B 05 65 78 74 72 61"
+	       "   A3 0F 30 0D"
+	       "      A0 03 02 01 01"
+	       "      A1 06 04 04 31 32 33 34"
+	       "   A4 05 02 03 01 E2 40"
+	       "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+	       "   A6 13 30 11"
+	       "      A0 03 02 01 01"
+	       "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+	       "   A7 07 02 05 00 FF FF FF FF"
+	       "   A8 24 30 22"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0x7fffffff;
+    decode_run("authenticator","(7FFFFFFF -> seq-number 0x7fffffff)",
+	       "62 81 A4 30 81 A1"
+	       "   A0 03 02 01 05"
+	       "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+	       "   A2 1A 30 18"
+	       "      A0 03 02 01 01"
+	       "      A1 11 30 0F"
+	       "         1B 06 68 66 74 73 61 69"
+	       "         1B 05 65 78 74 72 61"
+	       "   A3 0F 30 0D"
+	       "      A0 03 02 01 01"
+	       "      A1 06 04 04 31 32 33 34"
+	       "   A4 05 02 03 01 E2 40"
+	       "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+	       "   A6 13 30 11"
+	       "      A0 03 02 01 01"
+	       "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+	       "   A7 06 02 04 7F FF FF FF"
+	       "   A8 24 30 22"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xffffffff;
+    decode_run("authenticator","(FFFFFFFF -> seq-number 0xffffffff)",
+	       "62 81 A4 30 81 A1"
+	       "   A0 03 02 01 05"
+	       "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+	       "   A2 1A 30 18"
+	       "      A0 03 02 01 01"
+	       "      A1 11 30 0F"
+	       "         1B 06 68 66 74 73 61 69"
+	       "         1B 05 65 78 74 72 61"
+	       "   A3 0F 30 0D"
+	       "      A0 03 02 01 01"
+	       "      A1 06 04 04 31 32 33 34"
+	       "   A4 05 02 03 01 E2 40"
+	       "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+	       "   A6 13 30 11"
+	       "      A0 03 02 01 01"
+	       "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+	       "   A7 06 02 04 FF FF FF FF"
+	       "   A8 24 30 22"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       "      30 0F"
+	       "         A0 03 02 01 01"
+	       "         A1 08 04 06 66 6F 6F 62 61 72"
+	       ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ktest_destroy_checksum(&(ref.checksum));
+    ktest_destroy_keyblock(&(ref.subkey));
+    ref.seq_number = 0;
+    ktest_empty_authorization_data(ref.authorization_data);
+    decode_run("authenticator","(optionals empty)","62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ktest_destroy_authorization_data(&(ref.authorization_data));
+    
+    decode_run("authenticator","(optionals NULL)","62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ktest_empty_authenticator(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_ticket */
+  {
+    setup(krb5_ticket,"krb5_ticket",ktest_make_sample_ticket);
+    decode_run("ticket","","61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_ticket,ktest_equal_ticket,krb5_free_ticket);
+    decode_run("ticket","(+ trailing [4] INTEGER","61 61 30 5F A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A4 03 02 01 01",decode_krb5_ticket,ktest_equal_ticket,krb5_free_ticket);
+
+/*
+  "61 80 30 80 "
+  "  A0 03 02 01 05 "
+  "  A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 "
+  "  A2 80 30 80 "
+  "    A0 03 02 01 01 "
+  "    A1 80 30 80 "
+  "      1B 06 68 66 74 73 61 69 "
+  "      1B 05 65 78 74 72 61 "
+  "    00 00 00 00 "
+  "  00 00 00 00 "
+  "  A3 80 30 80 "
+  "    A0 03 02 01 00 "
+  "    A1 03 02 01 05 "
+  "    A2 17 04 15 6B 72 62 41 53 4E 2E 31 "
+  "      20 74 65 73 74 20 6D 65 73 73 61 67 65 "
+  "  00 00 00 00"
+  "00 00 00 00"
+*/
+    decode_run("ticket","(indefinite lengths)", "61 80 30 80 A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A3 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 00 00 00 00" ,decode_krb5_ticket,ktest_equal_ticket,krb5_free_ticket);
+/*
+  "61 80 30 80 "
+  "  A0 03 02 01 05 "
+  "  A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 "
+  "  A2 80 30 80 "
+  "    A0 03 02 01 01 "
+  "    A1 80 30 80 "
+  "      1B 06 68 66 74 73 61 69 "
+  "      1B 05 65 78 74 72 61 "
+  "    00 00 00 00 "
+  "  00 00 00 00 "
+  "  A3 80 30 80 "
+  "    A0 03 02 01 00 "
+  "    A1 03 02 01 05 "
+  "    A2 17 04 15 6B 72 62 41 53 4E 2E 31 "
+  "      20 74 65 73 74 20 6D 65 73 73 61 67 65 "
+  "  00 00 00 00"
+  "  A4 03 02 01 01 "
+  "00 00 00 00"
+*/
+    decode_run("ticket","(indefinite lengths + trailing [4] INTEGER)", "61 80 30 80 A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A3 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 A4 03 02 01 01 00 00 00 00",decode_krb5_ticket,ktest_equal_ticket,krb5_free_ticket);
+
+    ktest_empty_ticket(&ref);
+
+  }
+
+  /****************************************************************/
+  /* decode_krb5_encryption_key */
+  {
+    setup(krb5_keyblock,"krb5_keyblock",ktest_make_sample_keyblock);
+
+    decode_run("encryption_key","","30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+
+    decode_run("encryption_key","(+ trailing [2] INTEGER)","30 16 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 03 02 01 01",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    decode_run("encryption_key","(+ trailing [2] SEQUENCE {[0] INTEGER})","30 1A A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 07 30 05 A0 03 02 01 01",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    decode_run("encryption_key","(indefinite lengths)","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 00 00",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    decode_run("encryption_key","(indefinite lengths + trailing [2] INTEGER)","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 03 02 01 01 00 00",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    decode_run("encryption_key","(indefinite lengths + trailing [2] SEQUENCE {[0] INTEGER})","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 80 30 80 A0 03 02 01 01 00 00 00 00 00 00",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    decode_run("encryption_key","(indefinite lengths + trailing SEQUENCE {[0] INTEGER})","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 30 80 A0 03 02 01 01 00 00 00 00",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    ref.enctype = -1;
+    decode_run("encryption_key","(enctype = -1)","30 11 A0 03 02 01 FF A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    ref.enctype = -255;
+    decode_run("encryption_key","(enctype = -255)","30 12 A0 04 02 02 FF 01 A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    ref.enctype = 255;
+    decode_run("encryption_key","(enctype = 255)","30 12 A0 04 02 02 00 FF A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    ref.enctype = -2147483648;
+    decode_run("encryption_key","(enctype = -2147483648)","30 14 A0 06 02 04 80 00 00 00 A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+    ref.enctype = 2147483647;
+    decode_run("encryption_key","(enctype = 2147483647)","30 14 A0 06 02 04 7F FF FF FF A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock);
+
+    ktest_empty_keyblock(&ref);
+  }  
+  
+  /****************************************************************/
+  /* decode_krb5_enc_tkt_part */
+  {
+    setup(krb5_enc_tkt_part,"krb5_enc_tkt_part",ktest_make_sample_enc_tkt_part);
+    decode_run("enc_tkt_part","","63 82 01 14 30 82 01 10 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part);
+  
+    /* ref.times.starttime = 0; */
+    ref.times.starttime = ref.times.authtime;
+    ref.times.renew_till = 0;
+    ktest_destroy_address(&(ref.caddrs[1]));
+    ktest_destroy_address(&(ref.caddrs[0]));
+    ktest_destroy_authdata(&(ref.authorization_data[1]));
+    ktest_destroy_authdata(&(ref.authorization_data[0]));
+    /* ISODE version fails on the empty caddrs field */
+    ktest_destroy_addresses(&(ref.caddrs));
+    ktest_destroy_authorization_data(&(ref.authorization_data));
+  
+    decode_run("enc_tkt_part","(optionals NULL)","63 81 A5 30 81 A2 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part, krb5_free_enc_tkt_part);
+
+    decode_run("enc_tkt_part","(optionals NULL + bitstring enlarged to 38 bits)","63 81 A6 30 81 A3 A0 08 03 06 02 FE DC BA 98 DC A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part);
+
+    decode_run("enc_tkt_part","(optionals NULL + bitstring enlarged to 40 bits)","63 81 A6 30 81 A3 A0 08 03 06 00 FE DC BA 98 DE A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part);
+
+    decode_run("enc_tkt_part","(optionals NULL + bitstring reduced to 29 bits)","63 81 A5 30 81 A2 A0 07 03 05 03 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part);
+
+    ref.flags &= 0xFFFFFF00;
+
+    decode_run("enc_tkt_part","(optionals NULL + bitstring reduced to 24 bits)","63 81 A4 30 81 A1 A0 06 03 04 00 FE DC BA A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part);
+
+    ktest_empty_enc_tkt_part(&ref);
+  }  
+  
+  /****************************************************************/
+  /* decode_krb5_enc_kdc_rep_part */
+  {
+    setup(krb5_enc_kdc_rep_part,"krb5_enc_kdc_rep_part",ktest_make_sample_enc_kdc_rep_part);
+  
+#ifdef KRB5_GENEROUS_LR_TYPE
+    decode_run("enc_kdc_rep_part","(compat_lr_type)","7A 82 01 10 30 82 01 0C A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 38 30 36 30 19 A0 04 02 02 00 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 19 A0 04 02 02 00 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A4 07 03 05 00 FE DC BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_kdc_rep_part,ktest_equal_enc_kdc_rep_part,krb5_free_enc_kdc_rep_part);
+#endif
+  
+    decode_run("enc_kdc_rep_part","","7A 82 01 0E 30 82 01 0A A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A4 07 03 05 00 FE DC BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_kdc_rep_part,ktest_equal_enc_kdc_rep_part,krb5_free_enc_kdc_rep_part);
+  
+    ref.key_exp = 0;
+    /* ref.times.starttime = 0;*/
+    ref.times.starttime = ref.times.authtime;
+    ref.times.renew_till = 0;
+    ref.flags &= ~TKT_FLG_RENEWABLE;
+    ktest_destroy_addresses(&(ref.caddrs));
+  
+#ifdef KRB5_GENEROUS_LR_TYPE
+    decode_run("enc_kdc_rep_part","(optionals NULL)(compat lr_type)","7A 81 B4 30 81 B1 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 38 30 36 30 19 A0 04 02 02 00 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 19 A0 04 02 02 00 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A4 07 03 05 00 FE 5C BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61",decode_krb5_enc_kdc_rep_part,ktest_equal_enc_kdc_rep_part,krb5_free_enc_kdc_rep_part);
+#endif
+
+    decode_run("enc_kdc_rep_part","(optionals NULL)","7A 81 B2 30 81 AF A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A4 07 03 05 00 FE 5C BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61",decode_krb5_enc_kdc_rep_part,ktest_equal_enc_kdc_rep_part,krb5_free_enc_kdc_rep_part);
+
+    ktest_empty_enc_kdc_rep_part(&ref);
+  }  
+
+  /****************************************************************/
+  /* decode_krb5_as_rep */
+  {
+    setup(krb5_kdc_rep,"krb5_kdc_rep",ktest_make_sample_kdc_rep);
+    ref.msg_type = KRB5_AS_REP;
+
+    decode_run("as_rep","","6B 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0B A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_rep,ktest_equal_as_rep,krb5_free_kdc_rep);
+
+/*
+  6B 80 30 80
+    A0 03 02 01 05
+    A1 03 02 01 0B
+    A2 80 30 80
+      30 80
+	A1 03 02 01 0D
+	A2 09 04 07 70 61 2D 64 61 74 61
+      00 00
+      30 80
+	A1 03 02 01 0D
+	A2 09 04 07 70 61 2D 64 61 74 61
+      00 00
+    00 00 00 00
+    A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55
+    A4 80 30 80
+      A0 03 02 01 01
+      A1 80 30 80
+	1B 06 68 66 74 73 61 69
+	1B 05 65 78 74 72 61
+      00 00 00 00
+    00 00 00 00
+    A5 80 61 80 30 80
+      A0 03 02 01 05
+      A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55
+      A2 80 30 80
+	A0 03 02 01 01
+	A1 80 30 80
+	  1B 06 68 66 74 73 61 69
+	  1B 05 65 78 74 72 61
+	00 00 00 00
+      00 00 00 00
+      A3 80 30 80
+	A0 03 02 01 00
+	A1 03 02 01 05
+	A2 17 04 15 6B 72 62 41 53 4E 2E 31
+	  20 74 65 73 74 20 6D 65
+	  73 73 61 67 65
+      00 00 00 00
+    00 00 00 00 00 00
+    A6 80 30 80
+      A0 03 02 01 00
+      A1 03 02 01 05
+      A2 17 04 15 6B 72 62 41 53 4E 2E 31
+	20 74 65 73 74 20 6D 65
+	73 73 61 67 65
+    00 00 00 00
+  00 00 00 00
+*/
+    decode_run("as_rep","(indefinite lengths)","6B 80 30 80 A0 03 02 01 05 A1 03 02 01 0B A2 80 30 80 30 80 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 00 00 30 80 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 00 00 00 00 00 00 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A5 80 61 80 30 80 A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A3 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 00 00 00 00 00 00 A6 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 00 00 00 00",decode_krb5_as_rep,ktest_equal_as_rep,krb5_free_kdc_rep);
+    ktest_destroy_pa_data_array(&(ref.padata));
+    decode_run("as_rep","(optionals NULL)","6B 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0B A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_rep,ktest_equal_as_rep,krb5_free_kdc_rep);
+
+  ktest_empty_kdc_rep(&ref);
+  }  
+  
+  /****************************************************************/
+  /* decode_krb5_tgs_rep */
+  {
+    setup(krb5_kdc_rep,"krb5_kdc_rep",ktest_make_sample_kdc_rep);
+    ref.msg_type = KRB5_TGS_REP;
+
+    decode_run("tgs_rep","","6D 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0D A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_rep,ktest_equal_tgs_rep,krb5_free_kdc_rep);
+
+    ktest_destroy_pa_data_array(&(ref.padata));
+    decode_run("tgs_rep","(optionals NULL)","6D 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0D A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_rep,ktest_equal_tgs_rep,krb5_free_kdc_rep);
+
+  ktest_empty_kdc_rep(&ref);
+  }  
+  
+  /****************************************************************/
+  /* decode_krb5_ap_req */
+  {
+    setup(krb5_ap_req,"krb5_ap_req",ktest_make_sample_ap_req);
+    decode_run("ap_req","","6E 81 9D 30 81 9A A0 03 02 01 05 A1 03 02 01 0E A2 07 03 05 00 FE DC BA 98 A3 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A4 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_ap_req,ktest_equal_ap_req,krb5_free_ap_req);
+    ktest_empty_ap_req(&ref);
+
+  }  
+
+  /****************************************************************/
+  /* decode_krb5_ap_rep */
+  {
+    setup(krb5_ap_rep,"krb5_ap_rep",ktest_make_sample_ap_rep);
+    decode_run("ap_rep","","6F 33 30 31 A0 03 02 01 05 A1 03 02 01 0F A2 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_ap_rep,ktest_equal_ap_rep,krb5_free_ap_rep);
+    ktest_empty_ap_rep(&ref);
+  }  
+
+  /****************************************************************/
+  /* decode_krb5_ap_rep_enc_part */
+  {
+    setup(krb5_ap_rep_enc_part,"krb5_ap_rep_enc_part",ktest_make_sample_ap_rep_enc_part);
+
+    decode_run("ap_rep_enc_part","","7B 36 30 34 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 A2 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A3 03 02 01 11",decode_krb5_ap_rep_enc_part,ktest_equal_ap_rep_enc_part,krb5_free_ap_rep_enc_part);
+  
+    ktest_destroy_keyblock(&(ref.subkey));
+    ref.seq_number = 0;
+    decode_run("ap_rep_enc_part","(optionals NULL)","7B 1C 30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40",decode_krb5_ap_rep_enc_part,ktest_equal_ap_rep_enc_part,krb5_free_ap_rep_enc_part);
+    ktest_empty_ap_rep_enc_part(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_as_req */
+  {
+    setup(krb5_kdc_req,"krb5_kdc_req",ktest_make_sample_kdc_req);
+    ref.msg_type = KRB5_AS_REQ;
+
+    ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    decode_run("as_req","","6A 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0A A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_req,ktest_equal_as_req,krb5_free_kdc_req);
+
+    ktest_destroy_pa_data_array(&(ref.padata));
+    ktest_destroy_principal(&(ref.client));
+#ifndef ISODE_SUCKS
+    ktest_destroy_principal(&(ref.server));
+#endif
+    ref.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
+    ref.from = 0;
+    ref.rtime = 0;
+    ktest_destroy_addresses(&(ref.addresses));
+    ktest_destroy_enc_data(&(ref.authorization_data));
+    decode_run("as_req","(optionals NULL except second_ticket)","6A 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0A A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_req,ktest_equal_as_req,krb5_free_kdc_req);
+    ktest_destroy_sequence_of_ticket(&(ref.second_ticket));
+#ifndef ISODE_SUCKS
+    ktest_make_sample_principal(&(ref.server));
+#endif
+    ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    decode_run("as_req","(optionals NULL except server)","6A 69 30 67 A1 03 02 01 05 A2 03 02 01 0A A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01",decode_krb5_as_req,ktest_equal_as_req,krb5_free_kdc_req);
+
+  ktest_empty_kdc_req(&ref);
+
+  }
+
+  
+  /****************************************************************/
+  /* decode_krb5_tgs_req */
+  {
+    setup(krb5_kdc_req,"krb5_kdc_req",ktest_make_sample_kdc_req);
+    ref.msg_type = KRB5_TGS_REQ;
+
+    ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    decode_run("tgs_req","","6C 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0C A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_req,ktest_equal_tgs_req,krb5_free_kdc_req);
+
+    ktest_destroy_pa_data_array(&(ref.padata));
+    ktest_destroy_principal(&(ref.client));
+#ifndef ISODE_SUCKS
+    ktest_destroy_principal(&(ref.server));
+#endif
+    ref.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
+    ref.from = 0;
+    ref.rtime = 0;
+    ktest_destroy_addresses(&(ref.addresses));
+    ktest_destroy_enc_data(&(ref.authorization_data));
+    decode_run("tgs_req","(optionals NULL except second_ticket)","6C 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0C A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_req,ktest_equal_tgs_req,krb5_free_kdc_req);
+
+    ktest_destroy_sequence_of_ticket(&(ref.second_ticket));
+#ifndef ISODE_SUCKS
+    ktest_make_sample_principal(&(ref.server));
+#endif
+    ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    decode_run("tgs_req","(optionals NULL except server)","6C 69 30 67 A1 03 02 01 05 A2 03 02 01 0C A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01",decode_krb5_tgs_req,ktest_equal_tgs_req,krb5_free_kdc_req);
+
+    ktest_empty_kdc_req(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_kdc_req_body */
+  {
+    krb5_kdc_req ref, *var;
+    memset(&ref, 0, sizeof(krb5_kdc_req));
+    retval = ktest_make_sample_kdc_req_body(&ref);
+    if(retval){
+      com_err("making sample kdc_req_body",retval,"");
+      exit(1);
+    }
+    ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    decode_run("kdc_req_body","","30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req);
+
+    ktest_destroy_principal(&(ref.client));
+#ifndef ISODE_SUCKS
+    ktest_destroy_principal(&(ref.server));
+#endif
+    ref.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
+    ref.from = 0;
+    ref.rtime = 0;
+    ktest_destroy_addresses(&(ref.addresses));
+    ktest_destroy_enc_data(&(ref.authorization_data));
+    decode_run("kdc_req_body","(optionals NULL except second_ticket)","30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req);
+
+    ktest_destroy_sequence_of_ticket(&(ref.second_ticket));
+#ifndef ISODE_SUCKS
+    ktest_make_sample_principal(&(ref.server));
+#endif
+    ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    decode_run("kdc_req_body","(optionals NULL except server)","30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req);
+    ref.nktypes = 0;
+    free(ref.ktype);
+    ref.ktype = NULL;
+    decode_run("kdc_req_body","(optionals NULL except server; zero-length etypes)","30 53 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 02 30 00",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req);
+
+    ktest_empty_kdc_req(&ref);
+  }
+
+  
+  /****************************************************************/
+  /* decode_krb5_safe */
+  {
+    setup(krb5_safe,"krb5_safe",ktest_make_sample_safe);
+    decode_run("safe","","74 6E 30 6C A0 03 02 01 05 A1 03 02 01 14 A2 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_safe,ktest_equal_safe,krb5_free_safe);
+
+    ref.timestamp = 0;
+    ref.usec = 0;
+    ref.seq_number = 0;
+    ktest_destroy_address(&(ref.r_address));
+    decode_run("safe","(optionals NULL)","74 3E 30 3C A0 03 02 01 05 A1 03 02 01 14 A2 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_safe,ktest_equal_safe,krb5_free_safe);
+
+    ktest_empty_safe(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_priv */
+  {
+    setup(krb5_priv,"krb5_priv",ktest_make_sample_priv);
+    decode_run("priv","","75 33 30 31 A0 03 02 01 05 A1 03 02 01 15 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_priv,ktest_equal_priv,krb5_free_priv);
+    ktest_empty_priv(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_enc_priv_part */
+  {
+    setup(krb5_priv_enc_part,"krb5_priv_enc_part",ktest_make_sample_priv_enc_part);
+    decode_run("enc_priv_part","","7C 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_priv_part,ktest_equal_enc_priv_part,krb5_free_priv_enc_part);
+
+    ref.timestamp = 0;
+    ref.usec = 0;
+    ref.seq_number = 0;
+    ktest_destroy_address(&(ref.r_address));
+    decode_run("enc_priv_part","(optionals NULL)","7C 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_priv_part,ktest_equal_enc_priv_part,krb5_free_priv_enc_part);
+    ktest_empty_priv_enc_part(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_cred */
+  {
+    setup(krb5_cred,"krb5_cred",ktest_make_sample_cred);
+    decode_run("cred","","76 81 F6 30 81 F3 A0 03 02 01 05 A1 03 02 01 16 A2 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_cred,ktest_equal_cred,krb5_free_cred);
+    ktest_empty_cred(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_enc_cred_part */
+  {
+    setup(krb5_cred_enc_part,"krb5_cred_enc_part",ktest_make_sample_cred_enc_part);
+    decode_run("enc_cred_part","","7D 82 02 23 30 82 02 1F A0 82 01 DA 30 82 01 D6 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_cred_part,ktest_equal_enc_cred_part,krb5_free_cred_enc_part);
+    /* free_cred_enc_part does not free the pointer */
+    krb5_xfree(var);
+    ktest_destroy_principal(&(ref.ticket_info[0]->client));
+    ktest_destroy_principal(&(ref.ticket_info[0]->server));
+    ref.ticket_info[0]->flags = 0;
+    ref.ticket_info[0]->times.authtime = 0;
+    ref.ticket_info[0]->times.starttime = 0;
+    ref.ticket_info[0]->times.endtime = 0;
+    ref.ticket_info[0]->times.renew_till = 0;
+    ktest_destroy_addresses(&(ref.ticket_info[0]->caddrs));
+    ref.nonce = 0;
+    ref.timestamp = 0;
+    ref.usec = 0;
+    ktest_destroy_address(&(ref.s_address));
+    ktest_destroy_address(&(ref.r_address));
+    decode_run("enc_cred_part","(optionals NULL)","7D 82 01 0E 30 82 01 0A A0 82 01 06 30 82 01 02 30 15 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_cred_part,ktest_equal_enc_cred_part,krb5_free_cred_enc_part);
+    /* free_cred_enc_part does not free the pointer */
+    krb5_xfree(var);
+
+    ktest_empty_cred_enc_part(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_error */
+  {
+    setup(krb5_error,"krb5_error",ktest_make_sample_error);
+    decode_run("error","","7E 81 BA 30 81 B7 A0 03 02 01 05 A1 03 02 01 1E A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A7 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A8 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 0A 1B 08 6B 72 62 35 64 61 74 61 AC 0A 04 08 6B 72 62 35 64 61 74 61",decode_krb5_error,ktest_equal_error,krb5_free_error);
+
+    ref.ctime = 0;
+    ktest_destroy_principal(&(ref.client));
+    ktest_empty_data(&(ref.text));
+    ktest_empty_data(&(ref.e_data));
+    decode_run("error","(optionals NULL)","7E 60 30 5E A0 03 02 01 05 A1 03 02 01 1E A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61",decode_krb5_error,ktest_equal_error,krb5_free_error);
+
+    ktest_empty_error(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_authdata */
+  {
+    krb5_authdata **ref, **var;
+    retval = ktest_make_sample_authorization_data(&ref);
+    if(retval){
+      com_err("making sample authorization_data",retval,"");
+      exit(1);
+    }
+    retval = krb5_data_hex_parse(&code,"30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72");
+    if(retval){
+      com_err("parsing authorization_data",retval,"");
+      exit(1);
+    }
+    retval = decode_krb5_authdata(&code,&var);
+    if(retval) com_err("decoding authorization_data",retval,"");
+    test(ktest_equal_authorization_data(ref,var),"authorization_data\n")
+    krb5_free_data_contents(test_context, &code);
+    krb5_free_authdata(test_context, var);
+    ktest_destroy_authorization_data(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_pwd_sequence */
+  {
+    setup(passwd_phrase_element,"passwd_phrase_element",ktest_make_sample_passwd_phrase_element);
+    decode_run("PasswdSequence","","30 18 A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61",decode_krb5_pwd_sequence,ktest_equal_passwd_phrase_element,krb5_ktest_free_pwd_sequence);
+    ktest_empty_passwd_phrase_element(&ref);
+  }
+
+  /****************************************************************/
+  /* decode_passwd_data */
+  {
+    setup(krb5_pwd_data,"krb5_pwd_data",ktest_make_sample_krb5_pwd_data);
+    decode_run("PasswdData","","30 3D A0 03 02 01 02 A1 36 30 34 30 18 A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 30 18 A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61",decode_krb5_pwd_data,ktest_equal_krb5_pwd_data,krb5_free_pwd_data);
+    ktest_empty_pwd_data(&ref);
+  }
+
+  /****************************************************************/
+  /* decode_krb5_padata_sequence */
+  {
+    krb5_pa_data **ref, **var;
+    retval = ktest_make_sample_pa_data_array(&ref);
+    if(retval){
+      com_err("making sample pa_data array",retval,"");
+      exit(1);
+    }
+    retval = krb5_data_hex_parse(&code,"30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61");
+    if(retval){
+      com_err("parsing padata_sequence",retval,"");
+      exit(1);
+    }
+    retval = decode_krb5_padata_sequence(&code,&var);
+    if(retval) com_err("decoding padata_sequence",retval,"");
+    test(ktest_equal_sequence_of_pa_data(ref,var),"pa_data\n");
+    krb5_free_pa_data(test_context, var);
+    krb5_free_data_contents(test_context, &code);
+    ktest_destroy_pa_data_array(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_krb5_padata_sequence (empty) */
+  {
+    krb5_pa_data **ref, **var;
+    retval = ktest_make_sample_empty_pa_data_array(&ref);
+    if(retval){
+      com_err("making sample empty pa_data array",retval,"");
+      exit(1);
+    }
+    retval = krb5_data_hex_parse(&code,"30 00");
+    if(retval){
+      com_err("parsing padata_sequence (empty)",retval,"");
+      exit(1);
+    }
+    retval = decode_krb5_padata_sequence(&code,&var);
+    if(retval) com_err("decoding padata_sequence (empty)",retval,"");
+    test(ktest_equal_sequence_of_pa_data(ref,var),"pa_data (empty)\n");
+    krb5_free_pa_data(test_context, var);
+    krb5_free_data_contents(test_context, &code);
+    ktest_destroy_pa_data_array(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_pwd_sequence */
+  {
+    setup(krb5_alt_method,"krb5_alt_method",ktest_make_sample_alt_method);
+    decode_run("alt_method","","30 0F A0 03 02 01 2A A1 08 04 06 73 65 63 72 65 74",decode_krb5_alt_method,ktest_equal_krb5_alt_method,krb5_ktest_free_alt_method);
+    ref.length = 0;
+    decode_run("alt_method (no data)","","30 05 A0 03 02 01 2A",decode_krb5_alt_method,ktest_equal_krb5_alt_method,krb5_ktest_free_alt_method);
+    ktest_empty_alt_method(&ref);
+  }
+
+  /****************************************************************/
+  /* decode_etype_info */
+  {
+      krb5_etype_info ref, var;
+
+      retval = ktest_make_sample_etype_info(&ref);
+      if (retval) {
+	  com_err("krb5_decode_test", retval,
+		  "while making sample etype info");
+	  exit(1);
+      }
+      retval = krb5_data_hex_parse(&code,"30 33 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 30 05 A0 03 02 01 01 30 14 A0 03 02 01 02 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 32");
+      if(retval){
+	  com_err("krb5_decode_test", retval, "while parsing etype_info");
+	  exit(1);
+      }
+      retval = decode_krb5_etype_info(&code,&var);
+      if(retval){
+	  com_err("krb5_decode_test", retval, "while decoding etype_info");
+      }
+      test(ktest_equal_etype_info(ref,var),"etype_info\n");
+
+      ktest_destroy_etype_info(var);
+      ktest_destroy_etype_info_entry(ref[2]);      ref[2] = 0;
+      ktest_destroy_etype_info_entry(ref[1]);      ref[1] = 0;
+      krb5_free_data_contents(test_context, &code);
+      
+      retval = krb5_data_hex_parse(&code,"30 16 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30");
+      if(retval){
+	  com_err("krb5_decode_test", retval,
+		  "while parsing etype_info (only one)");
+	  exit(1);
+      }
+      retval = decode_krb5_etype_info(&code,&var);
+      if(retval){
+	  com_err("krb5_decode_test", retval,
+		  "while decoding etype_info (only one)");
+      }
+      test(ktest_equal_etype_info(ref,var),"etype_info (only one)\n");
+      
+      ktest_destroy_etype_info(var);
+      ktest_destroy_etype_info_entry(ref[0]);      ref[0] = 0;
+      krb5_free_data_contents(test_context, &code);
+      
+      retval = krb5_data_hex_parse(&code,"30 00");
+      if(retval){
+	  com_err("krb5_decode_test", retval,
+		  "while parsing etype_info (no info)");
+	  exit(1);
+      }
+      retval = decode_krb5_etype_info(&code,&var);
+      if(retval){
+	  com_err("krb5_decode_test", retval,
+		  "while decoding etype_info (no info)");
+      }
+      test(ktest_equal_etype_info(ref,var),"etype_info (no info)\n");
+
+      krb5_free_data_contents(test_context, &code);
+      ktest_destroy_etype_info(var);
+      ktest_destroy_etype_info(ref);
+  }
+
+  /****************************************************************/
+  /* decode_pa_enc_ts */
+  {
+    setup(krb5_pa_enc_ts,"krb5_pa_enc_ts",ktest_make_sample_pa_enc_ts);
+    decode_run("pa_enc_ts","","30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40",decode_krb5_pa_enc_ts,ktest_equal_krb5_pa_enc_ts,krb5_free_pa_enc_ts);
+    ref.pausec = 0;
+    decode_run("pa_enc_ts (no usec)","","30 13 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_pa_enc_ts,ktest_equal_krb5_pa_enc_ts,krb5_free_pa_enc_ts);
+  }
+  
+  /****************************************************************/
+  /* decode_enc_data */
+  {
+    setup(krb5_enc_data,"krb5_enc_data",ktest_make_sample_enc_data);
+    decode_run("enc_data","","30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_enc_data,ktest_equal_enc_data,krb5_ktest_free_enc_data);
+    ktest_destroy_enc_data(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_sam_challenge */
+  {
+    setup(krb5_sam_challenge,"krb5_sam_challenge",ktest_make_sample_sam_challenge);
+    decode_run("sam_challenge","","30 78 A0 03 02 01 2A A1 07 03 05 00 80 00 00 00 A2 0B 04 09 74 79 70 65 20 6E 61 6D 65 A3 02 04 00 A4 11 04 0F 63 68 61 6C 6C 65 6E 67 65 20 6C 61 62 65 6C A5 10 04 0E 63 68 61 6C 6C 65 6E 67 65 20 69 70 73 65 A6 16 04 14 72 65 73 70 6F 6E 73 65 5F 70 72 6F 6D 70 74 20 69 70 73 65 A7 02 04 00 A8 05 02 03 54 32 10 A9 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_sam_challenge,ktest_equal_sam_challenge,krb5_free_sam_challenge);
+    ktest_empty_sam_challenge(&ref);
+
+  }
+  
+  /****************************************************************/
+  /* decode_sam_challenge */
+  {
+    setup(krb5_sam_challenge,"krb5_sam_challenge - no optionals",ktest_make_sample_sam_challenge);
+    decode_run("sam_challenge","","30 70 A0 03 02 01 2A A1 07 03 05 00 80 00 00 00 A2 0B 04 09 74 79 70 65 20 6E 61 6D 65 A4 11 04 0F 63 68 61 6C 6C 65 6E 67 65 20 6C 61 62 65 6C A5 10 04 0E 63 68 61 6C 6C 65 6E 67 65 20 69 70 73 65 A6 16 04 14 72 65 73 70 6F 6E 73 65 5F 70 72 6F 6D 70 74 20 69 70 73 65 A8 05 02 03 54 32 10 A9 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_sam_challenge,ktest_equal_sam_challenge,krb5_free_sam_challenge);
+    ktest_empty_sam_challenge(&ref);
+  }
+  
+  /****************************************************************/
+  /* decode_sam_response */
+  {
+    setup(krb5_sam_response,"krb5_sam_response",ktest_make_sample_sam_response);
+    decode_run("sam_response","","30 6A A0 03 02 01 2A A1 07 03 05 00 80 00 00 00 A2 0C 04 0A 74 72 61 63 6B 20 64 61 74 61 A3 14 30 12 A0 03 02 01 01 A1 04 02 02 07 96 A2 05 04 03 6B 65 79 A4 1C 30 1A A0 03 02 01 01 A1 04 02 02 0D 36 A2 0D 04 0B 6E 6F 6E 63 65 20 6F 72 20 74 73 A5 05 02 03 54 32 10 A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_sam_response,ktest_equal_sam_response,krb5_free_sam_response);
+
+    ktest_empty_sam_response(&ref);
+  }
+  
+  krb5_free_context(test_context);
+  exit(error_count);
+  return(error_count);
+}
+
+
+void krb5_ktest_free_alt_method(krb5_context context, krb5_alt_method *val)
+{
+  if (val->data)
+    krb5_xfree(val->data);
+  krb5_xfree(val);
+}
+
+void krb5_ktest_free_pwd_sequence(krb5_context context, 
+				  passwd_phrase_element *val)
+{
+  krb5_free_data(context, val->passwd);
+  krb5_free_data(context, val->phrase);
+  krb5_xfree(val);
+}
+
+void krb5_ktest_free_enc_data(krb5_context context, krb5_enc_data *val)
+{
+  if(val) {
+       krb5_free_data_contents(context, &(val->ciphertext));
+       free(val);
+  }
+}
diff --git a/krb5-1-6/src/tests/asn.1/krb5_encode_test.c b/krb5-1-6/src/tests/asn.1/krb5_encode_test.c
new file mode 100644
index 000000000..a6f869492
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/krb5_encode_test.c
@@ -0,0 +1,681 @@
+#include <stdio.h>
+#include "k5-int.h"
+#include "com_err.h"
+#include "utility.h"
+
+#include "ktest.h"
+#include <string.h>
+
+#include "debug.h"
+
+extern int current_appl_type;
+
+krb5_context test_context;
+int error_count = 0;
+int do_trval = 0;
+int trval2();
+
+static void encoder_print_results(code, typestring, description)
+	krb5_data *code;
+	char	*typestring;
+	char	*description;
+{
+	char	*code_string = NULL;
+	krb5_error_code	retval;
+	int r, rlen;
+
+	if (do_trval) {
+		printf("encode_krb5_%s%s:\n", typestring, description);
+		r = trval2(stdout, code->data, code->length, 0, &rlen);
+		printf("\n\n");
+		if (rlen != code->length) {
+			printf("Error: length mismatch: was %d, parsed %d\n",
+			       code->length, rlen);
+			exit(1);
+		}
+		if (r != 0) {
+			printf("Error: Return from trval2 is %d.\n", r);
+			exit(1);
+		}
+		current_appl_type = -1;	/* Reset type */
+	} else {
+		retval = asn1_krb5_data_unparse(code,&(code_string));
+		if(retval) {
+			com_err("krb5_encode_test", retval ,
+				"while unparsing %s", typestring);
+			exit(1);
+		}
+		printf("encode_krb5_%s%s: %s\n", typestring, description,
+		       code_string);
+		free(code_string);
+	}
+	ktest_destroy_data(&code);
+}	
+
+static void PRS(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	extern char *optarg;	
+	int optchar;
+	extern int print_types, print_krb5_types, print_id_and_len,
+		print_constructed_length, print_skip_context,
+		print_skip_tagnum, print_context_shortcut;
+
+	while ((optchar = getopt(argc, argv, "tp:")) != -1) {
+		switch(optchar) {
+		case 't':
+			do_trval = 1;
+			break;
+		case 'p':
+			sample_principal_name = optarg;
+			break;
+		case '?':
+		default:
+			fprintf(stderr, "Usage: %s [-t] [-p principal]\n",
+				argv[0]);
+			exit(1);
+		}
+	}
+	print_types = 1;
+	print_krb5_types = 1;
+	print_id_and_len = 0;
+	print_constructed_length = 0;
+	print_skip_context = 1;
+	print_skip_tagnum = 1;
+	print_context_shortcut = 1;
+}
+
+int
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+  krb5_data *code;
+  krb5_error_code retval;
+
+  PRS(argc, argv);
+  
+  retval = krb5_init_context(&test_context);
+  if (retval) {
+	  com_err(argv[0], retval, "while initializing krb5");
+	  exit(1);
+  }
+  
+#define setup(value,type,typestring,constructor)\
+  retval = constructor(&(value));\
+  if(retval){\
+    com_err("krb5_encode_test", retval, "while making sample %s", typestring);\
+    exit(1);\
+  }
+    
+#define encode_run(value,type,typestring,description,encoder)\
+  retval = encoder(&(value),&(code));\
+  if(retval){\
+    com_err("krb5_encode_test", retval,"while encoding %s", typestring);\
+    exit(1);\
+  }\
+  encoder_print_results(code, typestring, description);
+      
+  /****************************************************************/
+  /* encode_krb5_authenticator */
+  {
+    krb5_authenticator authent;
+    setup(authent,authenticator,"authenticator",ktest_make_sample_authenticator);
+
+    encode_run(authent,authenticator,"authenticator","",encode_krb5_authenticator);
+
+    ktest_destroy_checksum(&(authent.checksum));
+    ktest_destroy_keyblock(&(authent.subkey));
+    authent.seq_number = 0;
+    ktest_empty_authorization_data(authent.authorization_data);
+    encode_run(authent,authenticator,"authenticator","(optionals empty)",encode_krb5_authenticator);
+
+    ktest_destroy_authorization_data(&(authent.authorization_data));
+    encode_run(authent,authenticator,"authenticator","(optionals NULL)",encode_krb5_authenticator);
+    ktest_empty_authenticator(&authent);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_ticket */
+  {
+    krb5_ticket tkt;
+    setup(tkt,ticket,"ticket",ktest_make_sample_ticket);
+    encode_run(tkt,ticket,"ticket","",encode_krb5_ticket);
+    ktest_empty_ticket(&tkt);
+  }
+
+  /****************************************************************/
+  /* encode_krb5_encryption_key */
+  {
+    krb5_keyblock keyblk;
+    setup(keyblk,keyblock,"keyblock",ktest_make_sample_keyblock);
+    current_appl_type = 1005;
+    encode_run(keyblk,keyblock,"keyblock","",encode_krb5_encryption_key);
+    ktest_empty_keyblock(&keyblk);
+  }  
+  
+  /****************************************************************/
+  /* encode_krb5_enc_tkt_part */
+  {
+    krb5_ticket tkt;
+    memset(&tkt, 0, sizeof(krb5_ticket));
+    tkt.enc_part2 = (krb5_enc_tkt_part*)calloc(1,sizeof(krb5_enc_tkt_part));
+    if(tkt.enc_part2 == NULL) com_err("allocating enc_tkt_part",errno,"");
+    setup(*(tkt.enc_part2),enc_tkt_part,"enc_tkt_part",ktest_make_sample_enc_tkt_part);
+  
+    encode_run(*(tkt.enc_part2),enc_tkt_part,"enc_tkt_part","",encode_krb5_enc_tkt_part);
+  
+    tkt.enc_part2->times.starttime = 0;
+    tkt.enc_part2->times.renew_till = 0;
+    ktest_destroy_address(&(tkt.enc_part2->caddrs[1]));
+    ktest_destroy_address(&(tkt.enc_part2->caddrs[0]));
+    ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[1]));
+    ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[0]));
+  
+    /* ISODE version fails on the empty caddrs field */
+    ktest_destroy_addresses(&(tkt.enc_part2->caddrs));
+    ktest_destroy_authorization_data(&(tkt.enc_part2->authorization_data));
+  
+    encode_run(*(tkt.enc_part2),enc_tkt_part,"enc_tkt_part","(optionals NULL)",encode_krb5_enc_tkt_part);
+    ktest_empty_ticket(&tkt);
+  }  
+  
+  /****************************************************************/
+  /* encode_krb5_enc_kdc_rep_part */
+  {
+    krb5_kdc_rep kdcr;
+
+    memset(&kdcr, 0, sizeof(kdcr));
+ 
+    kdcr.enc_part2 = (krb5_enc_kdc_rep_part*)
+      calloc(1,sizeof(krb5_enc_kdc_rep_part));
+    if(kdcr.enc_part2 == NULL) com_err("allocating enc_kdc_rep_part",errno,"");
+    setup(*(kdcr.enc_part2),enc_kdc_rep_part,"enc_kdc_rep_part",ktest_make_sample_enc_kdc_rep_part);
+  
+    encode_run(*(kdcr.enc_part2),enc_kdc_rep_part,"enc_kdc_rep_part","",encode_krb5_enc_kdc_rep_part);
+  
+    kdcr.enc_part2->key_exp = 0;
+    kdcr.enc_part2->times.starttime = 0;
+    kdcr.enc_part2->flags &= ~TKT_FLG_RENEWABLE;
+    ktest_destroy_addresses(&(kdcr.enc_part2->caddrs));
+  
+    encode_run(*(kdcr.enc_part2),enc_kdc_rep_part,"enc_kdc_rep_part","(optionals NULL)",encode_krb5_enc_kdc_rep_part);
+
+    ktest_empty_kdc_rep(&kdcr);
+  }  
+
+  /****************************************************************/
+  /* encode_krb5_as_rep */
+  {
+    krb5_kdc_rep kdcr;
+    setup(kdcr,kdc_rep,"kdc_rep",ktest_make_sample_kdc_rep);
+  
+/*    kdcr.msg_type = KRB5_TGS_REP;
+    test(encode_krb5_as_rep(&kdcr,&code) == KRB5_BADMSGTYPE,
+	   "encode_krb5_as_rep type check\n");
+    ktest_destroy_data(&code);*/
+  
+    kdcr.msg_type = KRB5_AS_REP;
+    encode_run(kdcr,as_rep,"as_rep","",encode_krb5_as_rep);
+  
+    ktest_destroy_pa_data_array(&(kdcr.padata));
+    encode_run(kdcr,as_rep,"as_rep","(optionals NULL)",encode_krb5_as_rep);
+
+    ktest_empty_kdc_rep(&kdcr);
+
+  }  
+  
+  /****************************************************************/
+  /* encode_krb5_tgs_rep */
+  {
+    krb5_kdc_rep kdcr;
+    setup(kdcr,kdc_rep,"kdc_rep",ktest_make_sample_kdc_rep);
+
+/*    kdcr.msg_type = KRB5_AS_REP;
+    test(encode_krb5_tgs_rep(&kdcr,&code) == KRB5_BADMSGTYPE,
+	   "encode_krb5_tgs_rep type check\n");*/
+  
+    kdcr.msg_type = KRB5_TGS_REP;
+    encode_run(kdcr,tgs_rep,"tgs_rep","",encode_krb5_tgs_rep);
+
+    ktest_destroy_pa_data_array(&(kdcr.padata));
+    encode_run(kdcr,tgs_rep,"tgs_rep","(optionals NULL)",encode_krb5_tgs_rep);
+
+    ktest_empty_kdc_rep(&kdcr);
+
+  }  
+  
+  /****************************************************************/
+  /* encode_krb5_ap_req */
+  {
+    krb5_ap_req apreq;
+    setup(apreq,ap_req,"ap_req",ktest_make_sample_ap_req);
+    encode_run(apreq,ap_req,"ap_req","",encode_krb5_ap_req);
+    ktest_empty_ap_req(&apreq);
+  }  
+
+  /****************************************************************/
+  /* encode_krb5_ap_rep */
+  {
+    krb5_ap_rep aprep;
+    setup(aprep,ap_rep,"ap_rep",ktest_make_sample_ap_rep);
+    encode_run(aprep,ap_rep,"ap_rep","",encode_krb5_ap_rep);
+    ktest_empty_ap_rep(&aprep);
+  }  
+
+  /****************************************************************/
+  /* encode_krb5_ap_rep_enc_part */
+  {
+    krb5_ap_rep_enc_part apenc;
+    setup(apenc,ap_rep_enc_part,"ap_rep_enc_part",ktest_make_sample_ap_rep_enc_part);
+    encode_run(apenc,ap_rep_enc_part,"ap_rep_enc_part","",encode_krb5_ap_rep_enc_part);
+  
+    ktest_destroy_keyblock(&(apenc.subkey));
+    apenc.seq_number = 0;
+    encode_run(apenc,ap_rep_enc_part,"ap_rep_enc_part","(optionals NULL)",encode_krb5_ap_rep_enc_part);
+    ktest_empty_ap_rep_enc_part(&apenc);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_as_req */
+  {
+    krb5_kdc_req asreq;
+    setup(asreq,kdc_req,"kdc_req",ktest_make_sample_kdc_req);
+    asreq.msg_type = KRB5_AS_REQ;
+    asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    encode_run(asreq,as_req,"as_req","",encode_krb5_as_req);
+
+    ktest_destroy_pa_data_array(&(asreq.padata));
+    ktest_destroy_principal(&(asreq.client));
+#ifndef ISODE_SUCKS
+    ktest_destroy_principal(&(asreq.server));
+#endif
+    asreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
+    asreq.from = 0;
+    asreq.rtime = 0;
+    ktest_destroy_addresses(&(asreq.addresses));
+    ktest_destroy_enc_data(&(asreq.authorization_data));
+    encode_run(asreq,as_req,"as_req","(optionals NULL except second_ticket)",encode_krb5_as_req);
+    ktest_destroy_sequence_of_ticket(&(asreq.second_ticket));
+#ifndef ISODE_SUCKS
+    ktest_make_sample_principal(&(asreq.server));
+#endif
+    asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    encode_run(asreq,as_req,"as_req","(optionals NULL except server)",encode_krb5_as_req);
+    ktest_empty_kdc_req(&asreq);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_tgs_req */
+  {
+    krb5_kdc_req tgsreq;
+    setup(tgsreq,kdc_req,"kdc_req",ktest_make_sample_kdc_req);
+    tgsreq.msg_type = KRB5_TGS_REQ;
+    tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    encode_run(tgsreq,tgs_req,"tgs_req","",encode_krb5_tgs_req);
+
+    ktest_destroy_pa_data_array(&(tgsreq.padata));
+    ktest_destroy_principal(&(tgsreq.client));
+#ifndef ISODE_SUCKS
+    ktest_destroy_principal(&(tgsreq.server));
+#endif
+    tgsreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
+    tgsreq.from = 0;
+    tgsreq.rtime = 0;
+    ktest_destroy_addresses(&(tgsreq.addresses));
+    ktest_destroy_enc_data(&(tgsreq.authorization_data));
+    encode_run(tgsreq,tgs_req,"tgs_req","(optionals NULL except second_ticket)",encode_krb5_tgs_req);
+
+    ktest_destroy_sequence_of_ticket(&(tgsreq.second_ticket));
+#ifndef ISODE_SUCKS
+    ktest_make_sample_principal(&(tgsreq.server));
+#endif
+    tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    encode_run(tgsreq,tgs_req,"tgs_req","(optionals NULL except server)",encode_krb5_tgs_req);
+
+    ktest_empty_kdc_req(&tgsreq);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_kdc_req_body */
+  {
+    krb5_kdc_req kdcrb;
+    memset(&kdcrb, 0, sizeof(kdcrb));
+    setup(kdcrb,kdc_req_body,"kdc_req_body",ktest_make_sample_kdc_req_body);
+    kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    current_appl_type = 1007;	/* Force interpretation as kdc-req-body */
+    encode_run(kdcrb,kdc_req_body,"kdc_req_body","",encode_krb5_kdc_req_body);
+
+    ktest_destroy_principal(&(kdcrb.client));
+#ifndef ISODE_SUCKS
+    ktest_destroy_principal(&(kdcrb.server));
+#endif
+    kdcrb.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
+    kdcrb.from = 0;
+    kdcrb.rtime = 0;
+    ktest_destroy_addresses(&(kdcrb.addresses));
+    ktest_destroy_enc_data(&(kdcrb.authorization_data));
+    current_appl_type = 1007;	/* Force interpretation as kdc-req-body */
+    encode_run(kdcrb,kdc_req_body,"kdc_req_body","(optionals NULL except second_ticket)",encode_krb5_kdc_req_body);
+
+    ktest_destroy_sequence_of_ticket(&(kdcrb.second_ticket));
+#ifndef ISODE_SUCKS
+    ktest_make_sample_principal(&(kdcrb.server));
+#endif
+    kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
+    current_appl_type = 1007;	/* Force interpretation as kdc-req-body */
+    encode_run(kdcrb,kdc_req_body,"kdc_req_body","(optionals NULL except server)",encode_krb5_kdc_req_body);
+
+    ktest_empty_kdc_req(&kdcrb);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_safe */
+  {
+    krb5_safe s;
+    setup(s,safe,"safe",ktest_make_sample_safe);
+    encode_run(s,safe,"safe","",encode_krb5_safe);
+
+    s.timestamp = 0;
+    /* s.usec should be opted out by the timestamp */
+    s.seq_number = 0;
+    ktest_destroy_address(&(s.r_address));
+    encode_run(s,safe,"safe","(optionals NULL)",encode_krb5_safe);
+
+    ktest_empty_safe(&s);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_priv */
+  {
+    krb5_priv p;
+    setup(p,priv,"priv",ktest_make_sample_priv);
+    encode_run(p,priv,"priv","",encode_krb5_priv);
+    ktest_empty_priv(&p);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_enc_priv_part */
+  {
+    krb5_priv_enc_part ep;
+    setup(ep,priv_enc_part,"priv_enc_part",ktest_make_sample_priv_enc_part);
+    encode_run(ep,enc_priv_part,"enc_priv_part","",encode_krb5_enc_priv_part);
+
+    ep.timestamp = 0;
+    /* ep.usec should be opted out along with timestamp */
+    ep.seq_number = 0;
+    ktest_destroy_address(&(ep.r_address));
+    encode_run(ep,enc_priv_part,"enc_priv_part","(optionals NULL)",encode_krb5_enc_priv_part);
+
+    ktest_empty_priv_enc_part(&ep);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_cred */
+  {
+    krb5_cred c;
+    setup(c,cred,"cred",ktest_make_sample_cred);
+    encode_run(c,cred,"cred","",encode_krb5_cred);
+    ktest_empty_cred(&c);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_enc_cred_part */
+  {
+    krb5_cred_enc_part cep;
+    setup(cep,cred_enc_part,"cred_enc_part",ktest_make_sample_cred_enc_part);
+    encode_run(cep,enc_cred_part,"enc_cred_part","",encode_krb5_enc_cred_part);
+
+    ktest_destroy_principal(&(cep.ticket_info[0]->client));
+    ktest_destroy_principal(&(cep.ticket_info[0]->server));
+    cep.ticket_info[0]->flags = 0;
+    cep.ticket_info[0]->times.authtime = 0;
+    cep.ticket_info[0]->times.starttime = 0;
+    cep.ticket_info[0]->times.endtime = 0;
+    cep.ticket_info[0]->times.renew_till = 0;
+    ktest_destroy_addresses(&(cep.ticket_info[0]->caddrs));
+    cep.nonce = 0;
+    cep.timestamp = 0;
+    ktest_destroy_address(&(cep.s_address));
+    ktest_destroy_address(&(cep.r_address));
+    encode_run(cep,enc_cred_part,"enc_cred_part","(optionals NULL)",encode_krb5_enc_cred_part);
+
+    ktest_empty_cred_enc_part(&cep);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_error */
+  {
+    krb5_error kerr;
+    setup(kerr,error,"error",ktest_make_sample_error);
+    encode_run(kerr,error,"error","",encode_krb5_error);
+
+    kerr.ctime = 0;
+    ktest_destroy_principal(&(kerr.client));
+    ktest_empty_data(&(kerr.text));
+    ktest_empty_data(&(kerr.e_data));
+    encode_run(kerr,error,"error","(optionals NULL)",encode_krb5_error);
+
+    ktest_empty_error(&kerr);
+  }
+  
+  /****************************************************************/
+  /* encode_krb5_authdata */
+  {
+    krb5_authdata **ad;
+    setup(ad,authorization_data,"authorization_data",ktest_make_sample_authorization_data);
+
+    retval = encode_krb5_authdata((const krb5_authdata**)ad,&(code));
+    if(retval) {
+	com_err("encoding authorization_data",retval,"");
+	exit(1);
+    }
+    current_appl_type = 1004;	/* Force type to be authdata */
+    encoder_print_results(code, "authorization_data", "");
+
+    ktest_destroy_authorization_data(&ad);
+  }
+  
+  /****************************************************************/
+  /* encode_pwd_sequence */
+  {
+    passwd_phrase_element ppe;
+    setup(ppe,passwd_phrase_element,"PasswdSequence",ktest_make_sample_passwd_phrase_element);
+    encode_run(ppe,passwd_phrase_element,"pwd_sequence","",encode_krb5_pwd_sequence);
+    ktest_empty_passwd_phrase_element(&ppe);
+  }
+
+  /****************************************************************/
+  /* encode_passwd_data */
+  {
+    krb5_pwd_data pd;
+    setup(pd,krb5_pwd_data,"PasswdData",ktest_make_sample_krb5_pwd_data);
+    encode_run(pd,krb5_pwd_data,"pwd_data","",encode_krb5_pwd_data);
+    ktest_empty_pwd_data(&pd);
+  }
+
+  /****************************************************************/
+  /* encode_padata_sequence */
+  {
+    krb5_pa_data **pa;
+    
+    setup(pa,krb5_pa_data,"PreauthData",ktest_make_sample_pa_data_array);
+    retval = encode_krb5_padata_sequence((const krb5_pa_data**)pa,&(code));
+    if(retval) {
+	com_err("encoding padata_sequence",retval,"");
+	exit(1);
+    }
+    encoder_print_results(code, "padata_sequence", "");
+    
+    ktest_destroy_pa_data_array(&pa);
+  }
+
+  /****************************************************************/
+  /* encode_padata_sequence (empty) */
+  {
+    krb5_pa_data **pa;
+    
+    setup(pa,krb5_pa_data,"EmptyPreauthData",ktest_make_sample_empty_pa_data_array);
+    retval = encode_krb5_padata_sequence((const krb5_pa_data**)pa,&(code));
+    if(retval) {
+	com_err("encoding padata_sequence(empty)",retval,"");
+	exit(1);
+    }
+    encoder_print_results(code, "padata_sequence(empty)", "");
+
+    ktest_destroy_pa_data_array(&pa);
+  }
+
+  /****************************************************************/
+  /* encode_alt_method */
+  {
+    krb5_alt_method am;
+    setup(am,krb5_alt_method,"AltMethod",ktest_make_sample_alt_method);
+    encode_run(am,krb5_alt_method,"alt_method","",encode_krb5_alt_method);
+    am.length = 0;
+    if (am.data)
+      free(am.data);
+    am.data = 0;
+    encode_run(am,krb5_alt_method,"alt_method (no data)","",
+	       encode_krb5_alt_method);
+    ktest_empty_alt_method(&am);
+  }
+
+  /****************************************************************/
+  /* encode_etype_info */
+  {
+    krb5_etype_info_entry **info;
+    
+    setup(info,krb5_etype_info_entry **,"etype_info",
+	  ktest_make_sample_etype_info);
+    retval = encode_krb5_etype_info((const krb5_etype_info_entry **)info,&(code));
+    if(retval) {
+	com_err("encoding etype_info",retval,"");
+	exit(1);
+    }
+    encoder_print_results(code, "etype_info", "");
+    ktest_destroy_etype_info_entry(info[2]);      info[2] = 0;
+    ktest_destroy_etype_info_entry(info[1]);      info[1] = 0;
+
+    retval = encode_krb5_etype_info((const krb5_etype_info_entry **)info,&(code));
+    if(retval) {
+	com_err("encoding etype_info (only 1)",retval,"");
+	exit(1);
+    }
+    encoder_print_results(code, "etype_info (only 1)", "");
+
+    ktest_destroy_etype_info_entry(info[0]);      info[0] = 0;
+    
+    retval = encode_krb5_etype_info((const krb5_etype_info_entry **)info,&(code));
+    if(retval) {
+	com_err("encoding etype_info (no info)",retval,"");
+	exit(1);
+    }
+    encoder_print_results(code, "etype_info (no info)", "");
+
+    ktest_destroy_etype_info(info);
+  }
+
+  /* encode_etype_info 2*/
+  {
+    krb5_etype_info_entry **info;
+    
+    setup(info,krb5_etype_info_entry **,"etype_info2",
+	  ktest_make_sample_etype_info2);
+    retval = encode_krb5_etype_info2((const krb5_etype_info_entry **)info,&(code));
+    if(retval) {
+	com_err("encoding etype_info",retval,"");
+	exit(1);
+    }
+    encoder_print_results(code, "etype_info2", "");
+    ktest_destroy_etype_info_entry(info[2]);      info[2] = 0;
+    ktest_destroy_etype_info_entry(info[1]);      info[1] = 0;
+
+    retval = encode_krb5_etype_info2((const krb5_etype_info_entry **)info,&(code));
+    if(retval) {
+	com_err("encoding etype_info (only 1)",retval,"");
+	exit(1);
+    }
+    encoder_print_results(code, "etype_info2 (only 1)", "");
+
+    ktest_destroy_etype_info(info);
+/*    ktest_destroy_etype_info_entry(info[0]);      info[0] = 0;*/
+    
+  }
+
+  /****************************************************************/
+  /* encode_pa_enc_ts */
+  {
+    krb5_pa_enc_ts pa_enc;
+    setup(pa_enc,krb5_pa_enc_ts,"pa_enc_ts",ktest_make_sample_pa_enc_ts);
+    encode_run(pa_enc,krb5_pa_enc_ts,"pa_enc_ts","",encode_krb5_pa_enc_ts);
+    pa_enc.pausec = 0;
+    encode_run(pa_enc,krb5_pa_enc_ts,"pa_enc_ts (no usec)","",encode_krb5_pa_enc_ts);
+  }
+
+  /****************************************************************/
+  /* encode_enc_data */
+  {
+    krb5_enc_data enc_data;
+    setup(enc_data,krb5_enc_data,"enc_data",ktest_make_sample_enc_data);
+    current_appl_type = 1001;
+    encode_run(enc_data,krb5_enc_data,"enc_data","",encode_krb5_enc_data);
+    ktest_destroy_enc_data(&enc_data);
+  }
+  /****************************************************************/
+  /* encode_krb5_sam_challenge */
+  {
+    krb5_sam_challenge sam_ch;
+    setup(sam_ch,krb5_sam_challenge,"sam_challenge",
+	  ktest_make_sample_sam_challenge);
+    encode_run(sam_ch,krb5_sam_challenge,"sam_challenge","",
+	       encode_krb5_sam_challenge);
+    ktest_empty_sam_challenge(&sam_ch);
+  }
+  /****************************************************************/
+  /* encode_krb5_sam_response */
+  {
+    krb5_sam_response sam_ch;
+    setup(sam_ch,krb5_sam_response,"sam_response",
+	  ktest_make_sample_sam_response);
+    encode_run(sam_ch,krb5_sam_response,"sam_response","",
+	       encode_krb5_sam_response);
+    ktest_empty_sam_response(&sam_ch);
+  }
+#if 0
+  /****************************************************************/
+  /* encode_krb5_sam_key */
+  {
+    krb5_sam_key sam_ch;
+    setup(sam_ch,krb5_sam_key,"sam_key",
+	  ktest_make_sample_sam_key);
+    encode_run(sam_ch,krb5_sam_key,"sam_key","",
+	       encode_krb5_sam_key);
+  }
+  /****************************************************************/
+  /* encode_krb5_enc_sam_response_enc */
+  {
+    krb5_enc_sam_response_enc sam_ch;
+    setup(sam_ch,krb5_enc_sam_response_enc,"enc_sam_response_enc",
+	  ktest_make_sample_enc_sam_response_enc);
+    encode_run(sam_ch,krb5_enc_sam_response_enc,"enc_sam_response_enc","",
+	       encode_krb5_enc_sam_response_enc);
+  }
+  /****************************************************************/
+  /* encode_krb5_predicted_sam_response */
+  {
+    krb5_predicted_sam_response sam_ch;
+    setup(sam_ch,krb5_predicted_sam_response,"predicted_sam_response",
+	  ktest_make_sample_predicted_sam_response);
+    encode_run(sam_ch,krb5_predicted_sam_response,"predicted_sam_response","",
+	       encode_krb5_predicted_sam_response);
+  }
+#endif
+
+  krb5_free_context(test_context);
+  exit(error_count);
+  return(error_count);
+}
+
+
diff --git a/krb5-1-6/src/tests/asn.1/ktest.c b/krb5-1-6/src/tests/asn.1/ktest.c
new file mode 100644
index 000000000..12ff8fb93
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/ktest.c
@@ -0,0 +1,1291 @@
+#include "ktest.h"
+#include "utility.h"
+#include <stdlib.h>
+
+char *sample_principal_name = "hftsai/extra@ATHENA.MIT.EDU";
+
+krb5_error_code ktest_make_sample_authenticator(a)
+     krb5_authenticator * a;
+{
+  krb5_error_code retval;
+
+  retval = ktest_make_sample_principal(&(a->client));
+  if(retval) return retval;
+  a->checksum = (krb5_checksum*)calloc(1,sizeof(krb5_checksum));
+  if(a->checksum == NULL) return ENOMEM;
+  retval = ktest_make_sample_checksum(a->checksum);
+  if(retval) return retval;
+  a->cusec = SAMPLE_USEC;
+  a->ctime = SAMPLE_TIME;
+  a->subkey = (krb5_keyblock*)calloc(1,sizeof(krb5_keyblock));
+  if(a->subkey == NULL) return ENOMEM;
+  retval = ktest_make_sample_keyblock(a->subkey);
+  if(retval) return retval;
+  a->seq_number = SAMPLE_SEQ_NUMBER;
+  retval = ktest_make_sample_authorization_data(&(a->authorization_data));
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_principal(p)
+     krb5_principal * p;
+{
+  krb5_error_code retval;
+
+  retval = krb5_parse_name(test_context, sample_principal_name, p);
+  return retval;
+}
+
+krb5_error_code ktest_make_sample_checksum(cs)
+     krb5_checksum * cs;
+{
+  cs->checksum_type = 1;
+  cs->length = 4;
+  cs->contents = (krb5_octet*)calloc(4,sizeof(krb5_octet));
+  if(cs->contents == NULL) return ENOMEM;
+  memcpy(cs->contents,"1234",4);
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_keyblock(kb)
+     krb5_keyblock * kb;
+{
+  kb->magic = KV5M_KEYBLOCK;
+  kb->enctype = 1;
+  kb->length = 8;
+  kb->contents = (krb5_octet*)calloc(8,sizeof(krb5_octet));
+  if(kb->contents == NULL) return ENOMEM;
+  memcpy(kb->contents,"12345678",8);
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_ticket(tkt)
+     krb5_ticket * tkt;
+{
+  krb5_error_code retval;
+
+  retval = ktest_make_sample_principal(&(tkt->server));
+  if(retval) return retval;
+  retval = ktest_make_sample_enc_data(&(tkt->enc_part));
+  if(retval) return retval;
+  tkt->enc_part2 = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_enc_data(ed)
+     krb5_enc_data * ed;
+{
+  krb5_error_code retval;
+
+  ed->kvno = 5;
+  ed->enctype = 0;
+  retval = krb5_data_parse(&(ed->ciphertext),"krbASN.1 test message");
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_enc_tkt_part(etp)
+     krb5_enc_tkt_part * etp;
+{
+  krb5_error_code retval;
+
+  etp->flags = SAMPLE_FLAGS;
+  etp->session = (krb5_keyblock*)calloc(1,sizeof(krb5_keyblock));
+  if(etp->session == NULL) return ENOMEM;
+  retval = ktest_make_sample_keyblock(etp->session);
+  if(retval) return retval;
+  retval = ktest_make_sample_principal(&(etp->client));
+  if(retval) return retval;
+  retval = ktest_make_sample_transited(&(etp->transited));
+  if(retval) return retval;
+  retval = ktest_make_sample_ticket_times(&(etp->times));
+  if(retval) return retval;
+  retval = ktest_make_sample_addresses(&(etp->caddrs));
+  if(retval) return retval;
+  retval = ktest_make_sample_authorization_data(&(etp->authorization_data));
+  if(retval) return retval;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_addresses(caddrs)
+     krb5_address *** caddrs;
+{
+  asn1_error_code retval;
+  int i;
+
+  *caddrs = (krb5_address**)calloc(3,sizeof(krb5_address*));
+  if(*caddrs == NULL) return ENOMEM;
+  for(i=0; i<2; i++){
+    (*caddrs)[i] = (krb5_address*)calloc(1,sizeof(krb5_address));
+    if((*caddrs)[i] == NULL) return ENOMEM;
+    retval = ktest_make_sample_address((*caddrs)[i]);
+    if(retval) return retval;
+  }
+  (*caddrs)[2] = NULL;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_authorization_data(ad)
+     krb5_authdata *** ad;
+{
+  krb5_error_code retval;
+  int i;
+
+  *ad = (krb5_authdata**)calloc(3,sizeof(krb5_authdata*));
+  if(*ad == NULL) return ENOMEM;
+
+  for(i=0; i<=1; i++){
+    (*ad)[i] = (krb5_authdata*)calloc(1,sizeof(krb5_authdata));
+    if((*ad)[i] == NULL) return ENOMEM;
+    retval = ktest_make_sample_authdata((*ad)[i]);
+    if(retval) return retval;
+  }
+  (*ad)[2] = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_transited(t)
+     krb5_transited * t;
+{
+  t->tr_type = 1;
+  return krb5_data_parse(&(t->tr_contents),
+			 "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.");
+}
+
+krb5_error_code ktest_make_sample_ticket_times(tt)
+     krb5_ticket_times * tt;
+{
+  tt->authtime = SAMPLE_TIME;
+  tt->starttime = SAMPLE_TIME;
+  tt->endtime = SAMPLE_TIME;
+  tt->renew_till = SAMPLE_TIME;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_address(a)
+     krb5_address * a;
+{
+  a->addrtype = ADDRTYPE_INET;
+  a->length = 4;
+  a->contents = (krb5_octet*)calloc(4,sizeof(krb5_octet));
+  if(a->contents == NULL) return ENOMEM;
+  a->contents[0] = 18;
+  a->contents[1] = 208;
+  a->contents[2] = 0;
+  a->contents[3] = 35;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_authdata(ad)
+     krb5_authdata * ad;
+{
+  ad->ad_type = 1;
+  ad->length = 6;
+  ad->contents = (krb5_octet*)calloc(6,sizeof(krb5_octet));
+  if(ad->contents == NULL) return ENOMEM;
+  memcpy(ad->contents,"foobar",6);
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_enc_kdc_rep_part(ekr)
+     krb5_enc_kdc_rep_part * ekr;
+{
+  krb5_error_code retval;
+
+  ekr->session = (krb5_keyblock*)calloc(1,sizeof(krb5_keyblock));
+  if(ekr->session == NULL) return ENOMEM;
+  retval = ktest_make_sample_keyblock(ekr->session);
+  if(retval) return retval;
+  retval = ktest_make_sample_last_req(&(ekr->last_req));
+  if(retval) return retval;
+  ekr->nonce = SAMPLE_NONCE;
+  ekr->key_exp = SAMPLE_TIME;
+  ekr->flags = SAMPLE_FLAGS;
+  ekr->times.authtime = SAMPLE_TIME;
+  ekr->times.starttime = SAMPLE_TIME;
+  ekr->times.endtime = SAMPLE_TIME;
+  ekr->times.renew_till = SAMPLE_TIME;
+  retval = ktest_make_sample_principal(&(ekr->server));
+  if(retval) return retval;
+  retval = ktest_make_sample_addresses(&(ekr->caddrs));
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_last_req(lr)
+     krb5_last_req_entry *** lr;
+{
+  krb5_error_code retval;
+  int i;
+
+  *lr = (krb5_last_req_entry**)calloc(3,sizeof(krb5_last_req_entry*));
+  if(*lr == NULL) return ENOMEM;
+  for(i=0; i<=1; i++){
+    retval = ktest_make_sample_last_req_entry(&((*lr)[i]));
+    if(retval) return retval;
+  }
+  (*lr)[2] = NULL;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_last_req_entry(lre)
+     krb5_last_req_entry ** lre;
+{
+  *lre = (krb5_last_req_entry*)calloc(1,sizeof(krb5_last_req_entry));
+  if(*lre == NULL) return ENOMEM;
+  (*lre)->lr_type = -5;
+  (*lre)->value = SAMPLE_TIME;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_kdc_rep(kdcr)
+     krb5_kdc_rep * kdcr;
+{
+  krb5_error_code retval;
+
+  retval = ktest_make_sample_pa_data_array(&(kdcr->padata));
+  if(retval) return retval;
+  retval = ktest_make_sample_principal(&(kdcr->client));
+  if(retval) return retval;
+  kdcr->ticket = (krb5_ticket*)calloc(1,sizeof(krb5_ticket));
+  if(kdcr->ticket == NULL) return ENOMEM;
+  retval = ktest_make_sample_ticket(kdcr->ticket);
+  if(retval) return retval;
+  retval = ktest_make_sample_enc_data(&(kdcr->enc_part));
+  if(retval) return retval;
+  kdcr->enc_part2 = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_pa_data_array(pad)
+     krb5_pa_data *** pad;
+{
+  krb5_error_code retval;
+  int i;
+
+  *pad = (krb5_pa_data**)calloc(3,sizeof(krb5_pa_data*));
+  if(*pad == NULL) return ENOMEM;
+
+  for(i=0; i<=1; i++){
+    (*pad)[i] = (krb5_pa_data*)calloc(1,sizeof(krb5_pa_data));
+    if((*pad)[i] == NULL) return ENOMEM;
+    retval = ktest_make_sample_pa_data((*pad)[i]);
+    if(retval) return retval;
+  }
+  (*pad)[2] = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_empty_pa_data_array(pad)
+     krb5_pa_data *** pad;
+{
+  *pad = (krb5_pa_data**)calloc(1,sizeof(krb5_pa_data*));
+  if(*pad == NULL) return ENOMEM;
+
+  (*pad)[0] = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_pa_data(pad)
+     krb5_pa_data * pad;
+{
+  pad->pa_type = 13;
+  pad->length = 7;
+  pad->contents = (krb5_octet*)calloc(7,sizeof(krb5_octet));
+  if(pad->contents == NULL) return ENOMEM;
+  memcpy(pad->contents,"pa-data",7);
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_ap_req(ar)
+     krb5_ap_req * ar;
+{
+  krb5_error_code retval;
+  ar->ap_options = SAMPLE_FLAGS;
+  ar->ticket = (krb5_ticket*)calloc(1,sizeof(krb5_ticket));
+  if(ar->ticket == NULL) return ENOMEM;
+  retval = ktest_make_sample_ticket(ar->ticket);
+  if(retval) return retval;
+  retval = ktest_make_sample_enc_data(&(ar->authenticator));
+  if(retval) return retval;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_ap_rep(ar)
+     krb5_ap_rep * ar;
+{
+  return ktest_make_sample_enc_data(&(ar->enc_part));
+}
+
+krb5_error_code ktest_make_sample_ap_rep_enc_part(arep)
+     krb5_ap_rep_enc_part * arep;
+{
+  krb5_error_code retval;
+
+  arep->ctime = SAMPLE_TIME;
+  arep->cusec = SAMPLE_USEC;
+  arep->subkey = (krb5_keyblock*)calloc(1,sizeof(krb5_keyblock));
+  if(arep->subkey == NULL) return ENOMEM;
+  retval = ktest_make_sample_keyblock(arep->subkey);
+  if(retval) return retval;
+  arep->seq_number = SAMPLE_SEQ_NUMBER;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_kdc_req(kr)
+     krb5_kdc_req * kr;
+{
+  krb5_error_code retval;
+
+  /* msg_type is left up to the calling procedure */
+  retval = ktest_make_sample_pa_data_array(&(kr->padata));
+  if(retval) return retval;
+  kr->kdc_options = SAMPLE_FLAGS;
+  retval = ktest_make_sample_principal(&(kr->client));
+  if(retval) return retval;
+  retval = ktest_make_sample_principal(&(kr->server));
+  if(retval) return retval;
+  kr->from = SAMPLE_TIME;
+  kr->till = SAMPLE_TIME;
+  kr->rtime = SAMPLE_TIME;
+  kr->nonce = SAMPLE_NONCE;
+  kr->nktypes = 2;
+  kr->ktype = (krb5_enctype*)calloc(2,sizeof(krb5_enctype));
+  kr->ktype[0] = 0;
+  kr->ktype[1] = 1;
+  retval = ktest_make_sample_addresses(&(kr->addresses));
+  if(retval) return retval;
+  retval = ktest_make_sample_enc_data(&(kr->authorization_data));
+  if(retval) return retval;
+  retval = ktest_make_sample_authorization_data(&(kr->unenc_authdata));
+  if(retval) return retval;
+  retval = ktest_make_sample_sequence_of_ticket(&(kr->second_ticket));
+  if(retval) return retval;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_kdc_req_body(krb)
+     krb5_kdc_req * krb;
+{
+  krb5_error_code retval;
+
+  krb->kdc_options = SAMPLE_FLAGS;
+  retval = ktest_make_sample_principal(&(krb->client));
+  if(retval) return retval;
+  retval = ktest_make_sample_principal(&(krb->server));
+  if(retval) return retval;
+  krb->from = SAMPLE_TIME;
+  krb->till = SAMPLE_TIME;
+  krb->rtime = SAMPLE_TIME;
+  krb->nonce = SAMPLE_NONCE;
+  krb->nktypes = 2;
+  krb->ktype = (krb5_enctype*)calloc(2,sizeof(krb5_enctype));
+  krb->ktype[0] = 0;
+  krb->ktype[1] = 1;
+  retval = ktest_make_sample_addresses(&(krb->addresses));
+  if(retval) return retval;
+  retval = ktest_make_sample_enc_data(&(krb->authorization_data));
+  if(retval) return retval;
+  retval = ktest_make_sample_authorization_data(&(krb->unenc_authdata));
+  if(retval) return retval;
+  retval = ktest_make_sample_sequence_of_ticket(&(krb->second_ticket));
+  if(retval) return retval;
+  return 0;
+}
+  
+krb5_error_code ktest_make_sample_safe(s)
+     krb5_safe * s;
+{
+  krb5_error_code retval;
+
+  retval = ktest_make_sample_data(&(s->user_data));
+  if(retval) return retval;
+  s->timestamp = SAMPLE_TIME;
+  s->usec = SAMPLE_USEC;
+  s->seq_number = SAMPLE_SEQ_NUMBER;
+  s->s_address = (krb5_address*)calloc(1,sizeof(krb5_address));
+  if(s->s_address == NULL) return ENOMEM;
+  retval = ktest_make_sample_address(s->s_address);
+  if(retval) return retval;
+  s->r_address = (krb5_address*)calloc(1,sizeof(krb5_address));
+  if(s->r_address == NULL) return ENOMEM;
+  retval = ktest_make_sample_address(s->r_address);
+  if(retval) return retval;
+  s->checksum = (krb5_checksum*)calloc(1,sizeof(krb5_checksum));
+  if(s->checksum == NULL) return ENOMEM;
+  retval = ktest_make_sample_checksum(s->checksum);
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_priv(p)
+     krb5_priv * p;
+{
+  return ktest_make_sample_enc_data(&(p->enc_part));
+}
+
+krb5_error_code ktest_make_sample_priv_enc_part(pep)
+     krb5_priv_enc_part * pep;
+{
+  krb5_error_code retval;
+  retval = ktest_make_sample_data(&(pep->user_data));
+  if(retval) return retval;
+  pep->timestamp = SAMPLE_TIME;
+  pep->usec = SAMPLE_USEC;
+  pep->seq_number = SAMPLE_SEQ_NUMBER;
+  pep->s_address = (krb5_address*)calloc(1,sizeof(krb5_address));
+  if(pep->s_address == NULL) return ENOMEM;
+  retval = ktest_make_sample_address(pep->s_address);
+  if(retval) return retval;
+  pep->r_address = (krb5_address*)calloc(1,sizeof(krb5_address));
+  if(pep->r_address == NULL) return ENOMEM;
+  retval = ktest_make_sample_address(pep->r_address);
+  if(retval) return retval;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_cred(c)
+     krb5_cred * c;
+{
+  krb5_error_code retval;
+  retval = ktest_make_sample_sequence_of_ticket(&(c->tickets));
+  if(retval) return retval;
+  retval = ktest_make_sample_enc_data(&(c->enc_part));
+  if(retval) return retval;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_sequence_of_ticket(sot)
+     krb5_ticket *** sot;
+{
+  krb5_error_code retval;
+  int i;
+
+  *sot = (krb5_ticket**)calloc(3,sizeof(krb5_ticket*));
+  if(*sot == NULL) return ENOMEM;
+  for(i=0; i<2; i++){
+    (*sot)[i] = (krb5_ticket*)calloc(1,sizeof(krb5_ticket));
+    if((*sot)[i] == NULL) return ENOMEM;
+    retval = ktest_make_sample_ticket((*sot)[i]);
+    if(retval) return retval;
+  }
+  (*sot)[2] = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_cred_enc_part(cep)
+     krb5_cred_enc_part * cep;
+{
+  krb5_error_code retval;
+
+  cep->nonce = SAMPLE_NONCE;
+  cep->timestamp = SAMPLE_TIME;
+  cep->usec = SAMPLE_USEC;
+  cep->s_address = (krb5_address*)calloc(1,sizeof(krb5_address));
+  if(cep->s_address == NULL) return ENOMEM;
+  retval = ktest_make_sample_address(cep->s_address);
+  if(retval) return retval;
+  cep->r_address = (krb5_address*)calloc(1,sizeof(krb5_address));
+  if(cep->r_address == NULL) return ENOMEM;
+  retval = ktest_make_sample_address(cep->r_address);
+  if(retval) return retval;
+  retval = ktest_make_sequence_of_cred_info(&(cep->ticket_info));
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sequence_of_cred_info(soci)
+     krb5_cred_info *** soci;
+{
+  krb5_error_code retval;
+  int i;
+
+  *soci = (krb5_cred_info**)calloc(3,sizeof(krb5_cred_info*));
+  if(*soci == NULL) return ENOMEM;
+  for(i=0; i<2; i++){
+    (*soci)[i] = (krb5_cred_info*)calloc(1,sizeof(krb5_cred_info));
+    if((*soci)[i] == NULL) return ENOMEM;
+    retval = ktest_make_sample_cred_info((*soci)[i]);
+    if(retval) return retval;
+  }
+  (*soci)[2] = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_cred_info(ci)
+     krb5_cred_info * ci;
+{
+  krb5_error_code retval;
+
+  ci->session = (krb5_keyblock*)calloc(1,sizeof(krb5_keyblock));
+  if(ci->session == NULL) return ENOMEM;
+  retval = ktest_make_sample_keyblock(ci->session);
+  if(retval) return retval;
+  retval = ktest_make_sample_principal(&(ci->client));
+  if(retval) return retval;
+  retval = ktest_make_sample_principal(&(ci->server));
+  if(retval) return retval;
+  ci->flags = SAMPLE_FLAGS;
+  ci->times.authtime = SAMPLE_TIME;
+  ci->times.starttime = SAMPLE_TIME;
+  ci->times.endtime = SAMPLE_TIME;
+  ci->times.renew_till = SAMPLE_TIME;
+  retval = ktest_make_sample_addresses(&(ci->caddrs));
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_error(kerr)
+     krb5_error * kerr;
+{
+  krb5_error_code retval;
+
+  kerr->ctime = SAMPLE_TIME;
+  kerr->cusec = SAMPLE_USEC;
+  kerr->susec = SAMPLE_USEC;
+  kerr->stime = SAMPLE_TIME;
+  kerr->error = SAMPLE_ERROR;
+  retval = ktest_make_sample_principal(&(kerr->client));
+  if(retval) return retval;
+  retval = ktest_make_sample_principal(&(kerr->server));
+  if(retval) return retval;
+  retval = ktest_make_sample_data(&(kerr->text));
+  if(retval) return retval;
+  retval = ktest_make_sample_data(&(kerr->e_data));
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_data(d)
+     krb5_data * d;
+{
+  d->data = (char*)calloc(8,sizeof(char));
+  if(d->data == NULL) return ENOMEM;
+  d->length = 8;
+  memcpy(d->data,"krb5data",8);
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_passwd_phrase_element(ppe)
+     passwd_phrase_element * ppe;
+{
+  krb5_error_code retval;
+
+  ppe->passwd = (krb5_data*)calloc(1,sizeof(krb5_data));
+  if(ppe->passwd == NULL) return ENOMEM;
+  retval = ktest_make_sample_data(ppe->passwd);
+  if(retval) return retval;
+  ppe->phrase = (krb5_data*)calloc(1,sizeof(krb5_data));
+  if(ppe->phrase == NULL) return ENOMEM;
+  retval = ktest_make_sample_data(ppe->phrase);
+  if(retval) return retval;
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_krb5_pwd_data(pd)
+     krb5_pwd_data * pd;
+{
+  krb5_error_code retval;
+  int i;
+
+  pd->sequence_count = 2;
+
+  pd->element = (passwd_phrase_element**)calloc(3,sizeof(passwd_phrase_element*));
+  if(pd->element == NULL) return ENOMEM;
+
+  for(i=0; i<=1; i++){
+    pd->element[i] = (passwd_phrase_element*)calloc(1,sizeof(passwd_phrase_element));
+    if(pd->element[i] == NULL) return ENOMEM;
+    retval = ktest_make_sample_passwd_phrase_element(pd->element[i]);
+    if(retval) return retval;
+  }
+  pd->element[2] = NULL;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_alt_method(p)
+     krb5_alt_method * p;
+{
+    p->method = 42;
+    p->data = (krb5_octet *) strdup("secret");
+    if(p->data == NULL) return ENOMEM;
+    p->length = strlen((char *) p->data);
+    return 0;
+}
+
+krb5_error_code ktest_make_sample_etype_info(p)
+     krb5_etype_info_entry *** p;
+{
+    krb5_etype_info_entry **info;
+    int	i;
+    char buf[80];
+
+    info = malloc(sizeof(krb5_etype_info_entry *) * 4);
+    if (!info)
+	return ENOMEM;
+    memset(info, 0, sizeof(krb5_etype_info_entry *) * 4);
+
+    for (i=0; i < 3; i++) {
+	info[i] = malloc(sizeof(krb5_etype_info_entry));
+	if (info[i] == 0)
+	    goto memfail;
+	info[i]->etype = i;
+	sprintf(buf, "Morton's #%d", i);
+	info[i]->length = strlen(buf);
+	info[i]->salt = malloc((size_t) (info[i]->length+1));
+	if (info[i]->salt == 0)
+	    goto memfail;
+	strcpy((char *) info[i]->salt, buf);
+	info[i]->s2kparams.data = NULL;
+	info[i]->s2kparams.length = 0;
+	info[i]->magic = KV5M_ETYPE_INFO_ENTRY;
+    }
+    free(info[1]->salt);
+    info[1]->length = KRB5_ETYPE_NO_SALT;
+    info[1]->salt = 0;
+    *p = info;
+    return 0;
+memfail:
+    ktest_destroy_etype_info(info);
+    return ENOMEM;
+}
+
+
+krb5_error_code ktest_make_sample_etype_info2(p)
+     krb5_etype_info_entry *** p;
+{
+    krb5_etype_info_entry **info;
+    int	i;
+    char buf[80];
+
+    info = malloc(sizeof(krb5_etype_info_entry *) * 4);
+    if (!info)
+	return ENOMEM;
+    memset(info, 0, sizeof(krb5_etype_info_entry *) * 4);
+
+    for (i=0; i < 3; i++) {
+	info[i] = malloc(sizeof(krb5_etype_info_entry));
+	if (info[i] == 0)
+	    goto memfail;
+	info[i]->etype = i;
+	sprintf(buf, "Morton's #%d", i);
+	info[i]->length = strlen(buf);
+	info[i]->salt = malloc((size_t) (info[i]->length+1));
+	if (info[i]->salt == 0)
+	    goto memfail;
+	strcpy((char *) info[i]->salt, buf);
+	sprintf(buf, "s2k: %d", i);
+	info[i]->s2kparams.data = malloc(strlen(buf)+1);
+	if (info[i]->s2kparams.data == NULL)
+	    goto memfail;
+	strcpy( info[i]->s2kparams.data, buf);
+	info[i]->s2kparams.length = strlen(buf);
+	info[i]->magic = KV5M_ETYPE_INFO_ENTRY;
+    }
+    free(info[1]->salt);
+    info[1]->length = KRB5_ETYPE_NO_SALT;
+    info[1]->salt = 0;
+    *p = info;
+    return 0;
+memfail:
+    ktest_destroy_etype_info(info);
+    return ENOMEM;
+}
+
+
+krb5_error_code ktest_make_sample_pa_enc_ts(pa_enc)
+     krb5_pa_enc_ts * pa_enc;
+{
+  pa_enc->patimestamp = SAMPLE_TIME;
+  pa_enc->pausec = SAMPLE_USEC;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_sam_challenge(p)
+     krb5_sam_challenge * p;
+{
+  krb5_error_code retval;
+
+  p->magic = KV5M_SAM_CHALLENGE;
+  p->sam_type = 42; /* information */
+  p->sam_flags = KRB5_SAM_USE_SAD_AS_KEY; /* KRB5_SAM_* values */
+  p->sam_type_name.data = strdup("type name");
+  if (p->sam_type_name.data == NULL) return ENOMEM;
+  p->sam_type_name.length = strlen(p->sam_type_name.data);
+  p->sam_track_id.data = 0;
+  p->sam_track_id.length = 0;
+  p->sam_challenge_label.data = strdup("challenge label");
+  if (p->sam_challenge_label.data == NULL) return ENOMEM;
+  p->sam_challenge_label.length = strlen(p->sam_challenge_label.data);
+  p->sam_challenge.data = strdup("challenge ipse");
+  if (p->sam_challenge.data == NULL) return ENOMEM;
+  p->sam_challenge.length = strlen(p->sam_challenge.data);
+  p->sam_response_prompt.data = strdup("response_prompt ipse");
+  if (p->sam_response_prompt.data == NULL) return ENOMEM;
+  p->sam_response_prompt.length = strlen(p->sam_response_prompt.data);
+  p->sam_pk_for_sad.data = 0;
+  p->sam_pk_for_sad.length = 0;
+  p->sam_nonce = 0x543210;
+  retval = ktest_make_sample_checksum(&p->sam_cksum);
+  if(retval) return retval;
+
+  return 0;
+}
+
+krb5_error_code ktest_make_sample_sam_response(p)
+     krb5_sam_response * p;
+{
+  p->magic = KV5M_SAM_RESPONSE;
+  p->sam_type = 42; /* information */
+  p->sam_flags = KRB5_SAM_USE_SAD_AS_KEY; /* KRB5_SAM_* values */
+  p->sam_track_id.data = strdup("track data");
+  if (p->sam_track_id.data == NULL) return ENOMEM;
+  p->sam_track_id.length = strlen(p->sam_track_id.data);
+  p->sam_enc_key.ciphertext.data = strdup("key");
+  if (p->sam_enc_key.ciphertext.data == NULL) return ENOMEM;
+  p->sam_enc_key.ciphertext.length = strlen(p->sam_enc_key.ciphertext.data);
+  p->sam_enc_key.enctype = ENCTYPE_DES_CBC_CRC;
+  p->sam_enc_key.kvno = 1942;
+  p->sam_enc_nonce_or_ts.ciphertext.data = strdup("nonce or ts");
+  if (p->sam_enc_nonce_or_ts.ciphertext.data == NULL) return ENOMEM;
+  p->sam_enc_nonce_or_ts.ciphertext.length = 
+    strlen(p->sam_enc_nonce_or_ts.ciphertext.data);
+  p->sam_enc_nonce_or_ts.enctype = ENCTYPE_DES_CBC_CRC;
+  p->sam_enc_nonce_or_ts.kvno = 3382;
+  p->sam_nonce = 0x543210;
+  p->sam_patimestamp = SAMPLE_TIME;
+
+  return 0;
+}
+
+
+
+
+
+/****************************************************************/
+/* destructors */
+
+void ktest_destroy_data(d)
+     krb5_data ** d;
+{
+  if(*d != NULL){
+    if((*d)->data != NULL) free((*d)->data);
+    free(*d);
+    *d = NULL;
+  }
+}
+
+void ktest_empty_data(d)
+     krb5_data * d;
+{
+  if(d->data != NULL){
+    free(d->data);
+    d->data = NULL;
+    d->length = 0;
+  }
+}  
+
+void ktest_destroy_checksum(cs)
+     krb5_checksum ** cs;
+{
+  if(*cs != NULL){
+    if((*cs)->contents != NULL) free((*cs)->contents);
+    free(*cs);
+    *cs = NULL;
+  }
+}
+
+void ktest_empty_keyblock(kb)
+     krb5_keyblock * kb;
+{
+  if (kb != NULL) {
+    if (kb->contents) {
+      free (kb->contents);
+      kb->contents = NULL;
+    }
+  }
+}
+
+void ktest_destroy_keyblock(kb)
+     krb5_keyblock ** kb;
+{
+  if(*kb != NULL){
+    if((*kb)->contents != NULL) free((*kb)->contents);
+    free(*kb);
+    *kb = NULL;
+  }
+}
+
+void ktest_empty_authorization_data(ad)
+     krb5_authdata ** ad;
+{
+  int i;
+
+  if(*ad != NULL) {
+    for(i=0; ad[i] != NULL; i++)
+      ktest_destroy_authdata(&(ad[i]));
+  }
+}
+
+void ktest_destroy_authorization_data(ad)
+     krb5_authdata *** ad;
+{
+  ktest_empty_authorization_data(*ad);
+  free(*ad);
+  *ad = NULL;
+}
+
+void ktest_destroy_authdata(ad)
+     krb5_authdata ** ad;
+{
+  if(*ad != NULL){
+    if((*ad)->contents != NULL) free((*ad)->contents);
+    free(*ad);
+    *ad = NULL;
+  }
+}
+
+void ktest_empty_pa_data_array(pad)
+     krb5_pa_data ** pad;
+{
+  int i;
+
+  for(i=0; pad[i] != NULL; i++)
+    ktest_destroy_pa_data(&(pad[i]));
+}
+
+void ktest_destroy_pa_data_array(pad)
+     krb5_pa_data *** pad;
+{
+  ktest_empty_pa_data_array(*pad);
+  free(*pad);
+  *pad = NULL;
+}
+
+void ktest_destroy_pa_data(pad)
+     krb5_pa_data ** pad;
+{
+  if(*pad != NULL){
+    if((*pad)->contents != NULL) free((*pad)->contents);
+    free(*pad);
+    *pad = NULL;
+  }
+}
+
+
+void ktest_destroy_address(a)
+     krb5_address ** a;
+{
+  if(*a != NULL){
+    if((*a)->contents != NULL) free((*a)->contents);
+    free(*a);
+    *a = NULL;
+  }
+}
+
+void ktest_empty_addresses(a)
+     krb5_address ** a;
+{
+  int i;
+
+  for(i=0; a[i] != NULL; i++)
+    ktest_destroy_address(&(a[i]));
+}  
+
+void ktest_destroy_addresses(a)
+     krb5_address *** a;
+{
+  ktest_empty_addresses(*a);
+  free(*a);
+  *a = NULL;
+}
+
+void ktest_destroy_principal(p)
+     krb5_principal * p;
+{
+  int i;
+
+  for(i=0; i<(*p)->length; i++)
+    ktest_empty_data(&(((*p)->data)[i]));
+  ktest_empty_data(&((*p)->realm));
+  free((*p)->data);
+  free(*p);
+  *p = NULL;
+}
+
+void ktest_destroy_sequence_of_integer(soi)
+     long ** soi;
+{
+  free(*soi);
+  *soi = NULL;
+}
+
+#if 0
+void ktest_destroy_sequence_of_enctype(soi)
+     krb5_enctype ** soi;
+{
+  free(*soi);
+  *soi = NULL;
+}
+#endif
+
+void ktest_destroy_sequence_of_ticket(sot)
+     krb5_ticket *** sot;
+{
+  int i;
+
+  for(i=0; (*sot)[i] != NULL; i++)
+    ktest_destroy_ticket(&((*sot)[i]));
+  free(*sot);
+  *sot = NULL;
+}
+
+void ktest_destroy_ticket(tkt)
+     krb5_ticket ** tkt;
+{
+  ktest_destroy_principal(&((*tkt)->server));
+  ktest_destroy_enc_data(&((*tkt)->enc_part));
+  /*  ktest_empty_enc_tkt_part(((*tkt)->enc_part2));*/
+  free(*tkt);
+  *tkt = NULL;
+}  
+
+void ktest_empty_ticket(tkt)
+     krb5_ticket * tkt;
+{
+  if(tkt->server)
+    ktest_destroy_principal(&((tkt)->server));
+  ktest_destroy_enc_data(&((tkt)->enc_part));
+  if (tkt->enc_part2) {
+    ktest_destroy_enc_tkt_part(&(tkt->enc_part2));
+  }
+}  
+
+void ktest_destroy_enc_data(ed)
+     krb5_enc_data * ed;
+{
+  ktest_empty_data(&(ed->ciphertext));
+  ed->kvno = 0;
+}
+
+void ktest_destroy_etype_info_entry(i)
+    krb5_etype_info_entry *i;
+{
+    if (i->salt)
+	free(i->salt);
+    ktest_empty_data(&(i->s2kparams));
+    free(i);
+}
+
+void ktest_destroy_etype_info(info)
+    krb5_etype_info_entry **info;
+{
+  int i;
+
+  for(i=0; info[i] != NULL; i++)
+      ktest_destroy_etype_info_entry(info[i]);
+  free(info);
+}
+    
+
+void ktest_empty_kdc_req(kr)
+     krb5_kdc_req *kr;
+{
+  if (kr->padata)
+      ktest_destroy_pa_data_array(&(kr->padata));
+
+  if (kr->client)
+      ktest_destroy_principal(&(kr->client));
+
+  if (kr->server)
+      ktest_destroy_principal(&(kr->server));
+  if (kr->ktype)
+      free(kr->ktype);
+  if (kr->addresses)
+      ktest_destroy_addresses(&(kr->addresses));
+      ktest_destroy_enc_data(&(kr->authorization_data));
+  if (kr->unenc_authdata)
+      ktest_destroy_authorization_data(&(kr->unenc_authdata));
+  if (kr->second_ticket)
+      ktest_destroy_sequence_of_ticket(&(kr->second_ticket));
+
+}
+
+void ktest_empty_kdc_rep(kr)
+     krb5_kdc_rep *kr;
+{
+  if (kr->padata)
+      ktest_destroy_pa_data_array(&(kr->padata));
+
+  if (kr->client)
+      ktest_destroy_principal(&(kr->client));
+
+  if (kr->ticket)
+      ktest_destroy_ticket(&(kr->ticket));
+
+  ktest_destroy_enc_data(&kr->enc_part);
+
+  if (kr->enc_part2) {
+    ktest_empty_enc_kdc_rep_part(kr->enc_part2);
+    free(kr->enc_part2);
+    kr->enc_part2 = NULL;
+  }
+}
+
+
+void ktest_empty_authenticator(a)
+     krb5_authenticator * a;
+{
+
+  if(a->client) 
+    ktest_destroy_principal(&(a->client));
+  if(a->checksum)
+    ktest_destroy_checksum(&(a->checksum));
+  if(a->subkey)
+    ktest_destroy_keyblock(&(a->subkey));
+  if(a->authorization_data)
+    ktest_destroy_authorization_data(&(a->authorization_data));
+}
+
+void ktest_empty_enc_tkt_part(etp)
+     krb5_enc_tkt_part * etp;
+{
+
+  if(etp->session)
+    ktest_destroy_keyblock(&(etp->session));
+  if(etp->client) 
+    ktest_destroy_principal(&(etp->client));
+  if (etp->caddrs)
+      ktest_destroy_addresses(&(etp->caddrs));
+  if(etp->authorization_data)
+    ktest_destroy_authorization_data(&(etp->authorization_data));
+  ktest_destroy_transited(&(etp->transited));
+}
+
+void ktest_destroy_enc_tkt_part(etp)
+     krb5_enc_tkt_part ** etp;
+{
+  if(*etp) {
+    ktest_empty_enc_tkt_part(*etp);
+    free(*etp);
+    *etp = NULL;
+  }
+}
+
+void ktest_empty_enc_kdc_rep_part(ekr)
+     krb5_enc_kdc_rep_part * ekr;
+{
+
+  if(ekr->session)
+    ktest_destroy_keyblock(&(ekr->session));
+
+  if(ekr->server) 
+    ktest_destroy_principal(&(ekr->server));
+
+  if (ekr->caddrs)
+    ktest_destroy_addresses(&(ekr->caddrs));
+  ktest_destroy_last_req(&(ekr->last_req));
+}
+
+
+void ktest_destroy_transited(t)
+     krb5_transited * t;
+{
+  if(t->tr_contents.data)
+    ktest_empty_data(&(t->tr_contents));
+}
+
+
+void ktest_empty_ap_rep(ar)
+     krb5_ap_rep * ar;
+{
+  ktest_destroy_enc_data(&ar->enc_part);
+}
+
+void ktest_empty_ap_req(ar)
+     krb5_ap_req * ar;
+{
+
+  if(ar->ticket)
+      ktest_destroy_ticket(&(ar->ticket));
+  ktest_destroy_enc_data(&(ar->authenticator));
+}
+
+void ktest_empty_cred_enc_part(cep)
+     krb5_cred_enc_part * cep;
+{
+  if (cep->s_address)
+      ktest_destroy_address(&(cep->s_address));
+  if (cep->r_address)
+      ktest_destroy_address(&(cep->r_address));
+  if (cep->ticket_info)
+    ktest_destroy_sequence_of_cred_info(&(cep->ticket_info));
+}
+
+void ktest_destroy_cred_info(ci)
+     krb5_cred_info ** ci;
+{
+  if((*ci)->session)
+    ktest_destroy_keyblock(&((*ci)->session));
+  if((*ci)->client) 
+    ktest_destroy_principal(&((*ci)->client));
+  if((*ci)->server) 
+    ktest_destroy_principal(&((*ci)->server));
+  if ((*ci)->caddrs)
+    ktest_destroy_addresses(&((*ci)->caddrs));
+  free(*ci);
+  *ci = NULL;
+}
+
+void ktest_destroy_sequence_of_cred_info(soci)
+     krb5_cred_info *** soci;
+{
+  int i;
+
+  for(i=0; (*soci)[i] != NULL; i++)
+    ktest_destroy_cred_info(&((*soci)[i]));
+  free(*soci);
+  *soci = NULL;
+}
+
+
+void ktest_empty_safe(s)
+     krb5_safe * s;
+{
+  ktest_empty_data(&(s->user_data));
+  ktest_destroy_address(&(s->s_address));
+  ktest_destroy_address(&(s->r_address));
+  ktest_destroy_checksum(&(s->checksum));
+}
+
+void ktest_empty_priv_enc_part(pep)
+     krb5_priv_enc_part * pep;
+{
+  ktest_empty_data(&(pep->user_data));
+  ktest_destroy_address(&(pep->s_address));
+  ktest_destroy_address(&(pep->r_address));
+}
+
+void ktest_empty_priv(p)
+     krb5_priv * p;
+{
+  ktest_destroy_enc_data(&(p->enc_part));
+}
+
+void ktest_empty_cred(c)
+     krb5_cred * c;
+{
+
+  ktest_destroy_sequence_of_ticket(&(c->tickets));
+  ktest_destroy_enc_data(&(c->enc_part));
+  /* enc_part2 */
+
+}
+
+void ktest_destroy_last_req(lr)
+     krb5_last_req_entry *** lr;
+{
+  int i;
+
+  if(*lr) {
+    for(i=0; (*lr)[i] != NULL; i++) {
+      free((*lr)[i]);
+    }
+    free(*lr);
+  }
+}
+
+void ktest_empty_error(kerr)
+     krb5_error * kerr;
+{
+  if(kerr->client)
+    ktest_destroy_principal(&(kerr->client));
+  if(kerr->server)
+    ktest_destroy_principal(&(kerr->server));
+  ktest_empty_data(&(kerr->text));
+  ktest_empty_data(&(kerr->e_data));
+}
+
+void ktest_empty_ap_rep_enc_part(arep)
+     krb5_ap_rep_enc_part * arep;
+{
+  ktest_destroy_keyblock(&((arep)->subkey));
+}
+
+void ktest_empty_passwd_phrase_element(ppe)
+     passwd_phrase_element * ppe;
+{
+  ktest_destroy_data(&(ppe->passwd));
+  ktest_destroy_data(&(ppe->phrase));
+}
+
+void ktest_empty_pwd_data(pd)
+     krb5_pwd_data * pd;
+{
+  int i;
+
+  for(i=0; i <= pd->sequence_count; i++){
+    if(pd->element[i]) {
+      ktest_empty_passwd_phrase_element(pd->element[i]);
+      free(pd->element[i]);
+      pd->element[i] = NULL;
+    }
+  }
+  free(pd->element);
+  
+}
+
+void ktest_empty_alt_method(am)
+     krb5_alt_method *am;
+{
+  if (am->data) {
+    free(am->data);
+    am->data = NULL;
+  }
+}
+
+void ktest_empty_sam_challenge(p)
+     krb5_sam_challenge * p;
+{
+  ktest_empty_data(&(p->sam_type_name));
+  ktest_empty_data(&(p->sam_track_id));
+  ktest_empty_data(&(p->sam_challenge_label));
+  ktest_empty_data(&(p->sam_challenge));
+  ktest_empty_data(&(p->sam_response_prompt));
+  ktest_empty_data(&(p->sam_pk_for_sad));
+
+  if(p->sam_cksum.contents != NULL) {
+    free(p->sam_cksum.contents);
+    p->sam_cksum.contents = NULL;
+  }
+
+}
+
+void ktest_empty_sam_response(p)
+     krb5_sam_response * p;
+{
+  ktest_empty_data(&(p->sam_track_id));
+  ktest_empty_data(&(p->sam_enc_key.ciphertext));
+  ktest_empty_data(&(p->sam_enc_nonce_or_ts.ciphertext));
+}
diff --git a/krb5-1-6/src/tests/asn.1/ktest.h b/krb5-1-6/src/tests/asn.1/ktest.h
new file mode 100644
index 000000000..915f36a00
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/ktest.h
@@ -0,0 +1,204 @@
+#ifndef __KTEST_H__
+#define __KTEST_H__
+
+#include "k5-int.h"
+
+#define SAMPLE_USEC 123456
+#define SAMPLE_TIME 771228197  /* Fri Jun 10  6:03:17 GMT 1994 */
+#define SAMPLE_SEQ_NUMBER 17
+#define SAMPLE_NONCE 42
+#define SAMPLE_FLAGS 0xFEDCBA98
+#define SAMPLE_ERROR 0x3C;
+krb5_error_code ktest_make_sample_data
+	(krb5_data *d);
+krb5_error_code ktest_make_sample_authenticator
+	(krb5_authenticator *a);
+  krb5_error_code ktest_make_sample_principal
+	(krb5_principal *p);
+  krb5_error_code ktest_make_sample_checksum
+	(krb5_checksum *cs);
+  krb5_error_code ktest_make_sample_keyblock
+	(krb5_keyblock *kb);
+krb5_error_code ktest_make_sample_ticket
+	(krb5_ticket *tkt);
+  krb5_error_code ktest_make_sample_enc_data
+	(krb5_enc_data *ed);
+krb5_error_code ktest_make_sample_enc_tkt_part
+	(krb5_enc_tkt_part *etp);
+  krb5_error_code ktest_make_sample_transited
+	(krb5_transited *t);
+  krb5_error_code ktest_make_sample_ticket_times
+	(krb5_ticket_times *tt);
+  krb5_error_code ktest_make_sample_addresses
+	(krb5_address ***caddrs);
+  krb5_error_code ktest_make_sample_address
+	(krb5_address *a);
+  krb5_error_code ktest_make_sample_authorization_data
+	(krb5_authdata ***ad);
+  krb5_error_code ktest_make_sample_authdata
+	(krb5_authdata *ad);
+krb5_error_code ktest_make_sample_enc_kdc_rep_part
+	(krb5_enc_kdc_rep_part *ekr);
+krb5_error_code ktest_make_sample_kdc_req
+	(krb5_kdc_req *kr);
+
+  krb5_error_code ktest_make_sample_last_req
+	(krb5_last_req_entry ***lr);
+  krb5_error_code ktest_make_sample_last_req_entry
+	(krb5_last_req_entry **lre);
+krb5_error_code ktest_make_sample_kdc_rep
+	(krb5_kdc_rep *kdcr);
+  krb5_error_code ktest_make_sample_pa_data_array
+	(krb5_pa_data ***pad);
+  krb5_error_code ktest_make_sample_empty_pa_data_array
+	(krb5_pa_data ***pad);
+  krb5_error_code ktest_make_sample_pa_data
+	(krb5_pa_data *pad);
+krb5_error_code ktest_make_sample_ap_req
+	(krb5_ap_req *ar);
+krb5_error_code ktest_make_sample_ap_rep
+	(krb5_ap_rep *ar);
+krb5_error_code ktest_make_sample_ap_rep_enc_part
+	(krb5_ap_rep_enc_part *arep);
+krb5_error_code ktest_make_sample_kdc_req_body
+	(krb5_kdc_req *krb);
+krb5_error_code ktest_make_sample_safe
+	(krb5_safe *s);
+krb5_error_code ktest_make_sample_priv
+	(krb5_priv *p);
+krb5_error_code ktest_make_sample_priv_enc_part
+	(krb5_priv_enc_part *pep);
+krb5_error_code ktest_make_sample_cred
+	(krb5_cred *c);
+krb5_error_code ktest_make_sample_cred_enc_part
+	(krb5_cred_enc_part *cep);
+  krb5_error_code ktest_make_sample_sequence_of_ticket
+	(krb5_ticket ***sot);
+krb5_error_code ktest_make_sample_error
+	(krb5_error *kerr);
+krb5_error_code ktest_make_sequence_of_cred_info
+	(krb5_cred_info ***soci);
+  krb5_error_code ktest_make_sample_cred_info
+	(krb5_cred_info *ci);
+krb5_error_code ktest_make_sample_passwd_phrase_element
+	(passwd_phrase_element *ppe);
+krb5_error_code ktest_make_sample_krb5_pwd_data
+	(krb5_pwd_data *pd);
+krb5_error_code ktest_make_sample_alt_method
+	(krb5_alt_method *am);
+
+krb5_error_code ktest_make_sample_etype_info
+    (krb5_etype_info_entry *** p);
+krb5_error_code ktest_make_sample_etype_info2
+    (krb5_etype_info_entry *** p);
+krb5_error_code ktest_make_sample_pa_enc_ts
+	(krb5_pa_enc_ts *am);
+krb5_error_code ktest_make_sample_sam_challenge
+	(krb5_sam_challenge * p);
+krb5_error_code ktest_make_sample_sam_response
+	(krb5_sam_response * p);
+
+/*----------------------------------------------------------------------*/
+
+void ktest_empty_authorization_data
+	(krb5_authdata **ad);
+void ktest_destroy_authorization_data
+	(krb5_authdata ***ad);
+  void ktest_destroy_authorization_data
+	(krb5_authdata ***ad);
+void ktest_empty_addresses
+	(krb5_address **a);
+void ktest_destroy_addresses
+	(krb5_address ***a);
+  void ktest_destroy_address
+	(krb5_address **a);
+void ktest_empty_pa_data_array
+	(krb5_pa_data **pad);
+void ktest_destroy_pa_data_array
+	(krb5_pa_data ***pad);
+  void ktest_destroy_pa_data
+	(krb5_pa_data **pad);
+
+void ktest_destroy_data
+	(krb5_data **d);
+void ktest_empty_data
+	(krb5_data *d);
+void ktest_destroy_principal
+	(krb5_principal *p);
+void ktest_destroy_checksum
+	(krb5_checksum **cs);
+void ktest_empty_keyblock
+	(krb5_keyblock *kb);
+void ktest_destroy_keyblock
+	(krb5_keyblock **kb);
+void ktest_destroy_authdata
+	(krb5_authdata **ad);
+void ktest_destroy_sequence_of_integer
+	(long **soi);
+void ktest_destroy_sequence_of_ticket
+	(krb5_ticket ***sot);
+  void ktest_destroy_ticket
+	(krb5_ticket **tkt);
+void ktest_empty_ticket
+	(krb5_ticket *tkt);
+void ktest_destroy_enc_data
+	(krb5_enc_data *ed);
+void ktest_empty_error
+        (krb5_error * kerr);
+void ktest_destroy_etype_info_entry
+	(krb5_etype_info_entry *i);
+void ktest_destroy_etype_info
+	(krb5_etype_info_entry **info);
+
+void ktest_empty_kdc_req
+        (krb5_kdc_req *kr);
+void ktest_empty_kdc_rep
+        (krb5_kdc_rep *kr);
+
+void ktest_empty_authenticator
+        (krb5_authenticator *a);
+void ktest_empty_enc_tkt_part
+        (krb5_enc_tkt_part * etp);
+void ktest_destroy_enc_tkt_part
+        (krb5_enc_tkt_part ** etp);
+void ktest_empty_enc_kdc_rep_part
+        (krb5_enc_kdc_rep_part * ekr);
+void ktest_destroy_transited
+        (krb5_transited * t);
+void ktest_empty_ap_rep
+        (krb5_ap_rep * ar);
+void ktest_empty_ap_req
+        (krb5_ap_req * ar);
+void ktest_empty_cred_enc_part
+        (krb5_cred_enc_part * cep);
+void ktest_destroy_cred_info
+        (krb5_cred_info ** ci);
+void ktest_destroy_sequence_of_cred_info
+        (krb5_cred_info *** soci);
+void ktest_empty_safe
+        (krb5_safe * s);
+void ktest_empty_priv
+        (krb5_priv * p);
+void ktest_empty_priv_enc_part
+        (krb5_priv_enc_part * pep);
+void ktest_empty_cred
+        (krb5_cred * c);
+void ktest_destroy_last_req
+        (krb5_last_req_entry *** lr);
+void ktest_empty_ap_rep_enc_part
+        (krb5_ap_rep_enc_part * arep);
+void ktest_empty_passwd_phrase_element
+        (passwd_phrase_element * ppe);
+void ktest_empty_pwd_data
+        (krb5_pwd_data * pd);
+void ktest_empty_alt_method
+	(krb5_alt_method *am);
+void ktest_empty_sam_challenge
+	(krb5_sam_challenge * p);
+void ktest_empty_sam_response
+	(krb5_sam_response * p);
+
+extern krb5_context test_context;
+extern char *sample_principal_name;
+
+#endif
diff --git a/krb5-1-6/src/tests/asn.1/ktest_equal.c b/krb5-1-6/src/tests/asn.1/ktest_equal.c
new file mode 100644
index 000000000..7f2fa44b1
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/ktest_equal.c
@@ -0,0 +1,669 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "ktest_equal.h"
+
+#define FALSE 0
+#define TRUE 1
+
+#define struct_equal(field,comparator)\
+comparator(&(ref->field),&(var->field))
+
+#define ptr_equal(field,comparator)\
+comparator(ref->field,var->field)
+
+#define scalar_equal(field)\
+((ref->field) == (var->field))
+
+#define len_equal(length,field,comparator)\
+((ref->length == var->length) && \
+ comparator(ref->length,ref->field,var->field))
+
+int ktest_equal_authenticator(ref, var)
+     krb5_authenticator * ref;
+     krb5_authenticator * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p = p && ptr_equal(client,ktest_equal_principal_data);
+  p = p && ptr_equal(checksum,ktest_equal_checksum);
+  p = p && scalar_equal(cusec);
+  p = p && scalar_equal(ctime);
+  p = p && ptr_equal(subkey,ktest_equal_keyblock);
+  p = p && scalar_equal(seq_number);
+  p = p && ptr_equal(authorization_data,ktest_equal_authorization_data);
+  return p;
+}
+
+int ktest_equal_principal_data(ref, var)
+     krb5_principal_data * ref;
+     krb5_principal_data * var;
+{
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  return(struct_equal(realm,ktest_equal_data) &&
+	 len_equal(length,data,ktest_equal_array_of_data) &&
+	 scalar_equal(type));
+}
+
+int ktest_equal_authdata(ref, var)
+     krb5_authdata * ref;
+     krb5_authdata * var;
+{
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  return(scalar_equal(ad_type) &&
+	 len_equal(length,contents,ktest_equal_array_of_octet));
+}
+
+int ktest_equal_checksum(ref, var)
+     krb5_checksum * ref;
+     krb5_checksum * var;
+{
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  return(scalar_equal(checksum_type) && len_equal(length,contents,ktest_equal_array_of_octet));
+}
+
+int ktest_equal_keyblock(ref, var)
+     krb5_keyblock * ref;
+     krb5_keyblock * var;
+{
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  return(scalar_equal(enctype) && len_equal(length,contents,ktest_equal_array_of_octet));
+}
+
+int ktest_equal_data(ref, var)
+     krb5_data * ref;
+     krb5_data * var;
+{
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  return(len_equal(length,data,ktest_equal_array_of_char));
+}
+
+int ktest_equal_ticket(ref, var)
+     krb5_ticket * ref;
+     krb5_ticket * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p = p && ptr_equal(server,ktest_equal_principal_data);
+  p = p && struct_equal(enc_part,ktest_equal_enc_data);
+  /* enc_part2 is irrelevant, as far as the ASN.1 code is concerned */
+  return p;
+}
+
+int ktest_equal_enc_data(ref, var)
+     krb5_enc_data * ref;
+     krb5_enc_data * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(enctype);
+  p=p&&scalar_equal(kvno);
+  p=p&&struct_equal(ciphertext,ktest_equal_data);
+  return p;
+}
+
+int ktest_equal_encryption_key(ref, var)
+     krb5_keyblock * ref;
+     krb5_keyblock * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p = p && scalar_equal(enctype);
+  p = p && len_equal(length,contents,ktest_equal_array_of_octet);
+  return p;
+}
+
+int ktest_equal_enc_tkt_part(ref, var)
+     krb5_enc_tkt_part * ref;
+     krb5_enc_tkt_part * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p = p && scalar_equal(flags);
+  p = p && ptr_equal(session,ktest_equal_encryption_key);
+  p = p && ptr_equal(client,ktest_equal_principal_data);
+  p = p && struct_equal(transited,ktest_equal_transited);
+  p = p && struct_equal(times,ktest_equal_ticket_times);
+  p = p && ptr_equal(caddrs,ktest_equal_addresses);
+  p = p && ptr_equal(authorization_data,ktest_equal_authorization_data);
+  return p;
+}
+
+int ktest_equal_transited(ref, var)
+     krb5_transited * ref;
+     krb5_transited * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p = p && scalar_equal(tr_type);
+  p = p && struct_equal(tr_contents,ktest_equal_data);
+  return p;
+}
+
+int ktest_equal_ticket_times(ref, var)
+     krb5_ticket_times * ref;
+     krb5_ticket_times * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p = p && scalar_equal(authtime);
+  p = p && scalar_equal(starttime);
+  p = p && scalar_equal(endtime);
+  p = p && scalar_equal(renew_till);
+  return p;
+}
+
+int ktest_equal_address(ref, var)
+     krb5_address * ref;
+     krb5_address * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(addrtype);
+  p=p&&len_equal(length,contents,ktest_equal_array_of_octet);
+  return p;
+}
+
+int ktest_equal_enc_kdc_rep_part(ref, var)
+     krb5_enc_kdc_rep_part * ref;
+     krb5_enc_kdc_rep_part * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&ptr_equal(session,ktest_equal_keyblock);
+  p=p&&ptr_equal(last_req,ktest_equal_last_req);
+  p=p&&scalar_equal(nonce);
+  p=p&&scalar_equal(key_exp);
+  p=p&&scalar_equal(flags);
+  p=p&&struct_equal(times,ktest_equal_ticket_times);
+  p=p&&ptr_equal(server,ktest_equal_principal_data);
+  p=p&&ptr_equal(caddrs,ktest_equal_addresses);
+  return p;
+}
+
+int ktest_equal_priv(ref, var)
+     krb5_priv * ref;
+     krb5_priv * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&struct_equal(enc_part,ktest_equal_enc_data);
+  return p;
+}
+
+int ktest_equal_cred(ref, var)
+     krb5_cred * ref;
+     krb5_cred * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&ptr_equal(tickets,ktest_equal_sequence_of_ticket);
+  p=p&&struct_equal(enc_part,ktest_equal_enc_data);
+  return p;
+}
+
+int ktest_equal_error(ref, var)
+     krb5_error * ref;
+     krb5_error * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(ctime);
+  p=p&&scalar_equal(cusec);
+  p=p&&scalar_equal(susec);
+  p=p&&scalar_equal(stime);
+  p=p&&scalar_equal(error);
+  p=p&&ptr_equal(client,ktest_equal_principal_data);
+  p=p&&ptr_equal(server,ktest_equal_principal_data);
+  p=p&&struct_equal(text,ktest_equal_data);
+  p=p&&struct_equal(e_data,ktest_equal_data);
+  return p;
+}
+
+int ktest_equal_ap_req(ref, var)
+     krb5_ap_req * ref;
+     krb5_ap_req * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(ap_options);
+  p=p&&ptr_equal(ticket,ktest_equal_ticket);
+  p=p&&struct_equal(authenticator,ktest_equal_enc_data);
+  return p;
+}
+
+int ktest_equal_ap_rep(ref, var)
+     krb5_ap_rep * ref;
+     krb5_ap_rep * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&struct_equal(enc_part,ktest_equal_enc_data);
+  return p;
+}
+
+int ktest_equal_ap_rep_enc_part(ref, var)
+     krb5_ap_rep_enc_part * ref;
+     krb5_ap_rep_enc_part * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(ctime);
+  p=p&&scalar_equal(cusec);
+  p=p&&ptr_equal(subkey,ktest_equal_encryption_key);
+  p=p&&scalar_equal(seq_number);
+  return p;
+}
+
+int ktest_equal_safe(ref, var)
+     krb5_safe * ref;
+     krb5_safe * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&struct_equal(user_data,ktest_equal_data);
+  p=p&&scalar_equal(timestamp);
+  p=p&&scalar_equal(usec);
+  p=p&&scalar_equal(seq_number);
+  p=p&&ptr_equal(s_address,ktest_equal_address);
+  p=p&&ptr_equal(r_address,ktest_equal_address);
+  p=p&&ptr_equal(checksum,ktest_equal_checksum);
+  return p;
+}
+
+
+int ktest_equal_enc_cred_part(ref, var)
+     krb5_cred_enc_part * ref;
+     krb5_cred_enc_part * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(nonce);
+  p=p&&scalar_equal(timestamp);
+  p=p&&scalar_equal(usec);
+  p=p&&ptr_equal(s_address,ktest_equal_address);
+  p=p&&ptr_equal(r_address,ktest_equal_address);
+  p=p&&ptr_equal(ticket_info,ktest_equal_sequence_of_cred_info);
+  return p;
+}
+
+int ktest_equal_enc_priv_part(ref, var)
+     krb5_priv_enc_part * ref;
+     krb5_priv_enc_part * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&struct_equal(user_data,ktest_equal_data);
+  p=p&&scalar_equal(timestamp);
+  p=p&&scalar_equal(usec);
+  p=p&&scalar_equal(seq_number);
+  p=p&&ptr_equal(s_address,ktest_equal_address);
+  p=p&&ptr_equal(r_address,ktest_equal_address);
+  return p;
+}
+
+int ktest_equal_as_rep(ref, var)
+     krb5_kdc_rep * ref;
+     krb5_kdc_rep * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(msg_type);
+  p=p&&ptr_equal(padata,ktest_equal_sequence_of_pa_data);
+  p=p&&ptr_equal(client,ktest_equal_principal_data);
+  p=p&&ptr_equal(ticket,ktest_equal_ticket);
+  p=p&&struct_equal(enc_part,ktest_equal_enc_data);
+  p=p&&ptr_equal(enc_part2,ktest_equal_enc_kdc_rep_part);
+  return p;
+}
+
+int ktest_equal_tgs_rep(ref, var)
+     krb5_kdc_rep * ref;
+     krb5_kdc_rep * var;
+{
+  return ktest_equal_as_rep(ref,var);
+}
+
+int ktest_equal_as_req(ref, var)
+     krb5_kdc_req * ref;
+     krb5_kdc_req * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(msg_type);
+  p=p&&ptr_equal(padata,ktest_equal_sequence_of_pa_data);
+  p=p&&scalar_equal(kdc_options);
+  p=p&&ptr_equal(client,ktest_equal_principal_data);
+  p=p&&ptr_equal(server,ktest_equal_principal_data);
+  p=p&&scalar_equal(from);
+  p=p&&scalar_equal(till);
+  p=p&&scalar_equal(rtime);
+  p=p&&scalar_equal(nonce);
+  p=p&&len_equal(nktypes,ktype,ktest_equal_array_of_enctype);
+  p=p&&ptr_equal(addresses,ktest_equal_addresses);
+  p=p&&struct_equal(authorization_data,ktest_equal_enc_data);
+/* This field isn't actually in the ASN.1 encoding. */
+/* p=p&&ptr_equal(unenc_authdata,ktest_equal_authorization_data); */
+  return p;
+}
+
+int ktest_equal_tgs_req(ref, var)
+     krb5_kdc_req * ref;
+     krb5_kdc_req * var;
+{
+  return ktest_equal_as_req(ref,var);
+}
+
+int ktest_equal_kdc_req_body(ref, var)
+     krb5_kdc_req * ref;
+     krb5_kdc_req * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(kdc_options);
+  p=p&&ptr_equal(client,ktest_equal_principal_data);
+  p=p&&ptr_equal(server,ktest_equal_principal_data);
+  p=p&&scalar_equal(from);
+  p=p&&scalar_equal(till);
+  p=p&&scalar_equal(rtime);
+  p=p&&scalar_equal(nonce);
+  p=p&&len_equal(nktypes,ktype,ktest_equal_array_of_enctype);
+  p=p&&ptr_equal(addresses,ktest_equal_addresses);
+  p=p&&struct_equal(authorization_data,ktest_equal_enc_data);
+  /* This isn't part of the ASN.1 encoding. */
+  /* p=p&&ptr_equal(unenc_authdata,ktest_equal_authorization_data); */
+  return p;
+}
+
+int ktest_equal_last_req_entry(ref, var)
+     krb5_last_req_entry * ref;
+     krb5_last_req_entry * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(lr_type);
+  p=p&&scalar_equal(value);
+  return p;
+}
+
+int ktest_equal_pa_data(ref, var)
+     krb5_pa_data * ref;
+     krb5_pa_data * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(pa_type);
+  p=p&&len_equal(length,contents,ktest_equal_array_of_octet);
+  return p;
+}
+
+int ktest_equal_cred_info(ref, var)
+     krb5_cred_info * ref;
+     krb5_cred_info * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&ptr_equal(session,ktest_equal_keyblock);
+  p=p&&ptr_equal(client,ktest_equal_principal_data);
+  p=p&&ptr_equal(server,ktest_equal_principal_data);
+  p=p&&scalar_equal(flags);
+  p=p&&struct_equal(times,ktest_equal_ticket_times);
+  p=p&&ptr_equal(caddrs,ktest_equal_addresses);
+
+  return p;
+}
+
+int ktest_equal_passwd_phrase_element(ref, var)
+     passwd_phrase_element * ref;
+     passwd_phrase_element * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&ptr_equal(passwd,ktest_equal_data);
+  p=p&&ptr_equal(phrase,ktest_equal_data);
+  return p;
+}
+
+int ktest_equal_krb5_pwd_data(ref, var)
+     krb5_pwd_data * ref;
+     krb5_pwd_data * var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(sequence_count);
+  p=p&&ptr_equal(element,ktest_equal_array_of_passwd_phrase_element);
+  return p;
+}
+
+int ktest_equal_krb5_alt_method(ref, var)
+    krb5_alt_method *ref;
+    krb5_alt_method *var;
+{
+    if (ref->method != var->method)
+	return FALSE;
+    if (ref->length != var->length)
+	return FALSE;
+    if (memcmp(ref->data, var->data, ref->length) != 0)
+	return FALSE;
+    return TRUE;
+}
+
+int ktest_equal_krb5_etype_info_entry(ref, var)
+    krb5_etype_info_entry *ref;
+    krb5_etype_info_entry *var;
+{
+    if (ref->etype != var->etype)
+	return FALSE;
+    if (ref->length != var->length)
+	return FALSE;
+    if (ref->length > 0 && ref->length != KRB5_ETYPE_NO_SALT)
+    	if (memcmp(ref->salt, var->salt, ref->length) != 0)
+	    return FALSE;
+    return TRUE;
+}
+
+int ktest_equal_krb5_pa_enc_ts(ref, var)
+    krb5_pa_enc_ts *ref;
+    krb5_pa_enc_ts *var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(patimestamp);
+  p=p&&scalar_equal(pausec);
+  return p;
+}
+
+#define equal_str(f) struct_equal(f,ktest_equal_data)
+
+int ktest_equal_sam_challenge(ref, var)
+     krb5_sam_challenge *ref;
+     krb5_sam_challenge *var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(sam_type);
+  p=p&&scalar_equal(sam_flags);
+  p=p&&scalar_equal(sam_nonce);
+  p=p&&ktest_equal_checksum(&ref->sam_cksum,&var->sam_cksum);
+  p=p&&equal_str(sam_track_id);
+  p=p&&equal_str(sam_challenge_label);
+  p=p&&equal_str(sam_challenge);
+  p=p&&equal_str(sam_response_prompt);
+  p=p&&equal_str(sam_pk_for_sad);
+  return p;
+}
+
+int ktest_equal_sam_response(ref, var)
+     krb5_sam_response *ref;
+     krb5_sam_response *var;
+{
+  int p=TRUE;
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  p=p&&scalar_equal(sam_type);
+  p=p&&scalar_equal(sam_flags);
+  p=p&&equal_str(sam_track_id);
+  p=p&&struct_equal(sam_enc_key,ktest_equal_enc_data);
+  p=p&&struct_equal(sam_enc_nonce_or_ts,ktest_equal_enc_data);
+  p=p&&scalar_equal(sam_nonce);
+  p=p&&scalar_equal(sam_patimestamp);
+  return p;
+}
+
+/**** arrays ****************************************************************/
+
+int ktest_equal_array_of_data(length, ref, var)
+     const int length;
+     krb5_data * ref;
+     krb5_data * var;
+{
+  int i,p=TRUE;
+
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  for(i=0; i<(length); i++){
+    p = p && ktest_equal_data(&(ref[i]),&(var[i]));
+  }
+  return p;
+}
+
+int ktest_equal_array_of_octet(length, ref, var)
+     const unsigned int length;
+     krb5_octet * ref;
+     krb5_octet * var;
+{
+  int i, p=TRUE;
+
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  for(i=0; i<length; i++)
+    p = p && (ref[i] == var[i]);
+  return p;
+}
+
+int ktest_equal_array_of_char(length, ref, var)
+     const unsigned int length;
+     char * ref;
+     char * var;
+{
+  int i, p=TRUE;
+
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  for(i=0; i<length; i++)
+    p = p && (ref[i] == var[i]);
+  return p;
+}
+
+int ktest_equal_array_of_enctype(length, ref, var)
+     const int length;
+     krb5_enctype * ref;
+     krb5_enctype * var;
+{
+  int i, p=TRUE;
+
+  if(ref==var) return TRUE;
+  else if(ref == NULL || var == NULL) return FALSE;
+  for(i=0; i<length; i++)
+    p = p && (ref[i] == var[i]);
+  return p;
+}
+
+#define array_compare(comparator)\
+int i,p=TRUE;\
+if(ref==var) return TRUE;\
+if(!ref || !ref[0])\
+  return (!var || !var[0]);\
+if(!var || !var[0]) return FALSE;\
+for(i=0; ref[i] != NULL && var[i] != NULL; i++)\
+  p = p && comparator(ref[i],var[i]);\
+if(ref[i] == NULL && var[i] == NULL) return p;\
+else return FALSE
+
+int ktest_equal_authorization_data(ref, var)
+     krb5_authdata ** ref;
+     krb5_authdata ** var;
+{
+  array_compare(ktest_equal_authdata);
+}
+
+int ktest_equal_addresses(ref, var)
+     krb5_address ** ref;
+     krb5_address ** var;
+{
+  array_compare(ktest_equal_address);
+}
+
+int ktest_equal_last_req(ref, var)
+     krb5_last_req_entry ** ref;
+     krb5_last_req_entry ** var;
+{
+  array_compare(ktest_equal_last_req_entry);
+}
+
+int ktest_equal_sequence_of_ticket(ref, var)
+     krb5_ticket ** ref;
+     krb5_ticket ** var;
+{
+  array_compare(ktest_equal_ticket);
+}
+
+int ktest_equal_sequence_of_pa_data(ref, var)
+     krb5_pa_data ** ref;
+     krb5_pa_data ** var;
+{
+  array_compare(ktest_equal_pa_data);
+}
+
+int ktest_equal_sequence_of_cred_info(ref, var)
+     krb5_cred_info ** ref;
+     krb5_cred_info ** var;
+{
+  array_compare(ktest_equal_cred_info);
+}
+
+int ktest_equal_array_of_passwd_phrase_element(ref, var)
+     passwd_phrase_element ** ref;
+     passwd_phrase_element ** var;
+{
+  array_compare(ktest_equal_passwd_phrase_element);
+}
+
+int ktest_equal_etype_info(ref, var)
+     krb5_etype_info_entry ** ref;
+     krb5_etype_info_entry ** var;
+{
+  array_compare(ktest_equal_krb5_etype_info_entry);
+}
diff --git a/krb5-1-6/src/tests/asn.1/ktest_equal.h b/krb5-1-6/src/tests/asn.1/ktest_equal.h
new file mode 100644
index 000000000..d45cf51a3
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/ktest_equal.h
@@ -0,0 +1,93 @@
+#ifndef __KTEST_EQUAL_H__
+#define __KTEST_EQUAL_H__
+
+#include "k5-int.h"
+
+/* int ktest_equal_structure(krb5_structure *ref, *var) */
+/* effects  Returns true (non-zero) if ref and var are
+             semantically equivalent (i.e. have the same values,
+	     but aren't necessarily the same object).
+	    Returns false (zero) if ref and var differ. */
+
+#define generic(funcname,type)\
+int funcname (type *ref, type *var)
+
+#define len_array(funcname,type)\
+int funcname (const int length, type *ref, type *var)
+#define len_unsigned_array(funcname,type)\
+int funcname (const unsigned int length, type *ref, type *var)
+
+generic(ktest_equal_authenticator,krb5_authenticator);
+generic(ktest_equal_principal_data,krb5_principal_data);
+generic(ktest_equal_checksum,krb5_checksum);
+generic(ktest_equal_keyblock,krb5_keyblock);
+generic(ktest_equal_data,krb5_data);
+generic(ktest_equal_authdata,krb5_authdata);
+generic(ktest_equal_ticket,krb5_ticket);
+generic(ktest_equal_enc_tkt_part,krb5_enc_tkt_part);
+generic(ktest_equal_transited,krb5_transited);
+generic(ktest_equal_ticket_times,krb5_ticket_times);
+generic(ktest_equal_address,krb5_address);
+generic(ktest_equal_enc_data,krb5_enc_data);
+
+generic(ktest_equal_enc_kdc_rep_part,krb5_enc_kdc_rep_part);
+generic(ktest_equal_priv,krb5_priv);
+generic(ktest_equal_cred,krb5_cred);
+generic(ktest_equal_error,krb5_error);
+generic(ktest_equal_ap_req,krb5_ap_req);
+generic(ktest_equal_ap_rep,krb5_ap_rep);
+generic(ktest_equal_ap_rep_enc_part,krb5_ap_rep_enc_part);
+generic(ktest_equal_safe,krb5_safe);
+
+generic(ktest_equal_last_req_entry,krb5_last_req_entry);
+generic(ktest_equal_pa_data,krb5_pa_data);
+generic(ktest_equal_cred_info,krb5_cred_info);
+
+generic(ktest_equal_enc_cred_part,krb5_cred_enc_part);
+generic(ktest_equal_enc_priv_part,krb5_priv_enc_part);
+generic(ktest_equal_as_rep,krb5_kdc_rep);
+generic(ktest_equal_tgs_rep,krb5_kdc_rep);
+generic(ktest_equal_as_req,krb5_kdc_req);
+generic(ktest_equal_tgs_req,krb5_kdc_req);
+generic(ktest_equal_kdc_req_body,krb5_kdc_req);
+generic(ktest_equal_encryption_key,krb5_keyblock);
+
+generic(ktest_equal_passwd_phrase_element,passwd_phrase_element);
+generic(ktest_equal_krb5_pwd_data,krb5_pwd_data);
+generic(ktest_equal_krb5_alt_method,krb5_alt_method);
+generic(ktest_equal_krb5_pa_enc_ts,krb5_pa_enc_ts);
+
+generic(ktest_equal_sam_challenge,krb5_sam_challenge);
+generic(ktest_equal_sam_response,krb5_sam_response);
+
+int ktest_equal_last_req
+	(krb5_last_req_entry **ref, krb5_last_req_entry **var);
+int ktest_equal_sequence_of_ticket
+	(krb5_ticket **ref, krb5_ticket **var);
+int ktest_equal_sequence_of_pa_data
+	(krb5_pa_data **ref, krb5_pa_data **var);
+int ktest_equal_sequence_of_cred_info
+	(krb5_cred_info **ref, krb5_cred_info **var);
+
+len_array(ktest_equal_array_of_enctype,krb5_enctype);
+len_array(ktest_equal_array_of_data,krb5_data);
+len_unsigned_array(ktest_equal_array_of_octet,krb5_octet);
+
+int ktest_equal_array_of_passwd_phrase_element
+	(passwd_phrase_element **ref, passwd_phrase_element **var);
+int ktest_equal_authorization_data
+	(krb5_authdata **ref, krb5_authdata **var);
+int ktest_equal_addresses
+	(krb5_address **ref, krb5_address **var);
+int ktest_equal_array_of_char
+	(const unsigned int length, char *ref, char *var);
+
+int ktest_equal_etype_info
+    (krb5_etype_info_entry ** ref,
+		    krb5_etype_info_entry ** var);
+
+int ktest_equal_krb5_etype_info_entry
+    (krb5_etype_info_entry * ref,
+		    krb5_etype_info_entry * var);
+
+#endif
diff --git a/krb5-1-6/src/tests/asn.1/reference_encode.out b/krb5-1-6/src/tests/asn.1/reference_encode.out
new file mode 100644
index 000000000..a118c050d
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/reference_encode.out
@@ -0,0 +1,53 @@
+encode_krb5_authenticator: 62 81 A1 30 81 9E A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A7 03 02 01 11 A8 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72
+encode_krb5_authenticator(optionals empty): 62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
+encode_krb5_authenticator(optionals NULL): 62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
+encode_krb5_ticket: 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_keyblock: 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38
+encode_krb5_enc_tkt_part: 63 82 01 14 30 82 01 10 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72
+encode_krb5_enc_tkt_part(optionals NULL): 63 81 A5 30 81 A2 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
+encode_krb5_enc_kdc_rep_part: 7A 82 01 0E 30 82 01 0A A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A4 07 03 05 00 FE DC BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23
+encode_krb5_enc_kdc_rep_part(optionals NULL): 7A 81 B2 30 81 AF A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A4 07 03 05 00 FE 5C BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61
+encode_krb5_as_rep: 6B 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0B A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_as_rep(optionals NULL): 6B 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0B A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_tgs_rep: 6D 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0D A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_tgs_rep(optionals NULL): 6D 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0D A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_ap_req: 6E 81 9D 30 81 9A A0 03 02 01 05 A1 03 02 01 0E A2 07 03 05 00 FE DC BA 98 A3 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A4 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_ap_rep: 6F 33 30 31 A0 03 02 01 05 A1 03 02 01 0F A2 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_ap_rep_enc_part: 7B 36 30 34 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 A2 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A3 03 02 01 11
+encode_krb5_ap_rep_enc_part(optionals NULL): 7B 1C 30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40
+encode_krb5_as_req: 6A 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0A A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_as_req(optionals NULL except second_ticket): 6A 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0A A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_as_req(optionals NULL except server): 6A 69 30 67 A1 03 02 01 05 A2 03 02 01 0A A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01
+encode_krb5_tgs_req: 6C 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0C A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_tgs_req(optionals NULL except second_ticket): 6C 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0C A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_tgs_req(optionals NULL except server): 6C 69 30 67 A1 03 02 01 05 A2 03 02 01 0C A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01
+encode_krb5_kdc_req_body: 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_kdc_req_body(optionals NULL except second_ticket): 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_kdc_req_body(optionals NULL except server): 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01
+encode_krb5_safe: 74 6E 30 6C A0 03 02 01 05 A1 03 02 01 14 A2 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
+encode_krb5_safe(optionals NULL): 74 3E 30 3C A0 03 02 01 05 A1 03 02 01 14 A2 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
+encode_krb5_priv: 75 33 30 31 A0 03 02 01 05 A1 03 02 01 15 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_enc_priv_part: 7C 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23
+encode_krb5_enc_priv_part(optionals NULL): 7C 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23
+encode_krb5_cred: 76 81 F6 30 81 F3 A0 03 02 01 05 A1 03 02 01 16 A2 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_enc_cred_part: 7D 82 02 23 30 82 02 1F A0 82 01 DA 30 82 01 D6 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23
+encode_krb5_enc_cred_part(optionals NULL): 7D 82 01 0E 30 82 01 0A A0 82 01 06 30 82 01 02 30 15 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23
+encode_krb5_error: 7E 81 BA 30 81 B7 A0 03 02 01 05 A1 03 02 01 1E A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A7 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A8 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 0A 1B 08 6B 72 62 35 64 61 74 61 AC 0A 04 08 6B 72 62 35 64 61 74 61
+encode_krb5_error(optionals NULL): 7E 60 30 5E A0 03 02 01 05 A1 03 02 01 1E A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61
+encode_krb5_authorization_data: 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72
+encode_krb5_pwd_sequence: 30 18 A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61
+encode_krb5_pwd_data: 30 3D A0 03 02 01 02 A1 36 30 34 30 18 A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 30 18 A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61
+encode_krb5_padata_sequence: 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61
+encode_krb5_padata_sequence(empty): 30 00
+encode_krb5_alt_method: 30 0F A0 03 02 01 2A A1 08 04 06 73 65 63 72 65 74
+encode_krb5_alt_method (no data): 30 05 A0 03 02 01 2A
+encode_krb5_etype_info: 30 33 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 30 05 A0 03 02 01 01 30 14 A0 03 02 01 02 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 32
+encode_krb5_etype_info (only 1): 30 16 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30
+encode_krb5_etype_info (no info): 30 00
+encode_krb5_etype_info2: 30 51 30 1E A0 03 02 01 00 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 A2 08 04 06 73 32 6B 3A 20 30 30 0F A0 03 02 01 01 A2 08 04 06 73 32 6B 3A 20 31 30 1E A0 03 02 01 02 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 32 A2 08 04 06 73 32 6B 3A 20 32
+encode_krb5_etype_info2 (only 1): 30 20 30 1E A0 03 02 01 00 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 A2 08 04 06 73 32 6B 3A 20 30
+encode_krb5_pa_enc_ts: 30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40
+encode_krb5_pa_enc_ts (no usec): 30 13 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
+encode_krb5_enc_data: 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
+encode_krb5_sam_challenge: 30 70 A0 03 02 01 2A A1 07 03 05 00 80 00 00 00 A2 0B 04 09 74 79 70 65 20 6E 61 6D 65 A4 11 04 0F 63 68 61 6C 6C 65 6E 67 65 20 6C 61 62 65 6C A5 10 04 0E 63 68 61 6C 6C 65 6E 67 65 20 69 70 73 65 A6 16 04 14 72 65 73 70 6F 6E 73 65 5F 70 72 6F 6D 70 74 20 69 70 73 65 A8 05 02 03 54 32 10 A9 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
+encode_krb5_sam_response: 30 6A A0 03 02 01 2A A1 07 03 05 00 80 00 00 00 A2 0C 04 0A 74 72 61 63 6B 20 64 61 74 61 A3 14 30 12 A0 03 02 01 01 A1 04 02 02 07 96 A2 05 04 03 6B 65 79 A4 1C 30 1A A0 03 02 01 01 A1 04 02 02 0D 36 A2 0D 04 0B 6E 6F 6E 63 65 20 6F 72 20 74 73 A5 05 02 03 54 32 10 A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
diff --git a/krb5-1-6/src/tests/asn.1/trval.c b/krb5-1-6/src/tests/asn.1/trval.c
new file mode 100644
index 000000000..fc18bc0e7
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/trval.c
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 1992,1993 Trusted Information Systems, Inc.
+ *
+ * Permission to include this software in the Kerberos V5 distribution
+ * was graciously provided by Trusted Information Systems.
+ * 
+ * Trusted Information Systems makes no representation about the
+ * suitability of this software for any purpose.  It is provided
+ * "as is" without express or implied warranty.
+ * 
+ * Copyright (C) 1994 Massachusetts Institute of Technology
+ * 
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+/*****************************************************************************
+ * trval.c.c
+ *****************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#define OK 0
+#define NOTOK (-1)
+	
+	/* IDENTIFIER OCTET = TAG CLASS | FORM OF ENCODING | TAG NUMBER */
+	
+	/* TAG CLASSES */
+#define ID_CLASS   0xc0		/* bits 8 and 7 */
+#define CLASS_UNIV 0x00		/* 0 = universal */
+#define CLASS_APPL 0x40		/* 1 = application */
+#define CLASS_CONT 0x80		/* 2 = context-specific */
+#define CLASS_PRIV 0xc0		/* 3 = private */
+	
+	/* FORM OF ENCODING */
+#define ID_FORM   0x20		/* bit 6 */
+#define FORM_PRIM 0x00		/* 0 = primitive */
+#define FORM_CONS 0x20		/* 1 = constructed */
+	
+	/* TAG NUMBERS */
+#define ID_TAG    0x1f		/* bits 5-1 */
+#define PRIM_BOOL 0x01		/* Boolean */
+#define PRIM_INT  0x02		/* Integer */
+#define PRIM_BITS 0x03		/* Bit String */
+#define PRIM_OCTS 0x04		/* Octet String */
+#define PRIM_NULL 0x05		/* Null */
+#define PRIM_OID  0x06		/* Object Identifier */
+#define PRIM_ODE  0x07		/* Object Descriptor */
+#define CONS_EXTN 0x08		/* External */
+#define PRIM_REAL 0x09		/* Real */
+#define PRIM_ENUM 0x0a		/* Enumerated type */
+#define PRIM_ENCR 0x0b		/* Encrypted */
+#define CONS_SEQ  0x10		/* SEQUENCE/SEQUENCE OF */
+#define CONS_SET  0x11		/* SET/SET OF */
+#define DEFN_NUMS 0x12		/* Numeric String */
+#define DEFN_PRTS 0x13		/* Printable String */
+#define DEFN_T61S 0x14		/* T.61 String */
+#define DEFN_VTXS 0x15		/* Videotex String */
+#define DEFN_IA5S 0x16		/* IA5 String */
+#define DEFN_UTCT 0x17		/* UTCTime */
+#define DEFN_GENT 0x18		/* Generalized Time */
+#define DEFN_GFXS 0x19		/* Graphics string (ISO2375) */
+#define DEFN_VISS 0x1a		/* Visible string */
+#define DEFN_GENS 0x1b		/* General string */
+#define DEFN_CHRS 0x1c		/* Character string */
+	
+#define	LEN_XTND	0x80	/* long or indefinite form */
+#define	LEN_SMAX	127	/* largest short form */
+#define	LEN_MASK	0x7f	/* mask to get number of bytes in length */
+#define	LEN_INDF	(-1)	/* indefinite length */
+
+#define KRB5	/* Do krb5 application types */
+	
+int print_types = 0;
+int print_id_and_len = 1;
+int print_constructed_length = 1;	
+int print_primitive_length = 1;
+int print_skip_context = 0;
+int print_skip_tagnum = 1;
+int print_context_shortcut = 0;
+int do_hex = 0;
+#ifdef KRB5
+int print_krb5_types = 0;
+#endif
+
+int current_appl_type = -1;
+
+int decode_len (FILE *, unsigned char *, int);
+int do_prim (FILE *, int, unsigned char *, int, int);
+int do_cons (FILE *, unsigned char *, int, int, int *);
+int do_prim_bitstring (FILE *, int, unsigned char *, int, int);
+int do_prim_int (FILE *, int, unsigned char *, int, int);
+int do_prim_string (FILE *, int, unsigned char *, int, int);
+void print_tag_type (FILE *, int, int);
+int trval (FILE *, FILE *);
+int trval2 (FILE *, unsigned char *, int, int, int *);
+
+
+/****************************************************************************/
+
+#ifdef STANDALONE
+
+static void usage()
+{
+	fprintf(stderr, "Usage: trval [--types] [--krb5] [--krb5decode] [--hex] [-notypebytes] [file]\n");
+	exit(1);
+}
+
+/*
+ * Returns true if the option was selected.  Allow "-option" and
+ * "--option" syntax, since we used to accept only "-option"
+ */
+static
+int check_option(word, option)
+	char *word;
+	char *option;
+{
+	if (word[0] != '-')
+		return 0;
+	if (word[1] == '-')
+		word++;
+	if (strcmp(word+1, option))
+		return 0;
+	return 1;
+}
+
+int main(argc, argv)
+	int argc;
+	char **argv;
+{
+	int optflg = 1;
+	FILE *fp;
+	int r = 0;
+	
+	while (--argc > 0) {
+		argv++;
+		if (optflg && *(argv)[0] == '-') {
+			if (check_option(*argv, "help"))
+				usage();
+			else if (check_option(*argv, "types"))
+				print_types = 1;
+			else if (check_option(*argv, "notypes"))
+				print_types = 0;
+			else if (check_option(*argv, "krb5"))
+				print_krb5_types = 1;
+			else if (check_option(*argv, "hex"))
+				do_hex = 1;
+			else if (check_option(*argv, "notypebytes"))
+				print_id_and_len = 0;
+			else if (check_option(*argv, "krb5decode")) {
+				print_id_and_len = 0;
+				print_krb5_types = 1;
+				print_types = 1;
+			} else {
+				fprintf(stderr,"trval: unknown option: %s\n", *argv);
+				usage();
+			}
+		} else {
+			optflg = 0;
+			if ((fp = fopen(*argv,"r")) == NULL) {
+				fprintf(stderr,"trval: unable to open %s\n", *argv);
+				continue;
+			}
+			r = trval(fp, stdout);
+			fclose(fp);
+		}
+	}
+	if (optflg) r = trval(stdin, stdout);
+	
+	exit(r);
+}
+#endif
+
+static int convert_nibble(int ch)
+{
+    if (isdigit(ch))
+	return (ch - '0');
+    if (ch >= 'a' && ch <= 'f')
+	return (ch - 'a' + 10);
+    if (ch >= 'A' && ch <= 'F')
+	return (ch - 'A' + 10);
+    return -1;
+}
+
+int trval(fin, fout)
+	FILE	*fin;
+	FILE	*fout;
+{
+	unsigned char *p;
+	unsigned int maxlen;
+	int len;
+	int cc, cc2, n1, n2;
+	int r;
+	int rlen;
+	
+	maxlen = BUFSIZ;
+	p = (unsigned char *)malloc(maxlen);
+	len = 0;
+	while ((cc = fgetc(fin)) != EOF) {
+		if (len == maxlen) {
+			maxlen += BUFSIZ;
+			p = (unsigned char *)realloc(p, maxlen);
+		}
+		if (do_hex) {
+			if (cc == ' ' || cc == '\n' || cc == '\t')
+				continue;
+			cc2 = fgetc(fin);
+			if (cc2 == EOF)
+				break;
+			n1 = convert_nibble(cc);
+			n2 = convert_nibble(cc2);
+			cc = (n1 << 4) + n2;
+		}
+		p[len++] = cc;
+	}
+	fprintf(fout, "<%d>", len);
+	r = trval2(fout, p, len, 0, &rlen);
+	fprintf(fout, "\n");
+	(void) free(p);
+	return(r);
+}
+
+int trval2(fp, enc, len, lev, rlen)
+	FILE *fp;
+	unsigned char *enc;
+	int len;
+	int lev;
+	int *rlen;
+{
+	int l, eid, elen, xlen, r, rlen2;
+	int rlen_ext = 0;
+
+	r = OK;
+
+	if (len < 2) {
+		fprintf(fp, "missing id and length octets (%d)\n", len);
+		return(NOTOK);
+	}
+	
+	fprintf(fp, "\n");
+	for (l=0; l<lev; l++) fprintf(fp, ".  ");
+	
+context_restart:
+	eid = enc[0];
+	elen = enc[1];
+
+	if (print_id_and_len) {
+		fprintf(fp, "%02x ", eid);
+		fprintf(fp, "%02x ", elen);
+	}
+	
+	if (elen == LEN_XTND) {
+		fprintf(fp,
+			"indefinite length encoding not implemented (0x%02x)\n", elen);
+		return(NOTOK);
+	}
+	
+	xlen = 0;
+	if (elen & LEN_XTND) {
+		xlen = elen & LEN_MASK;
+		if (xlen > len - 2) {
+			fprintf(fp, "extended length too long (%d > %d - 2)\n", xlen, len);
+			return(NOTOK);
+		}
+		elen = decode_len(fp, enc+2, xlen);
+	}
+	
+	if (elen > len - 2 - xlen) {
+		fprintf(fp, "length too long (%d > %d - 2 - %d)\n", elen, len, xlen);
+		return(NOTOK);
+	}
+	
+	print_tag_type(fp, eid, lev);
+
+	if (print_context_shortcut &&
+	    ((eid & ID_CLASS) == CLASS_CONT) && (lev > 0)) {
+		rlen_ext += 2 + xlen;
+		enc += 2 + xlen;
+		goto context_restart;
+	}
+
+	switch(eid & ID_FORM) {
+	case FORM_PRIM:
+		r = do_prim(fp, eid & ID_TAG, enc+2+xlen, elen, lev+1);
+		*rlen = 2 + xlen + elen + rlen_ext;
+		break;
+	case FORM_CONS:
+		if (print_constructed_length) {
+			fprintf(fp, "constr ");
+			fprintf(fp, "<%d>", elen);
+		}
+		r = do_cons(fp, enc+2+xlen, elen, lev+1, &rlen2);
+		*rlen = 2 + xlen + rlen2 + rlen_ext;
+		break;
+	}
+	
+	return(r);
+}
+
+int decode_len(fp, enc, len)
+	FILE *fp;
+	unsigned char *enc;
+	int len;
+{
+	int rlen;
+	int i;
+	
+	if (print_id_and_len)
+		fprintf(fp, "%02x ", enc[0]);
+	rlen = enc[0];
+	for (i=1; i<len; i++) {
+		if (print_id_and_len)
+			fprintf(fp, "%02x ", enc[i]);
+		rlen = (rlen * 0x100) + enc[i];
+	}
+	return(rlen);
+}
+
+/*
+ * This is the printing function for bit strings
+ */
+int do_prim_bitstring(fp, tag, enc, len, lev)
+	FILE *fp;
+	int tag;
+	unsigned char *enc;
+	int len;
+	int lev;
+{
+	int	i;
+	long	num = 0;
+
+	if (tag != PRIM_BITS || len > 5)
+		return 0;
+
+	for (i=1; i < len; i++) {
+		num = num << 8;
+		num += enc[i];
+	}
+
+	fprintf(fp, "0x%lx", num);
+	if (enc[0])
+		fprintf(fp, " (%d unused bits)", enc[0]);
+	return 1;
+}
+
+/*
+ * This is the printing function for integers
+ */
+int do_prim_int(fp, tag, enc, len, lev)
+	FILE *fp;
+	int tag;
+	unsigned char *enc;
+	int len;
+	int lev;
+{
+	int	i;
+	long	num = 0;
+
+	if (tag != PRIM_INT || len > 4)
+		return 0;
+
+	if (enc[0] & 0x80)
+		num = -1;
+
+	for (i=0; i < len; i++) {
+		num = num << 8;
+		num += enc[i];
+	}
+
+	fprintf(fp, "%ld", num);
+	return 1;
+}
+
+
+/*
+ * This is the printing function which we use if it's a string or
+ * other other type which is best printed as a string
+ */
+int do_prim_string(fp, tag, enc, len, lev)
+	FILE *fp;
+	int tag;
+	unsigned char *enc;
+	int len;
+	int lev;
+{
+	int	i;
+
+	/*
+	 * Only try this printing function with "reasonable" types
+	 */
+	if ((tag < DEFN_NUMS) && (tag != PRIM_OCTS))
+		return 0;
+
+	for (i=0; i < len; i++)
+		if (!isprint(enc[i]))
+			return 0;
+	fprintf(fp, "\"%.*s\"", len, enc);
+	return 1;
+}
+
+int do_prim(fp, tag, enc, len, lev)
+	FILE *fp;
+	int tag;
+	unsigned char *enc;
+	int len;
+	int lev;
+{
+	int n;
+	int i;
+	int j;
+	int width;
+
+	if (do_prim_string(fp, tag, enc, len, lev))
+		return OK;
+	if (do_prim_int(fp, tag, enc, len, lev))
+		return OK;
+	if (do_prim_bitstring(fp, tag, enc, len, lev))
+		return OK;
+
+	if (print_primitive_length)
+		fprintf(fp, "<%d>", len);
+	
+	width = (80 - (lev * 3) - 8) / 4;
+	
+	for (n = 0; n < len; n++) {
+		if ((n % width) == 0) {
+			fprintf(fp, "\n");
+			for (i=0; i<lev; i++) fprintf(fp, "   ");
+		}
+		fprintf(fp, "%02x ", enc[n]);
+		if ((n % width) == (width-1)) {
+			fprintf(fp, "    ");
+			for (i=n-(width-1); i<=n; i++)
+				if (isprint(enc[i])) fprintf(fp, "%c", enc[i]);
+				else fprintf(fp, ".");
+		}
+	}
+	if ((j = (n % width)) != 0) {
+		fprintf(fp, "    ");
+		for (i=0; i<width-j; i++) fprintf(fp, "   ");
+		for (i=n-j; i<n; i++)
+			if (isprint(enc[i])) fprintf(fp, "%c", enc[i]);
+			else fprintf(fp, ".");
+	}
+	return(OK);
+}
+
+int do_cons(fp, enc, len, lev, rlen)
+FILE *fp;
+unsigned char *enc;
+int len;
+int lev;
+int *rlen;
+{
+    int n;
+    int r = 0;
+    int rlen2;
+    int rlent;
+    int save_appl;
+
+    save_appl = current_appl_type;
+    for (n = 0, rlent = 0; n < len; n+=rlen2, rlent+=rlen2) {
+	r = trval2(fp, enc+n, len-n, lev, &rlen2);
+	current_appl_type = save_appl;
+	if (r != OK) return(r);
+    }
+    if (rlent != len) {
+	fprintf(fp, "inconsistent constructed lengths (%d != %d)\n",
+	rlent, len);
+	return(NOTOK);
+    }
+    *rlen = rlent;
+    return(r);
+}
+
+struct typestring_table {
+	int	k1, k2;
+	char	*str;
+	int	new_appl;
+};
+
+static char *lookup_typestring(table, key1, key2)
+	struct typestring_table *table;
+	int	key1, key2;
+{
+	struct typestring_table *ent;
+
+	for (ent = table; ent->k1 > 0; ent++) {
+		if ((ent->k1 == key1) &&
+		    (ent->k2 == key2)) {
+			if (ent->new_appl)
+				current_appl_type = ent->new_appl;
+			return ent->str;
+		}
+	}
+	return 0;
+}
+
+
+struct typestring_table univ_types[] = {
+	{ PRIM_BOOL, -1, "Boolean"},
+	{ PRIM_INT, -1, "Integer"},
+	{ PRIM_BITS, -1, "Bit String"},
+	{ PRIM_OCTS, -1, "Octet String"},
+	{ PRIM_NULL, -1, "Null"},
+	{ PRIM_OID, -1, "Object Identifier"},
+	{ PRIM_ODE, -1, "Object Descriptor"},
+	{ CONS_EXTN, -1, "External"},
+	{ PRIM_REAL, -1, "Real"},
+	{ PRIM_ENUM, -1, "Enumerated type"},
+	{ PRIM_ENCR, -1, "Encrypted"},
+	{ CONS_SEQ, -1, "Sequence/Sequence Of"},
+	{ CONS_SET, -1, "Set/Set Of"},
+	{ DEFN_NUMS, -1, "Numeric String"},
+	{ DEFN_PRTS, -1, "Printable String"},
+	{ DEFN_T61S, -1, "T.61 String"},
+	{ DEFN_VTXS, -1, "Videotex String"},
+	{ DEFN_IA5S, -1, "IA5 String"},
+	{ DEFN_UTCT, -1, "UTCTime"},
+	{ DEFN_GENT, -1, "Generalized Time"},
+	{ DEFN_GFXS, -1, "Graphics string (ISO2375)"},
+	{ DEFN_VISS, -1, "Visible string"},
+	{ DEFN_GENS, -1, "General string"},
+	{ DEFN_CHRS, -1, "Character string"},
+	{ -1, -1, 0}
+	};
+
+#ifdef KRB5
+struct typestring_table krb5_types[] = {
+	{ 1, -1, "Krb5 Ticket"},
+	{ 2, -1, "Krb5 Autenticator"},
+	{ 3, -1, "Krb5 Encrypted ticket part"},
+	{ 10, -1, "Krb5 AS-REQ packet"},
+	{ 11, -1, "Krb5 AS-REP packet"},
+	{ 12, -1, "Krb5 TGS-REQ packet"},
+	{ 13, -1, "Krb5 TGS-REP packet"},
+	{ 14, -1, "Krb5 AP-REQ packet"},
+	{ 15, -1, "Krb5 AP-REP packet"},
+	{ 20, -1, "Krb5 SAFE packet"},
+	{ 21, -1, "Krb5 PRIV packet"},
+	{ 22, -1, "Krb5 CRED packet"},
+	{ 30, -1, "Krb5 ERROR packet"},
+	{ 25, -1, "Krb5 Encrypted AS-REP part"},
+	{ 26, -1, "Krb5 Encrypted TGS-REP part"},
+	{ 27, -1, "Krb5 Encrypted AP-REP part"},
+	{ 28, -1, "Krb5 Encrypted PRIV part"},
+	{ 29, -1, "Krb5 Encrypted CRED part"},
+	{ -1, -1, 0}
+};
+
+struct typestring_table krb5_fields[] = {
+	{ 1000, 0, "name-type"}, /* PrincipalName */
+	{ 1000, 1, "name-string"},
+
+	{ 1001, 0, "etype"},	/* Encrypted data */
+	{ 1001, 1, "kvno"},	
+	{ 1001, 2, "cipher"},
+
+	{ 1002, 0, "addr-type"},	/* HostAddress */
+	{ 1002, 1, "address"},	
+
+	{ 1003, 0, "addr-type"},	/* HostAddresses */
+	{ 1003, 1, "address"},	
+
+	{ 1004, 0, "ad-type"},	/* AuthorizationData */
+	{ 1004, 1, "ad-data"},	
+
+	{ 1005, 0, "keytype"},	/* EncryptionKey */
+	{ 1005, 1, "keyvalue"},	
+
+	{ 1006, 0, "cksumtype"},	/* Checksum */
+	{ 1006, 1, "checksum"},
+
+	{ 1007, 0, "kdc-options"},	/* KDC-REQ-BODY */
+	{ 1007, 1, "cname", 1000},	
+	{ 1007, 2, "realm"},
+	{ 1007, 3, "sname", 1000},	
+	{ 1007, 4, "from"},
+	{ 1007, 5, "till"},	
+	{ 1007, 6, "rtime"},
+	{ 1007, 7, "nonce"},
+	{ 1007, 8, "etype"},
+	{ 1007, 9, "addresses", 1003},
+	{ 1007, 10, "enc-authorization-data", 1001},
+	{ 1007, 11, "additional-tickets"},
+
+	{ 1008, 1, "padata-type"},	/* PA-DATA */
+	{ 1008, 2, "pa-data"},
+
+	{ 1009, 0, "user-data"},	/* KRB-SAFE-BODY */
+	{ 1009, 1, "timestamp"},	
+	{ 1009, 2, "usec"},
+	{ 1009, 3, "seq-number"},	
+	{ 1009, 4, "s-address", 1002},
+	{ 1009, 5, "r-address", 1002},
+
+	{ 1010, 0, "lr-type"},	/* LastReq */
+	{ 1010, 1, "lr-value"},
+
+	{ 1011, 0, "key", 1005},	/* KRB-CRED-INFO */
+	{ 1011, 1, "prealm"},	
+	{ 1011, 2, "pname", 1000},
+	{ 1011, 3, "flags"},	
+	{ 1011, 4, "authtime"},
+	{ 1011, 5, "startime"},	
+	{ 1011, 6, "endtime"},
+	{ 1011, 7, "renew-till"},
+	{ 1011, 8, "srealm"},
+	{ 1011, 9, "sname", 1000},
+	{ 1011, 10, "caddr", 1002},
+
+	{ 1, 0, "tkt-vno"},	/* Ticket */
+	{ 1, 1, "realm"},
+	{ 1, 2, "sname", 1000},
+	{ 1, 3, "tkt-enc-part", 1001},
+
+	{ 2, 0, "authenticator-vno"}, /* Authenticator */
+	{ 2, 1, "crealm"},
+	{ 2, 2, "cname", 1000},
+	{ 2, 3, "cksum", 1006},
+	{ 2, 4, "cusec"},
+	{ 2, 5, "ctime"},
+	{ 2, 6, "subkey", 1005},
+	{ 2, 7, "seq-number"},
+	{ 2, 8, "authorization-data", 1004},
+
+	{ 3, 0, "flags"}, /* EncTicketPart */
+	{ 3, 1, "key", 1005},
+	{ 3, 2, "crealm"},
+	{ 3, 3, "cname", 1000},
+	{ 3, 4, "transited"},
+	{ 3, 5, "authtime"},
+	{ 3, 6, "starttime"},
+	{ 3, 7, "endtime"},
+	{ 3, 8, "renew-till"},
+	{ 3, 9, "caddr", 1003},
+	{ 3, 10, "authorization-data", 1004},
+
+	{ 10, 1, "pvno"},	/* AS-REQ */
+	{ 10, 2, "msg-type"},
+	{ 10, 3, "padata", 1008},
+	{ 10, 4, "req-body", 1007},
+
+	{ 11, 0, "pvno"},	/* AS-REP */
+	{ 11, 1, "msg-type"},
+	{ 11, 2, "padata", 1008},
+	{ 11, 3, "crealm"},
+	{ 11, 4, "cname", 1000},
+	{ 11, 5, "ticket"},
+	{ 11, 6, "enc-part", 1001},
+
+	{ 12, 1, "pvno"},	/* TGS-REQ */
+	{ 12, 2, "msg-type"},
+	{ 12, 3, "padata", 1008},
+	{ 12, 4, "req-body", 1007},
+
+	{ 13, 0, "pvno"},	/* TGS-REP */
+	{ 13, 1, "msg-type"},
+	{ 13, 2, "padata", 1008},
+	{ 13, 3, "crealm"},
+	{ 13, 4, "cname", 1000},
+	{ 13, 5, "ticket"},
+	{ 13, 6, "enc-part", 1001},
+
+	{ 14, 0, "pvno"},	/* AP-REQ */
+	{ 14, 1, "msg-type"},
+	{ 14, 2, "ap-options"},
+	{ 14, 3, "ticket"},
+	{ 14, 4, "authenticator", 1001},
+
+	{ 15, 0, "pvno"},	/* AP-REP */
+	{ 15, 1, "msg-type"},
+	{ 15, 2, "enc-part", 1001},
+	
+	{ 20, 0, "pvno"},	/* KRB-SAFE */
+	{ 20, 1, "msg-type"},
+	{ 20, 2, "safe-body", 1009},
+	{ 20, 3, "cksum", 1006},
+
+	{ 21, 0, "pvno"},	/* KRB-PRIV */
+	{ 21, 1, "msg-type"},
+	{ 21, 2, "enc-part", 1001},
+
+	{ 22, 0, "pvno"},	/* KRB-CRED */
+	{ 22, 1, "msg-type"},
+	{ 22, 2, "tickets"},
+	{ 22, 3, "enc-part", 1001},
+
+	{ 25, 0, "key", 1005},	/* EncASRepPart */
+	{ 25, 1, "last-req", 1010},
+	{ 25, 2, "nonce"},
+	{ 25, 3, "key-expiration"},
+	{ 25, 4, "flags"},
+	{ 25, 5, "authtime"},
+	{ 25, 6, "starttime"},
+	{ 25, 7, "enddtime"},
+	{ 25, 8, "renew-till"},
+	{ 25, 9, "srealm"},
+	{ 25, 10, "sname", 1000},
+	{ 25, 11, "caddr", 1003},
+	
+	{ 26, 0, "key", 1005},	/* EncTGSRepPart */
+	{ 26, 1, "last-req", 1010},
+	{ 26, 2, "nonce"},
+	{ 26, 3, "key-expiration"},
+	{ 26, 4, "flags"},
+	{ 26, 5, "authtime"},
+	{ 26, 6, "starttime"},
+	{ 26, 7, "enddtime"},
+	{ 26, 8, "renew-till"},
+	{ 26, 9, "srealm"},
+	{ 26, 10, "sname", 1000},
+	{ 26, 11, "caddr", 1003},
+	
+	{ 27, 0, "ctime"},	/* EncApRepPart */
+	{ 27, 1, "cusec"},
+	{ 27, 2, "subkey", 1005},
+	{ 27, 3, "seq-number"},
+
+	{ 28, 0, "user-data"},	/* EncKrbPrivPart */
+	{ 28, 1, "timestamp"},
+	{ 28, 2, "usec"},
+	{ 28, 3, "seq-number"},
+	{ 28, 4, "s-address", 1002},
+	{ 28, 5, "r-address", 1002},
+
+	{ 29, 0, "ticket-info", 1011},	/* EncKrbCredPart */
+	{ 29, 1, "nonce"},
+	{ 29, 2, "timestamp"},
+	{ 29, 3, "usec"},
+	{ 29, 4, "s-address", 1002},
+	{ 29, 5, "r-address", 1002},
+
+	{ 30, 0, "pvno"},	/* KRB-ERROR */
+	{ 30, 1, "msg-type"},
+	{ 30, 2, "ctime"},
+	{ 30, 3, "cusec"},
+	{ 30, 4, "stime"},
+	{ 30, 5, "susec"},
+	{ 30, 6, "error-code"},
+	{ 30, 7, "crealm"},
+	{ 30, 8, "cname", 1000},
+	{ 30, 9, "realm"},
+	{ 30, 10, "sname", 1000},
+	{ 30, 11, "e-text"},
+	{ 30, 12, "e-data"},
+	
+	{ -1, -1, 0}
+};
+#endif
+
+void print_tag_type(fp, eid, lev)
+        FILE *fp;
+        int     eid;
+        int     lev;
+{
+	int	tag = eid & ID_TAG;
+	int	do_space = 1;
+	char	*str;
+
+	fprintf(fp, "[");
+	
+	switch(eid & ID_CLASS) {
+	case CLASS_UNIV:
+		if (print_types && print_skip_tagnum)
+			do_space = 0;
+		else
+			fprintf(fp, "UNIV %d", tag);
+		break;
+	case CLASS_APPL:
+		current_appl_type = tag;
+#ifdef KRB5
+		if (print_krb5_types) {
+			str = lookup_typestring(krb5_types, tag, -1);
+			if (str) {
+				fputs(str, fp);
+				break;
+			}
+		}
+#endif
+		fprintf(fp, "APPL %d", tag);
+		break;
+	case CLASS_CONT:
+#ifdef KRB5
+		if (print_krb5_types && current_appl_type) {
+			str = lookup_typestring(krb5_fields,
+						current_appl_type, tag);
+			if (str) {
+				fputs(str, fp);
+				break;
+			}
+		}
+#endif
+		if (print_skip_context && lev)
+			fprintf(fp, "%d", tag);
+		else
+			fprintf(fp, "CONT %d", tag);
+		break;
+	case CLASS_PRIV:
+		fprintf(fp, "PRIV %d", tag);
+		break;
+	}
+	
+	if (print_types && ((eid & ID_CLASS) == CLASS_UNIV)) {
+		if (do_space)
+			fputs(" ", fp);
+		str = lookup_typestring(univ_types, eid & ID_TAG, -1);
+		if (str)
+			fputs(str, fp);
+		else
+			fprintf(fp, "UNIV %d???", eid & ID_TAG);
+	}
+	
+	fprintf(fp, "] ");
+	
+}	
+
+/*****************************************************************************/
+
diff --git a/krb5-1-6/src/tests/asn.1/trval_reference.out b/krb5-1-6/src/tests/asn.1/trval_reference.out
new file mode 100644
index 000000000..95311d3fe
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/trval_reference.out
@@ -0,0 +1,1198 @@
+encode_krb5_authenticator:
+
+[Krb5 Autenticator] 
+.  [Sequence/Sequence Of] 
+.  .  [authenticator-vno] [Integer] 5
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [cksum] [Sequence/Sequence Of] 
+.  .  .  [cksumtype] [Integer] 1
+.  .  .  [checksum] [Octet String] "1234"
+.  .  [cusec] [Integer] 123456
+.  .  [ctime] [Generalized Time] "19940610060317Z"
+.  .  [subkey] [Sequence/Sequence Of] 
+.  .  .  [keytype] [Integer] 1
+.  .  .  [keyvalue] [Octet String] "12345678"
+.  .  [seq-number] [Integer] 17
+.  .  [authorization-data] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [ad-type] [Integer] 1
+.  .  .  .  [ad-data] [Octet String] "foobar"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [ad-type] [Integer] 1
+.  .  .  .  [ad-data] [Octet String] "foobar"
+
+encode_krb5_authenticator(optionals empty):
+
+[Krb5 Autenticator] 
+.  [Sequence/Sequence Of] 
+.  .  [authenticator-vno] [Integer] 5
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [cusec] [Integer] 123456
+.  .  [ctime] [Generalized Time] "19940610060317Z"
+
+encode_krb5_authenticator(optionals NULL):
+
+[Krb5 Autenticator] 
+.  [Sequence/Sequence Of] 
+.  .  [authenticator-vno] [Integer] 5
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [cusec] [Integer] 123456
+.  .  [ctime] [Generalized Time] "19940610060317Z"
+
+encode_krb5_ticket:
+
+[Krb5 Ticket] 
+.  [Sequence/Sequence Of] 
+.  .  [tkt-vno] [Integer] 5
+.  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  [sname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_keyblock:
+
+[Sequence/Sequence Of] 
+.  [keytype] [Integer] 1
+.  [keyvalue] [Octet String] "12345678"
+
+encode_krb5_enc_tkt_part:
+
+[Krb5 Encrypted ticket part] 
+.  [Sequence/Sequence Of] 
+.  .  [flags] [Bit String] 0xfedcba98
+.  .  [key] [Sequence/Sequence Of] 
+.  .  .  [keytype] [Integer] 1
+.  .  .  [keyvalue] [Octet String] "12345678"
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [transited] [Sequence/Sequence Of] 
+.  .  .  [flags] [Integer] 1
+.  .  .  [key] [Octet String] "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS."
+.  .  [authtime] [Generalized Time] "19940610060317Z"
+.  .  [starttime] [Generalized Time] "19940610060317Z"
+.  .  [endtime] [Generalized Time] "19940610060317Z"
+.  .  [renew-till] [Generalized Time] "19940610060317Z"
+.  .  [caddr] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  [address] [Octet String] <4>
+               12 d0 00 23                                   ...#
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  [address] [Octet String] <4>
+               12 d0 00 23                                   ...#
+.  .  [authorization-data] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [ad-type] [Integer] 1
+.  .  .  .  [ad-data] [Octet String] "foobar"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [ad-type] [Integer] 1
+.  .  .  .  [ad-data] [Octet String] "foobar"
+
+encode_krb5_enc_tkt_part(optionals NULL):
+
+[Krb5 Encrypted ticket part] 
+.  [Sequence/Sequence Of] 
+.  .  [flags] [Bit String] 0xfedcba98
+.  .  [key] [Sequence/Sequence Of] 
+.  .  .  [keytype] [Integer] 1
+.  .  .  [keyvalue] [Octet String] "12345678"
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [transited] [Sequence/Sequence Of] 
+.  .  .  [flags] [Integer] 1
+.  .  .  [key] [Octet String] "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS."
+.  .  [authtime] [Generalized Time] "19940610060317Z"
+.  .  [endtime] [Generalized Time] "19940610060317Z"
+
+encode_krb5_enc_kdc_rep_part:
+
+[Krb5 Encrypted TGS-REP part] 
+.  [Sequence/Sequence Of] 
+.  .  [key] [Sequence/Sequence Of] 
+.  .  .  [keytype] [Integer] 1
+.  .  .  [keyvalue] [Octet String] "12345678"
+.  .  [last-req] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [lr-type] [Integer] -5
+.  .  .  .  [lr-value] [Generalized Time] "19940610060317Z"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [lr-type] [Integer] -5
+.  .  .  .  [lr-value] [Generalized Time] "19940610060317Z"
+.  .  [nonce] [Integer] 42
+.  .  [key-expiration] [Generalized Time] "19940610060317Z"
+.  .  [flags] [Bit String] 0xfedcba98
+.  .  [authtime] [Generalized Time] "19940610060317Z"
+.  .  [starttime] [Generalized Time] "19940610060317Z"
+.  .  [enddtime] [Generalized Time] "19940610060317Z"
+.  .  [renew-till] [Generalized Time] "19940610060317Z"
+.  .  [srealm] [General string] "ATHENA.MIT.EDU"
+.  .  [sname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [caddr] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  [address] [Octet String] <4>
+               12 d0 00 23                                   ...#
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  [address] [Octet String] <4>
+               12 d0 00 23                                   ...#
+
+encode_krb5_enc_kdc_rep_part(optionals NULL):
+
+[Krb5 Encrypted TGS-REP part] 
+.  [Sequence/Sequence Of] 
+.  .  [key] [Sequence/Sequence Of] 
+.  .  .  [keytype] [Integer] 1
+.  .  .  [keyvalue] [Octet String] "12345678"
+.  .  [last-req] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [lr-type] [Integer] -5
+.  .  .  .  [lr-value] [Generalized Time] "19940610060317Z"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [lr-type] [Integer] -5
+.  .  .  .  [lr-value] [Generalized Time] "19940610060317Z"
+.  .  [nonce] [Integer] 42
+.  .  [flags] [Bit String] 0xfe5cba98
+.  .  [authtime] [Generalized Time] "19940610060317Z"
+.  .  [enddtime] [Generalized Time] "19940610060317Z"
+.  .  [srealm] [General string] "ATHENA.MIT.EDU"
+.  .  [sname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+
+encode_krb5_as_rep:
+
+[Krb5 AS-REP packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 11
+.  .  [padata] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [ticket] [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [enc-part] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_as_rep(optionals NULL):
+
+[Krb5 AS-REP packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 11
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [ticket] [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [enc-part] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_tgs_rep:
+
+[Krb5 TGS-REP packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 13
+.  .  [padata] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [ticket] [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [enc-part] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_tgs_rep(optionals NULL):
+
+[Krb5 TGS-REP packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 13
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [ticket] [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [enc-part] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_ap_req:
+
+[Krb5 AP-REQ packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 14
+.  .  [ap-options] [Bit String] 0xfedcba98
+.  .  [ticket] [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [authenticator] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_ap_rep:
+
+[Krb5 AP-REP packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 15
+.  .  [enc-part] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_ap_rep_enc_part:
+
+[Krb5 Encrypted AP-REP part] 
+.  [Sequence/Sequence Of] 
+.  .  [ctime] [Generalized Time] "19940610060317Z"
+.  .  [cusec] [Integer] 123456
+.  .  [subkey] [Sequence/Sequence Of] 
+.  .  .  [keytype] [Integer] 1
+.  .  .  [keyvalue] [Octet String] "12345678"
+.  .  [seq-number] [Integer] 17
+
+encode_krb5_ap_rep_enc_part(optionals NULL):
+
+[Krb5 Encrypted AP-REP part] 
+.  [Sequence/Sequence Of] 
+.  .  [ctime] [Generalized Time] "19940610060317Z"
+.  .  [cusec] [Integer] 123456
+
+encode_krb5_as_req:
+
+[Krb5 AS-REQ packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 10
+.  .  [padata] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  [req-body] [Sequence/Sequence Of] 
+.  .  .  [kdc-options] [Bit String] 0xfedcba90
+.  .  .  [cname] [Sequence/Sequence Of] 
+.  .  .  .  [name-type] [Integer] 1
+.  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  [General string] "extra"
+.  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  [name-type] [Integer] 1
+.  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  [General string] "extra"
+.  .  .  [from] [Generalized Time] "19940610060317Z"
+.  .  .  [till] [Generalized Time] "19940610060317Z"
+.  .  .  [rtime] [Generalized Time] "19940610060317Z"
+.  .  .  [nonce] [Integer] 42
+.  .  .  [etype] [Sequence/Sequence Of] 
+.  .  .  .  [Integer] 0
+.  .  .  .  [Integer] 1
+.  .  .  [addresses] [Sequence/Sequence Of] 
+.  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  [address] [Octet String] <4>
+                  12 d0 00 23                                ...#
+.  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  [address] [Octet String] <4>
+                  12 d0 00 23                                ...#
+.  .  .  [enc-authorization-data] [Sequence/Sequence Of] 
+.  .  .  .  [etype] [Integer] 0
+.  .  .  .  [kvno] [Integer] 5
+.  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  .  [additional-tickets] [Sequence/Sequence Of] 
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_as_req(optionals NULL except second_ticket):
+
+[Krb5 AS-REQ packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 10
+.  .  [req-body] [Sequence/Sequence Of] 
+.  .  .  [kdc-options] [Bit String] 0xfedcba98
+.  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  [till] [Generalized Time] "19940610060317Z"
+.  .  .  [nonce] [Integer] 42
+.  .  .  [etype] [Sequence/Sequence Of] 
+.  .  .  .  [Integer] 0
+.  .  .  .  [Integer] 1
+.  .  .  [additional-tickets] [Sequence/Sequence Of] 
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_as_req(optionals NULL except server):
+
+[Krb5 AS-REQ packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 10
+.  .  [req-body] [Sequence/Sequence Of] 
+.  .  .  [kdc-options] [Bit String] 0xfedcba90
+.  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  [name-type] [Integer] 1
+.  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  [General string] "extra"
+.  .  .  [till] [Generalized Time] "19940610060317Z"
+.  .  .  [nonce] [Integer] 42
+.  .  .  [etype] [Sequence/Sequence Of] 
+.  .  .  .  [Integer] 0
+.  .  .  .  [Integer] 1
+
+encode_krb5_tgs_req:
+
+[Krb5 TGS-REQ packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 12
+.  .  [padata] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [padata-type] [Integer] 13
+.  .  .  .  [pa-data] [Octet String] "pa-data"
+.  .  [req-body] [Sequence/Sequence Of] 
+.  .  .  [kdc-options] [Bit String] 0xfedcba90
+.  .  .  [cname] [Sequence/Sequence Of] 
+.  .  .  .  [name-type] [Integer] 1
+.  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  [General string] "extra"
+.  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  [name-type] [Integer] 1
+.  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  [General string] "extra"
+.  .  .  [from] [Generalized Time] "19940610060317Z"
+.  .  .  [till] [Generalized Time] "19940610060317Z"
+.  .  .  [rtime] [Generalized Time] "19940610060317Z"
+.  .  .  [nonce] [Integer] 42
+.  .  .  [etype] [Sequence/Sequence Of] 
+.  .  .  .  [Integer] 0
+.  .  .  .  [Integer] 1
+.  .  .  [addresses] [Sequence/Sequence Of] 
+.  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  [address] [Octet String] <4>
+                  12 d0 00 23                                ...#
+.  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  [address] [Octet String] <4>
+                  12 d0 00 23                                ...#
+.  .  .  [enc-authorization-data] [Sequence/Sequence Of] 
+.  .  .  .  [etype] [Integer] 0
+.  .  .  .  [kvno] [Integer] 5
+.  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  .  [additional-tickets] [Sequence/Sequence Of] 
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_tgs_req(optionals NULL except second_ticket):
+
+[Krb5 TGS-REQ packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 12
+.  .  [req-body] [Sequence/Sequence Of] 
+.  .  .  [kdc-options] [Bit String] 0xfedcba98
+.  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  [till] [Generalized Time] "19940610060317Z"
+.  .  .  [nonce] [Integer] 42
+.  .  .  [etype] [Sequence/Sequence Of] 
+.  .  .  .  [Integer] 0
+.  .  .  .  [Integer] 1
+.  .  .  [additional-tickets] [Sequence/Sequence Of] 
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  .  .  [Krb5 Ticket] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_tgs_req(optionals NULL except server):
+
+[Krb5 TGS-REQ packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 12
+.  .  [req-body] [Sequence/Sequence Of] 
+.  .  .  [kdc-options] [Bit String] 0xfedcba90
+.  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  [name-type] [Integer] 1
+.  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  [General string] "extra"
+.  .  .  [till] [Generalized Time] "19940610060317Z"
+.  .  .  [nonce] [Integer] 42
+.  .  .  [etype] [Sequence/Sequence Of] 
+.  .  .  .  [Integer] 0
+.  .  .  .  [Integer] 1
+
+encode_krb5_kdc_req_body:
+
+[Sequence/Sequence Of] 
+.  [kdc-options] [Bit String] 0xfedcba90
+.  [cname] [Sequence/Sequence Of] 
+.  .  [name-type] [Integer] 1
+.  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  [General string] "hftsai"
+.  .  .  [General string] "extra"
+.  [realm] [General string] "ATHENA.MIT.EDU"
+.  [sname] [Sequence/Sequence Of] 
+.  .  [name-type] [Integer] 1
+.  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  [General string] "hftsai"
+.  .  .  [General string] "extra"
+.  [from] [Generalized Time] "19940610060317Z"
+.  [till] [Generalized Time] "19940610060317Z"
+.  [rtime] [Generalized Time] "19940610060317Z"
+.  [nonce] [Integer] 42
+.  [etype] [Sequence/Sequence Of] 
+.  .  [Integer] 0
+.  .  [Integer] 1
+.  [addresses] [Sequence/Sequence Of] 
+.  .  [Sequence/Sequence Of] 
+.  .  .  [addr-type] [Integer] 2
+.  .  .  [address] [Octet String] <4>
+            12 d0 00 23                                      ...#
+.  .  [Sequence/Sequence Of] 
+.  .  .  [addr-type] [Integer] 2
+.  .  .  [address] [Octet String] <4>
+            12 d0 00 23                                      ...#
+.  [enc-authorization-data] [Sequence/Sequence Of] 
+.  .  [etype] [Integer] 0
+.  .  [kvno] [Integer] 5
+.  .  [cipher] [Octet String] "krbASN.1 test message"
+.  [additional-tickets] [Sequence/Sequence Of] 
+.  .  [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_kdc_req_body(optionals NULL except second_ticket):
+
+[Sequence/Sequence Of] 
+.  [kdc-options] [Bit String] 0xfedcba98
+.  [realm] [General string] "ATHENA.MIT.EDU"
+.  [till] [Generalized Time] "19940610060317Z"
+.  [nonce] [Integer] 42
+.  [etype] [Sequence/Sequence Of] 
+.  .  [Integer] 0
+.  .  [Integer] 1
+.  [additional-tickets] [Sequence/Sequence Of] 
+.  .  [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [Krb5 Ticket] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_kdc_req_body(optionals NULL except server):
+
+[Sequence/Sequence Of] 
+.  [kdc-options] [Bit String] 0xfedcba90
+.  [realm] [General string] "ATHENA.MIT.EDU"
+.  [sname] [Sequence/Sequence Of] 
+.  .  [name-type] [Integer] 1
+.  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  [General string] "hftsai"
+.  .  .  [General string] "extra"
+.  [till] [Generalized Time] "19940610060317Z"
+.  [nonce] [Integer] 42
+.  [etype] [Sequence/Sequence Of] 
+.  .  [Integer] 0
+.  .  [Integer] 1
+
+encode_krb5_safe:
+
+[Krb5 SAFE packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 20
+.  .  [safe-body] [Sequence/Sequence Of] 
+.  .  .  [user-data] [Octet String] "krb5data"
+.  .  .  [timestamp] [Generalized Time] "19940610060317Z"
+.  .  .  [usec] [Integer] 123456
+.  .  .  [seq-number] [Integer] 17
+.  .  .  [s-address] [Sequence/Sequence Of] 
+.  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  [address] [Octet String] <4>
+               12 d0 00 23                                   ...#
+.  .  .  [r-address] [Sequence/Sequence Of] 
+.  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  [address] [Octet String] <4>
+               12 d0 00 23                                   ...#
+.  .  [cksum] [Sequence/Sequence Of] 
+.  .  .  [cksumtype] [Integer] 1
+.  .  .  [checksum] [Octet String] "1234"
+
+encode_krb5_safe(optionals NULL):
+
+[Krb5 SAFE packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 20
+.  .  [safe-body] [Sequence/Sequence Of] 
+.  .  .  [user-data] [Octet String] "krb5data"
+.  .  .  [s-address] [Sequence/Sequence Of] 
+.  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  [address] [Octet String] <4>
+               12 d0 00 23                                   ...#
+.  .  [cksum] [Sequence/Sequence Of] 
+.  .  .  [cksumtype] [Integer] 1
+.  .  .  [checksum] [Octet String] "1234"
+
+encode_krb5_priv:
+
+[Krb5 PRIV packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 21
+.  .  [3] [Sequence/Sequence Of] 
+.  .  .  [pvno] [Integer] 0
+.  .  .  [msg-type] [Integer] 5
+.  .  .  [enc-part] [Octet String] "krbASN.1 test message"
+
+encode_krb5_enc_priv_part:
+
+[Krb5 Encrypted PRIV part] 
+.  [Sequence/Sequence Of] 
+.  .  [user-data] [Octet String] "krb5data"
+.  .  [timestamp] [Generalized Time] "19940610060317Z"
+.  .  [usec] [Integer] 123456
+.  .  [seq-number] [Integer] 17
+.  .  [s-address] [Sequence/Sequence Of] 
+.  .  .  [addr-type] [Integer] 2
+.  .  .  [address] [Octet String] <4>
+            12 d0 00 23                                      ...#
+.  .  [r-address] [Sequence/Sequence Of] 
+.  .  .  [addr-type] [Integer] 2
+.  .  .  [address] [Octet String] <4>
+            12 d0 00 23                                      ...#
+
+encode_krb5_enc_priv_part(optionals NULL):
+
+[Krb5 Encrypted PRIV part] 
+.  [Sequence/Sequence Of] 
+.  .  [user-data] [Octet String] "krb5data"
+.  .  [s-address] [Sequence/Sequence Of] 
+.  .  .  [addr-type] [Integer] 2
+.  .  .  [address] [Octet String] <4>
+            12 d0 00 23                                      ...#
+
+encode_krb5_cred:
+
+[Krb5 CRED packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 22
+.  .  [tickets] [Sequence/Sequence Of] 
+.  .  .  [Krb5 Ticket] 
+.  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  .  [Krb5 Ticket] 
+.  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  [tkt-vno] [Integer] 5
+.  .  .  .  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  .  [General string] "extra"
+.  .  .  .  .  [tkt-enc-part] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [etype] [Integer] 0
+.  .  .  .  .  .  [kvno] [Integer] 5
+.  .  .  .  .  .  [cipher] [Octet String] "krbASN.1 test message"
+.  .  [enc-part] [Sequence/Sequence Of] 
+.  .  .  [etype] [Integer] 0
+.  .  .  [kvno] [Integer] 5
+.  .  .  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_enc_cred_part:
+
+[Krb5 Encrypted CRED part] 
+.  [Sequence/Sequence Of] 
+.  .  [ticket-info] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [key] [Sequence/Sequence Of] 
+.  .  .  .  .  [keytype] [Integer] 1
+.  .  .  .  .  [keyvalue] [Octet String] "12345678"
+.  .  .  .  [prealm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [pname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [flags] [Bit String] 0xfedcba98
+.  .  .  .  [authtime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [startime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [endtime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [renew-till] [Generalized Time] "19940610060317Z"
+.  .  .  .  [srealm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [caddr] [Sequence/Sequence Of] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  .  [address] [Octet String] <4>
+                     12 d0 00 23                             ...#
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  .  [address] [Octet String] <4>
+                     12 d0 00 23                             ...#
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [key] [Sequence/Sequence Of] 
+.  .  .  .  .  [keytype] [Integer] 1
+.  .  .  .  .  [keyvalue] [Octet String] "12345678"
+.  .  .  .  [prealm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [pname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [flags] [Bit String] 0xfedcba98
+.  .  .  .  [authtime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [startime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [endtime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [renew-till] [Generalized Time] "19940610060317Z"
+.  .  .  .  [srealm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [caddr] [Sequence/Sequence Of] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  .  [address] [Octet String] <4>
+                     12 d0 00 23                             ...#
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  .  [address] [Octet String] <4>
+                     12 d0 00 23                             ...#
+.  .  [nonce] [Integer] 42
+.  .  [timestamp] [Generalized Time] "19940610060317Z"
+.  .  [usec] [Integer] 123456
+.  .  [s-address] [Sequence/Sequence Of] 
+.  .  .  [addr-type] [Integer] 2
+.  .  .  [address] [Octet String] <4>
+            12 d0 00 23                                      ...#
+.  .  [r-address] [Sequence/Sequence Of] 
+.  .  .  [addr-type] [Integer] 2
+.  .  .  [address] [Octet String] <4>
+            12 d0 00 23                                      ...#
+
+encode_krb5_enc_cred_part(optionals NULL):
+
+[Krb5 Encrypted CRED part] 
+.  [Sequence/Sequence Of] 
+.  .  [ticket-info] [Sequence/Sequence Of] 
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [key] [Sequence/Sequence Of] 
+.  .  .  .  .  [keytype] [Integer] 1
+.  .  .  .  .  [keyvalue] [Octet String] "12345678"
+.  .  .  [Sequence/Sequence Of] 
+.  .  .  .  [key] [Sequence/Sequence Of] 
+.  .  .  .  .  [keytype] [Integer] 1
+.  .  .  .  .  [keyvalue] [Octet String] "12345678"
+.  .  .  .  [prealm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [pname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [flags] [Bit String] 0xfedcba98
+.  .  .  .  [authtime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [startime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [endtime] [Generalized Time] "19940610060317Z"
+.  .  .  .  [renew-till] [Generalized Time] "19940610060317Z"
+.  .  .  .  [srealm] [General string] "ATHENA.MIT.EDU"
+.  .  .  .  [sname] [Sequence/Sequence Of] 
+.  .  .  .  .  [name-type] [Integer] 1
+.  .  .  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  .  .  [General string] "hftsai"
+.  .  .  .  .  .  [General string] "extra"
+.  .  .  .  [caddr] [Sequence/Sequence Of] 
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  .  [address] [Octet String] <4>
+                     12 d0 00 23                             ...#
+.  .  .  .  .  [Sequence/Sequence Of] 
+.  .  .  .  .  .  [addr-type] [Integer] 2
+.  .  .  .  .  .  [address] [Octet String] <4>
+                     12 d0 00 23                             ...#
+
+encode_krb5_error:
+
+[Krb5 ERROR packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 30
+.  .  [ctime] [Generalized Time] "19940610060317Z"
+.  .  [cusec] [Integer] 123456
+.  .  [stime] [Generalized Time] "19940610060317Z"
+.  .  [susec] [Integer] 123456
+.  .  [error-code] [Integer] 60
+.  .  [crealm] [General string] "ATHENA.MIT.EDU"
+.  .  [cname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  [sname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+.  .  [e-text] [General string] "krb5data"
+.  .  [e-data] [Octet String] "krb5data"
+
+encode_krb5_error(optionals NULL):
+
+[Krb5 ERROR packet] 
+.  [Sequence/Sequence Of] 
+.  .  [pvno] [Integer] 5
+.  .  [msg-type] [Integer] 30
+.  .  [cusec] [Integer] 123456
+.  .  [stime] [Generalized Time] "19940610060317Z"
+.  .  [susec] [Integer] 123456
+.  .  [error-code] [Integer] 60
+.  .  [realm] [General string] "ATHENA.MIT.EDU"
+.  .  [sname] [Sequence/Sequence Of] 
+.  .  .  [name-type] [Integer] 1
+.  .  .  [name-string] [Sequence/Sequence Of] 
+.  .  .  .  [General string] "hftsai"
+.  .  .  .  [General string] "extra"
+
+encode_krb5_authorization_data:
+
+[Sequence/Sequence Of] 
+.  [Sequence/Sequence Of] 
+.  .  [ad-type] [Integer] 1
+.  .  [ad-data] [Octet String] "foobar"
+.  [Sequence/Sequence Of] 
+.  .  [ad-type] [Integer] 1
+.  .  [ad-data] [Octet String] "foobar"
+
+encode_krb5_pwd_sequence:
+
+[Sequence/Sequence Of] 
+.  [0] [Octet String] "krb5data"
+.  [1] [Octet String] "krb5data"
+
+encode_krb5_pwd_data:
+
+[Sequence/Sequence Of] 
+.  [0] [Integer] 2
+.  [1] [Sequence/Sequence Of] 
+.  .  [Sequence/Sequence Of] 
+.  .  .  [0] [Octet String] "krb5data"
+.  .  .  [1] [Octet String] "krb5data"
+.  .  [Sequence/Sequence Of] 
+.  .  .  [0] [Octet String] "krb5data"
+.  .  .  [1] [Octet String] "krb5data"
+
+encode_krb5_padata_sequence:
+
+[Sequence/Sequence Of] 
+.  [Sequence/Sequence Of] 
+.  .  [1] [Integer] 13
+.  .  [2] [Octet String] "pa-data"
+.  [Sequence/Sequence Of] 
+.  .  [1] [Integer] 13
+.  .  [2] [Octet String] "pa-data"
+
+encode_krb5_padata_sequence(empty):
+
+[Sequence/Sequence Of] 
+
+encode_krb5_alt_method:
+
+[Sequence/Sequence Of] 
+.  [0] [Integer] 42
+.  [1] [Octet String] "secret"
+
+encode_krb5_alt_method (no data):
+
+[Sequence/Sequence Of] 
+.  [0] [Integer] 42
+
+encode_krb5_etype_info:
+
+[Sequence/Sequence Of] 
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 0
+.  .  [1] [Octet String] "Morton's #0"
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 1
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 2
+.  .  [1] [Octet String] "Morton's #2"
+
+encode_krb5_etype_info (only 1):
+
+[Sequence/Sequence Of] 
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 0
+.  .  [1] [Octet String] "Morton's #0"
+
+encode_krb5_etype_info (no info):
+
+[Sequence/Sequence Of] 
+
+encode_krb5_etype_info2:
+
+[Sequence/Sequence Of] 
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 0
+.  .  [1] [General string] "Morton's #0"
+.  .  [2] [Octet String] "s2k: 0"
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 1
+.  .  [2] [Octet String] "s2k: 1"
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 2
+.  .  [1] [General string] "Morton's #2"
+.  .  [2] [Octet String] "s2k: 2"
+
+encode_krb5_etype_info2 (only 1):
+
+[Sequence/Sequence Of] 
+.  [Sequence/Sequence Of] 
+.  .  [0] [Integer] 0
+.  .  [1] [General string] "Morton's #0"
+.  .  [2] [Octet String] "s2k: 0"
+
+encode_krb5_pa_enc_ts:
+
+[Sequence/Sequence Of] 
+.  [0] [Generalized Time] "19940610060317Z"
+.  [1] [Integer] 123456
+
+encode_krb5_pa_enc_ts (no usec):
+
+[Sequence/Sequence Of] 
+.  [0] [Generalized Time] "19940610060317Z"
+
+encode_krb5_enc_data:
+
+[Sequence/Sequence Of] 
+.  [etype] [Integer] 0
+.  [kvno] [Integer] 5
+.  [cipher] [Octet String] "krbASN.1 test message"
+
+encode_krb5_sam_challenge:
+
+[Sequence/Sequence Of] 
+.  [0] [Integer] 42
+.  [1] [Bit String] 0x80000000
+.  [2] [Octet String] "type name"
+.  [4] [Octet String] "challenge label"
+.  [5] [Octet String] "challenge ipse"
+.  [6] [Octet String] "response_prompt ipse"
+.  [8] [Integer] 5517840
+.  [9] [Sequence/Sequence Of] 
+.  .  [0] [Integer] 1
+.  .  [1] [Octet String] "1234"
+
+encode_krb5_sam_response:
+
+[Sequence/Sequence Of] 
+.  [0] [Integer] 42
+.  [1] [Bit String] 0x80000000
+.  [2] [Octet String] "track data"
+.  [3] [Sequence/Sequence Of] 
+.  .  [0] [Integer] 1
+.  .  [1] [Integer] 1942
+.  .  [2] [Octet String] "key"
+.  [4] [Sequence/Sequence Of] 
+.  .  [0] [Integer] 1
+.  .  [1] [Integer] 3382
+.  .  [2] [Octet String] "nonce or ts"
+.  [5] [Integer] 5517840
+.  [6] [Generalized Time] "19940610060317Z"
+
diff --git a/krb5-1-6/src/tests/asn.1/utility.c b/krb5-1-6/src/tests/asn.1/utility.c
new file mode 100644
index 000000000..6ad2e9de8
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/utility.c
@@ -0,0 +1,125 @@
+#include "utility.h"
+#include "krb5.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+char hexchar (const unsigned int digit);
+
+asn1_error_code asn1_krb5_data_unparse(code, s)
+     const krb5_data * code;
+     char ** s;
+{
+  if(*s != NULL) free(*s);
+  
+  if(code==NULL){
+    *s = (char*)calloc(strlen("<NULL>")+1, sizeof(char));
+    if(*s == NULL) return ENOMEM;
+    strcpy(*s,"<NULL>");
+  }else if(code->data == NULL || ((int) code->length) <= 0){
+    *s = (char*)calloc(strlen("<EMPTY>")+1, sizeof(char));
+    if(*s==NULL) return ENOMEM;
+    strcpy(*s,"<EMPTY>");
+  }else{
+    int i;
+
+    *s = (char*)calloc((size_t) 3*(code->length), sizeof(char));
+    if(*s == NULL) return ENOMEM;
+    for(i = 0; i < code->length; i++){
+      (*s)[3*i] = hexchar((unsigned char) (((code->data)[i]&0xF0)>>4));
+      (*s)[3*i+1] = hexchar((unsigned char) ((code->data)[i]&0x0F));
+      (*s)[3*i+2] = ' ';
+    }
+    (*s)[3*(code->length)-1] = '\0';
+  }
+  return 0;
+}
+
+char hexchar(digit)
+     const unsigned int digit;
+{
+  if(digit<=9)
+    return '0'+digit;
+  else if(digit<=15)
+    return 'A'+digit-10;
+  else
+    return 'X';
+}
+
+krb5_error_code krb5_data_parse(d, s)
+     krb5_data * d;
+     const char * s;
+{
+  /*if(d->data != NULL){
+    free(d->data);
+    d->length = 0;
+  }*/
+  d->data = (char*)calloc(strlen(s),sizeof(char));
+  if(d->data == NULL) return ENOMEM;
+  d->length = strlen(s);
+  memcpy(d->data,s,strlen(s));
+  return 0;
+}
+
+krb5_error_code krb5_data_hex_parse(krb5_data *d, const char *s)
+{
+    int lo;
+    long v;
+    const char *cp;
+    char *dp;
+    char buf[2];
+
+    d->data = calloc((strlen(s) / 2 + 1), 1);
+    if (d->data == NULL)
+	return ENOMEM;
+    d->length = 0;
+    buf[1] = '\0';
+    for (lo = 0, dp = d->data, cp = s; *cp; cp++) {
+	if (*cp < 0)
+	    return ASN1_PARSE_ERROR;
+	else if (isspace((unsigned char) *cp))
+	    continue;
+	else if (isxdigit((unsigned char) *cp)) {
+	    buf[0] = *cp;
+	    v = strtol(buf, NULL, 16);
+	} else
+	    return ASN1_PARSE_ERROR;
+	if (lo) {
+	    *dp++ |= v;
+	    lo = 0;
+	} else {
+	    *dp = v << 4;
+	    lo = 1;
+	}
+    }
+
+    d->length = dp - d->data;
+    return 0;
+}
+
+#if 0
+void asn1buf_print(buf)
+     const asn1buf * buf;
+{
+  asn1buf bufcopy;
+  char *s=NULL;
+  int length;
+  int i;
+  
+  bufcopy.base = bufcopy.next = buf->next;
+  bufcopy.bound = buf->bound;
+  length = asn1buf_len(&bufcopy);
+
+  s = calloc(3*length, sizeof(char));
+  if(s == NULL) return;
+  for(i=0; i<length; i++){
+    s[3*i] = hexchar(((bufcopy.base)[i]&0xF0)>>4);
+    s[3*i+1] = hexchar((bufcopy.base)[i]&0x0F);
+    s[3*i+2] = ' ';
+  }
+  s[3*length-1] = '\0';
+
+  printf("%s\n",s);
+  free(s);
+}
+#endif
diff --git a/krb5-1-6/src/tests/asn.1/utility.h b/krb5-1-6/src/tests/asn.1/utility.h
new file mode 100644
index 000000000..4c761244f
--- /dev/null
+++ b/krb5-1-6/src/tests/asn.1/utility.h
@@ -0,0 +1,31 @@
+#ifndef __UTILITY_H__
+#define __UTILITY_H__
+
+#include "krbasn1.h"
+#include "asn1buf.h"
+
+asn1_error_code asn1_krb5_data_unparse
+	(const krb5_data *code, char **s);
+/* modifies  *s;
+   effects   Instantiates *s with a string representation of the series
+	      of hex octets in *code.  (e.g. "02 02 00 7F")  If code==NULL,
+	      the string rep is "<NULL>".  If code is empty (it contains no
+	      data or has length <= 0), the string rep is "<EMPTY>".
+	     If *s is non-NULL, then its currently-allocated storage
+	      will be freed prior to the instantiation.
+	     Returns ENOMEM or the string rep cannot be created. */
+
+krb5_error_code krb5_data_parse
+	(krb5_data *d, const char *s);
+/* effects  Parses character string *s into krb5_data *d. */
+
+krb5_error_code krb5_data_hex_parse
+	(krb5_data *d, const char *s);
+/* requires  *s is the string representation of a sequence of
+              hexadecimal octets.  (e.g. "02 01 00")
+   effects  Parses *s into krb5_data *d. */
+
+void asn1buf_print
+	(const asn1buf *buf);
+
+#endif
diff --git a/krb5-1-6/src/tests/configure.in b/krb5-1-6/src/tests/configure.in
new file mode 100644
index 000000000..9b8619b14
--- /dev/null
+++ b/krb5-1-6/src/tests/configure.in
@@ -0,0 +1,30 @@
+K5_AC_INIT(configure.in)
+CONFIG_RULES
+KRB5_RUN_FLAGS
+KRB5_BUILD_PROGRAM
+dnl Set krb5_cv_host
+KRB5_LIB_PARAMS
+dnl
+AC_HEADER_STDC
+AC_CHECK_FUNCS(strchr sem_init sem_trywait)
+AC_CHECK_HEADERS(unistd.h stdlib.h sys/param.h sys/socket.h dlfcn.h semaphore.h)
+AC_C_CONST
+AC_PROG_INSTALL
+AC_CHECK_PROG(RUNTEST,runtest,runtest)
+if test x"$RUNTEST" != x; then
+	HAVE_RUNTEST=yes
+else
+	HAVE_RUNTEST=no
+fi
+AC_SUBST(HAVE_RUNTEST)
+AC_TYPE_SIGNAL
+CHECK_SIGNALS
+if test "$KRB4_LIB" = ''; then
+	KRB4_DEJAGNU_TEST="KRBIV=0"
+else
+	AC_MSG_RESULT(Kerberos 4 testing enabled)
+	KRB4_DEJAGNU_TEST="KRBIV=1"
+fi
+AC_SUBST(KRB4_DEJAGNU_TEST)
+KRB5_AC_PRIOCNTL_HACK
+V5_AC_OUTPUT_MAKEFILE(. resolve asn.1 create hammer verify gssapi dejagnu threads shlib gss-threads misc)
diff --git a/krb5-1-6/src/tests/create/Makefile.in b/krb5-1-6/src/tests/create/Makefile.in
new file mode 100644
index 000000000..d71c630ef
--- /dev/null
+++ b/krb5-1-6/src/tests/create/Makefile.in
@@ -0,0 +1,35 @@
+thisconfigdir=./..
+myfulldir=tests/create
+mydir=create
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+SRCS=$(srcdir)/kdb5_mkdums.c
+KDB5_DEP_LIBS=$(THREAD_LINKOPTS) $(DL_LIB)
+
+all:: kdb5_mkdums
+
+kdb5_mkdums: kdb5_mkdums.o $(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o kdb5_mkdums kdb5_mkdums.o $(KDB5_DEP_LIBS) $(KDB5_LIBS) $(KRB5_BASE_LIBS)
+
+all:: kdb5_mkdums
+
+install::
+
+clean::
+	$(RM) kdb5_mkdums.o kdb5_mkdums
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kdb5_mkdums.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SS_DEPS) kdb5_mkdums.c
diff --git a/krb5-1-6/src/tests/create/kdb5_mkdums.M b/krb5-1-6/src/tests/create/kdb5_mkdums.M
new file mode 100644
index 000000000..23e258532
--- /dev/null
+++ b/krb5-1-6/src/tests/create/kdb5_mkdums.M
@@ -0,0 +1,141 @@
+.\" tests/create/kdb5_mkdums.M
+.\"
+.\" Copyright 1990 by the Massachusetts Institute of Technology.
+.\"
+.\" Export of this software from the United States of America may
+.\"   require a specific license from the United States Government.
+.\"   It is the responsibility of any person or organization contemplating
+.\"   export to obtain such a license before exporting.
+.\" 
+.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+.\" distribute this software and its documentation for any purpose and
+.\" without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" the name of M.I.T. not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.  Furthermore if you modify this software you must label
+.\" your software as modified software and not distribute it in such a
+.\" fashion that it might be confused with the original M.I.T. software.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is" without express
+.\" or implied warranty.
+.\" 
+.\"
+.TH KDB5_MKDUMS 8
+.SH NAME
+kdb5_mkdums \- create a new Kerberos V5 principal database
+.SH SYNOPSIS
+.B kdb5_mkdums
+.B \-n
+.I number
+.B \-p
+.I prefix
+[
+.B \-D
+.I depth
+] [
+.B \-r
+.I realm
+] [
+.B \-d
+.I dbname
+] [
+.B \-k
+.I keytype
+] [
+.B \-M
+.I mkeyname
+] [
+.B \-e
+.I enctype
+] [
+.B \-m
+]
+.br
+.SH DESCRIPTION
+.I kdb5_mkdums
+is used to create many test entries in a Kerberos version 5 principal
+database. 
+Each entry is created with a known password, for later verification.
+.I kdb5_verify
+can be used to verify that the entries were stored correctly in the
+database and can be retrieved.
+.I kdc5_hammer
+can be used to make repeated ticket requests of the KDC for principals
+created via
+.I kdb5_mkdums
+in order to ``stress test'' the KDC.
+.PP
+The
+.B \-p
+.I prefix
+argument specifies the prefix name for each principal to be created.
+The current number and depth will be appended to the prefix.
+.PP
+The
+.B \-n
+.I num_to_create
+argument specifies the number of principals to create (at each depth).
+.PP
+The
+.B \-D
+.I depth
+option specifies the maximum number of components a principal should
+have; the default depth is 1.
+.PP
+The
+.B \-r
+.I realm
+option specifies the realm in which the entreis should be created;
+by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.PP
+The
+.B \-d
+.I dbname
+option specifies the name under which the principal database is to be
+created; by default the database is in DEFAULT_DBM_FILE (normally
+/krb5/principal).
+.PP
+The
+.B \-k
+.I keytype
+option specifies the key type (as an ascii representation of a decimal
+number) of the master key in the database; the default is KEYTYPE_DES.
+.PP
+The
+.B \-M
+.I mkeyname
+option specifies the principal name for the master key in the database;
+the default is KRB5_KDB_M_NAME (usually "K/M" in the KDC's realm).
+.PP
+The
+.B \-e
+.I enctype
+option specifies the encryption type (as an ascii representation of a decimal
+number) to be used when placing entries in
+the database; the default is the default encryption type for the master
+keytype.
+.SH EXAMPLE
+.I
+kdb5_mkdums -p test -n 2 -D 3
+.R
+will create the following principals, each with their printed names as
+passwords:
+.nf
+.in +1i
+test1-DEPTH-1@FOO.MIT.EDU
+test2-DEPTH-1@FOO.MIT.EDU
+test1-DEPTH-1/test1-DEPTH-2@FOO.MIT.EDU
+test2-DEPTH-1/test2-DEPTH-2@FOO.MIT.EDU
+test1-DEPTH-1/test1-DEPTH-2/test1-DEPTH-3@FOO.MIT.EDU
+test2-DEPTH-1/test2-DEPTH-2/test2-DEPTH-3@FOO.MIT.EDU
+.in -1i
+.fi
+.SH BUGS
+Should be do something intelligent about testing fields other than the
+password.
+.SH AUTHOR
+Jon Rochlis, MIT Network Services
diff --git a/krb5-1-6/src/tests/create/kdb5_mkdums.c b/krb5-1-6/src/tests/create/kdb5_mkdums.c
new file mode 100644
index 000000000..f2fb27ad6
--- /dev/null
+++ b/krb5-1-6/src/tests/create/kdb5_mkdums.c
@@ -0,0 +1,434 @@
+/*
+ * tests/create/kdb5_mkdums.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Edit a KDC database.
+ */
+
+#include "k5-int.h"
+#include "kdb.h"
+#include "com_err.h"
+#include <ss/ss.h>
+#include <stdio.h>
+
+
+#define REALM_SEP	'@'
+#define REALM_SEP_STR	"@"
+
+struct mblock {
+    krb5_deltat max_life;
+    krb5_deltat max_rlife;
+    krb5_timestamp expiration;
+    krb5_flags flags;
+    krb5_kvno mkvno;
+} mblock = {				/* XXX */
+    KRB5_KDB_MAX_LIFE,
+    KRB5_KDB_MAX_RLIFE,
+    KRB5_KDB_EXPIRATION,
+    KRB5_KDB_DEF_FLAGS,
+    1
+};
+
+int set_dbname_help (char *, char *);
+
+static void
+usage(who, status)
+char *who;
+int status;
+{
+    fprintf(stderr,
+	    "usage: %s -p prefix -n num_to_create [-d dbpathname] [-r realmname]\n",
+	    who);
+    fprintf(stderr, "\t [-D depth] [-k enctype] [-M mkeyname]\n");
+
+    exit(status);
+}
+
+int master_princ_set = 0;
+krb5_keyblock master_keyblock;
+krb5_principal master_princ;
+krb5_db_entry master_entry;
+krb5_pointer master_random;
+krb5_context test_context;
+
+static char *progname;
+static char *cur_realm = 0;
+static char *mkey_name = 0;
+static char *mkey_password = 0;
+static krb5_boolean manual_mkey = FALSE;
+
+void add_princ (krb5_context, char *);
+
+int
+main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    extern char *optarg;	
+    int optchar, i, n;
+    char tmp[4096], tmp2[BUFSIZ], *str_newprinc;
+
+    krb5_error_code retval;
+    char *dbname = 0;
+    int enctypedone = 0;
+    extern krb5_kt_ops krb5_ktf_writable_ops;
+    int num_to_create;
+    char principal_string[BUFSIZ];
+    char *suffix = 0;
+    int depth;
+
+    krb5_init_context(&test_context);
+
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+
+    progname = argv[0];
+
+    memset(principal_string, 0, sizeof(principal_string));
+    num_to_create = 0;
+    depth = 1;
+
+    while ((optchar = getopt(argc, argv, "D:P:p:n:d:r:k:M:e:m")) != -1) {
+	switch(optchar) {
+	case 'D':
+	    depth = atoi(optarg);       /* how deep to go */
+	    break;
+        case 'P':		/* Only used for testing!!! */
+	    mkey_password = optarg;
+	    break;
+	case 'p':                       /* prefix name to create */
+	    strncpy(principal_string, optarg, sizeof(principal_string) - 1);
+	    principal_string[sizeof(principal_string) - 1] = '\0';
+	    suffix = principal_string + strlen(principal_string);
+	    break;
+	case 'n':                        /* how many to create */
+	    num_to_create = atoi(optarg);
+	    break;
+	case 'd':			/* set db name */
+	    dbname = optarg;
+	    break;
+	case 'r':
+	    cur_realm = optarg;
+	    break;
+	case 'k':
+	    master_keyblock.enctype = atoi(optarg);
+	    enctypedone++;
+	    break;
+	case 'M':			/* master key name in DB */
+	    mkey_name = optarg;
+	    break;
+	case 'm':
+	    manual_mkey = TRUE;
+	    break;
+	case '?':
+	default:
+	    usage(progname, 1);
+	    /*NOTREACHED*/
+	}
+    }
+
+    if (!(num_to_create && suffix)) usage(progname, 1);
+
+
+    if ((retval = krb5_kt_register(test_context, &krb5_ktf_writable_ops))) {
+        if (retval != KRB5_KT_TYPE_EXISTS) {
+	  com_err(progname, retval,
+		"while registering writable key table functions");
+	  exit(1);
+	}
+    }
+
+    if (!enctypedone)
+	master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
+
+    if (!krb5_c_valid_enctype(master_keyblock.enctype)) {
+	com_err(progname, KRB5_PROG_ETYPE_NOSUPP,
+		"while setting up enctype %d", master_keyblock.enctype);
+	exit(1);
+    }
+
+    if (!dbname)
+	dbname = DEFAULT_KDB_FILE;	/* XXX? */
+
+    if (!cur_realm) {
+	if ((retval = krb5_get_default_realm(test_context, &cur_realm))) {
+	    com_err(progname, retval, "while retrieving default realm name");
+	    exit(1);
+	}	    
+    }
+    if ((retval = set_dbname_help(progname, dbname)))
+	exit(retval);
+
+    for (n = 1; n <= num_to_create; n++) {
+      /* build the new principal name */
+      /* we can't pick random names because we need to generate all the names 
+	 again given a prefix and count to test the db lib and kdb */
+      (void) sprintf(suffix, "%d", n);
+      (void) sprintf(tmp, "%s-DEPTH-1", principal_string);
+      tmp[sizeof(tmp) - 1] = '\0';
+      str_newprinc = tmp;
+      add_princ(test_context, str_newprinc);
+
+      for (i = 2; i <= depth; i++) {
+	(void) sprintf(tmp2, "/%s-DEPTH-%d", principal_string, i);
+	tmp2[sizeof(tmp2) - 1] = '\0';
+	strncat(tmp, tmp2, sizeof(tmp) - 1 - strlen(tmp));
+	str_newprinc = tmp;
+	add_princ(test_context, str_newprinc);
+      }
+    }
+
+    retval = krb5_db_fini(test_context);
+    memset((char *)master_keyblock.contents, 0, 
+	   (size_t) master_keyblock.length);
+    if (retval && retval != KRB5_KDB_DBNOTINITED) {
+	com_err(progname, retval, "while closing database");
+	exit(1);
+    }
+    if (master_princ_set) {
+	krb5_free_principal(test_context, master_princ);
+    }
+    krb5_free_context(test_context);
+    exit(0);
+}
+
+void
+add_princ(context, str_newprinc)
+    krb5_context 	  context;
+    char 		* str_newprinc;
+{
+    krb5_error_code 	  retval;
+    krb5_principal 	  newprinc;
+    krb5_db_entry 	  newentry;
+    char 		  princ_name[4096];
+
+    memset((char *)&newentry, 0, sizeof(newentry));
+    sprintf(princ_name, "%s@%s", str_newprinc, cur_realm);
+    if ((retval = krb5_parse_name(context, princ_name, &newprinc))) {
+      com_err(progname, retval, "while parsing '%s'", princ_name);
+      return;
+    }
+
+    /* Add basic data */
+    newentry.len = KRB5_KDB_V1_BASE_LENGTH;
+    newentry.attributes = mblock.flags;
+    newentry.max_life = mblock.max_life;
+    newentry.max_renewable_life = mblock.max_rlife;
+    newentry.expiration = mblock.expiration;
+    newentry.pw_expiration = mblock.expiration;
+    
+    /* Add princ to db entry */
+    if ((retval = krb5_copy_principal(context, newprinc, &newentry.princ))) {
+      	com_err(progname, retval, "while encoding princ to db entry for '%s'", 
+	        princ_name);
+	krb5_free_principal(context, newprinc);
+	goto error;
+    }
+
+    {
+	/* Add mod princ to db entry */
+	krb5_int32 now;
+
+	retval = krb5_timeofday(context, &now);
+	if (retval) {
+	    com_err(progname, retval, "while fetching date");
+	    krb5_free_principal(context, newprinc);
+	    goto error;
+	}
+	retval = krb5_dbe_update_mod_princ_data(context, &newentry, now,
+					       master_princ);
+	if (retval) {
+	    com_err(progname, retval, "while encoding mod_princ data");
+	    krb5_free_principal(context, newprinc);
+	    goto error;
+	}
+    }
+
+    {   /* Add key and salt data to db entry */
+        krb5_data pwd, salt;
+        krb5_keyblock key;
+
+        if ((retval = krb5_principal2salt(context, newprinc, &salt))) {
+	    com_err(progname, retval, "while converting princ to salt for '%s'",
+		    princ_name);
+	    krb5_free_principal(context, newprinc);
+	    goto error;
+        }
+
+	krb5_free_principal(context, newprinc);
+
+    	pwd.length = strlen(princ_name);
+    	pwd.data = princ_name;  /* must be able to regenerate */
+    	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);
+	    goto error;
+	}
+	krb5_free_data_contents(context, &salt);
+
+	if ((retval = krb5_dbe_create_key_data(context, &newentry))) {
+	    com_err(progname, retval, "while creating key_data for '%s'",
+		    princ_name);
+            free(key.contents);
+	    goto error;
+        }
+
+        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'", 
+		    princ_name);
+            free(key.contents);
+	    goto error;
+        }
+        free(key.contents);
+    }
+
+    {
+	int one = 1;
+
+    	if ((retval = krb5_db_put_principal(context, &newentry, &one))) {
+	    com_err(progname, retval, "while storing principal date");
+	    goto error;
+    	}
+    	if (one != 1) {
+	   com_err(progname,0,"entry not stored in database (unknown failure)");
+	    goto error;
+    	}
+    }
+
+    fprintf(stdout, "Added %s to database\n", princ_name);
+
+error: /* Do cleanup of newentry regardless of error */
+#if 0
+    krb5_dbe_free_contents(context, &newentry);
+#endif
+    krb5_db_free_principal(context, &newentry, 1);
+    return;
+}
+
+int
+set_dbname_help(pname, dbname)
+char *pname;
+char *dbname;
+{
+    krb5_error_code retval;
+    int nentries;
+    krb5_boolean more;
+    krb5_data pwd, scratch;
+    char *args[2];
+
+    /* assemble & parse the master key name */
+
+    if ((retval = krb5_db_setup_mkey_name(test_context, mkey_name, cur_realm, 
+					  0, &master_princ))) {
+	com_err(pname, retval, "while setting up master key name");
+	return(1);
+    }
+    master_princ_set = 1;
+    if (mkey_password) {
+	pwd.data = mkey_password;
+	pwd.length = strlen(mkey_password);
+	retval = krb5_principal2salt(test_context, master_princ, &scratch);
+	if (retval) {
+	    com_err(pname, retval, "while calculated master key salt");
+	    return(1);
+	}
+	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);
+	}
+	free(scratch.data);
+    } else {
+	if ((retval = krb5_db_fetch_mkey(test_context, master_princ, 
+					master_keyblock.enctype, manual_mkey, 
+					FALSE, 0, NULL, &master_keyblock))) {
+	    com_err(pname, retval, "while reading master key");
+	    return(1);
+	}
+    }
+
+    /* Ick!  Current DAL interface requires that the default_realm
+       field be set in the krb5_context.  */
+    if ((retval = krb5_set_default_realm(test_context, cur_realm))) {
+	com_err(pname, retval, "setting default realm");
+	return 1;
+    }
+    /* Pathname is passed to db2 via 'args' parameter.  */
+    args[1] = NULL;
+    args[0] = malloc(sizeof("dbname=") + strlen(dbname));
+    if (args[0] == NULL) {
+	com_err(pname, errno, "while setting up db parameters");
+	return 1;
+    }
+    sprintf(args[0], "dbname=%s", dbname);
+
+    if ((retval = krb5_db_open(test_context, args, KRB5_KDB_OPEN_RO))) {
+	com_err(pname, retval, "while initializing database");
+	return(1);
+    }
+    /* Done with args */
+    free(args[0]);
+
+    if ((retval = krb5_db_verify_master_key(test_context, master_princ, 
+					   &master_keyblock))){
+	com_err(pname, retval, "while verifying master key");
+	(void) krb5_db_fini(test_context);
+	return(1);
+    }
+    nentries = 1;
+    if ((retval = krb5_db_get_principal(test_context, master_princ, 
+				       &master_entry, &nentries, &more))) {
+	com_err(pname, retval, "while retrieving master entry");
+	(void) krb5_db_fini(test_context);
+	return(1);
+    } else if (more) {
+	com_err(pname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
+		"while retrieving master entry");
+	(void) krb5_db_fini(test_context);
+	return(1);
+    } else if (!nentries) {
+	com_err(pname, KRB5_KDB_NOENTRY, "while retrieving master entry");
+	(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;
+
+    /* don't set flags, master has some extra restrictions */
+    mblock.mkvno = master_entry.key_data[0].key_data_kvno;
+
+    krb5_db_free_principal(test_context, &master_entry, nentries);
+    return 0;
+}
+
diff --git a/krb5-1-6/src/tests/dejagnu/Makefile.in b/krb5-1-6/src/tests/dejagnu/Makefile.in
new file mode 100644
index 000000000..61fbed088
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/Makefile.in
@@ -0,0 +1,54 @@
+thisconfigdir=./..
+myfulldir=tests/dejagnu
+mydir=dejagnu
+BUILDTOP=$(REL)..$(S)..
+RUNTEST = @RUNTEST@ $(DEJAFLAGS)
+RUNTESTFLAGS =
+KRB5_RUN_ENV= @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+KRB4_RUNTESTFLAGS=@KRB4_DEJAGNU_TEST@
+
+SRCS=$(srcdir)/t_inetd.c
+
+all install::
+
+check:: check-runtest-@HAVE_RUNTEST@
+
+check-runtest-no::
+	@echo "+++"
+	@echo "+++ WARNING: tests/dejagnu tests not run."
+	@echo "+++ runtest is unavailable."
+	@echo "+++"
+
+check-runtest-yes:: t_inetd site.exp
+	$(RUNTEST) --tool krb --srcdir $(srcdir) $(KRB4_RUNTESTFLAGS) PRIOCNTL_HACK=@PRIOCNTL_HACK@ VALGRIND="$(VALGRIND)" $(RUNTESTFLAGS)
+
+t_inetd:: t_inetd.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_inetd t_inetd.o $(KRB5_BASE_LIBS)
+
+clean::
+	$(RM) t_inetd t_inetd.o site.exp runenv.vars runenv.vals
+
+clean-unix::
+	$(RM) -rf tmpdir dbg.log krb.log krb.sum
+
+runenv.vars: Makefile
+	echo '$(KRB5_RUN_ENV)' | tr ';' '\012' | \
+		sed -ne 's% *\([^=]*\)=.*%\1%p' > runenv.vars
+
+runenv.vals: runenv.vars
+	$(KRB5_RUN_ENV) for i in `cat runenv.vars`; do \
+		eval echo "{$$i=\$$$$i}"; done > runenv.vals
+
+site.exp: runenv.vals Makefile
+	echo "set runvarlist [list `cat runenv.vals | tr '\n' ' '`]" | \
+		sed -e 's%=\.%='`pwd`'/.%g' > site.exp
+	echo "set KRB5_DB_MODULE_DIR {$(KRB5_DB_MODULE_DIR)}" >> site.exp
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)t_inetd.$(OBJEXT): $(COM_ERR_DEPS) t_inetd.c
diff --git a/krb5-1-6/src/tests/dejagnu/config/default.exp b/krb5-1-6/src/tests/dejagnu/config/default.exp
new file mode 100644
index 000000000..0c40553ff
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/config/default.exp
@@ -0,0 +1,2721 @@
+# Basic expect script for Kerberos tests.
+# This is a DejaGnu test script.
+# Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+# This script is automatically run by DejaGnu before running any of
+# the Kerberos test scripts.
+
+# This file provides several functions which deal with a local
+# Kerberos database.  We have to do this such that we don't interfere
+# with any existing Kerberos database.  We will create all the files
+# in the directory $tmppwd, which will have been created by the
+# testsuite default script.  We will use $REALMNAME as our Kerberos
+# realm name, defaulting to KRBTEST.COM.
+
+set timeout 100
+set stty_init {erase \^h kill \^u}
+set env(TERM) dumb
+
+set des3_krbtgt 0
+set tgt_support_desmd5 0
+set supported_enctypes "des-cbc-crc:normal"
+set kdc_supported_enctypes "des-cbc-crc:normal"
+
+# The names of the individual passes must be unique; lots of things
+# depend on it.  The PASSES variable may not contain comments; only
+# small pieces get evaluated, so comments will do strange things.
+
+# Most of the purpose of using multiple passes is to exercise the
+# dependency of various bugs on configuration file settings,
+# particularly with regards to encryption types.
+
+# The des.no-kdc-md5 pass will fail if the KDC does not constrain
+# session key enctypes to those in its permitted_enctypes list.  It
+# works by assuming enctype similarity, thus allowing the client to
+# request a des-cbc-md4 session key.  Since only des-cbc-crc is in the
+# KDC's permitted_enctypes list, the TGT will be unusable.
+
+# KLUDGE for tracking down leaking ptys
+if 0 {
+    rename spawn oldspawn
+    rename wait oldwait
+    proc spawn { args } {
+	upvar 1 spawn_id spawn_id
+	verbose "spawn: args=$args"
+	set pid [eval oldspawn $args]
+	verbose "spawn: pid=$pid spawn_id=$spawn_id"
+	return $pid
+    }
+    proc wait { args } {
+	upvar 1 spawn_id spawn_id
+	verbose "wait: args=$args"
+	set ret [eval oldwait $args]
+	verbose "wait: $ret"
+	return $ret
+    }
+}
+
+if { [string length $VALGRIND] } {
+    rename spawn valgrind_aux_spawn
+    proc spawn { args } {
+	global VALGRIND
+	upvar 1 spawn_id spawn_id
+	set newargs {}
+	set inflags 1
+	set eatnext 0
+	foreach arg $args {
+	    if { $arg == "-ignore" \
+		     || $arg == "-open" \
+		     || $arg == "-leaveopen" } {
+		lappend newargs $arg
+		set eatnext 1
+		continue
+	    }
+	    if [string match "-*" $arg] {
+		lappend newargs $arg
+		continue
+	    }
+	    if { $eatnext } {
+		set eatnext 0
+		lappend newargs $arg
+		continue
+	    }
+	    if { $inflags } {
+		set inflags 0
+		# Only run valgrind for local programs, not
+		# system ones.
+		if [string match "/" [string index $arg 0]]&&![string match "/bin/sh" $arg]&&![string match "/bin/ls" $arg]&&![regexp {/kshd$} $arg] {
+		    set newargs [concat $newargs $VALGRIND]
+		}
+	    }
+	    lappend newargs $arg
+	}
+	set pid [eval valgrind_aux_spawn $newargs]
+	return $pid
+    }
+}
+
+# Hack around Solaris 9 kernel race condition that causes last output
+# from a pty to get dropped.
+if { $PRIOCNTL_HACK } {
+    catch {exec priocntl -s -c FX -m 30 -p 30 -i pid [getpid]}
+    rename spawn oldspawn
+    proc spawn { args } {
+	upvar 1 spawn_id spawn_id
+	set newargs {}
+	set inflags 1
+	set eatnext 0
+	foreach arg $args {
+	    if { $arg == "-ignore" \
+		     || $arg == "-open" \
+		     || $arg == "-leaveopen" } {
+		lappend newargs $arg
+		set eatnext 1
+		continue
+	    }
+	    if [string match "-*" $arg] {
+		lappend newargs $arg
+		continue
+	    }
+	    if { $eatnext } {
+		set eatnext 0
+		lappend newargs $arg
+		continue
+	    }
+	    if { $inflags } {
+		set inflags 0
+		set newargs [concat $newargs {priocntl -e -c FX -p 0}]
+	    }
+	    lappend newargs $arg
+	}
+	set pid [eval oldspawn $newargs]
+	return $pid
+    }
+}
+
+# The des.des3-tgt.no-kdc-des3 pass will fail if the KDC doesn't
+# constrain ticket key enctypes to those in permitted_enctypes.  It
+# does this by not putting des3 in the permitted_enctypes, while
+# creating a TGT princpal that has a des3 key as well as a des key.
+
+# XXX -- master_key_type is fragile w.r.t. permitted_enctypes; it is
+# possible to configure things such that you have a master_key_type
+# that is not permitted, and the error message used to be cryptic.
+
+set passes {
+    {
+	des
+	mode=udp
+	des3_krbtgt=0
+	{supported_enctypes=des-cbc-crc:normal}
+	{kdc_supported_enctypes=des-cbc-crc:normal}
+	{dummy=[verbose -log "DES TGT, DES enctype"]}
+    }
+    {
+	des.des3tgt
+	mode=udp
+	des3_krbtgt=1
+	{supported_enctypes=des-cbc-crc:normal}
+	{kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+	{dummy=[verbose -log "DES3 TGT, DES enctype"]}
+    }
+    {
+	des3
+	mode=udp
+	des3_krbtgt=1
+	{supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+	{kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+	{dummy=[verbose -log "DES3 TGT, DES3 + DES enctypes"]}
+    }
+    {
+	aes
+	mode=udp
+	des3_krbtgt=0
+	{supported_enctypes=aes256-cts-hmac-sha1-96:normal des-cbc-crc:normal}
+	{kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des-cbc-crc:normal}
+	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des-cbc-crc}
+	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des-cbc-crc}
+	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des-cbc-crc}
+	{master_key_type=aes256-cts-hmac-sha1-96}
+	{dummy=[verbose -log "AES + DES enctypes"]}
+    }
+    {
+	aesonly
+	mode=udp
+	des3_krbtgt=0
+	{supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+	{kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
+	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
+	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
+	{master_key_type=aes256-cts-hmac-sha1-96}
+	{dummy=[verbose -log "AES enctypes"]}
+    }
+    {
+	aes-tcp
+	mode=tcp
+	des3_krbtgt=0
+	{supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+	{kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
+	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
+	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
+	{master_key_type=aes256-cts-hmac-sha1-96}
+	{dummy=[verbose -log "AES via TCP"]}
+    }
+    {
+	aes-des3
+	mode=udp
+	des3_krbtgt=0
+	{supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+	{kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+	{master_key_type=aes256-cts-hmac-sha1-96}
+	{dummy=[verbose -log "AES + DES enctypes"]}
+    }
+    {
+	des3-aes
+	mode=udp
+	des3_krbtgt=1
+	{supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+	{kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+	{master_key_type=aes256-cts-hmac-sha1-96}
+	{dummy=[verbose -log "AES + DES enctypes, DES3 TGT"]}
+    }
+    {
+	des-v4
+	mode=udp
+	des3_krbtgt=0
+	{supported_enctypes=des-cbc-crc:v4}
+	{kdc_supported_enctypes=des-cbc-crc:v4}
+	{default_tkt_enctypes(client)=des-cbc-crc}
+	{dummy=[verbose -log "DES TGT, DES-CRC enctype, V4 salt"]}
+    }
+    {
+	des-md5-v4
+	mode=udp
+	des3_krbtgt=0
+	{supported_enctypes=des-cbc-md5:v4 des-cbc-crc:v4}
+	{kdc_supported_enctypes=des-cbc-md5:v4 des-cbc-crc:v4}
+	{default_tkt_enctypes(client)=des-cbc-md5 des-cbc-crc}
+	{dummy=[verbose -log "DES TGT, DES-MD5 and -CRC enctypes, V4 salt"]}
+    }
+    {
+	all-des-des3-enctypes
+	mode=udp
+	des3_krbtgt=1
+	{supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal \
+		des-cbc-md5:normal des-cbc-crc:v4 des-cbc-md5:norealm \
+		des-cbc-md4:normal}
+	{kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal \
+		des-cbc-md5:normal des-cbc-crc:v4 des-cbc-md5:norealm \
+		des-cbc-md4:normal}
+	{dummy=[verbose -log "DES3 TGT, many DES3 + DES enctypes"]}
+    }
+    {
+	des.no-kdc-md5
+	mode=udp
+	des3_krbtgt=0
+	tgt_support_desmd5=0
+	{permitted_enctypes(kdc)=des-cbc-crc}
+	{default_tgs_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+	{default_tkt_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+	{supported_enctypes=des-cbc-crc:normal}
+	{kdc_supported_enctypes=des-cbc-crc:normal}
+	{master_key_type=des-cbc-crc}
+	{dummy=[verbose -log \
+		"DES TGT, KDC permitting only des-cbc-crc"]}
+    }
+    {
+	des.des3-tgt.no-kdc-des3
+	mode=udp
+	tgt_support_desmd5=0
+	{permitted_enctypes(kdc)=des-cbc-crc}
+	{default_tgs_enctypes(client)=des-cbc-crc}
+	{default_tkt_enctypes(client)=des-cbc-crc}
+	{supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+	{kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+	{master_key_type=des-cbc-crc}
+	{dummy=[verbose -log \
+		"DES3 TGT, KDC permitting only des-cbc-crc"]}
+    }
+}
+
+# des.md5-tgt is set as unused, since it won't trigger the error case
+# if SUPPORT_DESMD5 isn't honored.
+
+# The des.md5-tgt pass will fail if enctype similarity is inconsisent;
+# between 1.0.x and 1.1, the decrypt functions became more strict
+# about matching enctypes, while the KDB retrieval functions didn't
+# coerce the enctype to match what was requested.  It works by setting
+# SUPPORT_DESMD5 on the TGT principal, forcing an enctype of
+# des-cbc-md5 on the TGT key.  Since the database only contains a
+# des-cbc-crc key, the decrypt will fail if enctypes are not coerced.
+
+# des.no-kdc-md5.client-md4-skey is retained in unsed_passes, even
+# though des.no-kdc-md5 is roughly equivalent, since the associated
+# comment needs additional investigation at some point re the kadmin
+# client.
+
+# The des.no-kdc-md5.client-md4-skey will fail on TGS requests due to
+# the KDC issuing session keys that it won't accept.  It will also
+# fail for a kadmin client, but for different reasons, since the kadm5
+# library does some curious filtering of enctypes, and also uses
+# get_in_tkt() rather than get_init_creds(); the former does an
+# intersection of the enctypes provided by the caller and those listed
+# in the config file!
+
+set unused_passes {
+    {
+	des.md5-tgt
+	des3_krbtgt=0
+	tgt_support_desmd5=1
+	supported_enctypes=des-cbc-crc:normal
+	kdc_supported_enctypes=des-cbc-crc:normal
+	{permitted_enctypes(kdc)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+	{permitted_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+	{dummy=[verbose -log "DES TGT, SUPPORTS_DESMD5"]}
+    }
+    {
+	des.md5-tgt.no-kdc-md5
+	des3_krbtgt=0
+	tgt_support_desmd5=1
+	{permitted_enctypes(kdc)=des-cbc-crc}
+	{default_tgs_enctypes(client)=des-cbc-crc}
+	{default_tkt_enctypes(client)=des-cbc-crc}
+	{supported_enctypes=des-cbc-crc:normal}
+	{kdc_supported_enctypes=des-cbc-crc:normal}
+	{master_key_type=des-cbc-crc}
+	{dummy=[verbose -log \
+		"DES TGT, SUPPORTS_DESMD5, KDC permitting only des-cbc-crc"]}
+    }
+    {
+	des.no-kdc-md5.client-md4-skey
+	des3_krbtgt=0
+	{permitted_enctypes(kdc)=des-cbc-crc}
+	{permitted_enctypes(client)=des-cbc-crc des-cbc-md4}
+	{default_tgs_enctypes(client)=des-cbc-crc des-cbc-md4}
+	{default_tkt_enctypes(client)=des-cbc-md4}
+	{supported_enctypes=des-cbc-crc:normal}
+	{kdc_supported_enctypes=des-cbc-crc:normal}
+	{dummy=[verbose -log \
+		"DES TGT, DES enctype, KDC permitting only des-cbc-crc, client requests des-cbc-md4 session key"]}
+    }
+    {
+	all-enctypes
+	des3_krbtgt=1
+	{supported_enctypes=\
+	aes256-cts-hmac-sha1-96:normal aes256-cts-hmac-sha1-96:norealm \
+	aes128-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:norealm \
+	des3-cbc-sha1:normal des3-cbc-sha1:none \
+	des-cbc-md5:normal des-cbc-md4:normal des-cbc-crc:normal \
+	des-cbc-md5:v4 des-cbc-md4:v4 des-cbc-crc:v4 \
+	}
+	{kdc_supported_enctypes=\
+	des3-cbc-sha1:normal des3-cbc-sha1:none \
+	des-cbc-md5:normal des-cbc-md4:normal des-cbc-crc:normal \
+	des-cbc-md5:v4 des-cbc-md4:v4 des-cbc-crc:v4 \
+	}
+	{dummy=[verbose -log "DES3 TGT, default enctypes"]}
+    }
+    # This won't work for anything using GSSAPI until it gets AES support.
+    {
+	aes-only
+	des3_krbtgt=0
+	{supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+	{kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
+	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
+	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
+	{master_key_type=aes256-cts-hmac-sha1-96}
+	{dummy=[verbose -log "AES only, no DES or DES3 support"]}
+    }
+}
+#	{supported_enctypes=des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal }
+#	{kdc_supported_enctypes= des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal}
+
+# This shouldn't be necessary on dejagnu-1.4 and later, but 1.3 seems
+# to need it because its runtest.exp doesn't deal with PASS at all.
+if [info exists PASS] {
+    foreach pass $passes {
+	if { [lsearch -exact $PASS [lindex $pass 0]] >= 0 } {
+	    lappend MULTIPASS $pass
+	}
+    }
+} else {
+    set MULTIPASS $passes
+}
+
+set last_passname_conf ""
+set last_passname_db ""
+
+# We do everything in a temporary directory.
+if ![info exists TMPDIR] {
+    set tmppwd "[pwd]/tmpdir"
+    if ![file isdirectory $tmppwd] {
+	catch "exec mkdir $tmppwd" status
+    }
+} else {
+    set tmppwd $TMPDIR
+}
+verbose "tmppwd=$tmppwd"
+
+# On Ultrix, use /bin/sh5 in preference to /bin/sh.
+if ![info exists BINSH] {
+    if [file exists /bin/sh5] {
+	set BINSH /bin/sh5
+    } else {
+	set BINSH /bin/sh
+    }
+}
+
+# For security, we must not use generally known passwords.  This is
+# because some of the tests may be run as root.  If the passwords were
+# generally know, then somebody could work out the appropriate
+# Kerberos ticket to use, and come in when, say, the telnetd daemon
+# was being tested by root.  The window for doing this is very very
+# small, so the password does not have to be perfect, it just can't be
+# constant.
+if ![info exists KEY] {
+    catch {exec $BINSH -c "echo $$"} KEY
+    verbose "KEY is $KEY"
+    set keyfile [open $tmppwd/KEY w]
+    puts $keyfile "$KEY"
+    close $keyfile
+}
+
+# Clear away any files left over from a previous run.
+# We can't use them now because we don't know the right KEY.
+# krb5.conf might change if running tests on another host
+catch "exec rm -f $tmppwd/db.ok $tmppwd/srvtab $tmppwd/krb5.conf $tmppwd/kdc.conf $tmppwd/cpw_srvtab $tmppwd/krb.realms $tmppwd/krb.conf"
+
+# Put the installed kerberos directories on PATH.
+# This needs to be fixed for V5.
+# set env(PATH) $env(PATH):/usr/kerberos/bin:/usr/kerberos/etc
+# verbose "PATH=$env(PATH)"
+
+# Some of the tests expect $env(USER) to be set.
+if ![info exists env(USER)] {
+    if [info exists env(LOGNAME)] {
+	set env(USER) $env(LOGNAME)
+    } else {
+	if [info exists logname] {
+	    set env(USER) $logname
+	} else {
+	    catch "exec whoami" env(USER)
+	}
+    }
+}
+
+# set the realm. The user can override this on the runtest line.
+if ![info exists REALMNAME] {
+    set REALMNAME "KRBTEST.COM"
+}
+verbose "Test realm is $REALMNAME"
+
+# Find some programs we need.  We use the binaries from the build tree
+# if they exist.  If they do not, then they must be in PATH.  We
+# expect $objdir to be ...tests/dejagnu.
+
+foreach i {
+    {KDB5_UTIL $objdir/../../kadmin/dbutil/kdb5_util}
+    {KRB5KDC $objdir/../../kdc/krb5kdc}
+    {KADMIND $objdir/../../kadmin/server/kadmind}
+    {KADMIN $objdir/../../kadmin/cli/kadmin}
+    {KADMIN_LOCAL $objdir/../../kadmin/cli/kadmin.local}
+    {KINIT $objdir/../../clients/kinit/kinit}
+    {KTUTIL $objdir/../../kadmin/ktutil/ktutil}
+    {KLIST $objdir/../../clients/klist/klist}
+    {KDESTROY $objdir/../../clients/kdestroy/kdestroy}
+    {RESOLVE $objdir/../resolve/resolve}
+    {T_INETD $objdir/t_inetd}
+} {
+    set varname [lindex $i 0]
+    if ![info exists $varname] {
+	eval set varval [lindex $i 1]
+	set varval [findfile $varval]
+	set $varname $varval
+	verbose "$varname=$varval"
+    } {
+	eval set varval \$$varname
+	verbose "$varname already set to $varval"
+    }
+}
+
+if ![info exists RLOGIN] {
+    set RLOGIN rlogin
+}
+
+if ![info exists RLOGIN_FLAGS] {
+    set RLOGIN_FLAGS "-x"
+}
+
+# We use a couple of variables to hold shell prompts which may be
+# overridden by the user.
+
+if ![info exists ROOT_PROMPT] {
+    set ROOT_PROMPT "(%|#|>|\\$) $"
+}
+
+if ![info exists SHELL_PROMPT] {
+    set SHELL_PROMPT "(%|#|>|\\$) $"
+}
+
+verbose "setting up onexit handler (old handler=[exit -onexit])"
+exit -onexit [concat {
+    verbose "calling stop_kerberos_daemons (onexit handler)"
+    stop_kerberos_daemons;
+} [exit -onexit]]
+
+# check_k5login
+
+# Most of the tests won't work if the user has a .k5login file, unless
+# the user's name appears with $REALMNAME in .k5login
+
+# This procedure returns 1 if the .k5login file appears to be OK, 0
+# otherwise.  This check is not foolproof.
+
+# Note that this previously checked for a username with no realm; this
+# works for krb4's kuserok() but not for krb5_kuserok(), due to some
+# implementation details.  *sigh*
+
+proc check_k5login { testname } {
+    global env
+    global REALMNAME
+
+    if {![file exists ~/.k5login]} {
+	if {$env(USER) == "root"} {
+	    return 0
+	} else {
+	    return 1
+	}
+    }
+
+    verbose "looking for $env(USER)@$REALMNAME in ~/.k5login" 2
+    set file [open ~/.k5login r]
+    while { [gets $file principal] != -1 } {
+	verbose " found $principal" 2
+	if { $principal == "$env(USER)@$REALMNAME" } {
+	    close $file
+	    return 1
+	}
+    }
+    close $file
+
+    note "$testname test requires that your name appear in your ~/.k5login"
+    note "file in the form $env(USER)@$REALMNAME"
+    unsupported "$testname"
+
+    return 0
+}
+
+proc check_klogin { testname } {
+    global env
+    global REALMNAME
+
+    if {![file exists ~/.klogin]} {
+	if {$env(USER) == "root"} {
+	    return 0
+	} else {
+	    return 1
+	}
+    }
+
+    verbose "looking for $env(USER) in ~/.klogin" 2
+    set file [open ~/.klogin r]
+    while { [gets $file principal] != -1 } {
+	verbose " found $principal" 2
+	if { $principal == "$env(USER)" \
+		|| $principal == "$env(USER)@$REALMNAME" } {
+	    close $file
+	    return 1
+	}
+    }
+    close $file
+
+    note "$testname test requires that your name appear in your ~/.klogin"
+    note "file without a realm."
+    unsupported "$testname"
+
+    return 0
+}
+
+# check_exit_status
+# Check the exit status of a spawned program.  Returns 1 if the
+# program succeeded, 0 if it failed.
+
+proc check_exit_status { testname } {
+    global spawn_id
+
+    verbose "about to wait ($testname)"
+    set status_list [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $status_list ($testname)"
+    catch "close -i $spawn_id"
+    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
+	verbose -log "exit status: $status_list"
+	fail "$testname"
+	return 0
+    } else {
+	return 1
+    }
+}
+
+#
+# ENVSTACK
+#
+
+# These procedures implement an environment variable stack.  They use
+# the global variable $envvars_tosave for the purpose of identifying
+# which environment variables to save.  They also track which ones are
+# unset at any particular point.  The stack pointer is $envstackp,
+# which is an integer.  The arrays $envstack$envstackp and
+# $unenvstack$envstackp store respectively the set of old environment
+# variables/values pushed onto the stack and the set of old unset
+# environment variables for a given value of $envstackp.
+
+# Changing the value of $envvars_tosave after performing the first
+# push operation may result in strangeness.
+
+#
+# envstack_push
+#
+# Push set of current environment variables.
+#
+proc envstack_push { } {
+    global env
+    global envvars_tosave
+    global envstackp
+    global envstack$envstackp
+    global unenvstack$envstackp
+
+    verbose "envstack_push: starting, sp=$envstackp"
+    foreach i $envvars_tosave {
+	if [info exists env($i)] {
+	    verbose "envstack_push: saving $i=$env($i)"
+	    set envstack${envstackp}($i) $env($i)
+	} {
+	    verbose "envstack_push: marking $i as unset"
+	    set unenvstack${envstackp}($i) unset
+	}
+    }
+    incr envstackp
+    verbose "envstack_push: exiting, sp=$envstackp"
+}
+
+#
+# envstack_pop
+#
+# Pop set of current environment variables.
+#
+proc envstack_pop { } {
+    global env
+    global envstackp
+
+    verbose "envstack_pop: starting, sp=$envstackp"
+    incr envstackp -1
+    global envstack$envstackp	# YUCK!!! no obvious better way though...
+    global unenvstack$envstackp
+    if {$envstackp < 0} {
+	perror "envstack_pop: stack underflow!"
+	return
+    }
+    if [info exists envstack$envstackp] {
+	foreach i [array names envstack$envstackp] {
+	    if [info exists env($i)] {
+		verbose "envstack_pop: $i was $env($i)"
+	    }
+	    eval set env($i) \$envstack${envstackp}($i)
+	    verbose "envstack_pop: restored $i to $env($i)"
+	}
+	unset envstack$envstackp
+    }
+    if [info exists unenvstack$envstackp] {
+	foreach i [array names unenvstack$envstackp] {
+	    if [info exists env($i)] {
+		verbose "envstack_pop: $i was $env($i)"
+		unset env($i)
+		verbose "envstack_pop: $i unset"
+	    } {
+		verbose "envstack_pop: ignoring already unset $i"
+	    }
+	}
+	unset unenvstack$envstackp
+    }
+    verbose "envstack_pop: exiting, sp=$envstackp"
+}
+
+#
+# Initialize the envstack
+#
+set envvars_tosave {
+    KRB5_CONFIG KRB5CCNAME KRBTKFILE KRB5RCACHEDIR
+    KERBEROS_SERVER KRB5_KDC_PROFILE
+}
+set krb5_init_vars [list ]
+# XXX -- fix me later!
+foreach i $runvarlist {
+    verbose "processing $i"
+    if {[regexp "^(\[^=\]*)=(.*)" $i foo evar evalue]} {
+	verbose "adding $evar to savelist"
+	lappend envvars_tosave $evar
+	verbose "savelist $envvars_tosave"
+	lappend krb5_init_vars $i
+    }
+}
+set envstackp 0
+envstack_push
+
+# setup_runtime_flags
+# Sets the proper flags for shared libraries. 
+# Configuration is through a site.exp and the runvarlist variable
+# Returns 1 if variables were already set, otherwise 0
+proc setup_runtime_env { } {
+    global env
+    global krb5_init_vars
+
+    # Set the variables
+    foreach i $krb5_init_vars {
+	regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
+	set env($evar) "$evalue"
+	verbose "$evar=$evalue"
+    }
+    return 0
+}
+
+# get_hostname
+# This procedure will get the local hostname.  It sets the global
+# variables hostname (the full name) and localhostname (the first part
+# of the name).  Returns 1 on success, 0 on failure.
+
+proc get_hostname { } {
+    global RESOLVE
+    global hostname
+    global localhostname
+    global domain
+    global tmppwd
+
+    if {[info exists hostname] && [info exists localhostname]} {
+	return 1
+    }
+
+    envstack_push
+    setup_runtime_env
+    catch "exec $RESOLVE -q >$tmppwd/hostname" exec_output
+    envstack_pop
+    if ![string match "" $exec_output] {
+	verbose -log $exec_output
+	perror "can't get hostname"
+	return 0
+    }
+    set file [open $tmppwd/hostname r]
+    if { [ gets $file hostname ] == -1 } {
+	perror "no output from hostname"
+	return 0
+    }
+    close $file
+    catch "exec rm -f $tmppwd/hostname" exec_output
+    regexp "^(\[^.\]*)\\.(.*)$" $hostname foo localhostname domain
+
+    set hostname [string tolower $hostname]
+    set localhostname [string tolower $localhostname]
+    set domain [string tolower $domain]
+    verbose "hostname: $hostname; localhostname: $localhostname; domain $domain"
+
+    return 1
+}
+
+# modify_principal name options...
+
+proc modify_principal { name args } {
+    global KADMIN_LOCAL
+    global REALMNAME
+
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    expect_after {
+	eof {
+	    fail "modprinc (kadmin.local)"
+	    return 0
+	}
+	timeout {
+	    fail "modprinc (kadmin.local)"
+	    return 0
+	}
+    }
+    expect "kadmin.local: "
+    send "modprinc $args $name\r"
+    expect -re "modprinc \[^\n\r\]* $name"
+    expect -re "Principal .* modified."
+    send "quit\r"
+    expect eof
+    catch expect_after
+    if ![check_exit_status "kadmin.local modprinc"] {
+	perror "kadmin.local modprinc exited abnormally"
+    }
+    return 1
+}
+
+# kdc listens on +0..+3, depending whether we're testing reachable or not
+# client tries +1 and +6
+# kadmind +4
+# kpasswd +5
+# krb524 +7
+# application servers (krlogind, telnetd, krshd, ftpd, etc) +8
+if [info exists PORTBASE] {
+    set portbase $PORTBASE
+} else {
+    set portbase 3085
+}
+
+# setup_kerberos_files
+# This procedure will create some Kerberos files which must be created
+# manually before trying to run any Kerberos programs.  Returns 1 on
+# success, 0 on failure.
+
+proc setup_kerberos_files { } {
+    global REALMNAME
+    global hostname
+    global domain
+    global tmppwd
+    global supported_enctypes
+    global kdc_supported_enctypes
+    global last_passname_conf
+    global multipass_name
+    global master_key_type
+    global mode
+    global portbase
+
+    if ![get_hostname] { 
+	return 0
+    }
+
+    setup_krb5_conf client
+    setup_krb5_conf server
+    setup_krb5_conf kdc
+
+    # Create a kdc.conf file.
+    if { ![file exists $tmppwd/kdc.conf] \
+	    || $last_passname_conf != $multipass_name } {
+	if ![info exists master_key_type] {
+	    set master_key_type des-cbc-md5
+	}
+	set conffile [open $tmppwd/kdc.conf w]
+	puts $conffile "\[kdcdefaults\]"
+	puts $conffile "	kdc_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
+	puts $conffile "	kdc_tcp_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
+	puts $conffile ""
+	puts $conffile "\[realms\]"
+	puts $conffile "	$REALMNAME = \{"
+#	puts $conffile "		database_name = $tmppwd/db"
+	puts $conffile "		admin_database_name = $tmppwd/adb"
+	puts $conffile "		admin_database_lockfile = $tmppwd/adb.lock"
+	puts $conffile "		key_stash_file = $tmppwd/stash"
+	puts $conffile "		acl_file = $tmppwd/acl"
+	puts $conffile "		kadmind_port = [expr 4 + $portbase]"
+	puts $conffile "		kpasswd_port = [expr 5 + $portbase]"
+	puts $conffile "		max_life = 1:00:00"
+	puts $conffile "		max_renewable_life = 3:00:00"
+	puts $conffile "		master_key_type = $master_key_type"
+	puts $conffile "		master_key_name = master/key"
+	puts $conffile "		supported_enctypes = $supported_enctypes"
+	puts $conffile "		kdc_supported_enctypes = $kdc_supported_enctypes"
+	if { $mode == "tcp" } {
+	    puts $conffile "		kdc_ports = [expr 3 + $portbase]"
+	    puts $conffile "		kdc_tcp_ports = [expr 1 + $portbase],[expr 3 + $portbase]"
+	} else {
+	    puts $conffile "		kdc_ports = [expr 1 + $portbase]"
+	    puts $conffile "		kdc_tcp_ports = [expr 3 + $portbase]"
+	}
+	puts $conffile "		default_principal_expiration = 2037.12.31.23.59.59"
+	puts $conffile "		default_principal_flags = -postdateable forwardable"
+	puts $conffile "		dict_file = $tmppwd/dictfile"
+	puts $conffile "	\}"
+	puts $conffile ""
+	close $conffile
+    }
+
+    # Create ACL file.
+    if ![file exists $tmppwd/acl] {
+	set aclfile [open $tmppwd/acl w]
+	puts $aclfile "krbtest/admin@$REALMNAME *"
+	close $aclfile
+    }
+
+    # Create krb.conf file
+    if ![file exists $tmppwd/krb.conf] {
+	set conffile [open $tmppwd/krb.conf w]
+	puts $conffile "$REALMNAME"
+	puts $conffile "$REALMNAME $hostname:[expr 1 + $portbase] admin server"
+	close $conffile
+    }
+
+    # Create krb.realms file
+    if ![file exists $tmppwd/krb.realms] {
+	set conffile [open $tmppwd/krb.realms w]
+	puts $conffile ".[string toupper $domain] $REALMNAME"
+	puts $conffile "[string toupper $domain]. $REALMNAME"
+	close $conffile
+    }
+
+    # Create dictfile file.
+    if ![file exists $tmppwd/dictfile] {
+	set dictfile [open $tmppwd/dictfile w]
+	puts $dictfile "weak_password"
+	close $dictfile
+    }
+
+    set last_passname_conf $multipass_name
+    return 1
+}
+
+proc setup_krb5_conf { {type client} } {
+    global tmppwd
+    global hostname
+    global domain
+    global REALMNAME
+    global last_passname_conf
+    global multipass_name
+    global default_tgs_enctypes
+    global default_tkt_enctypes
+    global permitted_enctypes
+    global mode
+    global portbase
+    global KRB5_DB_MODULE_DIR
+
+    # Create a krb5.conf file.
+    if { ![file exists $tmppwd/krb5.$type.conf] \
+	    || $last_passname_conf != $multipass_name } {
+	set conffile [open $tmppwd/krb5.$type.conf w]
+	puts $conffile "\[libdefaults\]"
+	puts $conffile "	default_realm = $REALMNAME"
+	puts $conffile "	dns_lookup_kdc = false"
+	if [info exists default_tgs_enctypes($type)] {
+	    puts $conffile \
+		    "	default_tgs_enctypes = $default_tgs_enctypes($type)"
+	}
+	if [info exists default_tkt_enctypes($type)] {
+	    puts $conffile \
+		    "	default_tkt_enctypes = $default_tkt_enctypes($type)"
+	}
+	if [info exists permitted_enctypes($type)] {
+	    puts $conffile \
+		    "	permitted_enctypes = $permitted_enctypes($type)"
+	}
+	puts $conffile "	krb4_config = $tmppwd/krb.conf"
+	puts $conffile "	krb4_realms = $tmppwd/krb.realms"
+	puts $conffile "	krb4_srvtab = $tmppwd/v4srvtab"
+	if { $mode == "tcp" } {
+	    puts $conffile "	udp_preference_limit = 1"
+	}
+	puts $conffile ""
+	puts $conffile "\[realms\]"
+	puts $conffile "	$REALMNAME = \{"
+	# There's probably nothing listening here.  It would be a good
+	# test for the handling of a non-responsive KDC address.  However,
+	# on some systems, like Tru64, we often wind up with the client's
+	# socket bound to this address, causing our request to appear in
+	# our incoming queue as if it were a response, which causes test
+	# failures.  If we were running the client and KDC on different
+	# hosts, this would be okay....
+	#puts $conffile "		kdc = $hostname:[expr 6 + $portbase]"
+	puts $conffile "		kdc = $hostname:[expr 1 + $portbase]"
+	puts $conffile "		admin_server = $hostname:[expr 4 + $portbase]"
+	puts $conffile "		kpasswd_server = $hostname:[expr 5 + $portbase]"
+	puts $conffile "		default_domain = $domain"
+	puts $conffile "                krb524_server = $hostname:[expr 7 + $portbase]"
+	puts $conffile "		database_module = foo_db2"
+	puts $conffile "	\}"
+	puts $conffile ""
+	puts $conffile "\[domain_realm\]"
+	puts $conffile "	.$domain = $REALMNAME"
+	puts $conffile "	$domain = $REALMNAME"
+	puts $conffile ""
+	puts $conffile "\[logging\]"
+	puts $conffile "	admin_server = FILE:$tmppwd/kadmind5.log"
+	puts $conffile "	kdc = FILE:$tmppwd/kdc.log"
+	puts $conffile "	default = FILE:$tmppwd/others.log"
+	puts $conffile ""
+	puts $conffile "\[dbmodules\]"
+	puts $conffile "	db_module_dir = $tmppwd/../../../util/fakedest$KRB5_DB_MODULE_DIR"
+	puts $conffile "	foo_db2 = {"
+	puts $conffile "		db_library = db2"
+	puts $conffile "		database_name = $tmppwd/db"
+	puts $conffile "	}"
+	close $conffile
+    }
+}
+
+# Save the original values of the environment variables we are going
+# to muck with.
+
+# XXX deal with envstack later.
+
+if [info exists env(KRB5_CONFIG)] {
+    set orig_krb5_conf $env(KRB5_CONFIG)
+} else {
+    catch "unset orig_krb5_config"
+}
+
+if [info exists env(KRB5CCNAME)] {
+    set orig_krb5ccname $env(KRB5CCNAME)
+} else {
+    catch "unset orig_krb5ccname"
+}
+
+if [ info exists env(KRB5RCACHEDIR)] {
+    set orig_krb5rcachedir $env(KRB5RCACHEDIR)
+} else {
+    catch "unset orig_krb5rcachedir"
+}
+
+if [ info exists env(KERBEROS_SERVER)] {
+    set orig_kerberos_server $env(KERBEROS_SERVER)
+} else {
+    catch "unset orig_kerberos_server"
+}
+
+# setup_kerberos_env
+# Set the environment variables needed to run Kerberos programs.
+
+proc setup_kerberos_env { {type client} } {
+    global REALMNAME
+    global env
+    global tmppwd
+    global hostname
+    global krb5_init_vars
+    global portbase
+
+    # Set the environment variable KRB5_CONFIG to point to our krb5.conf file.
+    # All the Kerberos tools check KRB5_CONFIG.
+    # Actually, V5 doesn't currently use this.
+    set env(KRB5_CONFIG) $tmppwd/krb5.$type.conf
+    verbose "KRB5_CONFIG=$env(KRB5_CONFIG)"
+
+    # Direct the Kerberos programs at a local ticket file.
+    set env(KRB5CCNAME) $tmppwd/tkt
+    verbose "KRB5CCNAME=$env(KRB5CCNAME)"
+
+    # Direct the Kerberos programs at a local ticket file.
+    set env(KRBTKFILE) $tmppwd/tktv4
+    verbose "KRBTKFILE=$env(KRBTKFILE)"
+
+    # Direct the Kerberos server at a cache file stored in the
+    # temporary directory.
+    set env(KRB5RCACHEDIR) $tmppwd
+    verbose "KRB5RCACHEDIR=$env(KRB5RCACHEDIR)"
+
+    # Tell the Kerberos tools how to contact the $REALMNAME server.
+    set env(KERBEROS_SERVER) "$REALMNAME:$hostname:[expr 1 + $portbase]"
+    verbose "KERBEROS_SERVER=$env(KERBEROS_SERVER)"
+
+    # Get the run time environment variables... (including LD_LIBRARY_PATH)
+    setup_runtime_env
+
+    # Set our kdc config file.
+    set env(KRB5_KDC_PROFILE) $tmppwd/kdc.conf
+    verbose "KRB5_KDC_PROFILE=$env(KRB5_KDC_PROFILE)"
+
+    # Create an environment setup script.  (For convenience)
+    if ![file exists $tmppwd/env.sh] {
+	set envfile [open $tmppwd/env.sh w]
+	puts $envfile "KRB5_CONFIG=$env(KRB5_CONFIG)"
+	puts $envfile "KRB5CCNAME=$env(KRB5CCNAME)"
+	puts $envfile "KRB5RCACHEDIR=$env(KRB5RCACHEDIR)"
+	puts $envfile "KERBEROS_SERVER=$env(KERBEROS_SERVER)"
+	puts $envfile "KRB5_KDC_PROFILE=$env(KRB5_KDC_PROFILE)"
+	puts $envfile "export KRB5_CONFIG KRB5CCNAME KRB5RCACHEDIR"
+	puts $envfile "export KERBEROS_SERVER KRB5_KDC_PROFILE"
+	foreach i $krb5_init_vars {
+		regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
+		puts $envfile "$evar=$env($evar)"
+		puts $envfile "export $evar"
+	}
+	close $envfile
+    }
+    if ![file exists $tmppwd/env.csh] {
+	set envfile [open $tmppwd/env.csh w]
+	puts $envfile "setenv KRB5_CONFIG $env(KRB5_CONFIG)"
+	puts $envfile "setenv KRB5CCNAME $env(KRB5CCNAME)"
+	puts $envfile "setenv KRB5RCACHEDIR $env(KRB5RCACHEDIR)"
+	puts $envfile "setenv KERBEROS_SERVER $env(KERBEROS_SERVER)"
+	puts $envfile "setenv KRB5_KDC_PROFILE $env(KRB5_KDC_PROFILE)"
+	foreach i $krb5_init_vars {
+		regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
+		puts $envfile "setenv $evar $env($evar)"
+	}
+	close $envfile
+    }
+    return 1
+}
+
+# Restore the Kerberos environment, in case setup_kerberos_env was
+# already called by an earlier test.
+
+proc restore_kerberos_env { } {
+    global env
+    global orig_krb5_config
+    global orig_krb5ccname
+    global orig_krb5rcachedir
+    global orig_kerberos_server
+
+    if [info exists orig_krb5_config] {
+    set env(KRB5_CONFIG) $orig_krb5_config
+    } else {
+    catch "unset env(KRB5_CONFIG)"
+    }
+
+    if [info exists orig_krb5ccname] {
+	set env(KRB5CCNAME) $orig_krb5ccname
+    } else {
+	catch "unset env(KRB5CCNAME)"
+    }
+
+    if [info exists orig_krb5rcachedir] {
+	set env(KRB5RCACHEDIR) $orig_krb5rcachedir
+    } else {
+	catch "unset env(KRB5RCACHEDIR)"
+    }
+
+    if [info exists orig_kerberos_server] {
+	set env(KERBEROS_SERVER) $orig_kerberos_server
+    } else {
+	catch "unset env(KERBEROS_SERVER)"
+    }
+
+}
+
+# setup_kerberos_db
+# Initialize the Kerberos database.  If the argument is non-zero, call
+# pass at relevant points.  Returns 1 on success, 0 on failure.
+
+proc setup_kerberos_db { standalone } {
+    global REALMNAME
+    global KDB5_UTIL
+    global KADMIN_LOCAL
+    global KEY
+    global tmppwd
+    global spawn_id
+    global des3_krbtgt
+    global tgt_support_desmd5
+    global multipass_name
+    global last_passname_db
+
+    set failall 0
+
+    if {!$standalone && [file exists $tmppwd/db.ok] \
+	&& $last_passname_db == $multipass_name} {
+	return 1
+    }
+
+    catch "exec rm -f [glob -nocomplain $tmppwd/db* $tmppwd/adb*]"
+
+    # Creating a new database means we need a new srvtab.
+    catch "exec rm -f $tmppwd/srvtab"
+
+    envstack_push
+    if { ![setup_kerberos_files] || ![setup_kerberos_env kdc] } {
+	set failall 1
+    }
+
+    # Set up a common expect_after for use in multiple places.
+    set def_exp_after {
+	timeout {
+	    set test "$test (timeout)"
+	    break
+	}
+	eof {
+	    set test "$test (eof)"
+	    break
+	}
+    }
+
+    set test "kdb5_util create"
+    set body {
+	if $failall {
+	    break
+	}
+	#exec xterm
+	verbose "starting $test"
+	spawn $KDB5_UTIL -r $REALMNAME create
+	expect_after $def_exp_after
+
+	expect "Enter KDC database master key:"
+
+	set test "kdb5_util create (verify)"
+	send "masterkey$KEY\r"
+	expect "Re-enter KDC database master key to verify:"
+
+	set test "kdb5_util create"
+	send "masterkey$KEY\r"
+	expect {
+	    -re "\[Cc\]ouldn't" {
+		expect eof
+		break
+	    }
+	    "Cannot find/read stored" exp_continue
+	    "Warning: proceeding without master key" exp_continue
+	    eof { }
+	}
+	catch expect_after
+	if ![check_exit_status kdb5_util] {
+	    break
+	}
+    }
+    set ret [catch $body]
+    catch expect_after
+    if $ret {
+	set failall 1
+	if $standalone {
+	    fail $test
+	}
+    } else {
+	if $standalone {
+	    pass $test
+	}
+    }
+
+    # Stash the master key in a file.
+    set test "kdb5_util stash"
+    set body {
+	if $failall {
+	    break
+	}
+	spawn $KDB5_UTIL  -r $REALMNAME stash
+	verbose "starting $test"
+	expect_after $def_exp_after
+	expect "Enter KDC database master key:"
+	send "masterkey$KEY\r"
+	expect eof
+	catch expect_after
+	if ![check_exit_status kdb5_util] {
+	    break
+	}
+    }
+    set ret [catch $body]
+    catch "expect eof"
+    catch expect_after
+    if $ret {
+	set failall 1
+	if $standalone {
+	    fail $test
+	} else {
+	    catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
+	}
+    } else {
+	if $standalone {
+	    pass $test
+	}
+    }
+
+    # Add an admin user.
+#send_user "will run: $KADMIN_LOCAL -r $REALMNAME\n"
+#exec xterm
+    set test "kadmin.local ank krbtest/admin"
+    set body {
+	if $failall {
+	    break
+	}
+	spawn $KADMIN_LOCAL -r $REALMNAME
+	verbose "starting $test"
+	expect_after $def_exp_after
+
+	expect "kadmin.local: "
+	send "ank krbtest/admin@$REALMNAME\r"
+	# It echos...
+	expect "ank krbtest/admin@$REALMNAME\r"
+	expect "Enter password for principal \"krbtest/admin@$REALMNAME\":"
+	send "adminpass$KEY\r"
+	expect "Re-enter password for principal \"krbtest/admin@$REALMNAME\":"
+	send "adminpass$KEY\r"
+	expect {
+	    "Principal \"krbtest/admin@$REALMNAME\" created" { }
+	    "Principal or policy already exists while creating*" { }
+	}
+	expect "kadmin.local: "
+	send "quit\r"
+	expect eof
+	catch expect_after
+	if ![check_exit_status kadmin_local] {
+	    break
+	}
+    }
+    set ret [catch $body]
+    catch "expect eof"
+    catch expect_after
+    if $ret {
+	set failall 1
+	if $standalone {
+	    fail $test
+	} else {
+	    catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
+	}
+    } else {
+	if $standalone {
+	    pass $test
+	}
+    }
+
+    if $des3_krbtgt {
+	# Set the TGT key to DES3.
+	set test "kadmin.local TGT to DES3"
+	set body {
+	    if $failall {
+		break
+	    }
+	    spawn $KADMIN_LOCAL -r $REALMNAME -e des3-cbc-sha1:normal
+	    verbose "starting $test"
+	    expect_after $def_exp_after
+
+	    expect "kadmin.local: "
+	    send "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
+	    # It echos...
+	    expect "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
+	    expect {
+		"Key for \"krbtgt/$REALMNAME@$REALMNAME\" randomized." { }
+	    }
+	    expect "kadmin.local: "
+	    send "quit\r"
+	    expect eof
+	    catch expect_after
+	    if ![check_exit_status kadmin_local] {
+		break
+	    }
+	}
+	set ret [catch $body]
+	catch "expect eof"
+	catch expect_after
+	if $ret {
+	    set failall 1
+	    if $standalone {
+		fail $test
+	    } else {
+		catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
+	    }
+	} else {
+	    if $standalone {
+		pass $test
+	    }
+	}
+    }
+    if $tgt_support_desmd5 {
+	# Make TGT support des-cbc-md5
+	set test "kadmin.local TGT to SUPPORT_DESMD5"
+	set body {
+	    if $failall {
+		break
+	    }
+	    spawn $KADMIN_LOCAL -r $REALMNAME
+	    verbose "starting $test"
+	    expect_after $def_exp_after
+
+	    expect "kadmin.local: "
+	    send "modprinc +support_desmd5 krbtgt/$REALMNAME@$REALMNAME\r"
+	    # It echos...
+	    expect "modprinc +support_desmd5 krbtgt/$REALMNAME@$REALMNAME\r"
+	    expect {
+		"Principal \"krbtgt/$REALMNAME@$REALMNAME\" modified.\r\n" { }
+	    }
+	    expect "kadmin.local: "
+	    send "quit\r"
+	    expect eof
+	    catch expect_after
+	    if ![check_exit_status kadmin_local] {
+		break
+	    }
+	}
+	set ret [catch $body]
+	catch "expect eof"
+	catch expect_after
+	if $ret {
+	    set failall 1
+	    if $standalone {
+		fail $test
+	    } else {
+		catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
+	    }
+	} else {
+	    if $standalone {
+		pass $test
+	    }
+	}
+    }
+    envstack_pop
+
+    # create the admin database lock file
+    catch "exec touch $tmppwd/adb.lock"
+
+    set last_passname_db $multipass_name
+    return 1
+}
+
+proc start_tail { fname spawnid_var pid_var which standalone } {
+    upvar $spawnid_var spawnid
+    upvar $pid_var pid
+    global timeout
+
+    set f [open $fname a]
+
+    spawn tail -f $fname
+    set spawnid $spawn_id
+    set pid [exp_pid]
+
+    set markstr "===MARK $pid [clock format [clock seconds]] ==="
+    puts $f $markstr
+    flush $f
+
+    set p 0
+    set otimeout $timeout
+    set timeout 1
+    set ok 0
+    while { $ok == 0 && $p < 3 } {
+	expect {
+	    -i $spawn_id
+	    -ex "$markstr\r\n" { set ok 1 }
+	    -re "\[^\r\n\]*\r\n" { exp_continue }
+	    timeout {
+		# Some versions of GNU tail had a race condition where
+		# the first batch of data would be read from the end
+		# of the file, and then there was a brief window
+		# before calling stat and recording the size of the
+		# file.  If the marker is written during that window,
+		# then yet another file modification is needed to get
+		# the first one noticed.
+		if { $p < 3 } {
+		    verbose -log "no tail output yet, prodding with a blank line"
+		    incr p
+		    puts $f ""
+		    flush $f
+		    exp_continue
+		} else {
+		    close $f
+		    verbose -log "tail $fname output:"
+		    verbose -log [exec tail $fname]
+		    if {$standalone} {
+			verbose -log "tail -f timed out ($timeout sec) looking for mark in $which log"
+			fail "$which"
+		    } else {
+			perror "$which tail -f timed out ($timeout sec) looking for mark in $which log"
+		    }
+		    stop_kerberos_daemons
+		    exec kill $pid
+		    expect -i $spawn_id eof
+		    wait -i $spawn_id
+		    set timeout $otimeout
+		    return 0
+		}
+	    }
+	}
+    }
+    close $f
+    set timeout $otimeout
+    return 1
+}
+
+# start_kerberos_daemons
+# A procedure to build a Kerberos database and start up the kerberos
+# and kadmind daemons.  This sets the global variables kdc_pid,
+# kdc_spawn_id, kadmind_pid, and kadmind_spawn_id.  The procedure
+# stop_kerberos_daemons should be used to stop the daemons.  If the
+# argument is non-zero, call pass at relevant points.  Returns 1 on
+# success, 0 on failure.
+
+proc start_kerberos_daemons { standalone } {
+    global BINSH
+    global REALMNAME
+    global KRB5KDC
+    global KADMIND
+    global KEY
+    global kdc_pid
+    global kdc_spawn_id
+    global kadmind_pid
+    global kadmind_spawn_id
+    global tmppwd
+    global env
+    global timeout
+
+    if ![setup_kerberos_db 0] {
+	return 0
+    }
+
+    if {$standalone} {
+        catch "exec rm -f $tmppwd/krb.log"
+	catch "exec rm -f $tmppwd/kadmind.log"
+	catch "exec rm -f $tmppwd/krb5kdc_rcache"
+    }
+
+    # Start up the kerberos daemon
+    # Why are we doing all this with the log file you may ask.
+    #   We need a handle on when the server starts. If we log the output
+    #   of the server to say stderr, then if we stop looking for output,
+    #   buffers will fill and the server will stop working....
+    #   So, we look to see when a line is added to the log file and then
+    #   check it..
+    # The same thing is done a little later for the kadmind
+    set kdc_lfile $tmppwd/kdc.log
+    set kadmind_lfile $tmppwd/kadmind5.log
+
+    if ![start_tail $kdc_lfile tailf_spawn_id tailf_pid krb5kdc $standalone] {
+	return 0
+    }
+
+    envstack_push
+    setup_kerberos_env kdc
+    spawn $KRB5KDC -r $REALMNAME -n -4 full
+    envstack_pop
+    set kdc_pid [exp_pid]
+    set kdc_spawn_id $spawn_id
+
+    expect {
+	-i $tailf_spawn_id
+	-re "commencing operation\r\n" { }
+	-re "krb5kdc: \[a-zA-Z\]* - Cannot bind server socket to \[ 0-9a-fA-F:.\]*\r\n" {
+	    verbose -log "warning: $expect_out(0,string)"
+	    exp_continue
+	}
+	"no sockets set up?" {
+	    if {$standalone} {
+		verbose -log "krb5kdc startup failed to bind listening sockets"
+		fail "krb5kdc"
+	    } else {
+		perror "krb5kdc startup failed to bind listening sockets"
+	    }
+	    stop_kerberos_daemons
+	    exec kill $tailf_pid
+	    expect -i $tailf_spawn_id eof
+	    wait -i $tailf_spawn_id
+	    return 0
+	}
+	timeout {
+	    if {$standalone} {
+		verbose -log "krb5kdc startup timed out"
+		fail "krb5kdc"
+	    } else {
+		perror "krb5kdc startup timed out"
+	    }
+	    stop_kerberos_daemons
+	    exec kill $tailf_pid
+	    expect -i $tailf_spawn_id eof
+	    wait -i $tailf_spawn_id
+	    return 0
+	}
+    }
+    exec kill $tailf_pid
+    expect -i $tailf_spawn_id eof
+    wait -i $tailf_spawn_id
+
+    if {$standalone} {
+	pass "krb5kdc"
+    }
+
+    # Give the kerberos daemon a few seconds to get set up.
+#    sleep 2
+
+    #
+    # Save setting of KRB5_KTNAME. We do not want to override kdc.conf
+    # file during kadmind startup. (this is in case user has KRB5_KTNAME
+    # set before starting make check)
+    #
+    if [info exists env(KRB5_KTNAME)] {
+	set start_save_ktname $env(KRB5_KTNAME)
+    }
+    catch "unset env(KRB5_KTNAME)"
+
+    if ![start_tail $kadmind_lfile tailf_spawn_id tailf_pid kadmind $standalone] {
+	return 0
+    }
+
+    # Start up the kadmind daemon
+    # XXXX kadmind uses stderr a lot.  the sh -c and redirect can be
+    # removed when this is fixed
+    envstack_push
+    setup_kerberos_env kdc
+    spawn $BINSH -c "exec $KADMIND -r $REALMNAME -nofork 2>>$kadmind_lfile"
+    envstack_pop
+    set kadmind_pid [exp_pid]
+    set kadmind_spawn_id $spawn_id
+
+    # Restore KRB5_KTNAME
+    if [info exists start_save_ktname] {
+        set env(KRB5_KTNAME) $start_save_ktname
+        unset start_save_ktname
+    }
+
+    expect {
+	-i $tailf_spawn_id
+	"Seeding random number" exp_continue
+	"cannot initialize network" {
+	    if {$standalone} {
+		verbose -log "kadmind failed network init"
+		fail "kadmind"
+	    } else {
+		perror "kadmind failed network init"
+	    }
+	    stop_kerberos_daemons
+	    exec kill $tailf_pid
+	    expect -i $tailf_spawn_id eof
+	    wait -i $tailf_spawn_id
+	    return 0
+	}
+	"cannot bind to network address" {
+	    if {$standalone} {
+		verbose -log "kadmind failed to bind socket"
+		fail "kadmind"
+	    } else {
+		perror "kadmind failed to bind socket"
+	    }
+	    stop_kerberos_daemons
+	    exec kill $tailf_pid
+	    expect -i $tailf_spawn_id eof
+	    wait -i $tailf_spawn_id
+	    return 0
+	}
+	"No principal in keytab matches desired name" {
+	    dump_db
+	    exp_continue
+	}
+	"starting" { }
+	timeout {
+	    if {$standalone} {
+		verbose -log "kadmind failed to start"
+		fail "kadmind"
+	    } else {
+		verbose -log "kadmind failed to start"
+		perror "kadmind failed to start"
+	    }
+#sleep 10
+	    stop_kerberos_daemons
+	    exec kill $tailf_pid
+	    expect -i $tailf_spawn_id eof
+	    wait -i $tailf_spawn_id
+	    return 0
+	}
+    }
+    exec kill $tailf_pid
+    expect -i $tailf_spawn_id eof
+    wait -i $tailf_spawn_id
+
+    if {$standalone} {
+	pass "kadmind"
+    }
+
+    # Give the kadmind daemon a few seconds to get set up.
+#    sleep 2
+
+    return 1
+}
+
+# stop_kerberos_daemons
+# Stop the kerberos daemons.  Returns 1 on success, 0 on failure.
+
+proc stop_kerberos_daemons { } {
+    global kdc_pid
+    global kdc_spawn_id
+    global kadmind_pid
+    global kadmind_spawn_id
+
+    verbose "entered stop_kerberos_daemons"
+
+    if [info exists kdc_pid] {
+	if [catch "exec kill $kdc_pid" msg] {
+	    verbose "kill kdc: $msg"
+	}
+	if [catch "expect -i $kdc_spawn_id eof" msg] {
+	    verbose "expect kdc eof: $msg"
+	}
+	set kdc_list [wait -i $kdc_spawn_id]
+	verbose "wait -i $kdc_spawn_id returned $kdc_list (kdc)"
+	unset kdc_pid
+	unset kdc_list
+    }
+
+    if [info exists kadmind_pid] {
+	if [catch "exec kill $kadmind_pid" msg] {
+	    verbose "kill kadmind: $msg"
+	}
+	if [catch "expect -i $kadmind_spawn_id eof" msg] {
+	    verbose "expect kadmind eof: $msg"
+	}
+	set kadmind_list [wait -i $kadmind_spawn_id]
+	verbose "wait -i $kadmind_spawn_id returned $kadmind_list (kadmind5)"
+	unset kadmind_pid
+	unset kadmind_list
+    }
+
+    verbose "exiting stop_kerberos_daemons"
+
+    return 1
+}
+
+# add_kerberos_key
+# Add an key to the Kerberos database.  start_kerberos_daemons must be
+# called before this procedure.  If the standalone argument is
+# non-zero, call pass at relevant points.  Returns 1 on success, 0 on
+# failure.
+
+proc add_kerberos_key { kkey standalone } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    # Use kadmin to add an key.
+    set test "kadmin ank $kkey"
+    set body {
+	envstack_push
+	setup_kerberos_env client
+	spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank $kkey@$REALMNAME"
+	envstack_pop
+	verbose "starting $test"
+	expect_after {
+	    "Cannot contact any KDC" {
+		set test "$test (lost KDC)"
+		break
+	    }
+	    timeout {
+		set test "$test (timeout)"
+		break
+	    }
+	    eof {
+		set test "$test (eof)"
+		break
+	    }
+	}
+	expect -re "assword\[^\r\n\]*: *"
+	send "adminpass$KEY\r"
+	expect "Enter password for principal \"$kkey@$REALMNAME\":"
+	send "$kkey"
+	send "$KEY\r"
+	expect "Re-enter password for principal \"$kkey@$REALMNAME\":"
+	send "$kkey"
+	send "$KEY\r"
+	expect {
+	    "Principal \"$kkey@$REALMNAME\" created" { }
+	    "Principal or policy already exists while creating*" { }
+	}
+	expect eof
+	if ![check_exit_status kadmin] {
+	    break
+	}
+    }
+    set ret [catch $body]
+    catch "expect eof"
+    catch expect_after
+    if $ret {
+	if $standalone {
+	    fail $test
+	}
+	return 0
+    } else {
+	if $standalone {
+	    pass $test
+	}
+	return 1
+    }
+}
+
+# dump_db
+proc dump_db { } {
+    global KADMIN_LOCAL
+    global REALMNAME
+
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    expect_after {
+	eof {
+	    perror "failed to get debugging dump of database (eof)"
+	}
+	timeout {
+	    perror "failed to get debugging dump of database (timeout)"
+	}
+    }
+    expect "kadmin.local: "
+    send "getprincs\r"
+    expect "kadmin.local: "
+    send "quit\r"
+    expect eof
+    catch expect_after
+}
+
+# add_random_key
+# Add a key with a random password to the Kerberos database.
+# start_kerberos_daemons must be called before this procedure.  If the
+# standalone argument is non-zero, call pass at relevant points.
+# Returns 1 on success, 0 on failure.
+
+proc add_random_key { kkey standalone } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    # Use kadmin to add an key.
+    set test "kadmin ark $kkey"
+    set body {
+	envstack_push
+	setup_kerberos_env client
+	spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank -randkey $kkey@$REALMNAME"
+	envstack_pop
+	expect_after {
+	    timeout {
+		set test "$test (timeout)"
+		break
+	    }
+	    eof {
+		set test "$test (eof)"
+		break
+	    }
+	}
+	expect -re "assword\[^\r\n\]*: *"
+	send "adminpass$KEY\r"
+	expect {
+	    "Principal \"$kkey@$REALMNAME\" created" { }
+	    "Principal or policy already exists while creating*" { }
+	}
+	expect eof
+	if ![check_exit_status kadmin] {
+	    break
+	}
+    }
+    if [catch $body] {
+	catch expect_after
+	if $standalone {
+	    fail $test
+	}
+	return 0
+    } else {
+	catch expect_after
+	if $standalone {
+	    pass $test
+	}
+	return 1
+    }
+}
+
+# setup_srvtab
+# Set up a srvtab file.  start_kerberos_daemons and add_random_key
+# $id/$hostname must be called before this procedure.  If the
+# argument is non-zero, call pass at relevant points.  Returns 1 on
+# success, 0 on failure. If the id field is not provided, host is used.
+
+proc setup_srvtab { standalone {id host} } {
+    global REALMNAME
+    global KADMIN_LOCAL
+    global KEY
+    global tmppwd
+    global hostname
+    global spawn_id
+    global last_service
+
+    if {!$standalone && [file exists $tmppwd/srvtab] && $last_service == $id} {
+	return 1
+    }
+
+    catch "exec rm -f $tmppwd/srvtab $tmppwd/srvtab.old"
+
+    if ![get_hostname] {
+	return 0
+    }
+
+    catch "exec rm -f $hostname-new-srvtab"
+
+    envstack_push
+    setup_kerberos_env kdc
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    envstack_pop
+    expect_after {
+	-re "(.*)\r\nkadmin.local:  " {
+	    fail "kadmin.local srvtab (unmatched output: $expect_out(1,string))"
+	    if {!$standalone} {
+		catch "exec rm -f $tmppwd/srvtab"
+	    }
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin.local srvtab"
+	    if {!$standalone} {
+		catch "exec rm -f $tmppwd/srvtab"
+	    }
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin.local srvtab"
+	    if {!$standalone} {
+		catch "exec rm -f $tmppwd/srvtab"
+	    }
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect "kadmin.local:  "
+    send "xst -k $hostname-new-srvtab $id/$hostname\r"
+    expect "xst -k $hostname-new-srvtab $id/$hostname\r\n"
+    expect {
+	-re ".*Entry for principal $id/$hostname.* added to keytab WRFILE:$hostname-new-srvtab." { }
+	-re "\r\nkadmin.local:  " {
+	    if {$standalone} {
+		fail "kadmin.local srvtab"
+	    } else {
+		catch "exec rm -f $tmppwd/srvtab"
+	    }
+	    catch expect_after
+	    return 0
+	}
+    }
+    expect "kadmin.local:  "
+    send "quit\r"
+    expect eof
+    catch expect_after
+    if ![check_exit_status "kadmin.local srvtab"] {
+	if {!$standalone} {
+	    catch "exec rm -f $tmppwd/srvtab"
+	}
+	return 0
+    }
+
+    catch "exec mv -f $hostname-new-srvtab $tmppwd/srvtab" exec_output
+    if ![string match "" $exec_output] {
+	verbose -log "$exec_output"
+	perror "can't mv new srvtab"
+	return 0
+    }
+
+    if {$standalone} {
+	pass "kadmin.local srvtab"
+    }
+
+    # Make the srvtab file globally readable in case we are using a
+    # root shell and the srvtab is NFS mounted.
+    catch "exec chmod a+r $tmppwd/srvtab"
+
+    # Remember what we just extracted
+    set last_service $id
+
+    return 1
+}
+
+# kinit
+# Use kinit to get a ticket.  If the argument is non-zero, call pass
+# at relevant points.  Returns 1 on success, 0 on failure.
+
+proc kinit { name pass standalone } {
+    global REALMNAME
+    global KINIT
+    global spawn_id
+
+    # Use kinit to get a ticket.
+	#
+	# For now always get forwardable tickets. Later when we need to make
+	# tests that distiguish between forwardable tickets and otherwise
+	# we should but another option to this proc. --proven
+	#
+    spawn $KINIT -5 -f $name@$REALMNAME
+    expect {
+	"Password for $name@$REALMNAME:" {
+	    verbose "kinit started"
+	}
+	timeout {
+	    fail "kinit"
+	    return 0
+	}
+	eof {
+	    fail "kinit"
+	    return 0
+	}
+    }
+    send "$pass\r"
+    expect eof
+    if ![check_exit_status kinit] {
+	return 0
+    }
+
+    if {$standalone} {
+	pass "kinit"
+    }
+
+    return 1
+}
+
+proc kinit_kt { name keytab standalone testname } {
+    global REALMNAME
+    global KINIT
+    global spawn_id
+
+    # Use kinit to get a ticket.
+	#
+	# For now always get forwardable tickets. Later when we need to make
+	# tests that distiguish between forwardable tickets and otherwise
+	# we should but another option to this proc. --proven
+	#
+    spawn $KINIT -5 -f -k -t $keytab $name@$REALMNAME
+    expect {
+	timeout {
+	    fail "kinit $testname"
+	    return 0
+	}
+	eof { }
+    }
+    if ![check_exit_status "kinit $testname"] {
+	return 0
+    }
+
+    if {$standalone} {
+	pass "kinit $testname"
+    }
+
+    return 1
+}
+
+# List tickets.  Requires client and server names, and test name.
+# Checks that klist exist status is zero.
+# Records pass or fail, and returns 1 or 0.
+proc do_klist { myname servname testname } {
+    global KLIST
+    global tmppwd
+
+    spawn $KLIST -5 -e
+    expect {
+	-re "Ticket cache:\[ 	\]*(.+:)?$tmppwd/tkt.*Default principal:\[ 	\]*$myname.*$servname\r\n" {
+	    verbose "klist started"
+	}
+	timeout {
+	    fail $testname
+	    return 0
+	}
+	eof {
+	    fail $testname
+	    return 0
+	}
+    }
+
+    expect eof
+
+    if ![check_exit_status $testname] {
+	return 0
+    }
+    pass $testname
+    return 1
+}
+
+proc do_klist_kt { keytab testname } {
+    global KLIST
+    global tmppwd
+
+    spawn $KLIST -5 -e -k $keytab
+    expect {
+	-re "Keytab name:\[ 	\]*(.+:)?.*KVNO Principal\r\n---- -*\r\n" {
+	    verbose "klist started"
+	}
+	timeout {
+	    fail $testname
+	    return 0
+	}
+	eof {
+	    fail $testname
+	    return 0
+	}
+    }
+    set more 1
+    while {$more} {
+	expect {
+	    -re { *[0-9][0-9]* *[a-zA-Z/@.-]* \([/a-zA-Z 0-9-]*\) *\r\n} {
+		verbose -log "key: $expect_out(buffer)"
+	    }
+	    eof { set more 0 }
+	}
+    }
+
+    if ![check_exit_status $testname] {
+	return 0
+    }
+    pass $testname
+    return 1
+}
+
+proc do_klist_err { testname } {
+    global KLIST
+    global spawn_id
+
+    spawn $KLIST -5
+    # Might say "credentials cache" or "credentials cache file".
+    expect {
+	-re "klist: No credentials cache.*found.*\r\n" {
+	    verbose "klist started"
+	}
+	timeout {
+	    fail $testname
+	    return 0
+	}
+	eof {
+	    fail $testname
+	    return 0
+	}
+    }
+    # We can't use check_exit_status, because we expect an exit status
+    # of 1.
+    catch "expect eof"
+    set status_list [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $status_list ($testname)"
+    if { [lindex $status_list 2] != 0 } {
+	fail "$testname (bad exit status) $status_list"
+	return 0
+    } else { if { [lindex $status_list 3] != 1 } {
+	fail "$testname (bad exit status) $status_list"
+	return 0
+    } else {
+	pass $testname
+    } }
+    return 1
+}
+
+proc do_kdestroy { testname } {
+    global KDESTROY
+    spawn $KDESTROY -5
+    if ![check_exit_status $testname] {
+	fail $testname
+	return 0
+    }
+    pass $testname
+    return 1
+}
+
+proc xst { keytab name } {
+    global KADMIN_LOCAL
+    global REALMNAME
+
+    envstack_push
+    setup_kerberos_env kdc
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    envstack_pop
+    catch expect_after
+    expect_after {
+	-re "(.*)\r\nkadmin.local:  " {
+	    fail "kadmin.local xst $keytab (unmatched output: $expect_out(1,string)"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin.local xst $keytab (timeout)"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin.local xst $keytab (eof)"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect "kadmin.local:  "
+    send "xst -k $keytab $name\r"
+    expect -re "xst -k \[^\r\n\]*\r\n.*Entry for principal .* added to keytab WRFILE:.*\r\nkadmin.local:  "
+    send "quit\r"
+    expect eof
+    catch expect_after
+    if ![check_exit_status "kadmin.local $keytab"] {
+	perror "kadmin.local xst $keytab exited abnormally"
+	return 0
+    }
+    return 1
+}
+
+# v4_compatible_enctype
+# Returns 1 if v4 testing is enabled this passes encryption types are compatable with kerberos 4 work
+proc v4_compatible_enctype {} {
+    global supported_enctypes
+    global KRBIV
+
+    if ![info exists KRBIV] {
+	return 0;
+    }
+
+    if { $KRBIV && [string first des-cbc-crc:v4 "$supported_enctypes"] >= 0} {
+	return 1
+    } else {
+	return 0
+    }
+}
+
+# kinit
+# Use kinit to get a ticket.  If the argument is non-zero, call pass
+# at relevant points.  Returns 1 on success, 0 on failure.
+
+proc v4kinit { name pass standalone } {
+    global REALMNAME
+    global KINIT
+    global spawn_id
+    global des3_krbtgt
+
+    # Use kinit to get a ticket.
+	#
+	# For now always get forwardable tickets. Later when we need to make
+	# tests that distiguish between forwardable tickets and otherwise
+	# we should but another option to this proc. --proven
+	#
+    spawn $KINIT -4 $name@$REALMNAME
+    expect {
+	"Password for $name@$REALMNAME:" {
+	    verbose "v4kinit started"
+	}
+	timeout {
+	    fail "v4kinit"
+	    return 0
+	}
+	eof {
+	    fail "v4kinit"
+	    return 0
+	}
+    }
+    send "$pass\r"
+    expect eof
+    if {$des3_krbtgt == 0} {
+	if ![check_exit_status v4kinit] {
+	    return 0
+	}
+    } else {
+	# Fail if kinit is successful with a des3 TGT.
+	set status_list [wait -i $spawn_id]
+	set testname v4kinit
+	verbose "wait -i $spawn_id returned $status_list ($testname)"
+	if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } {
+	    verbose -log "exit status: $status_list"
+	    fail "$testname (exit status)"
+	}
+    }
+    if {$standalone} {
+	pass "v4kinit"
+    }
+
+    return 1
+}
+
+proc v4kinit_kt { name keytab standalone } {
+    global REALMNAME
+    global KINIT
+    global spawn_id
+
+    # Use kinit to get a ticket.
+	#
+	# For now always get forwardable tickets. Later when we need to make
+	# tests that distiguish between forwardable tickets and otherwise
+	# we should but another option to this proc. --proven
+	#
+    spawn $KINIT -4 -k -t $keytab $name@$REALMNAME
+    expect {
+	timeout {
+	    fail "v4kinit"
+	    return 0
+	}
+	eof { }
+    }
+    if ![check_exit_status kinit] {
+	return 0
+    }
+
+    if {$standalone} {
+	pass "v4kinit"
+    }
+
+    return 1
+}
+
+# List v4 tickets.
+# Client and server are regular expressions.
+proc v4klist { client server testname } {
+    global KLIST
+    global tmppwd
+
+    spawn $KLIST -4
+    expect {
+	-re "Kerberos 4 ticket cache:\[ 	\]*(.+:)?$tmppwd/tkt.*Principal:\[ 	\]*$client.*$server\r\n" {
+	    verbose "klist started"
+	}
+	timeout {
+	    fail $testname
+	    return 0
+	}
+	eof {
+	    fail $testname
+	    return 0
+	}
+    }
+
+    expect eof
+
+    if ![check_exit_status $testname] {
+	return 0
+    }
+    pass $testname
+    return 1
+}
+
+# Destroy tickets.
+proc v4kdestroy { testname } {
+    global KDESTROY
+    spawn $KDESTROY -4
+    if ![check_exit_status $testname] {
+	return 0
+    }
+    pass $testname
+    return 1
+}
+
+# Try to list the krb4 tickets -- there shouldn't be any ticket file.
+proc v4klist_none { testname } {
+    global KLIST
+    global tmppwd
+
+    # Double check that the ticket was destroyed.
+    spawn $KLIST -4
+    expect {
+	-re "Kerberos 4 ticket cache:\[ 	\]*(.+:)?$tmppwd/tkt.*klist: You have no tickets cached.*\r\n" {
+	    verbose "v4klist started"
+	    pass "$testname (output)"
+	}
+	timeout {
+	    fail "$testname (output)"
+	    # Skip the 'wait' below, if it's taking too long.
+	    untested "$testname (exit status)"
+	    return 0
+	}
+	eof {
+	    fail "$testname (output)"
+	}
+    }
+    # We can't use check_exit_status, because we expect an exit status
+    # of 1.
+    expect eof
+    set status_list [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $status_list (v4klist)"
+    if { [lindex $status_list 2] != 0 } {
+	fail "$testname (exit status)"
+	return 0
+    } else {
+	if { [lindex $status_list 3] != 1 } {
+	    fail "$testname (exit status)"
+	    return 0
+	} else {
+	    pass "$testname (exit status)"
+	}
+    }
+    return 1
+}
+
+# Set up a root shell using rlogin $hostname -l root.  This is used
+# when testing the daemons that must be run as root, such as telnetd
+# or rlogind.  This sets the global variables rlogin_spawn_id and
+# rlogin_pid.  Returns 1 on success, 0 on failure.
+#
+# This procedure will only succeed if the person running the test has
+# a valid ticket for a name listed in the /.klogin file.  Naturally,
+# Kerberos must already be installed on this machine.  It's a pain,
+# but I can't think of a better approach.
+
+if ![info exists can_get_root] { set can_get_root yes }
+
+proc setup_root_shell { testname } {
+    global BINSH
+    global ROOT_PROMPT
+    global KEY
+    global RLOGIN
+    global RLOGIN_FLAGS
+    global hostname
+    global rlogin_spawn_id
+    global rlogin_pid
+    global tmppwd
+    global env
+    global krb5_init_vars
+    global can_get_root
+
+    global timeout
+
+    if [string match $can_get_root no] {
+	note "$testname test requires ability to log in as root"
+	unsupported $testname
+	return 0
+    }
+
+    # Make sure we are using the original values of the environment
+    # variables.  This means that the caller must call
+    # setup_kerberos_env after calling this procedure.
+
+    # XXX fixme to deal with envstack
+    restore_kerberos_env
+
+    setup_runtime_env
+
+    set me [exec whoami]
+    if [string match root $me] {
+	return [setup_root_shell_noremote $testname]
+    }
+
+    if ![get_hostname] {
+	set can_get_root no
+	return 0
+    }
+
+    # If you have not installed Kerberos on your system, and you want
+    # to run these tests, you can do it if you are willing to put your
+    # root password in this file (this is not a very good idea, but
+    # it's safe enough if you disconnect from the network and remember
+    # to remove the password later).  Change the rlogin in the next
+    # line to be /usr/ucb/rlogin (or whatever is appropriate for your
+    # system).  Then change the lines after "word:" a few lines
+    # farther down to be
+    #    send "rootpassword\r"
+    #    exp_continue
+
+    eval spawn $RLOGIN $hostname -l root $RLOGIN_FLAGS
+    set rlogin_spawn_id $spawn_id
+    set rlogin_pid [exp_pid]
+    set old_timeout $timeout
+    set timeout 300
+    set got_refused 0
+
+    expect {
+	-re {connect to address [0-9a-fA-F.:]*: Connection refused} {
+	    note $expect_out(buffer)
+	    set got_refused 1
+	    exp_continue
+	}
+	-re "word:|erberos rlogin failed|ection refused|ection reset by peer|not authorized" {
+	    note "$testname test requires ability to rlogin as root"
+	    unsupported "$testname"
+	    set timeout $old_timeout
+	    stop_root_shell
+	    set can_get_root no
+	    return 0
+	}
+	"Cannot assign requested address" {
+	    note "$testname: rlogin as root 'cannot assign requested address'"
+	    unsupported "$testname"
+	    set timeout $old_timeout
+	    stop_root_shell
+	    set can_get_root no
+	    return 0
+	}
+	-re "usage: rlogin|illegal option -- x|invalid option -- x" {
+	    note "$testname: rlogin doesn't like command-line flags"
+	    unsupported "$testname"
+	    set timeout $old_timeout
+	    stop_root_shell
+	    set can_get_root no
+	    return 0
+	}
+	-re "$ROOT_PROMPT" { }
+	timeout {
+	    perror "timeout from rlogin $hostname -l root"
+	    perror "If you have an unusual root prompt,"
+	    perror "try running with ROOT_PROMPT=\"regexp\""
+	    set timeout $old_timeout
+	    stop_root_shell
+	    set can_get_root no
+	    return 0
+	}
+	eof {
+	    if {$got_refused} {
+		# reported some errors, continued, and failed
+		note "$testname test requires ability to log in as root"
+		unsupported $testname
+	    } else {
+		# unknown problem?
+#		perror "eof from rlogin $hostname -l root"
+		note "eof (and unrecognized messages?) from rlogin $hostname -l root"
+		note "$testname test requires ability to log in as root"
+		unsupported $testname
+	    }
+	    stop_root_shell
+	    set timeout $old_timeout
+	    catch "expect_after"
+	    set can_get_root no
+	    return 0
+	}
+    }
+
+    expect_after {
+	timeout {
+	    perror "timeout from rlogin $hostname -l root"
+	    stop_root_shell
+	    set timeout $old_timeout
+	    catch "expect_after"
+	    set can_get_root no
+	    return 0
+	}
+	eof {
+	    perror "eof from rlogin $hostname -l root"
+	    stop_root_shell
+	    set timeout $old_timeout
+	    catch "expect_after"
+	    set can_get_root no
+	    return 0
+	}
+    }
+
+    # Make sure the root shell is using /bin/sh.
+    send "$BINSH\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+
+    # Set up a shell variable tmppwd.  The callers use this to keep
+    # command line lengths down.  The command line length is important
+    # because we are feeding input to a shell via a pty.  On some
+    # systems a pty will only accept 255 characters.
+    send "tmppwd=$tmppwd\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+
+    # Set up our krb5.conf
+    send "KRB5_CONFIG=$tmppwd/krb5.server.conf\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+    send "export KRB5_CONFIG\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+
+    # For all of our runtime environment variables - send them over...
+    foreach i $krb5_init_vars {
+	regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
+	send "$evar=$env($evar)\r"
+	expect {
+		-re "$ROOT_PROMPT" { }
+        }
+
+        send "export $evar\r"
+        expect {
+		-re "$ROOT_PROMPT" { }
+        }
+    }
+
+    # Move over to the right directory.
+    set dir [pwd]
+    send "cd $dir\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+	"$dir:" {
+	    perror "root shell can not cd to $dir"
+	    set timeout $old_timeout
+	    stop_root_shell
+	    set can_get_root no
+	    return 0
+	}
+    }
+
+    expect_after
+    set timeout $old_timeout
+
+    return 1
+}
+
+proc setup_root_shell_noremote { testname } {
+    global BINSH
+    global ROOT_PROMPT
+    global KEY
+    global hostname
+    global rlogin_spawn_id
+    global rlogin_pid
+    global tmppwd
+    global env
+    global krb5_init_vars
+
+    eval spawn $BINSH
+    set rlogin_spawn_id $spawn_id
+    set rlogin_pid [exp_pid]
+
+    expect_after {
+	timeout {
+	    perror "timeout from root shell"
+	    stop_root_shell
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    perror "eof from root shell"
+	    stop_root_shell
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+
+    # Set up a shell variable tmppwd.  The callers use this to keep
+    # command line lengths down.  The command line length is important
+    # because we are feeding input to a shell via a pty.  On some
+    # systems a pty will only accept 255 characters.
+    send "tmppwd=$tmppwd\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+
+    # Set up our krb5.conf
+    send "KRB5_CONFIG=$tmppwd/krb5.server.conf\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+    send "export KRB5_CONFIG\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+    }
+
+    # For all of our runtime environment variables - send them over...
+    foreach i $krb5_init_vars {
+	regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
+	send "$evar=$env($evar)\r"
+	expect {
+		-re "$ROOT_PROMPT" { }
+        }
+
+        send "export $evar\r"
+        expect {
+		-re "$ROOT_PROMPT" { }
+        }
+    }
+
+    # Move over to the right directory.
+    set dir [pwd]
+    send "cd $dir\r"
+    expect {
+	-re "$ROOT_PROMPT" { }
+	"$dir:" {
+	    perror "root shell can not cd to $dir"
+	    stop_root_shell
+	    return 0
+	}
+    }
+
+    expect_after
+
+    return 1
+}
+
+# Kill off a root shell started by setup_root_shell.
+
+proc stop_root_shell { } {
+    global rlogin_spawn_id
+    global rlogin_pid
+
+    catch "close -i $rlogin_spawn_id"
+    catch "exec kill $rlogin_pid"
+    sleep 1
+    catch "exec kill -9 $rlogin_pid"
+    catch "wait -i $rlogin_spawn_id"
+}
+
+# Check the date.  The string will be the output of date on this
+# system, and we must make sure that it is in the same timezone as the
+# output of date run a second time.  The first date will be run on an
+# rlogin or some such connection to the local system.  This is to test
+# to make sure that the TZ environment variable is handled correctly.
+# Returns 1 on sucess, 0 on failure.
+
+proc check_date { date } {
+    catch "exec date" ndate
+    set atz ""
+    set ntz ""
+    scan $date "%s %s %d %d:%d:%d %s %d" adow amon adom ahr amn asc atz ayr
+    scan $ndate "%s %s %d %d:%d:%d %s %d" ndow nmon ndom nhr nmn nsc ntz nyr
+    if { $atz != $ntz } {
+	verbose -log "date check failed: $atz != $ntz"
+	return 0
+    }
+    return 1
+}
+
+proc touch { file } {
+    set f [open $file "a"]
+    puts $f ""
+    close $f
+}
+
+# Implement this in tcl someday?
+proc tail1 { file } {
+    exec tail -1 $file
+}
+
+# setup_wrapper
+# Sets up a wraper script to set the runtime shared library environment 
+# variables and then executes a specific command. This is used to allow
+# a "rsh klist" or telnetd to execute login.krb5. 
+proc setup_wrapper { file command } {
+    global BINSH
+    global env
+    global krb5_init_vars
+
+    # We will start with a BINSH script
+    catch "exec rm -f $file"
+
+    set f [open $file "w" 0777]
+    puts $f "#!$BINSH"
+    puts $f "KRB5_CONFIG=$env(KRB5_CONFIG)"
+    puts $f "export KRB5_CONFIG"
+    foreach i $krb5_init_vars {
+	regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
+	puts $f "$evar=$env($evar)"
+	puts $f "export $evar"
+    }
+    puts $f "exec $command"
+    close $f
+    
+    return 1
+}
+
+proc krb_exit { } {
+    stop_kerberos_daemons
+}
+
+# helpful sometimes for debugging the test suite
+proc spawn_xterm { } {
+    global env
+    foreach i {KDB5_UTIL KRB5KDC KADMIND KADMIN KADMIN_LOCAL KINIT KTUTIL KLIST RLOGIN RLOGIND FTP FTPD KPASSWD REALMNAME GSSCLIENT} {
+	global $i
+	if [info exists $i] { set env($i) [set $i] }
+    }
+    exec "xterm"
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-root/rlogin.exp b/krb5-1-6/src/tests/dejagnu/krb-root/rlogin.exp
new file mode 100644
index 000000000..bc4056467
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-root/rlogin.exp
@@ -0,0 +1,320 @@
+# Kerberos rlogin test.
+# This is a DejaGnu test script.
+# This script tests Kerberos rlogin.
+# Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+
+# Find the programs we need.  We use the binaries from the build tree
+# if they exist.  If they do not, then they must be in PATH.  We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists KRLOGIN] {
+    set KRLOGIN [findfile $objdir/../../appl/bsd/rlogin]
+}
+
+if ![info exists KRLOGIND] {
+    set KRLOGIND [findfile $objdir/../../appl/bsd/klogind]
+}
+
+if ![info exists LOGINKRB5] {
+    set LOGINKRB5 [findfile $objdir/../../appl/bsd/login.krb5]
+}
+
+# Start up a root shell.
+if ![setup_root_shell rlogin] {
+    return
+}
+
+# Make sure .k5login is reasonable.
+if ![check_k5login rlogin] {
+    stop_root_shell
+    return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_env] \
+    || ![setup_kerberos_db 0]} {
+    stop_root_shell
+    return
+}
+
+# A procedure to start up the rlogin daemon.
+
+proc start_rlogin_daemon { option } {
+    global REALMNAME
+    global KRLOGIND
+    global LOGINKRB5
+    global ROOT_PROMPT
+    global tmppwd
+    global hostname
+    global rlogin_spawn_id
+    global krlogind_pid
+    global portbase
+
+    # The -p argument tells it to accept a single connection, so we
+    # don't need to use inetd.  The 3543 is the port to listen at.
+    # Note that tmppwd here is a shell variable, which is set in
+    # setup_root_shell, not a TCL variable.  The sh -c is to workaround
+    # the broken controlling tty handling in hpux, and shouldn't hurt
+    # anything else.
+    send -i $rlogin_spawn_id "sh -c \"$KRLOGIND -k -c -D [expr 8 + $portbase] -S \$tmppwd/srvtab -M $REALMNAME -L $LOGINKRB5 $option\" &\r"
+    expect {
+	-i $rlogin_spawn_id 
+	-re "$ROOT_PROMPT" { }
+	timeout {
+	    send_error "ERROR: timeout from rlogin $hostname -l root\n"
+	    return
+	}
+	eof {
+	    send_error "ERROR: eof from rlogin $hostname -l root\n"
+	    return
+	}
+    }
+    send -i $rlogin_spawn_id "echo \$!\r"
+    expect {
+	-i $rlogin_spawn_id
+	-re "\[0-9\]+" {
+	    set krlogind_pid $expect_out(0,string)
+	    verbose "krlogind process ID is $krlogind_pid"
+	}
+	timeout {
+	    send_error "ERROR: timeout from rlogin $hostname -l root\n"
+	    return
+	}
+	eof {
+	    send_error "ERROR: eof from rlogin $hostname -l root\n"
+	    return
+	}
+    }
+    expect {
+	-i $rlogin_spawn_id
+	-re "$ROOT_PROMPT" { }
+	timeout {
+	    send_error "ERROR: timeout from rlogin $hostname -l root\n"
+	    return
+	}
+	eof {
+	    send_error "ERROR: eof from rlogin $hostname -l root\n"
+	    return
+	}
+    }
+
+    # Give the rlogin daemon a few seconds to get set up.
+    sleep 2
+}
+
+# A procedure to stop the rlogin daemon.
+
+proc stop_rlogin_daemon { } {
+    global krlogind_pid
+
+    if [info exists krlogind_pid] {
+	catch "exec kill $krlogind_pid"
+	unset krlogind_pid
+    }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc rlogin_test { } {
+    global REALMNAME
+    global KRLOGIN
+    global BINSH
+    global SHELL_PROMPT
+    global KEY
+    global hostname
+    global hostname
+    global env
+    global portbase
+
+    # Start up the kerberos and kadmind daemons and get a srvtab and a
+    # ticket file.
+    if {![start_kerberos_daemons 0] \
+        || ![add_kerberos_key host/$hostname 0] \
+        || ![setup_srvtab 0] \
+	|| ![add_kerberos_key $env(USER) 0] \
+	|| ![kinit $env(USER) $env(USER)$KEY 0]} {
+	return
+    }
+
+    # Start up the rlogin daemon.
+    start_rlogin_daemon -k
+
+    # Make an rlogin connection.
+    spawn $KRLOGIN $hostname -k $REALMNAME -D [expr 8 + $portbase]
+
+    expect_after {
+	timeout {
+	    fail "$testname (timeout)"
+	    catch "expect_after"
+	    return
+	}
+	"onnection closed." {
+	    fail "$testname (connection closed)"
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    set testname "rlogin"
+    expect {
+	-re "$SHELL_PROMPT" {
+	    pass $testname
+	}
+    }
+
+    # Switch to /bin/sh to try to avoid confusion from the shell
+    # prompt.
+    set testname "shell"
+    send "$BINSH\r"
+    expect -re "$SHELL_PROMPT"
+
+    set testname "date"
+    send "date\r"
+    expect "date"
+    expect {
+	-re "\[A-Za-z0-9 :\]+\[\r\n\]+" {
+	    if [check_date $expect_out(0,string)] {
+		pass "date"
+	    } else {
+		fail "date"
+	    }
+	}
+    }
+    expect -re "$SHELL_PROMPT"
+
+    set testname "exit"
+    send "exit\r"
+    expect -re "$SHELL_PROMPT"
+    send "exit\r"
+    expect {
+	"onnection closed." {
+	    pass $testname
+	}
+    }
+    # This last expect seems useless, but without it the rlogin process
+    # sometimes hangs on HP-UX, in a tcsetattr call with TCSADRAIN.
+    expect {
+        "\r" { }
+    }
+
+    expect_after
+
+    if [check_exit_status "exit status"] {
+	pass "exit status"
+    }
+
+    # The rlogin daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_rlogin_daemon
+
+    # Try an encrypted connection.
+    start_rlogin_daemon -e
+    spawn $KRLOGIN $hostname -x -k $REALMNAME -D [expr 8 + $portbase]
+
+    expect_after {
+	timeout {
+	    fail "$testname (timeout)"
+	    catch "expect_after"
+	    return
+	}
+	"onnection closed" {
+	    fail "$testname (connection closed)"
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    set testname "encrypted rlogin"
+    expect -re "encrypting .* transmissions"
+    expect {
+	-re "$SHELL_PROMPT" {
+	    pass $testname
+	}
+    }
+
+    # Switch to /bin/sh to try to avoid confusion from the shell
+    # prompt.
+    set testname "shell"
+    send "$BINSH\r"
+    expect -re "$SHELL_PROMPT"
+
+    # Make sure the encryption is not destroying the text.
+    set testname "echo"
+    send "echo hello\r"
+    expect "echo hello"
+    expect "hello"
+    expect {
+	-re "$SHELL_PROMPT" {
+	    pass $testname
+	}
+    }
+
+    # Send some characters which might cause an interrupt, and then
+    # make sure we can still talk to the shell.
+    set testname "interrupt characters"
+    send "\003\177\034\r"
+    expect -re "$SHELL_PROMPT"
+    send "echo hello\r"
+    expect "echo hello"
+    expect "hello"
+    expect {
+	-re "$SHELL_PROMPT" {
+	    pass $testname
+	}
+    }
+
+    set testname "~."
+    send "~."
+    expect {
+	"Closed connection.\r" {
+	    pass $testname
+	}
+	"onnection closed" {
+	    pass $testname
+	}
+    }
+
+    expect_after
+
+    if [check_exit_status "exit status"] {
+	pass "exit status"
+    }
+
+    # The rlogin daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_rlogin_daemon
+}
+
+# Run the test.  Logging in sometimes takes a while, so increase the
+# timeout.
+set oldtimeout $timeout
+set timeout 60
+set status [catch rlogin_test msg]
+set timeout $oldtimeout
+
+# Shut down the kerberos daemons, the rlogin daemon, and the root
+# process.
+stop_kerberos_daemons
+
+stop_rlogin_daemon
+
+stop_root_shell
+
+if { $status != 0 } {
+    send_error "ERROR: error in rlogin.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-root/telnet.exp b/krb5-1-6/src/tests/dejagnu/krb-root/telnet.exp
new file mode 100644
index 000000000..c283d6150
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-root/telnet.exp
@@ -0,0 +1,449 @@
+# Kerberos telnet test.
+# This is a DejaGnu test script.
+# This script tests Kerberos telnet.
+# Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+
+# Find the programs we need.  We use the binaries from the build tree
+# if they exist.  If they do not, then they must be in PATH.  We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists TELNET] {
+    set TELNET [findfile $objdir/../../appl/telnet/telnet/telnet]
+}
+
+if ![info exists TELNETD] {
+    set TELNETD [findfile $objdir/../../appl/telnet/telnetd/telnetd]
+}
+
+if ![info exists LOGINKRB5] {
+    set LOGINKRB5 [findfile $objdir/../../appl/bsd/login.krb5]
+}
+
+if ![regexp des- $supported_enctypes] {
+    # Telnet needs a DES enctype.
+    verbose "Skipping telnet tests for lack of DES support."
+    return
+}
+
+# Remove old wrapper script
+    catch "exec rm -f $tmppwd/login.wrap"
+
+# Start up a root shell.
+if ![setup_root_shell telnet] {
+    return
+}
+
+# Make sure .k5login is reasonable.
+if ![check_k5login rlogin] {
+    stop_root_shell
+    return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_env] \
+    || ![setup_kerberos_db 0]} {
+    stop_root_shell
+    return
+}
+
+# A procedure to start up the telnet daemon.
+
+proc start_telnet_daemon { args } {
+    global REALMNAME
+    global TELNETD
+    global LOGINKRB5
+    global ROOT_PROMPT
+    global tmppwd
+    global hostname
+    global rlogin_spawn_id
+    global telnetd_pid
+    global portbase
+
+    # Setup the shared library wrapper for login.krb5
+    if ![file exists $tmppwd/login.wrap] {
+	    setup_wrapper $tmppwd/login.wrap "$LOGINKRB5 $*"
+    }
+
+    # The -debug argument tells it to accept a single connection, so
+    # we don't need to use inetd.  The portbase+8 is the port to listen at.
+    # Note that tmppwd here is a shell variable, which is set in
+    # setup_root_shell, not a TCL variable.
+    send -i $rlogin_spawn_id "sh -c \"$TELNETD $args -debug -t \$tmppwd/srvtab -R $REALMNAME -L $tmppwd/login.wrap -X KERBEROS_V4 [expr 8 + $portbase]\" &\r"
+    expect {
+	-i $rlogin_spawn_id 
+	-re "$ROOT_PROMPT" { }
+	timeout {
+	    send_error "ERROR: timeout from rlogin $hostname -l root\n"
+	    return
+	}
+	eof {
+	    send_error "ERROR: eof from rlogin $hostname -l root\n"
+	    return
+	}
+    }
+    send -i $rlogin_spawn_id "echo \$!\r"
+    expect {
+	-i $rlogin_spawn_id
+	-re "\[0-9\]+" {
+	    set telnetd_pid $expect_out(0,string)
+	    verbose "telnetd process ID is $telnetd_pid"
+	}
+	timeout {
+	    send_error "ERROR: timeout from rlogin $hostname -l root\n"
+	    return
+	}
+	eof {
+	    send_error "ERROR: eof from rlogin $hostname -l root\n"
+	    return
+	}
+    }
+    expect {
+	-i $rlogin_spawn_id
+	-re "$ROOT_PROMPT" { }
+	timeout {
+	    send_error "ERROR: timeout from rlogin $hostname -l root\n"
+	    return
+	}
+	eof {
+	    send_error "ERROR: eof from rlogin $hostname -l root\n"
+	    return
+	}
+    }
+
+    # Give the telnet daemon a few seconds to get set up.
+    sleep 2
+}
+
+# A procedure to stop the telnet daemon.
+
+proc stop_telnet_daemon { } {
+    global telnetd_pid
+
+    if [info exists telnetd_pid] {
+	catch "exec kill $telnetd_pid"
+	unset telnetd_pid
+    }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc telnet_test { } {
+    global REALMNAME
+    global TELNET
+    global BINSH
+    global SHELL_PROMPT
+    global KEY
+    global hostname
+    global localhostname
+    global env
+    global portbase
+
+    # Start up the kerberos and kadmind daemons and get a srvtab and a
+    # ticket file.
+    if {![start_kerberos_daemons 0] \
+        || ![add_kerberos_key host/$hostname 0] \
+        || ![setup_srvtab 0] \
+	|| ![add_kerberos_key $env(USER) 0] \
+	|| ![kinit $env(USER) $env(USER)$KEY 0]} {
+	return
+    }
+
+    # Start up the telnet daemon.
+    start_telnet_daemon
+
+    # Start up our telnet connection.  We first try it without
+    # authentication, so the daemon should prompt for a login.
+    spawn $TELNET -- $hostname -[expr 8 + $portbase]
+    set telnet_pid [exp_pid]
+
+    expect_after {
+	timeout {
+	    fail "$testname (timeout)"
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    set testname "simple telnet"
+    expect {
+	"ogin: " {
+	    pass $testname
+	}
+    }
+
+    # Move back to telnet command mode and make sure it seems
+    # reasonable.
+    set testname "telnet command mode"
+    send "\035"
+    expect {
+	"telnet> " {
+	    pass $testname
+	}
+    }
+
+    set testname "telnet status"
+    send "status\r"
+    # use -nocase because telnet may output the fqdn in upper-case;
+    # however, -nocase requires the whole pattern to be in lower case
+    expect {
+	-nocase -re "connected to $localhostname.*operating in single character mode.*catching signals locally.*remote character echo.*flow control.*escape character is '.\]'" {
+	    pass $testname
+	}
+    }
+
+    set testname "back to command mode"
+
+    # For some reason, the telnet client doesn't necessarily reset the
+    # terminal mode back to raw after exiting command mode.
+    # Kick it somewhat by sending a CR.
+    send "\r"
+    expect "ogin: "
+
+    send "\035"
+    expect {
+	"telnet> " {
+	    pass $testname
+	}
+    }
+
+    set testname "quit"
+    send "quit\r"
+    expect {
+	"Connection closed.\r" {
+	    pass $testname
+	}
+    }
+
+    expect_after
+
+# on hpux 10.x, the child telnet will hang in an ioctl().  This will
+# wait a while for an EOF, and kill the process if it doesn't exit by
+# itself.  The hang doesn't happen when telnet is run at the shell.
+
+    expect {
+	eof { }
+	timeout {
+	    stop_telnet_daemon
+	}
+    }
+
+    if ![check_exit_status "exit status"] {
+	return
+    }
+
+    pass "exit status"
+
+    # The telnet daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_telnet_daemon
+
+    # Try an authenticated connection.
+    start_telnet_daemon
+    spawn $TELNET -a -k $REALMNAME -- $hostname -[expr 8 + $portbase]
+
+    expect_after {
+	timeout {
+	    fail "$testname (timeout)"
+	    catch "expect_after"
+	    return
+	}
+	"Connection closed by foreign host.\r" {
+	    fail "$testname (connection closed)"
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    set testname "authenticated telnet"
+    expect "Kerberos V5 accepts you"
+    expect {
+	-re "$SHELL_PROMPT" {
+	    pass $testname
+	}
+    }
+
+    # Switch to /bin/sh to try to avoid confusion from the shell
+    # prompt.
+    set testname "shell"
+    send "$BINSH\r"
+    expect -re "$SHELL_PROMPT"
+
+    set testname "date"
+    send "date\r"
+    expect "date"
+    expect {
+	-re "\[A-Za-z0-9 :\]+\[\r\n\]+" {
+	    if [check_date $expect_out(0,string)] {
+		pass "date"
+	    } else {
+		fail "date"
+	    }
+	}
+    }
+    expect -re "$SHELL_PROMPT"
+
+    set testname "exit"
+    send "exit\r"
+    expect -re "$SHELL_PROMPT"
+    send "exit\r"
+    expect {
+	"Connection closed by foreign host.\r" {
+	    pass $testname
+	}
+    }
+
+    expect_after
+    catch "expect eof"
+
+    # We can't use check_exit_status, because we expect an exit status
+    # of 1.
+    set status_list [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $status_list (klist)"
+    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } {
+	send_log "exit status: $status_list\n"
+	verbose "exit status: $status_list"
+	fail "exit status"
+    } else {
+	pass "exit status"
+    }
+
+    # The telnet daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_telnet_daemon
+
+    # Try an authenticated encrypted connection.
+    start_telnet_daemon
+    spawn $TELNET -a -x -k $REALMNAME -- $hostname -[expr 8 + $portbase]
+
+    expect_after {
+	timeout {
+	    fail $testname
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail $testname
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    set testname "encrypted telnet"
+    expect "Kerberos V5 accepts you"
+    expect {
+	-re "$SHELL_PROMPT" {
+	    pass $testname
+	}
+    }
+
+    # Make sure the encryption is not destroying the text.
+    set testname "echo"
+    send "echo hello\r"
+    expect "echo hello"
+    expect "hello"
+    expect {
+	-re "$SHELL_PROMPT" {
+	    pass $testname
+	}
+    }
+
+    # Move back to telnet command mode and check the encryption status.
+    set testname "encryption status"
+    send "\035"
+    expect "telnet> "
+    send "status\r"
+    expect {
+	-re "Currently encrypting output with DES_CFB64.*Currently decrypting input with DES_CFB64" {
+	    pass $testname
+	}
+    }
+
+    set testname "exit status"
+    send "exit\r"
+    expect "Connection closed by foreign host.\r"
+
+    expect_after
+    catch "expect eof"
+
+    # We can't use check_exit_status, because we expect an exit status
+    # of 1.
+    set status_list [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $status_list (klist)"
+    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } {
+	send_log "exit status: $status_list\n"
+	verbose "exit status: $status_list"
+	fail "exit status"
+    } else {
+	pass "exit status"
+    }
+
+    # The telnet daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_telnet_daemon
+
+    set testname "reject unencrypted telnet"
+    # Check rejection of unencrypted client when encryption is required
+    start_telnet_daemon -e
+
+    # unencrypted, unauthenticated
+    spawn $TELNET -- $hostname -[expr 8 + $portbase]
+    expect_after {
+	timeout {
+	    fail $testname
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail $testname
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    expect {
+	-re "Unencrypted connection refused.*\n" {
+	    pass $testname
+	}
+    }
+    catch "expect_after"
+    catch "expect eof"
+    catch wait
+
+    # The telnet daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_telnet_daemon
+}
+
+# Run the test.  Logging in sometimes takes a while, so increase the
+# timeout.
+set oldtimeout $timeout
+set timeout 60
+set status [catch telnet_test msg]
+set timeout $oldtimeout
+
+# Shut down the kerberos daemons, the telnet daemon, and the rlogin
+# process.
+stop_kerberos_daemons
+
+stop_telnet_daemon
+
+stop_root_shell
+
+if { $status != 0 } {
+    send_error "ERROR: error in telnet.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/gssapi.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/gssapi.exp
new file mode 100644
index 000000000..793c0db19
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/gssapi.exp
@@ -0,0 +1,328 @@
+# Test for the GSS-API.
+# This is a DejaGnu test script.
+# This script tests that the GSS-API tester functions correctly.
+
+# This mostly just calls procedures in test/dejagnu/config/default.exp.
+
+if ![info exists KDESTROY] {
+    set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
+}
+
+if ![info exists GSSCLIENT] {
+    set GSSCLIENT [findfile $objdir/../../appl/gss-sample/gss-client]
+}
+
+if ![info exists GSSSERVER] {
+    set GSSSERVER [findfile $objdir/../../appl/gss-sample/gss-server]
+}
+
+# Set up the Kerberos files and environment.
+if {![get_hostname] || ![setup_kerberos_files] || ![setup_kerberos_env]} {
+    return
+}
+
+# Initialize the Kerberos database.  The argument tells
+# setup_kerberos_db that it is being called from here.
+if ![setup_kerberos_db 0] {
+    return
+}
+
+#
+# Like kinit in default.exp, but allows us to specify a different ccache.
+#
+proc our_kinit { name pass ccache } {
+    global REALMNAME
+    global KINIT
+    global spawn_id
+
+    # Use kinit to get a ticket.
+    spawn $KINIT -5 -c $ccache $name@$REALMNAME
+    expect {
+	"Password for $name@$REALMNAME:" {
+	    verbose "kinit started"
+	}
+	timeout {
+	    fail "kinit"
+	    return 0
+	}
+	eof {
+	    fail "kinit"
+	    return 0
+	}
+    }
+    send "$pass\r"
+    # This last expect seems useless, but without it the test hangs on
+    # AIX.
+    expect {
+        "\r" { }
+    }
+    expect eof
+    if ![check_exit_status kinit] {
+	return 0
+    }
+
+    return 1
+}
+
+#
+# Destroys a particular ccache.
+#
+proc our_kdestroy { ccache } {
+    global KDESTROY
+    global spawn_id
+
+    spawn $KDESTROY -c $ccache
+    if ![check_exit_status "kdestroy"] {
+	return 0
+    }
+    return 1
+}
+
+#
+# Stops the gss-server.
+#
+proc stop_gss_server { } {
+    global gss_server_pid
+    global gss_server_spawn_id
+
+    if [info exists gss_server_pid] {
+	catch "close -i $gss_server_spawn_id"
+	catch "exec kill $gss_server_pid"
+	wait -i $gss_server_spawn_id
+	unset gss_server_pid
+    }
+}
+
+#
+# Restore environment variables possibly set.
+#
+proc gss_restore_env { } {
+    global env
+    global gss_save_ccname
+    global gss_save_ktname
+
+    catch "unset env(KRB5CCNAME)"
+    if [info exists gss_save_ccname] {
+	set env(KRB5CCNAME) $gss_save_ccname
+	unset gss_save_ccname
+    }
+    catch "unset env(KRB5_KTNAME)"
+    if [info exists gss_save_ktname] {
+	set env(KRB5_KTNAME) $gss_save_ktname
+	unset gss_save_ktname
+    }
+}
+
+proc run_client {test tkfile client} {
+    global env
+    global hostname
+    global GSSCLIENT
+    global spawn_id
+    global gss_server_spawn_id
+    global REALMNAME
+    global portbase
+
+    set env(KRB5CCNAME) $tkfile
+    verbose "KRB5CCNAME=$env(KRB5CCNAME)"
+    verbose "spawning gssclient, identity=$client"
+    spawn $GSSCLIENT -port [expr 8 + $portbase] $hostname gssservice@$hostname "message from $client"
+    set got_client 0
+    set got_server 0
+    expect_after {
+	-i $spawn_id
+	timeout {
+	    if {!$got_client} {
+		verbose -log "client timeout"
+		fail $test
+		catch "expect_after"
+		return
+	    }
+	}
+	eof {
+	    if {!$got_client} {
+		verbose -log "client eof"
+		fail $test
+		catch "expect_after"
+		return
+	    }
+	}
+	-i $gss_server_spawn_id
+	timeout {
+	    if {!$got_server} {
+		verbose -log "server timeout"
+		fail $test
+		catch "expect_after"
+		return
+	    }
+	}
+	eof {
+	    if {!$got_server} {
+		verbose -log "server eof"
+		fail $test
+		catch "expect_after"
+		return
+	    }
+	}
+    }
+    expect {
+	-i $gss_server_spawn_id
+	"Accepted connection: \"$client@$REALMNAME\"" exp_continue
+	"Received message: \"message from $client\"" {
+	    set got_server 1
+	    if {!$got_client} {
+		exp_continue
+	    }
+	}
+	-i $spawn_id
+	"Signature verified" {
+	    set got_client 1
+	    if {!$got_server} {
+		exp_continue
+	    }
+	}
+    }
+    catch "expect_after"
+    if ![check_exit_status $test] {
+	# check_exit_staus already calls fail for us
+	return
+    }
+    pass $test
+}
+
+proc doit { } {
+    global REALMNAME
+    global env
+    global KLIST
+    global KDESTROY
+    global KEY
+    global GSSTEST
+    global GSSSERVER
+    global GSSCLIENT
+    global hostname
+    global tmppwd
+    global spawn_id
+    global timeout
+    global gss_server_pid
+    global gss_server_spawn_id
+    global gss_save_ccname
+    global gss_save_ktname
+    global portbase
+
+    # Start up the kerberos and kadmind daemons.
+    if ![start_kerberos_daemons 0] {
+	perror "failed to start kerberos daemons"
+    }
+
+    # Use kadmin to add a key for us.
+    if ![add_kerberos_key gsstest0 0] {
+	perror "failed to set up gsstest0 key"
+    }
+
+    # Use kadmin to add a key for us.
+    if ![add_kerberos_key gsstest1 0] {
+	perror "failed to set up gsstest1 key"
+    }
+
+    # Use kadmin to add a key for us.
+    if ![add_kerberos_key gsstest2 0] {
+	perror "failed to set up gsstest2 key"
+    }
+
+    # Use kadmin to add a key for us.
+    if ![add_kerberos_key gsstest3 0] {
+	perror "failed to set up gsstest3 key"
+    }
+
+    # Use kadmin to add a service key for us.
+    if ![add_random_key gssservice/$hostname 0] {
+	perror "failed to set up gssservice/$hostname key"
+    }
+
+    # Use kdb5_edit to create a srvtab entry for gssservice
+    if ![setup_srvtab 0 gssservice] {
+	perror "failed to set up gssservice srvtab"
+    }
+
+    catch "exec rm -f $tmppwd/gss_tk_0 $tmppwd/gss_tk_1 $tmppwd/gss_tk_2 $tmppwd/gss_tk_3"
+
+    # Use kinit to get a ticket.
+    if ![our_kinit gsstest0 gsstest0$KEY $tmppwd/gss_tk_0] {
+	perror "failed to kinit gsstest0"
+    }
+
+    # Use kinit to get a ticket.
+    if ![our_kinit gsstest1 gsstest1$KEY $tmppwd/gss_tk_1] {
+	perror "failed to kinit gsstest1"
+    }
+
+    # Use kinit to get a ticket.
+    if ![our_kinit gsstest2 gsstest2$KEY $tmppwd/gss_tk_2] {
+	perror "failed to kinit gsstest2"
+    }
+
+    # Use kinit to get a ticket.
+    if ![our_kinit gsstest3 gsstest3$KEY $tmppwd/gss_tk_3] {
+	perror "failed to kinit gsstest3"
+    }
+
+    #
+    # Save settings of KRB5CCNAME and KRB5_KTNAME
+    #
+    if [info exists env(KRB5CCNAME)] {
+	set gss_save_ccname $env(KRB5CCNAME)
+    }
+    if [info exists env(KRB5_KTNAME)] {
+	set gss_save_ktname $env(KRB5_KTNAME)
+    }
+
+    #
+    # set KRB5CCNAME and KRB5_KTNAME
+    #
+    set env(KRB5_KTNAME) FILE:$tmppwd/srvtab
+    verbose "KRB5_KTNAME=$env(KRB5_KTNAME)"
+
+    # Now start the gss-server.
+    spawn $GSSSERVER -export -logfile $tmppwd/gss-server.log -verbose -port [expr 8 + $portbase] gssservice@$hostname
+    set gss_server_pid [exp_pid]
+    set gss_server_spawn_id $spawn_id
+    sleep 2
+
+    run_client gssclient0 $tmppwd/gss_tk_0 gssclient0
+    run_client gssclient1 $tmppwd/gss_tk_1 gssclient1
+    run_client gssclient2 $tmppwd/gss_tk_2 gssclient2
+    run_client gssclient3 $tmppwd/gss_tk_3 gssclient3
+
+    stop_gss_server
+    gss_restore_env
+
+    if ![our_kdestroy $tmppwd/gss_tk_0] {
+	perror "failed kdestroy gss_tk_0" 0
+    }
+
+    if ![our_kdestroy $tmppwd/gss_tk_1] {
+	perror "failed kdestroy gss_tk_1" 0
+    }
+
+    if ![our_kdestroy $tmppwd/gss_tk_2] {
+	perror "failed kdestroy gss_tk_2" 0
+    }
+
+    if ![our_kdestroy $tmppwd/gss_tk_3] {
+	perror "failed kdestroy gss_tk_3" 0
+    }
+
+    catch "exec rm -f $tmppwd/gss_tk_0 $tmppwd/gss_tk_1 $tmppwd/gss_tk_2 $tmppwd/gss_tk_3"
+
+    return
+}
+
+set status [catch doit msg]
+
+stop_gss_server
+gss_restore_env
+stop_kerberos_daemons
+
+if { $status != 0 } {
+    perror "error in gssapi.exp" 0
+    perror $msg 0
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/gssftp.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/gssftp.exp
new file mode 100644
index 000000000..146423d1c
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/gssftp.exp
@@ -0,0 +1,457 @@
+# Kerberos ftp test.
+# This is a DejaGnu test script.
+# This script tests Kerberos ftp.
+# Originally written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+# Modified bye Ezra Peisach for GSSAPI support.
+
+# Find the programs we need.  We use the binaries from the build tree
+# if they exist.  If they do not, then they must be in PATH.  We
+# expect $objdir to be .../kerberos/build/tests/dejagnu
+
+if ![info exists FTP] {
+    set FTP [findfile $objdir/../../appl/gssftp/ftp/ftp]
+}
+
+if ![info exists FTPD] {
+    set FTPD [findfile $objdir/../../appl/gssftp/ftpd/ftpd]
+}
+
+# Make sure .klogin is reasonable.
+if ![check_k5login ftp] {
+    return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_env] \
+    || ![setup_kerberos_db 0]} {
+    return
+}
+
+# A procedure to start up the ftp daemon.
+
+proc start_ftp_daemon { } {
+    global FTPD
+    global tmppwd
+    global ftpd_spawn_id
+    global ftpd_pid
+    global portbase
+
+    # The -p argument tells it to accept a single connection, so we
+    # don't need to use inetd.  Portbase+8 is the port to listen at.
+    # We rely on KRB5_KTNAME being set to the proper keyfile as there is
+    # no way to cleanly set it with the gssapi API.
+    # The -U argument tells it to use an alternate ftpusers file (using
+    # /dev/null will allow root to login regardless of /etc/ftpusers).
+    # The -a argument requires authorization, to mitigate any
+    # vulnerability introduced by circumventing ftpusers.
+    spawn $FTPD -p [expr 8 + $portbase] -a -U /dev/null -r $tmppwd/krb5.conf
+    set ftpd_spawn_id $spawn_id
+    set ftpd_pid [exp_pid]
+
+    # Give the ftp daemon a few seconds to get set up.
+    sleep 2
+}
+
+# A procedure to stop the ftp daemon.
+
+proc stop_ftp_daemon { } {
+    global ftpd_spawn_id
+    global ftpd_pid
+
+    if [info exists ftpd_pid] {
+	catch "close -i $ftpd_spawn_id"
+	catch "exec kill $ftpd_pid"
+	catch "wait -i $ftpd_spawn_id"
+	unset ftpd_pid
+    }
+}
+
+# Create a file to use for ftp testing.
+set file [open $tmppwd/ftp-test w]
+puts $file "This file is used for ftp testing."
+close $file
+
+# Create a large file to use for ftp testing. File needs to be 
+# larger that 2^20 or 1MB for PBSZ testing.
+set file [open $tmppwd/bigftp-test w]
+puts $file "This file is used for ftp testing.\n"
+seek $file 1048576 current
+puts $file "This file is used for ftp testing."
+close $file
+
+
+# Test that a file was copied correctly.
+proc check_file { filename {bigfile 0}} {
+    if ![file exists $filename] {
+	verbose "$filename does not exist"
+	send_log "$filename does not exist\n"
+	return 0
+    }
+
+    set file [open $filename r]
+    if { [gets $file line] == -1 } {
+	verbose "$filename is empty"
+	send_log "$filename is empty\n"
+	close $file
+	return 0
+    }
+
+    if ![string match "This file is used for ftp testing." $line] {
+	verbose "$filename contains $line"
+	send_log "$filename contains $line\n"
+	close $file
+	return 0
+    }
+
+    if {$bigfile} {
+	# + 1 for the newline
+	seek $file 1048577 current
+	if { [gets $file line] == -1 } {
+	    verbose "$filename is truncated"
+	    send_log "$filename is truncated\n"
+	    close $file
+	    return 0
+	}
+
+	if ![string match "This file is used for ftp testing." $line] {
+	    verbose "$filename contains $line"
+	    send_log "$filename contains $line\n"
+	    close $file
+	    return 0
+	}
+    }
+
+    if { [gets $file line] != -1} {
+	verbose "$filename is too long ($line)"
+	send_log "$filename is too long ($line)\n"
+	close $file
+	return 0
+    }
+
+    close $file
+
+    return 1
+}
+
+#
+# Restore environment variables possibly set.
+#
+proc ftp_restore_env { } {
+    global env
+    global ftp_save_ktname
+
+    catch "unset env(KRB5_KTNAME)"
+    if [info exists ftp_save_ktname] {
+	set env(KRB5_KTNAME) $ftp_save_ktname
+	unset ftp_save_ktname
+    }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc ftp_test { } {
+    global FTP
+    global KEY
+    global REALMNAME
+    global hostname
+    global localhostname
+    global env
+    global ftpd_spawn_id
+    global ftpd_pid
+    global spawn_id
+    global tmppwd
+    global ftp_save_ktname
+    global portbase
+
+    # Start up the kerberos and kadmind daemons and get a srvtab and a
+    # ticket file.
+    if {![start_kerberos_daemons 0] \
+        || ![add_random_key ftp/$hostname 0] \
+	|| ![modify_principal ftp/$hostname -kvno 254] \
+        || ![setup_srvtab 0 ftp] \
+	|| ![xst $tmppwd/srvtab ftp/$hostname]
+	|| ![xst $tmppwd/srvtab ftp/$hostname]
+	|| ![xst $tmppwd/srvtab ftp/$hostname]
+	|| ![do_klist_kt $tmppwd/srvtab "gssftp keytab list"]
+	|| ![add_kerberos_key $env(USER) 0] \
+	|| ![kinit $env(USER) $env(USER)$KEY 0]} {
+	return
+    }
+
+    #
+    # Save settings of KRB5_KTNAME
+    #
+    if [info exists env(KRB5_KTNAME)] {
+	set ftp_save_ktname $env(KRB5_KTNAME)
+    }
+
+    #
+    # set KRB5_KTNAME
+    #
+    set env(KRB5_KTNAME) FILE:$tmppwd/srvtab
+    verbose "KRB5_KTNAME=$env(KRB5_KTNAME)"
+
+    # Start the ftp daemon.
+    start_ftp_daemon
+
+    # Make an ftp client connection to it.
+    spawn $FTP -d -v $hostname [expr 8 + $portbase]
+
+    expect_after {
+	"GSSAPI authentication failed" {
+	    fail "$testname (auth failed)"
+	    catch "expect_after"
+	    return
+	}
+	-re "--->.*" { exp_continue }
+	-re "encoding \[0-9\]* bytes MIC \[a-zA-Z/+\]*" { exp_continue }
+	-re "sealed \[A-Z()\]*" { exp_continue }
+	-re "secure_command\[A-Z()\]*" { exp_continue }
+	timeout {
+	    fail "$testname (timeout)"
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    set testname "ftp connection"
+    expect -nocase "connected to $hostname"
+    expect -nocase -re "$localhostname.*ftp server .version \[0-9.\]*. ready."
+    expect -re "Using authentication type GSSAPI; ADAT must follow"
+    expect "GSSAPI accepted as authentication type"
+    expect {
+	"GSSAPI authentication succeeded" { pass "ftp authentication" }
+	eof	{ fail "ftp authentication" ; catch "expect_after" ; return }
+    }
+    expect -nocase "name ($hostname:$env(USER)): "
+    send "$env(USER)\r"
+    expect "GSSAPI user $env(USER)@$REALMNAME is authorized as $env(USER)"
+    expect "Remote system type is UNIX."
+    expect "Using binary mode to transfer files."
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "binary"
+    send "binary\r"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "status"
+    send "status\r"
+    expect -nocase "connected to $hostname."
+    expect "Authentication type: GSSAPI"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "ls"
+    send "ls $tmppwd/ftp-test\r"
+    expect -re "Opening ASCII mode data connection for .*ls."
+    expect -re ".* $tmppwd/ftp-test"
+    expect "ftp> " {
+	pass $testname
+    } 
+
+    set testname "nlist"
+    send "nlist $tmppwd/ftp-test\r"
+    expect -re "Opening ASCII mode data connection for file list."
+    expect -re "$tmppwd/ftp-test"
+    expect -re ".* Transfer complete."
+    expect "ftp> " {
+	pass $testname
+    } 
+
+    set testname "ls missing"
+    send "ls $tmppwd/ftp-testmiss\r"
+    expect -re "Opening ASCII mode data connection for .*ls."
+    expect {
+	-re "$tmppwd/ftp-testmiss not found" {}
+	-re "$tmppwd/ftp-testmiss: No such file or directory"
+    }
+    expect "ftp> " {
+	pass $testname
+    } 
+
+
+    set testname "get"
+    catch "exec rm -f $tmppwd/copy"
+    send "get $tmppwd/ftp-test $tmppwd/copy\r"
+    expect "Opening BINARY mode data connection for $tmppwd/ftp-test"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "put"
+    catch "exec rm -f $tmppwd/copy"
+    send "put $tmppwd/ftp-test $tmppwd/copy\r"
+    expect "Opening BINARY mode data connection for $tmppwd/copy"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes sent in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "cd"
+    send "cd $tmppwd\r"
+    expect "CWD command successful."
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "lcd"
+    send "lcd $tmppwd\r"
+    expect "Local directory now $tmppwd"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "local get"
+    catch "exec rm -f $tmppwd/copy"
+    send "get ftp-test copy\r"
+    expect "Opening BINARY mode data connection for ftp-test"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "big local get"
+    catch "exec rm -f $tmppwd/copy"
+    send "get bigftp-test copy\r"
+    expect "Opening BINARY mode data connection for bigftp-test"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy 1] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "start encryption"
+    send "private\r"
+    expect "Data channel protection level set to private"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "status"
+    send "status\r"
+    expect "Protection Level: private"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "encrypted get"
+    catch "exec rm -f $tmppwd/copy"
+    send "get ftp-test copy\r"
+    expect "Opening BINARY mode data connection for ftp-test"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "big encrypted get"
+    catch "exec rm -f $tmppwd/copy"
+    send "get bigftp-test copy\r"
+    expect "Opening BINARY mode data connection for bigftp-test"
+    expect {
+	-timeout 300
+	"Transfer complete" {}
+	-re "Length .* of PROT buffer > PBSZ" {
+	    fail "$testname (PBSZ)"
+	    return 0
+	}
+    }
+    expect -re "\[0-9\]+ bytes received in \[0-9.e+-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy 1] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+    
+    set testname "close"
+    send "close\r"
+    expect "Goodbye."
+    expect "ftp> "
+    set status_list [wait -i $ftpd_spawn_id]
+    verbose "wait -i $ftpd_spawn_id returned $status_list ($testname)"
+    catch "close -i $ftpd_spawn_id"
+    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
+	send_log "exit status: $status_list\n"
+	verbose "exit status: $status_list"
+	fail $testname
+    } else {
+	pass $testname
+	unset ftpd_pid
+    }
+
+    set testname "quit"
+    send "quit\r"
+    expect_after
+    expect eof
+    if [check_exit_status $testname] {
+	pass $testname
+    }
+}
+
+# The ftp client will look in $HOME/.netrc for the user name to use.
+# To avoid confusing the testsuite, point $HOME at a directory where
+# we know there is no .netrc file.
+if [info exists env(HOME)] {
+    set home $env(HOME)
+} elseif [info exists home] {
+    unset home
+}
+set env(HOME) $tmppwd
+
+# Run the test.  Logging in sometimes takes a while, so increase the
+# timeout.
+set oldtimeout $timeout
+set timeout 60
+set status [catch ftp_test msg]
+set timeout $oldtimeout
+
+# Shut down the kerberos daemons and the ftp daemon.
+stop_kerberos_daemons
+
+stop_ftp_daemon
+
+ftp_restore_env
+
+# Reset $HOME, for safety in case we are going to run more tests.
+if [info exists home] {
+    set env(HOME) $home
+} else {
+    unset env(HOME)
+}
+
+if { $status != 0 } {
+    perror "error in gssftp.exp: $msg"
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/kadmin.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/kadmin.exp
new file mode 100644
index 000000000..e3e39168d
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/kadmin.exp
@@ -0,0 +1,1075 @@
+# Kerberos kadmin test.
+# This is a DejaGnu test script.
+# This script tests Kerberos kadmin5 using kadmin.local as verification.
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_env] \
+    || ![setup_kerberos_db 0]} {
+    return
+}
+
+# find kpasswd
+if ![info exists KPASSWD] {
+    set KPASSWD [findfile $objdir/../../clients/kpasswd/kpasswd]
+}
+
+# find kdestroy
+if ![info exists KDESTROY] {
+    set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
+}
+
+#++
+# kadmin_add	- Test add new v5 principal function of kadmin.
+#
+# Adds principal $pname with password $password.  Returns 1 on success.
+#--
+proc kadmin_add { pname password } {
+    global REALMNAME
+    global KADMIN
+    global KADMIN_LOCAL
+    global KEY
+    global spawn_id
+    global tmppwd
+
+    set good 0
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin add $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin add $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin add $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*:" {
+	send "adminpass$KEY\r"
+    }
+    expect "Enter password for principal \"$pname@$REALMNAME\":" { send "$password\r" }
+    expect "Re-enter password for principal \"$pname@$REALMNAME\":" { send "$password\r" }
+    expect "Principal \"$pname@$REALMNAME\" created." { set good 1 }
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin add)"
+    catch "close -i $spawn_id"
+    if { $good == 1 } {
+	#
+	# use kadmin.local to verify that a principal was created and that its
+	# salt types are 0 (normal).
+	#
+	spawn $KADMIN_LOCAL -r $REALMNAME
+	expect_after {
+	    -i $spawn_id
+	    timeout {
+		fail "kadmin add $pname"
+		catch "expect_after"
+		return 0
+	    }
+	    eof {
+		fail "kadmin add $pname"
+		catch "expect_after"
+		return 0
+	    }
+	}
+	set good 0
+	expect "kadmin.local: " { send "getprinc $pname\r" }
+	expect "Principal: $pname@$REALMNAME" { set good 1 }
+	expect "Expiration date:" { verbose "got expiration date" }
+	expect "Last password change:" { verbose "got last pwchange" }
+	expect "Password expiration date:" { verbose "got pwexpire date" }
+	expect "Maximum ticket life:" { verbose "got max life" }
+	expect "Maximum renewable life:" { verbose "got max rlife" }
+	expect "Last modified:" { verbose "got last modified" }
+	expect "Last successful authentication:" { verbose "last succ auth" }
+	expect "Last failed authentication:" { verbose "last pw failed" }
+	expect "Failed password attempts:" { verbose "num failed attempts" }
+	expect "Number of keys:" { verbose "num keys"} 
+	expect {
+		"Key: " { verbose "Key listed" 
+			exp_continue
+		}
+		"Attributes:" { verbose "attributes" }
+	}
+	expect "kadmin.local: " { send "q\r" }
+
+	expect_after
+	expect eof
+	set k_stat [wait -i $spawn_id]
+	verbose "wait -i $spawn_id returned $k_stat (kadmin.local show)"
+	catch "close -i $spawn_id"
+	if { $good == 1 } {
+	    pass "kadmin add $pname"
+	    return 1
+	}
+	else {
+	    fail "kadmin add $pname"
+	    return 0
+	}
+    }
+    else {
+	fail "kadmin add $pname"
+	return 0
+    }
+}
+
+#++
+# kadmin_add_rnd	- Test add new v5 principal with random key function.
+#
+# Adds principal $pname with random key.  Returns 1 on success.
+#--
+proc kadmin_add_rnd { pname { flags "" } } {
+    global REALMNAME
+    global KADMIN
+    global KADMIN_LOCAL
+    global KEY
+    global spawn_id
+    global tmppwd
+
+    set good 0
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank -randkey $flags $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin add rnd $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin add_rnd $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin add_rnd $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+    expect "Principal \"$pname@$REALMNAME\" created." { set good 1 }
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin add_rnd)"
+    catch "close -i $spawn_id"
+    if { $good == 1 } {
+	#
+	# use kadmin.local to verify that a principal was created and that its
+	# salt types are 0 (normal).
+	#
+	spawn $KADMIN_LOCAL -r $REALMNAME
+	expect_after {
+	     -i $spawn_id
+	    timeout {
+		fail "kadmin add_rnd $pname"
+		catch "expect_after"
+		return 0
+	    }
+	    eof {
+		fail "kadmin add_rnd $pname"
+		catch "expect_after"
+		return 0
+	    }
+	}
+	set good 0
+	expect "kadmin.local:" { send "getprinc $pname\r" }
+	expect "Principal: $pname@$REALMNAME" { set good 1 }
+	expect "kadmin.local:" { send "q\r" }
+	expect_after
+	expect eof
+	set k_stat [wait -i $spawn_id]
+	verbose "wait -i $spawn_id returned $k_stat (kadmin.local show)"
+	catch "close -i $spawn_id"
+	if { $good == 1 } {
+	    pass "kadmin add_rnd $pname"
+	    return 1
+	}
+	else {
+	    fail "kadmin add_rnd $pname"
+	    return 0
+	}
+    }
+    else {
+	fail "kadmin add_rnd $pname"
+	return 0
+    }
+}
+
+#++
+# kadmin_show	- Test show principal function of kadmin.
+# 
+# Retrieves entry for $pname.  Returns 1 on success.
+#--
+proc kadmin_show { pname } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_principal $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin show $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin show $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin show $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *"
+    send "adminpass$KEY\r"
+    expect -re "\r.*Principal: $pname@$REALMNAME.*Key: .*Attributes:.*Policy: .*\r"
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin show)"
+    catch "close -i $spawn_id"
+    pass "kadmin show $pname"
+    return 1
+}
+
+#++
+# kadmin_cpw	- Test change password function of kadmin
+#
+# Change password of $pname to $password.  Returns 1 on success.
+#--
+proc kadmin_cpw { pname password } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "cpw $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin cpw $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin cpw $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin cpw $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+
+    expect "Enter password for principal \"$pname\":" { send "$password\r" }
+    expect "Re-enter password for principal \"$pname\":" { send "$password\r" }
+    # When in doubt, jam one of these in there.
+    expect "\r"
+    expect "Password for \"$pname@$REALMNAME\" changed."
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin cpw)"
+    catch "close -i $spawn_id"
+    pass "kadmin cpw $pname"
+    return 1
+}
+
+#++
+# kadmin_cpw_rnd	- Test change random key function of kadmin.
+#
+# Changes principal $pname's key to a new random key.  Returns 1 on success.
+#--
+proc kadmin_cpw_rnd { pname } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "cpw -randkey $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin cpw_rnd $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin cpw_rnd $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin cpw_rnd $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+    # When in doubt, jam one of these in there.
+    expect "\r"
+    expect "Key for \"$pname@$REALMNAME\" randomized."
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin cpw_rnd)"
+    catch "close -i $spawn_id"
+    pass "kadmin cpw_rnd $pname"
+    return 1
+}
+
+#++
+# kadmin_modify	- Test modify principal function of kadmin.
+#
+# Modifies principal $pname with flags $flags.  Returns 1 on success.
+#--
+proc kadmin_modify { pname flags } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "modprinc $flags $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin modify $pname ($flags) lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin modify $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin modify $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *"
+    send "adminpass$KEY\r"
+    # When in doubt, jam one of these in there.
+    expect "\r"
+    expect "Principal \"$pname@$REALMNAME\" modified."
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin modify)"
+    catch "close -i $spawn_id"
+    pass "kadmin modify $pname"
+    return 1
+}
+
+
+#++
+# kadmin_list	- Test list database function of kadmin.
+#
+# Lists the database and verifies that output matches regular expression
+# "(.*@$REALMNAME)*".  Returns 1 on success.
+#--
+proc kadmin_list {  } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_principals *"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin ldb lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	"Communication failure" {
+	    fail "kadmin ldb got RPC error"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin ldb"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin ldb"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+    expect -re "\(.*@$REALMNAME\r\n\)+"
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin list)"
+    catch "close -i $spawn_id"
+    pass "kadmin ldb"
+    return 1
+}
+
+#++
+# kadmin_extract	- Test extract service key function of kadmin.
+#
+# Extracts service key for service name $name instance $instance.  Returns
+# 1 on success.
+#--
+proc kadmin_extract { instance name } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+    global tmppwd
+
+    catch "exec rm -f $tmppwd/keytab"
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "xst -k $tmppwd/keytab $name/$instance"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin xst $instance $name lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin xst $instance $name"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin xst $instance $name"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+#    expect -re "kadmin: Entry for principal $name/$instance with kvno [0-9], encryption type .* added to keytab WRFILE:$tmppwd/keytab."
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin xst)"
+    catch "close -i $spawn_id"
+    catch "exec rm -f $instance-new-srvtab"
+    pass "kadmin xst $instance $name"
+    return 1
+}
+
+#++
+# kadmin_extractv4	- Test extract service key in v4 format function of
+#			  kadmin.
+#
+# Extracts service key for service name $name instance $instance in version
+# 4 format.  Returns 1 on success.
+#--
+#proc kadmin_extractv4 { instance name } {
+#    global REALMNAME
+#    global KADMIN
+#    global KEY
+#    global spawn_id
+#
+#    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "xst4 $instance $name"
+#    expect_after {
+#	"Cannot contact any KDC" {
+#	    fail "kadmin xst4 $instance $name lost KDC"
+#	    catch "expect_after"
+#	    return 0
+#	}
+#	timeout {
+#	    fail "kadmin xst4 $instance $name"
+#	    catch "expect_after"
+#	    return 0
+#	}
+#	eof {
+#	    fail "kadmin xst4 $instance $name"
+#	    catch "expect_after"
+#	    return 0
+#	}
+#    }
+#    expect -re "assword\[^\r\n\]*: *" {
+#	send "adminpass$KEY\r"
+#    }
+#    expect "extracted entry $name to key table $instance-new-v4-srvtab"
+#    expect_after
+#    expect eof
+#    set k_stat [wait -i $spawn_id]
+#    verbose "wait -i $spawn_id returned $k_stat (kadmin xst4)"
+#    catch "close -i $spawn_id"
+#    catch "exec rm -f $instance-new-v4-srvtab"
+#    pass "kadmin xst4 $instance $name"
+#    return 1
+#}
+
+#++
+# kadmin_delete	- Test delete principal function of kadmin.
+#
+# Deletes principal $pname.  Returns 1 on success.
+#--
+proc kadmin_delete { pname } {
+    global REALMNAME
+    global KADMIN
+    global KADMIN_LOCAL
+    global KEY
+    global spawn_id
+    global tmppwd
+
+    set good 0
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "delprinc -force $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin_delete $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin delprinc $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin delprinc $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+    expect "Principal \"$pname@$REALMNAME\" deleted." { set good 1 }
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin delprinc)"
+    catch "close -i $spawn_id"
+    if { $good == 1 } {
+	#
+	# use kadmin.local to verify that the old principal is not present.
+	#
+	spawn $KADMIN_LOCAL -r $REALMNAME
+	expect_after {
+	    -i $spawn_id
+	    timeout {
+		fail "kadmin delprinc $pname"
+		catch "expect_after"
+		return 0
+	    }
+	    eof {
+		fail "kadmin delprinc $pname"
+		catch "expect_after"
+		return 0
+	    }
+	}
+	set good 0
+	expect "kadmin.local: " { send "getprinc $pname\r" }
+	expect "Principal does not exist while retrieving \"$pname@$REALMNAME\"." { set good 1 }
+	expect "kadmin.local: " { send "quit\r" }
+	expect_after
+	expect eof
+	set k_stat [wait -i $spawn_id]
+	verbose "wait -i $spawn_id returned $k_stat (kadmin.local show)"
+	catch "close -i $spawn_id"
+	if { $good == 1 } {
+	    pass "kadmin delprinc $pname"
+	    return 1
+	}
+	else {
+	    fail "kadmin delprinc $pname"
+	    return 0
+	}
+    }
+    else {
+	fail "kadmin delprinc $pname"
+	return 0
+    }
+}
+
+#++
+# kpasswd_cpw	- Test password changing using kpasswd.
+#
+# Change $princ's password from $opw to $npw.  Returns 1 on success.
+#--
+proc kpasswd_cpw { princ opw npw } {
+    global KPASSWD
+    global REALMNAME
+
+    spawn $KPASSWD $princ
+    expect_after {
+	timeout {
+	    fail "kpasswd $princ $npw"
+#	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kpasswd $princ $npw"
+#	    catch "expect_after"
+	    return 0
+	}
+    }
+
+#    expect "Changing password for $princ."
+#    expect "Old password:" { send "$opw\r" }
+#    expect "New password:" { send "$npw\r" }
+#    expect "New password (again):" { send "$npw\r" }
+    expect "Password for $princ@$REALMNAME:" { send "$opw\r" }
+    expect "Enter new password:"  { send "$npw\r" }
+    expect "Enter it again:"      { send "$npw\r" }
+#    expect "Kerberos password changed."
+    expect "Password changed."
+    expect_after
+    expect eof
+
+    if ![check_exit_status "kpasswd"] {
+	fail "kpasswd $princ $npw"
+	return 0
+    }
+    pass "kpasswd $princ $npw"
+    return 1
+}
+
+#++
+# kadmin_addpol	- Test add new policy function of kadmin.
+#
+# Adds policy $pname.  Returns 1 on success.
+#--
+proc kadmin_addpol { pname } {
+    global REALMNAME
+    global KADMIN
+    global KADMIN_LOCAL
+    global KEY
+    global spawn_id
+    global tmppwd
+
+    set good 0
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "addpol $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin addpol $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin addpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin addpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin addpol)"
+    catch "close -i $spawn_id"
+    #
+    # use kadmin.local to verify that a policy was created
+    #
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    expect_after {
+        -i $spawn_id
+        timeout {
+	    fail "kadmin addpol $pname"
+	    catch "expect_after"
+	    return 0
+        }
+        eof {
+	    fail "kadmin addpol $pname"
+	    catch "expect_after"
+	    return 0
+        }
+    }
+    set good 0
+    expect "kadmin.local: " { send "getpol $pname\r" }
+    expect "Policy: $pname" { set good 1 }
+    expect "Maximum password life:" { verbose "got max pw life" }
+    expect "Minimum password life:" { verbose "got min pw life" }
+    expect "Minimum password length:" { verbose "got min pw length" }
+    expect "Minimum number of password character classes:" {
+        verbose "got min pw character classes" }
+    expect "Number of old keys kept:" { verbose "got num old keys kept" }
+    expect "Reference count:" { verbose "got refcount" }
+    expect "kadmin.local: " { send "q\r" }
+
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin.local showpol)"
+    catch "close -i $spawn_id"
+    if { $good == 1 } {
+        pass "kadmin addpol $pname"
+        return 1
+    }
+    else {
+        fail "kadmin addpol $pname"
+        return 0
+    }
+}
+
+#++
+# kadmin_delpol	- Test delete policy function of kadmin.
+#
+# Deletes policy $pname.  Returns 1 on success.
+#--
+proc kadmin_delpol { pname } {
+    global REALMNAME
+    global KADMIN
+    global KADMIN_LOCAL
+    global KEY
+    global spawn_id
+    global tmppwd
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "delpol -force $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin_delpol $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin delpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin delpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin delpol)"
+    catch "close -i $spawn_id"
+    #
+    # use kadmin.local to verify that the old policy is not present.
+    #
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    expect_after {
+        -i $spawn_id
+        timeout {
+	    fail "kadmin delpol $pname"
+	    catch "expect_after"
+	    return 0
+        }
+        eof {
+	    fail "kadmin delpol $pname"
+	    catch "expect_after"
+	    return 0
+        }
+    }
+    set good 0
+    expect "kadmin.local: " { send "getpol $pname\r" }
+    expect "Policy does not exist while retrieving policy \"$pname\"." {
+	set good 1
+    }
+    expect "kadmin.local: " { send "quit\r" }
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin.local showpol)"
+    catch "close -i $spawn_id"
+    if { $good == 1 } {
+        pass "kadmin delpol $pname"
+        return 1
+    }
+    else {
+        fail "kadmin delpol $pname"
+        return 0
+    }
+}
+
+#++
+# kadmin_listpols	- Test list policy database function of kadmin.
+#
+# Lists the policies.  Returns 1 on success.
+#--
+proc kadmin_listpols {  } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_policies *"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin lpols lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin lpols"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin lpols"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *" {
+	send "adminpass$KEY\r"
+    }
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin listpols)"
+    catch "close -i $spawn_id"
+    pass "kadmin lpols"
+    return 1
+}
+
+#++
+# kadmin_modpol	- Test modify policy function of kadmin.
+#
+# Modifies policy $pname with flags $flags.  Returns 1 on success.
+#--
+proc kadmin_modpol { pname flags } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "modpol $flags $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin modpol $pname ($flags) lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin modpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin modpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *"
+    send "adminpass$KEY\r"
+    # When in doubt, jam one of these in there.
+    expect "\r"
+    # Sadly, kadmin doesn't print a confirmation message for policy operations.
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin modpol)"
+    catch "close -i $spawn_id"
+    pass "kadmin modpol $pname"
+    return 1
+}
+
+#++
+# kadmin_showpol	- Test show policy function of kadmin.
+# 
+# Retrieves entry for $pname.  Returns 1 on success.
+#--
+proc kadmin_showpol { pname } {
+    global REALMNAME
+    global KADMIN
+    global KEY
+    global spawn_id
+
+    spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_policy $pname"
+    expect_after {
+	"Cannot contact any KDC" {
+	    fail "kadmin showpol $pname lost KDC"
+	    catch "expect_after"
+	    return 0
+	}
+	timeout {
+	    fail "kadmin showpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+	eof {
+	    fail "kadmin showpol $pname"
+	    catch "expect_after"
+	    return 0
+	}
+    }
+    expect -re "assword\[^\r\n\]*: *"
+    send "adminpass$KEY\r"
+    expect -re "\r.*Policy: $pname.*Number of old keys kept: .*Reference count: .*\r"
+    expect_after
+    expect eof
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin showpol)"
+    catch "close -i $spawn_id"
+    pass "kadmin showpol $pname"
+    return 1
+}
+
+#++
+# kdestroy
+#--
+proc kdestroy { } {
+    global KDESTROY
+
+    spawn $KDESTROY -5
+    if ![check_exit_status "kdestroy"] {
+	return 0
+    }
+    return 1
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc kadmin_test { } {
+    global hostname
+
+    # Start up the kerberos and kadmind daemons
+    if {![start_kerberos_daemons 0] } {
+	return
+    }
+
+    # Test basic kadmin functions.
+    if {![kadmin_add v5principal/instance1 v5principal] \
+	|| ![kadmin_addpol standardpol] \
+	|| ![kadmin_showpol standardpol] \
+	|| ![kadmin_listpols] \
+	|| ![kadmin_modpol standardpol "-minlength 5"] \
+	|| ![kadmin_add v4principal/instance2 v4principal] \
+	|| ![kadmin_add_rnd v5random] \
+	|| ![kadmin_show v5principal/instance1] \
+	|| ![kadmin_show v4principal/instance2] \
+	|| ![kadmin_show v5random] \
+	|| ![kadmin_cpw v5principal/instance1 faroutman] \
+	|| ![kadmin_cpw v4principal/instance2 honkydory] \
+	|| ![kadmin_cpw_rnd v5random] \
+	|| ![kadmin_modify v5random -allow_tix] \
+	|| ![kadmin_modify v5random +allow_tix] \
+	|| ![kadmin_modify v5random "-policy standardpol"] \
+	|| ![kadmin_list] \
+	|| ![kadmin_extract instance1 v5principal] \
+	|| ![kadmin_delete v5random] \
+	|| ![kadmin_delete v4principal/instance2] \
+	|| ![kadmin_delete v5principal/instance1] \
+	|| ![kadmin_delpol standardpol]} {
+	return
+    }
+
+# You cannot extract a v4 key...
+#	|| ![kadmin_extractv4 instance2 v4principal] \
+
+    # now test kpasswd
+    if {![kadmin_add testprinc/instance thisisatest] \
+	    || ![kpasswd_cpw testprinc/instance thisisatest anothertest] \
+	    || ![kpasswd_cpw testprinc/instance anothertest goredsox] \
+	    || ![kadmin_delete testprinc/instance]} {
+	return
+    }
+
+    # now test that we can kinit with principals/passwords.
+    if {![kadmin_add testprinc1/instance thisisatest] \
+	    || ![kinit testprinc1/instance thisisatest 0] \
+	    || ![kdestroy] \
+	    || ![kpasswd_cpw testprinc1/instance thisisatest anothertest] \
+	    || ![kinit testprinc1/instance anothertest 0] \
+	    || ![kdestroy] \
+	    || ![kpasswd_cpw testprinc1/instance anothertest goredsox] \
+	    || ![kinit testprinc1/instance goredsox 0] \
+	    || ![kdestroy] \
+	    || ![kadmin_cpw testprinc1/instance betterwork] \
+	    || ![kinit testprinc1/instance betterwork 0] \
+	    || ![kdestroy] \
+	    || ![kadmin_delete testprinc1/instance]} {
+	return
+    }
+
+    # now test modify changes.
+    if {![kadmin_add testuser longtestpw] \
+	    || ![kinit testuser longtestpw 0] \
+	    || ![kdestroy] \
+	    || ![kadmin_modify testuser "-maxlife \"2500 seconds\""] \
+	    || ![kinit testuser longtestpw 0] \
+	    || ![kdestroy] \
+	    || ![kadmin_delete testuser]} {
+	return
+    }
+
+    # now test that reducing the history number doesn't make kadmind vulnerable.
+    if {![kadmin_addpol crashpol] \
+	    || ![kadmin_modpol crashpol "-history 5"] \
+	    || ![kadmin_add crash first] \
+	    || ![kadmin_modify crash "-policy crashpol"] \
+	    || ![kadmin_cpw crash second] \
+	    || ![kadmin_cpw crash third] \
+	    || ![kadmin_cpw crash fourth] \
+	    || ![kadmin_modpol crashpol "-history 3"] \
+	    || ![kadmin_cpw crash fifth] \
+	    || ![kadmin_delete crash] \
+	    || ![kadmin_delpol crashpol]} {
+	return
+    }
+
+    # test retrieval of large number of principals
+    # bug [2877]
+    for { set i 0 } { $i < 200 } { incr i } {
+	if { ![kadmin_add "foo$i" foopass] } {
+	    return
+	}
+    }
+
+    if { ![kadmin_list] } {
+	return
+    }
+
+    # test fallback to kadmin/admin
+    if {![kadmin_delete kadmin/$hostname] \
+	    || ![kadmin_list] \
+	    || ![kadmin_add_rnd kadmin/$hostname -allow_tgs_req] \
+	    || ![kadmin_list]} {
+	return
+    }
+
+    verbose "kadmin_test succeeded"
+}
+
+# Run the test.
+set status [catch kadmin_test msg]
+
+# Shut down the kerberos daemons and the rsh daemon.
+stop_kerberos_daemons
+
+if { $status != 0 } {
+    send_error "ERROR: error in kadmin.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/pwhist.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/pwhist.exp
new file mode 100644
index 000000000..f9938e091
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/pwhist.exp
@@ -0,0 +1,215 @@
+# password history tests
+
+# one *non-interactive* kadmin.local request
+proc onerq { rq pname str {flags ""} } {
+    global REALMNAME
+    global KADMIN_LOCAL
+
+    spawn $KADMIN_LOCAL -r $REALMNAME -q "$rq $flags $pname"
+    expect_after {
+	timeout {
+	    verbose "kadmin.local $rq $flags $pname timed out"
+	    catch expect_after
+	    kill [exp_pid]
+	    close
+	    expect eof
+	    wait
+	    return 0
+	} eof {
+	    verbose "kadmin.local $rq $flags $pname got EOF"
+	    catch expect_after
+	    wait
+	    return 0
+	}
+    }
+    expect $str
+    expect_after
+    expect eof
+    wait
+    return 1
+}
+
+proc addprinc { pname pw } {
+    global REALMNAME
+
+    return [onerq addprinc $pname \
+		"Principal \"$pname@$REALMNAME\" created." "-pw $pw"]
+}
+
+proc delprinc { pname } {
+    global REALMNAME
+    return [onerq delprinc $pname \
+		"Principal \"$pname@$REALMNAME\" deleted." "-force"]
+}
+
+proc cpw { pname pw } {
+    global REALMNAME
+
+    return [onerq cpw $pname \
+		"Password for \"$pname@$REALMNAME\" changed." "-pw $pw"]
+}
+
+proc modprinc { pname flags } {
+    global REALMNAME
+
+    return [onerq modprinc $pname \
+		"Principal \"$pname@$REALMNAME\" modified." $flags]
+}
+
+proc addpol { pname } {
+    if ![onerq addpol $pname ""] {
+	return 0
+    }
+    return [onerq getpol $pname "Policy: $pname"]
+}
+
+proc delpol { pname } {
+    onerq delpol $pname "" -force
+    return [onerq getpol $pname \
+		"Policy does not exist while retrieving policy \"$pname\"."]
+}
+
+proc modpol { pname flags } {
+    return [onerq modpol $pname "" $flags]
+}
+
+# Mandatory command must return true.
+# Issues a break in its parent on failure.
+proc mustrun { cmd } {
+    if ![eval $cmd] {
+	perror "mandatory command failed: $cmd"
+	uplevel break
+    }
+}
+
+# Fail test if command fails.
+# Issues a break in its parent on failure.
+proc chkpass { cmd } {
+    upvar test test
+    if ![eval $cmd] {
+	verbose "unexpected failure: $cmd"
+	fail $test
+	uplevel break
+    }
+}
+
+# Fail test if command succeeds.
+# Issues a break in its parent on failure.
+proc chkfail { cmd } {
+    upvar test test
+    if [eval $cmd] {
+	verbose "unexpected success: $cmd"
+	fail $test
+	uplevel break
+    }
+}
+
+# wrapper to run command (actually usually sequence of commands)
+#
+# If any part of CMD throws an exception, set failall, otherwise pass.
+# If failall is already true, report unresolved.
+proc wraptest { test cmd } {
+    upvar failall failall
+    if $failall {
+	unresolved $test
+	return
+    }
+    if [catch $cmd] {
+	set failall 1
+    } else {
+	pass $test
+    }
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_env] \
+    || ![setup_kerberos_db 0]} {
+    return
+}
+
+set failall 0
+wraptest "nkeys=1, nhist=3" {
+    mustrun { addpol crashpol }
+    mustrun { modpol crashpol "-history 3"}
+    mustrun { addprinc crash 1111 }
+    mustrun { modprinc crash "-policy crashpol" }
+    chkpass { cpw crash 2222 }
+    chkfail { cpw crash 2222 }
+    chkfail { cpw crash 1111 }
+}
+verbose {old_keys [ 1111 ->[] ]}
+
+# The following will result in reading/writing past array bounds if
+# add_to_history() is not patched.
+#
+# NOTE: A pass from this test does not mean the bug isn't present;
+# check with Purify, valgrind, etc.
+wraptest "array bounds ok on nkeys=1, nhist 3->2" {
+    mustrun { modpol crashpol "-history 2" }
+    chkpass { cpw crash 3333 }
+}
+verbose {old_keys [ ->2222 ]}
+
+wraptest "verify nhist=2" {
+    mustrun { delprinc crash }
+    mustrun { addprinc crash 1111 }
+    mustrun { modprinc crash "-policy crashpol" }
+    chkpass { cpw crash 2222 }
+    chkfail { cpw crash 2222 }
+    chkfail { cpw crash 1111 }
+}
+verbose {old_keys [ ->1111 ]}
+
+# The following will fail if growing the history array causes an extra
+# key to be lost due to failure to shift entries.
+wraptest "grow nhist 2->3" {
+    mustrun { modpol crashpol "-history 3" }
+    chkpass { cpw crash 3333 }
+    chkfail { cpw crash 3333 }
+    chkfail { cpw crash 2222 }
+    chkfail { cpw crash 1111 }
+}
+verbose {old_keys [ 2222 ->1111 ]}
+
+wraptest "grow nhist 3->4" {
+    mustrun { modpol crashpol "-history 4" }
+    chkfail { cpw crash 3333 }
+    chkfail { cpw crash 2222 }
+    chkfail { cpw crash 1111 }
+    chkpass { cpw crash 4444 }
+    chkfail { cpw crash 3333 }
+    chkfail { cpw crash 2222 }
+    chkfail { cpw crash 1111 }
+}
+verbose {old_keys [ 2222 3333 ->1111 ]}
+wraptest "shrink nhist 4->3" {
+    mustrun { modpol crashpol "-history 3" }
+    chkfail { cpw crash 4444 }
+    chkfail { cpw crash 3333 }
+    chkfail { cpw crash 2222 }
+    chkfail { cpw crash 1111 }
+    chkpass { cpw crash 5555 }
+}
+verbose {old_keys [ 4444 ->3333 ]}
+wraptest "verify nhist=3" {
+    chkfail { cpw crash 5555 }
+    chkfail { cpw crash 4444 }
+    chkfail { cpw crash 3333 }
+    chkpass { cpw crash 2222 }
+}
+verbose {old_keys [ ->4444 5555 ]}
+wraptest "shrink nhist 3->2" {
+    mustrun { modpol crashpol "-history 2" }
+    chkfail { cpw crash 2222 }
+    chkfail { cpw crash 5555 }
+    chkfail { cpw crash 4444 }
+    chkpass { cpw crash 3333 }
+}
+verbose {old_keys [ ->2222 ]}
+
+delprinc crash
+delpol crashpol
+
+stop_kerberos_daemons
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/rcp.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/rcp.exp
new file mode 100644
index 000000000..94ec240e6
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/rcp.exp
@@ -0,0 +1,232 @@
+# Kerberos rcp test.
+# This is a DejaGnu test script.
+# This script tests Kerberos rcp.
+# Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+
+# Find the programs we need.  We use the binaries from the build tree
+# if they exist.  If they do not, then they must be in PATH.  We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists RCP] {
+    set RCP [findfile $objdir/../../appl/bsd/rcp]
+}
+
+if ![info exists KRSHD] {
+    set KRSHD [findfile $objdir/../../appl/bsd/kshd]
+}
+
+# Remove old wrapper script
+    catch "exec rm -f $tmppwd/rcp"
+
+# Make sure .k5login is reasonable.
+if ![check_k5login rcp] {
+    return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_env] \
+    || ![setup_kerberos_db 0]} {
+    return
+}
+
+# A procedure to start up the rsh daemon (rcp talks to the rsh
+# daemon).
+
+proc start_rsh_daemon { } {
+    global REALMNAME
+    global KRSHD
+    global RCP
+    global tmppwd
+    global krshd_spawn_id
+    global krshd_pid
+    global portbase
+
+    # Setup the shared library wrapper for login.krb5
+    if ![file exists $tmppwd/rcp] {
+	    setup_wrapper $tmppwd/rcp "$RCP $*"
+    }
+
+
+    # The -D argument tells it to accept a single connection, so we
+    # don't need to use inetd.  The portbase+8 is the port to listen at.
+    #
+    # The -L ENV_SET is for the I/S Athena brokeness in dot files where
+    #	LD_LIBRARY_PATH will be overridden causing the "exec csh -c rcp ..." 
+    #	to fail as the .cshrc is read in. We do not use the -f option as
+    #	a users shell might be sh...
+    #	Later a proper fix would be to have kshd exec rcp directly
+    #   shell indirection...
+    spawn $KRSHD -k -c -D [expr 8 + $portbase] -P $tmppwd -S $tmppwd/srvtab -M $REALMNAME -L ENV_SET
+    set krshd_spawn_id $spawn_id
+    set krshd_pid [exp_pid]
+
+    # Give the rsh daemon a few seconds to get set up.
+    sleep 2
+}
+
+# A procedure to stop the rsh daemon.
+
+proc stop_rsh_daemon { } {
+    global krshd_spawn_id
+    global krshd_pid
+
+    if [info exists krshd_pid] {
+	catch "exec kill $krshd_pid"
+	catch {
+	    expect {
+		-i $krshd_spawn_id
+		-re ..*	{ exp_continue }
+		eof	{}
+	    }
+	}
+	catch "close -i $krshd_spawn_id"
+	catch "wait -i $krshd_spawn_id"
+	unset krshd_pid
+    }
+}
+
+# Create a file to use for rcp testing.
+set file [open $tmppwd/rcp-test w]
+puts $file "This file is used for rcp testing."
+close $file
+
+# Test that a file was copied correctly.
+proc check_file { filename } {
+    if ![file exists $filename] {
+	verbose "$filename does not exist"
+	send_log "$filename does not exist\n"
+	return 0
+    }
+
+    set file [open $filename r]
+    if { [gets $file line] == -1 } {
+	verbose "$filename is empty"
+	send_log "$filename is empty\n"
+	close $file
+	return 0
+    }
+
+    if ![string match "This file is used for rcp testing." $line] {
+	verbose "$filename contains $line"
+	send_log "$filename contains $line\n"
+	close $file
+	return 0
+    }
+
+    if { [gets $file line] != -1} {
+	verbose "$filename is too long ($line)"
+	send_log "$filename is too long ($line)\n"
+	close $file
+	return 0
+    }
+
+    close $file
+
+    return 1
+}
+
+# Test copying one file to another.
+proc rcp_one_test { testname options frompref topref } {
+    global REALMNAME
+    global RCP
+    global tmppwd
+    global portbase
+
+    send_log "rm -f $tmppwd/copy\n"
+    verbose "exec rm -f $tmppwd/copy"
+    catch "exec rm -f $tmppwd/copy"
+
+    set from [format "%s%s" $frompref $tmppwd/rcp-test]
+    set to [format "%s%s" $topref $tmppwd/copy]
+
+    send_log "$RCP $options -D [expr 8 + $portbase] -N -k $REALMNAME $from $to\n"
+    verbose "$RCP $options -D [expr 8 + $portbase] -N -k $REALMNAME $from $to"
+    catch "exec $RCP $options -D [expr 8 + $portbase] -N -k $REALMNAME $from $to" exec_output
+
+    if ![string match "" $exec_output] {
+	send_log "$exec_output\n"
+	verbose "$exec_output"
+	fail $testname
+	return 0
+    }
+
+    if ![check_file $tmppwd/copy] {
+	fail $testname
+	return 0
+    }
+
+    pass $testname
+
+    return 1
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc rcp_test { } {
+    global RCP
+    global KEY
+    global hostname
+    global hostname
+    global env
+
+    # Start up the kerberos and kadmind daemons and get a srvtab and a
+    # ticket file.
+    if {![start_kerberos_daemons 0] \
+        || ![add_kerberos_key host/$hostname 0] \
+        || ![setup_srvtab 0] \
+	|| ![add_kerberos_key $env(USER) 0] \
+	|| ![kinit $env(USER) $env(USER)$KEY 0]} {
+	return
+    }
+
+    rcp_one_test "local rcp" "" "" ""
+
+    start_rsh_daemon
+    rcp_one_test "rcp from" "" "$hostname:" ""
+    stop_rsh_daemon
+
+    start_rsh_daemon
+    rcp_one_test "rcp to" "" "" "$hostname:"
+    stop_rsh_daemon
+
+    # Doing rcp between two hosts actually just executes rsh rcp on
+    # the source.  We could test this, but we're not set up for it
+    # right now.  Also, it's pretty much covered by the other rcp
+    # tests and by the rsh tests.
+    # start_rsh_daemon
+    # rcp_one_test "rcp between" "" "$hostname:" "$hostname:"
+    # stop_rsh_daemon
+
+    start_rsh_daemon
+    rcp_one_test "encrypted rcp from" "-x -c $env(KRB5CCNAME) -C $env(KRB5_CONFIG)" "$hostname:" ""
+    stop_rsh_daemon
+
+    start_rsh_daemon
+    rcp_one_test "encrypted rcp to" "-x -c $env(KRB5CCNAME) -C $env(KRB5_CONFIG)" "" "$hostname:"
+    stop_rsh_daemon
+
+    # Doing rcp between two hosts actually just executes rsh rcp on
+    # the source.  We could test this, but we're not set up for it
+    # right now.  Also, it's pretty much covered by the other rcp
+    # tests and by the rsh tests.
+    # start_rsh_daemon
+    # rcp_one_test "encrypted rcp between" "-x" "$hostname:" "$hostname:"
+    # stop_rsh_daemon
+}
+
+# Run the test.
+set status [catch rcp_test msg]
+
+# Shut down the kerberos daemons and the rsh daemon.
+stop_kerberos_daemons
+
+stop_rsh_daemon
+
+if { $status != 0 } {
+    send_error "ERROR: error in rcp.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/rsh.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/rsh.exp
new file mode 100644
index 000000000..b7c02a2a7
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/rsh.exp
@@ -0,0 +1,294 @@
+# Kerberos rsh test.
+# This is a DejaGnu test script.
+# This script tests Kerberos rsh.
+# Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+
+# Find the programs we need.  We use the binaries from the build tree
+# if they exist.  If they do not, then they must be in PATH.  We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists RSH] {
+    set RSH [findfile $objdir/../../appl/bsd/rsh]
+}
+
+if ![info exists KRSHD] {
+    set KRSHD [findfile $objdir/../../appl/bsd/kshd]
+}
+
+if ![info exists KLIST] {
+    set KLIST [findfile $objdir/../../clients/klist/klist]
+}
+
+# Make sure .k5login is reasonable.
+if ![check_k5login rsh] {
+    return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_db 0]} {
+    return
+}
+
+# A procedure to start up the rsh daemon.
+
+proc start_rsh_daemon { option } {
+    global REALMNAME
+    global KRSHD
+    global tmppwd
+    global krshd_spawn_id
+    global krshd_pid
+    global portbase
+
+    # The -D argument tells it to accept a single connection, so we
+    # don't need to use inetd.  The portbase+8 is the port to listen at.
+    spawn $KRSHD -k -c -D [expr 8 + $portbase] -S $tmppwd/srvtab -M $REALMNAME -A $option
+    set krshd_spawn_id $spawn_id
+    set krshd_pid [exp_pid]
+
+    # Give the rsh daemon a few seconds to get set up.
+    sleep 2
+}
+
+# A procedure to stop the rsh daemon.
+
+proc stop_rsh_daemon { } {
+    global krshd_spawn_id
+    global krshd_pid
+
+    if [info exists krshd_pid] {
+	catch "exec kill $krshd_pid"
+	catch {
+	    expect {
+		-i $krshd_spawn_id
+		-re ..*	{ exp_continue }
+		eof	{}
+	    }
+	}
+	catch "close -i $krshd_spawn_id"
+	catch "wait -i $krshd_spawn_id"
+	unset krshd_pid
+    }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc rsh_test { } {
+    global REALMNAME
+    global KLIST
+    global RSH
+    global KEY
+    global BINSH
+    global hostname
+    global env
+    global spawn_id
+    global tmppwd
+    global portbase
+
+    # Start up the kerberos and kadmind daemons and get a srvtab and a
+    # ticket file.
+    if {![start_kerberos_daemons 0] \
+        || ![add_kerberos_key host/$hostname 0] \
+        || ![setup_srvtab 0] \
+	|| ![add_kerberos_key $env(USER) 0] \
+	|| ![setup_kerberos_env client] \
+	|| ![kinit $env(USER) $env(USER)$KEY 0]} {
+	return
+    }
+
+    # Start up the rsh daemon.
+    start_rsh_daemon -k
+
+    # Run rsh date.
+    set testname "date"
+    spawn $RSH $hostname -k $REALMNAME -D [expr 8 + $portbase] -A date
+    expect {
+	-re "\[A-Za-z0-9\]+ \[A-Za-z0-9\]+ +\[0-9\]+ \[0-9\]+:\[0-9\]+:\[0-9\]+ \[A-Za-z0-9\]+ \[0-9\]+\r\n" {
+	    set result $expect_out(0,string)
+	}
+	timeout {
+	    fail "$testname (timeout)"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    return
+	}
+    }
+    expect eof
+    if ![check_exit_status $testname] {
+	return
+    }
+
+    if [check_date $result] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    # The rsh daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_rsh_daemon
+
+    # Check encrypted rsh.
+    set failed no
+    start_rsh_daemon -ek
+    set testname "encrypted rsh"
+    spawn $RSH $hostname -x -k $REALMNAME -D [expr 8 + $portbase] -A echo hello
+    expect {
+	"hello" { expect eof }
+	timeout {
+	    fail "$testname (timeout)"
+	    set failed yes
+	}
+	eof {
+	    fail "$testname (eof)"
+	    set failed yes
+	}
+    }
+
+    catch "expect eof"
+    if { $failed == "no" } {
+	if ![check_exit_status $testname] {
+	    return
+	}
+	pass $testname
+	stop_rsh_daemon
+    } else {
+	catch "wait -i $spawn_id"
+	catch "close -i $spawn_id"
+	stop_rsh_daemon
+    }
+
+    # Check ticket forwarding
+    set failed no
+    start_rsh_daemon -k
+    set testname "rsh forwarding tickets"
+
+    # We need a wrapper for klist in order to setup for shared library 
+    # runtime environment
+    setup_wrapper $tmppwd/klist.wrap $KLIST
+
+    spawn $RSH $hostname -f -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c $tmppwd/klist.wrap 
+    expect {
+	"Ticket cache:*\r" {
+	    expect eof
+	}
+ 	"klist: No credentials cache file found" {
+	    fail "$testname (not forwarded)"
+	    return
+	}
+	timeout {
+	    fail "$testname (timeout)"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    return
+	}
+    }
+
+    if ![check_exit_status $testname] {
+	return
+    }
+
+    pass $testname
+
+    stop_rsh_daemon
+
+    # Check encrypted ticket forwarding
+    set failed no
+    start_rsh_daemon -e
+    set testname "encrypted rsh forwarding tickets"
+    spawn $RSH $hostname -x -f -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c $tmppwd/klist.wrap 
+    expect {
+	"Ticket cache:*\r" {
+	    expect eof
+	}
+ 	"klist: No credentials cache file found" {
+	    fail "$testname (not forwarded)"
+	    return
+	}
+	timeout {
+	    fail "$testname (timeout)"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    return
+	}
+    }
+
+    if ![check_exit_status $testname] {
+	return
+    }
+
+    pass $testname
+
+    stop_rsh_daemon
+
+    # Check stderr
+    start_rsh_daemon -k
+    set testname "rsh to stderr"
+    spawn $RSH $hostname -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c "'echo hello 1>&2'"
+    expect {
+	"hello" { expect eof }
+	timeout {
+	    fail "$testname (timeout)"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    return
+	}
+    }
+
+    if ![check_exit_status $testname] {
+	return
+    }
+
+    pass $testname
+
+    stop_rsh_daemon
+
+    start_rsh_daemon -e
+    set testname "encrypted rsh to stderr"
+    spawn $RSH $hostname -x -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c "'echo hello 1>&2'"
+    expect {
+	"hello" { expect eof }
+	timeout {
+	    fail "$testname (timeout)"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    return
+	}
+    }
+
+    if ![check_exit_status $testname] {
+	return
+    }
+
+    pass $testname
+
+    # The rsh daemon should have stopped, but we have no easy way
+    # of checking whether it actually did.  Kill it just in case.
+    stop_rsh_daemon
+}
+
+# Run the test.
+set status [catch rsh_test msg]
+
+# Shut down the kerberos daemons and the rsh daemon.
+stop_kerberos_daemons
+
+stop_rsh_daemon
+
+if { $status != 0 } {
+    send_error "ERROR: error in rsh.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/sample.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/sample.exp
new file mode 100644
index 000000000..c19c49e91
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/sample.exp
@@ -0,0 +1,210 @@
+# Test for the sample clients
+# This is a DejaGnu test script.
+# This script tests that sample user-user communication works.
+
+# This mostly just calls procedures in test/dejagnu/config/default.exp.
+
+if ![info exists KLIST] {
+    set KLIST [findfile $objdir/../../clients/klist/klist]
+}
+
+if ![info exists KDESTROY] {
+    set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
+}
+
+if ![info exists SSERVER] {
+    set SSERVER [findfile $objdir/../../appl/sample/sserver/sserver]
+}
+if ![info exists SCLIENT] {
+    set SCLIENT [findfile $objdir/../../appl/sample/sclient/sclient]
+}
+
+# Set up the Kerberos files and environment.
+if {![get_hostname] || ![setup_kerberos_files] || ![setup_kerberos_env]} {
+    return
+}
+
+# Initialize the Kerberos database.  The argument tells
+# setup_kerberos_db that it is being called from here.
+if ![setup_kerberos_db 0] {
+    return
+}
+
+proc start_sserver_daemon { inetd } {
+    global spawn_id
+    global sserver_pid
+    global sserver_spawn_id
+    global SSERVER
+    global T_INETD
+    global tmppwd
+    global portbase
+
+    # if inetd = 0, then we are running stand-alone
+    if !{$inetd} {
+	    # Start the sserver
+	    spawn $SSERVER -p [expr 8 + $portbase] -S $tmppwd/srvtab
+	    set sserver_pid [exp_pid]
+	    set sserver_spawn_id $spawn_id
+
+	    verbose "sserver_spawn is $sserver_spawn_id" 1
+    } else {
+	    # Start the sserver
+	    spawn $T_INETD [expr 8 + $portbase] $SSERVER sserver -S $tmppwd/srvtab
+	    set sserver_pid [exp_pid]
+	    set sserver_spawn_id $spawn_id
+
+	    verbose "sserver_spawn (t_inetd) is $sserver_spawn_id" 1
+    }
+
+    # Give sserver some time to start
+    sleep 2
+
+    return 1
+}
+
+
+proc stop_sserver_daemon { } {
+    global sserver_pid
+    global sserver_spawn_id
+
+    if [info exists sserver_pid] {
+	catch "close -i $sserver_spawn_id"
+	catch "exec kill $sserver_pid"
+	wait -i $sserver_spawn_id
+	unset sserver_pid
+    }
+
+    return 1
+}
+
+proc stop_check_sserver_daemon { } {
+    global sserver_spawn_id
+    global sserver_pid
+
+    # Check the exit status of sserver - should exit here
+    set status_list [wait -i $sserver_spawn_id]
+    verbose "wait -i $sserver_spawn_id returned $status_list (sserver)"
+    catch "close -i $sserver_spawn_id"
+    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
+	send_log "exit status: $status_list\n"
+	verbose "exit status: $status_list"
+	fail "sserver"
+    } else {
+	pass "sserver"
+    }
+    # In either case the server shutdown
+    unset sserver_pid
+}
+
+proc test_sclient { msg } {
+    global REALMNAME
+    global SCLIENT
+    global hostname
+    global spawn_id
+    global portbase
+
+    # Test the client
+    spawn $SCLIENT $hostname [expr 8 + $portbase]
+    verbose "sclient_spawn is  $spawn_id" 1
+
+    expect {
+	"sendauth succeeded, reply is:" {
+		verbose "Start proper message"
+	}
+	timeout {
+		fail $msg 
+		return 0
+	}
+	eof {
+		fail $msg 
+		return 0
+	}	
+     }
+
+    expect {
+	"You are krbtest/admin@$REALMNAME\r" {
+		verbose "received valid sample message"}
+	eof {
+		fail $msg 
+		return 0
+	    }
+    }
+    # This last expect seems useless, but without it the test hangs on
+    # NETBSD.
+    expect {
+        "\r" { }
+    }
+
+    if ![check_exit_status "ssample"] {
+	return 0
+    }
+
+    return 1
+}
+# We are about to start up a couple of daemon processes.  We do all
+# the rest of the tests inside a proc, so that we can easily kill the
+# processes when the procedure ends.
+
+proc doit { } {
+    global hostname
+    global KEY
+    global sserver_pid
+    global sserver_spawn_id
+
+    # Start up the kerberos and kadmind daemons.
+    if ![start_kerberos_daemons 0] {
+	return
+    }
+
+    # Use kadmin to add an host key.
+    if ![add_random_key sample/$hostname 1] {
+	return
+    }
+
+    # Use ksrvutil to create a srvtab entry for sample
+    if ![setup_srvtab 1 sample] {
+	return
+    }
+
+    # Use kinit to get a ticket.
+    if ![kinit krbtest/admin adminpass$KEY 1] {
+	return
+    }
+
+    if ![start_sserver_daemon 0 ] {
+	return 
+    }
+
+    if ![test_sclient sclient] {
+	return
+    }
+    
+    pass "sample - standalone"
+
+    stop_check_sserver_daemon
+    
+    if ![start_sserver_daemon 1 ] {
+	return 
+    }
+
+    if ![test_sclient sclient-inetd] {
+	return
+    }
+    
+    pass "sample - inetd"
+
+    stop_check_sserver_daemon
+    return
+}
+
+set status [catch doit msg]
+
+stop_sserver_daemon
+
+stop_kerberos_daemons
+
+if { $status != 0 } {
+    send_error "ERROR: error in sample.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/standalone.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/standalone.exp
new file mode 100644
index 000000000..9a92b9303
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/standalone.exp
@@ -0,0 +1,277 @@
+# Standalone Kerberos test.
+# This is a DejaGnu test script.
+# This script tests that the Kerberos tools can talk to each other.
+
+# This mostly just calls procedures in testsuite/config/default.exp.
+
+# Set up the Kerberos files and environment.
+if {![get_hostname] || ![setup_kerberos_files] || ![setup_kerberos_env]} {
+    return
+}
+
+# Initialize the Kerberos database.  The argument tells
+# setup_kerberos_db that it is being called from here.
+if ![setup_kerberos_db 1] {
+    return
+}
+
+# We are about to start up a couple of daemon processes.  We do all
+# the rest of the tests inside a proc, so that we can easily kill the
+# processes when the procedure ends.
+
+proc dump_and_reload {} {
+    global KDB5_UTIL
+    global tmppwd
+
+    set dumpfile $tmppwd/dump-file
+    set dumpokfile $dumpfile.dump_ok
+
+    set test1name "kdb5_util dump"
+    set test2name "kdb5_util load"
+
+    if [file exists $dumpfile] { file delete $dumpfile }
+    if [file exists $dumpokfile] { file delete $dumpokfile }
+
+    spawn $KDB5_UTIL dump $dumpfile
+    expect {
+	-re "..*" {
+	    fail $test1name
+	    untested $test2name
+	    return
+	}
+	timeout {
+	    fail $test1name
+	    untested $test2name
+	    return
+	}
+	eof { }
+    }
+    if ![check_exit_status $test1name] {
+	untested $test2name
+	return
+    }
+    if ![file exists $dumpfile]||![file exists $dumpokfile] {
+	fail $test1name
+	untested $test2name
+	return
+    }
+    pass $test1name
+
+    spawn $KDB5_UTIL load $dumpfile
+    expect {
+	-re "..*" {
+	    fail $test2name
+	    return
+	}
+	timeout {
+	    fail $test2name
+	    return
+	}
+	eof { }
+    }
+    if [check_exit_status $test2name] {
+	pass $test2name
+    }
+}
+
+proc doit { } {
+    global REALMNAME
+    global KLIST
+    global KDESTROY
+    global KEY
+    global KADMIN_LOCAL
+    global KTUTIL
+    global hostname
+    global tmppwd
+    global spawn_id
+    global supported_enctypes
+    global KRBIV
+    global portbase
+    global mode
+
+    # Start up the kerberos and kadmind daemons.
+    if ![start_kerberos_daemons 1] {
+	return
+    }
+
+    # Use kadmin to add an host key.
+    if ![add_random_key host/$hostname 1] {
+	return
+    }
+
+    spawn $KADMIN_LOCAL -q "addpol fred"
+    catch expect_after
+    expect {
+	timeout {
+	    fail "kadmin.local addpol fred"
+	}
+	eof {
+	    pass "kadmin.local addpol fred"
+	}
+    }
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin addpol)"
+    catch "close -i $spawn_id"
+
+    # Use ksrvutil to create a srvtab entry.
+    if ![setup_srvtab 1] {
+	return
+    }
+
+    # Test dump and load.  Continue on, whatever the result.
+    dump_and_reload
+
+    spawn $KADMIN_LOCAL -q "getpols"
+    expect {
+	fred {
+	    pass "kadmin.local getpols"
+	    expect eof
+	}
+	timeout {
+	    fail "kadmin.local getpols"
+	}
+	eof {
+	    fail "kadmin.local getpols"
+	}
+    }
+    set k_stat [wait -i $spawn_id]
+    verbose "wait -i $spawn_id returned $k_stat (kadmin addpol)"
+    catch "close -i $spawn_id"
+
+    # Use kinit to get a ticket.
+    if ![kinit krbtest/admin adminpass$KEY 1] {
+	return
+    }
+
+    # Make sure that klist can see the ticket.
+    if ![do_klist "krbtest/admin@$REALMNAME" "krbtgt/$REALMNAME@$REALMNAME" "klist"] {
+	return
+    }
+
+    # Destroy the ticket.
+    spawn $KDESTROY -5
+    if ![check_exit_status "kdestroy"] {
+	return
+    }
+    pass "kdestroy"
+
+    # Double check that the ticket was destroyed.
+    if ![do_klist_err "klist after destroy"] { return }
+
+    if ![add_random_key foo/bar 1] {
+	return
+    }
+
+    set keytab $tmppwd/fookeytab
+    catch "exec rm -f $keytab"
+
+    modify_principal foo/bar -kvno 252
+    foreach vno {253 254 255 256 257 258} {
+	xst $tmppwd/fookeytab foo/bar
+	do_klist_kt $tmppwd/fookeytab "klist keytab foo/bar vno $vno"
+	kinit_kt "foo/bar" $tmppwd/fookeytab 1 "kt kvno $vno"
+	do_klist "foo/bar" "krbtgt/$REALMNAME@$REALMNAME" "klist kt foo/bar vno $vno"
+	do_kdestroy "kdestroy foo/bar vno $vno"
+	
+	if {[info exists KRBIV] && $KRBIV &&
+	    [regexp {des-cbc-[a-z0-9-]*:v4} [lindex $supported_enctypes 0]]} {
+	    catch "exec rm -f $tmppwd/foosrvtab"
+	    spawn $KTUTIL
+	    expect_after {
+		timeout	{ fail "ktutil converting keytab to srvtab" ; set ok 0 }
+		eof	{ fail "ktutil converting keytab to srvtab" ; set ok 0 }
+	    }
+	    expect "ktutil: "
+	    send "rkt $tmppwd/fookeytab\r"
+	    expect -ex "rkt $tmppwd/fookeytab\r"
+	    expect "ktutil: "
+# for debugging, just log this
+#	    send "list\r"
+#	    expect "ktutil: "
+	    #
+	    send "wst $tmppwd/foosrvtab\r"
+	    expect -ex "wst $tmppwd/foosrvtab\r"
+	    expect "ktutil: "
+# for debugging, just log this
+#	    send "clear\r"
+#	    expect "ktutil: "
+#	    send "rst $tmppwd/foosrvtab\r"
+#	    expect "ktutil: "
+#	    send "list\r"
+#	    expect "ktutil: "
+	    # okay, now quit and finish testing
+	    send "quit\r"
+	    expect eof
+	    catch expect_after
+	    if [check_exit_status "ktutil converting keytab to srvtab (vno $vno)"] {
+		pass "ktutil converting keytab to srvtab (vno $vno)"
+		do_klist_kt $tmppwd/fookeytab "klist srvtab foo/bar vno $vno"
+		kinit_kt "foo/bar" "SRVTAB:$tmppwd/foosrvtab" 1 "st kvno $vno"
+		do_klist "foo/bar" "krbtgt/$REALMNAME@$REALMNAME" "klist st foo/bar vno $vno"
+		do_kdestroy "kdestroy st foo/bar vno $vno"
+	    }
+	} else {
+	    verbose "skipping v5kinit/srvtab tests because of non-v4 enctype"
+	}
+    }
+    catch "exec rm -f $keytab"
+    # Check that kadmin.local can actually read the correct kvno, even
+    # if we don't expect kadmin to be able to.
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    set ok 1
+    expect_after {
+	timeout		{ fail "kadmin.local correct high kvno" ; set ok 0 }
+	eof		{ fail "kadmin.local correct high kvno" ; set ok 0 }
+    }
+    expect "kadmin.local: "
+    send "getprinc foo/bar\r"
+#    exec sleep 10
+    expect "Key: vno $vno,"
+    send "quit\r"
+    expect eof
+    if [check_exit_status "kadmin.local examine foo/bar for high kvno"] {
+	if $ok {
+	    pass "kadmin.local correct high kvno"
+	}
+    }
+
+    if { $mode == "tcp" } {
+	set response {}
+	set got_response 0
+	set kdcsock ""
+	catch {
+	    send_log "connecting to $hostname [expr 3 + $portbase]\n"
+	    set kdcsock [socket $hostname [expr 3 + $portbase]]
+	    fconfigure $kdcsock -encoding binary -blocking 0 -buffering none
+	    puts -nonewline $kdcsock [binary format H* ffffffff]
+	    # XXX
+	    sleep 3
+	    set response [read $kdcsock]
+	    set got_response 1
+	} msg
+	if [string length $kdcsock] { catch "close $kdcsock" }
+	if $got_response {
+#	send_log [list sent length -1, got back $response]
+#	send_log "\n"
+	    if [string length $response]>10 {
+		pass "too-long TCP request"
+	    } else {
+		send_log "response too short\n"
+		fail "too-long TCP request"
+	    }
+	} else {
+	    send_log "too-long connect/exchange failure: $msg\n"
+	    fail "too-long TCP request"
+	}
+    }
+}
+
+set status [catch doit msg]
+
+stop_kerberos_daemons
+
+if { $status != 0 } {
+    send_error "ERROR: error in standalone.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/v4gssftp.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/v4gssftp.exp
new file mode 100644
index 000000000..6353dc41f
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/v4gssftp.exp
@@ -0,0 +1,505 @@
+# Kerberos ftp test.
+# This is a DejaGnu test script.
+# This script tests Kerberos ftp.
+# Originally written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+# Modified bye Ezra Peisach for GSSAPI support.
+
+# Find the programs we need.  We use the binaries from the build tree
+# if they exist.  If they do not, then they must be in PATH.  We
+# expect $objdir to be .../kerberos/build/tests/dejagnu
+
+if ![info exists FTP] {
+    set FTP [findfile $objdir/../../appl/gssftp/ftp/ftp]
+}
+
+if ![info exists FTPD] {
+    set FTPD [findfile $objdir/../../appl/gssftp/ftpd/ftpd]
+}
+
+# If we do not have what is for a V4 test - return
+if ![v4_compatible_enctype] {
+    return
+}
+
+# Make sure .klogin is reasonable.
+if ![check_k5login ftp] {
+    return
+}
+
+if ![check_klogin ftp] {
+    return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+    || ![setup_kerberos_files] \
+    || ![setup_kerberos_env] \
+    || ![setup_kerberos_db 0]} {
+    return
+}
+
+# A procedure to start up the ftp daemon.
+
+proc start_ftp_daemon { } {
+    global FTPD
+    global tmppwd
+    global ftpd_spawn_id
+    global ftpd_pid
+    global portbase
+
+    # The -p argument tells it to accept a single connection, so we
+    # don't need to use inetd.  Portbase+8 is the port to listen at.
+    # We rely on KRB5_KTNAME being set to the proper keyfile as there is
+    # no way to cleanly set it with the gssapi API.
+    # The -U argument tells it to use an alternate ftpusers file (using
+    # /dev/null will allow root to login regardless of /etc/ftpusers).
+    # The -a argument requires authorization, to mitigate any
+    # vulnerability introduced by circumventing ftpusers.
+    spawn $FTPD -p [expr 8 + $portbase] -a -U /dev/null -r $tmppwd/krb.conf
+    set ftpd_spawn_id $spawn_id
+    set ftpd_pid [exp_pid]
+
+    # Give the ftp daemon a few seconds to get set up.
+    sleep 2
+}
+
+# A procedure to stop the ftp daemon.
+
+proc stop_ftp_daemon { } {
+    global ftpd_spawn_id
+    global ftpd_pid
+
+    if [info exists ftpd_pid] {
+	catch "close -i $ftpd_spawn_id"
+	catch "exec kill $ftpd_pid"
+	catch "wait -i $ftpd_spawn_id"
+	unset ftpd_pid
+    }
+}
+
+# Create a file to use for ftp testing.
+set file [open $tmppwd/ftp-test w]
+puts $file "This file is used for ftp testing."
+close $file
+
+# Create a large file to use for ftp testing. File needs to be 
+# larger that 2^20 or 1MB for PBSZ testing.
+set file [open $tmppwd/bigftp-test w]
+puts $file "This file is used for ftp testing.\n"
+seek $file 1048576 current
+puts $file "This file is used for ftp testing."
+close $file
+
+# Test that a file was copied correctly.
+proc check_file { filename {bigfile 0}} {
+    if ![file exists $filename] {
+	verbose "$filename does not exist"
+	send_log "$filename does not exist\n"
+	return 0
+    }
+
+    set file [open $filename r]
+    if { [gets $file line] == -1 } {
+	verbose "$filename is empty"
+	send_log "$filename is empty\n"
+	close $file
+	return 0
+    }
+
+    if ![string match "This file is used for ftp testing." $line] {
+	verbose "$filename contains $line"
+	send_log "$filename contains $line\n"
+	close $file
+	return 0
+    }
+
+    if {$bigfile} {
+	# + 1 for the newline
+	seek $file 1048577 current
+	if { [gets $file line] == -1 } {
+	    verbose "$filename is truncated"
+	    send_log "$filename is truncated\n"
+	    close $file
+	    return 0
+	}
+
+	if ![string match "This file is used for ftp testing." $line] {
+	    verbose "$filename contains $line"
+	    send_log "$filename contains $line\n"
+	    close $file
+	    return 0
+	}
+    }
+
+    if { [gets $file line] != -1} {
+	verbose "$filename is too long ($line)"
+	send_log "$filename is too long ($line)\n"
+	close $file
+	return 0
+    }
+
+    close $file
+
+    return 1
+}
+
+#
+# Restore environment variables possibly set.
+#
+proc ftp_restore_env { } {
+    global env
+    global ftp_save_ktname
+    global ftp_save_ccname
+
+    catch "unset env(KRB5_KTNAME)"
+    if [info exists ftp_save_ktname] {
+	set env(KRB5_KTNAME) $ftp_save_ktname
+	unset ftp_save_ktname
+    }
+
+    catch "unset env(KRB5CCNAME)"
+    if [info exists ftp_save_ccname] {
+	set env(KRB5CCNAME) $ftp_save_ccname
+	unset ftp_save_ccname
+    }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc v4ftp_test { } {
+    global FTP
+    global KEY
+    global REALMNAME
+    global hostname
+    global localhostname
+    global env
+    global ftpd_spawn_id
+    global ftpd_pid
+    global spawn_id
+    global tmppwd
+    global ftp_save_ktname
+    global ftp_save_ccname
+    global des3_krbtgt
+    global portbase
+
+    if {$des3_krbtgt} {
+	return
+    }
+    # Start up the kerberos and kadmind daemons and get a srvtab and a
+    # ticket file.
+    if {![start_kerberos_daemons 0] \
+        || ![add_random_key ftp/$hostname 0] \
+        || ![setup_srvtab 0 ftp] \
+	|| ![add_kerberos_key $env(USER) 0] \
+	|| ![v4kinit $env(USER) $env(USER)$KEY 0]} {
+	return
+    }
+
+    #
+    # Save settings of KRB5_KTNAME
+    #
+    if [info exists env(KRB5_KTNAME)] {
+	set ftp_save_ktname $env(KRB5_KTNAME)
+    }
+
+    #
+    # set KRB5_KTNAME
+    #
+    set env(KRB5_KTNAME) FILE:$tmppwd/srvtab
+    verbose "KRB5_KTNAME=$env(KRB5_KTNAME)"
+
+    #
+    # Save settings of KRB5CCNAME
+    # These tests fail if the krb5 cache happens to have a valid credential
+    # which can result from running the gssftp.exp test immediately
+    # preceeding these tests.
+    #
+    if [info exists env(KRB5CCNAME)] {
+	set ftp_save_ccname $env(KRB5CCNAME)
+    }
+
+    #
+    # set KRB5_KTNAME
+    #
+    set env(KRB5CCNAME) FILE:$tmppwd/non-existant-cache
+    verbose "KRB5CCNAME=$env(KRB5CCNAME)"
+
+    # Start the ftp daemon.
+    start_ftp_daemon
+
+    # Make an ftp client connection to it.
+    spawn $FTP $hostname [expr 8 + $portbase]
+
+    expect_after {
+	timeout {
+	    fail "$testname (timeout)"
+	    catch "expect_after"
+	    return
+	}
+	eof {
+	    fail "$testname (eof)"
+	    catch "expect_after"
+	    return
+	}
+    }
+
+    set testname "ftp connection(v4)"
+    expect -nocase "connected to $hostname"
+    expect -nocase -re "$localhostname.*ftp server .version \[0-9.\]*. ready."
+    expect -re "Using authentication type GSSAPI; ADAT must follow"
+    expect "GSSAPI accepted as authentication type"
+    expect -re "GSSAPI error major: (Unspecified GSS|Miscellaneous) failure"
+    expect {
+	"GSSAPI error minor: Unsupported credentials cache format version number" {}
+	"GSSAPI error minor: No credentials cache found" {}
+	"GSSAPI error minor: Decrypt integrity check failed" {}
+    }
+    expect "GSSAPI error: initializing context"
+    expect "GSSAPI authentication failed"
+    expect -re "Using authentication type KERBEROS_V4; ADAT must follow"
+    expect {
+	"Kerberos V4 authentication succeeded" { pass "ftp authentication" }
+	eof	{ fail "ftp authentication" ; catch "expect_after" ; return }
+	-re "Kerberos V4 .* failed.*\r" {
+	    fail "ftp authentication";
+	    send "quit\r"; catch "expect_after";
+	    return
+	}
+    }
+    expect -nocase "name ($hostname:$env(USER)): "
+    send "$env(USER)\r"
+    expect "Kerberos user $env(USER)@$REALMNAME is authorized as $env(USER)"
+    expect "Remote system type is UNIX."
+    expect "Using binary mode to transfer files."
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "binary(v4)"
+    send "binary\r"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "status(v4)"
+    send "status\r"
+    expect -nocase "connected to $hostname."
+    expect "Authentication type: KERBEROS_V4"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "ls(v4)"
+    send "ls $tmppwd/ftp-test\r"
+    expect -re "Opening ASCII mode data connection for .*ls."
+    expect -re ".* $tmppwd/ftp-test"
+    expect "ftp> " {
+	pass $testname
+    } 
+
+    set testname "nlist(v4)"
+    send "nlist $tmppwd/ftp-test\r"
+    expect -re "Opening ASCII mode data connection for file list."
+    expect -re "$tmppwd/ftp-test"
+    expect -re ".* Transfer complete."
+    expect "ftp> " {
+	pass $testname
+    } 
+
+    set testname "ls missing(v4)"
+    send "ls $tmppwd/ftp-testmiss\r"
+    expect -re "Opening ASCII mode data connection for .*ls."
+    expect {
+	-re "$tmppwd/ftp-testmiss not found" {}
+	-re "$tmppwd/ftp-testmiss: No such file or directory"
+    }
+    expect "ftp> " {
+	pass $testname
+    } 
+
+
+    set testname "get(v4)"
+    catch "exec rm -f $tmppwd/copy"
+    send "get $tmppwd/ftp-test $tmppwd/copy\r"
+    expect "Opening BINARY mode data connection for $tmppwd/ftp-test"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "put(v4)"
+    catch "exec rm -f $tmppwd/copy"
+    send "put $tmppwd/ftp-test $tmppwd/copy\r"
+    expect "Opening BINARY mode data connection for $tmppwd/copy"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes sent in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "cd(v4)"
+    send "cd $tmppwd\r"
+    expect "CWD command successful."
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "lcd(v4)"
+    send "lcd $tmppwd\r"
+    expect "Local directory now $tmppwd"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "local get(v4)"
+    catch "exec rm -f $tmppwd/copy"
+    send "get ftp-test copy\r"
+    expect "Opening BINARY mode data connection for ftp-test"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "big local get(v4)"
+    catch "exec rm -f $tmppwd/copy"
+    send "get bigftp-test copy\r"
+    expect "Opening BINARY mode data connection for bigftp-test"
+    expect "Transfer complete"
+    expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+    expect "ftp> "
+    if [check_file $tmppwd/copy 1] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "start encryption(v4)"
+    send "private\r"
+    expect "Data channel protection level set to private"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "status(v4)"
+    send "status\r"
+    expect "Protection Level: private"
+    expect "ftp> " {
+	pass $testname
+    }
+
+    set testname "encrypted get(v4)"
+    catch "exec rm -f $tmppwd/copy"
+    send "get ftp-test copy\r"
+    expect "Opening BINARY mode data connection for ftp-test"
+    expect "Transfer complete"
+    expect {
+	-re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds" {}
+	-re "krb_rd_priv failed for KERBEROS_V4" {
+	    fail $testname
+	    send "quit\r"
+	    catch "expect_after"
+	    return
+	}
+    }
+    expect "ftp> "
+    if [check_file $tmppwd/copy] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+
+    # Test a large file that will overflow PBSZ size
+    set testname "big encrypted get(v4)"
+    catch "exec rm -f $tmppwd/copy"
+    send "get bigftp-test copy\r"
+    expect "Opening BINARY mode data connection for bigftp-test"
+    expect "Transfer complete"
+    expect {
+	-re "\[0-9\]+ bytes received in \[0-9.e+-\]+ seconds" {}
+	-re "krb_rd_priv failed for KERBEROS_V4" {
+	    fail $testname
+	    send "quit\r"
+	    catch "expect_after"
+	    return
+	}
+    }
+    expect "ftp> "
+    if [check_file $tmppwd/copy 1] {
+	pass $testname
+    } else {
+	fail $testname
+    }
+
+    set testname "close(v4)"
+    send "close\r"
+    expect "Goodbye."
+    expect "ftp> "
+    set status_list [wait -i $ftpd_spawn_id]
+    verbose "wait -i $ftpd_spawn_id returned $status_list ($testname)"
+    catch "close -i $ftpd_spawn_id"
+    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
+	send_log "exit status: $status_list\n"
+	verbose "exit status: $status_list"
+	fail $testname
+    } else {
+	pass $testname
+	unset ftpd_pid
+    }
+
+    set testname "quit(v4)"
+    send "quit\r"
+    expect_after
+    expect eof
+    if [check_exit_status $testname] {
+	pass $testname
+    }
+
+}
+
+# The ftp client will look in $HOME/.netrc for the user name to use.
+# To avoid confusing the testsuite, point $HOME at a directory where
+# we know there is no .netrc file.
+if [info exists env(HOME)] {
+    set home $env(HOME)
+} elseif [info exists home] {
+    unset home
+}
+set env(HOME) $tmppwd
+
+# Run the test.  Logging in sometimes takes a while, so increase the
+# timeout.
+set oldtimeout $timeout
+set timeout 60
+set status [catch v4ftp_test msg]
+set timeout $oldtimeout
+
+# Shut down the kerberos daemons and the ftp daemon.
+stop_kerberos_daemons
+
+stop_ftp_daemon
+
+ftp_restore_env
+
+# Reset $HOME, for safety in case we are going to run more tests.
+if [info exists home] {
+    set env(HOME) $home
+} else {
+    unset env(HOME)
+}
+
+if { $status != 0 } {
+    perror "error in v4gssftp.exp: $msg"
+}
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/v4krb524d.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/v4krb524d.exp
new file mode 100644
index 000000000..d78f14ba3
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/v4krb524d.exp
@@ -0,0 +1,168 @@
+# Standalone Kerberos test.
+# This is a DejaGnu test script.
+# This script tests that the Kerberos tools can talk to each other.
+
+# This mostly just calls procedures in testsuite/config/default.exp.
+
+if ![info exists K524INIT] {
+    set K524INIT [findfile $objdir/../../krb524/k524init]
+}
+
+if ![info exists KRB524D] {
+    set KRB524D [findfile $objdir/../../krb524/krb524d]
+}
+
+if ![info exists KLIST] {
+    set KLIST [findfile $objdir/../../clients/klist/klist]
+}
+
+if ![info exists KDESTROY] {
+    set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
+}
+
+# Set up the Kerberos files and environment.
+if {![get_hostname] || ![setup_kerberos_files] || ![setup_kerberos_env]} {
+    return
+}
+
+# If we do not have what is for a V4 test - return
+if ![v4_compatible_enctype] {
+    return
+}
+
+# Initialize the Kerberos database.  The argument tells
+# setup_kerberos_db that it is being called from here.
+if ![setup_kerberos_db 1] {
+    return
+}
+
+# A procedure to stop the krb524 daemon.
+proc start_k524_daemon { } {
+    global KRB524D
+    global k524d_spawn_id
+    global k524d_pid
+    global REALMNAME
+    global portbase
+
+    spawn $KRB524D -m -p [expr 7 + $portbase] -r $REALMNAME -nofork
+    set k524d_spawn_id $spawn_id
+    set k524d_pid [exp_pid]
+
+    # Give the krb524d daemon a few seconds to get set up.
+    sleep 2
+}
+
+# A procedure to stop the krb524 daemon.
+proc stop_k524_daemon { } {
+    global k524d_spawn_id
+    global k524d_pid
+
+    if [info exists k524d_pid] {
+	catch "close -i $k524d_spawn_id"
+	catch "exec kill $k524d_pid"
+	catch "wait -i $k524d_spawn_id"
+	unset k524d_pid
+    }
+}
+
+# We are about to start up a couple of daemon processes.  We do all
+# the rest of the tests inside a proc, so that we can easily kill the
+# processes when the procedure ends.
+
+proc doit { } {
+    global env
+    global KEY
+    global K524INIT
+    # To pass spawn_id to the wait process
+    global spawn_id
+    global KLIST
+    global KDESTROY
+    global tmppwd
+    global REALMNAME
+    global des3_krbtgt
+
+    if {$des3_krbtgt} {
+	return
+    }
+    # Start up the kerberos and kadmind daemons.
+    if ![start_kerberos_daemons 1] {
+	return
+    }
+
+    # Add a user key and get a V5 ticket
+    if {![add_kerberos_key $env(USER) 0] \
+	|| ![kinit $env(USER) $env(USER)$KEY 0]} {
+	return
+    }
+
+    # Start the krb524d daemon.
+    start_k524_daemon
+
+    # The k524init program does not advertise anything on success -
+    #only failure.
+    spawn $K524INIT
+    expect {
+	-timeout 10 
+	-re "k524init: .*\r" {
+	    fail "k524init"
+	    return
+	}
+	eof {}
+	timeout {}
+    }
+
+
+    if ![check_exit_status "k524init"] {
+	return
+    }
+    pass "k524init"
+
+    # Make sure that klist can see the ticket.
+    spawn $KLIST -4
+    expect {
+	-re "Kerberos 4 ticket cache:\[ 	\]*(.+:)?$tmppwd/tkt.*Principal:\[ 	\]*$env(USER)@$REALMNAME.*krbtgt\.$REALMNAME@$REALMNAME\r\n" {
+	    verbose "klist started"
+	}
+	timeout {
+	    fail "v4klist"
+	    return
+	}
+	eof {
+	    fail "v4klist"
+	    return
+	}
+    }
+
+    expect {
+        "\r" { }
+	eof { }
+    }
+
+    if ![check_exit_status "klist"] {
+	return
+    }
+    pass "krb524d: v4klist"
+
+    # Destroy the ticket.
+    spawn $KDESTROY -4
+    if ![check_exit_status "kdestroy"] {
+	return
+    }
+    pass "krb524d: v4kdestroy"
+
+    pass "krb524d: krb524d"
+}
+
+set status [catch doit msg]
+
+stop_kerberos_daemons
+
+stop_k524_daemon
+
+if { $status != 0 } {
+    send_error "ERROR: error in v4krb524d.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
+
+
diff --git a/krb5-1-6/src/tests/dejagnu/krb-standalone/v4standalone.exp b/krb5-1-6/src/tests/dejagnu/krb-standalone/v4standalone.exp
new file mode 100644
index 000000000..cc42e8dab
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/krb-standalone/v4standalone.exp
@@ -0,0 +1,95 @@
+# Standalone Kerberos test.
+# This is a DejaGnu test script.
+# This script tests that the Kerberos tools can talk to each other.
+
+# This mostly just calls procedures in testsuite/config/default.exp.
+
+# Set up the Kerberos files and environment.
+if {![get_hostname] || ![setup_kerberos_files] || ![setup_kerberos_env]} {
+    return
+}
+
+# If we do not have what is for a V4 test - return
+if ![v4_compatible_enctype] {
+    return
+}
+
+# Initialize the Kerberos database.  The argument tells
+# setup_kerberos_db that it is being called from here.
+if ![setup_kerberos_db 1] {
+    return
+}
+
+# We are about to start up a couple of daemon processes.  We do all
+# the rest of the tests inside a proc, so that we can easily kill the
+# processes when the procedure ends.
+
+proc check_and_destroy_v4_tix { client server } {
+    global REALMNAME
+    global des3_krbtgt
+
+    # Skip this if we're using a des3 TGT, since that's supposed to fail.
+    if {$des3_krbtgt} {
+	return
+    }
+    # Make sure that klist can see the ticket.
+    if ![v4klist "$client" "$server" "v4klist"] {
+	return
+    }
+
+    # Destroy the ticket.
+    if ![v4kdestroy "v4kdestroy"] {
+	return
+    }
+
+    if ![v4klist_none "v4klist no tix 1"] {
+	return
+    }
+}
+
+proc doit { } {
+    global REALMNAME
+    global KLIST
+    global KDESTROY
+    global KEY
+    global hostname
+    global spawn_id
+    global tmppwd
+
+    # Start up the kerberos and kadmind daemons.
+    if ![start_kerberos_daemons 1] {
+	return
+    }
+
+    # Use kadmin to add an host key.
+    if ![add_random_key host/$hostname 1] {
+	return
+    }
+
+    # Use ksrvutil to create a srvtab entry.
+    if ![setup_srvtab 1] {
+	return
+    }
+
+    # Use kinit to get a ticket.
+    if [v4kinit krbtest.admin adminpass$KEY 1] {
+	check_and_destroy_v4_tix krbtest.admin@$REALMNAME krbtgt.$REALMNAME@$REALMNAME
+    }
+
+    # Use kinit with srvtab to get a ticket.
+    # XXX - Currently kinit doesn't support "-4 -k"!
+#    set shorthost [string range $hostname 0 [expr [string first . $hostname] - 1]]
+#    if [v4kinit_kt host.$shorthost SRVTAB:$tmppwd/srvtab 1] {
+#	check_and_destroy_v4_tix host.$shorthost@$REALMNAME krbtgt.$REALMNAME@$REALMNAME
+#    }
+}
+
+set status [catch doit msg]
+
+stop_kerberos_daemons
+
+if { $status != 0 } {
+    send_error "ERROR: error in v4standalone.exp\n"
+    send_error "$msg\n"
+    exit 1
+}
diff --git a/krb5-1-6/src/tests/dejagnu/t_inetd.c b/krb5-1-6/src/tests/dejagnu/t_inetd.c
new file mode 100644
index 000000000..80835b58b
--- /dev/null
+++ b/krb5-1-6/src/tests/dejagnu/t_inetd.c
@@ -0,0 +1,139 @@
+/*
+ * tests/dejagnu/t_inetd.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * A simple program to simulate starting a process from inetd.
+ *
+ * Unlike a proper inetd situation, environment variables are passed 
+ * to the client.
+ *
+ * usage: t_inetd port program argv0 ...
+ *		
+ */
+
+
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "com_err.h"
+
+
+char *progname;
+
+static void usage()
+{
+	fprintf(stderr, "%s: port program argv0 argv1 ...\n", progname);
+	exit(1);
+}
+
+int
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+	unsigned short port;
+	char *path;
+	int sock, acc;
+	int one = 1;
+	struct sockaddr_in l_inaddr, f_inaddr;	/* local, foreign address */
+	int namelen = sizeof(f_inaddr);
+#ifdef POSIX_SIGNALS
+	struct sigaction csig;
+#endif
+
+	progname = argv[0];
+
+	if(argc <= 3) usage();
+
+	if(atoi(argv[1]) == 0) usage();
+
+	port = htons(atoi(argv[1]));
+	path = argv[2];
+
+	if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+	    com_err(progname, errno, "creating socket");
+	    exit(3);
+	}
+
+	(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
+			  sizeof (one));
+
+	l_inaddr.sin_family = AF_INET;
+	l_inaddr.sin_addr.s_addr = 0;
+	l_inaddr.sin_port = port;
+
+	if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) {
+	    com_err(progname, errno, "binding socket");
+	    exit(3);
+	}
+
+	if (listen(sock, 1) == -1) {
+	    com_err(progname, errno, "listening");
+	    exit(3);
+	}
+
+	if ((acc = accept(sock, (struct sockaddr *)&f_inaddr,
+			  &namelen)) == -1) {
+	    com_err(progname, errno, "accepting");
+	    exit(3);
+	}
+
+	dup2(acc, 0);
+	dup2(acc, 1);
+	dup2(acc, 2);
+	close(sock);
+	sock = 0;
+
+	/* Don't wait for a child signal... Otherwise dejagnu gets confused */
+#ifdef POSIX_SIGNALS
+	csig.sa_handler = (RETSIGTYPE (*)())0;
+	sigemptyset(&csig.sa_mask);
+	csig.sa_flags = 0;
+	sigaction(SIGCHLD, &csig, (struct sigaction *)0);
+#else
+	signal(SIGCHLD, SIG_IGN);
+#endif
+
+	if(execv(path, &argv[3]))
+		fprintf(stderr, "t_inetd: Could not exec %s\n", path);
+	exit(1);
+}
+
diff --git a/krb5-1-6/src/tests/dump.c b/krb5-1-6/src/tests/dump.c
new file mode 100644
index 000000000..1e40ffeda
--- /dev/null
+++ b/krb5-1-6/src/tests/dump.c
@@ -0,0 +1,43 @@
+/*
+ * tests/dump.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Dump out a krb5_data to stderr (for debugging purposes).
+ */
+
+#include <stdio.h>
+#include "krb5.h"
+
+void dump_data (data)
+    krb5_data *data;
+{
+    unsigned char *ptr = (unsigned char *)data->data;
+    int i;
+    for (i=0; i<data->length; i++) {
+	fprintf(stderr, "%02x ", ptr[i]);
+	if ((i % 16) == 15) fprintf(stderr, "\n");
+    }
+    fprintf(stderr, "\n");    
+}
diff --git a/krb5-1-6/src/tests/gss-threads/Makefile.in b/krb5-1-6/src/tests/gss-threads/Makefile.in
new file mode 100644
index 000000000..b95cbcd1b
--- /dev/null
+++ b/krb5-1-6/src/tests/gss-threads/Makefile.in
@@ -0,0 +1,54 @@
+# Derived from appl/gss-sample, January 2005.
+
+thisconfigdir=./..
+myfulldir=tests/gss-threads
+mydir=gss-threads
+BUILDTOP=$(REL)..$(S)..
+DEFINES = -DUSE_AUTOCONF_H -DGSSAPI_V2
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+PTHREAD_LIBS=@PTHREAD_LIBS@
+
+SRCS= $(srcdir)/gss-client.c $(srcdir)/gss-misc.c $(srcdir)/gss-server.c
+
+OBJS= gss-client.o gss-misc.o gss-server.o
+
+all-unix:: all-unix-@THREAD_SUPPORT@
+all-unix-1:: gss-server gss-client
+all-unix-0::
+all-windows:: $(OUTPRE)gss-server.exe $(OUTPRE)gss-client.exe
+
+gss-server: gss-server.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) $(PTHREAD_CFLAGS) -o gss-server gss-server.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS)
+
+gss-client: gss-client.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) $(PTHREAD_CFLAGS) -o gss-client gss-client.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS)
+
+$(OUTPRE)gss-server.exe: $(OUTPRE)gss-server.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB)
+	link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib
+
+$(OUTPRE)gss-client.exe: $(OUTPRE)gss-client.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB)
+	link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib
+
+clean-unix::
+	$(RM) gss-server gss-client
+
+install-unix::
+#	$(INSTALL_PROGRAM) gss-client $(DESTDIR)$(CLIENT_BINDIR)/gss-tclient
+#	$(INSTALL_PROGRAM) gss-server $(DESTDIR)$(SERVER_BINDIR)/gss-tserver
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)gss-client.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h gss-client.c gss-misc.h
+$(OUTPRE)gss-misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  gss-misc.c gss-misc.h
+$(OUTPRE)gss-server.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
+  $(SRCTOP)/include/port-sockets.h gss-misc.h gss-server.c
diff --git a/krb5-1-6/src/tests/gss-threads/README b/krb5-1-6/src/tests/gss-threads/README
new file mode 100644
index 000000000..f555b3e3a
--- /dev/null
+++ b/krb5-1-6/src/tests/gss-threads/README
@@ -0,0 +1,165 @@
+[Out of date; needs updating for thread safety test support.  -- KR 2005-02-09]
+
+# Copyright 1993 by OpenVision Technologies, Inc.
+# 
+# Permission to use, copy, modify, distribute, and sell this software
+# and its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appears in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of OpenVision not be used
+# in advertising or publicity pertaining to distribution of the software
+# without specific, written prior permission. OpenVision makes no
+# representations about the suitability of this software for any
+# purpose.  It is provided "as is" without express or implied warranty.
+# 
+# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+This directory contains a sample GSS-API client and server
+application.  In addition to serving as an example of GSS-API
+programming, this application is also intended to be a tool for
+testing the performance of GSS-API implementations.
+
+Each time the client is invoked, it performs one or more exchanges
+with the server.  Each exchange with the server consists primarily of
+the following steps:
+
+	1. A TCP/IP connection is established.
+
+	2. (optional, on by default) The client and server establish a
+	   GSS-API context, and the server prints the identify of the
+	   client.
+
+      /	3. The client sends a message to the server.  The message may
+     /     be plaintext, cryptographically "signed" but not encrypted,
+     |     or encrypted (default).
+     |
+0 or |  4. The server decrypts the message (if necessary), verifies
+more |     its signature (if there is one) and prints it.
+times|
+     |  5. The server sends either a signature block (the default) or an
+     |     empty token back to the client to acknowledge the message.
+     \
+      \ 6. If the server sent a signature block, the client verifies
+           it and prints a message indicating that it was verified.
+  
+	7. The client sends an empty block to the server to tell it
+	   that the exchange is finished.
+  
+	8. The client and server close the TCP/IP connection and
+	   destroy the GSS-API context.
+
+The client also supports the -v1 flag which uses an older exchange
+format compatible with previous releases of Kerberos and with samples
+shipped in the Microsoft SDK.
+  
+The server's command line usage is
+  
+	gss-server [-port port] [-verbose] [-once] [-inetd] [-export]
+		[-logfile file] service_name
+  
+where service_name is a GSS-API service name of the form
+"service@host" (or just "service", in which case the local host name
+is used).  The command-line options have the following meanings:
+  
+-port	The TCP port on which to accept connections.  Default is 4444.
+  
+-once	Tells the server to exit after a single exchange, rather than
+	persisting.
+  
+-inetd	Tells the server that it is running out of inetd, so it should
+	interact with the client on stdin rather than binding to a
+	network port.  Implies "-once".
+  
+-export	Tells the server to test the gss_export_sec_context function
+	after establishing a context with a client.
+
+-logfile
+	The file to which the server should append its output, rather
+	than sending it to stdout.
+  
+The client's command line usage is
+
+	gss-client [-port port] [-mech mechanism] [-d] [-f] [-q]
+        [-seq] [-noreplay] [-nomutual]		
+        [-ccount count] [-mcount count] [-na] [-nw] [-nx] [-nm]
+		host service_name msg
+
+where host is the host running the server, service_name is the service
+name that the server will establish connections as (if you don't
+specify the host name in the service name when running gss-server, and
+it's running on a different machine from gss-client, make sure to
+specify the server's host name in the service name you specify to
+gss-client!) and msg is the message.  The command-line options have
+the following meanings:
+
+-port	The TCP port to which to connect.  Default is 4444.
+
+-mech	The OID of the GSS-API mechanism to use.
+
+-d	Tells the client to delegate credentials to the server.  For
+	the Kerberos GSS-API mechanism, this means that a forwardable
+	TGT will be sent to the server, which will put it in its
+	credential cache (you must have acquired your tickets with
+	"kinit -f" for this to work).
+
+-seq Tells the client to enforce ordered message delivery via
+    sequencing.  
+
+-noreplay Tells the client to disable the use of replay
+    detection.
+
+-nomutual Tells the client to disable the use of mutual authentication.
+
+-f	Tells the client that the "msg" argument is actually the name
+	of a file whose contents should be used as the message.
+
+-q	Tells the client to be quiet, i.e., to only print error
+	messages.
+
+-ccount	Specifies how many sessions the client should initiate with
+	the server (the "connection count").
+
+-mcount	Specifies how many times the message should be sent to the
+	server in each session (the "message count").
+
+-na	Tells the client not to do any authentication with the
+	server.  Implies "-nw", "-nx" and "-nm".
+
+-nw	Tells the client not to "wrap" messages.  Implies "-nx".
+
+-nx	Tells the client not to encrypt messages.
+
+-nm	Tells the client not to ask the server to send back a
+	cryptographic checksum ("MIC").
+
+To run the server on a host, you need to make sure that the principal
+corresponding to service_name is in the default keytab on the server
+host, and that the gss-server process can read the keytab.  For
+example, the service name "host@server" corresponds to the Kerberos
+principal "host/server.domain.com@REALM".
+
+This sample application uses the following GSS-API functions:
+
+	gss_accept_sec_context		gss_inquire_names_for_mech
+	gss_acquire_cred		gss_oid_to_str
+	gss_delete_sec_context		gss_release_buffer
+	gss_display_name		gss_release_cred
+	gss_display_status		gss_release_name
+	gss_export_sec_context		gss_release_oid
+	gss_get_mic			gss_release_oid_set
+	gss_import_name			gss_str_to_oid
+	gss_import_sec_context		gss_unwrap
+	gss_init_sec_context		gss_verify_mic
+	gss_inquire_context		gss_wrap
+  
+This application was originally written by Barry Jaspan of OpenVision
+Technologies, Inc.  It was updated significantly by Jonathan Kamens of
+OpenVision Technologies, Inc.
+
+$Id$
diff --git a/krb5-1-6/src/tests/gss-threads/gss-client.c b/krb5-1-6/src/tests/gss-threads/gss-client.c
new file mode 100644
index 000000000..f199dc252
--- /dev/null
+++ b/krb5-1-6/src/tests/gss-threads/gss-client.c
@@ -0,0 +1,883 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock.h>
+#else
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pthread.h>
+#endif
+
+#include <gssapi/gssapi_generic.h>
+#include "gss-misc.h"
+#include "port-sockets.h"
+#include "fake-addrinfo.h"
+
+static int verbose = 1;
+
+static void usage()
+{
+     fprintf(stderr, "Usage: gss-client [-port port] [-mech mechanism] [-d]\n");
+     fprintf(stderr, "       [-seq] [-noreplay] [-nomutual]");
+     fprintf(stderr, " [-threads num]");
+     fprintf(stderr, "\n");
+     fprintf(stderr, "       [-f] [-q] [-ccount count] [-mcount count]\n");
+     fprintf(stderr, "       [-v1] [-na] [-nw] [-nx] [-nm] host service msg\n");
+     exit(1);
+}
+
+/*
+ * Function: get_server_info
+ *
+ * Purpose: Sets up a socket address for the named host and port.
+ *
+ * Arguments:
+ *
+ * 	host		(r) the target host name
+ * 	port		(r) the target port, in host byte order
+ *
+ * Returns: 0 on success, or -1 on failure
+ *
+ * Effects:
+ *
+ * The host name is resolved with gethostbyname(), and "saddr" is set
+ * to the desired socket address.  If an error occurs, an error
+ * message is displayed and -1 is returned.
+ */
+struct sockaddr_in saddr;
+static int get_server_info(host, port)
+    char *host;
+    u_short port;
+{
+     struct hostent *hp;
+
+     if ((hp = gethostbyname(host)) == NULL) {
+	  fprintf(stderr, "Unknown host: %s\n", host);
+	  return -1;
+     }
+     
+     saddr.sin_family = hp->h_addrtype;
+     memcpy((char *)&saddr.sin_addr, hp->h_addr, sizeof(saddr.sin_addr));
+     saddr.sin_port = htons(port);
+     return 0;
+}
+
+/*
+ * Function: connect_to_server
+ *
+ * Purpose: Opens a TCP connection to the name host and port.
+ *
+ * Arguments:
+ *
+ * 	host		(r) the target host name
+ * 	port		(r) the target port, in host byte order
+ *
+ * Returns: the established socket file desciptor, or -1 on failure
+ *
+ * Effects:
+ *
+ * The host name is resolved with gethostbyname(), and the socket is
+ * opened and connected.  If an error occurs, an error message is
+ * displayed and -1 is returned.
+ */
+static int connect_to_server()
+{
+    int s;
+
+     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	  perror("creating socket");
+	  return -1;
+     }
+     if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
+	  perror("connecting to server");
+	  (void) closesocket(s);
+	  return -1;
+     }
+     return s;
+}
+
+/*
+ * Function: client_establish_context
+ *
+ * Purpose: establishes a GSS-API context with a specified service and
+ * returns the context handle
+ *
+ * Arguments:
+ *
+ * 	s		    (r) an established TCP connection to the service
+ * 	service_name(r) the ASCII service name of the service
+ *	gss_flags	(r) GSS-API delegation flag (if any)
+ *	auth_flag	(r) whether to actually do authentication
+ *  v1_format   (r) whether the v1 sample protocol should be used
+ *	oid		    (r) OID of the mechanism to use
+ * 	context		(w) the established GSS-API context
+ *	ret_flags	(w) the returned flags from init_sec_context
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * service_name is imported as a GSS-API name and a GSS-API context is
+ * established with the corresponding service; the service should be
+ * listening on the TCP connection s.  The default GSS-API mechanism
+ * is used, and mutual authentication and replay detection are
+ * requested.
+ * 
+ * If successful, the context handle is returned in context.  If
+ * unsuccessful, the GSS-API error messages are displayed on stderr
+ * and -1 is returned.
+ */
+static int client_establish_context(s, service_name, gss_flags, auth_flag,
+				    v1_format, oid, gss_context, ret_flags)
+     int s;
+     char *service_name;
+     gss_OID oid;
+     OM_uint32 gss_flags;
+     int auth_flag;
+     int v1_format;
+     gss_ctx_id_t *gss_context;
+     OM_uint32 *ret_flags;
+{
+     if (auth_flag) {
+       gss_buffer_desc send_tok, recv_tok, *token_ptr;
+       gss_name_t target_name;
+       OM_uint32 maj_stat, min_stat, init_sec_min_stat;
+       int token_flags;
+
+       /*
+	* Import the name into target_name.  Use send_tok to save
+	* local variable space.
+	*/
+       send_tok.value = service_name;
+       send_tok.length = strlen(service_name) ;
+       maj_stat = gss_import_name(&min_stat, &send_tok,
+				  (gss_OID) gss_nt_service_name, &target_name);
+       if (maj_stat != GSS_S_COMPLETE) {
+	 display_status("parsing name", maj_stat, min_stat);
+	 return -1;
+       }
+     
+       if (!v1_format) {
+	 if (send_token(s, TOKEN_NOOP|TOKEN_CONTEXT_NEXT, empty_token) < 0) {
+	   (void) gss_release_name(&min_stat, &target_name);
+	   return -1;
+	 }
+       }
+
+       /*
+	* Perform the context-establishement loop.
+	*
+	* On each pass through the loop, token_ptr points to the token
+	* to send to the server (or GSS_C_NO_BUFFER on the first pass).
+	* Every generated token is stored in send_tok which is then
+	* transmitted to the server; every received token is stored in
+	* recv_tok, which token_ptr is then set to, to be processed by
+	* the next call to gss_init_sec_context.
+	* 
+	* GSS-API guarantees that send_tok's length will be non-zero
+	* if and only if the server is expecting another token from us,
+	* and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
+	* and only if the server has another token to send us.
+	*/
+     
+       token_ptr = GSS_C_NO_BUFFER;
+       *gss_context = GSS_C_NO_CONTEXT;
+
+       do {
+	 maj_stat =
+	   gss_init_sec_context(&init_sec_min_stat,
+				GSS_C_NO_CREDENTIAL,
+				gss_context,
+				target_name,
+				oid,
+				gss_flags,
+				0,
+				NULL,	/* no channel bindings */
+				token_ptr,
+				NULL,	/* ignore mech type */
+				&send_tok,
+				ret_flags,
+				NULL);	/* ignore time_rec */
+
+	 if (token_ptr != GSS_C_NO_BUFFER)
+	   free (recv_tok.value);
+
+	 if (send_tok.length != 0) {
+	   if (verbose)
+	     printf("Sending init_sec_context token (size=%d)...",
+		    (int) send_tok.length);
+	   if (send_token(s, v1_format?0:TOKEN_CONTEXT, &send_tok) < 0) {
+	     (void) gss_release_buffer(&min_stat, &send_tok);
+	     (void) gss_release_name(&min_stat, &target_name);
+	     if (*gss_context != GSS_C_NO_CONTEXT) {
+		 gss_delete_sec_context(&min_stat, gss_context,
+					GSS_C_NO_BUFFER);
+		 *gss_context = GSS_C_NO_CONTEXT;
+	     }
+	     return -1;
+	   }
+	 }
+	 (void) gss_release_buffer(&min_stat, &send_tok);
+ 
+	 if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
+	      display_status("initializing context", maj_stat,
+			     init_sec_min_stat);
+	      (void) gss_release_name(&min_stat, &target_name);
+	      if (*gss_context != GSS_C_NO_CONTEXT)
+		      gss_delete_sec_context(&min_stat, gss_context,
+					     GSS_C_NO_BUFFER);
+	      return -1;
+	 }
+	  
+	 if (maj_stat == GSS_S_CONTINUE_NEEDED) {
+	   if (verbose)
+	     printf("continue needed...");
+	   if (recv_token(s, &token_flags, &recv_tok) < 0) {
+	     (void) gss_release_name(&min_stat, &target_name);
+	     return -1;
+	   }
+	   token_ptr = &recv_tok;
+	 }
+	 if (verbose)
+	   printf("\n");
+       } while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+       (void) gss_release_name(&min_stat, &target_name);
+     }
+     else {
+       if (send_token(s, TOKEN_NOOP, empty_token) < 0)
+	 return -1;
+     }
+
+     return 0;
+}
+
+static void read_file(file_name, in_buf)
+    char		*file_name;
+    gss_buffer_t	in_buf;
+{
+    int fd, count;
+    struct stat stat_buf;
+    
+    if ((fd = open(file_name, O_RDONLY, 0)) < 0) {
+	perror("open");
+	fprintf(stderr, "Couldn't open file %s\n", file_name);
+	exit(2);
+    }
+    if (fstat(fd, &stat_buf) < 0) {
+	perror("fstat");
+	exit(3);
+    }
+    in_buf->length = stat_buf.st_size;
+
+    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",
+		(int) in_buf->length);
+	exit(4);
+    }
+
+    /* 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(5);
+    }
+    if (count < in_buf->length)
+	fprintf(stderr, "Warning, only read in %d bytes, expected %d\n",
+		count, (int) in_buf->length);
+}
+
+/*
+ * Function: call_server
+ *
+ * Purpose: Call the "sign" service.
+ *
+ * Arguments:
+ *
+ * 	host		(r) the host providing the service
+ * 	port		(r) the port to connect to on host
+ * 	service_name	(r) the GSS-API service name to authenticate to
+ *	gss_flags	(r) GSS-API delegation flag (if any)
+ *	auth_flag	(r) whether to do authentication
+ *	wrap_flag	(r) whether to do message wrapping at all
+ *	encrypt_flag	(r) whether to do encryption while wrapping
+ *	mic_flag	(r) whether to request a MIC from the server
+ * 	msg		(r) the message to have "signed"
+ *	use_file	(r) whether to treat msg as an input file name
+ *	mcount		(r) the number of times to send the message
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * call_server opens a TCP connection to <host:port> and establishes a
+ * GSS-API context with service_name over the connection.  It then
+ * seals msg in a GSS-API token with gss_wrap, 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.  */
+static int call_server(host, port, oid, service_name, gss_flags, auth_flag,
+		       wrap_flag, encrypt_flag, mic_flag, v1_format, msg, use_file,
+		       mcount)
+     char *host;
+     u_short port;
+     gss_OID oid;
+     char *service_name;
+     OM_uint32 gss_flags;
+     int auth_flag, wrap_flag, encrypt_flag, mic_flag;
+     int v1_format;
+     char *msg;
+     int use_file;
+     int mcount;
+{
+     gss_ctx_id_t context;
+     gss_buffer_desc in_buf, out_buf;
+     int s, state;
+     OM_uint32 ret_flags;
+     OM_uint32 maj_stat, min_stat;
+     gss_name_t		src_name, targ_name;
+     gss_buffer_desc	sname, tname;
+     OM_uint32		lifetime;
+     gss_OID		mechanism, name_type;
+     int		is_local;
+     OM_uint32		context_flags;
+     int		is_open;
+     gss_qop_t		qop_state;
+     gss_OID_set	mech_names;
+     gss_buffer_desc	oid_name;
+     size_t	i;
+     int token_flags;
+
+     /* Open connection */
+     if ((s = connect_to_server()) < 0)
+	  return -1;
+
+     /* Establish context */
+     if (client_establish_context(s, service_name, gss_flags, auth_flag,
+				  v1_format, oid, &context,
+				  &ret_flags) < 0) {
+         (void) closesocket(s);
+         return -1;
+     }
+
+     if (auth_flag && verbose) {
+         /* display the flags */
+         display_ctx_flags(ret_flags);
+
+         /* Get context information */
+         maj_stat = gss_inquire_context( &min_stat, context,
+                                         &src_name, &targ_name, &lifetime,
+                                         &mechanism, &context_flags,
+                                         &is_local,
+                                         &is_open);
+         if (maj_stat != GSS_S_COMPLETE) {
+             display_status("inquiring context", maj_stat, min_stat);
+             return -1;
+         }
+
+         maj_stat = gss_display_name(&min_stat, src_name, &sname,
+                                      &name_type);
+         if (maj_stat != GSS_S_COMPLETE) {
+             display_status("displaying source name", maj_stat, min_stat);
+             return -1;
+         }
+         maj_stat = gss_display_name(&min_stat, targ_name, &tname,
+                                      (gss_OID *) NULL);
+         if (maj_stat != GSS_S_COMPLETE) {
+             display_status("displaying target name", maj_stat, min_stat);
+             return -1;
+         }
+         printf("\"%.*s\" to \"%.*s\", lifetime %d, flags %x, %s, %s\n",
+                 (int) sname.length, (char *) sname.value,
+                 (int) tname.length, (char *) tname.value, lifetime,
+                 context_flags,
+                 (is_local) ? "locally initiated" : "remotely initiated",
+                 (is_open) ? "open" : "closed");
+
+         (void) gss_release_name(&min_stat, &src_name);
+         (void) gss_release_name(&min_stat, &targ_name);
+         (void) gss_release_buffer(&min_stat, &sname);
+         (void) gss_release_buffer(&min_stat, &tname);
+
+         maj_stat = gss_oid_to_str(&min_stat,
+                                    name_type,
+                                    &oid_name);
+         if (maj_stat != GSS_S_COMPLETE) {
+             display_status("converting oid->string", maj_stat, min_stat);
+             return -1;
+         }
+         printf("Name type of source name is %.*s.\n",
+                 (int) oid_name.length, (char *) oid_name.value);
+         (void) gss_release_buffer(&min_stat, &oid_name);
+
+         /* Now get the names supported by the mechanism */
+         maj_stat = gss_inquire_names_for_mech(&min_stat,
+                                                mechanism,
+                                                &mech_names);
+         if (maj_stat != GSS_S_COMPLETE) {
+             display_status("inquiring mech names", maj_stat, min_stat);
+             return -1;
+         }
+
+         maj_stat = gss_oid_to_str(&min_stat,
+                                    mechanism,
+                                    &oid_name);
+         if (maj_stat != GSS_S_COMPLETE) {
+             display_status("converting oid->string", maj_stat, min_stat);
+             return -1;
+         }
+         printf("Mechanism %.*s supports %d names\n",
+                 (int) oid_name.length, (char *) oid_name.value,
+                 (int) mech_names->count);
+         (void) gss_release_buffer(&min_stat, &oid_name);
+
+         for (i=0; i<mech_names->count; i++) {
+             maj_stat = gss_oid_to_str(&min_stat,
+                                        &mech_names->elements[i],
+                                        &oid_name);
+             if (maj_stat != GSS_S_COMPLETE) {
+                 display_status("converting oid->string", maj_stat, min_stat);
+                 return -1;
+             }
+             printf("  %d: %.*s\n", (int) i,
+                     (int) oid_name.length, (char *) oid_name.value);
+
+             (void) gss_release_buffer(&min_stat, &oid_name);
+         }
+         (void) gss_release_oid_set(&min_stat, &mech_names);
+     }
+
+    if (use_file) {
+        read_file(msg, &in_buf);
+    } else {
+        /* Seal the message */
+        in_buf.value = msg;
+        in_buf.length = strlen(msg);
+    }
+
+    for (i = 0; i < mcount; i++) {
+        if (wrap_flag) {
+            maj_stat = gss_wrap(&min_stat, context, encrypt_flag, GSS_C_QOP_DEFAULT,
+                                 &in_buf, &state, &out_buf);
+            if (maj_stat != GSS_S_COMPLETE) {
+                display_status("wrapping message", maj_stat, min_stat);
+                (void) closesocket(s);
+                (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
+                return -1;
+            } else if (encrypt_flag && ! state) {
+                fprintf(stderr, "Warning!  Message not encrypted.\n");
+            }
+        }
+        else {
+            out_buf = in_buf;
+        }
+
+        /* Send to server */
+        if (send_token(s, (v1_format?0
+                            :(TOKEN_DATA |
+                               (wrap_flag ? TOKEN_WRAPPED : 0) |
+                               (encrypt_flag ? TOKEN_ENCRYPTED : 0) |
+                               (mic_flag ? TOKEN_SEND_MIC : 0))), &out_buf) < 0) {
+            (void) closesocket(s);
+            (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
+            return -1;
+        }
+        if (out_buf.value != in_buf.value)
+            (void) gss_release_buffer(&min_stat, &out_buf);
+
+        /* Read signature block into out_buf */
+        if (recv_token(s, &token_flags, &out_buf) < 0) {
+            (void) closesocket(s);
+            (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
+            return -1;
+        }
+
+        if (mic_flag) {
+            /* Verify signature block */
+            maj_stat = gss_verify_mic(&min_stat, context, &in_buf,
+                                       &out_buf, &qop_state);
+            if (maj_stat != GSS_S_COMPLETE) {
+                display_status("verifying signature", maj_stat, min_stat);
+                (void) closesocket(s);
+                (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
+                return -1;
+            }
+
+            if (verbose)
+                printf("Signature verified.\n");
+        }
+        else {
+            if (verbose)
+                printf("Response received.\n");
+        }
+
+        free (out_buf.value);
+    }
+
+    if (use_file)
+        free(in_buf.value);
+
+    /* Send NOOP */
+    if (!v1_format)
+        (void) send_token(s, TOKEN_NOOP, empty_token);
+
+    if (auth_flag) {
+        /* Delete context */
+        maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf);
+        if (maj_stat != GSS_S_COMPLETE) {
+            display_status("deleting context", maj_stat, min_stat);
+            (void) closesocket(s);
+            (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
+            return -1;
+        }
+
+        (void) gss_release_buffer(&min_stat, &out_buf);
+    }
+
+    (void) closesocket(s);
+    return 0;
+}
+
+static void parse_oid(char *mechanism, gss_OID *oid)
+{
+    char	*mechstr = 0, *cp;
+    gss_buffer_desc tok;
+    OM_uint32 maj_stat, min_stat;
+    
+    if (isdigit((int) mechanism[0])) {
+	mechstr = malloc(strlen(mechanism)+5);
+	if (!mechstr) {
+	    fprintf(stderr, "Couldn't allocate mechanism scratch!\n");
+	    return;
+	}
+	sprintf(mechstr, "{ %s }", mechanism);
+	for (cp = mechstr; *cp; cp++)
+	    if (*cp == '.')
+		*cp = ' ';
+	tok.value = mechstr;
+    } else
+	tok.value = mechanism;
+    tok.length = strlen(tok.value);
+    maj_stat = gss_str_to_oid(&min_stat, &tok, oid);
+    if (maj_stat != GSS_S_COMPLETE) {
+	display_status("str_to_oid", maj_stat, min_stat);
+	return;
+    }
+    if (mechstr)
+	free(mechstr);
+}
+
+static int max_threads = 1;
+
+#ifdef _WIN32
+static thread_count = 0;
+static HANDLE hMutex = NULL;
+static HANDLE hEvent = NULL;
+
+void
+InitHandles(void)
+{
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+void
+CleanupHandles(void)
+{
+    CloseHandle(hMutex);
+    CloseHandle(hEvent);
+}
+
+BOOL
+WaitAndIncrementThreadCounter(void)
+{
+    for (;;) {
+        if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+            if ( thread_count < max_threads ) {
+                thread_count++;
+                ReleaseMutex(hMutex);
+                return TRUE;
+            } else {
+                ReleaseMutex(hMutex);
+
+                if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) {
+                    continue;
+                } else {
+                    return FALSE;
+                }
+            }
+        } else {
+            return FALSE;
+        }
+    }
+}
+
+BOOL
+DecrementAndSignalThreadCounter(void)
+{
+    if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+        if (thread_count == max_threads)
+            SetEvent(hEvent);
+        thread_count--;
+        ReleaseMutex(hMutex);
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+#else /* assume pthread */
+static pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t counter_cond = PTHREAD_COND_INITIALIZER;
+int counter = 0;
+
+static int
+WaitAndIncrementThreadCounter(void)
+{
+    int err;
+    err = pthread_mutex_lock(&counter_mutex);
+    if (err) {
+	perror("pthread_mutex_lock");
+	return 0;
+    }
+    if (counter == max_threads) {
+	err = pthread_cond_wait(&counter_cond, &counter_mutex);
+	if (err) {
+	    perror("pthread_cond_wait");
+	    return 0;
+	}
+    }
+    counter++;
+    pthread_mutex_unlock(&counter_mutex);
+    return 1;
+}
+static void
+DecrementAndSignalThreadCounter(void)
+{
+    int err;
+    sleep(1);
+    err = pthread_mutex_lock(&counter_mutex);
+    if (err) {
+	perror("pthread_mutex_lock");
+	return;
+    }
+    if (counter == max_threads)
+	pthread_cond_broadcast(&counter_cond);
+    counter--;
+    pthread_mutex_unlock(&counter_mutex);
+}
+#endif
+
+static char *service_name, *server_host, *msg;
+static char *mechanism = 0;
+static u_short port = 4444;
+static int use_file = 0;
+static OM_uint32 gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
+static OM_uint32 min_stat;
+static gss_OID oid = GSS_C_NULL_OID;
+static int mcount = 1, ccount = 1;
+static int auth_flag, wrap_flag, encrypt_flag, mic_flag, v1_format;
+
+static void worker_bee(void * unused)
+{
+    printf("worker bee!\n");
+    if (call_server(server_host, port, oid, service_name,
+                    gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag,
+                    v1_format, msg, use_file, mcount) < 0)
+        if ( max_threads == 1 )
+            exit(6);
+
+    if ( max_threads > 1 )
+        DecrementAndSignalThreadCounter();
+    free(unused);
+}
+
+int main(argc, argv)
+     int argc;
+     char **argv;
+{
+     int i;
+
+     display_file = stdout;
+     auth_flag = wrap_flag = encrypt_flag = mic_flag = 1;
+     v1_format = 0;
+
+     /* Parse arguments. */
+     argc--; argv++;
+     while (argc) {
+	  if (strcmp(*argv, "-port") == 0) {
+	       argc--; argv++;
+	       if (!argc) usage();
+	       port = atoi(*argv);
+	   } else if (strcmp(*argv, "-mech") == 0) {
+	       argc--; argv++;
+	       if (!argc) usage();
+	       mechanism = *argv;
+	   } 
+#if defined(_WIN32) || 1
+           else if (strcmp(*argv, "-threads") == 0) {
+               argc--; argv++;
+               if (!argc) usage();
+               max_threads = atoi(*argv);
+           } 
+#endif
+           else if (strcmp(*argv, "-d") == 0) {
+	       gss_flags |= GSS_C_DELEG_FLAG;
+	   } else if (strcmp(*argv, "-seq") == 0) {
+	       gss_flags |= GSS_C_SEQUENCE_FLAG;
+	   } else if (strcmp(*argv, "-noreplay") == 0) {
+	       gss_flags &= ~GSS_C_REPLAY_FLAG;
+	   } else if (strcmp(*argv, "-nomutual") == 0) {
+	       gss_flags &= ~GSS_C_MUTUAL_FLAG;
+	  } else if (strcmp(*argv, "-f") == 0) {
+	       use_file = 1;
+	  } else if (strcmp(*argv, "-q") == 0) {
+	       verbose = 0;
+	  } else if (strcmp(*argv, "-ccount") == 0) {
+	    argc--; argv++;
+	    if (!argc) usage();
+	    ccount = atoi(*argv);
+	    if (ccount <= 0) usage();
+	  } else if (strcmp(*argv, "-mcount") == 0) {
+	    argc--; argv++;
+	    if (!argc) usage();
+	    mcount = atoi(*argv);
+	    if (mcount < 0) usage();
+	  } else if (strcmp(*argv, "-na") == 0) {
+	    auth_flag = wrap_flag = encrypt_flag = mic_flag = 0;
+	  } else if (strcmp(*argv, "-nw") == 0) {
+	    wrap_flag = 0;
+	  } else if (strcmp(*argv, "-nx") == 0) {
+	    encrypt_flag = 0;
+	  } else if (strcmp(*argv, "-nm") == 0) {
+	    mic_flag = 0;
+	  } else  if (strcmp(*argv, "-v1") == 0) {
+	    v1_format = 1;
+	  } else
+	    break;
+	  argc--; argv++;
+     }
+     if (argc != 3)
+	  usage();
+
+#ifdef _WIN32
+    if (max_threads < 1) {
+        fprintf(stderr, "warning: there must be at least one thread\n");
+        max_threads = 1;
+    }
+
+    InitHandles();
+    SetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT","1");
+#endif
+
+     server_host = *argv++;
+     service_name = *argv++;
+     msg = *argv++;
+
+     if (mechanism)
+	 parse_oid(mechanism, &oid);
+
+     if (get_server_info(server_host, port) < 0) {
+	 exit(1);
+     }
+
+    if ( max_threads == 1 ) {
+        for (i = 0; i < ccount; i++) {
+            worker_bee(0);
+        }
+    } else {
+        for (i = 0; i < ccount; i++) {
+            if ( WaitAndIncrementThreadCounter() ) {
+#ifdef _WIN32
+                uintptr_t handle = _beginthread(worker_bee, 0, (void *)0);
+                if (handle == (uintptr_t)-1) {
+                    exit(7);
+                }
+#else
+		int err;
+		pthread_t thr;
+		err = pthread_create(&thr, 0, (void *(*)(void *))worker_bee, malloc(12));
+		if (err) {
+		    perror("pthread_create");
+		    exit(7);
+		}
+		(void) pthread_detach(thr);
+#endif
+            } else {
+                exit(8);
+            }
+        }
+    }
+
+    if (oid != GSS_C_NULL_OID)
+        (void) gss_release_oid(&min_stat, &oid);
+	 
+#ifdef _WIN32
+    CleanupHandles();
+#else
+    if (max_threads > 1)
+	sleep(10);
+#endif
+
+    return 0;
+}
diff --git a/krb5-1-6/src/tests/gss-threads/gss-misc.c b/krb5-1-6/src/tests/gss-threads/gss-misc.c
new file mode 100644
index 000000000..3016db220
--- /dev/null
+++ b/krb5-1-6/src/tests/gss-threads/gss-misc.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock.h>
+#else
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+#include <errno.h>
+#include "autoconf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+
+/* need struct timeval */
+#if HAVE_TIME_H && (!HAVE_SYS_TIME_H || TIME_WITH_SYS_TIME)
+# include <time.h>
+#endif
+#if HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include <gssapi/gssapi_generic.h>
+#include "gss-misc.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *malloc();
+#endif
+
+FILE *display_file;
+
+gss_buffer_desc empty_token_buf = { 0, (void *) "" };
+gss_buffer_t empty_token = &empty_token_buf;
+
+static void display_status_1
+	(char *m, OM_uint32 code, int type);
+
+static int write_all(int fildes, char *buf, unsigned int nbyte)
+{
+     int ret;
+     char *ptr;
+
+     for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
+	  ret = send(fildes, ptr, nbyte, 0);
+	  if (ret < 0) {
+	       if (errno == EINTR)
+		    continue;
+	       return(ret);
+	  } else if (ret == 0) {
+	       return(ptr-buf);
+	  }
+     }
+
+     return(ptr-buf);
+}
+
+static int read_all(int fildes, char *buf, unsigned int nbyte)
+{
+    int ret;
+    char *ptr;
+    fd_set rfds;
+    struct timeval tv;
+
+    FD_ZERO(&rfds);
+    FD_SET(fildes, &rfds);
+    tv.tv_sec = 10;
+    tv.tv_usec = 0;
+
+    for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
+	if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0
+	    || !FD_ISSET(fildes, &rfds))
+	    return(ptr-buf);
+	ret = recv(fildes, ptr, nbyte, 0);
+	if (ret < 0) {
+	    if (errno == EINTR)
+		continue;
+	    return(ret);
+	} else if (ret == 0) {
+	    return(ptr-buf);
+	}
+    }
+
+    return(ptr-buf);
+}
+
+/*
+ * Function: send_token
+ *
+ * Purpose: Writes a token to a file descriptor.
+ *
+ * Arguments:
+ *
+ * 	s		(r) an open file descriptor
+ *	flags		(r) the flags to write
+ * 	tok		(r) the token to write
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ *
+ * If the flags are non-null, send_token writes the token flags (a
+ * single byte, even though they're passed in in an integer). Next,
+ * the token length (as a network long) and then the token data are
+ * written to the file descriptor s.  It returns 0 on success, and -1
+ * if an error occurs or if it could not write all the data.
+ */
+int send_token(s, flags, tok)
+     int s;
+     int flags;
+     gss_buffer_t tok;
+{
+     int ret;
+     unsigned char char_flags = (unsigned char) flags;
+     unsigned char lenbuf[4];
+
+     if (char_flags) {
+	 ret = write_all(s, (char *)&char_flags, 1);
+	 if (ret != 1) {
+	     perror("sending token flags");
+	     return -1;
+	 }
+     }
+     if (tok->length > 0xffffffffUL)
+	 abort();
+     lenbuf[0] = (tok->length >> 24) & 0xff;
+     lenbuf[1] = (tok->length >> 16) & 0xff;
+     lenbuf[2] = (tok->length >> 8) & 0xff;
+     lenbuf[3] = tok->length & 0xff;
+
+     ret = write_all(s, lenbuf, 4);
+     if (ret < 0) {
+	  perror("sending token length");
+	  return -1;
+     } else if (ret != 4) {
+	 if (display_file)
+	     fprintf(display_file, 
+		     "sending token length: %d of %d bytes written\n", 
+		     ret, 4);
+	  return -1;
+     }
+
+     ret = write_all(s, tok->value, tok->length);
+     if (ret < 0) {
+	  perror("sending token data");
+	  return -1;
+     } else if (ret != tok->length) {
+	 if (display_file)
+	     fprintf(display_file, 
+		     "sending token data: %d of %d bytes written\n", 
+		     ret, (int) tok->length);
+	 return -1;
+     }
+     
+     return 0;
+}
+
+/*
+ * Function: recv_token
+ *
+ * Purpose: Reads a token from a file descriptor.
+ *
+ * Arguments:
+ *
+ * 	s		(r) an open file descriptor
+ *	flags		(w) the read flags
+ * 	tok		(w) the read token
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * recv_token reads the token flags (a single byte, even though
+ * they're stored into an integer, then reads the token length (as a
+ * network long), allocates memory to hold the data, and then reads
+ * the token data from the file descriptor s.  It blocks to read the
+ * length and data, if necessary.  On a successful return, the token
+ * should be freed with gss_release_buffer.  It returns 0 on success,
+ * and -1 if an error occurs or if it could not read all the data.
+ */
+int recv_token(s, flags, tok)
+     int s;
+     int *flags;
+     gss_buffer_t tok;
+{
+     int ret;
+     unsigned char char_flags;
+     unsigned char lenbuf[4];
+
+     ret = read_all(s, (char *) &char_flags, 1);
+     if (ret < 0) {
+       perror("reading token flags");
+       return -1;
+     } else if (! ret) {
+       if (display_file)
+	 fputs("reading token flags: 0 bytes read\n", display_file);
+       return -1;
+     } else {
+       *flags = (int) char_flags;
+     }
+
+     if (char_flags == 0 ) {
+     lenbuf[0] = 0;
+     ret = read_all(s, &lenbuf[1], 3);
+     if (ret < 0) {
+	 perror("reading token length");
+	 return -1;
+     } else if (ret != 3) {
+	 if (display_file)
+	     fprintf(display_file, 
+		     "reading token length: %d of %d bytes read\n", 
+		     ret, 3);
+	 return -1;
+     }
+     }
+     else {
+       ret = read_all(s, lenbuf, 4);
+       if (ret < 0) {
+	 perror("reading token length");
+	 return -1;
+       } else if (ret != 4) {
+	 if (display_file)
+	   fprintf(display_file, 
+		   "reading token length: %d of %d bytes read\n", 
+		   ret, 4);
+	 return -1;
+       }
+     }
+
+     tok->length = ((lenbuf[0] << 24)
+		    | (lenbuf[1] << 16)
+		    | (lenbuf[2] << 8)
+		    | lenbuf[3]);
+     tok->value = (char *) malloc(tok->length ? tok->length : 1);
+     if (tok->length && tok->value == NULL) {
+	 if (display_file)
+	     fprintf(display_file, 
+		     "Out of memory allocating token data\n");
+	  return -1;
+     }
+
+     ret = read_all(s, (char *) tok->value, tok->length);
+     if (ret < 0) {
+	  perror("reading token data");
+	  free(tok->value);
+	  return -1;
+     } else if (ret != tok->length) {
+	  fprintf(stderr, "sending token data: %d of %d bytes written\n", 
+		  ret, (int) tok->length);
+	  free(tok->value);
+	  return -1;
+     }
+
+     return 0;
+}
+
+static void display_status_1(m, code, type)
+     char *m;
+     OM_uint32 code;
+     int type;
+{
+     OM_uint32 maj_stat, min_stat;
+     gss_buffer_desc msg;
+     OM_uint32 msg_ctx;
+     
+     msg_ctx = 0;
+     while (1) {
+	  maj_stat = gss_display_status(&min_stat, code,
+				       type, GSS_C_NULL_OID,
+				       &msg_ctx, &msg);
+	  if (display_file)
+	      fprintf(display_file, "GSS-API error %s: %s\n", m,
+		      (char *)msg.value); 
+	  (void) gss_release_buffer(&min_stat, &msg);
+	  
+	  if (!msg_ctx)
+	       break;
+     }
+}
+
+/*
+ * Function: display_status
+ *
+ * Purpose: displays GSS-API messages
+ *
+ * Arguments:
+ *
+ * 	msg		a string to be displayed with the message
+ * 	maj_stat	the GSS-API major status code
+ * 	min_stat	the GSS-API minor status code
+ *
+ * Effects:
+ *
+ * The GSS-API messages associated with maj_stat and min_stat are
+ * displayed on stderr, each preceeded by "GSS-API error <msg>: " and
+ * followed by a newline.
+ */
+void display_status(msg, maj_stat, min_stat)
+     char *msg;
+     OM_uint32 maj_stat;
+     OM_uint32 min_stat;
+{
+     display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
+     display_status_1(msg, min_stat, GSS_C_MECH_CODE);
+}
+
+/*
+ * Function: display_ctx_flags
+ *
+ * Purpose: displays the flags returned by context initation in
+ *	    a human-readable form
+ *
+ * Arguments:
+ *
+ * 	int		ret_flags
+ *
+ * Effects:
+ *
+ * Strings corresponding to the context flags are printed on
+ * stdout, preceded by "context flag: " and followed by a newline
+ */
+
+void display_ctx_flags(flags)
+     OM_uint32 flags;
+{
+     if (flags & GSS_C_DELEG_FLAG)
+	  fprintf(display_file, "context flag: GSS_C_DELEG_FLAG\n");
+     if (flags & GSS_C_MUTUAL_FLAG)
+	  fprintf(display_file, "context flag: GSS_C_MUTUAL_FLAG\n");
+     if (flags & GSS_C_REPLAY_FLAG)
+	  fprintf(display_file, "context flag: GSS_C_REPLAY_FLAG\n");
+     if (flags & GSS_C_SEQUENCE_FLAG)
+	  fprintf(display_file, "context flag: GSS_C_SEQUENCE_FLAG\n");
+     if (flags & GSS_C_CONF_FLAG )
+	  fprintf(display_file, "context flag: GSS_C_CONF_FLAG \n");
+     if (flags & GSS_C_INTEG_FLAG )
+	  fprintf(display_file, "context flag: GSS_C_INTEG_FLAG \n");
+}
+
+void print_token(tok)
+     gss_buffer_t tok;
+{
+    int i;
+    unsigned char *p = tok->value;
+
+    if (!display_file)
+	return;
+    for (i=0; i < tok->length; i++, p++) {
+	fprintf(display_file, "%02x ", *p);
+	if ((i % 16) == 15) {
+	    fprintf(display_file, "\n");
+	}
+    }
+    fprintf(display_file, "\n");
+    fflush(display_file);
+}
+
+#ifdef _WIN32
+#include <sys\timeb.h>
+#include <time.h>
+
+int gettimeofday (struct timeval *tv, void *ignore_tz)
+{
+    struct _timeb tb;
+    _tzset();
+    _ftime(&tb);
+    if (tv) {
+	tv->tv_sec = tb.time;
+	tv->tv_usec = tb.millitm * 1000;
+    }
+    return 0;
+}
+#endif /* _WIN32 */
diff --git a/krb5-1-6/src/tests/gss-threads/gss-misc.h b/krb5-1-6/src/tests/gss-threads/gss-misc.h
new file mode 100644
index 000000000..35b3b7390
--- /dev/null
+++ b/krb5-1-6/src/tests/gss-threads/gss-misc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef _GSSMISC_H_
+#define _GSSMISC_H_
+
+#include <gssapi/gssapi_generic.h>
+#include <stdio.h>
+
+extern FILE *display_file;
+
+int send_token
+	(int s, int flags, gss_buffer_t tok);
+int recv_token
+	(int s, int *flags, gss_buffer_t tok);
+void display_status
+	(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat);
+void display_ctx_flags
+	(OM_uint32 flags);
+void print_token
+	(gss_buffer_t tok);
+
+/* Token types */
+#define TOKEN_NOOP		(1<<0)
+#define TOKEN_CONTEXT		(1<<1)
+#define TOKEN_DATA		(1<<2)
+#define TOKEN_MIC		(1<<3)
+
+/* Token flags */
+#define TOKEN_CONTEXT_NEXT	(1<<4)
+#define TOKEN_WRAPPED		(1<<5)
+#define TOKEN_ENCRYPTED		(1<<6)
+#define TOKEN_SEND_MIC		(1<<7)
+
+extern gss_buffer_t empty_token;
+
+#endif
diff --git a/krb5-1-6/src/tests/gss-threads/gss-server.c b/krb5-1-6/src/tests/gss-threads/gss-server.c
new file mode 100644
index 000000000..6cbac84af
--- /dev/null
+++ b/krb5-1-6/src/tests/gss-threads/gss-server.c
@@ -0,0 +1,850 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdio.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <signal.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <gssapi/gssapi_generic.h>
+#include "gss-misc.h"
+#include "port-sockets.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+static void usage()
+{
+     fprintf(stderr, "Usage: gss-server [-port port] [-verbose] [-once]");
+#ifdef _WIN32
+     fprintf(stderr, " [-threads num]");
+#endif
+     fprintf(stderr, "\n");
+     fprintf(stderr, "       [-inetd] [-export] [-logfile file] service_name\n");
+     exit(1);
+}
+
+FILE *log;
+
+int verbose = 0;
+
+/*
+ * Function: server_acquire_creds
+ *
+ * Purpose: imports a service name and acquires credentials for it
+ *
+ * Arguments:
+ *
+ * 	service_name	(r) the ASCII service name
+ * 	server_creds	(w) the GSS-API service credentials
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ *
+ * The service name is imported with gss_import_name, and service
+ * credentials are acquired with gss_acquire_cred.  If either opertion
+ * fails, an error message is displayed and -1 is returned; otherwise,
+ * 0 is returned.
+ */
+static int server_acquire_creds(service_name, server_creds)
+     char *service_name;
+     gss_cred_id_t *server_creds;
+{
+     gss_buffer_desc name_buf;
+     gss_name_t server_name;
+     OM_uint32 maj_stat, min_stat;
+
+     name_buf.value = service_name;
+     name_buf.length = strlen(name_buf.value) + 1;
+     maj_stat = gss_import_name(&min_stat, &name_buf, 
+				(gss_OID) gss_nt_service_name, &server_name);
+     if (maj_stat != GSS_S_COMPLETE) {
+	  display_status("importing name", maj_stat, min_stat);
+	  return -1;
+     }
+
+     maj_stat = gss_acquire_cred(&min_stat, server_name, 0,
+				 GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+				 server_creds, NULL, NULL);
+     if (maj_stat != GSS_S_COMPLETE) {
+	  display_status("acquiring credentials", maj_stat, min_stat);
+	  return -1;
+     }
+
+     (void) gss_release_name(&min_stat, &server_name);
+
+     return 0;
+}
+
+/*
+ * Function: server_establish_context
+ *
+ * Purpose: establishses a GSS-API context as a specified service with
+ * an incoming client, and returns the context handle and associated
+ * client name
+ *
+ * Arguments:
+ *
+ * 	s		(r) an established TCP connection to the client
+ * 	service_creds	(r) server credentials, from gss_acquire_cred
+ * 	context		(w) the established GSS-API context
+ * 	client_name	(w) the client's ASCII name
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ *
+ * Any valid client request is accepted.  If a context is established,
+ * its handle is returned in context and the client name is returned
+ * in client_name and 0 is returned.  If unsuccessful, an error
+ * message is displayed and -1 is returned.
+ */
+static int server_establish_context(s, server_creds, context, client_name, 
+				    ret_flags)
+     int s;
+     gss_cred_id_t server_creds;
+     gss_ctx_id_t *context;
+     gss_buffer_t client_name;
+     OM_uint32 *ret_flags;
+{
+     gss_buffer_desc send_tok, recv_tok;
+     gss_name_t client;
+     gss_OID doid;
+     OM_uint32 maj_stat, min_stat, acc_sec_min_stat;
+     gss_buffer_desc	oid_name;
+     int token_flags;
+
+     if (recv_token(s, &token_flags, &recv_tok) < 0)
+       return -1;
+
+     if (recv_tok.value) {
+       free (recv_tok.value);
+       recv_tok.value = NULL;
+     }
+
+     if (! (token_flags & TOKEN_NOOP)) {
+       if (log)
+	 fprintf(log, "Expected NOOP token, got %d token instead\n",
+		 token_flags);
+       return -1;
+     }
+
+     *context = GSS_C_NO_CONTEXT;
+
+     if (token_flags & TOKEN_CONTEXT_NEXT) {
+       do {
+	 if (recv_token(s, &token_flags, &recv_tok) < 0)
+	   return -1;
+
+	 if (verbose && log) {
+	   fprintf(log, "Received token (size=%d): \n", (int) recv_tok.length);
+	   print_token(&recv_tok);
+	 }
+
+	 maj_stat =
+	   gss_accept_sec_context(&acc_sec_min_stat,
+				  context,
+				  server_creds,
+				  &recv_tok,
+				  GSS_C_NO_CHANNEL_BINDINGS,
+				  &client,
+				  &doid,
+				  &send_tok,
+				  ret_flags,
+				  NULL, 	/* ignore time_rec */
+				  NULL); 	/* ignore del_cred_handle */
+
+	 if(recv_tok.value) {
+	     free(recv_tok.value);
+	     recv_tok.value = NULL;
+	 }
+
+	 if (send_tok.length != 0) {
+	   if (verbose && log) {
+	     fprintf(log,
+		     "Sending accept_sec_context token (size=%d):\n",
+		     (int) send_tok.length);
+	     print_token(&send_tok);
+	   }
+	   if (send_token(s, TOKEN_CONTEXT, &send_tok) < 0) {
+	     if (log)
+	       fprintf(log, "failure sending token\n");
+	     return -1;
+	   }
+
+	   (void) gss_release_buffer(&min_stat, &send_tok);
+	 }
+	 if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
+	      display_status("accepting context", maj_stat,
+			     acc_sec_min_stat);
+	      if (*context != GSS_C_NO_CONTEXT)
+		      gss_delete_sec_context(&min_stat, context,
+					     GSS_C_NO_BUFFER);
+	      return -1;
+	 }
+ 
+	 if (verbose && log) {
+	   if (maj_stat == GSS_S_CONTINUE_NEEDED)
+	     fprintf(log, "continue needed...\n");
+	   else
+	     fprintf(log, "\n");
+	   fflush(log);
+	 }
+       } while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+       /* display the flags */
+       display_ctx_flags(*ret_flags);
+
+       if (verbose && log) {
+	 maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name);
+	 if (maj_stat != GSS_S_COMPLETE) {
+	   display_status("converting oid->string", maj_stat, min_stat);
+	   return -1;
+	 }
+	 fprintf(log, "Accepted connection using mechanism OID %.*s.\n",
+		 (int) oid_name.length, (char *) oid_name.value);
+	 (void) gss_release_buffer(&min_stat, &oid_name);
+       }
+
+       maj_stat = gss_display_name(&min_stat, client, client_name, &doid);
+       if (maj_stat != GSS_S_COMPLETE) {
+	 display_status("displaying name", maj_stat, min_stat);
+	 return -1;
+       }
+       maj_stat = gss_release_name(&min_stat, &client);
+       if (maj_stat != GSS_S_COMPLETE) {
+	 display_status("releasing name", maj_stat, min_stat);
+	 return -1;
+       }
+     }
+     else {
+       client_name->length = *ret_flags = 0;
+
+       if (log)
+	 fprintf(log, "Accepted unauthenticated connection.\n");
+     }
+
+     return 0;
+}
+
+/*
+ * Function: create_socket
+ *
+ * Purpose: Opens a listening TCP socket.
+ *
+ * Arguments:
+ *
+ * 	port		(r) the port number on which to listen
+ *
+ * Returns: the listening socket file descriptor, or -1 on failure
+ *
+ * Effects:
+ *
+ * A listening socket on the specified port and created and returned.
+ * On error, an error message is displayed and -1 is returned.
+ */
+static int create_socket(port)
+     u_short port;
+{
+     struct sockaddr_in saddr;
+     int s;
+     int on = 1;
+     
+     saddr.sin_family = AF_INET;
+     saddr.sin_port = htons(port);
+     saddr.sin_addr.s_addr = INADDR_ANY;
+
+     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	  perror("creating socket");
+	  return -1;
+     }
+     /* Let the socket be reused right away */
+     (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
+     if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
+	  perror("binding socket");
+	  (void) close(s);
+	  return -1;
+     }
+     if (listen(s, 5) < 0) {
+	  perror("listening on socket");
+	  (void) close(s);
+	  return -1;
+     }
+     return s;
+}
+
+static float timeval_subtract(tv1, tv2)
+	struct timeval *tv1, *tv2;
+{
+	return ((tv1->tv_sec - tv2->tv_sec) +
+		((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
+}
+
+/*
+ * Yes, yes, this isn't the best place for doing this test.
+ * DO NOT REMOVE THIS UNTIL A BETTER TEST HAS BEEN WRITTEN, THOUGH.
+ * 					-TYT
+ */
+static int test_import_export_context(context)
+	gss_ctx_id_t *context;
+{
+	OM_uint32	min_stat, maj_stat;
+	gss_buffer_desc context_token, copied_token;
+	struct timeval tm1, tm2;
+	
+	/*
+	 * Attempt to save and then restore the context.
+	 */
+	gettimeofday(&tm1, (struct timezone *)0);
+	maj_stat = gss_export_sec_context(&min_stat, context, &context_token);
+	if (maj_stat != GSS_S_COMPLETE) {
+		display_status("exporting context", maj_stat, min_stat);
+		return 1;
+	}
+	gettimeofday(&tm2, (struct timezone *)0);
+	if (verbose && log)
+		fprintf(log, "Exported context: %d bytes, %7.4f seconds\n",
+			(int) context_token.length, 
+			timeval_subtract(&tm2, &tm1));
+	copied_token.length = context_token.length;
+	copied_token.value = malloc(context_token.length);
+	if (copied_token.value == 0) {
+	  if (log)
+	    fprintf(log, "Couldn't allocate memory to copy context token.\n");
+	  return 1;
+	}
+	memcpy(copied_token.value, context_token.value, copied_token.length);
+	maj_stat = gss_import_sec_context(&min_stat, &copied_token, context);
+	if (maj_stat != GSS_S_COMPLETE) {
+		display_status("importing context", maj_stat, min_stat);
+		return 1;
+	}
+	free(copied_token.value);
+	gettimeofday(&tm1, (struct timezone *)0);
+	if (verbose && log)
+		fprintf(log, "Importing context: %7.4f seconds\n",
+			timeval_subtract(&tm1, &tm2));
+	(void) gss_release_buffer(&min_stat, &context_token);
+	return 0;
+}
+
+/*
+ * Function: sign_server
+ *
+ * Purpose: Performs the "sign" service.
+ *
+ * Arguments:
+ *
+ * 	s		(r) a TCP socket on which a connection has been
+ *			accept()ed
+ * 	service_name	(r) the ASCII name of the GSS-API service to
+ * 			establish a context as
+ *	export		(r) whether to test context exporting
+ * 
+ * Returns: -1 on error
+ *
+ * Effects:
+ *
+ * sign_server establishes a context, and performs a single sign request.
+ *
+ * A sign request is a single GSS-API sealed token.  The token is
+ * unsealed and a signature block, produced with gss_sign, is returned
+ * to the sender.  The context is the destroyed and the connection
+ * closed.
+ *
+ * If any error occurs, -1 is returned.
+ */
+static int sign_server(s, server_creds, export)
+     int s;
+     gss_cred_id_t server_creds;
+     int export;
+{
+    gss_buffer_desc client_name, xmit_buf, msg_buf;
+    gss_ctx_id_t context;
+    OM_uint32 maj_stat, min_stat;
+    int i, conf_state, ret_flags;
+    char	*cp;
+    int token_flags;
+
+    /* Establish a context with the client */
+    if (server_establish_context(s, server_creds, &context,
+                                  &client_name, &ret_flags) < 0)
+        return(-1);
+
+    if (context == GSS_C_NO_CONTEXT) {
+        printf("Accepted unauthenticated connection.\n");
+    }
+    else {
+        printf("Accepted connection: \"%.*s\"\n",
+                (int) client_name.length, (char *) client_name.value);
+        (void) gss_release_buffer(&min_stat, &client_name);
+
+        if (export) {
+            for (i=0; i < 3; i++)
+                if (test_import_export_context(&context))
+                    return -1;
+        }
+    }
+
+    do {
+        /* Receive the message token */
+        if (recv_token(s, &token_flags, &xmit_buf) < 0)
+            return(-1);
+
+        if (token_flags & TOKEN_NOOP) {
+            if (log)
+                fprintf(log, "NOOP token\n");
+            if(xmit_buf.value) {
+                free(xmit_buf.value);
+                xmit_buf.value = 0;
+            }
+            break;
+        }
+
+        if (verbose && log) {
+            fprintf(log, "Message token (flags=%d):\n", token_flags);
+            print_token(&xmit_buf);
+        }
+
+        if ((context == GSS_C_NO_CONTEXT) &&
+             (    token_flags & (TOKEN_WRAPPED|TOKEN_ENCRYPTED|TOKEN_SEND_MIC))) {
+            if (log)
+                fprintf(log,
+                         "Unauthenticated client requested authenticated services!\n");
+            if(xmit_buf.value) {
+                free (xmit_buf.value);
+                xmit_buf.value = 0;
+            }
+            return(-1);
+        }
+
+        if (token_flags & TOKEN_WRAPPED) {
+            maj_stat = gss_unwrap(&min_stat, context, &xmit_buf, &msg_buf,
+                                   &conf_state, (gss_qop_t *) NULL);
+            if (maj_stat != GSS_S_COMPLETE) {
+                display_status("unsealing message", maj_stat, min_stat);
+                if(xmit_buf.value) {
+                    free (xmit_buf.value);
+                    xmit_buf.value = 0;
+                }
+                return(-1);
+            } else if (! conf_state && (token_flags & TOKEN_ENCRYPTED)) {
+                fprintf(stderr, "Warning!  Message not encrypted.\n");
+            }
+
+            if(xmit_buf.value) {
+                free (xmit_buf.value);
+                xmit_buf.value = 0;
+            }
+        }
+        else {
+            msg_buf = xmit_buf;
+        }
+
+        if (log) {
+            fprintf(log, "Received message: ");
+            cp = msg_buf.value;
+            if ((isprint((int) cp[0]) || isspace((int) cp[0])) &&
+                 (isprint((int) cp[1]) || isspace((int) cp[1]))) {
+                fprintf(log, "\"%.*s\"\n", (int) msg_buf.length, 
+                         (char *) msg_buf.value);
+                 } else {
+                     fprintf(log, "\n");
+                     print_token(&msg_buf);
+                 }
+        }
+
+        if (token_flags & TOKEN_SEND_MIC) {
+            /* Produce a signature block for the message */
+            maj_stat = gss_get_mic(&min_stat, context, GSS_C_QOP_DEFAULT,
+                                    &msg_buf, &xmit_buf);
+            if (maj_stat != GSS_S_COMPLETE) {
+                display_status("signing message", maj_stat, min_stat);
+                return(-1);
+            }
+
+            if(msg_buf.value) {
+                free (msg_buf.value);
+                msg_buf.value = 0;
+            }
+
+            /* Send the signature block to the client */
+            if (send_token(s, TOKEN_MIC, &xmit_buf) < 0)
+                return(-1);
+
+            if(xmit_buf.value) {
+                free (xmit_buf.value);
+                xmit_buf.value = 0;
+            }
+        }
+        else {
+            if(msg_buf.value) {
+                free (msg_buf.value);
+                msg_buf.value = 0;
+            }
+            if (send_token(s, TOKEN_NOOP, empty_token) < 0)
+                return(-1);
+        }
+    } while (1 /* loop will break if NOOP received */);
+
+    if (context != GSS_C_NO_CONTEXT) {
+        /* Delete context */
+        maj_stat = gss_delete_sec_context(&min_stat, &context, NULL);
+        if (maj_stat != GSS_S_COMPLETE) {
+            display_status("deleting context", maj_stat, min_stat);
+            return(-1);
+        }
+    }
+
+    if (log)
+        fflush(log);
+
+    return(0);
+}
+
+static int max_threads = 1;
+
+#ifdef _WIN32
+static thread_count = 0;
+static HANDLE hMutex = NULL;
+static HANDLE hEvent = NULL;
+
+void
+InitHandles(void)
+{
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+void
+CleanupHandles(void)
+{
+    CloseHandle(hMutex);
+    CloseHandle(hEvent);
+}
+
+BOOL
+WaitAndIncrementThreadCounter(void)
+{
+    for (;;) {
+        if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+            if ( thread_count < max_threads ) {
+                thread_count++;
+                ReleaseMutex(hMutex);
+                return TRUE;
+            } else {
+                ReleaseMutex(hMutex);
+
+                if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) {
+                    continue;
+                } else {
+                    return FALSE;
+                }
+            }
+        } else {
+            return FALSE;
+        }
+    }
+}
+
+BOOL
+DecrementAndSignalThreadCounter(void)
+{
+    if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+        if ( thread_count == max_threads )
+            SetEvent(hEvent);
+        thread_count--;
+        ReleaseMutex(hMutex);
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+#else /* assume pthread */
+static pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t counter_cond = PTHREAD_COND_INITIALIZER;
+int counter = 0;
+
+static int
+WaitAndIncrementThreadCounter(void)
+{
+    int err;
+    err = pthread_mutex_lock(&counter_mutex);
+    if (err) {
+	perror("pthread_mutex_lock");
+	return 0;
+    }
+    if (counter == max_threads) {
+	err = pthread_cond_wait(&counter_cond, &counter_mutex);
+	if (err) {
+	    perror("pthread_cond_wait");
+	    return 0;
+	}
+    }
+    counter++;
+    pthread_mutex_unlock(&counter_mutex);
+    return 1;
+}
+static void
+DecrementAndSignalThreadCounter(void)
+{
+    int err;
+    err = pthread_mutex_lock(&counter_mutex);
+    if (err) {
+	perror("pthread_mutex_lock");
+	return;
+    }
+    if (counter == max_threads)
+	pthread_cond_broadcast(&counter_cond);
+    counter--;
+    pthread_mutex_unlock(&counter_mutex);
+}
+#endif
+
+struct _work_plan {
+    int             s;
+    gss_cred_id_t   server_creds;
+    int             export;
+};
+
+static void *
+worker_bee(void * param)
+{
+    struct _work_plan *work = (struct _work_plan *) param;
+
+    /* this return value is not checked, because there's
+     * not really anything to do if it fails 
+     */
+    sign_server(work->s, work->server_creds, work->export);
+    closesocket(work->s);
+    free(work);
+
+#if defined _WIN32 || 1
+    if ( max_threads > 1 )
+        DecrementAndSignalThreadCounter();
+#endif
+    return 0;
+}
+
+int
+main(argc, argv)
+     int argc;
+     char **argv;
+{
+     char *service_name;
+     gss_cred_id_t server_creds;
+     OM_uint32 min_stat;
+     u_short port = 4444;
+     int once = 0;
+     int do_inetd = 0;
+     int export = 0;
+
+     signal(SIGPIPE, SIG_IGN);
+     log = stdout;
+     display_file = stdout;
+     argc--; argv++;
+     while (argc) {
+	  if (strcmp(*argv, "-port") == 0) {
+	       argc--; argv++;
+	       if (!argc) usage();
+	       port = atoi(*argv);
+	  } 
+#if defined _WIN32 || 1
+          else if (strcmp(*argv, "-threads") == 0) {
+              argc--; argv++;
+              if (!argc) usage();
+              max_threads = atoi(*argv);
+          } 
+#endif
+          else if (strcmp(*argv, "-verbose") == 0) {
+	      verbose = 1;
+	  } else if (strcmp(*argv, "-once") == 0) {
+	      once = 1;
+	  } else if (strcmp(*argv, "-inetd") == 0) {
+	      do_inetd = 1;
+	  } else if (strcmp(*argv, "-export") == 0) {
+	      export = 1;
+	  } else if (strcmp(*argv, "-logfile") == 0) {
+	      argc--; argv++;
+	      if (!argc) usage();
+	      /* Gross hack, but it makes it unnecessary to add an
+                 extra argument to disable logging, and makes the code
+                 more efficient because it doesn't actually write data
+                 to /dev/null. */
+	      if (! strcmp(*argv, "/dev/null")) {
+		log = display_file = NULL;
+	      }
+	      else {
+		log = fopen(*argv, "a");
+		display_file = log;
+		if (!log) {
+		  perror(*argv);
+		  exit(1);
+		}
+	      }
+	  } else
+	       break;
+	  argc--; argv++;
+     }
+     if (argc != 1)
+	  usage();
+
+     if ((*argv)[0] == '-')
+	  usage();
+
+#ifdef _WIN32
+    if (max_threads < 1) {
+        fprintf(stderr, "warning: there must be at least one thread\n");
+        max_threads = 1;
+    }
+
+    if (max_threads > 1 && do_inetd)
+        fprintf(stderr, "warning: one thread may be used in conjunction with inetd\n");
+
+    InitHandles();
+#endif
+
+     service_name = *argv;
+
+     if (server_acquire_creds(service_name, &server_creds) < 0)
+	 return -1;
+     
+     if (do_inetd) {
+	 close(1);
+	 close(2);
+
+	 sign_server(0, server_creds, export);
+	 close(0);
+     } else {
+	 int stmp;
+
+ 	 if ((stmp = create_socket(port)) >= 0) {
+             if (listen(stmp, max_threads == 1 ? 0 : max_threads) < 0)
+                 perror("listening on socket");
+
+             do {
+                 struct _work_plan * work = malloc(sizeof(struct _work_plan));
+
+                 if ( work == NULL ) {
+                     fprintf(stderr, "fatal error: out of memory");
+                     break;
+                 }
+
+                 /* Accept a TCP connection */
+                 if ((work->s = accept(stmp, NULL, 0)) < 0) {
+                     perror("accepting connection");
+                     continue;
+                 }
+                  
+                 work->server_creds = server_creds;
+                 work->export = export;
+
+                 if (max_threads == 1) {
+                     worker_bee((void *)work);
+                 } 
+#if defined _WIN32 || 1
+                 else {
+                     if ( WaitAndIncrementThreadCounter() ) {
+#ifdef _WIN32
+                         uintptr_t handle = _beginthread(worker_bee, 0, (void *)work);
+                         if (handle == (uintptr_t)-1) {
+                             closesocket(work->s);
+                             free(work);
+                         }
+#else
+			 int err;
+			 pthread_t thr;
+			 err = pthread_create(&thr, 0, (void *(*)(void *))worker_bee,
+					      (void *) work);
+			 if (err) {
+			     perror("pthread_create");
+			     closesocket(work->s);
+			     free(work);
+			 }
+			 (void) pthread_detach(thr);
+#endif
+                     } else {
+                         fprintf(stderr, "fatal error incrementing thread counter");
+                         closesocket(work->s);
+                         free(work);
+                         break;
+                     }
+                 }
+#endif
+             } while (!once);
+
+ 	     closesocket(stmp);
+ 	 }
+     }
+
+     (void) gss_release_cred(&min_stat, &server_creds);
+
+#ifdef _WIN32
+    CleanupHandles();
+#else
+    if (max_threads > 1)
+	while (1)
+	    sleep (999999);
+#endif
+
+     return 0;
+}
diff --git a/krb5-1-6/src/tests/gssapi/Makefile.in b/krb5-1-6/src/tests/gssapi/Makefile.in
new file mode 100644
index 000000000..846a2411c
--- /dev/null
+++ b/krb5-1-6/src/tests/gssapi/Makefile.in
@@ -0,0 +1,27 @@
+thisconfigdir=./..
+myfulldir=tests/gssapi
+mydir=gssapi
+BUILDTOP=$(REL)..$(S)..
+DEFINES = -DUSE_AUTOCONF_H
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SRCS= $(srcdir)/t_imp_name.c
+
+OBJS= t_imp_name.o
+
+all:: t_imp_name
+
+t_imp_name: t_imp_name.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_imp_name t_imp_name.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
+
+clean::
+	$(RM) t_imp_name
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)t_imp_name.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_generic.h t_imp_name.c
diff --git a/krb5-1-6/src/tests/gssapi/t_imp_name.c b/krb5-1-6/src/tests/gssapi/t_imp_name.c
new file mode 100644
index 000000000..b7001b216
--- /dev/null
+++ b/krb5-1-6/src/tests/gssapi/t_imp_name.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 1996, Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Simple test program for testing how GSSAPI import name works.  (May
+ * be made into a more full-fledged test program later.)
+ * 
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+
+#define GSSAPI_V2
+void display_status (char *, OM_uint32, OM_uint32);
+static void display_status_1 (char *, OM_uint32, int);
+static void display_buffer (gss_buffer_desc);
+static int test_import_name (char *);
+
+FILE *display_file;
+
+int main(argc, argv)
+	int argc;
+	char **argv;
+{
+	int retval;
+
+	display_file = stdout;
+
+	retval = test_import_name("host@dcl.mit.edu");
+
+	return retval;
+}
+
+static int test_import_name(name)
+	char *name;
+{
+	OM_uint32 maj_stat, min_stat;
+	gss_name_t gss_name;
+	gss_buffer_desc buffer_name;
+	gss_OID	name_oid;
+
+	buffer_name.value = name;
+	buffer_name.length = strlen(name) + 1;
+	maj_stat = gss_import_name(&min_stat, &buffer_name,
+				   (gss_OID) gss_nt_service_name,
+				   &gss_name);
+	if (maj_stat != GSS_S_COMPLETE) {
+		display_status("parsing name", maj_stat, min_stat);
+		return -1;
+	}
+	
+	maj_stat = gss_display_name(&min_stat, gss_name, &buffer_name,
+				    &name_oid);
+	if (maj_stat != GSS_S_COMPLETE) {
+		display_status("displaying context", maj_stat, min_stat);
+		return -1;
+	}
+	printf("name is: ");
+	display_buffer(buffer_name);
+	printf("\n");
+	(void) gss_release_buffer(&min_stat, &buffer_name);
+
+	gss_oid_to_str(&min_stat, name_oid, &buffer_name);
+	printf("name type is: ");
+	display_buffer(buffer_name);
+	printf("\n");
+	(void) gss_release_buffer(&min_stat, &buffer_name);
+#ifdef	GSSAPI_V2
+	(void) gss_release_oid(&min_stat, &name_oid);
+#endif
+	(void) gss_release_name(&min_stat, &gss_name);
+	return 0;
+}
+
+static void display_buffer(buffer)
+	gss_buffer_desc buffer;
+{
+    char *namebuf;
+    
+    namebuf = malloc(buffer.length+1);    
+    if (!namebuf) {
+	fprintf(stderr, "display_buffer: couldn't allocate buffer!\n");
+	exit(1);
+    }
+    strncpy(namebuf, buffer.value, buffer.length);
+    namebuf[buffer.length] = '\0';
+    printf("%s", namebuf);
+    free(namebuf);
+}
+
+void display_status(msg, maj_stat, min_stat)
+     char *msg;
+     OM_uint32 maj_stat;
+     OM_uint32 min_stat;
+{
+     display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
+     display_status_1(msg, min_stat, GSS_C_MECH_CODE);
+}
+
+static void display_status_1(m, code, type)
+     char *m;
+     OM_uint32 code;
+     int type;
+{
+     OM_uint32 min_stat;
+     gss_buffer_desc msg;
+#ifdef	GSSAPI_V2
+     OM_uint32 msg_ctx;
+#else	/* GSSAPI_V2 */
+     int msg_ctx;
+#endif	/* GSSAPI_V2 */
+     
+     msg_ctx = 0;
+     while (1) {
+	  (void) gss_display_status(&min_stat, code,
+				       type, GSS_C_NULL_OID,
+				       &msg_ctx, &msg);
+	  if (display_file)
+	      fprintf(display_file, "GSS-API error %s: %s\n", m,
+		      (char *)msg.value); 
+	  (void) gss_release_buffer(&min_stat, &msg);
+	  
+	  if (!msg_ctx)
+	       break;
+     }
+}
+
diff --git a/krb5-1-6/src/tests/hammer/Makefile.in b/krb5-1-6/src/tests/hammer/Makefile.in
new file mode 100644
index 000000000..d87cc92db
--- /dev/null
+++ b/krb5-1-6/src/tests/hammer/Makefile.in
@@ -0,0 +1,33 @@
+thisconfigdir=./..
+myfulldir=tests/hammer
+mydir=hammer
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+SRCS=$(srcdir)/kdc5_hammer.c
+
+all:: kdc5_hammer
+
+kdc5_hammer: kdc5_hammer.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o kdc5_hammer kdc5_hammer.o $(KRB5_BASE_LIBS)
+
+install::
+
+clean::
+	$(RM) kdc5_hammer.o kdc5_hammer
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kdc5_hammer.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  kdc5_hammer.c
diff --git a/krb5-1-6/src/tests/hammer/kdc5_hammer.c b/krb5-1-6/src/tests/hammer/kdc5_hammer.c
new file mode 100644
index 000000000..5fd8d1c51
--- /dev/null
+++ b/krb5-1-6/src/tests/hammer/kdc5_hammer.c
@@ -0,0 +1,530 @@
+/*
+ * tests/hammer/kdc5_hammer.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Initialize a credentials cache.
+ */
+
+#include <stdio.h>
+#include <sys/time.h>
+
+#include "k5-int.h"
+#include "com_err.h"
+
+#define KRB5_DEFAULT_OPTIONS 0
+#define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */
+#define KRB5_RENEWABLE_LIFE 60*60*2 /* 2 hours */
+
+struct h_timer {
+    float	ht_cumulative;
+    float	ht_min;
+    float	ht_max;
+    krb5_int32	ht_observations;
+};
+
+extern int optind;
+extern char *optarg;
+char *prog;
+
+static int brief;
+static char *cur_realm = 0;
+static int do_timer = 0;
+
+krb5_data tgtname = {
+    0, 
+    KRB5_TGS_NAME_SIZE,
+    KRB5_TGS_NAME
+};
+
+int verify_cs_pair 
+	(krb5_context,
+		   char *,
+		   krb5_principal,
+		   char *,
+		   char *,
+		   int, int, int,
+		   krb5_ccache);
+
+int get_tgt 
+	(krb5_context,
+		   char *,
+		   krb5_principal *,
+		   krb5_ccache);
+
+static void
+usage(who, status)
+char *who;
+int status;
+{
+    fprintf(stderr,
+	    "usage: %s -p prefix -n num_to_check [-c cachename] [-r realmname]\n",
+	    who);
+    fprintf(stderr, "\t [-D depth]\n");
+    fprintf(stderr, "\t [-P preauth type] [-R repeat_count] [-t] [-b] [-v] \n");
+
+    exit(status);
+}
+
+static krb5_preauthtype * patype = NULL, patypedata[2] = { 0, -1 };
+static krb5_context test_context;
+
+struct timeval	tstart_time, tend_time;
+struct timezone	dontcare;
+
+struct h_timer in_tkt_times = { 0.0, 1000000.0, -1.0, 0 };
+struct h_timer tgs_req_times = { 0.0, 1000000.0, -1.0, 0 };
+/*
+ * Timer macros.
+ */
+#define	swatch_on()	((void) gettimeofday(&tstart_time, &dontcare))
+#define	swatch_eltime()	((gettimeofday(&tend_time, &dontcare)) ? -1.0 :	\
+			 (((float) (tend_time.tv_sec -			\
+				    tstart_time.tv_sec)) +		\
+			  (((float) (tend_time.tv_usec -		\
+				     tstart_time.tv_usec))/1000000.0)))
+
+int
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    krb5_ccache ccache = NULL;
+    char *cache_name = NULL;		/* -f option */
+    int option;
+    int errflg = 0;
+    krb5_error_code code;
+    int num_to_check, n, i, j, repeat_count, counter;
+    int n_tried, errors;
+    char prefix[BUFSIZ], client[4096], server[4096];
+    int depth;
+    char ctmp[4096], ctmp2[BUFSIZ], stmp[4096], stmp2[BUFSIZ];
+    krb5_principal client_princ;
+    krb5_error_code retval;
+
+    krb5_init_context(&test_context);
+
+    if (strrchr(argv[0], '/'))
+	prog = strrchr(argv[0], '/')+1;
+    else
+	prog = argv[0];
+
+    num_to_check = 0;
+    depth = 1;
+    repeat_count = 1;
+    brief = 0;
+    n_tried = 0;
+    errors = 0;
+
+    while ((option = getopt(argc, argv, "D:p:n:c:R:P:e:bvr:t")) != -1) {
+	switch (option) {
+	case 't':
+	    do_timer = 1;
+	    break;
+	case 'b':
+	    brief = 1;
+	    break;
+	case 'v':
+	    brief = 0;
+	    break;
+	case 'R':
+	    repeat_count = atoi(optarg); /* how many times? */
+	    break;
+	case 'r':
+	    cur_realm = optarg;
+	    break;
+	case 'D':
+	    depth = atoi(optarg);       /* how deep to go */
+	    break;
+	case 'p':                       /* prefix name to check */
+	    strncpy(prefix, optarg, sizeof(prefix) - 1);
+	    prefix[sizeof(prefix) - 1] = '\0';
+	    break;
+       case 'n':                        /* how many to check */
+	    num_to_check = atoi(optarg);
+	    break;
+	case 'P':
+	    patypedata[0] = atoi(optarg);
+	    patype = patypedata;
+	    break;
+	case 'c':
+	    if (ccache == NULL) {
+		cache_name = optarg;
+		
+		code = krb5_cc_resolve (test_context, cache_name, &ccache);
+		if (code != 0) {
+		    com_err (prog, code, "resolving %s", cache_name);
+		    errflg++;
+		}
+	    } else {
+		fprintf(stderr, "Only one -c option allowed\n");
+		errflg++;
+	    }
+	    break;
+	case '?':
+	default:
+	    errflg++;
+	    break;
+	}
+    }
+
+    if (!(num_to_check && prefix[0])) usage(prog, 1);
+
+    if (!cur_realm) {
+	if ((retval = krb5_get_default_realm(test_context, &cur_realm))) {
+	    com_err(prog, retval, "while retrieving default realm name");
+	    exit(1);
+	}	    
+    }
+
+    if (ccache == NULL) {
+	if ((code = krb5_cc_default(test_context, &ccache))) {
+	    com_err(prog, code, "while getting default ccache");
+	    exit(1);
+	}
+    }
+
+    memset(ctmp, 0, sizeof(ctmp));
+    memset(stmp, 0, sizeof(stmp));
+
+    for (counter = 0; counter < repeat_count; counter++) {
+      fprintf(stderr, "\nRound %d\n", counter);
+
+      for (n = 1; n <= num_to_check; n++) {
+	/* build the new principal name */
+	/* we can't pick random names because we need to generate all the names 
+	   again given a prefix and count to test the db lib and kdb */
+	ctmp[0] = '\0';
+	for (i = 1; i <= depth; i++) {
+	  (void) sprintf(ctmp2, "%s%s%d-DEPTH-%d", (i != 1) ? "/" : "",
+			 prefix, n, i);
+	  ctmp2[sizeof(ctmp2) - 1] = '\0';
+	  strncat(ctmp, ctmp2, sizeof(ctmp) - 1 - strlen(ctmp));
+	  ctmp[sizeof(ctmp) - 1] = '\0';
+	  sprintf(client, "%s@%s", ctmp, cur_realm);
+
+	  if (get_tgt (test_context, client, &client_princ, ccache)) {
+	    errors++;
+	    n_tried++;
+	    continue;
+	  }
+	  n_tried++;
+
+	  stmp[0] = '\0';
+	  for (j = 1; j <= depth; j++) {
+	    (void) sprintf(stmp2, "%s%s%d-DEPTH-%d", (j != 1) ? "/" : "",
+			   prefix, n, j);
+	    stmp2[sizeof (stmp2) - 1] = '\0';
+	    strncat(stmp, stmp2, sizeof(stmp) - 1 - strlen(stmp));
+	    stmp[sizeof(stmp) - 1] = '\0';
+	    sprintf(server, "%s@%s", stmp, cur_realm);
+	    if (verify_cs_pair(test_context, client, client_princ, 
+			       stmp, cur_realm, n, i, j, ccache))
+	      errors++;
+	    n_tried++;
+	  }
+	  krb5_free_principal(test_context, client_princ);
+	}
+      }
+    }
+    fprintf (stderr, "\nTried %d.  Got %d errors.\n", n_tried, errors);
+    if (do_timer) {
+	if (in_tkt_times.ht_observations)
+	    fprintf(stderr, 
+		    "%8d  AS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n",
+		    in_tkt_times.ht_observations,
+		    in_tkt_times.ht_cumulative /
+		    (float) in_tkt_times.ht_observations,
+		    in_tkt_times.ht_min,
+		    in_tkt_times.ht_max);
+	if (tgs_req_times.ht_observations)
+	    fprintf(stderr, 
+		    "%8d TGS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n",
+		    tgs_req_times.ht_observations,
+		    tgs_req_times.ht_cumulative /
+		    (float) tgs_req_times.ht_observations,
+		    tgs_req_times.ht_min,
+		    tgs_req_times.ht_max);
+    }
+
+    (void) krb5_cc_close(test_context, ccache);
+
+    krb5_free_context(test_context);
+
+    exit(errors);
+  }
+
+
+static krb5_error_code 
+get_server_key(context, server, enctype, key)
+    krb5_context context;
+    krb5_principal server;
+    krb5_enctype enctype;
+    krb5_keyblock ** key;
+{
+    krb5_error_code retval;
+    krb5_encrypt_block eblock;
+    char * string;
+    krb5_data salt;
+    krb5_data pwd;
+
+    if ((retval = krb5_principal2salt(context, server, &salt)))
+	return retval;
+
+    if ((retval = krb5_unparse_name(context, server, &string)))
+	goto cleanup_salt;
+
+    pwd.data = string;
+    pwd.length = strlen(string);
+
+    if ((*key = (krb5_keyblock *)malloc(sizeof(krb5_keyblock)))) {
+    	krb5_use_enctype(context, &eblock, enctype);
+    	if ((retval = krb5_string_to_key(context, &eblock, *key, &pwd, &salt)))
+	    free(*key);
+    } else 
+        retval = ENOMEM;
+
+    free(string);
+
+cleanup_salt:
+    free(salt.data);
+    return retval;
+}
+
+int verify_cs_pair(context, p_client_str, p_client, service, hostname, 
+		   p_num, c_depth, s_depth, ccache)
+    krb5_context context;
+    char *p_client_str;
+    krb5_principal p_client;
+    char * service;
+    char * hostname;
+    int p_num, c_depth, s_depth;
+    krb5_ccache ccache;
+{
+    krb5_error_code 	  retval;
+    krb5_creds 	 	  creds;
+    krb5_creds 		* credsp = NULL;
+    krb5_ticket 	* ticket = NULL;
+    krb5_keyblock 	* keyblock = NULL;
+    krb5_auth_context 	  auth_context = NULL;
+    krb5_data		  request_data;
+    char		* sname;
+    float		  dt;
+
+    if (brief)
+      fprintf(stderr, "\tprinc (%d) client (%d) for server (%d)\n", 
+	      p_num, c_depth, s_depth);
+    else
+      fprintf(stderr, "\tclient %s for server %s\n", p_client_str, 
+	      service);
+
+    /* Initialize variables */
+    memset((char *)&creds, 0, sizeof(creds));
+
+    /* Do client side */
+    sname = (char *) malloc(strlen(service)+strlen(hostname)+2);
+    if (sname) {
+	sprintf(sname, "%s@%s", service, hostname);
+	retval = krb5_parse_name(context, sname, &creds.server);
+	free(sname);
+    }
+    else
+	retval = ENOMEM;
+    if (retval)
+	return(retval);
+
+    /* obtain ticket & session key */
+    if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) {
+	com_err(prog, retval, "while getting client princ for %s", hostname);
+    	krb5_free_cred_contents(context, &creds);
+	return retval;
+    }
+
+    if ((retval = krb5_get_credentials(context, 0,
+                                      ccache, &creds, &credsp))) {
+	com_err(prog, retval, "while getting creds for %s", hostname);
+    	krb5_free_cred_contents(context, &creds);
+	return retval;
+    }
+
+    krb5_free_cred_contents(context, &creds);
+
+    if (do_timer)
+	swatch_on();
+
+    if ((retval = krb5_mk_req_extended(context, &auth_context, 0, NULL,
+			            credsp, &request_data))) {
+	com_err(prog, retval, "while preparing AP_REQ for %s", hostname);
+        krb5_auth_con_free(context, auth_context);
+	return retval;
+    }
+
+    krb5_auth_con_free(context, auth_context);
+    auth_context = NULL;
+
+    /* Do server side now */
+    if ((retval = get_server_key(context, credsp->server,
+				credsp->keyblock.enctype, &keyblock))) {
+	com_err(prog, retval, "while getting server key for %s", hostname);
+	goto cleanup_rdata;
+    }
+
+    if (krb5_auth_con_init(context, &auth_context)) {
+	com_err(prog, retval, "while creating auth_context for %s", hostname);
+	goto cleanup_keyblock;
+    }
+
+    if (krb5_auth_con_setuseruserkey(context, auth_context, keyblock)) {
+	com_err(prog, retval, "while setting auth_context key %s", hostname);
+	goto cleanup_keyblock;
+    }
+
+    if ((retval = krb5_rd_req(context, &auth_context, &request_data, 
+			     NULL /* server */, 0, NULL, &ticket))) { 
+	com_err(prog, retval, "while decoding AP_REQ for %s", hostname); 
+        krb5_auth_con_free(context, auth_context);
+	goto cleanup_keyblock;
+    }
+
+    if (do_timer) {
+	dt = swatch_eltime();
+	tgs_req_times.ht_cumulative += dt;
+	tgs_req_times.ht_observations++;
+	if (dt > tgs_req_times.ht_max)
+	    tgs_req_times.ht_max = dt;
+	if (dt < tgs_req_times.ht_min)
+	    tgs_req_times.ht_min = dt;
+    }
+
+    krb5_auth_con_free(context, auth_context);
+
+    if (!(krb5_principal_compare(context,ticket->enc_part2->client,p_client))){
+    	char *returned_client;
+        if ((retval = krb5_unparse_name(context, ticket->enc_part2->client, 
+			       	       &returned_client))) 
+	    com_err (prog, retval, 
+		     "Client not as expected, but cannot unparse client name");
+      	else
+	    com_err (prog, 0, "Client not as expected (%s).", returned_client);
+	retval = KRB5_PRINC_NOMATCH;
+      	free(returned_client);
+    } else {
+	retval = 0;
+    }
+
+    krb5_free_ticket(context, ticket);
+
+cleanup_keyblock:
+    krb5_free_keyblock(context, keyblock);
+
+cleanup_rdata:
+    krb5_free_data_contents(context, &request_data);
+    if(credsp ) krb5_free_creds(context, credsp);
+
+    return retval;
+}
+
+int get_tgt (context, p_client_str, p_client, ccache)
+    krb5_context context;
+    char *p_client_str;
+    krb5_principal *p_client;
+    krb5_ccache ccache;
+{
+    char *cache_name = NULL;		/* -f option */
+    long lifetime = KRB5_DEFAULT_LIFE;	/* -l option */
+    int options = KRB5_DEFAULT_OPTIONS;
+    krb5_error_code code;
+    krb5_creds my_creds;
+    krb5_timestamp start;
+    krb5_principal tgt_server;
+    float dt;
+
+    if (!brief)
+      fprintf(stderr, "\tgetting TGT for %s\n", p_client_str);
+
+    if ((code = krb5_timeofday(context, &start))) {
+	com_err(prog, code, "while getting time of day");
+	return(-1);
+    }
+
+    memset((char *)&my_creds, 0, sizeof(my_creds));
+    
+    if ((code = krb5_parse_name (context, p_client_str, p_client))) {
+	com_err (prog, code, "when parsing name %s", p_client_str);
+	return(-1);
+    }
+
+
+    if ((code = krb5_build_principal_ext(context, &tgt_server,
+				krb5_princ_realm(context, *p_client)->length,
+				krb5_princ_realm(context, *p_client)->data,
+				tgtname.length,
+				tgtname.data,
+				krb5_princ_realm(context, *p_client)->length,
+				krb5_princ_realm(context, *p_client)->data,
+				0))) {
+	com_err(prog, code, "when setting up tgt principal");
+	return(-1);
+    }
+
+    my_creds.client = *p_client;
+    my_creds.server = tgt_server;
+
+    code = krb5_cc_initialize (context, ccache, *p_client);
+    if (code != 0) {
+	com_err (prog, code, "when initializing cache %s",
+		 cache_name?cache_name:"");
+	return(-1);
+    }
+
+    my_creds.times.starttime = 0;	/* start timer when request
+					   gets to KDC */
+    my_creds.times.endtime = start + lifetime;
+    my_creds.times.renew_till = 0;
+
+    if (do_timer)
+	swatch_on();
+
+    code = krb5_get_in_tkt_with_password(context, options, 0,
+					 NULL, patype, p_client_str, ccache,
+					 &my_creds, 0);
+    if (do_timer) {
+	dt = swatch_eltime();
+	in_tkt_times.ht_cumulative += dt;
+	in_tkt_times.ht_observations++;
+	if (dt > in_tkt_times.ht_max)
+	    in_tkt_times.ht_max = dt;
+	if (dt < in_tkt_times.ht_min)
+	    in_tkt_times.ht_min = dt;
+    }
+    my_creds.server = my_creds.client = 0;
+    krb5_free_principal(context, tgt_server);
+    krb5_free_cred_contents(context, &my_creds);
+    if (code != 0) {
+	com_err (prog, code, "while getting initial credentials");
+	return(-1);
+      }
+
+    return(0);
+}
diff --git a/krb5-1-6/src/tests/hammer/pp.c b/krb5-1-6/src/tests/hammer/pp.c
new file mode 100644
index 000000000..403d60de8
--- /dev/null
+++ b/krb5-1-6/src/tests/hammer/pp.c
@@ -0,0 +1,28 @@
+/*
+ * tests/hammer/pp.c
+ *
+ * Copyright 1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/copyright.h>.
+ *
+ */
+
+#include "krb5.h"
+
+void
+print_principal(p)
+	krb5_principal	p;
+{
+	char	*buf;
+	krb5_error_code	retval;
+
+	if (retval = krb5_unparse_name(p, &buf)) {
+		com_err("DEBUG: Print_principal", retval,
+			"while unparsing name");
+		exit(1);
+	}
+	printf("%s\n", buf);
+	free(buf);
+}
diff --git a/krb5-1-6/src/tests/misc/Makefile.in b/krb5-1-6/src/tests/misc/Makefile.in
new file mode 100644
index 000000000..a22acde1c
--- /dev/null
+++ b/krb5-1-6/src/tests/misc/Makefile.in
@@ -0,0 +1,35 @@
+thisconfigdir=./..
+myfulldir=tests/misc
+mydir=misc
+BUILDTOP=$(REL)..$(S)..
+RUN_SETUP = @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+OBJS=test_getpw.o
+SRCS=$(srcdir)/test_getpw.c
+
+all:: test_getpw
+
+check:: test_getpw
+	$(RUN_SETUP) $(VALGRIND) ./test_getpw
+
+test_getpw: $(OUTPRE)test_getpw.$(OBJEXT) $(SUPPORT_DEPLIB)
+	$(CC_LINK) $(ALL_CFLAGS) -o test_getpw $(OUTPRE)test_getpw.$(OBJEXT) $(SUPPORT_LIB)
+
+test_getsockname: $(OUTPRE)test_getsockname.$(OBJEXT)
+	$(CC_LINK) $(ALL_CFLAGS) -o test_getsockname $(OUTPRE)test_getsockname.$(OBJEXT) $(LIBS)
+
+install::
+
+clean::
+	$(RM) test_getpw
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)test_getpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  test_getpw.c
diff --git a/krb5-1-6/src/tests/misc/test_getpw.c b/krb5-1-6/src/tests/misc/test_getpw.c
new file mode 100644
index 000000000..6d0fb1845
--- /dev/null
+++ b/krb5-1-6/src/tests/misc/test_getpw.c
@@ -0,0 +1,25 @@
+#include "autoconf.h"
+#include "k5-platform.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+int main()
+{
+    uid_t my_uid;
+    struct passwd *pwd, pwx;
+    char pwbuf[BUFSIZ];
+    int x;
+
+    my_uid = getuid();
+    printf("my uid: %ld\n", (long) my_uid);
+
+    x = k5_getpwuid_r(my_uid, &pwx, pwbuf, sizeof(pwbuf), &pwd);
+    printf("k5_getpwuid_r returns %d\n", x);
+    if (x != 0)
+	exit(1);
+    printf("    username is '%s'\n", pwd->pw_name);
+    exit(0);
+}
diff --git a/krb5-1-6/src/tests/misc/test_getsockname.c b/krb5-1-6/src/tests/misc/test_getsockname.c
new file mode 100644
index 000000000..7c85e7476
--- /dev/null
+++ b/krb5-1-6/src/tests/misc/test_getsockname.c
@@ -0,0 +1,91 @@
+/*
+ * test_getsockname.c
+ * 
+ * This routine demonstrates a bug in the socket emulation library of
+ * Solaris and other monstrosities that uses STREAMS.  On other
+ * machines with a real networking layer, it prints the local
+ * interface address that is used to send a message to a specific
+ * host.  On Solaris, it prints out 0.0.0.0.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include "autoconf.h"
+
+int
+main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int sock;
+    GETSOCKNAME_ARG3_TYPE i;
+    struct hostent *host;
+    struct sockaddr_in s_sock;		/* server address */
+    struct sockaddr_in c_sock;		/* client address */
+    
+    char *hostname;
+
+    if (argc == 2) {
+	hostname = argv[1];
+    } else {
+	fprintf(stderr, "Usage: %s hostname\n", argv[0]);
+	exit(1);
+    }
+
+    /* Look up server host */
+    if ((host = gethostbyname(hostname)) == (struct hostent *) 0) {
+	fprintf(stderr, "%s: unknown host\n", hostname);
+	exit(1);
+    }
+
+    /* Set server's address */
+    (void) memset((char *)&s_sock, 0, sizeof(s_sock));
+
+    memcpy((char *)&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr));
+#ifdef DEBUG
+    printf("s_sock.sin_addr is %s\n", inet_ntoa(s_sock.sin_addr));
+#endif
+    s_sock.sin_family = AF_INET;
+    s_sock.sin_port = htons(5555);
+    
+    /* Open a socket */
+    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+	perror("socket");
+	exit(1);
+    }
+
+    memset((char *)&c_sock, 0, sizeof(c_sock));
+    c_sock.sin_family = AF_INET;
+
+    /* Bind it to set the address; kernel will fill in port # */
+    if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) {
+	perror("bind");
+	exit(1);
+    }
+	
+    /* "connect" the datagram socket; this is necessary to get a local address
+       properly bound for getsockname() below. */
+    if (connect(sock, (struct sockaddr *)&s_sock, sizeof(s_sock)) == -1) {
+	perror("connect");
+	exit(1);
+    }
+    
+    /* Get my address */
+    memset((char *) &c_sock, 0, sizeof(c_sock));
+    i = sizeof(c_sock);
+    if (getsockname(sock, (struct sockaddr *)&c_sock, &i) < 0) {
+	perror("getsockname");
+	exit(1);
+    }
+
+    printf("My interface address is: %s\n", inet_ntoa(c_sock.sin_addr));
+    
+    exit(0);
+}
diff --git a/krb5-1-6/src/tests/misc/test_nfold.c b/krb5-1-6/src/tests/misc/test_nfold.c
new file mode 100644
index 000000000..78b586618
--- /dev/null
+++ b/krb5-1-6/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/krb5-1-6/src/tests/resolve/Makefile.in b/krb5-1-6/src/tests/resolve/Makefile.in
new file mode 100644
index 000000000..65981d285
--- /dev/null
+++ b/krb5-1-6/src/tests/resolve/Makefile.in
@@ -0,0 +1,44 @@
+thisconfigdir=./..
+myfulldir=tests/resolve
+mydir=resolve
+BUILDTOP=$(REL)..$(S)..
+RUN_SETUP = @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+OBJS=resolve.o addrinfo-test.o fake-addrinfo-test.o
+SRCS=$(srcdir)/resolve.c $(srcdir)/addrinfo-test.c \
+	$(srcdir)/fake-addrinfo-test.c
+
+all:: resolve addrinfo-test fake-addrinfo-test
+
+resolve: resolve.o
+	$(CC_LINK) -o $@ resolve.o $(LIBS)
+
+addrinfo-test: addrinfo-test.o
+	$(CC_LINK) -o $@ addrinfo-test.o $(LIBS)
+
+fake-addrinfo-test: fake-addrinfo-test.o
+	$(CC_LINK) -o $@ fake-addrinfo-test.o $(SUPPORT_LIB) $(LIBS)
+
+check:: resolve addrinfo-test
+	$(RUN_SETUP) $(VALGRIND) ./resolve
+	$(RUN_SETUP) $(VALGRIND) ./addrinfo-test -p telnet
+	$(RUN_SETUP) $(VALGRIND) ./fake-addrinfo-test -p telnet
+
+install::
+
+clean::
+	$(RM) resolve addrinfo-test
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)resolve.$(OBJEXT): resolve.c
+$(OUTPRE)addrinfo-test.$(OBJEXT): addrinfo-test.c
+$(OUTPRE)fake-addrinfo-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h addrinfo-test.c fake-addrinfo-test.c
diff --git a/krb5-1-6/src/tests/resolve/addrinfo-test.c b/krb5-1-6/src/tests/resolve/addrinfo-test.c
new file mode 100644
index 000000000..10394e7ae
--- /dev/null
+++ b/krb5-1-6/src/tests/resolve/addrinfo-test.c
@@ -0,0 +1,303 @@
+/*
+ * test/resolve/addrinfo-test.c
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * A simple program to test the functionality of the getaddrinfo function.
+ *
+ * Usage:
+ *   addrinfo-test [-t|-u|-R|-I] [-d|-s|-r] [-p port] [-P] [hostname]
+ *
+ *   When invoked with no arguments, NULL is used for the node name,
+ *   which (at least with a non-null "port") means a socket address
+ *   is desired that can be used with connect() or bind() (depending
+ *   on whether "-P" is given).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h> /* needed for IPPROTO_* on NetBSD */
+#ifdef USE_FAKE_ADDRINFO
+#include "fake-addrinfo.h"
+#endif
+
+static const char *protoname (int p) {
+    static char buf[30];
+
+#define X(N) if (p == IPPROTO_ ## N) return #N
+
+    X(TCP);
+    X(UDP);
+    X(ICMP);
+    X(IPV6);
+#ifdef IPPROTO_GRE
+    X(GRE);
+#endif
+    X(NONE);
+    X(RAW);
+#ifdef IPPROTO_COMP
+    X(COMP);
+#endif
+
+    sprintf(buf, " %-2d", p);
+    return buf;
+}	
+
+static const char *socktypename (int t) {
+    static char buf[30];
+    switch (t) {
+    case SOCK_DGRAM: return "DGRAM";
+    case SOCK_STREAM: return "STREAM";
+    case SOCK_RAW: return "RAW";
+    case SOCK_RDM: return "RDM";
+    case SOCK_SEQPACKET: return "SEQPACKET";
+    }
+    sprintf(buf, " %-2d", t);
+    return buf;
+}
+
+static char *whoami;
+
+static void usage () {
+    fprintf(stderr,
+	    "usage:\n"
+	    "\t%s [ options ] [host]\n"
+	    "options:\n"
+	    "\t-t\tspecify protocol IPPROTO_TCP\n"
+	    "\t-u\tspecify protocol IPPROTO_UDP\n"
+	    "\t-R\tspecify protocol IPPROTO_RAW\n"
+	    "\t-I\tspecify protocol IPPROTO_ICMP\n"
+	    "\n"
+	    "\t-d\tspecify socket type SOCK_DGRAM\n"
+	    "\t-s\tspecify socket type SOCK_STREAM\n"
+	    "\t-r\tspecify socket type SOCK_RAW\n"
+	    "\n"
+	    "\t-4\tspecify address family AF_INET\n"
+	    "\t-6\tspecify address family AF_INET6\n"
+	    "\n"
+	    "\t-p P\tspecify port P (service name or port number)\n"
+	    "\t-N\thostname is numeric, skip DNS query\n"
+	    "\t-n\tservice/port is numeric (sets AI_NUMERICSERV)\n"
+	    "\t-P\tset AI_PASSIVE\n"
+	    "\n"
+	    "default: protocol 0, socket type 0, address family 0, null port\n"
+	    ,
+	    whoami);
+    /* [ -t | -u | -R | -I ] [ -d | -s | -r ] [ -p port ] */
+    exit (1);
+}
+
+static const char *familyname (int f) {
+    static char buf[30];
+    switch (f) {
+    default:
+	sprintf(buf, "AF %d", f);
+	return buf;
+    case AF_INET: return "AF_INET";
+    case AF_INET6: return "AF_INET6";
+    }
+}
+
+#define eaistr(X) (X == EAI_SYSTEM ? strerror(errno) : gai_strerror(X))
+
+int main (int argc, char *argv[])
+{
+    struct addrinfo *ap, *ap2;
+    int err, numerichost = 0, numericserv = 0;
+    char *hname, *port = 0, *sep;
+    struct addrinfo hints;
+
+    whoami = strrchr(argv[0], '/');
+    if (whoami == 0)
+	whoami = argv[0];
+    else
+	whoami = whoami+1;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_flags = 0;
+    hints.ai_socktype = 0;
+
+    hname = 0;
+    hints.ai_family = 0;
+
+    if (argc == 1)
+	usage ();
+
+    while (++argv, --argc > 0) {
+	char *arg;
+	arg = *argv;
+
+	if (*arg != '-')
+	    hname = arg;
+	else if (arg[1] == 0 || arg[2] != 0)
+	    usage ();
+	else
+	    switch (arg[1]) {
+	    case 'u':
+		hints.ai_protocol = IPPROTO_UDP;
+		break;
+	    case 't':
+		hints.ai_protocol = IPPROTO_TCP;
+		break;
+	    case 'R':
+		hints.ai_protocol = IPPROTO_RAW;
+		break;
+	    case 'I':
+		hints.ai_protocol = IPPROTO_ICMP;
+		break;
+	    case 'd':
+		hints.ai_socktype = SOCK_DGRAM;
+		break;
+	    case 's':
+		hints.ai_socktype = SOCK_STREAM;
+		break;
+	    case 'r':
+		hints.ai_socktype = SOCK_RAW;
+		break;
+	    case 'p':
+		if (argv[1] == 0 || argv[1][0] == 0 || argv[1][0] == '-')
+		    usage ();
+		port = argv[1];
+		argc--, argv++;
+		break;
+	    case '4':
+		hints.ai_family = AF_INET;
+		break;
+	    case '6':
+		hints.ai_family = AF_INET6;
+		break;
+	    case 'N':
+		numerichost = 1;
+		break;
+	    case 'n':
+		numericserv = 1;
+		break;
+	    case 'P':
+		hints.ai_flags |= AI_PASSIVE;
+		break;
+	    default:
+		usage ();
+	    }
+    }
+
+    if (hname && !numerichost)
+	hints.ai_flags |= AI_CANONNAME;
+    if (numerichost) {
+#ifdef AI_NUMERICHOST
+	hints.ai_flags |= AI_NUMERICHOST;
+#else
+	fprintf(stderr, "AI_NUMERICHOST not defined on this platform\n");
+	exit(1);
+#endif
+    }
+    if (numericserv) {
+#ifdef AI_NUMERICSERV
+	hints.ai_flags |= AI_NUMERICSERV;
+#else
+	fprintf(stderr, "AI_NUMERICSERV not defined on this platform\n");
+	exit(1);
+#endif
+    }
+
+    printf("getaddrinfo(hostname %s, service %s,\n"
+	   "            hints { ",
+	   hname ? hname : "(null)", port ? port : "(null)");
+    sep = "";
+#define Z(FLAG) if (hints.ai_flags & AI_##FLAG) printf("%s%s", sep, #FLAG), sep = "|"
+    Z(CANONNAME);
+    Z(PASSIVE);
+#ifdef AI_NUMERICHOST
+    Z(NUMERICHOST);
+#endif
+#ifdef AI_NUMERICSERV
+    Z(NUMERICSERV);
+#endif
+    if (sep[0] == 0)
+	printf ("no-flags");
+    if (hints.ai_family)
+	printf(" %s", familyname(hints.ai_family));
+    if (hints.ai_socktype)
+	printf(" SOCK_%s", socktypename(hints.ai_socktype));
+    if (hints.ai_protocol)
+	printf(" IPPROTO_%s", protoname(hints.ai_protocol));
+    printf(" }):\n");
+
+    err = getaddrinfo(hname, port, &hints, &ap);
+    if (err) {
+	printf("\terror => %s\n", eaistr(err));
+	return 1;
+    }
+
+#if defined(SIN6_LEN)
+    if (ap->ai_addr->sa_len == 0)
+	printf ("BAD: sa_len not set!\n");
+#endif
+
+
+    for (ap2 = ap; ap2; ap2 = ap2->ai_next) {
+	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+	/* If we don't do this, even AIX's own getnameinfo will reject
+	   the sockaddr structures.  The sa_len field doesn't get set
+	   either, on AIX, but getnameinfo won't complain.  */
+	if (ap2->ai_addr->sa_family == 0) {
+	    printf("BAD: sa_family zero! fixing...\n");
+	    ap2->ai_addr->sa_family = ap2->ai_family;
+	} else if (ap2->ai_addr->sa_family != ap2->ai_family) {
+	    printf("BAD: sa_family != ai_family! fixing...\n");
+	    ap2->ai_addr->sa_family = ap2->ai_family;
+	}
+	if (getnameinfo(ap2->ai_addr, ap2->ai_addrlen, hbuf, sizeof(hbuf),
+			pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV))
+	    strcpy(hbuf, "..."), strcpy(pbuf, "...");
+	printf("%p:\n"
+	       "\tfamily = %s\tproto = %-4s\tsocktype = %s\n",
+	       ap2, familyname(ap2->ai_family),
+	       protoname (ap2->ai_protocol),
+	       socktypename (ap2->ai_socktype));
+	if (ap2->ai_canonname) {
+	    if (ap2->ai_canonname[0])
+		printf("\tcanonname = %s\n", ap2->ai_canonname);
+	    else
+		printf("BAD: ai_canonname is set but empty!\n");
+	} else if (ap2 == ap && (hints.ai_flags & AI_CANONNAME)) {
+	    printf("BAD: first ai_canonname is null!\n");
+	}
+	printf("\taddr = %-28s\tport = %s\n", hbuf, pbuf);
+
+	err = getnameinfo(ap2->ai_addr, ap2->ai_addrlen, hbuf, sizeof (hbuf),
+			  pbuf, sizeof(pbuf), NI_NAMEREQD);
+	if (err)
+	    printf("\tgetnameinfo(NI_NAMEREQD): %s\n", eaistr(err));
+	else
+	    printf("\tgetnameinfo => %s, %s\n", hbuf, pbuf);
+    }
+    freeaddrinfo(ap);
+    return 0;
+}
diff --git a/krb5-1-6/src/tests/resolve/fake-addrinfo-test.c b/krb5-1-6/src/tests/resolve/fake-addrinfo-test.c
new file mode 100644
index 000000000..f04024d73
--- /dev/null
+++ b/krb5-1-6/src/tests/resolve/fake-addrinfo-test.c
@@ -0,0 +1,2 @@
+#define USE_FAKE_ADDRINFO
+#include "addrinfo-test.c"
diff --git a/krb5-1-6/src/tests/resolve/resolve.c b/krb5-1-6/src/tests/resolve/resolve.c
new file mode 100644
index 000000000..b1fe969d3
--- /dev/null
+++ b/krb5-1-6/src/tests/resolve/resolve.c
@@ -0,0 +1,170 @@
+/*
+ * test/resolve/resolve.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * A simple program to test the functionality of the resolver library.
+ * It simply will try to get the IP address of the host, and then look 
+ * up the name from the address. If the resulting name does not contain the
+ * domain name, then the resolve library is broken.
+ *
+ * Warning: It is possible to fool this program into thinking everything is 
+ * alright byt a clever use of /etc/hosts - but this is better than nothing.
+ *
+ * Usage:
+ *   resolve [hostname]
+ *
+ *   When invoked with no arguments, gethostname is used for the local host.
+ *
+ */
+
+/* This program tests the resolve library and sees if it is broken... */
+
+#include <stdio.h>
+
+#if STDC_HEADERS
+#include <string.h>
+#else
+#ifndef HAVE_STRCHR
+#define strchr index
+#endif
+char *strchr();
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <netdb.h>
+
+int
+main(argc, argv)
+     int argc;
+     char **argv;
+{
+	char myname[MAXHOSTNAMELEN+1];
+	char *ptr;
+	char addrcopy[4];
+	struct hostent *host;
+	int quiet = 0;
+
+	argc--; argv++;
+	while (argc) {
+	    if ((strcmp(*argv, "--quiet") == 0) ||
+		(strcmp(*argv, "-q") == 0)) {
+		quiet++;
+	    } else 
+		break;
+	    argc--; argv++;
+	}
+
+	if (argc >= 1) {
+		strncpy(myname, *argv, MAXHOSTNAMELEN);
+	} else {
+		if(gethostname(myname, MAXHOSTNAMELEN)) {
+			perror("gethostname failure");
+			exit(1);
+		}
+	}
+	
+	myname[MAXHOSTNAMELEN] = '\0';	/* for safety */
+	
+	/* Look up the address... */
+	if (!quiet)
+	    printf("Hostname:  %s\n", myname);
+	
+
+	/* Set the hosts db to close each time - effectively rewinding file */
+	sethostent(0);
+
+	if((host = gethostbyname (myname)) == NULL) {
+		fprintf(stderr,
+			"Could not look up address for hostname '%s' - fatal\n",
+			myname);
+		exit(2);
+	}
+	
+	ptr = host->h_addr_list[0];
+#define UC(a) (((int)a)&0xff)
+	if (!quiet)
+	    printf("Host address: %d.%d.%d.%d\n", 
+		   UC(ptr[0]), UC(ptr[1]), UC(ptr[2]), UC(ptr[3]));
+
+	memcpy(addrcopy, ptr, 4);
+
+	/* Convert back to full name */
+	if((host = gethostbyaddr(addrcopy, 4, AF_INET)) == NULL) {
+		fprintf(stderr, "Error looking up IP address - fatal\n");
+		exit(2);
+	}
+	
+	if (quiet)
+	    printf("%s\n", host->h_name);
+	else
+	    printf("FQDN: %s\n", host->h_name);
+	
+	/*
+	 * The host name must have at least one '.' in the name, and
+	 * if there is only one '.', it must not be at the end of the
+	 * string.  (i.e., "foo." is not a FQDN)
+	 */
+	ptr = strchr(host->h_name, '.');
+	if (ptr == NULL || ptr[1] == '\0') {
+		fprintf(stderr,
+			"\nResolve library did not return a "
+			"fully qualified domain name.\n\n"
+			"If you are using /etc/hosts before DNS, "
+			"e.g. \"files\" is listed first\n"
+			"for \"hosts:\" in nsswitch.conf, ensure that "
+			"you have listed the FQDN\n"
+			"as the first name for the local host.\n\n"
+			"If this does not correct the problem, "
+			"you may have to reconfigure the kerberos\n"
+			"distribution to select a "
+			"different set of libraries using \n"
+			"--with-netlib[=libs]\n");
+		exit(3);
+	}
+
+	if (!quiet)
+	    printf("Resolve library appears to have passed the test\n");
+
+	/* All ok */
+	exit(0);
+
+}
+
+
diff --git a/krb5-1-6/src/tests/shlib/Makefile.in b/krb5-1-6/src/tests/shlib/Makefile.in
new file mode 100644
index 000000000..523dd125a
--- /dev/null
+++ b/krb5-1-6/src/tests/shlib/Makefile.in
@@ -0,0 +1,37 @@
+thisconfigdir=./..
+myfulldir=tests/shlib
+mydir=shlib
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@
+
+#VALGRIND=valgrind
+#VALGRINDFLAGS=--tool=memcheck --leak-check=yes --show-reachable=yes
+
+SRCS=$(srcdir)/t_loader.c
+
+all::
+
+run-t_loader: t_loader
+	$(RUN_SETUP) $(VALGRIND) ./t_loader
+
+t_loader: t_loader.o
+	$(CC_LINK) -o t_loader t_loader.o $(DL_LIB)
+
+check-unix::
+
+install::
+
+clean::
+	$(RM) t_loader.o t_loader
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)t_loader.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h t_loader.c
diff --git a/krb5-1-6/src/tests/shlib/t_loader.c b/krb5-1-6/src/tests/shlib/t_loader.c
new file mode 100644
index 000000000..70cd6d13b
--- /dev/null
+++ b/krb5-1-6/src/tests/shlib/t_loader.c
@@ -0,0 +1,372 @@
+/* foo */
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "autoconf.h"
+#include "krb5.h"
+#include "gssapi/gssapi.h"
+#define HAVE_DLOPEN 1
+
+static int verbose = 1;
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+/* Solaris man page recommends link.h too */
+
+/* lazy = 1 means resolve symbols later, 0 means now; any
+   other flags we should be testing?  On Windows, maybe?
+
+   Return value is the library handle.  On error, print a message and
+   exit.  */
+#define do_open(LIB,REV,FLAGS) do_open_1(LIB,REV,FLAGS,__LINE__)
+static void *do_open_1(const char *libname, const char *rev, int lazy, int line);
+
+/* Look up a function symbol in the library and return a pointer.
+
+   The return value may need casting to the correct type.  On error,
+   print a message and exit.  */
+static void *get_sym_1(void *libhandle, const char *sym, int line);
+#define get_sym(LIB, NAME) get_sym_1(LIB, NAME, __LINE__)
+#define GET_FSYM(TYPE, LIB, NAME) ((TYPE) get_sym(LIB, NAME))
+#define get_gfun(LIB, NAME) ((OM_uint32 KRB5_CALLCONV(*)()) get_sym(LIB, NAME))
+
+/* Close dynamically-opened library.
+
+   If the OS reports an error in doing so, print a message and
+   exit.  */
+#define do_close(X) do_close_1(X, __LINE__)
+static void do_close_1(void *libhandle, int line);
+
+#ifdef HAVE_DLOPEN
+
+#ifdef _AIX
+# define SHLIB_SUFFIX ".a"
+#else
+# define SHLIB_SUFFIX ".so"
+#endif
+
+#define HORIZ 25
+
+static void *do_open_1(const char *libname, const char *rev,
+		       int lazy, int line)
+{
+    void *p;
+    char *namebuf;
+    size_t sz;
+
+    if (verbose)
+	printf("from line %d: do_open(%s)...%*s", line, libname,
+	       HORIZ-strlen(libname), "");
+    sz = strlen(SHLIB_SUFFIX) + strlen(libname) + 4;
+#ifdef _AIX
+    sz += strlen(rev) + 8;
+#endif
+    namebuf = malloc(sz);
+    if (namebuf == 0) {
+	perror("malloc");
+	exit(1);
+    }
+    strcpy(namebuf, "lib");
+    strcat(namebuf, libname);
+    strcat(namebuf, SHLIB_SUFFIX);
+#ifdef _AIX
+    strcat(namebuf, "(shr.o.");
+    strcat(namebuf, rev);
+    strcat(namebuf, ")");
+#endif
+
+#ifndef RTLD_MEMBER
+#define RTLD_MEMBER 0
+#endif
+    p = dlopen(namebuf, (lazy ? RTLD_LAZY : RTLD_NOW) | RTLD_MEMBER);
+    if (p == 0) {
+	fprintf(stderr, "dlopen of %s failed: %s\n", namebuf, dlerror());
+	exit(1);
+    }
+    free(namebuf);
+    if (verbose)
+	printf("done: %p\n", p);
+    return p;
+}
+
+#define SYM_PREFIX ""
+static void *get_sym_1(void *libhandle, const char *symname, int line)
+{
+    void *s;
+
+    /* Bah.  Fix this later, if we care.  */
+    assert(strlen(SYM_PREFIX) == 0);
+
+    if (verbose)
+	printf("from line %d: get_sym(%s)...%*s", line, symname,
+	       HORIZ-strlen(symname), "");
+
+    s = dlsym(libhandle, symname);
+    if (s == 0) {
+	fprintf(stderr, "symbol %s not found\n", symname);
+	exit(1);
+    }
+    if (verbose)
+	printf("done: %p\n", s);
+    return s;
+}
+
+static void do_close_1(void *libhandle, int line)
+{
+    if (verbose) {
+	char pbuf[3*sizeof(libhandle)+4];
+	sprintf(pbuf, "%p", libhandle);
+	printf("from line %d: do_close(%s)...%*s", line, pbuf,
+	       HORIZ-1-strlen(pbuf), "");
+    }
+    if (dlclose(libhandle) != 0) {
+	fprintf(stderr, "dlclose failed: %s\n", dlerror());
+	exit(1);
+    }
+    if (verbose)
+	printf("done\n");
+}
+
+#elif defined _WIN32
+
+static void *do_open(const char *libname, int lazy)
+{
+    /* To be written?  */
+    abort();
+}
+
+static void *get_sym(void *libhandle, const char *symname)
+{
+    abort();
+}
+
+static void do_close(void *libhandle)
+{
+    abort();
+}
+
+#else
+
+static void *do_open(const char *libname, int lazy)
+{
+    printf("don't know how to do dynamic loading here, punting\n");
+    exit(0);
+}
+
+static void *get_sym(void *libhandle, const char *symname)
+{
+    abort();
+}
+
+static void do_close(void *libhandle)
+{
+    abort();
+}
+
+#endif
+
+int main()
+{
+    void *celib, *k5lib, *gsslib, *celib2;
+
+    (void) setvbuf(stdout, 0, _IONBF, 0);
+
+#if 0
+    /* Simplest test: Load, then unload out of order.  */
+    celib = do_open("com_err", "3.0", 0);
+    k5lib = do_open("krb5", "3.2", 0);
+    gsslib = do_open("gssapi_krb5", "2.2", 0);
+    celib2 = do_open("com_err", "3.0", 0);
+    do_close(celib);
+    do_close(k5lib);
+    do_close(celib2);
+    do_close(gsslib);
+#endif
+
+    celib = do_open("com_err", "3.0", 0);
+    k5lib = do_open("krb5", "3.2", 0);
+    gsslib = do_open("gssapi_krb5", "2.2", 0);
+    celib2 = do_open("com_err", "3.0", 0);
+    do_close(celib2);
+    {
+	typedef krb5_error_code KRB5_CALLCONV (*ict)(krb5_context *);
+	typedef void KRB5_CALLCONV (*fct)(krb5_context);
+
+	ict init_context = (ict) get_sym(k5lib, "krb5_init_context");
+	fct free_context = (fct) get_sym(k5lib, "krb5_free_context");
+	krb5_context ctx;
+	krb5_error_code err;
+
+#define CALLING(S) (verbose ? printf("at   line %d: calling %s...%*s", __LINE__, #S, (int)(HORIZ+1-strlen(#S)), "") : 0)
+#define DONE() (verbose ? printf("done\n") : 0)
+
+	CALLING(krb5_init_context);
+	err = init_context(&ctx);
+	DONE();
+	if (err) {
+	    fprintf(stderr, "error 0x%lx initializing context\n",
+		    (unsigned long) err);
+	    exit(1);
+	}
+	CALLING(krb5_free_context);
+	free_context(ctx);
+	DONE();
+    }
+    celib2 = do_open("com_err", "3.0", 0);
+    do_close(celib);
+    do_close(k5lib);
+    do_close(celib2);
+    do_close(gsslib);
+
+    /* Test gssapi_krb5 without having loaded anything else.  */
+    gsslib = do_open("gssapi_krb5", "2.2", 1);
+    {
+	OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t,
+						    gss_ctx_id_t *, gss_name_t,
+						    gss_OID,
+						    OM_uint32, OM_uint32,
+						    gss_channel_bindings_t,
+						    gss_buffer_t, gss_OID *,
+						    gss_buffer_t,
+						    OM_uint32 *, OM_uint32 *)
+	    = get_gfun(gsslib, "gss_init_sec_context");
+	OM_uint32 KRB5_CALLCONV (*import_name)(OM_uint32 *, gss_buffer_t,
+					       gss_OID, gss_name_t *)
+	    = get_gfun(gsslib, "gss_import_name");
+	OM_uint32 KRB5_CALLCONV (*release_buffer)(OM_uint32 *, gss_buffer_t)
+	    = get_gfun(gsslib, "gss_release_buffer");
+	OM_uint32 KRB5_CALLCONV (*release_name)(OM_uint32 *, gss_name_t *)
+	    = get_gfun(gsslib, "gss_release_name");
+	OM_uint32 KRB5_CALLCONV (*delete_sec_context)(OM_uint32 *,
+						      gss_ctx_id_t *,
+						      gss_buffer_t)
+	    = get_gfun(gsslib, "gss_delete_sec_context");
+
+	OM_uint32 gmaj, gmin;
+	OM_uint32 retflags;
+	gss_ctx_id_t gctx = GSS_C_NO_CONTEXT;
+	gss_buffer_desc token;
+	gss_name_t target;
+	static gss_buffer_desc target_name_buf = {
+	    9, "x@mit.edu"
+	};
+	static gss_OID_desc service_name = {
+	    10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"
+	};
+
+	CALLING(gss_import_name);
+	gmaj = import_name(&gmin, &target_name_buf, &service_name, &target);
+	DONE();
+	if (gmaj != GSS_S_COMPLETE) {
+	    fprintf(stderr,
+		    "import_name reports error major 0x%lx minor 0x%lx(%ld)\n",
+		    (unsigned long) gmaj, (unsigned long) gmin,
+		    (signed long) gmin);
+	    exit(1);
+	}
+	/* This will probably get different errors, depending on
+	   whether we have tickets at the time.  Doesn't matter much,
+	   we're ignoring the error and testing whether we're doing
+	   cleanup properly.  (Though the internal cleanup needed in
+	   the two cases might be different.)  */
+	CALLING(gss_init_sec_context);
+	gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target,
+				GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER,
+				NULL, &token, &retflags, NULL);
+	DONE();
+	/* Ignore success/failure indication.  */
+	if (token.length) {
+	    CALLING(gss_release_buffer);
+	    release_buffer(&gmin, &token);
+	    DONE();
+	}
+	CALLING(gss_release_name);
+	release_name(&gmin, &target);
+	DONE();
+	if (gctx != GSS_C_NO_CONTEXT) {
+	    CALLING(gss_delete_sec_context);
+	    delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER);
+	    DONE();
+	}
+    }
+    do_close(gsslib);
+
+    /* Test gssapi_krb5 with com_err already loaded, then unload
+       com_err first.  */
+    celib = do_open("com_err", "3.0", 1);
+    gsslib = do_open("gssapi_krb5", "2.2", 1);
+    {
+	OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t,
+						    gss_ctx_id_t *, gss_name_t,
+						    gss_OID,
+						    OM_uint32, OM_uint32,
+						    gss_channel_bindings_t,
+						    gss_buffer_t, gss_OID *,
+						    gss_buffer_t,
+						    OM_uint32 *, OM_uint32 *)
+	    = get_gfun(gsslib, "gss_init_sec_context");
+	OM_uint32 KRB5_CALLCONV (*import_name)(OM_uint32 *, gss_buffer_t,
+					       gss_OID, gss_name_t *)
+	    = get_gfun(gsslib, "gss_import_name");
+	OM_uint32 KRB5_CALLCONV (*release_buffer)(OM_uint32 *, gss_buffer_t)
+	    = get_gfun(gsslib, "gss_release_buffer");
+	OM_uint32 KRB5_CALLCONV (*release_name)(OM_uint32 *, gss_name_t *)
+	    = get_gfun(gsslib, "gss_release_name");
+	OM_uint32 KRB5_CALLCONV (*delete_sec_context)(OM_uint32 *,
+						      gss_ctx_id_t *,
+						      gss_buffer_t)
+	    = get_gfun(gsslib, "gss_delete_sec_context");
+
+	OM_uint32 gmaj, gmin;
+	OM_uint32 retflags;
+	gss_ctx_id_t gctx = GSS_C_NO_CONTEXT;
+	gss_buffer_desc token;
+	gss_name_t target;
+	static gss_buffer_desc target_name_buf = {
+	    9, "x@mit.edu"
+	};
+	static gss_OID_desc service_name = {
+	    10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"
+	};
+
+	CALLING(gss_import_name);
+	gmaj = import_name(&gmin, &target_name_buf, &service_name, &target);
+	DONE();
+	if (gmaj != GSS_S_COMPLETE) {
+	    fprintf(stderr,
+		    "import_name reports error major 0x%lx minor 0x%lx(%ld)\n",
+		    (unsigned long) gmaj, (unsigned long) gmin,
+		    (signed long) gmin);
+	    exit(1);
+	}
+	/* This will probably get different errors, depending on
+	   whether we have tickets at the time.  Doesn't matter much,
+	   we're ignoring the error and testing whether we're doing
+	   cleanup properly.  (Though the internal cleanup needed in
+	   the two cases might be different.)  */
+	CALLING(gss_init_sec_context);
+	gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target,
+				GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER,
+				NULL, &token, &retflags, NULL);
+	DONE();
+	/* Ignore success/failure indication.  */
+	if (token.length) {
+	    CALLING(gss_release_buffer);
+	    release_buffer(&gmin, &token);
+	    DONE();
+	}
+	CALLING(gss_release_name);
+	release_name(&gmin, &target);
+	DONE();
+	if (gctx != GSS_C_NO_CONTEXT) {
+	    CALLING(gss_delete_sec_context);
+	    delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER);
+	    DONE();
+	}
+    }
+    do_close(celib);
+    do_close(gsslib);
+
+    return 0;
+}
diff --git a/krb5-1-6/src/tests/test1.c b/krb5-1-6/src/tests/test1.c
new file mode 100644
index 000000000..bb142ead4
--- /dev/null
+++ b/krb5-1-6/src/tests/test1.c
@@ -0,0 +1,195 @@
+/*
+ * tests/test1.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Regression tests for the kerberos library.
+ */
+
+#include "krb5.h"
+
+unsigned char key_one[8] = { 0x10, 0x23, 0x32, 0x45, 0x54, 0x67, 0x76, 0x89 };
+unsigned char key_two[8] = { 0xea, 0x89, 0x57, 0x76, 0x5b, 0xcd, 0x0d, 0x34 };
+
+extern void dump_data();
+
+tkt_test_1()
+{
+    krb5_data *data;
+    krb5_ticket tk_in, *tk_out;
+    krb5_keyblock sess_k, serv_k, *nsess;
+    krb5_enc_tkt_part tk_in_enc;
+    int code;
+    krb5_address *addr_list[2];
+    krb5_address addr_1;
+    static krb5_octet ip_addr_1[4] = { 18, 72, 0, 122 };
+    char *out;
+    
+    /*
+     * fill in some values on the "in" side of the ticket
+     */
+    code = krb5_parse_name ("server/test/1@BOGUS.ORG", &tk_in.server);
+    if (code != 0) {
+	com_err("tkt_test_1", code, " parsing server principal");
+	return;
+    }
+
+    serv_k.enctype = 1;		/* XXX symbolic constant */
+    serv_k.length = 8;		/* XXX symbolic constant */
+    serv_k.contents = key_one;
+    
+    sess_k.enctype = 1;		/* XXX symbolic constant */
+    sess_k.length = 8;		/* XXX symbolic constant */
+    sess_k.contents = key_two;
+
+    tk_in.etype = 1;		/* XXX symbolic constant here */
+    tk_in.skvno = 4;		
+
+    tk_in.enc_part2 = &tk_in_enc;
+
+    tk_in_enc.flags = 0x11;
+    tk_in_enc.session = &sess_k;
+
+    tk_in_enc.times.authtime = 42;
+    tk_in_enc.times.starttime = 43;
+    tk_in_enc.times.endtime = 44;
+    
+    code = krb5_parse_name ("client/test/1@BOGUS.ORG", &tk_in_enc.client);
+    if (code != 0) {
+	com_err("tkt_test_1", code, " parsing client principal");
+	return;
+    }
+    tk_in_enc.transited.length = 0;
+
+    addr_1.addrtype = ADDRTYPE_INET; /* XXX should be KRB5_ADDR... */
+    addr_1.length = 4;
+    addr_1.contents = ip_addr_1;
+
+    addr_list[0] = &addr_1;
+    addr_list[1] = 0;
+
+    
+    tk_in_enc.caddrs = addr_list;
+    tk_in_enc.authorization_data = 0;
+
+    code = krb5_encrypt_tkt_part(&serv_k, &tk_in);
+    if (code != 0) {
+	com_err ("tkt_test_1", code, " encrypting ticket");
+	return;
+    }
+
+    data = 0;    
+    
+    code = krb5_encode_ticket (&tk_in,  &data);
+    if (code != 0) {
+	com_err ("tkt_test_1", code, " encoding ticket");
+	return;
+    }
+
+    dump_data(data);
+
+    tk_out = 0;
+    code = krb5_decode_ticket (data, &tk_out);
+    if (code != 0) {
+	com_err ("tkt_test_1", code, "decoding ticket");
+	return;
+    }
+    /* check the plaintext values */
+    if (tk_out->etype != 1) {
+	com_err ("tkt_test_1", 0, "wrong etype");
+	return;
+    }
+    if (tk_out->skvno != 4) {
+	com_err ("tkt_test_1", 0, "wrong kvno");
+	return;
+    }
+
+    code = krb5_unparse_name(tk_out->server, &out);
+    if (code != 0) {
+	com_err ("tkt_test_1", code, "couldn't unparse server principal");
+	return;
+    }
+    if (strcmp (out, "server/test/1@BOGUS.ORG") != 0) {
+	com_err("tkt_test_1", 0, "wrong server principal");
+	return;
+    }
+    free(out);
+    out = 0;
+    
+    /* decode the ciphertext */
+    code = krb5_decrypt_tkt_part (&serv_k, tk_out);
+    if (code != 0) {
+	com_err ("tkt_test_1", code, "while decrypting ticket");
+	return;
+    }
+
+    /* check the contents */
+    if (tk_out->enc_part2->flags != 0x11) {
+	com_err("tkt_test_1", 0, "wrong flags");
+	return;
+    }
+
+    nsess = tk_out->enc_part2->session;
+
+    if (nsess->enctype != 1) {
+	com_err("tkt_test_1", 0, "wrong session key type");
+	return;
+    }
+    if (nsess->length != 8) {
+	com_err("tkt_test_1", 0, "wrong session key length");
+	return;
+    }
+    if (memcmp(nsess->contents, key_two, 8) != 0) {
+	com_err("tkt_test_1", 0, "wrong session key contents");
+	return;
+    }
+
+    code = krb5_unparse_name(tk_out->enc_part2->client, &out);
+    if (code != 0) {
+	com_err ("tkt_test_1", code, "couldn't unparse client principal");
+	return;
+    }
+    if (strcmp (out, "client/test/1@BOGUS.ORG") != 0) {
+	com_err("tkt_test_1", 0, "wrong client principal");
+	return;
+    }
+    free(out);
+    out = 0;
+    if (tk_out->enc_part2->transited.length != 0) {
+	com_err("tkt_test_1", 0, "wrong transited length");
+	return;
+    }
+    /* XXX should check address here, too */
+    /* XXX should check times here */
+    /* XXX should check auth. data here */
+    printf("test 1 passed\n");
+}
+
+
+
+main()
+{
+    krb5_init_ets();
+    tkt_test_1();
+}
diff --git a/krb5-1-6/src/tests/threads/Makefile.in b/krb5-1-6/src/tests/threads/Makefile.in
new file mode 100644
index 000000000..b6da0b087
--- /dev/null
+++ b/krb5-1-6/src/tests/threads/Makefile.in
@@ -0,0 +1,44 @@
+thisconfigdir=./..
+myfulldir=tests/threads
+mydir=threads
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+RUN_SETUP = @KRB5_RUN_ENV@
+
+SRCS=$(srcdir)/t_rcache.c
+
+all::
+
+N = 4
+run-t_rcache: t_rcache
+	$(RUN_SETUP) $(VALGRIND) ./t_rcache -n $(N)
+
+t_rcache: t_rcache.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_rcache t_rcache.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS)
+
+syms: syms.o
+	$(CC_LINK) -o syms syms.o
+
+run-syms: syms
+	$(RUN_SETUP) $(VALGRIND) ./syms
+
+prof1: prof1.o $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o prof1 prof1.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS)
+
+prof1.o: prof1.c
+
+check-unix:: run-t_rcache
+
+install::
+
+clean::
+	$(RM) t_rcache.o t_rcache
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+
diff --git a/krb5-1-6/src/tests/threads/prof1.c b/krb5-1-6/src/tests/threads/prof1.c
new file mode 100644
index 000000000..766bfa3d0
--- /dev/null
+++ b/krb5-1-6/src/tests/threads/prof1.c
@@ -0,0 +1,79 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <time.h>
+#include <sys/time.h>
+#include <utime.h>
+#include <com_err.h>
+#include <profile.h>
+
+int nthreads = 10;
+unsigned int delay = 3600;
+
+volatile int done = 0; /* XXX hack */
+
+const char *path = "/tmp/foo1.conf:/tmp/foo.conf";
+const char *filename = "/tmp/foo.conf";
+
+const char *prog;
+
+static void *worker(void *arg)
+{
+    profile_t p;
+    long err;
+    int i;
+    const char *const names[] = {
+	"one", "two", "three", 0
+    };
+    char **values;
+    const char *mypath = (random() & 1) ? path : filename;
+
+    while (!done) {
+	err = profile_init_path(mypath, &p);
+	if (err) {
+	    com_err(prog, err, "calling profile_init(\"%s\")", mypath);
+	    exit(1);
+	}
+	for (i = 0; i < 10; i++) {
+	    values = 0;
+	    err = profile_get_values(p, names, &values);
+	    if (err == 0 && values != 0)
+		profile_free_list(values);
+	}
+	profile_release(p);
+    }
+    return 0;
+}
+
+static void *modifier(void *arg)
+{
+    struct timespec req;
+    while (!done) {
+	req.tv_sec = 0;
+	req.tv_nsec = random() & 499999999;
+	nanosleep(&req, 0);
+	utime(filename, 0);
+/*	printf("."), fflush(stdout); */
+    }
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    int i;
+    pthread_t thr;
+
+    prog = argv[0];
+    for (i = 0; i < nthreads; i++) {
+	assert(0 == pthread_create(&thr, 0, worker, 0));
+    }
+    sleep(1);
+    pthread_create(&thr, 0, modifier, 0);
+    sleep(delay);
+    done = 1;
+    sleep(2);
+    return 0;
+}
diff --git a/krb5-1-6/src/tests/threads/t_rcache.c b/krb5-1-6/src/tests/threads/t_rcache.c
new file mode 100644
index 000000000..49b6927b4
--- /dev/null
+++ b/krb5-1-6/src/tests/threads/t_rcache.c
@@ -0,0 +1,174 @@
+/*
+ * test/threads/t_rcache.c
+ *
+ * Copyright (C) 2006 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * 
+ *
+ */
+
+
+#include <stdio.h>
+#include <com_err.h>
+
+#include "k5-int.h"
+#include <krb5.h>
+#include <pthread.h>
+
+krb5_context ctx;
+krb5_rcache rcache;
+krb5_data piece = { .data = "hello", .length = 5 };
+time_t end_time;
+const char *prog;
+
+struct tinfo {
+    time_t now;
+    unsigned long my_ctime;
+    unsigned int my_cusec;
+    unsigned int total;
+    int idx;
+};
+
+#undef INIT_ONCE
+
+static void try_one (struct tinfo *t)
+{
+    krb5_donot_replay r;
+    krb5_error_code err;
+    char buf[100], buf2[100];
+    krb5_rcache my_rcache;
+
+    sprintf(buf, "host/all-in-one.mit.edu/%p@ATHENA.MIT.EDU", buf);
+    r.server = buf;
+    r.client = (t->my_cusec & 7) + "abcdefgh@ATHENA.MIT.EDU";
+    if (t->now != t->my_ctime) {
+	if (t->my_ctime != 0) {
+	    sprintf(buf2, "%3d: %ld %5d\n", t->idx, t->my_ctime, t->my_cusec);
+	    printf("%s", buf2);
+	}
+	t->my_ctime = t->now;
+	t->my_cusec = 1;
+    } else
+	t->my_cusec++;
+    r.ctime = t->my_ctime;
+    r.cusec = t->my_cusec;
+#ifndef INIT_ONCE
+    err = krb5_get_server_rcache(ctx, &piece, &my_rcache);
+    if (err) {
+	com_err(prog, err, "getting replay cache");
+	exit(1);
+    }
+#else
+    my_rcache = rcache;
+#endif
+    err = krb5_rc_store(ctx, my_rcache, &r);
+    if (err) {
+	com_err(prog, err, "storing in replay cache");
+	exit(1);
+    }
+#ifndef INIT_ONCE
+    krb5_rc_close(ctx, my_rcache);
+#endif
+}
+
+static void *run_a_loop (void *x)
+{
+    struct tinfo t = { 0 };
+/*    int chr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"[(*(int*)x) % 27]; */
+
+    t.now = time(0);
+    t.idx = *(int *)x;
+    while (t.now != time(0))
+	;
+    t.now = time(0);
+    while (t.now < end_time) {
+	t.now = time(0);
+	try_one(&t);
+	t.total++;
+/*	printf("%c", chr); */
+	fflush(stdout);
+    }
+    printf("thread %p total %u\n", &t, t.total);
+    *(int*)x = t.total;
+    return 0;
+}
+
+int main (int argc, char *argv[])
+{
+    int n;
+    krb5_error_code err;
+    int interval = 20 /* 5 * 60 */;
+
+    prog = argv[0];
+    unlink("/var/tmp/rc_hello_7882");
+    unlink("/var/tmp/hello_7882");
+    n = 2;
+    err = krb5_init_context(&ctx);
+    if (err) {
+	com_err(prog, err, "initializing context");
+	return 1;
+    }
+#ifdef INIT_ONCE
+    err = krb5_get_server_rcache(ctx, &piece, &rcache);
+    if (err) {
+	com_err(prog, err, "getting replay cache");
+	return 1;
+    }
+#endif
+    end_time = time(0) + interval;
+#undef DIRECT
+#ifdef DIRECT
+    {
+	int zero = 0;
+	run_a_loop(&zero);
+    }
+#else
+    {
+	int i, *ip;
+
+	ip = malloc(sizeof(int) * n);
+	if (ip == 0 && n > 0) {
+	    perror("malloc");
+	    exit(1);
+	}
+	for (i = 0; i < n; i++)
+	    ip[i] = i;
+
+	for (i = 0; i < n; i++) {
+	    pthread_t new_thread;
+	    int perr;
+	    perr = pthread_create(&new_thread, 0, run_a_loop, &ip[i]);
+	    if (perr) {
+		errno = perr;
+		perror("pthread_create");
+		exit(1);
+	    }
+	}
+	while (time(0) < end_time + 1)
+	    sleep(1);
+	for (i = 0; i < n; i++)
+	    printf("thread %d total %5d\n", i, ip[i]);
+    }
+#endif
+    return 0;
+}
diff --git a/krb5-1-6/src/tests/verify/Makefile.in b/krb5-1-6/src/tests/verify/Makefile.in
new file mode 100644
index 000000000..5323b9a81
--- /dev/null
+++ b/krb5-1-6/src/tests/verify/Makefile.in
@@ -0,0 +1,34 @@
+thisconfigdir=./..
+myfulldir=tests/verify
+mydir=verify
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+KDB5_DEP_LIB=$(THREAD_LINKOPTS) $(DL_LIB)
+
+SRCS=$(srcdir)/kdb5_verify.c
+
+all:: kdb5_verify
+
+kdb5_verify: kdb5_verify.o $(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o kdb5_verify kdb5_verify.o $(KDB5_LIBS) $(KDB5_DEP_LIB) $(KRB5_BASE_LIBS)
+
+install::
+
+clean::
+	$(RM) kdb5_verify.o kdb5_verify
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+$(OUTPRE)kdb5_verify.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+  $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+  $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h $(SS_DEPS) kdb5_verify.c
diff --git a/krb5-1-6/src/tests/verify/kdb5_verify.c b/krb5-1-6/src/tests/verify/kdb5_verify.c
new file mode 100644
index 000000000..2dd19ba44
--- /dev/null
+++ b/krb5-1-6/src/tests/verify/kdb5_verify.c
@@ -0,0 +1,471 @@
+/*
+ * tests/verify/kdb5_verify.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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Edit a KDC database.
+ */
+
+#include "k5-int.h"
+#include "kdb.h"
+#include "com_err.h"
+#include <ss/ss.h>
+#include <stdio.h>
+
+#define REALM_SEP	'@'
+#define REALM_SEP_STR	"@"
+
+struct mblock {
+    krb5_deltat max_life;
+    krb5_deltat max_rlife;
+    krb5_timestamp expiration;
+    krb5_flags flags;
+    krb5_kvno mkvno;
+} mblock = {				/* XXX */
+    KRB5_KDB_MAX_LIFE,
+    KRB5_KDB_MAX_RLIFE,
+    KRB5_KDB_EXPIRATION,
+    KRB5_KDB_DEF_FLAGS,
+    0
+};
+
+int set_dbname_help (krb5_context, char *, char *);
+
+static void
+usage(who, status)
+char *who;
+int status;
+{
+    fprintf(stderr,
+	    "usage: %s -p prefix -n num_to_check [-d dbpathname] [-r realmname]\n",
+	    who);
+    fprintf(stderr, "\t [-D depth] [-k enctype] [-M mkeyname]\n");
+
+    exit(status);
+}
+
+krb5_keyblock master_keyblock;
+krb5_principal master_princ;
+krb5_db_entry master_entry;
+krb5_encrypt_block master_encblock;
+krb5_pointer master_random;
+char *str_master_princ;
+
+static char *progname;
+static char *cur_realm = 0;
+static char *mkey_name = 0;
+static char *mkey_password = 0;
+static krb5_boolean manual_mkey = FALSE;
+
+
+int check_princ (krb5_context, char *);
+
+int
+main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    extern char *optarg;	
+    int optchar, i, n;
+    char tmp[4096], tmp2[BUFSIZ], *str_princ;
+
+    krb5_context context;
+    krb5_error_code retval;
+    char *dbname = 0;
+    int enctypedone = 0;
+    int num_to_check;
+    char principal_string[BUFSIZ];
+    char *suffix = 0;
+    int depth, errors;
+
+    krb5_init_context(&context);
+
+    if (strrchr(argv[0], '/'))
+	argv[0] = strrchr(argv[0], '/')+1;
+
+    progname = argv[0];
+
+    memset(principal_string, 0, sizeof(principal_string));
+    num_to_check = 0;
+    depth = 1;
+
+    while ((optchar = getopt(argc, argv, "D:P:p:n:d:r:R:k:M:e:m")) != -1) {
+	switch(optchar) {
+	case 'D':
+	    depth = atoi(optarg);       /* how deep to go */
+	    break;
+        case 'P':		/* Only used for testing!!! */
+	    mkey_password = optarg;
+	    break;
+	case 'p':                       /* prefix name to check */
+	    strncpy(principal_string, optarg, sizeof(principal_string) - 1);
+	    principal_string[sizeof(principal_string) - 1] = '\0';
+	    suffix = principal_string + strlen(principal_string);
+	    break;
+       case 'n':                        /* how many to check */
+	    num_to_check = atoi(optarg);
+	    break;
+	case 'd':			/* set db name */
+	    dbname = optarg;
+	    break;
+	case 'r':
+	    cur_realm = optarg;
+	    break;
+	case 'k':
+	    master_keyblock.enctype = atoi(optarg);
+	    enctypedone++;
+	    break;
+	case 'M':			/* master key name in DB */
+	    mkey_name = optarg;
+	    break;
+	case 'm':
+	    manual_mkey = TRUE;
+	    break;
+	case '?':
+	default:
+	    usage(progname, 1);
+	    /*NOTREACHED*/
+	}
+    }
+
+    if (!(num_to_check && suffix)) usage(progname, 1);
+
+    if (!enctypedone)
+	master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
+
+    if (!krb5_c_valid_enctype(master_keyblock.enctype)) {
+	com_err(progname, KRB5_PROG_ETYPE_NOSUPP,
+		"while setting up enctype %d", master_keyblock.enctype);
+	exit(1);
+    }
+
+    krb5_use_enctype(context, &master_encblock, master_keyblock.enctype);
+
+    if (!dbname)
+	dbname = DEFAULT_KDB_FILE;	/* XXX? */
+
+    if (!cur_realm) {
+	if ((retval = krb5_get_default_realm(context, &cur_realm))) {
+	    com_err(progname, retval, "while retrieving default realm name");
+	    exit(1);
+	}	    
+    }
+    if ((retval = set_dbname_help(context, progname, dbname)))
+	exit(retval);
+
+    errors = 0;
+
+    fprintf(stdout, "\nChecking ");
+
+    for (n = 1; n <= num_to_check; n++) {
+      /* build the new principal name */
+      /* we can't pick random names because we need to generate all the names 
+	 again given a prefix and count to test the db lib and kdb */
+      (void) sprintf(suffix, "%d", n);
+      (void) sprintf(tmp, "%s-DEPTH-1", principal_string);
+      str_princ = tmp;
+      if (check_princ(context, str_princ)) errors++;
+
+      for (i = 2; i <= depth; i++) {
+	(void) sprintf(tmp2, "/%s-DEPTH-%d", principal_string, i);
+	tmp2[sizeof(tmp2) - 1] = '\0';
+	strncat(tmp, tmp2, sizeof(tmp) - 1 - strlen(tmp));
+	str_princ = tmp;
+	if (check_princ(context, str_princ)) errors++;
+      }
+    }
+
+    if (errors)
+      fprintf(stdout, "\n%d errors/principals failed.\n", errors);
+    else
+      fprintf(stdout, "\nNo errors.\n");
+
+    krb5_finish_random_key(context, &master_encblock, &master_random);
+    krb5_finish_key(context, &master_encblock);
+
+    retval = krb5_db_fini(context);
+    memset((char *)master_keyblock.contents, 0, (size_t) master_keyblock.length);
+    if (retval && retval != KRB5_KDB_DBNOTINITED) {
+	com_err(progname, retval, "while closing database");
+	exit(1);
+    }
+
+    if (str_master_princ) {
+	krb5_free_unparsed_name(context, str_master_princ);
+    }
+    krb5_free_principal(context, master_princ);
+    krb5_free_context(context);
+    exit(0);
+}
+
+int
+check_princ(context, str_princ)
+    krb5_context context;
+    char * str_princ;
+{
+    krb5_error_code retval;
+    krb5_db_entry kdbe;
+    krb5_keyblock pwd_key, db_key;
+    krb5_data pwd, salt;
+    krb5_principal princ;
+    krb5_boolean more;
+    int nprincs = 1;
+    /* char *str_mod_name; */
+    char princ_name[4096];
+
+    sprintf(princ_name, "%s@%s", str_princ, cur_realm);
+
+    fprintf(stderr, "\t%s ...\n", princ_name);
+
+    if ((retval = krb5_parse_name(context, princ_name, &princ))) {
+      com_err(progname, retval, "while parsing '%s'", princ_name);
+      goto out;
+    }
+
+    pwd.data = princ_name;  /* must be able to regenerate */
+    pwd.length = strlen(princ_name);
+
+    if ((retval = krb5_principal2salt(context, princ, &salt))) {
+	com_err(progname, retval, "while converting principal to salt for '%s'", princ_name);
+	krb5_free_principal(context, princ);
+	goto out;
+    }
+
+    if ((retval = krb5_string_to_key(context, &master_encblock, 
+				    &pwd_key, &pwd, &salt))) {
+	com_err(progname, retval, "while converting password to key for '%s'", 
+		princ_name);
+	krb5_free_data_contents(context, &salt);
+	krb5_free_principal(context, princ);
+	goto out;
+    }
+    krb5_free_data_contents(context, &salt);
+
+    if ((retval = krb5_db_get_principal(context, princ, &kdbe, 
+					&nprincs, &more))) {
+      com_err(progname, retval, "while attempting to verify principal's existence");
+      krb5_free_principal(context, princ);
+      goto out;
+    }
+    krb5_free_principal(context, princ);
+
+    if (nprincs != 1) {
+      com_err(progname, 0, "Found %d entries db entry for %s.\n", nprincs,
+	      princ_name);
+      goto errout;
+    }
+
+    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;
+    }
+
+    if ((pwd_key.enctype != db_key.enctype) ||
+	(pwd_key.length != db_key.length)) {
+      fprintf (stderr, "\tKey types do not agree (%d expected, %d from db)\n",
+	       pwd_key.enctype, db_key.enctype);
+errout:
+      krb5_db_free_principal(context, &kdbe, nprincs);
+      return(-1);
+    }
+    else {
+      if (memcmp((char *)pwd_key.contents, (char *) db_key.contents, 
+		 (size_t) pwd_key.length)) {
+	fprintf(stderr, "\t key did not match stored value for %s\n", 
+		princ_name);
+	goto errout;
+      }
+    }
+
+    free((char *)pwd_key.contents);
+    free((char *)db_key.contents);
+
+    if (kdbe.key_data[0].key_data_kvno != 1) {
+      fprintf(stderr,"\tkvno did not match stored value for %s.\n", princ_name);
+      goto errout;
+    }
+
+    if (kdbe.max_life != mblock.max_life) {
+      fprintf(stderr, "\tmax life did not match stored value for %s.\n", 
+	      princ_name);
+      goto errout;
+    }
+
+    if (kdbe.max_renewable_life != mblock.max_rlife) {
+      fprintf(stderr, 
+	      "\tmax renewable life did not match stored value for %s.\n",
+	      princ_name);
+      goto errout;
+    }
+
+    if (kdbe.expiration != mblock.expiration) {
+      fprintf(stderr, "\texpiration time did not match stored value for %s.\n",
+	      princ_name);
+      goto errout;
+    }
+
+/*
+    if ((retval = krb5_unparse_name(context, kdbe.mod_name, &str_mod_name)))
+      com_err(progname, retval, "while unparsing mode name");
+    else {
+      if (strcmp(str_mod_name, str_master_princ) != 0) {
+	fprintf(stderr, "\tmod name isn't the master princ (%s not %s).\n",
+		str_mod_name, str_master_princ);
+	free(str_mod_name);
+	goto errout;
+      }
+      else free(str_mod_name);
+    }
+*/
+
+    if (kdbe.attributes != mblock.flags) {
+      fprintf(stderr, "\tAttributes did not match stored value for %s.\n",
+	      princ_name);
+      goto errout;
+    }
+
+    out:
+    krb5_db_free_principal(context, &kdbe, nprincs);
+
+    return(0);
+}
+
+int
+set_dbname_help(context, pname, dbname)
+    krb5_context context;
+    char *pname;
+    char *dbname;
+{
+    krb5_error_code retval;
+    int nentries;
+    krb5_boolean more;
+    krb5_data pwd, scratch;
+    char *args[2];
+
+    /* assemble & parse the master key name */
+
+    if ((retval = krb5_db_setup_mkey_name(context, mkey_name, cur_realm, 0,
+					 &master_princ))) {
+	com_err(pname, retval, "while setting up master key name");
+	return(1);
+    }
+    if (mkey_password) {
+	pwd.data = mkey_password;
+	pwd.length = strlen(mkey_password);
+	retval = krb5_principal2salt(context, master_princ, &scratch);
+	if (retval) {
+	    com_err(pname, retval, "while calculated master key salt");
+	    return(1);
+	}
+	if ((retval = krb5_string_to_key(context, &master_encblock, 
+				    &master_keyblock, &pwd, &scratch))) {
+	    com_err(pname, retval,
+		    "while transforming master key from password");
+	    return(1);
+	}
+	free(scratch.data);
+    } else {
+	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");
+	    return(1);
+	}
+    }
+
+    /* Ick!  Current DAL interface requires that the default_realm
+       field be set in the krb5_context.  */
+    if ((retval = krb5_set_default_realm(context, cur_realm))) {
+	com_err(pname, retval, "setting default realm");
+	return 1;
+    }
+    /* Pathname is passed to db2 via 'args' parameter.  */
+    args[1] = NULL;
+    args[0] = malloc(sizeof("dbname=") + strlen(dbname));
+    if (args[0] == NULL) {
+	com_err(pname, errno, "while setting up db parameters");
+	return 1;
+    }
+    sprintf(args[0], "dbname=%s", dbname);
+
+    if ((retval = krb5_db_open(context, args, KRB5_KDB_OPEN_RO))) {
+	com_err(pname, retval, "while initializing database");
+	return(1);
+    }
+    if ((retval = krb5_db_verify_master_key(context, master_princ, 
+					    &master_keyblock))) {
+	com_err(pname, retval, "while verifying master key");
+	(void) krb5_db_fini(context);
+	return(1);
+    }
+    nentries = 1;
+    if ((retval = krb5_db_get_principal(context, master_princ, &master_entry, 
+				       &nentries, &more))) {
+	com_err(pname, retval, "while retrieving master entry");
+	(void) krb5_db_fini(context);
+	return(1);
+    } else if (more) {
+	com_err(pname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
+		"while retrieving master entry");
+	(void) krb5_db_fini(context);
+	return(1);
+    } else if (!nentries) {
+	com_err(pname, KRB5_KDB_NOENTRY, "while retrieving master entry");
+	(void) krb5_db_fini(context);
+	return(1);
+    }
+
+    if ((retval = krb5_unparse_name(context, master_princ, 
+				    &str_master_princ))) {
+      com_err(pname, retval, "while unparsing master principal");
+      krb5_db_fini(context);
+      return(1);
+    }
+
+    if ((retval = krb5_process_key(context,
+				  &master_encblock, &master_keyblock))) {
+	com_err(pname, retval, "while processing master key");
+	(void) krb5_db_fini(context);
+	return(1);
+    }
+    if ((retval = krb5_init_random_key(context,
+				      &master_encblock, &master_keyblock,
+				      &master_random))) {
+	com_err(pname, retval, "while initializing random key generator");
+	krb5_finish_key(context, &master_encblock);
+	(void) krb5_db_fini(context);
+	return(1);
+    }
+    mblock.max_life = master_entry.max_life;
+    mblock.max_rlife = master_entry.max_renewable_life;
+    mblock.expiration = master_entry.expiration;
+    /* don't set flags, master has some extra restrictions */
+    mblock.mkvno = master_entry.key_data[0].key_data_kvno;
+
+    krb5_db_free_principal(context, &master_entry, nentries);
+    return 0;
+}
+
diff --git a/krb5-1-6/src/tests/verify/pkey.c b/krb5-1-6/src/tests/verify/pkey.c
new file mode 100644
index 000000000..a577f064f
--- /dev/null
+++ b/krb5-1-6/src/tests/verify/pkey.c
@@ -0,0 +1,24 @@
+/*
+ * tests/verify/pkey.c
+ *
+ * Copyright 1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/copyright.h>.
+ *
+ */
+
+#include <stdio.h>
+
+void pkey(k)
+     unsigned char *k;
+{
+  int i;
+  unsigned int foo;
+
+  for (i = 0 ; i < 8 ; i++) {
+    foo = *k++;
+    fprintf(stderr, "%x ", foo);
+  }
+}
diff --git a/krb5-1-6/src/util/Makefile.in b/krb5-1-6/src/util/Makefile.in
new file mode 100644
index 000000000..0ded4f35d
--- /dev/null
+++ b/krb5-1-6/src/util/Makefile.in
@@ -0,0 +1,61 @@
+thisconfigdir=./..
+myfulldir=util
+mydir=util
+##WIN32###Windows NMAKE doesn't like @ in make variable names, and on
+##WIN32### Windows we don't do the @FOO@ substitutions we do with UNIX
+##WIN32### configure scripts.  The set of subdirs to use is hard-coded
+##WIN32### below in the 'all-windows' target anyways, so just hide this.
+##WIN32##!if 0
+LOCAL_SUBDIRS=support $(MAYBE_ET_@COM_ERR_VERSION@) $(MAYBE_SS_@SS_VERSION@) \
+	profile send-pr
+##WIN32##!endif
+BUILDTOP=$(REL)..
+
+MAYBE_ET_k5 = et
+MAYBE_SS_k5 = ss
+MAYBE_ET_sys =
+MAYBE_SS_sys =
+
+editsh = sed -e 's,@''ARADD''@,$(ARADD),g' -e 's,@''ARCHIVE''@,$(ARCHIVE),g'
+HOST_TYPE=@HOST_TYPE@
+HAVE_GCC=@HAVE_GCC@
+SLIBSH=sed -e 's|@''CC''@|$(CC)|g' -e 's,@''HOST_TYPE''@,$(HOST_TYPE),g' -e 's,@''HAVE_GCC''@,$(HAVE_GCC),g'
+
+DL_COMPILE=@DL_COMPILE@
+DL_COMPILE_TAIL=@DL_COMPILE_TAIL@
+
+all-recurse:
+
+clean-unix::
+	$(RM) -r $(FAKEPREFIX)
+
+NO_OUTDIR=1
+all-windows::
+	@echo Making in util\windows
+	cd windows
+	$(MAKE) -$(MFLAGS)
+	@echo Making in util\support
+	cd ..\support
+	$(MAKE) -$(MFLAGS)
+	@echo Making in util\et
+	cd ..\et
+	$(MAKE) -$(MFLAGS) 
+	@echo Making in util\profile
+	cd ..\profile
+	$(MAKE) -$(MFLAGS) 
+	cd ..
+
+clean-windows::
+	@echo Making clean in util\windows
+	cd windows
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in util\et
+	cd ..\et
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in util\profile
+	cd ..\profile
+	$(MAKE) -$(MFLAGS) clean
+	cd ..
+
+install::
+	@echo nothing to install in util
diff --git a/krb5-1-6/src/util/ac_check_krb5.m4 b/krb5-1-6/src/util/ac_check_krb5.m4
new file mode 100644
index 000000000..e18183b65
--- /dev/null
+++ b/krb5-1-6/src/util/ac_check_krb5.m4
@@ -0,0 +1,58 @@
+dnl Copyright (C) 2005 by the Massachusetts Institute of Technology.
+dnl All rights reserved.
+dnl
+dnl Export of this software from the United States of America may
+dnl   require a specific license from the United States Government.
+dnl   It is the responsibility of any person or organization contemplating
+dnl   export to obtain such a license before exporting.
+dnl 
+dnl WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+dnl distribute this software and its documentation for any purpose and
+dnl without fee is hereby granted, provided that the above copyright
+dnl notice appear in all copies and that both that copyright notice and
+dnl this permission notice appear in supporting documentation, and that
+dnl the name of M.I.T. not be used in advertising or publicity pertaining
+dnl to distribution of the software without specific, written prior
+dnl permission.  Furthermore if you modify this software you must label
+dnl your software as modified software and not distribute it in such a
+dnl fashion that it might be confused with the original M.I.T. software.
+dnl M.I.T. makes no representations about the suitability of
+dnl this software for any purpose.  It is provided "as is" without express
+dnl or implied warranty.
+
+dnl AC_CHECK_KRB5
+dnl
+dnl Check for krb5-config; update CPPFLAGS and LDFLAGS accordingly.
+dnl
+AC_DEFUN([AC_CHECK_KRB5],
+[AC_ARG_WITH([kerberos5],
+	[  --with-kerberos5=PATH   Enable Kerberos 5 support],
+	[if test "x$withval" != "xno"; then
+		if test "x$withval" = "xyes"; then
+			KRB5ROOT=/usr/local
+		else
+			KRB5ROOT=${withval}
+		fi
+		AC_MSG_CHECKING([for krb5-config])
+		if test -x "$KRB5ROOT/bin/krb5-config"; then
+			KRB5CONF=$KRB5ROOT/bin/krb5-config
+			AC_MSG_RESULT([$KRB5CONF])
+			AC_MSG_CHECKING([for gssapi support in krb5-config])
+			if "$KRB5CONF" | grep gssapi > /dev/null; then
+				AC_MSG_RESULT([yes])
+				k5confopts=gssapi
+			else
+				AC_MSG_RESULT([no])
+				k5confopts=
+			fi
+			K5CFLAGS=`"$KRB5CONF" --cflags $k5confopts`
+			CPPFLAGS="$CPPFLAGS $K5CFLAGS"
+
+			K5LIBS=`"$KRB5CONF" --libs $k5confopts`
+			LIBS="$LIBS $K5LIBS"
+		else
+			AC_MSG_RESULT([no])
+			AC_MSG_WARN([--with-kerberos5 specified but krb5-config not found])
+		fi
+	fi])
+])
diff --git a/krb5-1-6/src/util/check-ac-syms b/krb5-1-6/src/util/check-ac-syms
new file mode 100755
index 000000000..a54a99042
--- /dev/null
+++ b/krb5-1-6/src/util/check-ac-syms
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# args: srcdir srctop-from-srcdir header-path
+
+d=`pwd`
+head -1 $1/configure.in > config-in.tmp
+echo "AC_CONFIG_HEADER(fooconfig.h:$d/fooconfig-h.tmp)" >> config-in.tmp
+tail +2 $1/configure.in | grep -v AC_CONFIG_HEADER >> config-in.tmp
+mv -f config-in.tmp config-in.ac~
+
+if (cd $1 && autoheader --include=$2 $d/config-in.ac~) > /dev/null; then
+  rm -rf $1/autom4te.cache config-in.ac~
+else
+  rm -rf $1/autom4te.cache
+# config-in.ac~ fooconfig-h.tmp
+  echo autoheader failed, eek
+  exit 1
+fi
+
+awk '/^#undef/ { print $2; }' < fooconfig-h.tmp | sort > acsyms.here
+rm -f fooconfig-h.tmp
+awk '/^#undef/ { print $2; }' < $3 | sort > acsyms.there
+
+comm -23 acsyms.here acsyms.there > acsyms.extra
+rm -f acsyms.here acsyms.there
+
+if test -s acsyms.extra; then
+  echo ERROR: Symbol or symbols defined here but not in `basename $3`: `cat acsyms.extra`
+  rm -f acsyms.extra
+  exit 1
+fi
+rm -f acsyms.extra
+exit 0
diff --git a/krb5-1-6/src/util/def-check.pl b/krb5-1-6/src/util/def-check.pl
new file mode 100644
index 000000000..a35e5c987
--- /dev/null
+++ b/krb5-1-6/src/util/def-check.pl
@@ -0,0 +1,259 @@
+#!/usr/athena/bin/perl -w
+
+# Code initially generated by s2p
+# Code modified to use strict and IO::File
+
+eval 'exec /usr/athena/bin/perl -S $0 ${1+"$@"}'
+    if 0; # line above evaluated when running under some shell (i.e., not perl)
+
+use strict;
+use IO::File;
+
+my $verbose = 0;
+my $error = 0;
+if ( $ARGV[0] eq "-v" ) { $verbose = 1; shift @ARGV; }
+my $h_filename = shift @ARGV || die "usage: $0 [-v] header-file [def-file]\n";
+my $d_filename = shift @ARGV;
+
+my $h = open_always($h_filename);
+my $d = open_always($d_filename) if $d_filename;
+
+sub open_always
+{
+    my $file = shift || die;
+    my $handle = new IO::File "<$file";
+    die "Could not open $file\n" if !$handle;
+    return $handle;
+}
+
+my @convW = ();
+my @convC = ();
+my @convK = ();
+my @convD = ();
+my @vararg = ();
+
+my $len1;
+my %conv;
+my $printit;
+my $vararg;
+
+LINE:
+while (! $h->eof()) {
+    $_ = $h->getline();
+    chop;
+    # get calling convention info for function decls
+    # what about function pointer typedefs?
+    # need to verify unhandled syntax actually triggers a report, not ignored
+    # blank lines
+    if (/^[ \t]*$/) {
+        next LINE;
+    }
+  Top:
+    # drop KRB5INT_BEGIN_DECLS and KRB5INT_END_DECLS
+    if (/^ *(KRB5INT|GSSAPI[A-Z]*)_(BEGIN|END)_DECLS/) {
+        next LINE;
+    }
+    # drop preprocessor directives
+    if (/^ *#/) {
+	while (/\\$/) { $_ .= $h->getline(); }
+        next LINE;
+    }
+    if (/^ *\?==/) {
+        next LINE;
+    }
+    s/#.*$//;
+    if (/^} *$/) {
+        next LINE;
+    }
+    # strip comments
+  Cloop1:
+    if (/\/\*./) {
+	s;/\*[^*]*;/*;;
+	s;/\*\*([^/]);/*$1;;
+	s;/\*\*$;/*;;
+	s;/\*\*/; ;g;
+	goto Cloop1;
+    }
+    # multi-line comments?
+    if (/\/\*$/) {
+	$_ .= " ";
+	$len1 = length;
+	$_ .= $h->getline();
+	chop if $len1 < length;
+	goto Cloop1 if /\/\*./;
+    }
+    # blank lines
+    if (/^[ \t]*$/) {
+        next LINE;
+    }
+    if (/^ *extern "C" {/) {
+        next LINE;
+    }
+    # elide struct definitions
+  Struct1:
+    if (/{[^}]*}/) {
+	s/{[^}]*}/ /g;
+	goto Struct1;
+    }
+    # multi-line defs
+    if (/{/) {
+	$_ .= "\n";
+	$len1 = length;
+	$_ .= $h->getline();
+	chop if $len1 < length;
+	goto Struct1;
+    }
+  Semi:
+    unless (/;/) {
+	$_ .= "\n";
+	$len1 = length;
+	$_ .= $h->getline();
+	chop if $len1 < length;
+	s/\n/ /g;
+	s/[ \t]+/ /g;
+	s/^[ \t]*//;
+	goto Top;
+    }
+    if (/^typedef[^;]*;/) {
+	s/^typedef[^;]*;//g;
+	goto Semi;
+    }
+    if (/^struct[^\(\)]*;/) {
+	s/^struct[^\(\)]*;//g;
+	goto Semi;
+    }
+    # should just have simple decls now; split lines at semicolons
+    s/ *;[ \t]*$//;
+    s/ *;/\n/g;
+    if (/^[ \t]*$/) {
+        next LINE;
+    }
+    s/[ \t]*$//;
+    goto Notfunct unless /\(.*\)/;
+    # Get rid of KRB5_PROTOTYPE
+    s/KRB5_PROTOTYPE//;
+    s/KRB5_STDARG_P//;
+    # here, is probably function decl
+    # strip simple arg list - parens, no parens inside; discard, iterate.
+    # the iteration should deal with function pointer args.
+    $vararg = /\.\.\./;
+  Striparg:
+    if (/ *\([^\(\)]*\)/) {
+	s/ *\([^\(\)]*\)//g;
+	goto Striparg;
+    }
+    # replace return type etc with one token indicating calling convention
+    if (/CALLCONV/) {
+	if (/\bKRB5_CALLCONV_WRONG\b/) {
+	    s/^.*KRB5_CALLCONV_WRONG *//;
+	    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
+	    push @convW, $_;
+	    push @vararg, $_ if $vararg;
+	} elsif (/\bKRB5_CALLCONV_C\b/) {
+	    s/^.*KRB5_CALLCONV_C *//;
+	    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
+	    push @convC, $_;
+	    push @vararg, $_ if $vararg;
+	} elsif (/\bKRB5_CALLCONV\b/) {
+	    s/^.*KRB5_CALLCONV *//;
+	    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
+	    push @convK, $_;
+	    push @vararg, $_ if $vararg;
+	} else {
+	    die "Unrecognized calling convention while parsing: '$_'\n";
+	}
+	goto Hadcallc;
+    }
+    # deal with no CALLCONV indicator
+    s/^.* \**(\w+) *$/$1/;
+    die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/);
+    push @convD, $_;
+    push @vararg, $_ if $vararg;
+  Hadcallc:
+    goto Skipnotf;
+  Notfunct:
+    # probably a variable
+    s/^/VARIABLE_DECL /;
+  Skipnotf:
+    # toss blank lines
+    if (/^[ \t]*$/) {
+        next LINE;
+    }
+}
+
+if ( $verbose ) {
+    print join("\n\t", "Using default calling convention:", sort(@convD));
+    print join("\n\t", "\nUsing KRB5_CALLCONV:", sort(@convK));
+    print join("\n\t", "\nUsing KRB5_CALLCONV_C:", sort(@convC));
+    print join("\n\t", "\nUsing KRB5_CALLCONV_WRONG:", sort(@convW));
+    print "\n","-"x70,"\n";
+}
+
+%conv = ();
+map { $conv{$_} = "default"; } @convD;
+map { $conv{$_} = "KRB5_CALLCONV"; } @convK;
+map { $conv{$_} = "KRB5_CALLCONV_C"; } @convC;
+map { $conv{$_} = "KRB5_CALLCONV_WRONG"; } @convW;
+
+my %vararg = ();
+map { $vararg{$_} = 1; } @vararg;
+
+if (!$d) {
+    print "No .DEF file specified\n" if $verbose;
+    exit 0;
+}
+
+LINE2:
+while (! $d->eof()) {
+    $_ = $d->getline();
+    chop;
+    #
+    if (/^;/) {
+        $printit = 0;
+        next LINE2;
+    }
+    if (/^[ \t]*$/) {
+        $printit = 0;
+        next LINE2;
+    }
+    if (/^EXPORTS/ || /^DESCRIPTION/ || /^HEAPSIZE/) {
+        $printit = 0;
+        next LINE2;
+    }
+    s/[ \t]*//g;
+    s/@[0-9]+//;
+    my($xconv);
+    if (/PRIVATE/ || /INTERNAL/) {
+	$xconv = "PRIVATE";
+    } elsif (/DATA/) {
+	$xconv = "DATA";
+    } elsif (/!CALLCONV/ || /KRB5_CALLCONV_WRONG/) {
+	$xconv = "KRB5_CALLCONV_WRONG";
+    } elsif ($vararg{$_}) {
+	$xconv = "KRB5_CALLCONV_C";
+    } else {
+	$xconv = "KRB5_CALLCONV";
+    }
+    s/;.*$//;
+
+    if ($xconv eq "PRIVATE") {
+	print "\t private $_\n" if $verbose;
+	next LINE2;
+    }
+    if ($xconv eq "DATA") {
+	print "\t data $_\n" if $verbose;
+	next LINE2;
+    }
+    if (!defined($conv{$_})) {
+	print "No calling convention specified for $_!\n";
+	$error = 1;
+    } elsif (! ($conv{$_} eq $xconv)) {
+	print "Function $_ should have calling convention '$xconv', but has '$conv{$_}' instead.\n";
+	$error = 1;
+    } else {
+#	print "Function $_ is okay.\n";
+    }
+}
+
+#print "Calling conventions defined for: ", keys(%conv);
+exit $error;
diff --git a/krb5-1-6/src/util/depfix.pl b/krb5-1-6/src/util/depfix.pl
new file mode 100644
index 000000000..473b649bb
--- /dev/null
+++ b/krb5-1-6/src/util/depfix.pl
@@ -0,0 +1,228 @@
+#!env perl -w
+#
+# Copyright 1995,2001,2002,2003,2004,2005 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+#
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+#
+
+eval 'exec perl -S $0 ${1+"$@"}'
+  if 0;
+$0 =~ s/^.*?(\w+)[\.\w+]*$/$1/;
+
+# Input: srctop thisdir srcdir buildtop libgccfilename stlibobjs
+
+# Notes: myrelativedir is something like "lib/krb5/asn.1" or ".".
+# stlibobjs will usually be empty, or include spaces.
+
+# A typical set of inputs, produced with srcdir=.. at top level:
+#
+# SRCTOP = ../../../util/et/../..
+# thisdir = util/et
+# srcdir = ../../../util/et
+# BUILDTOP = ../..
+# libgcc file name = /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/libgcc.a
+# STLIBOBJS = error_message.o et_name.o com_err.o
+
+my($SRCTOP,$thisdir,$srcdir,$BUILDTOP,$libgccpath,$STLIBOBJS) = @ARGV;
+
+if (0) {
+    print STDERR "SRCTOP = $SRCTOP\n";
+    print STDERR "BUILDTOP = $BUILDTOP\n";
+    print STDERR "STLIBOBJS = $STLIBOBJS\n";
+}
+
+$libgccincdir = $libgccpath;
+$libgccincdir =~ s,libgcc\.[^ ]*$,include,;
+$libgccincdir = quotemeta($libgccincdir);
+#$srcdirpat = quotemeta($srcdir);
+
+# Tweak here if you need to ignore additional directories.
+#my(@ignoredirs) = ( $libgccincdir, "/var/raeburn/openldap/Install/include" );
+my(@ignoredirs) = ( $libgccincdir );
+
+my($extrasuffixes) = ($STLIBOBJS ne "");
+
+sub my_qm {
+    my($x) = @_;
+    $x = quotemeta($x);
+    $x =~ s,\\/,/,g;
+    return $x;
+}
+
+sub strrep {
+    my($old,$new,$s) = @_;
+    my($l) = "strrep('$old','$new','$s')";
+    my($out) = "";
+    while ($s ne "") {
+	my($i) = index($s, $old);
+	if ($i == -1) {
+	    $out .= $s;
+	    $s = "";
+	} else {
+	    $out .= substr($s, 0, $i) . $new;
+	    if (length($s) > $i + length($old)) {
+		$s = substr($s, $i + length($old));
+	    } else {
+		$s = "";
+	    }
+	}
+    }
+#    print STDERR "$l = '$out'\n";
+    return $out;
+}
+
+sub do_subs {
+    local($_) = @_;
+    s,\\$, \\,g; s, + \\$, \\,g;
+    s,//+,/,g; s, \./, ,g;
+    if ($extrasuffixes) {
+	# Only care about the additional prefixes if we're building
+	# shared libraries.
+	s,^([a-zA-Z0-9_\-]*)\.o:,$1.so $1.po \$(OUTPRE)$1.\$(OBJEXT):,;
+    } else {
+	s,^([a-zA-Z0-9_\-]*)\.o:,\$(OUTPRE)$1.\$(OBJEXT):,;
+    }
+    # Drop GCC include files, they're basically system headers.
+    my ($x);
+    foreach $x (@ignoredirs) {
+	s,$x/[^ ]* ,,g;
+	s,$x/[^ ]*$,,g;
+    }
+    # Recognize $(SRCTOP) and variants.
+    my($srct) = $SRCTOP . "/";
+    $_ = strrep(" $srct", " \$(SRCTOP)/", $_);
+#    s, $pat, \$(SRCTOP)/,go;
+    while ($srct =~ m,/[a-z][a-zA-Z0-9_.\-]*/\.\./,) {
+	$srct =~ s,/[a-z][a-zA-Z0-9_.\-]*/\.\./,/,;
+	$_ = strrep(" $srct", " \$(SRCTOP)/", $_);
+    }
+    # Now try to produce pathnames relative to $(srcdir).
+    if ($thisdir eq ".") {
+	# blah
+    } else {
+	my($pat) = " \$(SRCTOP)/$thisdir/";
+	my($out) = " \$(srcdir)/";
+	$_ = strrep($pat, $out, $_);
+	while ($pat =~ m,/[a-z][a-zA-Z0-9_.\-]*/$,) {
+	    $pat =~ s,/[a-z][a-zA-Z0-9_.\-]*/$,/,;
+	    $out .= "../";
+	    if ($pat ne " \$(SRCTOP)/") {
+		$_ = strrep($pat, $out, $_);
+	    }
+	}
+    }
+    # Now substitute for BUILDTOP:
+    $_ = strrep(" $BUILDTOP/", " \$(BUILDTOP)/", $_);
+    return $_;
+}
+
+sub do_subs_2 {
+    local($_) = @_;
+    # Add a trailing space.
+    s/$/ /;
+    # Remove excess spaces.
+    s/  */ /g;
+    # Delete Tcl-specific headers.
+    s;/[^ ]*/tcl\.h ;;g;
+    s;/[^ ]*/tclDecls\.h ;;g;
+    s;/[^ ]*/tclPlatDecls\.h ;;g;
+    # Delete system-specific or compiler-specific files.
+    s;/os/usr/include/[^ ]* ;;g;
+    s;/usr/include/[^ ]* ;;g;
+    s;/usr/lib/[^ ]* ;;g;
+    # Remove foo/../ sequences.
+    while (m/\/[a-z][a-z0-9_.\-]*\/\.\.\//) {
+	s//\//g;
+    }
+    # Use VPATH.
+    s;\$\(srcdir\)/([^ /]* );$1;g;
+
+    # Allow override of some util dependencies in case local tools are used.
+    s;\$\(BUILDTOP\)/include/com_err.h ;\$(COM_ERR_DEPS) ;g;
+    s;\$\(BUILDTOP\)/include/ss/ss.h \$\(BUILDTOP\)/include/ss/ss_err.h ;\$(SS_DEPS) ;g;
+    s;\$\(BUILDTOP\)/include/db.h \$\(BUILDTOP\)/include/db-config.h ;\$(DB_DEPS) ;g;
+
+    $_ = &uniquify($_);
+
+    # Some krb4 dependencies should only be present if building with krb4
+    # enabled.
+    s;\$\(BUILDTOP\)/include/kerberosIV/krb_err.h ;\$(KRB_ERR_H_DEP) ;g;
+
+    # Delete trailing whitespace.
+    s; *$;;g;
+
+    return $_;
+}
+
+sub uniquify {
+    # Apparently some versions of gcc -- like
+    # "gcc version 3.4.4 20050721 (Red Hat 3.4.4-2)"
+    # -- will sometimes emit duplicate header file names.
+    local($_) = @_;
+    my(@sides) = split ": ", $_;
+    my($lhs) = "";
+    if ($#sides == 1) {
+	$lhs = $sides[0] . ": ";
+	$_ = $sides[1];
+    }
+    my(@words) = split " ", $_;
+    my($w);
+    my($result) = "";
+    my(%seen);
+    undef %seen;
+    foreach $w (sort { $a cmp $b; } @words) {
+	next if defined($seen{$w});
+	$seen{$w} = 1;
+	if ($result ne "") { $result .= " "; }
+	$result .= $w;
+    }
+    return $lhs . $result . " ";
+}
+
+sub split_lines {
+    local($_) = @_;
+    s/(.{50}[^ ]*) /$1 \\\n  /g;
+    return $_ . "\n";
+}
+
+print <<EOH ;
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+EOH
+my $buf = '';
+while (<STDIN>) {
+    # Strip newline.
+    chop;
+    # Do directory-specific path substitutions on each filename read.
+    $_ = &do_subs($_);
+    if (m/\\$/) {
+	chop;
+	$buf .= $_;
+    } else {
+	$buf = &do_subs_2($buf . $_);
+	print &split_lines($buf);
+	$buf = '';
+    }
+}
+exit 0;
diff --git a/krb5-1-6/src/util/et/ISSUES b/krb5-1-6/src/util/et/ISSUES
new file mode 100644
index 000000000..2197fb7af
--- /dev/null
+++ b/krb5-1-6/src/util/et/ISSUES
@@ -0,0 +1,60 @@
+Issues to be addressed for src/util/et: -*- text -*-
+
+Non-thread-safe aspects:
+
+error_message uses a static buffer for "unknown error code" messages;
+a per-thread buffer may be better, but that depends on dynamic
+allocation working.  A caller-provided buffer would be best, but
+that's a API change.
+
+initialize_foo_error_table uses a global linked list hung off an
+unprotected variable in the library.  {add,remove}_error_table do
+likewise, but can be changed without externally visible effect.
+
+Workaround: Use a global lock for all calls to error_message and
+com_err, and when adding or removing error tables.
+
+API divergence:
+
+Transarc and Heimdal both have APIs that are different from this
+version.  (Specifics?)
+
+Karl Ramm has offered to try to combine them.
+
+Workaround:
+
+Reference counting:
+
+If libraries are dynamically loaded and unloaded, and the init/fini
+functions add and remove error tables for *other* libraries they
+depend on (e.g., if a dynamically loadable Zephyr library's fini
+function removes the krb4 library error table and then dlcloses the
+krb4 library, while another dlopen reference keeps the krb4 library
+around), the error table is kept; a table must be removed the same
+number of times it was added before the library itself can be
+discarded.
+
+It's not implemented as a reference count, but the effect is the same.
+
+Fix needed: Update documentation.
+
+64-bit support:
+
+Values are currently computed as 32-bit values, sign-extended to
+"long", and output with "L" suffixes.  Type errcode_t is "long".
+Kerberos uses a seperately chosen signed type of at least 32 bits for
+error codes.  The com_err library only look at the low 32 bits, so
+this is mostly just an issue for application code -- if anything
+truncates to 32 bits, and then widens without sign-extending, the
+value may not compare equal to the macro defined in the .h file.  This
+isn't anything unusual for signed constants, of course, just something
+to keep in mind....
+
+Workaround: Always use signed types of at least 32 bits for error
+codes.
+
+man page:
+
+No documentation on add_error_table/remove_error_table interfaces,
+even though they're the new, preferred interface.
+
diff --git a/krb5-1-6/src/util/et/Makefile.in b/krb5-1-6/src/util/et/Makefile.in
new file mode 100644
index 000000000..b7aa747a8
--- /dev/null
+++ b/krb5-1-6/src/util/et/Makefile.in
@@ -0,0 +1,264 @@
+prefix=@prefix@
+bindir=@bindir@
+datadir=@datadir@
+mydatadir=$(datadir)/et
+thisconfigdir=../..
+myfulldir=util/et
+mydir=util/et
+BUILDTOP=$(REL)..$(S)..
+RELDIR=../util/et
+SED = sed
+DEFS=
+
+##DOS##BUILDTOP = ..\..
+##DOS##LIBNAME=$(OUTPRE)comerr.lib
+##DOS##XTRA=
+##DOS##OBJFILE=$(OUTPRE)comerr.lst
+
+STLIBOBJS=error_message.o et_name.o com_err.o
+STOBJLISTS=OBJS.ST
+LIBBASE=com_err
+LIBMAJOR=3
+LIBMINOR=0
+LIBINITFUNC=com_err_initialize
+LIBFINIFUNC=com_err_terminate
+
+all-unix:: all-liblinks
+clean-unix:: clean-liblinks clean-libs clean-libobjs clean-lclint
+install-unix:: install-libs
+
+LINTFLAGS=-uhvb 
+LINTFILES= error_message.c et_name.c com_err.c
+LIBOBJS=$(OUTPRE)com_err.$(OBJEXT) \
+	$(OUTPRE)error_message.$(OBJEXT) \
+	$(OUTPRE)et_name.$(OBJEXT)
+# for et_lex.lex.c include in error_table.y
+LOCALINCLUDES=-I. -I$(srcdir)
+
+FILES=	Makefile et_name.c error_message.c compile_et.c \
+		et_lex.lex.l error_table.y init_et.c \
+		com_err.c com_err.h \
+		error_table.h mit-sipb-copyright.h \
+		test_et.c test1.et test2.et \
+		t_com_err.c et1.et et2.et \
+		compiler.h internal.h \
+		com_err.texinfo texinfo.tex
+#SRCS=	compile_et.c error_table.c error_message.c et_name.c \
+#	init_et.c com_err.c
+SRCS= $(srcdir)/error_message.c \
+	$(srcdir)/et_name.c \
+	$(srcdir)/com_err.c
+
+#
+# Warning flags
+#
+# Uncomment WFLAGS if you want really anal GCC warning messages
+#
+#
+WFLAGS=		-ansi -D_POSIX_SOURCE -pedantic \
+			-Wall -Wwrite-strings -Wpointer-arith \
+			-Wcast-qual -Wcast-align -Wtraditional \
+			-Wstrict-prototypes -Wmissing-prototypes \
+			-Wnested-externs -Winline -DNO_INLINE_FUNCS -Wshadow 
+
+DEPLIBS=
+SHLIB_LIBS=
+SHLIB_EXPDEPS = $(SUPPORT_DEPLIB)
+SHLIB_EXPLIBS=-l$(SUPPORT_LIBNAME) $(LIBS)
+SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@	
+SHLIB_LIBDIRS= @SHLIB_LIBDIRS@
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+SHLIB_DIRS=-L$(TOPLIBD)
+
+COM_ERR_HDR=$(BUILDTOP)$(S)include$(S)com_err.h
+
+all-windows:: $(COM_ERR_HDR)
+
+$(COM_ERR_HDR): com_err.h
+	$(CP) com_err.h "$@"
+
+generate-files-mac: compile_et
+
+error_table.c: et_lex.lex.c 
+error_table.c: $(srcdir)/error_table.y
+
+error_table.o: error_table.c et_lex.lex.c
+	$(CC) $(ALL_CFLAGS) -c error_table.c
+
+com_err.o : com_err.c
+
+et_lex.lex.o: et_lex.lex.c
+test1.o: test1.c
+test2.o: test2.c
+test_et.o: test1.h test2.h
+et1.o: et1.c
+et2.o: et2.c
+test1.c test2.c et1.c et2.c test1.h test2.h et1.h et2.h: \
+	compile_et et_c.awk et_h.awk
+t_com_err.o: et1.h et2.h t_com_err.c
+
+# /u1/kr/lclint-2.5q/bin/lclint -warnposix -D__sparc
+LCLINT=lclint
+# +posixlib	gets more complete errno list than ansilib
+# -usedef	turns off bogus warnings from poor dataflow analysis (should be
+#		redundant with gcc warnings anyways)
+# -warnposix
+# +charintliteral
+# +ignoresigns
+# -predboolint
+# -exportlocal
+# -retvalint	allow ignoring of int return values (e.g., fputs)
+LCLINTOPTS=+posixlib \
+	-usedef -warnposix +charintliteral +ignoresigns -predboolint +boolint \
+	-exportlocal -retvalint \
+	+mod-uncon +modinternalstrict +modfilesys
+com_err.lcd: error_table.c error_table.h et_lex.lex.c com_err.h
+	$(LCLINT) $(LCLINTOPTS) $(LOCALINCLUDES) $(DEFS) $(SRCS) \
+		-dump com_err.new -expect 1
+	mv -f com_err.new com_err.lcd
+do-lclint: com_err.lcd t_com_err.c et1.c et2.c et1.h et2.h
+	$(LCLINT) $(LCLINTOPTS) $(LOCALINCLUDES) \
+		$(srcdir)/t_com_err.c et1.c et2.c
+# "-load com_err.lcd" -> lclint brokenness
+clean-lclint:
+	$(RM) com_err.new com_err.lcd
+ITS4=its4
+ITS4OPTS=
+do-its4: error_table.y et_lex.lex.c
+	$(ITS4) $(ITS4OPTS) $(SRCS)
+
+#test_et: test_et.o test1.o test2.o $(LIBOBJS)
+#	$(CC) -o test_et test_et.o test1.o test2.o $(LIBOBJS)
+#t_com_err: t_com_err.o et1.o et2.o $(LIBOBJS)
+#	$(CC) -o t_com_err t_com_err.o et1.o et2.o $(LIBOBJS)
+
+PROG_RPATH=$(KRB5_LIBDIR)
+PROG_LIBPATH=-L$(TOPLIBD)
+test_et: test_et.o test1.o test2.o $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o test_et test_et.o test1.o test2.o -lcom_err $(SUPPORT_LIB)
+t_com_err: t_com_err.o et1.o et2.o $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o t_com_err t_com_err.o et1.o et2.o -lcom_err $(SUPPORT_LIB)
+
+$(OUTPRE)test_et.exe: $(OUTPRE)test_et.$(OBJEXT) $(OUTPRE)test1.$(OBJEXT) \
+	$(OUTPRE)test2.$(OBJEXT) $(CLIB)
+	link $(EXE_LINKOPTS) -out:$(OUTPRE)test_et$(EXEEXT) $**
+
+all-unix:: compile_et includes
+
+includes:: com_err.h
+	if cmp $(srcdir)/com_err.h \
+	$(BUILDTOP)/include/com_err.h >/dev/null 2>&1; then :; \
+	else \
+		(set -x; $(RM) $(BUILDTOP)/include/com_err.h; \
+		 $(CP) $(srcdir)/com_err.h \
+			$(BUILDTOP)/include/com_err.h) ; \
+	fi
+
+clean-unix::
+	$(RM) $(BUILDTOP)/include/com_err.h
+
+RUN_SETUP = @KRB5_RUN_ENV@
+# test_et doesn't have an interesting exit status, but it'll exercise
+# some cases that t_com_err doesn't, so let's see if it crashes.
+check-unix:: t_com_err test_et
+	$(RUN_SETUP) $(VALGRIND) ./test_et
+	$(RUN_SETUP) $(VALGRIND) ./t_com_err
+
+check-windows:: $(OUTPRE)test_et$(EXEEXT)
+	set path=$(BUILDTOP)\lib\$(OUTPRE);%path%;
+	path
+	$(OUTPRE)test_et$(EXEEXT)
+
+# The real compile_et just isn't portable.  (But then again, anything using 
+# lex and yacc isn't portable by definition.  :-(  )
+#
+#compile_et: compile_et.o error_table.o
+#	$(CC) $(CFLAGS) -o $@ compile_et.o error_table.o $(LEXLIB) $(BSDLIB)
+#
+install-unix:: compile_et
+	$(INSTALL) compile_et $(DESTDIR)$(bindir)/compile_et
+	test -d $(DESTDIR)$(mydatadir) || mkdir $(DESTDIR)$(mydatadir)
+	$(INSTALL_DATA) $(srcdir)/et_c.awk $(DESTDIR)$(mydatadir)
+	$(INSTALL_DATA) $(srcdir)/et_h.awk $(DESTDIR)$(mydatadir)
+
+
+install-headers:: compile_et
+
+compile_et: $(srcdir)/compile_et.sh $(srcdir)/config_script
+	$(SHELL) $(srcdir)/config_script $(srcdir)/compile_et.sh \
+		"$(mydatadir)" $(AWK) $(SED) > compile_et
+	chmod 755 compile_et	
+
+rebuild: rebuild-c rebuild-h
+rebuild-c:
+	a2p < $(srcdir)/et_c.awk | awk 'NR != 1 || $$0 !~ /^\043!/{print;}' > $(srcdir)/et_c.tmp
+	mv -f $(srcdir)/et_c.tmp $(srcdir)/et_c.pl
+rebuild-h:
+	a2p < $(srcdir)/et_h.awk | awk 'NR != 1 || $$0 !~ /^\043!/{print;}' > $(srcdir)/et_h.tmp
+	mv -f $(srcdir)/et_h.tmp $(srcdir)/et_h.pl
+
+clean-unix::
+	$(RM) compile_et
+
+depend:: 
+
+install:: com_err.h 
+	$(INSTALL_DATA) $(srcdir)/com_err.h  $(DESTDIR)$(KRB5_INCDIR)/com_err.h
+
+install-unix:: compile_et.1
+	$(INSTALL_DATA) $(srcdir)/compile_et.1 $(DESTDIR)$(CLIENT_MANDIR)/compile_et.1
+
+
+## install_library_target(com_err,$(LIBOBJS),$(LINTFILES),)
+
+clean-unix:: clean-files
+
+clean-files::
+	rm -f *~ \#* *.bak \
+		*.otl *.aux *.toc *.PS *.dvi *.x9700 *.ps \
+		*.cp *.fn *.ky *.log *.pg *.tp *.vr \
+		*.o profiled/?*.o libcom_err.a libcom_err_p.a \
+		com_err.o compile_et \
+		et.ar TAGS y.tab.c lex.yy.c error_table.c \
+		et_lex.lex.c \
+		test1.h test1.c test2.h test2.c test_et \
+		et1.c et1.h et2.c et2.h t_com_err \
+		eddep makedep *.ln
+
+clean-windows::
+	$(RM) $(COM_ERR_HDR)
+
+com_err.ps : com_err.dvi
+com_err.dvi: com_err.texinfo
+
+libcom_err.o:	$(LIBOBJS)
+	ld -r -s -o libcom_err.o $(LIBOBJS)
+	chmod -x libcom_err.o
+
+archive:	et.tar
+
+TAGS:	et_name.c error_message.c compile_et.c error_table.c \
+		lex.yy.c init_et.c
+	etags et_name.c error_message.c compile_et.c \
+		error_table.c init_et.c
+
+depend::  et_lex.lex.c
+
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+error_message.so error_message.po $(OUTPRE)error_message.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h com_err.h error_message.c \
+  error_table.h
+et_name.so et_name.po $(OUTPRE)et_name.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-thread.h com_err.h error_table.h \
+  et_name.c
+com_err.so com_err.po $(OUTPRE)com_err.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-thread.h com_err.c com_err.h error_table.h
diff --git a/krb5-1-6/src/util/et/com_err.3 b/krb5-1-6/src/util/et/com_err.3
new file mode 100644
index 000000000..d4704342c
--- /dev/null
+++ b/krb5-1-6/src/util/et/com_err.3
@@ -0,0 +1,96 @@
+.\" Copyright (c) 1988 Massachusetts Institute of Technology,
+.\" Student Information Processing Board.  All rights reserved.
+.\"
+.\" util/et/com_err.3
+.\"
+.TH COM_ERR 3 "22 Nov 1988" SIPB
+.SH NAME
+com_err \- common error display routine
+.SH SYNOPSIS
+.nf
+ #include "com_err.h"
+.PP
+void com_err (whoami, code, format, ...);
+	const char *whoami;
+	long code;
+	const char *format;
+.PP
+proc = set_com_err_hook (proc);
+.fi
+void (*
+.I proc
+) (const char *, long, const char *, va_list);
+.nf
+.PP
+proc = reset_com_err_hook ();
+.PP
+void initialize_XXXX_error_table ();
+.fi
+.SH DESCRIPTION
+.I Com_err
+displays an error message on the standard error stream
+.I stderr
+(see
+.IR stdio (3S))
+composed of the
+.I whoami
+string, which should specify the program name or some subportion of
+a program, followed by an error message generated from the
+.I code
+value (derived from
+.IR compile_et (1)),
+and a string produced using the
+.I format
+string and any following arguments, in the same style as
+.IR fprintf (3).
+
+The behavior of
+.I com_err
+can be modified using
+.I set_com_err_hook;
+this defines a procedure which is called with the arguments passed to
+.I com_err,
+instead of the default internal procedure which sends the formatted
+text to error output.  Thus the error messages from a program can all
+easily be diverted to another form of diagnostic logging, such as
+.IR syslog (3).
+.I Reset_com_err_hook
+may be used to restore the behavior of
+.I com_err
+to its default form.  Both procedures return the previous ``hook''
+value.  These ``hook'' procedures must have the declaration given for
+.I proc
+above in the synopsis.
+
+The
+.I initialize_XXXX_error_table
+routine is generated mechanically by
+.IR compile_et (1)
+from a source file containing names and associated strings.  Each
+table has a name of up to four characters, which is used in place of
+the
+.B XXXX
+in the name of the routine.  These routines should be called before
+any of the corresponding error codes are used, so that the
+.I com_err
+library will recognize error codes from these tables when they are
+used.
+
+The
+.B com_err.h
+header file should be included in any source file that uses routines
+from the
+.I com_err
+library; executable files must be linked using
+.I ``-lcom_err''
+in order to cause the
+.I com_err
+library to be included.
+
+.\" .IR for manual entries
+.\" .PP for paragraph breaks
+
+.SH "SEE ALSO"
+compile_et (1), syslog (3).
+
+Ken Raeburn, "A Common Error Description Library for UNIX".
diff --git a/krb5-1-6/src/util/et/com_err.c b/krb5-1-6/src/util/et/com_err.c
new file mode 100644
index 000000000..c759e17b6
--- /dev/null
+++ b/krb5-1-6/src/util/et/com_err.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 1997 by Massachusetts Institute of Technology
+ * 
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "com_err.h"
+#include "error_table.h"
+
+#if defined(_WIN32)
+#include <io.h>
+#endif
+
+static /*@null@*/ et_old_error_hook_func com_err_hook = 0;
+k5_mutex_t com_err_hook_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+#if defined(_WIN32)
+BOOL  isGuiApp() {
+	DWORD mypid;
+	HANDLE myprocess;
+	mypid = GetCurrentProcessId();
+	myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid);
+	return GetGuiResources(myprocess, 1) > 0;
+	}
+#endif
+
+static void default_com_err_proc (const char *whoami, errcode_t code,
+				  const char *fmt, va_list ap)
+{
+#if defined(_WIN32)
+
+	char errbuf[1024] = "";
+
+	if (whoami) {
+		errbuf[sizeof(errbuf) - 1] = '\0';
+		strncat (errbuf, whoami, sizeof(errbuf) - 1 - strlen(errbuf));
+		strncat (errbuf, ": ", sizeof(errbuf) - 1 - strlen(errbuf));
+	}
+	if (code) {
+		errbuf[sizeof(errbuf) - 1] = '\0';
+		strncat (errbuf, error_message(code), sizeof(errbuf) - 1 - strlen(errbuf));
+		strncat (errbuf, " ", sizeof(errbuf) - 1 - strlen(errbuf));
+	}
+	if (fmt)
+	    /* ITS4: ignore vsprintf */
+	    vsprintf (errbuf + strlen (errbuf), fmt, ap);
+	errbuf[sizeof(errbuf) - 1] = '\0';
+
+	if (_isatty(_fileno(stderr)) || !isGuiApp()) {
+	    fputs(errbuf, stderr);
+	    fputc('\r', stderr);
+	    fputc('\n', stderr);
+	    fflush(stderr);
+	} else
+	    MessageBox ((HWND)NULL, errbuf, "Kerberos", MB_ICONEXCLAMATION);
+
+#else /* !_WIN32 */
+    
+	if (whoami) {
+		fputs(whoami, stderr);
+		fputs(": ", stderr);
+	}
+	if (code) {
+		fputs(error_message(code), stderr);
+		fputs(" ", stderr);
+	}
+	if (fmt) {
+		vfprintf(stderr, fmt, ap);
+	}
+	/* should do this only on a tty in raw mode */
+	putc('\r', stderr);
+	putc('\n', stderr);
+	fflush(stderr);
+
+#endif
+}
+
+void KRB5_CALLCONV com_err_va(const char *whoami,
+			      errcode_t code,
+			      const char *fmt,
+			      va_list ap)
+{
+    int err;
+    et_old_error_hook_func p;
+
+    err = com_err_finish_init();
+    if (err)
+	goto best_try;
+    err = k5_mutex_lock(&com_err_hook_lock);
+    if (err)
+	goto best_try;
+    p = com_err_hook ? com_err_hook : default_com_err_proc;
+    (*p)(whoami, code, fmt, ap);
+    k5_mutex_unlock(&com_err_hook_lock);
+    return;
+
+best_try:
+    /* Yikes.  Our library initialization failed or we couldn't lock
+       the lock we want.  We could be in trouble.  Gosh, we should
+       probably print an error message.  Oh, wait.  That's what we're
+       trying to do.  In fact, if we're losing on initialization here,
+       there's a good chance it has to do with failed initialization
+       of the caller.  */
+    if (!com_err_hook)
+	default_com_err_proc(whoami, code, fmt, ap);
+    else
+	(com_err_hook)(whoami, code, fmt, ap);
+    assert(err == 0);
+    abort();
+}
+
+
+void KRB5_CALLCONV_C com_err(const char *whoami,
+			     errcode_t code,
+			     const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	com_err_va(whoami, code, fmt, ap);
+	va_end(ap);
+}
+
+/* Make a separate function because the assert invocations below
+   use the macro expansion on some platforms, which may be insanely
+   long and incomprehensible.  */
+static int com_err_lock_hook_handle(void)
+{
+    return k5_mutex_lock(&com_err_hook_lock);
+}
+
+et_old_error_hook_func set_com_err_hook (et_old_error_hook_func new_proc)
+{
+	et_old_error_hook_func x;
+
+	/* Broken initialization?  What can we do?  */
+	assert(com_err_finish_init() == 0);
+	assert(com_err_lock_hook_handle() == 0);
+	x = com_err_hook;
+	com_err_hook = new_proc;
+	k5_mutex_unlock(&com_err_hook_lock);
+	return x;
+}
+
+et_old_error_hook_func reset_com_err_hook ()
+{
+	et_old_error_hook_func x;
+
+	/* Broken initialization?  What can we do?  */
+	assert(com_err_finish_init() == 0);
+	assert(com_err_lock_hook_handle() == 0);
+	x = com_err_hook;
+	com_err_hook = NULL;
+	k5_mutex_unlock(&com_err_hook_lock);
+	return x;
+}
diff --git a/krb5-1-6/src/util/et/com_err.h b/krb5-1-6/src/util/et/com_err.h
new file mode 100644
index 000000000..042a9bd45
--- /dev/null
+++ b/krb5-1-6/src/util/et/com_err.h
@@ -0,0 +1,72 @@
+/*
+ * Header file for common error description library.
+ *
+ * Copyright 1988, Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * Copyright 1995 by Cygnus Support.
+ *
+ * For copyright and distribution info, see the documentation supplied
+ * with this package.
+ */
+
+#ifndef __COM_ERR_H
+
+#if defined(_WIN32)
+#include <win-mac.h>
+#endif
+
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+#include <stdarg.h>
+
+typedef long errcode_t;
+typedef void (*et_old_error_hook_func) (const char *, errcode_t,
+					const char *, va_list ap);
+	
+struct error_table {
+	/*@shared@*/ char const * const * msgs;
+        long base;
+	unsigned int n_msgs;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public interfaces */
+extern void KRB5_CALLCONV_C com_err
+	(const char *, errcode_t, const char *, ...);
+extern void KRB5_CALLCONV com_err_va
+	(const char *whoami, errcode_t code, const char *fmt,
+	 va_list ap);
+extern /*@observer@*//*@dependent@*/ const char * KRB5_CALLCONV error_message
+	(errcode_t)
+       /*@modifies internalState@*/;
+extern errcode_t KRB5_CALLCONV add_error_table
+	(/*@dependent@*/ const struct error_table *)
+       /*@modifies internalState@*/;
+extern errcode_t KRB5_CALLCONV remove_error_table
+	(const struct error_table *)
+       /*@modifies internalState@*/;
+
+#if !defined(_WIN32)
+/*
+ * The display routine should be application specific.  A global hook,
+ * may cause inappropriate display procedures to be called between
+ * applications under non-Unix environments.
+ */
+
+extern et_old_error_hook_func set_com_err_hook (et_old_error_hook_func);
+extern et_old_error_hook_func reset_com_err_hook (void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define __COM_ERR_H
+#endif /* ! defined(__COM_ERR_H) */
diff --git a/krb5-1-6/src/util/et/com_err.texinfo b/krb5-1-6/src/util/et/com_err.texinfo
new file mode 100644
index 000000000..918f15276
--- /dev/null
+++ b/krb5-1-6/src/util/et/com_err.texinfo
@@ -0,0 +1,555 @@
+\input texinfo @c -*-texinfo-*-
+
+@c util/et/com_err.texinfo
+
+@c Note that although this source file is in texinfo format (more
+@c or less), it is not yet suitable for turning into an ``info''
+@c file.  Sorry, maybe next time.
+@c
+@c In order to produce hardcopy documentation from a texinfo file,
+@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
+@c provided in this distribution.  (texinfo.tex is from the Free
+@c Software Foundation, and is under different copyright restrictions
+@c from the rest of this package.)
+
+@ifinfo
+@barfo
+@end ifinfo
+
+@iftex
+@tolerance 10000
+
+@c Mutate section headers...
+@begingroup
+  @catcode#=6
+  @gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
+@endgroup
+@end iftex
+
+@setfilename com_err
+@settitle A Common Error Description Library for UNIX
+
+@ifinfo
+This file documents the use of the Common Error Description library.
+
+Copyright (C) 1987, 1988 Student Information Processing Board of the
+Massachusetts Institute of Technology.
+
+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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.  Furthermore if you modify this
+software you must label your software as modified software and not
+distribute it in such a fashion that it might be confused with the
+original M.I.T. software.  M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose.  It is provided "as is" without express or implied warranty.
+
+Note that the file texinfo.tex, provided with this distribution, is from
+the Free Software Foundation, and is under different copyright restrictions
+from the remainder of this package.
+
+@end ifinfo
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+
+@setchapternewpage odd
+
+@titlepage
+@center @titlefont{A Common Error Description}
+@center @titlefont{Library for UNIX}
+@sp 2
+@center Ken Raeburn
+@center Bill Sommerfeld
+@sp 1
+@center MIT Student Information Processing Board
+@sp 3
+@center last updated 1 January 1989
+@center for version 1.2
+@center ***DRAFT COPY ONLY***
+
+@vskip 2in
+
+@center @b{Abstract}
+
+UNIX has always had a clean and simple system call interface, with a
+standard set of error codes passed between the kernel and user
+programs.  Unfortunately, the same cannot be said of many of the
+libraries layered on top of the primitives provided by the kernel.
+Typically, each one has used a different style of indicating errors to
+their callers, leading to a total hodgepodge of error handling, and
+considerable amounts of work for the programmer.  This paper describes
+a library and associated utilities which allows a more uniform way for
+libraries to return errors to their callers, and for programs to
+describe errors and exceptional conditions to their users.
+
+@page
+@vskip 0pt plus 1filll
+
+Copyright @copyright{} 1987, 1988 by the Student Information Processing
+Board of the Massachusetts Institute of Technology.
+
+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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.  M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose.  It is provided "as is" without express or implied warranty.
+
+Note that the file texinfo.tex, provided with this distribution, is from
+the Free Software Foundation, and is under different copyright restrictions
+from the remainder of this package.
+
+@end titlepage
+
+@ifinfo
+@c should put a menu here someday....
+@end ifinfo
+
+@page
+
+@section Why com_err?
+
+In building application software packages, a programmer often has to
+deal with a number of libraries, each of which can use a different
+error-reporting mechanism.  Sometimes one of two values is returned,
+indicating simply SUCCESS or FAILURE, with no description of errors
+encountered.  Sometimes it is an index into a table of text strings,
+where the name of the table used is dependent on the library being
+used when the error is generated; since each table starts numbering at
+0 or 1, additional information as to the source of the error code is
+needed to determine which table to look at.  Sometimes no text messages are
+supplied at all, and the programmer must supply them at any point at which
+he may wish to report error conditions.
+Often, a global variable is assigned some value describing the error, but
+the programmer has to know in each case whether to look at @code{errno},
+@code{h_errno}, the return value from @code{hes_err()}, or whatever other
+variables or routines are specified.
+And what happens if something
+in the procedure of
+examining or reporting the error changes the same variable?
+
+The package we have developed is an attempt to present a common
+error-handling mechanism to manipulate the most common form of error code
+in a fashion that does not have the problems listed above.
+
+A list of up to 256 text messages is supplied to a translator we have
+written, along with the three- to four-character ``name'' of the error
+table.  The library using this error table need only call a routine
+generated from this error-table source to make the table ``known'' to the
+com_err library, and any error code the library generates can be converted
+to the corresponding error message.  There is also a default format for
+error codes accidentally returned before making the table known, which is
+of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
+of the table.
+
+@section Error codes
+
+Error codes themselves are 32 bit (signed) integers, of which the high
+order 24 bits are an identifier of which error table the error code is
+from, and the low order 8 bits are a sequential error number within
+the table.  An error code may thus be easily decomposed into its component
+parts.  Only the lowest 32 bits of an error code are considered significant
+on systems which support wider values.
+
+Error table 0 is defined to match the UNIX system call error table
+(@code{sys_errlist}); this allows @code{errno} values to be used directly
+in the library (assuming that @code{errno} is of a type with the same width
+as @t{long}).  Other error table numbers are formed by compacting together
+the first four characters of the error table name.  The mapping between
+characters in the name and numeric values in the error code are defined in
+a system-independent fashion, so that two systems that can pass integral
+values between them can reliably pass error codes without loss of meaning;
+this should work even if the character sets used are not the same.
+(However, if this is to be done, error table 0 should be avoided, since the
+local system call error tables may differ.)
+
+Any variable which is to contain an error code should be declared @t{long}.
+The draft proposed American National Standard for C (as of May, 1988)
+requires that @t{long} variables be at least 32 bits; any system which does
+not support 32-bit @t{long} values cannot make use of this package (nor
+much other software that assumes an ANSI-C environment base) without
+significant effort.
+
+@section Error table source file
+
+The error table source file begins with the declaration of the table name,
+as
+
+@example
+error_table @var{tablename}
+@end example
+
+Individual error codes are
+specified with
+
+@example
+error_code @var{ERROR_NAME}, @var{"text message"}
+@end example
+
+where @samp{ec} can also be used as a short form of @samp{error_code}.  To
+indicate the end of the table, use @samp{end}.  Thus, a (short) sample
+error table might be:
+
+@example
+
+        error_table     dsc
+
+        error_code      DSC_DUP_MTG_NAME,
+                        "Meeting already exists"
+
+        ec              DSC_BAD_PATH,
+                        "A bad meeting pathname was given"
+
+        ec              DSC_BAD_MODES,
+                        "Invalid mode for this access control list"
+
+        end
+
+@end example
+
+@section The error-table compiler
+
+The error table compiler is named @code{compile_et}.  It takes one
+argument, the pathname of a file (ending in @samp{.et}, e.g.,
+@samp{dsc_err.et}) containing an error table source file.  It parses the
+error table, and generates two output files -- a C header file
+(@samp{discuss_err.h}) which contains definitions of the numerical values
+of the error codes defined in the error table, and a C source file which
+should be compiled and linked with the executable.  The header file must be
+included in the source of a module which wishes to reference the error
+codes defined; the object module generated from the C code may be linked in
+to a program which wishes to use the printed forms of the error codes.
+
+This translator accepts a @kbd{-language @var{lang}} argument, which
+determines for which language (or language variant) the output should be
+written.  At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
+and @kbd{K&R-C}, and some abbreviated forms of each.  Eventually, this will
+be extended to include some support for C++.  The default is currently
+@kbd{K&R-C}, though the generated sources will have ANSI-C code
+conditionalized on the symbol @t{__STDC__}.
+
+@section Run-time support routines
+
+Any source file which uses the routines supplied with or produced by the
+com_err package should include the header file @file{<com_err.h>}.  It
+contains declarations and definitions which may be needed on some systems.
+(Some functions cannot be referenced properly without the return type
+declarations in this file.  Some functions may work properly on most
+architectures even without the header file, but relying on this is not
+recommended.)
+
+The run-time support routines and variables provided via this package
+include the following:
+
+@example
+void initialize_@var{xxxx}_error_table (void);
+@end example
+
+One of these routines is built by the error compiler for each error table.
+It makes the @var{xxxx} error table ``known'' to the error reporting
+system.  By convention, this routine should be called in the initialization
+routine of the @var{xxxx} library.  If the library has no initialization
+routine, some combination of routines which form the core of the library
+should ensure that this routine is called.  It is not advised to leave it
+the caller to make this call.
+
+There is no harm in calling this routine more than once.
+
+@example
+#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
+@end example
+
+This symbol contains the value of the first error code entry in the
+specified table.
+This rarely needs be used by the
+programmer.
+
+@example
+const char *error_message (long code);
+@end example
+
+This routine returns the character string error message associated
+with @code{code}; if this is associated with an unknown error table, or
+if the code is associated with a known error table but the code is not
+in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
+returned, where @var{xxxx} is the error table name produced by
+reversing the compaction performed on the error table number implied
+by that error code, and @var{nn} is the offset from that base value.
+
+Although this routine is available for use when needed, its use should be
+left to circumstances which render @code{com_err} (below) unusable.
+
+@example
+void com_err (const char *whoami,  /* module reporting error */
+              long code,           /* error code */
+              const char *format,  /* format for additional detail */
+              ...);                /*  (extra parameters) */
+@end example
+
+This routine provides an alternate way to print error messages to
+standard error; it allows the error message to be passed in as a
+parameter, rather than in an external variable.  @emph{Provide grammatical
+context for ``message.''}
+
+If @var{format} is @code{(char *)NULL}, the formatted message will not be
+printed.  @var{format} may not be omitted.
+
+@example
+#include <stdarg.h>
+
+void com_err_va (const char *whoami,
+                 long code,
+                 const char *format,
+                 va_list args);
+@end example
+
+This routine provides an interface, equivalent to @code{com_err} above,
+which may be used by higher-level variadic functions (functions which
+accept variable numbers of arguments).
+
+@example
+#include <stdarg.h>
+
+void (*set_com_err_hook (void (*proc) ())) ();
+
+void (*@var{proc}) (const char *whoami, long code, va_list args);
+
+void reset_com_err_hook ();
+@end example
+
+These two routines allow a routine to be dynamically substituted for
+@samp{com_err}.  After @samp{set_com_err_hook} has been called,
+calls to @samp{com_err} will turn into calls to the new hook routine.
+@samp{reset_com_err_hook} turns off this hook.  This may intended to
+be used in daemons (to use a routine which calls @var{syslog(3)}), or
+in a window system application (which could pop up a dialogue box).
+
+If a program is to be used in an environment in which simply printing
+messages to the @code{stderr} stream would be inappropriate (such as in a
+daemon program which runs without a terminal attached),
+@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
+The following is an example of an error handler which uses @var{syslog(3)}
+as supplied in BSD 4.3:
+
+@example
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+/* extern openlog (const char * name, int logopt, int facility); */
+/* extern syslog (int priority, char * message, ...); */
+
+void hook (const char * whoami, long code,
+           const char * format, va_list args)
+@{
+    char buffer[BUFSIZ];
+    static int initialized = 0;
+    if (!initialized) @{
+        openlog (whoami,
+                 LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
+                 LOG_DAEMON);
+        initialized = 1;
+    @}
+    vsprintf (buffer, format, args);
+    syslog (LOG_ERR, "%s %s", error_message (code), buffer);
+@}
+@end example
+
+After making the call
+@code{set_com_err_hook (hook);},
+any calls to @code{com_err} will result in messages being sent to the
+@var{syslogd} daemon for logging.
+The name of the program, @samp{whoami}, is supplied to the
+@samp{openlog()} call, and the message is formatted into a buffer and
+passed to @code{syslog}.
+
+Note that since the extra arguments to @code{com_err} are passed by
+reference via the @code{va_list} value @code{args}, the hook routine may
+place any form of interpretation on them, including ignoring them.  For
+consistency, @code{printf}-style interpretation is suggested, via
+@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
+the ANSI C library).
+
+@section Coding Conventions
+
+The following conventions are just some general stylistic conventions
+to follow when writing robust libraries and programs.  Conventions
+similar to this are generally followed inside the UNIX kernel and most
+routines in the Multics operating system.  In general, a routine
+either succeeds (returning a zero error code, and doing some side
+effects in the process), or it fails, doing minimal side effects; in
+any event, any invariant which the library assumes must be maintained.
+
+In general, it is not in the domain of non user-interface library
+routines to write error messages to the user's terminal, or halt the
+process.  Such forms of ``error handling'' should be reserved for
+failures of internal invariants and consistancy checks only, as it
+provides the user of the library no way to clean up for himself in the
+event of total failure.
+
+Library routines which can fail should be set up to return an error
+code.  This should usually be done as the return value of the
+function; if this is not acceptable, the routine should return a
+``null'' value, and put the error code into a parameter passed by
+reference.
+
+Routines which use the first style of interface can be used from
+user-interface levels of a program as follows:
+
+@example
+@{
+    if ((code = initialize_world(getuid(), random())) != 0) @{
+        com_err("demo", code,
+                "when trying to initialize world");
+        exit(1);
+    @}
+    if ((database = open_database("my_secrets", &code))==NULL) @{
+        com_err("demo", code,
+                "while opening my_secrets");
+        exit(1);
+    @}
+@}
+@end example
+
+A caller which fails to check the return status is in error.  It is
+possible to look for code which ignores error returns by using lint;
+look for error messages of the form ``foobar returns value which is
+sometimes ignored'' or ``foobar returns value which is always
+ignored.''
+
+Since libraries may be built out of other libraries, it is often necessary
+for the success of one routine to depend on another.  When a lower level
+routine returns an error code, the middle level routine has a few possible
+options.  It can simply return the error code to its caller after doing
+some form of cleanup, it can substitute one of its own, or it can take
+corrective action of its own and continue normally.  For instance, a
+library routine which makes a ``connect'' system call to make a network
+connection may reflect the system error code @code{ECONNREFUSED}
+(Connection refused) to its caller, or it may return a ``server not
+available, try again later,'' or it may try a different server.
+
+Cleanup which is typically necessary may include, but not be limited
+to, freeing allocated memory which will not be needed any more,
+unlocking concurrancy locks, dropping reference counts, closing file
+descriptors, or otherwise undoing anything which the procedure did up
+to this point.  When there are a lot of things which can go wrong, it
+is generally good to write one block of error-handling code which is
+branched to, using a goto, in the event of failure.  A common source
+of errors in UNIX programs is failing to close file descriptors on
+error returns; this leaves a number of ``zombied'' file descriptors
+open, which eventually causes the process to run out of file
+descriptors and fall over.
+
+@example
+@{
+    FILE *f1=NULL, *f2=NULL, *f3=NULL;
+    int status = 0;
+
+    if ( (f1 = fopen(FILE1, "r")) == NULL) @{
+        status = errno;
+        goto error;
+    @}
+
+    /*
+     * Crunch for a while
+     */
+
+    if ( (f2 = fopen(FILE2, "w")) == NULL) @{
+        status = errno;
+        goto error;
+    @}
+
+    if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
+        status = errno;
+            goto error;
+    @}
+
+    /*
+     * Do more processing.
+     */
+    fclose(f1);
+    fclose(f2);
+    fclose(f3);
+    return 0;
+
+error:
+    if (f1) fclose(f1);
+    if (f2) fclose(f2);
+    if (f3) fclose(f3);
+    return status;
+@}
+@end example
+
+@section Building and Installation
+
+The distribution of this package will probably be done as a compressed
+``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
+Retrieve @samp{pub/com_err.tar.Z} and extract the contents.  A subdirectory
+@t{profiled} should be created to hold objects compiled for profiling.
+Running ``make all'' should then be sufficient to build the library and
+error-table compiler.  The files @samp{libcom_err.a},
+@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
+installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
+installed as manual pages.
+
+Potential problems:
+
+@itemize @bullet
+
+@item Use of @code{strcasecmp}, a routine provided in BSD for
+case-insensitive string comparisons.  If an equivalent routine is
+available, you can modify @code{CFLAGS} in the makefile to define
+@code{strcasecmp} to the name of that routine.
+
+@item Compilers that defined @code{__STDC__} without providing the header
+file @code{<stdarg.h>}.  One such example is Metaware's High ``C''
+compiler, as provided at Project Athena on the IBM RT/PC workstation; if
+@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
+available, and therefore @code{<varargs.h>} must be used.  If the symbol
+@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
+be used.
+
+@item If your linker rejects symbols that are simultaneously defined in two
+library files, edit @samp{Makefile} to remove @samp{perror.c} from the
+library.  This file contains a version of @var{perror(3)} which calls
+@code{com_err} instead of calling @code{write} directly.
+
+@end itemize
+
+As I do not have access to non-BSD systems, there are probably
+bugs present that may interfere with building or using this package on
+other systems.  If they are reported to me, they can probably be fixed for
+the next version.
+
+@section Bug Reports
+
+Please send any comments or bug reports to the principal author: Ken
+Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
+
+@section Acknowledgements
+
+I would like to thank: Bill Sommerfeld, for his help with some of this
+documentation, and catching some of the bugs the first time around;
+Honeywell Information Systems, for not killing off the @emph{Multics}
+operating system before I had an opportunity to use it; Honeywell's
+customers, who persuaded them not to do so, for a while; Ted Anderson of
+CMU, for catching some problems before version 1.2 left the nest; Stan
+Zanarotti and several others of MIT's Student Information Processing Board,
+for getting us started with ``discuss,'' for which this package was
+originally written; and everyone I've talked into --- I mean, asked to read
+this document and the ``man'' pages.
+
+@bye
diff --git a/krb5-1-6/src/util/et/compile_et.1 b/krb5-1-6/src/util/et/compile_et.1
new file mode 100644
index 000000000..a082bca46
--- /dev/null
+++ b/krb5-1-6/src/util/et/compile_et.1
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1988 Massachusetts Institute of Technology,
+.\" Student Information Processing Board.  All rights reserved.
+.\"
+.\" util/et/compile_et.1
+.\"
+.TH COMPILE_ET 1 "22 Nov 1988" SIPB
+.SH NAME
+compile_et \- error table compiler
+.SH SYNOPSIS
+.B compile_et
+file
+.SH DESCRIPTION
+.B Compile_et
+converts a table listing error-code names and associated messages into
+a C source file suitable for use with the
+.IR com_err (3)
+library.
+
+The source file name must end with a suffix of ``.et''; the file
+consists of a declaration supplying the name (up to four characters
+long) of the error-code table:
+
+.B error_table
+.I name
+
+followed by up to 256 entries of the form:
+
+.B error_code
+.I name,
+"
+.I string
+"
+
+and a final
+
+.B end
+
+to indicate the end of the table.
+
+The name of the table is used to construct the name of a subroutine
+.I initialize_XXXX_error_table
+which must be called in order for the
+.I com_err
+library to recognize the error table.
+
+The various error codes defined are assigned sequentially increasing
+numbers (starting with a large number computed as a hash function of
+the name of the table); thus for compatibility it is suggested that
+new codes be added only to the end of an existing table, and that no
+codes be removed from tables.
+
+The names defined in the table are placed into a C header file with
+preprocessor directives defining them as integer constants of up to
+32 bits in magnitude.
+
+A C source file is also generated which should be compiled and linked
+with the object files which reference these error codes; it contains
+the text of the messages and the initialization subroutine.  Both C
+files have names derived from that of the original source file, with
+the ``.et'' suffix replaced by ``.c'' and ``.h''.
+
+A ``#'' in the source file is treated as a comment character, and all
+remaining text to the end of the source line will be ignored.
+
+.SH BUGS
+
+Since
+.B compile_et
+uses a very simple parser based on
+.IR yacc (1),
+its error recovery leaves much to be desired.
+
+.\" .IR for manual entries
+.\" .PP for paragraph breaks
+
+.SH "SEE ALSO"
+com_err (3).
+
+Ken Raeburn, "A Common Error Description Library for UNIX".
diff --git a/krb5-1-6/src/util/et/compile_et.c b/krb5-1-6/src/util/et/compile_et.c
new file mode 100644
index 000000000..dfaad5f57
--- /dev/null
+++ b/krb5-1-6/src/util/et/compile_et.c
@@ -0,0 +1,348 @@
+/*
+ *
+ * Copyright 1986, 1987, 1988
+ * by MIT Student Information Processing Board.
+ *
+ * For copyright info, see "mit-sipb-copyright.h".
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <string.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "mit-sipb-copyright.h"
+#include "compiler.h"
+
+#ifndef lint
+static const char copyright[] =
+    "Copyright 1987,1988 by MIT Student Information Processing Board";
+#endif
+
+extern char *gensym();
+extern char *current_token;
+extern int table_number, current;
+char buffer[BUFSIZ];
+char *table_name = (char *)NULL;
+FILE *hfile, *cfile;
+
+/* lex stuff */
+extern FILE *yyin;
+extern int yylineno;
+
+char * xmalloc (size) unsigned int size; {
+    char * p = malloc (size);
+    if (!p) {
+	perror (whoami);
+	exit (1);
+    }
+    return p;
+}
+
+static int check_arg (str_list, arg) char const *const *str_list, *arg; {
+    while (*str_list)
+	if (!strcmp(arg, *str_list++))
+	    return 1;
+    return 0;
+}
+
+static const char *const debug_args[] = {
+    "d",
+    "debug",
+    0,
+};
+
+static const char *const lang_args[] = {
+    "lang",
+    "language",
+    0,
+};
+
+static const char *const language_names[] = {
+    "C",
+    "K&R C",
+    "C++",
+    0,
+};
+
+static const char * const c_src_prolog[] = {
+    "static const char * const text[] = {\n",
+    0,
+};
+
+static const char * const krc_src_prolog[] = {
+    "#if defined(__STDC__) || defined(_WIN32)\n",
+    "#define NOARGS void\n",
+    "#else\n",
+    "#define NOARGS\n",
+    "#define const\n",
+    "#endif\n\n",
+    "static const char * const text[] = {\n",
+    0,
+};
+
+static const char *const struct_def[] = {
+    "struct error_table {\n",
+    "    char const * const * msgs;\n",
+    "    long base;\n",
+    "    int n_msgs;\n",
+    "};\n",
+    "struct et_list {\n",
+    "    struct et_list *next;\n",
+    "    const struct error_table * table;\n",
+    "};\n",
+    "extern struct et_list *_et_list;\n",
+    "\n", 0,
+};
+
+static const char warning[] =
+    "/*\n * %s:\n * This file is automatically generated; please do not edit it.\n */\n";
+
+/* pathnames */
+char c_file[MAXPATHLEN];	/* output file */
+char h_file[MAXPATHLEN];	/* output */
+
+static void usage () {
+    fprintf (stderr, "%s: usage: %s ERROR_TABLE\n",
+	     whoami, whoami);
+    exit (1);
+}
+
+static void dup_err (type, one, two) char const *type, *one, *two; {
+    fprintf (stderr, "%s: multiple %s specified: `%s' and `%s'\n",
+	     whoami, type, one, two);
+    usage ();
+}
+
+int main (argc, argv) int argc; char **argv; {
+    char *p, *ename;
+    int len;
+    char const * const *cpp;
+    int got_language = 0;
+
+    /* argument parsing */
+    debug = 0;
+    filename = 0;
+    whoami = argv[0];
+    p = strrchr (whoami, '/');
+    if (p)
+	whoami = p+1;
+    while (argv++, --argc) {
+	char *arg = *argv;
+	if (arg[0] != '-') {
+	    if (filename)
+		dup_err ("filenames", filename, arg);
+	    filename = arg;
+	}
+	else {
+	    arg++;
+	    if (check_arg (debug_args, arg))
+		debug++;
+	    else if (check_arg (lang_args, arg)) {
+		got_language++;
+		arg = *++argv, argc--;
+		if (!arg)
+		    usage ();
+		if (language)
+		    dup_err ("languanges", language_names[(int)language], arg);
+#define check_lang(x,v) else if (!strcasecmp(arg,x)) language = v
+		check_lang ("c", lang_C);
+		check_lang ("ansi_c", lang_C);
+		check_lang ("ansi-c", lang_C);
+		check_lang ("krc", lang_KRC);
+		check_lang ("kr_c", lang_KRC);
+		check_lang ("kr-c", lang_KRC);
+		check_lang ("k&r-c", lang_KRC);
+		check_lang ("k&r_c", lang_KRC);
+		check_lang ("c++", lang_CPP);
+		check_lang ("cplusplus", lang_CPP);
+		check_lang ("c-plus-plus", lang_CPP);
+#undef check_lang
+		else {
+		    fprintf (stderr, "%s: unknown language name `%s'\n",
+			     whoami, arg);
+		    fprintf (stderr, "\tpick one of: C K&R-C\n");
+		    exit (1);
+		}
+	    }
+	    else {
+		fprintf (stderr, "%s: unknown control argument -`%s'\n",
+			 whoami, arg);
+		usage ();
+	    }
+	}
+    }
+    if (!filename)
+	usage ();
+    if (!got_language)
+	language = lang_KRC;
+    else if (language == lang_CPP) {
+	fprintf (stderr, "%s: Sorry, C++ support is not yet finished.\n",
+		 whoami);
+	exit (1);
+    }
+
+    p = xmalloc (strlen (filename) + 5);
+    strcpy (p, filename);
+    filename = p;
+    p = strrchr(filename, '/');
+    if (p == (char *)NULL)
+	p = filename;
+    else
+	p++;
+    ename = p;
+    len = strlen (ename);
+    p += len - 3;
+    if (strcmp (p, ".et"))
+	p += 3;
+    *p++ = '.';
+    /* now p points to where "et" suffix should start */
+    /* generate new filenames */
+    strcpy (p, "c");
+    strcpy (c_file, ename);
+    *p = 'h';
+    strcpy (h_file, ename);
+    strcpy (p, "et");
+
+    yyin = fopen(filename, "r");
+    if (!yyin) {
+	perror(filename);
+	exit(1);
+    }
+
+    hfile = fopen(h_file, "w");
+    if (hfile == (FILE *)NULL) {
+	perror(h_file);
+	exit(1);
+    }
+    fprintf (hfile, warning, h_file);
+
+    cfile = fopen(c_file, "w");
+    if (cfile == (FILE *)NULL) {
+	perror(c_file);
+	exit(1);
+    }
+    fprintf (cfile, warning, c_file);
+
+    /* prologue */
+    if (language == lang_C)
+	cpp = c_src_prolog;
+    else if (language == lang_KRC)
+	cpp = krc_src_prolog;
+    else
+	abort ();
+    while (*cpp)
+	fputs (*cpp++, cfile);
+
+    /* parse it */
+    yyparse();
+    fclose(yyin);		/* bye bye input file */
+
+    fputs ("    0\n};\n\n", cfile);
+    for (cpp = struct_def; *cpp; cpp++)
+	fputs (*cpp, cfile);
+    fprintf(cfile,
+	    "const struct error_table et_%s_error_table = { text, %ldL, %d };\n\n",
+	    table_name, table_number, current);
+    fputs("static struct et_list link = { 0, 0 };\n\n",
+	  cfile);
+    fprintf(cfile, "void initialize_%s_error_table (%s) {\n",
+	    table_name, (language == lang_C) ? "void" : "NOARGS");
+    fputs("    if (!link.table) {\n", cfile);
+    fputs("        link.next = _et_list;\n", cfile);
+    fprintf(cfile, "        link.table = &et_%s_error_table;\n", table_name);
+    fputs("        _et_list = &link;\n", cfile);
+    fputs("    }\n", cfile);
+    fputs("}\n", cfile);
+    fclose(cfile);
+
+    fprintf (hfile, "extern void initialize_%s_error_table ();\n",
+	     table_name);
+    fprintf (hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n",
+	     table_name, table_number);
+    /* compatibility... */
+    fprintf (hfile, "\n/* for compatibility with older versions... */\n");
+    fprintf (hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
+	     table_name, table_name);
+    fprintf (hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", table_name,
+	     table_name);
+    fclose(hfile);		/* bye bye include file */
+
+    return 0;
+}
+
+int yyerror(s) char *s; {
+    fputs(s, stderr);
+#ifdef NO_YYLINENO
+    fprintf(stderr, "\nLast token was '%s'\n", current_token);
+#else
+    fprintf(stderr, "\nLine number %d; last token was '%s'\n",
+	    yylineno, current_token);
+#endif
+}
+
+#ifdef NEED_STRCASECMP
+/* Need strcasecmp for this machine */
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/* based on @(#)strcasecmp.c	1.3 (Berkeley) 8/3/87 */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static char charmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+strcasecmp(s1, s2)
+	register char *s1, *s2;
+{
+	register char *cm = charmap;
+
+	while (cm[*s1] == cm[*s2++])
+		if (*s1++ == '\0')
+			return(0);
+	return(cm[*s1] - cm[*--s2]);
+}
+
+#endif
diff --git a/krb5-1-6/src/util/et/compile_et.sh b/krb5-1-6/src/util/et/compile_et.sh
new file mode 100755
index 000000000..adb0be666
--- /dev/null
+++ b/krb5-1-6/src/util/et/compile_et.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+#
+AWK=@AWK@
+DIR=@DIR@
+
+usage="usage: $0 [ -d scriptDir ] inputfile.et"
+
+if [ "$1" = "-d" ]; then
+    if [ $# -lt 3 ]; then
+	echo $usage 1>&2 ; exit 1
+    fi
+    DIR=$2 ; shift ; shift
+fi
+if [ $# -ne 1 ]; then
+    echo $usage 1>&2 ; exit 1
+fi
+
+ROOT=`echo $1 | sed -e s/.et$//`
+BASE=`echo $ROOT | sed -e 's;.*/;;'`
+
+set -ex
+$AWK -f ${DIR}/et_h.awk outfile=${BASE}.h $ROOT.et
+$AWK -f ${DIR}/et_c.awk outfile=${BASE}.c $ROOT.et
diff --git a/krb5-1-6/src/util/et/compiler.h b/krb5-1-6/src/util/et/compiler.h
new file mode 100644
index 000000000..3e23f1296
--- /dev/null
+++ b/krb5-1-6/src/util/et/compiler.h
@@ -0,0 +1,14 @@
+/*
+ * definitions common to the source files of the error table compiler
+ */
+
+enum lang {
+    lang_C,			/* ANSI C (default) */
+    lang_KRC,			/* C: ANSI + K&R */
+    lang_CPP			/* C++ */
+};
+
+int debug;			/* dump debugging info? */
+char *filename;			/* error table source */
+enum lang language;
+const char *whoami;
diff --git a/krb5-1-6/src/util/et/config_script b/krb5-1-6/src/util/et/config_script
new file mode 100755
index 000000000..ee3bb2702
--- /dev/null
+++ b/krb5-1-6/src/util/et/config_script
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# This program takes a shell script and configures for the following
+# variables:	@DIR@
+#		@AWK@
+#		@SED@
+#
+# Usage: config_script <filename> [<dir>] [<awk>] [<sed>]
+#
+
+FILE=$1
+DIR=$2
+AWK=$3
+SED=$4
+
+if test "${AWK}x" = "x" ; then
+	AWK=awk
+fi
+if test "${SED}x" = "x" ; then
+	SED=sed
+fi
+sed -e "s;@DIR@;${DIR};" -e "s;@AWK@;${AWK};" -e "s;@SED@;${SED};" $FILE
diff --git a/krb5-1-6/src/util/et/error_message.c b/krb5-1-6/src/util/et/error_message.c
new file mode 100644
index 000000000..897b7a24c
--- /dev/null
+++ b/krb5-1-6/src/util/et/error_message.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright 1997,2000,2001,2004 by Massachusetts Institute of Technology
+ * 
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include "autoconf.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include "com_err.h"
+#include "error_table.h"
+#include "k5-platform.h"
+
+#if !defined(HAVE_STRERROR) && !defined(SYS_ERRLIST_DECLARED)
+extern char const * const sys_errlist[];
+extern const int sys_nerr;
+#endif
+
+/*@null@*/ static struct et_list * _et_list = (struct et_list *) NULL;
+/*@null@*//*@only@*/static struct dynamic_et_list * et_list_dynamic;
+static k5_mutex_t et_list_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+static int terminated = 0;	/* for debugging shlib fini sequence errors */
+
+MAKE_INIT_FUNCTION(com_err_initialize);
+MAKE_FINI_FUNCTION(com_err_terminate);
+
+int com_err_initialize(void)
+{
+    int err;
+#ifdef SHOW_INITFINI_FUNCS
+    printf("com_err_initialize\n");
+#endif
+    terminated = 0;
+    err = k5_mutex_finish_init(&et_list_lock);
+    if (err)
+	return err;
+    err = k5_mutex_finish_init(&com_err_hook_lock);
+    if (err)
+	return err;
+    err = k5_key_register(K5_KEY_COM_ERR, free);
+    if (err)
+	return err;
+    return 0;
+}
+
+void com_err_terminate(void)
+{
+    struct dynamic_et_list *e, *enext;
+    if (! INITIALIZER_RAN(com_err_initialize) || PROGRAM_EXITING()) {
+#ifdef SHOW_INITFINI_FUNCS
+	printf("com_err_terminate: skipping\n");
+#endif
+	return;
+    }
+#ifdef SHOW_INITFINI_FUNCS
+    printf("com_err_terminate\n");
+#endif
+    k5_key_delete(K5_KEY_COM_ERR);
+    k5_mutex_destroy(&com_err_hook_lock);
+    k5_mutex_lock(&et_list_lock);
+    for (e = et_list_dynamic; e; e = enext) {
+	enext = e->next;
+	free(e);
+    }
+    k5_mutex_unlock(&et_list_lock);
+    k5_mutex_destroy(&et_list_lock);
+    terminated = 1;
+}
+
+#ifndef DEBUG_TABLE_LIST
+#define dprintf(X)
+#else
+#define dprintf(X) printf X
+#endif
+
+static char *
+get_thread_buffer ()
+{
+    char *cp;
+    cp = k5_getspecific(K5_KEY_COM_ERR);
+    if (cp == NULL) {
+	cp = malloc(ET_EBUFSIZ);
+	if (cp == NULL) {
+	    return NULL;
+	}
+	if (k5_setspecific(K5_KEY_COM_ERR, cp) != 0) {
+	    free(cp);
+	    return NULL;
+	}
+    }
+    return cp;
+}
+
+const char * KRB5_CALLCONV
+error_message(long code)
+    /*@modifies internalState@*/
+{
+	unsigned long offset;
+	unsigned long l_offset;
+	struct et_list *et;
+	struct dynamic_et_list *det;
+	unsigned long table_num;
+	int started = 0;
+	unsigned int divisor = 100;
+	char *cp, *cp1;
+	const struct error_table *table;
+	int merr;
+
+	l_offset = (unsigned long)code & ((1<<ERRCODE_RANGE)-1);
+	offset = l_offset;
+	table_num = ((unsigned long)code - l_offset) & ERRCODE_MAX;
+	if (table_num == 0
+#ifdef __sgi
+	    /* Irix 6.5 uses a much bigger table than other UNIX
+	       systems I've looked at, but the table is sparse.  The
+	       sparse entries start around 500, but sys_nerr is only
+	       152.  */
+	    || (code > 0 && code <= 1600)
+#endif
+	    ) {
+		if (code == 0)
+			goto oops;
+
+		/* This could trip if int is 16 bits.  */
+		if ((unsigned long)(int)code != code)
+		    abort ();
+#ifdef HAVE_STRERROR_R
+		cp = get_thread_buffer();
+		if (cp && strerror_r((int) code, cp, ET_EBUFSIZ) == 0)
+		    return cp;
+#endif
+#ifdef HAVE_STRERROR
+		cp = strerror((int) code);
+		if (cp)
+			return cp;
+#elif defined HAVE_SYS_ERRLIST
+		if (offset < sys_nerr)
+			return(sys_errlist[offset]);
+#endif
+		goto oops;
+	}
+
+	if (CALL_INIT_FUNCTION(com_err_initialize))
+	    return 0;
+	merr = k5_mutex_lock(&et_list_lock);
+	if (merr)
+	    goto oops;
+	dprintf (("scanning static list for %x\n", table_num));
+	for (et = _et_list; et != NULL; et = et->next) {
+	    if (et->table == NULL)
+		continue;
+	    dprintf (("\t%x = %s\n", et->table->base & ERRCODE_MAX,
+		      et->table->msgs[0]));
+	    if ((et->table->base & ERRCODE_MAX) == table_num) {
+		table = et->table;
+		goto found;
+	    }
+	}
+	dprintf (("scanning dynamic list for %x\n", table_num));
+	for (det = et_list_dynamic; det != NULL; det = det->next) {
+	    dprintf (("\t%x = %s\n", det->table->base & ERRCODE_MAX,
+		      det->table->msgs[0]));
+	    if ((det->table->base & ERRCODE_MAX) == table_num) {
+		table = det->table;
+		goto found;
+	    }
+	}
+	goto no_table_found;
+
+ found:
+	k5_mutex_unlock(&et_list_lock);
+	dprintf (("found it!\n"));
+	/* This is the right table */
+
+	/* This could trip if int is 16 bits.  */
+	if ((unsigned long)(unsigned int)offset != offset)
+	    goto no_table_found;
+
+	if (table->n_msgs <= (unsigned int) offset)
+	    goto no_table_found;
+
+	return table->msgs[offset];
+
+ no_table_found:
+	k5_mutex_unlock(&et_list_lock);
+#if defined(_WIN32)
+	/*
+	 * WinSock errors exist in the 10000 and 11000 ranges
+	 * but might not appear if WinSock is not initialized
+	 */
+	if (code >= WSABASEERR && code < WSABASEERR + 1100) {
+		table_num = 0;
+		offset = code;
+		divisor = WSABASEERR;
+	}
+#endif
+#ifdef _WIN32	
+	{
+		LPVOID msgbuf;
+
+		if (! FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+				     NULL /* lpSource */,
+				     (DWORD) code,
+				     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+				     (LPTSTR) &msgbuf,
+				     (DWORD) 0 /*sizeof(buffer)*/,
+				     NULL /* va_list */ )) {
+			/*
+			 * WinSock errors exist in the 10000 and 11000 ranges
+			 * but might not appear if WinSock is not initialized
+			 */
+			if (code >= WSABASEERR && code < WSABASEERR + 1100) {
+			    table_num = 0;
+			    offset = code;
+			    divisor = 10000;
+			}
+
+			goto oops;
+		} else {
+			char *buffer;
+			cp = get_thread_buffer();
+			if (cp == NULL)
+			    return "Unknown error code";
+			buffer = cp;
+			strncpy(buffer, msgbuf, ET_EBUFSIZ);
+			buffer[ET_EBUFSIZ-1] = '\0';
+			cp = buffer + strlen(buffer) - 1;
+			if (*cp == '\n') *cp-- = '\0';
+			if (*cp == '\r') *cp-- = '\0';
+			if (*cp == '.') *cp-- = '\0';
+
+			LocalFree(msgbuf);
+			return buffer;
+		}
+	}
+#endif
+
+oops:
+
+#if TARGET_OS_MAC
+	{
+		/* ComErr doesn't know about this error, ask the system */
+		/* Of course there's no way to tell if it knew what error it got */
+		return (strerror (code));
+	}
+#endif
+
+	cp = get_thread_buffer();
+	if (cp == NULL)
+	    return "Unknown error code";
+	cp1 = cp;
+	strcpy(cp, "Unknown code ");
+	cp += sizeof("Unknown code ") - 1;
+	if (table_num != 0L) {
+		(void) error_table_name_r(table_num, cp);
+		while (*cp != '\0')
+			cp++;
+		*cp++ = ' ';
+	}
+	while (divisor > 1) {
+	    if (started != 0 || offset >= divisor) {
+		*cp++ = '0' + offset / divisor;
+		offset %= divisor;
+		started++;
+	    }
+	    divisor /= 10;
+	}
+	*cp++ = '0' + offset;
+	*cp = '\0';
+	return(cp1);
+}
+
+/*@-incondefs@*/ /* _et_list is global on unix but not in header annotations */
+errcode_t KRB5_CALLCONV
+add_error_table(/*@dependent@*/ const struct error_table * et)
+     /*@modifies _et_list,et_list_dynamic@*/
+/*@=incondefs@*/
+{
+    struct dynamic_et_list *del;
+    int merr;
+
+    if (CALL_INIT_FUNCTION(com_err_initialize))
+	return 0;
+
+    del = (struct dynamic_et_list *)malloc(sizeof(struct dynamic_et_list));
+    if (del == NULL)
+	return errno;
+
+    del->table = et;
+
+    merr = k5_mutex_lock(&et_list_lock);
+    if (merr) {
+	free(del);
+	return merr;
+    }
+    del->next = et_list_dynamic;
+    et_list_dynamic = del;
+    return k5_mutex_unlock(&et_list_lock);
+}
+
+/*@-incondefs@*/ /* _et_list is global on unix but not in header annotations */
+errcode_t KRB5_CALLCONV
+remove_error_table(const struct error_table * et)
+     /*@modifies _et_list,et_list_dynamic@*/
+/*@=incondefs@*/
+{
+    struct dynamic_et_list **del;
+    struct et_list **el;
+    int merr;
+
+    if (CALL_INIT_FUNCTION(com_err_initialize))
+	return 0;
+#if !defined(ENABLE_THREADS) && defined(DEBUG_THREADS)
+    if (et_list_lock.os.initialized == 0 && terminated != 0) {
+	fprintf(stderr, "\n\n *** Function remove_error_table called after com_err library termination. ***\n *** Shared library termination code executed in incorrect order?          ***\n\n");
+	abort();
+    }
+#endif
+    merr = k5_mutex_lock(&et_list_lock);
+    if (merr)
+	return merr;
+
+    /* Remove the entry that matches the error table instance.  Prefer dynamic
+       entries, but if there are none, check for a static one too.  */
+    for (del = &et_list_dynamic; *del; del = &(*del)->next)
+	if ((*del)->table == et) {
+	    /*@only@*/ struct dynamic_et_list *old = *del;
+	    *del = old->next;
+	    free (old);
+	    return k5_mutex_unlock(&et_list_lock);
+	}
+    for (el = &_et_list; *el; el = &(*el)->next)
+	if ((*el)->table == et) {
+	    struct et_list *old = *el;
+	    *el = old->next;
+	    old->next = NULL;
+	    old->table = NULL;
+	    return k5_mutex_unlock(&et_list_lock);
+	}
+    k5_mutex_unlock(&et_list_lock);
+    return ENOENT;
+}
+
+int com_err_finish_init()
+{
+    return CALL_INIT_FUNCTION(com_err_initialize);
+}
diff --git a/krb5-1-6/src/util/et/error_table.h b/krb5-1-6/src/util/et/error_table.h
new file mode 100644
index 000000000..b58502a58
--- /dev/null
+++ b/krb5-1-6/src/util/et/error_table.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1988 by the Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+
+#ifndef _ET_H
+
+#include <errno.h>
+
+#define ET_EBUFSIZ 1024
+
+struct et_list {
+    /*@dependent@*//*@null@*/ struct et_list *next;
+    /*@dependent@*//*@null@*/ const struct error_table *table;
+};
+
+struct dynamic_et_list {
+    /*@only@*//*@null@*/ struct dynamic_et_list *next;
+    /*@dependent@*/ const struct error_table *table;
+};
+
+#define	ERRCODE_RANGE	8	/* # of bits to shift table number */
+#define	BITS_PER_CHAR	6	/* # bits to shift per character in name */
+#define ERRCODE_MAX   0xFFFFFFFFUL      /* Mask for maximum error table */
+
+extern /*@observer@*/ const char *error_table_name (unsigned long)
+     /*@modifies internalState@*/;
+extern const char *error_table_name_r (unsigned long,
+					   /*@out@*/ /*@returned@*/ char *outbuf)
+     /*@modifies outbuf@*/;
+
+#include "k5-thread.h"
+extern k5_mutex_t com_err_hook_lock;
+extern int com_err_finish_init(void);
+
+#define _ET_H
+#endif
diff --git a/krb5-1-6/src/util/et/error_table.y b/krb5-1-6/src/util/et/error_table.y
new file mode 100644
index 000000000..f6b082fd4
--- /dev/null
+++ b/krb5-1-6/src/util/et/error_table.y
@@ -0,0 +1,231 @@
+%{
+#include <stdio.h>
+char *str_concat(), *ds(), *quote();
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+char *current_token = (char *)NULL;
+extern char *table_name;
+%}
+%union {
+	char *dynstr;
+}
+
+%token ERROR_TABLE ERROR_CODE_ENTRY END
+%token <dynstr> STRING QUOTED_STRING
+%type <dynstr> ec_name description table_id
+%{
+%}
+%start error_table
+%%
+
+error_table	:	ERROR_TABLE table_id error_codes END
+			{ table_name = ds($2);
+			  current_token = table_name;
+			  put_ecs(); }
+		;
+
+table_id	:	STRING
+			{ current_token = $1;
+			  set_table_num($1);
+			  $$ = $1; }
+		;
+
+error_codes	:	error_codes ec_entry
+		|	ec_entry
+		;
+
+ec_entry	:	ERROR_CODE_ENTRY ec_name ',' description
+			{ add_ec($2, $4);
+			  free($2);
+			  free($4); }
+		|	ERROR_CODE_ENTRY ec_name '=' STRING ',' description
+			{ add_ec_val($2, $4, $6);
+			  free($2);
+			  free($4);
+			  free($6);
+			}
+		;
+
+ec_name		:	STRING
+			{ $$ = ds($1);
+			  current_token = $$; }
+		;
+
+description	:	QUOTED_STRING
+			{ $$ = ds($1);
+			  current_token = $$; }
+		;
+
+%%
+/*
+ *
+ * Copyright 1986, 1987 by the MIT Student Information Processing Board
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include "com_err.h"
+#include "internal.h"
+#include "error_table.h"
+#include "mit-sipb-copyright.h"
+
+
+extern FILE *hfile, *cfile;
+
+static long gensym_n = 0;
+char *
+gensym(x)
+	char const *x;
+{
+	char *symbol;
+	if (!gensym_n) {
+		struct timeval tv;
+		struct timezone tzp;
+		gettimeofday(&tv, &tzp);
+		gensym_n = (tv.tv_sec%10000)*100 + tv.tv_usec/10000;
+	}
+	symbol = malloc(32 * sizeof(char));
+	gensym_n++;
+	sprintf(symbol, "et%ld", gensym_n);
+	return(symbol);
+}
+
+char *
+ds(string)
+	char const *string;
+{
+	char *rv;
+	rv = malloc(strlen(string)+1);
+	strcpy(rv, string);
+	return(rv);
+}
+
+char *
+quote(string)
+	char const *string;
+{
+	char *rv;
+	rv = malloc(strlen(string)+3);
+	strcpy(rv, "\"");
+	strcat(rv, string);
+	strcat(rv, "\"");
+	return(rv);
+}
+
+long table_number;
+int current = 0;
+char **error_codes = (char **)NULL;
+
+add_ec(name, description)
+	char const *name, *description;
+{
+	fprintf(cfile, "\t\"%s\",\n", description);
+	if (error_codes == (char **)NULL) {
+		error_codes = (char **)malloc(sizeof(char *));
+		*error_codes = (char *)NULL;
+	}
+	error_codes = (char **)realloc((char *)error_codes,
+				       (current + 2)*sizeof(char *));
+	error_codes[current++] = ds(name);
+	error_codes[current] = (char *)NULL;
+}
+
+add_ec_val(name, val, description)
+	char const *name, *val, *description;
+{
+	const int ncurrent = atoi(val);
+	if (ncurrent < current) {
+		printf("Error code %s (%d) out of order", name,
+		       current);
+		return;
+	}
+      
+	while (ncurrent > current)
+	     fputs("\t(char *)NULL,\n", cfile), current++;
+	
+	fprintf(cfile, "\t\"%s\",\n", description);
+	if (error_codes == (char **)NULL) {
+		error_codes = (char **)malloc(sizeof(char *));
+		*error_codes = (char *)NULL;
+	}
+	error_codes = (char **)realloc((char *)error_codes,
+				       (current + 2)*sizeof(char *));
+	error_codes[current++] = ds(name);
+	error_codes[current] = (char *)NULL;
+} 
+
+put_ecs()
+{
+	int i;
+	for (i = 0; i < current; i++) {
+	     if (error_codes[i] != (char *)NULL)
+		  fprintf(hfile, "#define %-40s (%ldL)\n",
+			  error_codes[i], table_number + i);
+	}
+}
+
+/*
+ * char_to_num -- maps letters and numbers into a small numbering space
+ * 	uppercase ->  1-26
+ *	lowercase -> 27-52
+ *	digits    -> 53-62
+ *	underscore-> 63
+ */
+
+static const char char_set[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+int char_to_num(c)
+	char c;
+{
+	const char *where;
+	int diff;
+
+	where = strchr (char_set, c);
+	if (where) {
+		diff = where - char_set + 1;
+		assert (diff < (1 << ERRCODE_RANGE));
+		return diff;
+	}
+	else if (isprint (c))
+		fprintf (stderr,
+			 "Illegal character `%c' in error table name\n",
+			 c);
+	else
+		fprintf (stderr,
+			 "Illegal character %03o in error table name\n",
+			 c);
+	exit (1);
+}
+
+set_table_num(string)
+	char *string;
+{
+	if (char_to_num (string[0]) > char_to_num ('z')) {
+		fprintf (stderr, "%s%s%s%s",
+			 "First character of error table name must be ",
+			 "a letter; name ``",
+			 string, "'' rejected\n");
+		exit (1);
+	}
+	if (strlen(string) > 4) {
+		fprintf(stderr, "Table name %s too long, truncated ",
+			string);
+		string[4] = '\0';
+		fprintf(stderr, "to %s\n", string);
+	}
+	while (*string != '\0') {
+		table_number = (table_number << BITS_PER_CHAR)
+			+ char_to_num(*string);
+		string++;
+	}
+	table_number = table_number << ERRCODE_RANGE;
+}
+
+#include "et_lex.lex.c"
diff --git a/krb5-1-6/src/util/et/et.exp b/krb5-1-6/src/util/et/et.exp
new file mode 100644
index 000000000..00e15a2df
--- /dev/null
+++ b/krb5-1-6/src/util/et/et.exp
@@ -0,0 +1,8 @@
+#
+# comerr library Macintosh export file
+#
+# $Header$
+
+error_message
+add_error_table
+remove_error_table
diff --git a/krb5-1-6/src/util/et/et.pbexp b/krb5-1-6/src/util/et/et.pbexp
new file mode 100644
index 000000000..31097615a
--- /dev/null
+++ b/krb5-1-6/src/util/et/et.pbexp
@@ -0,0 +1,10 @@
+#
+# comerr library Macintosh export file
+#
+# $Header$
+
+_com_err
+_com_err_va
+_error_message
+_add_error_table
+_remove_error_table
diff --git a/krb5-1-6/src/util/et/et1.et b/krb5-1-6/src/util/et/et1.et
new file mode 100644
index 000000000..71c4e6c59
--- /dev/null
+++ b/krb5-1-6/src/util/et/et1.et
@@ -0,0 +1,11 @@
+	error_table et1
+
+ec	ET1_M0, "error table 1 message 0"
+
+ec	ET1_M1,
+	"error table 1 message 1"
+
+error_code ET1_M2,
+	"error table 1 message 2"
+
+end
diff --git a/krb5-1-6/src/util/et/et2.et b/krb5-1-6/src/util/et/et2.et
new file mode 100644
index 000000000..4425f047a
--- /dev/null
+++ b/krb5-1-6/src/util/et/et2.et
@@ -0,0 +1,11 @@
+	error_table et2
+
+ec	ET2_M0, "error table 2 message 0"
+
+ec	ET2_M1,
+	"error table 2 message 1"
+
+error_code ET2_M2,
+	"error table 2 message 2"
+
+end
diff --git a/krb5-1-6/src/util/et/et_c.awk b/krb5-1-6/src/util/et/et_c.awk
new file mode 100644
index 000000000..cc277f5dc
--- /dev/null
+++ b/krb5-1-6/src/util/et/et_c.awk
@@ -0,0 +1,213 @@
+BEGIN { 
+char_shift=64
+## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+c2n["A"]=1
+c2n["B"]=2
+c2n["C"]=3
+c2n["D"]=4
+c2n["E"]=5
+c2n["F"]=6
+c2n["G"]=7
+c2n["H"]=8
+c2n["I"]=9
+c2n["J"]=10
+c2n["K"]=11
+c2n["L"]=12
+c2n["M"]=13
+c2n["N"]=14
+c2n["O"]=15
+c2n["P"]=16
+c2n["Q"]=17
+c2n["R"]=18
+c2n["S"]=19
+c2n["T"]=20
+c2n["U"]=21
+c2n["V"]=22
+c2n["W"]=23
+c2n["X"]=24
+c2n["Y"]=25
+c2n["Z"]=26
+c2n["a"]=27
+c2n["b"]=28
+c2n["c"]=29
+c2n["d"]=30
+c2n["e"]=31
+c2n["f"]=32
+c2n["g"]=33
+c2n["h"]=34
+c2n["i"]=35
+c2n["j"]=36
+c2n["k"]=37
+c2n["l"]=38
+c2n["m"]=39
+c2n["n"]=40
+c2n["o"]=41
+c2n["p"]=42
+c2n["q"]=43
+c2n["r"]=44
+c2n["s"]=45
+c2n["t"]=46
+c2n["u"]=47
+c2n["v"]=48
+c2n["w"]=49
+c2n["x"]=50
+c2n["y"]=51
+c2n["z"]=52
+c2n["0"]=53
+c2n["1"]=54
+c2n["2"]=55
+c2n["3"]=56
+c2n["4"]=57
+c2n["5"]=58
+c2n["6"]=59
+c2n["7"]=60
+c2n["8"]=61
+c2n["9"]=62
+c2n["_"]=63
+}
+/^#/ { next }
+/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
+	table_number = 0
+	table_name = $2
+	mod_base = 1000000
+	for(i=1; i<=length(table_name); i++) {
+	    table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
+	}
+
+	# We start playing *_high, *low games here because the some
+	# awk programs do not have the necessary precision (sigh)
+	tab_base_low = table_number % mod_base
+	tab_base_high = int(table_number / mod_base)
+	tab_base_sign = 1;
+
+	# figure out: table_number_base=table_number*256
+	tab_base_low = tab_base_low * 256
+	tab_base_high = (tab_base_high * 256) + \
+			int(tab_base_low / mod_base)
+	tab_base_low = tab_base_low % mod_base
+
+	if (table_number > 128*256*256) {
+		# figure out:  table_number_base -= 256*256*256*256
+		# sub_high, sub_low is 256*256*256*256
+		sub_low = 256*256*256 % mod_base
+		sub_high = int(256*256*256 / mod_base)
+
+		sub_low = sub_low * 256
+		sub_high = (sub_high * 256) + int(sub_low / mod_base)
+		sub_low = sub_low % mod_base
+
+		tab_base_low = sub_low - tab_base_low;
+		tab_base_high = sub_high - tab_base_high;
+		tab_base_sign = -1;
+		if (tab_base_low < 0) {
+			tab_base_low = tab_base_low + mod_base
+			tab_base_high--
+		}
+	}
+	print "/*" > outfile
+	print " * " outfile ":" > outfile
+	print " * This file is automatically generated; please do not edit it." > outfile
+	print " */" > outfile
+
+	print "#if defined(_WIN32)" > outfile
+	print "# include \"win-mac.h\"" > outfile
+	print "#endif" > outfile
+	print "" > outfile
+	print "#if !defined(_WIN32)" > outfile
+	print "extern void initialize_" table_name "_error_table (void);" > outfile
+	print "#endif" > outfile
+	print "" > outfile
+	print "/* Lclint doesn't handle null annotations on arrays" > outfile
+	print "   properly, so we need this typedef in each" > outfile
+	print "   generated .c file.  */" > outfile
+	print "/*@-redef@*/" > outfile
+	print "typedef /*@null@*/ const char *ncptr;" > outfile
+	print "/*@=redef@*/" > outfile
+	print "" > outfile
+	print "static ncptr const text[] = {" > outfile
+	table_item_count = 0
+}
+
+(continuation == 1) && ($0 ~ /\\[ \t]*$/) {
+	text=substr($0,1,length($0)-1);
+#	printf "\t\t\"%s\"\n", text > outfile
+	cont_buf=cont_buf text;
+}
+
+(continuation == 1) && ($0 ~ /"[ \t]*$/) {
+#	printf "\t\t\"%s,\n", $0 > outfile
+	printf "\t%s,\n", cont_buf $0 > outfile
+	continuation = 0;
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/ {
+	table_item_count++
+	skipone=1
+	next
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/ {
+	text=""
+	for (i=3; i<=NF; i++) { 
+	    text = text FS $i
+	}
+	text=substr(text,2,length(text)-1);
+	printf "\t%s,\n", text > outfile
+	table_item_count++
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*\\[ \t]*$/ {
+	text=""
+	for (i=3; i<=NF; i++) { 
+	    text = text FS $i
+	}
+	text=substr(text,2,length(text)-2);
+#	printf "\t%s\"\n", text > outfile
+	cont_buf=text
+	continuation++;
+}
+
+/^[ \t]*".*\\[ \t]*$/ {
+	if (skipone) {
+	    text=substr($0,1,length($0)-1);
+#	    printf "\t%s\"\n", text > outfile
+	    cont_buf=text
+	    continuation++;
+	}
+	skipone=0
+}
+
+{ 
+	if (skipone) {
+	    printf "\t%s,\n", $0 > outfile
+	}
+	skipone=0
+}
+END {
+	if (table_item_count > 256) {
+	    print "Error table too large!" | "cat 1>&2"
+	    exit 1
+	}
+	print "    0" > outfile
+	print "};" > outfile
+	print "" > outfile
+	print "#include <com_err.h>" > outfile
+	print "" > outfile
+	if (tab_base_high == 0) {
+	    print "const struct error_table et_" table_name "_error_table = { text, " \
+		sprintf("%dL, %d };", tab_base_sign*tab_base_low, \
+		table_item_count) > outfile
+	} else {
+	    print "const struct error_table et_" table_name "_error_table = { text, " \
+		sprintf("%d%06dL, %d };", tab_base_sign*tab_base_high, \
+		tab_base_low, table_item_count) > outfile
+	}
+	print "" > outfile
+	print "#if !defined(_WIN32)" > outfile
+	print "void initialize_" table_name "_error_table (void)" > outfile
+	print "    /*@modifies internalState@*/" > outfile
+	print "{" > outfile
+	print "    (void) add_error_table (&et_" table_name "_error_table);" > outfile
+	print "}" > outfile
+	print "#endif" > outfile
+}
diff --git a/krb5-1-6/src/util/et/et_c.pl b/krb5-1-6/src/util/et/et_c.pl
new file mode 100644
index 000000000..a845eb0f8
--- /dev/null
+++ b/krb5-1-6/src/util/et/et_c.pl
@@ -0,0 +1,289 @@
+eval 'exec /usr/athena/bin/perl -S $0 ${1+"$@"}'
+    if $running_under_some_shell;
+			# this emulates #! processing on NIH machines.
+			# (remove #! line above if indigestible)
+
+eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
+			# process any FOO=bar switches
+
+$[ = 1;			# set array base to 1
+$FS = ' ';		# set field separator
+$, = ' ';		# set output field separator
+$\ = "\n";		# set output record separator
+
+$char_shift = 64;
+## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+$c2n{'A'} = 1;
+$c2n{'B'} = 2;
+$c2n{'C'} = 3;
+$c2n{'D'} = 4;
+$c2n{'E'} = 5;
+$c2n{'F'} = 6;
+$c2n{'G'} = 7;
+$c2n{'H'} = 8;
+$c2n{'I'} = 9;
+$c2n{'J'} = 10;
+$c2n{'K'} = 11;
+$c2n{'L'} = 12;
+$c2n{'M'} = 13;
+$c2n{'N'} = 14;
+$c2n{'O'} = 15;
+$c2n{'P'} = 16;
+$c2n{'Q'} = 17;
+$c2n{'R'} = 18;
+$c2n{'S'} = 19;
+$c2n{'T'} = 20;
+$c2n{'U'} = 21;
+$c2n{'V'} = 22;
+$c2n{'W'} = 23;
+$c2n{'X'} = 24;
+$c2n{'Y'} = 25;
+$c2n{'Z'} = 26;
+$c2n{'a'} = 27;
+$c2n{'b'} = 28;
+$c2n{'c'} = 29;
+$c2n{'d'} = 30;
+$c2n{'e'} = 31;
+$c2n{'f'} = 32;
+$c2n{'g'} = 33;
+$c2n{'h'} = 34;
+$c2n{'i'} = 35;
+$c2n{'j'} = 36;
+$c2n{'k'} = 37;
+$c2n{'l'} = 38;
+$c2n{'m'} = 39;
+$c2n{'n'} = 40;
+$c2n{'o'} = 41;
+$c2n{'p'} = 42;
+$c2n{'q'} = 43;
+$c2n{'r'} = 44;
+$c2n{'s'} = 45;
+$c2n{'t'} = 46;
+$c2n{'u'} = 47;
+$c2n{'v'} = 48;
+$c2n{'w'} = 49;
+$c2n{'x'} = 50;
+$c2n{'y'} = 51;
+$c2n{'z'} = 52;
+$c2n{'0'} = 53;
+$c2n{'1'} = 54;
+$c2n{'2'} = 55;
+$c2n{'3'} = 56;
+$c2n{'4'} = 57;
+$c2n{'5'} = 58;
+$c2n{'6'} = 59;
+$c2n{'7'} = 60;
+$c2n{'8'} = 61;
+$c2n{'9'} = 62;
+$c2n{'_'} = 63;
+
+line: while (<>) {
+    chomp;	# strip record separator
+    @Fld = split($FS, $_, 9999);
+    if (/^#/) {
+	next line;
+    }
+    if (/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/) {
+	$table_number = 0;
+	$table_name = $Fld[2];
+	$mod_base = 1000000;
+	for ($i = 1; $i <= length($table_name); $i++) {
+	    $table_number = ($table_number * $char_shift) +
+
+	      $c2n{substr($table_name, $i, 1)};
+	}
+
+	# We start playing *_high, *low games here because the some
+	# awk programs do not have the necessary precision (sigh)
+	$tab_base_low = $table_number % $mod_base;
+	$tab_base_high = int($table_number / $mod_base);
+	$tab_base_sign = 1;
+
+	# figure out: table_number_base=table_number*256
+	$tab_base_low = $tab_base_low * 256;
+	$tab_base_high = ($tab_base_high * 256) + int($tab_base_low /
+
+	  $mod_base);
+	$tab_base_low = $tab_base_low % $mod_base;
+
+	if ($table_number > 128 * 256 * 256) {
+	    # figure out:  table_number_base -= 256*256*256*256
+	    # sub_high, sub_low is 256*256*256*256
+	    $sub_low = 256 * 256 * 256 % $mod_base;
+	    $sub_high = int(256 * 256 * 256 / $mod_base);
+
+	    $sub_low = $sub_low * 256;
+	    $sub_high = ($sub_high * 256) + int($sub_low / $mod_base);
+	    $sub_low = $sub_low % $mod_base;
+
+	    $tab_base_low = $sub_low - $tab_base_low;
+	    $tab_base_high = $sub_high - $tab_base_high;
+	    $tab_base_sign = -1;
+	    if ($tab_base_low < 0) {
+		$tab_base_low = $tab_base_low + $mod_base;
+		$tab_base_high--;
+	    }
+	}
+	&Pick('>', $outfile) &&
+	    (print $fh '/*');
+	&Pick('>', $outfile) &&
+	    (print $fh ' * ' . $outfile . ':');
+	&Pick('>', $outfile) &&
+	    (print $fh
+
+	      ' * This file is automatically generated; please do not edit it.');
+	&Pick('>', $outfile) &&
+	    (print $fh ' */');
+
+	&Pick('>', $outfile) &&
+	    (print $fh '#if defined(_WIN32)');
+	&Pick('>', $outfile) &&
+	    (print $fh "# include \"win-mac.h\"");
+	&Pick('>', $outfile) &&
+	    (print $fh '#endif');
+	&Pick('>', $outfile) &&
+	    (print $fh '');
+	&Pick('>', $outfile) &&
+	    (print $fh '#if !defined(_WIN32)');
+	&Pick('>', $outfile) &&
+	    (print $fh 'extern void initialize_' . $table_name .
+
+	      '_error_table (void);');
+	&Pick('>', $outfile) &&
+	    (print $fh '#endif');
+	&Pick('>', $outfile) &&
+	    (print $fh '');
+	&Pick('>', $outfile) &&
+	    (print $fh "/* Lclint doesn't handle null annotations on arrays");
+	&Pick('>', $outfile) &&
+	    (print $fh '   properly, so we need this typedef in each');
+	&Pick('>', $outfile) &&
+	    (print $fh '   generated .c file.  */');
+	&Pick('>', $outfile) &&
+	    (print $fh '/*@-redef@*/');
+	&Pick('>', $outfile) &&
+	    (print $fh 'typedef /*@null@*/ const char *ncptr;');
+	&Pick('>', $outfile) &&
+	    (print $fh '/*@=redef@*/');
+	&Pick('>', $outfile) &&
+	    (print $fh '');
+	&Pick('>', $outfile) &&
+	    (print $fh 'static ncptr const text[] = {');
+	$table_item_count = 0;
+    }
+
+    if (($continuation == 1) && ($_ =~ /\\[ \t]*$/)) {
+	$text = substr($_, 1, length($_) - 1);
+	#	printf "\t\t\"%s\"\n", text > outfile
+	$cont_buf = $cont_buf . $text;
+    }
+
+    if (($continuation == 1) && ($_ =~ /"[ \t]*$/)) {
+	#	printf "\t\t\"%s,\n", $0 > outfile
+	&Pick('>', $outfile) &&
+	    (printf $fh "\t%s,\n", $cont_buf . $_);
+	$continuation = 0;
+    }
+
+    if (/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/) {
+	$table_item_count++;
+	$skipone = 1;
+	next line;
+    }
+
+    if (/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/) {
+	$text = '';
+	for ($i = 3; $i <= $#Fld; $i++) {
+	    $text = $text . $FS . $Fld[$i];
+	}
+	$text = substr($text, 2, length($text) - 1);
+	&Pick('>', $outfile) &&
+	    (printf $fh "\t%s,\n", $text);
+	$table_item_count++;
+    }
+
+    if (/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*\\[ \t]*$/) {
+	$text = '';
+	for ($i = 3; $i <= $#Fld; $i++) {
+	    $text = $text . $FS . $Fld[$i];
+	}
+	$text = substr($text, 2, length($text) - 2);
+	#	printf "\t%s\"\n", text > outfile
+	$cont_buf = $text;
+	$continuation++;
+    }
+
+    if (/^[ \t]*".*\\[ \t]*$/) {
+	if ($skipone) {
+	    $text = substr($_, 1, length($_) - 1);
+	    #	    printf "\t%s\"\n", text > outfile
+	    $cont_buf = $text;
+	    $continuation++;
+	}
+	$skipone = 0;
+    }
+
+    if ($skipone) {
+	&Pick('>', $outfile) &&
+	    (printf $fh "\t%s,\n", $_);
+    }
+    $skipone = 0;
+}
+
+if ($table_item_count > 256) {
+    &Pick('|', 'cat 1>&2') &&
+	(print $fh 'Error table too large!');
+    exit 1;
+}
+&Pick('>', $outfile) &&
+    (print $fh '    0');
+&Pick('>', $outfile) &&
+    (print $fh '};');
+&Pick('>', $outfile) &&
+    (print $fh '');
+&Pick('>', $outfile) &&
+    (print $fh '#include <com_err.h>');
+&Pick('>', $outfile) &&
+    (print $fh '');
+if ($tab_base_high == 0) {
+    &Pick('>', $outfile) &&
+	(print $fh 'const struct error_table et_' . $table_name .
+
+	  '_error_table = { text, ' . sprintf('%dL, %d };',
+
+	  $tab_base_sign * $tab_base_low, $table_item_count));
+}
+else {
+    &Pick('>', $outfile) &&
+	(print $fh 'const struct error_table et_' . $table_name .
+
+	  '_error_table = { text, ' . sprintf('%d%06dL, %d };',
+
+	  $tab_base_sign * $tab_base_high, $tab_base_low, $table_item_count));
+}
+&Pick('>', $outfile) &&
+    (print $fh '');
+&Pick('>', $outfile) &&
+    (print $fh '#if !defined(_WIN32)');
+&Pick('>', $outfile) &&
+    (print $fh 'void initialize_' . $table_name . '_error_table (void)');
+&Pick('>', $outfile) &&
+    (print $fh '    /*@modifies internalState@*/');
+&Pick('>', $outfile) &&
+    (print $fh '{');
+&Pick('>', $outfile) &&
+    (print $fh '    (void) add_error_table (&et_' . $table_name .
+
+      '_error_table);');
+&Pick('>', $outfile) &&
+    (print $fh '}');
+&Pick('>', $outfile) &&
+    (print $fh '#endif');
+
+exit $ExitValue;
+
+sub Pick {
+    local($mode,$name,$pipe) = @_;
+    $fh = $name;
+    open($name,$mode.$name.$pipe) unless $opened{$name}++;
+}
diff --git a/krb5-1-6/src/util/et/et_h.awk b/krb5-1-6/src/util/et/et_h.awk
new file mode 100644
index 000000000..65c6c453f
--- /dev/null
+++ b/krb5-1-6/src/util/et/et_h.awk
@@ -0,0 +1,168 @@
+BEGIN { 
+char_shift=64
+## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+c2n["A"]=1
+c2n["B"]=2
+c2n["C"]=3
+c2n["D"]=4
+c2n["E"]=5
+c2n["F"]=6
+c2n["G"]=7
+c2n["H"]=8
+c2n["I"]=9
+c2n["J"]=10
+c2n["K"]=11
+c2n["L"]=12
+c2n["M"]=13
+c2n["N"]=14
+c2n["O"]=15
+c2n["P"]=16
+c2n["Q"]=17
+c2n["R"]=18
+c2n["S"]=19
+c2n["T"]=20
+c2n["U"]=21
+c2n["V"]=22
+c2n["W"]=23
+c2n["X"]=24
+c2n["Y"]=25
+c2n["Z"]=26
+c2n["a"]=27
+c2n["b"]=28
+c2n["c"]=29
+c2n["d"]=30
+c2n["e"]=31
+c2n["f"]=32
+c2n["g"]=33
+c2n["h"]=34
+c2n["i"]=35
+c2n["j"]=36
+c2n["k"]=37
+c2n["l"]=38
+c2n["m"]=39
+c2n["n"]=40
+c2n["o"]=41
+c2n["p"]=42
+c2n["q"]=43
+c2n["r"]=44
+c2n["s"]=45
+c2n["t"]=46
+c2n["u"]=47
+c2n["v"]=48
+c2n["w"]=49
+c2n["x"]=50
+c2n["y"]=51
+c2n["z"]=52
+c2n["0"]=53
+c2n["1"]=54
+c2n["2"]=55
+c2n["3"]=56
+c2n["4"]=57
+c2n["5"]=58
+c2n["6"]=59
+c2n["7"]=60
+c2n["8"]=61
+c2n["9"]=62
+c2n["_"]=63
+}
+/^#/ { next }
+/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
+	table_number = 0
+	table_name = $2
+	mod_base = 1000000
+	for(i=1; i<=length(table_name); i++) {
+	    table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
+	}
+	# We start playing *_high, *low games here because the some
+	# awk programs do not have the necessary precision (sigh)
+	tab_base_low = table_number % mod_base
+	tab_base_high = int(table_number / mod_base)
+	tab_base_sign = 1;
+
+	# figure out: table_number_base=table_number*256
+	tab_base_low = tab_base_low * 256
+	tab_base_high = (tab_base_high * 256) + \
+			int(tab_base_low / mod_base)
+	tab_base_low = tab_base_low % mod_base
+
+	if (table_number > 128*256*256) {
+		# figure out:  table_number_base -= 256*256*256*256
+		# sub_high, sub_low is 256*256*256*256
+		sub_low = 256*256*256 % mod_base
+		sub_high = int(256*256*256 / mod_base)
+
+		sub_low = sub_low * 256
+		sub_high = (sub_high * 256) + int(sub_low / mod_base)
+		sub_low = sub_low % mod_base
+
+		tab_base_low = sub_low - tab_base_low;
+		tab_base_high = sub_high - tab_base_high;
+		tab_base_sign = -1;
+		if (tab_base_low < 0) {
+			tab_base_low = tab_base_low + mod_base
+			tab_base_high--
+		}
+	}
+	curr_low = tab_base_low
+	curr_high = tab_base_high
+	curr_sign = tab_base_sign
+	print "/*" > outfile
+	print " * " outfile ":" > outfile
+	print " * This file is automatically generated; please do not edit it." > outfile
+	print " */" > outfile
+	print "" > outfile
+	print "#include <com_err.h>" > outfile
+	print "" > outfile
+	table_item_count = 0
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,/ {
+	tag=substr($2,1,length($2)-1)
+	if (curr_high == 0) {
+		printf "#define %-40s (%dL)\n", tag, \
+			curr_sign*curr_low > outfile
+	} else {
+		printf "#define %-40s (%d%06dL)\n", tag, curr_high*curr_sign, \
+			curr_low > outfile
+	}
+	curr_low += curr_sign;
+	if (curr_low >= mod_base) {
+		curr_low -= mod_base;
+		curr_high++
+	}
+	if (curr_low < 0) {
+		cur_low += mod_base
+		cur_high--
+	}
+}
+
+END {
+	if (table_item_count > 256) {
+	    print "Error table too large!" | "cat 1>&2"
+	    exit 1
+	}
+	if (tab_base_high == 0) {
+		print "#define ERROR_TABLE_BASE_" table_name " (" \
+			sprintf("%d", tab_base_sign*tab_base_low) \
+			"L)" > outfile
+	} else {
+		print "#define ERROR_TABLE_BASE_" table_name " (" \
+			sprintf("%d%06d", tab_base_sign*tab_base_high, \
+			tab_base_low) "L)" > outfile
+	}
+	print "" > outfile
+	print "extern const struct error_table et_" table_name "_error_table;" > outfile
+	print "" > outfile
+	print "#if !defined(_WIN32)" > outfile
+	print "/* for compatibility with older versions... */" > outfile
+	print "extern void initialize_" table_name "_error_table (void) /*@modifies internalState@*/;" > outfile
+	print "#else" > outfile
+	print "#define initialize_" table_name "_error_table()" > outfile
+	print "#endif" > outfile
+	print "" > outfile
+	print "#if !defined(_WIN32)" > outfile
+	print "#define init_" table_name "_err_tbl initialize_" table_name "_error_table" > outfile
+	print "#define " table_name "_err_base ERROR_TABLE_BASE_" table_name > outfile
+	print "#endif" > outfile
+}
+
diff --git a/krb5-1-6/src/util/et/et_h.pl b/krb5-1-6/src/util/et/et_h.pl
new file mode 100644
index 000000000..5ab8e8b46
--- /dev/null
+++ b/krb5-1-6/src/util/et/et_h.pl
@@ -0,0 +1,234 @@
+eval 'exec /usr/athena/bin/perl -S $0 ${1+"$@"}'
+    if $running_under_some_shell;
+			# this emulates #! processing on NIH machines.
+			# (remove #! line above if indigestible)
+
+eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
+			# process any FOO=bar switches
+
+$[ = 1;			# set array base to 1
+$, = ' ';		# set output field separator
+$\ = "\n";		# set output record separator
+
+$char_shift = 64;
+## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+$c2n{'A'} = 1;
+$c2n{'B'} = 2;
+$c2n{'C'} = 3;
+$c2n{'D'} = 4;
+$c2n{'E'} = 5;
+$c2n{'F'} = 6;
+$c2n{'G'} = 7;
+$c2n{'H'} = 8;
+$c2n{'I'} = 9;
+$c2n{'J'} = 10;
+$c2n{'K'} = 11;
+$c2n{'L'} = 12;
+$c2n{'M'} = 13;
+$c2n{'N'} = 14;
+$c2n{'O'} = 15;
+$c2n{'P'} = 16;
+$c2n{'Q'} = 17;
+$c2n{'R'} = 18;
+$c2n{'S'} = 19;
+$c2n{'T'} = 20;
+$c2n{'U'} = 21;
+$c2n{'V'} = 22;
+$c2n{'W'} = 23;
+$c2n{'X'} = 24;
+$c2n{'Y'} = 25;
+$c2n{'Z'} = 26;
+$c2n{'a'} = 27;
+$c2n{'b'} = 28;
+$c2n{'c'} = 29;
+$c2n{'d'} = 30;
+$c2n{'e'} = 31;
+$c2n{'f'} = 32;
+$c2n{'g'} = 33;
+$c2n{'h'} = 34;
+$c2n{'i'} = 35;
+$c2n{'j'} = 36;
+$c2n{'k'} = 37;
+$c2n{'l'} = 38;
+$c2n{'m'} = 39;
+$c2n{'n'} = 40;
+$c2n{'o'} = 41;
+$c2n{'p'} = 42;
+$c2n{'q'} = 43;
+$c2n{'r'} = 44;
+$c2n{'s'} = 45;
+$c2n{'t'} = 46;
+$c2n{'u'} = 47;
+$c2n{'v'} = 48;
+$c2n{'w'} = 49;
+$c2n{'x'} = 50;
+$c2n{'y'} = 51;
+$c2n{'z'} = 52;
+$c2n{'0'} = 53;
+$c2n{'1'} = 54;
+$c2n{'2'} = 55;
+$c2n{'3'} = 56;
+$c2n{'4'} = 57;
+$c2n{'5'} = 58;
+$c2n{'6'} = 59;
+$c2n{'7'} = 60;
+$c2n{'8'} = 61;
+$c2n{'9'} = 62;
+$c2n{'_'} = 63;
+
+line: while (<>) {
+    ($Fld1,$Fld2) = split(' ', $_, 9999);
+    if (/^#/) {
+	next line;
+    }
+    if (/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/) {
+	$table_number = 0;
+	$table_name = $Fld2;
+	$mod_base = 1000000;
+	for ($i = 1; $i <= length($table_name); $i++) {
+	    $table_number = ($table_number * $char_shift) +
+
+	      $c2n{substr($table_name, $i, 1)};
+	}
+	# We start playing *_high, *low games here because the some
+	# awk programs do not have the necessary precision (sigh)
+	$tab_base_low = $table_number % $mod_base;
+	$tab_base_high = int($table_number / $mod_base);
+	$tab_base_sign = 1;
+
+	# figure out: table_number_base=table_number*256
+	$tab_base_low = $tab_base_low * 256;
+	$tab_base_high = ($tab_base_high * 256) + int($tab_base_low /
+
+	  $mod_base);
+	$tab_base_low = $tab_base_low % $mod_base;
+
+	if ($table_number > 128 * 256 * 256) {
+	    # figure out:  table_number_base -= 256*256*256*256
+	    # sub_high, sub_low is 256*256*256*256
+	    $sub_low = 256 * 256 * 256 % $mod_base;
+	    $sub_high = int(256 * 256 * 256 / $mod_base);
+
+	    $sub_low = $sub_low * 256;
+	    $sub_high = ($sub_high * 256) + int($sub_low / $mod_base);
+	    $sub_low = $sub_low % $mod_base;
+
+	    $tab_base_low = $sub_low - $tab_base_low;
+	    $tab_base_high = $sub_high - $tab_base_high;
+	    $tab_base_sign = -1;
+	    if ($tab_base_low < 0) {
+		$tab_base_low = $tab_base_low + $mod_base;
+		$tab_base_high--;
+	    }
+	}
+	$curr_low = $tab_base_low;
+	$curr_high = $tab_base_high;
+	$curr_sign = $tab_base_sign;
+	&Pick('>', $outfile) &&
+	    (print $fh '/*');
+	&Pick('>', $outfile) &&
+	    (print $fh ' * ' . $outfile . ':');
+	&Pick('>', $outfile) &&
+	    (print $fh
+
+	      ' * This file is automatically generated; please do not edit it.');
+	&Pick('>', $outfile) &&
+	    (print $fh ' */');
+	&Pick('>', $outfile) &&
+	    (print $fh '');
+	&Pick('>', $outfile) &&
+	    (print $fh '#include <com_err.h>');
+	&Pick('>', $outfile) &&
+	    (print $fh '');
+	$table_item_count = 0;
+    }
+
+    if (/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,/) {
+	$tag = substr($Fld2, 1, length($Fld2) - 1);
+	if ($curr_high == 0) {
+	    &Pick('>', $outfile) &&
+		(printf $fh "#define %-40s (%dL)\n", $tag,
+
+		  $curr_sign * $curr_low);
+	}
+	else {
+	    &Pick('>', $outfile) &&
+		(printf $fh "#define %-40s (%d%06dL)\n", $tag,
+
+		  $curr_high * $curr_sign, $curr_low);
+	}
+	$curr_low += $curr_sign;
+	if ($curr_low >= $mod_base) {	#???
+	    $curr_low -= $mod_base;
+	    $curr_high++;
+	}
+	if ($curr_low < 0) {
+	    $cur_low += $mod_base;
+	    $cur_high--;
+	}
+    }
+}
+
+if ($table_item_count > 256) {
+    &Pick('|', 'cat 1>&2') &&
+	(print $fh 'Error table too large!');
+    exit 1;
+}
+if ($tab_base_high == 0) {
+    &Pick('>', $outfile) &&
+	(print $fh '#define ERROR_TABLE_BASE_' . $table_name . ' (' .
+
+	  sprintf('%d', $tab_base_sign * $tab_base_low) . 'L)');
+}
+else {
+    &Pick('>', $outfile) &&
+	(print $fh '#define ERROR_TABLE_BASE_' . $table_name . ' (' .
+
+	  sprintf('%d%06d', $tab_base_sign * $tab_base_high,
+
+	  $tab_base_low) . 'L)');
+}
+&Pick('>', $outfile) &&
+    (print $fh '');
+&Pick('>', $outfile) &&
+    (print $fh 'extern const struct error_table et_' . $table_name .
+
+      '_error_table;');
+&Pick('>', $outfile) &&
+    (print $fh '');
+&Pick('>', $outfile) &&
+    (print $fh '#if !defined(_WIN32)');
+&Pick('>', $outfile) &&
+    (print $fh '/* for compatibility with older versions... */');
+&Pick('>', $outfile) &&
+    (print $fh 'extern void initialize_' . $table_name .
+
+      '_error_table (void) /*@modifies internalState@*/;');
+&Pick('>', $outfile) &&
+    (print $fh '#else');
+&Pick('>', $outfile) &&
+    (print $fh '#define initialize_' . $table_name . '_error_table()');
+&Pick('>', $outfile) &&
+    (print $fh '#endif');
+&Pick('>', $outfile) &&
+    (print $fh '');
+&Pick('>', $outfile) &&
+    (print $fh '#if !defined(_WIN32)');
+&Pick('>', $outfile) &&
+    (print $fh '#define init_' . $table_name . '_err_tbl initialize_' .
+
+      $table_name . '_error_table');
+&Pick('>', $outfile) &&
+    (print $fh '#define ' . $table_name . '_err_base ERROR_TABLE_BASE_' .
+
+      $table_name);
+&Pick('>', $outfile) &&
+    (print $fh '#endif');
+
+exit $ExitValue;
+
+sub Pick {
+    local($mode,$name,$pipe) = @_;
+    $fh = $name;
+    open($name,$mode.$name.$pipe) unless $opened{$name}++;
+}
diff --git a/krb5-1-6/src/util/et/et_lex.lex.l b/krb5-1-6/src/util/et/et_lex.lex.l
new file mode 100644
index 000000000..b363e8ca4
--- /dev/null
+++ b/krb5-1-6/src/util/et/et_lex.lex.l
@@ -0,0 +1,23 @@
+PC	[^\"]
+AN	[A-Z_a-z0-9]
+%%
+
+error_table	return ERROR_TABLE;
+et		return ERROR_TABLE;
+error_code	return ERROR_CODE_ENTRY;
+ec		return ERROR_CODE_ENTRY;
+end		return END;
+
+[\t\n ]		;
+
+\"{PC}*\"	{ register char *p; yylval.dynstr = ds(yytext+1);
+		  if (p=strrchr(yylval.dynstr, '"')) *p='\0';
+		  return QUOTED_STRING;
+		}
+
+{AN}*	{ yylval.dynstr = ds(yytext); return STRING; }
+
+#.*\n		;
+
+.		{ return (*yytext); }
+%%
diff --git a/krb5-1-6/src/util/et/et_name.c b/krb5-1-6/src/util/et/et_name.c
new file mode 100644
index 000000000..64923c998
--- /dev/null
+++ b/krb5-1-6/src/util/et/et_name.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 1997 by Massachusetts Institute of Technology
+ * 
+ * Copyright 1987 by MIT Student Information Processing Board
+ *
+ * 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include "com_err.h"
+#include "error_table.h"
+
+static const char char_set[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+const char *
+error_table_name_r (unsigned long num,
+		    /*@out@*/ /*@returned@*/ char *outbuf)
+     /*@modifies outbuf@*/
+{
+	long ch;
+	int i;
+	/*@out@*/ char *p;
+
+	p = outbuf;
+	num >>= ERRCODE_RANGE;
+
+	for (i = 3; i >= 0; i--) {
+		ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
+		if (ch != 0)
+			*p++ = char_set[ch-1];
+	}
+	*p = '\0';
+	return(outbuf);
+}
+
+/*@observer@*/
+const char * error_table_name(unsigned long num)
+     /*@modifies internalState@*/
+{
+	static char buf[6];
+
+	return error_table_name_r(num, buf);
+}
diff --git a/krb5-1-6/src/util/et/init_et.c b/krb5-1-6/src/util/et/init_et.c
new file mode 100644
index 000000000..b0a406403
--- /dev/null
+++ b/krb5-1-6/src/util/et/init_et.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 1997 by Massachusetts Institute of Technology
+ * 
+ * Copyright 1986, 1987, 1988 by MIT Student Information Processing Board
+ *
+ * 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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "com_err.h"
+#include "error_table.h"
+
+#if 0
+/*
+ * XXX This function is provided without any prototypes in the public
+ * interface, and isn't used internally.  It's probably safe to make
+ * it go away.
+ */
+struct foobar {
+    struct et_list etl;
+    struct error_table et;
+};
+
+int init_error_table(msgs, base, count)
+    const char * const * msgs;
+    int base;
+    int count;
+{
+    struct foobar * new_et;
+
+    if (!base || !count || !msgs)
+	return 0;
+
+    new_et = (struct foobar *) malloc(sizeof(struct foobar));
+    if (!new_et)
+	return errno;	/* oops */
+    new_et->etl.table = &new_et->et;
+    new_et->et.msgs = msgs;
+    new_et->et.base = base;
+    new_et->et.n_msgs= count;
+
+    new_et->etl.next = _et_list;
+    _et_list = &new_et->etl;
+    return 0;
+}
+
+extern errcode_t KRB5_CALLCONV et_init(ectx)
+	et_ctx *ectx;
+{
+	struct et_context *ctx;
+
+	ctx = malloc(sizeof(struct et_context));
+	if (!ctx)
+		return ENOMEM;
+	ctx->tables = 0;
+	ctx->hook_func = 0;
+	ctx->hook_func_data = 0;
+	
+	*ectx = ctx;
+	return 0;
+}
+
+extern void KRB5_CALLCONV et_shutdown(ectx)
+	et_ctx ectx;	
+{
+	struct et_list *p, *n;
+
+	p = ectx->tables;
+	while (p) {
+		n = p->next;
+		free(p);
+		p = n;
+	}
+	free(ectx);
+}
+
+extern errcode_t KRB5_CALLCONV et_add_error_table(ectx, tbl)
+	et_ctx ectx;
+	struct error_table *tbl;
+{
+	struct et_list *e;
+
+	e = malloc(sizeof(struct et_list));
+	if (!e)
+		return ENOMEM;
+	
+	e->table = tbl;
+	e->next = ectx->tables;
+	ectx->tables = e;
+	
+	return 0;
+}
+
+#endif
diff --git a/krb5-1-6/src/util/et/internal.h b/krb5-1-6/src/util/et/internal.h
new file mode 100644
index 000000000..57b5cd58e
--- /dev/null
+++ b/krb5-1-6/src/util/et/internal.h
@@ -0,0 +1,15 @@
+/*
+ * internal include file for com_err package
+ */
+#include "mit-sipb-copyright.h"
+
+#include <errno.h>
+
+#ifndef SYS_ERRLIST_DECLARED
+extern char const * const sys_errlist[];
+extern const int sys_nerr;
+#endif
+
+#if defined(__STDC__) && !defined(HDR_HAS_PERROR) && !defined(WIN32)
+void perror (const char *);
+#endif
diff --git a/krb5-1-6/src/util/et/libcom_err.exports b/krb5-1-6/src/util/et/libcom_err.exports
new file mode 100644
index 000000000..ea8f32d5f
--- /dev/null
+++ b/krb5-1-6/src/util/et/libcom_err.exports
@@ -0,0 +1,9 @@
+add_error_table
+com_err
+com_err_va
+error_message
+error_table_name
+error_table_name_r
+remove_error_table
+reset_com_err_hook
+set_com_err_hook
diff --git a/krb5-1-6/src/util/et/mit-sipb-copyright.h b/krb5-1-6/src/util/et/mit-sipb-copyright.h
new file mode 100644
index 000000000..d7c4ee096
--- /dev/null
+++ b/krb5-1-6/src/util/et/mit-sipb-copyright.h
@@ -0,0 +1,22 @@
+/*
+
+Copyright 1987, 1988 by the Student Information Processing Board
+	of the Massachusetts Institute of Technology
+
+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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+Furthermore if you modify this software you must label
+your software as modified software and not distribute it in such a
+fashion that it might be confused with the original M.I.T. software.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose.  It is
+provided "as is" without express or implied warranty.
+
+*/
+
diff --git a/krb5-1-6/src/util/et/t_com_err.c b/krb5-1-6/src/util/et/t_com_err.c
new file mode 100644
index 000000000..2cba3cfdc
--- /dev/null
+++ b/krb5-1-6/src/util/et/t_com_err.c
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "com_err.h"
+#include "et1.h"
+#include "et2.h"
+
+int misc_err, known_err;	/* known_err is err in whether or not
+                                   table is 'known' to library */
+int fail;
+
+static void
+try_one (errcode_t code, int known, int table, int msgno)
+{
+    const char *msg = error_message (code);
+    char buffy[1024];
+
+    sprintf (buffy, "error table %d message %d", table, msgno);
+    if (0 == strcmp (buffy, msg)) {
+	if (!known) {
+	    known_err++;
+	}
+	return;
+    }
+    sprintf (buffy, "Unknown code et%d %d", table, msgno);
+    if (!strcmp (buffy, msg)) {
+	if (known)
+	    known_err++;
+	return;
+    }
+    printf ("error code %ld got unrecognized message '%s',\n"
+	    "should have been table %d message %d\n",
+	    (long) code, msg, table, msgno);
+    misc_err++;
+}
+
+static void
+try_table (int table, int known, int lineno,
+	   errcode_t c0, errcode_t c1, errcode_t c2)
+{
+    try_one (c0, known, table, 0);
+    try_one (c1, known, table, 1);
+    try_one (c2, known, table, 2);
+    if (misc_err != 0 || known_err != 0) {
+	fail++;
+	if (known_err)
+	    printf ("table list error from line %d, table %d\n", lineno,
+		    table);
+	if (misc_err)
+	    printf ("misc errors from line %d table %d\n", lineno, table);
+	misc_err = known_err = 0;
+    }
+}
+
+static void
+try_em_1 (int t1_known, int t2_known, int lineno)
+{
+    try_table (1, t1_known, lineno, ET1_M0, ET1_M1, ET1_M2);
+    try_table (2, t2_known, lineno, ET2_M0, ET2_M1, ET2_M2);
+}
+#define try_em(A,B) try_em_1(A,B,__LINE__)
+
+static void *run(/*@unused@*/ void *x)
+{
+    try_em (0, 0);
+    (void) add_error_table (&et_et1_error_table);
+    try_em (1, 0);
+    (void) add_error_table (&et_et2_error_table);
+    try_em (1, 1);
+    (void) remove_error_table (&et_et1_error_table);
+    try_em (0, 1);
+    (void) remove_error_table (&et_et1_error_table);
+    try_em (0, 1);
+    (void) remove_error_table (&et_et2_error_table);
+    try_em (0, 0);
+
+    initialize_et1_error_table ();
+    try_em (1, 0);
+    (void) add_error_table (&et_et1_error_table);
+    try_em (1, 0);
+    (void) remove_error_table (&et_et1_error_table);
+    try_em (1, 0);
+    (void) remove_error_table (&et_et1_error_table);
+    try_em (0, 0);
+
+    initialize_et1_error_table ();
+    try_em (1, 0);
+    (void) add_error_table (&et_et1_error_table);
+    try_em (1, 0);
+    (void) add_error_table (&et_et2_error_table);
+    try_em (1, 1);
+    (void) remove_error_table (&et_et1_error_table);
+    try_em (1, 1);
+    (void) remove_error_table (&et_et1_error_table);
+    try_em (0, 1);
+    (void) remove_error_table (&et_et2_error_table);
+    try_em (0, 0);
+    (void) remove_error_table (&et_et2_error_table);
+    try_em (0, 0);
+
+    (void) add_error_table (&et_et2_error_table);
+    try_em (0, 1);
+    initialize_et2_error_table ();
+    try_em (0, 1);
+    (void) add_error_table (&et_et1_error_table);
+    try_em (1, 1);
+    (void) remove_error_table (&et_et1_error_table);
+    try_em (0, 1);
+    (void) remove_error_table (&et_et2_error_table);
+    try_em (0, 1);
+    (void) remove_error_table (&et_et2_error_table);
+    try_em (0, 0);
+
+    return 0;
+}
+
+#ifdef TEST_THREADS
+#include <pthread.h>
+#endif
+
+int main (/*@unused@*/ int argc, /*@unused@*/ char *argv[])
+{
+#ifdef TEST_THREADS
+    pthread_t t;
+    int err;
+    void *t_retval;
+
+    err = pthread_create(&t, 0, run, 0);
+    if (err) {
+	fprintf(stderr, "pthread_create error: %s\n", strerror(err));
+	exit(1);
+    }
+    err = pthread_join(t, &t_retval);
+    if (err) {
+	fprintf(stderr, "pthread_join error: %s\n", strerror(err));
+	exit(1);
+    }
+    return fail;
+#else
+    run(0);
+    return fail;
+#endif
+}
diff --git a/krb5-1-6/src/util/et/test1.et b/krb5-1-6/src/util/et/test1.et
new file mode 100644
index 000000000..4c7b77f0e
--- /dev/null
+++ b/krb5-1-6/src/util/et/test1.et
@@ -0,0 +1,69 @@
+	error_table	krb
+
+	error_code	KRB_MK_AP_TKFIL,
+			"Can't read ticket file"
+
+	ec		KRB_MK_AP_NOTKT,
+			"Can't find ticket or TGT"
+
+	ec		KRB_MK_AP_TGTEXP,
+			"TGT expired"
+
+	ec		KRB_RD_AP_UNDEC,
+			"Can't decode authenticator"
+
+	ec		KRB_RD_AP_EXP,
+			"Ticket expired"
+
+	ec		KRB_RD_AP_REPEAT,
+			"Repeated request"
+
+	ec		KRB_RD_AP_NOT_US,
+			"The ticket isn't for us"
+
+	ec		KRB_RD_AP_INCON,
+			"Request is inconsistent"
+
+	ec		KRB_RD_AP_TIME,
+			"Delta-T too big"
+
+	ec		KRB_RD_AP_BADD,
+			"Incorrect net address"
+
+	ec		KRB_RD_AP_VERSION,
+			"Protocol version mismatch"
+
+	ec		KRB_RD_AP_MSG_TYPE,
+			"Invalid message type"
+
+	ec		KRB_RD_AP_MODIFIED,
+			"Message stream modified"
+
+	ec		KRB_RD_AP_ORDER,
+			"Message out of order"
+
+	ec		KRB_RD_AP_UNAUTHOR,
+			"Unauthorized request"
+
+	ec		KRB_GT_PW_NULL,
+			"Current password is null"
+
+	ec		KRB_GT_PW_BADPW,
+			"Incorrect current password"
+
+	ec		KRB_GT_PW_PROT,
+			"Protocol error"
+
+	ec		KRB_GT_PW_KDCERR,
+			"Error returned by KDC"
+
+	ec		KRB_GT_PW_NULLTKT,
+			"Null ticket returned by KDC"
+
+	ec		KRB_SKDC_RETRY,
+			"Retry count exceeded"
+
+	ec		KRB_SKDC_CANT,
+			"Can't send request"
+
+	end
diff --git a/krb5-1-6/src/util/et/test2.et b/krb5-1-6/src/util/et/test2.et
new file mode 100644
index 000000000..55ad74ead
--- /dev/null
+++ b/krb5-1-6/src/util/et/test2.et
@@ -0,0 +1,9 @@
+	error_table	quux
+
+	ec	FOO_ERR, "foo"
+
+	ec	BAR_ERR, "bar"
+
+	ec	BAZ_ERR, "meow"
+
+	end
diff --git a/krb5-1-6/src/util/et/test_et.c b/krb5-1-6/src/util/et/test_et.c
new file mode 100644
index 000000000..8bd88fcde
--- /dev/null
+++ b/krb5-1-6/src/util/et/test_et.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <errno.h>
+#include "com_err.h"
+#include "test1.h"
+#include "test2.h"
+#include "autoconf.h"
+
+#ifdef _WIN32
+# define EXPORT_LIST
+#endif
+
+/* XXX Not part of official public API.  */
+extern const char *error_table_name (errcode_t);
+
+#ifdef NEED_SYS_ERRLIST
+extern int sys_nerr;
+#endif
+
+int main()
+{
+	printf("Before initiating error table:\n\n");
+#ifndef EXPORT_LIST
+	printf("Table name '%s'\n", error_table_name(KRB_MK_AP_TGTEXP));
+	printf("UNIX  name '%s'\n", error_table_name(EPERM));
+#endif
+	printf("Msg TGT-expired is '%s'\n", error_message(KRB_MK_AP_TGTEXP));
+	printf("Msg EPERM is '%s'\n", error_message(EPERM));
+	printf("Msg FOO_ERR is '%s'\n", error_message(FOO_ERR));
+	printf("Msg 1002 is '%s'\n", error_message (1002));
+#ifdef HAVE_SYS_ERRLIST
+	printf("Msg {sys_nerr-1} is '%s'\n", error_message(sys_nerr-1));
+	printf("Msg {sys_nerr} is '%s'\n", error_message(sys_nerr));
+#endif
+	printf("Msg 0 is '%s'\n", error_message(0));
+
+	printf("With 0: tgt-expired -> %s\n", error_message(KRB_MK_AP_TGTEXP));
+
+	initialize_krb_error_table();
+#ifndef EXPORT_LIST
+	printf("KRB error table initialized:  base %ld (%s), name %s\n",
+	       ERROR_TABLE_BASE_krb, error_message(ERROR_TABLE_BASE_krb),
+	       error_table_name(ERROR_TABLE_BASE_krb));
+#else
+	printf("KRB error table initialized:  base %ld (%s)\n",
+	       ERROR_TABLE_BASE_krb, error_message(ERROR_TABLE_BASE_krb));
+#endif
+	add_error_table(&et_krb_error_table);
+	printf("With krb: tgt-expired -> %s\n",
+	       error_message(KRB_MK_AP_TGTEXP));
+
+	add_error_table(&et_quux_error_table);
+#ifndef EXPORT_LIST
+	printf("QUUX error table initialized: base %ld (%s), name %s\n",
+	       ERROR_TABLE_BASE_quux, error_message(ERROR_TABLE_BASE_quux),
+	       error_table_name(ERROR_TABLE_BASE_quux));
+#else
+	printf("QUUX error table initialized: base %ld (%s)\n",
+	       ERROR_TABLE_BASE_quux, error_message(ERROR_TABLE_BASE_quux));
+#endif
+
+	printf("Msg for TGT-expired is '%s'\n",
+	       error_message(KRB_MK_AP_TGTEXP));
+#ifdef HAVE_SYS_ERRLIST
+	printf("Msg {sys_nerr-1} is '%s'\n", error_message(sys_nerr-1));
+#endif
+	printf("Msg FOO_ERR is '%s'\n", error_message(FOO_ERR));
+	printf("Msg KRB_SKDC_CANT is '%s'\n",
+		    error_message(KRB_SKDC_CANT));
+	printf("Msg 1e6 (8B 64) is '%s'\n", error_message(1000000));
+	printf("\n\nCOM_ERR tests:\n");
+	com_err("whoami", FOO_ERR, (char *)NULL);
+	com_err("whoami", FOO_ERR, " -- message goes %s", "here");
+	com_err("whoami", 0, (char *)0);
+	com_err("whoami", 0, "error number %d\n", 0);
+	return 0;
+}
diff --git a/krb5-1-6/src/util/et/texinfo.tex b/krb5-1-6/src/util/et/texinfo.tex
new file mode 100644
index 000000000..eb29dfd7f
--- /dev/null
+++ b/krb5-1-6/src/util/et/texinfo.tex
@@ -0,0 +1,2077 @@
+%% TeX macros to handle texinfo files
+
+%   Copyright (C) 1985, 1986, 1988 Richard M. Stallman
+
+%		       NO WARRANTY
+
+%  BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+%NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
+%WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
+%RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
+%WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+%BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+%FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
+%AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
+%DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+%CORRECTION.
+
+% IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
+%STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
+%WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
+%LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
+%OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+%USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
+%DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
+%A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
+%PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+%DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
+
+%		GENERAL PUBLIC LICENSE TO COPY
+
+%  1. You may copy and distribute verbatim copies of this source file
+%as you receive it, in any medium, provided that you conspicuously
+%and appropriately publish on each copy a valid copyright notice
+%"Copyright (C) 1986 Richard M. Stallman"; and include
+%following the copyright notice a verbatim copy of the above disclaimer
+%of warranty and of this License.
+
+%  2. You may modify your copy or copies of this source file or
+%any portion of it, and copy and distribute such modifications under
+%the terms of Paragraph 1 above, provided that you also do the following:
+
+%    a) cause the modified files to carry prominent notices stating
+%    that you changed the files and the date of any change; and
+
+%    b) cause the whole of any work that you distribute or publish,
+%    that in whole or in part contains or is a derivative of this
+%    program or any part thereof, to be licensed at no charge to all
+%    third parties on terms identical to those contained in this
+%    License Agreement (except that you may choose to grant more extensive
+%    warranty protection to some or all third parties, at your option).
+
+%    c) You may charge a distribution fee for the physical act of
+%    transferring a copy, and you may at your option offer warranty
+%    protection in exchange for a fee.
+
+%Mere aggregation of another unrelated program with this program (or its
+%derivative) on a volume of a storage or distribution medium does not bring
+%the other program under the scope of these terms.
+
+%  3. You may copy and distribute this program (or a portion or derivative
+%of it, under Paragraph 2) in object code or executable form under the terms
+%of Paragraphs 1 and 2 above provided that you also do one of the following:
+
+%    a) accompany it with the complete corresponding machine-readable
+%    source code, which must be distributed under the terms of
+%    Paragraphs 1 and 2 above; or,
+
+%    b) accompany it with a written offer, valid for at least three
+%    years, to give any third party free (except for a nominal
+%    shipping charge) a complete machine-readable copy of the
+%    corresponding source code, to be distributed under the terms of
+%    Paragraphs 1 and 2 above; or,
+
+%    c) accompany it with the information you received as to where the
+%    corresponding source code may be obtained.  (This alternative is
+%    allowed only for noncommercial distribution and only if you
+%    received the program in object code or executable form alone.)
+
+%For an executable file, complete source code means all the source code for
+%all modules it contains; but, as a special exception, it need not include
+%source code for modules which are standard libraries that accompany the
+%operating system on which the executable file runs.
+
+%  4. You may not copy, sublicense, distribute or transfer this program
+%except as expressly provided under this License Agreement.  Any attempt
+%otherwise to copy, sublicense, distribute or transfer this program is void and
+%your rights to use the program under this License agreement shall be
+%automatically terminated.  However, parties who have received computer
+%software programs from you with this License Agreement will not have
+%their licenses terminated so long as such parties remain in full compliance.
+
+%  5. If you wish to incorporate parts of this program into other free
+%programs whose distribution conditions are different, write to the Free
+%Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
+%worked out a simple rule that can be stated here, but we will often permit
+%this.  We will be guided by the two goals of preserving the free status of
+%all derivatives of our free software and of promoting the sharing and reuse of
+%software.
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them.   Help stamp out software-hoarding!
+
+\def\texinfoversion{1.18}
+\message{Loading texinfo package [Version \texinfoversion]:}
+\message{}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ }     % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset  \bindingoffset=0pt
+\newdimen \normaloffset   \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+%---------------------Begin change-----------------------
+%
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt	% These set size of cropmarks
+\outerhsize=7in
+\outervsize=9.5in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument.  Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255  \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno  \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+ {\let\hsize=\pagewidth \makefootline}}
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box.  (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+		 \shipout
+		 \vbox to \outervsize{\hsize=\outerhsize
+                 \vbox{\line{\ewtop\hfill\ewtop}}
+                 \nointerlineskip
+                 \line{\vbox{\moveleft\cornerthick\nstop}
+                       \hfill
+                       \vbox{\moveright\cornerthick\nstop}}
+                 \vskip \topandbottommargin
+                 \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+			\vbox{
+			{\let\hsize=\pagewidth \makeheadline}
+			\pagebody{#1}
+			{\let\hsize=\pagewidth \makefootline}}
+			\ifodd\pageno\else\hskip\bindingoffset\fi}
+		 \vskip \topandbottommargin plus1fill minus1fill
+                 \boxmaxdepth\cornerthick
+                 \line{\vbox{\moveleft\cornerthick\nsbot}
+                       \hfill
+                       \vbox{\moveright\cornerthick\nsbot}}
+                 \nointerlineskip
+                 \vbox{\line{\ewbot\hfill\ewbot}}
+	}
+  \advancepageno 
+  \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks.  Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.
+% The argument can be delimited with [...] or with "..." or braces
+% or it can be a whole line.
+% #1 should be a macro which expects
+% an ordinary undelimited TeX argument.
+
+\def\parsearg #1{\let\next=#1\begingroup\obeylines\futurelet\temp\parseargx}
+
+\def\parseargx{%
+\ifx \obeyedspace\temp \aftergroup\parseargdiscardspace \else%
+\aftergroup \parseargline %
+\fi \endgroup}
+
+{\obeyspaces %
+\gdef\parseargdiscardspace {\begingroup\obeylines\futurelet\temp\parseargx}}
+
+\gdef\obeyedspace{\ }
+
+\def\parseargline{\begingroup \obeylines \parsearglinex}
+{\obeylines %
+\gdef\parsearglinex #1^^M{\endgroup \next {#1}}}
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment.  Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo  is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+%% @end foo executes the definition of \Efoo.
+%% foo can be delimited by doublequotes or brackets.
+
+\def\end{\parsearg\endxxx}
+
+\def\endxxx #1{%
+\expandafter\ifx\csname E#1\endcsname\relax
+\expandafter\ifx\csname #1\endcsname\relax
+\errmessage{Undefined command @end #1}\else
+\errorE{#1}\fi\fi
+\csname E#1\endcsname}
+\def\errorE#1{
+{\errhelp=\EMsimple \errmessage{@end #1 not within #1 environment}}}
+
+% Single-spacing is done by various environments.
+
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+{\advance \baselineskip by -\singlespaceskip
+\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\sf \char '100}}
+
+% Define @` and @' to be the same as ` and '
+% but suppressing ligatures.
+\def\`{{`}}
+\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break
+\def\w #1{\hbox{#1}}
+
+% @group ... @end group  forces ... to be all on one page.
+
+\def\group{\begingroup% \inENV ???
+\def \Egroup{\egroup\endgroup}
+\vbox\bgroup}
+
+% @br   forces paragraph break
+
+\let\br = \par
+
+% @dots{}  output some dots
+
+\def\dots{$\ldots$}
+
+% @page    forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+\def\exdent{\errmessage{@exdent in filled text}}
+  % @lisp, etc, define \exdent locally from \internalexdent
+
+{\obeyspaces
+\gdef\internalexdent{\parsearg\exdentzzz}}
+
+\def\exdentzzz #1{{\advance \leftskip by -\lispnarrowing
+\advance \hsize by -\leftskip
+\advance \hsize by -\rightskip
+\leftline{{\rm#1}}}}
+
+% @include file    insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+\def\includezzz #1{{\def\thisfile{#1}\input #1
+}}
+
+\def\thisfile{}
+
+% @center line   outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n   outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore  is another way to write a comment
+
+\def\comment{\parsearg \commentxxx}
+
+\def\commentxxx #1{}
+
+\let\c=\comment
+
+\long\def\ignore #1\end ignore{}
+
+\outer\def\ifset{\parsearg\ifsetxxx}
+
+\def\ifsetxxx #1#2\end ifset{%
+\expandafter\ifx\csname IF#1\endcsname\relax \else #2\fi}
+
+\outer\def\ifclear{\parsearg\ifclearxxx}
+
+\def\ifclearxxx #1#2\end ifclear{%
+\expandafter\ifx\csname IF#1\endcsname\relax #2\fi}
+
+% Some texinfo constructs that are trivial in tex
+
+\def\iftex{}
+\def\Eiftex{}
+\long\def\ifinfo #1\end ifinfo{}
+\long\def\menu #1\end menu{}
+\def\asis#1{#1}
+
+\def\node{\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+\let\setfilename=\comment
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\losespace#3{}}, node `\losespace#1{}'}
+\def\losespace #1{#1}
+
+\message{fonts,}
+
+% Font-change commands.
+
+%% Try out Computer Modern fonts at \magstephalf
+\font\tenrm=cmr10 scaled \magstephalf
+\font\tentt=cmtt10 scaled \magstephalf
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\tenbf=cmb10 scaled \magstephalf 
+\font\tenit=cmti10 scaled \magstephalf
+\font\tensl=cmsl10 scaled \magstephalf
+\font\tensf=cmss10 scaled \magstephalf
+\def\li{\sf}
+\font\tensc=cmcsc10 scaled \magstephalf
+
+% Fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\let\deftt=\tentt
+\def\df{\let\tt=\deftt \defbf}
+
+% Font for title
+\font\titlerm = cmbx10 scaled \magstep5
+
+% Fonts for indices
+\font\indit=cmti9 \font\indrm=cmr9
+\def\indbf{\indrm} \def\indsl{\indit}
+\def\indexfonts{\let\it=\indit \let\sl=\indsl \let\bf=\indbf \let\rm=\indrm}
+
+% Fonts for headings
+\font\chaprm=cmbx10 scaled \magstep3
+\font\chapit=cmti10 scaled \magstep3
+\font\chapsl=cmsl10 scaled \magstep3
+\font\chaptt=cmtt10 scaled \magstep3
+\font\chapsf=cmss10 scaled \magstep3
+\let\chapbf=\chaprm
+
+\font\secrm=cmbx10 scaled \magstep2
+\font\secit=cmti10 scaled \magstep2
+\font\secsl=cmsl10 scaled \magstep2
+\font\sectt=cmtt10 scaled \magstep2
+\font\secsf=cmss10 scaled \magstep2
+\let\secbf=\secrm
+
+\font\ssecrm=cmbx10 scaled \magstep1
+\font\ssecit=cmti10 scaled \magstep1
+\font\ssecsl=cmsl10 scaled \magstep1
+\font\ssectt=cmtt10 scaled \magstep1
+\font\ssecsf=cmss10 scaled \magstep1
+\let\ssecbf=\ssecrm
+
+\def\textfonts{\let\rm=\tenrm\let\it=\tenit\let\sl=\tensl\let\bf=\tenbf%
+\let\sc=\tensc\let\sf=\tensf}
+\def\chapfonts{\let\rm=\chaprm\let\it=\chapit\let\sl=\chapsl\let\bf=\chapbf\let\tt=\chaptt\let\sf=\chapsf}
+\def\secfonts{\let\rm=\secrm\let\it=\secit\let\sl=\secsl\let\bf=\secbf\let\tt=\sectt\let\sf=\secsf}
+\def\subsecfonts{\let\rm=\ssecrm\let\it=\ssecit\let\sl=\ssecsl\let\bf=\ssecbf\let\tt=\ssectt\let\sf=\ssecsf}
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+\def\i#1{{\sl #1}}
+\let\var=\i
+\let\dfn=\i
+\let\emph=\i
+\let\cite=\i
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+\def\t#1{{\tt \rawbackslash \frenchspacing #1}\null}
+\let\ttfont = \t
+\let\kbd=\t
+\let\code=\t
+\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\key #1{{\tt \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+\def\l#1{{\li #1}\null}
+
+\def\r#1{{\rm #1}}
+\def\s#1{{\sc #1}}
+\def\ii#1{{\it #1}}
+
+\def\titlefont#1{{\titlerm #1}}
+
+\def\titlepage{\begingroup \parindent=0pt \hbox{}%
+\let\oldpage=\page
+\def\page{\oldpage \hbox{}}}
+
+\def\Etitlepage{\endgroup\page\HEADINGSon}
+
+% Make altmode in file print out right
+
+\catcode `\^^[=\active \def^^[{$\diamondsuit$}
+
+\message{page headings,}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline    % Token sequence for heading line of even pages
+\newtoks \oddheadline     % Token sequence for heading line of odd pages
+\newtoks \evenfootline    % Token sequence for footing line of even pages
+\newtoks \oddfootline     % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}}
+
+% Commands to set those variables.
+% For example, this is what  @headings on  does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings on   turns them on.
+% @headings off  turns them off.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1,
+% Put current file name in lower left corner,
+% Put chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSon{
+\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line...  specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% Tables -- @table, @ftable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent  \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin  \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table and @ftable define @item, @itemx, etc., with these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}\itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}\itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+\advance \hsize by -\rightskip %
+\advance \hsize by -\leftskip %
+\setbox0=\hbox{\itemfont{#1}}%
+\itemindex{#1}%
+\parskip=0in %
+\noindent %
+\ifdim \wd0>\itemmax %
+\vadjust{\penalty 10000}%
+\hbox to \hsize{\hskip -\tableindent\box0\hss}\ %
+\else %
+\hbox to 0pt{\hskip -\tableindent\box0\hss}%
+\fi %
+\endgroup %
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1        \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1        \endtabley}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\endgroup\afterenvbreak}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{\itemizey {#1}{\Eitemize}}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\begingroup %
+\itemno = 0 %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\endgroup\afterenvbreak}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+\def\enumerate{\itemizey{\the\itemno.}\Eenumerate\flushcr}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 300}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that	accumulates this index.  The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1	% Open the file
+\expandafter\xdef\csname#1index\endcsname{%	% Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo  ==  \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1	% Open the file
+\expandafter\xdef\csname#1index\endcsname{%	% Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar    makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\xdef\csname#1index\endcsname{%	% Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\xdef\csname#1index\endcsname{%	% Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+%  and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexnofonts{%
+\let\code=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0  %overridden during \printindex.
+
+\def\doind #1#2{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry.  We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry.  We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+\penalty\count10}}
+
+% The index entry written in the file actually looks like
+%  \entry {sortstring}{page}{topic}
+% or
+%  \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+%  \initial {c}
+%     before the first topic whose initial is c
+%  \entry {topic}{pagelist}
+%     for a topic that is used without subtopics
+%  \primary {topic}
+%     for the beginning of a topic that is used with subtopics
+%  \secondary {subtopic}{pagelist}
+%     for each subtopic.
+
+% Define the user-accessible indexing commands 
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{\tex %
+\catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+\catcode`\$=\other\catcode`\_=\other
+\catcode`\~=\other
+\def\indexbackslash{\rawbackslashxx}
+\indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+\begindoublecolumns
+\openin 1 \jobname.#1s
+\ifeof 1 \else \closein 1 \input \jobname.#1s
+\fi
+\enddoublecolumns
+\Etex}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\outer\def\initial #1{%
+{\let\tentt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty3000}}
+
+\outer\def\entry #1#2{
+{\parfillskip=0in \parskip=0in \parindent=0in
+\hangindent=1in \hangafter=1%
+\noindent\hbox{#1}\leaders\Dotsbox\hskip 0pt plus 1filll #2\par
+}}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\leaders\Dotsbox\hskip 0pt plus 1filll#2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXBook, page 416
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize  \doublecolumnhsize = 3.11in
+\newdimen\doublecolumnvsize  \doublecolumnvsize = 19.1in
+
+\def\begindoublecolumns{\begingroup
+  \output={\global\setbox\partialpage=\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}\eject
+  \output={\doublecolumnout} \hsize=\doublecolumnhsize \vsize=\doublecolumnvsize}
+\def\enddoublecolumns{\output={\balancecolumns}\eject
+  \endgroup \pagegoal=\vsize}
+
+\def\doublecolumnout{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+  \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+  \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+  \onepageout\pagesofar \unvbox255 \penalty\outputpenalty}
+\def\pagesofar{\unvbox\partialpage %
+  \hsize=\doublecolumnhsize % have to restore this since output routine
+%	      changes it to set cropmarks (P. A. MacKay, 12 Nov. 1986)
+  \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\balancecolumns{\setbox0=\vbox{\unvbox255} \dimen@=\ht0
+  \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+  \divide\dimen@ by2 \splittopskip=\topskip
+  {\vbadness=10000 \loop \global\setbox3=\copy0
+    \global\setbox1=\vsplit3 to\dimen@
+    \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}
+  \setbox0=\vbox to\dimen@{\unvbox1}  \setbox2=\vbox to\dimen@{\unvbox3}
+  \pagesofar}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno
+\newcount \subsecno
+\newcount \subsubsecno
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno  \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+\openout \contentsfile = \jobname.toc
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it.  @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\outer\def\chapter{\parsearg\chapterzzz}
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0 \global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}\gdef\thischapter{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\donoderef %
+}
+
+\outer\def\appendix{\parsearg\appendixzzz}
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0 \global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash chapentry {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\unnumbnoderef %
+}
+
+\outer\def\unnumbered{\parsearg\unnumberedzzz}
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0 \message{(#1)}
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\unnumbnoderef %
+}
+
+\outer\def\section{\parsearg\sectionzzz}
+\def\sectionzzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}
+
+\outer\def\appendixsection{\parsearg\appendixsectionzzz}
+\outer\def\appendixsec{\parsearg\appendixsectionzzz}
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedseczzz}
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\subsection{\parsearg\subsectionzzz}
+\def\subsectionzzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubseczzz}
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\subsubsection{\parsearg\subsubsectionzzz}
+\def\subsubsectionzzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsubsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%\
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubseczzz}
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%\
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}
+
+% Define @majorheading, @heading and @subheading
+
+\outer\def\majorheading #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 200}
+
+\outer\def\chapheading #1{\chapbreak %
+{\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 200}
+
+\let\heading=\secheadingi
+\let\subheading=\subsecheadingi
+\let\subsubheading=\subsubsecheadingi
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+\pchapsepmacro %
+{\chapfonts \line{\chaprm #2.\enspace #1\hfill}}\bigskip \par\penalty 5000 %
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \line{\chaprm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip  \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip  \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \line{\secrm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsecheading #1#2#3#4{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\secfonts \line{\secrm#2.#3.#4\enspace #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change
+
+\def\subsubsecheading #1#2#3#4#5{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\secfonts \line{\secrm#2.#3.#4.#5\enspace #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+\message{toc printing,}
+
+\def\Dotsbox{\hbox to 1em{\hss.\hss}} % Used by index macros
+
+\def\finishcontents{%
+\ifnum\pageno>0 %
+\pagealignmacro %
+\immediate\closeout \contentsfile%
+\pageno=-1		% Request roman numbered pages
+\fi}
+
+\outer\def\contents{%
+\finishcontents %
+\unnumbchapmacro{Table of Contents}
+\def\thischapter{Table of Contents}
+{\catcode`\\=0
+\catcode`\{=1		% Set up to handle contents files properly
+\catcode`\}=2
+\catcode`\@=11
+\input \jobname.toc
+}
+\vfill \eject}
+
+\outer\def\summarycontents{%
+\finishcontents %
+\unnumbchapmacro{Summary Table of Contents}
+\def\thischapter{Summary Table of Contents}
+{\catcode`\\=0
+\catcode`\{=1		% Set up to handle contents files properly
+\catcode`\}=2
+\catcode`\@=11
+\def\smallbreak{}
+\def\secentry ##1##2##3##4{}
+\def\subsecentry ##1##2##3##4##5{}
+\def\subsubsecentry ##1##2##3##4##5##6{}
+\def\unnumbsecentry ##1##2{}
+\def\unnumbsubsecentry ##1##2{}
+\def\unnumbsubsubsecentry ##1##2{}
+\let\medbreak=\smallbreak
+\input \jobname.toc
+}
+\vfill \eject}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+% These macros generate individual entries in the table of contents
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+\def\chapentry #1#2#3{%
+\medbreak
+\line{#2.\space#1\leaders\hbox to 1em{\hss.\hss}\hfill #3}
+}
+
+\def\unnumbchapentry #1#2{%
+\medbreak
+\line{#1\leaders\Dotsbox\hfill #2}
+}
+
+\def\secentry #1#2#3#4{%
+\line{\enspace\enspace#2.#3\space#1\leaders\Dotsbox\hfill#4}
+}
+
+\def\unnumbsecentry #1#2{%
+\line{\enspace\enspace#1\leaders\Dotsbox\hfill #2}
+}
+
+\def\subsecentry #1#2#3#4#5{%
+\line{\enspace\enspace\enspace\enspace
+#2.#3.#4\space#1\leaders\Dotsbox\hfill #5}
+}
+
+\def\unnumbsubsecentry #1#2{%
+\line{\enspace\enspace\enspace\enspace#1\leaders\Dotsbox\hfill #2}
+}
+
+\def\subsubsecentry #1#2#3#4#5#6{%
+\line{\enspace\enspace\enspace\enspace\enspace\enspace
+#2.#3.#4.#5\space#1\leaders\Dotsbox\hfill #6}
+}
+
+\def\unnumbsubsubsecentry #1#2{%
+\line{\enspace\enspace\enspace\enspace\enspace\enspace#1\leaders\Dotsbox\hfill #2}
+}
+
+\message{environments,}
+
+% @tex ... @end tex    escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode`\"=12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\def\@={@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^M gets inside @lisp
+% phr: changed space to \null, to avoid overfull hbox problems.
+{\obeyspaces%
+\gdef\lisppar{\null\endgraf}}
+
+% Cause \obeyspaces to make each Space cause a word-separation
+% rather than the default which is that it acts punctuation.
+% This is because space in tt font looks funny.
+{\obeyspaces %
+\gdef\sepspaces{\def {\ }}}
+
+\newskip\aboveenvskipamount \aboveenvskipamount= 0pt
+\def\aboveenvbreak{{\advance\aboveenvskipamount by \parskip
+\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}}
+
+\def\afterenvbreak{\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}
+
+\def\lisp{\aboveenvbreak\begingroup\inENV %This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Elisp{\endgroup\afterenvbreak}%
+\parskip=0pt \advance \rightskip by \lispnarrowing 
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \tt \rawbackslash
+\def\next##1{}\next}
+
+
+\let\example=\lisp
+\def\Eexample{\Elisp}
+
+\let\smallexample=\lisp
+\def\Esmallexample{\Elisp}
+
+% Macro for 9 pt. examples, necessary to print with 5" lines.
+% From Pavel@xerox.  This is not really used unless the
+% @smallbook command is given.
+
+\def\smalllispx{\aboveenvbreak\begingroup\inENV
+%			This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Esmalllisp{\endgroup\afterenvbreak}%
+\parskip=0pt \advance \rightskip by \lispnarrowing 
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \ninett \rawbackslash
+\def\next##1{}\next}
+
+% This is @display; same as @lisp except use roman font.
+
+\def\display{\begingroup\inENV %This group ends at the end of the @display body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Edisplay{\endgroup\afterenvbreak}%
+\parskip=0pt \advance \rightskip by \lispnarrowing 
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% This is @format; same as @lisp except use roman font and don't narrow margins
+
+\def\format{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Eformat{\endgroup\afterenvbreak}
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @flushleft and @flushright
+
+\def\flushleft{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushleft{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+\def\flushright{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushright{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\advance \leftskip by 0pt plus 1fill
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @quotation - narrow the margins.
+
+\def\quotation{\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt  % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\def\Equotation{\par\endgroup\afterenvbreak}%
+\advance \rightskip by \lispnarrowing 
+\advance \leftskip by \lispnarrowing}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=36pt
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text.  This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\tt\char`\[}} \def\rbrb{{\tt\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+\leftskip = 0in  %
+\noindent        %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1     %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}%
+\tolerance=10000 \hbadness=10000    % Make all lines underfull and no complaints
+{\df #1}\enskip        % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+%    such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in \leftskip=\defbodyindent %
+\begingroup\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in \leftskip=\defbodyindent %
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+%  the first is all of #2 before the space token,
+%  the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl #1%
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\endgraf\vskip -\parskip \penalty 10000}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special form}%
+\defunargs {#2}\endgroup %
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defmethparsebody\Edefop\defopx\defopheader}
+
+\def\defopheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Operation on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defmethparsebody\Edefcv\defcvx\defcvheader}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defmethparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\vskip -\parskip \penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defmethparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\defmethparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+% \xref and \pxref generate cross references to specified points.
+
+\def\pxref #1{see \xrefX [#1,,,,,,,]}
+\def\xref #1{See \xrefX [#1,,,,,,,]}
+\def\xrefX [#1,#2,#3,#4,#5,#6]{%
+\setbox1=\hbox{\i{\losespace#5{}}}%
+\setbox0=\hbox{\losespace#3{}}%
+\ifdim \wd0 =0pt \setbox0=\hbox{\losespace#1{}}\fi%
+\ifdim \wd1 >0pt%
+section \unhbox0{} in \unhbox1%
+\else%
+\refx{#1-snt} [\unhbox0], page\tie \refx{#1-pg}%
+\fi }
+
+% \dosetq is the interface for calls from other macros
+
+\def\dosetq #1#2{{\let\folio=0%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Define @refx to reference a specific cross-reference string.
+
+\def\refx#1{%
+{%
+\expandafter\ifx\csname X#1\endcsname\relax
+% If not defined, say something at least.
+\expandafter\gdef\csname X#1\endcsname {$<$undefined$>$}%
+\message {WARNING: Cross-reference "#1" used but not yet defined}%
+\message {}%
+\fi %
+\csname X#1\endcsname %It's defined, so just use it.
+}}
+
+% Read the last existing aux file, if any.  No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+{
+\catcode `\^^@=\other
+\catcode `\^^A=\other
+\catcode `\^^B=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\^^K=\other
+\catcode `\^^L=\other
+\catcode `\^^N=\other
+\catcode `\^^O=\other
+\catcode `\^^P=\other
+\catcode `\^^Q=\other
+\catcode `\^^R=\other
+\catcode `\^^S=\other
+\catcode `\^^T=\other
+\catcode `\^^U=\other
+\catcode `\^^V=\other
+\catcode `\^^W=\other
+\catcode `\^^X=\other
+\catcode `\^^Y=\other
+\catcode `\^^Z=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+
+'openin 1 'jobname.aux
+'ifeof 1 'else 'closein 1 'input 'jobname.aux
+'fi
+}
+
+% Open the new aux file.  Tex will close it automatically at exit.
+
+\openout \auxfile=\jobname.aux
+
+% Footnotes.
+
+\newcount \footnoteno
+
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+\gdef\footnote{\global\advance \footnoteno by \@ne
+\edef\thisfootno{$^{\the\footnoteno}$}%
+\let\@sf\empty
+\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+\thisfootno\@sf\parsearg\footnotezzz}
+
+\gdef\footnotezzz #1{\insert\footins{
+\interlinepenalty\interfootnotelinepenalty
+\splittopskip\ht\strutbox % top baseline for broken footnotes
+\splitmaxdepth\dp\strutbox \floatingpenalty\@MM
+\leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
+\footstrut\hang\textindent{\thisfootno}#1\strut}}
+
+}%end \catcode `\@=11
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\newindex{cp}
+\newcodeindex{fn}
+\newcodeindex{vr}
+\newcodeindex{tp}
+\newcodeindex{ky}
+\newcodeindex{pg}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+\hsize = 6.5in
+\parindent 15pt
+\parskip 18pt plus 1pt
+\baselineskip 15pt
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Use @smallbook to reset parameters for 7x9.5 format
+\def\smallbook{
+\global\lispnarrowing = 0.3in
+\global\baselineskip 12pt
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\doublecolumnhsize=2.4in \global\doublecolumnvsize=15.0in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+\global\font\ninett=cmtt9
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+%% For a final copy, take out the rectangles
+%% that mark overfull boxes (in case you have decided
+%% that the text looks ok even though it passes the margin).
+\def\finalout{\overfullrule=0pt}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary)
+% Define certain chars to be always in tt font.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+\catcode`\_=\active
+\def_{{\tt \char '137}}
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+{\catcode`\\=\other
+@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+%% These look ok in all fonts, so just make them not special.  The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+\catcode`\$=\other \catcode`\%=\other \catcode`\&=\other \catcode`\#=\other
+
+\catcode 17=0   @c Define control-q
+\catcode`\\=\active
+@let\=@normalbackslash
+
+@textfonts
+@rm
diff --git a/krb5-1-6/src/util/et/vfprintf.c b/krb5-1-6/src/util/et/vfprintf.c
new file mode 100644
index 000000000..cad291602
--- /dev/null
+++ b/krb5-1-6/src/util/et/vfprintf.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)vfprintf.c	5.2 (Berkeley) 6/27/88 */
+
+#include <stdio.h>
+#if defined(HAVE_STDARG_H) || defined(_WIN32)
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#define VARARGS
+#endif
+
+int
+vfprintf(iop, fmt, ap)
+	FILE *iop;
+	char *fmt;
+	va_list ap;
+{
+	int len;
+	char localbuf[BUFSIZ];
+
+	if (iop->_flag & _IONBF) {
+		iop->_flag &= ~_IONBF;
+		iop->_ptr = iop->_base = localbuf;
+		len = _doprnt(fmt, ap, iop);
+		(void) fflush(iop);
+		iop->_flag |= _IONBF;
+		iop->_base = NULL;
+		iop->_bufsiz = 0;
+		iop->_cnt = 0;
+	} else
+		len = _doprnt(fmt, ap, iop);
+
+	return (ferror(iop) ? EOF : len);
+}
diff --git a/krb5-1-6/src/util/exitsleep.c b/krb5-1-6/src/util/exitsleep.c
new file mode 100644
index 000000000..95232e5b3
--- /dev/null
+++ b/krb5-1-6/src/util/exitsleep.c
@@ -0,0 +1,47 @@
+/*
+ * util/exitsleep.c
+ *
+ * Copyright (C) 2003 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Kludge to sleep 100ms prior to exit on Solaris 9 to work around a
+ * pty bug.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <link.h>
+
+void
+exit(int status)
+{
+    void (*realexit)(int);
+    struct timeval tv;
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 100000;
+    realexit = (void (*)(int))dlsym(RTLD_NEXT, "exit");
+    select(0, 0, 0, 0, &tv);
+    realexit(status);
+}
diff --git a/krb5-1-6/src/util/export-check.pl b/krb5-1-6/src/util/export-check.pl
new file mode 100755
index 000000000..ff2c6e037
--- /dev/null
+++ b/krb5-1-6/src/util/export-check.pl
@@ -0,0 +1,79 @@
+#
+
+# Copyright 2006 Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+#
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+#
+
+$0 =~ s/^.*?([\w.-]+)$/$1/;
+
+# The real stuff.
+
+# Args: exportlist libfoo.so
+
+# This code assumes the GNU version of nm.
+# For now, we'll only run it on GNU/Linux systems, so that's okay.
+
+if ($#ARGV != 1) {
+    die "usage: $0 exportfile libfoo.so\n";
+}
+my($exfile, $libfile) = @ARGV;
+
+@missing = ();
+open NM, "nm -Dg --defined-only $libfile |" || die "can't run nm on $libfile: $!";
+open EXPORT, "< $exfile" || die "can't read $exfile: $!";
+
+@export = <EXPORT>;
+map chop, @export;
+@export = sort @export;
+
+@found = ();
+while (<NM>) {
+    chop;
+    s/^[0-9a-fA-F]+ +//;
+    next if /^A /;
+    if (!/^[TDRBGS] /) {
+	unlink $libfile;
+	die "not sure what to do with '$_'";
+    }
+    s/^[TDRBGS] +//;
+    push @found, $_;
+}
+@found = sort @found;
+while ($#export >= 0 && $#found >= 0) {
+    if ($export[0] eq $found[0]) {
+#	print "ok $export[0]\n";
+	shift @export;
+	shift @found;
+    } elsif ($export[0] lt $found[0]) {
+	push @missing, shift @export;
+    } else {
+	# Ignore added symbols, for now.
+	shift @found;
+    }
+}
+if ($#export >= 0) { @missing = (@missing, @export); }
+if ($#missing >= 0) {
+    print STDERR "Missing symbols:\n\t", join("\n\t", @missing), "\n";
+#    unlink $libfile;
+    exit(1);
+}
+exit 0;
diff --git a/krb5-1-6/src/util/getsyms b/krb5-1-6/src/util/getsyms
new file mode 100755
index 000000000..6db164c60
--- /dev/null
+++ b/krb5-1-6/src/util/getsyms
@@ -0,0 +1,63 @@
+#!/bin/sh
+# Run this from the TOP of the source tree!
+M4=gm4
+configs=`find $1 -name configure.in -print|sort|sed -e 's@/configure.in@@'`
+for dir in $configs; do
+	syms=""
+	libs=""
+	headers=""
+	types=""
+	funcs=""
+	AC_MACRODIR=./util/autoconf
+	# The following bits shamelessly stolen from autoheader.sh
+	eval "`$M4 -I$AC_MACRODIR autoheader.m4 $dir/configure.in|
+		sed -n -e '
+		: again
+		/^@@@.*@@@$/s/^@@@\(.*\)@@@$/\1/p
+		/^@@@/{
+			s/^@@@//p
+			n
+			s/^/@@@/
+			b again
+		}'`"
+	allsyms="`for sym in $syms; do echo $sym; done | sort | uniq`"
+	if test -n "$funcs"; then
+		funcs="`for func in $funcs; do echo $func; done | sort | uniq`"
+		funcs="`for func in $funcs; do echo $func
+			done | sed 's/[^a-zA-Z0-9_]/_/g' | tr '[a-z]' '[A-Z]' | sed 's/^/HAVE_/'`"
+	allsyms="$allsyms $funcs"
+	fi
+	if test -n "$headers"; then
+		headers="`for header in $headers; do echo $header
+			done | sort | uniq`"
+		headers="`for header in $headers; do echo $header
+			done | sed 's/[^a-zA-Z0-9_]/_/g' | tr '[a-z]' '[A-Z]' | sed 's/^/HAVE_/'`"
+	allsyms="$allsyms $headers"
+	fi
+	if test -n "$libs"; then
+		libs="`for lib in $libs; do echo $lib
+			done | sort | uniq`"
+		libs="`for lib in $libs; do echo $lib
+			done | sed 's/[^a-zA-Z0-9_]/_/g' | tr '[a-z]' '[A-Z]' | sed 's/^/HAVE_LIB/'`"
+	allsyms="$allsyms $libs"
+	fi
+	echo $dir/configure.in: $allsyms
+	allsyms="`echo $allsyms|tr ' ' '|'`"
+	files="$dir/*.[ch]"
+	if test ! "`echo $files`" = "$dir/"'*.[ch]'; then
+	for file in $files; do
+		badsyms=""
+		fsyms=`sed -f ./util/getsyms.sed $file`
+		fsyms="`for sym in $fsyms; do echo $sym; done | sort | uniq`"
+		for sym in $fsyms; do
+			if echo $sym|egrep -s "$allsyms">/dev/null; then :
+			else
+				badsyms="$badsyms $sym"
+			fi
+		done
+		if test -n "$badsyms"; then
+			echo $file:$badsyms
+		fi
+	done
+	fi
+done
diff --git a/krb5-1-6/src/util/getsyms.sed b/krb5-1-6/src/util/getsyms.sed
new file mode 100644
index 000000000..a24b5157f
--- /dev/null
+++ b/krb5-1-6/src/util/getsyms.sed
@@ -0,0 +1,42 @@
+# emulate a C preprocessor (well, sort of)
+:TOP
+y/	/ /
+s/  */ /g
+s%/\*.*\*/%%
+/\/\*/{
+	:COMMENT
+	/\*\//!{
+		s/.*//
+		N
+		bCOMMENT
+	}
+	s%^.*\*/%%
+	bTOP
+}
+/^ *# *ifdef/{
+	s/^ *# *ifdef //
+	b
+}
+/^ *# *ifndef/{
+	s/^ *# *ifndef //
+	b
+}
+/^ *# *if.*defined/{
+	s/^ *# *if //
+	:IF
+	/^defined/!{
+		:NUKE
+		s/^.//
+		/^defined/!bNUKE
+	}
+	h
+	/^defined/s/^defined *( *\([A-Za-z0-9_]*\) *).*/\1/p
+	g
+	/^defined/s/^defined *( *\([[A-Za-z0-9_]*\) *)//
+	/defined/!{
+		d
+		b
+	}
+	bIF
+}
+d
diff --git a/krb5-1-6/src/util/kbuild b/krb5-1-6/src/util/kbuild
new file mode 100755
index 000000000..7596f6170
--- /dev/null
+++ b/krb5-1-6/src/util/kbuild
@@ -0,0 +1,168 @@
+#!/bin/sh
+#
+# Kerberos V5 build tool.  Builds Kerberos V5 using a specified 
+# configuration file to control which support programs are used to
+# compile it, which options are given to configure, etc.
+#
+# usage: kbuild { [ frag ] [ var=value ] [ config-lib-path ] }
+#    where frag is something like base, or gcc, or cns, where it finds
+#    base.conf in the config lib path
+#    var=value sets var to value in the script processing (useful to override
+#    SRCDIR or KRB4)
+#    config-lib-path adds itself to the search path for frags.
+#
+#
+# frags themselves are files named frag.conf which have variable settings
+# and filenames. # is a comment marker. If the line is an assignment, it's
+# read; if it begins with /, it's an explicit member of the path; if it 
+# doesn't, it's searched for in the path set in the last fragment.
+#
+# for example, at mit, one might say
+#
+# /mit/krb5/sandbox/util/kbuild base suncc athena
+#
+# or at cygnus, one might say
+#
+# /6h/eichin/mit-v5/build/base/util/kbuild base gcc cns
+#
+# You get the idea.
+#
+# -- Mark Eichin <eichin@cygnus.com> This file is in the Public Domain.
+#
+
+progname=$0
+pts="`echo ${progname} | sed 's=[^/]*$=='`"
+
+#
+# sneak in default knowledge that this program is one level down from the
+# top of the source tree
+#
+
+case $pts in
+/*)   SRCDIR="`echo ${pts} | sed 's=[^/]*/*$=='`"
+      echo "default srcdir $SRCDIR";;
+../*) SRCDIR="`cd ${pts}/.. ; pwd`"
+      echo "default srcdir $SRCDIR";;
+esac
+
+conflib=". $pts/kfrags"
+
+THISCONF=./kbuild.temp
+RECONF=./kbuild.reconf
+rm -f $THISCONF
+BUILD_PATH=./build-path
+rm -rf $BUILD_PATH
+
+echo '#' $0 $* > $THISCONF
+
+echo  $0 $* > $RECONF
+chmod +x $RECONF
+
+for arg
+do
+  case "$arg" in
+  /*)	conflib="$arg $conflib" ;;
+  ..*)	conflib="$arg $conflib" ;;
+  *=*)  echo $arg >> $THISCONF ;;
+  *)
+	  for p in $conflib
+	  do
+		frag=$p/$arg.conf
+		if test -r $frag ; then
+			break
+		fi
+	  done
+	  echo "# $frag" >> $THISCONF
+	  awk '/^#/ { next; } /^[ \t]*$/ {next; }/^[a-zA-Z0-9_]+=.*$/ { print; next; } /^\// { print "ABS_PROGS=\"${ABS_PROGS} "$0"\""; next; } { print "CMD_PROGS=\"${CMD_PROGS} "$0"\""; next; }' < $frag | sed -e 's/^PATH=/XPATH=/' >> $THISCONF
+	;;
+  esac
+done
+
+CONFIG_OPTS="-v"
+MAKETARGETS="all check"
+# echo ==== THISCONF: =====
+# cat $THISCONF
+# echo --------------------
+. $THISCONF
+
+
+if test "x${CC}" != "x"
+then
+	CONFIG_OPTS="$CONFIG_OPTS --with-cc=${CC}"
+fi
+
+if test "x${CC_OPTS}" != "x"
+then
+	CONFIG_OPTS="$CONFIG_OPTS --with-ccopts=${CC_OPTS}"
+fi
+
+if test "x${KRB4}" != "x"
+then
+	CONFIG_OPTS="$CONFIG_OPTS --with-krb4=${KRB4}"
+fi
+
+if test "x${SHARED}" != "x"
+then
+	CONFIG_OPTS="$CONFIG_OPTS --enable-shared"
+fi
+
+/bin/rm -rf $BUILD_PATH
+mkdir $BUILD_PATH
+cd $BUILD_PATH
+
+for i in $CMD_PROGS
+do
+missed=true
+# echo "trying cmdprog $i"
+	for p in `echo $XPATH | sed 's/:/ /g'`
+	do
+# echo "trying cmdprog $i in path element $p"
+		if test -x $p/$i ; then
+			if test -x $i ; then
+# echo "nuking $i"
+				rm $i
+			fi
+# echo "linking $p/$i"
+			ln -s $p/$i
+			missed=false
+			break
+		fi
+	done
+if $missed ; then
+	echo "COULDN'T FIND $i in $XPATH"
+fi
+done
+
+for i in $ABS_PROGS
+do
+	if test -x $i ; then
+# echo "trying absprog $i"
+	base=`echo $i | sed 's-^.*/\([^/]*\)$-\1-p'`
+	if test -x $base ; then
+		rm $base
+# echo "nuking $base"
+	fi
+# echo "linking $i"
+	ln -s $i 
+	else
+		echo "COULDN'T FIND $i"
+	fi
+done
+
+cd ..
+
+echo "Build path is `pwd`/$BUILD_PATH"
+echo "contents of build path: "
+ls -l $BUILD_PATH
+PATH=`pwd`/$BUILD_PATH
+export PATH
+echo "======"
+
+echo "configuring with: $SRCDIR/configure $CONFIG_OPTS"
+$SRCDIR/configure $CONFIG_OPTS
+
+echo "Configuration done.  Building using the command:"
+echo "	(setenv PATH $PATH; make $MAKETARGETS)"
+echo " "
+
+make $MAKETARGETS
diff --git a/krb5-1-6/src/util/kfrags/athena.conf b/krb5-1-6/src/util/kfrags/athena.conf
new file mode 100644
index 000000000..86e9f34c8
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/athena.conf
@@ -0,0 +1 @@
+KRB4=/usr/athena
diff --git a/krb5-1-6/src/util/kfrags/base.conf b/krb5-1-6/src/util/kfrags/base.conf
new file mode 100644
index 000000000..f6b3b348f
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/base.conf
@@ -0,0 +1,16 @@
+PATH=/bin:/usr/bin
+cp rm mv test cat cmp echo true ls touch
+
+awk sed grep egrep chmod mkdir tr ln
+
+ar lex yacc
+
+install
+cc
+make
+
+# for "make check"
+sort
+
+# For config.guess
+uname
diff --git a/krb5-1-6/src/util/kfrags/cns.conf b/krb5-1-6/src/util/kfrags/cns.conf
new file mode 100644
index 000000000..63327bc05
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/cns.conf
@@ -0,0 +1 @@
+KRB4=/usr/kerberos
diff --git a/krb5-1-6/src/util/kfrags/gcc.conf b/krb5-1-6/src/util/kfrags/gcc.conf
new file mode 100644
index 000000000..4019d8284
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/gcc.conf
@@ -0,0 +1,2 @@
+CC=gcc
+# CC_OPTS=" -g -O -Wall " doesn't work
diff --git a/krb5-1-6/src/util/kfrags/ranlib.conf b/krb5-1-6/src/util/kfrags/ranlib.conf
new file mode 100644
index 000000000..6906e90ca
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/ranlib.conf
@@ -0,0 +1 @@
+ranlib
diff --git a/krb5-1-6/src/util/kfrags/shared.conf b/krb5-1-6/src/util/kfrags/shared.conf
new file mode 100644
index 000000000..ba5bb74c2
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/shared.conf
@@ -0,0 +1,4 @@
+# For shared libraries
+SHARED=true
+# ld is needed on the Alpha.
+ld
diff --git a/krb5-1-6/src/util/kfrags/sunpro.conf b/krb5-1-6/src/util/kfrags/sunpro.conf
new file mode 100644
index 000000000..c79a57bc4
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/sunpro.conf
@@ -0,0 +1 @@
+/opt/SUNWspro/bin/cc
diff --git a/krb5-1-6/src/util/kfrags/svr4.conf b/krb5-1-6/src/util/kfrags/svr4.conf
new file mode 100644
index 000000000..9a455cf31
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/svr4.conf
@@ -0,0 +1 @@
+PATH=/bin:/usr/bin:/usr/ccs/bin
diff --git a/krb5-1-6/src/util/kfrags/ucb.conf b/krb5-1-6/src/util/kfrags/ucb.conf
new file mode 100644
index 000000000..19ca6b176
--- /dev/null
+++ b/krb5-1-6/src/util/kfrags/ucb.conf
@@ -0,0 +1,2 @@
+PATH=/bin:/usr/bin:/usr/ucb
+ranlib
diff --git a/krb5-1-6/src/util/lndir b/krb5-1-6/src/util/lndir
new file mode 100755
index 000000000..31566c6bf
--- /dev/null
+++ b/krb5-1-6/src/util/lndir
@@ -0,0 +1,103 @@
+#! /bin/sh
+
+# lndir - create shadow link tree
+#
+# Time stamp <89/11/28 18:56:54 gildea>
+# By Stephen Gildea <gildea@bbn.com> based on
+#  XConsortium: lndir.sh,v 1.1 88/10/20 17:37:16 jim Exp
+#
+# Used to create a copy of the a directory tree that has links for all non-
+# directories (except those named RCS).  If you are building the distribution
+# on more than one machine, you should use this script.
+#
+# If your master sources are located in /usr/local/src/X and you would like
+# your link tree to be in /usr/local/src/new-X, do the following:
+#
+# 	%  mkdir /usr/local/src/new-X
+#	%  cd /usr/local/src/new-X
+# 	%  lndir ../X
+#
+# Note: does not link files beginning with "."  Is this a bug or a feature?
+#
+# Improvements over R3 version:
+#   Allows the fromdir to be relative: usually you want to say "../dist"
+#   The name is relative to the todir, not the current directory.
+#
+# Bugs in R3 version fixed:
+#   Do "pwd" command *after* "cd $DIRTO".
+#   Don't try to link directories, avoiding error message "<dir> exists".
+#   Barf with Usage message if either DIRFROM *or* DIRTO is not a directory.
+
+USAGE="Usage: $0 fromdir [todir]"
+
+case $0 in 
+/*) lndir=$0 ;;
+*/*) lndir=`pwd`/$0 ;;
+*) lndir=$0 ;;
+esac
+
+if [ $# -lt 1 -o $# -gt 2 ]
+then
+	echo "$USAGE"
+	exit 1
+fi
+
+DIRFROM=$1
+
+if [ $# -eq 2 ];
+then
+	DIRTO=$2
+else
+	DIRTO=.
+fi
+
+if [ ! -d $DIRTO ]
+then
+	echo "$0: $DIRTO is not a directory"
+	echo "$USAGE"
+	exit 2
+fi
+
+cd $DIRTO
+
+if [ ! -d $DIRFROM ]
+then
+	echo "$0: $DIRFROM is not a directory"
+	echo "$USAGE"
+	exit 2
+fi
+
+pwd=`pwd`
+
+if [ `(cd $DIRFROM; pwd)` = $pwd ]
+then
+	echo "$pwd: FROM and TO are identical!"
+	exit 1
+fi
+
+for file in `ls -a $DIRFROM`
+do
+	if [ ! -d $DIRFROM/$file ]
+	then
+		ln -s $DIRFROM/$file .
+	else
+	       if [ $file != RCS -a $file != CVS -a $file != . -a $file != .. ]
+		then
+			echo $file:
+			mkdir $file
+			(cd $file
+			 pwd=`pwd`
+			 case "$DIRFROM" in
+				 /*) ;;
+				 *)  DIRFROM=../$DIRFROM ;;
+			 esac
+			 if [ `(cd $DIRFROM/$file; pwd)` = $pwd ]
+			 then
+				echo "$pwd: FROM and TO are identical!"
+				exit 1
+			 fi
+			 $lndir $DIRFROM/$file
+			)
+		fi
+	fi
+done
diff --git a/krb5-1-6/src/util/makedepend/cpp.ed b/krb5-1-6/src/util/makedepend/cpp.ed
new file mode 100644
index 000000000..ffa586f54
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/cpp.ed
@@ -0,0 +1,75 @@
+#
+# $XConsortium: cpp.ed,v 1.3 89/12/12 12:44:18 jim Exp $
+#
+# $Locker $
+#
+/struct symtab stab/d
+/struct symtab \*defloc;/d
+/struct symtab \*udfloc;/d
+/struct symtab \*incloc;/d
+/struct symtab \*ifloc;/d
+/struct symtab \*elsloc;/d
+/struct symtab \*eifloc;/d
+/struct symtab \*ifdloc;/d
+/struct symtab \*ifnloc;/d
+/struct symtab \*ysysloc;/d
+/struct symtab \*varloc;/d
+/struct symtab \*lneloc;/d
+/struct symtab \*ulnloc;/d
+/struct symtab \*uflloc;/d
+/^sayline(/s/$/	DELETED/p
+.,/^}/d
+/^unfill(/s/$/	DELETED/p
+.-1,/^}/d
+/^doincl(/s/$/	DELETED/p
+.-1,/^}/d
+/^equfrm(/s/$/	DELETED/p
+.,/^}/d
+/^dodef(/s/$/	DELETED/p
+.-1,/^}/d
+/^control(/s/$/	DELETED/p
+.-1,/^}/d
+/^savestring(/s/$/	DELETED/p
+.-1,/^}/d
+/^stsym(/s/$/	DELETED/p
+.-1,/^}/d
+/^ppsym(/s/$/	DELETED/p
+.-1,/^}/d
+/^yyerror(/s/$/	DELETED/p
+.,/^}/d
+/^ppwarn(/s/$/	DELETED/p
+.,/^}/d
+/^lookup(/s/$/	DELETED/p
+.-1,/^}/d
+/^subst(/s/$/	DELETED/p
+.-1,/^}/d
+/^trmdir(/s/$/	DELETED/p
+.-1,/^}/d
+/^copy(/s/$/	DELETED/p
+.-1,/^}/d
+/^pperror(/s/$/	DELETED/p
+.,/^}/d
+/^main(/s/$/	CHANGED to cpp_varsetup(argc,argv)/p
+.c
+cpp_varsetup(argc,argv)
+.
+/^strdex(/s/$/	DELETED/p
+.-1,/^}/d
+/^ for(i=1; i<argc; i++)/s/$/	To the end DELETED/p
+.,$c
+}
+.
+/^dump(/s/$/	DELETED/p
+.,/^}/c
+dump() { fatal("dump\n"); }
+.
+/^refill(/s/$/	DELETED/p
+.,/^}/c
+refill() { fatal("refill\n"); }
+.
+/^slookup(/s/$/	DELETED/p
+.-1,/^}/c
+static struct symtab *slookup() { fatal("slookup\n"); }
+.
+w
+q
diff --git a/krb5-1-6/src/util/makedepend/cppsetup.c b/krb5-1-6/src/util/makedepend/cppsetup.c
new file mode 100644
index 000000000..bf1c4fc5e
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/cppsetup.c
@@ -0,0 +1,242 @@
+/* $XConsortium: cppsetup.c,v 1.13 94/04/17 20:10:32 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+
+#ifdef	CPP
+/*
+ * This file is strictly for the sake of cpy.y and yylex.c (if
+ * you indeed have the source for cpp).
+ */
+#define IB 1
+#define SB 2
+#define NB 4
+#define CB 8
+#define QB 16
+#define WB 32
+#define SALT '#'
+#if pdp11 | vax | ns16000 | mc68000 | ibm032
+#define COFF 128
+#else
+#define COFF 0
+#endif
+/*
+ * These variables used by cpy.y and yylex.c
+ */
+extern char	*outp, *inp, *newp, *pend;
+extern char	*ptrtab;
+extern char	fastab[];
+extern char	slotab[];
+
+/*
+ * cppsetup
+ */
+struct filepointer	*currentfile;
+struct inclist		*currentinc;
+
+cppsetup(line, filep, inc)
+	register char	*line;
+	register struct filepointer	*filep;
+	register struct inclist		*inc;
+{
+	register char *p, savec;
+	static boolean setupdone = FALSE;
+	boolean	value;
+
+	if (!setupdone) {
+		cpp_varsetup();
+		setupdone = TRUE;
+	}
+
+	currentfile = filep;
+	currentinc = inc;
+	inp = newp = line;
+	for (p=newp; *p; p++)
+		;
+
+	/*
+	 * put a newline back on the end, and set up pend, etc.
+	 */
+	*p++ = '\n';
+	savec = *p;
+	*p = '\0';
+	pend = p;
+
+	ptrtab = slotab+COFF;
+	*--inp = SALT; 
+	outp=inp; 
+	value = yyparse();
+	*p = savec;
+	return(value);
+}
+
+struct symtab *lookup(symbol)
+	char	*symbol;
+{
+	static struct symtab    undefined;
+	struct symtab   *sp;
+
+	sp = isdefined(symbol, currentinc, NULL);
+	if (sp == NULL) {
+		sp = &undefined;
+		sp->s_value = NULL;
+	}
+	return (sp);
+}
+
+pperror(tag, x0,x1,x2,x3,x4)
+	int	tag,x0,x1,x2,x3,x4;
+{
+	warning("\"%s\", line %d: ", currentinc->i_file, currentfile->f_line);
+	warning(x0,x1,x2,x3,x4);
+}
+
+
+yyerror(s)
+	register char	*s;
+{
+	fatalerr("Fatal error: %s\n", s);
+}
+#else /* not CPP */
+
+#include "ifparser.h"
+struct _parse_data {
+    struct filepointer *filep;
+    struct inclist *inc;
+    const char *line;
+};
+
+static const char *
+_my_if_errors (ip, cp, expecting)
+    IfParser *ip;
+    const char *cp;
+    const char *expecting;
+{
+    struct _parse_data *pd = (struct _parse_data *) ip->data;
+    int lineno = pd->filep->f_line;
+    char *filename = pd->inc->i_file;
+    char prefix[300];
+    int prefixlen;
+    int i;
+
+    sprintf (prefix, "\"%s\":%d", filename, lineno);
+    prefixlen = strlen(prefix);
+    fprintf (stderr, "%s:  %s", prefix, pd->line);
+    i = cp - pd->line;
+    if (i > 0 && pd->line[i-1] != '\n') {
+	putc ('\n', stderr);
+    }
+    for (i += prefixlen + 3; i > 0; i--) {
+	putc (' ', stderr);
+    }
+    fprintf (stderr, "^--- expecting %s\n", expecting);
+    return NULL;
+}
+
+
+#define MAXNAMELEN 256
+
+static struct symtab *
+_lookup_variable (ip, var, len)
+    IfParser *ip;
+    const char *var;
+    int len;
+{
+    char tmpbuf[MAXNAMELEN + 1];
+    struct _parse_data *pd = (struct _parse_data *) ip->data;
+
+    if (len > MAXNAMELEN)
+	return 0;
+
+    strncpy (tmpbuf, var, len);
+    tmpbuf[len] = '\0';
+    return isdefined (tmpbuf, pd->inc, NULL);
+}
+
+
+static int
+_my_eval_defined (ip, var, len)
+    IfParser *ip;
+    const char *var;
+    int len;
+{
+    if (_lookup_variable (ip, var, len))
+	return 1;
+    else
+	return 0;
+}
+
+#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
+
+static int
+_my_eval_variable (ip, var, len)
+    IfParser *ip;
+    const char *var;
+    int len;
+{
+    struct symtab *s;
+
+    s = _lookup_variable (ip, var, len);
+    if (!s)
+	return 0;
+    do {
+	var = s->s_value;
+	if (!isvarfirstletter(*var))
+	    break;
+	s = _lookup_variable (ip, var, strlen(var));
+    } while (s);
+
+    return atoi(var);
+}
+
+
+cppsetup(line, filep, inc)
+	register char	*line;
+	register struct filepointer	*filep;
+	register struct inclist		*inc;
+{
+    IfParser ip;
+    struct _parse_data pd;
+    int val = 0;
+
+    pd.filep = filep;
+    pd.inc = inc;
+    pd.line = line;
+    ip.funcs.handle_error = _my_if_errors;
+    ip.funcs.eval_defined = _my_eval_defined;
+    ip.funcs.eval_variable = _my_eval_variable;
+    ip.data = (char *) &pd;
+
+    (void) ParseIfExpression (&ip, line, &val);
+    if (val)
+	return IF;
+    else
+	return IFFALSE;
+}
+#endif /* CPP */
+
diff --git a/krb5-1-6/src/util/makedepend/def.h b/krb5-1-6/src/util/makedepend/def.h
new file mode 100644
index 000000000..8a49b3215
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/def.h
@@ -0,0 +1,135 @@
+/* $XConsortium: def.h,v 1.25 94/04/17 20:10:33 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define MAXDEFINES	512
+#define MAXFILES	512
+#define MAXDIRS		64
+#define SYMTABINC	10	/* must be > 1 for define() to work right */
+#define	TRUE		1
+#define	FALSE		0
+
+/* the following must match the directives table in main.c */
+#define	IF		0
+#define	IFDEF		1
+#define	IFNDEF		2
+#define	ELSE		3
+#define	ENDIF		4
+#define	DEFINE		5
+#define	UNDEF		6
+#define	INCLUDE		7
+#define	LINE		8
+#define	PRAGMA		9
+#define ERROR           10
+#define IDENT           11
+#define SCCS            12
+#define ELIF            13
+#define EJECT           14
+#define IFFALSE         15     /* pseudo value --- never matched */
+#define ELIFFALSE       16     /* pseudo value --- never matched */
+#define INCLUDEDOT      17     /* pseudo value --- never matched */
+#define IFGUESSFALSE    18     /* pseudo value --- never matched */
+#define ELIFGUESSFALSE  19     /* pseudo value --- never matched */
+
+#ifdef DEBUG
+extern int	_debugmask;
+/*
+ * debug levels are:
+ * 
+ *     0	show ifn*(def)*,endif
+ *     1	trace defined/!defined
+ *     2	show #include
+ *     3	show #include SYMBOL
+ *     4-6	unused
+ */
+#define debug(level,arg) { if (_debugmask & (1 << level)) warning arg; }
+#else
+#define	debug(level,arg) /**/
+#endif /* DEBUG */
+
+typedef	unsigned char boolean;
+
+struct symtab {
+	char	*s_name;
+	char	*s_value;
+};
+
+struct	inclist {
+	char		*i_incstring;	/* string from #include line */
+	char		*i_file;	/* path name of the include file */
+	struct inclist	**i_list;	/* list of files it itself includes */
+	int		i_listlen;	/* length of i_list */
+	struct symtab	*i_defs;	/* symbol table for this file */
+	int		i_ndefs;	/* current # defines */
+	int		i_deflen;	/* amount of space in table */
+	boolean		i_defchecked;	/* whether defines have been checked */
+	boolean		i_notified;	/* whether we have revealed includes */
+	boolean		i_marked;	/* whether it's in the makefile */
+	boolean		i_searched;	/* whether we have read this */
+	boolean         i_included_sym; /* whether #include SYMBOL was found */
+					/* Can't use i_list if TRUE */
+};
+
+struct filepointer {
+	char	*f_p;
+	char	*f_base;
+	char	*f_end;
+	long	f_len;
+	long	f_line;
+};
+
+#ifndef NO_STDLIB_H		/* X_NOT_STDC_ENV */
+#include <stdlib.h>
+#if defined(macII) && !defined(__STDC__)  /* stdlib.h fails to define these */
+char *malloc(), *realloc();
+#endif /* macII */
+#else
+char			*malloc();
+char			*realloc();
+#endif
+
+char			*copy();
+char			*base_name();
+char			*getline();
+struct symtab		*slookup();
+struct symtab		*isdefined();
+struct symtab		*fdefined();
+struct filepointer	*getfile();
+struct inclist		*newinclude();
+struct inclist		*inc_path();
+
+#ifdef HAVE_STDARG_H	/* NeedVarargsPrototypes */
+extern fatalerr(char *, ...);
+extern warning(char *, ...);
+extern warning1(char *, ...);
+#endif
diff --git a/krb5-1-6/src/util/makedepend/ifparser.c b/krb5-1-6/src/util/makedepend/ifparser.c
new file mode 100644
index 000000000..e0f171d72
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/ifparser.c
@@ -0,0 +1,451 @@
+/*
+ * $XConsortium: ifparser.c,v 1.7 94/01/18 21:30:50 rws Exp $
+ *
+ * Copyright 1992 Network Computing Devices, Inc.
+ * 
+ * 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 Network Computing Devices may not be
+ * used in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  Network Computing Devices makes
+ * no representations about the suitability of this software for any purpose.
+ * It is provided ``as is'' without express or implied warranty.
+ * 
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ * 
+ * Author:  Jim Fulton
+ *          Network Computing Devices, Inc.
+ * 
+ * Simple if statement processor
+ *
+ * This module can be used to evaluate string representations of C language
+ * if constructs.  It accepts the following grammar:
+ * 
+ *     EXPRESSION	:=	VALUE
+ * 			 |	VALUE  BINOP	EXPRESSION
+ * 
+ *     VALUE		:=	'('  EXPRESSION  ')'
+ * 			 |	'!'  VALUE
+ * 			 |	'-'  VALUE
+ * 			 |	'defined'  '('  variable  ')'
+ * 			 |	'defined'  variable
+ *			 |	# variable '(' variable-list ')'
+ * 			 |	variable
+ * 			 |	number
+ * 
+ *     BINOP		:=	'*'	|  '/'	|  '%'
+ * 			 |	'+'	|  '-'
+ * 			 |	'<<'	|  '>>'
+ * 			 |	'<'	|  '>'	|  '<='  |  '>='
+ * 			 |	'=='	|  '!='
+ * 			 |	'&'	|  '|'
+ * 			 |	'&&'	|  '||'
+ * 
+ * The normal C order of precidence is supported.
+ * 
+ * 
+ * External Entry Points:
+ * 
+ *     ParseIfExpression		parse a string for #if
+ */
+
+#include "ifparser.h"
+#include <ctype.h>
+
+/****************************************************************************
+		   Internal Macros and Utilities for Parser
+ ****************************************************************************/
+
+#define DO(val) if (!(val)) return NULL
+#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
+#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
+#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
+
+
+static const char *
+parse_variable (g, cp, varp)
+    IfParser *g;
+    const char *cp;
+    const char **varp;
+{
+    SKIPSPACE (cp);
+
+    if (!isvarfirstletter (*cp))
+	return CALLFUNC(g, handle_error) (g, cp, "variable name");
+
+    *varp = cp;
+    /* EMPTY */
+    for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
+    return cp;
+}
+
+
+static const char *
+parse_number (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    SKIPSPACE (cp);
+
+    if (!isdigit(*cp))
+	return CALLFUNC(g, handle_error) (g, cp, "number");
+
+#ifdef WIN32
+    *valp = strtol(cp, &cp, 0);
+#else
+    *valp = atoi (cp);
+    /* EMPTY */
+    for (cp++; isdigit(*cp); cp++) ;
+#endif
+    return cp;
+}
+
+
+static const char *
+parse_value (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    const char *var;
+
+    *valp = 0;
+
+    SKIPSPACE (cp);
+    if (!*cp)
+	return cp;
+
+    switch (*cp) {
+      case '(':
+	DO (cp = ParseIfExpression (g, cp + 1, valp));
+	SKIPSPACE (cp);
+	if (*cp != ')') 
+	    return CALLFUNC(g, handle_error) (g, cp, ")");
+
+	return cp + 1;			/* skip the right paren */
+
+      case '!':
+	DO (cp = parse_value (g, cp + 1, valp));
+	*valp = !(*valp);
+	return cp;
+
+      case '-':
+	DO (cp = parse_value (g, cp + 1, valp));
+	*valp = -(*valp);
+	return cp;
+
+      case '#':
+	DO (cp = parse_variable (g, cp + 1, &var));
+	SKIPSPACE (cp);
+	if (*cp != '(')
+	    return CALLFUNC(g, handle_error) (g, cp, "(");
+	do {
+	    DO (cp = parse_variable (g, cp + 1, &var));
+	    SKIPSPACE (cp);
+	} while (*cp && *cp != ')');
+	if (*cp != ')')
+	    return CALLFUNC(g, handle_error) (g, cp, ")");
+	*valp = 1; /* XXX */
+	return cp + 1;
+
+      case 'd':
+	if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
+	    int paren = 0;
+	    cp += 7;
+	    SKIPSPACE (cp);
+	    if (*cp == '(') {
+		paren = 1;
+		cp++;
+	    }
+	    DO (cp = parse_variable (g, cp, &var));
+	    SKIPSPACE (cp);
+	    if (paren && *cp != ')')
+		return CALLFUNC(g, handle_error) (g, cp, ")");
+	    *valp = (*(g->funcs.eval_defined)) (g, var, cp - var);
+	    return cp + paren;		/* skip the right paren */
+	}
+	/* fall out */
+    }
+
+    if (isdigit(*cp)) {
+	DO (cp = parse_number (g, cp, valp));
+    } else if (!isvarfirstletter(*cp))
+	return CALLFUNC(g, handle_error) (g, cp, "variable or number");
+    else {
+	DO (cp = parse_variable (g, cp, &var));
+	*valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
+    }
+    
+    return cp;
+}
+
+
+
+static const char *
+parse_product (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_value (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '*':
+	DO (cp = parse_product (g, cp + 1, &rightval));
+	*valp = (*valp * rightval);
+	break;
+
+      case '/':
+	DO (cp = parse_product (g, cp + 1, &rightval));
+	*valp = (*valp / rightval);
+	break;
+
+      case '%':
+	DO (cp = parse_product (g, cp + 1, &rightval));
+	*valp = (*valp % rightval);
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_sum (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_product (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '+':
+	DO (cp = parse_sum (g, cp + 1, &rightval));
+	*valp = (*valp + rightval);
+	break;
+
+      case '-':
+	DO (cp = parse_sum (g, cp + 1, &rightval));
+	*valp = (*valp - rightval);
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_shift (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_sum (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '<':
+	if (cp[1] == '<') {
+	    DO (cp = parse_shift (g, cp + 2, &rightval));
+	    *valp = (*valp << rightval);
+	}
+	break;
+
+      case '>':
+	if (cp[1] == '>') {
+	    DO (cp = parse_shift (g, cp + 2, &rightval));
+	    *valp = (*valp >> rightval);
+	}
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_inequality (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_shift (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '<':
+	if (cp[1] == '=') {
+	    DO (cp = parse_inequality (g, cp + 2, &rightval));
+	    *valp = (*valp <= rightval);
+	} else {
+	    DO (cp = parse_inequality (g, cp + 1, &rightval));
+	    *valp = (*valp < rightval);
+	}
+	break;
+
+      case '>':
+	if (cp[1] == '=') {
+	    DO (cp = parse_inequality (g, cp + 2, &rightval));
+	    *valp = (*valp >= rightval);
+	} else {
+	    DO (cp = parse_inequality (g, cp + 1, &rightval));
+	    *valp = (*valp > rightval);
+	}
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_equality (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_inequality (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '=':
+	if (cp[1] == '=')
+	    cp++;
+	DO (cp = parse_equality (g, cp + 1, &rightval));
+	*valp = (*valp == rightval);
+	break;
+
+      case '!':
+	if (cp[1] != '=')
+	    break;
+	DO (cp = parse_equality (g, cp + 2, &rightval));
+	*valp = (*valp != rightval);
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_band (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_equality (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '&':
+	if (cp[1] != '&') {
+	    DO (cp = parse_band (g, cp + 1, &rightval));
+	    *valp = (*valp & rightval);
+	}
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_bor (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_band (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '|':
+	if (cp[1] != '|') {
+	    DO (cp = parse_bor (g, cp + 1, &rightval));
+	    *valp = (*valp | rightval);
+	}
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_land (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_bor (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '&':
+	if (cp[1] != '&')
+	    return CALLFUNC(g, handle_error) (g, cp, "&&");
+	DO (cp = parse_land (g, cp + 2, &rightval));
+	*valp = (*valp && rightval);
+	break;
+    }
+    return cp;
+}
+
+
+static const char *
+parse_lor (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    int rightval;
+
+    DO (cp = parse_land (g, cp, valp));
+    SKIPSPACE (cp);
+
+    switch (*cp) {
+      case '|':
+	if (cp[1] != '|')
+	    return CALLFUNC(g, handle_error) (g, cp, "||");
+	DO (cp = parse_lor (g, cp + 2, &rightval));
+	*valp = (*valp || rightval);
+	break;
+    }
+    return cp;
+}
+
+
+/****************************************************************************
+			     External Entry Points
+ ****************************************************************************/
+
+const char *
+ParseIfExpression (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *valp;
+{
+    return parse_lor (g, cp, valp);
+}
+
+
diff --git a/krb5-1-6/src/util/makedepend/ifparser.h b/krb5-1-6/src/util/makedepend/ifparser.h
new file mode 100644
index 000000000..c33379822
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/ifparser.h
@@ -0,0 +1,76 @@
+/*
+ * $XConsortium: ifparser.h,v 1.1 92/08/22 13:05:39 rws Exp $
+ *
+ * Copyright 1992 Network Computing Devices, Inc.
+ * 
+ * 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 Network Computing Devices may not be
+ * used in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  Network Computing Devices makes
+ * no representations about the suitability of this software for any purpose.
+ * It is provided ``as is'' without express or implied warranty.
+ * 
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ * 
+ * Author:  Jim Fulton
+ *          Network Computing Devices, Inc.
+ * 
+ * Simple if statement processor
+ *
+ * This module can be used to evaluate string representations of C language
+ * if constructs.  It accepts the following grammar:
+ * 
+ *     EXPRESSION	:=	VALUE
+ * 			 |	VALUE  BINOP	EXPRESSION
+ * 
+ *     VALUE		:=	'('  EXPRESSION  ')'
+ * 			 |	'!'  VALUE
+ * 			 |	'-'  VALUE
+ * 			 |	'defined'  '('  variable  ')'
+ * 			 |	variable
+ * 			 |	number
+ * 
+ *     BINOP		:=	'*'	|  '/'	|  '%'
+ * 			 |	'+'	|  '-'
+ * 			 |	'<<'	|  '>>'
+ * 			 |	'<'	|  '>'	|  '<='  |  '>='
+ * 			 |	'=='	|  '!='
+ * 			 |	'&'	|  '|'
+ * 			 |	'&&'	|  '||'
+ * 
+ * The normal C order of precidence is supported.
+ * 
+ * 
+ * External Entry Points:
+ * 
+ *     ParseIfExpression		parse a string for #if
+ */
+
+#include <stdio.h>
+
+#define const /**/
+typedef int Bool;
+#define False 0
+#define True 1
+
+typedef struct _if_parser {
+    struct {				/* functions */
+	char *(*handle_error) (/* struct _if_parser *, const char *,
+				 const char * */);
+	int (*eval_variable) (/* struct _if_parser *, const char *, int */);
+	int (*eval_defined) (/* struct _if_parser *, const char *, int */);
+    } funcs;
+    char *data;
+} IfParser;
+
+char *ParseIfExpression (/* IfParser *, const char *, int * */);
+
diff --git a/krb5-1-6/src/util/makedepend/include.c b/krb5-1-6/src/util/makedepend/include.c
new file mode 100644
index 000000000..349020aff
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/include.c
@@ -0,0 +1,295 @@
+/* $XConsortium: include.c,v 1.16 94/04/17 20:10:34 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+
+#include "def.h"
+
+extern struct	inclist	inclist[ MAXFILES ],
+			*inclistp;
+extern char	*includedirs[ ];
+extern char	*notdotdot[ ];
+extern boolean show_where_not;
+extern boolean warn_multiple;
+
+struct inclist *inc_path(file, include, dot)
+	register char	*file,
+			*include;
+	boolean	dot;
+{
+	static char	path[ BUFSIZ ];
+	register char		**pp, *p;
+	register struct inclist	*ip;
+	struct stat	st;
+	boolean	found = FALSE;
+
+	/*
+	 * Check all previously found include files for a path that
+	 * has already been expanded.
+	 */
+	for (ip = inclist; ip->i_file; ip++)
+	    if ((strcmp(ip->i_incstring, include) == 0) && !ip->i_included_sym)
+	    {
+		found = TRUE;
+		break;
+	    }
+
+	/*
+	 * If the path was surrounded by "" or is an absolute path,
+	 * then check the exact path provided.
+	 */
+	if (!found && (dot || *include == '/')) {
+		if (stat(include, &st) == 0) {
+			ip = newinclude(include, include);
+			found = TRUE;
+		}
+		else if (show_where_not)
+			warning1("\tnot in %s\n", include);
+	}
+
+	/*
+	 * See if this include file is in the directory of the
+	 * file being compiled.
+	 */
+	if (!found) {
+		for (p=file+strlen(file); p>file; p--)
+			if (*p == '/')
+				break;
+		if (p == file)
+			strcpy(path, include);
+		else {
+			strncpy(path, file, (p-file) + 1);
+			path[ (p-file) + 1 ] = '\0';
+			strcpy(path + (p-file) + 1, include);
+		}
+		remove_dotdot(path);
+		if (stat(path, &st) == 0) {
+			ip = newinclude(path, include);
+			found = TRUE;
+		}
+		else if (show_where_not)
+			warning1("\tnot in %s\n", path);
+	}
+
+	/*
+	 * Check the include directories specified. (standard include dir
+	 * should be at the end.)
+	 */
+	if (!found)
+		for (pp = includedirs; *pp; pp++) {
+			sprintf(path, "%s/%s", *pp, include);
+			remove_dotdot(path);
+			if (stat(path, &st) == 0) {
+				ip = newinclude(path, include);
+				found = TRUE;
+				break;
+			}
+			else if (show_where_not)
+				warning1("\tnot in %s\n", path);
+		}
+
+	if (!found)
+		ip = NULL;
+	return(ip);
+}
+
+/*
+ * Ocaisionally, pathnames are created that look like ../x/../y
+ * Any of the 'x/..' sequences within the name can be eliminated.
+ * (but only if 'x' is not a symbolic link!!)
+ */
+remove_dotdot(path)
+	char	*path;
+{
+	register char	*end, *from, *to, **cp;
+	char		*components[ MAXFILES ],
+			newpath[ BUFSIZ ];
+	boolean		component_copied;
+
+	/*
+	 * slice path up into components.
+	 */
+	to = newpath;
+	if (*path == '/')
+		*to++ = '/';
+	*to = '\0';
+	cp = components;
+	for (from=end=path; *end; end++)
+		if (*end == '/') {
+			while (*end == '/')
+				*end++ = '\0';
+			if (*from)
+				*cp++ = from;
+			from = end;
+		}
+	*cp++ = from;
+	*cp = NULL;
+
+	/*
+	 * Now copy the path, removing all 'x/..' components.
+	 */
+	cp = components;
+	component_copied = FALSE;
+	while(*cp) {
+		if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))) {
+			if (issymbolic(newpath, *cp))
+				goto dont_remove;
+			cp++;
+		} else {
+		dont_remove:
+			if (component_copied)
+				*to++ = '/';
+			component_copied = TRUE;
+			for (from = *cp; *from; )
+				*to++ = *from++;
+			*to = '\0';
+		}
+		cp++;
+	}
+	*to++ = '\0';
+
+	/*
+	 * copy the reconstituted path back to our pointer.
+	 */
+	strcpy(path, newpath);
+}
+
+isdot(p)
+	register char	*p;
+{
+	if(p && *p++ == '.' && *p++ == '\0')
+		return(TRUE);
+	return(FALSE);
+}
+
+isdotdot(p)
+	register char	*p;
+{
+	if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
+		return(TRUE);
+	return(FALSE);
+}
+
+issymbolic(dir, component)
+	register char	*dir, *component;
+{
+#ifdef S_IFLNK
+	struct stat	st;
+	char	buf[ BUFSIZ ], **pp;
+
+	sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
+	for (pp=notdotdot; *pp; pp++)
+		if (strcmp(*pp, buf) == 0)
+			return (TRUE);
+	if (lstat(buf, &st) == 0
+	&& (st.st_mode & S_IFMT) == S_IFLNK) {
+		*pp++ = copy(buf);
+		if (pp >= ¬dotdot[ MAXDIRS ])
+			fatalerr("out of .. dirs, increase MAXDIRS\n");
+		return(TRUE);
+	}
+#endif
+	return(FALSE);
+}
+
+/*
+ * Add an include file to the list of those included by 'file'.
+ */
+struct inclist *newinclude(newfile, incstring)
+	register char	*newfile, *incstring;
+{
+	register struct inclist	*ip;
+
+	/*
+	 * First, put this file on the global list of include files.
+	 */
+	ip = inclistp++;
+	if (inclistp == inclist + MAXFILES - 1)
+		fatalerr("out of space: increase MAXFILES\n");
+	ip->i_file = copy(newfile);
+	ip->i_included_sym = FALSE;
+	if (incstring == NULL)
+		ip->i_incstring = ip->i_file;
+	else
+		ip->i_incstring = copy(incstring);
+
+	return(ip);
+}
+
+included_by(ip, newfile)
+	register struct inclist	*ip, *newfile;
+{
+	register i;
+
+	if (ip == NULL)
+		return;
+	/*
+	 * Put this include file (newfile) on the list of files included
+	 * by 'file'.  If 'file' is NULL, then it is not an include
+	 * file itself (i.e. was probably mentioned on the command line).
+	 * If it is already on the list, don't stick it on again.
+	 */
+	if (ip->i_list == NULL)
+		ip->i_list = (struct inclist **)
+			malloc(sizeof(struct inclist *) * ++ip->i_listlen);
+	else {
+		for (i=0; i<ip->i_listlen; i++)
+			if (ip->i_list[ i ] == newfile) {
+			    i = strlen(newfile->i_file);
+			    if (!ip->i_included_sym &&
+				!(i > 2 &&
+				  newfile->i_file[i-1] == 'c' &&
+				  newfile->i_file[i-2] == '.'))
+			    {
+				/* only bitch if ip has */
+				/* no #include SYMBOL lines  */
+				/* and is not a .c file */
+				if (warn_multiple)
+				{
+					warning("%s includes %s more than once!\n",
+						ip->i_file, newfile->i_file);
+					warning1("Already have\n");
+					for (i=0; i<ip->i_listlen; i++)
+						warning1("\t%s\n", ip->i_list[i]->i_file);
+				}
+			    }
+			    return;
+			}
+		ip->i_list = (struct inclist **) realloc(ip->i_list,
+			sizeof(struct inclist *) * ++ip->i_listlen);
+	}
+	ip->i_list[ ip->i_listlen-1 ] = newfile;
+}
+
+inc_clean ()
+{
+	register struct inclist *ip;
+
+	for (ip = inclist; ip < inclistp; ip++) {
+		ip->i_marked = FALSE;
+	}
+}
diff --git a/krb5-1-6/src/util/makedepend/main.c b/krb5-1-6/src/util/makedepend/main.c
new file mode 100644
index 000000000..ccf35147c
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/main.c
@@ -0,0 +1,688 @@
+/* $XConsortium: main.c,v 1.83 94/04/17 20:10:36 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+#ifdef hpux
+#define sigvec sigvector
+#endif /* hpux */
+
+#include <signal.h>
+
+#if NeedVarargsPrototypes
+#include <stdarg.h>
+#endif
+
+#ifdef DEBUG
+int	_debugmask;
+#endif
+
+char *ProgramName;
+
+char	*directives[] = {
+	"if",
+	"ifdef",
+	"ifndef",
+	"else",
+	"endif",
+	"define",
+	"undef",
+	"include",
+	"line",
+	"pragma",
+	"error",
+	"ident",
+	"sccs",
+	"elif",
+	"eject",
+	NULL
+};
+
+#define MAKEDEPEND
+#include "imakemdep.h"	/* from config sources */
+#undef MAKEDEPEND
+
+struct	inclist inclist[ MAXFILES ],
+		*inclistp = inclist,
+		maininclist;
+
+char	*filelist[ MAXFILES ];
+char	*includedirs[ MAXDIRS + 1 ];
+char	*notdotdot[ MAXDIRS ];
+char	*objprefix = "";
+char	*objsuffix = OBJSUFFIX;
+char	*startat = "# DO NOT DELETE";
+int	width = 78;
+boolean	append = FALSE;
+boolean	printed = FALSE;
+boolean	verbose = FALSE;
+boolean	show_where_not = FALSE;
+boolean warn_multiple = FALSE;	/* Warn on multiple includes of same file */
+
+static
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+catch (sig)
+    int sig;
+{
+	fflush (stdout);
+	fatalerr ("got signal %d\n", sig);
+}
+
+#if defined(USG) || (defined(SYSV386) && defined(SYSV)) || defined(WIN32)
+#define USGISH
+#endif
+
+#ifndef USGISH
+#ifndef _POSIX_SOURCE
+#define sigaction sigvec
+#define sa_handler sv_handler
+#define sa_mask sv_mask
+#define sa_flags sv_flags
+#endif
+struct sigaction sig_act;
+#endif /* USGISH */
+
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	register char	**fp = filelist;
+	register char	**incp = includedirs;
+	register char	*p;
+	register struct inclist	*ip;
+	char	*makefile = NULL;
+	struct filepointer	*filecontent;
+	struct symtab *psymp = predefs;
+	char *endmarker = NULL;
+	char *defincdir = NULL;
+
+	ProgramName = argv[0];
+
+	while (psymp->s_name)
+	{
+	    define2(psymp->s_name, psymp->s_value, &maininclist);
+	    psymp++;
+	}
+	if (argc == 2 && argv[1][0] == '@') {
+	    struct stat ast;
+	    int afd;
+	    char *args;
+	    char **nargv;
+	    int nargc;
+	    char quotechar = '\0';
+
+	    nargc = 1;
+	    if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
+		fatalerr("cannot open \"%s\"\n", argv[1]+1);
+	    fstat(afd, &ast);
+	    args = (char *)malloc(ast.st_size + 1);
+	    if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
+		fatalerr("failed to read %s\n", argv[1]+1);
+	    args[ast.st_size] = '\0';
+	    close(afd);
+	    for (p = args; *p; p++) {
+		if (quotechar) {
+		    if (quotechar == '\\' ||
+			(*p == quotechar && p[-1] != '\\'))
+			quotechar = '\0';
+		    continue;
+		}
+		switch (*p) {
+		case '\\':
+		case '"':
+		case '\'':
+		    quotechar = *p;
+		    break;
+		case ' ':
+		case '\n':
+		    *p = '\0';
+		    if (p > args && p[-1])
+			nargc++;
+		    break;
+		}
+	    }
+	    if (p[-1])
+		nargc++;
+	    nargv = (char **)malloc(nargc * sizeof(char *));
+	    nargv[0] = argv[0];
+	    argc = 1;
+	    for (p = args; argc < nargc; p += strlen(p) + 1)
+		if (*p) nargv[argc++] = p;
+	    argv = nargv;
+	}
+	for(argc--, argv++; argc; argc--, argv++) {
+	    	/* if looking for endmarker then check before parsing */
+		if (endmarker && strcmp (endmarker, *argv) == 0) {
+		    endmarker = NULL;
+		    continue;
+		}
+		if (**argv != '-') {
+			/* treat +thing as an option for C++ */
+			if (endmarker && **argv == '+')
+				continue;
+			*fp++ = argv[0];
+			continue;
+		}
+		switch(argv[0][1]) {
+		case '-':
+			endmarker = &argv[0][2];
+			if (endmarker[0] == '\0') endmarker = "--";
+			break;
+		case 'D':
+			if (argv[0][2] == '\0') {
+				argv++;
+				argc--;
+			}
+			for (p=argv[0] + 2; *p ; p++)
+				if (*p == '=') {
+					*p = ' ';
+					break;
+				}
+			define(argv[0] + 2, &maininclist);
+			break;
+		case 'I':
+			if (incp >= includedirs + MAXDIRS)
+			    fatalerr("Too many -I flags.\n");
+			*incp++ = argv[0]+2;
+			if (**(incp-1) == '\0') {
+				*(incp-1) = *(++argv);
+				argc--;
+			}
+			break;
+		case 'Y':
+			defincdir = argv[0]+2;
+			break;
+		/* do not use if endmarker processing */
+		case 'a':
+			if (endmarker) break;
+			append = TRUE;
+			break;
+		case 'w':
+			if (endmarker) break;
+			if (argv[0][2] == '\0') {
+				argv++;
+				argc--;
+				width = atoi(argv[0]);
+			} else
+				width = atoi(argv[0]+2);
+			break;
+		case 'o':
+			if (endmarker) break;
+			if (argv[0][2] == '\0') {
+				argv++;
+				argc--;
+				objsuffix = argv[0];
+			} else
+				objsuffix = argv[0]+2;
+			break;
+		case 'p':
+			if (endmarker) break;
+			if (argv[0][2] == '\0') {
+				argv++;
+				argc--;
+				objprefix = argv[0];
+			} else
+				objprefix = argv[0]+2;
+			break;
+		case 'v':
+			if (endmarker) break;
+			verbose = TRUE;
+#ifdef DEBUG
+			if (argv[0][2])
+				_debugmask = atoi(argv[0]+2);
+#endif
+			break;
+		case 's':
+			if (endmarker) break;
+			startat = argv[0]+2;
+			if (*startat == '\0') {
+				startat = *(++argv);
+				argc--;
+			}
+			if (*startat != '#')
+				fatalerr("-s flag's value should start %s\n",
+					"with '#'.");
+			break;
+		case 'f':
+			if (endmarker) break;
+			makefile = argv[0]+2;
+			if (*makefile == '\0') {
+				makefile = *(++argv);
+				argc--;
+			}
+			break;
+
+		case 'm':
+			warn_multiple = TRUE;
+			break;
+			
+		/* Ignore -O, -g so we can just pass ${CFLAGS} to
+		   makedepend
+		 */
+		case 'O':
+		case 'g':
+			break;
+		default:
+			if (endmarker) break;
+	/*		fatalerr("unknown opt = %s\n", argv[0]); */
+			warning("ignoring option %s\n", argv[0]);
+		}
+	}
+	if (!defincdir) {
+#ifdef PREINCDIR
+	    if (incp >= includedirs + MAXDIRS)
+		fatalerr("Too many -I flags.\n");
+	    *incp++ = PREINCDIR;
+#endif
+	    if (incp >= includedirs + MAXDIRS)
+		fatalerr("Too many -I flags.\n");
+	    *incp++ = INCLUDEDIR;
+#ifdef POSTINCDIR
+	    if (incp >= includedirs + MAXDIRS)
+		fatalerr("Too many -I flags.\n");
+	    *incp++ = POSTINCDIR;
+#endif
+	} else if (*defincdir) {
+	    if (incp >= includedirs + MAXDIRS)
+		fatalerr("Too many -I flags.\n");
+	    *incp++ = defincdir;
+	}
+
+	redirect(startat, makefile);
+
+	/*
+	 * catch signals.
+	 */
+#ifdef USGISH
+/*  should really reset SIGINT to SIG_IGN if it was.  */
+#ifdef SIGHUP
+	signal (SIGHUP, catch);
+#endif
+	signal (SIGINT, catch);
+#ifdef SIGQUIT
+	signal (SIGQUIT, catch);
+#endif
+	signal (SIGILL, catch);
+#ifdef SIGBUS
+	signal (SIGBUS, catch);
+#endif
+	signal (SIGSEGV, catch);
+#ifdef SIGSYS
+	signal (SIGSYS, catch);
+#endif
+#else
+	sig_act.sa_handler = catch;
+#ifdef _POSIX_SOURCE
+	sigemptyset(&sig_act.sa_mask);
+	sigaddset(&sig_act.sa_mask, SIGINT);
+	sigaddset(&sig_act.sa_mask, SIGQUIT);
+#ifdef SIGBUS
+	sigaddset(&sig_act.sa_mask, SIGBUS);
+#endif
+	sigaddset(&sig_act.sa_mask, SIGILL);
+	sigaddset(&sig_act.sa_mask, SIGSEGV);
+	sigaddset(&sig_act.sa_mask, SIGHUP);
+	sigaddset(&sig_act.sa_mask, SIGPIPE);
+#ifdef SIGSYS
+	sigaddset(&sig_act.sa_mask, SIGSYS);
+#endif
+#else
+	sig_act.sa_mask = ((1<<(SIGINT -1))
+			   |(1<<(SIGQUIT-1))
+#ifdef SIGBUS
+			   |(1<<(SIGBUS-1))
+#endif
+			   |(1<<(SIGILL-1))
+			   |(1<<(SIGSEGV-1))
+			   |(1<<(SIGHUP-1))
+			   |(1<<(SIGPIPE-1))
+#ifdef SIGSYS
+			   |(1<<(SIGSYS-1))
+#endif
+			   );
+#endif /* _POSIX_SOURCE */
+	sig_act.sa_flags = 0;
+	sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
+	sigaction(SIGINT, &sig_act, (struct sigaction *)0);
+	sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
+	sigaction(SIGILL, &sig_act, (struct sigaction *)0);
+#ifdef SIGBUS
+	sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
+#endif
+	sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
+#ifdef SIGSYS
+	sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
+#endif
+#endif /* USGISH */
+
+	/*
+	 * now peruse through the list of files.
+	 */
+	for(fp=filelist; *fp; fp++) {
+		filecontent = getfile(*fp);
+		ip = newinclude(*fp, (char *)NULL);
+
+		find_includes(filecontent, ip, ip, 0, FALSE);
+		freefile(filecontent);
+		recursive_pr_include(ip, ip->i_file, base_name(*fp));
+		inc_clean();
+	}
+	if (printed)
+		printf("\n");
+	exit(0);
+}
+
+struct filepointer *getfile(file)
+	char	*file;
+{
+	register int	fd;
+	struct filepointer	*content;
+	struct stat	st;
+
+	content = (struct filepointer *)malloc(sizeof(struct filepointer));
+	if ((fd = open(file, O_RDONLY)) < 0) {
+		warning("cannot open \"%s\"\n", file);
+		content->f_p = content->f_base = content->f_end = (char *)malloc(1);
+		*content->f_p = '\0';
+		return(content);
+	}
+	fstat(fd, &st);
+	content->f_base = (char *)malloc(st.st_size+1);
+	if (content->f_base == NULL)
+		fatalerr("cannot allocate mem\n");
+	if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
+		fatalerr("failed to read %s\n", file);
+	close(fd);
+	content->f_len = st.st_size+1;
+	content->f_p = content->f_base;
+	content->f_end = content->f_base + st.st_size;
+	*content->f_end = '\0';
+	content->f_line = 0;
+	return(content);
+}
+
+freefile(fp)
+	struct filepointer	*fp;
+{
+	free(fp->f_base);
+	free(fp);
+}
+
+char *copy(str)
+	register char	*str;
+{
+	register char	*p = (char *)malloc(strlen(str) + 1);
+
+	strcpy(p, str);
+	return(p);
+}
+
+match(str, list)
+	register char	*str, **list;
+{
+	register int	i;
+
+	for (i=0; *list; i++, list++)
+		if (strcmp(str, *list) == 0)
+			return(i);
+	return(-1);
+}
+
+/*
+ * Get the next line.  We only return lines beginning with '#' since that
+ * is all this program is ever interested in.
+ */
+char *getline(filep)
+	register struct filepointer	*filep;
+{
+	register char	*p,	/* walking pointer */
+			*eof,	/* end of file pointer */
+			*bol;	/* beginning of line pointer */
+	register	lineno;	/* line number */
+
+	p = filep->f_p;
+	eof = filep->f_end;
+	if (p >= eof)
+		return((char *)NULL);
+	lineno = filep->f_line;
+
+	for(bol = p--; ++p < eof; ) {
+		if (*p == '/' && *(p+1) == '*') { /* consume comments */
+			*p++ = ' ', *p++ = ' ';
+			while (*p) {
+				if (*p == '*' && *(p+1) == '/') {
+					*p++ = ' ', *p = ' ';
+					break;
+				}
+				else if (*p == '\n')
+					lineno++;
+				*p++ = ' ';
+			}
+			continue;
+		}
+#ifdef WIN32
+		else if (*p == '/' && *(p+1) == '/') { /* consume comments */
+			*p++ = ' ', *p++ = ' ';
+			while (*p && *p != '\n')
+				*p++ = ' ';
+			lineno++;
+			continue;
+		}
+#endif
+		else if (*p == '\\') {
+			if (*(p+1) == '\n') {
+				*p = ' ';
+				*(p+1) = ' ';
+				lineno++;
+			}
+		}
+		else if (*p == '\n') {
+			lineno++;
+			if (*bol == '#') {
+				register char *cp;
+
+				*p++ = '\0';
+				/* punt lines with just # (yacc generated) */
+				for (cp = bol+1; 
+				     *cp && (*cp == ' ' || *cp == '\t'); cp++);
+				if (*cp) goto done;
+			}
+			bol = p+1;
+		}
+	}
+	if (*bol != '#')
+		bol = NULL;
+done:
+	filep->f_p = p;
+	filep->f_line = lineno;
+	return(bol);
+}
+
+/*
+ * Strip the file name down to what we want to see in the Makefile.
+ * It will have objprefix and objsuffix around it.
+ */
+char *base_name(file)
+	register char	*file;
+{
+	register char	*p;
+
+	file = copy(file);
+	for(p=file+strlen(file); p>file && *p != '.'; p--) ;
+
+	if (*p == '.')
+		*p = '\0';
+	return(file);
+}
+
+#if defined(USG) && !defined(CRAY) && !defined(SVR4)
+int rename (from, to)
+    char *from, *to;
+{
+    (void) unlink (to);
+    if (link (from, to) == 0) {
+	unlink (from);
+	return 0;
+    } else {
+	return -1;
+    }
+}
+#endif /* USGISH */
+
+redirect(line, makefile)
+	char	*line,
+		*makefile;
+{
+	struct stat	st;
+	FILE	*fdin, *fdout;
+	char	backup[ BUFSIZ ],
+		buf[ BUFSIZ ];
+	boolean	found = FALSE;
+	int	len;
+
+	/*
+	 * if makefile is "-" then let it pour onto stdout.
+	 */
+	if (makefile && *makefile == '-' && *(makefile+1) == '\0')
+		return;
+
+	/*
+	 * use a default makefile is not specified.
+	 */
+	if (!makefile) {
+		if (stat("Makefile", &st) == 0)
+			makefile = "Makefile";
+		else if (stat("makefile", &st) == 0)
+			makefile = "makefile";
+		else
+			fatalerr("[mM]akefile is not present\n");
+	}
+	else
+	    stat(makefile, &st);
+	if ((fdin = fopen(makefile, "r")) == NULL)
+		fatalerr("cannot open \"%s\"\n", makefile);
+	sprintf(backup, "%s.bak", makefile);
+	unlink(backup);
+#ifdef WIN32
+	fclose(fdin);
+#endif
+	if (rename(makefile, backup) < 0)
+		fatalerr("cannot rename %s to %s\n", makefile, backup);
+#ifdef WIN32
+	if ((fdin = fopen(backup, "r")) == NULL)
+		fatalerr("cannot open \"%s\"\n", backup);
+#endif
+	if ((fdout = freopen(makefile, "w", stdout)) == NULL)
+		fatalerr("cannot open \"%s\"\n", backup);
+	len = strlen(line);
+	while (!found && fgets(buf, BUFSIZ, fdin)) {
+		if (*buf == '#' && strncmp(line, buf, len) == 0)
+			found = TRUE;
+		fputs(buf, fdout);
+	}
+	if (!found) {
+		if (verbose)
+		warning("Adding new delimiting line \"%s\" and dependencies...\n",
+			line);
+		puts(line); /* same as fputs(fdout); but with newline */
+	} else if (append) {
+	    while (fgets(buf, BUFSIZ, fdin)) {
+		fputs(buf, fdout);
+	    }
+	}
+	fflush(fdout);
+#if defined(USGISH) || defined(_SEQUENT_)
+	chmod(makefile, st.st_mode);
+#else
+        fchmod(fileno(fdout), st.st_mode);
+#endif /* USGISH */
+}
+
+#if NeedVarargsPrototypes
+fatalerr(char *msg, ...)
+#else
+/*VARARGS*/
+fatalerr(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
+    char *msg;
+#endif
+{
+#if NeedVarargsPrototypes
+	va_list args;
+#endif
+	fprintf(stderr, "%s: error:  ", ProgramName);
+#if NeedVarargsPrototypes
+	va_start(args, msg);
+	vfprintf(stderr, msg, args);
+	va_end(args);
+#else
+	fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
+#endif
+	exit (1);
+}
+
+#if NeedVarargsPrototypes
+warning(char *msg, ...)
+#else
+/*VARARGS0*/
+warning(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
+    char *msg;
+#endif
+{
+#if NeedVarargsPrototypes
+	va_list args;
+#endif
+	fprintf(stderr, "%s: warning:  ", ProgramName);
+#if NeedVarargsPrototypes
+	va_start(args, msg);
+	vfprintf(stderr, msg, args);
+	va_end(args);
+#else
+	fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
+#endif
+}
+
+#if NeedVarargsPrototypes
+warning1(char *msg, ...)
+#else
+/*VARARGS0*/
+warning1(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
+    char *msg;
+#endif
+{
+#if NeedVarargsPrototypes
+	va_list args;
+	va_start(args, msg);
+	vfprintf(stderr, msg, args);
+	va_end(args);
+#else
+	fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
+#endif
+}
diff --git a/krb5-1-6/src/util/makedepend/mkdepend.man b/krb5-1-6/src/util/makedepend/mkdepend.man
new file mode 100644
index 000000000..72d1c87bf
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/mkdepend.man
@@ -0,0 +1,370 @@
+.\" $XConsortium: mkdepend.man,v 1.15 94/04/17 20:10:37 gildea Exp $
+.\" Copyright (c) 1993, 1994  X Consortium
+.\" 
+.\" Permission is hereby granted, free of charge, to any person obtaining a
+.\" copy of this software and associated documentation files (the "Software"), 
+.\" to deal in the Software without restriction, including without limitation 
+.\" the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+.\" and/or sell copies of the Software, and to permit persons to whom the 
+.\" Software furnished to do so, subject to the following conditions:
+.\" 
+.\" The above copyright notice and this permission notice shall be included in
+.\" all copies or substantial portions of the Software.
+.\" 
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
+.\" THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+.\" WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 
+.\" OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+.\" SOFTWARE.
+.\" 
+.\" Except as contained in this notice, the name of the X Consortium shall not 
+.\" be used in advertising or otherwise to promote the sale, use or other 
+.\" dealing in this Software without prior written authorization from the 
+.\" X Consortium.
+.\" "
+.so man1/header.doc
+.TH MAKEDEPEND 1 \*h
+.UC 4
+.SH NAME
+makedepend \- create dependencies in makefiles
+.SH SYNOPSIS
+.B makedepend
+[
+.B \-Dname=def
+] [
+.B \-Dname
+] [
+.B \-Iincludedir
+] [
+.B \-Yincludedir
+] [
+.B \-a
+] [
+.B \-fmakefile
+] [
+.B \-oobjsuffix
+] [
+.B \-pobjprefix
+] [
+.B \-sstring
+] [
+.B \-wwidth
+] [
+.B \-v
+] [
+.B \-m
+] [
+\-\^\-
+.B otheroptions
+\-\^\-
+]
+sourcefile .\|.\|.
+.br
+.SH DESCRIPTION
+.B Makedepend
+reads each
+.I sourcefile
+in sequence and parses it like a C-preprocessor,
+processing all
+.I #include,
+.I #define,
+.I #undef,
+.I #ifdef,
+.I #ifndef,
+.I #endif,
+.I #if
+and
+.I #else
+directives so that it can correctly tell which
+.I #include,
+directives would be used in a compilation.
+Any
+.I #include,
+directives can reference files having other
+.I #include
+directives, and parsing will occur in these files as well.
+.PP
+Every file that a
+.I sourcefile
+includes,
+directly or indirectly,
+is what
+.B makedepend
+calls a "dependency".
+These dependencies are then written to a
+.I makefile
+in such a way that
+.B make(1)
+will know which object files must be recompiled when a dependency has changed.
+.PP
+By default,
+.B makedepend
+places its output in the file named
+.I makefile
+if it exists, otherwise
+.I Makefile.
+An alternate makefile may be specified with the
+.B \-f
+option.
+It first searches the makefile for
+the line
+.sp
+    # DO NOT DELETE THIS LINE \-\^\- make depend depends on it.
+.sp
+or one provided with the
+.B \-s
+option,
+as a delimiter for the dependency output.
+If it finds it, it will delete everything
+following this to the end of the makefile
+and put the output after this line.
+If it doesn't find it, the program
+will append the string to the end of the makefile
+and place the output following that.
+For each
+.I sourcefile
+appearing on the command line,
+.B makedepend
+puts lines in the makefile of the form
+.sp
+     sourcefile.o:\0dfile .\|.\|.
+.sp
+Where "sourcefile.o" is the name from the command
+line with its suffix replaced with ".o",
+and "dfile" is a dependency discovered in a
+.I #include
+directive while parsing
+.I sourcefile
+or one of the files it included.
+.SH EXAMPLE
+Normally,
+.B makedepend
+will be used in a makefile target so that typing "make depend" will
+bring the dependencies up to date for the makefile.
+For example,
+.nf
+    SRCS\0=\0file1.c\0file2.c\0.\|.\|.
+    CFLAGS\0=\0\-O\0\-DHACK\0\-I\^.\^.\^/foobar\0\-xyz
+    depend:
+            makedepend\0\-\^\-\0$(CFLAGS)\0\-\^\-\0$(SRCS)
+.fi
+.SH OPTIONS
+.B Makedepend
+will ignore any option that it does not understand so that you may use
+the same arguments that you would for
+.B cc(1).
+.TP 5
+.B \-Dname=def or \-Dname
+Define.
+This places a definition for
+.I name
+in
+.B makedepend's
+symbol table.
+Without 
+.I =def
+the symbol becomes defined as "1".
+.TP 5
+.B \-Iincludedir
+Include directory.
+This option tells
+.B makedepend
+to prepend
+.I includedir
+to its list of directories to search when it encounters
+a
+.I #include
+directive.
+By default,
+.B makedepend
+only searches the standard include directories (usually /usr/include
+and possibly a compiler-dependent directory).
+.TP 5
+.B \-Yincludedir
+Replace all of the standard include directories with the single specified
+include directory; you can omit the
+.I includedir
+to simply prevent searching the standard include directories.
+.TP 5
+.B \-a
+Append the dependencies to the end of the file instead of replacing them. 
+.TP 5
+.B \-fmakefile
+Filename.
+This allows you to specify an alternate makefile in which
+.B makedepend
+can place its output.
+.TP 5
+.B \-oobjsuffix
+Object file suffix.
+Some systems may have object files whose suffix is something other
+than ".o".
+This option allows you to specify another suffix, such as
+".b" with
+.I -o.b
+or ":obj"
+with
+.I -o:obj
+and so forth.
+.TP 5
+.B \-pobjprefix
+Object file prefix.
+The prefix is prepended to the name of the object file. This is
+usually used to designate a different directory for the object file.
+The default is the empty string.
+.TP 5
+.B \-sstring
+Starting string delimiter.
+This option permits you to specify
+a different string for
+.B makedepend
+to look for in the makefile.
+.TP 5
+.B \-wwidth
+Line width.
+Normally,
+.B makedepend
+will ensure that every output line that it writes will be no wider than
+78 characters for the sake of readability.
+This option enables you to change this width.
+.TP 5
+.B \-v
+Verbose operation.
+This option causes 
+.B makedepend
+to emit the list of files included by each input file on standard output.
+.TP 5
+.B \-m
+Warn about multiple inclusion.
+This option causes 
+.B makedepend
+to produce a warning if any input file includes another file more than
+once.  In previous versions of 
+.B makedepend
+this was the default behavior; the default has been changed to better
+match the behavior of the C compiler, which does not consider multiple
+inclusion to be an error.  This option is provided for backward 
+compatibility, and to aid in debugging problems related to multiple
+inclusion.
+.TP 5
+.B "\-\^\- options \-\^\-"
+If
+.B makedepend
+encounters a double hyphen (\-\^\-) in the argument list,
+then any unrecognized argument following it
+will be silently ignored; a second double hyphen terminates this
+special treatment.
+In this way,
+.B makedepend
+can be made to safely ignore esoteric compiler arguments that might
+normally be found in a CFLAGS
+.B make
+macro (see the
+.B EXAMPLE
+section above).
+All options that
+.B makedepend
+recognizes and appear between the pair of double hyphens
+are processed normally.
+.SH ALGORITHM
+The approach used in this program enables it to run an order of magnitude
+faster than any other "dependency generator" I have ever seen.
+Central to this performance are two assumptions:
+that all files compiled by a single
+makefile will be compiled with roughly the same
+.I -I
+and
+.I -D
+options;
+and that most files in a single directory will include largely the
+same files.
+.PP
+Given these assumptions,
+.B makedepend
+expects to be called once for each makefile, with
+all source files that are maintained by the
+makefile appearing on the command line.
+It parses each source and include
+file exactly once, maintaining an internal symbol table
+for each.
+Thus, the first file on the command line will take an amount of time
+proportional to the amount of time that a normal C preprocessor takes.
+But on subsequent files, if it encounter's an include file
+that it has already parsed, it does not parse it again.
+.PP
+For example,
+imagine you are compiling two files,
+.I file1.c
+and
+.I file2.c,
+they each include the header file
+.I header.h,
+and the file
+.I header.h
+in turn includes the files
+.I def1.h
+and
+.I def2.h.
+When you run the command
+.sp
+    makedepend\0file1.c\0file2.c
+.sp
+.B makedepend
+will parse
+.I file1.c
+and consequently,
+.I header.h
+and then
+.I def1.h
+and
+.I def2.h.
+It then decides that the dependencies for this file are
+.sp
+    file1.o:\0header.h\0def1.h\0def2.h
+.sp
+But when the program parses
+.I file2.c
+and discovers that it, too, includes
+.I header.h,
+it does not parse the file,
+but simply adds
+.I header.h,
+.I def1.h
+and
+.I def2.h
+to the list of dependencies for
+.I file2.o.
+.SH "SEE ALSO"
+cc(1), make(1)
+.SH BUGS
+.B makedepend
+parses, but does not currently evaluate, the SVR4
+#predicate(token-list) preprocessor expression;
+such expressions are simply assumed to be true.
+This may cause the wrong
+.I #include
+directives to be evaluated.
+.PP
+Imagine you are parsing two files,
+say
+.I file1.c
+and
+.I file2.c,
+each includes the file
+.I def.h.
+The list of files that
+.I def.h
+includes might truly be different when
+.I def.h
+is included by
+.I file1.c
+than when it is included by
+.I file2.c.
+But once
+.B makedepend
+arrives at a list of dependencies for a file,
+it is cast in concrete.
+.SH AUTHOR
+Todd Brunhoff, Tektronix, Inc. and MIT Project Athena
diff --git a/krb5-1-6/src/util/makedepend/parse.c b/krb5-1-6/src/util/makedepend/parse.c
new file mode 100644
index 000000000..cf557c0ba
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/parse.c
@@ -0,0 +1,567 @@
+/* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+
+extern char	*directives[];
+extern struct inclist	maininclist;
+
+find_includes(filep, file, file_red, recursion, failOK)
+	struct filepointer	*filep;
+	struct inclist		*file, *file_red;
+	int			recursion;
+	boolean			failOK;
+{
+	register char	*line;
+	register int	type;
+	boolean recfailOK;
+
+	while (line = getline(filep)) {
+		switch(type = deftype(line, filep, file_red, file, TRUE)) {
+		case IF:
+		doif:
+			type = find_includes(filep, file,
+				file_red, recursion+1, failOK);
+			while ((type == ELIF) || (type == ELIFFALSE) ||
+			       (type == ELIFGUESSFALSE))
+				type = gobble(filep, file, file_red);
+			if (type == ELSE)
+				gobble(filep, file, file_red);
+			break;
+		case IFFALSE:
+		case IFGUESSFALSE:
+		    doiffalse:
+			if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
+			    recfailOK = TRUE;
+			else
+			    recfailOK = failOK;
+			type = gobble(filep, file, file_red);
+			if (type == ELSE)
+			    find_includes(filep, file,
+					  file_red, recursion+1, recfailOK);
+			else
+			if (type == ELIF)
+			    goto doif;
+			else
+			if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
+			    goto doiffalse;
+			break;
+		case IFDEF:
+		case IFNDEF:
+			if ((type == IFDEF && isdefined(line, file_red, NULL))
+			 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
+				debug(1,(type == IFNDEF ?
+				    "line %d: %s !def'd in %s via %s%s\n" : "",
+				    filep->f_line, line,
+				    file->i_file, file_red->i_file, ": doit"));
+				type = find_includes(filep, file,
+					file_red, recursion+1, failOK);
+				while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
+					type = gobble(filep, file, file_red);
+				if (type == ELSE)
+					gobble(filep, file, file_red);
+			}
+			else {
+				debug(1,(type == IFDEF ?
+				    "line %d: %s !def'd in %s via %s%s\n" : "",
+				    filep->f_line, line,
+				    file->i_file, file_red->i_file, ": gobble"));
+				type = gobble(filep, file, file_red);
+				if (type == ELSE)
+					find_includes(filep, file,
+						file_red, recursion+1, failOK);
+				else if (type == ELIF)
+				    	goto doif;
+				else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
+				    	goto doiffalse;
+			}
+			break;
+		case ELSE:
+		case ELIFFALSE:
+		case ELIFGUESSFALSE:
+		case ELIF:
+			if (!recursion)
+				gobble(filep, file, file_red);
+		case ENDIF:
+			if (recursion)
+				return(type);
+		case DEFINE:
+			define(line, file);
+			break;
+		case UNDEF:
+			if (!*line) {
+			    warning("%s, line %d: incomplete undef == \"%s\"\n",
+				file_red->i_file, filep->f_line, line);
+			    break;
+			}
+			undefine(line, file_red);
+			break;
+		case INCLUDE:
+			add_include(filep, file, file_red, line, FALSE, failOK);
+			break;
+		case INCLUDEDOT:
+			add_include(filep, file, file_red, line, TRUE, failOK);
+			break;
+		case ERROR:
+		    	warning("%s: %d: %s\n", file_red->i_file,
+				 filep->f_line, line);
+		    	break;
+		    
+		case PRAGMA:
+		case IDENT:
+		case SCCS:
+		case EJECT:
+			break;
+		case -1:
+			warning("%s", file_red->i_file);
+			if (file_red != file)
+			    warning1(" (reading %s)", file->i_file);
+			warning1(", line %d: unknown directive == \"%s\"\n",
+				 filep->f_line, line);
+			break;
+		case -2:
+			warning("%s", file_red->i_file);
+			if (file_red != file)
+			    warning1(" (reading %s)", file->i_file);
+			warning1(", line %d: incomplete include == \"%s\"\n",
+				 filep->f_line, line);
+			break;
+		}
+	}
+	return(-1);
+}
+
+gobble(filep, file, file_red)
+	register struct filepointer *filep;
+	struct inclist		*file, *file_red;
+{
+	register char	*line;
+	register int	type;
+
+	while (line = getline(filep)) {
+		switch(type = deftype(line, filep, file_red, file, FALSE)) {
+		case IF:
+		case IFFALSE:
+		case IFGUESSFALSE:
+		case IFDEF:
+		case IFNDEF:
+			type = gobble(filep, file, file_red);
+			while ((type == ELIF) || (type == ELIFFALSE) ||
+			       (type == ELIFGUESSFALSE))
+			    type = gobble(filep, file, file_red);
+			if (type == ELSE)
+			        (void)gobble(filep, file, file_red);
+			break;
+		case ELSE:
+		case ENDIF:
+			debug(0,("%s, line %d: #%s\n",
+				file->i_file, filep->f_line,
+				directives[type]));
+			return(type);
+		case DEFINE:
+		case UNDEF:
+		case INCLUDE:
+		case INCLUDEDOT:
+		case PRAGMA:
+		case ERROR:
+		case IDENT:
+		case SCCS:
+		case EJECT:
+			break;
+		case ELIF:
+		case ELIFFALSE:
+		case ELIFGUESSFALSE:
+			return(type);
+		case -1:
+			warning("%s, line %d: unknown directive == \"%s\"\n",
+				file_red->i_file, filep->f_line, line);
+			break;
+		}
+	}
+	return(-1);
+}
+
+/*
+ * Decide what type of # directive this line is.
+ */
+int deftype (line, filep, file_red, file, parse_it)
+	register char	*line;
+	register struct filepointer *filep;
+	register struct inclist *file_red, *file;
+	int	parse_it;
+{
+	register char	*p;
+	char	*directive, savechar;
+	register int	ret;
+
+	/*
+	 * Parse the directive...
+	 */
+	directive=line+1;
+	while (*directive == ' ' || *directive == '\t')
+		directive++;
+
+	p = directive;
+	while (*p >= 'a' && *p <= 'z')
+		p++;
+	savechar = *p;
+	*p = '\0';
+	ret = match(directive, directives);
+	*p = savechar;
+
+	/* If we don't recognize this compiler directive or we happen to just
+	 * be gobbling up text while waiting for an #endif or #elif or #else
+	 * in the case of an #elif we must check the zero_value and return an
+	 * ELIF or an ELIFFALSE.
+	 */
+
+	if (ret == ELIF && !parse_it)
+	{
+	    while (*p == ' ' || *p == '\t')
+		p++;
+	    /*
+	     * parse an expression.
+	     */
+	    debug(0,("%s, line %d: #elif %s ",
+		   file->i_file, filep->f_line, p));
+	    ret = zero_value(p, filep, file_red);
+	    if (ret != IF)
+	    {
+		debug(0,("false...\n"));
+		if (ret == IFFALSE)
+		    return(ELIFFALSE);
+		else
+		    return(ELIFGUESSFALSE);
+	    }
+	    else
+	    {
+		debug(0,("true...\n"));
+		return(ELIF);
+	    }
+	}
+
+	if (ret < 0 || ! parse_it)
+		return(ret);
+
+	/*
+	 * now decide how to parse the directive, and do it.
+	 */
+	while (*p == ' ' || *p == '\t')
+		p++;
+	switch (ret) {
+	case IF:
+		/*
+		 * parse an expression.
+		 */
+		ret = zero_value(p, filep, file_red);
+		debug(0,("%s, line %d: %s #if %s\n",
+			 file->i_file, filep->f_line, ret?"false":"true", p));
+		break;
+	case IFDEF:
+	case IFNDEF:
+		debug(0,("%s, line %d: #%s %s\n",
+			file->i_file, filep->f_line, directives[ret], p));
+	case UNDEF:
+		/*
+		 * separate the name of a single symbol.
+		 */
+		while (isalnum(*p) || *p == '_')
+			*line++ = *p++;
+		*line = '\0';
+		break;
+	case INCLUDE:
+		debug(2,("%s, line %d: #include %s\n",
+			file->i_file, filep->f_line, p));
+
+		/* Support ANSI macro substitution */
+		{
+		    struct symtab *sym = isdefined(p, file_red, NULL);
+		    while (sym) {
+			p = sym->s_value;
+			debug(3,("%s : #includes SYMBOL %s = %s\n",
+			       file->i_incstring,
+			       sym -> s_name,
+			       sym -> s_value));
+			/* mark file as having included a 'soft include' */
+			file->i_included_sym = TRUE; 
+			sym = isdefined(p, file_red, NULL);
+		    }
+		}
+
+		/*
+		 * Separate the name of the include file.
+		 */
+		while (*p && *p != '"' && *p != '<')
+			p++;
+		if (! *p)
+			return(-2);
+		if (*p++ == '"') {
+			ret = INCLUDEDOT;
+			while (*p && *p != '"')
+				*line++ = *p++;
+		} else
+			while (*p && *p != '>')
+				*line++ = *p++;
+		*line = '\0';
+		break;
+	case DEFINE:
+		/*
+		 * copy the definition back to the beginning of the line.
+		 */
+		strcpy (line, p);
+		break;
+	case ELSE:
+	case ENDIF:
+	case ELIF:
+	case PRAGMA:
+	case ERROR:
+	case IDENT:
+	case SCCS:
+	case EJECT:
+		debug(0,("%s, line %d: #%s\n",
+			file->i_file, filep->f_line, directives[ret]));
+		/*
+		 * nothing to do.
+		 */
+		break;
+	}
+	return(ret);
+}
+
+struct symtab *isdefined(symbol, file, srcfile)
+	register char	*symbol;
+	struct inclist	*file;
+	struct inclist	**srcfile;
+{
+	register struct symtab	*val;
+
+	if (val = slookup(symbol, &maininclist)) {
+		debug(1,("%s defined on command line\n", symbol));
+		if (srcfile != NULL) *srcfile = &maininclist;
+		return(val);
+	}
+	if (val = fdefined(symbol, file, srcfile))
+		return(val);
+	debug(1,("%s not defined in %s\n", symbol, file->i_file));
+	return(NULL);
+}
+
+struct symtab *fdefined(symbol, file, srcfile)
+	register char	*symbol;
+	struct inclist	*file;
+	struct inclist	**srcfile;
+{
+	register struct inclist	**ip;
+	register struct symtab	*val;
+	register int	i;
+	static int	recurse_lvl = 0;
+
+	if (file->i_defchecked)
+		return(NULL);
+	file->i_defchecked = TRUE;
+	if (val = slookup(symbol, file))
+		debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value));
+	if (val == NULL && file->i_list)
+		{
+		for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
+			if (val = fdefined(symbol, *ip, srcfile)) {
+				break;
+			}
+		}
+	else if (val != NULL && srcfile != NULL) *srcfile = file;
+	recurse_lvl--;
+	file->i_defchecked = FALSE;
+
+	return(val);
+}
+
+/*
+ * Return type based on if the #if expression evaluates to 0
+ */
+zero_value(exp, filep, file_red)
+	register char	*exp;
+	register struct filepointer *filep;
+	register struct inclist *file_red;
+{
+	if (cppsetup(exp, filep, file_red))
+	    return(IFFALSE);
+	else
+	    return(IF);
+}
+
+define(def, file)
+	char	*def;
+	struct inclist	*file;
+{
+    char *val;
+
+    /* Separate symbol name and its value */
+    val = def;
+    while (isalnum(*val) || *val == '_')
+	val++;
+    if (*val)
+	*val++ = '\0';
+    while (*val == ' ' || *val == '\t')
+	val++;
+
+    if (!*val)
+	val = "1";
+    define2(def, val, file);
+}
+
+define2(name, val, file)
+	char	*name, *val;
+	struct inclist	*file;
+{
+    int first, last, below;
+    register struct symtab *sp = NULL, *dest;
+
+    /* Make space if it's needed */
+    if (file->i_defs == NULL)
+    {
+	file->i_defs = (struct symtab *)
+			malloc(sizeof (struct symtab) * SYMTABINC);
+	file->i_deflen = SYMTABINC;
+	file->i_ndefs = 0;
+    }
+    else if (file->i_ndefs == file->i_deflen)
+	file->i_defs = (struct symtab *)
+			realloc(file->i_defs,
+			    sizeof(struct symtab)*(file->i_deflen+=SYMTABINC));
+
+    if (file->i_defs == NULL)
+	fatalerr("malloc()/realloc() failure in insert_defn()\n");
+
+    below = first = 0;
+    last = file->i_ndefs - 1;
+    while (last >= first)
+    {
+	/* Fast inline binary search */
+	register char *s1;
+	register char *s2;
+	register int middle = (first + last) / 2;
+
+	/* Fast inline strchr() */
+	s1 = name;
+	s2 = file->i_defs[middle].s_name;
+	while (*s1++ == *s2++)
+	    if (s2[-1] == '\0') break;
+
+	/* If exact match, set sp and break */
+	if (*--s1 == *--s2) 
+	{
+	    sp = file->i_defs + middle;
+	    break;
+	}
+
+	/* If name > i_defs[middle] ... */
+	if (*s1 > *s2) 
+	{
+	    below = first;
+	    first = middle + 1;
+	}
+	/* else ... */
+	else
+	{
+	    below = last = middle - 1;
+	}
+    }
+
+    /* Search is done.  If we found an exact match to the symbol name,
+       just replace its s_value */
+    if (sp != NULL)
+    {
+	free(sp->s_value);
+	sp->s_value = copy(val);
+	return;
+    }
+
+    sp = file->i_defs + file->i_ndefs++;
+    dest = file->i_defs + below + 1;
+    while (sp > dest)
+    {
+	*sp = sp[-1];
+	sp--;
+    }
+    sp->s_name = copy(name);
+    sp->s_value = copy(val);
+}
+
+struct symtab *slookup(symbol, file)
+	register char	*symbol;
+	register struct inclist	*file;
+{
+	register int first = 0;
+	register int last = file->i_ndefs - 1;
+
+	if (file) while (last >= first)
+	{
+	    /* Fast inline binary search */
+	    register char *s1;
+	    register char *s2;
+	    register int middle = (first + last) / 2;
+
+	    /* Fast inline strchr() */
+	    s1 = symbol;
+	    s2 = file->i_defs[middle].s_name;
+	    while (*s1++ == *s2++)
+	        if (s2[-1] == '\0') break;
+
+	    /* If exact match, we're done */
+	    if (*--s1 == *--s2) 
+	    {
+	        return file->i_defs + middle;
+	    }
+
+	    /* If symbol > i_defs[middle] ... */
+	    if (*s1 > *s2) 
+	    {
+	        first = middle + 1;
+	    }
+	    /* else ... */
+	    else
+	    {
+	        last = middle - 1;
+	    }
+	}
+	return(NULL);
+}
+
+undefine(symbol, file)
+	char	*symbol;
+	register struct inclist	*file;
+{
+	register struct symtab *ptr;
+	struct inclist *srcfile;
+	while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
+	{
+	    srcfile->i_ndefs--;
+	    for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
+		*ptr = ptr[1];
+	}
+}
diff --git a/krb5-1-6/src/util/makedepend/pr.c b/krb5-1-6/src/util/makedepend/pr.c
new file mode 100644
index 000000000..407b1ec0b
--- /dev/null
+++ b/krb5-1-6/src/util/makedepend/pr.c
@@ -0,0 +1,127 @@
+/* $XConsortium: pr.c,v 1.17 94/04/17 20:10:38 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+
+extern struct	inclist	inclist[ MAXFILES ],
+			*inclistp;
+extern char	*objprefix;
+extern char	*objsuffix;
+extern int	width;
+extern boolean	printed;
+extern boolean	verbose;
+extern boolean	show_where_not;
+
+add_include(filep, file, file_red, include, dot, failOK)
+	struct filepointer	*filep;
+	struct inclist	*file, *file_red;
+	char	*include;
+	boolean	dot;
+{
+	register struct inclist	*newfile;
+	register struct filepointer	*content;
+
+	/*
+	 * First decide what the pathname of this include file really is.
+	 */
+	newfile = inc_path(file->i_file, include, dot);
+	if (newfile == NULL) {
+		if (failOK)
+		    return;
+		if (file != file_red)
+			warning("%s (reading %s, line %d): ",
+				file_red->i_file, file->i_file, filep->f_line);
+		else
+			warning("%s, line %d: ", file->i_file, filep->f_line);
+		warning1("cannot find include file \"%s\"\n", include);
+		show_where_not = TRUE;
+		newfile = inc_path(file->i_file, include, dot);
+		show_where_not = FALSE;
+	}
+
+	if (newfile) {
+		included_by(file, newfile);
+		if (!newfile->i_searched) {
+			newfile->i_searched = TRUE;
+			content = getfile(newfile->i_file);
+			find_includes(content, newfile, file_red, 0, failOK);
+			freefile(content);
+		}
+	}
+}
+
+recursive_pr_include(head, file, base)
+	register struct inclist	*head;
+	register char	*file, *base;
+{
+	register int	i;
+
+	if (head->i_marked)
+		return;
+	head->i_marked = TRUE;
+	if (head->i_file != file)
+		pr(head, file, base);
+	for (i=0; i<head->i_listlen; i++)
+		recursive_pr_include(head->i_list[ i ], file, base);
+}
+
+pr(ip, file, base)
+	register struct inclist  *ip;
+	char	*file, *base;
+{
+	static char	*lastfile;
+	static int	current_len;
+	register int	len, i;
+	char	buf[ BUFSIZ ];
+
+	printed = TRUE;
+	len = strlen(ip->i_file)+1;
+	if (current_len + len > width || file != lastfile) {
+		lastfile = file;
+		sprintf(buf, "\n%s%s%s: %s", objprefix, base, objsuffix,
+			ip->i_file);
+		len = current_len = strlen(buf);
+	}
+	else {
+		buf[0] = ' ';
+		strcpy(buf+1, ip->i_file);
+		current_len += len;
+	}
+	fwrite(buf, len, 1, stdout);
+
+	/*
+	 * If verbose is set, then print out what this file includes.
+	 */
+	if (! verbose || ip->i_list == NULL || ip->i_notified)
+		return;
+	ip->i_notified = TRUE;
+	lastfile = NULL;
+	printf("\n# %s includes:", ip->i_file);
+	for (i=0; i<ip->i_listlen; i++)
+		printf("\n#\t%s", ip->i_list[ i ]->i_incstring);
+}
diff --git a/krb5-1-6/src/util/mkrel b/krb5-1-6/src/util/mkrel
new file mode 100755
index 000000000..ca9108767
--- /dev/null
+++ b/krb5-1-6/src/util/mkrel
@@ -0,0 +1,224 @@
+#!/bin/sh
+set -e
+repository=svn+ssh://svn.mit.edu/krb5
+dodoc=t
+dosrc=t
+checkout=t
+multitar=nil
+while test $# -gt 2; do
+	case $1 in
+	--srconly)
+		dodoc=nil;;
+	--doconly)
+		dosrc=nil;;
+	--multi*)
+		multitar=t;;
+	--repository)
+		shift; repository=$1;;
+	--nocheckout)
+		checkout=nil;;
+	esac
+	shift
+done
+if test $# -lt 2; then
+	echo "usage: $0 [opts] release-tag release-dir"
+	echo "	release-tag is relative to $repository/"
+	exit 1
+fi
+
+reltag=$1
+reldir=$2
+
+relmajor=0
+relminor=0
+relpatch=0
+relhead=
+# reltail=
+reldate=`date +%Y%m%d`
+
+case "$reldir" in
+*/*)
+	echo "release-dir may not contain slashes."
+	exit 1
+	;;
+*" "*|*"	"*)
+	echo "release-dir may  not contain whitespace."
+	exit 1
+	;;
+krb5-*.*.*-*)
+	release=`echo $reldir|sed -e 's/krb5-//'`
+	relhead=`echo $release|sed -e 's/-.*//'`
+	reltail=`echo $release|sed -e 's/.*-//'`
+	relmajor=`echo $relhead|awk -F. '{print $1}'`
+	relminor=`echo $relhead|awk -F. '{print $2}'`
+	relpatch=`echo $relhead|awk -F. '{print $3}'`
+	;;
+krb5-*.*.*)
+	release=`echo $reldir|sed -e 's/krb5-//'`
+	relmajor=`echo $release|awk -F. '{print $1}'`
+	relminor=`echo $release|awk -F. '{print $2}'`
+	relpatch=`echo $release|awk -F. '{print $3}'`
+	;;
+krb5-*.*-current)
+	release=`echo $reldir|sed -e 's/krb5-//'`
+	relhead=`echo $release|sed -e 's/-.*//'`
+	relmajor=`echo $relhead|awk -F. '{print $1}'`
+	relminor=`echo $relhead|awk -F. '{print $2}'`
+	release=${relhead}-$reldate
+	;;
+krb5-*.*-*)
+	release=`echo $reldir|sed -e 's/krb5-//'`
+	relhead=`echo $release|sed -e 's/-.*//'`
+	reltail=`echo $release|sed -e 's/.*-//'`
+	relmajor=`echo $relhead|awk -F. '{print $1}'`
+	relminor=`echo $relhead|awk -F. '{print $2}'`
+	;;
+krb5-*.*)
+	release=`echo $reldir|sed -e 's/krb5-//'`
+	relmajor=`echo $release|awk -F. '{print $1}'`
+	relminor=`echo $release|awk -F. '{print $2}'`
+	;;
+krb5-current)
+	release=current-$reldate
+	;;
+*)
+	release="$reldir"
+	;;
+esac
+
+echo "release=$release"
+echo "major=$relmajor minor=$relminor patch=$relpatch"
+
+# $release is used for send-pr
+# $reltag, $release, $reldate are used for brand.c currently
+# $relmajor, $relminor, $relpatch are used for patchlevel.h currently
+
+#
+# $newstyle = t if patchlevel.h is the master version stamp file.  If
+# so, we don't edit it here.
+#
+if test $checkout = t; then
+	if svn cat $repository/$reltag/src/patchlevel.h | grep KRB5_RELDATE > /dev/null 2>&1; then
+		newstyle=t
+	else
+		newstyle=nil;
+	fi
+else
+	if grep KRB5_RELDATE $reldir/src/patchlevel.h > /dev/null 2>&1; then
+		newstyle=t;
+	else
+		newstyle=nil;
+	fi
+fi
+
+if test $newstyle = t; then
+	echo "parsing new style patchlevel.h..."
+	if test $checkout = t; then
+		eval `svn cat $repository/$reltag/src/patchlevel.h | sed -n 's/#define \([A-Z0-9_]*\)[ \t]*\(.*\)/\1=\2/p'`
+	else
+		eval `sed -n 's/#define \([A-Z0-9_]*\)[ \t]*\(.*\)/\1=\2/p' < $reldir/src/patchlevel.h`
+	fi
+	if test "$KRB5_RELTAG" != $reltag && \
+		test "$KRB5_RELTAG" != `echo $reltag|sed 's%[^/]*/%%'` ; then
+		echo "WARNING: patchlevel.h '$KRB5_RELTAG' != $reltag"
+	fi
+	if test "$KRB5_MAJOR_RELEASE" != "$relmajor" || \
+		test "$KRB5_MINOR_RELEASE" != "$relminor" || \
+		test "$KRB5_PATCHLEVEL" != "$relpatch" || \
+		( test -n "$reltail" && \
+			test "$KRB5_RELTAIL" != "$reltail" ); then
+
+		echo "WARNING: patchlevel.h $KRB5_MAJOR_RELEASE.$KRB5_MINOR_RELEASE.$KRB5_PATCHLEVEL${KRB5_RELTAIL+-$KRB5_RELTAIL} != $relmajor.$relminor.$relpatch${reltail+-$reltail}"
+	fi
+else
+	echo "old style patchlevel.h"
+fi
+
+if test $checkout = t; then
+	echo "Checking out krb5 with tag $reltag into directory $reldir..."
+	svn export $repository/$reltag $reldir
+fi
+
+echo "Editing release-specific files..."
+
+if test $newstyle = t; then 
+	(cd $reldir/src && \
+		sed -e '/#[a-z 	]*KRB5_RELDATE/c\
+#define KRB5_RELDATE "'"$reldate"'"' patchlevel.h > patchlevel.h.new && \
+		mv patchlevel.h.new patchlevel.h)
+	if test $checkout = t; then
+		(cd $reldir && svn log -v $repository/$reltag > doc/CHANGES)
+	fi
+else
+
+	(cd $reldir/src/lib/krb5/krb && \
+		sed -e '/static/s%KRB5_BRAND:[^"]*"%'"KRB5_BRAND: $reltag $release $reldate"'"%' \
+			brand.c > brand.c.new && mv brand.c.new brand.c; \
+		rm -f brand.c.new)
+
+	(cd $reldir/src/util/send-pr && \
+		sed -e 's%RELEASE=.*%RELEASE='"krb5-$release"'%' Makefile.in \
+			> Makefile.in.new && mv Makefile.in.new Makefile.in)
+
+	(cd $reldir/src && \
+		cat > patchlevel.h <<EOF
+#define KRB5_MAJOR_RELEASE $relmajor
+#define KRB5_MINOR_RELEASE $relminor
+#define KRB5_PATCHLEVEL    $relpatch
+EOF
+	)
+fi
+
+if test $dosrc = t; then
+	if test -d $reldir/src/util/autoconf; then
+		echo "Building autoconf..."
+		(cd $reldir/src/util/autoconf
+			M4=gm4 ./configure
+			make)
+	fi
+	echo "Creating configure scripts..."
+	(cd $reldir/src; util/reconf)
+
+	if test -d $reldir/src/util/autoconf; then
+		echo "Cleaning src/util/autoconf..."
+		(cd $reldir/src/util/autoconf; make distclean)
+	fi
+fi
+
+echo "Nuking unneeded files..."
+find $reldir \( -name TODO -o -name todo -o -name .cvsignore \
+	-o -name BADSYMS -o -name .Sanitize -o -name .rconf \) -print \
+	| xargs rm -f || true
+find $reldir -type d \( -name autom4te.cache -o -name .svn \
+	-o -name \$ac_config_fragdir \) -exec rm -rf {} \; || true
+
+if test $dodoc = t; then
+	echo "Building doc..."
+	(cd $reldir/doc; make)
+fi
+
+echo "Generating tarfiles..."
+GZIP=-9; export GZIP
+if test $multitar = t; then
+	if test $dosrc = t; then
+		gtar --exclude $reldir/src/lib/crypto \
+			--exclude $reldir/src/lib/des425 \
+			--exclude $reldir/doc \
+			-zcf ${reldir}.src.tar.gz $reldir
+
+		gtar zcf ${reldir}.crypto.tar.gz \
+			$reldir/src/lib/crypto \
+			$reldir/src/lib/des425
+	fi
+	if test $dodoc = t; then
+		gtar zcf ${reldir}.doc.tar.gz $reldir/doc $reldir/README
+	fi
+	ls -l ${reldir}.*.tar.gz
+fi
+
+gtar zcf ${reldir}.tar.gz $reldir
+ls -l ${reldir}.tar.gz
+
+echo "Done."
+
+exit 0
diff --git a/krb5-1-6/src/util/profile/Makefile.in b/krb5-1-6/src/util/profile/Makefile.in
new file mode 100644
index 000000000..5c524138d
--- /dev/null
+++ b/krb5-1-6/src/util/profile/Makefile.in
@@ -0,0 +1,197 @@
+thisconfigdir=../..
+myfulldir=util/profile
+mydir=util/profile
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD) $(TCL_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)$(TCL_RPATH)
+KRB5_RUN_ENV=@KRB5_RUN_ENV@
+DEFS=
+##DOS##BUILDTOP = ..\..
+##DOS##OBJFILE=$(OUTPRE)profile.lst
+##DOS##LIBNAME=$(OUTPRE)profile.lib
+
+LOCALINCLUDES=-I. $(TCL_INCLUDES)
+# for tcl.h
+DEFINES=-DHAS_STDARG
+
+STLIBOBJS = \
+	prof_tree.o \
+	prof_file.o \
+	prof_parse.o \
+	prof_get.o \
+	prof_set.o \
+	prof_err.o \
+	prof_init.o
+
+OBJS = $(OUTPRE)prof_tree.$(OBJEXT) \
+	$(OUTPRE)prof_file.$(OBJEXT) \
+	$(OUTPRE)prof_parse.$(OBJEXT) \
+	$(OUTPRE)prof_get.$(OBJEXT) \
+	$(OUTPRE)prof_set.$(OBJEXT) \
+	$(OUTPRE)prof_err.$(OBJEXT) \
+	$(OUTPRE)prof_init.$(OBJEXT)
+
+SRCS = $(srcdir)/prof_tree.c \
+	$(srcdir)/prof_file.c \
+	$(srcdir)/prof_parse.c \
+	$(srcdir)/prof_get.c \
+	$(srcdir)/prof_set.c \
+	prof_err.c \
+	$(srcdir)/prof_init.c
+
+EXTRADEPSRCS=$(srcdir)/test_parse.c $(srcdir)/test_profile.c \
+	$(srcdir)/profile_tcl.c
+
+DEPLIBS = $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+MLIBS = -lcom_err $(SUPPORT_LIB) $(LIBS)
+
+LIBBASE=profile
+LIBMAJOR=1
+LIBMINOR=1
+SHLIB_EXPDEPS = $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+SHLIB_EXPLIBS = -lcom_err $(SUPPORT_LIB) $(LIBS)
+SHLIB_DIRS = -L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+STOBJLISTS=OBJS.ST
+
+PROFILE_HDR=$(BUILDTOP)$(S)include$(S)profile.h
+
+all-unix:: includes 
+all-unix:: all-libs
+all-windows:: $(PROFILE_HDR)
+
+install-headers-unix:: includes
+
+generate-files-mac: profile.h
+
+$(PROFILE_HDR):: profile.h
+	$(CP) profile.h "$@"
+
+includes:: profile.h
+	if cmp profile.h \
+	$(BUILDTOP)/include/profile.h >/dev/null 2>&1; then :; \
+	else \
+		(set -x; $(RM) $(BUILDTOP)/include/profile.h; \
+		 $(CP) profile.h $(BUILDTOP)/include/profile.h) ; \
+	fi
+
+clean-unix::
+	$(RM) $(BUILDTOP)/include/profile.h
+
+##DOS##LIBOBJS = $(OBJS)
+
+
+awk-windows:
+	$(AWK) -f $(BUILDTOP)/util/et/et_h.awk outfile=prof_err.h prof_err.et
+	$(AWK) -f $(BUILDTOP)/util/et/et_c.awk outfile=prof_err.c prof_err.et
+	if exist prof_err.h copy profile.hin+prof_err.h profile.h
+	if exist profile.h copy profile.h $(BUILDTOP)\include\profile.h
+
+test_parse: test_parse.$(OBJEXT) $(OBJS) $(DEPLIBS)
+	$(CC_LINK) -o test_parse test_parse.$(OBJEXT) $(OBJS) $(MLIBS)
+
+test_profile: test_profile.$(OBJEXT) argv_parse.$(OBJEXT) $(OBJS) $(DEPLIBS)
+	$(CC_LINK) -o test_profile test_profile.$(OBJEXT) \
+		argv_parse.$(OBJEXT) $(OBJS) $(MLIBS)
+
+.d: includes
+
+# NEED TO FIX!!
+$(OUTPRE)test_parse.exe: 
+	$(CC) $(CFLAGS2) -o test_parse.exe test_parse.c \
+		prof_parse.c prof_tree.c /link /stack:16384
+
+# NEED TO FIX!!
+$(OUTPRE)test_profile.exe: 
+	$(CC) $(CFLAGS2) -o test_profile.exe test_profile.c prof_init.c \
+		prof_file.c prof_parse.c prof_tree.c /link /stack:16384
+
+profile.h: prof_err.h profile.hin
+	cat $(srcdir)/profile.hin prof_err.h > $@
+
+prof_err.h: $(srcdir)/prof_err.et
+
+prof_err.c: $(srcdir)/prof_err.et
+
+prof_err.o: prof_err.c
+
+# not built by default, but may be useful for testing
+$(srcdir)/profile_tcl.c: profile.swg
+#	(cd $(srcdir) && swig -tcl8 -o profile_tcl.c profile.swg)
+profile_tcl.o: $(srcdir)/profile_tcl.c profile.h
+profile_tcl: profile_tcl.o libprofile.a
+	$(CC_LINK) -o profile_tcl profile_tcl.o \
+		$(TCL_MAYBE_RPATH) \
+		-L../et -L../.. libprofile.a $(TCL_LIBS) $(MLIBS)
+
+clean-unix:: clean-libs clean-libobjs
+	$(RM) $(PROGS) *.o *~ test_parse core prof_err.h \
+		prof_err.c test_profile profile.h profile_tcl
+
+clean-windows::
+	$(RM) $(PROFILE_HDR)
+
+check-unix:: test_parse test_profile
+
+DO_TCL=@DO_TCL@
+check-unix:: check-unix-tcl-$(DO_TCL)
+
+check-unix-tcl-:
+	@echo "+++"
+	@echo "+++ Tcl not available, some profile tests not run."
+	@echo "+++"
+
+check-unix-tcl-ok: profile_tcl
+	cp $(srcdir)/test.ini test2.ini
+	$(KRB5_RUN_ENV) $(VALGRIND) ./profile_tcl $(srcdir)/prof_test1
+
+check-windows:: $(OUTPRE)test_profile.exe $(OUTPRE)test_parse.exe
+	$(RM) $(OUTPRE)*.obj
+	$(OUTPRE)test_parse test.ini
+
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+prof_tree.so prof_tree.po $(OUTPRE)prof_tree.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  prof_int.h prof_tree.c
+prof_file.so prof_file.po $(OUTPRE)prof_file.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  prof_file.c prof_int.h
+prof_parse.so prof_parse.po $(OUTPRE)prof_parse.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  prof_int.h prof_parse.c
+prof_get.so prof_get.po $(OUTPRE)prof_get.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  prof_get.c prof_int.h
+prof_set.so prof_set.po $(OUTPRE)prof_set.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  prof_int.h prof_set.c
+prof_err.so prof_err.po $(OUTPRE)prof_err.$(OBJEXT): \
+  $(COM_ERR_DEPS) prof_err.c
+prof_init.so prof_init.po $(OUTPRE)prof_init.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  prof_init.c prof_int.h
+test_parse.so test_parse.po $(OUTPRE)test_parse.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  prof_int.h test_parse.c
+test_profile.so test_profile.po $(OUTPRE)test_profile.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  argv_parse.h prof_int.h test_profile.c
+profile_tcl.so profile_tcl.po $(OUTPRE)profile_tcl.$(OBJEXT): \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) profile_tcl.c
diff --git a/krb5-1-6/src/util/profile/argv_parse.c b/krb5-1-6/src/util/profile/argv_parse.c
new file mode 100644
index 000000000..7740d5345
--- /dev/null
+++ b/krb5-1-6/src/util/profile/argv_parse.c
@@ -0,0 +1,168 @@
+/*
+ * argv_parse.c --- utility function for parsing a string into a
+ * 	argc, argv array.
+ * 
+ * This file defines a function argv_parse() which parsing a
+ * passed-in string, handling double quotes and backslashes, and
+ * creates an allocated argv vector which can be freed using the
+ * argv_free() function.
+ *
+ * See argv_parse.h for the formal definition of the functions.
+ *
+ * Copyright 1999 by Theodore Ts'o.
+ * 
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose with or without fee is hereby granted, provided that
+ * the above copyright notice and this permission notice appear in all
+ * copies.  THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
+ * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  (Isn't
+ * it sick that the U.S. culture of lawsuit-happy lawyers requires
+ * this kind of disclaimer?)
+ *
+ * Version 1.1, modified 2/27/1999
+ */
+
+#include "prof_int.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#include <string.h>
+#include "argv_parse.h"
+
+#define STATE_WHITESPACE	1
+#define STATE_TOKEN		2
+#define STATE_QUOTED		3
+
+/*
+ * Returns 0 on success, -1 on failure.
+ */
+int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
+{
+	int	argc = 0, max_argc = 0;
+	char 	**argv, **new_argv, *buf, ch;
+	char	*cp = 0, *outcp = 0;
+	int	state = STATE_WHITESPACE;
+
+	buf = malloc(strlen(in_buf)+1);
+	if (!buf)
+		return -1;
+
+	max_argc = 0; argc = 0; argv = 0;
+	outcp = buf;
+	for (cp = in_buf; (ch = *cp); cp++) {
+		if (state == STATE_WHITESPACE) {
+			if (isspace((int) ch))
+				continue;
+			/* Not whitespace, so start a new token */
+			state = STATE_TOKEN;
+			if (argc >= max_argc) {
+				max_argc += 3;
+				new_argv = realloc(argv,
+						  (max_argc+1)*sizeof(char *));
+				if (!new_argv) {
+					if (argv) free(argv);
+					free(buf);
+					return -1;
+				}
+				argv = new_argv;
+			}
+			argv[argc++] = outcp;
+		}
+		if (state == STATE_QUOTED) {
+			if (ch == '"')
+				state = STATE_TOKEN;
+			else
+				*outcp++ = ch;
+			continue;
+		}
+		/* Must be processing characters in a word */
+		if (isspace((int) ch)) {
+			/*
+			 * Terminate the current word and start
+			 * looking for the beginning of the next word.
+			 */
+			*outcp++ = 0;
+			state = STATE_WHITESPACE;
+			continue;
+		}
+		if (ch == '"') {
+			state = STATE_QUOTED;
+			continue;
+		}
+		if (ch == '\\') {
+			ch = *++cp;
+			switch (ch) {
+			case '\0':
+				ch = '\\'; cp--; break;
+			case 'n':
+				ch = '\n'; break;
+			case 't':
+				ch = '\t'; break;
+			case 'b':
+				ch = '\b'; break;
+			}
+		}
+		*outcp++ = ch;
+	}
+	if (state != STATE_WHITESPACE)
+		*outcp++ = '\0';
+	if (argv == 0) {
+		argv = malloc(sizeof(char *));
+		free(buf);
+	}
+	argv[argc] = 0;
+	if (ret_argc)
+		*ret_argc = argc;
+	if (ret_argv)
+		*ret_argv = argv;
+	return 0;
+}
+
+void argv_free(char **argv)
+{
+	if (*argv)
+		free(*argv);
+	free(argv);
+}
+
+#ifdef DEBUG
+/*
+ * For debugging
+ */
+
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+	int	ac, ret;
+	char	**av, **cpp;
+	char	buf[256];
+
+	while (!feof(stdin)) {
+		if (fgets(buf, sizeof(buf), stdin) == NULL)
+			break;
+		ret = argv_parse(buf, &ac, &av);
+		if (ret != 0) {
+			printf("Argv_parse returned %d!\n", ret);
+			continue;
+		}
+		printf("Argv_parse returned %d arguments...\n", ac);
+		for (cpp = av; *cpp; cpp++) {
+			if (cpp != av)
+				printf(", ");
+			printf("'%s'", *cpp);
+		}
+		printf("\n");
+		argv_free(av);
+	}
+	exit(0);
+}
+#endif /* DEBUG */
diff --git a/krb5-1-6/src/util/profile/argv_parse.h b/krb5-1-6/src/util/profile/argv_parse.h
new file mode 100644
index 000000000..84568e7bd
--- /dev/null
+++ b/krb5-1-6/src/util/profile/argv_parse.h
@@ -0,0 +1,43 @@
+/*
+ * argv_parse.h --- header file for the argv parser.
+ *
+ * This file defines the interface for the functions argv_parse() and
+ * argv_free().
+ * 
+ ***********************************************************************
+ * int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
+ *
+ * This function takes as its first argument a string which it will
+ * parse into an argv argument vector, with each white-space separated
+ * word placed into its own slot in the argv.  This function handles
+ * double quotes and backslashes so that the parsed words can contain
+ * special characters.   The count of the number words found in the
+ * parsed string, as well as the argument vector, are returned into
+ * ret_argc and ret_argv, respectively.
+ ***********************************************************************
+ * extern void argv_free(char **argv);
+ * 
+ * This function frees the argument vector created by argv_parse().
+ ***********************************************************************
+ *
+ * Copyright 1999 by Theodore Ts'o.
+ * 
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose with or without fee is hereby granted, provided that
+ * the above copyright notice and this permission notice appear in all
+ * copies.  THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
+ * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  (Isn't
+ * it sick that the U.S. culture of lawsuit-happy lawyers requires
+ * this kind of disclaimer?)
+ *
+ * Version 1.1, modified 2/27/1999
+ */
+
+extern int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv);
+extern void argv_free(char **argv);
diff --git a/krb5-1-6/src/util/profile/dosshell.ini b/krb5-1-6/src/util/profile/dosshell.ini
new file mode 100644
index 000000000..cec96ec59
--- /dev/null
+++ b/krb5-1-6/src/util/profile/dosshell.ini
@@ -0,0 +1,537 @@
+EGA.INI/VGA.INI
+****************  WARNING  ********************
+This file may contain lines with more than 256
+characters. Some editors will truncate or split
+these lines. If you are not sure whether your
+editor can handle long lines, exit now without
+saving the file.
+
+Note: The editor which is invoked by the
+	  MS-DOS 5.0 EDIT command can be used
+	  to edit this file.
+****************  NOTE  ***********************
+Everything up to the first left square bracket
+character is considered a comment.
+***********************************************
+[savestate]
+screenmode = text
+resolution = low
+startup = filemanager
+filemanagermode = shared
+sortkey = name
+pause = disabled
+explicitselection = disabled
+swapmouse = disabled
+tasklist = disabled
+switching = disabled
+[programstarter]
+currentcolor = Ocean
+filemanager = enabled
+command = enabled
+group = 
+{
+	program = 
+	{
+	command = COMMAND
+	title = Command Prompt
+	help = Starts the MS-DOS command prompt where you can type any MS-DOS command.^m^mTo return to MS-DOS Shell from the command line:^m^m1. Type exit^m2. Press ENTER.^m^mRelated Topic^m   " More on Command Prompt "~$129~
+	pause = disabled
+	}
+	program = 
+	{
+	command = EDIT %1
+	title = Editor
+	help = Starts MS-DOS Editor, a text editor you can use to create and modify text files. After you choose Editor, you can specify the file you want to work with in a dialog box.^m^mRelated Topic^m   " More on Editor "~$130~
+	pause = disabled
+	dialog = 
+	{
+		title = File to Edit
+		info = Enter the name of the file to edit. To start MS-DOS Editor without opening a file, press ENTER.
+		prompt = File to edit?
+		parameter = %1
+	}
+	}
+	program = 
+	{
+	command = QBASIC %1
+	title = MS-DOS QBasic
+	help = Starts MS-DOS QBasic, a programming environment you can use to create, modify, run, and debug programs. After you choose MS-DOS QBasic, you can specify the file you want to work with in a dialog box.^m^mRelated Topic^m   " More on MS-DOS QBasic "~$131~
+	pause = disabled
+	dialog = 
+	{
+		title = MS-DOS QBasic File
+		info = Enter the name of a QBasic program. To start without opening a program, press ENTER.
+		prompt = QBasic File?
+		parameter = %1
+	}
+	}
+	group = 
+	{
+	title = Disk Utilities
+	help = Displays program items you can choose to manage your disks. You can also choose to open the Main group or any group you may have added.
+	program = 
+	{
+		command = diskcopy %1
+		title = Disk Copy
+		pause = enabled
+		dialog = 
+		{
+		title = Disk Copy
+		info = Enter the source and destination drives.
+		prompt = Parameters . . .
+		default = a: b:
+		parameter = %1
+		}
+		help = Temporarily leaves MS-DOS Shell to copy the contents of a floppy disk to another floppy disk. After you choose Disk Copy, a dialog box suggests parameters and switches you can either accept or replace.^m^mRelated Topic^m   " More on Disk Copy "~$132~
+	}
+	program = 
+	{
+		command = backup %1
+		title = Backup Fixed Disk
+		pause = enabled
+		dialog = 
+		{
+		title = Backup Fixed Disk
+		info = Enter the source and destination drives.
+		prompt = Parameters . . .
+		default = c:\*.* a: /s
+		parameter = %1 
+		}
+		help = Temporarily leaves MS-DOS Shell to copy files from one disk to another. After you choose Backup Fixed Disk, a dialog box suggests parameters and switches you can either accept or replace.^m^mRelated Topic^m   " More on Backup Fixed Disk "~$133~
+	}
+	program = 
+	{
+		command = restore %1
+		title = Restore Fixed Disk
+		pause = enabled
+		dialog = 
+		{
+		title = Restore Fixed Disk
+		info = Enter the source and destination drives.
+		prompt = Parameters . . .
+		parameter = %1
+		}
+		help = Temporarily leaves MS-DOS Shell to restore files that were backed up. After you choose Restore Fixed Disk, a dialog box suggests parameters and switches you can either accept or replace.^m^mRelated Topic^m   " More on Restore Fixed Disk "~$134~
+	}
+	program = 
+	{
+		command = format %1 /q
+		title = Quick Format
+		pause = enabled
+		dialog = 
+		{
+		title = Quick Format
+		info = Enter the drive to quick format.
+		prompt = Parameters . . .
+		default = a:
+		parameter = %1
+		}
+		help = Temporarily leaves MS-DOS Shell to prepare a disk to accept MS-DOS files. After you choose Quick Format, a dialog box suggests parameters and switches you can either accept or replace.^m^mRelated Topic^m   " More on Quick Format "~$136~
+		screenmode = text
+		alttab = enabled
+		altesc = enabled
+		ctrlesc = enabled
+		prevent = enabled
+	}
+	program = 
+	{
+		command = format %1
+		title = Format
+		pause = enabled
+		dialog = 
+		{
+		title = Format
+		info = Enter the drive to format.
+		prompt = Parameters . . .
+		default = a:
+		parameter = %1
+		}
+		help = Temporarily leaves MS-DOS Shell to prepare a disk to accept MS-DOS files. After you choose Format, a dialog box suggests parameters and switches you can either accept or replace.^m^mRelated Topic^m   " More on Format "~$135~
+	}
+	program = 
+	{
+		command = undelete %1
+		title = Undelete
+		help = Recovers deleted files.^m^mWARNING: If your disk is full or if you are using task swapping, using this program item may render some deleted files unrecoverable.^m^mRelated Procedure^m   " Restoring Deleted Files "~I155~
+		pause = enabled
+		dialog = 
+		{
+		title = Undelete
+		info = WARNING! This action may cause the permanent loss of some deleted files.  Press F1 for more information.
+		prompt = Parameters . . .
+		default = /LIST
+		parameter = %1
+		}
+		screenmode = text
+		alttab = enabled
+		altesc = enabled
+		ctrlesc = enabled
+		prevent = enabled
+	}
+	}
+}
+color = 
+{
+	selection = 
+	{
+	title = Basic Blue
+	foreground = 
+	{
+		base = black
+		highlight = brightwhite
+		selection = brightwhite
+		alert = brightred
+		menubar = black
+		menu = black
+		disabled = white
+		accelerator = cyan
+		dialog = black
+		button = black
+		elevator = white
+		titlebar = black
+		scrollbar = brightwhite
+		borders = black
+		drivebox = black
+		driveicon = black
+		cursor = black
+	}
+	background = 
+	{
+		base = brightwhite
+		highlight = blue
+		selection = black
+		alert = brightwhite
+		menubar = white
+		menu = brightwhite
+		disabled = brightwhite
+		accelerator = brightwhite
+		dialog = brightwhite
+		button = white
+		elevator = white
+		titlebar = white
+		scrollbar = black
+		borders = brightwhite
+		drivebox = brightwhite
+		driveicon = brightwhite
+		cursor = brightblack
+	}
+	}
+	selection = 
+	{
+	title = Ocean
+	foreground = 
+	{
+		base = black
+		highlight = brightwhite
+		selection = brightwhite
+		alert = brightwhite
+		menubar = black
+		menu = black
+		disabled = white
+		accelerator = brightwhite
+		dialog = black
+		button = black
+		elevator = white
+		titlebar = black
+		scrollbar = brightwhite
+		borders = black
+		drivebox = black
+		driveicon = black
+		cursor = black
+	}
+	background = 
+	{
+		base = brightwhite
+		highlight = blue
+		selection = black
+		alert = white
+		menubar = cyan
+		menu = cyan
+		disabled = cyan
+		accelerator = cyan
+		dialog = cyan
+		button = brightwhite
+		elevator = white
+		titlebar = white
+		scrollbar = black
+		borders = black
+		drivebox = brightwhite
+		driveicon = brightwhite
+		cursor = brightcyan
+	}
+	}
+	selection = 
+	{
+	title = Monochrome-2 Colors
+	foreground = 
+	{
+		base = black
+		highlight = white
+		selection = white
+		alert = black
+		menubar = black
+		menu = black
+		disabled = white
+		accelerator = white
+		dialog = black
+		button = white
+		elevator = black
+		titlebar = white
+		scrollbar = white
+		borders = black
+		drivebox = black
+		driveicon = black
+	}
+	background = 
+	{
+		base = white
+		highlight = black
+		selection = black
+		alert = white
+		menubar = white
+		menu = white
+		disabled = white
+		accelerator = black
+		dialog = white
+		button = black
+		elevator = white
+		titlebar = black
+		scrollbar = black
+		borders = black
+		drivebox = white
+		driveicon = white
+	}
+	}
+	selection = 
+	{
+	title = Monochrome-4 Colors
+	foreground = 
+	{
+		base = black
+		highlight = brightwhite
+		selection = brightwhite
+		alert = black
+		menubar = black
+		menu = black
+		disabled = white
+		accelerator = brightwhite
+		dialog = black
+		button = black
+		elevator = white
+		titlebar = black
+		scrollbar = brightwhite
+		borders = black
+		drivebox = black
+		driveicon = black
+		cursor = black
+	}
+	background = 
+	{
+		base = brightwhite
+		highlight = brightblack
+		selection = brightblack
+		alert = brightwhite
+		menubar = brightwhite
+		menu = white
+		disabled = white
+		accelerator = brightblack
+		dialog = brightwhite
+		button = white
+		elevator = white
+		titlebar = white
+		scrollbar = black
+		borders = black
+		drivebox = brightwhite
+		driveicon = brightwhite
+		cursor = black
+	}
+	}
+	selection = 
+	{
+	title = Reverse
+	foreground = 
+	{
+		base = white
+		highlight = black
+		selection = black
+		alert = white
+		menubar = white
+		menu = white
+		disabled = black
+		accelerator = black
+		dialog = white
+		button = black
+		elevator = white
+		titlebar = black
+		scrollbar = black
+		borders = white
+		drivebox = white
+		driveicon = white
+	}
+	background = 
+	{
+		base = black
+		highlight = white
+		selection = white
+		alert = black
+		menubar = black
+		menu = black
+		disabled = black
+		accelerator = white
+		dialog = black
+		button = white
+		elevator = black
+		titlebar = white
+		scrollbar = white
+		borders = black
+		drivebox = black
+		driveicon = black
+	}
+	}
+	selection = 
+	{
+	title = Hot Pink
+	foreground = 
+	{
+		base = black
+		highlight = brightwhite
+		selection = brightwhite
+		alert = brightmagenta
+		menubar = black
+		menu = black
+		disabled = white
+		accelerator = magenta
+		dialog = black
+		button = brightwhite
+		elevator = white
+		titlebar = brightwhite
+		scrollbar = brightwhite
+		borders = black
+		drivebox = black
+		driveicon = black
+		cursor = black
+	}
+	background = 
+	{
+		base = brightwhite
+		highlight = brightmagenta
+		selection = magenta
+		alert = brightwhite
+		menubar = brightwhite
+		menu = brightwhite
+		disabled = brightwhite
+		accelerator = brightwhite
+		dialog = brightwhite
+		button = magenta
+		elevator = white
+		titlebar = magenta
+		scrollbar = black
+		borders = black
+		drivebox = brightwhite
+		driveicon = brightwhite
+		cursor = brightred
+	}
+	}
+	selection = 
+	{
+	title = Emerald City
+	foreground = 
+	{
+		base = black
+		highlight = black
+		selection = brightwhite
+		alert = green
+		menubar = black
+		menu = black
+		disabled = white
+		accelerator = green
+		dialog = black
+		button = brightwhite
+		elevator = white
+		titlebar = brightwhite
+		scrollbar = brightwhite
+		borders = black
+		drivebox = black
+		driveicon = black
+		cursor = black
+	}
+	background = 
+	{
+		base = brightwhite
+		highlight = brightgreen
+		selection = green
+		alert = brightwhite
+		menubar = brightwhite
+		menu = brightwhite
+		disabled = brightwhite
+		accelerator = brightwhite
+		dialog = brightwhite
+		button = green
+		elevator = white
+		titlebar = green
+		scrollbar = black
+		borders = black
+		drivebox = brightwhite
+		driveicon = brightwhite
+		cursor = brightcyan
+	}
+	}
+	selection = 
+	{
+	title = Turquoise
+	foreground = 
+	{
+		base = black
+		highlight = brightwhite
+		selection = brightwhite
+		alert = brightred
+		menubar = brightwhite
+		menu = black
+		disabled = white
+		accelerator = white
+		dialog = black
+		button = black
+		elevator = white
+		titlebar = black
+		scrollbar = brightwhite
+		borders = black
+		drivebox = black
+		driveicon = black
+		cursor = black
+	}
+	background = 
+	{
+		base = brightwhite
+		highlight = brightblue
+		selection = black
+		alert = brightwhite
+		menubar = brightcyan
+		menu = brightcyan
+		disabled = brightcyan
+		accelerator = brightcyan
+		dialog = brightcyan
+		button = brightwhite
+		elevator = white
+		titlebar = white
+		scrollbar = black
+		borders = black
+		drivebox = brightwhite
+		driveicon = brightwhite
+		cursor = cyan
+	}
+	}
+}
+
+associations = 
+{
+	association = 
+	{
+	program = EDIT
+	extension = TXT
+	}
+	association = 
+	{
+	program = QBASIC /run 
+	extension = BAS
+	}
+}
diff --git a/krb5-1-6/src/util/profile/krb5.conf b/krb5-1-6/src/util/profile/krb5.conf
new file mode 100644
index 000000000..19c59c60d
--- /dev/null
+++ b/krb5-1-6/src/util/profile/krb5.conf
@@ -0,0 +1,57 @@
+[libdefaults]
+	default_realm = ATHENA.MIT.EDU 
+	default_tgs_enctypes = des-cbc-crc
+	default_tkt_enctypes = des-cbc-crc
+	krb4_config = /etc/athena/krb.conf
+	krb4_realms = /etc/athena/krb.realms
+	default_keytab_name = FILE:/etc/krb5.keytab
+	kdc_timesync = 1
+	ccache_type = 4
+
+[realms] 
+	ATHENA.MIT.EDU = { 
+#		kdc = kerberos-2000.mit.edu
+		kdc = kerberos.mit.edu:88
+		kdc = kerberos-1.mit.edu:88
+		kdc = kerberos-2.mit.edu:88
+		kdc = kerberos-3.mit.edu:88
+		admin_server = kerberos.mit.edu
+		default_domain = mit.edu
+	} 
+	MEDIA-LAB.MIT.EDU = {
+		kdc = kerberos.media.mit.edu
+		admin_server = kerberos.media.mit.edu
+	}
+	ZONE.MIT.EDU = {
+		kdc = casio.mit.edu
+		kdc = seiko.mit.edu
+		admin_server = casio.mit.edu
+	}
+	MOOF.MIT.EDU = {
+		kdc = three-headed-dogcow.mit.edu:88
+		kdc = three-headed-dogcow-1.mit.edu:88
+		admin_server = three-headed-dogcow.mit.edu
+	}
+	CYGNUS.COM = {
+		kdc = KERBEROS-1.CYGNUS.COM
+		kdc = KERBEROS.CYGNUS.COM
+		admin_server = KERBEROS.CYGNUS.COM
+	}
+	GREY17.ORG = {
+		kdc = kerberos.grey17.org
+		admin_server = kerberos.grey17.org
+	}
+	IHTFP.ORG = {
+		kdc = kerberos.ihtfp.org
+		admin_server = kerberos.ihtfp.org
+	}
+
+[domain_realm]
+	.mit.edu = ATHENA.MIT.EDU
+	mit.edu = ATHENA.MIT.EDU
+	.media.mit.edu = MEDIA-LAB.MIT.EDU
+	media.mit.edu = MEDIA-LAB.MIT.EDU
+
+[login]
+	krb4_convert = true
+	krb4_get_tickets = true
diff --git a/krb5-1-6/src/util/profile/libprofile.exports b/krb5-1-6/src/util/profile/libprofile.exports
new file mode 100644
index 000000000..26db5e898
--- /dev/null
+++ b/krb5-1-6/src/util/profile/libprofile.exports
@@ -0,0 +1,55 @@
+et_prof_error_table
+initialize_prof_error_table
+profile_abandon
+profile_add_node
+profile_add_relation
+profile_clear_relation
+profile_close_file
+profile_create_node
+profile_dereference_data
+profile_find_node
+profile_find_node_relation
+profile_find_node_subsection
+profile_flush
+profile_flush_file_data
+profile_free_file
+profile_free_list
+profile_free_node
+profile_get_boolean
+profile_get_integer
+profile_get_node_name
+profile_get_node_parent
+profile_get_node_value
+profile_get_relation_names
+profile_get_string
+profile_get_subsection_names
+profile_get_value
+profile_get_values
+profile_init
+profile_init_path
+profile_is_node_final
+profile_iterator
+profile_iterator_create
+profile_iterator_free
+profile_make_node_final
+profile_node_iterator
+profile_node_iterator_create
+profile_node_iterator_free
+profile_open_file
+profile_parse_file
+profile_release
+profile_release_string
+profile_remove_node
+profile_rename_node
+profile_rename_section
+profile_ser_externalize
+profile_ser_internalize
+profile_ser_size
+profile_set_relation_value
+profile_update_file_data
+profile_update_relation
+profile_verify_node
+profile_write_tree_file
+profile_flush_to_file
+profile_flush_to_buffer
+profile_free_buffer
diff --git a/krb5-1-6/src/util/profile/prof_FSp_glue.c b/krb5-1-6/src/util/profile/prof_FSp_glue.c
new file mode 100644
index 000000000..511c85f15
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_FSp_glue.c
@@ -0,0 +1,91 @@
+/*
+ * prof_FSp_glue.c --- Deprecated FSSpec functions.  Mac-only.
+ */
+
+#include "prof_int.h"
+
+#include <Kerberos/FSpUtils.h>
+#include <limits.h>
+
+long KRB5_CALLCONV FSp_profile_init (const FSSpec* files, profile_t *ret_profile);
+
+long KRB5_CALLCONV FSp_profile_init_path (const FSSpec* files, profile_t *ret_profile);
+
+errcode_t KRB5_CALLCONV
+FSp_profile_init(files, ret_profile)
+	const FSSpec* files;
+	profile_t *ret_profile;
+{
+    unsigned int        fileCount = 0;
+    const FSSpec       *nextSpec;
+    profile_filespec_t *pathArray = NULL;
+    unsigned int        i;
+    errcode_t           retval = 0;
+
+    for (nextSpec = files; ; nextSpec++) {
+        if ((nextSpec -> vRefNum == 0) &&
+            (nextSpec -> parID == 0) &&
+            (StrLength (nextSpec -> name) == 0))
+            break;
+        fileCount++;
+    }
+    
+    pathArray = (profile_filespec_t *) malloc ((fileCount + 1) * sizeof(const_profile_filespec_t));
+    if (pathArray == NULL) {
+        retval = ENOMEM;
+    }
+    
+    if (retval == 0) {
+        for (i = 0; i < fileCount + 1; i++) {
+            pathArray [i] = NULL;
+        }
+    }
+        
+    if (retval == 0) {
+        for (i = 0; i < fileCount; i++) {
+            OSStatus err = noErr;
+            
+            if (err == noErr) {
+                pathArray[i] = (char *) malloc (sizeof(char) * PATH_MAX);
+                if (pathArray[i] == NULL) {
+                    err = memFullErr;
+                }
+            }
+            /* convert the FSSpec to an path */
+            if (err == noErr) {
+                err = FSSpecToPOSIXPath (&files[i], pathArray[i], PATH_MAX);
+            }
+
+            if (err == memFullErr) {
+                retval = ENOMEM;
+                break;
+            } else if (err != noErr) {
+                retval = ENOENT;
+                break;
+            }
+        }
+    }
+    
+    if (retval == 0) {
+        retval = profile_init ((const_profile_filespec_t *) pathArray, 
+                               ret_profile);
+    }
+    
+    if (pathArray != NULL) {
+        for (i = 0; i < fileCount; i++) {
+            if (pathArray [i] != 0)
+                free (pathArray [i]);
+        }
+        free (pathArray);
+    }
+    
+    return retval;
+}
+
+errcode_t KRB5_CALLCONV
+FSp_profile_init_path(files, ret_profile)
+	const FSSpec* files;
+	profile_t *ret_profile;
+{
+    return FSp_profile_init (files, ret_profile);
+}
diff --git a/krb5-1-6/src/util/profile/prof_err.et b/krb5-1-6/src/util/profile/prof_err.et
new file mode 100644
index 000000000..af7801ee0
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_err.et
@@ -0,0 +1,66 @@
+error_table prof
+
+error_code	PROF_VERSION,	"Profile version 0.0"
+
+#
+# generated by prof_tree.c
+#
+error_code	PROF_MAGIC_NODE,	"Bad magic value in profile_node"
+error_code	PROF_NO_SECTION,	"Profile section not found"
+error_code	PROF_NO_RELATION,	"Profile relation not found"
+error_code	PROF_ADD_NOT_SECTION, 
+	"Attempt to add a relation to node which is not a section"
+error_code	PROF_SECTION_WITH_VALUE, 
+	"A profile section header has a non-zero value"
+error_code	PROF_BAD_LINK_LIST, 	"Bad linked list in profile structures"
+error_code	PROF_BAD_GROUP_LVL, 	"Bad group level in profile strctures"
+error_code	PROF_BAD_PARENT_PTR, 	
+	"Bad parent pointer in profile strctures"
+error_code	PROF_MAGIC_ITERATOR,	"Bad magic value in profile iterator"
+error_code	PROF_SET_SECTION_VALUE,	"Can't set value on section node"
+error_code	PROF_EINVAL,		"Invalid argument passed to profile library"
+error_code	PROF_READ_ONLY,		"Attempt to modify read-only profile"
+
+#
+# generated by prof_parse.c
+#
+
+error_code	PROF_SECTION_NOTOP, "Profile section header not at top level"
+error_code	PROF_SECTION_SYNTAX, "Syntax error in profile section header"
+error_code	PROF_RELATION_SYNTAX, "Syntax error in profile relation"
+error_code	PROF_EXTRA_CBRACE, "Extra closing brace in profile"
+error_code	PROF_MISSING_OBRACE, "Missing open brace in profile"
+
+#
+# generated by prof_init.c
+# 
+error_code	PROF_MAGIC_PROFILE,	"Bad magic value in profile_t"
+error_code	PROF_MAGIC_SECTION,	"Bad magic value in profile_section_t"
+error_code	PROF_TOPSECTION_ITER_NOSUPP,
+	"Iteration through all top level section not supported"
+error_code	PROF_INVALID_SECTION,	"Invalid profile_section object"
+error_code	PROF_END_OF_SECTIONS,	"No more sections"
+error_code	PROF_BAD_NAMESET,	"Bad nameset passed to query routine"
+error_code	PROF_NO_PROFILE,	"No profile file open"
+
+#
+# generated by prof_file.c
+#
+error_code      PROF_MAGIC_FILE,	"Bad magic value in profile_file_t"
+error_code	PROF_FAIL_OPEN,		"Couldn't open profile file"
+
+#
+# generated by prof_set.c
+#
+error_code	PROF_EXISTS,		"Section already exists"
+
+#
+# generated by prof_get.c
+#
+error_code	PROF_BAD_BOOLEAN,		"Invalid boolean value"
+error_code	PROF_BAD_INTEGER,		"Invalid integer value"
+
+error_code	PROF_MAGIC_FILE_DATA, "Bad magic value in profile_file_data_t"
+
+
+end
diff --git a/krb5-1-6/src/util/profile/prof_file.c b/krb5-1-6/src/util/profile/prof_file.c
new file mode 100644
index 000000000..265ccd6cf
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_file.c
@@ -0,0 +1,607 @@
+/*
+ * prof_file.c ---- routines that manipulate an individual profile file.
+ */
+
+#include "prof_int.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stddef.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#if defined(_WIN32)
+#include <io.h>
+#define HAVE_STAT	
+#define stat _stat
+#endif
+
+#include "k5-platform.h"
+
+struct global_shared_profile_data {
+	/* This is the head of the global list of shared trees */
+	prf_data_t trees;
+	/* Lock for above list.  */
+	k5_mutex_t mutex;
+};
+#define g_shared_trees		(krb5int_profile_shared_data.trees)
+#define g_shared_trees_mutex	(krb5int_profile_shared_data.mutex)
+
+static struct global_shared_profile_data krb5int_profile_shared_data = {
+    0,
+    K5_MUTEX_PARTIAL_INITIALIZER
+};
+
+MAKE_INIT_FUNCTION(profile_library_initializer);
+MAKE_FINI_FUNCTION(profile_library_finalizer);
+
+int profile_library_initializer(void)
+{
+#ifdef SHOW_INITFINI_FUNCS
+    printf("profile_library_initializer\n");
+#endif
+#if !USE_BUNDLE_ERROR_STRINGS
+    add_error_table(&et_prof_error_table);
+#endif
+    return k5_mutex_finish_init(&g_shared_trees_mutex);
+}
+void profile_library_finalizer(void)
+{
+    if (! INITIALIZER_RAN(profile_library_initializer) || PROGRAM_EXITING()) {
+#ifdef SHOW_INITFINI_FUNCS
+	printf("profile_library_finalizer: skipping\n");
+#endif
+	return;
+    }
+#ifdef SHOW_INITFINI_FUNCS
+    printf("profile_library_finalizer\n");
+#endif
+    k5_mutex_destroy(&g_shared_trees_mutex);
+#if !USE_BUNDLE_ERROR_STRINGS
+    remove_error_table(&et_prof_error_table);
+#endif
+}
+
+static void profile_free_file_data(prf_data_t);
+
+#if 0
+
+#define scan_shared_trees_locked()				\
+	{							\
+	    prf_data_t d;					\
+	    k5_mutex_assert_locked(&g_shared_trees_mutex);	\
+	    for (d = g_shared_trees; d; d = d->next) {		\
+		assert(d->magic == PROF_MAGIC_FILE_DATA);	\
+		assert((d->flags & PROFILE_FILE_SHARED) != 0);	\
+		assert(d->filespec[0] != 0);			\
+		assert(d->fslen <= 1000); /* XXX */		\
+		assert(d->filespec[d->fslen] == 0);		\
+		assert(d->fslen = strlen(d->filespec));		\
+		assert(d->root != NULL);			\
+	    }							\
+	}
+
+#define scan_shared_trees_unlocked()			\
+	{						\
+	    int r;					\
+	    r = k5_mutex_lock(&g_shared_trees_mutex);	\
+	    assert (r == 0);				\
+	    scan_shared_trees_locked();			\
+	    k5_mutex_unlock(&g_shared_trees_mutex);	\
+	}
+
+#else
+
+#define scan_shared_trees_locked()	{ ; }
+#define scan_shared_trees_unlocked()	{ ; }
+
+#endif
+
+static int rw_access(const_profile_filespec_t filespec)
+{
+#ifdef HAVE_ACCESS
+	if (access(filespec, W_OK) == 0)
+		return 1;
+	else
+		return 0;
+#else
+	/*
+	 * We're on a substandard OS that doesn't support access.  So
+	 * we kludge a test using stdio routines, and hope fopen
+	 * checks the r/w permissions.
+	 */
+	FILE	*f;
+
+	f = fopen(filespec, "r+");
+	if (f) {
+		fclose(f);
+		return 1;
+	}
+	return 0;
+#endif
+}
+
+static int r_access(const_profile_filespec_t filespec)
+{
+#ifdef HAVE_ACCESS
+	if (access(filespec, R_OK) == 0)
+		return 1;
+	else
+		return 0;
+#else
+	/*
+	 * We're on a substandard OS that doesn't support access.  So
+	 * we kludge a test using stdio routines, and hope fopen
+	 * checks the r/w permissions.
+	 */
+	FILE	*f;
+
+	f = fopen(filespec, "r");
+	if (f) {
+		fclose(f);
+		return 1;
+	}
+	return 0;
+#endif
+}
+
+prf_data_t
+profile_make_prf_data(const char *filename)
+{
+    prf_data_t d;
+    size_t len, flen, slen;
+    char *fcopy;
+
+    flen = strlen(filename);
+    slen = offsetof(struct _prf_data_t, filespec);
+    len = slen + flen + 1;
+    if (len < sizeof(struct _prf_data_t))
+	len = sizeof(struct _prf_data_t);
+    d = malloc(len);
+    if (d == NULL)
+	return NULL;
+    memset(d, 0, len);
+    fcopy = (char *) d + slen;
+    assert(fcopy == d->filespec);
+    strcpy(fcopy, filename);
+    d->refcount = 1;
+    d->comment = NULL;
+    d->magic = PROF_MAGIC_FILE_DATA;
+    d->root = NULL;
+    d->next = NULL;
+    d->fslen = flen;
+    return d;
+}
+
+errcode_t profile_open_file(const_profile_filespec_t filespec,
+			    prf_file_t *ret_prof)
+{
+	prf_file_t	prf;
+	errcode_t	retval;
+	char		*home_env = 0;
+	unsigned int	len;
+	prf_data_t	data;
+	char		*expanded_filename;
+
+	retval = CALL_INIT_FUNCTION(profile_library_initializer);
+	if (retval)
+		return retval;
+
+	scan_shared_trees_unlocked();
+
+	prf = malloc(sizeof(struct _prf_file_t));
+	if (!prf)
+		return ENOMEM;
+	memset(prf, 0, sizeof(struct _prf_file_t));
+	prf->magic = PROF_MAGIC_FILE;
+
+	len = strlen(filespec)+1;
+	if (filespec[0] == '~' && filespec[1] == '/') {
+		home_env = getenv("HOME");
+#ifdef HAVE_PWD_H
+		if (home_env == NULL) {
+		    uid_t uid;
+		    struct passwd *pw, pwx;
+		    char pwbuf[BUFSIZ];
+
+		    uid = getuid();
+		    if (!k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw)
+			&& pw != NULL && pw->pw_dir[0] != 0)
+			home_env = pw->pw_dir;
+		}
+#endif
+		if (home_env)
+			len += strlen(home_env);
+	}
+	expanded_filename = malloc(len);
+	if (expanded_filename == 0)
+	    return errno;
+	if (home_env) {
+	    strcpy(expanded_filename, home_env);
+	    strcat(expanded_filename, filespec+1);
+	} else
+	    memcpy(expanded_filename, filespec, len);
+
+	retval = k5_mutex_lock(&g_shared_trees_mutex);
+	if (retval) {
+	    free(expanded_filename);
+	    free(prf);
+	    scan_shared_trees_unlocked();
+	    return retval;
+	}
+	scan_shared_trees_locked();
+	for (data = g_shared_trees; data; data = data->next) {
+	    if (!strcmp(data->filespec, expanded_filename)
+		/* Check that current uid has read access.  */
+		&& r_access(data->filespec))
+		break;
+	}
+	if (data) {
+	    data->refcount++;
+	    (void) k5_mutex_unlock(&g_shared_trees_mutex);
+	    retval = profile_update_file_data(data);
+	    free(expanded_filename);
+	    prf->data = data;
+	    *ret_prof = prf;
+	    scan_shared_trees_unlocked();
+	    return retval;
+	}
+	(void) k5_mutex_unlock(&g_shared_trees_mutex);
+	data = profile_make_prf_data(expanded_filename);
+	if (data == NULL) {
+	    free(prf);
+	    free(expanded_filename);
+	    return ENOMEM;
+	}
+	free(expanded_filename);
+	prf->data = data;
+
+	retval = k5_mutex_init(&data->lock);
+	if (retval) {
+	    free(data);
+	    free(prf);
+	    return retval;
+	}
+
+	retval = profile_update_file(prf);
+	if (retval) {
+		profile_close_file(prf);
+		return retval;
+	}
+
+	retval = k5_mutex_lock(&g_shared_trees_mutex);
+	if (retval) {
+	    profile_close_file(prf);
+	    scan_shared_trees_unlocked();
+	    return retval;
+	}
+	scan_shared_trees_locked();
+	data->flags |= PROFILE_FILE_SHARED;
+	data->next = g_shared_trees;
+	g_shared_trees = data;
+	scan_shared_trees_locked();
+	(void) k5_mutex_unlock(&g_shared_trees_mutex);
+
+	*ret_prof = prf;
+	return 0;
+}
+
+errcode_t profile_update_file_data(prf_data_t data)
+{
+	errcode_t retval;
+#ifdef HAVE_STAT
+	struct stat st;
+	unsigned long frac;
+	time_t now;
+#endif
+	FILE *f;
+
+	retval = k5_mutex_lock(&data->lock);
+	if (retval)
+	    return retval;
+
+#ifdef HAVE_STAT
+	now = time(0);
+	if (now == data->last_stat && data->root != NULL) {
+	    k5_mutex_unlock(&data->lock);
+	    return 0;
+	}
+	if (stat(data->filespec, &st)) {
+	    retval = errno;
+	    k5_mutex_unlock(&data->lock);
+	    return retval;
+	}
+	data->last_stat = now;
+#if defined HAVE_STRUCT_STAT_ST_MTIMENSEC
+	frac = st.st_mtimensec;
+#elif defined HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
+	frac = st.st_mtimespec.tv_nsec;
+#elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+	frac = st.st_mtim.tv_nsec;
+#else
+	frac = 0;
+#endif
+	if (st.st_mtime == data->timestamp
+	    && frac == data->frac_ts
+	    && data->root != NULL) {
+	    k5_mutex_unlock(&data->lock);
+	    return 0;
+	}
+	if (data->root) {
+		profile_free_node(data->root);
+		data->root = 0;
+	}
+	if (data->comment) {
+		free(data->comment);
+		data->comment = 0;
+	}
+#else
+	/*
+	 * If we don't have the stat() call, assume that our in-core
+	 * memory image is correct.  That is, we won't reread the
+	 * profile file if it changes.
+	 */
+	if (data->root) {
+	    k5_mutex_unlock(&data->lock);
+	    return 0;
+	}
+#endif
+	errno = 0;
+	f = fopen(data->filespec, "r");
+	if (f == NULL) {
+		retval = errno;
+		k5_mutex_unlock(&data->lock);
+		if (retval == 0)
+			retval = ENOENT;
+		return retval;
+	}
+	data->upd_serial++;
+	data->flags &= PROFILE_FILE_SHARED;
+	if (rw_access(data->filespec))
+		data->flags |= PROFILE_FILE_RW;
+	retval = profile_parse_file(f, &data->root);
+	fclose(f);
+	if (retval) {
+	    k5_mutex_unlock(&data->lock);
+	    return retval;
+	}
+	assert(data->root != NULL);
+#ifdef HAVE_STAT
+	data->timestamp = st.st_mtime;
+	data->frac_ts = frac;
+#endif
+	k5_mutex_unlock(&data->lock);
+	return 0;
+}
+
+static int
+make_hard_link(const char *oldpath, const char *newpath)
+{
+#ifdef _WIN32
+    return -1;
+#else
+    return link(oldpath, newpath);
+#endif
+}
+
+static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
+				    int can_create)
+{
+	FILE		*f;
+	profile_filespec_t new_file;
+	profile_filespec_t old_file;
+	errcode_t	retval = 0;
+
+	retval = ENOMEM;
+	
+	new_file = old_file = 0;
+	new_file = malloc(strlen(outfile) + 5);
+	if (!new_file)
+		goto errout;
+	old_file = malloc(strlen(outfile) + 5);
+	if (!old_file)
+		goto errout;
+
+	sprintf(new_file, "%s.$$$", outfile);
+	sprintf(old_file, "%s.bak", outfile);
+
+	errno = 0;
+
+	f = fopen(new_file, "w");
+	if (!f) {
+		retval = errno;
+		if (retval == 0)
+			retval = PROF_FAIL_OPEN;
+		goto errout;
+	}
+
+	profile_write_tree_file(data->root, f);
+	if (fclose(f) != 0) {
+		retval = errno;
+		goto errout;
+	}
+
+	unlink(old_file);
+	if (make_hard_link(outfile, old_file) == 0) {
+	    /* Okay, got the hard link.  Yay.  Now we've got our
+	       backup version, so just put the new version in
+	       place.  */
+	    if (rename(new_file, outfile)) {
+		/* Weird, the rename didn't work.  But the old version
+		   should still be in place, so no special cleanup is
+		   needed.  */
+		retval = errno;
+		goto errout;
+	    }
+	} else if (errno == ENOENT && can_create) {
+	    if (rename(new_file, outfile)) {
+		retval = errno;
+		goto errout;
+	    }
+	} else {
+	    /* Couldn't make the hard link, so there's going to be a
+	       small window where data->filespec does not refer to
+	       either version.  */
+#ifndef _WIN32
+	    sync();
+#endif
+	    if (rename(outfile, old_file)) {
+		retval = errno;
+		goto errout;
+	    }
+	    if (rename(new_file, outfile)) {
+		retval = errno;
+		rename(old_file, outfile); /* back out... */
+		goto errout;
+	    }
+	}
+
+	data->flags = 0;
+	if (rw_access(outfile))
+		data->flags |= PROFILE_FILE_RW;
+	retval = 0;
+
+errout:
+	if (new_file)
+		free(new_file);
+	if (old_file)
+		free(old_file);
+	return retval;
+}
+
+errcode_t profile_flush_file_data_to_buffer (prf_data_t data, char **bufp)
+{
+	errcode_t	retval;
+	retval = k5_mutex_lock(&data->lock);
+	if (retval)
+		return retval;
+	retval = profile_write_tree_to_buffer(data->root, bufp);
+	k5_mutex_unlock(&data->lock);
+	return retval;
+}
+
+errcode_t profile_flush_file_data(prf_data_t data)
+{
+	errcode_t	retval = 0;
+
+	if (!data || data->magic != PROF_MAGIC_FILE_DATA)
+		return PROF_MAGIC_FILE_DATA;
+
+	retval = k5_mutex_lock(&data->lock);
+	if (retval)
+	    return retval;
+	
+	if ((data->flags & PROFILE_FILE_DIRTY) == 0) {
+	    k5_mutex_unlock(&data->lock);
+	    return 0;
+	}
+
+	retval = write_data_to_file(data, data->filespec, 0);
+	k5_mutex_unlock(&data->lock);
+	return retval;
+}
+
+errcode_t profile_flush_file_data_to_file(prf_data_t data, const char *outfile)
+{
+    errcode_t retval = 0;
+
+    if (!data || data->magic != PROF_MAGIC_FILE_DATA)
+	return PROF_MAGIC_FILE_DATA;
+
+    retval = k5_mutex_lock(&data->lock);
+    if (retval)
+	return retval;
+    retval = write_data_to_file(data, outfile, 1);
+    k5_mutex_unlock(&data->lock);
+    return retval;
+}
+
+
+
+void profile_dereference_data(prf_data_t data)
+{
+    int err;
+    err = k5_mutex_lock(&g_shared_trees_mutex);
+    if (err)
+	return;
+    profile_dereference_data_locked(data);
+    (void) k5_mutex_unlock(&g_shared_trees_mutex);
+}
+void profile_dereference_data_locked(prf_data_t data)
+{
+    scan_shared_trees_locked();
+    data->refcount--;
+    if (data->refcount == 0)
+	profile_free_file_data(data);
+    scan_shared_trees_locked();
+}
+
+int profile_lock_global()
+{
+    return k5_mutex_lock(&g_shared_trees_mutex);
+}
+int profile_unlock_global()
+{
+    return k5_mutex_unlock(&g_shared_trees_mutex);
+}
+
+void profile_free_file(prf_file_t prf)
+{
+    profile_dereference_data(prf->data);
+    free(prf);
+}
+
+/* Call with mutex locked!  */
+static void profile_free_file_data(prf_data_t data)
+{
+    scan_shared_trees_locked();
+    if (data->flags & PROFILE_FILE_SHARED) {
+	/* Remove from linked list.  */
+	if (g_shared_trees == data)
+	    g_shared_trees = data->next;
+	else {
+	    prf_data_t prev, next;
+	    prev = g_shared_trees;
+	    next = prev->next;
+	    while (next) {
+		if (next == data) {
+		    prev->next = next->next;
+		    break;
+		}
+		prev = next;
+		next = next->next;
+	    }
+	}
+    }
+    if (data->root)
+	profile_free_node(data->root);
+    if (data->comment)
+	free(data->comment);
+    data->magic = 0;
+    k5_mutex_destroy(&data->lock);
+    free(data);
+    scan_shared_trees_locked();
+}
+
+errcode_t profile_close_file(prf_file_t prf)
+{
+	errcode_t	retval;
+	
+	retval = profile_flush_file(prf);
+	if (retval)
+		return retval;
+	profile_free_file(prf);
+	return 0;
+}
diff --git a/krb5-1-6/src/util/profile/prof_get.c b/krb5-1-6/src/util/profile/prof_get.c
new file mode 100644
index 000000000..08fac7f06
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_get.c
@@ -0,0 +1,462 @@
+/*
+ * prof_get.c --- routines that expose the public interfaces for
+ * 	querying items from the profile.
+ *
+ */
+
+#include "prof_int.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+#include <limits.h>
+
+/*
+ * These functions --- init_list(), end_list(), and add_to_list() are
+ * internal functions used to build up a null-terminated char ** list
+ * of strings to be returned by functions like profile_get_values.
+ *
+ * The profile_string_list structure is used for internal booking
+ * purposes to build up the list, which is returned in *ret_list by
+ * the end_list() function.
+ *
+ * The publicly exported interface for freeing char** list is
+ * profile_free_list().
+ */
+
+struct profile_string_list {
+	char	**list;
+	int	num;
+	int	max;
+};
+
+/*
+ * Initialize the string list abstraction.
+ */
+static errcode_t init_list(struct profile_string_list *list)
+{
+	list->num = 0;
+	list->max = 10;
+	list->list = malloc(list->max * sizeof(char *));
+	if (list->list == 0)
+		return ENOMEM;
+	list->list[0] = 0;
+	return 0;
+}
+
+/*
+ * Free any memory left over in the string abstraction, returning the
+ * built up list in *ret_list if it is non-null.
+ */
+static void end_list(struct profile_string_list *list, char ***ret_list)
+{
+	char	**cp;
+
+	if (list == 0)
+		return;
+
+	if (ret_list) {
+		*ret_list = list->list;
+		return;
+	} else {
+		for (cp = list->list; *cp; cp++)
+			free(*cp);
+		free(list->list);
+	}
+	list->num = list->max = 0;
+	list->list = 0;
+}
+
+/*
+ * Add a string to the list.
+ */
+static errcode_t add_to_list(struct profile_string_list *list, const char *str)
+{
+	char 	*newstr, **newlist;
+	int	newmax;
+	
+	if (list->num+1 >= list->max) {
+		newmax = list->max + 10;
+		newlist = realloc(list->list, newmax * sizeof(char *));
+		if (newlist == 0)
+			return ENOMEM;
+		list->max = newmax;
+		list->list = newlist;
+	}
+	newstr = malloc(strlen(str)+1);
+	if (newstr == 0)
+		return ENOMEM;
+	strcpy(newstr, str);
+
+	list->list[list->num++] = newstr;
+	list->list[list->num] = 0;
+	return 0;
+}
+
+/*
+ * Return TRUE if the string is already a member of the list.
+ */
+static int is_list_member(struct profile_string_list *list, const char *str)
+{
+	char **cpp;
+
+	if (!list->list)
+		return 0;
+
+	for (cpp = list->list; *cpp; cpp++) {
+		if (!strcmp(*cpp, str))
+			return 1;
+	}
+	return 0;
+}	
+	
+/*
+ * This function frees a null-terminated list as returned by
+ * profile_get_values.
+ */
+void KRB5_CALLCONV profile_free_list(char **list)
+{
+    char	**cp;
+
+    if (list == 0)
+	    return;
+    
+    for (cp = list; *cp; cp++)
+	free(*cp);
+    free(list);
+}
+
+errcode_t KRB5_CALLCONV
+profile_get_values(profile_t profile, const char *const *names,
+		   char ***ret_values)
+{
+	errcode_t		retval;
+	void			*state;
+	char			*value;
+	struct profile_string_list values;
+
+	if ((retval = profile_node_iterator_create(profile, names,
+						   PROFILE_ITER_RELATIONS_ONLY,
+						   &state)))
+		return retval;
+
+	if ((retval = init_list(&values)))
+		return retval;
+
+	do {
+		if ((retval = profile_node_iterator(&state, 0, 0, &value)))
+			goto cleanup;
+		if (value)
+			add_to_list(&values, value);
+	} while (state);
+
+	if (values.num == 0) {
+		retval = PROF_NO_RELATION;
+		goto cleanup;
+	}
+
+	end_list(&values, ret_values);
+	return 0;
+	
+cleanup:
+	end_list(&values, 0);
+	return retval;
+}
+
+/*
+ * This function only gets the first value from the file; it is a
+ * helper function for profile_get_string, profile_get_integer, etc.
+ */
+errcode_t profile_get_value(profile_t profile, const char **names,
+			    const char **ret_value)
+{
+	errcode_t		retval;
+	void			*state;
+	char			*value;
+
+	if ((retval = profile_node_iterator_create(profile, names,
+						   PROFILE_ITER_RELATIONS_ONLY,
+						   &state)))
+		return retval;
+
+	if ((retval = profile_node_iterator(&state, 0, 0, &value)))
+		goto cleanup;
+
+	if (value)
+		*ret_value = value;
+	else
+		retval = PROF_NO_RELATION;
+	
+cleanup:
+	profile_node_iterator_free(&state);
+	return retval;
+}
+
+errcode_t KRB5_CALLCONV
+profile_get_string(profile_t profile, const char *name, const char *subname,
+		   const char *subsubname, const char *def_val,
+		   char **ret_string)
+{
+	const char	*value;
+	errcode_t	retval;
+	const char	*names[4];
+
+	if (profile) {
+		names[0] = name;
+		names[1] = subname;
+		names[2] = subsubname;
+		names[3] = 0;
+		retval = profile_get_value(profile, names, &value);
+		if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION)
+			value = def_val;
+		else if (retval)
+			return retval;
+	} else
+		value = def_val;
+    
+	if (value) {
+		*ret_string = malloc(strlen(value)+1);
+		if (*ret_string == 0)
+			return ENOMEM;
+		strcpy(*ret_string, value);
+	} else
+		*ret_string = 0;
+	return 0;
+}
+
+errcode_t KRB5_CALLCONV
+profile_get_integer(profile_t profile, const char *name, const char *subname,
+		    const char *subsubname, int def_val, int *ret_int)
+{
+	const char	*value;
+	errcode_t	retval;
+	const char	*names[4];
+	char            *end_value;
+	long		ret_long;
+
+	*ret_int = def_val;
+	if (profile == 0)
+		return 0;
+
+	names[0] = name;
+	names[1] = subname;
+	names[2] = subsubname;
+	names[3] = 0;
+	retval = profile_get_value(profile, names, &value);
+	if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
+		*ret_int = def_val;
+		return 0;
+	} else if (retval)
+		return retval;
+
+	if (value[0] == 0)
+	    /* Empty string is no good.  */
+	    return PROF_BAD_INTEGER;
+	errno = 0;
+	ret_long = strtol (value, &end_value, 10);
+
+	/* Overflow or underflow.  */
+	if ((ret_long == LONG_MIN || ret_long == LONG_MAX) && errno != 0)
+	    return PROF_BAD_INTEGER;
+	/* Value outside "int" range.  */
+	if ((long) (int) ret_long != ret_long)
+	    return PROF_BAD_INTEGER;
+	/* Garbage in string.  */
+	if (end_value != value + strlen (value))
+	    return PROF_BAD_INTEGER;
+	
+   
+	*ret_int = ret_long;
+	return 0;
+}
+
+static const char *const conf_yes[] = {
+    "y", "yes", "true", "t", "1", "on",
+    0,
+};
+
+static const char *const conf_no[] = {
+    "n", "no", "false", "nil", "0", "off",
+    0,
+};
+
+static errcode_t
+profile_parse_boolean(const char *s, int *ret_boolean)
+{
+    const char *const *p;
+    
+    if (ret_boolean == NULL)
+    	return PROF_EINVAL;
+
+    for(p=conf_yes; *p; p++) {
+		if (!strcasecmp(*p,s)) {
+			*ret_boolean = 1;
+	    	return 0;
+		}
+    }
+
+    for(p=conf_no; *p; p++) {
+		if (!strcasecmp(*p,s)) {
+			*ret_boolean = 0;
+			return 0;
+		}
+    }
+	
+	return PROF_BAD_BOOLEAN;
+}
+
+errcode_t KRB5_CALLCONV
+profile_get_boolean(profile_t profile, const char *name, const char *subname,
+		    const char *subsubname, int def_val, int *ret_boolean)
+{
+	const char	*value;
+	errcode_t	retval;
+	const char	*names[4];
+
+	if (profile == 0) {
+		*ret_boolean = def_val;
+		return 0;
+	}
+
+	names[0] = name;
+	names[1] = subname;
+	names[2] = subsubname;
+	names[3] = 0;
+	retval = profile_get_value(profile, names, &value);
+	if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
+		*ret_boolean = def_val;
+		return 0;
+	} else if (retval)
+		return retval;
+   
+	return profile_parse_boolean (value, ret_boolean);
+}
+
+/*
+ * This function will return the list of the names of subections in the
+ * under the specified section name.
+ */
+errcode_t KRB5_CALLCONV
+profile_get_subsection_names(profile_t profile, const char **names,
+			     char ***ret_names)
+{
+	errcode_t		retval;
+	void			*state;
+	char			*name;
+	struct profile_string_list values;
+
+	if ((retval = profile_node_iterator_create(profile, names,
+		   PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
+		   &state)))
+		return retval;
+
+	if ((retval = init_list(&values)))
+		return retval;
+
+	do {
+		if ((retval = profile_node_iterator(&state, 0, &name, 0)))
+			goto cleanup;
+		if (name)
+			add_to_list(&values, name);
+	} while (state);
+
+	end_list(&values, ret_names);
+	return 0;
+	
+cleanup:
+	end_list(&values, 0);
+	return retval;
+}
+
+/*
+ * This function will return the list of the names of relations in the
+ * under the specified section name.
+ */
+errcode_t KRB5_CALLCONV
+profile_get_relation_names(profile_t profile, const char **names,
+			   char ***ret_names)
+{
+	errcode_t		retval;
+	void			*state;
+	char			*name;
+	struct profile_string_list values;
+
+	if ((retval = profile_node_iterator_create(profile, names,
+		   PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
+		   &state)))
+		return retval;
+
+	if ((retval = init_list(&values)))
+		return retval;
+
+	do {
+		if ((retval = profile_node_iterator(&state, 0, &name, 0)))
+			goto cleanup;
+		if (name && !is_list_member(&values, name))
+			add_to_list(&values, name);
+	} while (state);
+
+	end_list(&values, ret_names);
+	return 0;
+	
+cleanup:
+	end_list(&values, 0);
+	return retval;
+}
+
+errcode_t KRB5_CALLCONV
+profile_iterator_create(profile_t profile, const char *const *names, int flags,
+			void **ret_iter)
+{
+	return profile_node_iterator_create(profile, names, flags, ret_iter);
+}
+
+void KRB5_CALLCONV
+profile_iterator_free(void **iter_p)
+{
+	profile_node_iterator_free(iter_p);
+}
+
+errcode_t KRB5_CALLCONV
+profile_iterator(void **iter_p, char **ret_name, char **ret_value)
+{
+	char *name, *value;
+	errcode_t	retval;
+	
+	retval = profile_node_iterator(iter_p, 0, &name, &value);
+	if (retval)
+		return retval;
+
+	if (ret_name) {
+		if (name) {
+			*ret_name = malloc(strlen(name)+1);
+			if (!*ret_name)
+				return ENOMEM;
+			strcpy(*ret_name, name);
+		} else
+			*ret_name = 0;
+	}
+	if (ret_value) {
+		if (value) {
+			*ret_value = malloc(strlen(value)+1);
+			if (!*ret_value) {
+				if (ret_name) {
+					free(*ret_name);
+					*ret_name = 0;
+				}
+				return ENOMEM;
+			}
+			strcpy(*ret_value, value);
+		} else
+			*ret_value = 0;
+	}
+	return 0;
+}
+
+void KRB5_CALLCONV
+profile_release_string(char *str)
+{
+	free(str);
+}
diff --git a/krb5-1-6/src/util/profile/prof_init.c b/krb5-1-6/src/util/profile/prof_init.c
new file mode 100644
index 000000000..e5c6f9c8c
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_init.c
@@ -0,0 +1,402 @@
+/*
+ * prof_init.c --- routines that manipulate the user-visible profile_t
+ * 	object.
+ */
+
+#include "prof_int.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+typedef int32_t prof_int32;
+
+errcode_t KRB5_CALLCONV
+profile_init(const_profile_filespec_t *files, profile_t *ret_profile)
+{
+	const_profile_filespec_t *fs;
+	profile_t profile;
+	prf_file_t  new_file, last = 0;
+	errcode_t retval = 0;
+
+	profile = malloc(sizeof(struct _profile_t));
+	if (!profile)
+		return ENOMEM;
+	memset(profile, 0, sizeof(struct _profile_t));
+	profile->magic = PROF_MAGIC_PROFILE;
+
+        /* if the filenames list is not specified return an empty profile */
+        if ( files ) {
+	    for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) {
+		retval = profile_open_file(*fs, &new_file);
+		/* if this file is missing, skip to the next */
+		if (retval == ENOENT || retval == EACCES) {
+			continue;
+		}
+		if (retval) {
+			profile_release(profile);
+			return retval;
+		}
+		if (last)
+			last->next = new_file;
+		else
+			profile->first_file = new_file;
+		last = new_file;
+	    }
+	    /*
+	     * If last is still null after the loop, then all the files were
+	     * missing, so return the appropriate error.
+	     */
+	    if (!last) {
+		profile_release(profile);
+		return ENOENT;
+	    }
+	}
+
+        *ret_profile = profile;
+        return 0;
+}
+
+#define COUNT_LINKED_LIST(COUNT, PTYPE, START, FIELD)	\
+	{						\
+	    int cll_counter = 0;			\
+	    PTYPE cll_ptr = (START);			\
+	    while (cll_ptr != NULL) {			\
+		cll_counter++;				\
+		cll_ptr = cll_ptr->FIELD;		\
+	    }						\
+	    (COUNT) = cll_counter;			\
+	}
+
+errcode_t KRB5_CALLCONV
+profile_copy(profile_t old_profile, profile_t *new_profile)
+{
+    size_t size, i;
+    const_profile_filespec_t *files;
+    prf_file_t file;
+    errcode_t err;
+
+    /* The fields we care about are read-only after creation, so
+       no locking is needed.  */
+    COUNT_LINKED_LIST (size, prf_file_t, old_profile->first_file, next);
+    files = malloc ((size+1) * sizeof(*files));
+    if (files == NULL)
+	return errno;
+    for (i = 0, file = old_profile->first_file; i < size; i++, file = file->next)
+	files[i] = file->data->filespec;
+    files[size] = NULL;
+    err = profile_init (files, new_profile);
+    free (files);
+    return err;
+}
+
+errcode_t KRB5_CALLCONV
+profile_init_path(const_profile_filespec_list_t filepath,
+		  profile_t *ret_profile)
+{
+	int n_entries, i;
+	unsigned int ent_len;
+	const char *s, *t;
+	profile_filespec_t *filenames;
+	errcode_t retval;
+
+	/* count the distinct filename components */
+	for(s = filepath, n_entries = 1; *s; s++) {
+		if (*s == ':')
+			n_entries++;
+	}
+	
+	/* the array is NULL terminated */
+	filenames = (profile_filespec_t*) malloc((n_entries+1) * sizeof(char*));
+	if (filenames == 0)
+		return ENOMEM;
+
+	/* measure, copy, and skip each one */
+	for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
+		ent_len = t-s;
+		filenames[i] = (char*) malloc(ent_len + 1);
+		if (filenames[i] == 0) {
+			/* if malloc fails, free the ones that worked */
+			while(--i >= 0) free(filenames[i]);
+                        free(filenames);
+			return ENOMEM;
+		}
+		strncpy(filenames[i], s, ent_len);
+		filenames[i][ent_len] = 0;
+		if (*t == 0) {
+			i++;
+			break;
+		}
+	}
+	/* cap the array */
+	filenames[i] = 0;
+
+	retval = profile_init((const_profile_filespec_t *) filenames, 
+			      ret_profile);
+
+	/* count back down and free the entries */
+	while(--i >= 0) free(filenames[i]);
+	free(filenames);
+
+	return retval;
+}
+
+errcode_t KRB5_CALLCONV
+profile_is_writable(profile_t profile, int *writable)
+{
+    if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+        return PROF_MAGIC_PROFILE;
+    
+    if (!writable) 
+        return EINVAL;
+    
+    if (profile->first_file)
+        *writable = (profile->first_file->data->flags & PROFILE_FILE_RW);
+    
+    return 0;
+}
+
+errcode_t KRB5_CALLCONV
+profile_is_modified(profile_t profile, int *modified)
+{
+    if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+        return PROF_MAGIC_PROFILE;
+    
+    if (!modified) 
+        return EINVAL;
+    
+    if (profile->first_file)
+        *modified = (profile->first_file->data->flags & PROFILE_FILE_DIRTY);
+    
+    return 0;
+}
+
+errcode_t KRB5_CALLCONV
+profile_flush(profile_t profile)
+{
+	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+		return PROF_MAGIC_PROFILE;
+
+	if (profile->first_file)
+		return profile_flush_file(profile->first_file);
+
+	return 0;
+}
+
+errcode_t KRB5_CALLCONV
+profile_flush_to_file(profile_t profile, const_profile_filespec_t outfile)
+{
+	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+		return PROF_MAGIC_PROFILE;
+
+	if (profile->first_file)
+		return profile_flush_file_to_file(profile->first_file,
+						  outfile);
+
+	return 0;
+}
+
+errcode_t KRB5_CALLCONV
+profile_flush_to_buffer(profile_t profile, char **buf)
+{
+    return profile_flush_file_data_to_buffer(profile->first_file->data, buf);
+}
+
+void KRB5_CALLCONV
+profile_free_buffer(profile_t profile, char *buf)
+{
+    free(buf);
+}
+
+void KRB5_CALLCONV
+profile_abandon(profile_t profile)
+{
+	prf_file_t	p, next;
+
+	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+		return;
+
+	for (p = profile->first_file; p; p = next) {
+		next = p->next;
+		profile_free_file(p);
+	}
+	profile->magic = 0;
+	free(profile);
+}
+
+void KRB5_CALLCONV
+profile_release(profile_t profile)
+{
+	prf_file_t	p, next;
+
+	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+		return;
+
+	for (p = profile->first_file; p; p = next) {
+		next = p->next;
+		profile_close_file(p);
+	}
+	profile->magic = 0;
+	free(profile);
+}
+
+/*
+ * Here begins the profile serialization functions.
+ */
+errcode_t profile_ser_size(const char *unused, profile_t profile,
+			   size_t *sizep)
+{
+    size_t	required;
+    prf_file_t	pfp;
+
+    required = 3*sizeof(prof_int32);
+    for (pfp = profile->first_file; pfp; pfp = pfp->next) {
+	required += sizeof(prof_int32);
+	required += strlen(pfp->data->filespec);
+    }
+    *sizep += required;
+    return 0;
+}
+
+static void pack_int32(prof_int32 oval, unsigned char **bufpp, size_t *remainp)
+{
+    (*bufpp)[0] = (unsigned char) ((oval >> 24) & 0xff);
+    (*bufpp)[1] = (unsigned char) ((oval >> 16) & 0xff);
+    (*bufpp)[2] = (unsigned char) ((oval >> 8) & 0xff);
+    (*bufpp)[3] = (unsigned char) (oval & 0xff);
+    *bufpp += sizeof(prof_int32);
+    *remainp -= sizeof(prof_int32);
+}
+
+errcode_t profile_ser_externalize(const char *unused, profile_t profile,
+				  unsigned char **bufpp, size_t *remainp)
+{
+    errcode_t		retval;
+    size_t		required;
+    unsigned char	*bp;
+    size_t		remain;
+    prf_file_t		pfp;
+    prof_int32		fcount, slen;
+
+    required = 0;
+    bp = *bufpp;
+    remain = *remainp;
+    retval = EINVAL;
+    if (profile) {
+	retval = ENOMEM;
+	(void) profile_ser_size(unused, profile, &required);
+	if (required <= remain) {
+	    fcount = 0;
+	    for (pfp = profile->first_file; pfp; pfp = pfp->next)
+		fcount++;
+	    pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
+	    pack_int32(fcount, &bp, &remain);
+	    for (pfp = profile->first_file; pfp; pfp = pfp->next) {
+		slen = (prof_int32) strlen(pfp->data->filespec);
+		pack_int32(slen, &bp, &remain);
+		if (slen) {
+		    memcpy(bp, pfp->data->filespec, (size_t) slen);
+		    bp += slen;
+		    remain -= (size_t) slen;
+		}
+	    }
+	    pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
+	    retval = 0;
+	    *bufpp = bp;
+	    *remainp = remain;
+	}
+    }
+    return(retval);
+}
+
+static int unpack_int32(prof_int32 *intp, unsigned char **bufpp,
+			size_t *remainp)
+{
+    if (*remainp >= sizeof(prof_int32)) {
+	*intp = (((prof_int32) (*bufpp)[0] << 24) |
+		 ((prof_int32) (*bufpp)[1] << 16) |
+		 ((prof_int32) (*bufpp)[2] << 8) |
+		 ((prof_int32) (*bufpp)[3]));
+	*bufpp += sizeof(prof_int32);
+	*remainp -= sizeof(prof_int32);
+	return 0;
+    }
+    else
+	return 1;
+}
+
+errcode_t profile_ser_internalize(const char *unused, profile_t *profilep,
+				  unsigned char **bufpp, size_t *remainp)
+{
+	errcode_t		retval;
+	unsigned char	*bp;
+	size_t		remain;
+	int			i;
+	prof_int32		fcount, tmp;
+	profile_filespec_t		*flist = 0;
+
+	bp = *bufpp;
+	remain = *remainp;
+
+	if (remain >= 12)
+		(void) unpack_int32(&tmp, &bp, &remain);
+	else
+		tmp = 0;
+	
+	if (tmp != PROF_MAGIC_PROFILE) {
+		retval = EINVAL;
+		goto cleanup;
+	}
+	
+	(void) unpack_int32(&fcount, &bp, &remain);
+	retval = ENOMEM;
+
+	flist = (profile_filespec_t *) malloc(sizeof(profile_filespec_t) * (fcount + 1));
+	if (!flist)
+		goto cleanup;
+	
+	memset(flist, 0, sizeof(char *) * (fcount+1));
+	for (i=0; i<fcount; i++) {
+		if (!unpack_int32(&tmp, &bp, &remain)) {
+			flist[i] = (char *) malloc((size_t) (tmp+1));
+			if (!flist[i])
+				goto cleanup;
+			memcpy(flist[i], bp, (size_t) tmp);
+			flist[i][tmp] = '\0';
+			bp += tmp;
+			remain -= (size_t) tmp;
+		}
+	}
+
+	if (unpack_int32(&tmp, &bp, &remain) ||
+	    (tmp != PROF_MAGIC_PROFILE)) {
+		retval = EINVAL;
+		goto cleanup;
+	}
+
+	if ((retval = profile_init((const_profile_filespec_t *) flist, 
+				   profilep)))
+		goto cleanup;
+	
+	*bufpp = bp;
+	*remainp = remain;
+    
+cleanup:
+	if (flist) {
+		for (i=0; i<fcount; i++) {
+			if (flist[i])
+				free(flist[i]);
+		}
+		free(flist);
+	}
+	return(retval);
+}
diff --git a/krb5-1-6/src/util/profile/prof_int.h b/krb5-1-6/src/util/profile/prof_int.h
new file mode 100644
index 000000000..d6349afd7
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_int.h
@@ -0,0 +1,244 @@
+/*
+ * prof-int.h
+ */
+
+#include <time.h>
+#include <stdio.h>
+
+#if defined(__MACH__) && defined(__APPLE__)
+#include <TargetConditionals.h>
+#define PROFILE_SUPPORTS_FOREIGN_NEWLINES
+#endif
+
+#include "k5-thread.h"
+#include "k5-platform.h"
+#include "com_err.h"
+#include "profile.h"
+
+typedef long prf_magic_t;
+
+/*
+ * This is the structure which stores the profile information for a
+ * particular configuration file.
+ *
+ * Locking strategy:
+ * - filespec, fslen are fixed after creation
+ * - refcount and next should only be tweaked with the global lock held
+ * - other fields can be tweaked after grabbing the in-struct lock
+ */
+struct _prf_data_t {
+	prf_magic_t	magic;
+	k5_mutex_t	lock;
+	struct profile_node *root;
+	time_t		last_stat;
+	time_t		timestamp; /* time tree was last updated from file */
+	unsigned long	frac_ts;   /* fractional part of timestamp, if any */
+	int		flags;	/* r/w, dirty */
+	int		upd_serial; /* incremented when data changes */
+	char		*comment;
+
+	size_t		fslen;
+
+	/* Some separation between fields controlled by different
+	   mutexes.  Theoretically, both could be accessed at the same
+	   time from different threads on different CPUs with separate
+	   caches.  Don't let the threads clobber each other's
+	   changes.  One mutex controlling the whole thing would be
+	   better, but sufficient separation might suffice.
+
+	   This is icky.  I just hope it's adequate.
+
+	   For next major release, fix this.  */
+	union { double d; void *p; UINT64_TYPE ll; k5_mutex_t m; } pad;
+
+	int		refcount; /* prf_file_t references */
+	struct _prf_data_t *next;
+	/* Was: "profile_filespec_t filespec".  Now: flexible char
+	   array ... except, we need to work in C89, so an array
+	   length must be specified.  */
+	const char	filespec[sizeof("/etc/krb5.conf")];
+};
+
+typedef struct _prf_data_t *prf_data_t;
+prf_data_t profile_make_prf_data(const char *);
+
+struct _prf_file_t {
+	prf_magic_t	magic;
+	struct _prf_data_t	*data;
+	struct _prf_file_t *next;
+};
+
+typedef struct _prf_file_t *prf_file_t;
+
+/*
+ * The profile flags
+ */
+#define PROFILE_FILE_RW		0x0001
+#define PROFILE_FILE_DIRTY	0x0002
+#define PROFILE_FILE_SHARED	0x0004
+
+/*
+ * This structure defines the high-level, user visible profile_t
+ * object, which is used as a handle by users who need to query some
+ * configuration file(s)
+ */
+struct _profile_t {
+	prf_magic_t	magic;
+	prf_file_t	first_file;
+};
+
+/*
+ * Used by the profile iterator in prof_get.c
+ */
+#define PROFILE_ITER_LIST_SECTION	0x0001
+#define PROFILE_ITER_SECTIONS_ONLY	0x0002
+#define PROFILE_ITER_RELATIONS_ONLY	0x0004
+
+#define PROFILE_ITER_FINAL_SEEN		0x0100
+
+/*
+ * Check if a filespec is last in a list (NULL on UNIX, invalid FSSpec on MacOS
+ */
+
+#define	PROFILE_LAST_FILESPEC(x) (((x) == NULL) || ((x)[0] == '\0'))
+
+/* profile_parse.c */
+
+errcode_t profile_parse_file
+	(FILE *f, struct profile_node **root);
+
+errcode_t profile_write_tree_file
+	(struct profile_node *root, FILE *dstfile);
+
+errcode_t profile_write_tree_to_buffer
+	(struct profile_node *root, char **buf);
+
+
+/* prof_tree.c */
+
+void profile_free_node
+	(struct profile_node *relation);
+
+errcode_t profile_create_node
+	(const char *name, const char *value,
+		   struct profile_node **ret_node);
+
+errcode_t profile_verify_node
+	(struct profile_node *node);
+
+errcode_t profile_add_node
+	(struct profile_node *section,
+		    const char *name, const char *value,
+		    struct profile_node **ret_node);
+
+errcode_t profile_make_node_final
+	(struct profile_node *node);
+	
+int profile_is_node_final
+	(struct profile_node *node);
+
+const char *profile_get_node_name
+	(struct profile_node *node);
+
+const char *profile_get_node_value
+	(struct profile_node *node);
+
+errcode_t profile_find_node
+	(struct profile_node *section,
+		    const char *name, const char *value,
+		    int section_flag, void **state,
+		    struct profile_node **node);
+
+errcode_t profile_find_node_relation
+	(struct profile_node *section,
+		    const char *name, void **state,
+		    char **ret_name, char **value);
+
+errcode_t profile_find_node_subsection
+	(struct profile_node *section,
+		    const char *name, void **state,
+		    char **ret_name, struct profile_node **subsection);
+		   
+errcode_t profile_get_node_parent
+	(struct profile_node *section,
+		   struct profile_node **parent);
+		   
+errcode_t profile_delete_node_relation
+	(struct profile_node *section, const char *name);
+
+errcode_t profile_find_node_name
+	(struct profile_node *section, void **state,
+		    char **ret_name);
+
+errcode_t profile_node_iterator_create
+	(profile_t profile, const char *const *names,
+		   int flags, void **ret_iter);
+
+void profile_node_iterator_free
+	(void	**iter_p);
+
+errcode_t profile_node_iterator
+	(void	**iter_p, struct profile_node **ret_node,
+		   char **ret_name, char **ret_value);
+
+errcode_t profile_remove_node
+	(struct profile_node *node);
+
+errcode_t profile_set_relation_value
+	(struct profile_node *node, const char *new_value);
+
+errcode_t profile_rename_node
+	(struct profile_node *node, const char *new_name);
+
+/* prof_file.c */
+
+errcode_t KRB5_CALLCONV profile_copy (profile_t, profile_t *);
+
+errcode_t profile_open_file
+	(const_profile_filespec_t file, prf_file_t *ret_prof);
+
+#define profile_update_file(P) profile_update_file_data((P)->data)
+errcode_t profile_update_file_data
+	(prf_data_t profile);
+
+#define profile_flush_file(P) (((P) && (P)->magic == PROF_MAGIC_FILE) ? profile_flush_file_data((P)->data) : PROF_MAGIC_FILE)
+errcode_t profile_flush_file_data
+	(prf_data_t data);
+
+#define profile_flush_file_to_file(P,F) (((P) && (P)->magic == PROF_MAGIC_FILE) ? profile_flush_file_data_to_file((P)->data, (F)) : PROF_MAGIC_FILE)
+errcode_t profile_flush_file_data_to_file
+	(prf_data_t data, const char *outfile);
+
+errcode_t profile_flush_file_data_to_buffer
+	(prf_data_t data, char **bufp);
+
+void profile_free_file
+	(prf_file_t profile);
+
+errcode_t profile_close_file
+	(prf_file_t profile);
+
+void profile_dereference_data (prf_data_t);
+void profile_dereference_data_locked (prf_data_t);
+
+int profile_lock_global (void);
+int profile_unlock_global (void);
+
+/* prof_init.c -- included from profile.h */
+errcode_t profile_ser_size
+        (const char *, profile_t, size_t *);
+
+errcode_t profile_ser_externalize
+        (const char *, profile_t, unsigned char **, size_t *);
+
+errcode_t profile_ser_internalize
+        (const char *, profile_t *, unsigned char **, size_t *);
+
+/* prof_get.c */
+
+errcode_t profile_get_value
+	(profile_t profile, const char **names,
+		    const char	**ret_value);
+/* Others included from profile.h */
+	
+/* prof_set.c -- included from profile.h */
diff --git a/krb5-1-6/src/util/profile/prof_parse.c b/krb5-1-6/src/util/profile/prof_parse.c
new file mode 100644
index 000000000..db491591d
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_parse.c
@@ -0,0 +1,494 @@
+#include "prof_int.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+#include <ctype.h>
+
+#define SECTION_SEP_CHAR '/'
+
+#define STATE_INIT_COMMENT	1
+#define STATE_STD_LINE		2
+#define STATE_GET_OBRACE	3
+
+struct parse_state {
+	int	state;
+	int	group_level;
+	struct profile_node *root_section;
+	struct profile_node *current_section;
+};
+
+static char *skip_over_blanks(char *cp)
+{
+	while (*cp && isspace((int) (*cp)))
+		cp++;
+	return cp;
+}
+
+static void strip_line(char *line)
+{
+	char *p = line + strlen(line);
+	while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
+	    *p-- = 0;
+}
+
+static void parse_quoted_string(char *str)
+{
+	char *to, *from;
+
+	to = from = str;
+
+	for (to = from = str; *from && *from != '"'; to++, from++) {
+		if (*from == '\\') {
+			from++;
+			switch (*from) {
+			case 'n':
+				*to = '\n';
+				break;
+			case 't':
+				*to = '\t';
+				break;
+			case 'b':
+				*to = '\b';
+				break;
+			default:
+				*to = *from;
+			}
+			continue;
+		}
+		*to = *from;
+	}
+	*to = '\0';
+}
+
+
+static errcode_t parse_init_state(struct parse_state *state)
+{
+	state->state = STATE_INIT_COMMENT;
+	state->group_level = 0;
+
+	return profile_create_node("(root)", 0, &state->root_section);
+}
+
+static errcode_t parse_std_line(char *line, struct parse_state *state)
+{
+	char	*cp, ch, *tag, *value;
+	char	*p;
+	errcode_t retval;
+	struct profile_node	*node;
+	int do_subsection = 0;
+	void *iter = 0;
+	
+	if (*line == 0)
+		return 0;
+	cp = skip_over_blanks(line);
+	if (cp[0] == ';' || cp[0] == '#')
+		return 0;
+	strip_line(cp);
+	ch = *cp;
+	if (ch == 0)
+		return 0;
+	if (ch == '[') {
+		if (state->group_level > 0)
+			return PROF_SECTION_NOTOP;
+		cp++;
+		p = strchr(cp, ']');
+		if (p == NULL)
+			return PROF_SECTION_SYNTAX;
+		*p = '\0';
+		retval = profile_find_node_subsection(state->root_section,
+						 cp, &iter, 0,
+						 &state->current_section);
+		if (retval == PROF_NO_SECTION) {
+			retval = profile_add_node(state->root_section,
+						  cp, 0,
+						  &state->current_section);
+			if (retval)
+				return retval;
+		} else if (retval)
+			return retval;
+
+		/*
+		 * Finish off the rest of the line.
+		 */
+		cp = p+1;
+		if (*cp == '*') {
+			profile_make_node_final(state->current_section);
+			cp++;
+		}
+		/*
+		 * A space after ']' should not be fatal 
+		 */
+		cp = skip_over_blanks(cp);
+		if (*cp)
+			return PROF_SECTION_SYNTAX;
+		return 0;
+	}
+	if (ch == '}') {
+		if (state->group_level == 0)
+			return PROF_EXTRA_CBRACE;
+		if (*(cp+1) == '*')
+			profile_make_node_final(state->current_section);
+		retval = profile_get_node_parent(state->current_section,
+						 &state->current_section);
+		if (retval)
+			return retval;
+		state->group_level--;
+		return 0;
+	}
+	/*
+	 * Parse the relations
+	 */
+	tag = cp;
+	cp = strchr(cp, '=');
+	if (!cp)
+		return PROF_RELATION_SYNTAX;
+	if (cp == tag)
+	    return PROF_RELATION_SYNTAX;
+	*cp = '\0';
+	p = tag;
+	/* Look for whitespace on left-hand side.  */
+	while (p < cp && !isspace((int)*p))
+	    p++;
+	if (p < cp) {
+	    /* Found some sort of whitespace.  */
+	    *p++ = 0;
+	    /* If we have more non-whitespace, it's an error.  */
+	    while (p < cp) {
+		if (!isspace((int)*p))
+		    return PROF_RELATION_SYNTAX;
+		p++;
+	    }
+	}
+	cp = skip_over_blanks(cp+1);
+	value = cp;
+	if (value[0] == '"') {
+		value++;
+		parse_quoted_string(value);
+	} else if (value[0] == 0) {
+		do_subsection++;
+		state->state = STATE_GET_OBRACE;
+	} else if (value[0] == '{' && *(skip_over_blanks(value+1)) == 0)
+		do_subsection++;
+	else {
+		cp = value + strlen(value) - 1;
+		while ((cp > value) && isspace((int) (*cp)))
+			*cp-- = 0;
+	}
+	if (do_subsection) {
+		p = strchr(tag, '*');
+		if (p)
+			*p = '\0';
+		retval = profile_add_node(state->current_section,
+					  tag, 0, &state->current_section);
+		if (retval)
+			return retval;
+		if (p)
+			profile_make_node_final(state->current_section);
+		state->group_level++;
+		return 0;
+	}
+	p = strchr(tag, '*');
+	if (p)
+		*p = '\0';
+	profile_add_node(state->current_section, tag, value, &node);
+	if (p)
+		profile_make_node_final(node);
+	return 0;
+}
+
+static errcode_t parse_line(char *line, struct parse_state *state)
+{
+	char	*cp;
+	
+	switch (state->state) {
+	case STATE_INIT_COMMENT:
+		if (line[0] != '[')
+			return 0;
+		state->state = STATE_STD_LINE;
+	case STATE_STD_LINE:
+		return parse_std_line(line, state);
+	case STATE_GET_OBRACE:
+		cp = skip_over_blanks(line);
+		if (*cp != '{')
+			return PROF_MISSING_OBRACE;
+		state->state = STATE_STD_LINE;
+	}
+	return 0;
+}
+
+errcode_t profile_parse_file(FILE *f, struct profile_node **root)
+{
+#define BUF_SIZE	2048
+	char *bptr;
+	errcode_t retval;
+	struct parse_state state;
+
+	bptr = malloc (BUF_SIZE);
+	if (!bptr)
+		return ENOMEM;
+
+	retval = parse_init_state(&state);
+	if (retval) {
+		free (bptr);
+		return retval;
+	}
+	while (!feof(f)) {
+		if (fgets(bptr, BUF_SIZE, f) == NULL)
+			break;
+#ifndef PROFILE_SUPPORTS_FOREIGN_NEWLINES
+		retval = parse_line(bptr, &state);
+		if (retval) {
+			free (bptr);
+			return retval;
+		}
+#else
+		{
+		    char *p, *end;
+
+		    if (strlen(bptr) >= BUF_SIZE - 1) {
+			/* The string may have foreign newlines and
+			   gotten chopped off on a non-newline
+			   boundary.  Seek backwards to the last known
+			   newline.  */
+			long offset;
+			char *c = bptr + strlen (bptr);
+			for (offset = 0; offset > -BUF_SIZE; offset--) {
+			    if (*c == '\r' || *c == '\n') {
+				*c = '\0';
+				fseek (f, offset, SEEK_CUR);
+				break;
+			    }
+			    c--;
+			}
+		    }
+
+		    /* First change all newlines to \n */
+		    for (p = bptr; *p != '\0'; p++) {
+			if (*p == '\r')
+                            *p = '\n';
+		    }
+		    /* Then parse all lines */
+		    p = bptr;
+		    end = bptr + strlen (bptr);
+		    while (p < end) {
+			char* newline;
+			char* newp;
+
+			newline = strchr (p, '\n');
+			if (newline != NULL)
+			    *newline = '\0';
+
+			/* parse_line modifies contents of p */
+			newp = p + strlen (p) + 1;
+			retval = parse_line (p, &state);
+			if (retval) {
+			    free (bptr);
+			    return retval;
+			}
+
+			p = newp;
+		    }
+		}
+#endif
+	}
+	*root = state.root_section;
+
+	free (bptr);
+	return 0;
+}
+
+/*
+ * Return TRUE if the string begins or ends with whitespace
+ */
+static int need_double_quotes(char *str)
+{
+	if (!str)
+                return 0;
+        if (*str)
+		return 1;
+	if (isspace((int) (*str)) ||isspace((int) (*(str + strlen(str) - 1))))
+		return 1;
+	if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b'))
+		return 1;
+	return 0;
+}
+
+/*
+ * Output a string with double quotes, doing appropriate backquoting
+ * of characters as necessary.
+ */
+static void output_quoted_string(char *str, void (*cb)(const char *,void *),
+				 void *data)
+{
+	char	ch;
+	char buf[2];
+
+	cb("\"", data);
+	if (!str) {
+		cb("\"", data);
+		return;
+	}
+	buf[1] = 0;
+	while ((ch = *str++)) {
+		switch (ch) {
+		case '\\':
+			cb("\\\\", data);
+			break;
+		case '\n':
+			cb("\\n", data);
+			break;
+		case '\t':
+			cb("\\t", data);
+			break;
+		case '\b':
+			cb("\\b", data);
+			break;
+		default:
+			/* This would be a lot faster if we scanned
+			   forward for the next "interesting"
+			   character.  */
+			buf[0] = ch;
+			cb(buf, data);
+			break;
+		}
+	}
+	cb("\"", data);
+}
+
+
+
+#if defined(_WIN32)
+#define EOL "\r\n"
+#endif
+
+#ifndef EOL
+#define EOL "\n"
+#endif
+
+/* Errors should be returned, not ignored!  */
+static void dump_profile(struct profile_node *root, int level,
+			 void (*cb)(const char *, void *), void *data)
+{
+	int i;
+	struct profile_node *p;
+	void *iter;
+	long retval;
+	char *name, *value;
+	
+	iter = 0;
+	do {
+		retval = profile_find_node_relation(root, 0, &iter,
+						    &name, &value);
+		if (retval)
+			break;
+		for (i=0; i < level; i++)
+			cb("\t", data);
+		if (need_double_quotes(value)) {
+			cb(name, data);
+			cb(" = ", data);
+			output_quoted_string(value, cb, data);
+			cb(EOL, data);
+		} else {
+			cb(name, data);
+			cb(" = ", data);
+			cb(value, data);
+			cb(EOL, data);
+		}
+	} while (iter != 0);
+
+	iter = 0;
+	do {
+		retval = profile_find_node_subsection(root, 0, &iter,
+						      &name, &p);
+		if (retval)
+			break;
+		if (level == 0)	{ /* [xxx] */
+			cb("[", data);
+			cb(name, data);
+			cb("]", data);
+			cb(profile_is_node_final(p) ? "*" : "", data);
+			cb(EOL, data);
+			dump_profile(p, level+1, cb, data);
+			cb(EOL, data);
+		} else { 	/* xxx = { ... } */
+			for (i=0; i < level; i++)
+				cb("\t", data);
+			cb(name, data);
+			cb(" = {", data);
+			cb(EOL, data);
+			dump_profile(p, level+1, cb, data);
+			for (i=0; i < level; i++)
+				cb("\t", data);
+			cb("}", data);
+			cb(profile_is_node_final(p) ? "*" : "", data);
+			cb(EOL, data);
+		}
+	} while (iter != 0);
+}
+
+static void dump_profile_to_file_cb(const char *str, void *data)
+{
+	fputs(str, data);
+}
+
+errcode_t profile_write_tree_file(struct profile_node *root, FILE *dstfile)
+{
+	dump_profile(root, 0, dump_profile_to_file_cb, dstfile);
+	return 0;
+}
+
+struct prof_buf {
+	char *base;
+	size_t cur, max;
+	int err;
+};
+
+static void add_data_to_buffer(struct prof_buf *b, const void *d, size_t len)
+{
+	if (b->err)
+		return;
+	if (b->max - b->cur < len) {
+		size_t newsize;
+		char *newptr;
+
+		newsize = b->max + (b->max >> 1) + len + 1024;
+		newptr = realloc(b->base, newsize);
+		if (newptr == NULL) {
+			b->err = 1;
+			return;
+		}
+		b->base = newptr;
+		b->max = newsize;
+	}
+	memcpy(b->base + b->cur, d, len);
+	b->cur += len; 		/* ignore overflow */
+}
+
+static void dump_profile_to_buffer_cb(const char *str, void *data)
+{
+	add_data_to_buffer((struct prof_buf *)data, str, strlen(str));
+}
+
+errcode_t profile_write_tree_to_buffer(struct profile_node *root,
+				       char **buf)
+{
+	struct prof_buf prof_buf = { 0, 0, 0, 0 };
+
+	dump_profile(root, 0, dump_profile_to_buffer_cb, &prof_buf);
+	if (prof_buf.err) {
+		*buf = NULL;
+		return ENOMEM;
+	}
+	add_data_to_buffer(&prof_buf, "", 1); /* append nul */
+	if (prof_buf.max - prof_buf.cur > (prof_buf.max >> 3)) {
+		char *newptr = realloc(prof_buf.base, prof_buf.cur);
+		if (newptr)
+			prof_buf.base = newptr;
+	}
+	*buf = prof_buf.base;
+	return 0;
+}
diff --git a/krb5-1-6/src/util/profile/prof_set.c b/krb5-1-6/src/util/profile/prof_set.c
new file mode 100644
index 000000000..85f228630
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_set.c
@@ -0,0 +1,286 @@
+/*
+ * prof_set.c --- routines that expose the public interfaces for
+ * 	inserting, updating and deleting items from the profile.
+ *
+ * WARNING: These routines only look at the first file opened in the
+ * profile.  It's not clear how to handle multiple files, actually.
+ * In the future it may be necessary to modify this public interface,
+ * or possibly add higher level functions to support this correctly.
+ *
+ * WARNING: We're not yet doing locking yet, either.  
+ *
+ */
+
+#include "prof_int.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+
+static errcode_t rw_setup(profile_t profile)
+{
+   	prf_file_t	file;
+	errcode_t	retval = 0;
+
+	if (!profile)
+		return PROF_NO_PROFILE;
+
+	if (profile->magic != PROF_MAGIC_PROFILE)
+		return PROF_MAGIC_PROFILE;
+
+	file = profile->first_file;
+
+	retval = profile_lock_global();
+	if (retval)
+	    return retval;
+
+	/* Don't update the file if we've already made modifications */
+	if (file->data->flags & PROFILE_FILE_DIRTY) {
+	    profile_unlock_global();
+	    return 0;
+	}
+
+	if ((file->data->flags & PROFILE_FILE_SHARED) != 0) {
+	    prf_data_t new_data;
+	    new_data = profile_make_prf_data(file->data->filespec);
+	    if (new_data == NULL) {
+		retval = ENOMEM;
+	    } else {
+		retval = k5_mutex_init(&new_data->lock);
+		if (retval == 0) {
+		    new_data->root = NULL;
+		    new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED;
+		    new_data->timestamp = 0;
+		    new_data->upd_serial = file->data->upd_serial;
+		}
+	    }
+
+	    if (retval != 0) {
+		profile_unlock_global();
+		free(new_data);
+		return retval;
+	    }
+	    profile_dereference_data_locked(file->data);
+	    file->data = new_data;
+	}
+
+	profile_unlock_global();
+	retval = profile_update_file(file);
+
+	return retval;
+}
+
+
+/* 
+ * Delete or update a particular child node 
+ * 
+ * ADL - 2/23/99, rewritten TYT 2/25/99
+ */
+errcode_t KRB5_CALLCONV
+profile_update_relation(profile_t profile, const char **names,
+			const char *old_value, const char *new_value)
+{	
+	errcode_t	retval;
+	struct profile_node *section, *node;
+	void		*state;
+	const char	**cpp;
+
+	retval = rw_setup(profile);
+	if (retval)
+		return retval;
+	
+	if (names == 0 || names[0] == 0 || names[1] == 0)
+		return PROF_BAD_NAMESET;
+
+	if (!old_value || !*old_value)
+		return PROF_EINVAL;
+
+	retval = k5_mutex_lock(&profile->first_file->data->lock);
+	if (retval)
+	    return retval;
+	section = profile->first_file->data->root;
+	for (cpp = names; cpp[1]; cpp++) {
+		state = 0;
+		retval = profile_find_node(section, *cpp, 0, 1,
+					   &state, §ion);
+		if (retval) {
+		    k5_mutex_unlock(&profile->first_file->data->lock);
+		    return retval;
+		}
+	}
+
+	state = 0;
+	retval = profile_find_node(section, *cpp, old_value, 0, &state, &node);
+	if (retval == 0) {
+	    if (new_value)
+		retval = profile_set_relation_value(node, new_value);
+	    else
+		retval = profile_remove_node(node);
+	}
+	if (retval == 0)
+	    profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
+	k5_mutex_unlock(&profile->first_file->data->lock);
+	
+	return retval;
+}
+
+/* 
+ * Clear a particular all of the relations with a specific name.
+ * 
+ * TYT - 2/25/99
+ */
+errcode_t KRB5_CALLCONV
+profile_clear_relation(profile_t profile, const char **names)
+{	
+	errcode_t	retval;
+	struct profile_node *section, *node;
+	void		*state;
+	const char	**cpp;
+
+	retval = rw_setup(profile);
+	if (retval)
+		return retval;
+	
+	if (names == 0 || names[0] == 0 || names[1] == 0)
+		return PROF_BAD_NAMESET;
+
+	section = profile->first_file->data->root;
+	for (cpp = names; cpp[1]; cpp++) {
+		state = 0;
+		retval = profile_find_node(section, *cpp, 0, 1,
+					   &state, §ion);
+		if (retval)
+			return retval;
+	}
+
+	state = 0;
+	do {
+		retval = profile_find_node(section, *cpp, 0, 0, &state, &node);
+		if (retval)
+			return retval;
+		retval = profile_remove_node(node);
+		if (retval)
+			return retval;
+	} while (state);
+
+	profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
+	
+	return 0;
+}
+
+/* 
+ * Rename a particular section; if the new_section name is NULL,
+ * delete it.
+ * 
+ * ADL - 2/23/99, rewritten TYT 2/25/99
+ */
+errcode_t KRB5_CALLCONV
+profile_rename_section(profile_t profile, const char **names,
+		       const char *new_name)
+{	
+	errcode_t	retval;
+	struct profile_node *section, *node;
+	void		*state;
+	const char	**cpp;
+	
+	retval = rw_setup(profile);
+	if (retval)
+		return retval;
+	
+	if (names == 0 || names[0] == 0 || names[1] == 0)
+		return PROF_BAD_NAMESET;
+
+	retval = k5_mutex_lock(&profile->first_file->data->lock);
+	if (retval)
+	    return retval;
+	section = profile->first_file->data->root;
+	for (cpp = names; cpp[1]; cpp++) {
+		state = 0;
+		retval = profile_find_node(section, *cpp, 0, 1,
+					   &state, §ion);
+		if (retval) {
+		    k5_mutex_unlock(&profile->first_file->data->lock);
+		    return retval;
+		}
+	}
+
+	state = 0;
+	retval = profile_find_node(section, *cpp, 0, 1, &state, &node);
+	if (retval == 0) {
+	    if (new_name)
+		retval = profile_rename_node(node, new_name);
+	    else
+		retval = profile_remove_node(node);
+	}
+	if (retval == 0)
+	    profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
+	k5_mutex_unlock(&profile->first_file->data->lock);
+	return retval;
+}
+
+/*
+ * Insert a new relation.  If the new_value argument is NULL, then
+ * create a new section instead.
+ *
+ * Note: if the intermediate sections do not exist, this function will
+ * automatically create them.
+ *
+ * ADL - 2/23/99, rewritten TYT 2/25/99
+ */
+errcode_t KRB5_CALLCONV
+profile_add_relation(profile_t profile, const char **names,
+		     const char *new_value)
+{
+	errcode_t	retval;
+    	struct profile_node *section;
+	const char 	**cpp;
+	void		*state;
+
+	retval = rw_setup(profile);
+	if (retval)
+		return retval;
+	
+	if (names == 0 || names[0] == 0 || names[1] == 0)
+		return PROF_BAD_NAMESET;
+
+	retval = k5_mutex_lock(&profile->first_file->data->lock);
+	if (retval)
+	    return retval;
+	section = profile->first_file->data->root;
+	for (cpp = names; cpp[1]; cpp++) {
+		state = 0;
+		retval = profile_find_node(section, *cpp, 0, 1,
+					   &state, §ion);
+		if (retval == PROF_NO_SECTION)
+			retval = profile_add_node(section, *cpp, 0, §ion);
+		if (retval) {
+		    k5_mutex_unlock(&profile->first_file->data->lock);
+		    return retval;
+		}
+	}
+
+	if (new_value == 0) {
+		retval = profile_find_node(section, *cpp, 0, 1, &state, 0);
+		if (retval == 0) {
+		    k5_mutex_unlock(&profile->first_file->data->lock);
+		    return PROF_EXISTS;
+		} else if (retval != PROF_NO_SECTION) {
+		    k5_mutex_unlock(&profile->first_file->data->lock);
+		    return retval;
+		}
+	}
+
+	retval = profile_add_node(section, *cpp, new_value, 0);
+	if (retval) {
+	    k5_mutex_unlock(&profile->first_file->data->lock);
+	    return retval;
+	}
+
+	profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
+	k5_mutex_unlock(&profile->first_file->data->lock);
+	return 0;
+}
+
diff --git a/krb5-1-6/src/util/profile/prof_test1 b/krb5-1-6/src/util/profile/prof_test1
new file mode 100644
index 000000000..bd4901272
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_test1
@@ -0,0 +1,154 @@
+# To do: Should run all tests and return a useful exit status, not
+# punt on the first failure.
+
+set wd [pwd]
+set verbose 0
+
+proc test1 {} {
+    global wd verbose
+    set p [profile_init_path $wd/test2.ini]
+    set sect {{test section 1} child_section child}
+    set iter [profile_iterator_create $p $sect 0]
+    set done 0
+    if $verbose { puts "Iterating over {$sect} entries:" }
+    while {!$done} {
+	set pair [profile_iterator $iter]
+	if [string match $pair {{} {}}] {
+	    set done 1
+	} else {
+	    set val [lindex $pair 1]
+	    if $verbose { puts -nonewline "\t$val" }
+	}
+    }
+    if $verbose { puts "" }
+    #profile_iterator_free $iter
+
+    set iter [profile_iterator_create $p $sect 0]
+    set done 0
+    if $verbose { puts "Iterating again, deleting:" }
+    while {!$done} {
+	set pair [profile_iterator $iter]
+	if [string match $pair {{} {}}] {
+	    set done 1
+	} else {
+	    set val [lindex $pair 1]
+	    if $verbose { puts -nonewline "\t$val" }
+	    profile_update_relation $p $sect $val
+	}
+    }
+    if $verbose { puts "" }
+    #profile_iterator_free $iter
+    catch {file delete $wd/test3.ini}
+    profile_flush_to_file $p $wd/test3.ini
+    profile_release $p
+
+    if $verbose { puts "Reloading new profile" }
+    set p [profile_init_path $wd/test3.ini]
+    set iter [profile_iterator_create $p $sect 0]
+    set done 0
+    if $verbose { puts "Iterating again:" }
+    set found_some 0
+    while {!$done} {
+	set pair [profile_iterator $iter]
+	if [string match $pair {{} {}}] {
+	    set done 1
+	} else {
+	    set found_some 1
+	    set val [lindex $pair 1]
+	    if $verbose { puts -nonewline "\t$val" }
+	}
+    }
+    #profile_iterator_free $iter
+    profile_abandon $p
+
+    if {$found_some} {
+	if $verbose { puts "" }
+	puts stderr "Error: Deleting in iterator didn't get them all."
+	exit 1
+    } else {
+	puts "OK: test1: Deleting in iteration got rid of all entries."
+    }
+}
+
+proc test2 {} {
+    global wd verbose
+
+    # lxs said: create A, read A, flush A, read A, create B, read B, crash
+    # (where "create" refers to the object, not the file)
+
+    if $verbose { puts "Running test2" }
+    set c [profile_init_path $wd/test2.ini]
+    # create A
+    set a [profile_init_path $wd/test2.ini]
+    if $verbose { puts "Opened profile $wd/test2.ini" }
+    # read A
+    set x [profile_get_values $a {{test section 1} foo}]
+    if $verbose { puts "Read $x from profile" }
+    if $verbose { puts "updating" }
+    exec sleep 2
+    profile_update_relation $a {{test section 1} foo} [lindex $x 0] [lindex $x 0]
+    set x [profile_get_values $a {{test section 1} foo}]
+    if $verbose { puts "Read $x from profile" }
+    # flush A
+    profile_flush $a
+    # read A again
+    set x [profile_get_values $a {{test section 1} foo}]
+    if $verbose { puts "Read $x from profile" }
+    profile_release $a
+    # create B
+    set b [profile_init_path $wd/test2.ini]
+    if $verbose { puts "Opened profile again" }
+    # read B
+    set x [profile_get_values $b {{test section 1} foo}]
+    if $verbose { puts "Read $x from profile" }
+    # read B
+    set x [profile_get_values $b {{test section 1} foo}]
+    if $verbose { puts "Read $x from profile" }
+    # If we got this far, now what?
+    profile_release $b
+    profile_release $c
+    puts "OK: test2: Modifications don't corrupt existing open handles"
+}
+
+proc test3 {} {
+    # lxs said: Start with a relation in the file.  Open, delete
+    # relation, add relation back, list relations.  In 1.4 release
+    # code, got two back.
+
+    global wd verbose
+
+    exec cp $wd/test2.ini $wd/test1c.ini
+    set p [profile_init_path $wd/test1c.ini]
+    set sect {{test section 1} quux}
+
+    set v [profile_get_values $p $sect]
+    set v1 [lindex $v 0]
+    if $verbose { puts "Old values: $v" }
+    profile_clear_relation $p $sect
+    if $verbose { puts "Cleared." }
+    # profile_get_values raises an exception if no data is there; so if
+    # it succeeds, the test fails.
+    catch {
+	set v [profile_get_values $p $sect]
+	if $verbose { puts "New values: $v" }
+	puts stderr "Error: test3: Clearing relation didn't get rid of all values."
+	exit 1
+    }
+    if $verbose { puts "Adding back $v1 ..." }
+    profile_add_relation $p $sect $v1
+    set v [profile_get_values $p $sect]
+    if $verbose { puts "New values: $v" }
+    if [llength $v]!=1 {
+	puts stderr "Error: test3: Adding one entry after clearing relation leaves [llength $v] entries."
+	exit 1
+    }
+    profile_abandon $p
+    file delete $wd/test1c.ini
+    puts "OK: test3: Clearing relation and adding one entry yields correct count."
+}
+
+test1
+test2
+test3
+
+exit 0
diff --git a/krb5-1-6/src/util/profile/prof_tree.c b/krb5-1-6/src/util/profile/prof_tree.c
new file mode 100644
index 000000000..b014e245d
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prof_tree.c
@@ -0,0 +1,714 @@
+/*
+ * prof_tree.c --- these routines maintain the parse tree of the
+ * 	config file.
+ * 
+ * All of the details of how the tree is stored is abstracted away in
+ * this file; all of the other profile routines build, access, and
+ * modify the tree via the accessor functions found in this file.
+ *
+ * Each node may represent either a relation or a section header.
+ * 
+ * A section header must have its value field set to 0, and may a one
+ * or more child nodes, pointed to by first_child.
+ * 
+ * A relation has as its value a pointer to allocated memory
+ * containing a string.  Its first_child pointer must be null.
+ *
+ */
+
+
+#include "prof_int.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+#include <ctype.h>
+
+struct profile_node {
+	errcode_t	magic;
+	char *name;
+	char *value;
+	int group_level;
+	int final:1;		/* Indicate don't search next file */
+	int deleted:1;
+	struct profile_node *first_child;
+	struct profile_node *parent;
+	struct profile_node *next, *prev;
+};
+
+#define CHECK_MAGIC(node) \
+	  if ((node)->magic != PROF_MAGIC_NODE) \
+		  return PROF_MAGIC_NODE;
+
+/*
+ * Free a node, and any children
+ */
+void profile_free_node(struct profile_node *node)
+{
+	struct profile_node *child, *next;
+
+	if (node->magic != PROF_MAGIC_NODE)
+		return;
+	
+	if (node->name)
+		free(node->name);
+	if (node->value)
+		free(node->value);
+
+	for (child=node->first_child; child; child = next) {
+		next = child->next;
+		profile_free_node(child);
+	}
+	node->magic = 0;
+	
+	free(node);
+}
+
+#ifndef HAVE_STRDUP
+#undef strdup
+#define strdup MYstrdup
+static char *MYstrdup (const char *s)
+{
+    size_t sz = strlen(s) + 1;
+    char *p = malloc(sz);
+    if (p != 0)
+	memcpy(p, s, sz);
+    return p;
+}
+#endif
+
+/*
+ * Create a node
+ */
+errcode_t profile_create_node(const char *name, const char *value,
+			      struct profile_node **ret_node)
+{
+	struct profile_node *new;
+
+	new = malloc(sizeof(struct profile_node));
+	if (!new)
+		return ENOMEM;
+	memset(new, 0, sizeof(struct profile_node));
+	new->name = strdup(name);
+	if (new->name == 0) {
+	    profile_free_node(new);
+	    return ENOMEM;
+	}
+	if (value) {
+		new->value = strdup(value);
+		if (new->value == 0) {
+		    profile_free_node(new);
+		    return ENOMEM;
+		}
+	}
+	new->magic = PROF_MAGIC_NODE;
+
+	*ret_node = new;
+	return 0;
+}
+
+/*
+ * This function verifies that all of the representation invarients of
+ * the profile are true.  If not, we have a programming bug somewhere,
+ * probably in this file.
+ */
+errcode_t profile_verify_node(struct profile_node *node)
+{
+	struct profile_node *p, *last;
+	errcode_t	retval;
+
+	CHECK_MAGIC(node);
+
+	if (node->value && node->first_child)
+		return PROF_SECTION_WITH_VALUE;
+
+	last = 0;
+	for (p = node->first_child; p; last = p, p = p->next) {
+		if (p->prev != last)
+			return PROF_BAD_LINK_LIST;
+		if (last && (last->next != p))
+			return PROF_BAD_LINK_LIST;
+		if (node->group_level+1 != p->group_level)
+			return PROF_BAD_GROUP_LVL;
+		if (p->parent != node)
+			return PROF_BAD_PARENT_PTR;
+		retval = profile_verify_node(p);
+		if (retval)
+			return retval;
+	}
+	return 0;
+}
+
+/*
+ * Add a node to a particular section
+ */
+errcode_t profile_add_node(struct profile_node *section, const char *name,
+			   const char *value, struct profile_node **ret_node)
+{
+	errcode_t retval;
+	struct profile_node *p, *last, *new;
+
+	CHECK_MAGIC(section);
+
+	if (section->value)
+		return PROF_ADD_NOT_SECTION;
+
+	/*
+	 * Find the place to insert the new node.  We look for the
+	 * place *after* the last match of the node name, since 
+	 * order matters.
+	 */
+	for (p=section->first_child, last = 0; p; last = p, p = p->next) {
+		int cmp;
+		cmp = strcmp(p->name, name);
+		if (cmp > 0)
+			break;
+	}
+	retval = profile_create_node(name, value, &new);
+	if (retval)
+		return retval;
+	new->group_level = section->group_level+1;
+	new->deleted = 0;
+	new->parent = section;
+	new->prev = last;
+	new->next = p;
+	if (p)
+		p->prev = new;
+	if (last)
+		last->next = new;
+	else
+		section->first_child = new;
+	if (ret_node)
+		*ret_node = new;
+	return 0;
+}
+
+/*
+ * Set the final flag on a particular node.
+ */
+errcode_t profile_make_node_final(struct profile_node *node)
+{
+	CHECK_MAGIC(node);
+
+	node->final = 1;
+	return 0;
+}
+
+/*
+ * Check the final flag on a node
+ */
+int profile_is_node_final(struct profile_node *node)
+{
+	return (node->final != 0);
+}
+
+/*
+ * Return the name of a node.  (Note: this is for internal functions
+ * only; if the name needs to be returned from an exported function,
+ * strdup it first!)
+ */
+const char *profile_get_node_name(struct profile_node *node)
+{
+	return node->name;
+}
+
+/*
+ * Return the value of a node.  (Note: this is for internal functions
+ * only; if the name needs to be returned from an exported function,
+ * strdup it first!)
+ */
+const char *profile_get_node_value(struct profile_node *node)
+{
+	return node->value;
+}
+
+/*
+ * Iterate through the section, returning the nodes which match
+ * the given name.  If name is NULL, then interate through all the
+ * nodes in the section.  If section_flag is non-zero, only return the
+ * section which matches the name; don't return relations.  If value
+ * is non-NULL, then only return relations which match the requested
+ * value.  (The value argument is ignored if section_flag is non-zero.)
+ * 
+ * The first time this routine is called, the state pointer must be
+ * null.  When this profile_find_node_relation() returns, if the state
+ * pointer is non-NULL, then this routine should be called again.
+ * (This won't happen if section_flag is non-zero, obviously.)
+ *
+ */
+errcode_t profile_find_node(struct profile_node *section, const char *name,
+			    const char *value, int section_flag, void **state,
+			    struct profile_node **node)
+{
+	struct profile_node *p;
+
+	CHECK_MAGIC(section);
+	p = *state;
+	if (p) {
+		CHECK_MAGIC(p);
+	} else
+		p = section->first_child;
+	
+	for (; p; p = p->next) {
+		if (name && (strcmp(p->name, name)))
+			continue;
+		if (section_flag) {
+			if (p->value)
+				continue;
+		} else {
+			if (!p->value)
+				continue;
+			if (value && (strcmp(p->value, value)))
+				continue;
+		}
+		if (p->deleted)
+		    continue;
+		/* A match! */
+		if (node)
+			*node = p;
+		break;
+	}
+	if (p == 0) {
+		*state = 0;
+		return section_flag ? PROF_NO_SECTION : PROF_NO_RELATION;
+	}
+	/*
+	 * OK, we've found one match; now let's try to find another
+	 * one.  This way, if we return a non-zero state pointer,
+	 * there's guaranteed to be another match that's returned.
+	 */
+	for (p = p->next; p; p = p->next) {
+		if (name && (strcmp(p->name, name)))
+			continue;
+		if (section_flag) {
+			if (p->value)
+				continue;
+		} else {
+			if (!p->value)
+				continue;
+			if (value && (strcmp(p->value, value)))
+				continue;
+		}
+		/* A match! */
+		break;
+	}
+	*state = p;
+	return 0;
+}
+
+
+/*
+ * Iterate through the section, returning the relations which match
+ * the given name.  If name is NULL, then interate through all the
+ * relations in the section.  The first time this routine is called,
+ * the state pointer must be null.  When this profile_find_node_relation()
+ * returns, if the state pointer is non-NULL, then this routine should
+ * be called again.
+ *
+ * The returned character string in value points to the stored
+ * character string in the parse string.  Before this string value is
+ * returned to a calling application (profile_find_node_relation is not an
+ * exported interface), it should be strdup()'ed.
+ */
+errcode_t profile_find_node_relation(struct profile_node *section,
+				     const char *name, void **state,
+				     char **ret_name, char **value)
+{
+	struct profile_node *p;
+	errcode_t	retval;
+
+	retval = profile_find_node(section, name, 0, 0, state, &p);
+	if (retval)
+		return retval;
+
+	if (p) {
+		if (value)
+			*value = p->value;
+		if (ret_name)
+			*ret_name = p->name;
+	}
+	return 0;
+}
+
+/*
+ * Iterate through the section, returning the subsections which match
+ * the given name.  If name is NULL, then interate through all the
+ * subsections in the section.  The first time this routine is called,
+ * the state pointer must be null.  When this profile_find_node_subsection()
+ * returns, if the state pointer is non-NULL, then this routine should
+ * be called again.
+ *
+ * This is (plus accessor functions for the name and value given a
+ * profile node) makes this function mostly syntactic sugar for
+ * profile_find_node. 
+ */
+errcode_t profile_find_node_subsection(struct profile_node *section,
+				       const char *name, void **state,
+				       char **ret_name,
+				       struct profile_node **subsection)
+{
+	struct profile_node *p;
+	errcode_t	retval;
+
+	retval = profile_find_node(section, name, 0, 1, state, &p);
+	if (retval)
+		return retval;
+
+	if (p) {
+		if (subsection)
+			*subsection = p;
+		if (ret_name)
+			*ret_name = p->name;
+	}
+	return 0;
+}
+
+/*
+ * This function returns the parent of a particular node.
+ */
+errcode_t profile_get_node_parent(struct profile_node *section,
+				  struct profile_node **parent)
+{
+	*parent = section->parent;
+	return 0;
+}
+
+/*
+ * This is a general-purpose iterator for returning all nodes that
+ * match the specified name array.  
+ */
+struct profile_iterator {
+	prf_magic_t		magic;
+	profile_t		profile;
+	int			flags;
+	const char 		*const *names;
+	const char		*name;
+	prf_file_t		file;
+	int			file_serial;
+	int			done_idx;
+	struct profile_node 	*node;
+	int			num;
+};
+
+errcode_t profile_node_iterator_create(profile_t profile,
+				       const char *const *names, int flags,
+				       void **ret_iter)
+{
+	struct profile_iterator *iter;
+	int	done_idx = 0;
+
+	if (profile == 0)
+		return PROF_NO_PROFILE;
+	if (profile->magic != PROF_MAGIC_PROFILE)
+		return PROF_MAGIC_PROFILE;
+	if (!names)
+		return PROF_BAD_NAMESET;
+	if (!(flags & PROFILE_ITER_LIST_SECTION)) {
+		if (!names[0])
+			return PROF_BAD_NAMESET;
+		done_idx = 1;
+	}
+
+	if ((iter = malloc(sizeof(struct profile_iterator))) == NULL)
+		return ENOMEM;
+
+	iter->magic = PROF_MAGIC_ITERATOR;
+	iter->profile = profile;
+	iter->names = names;
+	iter->flags = flags;
+	iter->file = profile->first_file;
+	iter->done_idx = done_idx;
+	iter->node = 0;
+	iter->num = 0;
+	*ret_iter = iter;
+	return 0;
+}
+
+void profile_node_iterator_free(void **iter_p)
+{
+	struct profile_iterator *iter;
+
+	if (!iter_p)
+		return;
+	iter = *iter_p;
+	if (!iter || iter->magic != PROF_MAGIC_ITERATOR)
+		return;
+	free(iter);
+	*iter_p = 0;
+}
+
+/*
+ * Note: the returned character strings in ret_name and ret_value
+ * points to the stored character string in the parse string.  Before
+ * this string value is returned to a calling application
+ * (profile_node_iterator is not an exported interface), it should be
+ * strdup()'ed.
+ */
+errcode_t profile_node_iterator(void **iter_p, struct profile_node **ret_node,
+				char **ret_name, char **ret_value)
+{
+	struct profile_iterator 	*iter = *iter_p;
+	struct profile_node 		*section, *p;
+	const char			*const *cpp;
+	errcode_t			retval;
+	int				skip_num = 0;
+
+	if (!iter || iter->magic != PROF_MAGIC_ITERATOR)
+		return PROF_MAGIC_ITERATOR;
+	if (iter->file && iter->file->magic != PROF_MAGIC_FILE)
+	    return PROF_MAGIC_FILE;
+	if (iter->file && iter->file->data->magic != PROF_MAGIC_FILE_DATA)
+	    return PROF_MAGIC_FILE_DATA;
+	/*
+	 * If the file has changed, then the node pointer is invalid,
+	 * so we'll have search the file again looking for it.
+	 */
+	if (iter->file) {
+	    retval = k5_mutex_lock(&iter->file->data->lock);
+	    if (retval)
+		return retval;
+	}
+	if (iter->node && (iter->file->data->upd_serial != iter->file_serial)) {
+		iter->flags &= ~PROFILE_ITER_FINAL_SEEN;
+		skip_num = iter->num;
+		iter->node = 0;
+	}
+	if (iter->node && iter->node->magic != PROF_MAGIC_NODE) {
+	    if (iter->file)
+		k5_mutex_unlock(&iter->file->data->lock);
+	    return PROF_MAGIC_NODE;
+	}
+get_new_file:
+	if (iter->node == 0) {
+		if (iter->file == 0 ||
+		    (iter->flags & PROFILE_ITER_FINAL_SEEN)) {
+			if (iter->file)
+			    k5_mutex_unlock(&iter->file->data->lock);
+			profile_node_iterator_free(iter_p);
+			if (ret_node)
+				*ret_node = 0;
+			if (ret_name)
+				*ret_name = 0;
+			if (ret_value)
+				*ret_value =0;
+			return 0;
+		}
+		k5_mutex_unlock(&iter->file->data->lock);
+		if ((retval = profile_update_file(iter->file))) {
+		    if (retval == ENOENT || retval == EACCES) {
+			/* XXX memory leak? */
+			iter->file = iter->file->next;
+			if (iter->file) {
+			    retval = k5_mutex_lock(&iter->file->data->lock);
+			    if (retval) {
+				profile_node_iterator_free(iter_p);
+				return retval;
+			    }
+			}
+			skip_num = 0;
+			retval = 0;
+			goto get_new_file;
+		    } else {
+			profile_node_iterator_free(iter_p);
+			return retval;
+		    }
+		}
+		retval = k5_mutex_lock(&iter->file->data->lock);
+		if (retval) {
+		    profile_node_iterator_free(iter_p);
+		    return retval;
+		}
+		iter->file_serial = iter->file->data->upd_serial;
+		/*
+		 * Find the section to list if we are a LIST_SECTION,
+		 * or find the containing section if not.
+		 */
+		section = iter->file->data->root;
+		assert(section != NULL);
+		for (cpp = iter->names; cpp[iter->done_idx]; cpp++) {
+			for (p=section->first_child; p; p = p->next) {
+				if (!strcmp(p->name, *cpp) && !p->value)
+					break;
+			}
+			if (!p) {
+				section = 0;
+				break;
+			}
+			section = p;
+			if (p->final)
+				iter->flags |= PROFILE_ITER_FINAL_SEEN;
+		}
+		if (!section) {
+			k5_mutex_unlock(&iter->file->data->lock);
+			iter->file = iter->file->next;
+			if (iter->file) {
+			    retval = k5_mutex_lock(&iter->file->data->lock);
+			    if (retval) {
+				profile_node_iterator_free(iter_p);
+				return retval;
+			    }
+			}
+			skip_num = 0;
+			goto get_new_file;
+		}
+		iter->name = *cpp;
+		iter->node = section->first_child;
+	}
+	/*
+	 * OK, now we know iter->node is set up correctly.  Let's do
+	 * the search.
+	 */
+	for (p = iter->node; p; p = p->next) {
+		if (iter->name && strcmp(p->name, iter->name))
+			continue;
+		if ((iter->flags & PROFILE_ITER_SECTIONS_ONLY) &&
+		    p->value)
+			continue;
+		if ((iter->flags & PROFILE_ITER_RELATIONS_ONLY) &&
+		    !p->value)
+			continue;
+		if (skip_num > 0) {
+			skip_num--;
+			continue;
+		}
+		if (p->deleted)
+			continue;
+		break;
+	}
+	iter->num++;
+	if (!p) {
+		k5_mutex_unlock(&iter->file->data->lock);
+		iter->file = iter->file->next;
+		if (iter->file) {
+		    retval = k5_mutex_lock(&iter->file->data->lock);
+		    if (retval) {
+			profile_node_iterator_free(iter_p);
+			return retval;
+		    }
+		}
+		iter->node = 0;
+		skip_num = 0;
+		goto get_new_file;
+	}
+	k5_mutex_unlock(&iter->file->data->lock);
+	if ((iter->node = p->next) == NULL)
+		iter->file = iter->file->next;
+	if (ret_node)
+		*ret_node = p;
+	if (ret_name)
+		*ret_name = p->name;
+	if (ret_value)
+		*ret_value = p->value;
+	return 0;
+}
+
+/* 
+ * Remove a particular node.
+ * 
+ * TYT, 2/25/99
+ */
+errcode_t profile_remove_node(struct profile_node *node)
+{
+	CHECK_MAGIC(node);
+
+	if (node->parent == 0)
+		return PROF_EINVAL; /* Can't remove the root! */
+	
+	node->deleted = 1;
+
+	return 0;
+}
+
+/*
+ * Set the value of a specific node containing a relation.
+ *
+ * TYT, 2/25/99
+ */
+errcode_t profile_set_relation_value(struct profile_node *node,
+				     const char *new_value)
+{
+	char	*cp;
+	
+	CHECK_MAGIC(node);
+
+	if (!node->value)
+		return PROF_SET_SECTION_VALUE;
+
+	cp = malloc(strlen(new_value)+1);
+	if (!cp)
+		return ENOMEM;
+
+	strcpy(cp, new_value);
+	free(node->value);
+	node->value = cp;
+
+	return 0;
+}
+
+/*
+ * Rename a specific node
+ *
+ * TYT 2/25/99
+ */
+errcode_t profile_rename_node(struct profile_node *node, const char *new_name)
+{
+	char			*new_string;
+	struct profile_node 	*p, *last;
+
+	CHECK_MAGIC(node);
+
+	if (strcmp(new_name, node->name) == 0)
+		return 0;	/* It's the same name, return */
+
+	/*
+	 * Make sure we can allocate memory for the new name, first!
+	 */
+	new_string = malloc(strlen(new_name)+1);
+	if (!new_string)
+		return ENOMEM;
+	strcpy(new_string, new_name);
+
+	/*
+	 * Find the place to where the new node should go.  We look
+	 * for the place *after* the last match of the node name,
+	 * since order matters.
+	 */
+	for (p=node->parent->first_child, last = 0; p; last = p, p = p->next) {
+		if (strcmp(p->name, new_name) > 0)
+			break;
+	}
+
+	/*
+	 * If we need to move the node, do it now.
+	 */
+	if ((p != node) && (last != node)) {
+		/*
+		 * OK, let's detach the node
+		 */
+		if (node->prev)
+			node->prev->next = node->next;
+		else
+			node->parent->first_child = node->next;
+		if (node->next)
+			node->next->prev = node->prev;
+
+		/*
+		 * Now let's reattach it in the right place.
+		 */
+		if (p)
+			p->prev = node;
+		if (last)
+			last->next = node;
+		else
+			node->parent->first_child = node;
+		node->next = p;
+		node->prev = last;
+	}
+
+	free(node->name);
+	node->name = new_string;
+	return 0;
+}
diff --git a/krb5-1-6/src/util/profile/profile.5 b/krb5-1-6/src/util/profile/profile.5
new file mode 100644
index 000000000..7f3b36ab5
--- /dev/null
+++ b/krb5-1-6/src/util/profile/profile.5
@@ -0,0 +1,71 @@
+
+A profile file is a generic way of storing program configuration
+information for applications.  An application may choose to consult
+multiple configuration files; for example, a Kerberos application
+might look first in ~/.krb5rc, and then in /etc/krb5.conf.  So
+/etc/krb5.conf would contain the side-wide default configuration for
+Kerberos, and ~/.krb5rc would contain the user's specific
+configuration overrides.
+
+Configuration information is stored in relations, which have a name
+and a value.  There may be multiple relations with the same name.
+Relations are always contained inside named sections.  Sections can
+contain relations and other named child sections.
+
+Top-level sections are defined by enclosing the section name in square
+braces.  Child sections are defined by enclosing the contents of the
+child section in curly braces.  Relations are defined by using the
+format "name = value".  
+
+An example profile file might look like this:
+
+[libdefaults]
+	default_realm = ATHENA.MIT.EDU
+
+[realms]
+	ATHENA.MIT.EDU = {
+		kdc = kerberos.mit.edu:88
+		kdc = kerberos-1.mit.edu:88
+		kdc = kerberos-2.mit.edu:88
+		admin_server = kerberos.mit.edu:88
+		default_domain = mit.edu
+	}
+	CYGNUS.COM = {
+		kdc = KERBEROS-1.CYGNUS.COM
+		kdc = KERBEROS.CYGNUS.COM
+		admin_server = KERBEROS.MIT.EDU
+	}
+
+In this example, the profile file has two top-level sections,
+"libdefaults" and "realms".  The libdefaults section has a single
+relation which is named "default_realm" and has the value
+"ATHENA.MIT.EDU".  The realms section has two child sections,
+"ATHENA.MIT.EDU" and "CYGNUS.MIT.EDU".  Each of these child has a
+number of relations, "kdc", "admin_server", and (in the case of
+"ATHENA.MIT.EDU"), "default_domain".  Note that there are multiple
+relations with the name "kdc" in both sections; if a
+profile_get_values() is called querying the "kdc" relation, both
+values will be returned.
+
+Sections may be marked as "final".  If they are marked as final, then
+the contents of that section override all subsequent profile files (if
+the application is searching multiple profile files for its
+configuration information).  Normally, all of the profiles are
+searched for a matching relation, and all of the values found in all
+of the various profile files will be returned.  
+
+Top-level sections are marked as final by adding an '*' character
+following the closing square brace.  Child sections are marked as
+final by adding a '*' character after the closing curly brace.  So for
+example, in this example both the "libdefaults" and "ATHENA.MIT.EDU"
+sections have been marked as final:
+
+[libdefaults]*
+	default_realm = ATHENA.MIT.EDU
+
+[realms]
+	ATHENA.MIT.EDU = {
+		kdc = kerberos.mit.edu:88
+		admin_server = kerberos.mit.edu:88
+	}*
+
diff --git a/krb5-1-6/src/util/profile/profile.exp b/krb5-1-6/src/util/profile/profile.exp
new file mode 100644
index 000000000..eaf720cd2
--- /dev/null
+++ b/krb5-1-6/src/util/profile/profile.exp
@@ -0,0 +1,35 @@
+#
+# Profile library Macintosh export file
+#
+# $Header$
+
+profile_init
+profile_init_path
+profile_flush
+profile_abandon
+profile_release
+profile_get_values
+profile_free_list
+profile_get_string
+profile_get_boolean
+profile_get_integer
+profile_get_relation_names
+profile_get_subsection_names
+profile_iterator_create
+profile_iterator_free
+profile_iterator
+profile_release_string
+profile_update_relation
+profile_clear_relation
+profile_rename_section
+profile_add_relation
+
+### Temporary -- DO NOT USE
+
+profile_ser_internalize
+profile_ser_externalize
+profile_ser_size
+
+# Mac only
+FSp_profile_init
+FSp_profile_init_path
diff --git a/krb5-1-6/src/util/profile/profile.hin b/krb5-1-6/src/util/profile/profile.hin
new file mode 100644
index 000000000..10abe725a
--- /dev/null
+++ b/krb5-1-6/src/util/profile/profile.hin
@@ -0,0 +1,125 @@
+/*
+ * profile.h
+ */
+
+#ifndef _KRB5_PROFILE_H
+#define _KRB5_PROFILE_H
+
+#if defined(_WIN32)
+#include <win-mac.h>
+#endif
+
+#if defined(__MACH__) && defined(__APPLE__)
+#    include <TargetConditionals.h>
+#    if TARGET_RT_MAC_CFM
+#        error "Use KfM 4.0 SDK headers for CFM compilation."
+#    endif
+#endif
+
+#ifndef KRB5_CALLCONV
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#endif
+
+typedef struct _profile_t *profile_t;
+
+/*
+ * Used by the profile iterator in prof_get.c
+ */
+#define PROFILE_ITER_LIST_SECTION	0x0001
+#define PROFILE_ITER_SECTIONS_ONLY	0x0002
+#define PROFILE_ITER_RELATIONS_ONLY	0x0004
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef char* profile_filespec_t;	/* path as C string */
+typedef char* profile_filespec_list_t;	/* list of : separated paths, C string */
+typedef const char * const_profile_filespec_t;	/* path as C string */
+typedef const char * const_profile_filespec_list_t;	/* list of : separated paths, C string */
+
+long KRB5_CALLCONV profile_init
+	(const_profile_filespec_t *files, profile_t *ret_profile);
+
+long KRB5_CALLCONV profile_init_path
+	(const_profile_filespec_list_t filelist, profile_t *ret_profile);
+
+long KRB5_CALLCONV profile_flush
+	(profile_t profile);
+long KRB5_CALLCONV profile_flush_to_file
+	(profile_t profile, const_profile_filespec_t outfile);
+long KRB5_CALLCONV profile_flush_to_buffer
+	(profile_t profile, char **bufp);
+void KRB5_CALLCONV profile_free_buffer
+	(profile_t profile, char *buf);
+
+long KRB5_CALLCONV profile_is_writable
+	(profile_t profile, int *writable);
+long KRB5_CALLCONV profile_is_modified
+	(profile_t profile, int *modified);
+
+void KRB5_CALLCONV profile_abandon
+	(profile_t profile);
+
+void KRB5_CALLCONV profile_release
+	(profile_t profile);
+
+long KRB5_CALLCONV profile_get_values
+	(profile_t profile, const char *const *names, char ***ret_values);
+
+void KRB5_CALLCONV profile_free_list
+	(char **list);
+
+long KRB5_CALLCONV profile_get_string
+	(profile_t profile, const char *name, const char *subname, 
+			const char *subsubname, const char *def_val,
+			char **ret_string);
+long KRB5_CALLCONV profile_get_integer
+	(profile_t profile, const char *name, const char *subname,
+			const char *subsubname, int def_val,
+			int *ret_default);
+
+long KRB5_CALLCONV profile_get_boolean
+	(profile_t profile, const char *name, const char *subname,
+			const char *subsubname, int def_val,
+			int *ret_default);
+
+long KRB5_CALLCONV profile_get_relation_names
+	(profile_t profile, const char **names, char ***ret_names);
+
+long KRB5_CALLCONV profile_get_subsection_names
+	(profile_t profile, const char **names, char ***ret_names);
+
+long KRB5_CALLCONV profile_iterator_create
+	(profile_t profile, const char *const *names,
+		   int flags, void **ret_iter);
+
+void KRB5_CALLCONV profile_iterator_free
+	(void **iter_p);
+	
+long KRB5_CALLCONV profile_iterator
+	(void	**iter_p, char **ret_name, char **ret_value);
+
+void KRB5_CALLCONV profile_release_string (char *str);
+
+long KRB5_CALLCONV profile_update_relation
+	(profile_t profile, const char **names, 
+		   const char *old_value, const char *new_value);
+
+long KRB5_CALLCONV profile_clear_relation
+	(profile_t profile, const char **names);
+
+long KRB5_CALLCONV profile_rename_section
+	(profile_t profile, const char **names, 
+		   const char *new_name);
+
+long KRB5_CALLCONV profile_add_relation
+	(profile_t profile, const char **names, 
+		   const char *new_value);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _KRB5_PROFILE_H */
diff --git a/krb5-1-6/src/util/profile/profile.pbexp b/krb5-1-6/src/util/profile/profile.pbexp
new file mode 100644
index 000000000..9033b54ea
--- /dev/null
+++ b/krb5-1-6/src/util/profile/profile.pbexp
@@ -0,0 +1,33 @@
+#
+# Profile library Macintosh export file
+#
+# $Header$
+
+_profile_init
+_profile_init_path
+_FSp_profile_init
+_FSp_profile_init_path
+_profile_flush
+_profile_abandon
+_profile_release
+_profile_get_values
+_profile_free_list
+_profile_get_string
+_profile_get_boolean
+_profile_get_integer
+_profile_get_relation_names
+_profile_get_subsection_names
+_profile_iterator_create
+_profile_iterator_free
+_profile_iterator
+_profile_release_string
+_profile_update_relation
+_profile_clear_relation
+_profile_rename_section
+_profile_add_relation
+
+### Temporary -- DO NOT USE
+
+_profile_ser_internalize
+_profile_ser_externalize
+_profile_ser_size
diff --git a/krb5-1-6/src/util/profile/profile.swg b/krb5-1-6/src/util/profile/profile.swg
new file mode 100644
index 000000000..2e75bb4c6
--- /dev/null
+++ b/krb5-1-6/src/util/profile/profile.swg
@@ -0,0 +1,258 @@
+%{
+/*
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * Input for wrapper generator program SWIG for profile routines.
+ */
+#include <errno.h>
+#include "com_err.h"
+#include "profile.h"
+
+#ifdef SWIGTCL
+/* Reduce warnings about cast discarding const to just this one, from
+   every SWIG-generated call to Tcl_SetResult.  */
+static void my_tcl_setresult(Tcl_Interp *i, const char *str, Tcl_FreeProc *f)
+{
+    Tcl_SetResult(i, (char *) str, f);
+}
+#undef Tcl_SetResult
+#define Tcl_SetResult my_tcl_setresult
+#endif
+%}
+
+%include "typemaps.i"
+
+/* These should perhaps be part of the general SWIG package, maybe?  */
+%typemap(in,numinputs=0) SWIGTYPE *OUTPUT ($1_basetype tmp) {
+    /*generic swigtype hack*/ $1 = &tmp;
+}
+%typemap(tcl8,argout) SWIGTYPE *OUTPUT
+  "/*generic swigtype hack*/ Tcl_SetObjResult(interp,SWIG_NewInstanceObj((void *) *$1, $*1_descriptor,0));";
+%typemap(python,argout) SWIGTYPE *OUTPUT
+  "/*generic swigtype hack*/ resultobj = SWIG_NewPointerObj((void *) *$1, $*1_descriptor,0);";
+
+%module profile
+
+typedef long errcode_t;
+%inline %{
+typedef void **iter_t; /* ick */
+%}
+
+/* As a hack, if we have too much trouble trying to manage output
+   arguments for functions returning error codes, this output argument
+   type will let us twist it around into a function returning the
+   interesting type, and incidentally possibly raising an error.  */
+%typemap(in,numinputs=0) errcode_t * (errcode_t tmp) {
+    /* in errcode_t * */
+    tmp = 0;
+    $1 = &tmp;
+}
+%typemap(tcl8,argout) errcode_t* {
+    /* argout errcode_t * */
+    if (*$1) {
+	/* There could be a memory leak here in the SWIG-Tcl layer,
+	   I'm not sure.  Not going to worry about it though.  */
+	Tcl_SetResult(interp, (char *) error_message(*$1), TCL_STATIC);
+	SWIG_fail;
+    }
+}
+/* returning errcode_t */
+%typemap(tcl8,out) errcode_t {
+    /* out errcode_t $1 */
+    if ($1) {
+	/* There could be a memory leak here in the SWIG-Tcl layer,
+	   I'm not sure.  Not going to worry about it though.  */
+	Tcl_SetResult(interp, (char *) error_message($1), TCL_STATIC);
+	SWIG_fail;
+    }
+}
+%typemap(python,argout) errcode_t* {
+    /* do something with *($1) */ abort();
+}
+%typemap(python,out) errcode_t {
+    /* do something with $1 */ abort();
+}
+
+/* "char **OUTPUT" : Supply a place for the function to stuff one
+   string pointer.  */
+%typemap(in,numinputs=0) char **OUTPUT (char * tmp) {
+    /* in char **OUTPUT */
+    tmp = NULL;
+    $1 = &tmp;
+}
+%typemap(tcl8,argout) char **OUTPUT {
+    /* argout char **OUTPUT */
+/*    Tcl_SetResult(interp, *$1, TCL_DYNAMIC); */
+    char *s = ($1 && *$1) ? *$1 : "";
+    Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
+			     Tcl_NewStringObj(s, strlen(s)));
+}
+%typemap(freearg) char **OUTPUT {
+    /* There may be a memory leak here.  Investigate later, if anyone
+       cares.  */
+/*    profile_release_string(*$1); */
+}
+
+/* "char **nullterm" : Null-terminated list of strings, from a single
+   input value which is a list.  */
+%typemap(tcl8,in) char **nullterm {
+    /* in char **nullterm */
+    int n;
+    if (Tcl_SplitList(interp, Tcl_GetStringFromObj($input,NULL), &n, &$1) == TCL_ERROR) SWIG_fail;
+}
+%typemap(tcl8,freearg) char **nullterm {
+    /* freearg char **nullterm */
+    if ($1) { Tcl_Free((char *)$1); $1 = (char **) NULL; }
+}
+
+/* "char ***OUTPUT" : Supply a place for the function to stuff a
+   pointer to a list of strings, which will be combined into a list to
+   return, and the data from the function itself freed before
+   returning.  */
+%typemap(in,numinputs=0) char ***OUTPUT (char ** tmp) {
+    /* in char ***OUTPUT */
+    tmp = NULL;
+    $1 = &tmp;
+}
+%typemap(tcl8,argout) char ***OUTPUT {
+    /* argout char ***OUTPUT */
+    int i;
+    for (i = 0; (*$1)[i]; i++)
+	Tcl_AppendElement(interp, (*$1)[i]);
+}
+%typemap(tcl8,freearg) char ***OUTPUT {
+    /* freearg char ***OUTPUT */
+    profile_free_list(*$1);
+}
+
+typedef struct _profile_t *profile_t;
+
+errcode_t profile_init_path(const char *path = NULL, profile_t *OUTPUT);
+errcode_t profile_init(const char **nullterm = NULL, profile_t *OUTPUT);
+errcode_t profile_flush(profile_t);
+errcode_t profile_flush_to_file(profile_t, const char *path);
+/* Nota bene: There is nothing at all in this code to prevent a script
+   from accessing a profile object after calling one of these routines
+   to destroy it!  */
+void profile_abandon(profile_t);
+void profile_release(profile_t);
+
+errcode_t profile_get_values(profile_t p, const char **nullterm,
+			     char ***OUTPUT);
+
+/* XXX Because of the way this is specified, the default can only be
+   given if you're actually using all three names (e.g., for realm
+   data).  SWIG currently doesn't support a non-optional argument (at
+   the scripting-language level -- the output-only argument doesn't
+   count) after an optional one.  */
+extern errcode_t profile_get_string(profile_t p,
+				    const char *name,
+				    const char *subname,
+				    const char *subsubname = NULL,
+				    const char *defval = NULL,
+				    char **OUTPUT);
+
+errcode_t profile_get_integer(profile_t p,
+			      const char *name,
+			      const char *subname,
+			      const char *subsubname = NULL,
+			      int defval = 0,
+			      int *OUTPUT);
+errcode_t profile_get_boolean(profile_t p,
+			      const char *name,
+			      const char *subname,
+			      const char *subsubname = NULL,
+			      int defval = 0,
+			      int *OUTPUT);
+errcode_t profile_get_relation_names(profile_t p,
+				     const char **nullterm,
+				     char ***OUTPUT);
+errcode_t profile_get_subsection_names(profile_t p,
+				       const char **nullterm,
+				       char ***OUTPUT);
+
+%rename("profile_iterator_create") iter_create;
+%rename("profile_iterator_free") iter_free;
+%inline %{
+static errcode_t iter_create(profile_t p, const char **nullterm,
+			     int flags, iter_t *OUTPUT)
+{
+    iter_t it;
+    errcode_t err;
+    char **args;
+
+    it = malloc(sizeof(*it));
+    if (it == NULL)
+	return errno;
+    {
+	/* Memory leak!
+
+	   The profile code seems to assume that I'll keep the string
+	   array around for as long as the iterator is valid; I can't
+	   create the iterator and then throw them away.
+
+	   But right now, I can't be bothered to track the necessary
+	   information to do the cleanup later.  */
+	int count, j;
+	for (count = 0; nullterm[count]; count++) ;
+	args = calloc(count+1, sizeof(char *));
+	if (args == NULL)
+	    return errno;
+	for (j = 0; j < count; j++) {
+	    args[j] = strdup(nullterm[j]);
+	    if (args[j] == NULL)
+		return errno;
+	}
+	args[j] = NULL;
+    }
+    err = profile_iterator_create(p, args, flags, it);
+    if (err)
+	free(it);
+    else
+	*OUTPUT = it;
+    return err;
+}
+static errcode_t iter_free(iter_t i)
+{
+    profile_iterator_free(i);
+    free(i);
+}
+%}
+errcode_t profile_iterator(iter_t, char **OUTPUT, char **OUTPUT);
+
+
+errcode_t profile_update_relation(profile_t p, const char **nullterm,
+				  const char *oldval,
+				  const char *newval = NULL);
+errcode_t profile_clear_relation(profile_t p, const char **nullterm);
+errcode_t profile_rename_section(profile_t p, const char **nullterm,
+				 const char *new_name = NULL);
+errcode_t profile_add_relation(profile_t p, const char **nullterm,
+			       const char *new_val = NULL);
+/* XXX Should be using profile_free_buffer blah.  */
+errcode_t profile_flush_to_buffer(profile_t p, char **OUTPUT);
+
+#ifdef SWIGTCL
+%include "tclsh.i"
+#endif
diff --git a/krb5-1-6/src/util/profile/profile_tcl.c b/krb5-1-6/src/util/profile/profile_tcl.c
new file mode 100644
index 000000000..31a82f1b4
--- /dev/null
+++ b/krb5-1-6/src/util/profile/profile_tcl.c
@@ -0,0 +1,2159 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.21
+ * 
+ * This file is not intended to be easily readable and contains a number of 
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG 
+ * interface file instead. 
+ * ----------------------------------------------------------------------------- */
+
+/*************************************************************** -*- c -*-
+ * Tcl/precommon.swg
+ *
+ * Rename all exported symbols from common.swg, to avoid symbol
+ * clashes if multiple interpreters are included
+ *
+ ************************************************************************/
+
+#define SWIG_TypeRegister    SWIG_Tcl_TypeRegister
+#define SWIG_TypeCheck       SWIG_Tcl_TypeCheck
+#define SWIG_TypeCast        SWIG_Tcl_TypeCast
+#define SWIG_TypeDynamicCast SWIG_Tcl_TypeDynamicCast
+#define SWIG_TypeName        SWIG_Tcl_TypeName
+#define SWIG_TypeQuery       SWIG_Tcl_TypeQuery
+#define SWIG_TypeClientData  SWIG_Tcl_TypeClientData
+#define SWIG_PackData        SWIG_Tcl_PackData 
+#define SWIG_UnpackData      SWIG_Tcl_UnpackData 
+
+
+/***********************************************************************
+ * common.swg
+ *
+ *     This file contains generic SWIG runtime support for pointer
+ *     type checking as well as a few commonly used macros to control
+ *     external linkage.
+ *
+ * Author : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (c) 1999-2000, The University of Chicago
+ * 
+ * This file may be freely redistributed without license or fee provided
+ * this copyright message remains intact.
+ ************************************************************************/
+
+#include <string.h>
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#  if defined(_MSC_VER) || defined(__GNUC__)
+#    if defined(STATIC_LINKED)
+#      define SWIGEXPORT(a) a
+#      define SWIGIMPORT(a) extern a
+#    else
+#      define SWIGEXPORT(a) __declspec(dllexport) a
+#      define SWIGIMPORT(a) extern a
+#    endif
+#  else
+#    if defined(__BORLANDC__)
+#      define SWIGEXPORT(a) a _export
+#      define SWIGIMPORT(a) a _export
+#    else
+#      define SWIGEXPORT(a) a
+#      define SWIGIMPORT(a) a
+#    endif
+#  endif
+#else
+#  define SWIGEXPORT(a) a
+#  define SWIGIMPORT(a) a
+#endif
+
+#ifdef SWIG_GLOBAL
+#  define SWIGRUNTIME(a) SWIGEXPORT(a)
+#else
+#  define SWIGRUNTIME(a) static a
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *(*swig_converter_func)(void *);
+typedef struct swig_type_info *(*swig_dycast_func)(void **);
+
+typedef struct swig_type_info {
+  const char             *name;
+  swig_converter_func     converter;
+  const char             *str;
+  void                   *clientdata;
+  swig_dycast_func        dcast;
+  struct swig_type_info  *next;
+  struct swig_type_info  *prev;
+} swig_type_info;
+
+#ifdef SWIG_NOINCLUDE
+
+SWIGIMPORT(swig_type_info *) SWIG_TypeRegister(swig_type_info *);
+SWIGIMPORT(swig_type_info *) SWIG_TypeCheck(char *c, swig_type_info *);
+SWIGIMPORT(void *)           SWIG_TypeCast(swig_type_info *, void *);
+SWIGIMPORT(swig_type_info *) SWIG_TypeDynamicCast(swig_type_info *, void **);
+SWIGIMPORT(const char *)     SWIG_TypeName(const swig_type_info *);
+SWIGIMPORT(swig_type_info *) SWIG_TypeQuery(const char *);
+SWIGIMPORT(void)             SWIG_TypeClientData(swig_type_info *, void *);
+SWIGIMPORT(char *)           SWIG_PackData(char *, void *, int);
+SWIGIMPORT(char *)           SWIG_UnpackData(char *, void *, int);
+
+#else
+
+static swig_type_info *swig_type_list = 0;
+
+/* Register a type mapping with the type-checking */
+SWIGRUNTIME(swig_type_info *)
+SWIG_TypeRegister(swig_type_info *ti) {
+  swig_type_info *tc, *head, *ret, *next;
+  /* Check to see if this type has already been registered */
+  tc = swig_type_list;
+  while (tc) {
+    if (strcmp(tc->name, ti->name) == 0) {
+      /* Already exists in the table.  Just add additional types to the list */
+      if (tc->clientdata) ti->clientdata = tc->clientdata;
+      head = tc;
+      next = tc->next;
+      goto l1;
+    }
+    tc = tc->prev;
+  }
+  head = ti;
+  next = 0;
+
+  /* Place in list */
+  ti->prev = swig_type_list;
+  swig_type_list = ti;
+
+  /* Build linked lists */
+  l1:
+  ret = head;
+  tc = ti + 1;
+  /* Patch up the rest of the links */
+  while (tc->name) {
+    head->next = tc;
+    tc->prev = head;
+    head = tc;
+    tc++;
+  }
+  if (next) next->prev = head;
+  head->next = next;
+  return ret;
+}
+
+/* Check the typename */
+SWIGRUNTIME(swig_type_info *) 
+SWIG_TypeCheck(char *c, swig_type_info *ty) {
+  swig_type_info *s;
+  if (!ty) return 0;        /* Void pointer */
+  s = ty->next;             /* First element always just a name */
+  do {
+    if (strcmp(s->name,c) == 0) {
+      if (s == ty->next) return s;
+      /* Move s to the top of the linked list */
+      s->prev->next = s->next;
+      if (s->next) {
+        s->next->prev = s->prev;
+      }
+      /* Insert s as second element in the list */
+      s->next = ty->next;
+      if (ty->next) ty->next->prev = s;
+      ty->next = s;
+      s->prev = ty;
+      return s;
+    }
+    s = s->next;
+  } while (s && (s != ty->next));
+  return 0;
+}
+
+/* Cast a pointer up an inheritance hierarchy */
+SWIGRUNTIME(void *) 
+SWIG_TypeCast(swig_type_info *ty, void *ptr) {
+  if ((!ty) || (!ty->converter)) return ptr;
+  return (*ty->converter)(ptr);
+}
+
+/* Dynamic pointer casting. Down an inheritance hierarchy */
+SWIGRUNTIME(swig_type_info *) 
+SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
+  swig_type_info *lastty = ty;
+  if (!ty || !ty->dcast) return ty;
+  while (ty && (ty->dcast)) {
+    ty = (*ty->dcast)(ptr);
+    if (ty) lastty = ty;
+  }
+  return lastty;
+}
+
+/* Return the name associated with this type */
+SWIGRUNTIME(const char *)
+SWIG_TypeName(const swig_type_info *ty) {
+  return ty->name;
+}
+
+/* Search for a swig_type_info structure */
+SWIGRUNTIME(swig_type_info *)
+SWIG_TypeQuery(const char *name) {
+  swig_type_info *ty = swig_type_list;
+  while (ty) {
+    if (ty->str && (strcmp(name,ty->str) == 0)) return ty;
+    if (ty->name && (strcmp(name,ty->name) == 0)) return ty;
+    ty = ty->prev;
+  }
+  return 0;
+}
+
+/* Set the clientdata field for a type */
+SWIGRUNTIME(void)
+SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
+  swig_type_info *tc, *equiv;
+  if (ti->clientdata == clientdata) return;
+  ti->clientdata = clientdata;
+  equiv = ti->next;
+  while (equiv) {
+    if (!equiv->converter) {
+      tc = swig_type_list;
+      while (tc) {
+        if ((strcmp(tc->name, equiv->name) == 0))
+          SWIG_TypeClientData(tc,clientdata);
+        tc = tc->prev;
+      }
+    }
+    equiv = equiv->next;
+  }
+}
+
+/* Pack binary data into a string */
+SWIGRUNTIME(char *)
+SWIG_PackData(char *c, void *ptr, int sz) {
+  static char hex[17] = "0123456789abcdef";
+  int i;
+  unsigned char *u = (unsigned char *) ptr;
+  register unsigned char uu;
+  for (i = 0; i < sz; i++,u++) {
+    uu = *u;
+    *(c++) = hex[(uu & 0xf0) >> 4];
+    *(c++) = hex[uu & 0xf];
+  }
+  return c;
+}
+
+/* Unpack binary data from a string */
+SWIGRUNTIME(char *)
+SWIG_UnpackData(char *c, void *ptr, int sz) {
+  register unsigned char uu = 0;
+  register int d;
+  unsigned char *u = (unsigned char *) ptr;
+  int i;
+  for (i = 0; i < sz; i++, u++) {
+    d = *(c++);
+    if ((d >= '0') && (d <= '9'))
+      uu = ((d - '0') << 4);
+    else if ((d >= 'a') && (d <= 'f'))
+      uu = ((d - ('a'-10)) << 4);
+    d = *(c++);
+    if ((d >= '0') && (d <= '9'))
+      uu |= (d - '0');
+    else if ((d >= 'a') && (d <= 'f'))
+      uu |= (d - ('a'-10));
+    *u = uu;
+  }
+  return c;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * $Header: /cvsroot/SWIG/Lib/tcl/swigtcl8.swg,v 1.19 2003/12/09 12:44:49 beazley Exp $
+ * 
+ * swigtcl8.swg
+ */
+
+#include <tcl.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Constant table */
+
+#define SWIG_TCL_INT     1
+#define SWIG_TCL_FLOAT   2
+#define SWIG_TCL_STRING  3
+#define SWIG_TCL_POINTER 4
+#define SWIG_TCL_BINARY  5
+
+/* Flags for pointer conversion */
+#define SWIG_POINTER_EXCEPTION     0x1
+#define SWIG_POINTER_DISOWN        0x2
+
+/* Swig fail macro */
+
+#define SWIG_fail   goto fail
+
+/* Constant information structure */
+typedef struct swig_const_info {
+    int type;
+    char *name;
+    long lvalue;
+    double dvalue;
+    void   *pvalue;
+    swig_type_info **ptype;
+} swig_const_info;
+
+typedef int   (*swig_wrapper)(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
+typedef int   (*swig_wrapper_func)(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
+typedef char *(*swig_variable_func)(ClientData, Tcl_Interp *, char *, char *, int);
+typedef void  (*swig_delete_func)(ClientData);
+
+typedef struct swig_method {
+  const char     *name;
+  swig_wrapper   method;
+} swig_method;
+
+typedef struct swig_attribute {
+  const char     *name;
+  swig_wrapper   getmethod;
+  swig_wrapper   setmethod;
+} swig_attribute;
+
+typedef struct swig_class {
+  const char         *name;
+  swig_type_info   **type;
+  swig_wrapper       constructor;
+  void              (*destructor)(void *);
+  swig_method        *methods;
+  swig_attribute     *attributes;
+  struct swig_class **bases;
+} swig_class;
+
+typedef struct swig_instance {
+  Tcl_Obj       *thisptr;
+  void          *thisvalue;
+  swig_class   *classptr;
+  int            destroy;
+  Tcl_Command    cmdtok;
+} swig_instance;
+
+#define SWIG_NewPointerObj(ptr, type, flags) \
+  SWIG_Tcl_NewPointerObj(ptr, type, flags)
+#define SWIG_ConvertPtr(oc, ptr, ty, flags) \
+  SWIG_Tcl_ConvertPtr(interp, oc, ptr, ty, flags)
+#define SWIG_ConvertPtrFromString(c, ptr, ty, flags) \
+  SWIG_Tcl_ConvertPtrFromString(interp, c, ptr, ty, flags)
+#define SWIG_ConvertPacked(obj, ptr, sz, ty, flags) \
+  SWIG_Tcl_ConvertPacked(interp, obj, ptr, sz, ty, flags)
+#define SWIG_MakePtr(c, ptr, ty, flags) \
+  SWIG_Tcl_MakePtr(c, ptr, ty, flags)
+#define SWIG_NewPackedObj(ptr, sz, type, flags) \
+  SWIG_Tcl_NewPackedObj(ptr, sz, type, flags)
+#define SWIG_GetArgs SWIG_Tcl_GetArgs
+#define SWIG_PointerTypeFromString(c) \
+  SWIG_Tcl_PointerTypeFromString(c)
+#define SWIG_Acquire(ptr) \
+  SWIG_Tcl_Acquire(ptr)
+#define SWIG_Disown(ptr) \
+  SWIG_Tcl_Disown(ptr)
+#define SWIG_Thisown(ptr) \
+  SWIG_Tcl_Thisown(ptr)
+#define SWIG_InstallConstants(interp, constants) \
+  SWIG_Tcl_InstallConstants(interp, constants)
+#define SWIG_GetConstant(key) \
+  SWIG_Tcl_GetConstant(key)
+#define SWIG_NewInstanceObj(thisvalue, type, flags) \
+  SWIG_Tcl_NewInstanceObj(interp, thisvalue, type, flags)
+#define SWIG_ObjectConstructor SWIG_Tcl_ObjectConstructor
+#define SWIG_MethodCommand SWIG_Tcl_MethodCommand
+#define SWIG_ObjectDelete SWIG_Tcl_ObjectDelete
+
+#ifdef SWIG_NOINCLUDE
+
+SWIGIMPORT(int)       SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *, char *, void **, swig_type_info *,int flags);
+SWIGIMPORT(int)       SWIG_Tcl_ConvertPtr(Tcl_Interp *, Tcl_Obj *, void **, swig_type_info *, int flags);
+SWIGIMPORT(int)       SWIG_Tcl_ConvertPacked(Tcl_Interp *, Tcl_Obj *, void *, int sz, swig_type_info *, int flags);
+SWIGIMPORT(void)      SWIG_Tcl_MakePtr(char *, void *, swig_type_info *, int flags);
+SWIGIMPORT(Tcl_Obj *) SWIG_Tcl_NewPointerObj(void *, swig_type_info *, int flags);
+SWIGIMPORT(Tcl_Obj *) SWIG_Tcl_NewPackedObj(void *, int sz, swig_type_info *, int flags);
+SWIGIMPORT(int)       SWIG_Tcl_GetArgs(Tcl_Interp *, int, Tcl_Obj *CONST [], const char *, ...);
+SWIGIMPORT(char *)    SWIG_Tcl_PointerTypeFromString(char *c);
+SWIGIMPORT(void)      SWIG_Tcl_Acquire(void *ptr);
+SWIGIMPORT(int)       SWIG_Tcl_Disown(void *ptr);
+SWIGIMPORT(int)       SWIG_Tcl_Thisown(void *ptr);
+SWIGIMPORT(void)      SWIG_Tcl_InstallConstants(Tcl_Interp *interp, struct swig_const_info constants[]);
+SWIGIMPORT(Tcl_Obj *) SWIG_Tcl_GetConstant(const char *key);
+SWIGIMPORT(Tcl_Obj *) SWIG_Tcl_NewInstanceObj(Tcl_Interp *interp, void *, swig_type_info *, int flags);
+SWIGIMPORT(int)       SWIG_Tcl_ObjectConstructor(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
+SWIGIMPORT(int)       SWIG_Tcl_MethodCommand(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
+SWIGIMPORT(void)      SWIG_Tcl_ObjectDelete(ClientData);
+
+#else
+
+/* Object support */
+static Tcl_HashTable  swigobjectTable;
+static int            swigobjectTableinit = 0;
+
+/* Acquire ownership of a pointer */
+SWIGRUNTIME(void)
+SWIG_Tcl_Acquire(void *ptr) {
+  Tcl_HashEntry *entryPtr;
+  int newobj;
+  if (!swigobjectTableinit) {
+    Tcl_InitHashTable(&swigobjectTable, TCL_ONE_WORD_KEYS);
+    swigobjectTableinit = 1;
+  }
+  entryPtr = Tcl_CreateHashEntry(&swigobjectTable, (char *) ptr, &newobj);
+}
+
+/* Disown a pointer.  Returns 1 if we owned it to begin with */
+SWIGRUNTIME(int)
+SWIG_Tcl_Disown(void *ptr) {
+  Tcl_HashEntry *entryPtr;
+  if (!swigobjectTableinit) return 0;
+  entryPtr = Tcl_FindHashEntry(&swigobjectTable, (char *) ptr);
+  if (entryPtr) {
+    Tcl_DeleteHashEntry(entryPtr);
+    return 1;
+  }
+  return 0;
+}
+
+SWIGRUNTIME(int)
+SWIG_Tcl_Thisown(void *ptr) {
+  if (!swigobjectTableinit) return 0;
+  if (Tcl_FindHashEntry(&swigobjectTable, (char *) ptr)) {
+    return 1;
+  }
+  return 0;
+}
+
+/* Convert a pointer value */
+SWIGRUNTIME(int)
+SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *interp, char *c, void **ptr, swig_type_info *ty, int flags) {
+  swig_type_info *tc;
+  /* Pointer values must start with leading underscore */
+  while (*c != '_') {
+    *ptr = (void *) 0;
+    if (strcmp(c,"NULL") == 0) return TCL_OK;
+    /* Hmmm. It could be an object name. */
+    if (Tcl_VarEval(interp,c," cget -this", (char *) NULL) == TCL_OK) {
+      Tcl_Obj *result = Tcl_GetObjResult(interp);
+      c = Tcl_GetStringFromObj(result, NULL);
+      continue;
+    }
+    Tcl_ResetResult(interp);
+    if (flags & SWIG_POINTER_EXCEPTION) 
+      Tcl_SetResult(interp, (char *) "Type error. Expected a pointer", TCL_STATIC);
+    return TCL_ERROR;
+  }
+  c++;
+  c = SWIG_UnpackData(c,ptr,sizeof(void *));
+  if (ty) {
+    tc = SWIG_TypeCheck(c,ty);
+    if ((!tc) && (flags & SWIG_POINTER_EXCEPTION)) {
+      Tcl_SetResult(interp, (char *) "Type error. Expected ", TCL_STATIC);
+      Tcl_AppendElement(interp, (char *) ty->name);
+      return TCL_ERROR;
+    } else if (!tc) {
+      Tcl_ResetResult(interp);
+      return TCL_ERROR;
+    }
+    if (flags & SWIG_POINTER_DISOWN) {
+      SWIG_Disown((void *) *ptr);
+    }
+    *ptr = SWIG_TypeCast(tc,(void *) *ptr);
+  }
+  return TCL_OK;
+}
+
+/* Convert a pointer value */
+SWIGRUNTIME(int)
+SWIG_Tcl_ConvertPtr(Tcl_Interp *interp, Tcl_Obj *oc, void **ptr, swig_type_info *ty, int flags) {
+  return SWIG_Tcl_ConvertPtrFromString(interp, Tcl_GetStringFromObj(oc,NULL), ptr, ty, flags);
+}
+
+/* Convert a pointer value */
+SWIGRUNTIME(char *)
+SWIG_Tcl_PointerTypeFromString(char *c) {
+  char d;
+  /* Pointer values must start with leading underscore. NULL has no type */
+  if (*c != '_') {
+    return 0;
+  }
+  c++;
+  /* Extract hex value from pointer */
+  while ((d = *c)) {
+    if (!(((d >= '0') && (d <= '9')) || ((d >= 'a') && (d <= 'f')))) break;
+    c++;
+  }
+  return c;
+}
+
+/* Convert a packed value value */
+SWIGRUNTIME(int)
+SWIG_Tcl_ConvertPacked(Tcl_Interp *interp, Tcl_Obj *obj, void *ptr, int sz, swig_type_info *ty, int flags) {
+  swig_type_info *tc;
+  char  *c;
+
+  if (!obj) goto type_error;
+  c = Tcl_GetStringFromObj(obj,NULL);
+  /* Pointer values must start with leading underscore */
+  if (*c != '_') goto type_error;
+  c++;
+  c = SWIG_UnpackData(c,ptr,sz);
+  if (ty) {
+    tc = SWIG_TypeCheck(c,ty);
+    if (!tc) goto type_error;
+  }
+  return TCL_OK;
+
+type_error:
+
+  if (flags) {
+    if (ty) {
+      Tcl_SetResult(interp, (char *) "Type error. Expected ", TCL_STATIC);
+      Tcl_AppendElement(interp, (char *) ty->name);
+      return TCL_ERROR;
+    } else {
+      Tcl_SetResult(interp, (char *) "Expected packed data.", TCL_STATIC);
+      return TCL_ERROR;
+    }
+  }
+  return TCL_ERROR;
+}
+
+
+/* Take a pointer and convert it to a string */
+SWIGRUNTIME(void)
+SWIG_Tcl_MakePtr(char *c, void *ptr, swig_type_info *ty, int flags) {
+  if (ptr) {
+    *(c++) = '_';
+    c = SWIG_PackData(c,&ptr,sizeof(void *));
+    strcpy(c,ty->name);
+  } else {
+    strcpy(c,(char *)"NULL");
+  }
+  flags = 0;
+}
+
+/* Create a new pointer object */
+SWIGRUNTIME(Tcl_Obj *)
+SWIG_Tcl_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
+  Tcl_Obj *robj;
+  char result[512];
+  SWIG_MakePtr(result,ptr,type,flags);
+  robj = Tcl_NewStringObj(result,-1);
+  return robj;
+}
+
+SWIGRUNTIME(Tcl_Obj *)
+SWIG_Tcl_NewPackedObj(void *ptr, int sz, swig_type_info *type, int flags) {
+  char result[1024];
+  char *r = result;
+  if ((2*sz + 1 + strlen(type->name)) > 1000) return 0;
+  *(r++) = '_';
+  r = SWIG_PackData(r,ptr,sz);
+  strcpy(r,type->name);
+  flags = 0;
+  return Tcl_NewStringObj(result,-1);
+}
+
+static Tcl_HashTable   swigconstTable;
+static int             swigconstTableinit = 0;
+
+/* Install Constants */
+SWIGRUNTIME(void)
+SWIG_Tcl_InstallConstants(Tcl_Interp *interp, swig_const_info constants[]) {
+  int i;
+  Tcl_Obj *obj;
+  Tcl_HashEntry *entryPtr;
+  int            newobj;
+
+  if (!swigconstTableinit) {
+    Tcl_InitHashTable(&swigconstTable, TCL_STRING_KEYS);
+    swigconstTableinit = 1;
+  }
+  for (i = 0; constants[i].type; i++) {
+    switch(constants[i].type) {
+    case SWIG_TCL_INT:
+      obj = Tcl_NewIntObj(constants[i].lvalue);
+      break;
+    case SWIG_TCL_FLOAT:
+      obj = Tcl_NewDoubleObj(constants[i].dvalue);
+      break;
+    case SWIG_TCL_STRING:
+      obj = Tcl_NewStringObj((char *) constants[i].pvalue,-1);
+      break;
+    case SWIG_TCL_POINTER:
+      obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+      break;
+    case SWIG_TCL_BINARY:
+      obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype),0);
+      break;
+    default:
+      obj = 0;
+      break;
+    }
+    if (obj) {
+      Tcl_ObjSetVar2(interp,Tcl_NewStringObj(constants[i].name,-1), NULL, obj, TCL_GLOBAL_ONLY);
+      entryPtr = Tcl_CreateHashEntry(&swigconstTable, constants[i].name, &newobj);
+      Tcl_SetHashValue(entryPtr, (ClientData) obj);
+    }
+  }
+}
+
+SWIGRUNTIME(Tcl_Obj *)
+SWIG_Tcl_GetConstant(const char *key) {
+  Tcl_HashEntry *entryPtr;
+  if (!swigconstTableinit) return 0;
+  entryPtr = Tcl_FindHashEntry(&swigconstTable, key);
+  if (entryPtr) {
+    return (Tcl_Obj *) Tcl_GetHashValue(entryPtr);
+  }
+  printf("Searching %s\n", key);
+  return 0;
+}
+
+/* Get arguments */
+SWIGRUNTIME(int)
+SWIG_Tcl_GetArgs(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], const char *fmt, ...) {
+  int        argno = 0, opt = 0;
+  long       tempi;
+  double     tempd;
+  const char *c;
+  va_list    ap;
+  void      *vptr;
+  Tcl_Obj   *obj = 0;
+  swig_type_info *ty;
+
+  va_start(ap,fmt);
+  for (c = fmt; (*c && (*c != ':') && (*c != ';')); c++,argno++) {
+    if (*c == '|') {
+      opt = 1;
+      c++;
+    }
+    if (argno >= (objc-1)) {
+      if (!opt) {
+        Tcl_SetResult(interp, (char *) "Wrong # args. ", TCL_STATIC);
+        goto argerror;
+      } else {
+        va_end(ap);
+        return TCL_OK;
+      }
+    }
+
+    vptr = va_arg(ap,void *);
+    if (vptr) {
+      if (isupper(*c)) {
+        obj = SWIG_GetConstant(Tcl_GetStringFromObj(objv[argno+1],0));
+        if (!obj) obj = objv[argno+1];
+      } else {
+        obj = objv[argno+1];
+      }
+      switch(*c) {
+      case 'i': case 'I':
+      case 'l': case 'L':
+      case 'h': case 'H':
+      case 'b': case 'B':
+        if (Tcl_GetLongFromObj(interp,obj,&tempi) != TCL_OK) goto argerror;
+        if ((*c == 'i') || (*c == 'I')) *((int *)vptr) = (int)tempi;
+        else if ((*c == 'l') || (*c == 'L')) *((long *)vptr) = (long)tempi;
+        else if ((*c == 'h') || (*c == 'H')) *((short*)vptr) = (short)tempi;
+        else if ((*c == 'b') || (*c == 'B')) *((unsigned char *)vptr) = (unsigned char)tempi;
+        break;
+      case 'f': case 'F':
+      case 'd': case 'D':
+        if (Tcl_GetDoubleFromObj(interp,obj,&tempd) != TCL_OK) goto argerror;
+        if ((*c == 'f') || (*c == 'F')) *((float *) vptr) = (float)tempd;
+        else if ((*c == 'd') || (*c == 'D')) *((double*) vptr) = tempd;
+        break;
+      case 's': case 'S':
+        if (*(c+1) == '#') {
+          int *vlptr = (int *) va_arg(ap, void *);
+          *((char **) vptr) = Tcl_GetStringFromObj(obj, vlptr);
+          c++;
+        } else {
+          *((char **)vptr) = Tcl_GetStringFromObj(obj,NULL);
+        }
+        break;
+      case 'c': case 'C':
+        *((char *)vptr) = *(Tcl_GetStringFromObj(obj,NULL));
+        break;
+      case 'p': case 'P':
+        ty = (swig_type_info *) va_arg(ap, void *);
+        if (SWIG_Tcl_ConvertPtr(interp, obj, (void **) vptr, ty, SWIG_POINTER_EXCEPTION) == TCL_ERROR) goto argerror;
+        break;
+      case 'o': case 'O':
+        *((Tcl_Obj **)vptr) = objv[argno+1];
+        break;
+      default:
+        break;
+      }
+    }
+  }
+
+  if ((*c != ';') && ((objc-1) > argno)) {
+    Tcl_SetResult(interp, (char *) "Wrong # args.", TCL_STATIC);
+    goto argerror;
+  }
+  va_end(ap);
+  return TCL_OK;
+
+ argerror:
+  {
+    char temp[32];
+    sprintf(temp,"%d", argno+1);
+    c = strchr(fmt,':');
+    if (!c) c = strchr(fmt,';');
+    if (!c) c = (char *)"";
+    Tcl_AppendResult(interp,c," argument ", temp, NULL);
+    va_end(ap);
+    return TCL_ERROR;
+  }
+}
+
+SWIGRUNTIME(void)
+SWIG_Tcl_ObjectDelete(ClientData clientData) {
+  swig_instance *si = (swig_instance *) clientData;
+  if ((si) && (si->destroy) && (SWIG_Disown(si->thisvalue))) {
+    if (si->classptr->destructor) {
+      (si->classptr->destructor)(si->thisvalue);
+    }
+  }
+  Tcl_DecrRefCount(si->thisptr);
+  free(si);
+}
+
+/* Function to invoke object methods given an instance */
+SWIGRUNTIME(int)
+SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST _objv[]) {
+  char *method,   *attrname;
+  swig_instance   *inst = (swig_instance *) clientData;
+  swig_method     *meth;
+  swig_attribute  *attr;
+  Tcl_Obj         *oldarg;
+  Tcl_Obj         **objv;
+  int              rcode;
+  swig_class      *cls;
+  swig_class      *cls_stack[64];
+  int              cls_stack_bi[64];
+  int              cls_stack_top = 0;
+  int              numconf = 2;
+  int              bi;
+
+  objv = (Tcl_Obj **) _objv;
+  if (objc < 2) {
+    Tcl_SetResult(interp, (char *) "wrong # args.", TCL_STATIC);
+    return TCL_ERROR;
+  }
+  method = Tcl_GetStringFromObj(objv[1],NULL);
+  if (strcmp(method,"-acquire") == 0) {
+    inst->destroy = 1;
+    SWIG_Acquire(inst->thisvalue);
+    return TCL_OK;
+  }
+  if (strcmp(method,"-disown") == 0) {
+    if (inst->destroy) {
+      SWIG_Disown(inst->thisvalue);
+    }
+    inst->destroy = 0;
+    return TCL_OK;
+  }
+  if (strcmp(method,"-delete") == 0) {
+    Tcl_DeleteCommandFromToken(interp,inst->cmdtok);
+    return TCL_OK;
+  }
+  cls_stack[cls_stack_top] = inst->classptr;
+  cls_stack_bi[cls_stack_top] = -1;
+  cls = inst->classptr;
+  while (1) {
+    bi = cls_stack_bi[cls_stack_top];
+    cls = cls_stack[cls_stack_top];
+    if (bi != -1) {
+      cls = cls->bases[bi];
+      if (cls) {
+        cls_stack_bi[cls_stack_top]++;
+        cls_stack_top++;
+        cls_stack[cls_stack_top] = cls;
+        cls_stack_bi[cls_stack_top] = -1;
+        continue;
+      }
+    }
+    if (!cls) {
+      cls_stack_top--;
+      if (cls_stack_top < 0) break;
+      else continue;
+    }
+    cls_stack_bi[cls_stack_top]++;
+
+    meth = cls->methods;
+    /* Check for methods */
+    while (meth && meth->name) {
+      if (strcmp(meth->name,method) == 0) {
+        oldarg = objv[1];
+        objv[1] = inst->thisptr;
+        Tcl_IncrRefCount(inst->thisptr);
+        rcode = (*meth->method)(clientData,interp,objc,objv);
+        objv[1] = oldarg;
+        Tcl_DecrRefCount(inst->thisptr);
+        return rcode;
+      }
+      meth++;
+    }
+    /* Check class methods for a match */
+    if (strcmp(method,"cget") == 0) {
+      if (objc < 3) {
+        Tcl_SetResult(interp, (char *) "wrong # args.", TCL_STATIC);
+        return TCL_ERROR;
+      }
+      attrname = Tcl_GetStringFromObj(objv[2],NULL);
+      attr = cls->attributes;
+      while (attr && attr->name) {
+        if ((strcmp(attr->name, attrname) == 0) && (attr->getmethod)) {
+          oldarg = objv[1];
+          objv[1] = inst->thisptr;
+          Tcl_IncrRefCount(inst->thisptr);
+          rcode = (*attr->getmethod)(clientData,interp,2, objv);
+          objv[1] = oldarg;
+          Tcl_DecrRefCount(inst->thisptr);
+          return rcode;
+        }
+        attr++;
+      }
+      if (strcmp(attrname, "-this") == 0) {
+        Tcl_SetObjResult(interp, Tcl_DuplicateObj(inst->thisptr));
+        return TCL_OK;
+      }
+      if (strcmp(attrname, "-thisown") == 0) {
+        if (SWIG_Thisown(inst->thisvalue)) {
+          Tcl_SetResult(interp,(char*)"1",TCL_STATIC);
+        } else {
+          Tcl_SetResult(interp,(char*)"0",TCL_STATIC);
+        }
+        return TCL_OK;
+      }
+    } else if (strcmp(method, "configure") == 0) {
+      int i;
+      if (objc < 4) {
+        Tcl_SetResult(interp, (char *) "wrong # args.", TCL_STATIC);
+        return TCL_ERROR;
+      }
+      i = 2;
+      while (i < objc) {
+        attrname = Tcl_GetStringFromObj(objv[i],NULL);
+        attr = cls->attributes;
+        while (attr && attr->name) {
+          if ((strcmp(attr->name, attrname) == 0) && (attr->setmethod)) {
+            oldarg = objv[i];
+            objv[i] = inst->thisptr;
+            Tcl_IncrRefCount(inst->thisptr);
+            rcode = (*attr->setmethod)(clientData,interp,3, &objv[i-1]);
+            objv[i] = oldarg;
+            Tcl_DecrRefCount(inst->thisptr);
+            if (rcode != TCL_OK) return rcode;
+            numconf += 2;
+          }
+          attr++;
+        }
+        i+=2;
+      }
+    }
+  }
+  if (strcmp(method,"configure") == 0) {
+    if (numconf >= objc) {
+      return TCL_OK;
+    } else {
+      Tcl_SetResult(interp,(char *) "Invalid attribute name.", TCL_STATIC);
+      return TCL_ERROR;
+    }
+  }
+  if (strcmp(method,"cget") == 0) {
+      Tcl_SetResult(interp,(char *) "Invalid attribute name.", TCL_STATIC);
+      return TCL_ERROR;
+  }
+
+  Tcl_SetResult(interp, (char *) "Invalid method. Must be one of: configure cget -acquire -disown -delete", TCL_STATIC);
+  cls = inst->classptr;
+  bi = 0;
+  while (cls) {
+    meth = cls->methods;
+    while (meth && meth->name) {
+      char *cr = (char *) Tcl_GetStringResult(interp);
+      if (!strstr(strchr(cr,':'), meth->name))
+        Tcl_AppendElement(interp, (char *) meth->name);
+      meth++;
+    }
+    cls = inst->classptr->bases[bi++];
+  }
+  return TCL_ERROR;
+}
+
+/* Function to create objects */
+SWIGRUNTIME(int)
+SWIG_Tcl_ObjectConstructor(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    Tcl_Obj          *newObj = 0;
+    void             *thisvalue = 0;
+    swig_instance   *newinst = 0;
+    swig_class      *classptr = (swig_class *) clientData;
+    swig_wrapper     cons = 0;
+    char             *name = 0;
+    int               firstarg = 0;
+    int               thisarg = 0;
+    int               destroy = 1;
+
+    if (!classptr) {
+      Tcl_SetResult(interp, (char *) "swig: internal runtime error. No class object defined.", TCL_STATIC);
+      return TCL_ERROR;
+    }
+    cons = classptr->constructor;
+    if (objc > 1) {
+      char *s = Tcl_GetStringFromObj(objv[1],NULL);
+      if (strcmp(s,"-this") == 0) {
+        thisarg = 2;
+        cons = 0;
+      } else if (strcmp(s,"-args") == 0) {
+        firstarg = 1;
+      } else if (objc == 2) {
+        firstarg = 1;
+        name = s;
+      } else if (objc >= 3) {
+        char *s1;
+        name = s;
+        s1 = Tcl_GetStringFromObj(objv[2],NULL);
+        if (strcmp(s1,"-this") == 0) {
+          thisarg = 3;
+          cons = 0;
+        } else {
+          firstarg = 1;
+        }
+      }
+    }
+    if (cons) {
+      int result;
+      result = (*cons)(0, interp, objc-firstarg, &objv[firstarg]);
+      if (result != TCL_OK) {
+        return result;
+      }
+      newObj = Tcl_DuplicateObj(Tcl_GetObjResult(interp));
+      if (!name) name = Tcl_GetStringFromObj(newObj,NULL);
+    } else if (thisarg > 0) {
+      if (thisarg < objc) {
+        destroy = 0;
+        newObj = Tcl_DuplicateObj(objv[thisarg]);
+        if (!name) name = Tcl_GetStringFromObj(newObj,NULL);
+      } else {
+        Tcl_SetResult(interp, (char *) "wrong # args.", TCL_STATIC);
+        return TCL_ERROR;
+      }
+    } else {
+      Tcl_SetResult(interp, (char *) "No constructor available.", TCL_STATIC);
+      return TCL_ERROR;
+    }
+    if (SWIG_Tcl_ConvertPtr(interp,newObj, (void **) &thisvalue, *(classptr->type), SWIG_POINTER_EXCEPTION) == TCL_ERROR) {
+      Tcl_DecrRefCount(newObj);
+      return TCL_ERROR;
+    }
+    newinst = (swig_instance *) malloc(sizeof(swig_instance));
+    newinst->thisptr = newObj;
+    Tcl_IncrRefCount(newObj);
+    newinst->thisvalue = thisvalue;
+    newinst->classptr = classptr;
+    newinst->destroy = destroy;
+    if (destroy) {
+      SWIG_Acquire(thisvalue);
+    }
+    newinst->cmdtok = Tcl_CreateObjCommand(interp,name, (swig_wrapper) SWIG_MethodCommand, (ClientData) newinst, (swig_delete_func) SWIG_ObjectDelete);
+    return TCL_OK;
+}
+
+
+/* This function takes the current result and turns it into an object command */
+SWIGRUNTIME(Tcl_Obj *)
+SWIG_Tcl_NewInstanceObj(Tcl_Interp *interp, void *thisvalue, swig_type_info *type, int flags) {
+  Tcl_Obj *robj = SWIG_NewPointerObj(thisvalue, type,0);
+  /* Check to see if this pointer belongs to a class or not */
+  if ((type->clientdata) && (interp)) {
+    Tcl_CmdInfo    ci;
+    char          *name;
+    name = Tcl_GetStringFromObj(robj,NULL);
+    if (!Tcl_GetCommandInfo(interp,name, &ci) || (flags)) {
+      swig_instance *newinst = (swig_instance *) malloc(sizeof(swig_instance));
+      newinst->thisptr = Tcl_DuplicateObj(robj);
+      Tcl_IncrRefCount(newinst->thisptr);
+      newinst->thisvalue = thisvalue;
+      newinst->classptr = (swig_class *) type->clientdata;
+      newinst->destroy = flags;
+      newinst->cmdtok = Tcl_CreateObjCommand(interp, Tcl_GetStringFromObj(robj,NULL), (swig_wrapper_func) SWIG_MethodCommand, (ClientData) newinst, (swig_delete_func) SWIG_ObjectDelete);
+      if (flags) {
+        SWIG_Acquire(thisvalue);
+      }
+    }
+  }
+  return robj;
+}
+
+#endif
+
+/* Structure for command table */
+typedef struct {
+  const char *name;
+  int       (*wrapper)(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
+  ClientData  clientdata;
+} swig_command_info;
+
+/* Structure for variable linking table */
+typedef struct {
+  const char *name;
+  void *addr;
+  char * (*get)(ClientData, Tcl_Interp *, char *, char *, int);
+  char * (*set)(ClientData, Tcl_Interp *, char *, char *, int);
+} swig_var_info;
+
+
+/* Contract support */
+
+#define SWIG_contract_assert(expr, msg)  if (!(expr)) { Tcl_SetResult(interp, (char *) msg, TCL_STATIC ); goto fail; } else
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define  SWIGTYPE_p_p_char swig_types[0] 
+#define  SWIGTYPE_p_p_p_char swig_types[1] 
+#define  SWIGTYPE_p_iter_t swig_types[2] 
+#define  SWIGTYPE_iter_t swig_types[3] 
+#define  SWIGTYPE_p_profile_t swig_types[4] 
+#define  SWIGTYPE_profile_t swig_types[5] 
+#define  SWIGTYPE_p_int swig_types[6] 
+static swig_type_info *swig_types[8];
+
+/* -------- TYPES TABLE (END) -------- */
+
+#define SWIG_init    Profile_Init
+#define SWIG_name    "profile"
+#define SWIG_prefix  ""
+#define SWIG_version "0.0"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef MAC_TCL
+#pragma export on
+#endif
+SWIGEXPORT(int) SWIG_init(Tcl_Interp *);
+#ifdef MAC_TCL
+#pragma export off
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/*
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * Input for wrapper generator program SWIG for profile routines.
+ */
+#include <errno.h>
+#include "com_err.h"
+#include "profile.h"
+
+#ifdef SWIGTCL
+/* Reduce warnings about cast discarding const to just this one, from
+   every SWIG-generated call to Tcl_SetResult.  */
+static void my_tcl_setresult(Tcl_Interp *i, const char *str, Tcl_FreeProc *f)
+{
+    Tcl_SetResult(i, (char *) str, f);
+}
+#undef Tcl_SetResult
+#define Tcl_SetResult my_tcl_setresult
+#endif
+
+
+typedef void **iter_t; /* ick */
+
+extern errcode_t profile_get_string(profile_t,char const *,char const *,char const *,char const *,char **);
+
+static errcode_t iter_create(profile_t p, const char **nullterm,
+			     int flags, iter_t *OUTPUT)
+{
+    iter_t it;
+    errcode_t err;
+    char **args;
+
+    it = malloc(sizeof(*it));
+    if (it == NULL)
+	return errno;
+    {
+	/* Memory leak!
+
+	   The profile code seems to assume that I'll keep the string
+	   array around for as long as the iterator is valid; I can't
+	   create the iterator and then throw them away.
+
+	   But right now, I can't be bothered to track the necessary
+	   information to do the cleanup later.  */
+	int count, j;
+	for (count = 0; nullterm[count]; count++) ;
+	args = calloc(count+1, sizeof(char *));
+	if (args == NULL)
+	    return errno;
+	for (j = 0; j < count; j++) {
+	    args[j] = strdup(nullterm[j]);
+	    if (args[j] == NULL)
+		return errno;
+	}
+	args[j] = NULL;
+    }
+    err = profile_iterator_create(p, args, flags, it);
+    if (err)
+	free(it);
+    else
+	*OUTPUT = it;
+    return err;
+}
+static errcode_t iter_free(iter_t i)
+{
+    profile_iterator_free(i);
+    free(i);
+}
+
+
+
+/* A TCL_AppInit() function that lets you build a new copy
+ * of tclsh.
+ *
+ * The macro SWIG_init contains the name of the initialization
+ * function in the wrapper file.
+ */
+
+#ifndef SWIG_RcFileName
+char *SWIG_RcFileName = "~/.myapprc";
+#endif
+
+
+#ifdef MAC_TCL
+extern int		MacintoshInit _ANSI_ARGS_((void));
+#endif
+
+int Tcl_AppInit(Tcl_Interp *interp){
+
+  if (Tcl_Init(interp) == TCL_ERROR) 
+    return TCL_ERROR;
+
+  /* Now initialize our functions */
+
+  if (SWIG_init(interp) == TCL_ERROR)
+    return TCL_ERROR;
+#if TCL_MAJOR_VERSION > 7 || TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION >= 5
+   Tcl_SetVar(interp, (char *) "tcl_rcFileName",SWIG_RcFileName,TCL_GLOBAL_ONLY);
+#else
+   tcl_RcFileName = SWIG_RcFileName;
+#endif
+#ifdef SWIG_RcRsrcName
+  Tcl_SetVar(interp, (char *) "tcl_rcRsrcName",SWIG_RcRsrcName,TCL_GLOBAL);
+#endif
+  
+  return TCL_OK;
+}
+
+#if TCL_MAJOR_VERSION > 7 || TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION >= 4
+int main(int argc, char **argv) {
+#ifdef MAC_TCL
+    char *newArgv[2];
+    
+    if (MacintoshInit()  != TCL_OK) {
+	Tcl_Exit(1);
+    }
+
+    argc = 1;
+    newArgv[0] = "tclsh";
+    newArgv[1] = NULL;
+    argv = newArgv;
+#endif
+
+  Tcl_Main(argc, argv, Tcl_AppInit);
+  return(0);
+
+}
+#else
+extern int main();
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static int
+_wrap_profile_init_path(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    char *arg1 = (char *) NULL ;
+    profile_t *arg2 = (profile_t *) 0 ;
+    errcode_t result;
+    profile_t tmp2 ;
+    
+    {
+        /*generic swigtype hack*/ arg2 = &tmp2;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"|s:profile_init_path ?path? ",&arg1) == TCL_ERROR) SWIG_fail;
+    result = (errcode_t)profile_init_path((char const *)arg1,arg2);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    /*generic swigtype hack*/ Tcl_SetObjResult(interp,SWIG_NewInstanceObj((void *) *arg2, SWIGTYPE_profile_t,0));
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_init(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    char **arg1 = (char **) NULL ;
+    profile_t *arg2 = (profile_t *) 0 ;
+    errcode_t result;
+    profile_t tmp2 ;
+    
+    {
+        /*generic swigtype hack*/ arg2 = &tmp2;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"|o:profile_init ?nullterm? ",0) == TCL_ERROR) SWIG_fail;
+    if (objc > 1) {
+        {
+            /* in char **nullterm */
+            int n;
+            if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[1],NULL), &n, &arg1) == TCL_ERROR) SWIG_fail;
+        }
+    }
+    result = (errcode_t)profile_init((char const **)arg1,arg2);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    /*generic swigtype hack*/ Tcl_SetObjResult(interp,SWIG_NewInstanceObj((void *) *arg2, SWIGTYPE_profile_t,0));
+    {
+        /* freearg char **nullterm */
+        if (arg1) {
+            Tcl_Free((char *)arg1); arg1 = (char **) NULL; 
+        }
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg1) {
+            Tcl_Free((char *)arg1); arg1 = (char **) NULL; 
+        }
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_flush(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    errcode_t result;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"o:profile_flush profile_t ",0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_flush(arg1);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_flush_to_file(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char *arg2 ;
+    errcode_t result;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"os:profile_flush_to_file profile_t path ",0,&arg2) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_flush_to_file(arg1,(char const *)arg2);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_abandon(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"o:profile_abandon profile_t ",0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    profile_abandon(arg1);
+    
+    
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_release(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"o:profile_release profile_t ",0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    profile_release(arg1);
+    
+    
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_get_values(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    char ***arg3 = (char ***) 0 ;
+    errcode_t result;
+    char **tmp3 ;
+    
+    {
+        /* in char ***OUTPUT */
+        tmp3 = NULL;
+        arg3 = &tmp3;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"oo:profile_get_values p nullterm ",0,0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)profile_get_values(arg1,(char const **)arg2,arg3);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* argout char ***OUTPUT */
+        int i;
+        for (i = 0; (*arg3)[i]; i++)
+        Tcl_AppendElement(interp, (*arg3)[i]);
+    }
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    {
+        /* freearg char ***OUTPUT */
+        profile_free_list(*arg3);
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    {
+        /* freearg char ***OUTPUT */
+        profile_free_list(*arg3);
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_get_string(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char *arg2 ;
+    char *arg3 ;
+    char *arg4 = (char *) NULL ;
+    char *arg5 = (char *) NULL ;
+    char **arg6 = (char **) 0 ;
+    errcode_t result;
+    char *tmp6 ;
+    
+    {
+        /* in char **OUTPUT */
+        tmp6 = NULL;
+        arg6 = &tmp6;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"oss|ss:profile_get_string p name subname ?subsubname? ?defval? ",0,&arg2,&arg3,&arg4,&arg5) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_get_string(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,(char const *)arg5,arg6);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* argout char **OUTPUT */
+        /*    Tcl_SetResult(interp, *arg6, TCL_DYNAMIC); */
+        char *s = (arg6 && *arg6) ? *arg6 : "";
+        Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
+        Tcl_NewStringObj(s, strlen(s)));
+    }
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg6); */
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg6); */
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_get_integer(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char *arg2 ;
+    char *arg3 ;
+    char *arg4 = (char *) NULL ;
+    int arg5 = (int) 0 ;
+    int *arg6 = (int *) 0 ;
+    errcode_t result;
+    int temp6 ;
+    
+    arg6 = &temp6;
+    if (SWIG_GetArgs(interp, objc, objv,"oss|si:profile_get_integer p name subname ?subsubname? ?defval? ",0,&arg2,&arg3,&arg4,&arg5) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_get_integer(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,arg6);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        Tcl_Obj *o;
+        o = Tcl_NewIntObj((int) *(arg6));
+        Tcl_ListObjAppendElement(interp,Tcl_GetObjResult(interp),o);
+    }
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_get_boolean(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char *arg2 ;
+    char *arg3 ;
+    char *arg4 = (char *) NULL ;
+    int arg5 = (int) 0 ;
+    int *arg6 = (int *) 0 ;
+    errcode_t result;
+    int temp6 ;
+    
+    arg6 = &temp6;
+    if (SWIG_GetArgs(interp, objc, objv,"oss|si:profile_get_boolean p name subname ?subsubname? ?defval? ",0,&arg2,&arg3,&arg4,&arg5) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_get_boolean(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,arg6);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        Tcl_Obj *o;
+        o = Tcl_NewIntObj((int) *(arg6));
+        Tcl_ListObjAppendElement(interp,Tcl_GetObjResult(interp),o);
+    }
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_get_relation_names(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    char ***arg3 = (char ***) 0 ;
+    errcode_t result;
+    char **tmp3 ;
+    
+    {
+        /* in char ***OUTPUT */
+        tmp3 = NULL;
+        arg3 = &tmp3;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"oo:profile_get_relation_names p nullterm ",0,0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)profile_get_relation_names(arg1,(char const **)arg2,arg3);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* argout char ***OUTPUT */
+        int i;
+        for (i = 0; (*arg3)[i]; i++)
+        Tcl_AppendElement(interp, (*arg3)[i]);
+    }
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    {
+        /* freearg char ***OUTPUT */
+        profile_free_list(*arg3);
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    {
+        /* freearg char ***OUTPUT */
+        profile_free_list(*arg3);
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_get_subsection_names(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    char ***arg3 = (char ***) 0 ;
+    errcode_t result;
+    char **tmp3 ;
+    
+    {
+        /* in char ***OUTPUT */
+        tmp3 = NULL;
+        arg3 = &tmp3;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"oo:profile_get_subsection_names p nullterm ",0,0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)profile_get_subsection_names(arg1,(char const **)arg2,arg3);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* argout char ***OUTPUT */
+        int i;
+        for (i = 0; (*arg3)[i]; i++)
+        Tcl_AppendElement(interp, (*arg3)[i]);
+    }
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    {
+        /* freearg char ***OUTPUT */
+        profile_free_list(*arg3);
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    {
+        /* freearg char ***OUTPUT */
+        profile_free_list(*arg3);
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_iterator_create(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    int arg3 ;
+    iter_t *arg4 = (iter_t *) 0 ;
+    errcode_t result;
+    iter_t tmp4 ;
+    
+    {
+        /*generic swigtype hack*/ arg4 = &tmp4;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"ooi:profile_iterator_create p nullterm flags ",0,0,&arg3) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)iter_create(arg1,(char const **)arg2,arg3,arg4);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    /*generic swigtype hack*/ Tcl_SetObjResult(interp,SWIG_NewInstanceObj((void *) *arg4, SWIGTYPE_iter_t,0));
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_iterator_free(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    iter_t arg1 = (iter_t) 0 ;
+    errcode_t result;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"o:profile_iterator_free i ",0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_iter_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)iter_free(arg1);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    return TCL_OK;
+    fail:
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_iterator(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    iter_t arg1 = (iter_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    char **arg3 = (char **) 0 ;
+    errcode_t result;
+    char *tmp2 ;
+    char *tmp3 ;
+    
+    {
+        /* in char **OUTPUT */
+        tmp2 = NULL;
+        arg2 = &tmp2;
+    }
+    {
+        /* in char **OUTPUT */
+        tmp3 = NULL;
+        arg3 = &tmp3;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"o:profile_iterator iter_t ",0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_iter_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_iterator(arg1,arg2,arg3);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* argout char **OUTPUT */
+        /*    Tcl_SetResult(interp, *arg2, TCL_DYNAMIC); */
+        char *s = (arg2 && *arg2) ? *arg2 : "";
+        Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
+        Tcl_NewStringObj(s, strlen(s)));
+    }
+    {
+        /* argout char **OUTPUT */
+        /*    Tcl_SetResult(interp, *arg3, TCL_DYNAMIC); */
+        char *s = (arg3 && *arg3) ? *arg3 : "";
+        Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
+        Tcl_NewStringObj(s, strlen(s)));
+    }
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg2); */
+    }
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg3); */
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg2); */
+    }
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg3); */
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_update_relation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    char *arg3 ;
+    char *arg4 = (char *) NULL ;
+    errcode_t result;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"oos|s:profile_update_relation p nullterm oldval ?newval? ",0,0,&arg3,&arg4) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)profile_update_relation(arg1,(char const **)arg2,(char const *)arg3,(char const *)arg4);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_clear_relation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    errcode_t result;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"oo:profile_clear_relation p nullterm ",0,0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)profile_clear_relation(arg1,(char const **)arg2);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_rename_section(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    char *arg3 = (char *) NULL ;
+    errcode_t result;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"oo|s:profile_rename_section p nullterm ?new_name? ",0,0,&arg3) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)profile_rename_section(arg1,(char const **)arg2,(char const *)arg3);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_add_relation(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    char *arg3 = (char *) NULL ;
+    errcode_t result;
+    
+    if (SWIG_GetArgs(interp, objc, objv,"oo|s:profile_add_relation p nullterm ?new_val? ",0,0,&arg3) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    {
+        /* in char **nullterm */
+        int n;
+        if (Tcl_SplitList(interp, Tcl_GetStringFromObj(objv[2],NULL), &n, &arg2) == TCL_ERROR) SWIG_fail;
+    }
+    result = (errcode_t)profile_add_relation(arg1,(char const **)arg2,(char const *)arg3);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* freearg char **nullterm */
+        if (arg2) {
+            Tcl_Free((char *)arg2); arg2 = (char **) NULL; 
+        }
+    }
+    return TCL_ERROR;
+}
+
+
+static int
+_wrap_profile_flush_to_buffer(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    profile_t arg1 = (profile_t) 0 ;
+    char **arg2 = (char **) 0 ;
+    errcode_t result;
+    char *tmp2 ;
+    
+    {
+        /* in char **OUTPUT */
+        tmp2 = NULL;
+        arg2 = &tmp2;
+    }
+    if (SWIG_GetArgs(interp, objc, objv,"o:profile_flush_to_buffer p ",0) == TCL_ERROR) SWIG_fail;
+    if ((SWIG_ConvertPtr(objv[1], (void **) &arg1, SWIGTYPE_profile_t,SWIG_POINTER_EXCEPTION | 0) != TCL_OK)) SWIG_fail;
+    result = (errcode_t)profile_flush_to_buffer(arg1,arg2);
+    
+    {
+        /* out errcode_t result */
+        if (result) {
+            /* There could be a memory leak here in the SWIG-Tcl layer,
+            	   I'm not sure.  Not going to worry about it though.  */
+            Tcl_SetResult(interp, (char *) error_message(result), TCL_STATIC);
+            SWIG_fail;
+        }
+    }
+    {
+        /* argout char **OUTPUT */
+        /*    Tcl_SetResult(interp, *arg2, TCL_DYNAMIC); */
+        char *s = (arg2 && *arg2) ? *arg2 : "";
+        Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
+        Tcl_NewStringObj(s, strlen(s)));
+    }
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg2); */
+    }
+    return TCL_OK;
+    fail:
+    {
+        /* There may be a memory leak here.  Investigate later, if anyone
+               cares.  */
+        /*    profile_release_string(*arg2); */
+    }
+    return TCL_ERROR;
+}
+
+
+
+static swig_command_info swig_commands[] = {
+    { SWIG_prefix "profile_init_path", (swig_wrapper_func) _wrap_profile_init_path, NULL},
+    { SWIG_prefix "profile_init", (swig_wrapper_func) _wrap_profile_init, NULL},
+    { SWIG_prefix "profile_flush", (swig_wrapper_func) _wrap_profile_flush, NULL},
+    { SWIG_prefix "profile_flush_to_file", (swig_wrapper_func) _wrap_profile_flush_to_file, NULL},
+    { SWIG_prefix "profile_abandon", (swig_wrapper_func) _wrap_profile_abandon, NULL},
+    { SWIG_prefix "profile_release", (swig_wrapper_func) _wrap_profile_release, NULL},
+    { SWIG_prefix "profile_get_values", (swig_wrapper_func) _wrap_profile_get_values, NULL},
+    { SWIG_prefix "profile_get_string", (swig_wrapper_func) _wrap_profile_get_string, NULL},
+    { SWIG_prefix "profile_get_integer", (swig_wrapper_func) _wrap_profile_get_integer, NULL},
+    { SWIG_prefix "profile_get_boolean", (swig_wrapper_func) _wrap_profile_get_boolean, NULL},
+    { SWIG_prefix "profile_get_relation_names", (swig_wrapper_func) _wrap_profile_get_relation_names, NULL},
+    { SWIG_prefix "profile_get_subsection_names", (swig_wrapper_func) _wrap_profile_get_subsection_names, NULL},
+    { SWIG_prefix "profile_iterator_create", (swig_wrapper_func) _wrap_profile_iterator_create, NULL},
+    { SWIG_prefix "profile_iterator_free", (swig_wrapper_func) _wrap_profile_iterator_free, NULL},
+    { SWIG_prefix "profile_iterator", (swig_wrapper_func) _wrap_profile_iterator, NULL},
+    { SWIG_prefix "profile_update_relation", (swig_wrapper_func) _wrap_profile_update_relation, NULL},
+    { SWIG_prefix "profile_clear_relation", (swig_wrapper_func) _wrap_profile_clear_relation, NULL},
+    { SWIG_prefix "profile_rename_section", (swig_wrapper_func) _wrap_profile_rename_section, NULL},
+    { SWIG_prefix "profile_add_relation", (swig_wrapper_func) _wrap_profile_add_relation, NULL},
+    { SWIG_prefix "profile_flush_to_buffer", (swig_wrapper_func) _wrap_profile_flush_to_buffer, NULL},
+    {0, 0, 0}
+};
+
+static swig_var_info swig_variables[] = {
+    {0,0,0,0}
+};
+
+static swig_const_info swig_constants[] = {
+    {0,0,0,0,0,0}
+};
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static swig_type_info _swigt__p_p_char[] = {{"_p_p_char", 0, "char **", 0},{"_p_p_char"},{0}};
+static swig_type_info _swigt__p_p_p_char[] = {{"_p_p_p_char", 0, "char ***", 0},{"_p_p_p_char"},{0}};
+static swig_type_info _swigt__p_iter_t[] = {{"_p_iter_t", 0, "iter_t *", 0},{"_p_iter_t"},{0}};
+static swig_type_info _swigt__iter_t[] = {{"_iter_t", 0, "iter_t", 0},{"_iter_t"},{0}};
+static swig_type_info _swigt__p_profile_t[] = {{"_p_profile_t", 0, "profile_t *", 0},{"_p_profile_t"},{0}};
+static swig_type_info _swigt__profile_t[] = {{"_profile_t", 0, "profile_t", 0},{"_profile_t"},{0}};
+static swig_type_info _swigt__p_int[] = {{"_p_int", 0, "int *", 0},{"_p_int"},{0}};
+
+static swig_type_info *swig_types_initial[] = {
+_swigt__p_p_char, 
+_swigt__p_p_p_char, 
+_swigt__p_iter_t, 
+_swigt__iter_t, 
+_swigt__p_profile_t, 
+_swigt__profile_t, 
+_swigt__p_int, 
+0
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+SWIGEXPORT(int) SWIG_init(Tcl_Interp *interp) {
+    int i;
+    static int _init = 0;
+    if (interp == 0) return TCL_ERROR;
+#ifdef USE_TCL_STUBS
+    if (Tcl_InitStubs(interp, (char*)"8.1", 0) == NULL) {
+        return TCL_ERROR;
+    }
+#endif
+    
+    Tcl_PkgProvide(interp, (char*)SWIG_name, (char*)SWIG_version);
+    
+#ifdef SWIG_namespace
+    Tcl_Eval(interp, "namespace eval " SWIG_namespace " { }");
+#endif
+    if (!_init) {
+        for (i = 0; swig_types_initial[i]; i++) {
+            swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);
+        }
+        _init = 1;
+    }
+    for (i = 0; swig_commands[i].name; i++) {
+        Tcl_CreateObjCommand(interp, (char *) swig_commands[i].name, (swig_wrapper_func) swig_commands[i].wrapper, swig_commands[i].clientdata, NULL);
+    }
+    for (i = 0; swig_variables[i].name; i++) {
+        Tcl_SetVar(interp, (char *) swig_variables[i].name, (char *) "", TCL_GLOBAL_ONLY);
+        Tcl_TraceVar(interp, (char *) swig_variables[i].name, TCL_TRACE_READS | TCL_GLOBAL_ONLY, (Tcl_VarTraceProc *) swig_variables[i].get, (ClientData) swig_variables[i].addr);
+        Tcl_TraceVar(interp, (char *) swig_variables[i].name, TCL_TRACE_WRITES | TCL_GLOBAL_ONLY, (Tcl_VarTraceProc *) swig_variables[i].set, (ClientData) swig_variables[i].addr);
+    }
+    SWIG_InstallConstants(interp, swig_constants);
+    
+    return TCL_OK;
+}
+SWIGEXPORT(int) Profile_SafeInit(Tcl_Interp *interp) {
+    return SWIG_init(interp);
+}
+
diff --git a/krb5-1-6/src/util/profile/prtest.in b/krb5-1-6/src/util/profile/prtest.in
new file mode 100644
index 000000000..ef3efb308
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prtest.in
@@ -0,0 +1,36 @@
+#!/bin/sh
+SRCDIR=@srcdir@
+SCRIPT=$SRCDIR/prtest.script
+REPORT=prtest.report
+TESTPROG=./test_profile
+
+rm -f $REPORT
+
+if test -f $SCRIPT ; then 
+	: 
+else
+	echo "$SCRIPT not found!"
+	exit 1
+fi
+
+grep -v ^\# < $SCRIPT | while read filespec cmd args
+do
+	case $filespec in
+	krb5)
+		file=$SRCDIR/krb5.conf
+		;;
+	test)
+		file=$SRCDIR/test.ini
+		;;
+	*)
+		echo "Unknown file specifer $file!"
+		exit 1
+		;;
+	esac
+	if test $cmd = parse ; then
+	    echo \# test_parse $filespec   >> $REPORT 2>&1
+	    $TESTPARSE $file >> $REPORT    >> $REPORT 2>&1
+	fi
+	echo \# $filespec $cmd $args  >> $REPORT 2>&1
+	$TESTPROG $file $cmd $args    >> $REPORT 2>&1 
+done 
diff --git a/krb5-1-6/src/util/profile/prtest.script b/krb5-1-6/src/util/profile/prtest.script
new file mode 100644
index 000000000..5d5a14422
--- /dev/null
+++ b/krb5-1-6/src/util/profile/prtest.script
@@ -0,0 +1,11 @@
+krb5 query realms ATHENA.MIT.EDU kdc
+krb5 query1 realms ATHENA.MIT.EDU kdc
+krb5 query libdefaults ticket_lifetime
+krb5 query1 libdefaults ticket_lifetime
+krb5 query libdefaults not_present
+krb5 query1 libdefaults not_present
+krb5 list_sections libdefaults
+krb5 list_sections realms
+krb5 list_relations libdefaults
+krb5 list_relations realms
+krb5 list_relations realms ATHENA.MIT.EDU
diff --git a/krb5-1-6/src/util/profile/test.ini b/krb5-1-6/src/util/profile/test.ini
new file mode 100644
index 000000000..c1c8830aa
--- /dev/null
+++ b/krb5-1-6/src/util/profile/test.ini
@@ -0,0 +1,47 @@
+this is a comment.  Everything up to the first square brace is ignored.
+
+[test section 2]
+	test_child = "foo\nbar"
+	child_section2 = "one"
+	child_section2 = {
+		child = slick
+		child = harry
+		child = "john\tb "
+	}
+	child_section2 = foo
+
+[realms]
+ATHENA.MIT.EDU = {
+	server = KERBEROS.MIT.EDU:88
+	server = KERBEROS1.MIT.EDU:750
+	server = KERBEROS2.MIT.EDU:750
+	admin = KERBEROS.MIT.EDU
+	etype = DES-MD5
+}
+	
+
+
+[test section 1]
+    foo = "bar "
+
+[test section 2]
+	quux = "bar"
+	frep = bar
+	kappa = alpha
+	beta = epsilon
+
+[test section 1]
+    bar = foo
+	foo = bar2
+    quux = zap
+	foo = bar3
+	child_section = {
+		child = slick
+		child = harry
+		child = john
+	}
+	child_section = foo
+
+
+
+
diff --git a/krb5-1-6/src/util/profile/test_parse.c b/krb5-1-6/src/util/profile/test_parse.c
new file mode 100644
index 000000000..961149c80
--- /dev/null
+++ b/krb5-1-6/src/util/profile/test_parse.c
@@ -0,0 +1,54 @@
+#include "prof_int.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+#include <ctype.h>
+
+void dump_profile (struct profile_node *root, int level);
+
+int main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	struct profile_node *root;
+	unsigned long retval;
+	FILE *f;
+
+	initialize_prof_error_table();
+	if (argc != 2) {
+		fprintf(stderr, "%s: Usage <filename>\n", argv[0]);
+		exit(1);
+	}
+
+	f = fopen(argv[1], "r");
+	if (!f) {
+		perror(argv[1]);
+		exit(1);
+	}
+
+	retval = profile_parse_file(f, &root);
+	if (retval) {
+		printf("profile_parse_file error %s\n", 
+		       error_message((errcode_t) retval));
+		exit(1);
+	}
+	fclose(f);
+	
+	printf("\n\nDebugging dump.\n");
+	profile_write_tree_file(root, stdout);
+	
+	retval = profile_verify_node(root);
+	if (retval) {
+		printf("profile_verify_node reported an error: %s\n",
+		       error_message((errcode_t) retval));
+		exit(1);
+	}
+
+	profile_free_node(root);
+
+	return 0;
+}
diff --git a/krb5-1-6/src/util/profile/test_profile.c b/krb5-1-6/src/util/profile/test_profile.c
new file mode 100644
index 000000000..5cdbf7689
--- /dev/null
+++ b/krb5-1-6/src/util/profile/test_profile.c
@@ -0,0 +1,169 @@
+/*
+ * test_profile.c --- testing program for the profile routine
+ */
+
+#include "prof_int.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include "argv_parse.h"
+#include "com_err.h"
+
+const char *program_name = "test_profile";
+
+#define PRINT_VALUE	1
+#define PRINT_VALUES	2
+
+static void do_batchmode(profile)
+	profile_t	profile;
+{
+	errcode_t	retval;
+	int		argc, ret;
+	char		**argv, **values, **cpp;
+	char		buf[256];
+	const char	**names, *value;
+	char		*cmd;
+	int		print_status;
+
+	while (!feof(stdin)) {
+		if (fgets(buf, sizeof(buf), stdin) == NULL)
+			break;
+		printf(">%s", buf);
+		ret = argv_parse(buf, &argc, &argv);
+		if (ret != 0) {
+			printf("Argv_parse returned %d!\n", ret);
+			continue;
+		}
+		cmd = *(argv);
+		names = (const char **) argv + 1;
+		print_status = 0;
+		retval = 0;
+		if (cmd == 0) {
+			argv_free(argv);
+			continue;
+		}
+		if (!strcmp(cmd, "query")) {
+			retval = profile_get_values(profile, names, &values);
+			print_status = PRINT_VALUES;
+		} else if (!strcmp(cmd, "query1")) {
+			retval = profile_get_value(profile, names, &value);
+			print_status = PRINT_VALUE;
+		} else if (!strcmp(cmd, "list_sections")) {
+			retval = profile_get_subsection_names(profile, names, 
+							      &values);
+			print_status = PRINT_VALUES;
+		} else if (!strcmp(cmd, "list_relations")) {
+			retval = profile_get_relation_names(profile, names, 
+							    &values);
+			print_status = PRINT_VALUES;
+		} else if (!strcmp(cmd, "dump")) {
+			retval = profile_write_tree_file
+				(profile->first_file->data->root, stdout);
+		} else if (!strcmp(cmd, "clear")) {
+			retval = profile_clear_relation(profile, names);
+		} else if (!strcmp(cmd, "update")) {
+			retval = profile_update_relation(profile, names+2,
+							 *names, *(names+1));
+		} else if (!strcmp(cmd, "verify")) {
+			retval = profile_verify_node
+				(profile->first_file->data->root);
+		} else if (!strcmp(cmd, "rename_section")) {
+			retval = profile_rename_section(profile, names+1,
+							*names);
+		} else if (!strcmp(cmd, "add")) {
+			value = *names;
+			if (strcmp(value, "NULL") == 0)
+				value = NULL;
+			retval = profile_add_relation(profile, names+1,
+						      value);
+		} else if (!strcmp(cmd, "flush")) {
+			retval = profile_flush(profile);
+		} else {
+			printf("Invalid command.\n");
+		}
+		if (retval) {
+			com_err(cmd, retval, "");
+			print_status = 0;
+		}
+		switch (print_status) {
+		case PRINT_VALUE:
+			printf("%s\n", value);
+			break;
+		case PRINT_VALUES:
+			for (cpp = values; *cpp; cpp++)
+				printf("%s\n", *cpp);
+			profile_free_list(values);
+			break;
+		}
+		printf("\n");
+		argv_free(argv);
+	}
+	profile_release(profile);
+	exit(0);
+	
+}
+
+
+int main(argc, argv)
+    int		argc;
+    char	**argv;
+{
+    profile_t	profile;
+    long	retval;
+    char	**values, **cpp;
+    const char	*value;
+    const char	**names;
+    char	*cmd;
+    int		print_value = 0;
+    
+    if (argc < 2) {
+	    fprintf(stderr, "Usage: %s filename [cmd argset]\n", program_name);
+	    exit(1);
+    }
+
+    initialize_prof_error_table();
+    
+    retval = profile_init_path(argv[1], &profile);
+    if (retval) {
+	com_err(program_name, retval, "while initializing profile");
+	exit(1);
+    }
+    cmd = *(argv+2);
+    names = (const char **) argv+3;
+    if (!cmd || !strcmp(cmd, "batch"))
+	    do_batchmode(profile);
+    if (!strcmp(cmd, "query")) {
+	    retval = profile_get_values(profile, names, &values);
+    } else if (!strcmp(cmd, "query1")) {
+	    retval = profile_get_value(profile, names, &value);
+	    print_value++;
+    } else if (!strcmp(cmd, "list_sections")) {
+	    retval = profile_get_subsection_names(profile, names, &values);
+    } else if (!strcmp(cmd, "list_relations")) {
+	    retval = profile_get_relation_names(profile, names, &values);
+    } else {
+	    fprintf(stderr, "Invalid command.\n");
+	    exit(1);
+    }
+    if (retval) {
+	    com_err(argv[0], retval, "while getting values");
+	    profile_release(profile);
+	    exit(1);
+    }
+    if (print_value) {
+	    printf("%s\n", value);
+    } else {
+	    for (cpp = values; *cpp; cpp++)
+		    printf("%s\n", *cpp);
+	    profile_free_list(values);
+    }
+    profile_release(profile);
+
+    return 0;
+}
+    
+    
diff --git a/krb5-1-6/src/util/reconf b/krb5-1-6/src/util/reconf
new file mode 100755
index 000000000..aec534f70
--- /dev/null
+++ b/krb5-1-6/src/util/reconf
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+force=
+autoreconfprog=autoreconf
+localdir=.
+autoreconfoptions=""
+verbose=false
+localdirarg=
+
+autoreconf="/bin/sh $autoreconfprog"
+
+# This should prevent autoreconf -- at least, the Debian version -- from
+# running aclocal in directories with configure.in but not aclocal.m4, so
+# that we can find the top-level one via the --include option.
+ACLOCAL=true ; export ACLOCAL
+
+usage="Usage: $0 [--force] [--verbose] [--help]"
+for option
+do
+  case "$option" in
+  --force | -f)
+    echo "Remaking all configuration files"
+    force=--force ;;
+  -help | --help | --hel | --he | --h)
+    echo "$usage"; exit 0 ;;
+  -v | --verbose)
+    verbose=true ;;
+  *) echo "$usage"; exit 1 ;;
+  esac
+done
+
+# Currently (2003-04-24) we need 2.52 or later.
+patb="2.(1[0-9][0-9])|(5[2-9])|([6-9][0-9])"
+
+# sedcmd1 recognizes the older 2.12 version, and sedcmd2 the newer 2.49
+sedcmd1="s,.*version \(.*\)$,\1,"
+sedcmd2="s,.*) \(.*\)$,\1,;1q"
+
+if autoreconf --version | sed -e "$sedcmd1" -e "$sedcmd2" | egrep "$patb" >/dev/null && \
+    autoconf --version  | sed -e "$sedcmd1" -e "$sedcmd2"  | egrep "$patb" >/dev/null && \
+    autoheader --version | sed -e "$sedcmd1" -e "$sedcmd2" | egrep "$patb" >/dev/null; then
+    autoreconf=autoreconf
+    autoreconfoptions=
+    autoconfversion=`autoconf --version | sed -e "$sedcmd1" -e "$sedcmd2"`
+	echo "Using autoconf version $autoconfversion found in your path..."
+	localdir=`pwd`
+
+	# Determine if we need to patch autoreconf for 2.53
+	case "$autoconfversion" in
+	  2.52)
+	       echo "WARNING: autoconf 2.52 is known to generate buggy configure scripts!"
+	       ;;
+	  2.53)
+	       echo "Patching autoreconf"
+	       # Walk the path to find autoreconf
+	       autoreconfpath=
+	       for i in `echo $PATH | sed -e 's/:/ /g'` ; do
+		   if test -r $i/autoreconf; then
+		       autoreconfpath=$i/autoreconf
+		       break
+		   fi
+	       done
+	       if test "x$autoreconfpath" = "x" ; then 
+		   echo "Could not find autoreconf executable!!!"
+		   exit
+	       fi
+	       
+	       echo "About to patch $autoreconfpath to ..."
+	       TMPCMD=/tmp/autoreconf$$
+	       sed -e 's/push @ARGV, $_;/push @ARGV, catfile ($directory, $_);/' $autoreconfpath > $TMPCMD
+	       autoreconf="/bin/sh $TMPCMD"
+	       trap "rm $TMPCMD" 0
+	       ;;
+	  *)
+	       ;;
+	esac
+
+	# Determine the proper argument to autoreconf 
+	case "$autoconfversion" in
+	  2.1*)
+	       localdirarg="-l"
+	       ;;
+	  2.5[23])
+	       localdirarg="-l"
+	       ;;
+	    *)
+	       localdirarg="-I"
+	       ;;
+	esac
+else
+	echo "Couldn't find autoconf 2.52 or higher in your path."
+	echo " "
+	echo "Please install or add to your path and re-run ./util/reconf"
+	exit 1
+fi
+
+if $verbose ; then 
+	echo $autoreconf $autoreconfoptions $localdirarg $localdir --verbose $force
+fi
+$autoreconf $autoreconfoptions  $localdirarg $localdir --verbose $force || exit 1
+if test $? = 0 ; then
+    if test ! -d include/autoconf.stmp ; then
+	cp /dev/null include/autoconf.stmp
+    fi
+fi
+find . -name autom4te.cache -print | xargs rm -rf
diff --git a/krb5-1-6/src/util/send-pr/COPYING b/krb5-1-6/src/util/send-pr/COPYING
new file mode 100644
index 000000000..515b6d333
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/COPYING
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+he GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/krb5-1-6/src/util/send-pr/INSTALL b/krb5-1-6/src/util/send-pr/INSTALL
new file mode 100644
index 000000000..711c63d8a
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/INSTALL
@@ -0,0 +1,83 @@
+	Installation procedures for `send-pr'
+
+If you receive `send-pr' as part of a larger software distribution, it
+will be automatically installed when the full distribution is
+installed.  The `send-pr' directory, however, is easily installed by
+itself by following these steps:
+
+1.  Unpack the distribution into a directory which we will refer to as
+    SRCDIR.  
+
+2.  Edit the `Makefile' to reflect local conventions.
+
+    Specifically, you should edit the variable "prefix" to alter
+    the installation location.  The default is '/usr/local'.  All
+    files are installed under "prefix" (see below).
+
+3.  Run 
+	make all install [ info ] install-info [ clean ]
+
+    from the "build directory".  The targets mean the following:
+
+	 all	Builds `send-pr' and `install-sid'
+
+     install	Installs the following:
+
+			    send-pr	into PREFIX/bin 
+			install-sid	into PREFIX/bin
+			  send-pr.1	into PREFIX/man/man1
+			 categories	as PREFIX/lib/gnats/SITE
+		      send-pr-el.in	as PREFIX/lib/emacs/lisp/send-pr.el
+
+        info	(optional) Builds "send-pr.info" from "send-pr.texi"
+		(send-pr.info is included with this distribution)
+
+install-info	Installs "send-pr.info" into PREFIX/info
+
+       clean 	(optional) Removes all intermediary build files that can
+		           be rebuilt from source code
+
+4.  Run 
+
+	install-sid SID
+
+    where SID is the submitter identification code you received with
+    `send-pr'.  If you've downloaded `send-pr' from the Net, use "net"
+    for this value.
+
+
+5.  Any users who wish to use the Emacs version of `send-pr' must place
+    the following line in their ".emacs" files:
+
+	(autoload 'send-pr "send-pr" "Submit a Problem Report." t)
+
+
+6.  Create a mail alias for the support site you received `send-pr'
+    from, and for every site with which you wish to use `send-pr' to
+    communicate with, each with a suffix of `-gnats'.  The support
+    site(s) will provide the correct addresses toward which these
+    aliases should point.  For instance, edit your mail aliases file
+    to contain something like:
+
+	# support sites; for use with send-pr
+	cygnus-gnats:     bugs@cygnus.com            # Cygnus Support
+	bumblebee-gnats:  bumblebugs@bumblebee.com   # Bumblebee BASIC, Inc.
+	mycompany-gnats:  bugs@my.company.com      (if you use GNATS locally)
+
+    `send-pr' automatically searches for these aliases when you type
+
+	send-pr cygnus
+	send-pr bumblebee
+	send-pr SITE...
+
+    `send-pr' also uses SITE to determine the categories of bugs the site
+    in question accepts by looking in PREFIX/lib/gnats/SITE
+
+
+7.  That's it!  See "send-pr.info", "send-pr.texi", and/or "send-pr.1" for
+    information on using `send-pr'.
+
+
+Copyright (c) 1993, Free Software Foundation, Inc.  
+See the file COPYING for copyright information concerning this
+distribution and all its components.
diff --git a/krb5-1-6/src/util/send-pr/MANIFEST b/krb5-1-6/src/util/send-pr/MANIFEST
new file mode 100644
index 000000000..35375a6fd
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/MANIFEST
@@ -0,0 +1,20 @@
+	MANIFEST for send-pr
+
+The following files should have accompanied this distribution.
+
+	COPYING		copyright information
+      ChangeLog		sourcecode change log
+        INSTALL		installation procedure
+    Makefile.in		Makefile template used by `configure'
+       MANIFEST		list of accompanying files
+         README		introductory information
+        config/		any specialized configuration files
+   configure.in		input file for `configure'
+     categories		list of valid categories
+ install-sid.sh		script which installs Submitter-Id
+  send-pr-el.in		elisp version of `send-pr' for Emacs
+    send-pr.man		`send-pr' man file, installed as send-pr.1
+   send-pr.info		`send-pr' Info file
+     send-pr.sh		`send-pr' shell script - command line version
+   send-pr.texi		`send-pr' Texinfo documentation
+  send-pr.input 	`send-pr' Texinfo documentation input file
diff --git a/krb5-1-6/src/util/send-pr/Makefile.in b/krb5-1-6/src/util/send-pr/Makefile.in
new file mode 100644
index 000000000..6d586c69e
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/Makefile.in
@@ -0,0 +1,48 @@
+thisconfigdir=./../..
+myfulldir=util/send-pr
+mydir=util/send-pr
+BUILDTOP=$(REL)..$(S)..
+#
+# Makefile for building a standalone send-pr.
+#
+RELEASE=@KRB5_VERSION@
+SUBMITTER=net
+sendprname = krb5-send-pr
+EMACS=emacs
+
+infodir = $(prefix)/info
+lispdir = $(prefix)/lib/emacs/site-lisp
+mandir  = $(KRB5MANROOT)
+man1dir = $(mandir)/man1
+datadir = @datadir@
+
+all:: send-pr  install-sid
+
+send-pr: send-pr.sh
+	sed -e 's,@DATADIR@,$(datadir),g' \
+	    -e 's,@SUBMITTER@,$(SUBMITTER),g' \
+	    -e 's/@DEFAULT_RELEASE@/$(RELEASE)/g' $(srcdir)/send-pr.sh > send-pr
+
+
+
+install-sid: install-sid.sh
+	sed -e 's,@ADMIN_BINDIR@,$(ADMIN_BINDIR),g' $(srcdir)/install-sid.sh > install-sid
+
+install:: all
+	if [ -d $(DESTDIR)$(prefix) ]; then true ; else mkdir $(DESTDIR)$(prefix) ; fi
+	if [ -d $(DESTDIR)$(ADMIN_BINDIR) ]; then true ; else mkdir $(DESTDIR)$(ADMIN_BINDIR) ; fi
+	cp send-pr $(DESTDIR)$(ADMIN_BINDIR)/$(sendprname)
+	chmod 755 $(DESTDIR)$(ADMIN_BINDIR)/$(sendprname)
+	if [ -d $(DESTDIR)$(datadir) ] ; then true ; else mkdir $(DESTDIR)$(datadir) ; fi
+	if [ -d $(DESTDIR)$(datadir)/gnats ] ; then true ; else mkdir $(DESTDIR)$(datadir)/gnats ; fi
+	cp $(srcdir)/categories $(DESTDIR)$(datadir)/gnats/mit
+	chmod 644 $(DESTDIR)$(datadir)/gnats/mit
+	-parent=`echo $(DESTDIR)$(man1dir)|sed -e 's@/[^/]*$$@@'`; \
+	if [ -d $$parent ] ; then true ; else mkdir $$parent ; fi
+	if [ -d $(DESTDIR)$(man1dir) ] ; then true ; else mkdir $(DESTDIR)$(man1dir) ; fi
+	sed -e 's/send-pr/$(sendprname)/g' $(srcdir)/send-pr.1 > $(DESTDIR)$(man1dir)/$(sendprname).1
+	chmod 644 $(DESTDIR)$(man1dir)/$(sendprname).1
+
+clean::
+	rm -f install-sid send-pr send-pr.el*
+
diff --git a/krb5-1-6/src/util/send-pr/README b/krb5-1-6/src/util/send-pr/README
new file mode 100644
index 000000000..b47917955
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/README
@@ -0,0 +1,43 @@
+	send-pr - sends bug reports to a central support site
+
+`send-pr' uses electronic mail to submit support questions and
+software bugs to a central site.  No piece of software is perfect, and
+software organizations understand this `send-pr' is designed to allow
+users who have problems to submit reports of these problems to sites
+responsible for supporting the software in question, in a defined form
+which can be read by an electronically managed database.
+
+`send-pr' is part of a suite of programs known collectively as GNATS,
+an acronym for Problem Report Management System.  GNATS consists of
+several programs which, used in concert, formulate and partially
+administer a database of Problem Reports, or PRs, at a central support
+site.  A PR goes through several states in its lifetime; GNATS tracks
+the PR and all information associated with it through each state and
+finally acts as an archive for PRs which have been resolved.
+
+The same engine can be used to submit bugs to any number of support
+sites by setting up aliases for each of them; `send-pr' error-checks
+each PR as it is sent to be sure that the category specified matches a
+category supported by the site in question.
+
+`send-pr' invokes an editor on a problem report template (after trying
+to fill in some fields with reasonable default values).  When you exit
+the editor, `send-pr' sends the completed form to the support site.
+At the support site, the PR is assigned a unique number and is stored
+in the GNATS database according to its category and customer-id.  GNATS
+automatically replies with an acknowledgement, citing the category and
+the PR number.
+
+See the Texinfo file `send-pr.texi' or the Info file `send-pr.info'
+for detailed installation and usage information.
+
+See the file MANIFEST for a list of the files which should have
+accompanied this distribution.
+
+See `send-pr.texi', `send-pr.info', or the file INSTALL for the
+installation procedure for `send-pr'.
+
+
+Copyright (c) 1993, Free Software Foundation, Inc.  
+See the file COPYING for copyright information concerning this
+distribution and all its components.
diff --git a/krb5-1-6/src/util/send-pr/categories b/krb5-1-6/src/util/send-pr/categories
new file mode 100644
index 000000000..7700dd2bb
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/categories
@@ -0,0 +1,11 @@
+krb5-libs
+krb5-admin
+krb5-kdc
+krb5-clients
+krb5-appl
+krb5-doc
+krb5-misc
+krb5-build
+pty
+telnet
+test
diff --git a/krb5-1-6/src/util/send-pr/install-sid.sh b/krb5-1-6/src/util/send-pr/install-sid.sh
new file mode 100644
index 000000000..15681cf74
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/install-sid.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+# Drop in the SUBMITTER id into a site's installed send-pr script.
+# Copyright (C) 1993 Free Software Foundation, Inc.
+# Contributed by Brendan Kehoe (brendan@cygnus.com), based on a
+# version written by Heinz G. Seidl (hgs@ide.com).
+#
+# This file is part of GNU GNATS.
+#
+# GNU GNATS is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU GNATS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU GNATS; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+COMMAND=`echo $0 | sed -e 's,.*/,,g'`
+USAGE="Usage: $COMMAND [--install-dir=prefix] [--help] [--version] submitter-id"
+
+VERSION=3.99
+
+BINDIR=@BINDIR@
+
+SUBMITTER=
+TEMP=/tmp/sp$$
+
+if [ $# -eq 0 ]; then
+  echo "$USAGE"
+  exit 1
+fi
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -install-dir=*|--install-dir=*|--install-di=*|--install-d=*|--install-=*|--install=*|--instal=*|--insta=*|--inst=*|--ins=*|--in=*|--i=*)
+    I=`echo "$1" | sed 's/-*i[a-z\-]*=//'`
+    BINDIR=$I/bin ;;
+    --version) echo $COMMAND version $VERSION ; exit 1 ;;
+    -*) echo "$USAGE" ; exit 1 ;;
+    *) SUBMITTER=$1 ;;
+  esac
+  shift
+done
+
+path=`echo $0 | sed -e "s;${COMMAND};;"`
+
+[ -z "$path" ] && path=.
+
+if [ -f $BINDIR/send-pr ]; then
+  SPPATHLIST=$BINDIR/send-pr
+else
+      if [ -f $path/send-pr ]; then
+	 SPPATHLIST=$path/send-pr
+      else
+	 echo "$COMMAND: cannot find \`$BINDIR/send-pr' or \`$path/send-pr'" >&2
+	 exit 1
+      fi
+fi
+
+trap 'rm -f $TEMP ; exit 0' 0
+trap 'echo "$COM: Aborting ..."; rm -f $TEMP ; exit 1' 1 2 3 13 15
+
+for SPPATH in $SPPATHLIST; do
+   sed -e "s/^SUBMITTER=.*/SUBMITTER=${SUBMITTER}/" $SPPATH > $TEMP
+
+   if grep $SUBMITTER $TEMP > /dev/null; then
+      cp $SPPATH $SPPATH.orig &&
+      rm -f $SPPATH &&
+      cp $TEMP $SPPATH &&
+      chmod a+rx $SPPATH &&
+      rm -f $TEMP $SPPATH.orig ||
+      { echo "$COMMAND: unable to replace send-pr" >&2 ; exit 1; }  
+   else
+      echo "$COMMAND: something went wrong when sed-ing the submitter into send-pr" >&2
+      exit 1
+   fi
+done
+
+echo "$COMMAND: \`$SUBMITTER' is now the default submitter ID for send-pr"
+
+exit 0
diff --git a/krb5-1-6/src/util/send-pr/send-pr.1 b/krb5-1-6/src/util/send-pr/send-pr.1
new file mode 100644
index 000000000..bc241d7f2
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/send-pr.1
@@ -0,0 +1,289 @@
+.\" -*- nroff -*-
+.\" ---------------------------------------------------------------------------
+.\"    man page for send-pr (by Heinz G. Seidl, hgs@cygnus.com)
+.\"    updated Feb 1993 for GNATS 3.00 by Jeffrey Osier, jeffrey@cygnus.com
+.\"
+.\"    This file is part of the Problem Report Management System (GNATS)
+.\"    Copyright 1992 Cygnus Support
+.\"
+.\"    This program is free software; you can redistribute it and/or
+.\"    modify it under the terms of the GNU General Public
+.\"    License as published by the Free Software Foundation; either
+.\"    version 2 of the License, or (at your option) any later version.
+.\"
+.\"    This program is distributed in the hope that it will be useful,
+.\"    but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\"    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\"    General Public License for more details.
+.\"
+.\"    You should have received a copy of the GNU Library General Public
+.\"    License along with this program; if not, write to the Free
+.\"    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
+.\"
+.\" ---------------------------------------------------------------------------
+.nh
+.TH SEND-PR 1 3.99 "February 1993"
+.SH NAME
+send-pr \- send problem report (PR) to a central support site
+.SH SYNOPSIS
+.B send-pr
+[
+.I site
+]
+[
+.B \-f
+.I problem-report
+]
+[
+.B \-t
+.I mail-address
+]
+.br
+.in +0.8i
+[
+.B \-P
+]
+[
+.B \-L
+]
+[
+.B \-s
+.I severity
+]
+[
+.B \-c
+.I address
+]
+.br
+[
+.B \-\-request-id
+]
+[
+.B \-V
+]
+.SH DESCRIPTION
+.B send-pr
+is a tool used to submit 
+.I problem reports 
+.\" SITE ADMINISTRATORS - change this if you use a local default
+(PRs) to a central support site.  In most cases the correct 
+.I site
+will be the default.  This argument indicates the support site which
+is responsible for the category of problem involved.  Some sites may
+use a local address as a default.  
+.I site
+values are defined by using the 
+.BR aliases (5).
+.LP
+.B send-pr
+invokes an editor on a problem report template (after trying to fill
+in some fields with reasonable default values).  When you exit the
+editor,
+.B send-pr 
+sends the completed form to the
+.I Problem Report Management System
+(\fBGNATS\fR) at a central support site.  At the support site, the PR
+is assigned a unique number and is stored in the \fBGNATS\fR database
+according to its category and submitter-id.  \fBGNATS\fR automatically
+replies with an acknowledgement, citing the category and the PR
+number.
+.LP
+To ensure that a PR is handled promptly, it should contain your (unique)
+\fIsubmitter-id\fR and one of the available \fIcategories\fR to identify the
+problem area.  (Use
+.B `send-pr -L'
+to see a list of categories.)
+.LP
+The
+.B send-pr
+template at your site should already be customized with your
+submitter-id (running `\|\fBinstall-sid\fP \fIsubmitter-id\fP\|' to
+accomplish this is part of the installation procedures for
+.BR send-pr ).
+If this hasn't been done, see your system administrator for your
+submitter-id, or request one from your support site by invoking
+.B `send-pr \-\-request\-id'.
+If your site does not distinguish between different user sites, or if
+you are not affiliated with the support site, use
+.B `net'
+for this field.
+.LP
+The more precise your problem description and the more complete your
+information, the faster your support team can solve your problems.
+.SH OPTIONS
+.TP
+.BI \-f " problem-report"
+specify a file (\fIproblem-report\fR) which already contains a
+complete problem report.
+.B send-pr
+sends the contents of the file without invoking the editor.  If 
+the value for 
+.I problem-report
+is
+.BR `\|\-\|' ,
+then
+.B send-pr
+reads from standard input.
+.TP
+.BI \-s " severity"
+Give the problem report the severity
+.IR severity .
+.TP
+.BI \-t " mail-address"
+Change mail address at the support site for problem reports.  The
+default 
+.I mail-address
+is the address used for the default 
+.IR site .  
+Use the
+.I site
+argument rather than this option in nearly all cases.
+.TP
+.BI \-c " address"
+Put
+.I address
+in the 
+.B Cc:
+header of the message.
+.TP
+.B \-P
+print the form specified by the environment variable 
+.B PR_FORM 
+on standard output.  If 
+.B PR_FORM
+is not set, print the standard blank PR template.  No mail is sent.
+.TP
+.B -L
+print the list of available categories.  No mail is sent.
+.TP
+.B \-\-request\-id
+sends mail to the default support site, or
+.I site
+if specified, with a request for your 
+.IR submitter-id . 
+If you are
+not affiliated with 
+.IR site ,
+use a
+.I submitter-id
+of
+.BR net \|'.
+.TP
+.B \-V
+Display the 
+.B send-pr
+version number.
+.LP
+Note: use
+.B send-pr
+to submit problem reports rather than mailing them directly.  Using
+both the template and
+.B send-pr
+itself will help ensure all necessary information will reach the
+support site.
+.SH ENVIRONMENT
+The environment variable 
+.B EDITOR
+specifies the editor to invoke on the template.
+.br
+default:
+.B vi
+.sp
+If the environment variable 
+.B PR_FORM
+is set, then its value is used as the file name of the template for
+your problem-report editing session.  You can use this to start with a
+partially completed form (for example, a form with the identification
+fields already completed).
+.SH "HOW TO FILL OUT A PROBLEM REPORT"
+Problem reports have to be in a particular form so that a program can
+easily manage them.  Please remember the following guidelines:
+.IP \(bu 3m 
+describe only 
+.B one problem
+with each problem report.
+.IP \(bu 3m
+For follow-up mail, use the same subject line as the one in the automatic
+acknowledgent. It consists of category, PR number and the original synopsis
+line.  This allows the support site to relate several mail messages to a
+particular PR and to record them automatically.
+.IP \(bu 3m 
+Please try to be as accurate as possible in the subject and/or synopsis line.
+.IP \(bu 3m 
+The subject and the synopsis line are not confidential.  This is
+because open-bugs lists are compiled from them.  Avoid confidential
+information there.
+.LP
+See the GNU 
+.B Info 
+file
+.B send-pr.info
+or the document \fIReporting Problems With send-pr\fR\ for detailed
+information on reporting problems
+.SH "HOW TO SUBMIT TEST CASES, CODE, ETC."
+Submit small code samples with the PR.  Contact the support site for
+instructions on submitting larger test cases and problematic source
+code.
+.SH FILES
+.ta \w'/tmp/pbad$$  'u
+/tmp/p$$	copy of PR used in editing session
+.br
+/tmp/pf$$	copy of empty PR form, for testing purposes
+.br
+/tmp/pbad$$	file for rejected PRs
+.SH EMACS USER INTERFACE
+An Emacs user interface for 
+.B send-pr
+with completion of field values is part of the 
+.B send-pr
+distribution (invoked with
+.BR "M-x send-pr" ).
+See the file
+.B send-pr.info
+or the ASCII file
+.B INSTALL
+in the top level directory of the distribution for configuration and
+installation information.  The Emacs LISP template file is 
+.B send-pr-el.in
+and is installed as
+.BR send-pr.el .
+.SH INSTALLATION AND CONFIGURATION
+See 
+.B send-pr.info
+or
+.B INSTALL
+for installation instructions.
+.SH SEE ALSO
+.I Reporting Problems Using send-pr
+(also installed as the GNU Info file
+.BR send-pr.info ).
+.LP
+.BR gnats (l),
+.BR query-pr (1),
+.BR edit-pr (1),
+.BR gnats (8),
+.BR queue-pr (8),
+.BR at-pr (8),
+.BR mkcat (8),
+.BR mkdist (8).
+.SH AUTHORS
+Jeffrey Osier, Brendan Kehoe, Jason Merrill, Heinz G. Seidl (Cygnus
+Support)
+.SH COPYING
+Copyright (c) 1992, 1993 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+
diff --git a/krb5-1-6/src/util/send-pr/send-pr.sh b/krb5-1-6/src/util/send-pr/send-pr.sh
new file mode 100644
index 000000000..e15ea5dfe
--- /dev/null
+++ b/krb5-1-6/src/util/send-pr/send-pr.sh
@@ -0,0 +1,542 @@
+#!/bin/sh
+# Submit a problem report to a GNATS site.
+# Copyright (C) 1993 Free Software Foundation, Inc.
+# Contributed by Brendan Kehoe (brendan@cygnus.com), based on a
+# version written by Heinz G. Seidl (hgs@cygnus.com).
+#
+# This file is part of GNU GNATS.
+#
+# GNU GNATS is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU GNATS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU GNATS; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The version of this send-pr.
+VERSION=3.99
+
+# The submitter-id for your site.
+SUBMITTER=@SUBMITTER@
+
+# Where the GNATS directory lives, if at all.
+[ -z "$GNATS_ROOT" ] && 
+GNATS_ROOT=
+
+# The default mail address for PR submissions. 
+GNATS_ADDR=krb5-bugs@mit.edu
+
+# Where the gnats category tree lives.
+DATADIR=@DATADIR@
+
+# If we've been moved around, try using GCC_EXEC_PREFIX.
+[ ! -d $DATADIR/gnats -a -d "$GCC_EXEC_PREFIX" ] && 
+  DATADIR=@DATADIR@
+
+
+# The default release for this host.
+DEFAULT_RELEASE="@DEFAULT_RELEASE@"
+
+# The default organization.
+DEFAULT_ORGANIZATION=
+
+# The default site to look for.
+GNATS_SITE=mit
+
+# Newer config information?
+[ -f ${GNATS_ROOT}/gnats-adm/config ] && . ${GNATS_ROOT}/gnats-adm/config
+
+# What mailer to use.  This must come after the config file, since it is
+# host-dependent.
+for dir in /usr/lib /usr/sbin /usr/ucblib; do
+  if test -f $dir/sendmail; then
+    MAIL_AGENT="$dir/sendmail -oi -t"
+    break
+  fi
+done
+
+# How to read the passwd database.
+PASSWD="cat /etc/passwd"
+if test -f /bin/domainname && test -n "`/bin/domainname`"; then
+  if test -f /usr/bin/niscat && 
+     /usr/bin/niscat passwd.org_dir > /dev/null 2>&1; then
+    PASSWD="/usr/bin/niscat passwd.org_dir"
+  elif test -f /usr/bin/ypcat && /usr/bin/ypcat passwd > /dev/null 2>&1; then
+    PASSWD="/usr/bin/ypcat passwd"
+  fi
+fi
+
+# Figure out how to do "echo -n"
+
+if test "`echo -n foo`" = foo; then
+  ECHON1="echo -n"
+  ECHON2=
+elif test "`echo 'foo\c'`" = foo; then
+  ECHON1=echo
+  ECHON2='\c'
+else
+  ECHON1=echo
+  ECHON2=
+fi
+
+#
+
+if [ -z "$TMPDIR" ]; then
+  TMPDIR=/tmp
+else
+  if [ "`echo $TMPDIR | grep '/$'`" != "" ]; then
+    TMPDIR="`echo $TMPDIR | sed -e 's,/$,,'`"
+  fi
+fi
+
+TEMP=$TMPDIR/p$$
+BAD=$TMPDIR/pbad$$
+REF=$TMPDIR/pf$$
+
+# find a user name
+if [ "$LOGNAME" = "" ]; then
+	if [ "$USER" != "" ]; then
+		LOGNAME="$USER"
+	else
+		LOGNAME="UNKNOWN"
+	fi
+fi
+
+FROM="$LOGNAME"
+if [ -z "$REPLYTO" ]; then
+  REPLYTO="$LOGNAME"
+fi
+
+# Find out the name of the originator of this PR.
+if [ -n "$NAME" ]; then
+  ORIGINATOR="$NAME"
+elif [ -f $HOME/.fullname ]; then
+  ORIGINATOR="`sed -e '1q' $HOME/.fullname`"
+else
+  # Must use temp file due to incompatibilities in quoting behavior
+  # and to protect shell metacharacters in the expansion of $LOGNAME
+  $PASSWD | grep "^$LOGNAME:" | awk -F: '{print $5}' | sed -e 's/,.*//' > $TEMP
+  ORIGINATOR="`cat $TEMP`"
+  rm -f $TEMP
+fi
+
+if [ -n "$ORGANIZATION" ]; then
+  if [ -f "$ORGANIZATION" ]; then
+    ORGANIZATION="`cat $ORGANIZATION`"
+  fi
+else
+  if [ -n "$DEFAULT_ORGANIZATION" ]; then
+    ORGANIZATION="$DEFAULT_ORGANIZATION"
+  elif [ -f $HOME/.organization ]; then
+    ORGANIZATION="`cat $HOME/.organization`"
+  elif [ -f $HOME/.signature ]; then
+    ORGANIZATION="`cat $HOME/.signature`"
+  fi
+fi
+
+# If they don't have a preferred editor set, then use
+if [ -z "$VISUAL" ]; then
+  if [ -z "$EDITOR" ]; then
+    EDIT=vi
+  else
+    EDIT="$EDITOR"
+  fi
+else
+  EDIT="$VISUAL"
+fi
+
+# Find out some information.
+SYSTEM=`( [ -f /bin/uname ] && /bin/uname -a ) || \
+        ( [ -f /usr/bin/uname ] && /usr/bin/uname -a ) || echo ""`
+ARCH=`[ -f /bin/arch ] && /bin/arch`
+MACHINE=`[ -f /bin/machine ] && /bin/machine`
+
+COMMAND=`echo $0 | sed -e 's,.*/,,'`
+USAGE="Usage: $COMMAND [-PVL] [-t address] [-f filename] [-s severity]
+       [-c address] [--request-id] [--version]"
+REMOVE=
+BATCH=
+CC=
+SEVERITY_C=
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -r) ;; 		# Ignore for backward compat.
+    -t | --to) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+	shift ; GNATS_ADDR="$1"
+	EXPLICIT_GNATS_ADDR=true
+        ;;
+    -f | --file) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+	shift ; IN_FILE="$1"
+	if [ "$IN_FILE" != "-" -a ! -r "$IN_FILE" ]; then
+	  echo "$COMMAND: cannot read $IN_FILE"
+	  exit 1
+	fi
+	;;
+    -b | --batch) BATCH=true ;;
+    -c | --cc) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+	shift ; CC="$1"
+	;;
+    -s | --severity) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+	shift ; SEVERITY_C="$1"
+	;;
+    -p | -P | --print) PRINT=true ;;
+    -L | --list) FORMAT=norm ;;
+    -l | -CL | --lisp) FORMAT=lisp ;;
+    --request-id) REQUEST_ID=true ;;
+    -h | --help) echo "$USAGE"; exit 0 ;;
+    -V | --version) echo "$VERSION"; exit 0 ;;
+    -*) echo "$USAGE" ; exit 1 ;;
+    *) if [ -z "$USER_GNATS_SITE" ]; then
+	 if [ ! -r "$DATADIR/gnats/$1" ]; then
+	   echo "$COMMAND: the GNATS site $1 does not have a categories list."
+	   exit 1
+	 else
+	   # The site name is the alias they'll have to have created.
+	   USER_GNATS_SITE=$1
+	 fi
+       else
+	 echo "$USAGE" ; exit 1
+       fi
+       ;;
+ esac
+ shift
+done
+
+if [ -n "$USER_GNATS_SITE" ] && [ "$USER_GNATS_SITE" != "$GNATS_SITE" ]; then
+  GNATS_SITE=$USER_GNATS_SITE
+  GNATS_ADDR=$USER_GNATS_SITE-gnats
+fi
+
+if [ "$SUBMITTER" = "unknown" -a -z "$REQUEST_ID" -a -z "$IN_FILE" ]; then
+  cat << '__EOF__'
+It seems that send-pr is not installed with your unique submitter-id.
+You need to run
+
+          install-sid YOUR-SID
+
+where YOUR-SID is the identification code you received with `send-pr'.
+`send-pr' will automatically insert this value into the template field
+`>Submitter-Id'.  If you've downloaded `send-pr' from the Net, use `net'
+for this value.  If you do not know your id, run `send-pr --request-id' to 
+get one from your support site.
+__EOF__
+  exit 1
+fi
+
+if [ -r "$DATADIR/gnats/$GNATS_SITE" ]; then
+  CATEGORIES=`grep -v '^#' $DATADIR/gnats/$GNATS_SITE | sort`
+else
+  echo "$COMMAND: could not read $DATADIR/gnats/$GNATS_SITE for categories list."
+  exit 1
+fi
+
+if [ -z "$CATEGORIES" ]; then
+  echo "$COMMAND: the categories list for $GNATS_SITE was empty!"
+  exit 1
+fi
+
+case "$FORMAT" in
+  lisp) echo "$CATEGORIES" | \
+        awk 'BEGIN {printf "( "} {printf "(\"%s\") ",$0} END {printf ")\n"}'
+        exit 0
+        ;;
+  norm) l=`echo "$CATEGORIES" | \
+	awk 'BEGIN {max = 0; } { if (length($0) > max) { max = length($0); } }
+	     END {print max + 1;}'`
+	c=`expr 70 / $l`
+	if [ $c -eq 0 ]; then c=1; fi
+	echo "$CATEGORIES" | \
+        awk 'BEGIN {print "Known categories:"; i = 0 }
+          { printf ("%-'$l'.'$l's", $0); if ((++i % '$c') == 0) { print "" } }
+            END { print ""; }'
+        exit 0
+        ;;
+esac
+
+ORIGINATOR_C='<name of the PR author (one line)>'
+ORGANIZATION_C='<organization of PR author (multiple lines)>'
+CONFIDENTIAL_C='<[ yes | no ] (one line)>'
+SYNOPSIS_C='<synopsis of the problem (one line)>'
+if [ -z "$SEVERITY_C" ]; then
+  SEVERITY_C='<[ non-critical | serious | critical ] (one line)>'
+fi
+PRIORITY_C='<[ low | medium | high ] (one line)>'
+CATEGORY_C='<name of the product (one line)>'
+CLASS_C='<[ sw-bug | doc-bug | change-request | support ] (one line)>'
+RELEASE_C='<release number or tag (one line)>'
+ENVIRONMENT_C='<machine, os, target, libraries (multiple lines)>'
+DESCRIPTION_C='<precise description of the problem (multiple lines)>'
+HOW_TO_REPEAT_C='<code/input/activities to reproduce the problem (multiple lines)>'
+FIX_C='<how to correct or work around the problem, if known (multiple lines)>'
+
+# Catch some signals. ($xs kludge needed by Sun /bin/sh)
+xs=0
+trap 'rm -f $REF $TEMP; exit $xs' 0
+trap 'echo "$COMMAND: Aborting ..."; rm -f $REF $TEMP; xs=1; exit' 1 2 3 13 15
+
+# If they told us to use a specific file, then do so.
+if [ -n "$IN_FILE" ]; then
+  if [ "$IN_FILE" = "-" ]; then
+    # The PR is coming from the standard input.
+    if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
+      sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" > $TEMP
+    else
+      cat > $TEMP
+    fi
+  else
+    # Use the file they named.
+    if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
+      sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" $IN_FILE > $TEMP
+    else
+      cat $IN_FILE > $TEMP
+    fi
+  fi
+else
+
+  if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
+    # If their PR_FORM points to a bogus entry, then bail.
+    if [ ! -f "$PR_FORM" -o ! -r "$PR_FORM" -o ! -s "$PR_FORM" ]; then
+      echo "$COMMAND: can't seem to read your template file (\`$PR_FORM'), ignoring PR_FORM"
+      sleep 1
+      PRINT_INTERN=bad_prform
+    fi
+  fi
+
+  if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
+    cp $PR_FORM $TEMP || 
+      ( echo "$COMMAND: could not copy $PR_FORM" ; xs=1; exit )
+  else
+    for file in $TEMP $REF ; do
+      cat  > $file << '__EOF__'
+SEND-PR: -*- send-pr -*-
+SEND-PR: Lines starting with `SEND-PR' will be removed automatically, as
+SEND-PR: will all comments (text enclosed in `<' and `>').
+SEND-PR: 
+SEND-PR: Please consult the send-pr man page `send-pr(1)' or the Texinfo
+SEND-PR: manual if you are not sure how to fill out a problem report.
+SEND-PR:
+SEND-PR: Choose from the following categories:
+SEND-PR:
+__EOF__
+
+      # Format the categories so they fit onto lines.
+	l=`echo "$CATEGORIES" | \
+	awk 'BEGIN {max = 0; } { if (length($0) > max) { max = length($0); } }
+	     END {print max + 1;}'`
+	c=`expr 61 / $l`
+	if [ $c -eq 0 ]; then c=1; fi
+	echo "$CATEGORIES" | \
+        awk 'BEGIN {printf "SEND-PR: "; i = 0 }
+          { printf ("%-'$l'.'$l's", $0);
+	    if ((++i % '$c') == 0) { printf "\nSEND-PR: " } }
+            END { printf "\nSEND-PR:\n"; }' >> $file
+
+      cat >> $file << __EOF__
+To: $GNATS_ADDR
+Subject: 
+From: $FROM
+Reply-To: $REPLYTO
+Cc: $CC
+X-send-pr-version: $VERSION
+
+
+>Submitter-Id:	$SUBMITTER
+>Originator:	$ORIGINATOR
+>Organization:
+${ORGANIZATION-	$ORGANIZATION_C}
+>Confidential:	$CONFIDENTIAL_C
+>Synopsis:	$SYNOPSIS_C
+>Severity:	$SEVERITY_C
+>Priority:	$PRIORITY_C
+>Category:	$CATEGORY_C
+>Class:		$CLASS_C
+>Release:	${DEFAULT_RELEASE-$RELEASE_C}
+>Environment:
+	$ENVIRONMENT_C
+`[ -n "$SYSTEM" ] && echo System: $SYSTEM`
+`[ -n "$ARCH" ] && echo Architecture: $ARCH`
+`[ -n "$MACHINE" ] && echo Machine: $MACHINE`
+>Description:
+	$DESCRIPTION_C
+>How-To-Repeat:
+	$HOW_TO_REPEAT_C
+>Fix:
+	$FIX_C
+__EOF__
+    done
+  fi
+
+  if [ "$PRINT" = true -o "$PRINT_INTERN" = true ]; then
+    cat $TEMP
+    xs=0; exit
+  fi
+
+  chmod u+w $TEMP
+  if [ -z "$REQUEST_ID" ]; then
+    eval $EDIT $TEMP
+  else
+    ed -s $TEMP << '__EOF__'
+/^Subject/s/^Subject:.*/Subject: request for a customer id/
+/^>Category/s/^>Category:.*/>Category: send-pr/
+w
+q
+__EOF__
+  fi
+
+  if cmp -s $REF $TEMP ; then
+    echo "$COMMAND: problem report not filled out, therefore not sent"
+    xs=1; exit
+  fi
+fi
+
+#
+#	Check the enumeration fields
+
+# This is a "sed-subroutine" with one keyword parameter 
+# (with workaround for Sun sed bug)
+#
+SED_CMD='
+/$PATTERN/{
+s|||
+s|<.*>||
+s|^[ 	]*||
+s|[ 	]*$||
+p
+q
+}'
+
+
+while [ -z "$REQUEST_ID" ]; do
+  CNT=0
+
+  # 1) Confidential
+  #
+  PATTERN=">Confidential:"
+  CONFIDENTIAL=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
+  case "$CONFIDENTIAL" in
+    ""|yes|no) CNT=`expr $CNT + 1` ;;
+    *) echo "$COMMAND: \`$CONFIDENTIAL' is not a valid value for \`Confidential'." ;;
+  esac
+  #
+  # 2) Severity
+  #
+  PATTERN=">Severity:"
+  SEVERITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
+  case "$SEVERITY" in
+    ""|non-critical|serious|critical) CNT=`expr $CNT + 1` ;;
+    *)  echo "$COMMAND: \`$SEVERITY' is not a valid value for \`Severity'."
+  esac
+  #
+  # 3) Priority
+  #
+  PATTERN=">Priority:"
+  PRIORITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
+  case "$PRIORITY" in
+    ""|low|medium|high) CNT=`expr $CNT + 1` ;;
+    *)  echo "$COMMAND: \`$PRIORITY' is not a valid value for \`Priority'."
+  esac
+  #
+  # 4) Category
+  #
+  PATTERN=">Category:"
+  CATEGORY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
+  FOUND=
+  for C in $CATEGORIES
+  do
+    if [ "$C" = "$CATEGORY" ]; then FOUND=true ; break ; fi
+  done
+  if [ -n "$FOUND" ]; then
+    CNT=`expr $CNT + 1`	
+  else
+    if [ -z "$CATEGORY" ]; then
+      echo "$COMMAND: you must include a Category: field in your report."
+    else
+      echo "$COMMAND: \`$CATEGORY' is not a known category."
+    fi
+  fi
+  #
+  # 5) Class
+  #
+  PATTERN=">Class:"
+  CLASS=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
+  case "$CLASS" in
+    ""|sw-bug|doc-bug|change-request|support) CNT=`expr $CNT + 1` ;;
+    *)  echo "$COMMAND: \`$CLASS' is not a valid value for \`Class'."
+  esac
+
+  [ $CNT -lt 5 -a -z "$BATCH" ] && 
+    echo "Errors were found with the problem report."
+
+  while true; do
+    if [ -z "$BATCH" ]; then
+      $ECHON1 "a)bort, e)dit or s)end? $ECHON2"
+      read input
+    else
+      if [ $CNT -eq 5 ]; then
+        input=s
+      else
+        input=a
+      fi
+    fi
+    case "$input" in
+      a*)
+	if [ -z "$BATCH" ]; then
+	  echo "$COMMAND: the problem report remains in $BAD and is not sent."
+	  mv $TEMP $BAD
+        else
+	  echo "$COMMAND: the problem report is not sent."
+	fi
+	xs=1; exit
+	;;
+      e*)
+        eval $EDIT $TEMP
+	continue 2
+	;;
+      s*)
+	break 2
+	;;
+    esac
+  done
+done
+#
+#	Remove comments and send the problem report
+#	(we have to use patterns, where the comment contains regex chars)
+#
+# /^>Originator:/s;$ORIGINATOR;;
+sed  -e "
+/^SEND-PR:/d
+/^>Organization:/,/^>[A-Za-z-]*:/s;$ORGANIZATION_C;;
+/^>Confidential:/s;<.*>;;
+/^>Synopsis:/s;$SYNOPSIS_C;;
+/^>Severity:/s;<.*>;;
+/^>Priority:/s;<.*>;;
+/^>Category:/s;$CATEGORY_C;;
+/^>Class:/s;<.*>;;
+/^>Release:/,/^>[A-Za-z-]*:/s;$RELEASE_C;;
+/^>Environment:/,/^>[A-Za-z-]*:/s;$ENVIRONMENT_C;;
+/^>Description:/,/^>[A-Za-z-]*:/s;$DESCRIPTION_C;;
+/^>How-To-Repeat:/,/^>[A-Za-z-]*:/s;$HOW_TO_REPEAT_C;;
+/^>Fix:/,/^>[A-Za-z-]*:/s;$FIX_C;;
+" $TEMP > $REF
+
+if $MAIL_AGENT < $REF; then
+  echo "$COMMAND: problem report sent"
+  xs=0; exit
+else
+  echo "$COMMAND: mysterious mail failure."
+  if [ -z "$BATCH" ]; then
+    echo "$COMMAND: the problem report remains in $BAD and is not sent."
+    mv $REF $BAD
+  else
+    echo "$COMMAND: the problem report is not sent."
+  fi
+  xs=1; exit
+fi
diff --git a/krb5-1-6/src/util/ss/Makefile.in b/krb5-1-6/src/util/ss/Makefile.in
new file mode 100644
index 000000000..fe39c3918
--- /dev/null
+++ b/krb5-1-6/src/util/ss/Makefile.in
@@ -0,0 +1,227 @@
+thisconfigdir=.
+myfulldir=util/ss
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+SED = sed
+DEFS=
+
+INSTALLLIB=cp
+INSTALLFILE=cp
+
+all::
+
+TOP=$(BUILDTOP)
+
+LIBBASE=ss
+LIBMAJOR=1
+LIBMINOR=0
+RELDIR=../util/ss
+
+STOBJLISTS=OBJS.ST
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+install-unix:: install-libs
+
+# hard coded srcdir/.. is so that ss/ss.h works
+
+# hard coded .. is so that ss/ss_err.h works
+# hard coded ../et is so com_err.h works
+# CFLAGS= -g
+# CPPFLAGS= -I${INCDIR} -I. -I.. -I../et
+LOCALINCLUDES= -I. -I$(srcdir)/
+
+# with ss_err.o first, ss_err.h should get rebuilt first too.  should not
+# be relying on this, though.
+STLIBOBJS=\
+	ss_err.o \
+	std_rqs.o \
+	invocation.o help.o \
+	execute_cmd.o listen.o parse.o error.o prompt.o \
+	request_tbl.o list_rqs.o pager.o requests.o \
+	data.o
+
+SRCS=	$(srcdir)/invocation.c $(srcdir)/help.c \
+	$(srcdir)/execute_cmd.c $(srcdir)/listen.c $(srcdir)/parse.c \
+	$(srcdir)/error.c $(srcdir)/prompt.c \
+	$(srcdir)/request_tbl.c $(srcdir)/list_rqs.c $(srcdir)/pager.c \
+	$(srcdir)/requests.c $(srcdir)/data.c
+EXTRADEPSRCS= \
+	$(srcdir)/mk_cmds.c $(srcdir)/utils.c $(srcdir)/options.c \
+	cmd_tbl.lex.c ct.tab.c \
+	ss_err.c \
+	std_rqs.c
+depend-dependencies: ss_err.h includes
+
+std_rqs.o: std_rqs.c ss_err.h
+
+CODE= $(SRCS) $(MKCMDSFILES)
+
+MKCMDSOBJS=	mk_cmds.o utils.o options.o ct.tab.o cmd_tbl.lex.o
+
+MKCMDSFILES=	mk_cmds.c utils.c options.c ct.y cmd_tbl.lex.l
+
+MKCMDSCSRCS=	mk_cmds.c utils.c options.c ct.tab.c cmd_tbl.lex.c
+
+
+HFILES=	ss.h mit-sipb-copyright.h
+BUILT_HFILES = ss_err.h
+
+# for 'tags' and dependencies
+
+CFILES=	$(SRCS) $(MKCMDSCSRCS) test_ss.c
+
+# for building archives
+
+FILES=	$(SRCS) $(MKCMDSFILES) $(HFILES) \
+	ss_err.et std_rqs.ct Makefile \
+	test_ss.c ss mit-sipb-copyright.h copyright.h
+
+#
+# stuff to build
+#
+
+all-unix::	mk_cmds ct_c.awk ct_c.sed includes # libss_p.a lint
+all-unix:: all-liblinks
+all-windows::  all-unix
+
+dist:	archives
+
+install::
+
+includes:: mk_cmds ct_c.sed ct_c.awk ss_err.h
+
+HDRDIR=$(BUILDTOP)/include/ss
+HDRS =	$(HDRDIR)/ss.h \
+	$(HDRDIR)/ss_err.h
+
+BUILD_HDRS = ss_err.h
+SRC_HDRS = ss.h 
+SRC_HDRS_DEP = $(srcdir)/ss.h
+
+generate-files-mac: ct_c.awk ct_c.sed std_rqs.c ss_err.h
+
+includes:: $(HDRS)
+$(HDRDIR)/timestamp:
+	if [ -d $(HDRDIR) ] ; then :; else mkdir -p $(HDRDIR); fi
+	echo timestamp > $(HDRDIR)/timestamp
+$(HDRDIR)/ss.h: ss.h $(HDRDIR)/timestamp
+	$(RM) $(HDRDIR)/ss.h
+	$(CP) $(srcdir)/ss.h $(HDRDIR)/ss.h
+$(HDRDIR)/ss_err.h: ss_err.h $(HDRDIR)/timestamp
+	$(RM) $(HDRDIR)/ss_err.h
+	$(CP) ss_err.h $(HDRDIR)/ss_err.h
+
+clean-unix::
+	$(RM) $(HDRS) $(HDRDIR)/timestamp
+
+std_rqs.c: std_rqs.ct mk_cmds ct_c.sed ct_c.awk
+
+ss_err.h: ss_err.et
+
+ss_err.c: ss_err.et
+
+clean::
+	$(RM) ss_err.o ss_err.c ss_err.h std_rqs.c
+
+depend:: ss_err.h
+
+ct.tab.c ct.tab.h: ct.y
+	$(RM) ct.tab.* y.*
+	$(YACC) -d $(srcdir)/ct.y
+	$(MV) y.tab.c ct.tab.c
+	$(MV) y.tab.h ct.tab.h
+
+# install_library_target(ss,$(OBJS),$(SRCS),)
+
+#mk_cmds: $(MKCMDSOBJS)
+#	$(CC) $(ALL_CFLAGS) -o $@ $(MKCMDSOBJS) $(LEXLIB) $(BSDLIB)
+#
+#mk_cmds.o:	ss_err.h
+#
+#install::
+#	$(INSTALLPROG) mk_cmds ${DESTDIR}$(PROGDIR)/mk_cmds
+
+mk_cmds: $(srcdir)/mk_cmds.sh $(srcdir)/config_script 
+	$(SHELL) $(srcdir)/config_script $(srcdir)/mk_cmds.sh . $(AWK) $(SED) > mk_cmds
+	chmod 755 mk_cmds	
+
+ct_c.awk: $(srcdir)/ct_c_awk.in
+	$(RM) $@
+	$(CP) $(srcdir)/ct_c_awk.in $@
+
+ct_c.sed: $(srcdir)/ct_c_sed.in
+	$(SED) -e '/^#/d' $(srcdir)/ct_c_sed.in > ct_c.sed
+
+clean::
+	$(RM) mk_cmds ct_c.awk ct_c.sed $(MKCMDSOBJS)
+
+# 
+
+clean::
+	rm -f *.o *~ \#* *.bak core \
+		ss_err.h ct.tab.c ct.tab.h cmd_tbl.lex.c \
+		lex.yy.c y.tab.c \
+		libss.a libss_p.a llib-lss.ln mk_cmds \
+		ss.ar ss.tar \
+		TAGS test_ss
+
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+invocation.so invocation.po $(OUTPRE)invocation.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/ss/ss_err.h \
+  $(COM_ERR_DEPS) copyright.h invocation.c ss.h ss_internal.h
+help.so help.po $(OUTPRE)help.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  help.c ss.h ss_internal.h
+execute_cmd.so execute_cmd.po $(OUTPRE)execute_cmd.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/ss/ss_err.h \
+  $(COM_ERR_DEPS) copyright.h execute_cmd.c ss.h ss_internal.h
+listen.so listen.po $(OUTPRE)listen.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  listen.c ss.h ss_internal.h
+parse.so parse.po $(OUTPRE)parse.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  parse.c ss.h ss_internal.h
+error.so error.po $(OUTPRE)error.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  error.c ss.h ss_internal.h
+prompt.so prompt.po $(OUTPRE)prompt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  prompt.c ss.h ss_internal.h
+request_tbl.so request_tbl.po $(OUTPRE)request_tbl.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/ss/ss_err.h \
+  $(COM_ERR_DEPS) copyright.h request_tbl.c ss.h ss_internal.h
+list_rqs.so list_rqs.po $(OUTPRE)list_rqs.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/ss/ss_err.h \
+  $(COM_ERR_DEPS) copyright.h list_rqs.c ss.h ss_internal.h
+pager.so pager.po $(OUTPRE)pager.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  pager.c ss.h ss_internal.h
+requests.so requests.po $(OUTPRE)requests.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/ss/ss_err.h \
+  $(COM_ERR_DEPS) requests.c ss.h ss_internal.h
+data.so data.po $(OUTPRE)data.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  data.c ss.h ss_internal.h
+mk_cmds.so mk_cmds.po $(OUTPRE)mk_cmds.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  mk_cmds.c ss.h ss_internal.h
+utils.so utils.po $(OUTPRE)utils.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) copyright.h \
+  ss.h ss_internal.h utils.c
+options.so options.po $(OUTPRE)options.$(OBJEXT): $(BUILDTOP)/include/ss/ss_err.h \
+  $(COM_ERR_DEPS) copyright.h options.c ss.h
+cmd_tbl.lex.o: cmd_tbl.lex.c ct.tab.h
+ct.tab.o: $(BUILDTOP)/include/ss/ss_err.h $(COM_ERR_DEPS) \
+  ct.tab.c ss.h
+ss_err.so ss_err.po $(OUTPRE)ss_err.$(OBJEXT): $(COM_ERR_DEPS) \
+  ss_err.c
+std_rqs.so std_rqs.po $(OUTPRE)std_rqs.$(OBJEXT): $(COM_ERR_DEPS) \
+  $(SS_DEPS) std_rqs.c
diff --git a/krb5-1-6/src/util/ss/cmd_tbl.lex.l b/krb5-1-6/src/util/ss/cmd_tbl.lex.l
new file mode 100644
index 000000000..b47085e98
--- /dev/null
+++ b/krb5-1-6/src/util/ss/cmd_tbl.lex.l
@@ -0,0 +1,81 @@
+N	[0-9]
+PC	[^\"]
+AN      [A-Z_a-z0-9]
+%%
+
+command_table	return l_command_table();
+request		return l_request();
+unimplemented	return l_unimplemented();
+end		return l_end();
+
+[\t\n ]		;
+
+\"{PC}*\"	return l_quoted_string();
+
+{AN}*		return l_string();
+
+#.*\n		;
+
+.		return (*yytext);
+%%
+/*
+ * User-subroutines section.
+ *
+ * Have to put all this stuff here so that the include file
+ * from YACC output can be included, since LEX doesn't allow
+ * an include file before the code it generates for the above
+ * rules.
+ *
+ * Copyright 1987 by MIT Student Information Processing Board.
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+#include <string.h>
+#include "ct.tab.h"
+
+#ifndef HAS_STRDUP
+extern char *strdup();
+#endif
+
+extern char *last_token;
+
+static l_command_table()
+{
+     last_token = "command_table";
+     return COMMAND_TABLE;
+}
+
+static l_request()
+{
+     last_token = "request";
+     return REQUEST;
+}
+
+static l_unimplemented()
+{
+     last_token = "unimplemented";
+     return UNIMPLEMENTED;
+}
+
+static l_end()
+{
+     last_token = "end";
+     return END;
+}
+
+static l_quoted_string()
+{
+     register char *p;
+     yylval.dynstr = strdup(yytext+1);
+     if (p=strrchr(yylval.dynstr, '"'))
+	  *p='\0';
+     last_token = strdup(yylval.dynstr);
+     return STRING;
+}
+
+static l_string()
+{
+     yylval.dynstr = strdup(yytext);
+     last_token = strdup(yylval.dynstr);
+     return STRING;
+}
diff --git a/krb5-1-6/src/util/ss/config_script b/krb5-1-6/src/util/ss/config_script
new file mode 100755
index 000000000..5add600ed
--- /dev/null
+++ b/krb5-1-6/src/util/ss/config_script
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# This program takes a shell script and configures for the following
+# variables:	@DIR@
+#		@AWK@
+#		@SED@
+#
+# Usage: config_script <filename> [<dir>] [<awk>] [<sed>]
+#
+
+FILE=$1
+DIR=$2
+AWK=$3
+SED=$4
+
+if test "${DIR}x" = "x" ; then
+	DIR=.
+fi
+DIR=`cd ${DIR}; pwd`
+if test "${AWK}x" = "x" ; then
+	AWK=awk
+fi
+if test "${SED}x" = "x" ; then
+	SED=sed
+fi
+
+
+sed -e "s;@DIR@;${DIR};" -e "s;@AWK@;${AWK};" -e "s;@SED@;${SED};" $FILE
diff --git a/krb5-1-6/src/util/ss/configure.in b/krb5-1-6/src/util/ss/configure.in
new file mode 100644
index 000000000..f68c53380
--- /dev/null
+++ b/krb5-1-6/src/util/ss/configure.in
@@ -0,0 +1,17 @@
+K5_AC_INIT(ct.y)
+CONFIG_RULES
+AC_PROG_LEX
+AC_PROG_YACC
+AC_PROG_AWK
+HAVE_YYLINENO
+AC_CHECK_FUNCS(strdup)
+CHECK_DIRENT
+CHECK_WAIT_TYPE
+CHECK_SIGNALS
+CHECK_SIGPROCMASK
+AC_TYPE_SIGNAL
+AC_HEADER_STDARG
+AC_CHECK_HEADERS(stdlib.h)
+KRB5_BUILD_LIBRARY_STATIC
+KRB5_BUILD_LIBOBJS
+V5_AC_OUTPUT_MAKEFILE
diff --git a/krb5-1-6/src/util/ss/copyright.h b/krb5-1-6/src/util/ss/copyright.h
new file mode 100644
index 000000000..d118f10bf
--- /dev/null
+++ b/krb5-1-6/src/util/ss/copyright.h
@@ -0,0 +1,22 @@
+/*
+
+Copyright 1987, 1989 by the Student Information Processing Board
+	of the Massachusetts Institute of Technology
+
+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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+Furthermore if you modify this software you must label
+your software as modified software and not distribute it in such a
+fashion that it might be confused with the original M.I.T. software.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose.  It is
+provided "as is" without express or implied warranty.
+
+*/
+
diff --git a/krb5-1-6/src/util/ss/ct.y b/krb5-1-6/src/util/ss/ct.y
new file mode 100644
index 000000000..0727492cf
--- /dev/null
+++ b/krb5-1-6/src/util/ss/ct.y
@@ -0,0 +1,81 @@
+%{
+/*
+ * Copyright 1987 by MIT Student Information Processing Board
+ *
+ * For copyright info, see mit-sipb-copyright.h.
+ */
+#include <stdio.h>
+#include <string.h>
+
+#ifndef HAS_STRDUP
+extern char *strdup();
+#endif
+
+char *str_concat3(), *generate_rqte(), *quote();
+long flag_value();
+char *last_token = (char *)NULL;
+FILE *output_file;
+long gensym_n = 0;
+
+%}
+%union {
+	char *dynstr;
+	long flags;
+}
+
+%token COMMAND_TABLE REQUEST UNKNOWN UNIMPLEMENTED END
+%token <dynstr> STRING
+%token <dynstr> FLAGNAME
+%type <dynstr> namelist header request_list
+%type <dynstr> request_entry
+%type <flags> flag_list options
+%left OPTIONS
+%{
+#include "ss.h"
+%}
+%start command_table
+%%
+command_table :	header request_list END ';'
+		{ write_ct($1, $2); }
+	;
+
+header	:	COMMAND_TABLE STRING ';'
+		{ $$ = $2; }
+	;
+
+request_list :	request_list request_entry
+		{ $$ = str_concat3($1, $2, ""); }
+	|
+		{ $$ = ""; }
+	;
+
+request_entry :	REQUEST STRING ',' STRING ',' namelist ',' options ';'
+		{ $$ = generate_rqte($2, quote($4), $6, $8); }
+	|	REQUEST STRING ',' STRING ',' namelist ';'
+		{ $$ = generate_rqte($2, quote($4), $6, 0); }
+	|	UNKNOWN namelist ';'
+		{ $$ = generate_rqte("ss_unknown_request",
+					(char *)NULL, $2, 0); }
+	|	UNIMPLEMENTED STRING ',' STRING ',' namelist ';'
+		{ $$ = generate_rqte("ss_unimplemented", quote($4), $6, 3); }
+	;
+
+options	:	'(' flag_list ')'
+		{ $$ = $2; }
+	|	'(' ')'
+		{ $$ = 0; }
+	;
+
+flag_list :	flag_list ',' STRING
+		{ $$ = $1 | flag_val($3); }
+	|	STRING
+		{ $$ = flag_val($1); }
+	;
+
+namelist: 	STRING
+		{ $$ = quote(strdup($1)); }
+	|	namelist ',' STRING
+		{ $$ = str_concat3($1, quote($3), ",\n    "); }
+	;
+
+%%
diff --git a/krb5-1-6/src/util/ss/ct_c_awk.in b/krb5-1-6/src/util/ss/ct_c_awk.in
new file mode 100644
index 000000000..872f6e007
--- /dev/null
+++ b/krb5-1-6/src/util/ss/ct_c_awk.in
@@ -0,0 +1,77 @@
+/^command_table / {
+	cmdtbl = $2;
+	printf "/* %s.c - automatically generated from %s.ct */\n", \
+		rootname, rootname > outfile
+	print "#include <ss/ss.h>" > outfile
+	print "" >outfile
+	print "#ifndef __STDC__" > outfile
+	print "#define const" > outfile
+	print "#endif" > outfile
+	print "" > outfile
+}
+	
+/^BOR$/ {
+	cmdnum++
+	options = 0
+	cmdtab = ""
+	printf "static char const * const ssu%05d[] = {\n", cmdnum > outfile
+}
+
+/^sub/ {
+	subr = substr($0, 6, length($0)-5)
+}
+
+/^hlp/ {
+	help = substr($0, 6, length($0)-5)
+}
+
+/^cmd/ {
+	cmd = substr($0, 6, length($0)-5)
+	printf "%s\"%s\",\n", cmdtab, cmd > outfile
+	cmdtab = "    "
+}
+
+/^opt/ {
+	opt = substr($0, 6, length($0)-5)
+	if (opt == "dont_list") {
+		options += 1
+	}
+	if (opt == "dont_summarize") {
+		options += 2
+	}
+}
+
+/^EOR/ {
+	print "    (char const *)0" > outfile
+	print "};" > outfile 
+	printf "extern void %s __SS_PROTO;\n", subr > outfile
+	subr_tab[cmdnum] = subr
+	options_tab[cmdnum] = options
+	help_tab[cmdnum] = help
+}
+
+/^[0-9]/ {
+	linenum = $1;
+}
+
+/^ERROR/ {
+	error = substr($0, 8, length($0)-7)
+	printf "Error in line %d: %s\n", linenum, error
+	print "#__ERROR_IN_FILE__" > outfile
+}
+
+END {
+	printf "static ss_request_entry ssu%05d[] = {\n", cmdnum+1 > outfile
+	for (i=1; i <= cmdnum; i++) {
+		printf "    { ssu%05d,\n", i > outfile
+		printf "      %s,\n", subr_tab[i] > outfile
+		printf "      \"%s\",\n", help_tab[i] > outfile
+		printf "      %d },\n", options_tab[i] > outfile
+	}
+	print "    { 0, 0, 0, 0 }" > outfile
+	print "};" > outfile
+	print "" > outfile
+	printf "ss_request_table %s = { 2, ssu%05d };\n", \
+		cmdtbl, cmdnum+1 > outfile
+}
+
diff --git a/krb5-1-6/src/util/ss/ct_c_sed.in b/krb5-1-6/src/util/ss/ct_c_sed.in
new file mode 100644
index 000000000..f99cd7fd2
--- /dev/null
+++ b/krb5-1-6/src/util/ss/ct_c_sed.in
@@ -0,0 +1,161 @@
+#
+# This script parses a command_table file into something which is a bit 
+# easier for an awk script to understand.
+#
+# Input syntax: a .ct file
+#
+# Output syntax:
+# (for the command_table line)
+#	command_table  <command_table>
+#
+#(for each request definition)
+#	BOR
+#	sub: <subroutine name>
+#	hlp: <help text>
+#	cmd: <command>
+#	opt: <option>
+#	EOR
+# (there may be more than one 'cmd' or 'opt' line
+#
+# A number sent to the output represents a parse error --- it will be 
+# followed by the next line which will have the form:
+#	ERROR: <error text>
+#
+# The design of this output syntax is such that it should be easy for
+# an awk script to parse.
+
+#
+# The first section of this script is just to cannoicalize the file.  
+# It removes comments, and puts each command_table request onto a single
+# line
+#
+:FIRST
+y/	/ /
+s/^ *//
+s/#.*$//
+/; *$/!{
+N
+y/	/ /
+s/\n */ /
+bFIRST
+}
+s/, */, /g
+/^$/d
+#
+# Now we take care of some syntatic sugar.....
+#
+/^unimplemented/ {
+	s/^unimplemented [A-Za-z_0-9]*/request ss_unimplemented/
+	s/;/, (dont_list, dont_summarize);/
+}
+/^unknown/ {
+	s/^unknown /request ss_unknown, "", /
+}
+#
+# Dispatch based on the keyword....  illegal keywords are prefixed by ERROR:
+# and are handled by the awk script.
+#
+/^command_table /bCMD
+/^request /bREQUEST
+/^end;/bEND
+s/ .*//
+s/^/ERROR: unknown keyword: /
+=
+b
+#
+# Handle the command_table keyword
+#
+:CMD
+s/;$//
+p
+d
+b
+#
+# Handle the request keyword --- this is the heart of the sed script.
+# 
+:REQUEST
+s/^request *//
+h
+i\
+BOR
+# First, parse out the subroutine name
+s/^/sub: /
+s/,.*//
+p
+# Next, parse out the help message, being careful to handle a quoted string
+g
+s/^[^,]*, *//
+h
+/^"/ {
+	s/^"//
+	s/".*//
+	x
+	s/^"[^"]*", *//
+	x
+	b EMITHLP
+}
+s/[^a-zA-Z0-9].*//
+x
+s/[a-zA-Z0-9]*, *//
+x
+:EMITHLP
+s/^/hlp: /
+p
+# Next take care of the command names
+:CMDLIST
+g
+/^(/b OPTIONS
+/^;/b EOR
+/^"/ {
+	s/^"//
+	s/".*//
+	x
+	s/^"[^"]*"//
+	s/, *//
+	x
+	b EMITREQ
+}
+s/[^A-Za-z_0-9].*//
+x
+s/[A-Za-z_0-9]*//
+s/, *//
+x
+:EMITREQ
+s/^/cmd: /
+p
+b CMDLIST
+#
+# Here we parse the list of options.
+#
+: OPTIONS
+g
+s/^(//
+h
+: OPTLIST
+/^)/ b EOR
+/^[^A-Za-z_0-9]/ {
+	=
+	c\
+ERROR: parse error in options list
+}
+s/[^A-Za-z_0-9].*//
+x
+s/[A-Za-z_0-9]*//
+s/, *//
+x
+s/^/opt: /
+p
+g
+b OPTLIST
+: EOR
+c\
+EOR\
+
+d
+b
+#
+# Handle the end keyword --- it's basically ignored.
+#
+:END
+d
+b
diff --git a/krb5-1-6/src/util/ss/data.c b/krb5-1-6/src/util/ss/data.c
new file mode 100644
index 000000000..dd6341c0c
--- /dev/null
+++ b/krb5-1-6/src/util/ss/data.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1987, 1988, 1989 Massachusetts Institute of Technology
+ * (Student Information Processing Board)
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include <stdio.h>
+#include "ss_internal.h"
+#include "copyright.h"
+
+const static char copyright[] =
+    "Copyright 1987, 1988, 1989 by the Massachusetts Institute of Technology";
+
+ss_data **_ss_table = (ss_data **)NULL;
+char *_ss_pager_name = (char *)NULL;
diff --git a/krb5-1-6/src/util/ss/error.c b/krb5-1-6/src/util/ss/error.c
new file mode 100644
index 000000000..064805506
--- /dev/null
+++ b/krb5-1-6/src/util/ss/error.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1987, 1988, 1989 by MIT Student Information Processing
+ * Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include <stdio.h>
+
+#include "copyright.h"
+#include "com_err.h"
+#include "ss_internal.h"
+
+char * ss_name(sci_idx)
+    int sci_idx;
+{
+    register char *ret_val;
+    register ss_data *infop;
+    
+    infop = ss_info(sci_idx);
+    if (infop->current_request == (char const *)NULL) {
+	ret_val = malloc((unsigned)
+			 (strlen(infop->subsystem_name)+1)
+			 * sizeof(char));
+	if (ret_val == (char *)NULL)
+	    return((char *)NULL);
+	strcpy(ret_val, infop->subsystem_name);
+	return(ret_val);
+    }
+    else {
+	register char *cp;
+	register char const *cp1;
+	ret_val = malloc((unsigned)sizeof(char) * 
+			 (strlen(infop->subsystem_name)+
+			  strlen(infop->current_request)+
+			  4));
+	cp = ret_val;
+	cp1 = infop->subsystem_name;
+	while (*cp1)
+	    *cp++ = *cp1++;
+	*cp++ = ' ';
+	*cp++ = '(';
+	cp1 = infop->current_request;
+	while (*cp1)
+	    *cp++ = *cp1++;
+	*cp++ = ')';
+	*cp = '\0';
+	return(ret_val);
+    }
+}
+
+void ss_error (int sci_idx, long code, const char * fmt, ...)
+{
+    register char *whoami;
+    va_list pvar;
+    va_start (pvar, fmt);
+    whoami = ss_name (sci_idx);
+    com_err_va (whoami, code, fmt, pvar);
+    free (whoami);
+    va_end(pvar);
+}
+
+void ss_perror (sci_idx, code, msg) /* for compatibility */
+    int sci_idx;
+    long code;
+    char const *msg;
+{
+    ss_error (sci_idx, code, "%s", msg);
+}
diff --git a/krb5-1-6/src/util/ss/execute_cmd.c b/krb5-1-6/src/util/ss/execute_cmd.c
new file mode 100644
index 000000000..3f684052c
--- /dev/null
+++ b/krb5-1-6/src/util/ss/execute_cmd.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright 1987, 1988, 1989 by Massachusetts Institute of Technology
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include "ss_internal.h"
+#include "copyright.h"
+#include <stdio.h>
+
+
+/*
+ * get_request(tbl, idx)
+ *
+ * Function:
+ *      Gets the idx'th request from the request table pointed to
+ *      by tbl.
+ * Arguments:
+ *      tbl (ss_request_table *)
+ *              pointer to request table
+ *      idx (int)
+ *              index into table
+ * Returns:
+ *      (ss_request_entry *)
+ *              pointer to request table entry
+ * Notes:
+ *      Has been replaced by a macro.
+ */
+
+#ifdef __SABER__
+/* sigh.  saber won't deal with pointer-to-const-struct */
+static struct _ss_request_entry * get_request (tbl, idx)
+    ss_request_table * tbl;
+    int idx;
+{
+    struct _ss_request_table *tbl1 = (struct _ss_request_table *) tbl;
+    struct _ss_request_entry *e = (struct _ss_request_entry *) tbl1->requests;
+    return e + idx;
+}
+#else
+#define get_request(tbl,idx)    ((tbl) -> requests + (idx))
+#endif
+
+/*
+ * check_request_table(rqtbl, argc, argv, sci_idx)
+ *
+ * Function:
+ *      If the command string in argv[0] is in the request table, execute
+ *      the commands and return error code 0.  Otherwise, return error
+ *      code ss_et_command_not_found.
+ * Arguments:
+ *      rqtbl (ss_request_table *)
+ *              pointer to request table
+ *      argc (int)
+ *              number of elements in argv[]
+ *      argv (char *[])
+ *              argument string array
+ *      sci_idx (int)
+ *              ss-internal index for subsystem control info structure
+ * Returns:
+ *      (int)
+ *              zero if command found, ss_et_command_not_found otherwise
+ * Notes:
+ */
+
+static int check_request_table (rqtbl, argc, argv, sci_idx)
+    register ss_request_table *rqtbl;
+    int argc;
+    char *argv[];
+    int sci_idx;
+{
+#ifdef __SABER__
+    struct _ss_request_entry *request;
+#else
+    register ss_request_entry *request;
+#endif
+    register ss_data *info;
+    register char const * const * name;
+    char *string = argv[0];
+    int i;
+
+    info = ss_info(sci_idx);
+    info->argc = argc;
+    info->argv = argv;
+    for (i = 0; (request = get_request(rqtbl, i))->command_names; i++) {
+	for (name = request->command_names; *name; name++)
+	    if (!strcmp(*name, string)) {
+		info->current_request = request->command_names[0];
+		(request->function)(argc, (const char *const *) argv,
+				    sci_idx,info->info_ptr);
+		info->current_request = (char *)NULL;
+		return(0);
+	    }
+    }
+    return(SS_ET_COMMAND_NOT_FOUND);
+}
+
+/*
+ * really_execute_command(sci_idx, argc, argv)
+ *
+ * Function:
+ *      Fills in the argc, argv values in the subsystem entry and
+ *      call the appropriate routine.
+ * Arguments:
+ *      sci_idx (int)
+ *              ss-internal index for subsystem control info structure
+ *      argc (int)
+ *              number of arguments in argument list
+ *      argv (char **[])
+ *              pointer to parsed argument list (may be reallocated
+ *              on abbrev expansion)
+ *
+ * Returns:
+ *      (int)
+ *              Zero if successful, ss_et_command_not_found otherwise.
+ * Notes:
+ */
+
+static int really_execute_command (sci_idx, argc, argv)
+    int sci_idx;
+    int argc;
+    char **argv[];
+{
+    register ss_request_table **rqtbl;
+    register ss_data *info;
+
+    info = ss_info(sci_idx);
+
+    for (rqtbl = info->rqt_tables; *rqtbl; rqtbl++) {
+        if (check_request_table (*rqtbl, argc, *argv, sci_idx) == 0)
+            return(0);
+    }
+    return(SS_ET_COMMAND_NOT_FOUND);
+}
+
+/*
+ * ss_execute_command(sci_idx, argv)
+ *
+ * Function:
+ *	Executes a parsed command list within the subsystem.
+ * Arguments:
+ *	sci_idx (int)
+ *		ss-internal index for subsystem control info structure
+ *	argv (char *[])
+ *		parsed argument list
+ * Returns:
+ *	(int)
+ *		Zero if successful, ss_et_command_not_found otherwise.
+ * Notes:
+ */
+
+int
+ss_execute_command(sci_idx, argv)
+	int sci_idx;
+	register char *argv[];
+{
+	register int i, argc;
+	char **argp;
+
+	argc = 0;
+	for (argp = argv; *argp; argp++)
+		argc++;
+	argp = (char **)malloc((argc+1)*sizeof(char *));
+	for (i = 0; i <= argc; i++)
+		argp[i] = argv[i];
+	i = really_execute_command(sci_idx, argc, &argp);
+	free(argp);
+	return(i);
+}
+
+/*
+ * ss_execute_line(sci_idx, line_ptr)
+ *
+ * Function:
+ *      Parses and executes a command line within a subsystem.
+ * Arguments:
+ *      sci_idx (int)
+ *              ss-internal index for subsystem control info structure
+ *      line_ptr (char *)
+ *              Pointer to command line to be parsed.
+ * Returns:
+ *      (int)
+ *      	Error code.
+ * Notes:
+ */
+
+int ss_execute_line (sci_idx, line_ptr)
+    int sci_idx;
+    char *line_ptr;
+{
+    char **argv;
+    int argc, ret;
+
+    /* flush leading whitespace */
+    while (line_ptr[0] == ' ' || line_ptr[0] == '\t')
+        line_ptr++;
+
+    /* check if it should be sent to operating system for execution */
+    if (*line_ptr == '!') {
+        if (ss_info(sci_idx)->flags.escape_disabled)
+            return SS_ET_ESCAPE_DISABLED;
+        else {
+            line_ptr++;
+            system(line_ptr);
+	    return 0;
+        }
+    }
+
+    /* parse it */
+    argv = ss_parse(sci_idx, line_ptr, &argc);
+    if (argc == 0)
+        return 0;
+
+    /* look it up in the request tables, execute if found */
+    ret = really_execute_command (sci_idx, argc, &argv);
+
+    free(argv);
+
+    return(ret);
+}
diff --git a/krb5-1-6/src/util/ss/help.c b/krb5-1-6/src/util/ss/help.c
new file mode 100644
index 000000000..2752f40ed
--- /dev/null
+++ b/krb5-1-6/src/util/ss/help.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/file.h>
+#include <fcntl.h>	/* just for O_* */
+#include <sys/wait.h>
+#include "ss_internal.h"
+#include "copyright.h"
+
+
+void ss_help (argc, argv, sci_idx, info_ptr)
+    int argc;
+    char const * const *argv;
+    int sci_idx;
+    pointer info_ptr;
+{
+    char buffer[MAXPATHLEN];
+    char const *request_name;
+    int code;
+    int fd, child;
+    register int idx;
+    register ss_data *info;
+
+    request_name = ss_current_request(sci_idx, &code);
+    if (code != 0) {
+	ss_perror(sci_idx, code, "");
+	return;		/* no ss_abort_line, if invalid invocation */
+    }
+    if (argc == 1) {
+	ss_list_requests(argc, argv, sci_idx, info_ptr);
+	return;
+    }
+    else if (argc != 2) {
+	/* should do something better than this */
+	sprintf(buffer, "usage:\n\t%s [topic|command]\nor\t%s\n",
+		request_name, request_name);
+	ss_perror(sci_idx, 0, buffer);
+	return;
+    }
+    info = ss_info(sci_idx);
+    if (info->info_dirs == (char **)NULL) {
+	ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
+	return;
+    }
+    if (info->info_dirs[0] == (char *)NULL) {
+	ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
+	return;
+    }
+    for (idx = 0; info->info_dirs[idx] != (char *)NULL; idx++) {
+	(void) strncpy(buffer, info->info_dirs[idx], sizeof(buffer) - 1);
+	buffer[sizeof(buffer) - 1] = '\0';
+	(void) strncat(buffer, "/", sizeof(buffer) - 1 - strlen(buffer));
+	(void) strncat(buffer, argv[1], sizeof(buffer) - 1 - strlen(buffer));
+	(void) strncat(buffer, ".info", sizeof(buffer) - 1 - strlen(buffer));
+	if ((fd = open(&buffer[0], O_RDONLY)) >= 0) goto got_it;
+    }
+    if ((fd = open(&buffer[0], O_RDONLY)) < 0) {
+	char buf[MAXPATHLEN];
+	strncpy(buf, "No info found for ", sizeof(buf) - 1);
+	buf[sizeof(buf) - 1] = '\0';
+	strncat(buf, argv[1], sizeof(buf) - 1 - strlen(buf));
+	ss_perror(sci_idx, 0, buf);
+	return;
+    }
+got_it:
+    switch (child = fork()) {
+    case -1:
+	ss_perror(sci_idx, errno, "Can't fork for pager");
+	return;
+    case 0:
+	(void) dup2(fd, 0); /* put file on stdin */
+	ss_page_stdin();
+    default:
+	(void) close(fd); /* what can we do if it fails? */
+#ifdef WAIT_USES_INT
+	while (wait((int *)NULL) != child) {
+#else
+	while (wait((union wait *)NULL) != child) {
+#endif
+	    /* do nothing if wrong pid */
+	};
+    }
+}
+
+#ifndef USE_DIRENT_H
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#endif
+
+void ss_add_info_dir(sci_idx, info_dir, code_ptr)
+    int sci_idx;
+    char *info_dir;
+    int *code_ptr;
+{
+    register ss_data *info;
+    DIR *d;
+    int n_dirs;
+    register char **dirs;
+
+    info = ss_info(sci_idx);
+    if (info_dir == NULL && *info_dir) {
+	*code_ptr = SS_ET_NO_INFO_DIR;
+	return;
+    }
+    if ((d = opendir(info_dir)) == (DIR *)NULL) {
+	*code_ptr = errno;
+	return;
+    }
+    closedir(d);
+    dirs = info->info_dirs;
+    for (n_dirs = 0; dirs[n_dirs] != (char *)NULL; n_dirs++)
+	;		/* get number of non-NULL dir entries */
+    dirs = (char **)realloc((char *)dirs,
+			    (unsigned)(n_dirs + 2)*sizeof(char *));
+    if (dirs == (char **)NULL) {
+	info->info_dirs = (char **)NULL;
+	*code_ptr = errno;
+	return;
+    }
+    info->info_dirs = dirs;
+    dirs[n_dirs + 1] = (char *)NULL;
+    dirs[n_dirs] = malloc((unsigned)strlen(info_dir)+1);
+    strcpy(dirs[n_dirs], info_dir);
+    *code_ptr = 0;
+}
+
+void ss_delete_info_dir(sci_idx, info_dir, code_ptr)
+    int sci_idx;
+    char *info_dir;
+    int *code_ptr;
+{
+    register char **i_d;
+    register char **info_dirs;
+
+    info_dirs = ss_info(sci_idx)->info_dirs;
+    for (i_d = info_dirs; *i_d; i_d++) {
+	if (!strcmp(*i_d, info_dir)) {
+	    while (*i_d) {
+		*i_d = *(i_d+1);
+		i_d++;
+	    }
+	    *code_ptr = 0;
+	    return;
+	}
+    }
+    *code_ptr = SS_ET_NO_INFO_DIR;
+}
diff --git a/krb5-1-6/src/util/ss/invocation.c b/krb5-1-6/src/util/ss/invocation.c
new file mode 100644
index 000000000..5e1a2565b
--- /dev/null
+++ b/krb5-1-6/src/util/ss/invocation.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+#include "ss_internal.h"
+#include "copyright.h"
+#define	size	sizeof(ss_data *)
+
+
+int ss_create_invocation(subsystem_name, version_string, info_ptr,
+			 request_table_ptr, code_ptr)
+	char *subsystem_name, *version_string;
+	char *info_ptr;
+	ss_request_table *request_table_ptr;
+	int *code_ptr;
+{
+	register int sci_idx;
+	register ss_data *new_table;
+	register ss_data **table;
+
+	*code_ptr = 0;
+	table = _ss_table;
+	new_table = (ss_data *) malloc(sizeof(ss_data));
+
+	if (table == (ss_data **) NULL) {
+		table = (ss_data **) malloc(2 * size);
+		table[0] = table[1] = (ss_data *)NULL;
+	}
+	initialize_ss_error_table ();
+
+	for (sci_idx = 1; table[sci_idx] != (ss_data *)NULL; sci_idx++)
+		;
+	table = (ss_data **) realloc((char *)table,
+				     ((unsigned)sci_idx+2)*size);
+	table[sci_idx+1] = (ss_data *) NULL;
+	table[sci_idx] = new_table;
+
+	new_table->subsystem_name = subsystem_name;
+	new_table->subsystem_version = version_string;
+	new_table->argv = (char **)NULL;
+	new_table->current_request = (char *)NULL;
+	new_table->info_dirs = (char **)malloc(sizeof(char *));
+	*new_table->info_dirs = (char *)NULL;
+	new_table->info_ptr = info_ptr;
+	new_table->prompt = malloc((unsigned)strlen(subsystem_name)+4);
+	strcpy(new_table->prompt, subsystem_name);
+	strcat(new_table->prompt, ":  ");
+#ifdef silly
+	new_table->abbrev_info = ss_abbrev_initialize("/etc/passwd", code_ptr);
+#else
+	new_table->abbrev_info = NULL;
+#endif
+	new_table->flags.escape_disabled = 0;
+	new_table->flags.abbrevs_disabled = 0;
+	new_table->rqt_tables =
+		(ss_request_table **) calloc(2, sizeof(ss_request_table *));
+	*(new_table->rqt_tables) = request_table_ptr;
+	*(new_table->rqt_tables+1) = (ss_request_table *) NULL;
+	_ss_table = table;
+	return(sci_idx);
+}
+
+void
+ss_delete_invocation(sci_idx)
+	int sci_idx;
+{
+	register ss_data *t;
+	int ignored_code;
+
+	t = ss_info(sci_idx);
+	free(t->prompt);
+	free(t->rqt_tables);
+	while(t->info_dirs[0] != (char *)NULL)
+		ss_delete_info_dir(sci_idx, t->info_dirs[0], &ignored_code);
+	free((char *)t->info_dirs);
+	free((char *)t);
+}
diff --git a/krb5-1-6/src/util/ss/list_rqs.c b/krb5-1-6/src/util/ss/list_rqs.c
new file mode 100644
index 000000000..045a0c82b
--- /dev/null
+++ b/krb5-1-6/src/util/ss/list_rqs.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+#include "copyright.h"
+#include "ss_internal.h"
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/wait.h>
+
+#ifdef lint     /* "lint returns a value which is sometimes ignored" */
+#define DONT_USE(x)     x=x;
+#else /* !lint */
+#define DONT_USE(x)     ;
+#endif /* lint */
+
+static char const twentyfive_spaces[26] =
+    "                         ";
+static char const NL[2] = "\n";
+
+void
+ss_list_requests(argc, argv, sci_idx, info_ptr)
+    int argc;
+    const char * const *argv;
+    int sci_idx;
+#ifdef __STDC__
+    void *info_ptr;
+#else
+    char *info_ptr;
+#endif
+{
+    register ss_request_entry *entry;
+    register char const * const *name;
+    register int spacing;
+    register ss_request_table **table;
+
+    char buffer[BUFSIZ];
+    FILE *output;
+    int fd;
+#ifdef POSIX_SIGNALS
+    struct sigaction nsig, osig;
+    sigset_t nmask, omask;
+#else
+    int mask;
+    RETSIGTYPE (*func)();
+#endif
+#ifndef WAIT_USES_INT
+    union wait waitb;
+#else
+    int waitb;
+#endif
+
+    DONT_USE(argc);
+    DONT_USE(argv);
+
+#ifdef POSIX_SIGNALS
+    sigemptyset(&nmask);
+    sigaddset(&nmask, SIGINT);
+    sigprocmask(SIG_BLOCK, &nmask, &omask);
+    
+    nsig.sa_handler = SIG_IGN;
+    sigemptyset(&nsig.sa_mask);
+    nsig.sa_flags = 0;
+    sigaction(SIGINT, &nsig, &osig);
+#else
+    mask = sigblock(sigmask(SIGINT));
+    func = signal(SIGINT, SIG_IGN);
+#endif
+
+    fd = ss_pager_create();
+    output = fdopen(fd, "w");
+
+#ifdef POSIX_SIGNALS
+    sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+#else
+    sigsetmask(mask);
+#endif
+
+    fprintf (output, "Available %s requests:\n\n",
+	     ss_info (sci_idx) -> subsystem_name);
+
+    for (table = ss_info(sci_idx)->rqt_tables; *table; table++) {
+        entry = (*table)->requests;
+        for (; entry->command_names; entry++) {
+            spacing = -2;
+            buffer[0] = '\0';
+            if (entry->flags & SS_OPT_DONT_LIST)
+                continue;
+            buffer[sizeof(buffer) - 1] = '\0';
+            for (name = entry->command_names; *name; name++) {
+                register int len = strlen(*name);
+                strncat(buffer, *name, sizeof(buffer) - 1 - strlen(buffer));
+                spacing += len + 2;
+                if (name[1]) {
+                    strncat(buffer, ", ", sizeof(buffer) - 1 - strlen(buffer));
+                }
+            }
+            if (spacing > 23) {
+                strncat(buffer, NL, sizeof(buffer) - 1 - strlen(buffer));
+                fputs(buffer, output);
+                spacing = 0;
+                buffer[0] = '\0';
+            }
+            strncat(buffer, twentyfive_spaces, sizeof(buffer) - 1 - (25-spacing));
+            strncpy(buffer + 25, entry->info_string, sizeof(buffer) - 1 - 25);
+            strncat(buffer, NL, sizeof(buffer) - 1 - strlen(buffer));
+            fputs(buffer, output);
+        }
+    }
+    fclose(output);
+#ifndef NO_FORK
+    wait(&waitb);
+#endif
+#ifdef POSIX_SIGNALS
+    sigaction(SIGINT, &osig, (struct sigaction *)0);
+#else
+    (void) signal(SIGINT, func);
+#endif
+}
diff --git a/krb5-1-6/src/util/ss/listen.c b/krb5-1-6/src/util/ss/listen.c
new file mode 100644
index 000000000..ae9700757
--- /dev/null
+++ b/krb5-1-6/src/util/ss/listen.c
@@ -0,0 +1,169 @@
+/*
+ * Listener loop for subsystem library libss.a.
+ *
+ *	util/ss/listen.c
+ * 
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "copyright.h"
+#include "ss_internal.h"
+#include <stdio.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/param.h>
+
+static ss_data *current_info;
+static jmp_buf listen_jmpb;
+
+static RETSIGTYPE print_prompt()
+{
+    struct termios termbuf;
+
+    if (tcgetattr(STDIN_FILENO, &termbuf) == 0) {
+	termbuf.c_lflag |= ICANON|ISIG|ECHO;
+	tcsetattr(STDIN_FILENO, TCSANOW, &termbuf);
+    }
+    (void) fputs(current_info->prompt, stdout);
+    (void) fflush(stdout);
+}
+
+static RETSIGTYPE listen_int_handler(signo)
+    int signo;
+{
+    putc('\n', stdout);
+    longjmp(listen_jmpb, 1);
+}
+
+int ss_listen (sci_idx)
+    int sci_idx;
+{
+    register char *cp;
+    register ss_data *info;
+    char input[BUFSIZ];
+    char buffer[BUFSIZ];
+    char *volatile end = buffer;
+    int code;
+    jmp_buf old_jmpb;
+    ss_data *old_info = current_info;
+#ifdef POSIX_SIGNALS
+    struct sigaction isig, csig, nsig, osig;
+    sigset_t nmask, omask;
+#else
+    register RETSIGTYPE (*sig_cont)();
+    RETSIGTYPE (*sig_int)(), (*old_sig_cont)();
+    int mask;
+#endif
+    
+    current_info = info = ss_info(sci_idx);
+    info->abort = 0;
+
+#ifdef POSIX_SIGNALS
+    csig.sa_handler = (RETSIGTYPE (*)())0;
+    sigemptyset(&nmask);
+    sigaddset(&nmask, SIGINT);
+    sigprocmask(SIG_BLOCK, &nmask, &omask);
+#else
+    sig_cont = (RETSIGTYPE (*)())0;
+    mask = sigblock(sigmask(SIGINT));
+#endif
+
+    memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
+
+#ifdef POSIX_SIGNALS
+    nsig.sa_handler = listen_int_handler;
+    sigemptyset(&nsig.sa_mask);
+    nsig.sa_flags = 0;
+    sigaction(SIGINT, &nsig, &isig);
+#else
+    sig_int = signal(SIGINT, listen_int_handler);
+#endif
+
+    setjmp(listen_jmpb);
+
+#ifdef POSIX_SIGNALS
+    sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+#else
+    (void) sigsetmask(mask);
+#endif
+    while(!info->abort) {
+	print_prompt();
+	*end = '\0';
+#ifdef POSIX_SIGNALS
+	nsig.sa_handler = listen_int_handler;	/* fgets is not signal-safe */
+	osig = csig;
+	sigaction(SIGCONT, &nsig, &csig);
+	if ((RETSIGTYPE (*)())csig.sa_handler==(RETSIGTYPE (*)())listen_int_handler)
+	    csig = osig;
+#else
+	old_sig_cont = sig_cont;
+	sig_cont = signal(SIGCONT, print_prompt);
+	if (sig_cont == print_prompt)
+	    sig_cont = old_sig_cont;
+#endif
+	if (fgets(input, BUFSIZ, stdin) != input) {
+	    code = SS_ET_EOF;
+	    goto egress;
+	}
+	cp = strchr(input, '\n');
+	if (cp) {
+	    *cp = '\0';
+	    if (cp == input)
+		continue;
+	}
+#ifdef POSIX_SIGNALS
+	sigaction(SIGCONT, &csig, (struct sigaction *)0);
+#else
+	(void) signal(SIGCONT, sig_cont);
+#endif
+	for (end = input; *end; end++)
+	    ;
+
+	code = ss_execute_line (sci_idx, input);
+	if (code == SS_ET_COMMAND_NOT_FOUND) {
+	    register char *c = input;
+	    while (*c == ' ' || *c == '\t')
+		c++;
+	    cp = strchr (c, ' ');
+	    if (cp)
+		*cp = '\0';
+	    cp = strchr (c, '\t');
+	    if (cp)
+		*cp = '\0';
+	    ss_error (sci_idx, 0,
+		    "Unknown request \"%s\".  Type \"?\" for a request list.",
+		       c);
+	}
+    }
+    code = 0;
+egress:
+#ifdef POSIX_SIGNALS
+    sigaction(SIGINT, &isig, (struct sigaction *)0);
+#else
+    (void) signal(SIGINT, sig_int);
+#endif
+    memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
+    current_info = old_info;
+    return code;
+}
+
+void ss_abort_subsystem(sci_idx, code)
+    int sci_idx;
+    int code;
+{
+    ss_info(sci_idx)->abort = 1;
+    ss_info(sci_idx)->exit_status = code;
+    
+}
+
+void ss_quit(argc, argv, sci_idx, infop)
+    int argc;
+    char const * const *argv;
+    int sci_idx;
+    pointer infop;
+{
+    ss_abort_subsystem(sci_idx, 0);
+}
diff --git a/krb5-1-6/src/util/ss/mit-sipb-copyright.h b/krb5-1-6/src/util/ss/mit-sipb-copyright.h
new file mode 100644
index 000000000..d6d5f1edc
--- /dev/null
+++ b/krb5-1-6/src/util/ss/mit-sipb-copyright.h
@@ -0,0 +1,22 @@
+/*
+
+Copyright 1987 by the Student Information Processing Board
+	of the Massachusetts Institute of Technology
+
+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 names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+Furthermore if you modify this software you must label
+your software as modified software and not distribute it in such a
+fashion that it might be confused with the original M.I.T. software.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose.  It is
+provided "as is" without express or implied warranty.
+
+*/
+
diff --git a/krb5-1-6/src/util/ss/mk_cmds.c b/krb5-1-6/src/util/ss/mk_cmds.c
new file mode 100644
index 000000000..8e29ccfb3
--- /dev/null
+++ b/krb5-1-6/src/util/ss/mk_cmds.c
@@ -0,0 +1,102 @@
+/*
+ * make_commands.c
+ *
+ * util/ss/mk_cmds.c
+ *
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "copyright.h"
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <string.h>
+#include "ss_internal.h"
+
+static const char copyright[] =
+    "Copyright 1987 by MIT Student Information Processing Board";
+
+extern pointer malloc (unsigned);
+extern char *last_token;
+extern FILE *output_file;
+
+extern FILE *yyin, *yyout;
+#ifndef NO_YYLINENO
+extern int yylineno;
+#endif
+
+int main(argc, argv)
+    int argc;
+    char **argv;
+{
+    char c_file[MAXPATHLEN];
+    int result;
+    char *path, *p, *q;
+
+    if (argc != 2) {
+	fputs("Usage: ", stderr);
+	fputs(argv[0], stderr);
+	fputs("cmdtbl.ct\n", stderr);
+	exit(1);
+    }
+
+    path = malloc(strlen(argv[1])+4); /* extra space to add ".ct" */
+    strcpy(path, argv[1]);
+    p = strrchr(path, '/');
+    if (p == (char *)NULL)
+	p = path;
+    else
+	p++;
+    p = strrchr(p, '.');
+    if (p == (char *)NULL || strcmp(p, ".ct"))
+	strcat(path, ".ct");
+    yyin = fopen(path, "r");
+    if (!yyin) {
+	perror(path);
+	exit(1);
+    }
+
+    p = strrchr(path, '.');
+    *p = '\0';
+    q = rindex(path, '/');
+    strncpy(c_file, (q) ? q + 1 : path, sizeof(c_file) - 1);
+    c_file[sizeof(c_file) - 1] = '\0';
+    strncat(c_file, ".c", sizeof(c_file) - 1 - strlen(c_file));
+    *p = '.';
+
+    output_file = fopen(c_file, "w+");
+    if (!output_file) {
+	perror(c_file);
+	exit(1);
+    }
+
+    fputs("/* ", output_file);
+    fputs(c_file, output_file);
+    fputs(" - automatically generated from ", output_file);
+    fputs(path, output_file);
+    fputs(" */\n", output_file);
+    fputs("#include <ss/ss.h>\n\n", output_file);
+    fputs("#ifndef __STDC__\n#define const\n#endif\n\n", output_file);
+    /* parse it */
+    result = yyparse();
+    /* put file descriptors back where they belong */
+    fclose(yyin);		/* bye bye input file */
+    fclose(output_file);	/* bye bye output file */
+
+    return result;
+}
+
+yyerror(s)
+    char *s;
+{
+    fputs(s, stderr);
+#ifdef NO_YYLINENO
+    fprintf(stderr, "\nLast token was '%s'\n", last_token);
+#else
+    fprintf(stderr, "\nLine %d; last token was '%s'\n",
+	    yylineno, last_token);
+#endif
+}
diff --git a/krb5-1-6/src/util/ss/mk_cmds.sh b/krb5-1-6/src/util/ss/mk_cmds.sh
new file mode 100755
index 000000000..aaf3256b5
--- /dev/null
+++ b/krb5-1-6/src/util/ss/mk_cmds.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+#
+
+DIR=@DIR@
+AWK=@AWK@
+SED=@SED@
+
+set -e
+FILE=$1
+ROOT=`echo $1 | ${SED} -e s/.ct$//`
+BASE=`echo $ROOT | ${SED} -e 's;.*/;;'`
+TMP=ct$$.c
+
+if [ ! -r ${FILE} ] ; then
+	echo mk_cmds: ${FILE} not found
+	exit 1
+fi
+
+${SED} -f ${DIR}/ct_c.sed  ${FILE} \
+	| ${AWK} -f ${DIR}/ct_c.awk rootname=${ROOT} outfile=${TMP} -
+
+if grep "^#__ERROR_IN_FILE" ${TMP} > /dev/null; then
+	rm ${TMP}
+	exit 1
+else
+	mv ${TMP} ${BASE}.c
+	exit 0
+fi
diff --git a/krb5-1-6/src/util/ss/options.c b/krb5-1-6/src/util/ss/options.c
new file mode 100644
index 000000000..dd648b01a
--- /dev/null
+++ b/krb5-1-6/src/util/ss/options.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+#include "copyright.h"
+#include <stdio.h>
+#include "ss.h"
+
+struct option {
+     char *text;
+     long value;
+};
+
+static struct option options[] = {
+     { "dont_list", SS_OPT_DONT_LIST },
+     { "^list", SS_OPT_DONT_LIST },
+     { "dont_summarize", SS_OPT_DONT_SUMMARIZE },
+     { "^summarize", SS_OPT_DONT_SUMMARIZE },
+     { (char *)NULL, 0 }
+};
+
+long
+flag_val(string)
+     register char *string;
+{
+     register struct option *opt;
+     for (opt = options; opt->text; opt++)
+	  if (!strcmp(opt->text, string))
+	       return(opt->value);
+     return(0);
+}
diff --git a/krb5-1-6/src/util/ss/pager.c b/krb5-1-6/src/util/ss/pager.c
new file mode 100644
index 000000000..c8a52f079
--- /dev/null
+++ b/krb5-1-6/src/util/ss/pager.c
@@ -0,0 +1,108 @@
+/*
+ * Pager: Routines to create a "more" running out of a particular file
+ * descriptor.
+ *
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "ss_internal.h"
+#include "copyright.h"
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <signal.h>
+
+static char MORE[] = "more";
+extern char *_ss_pager_name;
+extern char *getenv();
+
+/*
+ * this needs a *lot* of work....
+ *
+ * run in same process
+ * handle SIGINT sensibly
+ * allow finer control -- put-page-break-here
+ */
+void ss_page_stdin();
+
+#ifndef NO_FORK
+int ss_pager_create() 
+{
+	int filedes[2];
+     
+	if (pipe(filedes) != 0)
+		return(-1);
+
+	switch((int) fork()) {
+	case -1:
+		return(-1);
+	case 0:
+		/*
+		 * Child; dup read half to 0, close all but 0, 1, and 2
+		 */
+		if (dup2(filedes[0], 0) == -1)
+			exit(1);
+		ss_page_stdin();
+	default:
+		/*
+		 * Parent:  close "read" side of pipe, return
+		 * "write" side.
+		 */
+		(void) close(filedes[0]);
+		return(filedes[1]);
+	}
+}
+#else /* don't fork */
+int ss_pager_create()
+{
+    int fd;
+    fd = open("/dev/tty", O_WRONLY, 0);
+    return fd;
+}
+#endif
+
+void ss_page_stdin()
+{
+	int i;
+#ifdef POSIX_SIGNALS
+	struct sigaction sa;
+	sigset_t mask;
+#endif
+	for (i = 3; i < 32; i++)
+		(void) close(i);
+#ifdef POSIX_SIGNALS
+	sa.sa_handler = SIG_DFL;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	sigaction(SIGINT, &sa, (struct sigaction *)0);
+#else
+	(void) signal(SIGINT, SIG_DFL);
+#endif
+	{
+#ifdef POSIX_SIGNALS
+		sigemptyset(&mask);
+		sigaddset(&mask, SIGINT);
+		sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)0);
+#else
+		int mask = sigblock(0);
+		mask &= ~sigmask(SIGINT);
+		sigsetmask(mask);
+#endif
+	}
+	if (_ss_pager_name == (char *)NULL) {
+		if ((_ss_pager_name = getenv("PAGER")) == (char *)NULL)
+			_ss_pager_name = MORE;
+	}
+	(void) execlp(_ss_pager_name, _ss_pager_name, (char *) NULL);
+	{
+		/* minimal recovery if pager program isn't found */
+		char buf[80];
+		register int n;
+		while ((n = read(0, buf, 80)) > 0)
+			write(1, buf, (unsigned) n);
+	}
+	exit(errno);
+}
diff --git a/krb5-1-6/src/util/ss/parse.c b/krb5-1-6/src/util/ss/parse.c
new file mode 100644
index 000000000..382a61a40
--- /dev/null
+++ b/krb5-1-6/src/util/ss/parse.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright info, see copyright.h.
+ */
+
+#include "ss_internal.h"
+#include "copyright.h"
+#include <errno.h>
+
+enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
+
+/*
+ * parse(line_ptr, argc_ptr)
+ *
+ * Function:
+ *      Parses line, dividing at whitespace, into tokens, returns
+ *      the "argc" and "argv" values.
+ * Arguments:
+ *      line_ptr (char *)
+ *              Pointer to text string to be parsed.
+ *      argc_ptr (int *)
+ *              Where to put the "argc" (number of tokens) value.
+ * Returns:
+ *      argv (char **)
+ *              Series of pointers to parsed tokens.
+ */
+
+#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
+					 (unsigned)(n+2)*sizeof(char*))
+
+char **ss_parse (sci_idx, line_ptr, argc_ptr)
+    int sci_idx;
+    register char *line_ptr;
+    int *argc_ptr;
+{
+    register char **argv, *cp;
+    register int argc;
+    register enum parse_mode parse_mode;
+
+    argv = (char **) malloc (sizeof(char *));
+    if (argv == (char **)NULL) {
+	ss_error(sci_idx, errno, "Can't allocate storage");
+	*argc_ptr = 0;
+	return(argv);
+    }
+    *argv = (char *)NULL;
+
+    argc = 0;
+
+    parse_mode = WHITESPACE;	/* flushing whitespace */
+    cp = line_ptr;		/* cp is for output */
+    while (1) {
+#ifdef DEBUG
+	{
+	    printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
+	}
+#endif
+	while (parse_mode == WHITESPACE) {
+	    if (*line_ptr == '\0')
+		goto end_of_line;
+	    if (*line_ptr == ' ' || *line_ptr == '\t') {
+		line_ptr++;
+		continue;
+	    }
+	    if (*line_ptr == '"') {
+		/* go to quoted-string mode */
+		parse_mode = QUOTED_STRING;
+		cp = line_ptr++;
+		argv = NEW_ARGV (argv, argc);
+		argv[argc++] = cp;
+		argv[argc] = NULL;
+	    }
+	    else {
+		/* random-token mode */
+		parse_mode = TOKEN;
+		cp = line_ptr;
+		argv = NEW_ARGV (argv, argc);
+		argv[argc++] = line_ptr;
+		argv[argc] = NULL;
+	    }
+	}
+	while (parse_mode == TOKEN) {
+	    if (*line_ptr == '\0') {
+		*cp++ = '\0';
+		goto end_of_line;
+	    }
+	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
+		*cp++ = '\0';
+		line_ptr++;
+		parse_mode = WHITESPACE;
+	    }
+	    else if (*line_ptr == '"') {
+		line_ptr++;
+		parse_mode = QUOTED_STRING;
+	    }
+	    else {
+		*cp++ = *line_ptr++;
+	    }
+	}
+	while (parse_mode == QUOTED_STRING) {
+	    if (*line_ptr == '\0') {
+		ss_error (sci_idx, 0,
+			  "Unbalanced quotes in command line");
+		free (argv);
+		*argc_ptr = 0;
+		return NULL;
+	    }
+	    else if (*line_ptr == '"') {
+		if (*++line_ptr == '"') {
+		    *cp++ = '"';
+		    line_ptr++;
+		}
+		else {
+		    parse_mode = TOKEN;
+		}
+	    }
+	    else {
+		*cp++ = *line_ptr++;
+	    }
+	}
+    }
+end_of_line:
+    *argc_ptr = argc;
+#ifdef DEBUG
+    {
+	int i;
+	printf ("argc = %d\n", argc);
+	for (i = 0; i <= argc; i++)
+	    printf ("\targv[%2d] = `%s'\n", i,
+		    argv[i] ? argv[i] : "<NULL>");
+    }
+#endif
+    return(argv);
+}
diff --git a/krb5-1-6/src/util/ss/prompt.c b/krb5-1-6/src/util/ss/prompt.c
new file mode 100644
index 000000000..0751baeba
--- /dev/null
+++ b/krb5-1-6/src/util/ss/prompt.c
@@ -0,0 +1,28 @@
+/*
+ * prompt.c: Routines for retrieving and setting a prompt.
+ *
+ * util/ss/prompt.c
+ *
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "copyright.h"
+#include <stdio.h>
+#include "ss_internal.h"
+
+void
+ss_set_prompt(sci_idx, new_prompt)
+     int sci_idx;
+     char *new_prompt;
+{
+     ss_info(sci_idx)->prompt = new_prompt;
+}
+
+char *
+ss_get_prompt(sci_idx)
+     int sci_idx;
+{
+     return(ss_info(sci_idx)->prompt);
+}
diff --git a/krb5-1-6/src/util/ss/request_tbl.c b/krb5-1-6/src/util/ss/request_tbl.c
new file mode 100644
index 000000000..46eb3a0ad
--- /dev/null
+++ b/krb5-1-6/src/util/ss/request_tbl.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include "copyright.h"
+#include "ss_internal.h"
+
+#define ssrt ss_request_table	/* for some readable code... */
+
+void
+ss_add_request_table(sci_idx, rqtbl_ptr, position, code_ptr)
+	int sci_idx;
+	ssrt *rqtbl_ptr;
+	int position;		/* 1 -> becomes second... */
+	int *code_ptr;
+{
+	register ss_data *info;
+	register int i, size;
+
+	info = ss_info(sci_idx);
+	for (size=0; info->rqt_tables[size] != (ssrt *)NULL; size++)
+		;
+	/* size == C subscript of NULL == #elements */
+	size += 2;		/* new element, and NULL */
+	info->rqt_tables = (ssrt **)realloc(info->rqt_tables,
+					    size*sizeof(ssrt));
+	if (info->rqt_tables == (ssrt **)NULL) {
+		*code_ptr = errno;
+		return;
+	}
+	if (position > size - 2)
+		position = size - 2;
+
+	if (size > 1)
+		for (i = size - 2; i >= position; i--)
+			info->rqt_tables[i+1] = info->rqt_tables[i];
+
+	info->rqt_tables[position] = rqtbl_ptr;
+	info->rqt_tables[size-1] = (ssrt *)NULL;
+	*code_ptr = 0;
+}
+
+void
+ss_delete_request_table(sci_idx, rqtbl_ptr, code_ptr)
+     int sci_idx;
+     ssrt *rqtbl_ptr;
+     int *code_ptr;
+{
+     register ss_data *info;
+     register ssrt **rt1, **rt2;
+
+     *code_ptr = SS_ET_TABLE_NOT_FOUND;
+     info = ss_info(sci_idx);
+     rt1 = info->rqt_tables;
+     for (rt2 = rt1; *rt1; rt1++) {
+	  if (*rt1 != rqtbl_ptr) {
+	       *rt2++ = *rt1;
+	       *code_ptr = 0;
+	  }
+     }
+     *rt2 = (ssrt *)NULL;
+     return;
+}
diff --git a/krb5-1-6/src/util/ss/requests.c b/krb5-1-6/src/util/ss/requests.c
new file mode 100644
index 000000000..ccd0f792c
--- /dev/null
+++ b/krb5-1-6/src/util/ss/requests.c
@@ -0,0 +1,47 @@
+/*
+ * Various minor routines...
+ *
+ * Copyright 1987, 1988, 1989 by MIT
+ *
+ * For copyright information, see mit-sipb-copyright.h.
+ */
+
+#include <stdio.h>
+#include "ss_internal.h"
+
+#define	DECLARE(name)	void name(argc,argv,sci_idx,info_ptr)int argc,sci_idx;const char * const *argv; pointer info_ptr;
+
+/*
+ * ss_self_identify -- assigned by default to the "." request
+ */
+DECLARE(ss_self_identify)
+{
+     register ss_data *info = ss_info(sci_idx);
+     printf("%s version %s\n", info->subsystem_name,
+	    info->subsystem_version);
+}
+
+/*
+ * ss_subsystem_name -- print name of subsystem
+ */
+DECLARE(ss_subsystem_name)
+{
+     printf("%s\n", ss_info(sci_idx)->subsystem_name);
+}
+
+/*
+ * ss_subsystem_version -- print version of subsystem
+ */
+DECLARE(ss_subsystem_version)
+{
+     printf("%s\n", ss_info(sci_idx)->subsystem_version);
+}
+
+/*
+ * ss_unimplemented -- routine not implemented (should be
+ * set up as (dont_list,dont_summarize))
+ */
+DECLARE(ss_unimplemented)
+{
+     ss_perror(sci_idx, SS_ET_UNIMPLEMENTED, "");
+}
diff --git a/krb5-1-6/src/util/ss/ss.h b/krb5-1-6/src/util/ss/ss.h
new file mode 100644
index 000000000..45ba4061b
--- /dev/null
+++ b/krb5-1-6/src/util/ss/ss.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see mit-sipb-copyright.h.
+ */
+
+#ifndef _ss_h
+#define _ss_h __FILE__
+
+#include <errno.h>
+#include <ss/ss_err.h>
+
+#ifdef __STDC__
+#define __SS_CONST const
+#define __SS_PROTO (int, const char * const *, int, void *)
+#else
+#define __SS_CONST
+#define __SS_PROTO ()
+#endif
+
+typedef __SS_CONST struct _ss_request_entry {
+    __SS_CONST char * __SS_CONST *command_names; /* whatever */
+    void (* __SS_CONST function) __SS_PROTO; /* foo */
+    __SS_CONST char * __SS_CONST info_string;	/* NULL */
+    int flags;			/* 0 */
+} ss_request_entry;
+
+typedef __SS_CONST struct _ss_request_table {
+    int version;
+    ss_request_entry *requests;
+} ss_request_table;
+
+#define SS_RQT_TBL_V2	2
+
+typedef struct _ss_rp_options {	/* DEFAULT VALUES */
+    int version;		/* SS_RP_V1 */
+    void (*unknown) __SS_PROTO;	/* call for unknown command */
+    int allow_suspend;
+    int catch_int;
+} ss_rp_options;
+
+#define SS_RP_V1 1
+
+#define SS_OPT_DONT_LIST	0x0001
+#define SS_OPT_DONT_SUMMARIZE	0x0002
+
+void ss_help __SS_PROTO;
+void ss_list_requests __SS_PROTO;
+void ss_quit __SS_PROTO;
+char *ss_current_request();
+char *ss_name(int);
+void ss_error (int, long, char const *, ...);
+void ss_perror (int, long, char const *);
+int ss_listen (int);
+int ss_create_invocation(char *, char *, char *, ss_request_table *, int *);
+void ss_delete_invocation(int);
+void ss_add_info_dir(int , char *, int *);
+void ss_delete_info_dir(int , char *, int *);
+int ss_execute_command(int sci_idx, char **);
+void ss_abort_subsystem(int, int);
+void ss_set_prompt(int, char *);
+char *ss_get_prompt(int);
+void ss_add_request_table(int, ss_request_table *, int, int *);
+void ss_delete_request_table(int, ss_request_table *, int *);
+int ss_execute_line (int, char*);
+extern ss_request_table ss_std_requests;
+#endif /* _ss_h */
diff --git a/krb5-1-6/src/util/ss/ss_err.et b/krb5-1-6/src/util/ss/ss_err.et
new file mode 100644
index 000000000..80e9dfa44
--- /dev/null
+++ b/krb5-1-6/src/util/ss/ss_err.et
@@ -0,0 +1,39 @@
+	error_table ss
+
+ec	SS_ET_SUBSYSTEM_ABORTED,
+	"Subsystem aborted"
+
+ec	SS_ET_VERSION_MISMATCH,
+	"Version mismatch"
+
+ec	SS_ET_NULL_INV,
+	"No current invocation"
+
+ec	SS_ET_NO_INFO_DIR,
+	"No info directory"
+
+ec	SS_ET_COMMAND_NOT_FOUND,
+	"Command not found"
+
+ec	SS_ET_LINE_ABORTED,
+	"Command line aborted"
+
+ec	SS_ET_EOF,
+	"End-of-file reached"
+
+ec	SS_ET_PERMISSION_DENIED,
+	"Permission denied"
+
+ec	SS_ET_TABLE_NOT_FOUND,
+	"Request table not found"
+
+ec	SS_ET_NO_HELP_FILE,
+	"No info available"
+
+ec	SS_ET_ESCAPE_DISABLED,
+	"Shell escapes are disabled"
+
+ec	SS_ET_UNIMPLEMENTED,
+	"Sorry, this request is not yet implemented"
+
+	end
diff --git a/krb5-1-6/src/util/ss/ss_internal.h b/krb5-1-6/src/util/ss/ss_internal.h
new file mode 100644
index 000000000..c597820d0
--- /dev/null
+++ b/krb5-1-6/src/util/ss/ss_internal.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#ifndef _ss_ss_internal_h
+#define _ss_ss_internal_h __FILE__
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "autoconf.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+typedef void * pointer;
+
+#include "ss.h"
+
+#if defined(__GNUC__)
+#define LOCAL_ALLOC(x) __builtin_alloca(x)
+#define LOCAL_FREE(x)
+#else
+#if defined(vax)
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca (unsigned);
+#else
+#if defined(__HIGHC__)	/* Barf! */
+pragma on(alloca);
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca (unsigned);
+#else
+/* no alloca? */
+#define LOCAL_ALLOC(x) malloc(x)
+#define LOCAL_FREE(x) free(x)
+#endif
+#endif
+#endif				/* LOCAL_ALLOC stuff */
+
+typedef char BOOL;
+
+typedef struct _ss_abbrev_entry {
+    char *name;			/* abbrev name */
+    char **abbrev;		/* new tokens to insert */
+    unsigned int beginning_of_line : 1;
+} ss_abbrev_entry;
+
+typedef struct _ss_abbrev_list {
+    int n_abbrevs;
+    ss_abbrev_entry *first_abbrev;
+} ss_abbrev_list;
+
+typedef struct {
+/*    char *path; */
+    ss_abbrev_list abbrevs[127];
+} ss_abbrev_info;
+
+typedef struct _ss_data {	/* init values */
+    /* this subsystem */
+    char *subsystem_name;
+    char *subsystem_version;
+    /* current request info */
+    int argc;
+    char **argv;		/* arg list */
+    char const *current_request; /* primary name */
+    /* info directory for 'help' */
+    char **info_dirs;
+    /* to be extracted by subroutines */
+    pointer info_ptr;		/* (void *) NULL */
+    /* for ss_listen processing */
+    char *prompt;
+    ss_request_table **rqt_tables;
+    ss_abbrev_info *abbrev_info;
+    struct {
+	unsigned int  escape_disabled : 1,
+		      abbrevs_disabled : 1;
+    } flags;
+    /* to get out */
+    int abort;			/* exit subsystem */
+    int exit_status;
+} ss_data;
+
+#define CURRENT_SS_VERSION 1
+
+#define	ss_info(sci_idx)	(_ss_table[sci_idx])
+#define	ss_current_request(sci_idx,code_ptr)	\
+     (*code_ptr=0,ss_info(sci_idx)->current_request)
+void ss_unknown_function();
+void ss_delete_info_dir();
+char **ss_parse (int, char *, int *);
+ss_abbrev_info *ss_abbrev_initialize (char *, int *);
+void ss_page_stdin (void);
+int ss_pager_create (void);
+void ss_self_identify __SS_PROTO;
+void ss_subsystem_name __SS_PROTO;
+void ss_subsystem_version __SS_PROTO;
+void ss_unimplemented __SS_PROTO;
+
+extern ss_data **_ss_table;
+extern char *ss_et_msgs[];
+
+#ifndef HAVE_STDLIB_H
+extern pointer malloc (unsigned);
+extern pointer realloc (pointer, unsigned);
+extern pointer calloc (unsigned, unsigned);
+#endif
+
+#if defined(USE_SIGPROCMASK) && !defined(POSIX_SIGNALS)
+/* fake sigmask, sigblock, sigsetmask */
+#include <signal.h>
+#ifdef sigmask
+#undef sigmask
+#endif
+#define sigmask(x) (1L<<(x)-1)
+#define sigsetmask(x) sigprocmask(SIG_SETMASK,&x,NULL)
+static int _fake_sigstore;
+#define sigblock(x) (_fake_sigstore=x,sigprocmask(SIG_BLOCK,&_fake_sigstore,0))
+#endif
+#endif /* _ss_internal_h */
diff --git a/krb5-1-6/src/util/ss/std_rqs.ct b/krb5-1-6/src/util/ss/std_rqs.ct
new file mode 100644
index 000000000..500288a02
--- /dev/null
+++ b/krb5-1-6/src/util/ss/std_rqs.ct
@@ -0,0 +1,46 @@
+	command_table	ss_std_requests;
+
+	request	ss_self_identify, "Identify the subsystem.",
+		".",
+		(dont_list, dont_summarize);
+
+	request	ss_help, "Display info on command or topic.",
+		help;
+
+	unimplemented
+		ss_list_help,
+		"List topics for which help is available.",
+		list_help, lh;
+
+	request	ss_list_requests, "List available commands.",
+		list_requests, lr, "?";
+
+	request	ss_quit, "Leave the subsystem.",
+		quit, q;
+
+	unimplemented
+		ss_abbrev,
+		"Enable/disable abbreviation processing of request lines.",
+		abbrev, ab;
+
+	unimplemented
+		ss_execute,
+		"Execute a UNIX command line.",
+		execute, e;
+
+	unimplemented
+		ss_summarize_requests,
+		"Produce a list of the most commonly used requests.",
+		"?";
+		
+	request	ss_subsystem_name,
+		"Return the name of this subsystem.",
+		subsystem_name,
+		(dont_list);
+
+	request	ss_subsystem_version,
+		"Return the version of this subsystem.",
+		subsystem_version,
+		(dont_list);
+
+	end;
diff --git a/krb5-1-6/src/util/ss/test_ss.c b/krb5-1-6/src/util/ss/test_ss.c
new file mode 100644
index 000000000..9bab95c3c
--- /dev/null
+++ b/krb5-1-6/src/util/ss/test_ss.c
@@ -0,0 +1,99 @@
+/*
+ * util/ss/test_ss.c
+ */
+
+
+#include <stdio.h>
+#include "ss.h"
+
+extern ss_request_table test_cmds;
+
+#define TRUE 1
+#define FALSE 0
+
+static char def_subsystem_name[5] = "test";
+static char version [4] = "1.0";
+
+int main(argc, argv)
+    int argc;
+    char **argv;
+{
+    int code;
+    char *argv0 = argv[0];
+    char *initial_request = (char *)NULL;
+    int quit = FALSE;	/* quit after processing request */
+    int sci_idx;
+    char *subsystem_name;
+
+    subsystem_name = def_subsystem_name;
+
+    for (; *argv; ++argv, --argc) {
+	printf("checking arg: %s\n", *argv);
+	if (!strcmp(*argv, "-prompt")) {
+	    if (argc == 1) {
+		fprintf(stderr,
+			"No argument supplied with -prompt\n");
+		exit(1);
+	    }
+	    argc--; argv++;
+	    subsystem_name = *argv;
+	}
+	else if (!strcmp(*argv, "-request") || !strcmp(*argv, "-rq")) {
+	    if (argc == 1) {
+		fprintf(stderr,
+			"No string supplied with -request.\n");
+		exit(1);
+	    }
+	    argc--; argv++;
+	    initial_request = *argv;
+	}
+	else if (!strcmp(*argv, "-quit"))
+	    quit = TRUE;
+	else if (!strcmp(*argv, "-no_quit"))
+	    quit = FALSE;
+	else if (**argv == '-') {
+	    fprintf(stderr, "Unknown control argument %s\n",
+		    *argv);
+	    fprintf(stderr,
+	"Usage: %s [gateway] [ -prompt name ] [ -request name ] [ -quit ]\n",
+		    argv0);
+	    exit(1);
+	}
+    }
+
+    sci_idx = ss_create_invocation(subsystem_name, version,
+				   (char *)NULL, &test_cmds, &code);
+    if (code) {
+	ss_perror(sci_idx, code, "creating invocation");
+	exit(1);
+    }
+
+    (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &code);
+    if (code) {
+	ss_perror (sci_idx, code, "adding standard requests");
+	exit (1);
+    }
+
+    if (!quit)
+	printf("test version %s.  Type '?' for a list of commands.\n\n",
+	       version);
+
+    if (initial_request != (char *)NULL) {
+	code = ss_execute_line(sci_idx, initial_request);
+	if (code != 0)
+	    ss_perror(sci_idx, code, initial_request);
+    }
+    if (!quit || code)
+	code =  ss_listen (sci_idx);
+    exit(0);
+}
+
+
+void test_cmd (argc, argv)
+    int argc;
+    char **argv;
+{
+    while (++argv, --argc)
+	fputs(*argv, stdout);
+    putchar ('\n');
+}
diff --git a/krb5-1-6/src/util/ss/utils.c b/krb5-1-6/src/util/ss/utils.c
new file mode 100644
index 000000000..c57800157
--- /dev/null
+++ b/krb5-1-6/src/util/ss/utils.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include <string.h>
+#include "copyright.h"
+#include "ss_internal.h"	/* includes stdio and string */
+
+extern FILE *output_file;
+
+char *gensym(), *str_concat3(), *quote();
+extern long gensym_n;
+
+void write_ct(hdr, rql)
+    char const *hdr, *rql;
+{
+    char *sym;
+    sym = gensym("ssu");
+    fputs("static ss_request_entry ", output_file);
+    fputs(sym, output_file);
+    fputs("[] = {\n", output_file);
+    fputs(rql, output_file);
+    fputs("    { 0, 0, 0, 0 }\n", output_file);
+    fputs("};\n\nss_request_table ", output_file);
+    fputs(hdr, output_file);
+    fprintf(output_file, " = { %d, ", SS_RQT_TBL_V2);
+    fputs(sym, output_file);
+    fputs(" };\n", output_file);
+}
+
+char * generate_cmds_string(cmds)
+    char const *cmds;
+{
+    char * var_name = gensym("ssu");
+    fputs("static char const * const ", output_file);
+    fputs(var_name, output_file);
+    fputs("[] = {\n", output_file);
+    fputs(cmds, output_file);
+    fputs(",\n    (char const *)0\n};\n", output_file);
+    return(var_name);
+}
+
+void generate_function_definition(func)
+    char const *func;
+{
+    fputs("extern void ", output_file);
+    fputs(func, output_file);
+    fputs(" __SS_PROTO;\n", output_file);
+}
+
+char * generate_rqte(func_name, info_string, cmds, options)
+    char const *func_name;
+    char const *info_string;
+    char const *cmds;
+    int options;
+{
+    int size;
+    char *string, *var_name, numbuf[16];
+    var_name = generate_cmds_string(cmds);
+    generate_function_definition(func_name);
+    size = 6;		/* "    { " */
+    size += strlen(var_name)+8; /* "quux, " */
+    size += strlen(func_name)+8; /* "foo, " */
+    size += strlen(info_string)+8; /* "\"Info!\", " */
+    sprintf(numbuf, "%d", options);
+    size += strlen(numbuf)+5;		/* " }," + NL + NUL */
+    string = malloc(size);
+    strcpy(string, "    { ");
+    strcat(string, var_name);
+    strcat(string, ",\n      ");
+    strcat(string, func_name);
+    strcat(string, ",\n      ");
+    strcat(string, info_string);
+    strcat(string, ",\n      ");
+    strcat(string, numbuf);
+    strcat(string, " },\n");
+    return(string);
+}
+
+char *
+gensym(name)
+	char *name;
+{
+	char *symbol;
+
+	symbol = malloc((strlen(name)+6) * sizeof(char));
+	gensym_n++;
+	sprintf(symbol, "%s%05ld", name, gensym_n);
+	return(symbol);
+}
+
+/* concatenate three strings and return the result */
+char *str_concat3(a, b, c)
+	register char *a, *b, *c;
+{
+	char *result;
+	int size_a = strlen(a);
+	int size_b = strlen(b);
+	int size_c = strlen(c);
+
+	result = malloc((size_a + size_b + size_c + 2)*sizeof(char));
+	strcpy(result, a);
+	strcpy(&result[size_a], c);
+	strcpy(&result[size_a+size_c], b);
+	return(result);
+}
+
+/* return copy of string enclosed in double-quotes */
+char *quote(string)
+	register char *string;
+{
+	register char *result;
+	int len;
+	len = strlen(string)+1;
+	result = malloc(len+2);
+	result[0] = '"';
+	strncpy(&result[1], string, len-1);
+	result[len] = '"';
+	result[len+1] = '\0';
+	return(result);
+}
+
+#ifndef HAVE_STRDUP
+/* make duplicate of string and return pointer */
+char *strdup(s)
+	register char *s;
+{
+	register int len = strlen(s) + 1;
+	register char *new;
+	new = malloc(len);
+	strncpy(new, s, len);
+	return(new);
+}
+#endif
diff --git a/krb5-1-6/src/util/support/Makefile.in b/krb5-1-6/src/util/support/Makefile.in
new file mode 100644
index 000000000..78c322ec0
--- /dev/null
+++ b/krb5-1-6/src/util/support/Makefile.in
@@ -0,0 +1,106 @@
+thisconfigdir=../..
+myfulldir=util/support
+mydir=util/support
+BUILDTOP=$(REL)..$(S)..
+RELDIR=../util/support
+DEFS=
+
+##DOS##BUILDTOP = ..\..
+##DOS##LIBNAME=$(OUTPRE)k5sprt32.lib
+##DOS##WIN64LIBNAME=$(OUTPRE)k5sprt64.lib
+##DOS##XTRA=
+##DOS##OBJFILE=$(OUTPRE)k5sprt32.lst
+##DOS##WIN64OBJFILE=$(OUTPRE)k5sprt64.lst
+
+SED = sed
+
+KRB5_RUN_ENV= @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+LIBBASE=krb5support
+LIBMAJOR=@SUPPORTLIB_MAJOR@
+LIBMINOR=1
+
+LIBINITFUNC=krb5int_thread_support_init
+LIBFINIFUNC=krb5int_thread_support_fini
+
+STLIBOBJS= \
+	threads.o \
+	init-addrinfo.o \
+	plugins.o \
+	errors.o \
+	gmt_mktime.o \
+	fake-addrinfo.o
+
+LIBOBJS= \
+	$(OUTPRE)threads.$(OBJEXT) \
+	$(OUTPRE)init-addrinfo.$(OBJEXT) \
+	$(OUTPRE)plugins.$(OBJEXT) \
+	$(OUTPRE)errors.$(OBJEXT) \
+	$(OUTPRE)gmt_mktime.$(OBJEXT) \
+	$(OUTPRE)fake-addrinfo.$(OBJEXT)
+
+STOBJLISTS=OBJS.ST
+
+INSTALLFILE = cp
+
+LOCALINCLUDES=-I. -I$(srcdir)
+
+SRCS=\
+	$(srcdir)/threads.c \
+	$(srcdir)/init-addrinfo.c \
+	$(srcdir)/errors.c \
+	$(srcdir)/gmt_mktime.c \
+	$(srcdir)/fake-addrinfo.c
+SHLIB_EXPDEPS =
+# Add -lm if dumping thread stats, for sqrt.
+SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
+SHLIB_DIRS=
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+DEPLIBS=
+
+#
+all-unix:: all-liblinks
+
+install-unix:: install-libs
+
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+##DOS##!if 0
+$(BUILDTOP)/include/autoconf.h: $(SRCTOP)/include/autoconf.h.in
+	(cd $(BUILDTOP)/include; $(MAKE) autoconf.h)
+##DOS##!endif
+
+t_mktime: gmt_mktime.c
+	$(CC) $(ALL_CFLAGS) -DTEST_LEAP -o t_mktime $(srcdir)/gmt_mktime.c
+
+@lib_frag@
+@libobj_frag@
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+threads.so threads.po $(OUTPRE)threads.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/port-sockets.h \
+  $(SRCTOP)/include/socket-utils.h cache-addrinfo.h supp-int.h \
+  threads.c
+init-addrinfo.so init-addrinfo.po $(OUTPRE)init-addrinfo.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  cache-addrinfo.h init-addrinfo.c
+errors.so errors.po $(OUTPRE)errors.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-platform.h \
+  $(SRCTOP)/include/k5-thread.h errors.c supp-int.h
+gmt_mktime.so gmt_mktime.po $(OUTPRE)gmt_mktime.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h gmt_mktime.c
+fake-addrinfo.so fake-addrinfo.po $(OUTPRE)fake-addrinfo.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(SRCTOP)/include/fake-addrinfo.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  cache-addrinfo.h fake-addrinfo.c supp-int.h
diff --git a/krb5-1-6/src/util/support/cache-addrinfo.h b/krb5-1-6/src/util/support/cache-addrinfo.h
new file mode 100644
index 000000000..807c652f8
--- /dev/null
+++ b/krb5-1-6/src/util/support/cache-addrinfo.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+/* Approach overview:
+
+   If a system version is available but buggy, save handles to it,
+   redefine the names to refer to static functions defined here, and
+   in those functions, call the system versions and fix up the
+   returned data.  Use the native data structures and flag values.
+
+   If no system version exists, use gethostby* and fake it.  Define
+   the data structures and flag values locally.
+
+
+   On Mac OS X, getaddrinfo results aren't cached (though
+   gethostbyname results are), so we need to build a cache here.  Now
+   things are getting really messy.  Because the cache is in use, we
+   use getservbyname, and throw away thread safety.  (Not that the
+   cache is thread safe, but when we get locking support, that'll be
+   dealt with.)  This code needs tearing down and rebuilding, soon.
+
+
+   Note that recent Windows developers' code has an interesting hack:
+   When you include the right header files, with the right set of
+   macros indicating system versions, you'll get an inline function
+   that looks for getaddrinfo (or whatever) in the system library, and
+   calls it if it's there.  If it's not there, it fakes it with
+   gethostby* calls.
+
+   We're taking a simpler approach: A system provides these routines or
+   it does not.
+
+   Someday, we may want to take into account different versions (say,
+   different revs of GNU libc) where some are broken in one way, and
+   some work or are broken in another way.  Cross that bridge when we
+   come to it.  */
+
+/* To do, maybe:
+
+   + For AIX 4.3.3, using the RFC 2133 definition: Implement
+     AI_NUMERICHOST.  It's not defined in the header file.
+
+     For certain (old?) versions of GNU libc, AI_NUMERICHOST is
+     defined but not implemented.
+
+   + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
+     functions if available.  But, see
+     http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
+     gethostbyname2 problem on Linux.  And besides, if a platform is
+     supporting IPv6 at all, they really should be doing getaddrinfo
+     by now.
+
+   + inet_ntop, inet_pton
+
+   + Conditionally export/import the function definitions, so a
+     library can have a single copy instead of multiple.
+
+   + Upgrade host requirements to include working implementations of
+     these functions, and throw all this away.  Pleeease?  :-)  */
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+#include "k5-platform.h"
+#include "k5-thread.h"
+
+#include "fake-addrinfo.h"
+
+#if defined (__APPLE__) && defined (__MACH__)
+#define FAI_CACHE
+#endif
+
+struct face {
+    struct in_addr *addrs4;
+    struct in6_addr *addrs6;
+    unsigned int naddrs4, naddrs6;
+    time_t expiration;
+    char *canonname, *name;
+    struct face *next;
+};
+
+/* fake addrinfo cache */
+struct fac {
+    k5_mutex_t lock;
+    struct face *data;
+};
+
+extern struct fac krb5int_fac;
+
+extern int krb5int_init_fac (void);
+extern void krb5int_fini_fac (void);
diff --git a/krb5-1-6/src/util/support/errors.c b/krb5-1-6/src/util/support/errors.c
new file mode 100644
index 000000000..56581218a
--- /dev/null
+++ b/krb5-1-6/src/util/support/errors.c
@@ -0,0 +1,166 @@
+/* Can't include krb5.h here, or k5-int.h which includes it, because
+   krb5.h needs to be generated with error tables, after util/et,
+   which builds after this directory.  */
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "k5-err.h"
+
+#include "k5-thread.h"
+#include "k5-platform.h"
+#include "supp-int.h"
+
+#ifdef _WIN32
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+#endif
+
+/* It would be nice to just use error_message() always.  Pity that
+   it's defined in a library that depends on this one, and we're not
+   allowed to make circular dependencies.  */
+/* We really want a rwlock here, since we should hold it while calling
+   the function and copying out its results.  But I haven't
+   implemented shims for rwlock yet.  */
+static k5_mutex_t krb5int_error_info_support_mutex =
+    K5_MUTEX_PARTIAL_INITIALIZER;
+static const char *(KRB5_CALLCONV *fptr)(long); /* = &error_message */
+
+int
+krb5int_err_init (void)
+{
+    return k5_mutex_finish_init (&krb5int_error_info_support_mutex);
+}
+#define initialize()	krb5int_call_thread_support_init()
+#define lock()		k5_mutex_lock(&krb5int_error_info_support_mutex)
+#define unlock()	k5_mutex_unlock(&krb5int_error_info_support_mutex)
+
+void
+krb5int_set_error (struct errinfo *ep, long code, const char *fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    krb5int_vset_error (ep, code, fmt, args);
+    va_end (args);
+}
+
+void
+krb5int_vset_error (struct errinfo *ep, long code,
+		    const char *fmt, va_list args)
+{
+    char *p;
+
+    if (ep->msg && ep->msg != ep->scratch_buf) {
+	free (ep->msg);
+	ep->msg = NULL;
+    }
+    ep->code = code;
+#ifdef HAVE_VASPRINTF
+    {
+	char *str = NULL;
+	if (vasprintf(&str, fmt, args) >= 0 && str != NULL) {
+	    ep->msg = str;
+	    return;
+	}
+    }
+#endif
+    vsnprintf(ep->scratch_buf, sizeof(ep->scratch_buf), fmt, args);
+    p = strdup(ep->scratch_buf);
+    ep->msg = p ? p : ep->scratch_buf;
+}
+
+const char *
+krb5int_get_error (struct errinfo *ep, long code)
+{
+    char *r, *r2;
+    if (code == ep->code && ep->msg) {
+	r = strdup(ep->msg);
+	if (r == NULL) {
+	    strcpy(ep->scratch_buf, _("Out of memory"));
+	    r = ep->scratch_buf;
+	}
+	return r;
+    }
+    if (initialize() != 0) {
+	strncpy(ep->scratch_buf, _("Kerberos library initialization failure"),
+		sizeof(ep->scratch_buf));
+	ep->scratch_buf[sizeof(ep->scratch_buf)-1] = 0;
+	ep->msg = NULL;
+	return ep->scratch_buf;
+    }
+    lock();
+    if (fptr == NULL) {
+	unlock();
+#ifdef HAVE_STRERROR_R
+	if (strerror_r (code, ep->scratch_buf, sizeof(ep->scratch_buf)) == 0) {
+	    char *p = strdup(ep->scratch_buf);
+	    if (p)
+		return p;
+	    return ep->scratch_buf;
+	}
+	/* If strerror_r didn't work with the 1K buffer, we can try a
+	   really big one.  This seems kind of gratuitous though.  */
+#define BIG_ERR_BUFSIZ 8192
+	r = malloc(BIG_ERR_BUFSIZ);
+	if (r) {
+	    if (strerror_r (code, r, BIG_ERR_BUFSIZ) == 0) {
+		r2 = realloc (r, 1 + strlen(r));
+		if (r2)
+		    return r2;
+		return r;
+	    }
+	    free (r);
+	}
+#endif
+	r = strerror (code);
+	if (r) {
+	    if (strlen (r) < sizeof (ep->scratch_buf)
+		|| (r2 = strdup (r)) == NULL) {
+		strncpy (ep->scratch_buf, r, sizeof(ep->scratch_buf));
+		return ep->scratch_buf;
+	    } else
+		return r2;
+	}
+    format_number:
+	sprintf (ep->scratch_buf, _("error %ld"), code);
+	return ep->scratch_buf;
+    }
+    r = (char *) fptr(code);
+    if (r == NULL) {
+	unlock();
+	goto format_number;
+    }
+    r2 = strdup (r);
+    if (r2 == NULL) {
+	strncpy(ep->scratch_buf, r, sizeof(ep->scratch_buf));
+	unlock();
+	return ep->scratch_buf;
+    } else {
+	unlock();
+	return r2;
+    }
+}
+
+void
+krb5int_free_error (struct errinfo *ep, const char *msg)
+{
+    if (msg != ep->scratch_buf)
+	free ((char *) msg);
+}
+
+void
+krb5int_clear_error (struct errinfo *ep)
+{
+    krb5int_free_error (ep, ep->msg);
+    ep->msg = NULL;
+}
+
+void
+krb5int_set_error_info_callout_fn (const char *(KRB5_CALLCONV *f)(long))
+{
+    initialize();
+    lock();
+    fptr = f;
+    unlock();
+}
diff --git a/krb5-1-6/src/util/support/fake-addrinfo.c b/krb5-1-6/src/util/support/fake-addrinfo.c
new file mode 100644
index 000000000..325418983
--- /dev/null
+++ b/krb5-1-6/src/util/support/fake-addrinfo.c
@@ -0,0 +1,1358 @@
+/*
+ * Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+/* Approach overview:
+
+   If a system version is available but buggy, save handles to it,
+   redefine the names to refer to static functions defined here, and
+   in those functions, call the system versions and fix up the
+   returned data.  Use the native data structures and flag values.
+
+   If no system version exists, use gethostby* and fake it.  Define
+   the data structures and flag values locally.
+
+
+   On Mac OS X, getaddrinfo results aren't cached (though
+   gethostbyname results are), so we need to build a cache here.  Now
+   things are getting really messy.  Because the cache is in use, we
+   use getservbyname, and throw away thread safety.  (Not that the
+   cache is thread safe, but when we get locking support, that'll be
+   dealt with.)  This code needs tearing down and rebuilding, soon.
+
+
+   Note that recent Windows developers' code has an interesting hack:
+   When you include the right header files, with the right set of
+   macros indicating system versions, you'll get an inline function
+   that looks for getaddrinfo (or whatever) in the system library, and
+   calls it if it's there.  If it's not there, it fakes it with
+   gethostby* calls.
+
+   We're taking a simpler approach: A system provides these routines or
+   it does not.
+
+   Someday, we may want to take into account different versions (say,
+   different revs of GNU libc) where some are broken in one way, and
+   some work or are broken in another way.  Cross that bridge when we
+   come to it.  */
+
+/* To do, maybe:
+
+   + For AIX 4.3.3, using the RFC 2133 definition: Implement
+     AI_NUMERICHOST.  It's not defined in the header file.
+
+     For certain (old?) versions of GNU libc, AI_NUMERICHOST is
+     defined but not implemented.
+
+   + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
+     functions if available.  But, see
+     http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
+     gethostbyname2 problem on Linux.  And besides, if a platform is
+     supporting IPv6 at all, they really should be doing getaddrinfo
+     by now.
+
+   + inet_ntop, inet_pton
+
+   + Conditionally export/import the function definitions, so a
+     library can have a single copy instead of multiple.
+
+   + Upgrade host requirements to include working implementations of
+     these functions, and throw all this away.  Pleeease?  :-)  */
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+#include "k5-platform.h"
+#include "k5-thread.h"
+#include "supp-int.h"
+
+#include <stdio.h>		/* for sprintf */
+#include <errno.h>
+
+#define IMPLEMENT_FAKE_GETADDRINFO
+#include "fake-addrinfo.h"
+
+#ifdef S_SPLINT_S
+/*@-incondefs@*/
+extern int
+getaddrinfo (/*@in@*/ /*@null@*/ const char *,
+	     /*@in@*/ /*@null@*/ const char *,
+	     /*@in@*/ /*@null@*/ const struct addrinfo *,
+	     /*@out@*/ struct addrinfo **)
+    ;
+extern void
+freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
+    ;
+extern int
+getnameinfo (const struct sockaddr *addr, socklen_t addrsz,
+	     /*@out@*/ /*@null@*/ char *h, socklen_t hsz,
+	     /*@out@*/ /*@null@*/ char *s, socklen_t ssz,
+	     int flags)
+    /*@requires (maxSet(h)+1) >= hsz /\ (maxSet(s)+1) >= ssz @*/
+    /* too hard: maxRead(addr) >= (addrsz-1) */
+    /*@modifies *h, *s@*/;
+extern /*@dependent@*/ char *gai_strerror (int code) /*@*/;
+/*@=incondefs@*/
+#endif
+
+
+#include "cache-addrinfo.h"
+
+#if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
+/* See comments below.  */
+#  define WRAP_GETADDRINFO
+#endif
+
+#if defined (__linux__) && defined(HAVE_GETADDRINFO)
+# define COPY_FIRST_CANONNAME
+#endif
+
+#ifdef _AIX
+# define NUMERIC_SERVICE_BROKEN
+# define COPY_FIRST_CANONNAME
+#endif
+
+
+#ifdef COPY_FIRST_CANONNAME
+# include <string.h>
+#endif
+
+#ifdef NUMERIC_SERVICE_BROKEN
+# include <ctype.h>		/* isdigit */
+# include <stdlib.h>		/* strtoul */
+#endif
+
+
+/* Do we actually have *any* systems we care about that don't provide
+   either getaddrinfo or one of these two flavors of
+   gethostbyname_r?  */
+#if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME)
+typedef struct hostent *GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+    { TMP = gethostbyname (NAME); (ERR) = h_errno; (HP) = TMP; }
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
+    { TMP = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; (HP) = TMP; }
+#else
+#ifdef _AIX /* XXX should have a feature test! */
+typedef struct {
+    struct hostent ent;
+    struct hostent_data data;
+} GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+    {								\
+	(HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data)	\
+		? 0						\
+		: &TMP.ent);					\
+	(ERR) = h_errno;					\
+    }
+/*
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
+    {									\
+	struct hostent my_h_ent;					\
+	struct hostent_data my_h_ent_data;				\
+	(HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent,	\
+				&my_h_ent_data)				\
+		? 0							\
+		: &my_h_ent);						\
+	(ERR) = my_h_err;						\
+    }
+*/
+#else
+#ifdef GETHOSTBYNAME_R_RETURNS_INT
+typedef struct {
+    struct hostent ent;
+    char buf[8192];
+} GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+    {									\
+	struct hostent *my_hp = NULL;					\
+	int my_h_err, my_ret;						\
+	my_ret = gethostbyname_r((NAME), &TMP.ent,			\
+				 TMP.buf, sizeof (TMP.buf), &my_hp,	\
+				 &my_h_err);				\
+	(HP) = (((my_ret != 0) || (my_hp != &TMP.ent))			\
+		? 0							\
+		: &TMP.ent);						\
+	(ERR) = my_h_err;						\
+    }
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
+    {									\
+	struct hostent *my_hp;						\
+	int my_h_err, my_ret;						\
+	my_ret = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent,	\
+				 TMP.buf, sizeof (TMP.buf), &my_hp,	\
+				 &my_h_err);				\
+	(HP) = (((my_ret != 0) || (my_hp != &TMP.ent))			\
+		? 0							\
+		: &TMP.ent);						\
+	(ERR) = my_h_err;						\
+    }
+#else
+typedef struct {
+    struct hostent ent;
+    char buf[8192];
+} GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+    {									\
+	int my_h_err;							\
+	(HP) = gethostbyname_r((NAME), &TMP.ent,			\
+			       TMP.buf, sizeof (TMP.buf), &my_h_err);	\
+	(ERR) = my_h_err;						\
+    }
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
+    {									\
+	int my_h_err;							\
+	(HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent,	\
+			       TMP.buf, sizeof (TMP.buf), &my_h_err);	\
+	(ERR) = my_h_err;						\
+    }
+#endif /* returns int? */
+#endif /* _AIX */
+#endif
+
+/* Now do the same for getservby* functions.  */
+#ifndef HAVE_GETSERVBYNAME_R
+typedef struct servent *GET_SERV_TMP;
+#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
+    (TMP = getservbyname (NAME, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
+#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
+    (TMP = getservbyport (PORT, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
+#else
+#ifdef GETSERVBYNAME_R_RETURNS_INT
+typedef struct {
+    struct servent ent;
+    char buf[8192];
+} GET_SERV_TMP;
+#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
+    {									\
+	struct servent *my_sp;						\
+	int my_s_err;							\
+	(SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent,		\
+				TMP.buf, sizeof (TMP.buf), &my_sp,	\
+				&my_s_err)				\
+		? 0							\
+		: &TMP.ent);						\
+	(ERR) = my_s_err;						\
+    }
+#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
+    {									\
+	struct servent *my_sp;						\
+	int my_s_err;							\
+	(SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent,		\
+				TMP.buf, sizeof (TMP.buf), &my_sp,	\
+				&my_s_err)				\
+		? 0							\
+		: &TMP.ent);						\
+	(ERR) = my_s_err;						\
+    }
+#else
+/* returns ptr -- IRIX? */
+typedef struct {
+    struct servent ent;
+    char buf[8192];
+} GET_SERV_TMP;
+#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
+    {									\
+	(SP) = getservbyname_r((NAME), (PROTO), &TMP.ent,		\
+			       TMP.buf, sizeof (TMP.buf));		\
+	(ERR) = (SP) == NULL;						\
+    }
+
+#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
+    {									\
+	struct servent *my_sp;						\
+	my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent,		\
+				TMP.buf, sizeof (TMP.buf));		\
+	(SP) = my_sp;							\
+	(ERR) = my_sp == 0;						\
+	(ERR) = (ERR);	/* avoid "unused" warning */			\
+    }
+#endif
+#endif
+
+#if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
+static inline int
+system_getaddrinfo (const char *name, const char *serv,
+		    const struct addrinfo *hint,
+		    struct addrinfo **res)
+{
+    return getaddrinfo(name, serv, hint, res);
+}
+
+static inline void
+system_freeaddrinfo (struct addrinfo *ai)
+{
+    freeaddrinfo(ai);
+}
+
+/* Note: Implementations written to RFC 2133 use size_t, while RFC
+   2553 implementations use socklen_t, for the second parameter.
+
+   Mac OS X (10.2) and AIX 4.3.3 appear to be in the RFC 2133 camp,
+   but we don't have an autoconf test for that right now.  */
+static inline int
+system_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+		    char *host, size_t hostlen, char *serv, size_t servlen,
+		    int flags)
+{
+    return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+#endif
+
+#if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
+
+#undef  getaddrinfo
+#define getaddrinfo	my_fake_getaddrinfo
+#undef  freeaddrinfo
+#define freeaddrinfo	my_fake_freeaddrinfo
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO)
+
+#undef  gai_strerror
+#define gai_strerror	my_fake_gai_strerror
+
+#endif /* ! HAVE_GETADDRINFO */
+
+#if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
+/* Some debug routines.  */
+
+static const char *protoname (int p, char *buf) {
+#define X(N) if (p == IPPROTO_ ## N) return #N
+
+    X(TCP);
+    X(UDP);
+    X(ICMP);
+    X(IPV6);
+#ifdef IPPROTO_GRE
+    X(GRE);
+#endif
+    X(NONE);
+    X(RAW);
+#ifdef IPPROTO_COMP
+    X(COMP);
+#endif
+#ifdef IPPROTO_IGMP
+    X(IGMP);
+#endif
+
+    sprintf(buf, " %-2d", p);
+    return buf;
+}	
+
+static const char *socktypename (int t, char *buf) {
+    switch (t) {
+    case SOCK_DGRAM: return "DGRAM";
+    case SOCK_STREAM: return "STREAM";
+    case SOCK_RAW: return "RAW";
+    case SOCK_RDM: return "RDM";
+    case SOCK_SEQPACKET: return "SEQPACKET";
+    }
+    sprintf(buf, " %-2d", t);
+    return buf;
+}
+
+static const char *familyname (int f, char *buf) {
+    switch (f) {
+    default:
+	sprintf(buf, "AF %d", f);
+	return buf;
+    case AF_INET: return "AF_INET";
+    case AF_INET6: return "AF_INET6";
+#ifdef AF_UNIX
+    case AF_UNIX: return "AF_UNIX";
+#endif
+    }
+}
+
+static void debug_dump_getaddrinfo_args (const char *name, const char *serv,
+					 const struct addrinfo *hint)
+{
+    const char *sep;
+    fprintf(stderr,
+	    "getaddrinfo(hostname %s, service %s,\n"
+	    "            hints { ",
+	    name ? name : "(null)", serv ? serv : "(null)");
+    if (hint) {
+	char buf[30];
+	sep = "";
+#define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
+	Z(CANONNAME);
+	Z(PASSIVE);
+#ifdef AI_NUMERICHOST
+	Z(NUMERICHOST);
+#endif
+	if (sep[0] == 0)
+	    fprintf(stderr, "no-flags");
+	if (hint->ai_family)
+	    fprintf(stderr, " %s", familyname(hint->ai_family, buf));
+	if (hint->ai_socktype)
+	    fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf));
+	if (hint->ai_protocol)
+	    fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf));
+    } else
+	fprintf(stderr, "(null)");
+    fprintf(stderr, " }):\n");
+}
+
+static void debug_dump_error (int err)
+{
+    fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
+}
+
+static void debug_dump_addrinfos (const struct addrinfo *ai)
+{
+    int count = 0;
+    char buf[10];
+    fprintf(stderr, "addrinfos returned:\n");
+    while (ai) {
+	fprintf(stderr, "%p...", ai);
+	fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype, buf));
+	fprintf(stderr, " ai_family=%s", familyname(ai->ai_family, buf));
+	if (ai->ai_family != ai->ai_addr->sa_family)
+	    fprintf(stderr, " sa_family=%s",
+		    familyname(ai->ai_addr->sa_family, buf));
+	fprintf(stderr, "\n");
+	ai = ai->ai_next;
+	count++;
+    }
+    fprintf(stderr, "end addrinfos returned (%d)\n");
+}
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
+
+static
+int getaddrinfo (const char *name, const char *serv,
+		 const struct addrinfo *hint, struct addrinfo **result);
+
+static
+void freeaddrinfo (struct addrinfo *ai);
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO)
+
+#define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
+#define HAVE_GETADDRINFO
+#define NEED_FAKE_GETNAMEINFO
+#undef  HAVE_GETNAMEINFO
+#define HAVE_GETNAMEINFO 1
+
+#undef  getnameinfo
+#define getnameinfo	my_fake_getnameinfo
+
+static
+char *gai_strerror (int code);
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO)
+static
+int getnameinfo (const struct sockaddr *addr, socklen_t len,
+		 char *host, socklen_t hostlen,
+		 char *service, socklen_t servicelen,
+		 int flags);
+#endif
+
+/* Fudge things on older gai implementations.  */
+/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST.  */
+#ifndef AI_NUMERICHOST
+# define AI_NUMERICHOST 0
+#endif
+/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
+   friends, which RFC 3493 says are now part of the getaddrinfo
+   interface, and we'll want to use.  */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+#ifndef AI_V4MAPPED
+# define AI_V4MAPPED 0
+#endif
+#ifndef AI_ALL
+# define AI_ALL 0
+#endif
+#ifndef AI_DEFAULT
+# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
+#endif
+
+#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
+#define NEED_FAKE_GETADDRINFO
+#endif
+
+#if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_FAKE_GETADDRINFO
+#include <string.h> /* for strspn */
+
+static inline int translate_h_errno (int h);
+
+static inline int fai_add_entry (struct addrinfo **result, void *addr,
+				 int port, const struct addrinfo *template)
+{
+    struct addrinfo *n = malloc (sizeof (struct addrinfo));
+    if (n == 0)
+	return EAI_MEMORY;
+    if (template->ai_family != AF_INET
+#ifdef KRB5_USE_INET6
+	&& template->ai_family != AF_INET6
+#endif
+	)
+	return EAI_FAMILY;
+    *n = *template;
+    if (template->ai_family == AF_INET) {
+	struct sockaddr_in *sin4;
+	sin4 = malloc (sizeof (struct sockaddr_in));
+	if (sin4 == 0)
+	    return EAI_MEMORY;
+        memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
+	n->ai_addr = (struct sockaddr *) sin4;
+	sin4->sin_family = AF_INET;
+	sin4->sin_addr = *(struct in_addr *)addr;
+	sin4->sin_port = port;
+#ifdef HAVE_SA_LEN
+	sin4->sin_len = sizeof (struct sockaddr_in);
+#endif
+    }
+#ifdef KRB5_USE_INET6
+    if (template->ai_family == AF_INET6) {
+	struct sockaddr_in6 *sin6;
+	sin6 = malloc (sizeof (struct sockaddr_in6));
+	if (sin6 == 0)
+	    return EAI_MEMORY;
+        memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
+	n->ai_addr = (struct sockaddr *) sin6;
+	sin6->sin6_family = AF_INET6;
+	sin6->sin6_addr = *(struct in6_addr *)addr;
+	sin6->sin6_port = port;
+#ifdef HAVE_SA_LEN
+	sin6->sin6_len = sizeof (struct sockaddr_in6);
+#endif
+    }
+#endif
+    n->ai_next = *result;
+    *result = n;
+    return 0;
+}
+
+#ifdef FAI_CACHE
+/* fake addrinfo cache entries */
+#define CACHE_ENTRY_LIFETIME	15 /* seconds */
+
+static void plant_face (const char *name, struct face *entry)
+{
+    entry->name = strdup(name);
+    if (entry->name == NULL)
+	/* @@ Wastes memory.  */
+	return;
+    k5_mutex_assert_locked(&krb5int_fac.lock);
+    entry->next = krb5int_fac.data;
+    entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
+    krb5int_fac.data = entry;
+#ifdef DEBUG_ADDRINFO
+    printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
+	   name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
+#endif
+}
+
+static int find_face (const char *name, struct face **entry)
+{
+    struct face *fp, **fpp;
+    time_t now = time(0);
+
+    /* First, scan for expired entries and free them.
+       (Future improvement: Integrate these two loops.)  */
+#ifdef DEBUG_ADDRINFO
+    printf("scanning cache at %d for '%s'...\n", now, name);
+#endif
+    k5_mutex_assert_locked(&krb5int_fac.lock);
+    for (fpp = &krb5int_fac.data; *fpp; ) {
+	fp = *fpp;
+#ifdef DEBUG_ADDRINFO
+	printf("  checking expiration time of @%p: %d\n",
+	       fp, fp->expiration);
+#endif
+	if (fp->expiration < now) {
+#ifdef DEBUG_ADDRINFO
+	    printf("\texpiring cache entry\n");
+#endif
+	    free(fp->name);
+	    free(fp->canonname);
+	    free(fp->addrs4);
+	    free(fp->addrs6);
+	    *fpp = fp->next;
+	    free(fp);
+	    /* Stay at this point in the list, and check again.  */
+	} else
+	    /* Move forward.  */
+	    fpp = &(*fpp)->next;
+    }
+
+    for (fp = krb5int_fac.data; fp; fp = fp->next) {
+#ifdef DEBUG_ADDRINFO
+	printf("  comparing entry @%p\n", fp);
+#endif
+	if (!strcasecmp(fp->name, name)) {
+#ifdef DEBUG_ADDRINFO
+	    printf("\tMATCH!\n");
+#endif
+	    *entry = fp;
+	    return 1;
+	}
+    }
+    return 0;
+}
+
+#endif
+
+static int krb5int_lock_fac(void), krb5int_unlock_fac(void);
+
+static inline int fai_add_hosts_by_name (const char *name,
+					 struct addrinfo *template,
+					 int portnum, int flags,
+					 struct addrinfo **result)
+{
+#ifdef FAI_CACHE
+
+    struct face *ce;
+    int i, r, err;
+
+    err = krb5int_lock_fac();
+    if (err) {
+	errno = err;
+	return EAI_SYSTEM;
+    }
+    if (!find_face(name, &ce)) {
+	struct addrinfo myhints = { 0 }, *ai, *ai2;
+	int i4, i6, aierr;
+
+#ifdef DEBUG_ADDRINFO
+	printf("looking up new data for '%s'...\n", name);
+#endif
+	myhints.ai_socktype = SOCK_STREAM;
+	myhints.ai_flags = AI_CANONNAME;
+	/* Don't set ai_family -- we want to cache all address types,
+	   because the next lookup may not use the same constraints as
+	   the current one.  We *could* cache them separately, so that
+	   we never have to look up an IPv6 address if we are always
+	   asked for IPv4 only, but let's deal with that later, if we
+	   have to.  */
+	/* Try NULL for the service for now.
+
+	   It would be nice to use the requested service name, and not
+	   have to patch things up, but then we'd be doing multiple
+	   queries for the same host when we get different services.
+	   We were using "telnet" for a little more confidence that
+	   getaddrinfo would heed the hints to only give us stream
+	   socket types (with no socket type and null service name, we
+	   might get stream *and* dgram *and* raw, for each address,
+	   or only raw).  The RFC 3493 description of ai_socktype
+	   sometimes associates it with the specified service,
+	   sometimes not.
+
+	   But on Mac OS X (10.3, 10.4) they've "extended" getaddrinfo
+	   to make SRV RR queries.  (Please, somebody, show me
+	   something in the specs that actually supports this?  RFC
+	   3493 says nothing about it, but it does say getaddrinfo is
+	   the new way to look up hostnames.  RFC 2782 says SRV
+	   records should *not* be used unless the application
+	   protocol spec says to do so.  The Telnet spec does not say
+	   to do it.)  And then they complain when our code
+	   "unexpectedly" seems to use this "extension" in cases where
+	   they don't want it to be used.
+
+	   Fortunately, it appears that if we specify ai_socktype as
+	   SOCK_STREAM and use a null service name, we only get one
+	   copy of each address on all the platforms I've tried,
+	   although it may not have ai_socktype filled in properly.
+	   So, we'll fudge it with that for now.  */
+	aierr = system_getaddrinfo(name, NULL, &myhints, &ai);
+	if (aierr) {
+	    krb5int_unlock_fac();
+	    return aierr;
+	}
+	ce = malloc(sizeof(struct face));
+	memset(ce, 0, sizeof(*ce));
+	ce->expiration = time(0) + 30;
+	for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
+#ifdef DEBUG_ADDRINFO
+	    printf("  found an address in family %d...\n", ai2->ai_family);
+#endif
+	    switch (ai2->ai_family) {
+	    case AF_INET:
+		ce->naddrs4++;
+		break;
+	    case AF_INET6:
+		ce->naddrs6++;
+		break;
+	    default:
+		break;
+	    }
+	}
+	ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
+	if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
+	    krb5int_unlock_fac();
+	    system_freeaddrinfo(ai);
+	    return EAI_MEMORY;
+	}
+	ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
+	if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
+	    krb5int_unlock_fac();
+	    free(ce->addrs4);
+	    system_freeaddrinfo(ai);
+	    return EAI_MEMORY;
+	}
+	for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
+	    switch (ai2->ai_family) {
+	    case AF_INET:
+		ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
+		break;
+	    case AF_INET6:
+		ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
+		break;
+	    default:
+		break;
+	    }
+	}
+	ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
+	system_freeaddrinfo(ai);
+	plant_face(name, ce);
+    }
+    template->ai_family = AF_INET6;
+    template->ai_addrlen = sizeof(struct sockaddr_in6);
+    for (i = 0; i < ce->naddrs6; i++) {
+	r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
+	if (r) {
+	    krb5int_unlock_fac();
+	    return r;
+	}
+    }
+    template->ai_family = AF_INET;
+    template->ai_addrlen = sizeof(struct sockaddr_in);
+    for (i = 0; i < ce->naddrs4; i++) {
+	r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
+	if (r) {
+	    krb5int_unlock_fac();
+	    return r;
+	}
+    }
+    if (*result && (flags & AI_CANONNAME))
+	(*result)->ai_canonname = (ce->canonname
+				   ? strdup(ce->canonname)
+				   : NULL);
+    krb5int_unlock_fac();
+    return 0;
+
+#else
+
+    struct hostent *hp;
+    int i, r;
+    int herr;
+    GET_HOST_TMP htmp;
+
+    GET_HOST_BY_NAME (name, hp, herr, htmp);
+    if (hp == 0)
+	return translate_h_errno (herr);
+    for (i = 0; hp->h_addr_list[i]; i++) {
+	r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
+	if (r)
+	    return r;
+    }
+    if (*result && (flags & AI_CANONNAME))
+	(*result)->ai_canonname = strdup (hp->h_name);
+    return 0;
+
+#endif
+}
+
+static inline void
+fake_freeaddrinfo (struct addrinfo *ai)
+{
+    struct addrinfo *next;
+    while (ai) {
+	next = ai->ai_next;
+	if (ai->ai_canonname)
+	  free (ai->ai_canonname);
+	if (ai->ai_addr)
+	  free (ai->ai_addr);
+	free (ai);
+	ai = next;
+    }
+}
+
+static inline int
+fake_getaddrinfo (const char *name, const char *serv,
+		  const struct addrinfo *hint, struct addrinfo **result)
+{
+    struct addrinfo *res = 0;
+    int ret;
+    int port = 0, socktype;
+    int flags;
+    struct addrinfo template;
+
+#ifdef DEBUG_ADDRINFO
+    debug_dump_getaddrinfo_args(name, serv, hint);
+#endif
+
+    if (hint != 0) {
+	if (hint->ai_family != 0 && hint->ai_family != AF_INET)
+	    return EAI_NODATA;
+	socktype = hint->ai_socktype;
+	flags = hint->ai_flags;
+    } else {
+	socktype = 0;
+	flags = 0;
+    }
+
+    if (serv) {
+	size_t numlen = strspn (serv, "0123456789");
+	if (serv[numlen] == '\0') {
+	    /* pure numeric */
+	    unsigned long p = strtoul (serv, 0, 10);
+	    if (p == 0 || p > 65535)
+		return EAI_NONAME;
+	    port = htons (p);
+	} else {
+	    struct servent *sp;
+	    int try_dgram_too = 0, s_err;
+	    GET_SERV_TMP stmp;
+
+	    if (socktype == 0) {
+		try_dgram_too = 1;
+		socktype = SOCK_STREAM;
+	    }
+	try_service_lookup:
+	    GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
+			     sp, s_err, stmp);
+	    if (sp == 0) {
+		if (try_dgram_too) {
+		    socktype = SOCK_DGRAM;
+		    goto try_service_lookup;
+		}
+		return EAI_SERVICE;
+	    }
+	    port = sp->s_port;
+	}
+    }
+
+    if (name == 0) {
+	name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
+	flags |= AI_NUMERICHOST;
+    }
+
+    template.ai_family = AF_INET;
+    template.ai_addrlen = sizeof (struct sockaddr_in);
+    template.ai_socktype = socktype;
+    template.ai_protocol = 0;
+    template.ai_flags = 0;
+    template.ai_canonname = 0;
+    template.ai_next = 0;
+    template.ai_addr = 0;
+
+    /* If NUMERICHOST is set, parse a numeric address.
+       If it's not set, don't accept such names.  */
+    if (flags & AI_NUMERICHOST) {
+	struct in_addr addr4;
+#if 0
+	ret = inet_aton (name, &addr4);
+	if (ret)
+	    return EAI_NONAME;
+#else
+	addr4.s_addr = inet_addr (name);
+	if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
+	    /* 255.255.255.255 or parse error, both bad */
+	    return EAI_NONAME;
+#endif
+	ret = fai_add_entry (&res, &addr4, port, &template);
+    } else {
+	ret = fai_add_hosts_by_name (name, &template, port, flags,
+				     &res);
+    }
+
+    if (ret && ret != NO_ADDRESS) {
+	fake_freeaddrinfo (res);
+	return ret;
+    }
+    if (res == 0)
+	return NO_ADDRESS;
+    *result = res;
+    return 0;
+}
+
+#ifdef NEED_FAKE_GETNAMEINFO
+static inline int
+fake_getnameinfo (const struct sockaddr *sa, socklen_t len,
+		  char *host, socklen_t hostlen,
+		  char *service, socklen_t servicelen,
+		  int flags)
+{
+    struct hostent *hp;
+    const struct sockaddr_in *sinp;
+    struct servent *sp;
+    size_t hlen, slen;
+
+    if (sa->sa_family != AF_INET) {
+	return EAI_FAMILY;
+    }
+    sinp = (const struct sockaddr_in *) sa;
+
+    hlen = hostlen;
+    if (hostlen < 0 || hlen != hostlen) {
+	errno = EINVAL;
+	return EAI_SYSTEM;
+    }
+    slen = servicelen;
+    if (servicelen < 0 || slen != servicelen) {
+	errno = EINVAL;
+	return EAI_SYSTEM;
+    }
+
+    if (host) {
+	if (flags & NI_NUMERICHOST) {
+#if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
+	    /* The inet_ntoa call, passing a struct, fails on IRIX 6.5
+	       using gcc 2.95; we get back "0.0.0.0".  Since this in a
+	       configuration still important at Athena, here's the
+	       workaround, which also happens to be thread-safe....  */
+	    const unsigned char *uc;
+	    char tmpbuf[20];
+	numeric_host:
+	    uc = (const unsigned char *) &sinp->sin_addr;
+	    sprintf(tmpbuf, "%d.%d.%d.%d", uc[0], uc[1], uc[2], uc[3]);
+	    strncpy(host, tmpbuf, hlen);
+#else
+	    char *p;
+	numeric_host:
+	    p = inet_ntoa (sinp->sin_addr);
+	    strncpy (host, p, hlen);
+#endif
+	} else {
+	    int herr;
+	    GET_HOST_TMP htmp;
+
+	    GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
+			     sizeof (struct in_addr),
+			     sa->sa_family, hp, herr, htmp);
+	    if (hp == 0) {
+		if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
+		    goto numeric_host;
+		return translate_h_errno (herr);
+	    }
+	    /* According to the Open Group spec, getnameinfo can
+	       silently truncate, but must still return a
+	       null-terminated string.  */
+	    strncpy (host, hp->h_name, hlen);
+	}
+	host[hostlen-1] = 0;
+    }
+
+    if (service) {
+	if (flags & NI_NUMERICSERV) {
+	    char numbuf[10];
+	    int port;
+	numeric_service:
+	    port = ntohs (sinp->sin_port);
+	    if (port < 0 || port > 65535)
+		return EAI_FAIL;
+	    sprintf (numbuf, "%d", port);
+	    strncpy (service, numbuf, slen);
+	} else {
+	    int serr;
+	    GET_SERV_TMP stmp;
+
+	    GET_SERV_BY_PORT(sinp->sin_port,
+			     (flags & NI_DGRAM) ? "udp" : "tcp",
+			     sp, serr, stmp);
+	    if (sp == 0)
+		goto numeric_service;
+	    strncpy (service, sp->s_name, slen);
+	}
+	service[servicelen-1] = 0;
+    }
+
+    return 0;
+}
+#endif
+
+#if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
+
+static inline
+char *gai_strerror (int code)
+{
+    switch (code) {
+    case EAI_ADDRFAMILY: return "address family for nodename not supported";
+    case EAI_AGAIN:	return "temporary failure in name resolution";
+    case EAI_BADFLAGS:	return "bad flags to getaddrinfo/getnameinfo";
+    case EAI_FAIL:	return "non-recoverable failure in name resolution";
+    case EAI_FAMILY:	return "ai_family not supported";
+    case EAI_MEMORY:	return "out of memory";
+    case EAI_NODATA:	return "no address associated with hostname";
+    case EAI_NONAME:	return "name does not exist";
+    case EAI_SERVICE:	return "service name not supported for specified socket type";
+    case EAI_SOCKTYPE:	return "ai_socktype not supported";
+    case EAI_SYSTEM:	return strerror (errno);
+    default:		return "bogus getaddrinfo error?";
+    }
+}
+#endif
+
+static inline int translate_h_errno (int h)
+{
+    switch (h) {
+    case 0:
+	return 0;
+#ifdef NETDB_INTERNAL
+    case NETDB_INTERNAL:
+	if (errno == ENOMEM)
+	    return EAI_MEMORY;
+	return EAI_SYSTEM;
+#endif
+    case HOST_NOT_FOUND:
+	return EAI_NONAME;
+    case TRY_AGAIN:
+	return EAI_AGAIN;
+    case NO_RECOVERY:
+	return EAI_FAIL;
+    case NO_DATA:
+#if NO_DATA != NO_ADDRESS
+    case NO_ADDRESS:
+#endif
+	return EAI_NODATA;
+    default:
+	return EAI_SYSTEM;
+    }
+}
+
+#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
+static inline
+int getaddrinfo (const char *name, const char *serv,
+		 const struct addrinfo *hint, struct addrinfo **result)
+{
+    return fake_getaddrinfo(name, serv, hint, result);
+}
+
+static inline
+void freeaddrinfo (struct addrinfo *ai)
+{
+    fake_freeaddrinfo(ai);
+}
+
+#ifdef NEED_FAKE_GETNAMEINFO
+static inline
+int getnameinfo (const struct sockaddr *sa, socklen_t len,
+		 char *host, socklen_t hostlen,
+		 char *service, socklen_t servicelen,
+		 int flags)
+{
+    return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
+			    flags);
+}
+#endif /* NEED_FAKE_GETNAMEINFO */
+#endif /* HAVE_FAKE_GETADDRINFO */
+#endif /* NEED_FAKE_GETADDRINFO */
+
+
+#ifdef WRAP_GETADDRINFO
+
+static inline
+int
+getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
+	     struct addrinfo **result)
+{
+    int aierr;
+#if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
+    struct addrinfo *ai;
+#endif
+#ifdef NUMERIC_SERVICE_BROKEN
+    int service_is_numeric = 0;
+    int service_port = 0;
+    int socket_type = 0;
+#endif
+
+#ifdef DEBUG_ADDRINFO
+    debug_dump_getaddrinfo_args(name, serv, hint);
+#endif
+
+#ifdef NUMERIC_SERVICE_BROKEN
+    /* AIX 4.3.3 is broken.  (Or perhaps out of date?)
+
+       If a numeric service is provided, and it doesn't correspond to
+       a known service name for tcp or udp (as appropriate), an error
+       code (for "host not found") is returned.  If the port maps to a
+       known service for both udp and tcp, all is well.  */
+    if (serv && serv[0] && isdigit(serv[0])) {
+	unsigned long lport;
+	char *end;
+	lport = strtoul(serv, &end, 10);
+	if (!*end) {
+	    if (lport > 65535)
+		return EAI_SOCKTYPE;
+	    service_is_numeric = 1;
+	    service_port = htons(lport);
+#ifdef AI_NUMERICSERV
+	    if (hint && hint->ai_flags & AI_NUMERICSERV)
+		serv = "9";
+	    else
+#endif
+		serv = "discard";	/* defined for both udp and tcp */
+	    if (hint)
+		socket_type = hint->ai_socktype;
+	}
+    }
+#endif
+
+    aierr = system_getaddrinfo (name, serv, hint, result);
+    if (aierr || *result == 0) {
+#ifdef DEBUG_ADDRINFO
+	debug_dump_error(aierr);
+#endif
+	return aierr;
+    }
+
+    /* Linux libc version 6 (libc-2.2.4.so on Debian) is broken.
+
+       RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
+       flag of the first returned structure has the canonical name of
+       the host.  Instead, GNU libc sets ai_canonname in each returned
+       structure to the name that the corresponding address maps to,
+       if any, or a printable numeric form.
+
+       RFC 2553 bis and the new Open Group spec say that field will be
+       the canonical name if it can be determined, otherwise, the
+       provided hostname or a copy of it.
+
+       IMNSHO, "canonical name" means CNAME processing and not PTR
+       processing, but I can see arguing it.  Using the numeric form
+       when that's not the form provided is just wrong.  So, let's fix
+       it.
+
+       The glibc 2.2.5 sources indicate that the canonical name is
+       *not* allocated separately, it's just some extra storage tacked
+       on the end of the addrinfo structure.  So, let's try this
+       approach: If getaddrinfo sets ai_canonname, we'll replace the
+       *first* one with allocated storage, and free up that pointer in
+       freeaddrinfo if it's set; the other ai_canonname fields will be
+       left untouched.  And we'll just pray that the application code
+       won't mess around with the list structure; if we start doing
+       that, we'll have to start replacing and freeing all of the
+       ai_canonname fields.
+
+       Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
+
+       Since it's dependent on the target hostname, it's hard to check
+       for at configure time.  Always do it on Linux for now.  When
+       they get around to fixing it, add a compile-time or run-time
+       check for the glibc version in use.
+
+       Some Windows documentation says that even when AI_CANONNAME is
+       set, the returned ai_canonname field can be null.  The NetBSD
+       1.5 implementation also does this, if the input hostname is a
+       numeric host address string.  That case isn't handled well at
+       the moment.
+
+       Libc version 5 didn't have getaddrinfo at all.  */
+
+#ifdef COPY_FIRST_CANONNAME
+    /*
+     * This code must *always* return an error, return a null
+     * ai_canonname, or return an ai_canonname allocated here using
+     * malloc, so that freeaddrinfo can always free a non-null
+     * ai_canonname.  Note that it really doesn't matter if the
+     * AI_CANONNAME flag was set.
+     */
+    ai = *result;
+    if (ai->ai_canonname) {
+	struct hostent *hp;
+	const char *name2 = 0;
+	int i, herr;
+	GET_HOST_TMP htmp;
+
+	/*
+	 * Current versions of GET_HOST_BY_NAME will fail if the
+	 * target hostname has IPv6 addresses only.  Make sure it
+	 * fails fairly cleanly.
+	 */
+	GET_HOST_BY_NAME (name, hp, herr, htmp);
+	if (hp == 0) {
+	    /*
+	     * This case probably means it's an IPv6-only name.  If
+	     * ai_canonname is a numeric address, get rid of it.
+	     */
+	    if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
+		ai->ai_canonname = 0;
+	    name2 = ai->ai_canonname ? ai->ai_canonname : name;
+	} else {
+	    /* Sometimes gethostbyname will be directed to /etc/hosts
+	       first, and sometimes that file will have entries with
+	       the unqualified name first.  So take the first entry
+	       that looks like it could be a FQDN.  */
+	    for (i = 0; hp->h_aliases[i]; i++) {
+		if (strchr(hp->h_aliases[i], '.') != 0) {
+		    name2 = hp->h_aliases[i];
+		    break;
+		}
+	    }
+	    /* Give up, just use the first name (h_name ==
+	       h_aliases[0] on all systems I've seen).  */
+	    if (hp->h_aliases[i] == 0)
+		name2 = hp->h_name;
+	}
+
+	ai->ai_canonname = strdup(name2);
+	if (name2 != 0 && ai->ai_canonname == 0) {
+	    system_freeaddrinfo(ai);
+	    *result = 0;
+#ifdef DEBUG_ADDRINFO
+	    debug_dump_error(EAI_MEMORY);
+#endif
+	    return EAI_MEMORY;
+	}
+	/* Zap the remaining ai_canonname fields glibc fills in, in
+	   case the application messes around with the list
+	   structure.  */
+	while ((ai = ai->ai_next) != NULL)
+	    ai->ai_canonname = 0;
+    }
+#endif
+
+#ifdef NUMERIC_SERVICE_BROKEN
+    if (service_port != 0) {
+	for (ai = *result; ai; ai = ai->ai_next) {
+	    if (socket_type != 0 && ai->ai_socktype == 0)
+		/* Is this check actually needed?  */
+		ai->ai_socktype = socket_type;
+	    switch (ai->ai_family) {
+	    case AF_INET:
+		((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port;
+		break;
+	    case AF_INET6:
+		((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port;
+		break;
+	    }
+	}
+    }
+#endif
+
+#ifdef _AIX
+    for (ai = *result; ai; ai = ai->ai_next) {
+	/* AIX 4.3.3 libc is broken.  It doesn't set the family or len
+	   fields of the sockaddr structures.  Usually, sa_family is
+	   zero, but I've seen it set to 1 in some cases also (maybe
+	   just leftover from previous contents of the memory
+	   block?).  So, always override what libc returned.  */
+	ai->ai_addr->sa_family = ai->ai_family;
+#ifdef HAVE_SA_LEN /* always true on AIX, actually */
+	ai->ai_addr->sa_len = ai->ai_addrlen;
+#endif
+    }
+#endif
+
+    /* Not dealt with currently:
+
+       - Some versions of GNU libc can lose some IPv4 addresses in
+	 certain cases when multiple IPv4 and IPv6 addresses are
+	 available.  */
+
+#ifdef DEBUG_ADDRINFO
+    debug_dump_addrinfos(*result);
+#endif
+
+    return 0;
+}
+
+static inline
+void freeaddrinfo (struct addrinfo *ai)
+{
+#ifdef COPY_FIRST_CANONNAME
+    if (ai) {
+      free(ai->ai_canonname);
+	ai->ai_canonname = 0;
+	system_freeaddrinfo(ai);
+    }
+#else
+    system_freeaddrinfo(ai);
+#endif
+}
+#endif /* WRAP_GETADDRINFO */
+
+static int krb5int_lock_fac (void)
+{
+    int err;
+    err = krb5int_call_thread_support_init();
+    if (err)
+	return err;
+    return k5_mutex_lock(&krb5int_fac.lock);
+}
+
+static int krb5int_unlock_fac (void)
+{
+    return k5_mutex_unlock(&krb5int_fac.lock);
+}
+
+/* Some systems don't define in6addr_any.  */
+const struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT;
+
+int krb5int_getaddrinfo (const char *node, const char *service,
+			 const struct addrinfo *hints,
+			 struct addrinfo **aip)
+{
+    return getaddrinfo(node, service, hints, aip);
+}
+
+void krb5int_freeaddrinfo (struct addrinfo *ai)
+{
+    freeaddrinfo(ai);
+}
+
+const char *krb5int_gai_strerror(int err)
+{
+    return gai_strerror(err);
+}
+
+int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+			 char *hbuf, size_t hbuflen,
+			 char *sbuf, size_t sbuflen,
+			 int flags)
+{
+    return getnameinfo(sa, salen, hbuf, hbuflen, sbuf, sbuflen, flags);
+}
diff --git a/krb5-1-6/src/util/support/gmt_mktime.c b/krb5-1-6/src/util/support/gmt_mktime.c
new file mode 100644
index 000000000..65ab87349
--- /dev/null
+++ b/krb5-1-6/src/util/support/gmt_mktime.c
@@ -0,0 +1,127 @@
+/* This code placed in the public domain by Mark W. Eichin */
+
+#include <stdio.h>
+#include "autoconf.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#include <time.h>
+#endif
+
+/* take a struct tm, return seconds from GMT epoch */
+/* like mktime, this ignores tm_wday and tm_yday. */
+/* unlike mktime, this does not set them... it only passes a return value. */
+
+static const int days_in_month[12] = {
+0,				/* jan 31 */
+31,				/* feb 28 */
+59,				/* mar 31 */
+90,				/* apr 30 */
+120,				/* may 31 */
+151,				/* jun 30 */
+181,				/* jul 31 */
+212,				/* aug 31 */
+243,				/* sep 30 */
+273,				/* oct 31 */
+304,				/* nov 30 */
+334				/* dec 31 */
+};
+
+#define hasleapday(year) (year%400?(year%100?(year%4?0:1):0):1)
+
+time_t krb5int_gmt_mktime(struct tm *t)
+{
+  time_t accum;
+
+#define assert_time(cnd) if(!(cnd)) return (time_t) -1
+
+  /*
+   * For 32-bit signed time_t centered on 1/1/1970, the range is:
+   * time 0x80000000 -> Fri Dec 13 16:45:52 1901
+   * time 0x7fffffff -> Mon Jan 18 22:14:07 2038
+   *
+   * So years 1901 and 2038 are allowable, but we can't encode all
+   * dates in those years, and we're not doing overflow/underflow
+   * checking for such cases.
+   */
+  assert_time(t->tm_year>=1);
+  assert_time(t->tm_year<=138);
+
+  assert_time(t->tm_mon>=0);
+  assert_time(t->tm_mon<=11);
+  assert_time(t->tm_mday>=1);
+  assert_time(t->tm_mday<=31);
+  assert_time(t->tm_hour>=0);
+  assert_time(t->tm_hour<=23);
+  assert_time(t->tm_min>=0);
+  assert_time(t->tm_min<=59);
+  assert_time(t->tm_sec>=0);
+  assert_time(t->tm_sec<=62);
+
+#undef assert_time
+
+
+  accum = t->tm_year - 70;
+  accum *= 365;			/* 365 days/normal year */
+
+  /* add in leap day for all previous years */
+  if (t->tm_year >= 70)
+    accum += (t->tm_year - 69) / 4;
+  else
+    accum -= (72 - t->tm_year) / 4;
+  /* add in leap day for this year */
+  if(t->tm_mon >= 2)		/* march or later */
+    if(hasleapday((t->tm_year + 1900))) accum += 1;
+
+  accum += days_in_month[t->tm_mon];
+  accum += t->tm_mday-1;	/* days of month are the only 1-based field */
+  accum *= 24;			/* 24 hour/day */
+  accum += t->tm_hour;
+  accum *= 60;			/* 60 minute/hour */
+  accum += t->tm_min;
+  accum *= 60;			/* 60 seconds/minute */
+  accum += t->tm_sec;
+
+  return accum;
+}
+
+#ifdef TEST_LEAP
+int
+main (int argc, char *argv[])
+{
+  int yr;
+  time_t t;
+  struct tm tm = {
+    .tm_mon = 0, .tm_mday = 1,
+    .tm_hour = 0, .tm_min = 0, .tm_sec = 0,
+  };
+  for (yr = 60; yr <= 104; yr++)
+    {
+      printf ("1/1/%d%c -> ", 1900 + yr, hasleapday((1900+yr)) ? '*' : ' ');
+      tm.tm_year = yr;
+      t = gmt_mktime (&tm);
+      if (t == (time_t) -1)
+	printf ("-1\n");
+      else
+	{
+	  long u;
+	  if (t % (24 * 60 * 60))
+	    printf ("(not integral multiple of days) ");
+	  u = t / (24 * 60 * 60);
+	  printf ("%3ld*365%+ld\t0x%08lx\n",
+		  (long) (u / 365), (long) (u % 365),
+		  (long) t);
+	}
+    }
+  t = 0x80000000, printf ("time 0x%lx -> %s", t, ctime (&t));
+  t = 0x7fffffff, printf ("time 0x%lx -> %s", t, ctime (&t));
+  return 0;
+}
+#endif
diff --git a/krb5-1-6/src/util/support/init-addrinfo.c b/krb5-1-6/src/util/support/init-addrinfo.c
new file mode 100644
index 000000000..4c94dc743
--- /dev/null
+++ b/krb5-1-6/src/util/support/init-addrinfo.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA.  All Rights Reserved.
+ * 
+ * This software is being provided to you, the LICENSEE, by the 
+ * Massachusetts Institute of Technology (M.I.T.) under the following 
+ * license.  By obtaining, using and/or copying this software, you agree 
+ * that you have read, understood, and will comply with these terms and 
+ * conditions:  
+ * 
+ * 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 or 
+ * royalty is hereby granted, provided that you agree to comply with the 
+ * following copyright notice and statements, including the disclaimer, and 
+ * that the same appear on ALL copies of the software and documentation, 
+ * including modifications that you make for internal use or for 
+ * distribution:
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 
+ * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not 
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.   
+ * 
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 
+ * be used in advertising or publicity pertaining to distribution of the 
+ * software.  Title to copyright in this software and any associated 
+ * documentation shall at all times remain with M.I.T., and USER agrees to 
+ * preserve same.
+ *
+ * Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.  
+ */
+
+/* Stuff that needs initialization for fake-addrinfo.c.
+
+   Separated out, so that static linking against this library doesn't
+   require pulling in socket/nsl/whatever libraries for code not using
+   getaddrinfo.  */
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+#include "k5-platform.h"
+#include "k5-thread.h"
+
+#include <stdio.h>		/* for sprintf */
+#include <errno.h>
+
+#define IMPLEMENT_FAKE_GETADDRINFO
+#include "fake-addrinfo.h"
+#include "cache-addrinfo.h"
+
+struct fac krb5int_fac = { K5_MUTEX_PARTIAL_INITIALIZER, 0 };
+
+int krb5int_init_fac (void)
+{
+    return k5_mutex_finish_init(&krb5int_fac.lock);
+}
+
+void krb5int_fini_fac (void)
+{
+    k5_mutex_destroy(&krb5int_fac.lock);
+}
diff --git a/krb5-1-6/src/util/support/libkrb5support.exports b/krb5-1-6/src/util/support/libkrb5support.exports
new file mode 100644
index 000000000..850db8c64
--- /dev/null
+++ b/krb5-1-6/src/util/support/libkrb5support.exports
@@ -0,0 +1,34 @@
+krb5int_key_register
+krb5int_key_delete
+krb5int_getspecific
+krb5int_setspecific
+krb5int_mutex_lock_update_stats
+krb5int_mutex_unlock_update_stats
+krb5int_mutex_report_stats
+krb5int_getaddrinfo
+krb5int_freeaddrinfo
+krb5int_gai_strerror
+krb5int_getnameinfo
+krb5int_in6addr_any
+krb5int_pthread_loaded
+krb5int_open_plugin
+krb5int_close_plugin
+krb5int_get_plugin_data
+krb5int_get_plugin_func
+krb5int_open_plugin_dirs
+krb5int_close_plugin_dirs
+krb5int_get_plugin_dir_data
+krb5int_get_plugin_dir_func
+krb5int_free_plugin_dir_data
+krb5int_free_plugin_dir_func
+krb5int_mutex_alloc
+krb5int_mutex_free
+krb5int_mutex_lock
+krb5int_mutex_unlock
+krb5int_set_error
+krb5int_vset_error
+krb5int_get_error
+krb5int_free_error
+krb5int_clear_error
+krb5int_set_error_info_callout_fn
+krb5int_gmt_mktime
diff --git a/krb5-1-6/src/util/support/plugins.c b/krb5-1-6/src/util/support/plugins.c
new file mode 100644
index 000000000..b26726fab
--- /dev/null
+++ b/krb5-1-6/src/util/support/plugins.c
@@ -0,0 +1,646 @@
+/*
+ * util/support/plugins.c
+ *
+ * Copyright 2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Plugin module support, and shims around dlopen/whatever.
+ */
+
+#include "k5-plugin.h"
+#if USE_DLOPEN
+#include <dlfcn.h>
+#endif
+#if USE_CFBUNDLE
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdarg.h>
+static void Tprintf (const char *fmt, ...)
+{
+#ifdef DEBUG
+    va_list va;
+    va_start (va, fmt);
+    vfprintf (stderr, fmt, va);
+    va_end (va);
+#endif
+}
+
+struct plugin_file_handle {
+#if USE_DLOPEN
+    void *dlhandle;
+#endif
+#if USE_CFBUNDLE
+    CFBundleRef bundle;
+#endif
+#if !defined (USE_DLOPEN) && !defined (USE_CFBUNDLE)
+    char dummy;
+#endif
+};
+
+long KRB5_CALLCONV
+krb5int_open_plugin (const char *filepath, struct plugin_file_handle **h, struct errinfo *ep)
+{
+    long err = 0;
+    struct stat statbuf;
+    struct plugin_file_handle *htmp = NULL;
+    int got_plugin = 0;
+
+    if (!err) {
+        if (stat (filepath, &statbuf) < 0) {
+            Tprintf ("stat(%s): %s\n", filepath, strerror (errno));
+            err = errno;
+        }
+    }
+
+    if (!err) {
+        htmp = calloc (1, sizeof (*htmp)); /* calloc initializes ptrs to NULL */
+        if (htmp == NULL) { err = errno; }
+    }
+
+#if USE_DLOPEN
+    if (!err && (statbuf.st_mode & S_IFMT) == S_IFREG) {
+        void *handle = NULL;
+#ifdef RTLD_GROUP
+#define PLUGIN_DLOPEN_FLAGS (RTLD_NOW | RTLD_LOCAL | RTLD_GROUP)
+#else
+#define PLUGIN_DLOPEN_FLAGS (RTLD_NOW | RTLD_LOCAL)
+#endif
+
+        if (!err) {
+            handle = dlopen(filepath, PLUGIN_DLOPEN_FLAGS);
+            if (handle == NULL) {
+                const char *e = dlerror();
+                Tprintf ("dlopen(%s): %s\n", filepath, e);
+                err = ENOENT; /* XXX */
+		krb5int_set_error (ep, err, "%s", e);
+            }
+        }
+
+        if (!err) {
+            got_plugin = 1;
+            htmp->dlhandle = handle;
+            handle = NULL;
+        }
+
+        if (handle != NULL) { dlclose (handle); }
+    }
+#endif
+
+#if USE_CFBUNDLE
+    if (!err && (statbuf.st_mode & S_IFMT) == S_IFDIR) {
+        CFStringRef pluginPath = NULL;
+        CFURLRef pluginURL = NULL;
+        CFBundleRef pluginBundle = NULL;
+
+        if (!err) {
+            pluginPath = CFStringCreateWithCString (kCFAllocatorDefault, filepath, 
+                                                    kCFStringEncodingASCII);
+            if (pluginPath == NULL) { err = ENOMEM; }
+        }
+        
+        if (!err) {
+            pluginURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, pluginPath, 
+                                                       kCFURLPOSIXPathStyle, true);
+            if (pluginURL == NULL) { err = ENOMEM; }
+        }
+        
+        if (!err) {
+            pluginBundle = CFBundleCreate (kCFAllocatorDefault, pluginURL);
+            if (pluginBundle == NULL) { err = ENOENT; } /* XXX need better error */
+        }
+        
+        if (!err) {
+            if (!CFBundleIsExecutableLoaded (pluginBundle)) {
+                int loaded = CFBundleLoadExecutable (pluginBundle);
+                if (!loaded) { err = ENOENT; }  /* XXX need better error */
+            }
+        }
+        
+        if (!err) {
+            got_plugin = 1;
+            htmp->bundle = pluginBundle;
+            pluginBundle = NULL;  /* htmp->bundle takes ownership */
+        }
+
+        if (pluginBundle != NULL) { CFRelease (pluginBundle); }
+        if (pluginURL    != NULL) { CFRelease (pluginURL); }
+        if (pluginPath   != NULL) { CFRelease (pluginPath); }
+    }
+#endif
+        
+    if (!err && !got_plugin) {
+        err = ENOENT;  /* no plugin or no way to load plugins */
+    }
+    
+    if (!err) {
+        *h = htmp;
+        htmp = NULL;  /* h takes ownership */
+    }
+    
+    if (htmp != NULL) { free (htmp); }
+    
+    return err;
+}
+
+static long
+krb5int_get_plugin_sym (struct plugin_file_handle *h, 
+                        const char *csymname, int isfunc, void **ptr,
+			struct errinfo *ep)
+{
+    long err = 0;
+    void *sym = NULL;
+    
+#if USE_DLOPEN
+    if (!err && !sym && (h->dlhandle != NULL)) {
+        /* XXX Do we need to add a leading "_" to the symbol name on any
+        modern platforms?  */
+        sym = dlsym (h->dlhandle, csymname);
+        if (sym == NULL) {
+            const char *e = dlerror (); /* XXX copy and save away */
+            Tprintf ("dlsym(%s): %s\n", csymname, e);
+            err = ENOENT; /* XXX */
+	    krb5int_set_error(ep, err, "%s", e);
+        }
+    }
+#endif
+    
+#if USE_CFBUNDLE
+    if (!err && !sym && (h->bundle != NULL)) {
+        CFStringRef cfsymname = NULL;
+        
+        if (!err) {
+            cfsymname = CFStringCreateWithCString (kCFAllocatorDefault, csymname, 
+                                                   kCFStringEncodingASCII);
+            if (cfsymname == NULL) { err = ENOMEM; }
+        }
+        
+        if (!err) {
+            if (isfunc) {
+                sym = CFBundleGetFunctionPointerForName (h->bundle, cfsymname);
+            } else {
+                sym = CFBundleGetDataPointerForName (h->bundle, cfsymname);
+            }
+            if (sym == NULL) { err = ENOENT; }  /* XXX */       
+        }
+        
+        if (cfsymname != NULL) { CFRelease (cfsymname); }
+    }
+#endif
+    
+    if (!err && (sym == NULL)) {
+        err = ENOENT;  /* unimplemented */
+    }
+    
+    if (!err) {
+        *ptr = sym;
+    }
+    
+    return err;
+}
+
+long KRB5_CALLCONV
+krb5int_get_plugin_data (struct plugin_file_handle *h, const char *csymname,
+			 void **ptr, struct errinfo *ep)
+{
+    return krb5int_get_plugin_sym (h, csymname, 0, ptr, ep);
+}
+
+long KRB5_CALLCONV
+krb5int_get_plugin_func (struct plugin_file_handle *h, const char *csymname,
+			 void (**ptr)(), struct errinfo *ep)
+{
+    void *dptr = NULL;    
+    long err = krb5int_get_plugin_sym (h, csymname, 1, &dptr, ep);
+    if (!err) {
+        /* Cast function pointers to avoid code duplication */
+        *ptr = (void (*)()) dptr;
+    }
+    return err;
+}
+
+void KRB5_CALLCONV
+krb5int_close_plugin (struct plugin_file_handle *h)
+{
+#if USE_DLOPEN
+    if (h->dlhandle != NULL) { dlclose(h->dlhandle); }
+#endif
+#if USE_CFBUNDLE
+    /* Do not call CFBundleUnloadExecutable because it's not ref counted. 
+     * CFRelease will unload the bundle if the internal refcount goes to zero. */
+    if (h->bundle != NULL) { CFRelease (h->bundle); }
+#endif
+    free (h);
+}
+
+/* autoconf docs suggest using this preference order */
+#if HAVE_DIRENT_H || USE_DIRENT_H
+#include <dirent.h>
+#define NAMELEN(D) strlen((D)->d_name)
+#else
+#define dirent direct
+#define NAMELEN(D) ((D)->d->namlen)
+#if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+#elif HAVE_SYS_DIR_H
+# include <sys/dir.h>
+#elif HAVE_NDIR_H
+# include <ndir.h>
+#endif
+#endif
+
+
+#ifdef HAVE_STRERROR_R
+#define ERRSTR(ERR, BUF) \
+    (strerror_r (ERR, BUF, sizeof(BUF)) == 0 ? BUF : strerror (ERR))
+#else
+#define ERRSTR(ERR, BUF) \
+    (strerror (ERR))
+#endif
+
+static long
+krb5int_plugin_file_handle_array_init (struct plugin_file_handle ***harray)
+{
+    long err = 0;
+
+    *harray = calloc (1, sizeof (**harray)); /* calloc initializes to NULL */
+    if (*harray == NULL) { err = errno; }
+
+    return err;
+}
+
+static long
+krb5int_plugin_file_handle_array_add (struct plugin_file_handle ***harray, int *count, 
+                                      struct plugin_file_handle *p)
+{
+    long err = 0;
+    struct plugin_file_handle **newharray = NULL;
+    int newcount = *count + 1;
+    
+    newharray = realloc (*harray, ((newcount + 1) * sizeof (**harray))); /* +1 for NULL */
+    if (newharray == NULL) { 
+        err = errno; 
+    } else {
+        newharray[newcount - 1] = p;
+        newharray[newcount] = NULL;
+	*count = newcount;
+        *harray = newharray;
+    }
+
+    return err;    
+}
+
+static void
+krb5int_plugin_file_handle_array_free (struct plugin_file_handle **harray)
+{
+    if (harray != NULL) {
+        int i;
+        for (i = 0; harray[i] != NULL; i++) {
+            krb5int_close_plugin (harray[i]);
+        }
+        free (harray);
+    }
+}
+
+#if TARGET_OS_MAC
+#define FILEEXTS { "", ".bundle", ".so", NULL }
+#elif defined(_WIN32)
+#define FILEEXTS  { "", ".dll", NULL }
+#else
+#define FILEEXTS  { "", ".so", NULL }
+#endif
+
+
+static void 
+krb5int_free_plugin_filenames (char **filenames)
+{
+    if (filenames != NULL) { 
+        int i;
+        for (i = 0; filenames[i] != NULL; i++) {
+            free (filenames[i]);
+        }
+        free (filenames); 
+    }    
+}
+
+
+static long 
+krb5int_get_plugin_filenames (const char * const *filebases, char ***filenames)
+{
+    long err = 0;
+    static const char *const fileexts[] = FILEEXTS;
+    char **tempnames = NULL;
+    int i;
+
+    if (!err) {
+        size_t count = 0;
+        for (i = 0; filebases[i] != NULL; i++, count++);
+        for (i = 0; fileexts[i] != NULL; i++, count++);
+        tempnames = calloc (count, sizeof (char *));
+        if (tempnames == NULL) { err = errno; }
+    }
+
+    if (!err) {
+        int j;
+        for (i = 0; !err && (filebases[i] != NULL); i++) {
+            size_t baselen = strlen (filebases[i]);
+            for (j = 0; !err && (fileexts[j] != NULL); j++) {
+                size_t len = baselen + strlen (fileexts[j]) + 2; /* '.' + NULL */
+                tempnames[i+j] = malloc (len * sizeof (char));
+                if (tempnames[i+j] == NULL) { 
+                    err = errno; 
+                } else {
+                    sprintf (tempnames[i+j], "%s%s", filebases[i], fileexts[j]);
+                }
+            }
+        }
+    }
+    
+    if (!err) {
+        *filenames = tempnames;
+        tempnames = NULL;
+    }
+    
+    if (tempnames != NULL) { krb5int_free_plugin_filenames (tempnames); }
+    
+    return err;
+}
+
+
+/* Takes a NULL-terminated list of directories.  If filebases is NULL, filebases is ignored
+ * all plugins in the directories are loaded.  If filebases is a NULL-terminated array of names, 
+ * only plugins in the directories with those name (plus any platform extension) are loaded. */
+
+long KRB5_CALLCONV
+krb5int_open_plugin_dirs (const char * const *dirnames,
+                          const char * const *filebases,
+			  struct plugin_dir_handle *dirhandle,
+                          struct errinfo *ep)
+{
+    long err = 0;
+    struct plugin_file_handle **h = NULL;
+    int count = 0;
+    char **filenames = NULL;
+    int i;
+
+    if (!err) {
+        err = krb5int_plugin_file_handle_array_init (&h);
+    }
+    
+    if (!err && (filebases != NULL)) {
+	err = krb5int_get_plugin_filenames (filebases, &filenames);
+    }
+    
+    for (i = 0; !err && dirnames[i] != NULL; i++) {
+	size_t dirnamelen = strlen (dirnames[i]) + 1; /* '/' */
+        if (filenames != NULL) {
+            /* load plugins with names from filenames from each directory */
+            int j;
+            
+            for (j = 0; !err && filenames[j] != NULL; j++) {
+                struct plugin_file_handle *handle = NULL;
+		char *filepath = NULL;
+		
+		if (!err) {
+		    filepath = malloc (dirnamelen + strlen (filenames[j]) + 1); /* NULL */
+		    if (filepath == NULL) { 
+			err = errno; 
+		    } else {
+			sprintf (filepath, "%s/%s", dirnames[i], filenames[j]);
+		    }
+		}
+		
+                if (krb5int_open_plugin (filepath, &handle, ep) == 0) {
+                    err = krb5int_plugin_file_handle_array_add (&h, &count, handle);
+                    if (!err) { handle = NULL; }  /* h takes ownership */
+                }
+                
+		if (filepath != NULL) { free (filepath); }
+		if (handle   != NULL) { krb5int_close_plugin (handle); }
+            }
+        } else {
+            /* load all plugins in each directory */
+#ifndef _WIN32
+	    DIR *dir = opendir (dirnames[i]);
+            
+            while (dir != NULL && !err) {
+                struct dirent *d = NULL;
+                char *filepath = NULL;
+                struct plugin_file_handle *handle = NULL;
+                
+                d = readdir (dir);
+                if (d == NULL) { break; }
+                
+                if ((strcmp (d->d_name, ".") == 0) || 
+                    (strcmp (d->d_name, "..") == 0)) {
+                    continue;
+                }
+                
+		if (!err) {
+                    int len = NAMELEN (d);
+		    filepath = malloc (dirnamelen + len + 1); /* NULL */
+		    if (filepath == NULL) { 
+			err = errno; 
+		    } else {
+			sprintf (filepath, "%s/%*s", dirnames[i], len, d->d_name);
+		    }
+		}
+                
+                if (!err) {            
+                    if (krb5int_open_plugin (filepath, &handle, ep) == 0) {
+                        err = krb5int_plugin_file_handle_array_add (&h, &count, handle);
+                        if (!err) { handle = NULL; }  /* h takes ownership */
+                    }
+                }
+                
+                if (filepath  != NULL) { free (filepath); }
+                if (handle    != NULL) { krb5int_close_plugin (handle); }
+            }
+            
+            if (dir != NULL) { closedir (dir); }
+#else
+	    /* Until a Windows implementation of this code is implemented */
+	    err = ENOENT;
+#endif /* _WIN32 */
+        }
+    }
+        
+    if (err == ENOENT) {
+        err = 0;  /* ran out of plugins -- do nothing */
+    }
+     
+    if (!err) {
+        dirhandle->files = h;
+        h = NULL;  /* dirhandle->files takes ownership */
+    }
+    
+    if (filenames != NULL) { krb5int_free_plugin_filenames (filenames); }
+    if (h         != NULL) { krb5int_plugin_file_handle_array_free (h); }
+    
+    return err;
+}
+
+void KRB5_CALLCONV
+krb5int_close_plugin_dirs (struct plugin_dir_handle *dirhandle)
+{
+    if (dirhandle->files != NULL) {
+        int i;
+        for (i = 0; dirhandle->files[i] != NULL; i++) {
+            krb5int_close_plugin (dirhandle->files[i]);
+        }
+        free (dirhandle->files);
+        dirhandle->files = NULL;
+    }
+}
+
+void KRB5_CALLCONV
+krb5int_free_plugin_dir_data (void **ptrs)
+{
+    /* Nothing special to be done per pointer.  */
+    free(ptrs);
+}
+
+long KRB5_CALLCONV
+krb5int_get_plugin_dir_data (struct plugin_dir_handle *dirhandle,
+			     const char *symname,
+			     void ***ptrs,
+			     struct errinfo *ep)
+{
+    long err = 0;
+    void **p = NULL;
+    int count = 0;
+
+    /* XXX Do we need to add a leading "_" to the symbol name on any
+       modern platforms?  */
+    
+    Tprintf("get_plugin_data_sym(%s)\n", symname);
+
+    if (!err) {
+        p = calloc (1, sizeof (*p)); /* calloc initializes to NULL */
+        if (p == NULL) { err = errno; }
+    }
+    
+    if (!err && (dirhandle != NULL) && (dirhandle->files != NULL)) {
+        int i = 0;
+
+        for (i = 0; !err && (dirhandle->files[i] != NULL); i++) {
+            void *sym = NULL;
+
+            if (krb5int_get_plugin_data (dirhandle->files[i], symname, &sym, ep) == 0) {
+                void **newp = NULL;
+
+                count++;
+                newp = realloc (p, ((count + 1) * sizeof (*p))); /* +1 for NULL */
+                if (newp == NULL) { 
+                    err = errno; 
+                } else {
+                    p = newp;
+                    p[count - 1] = sym;
+                    p[count] = NULL;
+                }
+            }
+        }
+    }
+    
+    if (!err) {
+        *ptrs = p;
+        p = NULL; /* ptrs takes ownership */
+    }
+    
+    if (p != NULL) { free (p); }
+    
+    return err;
+}
+
+void KRB5_CALLCONV
+krb5int_free_plugin_dir_func (void (**ptrs)(void))
+{
+    /* Nothing special to be done per pointer.  */
+    free(ptrs);
+}
+
+long KRB5_CALLCONV
+krb5int_get_plugin_dir_func (struct plugin_dir_handle *dirhandle,
+			     const char *symname,
+			     void (***ptrs)(void),
+			     struct errinfo *ep)
+{
+    long err = 0;
+    void (**p)() = NULL;
+    int count = 0;
+    
+    /* XXX Do we need to add a leading "_" to the symbol name on any
+        modern platforms?  */
+    
+    Tprintf("get_plugin_data_sym(%s)\n", symname);
+    
+    if (!err) {
+        p = calloc (1, sizeof (*p)); /* calloc initializes to NULL */
+        if (p == NULL) { err = errno; }
+    }
+    
+    if (!err && (dirhandle != NULL) && (dirhandle->files != NULL)) {
+        int i = 0;
+        
+        for (i = 0; !err && (dirhandle->files[i] != NULL); i++) {
+            void (*sym)() = NULL;
+            
+            if (krb5int_get_plugin_func (dirhandle->files[i], symname, &sym, ep) == 0) {
+                void (**newp)() = NULL;
+
+                count++;
+                newp = realloc (p, ((count + 1) * sizeof (*p))); /* +1 for NULL */
+                if (newp == NULL) { 
+                    err = errno; 
+                } else {
+                    p = newp;
+                    p[count - 1] = sym;
+                    p[count] = NULL;
+                }
+            }
+        }
+    }
+    
+    if (!err) {
+        *ptrs = p;
+        p = NULL; /* ptrs takes ownership */
+    }
+    
+    if (p != NULL) { free (p); }
+    
+    return err;
+}
diff --git a/krb5-1-6/src/util/support/supp-int.h b/krb5-1-6/src/util/support/supp-int.h
new file mode 100644
index 000000000..ffc0e6455
--- /dev/null
+++ b/krb5-1-6/src/util/support/supp-int.h
@@ -0,0 +1,36 @@
+/*
+ * util/support/supp-int.h
+ *
+ * Copyright (C) 2006 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ *  Internal prototypes for the krb5support library
+ */
+#ifndef KRB5_SUPP_INT_H__
+#define KRB5_SUPP_INT_H__
+
+extern int krb5int_call_thread_support_init (void);
+
+extern int krb5int_err_init (void);
+
+#endif /* KRB5_SUPP_INT_H__ */
diff --git a/krb5-1-6/src/util/support/threads.c b/krb5-1-6/src/util/support/threads.c
new file mode 100644
index 000000000..968a99554
--- /dev/null
+++ b/krb5-1-6/src/util/support/threads.c
@@ -0,0 +1,652 @@
+/*
+ * util/support/threads.c
+ *
+ * Copyright 2004,2005,2006 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Preliminary thread support.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "k5-thread.h"
+#include "k5-platform.h"
+#include "supp-int.h"
+
+MAKE_INIT_FUNCTION(krb5int_thread_support_init);
+MAKE_FINI_FUNCTION(krb5int_thread_support_fini);
+
+#ifndef ENABLE_THREADS /* no thread support */
+
+static void (*destructors[K5_KEY_MAX])(void *);
+struct tsd_block { void *values[K5_KEY_MAX]; };
+static struct tsd_block tsd_no_threads;
+static unsigned char destructors_set[K5_KEY_MAX];
+
+int krb5int_pthread_loaded (void)
+{
+    return 0;
+}
+
+#elif defined(_WIN32)
+
+static DWORD tls_idx;
+static CRITICAL_SECTION key_lock;
+struct tsd_block {
+  void *values[K5_KEY_MAX];
+};
+static void (*destructors[K5_KEY_MAX])(void *);
+static unsigned char destructors_set[K5_KEY_MAX];
+
+void krb5int_thread_detach_hook (void)
+{
+    /* XXX Memory leak here!
+       Need to destroy all TLS objects we know about for this thread.  */
+    struct tsd_block *t;
+    int i, err;
+
+    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
+    if (err)
+	return;
+
+    t = TlsGetValue(tls_idx);
+    if (t == NULL)
+	return;
+    for (i = 0; i < K5_KEY_MAX; i++) {
+	if (destructors_set[i] && destructors[i] && t->values[i]) {
+	    void *v = t->values[i];
+	    t->values[i] = 0;
+	    (*destructors[i])(v);
+	}
+    }
+}
+
+/* Stub function not used on Windows. */ 
+int krb5int_pthread_loaded (void)
+{
+    return 0;
+}
+#else /* POSIX threads */
+
+/* Must support register/delete/register sequence, e.g., if krb5 is
+   loaded so this support code stays in the process, and gssapi is
+   loaded, unloaded, and loaded again.  */
+
+static k5_mutex_t key_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+static void (*destructors[K5_KEY_MAX])(void *);
+static unsigned char destructors_set[K5_KEY_MAX];
+
+/* This is not safe yet!
+
+   Thread termination concurrent with key deletion can cause two
+   threads to interfere.  It's a bit tricky, since one of the threads
+   will want to remove this structure from the list being walked by
+   the other.
+
+   Other cases, like looking up data while the library owning the key
+   is in the process of being unloaded, we don't worry about.  */
+
+struct tsd_block {
+    struct tsd_block *next;
+    void *values[K5_KEY_MAX];
+};
+
+#ifdef HAVE_PRAGMA_WEAK_REF
+# pragma weak pthread_getspecific
+# pragma weak pthread_setspecific
+# pragma weak pthread_key_create
+# pragma weak pthread_key_delete
+# pragma weak pthread_create
+# pragma weak pthread_join
+static volatile int flag_pthread_loaded = -1;
+static void loaded_test_aux(void)
+{
+    if (flag_pthread_loaded == -1)
+	flag_pthread_loaded = 1;
+    else
+	/* Could we have been called twice?  */
+	flag_pthread_loaded = 0;
+}
+static pthread_once_t loaded_test_once = PTHREAD_ONCE_INIT;
+int krb5int_pthread_loaded (void)
+{
+    int x = flag_pthread_loaded;
+    if (x != -1)
+	return x;
+    if (&pthread_getspecific == 0
+	|| &pthread_setspecific == 0
+	|| &pthread_key_create == 0
+	|| &pthread_key_delete == 0
+	|| &pthread_once == 0
+	|| &pthread_mutex_lock == 0
+	|| &pthread_mutex_unlock == 0
+	|| &pthread_mutex_destroy == 0
+	|| &pthread_mutex_init == 0
+	|| &pthread_self == 0
+	|| &pthread_equal == 0
+	/* Any program that's really multithreaded will have to be
+	   able to create threads.  */
+	|| &pthread_create == 0
+	|| &pthread_join == 0
+	/* Okay, all the interesting functions -- or stubs for them --
+	   seem to be present.  If we call pthread_once, does it
+	   actually seem to cause the indicated function to get called
+	   exactly one time?  */
+	|| pthread_once(&loaded_test_once, loaded_test_aux) != 0
+	|| pthread_once(&loaded_test_once, loaded_test_aux) != 0
+	/* This catches cases where pthread_once does nothing, and
+	   never causes the function to get called.  That's a pretty
+	   clear violation of the POSIX spec, but hey, it happens.  */
+	|| flag_pthread_loaded < 0) {
+	flag_pthread_loaded = 0;
+	return 0;
+    }
+    /* If we wanted to be super-paranoid, we could try testing whether
+       pthread_get/setspecific work, too.  I don't know -- so far --
+       of any system with non-functional stubs for those.  */
+    return flag_pthread_loaded;
+}
+static struct tsd_block tsd_if_single;
+# define GET_NO_PTHREAD_TSD()	(&tsd_if_single)
+#else
+# define GET_NO_PTHREAD_TSD()	(abort(),(struct tsd_block *)0)
+#endif
+
+static pthread_key_t key;
+static void thread_termination(void *);
+
+static void thread_termination (void *tptr)
+{
+    int err = k5_mutex_lock(&key_lock);
+    if (err == 0) {
+        int i, pass, none_found;
+        struct tsd_block *t = tptr;
+        
+        /* Make multiple passes in case, for example, a libkrb5 cleanup
+            function wants to print out an error message, which causes
+            com_err to allocate a thread-specific buffer, after we just
+            freed up the old one.
+            
+            Shouldn't actually happen, if we're careful, but check just in
+            case.  */
+        
+        pass = 0;
+        none_found = 0;
+        while (pass < 4 && !none_found) {
+            none_found = 1;
+            for (i = 0; i < K5_KEY_MAX; i++) {
+                if (destructors_set[i] && destructors[i] && t->values[i]) {
+                    void *v = t->values[i];
+                    t->values[i] = 0;
+                    (*destructors[i])(v);
+                    none_found = 0;
+                }
+            }
+        }
+        free (t);
+        err = k5_mutex_unlock(&key_lock);
+   }
+    
+    /* remove thread from global linked list */
+}
+
+#endif /* no threads vs Win32 vs POSIX */
+
+void *k5_getspecific (k5_key_t keynum)
+{
+    struct tsd_block *t;
+    int err;
+
+    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
+    if (err)
+	return NULL;
+
+    assert(keynum >= 0 && keynum < K5_KEY_MAX);
+    assert(destructors_set[keynum] == 1);
+
+#ifndef ENABLE_THREADS
+
+    t = &tsd_no_threads;
+
+#elif defined(_WIN32)
+
+    t = TlsGetValue(tls_idx);
+
+#else /* POSIX */
+
+    if (K5_PTHREADS_LOADED)
+	t = pthread_getspecific(key);
+    else
+	t = GET_NO_PTHREAD_TSD();
+
+#endif
+
+    if (t == NULL)
+	return NULL;
+    return t->values[keynum];
+}
+
+int k5_setspecific (k5_key_t keynum, void *value)
+{
+    struct tsd_block *t;
+    int err;
+
+    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
+    if (err)
+	return err;
+
+    assert(keynum >= 0 && keynum < K5_KEY_MAX);
+    assert(destructors_set[keynum] == 1);
+
+#ifndef ENABLE_THREADS
+
+    t = &tsd_no_threads;
+
+#elif defined(_WIN32)
+
+    t = TlsGetValue(tls_idx);
+    if (t == NULL) {
+	int i;
+	t = malloc(sizeof(*t));
+	if (t == NULL)
+	    return errno;
+	for (i = 0; i < K5_KEY_MAX; i++)
+	    t->values[i] = 0;
+	/* add to global linked list */
+	/*	t->next = 0; */
+	err = TlsSetValue(tls_idx, t);
+	if (!err) {
+	    free(t);
+	    return GetLastError();
+	}
+    }
+
+#else /* POSIX */
+
+    if (K5_PTHREADS_LOADED) {
+	t = pthread_getspecific(key);
+	if (t == NULL) {
+	    int i;
+	    t = malloc(sizeof(*t));
+	    if (t == NULL)
+		return errno;
+	    for (i = 0; i < K5_KEY_MAX; i++)
+		t->values[i] = 0;
+	    /* add to global linked list */
+	    t->next = 0;
+	    err = pthread_setspecific(key, t);
+	    if (err) {
+		free(t);
+		return err;
+	    }
+	}
+    } else {
+	t = GET_NO_PTHREAD_TSD();
+    }
+
+#endif
+
+    t->values[keynum] = value;
+    return 0;
+}
+
+int k5_key_register (k5_key_t keynum, void (*destructor)(void *))
+{
+    int err;
+
+    err = CALL_INIT_FUNCTION(krb5int_thread_support_init);
+    if (err)
+	return err;
+
+    assert(keynum >= 0 && keynum < K5_KEY_MAX);
+
+#ifndef ENABLE_THREADS
+
+    assert(destructors_set[keynum] == 0);
+    destructors[keynum] = destructor;
+    destructors_set[keynum] = 1;
+    err = 0;
+
+#elif defined(_WIN32)
+
+    /* XXX: This can raise EXCEPTION_POSSIBLE_DEADLOCK.  */
+    EnterCriticalSection(&key_lock);
+    assert(destructors_set[keynum] == 0);
+    destructors_set[keynum] = 1;
+    destructors[keynum] = destructor;
+    LeaveCriticalSection(&key_lock);
+    err = 0;
+
+#else /* POSIX */
+
+    err = k5_mutex_lock(&key_lock);
+    if (err == 0) {
+	assert(destructors_set[keynum] == 0);
+	destructors_set[keynum] = 1;
+	destructors[keynum] = destructor;
+	err = k5_mutex_unlock(&key_lock);
+    }
+
+#endif
+    return 0;
+}
+
+int k5_key_delete (k5_key_t keynum)
+{
+    assert(keynum >= 0 && keynum < K5_KEY_MAX);
+
+#ifndef ENABLE_THREADS
+
+    assert(destructors_set[keynum] == 1);
+    if (destructors[keynum] && tsd_no_threads.values[keynum])
+	(*destructors[keynum])(tsd_no_threads.values[keynum]);
+    destructors[keynum] = 0;
+    tsd_no_threads.values[keynum] = 0;
+    destructors_set[keynum] = 0;
+
+#elif defined(_WIN32)
+
+    /* XXX: This can raise EXCEPTION_POSSIBLE_DEADLOCK.  */
+    EnterCriticalSection(&key_lock);
+    /* XXX Memory leak here!
+       Need to destroy the associated data for all threads.
+       But watch for race conditions in case threads are going away too.  */
+    assert(destructors_set[keynum] == 1);
+    destructors_set[keynum] = 0;
+    destructors[keynum] = 0;
+    LeaveCriticalSection(&key_lock);
+
+#else /* POSIX */
+
+    {
+	int err;
+
+	/* XXX RESOURCE LEAK:
+
+	   Need to destroy the allocated objects first!  */
+
+	err = k5_mutex_lock(&key_lock);
+	if (err == 0) {
+	    assert(destructors_set[keynum] == 1);
+	    destructors_set[keynum] = 0;
+	    destructors[keynum] = NULL;
+	    k5_mutex_unlock(&key_lock);
+	}
+    }
+
+#endif
+
+    return 0;
+}
+
+int krb5int_call_thread_support_init (void)
+{
+    return CALL_INIT_FUNCTION(krb5int_thread_support_init);
+}
+
+#include "cache-addrinfo.h"
+
+#ifdef DEBUG_THREADS_STATS
+#include <stdio.h>
+static FILE *stats_logfile;
+#endif
+
+int krb5int_thread_support_init (void)
+{
+    int err;
+
+#ifdef SHOW_INITFINI_FUNCS
+    printf("krb5int_thread_support_init\n");
+#endif
+
+#ifdef DEBUG_THREADS_STATS
+    /*    stats_logfile = stderr; */
+    stats_logfile = fopen("/dev/tty", "w+");
+    if (stats_logfile == NULL)
+      stats_logfile = stderr;
+#endif
+
+#ifndef ENABLE_THREADS
+
+    /* Nothing to do for TLS initialization.  */
+
+#elif defined(_WIN32)
+
+    tls_idx = TlsAlloc();
+    /* XXX This can raise an exception if memory is low!  */
+    InitializeCriticalSection(&key_lock);
+
+#else /* POSIX */
+
+    err = k5_mutex_finish_init(&key_lock);
+    if (err)
+	return err;
+    if (K5_PTHREADS_LOADED) {
+	err = pthread_key_create(&key, thread_termination);
+	if (err)
+	    return err;
+    }
+
+#endif
+
+    err = krb5int_init_fac();
+    if (err)
+	return err;
+
+    err = krb5int_err_init();
+    if (err)
+	return err;
+
+    return 0;
+}
+
+void krb5int_thread_support_fini (void)
+{
+    if (! INITIALIZER_RAN (krb5int_thread_support_init))
+	return;
+
+#ifdef SHOW_INITFINI_FUNCS
+    printf("krb5int_thread_support_fini\n");
+#endif
+
+#ifndef ENABLE_THREADS
+
+    /* Do nothing.  */
+
+#elif defined(_WIN32)
+
+    /* ... free stuff ... */
+    TlsFree(tls_idx);
+    DeleteCriticalSection(&key_lock);
+
+#else /* POSIX */
+
+    if (! INITIALIZER_RAN(krb5int_thread_support_init))
+	return;
+    if (K5_PTHREADS_LOADED)
+	pthread_key_delete(key);
+    /* ... delete stuff ... */
+    k5_mutex_destroy(&key_lock);
+
+#endif
+
+#ifdef DEBUG_THREADS_STATS
+    fflush(stats_logfile);
+    /* XXX Should close if not stderr, in case unloading library but
+       not exiting.  */
+#endif
+
+    krb5int_fini_fac();
+}
+
+#ifdef DEBUG_THREADS_STATS
+void KRB5_CALLCONV
+k5_mutex_lock_update_stats(k5_debug_mutex_stats *m,
+			   k5_mutex_stats_tmp startwait)
+{
+  k5_debug_time_t now;
+  k5_debug_timediff_t tdiff, tdiff2;
+
+  now = get_current_time();
+  (void) krb5int_call_thread_support_init();
+  m->count++;
+  m->time_acquired = now;
+  tdiff = timediff(now, startwait);
+  tdiff2 = tdiff * tdiff;
+  if (m->count == 1 || m->lockwait.valmin > tdiff)
+    m->lockwait.valmin = tdiff;
+  if (m->count == 1 || m->lockwait.valmax < tdiff)
+    m->lockwait.valmax = tdiff;
+  m->lockwait.valsum += tdiff;
+  m->lockwait.valsqsum += tdiff2;
+}
+
+void KRB5_CALLCONV
+krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m)
+{
+  k5_debug_time_t now = get_current_time();
+  k5_debug_timediff_t tdiff, tdiff2;
+  tdiff = timediff(now, m->time_acquired);
+  tdiff2 = tdiff * tdiff;
+  if (m->count == 1 || m->lockheld.valmin > tdiff)
+    m->lockheld.valmin = tdiff;
+  if (m->count == 1 || m->lockheld.valmax < tdiff)
+    m->lockheld.valmax = tdiff;
+  m->lockheld.valsum += tdiff;
+  m->lockheld.valsqsum += tdiff2;
+}
+
+#include <math.h>
+static inline double
+get_stddev(struct k5_timediff_stats sp, int count)
+{
+  long double mu, mu_squared, rho_squared;
+  mu = (long double) sp.valsum / count;
+  mu_squared = mu * mu;
+  /* SUM((x_i - mu)^2)
+     = SUM(x_i^2 - 2*mu*x_i + mu^2)
+     = SUM(x_i^2) - 2*mu*SUM(x_i) + N*mu^2
+
+     Standard deviation rho^2 = SUM(...) / N.  */
+  rho_squared = (sp.valsqsum - 2 * mu * sp.valsum + count * mu_squared) / count;
+  return sqrt(rho_squared);
+}
+
+void KRB5_CALLCONV
+krb5int_mutex_report_stats(k5_mutex_t *m)
+{
+  char *p;
+
+  /* Tweak this to only record data on "interesting" locks.  */
+  if (m->stats.count < 10)
+    return;
+  if (m->stats.lockwait.valsum < 10 * m->stats.count)
+    return;
+
+  p = strrchr(m->loc_created.filename, '/');
+  if (p == NULL)
+    p = m->loc_created.filename;
+  else
+    p++;
+  fprintf(stats_logfile, "mutex @%p: created at line %d of %s\n",
+	  (void *) m, m->loc_created.lineno, p);
+  if (m->stats.count == 0)
+    fprintf(stats_logfile, "\tnever locked\n");
+  else {
+    double sd_wait, sd_hold;
+    sd_wait = get_stddev(m->stats.lockwait, m->stats.count);
+    sd_hold = get_stddev(m->stats.lockheld, m->stats.count);
+    fprintf(stats_logfile,
+	    "\tlocked %d time%s; wait %lu/%f/%lu/%fus, hold %lu/%f/%lu/%fus\n",
+	    m->stats.count, m->stats.count == 1 ? "" : "s",
+	    (unsigned long) m->stats.lockwait.valmin,
+	    (double) m->stats.lockwait.valsum / m->stats.count,
+	    (unsigned long) m->stats.lockwait.valmax,
+	    sd_wait,
+	    (unsigned long) m->stats.lockheld.valmin,
+	    (double) m->stats.lockheld.valsum / m->stats.count,
+	    (unsigned long) m->stats.lockheld.valmax,
+	    sd_hold);
+  }
+}
+#else
+/* On Windows, everything defined in the export list must be defined.
+   The UNIX systems where we're using the export list don't seem to
+   care.  */
+#undef krb5int_mutex_lock_update_stats
+void KRB5_CALLCONV
+krb5int_mutex_lock_update_stats(k5_debug_mutex_stats *m,
+				k5_mutex_stats_tmp startwait)
+{
+}
+#undef krb5int_mutex_unlock_update_stats
+void KRB5_CALLCONV
+krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m)
+{
+}
+#undef krb5int_mutex_report_stats
+void KRB5_CALLCONV
+krb5int_mutex_report_stats(k5_mutex_t *m)
+{
+}
+#endif
+
+/* Mutex allocation functions, for use in plugins that may not know
+   what options a given set of libraries was compiled with.  */
+int KRB5_CALLCONV
+krb5int_mutex_alloc (k5_mutex_t **m)
+{
+    k5_mutex_t *ptr;
+    int err;
+
+    ptr = malloc (sizeof (k5_mutex_t));
+    if (ptr == NULL)
+	return errno;
+    err = k5_mutex_init (ptr);
+    if (err) {
+	free (ptr);
+	return err;
+    }
+    *m = ptr;
+    return 0;
+}
+
+void KRB5_CALLCONV
+krb5int_mutex_free (k5_mutex_t *m)
+{
+    (void) k5_mutex_destroy (m);
+    free (m);
+}
+
+/* Callable versions of the various macros.  */
+int KRB5_CALLCONV
+krb5int_mutex_lock (k5_mutex_t *m)
+{
+    return k5_mutex_lock (m);
+}
+int KRB5_CALLCONV
+krb5int_mutex_unlock (k5_mutex_t *m)
+{
+    return k5_mutex_unlock (m);
+}
diff --git a/krb5-1-6/src/util/valgrind-suppressions b/krb5-1-6/src/util/valgrind-suppressions
new file mode 100644
index 000000000..b189249da
--- /dev/null
+++ b/krb5-1-6/src/util/valgrind-suppressions
@@ -0,0 +1,16 @@
+{
+   glibc.getifaddrs.sendto.uninit
+   Memcheck:Param
+   socketcall.sendto(msg)
+   fun:sendto
+   fun:getifaddrs
+   fun:krb5int_foreach_localaddr
+}
+{
+   glibc.getnameinfo.gifname.uninit
+   Memcheck:Param
+   ioctl(SIOCGIFNAME)
+   fun:ioctl
+   fun:getnameinfo
+   fun:krb5int_getnameinfo
+}
diff --git a/krb5-1-6/src/util/windows/Makefile.in b/krb5-1-6/src/util/windows/Makefile.in
new file mode 100644
index 000000000..f857c4667
--- /dev/null
+++ b/krb5-1-6/src/util/windows/Makefile.in
@@ -0,0 +1,16 @@
+BUILDTOP = ..\..
+
+all-windows:: $(OUTPRE)libecho.exe $(OUTPRE)getopt.lib
+
+$(OUTPRE)libecho.exe: $(OUTPRE)libecho.obj
+	link -out:$@ $** $(SCLIB)
+	$(_VC_MANIFEST_EMBED_EXE)
+	
+
+$(OUTPRE)getopt.lib: $(OUTPRE)getopt.obj $(OUTPRE)getopt_long.obj
+	lib -out:$@ $**
+
+install-windows::
+
+clean-windows::
+	$(RM) $(OUTPRE)*.res $(OUTPRE)*.map $(OUTPRE)*.obj $(OUTPRE)*.exe $(OUTPRE)*.manifest
diff --git a/krb5-1-6/src/util/windows/getopt.c b/krb5-1-6/src/util/windows/getopt.c
new file mode 100644
index 000000000..2b21c7be5
--- /dev/null
+++ b/krb5-1-6/src/util/windows/getopt.c
@@ -0,0 +1,152 @@
+/*	$NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $	*/
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+static char sccsid[] = "@(#)getopt.c	8.3 (Berkeley) 4/27/95";
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+#ifdef __weak_alias
+__weak_alias(getopt,_getopt);
+#endif
+
+
+int	opterr = 1,		/* if error message should be printed */
+	optind = 1,		/* index into parent argv vector */
+	optopt,			/* character checked for validity */
+	optreset;		/* reset getopt */
+char	*optarg;		/* argument associated with option */
+
+static char * _progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+_progname(nargv0)
+	char * nargv0;
+{
+	char * tmp;
+
+	_DIAGASSERT(nargv0 != NULL);
+
+	tmp = strrchr(nargv0, '/');
+	if (tmp)
+		tmp++;
+	else
+		tmp = nargv0;
+	return(tmp);
+}
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+	int nargc;
+	char * const nargv[];
+	const char *ostr;
+{
+	static char *__progname = 0;
+	static char *place = EMSG;		/* option letter processing */
+	char *oli;				/* option letter list index */
+        __progname = __progname?__progname:_progname(*nargv);
+
+	_DIAGASSERT(nargv != NULL);
+	_DIAGASSERT(ostr != NULL);
+
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+			place = EMSG;
+			return (-1);
+		}
+		if (place[1] && *++place == '-'	/* found "--" */
+		    && place[1] == '\0') {
+			++optind;
+			place = EMSG;
+			return (-1);
+		}
+	}					/* option letter okay? */
+	if ((optopt = (int)*place++) == (int)':' ||
+	    !(oli = strchr(ostr, optopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means -1.
+		 */
+		if (optopt == (int)'-')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "%s: illegal option -- %c\n", __progname, optopt);
+		return (BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		optarg = NULL;
+		if (!*place)
+			++optind;
+	}
+	else {					/* need an argument */
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (nargc <= ++optind) {	/* no arg */
+			place = EMSG;
+			if (*ostr == ':')
+				return (BADARG);
+			if (opterr)
+				(void)fprintf(stderr,
+				    "%s: option requires an argument -- %c\n",
+				    __progname, optopt);
+			return (BADCH);
+		}
+	 	else				/* white space */
+			optarg = nargv[optind];
+		place = EMSG;
+		++optind;
+	}
+	return (optopt);			/* dump back option letter */
+}
diff --git a/krb5-1-6/src/util/windows/getopt.h b/krb5-1-6/src/util/windows/getopt.h
new file mode 100644
index 000000000..7137f0379
--- /dev/null
+++ b/krb5-1-6/src/util/windows/getopt.h
@@ -0,0 +1,33 @@
+#ifndef __GETOPT_H__
+#define __GETOPT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int opterr;		/* if error message should be printed */
+extern int optind;		/* index into parent argv vector */
+extern int optopt;		/* character checked for validity */
+extern int optreset;		/* reset getopt */
+extern char *optarg;		/* argument associated with option */
+
+struct option
+{
+  const char *name;
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+#define no_argument       0
+#define required_argument 1
+#define optional_argument 2
+
+int getopt(int, char**, char*);
+int getopt_long(int, char**, char*, struct option*, int*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GETOPT_H__ */
diff --git a/krb5-1-6/src/util/windows/getopt_long.c b/krb5-1-6/src/util/windows/getopt_long.c
new file mode 100644
index 000000000..bb819628e
--- /dev/null
+++ b/krb5-1-6/src/util/windows/getopt_long.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1987, 1993, 1994, 1996
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+
+extern int	  opterr;	/* if error message should be printed */
+extern int	  optind;	/* index into parent argv vector */
+extern int	  optopt;	/* character checked for validity */
+extern int	  optreset;	/* reset getopt */
+extern char *optarg;	/* argument associated with option */
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+static char * __progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+__progname(nargv0)
+	char * nargv0;
+{
+	char * tmp;
+
+	_DIAGASSERT(nargv0 != NULL);
+
+	tmp = strrchr(nargv0, '/');
+	if (tmp)
+		tmp++;
+	else
+		tmp = nargv0;
+	return(tmp);
+}
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_internal(nargc, nargv, ostr)
+	int nargc;
+	char * const *nargv;
+	const char *ostr;
+{
+	static char *place = EMSG;		/* option letter processing */
+	char *oli;				/* option letter list index */
+
+	_DIAGASSERT(nargv != NULL);
+	_DIAGASSERT(ostr != NULL);
+
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+			place = EMSG;
+			return (-1);
+		}
+		if (place[1] && *++place == '-') {	/* found "--" */
+			/* ++optind; */
+			place = EMSG;
+			return (-2);
+		}
+	}					/* option letter okay? */
+	if ((optopt = (int)*place++) == (int)':' ||
+	    !(oli = strchr(ostr, optopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means -1.
+		 */
+		if (optopt == (int)'-')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
+		return (BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		optarg = NULL;
+		if (!*place)
+			++optind;
+	} else {				/* need an argument */
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (nargc <= ++optind) {	/* no arg */
+			place = EMSG;
+			if ((opterr) && (*ostr != ':'))
+				(void)fprintf(stderr,
+				    "%s: option requires an argument -- %c\n",
+				    __progname(nargv[0]), optopt);
+			return (BADARG);
+		} else				/* white space */
+			optarg = nargv[optind];
+		place = EMSG;
+		++optind;
+	}
+	return (optopt);			/* dump back option letter */
+}
+
+#if 0
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt2(nargc, nargv, ostr)
+	int nargc;
+	char * const *nargv;
+	const char *ostr;
+{
+	int retval;
+
+	if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
+		retval = -1;
+		++optind; 
+	}
+	return(retval);
+}
+#endif
+
+/*
+ * getopt_long --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long(nargc, nargv, options, long_options, index)
+	int nargc;
+	char ** nargv;
+	char * options;
+	struct option * long_options;
+	int * index;
+{
+	int retval;
+
+	_DIAGASSERT(nargv != NULL);
+	_DIAGASSERT(options != NULL);
+	_DIAGASSERT(long_options != NULL);
+	/* index may be NULL */
+
+	if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+		char *current_argv = nargv[optind++] + 2, *has_equal;
+		int i, current_argv_len, match = -1;
+
+		if (*current_argv == '\0') {
+			return(-1);
+		}
+		if ((has_equal = strchr(current_argv, '=')) != NULL) {
+			current_argv_len = has_equal - current_argv;
+			has_equal++;
+		} else
+			current_argv_len = strlen(current_argv);
+
+		for (i = 0; long_options[i].name; i++) { 
+			if (strncmp(current_argv, long_options[i].name, current_argv_len))
+				continue;
+
+			if (strlen(long_options[i].name) == (unsigned)current_argv_len) { 
+				match = i;
+				break;
+			}
+			if (match == -1)
+				match = i;
+		}
+		if (match != -1) {
+			if (long_options[match].has_arg == required_argument ||
+			    long_options[match].has_arg == optional_argument) {
+				if (has_equal)
+					optarg = has_equal;
+				else
+					optarg = nargv[optind++];
+			}
+			if ((long_options[match].has_arg == required_argument)
+			    && (optarg == NULL)) {
+				/*
+				 * Missing argument, leading :
+				 * indicates no error should be generated
+				 */
+				if ((opterr) && (*options != ':'))
+					(void)fprintf(stderr,
+				      "%s: option requires an argument -- %s\n",
+				      __progname(nargv[0]), current_argv);
+				return (BADARG);
+			}
+		} else { /* No matching argument */
+			if ((opterr) && (*options != ':'))
+				(void)fprintf(stderr,
+				    "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
+			return (BADCH);
+		}
+		if (long_options[match].flag) {
+			*long_options[match].flag = long_options[match].val;
+			retval = 0;
+		} else 
+			retval = long_options[match].val;
+		if (index)
+			*index = match;
+	}
+	return(retval);
+}
diff --git a/krb5-1-6/src/util/windows/libecho.c b/krb5-1-6/src/util/windows/libecho.c
new file mode 100644
index 000000000..9fcbe2e98
--- /dev/null
+++ b/krb5-1-6/src/util/windows/libecho.c
@@ -0,0 +1,76 @@
+/*
+ * libecho.c
+ *
+ * For each argument on the command line, echo it.  Should expand
+ * DOS wildcards correctly.
+ *
+ * Syntax: libecho [-p prefix] list...
+ */
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+
+void echo_files(char *, char *);
+
+int
+main(int argc, char *argv[])
+{
+  int i;
+  char *prefix;
+
+  prefix = "";
+
+  if (argc < 2) {
+    fprintf(stderr, "Usage:  libecho [-p prefix] list...\n");
+    return 1;
+  }
+
+  for (i = 1 ; i < argc ; i++)
+    if (!stricmp(argv[i], "-p"))
+      prefix = argv[++i];
+    else
+      echo_files(prefix, argv[i]);
+
+  return 0;
+}
+
+void
+echo_files(char *prefix, char *f)
+{
+  long ff;
+  struct _finddata_t fdt;
+  char *slash;
+  char filepath[256];
+
+  /*
+   * We're unix based quite a bit here.  Look for normal slashes and
+   * make them reverse slashes.
+   */
+  while((slash = strrchr(f, '/')) != NULL)
+    *slash = '\\';
+
+  strcpy(filepath, f);
+
+  slash = strrchr(filepath, '\\');
+
+  if (slash) {
+    slash++;
+    *slash = 0;
+  } else {
+    filepath[0] = '\0';
+  }
+
+  ff = _findfirst(f, &fdt);
+
+  if (ff < 0)
+    return;
+
+  printf("%s%s%s\n", prefix, filepath, fdt.name);
+
+  for (;;) {
+    if (_findnext(ff, &fdt) < 0)
+      break;
+    printf("%s%s%s\n", prefix, filepath, fdt.name);
+  }
+  _findclose(ff);
+}
diff --git a/krb5-1-6/src/wconfig.c b/krb5-1-6/src/wconfig.c
new file mode 100644
index 000000000..087a54b5c
--- /dev/null
+++ b/krb5-1-6/src/wconfig.c
@@ -0,0 +1,219 @@
+/*
+ * wconfig.c
+ *
+ * Copyright 1995,1996,1997,1998 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * Program to take the place of the configure shell script under DOS.
+ * The makefile.in files are constructed in such a way that all this
+ * program needs to do is uncomment lines beginning ##DOS by removing the
+ * first 5 characters of the line.  This will allow lines like:
+ * ##DOS!include win-pre.in to become: !include win-pre.in
+ *
+ * We also turn any line beginning with '@' into a blank line.
+ *
+ * If a config directory is specified, then the output will be start with
+ * config\pre.in, then the filtered stdin text, and will end with
+ * config\post.in.
+ *
+ * Syntax: wconfig [options] [config_directory] <input_file >output_file
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+static int copy_file (char *path, char *fname);
+void add_ignore_list(char *str);
+
+int mit_specific = 0;
+
+char *win16_flag = "WIN16##";
+char *win32_flag = "WIN32##";
+
+
+int main(int argc, char *argv[])
+{
+	char *ignore_str = "--ignore=";
+	int ignore_len;
+	char *cp, tmp[80];
+	char *win_flag;
+	char wflags[1024];
+
+#ifdef _WIN32
+	win_flag = win32_flag;
+#else
+	win_flag = "UNIX##";
+#endif
+
+	wflags[0] = 0;
+
+	ignore_len = strlen(ignore_str);
+	argc--; argv++;
+	while (*argv && *argv[0] == '-') {
+		wflags[sizeof(wflags) - 1] = '\0';
+		if (strlen (wflags) + 1 + strlen (*argv) > sizeof (wflags) - 1) {
+			fprintf (stderr,
+				 "wconfig: argument list too long (internal limit %d)",
+				 sizeof (wflags));
+			exit (1);
+		}
+		if (wflags[0])
+			strcat(wflags, " ");
+		strcat(wflags, *argv);
+
+		if (!strcmp(*argv, "--mit")) {
+			mit_specific = 1;
+			argc--; argv++;
+			continue;
+		}
+		if (!strcmp(*argv, "--win16")) {
+			win_flag = win16_flag;
+			argc--; argv++;
+			continue;
+		}
+		if (!strcmp(*argv, "--win32")) {
+			win_flag = win32_flag;
+			argc--; argv++;
+			continue;
+		}
+		if (!strncmp(*argv, "--enable-", 9)) {
+			sprintf(tmp, "%s##", (*argv)+ignore_len);
+			for (cp = tmp; *cp; cp++) {
+				if (islower(*cp))
+					*cp = toupper(*cp);
+			}
+			cp = malloc(strlen(tmp)+1);
+			if (!cp) {
+				fprintf(stderr,
+					"wconfig: malloc failed!\n");
+				exit(1);
+			}
+			strcpy(cp, tmp);
+			add_ignore_list(cp);
+			argc--; argv++;
+			continue;
+		}
+		if (!strncmp(*argv, ignore_str, ignore_len)) {
+			add_ignore_list((*argv)+ignore_len);
+			argc--; argv++;
+			continue;
+		}
+		fprintf(stderr, "Invalid option: %s\n", *argv);
+		exit(1);
+	}
+
+	if (win_flag)
+		add_ignore_list(win_flag);
+
+	if (mit_specific)
+		add_ignore_list("MIT##");
+		
+	if (wflags[0] && (argc > 0))
+		printf("WCONFIG_FLAGS=%s\n", wflags);
+
+	if (argc > 0)
+		copy_file (*argv, "win-pre.in");
+
+	copy_file("", "-");
+    
+	if (argc > 0)
+		copy_file (*argv, "win-post.in");
+
+	return 0;
+}
+
+char *ignore_list[64] = {
+	"DOS##",
+	"DOS",
+	};
+
+/*
+ * Add a new item to the ignore list
+ */
+void add_ignore_list(char *str)
+{
+	char **cpp;
+
+	for (cpp = ignore_list; *cpp; cpp++)
+		;
+	*cpp = str;
+}
+
+		
+/*
+ * 
+ * Copy_file
+ * 
+ * Copies file 'path\fname' to stdout.
+ * 
+ */
+static int
+copy_file (char *path, char *fname)
+{
+    FILE *fin;
+    char buf[1024];
+    char **cpp, *ptr;
+    int len;
+
+    if (strcmp(fname, "-") == 0) {
+	    fin = stdin;
+    } else {
+#ifdef _WIN32
+	    sprintf(buf, "%s\\%s", path, fname);
+#else
+	    sprintf(buf, "%s/%s", path, fname);
+#endif
+	    fin = fopen (buf, "r");                     /* File to read */
+	    if (fin == NULL) {
+		    fprintf(stderr, "wconfig: Can't open file %s\n", buf);
+		    return 1;
+	    }
+    }
+    
+
+    while (fgets (buf, sizeof(buf), fin) != NULL) { /* Copy file over */
+	    if (buf[0] == '@') {
+		    fputs("\n", stdout);
+		    continue;
+	    }
+	    if (buf[0] != '#' || buf[1] != '#') {
+		    fputs(buf, stdout);
+		    continue;
+	    }
+	    ptr = buf;
+	    for (cpp = ignore_list; *cpp; cpp++) {
+		    len = strlen(*cpp);
+		    if (memcmp (*cpp, buf+2, len) == 0) {
+			    ptr += 2+len;
+			    break;
+		    }
+	    }
+	    fputs(ptr, stdout);
+    }
+
+    fclose (fin);
+
+    return 0;
+}
diff --git a/krb5-1-6/src/windows/Makefile.in b/krb5-1-6/src/windows/Makefile.in
new file mode 100644
index 000000000..3ba9da6e4
--- /dev/null
+++ b/krb5-1-6/src/windows/Makefile.in
@@ -0,0 +1,63 @@
+BUILDTOP=..
+NO_OUTPRE=1
+
+#
+# Makefile that recurses into cns subdirectory.
+#
+all-windows::
+	@echo Making in windows\lib
+	cd lib
+	$(MAKE) -$(MFLAGS)
+	@echo Making in windows\cns
+	cd ..\cns
+	$(MAKE) -$(MFLAGS)
+	@echo Making in windows\wintel
+	cd ..\wintel
+	$(MAKE) -$(MFLAGS)
+       @echo Making in windows\gss
+	cd ..\gss
+	$(MAKE) -$(MFLAGS)
+	@echo Making in windows\gina
+	cd ..\gina
+	$(MAKE) -$(MFLAGS)
+	@echo Making in windows\ms2mit
+	cd ..\ms2mit
+	$(MAKE) -$(MFLAGS)
+!if "$(KRB5_KFW_COMPILE)"=="1" 
+        @echo Making in windows\kfwlogon
+        cd ..\kfwlogon
+        $(MAKE) -$(MFLAGS) 
+        @echo Making in windows\identity 
+        cd ..\identity 
+        $(MAKE) -$(MFLAGS) 
+!endif 
+	cd ..
+
+clean-windows::
+	@echo Making clean in windows\lib
+	cd lib
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in windows\cns
+	cd ..\cns
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in windows\wintel
+	cd ..\wintel
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in windows\gss
+	cd ..\gss
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in windows\gina
+	cd ..\gina
+	$(MAKE) -$(MFLAGS) clean
+	@echo Making clean in windows\ms2mit
+	cd ..\ms2mit
+	$(MAKE) -$(MFLAGS) clean
+!if "$(KRB5_KFW_COMPILE)"=="1" 
+        @echo Making clean in windows\kfwlogon
+        cd ..\kfwlogon
+        $(MAKE) -$(MFLAGS) clean 
+        @echo Making clean in windows\identity 
+        cd ..\identity 
+        $(MAKE) -$(MFLAGS) clean 
+!endif 
+	cd ..
diff --git a/krb5-1-6/src/windows/README b/krb5-1-6/src/windows/README
new file mode 100644
index 000000000..0276b4350
--- /dev/null
+++ b/krb5-1-6/src/windows/README
@@ -0,0 +1,305 @@
+	       Building & Running Kerberos 5 on Windows
+	       ----------------------------------------
+
+Kerberos 5 builds on Windows with MSVC++ 6.0, MSVS.NET, and 
+MSVS.NET 2003.  You will need the XP SP2 Platform SDK or 
+later; this SDK is required to define getaddrinfo.  It may or 
+may not build with other compilers or make utilities.
+
+These build instructions assume that you have the standalone source
+distribution of Kerberos 5 rather than the MIT Kerberos for Windows
+distribution (which includes a working Kerberos 4).
+
+There are two methods for building a Windows version of Kerberos 5.
+The traditional method involves starting on a Unix machine and
+creating a distribution that can be built on Windows.  The second
+method works from the sources that come from the Unix distribution if
+you have certain Unix-type utilities (see below).
+
+IMPORTANT NOTE: By default, the sources are built with debug
+information and linked against the debug version of the Microsoft C
+Runtime library, which is not found on most Windows systems unless
+they have development tools.  To build a release version, you need to
+define NODEBUG either in the environment or the nmake command-line.
+
+To configuring the build environment execute first the compiler
+batch file, vcvars32.bat or vsvars32.bat, followed by the SDK
+batch file, setenv.bat.  For example, 
+
+  "c:\program files\microsoft visual studio .net 2003\common7\tools\vsvars32.bat"
+  "c:\program files\microsoft sdk\setenv.bat" /2000 /RETAIL
+
+or 
+
+  "c:\program files\microsoft visual studio\vc98\bin\vcvars32.bat"
+  "c:\program files\microsoft sdk\setenv.bat" /2000 /DEBUG
+  
+DNS Support: To support DNS lookups, you will need to define
+KRB5_DNS_LOOKUP, KRB5_DNS_LOOKUP_KDC, or KRB5_DNS_LOOKUP_REALMS.  When 
+any of the KRB5_DNS_LOOKUP definitions are used, the default build will use
+the WSHelper library which is part of the Kerberos for Windows (Kfw) 
+distribution.  If you are building outside of KfW and wish to build Krb5 
+with DNS support, you must provide a resolver library whose include files 
+match the Unix resolver library.  You will need to define KRB5_NO_WSHELPER,
+define DNS_INC to point to the include directory for the library and DNS_LIB 
+to library itself.  The default is not to support DNS because the build 
+cannot know whether there is a DNS resolver library around for it to use.
+
+
+Traditional Build Method:
+------------------------
+
+On the Unix side
+1) cd xxx/src                          # Go to where the source lives
+2) make -f Makefile.in kerbsrc.zip     # Do some Unix-side configuring
+                                       # ...and create kerbsrc.zip
+3) <transfer kerbsrc.zip to the PC>
+
+
+On the PC side
+1) md \krb5                            # Create dir where we'll put the tree
+2) cd \krb5
+3) unzip kerbsrc.zip
+        - or -
+   pkunzip -d kerbsrc.zip
+4) nmake [NODEBUG=1] [DNS-options]     # Build the sources
+5) nmake install [NODEBUG=1] [options] # Copy headers, libs, executables
+
+
+All-Windows Build Method:
+------------------------
+
+First, make sure you have sed, gawk, cat, and cp.
+
+1) cd xxx/src                          # Go to where the source lives
+2) nmake -f Makefile.in prep-windows   # Create Makefile for Windows
+3) nmake [NODEBUG=1] [DNS-options]     # Build the sources
+4) nmake install [NODEBUG=1] [options] # Copy headers, libs, executables
+
+
+Notes on the install Target:
+---------------------------
+
+For the install target, you will need to define KRB_INSTALL_DIR to
+point to the directory where the header, library, and executable files
+will be installed.  You can either define this in the environment or
+at the nmake command-line.  For example:
+
+nmake install [NODEBUG=1] KRB_INSTALL_DIR=c:\sdk\krb5
+
+Make sure you create the directory first.  Otherwise, nmake will
+complain.  The files will get installed into include, lib, and bin
+subdirectories.  You can then copy the binaries to where ever you want
+have them (probably somewhere in your path).
+
+
+Running Kerberos 5 Apps:
+-----------------------
+
+Make sure you have a valid krb5.ini file.  That will look just like a
+Unix krb5.conf file.  You can place this file in the same directory as
+your krb5_32.dll or in your Windows directory.  You should then be
+able to run the applications that are built.  Note that Kerberos 5
+will not look for the krb5.ini file in your path.
+
+
+krb5.ini File:
+-------------
+
+WARNING: Despite its name, this is not a Windows .ini file.
+Therefore, do not try to use any .ini tools, including the Windows API
+or any installer tools to manipulate this file.  Its format is subtly
+different from Windows .ini files!
+
+
+Controlling the Kerberos 5 Run-Time Environment:
+-----------------------------------------------
+
+The Kerberos 5 configuration file and credentials cache can be
+controlled with environment variables and registry settings.  The
+environment variable for a particular setting always takes precedence.
+Next in precedence comes the setting in the registry under
+HKEY_CURRENT_USER\Software\MIT\Kerberos5.  Then comes the registry
+setting under HKEY_LOCAL_MACHINE\Software\MIT\Kerberos5.  If none of
+those are found, a default value is used.
+
+Configuration File:
+- Environment: KRB5_CONFIG
+- Registry Value: config
+- Default: looks in krb5_32.dll's dir and Windows directory
+
+Default Credentials Cache:
+- Environment: KRB5CCNAME
+- Registry Value: ccname
+- Default: API:krb5cc or FILE:%TEMP%\krb5cc or FILE:<windows dir>\krb5cc
+
+
+Credentials Cache:
+-----------------
+
+In addition to standard FILE: (disk file) and MEMORY: (in-process
+non-shared memory) Windows supports the API: cache type, which is a
+shared memory cache.  This is implemented by krbcc32.dll, which is not
+included the the krb5-only distribution.  Rather, it is part of MIT's
+Kerberos for Win32 suite.  
+
+As of the 1.3.2 release, a new cache type, MSLSA:, has been added for
+use in accessing the Microsoft Kerberos Logon Session credentials 
+cache.  The MSLSA: cache is available when the user logon is performed
+using Kerberos either to an Active Directory Domain or a non-Microsoft
+KDC.
+
+A user is able to logon to Windows using the Kerberos LSA if the machine
+is part of a Windows 2000 or Windows 2003 Active Directory domain or
+if the machine has been configured to authenticate to a non-Microsoft KDC
+such as MIT.  The instructions for configuring a Windows 2000 XP
+workstation to authenticate to a non-Microsoft KDC are documented
+in TechNet somewhere.  In brief:
+
+  1. Install the Windows 2000 or XP support tools in order to obtain
+     the tools: KSETUP.EXE and KTPASS.EXE.
+  2. Install the Windows 2000 or XP Resource Kit to obtain the tools
+     KERBTRAY.EXE and KLIST.EXE
+  3. Add Realms and associated KDCs with: *KSETUP /AddKdc <realm>
+     [<kdcname>]*.  If you leave off the <kdcname> DNS SRV records will
+     be used.
+  4. Specify the password change service host for the realm with:
+     *KSETUP /AddKpasswd <realm> <Kpwdhost>*
+  5. Assign the realm of the local machine with: *KSETUP /SetRealm
+     <realm>* where realm must be all upper case.   
+  6. Assign the local machine's password with: *KSETUP
+     /SetComputerPassword <Password>
+     *
+  7. Specify the capabilities of the Realm KDC with: *KSETUP
+     /SetRealmFlags <realm> <flag> [<flag> ...]* where flags may be
+     *None, SendAddress, TcpSupported, Delegate, *and *NcSupported*,
+  8. Map principal names to local accounts with: *KSETUP /MapUser
+     <principal> <account>*
+
+On the MIT KDC, you must then create service principals using the "Password" 
+assigned to the machine.  So far the minimum list of principals required appear 
+to be for a machine named "mymachine" in the realm "EXAMPLE.COM" with a 
+domain name of "example.com":
+
+   * host/mymachine@EXAMPLE.COM
+   * host/mymachine.example.com@EXAMPLE.COM
+   * cifs/mymachine@EXAMPLE.COM
+   * cifs/mymachine.example.com@EXAMPLE.COM
+
+There may very well be other serivces for which principals must be created depending 
+on what services are being executed on the machine.
+
+It is very important to note that while you can successfully log into a Windows 
+workstation by authenticating to the KDC without creating a host key; the logon 
+session you receive will not be a Kerberos Logon Session.  There will be no Kerberos 
+principal and no LSA cache to access.
+
+The result of a real KSETUP configuration looks like this:
+
+   [C:\4\4NT]ksetup
+   default realm = KRB5.COLUMBIA.EDU (external)
+   ATHENA.MIT.EDU:
+           kdc = kerberos.mit.edu
+           kdc = kerberos-1.mit.edu
+           kdc = kerberos-2.mit.edu
+           kdc = kerberos-3.mit.edu
+           Realm Flags = 0x0 none
+   CC.COLUMBIA.EDU:
+           kdc = kerberos.cc.columbia.edu
+           Realm Flags = 0x0 none
+   GRAND.CENTRAL.ORG:
+           kdc = penn.central.org
+           kdc = grand-opening.mit.edu
+           Realm Flags = 0x0 none
+   KRB5.COLUMBIA.EDU:
+           kdc = yclept.kermit.columbia.edu
+           Realm Flags = 0x0 none
+   OPENAFS.ORG:
+           kdc = virtue.openafs.org
+           Realm Flags = 0x0 none
+   Mapping jaltman@KRB5.COLUMBIA.EDU to jaltman.
+   Mapping jaltman@CC.COLUMBIA.EDU to jaltman.
+   Mapping jaltman@ATHENA.MIT.EDU to jaltman.
+   Mapping all users (*) to a local account by the same name (*).
+
+The MSLSA: credential cache relies on the ability to extract the entire
+Kerberos ticket including the session key from the Kerberos LSA.  In an
+attempt to increase security Microsoft has begun to implement a feature
+by which they no longer export the session keys for Ticket Getting Tickets.
+This has the side effect of making them useless to the MIT krb5 library
+when attempting to request additional service tickets.
+
+This new feature has been seen in Windows 2003 Server, Windows 2000 Server SP4,
+and Windows XP SP2.  We assume that it will be implemented in all future
+Microsoft operating systems supporting the Kerberos SSPI.  Microsoft does work
+closely with MIT and has provided a registry key to disable this new feature.
+On server platforms the key is specified as:
+
+  HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters
+    AllowTGTSessionKey = 0x01 (DWORD)
+
+On workstation platforms the key is specified as: 
+
+  HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos
+    AllowTGTSessionKey = 0x01 (DWORD)
+
+It has been noted that the Microsoft Kerberos LSA does not provide enough 
+information within its KERB_EXTERNAL_TICKET structure to properly construct
+the Client Principal simply by examining a single ticket. From the MSDN
+Library:
+
+  ClientName 
+    KERB_EXTERNAL_NAME structure that contains the client name in the ticket. 
+    This name is relative to the current domain. 
+
+  DomainName 
+    UNICODE_STRING that contains the name of the domain that corresponds to 
+    the ServiceName member. This is the domain that issued the ticket. 
+
+  TargetDomainName 
+    UNICODE_STRING that contains the name of the domain in which the ticket is
+    valid. For an interdomain ticket, this is the destination domain. 
+
+  AltTargetDomainName 
+    UNICODE_STRING that contains a synonym for the destination domain. Every 
+    domain has two names: a DNS name and a NetBIOS name. If the name returned 
+    in the ticket is different from the name used to request the ticket (the 
+    Kerberos Key Distribution Center (KDC) may do name mapping), this string 
+    contains the original name. 
+
+Unfortunately, there is no field here which contains the domain of the client.
+In order for the krb5_ccache to properly report the client principal name, the 
+client principal name is constructed by utilizing the ClientName and DomainName
+fields of the Initial TGT associated with the Kerberos LSA credential cache.
+To disable the use of the TGT info and instead simply use the "DomainName" field
+of the current ticket define one of the following registry keys depending on
+whether the change should be system global or just for the current user.
+
+   HKLM\Software\MIT\Kerberos5\
+      PreserveInitialTicketIdentity = 0x0 (DWORD)
+
+   HKCU\Software\MIT\Kerberos5\
+      PreserveInitialTicketIdentity = 0x0 (DWORD)
+
+GSSAPI Sample Client:
+---------------------
+
+The GSS API Sample Client provided in this distribution is compatible with the
+gss-server application built on Unix/Linux systems.  This client is not compatible
+with the Platform SDK/Samples/Security/SSPI/GSS/ samples which Microsoft has been
+shipping as of January 2004.  Revised versions of these samples are available upon 
+request to krbdev@mit.edu.  
+
+Kerberos 4 Library Support:
+---------------------------
+
+The krb4_32.dll that is built (but not installed) is not supported.
+If you need Kerberos 4, you can use the krbv4w32.dll that MIT
+distributes as part of the MIT Kerberos for Windows distribution.
+
+
+More Information:
+----------------
+
+For more information, please read the Kerberos 5 documentation in
+the doc directory of the distribution.
diff --git a/krb5-1-6/src/windows/build/BKWconfig.xml b/krb5-1-6/src/windows/build/BKWconfig.xml
new file mode 100644
index 000000000..92fdc6ecd
--- /dev/null
+++ b/krb5-1-6/src/windows/build/BKWconfig.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- BKW: Build Kerberos for Windows -->
+<BKW_Config>
+    <Config>
+        <!-- All the parameters are specified here.  Most can be over-ridden
+                on the command line.
+
+            Parameters are grouped into Options, Directories, Repository and Environment.
+
+            Attributes a parameter can have:
+            abbr: A one character abbreviation.
+            def:  defined or not.  A value of 'A' for 'always' means the    
+               option can't be negated on the command line.                 
+            value:  string value, if the option can have a value.  If the option
+               can't take a value, omit the value attribute.
+            options:  space-delimited list, the 1st element is the default.
+               Synonyms for a valid option are concatenated with '|'.      
+            env: an environment variable will be set to value or deleted,  
+                depending on def.  If set and no value is given, '1' is used.                                 
+            -->
+        <!-- Options: -->
+        <clean      def="0" />
+        <config     def="1" abbr="f" value="bkwconfig.xml" />
+        <debug      def="0" abbr="d" />
+        <help       def="0" abbr="h|?" />
+        <logfile    def="1" abbr="l" value="bkw.pl.log" />
+        <make       def="1" />
+        <nolog      def="0" />
+        <package    def="1" />
+        <repository def="A" abbr="r" value="skip" options="skip checkout|co export|ex update|up" />
+        <sign       def="0" />
+        <verbose    def="0" abbr="v" />
+        <vverbose   def="0" />
+
+        <!-- Directory settings: -->
+        <!--    Sources will be checked out of repositories into <src>.  The structure
+                of the repositories will cause pismere/athena to be created under <src>.    -->
+        <src        def="A" abbr="s" value="C:\KfW" />        <!-- Must be absolute path. -->
+        <out        def="A" abbr="o" value="C:\KfW\public" /> <!-- Must be absolute path. -->
+
+        <!-- Repository settings: -->
+        <cvstag     def="0" abbr="c" value="" />
+        <svntag     def="0" abbr="t" value="" />
+        <svnbranch  def="0" abbr="b" value="" />
+        <username   def="0" abbr="u" value="" />    <!-- Needed for svn/plink.  Override from command line -->
+        <CVSROOT    def="A" value=":kserver:cvs.mit.edu:/cvs/pismere" />
+        <SVNURL     def="A" value="svn.mit.edu" />  <!-- NB:  No protocol or slashes!! -->
+
+        <!-- Environment variables: -->
+        <KH_RELEASE def="1" env="1" value="OFFICIAL" options="OFFICIAL PRERELEASE PRIVATE" />
+        <NODEBUG    def="1" env="1" />  <!-- Interacts with /DEBUG -->
+        </Config>
+    <Stages>
+        <FetchSources>
+            <Zips>
+                <Zip dummy="foo" /> <!-- To force desired XML::Simple behavior    -->
+                <Zip name="SRC" filename="%filestem%-src.zip" topdir="%filestem%-final">
+                    <CopyList>
+                        <Files>
+                            <!-- File from    paths are relative to <src>/pismere.  -->
+                            <!-- File to      paths are relative to <out>.          -->
+                            <File dummy="foo" /> <!-- Forces XML::Simple behavior   -->
+                            <!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+                            <File name="*.*" from="athena"  to="src\athena" />
+                            <File name="*.*" from="doc"     to="src\doc" />
+                            <File name="*.*" from="scripts" to="src\scripts" />
+                            </Files>
+                    </CopyList>
+                    <Prunes> <!-- Files to be removed from current build to match what is in the 3.1 distribution:    -->
+                        <Prune name="CVS" />
+                        <Prune name=".cvsignore" flags="i" />
+                        <Prune name="Changelog"  flags="i" />
+                        </Prunes>
+                    <Requires>
+                        <Switch dummy="foo" />
+                        <Switch name="REPOSITORY" value="CHECKOUT|EXPORT"/>
+                        <ErrorMsg text="Can't build source zip unless /REPOSITORY CHECKOUT or /REPOSITORY EXPORT is specified." />
+                        </Requires>
+                    </Zip>
+                </Zips>
+            </FetchSources>
+        <Make>
+            <!-- Script checks for prunes. -->
+            </Make>
+        <PrePackage>
+            <CopyList>
+                <Config>
+                    <!--    Debug and Release build results go in different places.
+                            The otherwise identical paths differ in one section.  For example:
+                            .../target/bin/i386/bin/rel/filename and .../target/bin/i386/dbg/filename.
+                            Here we define the two differing sections:    -->
+                    <DebugArea value="dbg" />
+                    <ReleaseArea value="rel" />
+                    <!--    Paths in the file list that include <AlwaysTag> will always have the tag replaced 
+                            with <DebugArea> or <ReleaseArea>, depending on the type of build.
+                            Paths that include <DebugTag> (or <ReleaseTag>) will only have the tag substituted 
+                            and be copied when doing a debug (or release) build.  Examples:
+                            Will always be copied, from a build-dependent directory:
+                            <File name="kfwlogon.dll"                 from="..\target\bin\i386\%bldtype%\" to="\bin\i386" /> 
+                            Will only be copied in debug build:
+                            <File name="netidmgr.exe.static.manifest" from="..\target\bin\i386\%debug%\"   to="\bin\i386" notrequired="true" />
+                            Will always be copied, from a build-independent directory:
+                            <File name="des.h"                        from="auth\krb4\include\"            to="\inc\krb4" newname="foo.h"/>
+                            -->
+                    <AlwaysTag  value="%bldtype%" />    <!-- Pick a string that won't appear in a path. -->
+                    <DebugTag   value="%debug%" />      <!-- Pick a string that won't appear in a path. -->
+                    <ReleaseTag value="%release%" />    <!-- Pick a string that won't appear in a path. -->
+                    </Config>
+                <Files>
+                    <Include path="copyfiles.xml" />
+                    </Files> <!-- Relative to location of bkw.pl. -->
+            </CopyList>
+        </PrePackage>
+        <Package>
+            <Config>
+                <Paths>    
+                    <Versions path="pismere/athena/include/kerberos.ver" /> <!-- Relative to <src>. -->
+                    </Paths>
+                </Config>
+            <MSI></MSI>
+            <NSIS></NSIS> <!-- NB:  Most config is done in site-local.nsi.  -->
+        </Package>
+        <PostPackage>
+            <Config>    <!-- This config info will be copied into each CopyList in PostPackage. -->
+                <FileStem name="kfw-%VERSION_MAJOR%-%VERSION_MINOR%-%VERSION_PATCH%" /> <!-- <FileStem> will be substituted for %filestem%. -->
+                <Signing>
+                    <CommandTemplate    value="signtool sign /a /d "MIT Kerberos for Windows" /du "http://web.mit.edu/kerberos" /t TIMESTAMPSERVERGOESHERE %filename%" />
+                    <FilePatterns       value="*.exe *.dll *.cpl *.msi" />
+                    </Signing>
+                </Config>
+            <Zips>
+                <Zip dummy="foo" /> <!-- To force desired XML::Simple behavior    -->
+                <!--    Files will be copied into directory <topdir>; <topdir> will appear in the paths of the files.    -->
+                <!-- File from  paths are relative to <src>/pismere.    -->
+                <!-- File to    paths are relative to <out>.            -->
+                <Zip name="Core Binaries" filename="%filestem%.zip" topdir="%filestem%-final">
+                    <CopyList>
+                        <Config>
+                            <DebugArea   value="dbg" />
+                            <ReleaseArea value="rel" />
+                            <AlwaysTag   value="%bldtype%" /> <!-- Pick a string that won't appear in a path. -->
+                            <DebugTag    value="%debug%" />   <!-- Pick a string that won't appear in a path. -->
+                            <ReleaseTag  value="%release%" /> <!-- Pick a string that won't appear in a path. -->
+                            </Config>
+                        <Files>
+                            <Include path="corebinaryfiles.xml" />  <!-- Included file is relative to location of bkw.pl. -->
+                            </Files> 
+                        </CopyList>
+                </Zip>
+                <Zip name="SDK" filename="%filestem%-sdk.zip" topdir="%filestem%-final">
+                    <CopyList>
+                        <Files>
+                            <Include path="sdkfiles.xml" />         <!-- Included file is relative to location of bkw.pl. -->
+                            </Files>
+                        </CopyList>
+                    </Zip>
+                </Zips>            
+            <CopyList>            <!-- Copied at end of post-package step.  -->
+                <Files>
+                    <File dummy="foo" />
+                    <!-- File from    paths are relative to <src/pismere>.  -->
+                    <!-- File to      paths are relative to <out>.          -->
+                    <File name="msi-deployment-guide.txt"   from="staging\install\wix\" to="" />
+                    <File name="netidmgr_userdoc.pdf"       from="staging\doc"          to="" />
+                    <File name="kfw.msi"                    from="buildwix"             to="" newname="%filestem%.msi" />
+                    <File name="MITKerberosForWindows%-DEBUG%.exe" from="buildnsi"      to="" newname="%filestem%%-DEBUG%.exe" />
+                    <File name="relnotes.html"              from="staging\doc"          to="" />
+                    </Files>
+                </CopyList>
+            </PostPackage>
+    </Stages>
+</BKW_Config>
\ No newline at end of file
diff --git a/krb5-1-6/src/windows/build/Logger.pm b/krb5-1-6/src/windows/build/Logger.pm
new file mode 100644
index 000000000..c7f904a94
--- /dev/null
+++ b/krb5-1-6/src/windows/build/Logger.pm
@@ -0,0 +1,87 @@
+package Logger;
+
+use strict;
+use IO::File;
+use FindBin;
+
+my $bStarted = 0;
+
+sub new {
+    my $class = shift;
+    my $file = shift;
+    my $append = shift;
+    $file || die "Usage: \$foo = new Logger filename [append]\n";
+    my $self = {};
+    bless  $self, $class;
+    $self->{FILE} = $file;
+    $self->{APPEND} = $append?'-a':'';
+    return $self;
+}
+
+sub start {
+    my $self = shift;
+
+    return 1 if $self->{PIPE};
+
+    STDOUT->flush;
+    STDERR->flush;
+
+    my $fh_out = new IO::File;
+    my $fh_err = new IO::File;
+    my $fh_pipe = new IO::File;
+
+    $self->{OUT} = $fh_out;
+    $self->{ERR} = $fh_err;
+    $self->{PIPE} = $fh_pipe;
+
+    $fh_out->open(">&STDOUT") || die;
+    $fh_err->open(">&STDERR") || die;
+    $fh_pipe->open("|$^X $FindBin::Bin/tee.pl $self->{APPEND} $self->{FILE}") || die;
+
+    STDOUT->fdopen(fileno $fh_pipe, "w") || die;
+    STDERR->fdopen(fileno $fh_pipe, "w") || die;
+
+    STDOUT->autoflush(1);
+    STDERR->autoflush(1);
+
+    $SIG{__DIE__} = sub {
+	print STDERR $_[0];
+	$self->stop;
+	die "\n";
+    };
+
+	$bStarted = 1;
+    return 1;
+}
+
+# 20070314 kpkoch:	
+#  There appears to be a bug in ActivePerl where Logger's games with streams
+#  and the SIG DIE handler cause eval to throw exceptions.  By deleting the DIE handler,
+#  subsequent evals do not fail.
+sub no_die_handler {
+	delete $SIG{__DIE__};
+	}
+
+sub stop {
+    my $self = shift;
+
+    return 0 if !$self->{PIPE};
+
+    STDOUT->close;
+    STDERR->close;
+    $self->{PIPE}->close;
+    STDOUT->fdopen(fileno $self->{OUT}, "w");
+    STDERR->fdopen(fileno $self->{ERR}, "w");
+    delete $self->{OUT};
+    delete $self->{ERR};
+    delete $self->{PIPE};
+	$bStarted = 0;
+    return 1;
+}
+
+sub DESTROY {
+    my $self = shift;
+	$self->stop	if ($bStarted);
+	}
+
+1;
diff --git a/krb5-1-6/src/windows/build/bkw-automation.html b/krb5-1-6/src/windows/build/bkw-automation.html
new file mode 100644
index 000000000..5e21ba570
--- /dev/null
+++ b/krb5-1-6/src/windows/build/bkw-automation.html
@@ -0,0 +1,356 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
+<!-- saved from url=(0066)https://confab.mit.edu/confluence/display/ISDA/lore-bkw-automation --><HTML><HEAD>
+        <TITLE>lore-bkw-automation - Confluence
+        
+        
+        
+        
+            
+                
+    
+        
+
The + Kerberos for Windows (KfW) build is automated.  A script will fetch the + sources from a repository and then build, sign and package all the KfW + distribution components. +
+
This + description consists of +
+ +

Setting Up the Build Environment

+

KfW is built on a Windows PC, in the default Windows shell (cmd.exe). These + components must be installed:

+
    +
  • + Visual Studio 2003
    + Versions of Visual Studio before or after 2003 are not supported. +
  • + A recent release of the + + + Microsoft Platform SDK +   +
  • + + + ActiveState Perl 5.8 or more recent
    + Build 631 is known to work. +
  • + + + Doxygen +
  • + sed, awk, cat, rm and find
    + These can be obtained from the + + Cygwin + distribution. +
    +
    + find must be in C:\tools\cygwin\bin, so install Cygwin in C:\tools\cygwin. +
    +
    + The cygwin awk is a link and the MS shell doesn't deal well with that.  C + opy c:\tools\cygwin\bin\gawk to c:\tools\cygwin\bin\awk. +
  • + + Wix +
  • + + + NSIS
+

Environment variables

+

+ All the components above must be in PATH. Installing ActivePerl puts perl in + the PATH. Doxygen, Cygwin, hhc, wix and nsis need to be added.

+

perl must be installed so that .pl files are automatically executed with perl. + The ActivePerl installation will do this for you.

+

In the INCLUDE path, the Microsoft Platform SDK must come before the Microsoft + Visual C++ include files. Using a Platform SDK Build Environment window will + set this up the right way. 

+

If you make your path modifications permanent via Control Panel / System / + Advanced / Environment Variables:  If you use a Platform SDK Build + Environment window, it appears that you need to put your PATH components in the + System PATH, not the User PATH.

+

Visual Studio installs hhc in C:\Program Files\HTML Help Workshop.

+

nmake must be in PATH. If you use a Platform SDK build environment window, it is + already done for you.

+

Running the Script

+

+ The build is a perl script controlled by command line switches and an XML + configuration file. The config file is required. Settings in the config file + can be overridden by optional command line switches. 

+

There are options for controlling most steps of the build process.  The + steps are

+
    +
  • + Verifying the environment +
  • + Fetching the sources from repositories +
  • + Building the sources +
  • + Setting up the packaging environment +
  • + Building the installers +
  • + Building the rest of the components +
  • +
+

The usage message shows the switches that control these steps:

+

C:\Projects\KfW>perl bkw.pl /?
+ Usage: bkw.pl [options] NMAKE-options

+

  Options are case insensitive. +

+

  Options:  +
+
  /help /?          + usage information (what you now see). +
+   /config /f path   Path to config file. Default is + bkwconfig.xml. +
+   /src /s dir       Source directory to use. + Should contain +
+     +                 + pismere/athena. If cvstag or svntag is null, +
+       +               + the directory should be prepopulated. +
+   /out /o dir       Directory to be created + where build results will go +
+
  /repository checkout | co \ What repository action to take. +
+      /r       + update   | up \ Options are to checkout, update, export
+               export   + | ex \ or take no action [skip]. 
+               + skip
+   /username /u name username used to access svn if checking out. +
+   /cvstag /c tag    use -r <tag> + in cvs +command
  /svnbranch /b tag use +/branches/<tag> instead of /trunk.
  /svntag /t tag    use +/tags/<tag> instead of /trunk.
  /debug +/d         Do debug make instead of +release make.
  +/[no]make         +Control the make +step.
  +/clean            Build +clean target.
  +/[no]package      Control the packaging step.
  +/[no]sign         Control +signing +of executable files.
  /verbose +/v       Debug mode - verbose output.
  /logfile /l path  Where to write output. +Default is bkw.pl.log.
  + /nolog            Don't + save output.
+

+

  Other: +
+     NMAKE-options any options you want to pass to NMAKE, which + can be: +
+                   + (note: /nologo is always used)
+                   NODEBUG=1

+

NMAKE-options any options you want to pass to NMAKE, which can be:
+ (note: /nologo is always used)
+ [ nmake options follow ]

+


+ Notes on the script steps:

+

Verifying the environment:  +
+ The script tests for each program that it needs and warns if the program isn't + found.

+

Fetching sources from repositories:  +
+ If building from a source distribution kit, this section does not apply.

+

CVSROOT and SVNURL must be specified in the configuration file.

+

A source zip file can only be produced if checking out fresh sources from a + repository. 

+

If checking out, the entire pismere directory will be deleted.  A warning + message requires that you confirm this action.

+

Building the sources:
+ /DEBUG controls whether a debug or release build is done.  /CLEAN will + build the CLEAN target.

+

Setting up the packaging environment :
+
The pre-package steps gathers up build results and puts them in a + staging area.  +

+

If /SIGN is specified, .exes, .dlls + and .cpls are signed.  The signing command + template is in the configuration file.

+

Building the installers:
+ The staging area is copied into a fresh area for + each of the installers.  The installer results are copied back to the + staging area.

+

Building the rest of the components:
+ Zip files are built in temporary areas and copied to outdir.  + The installers and assorted files are copied from staging + to outdir.  If /SIGN is specified, the + installers will be signed.

+

 

+

Script Internal Details

+

Copy Lists

+

CopyLists are used in many places.  For example, files to be put into + a .zip are copied to a fresh directory which is then zipped up.  There is + an optional Configuration section and a required Files section. 

+

The configuration section defines the roots of the from and to paths and can + optionally define path substitutions.  +

+

The to and from paths are forced by the script rather than being set in the + config file.  Comments in the copyfile xml indicate this.

+

Lengthy copy lists can be kept in separate files and included with the Include + directive.  Example:

+

<Include path="sdkfiles.xml" />

+

Substitution tags

+

Filenames in copylists can contain variable 'tags' that are replaced before the + file is copied.  Some configuration files contain substitution tags which + customize the configuration.  The supported tags are

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
%VERSION_MAJOR%KfW Version from pismere/athena/include/kerberos.ver.
%VERSION_MINOR%KfW Version from pismere/athena/include/kerberos.ver.
%VERSION_PATCH%KfW Version from pismere/athena/include/kerberos.ver.
%filestem%Defined as kfw-%VERSION_MAJOR%-%VERSION_MINOR%-%VERSION_PATCH%.
%debug%'dbg.'  Only substituted during a debug build. 
%release%'rel.'  Only substituted during a release build.  +
%bldtype%Always substituted, to 'dbg' or 'rel,' depending on the type of build.
%-DEBUG%'-DEBUG' during a debug build; otherwise empty.
%BUILDDIR%SRCDIR\pismere.  Used in site-local installer configuration files.
%TARGETDIR%SRCDIR\pismere\staging.  Used in site-local installer configuration files.
%CONFIGDIR-WIX%SRCDIR\pismere\staging\sample.  Used in site-local installer configuration + files.
%CONFIGDIR-NSI%SRCDIR\pismere\staging.  Used in site-local installer configuration files.
+

+

The overall build configuration specifies a debug or release build.  Debug + and release results are put in different places.  Files whose location + depend on the build type can use %bldtype% in their names.  The script + will substitute %bldtype% with either dbg or rel, depending on the build + type. 

+
+
+

Example

+
+

Here is a copylist entry.  Each segment of the file's path that comes + from a different place is in a different color.

+

Release build.  Config file: +

+

+ + + + + + + + + + + + + +
<BKW_Config>
<Config>
<src value ="C:\bkw" /> +
+

+

Copylist comments:

+

<!-- File from paths are relative to + \pismere\athena -->
<!-- File to paths are relative to \ + pismere\staging + -->
+

+

When the script processes this copylist, it will force the from and to paths as + indicated.

+

This line +

+

<File name="comerr32.dll" from="..\target\bin\i386\%bldtype%\" + to="\bin\i386" />

+

will result in C:\bkw\pismere\athena\..\target\bin\i386\rel\comerr32.dll

+

being copied to C:\bkw\pismere\staging\bin\i386\comerr32.dll.

+

Other possible attributes in a copylist entry:

+
    +
  • + notrequired +
  • + newname="filename" +
  • +
+

By default, copylist entries are required and the script will die if they aren't + present. To ignore missing files, add notrequired.

+

To rename the file, set the newname attribute.

+

Remaining Work / Bug List

+

Implement RETAIL, OFFICIAL, PRERELEASE, PRIVATE, SPECIAL.

+

Figure out what MIT_ONLY, BUILD_KFW, DEBUG_SYMBOL should be.

+

TARGET, APPVER.

+

NODEBUG=1.  Set if release build.

+

Troubleshooting +

+

Can't clean directory; can't delete file or directory
+ Make sure a file in the named directory isn't open in another application.

+

Can't find kerberos.ver
+ You skipped the repository step and are trying to build in an empty directory.

+
+ + diff --git a/krb5-1-6/src/windows/build/bkw.pl b/krb5-1-6/src/windows/build/bkw.pl new file mode 100644 index 000000000..9984a3343 --- /dev/null +++ b/krb5-1-6/src/windows/build/bkw.pl @@ -0,0 +1,690 @@ +#!perl -w + +#use strict; +use FindBin; +use File::Spec; +use File::Basename; +use lib "$FindBin::Bin/build/lib"; +use Getopt::Long; +use Cwd; +use XML::Simple; +use Data::Dumper; +use Archive::Zip; +use Logger; +require "copyfiles.pl"; +require "prunefiles.pl"; +require "signfiles.pl"; +require "zipXML.pl"; + +my $BAIL; +$0 = fileparse($0); +my $OPT = {foo => 'bar'}; +my $MAKE = 'NMAKE'; +our $config; + +sub get_info { + my $cmd = shift || die; + my $which = $^X.' which.pl'; + my $full = `$which $cmd`; + return 0 if ($? / 256); + chomp($full); + $full = "\"".$full."\""; + return { cmd => $cmd, full => $full}; + } + +sub usage { + print < in cvs command + /svnbranch /b tag use /branches/ instead of /trunk. + /svntag /t tag use /tags/ instead of /trunk. + /debug /d Do debug make instead of release make. + /[no]make Control the make step. + /clean Build clean target. + /[no]package Control the packaging step. + /[no]sign Control signing of executable files. + /verbose /v Debug mode - verbose output. + /logfile /l path Where to write output. Default is bkw.pl.log. + /nolog Don't save output. + Other: + NMAKE-options any options you want to pass to NMAKE, which can be: + (note: /nologo is always used) + +USAGE + system("$MAKE /?"); + } + +sub handler { + my $sig = shift; + my $bailmsg = "Bailing out due to SIG$sig!\n"; + my $warnmsg = <{config}) {$OPT->{config} = "bkwconfig.xml";} + my $configfile = $OPT->{config}; + print "Info -- Reading configuration from $configfile.\n"; + my $xml = new XML::Simple(); + $config = $xml->XMLin($configfile); ## Read in configuration file. + + # Set up convenience variables: + local $odr = $config->{Config}; ## Options, directories, repository, environment. + + # Build argument description from Config section of the XML, + # to parse the rest of the arguments: + local @xmlargs; + while (($sw, $val) = each %$odr) { + local $arg = $sw; + if (exists $val->{abbr}) {$arg .= "|$val->{abbr}";} + if (exists $val->{value}) { ## Can't do both negations and string values. + $arg .= ":s"; + } + else { + if (! ($val->{def} =~ /A/)) {$arg .= "!";} + } + push @xmlargs, $arg; + } + + if (!GetOptions($OPT, @xmlargs)) {$OPT->{help} = 1;} + + if ( $OPT->{help} ) { + usage(); + exit(0); + } + + delete $OPT->{foo}; + +##++ Validate required conditions: + + # List of programs which must be in PATH: + my @required_list = ('sed', 'awk', 'which', 'cat', 'rm', 'cvs', 'svn', 'doxygen', + 'hhc', 'candle', 'light', 'makensis', 'nmake', 'plink', 'filever'); + my $requirements_met = 1; + my $first_missing = 0; + my $error_list = ""; + foreach my $required (@required_list) { + if (!get_info($required)) { + $requirements_met = 0; + if (!$first_missing) { + $first_missing = 1; + $error_list = "Fatal -- Environment problem! The following program(s) are not in PATH:\n"; + } + $error_list .= "$required\n"; + } + } + if (!$requirements_met) { + print $error_list; + print "Info -- Update PATH or install the programs and try again.\n"; + exit(0); + } + +##-- Validate required conditions. + + use Time::gmtime; + $ENV{DATE} = gmctime()." GMT"; + our $originalDir = `cd`; + $originalDir =~ s/\n//g; + +##++ Assemble configuration from config file and command line: + + my $bOutputCleaned = 0; + +#while ($v = each %$OPT) {print "$v: $OPT->{$v}\n";} + + # Scan the configuration for switch definitions: + while (($sw, $val) = each %$odr) { + next if (! exists $val->{def}); ## ?? Should always exist. + + # Set/clear environment variables: + if ($val->{env}) { + if ($val->{def}) {$ENV{$sw} = (exists $val->{value}) ? $val->{value} : 1; } + else {delete $ENV{$sw}; } + } + + # If the switch is in the command line, override the stored value: + if (exists $OPT->{$sw}) { + if (exists $val->{value}) { + $val->{value} = $OPT->{$sw}; + $val->{def} = 1; + } + else { + $val->{def} = $OPT->{$sw}; ## If no, value will be zero. + } + } + # If the switch can be negated, test that, too: + if ( ! ($val->{def} =~ /A/)) { + local $nosw = "no".$sw; + if (exists $OPT->{$nosw}) { + $val->{def} = 0; + } + } + + # For any switch definition with fixed values ("options"), validate: + if (exists $val->{options}) { + local $bValid = 0; + # options can be like value1|syn1 value2|syn2|syn3 + foreach $option (split(/ /, $val->{options})) { + local $bFirst = 1; + local $sFirst; + foreach $opt (split(/\|/, $option)) { + # opt will be like value2, syn2, syn3 + if ($bFirst) { + $sFirst = $opt; ## Remember the full name of the option. + $bFirst = 0; + } + if ($val->{value} =~ /$opt/i) { + $val->{value} = $sFirst; ## Save the full name. + $bValid = 1; + } + } + } + if (! $bValid) { + print "Fatal -- invalid $sw value $val->{value}. Possible values are $val->{options}.\n"; + usage(); + die; + } + } + } + + # Set up convenience variables: + our $verbose = $odr->{verbose}->{def}; + our $vverbose = $odr->{vverbose}->{def}; + our $clean = $clean->{clean}->{def}; + local $src = $odr->{src}->{value}; + local $out = $odr->{out}->{value}; + + if ($clean && $odr->{package}->{def}) { + print "Info -- /clean forces /nopackage.\n"; + $odr->{package}->{def} = 0; + } + + if ($vverbose) {print "Debug -- Config: ".Dumper($config);} + + # Test the unix find command: + # List of directories where it might be: + my @find_dirs = ('c:\\cygwin\\bin', 'c:\\tools\\cygwin\\bin'); + if (exists $odr->{unixfind}->{value}) { ## Was an additional place to look specified? + push (@find_dirs, $odr->{unixfind}->{value}); + } + my $bFindFound = 0; + foreach my $dir (@find_dirs) { + if (-d $dir) { + local $savedPATH = $ENV{PATH}; + $ENV{PATH} = $dir.";".$savedPATH; + if (-e "a.tmp") {!system("rm a.tmp") or die "Fatal -- Couldn't clean temporary file a.tmp.";} + !system("find . -maxdepth 0 -name a.tmp > b.tmp 2>&1") or die "Fatal -- find test failed."; + local $filesize = -s "b.tmp"; + $ENV{PATH} = $savedPATH; + if ($filesize <= 0) { + $bFindFound = 1; + $odr->{unixfind}->{value} = $dir; + last; + } + } + } + if (! $bFindFound) { + print "Fatal -- unix find command not found in \n"; + map {print " $_ "} @find_dirs; + print "\n"; + die; + } + + # Don't allow /svntag and /svnbranch simultaneously: + if ( (length $odr->{svntag}->{value} > 0) && + (length $odr->{svnbranch}->{value} > 0) ) { + die "Fatal -- Can't specify both /SVNTAG and /SVNBRANCH."; + } + + # /logfile and /nolog interact: + if ($odr->{nolog}->{def}) {$odr->{logfile}->{def} = 0;} + +##-- Assemble configuration from config file and command line. + + local $rverb = $odr->{repository}->{value}; + if ( (($rverb =~ /checkout/) || ($rverb =~ /export/)) && $clean) { + print "Warning -- Because sources are being checked out, make clean will not be run.\n"; + $clean = $odr->{clean}->{def} = 0; + } + + my $wd = $src."\\pismere"; + + if (! ($rverb =~ /skip/)) { + local $len = 0; + if (exists $odr->{username}->{value}) { + $len = length $odr->{username}->{value}; + } + if ($len < 1) { + die "Fatal -- you won't get far accessing the repository without specifying a username."; + } + } + + # (------------------------------------------------) + if ( (-d $wd) && ( ($rverb =~ /export/) || ($rverb =~ /checkout/) ) ) { + print "\n\nHEADS UP!!\n\n"; + print "/REPOSITORY ".uc($rverb)." will cause everything under $wd to be deleted.\n"; + print "If this is not what you intended, here's your chance to bail out!\n\n\n"; + print "Are you sure you want to remove everything under $wd? "; + my $char = getc; + if (! ($char =~ /y/i)) {die "Info -- operation aborted by user."} + !system("rm -rf $wd/*") or die "Fatal -- Couldn't clean $wd."; + !system("rmdir $wd") or die "Fatal -- Couldn't remove $wd."; + } + +# Begin logging: + my $l; + if ($odr->{logfile}->{def}) { + print "Info -- logging to $odr->{logfile}->{value}.\n"; + $l = new Logger $odr->{logfile}->{value}; + $l->start; + $l->no_die_handler; ## Needed so XML::Simple won't throw exceptions. + } + + print "Executing $cmdline\n"; + local $argvsize = @ARGV; + if ($argvsize > 0) { + print "\nArguments for NMAKE: "; + map {print " $_ "} @ARGV; + print "\n"; + } + + print "Info -- Using unix find in $odr->{unixfind}->{value}\n" if ($verbose); + +##++ Begin repository action: + if ($rverb =~ /skip/) {print "Info -- *** Skipping repository access.\n" if ($verbose);} + else { + if ($verbose) {print "Info -- *** Begin fetching sources.\n";} + local $cvspath = "$src"; + if (! -d $cvspath) { ## xcopy will create the entire path for us. + !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`; + !system("echo F | xcopy a.tmp $cvspath\\a.tmp") or die "Fatal -- Couldn't xcopy to $cvspath."; + !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file."; + !system("rm $cvspath\\a.tmp") or die "Fatal -- Couldn't remove temporary file."; + } + + # Set up cvs environment variables: + $ENV{CVSROOT} = $odr->{CVSROOT}->{value}; + local $krb5dir = "$wd\\athena\\auth\\krb5"; + + local $cvscmdroot = "cvs $rverb"; + if (length $odr->{cvstag}->{value} > 0) { + $cvscmdroot .= " -r $odr->{cvstag}->{value}"; + } + + if (($rverb =~ /checkout/) || ($rverb =~ /export/)) { + chdir($src) or die "Fatal -- couldn't chdir to $src\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + my @cvsmodules = ( + 'krb', + 'pismere/athena/util/lib/delaydlls', + 'pismere/athena/util/lib/getopt', + 'pismere/athena/util/guiwrap' + ); + foreach my $module (@cvsmodules) { + local $cvscmd = $cvscmdroot." ".$module; + if ($verbose) {print "Info -- cvs command: $cvscmd\n";} + !system("$cvscmd") or die "Fatal -- command \"$cvscmd\" failed; return code $?\n"; + } + } + else { ## Update. + chdir($wd) or die "Fatal -- couldn't chdir to $wd\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + if ($verbose) {print "Info -- cvs command: $cvscmdroot\n";} + !system($cvscmdroot) or die "Fatal -- command \"$cvscmdroot\" failed; return code $?\n"; + } + + # Set up svn environment variable: + $ENV{SVN_SSH} = "plink.exe"; + # If the directory structure doesn't exist, many cd commands will fail. + if (! -d $krb5dir) { ## xcopy will create the entire path for us. + !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`; + !system("echo F | xcopy a.tmp $krb5dir\\a.tmp") or die "Fatal -- Couldn't xcopy to $krb5dir."; + !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file."; + !system("rm $krb5dir\\a.tmp") or die "Fatal -- Couldn't remove temporary file."; + } + + chdir($krb5dir) or die "Fatal -- Couldn't chdir to $krb5dir"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + my $svncmd = "svn $rverb "; + if (($rverb =~ /checkout/) || ($rverb =~ /export/)) { # Append the rest of the checkout/export command: + chdir(".."); + if ($rverb =~ /export/) { + ## svn export will fail if the destination directory exists + rmdir "krb5"; + } + $svncmd .= "svn+ssh://".$odr->{username}->{value}."@".$odr->{SVNURL}->{value}."/krb5/"; + if (length $odr->{svntag}->{value} > 0) { + $svncmd .= "tags/$odr->{svntag}->{value}"; + } + elsif (length $odr->{svnbranch}->{value} > 0) { + $svncmd .= "branches/$odr->{svnbranch}->{value}"; + } + else { + $svncmd .= "trunk"; + } + + $svncmd .= " krb5"; + + } + if ($verbose) {print "Info -- svn command: $svncmd\n";} + !system($svncmd) or die "Fatal -- command \"$svncmd\" failed; return code $?\n"; + if ($verbose) {print "Info -- *** End fetching sources.\n";} + } +##-- End repository action. + + ##++ Read in the version information to be able to update the + # site-local files in the install build areas. + # ** Do this now (after repository update and before first zip) + # because making zip files requires some configuration data be set up. + local $version_path = $config->{Stages}->{Package}->{Config}->{Paths}->{Versions}->{path}; + open(DAT, "$src/$version_path") or die "Could not open $version_path."; + @raw = ; + close DAT; + foreach $line (@raw) { + chomp $line; + if ($line =~ /#define/) { # Process #define lines: + $line =~ s/#define//; # Remove #define token + $line =~ s/^\s+//; # and leading & trailing whitespace + $line =~ s/\s+$//; + local @qr = split("\"", $line); # Try splitting with quotes + if (exists $qr[1]) { + $qr[0] =~ s/^\s+//; # Clean up whitespace + $qr[0] =~ s/\s+$//; + $config->{Versions}->{$qr[0]} = $qr[1]; # Save string + } + else { # No quotes, so + local @ar = split(" ", $line); # split with space + $ar[0] =~ s/^\s+//; # Clean up whitespace + $ar[0] =~ s/\s+$//; + $config->{Versions}->{$ar[0]} = $ar[1]; # and save numeric value + } + } + } + + # Check that the versions we will need for site-local have been defined: + my @required_versions = ('VER_PROD_MAJOR', 'VER_PROD_MINOR', 'VER_PROD_REV', + 'VER_PROD_MAJOR_STR', 'VER_PROD_MINOR_STR', 'VER_PROD_REV_STR', + 'VER_PRODUCTNAME_STR'); + $requirements_met = 1; + $first_missing = 0; + $error_list = ""; + foreach my $required (@required_versions) { + if (! exists $config->{Versions}->{$required}) { + $requirements_met = 0; + if (!$first_missing) { + $first_missing = 1; + $error_list = "Fatal -- The following version(s) are not defined in $src/$version_path.\n"; + } + $error_list .= "$required\n"; + } + } + if (!$requirements_met) { + print $error_list; + exit(0); + } + + # Apply any of these tags to filestem: + my $filestem = $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name}; + $filestem =~ s/%VERSION_MAJOR%/$config->{Versions}->{'VER_PROD_MAJOR_STR'}/; + $filestem =~ s/%VERSION_MINOR%/$config->{Versions}->{'VER_PROD_MINOR_STR'}/; + $filestem =~ s/%VERSION_PATCH%/$config->{Versions}->{'VER_PROD_REV_STR'}/; + $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name} = $filestem; + ##-- Read in the version information & set config info. + +##++ Repository action, part 2: + if (($rverb =~ /checkout/) || ($rverb =~ /export/)) { + if (! $bOutputCleaned) { ## In case somebody cleaned $out before us. + if (-d $out) {!system("rm -rf $out/*") or die "Fatal -- Couldn't clean $out."} ## Clean output directory. + else {mkdir($out);} + $bOutputCleaned = 1; + } + zipXML($config->{Stages}->{FetchSources}, $config); ## Make zips. + } +##-- End repository action, part 2. + +##++ Make action: + if ( ($odr->{make}->{def}) ) { + if ($verbose) {print "Info -- *** Begin preparing for build.\n";} + + chdir("$wd") or die "Fatal -- couldn't chdir to $wd\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + + my ($path, $destpath); + + # Copy athena\scripts\site\graft\krb5\Makefile.src to athena\auth\krb5: + $path = "scripts\\site\\graft\\krb5\\Makefile.src"; + if (!-e $path) {die "Fatal -- Expected file $wd\\$path not found.";} + $destpath = "athena\\auth\\krb5\\Makefile.src"; + !system("echo F | xcopy /D $wd\\$path $wd\\$destpath /Y > NUL") or die "Fatal -- Copy of $wd\\$path to $wd\\$destpath failed."; + print "Info -- copied $wd\\$path to $wd\\$destpath\n" if ($verbose);; + + # Add DEBUG_SYMBOL to .../wshelper/Makefile.src: + $path = "athena\\wshelper\\wshelper\\Makefile.src"; + if (!-e $path) {die "Fatal -- Expected file $wd\\$path not found.";} + if (system("grep DEBUG_SYMBOL $path > NUL") != 0) { + !system ("echo DEBUG_SYMBOL=1 >> $wd\\$path") or die "Fatal -- Append line to file failed.\n"; + print "Info -- Added DEBUG_SYMBOL to $wd\\$path\n" if ($verbose); + } + + # Prune any unwanted directories before the build: + pruneFiles($config->{Stages}->{Make}, $config); + + if ($verbose) {print "Info -- *** End preparing for build.\n";} + + my ($buildtarget, $buildtext); + if ($clean) { + $buildtarget = "clean" ; + $buildtext = " clean." + } + else { + $buildtarget = "" ; + $buildtext = "." + } + + chdir("$wd\\athena") or die "Fatal -- couldn't chdir to source directory $wd\\athena\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + local $dbgswitch = ($odr->{debug}->{def}) ? " " : "NODEBUG=1"; + !system("perl ../scripts/build.pl --softdirs --nolog $buildtarget $dbgswitch BUILD_KFW=1 BUILD_OFFICIAL=1 DEBUG_SYMBOL=1") + or die "Fatal -- build $buildtarget failed."; + + chdir("$wd") or die "Fatal -- couldn't chdir to $wd."; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + if ($clean) { + if (-d "staging") { + !system("rm -rf staging") or die "Fatal -- Couldn't remove $wd\\staging."; + } + } + + if ($verbose) {print "Info -- *** End build".$buildtext."\n";} + } ## End make conditional. + else {print "Info -- *** Skipping build.\n" if ($verbose);} +##-- Make action. + +##++ Package action: + if (! $odr->{package}->{def}) { ## If /clean, nopackage will be set. + print "Info -- *** Skipping packaging.\n"; + if ((-d $out) && ! $bOutputCleaned) { + print "Warning -- *** Output directory $out will not be cleaned.\n"; + } + } + else { + if ($verbose) {print "Info -- *** Begin prepackage.\n";} + + if (! $bOutputCleaned) { ## In case somebody cleaned $out before us. + if (-d $out) {!system("rm -rf $out/*") or die "Fatal -- Couldn't clean $out."} ## Clean output directory. + else {mkdir($out);} + $bOutputCleaned = 1; + } + + # The build results are copied to a staging area, where the packager expects to find them. + # We put the staging area in the fixed area .../pismere/staging. + my $prepackage = $config->{Stages}->{PrePackage}; + my $staging = "$wd\\staging"; + chdir($wd) or die "Fatal -- couldn't chdir to $wd\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + if (-d "staging") { + !system("rm -rf $staging/*") or die "Fatal -- Couldn't clean $staging."; + } + else { + mkdir($staging) or die "Fatal -- Couldn't create $staging."; + } + + # Force Where From and To are relative to: + $prepackage->{CopyList}->{Config}->{From}->{root} = "$wd\\athena"; + $prepackage->{CopyList}->{Config}->{To}->{root} = "$wd\\staging"; + copyFiles($prepackage->{CopyList}, $config); ## Copy any files [this step takes a while] + + # Sign files: + chdir($staging) or die "Fatal -- couldn't chdir to $staging\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + if ($odr->{sign}->{def}) { + signFiles($config->{Stages}->{PostPackage}->{Config}->{Signing}, $config); + } + + # Create working directories for building the installers: + if (-d "$wd\\buildwix") {!system("rm -rf $wd\\buildwix/*") or die "Fatal -- Couldn't clean $wd\\buildwix."} + !system("echo D | xcopy /s $wd\\staging\\install\\wix\\*.* $wd\\buildwix") or die "Fatal -- Couldn't create $wd\\buildwix."; + if (-d "$wd\\buildnsi") {!system("rm -rf $wd\\buildnsi/*") or die "Fatal -- Couldn't clean $wd\\buildnsi."} + !system("echo D | xcopy /s $wd\\staging\\install\\nsis\\*.* $wd\\buildnsi") or die "Fatal -- Couldn't create $wd\\buildnsi."; + + chdir("$staging\\install\\wix") or die "Fatal -- Couldn't cd to $staging\\install\\wix"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + # Correct errors in files.wxi: + !system("sed 's/WorkingDirectory=\"\\[dirbin\\]\"/WorkingDirectory=\"dirbin\"/g' files.wxi > a.tmp") or die "Fatal -- Couldn't modify files.wxi."; + !system("mv a.tmp files.wxi") or die "Fatal -- Couldn't update files.wxi."; + + # Make sed script to run on the site-local configuration files: + local $tmpfile = "site-local.sed" ; + if (-e $tmpfile) {system("del $tmpfile");} + # Basic substitutions: + local $dblback_wd = $wd; + $dblback_wd =~ s/\\/\\\\/g; + !system("echo s/%BUILDDIR%/$dblback_wd/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + local $dblback_staging = "$wd\\staging"; + $dblback_staging =~ s/\\/\\\\/g; + !system("echo s/%TARGETDIR%/$dblback_staging/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + local $dblback_sample = "$wd\\staging\\sample"; + $dblback_sample =~ s/\\/\\\\/g; + !system("echo s/%CONFIGDIR-WIX%/$dblback_sample/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + !system("echo s/%CONFIGDIR-NSI%/$dblback_staging/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + !system("echo s/%VERSION_MAJOR%/$config->{Versions}->{'VER_PROD_MAJOR_STR'}/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + !system("echo s/%VERSION_MINOR%/$config->{Versions}->{'VER_PROD_MINOR_STR'}/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + !system("echo s/%VERSION_PATCH%/$config->{Versions}->{'VER_PROD_REV_STR'}/ >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + # Strip out some defines so they can be replaced: [used for site-local.nsi] + !system("echo /\^!define\.\*RELEASE\.\*\$/d >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + !system("echo /\^!define\.\*DEBUG\.\*\$/d >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + !system("echo /\^!define\.\*BETA\.\*\$/d >> $tmpfile") or die "Fatal -- Couldn't modify $tmpfile."; + + # Run the script on site-local.wxi: + !system("sed -f $tmpfile site-local-tagged.wxi > $wd\\buildwix\\site-local.wxi") or die "Fatal -- Couldn't modify site-local.wxi."; + + # Now update site-local.nsi: + chdir "..\\nsis"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + !system("sed -f ..\\wix\\$tmpfile site-local-tagged.nsi > b.tmp") or die "Fatal -- Couldn't modify site-local.wxi."; + # Add DEBUG or RELEASE: + if ($odr->{debug}->{def}) { ## debug build + !system("echo !define DEBUG >> b.tmp") or die "Fatal -- Couldn't modify b.tmp."; + } + else { ## release build + !system("echo !define RELEASE >> b.tmp") or die "Fatal -- Couldn't modify b.tmp."; + } + # Add BETA if present: + if (exists $config->{Versions}->{'BETA_STR'}) { + !system("echo !define BETA $config->{Versions}->{'BETA_STR'} >> b.tmp") or die "Fatal -- Couldn't modify b.tmp."; + } + !system("mv -f b.tmp $wd\\buildnsi\\site-local.nsi") or die "Fatal -- Couldn't replace site-local.nsi."; + + # Run the script on nsi-includes-tagged.nsi: + !system("sed -f ..\\wix\\$tmpfile nsi-includes-tagged.nsi > $wd\\buildnsi\\nsi-includes.nsi") or die "Fatal -- Couldn't modify nsi-includes.nsi."; + !system("rm ..\\wix\\$tmpfile") or die "Fatal -- Couldn't remove $tmpfile."; + + if ($verbose) {print "Info -- *** End prepackage.\n";} + + if ($verbose) {print "Info -- *** Begin package.\n";} + # Make the msi: + chdir("$wd\\buildwix") or die "Fatal -- Couldn't cd to $wd\\buildwix"; + print "Info -- *** Make .msi:\n" if ($verbose); + print "Info -- chdir to ".`cd`."\n" if ($verbose); + !system("$MAKE") or die "Error -- msi installer build failed."; + + chdir("$wd\\buildnsi") or die "Fatal -- Couldn't cd to $wd\\buildnsi"; + print "Info -- *** Make NSIS:\n" if ($verbose); + print "Info -- chdir to ".`cd`."\n" if ($verbose); + !system("cl.exe killer.cpp advapi32.lib") or die "Error -- nsis killer.exe not built."; + !system("rename killer.exe Killer.exe") or die "Error -- Couldn't rename killer.exe"; + !system("makensis kfw.nsi") or die "Error -- executable installer build failed."; + +# Begin packaging extra items: + chdir($wd) or die "Fatal -- Couldn't cd to $wd"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + + zipXML($config->{Stages}->{PostPackage}, $config); ## Make zips. + + $config->{Stages}->{PostPackage}->{CopyList}->{Config} = $config->{Stages}->{PostPackage}->{Config}; ## Use the post package config. + $config->{Stages}->{PostPackage}->{CopyList}->{Config}->{From}->{root} = "$src\\pismere"; + $config->{Stages}->{PostPackage}->{CopyList}->{Config}->{To}->{root} = $out; + copyFiles($config->{Stages}->{PostPackage}->{CopyList}, $config); ## Copy any files + + !system("rm -rf $wd\\buildwix") or die "Fatal -- Couldn't remove $wd\\buildwix."; + !system("rm -rf $wd\\buildnsi") or die "Fatal -- Couldn't remove $wd\\buildnsi."; + + chdir($out) or die "Fatal -- Couldn't cd to $out"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + if ($odr->{sign}->{def}) { + signFiles($config->{Stages}->{PostPackage}->{Config}->{Signing}, $config); + } + + if ($verbose) {print "Info -- *** End package.\n";} + } +##-- Package action. + + system("rm -rf $src/a.tmp"); ## Clean up junk. + system("rm -rf $out/a.tmp"); ## Clean up junk. + system("rm -rf $out/ziptemp"); ## Clean up junk. + +# End logging: + if ($odr->{logfile}->{def}) {$l->stop;} + + return 0; + } ## End subroutine main. + +$SIG{'INT'} = \&handler; +$SIG{'QUIT'} = \&handler; + +exit(main()); \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/bootstrap.xml b/krb5-1-6/src/windows/build/bootstrap.xml new file mode 100644 index 000000000..7cff6f53f --- /dev/null +++ b/krb5-1-6/src/windows/build/bootstrap.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/commandandcontrol.pl b/krb5-1-6/src/windows/build/commandandcontrol.pl new file mode 100644 index 000000000..305b96603 --- /dev/null +++ b/krb5-1-6/src/windows/build/commandandcontrol.pl @@ -0,0 +1,170 @@ +#!perl -w + +#use strict; + +sub commandandcontrol { + local ($configdefault, $bIgnoreCmdlineConfig) = @_; + local $OPT = {foo => 'bar'}; + + Getopt::Long::Configure('no_bundling', 'no_auto_abbrev', + 'no_getopt_compat', 'require_order', + 'ignore_case', 'pass_through', + 'prefix_pattern=(--|-|\+|\/)' + ); + GetOptions($OPT, + 'help|h|?', + 'cvstag|c:s', + 'svntag|s:s', + 'svnbranch|b:s', + 'src|r:s', + 'out|o:s', + 'debug|d', + 'nodebug', + 'config|f=s', + 'logfile|l:s', + 'nolog', + 'repository:s', + 'username|u:s', + 'verbose|v', + 'vverbose', + 'make!', + 'clean', + 'package!', + 'sign!', + ); + + if ( $OPT->{help} ) { + usage(); + exit(0); + } + + delete $OPT->{foo}; + + local $argvsize = @ARGV; + if ($argvsize > 0) { + print "Error -- invalid argument: $ARGV[0]\n"; + usage(); + die; + } + # The first time C&C is called, it is OK to override the default (./bkwconfig.xml) + # with a value from the command line. + # The second time C&C is called, the repository has been updated and C&C will be passed + # /pismere/athena/auth/krb5/windows/build/bkwconfig.xml. That value MUST be used. + if ($bIgnoreCmdlineConfig) {$OPT->{config} = $configdefault;} + elsif (! exists $OPT->{config}) {$OPT->{config} = $configdefault;} + + my $configfile = $OPT->{config}; + my $bOutputCleaned = 0; + + print "Info -- Reading configuration from $configfile.\n"; + + # Get configuration file: + local $xml = new XML::Simple(); + my $config = $xml->XMLin($configfile); + # Set up convenience variables: + local $odr = $config->{Config}; ## Options, directories, repository, environment. + +#while ($v = each %$OPT) {print "$v: $OPT->{$v}\n";} + + # Scan the configuration for switch definitions: + while (($sw, $val) = each %$odr) { + next if (! exists $val->{def}); ## ?? Should always exist. + + # Set/clear environment variables: + if ($val->{env}) { + if ($val->{def}) {$ENV{$sw} = (exists $val->{value}) ? $val->{value} : 1; } + else {delete $ENV{$sw}; } + } + + # If the switch is in the command line, override the stored value: + if (exists $OPT->{$sw}) { + if (exists $val->{value}) { + $val->{value} = $OPT->{$sw}; + $val->{def} = 1; + } + else { + $val->{def} = $OPT->{$sw}; ## If no, value will be zero. + } + } + # If the switch can be negated, test that, too: + if ( ! ($val->{def} =~ /A/)) { + local $nosw = "no".$sw; + if (exists $OPT->{$nosw}) { + $val->{def} = 0; + } + } + + # For any switch definition with fixed values ("options"), validate: + if (exists $val->{options}) { + local $bValid = 0; + # options can be like value1|syn1 value2|syn2|syn3 + foreach $option (split(/ /, $val->{options})) { + local $bFirst = 1; + local $sFirst; + foreach $opt (split(/\|/, $option)) { + # opt will be like value2, syn2, syn3 + if ($bFirst) { + $sFirst = $opt; ## Remember the full name of the option. + $bFirst = 0; + } + if ($val->{value} =~ /$opt/i) { + $val->{value} = $sFirst; ## Save the full name. + $bValid = 1; + } + } + } + if (! $bValid) { + print "Fatal -- invalid $sw value $val->{value}. Possible values are $val->{options}.\n"; + usage(); + die; + } + } + } + + # Don't allow /svntag and /svnbranch simultaneously: + if ( (length $odr->{svntag}->{value} > 0) && + (length $odr->{svnbranch}->{value} > 0) ) { + die "Fatal -- Can't specify both /SVNTAG and /SVNBRANCH."; + } + + return $config; + } + + +sub usage { + print < in cvs command + /svnbranch /b tag use /branches/ instead of /trunk. + /svntag /s tag use /tags/ instead of /trunk. + /debug /d Do debug make instead of release make. + /[no]make Control the make step. + /clean Build clean target. + /[no]package Control the packaging step. + /[no]sign Control signing of executable files. + /verbose /v Debug mode - verbose output. + /logfile /l path Where to write output. Default is bkw.pl.log. + /nolog Don't save output. + Other: + NMAKE-options any options you want to pass to NMAKE, which can be: + (note: /nologo is always used) + +USAGE + system("$MAKE /?"); + } + +return 1; \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/copyfiles.pl b/krb5-1-6/src/windows/build/copyfiles.pl new file mode 100644 index 000000000..9f9ccdde6 --- /dev/null +++ b/krb5-1-6/src/windows/build/copyfiles.pl @@ -0,0 +1,137 @@ +#!perl -w + +#use strict; +use XML::Simple; +use Data::Dumper; + +sub copyFiles { + local ($xml, $config) = @_; + local @odr = $config->{Config}; + local @files = $xml->{Files}; + # Check for includes: + if (exists $xml->{Files}->{Include}->{path}) { + my $includepath = $xml->{Files}->{Include}->{path}; + print "Info -- Including files from $includepath\n"; + my $savedDir = `cd`; + $savedDir =~ s/\n//g; + chdir $originalDir; ## Includes are relative to where we were invoked. + print "Info -- chdir to ".`cd`."\n" if ($verbose); + my $tmp = new XML::Simple; + my $includeXML = $tmp->XMLin($includepath); + chdir $savedDir; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + + local $i = 0; + while ($includeXML->{File}[$i]) { ## Copy File entries from includeXML. + $files[0]->{File}[++$#{$files[0]->{File}}] = $includeXML->{File}[$i]; + $i++; + } + delete $files->{Include}; + } + ##++ Set up path substitution variables for use inside the copy loop: + # A path can contain a variable part, which will be handled here. If the variable part is + # the Always or BuildDependent tag, then the variable will be changed to the + # build-type-dependent PathFragment. + # If the variable part is the IgnoreTag, then the file will not be copied. + # If the variable part is %filestem%, it will be replaced with Config->FileStem->name. + my ($PathFragment, $BuildDependentTag, $IgnoreTag, $FileStemFragment, $fromRoot, $toRoot); + my $bPathTags = (exists $xml->{Config}->{DebugArea}) && (exists $xml->{Config}->{ReleaseArea}); + my $bFileStem = (exists $xml->{Config}->{FileStem}); + + if ($odr->{debug}->{def}) { ## Debug build tags: + $PathFragment = $xml->{Config}->{DebugArea}->{value}; + $BuildDependentTag = $xml->{Config}->{DebugTag}->{value}; + $IgnoreTag = $xml->{Config}->{ReleaseTag}->{value}; + } + else { ## Release build tags: + $PathFragment = $xml->{Config}->{ReleaseArea}->{value}; + $BuildDependentTag = $xml->{Config}->{ReleaseTag}->{value}; + $IgnoreTag = $xml->{Config}->{DebugTag}->{value}; + } + my $AlwaysTag = $xml->{Config}->{AlwaysTag}->{value}; + $FileStemFragment = $xml->{Config}->{FileStem}->{name}; + $fromRoot = $xml->{Config}->{From}->{root}; + $toRoot = $xml->{Config}->{To}->{root}; + ##-- Set up path substitution variables for use inside the copy loop. + # For each file in the file list: + # Substitute any variable parts of the path name. + # Handle wildcards + # Copy + + local $i = 0; + my $bOldDot = 1; + my $bDot = 0; + while ($files[0]->{File}[$i]) { + + my ($name, $newname, $from, $to, $file); + $file = $files[0]->{File}->[$i]; + $name = $file->{name}; + if (exists $file->{newname}) {$newname = $file->{newname};} + else {$newname = $name;} + if ($name && (! exists $file->{ignore})) { ## Ignore or process this entry? + $from = "$fromRoot\\$file->{from}\\$name"; + $to = "$toRoot\\$file->{to}\\$newname"; + # Copy this file? Check for ignore tag [debug-only in release mode or vice versa]. + if ( $bPathTags || $bFileStem || (index($from.$to, $IgnoreTag) <0) ) { + if ($bPathTags) { ## Apply PathTag substitutions: + $from =~ s/$AlwaysTag/$PathFragment/g; + $to =~ s/$AlwaysTag/$PathFragment/g; + $from =~ s/$BuildDependentTag/$PathFragment/g; + $to =~ s/$BuildDependentTag/$PathFragment/g; + } + if ($bFileStem) { ## FileStem substitution? + $from =~ s/%filestem%/$FileStemFragment/g; + $to =~ s/%filestem%/$FileStemFragment/g; + } + # %-DEBUG% substitution: + local $DebugFragment = ($odr->{debug}->{def}) ? "-DEBUG" : ""; + $from =~ s/%\-DEBUG%/$DebugFragment/g; + $to =~ s/%\-DEBUG%/$DebugFragment/g; + $to =~ s/\*.*//; ## Truncate to path before any wildcard + + my $bCopyOK = 1; + my $fromcheck = $from; + my $bRequired = ! (exists $file->{notrequired}); + if ($name =~ /\*/) { ## Wildcard case + $fromcheck =~ s/\*.*//; + if ($bRequired && (! -d $fromcheck)) { + if ($bDot) {print "\n";} + die "Fatal -- Can't find $fromcheck"; + } + $bCopyOK = !system("echo D | xcopy /D /F /Y /S $from $to > a.tmp 2>NUL"); + } + else { ## Specific file case + if ($bRequired && (! -e $fromcheck)) { + if ($bDot) {print "\n";} + die "Fatal -- Can't find $fromcheck"; + } + $bCopyOK = !system("echo F | xcopy /D /F /Y $from $to > a.tmp 2>NUL"); + } + + if ($bCopyOK) { ## xcopy OK - show progress + # To show progress when files aren't copied, print a string of dots. + open(MYINPUTFILE, "; + foreach $line (@lines) { + $bDot = ($line =~ /^0/); + } + close(MYINPUTFILE); + if (!$bDot && $bOldDot) {print "\n";} + if ($bDot) {print "."; STDOUT->flush;} + else {print "$from copied to $to\n";} + $bOldDot = $bDot; + } + else { ## xcopy failed + if (!exists $file->{notrequired}) { + if ($bDot) {print "\n";} + die "Fatal -- Copy of $from to $to failed"; + } + } ## End xcopy succeed or fail + } ## End not dummy entry nor ignored + } + $i++; + } + if ($bDot) {print "\n";} + } + +return 1; diff --git a/krb5-1-6/src/windows/build/copyfiles.xml b/krb5-1-6/src/windows/build/copyfiles.xml new file mode 100644 index 000000000..11809ca74 --- /dev/null +++ b/krb5-1-6/src/windows/build/copyfiles.xml @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/corebinaryfiles.xml b/krb5-1-6/src/windows/build/corebinaryfiles.xml new file mode 100644 index 000000000..9fcf8aa3a --- /dev/null +++ b/krb5-1-6/src/windows/build/corebinaryfiles.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/css/main-action(1).css b/krb5-1-6/src/windows/build/css/main-action(1).css new file mode 100644 index 000000000..2a1cfc0d9 --- /dev/null +++ b/krb5-1-6/src/windows/build/css/main-action(1).css @@ -0,0 +1,54 @@ +.sidebar { + BACKGROUND-COLOR: #f0f0f0 +} +#logodiv { + PADDING-RIGHT: 15px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; TEXT-ALIGN: center +} +#menu { + WIDTH: 150px +} +.leftnav H1 { + PADDING-RIGHT: 4px; BORDER-TOP: white 1px solid; PADDING-LEFT: 4px; FONT-WEIGHT: bold; FONT-SIZE: 11px; PADDING-BOTTOM: 4px; MARGIN: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #ccc 1px solid +} +.leftnav H5 { + PADDING-RIGHT: 0px; BORDER-TOP: white 1px solid; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 11px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: #ccc 1px solid +} +.leftnav H5 A { + BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 5px; DISPLAY: block; PADDING-LEFT: 5px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none +} +.leftnav H5 A:hover { + BORDER-TOP-WIDTH: 0px; DISPLAY: block; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BACKGROUND-COLOR: white; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none +} +.leftnav UL { + PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none +} +.leftnav LI { + PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px +} +.leftnav LI A { + PADDING-RIGHT: 2px; DISPLAY: block; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 0px; COLOR: white; PADDING-TOP: 2px; TEXT-DECORATION: none +} +.leftnav LI A.current { + COLOR: white; BACKGROUND-COLOR: #003366 +} +.leftnav LI A:active { + COLOR: white +} +.leftnav LI A:visited { + COLOR: white +} +.leftnav LI A:hover { + COLOR: white; BACKGROUND-COLOR: #003366 +} +.leftnav LI.current { + BACKGROUND-COLOR: #487bb7 +} +.leftnav LI.current A { + COLOR: #3c78b5 +} +#PageContent { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BACKGROUND-COLOR: #fff; TEXT-ALIGN: left +} +H1 { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 22px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 27px 0px 4px; COLOR: #660000; PADDING-TOP: 0px; FONT-FAMILY: Arial, sans-serif; BACKGROUND-COLOR: #fff +} diff --git a/krb5-1-6/src/windows/build/css/main-action.css b/krb5-1-6/src/windows/build/css/main-action.css new file mode 100644 index 000000000..e08c50ecd --- /dev/null +++ b/krb5-1-6/src/windows/build/css/main-action.css @@ -0,0 +1,1032 @@ +BODY { + FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +P { + FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +TD { + FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +TABLE { + FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +TR { + FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +.bodytext { + FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +.stepfield { + FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #000000; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +#PageContent { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 20px; MARGIN: 0px; PADDING-TOP: 0px; BACKGROUND-COLOR: #fff; TEXT-ALIGN: left +} +BODY { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; BACKGROUND-COLOR: #ffffff; TEXT-ALIGN: center +} +.monospaceInput { + FONT: 12px monospace +} +.wiki-content P { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 16px 0px; PADDING-TOP: 0px +} +.commentblock P { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 16px 0px; PADDING-TOP: 0px +} +.wiki-content-preview { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 5px +} +UL { + MARGIN-TOP: 2px; MARGIN-BOTTOM: 2px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px +} +OL { + MARGIN-TOP: 2px; MARGIN-BOTTOM: 2px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px +} +PRE { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 5px 5px 5px 15px; PADDING-TOP: 0px; TEXT-ALIGN: left +} +.helpheading { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; PADDING-BOTTOM: 4px; MARGIN: 10px 0px 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #d0d9bd +} +.helpcontent { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 20px; PADDING-TOP: 4px; BACKGROUND-COLOR: #f5f7f1 +} +.code { + BORDER-RIGHT: #3c78b5 1px dashed; BORDER-TOP: #3c78b5 1px dashed; FONT-SIZE: 11px; MARGIN: 10px; BORDER-LEFT: #3c78b5 1px dashed; LINE-HEIGHT: 13px; BORDER-BOTTOM: #3c78b5 1px dashed; FONT-FAMILY: Courier +} +.focusedComment { + BACKGROUND: #ffffce +} +.commentBox { + BORDER-RIGHT: #bbb 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #bbb 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 5px 0px; BORDER-LEFT: #bbb 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #bbb 1px solid +} +.focusedComment { + BORDER-RIGHT: #bbb 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #bbb 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 5px 0px; BORDER-LEFT: #bbb 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #bbb 1px solid +} +.codeHeader { + PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px dashed; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center +} +.codeContent { + PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: left +} +.preformatted { + BORDER-RIGHT: #3c78b5 1px dashed; BORDER-TOP: #3c78b5 1px dashed; FONT-SIZE: 11px; MARGIN: 10px; BORDER-LEFT: #3c78b5 1px dashed; LINE-HEIGHT: 13px; BORDER-BOTTOM: #3c78b5 1px dashed; FONT-FAMILY: Courier +} +.preformattedHeader { + PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px dashed; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center +} +.preformattedContent { + PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BACKGROUND-COLOR: #eeefcc +} +.panel { + BORDER-RIGHT: #3c78b5 1px dashed; BORDER-TOP: #3c78b5 1px dashed; MARGIN: 0px 10px 10px; BORDER-LEFT: #3c78b5 1px dashed; BORDER-BOTTOM: #3c78b5 1px dashed +} +.panelHeader { + PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px dashed; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center +} +.panelContent { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BACKGROUND-COLOR: #eeefcc +} +.anonymousAlert { + BORDER-RIGHT: red 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: red 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 11px; PADDING-BOTTOM: 10px; MARGIN: 4px; BORDER-LEFT: red 1px dashed; LINE-HEIGHT: 13px; PADDING-TOP: 10px; BORDER-BOTTOM: red 1px dashed; BACKGROUND-COLOR: #eeefcc +} +.lockAlert { + BORDER-RIGHT: red 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: red 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 11px; PADDING-BOTTOM: 10px; MARGIN: 4px; BORDER-LEFT: red 1px dashed; WIDTH: 50%; LINE-HEIGHT: 13px; PADDING-TOP: 10px; BORDER-BOTTOM: red 1px dashed; BACKGROUND-COLOR: #eeefcc +} +.code-keyword { + COLOR: #000091 +} +.code-object { + COLOR: #910091 +} +.code-quote { + COLOR: #009100 +} +.code-comment { + COLOR: #808080 +} +.code-xml .code-keyword { + FONT-WEIGHT: bold +} +.code-tag { + COLOR: #000091 +} +.breadcrumbs { + BORDER-RIGHT: #3c78b5 0px solid; PADDING-RIGHT: 0px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 11px; PADDING-BOTTOM: 3px; BORDER-LEFT: #3c78b5 0px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc +} +.navmenu { + BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid; BORDER-BOTTOM: #ccc 1px solid +} +.menuheading { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; PADDING-BOTTOM: 2px; PADDING-TOP: 4px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc +} +.menuitems { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 20px; PADDING-TOP: 4px +} +.rightpanel { + BORDER-LEFT: #ccc 1px solid; BORDER-BOTTOM: #ccc 1px solid +} +#helpheading { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; PADDING-BOTTOM: 4px; MARGIN: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #d0d9bd; TEXT-ALIGN: left +} +#helpcontent { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px; BACKGROUND-COLOR: #f5f7f1 +} +.helptab-unselected { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BACKGROUND-COLOR: #f5f7f1 +} +.helptab-selected { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BACKGROUND-COLOR: #d0d9bd +} +.helptabs { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; PADDING-TOP: 5px; BACKGROUND-COLOR: #f5f7f1 +} +.infopanel-heading { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; PADDING-BOTTOM: 2px; PADDING-TOP: 4px +} +.pagebody { + +} +.pageheader { + PADDING-RIGHT: 5px; PADDING-LEFT: 0px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 1px solid +} +.pagetitle { + FONT-WEIGHT: bold; FONT-SIZE: 22px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif +} +.newpagetitle { + COLOR: #ccc! important +} +.steptitle { + FONT-WEIGHT: bold; FONT-SIZE: 18px; MARGIN-BOTTOM: 7px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif +} +.substeptitle { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; FONT-SIZE: 12px; PADDING-BOTTOM: 1px; MARGIN: 2px 4px 4px; COLOR: #003366; PADDING-TOP: 2px; FONT-FAMILY: Arial, sans-serif +} +.stepdesc { + MARGIN-TOP: 7px; FONT-WEIGHT: normal; FONT-SIZE: 11px; MARGIN-BOTTOM: 7px; COLOR: #666666; LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, arial, sans-serif +} +.steplabel { + FONT-WEIGHT: bold; FLOAT: left; WIDTH: 15%; COLOR: black; MARGIN-RIGHT: 4px; TEXT-ALIGN: right +} +.stepfield { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 5px; PADDING-TOP: 5px +} +.submitButtons { + MARGIN-TOP: 5px; TEXT-ALIGN: right +} +.formtitle { + FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif +} +.sectionbottom { + BORDER-BOTTOM: #3c78b5 1px solid +} +.topRow { + BORDER-TOP: #3c78b5 2px solid +} +.tabletitle { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 14px; PADDING-BOTTOM: 2px; MARGIN: 8px 4px 2px 0px; COLOR: #003366; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 2px solid; FONT-FAMILY: Arial, sans-serif +} +.pagesubheading { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 10px; PADDING-BOTTOM: 5px; COLOR: #666666; PADDING-TOP: 0px +} +HR { + +} +A:link { + COLOR: #003366 +} +A:visited { + COLOR: #003366 +} +A:active { + COLOR: #003366 +} +A:hover { + COLOR: #003366 +} +H1 A:link { + TEXT-DECORATION: none +} +H1 A:visited { + TEXT-DECORATION: none +} +H1 A:active { + TEXT-DECORATION: none +} +H1 A:hover { + BORDER-BOTTOM: #003366 1px dotted +} +UNKNOWN { + MARGIN-TOP: 3px +} +.logocell { + PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px +} +INPUT { + FONT-SIZE: 11px; COLOR: #000000; FONT-FAMILY: verdana, geneva, arial, sans-serif +} +TEXTAREA { + FONT-SIZE: 11px; COLOR: #333333; FONT-FAMILY: verdana, geneva, arial, sans-serif +} +TEXTAREA.editor { + FONT-SIZE: 11px; COLOR: #333333; FONT-FAMILY: verdana, geneva, arial, sans-serif +} +.spacenametitle-printable { + MARGIN: 0px; FONT: 100 20px/25px Impact, Arial, Helvetica; COLOR: #999999 +} +.spacenametitle-printable A { + COLOR: #999999; TEXT-DECORATION: none +} +.spacenametitle-printable A:visited { + COLOR: #999999; TEXT-DECORATION: none +} +.blogDate { + FONT-WEIGHT: bold; COLOR: black; TEXT-DECORATION: none +} +.blogSurtitle { + BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid +} +.blogHeading { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: 20px; PADDING-BOTTOM: 0px; MARGIN: 0px; LINE-HEIGHT: normal; PADDING-TOP: 0px +} +.blogHeading A { + COLOR: black; TEXT-DECORATION: none +} +.endsection { + MARGIN-TOP: 10px; COLOR: #666666; align: right +} +.endsectionleftnav { + MARGIN-TOP: 10px; COLOR: #666666; align: right +} +H1 { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 24px; PADDING-BOTTOM: 2px; MARGIN: 36px 0px 4px; COLOR: #003366; LINE-HEIGHT: normal; PADDING-TOP: 2px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc +} +H2 { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 18px; PADDING-BOTTOM: 2px; MARGIN: 27px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc +} +H3 { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 14px; PADDING-BOTTOM: 2px; MARGIN: 21px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc +} +H4 { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 12px; PADDING-BOTTOM: 2px; MARGIN: 18px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc +} +H4.search { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: normal; FONT-SIZE: 12px; PADDING-BOTTOM: 4px; MARGIN: 18px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 4px; BACKGROUND-COLOR: #eeefcc +} +H5 { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 10px; PADDING-BOTTOM: 2px; MARGIN: 14px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc +} +H6 { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: 8px; PADDING-BOTTOM: 2px; MARGIN: 14px 0px 4px; LINE-HEIGHT: normal; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc +} +.smallfont { + FONT-SIZE: 10px +} +.descfont { + FONT-SIZE: 10px; COLOR: #666666 +} +.smallerfont { + FONT-SIZE: 9px +} +.smalltext { + FONT-SIZE: 10px; COLOR: #666666 +} +.smalltext A { + COLOR: #666666 +} +.smalltext-blue { + FONT-SIZE: 10px; COLOR: #3c78b5 +} +.surtitle { + FONT-SIZE: 14px; MARGIN-BOTTOM: 5px; MARGIN-LEFT: 1px; COLOR: #666666 +} +.navItemOver { + FONT-WEIGHT: bold; FONT-SIZE: 10px; CURSOR: pointer; COLOR: #ffffff; BACKGROUND-COLOR: #003366; voice-family: inherit +} +.navItemOver A { + COLOR: #ffffff; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none +} +.navItemOver A:visited { + COLOR: #ffffff; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none +} +.navItemOver A:hover { + COLOR: #ffffff; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none +} +.navItem { + FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #ffffff; BACKGROUND-COLOR: #3c78b5 +} +.navItem A { + COLOR: #ffffff; TEXT-DECORATION: none +} +.navItem A:hover { + COLOR: #ffffff; TEXT-DECORATION: none +} +.navItem A:visited { + COLOR: #ffffff; TEXT-DECORATION: none +} +DIV.padded { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px +} +DIV.thickPadded { + PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px +} +H3.macrolibrariestitle { + MARGIN: 0px +} +DIV.centered { + MARGIN: 10px; TEXT-ALIGN: center +} +DIV.centered TABLE { + MARGIN: 0px auto; TEXT-ALIGN: left +} +.tableview TABLE { + MARGIN: 0px +} +.tableview TH { + PADDING-RIGHT: 0px; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 0px; COLOR: #003366; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 2px solid; TEXT-ALIGN: left +} +.tableview TD { + BORDER-RIGHT: #ccc 0px solid; PADDING-RIGHT: 10px; BORDER-TOP: #ccc 0px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 4px; MARGIN: 0px; BORDER-LEFT: #ccc 0px solid; PADDING-TOP: 4px; BORDER-BOTTOM: #ccc 1px solid; TEXT-ALIGN: left +} +.grid { + MARGIN: 2px 0px 5px; BORDER-COLLAPSE: collapse +} +.grid TH { + BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 2px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #ccc 1px solid; TEXT-ALIGN: center +} +.grid TD { + BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid +} +.gridHover { + BACKGROUND-COLOR: #f9f9f9 +} +TD.infocell { + BACKGROUND-COLOR: #eeefcc +} +.label { + FONT-WEIGHT: bold; COLOR: #003366 +} +LABEL { + FONT-WEIGHT: bold; COLOR: #003366 +} +.error { + BACKGROUND-COLOR: #fcc +} +.errorBox { + BORDER-RIGHT: #c00 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #c00 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 5px; BORDER-LEFT: #c00 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #c00 1px solid; BACKGROUND-COLOR: #fcc +} +.errorMessage { + COLOR: #c00 +} +.success { + BACKGROUND-COLOR: #dfd +} +.successBox { + BORDER-RIGHT: #090 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #090 1px solid; MARGIN-TOP: 5px; PADDING-LEFT: 5px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #090 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #090 1px solid; BACKGROUND-COLOR: #dfd +} +BLOCKQUOTE { + PADDING-RIGHT: 10px; PADDING-LEFT: 10px; MARGIN-LEFT: 5px; BORDER-LEFT: #3c78b5 1px solid; MARGIN-RIGHT: 0px +} +TABLE.confluenceTable { + MARGIN: 5px; BORDER-COLLAPSE: collapse +} +TABLE.confluenceTable TD.confluenceTd { + BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid +} +TABLE.confluenceTable TH.confluenceTh { + BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center +} +TD.confluenceTd { + BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid +} +TH.confluenceTh { + BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 3px; BORDER-LEFT: #ccc 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ccc 1px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center +} +DIV.small { + FONT-SIZE: 9px +} +H1.pagename { + MARGIN-TOP: 0px +} +IMG.inline { + +} +.loginform { + BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; MARGIN: 5px; BORDER-LEFT: #ccc 1px solid; BORDER-BOTTOM: #ccc 1px solid +} +.previewnote { + FONT-SIZE: 11px; COLOR: red; TEXT-ALIGN: center +} +.previewcontent { + BACKGROUND: #e0e0e0 +} +.messagecontent { + BACKGROUND: #e0e0e0 +} +.conflictnote { + +} +.createlink { + COLOR: maroon +} +A.createlink { + COLOR: maroon +} +.templateparameter { + FONT-SIZE: 9px; COLOR: darkblue +} +.diffadded { + PADDING-RIGHT: 1px; PADDING-LEFT: 4px; BACKGROUND: #ddffdd; PADDING-BOTTOM: 1px; BORDER-LEFT: darkgreen 4px solid; PADDING-TOP: 1px +} +.diffdeleted { + PADDING-RIGHT: 1px; PADDING-LEFT: 4px; BACKGROUND: #ffdddd; PADDING-BOTTOM: 1px; BORDER-LEFT: darkred 4px solid; COLOR: #999; PADDING-TOP: 1px +} +.diffnochange { + PADDING-RIGHT: 1px; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: lightgrey 4px solid; PADDING-TOP: 1px +} +.differror { + BACKGROUND: brown +} +.diff { + FONT-SIZE: 12px; LINE-HEIGHT: 14px; FONT-FAMILY: lucida console, courier new, fixed-width +} +.diffaddedchars { + FONT-WEIGHT: bolder; BACKGROUND-COLOR: #99ff99 +} +.diffremovedchars { + FONT-WEIGHT: bolder; BACKGROUND-COLOR: #ff9999; TEXT-DECORATION: line-through +} +.greybackground { + BACKGROUND: #eeefcc +} +.greybox { + BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid +} +.borderedGreyBox { + BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeefcc +} +.greyboxfilled { + BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid +} +.navBackgroundBox { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; FONT-SIZE: 22px; BACKGROUND: #3c78b5; PADDING-BOTTOM: 5px; COLOR: white; PADDING-TOP: 5px; FONT-FAMILY: Arial, sans-serif; TEXT-DECORATION: none +} +.previewBoxTop { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 5px 0px 0px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 0px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center +} +.previewContent { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #3c78b5 0px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 0px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #3c78b5 0px solid; BACKGROUND-COLOR: #fff +} +.previewBoxBottom { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #3c78b5 0px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px 0px 5px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc; TEXT-ALIGN: center +} +.functionbox { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #eeefcc +} +.functionbox-greyborder { + BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 1px 1px 10px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #ddd 1px solid; BACKGROUND-COLOR: #eeefcc +} +.search-highlight { + BACKGROUND-COLOR: #ffffcc +} +.rowNormal { + BACKGROUND-COLOR: #ffffff +} +.rowAlternate { + BACKGROUND-COLOR: #f7f7f7 +} +.rowAlternateNoBottomColor { + BACKGROUND-COLOR: #f7f7f7 +} +.rowAlternateNoBottomNoColor { + +} +.rowAlternateNoBottomColor TD { + BORDER-BOTTOM-WIDTH: 0px +} +.rowAlternateNoBottomNoColor TD { + BORDER-BOTTOM-WIDTH: 0px +} +.rowHighlight { + BACKGROUND-COLOR: #eeefcc +} +TD.greenbar { + BORDER-RIGHT: #9c9c9c 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #9c9c9c 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #00df00; PADDING-BOTTOM: 0px; BORDER-LEFT: #9c9c9c 1px solid; PADDING-TOP: 0px; BORDER-BOTTOM: #9c9c9c 1px solid +} +TD.redbar { + BORDER-RIGHT: #9c9c9c 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #9c9c9c 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #df0000; PADDING-BOTTOM: 0px; BORDER-LEFT: #9c9c9c 1px solid; PADDING-TOP: 0px; BORDER-BOTTOM: #9c9c9c 1px solid +} +TD.darkredbar { + BORDER-RIGHT: #9c9c9c 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #9c9c9c 1px solid; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #af0000; PADDING-BOTTOM: 0px; BORDER-LEFT: #9c9c9c 1px solid; PADDING-TOP: 0px; BORDER-BOTTOM: #9c9c9c 1px solid +} +TR.testpassed { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #ddffdd; PADDING-BOTTOM: 0px; PADDING-TOP: 0px +} +TR.testfailed { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 2px; BACKGROUND: #ffdddd; PADDING-BOTTOM: 0px; PADDING-TOP: 0px +} +.toolbar { + MARGIN: 0px; BORDER-COLLAPSE: collapse +} +.toolbar TD { + BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #ccc 1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; BORDER-LEFT: #ccc 1px solid; COLOR: #ccc; PADDING-TOP: 2px; BORDER-BOTTOM: #ccc 1px solid +} +TD.noformatting { + BORDER-RIGHT: 0px; PADDING-RIGHT: 0px; BORDER-TOP: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: 0px; TEXT-ALIGN: center +} +.commentblock { + MARGIN: 12px 0px +} +.license-eval { + BORDER-TOP: #bbbbbb 1px solid; FONT-SIZE: 10px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; TEXT-ALIGN: center +} +.license-none { + BORDER-TOP: #bbbbbb 1px solid; FONT-SIZE: 10px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; TEXT-ALIGN: center +} +.license-nonprofit { + BORDER-TOP: #bbbbbb 1px solid; FONT-SIZE: 10px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; TEXT-ALIGN: center +} +.license-eval { + BACKGROUND-COLOR: #ffcccc +} +.license-none { + BACKGROUND-COLOR: #ffcccc +} +.license-eval B { + COLOR: #990000 +} +.license-none B { + COLOR: #990000 +} +.license-nonprofit { + BACKGROUND-COLOR: #ffffff +} +.bottomshadow { + BACKGROUND-IMAGE: url(/confluence/images/border/border_bottom.gif); BACKGROUND-REPEAT: repeat-x; HEIGHT: 12px +} +.navmenu .operations LI { + PADDING-LEFT: 0px; MARGIN-LEFT: 0px; LIST-STYLE-TYPE: none +} +.navmenu .operations UL { + PADDING-LEFT: 0px; MARGIN-LEFT: 0px; LIST-STYLE-TYPE: none +} +.navmenu .operations UL { + MARGIN-BOTTOM: 9px +} +.navmenu .label { + +} +.toolbar DIV { + DISPLAY: none +} +.toolbar .label { + DISPLAY: none +} +.toolbar .operations { + DISPLAY: block +} +.toolbar .operations UL { + DISPLAY: inline; PADDING-LEFT: 0px; MARGIN-LEFT: 10px; LIST-STYLE-TYPE: none +} +.toolbar .operations LI { + DISPLAY: inline; LIST-STYLE-TYPE: none +} +#foldertab { + PADDING-RIGHT: 0px; PADDING-LEFT: 8px; PADDING-BOTTOM: 3px; FONT: bold 11px Verdana, sans-serif; MARGIN-LEFT: 0px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid +} +#foldertab LI { + DISPLAY: inline; MARGIN: 0px; LIST-STYLE-TYPE: none +} +#foldertab LI A { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 0.5em; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 0.5em; BACKGROUND: #3c78b5; PADDING-BOTTOM: 3px; MARGIN-LEFT: 3px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px; TEXT-DECORATION: none +} +#foldertab LI A:link { + COLOR: #ffffff +} +#foldertab LI A:visited { + COLOR: #ffffff +} +#foldertab LI A:hover { + BORDER-LEFT-COLOR: #003366; BACKGROUND: #003366; BORDER-BOTTOM-COLOR: #003366; COLOR: #ffffff; BORDER-TOP-COLOR: #003366; BORDER-RIGHT-COLOR: #003366 +} +#foldertab LI A.current { + BACKGROUND: white; COLOR: black; BORDER-BOTTOM: white 1px solid +} +#foldertab LI A.current:link { + COLOR: black +} +#foldertab LI A.current:visited { + COLOR: black +} +#foldertab LI A.current:hover { + BACKGROUND: white; COLOR: black; BORDER-BOTTOM: white 1px solid +} +UL#squaretab { + PADDING-LEFT: 0px; FONT: bold 8px Verdana, sans-serif; MARGIN-LEFT: 0px; WHITE-SPACE: nowrap +} +#squaretab LI { + DISPLAY: inline; LIST-STYLE-TYPE: none +} +#squaretab A { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 6px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 6px; PADDING-BOTTOM: 2px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #3c78b5 1px solid +} +#squaretab A:link { + COLOR: #fff; BACKGROUND-COLOR: #3c78b5; TEXT-DECORATION: none +} +#squaretab A:visited { + COLOR: #fff; BACKGROUND-COLOR: #3c78b5; TEXT-DECORATION: none +} +#squaretab A:hover { + BORDER-LEFT-COLOR: #003366; BORDER-BOTTOM-COLOR: #003366; COLOR: #ffffff; BORDER-TOP-COLOR: #003366; BACKGROUND-COLOR: #003366; TEXT-DECORATION: none; BORDER-RIGHT-COLOR: #003366 +} +#squaretab LI A#current { + BACKGROUND: white; COLOR: black +} +.blogcalendar { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; LINE-HEIGHT: 140%; PADDING-TOP: 2px; FONT-FAMILY: verdana, arial, sans-serif +} +TABLE.blogcalendar { + BORDER-RIGHT: #3c78b5 1px solid; BORDER-TOP: #3c78b5 1px solid; BORDER-LEFT: #3c78b5 1px solid; BORDER-BOTTOM: #3c78b5 1px solid +} +.blogcalendar TH.calendarhead { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; COLOR: #ffffff; PADDING-TOP: 2px; LETTER-SPACING: 0.3em; BACKGROUND-COLOR: #3c78b5 +} +A.calendarhead { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; COLOR: #ffffff; PADDING-TOP: 2px; LETTER-SPACING: 0.3em; BACKGROUND-COLOR: #3c78b5 +} +.calendarhead:visited { + COLOR: white +} +.calendarhead:active { + COLOR: white +} +.calendarhead:hover { + COLOR: white +} +.blogcalendar TH { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: x-small; PADDING-BOTTOM: 2px; PADDING-TOP: 2px; BACKGROUND-COLOR: #eeefcc +} +.blogcalendar TD { + FONT-WEIGHT: normal; FONT-SIZE: x-small +} +.searchGroup { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 10px; PADDING-TOP: 0px +} +.searchGroupHeading { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; FONT-SIZE: 10px; PADDING-BOTTOM: 1px; COLOR: #ffffff; PADDING-TOP: 2px; BACKGROUND-COLOR: #3c78b5 +} +.searchItem { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; PADDING-TOP: 1px +} +.searchItemSelected { + PADDING-RIGHT: 4px; PADDING-LEFT: 4px; FONT-WEIGHT: bold; BACKGROUND: #ddd; PADDING-BOTTOM: 1px; PADDING-TOP: 1px +} +.permissionHeading { + BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; FONT-SIZE: 16px; BORDER-LEFT: 0px solid; BORDER-BOTTOM: #bbb 1px solid; TEXT-ALIGN: left +} +.permissionTab { + BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; FONT-SIZE: 10px; BACKGROUND: #3c78b5; BORDER-LEFT: 1px solid; COLOR: #ffffff; BORDER-BOTTOM: 0px solid +} +.permissionSuperTab { + BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; BACKGROUND: #003366; BORDER-LEFT: 1px solid; COLOR: #ffffff; BORDER-BOTTOM: 0px solid +} +.permissionCell { + BORDER-RIGHT: 0px solid; BORDER-TOP: 0px solid; BORDER-LEFT: #bbb 1px solid; BORDER-BOTTOM: 0px solid +} +.warningPanel { + BORDER-RIGHT: #f0c000 1px solid; PADDING-RIGHT: 8px; BORDER-TOP: #f0c000 1px solid; PADDING-LEFT: 8px; BACKGROUND: #ffffce; PADDING-BOTTOM: 8px; MARGIN: 10px; BORDER-LEFT: #f0c000 1px solid; PADDING-TOP: 8px; BORDER-BOTTOM: #f0c000 1px solid +} +.alertPanel { + BORDER-RIGHT: #c00 1px solid; PADDING-RIGHT: 8px; BORDER-TOP: #c00 1px solid; PADDING-LEFT: 8px; BACKGROUND: #ffcccc; PADDING-BOTTOM: 8px; MARGIN: 10px; BORDER-LEFT: #c00 1px solid; PADDING-TOP: 8px; BORDER-BOTTOM: #c00 1px solid +} +.infoPanel { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 8px; BORDER-TOP: #3c78b5 1px solid; PADDING-LEFT: 8px; BACKGROUND: #d8e4f1; PADDING-BOTTOM: 8px; MARGIN: 10px; BORDER-LEFT: #3c78b5 1px solid; PADDING-TOP: 8px; BORDER-BOTTOM: #3c78b5 1px solid +} +.optionPadded { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; PADDING-TOP: 2px +} +.optionSelected { + BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; MARGIN: -1px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #ddd 1px solid; BACKGROUND-COLOR: #ffffcc +} +.optionSelected A { + FONT-WEIGHT: bold; COLOR: black; TEXT-DECORATION: none +} +.noteMacro { + BORDER-RIGHT: #f0c000 1px solid; BORDER-TOP: #f0c000 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #f0c000 1px solid; BORDER-BOTTOM: #f0c000 1px solid; BACKGROUND-COLOR: #ffffce; TEXT-ALIGN: left +} +.warningMacro { + BORDER-RIGHT: #c00 1px solid; BORDER-TOP: #c00 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #c00 1px solid; BORDER-BOTTOM: #c00 1px solid; BACKGROUND-COLOR: #fcc; TEXT-ALIGN: left +} +.infoMacro { + BORDER-RIGHT: #3c78b5 1px solid; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #3c78b5 1px solid; BORDER-BOTTOM: #3c78b5 1px solid; BACKGROUND-COLOR: #d8e4f1; TEXT-ALIGN: left +} +.tipMacro { + BORDER-RIGHT: #090 1px solid; BORDER-TOP: #090 1px solid; MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; BORDER-LEFT: #090 1px solid; BORDER-BOTTOM: #090 1px solid; BACKGROUND-COLOR: #dfd; TEXT-ALIGN: left +} +.informationMacroPadding { + PADDING-RIGHT: 0px; PADDING-LEFT: 5px; PADDING-BOTTOM: 0px; PADDING-TOP: 5px +} +TABLE.infoMacro TD { + BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none +} +TABLE.warningMacro TD { + BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none +} +TABLE.tipMacro TD { + BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none +} +TABLE.noteMacro TD { + BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none +} +TABLE.sectionMacro TD { + BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none +} +TABLE.sectionMacroWithBorder TD.columnMacro { + BORDER-RIGHT: #cccccc 1px dashed; BORDER-TOP: #cccccc 1px dashed; BORDER-LEFT: #cccccc 1px dashed; BORDER-BOTTOM: #cccccc 1px dashed +} +.pagecontent { + PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; TEXT-ALIGN: left +} +.topBarDiv A:link { + COLOR: #ffffff +} +.topBarDiv A:visited { + COLOR: #ffffff +} +.topBarDiv A:active { + COLOR: #ffffff +} +.topBarDiv A:hover { + COLOR: #ffffff +} +.topBarDiv { + COLOR: #ffffff +} +.topBar { + BACKGROUND-COLOR: #003366 +} +.greyLinks A:link { + COLOR: #666666; TEXT-DECORATION: underline +} +.greyLinks A:visited { + COLOR: #666666; TEXT-DECORATION: underline +} +.greyLinks A:active { + COLOR: #666666; TEXT-DECORATION: underline +} +.greyLinks A:hover { + COLOR: #666666; TEXT-DECORATION: underline +} +.greyLinks { + PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; COLOR: #666666; PADDING-TOP: 10px +} +.logoSpaceLink { + COLOR: #999999; TEXT-DECORATION: none +} +.logoSpaceLink A:link { + COLOR: #999999; TEXT-DECORATION: none +} +.logoSpaceLink A:visited { + COLOR: #999999; TEXT-DECORATION: none +} +.logoSpaceLink A:active { + COLOR: #999999; TEXT-DECORATION: none +} +.logoSpaceLink A:hover { + COLOR: #003366; TEXT-DECORATION: none +} +.basicPanelContainer { + BORDER-RIGHT: #3c78b5 1px solid; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 2px; MARGIN-BOTTOM: 8px; BORDER-LEFT: #3c78b5 1px solid; WIDTH: 100%; BORDER-BOTTOM: #3c78b5 1px solid +} +.basicPanelTitle { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; PADDING-BOTTOM: 5px; MARGIN: 0px; COLOR: black; PADDING-TOP: 5px; BACKGROUND-COLOR: #eeefcc +} +.basicPanelBody { + PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; PADDING-TOP: 5px +} +.separatorLinks A:link { + COLOR: white +} +.separatorLinks A:visited { + COLOR: white +} +.separatorLinks A:active { + COLOR: white +} +.greynavbar { + BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 2px; BACKGROUND-COLOR: #eeefcc +} +DIV.headerField { + FLOAT: left; WIDTH: auto; HEIGHT: 100% +} +.headerFloat { + MARGIN-LEFT: auto; WIDTH: 50% +} +.headerFloatLeft { + FLOAT: left; MARGIN-BOTTOM: 10px; MARGIN-RIGHT: 20px +} +#headerRow { + PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; PADDING-TOP: 10px +} +DIV.license-personal { + COLOR: #ffffff; BACKGROUND-COLOR: #003366 +} +DIV.license-personal A { + COLOR: #ffffff +} +.greyFormBox { + BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid +} +.marginlessForm { + MARGIN: 0px +} +.openPageHighlight { + BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #ddd 1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: #ddd 1px solid; BACKGROUND-COLOR: #ffffcc +} +.editPageInsertLinks { + FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #666666 +} +.editPageInsertLinks A { + FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #666666 +} +.top10 A { + FONT-WEIGHT: bold; FONT-SIZE: 2em; COLOR: #003366 +} +.top25 A { + FONT-WEIGHT: bold; FONT-SIZE: 1.6em; COLOR: #003366 +} +.top50 A { + FONT-SIZE: 1.4em; COLOR: #003366 +} +.top100 A { + FONT-SIZE: 1.2em; COLOR: #003366 +} +.heatmap { + MARGIN: 0px auto; WIDTH: 95%; LIST-STYLE-TYPE: none +} +.heatmap A { + TEXT-DECORATION: none +} +.heatmap A:hover { + TEXT-DECORATION: underline +} +.heatmap LI { + DISPLAY: inline +} +.minitab { + PADDING-RIGHT: 0px; MARGIN-TOP: 1px; PADDING-LEFT: 8px; FLOAT: none; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 3px; FONT: bold 9px Verdana, sans-serif; MARGIN-LEFT: 0px; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px solid; TEXT-DECORATION: none +} +.selectedminitab { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 0.5em; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 1px; PADDING-LEFT: 0.5em; BACKGROUND: white; PADDING-BOTTOM: 3px; MARGIN-LEFT: 3px; BORDER-LEFT: #3c78b5 1px solid; COLOR: #000000; PADDING-TOP: 3px; BORDER-BOTTOM: white 1px solid; TEXT-DECORATION: none +} +.unselectedminitab { + BORDER-RIGHT: #3c78b5 1px solid; PADDING-RIGHT: 0.5em; BORDER-TOP: #3c78b5 1px solid; MARGIN-TOP: 1px; PADDING-LEFT: 0.5em; BACKGROUND: #3c78b5; PADDING-BOTTOM: 3px; MARGIN-LEFT: 3px; BORDER-LEFT: #3c78b5 1px solid; COLOR: #ffffff; PADDING-TOP: 3px; BORDER-BOTTOM: #3c78b5 1px; TEXT-DECORATION: none +} +A.unselectedminitab:hover { + BORDER-LEFT-COLOR: #003366; BACKGROUND: #003366; BORDER-BOTTOM-COLOR: #003366; COLOR: #ffffff; BORDER-TOP-COLOR: #003366; BORDER-RIGHT-COLOR: #003366 +} +A.unselectedminitab:link { + COLOR: white +} +A.unselectedminitab:visited { + COLOR: white +} +A.selectedminitab:link { + COLOR: black +} +A.selectedminitab:visited { + COLOR: black +} +.linkerror { + BACKGROUND-COLOR: #fcc +} +A.labelOperationLink:link { + TEXT-DECORATION: underline +} +A.labelOperationLink:active { + TEXT-DECORATION: underline +} +A.labelOperationLink:visited { + TEXT-DECORATION: underline +} +A.labelOperationLink:hover { + TEXT-DECORATION: underline +} +A.newLabel:link { + BACKGROUND-COLOR: #ddffdd +} +A.newLabel:active { + BACKGROUND-COLOR: #ddffdd +} +A.newLabel:visited { + BACKGROUND-COLOR: #ddffdd +} +A.newLabel:hover { + BACKGROUND-COLOR: #ddffdd +} +UL.square { + LIST-STYLE-TYPE: square +} +.inline-control-link { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-SIZE: 9px; BACKGROUND: #ffc; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; COLOR: #666; PADDING-TOP: 2px; TEXT-DECORATION: none +} +.inline-control-link A:link { + TEXT-DECORATION: none +} +.inline-control-link A:active { + TEXT-DECORATION: none +} +.inline-control-link A:visited { + TEXT-DECORATION: none +} +.inline-control-link A:hover { + TEXT-DECORATION: none +} +.inline-control-link { + PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-SIZE: 9px; BACKGROUND: #ffc; PADDING-BOTTOM: 2px; TEXT-TRANSFORM: uppercase; CURSOR: pointer; COLOR: #666; PADDING-TOP: 2px; TEXT-DECORATION: none +} +DIV.auto_complete { + BACKGROUND: #fff; WIDTH: 350px +} +DIV.auto_complete UL { + BORDER-RIGHT: #888 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #888 1px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; BORDER-LEFT: #888 1px solid; WIDTH: 100%; PADDING-TOP: 0px; BORDER-BOTTOM: #888 1px solid; LIST-STYLE-TYPE: none +} +DIV.auto_complete UL LI { + PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; MARGIN: 0px; PADDING-TOP: 3px +} +DIV.auto_complete UL LI.selected { + BACKGROUND-COLOR: #ffb +} +DIV.auto_complete UL STRONG.highlight { + PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #800; PADDING-TOP: 0px +} +.toogleFormDiv { + BORDER-RIGHT: #a7a6aa 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #a7a6aa 1px solid; MARGIN-TOP: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #a7a6aa 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #a7a6aa 1px solid; BACKGROUND-COLOR: white +} +.toogleInfoDiv { + BORDER-RIGHT: #a7a6aa 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #a7a6aa 1px solid; MARGIN-TOP: 10px; DISPLAY: none; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #a7a6aa 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #a7a6aa 1px solid; BACKGROUND-COLOR: white +} +.inputSection { + MARGIN-BOTTOM: 20px +} +#editBox { + BACKGROUND-COLOR: #eeefcc +} +.leftnav LI A { + PADDING-RIGHT: 2px; BORDER-TOP: #3c78b5 1px solid; DISPLAY: block; PADDING-LEFT: 5px; PADDING-BOTTOM: 2px; MARGIN: 0px; COLOR: white; PADDING-TOP: 2px; BACKGROUND-COLOR: #3c78b5; TEXT-DECORATION: none +} +.leftnav LI A:active { + COLOR: white +} +.leftnav LI A:visited { + COLOR: white +} +.leftnav LI A:hover { + COLOR: white; BACKGROUND-COLOR: #003366 +} +.replaced { + BACKGROUND-COLOR: #33cc66 +} +.topPadding { + MARGIN-TOP: 20px +} +.form-block { + PADDING-RIGHT: 6px; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; PADDING-TOP: 6px +} +.form-error-block { + PADDING-RIGHT: 12px; BORDER-TOP: #eeefcc 1px solid; PADDING-LEFT: 12px; BACKGROUND: #fcc; MARGIN-BOTTOM: 6px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: #eeefcc 1px solid +} +.form-element-large { + FONT-WEIGHT: bold; FONT-SIZE: 16px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif +} +.form-element-small { + FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #003366; FONT-FAMILY: Arial, sans-serif +} +.form-header { + PADDING-RIGHT: 12px; BORDER-TOP: #eeefcc 1px solid; PADDING-LEFT: 12px; BACKGROUND: lightyellow; MARGIN-BOTTOM: 6px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: #eeefcc 1px solid +} +.form-header P { + MARGIN: 12px 0px; LINE-HEIGHT: normal +} +.form-block P { + MARGIN: 12px 0px; LINE-HEIGHT: normal +} +.form-error-block P { + MARGIN: 12px 0px; LINE-HEIGHT: normal +} +.form-example { + FONT-SIZE: 11px; COLOR: #888 +} +.form-divider { + MARGIN-BOTTOM: 6px; BORDER-BOTTOM: #ccc 1px solid +} +.form-buttons { + PADDING-RIGHT: 10px; BORDER-TOP: #ccc 1px solid; MARGIN-TOP: 6px; PADDING-LEFT: 10px; BACKGROUND: #eeefcc; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; BORDER-BOTTOM: #ccc 1px solid; TEXT-ALIGN: center +} +.form-buttons INPUT { + WIDTH: 100px +} +.form-block .error { + PADDING-RIGHT: 6px; PADDING-LEFT: 6px; MARGIN-BOTTOM: 6px; PADDING-BOTTOM: 6px; PADDING-TOP: 6px +} diff --git a/krb5-1-6/src/windows/build/makeZip.pl b/krb5-1-6/src/windows/build/makeZip.pl new file mode 100644 index 000000000..30f0cf14b --- /dev/null +++ b/krb5-1-6/src/windows/build/makeZip.pl @@ -0,0 +1,84 @@ +#!perl -w + +#use strict; + +require "prunefiles.pl"; + +use Data::Dumper; + +sub makeZip { + local ($zip, $config) = @_; + + local $odr = $config->{Config}; ## Options, directories, repository, environment. + local $src = $odr->{src}->{value}; + local $out = $odr->{out}->{value}; + local $zipname = $zip->{filename}; + local $filestem = $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name}; + $zipname =~ s/%filestem%/$filestem/g; + if (exists $zip->{Requires}) { + local $bMakeIt = 1; + local $rverb = $odr->{repository}->{value}; + local $j = 0; + while ($zip->{Requires}->{Switch}[$j]) { ## Check Require switches + local $switch = $zip->{Requires}->{Switch}[$j]; + if (exists $switch->{name}) { ## Ignore dummy entry + # We handle REPOSITORY and CLEAN switches: + if ($switch->{name} =~ /REPOSITORY/i) { + $bMakeIt &&= ($switch->{value} =~ /$rverb/i); ## Repository verb must match requirement + } + elsif ($switch->{name} =~ /CLEAN/i) { ## Clean must be specified + $bMakeIt &&= $clean; + } + else {print "Error -- Unsupported switch $switch->{name} in Requires in ".Dumper($zip); + $bMakeIt = 0; + } + } + $j++; + } + if ( !$bMakeIt ) { + if (exists $zip->{Requires}->{ErrorMsg}) { + print "Error -- $zip->{Requires}->{ErrorMsg}->{text}\n"; + } + else { + print "Error -- requirements not met for building $zipname.\n"; + } + return 0; + } + } + + local $ziptemp = "$out\\ziptemp"; + chdir "$out"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + system("rm -rf $ziptemp") if (-d $ziptemp); + die "Fatal -- Couldn't remove $ziptemp" if (-d $ziptemp); + mkdir($ziptemp); + # Set up the zip's config section: + $zip->{Config} = $config->{Stages}->{PostPackage}->{Config}; + # Add to the copylist's config section. Don't copy Postpackage->Config, + # because the CopyList's Config might contain substitution tags. + $zip->{CopyList}->{Config}->{FileStem}->{name} = $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name}; + $zip->{CopyList}->{Config}->{From}->{root} = "$src\\pismere"; ## Add zip-specific config settings. + $zip->{CopyList}->{Config}->{To}->{root} = $ziptemp; + copyFiles($zip->{CopyList}, $config); + # Drop down into /ziptemp so the path to the added file won't include : + chdir $ziptemp; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + + # Prune any unwanted files or directories from the directory we're about to zip: + pruneFiles($zip, $config); + + local $zipfile = Archive::Zip->new(); + local $topdir = $zip->{topdir}; + $topdir =~ s/%filestem%/$filestem/g; + $zipfile->addTree('.', $topdir); + if (-e $zipname) {!system("rm -f $zipname") or die "Error -- Couldn't remove $zipname.";} + $zipfile->writeToFileNamed($zipname); + chdir("$out"); + print "Info -- chdir to ".`cd`."\n" if ($verbose); + # move .zip from /ziptemp to . + !system("mv -f ziptemp/$zipname .") or die "Error -- Couldn't move $zipname to .."; + system("rm -rf ziptemp") if (-d "ziptemp"); ## Clean up any temp directory. + print "Info -- created $out\\$zipname.\n" if ($verbose); + } + +return 1; \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/pruneFiles.pl b/krb5-1-6/src/windows/build/pruneFiles.pl new file mode 100644 index 000000000..0bb517624 --- /dev/null +++ b/krb5-1-6/src/windows/build/pruneFiles.pl @@ -0,0 +1,36 @@ +#!perl -w + +#use strict; +use Data::Dumper; + +sub pruneFiles { + local ($xml, $config) = @_; + local $prunes = $xml->{Prunes}; + if (! $prunes) {return 0;} + + # Use Unix find instead of Windows find. Save PATH so we can restore it when we're done: + local $savedPATH = $ENV{PATH}; + $ENV{PATH} = $config->{Config}->{unixfind}->{value}.";".$savedPATH; + print "Info -- Processing prunes in ".`cd`."\n" if ($verbose); + local $pru = $prunes->{Prune}; + local $files = "( "; + local $bFirst = 1; + while (($key, $val) = each %$pru) { + local $flags = $val->{flags}; + $flags = "" if (!$flags); + if (!$bFirst) {$files .= " -or ";} + $bFirst = 0; + $files .= "-".$flags."name $key"; + print "Info -- Looking for filenames matching $key\n" if ($verbose); + } + $files .= " )"; + local $list = `find . $files`; + if (length($list) > 1) { + print "Info -- Pruning $list\n" if ($verbose); + ! system("rm -rf $list") or die "Unable to prune $list"; + } + + $ENV{PATH} = $savedPATH; + } + +return 1; diff --git a/krb5-1-6/src/windows/build/repository1.pl b/krb5-1-6/src/windows/build/repository1.pl new file mode 100644 index 000000000..2f4ee21ae --- /dev/null +++ b/krb5-1-6/src/windows/build/repository1.pl @@ -0,0 +1,90 @@ +#!perl -w + +#use strict; + +sub repository1 { + local ($config) = @_; + local $odr = $config->{Config}; ## Options, directories, repository, environment. + local $src = $odr->{src}->{value}; + local $rverb = $odr->{repository}->{value}; + local $wd = $src."\\pismere"; + + if ($rverb =~ /skip/) {print "Info -- *** Skipping repository access.\n" if ($verbose);} + else { + if ($verbose) {print "Info -- *** Begin fetching sources.\n";} + local $cvspath = "$src"; + if (! -d $cvspath) { ## xcopy will create the entire path for us. + !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`; + !system("echo F | xcopy a.tmp $cvspath\\a.tmp") or die "Fatal -- Couldn't xcopy to $cvspath."; + !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file."; + !system("rm $cvspath\\a.tmp") or die "Fatal -- Couldn't remove temporary file."; + } + + # Set up cvs environment variables: + $ENV{CVSROOT} = $odr->{CVSROOT}->{value}; + local $krb5dir = "$wd\\athena\\auth\\krb5"; + + local $cvscmdroot = "cvs $rverb"; + if (length $odr->{cvstag}->{value} > 0) { + $cvscmdroot .= " -r $odr->{cvstag}->{value}"; + } + + if ($rverb =~ /checkout/) { + chdir($src) or die "Fatal -- couldn't chdir to $src\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + my @cvsmodules = ( + 'krb', + 'pismere/athena/util/lib/delaydlls', + 'pismere/athena/util/lib/getopt', + 'pismere/athena/util/guiwrap' + ); + + foreach my $module (@cvsmodules) { + local $cvscmd = $cvscmdroot." ".$module; + if ($verbose) {print "Info -- cvs command: $cvscmd\n";} + !system($cvscmd) or die "Fatal -- command \"$cvscmd\" failed; return code $?\n"; + } + } + else { ## Update. + chdir($wd) or die "Fatal -- couldn't chdir to $wd\n"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + if ($verbose) {print "Info -- cvs command: $cvscmdroot\n";} + !system($cvscmdroot) or die "Fatal -- command \"$cvscmdroot\" failed; return code $?\n"; + } + + # Set up svn environment variable: + $ENV{SVN_SSH} = "plink.exe"; + # If the directory structure doesn't exist, many cd commands will fail. + if (! -d $krb5dir) { ## xcopy will create the entire path for us. + !system("echo foo > a.tmp") or die "Fatal -- Couldn't create temporary file in ".`cd`; + !system("echo F | xcopy a.tmp $krb5dir\\a.tmp") or die "Fatal -- Couldn't xcopy to $krb5dir."; + !system("rm a.tmp") or die "Fatal -- Couldn't remove temporary file."; + !system("rm $krb5dir\\a.tmp") or die "Fatal -- Couldn't remove temporary file."; + } + + chdir($krb5dir) or die "Fatal -- Couldn't chdir to $krb5dir"; + print "Info -- chdir to ".`cd`."\n" if ($verbose); + my $svncmd = "svn $rverb "; + if ($rverb =~ /checkout/) { # Append the rest of the checkout command: + chdir(".."); + $svncmd .= "svn+ssh://".$odr->{username}->{value}."@".$odr->{SVNURL}->{value}."/krb5/"; + if (length $odr->{svntag}->{value} > 0) { + $svncmd .= "tags/$odr->{svntag}->{value}"; + } + elsif (length $odr->{svnbranch}->{value} > 0) { + $svncmd .= "branches/$odr->{svnbranch}->{value}"; + } + else { + $svncmd .= "trunk"; + } + + $svncmd .= " krb5"; + + } + if ($verbose) {print "Info -- svn command: $svncmd\n";} + !system($svncmd) or die "Fatal -- command \"$svncmd\" failed; return code $?\n"; + if ($verbose) {print "Info -- *** End fetching sources.\n";} + } + } + +return 1; \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/sdkfiles.xml b/krb5-1-6/src/windows/build/sdkfiles.xml new file mode 100644 index 000000000..c938107ca --- /dev/null +++ b/krb5-1-6/src/windows/build/sdkfiles.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/signFiles.pl b/krb5-1-6/src/windows/build/signFiles.pl new file mode 100644 index 000000000..ea093b1d7 --- /dev/null +++ b/krb5-1-6/src/windows/build/signFiles.pl @@ -0,0 +1,27 @@ +#!perl -w + +#use strict; +use Data::Dumper; + +sub signFiles { + local ($signing, $config) = @_; + local $exprs = $signing->{FilePatterns}->{value}; + local $template = $signing->{CommandTemplate}->{value}; + # Use Unix find instead of Windows find. Save PATH so we can restore it when we're done: + local $savedPATH= $ENV{PATH}; + $ENV{PATH} = $config->{Config}->{unixfind}->{value}.";".$savedPATH; + foreach $expr (split(" ", $exprs)) { ## exprs is something like "*.exe *.dll" + local $cmd = "find . -iname \"$expr\""; + local $list = `$cmd`; ## $list is files matching *.exe, for example. + foreach $target (split("\n", $list)) { + $target =~ s|/|\\|g; ## Flip path separators from unix-style to windows-style. + local $template2 = $template; + $template2 =~ s/%filename%/$target/; + print "Info -- Signing $target\n" if ($verbose); + !system("$template2") or die "Fatal -- Error signing $target."; + } + } + $ENV{PATH} = $savedPATH; + } + +return 1; \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/site-local.sed b/krb5-1-6/src/windows/build/site-local.sed new file mode 100644 index 000000000..191d20089 --- /dev/null +++ b/krb5-1-6/src/windows/build/site-local.sed @@ -0,0 +1,2 @@ +s/// +s/// \ No newline at end of file diff --git a/krb5-1-6/src/windows/build/tee.pl b/krb5-1-6/src/windows/build/tee.pl new file mode 100644 index 000000000..2c33370af --- /dev/null +++ b/krb5-1-6/src/windows/build/tee.pl @@ -0,0 +1,79 @@ +# Usage 'tee filename' +# Make sure that when using this as a perl pipe you +# print a EOF char! +# (This may be a bug in perl 4 for NT) +# +# Use it like: +# open(PIPE, "|$^X tee.pl foo.log") || die "Can't pipe"; +# open(STDOUT, ">&PIPE") || die "Can't dup pipe to stdout"; +# open(STDERR, ">&PIPE") || die "Can't dup pipe to stderr"; + +use IO::File; + +#$SIG{'INT'} = \&handler; +#$SIG{'QUIT'} = \&handler; + +$SIG{'INT'} = 'IGNORE'; +$SIG{'QUIT'} = \&handler; + +my $fh = new IO::File; + +my $arg = shift; +my $file; +my $access = ">"; + +while ($arg) { + if ($arg =~ /-a/) { + $access = ">>"; + } elsif ($arg =~ /-i/) { + $SIG{'INT'} = 'IGNORE'; + $SIG{'QUIT'} = 'IGNORE'; + } else { + $file = $arg; + last; + } + $arg = shift; +} + +STDOUT->autoflush(1); + +if ($file) { + $fh->open($access.$file) || die "Could not open $file\n"; + $fh->autoflush(1); +} + +while (<>) { + $_ = &logtime.$_; + print $_; + print $fh $_ if $file; +} + +sub logtime { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + $mon = $mon + 1; + $year %= 100; + sprintf ("[%02d/%02d/%02d %02d:%02d:%02d] ", + $year, $mon, $mday, + $hour, $min, $sec); +} + +sub handler { + my $sig = shift; + my $bailmsg = &logtime."Bailing out due to SIG$sig!\n"; + my $warnmsg = <{help} || !$f) { + usage(); + exit(0) if $OPT->{help}; + exit(1); + } + + my $p = $OPT->{path} || $ENV{PATH}; + my $s = $Config{path_sep}; + my @d = split(/$s/, $p); + my @e = split(/$s/, lc($ENV{PATHEXT} || '.bat;.exe;.com')); + my @f = ($f, map { $f.$_; } @e); + my $found = 0; + foreach my $d (@d) { + print "(Searching $d)\n" if $OPT->{debug}; + foreach my $f (@f) { + my $df = $d.'\\'.$f; # cannot use $File::Spec->catfile due to UNC. + print "(Checking for $df)\n" if $OPT->{debug}; + if (-f $df) { + exit(0) if $OPT->{quiet}; + print "$df\n"; + exit(0) if !$OPT->{all}; + $found = 1; + } + } + } + print "Could not find $f\n" if !$found && !$OPT->{quiet}; + exit($found?0:1); +} + +sub usage +{ + print <{Zips}; + if (! $zipsXML) {return 0;} + + local $i = 0; + while ($zipsXML->{Zip}[$i]) { + local $zip = $zipsXML->{Zip}[$i]; + makeZip($zip, $config) if (exists $zip->{name}); ## Ignore dummy entry. + $i++; + } ## End zip in xml. + } + +return 1; diff --git a/krb5-1-6/src/windows/cns/Makefile.in b/krb5-1-6/src/windows/cns/Makefile.in new file mode 100644 index 000000000..bc884a3fb --- /dev/null +++ b/krb5-1-6/src/windows/cns/Makefile.in @@ -0,0 +1,76 @@ +# Makefile for the Kerberos for Windows ticket manager +# Works for both k4 and k5 releases. +# +NAME = krb5 +OBJS = $(OUTPRE)cns.obj $(OUTPRE)tktlist.obj $(OUTPRE)password.obj $(OUTPRE)options.obj + +##### Options +# Set NODEBUG if building release instead of debug +!IF ! defined(KVERSION) +KVERSION = 5 +!endif +KRB = KRB$(KVERSION) + +!if $(KVERSION) == 4 +BUILDTOP = .. +LIBDIR = $(BUILDTOP)\lib\krb +KLIB = $(LIBDIR)\kerberos.lib +RESFILE = $(OUTPRE)cnsres4.res +XOBJS = $(RESFILE) +LOCALINCLUDES = /I$(BUILDTOP) /I$(BUILDTOP)\include +!endif + +!if $(KVERSION) == 5 +BUILDTOP =..\.. +LIBDIR = $(BUILDTOP)\lib +RESFILE = $(OUTPRE)cnsres5.res +XOBJS = $(RESFILE) $(OUTPRE)kpasswd.obj $(OUTPRE)cns_reg.obj +LOCALINCLUDES = /I$(BUILDTOP) /I$(BUILDTOP)\include /I$(BUILDTOP)\include\krb5 +!endif + +##### C Compiler +#CC = cl +!ifdef NODEBUG +DEFINES = /D$(KRB)=1 +!else +DEFINES = /D$(KRB)=1 /DDEBUG +!endif + +##### RC Compiler +#RC = rc +RFLAGS = /D$(KRB)=1 $(LOCALINCLUDES) +RCFLAGS = $(RFLAGS) -DKRB5_APP + +##### CVSRES -- .res -> .obj converter +CVTRES = cvtres + +##### Linker +LINK = link +LIBS = $(KLIB) $(CLIB) $(WLIB) ../lib/$(OUTPRE)libwin.lib +SYSLIBS = kernel32.lib ws2_32.lib user32.lib gdi32.lib advapi32.lib +LFLAGS = /nologo $(LOPTS) + +all:: Makefile $(OUTPRE)$(NAME).exe + +$(OUTPRE)$(NAME).exe: $(NAME).def $(OBJS) $(XOBJS) $(LIBS) + $(LINK) $(LFLAGS) /map:$*.map /out:$@ $(OBJS) $(XOBJS) \ + $(LIBS) $(SYSLIBS) $(SCLIB) + $(_VC_MANIFEST_EMBED_EXE) + +install:: + $(CP) $(OUTPRE)$(NAME).exe $(DESTDIR) + $(CP) krb5.hlp $(DESTDIR) + +clean:: + $(RM) $(OUTPRE)*.exe + $(RM) $(OUTPRE)*.res + $(RM) $(OUTPRE)*.map + +$(OBJS): cns.h tktlist.h + +$(RESFILE): cns.h ..\version.rc + +$(RESFILE): clock00.ico clock05.ico clock10.ico clock15.ico clock20.ico \ + clock25.ico clock30.ico clock35.ico clock40.ico clock45.ico \ + clock50.ico clock55.ico clock60.ico clockexp.ico clocktkt.ico \ + cns.ico diff --git a/krb5-1-6/src/windows/cns/clock00.ico b/krb5-1-6/src/windows/cns/clock00.ico new file mode 100644 index 0000000000000000000000000000000000000000..1c2e424c83feaba846167809f124ed859e27099b GIT binary patch literal 1086 zcmd5)%MHRX41Fm`+z=z=ggCMRY{jXn*XT6OCS2Ko6PV|wrA=u;NEPBG{yZmf;>dtQ z2Jbg8Tryxw>pdM}?|}6J*jbEnq&O_80f}2`KUEdLiK>c*nl3^J5D_kDJ)vqIg~LLo z{s3iz_9-uXbuyIC^%*!*B>BGO!}ko&U;Fvv!@K)F)Z5ni3(FoD2T-!nad5}675Y`S(rPO@Z9u6N?@uGZlCRE zCr%t0P>7)Q93r;}SkP)shq6+@YyvDLMr;X%DK%i+lG^uG4)8~wJ3~zuMNz;Q!-TDW zSSudEPeP*pK(a>KtGw|z5y`sz2%IIndKmCH_VYuY4D+SGzI?6cF5aKV22Yo4z|S3T z`}~FF41@(pAHZe|aLUr~A=dhH&fynnj3d2fjh=)&YYm6mpilYhu^nPAjp> Z?XgGhKbTPIHuk9x>2Zv=k{aLM>j_+x5QYE% literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock10.ico b/krb5-1-6/src/windows/cns/clock10.ico new file mode 100644 index 0000000000000000000000000000000000000000..15e00b24af94ea279af062fb5c16dc81b395919d GIT binary patch literal 1086 zcmd5)%MpSw5PhICxjB}=$?<3djy7O9PHvJmumfp=R3cY9;H2>_A0ZlU==jLn-M0xF zmRTS|j3ik?aEpNzeUdOBHW9Fx0c**TdoseD7BJ0`I`&NgaG@v~N6Qe_S{P%v;pzqF zBqI4pO3WW1YtenmhgMpUz4j;2c&n%2*H>D3_bFXny!(~Thgwy>uJk}R2mAAE@SNwP zx~uyO&lv~6D()}(;jK!(3Aid%CdE|3}LN>F@_tiS#VAw zl8>as`~h;0?kXQzX+i$lpFji0pq|oMF|4n&dee2FwbFrBb*O7S&~4%VJR7_e#i;J? z@e9uxhy%zTzb>!3_K?Vv;}^Gr=nwi&_2mi1aye?4SUD~{0ZwN?N;Om-l85Yxh`GX$P|>; zkvxf{MS(zu9f~4{$aM!i(-s9C$}s~Dd*DU(h&Lj`6E)ys$lz<$0bJ<1XsGGJdk^Ov z55lkzf_MZ!*%I{+q)swkqF3D5a>lC}*ZIckd~2+Z?=|o3 zFCH&8#k0YtZCCl&$0ICfU|E3b2E48#-#F8GoU&^9Cn4xL=kSXp6Un4mV^6G*^1qIuW#563hDp= literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock25.ico b/krb5-1-6/src/windows/cns/clock25.ico new file mode 100644 index 0000000000000000000000000000000000000000..fc163fa23d4967135acb93dc84874f5076de5890 GIT binary patch literal 1086 zcmd5)I}(C05PhIC=^T$h<`aZ!TI(0 zzOJw#KMQ1ev$}tWUod-M+JLM9_MZT|ESo;WTEEZP{9+wBF?i+}#8hNoY-*xh0Tpjv kJvzRT@5G5X6UUBaUUb7fWNRFza(82Mbx4iO^7Z$61JPd!1ONa4 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock30.ico b/krb5-1-6/src/windows/cns/clock30.ico new file mode 100644 index 0000000000000000000000000000000000000000..3dfd8458d2804c5ffd5d0308e5555abab1339773 GIT binary patch literal 1086 zcmd5)I}XAy41Fy~*$_v_gc!L29EpiY3^dn(BlHsON$AQAx-~pEtx7@*3m}~M^I|)( zBLfLiXuX8cEd^H8TGJqH5@0a{)^bMPkrT`*0qa9rI}`=LjiT_1k|xTsgte9q*KRl` z7MV+qMEn7rNtZm&`%<2;GKPEb6VxiirVg<(Du`F6j_^LhS%hEbv!F0OdcS_G*EcrA zzv;LChhJ#Uz&HU}18hIRoU&~E5$D1==kN=4%7a1jjsc8W&T^>9C7l&3uTJDE`Ow+N ZPWM=R64UscKA-7RG}VXn$XmYtUw0}w2KfL0 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock35.ico b/krb5-1-6/src/windows/cns/clock35.ico new file mode 100644 index 0000000000000000000000000000000000000000..b508e881d648eaf8094e965adf35afc1e6dc4697 GIT binary patch literal 1086 zcmd5)OAdlC5Phf#JL3^p8JFHbkK{@c7t(9gBX|k8h~Ux_*q!wa1z`y8)HrlLZ$9k| z86d(0NwR>@Z2~N*lY|Co9Rc$xuo546OO7z31WZV&Z7p(u2YDV8B~27X0b>jUzCQ3? zEHXcFiTDGu_FPljinS+=<22xoPg{BY(BxCn}f->Hq)$ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock40.ico b/krb5-1-6/src/windows/cns/clock40.ico new file mode 100644 index 0000000000000000000000000000000000000000..d7e64a398494b2f9fd6bfda0ce5f8b19ea02e8eb GIT binary patch literal 1086 zcmd5)I}XAy41EQpY=|4s2{Cd5I1&?)7-+7MN?d?Tw0B@dbmateBRn@PZTNIT2si#b z+i~p5K!gF}cmkoz0GLt7F%8lp0>(pNEcBa%$o#}5;t%LhQ`5=|R$B8Mns}-f5f?P&$;|Uwep~q ztkHr#Ys#*tJ79kX3fjjjaH1}@WcrIuttBp)v77~+@!V7U(;PA*t1Q34egEqYV}k{Q literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock45.ico b/krb5-1-6/src/windows/cns/clock45.ico new file mode 100644 index 0000000000000000000000000000000000000000..e35b2008dfb46e3ec83fc7051b684677430a7f89 GIT binary patch literal 1086 zcmc(eO-{ow5QSe#rLZeU$O?7Ijuk4W;2f;5#De4+<_Nt+auT}j3GlAwvz^q5NGc>G znAm=PwF@H|gO6 zWPkseaQiA9&>voU@&}Gj7af@EF-U6fScD zmFD@(?Iy&pGmrVQzl}Wm2adzkew06)yHUM16`t*_weMVVxDRx~2mN2*();6OEWh(L Q@BfN<{j>id#9GSp1(5Foj{pDw literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock50.ico b/krb5-1-6/src/windows/cns/clock50.ico new file mode 100644 index 0000000000000000000000000000000000000000..b1eaa1c82952b060a1823219067081c461c56392 GIT binary patch literal 1086 zcmd5)OK!qI41J-MyrY#^bcM*O>asVWH|Z5vVTlEqYos?Qmq<=hww!?3b^4qkOu{EC zgzAhx&-Qri$Uue>^86V_yAkk8o#!-2?-?+D0N%_;{vc;~qy$_{Y3#nJ03K9TRFpJP z*EO7T420$&1hdHe%w^&q(B?pGD`!|#c{azmsCemNufB_!t7#F}%$wE=HVW*cq2%W*bTJ9kGiT`d$_BOmQ8tNW~Hf zb|UHb4Duv#<0PxkYH7cr@tEK2Hd_vPny1-hc=SI)a|bRHP#=NSEtp$YUoPT(zUN$i zr9lM{CEtkPn$>r`20r#-g5^)pi*IWB-@h0e&Fuh3s}=!|^j?*Ho-GMoLK literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clock60.ico b/krb5-1-6/src/windows/cns/clock60.ico new file mode 100644 index 0000000000000000000000000000000000000000..0e9d6ebd14d4696ef4fcc7220127e16f899af2c2 GIT binary patch literal 1086 zcmd5)I}XAy41EQpY`_sZAvV~U5FCk#NDQ>+;0RozJqa@>ARFO1fhH}bLINS&`15Sn zjw1sJdPvhTgw8!+LY<~GNb>|3_JOJR$ZK+f0VR<86ld2(0q~$GyrQIuvMiD3IRn-m zSSuEppSVQ)0Uhu3xXKe&TJs#MxYEj~8aCR*nAuuI`G(j845_yXcqBLrSg}Fle-;1l z!f`)sRINX|#rO3W5A`|Vfn3egzz_c~G=o#PAvIv(yKXSMppUwy}I5?dfxzVT>t|B literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clockexp.ico b/krb5-1-6/src/windows/cns/clockexp.ico new file mode 100644 index 0000000000000000000000000000000000000000..6a22b90b94bc5b1569fb5d467a99ab7bcb29d4ea GIT binary patch literal 1086 zcmc&yy-LJD5dLxsAsnc0kW^yn3&`5tgWL0;7VfDTWWw)TA=VLTYuNo z06)~VKWOQqX&Mwo!Ha(Tq3^|`@+ToNegc_Gr?n1W`^%EJ}^3Gg*4ZhFThJCu;7G4rn1F^TS?IEgoO<`OgPm#B8L%| z>>ZMW@%1A%V=*)GiAX?)IVT+ElUmYZm)W+5C_91E-}X{{R30 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/clocktkt.ico b/krb5-1-6/src/windows/cns/clocktkt.ico new file mode 100644 index 0000000000000000000000000000000000000000..dc4d246f4af8b968c21d4a4e646ee8b278971f02 GIT binary patch literal 1086 zcmd5)Jqp4w7=5i`AxQNInZ(gWT)l=4;t{$DF7_yya{{;a7RAlc(Xm^6U+PZ_S`h?& z$@}uXd@pGe0t5)5^$>zn2#h#t&4ic)K->YwGDptI09{5Ptt>uoh74dwmQ@2IQ{;J$ zG)-A>zQZ}mNH&?0@NbB04F>pJ8>@^`q_JF&Ew!?+icJn1-83yX?fnK`(@!W*v0HGt z5p89^&;Q4-tb%-CQ$s@iTks9ML3IqBX_&! z-95`k8Ja-TGUXqrP4Sd;2qn;#v?Yafm`>VGJEeIm1$Tg!Oba-W>Cl-rkc5PnBvwDa z=h^3OCCjo6?hC0_{_eB;?6c4Fdw%cF-mZ^-W%-Fu{OJ|Xs9D=vRiipNy;!xR>N6a_ z(Vj0;%Hde*PEJoxOZ7E?!-ee^hy(xnsY#VPvA9X(=gH1)jmQ&WH{D_@>gAJ{DV62= zyj!PI&o$5@DWB_7>Nux=wLz&5QC@O`xjS86Le+Cg{n?Z&Y2UO-DJgCH=WkYOALmz4 zFWcFaOh;{^{Z*6$l&H4)!A(jD`7cn)mM*t&zWyyreT{NDDZk3NqW?R&cqioplzB>_ zXRgi8`#?gcjCwIP*LVuWv+uTd*wT)$`bN{z_H0Ybf!Y1odVAmOQu==k^Pb($>~rB% zdb_9Lck|!7=g~|Dl6*TCLdy404s0~%$0+68_G3#sAKRbM^Cd)J=}M1r{*G5UtDSyl zz0(u;vFFE8TXxcO#)D!pm@4=a&Q7mbcCtaakc%8Q^c?q)TPV6?Memljwmp%w==Z|0 zbpu|^O`)@|;OB#>NM9MXS4O!qnp|<(q}B_A$jKIRcYASU&qtHbOo+bfd|&4&=s&`N)7<@{T%V!QswXqlcbbEY-RjmNTcLREc6| z3>_#Iol3dvh1ciY$gB6Jn}<4INOR*(CN5w?3Kz|S>l?=d~eE0`f#QS%*w6A zLCK|xDOT;6u3vS$!-dG)Y=mow%1yfdL_(CE=L}+cOoP;v&6FG`J6VX#m}4mU1pGug z`GQ*vCPW@xj?;@hh6xW(uM1~Xfg0aavaSioO4yl8-d0KKV(oIWHAM}IdB@JVHpXBv zpAxH9XyI|KT|8CDd7VyxuF5^0o0~)ly(xVYbKWP4AnFy2YfXR?p7A^7FhJoD$~baD zn+yI7Mi2JaCEnKd&YX;em-v#VU_<#E8M z0JP^AtHY?K9U}3My6?4ZQuxJ56FMR{a?<)B;^9V^75a^j%1 zy7~DH+&$)b`XU|rM%%1Kc!$e{(5sE4rD?Av!{7|??Ne@;mym!fwTIT3x7D4form@N zZCcnuB38%XVs(jyBardVx|^FQ96}3pOCP}(G>>ZC8In+*j&1c@Or?X3p$49x3#(=E zfoM@2%FMV}?R3yknHiU^i=9dL5Dfx{UPIjVSWt;Y z4-27Fa((D6aT8LM>Z#4Y%- zfdH;+KA1KU&Q1i+I74CK5b8Ps=aOsCTft`C$O#F(2*U)P`sGSg(Z194Ax7>x5cKL;K-rlGC)M^p)wF+M3G7g}CZ;SZ=$d560Rj zgD75W`R3!ea~|da5A2``ZxdCl)z(L_BEn@!;v#AtdLB+XjI9EX7eYe4C_8NAPRT^H z=#YI<>ytWIFKB7AN@c7d@)!Y6ZF;e)QtQUZNHPfNCYd0OEqOl1B2gEWcRKt^vAC8g zjRcG;!x^>EvPfxpZIa^XVrWhDGn%QkqBD6kQu8Q)0Mp}?cAXr{wArV63w%P4c9Ho& zG)$YlHk!~oSixEnR*{_+v^vQ-u0^NJR806{L%}H>CsL}7xo68RjoK6gy$XkG496F0ac_k#uW^ z68;O7QWxRID|f*dL?HpsSfw?3$uEwa+Lp+U3^80It+N|4?~acL`9iU4 zyfWs7T|p?)Kh2P}wuU^~b{&;e5xR&SB*9{2M%`2=UOa#6%3&CVza zd^O!jQ!|B{D#HmK^QS_h5=NBrSv3Qgsgh7=6&~MjHNK{5^(BqdQ7{=}?HadAVx%1h z>3`zU4MipmBp8*&edaMu>B)Dx9kEn+)Io@-PaqLaBpxqOoxC^hR*Gn`tc*HEpCt@4 z^MGJMrXjh*_9}+!ACk-_AX}Z$pGis!j0~&loKD13PgBKzc!ymve?r~3bI2_g@^x2V zV_QUiIvxaVXy^v*+BkZ5-3PQCtW*xq@(cCYG;5`-yPv(HH%csdEdg=t?r>~#SDrlG zE(s(2vNkQ54;e^^rpJ>A{GBrvwI&rlQ+izMHBqBl(mjJ~dX!pz?sQcAJP}g3th4x| z|~qw2hFmF)P=pFR6&3vZk`hM`Em`rYJP)QOU29MLt1_ zFe?)E$VjV5Gcgo9M{G{gA??)dyljqSgP+Nt=5Y2kgSB^#X61oaV)secS|B!$CXGQv zNqS_0s+`(5DK*e&9#vTq`|RVNEY^_rh+-W{T6WIF)%qE)gqo&`&!R^n!{Q>${?C6Q?t>9lKoZMRMq6VTZd>t$KIxb;lUqE89glSKdtU2z8LM+G>iGO03ky+ z;nfgQ5*A77%d|x%<~9>~4Lj4prXXGedr!I`+@xcMjn0V<@qmvN?Wt)-O%^jX568y% zy1hFt&Ph(&yW4dnnSni+3ypLys98~U-9juM1Ev$`nwcvyL;h6B{j*Q}!C zxw3Y%lH9U146(%|NatAn;;pTFswFW@s*tM`-P9A%gx@x=6u&MZGY+egVBr0dhqH-? zfJfUC7b^2ilg3Pi3&{Z7sfiP2>A;{>BuTeY9@6)WCh7$@;l5lI->jb#XfEiSMfVg{ zS;~~my2B_%5L%AjUVm^>dpd%nmf7gM77o}4E7p}88ss5YauF-256?i%z(uc0Vj!Zw zT0NMgrvrm|oI)FkCYrvquhfzft*qUx?Mj|TKu^Ni`ZH_$c+XB}-ngf&Wxlv5#-k}V z+QM?Gf{U?QYv*szlZe95tDL?aJ4bs42eQ2b*^#!@^xb)|{@&s31HIW>Hgd!1 zf2QE}c^>-r&vS9BRhg|h7C4s7+JUoK>YdGPGbyp{Y=C5ZTUFDD{!^;98nxb<%KE+Z z2_|>iarEyf=}~k=dJL)9T5}t6Byn%6b(UMT?ak_cRw_B?k1ot@Rx>@ZQ!>u}vud_A zp7~qQ*0IV&G>a8eKy3VSXiq|wHwwEBGt%Lq*~1I zqUP~%s`-qoj`p#uoRq&vDNL%irZY0mY12$S#d%DT)Mtfy@c4#Low)7Ot&4uYbBKQ$_6}(u_dZuzZ^Ak)HuX@6L-n@ym+88paE*Rd5t^uTW|m*baKYUf_WWSWV||0&Bo^zynj@KJYkr0z3(x z0u7h)HUMY`8+jSy2Cxad8GIW&52iuaL*N}?7(5KV z03HKRf~UYYz|-Kn;92k-_&)e4cm-U_OCXnl8^LC97*xTpf&0Km!7=a|@DMlwo&o;> z{u8_gPJ%aFt<;5}8*Br+z-|zM82k?S82Be3GI~Y*_~qoEoWA(7uAQ^6Lgxm1IDd&% zYl$1#Yb`(@jQnN%e+J(H-vvJeFM$?bW?2L-2Umbja6RY-+dvlV0Uj6!hrkp#3O)ip z2R;v;08fH%fp3FX!E4}Z-Yt^%i#CHZQ2)yLd)s57C&Ph;O2)|F5&yp&+ycbci;oxI zE-qS_}g`$0=@vQ6<-SO0`CTD2|flKz=!?{ z`0g99Kd=)YnZrNkK?(opgD3GxPk}FkMEE~3bf0tabKahe_b+DjIg6ypd;`sQ?VM+% zNx?wdmMpz-I-_8lglTxsK!4#+8OS`6w!bjtJuM-}B1N_m$LvgWw4u z{#ksp_+|0Q;*Z4_iysyrEdEz~ulU`QW^yx&gpo5V&;IO3bM=|rKIgUnvC5YWWj|+u ziXgQN!mr6*6sJ@8DKSjqm&7iKTN1M*UP-KyI3+Pc;)BEni3<`FBpygCkT@VQK>WY> ze)0R_^TpqbufGcaZhig9d3gMP>DsG?&ZICWueZH;0W{)@H>gYTAsN-LaKr=yRG|C$ z=?2P{0eNm!RPq*Vi~8jzQs|~ND$|{zW{q0B({uI91~({u|B74H%EPKz?YTEc7wc4m zZnv)9Zj*$72DNN5vwSkM;xMZWX^V&GP>s56N4@QvmAU|0S~DwtpjO^mYq?rA>6WYO zEpL>5niO499>_?4t5x&tR-1*!W@UP7R5^Uq8r7m(rDk%Iv}#FOHLJb%N;^j_((Ro3 zm~WAGi;{MDLDi~TwAWkQEG=4-77g^oD6>b~B5f9@N5lKJt8LvcOn-uM<&NYhwjthM zoCw|WB+FhuMizE+)XBk&dI1VA&@ZSuSzh6w&kGYCixfq9?On5EI*ElwX3V((DqEb;*A{9J04h@R?X@XrJL}6_0_Z) z&RnB-Z8eDX!*4xl^a|$&C)RZTo^msex~O)2*c;~;Z+;M`jR}#W&m=NP8t;@L3k42n z2QHO4;DHGs8H}tPWz{Gv##bO%n1O5@T!I;az zdT<*U0y!`RJ_zmye+>Q}{5!x&s1;<0Zw4b^FIb8OO_P<#zCrIB;rsM-lRj?N`xd=l zr1!0QzgX`t(0hCY_mUv8$!uf>LbXsT)Cpxml~5$q2qi*=jBYj>vQf=uDn;6&zp^1z zHWF4gawj&#%65U?lb|M>NT@}xP?#y(Qq^*;o*DZFeay@pnVHlxGxja|n3-{mCt=Ub z*k7QJnHk4sW}S5`q+Mv+7@Gf|#Kbv^qgY(r)y z+TWtTgIFYsd1mIYU#z&DnYFV|W(GrK#V-+ER$h1kELPYgd7$J1vL?HjURQ8$%eH}@ zorA;8*}m+q-qzv4?SngecMZ{*=G;*-^*1JZEIb#E3tuq{mA>|F&OZ$92e=XJm!~J- z82BvsBKRg)Ne64egHZD*cpRJnEr{=Oum=Ig;A7xn&<+0%fD!{nAO=T32Xx&AszB%% zWo8xN!QPT@Ja9x_#T)B55u&_fPCfhDp(2A`#=DG9sD+U4!jBmFuV}_ zIrutw7Q6^r$zCr5UEpnCFUW(#;0SmGJPu9(dFpT#d=y?TLbm^X_}O}1#8(*0`M^QH z^EKjyxeD*ERB!FMW&ggufgOYUM)vRUqPyduyx%@&b~f+lbB8UPojdmQ?e7^F(H|D< zPkwpm+A-L((B12jcf;A+&!=SP>~1A`$Llwf{C--~sIzW}>P>g=9CCK?({uQCeo?-0 zx7xoy+t;5R?BCA|9{jfBPN|(kLp{4T?;hb`M$1{JxUyMWQ>N*t>Q;>tvc|%r=`Euc zXYOo}^E(?%Aewd8IiHH7wOfYqc8~1YG0=D>>Yhyq+N#SYK2DR6cc#0T$uHcT)IFB> z;!x|yhG+ZKij^OtGRw=&k;BIq&M+_j`D!V(4QixX8VibQ$r@?0E#zwib@4@V+;ay% zD#;xk`v%sk{oBpo7DYGb}dKkH+%4$%Jsdw4SQZ}{f zw`uOou4dBrGRW@Vu;lz^($S@@7wPq?<-qjx;80(WaxQooI)||hX=fOc?wMmdQnMP- zvo0xD^S+PSk87StO{@wW`^mjcO@sReR`(4Kh#-=!BN<=hB2+NgOV?R4ZKGMG5G3iq zwxP@tAy8~1a#5s~OeT}9h zlfAvtPUdmS!diI^a!t1*`>q}LeoNmk^b7}Mfh>T!@+Fryqd#V$DB{FuL z-D=A9)QeqWizN*|)nl7pUNZ*pU@ooi0K(0+jf3mjPBzyb#rIIzHh1r985 zV1WY*99ZDM>yZOI)8PwB`yUrNTQ;+1>b47~xsIP2yhHwXN8KhlmZg@g>!g%lxTKU{ cxuleB?k7Kdw?m8n59`nQ=AV9c@V{~VU%s&Km;e9( literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/cns-help.hlp b/krb5-1-6/src/windows/cns/cns-help.hlp new file mode 100644 index 0000000000000000000000000000000000000000..a9a00244d5d852052e8944c7d8eb88571904bca4 GIT binary patch literal 11944 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',`IDH_Glossary')") +; + + +[FILES] +; The files section is where you specify to the Help Compiler which +; Rich Text Format (.RTF) (your help source) files will be used in the +; Help system. RoboHELP generates and maintains the main .RTF +; file for your Help System. If you desire to have multiple .RTF files, +; simply add the additonal names to the [FILES] section. + +KERBNET.RTF +[ALIAS] +; The Alias section allows you to set up aliases for context strings +; in your help system. +; +; Brief example: +; +; IDH_UserID = IDH_RoboGenerated_Id +; IDH_WMP_MenuID = IDH_RoboGenerated_Id +; IDH_Any = IDH_AnyOther + +[MAP] +; +; The Map Section is where the C language #defines are translated +; or mapped into the Help System Context Strings. Standard C syntax +; can be employed. The .HH file is meant to be #include(d) into your +; Windows application source code. +; + +[BITMAPS] +; +; The [BITMAPS] section is where you list any Bitmaps which have +; been placed by reference in the Help System. See the Help compiler +; documentation for more information about placing bitmaps. +; +; The [BITMAPS] section is not really required under Windows 3.1, +; with the advent of the BMROOT item in the [OPTIONS] section. +; +;FOO1.BMP +;FOO2.BMP +;C:\FOO\FOO3.BMP +;And So On + +[WINDOWS] +; Windows Help can display help in one of 5 secondary windows. +; Before using a secondary window, the window must be defined +; in this section: +; +;Gloss = "Glossary",(100,100,350,350),0,(255,255,255),(255,255,255) +main=,,0,, + +[BAGGAGE] +; +; The Baggage section allows the user to include files which +; will be placed in the internal file system for WinHelp. +; Using files from Baggage is a little faster for CDROM, since +; the CDROM drive table does not need to be read from disk. +; +; Baggage files are referred to as regular bitmaps, except +; that you prefix the filename with '!'. +; +; For Instance: +; {bmc !bitmap.bmp} instead of {bmc bitmap.bmp} +; diff --git a/krb5-1-6/src/windows/cns/cns.c b/krb5-1-6/src/windows/cns/cns.c new file mode 100644 index 000000000..7a02abba7 --- /dev/null +++ b/krb5-1-6/src/windows/cns/cns.c @@ -0,0 +1,2208 @@ +/* + * cns.c + * + * Main routine of the Kerberos user interface. Also handles + * all dialog level management functions. + * + * Copyright 1994 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "cns.h" +#include "tktlist.h" +#include "cns_reg.h" + +#include "../lib/gic.h" + +enum { /* Actions after login */ + LOGIN_AND_EXIT, + LOGIN_AND_MINIMIZE, + LOGIN_AND_RUN, +}; + +/* + * Globals + */ +static HICON kwin_icons[MAX_ICONS]; /* Icons depicting time */ +HFONT hfontdialog = NULL; /* Font in which the dialog is drawn. */ +static HFONT hfonticon = NULL; /* Font for icon label */ +HINSTANCE hinstance; +static int dlgncmdshow; /* ncmdshow from WinMain */ +#if 0 +static UINT wm_kerberos_changed; /* message for cache changing */ +#endif +static int action; /* After login actions */ +static UINT kwin_timer_id; /* Timer being used for update */ +BOOL alert; /* Actions on ticket expiration */ +BOOL beep; +static BOOL alerted; /* TRUE when user already alerted */ +BOOL isblocking = FALSE; /* TRUE when blocked in WinSock */ +static DWORD blocking_end_time; /* Ending count for blocking timeout */ +static FARPROC hook_instance; /* handle for blocking hook function */ + +char confname[FILENAME_MAX]; /* krb5.conf (or krb.conf for krb4) */ + +#ifdef KRB5 +char ccname[FILENAME_MAX]; /* ccache file location */ +BOOL forwardable; /* TRUE to get forwardable tickets */ +BOOL noaddresses; +krb5_context k5_context; +krb5_ccache k5_ccache; +#endif + +/* + * Function: Called during blocking operations. Implement a timeout + * if nothing occurs within the specified time, cancel the blocking + * operation. Also permit the user to press escape in order to + * cancel the blocking operation. + * + * Returns: TRUE if we got and dispatched a message, FALSE otherwise. + */ +BOOL CALLBACK +blocking_hook_proc(void) +{ + MSG msg; + BOOL rc; + + if (GetTickCount() > blocking_end_time) { + WSACancelBlockingCall(); + return FALSE; + } + + rc = (BOOL)PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + if (!rc) + return FALSE; + + if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) { + WSACancelBlockingCall(); + blocking_end_time = msg.time - 1; + return FALSE; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + + return TRUE; +} + + +/* + * Function: Set up a blocking hook function. + * + * Parameters: + * timeout - # of seconds to block for before cancelling. + */ +void +start_blocking_hook(int timeout) +{ + FARPROC proc; + + if (isblocking) + return; + + isblocking = TRUE; + blocking_end_time = GetTickCount() + (1000 * timeout); +#ifdef _WIN32 + proc = WSASetBlockingHook(blocking_hook_proc); +#else + hook_instance = MakeProcInstance(blocking_hook_proc, hinstance); + proc = WSASetBlockingHook(hook_instance); +#endif + assert(proc != NULL); +} + + +/* + * Function: End the blocking hook fuction set up above. + */ +void +end_blocking_hook(void) +{ +#ifndef _WIN32 + FreeProcInstance(hook_instance); +#endif + WSAUnhookBlockingHook(); + isblocking = FALSE; +} + + +/* + * Function: Centers the specified window on the screen. + * + * Parameters: + * hwnd - the window to center on the screen. + */ +void +center_dialog(HWND hwnd) +{ + int scrwidth, scrheight; + int dlgwidth, dlgheight; + RECT r; + HDC hdc; + + if (hwnd == NULL) + return; + + GetWindowRect(hwnd, &r); + dlgwidth = r.right - r.left; + dlgheight = r.bottom - r.top ; + hdc = GetDC(NULL); + scrwidth = GetDeviceCaps(hdc, HORZRES); + scrheight = GetDeviceCaps(hdc, VERTRES); + ReleaseDC(NULL, hdc); + r.left = (scrwidth - dlgwidth) / 2; + r.top = (scrheight - dlgheight) / 2; + MoveWindow(hwnd, r.left, r.top, dlgwidth, dlgheight, TRUE); +} + + +/* + * Function: Positions the kwin dialog either to the saved location + * or the center of the screen if no saved location. + * + * Parameters: + * hwnd - the window to center on the screen. + */ +static void +position_dialog(HWND hwnd) +{ + int scrwidth, scrheight; + HDC hdc; + int x, y, cx, cy; + + if (hwnd == NULL) + return; + + hdc = GetDC(NULL); + scrwidth = GetDeviceCaps(hdc, HORZRES); + scrheight = GetDeviceCaps(hdc, VERTRES); + ReleaseDC(NULL, hdc); + x = cns_res.x; + y = cns_res.y; + cx = cns_res.cx; + cy = cns_res.cy; + + if (x > scrwidth || + y > scrheight || + x + cx <= 0 || + y + cy <= 0) + center_dialog(hwnd); + else + MoveWindow(hwnd, x, y, cx, cy, TRUE); +} + + +/* + * Function: Set font of all dialog items. + * + * Parameters: + * hwnd - the dialog to set the font of + */ +void +set_dialog_font(HWND hwnd, HFONT hfont) +{ + hwnd = GetWindow(hwnd, GW_CHILD); + + while (hwnd != NULL) { + SetWindowFont(hwnd, hfont, 0); + hwnd = GetWindow(hwnd, GW_HWNDNEXT); + } +} + + +/* + * Function: Trim leading and trailing white space from a string. + * + * Parameters: + * s - the string to trim. + */ +void +trim(char *s) +{ + int l; + int i; + + for (i = 0 ; s[i] ; i++) + if (s[i] != ' ' && s[i] != '\t') + break; + + l = strlen(&s[i]); + memmove(s, &s[i], l + 1); + + for (l--; l >= 0; l--) { + if (s[l] != ' ' && s[l] != '\t') + break; + } + s[l + 1] = 0; +} + + +/* + * Function: This routine figures out the current time epoch and + * returns the conversion factor. It exists because Microloss + * screwed the pooch on the time() and _ftime() calls in its release + * 7.0 libraries. They changed the epoch to Dec 31, 1899! + */ +time_t +kwin_get_epoch(void) +{ + static struct tm jan_1_70 = {0, 0, 0, 1, 0, 70}; + time_t epoch = 0; + + epoch = -mktime(&jan_1_70); /* Seconds til 1970 localtime */ + epoch += _timezone; /* Seconds til 1970 GMT */ + + return epoch; +} + + +/* + * Function: Save the credentials for later restoration. + * + * Parameters: + * c - Returned pointer to saved credential cache. + * + * pname - Returned as principal name of session. + * + * pinstance - Returned as principal instance of session. + * + * ncred - Returned number of credentials saved. + */ +static void +push_credentials(CREDENTIALS **cp, char *pname, char *pinstance, int *ncred) +{ +#ifdef KRB4 + int i; + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + CREDENTIALS *c; + + if (krb_get_tf_fullname(NULL, pname, pinstance, NULL) != KSUCCESS) { + pname[0] = 0; + + pinstance[0] = 0; + } + + *ncred = krb_get_num_cred(); + if (*ncred <= 0) + return; + + c= malloc(*ncred * sizeof(CREDENTIALS)); + assert(c != NULL); + if (c == NULL) { + *ncred = 0; + + return; + } + + for (i = 0; i < *ncred; i++) { + krb_get_nth_cred(service, instance, realm, i + 1); + krb_get_cred(service, instance, realm, &c[i]); + } + + *cp = c; +#endif + +#ifdef KRB5 /* FIXME */ + return; +#endif +} + + +/* + * Function: Restore the saved credentials. + * + * c - Pointer to saved credential cache. + * + * pname - Principal name of session. + * + * pinstance - Principal instance of session. + * + * ncred - Number of credentials saved. + */ +static void +pop_credentials(CREDENTIALS *c, char *pname, char *pinstance, int ncred) +{ +#ifdef KRB4 + int i; + + if (pname[0]) + in_tkt(pname, pinstance); + else + dest_tkt(); + + if (ncred <= 0) + return; + + for (i = 0; i < ncred; i++) { + krb_save_credentials(c[i].service, c[i].instance, c[i].realm, + c[i].session, c[i].lifetime, c[i].kvno, + &(c[i].ticket_st), + c[i].issue_date); + } + + free(c); +#endif +#ifdef KRB5 /* FIXME */ + return; +#endif +} + + +/* + * Function: Save most recent login triplets for placement on the + * bottom of the file menu. + * + * Parameters: + * hwnd - the handle of the window containing the menu to edit. + * + * name - A login name to save in the recent login list + * + * instance - An instance to save in the recent login list + * + * realm - A realm to save in the recent login list + */ +static void +kwin_push_login(HWND hwnd, char *name, char *instance, char *realm) +{ + HMENU hmenu; + int i; + int id; + int ctitems; + char fullname[MAX_K_NAME_SZ + 3]; + char menuitem[MAX_K_NAME_SZ + 3]; + BOOL rc; + + fullname[sizeof(fullname) - 1] = '\0'; + strncpy(fullname, "&x ", sizeof(fullname) - 1); + strncat(fullname, name, sizeof(fullname) - 1 - strlen(fullname)); + strncat(fullname, ".", sizeof(fullname) - 1 - strlen(fullname)); + strncat(fullname, instance, sizeof(fullname) - 1 - strlen(fullname)); + strncat(fullname, "@", sizeof(fullname) - 1 - strlen(fullname)); + strncat(fullname, realm, sizeof(fullname) - 1 - strlen(fullname)); + + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + ctitems = GetMenuItemCount(hmenu); + assert(ctitems >= FILE_MENU_ITEMS); + + if (ctitems == FILE_MENU_ITEMS) { + rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL); + assert(rc); + + ctitems++; + } + + for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) { + GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION); + + if (strcmp(&fullname[3], &menuitem[3]) == 0) { + rc = RemoveMenu(hmenu, i, MF_BYPOSITION); + assert(rc); + + ctitems--; + + break; + } + } + + rc = InsertMenu(hmenu, FILE_MENU_ITEMS + 1, MF_BYPOSITION, 1, fullname); + assert(rc); + + ctitems++; + if (ctitems - FILE_MENU_ITEMS - 1 > FILE_MENU_MAX_LOGINS) { + RemoveMenu(hmenu, ctitems - 1, MF_BYPOSITION); + + ctitems--; + } + + id = 0; + for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) { + GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION); + + rc = RemoveMenu(hmenu, i, MF_BYPOSITION); + assert(rc); + + menuitem[1] = '1' + id; + rc = InsertMenu(hmenu, i, MF_BYPOSITION, IDM_FIRST_LOGIN + id, menuitem); + assert(rc); + + id++; + } +} + + +/* + * Function: Initialize the logins on the file menu form the KERBEROS.INI + * file. + * + * Parameters: + * hwnd - handle of the dialog containing the file menu. + */ +static void +kwin_init_file_menu(HWND hwnd) +{ + HMENU hmenu; + int i; + char menuitem[MAX_K_NAME_SZ + 3]; + int id; + BOOL rc; + + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + id = 0; + for (i = 0; i < FILE_MENU_MAX_LOGINS; i++) { + strcpy(menuitem + 3, cns_res.logins[i]); + + if (!menuitem[3]) + continue; + + menuitem[0] = '&'; + menuitem[1] = '1' + id; + menuitem[2] = ' '; + + if (id == 0) { + rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL); + assert(rc); + } + AppendMenu(hmenu, MF_STRING, IDM_FIRST_LOGIN + id, menuitem); + + id++; + } +} + + +/* + * Function: Save the items on the file menu in the KERBEROS.INI file. + * + * Parameters: + * hwnd - handle of the dialog containing the file menu. + */ +static void +kwin_save_file_menu(HWND hwnd) +{ + HMENU hmenu; + int i; + int id; + int ctitems; + char menuitem[MAX_K_NAME_SZ + 3]; + + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + ctitems = GetMenuItemCount(hmenu); + assert(ctitems >= FILE_MENU_ITEMS); + + id = 0; + for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) { + GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION); + + strcpy(cns_res.logins[id], menuitem + 3); + + id++; + } +} + + + +/* + * Function: Given an expiration time, choose an appropriate + * icon to display. + * + * Parameters: + * expiration time of expiration in time() compatible units + * + * Returns: Handle of icon to display + */ +HICON +kwin_get_icon(time_t expiration) +{ + int ixicon; + time_t dt; + + dt = expiration - time(NULL); + dt = dt / 60; /* convert to minutes */ + if (dt <= 0) + ixicon = IDI_EXPIRED - IDI_FIRST_CLOCK; + else if (dt > 60) + ixicon = IDI_TICKET - IDI_FIRST_CLOCK; + else + ixicon = (int)(dt / 5); + + return kwin_icons[ixicon]; +} + + +/* + * Function: Intialize name fields in the Kerberos dialog. + * + * Parameters: + * hwnd - the window recieving the message. + * + * fullname - the full kerberos name to initialize with + */ +void +kwin_init_name(HWND hwnd, char *fullname) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + int krc; +#ifdef KRB5 + krb5_error_code code; + char *ptr; +#endif + + if (fullname == NULL || fullname[0] == 0) { +#ifdef KRB4 + strcpy(name, krb_get_default_user()); + strcpy(instance, cns_res.instance); + krc = krb_get_lrealm(realm, 1); + if (krc != KSUCCESS) + realm[0] = 0; + strcpy(realm, cns_res.realm); +#endif /* KRB4 */ + +#ifdef KRB5 + strcpy(name, cns_res.name); + + *realm = '\0'; + code = krb5_get_default_realm(k5_context, &ptr); + if (!code) { + strcpy(realm, ptr); + /* free(ptr); XXX */ + } + strcpy(realm, cns_res.realm); +#endif /* KRB5 */ + + } else { +#ifdef KRB4 + kname_parse(name, instance, realm, fullname); + SetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance); +#endif + +#ifdef KRB5 + krc = k5_kname_parse(name, realm, fullname); + *instance = '\0'; +#endif + } + + SetDlgItemText(hwnd, IDD_LOGIN_NAME, name); + SetDlgItemText(hwnd, IDD_LOGIN_REALM, realm); +} + + +/* + * Function: Set the focus to the name control if no name + * exists, the realm control if no realm exists or the + * password control. Uses PostMessage not SetFocus. + * + * Parameters: + * hwnd - the Window handle of the parent. + */ +void +kwin_set_default_focus(HWND hwnd) +{ + char name[ANAME_SZ]; + char realm[REALM_SZ]; + HWND hwnditem; + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + + trim(name); + if (strlen(name) <= 0) + hwnditem = GetDlgItem(hwnd, IDD_LOGIN_NAME); + else { + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + + if (strlen(realm) <= 0) + hwnditem = GetDlgItem(hwnd, IDD_LOGIN_REALM); + else + hwnditem = GetDlgItem(hwnd, IDD_LOGIN_PASSWORD); + } + + PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwnditem, MAKELONG(1, 0)); +} + + +/* + * Function: Save the values which live in the KERBEROS.INI file. + * + * Parameters: + * hwnd - the window handle of the dialog containing fields to + * be saved + */ +static void +kwin_save_name(HWND hwnd) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + +#ifdef KRB4 + krb_set_default_user(name); + GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance)); + trim(instance); + strcpy(cns_res.instance, instance); +#endif + +#ifdef KRB5 + strcpy(cns_res.name, name); + *instance = '\0'; +#endif + + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + strcpy(cns_res.realm, realm); + + kwin_push_login(hwnd, name, instance, realm); +} + + +/* + * Function: Process WM_INITDIALOG messages. Set the fonts + * for all items on the dialog and populate the ticket list. + * Also set the default values for user, instance and realm. + * + * Returns: TRUE if we didn't set the focus here, + * FALSE if we did. + */ +static BOOL +kwin_initdialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) +{ + LOGFONT lf; + HDC hdc; + char name[ANAME_SZ]; + + position_dialog(hwnd); + ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + kwin_init_file_menu(hwnd); + kwin_init_name(hwnd, (char *)lParam); + hdc = GetDC(NULL); + assert(hdc != NULL); + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -MulDiv(9, GetDeviceCaps(hdc, LOGPIXELSY), 72); + strcpy(lf.lfFaceName, "Arial"); + hfontdialog = CreateFontIndirect(&lf); + assert(hfontdialog != NULL); + + if (hfontdialog == NULL) { + ReleaseDC(NULL, hdc); + + return TRUE; + } + + lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + hfonticon = CreateFontIndirect(&lf); + assert(hfonticon != NULL); + + if (hfonticon == NULL) { + ReleaseDC(NULL, hdc); + + return TRUE; + } + + ReleaseDC(NULL, hdc); + + set_dialog_font(hwnd, hfontdialog); + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + + if (strlen(name) > 0) + SetFocus(GetDlgItem(hwnd, IDD_LOGIN_PASSWORD)); + else + SetFocus(GetDlgItem(hwnd, IDD_LOGIN_NAME)); + + ShowWindow(hwnd, dlgncmdshow); + + kwin_timer_id = SetTimer(hwnd, 1, KWIN_UPDATE_PERIOD, NULL); + assert(kwin_timer_id != 0); + + return FALSE; +} + + +/* + * Function: Process WM_DESTROY messages. Delete the font + * created for use by the controls. + */ +static void +kwin_destroy(HWND hwnd) +{ + RECT r; + + ticket_destroy(GetDlgItem(hwnd, IDD_TICKET_LIST)); + + if (hfontdialog != NULL) + DeleteObject(hfontdialog); + + if (hfonticon != NULL) + DeleteObject(hfonticon); + + kwin_save_file_menu(hwnd); + GetWindowRect(hwnd, &r); + cns_res.x = r.left; + cns_res.y = r.top; + cns_res.cx = r.right - r.left; + cns_res.cy = r.bottom - r.top; + + KillTimer(hwnd, kwin_timer_id); +} + + +/* + * Function: Retrievs item WindowRect in hwnd client + * coordiate system. + * + * Parameters: + * hwnditem - the item to retrieve + * + * item - dialog in which into which to translate + * + * r - rectangle returned + */ +static void +windowrect(HWND hwnditem, HWND hwnd, RECT *r) +{ + GetWindowRect(hwnditem, r); + ScreenToClient(hwnd, (LPPOINT)&(r->left)); + ScreenToClient(hwnd, (LPPOINT)&(r->right)); +} + + +/* + * Function: Process WM_SIZE messages. Resize the + * list and position the buttons attractively. + */ +static void +kwin_size(HWND hwnd, UINT state, int cxdlg, int cydlg) +{ +#define listgap 8 + RECT r; + RECT rdlg; + int hmargin, vmargin; + HWND hwnditem; + int cx, cy; + int i; + int titlebottom; + int editbottom; + int listbottom; + int gap; + int left; + int titleleft[IDD_MAX_TITLE - IDD_MIN_TITLE + 1]; + + if (state == SIZE_MINIMIZED) + return; + + GetClientRect(hwnd, &rdlg); + + /* + * The ticket list title + */ + hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST_TITLE); + + if (hwnditem == NULL) + return; + + windowrect(hwnditem, hwnd, &r); + hmargin = r.left; + vmargin = r.top; + cx = cxdlg - 2 * hmargin; + cy = r.bottom - r.top; + MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE); + + /* + * The buttons + */ + cx = 0; + + for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + if (i == IDD_MIN_BUTTON) + hmargin = r.left; + + cx += r.right - r.left; + } + + gap = (cxdlg - 2 * hmargin - cx) / (IDD_MAX_BUTTON - IDD_MIN_BUTTON); + left = hmargin; + for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + editbottom = -r.top; + cx = r.right - r.left; + cy = r.bottom - r.top; + r.top = rdlg.bottom - vmargin - cy; + MoveWindow(hwnditem, left, r.top, cx, cy, TRUE); + + left += cx + gap; + } + + /* + * Edit fields: stretch boxes, keeping the gap between boxes equal to + * what it was on entry. + */ + editbottom += r.top; + + hwnditem = GetDlgItem(hwnd, IDD_MIN_EDIT); + windowrect(hwnditem, hwnd, &r); + gap = r.right; + hmargin = r.left; + editbottom += r.bottom; + titlebottom = -r.top; + + hwnditem = GetDlgItem(hwnd, IDD_MIN_EDIT + 1); + windowrect(hwnditem, hwnd, &r); + gap = r.left - gap; + + cx = cxdlg - 2 * hmargin - (IDD_MAX_EDIT - IDD_MIN_EDIT) * gap; + cx = cx / (IDD_MAX_EDIT - IDD_MIN_EDIT + 1); + left = hmargin; + + for (i = IDD_MIN_EDIT; i <= IDD_MAX_EDIT; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + cy = r.bottom - r.top; + r.top = editbottom - cy; + MoveWindow(hwnditem, left, r.top, cx, cy, TRUE); + titleleft[i-IDD_MIN_EDIT] = left; + + left += cx + gap; + } + + /* + * Edit field titles + */ + titlebottom += r.top; + windowrect(GetDlgItem(hwnd, IDD_MIN_TITLE), hwnd, &r); + titlebottom += r.bottom; + listbottom = -r.top; + + for (i = IDD_MIN_TITLE; i <= IDD_MAX_TITLE; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + cx = r.right - r.left; + cy = r.bottom - r.top; + r.top = titlebottom - cy; + MoveWindow(hwnditem, titleleft[i-IDD_MIN_TITLE], r.top, cx, cy, TRUE); + } + + /* + * The list + */ + listbottom = r.top - listgap; + hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST); + windowrect(hwnditem, hwnd, &r); + hmargin = r.left; + cx = cxdlg - 2 * hmargin; + cy = listbottom - r.top; + MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE); +} + + +/* + * Function: Process WM_GETMINMAXINFO messages + */ +static void +kwin_getminmaxinfo(HWND hwnd, LPMINMAXINFO lpmmi) +{ + lpmmi->ptMinTrackSize.x = + (KWIN_MIN_WIDTH * LOWORD(GetDialogBaseUnits())) / 4; + + lpmmi->ptMinTrackSize.y = + (KWIN_MIN_HEIGHT * HIWORD(GetDialogBaseUnits())) / 8; +} + + +/* + * Function: Process WM_TIMER messages + */ +static void +kwin_timer(HWND hwnd, UINT timer_id) +{ + HWND hwndfocus; + time_t t; + time_t expiration; + BOOL expired; +#ifdef KRB4 + CREDENTIALS c; + int ncred; + int i; + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; +#endif +#ifdef KRB5 + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds cred; + int n; + char *s; +#endif + + if (timer_id != 1) { + FORWARD_WM_TIMER(hwnd, timer_id, DefDlgProc); + return; + } + + expired = FALSE; + ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + + if (alerted) { + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + + return; + } + +#ifdef KRB4 + ncred = krb_get_num_cred(); + for (i = 1; i <= ncred; i++) { + krb_get_nth_cred(service, instance, realm, i); + + if (_stricmp(service, "krbtgt") == 0) { + /* Warn if ticket will expire w/i TIME_BUFFER seconds */ + krb_get_cred(service, instance, realm, &c); + expiration = c.issue_date + (long)c.lifetime * 5L * 60L; + t = TIME_BUFFER + time(NULL); + + if (t >= expiration) { + expired = TRUE; + /* Don't alert because of stale tickets */ + if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) { + alerted = TRUE; + + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + return; + } + break; + } + } + } +#endif + +#ifdef KRB5 + code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor); + + while (code == 0) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &cred); + if (code) + break; + n = krb5_princ_component(k5_context, cred.server, 0)->length; + s = krb5_princ_component(k5_context, cred.server, 0)->data; + if (n != KRB5_TGS_NAME_SIZE) + continue; + if (memcmp(KRB5_TGS_NAME, s, KRB5_TGS_NAME_SIZE)) + continue; + + /* Warn if ticket will expire w/i TIME_BUFFER seconds */ + expiration = cred.times.endtime; + t = TIME_BUFFER + time(NULL); + + if (t >= expiration) { + expired = TRUE; + /* Don't alert because of stale tickets */ + if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) { + alerted = TRUE; + + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + return; + } + break; + } + } + if (code == 0 || code == KRB5_CC_END) + krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor); + +#endif + + if (!expired) { + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + + return; + } + + alerted = TRUE; + + if (beep) + MessageBeep(MB_ICONEXCLAMATION); + + if (alert) { + if (IsIconic(hwnd)) { + hwndfocus = GetFocus(); + ShowWindow(hwnd, SW_RESTORE); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + SetFocus(hwndfocus); + } + + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + + return; + } + + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); +} + +/* + * Function: Process WM_COMMAND messages + */ +static void +kwin_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify) +{ + char name[ANAME_SZ]; + char realm[REALM_SZ]; + char password[MAX_KPW_LEN]; + HCURSOR hcursor; + BOOL blogin; + HMENU hmenu; + char menuitem[MAX_K_NAME_SZ + 3]; + char copyright[128]; + int id; +#ifdef KRB4 + char instance[INST_SZ]; + int lifetime; + int krc; +#endif +#ifdef KRB5 + long lifetime; + krb5_error_code code; + krb5_principal principal; + krb5_creds creds; + krb5_get_init_creds_opt opts; + gic_data gd; +#endif + +#ifdef KRB4 + EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), krb_get_num_cred() > 0); +#endif + +#ifdef KRB5 + EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), k5_get_num_cred(1) > 0); +#endif + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + blogin = strlen(name) > 0; + + if (blogin) { + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + blogin = strlen(realm) > 0; + } + + if (blogin) { + GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password)); + blogin = strlen(password) > 0; + } + + EnableWindow(GetDlgItem(hwnd, IDD_LOGIN), blogin); + id = (blogin) ? IDD_LOGIN : IDD_PASSWORD_CR2; + SendMessage(hwnd, DM_SETDEFID, id, 0); + + if (codeNotify != BN_CLICKED && codeNotify != 0 && codeNotify != 1) + return; /* FALSE */ + + /* + * Check to see if this item is in a list of the ``recent hosts'' sort + * of list, under the FILE menu. + */ + if (cid >= IDM_FIRST_LOGIN && cid < IDM_FIRST_LOGIN + FILE_MENU_MAX_LOGINS) { + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + if (!GetMenuString(hmenu, cid, menuitem, sizeof(menuitem), MF_BYCOMMAND)) + return; /* TRUE */ + + if (menuitem[0]) + kwin_init_name(hwnd, &menuitem[3]); + + return; /* TRUE */ + } + + switch (cid) { + case IDM_EXIT: + if (isblocking) + WSACancelBlockingCall(); + WinHelp(hwnd, KERBEROS_HLP, HELP_QUIT, 0); + PostQuitMessage(0); + + return; /* TRUE */ + + case IDD_PASSWORD_CR2: /* Make CR == TAB */ + id = GetDlgCtrlID(GetFocus()); + assert(id != 0); + + if (id == IDD_MAX_EDIT) + PostMessage(hwnd, WM_NEXTDLGCTL, + (WPARAM)GetDlgItem(hwnd, IDD_MIN_EDIT), MAKELONG(1, 0)); + else + PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0); + + return; /* TRUE */ + + case IDD_LOGIN: + if (isblocking) + return; /* TRUE */ + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password)); + SetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, ""); /* nuke the password */ + trim(password); + +#ifdef KRB4 + GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance)); + trim(instance); +#endif + + hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + lifetime = cns_res.lifetime; + start_blocking_hook(BLOCK_MAX_SEC); + +#ifdef KRB4 + lifetime = (lifetime + 4) / 5; + krc = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm, + lifetime, password); +#endif + +#ifdef KRB5 + principal = NULL; + + /* + * convert the name + realm into a krb5 principal string and parse it into a principal + */ + sprintf(menuitem, "%s@%s", name, realm); + code = krb5_parse_name(k5_context, menuitem, &principal); + if (code) + goto errorpoint; + + /* + * set the various ticket options. First, initialize the structure, then set the ticket + * to be forwardable if desired, and set the lifetime. + */ + krb5_get_init_creds_opt_init(&opts); + krb5_get_init_creds_opt_set_forwardable(&opts, forwardable); + krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime * 60); + if (noaddresses) { + krb5_get_init_creds_opt_set_address_list(&opts, NULL); + } + + /* + * get the initial creds using the password and the options we set above + */ + gd.hinstance = hinstance; + gd.hwnd = hwnd; + gd.id = ID_VARDLG; + code = krb5_get_init_creds_password(k5_context, &creds, principal, password, + gic_prompter, &gd, 0, NULL, &opts); + if (code) + goto errorpoint; + + /* + * initialize the credential cache + */ + code = krb5_cc_initialize(k5_context, k5_ccache, principal); + if (code) + goto errorpoint; + + /* + * insert the principal into the cache + */ + code = krb5_cc_store_cred(k5_context, k5_ccache, &creds); + + errorpoint: + + if (principal) + krb5_free_principal(k5_context, principal); + + end_blocking_hook(); + SetCursor(hcursor); + kwin_set_default_focus(hwnd); + + if (code) { + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) + MessageBox(hwnd, "Password incorrect", NULL, + MB_OK | MB_ICONEXCLAMATION); + else + com_err(NULL, code, "while logging in"); + } +#endif /* KRB5 */ + +#ifdef KRB4 + if (krc != KSUCCESS) { + MessageBox(hwnd, krb_get_err_text(krc), "", + MB_OK | MB_ICONEXCLAMATION); + + return; /* TRUE */ + } +#endif + + kwin_save_name(hwnd); + alerted = FALSE; + + switch (action) { + case LOGIN_AND_EXIT: + SendMessage(hwnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EXIT, 0, 0)); + break; + + case LOGIN_AND_MINIMIZE: + ShowWindow(hwnd, SW_MINIMIZE); + break; + } + + return; /* TRUE */ + + case IDD_TICKET_DELETE: + if (isblocking) + return; /* TRUE */ + +#ifdef KRB4 + krc = dest_tkt(); + if (krc != KSUCCESS) + MessageBox(hwnd, krb_get_err_text(krc), "", + MB_OK | MB_ICONEXCLAMATION); +#endif + +#ifdef KRB5 + code = k5_dest_tkt(); +#endif + + kwin_set_default_focus(hwnd); + alerted = FALSE; + + return; /* TRUE */ + + case IDD_CHANGE_PASSWORD: + if (isblocking) + return; /* TRUE */ + password_dialog(hwnd); + kwin_set_default_focus(hwnd); + + return; /* TRUE */ + + case IDM_OPTIONS: + if (isblocking) + return; /* TRUE */ + opts_dialog(hwnd); + + return; /* TRUE */ + + case IDM_HELP_INDEX: + WinHelp(hwnd, KERBEROS_HLP, HELP_INDEX, 0); + + return; /* TRUE */ + + case IDM_ABOUT: + ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + if (isblocking) + return; /* TRUE */ + +#ifdef KRB4 + strcpy(copyright, " Kerberos 4 for Windows "); +#endif +#ifdef KRB5 + strcpy(copyright, " Kerberos V5 for Windows "); +#endif +#ifdef _WIN32 + strncat(copyright, "32-bit\n", sizeof(copyright) - 1 - strlen(copyright)); +#else + strncat(copyright, "16-bit\n", sizeof(copyright) - 1 - strlen(copyright)); +#endif + strncat(copyright, "\n Version 1.12\n\n", + sizeof(copyright) - 1 - strlen(copyright)); +#ifdef ORGANIZATION + strncat(copyright, " For information, contact:\n", + sizeof(copyright) - 1 - strlen(copyright)); + strncat(copyright, ORGANIZATION, sizeof(copyright) - 1 - strlen(copyright)); +#endif + MessageBox(hwnd, copyright, KWIN_DIALOG_NAME, MB_OK); + + return; /* TRUE */ + } + + return; /* FALSE */ +} + + +/* + * Function: Process WM_SYSCOMMAND messages by setting + * the focus to the password or name on restore. + */ +static void +kwin_syscommand(HWND hwnd, UINT cmd, int x, int y) +{ + if (cmd == SC_RESTORE) + kwin_set_default_focus(hwnd); + + if (cmd == SC_CLOSE) { + SendMessage(hwnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EXIT, 0, 0)); + return; + } + + FORWARD_WM_SYSCOMMAND(hwnd, cmd, x, y, DefDlgProc); +} + + +/* + * Function: Process WM_PAINT messages by displaying an + * informative icon when we are iconic. + */ +static void +kwin_paint(HWND hwnd) +{ + HDC hdc; + PAINTSTRUCT ps; + HICON hicon; + time_t expiration = 0; + time_t dt; + char buf[20]; + RECT r; +#ifdef KRB4 + int i; + int ncred; + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + CREDENTIALS c; +#endif +#ifdef KRB5 + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds c; + int n; + char *service; +#endif + + if (!IsIconic(hwnd)) { + FORWARD_WM_PAINT(hwnd, DefDlgProc); + return; + } + +#ifdef KRB4 + ncred = krb_get_num_cred(); + + for (i = 1; i <= ncred; i++) { + krb_get_nth_cred(service, instance, realm, i); + krb_get_cred(service, instance, realm, &c); + if (_stricmp(c.service, "krbtgt") == 0) { + expiration = c.issue_date - kwin_get_epoch() + + (long)c.lifetime * 5L * 60L; + break; + } + } +#endif + +#ifdef KRB5 + code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor); + + while (code == 0) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c); + if (code) + break; + n = krb5_princ_component(k5_context, c.server, 0)->length; + service = krb5_princ_component(k5_context, c.server, 0)->data; + if (n != KRB5_TGS_NAME_SIZE) + continue; + if (memcmp(KRB5_TGS_NAME, service, KRB5_TGS_NAME_SIZE)) + continue; + expiration = c.times.endtime; + break; + + } + if (code == 0 || code == KRB5_CC_END) + krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor); +#endif + + hdc = BeginPaint(hwnd, &ps); + GetClientRect(hwnd, &r); + DefWindowProc(hwnd, WM_ICONERASEBKGND, (WPARAM)hdc, 0); + + if (expiration == 0) { + strcpy(buf, KWIN_DIALOG_NAME); + hicon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN)); + } + else { + hicon = kwin_get_icon(expiration); + dt = (expiration - time(NULL)) / 60; + + if (dt <= 0) + sprintf(buf, "%s - %s", KWIN_DIALOG_NAME, "Expired"); + else if (dt < 60) { + dt %= 60; + sprintf(buf, "%s - %ld min", KWIN_DIALOG_NAME, dt); + } + else { + dt /= 60; + sprintf(buf, "%s - %ld hr", KWIN_DIALOG_NAME, dt); + } + + buf[sizeof(buf) - 1] = '\0'; + if (dt > 1) + strncat(buf, "s", sizeof(buf) - 1 - strlen(buf)); + } + + DrawIcon(hdc, r.left, r.top, hicon); + EndPaint(hwnd, &ps); + SetWindowText(hwnd, buf); +} + + +/* + * Function: Window procedure for the Kerberos control panel dialog. + */ +LRESULT CALLBACK +kwin_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + +#if 0 + if (message == wm_kerberos_changed) { /* Message from the ccache */ + n = ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), n > 0); + + return 0; + } +#endif + + switch (message) { + HANDLE_MSG(hwnd, WM_GETMINMAXINFO, kwin_getminmaxinfo); + + HANDLE_MSG(hwnd, WM_DESTROY, kwin_destroy); + + HANDLE_MSG(hwnd, WM_MEASUREITEM, ticket_measureitem); + + HANDLE_MSG(hwnd, WM_DRAWITEM, ticket_drawitem); + + case WM_SETCURSOR: + if (isblocking) { + SetCursor(LoadCursor(NULL, IDC_WAIT)); + return TRUE; + } + break; + + HANDLE_MSG(hwnd, WM_SIZE, kwin_size); + + HANDLE_MSG(hwnd, WM_SYSCOMMAND, kwin_syscommand); + + HANDLE_MSG(hwnd, WM_TIMER, kwin_timer); + + HANDLE_MSG(hwnd, WM_PAINT, kwin_paint); + + case WM_ERASEBKGND: + if (!IsIconic(hwnd)) + break; + return 0; + + case WM_KWIN_SETNAME: + kwin_init_name(hwnd, (char *)lParam); + } + + return DefDlgProc(hwnd, message, wParam, lParam); +} + + +/* + * Function: Dialog procedure called by the dialog manager + * to process dialog specific messages. + */ +static BOOL CALLBACK +kwin_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + HANDLE_MSG(hwnd, WM_INITDIALOG, kwin_initdialog); + + HANDLE_MSG(hwnd, WM_COMMAND, kwin_command); + } + + return FALSE; +} + + +/* + * Function: Initialize the kwin dialog class. + * + * Parameters: + * hinstance - the instance to initialize + * + * Returns: TRUE if dialog class registration is sucessfully, false otherwise. + */ +static BOOL +kwin_init(HINSTANCE hinstance) +{ + WNDCLASS class; + ATOM rc; + + class.style = CS_HREDRAW | CS_VREDRAW; + class.lpfnWndProc = (WNDPROC)kwin_wnd_proc; + class.cbClsExtra = 0; + class.cbWndExtra = DLGWINDOWEXTRA; + class.hInstance = hinstance; + class.hIcon = NULL; + /* LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN)); */ + class.hCursor = NULL; + class.hbrBackground = NULL; + class.lpszMenuName = NULL; + class.lpszClassName = KWIN_DIALOG_CLASS; + + rc = RegisterClass(&class); + assert(rc); + + return rc; +} + + +/* + * Function: Initialize the KWIN application. This routine should + * only be called if no previous instance of the application + * exists. Currently it only registers a class for the kwin + * dialog type. + * + * Parameters: + * hinstance - the instance to initialize + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static BOOL +init_application(HINSTANCE hinstance) +{ + BOOL rc; + +#if 0 +#ifdef KRB4 + wm_kerberos_changed = krb_get_notification_message(); +#endif + +#ifdef KRB5 + wm_kerberos_changed = krb5_get_notification_message(); +#endif +#endif + + rc = kwin_init(hinstance); + + return rc; +} + + +/* + * Function: Quits the KWIN application. This routine should + * be called when the last application instance exits. + * + * Parameters: + * hinstance - the instance which is quitting. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static BOOL +quit_application(HINSTANCE hinstance) +{ + return TRUE; +} + + +/* + * Function: Initialize the current instance of the KWIN application. + * + * Parameters: + * hinstance - the instance to initialize + * + * ncmdshow - show flag to indicate wheather to come up minimized + * or not. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static BOOL +init_instance(HINSTANCE hinstance, int ncmdshow) +{ + WORD versionrequested; + WSADATA wsadata; + int rc; + int i; + + versionrequested = 0x0101; /* We need version 1.1 */ + rc = WSAStartup(versionrequested, &wsadata); + if (rc != 0) { + MessageBox(NULL, "Couldn't initialize Winsock library", "", + MB_OK | MB_ICONSTOP); + + return FALSE; + } + + if (versionrequested != wsadata.wVersion) { + WSACleanup(); + MessageBox(NULL, "Winsock version 1.1 not available", "", + MB_OK | MB_ICONSTOP); + + return FALSE; + } + +#ifdef KRB5 + { + krb5_error_code code; + + code = krb5_init_context(&k5_context); + if (!code) { +#if 0 /* Not needed under windows */ + krb5_init_ets(k5_context); +#endif + code = k5_init_ccache(&k5_ccache); + } + if (code) { + com_err(NULL, code, "while initializing program"); + return FALSE; + } + k5_name_from_ccache(k5_ccache); + } +#endif + + cns_load_registry(); + + /* + * Set up expiration action + */ + alert = cns_res.alert; + beep = cns_res.beep; + + /* + * ticket options + */ + forwardable = cns_res.forwardable; + noaddresses = cns_res.noaddresses; + + /* + * Load clock icons + */ + for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++) + kwin_icons[i - IDI_FIRST_CLOCK] = LoadIcon(hinstance, MAKEINTRESOURCE(i)); + +#ifdef KRB4 + krb_start_session(NULL); +#endif + + return TRUE; +} + + +/* + * Function: Quits the current instance of the KWIN application. + * + * Parameters: + * hinstance - the instance to quit. + * + * Returns: TRUE if termination was sucessfully, false otherwise. + */ +static BOOL +quit_instance(HINSTANCE hinstance) +{ + int i; + +#ifdef KRB4 + krb_end_session(NULL); +#endif + +#ifdef KRB5 /* FIXME */ + krb5_cc_close(k5_context, k5_ccache); +#endif + + WSACleanup(); + + /* + * Unload clock icons + */ + for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++) + DestroyIcon(kwin_icons[i - IDI_FIRST_CLOCK]); + + return TRUE; +} + + +/* + * Function: Main routine called on program invocation. + * + * Parameters: + * hinstance - the current instance + * + * hprevinstance - previous instance if one exists or NULL. + * + * cmdline - the command line string passed by Windows. + * + * ncmdshow - show flag to indicate wheather to come up minimized + * or not. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +int PASCAL +WinMain(HINSTANCE hinst, HINSTANCE hprevinstance, LPSTR cmdline, int ncmdshow) +{ + DLGPROC dlgproc; + HWND hwnd; + HACCEL haccel; + MSG msg; + char *p; + char buf[MAX_K_NAME_SZ + 9]; + char name[MAX_K_NAME_SZ]; + + strcpy(buf, cmdline); + action = LOGIN_AND_RUN; + name[0] = 0; + p = strtok(buf, " ,"); + + while (p != NULL) { + if (_stricmp(p, "/exit") == 0) + action = LOGIN_AND_EXIT; + else if (_stricmp(p, "/minimize") == 0) + action = LOGIN_AND_MINIMIZE; + else + strcpy(name, p); + + p = strtok(NULL, " ,"); + } + + dlgncmdshow = ncmdshow; + hinstance = hinst; + +#ifndef _WIN32 + /* + * If a previous instance of this application exits, bring it + * to the front and exit. + * + * This code is not compiled for WIN32, since hprevinstance will always + * be NULL. + */ + if (hprevinstance != NULL) { + hwnd = FindWindow(KWIN_DIALOG_CLASS, NULL); + + if (IsWindow(hwnd) && IsWindowVisible(hwnd)) { + if (GetWindowWord(hwnd, GWW_HINSTANCE) == hprevinstance) { + if (name[0]) + SendMessage(hwnd, WM_KWIN_SETNAME, 0, (LONG)name); + + ShowWindow(hwnd, ncmdshow); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + + return FALSE; + } + } + } + + if (hprevinstance == NULL) +#endif /* _WIN32 */ + + if (!init_application(hinstance)) + return FALSE; + + if (!init_instance(hinstance, ncmdshow)) + return FALSE; + +#ifdef _WIN32 + dlgproc = kwin_dlg_proc; +#else + dlgproc = (FARPROC)MakeProcInstance(kwin_dlg_proc, hinstance); + assert(dlgproc != NULL); + + if (dlgproc == NULL) + return 1; +#endif + + hwnd = CreateDialogParam(hinstance, MAKEINTRESOURCE(ID_KWIN), + HWND_DESKTOP, dlgproc, (LONG)name); + assert(hwnd != NULL); + + if (hwnd == NULL) + return 1; + haccel = LoadAccelerators(hinstance, MAKEINTRESOURCE(IDA_KWIN)); + assert(hwnd != NULL); + + while (GetMessage(&msg, NULL, 0, 0)) { + if (!TranslateAccelerator(hwnd, haccel, &msg) && + !IsDialogMessage(hwnd, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + DestroyWindow(hwnd); + +#ifndef _WIN32 + FreeProcInstance((FARPROC)dlgproc); +#endif + + cns_save_registry(); + + return 0; +} + + +#if 0 + +#define WM_ASYNC_COMPLETED (WM_USER + 1) +#define GETHOSTBYNAME_CLASS "krb_gethostbyname" +static HTASK htaskasync; /* Asynchronos call in progress */ +static BOOL iscompleted; /* True when async call is completed */ + +/* + * This routine is called to cancel a blocking hook call within + * the Kerberos library. The need for this routine arises due + * to bugs which exist in existing WINSOCK implementations. We + * blocking gethostbyname with WSAASyncGetHostByName. In order + * to cancel such an operation, this routine must be called. + * Applications may call this routine in addition to calls to + * WSACancelBlockingCall to get any sucy Async calls canceled. + * Return values are as they would be for WSACancelAsyncRequest. + */ +int +krb_cancel_blocking_call(void) +{ + if (htaskasync == NULL) + return 0; + iscompleted = TRUE; + + return WSACancelAsyncRequest(htask); +} + + +/* + * Window proceedure for temporary Windows created in + * krb_gethostbyname. Fields completion messages. + */ +LRESULT CALLBACK +krb_gethostbyname_wnd_proc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + if (message == WM_ASYNC_COMPLETED) { + iscompleted = TRUE; + return 0; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + + +/* + * The WINSOCK routine gethostbyname has a bug in both FTP and NetManage + * implementations which causes the blocking hook, if any, not to be + * called. This routine attempts to work around the problem by using + * the async routines to emulate the functionality of the synchronous + * routines + */ +struct hostent *PASCAL +krb_gethostbyname( + const char *name) +{ + HWND hwnd; + char buf[MAXGETHOSTSTRUCT]; + BOOL FARPROC blockinghook; + WNDCLASS wc; + static BOOL isregistered; + + blockinghook = WSASetBlockingHook(NULL); + WSASetBlockingHook(blockinghook); + + if (blockinghook == NULL) + return gethostbyname(name); + + if (RegisterWndClass() == NULL) + return gethostbyname(name); + + if (!isregistered) { + wc.style = 0; + wc.lpfnWndProc = gethostbyname_wnd_proc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hlibinstance; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = GETHOSTBYNAME_CLASS; + + if (!RegisterClass(&wc)) + return gethostbyname(name); + + isregistered = TRUE; + } + + hwnd = CreateWindow(GETHOSTBYNAME_CLASS, "", WS_OVERLAPPED, + -100, -100, 0, 0, HWND_DESKTOP, NULL, hlibinstance, NULL); + if (hwnd == NULL) + return gethostbyname(name); + + htaskasync = + WSAAsyncGetHostByName(hwnd, WM_ASYNC_COMPLETED, name, buf, sizeof(buf)); + b = blockinghook(NULL); +} + +#endif /* if 0 */ + +#ifdef KRB5 + +/* + * Function: destroys all tickets in a k5 ccache + * + * Returns: K5 error code (0 == success) + */ +krb5_error_code +k5_dest_tkt(void) +{ + krb5_error_code code; + krb5_principal princ; + + if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ)) { + com_err(NULL, code, "while retrieving principal name"); + return code; + } + + code = krb5_cc_initialize(k5_context, k5_ccache, princ); + if (code != 0) { + com_err(NULL, code, "when re-initializing cache"); + krb5_free_principal(k5_context, princ); + return code; + } + + krb5_free_principal(k5_context, princ); + + return code; +} + +/* + * + * k5_get_num_cred + * + * Returns: number of creds in the credential cache, -1 on error + * + */ +int +k5_get_num_cred(int verbose) +{ + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds c; + int ncreds = 0; + + /* Turn off OPENCLOSE and leave open while we use ccache */ + if (code = krb5_cc_set_flags(k5_context, k5_ccache, 0)) { + if (code == KRB5_FCC_NOFILE) + return 0; + if (verbose) + com_err(NULL, code, + "while setting cache flags (ticket cache %s)", + krb5_cc_get_name(k5_context, k5_ccache)); + return -1; + } + + if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) { + if (verbose) + com_err(NULL, code, "while starting to retrieve tickets."); + return -1; + } + + while (1) { /* Loop and get creds */ + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c); + if (code) + break; + ++ncreds; + } + + if (code != KRB5_CC_END) { /* Error while looping??? */ + if (verbose) + com_err(NULL, code, "while retrieving a ticket."); + return -1; + } + + if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor)) { + if (verbose) + com_err(NULL, code, "while closing ccache."); + } else if (code = krb5_cc_set_flags(k5_context, k5_ccache, + KRB5_TC_OPENCLOSE)) { + if (verbose) + com_err(NULL, code, "while closing ccache."); + } + + return ncreds; +} + +static int +k5_get_num_cred2() +{ + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds c; + int ncreds = 0; + + code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor); + if (code == KRB5_FCC_NOFILE) + return 0; + + while (1) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c); + if (code) + break; + ++ncreds; + } + + if (code == KRB5_CC_END) + krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor); + + return ncreds; +} + + +/* + * Function: Parses fullname into name and realm + * + * Parameters: + * name - buffer filled with name of user + * realm - buffer filled with realm of user + * fullname - string in form name.instance@realm + * + * Returns: 0 + */ +int +k5_kname_parse(char *name, char *realm, char *fullname) +{ + char *ptr; /* For parsing */ + + ptr = strchr(fullname, '@'); /* Name, realm separator */ + + if (ptr != NULL) /* Get realm */ + strcpy(realm, ptr + 1); + else + *realm = '\0'; + + if (ptr != NULL) { /* Get the name */ + strncpy(name, fullname, ptr - fullname); + name[ptr - fullname] = '\0'; + } else + strcpy(name, fullname); + + ptr = strchr(name, '.'); /* K4 compatability */ + if (ptr != NULL) + *ptr = '\0'; + + return 0; +} + + +/* + * Function: Initializes ccache and catches illegal caches such as + * bad format or no permissions. + * + * Parameters: + * ccache - credential cache structure to use + * + * Returns: krb5_error_code + */ +krb5_error_code +k5_init_ccache(krb5_ccache *ccache) +{ + krb5_error_code code; + krb5_principal princ; + FILE *fp; + + code = krb5_cc_default(k5_context, ccache); /* Initialize the ccache */ + if (code) + return code; + + code = krb5_cc_get_principal(k5_context, *ccache, &princ); + if (code == KRB5_FCC_NOFILE) { /* Doesn't exist yet */ + fp = fopen(krb5_cc_get_name(k5_context, *ccache), "w"); + if (fp == NULL) /* Can't open it */ + return KRB5_FCC_PERM; + fclose (fp); + } + + if (code) { /* Bad, delete and try again */ + remove(krb5_cc_get_name(k5_context, *ccache)); + code = krb5_cc_get_principal(k5_context, *ccache, &princ); + if (code == KRB5_FCC_NOFILE) /* Doesn't exist yet */ + return 0; + if (code) + return code; + } + + /* krb5_free_principal(k5_context, princ); */ + + return 0; +} + + +/* + * + * Function: Reads the name and realm out of the ccache. + * + * Parameters: + * ccache - credentials cache to get info from + * + * name - buffer to hold user name + * + * realm - buffer to hold the realm + * + * + * Returns: TRUE if read names, FALSE if not + * + */ +int +k5_name_from_ccache(krb5_ccache k5_ccache) +{ + krb5_error_code code; + krb5_principal princ; + char name[ANAME_SZ]; + char realm[REALM_SZ]; + char *defname; + + if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ)) + return FALSE; + + code = krb5_unparse_name(k5_context, princ, &defname); + if (code) { + return FALSE; + } + + k5_kname_parse(name, realm, defname); /* Extract the components */ + strcpy(cns_res.name, name); + strcpy(cns_res.realm, realm); + + return TRUE; +} +#endif /* KRB5 */ diff --git a/krb5-1-6/src/windows/cns/cns.h b/krb5-1-6/src/windows/cns/cns.h new file mode 100644 index 000000000..cdd6da3b3 --- /dev/null +++ b/krb5-1-6/src/windows/cns/cns.h @@ -0,0 +1,249 @@ +/* + * cns.h + * + * Public Domain -- written by Cygnus Support. + */ + +/* Only one time, please */ +#ifndef KWIN_DEFS +#define KWIN_DEFS + +#if !defined(KRB4) && !defined(KRB5) +#define KRB5 +#endif + +#ifndef RC_INVOKED + +#ifdef KRB4 +#include "mit-copyright.h" +#include "krb.h" +#include "kadm.h" +#include "org.h" +#endif + +#ifdef KRB5 +#include "winsock.h" +#include "krb5.h" +#include "krbini.h" +#include "com_err.h" + +#define DEFAULT_TKT_LIFE 120 /* In 5 minute units */ +#define ANAME_SZ 40 +#define REALM_SZ 40 +#define SNAME_SZ 40 +#define INST_SZ 40 +#define MAX_KPW_LEN 128 +/* include space for '.' and '@' */ +#define MAX_K_NAME_SZ (ANAME_SZ + INST_SZ + REALM_SZ + 2) +#ifdef CYGNUS +#define ORGANIZATION "Cygnus Solutions\n(800)CYGNUS-1\nhttp://www.cygnus.com\ninfo@cygnus.com" +#endif +#define CREDENTIALS char +#endif + +/* + * Constants + */ +#define BLOCK_MAX_SEC 30 /* Blocking timeout duration */ +#define KWIN_UPDATE_PERIOD 30000 /* Every 30 seconds update the screen */ +#define TIME_BUFFER 300 /* Pop-up time buffer in seconds */ +#define WM_KWIN_SETNAME (WM_USER+100) /* Sets the name fields in the dialog */ + +#endif /* RC_INVOKED */ + +/* + * Menu items + */ +#define FILE_MENU_ITEMS 3 +#define FILE_MENU_MAX_LOGINS 5 +#define IDM_KWIN 1000 +#define IDM_OPTIONS 1001 +#define IDM_EXIT 1002 +#define IDM_FIRST_LOGIN 1003 + +#define IDM_HELP_INDEX 1020 +#define IDM_ABOUT 1021 + +/* + * Accelerator + */ +#define IDA_KWIN 2000 + +/* + * Dialog and dialog item ids + */ +#define KWIN_DIALOG_CLASS "KERBEROS" /* class for kerberos dialog */ +#define KWIN_DIALOG_NAME "Krb5" /* name for kerberos dialog */ + +#define ID_KWIN 100 /* the main kerberos dialog */ +#define IDD_KWIN_FIRST 101 +#define IDD_TICKET_LIST_TITLE 101 +#define IDD_TICKET_LIST 102 + +#ifdef KRB4 + +#define IDD_MIN_TITLE 103 +#define IDD_LOGIN_NAME_TITLE 103 +#define IDD_LOGIN_INSTANCE_TITLE 104 +#define IDD_LOGIN_REALM_TITLE 105 +#define IDD_LOGIN_PASSWORD_TITLE 106 +#define IDD_MAX_TITLE 106 + +#define IDD_MIN_EDIT 107 +#define IDD_LOGIN_NAME 107 +#define IDD_LOGIN_INSTANCE 108 +#define IDD_LOGIN_REALM 109 +#define IDD_LOGIN_PASSWORD 110 +#define IDD_MAX_EDIT 110 + +#endif + +#ifdef KRB5 + +#define IDD_MIN_TITLE 103 +#define IDD_LOGIN_NAME_TITLE 103 +#define IDD_LOGIN_PASSWORD_TITLE 104 +#define IDD_LOGIN_REALM_TITLE 105 +#define IDD_MAX_TITLE 105 + +#define IDD_MIN_EDIT 107 +#define IDD_LOGIN_NAME 107 +#define IDD_LOGIN_PASSWORD 108 +#define IDD_LOGIN_REALM 109 +#define IDD_MAX_EDIT 109 + +#endif + +#define IDD_MIN_BUTTON 111 +#define IDD_CHANGE_PASSWORD 111 +#define IDD_TICKET_DELETE 112 +#define IDD_LOGIN 113 +#define IDD_MAX_BUTTON 113 +#define IDD_PASSWORD_CR2 114 /* For better cr handling */ + +#define IDD_KWIN_LAST 114 + + +#define ID_PASSWORD 200 +#define IDD_PASSWORD_NAME 204 +#define IDD_PASSWORD_INSTANCE 205 +#define IDD_PASSWORD_REALM 206 +#define IDD_OLD_PASSWORD 207 +#define IDD_NEW_PASSWORD1 208 +#define IDD_NEW_PASSWORD2 209 +#define IDD_PASSWORD_CR 210 + + +#define ID_OPTS 300 +#define IDD_CONF 301 +#define IDD_REALMS 302 +#define IDD_LIFETIME 303 +#define IDD_CCACHE 304 +#define IDD_ACTIONS 310 +#define IDD_BEEP 311 +#define IDD_ALERT 312 +#define IDD_TKOPT 320 +#define IDD_FORWARDABLE 321 +#define IDD_NOADDRESSES 322 + +/* + * the entire range (400 through 499) is reserved for the blasted variable + * dialog box thingie. + */ +#define ID_VARDLG 400 + +/* + * Dialog dimensions + */ +#define KWIN_MIN_WIDTH 180 +#define KWIN_MIN_HEIGHT 110 + +/* + * Icons + */ +#define IDI_KWIN 1 /* The program icon */ + +#define ICON_WIDTH 30 /* Width used with icons */ +#define ICON_HEIGHT 20 /* Height used with icons */ + +#define IDI_FIRST_CLOCK 2 +#define IDI_0_MIN 2 /* < 5 minutes left */ +#define IDI_5_MIN 3 +#define IDI_10_MIN 4 +#define IDI_15_MIN 5 +#define IDI_20_MIN 6 +#define IDI_25_MIN 7 +#define IDI_30_MIN 8 +#define IDI_35_MIN 9 +#define IDI_40_MIN 10 +#define IDI_45_MIN 11 +#define IDI_50_MIN 12 +#define IDI_55_MIN 13 +#define IDI_60_MIN 14 +#define IDI_EXPIRED 15 +#define IDI_TICKET 16 +#define IDI_LAST_CLOCK 16 +#define MAX_ICONS (IDI_LAST_CLOCK - IDI_FIRST_CLOCK + 1) + +#ifndef RC_INVOKED + +extern BOOL isblocking; +extern HFONT hfontdialog; +extern HINSTANCE hinstance; +extern BOOL alert; +extern BOOL beep; + +extern char confname[FILENAME_MAX]; + +#ifdef KRB5 +extern krb5_context k5_context; +extern krb5_ccache k5_ccache; +extern char ccname[FILENAME_MAX]; +extern BOOL forwardable; +extern BOOL noaddresses; +#endif + +/* + * Prototypes + */ + +/* in cns.c */ + +void kwin_init_name(HWND, char *); +void kwin_set_default_focus(HWND); +time_t kwin_get_epoch(void); + +/* in options.c */ +BOOL opts_initdialog(HWND, HWND, LPARAM); +void opts_command(HWND, int, HWND, UINT); +BOOL CALLBACK opts_dlg_proc(HWND, UINT, WPARAM, LPARAM); +BOOL opts_dialog(HWND); + +/* in password.c */ +BOOL change_password(HWND, char *, char *, char *, char *, char *); +void password_command(HWND, int, HWND, UINT); +BOOL password_initdialog(HWND, HWND, LPARAM); +BOOL CALLBACK password_dlg_proc(HWND, UINT, WPARAM, LPARAM); +BOOL password_dialog(HWND); + +#ifdef KRB5 +krb5_error_code k5_dest_tkt(void); +int k5_get_num_cred(int); +int k5_kname_parse(char *, char *, char *); +krb5_error_code k5_init_ccache(krb5_ccache *); +int k5_name_from_ccache(krb5_ccache); +krb5_error_code k5_change_password(HWND, krb5_context, char *, char *, char *, + char *, char **); + +#endif /* KRB5 */ + +HICON kwin_get_icon(time_t); +void trim(char *); +void start_blocking_hook(int); +void end_blocking_hook(void); +void center_dialog(HWND); +void set_dialog_font(HWND, HFONT); + +#endif /* RC_INVOKED */ + +#endif diff --git a/krb5-1-6/src/windows/cns/cns.ico b/krb5-1-6/src/windows/cns/cns.ico new file mode 100644 index 0000000000000000000000000000000000000000..645efa5ba049b95732ee60341a4603a7bd1df9cb GIT binary patch literal 1086 zcmc&yv5wO~6da#XY$@VQj}Wd-lvmM)ub@P(Tp^Us?z|F(x7&gb;1{l-J0#puLQfGY zL`AmCN-=rN?%Kl930=uc=DnTq+qdgUfCLvP%M19pPJk=cvV0WyPs%T;J@Xpzf=KxB zp+df!MC7hGD`^EhRKW9(z&Ea6v-h1vB73B6r`Ctf*T+Zs@Z`6=c{QwddnBI@D(#Md zj7U!-l7JQ%J+?r5O_aPk!EX%SA;j37Hb;@&VKeSe6ierF{i|AOzC5emyZ{?JF^di}3;){qO-cQHMxnB?Bv}o}>c~Mm~Q>oyo&s-7; z!!WRq9(hZ7>rj}z#XO7Rz0uGkA6XMi$RULXTST2DJ8ziwdC_DGLYmvqIwex2rzw;q zw`UE7H8AqG!RDm2a|-?-45jtN4GDBEE*@Et7mhom_xD>>TEvDeR#UjFbKl^F^-Z%~ zUDj0`l-b*?Z|dqtJ2{b-uHc7SHB|7;B?#8_1uom=w2;&?wsB(cwvlI tt9crSIOnkB#u)NA-RIoVwFNJX0xJJx3hzlZ6IQiY|6>`9VESMG^FQ(KGx`7k literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/cns_reg.c b/krb5-1-6/src/windows/cns/cns_reg.c new file mode 100644 index 000000000..92255fe4f --- /dev/null +++ b/krb5-1-6/src/windows/cns/cns_reg.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1997 Cygnus Solutions + * + * Author: Michael Graff + */ + +#include +#include +#include +#include + +#include "cns.h" +#include "cns_reg.h" + +#include "../lib/registry.h" + +cns_reg_t cns_res; /* yes, a global. Sue me. */ + +/* + * function to load all the data we will want from the registry. If the + * registry data cannot be found this function will initialize a default + * environment. + */ +void +cns_load_registry(void) +{ + char tmp[1024]; + DWORD tdw; + char *ts; + HKEY key; + int i; + + /* + * Set up reasonable default values. These will all be overwritten if + * the registry is successfully opened. + */ + cns_res.name[0] = '\0'; + cns_res.realm[0] = '\0'; + cns_res.x = 0; + cns_res.y = 0; + cns_res.cx = 0; + cns_res.cy = 0; + + cns_res.alert = 0; + cns_res.beep = 0; + cns_res.lifetime = DEFAULT_TKT_LIFE * 5; + cns_res.forwardable = 1; + cns_res.noaddresses = 0; + + for (i = 1 ; i < FILE_MENU_MAX_LOGINS ; i++) + cns_res.logins[i][0] = '\0'; + + /* + * by default, allow the user to override the config file location and NOT the + * cred cache name. + */ + cns_res.conf_override = 1; + cns_res.cc_override = 0; + + { + char *s; + s = krb5_cc_default_name(k5_context); + + strcpy(cns_res.def_ccname, s); + } + + cns_res.def_confname[0] = '\0'; + + /* + * If the system has these keys in the registry, do not allow the user to + * override the config file and ccache locations. + */ + key = registry_open(HKEY_LOCAL_MACHINE, KERBNET_BASE, KEY_READ); + if (key != INVALID_HANDLE_VALUE) { + if (registry_string_get(key, KERBNET_HOME, &ts) == 0) { + cns_res.conf_override = 0; + cns_res.def_confname[sizeof(cns_res.def_confname) - 1]; + strncpy(cns_res.def_confname, ts, + sizeof(cns_res.def_confname) - 1); + strncat(cns_res.def_confname, "\\etc\\krb5.conf", + sizeof(cns_res.def_confname) - 1 - + strlen(cns_res.def_confname)); + free(ts); + } + + if (registry_string_get(key, "ccname", &ts) == 0) { + cns_res.cc_override = 0; + strcpy(cns_res.def_ccname, ts); + free(ts); + } + } + + /* + * Try to open the registry. If we succeed, read the last used values from there. If we + * do not get the registry open simply return. + */ + key = registry_open(HKEY_CURRENT_USER, KERBNET_CNS_BASE, KEY_ALL_ACCESS); + + if (key == INVALID_HANDLE_VALUE) + return; + + if (registry_dword_get(key, "x", &tdw) == 0) + cns_res.x = tdw; + + if (registry_dword_get(key, "y", &tdw) == 0) + cns_res.y = tdw; + + if (registry_dword_get(key, "cx", &tdw) == 0) + cns_res.cx = tdw; + + if (registry_dword_get(key, "cy", &tdw) == 0) + cns_res.cy = tdw; + + if (registry_dword_get(key, "lifetime", &tdw) == 0) + cns_res.lifetime = tdw; + + if (registry_dword_get(key, "forwardable", &tdw) == 0) + cns_res.forwardable = tdw; + + if (registry_dword_get(key, "noaddresses", &tdw) == 0) + cns_res.noaddresses = tdw; + + if (registry_dword_get(key, "alert", &tdw) == 0) + cns_res.alert = tdw; + + if (registry_dword_get(key, "beep", &tdw) == 0) + cns_res.beep = tdw; + + if (registry_string_get(key, "name", &ts) == 0) { + strcpy(cns_res.name, ts); + free(ts); + } + + if (registry_string_get(key, "realm", &ts) == 0) { + strcpy(cns_res.realm, ts); + free(ts); + } + + if (cns_res.conf_override && (registry_string_get(key, "confname", &ts) == 0)) { + strcpy(cns_res.confname, ts); + free(ts); + } else + strcpy(cns_res.confname, cns_res.def_confname); + + if (cns_res.cc_override && (registry_string_get(key, "ccname", &ts) == 0)) { + strcpy(cns_res.ccname, ts); + free(ts); + } else + strcpy(cns_res.ccname, cns_res.def_ccname); + + for (i = 0 ; i < FILE_MENU_MAX_LOGINS ; i++) { + sprintf(tmp, "login_%02d", i); + if (registry_string_get(key, tmp, &ts) == 0) { + strcpy(cns_res.logins[i], ts); + free(ts); + } + } + + registry_close(key); +} + +/* + * save all the registry data, creating the keys if needed. + */ +void +cns_save_registry(void) +{ + char tmp[1024]; + HKEY key; + int i; + + /* + * First, create the heirachy... This is gross, but functional + */ + key = registry_key_create(HKEY_CURRENT_USER, CYGNUS_SOLUTIONS, KEY_WRITE); + if (key == INVALID_HANDLE_VALUE) + return; + + key = registry_key_create(HKEY_CURRENT_USER, KERBNET_SANS_VERSION, KEY_WRITE); + if (key == INVALID_HANDLE_VALUE) + return; + registry_close(key); + + key = registry_key_create(HKEY_CURRENT_USER, KERBNET_BASE, KEY_WRITE); + if (key == INVALID_HANDLE_VALUE) + return; + registry_close(key); + + key = registry_key_create(HKEY_CURRENT_USER, KERBNET_CNS_BASE, KEY_WRITE); + if (key == INVALID_HANDLE_VALUE) + return; + + registry_dword_set(key, "x", cns_res.x); + registry_dword_set(key, "y", cns_res.y); + registry_dword_set(key, "cx", cns_res.cx); + registry_dword_set(key, "cy", cns_res.cy); + + registry_dword_set(key, "alert", cns_res.alert); + registry_dword_set(key, "beep", cns_res.beep); + registry_dword_set(key, "lifetime", cns_res.lifetime); + registry_dword_set(key, "forwardable", cns_res.forwardable); + registry_dword_set(key, "noaddresses", cns_res.noaddresses); + + registry_string_set(key, "name", cns_res.name); + registry_string_set(key, "realm", cns_res.realm); + + if (cns_res.conf_override) + { + if (strcmp(cns_res.confname, cns_res.def_confname)) + registry_string_set(key, "confname", cns_res.confname); + else + registry_value_delete(key, "confname"); + } + + if (cns_res.cc_override) + { + if (strcmp(cns_res.ccname, cns_res.def_ccname)) + registry_string_set(key, "ccname", cns_res.ccname); + else + registry_value_delete(key, "ccname"); + } + + for (i = 0 ; i < FILE_MENU_MAX_LOGINS ; i++) + if (cns_res.logins[i][0] != '\0') { + sprintf(tmp, "login_%02d", i); + registry_string_set(key, tmp, cns_res.logins[i]); + } + + registry_close(key); +} diff --git a/krb5-1-6/src/windows/cns/cns_reg.h b/krb5-1-6/src/windows/cns/cns_reg.h new file mode 100644 index 000000000..9ebed4fe8 --- /dev/null +++ b/krb5-1-6/src/windows/cns/cns_reg.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1997 Cygnus Solutions + * + * Author: Michael Graff + */ + +#include + +typedef struct cns_reg { + DWORD x; /* default dialog size */ + DWORD y; + DWORD cx; + DWORD cy; + DWORD lifetime; /* ticket lifetime */ + DWORD beep; /* beep on expire/warning? */ + DWORD alert; /* alert (deiconify) when tix expired? */ + DWORD forwardable; /* get forwardable tickets? */ + DWORD conf_override; /* allow changing of confname */ + DWORD cc_override; /* allow changing of ccname */ + DWORD noaddresses; /* Don't require address in tickets */ + char name[MAX_K_NAME_SZ]; /* last user used */ + char realm[MAX_K_NAME_SZ]; /* last realm used */ + char confname[FILENAME_MAX]; + char ccname[FILENAME_MAX]; + char def_confname[FILENAME_MAX]; + char def_ccname[FILENAME_MAX]; + char logins[FILE_MENU_MAX_LOGINS][MAX_K_NAME_SZ]; +} cns_reg_t; + +extern cns_reg_t cns_res; + +void cns_load_registry(void); +void cns_save_registry(void); diff --git a/krb5-1-6/src/windows/cns/cnsres4.rc b/krb5-1-6/src/windows/cns/cnsres4.rc new file mode 100644 index 000000000..77e21e028 --- /dev/null +++ b/krb5-1-6/src/windows/cns/cnsres4.rc @@ -0,0 +1,108 @@ +#include + +#define KRB4 +#include "cns.h" + +IDI_KWIN ICON PRELOAD cns.ico +IDI_0_MIN ICON PRELOAD clock00.ico +IDI_5_MIN ICON PRELOAD clock05.ico +IDI_10_MIN ICON PRELOAD clock10.ico +IDI_15_MIN ICON PRELOAD clock15.ico +IDI_20_MIN ICON PRELOAD clock20.ico +IDI_25_MIN ICON PRELOAD clock25.ico +IDI_30_MIN ICON PRELOAD clock30.ico +IDI_35_MIN ICON PRELOAD clock35.ico +IDI_40_MIN ICON PRELOAD clock40.ico +IDI_45_MIN ICON PRELOAD clock45.ico +IDI_50_MIN ICON PRELOAD clock50.ico +IDI_55_MIN ICON PRELOAD clock55.ico +IDI_60_MIN ICON PRELOAD clock60.ico +IDI_EXPIRED ICON PRELOAD clockexp.ico +IDI_TICKET ICON PRELOAD clocktkt.ico + +IDM_KWIN MENU PRELOAD +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Options...", IDM_OPTIONS + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_EXIT + END + + POPUP "&Help" + BEGIN + MENUITEM "&Index\tF1", IDM_HELP_INDEX + MENUITEM SEPARATOR + MENUITEM "&About Kerberos...", IDM_ABOUT + END +END + +IDA_KWIN ACCELERATORS PRELOAD +BEGIN + VK_F1, IDM_HELP_INDEX, VIRTKEY +END + +ID_KWIN DIALOG PRELOAD MOVEABLE DISCARDABLE 0, 0, 276, 114 +STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX +CLASS KWIN_DIALOG_CLASS +CAPTION KWIN_DIALOG_NAME +MENU IDM_KWIN +FONT 8, "Arial" +BEGIN + CONTROL " Start Time End Time Ticket", IDD_TICKET_LIST_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 16, 7, 240, 8 + CONTROL "", IDD_TICKET_LIST, "LISTBOX", LBS_NOTIFY | LBS_DISABLENOSCROLL | LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL, 8, 18, 261, 52 + CONTROL "&Name", IDD_LOGIN_NAME_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 6, 69, 27, 8 + CONTROL "&Instance", IDD_LOGIN_INSTANCE_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 73, 69, 36, 8 + CONTROL "&Realm", IDD_LOGIN_REALM_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 140, 69, 26, 8 + CONTROL "&Password", IDD_LOGIN_PASSWORD_TITLE, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 207, 69, 36, 8 + CONTROL "", IDD_LOGIN_NAME, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 6, 79, 62, 12 + CONTROL "", IDD_LOGIN_INSTANCE, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 73, 79, 62, 12 + CONTROL "", IDD_LOGIN_REALM, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_UPPERCASE | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 140, 79, 62, 12 + CONTROL "", IDD_LOGIN_PASSWORD, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 207, 79, 62, 12 + + CONTROL "&Change Password...", IDD_CHANGE_PASSWORD, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 6, 96, 74, 14 + CONTROL "&Delete", IDD_TICKET_DELETE, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 122, 96, 52, 14 + CONTROL "&Login", IDD_LOGIN, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 216, 96, 52, 14 + CONTROL "", IDD_PASSWORD_CR2, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, 5000, 5000, 0, 0 +END + +ID_PASSWORD DIALOG 96, 50, 143, 129 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Change Password" +FONT 8, "Arial" +BEGIN + CONTROL "&Name:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 9, 53, 8 + CONTROL "", IDD_PASSWORD_NAME, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_GROUP | WS_TABSTOP, 61, 6, 76, 12 + CONTROL "&Instance:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 26, 53, 8 + CONTROL "", IDD_PASSWORD_INSTANCE, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 23, 76, 12 + CONTROL "&Realm:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 43, 53, 8 + CONTROL "", IDD_PASSWORD_REALM, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 40, 76, 12 + CONTROL "&Old Password:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 60, 53, 8 + CONTROL "", IDD_OLD_PASSWORD, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 57, 76, 12 + CONTROL "&New Password:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 77, 53, 8 + CONTROL "", IDD_NEW_PASSWORD1, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 74, 76, 12 + CONTROL "&New Password:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 94, 53, 8 + CONTROL "", IDD_NEW_PASSWORD2, "EDIT", ES_LEFT | ES_AUTOHSCROLL | ES_PASSWORD | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 61, 91, 76, 12 + CONTROL "", IDD_PASSWORD_CR, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, 5000, 5000, 0, 0 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 13, 110, 52, 14 + CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 77, 110, 52, 14 +END + +ID_OPTS DIALOG 97, 52, 148, 107 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Kerberos Options" +FONT 8, "Arial" +BEGIN + CONTROL "&Conf file:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 9, 40, 8 + CONTROL "", IDD_CONF, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 60, 6, 82, 12 + CONTROL "&Realms file:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 26, 40, 8 + CONTROL "", IDD_REALMS, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 60, 23, 82, 12 + CONTROL "&Ticket lifetime:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 43, 53, 8 + CONTROL "", IDD_LIFETIME, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 60, 40, 20, 12 + CONTROL "minutes", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 85, 43, 46, 8 + CONTROL "Action when login expires", 209, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 56, 138, 23 + CONTROL "&Alert ", IDD_ALERT, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 31, 65, 28, 12 + CONTROL "&Beep", IDD_BEEP, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 80, 65, 39, 12 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 17, 87, 52, 14 + CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 81, 87, 52, 14 +END diff --git a/krb5-1-6/src/windows/cns/cnsres5.rc b/krb5-1-6/src/windows/cns/cnsres5.rc new file mode 100644 index 000000000..d398078e3 --- /dev/null +++ b/krb5-1-6/src/windows/cns/cnsres5.rc @@ -0,0 +1,215 @@ +//Microsoft Developer Studio generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "cns.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_KWIN ICON PRELOAD DISCARDABLE "cns.ico" +IDI_0_MIN ICON PRELOAD DISCARDABLE "clock00.ico" +IDI_5_MIN ICON PRELOAD DISCARDABLE "clock05.ico" +IDI_10_MIN ICON PRELOAD DISCARDABLE "clock10.ico" +IDI_15_MIN ICON PRELOAD DISCARDABLE "clock15.ico" +IDI_20_MIN ICON PRELOAD DISCARDABLE "clock20.ico" +IDI_25_MIN ICON PRELOAD DISCARDABLE "clock25.ico" +IDI_30_MIN ICON PRELOAD DISCARDABLE "clock30.ico" +IDI_35_MIN ICON PRELOAD DISCARDABLE "clock35.ico" +IDI_40_MIN ICON PRELOAD DISCARDABLE "clock40.ico" +IDI_45_MIN ICON PRELOAD DISCARDABLE "clock45.ico" +IDI_50_MIN ICON PRELOAD DISCARDABLE "clock50.ico" +IDI_55_MIN ICON PRELOAD DISCARDABLE "clock55.ico" +IDI_60_MIN ICON PRELOAD DISCARDABLE "clock60.ico" +IDI_EXPIRED ICON PRELOAD DISCARDABLE "clockexp.ico" +IDI_TICKET ICON PRELOAD DISCARDABLE "clocktkt.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDM_KWIN MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Options...", IDM_OPTIONS + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&Index\tF1", IDM_HELP_INDEX + MENUITEM SEPARATOR + MENUITEM "&About Kerberos...", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDA_KWIN ACCELERATORS PRELOAD MOVEABLE PURE +BEGIN + VK_F1, IDM_HELP_INDEX, VIRTKEY +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ID_KWIN DIALOG PRELOAD DISCARDABLE 0, 0, 336, 115 +STYLE WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +#ifdef CYGNUS +CAPTION "KerbNet" +#else +CAPTION "Kerberos" +#endif +MENU IDM_KWIN +CLASS "KERBEROS" +FONT 8, "Arial" +BEGIN + CONTROL " Start Time End Time Ticket", + IDD_TICKET_LIST_TITLE,"Static",SS_LEFTNOWORDWRAP | + WS_GROUP,16,7,311,8 + LISTBOX IDD_TICKET_LIST,8,18,319,52,LBS_OWNERDRAWFIXED | + LBS_DISABLENOSCROLL | WS_VSCROLL + LTEXT "&Name",IDD_LOGIN_NAME_TITLE,6,69,27,8 + LTEXT "&Password",IDD_LOGIN_PASSWORD_TITLE,125,69,42,8 + LTEXT "&Realm",IDD_LOGIN_REALM_TITLE,239,69,26,8 + EDITTEXT IDD_LOGIN_NAME,6,79,84,12,ES_AUTOHSCROLL + EDITTEXT IDD_LOGIN_PASSWORD,126,78,84,12,ES_PASSWORD | + ES_AUTOHSCROLL + EDITTEXT IDD_LOGIN_REALM,239,79,84,12,ES_AUTOHSCROLL + PUSHBUTTON "&Change Password...",IDD_CHANGE_PASSWORD,6,96,84,14 + PUSHBUTTON "&Delete",IDD_TICKET_DELETE,141,96,52,14 + DEFPUSHBUTTON "&Login",IDD_LOGIN,271,96,52,14 + PUSHBUTTON "",IDD_PASSWORD_CR2,5000,5000,6,6,NOT WS_TABSTOP +END + +ID_PASSWORD DIALOG DISCARDABLE 96, 50, 143, 112 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Change Password" +FONT 8, "Arial" +BEGIN + LTEXT "&Name:",-1,5,9,53,8,NOT WS_GROUP + EDITTEXT IDD_PASSWORD_NAME,61,6,76,12,ES_AUTOHSCROLL | WS_GROUP + LTEXT "&Realm:",-1,5,26,53,8,NOT WS_GROUP + EDITTEXT IDD_PASSWORD_REALM,61,23,76,12,ES_AUTOHSCROLL + LTEXT "&Old Password:",-1,5,43,53,8,NOT WS_GROUP + EDITTEXT IDD_OLD_PASSWORD,61,40,76,12,ES_PASSWORD | + ES_AUTOHSCROLL + LTEXT "&New Password:",-1,5,60,53,8,NOT WS_GROUP + EDITTEXT IDD_NEW_PASSWORD1,61,57,76,12,ES_PASSWORD | + ES_AUTOHSCROLL + LTEXT "&New Password:",-1,5,77,53,8,NOT WS_GROUP + EDITTEXT IDD_NEW_PASSWORD2,61,74,76,12,ES_PASSWORD | + ES_AUTOHSCROLL + PUSHBUTTON "",IDD_PASSWORD_CR,5000,5000,0,0,NOT WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,13,93,52,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,77,93,52,14 +END + +ID_OPTS DIALOG DISCARDABLE 97, 52, 169, 138 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +#ifdef CYGNUS +CAPTION "KerbNet Options" +#else +CAPTION "Kerberos Options" +#endif +FONT 8, "Arial" +BEGIN + LTEXT "&Config file:",-1,5,9,40,8,NOT WS_GROUP + EDITTEXT IDD_CONF,70,6,92,12,ES_AUTOHSCROLL + LTEXT "Cre&dential cache:",-1,5,26,58,8,NOT WS_GROUP + EDITTEXT IDD_CCACHE,70,23,92,12,ES_AUTOHSCROLL + LTEXT "&Ticket lifetime:",-1,5,43,53,8,NOT WS_GROUP + EDITTEXT IDD_LIFETIME,70,40,32,12,ES_AUTOHSCROLL + LTEXT "minutes",-1,109,42,46,8,NOT WS_GROUP + GROUPBOX "Action when login expires",IDD_ACTIONS,5,56,158,23, + WS_GROUP + CONTROL "&Alert ",IDD_ALERT,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,41,65,28,12 + CONTROL "&Beep",IDD_BEEP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 95,65,39,12 + GROUPBOX "Ticket options",IDD_TKOPT,5,86,158,23,WS_GROUP + CONTROL "&Forwardable",IDD_FORWARDABLE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,25,95,65,12 + CONTROL "&NoAddresses",IDD_NOADDRESSES,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,90,95,65,12 + DEFPUSHBUTTON "OK",IDOK,19,117,52,14 + PUSHBUTTON "Cancel",IDCANCEL,95,117,52,14 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""cns.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + +#include "..\version.rc" diff --git a/krb5-1-6/src/windows/cns/debug.c b/krb5-1-6/src/windows/cns/debug.c new file mode 100644 index 000000000..d35e64ed5 --- /dev/null +++ b/krb5-1-6/src/windows/cns/debug.c @@ -0,0 +1,91 @@ +#ifdef DEBUG + +#include +#include +#include +#include + +void +OutputHeading(const char *explanation) +{ + _RPT1(_CRT_WARN, + "\n\n%s:\n*********************************\n", explanation ); +} + +/* + * The following macros set and clear, respectively, given bits + * of the C runtime library debug flag, as specified by a bitmask. + */ +#define SET_CRT_DEBUG_FIELD(a) \ + _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) +#define CLEAR_CRT_DEBUG_FIELD(a) \ + _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) + +_CrtMemState s1; +_CrtMemState s2; +_CrtMemState s3; +static _CrtMemState *ss1 = NULL; +static _CrtMemState *ss2 = NULL; + +void debug_init(); + +void +debug_check() +{ + _CrtMemState *temp; + + OutputHeading("Checking memory..."); + + if (ss1 == NULL) { + debug_init(); + ss1 = &s1; + ss2 = &s2; + } + + _CrtCheckMemory(); + + /* _CrtMemDumpAllObjectsSince( NULL ); */ + + _CrtMemCheckpoint( &s2 ); + + if ( _CrtMemDifference( &s3, &s1, &s2 ) ) + _CrtMemDumpStatistics( &s3 ); + + /* _CrtDumpMemoryLeaks(); */ + + /* + * swap the snapshots around + */ + temp = ss1; + ss1 = ss2; + ss2 = temp; +} + +void +debug_init() +{ + /* Send all reports to STDOUT */ + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); + + _CrtMemCheckpoint( &s1 ); + + /* + * Set the debug-heap flag so that freed blocks are kept on the + * linked list, to catch any inadvertent use of freed memory + */ + SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF ); + + + /* + * Set the debug-heap flag so that memory leaks are reported when + * the process terminates. Then, exit. + */ + SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF ); +} +#endif /* DEBUG */ + diff --git a/krb5-1-6/src/windows/cns/heap.c b/krb5-1-6/src/windows/cns/heap.c new file mode 100644 index 000000000..46d39df0b --- /dev/null +++ b/krb5-1-6/src/windows/cns/heap.c @@ -0,0 +1,33 @@ +#include +#include + +void heapdump( void ) +{ + _HEAPINFO hinfo; + int heapstatus; + hinfo._pentry = NULL; + while( ( heapstatus = _heapwalk( &hinfo ) ) == _HEAPOK ) + { printf( "%6s block at %Fp of size %4.4X\n", + ( hinfo._useflag == _USEDENTRY ? "USED" : "FREE" ), + hinfo._pentry, hinfo._size ); + } + + switch( heapstatus ) + { + case _HEAPEMPTY: + printf( "OK - empty heap\n" ); + break; + case _HEAPEND: + printf( "OK - end of heap\n" ); + break; + case _HEAPBADPTR: + printf( "ERROR - bad pointer to heap\n" ); + break; + case _HEAPBADBEGIN: + printf( "ERROR - bad start of heap\n" ); + break; + case _HEAPBADNODE: + printf( "ERROR - bad node in heap\n" ); + break; + } +} diff --git a/krb5-1-6/src/windows/cns/kerbnet.doc b/krb5-1-6/src/windows/cns/kerbnet.doc new file mode 100644 index 0000000000000000000000000000000000000000..161b3c31eabb25652b3a0009cadf4f8f354c03cb GIT binary patch literal 22528 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 S#UH}{bH4S*pB?-@&i@YzaoD5) literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/cns/kerbnet.hlp b/krb5-1-6/src/windows/cns/kerbnet.hlp new file mode 100644 index 0000000000000000000000000000000000000000..c25fafcd5b5d4e139a611ab196bd7202605625b7 GIT binary patch literal 16334 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',`IDH_Glossary')") +; + + +[FILES] +; The files section is where you specify to the Help Compiler which +; Rich Text Format (.RTF) (your help source) files will be used in the +; Help system. RoboHELP generates and maintains the main .RTF +; file for your Help System. If you desire to have multiple .RTF files, +; simply add the additonal names to the [FILES] section. + +KERBNET.RTF +[ALIAS] +; The Alias section allows you to set up aliases for context strings +; in your help system. +; +; Brief example: +; +; IDH_UserID = IDH_RoboGenerated_Id +; IDH_WMP_MenuID = IDH_RoboGenerated_Id +; IDH_Any = IDH_AnyOther + +[MAP] +; +; The Map Section is where the C language #defines are translated +; or mapped into the Help System Context Strings. Standard C syntax +; can be employed. The .HH file is meant to be #include(d) into your +; Windows application source code. +; + +[BITMAPS] +; +; The [BITMAPS] section is where you list any Bitmaps which have +; been placed by reference in the Help System. See the Help compiler +; documentation for more information about placing bitmaps. +; +; The [BITMAPS] section is not really required under Windows 3.1, +; with the advent of the BMROOT item in the [OPTIONS] section. +; +;FOO1.BMP +;FOO2.BMP +;C:\FOO\FOO3.BMP +;And So On + +[WINDOWS] +; Windows Help can display help in one of 5 secondary windows. +; Before using a secondary window, the window must be defined +; in this section: +; +;Gloss = "Glossary",(100,100,350,350),0,(255,255,255),(255,255,255) +main=,,0,, + +[BAGGAGE] +; +; The Baggage section allows the user to include files which +; will be placed in the internal file system for WinHelp. +; Using files from Baggage is a little faster for CDROM, since +; the CDROM drive table does not need to be read from disk. +; +; Baggage files are referred to as regular bitmaps, except +; that you prefix the filename with '!'. +; +; For Instance: +; {bmc !bitmap.bmp} instead of {bmc bitmap.bmp} +; diff --git a/krb5-1-6/src/windows/cns/kpasswd.c b/krb5-1-6/src/windows/cns/kpasswd.c new file mode 100644 index 000000000..3219ea2aa --- /dev/null +++ b/krb5-1-6/src/windows/cns/kpasswd.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997 Cygnus Solutions. + * + * Author: Michael Graff + */ + +#include +#include +#include + +#include "krb5.h" +#include "com_err.h" + +#include "cns.h" + +#include "../lib/gic.h" + +/* + * k5_change_password + * + * Use the new functions to change the password. + */ +krb5_error_code +k5_change_password(HWND hwnd, krb5_context context, char *user, char *realm, + char *opasswd, char *npasswd, char **text) +{ + krb5_error_code ret; + krb5_data result_string; + krb5_data result_code_string; + int result_code; + krb5_get_init_creds_opt opts; + krb5_creds creds; + krb5_principal princ; + char *name; + gic_data gd; + + *text = NULL; + + name = malloc(strlen(user) + strlen(realm) + 2); + if (name == NULL) { + *text = "Failed to allocate memory while changing password"; + return 1; + } + sprintf(name, "%s@%s", user, realm); + + ret = krb5_parse_name(context, name, &princ); + free(name); + if (ret) { + *text = "while parsing name"; + return ret; + } + + krb5_get_init_creds_opt_init(&opts); + krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); + krb5_get_init_creds_opt_set_renew_life(&opts, 0); + krb5_get_init_creds_opt_set_forwardable(&opts, 0); + krb5_get_init_creds_opt_set_proxiable(&opts, 0); + + gd.hinstance = hinstance; + gd.hwnd = hwnd; + gd.id = ID_VARDLG; + + ret = krb5_get_init_creds_password(context, &creds, princ, opasswd, gic_prompter, + &gd, 0, "kadmin/changepw", &opts); + if (ret) { + *text = "while getting creds"; + return ret; + } + + ret = krb5_change_password(context, &creds, npasswd, &result_code, &result_code_string, + &result_string); + if (ret) { + *text = "while changing password"; + return ret; + } + + if (result_code) { + *text = malloc(result_code_string.length + result_string.length + 3); + if (*text == NULL) + return -1; + + sprintf(*text, "%.*s%s%.*s", + result_code_string.length, result_code_string.data, + (result_string.length ? ": " : ""), + result_string.length, + result_string.data ? result_string.data : ""); + } + + return 0; +} diff --git a/krb5-1-6/src/windows/cns/krb5.def b/krb5-1-6/src/windows/cns/krb5.def new file mode 100644 index 000000000..6a88ffbb9 --- /dev/null +++ b/krb5-1-6/src/windows/cns/krb5.def @@ -0,0 +1,9 @@ +NAME KRB5 +DESCRIPTION 'KRB5 - Credentials Manager' +EXETYPE WINDOWS +STUB 'WINSTUB.EXE' +SEGMENTS _TEXT CLASS 'CODE' PRELOAD +CODE DISCARDABLE +DATA PRELOAD MULTIPLE MOVEABLE +HEAPSIZE 20480 +STACKSIZE 20480 diff --git a/krb5-1-6/src/windows/cns/krbini.h b/krb5-1-6/src/windows/cns/krbini.h new file mode 100644 index 000000000..8daf93b73 --- /dev/null +++ b/krb5-1-6/src/windows/cns/krbini.h @@ -0,0 +1,37 @@ +/* Kerberos changed window message */ +#define WM_KERBEROS_CHANGED "Kerberos Changed" + +/* Kerberos Windows initialization file */ +#define KERBEROS_INI "kerberos.ini" +#ifdef CYGNUS +#define KERBEROS_HLP "kerbnet.hlp" +#else +#define KERBEROS_HLP "krb5.hlp" +#endif +#define INI_DEFAULTS "Defaults" +#define INI_USER "User" /* Default user */ +#define INI_INSTANCE "Instance" /* Default instance */ +#define INI_REALM "Realm" /* Default realm */ +#define INI_POSITION "Position" +#define INI_OPTIONS "Options" +#define INI_DURATION "Duration" /* Ticket duration in minutes */ +#define INI_EXPIRATION "Expiration" /* Action on expiration (alert or beep) */ +#define INI_ALERT "Alert" +#define INI_BEEP "Beep" +#define INI_FILES "Files" +#ifdef KRB4 +#define INI_KRB_CONF "krb.conf" /* Location of krb.conf file */ +#define DEF_KRB_CONF "krb.conf" /* Default name for krb.conf file */ +#endif /* KRB4 */ +#ifdef KRB5 +#define INI_KRB5_CONF "krb5.ini" /* From k5-config.h */ +#define INI_KRB_CONF INI_KRB5_CONF /* Location of krb.conf file */ +#define DEF_KRB_CONF INI_KRB5_CONF /* Default name for krb.conf file */ +#define INI_TICKETOPTS "TicketOptions" /* Ticket options */ +#define INI_FORWARDABLE "Forwardable" /* get forwardable tickets */ +#define INI_KRB_CCACHE "krb5cc" /* From k5-config.h */ +#endif /* KRB5 */ +#define INI_KRB_REALMS "krb.realms" /* Location of krb.realms file */ +#define DEF_KRB_REALMS "krb.realms" /* Default name for krb.realms file */ +#define INI_RECENT_LOGINS "Recent Logins" +#define INI_LOGIN "Login" diff --git a/krb5-1-6/src/windows/cns/options.c b/krb5-1-6/src/windows/cns/options.c new file mode 100644 index 000000000..9e7c30e94 --- /dev/null +++ b/krb5-1-6/src/windows/cns/options.c @@ -0,0 +1,232 @@ +/* + * Copyright 1994 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + */ + +/* + * functions to tweak the options dialog + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "cns.h" +#include "tktlist.h" +#include "cns_reg.h" + +/* + * Function: Process WM_INITDIALOG messages for the options dialog. + * Set up all initial dialog values from the KERBEROS_INI file. + * + * Returns: TRUE if we didn't set the focus here, + * FALSE if we did. + */ +BOOL +opts_initdialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) +{ + center_dialog(hwnd); + set_dialog_font(hwnd, hfontdialog); + + /* krb.conf file */ + strcpy(confname, cns_res.confname); +#ifndef _WIN32 + _strupr(confname); +#endif + SetDlgItemText(hwnd, IDD_CONF, confname); + + if (cns_res.conf_override == 0) + EnableWindow(GetDlgItem(hwnd, IDD_CONF), 0); + else + EnableWindow(GetDlgItem(hwnd, IDD_CONF), 1); + + /* Credential cache file */ + strcpy(ccname, cns_res.ccname); +#ifndef _WIN32 + _strupr(ccname); +#endif + SetDlgItemText(hwnd, IDD_CCACHE, ccname); + + if (cns_res.cc_override == 0) + EnableWindow(GetDlgItem(hwnd, IDD_CCACHE), 0); + else + EnableWindow(GetDlgItem(hwnd, IDD_CCACHE), 1); + + /* Ticket duration */ + SetDlgItemInt(hwnd, IDD_LIFETIME, cns_res.lifetime, FALSE); + + /* Expiration action */ + alert = cns_res.alert; + SendDlgItemMessage(hwnd, IDD_ALERT, BM_SETCHECK, alert, 0); + + beep = cns_res.beep; + SendDlgItemMessage(hwnd, IDD_BEEP, BM_SETCHECK, beep, 0); + + forwardable = cns_res.forwardable; + SendDlgItemMessage(hwnd, IDD_FORWARDABLE, BM_SETCHECK, forwardable, 0); + + noaddresses = cns_res.noaddresses; + SendDlgItemMessage(hwnd, IDD_NOADDRESSES, BM_SETCHECK, noaddresses, 0); + + return TRUE; +} + + +/* + * Function: Process WM_COMMAND messages for the options dialog. + */ +void +opts_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify) +{ + char newname[FILENAME_MAX]; + BOOL b; + int lifetime; + + switch (cid) { + case IDOK: + + /* Ticket duration */ + lifetime = GetDlgItemInt(hwnd, IDD_LIFETIME, &b, FALSE); + + if (!b) { + MessageBox(hwnd, "Lifetime must be a number!", "", + MB_OK | MB_ICONEXCLAMATION); + return; /* TRUE */ + } + + cns_res.lifetime = lifetime; + + if (cns_res.conf_override) { + /* krb.conf file */ + GetDlgItemText(hwnd, IDD_CONF, newname, sizeof(newname)); + trim(newname); + if (newname[0] == '\0') + strcpy(newname, cns_res.def_confname); + if (_stricmp(newname, confname)) { /* file name changed */ + MessageBox(NULL, + "Change to configuration file location requires a restart" + "of KerbNet.\n" + "Please exit this application and restart it for the change to take" + "effect", + "", MB_OK | MB_ICONEXCLAMATION); + } + strcpy(confname, newname); + } + + /* Credential cache file */ + GetDlgItemText(hwnd, IDD_CCACHE, newname, sizeof(newname)); + trim(newname); + + if (newname[0] == '\0') + strcpy(newname, cns_res.def_ccname); + + if (_stricmp(ccname, newname)) { /* Did we change ccache file? */ + krb5_error_code code; + krb5_ccache cctemp; + + code = k5_init_ccache(&cctemp); + if (code) { /* Problem opening new one? */ + com_err(NULL, code, + "while changing ccache.\r\nRestoring old ccache."); + } else { + strcpy(ccname, newname); + strcpy(cns_res.ccname, newname); + + code = krb5_cc_close(k5_context, k5_ccache); + k5_ccache = cctemp; /* Copy new into old */ + if (k5_name_from_ccache(k5_ccache)) { + kwin_init_name(GetParent(hwnd), ""); + kwin_set_default_focus(GetParent(hwnd)); + } + ticket_init_list(GetDlgItem (GetParent(hwnd), + IDD_TICKET_LIST)); + } + } + + /* + * get values for the clickboxes + */ + alert = SendDlgItemMessage(hwnd, IDD_ALERT, BM_GETCHECK, 0, 0); + cns_res.alert = alert; + + beep = SendDlgItemMessage(hwnd, IDD_BEEP, BM_GETCHECK, 0, 0); + cns_res.beep = beep; + + forwardable = SendDlgItemMessage(hwnd, IDD_FORWARDABLE, BM_GETCHECK, 0, 0); + cns_res.forwardable = forwardable; + + noaddresses = SendDlgItemMessage(hwnd, IDD_NOADDRESSES, BM_GETCHECK, 0, 0); + cns_res.noaddresses = noaddresses; + + EndDialog(hwnd, IDOK); + + return; /* TRUE */ + + case IDCANCEL: + EndDialog(hwnd, IDCANCEL); + + return; /* TRUE */ + } + + return; /* FALSE */ +} + + +/* + * Function: Process dialog specific messages for the opts dialog. + */ +BOOL CALLBACK +opts_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + HANDLE_MSG(hwnd, WM_INITDIALOG, opts_initdialog); + + HANDLE_MSG(hwnd, WM_COMMAND, opts_command); + } + + return FALSE; +} + + +/* + * Function: Display and process the options dialog. + * + * Parameters: + * hwnd - the parent window for the dialog + * + * Returns: TRUE if the dialog completed successfully, FALSE otherwise. + */ +BOOL +opts_dialog(HWND hwnd) +{ + DLGPROC dlgproc; + int rc; + +#ifdef _WIN32 + dlgproc = opts_dlg_proc; +#else + dlgproc = (FARPROC)MakeProcInstance(opts_dlg_proc, hinstance); + assert(dlgproc != NULL); + + if (dlgproc == NULL) + return FALSE; +#endif + + rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_OPTS), hwnd, dlgproc); + assert(rc != -1); + +#ifndef _WIN32 + FreeProcInstance((FARPROC)dlgproc); +#endif + + return rc == IDOK; +} diff --git a/krb5-1-6/src/windows/cns/password.c b/krb5-1-6/src/windows/cns/password.c new file mode 100644 index 000000000..b98665994 --- /dev/null +++ b/krb5-1-6/src/windows/cns/password.c @@ -0,0 +1,323 @@ +/* + * Copyright 1994 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + */ + +/* + * functions to tweak the options dialog + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "cns.h" + +/* + * Function: Changes the password. + * + * Parameters: + * hwnd - the current window from which command was invoked. + * + * name - name of user to change password for + * + * instance - instance of user to change password for + * + * realm - realm in which to change password + * + * oldpw - the old password + * + * newpw - the new password to change to + * + * Returns: TRUE if change took place, FALSE otherwise. + */ +BOOL +change_password(HWND hwnd, char *name, char *instance, char *realm, + char *oldpw, char *newpw) +{ +#ifdef KRB4 + des_cblock new_key; + char *ret_st; + int krc; + char *p; + CREDENTIALS *c; + int ncred; + char pname[ANAME_SZ]; + char pinstance[INST_SZ]; + + push_credentials(&c, pname, pinstance, &ncred); + krc = krb_get_pw_in_tkt(name, instance, realm, PWSERV_NAME, KADM_SINST, + 1, oldpw); + + if (krc != KSUCCESS) { + if (krc == INTK_BADPW) + p = "Old password is incorrect"; + else + p = krb_get_err_text(krc); + pop_credentials(c, pname, pinstance, ncred); + MessageBox(hwnd, p, "", MB_OK | MB_ICONEXCLAMATION); + + return FALSE; + } + + krc = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm); + + if (krc != KSUCCESS) { + pop_credentials(c, pname, pinstance, ncred); + MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION); + + return FALSE; + } + + des_string_to_key(newpw, new_key); + krc = kadm_change_pw2(new_key, newpw, &ret_st); + pop_credentials(c, pname, pinstance, ncred); + + if (ret_st != NULL) + free(ret_st); + + if (krc != KSUCCESS) { + MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION); + + return FALSE; + } + + return TRUE; +#endif /* KRB4 */ + +#ifdef KRB5 + char *msg; /* Message string */ + krb5_error_code code; /* Return value */ + code = k5_change_password(hwnd, k5_context, name, realm, oldpw, newpw, &msg); + + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) + MessageBox(NULL, "Password incorrect", NULL, MB_ICONEXCLAMATION); + else if (code == -1) + MessageBox(NULL, (msg ? msg : "Cannot change password"), NULL, + MB_ICONEXCLAMATION); + else if (code != 0) + com_err(NULL, code, (msg ? msg : "while changing password.")); + else + MessageBox(NULL, (msg ? msg : "Password changed"), "Kerberos", MB_OK | MB_APPLMODAL); + + return (code == 0); + +#endif /* KRB5 */ +} +/* + * Function: Process WM_COMMAND messages for the password dialog. + */ +void +password_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + char oldpw[MAX_KPW_LEN]; + char newpw1[MAX_KPW_LEN]; + char newpw2[MAX_KPW_LEN]; + HCURSOR hcursor; + BOOL b; + int id; + + if (codeNotify != BN_CLICKED) { + GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name)); + trim(name); + GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm)); + trim(realm); + GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2)); + b = strlen(name) && strlen(realm) && strlen(oldpw) && + strlen(newpw1) && strlen(newpw2); + EnableWindow(GetDlgItem(hwnd, IDOK), b); + id = (b) ? IDOK : IDD_PASSWORD_CR; + SendMessage(hwnd, DM_SETDEFID, id, 0); + + return; /* FALSE */ + } + + switch (cid) { + case IDOK: + if (isblocking) + return; /* TRUE */ + + GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name)); + trim(name); + GetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance, sizeof(instance)); + trim(instance); + GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm)); + trim(realm); + GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2)); + + if (strcmp(newpw1, newpw2) != 0) { + MessageBox(hwnd, "The two passwords you entered don't match!", "", + MB_OK | MB_ICONEXCLAMATION); + SetDlgItemText(hwnd, IDD_NEW_PASSWORD1, ""); + SetDlgItemText(hwnd, IDD_NEW_PASSWORD2, ""); + PostMessage(hwnd, WM_NEXTDLGCTL, + (WPARAM)GetDlgItem(hwnd, IDD_NEW_PASSWORD1), MAKELONG(1, 0)); + + return; /* TRUE */ + } + + hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + start_blocking_hook(BLOCK_MAX_SEC); + + if (change_password(hwnd, name, instance, realm, oldpw, newpw1)) + EndDialog(hwnd, IDOK); + else + PostMessage(hwnd, WM_NEXTDLGCTL, + (WPARAM)GetDlgItem(hwnd, IDD_OLD_PASSWORD), MAKELONG(1, 0)); + + end_blocking_hook(); + SetCursor(hcursor); + + return; /* TRUE */ + + case IDCANCEL: + if (isblocking) + WSACancelBlockingCall(); + EndDialog(hwnd, IDCANCEL); + + return; /* TRUE */ + + case IDD_PASSWORD_CR: + id = GetDlgCtrlID(GetFocus()); + assert(id != 0); + + if (id == IDD_NEW_PASSWORD2) + PostMessage(hwnd, WM_NEXTDLGCTL, + (WPARAM)GetDlgItem(hwnd, IDD_PASSWORD_NAME), MAKELONG(1, 0)); + else + PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0); + + return; /* TRUE */ + + } + + return; /* FALSE */ +} + + +/* + * Function: Process WM_INITDIALOG messages for the password dialog. + * Set up all initial dialog values from the parent dialog. + * + * Returns: TRUE if we didn't set the focus here, + * FALSE if we did. + */ +BOOL +password_initdialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) +{ + char name[ANAME_SZ]; + char realm[REALM_SZ]; + HWND hwndparent; + int id; +#ifdef KRB4 + char instance[INST_SZ]; +#endif + + center_dialog(hwnd); + set_dialog_font(hwnd, hfontdialog); + + hwndparent = GetParent(hwnd); + assert(hwndparent != NULL); + + GetDlgItemText(hwndparent, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + SetDlgItemText(hwnd, IDD_PASSWORD_NAME, name); + +#ifdef KRB4 + GetDlgItemText(hwndparent, IDD_LOGIN_INSTANCE, instance, sizeof(instance)); + trim(instance); + SetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance); +#endif + + GetDlgItemText(hwndparent, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + SetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm); + + if (strlen(name) == 0) + id = IDD_PASSWORD_NAME; + else if (strlen(realm) == 0) + id = IDD_PASSWORD_REALM; + else + id = IDD_OLD_PASSWORD; + + SetFocus(GetDlgItem(hwnd, id)); + + return FALSE; +} + + +/* + * Function: Process dialog specific messages for the password dialog. + */ +BOOL CALLBACK +password_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + + HANDLE_MSG(hwnd, WM_INITDIALOG, password_initdialog); + + HANDLE_MSG(hwnd, WM_COMMAND, password_command); + + case WM_SETCURSOR: + if (isblocking) { + SetCursor(LoadCursor(NULL, IDC_WAIT)); + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE); + + return TRUE; + } + break; + } + + return FALSE; +} + + +/* + * Function: Display and process the password dialog. + * + * Parameters: + * hwnd - the parent window for the dialog + * + * Returns: TRUE if the dialog completed successfully, FALSE otherwise. + */ +BOOL +password_dialog(HWND hwnd) +{ + DLGPROC dlgproc; + int rc; + +#ifdef _WIN32 + dlgproc = password_dlg_proc; +#else + dlgproc = (FARPROC)MakeProcInstance(password_dlg_proc, hinstance); + assert(dlgproc != NULL); + + if (dlgproc == NULL) + return FALSE; +#endif + + rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_PASSWORD), hwnd, dlgproc); + assert(rc != -1); + +#ifndef _WIN32 + FreeProcInstance((FARPROC)dlgproc); +#endif + + return rc == IDOK; +} diff --git a/krb5-1-6/src/windows/cns/tktlist.c b/krb5-1-6/src/windows/cns/tktlist.c new file mode 100644 index 000000000..68a6f1c62 --- /dev/null +++ b/krb5-1-6/src/windows/cns/tktlist.c @@ -0,0 +1,442 @@ +/* + * tktlist.c + * + * Handle all actions of the Kerberos ticket list. + * + * Copyright 1994 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + */ + +#if !defined(KRB5) && !defined(KRB4) +#define KRB5 1 +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef KRB4 +#include "mit-copyright.h" +#include "kerberos.h" +#endif + +#ifdef KRB5 +#include "winsock.h" +#include "krb5.h" +#include "com_err.h" +#endif + +#include "cns.h" +#include "tktlist.h" + +/* + * Ticket information for a list line + */ +typedef struct { + BOOL ticket; /* TRUE if this is a real ticket */ + time_t issue_time; /* time_t of issue */ + long lifetime; /* Lifetime for ticket in 5 minute intervals */ + char buf[0]; /* String to display */ +} TICKETINFO, *LPTICKETINFO; + +/* + * Function: Returns a standard ctime date with day of week and year + * removed. + * + * Parameters: + * t - time_t date to convert + * + * Returns: A pointer to the adjusted time value. + */ +static char * +short_date (time_t t) +{ + static char buf[26 - 4]; + char *p; + + p = ctime(&t); + assert(p != NULL); + + strcpy (buf, p + 4); + buf[12] = '\0'; + + return buf; +} + + +/*+ + * Function: Initializes and populates the ticket list with all existing + * Kerberos tickets. + * + * Parameters: + * hwnd - the window handle of the ticket window. + * + * Returns: Number of elements in the list or -1 on error + */ +int +ticket_init_list (HWND hwnd) +{ + int ncred; + LRESULT rc; + int l; + LPTICKETINFO lpinfo; + char buf[26+2 + 26+2 + ANAME_SZ+1 + INST_SZ+1 + REALM_SZ + 22]; +#ifdef KRB4 + int i; + time_t expiration; + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + CREDENTIALS c; +#endif +#ifdef KRB5 + krb5_cc_cursor cursor; + krb5_error_code code; + krb5_creds c; + krb5_flags flags; + char *sname; /* Name of the service */ + char *flags_string(krb5_creds *cred); +#endif + + SetWindowRedraw(hwnd, FALSE); + + rc = ListBox_GetCount(hwnd); + assert(rc != LB_ERR); + + if (rc > 0) + ticket_destroy(hwnd); + + while (--rc >= 0) + ListBox_DeleteString(hwnd, rc); + +#ifdef KRB4 + ncred = krb_get_num_cred(); + for (i = 1; i <= ncred; i++) { + krb_get_nth_cred(service, instance, realm, i); + krb_get_cred(service, instance, realm, &c); + strcpy(buf, " "); + strncat(buf, short_date(c.issue_date - kwin_get_epoch()), + sizeof(buf) - 1 - strlen(buf)); + expiration = c.issue_date - kwin_get_epoch() + (long) c.lifetime * 5L * 60L; + strncat(buf, " ", sizeof(buf) - 1 - strlen(buf)); + strncat(buf, short_date(expiration), sizeof(buf) - 1 - strlen(buf)); + strncat(buf, " ", sizeof(buf) - 1 - strlen(buf)); + l = strlen(buf); + sprintf(&buf[l], "%s%s%s%s%s (%d)", + c.service, (c.instance[0] ? "." : ""), c.instance, + (c.realm[0] ? "@" : ""), c.realm, c.kvno); + l = strlen(buf); + + lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + l + 1); + assert(lpinfo != NULL); + + if (lpinfo == NULL) + return -1; + + lpinfo->ticket = TRUE; + lpinfo->issue_time = c.issue_date - kwin_get_epoch(); /* back to system time */ + lpinfo->lifetime = (long) c.lifetime * 5L * 60L; + strcpy(lpinfo->buf, buf); + + rc = ListBox_AddItemData(hwnd, lpinfo); + assert(rc >= 0); + + if (rc < 0) + return -1; + } + +#endif + +#ifdef KRB5 + + ncred = 0; + flags = 0; + if (code = krb5_cc_set_flags(k5_context, k5_ccache, flags)) { + if (code != KRB5_FCC_NOFILE) { + return -1; + } + } else { + if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) { + return -1; + } + while (1) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c); + if (code != 0) + break; + + ncred++; + strcpy (buf, " "); + strncat(buf, short_date (c.times.starttime - kwin_get_epoch()), + sizeof(buf) - 1 - strlen(buf)); + strncat(buf, " ", sizeof(buf) - 1 - strlen(buf)); + strncat(buf, short_date (c.times.endtime - kwin_get_epoch()), + sizeof(buf) - 1 - strlen(buf)); + strncat(buf, " ", sizeof(buf) - 1 - strlen(buf)); + + /* Add ticket service name and realm */ + code = krb5_unparse_name (k5_context, c.server, &sname); + if (code) { + com_err (NULL, code, "while unparsing server name"); + break; + } + strncat (buf, sname, sizeof(buf) - 1 - strlen(buf)); + + strncat (buf, flags_string (&c), sizeof(buf) - 1 - strlen(buf)); /* Add flag info */ + + l = strlen(buf); + lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + l + 1); + assert(lpinfo != NULL); + + if (lpinfo == NULL) + return -1; + + lpinfo->ticket = TRUE; + lpinfo->issue_time = c.times.starttime - kwin_get_epoch(); + lpinfo->lifetime = c.times.endtime - c.times.starttime; + strcpy(lpinfo->buf, buf); + + rc = ListBox_AddItemData(hwnd, lpinfo); + assert(rc >= 0); + + if (rc < 0) + return -1; + } + if (code == KRB5_CC_END) { /* End of ccache */ + if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor)) { + return -1; + } + flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */ + if (code = krb5_cc_set_flags(k5_context, k5_ccache, flags)) { + return -1; + } + } else { + return -1; + } + } +#endif + + if (ncred <= 0) { + strcpy(buf, " No Tickets"); + lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + strlen(buf) + 1); + assert(lpinfo != NULL); + + if (lpinfo == NULL) + return -1; + + lpinfo->ticket = FALSE; + strcpy (lpinfo->buf, buf); + rc = ListBox_AddItemData(hwnd, lpinfo); + assert(rc >= 0); + } + + SetWindowRedraw(hwnd, TRUE); + + return ncred; +} + + +/* + * Function: Destroy the ticket list. Make sure to delete all + * ticket entries created during ticket initialization. + * + * Parameters: + * hwnd - the window handle of the ticket window. + */ +void +ticket_destroy ( + HWND hwnd) +{ + int i; + int n; + LRESULT rc; + + n = ListBox_GetCount(hwnd); + + for (i = 0; i < n; i++) { + rc = ListBox_GetItemData(hwnd, i); + assert(rc != LB_ERR); + + if (rc != LB_ERR) + free ((void *) rc); + } +} + + +/* + * Function: Respond to the WM_MEASUREITEM message for the ticket list + * by setting each list item up at 1/4 inch hight. + */ +void +ticket_measureitem(HWND hwnd, MEASUREITEMSTRUCT *lpmi) +{ + int logpixelsy; + HDC hdc; + + if (lpmi->CtlID != IDD_TICKET_LIST) + return; + + hdc = GetDC(HWND_DESKTOP); + logpixelsy = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(HWND_DESKTOP, hdc); + lpmi->itemHeight = logpixelsy / 4; /* 1/4 inch */ +} + + +/* + * Function: Respond to the WM_DRAWITEM message for the ticket list + * by displaying a single list item. + */ +void +ticket_drawitem(HWND hwnd, const DRAWITEMSTRUCT *lpdi) +{ + BOOL rc; + COLORREF bkcolor; + HBRUSH hbrush; + UINT textheight; + UINT alignment; + int left, top; + BOOL b; + LPTICKETINFO lpinfo; + HICON hicon; +#if 0 + COLORREF textcolor; + COLORREF orgbkcolor; + COLORREF orgtextcolor; +#endif + SIZE Size; + + if (lpdi->CtlID != IDD_TICKET_LIST) + return; + + lpinfo = (LPTICKETINFO) lpdi->itemData; + + if (lpdi->itemAction == ODA_FOCUS) + return; + +#if 0 + if (lpdi->itemState & ODS_SELECTED) { + textcolor = GetSysColor(COLOR_HIGHLIGHTTEXT); + bkcolor = GetSysColor(COLOR_HIGHLIGHT); + + orgtextcolor = SetTextColor(lpdi->hDC, textcolor); + assert(textcolor != 0x80000000); + + orgbkcolor = SetBkColor(lpdi->hDC, bkcolor); + assert(bkcolor != 0x80000000); + } + else +#endif + + bkcolor = GetBkColor(lpdi->hDC); + hbrush = CreateSolidBrush(bkcolor); + assert(hbrush != NULL); + + FillRect(lpdi->hDC, &(lpdi->rcItem), hbrush); + DeleteObject(hbrush); + + /* + * Display the appropriate icon + */ + if (lpinfo->ticket) { + hicon = kwin_get_icon(lpinfo->issue_time + lpinfo->lifetime); + left = lpdi->rcItem.left - (32 - ICON_WIDTH) / 2; + top = lpdi->rcItem.top; + top += (lpdi->rcItem.bottom - lpdi->rcItem.top - 32) / 2; + + b = DrawIcon(lpdi->hDC, left, top, hicon); + assert(b); + } + + /* + * Display centered string + */ +#ifdef _WIN32 + GetTextExtentPoint32(lpdi->hDC, "X", 1, &Size); +#else + GetTextExtentPoint(lpdi->hDC, "X", 1, &Size); +#endif + + textheight = Size.cy; + + alignment = SetTextAlign(lpdi->hDC, TA_TOP | TA_LEFT); + + if (lpinfo->ticket) + left = lpdi->rcItem.left + ICON_WIDTH; + else + left = lpdi->rcItem.left; + + top = lpdi->rcItem.top; + top += (lpdi->rcItem.bottom - lpdi->rcItem.top - textheight) / 2; + rc = TextOut(lpdi->hDC, left, top, (LPSTR) lpinfo->buf, + strlen((LPSTR) lpinfo->buf)); + assert(rc); + + alignment = SetTextAlign(lpdi->hDC, alignment); + +#if 0 + if (lpdi->itemState & ODS_SELECTED) { + textcolor = SetTextColor(lpdi->hDC, orgtextcolor); + assert(textcolor != 0x80000000); + + bkcolor = SetBkColor(lpdi->hDC, orgbkcolor); + assert(bkcolor != 0x80000000); + } + +#endif +} + + +#ifdef KRB5 + +/* + * + * Flags_string + * + * Return buffer with the current flags for the credential + * + */ +char * +flags_string(krb5_creds *cred) { + static char buf[32]; + int i = 0; + + buf[i++] = ' '; + buf[i++] = '('; + if (cred->ticket_flags & TKT_FLG_FORWARDABLE) + buf[i++] = 'F'; + if (cred->ticket_flags & TKT_FLG_FORWARDED) + buf[i++] = 'f'; + if (cred->ticket_flags & TKT_FLG_PROXIABLE) + buf[i++] = 'P'; + if (cred->ticket_flags & TKT_FLG_PROXY) + buf[i++] = 'p'; + if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE) + buf[i++] = 'D'; + if (cred->ticket_flags & TKT_FLG_POSTDATED) + buf[i++] = 'd'; + if (cred->ticket_flags & TKT_FLG_INVALID) + buf[i++] = 'i'; + if (cred->ticket_flags & TKT_FLG_RENEWABLE) + buf[i++] = 'R'; + if (cred->ticket_flags & TKT_FLG_INITIAL) + buf[i++] = 'I'; + if (cred->ticket_flags & TKT_FLG_HW_AUTH) + buf[i++] = 'H'; + if (cred->ticket_flags & TKT_FLG_PRE_AUTH) + buf[i++] = 'A'; + + buf[i++] = ')'; + buf[i] = '\0'; + if (i <= 3) + buf[0] = '\0'; + return(buf); +} + +#endif /* KRB5 */ diff --git a/krb5-1-6/src/windows/cns/tktlist.h b/krb5-1-6/src/windows/cns/tktlist.h new file mode 100644 index 000000000..a522f76c7 --- /dev/null +++ b/krb5-1-6/src/windows/cns/tktlist.h @@ -0,0 +1,27 @@ +/* + * tktlist.h + * + * Handle all actions of the Kerberos ticket list. + * + * Copyright 1994 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + */ + +/* Only one time, please */ +#ifndef TKTLIST_DEFS +#define TKTLIST_DEFS + +/* + * Prototypes + */ +BOOL ticket_init_list(HWND); + +void ticket_destroy(HWND); + +void ticket_measureitem(HWND, MEASUREITEMSTRUCT *); + +void ticket_drawitem(HWND, const DRAWITEMSTRUCT *); + +#endif diff --git a/krb5-1-6/src/windows/gina/Makefile.in b/krb5-1-6/src/windows/gina/Makefile.in new file mode 100644 index 000000000..c2f7ada19 --- /dev/null +++ b/krb5-1-6/src/windows/gina/Makefile.in @@ -0,0 +1,36 @@ +BUILDTOP=..\.. + +OBJS= $(OUTPRE)ginastub.$(OBJEXT) + +# Set NODEBUG if building release instead of debug + +LOCALINCLUDES = -I$(BUILDTOP)\include + +WINLIBS = advapi32.lib comctl32.lib \ + libcmt.lib kernel32.lib ws2_32.lib user32.lib shell32.lib oldnames.lib + +WINDLLFLAGS = /nodefaultlib /incremental:no /release \ + /nologo /base:0x1c000000 /dll $(LOPTS) + +DEFINES = -DUNICODE -D_UNICODE +!ifdef NODEBUG +DEFINES = $(DEFINES) +!else +DEFINES = $(DEFINES) -DDBG +!endif + +all-windows:: +all-windows:: $(OUTPRE)kgina.dll + +clean-windows:: + $(RM) $(OUTPRE)kgina.dll + +$(OUTPRE)kgina.dll: $(OBJS) $(KLIB) $(CLIB) + link $(WINDLLFLAGS) -def:gina.def -out:$*.dll \ + $** $(WINLIBS) $(SCLIB) + $(_VC_MANIFEST_EMBED_DLL) + +$(OUTPRE)ginastub.obj: ginastub.h + +#$(OUTPRE)gina.res: res.rc +# $(RC) $(RFLAGS) -r -fo $@ res.rc diff --git a/krb5-1-6/src/windows/gina/gina.def b/krb5-1-6/src/windows/gina/gina.def new file mode 100644 index 000000000..99e066bec --- /dev/null +++ b/krb5-1-6/src/windows/gina/gina.def @@ -0,0 +1,21 @@ +LIBRARY KGINA + +DESCRIPTION 'Alternate Windows NT Logon GUI' + +EXPORTS +; Version 1.0 + WlxNegotiate + WlxInitialize + WlxDisplaySASNotice + WlxLoggedOutSAS + WlxActivateUserShell + WlxLoggedOnSAS + WlxDisplayLockedNotice + WlxWkstaLockedSAS + WlxIsLockOk + WlxIsLogoffOk + WlxLogoff + WlxShutdown +; Version 1.1 + WlxScreenSaverNotify + WlxStartApplication diff --git a/krb5-1-6/src/windows/gina/ginastub.c b/krb5-1-6/src/windows/gina/ginastub.c new file mode 100644 index 000000000..ec4291b2b --- /dev/null +++ b/krb5-1-6/src/windows/gina/ginastub.c @@ -0,0 +1,365 @@ + +/* + Copyright (c) 1996 Microsoft Corporation + +Module Name: + ginastub.c + +Abstract: + This sample illustrates a pass-thru "stub" gina which can be used + in some cases to simplify gina development. + + A common use for a gina is to implement code which requires the + credentials of the user logging onto the workstation. The credentials + may be required for syncronization with foreign account databases + or custom authentication activities. + + In this example case, it is possible to implement a simple gina + stub layer which simply passes control for the required functions + to the previously installed gina, and captures the interesting + parameters from that gina. In this scenario, the existing functionality + in the existent gina is retained. In addition, the development time + is reduced drastically, as existing functionality does not need to + be duplicated. + + When dealing with credentials, take steps to maintain the security + of the credentials. For instance, if transporting credentials over + a network, be sure to encrypt the credentials. + +Author: + Scott Field (sfield) 18-Jul-96 +*/ + + +#include +#include +#include +#include "ginastub.h" + + +/* Location of the real msgina. */ + +#define REALGINA_PATH TEXT("MSGINA.DLL") + + +/* winlogon function dispatch table */ +PGWLX_DISPATCH_VERSION pWlxFuncs; + + +/* winlogon version */ +DWORD WlxVersion; + + +/* Functions pointers to the real msgina which we will call. */ + +PGWLX_Negotiate GWlxNegotiate; +PGWLX_Initialize GWlxInitialize; +PGWLX_DisplaySASNotice GWlxDisplaySASNotice; +PGWLX_LoggedOutSAS GWlxLoggedOutSAS; +PGWLX_ActivateUserShell GWlxActivateUserShell; +PGWLX_LoggedOnSAS GWlxLoggedOnSAS; +PGWLX_DisplayLockedNotice GWlxDisplayLockedNotice; +PGWLX_WkstaLockedSAS GWlxWkstaLockedSAS; +PGWLX_IsLockOk GWlxIsLockOk; +PGWLX_IsLogoffOk GWlxIsLogoffOk; +PGWLX_Logoff GWlxLogoff; +PGWLX_Shutdown GWlxShutdown; + + +/* NEW for version 1.1 */ + +PGWLX_StartApplication GWlxStartApplication; +PGWLX_ScreenSaverNotify GWlxScreenSaverNotify; + + +/* hook into the real GINA. */ + +static BOOL +MyInitialize(void) +{ + HINSTANCE hDll; + + /* Load MSGINA.DLL. */ + + if (! (hDll = LoadLibrary(REALGINA_PATH))) + return FALSE; + + + /* Get pointers to all of the WLX functions in the real MSGINA. */ + + GWlxNegotiate = (PGWLX_Negotiate) + GetProcAddress(hDll, "WlxNegotiate"); + if (! GWlxNegotiate) + return FALSE; + + GWlxInitialize = (PGWLX_Initialize) + GetProcAddress(hDll, "WlxInitialize"); + if (! GWlxInitialize) + return FALSE; + + GWlxDisplaySASNotice = (PGWLX_DisplaySASNotice) + GetProcAddress(hDll, "WlxDisplaySASNotice"); + if (! GWlxDisplaySASNotice) + return FALSE; + + GWlxLoggedOutSAS = (PGWLX_LoggedOutSAS) + GetProcAddress(hDll, "WlxLoggedOutSAS"); + if (! GWlxLoggedOutSAS) + return FALSE; + + GWlxActivateUserShell = (PGWLX_ActivateUserShell) + GetProcAddress(hDll, "WlxActivateUserShell"); + if (! GWlxActivateUserShell) + return FALSE; + + GWlxLoggedOnSAS = (PGWLX_LoggedOnSAS) + GetProcAddress(hDll, "WlxLoggedOnSAS"); + if (! GWlxLoggedOnSAS) + return FALSE; + + GWlxDisplayLockedNotice = (PGWLX_DisplayLockedNotice) + GetProcAddress(hDll, "WlxDisplayLockedNotice"); + if (! GWlxDisplayLockedNotice) + return FALSE; + + GWlxIsLockOk = (PGWLX_IsLockOk) + GetProcAddress(hDll, "WlxIsLockOk"); + if (! GWlxIsLockOk) + return FALSE; + + GWlxWkstaLockedSAS = (PGWLX_WkstaLockedSAS) + GetProcAddress(hDll, "WlxWkstaLockedSAS"); + if (! GWlxWkstaLockedSAS) + return FALSE; + + GWlxIsLogoffOk = (PGWLX_IsLogoffOk) + GetProcAddress(hDll, "WlxIsLogoffOk"); + if (! GWlxIsLogoffOk) + return FALSE; + + GWlxLogoff = (PGWLX_Logoff) + GetProcAddress(hDll, "WlxLogoff"); + if (! GWlxLogoff) + return FALSE; + + GWlxShutdown = (PGWLX_Shutdown) + GetProcAddress(hDll, "WlxShutdown"); + if (! GWlxShutdown) + return FALSE; + + + /* Don't check for failure because these don't exist prior to NT 4.0 */ + + GWlxStartApplication = (PGWLX_StartApplication) + GetProcAddress(hDll, "WlxStartApplication"); + GWlxScreenSaverNotify = (PGWLX_ScreenSaverNotify) + GetProcAddress(hDll, "WlxScreenSaverNotify"); + + + /* Everything loaded ok. Return success. */ + return TRUE; +} + +BOOL +WINAPI +WlxNegotiate( + DWORD dwWinlogonVersion, + DWORD *pdwDllVersion) +{ + if (! MyInitialize()) + return FALSE; + + WlxVersion = dwWinlogonVersion; + return (* GWlxNegotiate)(dwWinlogonVersion, pdwDllVersion); +} + +BOOL +WINAPI +WlxInitialize( + LPWSTR lpWinsta, + HANDLE hWlx, + PVOID pvReserved, + PVOID pWinlogonFunctions, + PVOID *pWlxContext) +{ + pWlxFuncs = (PGWLX_DISPATCH_VERSION) pWinlogonFunctions; + + return (* GWlxInitialize)( + lpWinsta, + hWlx, + pvReserved, + pWinlogonFunctions, + pWlxContext + ); +} + +VOID +WINAPI +WlxDisplaySASNotice( + PVOID pWlxContext) +{ + (* GWlxDisplaySASNotice)(pWlxContext); +} + +int +WINAPI +WlxLoggedOutSAS( + PVOID pWlxContext, + DWORD dwSasType, + PLUID pAuthenticationId, + PSID pLogonSid, + PDWORD pdwOptions, + PHANDLE phToken, + PWLX_MPR_NOTIFY_INFO pMprNotifyInfo, + PVOID *pProfile) +{ + int iRet; + + iRet = (* GWlxLoggedOutSAS)( + pWlxContext, + dwSasType, + pAuthenticationId, + pLogonSid, + pdwOptions, + phToken, + pMprNotifyInfo, + pProfile + ); + + if (iRet == WLX_SAS_ACTION_LOGON) { + /* copy pMprNotifyInfo and pLogonSid for later use */ + + /* pMprNotifyInfo->pszUserName */ + /* pMprNotifyInfo->pszDomain */ + /* pMprNotifyInfo->pszPassword */ + /* pMprNotifyInfo->pszOldPassword */ + } + + return iRet; +} + +BOOL +WINAPI +WlxActivateUserShell( + PVOID pWlxContext, + PWSTR pszDesktopName, + PWSTR pszMprLogonScript, + PVOID pEnvironment) +{ + return (* GWlxActivateUserShell)( + pWlxContext, + pszDesktopName, + pszMprLogonScript, + pEnvironment + ); +} + +int +WINAPI +WlxLoggedOnSAS( + PVOID pWlxContext, + DWORD dwSasType, + PVOID pReserved) +{ + return (* GWlxLoggedOnSAS)(pWlxContext, dwSasType, pReserved); +} + +VOID +WINAPI +WlxDisplayLockedNotice( + PVOID pWlxContext) +{ + (* GWlxDisplayLockedNotice)(pWlxContext); +} + +BOOL +WINAPI +WlxIsLockOk( + PVOID pWlxContext) +{ + return (* GWlxIsLockOk)(pWlxContext); +} + +int +WINAPI +WlxWkstaLockedSAS( + PVOID pWlxContext, + DWORD dwSasType) +{ + return (* GWlxWkstaLockedSAS)(pWlxContext, dwSasType); +} + +BOOL +WINAPI +WlxIsLogoffOk( + PVOID pWlxContext + ) +{ + BOOL bSuccess; + + bSuccess = (* GWlxIsLogoffOk)(pWlxContext); + if (bSuccess) { + /* if it's ok to logoff, finish with the stored credentials */ + /* and scrub the buffers */ + } + + return bSuccess; +} + +VOID +WINAPI +WlxLogoff( + PVOID pWlxContext + ) +{ + (* GWlxLogoff)(pWlxContext); +} + +VOID +WINAPI +WlxShutdown( +PVOID pWlxContext, +DWORD ShutdownType +) +{ + (* GWlxShutdown)(pWlxContext, ShutdownType); +} + + +/* NEW for version 1.1 */ + +BOOL +WINAPI +WlxScreenSaverNotify( +PVOID pWlxContext, +BOOL * pSecure +) +{ + if (GWlxScreenSaverNotify) + return (* GWlxScreenSaverNotify)(pWlxContext, pSecure); + + /* if not exported, return something intelligent */ + *pSecure = TRUE; + return TRUE; +} + +BOOL +WINAPI +WlxStartApplication( + PVOID pWlxContext, + PWSTR pszDesktopName, + PVOID pEnvironment, + PWSTR pszCmdLine + ) +{ + if (GWlxStartApplication) + return (* GWlxStartApplication)( + pWlxContext, + pszDesktopName, + pEnvironment, + pszCmdLine + ); + + /* if not exported, return something intelligent */ + return TRUE; /* ??? */ +} diff --git a/krb5-1-6/src/windows/gina/ginastub.h b/krb5-1-6/src/windows/gina/ginastub.h new file mode 100644 index 000000000..e9c833492 --- /dev/null +++ b/krb5-1-6/src/windows/gina/ginastub.h @@ -0,0 +1,39 @@ +/* WinLogin 1.0 */ +typedef BOOL (CALLBACK * PGWLX_Negotiate) + (DWORD, DWORD *); +typedef BOOL (CALLBACK * PGWLX_Initialize) + (LPWSTR, HANDLE, PVOID, PVOID, PVOID); +typedef VOID (CALLBACK * PGWLX_DisplaySASNotice) + (PVOID); +typedef int (CALLBACK * PGWLX_LoggedOutSAS) + (PVOID, DWORD, PLUID, PSID, PDWORD, PHANDLE, + PWLX_MPR_NOTIFY_INFO, PVOID *); +typedef BOOL (CALLBACK * PGWLX_ActivateUserShell) + (PVOID, PWSTR, PWSTR, PVOID); +typedef int (CALLBACK * PGWLX_LoggedOnSAS) + (PVOID, DWORD, PVOID); +typedef VOID (CALLBACK * PGWLX_DisplayLockedNotice) + (PVOID); +typedef int (CALLBACK * PGWLX_WkstaLockedSAS) + (PVOID, DWORD); +typedef BOOL (CALLBACK * PGWLX_IsLockOk) + (PVOID); +typedef BOOL (CALLBACK * PGWLX_IsLogoffOk) + (PVOID); +typedef VOID (CALLBACK * PGWLX_Logoff) + (PVOID); +typedef VOID (CALLBACK * PGWLX_Shutdown) + (PVOID, DWORD); + +/* WinLogin 1.1 */ +typedef BOOL (CALLBACK * PGWLX_StartApplication) + (PVOID, PWSTR, PVOID, PWSTR); +typedef BOOL (CALLBACK * PGWLX_ScreenSaverNotify) + (PVOID, BOOL *); + + +#if defined(WLX_VERSION_1_1) +typedef PWLX_DISPATCH_VERSION_1_1 PGWLX_DISPATCH_VERSION; +#else +typedef PWLX_DISPATCH_VERSION_1_0 PGWLX_DISPATCH_VERSION; +#endif diff --git a/krb5-1-6/src/windows/gss/Makefile.in b/krb5-1-6/src/windows/gss/Makefile.in new file mode 100644 index 000000000..5413a278a --- /dev/null +++ b/krb5-1-6/src/windows/gss/Makefile.in @@ -0,0 +1,52 @@ +# makefile: Constructs the Kerberos for Windows ticket manager +# Works for both k4 and k5 releases. +# +OBJS = $(OUTPRE)gss.obj $(OUTPRE)gss-client.obj $(OUTPRE)gss-misc.obj +RESFILE = $(OUTPRE)gss.res +XOBJS = $(RESFILE) + +##### Options +# Set NODEBUG if building release instead of debug +BUILDTOP=..\.. + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!if ( "$(CPU)" == "i386" ) +KFWLIB= $(BUILDTOP)\..\..\..\..\target\lib\$(CPU)\$(OUTPRE_DBG)\krbcc32.lib +!else +KFWLIB= $(BUILDTOP)\..\..\..\..\target\lib\$(CPU)\$(OUTPRE_DBG)\krbcc64.lib +!endif +!endif +LOCALINCLUDES= /I$(BUILDTOP) /I$(BUILDTOP)\include /I$(BUILDTOP)\include\krb5 $(KFWINC) + +##### RC Compiler +RFLAGS = $(LOCALINCLUDES) +RCFLAGS = $(RFLAGS) -D_WIN32 -DGSS_APP + +##### Linker +LINK = link +LIBS = $(GLIB) $(CLIB) $(WLIB) +SYSLIBS = kernel32.lib ws2_32.lib user32.lib gdi32.lib comdlg32.lib comctl32.lib +LFLAGS = /nologo $(LOPTS) + +all:: Makefile $(OUTPRE)gss.exe + +$(OUTPRE)gss.exe: gss.def $(OBJS) $(XOBJS) $(LIBS) + $(LINK) $(LFLAGS) /map:$*.map /out:$@ $(OBJS) $(XOBJS) \ + $(LIBS) $(SYSLIBS) $(KFWLIB) $(SCLIB) + +$(OBJS) $(XOBJS): gss.h + +$(RESFILE): ..\version.rc + +install:: + copy $(OUTPRE)gss.exe ..\floppy + +clean:: + if exist $(OUTPRE)*.exe del $(OUTPRE)*.exe + if exist ..\floppy\gss.exe del ..\floppy\gss.exe + if exist $(OUTPRE)*.obj del $(OUTPRE)*.obj + if exist $(OUTPRE)*.res del $(OUTPRE)*.res + if exist $(OUTPRE)*.map del $(OUTPRE)*.map + if exist $(OUTPRE)*.pdb del $(OUTPRE)*.pdb + if exist *.err del *.err diff --git a/krb5-1-6/src/windows/gss/gss-client.c b/krb5-1-6/src/windows/gss/gss-client.c new file mode 100644 index 000000000..d9c1491c2 --- /dev/null +++ b/krb5-1-6/src/windows/gss/gss-client.c @@ -0,0 +1,615 @@ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include "gss.h" +#include "gss-misc.h" + +static int verbose = 1; + +/* + * Function: connect_to_server + * + * Purpose: Opens a TCP connection to the name host and port. + * + * Arguments: + * + * host (r) the target host name + * port (r) the target port, in host byte order + * + * Returns: the established socket file desciptor, or -1 on failure + * + * Effects: + * + * The host name is resolved with gethostbyname(), and the socket is + * opened and connected. If an error occurs, an error message is + * displayed and -1 is returned. + */ +static int connect_to_server(host, port) + char *host; + u_short port; +{ + struct sockaddr_in saddr; + struct hostent *hp; + int s; + + if ((hp = gethostbyname(host)) == NULL) { + printf("Unknown host: %s\r\n", host); + return -1; + } + + saddr.sin_family = hp->h_addrtype; + memcpy((char *)&saddr.sin_addr, hp->h_addr, sizeof(saddr.sin_addr)); + saddr.sin_port = htons(port); + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("creating socket"); + return -1; + } + if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { + perror("connecting to server"); + (void) closesocket(s); + return -1; + } + return s; +} + +/* + * Function: client_establish_context + * + * Purpose: establishes a GSS-API context with a specified service and + * returns the context handle + * + * Arguments: + * + * s (r) an established TCP connection to the service + * service_name (r) the ASCII service name of the service + * gss_flags (r) GSS-API delegation flag (if any) + * auth_flag (r) whether to actually do authentication + * oid (r) OID of the mechanism to use + * context (w) the established GSS-API context + * ret_flags (w) the returned flags from init_sec_context + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * service_name is imported as a GSS-API name and a GSS-API context is + * established with the corresponding service; the service should be + * listening on the TCP connection s. The default GSS-API mechanism + * is used, and mutual authentication and replay detection are + * requested. + * + * If successful, the context handle is returned in context. If + * unsuccessful, the GSS-API error messages are displayed on stderr + * and -1 is returned. + */ +int client_establish_context( int s, + char *service_name, + OM_uint32 gss_flags, + int auth_flag, + int v1_format, + gss_OID oid, + gss_ctx_id_t *gss_context, + OM_uint32 *ret_flags) +{ + if (auth_flag) { + gss_buffer_desc send_tok, recv_tok, *token_ptr; + gss_name_t target_name; + OM_uint32 maj_stat, min_stat, init_sec_min_stat; + int token_flags; + + /* + * Import the name into target_name. Use send_tok to save + * local variable space. + */ + send_tok.value = service_name; + send_tok.length = strlen(service_name) ; + maj_stat = gss_import_name(&min_stat, &send_tok, + (gss_OID) gss_nt_service_name, &target_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("parsing name", maj_stat, min_stat); + return -1; + } + + if (!v1_format) { + if (send_token(s, TOKEN_NOOP|TOKEN_CONTEXT_NEXT, empty_token) < 0) { + (void) gss_release_name(&min_stat, &target_name); + return -1; + } + } + + /* + * Perform the context-establishement loop. + * + * On each pass through the loop, token_ptr points to the token + * to send to the server (or GSS_C_NO_BUFFER on the first pass). + * Every generated token is stored in send_tok which is then + * transmitted to the server; every received token is stored in + * recv_tok, which token_ptr is then set to, to be processed by + * the next call to gss_init_sec_context. + * + * GSS-API guarantees that send_tok's length will be non-zero + * if and only if the server is expecting another token from us, + * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if + * and only if the server has another token to send us. + */ + + token_ptr = GSS_C_NO_BUFFER; + *gss_context = GSS_C_NO_CONTEXT; + + do { + maj_stat = + gss_init_sec_context(&init_sec_min_stat, + GSS_C_NO_CREDENTIAL, + gss_context, + target_name, + oid, + gss_flags, + 0, + NULL, /* no channel bindings */ + token_ptr, + NULL, /* ignore mech type */ + &send_tok, + ret_flags, + NULL); /* ignore time_rec */ + + if (token_ptr != GSS_C_NO_BUFFER) + free (recv_tok.value); + + if (send_tok.length != 0) { + if (verbose) + printf("Sending init_sec_context token (size=%d)...", + (int) send_tok.length); + if (send_token(s, v1_format?0:TOKEN_CONTEXT, &send_tok) < 0) { + (void) gss_release_buffer(&min_stat, &send_tok); + (void) gss_release_name(&min_stat, &target_name); + return -1; + } + } + (void) gss_release_buffer(&min_stat, &send_tok); + + if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) { + display_status("initializing context", maj_stat, + init_sec_min_stat); + (void) gss_release_name(&min_stat, &target_name); + if (*gss_context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&min_stat, gss_context, + GSS_C_NO_BUFFER); + return -1; + } + + if (maj_stat == GSS_S_CONTINUE_NEEDED) { + if (verbose) + printf("continue needed..."); + if (recv_token(s, &token_flags, &recv_tok) < 0) { + (void) gss_release_name(&min_stat, &target_name); + return -1; + } + token_ptr = &recv_tok; + } + if (verbose) + printf("\r\n"); + } while (maj_stat == GSS_S_CONTINUE_NEEDED); + + (void) gss_release_name(&min_stat, &target_name); + } + else { + if (send_token(s, TOKEN_NOOP, empty_token) < 0) + return -1; + } + + return 0; +} + +static void read_file(file_name, in_buf) + char *file_name; + gss_buffer_t in_buf; +{ + int fd, count; + struct stat stat_buf; + + if ((fd = open(file_name, O_RDONLY, 0)) < 0) { + perror("open"); + printf("Couldn't open file %s\r\n", file_name); + exit(1); + } + if (fstat(fd, &stat_buf) < 0) { + perror("fstat"); + exit(1); + } + in_buf->length = stat_buf.st_size; + + if (in_buf->length == 0) { + in_buf->value = NULL; + return; + } + + if ((in_buf->value = malloc(in_buf->length)) == 0) { + printf("Couldn't allocate %d byte buffer for reading file\r\n", + (int) in_buf->length); + exit(1); + } + + /* 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 (count < in_buf->length) + printf("Warning, only read in %d bytes, expected %d\r\n", + count, (int) in_buf->length); +} + +/* + * Function: call_server + * + * Purpose: Call the "sign" service. + * + * Arguments: + * + * host (r) the host providing the service + * port (r) the port to connect to on host + * service_name (r) the GSS-API service name to authenticate to + * gss_flags (r) GSS-API delegation flag (if any) + * auth_flag (r) whether to do authentication + * wrap_flag (r) whether to do message wrapping at all + * encrypt_flag (r) whether to do encryption while wrapping + * mic_flag (r) whether to request a MIC from the server + * msg (r) the message to have "signed" + * use_file (r) whether to treat msg as an input file name + * mcount (r) the number of times to send the message + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * call_server opens a TCP connection to and establishes a + * GSS-API context with service_name over the connection. It then + * seals msg in a GSS-API token with gss_wrap, 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. */ +int call_server(char *host, u_short port, gss_OID oid, char *service_name, + OM_uint32 gss_flags, int auth_flag, + int wrap_flag, int encrypt_flag, int mic_flag, int v1_format, + char *msg, int use_file, int mcount) +{ + gss_ctx_id_t context; + gss_buffer_desc in_buf, out_buf; + int s, state; + OM_uint32 ret_flags; + OM_uint32 maj_stat, min_stat; + gss_name_t src_name, targ_name; + gss_buffer_desc sname, tname; + OM_uint32 lifetime; + gss_OID mechanism, name_type; + int is_local; + OM_uint32 context_flags; + int is_open; + gss_qop_t qop_state; + gss_OID_set mech_names; + gss_buffer_desc oid_name; + size_t i; + int token_flags; + + /* Open connection */ + if ((s = connect_to_server(host, port)) < 0) + return -1; + + /* Establish context */ + if (client_establish_context(s, service_name, gss_flags, auth_flag, + v1_format, oid, &context, + &ret_flags) < 0) { + (void) closesocket(s); + return -1; + } + + if (auth_flag) { + if (verbose) { + /* display the flags */ + /* display_ctx_flags(ret_flags); */ + + /* Get context information */ + maj_stat = gss_inquire_context(&min_stat, context, + &src_name, &targ_name, &lifetime, + &mechanism, &context_flags, + &is_local, + &is_open); + if (maj_stat != GSS_S_COMPLETE) { + display_status("inquiring context", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_display_name(&min_stat, src_name, &sname, + &name_type); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying source name", maj_stat, min_stat); + return -1; + } + maj_stat = gss_display_name(&min_stat, targ_name, &tname, + (gss_OID *) NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying target name", maj_stat, min_stat); + return -1; + } + printf("\"%.*s\" to \"%.*s\", lifetime %d, flags %x, %s, %s\r\n", + (int) sname.length, (char *) sname.value, + (int) tname.length, (char *) tname.value, lifetime, + context_flags, + (is_local) ? "locally initiated" : "remotely initiated", + (is_open) ? "open" : "closed"); + + (void) gss_release_name(&min_stat, &src_name); + (void) gss_release_name(&min_stat, &targ_name); + (void) gss_release_buffer(&min_stat, &sname); + (void) gss_release_buffer(&min_stat, &tname); + + maj_stat = gss_oid_to_str(&min_stat, + name_type, + &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf("Name type of source name is %.*s.\r\n", + (int) oid_name.length, (char *) oid_name.value); + (void) gss_release_buffer(&min_stat, &oid_name); + + /* Now get the names supported by the mechanism */ + maj_stat = gss_inquire_names_for_mech(&min_stat, + mechanism, + &mech_names); + if (maj_stat != GSS_S_COMPLETE) { + display_status("inquiring mech names", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_oid_to_str(&min_stat, + mechanism, + &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf("Mechanism %.*s supports %d names\r\n", + (int) oid_name.length, (char *) oid_name.value, + (int) mech_names->count); + (void) gss_release_buffer(&min_stat, &oid_name); + + for (i=0; icount; i++) { + maj_stat = gss_oid_to_str(&min_stat, + &mech_names->elements[i], + &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf(" %d: %.*s\r\n", (int) i, + (int) oid_name.length, (char *) oid_name.value); + + (void) gss_release_buffer(&min_stat, &oid_name); + } + (void) gss_release_oid_set(&min_stat, &mech_names); + } + } + + if (use_file) { + read_file(msg, &in_buf); + } else { + /* Seal the message */ + in_buf.value = msg; + in_buf.length = strlen(msg); + } + + for (i = 0; i < mcount; i++) { + if (wrap_flag) { + maj_stat = gss_wrap(&min_stat, context, encrypt_flag, GSS_C_QOP_DEFAULT, + &in_buf, &state, &out_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("wrapping message", maj_stat, min_stat); + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } else if (encrypt_flag && ! state) { + fprintf(stderr, "Warning! Message not encrypted.\r\n"); + } + } + else { + out_buf = in_buf; + } + + /* Send to server */ + if (send_token(s, (v1_format?0 + :(TOKEN_DATA | + (wrap_flag ? TOKEN_WRAPPED : 0) | + (encrypt_flag ? TOKEN_ENCRYPTED : 0) | + (mic_flag ? TOKEN_SEND_MIC : 0))), &out_buf) < 0) { + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } + if (out_buf.value != in_buf.value) + (void) gss_release_buffer(&min_stat, &out_buf); + + /* Read signature block into out_buf */ + if (recv_token(s, &token_flags, &out_buf) < 0) { + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } + + if (mic_flag) { + /* Verify signature block */ + maj_stat = gss_verify_mic(&min_stat, context, &in_buf, + &out_buf, &qop_state); + if (maj_stat != GSS_S_COMPLETE) { + display_status("verifying signature", maj_stat, min_stat); + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } + + if (verbose) + printf("Signature verified.\r\n"); + } + else { + if (verbose) + printf("Response received.\r\n"); + } + + free (out_buf.value); + } + + if (use_file) + free(in_buf.value); + + /* Send NOOP */ + if (!v1_format) + (void) send_token(s, TOKEN_NOOP, empty_token); + + if (auth_flag) { + /* Delete context */ + maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("deleting context", maj_stat, min_stat); + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } + + (void) gss_release_buffer(&min_stat, &out_buf); + } + + (void) closesocket(s); + return 0; +} + +static void parse_oid(char *mechanism, gss_OID *oid) +{ + char *mechstr = 0, *cp; + gss_buffer_desc tok; + OM_uint32 maj_stat, min_stat; + + if (isdigit((int) mechanism[0])) { + mechstr = malloc(strlen(mechanism)+5); + if (!mechstr) { + printf("Couldn't allocate mechanism scratch!\r\n"); + return; + } + sprintf(mechstr, "{ %s }", mechanism); + for (cp = mechstr; *cp; cp++) + if (*cp == '.') + *cp = ' '; + tok.value = mechstr; + } else + tok.value = mechanism; + tok.length = strlen(tok.value); + maj_stat = gss_str_to_oid(&min_stat, &tok, oid); + if (maj_stat != GSS_S_COMPLETE) { + display_status("str_to_oid", maj_stat, min_stat); + return; + } + if (mechstr) + free(mechstr); +} + +int +gss (char *server_host, char *service_name, char *mechanism, char *msg, int port, + int verbose, int delegate, int mutual, int replay, int sequence, + int v1_format, int auth_flag, int wrap_flag, + int encrypt_flag, int mic_flag, int ccount, int mcount, char *ccache) +{ + int use_file = 0; + OM_uint32 gss_flags = 0, min_stat; + gss_OID oid = GSS_C_NULL_OID; + OM_uint32 minor_status; + int i; + int rc = 0; + + if (ccount <= 0) ccount = 1; + if (mcount <= 0) mcount = 1; + + if (mechanism && mechanism[0]) + parse_oid(mechanism, &oid); + + if ( delegate ) + gss_flags |= GSS_C_DELEG_FLAG; + if ( mutual ) + gss_flags |= GSS_C_MUTUAL_FLAG; + if ( replay ) + gss_flags |= GSS_C_REPLAY_FLAG; + if ( sequence ) + gss_flags |= GSS_C_SEQUENCE_FLAG; + + /* By using this function the independence between the application and + * the underlying authentication system is broken + */ + if ( ccache && ccache[0] ) + gss_krb5_ccache_name(&minor_status, ccache, NULL); + + for (i = 0; i < ccount; i++) { + if (call_server(server_host, port, oid, service_name, + gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag, + v1_format, msg, use_file, mcount) < 0) + rc = -1; + break; + } + + if (oid != GSS_C_NULL_OID) + (void) gss_release_oid(&min_stat, &oid); + + return rc; +} diff --git a/krb5-1-6/src/windows/gss/gss-misc.c b/krb5-1-6/src/windows/gss/gss-misc.c new file mode 100644 index 000000000..28227e248 --- /dev/null +++ b/krb5-1-6/src/windows/gss/gss-misc.c @@ -0,0 +1,429 @@ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +#include "gss.h" +#include +#include +#include +#include +#include +#include + +FILE *display_file; +DWORD ws_err; + +gss_buffer_desc empty_token_buf = { 0, (void *) "" }; +gss_buffer_t empty_token = &empty_token_buf; + +static void display_status_1 + (char *m, OM_uint32 code, int type); + +static int write_all(int fildes, char *buf, unsigned int nbyte) +{ + int ret; + char *ptr; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + ret = send(fildes, ptr, nbyte, 0); + if (ret < 0) { + ws_err = WSAGetLastError(); + errno = ws_err; + return(ret); + } else if (ret == 0) { + return(ptr-buf); + } + } + + return(ptr-buf); +} + +static int read_all(int s, char *buf, unsigned int nbyte) +{ + int ret; + char *ptr; + fd_set rfds; + struct timeval tv; + + FD_ZERO(&rfds); + FD_SET(s, &rfds); + tv.tv_sec = 10; + tv.tv_usec = 0; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + if ( select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0 || !FD_ISSET(s, &rfds) ) + return(ptr-buf); + ret = recv(s, ptr, nbyte, 0); + if (ret < 0) { + ws_err = WSAGetLastError(); + errno = ws_err; + return(ret); + } else if (ret == 0) { + return(ptr-buf); + } + } + + return(ptr-buf); +} + +/* + * Function: send_token + * + * Purpose: Writes a token to a file descriptor. + * + * Arguments: + * + * s (r) an open file descriptor + * flags (r) the flags to write + * tok (r) the token to write + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * If the flags are non-null, send_token writes the token flags (a + * single byte, even though they're passed in in an integer). Next, + * the token length (as a network long) and then the token data are + * written to the file descriptor s. It returns 0 on success, and -1 + * if an error occurs or if it could not write all the data. + */ +int send_token(int s, int flags, gss_buffer_t tok) +{ + int len, ret; + unsigned char char_flags = (unsigned char) flags; + unsigned char lenbuf[4]; + + if (char_flags) { + ret = write_all(s, (char *)&char_flags, 1); + if (ret != 1) { + my_perror("sending token flags"); + OkMsgBox ("Winsock error %d \n", ws_err); + return -1; + } + } + if (tok->length > 0xffffffffUL) + abort(); + lenbuf[0] = (tok->length >> 24) & 0xff; + lenbuf[1] = (tok->length >> 16) & 0xff; + lenbuf[2] = (tok->length >> 8) & 0xff; + lenbuf[3] = tok->length & 0xff; + + ret = write_all(s, lenbuf, 4); + if (ret < 0) { + my_perror("sending token length"); + OkMsgBox ("Winsock error %d \n", ws_err); + return -1; + } else if (ret != 4) { + if (verbose) + printf("sending token length: %d of %d bytes written\r\n", + ret, 4); + return -1; + } + + ret = write_all(s, tok->value, tok->length); + if (ret < 0) { + my_perror("sending token data"); + OkMsgBox ("Winsock error %d \n", ws_err); + return -1; + } else if (ret != tok->length) { + if (verbose) + printf("sending token data: %d of %d bytes written\r\n", + ret, (int) tok->length); + return -1; + } + + return 0; +} + +/* + * Function: recv_token + * + * Purpose: Reads a token from a file descriptor. + * + * Arguments: + * + * s (r) an open file descriptor + * flags (w) the read flags + * tok (w) the read token + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * recv_token reads the token flags (a single byte, even though + * they're stored into an integer, then reads the token length (as a + * network long), allocates memory to hold the data, and then reads + * the token data from the file descriptor s. It blocks to read the + * length and data, if necessary. On a successful return, the token + * should be freed with gss_release_buffer. It returns 0 on success, + * and -1 if an error occurs or if it could not read all the data. + */ +int recv_token(int s, int * flags, gss_buffer_t tok) +{ + int ret; + unsigned char char_flags; + unsigned char lenbuf[4]; + + ret = read_all(s, (char *) &char_flags, 1); + if (ret < 0) { + my_perror("reading token flags"); + OkMsgBox ("Winsock error %d \n", ws_err); + return -1; + } else if (! ret) { + if (display_file) + printf("reading token flags: 0 bytes read\r\n", display_file); + return -1; + } else { + *flags = (int) char_flags; + } + + if (char_flags == 0 ) { + lenbuf[0] = 0; + ret = read_all(s, &lenbuf[1], 3); + if (ret < 0) { + my_perror("reading token length"); + OkMsgBox ("Winsock error %d \n", ws_err); + return -1; + } else if (ret != 3) { + if (verbose) + printf("reading token length: %d of %d bytes read\r\n", + ret, 3); + return -1; + } + } + else { + ret = read_all(s, lenbuf, 4); + if (ret < 0) { + my_perror("reading token length"); + OkMsgBox ("Winsock error %d \n", ws_err); + return -1; + } else if (ret != 4) { + if (verbose) + printf("reading token length: %d of %d bytes read\r\n", + ret, 4); + return -1; + } + } + + tok->length = ((lenbuf[0] << 24) + | (lenbuf[1] << 16) + | (lenbuf[2] << 8) + | lenbuf[3]); + tok->value = (char *) malloc(tok->length ? tok->length : 1); + if (tok->length && tok->value == NULL) { + if (verbose) + printf("Out of memory allocating token data\r\n"); + return -1; + } + + ret = read_all(s, (char *) tok->value, tok->length); + if (ret < 0) { + my_perror("reading token data"); + OkMsgBox ("Winsock error %d \n", ws_err); + free(tok->value); + return -1; + } else if (ret != tok->length) { + printf("sending token data: %d of %d bytes written\r\n", + ret, (int) tok->length); + free(tok->value); + return -1; + } + + return 0; +} + +void +free_token(gss_buffer_t tok) +{ + if (tok->length <= 0 || tok->value == NULL) + return; + + free(tok->value); + tok->value = NULL; + tok->length = 0; +} + +/*+ + * Function: display_status + * + * Purpose: displays GSS-API messages + * + * Arguments: + * + * msg a string to be displayed with the message + * maj_stat the GSS-API major status code + * min_stat the GSS-API minor status code + * + * Effects: + * + * The GSS-API messages associated with maj_stat and min_stat are + * displayed on stderr, each preceeded by "GSS-API error : " and + * followed by a newline. + */ +void +display_status (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) { + display_status_1(msg, maj_stat, GSS_C_GSS_CODE); + display_status_1(msg, min_stat, GSS_C_MECH_CODE); +} + +static void +display_status_1(char *m, OM_uint32 code, int type) { + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + maj_stat = gss_display_status(&min_stat, code, + type, GSS_C_NULL_OID, + &msg_ctx, &msg); + if (verbose) + printf("GSS-API error %s: %s\r\n", m, + (char *)msg.value); + OkMsgBox ("GSS-API error %s: %s\n", m, + (char *)msg.value); + (void) gss_release_buffer(&min_stat, &msg); + + if (!msg_ctx) + break; + } +} + +/* + * Function: display_ctx_flags + * + * Purpose: displays the flags returned by context initation in + * a human-readable form + * + * Arguments: + * + * int ret_flags + * + * Effects: + * + * Strings corresponding to the context flags are printed on + * stdout, preceded by "context flag: " and followed by a newline + */ + +void display_ctx_flags(flags) + OM_uint32 flags; +{ + if (flags & GSS_C_DELEG_FLAG) + printf("context flag: GSS_C_DELEG_FLAG\r\n"); + if (flags & GSS_C_MUTUAL_FLAG) + printf("context flag: GSS_C_MUTUAL_FLAG\r\n"); + if (flags & GSS_C_REPLAY_FLAG) + printf("context flag: GSS_C_REPLAY_FLAG\r\n"); + if (flags & GSS_C_SEQUENCE_FLAG) + printf("context flag: GSS_C_SEQUENCE_FLAG\r\n"); + if (flags & GSS_C_CONF_FLAG ) + printf("context flag: GSS_C_CONF_FLAG \r\n"); + if (flags & GSS_C_INTEG_FLAG ) + printf("context flag: GSS_C_INTEG_FLAG \r\n"); +} + +void print_token(tok) + gss_buffer_t tok; +{ + int i; + unsigned char *p = tok->value; + + if (!verbose) + return; + for (i=0; i < tok->length; i++, p++) { + printf("%02x ", *p); + if ((i % 16) == 15) { + printf("\r\n"); + } + } + printf("\r\n"); +} + + +int gettimeofday (struct timeval *tv, void *ignore_tz) +{ + struct _timeb tb; + _tzset(); + _ftime(&tb); + if (tv) { + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000; + } + return 0; +} + +/*+************************************************************************* +** +** OkMsgBox +** +** A MessageBox version of printf +** +***************************************************************************/ +void +OkMsgBox (char *format, ...) { + char buf[256]; // Message goes into here + char *args; // Args for printf + + args = (char *) &format + sizeof(format); + vsprintf (buf, format, args); + MessageBox(NULL, buf, "", MB_OK); +} +/*+************************************************************************* +** +** My_perror +** +** A windows conversion of perror displaying the output into a MessageBox. +** +***************************************************************************/ +void +my_perror (char *msg) { + char *err; + + err = strerror (errno); + + if (msg && *msg != '\0') + OkMsgBox ("%s: %s", msg, err); + else + MessageBox (NULL, err, "", MB_OK); +} + diff --git a/krb5-1-6/src/windows/gss/gss-misc.h b/krb5-1-6/src/windows/gss/gss-misc.h new file mode 100644 index 000000000..35b3b7390 --- /dev/null +++ b/krb5-1-6/src/windows/gss/gss-misc.h @@ -0,0 +1,60 @@ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#ifndef _GSSMISC_H_ +#define _GSSMISC_H_ + +#include +#include + +extern FILE *display_file; + +int send_token + (int s, int flags, gss_buffer_t tok); +int recv_token + (int s, int *flags, gss_buffer_t tok); +void display_status + (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat); +void display_ctx_flags + (OM_uint32 flags); +void print_token + (gss_buffer_t tok); + +/* Token types */ +#define TOKEN_NOOP (1<<0) +#define TOKEN_CONTEXT (1<<1) +#define TOKEN_DATA (1<<2) +#define TOKEN_MIC (1<<3) + +/* Token flags */ +#define TOKEN_CONTEXT_NEXT (1<<4) +#define TOKEN_WRAPPED (1<<5) +#define TOKEN_ENCRYPTED (1<<6) +#define TOKEN_SEND_MIC (1<<7) + +extern gss_buffer_t empty_token; + +#endif diff --git a/krb5-1-6/src/windows/gss/gss.c b/krb5-1-6/src/windows/gss/gss.c new file mode 100644 index 000000000..f42d293ea --- /dev/null +++ b/krb5-1-6/src/windows/gss/gss.c @@ -0,0 +1,722 @@ +/* + * Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/*+************************************************************************* +** +** GSS test - Windows scaffolding to test the gssapi dll +** +** Given a hostname it does the equivalent of the Unix command +** ./gss-client [-port ] host@ "msg" +** +***************************************************************************/ +#include +#include +#include +#include +#include "gss.h" +#include +#ifdef USE_LEASH +#include +#endif + +#include "resource.h" + +#define GSSAPI_INI "gsstest.ini" // Which INI file +#define INI_HOSTS "GSSAPI Hosts" // INI file section +#define INI_HOST "Host" // INI file line label +#define INI_SVCS "GSSAPI Services" // INI file section +#define INI_SVC "Service" // INI file line label +#define INI_MSGS "GSSAPI Messages" // INI file section +#define INI_MSG "Message" // INI file line label +#define INI_MECHS "GSSAPI Mechanisms" // INI file section +#define INI_MECH "Mech" // INI file line label +#define INI_LAST "GSSAPI Most Recent" +#define INI_LAST_HOST "Host" +#define INI_LAST_PORT "Port" +#define INI_LAST_SVC "Service" +#define INI_LAST_MECH "Mechanism" +#define INI_LAST_MSG "Message" +#define INI_LAST_DELEGATE "Delegation" +#define INI_LAST_SEQUENCE "Sequence" +#define INI_LAST_MUTUAL "Mutual" +#define INI_LAST_REPLAY "Replay" +#define INI_LAST_VERBOSE "Verbose" +#define INI_LAST_CCOUNT "Call Count" +#define INI_LAST_MCOUNT "Message Count" +#define INI_LAST_VER1 "Version One" +#define INI_LAST_NOAUTH "No Auth" +#define INI_LAST_NOWRAP "No Wrap" +#define INI_LAST_NOCRYPT "No Encrypt" +#define INI_LAST_NOMIC "No Mic" +#define INI_LAST_CCACHE "CCache" + +#define MAX_SAVED 9 +char hosts[MAX_SAVED][256]; +char svcs[MAX_SAVED][256]; +char msgs[MAX_SAVED][256]; +char mechs[MAX_SAVED][256]; +char szHost[256]; // GSSAPI Host to connect to +char szService[256]; // Service to do +char szMessage[256]; // Message to send +char szMech[256]; // OID to use +char szCCache[256]; // CCache to use +int port = 0; // Which port to use +int delegate = 0; // Delegate? +int replay = 1; // Replay? +int mutual = 1; // Mutual? +int sequence = 0; // Sequence? +int verbose = 1; // Verbose? +int ccount = 1; // Call Count +int mcount = 1; // Message Count +int gssv1 = 0; // Version 1? +int noauth = 0; // No Auth? +int nowrap = 0; // No Wrap? +int nocrypt = 0; // No Crypt? +int nomic = 0; // No Mic? + +HWND hDialog = 0; + +static void do_gssapi_test (void); +static void parse_name (char *name); +static void read_saved(void); +static void write_saved (void); +static void update_saved (void); +static void fill_combo (HWND hDlg); + +/*+************************************************************************* +** +** WinMain +** +** Sets up the Dialog that drives our program +** +***************************************************************************/ +int __stdcall +WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) +{ + WSADATA wsadata; + WORD versionrequested; + int rc; + + InitCommonControls(); + + versionrequested = 0x0101; /* Version 1.1 */ + rc = WSAStartup(versionrequested, &wsadata); + if (rc) { + MessageBox(NULL, "Couldn't initialize Winsock library", "", + MB_OK | MB_ICONSTOP); + return FALSE; + } + if (versionrequested != wsadata.wVersion) { + WSACleanup(); + MessageBox(NULL, "Winsock version 1.1 not available", "", + MB_OK | MB_ICONSTOP); + return FALSE; + } + + rc = DialogBoxParam (hInstance, "GSSAPIDLG", HWND_DESKTOP, OpenGssapiDlg, 0L); + rc = GetLastError(); + + WSACleanup(); + return 0; +} +/*+************************************************************************* +** +** Do_gssapi_test +** +** Does the actual call to GSS-client +** +***************************************************************************/ +void +do_gssapi_test (void) { + int n; // Return value + HCURSOR hcursor; // For the hourglass cursor + + hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + n = gss (szHost, szService, szMech, szMessage[0] ? szMessage : "Test Gssapi Message", port, + verbose, delegate, mutual, replay, sequence, + gssv1, !noauth, !nowrap, !nocrypt, !nomic, ccount, mcount, + szCCache); + SetCursor(hcursor); + + if (n) + MessageBox (NULL, "gss failed", "", IDOK | MB_ICONINFORMATION); +} + +/*+************************************************************************* +** +** OpenGssapiDlg(HWND, unsigned, WORD, LONG) +** +** Processes messages for "Open Gssapi Connection" dialog box +** +** Messages: +** WM_INITDIALOG - initialize dialog box +** WM_COMMAND - Input received +** +***************************************************************************/ +INT_PTR CALLBACK +OpenGssapiDlg( + HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + HDC hDC; // For getting graphic info + DWORD Ext; // Size of dialog + int xExt, yExt; // Size broken apart + char buff[64]; + + switch (message) { + case WM_INITDIALOG: + hDialog = hDlg; + /* + ** First center the dialog + */ + hDC = GetDC(hDlg); + Ext = GetDialogBaseUnits(); + xExt = (190 *LOWORD(Ext)) /4 ; + yExt = (72 * HIWORD(Ext)) /8 ; + SetWindowPos(hDlg, NULL, + (GetSystemMetrics(SM_CXSCREEN)/2)-(xExt/2), + (GetSystemMetrics(SM_CYSCREEN)/2)-(yExt/2), + 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); + ReleaseDC(hDlg, hDC); + + SendDlgItemMessage(hDlg, GSS_HOST_NAME, CB_LIMITTEXT, sizeof(szHost), 0); + read_saved (); // Get the host list + fill_combo (hDlg); // Put into combo box + + SendMessage(hDlg, WM_SETFOCUS, 0, 0); + return (TRUE); + + case WM_HSCROLL: + switch (LOWORD(wParam)) { + case TB_THUMBTRACK: + case TB_THUMBPOSITION: + { + long pos = HIWORD(wParam); // the position of the slider + int ctrlID = GetDlgCtrlID((HWND)lParam); + + if (ctrlID == GSS_CALL_COUNT) { + sprintf(buff,"Call Count: %d",pos); + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_CCOUNT),buff); + } + if (ctrlID == GSS_MESSAGE_COUNT) { + sprintf(buff,"Message Count: %d",pos); + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_MSG_COUNT),buff); + } + } + break; + case TB_BOTTOM: + case TB_TOP: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + default: + { + int ctrlID = GetDlgCtrlID((HWND)lParam); + long pos = SendMessage(GetDlgItem(hDialog,ctrlID), TBM_GETPOS, 0, 0); // the position of the slider + + if (ctrlID == GSS_CALL_COUNT) { + sprintf(buff,"Call Count: %d",pos); + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_CCOUNT),buff); + } + if (ctrlID == GSS_MESSAGE_COUNT) { + sprintf(buff,"Message Count: %d",pos); + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_MSG_COUNT),buff); + } + } + } + break; + + + case WM_COMMAND: + switch (wParam) { + case GSS_CANCEL: // Only way out of the dialog + case IDCANCEL: // From the menu + EndDialog(hDlg, FALSE); + break; + + case GSS_OK: + GetDlgItemText(hDlg, GSS_HOST_NAME, szHost, 256); + SendDlgItemMessage(hDlg, GSS_HOST_NAME, CB_SHOWDROPDOWN, FALSE, 0); + + if (!*szHost) { + MessageBox(hDlg, "You must enter a host name", NULL, MB_OK); + break; + } + + GetDlgItemText(hDlg, GSS_SERVICE_NAME, szService, 256); + SendDlgItemMessage(hDlg, GSS_SERVICE_NAME, CB_SHOWDROPDOWN, FALSE, 0); + + if (!*szService) { + MessageBox(hDlg, "You must enter a service name", NULL, MB_OK); + break; + } + + GetDlgItemText(hDlg, GSS_MECHANISM, szMech, 256); + GetDlgItemText(hDlg, GSS_CCACHE_NAME, szCCache, 256); + GetDlgItemText(hDlg, GSS_MESSAGE, szMessage, 256); + GetDlgItemText(hDlg, GSS_PORT, buff, 32); + if (!*buff) { + MessageBox(hDlg, "You must enter a valid port number", NULL, MB_OK); + break; + } + port = atoi(buff); + if (port == 0 || port == -1) + port = 4444; + + ccount = SendDlgItemMessage( hDlg, GSS_CALL_COUNT, TBM_GETPOS, 0, 0); + mcount = SendDlgItemMessage( hDlg, GSS_MESSAGE_COUNT, TBM_GETPOS, 0, 0); + + verbose = IsDlgButtonChecked(hDlg, GSS_VERBOSE); + delegate = IsDlgButtonChecked(hDlg, GSS_DELEGATION); + mutual = IsDlgButtonChecked(hDlg, GSS_MUTUAL); + replay = IsDlgButtonChecked(hDlg, GSS_REPLAY); + sequence = IsDlgButtonChecked(hDlg, GSS_SEQUENCE); + gssv1 = IsDlgButtonChecked(hDlg, GSS_VERSION_ONE); + + noauth = IsDlgButtonChecked(hDlg, GSS_NO_AUTH); + if ( noauth ) { + nowrap = nocrypt = nomic = 0; + } else { + nowrap = IsDlgButtonChecked(hDlg, GSS_NO_WRAP); + nocrypt = IsDlgButtonChecked(hDlg, GSS_NO_ENCRYPT); + nomic = IsDlgButtonChecked(hDlg, GSS_NO_MIC); + } + + update_saved (); // Add it to the host list + fill_combo (hDlg); // Update the combo box + SetDlgItemText(hDlg, GSS_OUTPUT, ""); + do_gssapi_test (); // Test GSSAPI + + //EndDialog(hDlg, TRUE); + break; + + case GSS_NO_AUTH: + if ( IsDlgButtonChecked(hDlg, GSS_NO_AUTH) ) { + // disable the other no_xxx options + EnableWindow(GetDlgItem(hDlg, GSS_NO_WRAP), FALSE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_ENCRYPT), FALSE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_MIC), FALSE); + } else { + // enable the other no_xxx options + EnableWindow(GetDlgItem(hDlg, GSS_NO_WRAP), TRUE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_ENCRYPT), TRUE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_MIC), TRUE); + } + break; + } + return FALSE; + } + return FALSE; + +} +/*+************************************************************************* +** +** Parse_name +** +** Turns NAME which the user entered into host, service and port. +** The host is up to first space, port is after that and service is made +** from host. +** +***************************************************************************/ +static void +parse_name (char *name) { + char *ptr; + char seps[] = " ,\t"; + char tempname[256]; + + memset( &tempname[0], '\0', 256 ); + strcpy( tempname, name); + ptr = strtok( tempname, seps); + if (ptr != NULL ){ + strcpy( szHost, ptr ); + } else { + wsprintf( szHost, "k5test" ); + } + if(ptr){ + ptr = strtok( NULL, seps); + } + if( ptr ){ + port = atoi (ptr); + } + if( ptr ){ + ptr = strtok( NULL, seps); + } + if( ptr ){ + strcpy( szService, ptr ); + }else{ + wsprintf (szService, "sample@%s", szHost); // Make the service name + } + if( ptr ){ + ptr = strtok( NULL, seps); + } + if( ptr ){ + wsprintf (szMech, "{ %s }", ptr); // Put in the OID + for (ptr = szMech; *ptr; ptr++) + if (*ptr == '.') + *ptr = ' '; + } else { + szMech[0] = 0; + } + +} +/*+************************************************************************* +** +** read_saved +** +** Reads all the hosts listed in the INI file. +** +***************************************************************************/ +static void +read_saved (void) { + int i; /* Index */ + char buff[32]; + + for (i = 0; MAX_SAVED; ++i) { /* Read this many entries */ + wsprintf (buff, INI_HOST "%d", i); + GetPrivateProfileString(INI_HOSTS, buff, "", hosts[i], 256, GSSAPI_INI); + if (*hosts[i] == '\0') /* No more entries??? */ + break; + } + for (i = 0; MAX_SAVED; ++i) { /* Read this many entries */ + wsprintf (buff, INI_SVC "%d", i); + GetPrivateProfileString(INI_SVCS, buff, "", svcs[i], 256, GSSAPI_INI); + if (*svcs[i] == '\0') /* No more entries??? */ + break; + } + for (i = 0; MAX_SAVED; ++i) { /* Read this many entries */ + wsprintf (buff, INI_MSG "%d", i); + GetPrivateProfileString(INI_MSGS, buff, "", msgs[i], 256, GSSAPI_INI); + if (*msgs[i] == '\0') /* No more entries??? */ + break; + } + for (i = 0; MAX_SAVED; ++i) { /* Read this many entries */ + wsprintf (buff, INI_MECH "%d", i); + GetPrivateProfileString(INI_MECHS, buff, "", mechs[i], 256, GSSAPI_INI); + if (*mechs[i] == '\0') /* No more entries??? */ + break; + } + GetPrivateProfileString(INI_LAST, INI_LAST_HOST, "", szHost, 256, GSSAPI_INI); + GetPrivateProfileString(INI_LAST, INI_LAST_PORT, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + port = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_SVC, "", szService, 256, GSSAPI_INI); + GetPrivateProfileString(INI_LAST, INI_LAST_MSG, "", szMessage, 256, GSSAPI_INI); + GetPrivateProfileString(INI_LAST, INI_LAST_MECH, "", szMech, 256, GSSAPI_INI); + GetPrivateProfileString(INI_LAST, INI_LAST_CCACHE, "", szCCache, 256, GSSAPI_INI); + GetPrivateProfileString(INI_LAST, INI_LAST_DELEGATE, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + delegate = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_MUTUAL, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + mutual = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_REPLAY, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + replay = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_SEQUENCE, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + sequence = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_VERBOSE, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + verbose = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_CCOUNT, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + ccount = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_MCOUNT, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + mcount = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_VER1, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + gssv1 = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_NOAUTH, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + noauth = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_NOWRAP, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + nowrap = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_NOCRYPT, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + nocrypt = atoi(buff); + GetPrivateProfileString(INI_LAST, INI_LAST_NOMIC, "", buff, 32, GSSAPI_INI); + if ( buff[0] ) + nomic = atoi(buff); +} + +/*+************************************************************************* +** +** write_saved +** +** Writes the hosts list back to the ini file. +** +***************************************************************************/ +static void +write_saved () { + int i; // Index + char buff[32]; + + for (i = 0; i < MAX_SAVED; ++i) { + if (*hosts[i] == '\0') // End of the list? + break; + wsprintf (buff, INI_HOST "%d", i); + WritePrivateProfileString(INI_HOSTS, buff, hosts[i], GSSAPI_INI); + } + for (i = 0; i < MAX_SAVED; ++i) { + if (*svcs[i] == '\0') // End of the list? + break; + wsprintf (buff, INI_SVC "%d", i); + WritePrivateProfileString(INI_SVCS, buff, svcs[i], GSSAPI_INI); + } + for (i = 0; i < MAX_SAVED; ++i) { + if (*msgs[i] == '\0') // End of the list? + break; + wsprintf (buff, INI_MSG "%d", i); + WritePrivateProfileString(INI_MSGS, buff, msgs[i], GSSAPI_INI); + } + for (i = 0; i < MAX_SAVED; ++i) { + if (*mechs[i] == '\0') // End of the list? + break; + wsprintf (buff, INI_MECH "%d", i); + WritePrivateProfileString(INI_MECHS, buff, mechs[i], GSSAPI_INI); + } + WritePrivateProfileString(INI_LAST, INI_LAST_HOST, szHost, GSSAPI_INI); + wsprintf(buff, "%d", port); + WritePrivateProfileString(INI_LAST, INI_LAST_PORT, buff, GSSAPI_INI); + WritePrivateProfileString(INI_LAST, INI_LAST_SVC, szService, GSSAPI_INI); + WritePrivateProfileString(INI_LAST, INI_LAST_MECH, szMech, GSSAPI_INI); + WritePrivateProfileString(INI_LAST, INI_LAST_CCACHE, szCCache, GSSAPI_INI); + WritePrivateProfileString(INI_LAST, INI_LAST_MSG, szMessage, GSSAPI_INI); + wsprintf(buff, "%d", delegate); + WritePrivateProfileString(INI_LAST, INI_LAST_DELEGATE, buff, GSSAPI_INI); + wsprintf(buff, "%d", mutual); + WritePrivateProfileString(INI_LAST, INI_LAST_MUTUAL, buff, GSSAPI_INI); + wsprintf(buff, "%d", replay); + WritePrivateProfileString(INI_LAST, INI_LAST_REPLAY, buff, GSSAPI_INI); + wsprintf(buff, "%d", sequence); + WritePrivateProfileString(INI_LAST, INI_LAST_SEQUENCE, buff, GSSAPI_INI); + wsprintf(buff, "%d", verbose); + WritePrivateProfileString(INI_LAST, INI_LAST_VERBOSE, buff, GSSAPI_INI); + wsprintf(buff, "%d", ccount); + WritePrivateProfileString(INI_LAST, INI_LAST_CCOUNT, buff, GSSAPI_INI); + wsprintf(buff, "%d", mcount); + WritePrivateProfileString(INI_LAST, INI_LAST_MCOUNT, buff, GSSAPI_INI); + wsprintf(buff, "%d", gssv1); + WritePrivateProfileString(INI_LAST, INI_LAST_VER1, buff, GSSAPI_INI); + wsprintf(buff, "%d", noauth); + WritePrivateProfileString(INI_LAST, INI_LAST_NOAUTH, buff, GSSAPI_INI); + wsprintf(buff, "%d", nowrap); + WritePrivateProfileString(INI_LAST, INI_LAST_NOWRAP, buff, GSSAPI_INI); + wsprintf(buff, "%d", nocrypt); + WritePrivateProfileString(INI_LAST, INI_LAST_NOCRYPT, buff, GSSAPI_INI); + wsprintf(buff, "%d", nomic); + WritePrivateProfileString(INI_LAST, INI_LAST_NOMIC, buff, GSSAPI_INI); +} +/*+************************************************************************* +** +** Update_saved +** +** Updates the host list with the new NAME the user typed. +** +***************************************************************************/ +static void +update_saved (void) { + int i; // Index + + for (i = 0; i < MAX_SAVED-1; ++i) { // Find it in the list + if (! _stricmp (szHost, hosts[i])) // A match + break; + if (*hosts[i] == '\0') // End of the list + break; + } + memmove (hosts[1], hosts[0], i * sizeof(hosts[0])); // Move the data down + strcpy (hosts[0], szHost); // Insert this item + + for (i = 0; i < MAX_SAVED-1; ++i) { // Find it in the list + if (! _stricmp (szService, svcs[i])) // A match + break; + if (*svcs[i] == '\0') // End of the list + break; + } + memmove (svcs[1], svcs[0], i * sizeof(svcs[0])); // Move the data down + strcpy (svcs[0], szService); // Insert this item + + for (i = 0; i < MAX_SAVED-1; ++i) { // Find it in the list + if (! _stricmp (szMessage, msgs[i])) // A match + break; + if (*msgs[i] == '\0') // End of the list + break; + } + memmove (msgs[1], msgs[0], i * sizeof(msgs[0])); // Move the data down + strcpy (msgs[0], szMessage); // Insert this item + + for (i = 0; i < MAX_SAVED-1; ++i) { // Find it in the list + if (! _stricmp (szMech, mechs[i])) // A match + break; + if (*mechs[i] == '\0') // End of the list + break; + } + memmove (mechs[1], mechs[0], i * sizeof(hosts[0])); // Move the data down + strcpy (mechs[0], szMech); // Insert this item + + write_saved (); +} +/*+************************************************************************* +** +** Fill_combo +** +** Fills the combo box with the contents of the host list. Item 0 goes +** into the edit portion and the rest go into the libt box. +** +***************************************************************************/ +static void +fill_combo (HWND hDlg) { + int i; // Index + char buff[256]; +#ifdef USE_LEASH + krb5_error_code retval; + apiCB * cc_ctx = 0; + struct _infoNC ** pNCi = 0; +#endif + + SendDlgItemMessage(hDlg, GSS_HOST_NAME, CB_RESETCONTENT, 0, 0); + SetDlgItemText(hDlg, GSS_HOST_NAME, szHost); + SendDlgItemMessage(hDlg, GSS_HOST_NAME, CB_SETEDITSEL, 0, 0); + for (i = 1; i < MAX_SAVED; ++i) { // Fill in the list box + if (*hosts[i] == '\0') + break; + SendDlgItemMessage(hDlg, GSS_HOST_NAME, CB_ADDSTRING, 0, (LPARAM) ((LPSTR) hosts[i])); + } + + SendDlgItemMessage(hDlg, GSS_SERVICE_NAME, CB_RESETCONTENT, 0, 0); + SetDlgItemText(hDlg, GSS_SERVICE_NAME, szService); + SendDlgItemMessage(hDlg, GSS_SERVICE_NAME, CB_SETEDITSEL, 0, 0); + for (i = 1; i < MAX_SAVED; ++i) { // Fill in the list box + if (*svcs[i] == '\0') + break; + SendDlgItemMessage(hDlg, GSS_SERVICE_NAME, CB_ADDSTRING, 0, (LPARAM) ((LPSTR) svcs[i])); + } + + SendDlgItemMessage(hDlg, GSS_MECHANISM, CB_RESETCONTENT, 0, 0); + SetDlgItemText(hDlg, GSS_MECHANISM, szMech); + SendDlgItemMessage(hDlg, GSS_MECHANISM, CB_SETEDITSEL, 0, 0); + for (i = 1; i < MAX_SAVED; ++i) { // Fill in the list box + if (*mechs[i] == '\0') + break; + SendDlgItemMessage(hDlg, GSS_MECHANISM, CB_ADDSTRING, 0, (LPARAM) ((LPSTR) mechs[i])); + } + + SendDlgItemMessage(hDlg, GSS_CCACHE_NAME, CB_RESETCONTENT, 0, 0); + SetDlgItemText(hDlg, GSS_CCACHE_NAME, szCCache); + SendDlgItemMessage(hDlg, GSS_CCACHE_NAME, CB_SETEDITSEL, 0, 0); + +#ifdef USE_LEASH + retval = cc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL); + if (retval) + goto skip_ccache; + + retval = cc_get_NC_info(cc_ctx, &pNCi); + if (retval) + goto clean_ccache; + + for ( i=0; pNCi[i]; i++ ) { + if (pNCi[i]->vers == CC_CRED_V5) { + sprintf(buff,"API:%s",pNCi[i]->name); + SendDlgItemMessage(hDlg, GSS_CCACHE_NAME, CB_ADDSTRING, 0, (LPARAM) ((LPSTR) buff)); + } + } + + clean_ccache: + if (pNCi) + cc_free_NC_info(cc_ctx, &pNCi); + if (cc_ctx) + cc_shutdown(&cc_ctx); + skip_ccache: +#endif /* USE_LEASH */ + if ( szCCache[0] ) + SendDlgItemMessage(hDlg, GSS_CCACHE_NAME, CB_ADDSTRING, 0, (LPARAM) ((LPSTR) szCCache)); + SendDlgItemMessage(hDlg, GSS_CCACHE_NAME, CB_ADDSTRING, 0, (LPARAM) ((LPSTR) "MSLSA:")); + + SendDlgItemMessage(hDlg, GSS_MESSAGE, CB_RESETCONTENT, 0, 0); + SetDlgItemText(hDlg, GSS_MESSAGE, szMessage); + SendDlgItemMessage(hDlg, GSS_MESSAGE, CB_SETEDITSEL, 0, 0); + for (i = 1; i < MAX_SAVED; ++i) { // Fill in the list box + if (*msgs[i] == '\0') + break; + SendDlgItemMessage(hDlg, GSS_MESSAGE, CB_ADDSTRING, 0, (LPARAM) ((LPSTR) msgs[i])); + } + + wsprintf(buff, "%d", port); + SetDlgItemText(hDlg, GSS_PORT, buff); + + CheckDlgButton(hDlg, GSS_VERBOSE, verbose); + CheckDlgButton(hDlg, GSS_DELEGATION, delegate); + CheckDlgButton(hDlg, GSS_MUTUAL, mutual); + CheckDlgButton(hDlg, GSS_REPLAY, replay); + CheckDlgButton(hDlg, GSS_SEQUENCE, sequence); + CheckDlgButton(hDlg, GSS_VERSION_ONE, gssv1); + CheckDlgButton(hDlg, GSS_NO_AUTH, noauth); + CheckDlgButton(hDlg, GSS_NO_WRAP, nowrap); + CheckDlgButton(hDlg, GSS_NO_ENCRYPT, nocrypt); + CheckDlgButton(hDlg, GSS_NO_MIC, nomic); + + if ( noauth ) { + // disable the other no_xxx options + EnableWindow(GetDlgItem(hDlg, GSS_NO_WRAP), FALSE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_ENCRYPT), FALSE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_MIC), FALSE); + } else { + // enable the other no_xxx options + EnableWindow(GetDlgItem(hDlg, GSS_NO_WRAP), TRUE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_ENCRYPT), TRUE); + EnableWindow(GetDlgItem(hDlg, GSS_NO_MIC), TRUE); + } + + SendDlgItemMessage(hDlg, GSS_CALL_COUNT, TBM_SETRANGEMIN, (WPARAM) FALSE, (LPARAM) 1); + SendDlgItemMessage(hDlg, GSS_CALL_COUNT, TBM_SETRANGEMAX, (WPARAM) FALSE, (LPARAM) 20); + SendDlgItemMessage(hDlg, GSS_CALL_COUNT, TBM_SETPOS, (WPARAM) FALSE, (LPARAM) ccount); + sprintf(buff,"Call Count: %d",ccount); + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_CCOUNT),buff); + + SendDlgItemMessage(hDlg, GSS_MESSAGE_COUNT, TBM_SETRANGEMIN, (WPARAM) FALSE, (LPARAM) 1); + SendDlgItemMessage(hDlg, GSS_MESSAGE_COUNT, TBM_SETRANGEMAX, (WPARAM) FALSE, (LPARAM) 20); + SendDlgItemMessage(hDlg, GSS_MESSAGE_COUNT, TBM_SETPOS, (WPARAM) FALSE, (LPARAM) mcount); + sprintf(buff,"Message Count: %d",mcount); + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_MSG_COUNT),buff); +} + +int +gss_printf (const char *format, ...) { + static char myprtfstr[4096]; + int i, len, rc=0; + char *cp; + va_list ap; + + va_start(ap, format); + rc = _vsnprintf(myprtfstr, sizeof(myprtfstr)-1, format, ap); + va_end(ap); + + SendDlgItemMessage(hDialog, GSS_OUTPUT, EM_REPLACESEL, FALSE, (LPARAM) myprtfstr); + return rc; +} diff --git a/krb5-1-6/src/windows/gss/gss.def b/krb5-1-6/src/windows/gss/gss.def new file mode 100644 index 000000000..f49806698 --- /dev/null +++ b/krb5-1-6/src/windows/gss/gss.def @@ -0,0 +1,15 @@ +; +; Gss - tests the GSSAPI dll +; + +NAME GSS +DESCRIPTION 'Tests the gssapi dll' + +EXETYPE windows +STUB 'winstub.exe' +CODE preload moveable +DATA preload moveable multiple +HEAPSIZE 1024 +STACKSIZE 4096 + +EXPORTS OpenGssapiDlg diff --git a/krb5-1-6/src/windows/gss/gss.h b/krb5-1-6/src/windows/gss/gss.h new file mode 100644 index 000000000..60d91bf6b --- /dev/null +++ b/krb5-1-6/src/windows/gss/gss.h @@ -0,0 +1,43 @@ +/*+************************************************************************* +** +** gss.h +** +** +***************************************************************************/ +#include +#include "winsock.h" +#include + +#include +#include + +// gss.c +INT_PTR CALLBACK OpenGssapiDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +// gss-misc.c +int send_token(int s, int flags, gss_buffer_t tok); +int recv_token(int s, int *flags, gss_buffer_t tok); +void free_token(gss_buffer_t tok); +void display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat); +static void display_status_1(char *m, OM_uint32 code, int type); +void OkMsgBox (char *format, ...); +void my_perror (char *msg); + +// gss-client.c +int +gss (char *server_host, char *service_name, char *mechanism, char *msg, int port, + int verbose, int delegate, int mutual, int replay, int sequence, + int v1_format, int auth_flag, int wrap_flag, + int encrypt_flag, int mic_flag, int ccount, int mcount, char * ccache); +int call_server(char *host, u_short port, gss_OID oid, char *service_name, + OM_uint32 deleg_flag, int auth_flag, + int wrap_flag, int encrypt_flag, int mic_flag, int v1_format, + char *msg, int use_file, int mcount); +int connect_to_server(char *host, u_short port); +int client_establish_context(int s, char *service_name, OM_uint32 deleg_flag, + int auth_flag, int v1_format, gss_OID oid, + gss_ctx_id_t *gss_context, OM_uint32 *ret_flags); + + +extern int verbose; +#define printf gss_printf diff --git a/krb5-1-6/src/windows/gss/gss.ico b/krb5-1-6/src/windows/gss/gss.ico new file mode 100644 index 0000000000000000000000000000000000000000..8cd96a18a5ac029bc2e3e07d6b601e39a0703b20 GIT binary patch literal 766 zcmc(bF>b>!3`OapyHW(`YL8uWg7j#LlD~+F_$CHT$6Ch!fh8{>=iI%m zJ?5O7>5GP;g`Z9sy=XgC%|#@&9I|RjJ)!~ST;-6V0}V`$0{ytiVMs*=F3&e%K<J3M|@3JCXHI=YoMq#uc-nWjrouYrXGT}MmZeEuD040CM6951J literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/gss/gss.rc b/krb5-1-6/src/windows/gss/gss.rc new file mode 100644 index 000000000..46cf6424e --- /dev/null +++ b/krb5-1-6/src/windows/gss/gss.rc @@ -0,0 +1,148 @@ +// Microsoft Visual C++ generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +GSS ICON "gss.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +GSSAPIDLG DIALOGEX 63, 65, 330, 311 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Test GSSAPI Connection" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + RTEXT "Hostname:",IDC_STATIC_HOST,5,12,60,10,NOT WS_GROUP + COMBOBOX GSS_HOST_NAME,70,9,245,60,CBS_DROPDOWN | CBS_AUTOHSCROLL | + WS_VSCROLL | WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "Test",GSS_OK,80,290,51,14,WS_GROUP + PUSHBUTTON "Exit",GSS_CANCEL,185,290,51,14 + RTEXT "Port:",IDC_STATIC_PORT,16,27,50,8 + EDITTEXT GSS_PORT,70,25,40,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + COMBOBOX GSS_SERVICE_NAME,70,41,245,60,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + RTEXT "GSS Service Name:",IDC_STATIC_SERVICE,1,44,64,8 + COMBOBOX GSS_CCACHE_NAME,70,69,245,60,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + RTEXT "CCache Name:",IDC_STATIC_CCACHE,16,71,49,8 + COMBOBOX GSS_MECHANISM,70,110,245,60,CBS_DROPDOWN | + CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + RTEXT "Mechanism (OID):",IDC_STATIC_MECH,0,115,65,8 + RTEXT "Test Message:",IDC_STATIC_MSG,0,55,65,8 + COMBOBOX GSS_MESSAGE,70,55,245,60,CBS_DROPDOWN | CBS_AUTOHSCROLL | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "The following items are optional and should only be altered by those who understand their implications.", + IDC_STATIC_OPTIONS,10,85,305,20 + CONTROL "Verbose Output",GSS_VERBOSE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,72,138,65,10 + CONTROL "Delegation",GSS_DELEGATION,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,72,150,50,10 + CONTROL "Version 1",GSS_VERSION_ONE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,150,138,45,10 + CONTROL "No Auth",GSS_NO_AUTH,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,72,162,42,10 + CONTROL "No Wrap",GSS_NO_WRAP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,162,45,10 + CONTROL "No Encrypt",GSS_NO_ENCRYPT,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,198,162,51,10 + CONTROL "No Mic",GSS_NO_MIC,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,270,162,39,10 + CONTROL "Slider1",GSS_CALL_COUNT,"msctls_trackbar32",TBS_BOTH | + WS_TABSTOP,66,174,100,15 + CONTROL "Slider2",GSS_MESSAGE_COUNT,"msctls_trackbar32",TBS_BOTH | + WS_TABSTOP,204,174,100,15 + CTEXT "Call Count",IDC_STATIC_CCOUNT,72,192,90,8 + CTEXT "Message Count",IDC_STATIC_MSG_COUNT,210,192,90,8 + GROUPBOX "Output",IDC_GROUP_OUTPUT,0,210,325,75 + GROUPBOX "Configuration Options",IDC_GROUP_OPTIONS,0,0,325,205 + EDITTEXT GSS_OUTPUT,0,220,320,60,ES_MULTILINE | ES_AUTOVSCROLL | + ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL + CONTROL "Mutual",GSS_MUTUAL,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,150,37,10 + CONTROL "Replay",GSS_REPLAY,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,198,150,38,10 + CONTROL "Sequence",GSS_SEQUENCE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,270,150,49,10 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resrc1.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + + +#include +#include "..\version.rc" + +TestTrackerMOTD TEXT ver_serv.txt diff --git a/krb5-1-6/src/windows/gss/resource.h b/krb5-1-6/src/windows/gss/resource.h new file mode 100644 index 000000000..de7b2c127 --- /dev/null +++ b/krb5-1-6/src/windows/gss/resource.h @@ -0,0 +1,50 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by gss.rc +// +#define GSS_HOST_NAME 1000 +#define GSS_PORT 1001 +#define GSS_SERVICE_NAME 1003 +#define IDC_STATIC_SERVICE 1004 +#define GSS_MECHANISM 1005 +#define IDC_STATIC_MECH 1006 +#define IDC_STATIC_MSG 1007 +#define GSS_MESSAGE 1008 +#define IDC_STATIC_OPTIONS 1009 +#define GSS_VERBOSE 1010 +#define GSS_DELEGATION 1011 +#define GSS_VERSION_ONE 1012 +#define GSS_NO_AUTH 1013 +#define GSS_NO_WRAP 1014 +#define GSS_NO_ENCRYPT 1015 +#define GSS_NO_MIC 1016 +#define GSS_CALL_COUNT 1017 +#define GSS_MESSAGE_COUNT 1018 +#define IDC_STATIC_CCOUNT 1019 +#define IDC_STATIC_MSG_COUNT 1020 +#define IDC_GROUP_OUTPUT 1021 +#define IDC_GROUP_OPTIONS 1022 +#define GSS_OUTPUT 1023 +#define GSS_OK 1024 +#define GSS_CANCEL 1025 +#define IDC_STATIC_PORT 1026 +#define IDC_STATIC_HOST 1027 +#define GSS_CCACHE_NAME 1028 +#define IDC_STATIC_CCACHE 1029 +#define GSS_MUTUAL 1030 +#define GSS_REPLAY 1031 +#define GSS_SEQUENCE 1032 + +#define IDD_GSSAPIDLG 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1033 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/gss/ver_serv.txt b/krb5-1-6/src/windows/gss/ver_serv.txt new file mode 100644 index 000000000..c7dcf80d7 --- /dev/null +++ b/krb5-1-6/src/windows/gss/ver_serv.txt @@ -0,0 +1,11 @@ + +The user provided information, along with version information about this application and the machine configuration, will be logged each time the application is launched. Recording this information will provide usage information to IS staff. This information will help us to focus our resources and serve you better in the future. This information will be treated as confidential and will only be accessible by IS staff members. + +If you would rather remain anonymous during this testing phase then use the "Register Anonymously" check box. + +To see more information about configuring the version checking part of this application please consult the local help file. + +We welcome comments on suggestions about this test-tracking system; please send them to testtrack@mit.edu. + + Paul B. Hill + MIT Information Systems diff --git a/krb5-1-6/src/windows/identity/Makefile b/krb5-1-6/src/windows/identity/Makefile new file mode 100644 index 000000000..a2fdcf449 --- /dev/null +++ b/krb5-1-6/src/windows/identity/Makefile @@ -0,0 +1,214 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2006 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +!ifdef ETAGRUN +all: finale doc +!else +all: finale +!endif + +MODULE=all +!include + +!ifndef CLEANRUN +!ifndef TESTRUN +!ifndef ETAGRUN + +# Define KH_NO_WX if the build should not fail on warnings. The +# default is to treat warnings as errors. + +#RMAKE=$(MAKECMD) /nologo all KH_NO_WX=1 +RMAKE=$(MAKECMD) /nologo all +RMAKE_W2K=$(MAKECMD) /nologo all KHBUILD_W2K=1 + +!else +RMAKE=$(MAKECMD) /nologo etag +RMAKE_W2K=echo Skipping W2K target for ETAGS run. +!endif +!else +RMAKE=$(MAKECMD) /nologo test +RMAKE_W2K=$(MAKECMD) /nologo test KHBUILD_W2K=1 +!endif +!else +RMAKE=$(MAKECMD) /nologo clean +RMAKE_W2K=$(MAKECMD) /nologo clean KHBUILD_W2K=1 +!endif + +!if "$(CPU)" != "i386" +NO_KRB4=1 +!endif + +start: + +config: start + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +include: config + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +util: include + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +kherr: util + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +kconfig: kherr + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +kmq: kconfig + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +kcreddb: kmq + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +kmm: kcreddb + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +help: kmm + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +uilib: help + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(RMAKE_W2K) + $(CD) .. + $(ECHO) -- Done with $@ + +nidmgrdll: uilib + $(ECHO) -- Entering $@ + $(CD) $@ + $(RMAKE) + $(RMAKE_W2K) + $(CD) .. + $(ECHO) -- Done with $@ + +ui: nidmgrdll + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(RMAKE_W2K) + $(CD) .. + $(ECHO) -- Done with $@ + +# Now build the plugins +plugincommon: ui + $(ECHO) -- Entering $@ + $(CD) plugins\common + $(RMAKE) + $(CD) ..\.. + $(ECHO) -- Done with $@ + +krb5plugin: plugincommon + $(ECHO) -- Entering $@ + $(CD) plugins\krb5 + $(RMAKE) + $(CD) ..\.. + $(ECHO) -- Done with $@ + +!ifndef NO_KRB4 +finale: krb4plugin + +krb4plugin: plugincommon + $(ECHO) -- Entering $@ + $(CD) plugins\krb4 + $(RMAKE) + $(CD) ..\.. + $(ECHO) -- Done with $@ +!endif + +!ifdef BUILD_AFS +finale: afsplugin + +afsplugin: plugincommon + $(ECHO) -- Entering $@ + $(CD) plugins\afs + $(RMAKE) + $(CD) ..\.. + $(ECHO) -- Done with $@ +!endif + +!ifdef NODOCBUILD +doctarget= +!else +doctarget=doc +!endif + +finale: krb5plugin $(doctarget) + $(ECHO) -- Done. + +pdoc: + +doc: pdoc + $(ECHO) -- Entering $@: + $(CD) $@ + $(RMAKE) + $(CD) .. + $(ECHO) -- Done with $@ + +clean:: + $(MAKECMD) /nologo CLEANRUN=1 + +test:: + $(MAKECMD) /nologo TESTRUN=1 + +etags:: + $(RM) $(TAGFILE) + $(MAKECMD) /nologo ETAGRUN=1 diff --git a/krb5-1-6/src/windows/identity/apiversion.txt b/krb5-1-6/src/windows/identity/apiversion.txt new file mode 100644 index 000000000..5f07d46f2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/apiversion.txt @@ -0,0 +1,367 @@ +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +# This file documents the versions of the API for NetIDMgr. The +# syntax of the file is: +# +# Version= +# AppVersion= +# Date= | NOTRELEASED +# # +# +# # comment +# Schema: +# # comment + + +#---------------------------------------------------------------- +Version=1 +AppVersion=0.1.0.0 +Date=NOTRELEASED +# Original Khimaira API. + +#---------------------------------------------------------------- +Version=2 +AppVersion=0.1.1.0 +Date=Nov 01, 2005 +# Alpha 1 release of NetIDMgr, along with KFW 3.0.0 beta + +#---------------------------------------------------------------- +Version=3 +AppVersion=0.1.2.0 +Date=Nov 30, 2005 +# Alpha 2 release of NetIDMgr, along with KFW 3.0.0 beta 2 + +#---------------------------------------------------------------- +Version=4 +AppVersion=1.0.0.0 +Date=Dec 05, 2005 +# Released with KfW 3.0.0 + +#---------------------------------------------------------------- +Version=5 +AppVersion=1.1.0.0 +Date=(TBD) +# Released with KFW 3.1.0 + ++khui_alert_show_modal(),KMSG_ALERT_SHOW_MODAL, KHUI_ALERT_FLAG_MODAL +# Support for modal alert boxes + ++KHUI_PACTION_YES, KHUI_PACTION_NO, KHUI_PACTION_YESALL, KHUI_PACTION_NOALL, KHUI_PACTION_KEEP, KHUI_PACTION_REMOVE, KHUI_PACTION_DISCARD +# Additional pseudo actions + +!tag_khui_action, khui_action +# Membership extension for supporting custom actions. Type changes +# from 'int' to khm_int32. + ++khui_action_create(), khui_action_get_data(), khui_action_delete() +# Support for creating custom actions + +!kmq_msg_subscription, tag_kmq_msg_subscription +# Add 'magic' field. + ++KHUI_MENU_NONE +# New identifier for unspecified menu commands. + ++khui_menu_insert_action(), khui_menu_get_action(), khui_menu_get_size(), khui_menu_remove_action() +# Functions for manipulating custom menus + ++khui_menu_insert_paction() +# Exported, but not exposed as an API. For inserting actions by +# reference in to menus. + +-khui_menu_add_action(), khui_menu_add_paction() +# Removed deprecated functions. Temporarily provided as macros. The +# replacements are khui_menu_insert_action() and +# khui_menu_insert_paction() respectively. + ++kmq_create_hwnd_subscription() +# Ad-hoc subscriptions can now be obtained for Win32 windows. + +-khui_create_gloabl_accel_table() +# Exported but no longer exposed. + +-khui_action_list_length() +# Exported but no longer exposed. + ++kmm_enable_plugin() +# New API for enabling or disabling plugins + +!kmm_plugin_info +# Added 'flags' field. + ++KCDB_ATTR_FLAG_TRANSIENT +# New flag for transient attributes. + ++kherr_get_prev_event(), kherr_get_last_event() +# For more efficient traversal of the event lists for use by error context handlers. + ++KHERR_RF_COMMIT +# Flag for error events to signal that the error event has been committed. + ++khui_action_trigger() +# Function for triggerring an action. + ++khui_action_set_hwnd() +# internal API. Should not be used by anyone. Basically sets the HWND that should receive event notifications from the UI library. + ++KEPT_PTR +# error library data type for pointers + ++_cptr +# type cast macro for pointer types + +!khc_open_space +# name parameter is now a const string + +!KCDB_ATTRNAME_ISSUE +# Fixed typo + +!kherr_val +# is now an inline function instead of a macro + +!kherr_param +# is now a structure instead of an integer type + ++KEPT_NONE +# new constant signifying a NULL parameter + +!_int32, _uint32, _int64, _uint64, _cstr, _tstr, _cptr +# appropriate typecasts added + ++vnull +# macro to insert a NULL parameter + +!_report_cs0, _report_cs1, _report_cs2, _report_cs3 +!_report_sr0, _report_sr1, _report_sr2, _report_sr3 +!_report_mr0, _report_mr1, _report_mr2, _report_mr3 +!_report_ts0, _report_ts1, _report_ts2, _report_ts3 +# modified to use _vnull() instead of 0 for NULL parameters + ++KCONF_FLAG_WRITEIFMOD +# new flag for khc_open_space() indicating that the specified handle should only write to a configuration space if the value read from the handle is different from the value being written + ++KCONF_FLAG_IFMODCI +# indicates that the string comparison function used for KCONF_FLAG_WRITEIFMOD should be case insensitive. + +!khc_write_int32(), khc_write_int64(), khc_write_string(), khc_write_multi_string() +# Change of behavior. If the configuration handle has KCONF_FLAG_WRITEIFMOD flag set, only writes if the value being written to is different from the value being read. + +!khc_read_string(), khc_read_multi_string(), khc_read_int32(), khc_read_int64(), khc_read_binary(), khc_write_string(), khc_write_int32(), khc_write_int64(), khc_write_binary(), khc_get_type(), khc_value_exists(), khc_remove_value() +# The value name parameter is now a constant pointer + +!khc_load_schema(), khc_unload_schema() +# The schema pointer is now a constant pointer + +-Schema:NetIDMgr\PluginManager\Modules\\Flags +-Schema:NetIDMgr\PluginManager\Plugins\\Flags +# Deprecated. Replaced by separate values for each of the bits in Flags. This allows each setting to be deployed independently via GPO. + ++Schema:NetIDMgr\PluginManager\Modules\\Disabled ++Schema:NetIDMgr\PluginManager\Plugins\\Disabled +# If non-zero, the corresponding module or plug-in is disabled. + +!kcdb_identity_set_attrib(), kcdb_identity_get_attrib(), kcdb_identity_get_attrib_string() +# Attribute name parameter is now a const pointer to a wchar_t string + +!kcdb_cred_create() +# Name parameter is now a const pointer to a wchar_t string + +!kcdb_cred_set_attrib(), kcdb_cred_get_attrib() +!kcdb_cred_get_attrib_string(), kcdb_creds_comp_attrib() +# Attribute name parameter is now a const pointer to a wchar_t string + +!kcdb_type_get_id() +# Name parameter is now a const pointer to a wchar_t string + +!kcdb_type_register() +# type parameter is now a const pointer + +!kcdb_attrib_get_id() +# Name parameter is now a const pointer + +!kcdb_attrib_register() +# attrib parameter is now a const pointer + +!kcdb_credtype_register() +# type parameter is now a const pointer + +!kcdb_credtype_get_id() +# name parameter is now a const pointer + +!kcdb_buf_get_attrib(), kcdb_buf_get_attrib_string(), kcbd_buf_set_attrib() +# attr_name is now a const pointer + ++KCDB_OP_DELCONFIG +# notification that the configuration information for an identity is to be removed. + + +#---------------------------------------------------------------- +Version=7 +AppVersion=1.1.9.0 +Date=Feb 16, 2007 +# Released with KFW 3.2 Alpha 1 + ++KHUI_ACTION_UICB +# Internal action to dispatch a UI callback + ++WMNC_UPDATE_LAYOUT +# Used to update the layout and size of the dialogs during a new +# credentials operation. + +- NCDLG_TAB_HEIGHT, NCDLG_TAB_WIDTH +# No longer used + +- NCDLG_BBAR_WIDTH +# Moved to internal header file + ++ KCDB_IDENT_FLAG_UNKNOWN +# Used to indicate that an authority could not be contacted to +# determine the validity of an identity. + ++ khui_refresh_actions() +# Force a refresh of the application menus and toolbars. + ++ khui_action_lock() ++ khui_action_unlock() +# Synchronization of action and menu operations. + +! khui_alert +# Structure definition is now internal + +! khui_action +# Structure definition is now internal + ++ khui_alert_set_type() ++ khui_alert_set_ctx() ++ khui_alert_get_response() +# Additional functions to setup an alert. + +! kmq_message +# Added field "aborted" + ++ kmq_abort_call() ++ kmq_is_call_aborted() +# Added placeholders + +! kmq_message_ref +! kmq_queue +! kmq_msg_subscription +! kmq_msg_type +# Structure definition now internal + +! KMQ_MSG_TYPE_MAX +! KMQ_MAXCCH_TYPE_NAME +! KMQ_MAXCB_TYPE_NAME +! KMQ_MSG_SUB_MAGIC +! KMQ_RCPTTYPE_CB +! KMQ_RCPTTYPE_HWND +! KMQ_QUEUE_FLAG_DELETED +# Macros not internal + +#---------------------------------------------------------------- +Version=8 +AppVersion=1.1.10.0 +Date=(TBD) +# Released with (TBD) + +! hash_add(), hash_del(), hash_lookup(), hash_exist() +# 'key' parameter is now (const void *) + +! struct tag_has_bin, hash_bin +# 'key' member is now (const void *) + + ++WMNC_UPDATE_LAYOUT +# Used to update the layout and size of the dialogs during a new +# credentials operation. + +- NCDLG_TAB_HEIGHT, NCDLG_TAB_WIDTH +# No longer used + +- NCDLG_BBAR_WIDTH +# Moved to internal header file + ++ KCDB_IDENT_FLAG_UNKNOWN +# Used to indicate that an authority could not be contacted to +# determine the validity of an identity. + ++ khui_refresh_actions() +# Force a refresh of the application menus and toolbars. + ++ khui_action_lock() ++ khui_action_unlock() +# Synchronization of action and menu operations. + +! khui_alert +# Structure definition is now internal + +! khui_action +# Structure definition is now internal + ++ khui_alert_set_type() ++ khui_alert_set_ctx() ++ khui_alert_get_response() +# Additional functions to setup an alert. + +! kmq_message +# Added field "aborted" + ++ kmq_abort_call() ++ kmq_is_call_aborted() +# Added placeholders + +! kmq_message_ref +! kmq_queue +! kmq_msg_subscription +! kmq_msg_type +# Structure definition now internal + +! KMQ_MSG_TYPE_MAX +! KMQ_MAXCCH_TYPE_NAME +! KMQ_MAXCB_TYPE_NAME +! KMQ_MSG_SUB_MAGIC +! KMQ_RCPTTYPE_CB +! KMQ_RCPTTYPE_HWND +! KMQ_QUEUE_FLAG_DELETED +# Macros not internal + +! khc_value_exists() +# Behavior change with respect to shadowed handles. If a value +# doesn't exist in the top level handle, then each shadowed handle +# will be tried in turn until the value is found. + +#---------------------------------------------------------------- +Version=9 +AppVersion=1.3.0.0 +Date=(TBD) +# Released with (TBD) + ++ KHERR_CTX_NEWCHILD ++ KHERR_CTX_FOLDCHILD +# Added to kherr.h to support additional notifications + ++ WMNC_IDENT_PREPROCESS +# Preprocess the identity selector controls before fetching the +# selected identity diff --git a/krb5-1-6/src/windows/identity/config/Makefile b/krb5-1-6/src/windows/identity/config/Makefile new file mode 100644 index 000000000..e5bc7eea8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/config/Makefile @@ -0,0 +1,147 @@ +# +# Copyright (c) 2004,2005,2006 Massachusetts Institute of Technology +# Copyright (c) 2006 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=config +!include + +all: showvars showvers mkalldirs mkversion + +showvars: + $(ECHO) SRC= $(SRC) + $(ECHO) DESTDIR = $(DESTDIR) + $(ECHO) OBJDIR = $(OBJDIR) + $(ECHO). + $(ECHO) CC = $(CC) + $(ECHO) DOXYGEN = $(DOXYGEN) + $(ECHO) HHC = $(HHC) + +showvers: + $(ECHO) ---- Version Information ---- + $(ECHO) NETIDMGR_VERSION= $(NETIDMGR_VERSION) + $(ECHO) NETIDMGR_VERSION_API=$(NETIDMGR_VERSION_API) + $(ECHO) NETIDMGR_RELEASEDESC=$(NETIDMGR_RELEASEDESC) + $(ECHO) Build Type :$(KH_BUILD), $(KH_RELEASE) + $(ECHO) Strings: + $(ECHO) Company = $(NETIDMGR_SRC_COMPANY_1033) + $(ECHO) Copyright = $(NETIDMGR_SRC_COPYRIGHT_1033) + $(ECHO) ---- End Version Information --- + $(ECHO). + +mkalldirs: +! if !exist($(DESTROOT)) + -$(MKDIR) $(DESTROOT) +! endif +! if !exist($(OBJROOT)) + -$(MKDIR) $(OBJROOT) +! endif +! if !exist($(DESTDIR)) + -$(MKDIR) $(DESTDIR) +! endif +! if !exist($(OBJDIR)) + -$(MKDIR) $(OBJDIR) +! endif +! if !exist($(INCDIR)) + -$(MKDIR) $(INCDIR) +! endif +! if !exist($(BINDIR)) + -$(MKDIR) $(BINDIR) +! endif +! if !exist($(LIBDIR)) + -$(MKDIR) $(LIBDIR) +! endif +! if !exist($(DOCDIR)) + -$(MKDIR) $(DOCDIR) +! endif +! if !exist($(OBJDIR)\W2K) + -$(MKDIR) $(OBJDIR)\W2K +! endif +! if !exist($(BINDIR)\W2K) + -$(MKDIR) $(BINDIR)\W2K +! endif +! if !exist($(LIBDIR)\W2K) + -$(MKDIR) $(LIBDIR)\W2K +! endif + $(ECHO) Done creating directories. + +VERSIONINT=$(INCDIR)\netidmgr_intver.h + +VERSIONEXT=$(INCDIR)\netidmgr_version.h + +# Version related defines + +! if "$(KH_BUILD)"=="RETAIL" +kh_fileflags=0 +! else +kh_fileflags=VS_FF_DEBUG +! endif +! if "$(KH_RELEASE)"=="PRERELEASE" +kh_fileflags=$(kh_fileflags) | VS_FF_PRERELEASE +! elseif "$(KH_RELEASE)"=="PRIVATE" +kh_fileflags=$(kh_fileflags) | VS_FF_PRIVATEBUILD +! elseif "$(KH_RELEASE)"=="SPECIAL" +kh_fileflags=$(kh_fileflags) | VS_FF_SPECIALBUILD +! endif + +kh_fileos=VOS_NT_WINDOWS32 +kh_filetype_app=VFT_APP +kh_filetype_dll=VFT_DLL + +mkversion: $(VERSIONINT) $(VERSIONEXT) + +# Version and build strings + +!if "$(KH_RELEASE)" == "OFFICIAL" +NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION) +NETIDMGR_COMMENT_STR_1033=Official build. Please send bug reports to kfw-bugs@MIT.EDU +!elseif "$(KH_RELEASE)" == "PRERELEASE" +NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION) Prelease $(NETIDMGR_RELEASEDESC) +NETIDMGR_COMMENT_STR_1033=Prerelease build. Please send bug reports to kfw-bugs@MIT.EDU +!elseif "$(KH_RELEASE)" == "PRIVATE" +NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION).PRIVATE +NETIDMGR_PRIVATE_STR_1033=Private build. Please send bug reports to kfw-bugs@MIT.EDU +!elseif "$(KH_RELEASE)" == "SPECIAL" +NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION).SPECIAL +NETIDMGR_SPECIAL_STR_1033=Special build. Please send bug reports to kfw-bugs@MIT.EDU +!endif + +!if "$(KH_BUILD)" == "DEBUG" +NETIDMGR_VERSION_STR_1033=$(NETIDMGR_VERSION_STR_1033).DEBUG +!else +!endif + +NETIDMGR_PRODUCT_1033=NetIDMgr $(NETIDMGR_VERSION_STR_1033) + +!include netidmgr_version.h.in + +!include netidmgr_intver.h.in + +clean:: +! if exist($(VERSIONINT)) + $(RM) $(VERSIONINT) +! endif +! if exist($(VERSIONEXT)) + $(RM) $(VERSIONEXT) +! endif + diff --git a/krb5-1-6/src/windows/identity/config/Makefile.w2k b/krb5-1-6/src/windows/identity/config/Makefile.w2k new file mode 100644 index 000000000..14c707d7e --- /dev/null +++ b/krb5-1-6/src/windows/identity/config/Makefile.w2k @@ -0,0 +1,306 @@ +# +# Khimaira : Win32 configuration makefile +# This file will be included by all the makefiles +# in the build tree. +# +# Copyright (c) 2004,2005,2006 Massachusetts Institute of Technology +# Copyright (c) 2006,2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +!ifndef KHIMAIRA_WIN32_CONFIG +KHIMAIRA_WIN32_CONFIG=1 + +# Environment Variables +# The following environment variables MUST be set: +# KH_ROOT : Root of the source tree. +# KH_BUILD: One of DEBUG or RETAIL +# +# The following environment variables are optional: +# KH_RUNTIME: One of STATIC or DLL, specifies whether the CRT libs +# are linked statically or through MSVCRT.DLL. +# KH_AUXCFLAGS: Optional flags for CL +# KH_RELEASE: Release type. One of OFFICIAL, PRERELEASE, PRIVATE or SPECIAL. +# OFFICIAL : An official release of Khimaira +# PREPRELEASE: A beta/release candidate release +# PRIVATE : Private build +# SPECIAL : Special build. Typically one with non-mainline patches. + +# Version info +NETIDMGR_VERSION_MAJOR=1 +NETIDMGR_VERSION_MINOR=3 +NETIDMGR_VERSION_PATCH=1 +NETIDMGR_VERSION_AUX=0 +NETIDMGR_RELEASEDESC= + +# The API version. This number must be incremented each time the API +# changes. Plugins specify the version of the API that they were +# compiled against and the Module Manager uses the API numbers to +# decide whether the plugin is safe to load or not. +# +# Changes to the API version numbers should be documented in +# apiversion.txt at the root of the source tree. +NETIDMGR_VERSION_API=10 + +# Minimum backwards compatible version. API versions from +# NETIDMGR_VERSION_API_MINCOMPAT through NETIDMGR_VERSION_API +# inclusive, are compatible with this version. +NETIDMGR_VERSION_API_MINCOMPAT=5 + +NETIDMGR_VERSION=$(NETIDMGR_VERSION_MAJOR).$(NETIDMGR_VERSION_MINOR).$(NETIDMGR_VERSION_PATCH).$(NETIDMGR_VERSION_AUX) +NETIDMGR_VERSIONC=$(NETIDMGR_VERSION_MAJOR),$(NETIDMGR_VERSION_MINOR),$(NETIDMGR_VERSION_PATCH),$(NETIDMGR_VERSION_AUX) + +# Source information +NETIDMGR_SRC_COMPANY_1033=Massachusetts Institute of Technology +NETIDMGR_SRC_COPYRIGHT_1033=(C) 2005-2007 Massachusetts Institute of Technology + +# Choose the default build type if one is not set +!if ("$(KH_BUILD)" != "DEBUG") && ("$(KH_BUILD)" != "RETAIL") +! if defined(NODEBUG) && "$(NODEBUG)"=="1" +KH_BUILD=RETAIL +! else +KH_BUILD=DEBUG +! endif +!endif + +!if "$(KH_BUILD)"=="DEBUG" && defined(NODEBUG) && "$(NODEBUG)"=="1" +! error The Khimaira build configuration is set for DEBUG while the Platform SDK build environment is set to RETAIL. +!endif + +# The default release type is PRIVATE is no other type is specified +!if ("$(KH_RELEASE)" != "OFFICIAL") && ("$(KH_RELEASE)" != "PRERELEASE") && ("$(KH_RELEASE)" != "PRIVATE") && ("$(KH_RELEASE)" != "SPECIAL") +KH_RELEASE=PRIVATE +!endif + +# Actual build environment settings + +# See what compiler we are using +# TODO: Update this to support other compilers +!if defined(MSVCVer) && "$(MSVCVer)"=="8.0" +KH_CLVER=vc8 +!else +KH_CLVER=vc7 +!endif + +# Check for required env vars +!ifndef MODULE +! error MODULE must be specified +!endif +!ifndef KH_ROOT +! ifndef PISMERE +! error Either KH_ROOT or PISMERE must be defined +! else +KH_ROOT=$(PISMERE)\athena\auth\krb5\src\windows\identity +! endif +!endif + +!ifdef NODEBUG +OUTPRE_DBG=rel +!else +OUTPRE_DBG=dbg +!endif +OUTPRE1=obj +OUTPRE2=$(OUTPRE1)\$(CPU) +OUTPRE3=$(OUTPRE2)\$(OUTPRE_DBG) +OUTPRE=$(OUTPRE3)^\ + + + +# Output directory structure +DESTROOT=$(KH_ROOT)\obj +OBJROOT=$(KH_ROOT)\obj +SRC=$(KH_ROOT) + +DESTDIR=$(DESTROOT)\$(CPU)\$(OUTPRE_DBG) +OBJDIR=$(OBJROOT)\$(CPU)\$(OUTPRE_DBG) + +OBJ=$(OBJDIR)\$(MODULE) +INCDIR=$(DESTDIR)\inc +#BINDIR=$(DESTDIR)\bin +BINDIR=$(KH_ROOT)\$(OUTPRE)\W2K +#LIBDIR=$(DESTDIR)\lib +LIBDIR=$(KH_ROOT)\$(OUTPRE)\W2K +DOCDIR=$(DESTDIR)\doc + +# Source directories +CONFDIR=$(SRC)\config + +# Setup environment for win32.mak + +!if "$(KH_BUILD)" == "RETAIL" +NODEBUG=1 +!endif + +# Win32.mak +APPVER=5.0 +TARGETOS=WINNT +_WIN32_IE=0x0500 +_WIN32_WINNT=0x0500 +!include + +# Program macros + +CD=cd +RM=del /q +MKDIR=mkdir +RMDIR=rmdir +ECHO=echo +MAKECMD=nmake /nologo +CP=copy /y +LINK=link +CCSV=perl $(SRC)\config\ccsv.pl +MC=mc + +!ifdef KH_DOXYFULLPATH +DOXYGEN=$(KH_DOXYFULLPATH) +!else +DOXYGEN=doxygen +!endif + +!ifdef KH_HHCFULLPATH +HHC=$(KH_HHCFULLPATH) +!else +HHC=hhc +!endif + +!ifdef KH_KFWPATH +KFWINCDIR=$(KH_KFWPATH)\inc +kfwincflags = -I$(KFWINCDIR)\krb5 -I$(KFWINCDIR)\krb5\KerberosIV -I$(KFWINCDIR)\krb4 -I$(KFWINCDIR)\loadfuncs -I$(KFWINCDIR) +KFWLIBDIR=$(KH_KFWPATH)\lib\$(CPU) +!else if defined(PISMERE) +KFWINCDIR=$(PISMERE)\athena\auth\krb5\src\include +kfwincflags = -I$(KFWINCDIR) -I$(PISMERE)\athena\util\loadfuncs -I$(PISMERE)\athena\auth\krb5\src\include\kerberosIV -I$(PISMERE)\athena\auth\krb4\include +KFWLIBDIR=$(PISMERE)\target\lib\$(CPU)\$(OUTPRE_DBG) +!endif + +!ifdef KH_AFSPATH +AFSINCDIR=$(KH_AFSPATH)\include +AFSLIBDIR=$(KH_AFSPATH)\lib +afsincflags=-I$(AFSINCDIR) +!endif + +#EXTLIBDIR=$(SRC)\ext-lib\$(CPU) +#EXTINCDIR=-I$(SRC)\ext-inc + +incflags= -I$(INCDIR) -I$(SRC)\include -I. -I$(OBJ) $(kfwincflags) $(afsincflags) +rincflags= /i $(INCDIR) /i $(SRC)\include /i . +khdefines=-DUNICODE -D_UNICODE +khcwarn=/Wp64 +!ifndef KH_NO_WX +khcwarn=$(khcwarn) /WX +!endif + +!if "$(CPU)" == "i386" +khdefines=$(khdefines) -D_USE_32BIT_TIME_T +!endif + +#DEBUG_SYMBOLS +ldebug=$(ldebug) /DEBUG +cdebug=$(cdebug) -Os -Zi + +# Additionally, suppress conflicting default library directives that we +# might pull in from external libraries. + +!ifndef NODEBUG +lndeflibflag=/NODEFAULTLIB:MSVCRT +!else +lndeflibflag=/NODEFAULTLIB:MSVCRTD +!endif + +khcflags=$(cdebug) $(cflags) $(incflags) $(khdefines) $(khcwarn) +khlguiflags=$(ldebug) $(guilflags) $(lndeflibflag) +khlconflags=$(ldebug) $(conlflags) $(lndeflibflag) +khldllguiflags=$(ldebug) $(dlllflags) $(lndeflibflag) +khldllconflags=$(ldebug) $(dlllflags) $(lndeflibflag) + +!if "$(KH_RUNTIME)" == "STATIC" +khcflags=$(khcflags) $(cvarsmt) +khlguiflags=$(khlguiflags) $(guilibsmt) +khlconflags=$(khlconflags) $(conlibsmt) +khldllguiflags=$(khldllguiflags) $(guilibsmt) +khldllconflags=$(khldllconflags) $(conlibsmt) +!else +khcflags=$(khcflags) $(cvarsdll) +khlguiflags=$(khlguiflags) $(guilibsdll) +khlconflags=$(khlconflags) $(conlibsdll) +khldllguiflags=$(khldllguiflags) $(guilibsdll) +khldllconflags=$(khldllconflags) $(conlibsdll) +!endif + +C2OBJ=$(CC) $(khcflags) $(KH_AUXCFLAGS) /Fo"$@" /c $** + +EXECONLINK=$(LINK) /NOLOGO $(khlconflags) /OUT:$@ $** + +EXEGUILINK=$(LINK) /NOLOGO $(khlguiflags) /OUT:$@ $** + +DLLCONLINK=$(LINK) /NOLOGO $(khldllconflags) /OUT:$@ /IMPLIB:$(LIBDIR)\$(@B).lib $** + +DLLGUILINK=$(LINK) /NOLOGO $(khldllguiflags) /OUT:$@ /IMPLIB:$(LIBDIR)\$(@B).lib $** + +DLLRESLINK=$(LINK) /NOLOGO /DLL /NOENTRY /MACHINE:$(PROCESSOR_ARCHITECTURE) /OUT:$@ $** + +RC2RES=$(RC) $(RFLAGS) $(rincflags) /fo $@ $** + +MC2RC=$(MC) $(MCFLAGS) -h $(OBJ)\ -m 1024 -r $(OBJ)\ -x $(OBJ)\ $** + +{}.c{$(OBJ)}.obj: + $(C2OBJ) + +{$(OBJ)}.c{$(OBJ)}.obj: + $(C2OBJ) + +{}.h{$(INCDIR)}.h: + $(CP) $** $@ + +{}.rc{$(OBJ)}.res: + $(RC2RES) + +{$(OBJ)}.rc{$(OBJ)}.res: + $(RC2RES) + +clean:: +!if exist($(OBJ)) + $(RM) $(OBJ)\ +!endif + if exist vc70.pdb $(RM) vc70.pdb + if exist vc80.pdb $(RM) vc80.pdb + +test:: + +mkdirs:: +!if !exist($(LIBDIR)) + $(MKDIR) $(LIBDIR) +!endif +!if !exist($(BINDIR)) + $(MKDIR) $(BINDIR) +!endif +!if !exist($(OBJ)) + $(MKDIR) $(OBJ) +!endif + +TAGFILE = $(SRC)\TAGS + +etag:: + etags -o $(TAGFILE) -a *.c *.h + +.SUFFIXES: .h + +!endif diff --git a/krb5-1-6/src/windows/identity/config/Makefile.w32 b/krb5-1-6/src/windows/identity/config/Makefile.w32 new file mode 100644 index 000000000..3b61c6638 --- /dev/null +++ b/krb5-1-6/src/windows/identity/config/Makefile.w32 @@ -0,0 +1,344 @@ +# +# Khimaira : Win32 configuration makefile +# This file will be included by all the makefiles +# in the build tree. +# +# Copyright (c) 2004,2005,2006 Massachusetts Institute of Technology +# Copyright (c) 2006,2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +!ifndef KHIMAIRA_WIN32_CONFIG +KHIMAIRA_WIN32_CONFIG=1 + +# Environment Variables +# The following environment variables MUST be set: +# KH_ROOT : Root of the source tree. +# KH_BUILD: One of DEBUG or RETAIL +# +# The following environment variables are optional: +# KH_RUNTIME: One of STATIC or DLL, specifies whether the CRT libs +# are linked statically or through MSVCRT.DLL. +# KH_AUXCFLAGS: Optional flags for CL +# KH_RELEASE: Release type. One of OFFICIAL, PRERELEASE, PRIVATE or SPECIAL. +# OFFICIAL : An official release of Khimaira +# PREPRELEASE: A beta/release candidate release +# PRIVATE : Private build +# SPECIAL : Special build. Typically one with non-mainline patches. + +# Version info +NETIDMGR_VERSION_MAJOR=1 +NETIDMGR_VERSION_MINOR=3 +NETIDMGR_VERSION_PATCH=1 +NETIDMGR_VERSION_AUX=0 +NETIDMGR_RELEASEDESC= + +# The API version. This number must be incremented each time the API +# changes. Plugins specify the version of the API that they were +# compiled against and the Module Manager uses the API numbers to +# decide whether the plugin is safe to load or not. +# +# Changes to the API version numbers should be documented in +# apiversion.txt at the root of the source tree. +NETIDMGR_VERSION_API=10 + +# Minimum backwards compatible version. API versions from +# NETIDMGR_VERSION_API_MINCOMPAT through NETIDMGR_VERSION_API +# inclusive, are compatible with this version. +NETIDMGR_VERSION_API_MINCOMPAT=5 + +NETIDMGR_VERSION=$(NETIDMGR_VERSION_MAJOR).$(NETIDMGR_VERSION_MINOR).$(NETIDMGR_VERSION_PATCH).$(NETIDMGR_VERSION_AUX) +NETIDMGR_VERSIONC=$(NETIDMGR_VERSION_MAJOR),$(NETIDMGR_VERSION_MINOR),$(NETIDMGR_VERSION_PATCH),$(NETIDMGR_VERSION_AUX) + +# Source information +NETIDMGR_SRC_COMPANY_1033=Massachusetts Institute of Technology +NETIDMGR_SRC_COPYRIGHT_1033=(C) 2005-2007 Massachusetts Institute of Technology + +# Choose the default build type if one is not set +!if ("$(KH_BUILD)" != "DEBUG") && ("$(KH_BUILD)" != "RETAIL") +! if defined(NODEBUG) && "$(NODEBUG)"=="1" +KH_BUILD=RETAIL +! else +KH_BUILD=DEBUG +! endif +!endif + +!if "$(KH_BUILD)"=="DEBUG" && defined(NODEBUG) && "$(NODEBUG)"=="1" +! error The Khimaira build configuration is set for DEBUG while the Platform SDK build environment is set to RETAIL. +!endif + +# The default release type is PRIVATE is no other type is specified +!if ("$(KH_RELEASE)" != "OFFICIAL") && ("$(KH_RELEASE)" != "PRERELEASE") && ("$(KH_RELEASE)" != "PRIVATE") && ("$(KH_RELEASE)" != "SPECIAL") +KH_RELEASE=PRIVATE +!endif + +# Actual build environment settings + +# See what compiler we are using +# TODO: Update this to support other compilers +!if defined(MSVCVer) && "$(MSVCVer)"=="8.0" +KH_CLVER=vc8 +!else +KH_CLVER=vc7 +!endif + +# Check for required env vars +!ifndef MODULE +! error MODULE must be specified +!endif +!ifndef KH_ROOT +! ifndef PISMERE +! error Either KH_ROOT or PISMERE must be defined +! else +KH_ROOT=$(PISMERE)\athena\auth\krb5\src\windows\identity +! endif +!endif + +!ifdef NODEBUG +OUTPRE_DBG=rel +!else +OUTPRE_DBG=dbg +!endif +OUTPRE1=obj +OUTPRE2=$(OUTPRE1)\$(CPU) +OUTPRE3=$(OUTPRE2)\$(OUTPRE_DBG) +OUTPRE=$(OUTPRE3)^\ + + + +# Output directory structure +DESTROOT=$(KH_ROOT)\obj +OBJROOT=$(KH_ROOT)\obj +SRC=$(KH_ROOT) + +DESTDIR=$(DESTROOT)\$(CPU)\$(OUTPRE_DBG) +OBJDIR=$(OBJROOT)\$(CPU)\$(OUTPRE_DBG) + +OBJ=$(OBJDIR)\$(MODULE) +INCDIR=$(DESTDIR)\inc +#BINDIR=$(DESTDIR)\bin +BINDIR=$(KH_ROOT)\$(OUTPRE) +#LIBDIR=$(DESTDIR)\lib +LIBDIR=$(KH_ROOT)\$(OUTPRE) +DOCDIR=$(DESTDIR)\doc + +# Source directories +CONFDIR=$(SRC)\config + +# If we are forcing a Win2K build, we need to adjust the build +# directories and environment. + +!ifdef KHBUILD_W2K + +OBJ=$(OBJ)\W2K +BINDIR=$(BINDIR)\W2K +LIBDIR=$(LIBDIR)\W2K + +APPVER=5.0 +TARGETOS=WINNT +_WIN32_IE=0x0500 +_WIN32_WINNT=0x0500 + +!endif + +# Setup environment for win32.mak + +!if "$(KH_BUILD)" == "RETAIL" +NODEBUG=1 +!endif + +# Win32.mak + +!include + +# Program macros + +CD=cd +RM=del /q +MKDIR=mkdir +RMDIR=rmdir +ECHO=echo +MAKECMD=nmake /nologo +CP=copy /y +LINK=link +CCSV=perl $(SRC)\config\ccsv.pl +MC=mc + +!ifdef KH_DOXYFULLPATH +DOXYGEN=$(KH_DOXYFULLPATH) +!else +DOXYGEN=doxygen +!endif + +!ifdef KH_HHCFULLPATH +HHC=$(KH_HHCFULLPATH) +!else +HHC=hhc +!endif + +!ifdef KH_KFWPATH +KFWINCDIR=$(KH_KFWPATH)\inc +kfwincflags = -I$(KFWINCDIR)\krb5 -I$(KFWINCDIR)\krb5\KerberosIV -I$(KFWINCDIR)\krb4 -I$(KFWINCDIR)\loadfuncs -I$(KFWINCDIR) +KFWLIBDIR=$(KH_KFWPATH)\lib\$(CPU) +!else if defined(PISMERE) +KFWINCDIR=$(PISMERE)\athena\auth\krb5\src\include +kfwincflags = -I$(KFWINCDIR) -I$(PISMERE)\athena\util\loadfuncs -I$(PISMERE)\athena\auth\krb5\src\include\kerberosIV -I$(PISMERE)\athena\auth\krb4\include +KFWLIBDIR=$(PISMERE)\target\lib\$(CPU)\$(OUTPRE_DBG) +!endif + +!ifdef KH_AFSPATH +AFSINCDIR=$(KH_AFSPATH)\include +AFSLIBDIR=$(KH_AFSPATH)\lib +afsincflags=-I$(AFSINCDIR) +!endif + +#EXTLIBDIR=$(SRC)\ext-lib\$(CPU) +#EXTINCDIR=-I$(SRC)\ext-inc + +incflags= -I$(INCDIR) -I$(SRC)\include -I. -I$(OBJ) $(kfwincflags) $(afsincflags) +rincflags= /i $(INCDIR) /i $(SRC)\include /i . +khdefines=-DUNICODE -D_UNICODE +khcwarn=/Wp64 +!ifndef KH_NO_WX +khcwarn=$(khcwarn) /WX +!endif + +!if "$(CPU)" == "i386" +khdefines=$(khdefines) -D_USE_32BIT_TIME_T +!endif + +#DEBUG_SYMBOLS +ldebug=$(ldebug) /DEBUG +cdebug=$(cdebug) -Os -Zi + +# Additionally, suppress conflicting default library directives that we +# might pull in from external libraries. + +!ifndef NODEBUG +lndeflibflag=/NODEFAULTLIB:MSVCRT +!else +lndeflibflag=/NODEFAULTLIB:MSVCRTD +!endif + +khcflags=$(cdebug) $(cflags) $(incflags) $(khdefines) $(khcwarn) +khlguiflags=$(ldebug) $(guilflags) $(lndeflibflag) +khlconflags=$(ldebug) $(conlflags) $(lndeflibflag) +khldllguiflags=$(ldebug) $(dlllflags) $(lndeflibflag) +khldllconflags=$(ldebug) $(dlllflags) $(lndeflibflag) + +!if "$(KH_RUNTIME)" == "STATIC" +khcflags=$(khcflags) $(cvarsmt) +khlguiflags=$(khlguiflags) $(guilibsmt) +khlconflags=$(khlconflags) $(conlibsmt) +khldllguiflags=$(khldllguiflags) $(guilibsmt) +khldllconflags=$(khldllconflags) $(conlibsmt) +!else +khcflags=$(khcflags) $(cvarsdll) +khlguiflags=$(khlguiflags) $(guilibsdll) +khlconflags=$(khlconflags) $(conlibsdll) +khldllguiflags=$(khldllguiflags) $(guilibsdll) +khldllconflags=$(khldllconflags) $(conlibsdll) +!endif + +C2OBJ=$(CC) $(khcflags) $(KH_AUXCFLAGS) /Fo"$@" /c $** + +EXECONLINK=$(LINK) /NOLOGO $(khlconflags) /OUT:$@ $** + +EXEGUILINK=$(LINK) /NOLOGO $(khlguiflags) /OUT:$@ $** + +DLLCONLINK=$(LINK) /NOLOGO $(khldllconflags) /OUT:$@ /IMPLIB:$(LIBDIR)\$(@B).lib $** + +DLLGUILINK=$(LINK) /NOLOGO $(khldllguiflags) /OUT:$@ /IMPLIB:$(LIBDIR)\$(@B).lib $** + +DLLRESLINK=$(LINK) /NOLOGO /DLL /NOENTRY /MACHINE:$(PROCESSOR_ARCHITECTURE) /OUT:$@ $** + +RC2RES=$(RC) $(RFLAGS) $(rincflags) /fo $@ $** + +MC2RC=$(MC) $(MCFLAGS) -h $(OBJ)\ -m 1024 -r $(OBJ)\ -x $(OBJ)\ $** + +{}.c{$(OBJ)}.obj: + $(C2OBJ) + +{$(OBJ)}.c{$(OBJ)}.obj: + $(C2OBJ) + +{}.h{$(INCDIR)}.h: + $(CP) $** $@ + +{}.rc{$(OBJ)}.res: + $(RC2RES) + +{$(OBJ)}.rc{$(OBJ)}.res: + $(RC2RES) + +clean:: + if exist "$(OBJ)" $(RM) "$(OBJ)" + if exist vc70.pdb $(RM) vc70.pdb + if exist vc80.pdb $(RM) vc80.pdb + +test:: + +mkdirs:: +!if !exist($(OBJ)) + $(MKDIR) $(OBJ) +!endif + +TAGFILE = $(SRC)\TAGS + +etag:: + etags -o $(TAGFILE) -a *.c *.h + +.SUFFIXES: .h + +# +# Manifest handling +# +# Starting with Visual Studio 8, the C compiler and the linker +# generate manifests so that the applications will link with the +# correct side-by-side DLLs at run-time. These are required for +# correct operation under Windows XP. We also have custom manifests +# which need to be merged with the manifests that VS creates. +# +# The syntax for invoking the _VC_MANIFEST_EMBED_foo macro is: +# $(_VC_MANIFEST_EMBED_???) +# + +!ifndef MT +MT=mt.exe -nologo +!endif + +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest $(MT) -outputresource:$@;1 -manifest $@.manifest + +_VC_MANIFEST_EMBED_DLL= \ +if exist $@.manifest $(MT) -outputresource:$@;2 -manifest $@.manifest + +# Note that if you are merging manifests, then the VS generated +# manifest should be cleaned up after calling _VC_MANIFEST_EMBED_???. +# This ensures that even if the DLL or EXE is executed in-place, the +# embedded manifest will be used. Otherwise the $@.manifest file will +# be used. +_VC_MANIFEST_CLEAN= \ +if exist $@.manifest $(RM) $@.manifest + +# End of manifest handling + +!endif diff --git a/krb5-1-6/src/windows/identity/config/ccsv.pl b/krb5-1-6/src/windows/identity/config/ccsv.pl new file mode 100644 index 000000000..f23179363 --- /dev/null +++ b/krb5-1-6/src/windows/identity/config/ccsv.pl @@ -0,0 +1,134 @@ +#!/usr/bin/perl + +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + + +# This is a simple script that is used for generating C code from CSV +#files. We expect three arguments, the which is the .csv file +#to be parsed, a which is a configuration file and the +#. + +# The configuration file is a perl file which defines the following +#variables : + +# $skip_lines : the number of lines to skip in the csv. The default is 0 + +# @pquote : an array of boolean integers that specify whether or not +# to quote the specific field using double quotes. The default is to +# not quote anything. + +# $file_prefix : the prefix for the file + +# $record_prefix : the prefix for each record + +# $field_sep : the field separator. The default is ',' + +# $record_postfix : the postfix for each record + +# $record_sep : A record separator. Only shows up between records. + +# $file_postfix : the postfix for the entire file + +use Text::ParseWords; + +sub do_nothingus { +} + +if($#ARGV != 2) { + print "Usage: ccsv.pl \n"; + die; +} + +$infn=$ARGV[0]; +$cfgfn=$ARGV[1]; +$outfn=$ARGV[2]; + +$skip_lines = 0; +@pquote = {}; +$file_prefix = ""; +$record_prefix = ""; +$finc = ""; +$field_sep = ","; +$record_postfix = ""; +$record_sep = "\n"; +$file_postfix = ""; +$record_parser = \&do_nothingus; + +($inbase) = ($infn =~ m/^(\w*)/); + +do $cfgfn; + +open(IN, "<".$infn) or die "Can't open input file:".$infn; +open(OUT, ">".$outfn) or die "Can't open output file:".$outfn; + +$first_line = 1; + +while() { + chomp $_; + if (m/^\#/) { + if (m/^\#\@/) { + ($inc) = m/^\#\@(.*)/; + $finc = $finc.$inc."\n"; + } else { + # ignore + } + } elsif ($skip_lines > 0) { + $skip_lines--; + } else { + if($first_line == 0){ + print OUT $record_sep; + } else { + $file_prefix =~ s/\$finc/$finc/; + print OUT $file_prefix; + $first_line = 0; + } + + @fields = &parse_line(',',0,$_); + for(@fields) { + chomp; + s/^\s*//; + } + + &$record_parser(\@fields); + + print OUT $record_prefix; + for(my $i=0; $i <= $#fields; $i++) { + print OUT $field_sep if $i != 0; + print OUT 'L"' if $pquote[$i] == 1; + print OUT $fields[$i]; + print OUT '"' if $pquote[$i] == 1; + } + print OUT $record_postfix; + } +} + +if ($first_line == 1) { + print OUT $file_prefix; +} + +print OUT $file_postfix; + +close INF; +close OUT; diff --git a/krb5-1-6/src/windows/identity/config/csvschema.cfg b/krb5-1-6/src/windows/identity/config/csvschema.cfg new file mode 100644 index 000000000..a21c83c5b --- /dev/null +++ b/krb5-1-6/src/windows/identity/config/csvschema.cfg @@ -0,0 +1,67 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +$file_prefix = < + +\$finc + +kconf_schema schema_$inbase\[] = { +EOS + +$record_prefix = "{"; + +$record_sep = ",\n"; + +$record_postfix = "}"; + +$file_postfix = < + +/* Language specific version strings */ +#define KH_VERSTR_COMPANY_1033 "$(NETIDMGR_SRC_COMPANY_1033)" +#define KH_VERSTR_COPYRIGHT_1033 "$(NETIDMGR_SRC_COPYRIGHT_1033)" +#define KH_VERSTR_PRODUCT_1033 "$(NETIDMGR_PRODUCT_1033)" +#define KH_VERSTR_VERSION_1033 "$(NETIDMGR_VERSION_STR_1033)" + +!ifdef NETIDMGR_COMMENT_STR_1033 +#define KH_VERSTR_COMMENT_1033 "$(NETIDMGR_COMMENT_STR_1033)" +#define KH_VERSTR_BUILDINFO_1033 KH_VERSTR_COMMENT_1033 +!endif +!ifdef NETIDMGR_PRIVATE_STR_1033 +#define KH_VERSTR_PRIVATE_1033 "$(NETIDMGR_PRIVATE_STR_1033)" +#define KH_VERSTR_BUILDINFO_1033 KH_VERSTR_PRIVATE_1033 +!endif +!ifdef NETIDMGR_SPECIAL_STR_1033 +#define KH_VERSTR_SPECIAL_1033 "$(NETIDMGR_SPECIAL_STR_1033)" +#define KH_VERSTR_BUILDINFO_1033 KH_VERSTR_SPECIAL_1033 +!endif +#endif + +#define KH_BUILD "$(KH_BUILD)" + +! if "$(KH_BUILD)"=="RETAIL" +#define KH_BUILD_RETAIL +! elseif "$(KH_RELEASE)"=="PRERELEASE" +#define KH_BUILD_PRERELEASE +! elseif "$(KH_RELEASE)"=="PRIVATE" +#define KH_BUILD_PRIVATE +! elseif "$(KH_RELEASE)"=="SPECIAL" +#define KH_BUILD_SPECIAL +! endif + +<< + diff --git a/krb5-1-6/src/windows/identity/config/netidmgr_version.h.in b/krb5-1-6/src/windows/identity/config/netidmgr_version.h.in new file mode 100644 index 000000000..febbeb3d7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/config/netidmgr_version.h.in @@ -0,0 +1,63 @@ +$(VERSIONEXT): Makefile Makefile.w32 + $(CP) << $(VERSIONEXT) +/* Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __NETIDMGR_VERSION_H +#define __NETIDMGR_VERSION_H + +#include + +/* Version number macros */ +#define KH_VERSION_MAJOR $(NETIDMGR_VERSION_MAJOR) +#define KH_VERSION_MINOR $(NETIDMGR_VERSION_MINOR) +#define KH_VERSION_PATCH $(NETIDMGR_VERSION_PATCH) +#define KH_VERSION_AUX $(NETIDMGR_VERSION_AUX) + +#define KH_VERSION_API $(NETIDMGR_VERSION_API) +#define KH_VERSION_API_MINCOMPAT $(NETIDMGR_VERSION_API_MINCOMPAT) + +#define KH_VERSION_LIST $(NETIDMGR_VERSIONC) +#define KH_VERSION_STRING "$(NETIDMGR_VERSION)" +#define KH_VERSION_STRINGW L"$(NETIDMGR_VERSION)" +#define KH_VERSION_STRINGC "$(NETIDMGR_VERSIONC)" +#define KH_VERSION_STRINGCW L"$(NETIDMGR_VERSIONC)" +#define KH_VERSION_STRINGAPI "$(NETIDMGR_VERSION_API)" + +/* Version definition macros */ +#define KH_VER_FILEFLAGMASK 0x17L +#define KH_VER_FILEFLAGS $(kh_fileflags) +#define KH_VER_FILEOS $(kh_fileos) +#define KH_VER_FILETYPEDLL $(kh_filetype_dll) +#define KH_VER_FILETYPEAPP $(kh_filetype_app) + +/* Special macros for NetIDMgr special string resources */ +#define NIMV_MODULE "NIDM_Module" +#define NIMV_PLUGINS "NIDM_Plugins" +#define NIMV_APIVER "NIDM_APIVers" +#define NIMV_SUPPORT "NIDM_Support" + +#endif +<< + diff --git a/krb5-1-6/src/windows/identity/doc/Makefile b/krb5-1-6/src/windows/identity/doc/Makefile new file mode 100644 index 000000000..db40d0f65 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/Makefile @@ -0,0 +1,71 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=doc +!include <../config/Makefile.w32> + +all: mkdirs docs + +docs: + $(DOXYGEN) << +@INCLUDE = doxyfile.cfg + +PROJECT_NUMBER = "$(KHIMAIRA_VERSION)" + +OUTPUT_DIRECTORY = "$(DOCDIR)" + +STRIP_FROM_PATH = "$(SRC)" + +INTERNAL_DOCS = NO + +WARN_LOGFILE = "$(OBJ)\doxywarnings.txt" + +INPUT = "$(SRC)\include" +INPUT += "$(SRC)\kconfig" +INPUT += "$(SRC)\kcreddb" +INPUT += "$(SRC)\kmq" +INPUT += "$(SRC)\ui" +INPUT += "$(SRC)\uilib" +INPUT += "$(SRC)\util" +INPUT += "$(SRC)\doc" +INPUT += "$(SRC)\kmm" +INPUT += "$(SRC)\kherr" +!ifdef BUILD_AFS +INPUT += "$(SRC)\plugins\afs" + +ALIASES = "apiversion=$(NETIDMGR_VERSION_API)" +!endif + +IMAGE_PATH = "$(SRC)\doc\images" + +INCLUDE_PATH = "$(INCDIR)" "$(SRC)\include" + +CHM_FILE = "$(DOCDIR)\netiddev.chm" +<< + -$(HHC) $(DOCDIR)\html\index.hhp + +clean:: + if exist "$(DOCDIR)/html" $(RMDIR) /s /q "$(DOCDIR)\html" + if exist "$(DOCDIR)" $(RM) "$(DOCDIR)\*.*" diff --git a/krb5-1-6/src/windows/identity/doc/cred_aquisition.h b/krb5-1-6/src/windows/identity/doc/cred_aquisition.h new file mode 100644 index 000000000..613d5a04b --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/cred_aquisition.h @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page cred_acq Managed credential acquisition + + Credential providers and identity providers must participate in + managed credential acquisition in order to respond to the user's + requests to obtain new credentials for an identity or to renew + credentials for an existing identity. + + There are two major processes that result in managed credential + acuqisition. One is the acquisition of credentials, while the + other is credential renewal. During a renewal, existing + credentials are used to obtain new credentials which expire later + than the existing credential. Typically, the identity provider + performs the task of obtaining renewed initial credentials while + the other credential providers obtain new credentials based on + these initial credentials. + + \section cred_acq_new New Credentials + + When a user initiates the process of initial credential + acquisition, Network Identity Manager broadcasts a + <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> message. Credential providers + which need to participate in the credential acquisition should + respond to this message as detailed in \ref cred_acq_handle. + + \section cred_acq_renew Renew Credentials + + Network Identity Manager broadcasts a + <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> message to initiate the + process of renewing credentials. This may be triggered + automatically or by a user action. Credential providers which + need to participate in the renewal should respond to this message + as detailed in \ref cred_acq_handle. + + The following pages provide detailed information: + + - \subpage cred_acq_new_resp + - \subpage cred_acq_dlgproc + */ + +/*! \page cred_acq_new_resp Handling new credentials acquisition + + The process of acquiring credentials happens as follows: + + - Network Identity Manager creates a ::khui_new_creds object and a + credentials acquisition window. + + - <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> or + <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> is sent to all the + credentials providers. + + - The credential providers create the panels (where appropriate) + for customizing their respective credential types. The type, + panel and any dependency information is populated into a + ::khui_new_creds_by_type structure and added to the + ::khui_new_creds structure. (See khui_cw_add_type()). + + - <::KMSG_CRED, ::KMSG_CRED_DIALOG_PRESTART> is sent to all the + credentials providers. + + - <::KMSG_CRED, ::KMSG_CRED_DIALOG_START> is sent to all the + credentials providers. + + - The dialog for obtaining credentials is displayed. + Notifications between the main dialog and the individual panels + are done through ::KHUI_WM_NC_NOTIFY messages to the dialog + procedures. + + - Once the dialog processing is done, a ::WMNC_DIALOG_PREPROCESS + message is sent to the dialog procedure. + + - Network Identity Manager posts + <::KMSG_CRED,::KMSG_CRED_DIALOG_PROCESS> message to all the + credentials providers. Each provider should check if the user + cancelled the dialog or indicated that the new credentials + should be obtained and act accordingly. The \c result field of + the ::khui_new_creds structure will be set to either + ::KHUI_NC_RESULT_PROCESS or ::KHUI_NC_RESULT_CANCEL to indicate + whether the user wishes to acquire credentials or cancel the + operation. + + - Once all the plug-ins have processed the <::KMSG_CRED, + ::KMSG_CRED_DIALOG_PROCESS> message, the application checks + whether the new credentials dialog should continue processing, + or whether the dialog should be closed. If the dialog should + continue processing, then the dialog returns to the state it was + in prior to the ::WMNC_DIALOG_PREPROCESS message was sent. If + the dialog should be closed, then a <::KMSG_CRED, + ::KMSG_CRED_END> message is sent. + + - A <::KMSG_CRED, ::KMSG_CRED_END> message signals the end of the + credentials acquisition process. Each credentials provider is + responsible for removing the ::khui_new_creds_by_type structre + from the ::khui_new_creds structure and freeing up any resources + it allocated earlier in preparation for obtaining new + credentials. + + \section cred_acq_handle Responding to credential acquisition messages + + \subsection cred_acq_handle_init <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> and <::KMSG_CRED,::KMSG_CRED_RENEW_CREDS> Messages + + The credential acquisition messages are + <::KMSG_CRED,::KMSG_CRED_NEW_CREDS> and <::KMSG_CRED, + ::KMSG_CRED_RENEW_CREDS>. They are structured as follows: + + - \b type : ::KMSG_CRED + - \b subtype: ::KMSG_CRED_NEW_CREDS or ::KMSG_CRED_RENEW_CREDS + - \b uparam : 0 (unused) + - \b vparam : a pointer to a ::khui_new_creds structure. + + The \a vparam parameter of the message, as shown above, is a + pointer to a ::khui_new_creds structure. You can use the \a + subtype field of this structure to determine whether this is a new + credentials acquisition or a renewal. + + In response to this message, a credentials provider is expected to + provide a configuration panel which the user can use to customize + how the credentials of this type are to be obtained. The panel is + described by the ::khui_new_creds_by_type structure. + + \subsubsection cred_acq_panel_spec Specifying the credentials type panel + + The credentials type panel is used by the user to customize how + credentials of the specified type are to be obtained. The + ::khui_new_creds_by_type structure that describes the panel can be + used to specify a number of parameters that guide how the panel is + to be displayed in the new credentials acquisition dialog. + + The \a name field defines a localized string that will be + displayed in the tab control that houses the panel. If it is \a + NULL, then the name of the credentials type is used. Optionally, + an icon can be specified in the \a icon field which will appear + alongside the name. A tooltip may be provided in the \a tooltip + field which will be displayed when the user hovers the mouse over + the tab. + + In order to assert that the tab appears at a specific position in + the list of tabs, you can specify a positive number in the \a + ordinal field. Zero does not count as a valid ordinal. The + panels with positive ordinals are arranged first in increasing + order of ordinal (conflicts are resolved by sorting along the \a + name). Then the panels without a positive ordianl are arranged + behind these in increasing order of \a name. + + Currently, the credentials provider must specify a dialog template + that will be used to create the embedded dialog for configuring + new credentials for the type. This is done by setting the + khui_new_creds_by_type::h_module, khui_new_creds_by_type::dlg_proc + and khui_new_creds_by_type::dlg_template fields. + + Following is example code which suggests how this could be done: + + \code + // Message handling code for KMSG_CRED_NEW_CREDS or + // KMSG_CRED_INIT_CREDS + ... + khui_new_creds * c; + khui_new_creds_by_type * t; + + c = (khui_new_creds *) vparam; + t = PMALLOC(sizeof(*t)); + ZeroMemory(t, sizeof(*t)); + + t->type = my_cred_type; + + // set look and feel params + t->ordinal = 3; // third in line + t->name = L"My panel name"; + t->icon = LoadIcon(my_hInstance, MAKEINTRESOURCE(IDI_PANEL_ICON)); + t->tooltip = L"Configure credentials of my type"; + + // specify the dialog template to use + t->h_module = my_hInstance; + t->dlg_proc = my_dialog_procedure; + t->dlg_template = MAKEINTRESOURCE(IDD_NEW_CREDS); + + if(KHM_FAILED(khui_cw_add_type(c,t))) { + // handle error + } + \endcode + + It is important to note that the ::khui_new_creds_by_type pointer + that is passed into khui_cw_add_type() points to an allocated + block of memory which should remain in memory until + <::KMSG_CRED,::KMSG_CRED_END> message is received. + + For information on how the dialog procedure should be written, see + \ref cred_acq_dlgproc . + +*/ + +/*! \page cred_acq_dlgproc Writing the dialog procedure for a cred type panel + + Once each credentials provider has had a chance to add a + credentials type panel for the new credentials dialog, the + application will attempt to create all the dialog panels. It will + use the dialog template and the dialog procedure specified in the + \c dlg_proc and \c dlg_template members of the + ::khui_new_creds_by_type structure. + + The credentials type panel will be an ordinary dialog that is + created as a child of the new credentials window. Therefore, the + dialog template should have the WS_CHILD style and the + WS_EX_CONTROLPARENT extended style set so that the main dialog + procedure can correctly navigate the child dialog. + + \section cred_acq_dlgmsg Handling Messages + + \subsection cred_acq_dlg_WM_INITDIALOG WM_INITDIALOG + + When the application creates a credentials type panel dialog, it + passes a pointer to the ::khui_new_creds structure as the \c + LPARAM parameter. This can be used to query for the credentials + type panel for the plug-in, as follows: + + \code + + // Handler for WM_INITDIALOG: + // HWND hwnd, WPARAM wParam and LPARAM lParam + + khui_new_creds * nc = NULL; + khui_new_creds_by_type * nct = NULL; + + // We can define and use a structure like the following to + // maintain the data that will be used to drive the dialog user + // interface and to store credentials type settings: + struct nc_dialog_data * d = NULL; + + nc = (khui_new_creds *) lParam; + + // Now we can use nc to query for our credentials type structure + khui_cw_find_type(nc, credtype_id, &nct); + + assert(nct); + + // The dialog data structure should live until we receive + // WM_DESTROY. + d = malloc(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->nc = nc; + d->nct = nct; + + // Store it as our user data for the dialog. + SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d); + + // The aux member of the khui_new_creds_by_type structure is + // reserved for use by the credentials provider. We can use it to + // store our dialog data. This way, the dialog procedure and the + // plug-in thread can both access it and use it to store + // credential options for use when obtaining credentials. The + // dialog and the dialog data exist until KMSG_CRED_END is sent. + nct->aux = (LPARAM) d; + + // We should return FALSE here to indicate that we don't want to + // set keyboard focus to this dialog yet. The application will + // attempt to create all the credentials type panels as well as + // the other child dialogs used for the new credentials opeartion. + return FALSE; + + \endcode + + \subsection cred_acq_dlg_WM_NC_NOTIFY WM_NC_NOTIFY + + ::WM_NC_NOTIFY is a special window message that Network Identity + Manager uses to communicate with credentials type panels. The + messages are listed in the ::khui_wm_nc_notifications enumeration. + The format of the message is as follows: + + - uMsg : KHUI_WM_NC_NOTIFY + - HIWORD(wParam) : one of ::khui_wm_nc_notifications + - LPARAM : pointer to the ::khui_new_creds structure (except where noted) + + The ::WM_NC_NOTIFY notifications that a credentials provider is + expected to handle are the following: + + - ::WMNC_IDENTITY_CHANGE + + \copydoc WMNC_IDENTITY_CHANGE + + - ::WMNC_DIALOG_MOVE + + \copydoc WMNC_DIALOG_MOVE + + - ::WMNC_UPDATE_CREDTEXT + + \copydoc WMNC_UPDATE_CREDTEXT + + - ::WMNC_CREDTEXT_LINK + + \copydoc WMNC_CREDTEXT_LINK + + - ::WMNC_DIALOG_PREPROCESS + + \copydoc WMNC_DIALOG_PREPROCESS + + \section cred_acq_other Other notes + +*/ diff --git a/krb5-1-6/src/windows/identity/doc/cred_data_types.h b/krb5-1-6/src/windows/identity/doc/cred_data_types.h new file mode 100644 index 000000000..f2a412211 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/cred_data_types.h @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page cred_data_types Data types in Network Identity Manager + + Network Identity Manager's Credentials Database supports several + useful data types. In addition, plug-ins can define custom data + types. Only a few operations are expected of these data types + since the core KCDB delegates fine grained operations to other + entities that understand the underlying format. + + A field in a credential can have any one of these data types, but + it must have some data type. Each value can be at most \a + KCDB_TYPE_MAXCB bytes in length regardless of the data type. + + Some data types have a fixed size (such as \a Int32), while others + are variable size. The required memory for each field in a + credential is allocated as needed. + + \section kcdb_pg_dt Data types + + Descriptions of individual data types are below. + + \subsection kcdb_pg_idt Individual data types + + \subsubsection kcdb_pg_idt_v Void + + Type identifier : ::KCDB_TYPE_VOID + + The Void data type is used to indicate that the associated object + does not contain any data. + + \subsubsection kcdb_pg_idt_s String + + Type identifier : ::KCDB_TYPE_STRING + + A unicode string that is terminated with a unicode NULL (L'\\0'). + By default, the type has the following flags: + + \a KCDB_TYPE_FLAG_CB_AUTO + + This is because, as long as the string is terminated with a unicode NULL, + the length of the string, and therefore it's size in bytes, can be inferred + from the data itself. + + \subsubsection kcdb_pg_idt_d Date + + Type identifier : ::KCDB_TYPE_DATE + + Dates and times in Network Identity Manager are stored in \a + FILETIME structures. Utility functions are provided for + converting from other formats such as \a time_t. + + \subsubsection kcdb_pg_idt_i Interval + + Type identifier : ::KCDB_TYPE_INTERVAL + + Stores an interval of time. Stored as a 64-bit signed integer. The + string representation of this data type is different from the \a + Date data type and designates an interval of time. + + The special value _I64_MAX (which is defined in limits.h as + 0x7fffffffffffffff, or in other words, the largest positive value + that can be stored in a 64-bit signed integer) is used to + represent an interval of unknown length. + + The string representations of a data value of Interval type are + defined as follows for English (US): + + - "(Unknown)" if the value is _I64_MAX + + - "(Expired)" if the value is less than zero + + - "%d days %d hours" if the value is greater than 24 hours + + - "%d hours %d mins" if the value is greater than 1 hour + + - "%d mins %d secs" if the value is greater than 1 minute + + - "%d seconds" otherwise + + \subsubsection kcdb_pg_idt_i32 Int32 + + Type identifier : ::KCDB_TYPE_INT32 + + A signed 32-bit integer. + + \subsubsection kcdb_pg_idt_i64 Int64 + + Type identifier : ::KCDB_TYPE_INT64 + + A signed 64-bit integer. + + \subsubsection kcdb_pg_idt_da Data + + Type identifier : ::KCDB_TYPE_DATA + + Raw data. Can contain a byte stream. This data type can be used + by plug-ins to associate raw data with a credential. However, + there is no built-in string representation for this data type. As + such, this is not meant to be used for storing anything that has + to be displayed to the user verbatim. + + \section kcdb_pg_cust Custom data types + + \subsection kcdb_pg_cb Custom data type call backs + + Custom data types in the Network Identity Manager Credentials + Database are defined using \a kcdb_type structures that must + include several callback functions. The expected behavior of + these callback functions is documented below. + + \subsubsection kcdb_pg_cb_ts toString + + \code + khm_int32 toString( + const void * data, + khm_int32 cb_data, + wchar_t *buffer, + khm_int32 *pcb_buffer, + khm_int32 flags); + \endcode + + Produce the localized string representation of the object pointed to by + \a data. The size of the data block is specified by the \a cb_data + parameter. If the data type specified the \a KCDB_TYPE_FLAG_CB_AUTO flag + then \a cb_data can be \a KCDB_CBSIZE_AUTO, in which case the size of the + data block is to be inferred. + + \a toString should assume that the block of data pointed to by \a data is + valid for this data type. + + The \a pcb_buffer parameter is always a valid pointer to an \a khm_int32 + variable. + + The \a buffer parameter is a pointer to a \a wchar_t buffer which is to + receive the unicode string representing the object. \a buffer may be + \a NULL, in which case the required size of the buffer should be returned + in \a pcb_buffer. In this case, the function should return + \a KHM_ERROR_TOO_LONG. + + If the \a buffer parameter is not \a NULL and the \a pcb_buffer specifies + that the buffer is large enough to hold the string representation, the + function should copy the string representation to the buffer, set the + \a pcb_buffer to the number of bytes that were copied including the + terminating \a NULL, and return \a KHM_ERROR_SUCCESS. + + If the \a buffer parameter is not \a NULL and the \a pcb_buffer specifies + a buffer that is not large enough, the function should set \a pcb_buffer + to the required size (including the terminating \a NULL) and then return + \a KHM_ERROR_TOO_LONG. + + \subsubsection kcdb_pg_cb_cmp comp + + \code + khm_int32 comp( + const void * data1, + khm_int32 cb_data1, + const void * data2, + khm_int32 cb_d2); + \endcode + + Compares two objects and returns a value indicating the relative ordering. + + Since the KCDB does not interpret any data type, it relies on a loose + definition of what a relative ordering is. It is left up to each data + type callback to interpret what 'ascending' and 'descending' mean. + + The return value \a r should be as follows: + + \a r < 0 : if \a data1 < \a data2 + + \a r > 0 : if \a data1 > \a data2 + + \a r = 0 : if \a data1 = \a data2 or no relative ordering can be determined + for the two objects \a data1 and \a data2. + + The function should assume that both objects are valid for this data type. + + The size specifiers \a cb_data1 and \a cb_data2 can (either or both) be + \a KCDB_CBSIZE_AUTO if the data type specified \a KCDB_TYPE_FLAG_CB_AUTO + flag. + + \subsubsection kcdb_pg_cb_dup dup + + \code + khm_int32 dup( + const void * d_src, + khm_int32 cb_src, + void * d_dst, + khm_int32 * pcb_dst); + \endcode + + Duplicate an object. The object pointed to by \a d_src is to be copied to + the buffer pointed to by \a d_dst. The function is to assume that \a d_src + object is valid. The size specifier \a cb_src may be \a KCDB_CBSIZE_AUTO + if \a KCDB_TYPE_FLAG_CB_AUTO was specified for the data type. + + If \a d_dst pointer is \a NULL, then the required buffer size should be + returned in \a pcb_dst. In this case, the function itself should return + \a KHM_ERROR_TOO_LONG. The same behavior should occur if \a d_dst is non + \a NULL and \a pcb_dst indicates that the buffer is not sufficient. + + If \a d_dst is not \a NULL and \a pcb_dst indicates that the buffer is + sufficient, then a copy of the object in \a d_src should be placed in + \a d_dst. The function shold return \a KHM_ERROR_SUCCESS and set + \a pcb_dst to the number of bytes that were copied. + + This callback will only be called when the credentials database is + retrieving objects from the outside. Once it receives an object it may be + copied or moved as required. Hence the object should not assume to reside + in a specific location of memory. Also, \a dup is not intended to perform + such functions as reference counting which require knowledge of a precise + number of instances of an object, as the credentials database may copy + the object simply by copying the block of memory. + + Note that whenever \a pcb_dst is to be set, it MUST be set to a valid byte + count. It can not be assigned \a KCDB_CBSIZE_AUTO even if the data type + supports it. The \a pcb_dst parameter is used internally to allocate + memory for the object. + + \subsubsection kcdb_pg_cb_iv isValid + + \code + khm_boolean isValid( + const void * data, + khm_int32 cb_data); + \endcode + + Checks if the object pointed to by the \a data pointer is a valid object + for this data type. If the data type specified the \a KCDB_TYPE_CB_AUTO + flag, then the \a cb_data parameter may be \a KCDB_CBSIZE_AUTO, in which + the size of the object should be inferred from the data. + + The function should be able to determine the validity of the object and + return \a TRUE if it is valid. Return \a FALSE if it isn't, or if the + size of the object can not be inferred from the given data, or if the + inferred size exceeds \a KCDB_TYPE_MAXCB. + +*/ diff --git a/krb5-1-6/src/windows/identity/doc/cred_main.h b/krb5-1-6/src/windows/identity/doc/cred_main.h new file mode 100644 index 000000000..cbd88bbcb --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/cred_main.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page cred Credentials Providers + + \section cred_contents Contents + + - \subpage cred_data_types + - \subpage cred_msgs + - \subpage cred_acq + - \subpage cred_prop_pages +*/ diff --git a/krb5-1-6/src/windows/identity/doc/cred_msgs.h b/krb5-1-6/src/windows/identity/doc/cred_msgs.h new file mode 100644 index 000000000..a60b883d2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/cred_msgs.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page cred_msgs Handling credentials provider messages + +A credentials provider plug-in receives a number of messages during the +course of execution. This section describes the appropriate ways of +handling these messages. + + - \ref pi_credmsg_system + - \ref pi_credmsg_cred + - \ref pi_credmsg_list + - \ref pi_credmsg_credacq + - \ref pi_credmsg_destroy + - \ref pi_credmsg_import + - \ref pi_credmsg_prop + +\section pi_credmsg_system System mesages + +There are only two system messages that a credentials provider needs +to handle. Both of these are explained elsewhere as they deal with +initialization and uninitialization of the plug-in. See the following +two sections for details on handling these messages. + +- <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> \ref pi_pt_cred_init +- <::KMSG_SYSTEM,::KMSG_SYSTEM_EXIT> \ref pi_pt_cred_exit + +\section pi_credmsg_cred Credential messages + +\subsection pi_credmsg_list Listing Credentials + +When the Network Identity Manager application needs to refresh the +list of credentials that credentials providers are aware of, it sends +out a <::KMSG_CRED, ::KMSG_CRED_REFRESH> message. + +Each credentials provider is expected to populate a credential set +with the credentials that it is aware of and call +kcdb_credset_collect() or kcdb_credset_collect_filtered() to merge the +credentials into the root credentials set. + +In addition to responding to <::KMSG_CRED, ::KMSG_CRED_REFRESH>, each +credentials provider is expected to list and merge their credentials +during the following events: + +- When the plug-in is initialized, during <::KMSG_SYSTEM, ::KMSG_SYSTEM_INIT> + +- When the plug-in obtains new credentials during the new credentials + acquisition sequence and whenever the plug-in becomes aware of new + credentials. + +\subsection pi_credmsg_credacq Credential Acquisition Message Sequence + +The aquisition of new or renewed credentials is conducted via a +sequence of messages. Details of handling this sequence is explained +in the section \ref cred_acq . + +\subsection pi_credmsg_destroy Destroying Credentials + +When a request is received to destroy credentials, Network Identity +Manager sends out a <::KMSG_CRED, ::KMSG_CRED_DESTROY_CRED> message. +The \c vparam member of the message will point to a +::khui_action_context structure that describes which credentials are +being destroyed. The plug-in is expected to destroy any credentials +that were provided by the plug-in which are included in the user +interface context. + +\see \ref khui_context_using + +\subsection pi_credmsg_import Importing Credentials + +The import action is typically used to request that plug-ins import +any relevant credentials from the Windows LSA cache. This typically +only applies to plug-ins that provide Kerberos credentials and is not +discussed in detail. + +\subsection pi_credmsg_prop Property Pages + +Credentials providers are also expected to participate in the user +interface when the user makes a request to view the properties of a +credential or identity. + + - <::KMSG_CRED, ::KMSG_CRED_PP_BEGIN> + - <::KMSG_CRED, ::KMSG_CRED_PP_PRECREATE> + - <::KMSG_CRED, ::KMSG_CRED_PP_END> + - <::KMSG_CRED, ::KMSG_CRED_PP_DESTROY> + +Details about handling this sequence of messages is discussed in \ref +cred_prop_pages . + +\subsection pi_credmsg_addrchange Address Change Notification + +When the Network Identity Manager detects that that IP address of the +machine has changed, it will issue a <::KMSG_CRED, +::KMSG_CRED_ADDR_CHANGE>. Handling this notification is optional and +is only necessary for credentials providers which are affected by IP +address changes. This is just a notification and the plug-in is not +expected to take any special action. + +*/ diff --git a/krb5-1-6/src/windows/identity/doc/cred_prop_pages.h b/krb5-1-6/src/windows/identity/doc/cred_prop_pages.h new file mode 100644 index 000000000..19426237b --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/cred_prop_pages.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page cred_prop_pages Property Pages for Credentials + + This section describes the logistics of property pages. When a + user selects the 'Properties' option from a menu (either the File + menu or a context menu), then a KHUI_ACTION_PROPERTIES action is + triggered. This is handled by the credentials window and triggers + the launch of a property sheet if there is a valid context to + extract properties from. + + Sequence of actions: + + - KHUI_ACTION_PROPERTIES action is triggered. + + - The main window dispatches the action to the credentials window. + + - If there is a valid context, then the credentials window calls + khui_ps_create_sheet() to create an empty property sheet + structure of type ::khui_property_sheet. The \a ctx member of + the structure is populated with the property context obtained + through khui_context_get(). + + In addition to the \c ctx member, depending on the scope of the + context, other fields of the ::khui_property_sheet structure + could also be set: + + - For ::KHUI_SCOPE_IDENT, the \c identity field will be set to + the selected identity. + + - For ::KHUI_SCOPE_CREDTYPE, the \c identity field will be set to + the selected identity, and the \c credtype field will be set to + the selected credential type. + + - For ::KHUI_SCOPE_CRED, in addition to the \c identity and \c + credtype fields being set as above, the \c cred field will be + set to a handle to the credential. + + - A global message is broadcast of type + <::KMSG_CRED,::KMSG_CRED_PP_BEGIN> with the parameter blob that + is a pointer to the ::khui_property_sheet structure. + + - Subscribers to <::KMSG_CRED> messages handle the message, check + the ::khui_property_sheet structure and determine whether or + not and what type property pages to add to the property sheet. + New property sheets are added by calling khui_ps_add_page(). + + The following code shows how this message might be handled. + + \code + + // Message handler code for KMSG_CRED_PP_BEGIN + + khui_property_sheet * ps; + PROPSHEETPAGE * psp; // from prsht.h + + if (ps->credtype == credtype_id && + ps->cred) { + + // We have been requested to show a property sheet for one of + // our credentials. + + // The PROPSHEETPAGE structure has to exist until we remove the + // property sheet page when we are handling KMSG_CRED_PP_END. + + psp = malloc(sizeof(*psp)); + ZeroMemory(p, sizeof(*psp)); + + psp->dwSize = sizeof(*psp); + psp->dwFlags = 0; + + // hResModule is the handle to the resource module + psp->hInstance = hResModule; + + // IDD_PP_CRED is the dialog template for our property page + psp->pszTemplate = MAKEINTRESOURCE(IDD_PP_CRED); + + // pp_cred_dlg_proc is the message handler for our property + // page. See the Platform SDK for details. + psp->pfnDlgProc = pp_cred_dlg_proc; + + // We can pass the khui_property_sheet structure as the + // lParam for the message handler so it knows the scope of + // the property sheet. + psp->lParam = (LPARAM) ps; + + // Finally, add a property page for our credential type + // stored in credtype_id. Note that only one property page + // can be added per credential type. + + khui_ps_add_page(ps, credtype_id, 0, psp, NULL); + + return KHM_ERROR_SUCCESS; + } + + \endcode + + - Once all the plug-ins have had a chance to add their property + sheets, a <::KMSG_CRED,::KMSG_CRED_PP_PRECREATE> message is + broadcast. This is a chance for the property page providers to + do any processing before the property page is created. + + - The property sheet is created and made visible with a call to + khui_ps_show_sheet(). + + - The Network Identity Manager message loop takes over. Further + interaction including notifications of 'Ok','Cancel','Apply' and + other property sheet related actions are handled through WIN32 + messages to the window procedure of the property sheet and the + message handlers for the individual property pages. + + - Once the user closes the property sheet, a + <::KMSG_CRED,::KMSG_CRED_PP_END> message is sent to all + subscribers. Individual subscribers who added pages to the + property sheet must free up any associated resources at this + point. + + Continuing our example from above, the following code could be + used to handle this message: + + \code + + // Handler for KMSG_CRED_PP_END + + khui_property_page * p = NULL; + + // If a property sheet was added by us, this call would get + // a handle to the property page structure. + + if (KHM_SUCCEEDED(khui_ps_find_page(ps, credtype_id, &p))) { + + // It is safe to assume that the property page window has + // been destroyed by the time we receive KMSG_CRED_PP_END. + // So we can free the PROPSHEETPAGE structure we allocated + // above. + + if (p->p_page) + free(p->p_page); + p->p_page = NULL; + + // The property page structure we added will automatically + // be removed and freed by the application. + } + + return KHM_ERROR_SUCCESS; + \endcode + + - All the ::khui_property_page structures that were allocated as + well as the ::khui_property_sheet structure are freed up with a + call to khui_ps_destroy_sheet(). + +\note The maximum number of property sheets that can be open at one +time is currently set to 256. Each property sheet can have a maximum +of 16 property pages. + */ diff --git a/krb5-1-6/src/windows/identity/doc/doxyfile.cfg b/krb5-1-6/src/windows/identity/doc/doxyfile.cfg new file mode 100644 index 000000000..7bb3092fe --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/doxyfile.cfg @@ -0,0 +1,1259 @@ +# Doxyfile 1.5.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Network Identity Manager" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = stylesheet.css + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = YES + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = YES + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = _WIN32 \ + UNICODE \ + _UNICODE + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen will always +# show the root nodes and its direct children regardless of this setting. + +DOT_GRAPH_MAX_NODES = 50 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/krb5-1-6/src/windows/identity/doc/footer.html b/krb5-1-6/src/windows/identity/doc/footer.html new file mode 100644 index 000000000..6383e6a57 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/footer.html @@ -0,0 +1,21 @@ +
+ + + + + + +
+
+ Generated on $datetime for $projectname $projectnumber by Doxygen $doxygenversion
+ © 2004-2007 Massachusetts Institute of Technology.
+ © 2005-2007 Secure Endpoints Inc.
+ Contact khimaira@mit.edu
+
+
+
+ +
+ + + diff --git a/krb5-1-6/src/windows/identity/doc/header.html b/krb5-1-6/src/windows/identity/doc/header.html new file mode 100644 index 000000000..b85d6a1e7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/header.html @@ -0,0 +1,6 @@ + + +$title + + + diff --git a/krb5-1-6/src/windows/identity/doc/images/credview-select-outline.jpg b/krb5-1-6/src/windows/identity/doc/images/credview-select-outline.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d06ca9f88cc2b5f816b837f4a3d2247186df5c0b GIT binary patch literal 16084 zcmeHt2UL{Vw&ssyL6M|nkRV775{n=zStLk~N|B++sYrz)1|%b3ASh9?#tMi?EUR;e`oK*!G6Vl11_j5t0@C`czD1) z+z)`A1a1N(L`1|yge1ho#H6GoXUS>Kk&}^;(^FAX&@eNwvM@6+F|lz9a)r)@$f0}u%7@{0Kg-}S^JB@zrOI!;1duM5tERfCBqG#Ipd_TaETTw6t#hB4-JM4CLF_vcjvFP-w7LU3oMKiU4@u8nyhKOOz;%V2=PK_t zaS2H&X_=e1l$2Fe)zt6m=^Gdt8JmEuZEWrA9UMKqynTHAp#Gtc!X7_)`Yb#y{zXD! z(#uz`(=#%&vUA?&=9QL}S5#J2*VMMOe)`aB8L{y48#P{8) z*+n0a(AG16|7(st{8OI&?$|&4ngGc0@o>Sz zrvwy$Bdtm-Frq6>HcQU)Di2k zecDMvBjOzvn0Su`9zVkZxu#fvmld5?UC7vCB7k{!F<#*?qz=I^$XOFLN8nsVHTf`I zjGirT3JmH~U#63y@xlV<9egJ=KMmeK^z~Hq49IEc>Wob#N$5LU08;DG6@;_1h?UWu zYegr-ub<{*)pqB7#0X9t@lEJ$`Lq7eUbE$=`+RtLO6X#5F^5qdEoYbITI<+F$)f;C z(blWBHc>b3G>J-cgt!+6QqrcDPxyCwy2Uu0gpGXacngdo%-RYgnDcIngvLRw#5&&R zBrXgZdKESrdm#@|U#8Z4LH$2=y#{TkKHyrxH89Hf#=3e}37wF4ql4vcx%S!sS<46M=hViIG-76`h6t9+^Pb zqE_lP@tLW?iNh@{kbig{I_sJ9&v-|FXHR~bpEGsqn5P*tr=w@Z^QYhZ7`i|em!8(4 zO2K#;*N+v1UVdx1@PP?6V4^Vxay?cp_69jM7g)MZ+H=QdA~vg#Zx(JaD(I?7w@KGR z4fLf=zaCV5<{msTUaPfSI`6sVPy9pNjr_M#?iauuji$N}jj_Pol@URzbtn0b3@~DeIeSqJ|ttuIt%o891@~$S3&0NUqUMd-lR4a>z*l0Svi?LJ{ zlYFjZK^8<{6z#n_*xWBZyo#GN9kynG1-hPK0mlps12-ni74;r=m^W7_K3S)5M#&Qk zke)9CL)~*{I^W#Tny^L`_HSGE=t|4EwJ&kAd@wTW_noWu%6H12BqfaO$sTxn&LQ~O zQpb>pz)?%C5{U8K*}(4Tc-IZH+P*uFpH0rEX-s37g_iFJs2$1Sf488*_m&h(HI7yo zH!wT+l&<*}JCBWNmkWSsL^6G{E=0f`<5Zc6{E7@}d3Fv>rK)%(MvB9=>|9pv6pY=S zf_*>D_YUo>@wpzj@?n8AOXRi29*c>fe)pe*z4d(t+O!J`ERSI{h4v^Q^2^m&;QJ(2 z`7UhwbHh5A!bRBLIu^K+gnUw&=J_*2c(8y0q7iw31>!YOt&>_cTM9b^3I}|!#hX~5 zLI(?+qs9WdRTw>mQ++>g8dyHm5_N(FI*n7rK>M9Gh%izrb<5cB7Nvd7RrW?;|%4Me-bu(Adw8e-z;VH#|4?cWu)oR<3r6 z6q=iP0|s4IjvKXp7QVnl^&vDO#C?OW<1dW28fASE;b(xE1a791^qD- z57p%5WD9Fhpm;1`Ig2iOg$2kaFiYp*$aFT&rsQzKN zQy3zlLg<(3LCE#z6KkLix?sP`*st?i{A}EY`u~+bH~|Vxzpia-o<@#b}K* zq#Uj)S-}EfxE(`x8KVU|tld4q$(Vj=+HW$pP76wH#!WZ$+jL&7yY1WxJ5g9*VH*oL z6|>_M#PsTK`YVrvV;v5UnNZwWQp5r|I6&0Xm|A%7TmQb;dizSozZ(8KV80mtJ=EVD z9{r0cAGzBJV;*CHN6y5SwX+bM-7#x4$CJDu;V&l#tWG%bx?aqk{(3GVmoMNSFmk|4 z+U1!DPA#y&VeKY{6?HSdjnx(Z&MEr@G>{(EdwK*b6^U#t4D7dP-QmW7al>%FRXDZv zmohaHCk+?hNXaa;gUT%=8A2lMN0YN(q&}(T8opB_P=3O|cQyOj9R@w(FCWqyW%X^o zZY(Nw@uYveOTB#DKziIl8fWji|8y}jlp|}nDVOOX$@5Ty1J_5vqN75QJ!1?s*LiL| z=6iLhoKgBXB8IeceK>yR<7oJSg>ST{J`;N3btAuzPooyQTr$LoRUXz7wQGq&uQVQ0 z3Sj|;3=EBLIBqlBR>A^J&tS(RLBvW9m=Cs=dq+FbNV4&pC2)9Cu)>q;&s9q62AtnU z+w~G<_^a_Yw-UN_MAj2`@h0!HQJvSXYDs%4VL)wUvOcP9++WvQ^;|mz9PidVl`hK^ zg4geOWWq|4THX#@P4#cm1|A!dBzq4R zN|-yj3zdUuP>Lem^kW4Pp6Yw5IofFy9Jz)bvJJ*B5;zfxYzM{O>BXn6%#AWQ<8hF8 zJSltjZFc8G)b7O3<>ANH^ioq8dkh3FH)d=W8}07og$2JduQs}SqBNmkw(3v23x zEK+-hqCC@B8bt6x_;!4J6+K+Ksn{j`nVsJ%pSnZwPCFKerLd!JT0EA7OV{s=o$$8H zraQ1lL8(OHKIcC_ap*jr95kIKC9NNheJu6151xH8of(#EU`Wdy0vx2eIS#9~O>oW^of##-*#&-3PRf%1#= z;_HUK1!NslGw^!4n^UBeV*yIPP_+kdhrBhqrHre}ea7OHvpx{HRns>yo$67p)fSjI z*E;)pay=?+(9o~GPhG|IVnwT~9{yp!P=VHo+iWbm+JJ~;kA_i&5s#aL?E=}wdlYOJ zKn4OqN@uBZHT81+I>#%v>J%*W^Q0%sO7Y!&zHkyO(b#%Nbot~912G~Ys`{PV4_0-} z#vLV0gU7&}jHQ=)$!prpY=S;J`6>5qqs+5RGs3`b#mV31?#$yIu-)_N6MN9>uku;L zX}nxPV#_pW6p?{PDRsZ=#2fhl|1Dn43PpT$uLXthyU-lJH`FAORGakq-=+)-88BHR zt`mElHdh|DHBGKvl00+hO(Ng%RF|Tx71Z&myF$GH&X!Vbz%^`GEK~9b$)!I#;58O( z>TI2GP|~(!xy6k>gtbI;qd#GRhW=y2jEQ4;IZ;sO>$Qo)-i^h?3j;Sfs35MDmHWQ> zyoVcZMNO#8xg>n?dLmd^*q6p}P90U3x3N}xmlGh1FRu(IyoBX?%imKbX1$6GX$D_4 zFLvBqX+%;Y8ro@J!K%}a#<9RzF`*-B%&Eeh#j`ofa}JGm147%4FoC6<9H@J_X*_t! ztZlbi;9=%T-u=tA4`pijWvg z`y8{(I}p|-wJ1O{y)ippnOb7$U7WQEQR#w4*JjGic}q$;I`u{YAA@Ij2|`I!KHpB+qs&D=JX1!tQ5USY-?^{K9n80e0RFZ>Dm zTQpzWLP~%^G);nvR;ppGsbJ+c%bOFjB#mU2e_f61W7nF=Sjgs`{S>nd?nZUzQCpW#p6yQ-;LqeRxY^j)NMZ>lQ}A5|Cndd=01JwEgp0I77;=t zNC#f2-mv2cB>$sOMQU%MT;F=(!;S^dUt_5J>(YGngQyM^Y;ISUL42e#i=Xnb<^F8)eO%{Y@U`8nNbI98Mc!n4qsR>No3hG2@KCUO z*fQD_%w&hA|w^oCh67_+I)+)^WGQD9wZ54Y>p^5?ge&c`rU0axma@XZNsI; z*uv*2`BllJ#01o7)xXe4{$$zrllJkX=}=C2TJuq7p9Wt(+`+?**z#{w0fWYT8+9yf z`50vluF%yE+{qNMD@yb=;f9=M7+FxdJs(IDw-3I!Yw!$q?MR+x#DyJ^D*5>06Q^$_ z$k5E^?3k4piR3i?(6~2+YbUTzjJ?|C?Q`ATeub|hgjHy6=MmhvNFYets^W~NUB}2q zct+{mzCP{5UXNK`fJ)bNVbx6q8%85!+fwVisS2lNx>-Bbr!OxzH#P^(5Z36@YU6dp z!E-D{R6Fevn)i44m37KB(&8*-R5U$MQL zod!>FBRvo<5dCSfCdzlvb$n9-dR>u>KlpZ>>Kht&L}|w*{H+g)h>pAwXO!G7u^Od7 zL#Q9sND(vT+i?A!rvu&19d4bZbkf9&?X%{yw{`T&rgSyA7!|hO9_q;34Wqc{O<$6` zp%g9(FAlg>dXBzARzB_N`l$ro4X&wf zPwS8k+K7&=Y{y@lA1{patAF*))GE$G@d16D^o_`V#JPjz(SXf+A~td2lV)%O`TIR!nb!u;NlyL`gu!w7VM&>t_9%2T2#cE(%ry5p~Ila*Gp4S%X%t7kJ;Hb+`d{bStuX&O{7-1dpmhN%WCGgbZe?KmsH8xZxPUt2;#PL{=Uy;Mcy8JHZxqQxR`M5NT%`?fulxaEWsjvea~d6`2#%a zFr-n8d-%$y8(xk#L{k<)Sz9V2TWHG}bzhZBhnp@ClkU650vxrK_A`^#qa`Y&g z(29PyXr(!$QiM)5*ld*OJuR7(HRwXgmJgQ0=uFlnYyF1HKbP2VjpT@!(wi-+>UC4q z`Sambdq}srQZv8^1M0GDXs3m0q=gzaN+wP-`hU3ahbw7br^1zRpDCC65byDbMO^h` zRMUT3A{Y)Xt2|bjH{LFWSZ;iIWBR#FFtAg9`h^rnw=!>?F{#~IqPb+I2f7N6UvI=Y zNMLN@W*mLRCY2lqCH95I_zM;Ur}NAAt?nq}6|Eck~HO45AQ?T zHmj$hzd_b#TyGxeo2x~=JT(9lN9WaOlKEdp=MRxAmQwpx}G9zTtYN}Qcr%7Mzi z=HK=@eQvHyx?EKonK>~}bu0YB+k}_*0`ndvFIeM8Ofm}&_O~6H*yeiL$c4`;F@M@I zd;DNtP*ONni>&;hgQI~&YCtcS4>4A!R_BqwnltO|^yP8#?yFxbL-A(qcChPKjdFHX5kMvldtuM``z52L+%9%80TE0i1db*0S zn2p&7EFG*cD(E?M4!1iNDzW}*10not=?^pD!4L7KeV?&*T#Q8H8k@KE0T=K7NMwGJ z>sA#sL6)?*)}|4mcPZMc>xY~t_@RRa>CyS~jmt+E^@qC~#y`aC$0;5@taA`(h{E7{ z25k$u=U0CS81;`FEHMd}FUB2Nrp+RG$=XY7eu&tQbDB>_Wn|ZK?-bX`D*nZYzZkJ4 z@fRb0tq1W?g7t6oKY~y|w4Q%~mnK z5R`=a^=YxL8%nP}>64J3&3#|AAxUZFHVnS;f-QsACIffE`!s=z+owMfd>k;p>I3=W zN`$VSdgor(-R9wk1x#?=iM)Hs;emSEg)R9`rc`>W@kmi-K@I8j`!u_PvjUlf&F8ai zKo4}YEVDaBwqNM$&)?QG^&ASV!u`vA;en2ZZ6H!G4IZhYURhSN6G+{cD6+aU(+_zC z4)ve~#GDPz=$oJ7^H9W{l{Ovhgm2ziH+j9+{KZVAI4EgTSc9qLE#i@tEG2I#7AUyk z;WvS7YoFXIH_(#H!vc#_@~ggDS^=86{ywaw=KW`(4VTwE?@XjUdOK`Y*AR}rS65{d zb@hhw^Ojmv9cQF^4F}0&jT*_r&R~va?kAa*J1gOu?8cdu>|d1`H_0Q`)?@M-8}I?a zfySJ~&q0WA4bb}}q0+EA<4N1frHu&+>$py9-8}@Iw{&t zw7?74ek~x#t2-ppX62;usHy;^Ju^WMPMaOOLFbpq>aLP=GSUN&g10@H^CmL{ixawP zns^q2bXz}56z0sDIZ|b6*^b5CW{-TSLLk;j=hNn<8u88Bs<=EbhkOWS4sp+)9XBiZ zQsAqj1mPI(d8+^I*|6$Holdu^9v`jj`!>}cEa0kF8{Eb0FJFf)7HI5|i`(kwi|{*k zO050-BoyN88vJ!En$su8tDon3^Ms16{->$;yq82-$enewiqhau%gK5fhMIS7Lf!`! z%-Xi*fo^qWmff#>b;(JU9*$n3_mQ79t=L_P!!VbO6cdhASC^S~T15>yMAlyL=&umX zjrr;W2^**zC|SG&Aw9O~*V7gm3l&pC0M;nA1Dz8vW^{Y?Ym?2S5yY0(Xa8;ZTIazz4cAG? z+m~Xkm`KjTFmm;|0mG#}v8ehn!;|qyj1jsY*R*hdy|vSUVL7fff8)j2+~^|7W9EX` zO-@x9E%F?qNOlg&{HcOCmmh~7HlFnhMnkZ`yiKmT$)uKR8T!sqgxY2EalMH({V3RI zYuZOsi6sBY5XA@mYOS^`6i}tS4Tk=r(?8UbXU@F0|L_tXbO`<^ag*WwfdL{>qm!~%Oh`EWR%~zGbb$N<|D6+PH+X-x4)u`O?dfAex5(VwAu_WPK+pRzPq?8 z^X~Mx9Y$Wt_c*&@yxSW54k>WmeE5}bI`=|5@YG`ef zd7QO_fzc?Q%lk|e&($a^xL^{qmhyL_?js9kaww?mhC>z4*NF*Zr&c2@6DK* zZA=hOvW|sX7(pUiQZ`eUnJ7b5{(VLrAGh&E-fi{qajTKZkghhSajDP`S02B@xDX#` zq3Xz9&A_SGixZ-#SLC{p;{ubP!$A6(#6oIAtb&Tf~Ep%wkxy_${0~4r)gM#lck0G zVf)U}=fRE1w=?HX-D_^ZeUl;6w=Gk*6+$*Fu7nfl5X`@H7tc_zbkT04ZtPL*l%Kt%i?98KQG3a zS9S$si88nzRRwTI_w4y9&v8(;#eqO@$M?oy&@=oceChd|isAX;f-7m7EY`U-wZ;s40u&J1wl-hs-^3)GSVepr!`CFU?OG<<9zr>ifsOQitG!% zfuCd8H@#jPr{%Uz0_DK1(*{xgO9s1`7{4U#nw0em<3jXuU?t z|*p37C^EcQpy|uOoS#>ex~0iufr8a>s=A;TQF2i07)AEPu2dw@=>jPe!Bh9u4AI1 zM5=Qqr;{+-1@PS%N$+L=_4c8#8n3>ba{g2@ABpSj)qD)Y^nFEu1>-L ziL*CRxP$x)!!Bm!Fxo;Te~Yn>mNre?Uo2xC{MG{|!#bOR5C7XefNrFoZHvzvH(6s* zIV_%38b|o@AvZbrAXCDt9}RtiZOkZJXi6j>yDW_qb3&9Uv!`d9VO-S}@@{doPwc6- z+XlZ}R=DD(+VL%FE!<+jhm1w7zz=L(K4hshzyTdxS2O3;$bA>_=|j%z5^Lnj+MG4$ zD@SOvJ{_OAQqB|kUYIMNIWn& zUoVYLU6-qv=`OC&luDs=`|&-gMEqmZ>o&k_}&b$Y~%g ztHNsju*zyEu+V>7Z_o4axsd?sW20}kgQ;}C^qzZ!d(~`IVz^vRjM4lxW@@8Bucz1Y zBdta?OasI#9%?vI({$+H$WMeas{vl)5vOjDRe$s83iN2k`bmCs( zL~{m-V(0l{zU{kBY_w8+B%G8wC~<-ICkK;^`3p`TZLF!Ml<-ssUei9JjVO^i8}4Sb zupC2zUzHy1uy9e-zR;29ut5=gC44kJ+UffT?~NTAZHB%1#*%vD5PCLT&~WicJ>~OI z^X6G5z}iKcbHDtTjBKZOpX*mRy@?ibofHR|-$YyZK;>0B$C8oE0WK@N2@0grgb9+_r^+BT6OPI;hl1FaXX^$J9 zv_V-#xDL-MhPt+5)TKi0ASrQe(T;p~GLLRTuhJ~rmt1JPLA$y79$g7RWo1~lM&@e1 zgLs$bV=e=p2=`kbVAexb(d4Ol&q5urXG1 zT|(Av6$wg0CZi?nl9;tLkNX4dq7uR&--^qOO(wB`y$eFXt1f8fj$}|2STOjAaW4W! zVc~C3ZPQ2ED|I`+CFH8C*3r$Fwjo(s^qaSlLZ>%-K95AUzgmD}!E*S#-z`j8I&HIeLDh0%`hkNK#6+1<<_o!W?CIH;`vi;}C43nd!5?Wkbj+&wSM1Zn zw?)qKq=)=peJ|Jm<`2HQV64LVc*Aa~H4ayBRTIg^@T8ZT(uiY$QSoy}PX@!UK23xj zz#?T>5BQX5h3-Fd!+TIFbN=c8mDLTX6pfC?+e;8yV=gYm%XdU&?%Jnkn-e|dI^8b; z{2wUMoZyMm=x7V4hw}g#6*SreLfX*>FLVqZi8mam5ua?ggkSv_Qi=nk#|}IGKLE=e Bz5Df-tb=-dzn2moMooNDw~?hoe)KtB#J^>GadbntfpAe?<1UEmMA9Nb(?TpXN({d!$g z0RUQnvA!94YjbOSYlntb5s&YRkB|4v=>OKzi7l%inOI_D7hYXIP54-rm-pV-r}~d< zQ)Bbw#AHoPjiO=VKriKa5)O$(kw_#KXne+4WJ(RI$&w`&~yvbxTfk2pcE7zr_VTb zD)svokU^J|OPqt9|7`DUWMl#W5QadM+1ce-ScD4mKV7@Vr>2Ii$5TTxKW^;p)59#w z+6f{;5@nyu@RQ3iF|mgShiun*P0j2b9bIT>rGL~m>F7K_qjl3VKcLMcKC}&lybOz} zm_k@(0s!=+zG)4l357gjWrG2FZ-{ytTO62J-Oe(8QCl?xDUBE^d+Z z$`PcdwXJ)EzOG3`R1#dt*FfKrn^O?mvjc-kL140lpT7w5N`TL_`dn^PGCxc<=4W^Q@)v4t~{L^?UxAL=KG@Z5@s zc(u5=$i;Q$aEc~wta&)(7T!u-nM1Al(bM;&b=TqVxZ z($6U@x0^ue8l?8(sifXN8yLhKq=S#G3Z( z=2(_Dtt~Bi`1whgEb*Wc!GT?KBXbZi{6ib`f@_5y8DI{QwZWXAMjUVQwSu0m{7 zl>Mdd;z^_fb5tN$GZcuB{YO|@I=$CWRA3VzUG~+PwPYMb+0{vBzKv4PT+=NDW zZ86QE(}_xfS$9Yp9F)){DNA3yRutgdU>{)Yypwy>2v@ir6YzZ96FacAlA*)K^q@^r z76?61No<%dfP1@XgXpa-4Gk}B_+x^8@_zp3nBH51SII>PSD7>2PcVwY`O?3K3bnbs!zxEWus#J!6|MuVf05Cq_^end9Qj+nW zt`}hAi5HlWmafvdI%9oQ6E$;@*z*+qAJ2DSX_XAeqe9+u$B-LW9^yO~_XbAEDT~JA zRH|8&4(HY`7RzRy5cP?m4q}0+=1MMVw);H`NnMkZvw{;=aKEcIA~Q@`Tg4s~%h5Yj z3(KUeJd*)k1kuEH{+!ox5I_b9YE~7Z3q8Mwi)LvRd1dDPlZ#~D%fHXB>0VWJG1Tkr zfWa^^${i}sfHfN%aYe#{9}vZ0Y#ZvjO{T7e-R7Tn^AM_S%#mP!*E4OPL49>vti|%M zD{OouD>4#l6?Azg@-~zQ#lsMdTK_R2t1EeV1+LhYFpfz(`^J^t#;Wk?-tU80O(V~2 zScW2*asy&-4)G!X zR25j8Fav2gWj{M~C7$^%rsp=iB5U4vGc97+Rjul z6yXKNTs1gpme z*K^Lq&ZOvm!>{BHCyfOB9X7(OG-bt`a_jQ0gL5oai|Fk$m!Wt>yOb1EVaGT1=?muX zw88d*XAs-TCF-+n9=Jr~TVP<0L_Agt`;;ia%w7*wMOw?5?JN}Y)2Kbk|v)d?iLi~fc z!p9(Jjq17+mHWbPUBl+NoFF;p)i|6N8G4B7*G6f@{S-k?ZoRNYW!!(9G~-4GjirIP z;^KKbMkw8>%(T(D%$XyC#7Pr%8-oj~ji!tz6htOAqVwh{x7GAZ#V9A+9r?)#LIrf) zUD8983RY5Qlm^F_!wigJwjYYKBFa>~6R0`wIE&RW($`m2g{pnajTF!FVh7lR z^JwTJ39ZBkldv#&h4ZgdwWn34Yz3M^TrB`v&4Ln} zW*FZV{Ml=k{YMMK8ylqs!duN6%s*eK2LC&+1V;=U>-1jhJO=aOO^voXm^E6?R^-Jc zvr_l{raSG1g--$Sys2*tG(g=&vBe}4J9!tyghS^`>`g;Bg*j*Zy8 z|E2UPk+|A_wq9EM$JdgQw%O3s#h%NI3(l_v_!53cs$w{|GFNH_%Xuz)_b$9r` zhChDtMA7X!ULe`o;CiHZPewXdo8?5EikcR|UZ&8udjqd~Vo{9K0E%&{pEoHroIF2U zCcfL;XcLGV|8U=KC1(ft@MQ)KIibmy4(Y+b5Yr*8PnBOeZc-F88blJ-h1jt3XJfcK z*prhx&49kx9Y#UR{QNWE$;*(C9s265uM@5LN^}G)fuNm=eJxwfp3`uNI!7cc3%)WE zy>FJfzSA1&fU%ufD@LXL8x|P^7fu>5zs~=o8~k=T4GM*(-eQs2rH8-&;eZ!3PRR^- zZfU2_vq*^uK3w}jj!9D@h2_g|q&{IyeMzsP^0N9-_S*)RU=#|CM&SV&nCW}T!F60& zj)bbR%;vu?^|Xrw`xAxQi^RDC8RYDeILl!bDB`GNgVqoAlQ%%_|LYLkj zDOP4lwQ@mW*|bDSGxe+%G^#YOBiOLFIpWkLvr{bSl?DAHB`Oe@>|~O;)prFmv{;It z-+E7!lHN%z6uBaZzuU?z2`B6Uv)Vc02BfmD7E|B2@$xSF2ji~@J=Pw(oBQpKr+jB( ze12cQ5HlIZts#ie!S@sK+7d*Zwl+8}<~1#4JjmSeYZ-j!Gk z25&=KGbDStu0G_Ics3>6#U)vm@QbO`5RqBqUu$D18qHDto+(dT{4h%Dn!xg44kc`B zI>^yy8_>?l`rY2tx5-qUYk}aPkk+3o-Oq>Px#6(=*R#(|ev=HB z)*S>Jc`nwFboep$?JNJ7xqN_*5R&Q<%;*esd*ST7gzb5uTrCk9%KtoWfhsL}eqC;i z$8_PFFr_|PmYKQ13$+BRwThmM)iu1uTc|whTKA^KV@L9($;Ws3r%8i0ZlBxkzDwrF z1I-{2qVwJFdgOB$+{##_;AXTt2u3H;#WtYC14L{95y}IxMSR^S+@jDbDy&{evpDiQhxPY{|19 z%=9oL6*EYkIye+<{W*Ff9+z#*fjDUmBVXN_4Sb}qlx;lAchIWvf0;Awx5bhokO5$Z Xg7(?pxrzMKb^#C2hN!Pd`>6i`gPRKu literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/doc/images/khimaira_logo_small.png b/krb5-1-6/src/windows/identity/doc/images/khimaira_logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..26c338007d5dc8534986c5dc5461d786c157a3d5 GIT binary patch literal 3970 zcmd^C=RX??*iEdEQi)YUEB2~eRE=v?B0=q<)T%wAcD1Nkt5&I%8m&^bZfUrxs7(-p zNW`ACSM7b#x9^wtpLn0&?|IJed^sP^m*<=WV?%8gFboU;09YRApiKUt^Zza*?Vqcy z>f-tb=-dzn2moMooNDw~?hoe)KtB#J^>GadbntfpAe?<1UEmMA9Nb(?TpXN({d!$g z0RUQnvA!94YjbOSYlntb5s&YRkB|4v=>OKzi7l%inOI_D7hYXIP54-rm-pV-r}~d< zQ)Bbw#AHoPjiO=VKriKa5)O$(kw_#KXne+4WJ(RI$&w`&~yvbxTfk2pcE7zr_VTb zD)svokU^J|OPqt9|7`DUWMl#W5QadM+1ce-ScD4mKV7@Vr>2Ii$5TTxKW^;p)59#w z+6f{;5@nyu@RQ3iF|mgShiun*P0j2b9bIT>rGL~m>F7K_qjl3VKcLMcKC}&lybOz} zm_k@(0s!=+zG)4l357gjWrG2FZ-{ytTO62J-Oe(8QCl?xDUBE^d+Z z$`PcdwXJ)EzOG3`R1#dt*FfKrn^O?mvjc-kL140lpT7w5N`TL_`dn^PGCxc<=4W^Q@)v4t~{L^?UxAL=KG@Z5@s zc(u5=$i;Q$aEc~wta&)(7T!u-nM1Al(bM;&b=TqVxZ z($6U@x0^ue8l?8(sifXN8yLhKq=S#G3Z( z=2(_Dtt~Bi`1whgEb*Wc!GT?KBXbZi{6ib`f@_5y8DI{QwZWXAMjUVQwSu0m{7 zl>Mdd;z^_fb5tN$GZcuB{YO|@I=$CWRA3VzUG~+PwPYMb+0{vBzKv4PT+=NDW zZ86QE(}_xfS$9Yp9F)){DNA3yRutgdU>{)Yypwy>2v@ir6YzZ96FacAlA*)K^q@^r z76?61No<%dfP1@XgXpa-4Gk}B_+x^8@_zp3nBH51SII>PSD7>2PcVwY`O?3K3bnbs!zxEWus#J!6|MuVf05Cq_^end9Qj+nW zt`}hAi5HlWmafvdI%9oQ6E$;@*z*+qAJ2DSX_XAeqe9+u$B-LW9^yO~_XbAEDT~JA zRH|8&4(HY`7RzRy5cP?m4q}0+=1MMVw);H`NnMkZvw{;=aKEcIA~Q@`Tg4s~%h5Yj z3(KUeJd*)k1kuEH{+!ox5I_b9YE~7Z3q8Mwi)LvRd1dDPlZ#~D%fHXB>0VWJG1Tkr zfWa^^${i}sfHfN%aYe#{9}vZ0Y#ZvjO{T7e-R7Tn^AM_S%#mP!*E4OPL49>vti|%M zD{OouD>4#l6?Azg@-~zQ#lsMdTK_R2t1EeV1+LhYFpfz(`^J^t#;Wk?-tU80O(V~2 zScW2*asy&-4)G!X zR25j8Fav2gWj{M~C7$^%rsp=iB5U4vGc97+Rjul z6yXKNTs1gpme z*K^Lq&ZOvm!>{BHCyfOB9X7(OG-bt`a_jQ0gL5oai|Fk$m!Wt>yOb1EVaGT1=?muX zw88d*XAs-TCF-+n9=Jr~TVP<0L_Agt`;;ia%w7*wMOw?5?JN}Y)2Kbk|v)d?iLi~fc z!p9(Jjq17+mHWbPUBl+NoFF;p)i|6N8G4B7*G6f@{S-k?ZoRNYW!!(9G~-4GjirIP z;^KKbMkw8>%(T(D%$XyC#7Pr%8-oj~ji!tz6htOAqVwh{x7GAZ#V9A+9r?)#LIrf) zUD8983RY5Qlm^F_!wigJwjYYKBFa>~6R0`wIE&RW($`m2g{pnajTF!FVh7lR z^JwTJ39ZBkldv#&h4ZgdwWn34Yz3M^TrB`v&4Ln} zW*FZV{Ml=k{YMMK8ylqs!duN6%s*eK2LC&+1V;=U>-1jhJO=aOO^voXm^E6?R^-Jc zvr_l{raSG1g--$Sys2*tG(g=&vBe}4J9!tyghS^`>`g;Bg*j*Zy8 z|E2UPk+|A_wq9EM$JdgQw%O3s#h%NI3(l_v_!53cs$w{|GFNH_%Xuz)_b$9r` zhChDtMA7X!ULe`o;CiHZPewXdo8?5EikcR|UZ&8udjqd~Vo{9K0E%&{pEoHroIF2U zCcfL;XcLGV|8U=KC1(ft@MQ)KIibmy4(Y+b5Yr*8PnBOeZc-F88blJ-h1jt3XJfcK z*prhx&49kx9Y#UR{QNWE$;*(C9s265uM@5LN^}G)fuNm=eJxwfp3`uNI!7cc3%)WE zy>FJfzSA1&fU%ufD@LXL8x|P^7fu>5zs~=o8~k=T4GM*(-eQs2rH8-&;eZ!3PRR^- zZfU2_vq*^uK3w}jj!9D@h2_g|q&{IyeMzsP^0N9-_S*)RU=#|CM&SV&nCW}T!F60& zj)bbR%;vu?^|Xrw`xAxQi^RDC8RYDeILl!bDB`GNgVqoAlQ%%_|LYLkj zDOP4lwQ@mW*|bDSGxe+%G^#YOBiOLFIpWkLvr{bSl?DAHB`Oe@>|~O;)prFmv{;It z-+E7!lHN%z6uBaZzuU?z2`B6Uv)Vc02BfmD7E|B2@$xSF2ji~@J=Pw(oBQpKr+jB( ze12cQ5HlIZts#ie!S@sK+7d*Zwl+8}<~1#4JjmSeYZ-j!Gk z25&=KGbDStu0G_Ics3>6#U)vm@QbO`5RqBqUu$D18qHDto+(dT{4h%Dn!xg44kc`B zI>^yy8_>?l`rY2tx5-qUYk}aPkk+3o-Oq>Px#6(=*R#(|ev=HB z)*S>Jc`nwFboep$?JNJ7xqN_*5R&Q<%;*esd*ST7gzb5uTrCk9%KtoWfhsL}eqC;i z$8_PFFr_|PmYKQ13$+BRwThmM)iu1uTc|whTKA^KV@L9($;Ws3r%8i0ZlBxkzDwrF z1I-{2qVwJFdgOB$+{##_;AXTt2u3H;#WtYC14L{95y}IxMSR^S+@jDbDy&{evpDiQhxPY{|19 z%=9oL6*EYkIye+<{W*Ff9+z#*fjDUmBVXN_4Sb}qlx;lAchIWvf0;Awx5bhokO5$Z Xg7(?pxrzMKb^#C2hN!Pd`>6i`gPRKu literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/doc/images/modules_plugins_krb5.png b/krb5-1-6/src/windows/identity/doc/images/modules_plugins_krb5.png new file mode 100644 index 0000000000000000000000000000000000000000..127e89e8dd10faf16b794cce9eb838040de06fab GIT binary patch literal 22193 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�gaH|V0V=9(eVw+ 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/doc/main_page.h b/krb5-1-6/src/windows/identity/doc/main_page.h new file mode 100644 index 000000000..9dd55406a --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/main_page.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \mainpage Network Identity Manager + + \image html khimaira_logo.png + + \section main_dev Documentation for Developers + + Network Identity Manager is a credentials manager, which is + capable of managing Kerberos v5, Kerberos v4, Andrew File System, + and Kerberized Certificate Authority credentials. This document + describes the API that is implemented by the Khimaira framework + upon which Network Identity Manager is based. + + See the following sections for more information : + - \subpage license + - \subpage bugs + - \subpage releases + + © 2004-2007 Massachusetts Institute of Technology + + © 2005-2007 Secure Endpoints Inc. +*/ + +/*! + \page license License agreement and credits + + Network Identity Manager is distributed under the MIT License. + + \section license_l MIT License + + Copyright © 2004,2005,2006,2007 Massachusetts Institute of Technology + + Copyright © 2005,2006,2007 Secure Endpoints Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + \section license_credits Credits + + Network Identity Manager was developed at the Massachusetts Institute of + Technology in partnership with Secure Endpoints Inc. + + Information Services and + Technology at Massachusetts + Institute of Technology + + Secure Endpoints Inc. +*/ + +/*! \page bugs Reporting bugs + + Network Identity Manager bugs can be reported to + kfw-bugs@mit.edu or + netidmgr@secure-endpoints.com + + When reporting bugs, please include as much information as + possible to help reproduce the problem. + + \image html khimaira_logo_small.png +*/ + +/*! \page releases Prior releases + + The following is a list of releases of Network Identity Manager. + Whenever there is an addition to the API or a significant change + in behavior, the API version is incremented. A plug-in that is + developed against a particular version of the API will be + compatible with any release of Network Identity Manager that + implements that version of the API. + + The Network Identity Manager version number is set as the file and + product version of nidmgr32.dll. + + The API version refers to the version of the API exposed by + nidmgr32.dll. A plug-in that was built against a + particular API version will be compatible with any version of + Network Identity Manager whose API version is the same. + + - 1.3.0.0 Kerberos for Windows 3.2 August 15, 2007\n + API version : 9 + + - 1.2.0.2 Kerberos for Windows 3.2 Beta 2 Apr 11, 2007\n + API version : 8 + + - 1.2.0.1 Apr 06, 2007\n + API version : 8 + + - 1.2.0.0 Kerberos for Windows 3.2 Beta 1 Mar 29, 2007\n + API version : 8 + + - 1.1.11.0 Mar 20, 2007\n + API version : 8 + + - 1.1.10.0 Feb 28, 2007\n + API version : 8 + + - 1.1.9.0 Jan 20, 2007\n + API version : 7 + + - 1.1.8.0 Kerberos for Windows 3.1 Final Nov 22, 2006\n + API version : 6 + + - 1.1.6.0 Kerberos for Windows 3.1 Beta 4 Nov 17, 2006\n + API version : 6 + + - 1.1.4.0 Kerberos for Windows 3.1 Beta 3 Nov 08, 2006\n + API version : 6 + + - 1.1.2.0 Oct 09, 2006\n + API version : 6 + + - 1.1.0.2 Sep 21, 2006\n + API version : 6 + + - 1.1.0.1 Jul 19, 2006\n + API version : 5 + + - 1.1.0.0 Mar 08, 2006\n + API version : 5 + + - 1.0.0.0 Kerberos for Windows 3.0 Dec 05, 2005\n + API version : 4 + + - 0.1.2.0 Second Alpha release Nov 30, 2005\n + API version : 3\n + Released along with Kerberos for Windows 3.0 beta 2. + + - 0.1.1 First Alpha release Nov 01, 2005\n + Released along with Kerberos for Windows 3.0 beta. + +*/ diff --git a/krb5-1-6/src/windows/identity/doc/netidmgr.doc b/krb5-1-6/src/windows/identity/doc/netidmgr.doc new file mode 100755 index 0000000000000000000000000000000000000000..6e2c9a37f493ae9e064af3b0d4b9cabdbc7d0a7d GIT binary patch literal 2042368 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 rb^0+TmupyoMi{7g58ed1D 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 z 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 z%0A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

LL%>qPBljUrEBb}B^pSy|Qu{2UxPZ{;J^??Yvz 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

*8RIpH`+>bRh9Tuo4V@| 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ÉYv0wVG8*k@C&DS-2mMp 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 z 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 z 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%0D_ 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
    GpVgM4U=^jQ?#%02k2<8o5f6p{+N`6HUPG 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%0DjvER! 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 RX2C5W*S|S17v_Nr{tq`?DL4QC literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/doc/netidmgr.pdf b/krb5-1-6/src/windows/identity/doc/netidmgr.pdf new file mode 100755 index 0000000000000000000000000000000000000000..a5b22a965e97b1634cc19930a8bfc80eae7a948d GIT binary patch literal 1565851 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%0A_#@mV4Z~5gUcuikWO^T?(Eq6!2%{D%Kw| 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%0AZ5vkf@OnQ zXwieO8bYDWhnI873CsXe%e?)~UgF%H`GN5-8=I&eW=s(*HX1PtW>=;WV8s2WI1&Jq zabVN<O*JWhZA9@`aPsD<k>Bp1oHVZ#0>`t3`ohV~YtF}Zq&exd_jE~|Tn><P{w>^e zU&e=&!B`Y6OiHHY<NsT3Ng85gGvthSEPsmlS4kfX#A!6;LaR$1Ys#sIY*gW_zoi+7 z!4}{1C8O}5hIBo>a?4;ah$K#bH}chS<<K^?CbY6(kb5=D9m3Q%wV=6sWL>B8%CXSd zPMC|yZ-IZ^`yIb{<qGNf^*8k&NT@bW4Iq*zeQL=3SVb6=dU@8hf2Ug1oo<t--o6+K z?(Dq>`H8ItCh-HfR!>4qHD{KM-V4}n^WwKigX_!*!u!rT)*|~Z;~nQKQf5G&ZqU<r zE`nesQ3VNrR-RIuCVs7==lun~*veb=D+cA`GBVM=pXFO)hoHPK+1~h}`|i~kZQ;y7 ztX>mml!=-leqsI$UXC41TxYL0$j=xbk-m`DrOlp<)_MQ4O(2LQ9;zz+O7|~n<OoZq zgX0Xnw-czlB4^Uyx-Y{FY>@lX6FqVL>%X_%juSF)io%&lFyCj0Ph6*ZPVK3+eY%)k zBjA-AI=tSu&}dDdnb4EG^7q?b+`TCA3a^AayYjb0D)!7!XhnaarOEbDy_A{kJaklN zT?_|mwic>Rd>@NMTx!1Z!+gb3bnb}0WCujs;00-NOKBB*ul4uKw@-XCvPJ?%^f7+* zV(6}Y0#9FY9)c#N3T*tTqP$Y~p6+{Zyiypm#w<~%-z91fSWhXJkLU-=^*M0=;HgqO zt_Q%w3F*c3&S$~=*!ikSNM@)<yzPZE%E?JzsTHFG&jWi$VT6YTEnOytg%!Xeh7+_J z&aY=l&=fK;O_n5G`9DDxfgqPbwTwR!9ocV#?<#cYky~b3n_!gSS5UFmiqbfc8;V>x ztXBw(i`+Bp0CC@FG&rg<$vJ^g6CK6sYP?lowl;vvE}(HFXzP+4JsCf(hqk(V-zk^E z^?A0nrOleTmjJc3xb4mQ(C%Vxzv&9dcs5~h;UuwGf=bSnO1`1)0vglM=!M&31W3(P z%QcL0(az&&6)RKAImbRzXd6-exOx-CmMLpy?LmYq&8CvhU2h=wVNTYoN7NOXj!b6{ ze&pD^fPJe;RO&L)cbo+xiPg8m7*5VXs$>}Nj)b4J&jO;e>|Uj`Ig*J4=fC61hhM1S z-HsYU7F=fJx|7x4=^8O47BM*{H#!){EMrL}O{$gh>hXW!B}T!+B4X22IcmdI&^K4+ z+h0uobV%&DGJN~K`x28fZhoiAfk$S=Mp!&b2s3QWWSw|QP1YFtILuURKpPC4QY-z? zwt6I_MrDB7uu|Y(xA#e5#Dr)yf0nUOQaN;y+FX0dG+TPxo|VeAfD`rb2GLW!jj^*M zm7X8E{w8AEZK8CsmjEej7)I;5Pl!^^EcSR{7MZiZX`KBFT<Qn_^strHaJ{6+mUiU- zqCw8-Lvlp|TZMzzZ<s;@4A=SJ!T*9uHuvOAY97@=G}g|=Pp!zLg%|m-(}y9kKJIaO z0&C=$7QS8NXal2{R5Ijckh3*s)~m%$@tW&1VXMY0oDIqNPWI%Xb=s_ySpqh%-=fqZ z&^%3)12~G>I6;@!-$qh9HfOJ76qPV-i9pJ>RXe832-B#k=R0NLEYG!Bdtjm$(Geu~ zY8wgJ!3BKz(@z2+09dL*Z=rpi%^4gR)xv#!tSU$IjbsJO?P6Ni(_$7=q8pPD0By?3 z{Ngt=-kB+@N=aD)n`tUiAVvZ@YP3Lx8nlw`;10gL@{@)(7J(Th0f9^65f=#LvBnL= zaB_hs+RH)&S$62@wSS(?kYN2sa?6!JUsxvEnD7Ft^|IYJcc+pOp@qAg3AbD(?^FCd z8o!>*#K%TBLCa#UFk5)&^|ePJP8f(_7GtnqxM$vk1p`}b*l&p&(m0;L!h#ZSG|S7x zOyDpKQLR$aB<|I}8he#G<I}3cTPH#X_Fl+=zi2x)sdcrxqK*PifV)U2*b)pYc5{c= zR*<iY8<S~df}7B@%neRkg*3ShKsK>@n;HFjNk~ASUk9be2_OV?2Ysg1-lF}uta=;Q zLNU2)9k{#y5Q+vh5=z_AgK{b1E_f`N{q(oN;feaN5XkaD?|M;xuyg#nNsM%pKrSVf z#Cyv0S;QX2kf%a4s{D67*x;FO-&5bKoQmh{BlFk1v}qE!dkk&U-|3OsUedELtl~rD zxjgQp$*Xb{NEvS2y-Ise?hxYqr+~&!^wZd9v-RS*3;YP3>TpkAf+dk5I!~~s1>t1( zs8=xAx=Z?4R`%@wO^sCw{?@g?`Y+gRb$6bKwJe6KZCL{c^$Ix(bySGP4CG!`rO+=9 z9`qd-SuM@wu5>s_a9#tBG}4yXUrux77MbXAa$B5fg%n<uy}EBhRKUJbLEyyxmp8C< zCwVl(y!pfvCJuw`Ckrnp9t=O8m8Q4LxX3oo4pE_etjn!FmMs{m^z%6v=N%e<rNA^M zcJk;UMYk#f^0Q^FP~SIgIpU7pUs0w#XO$DOW(Y*_@Ww#Whbr}R!S7ur@8iuiI9KRB zdf=Uh5Mci?#@8VJq@+TrJ7x#q=w+_t=Gpfp*iFwPqte0K30Qs!i6vNmqwc8@$b)FM z1R17UkpKFj<ggU#Jk@}@e{ONRDcEM*tqu^U(ghqIyCouegeMgy()-f+laaNZ0A<KU zI6_lOpp)TEV|gU7^vjFdx!kPVzzDUt*>_k<)istuSivq{^lgv5^$AdCE9SDA@_up0 zDQpZ=47OIQ2HhcU!Tzv_`5=-!1r%gt2Q6Y^lIs^AftGu~KhYZ{Nv5#|RMQ#06zYe% z{Pu{Chu)HM&=Q<kI^2JVLHqa#bOnt(yu`EE9}A^yYnYdY+8`UUbR+u@`B(pV8sZN9 zs1o(ScAcAWV+xZg<+*(-0aYON5-qvL-;T3Erhl@;%bN_U1x>}M!(^m>L-S3t;{qs^ zSPjSJj^8-%ug-^zzVv-mlzg*DUE_Ti%)~MTAzlN}y$!692urjPI@MldPq{QO1`}DU zZ&Y?sbd62$u}_y68LkB;>A%%l&~B<s_KZWU+7<zDJ6c?iY7%pf*`GKRCgVCsmNc}> zqVtq>`sO9}dVm?`RNbt@@CRL_vPZXjQRvIj_^&c~UqJ}Fi;YIbvyL?(YKxVe6yJ7M zjf$e}M*759d$o=x4Zoy#?R<-C=B+g~+x1Q_U1;J9EmJMGG0Y@~m*=LwIK&|OCR|o= z=RbMgpH<ly<drh12wE(A4}HI@R<)ZKV!eez8Ybk8aJO$uPMG?oN5tV*eB1#`4NQc( zO>j6_Jew&sFs{@?uxoNg**h|8tX{9JVBD}C0isifqkVw=`4ZAT(XimbTLkZ}DHvK* zW}Ytt)K}M!_Z6IYyTAQ_0`xU3{_<UgHv+NWbVs^DfVDJBElm43SCz<E=$hv=B(&!( z3W(Vkgl@P-r%tZDXf<wID*MpRJN~te7koL8CD#xg<*5!#X6#GmnR5=HuX2h+1u=p) z4g{cg7vJZZuH=cUThl{}*$<D%5ODt0KY&daQBF0E@m66FD}s*UNJp?{^6;7`*1<Jd zgIFvS3ART2`#AiiNe%8-{^D_<`a*6vG|~4R-Kf?Ilf%Jd!YTuT82L{8hc&O5SsiaM zkzLQWm}QhkpA_fCN2A)|L6%(q+RsI%5SbhwL3P;%b9Lf=5R}nfM0Y~<o@CRKvqpi; zWAHl;*G|i<7D*kR)bl8nFOrfjHArjmaO`DX3TU+Atx8nMO>KZ*Kr#l+q9<u6o8rr$ z$8{0x6MSo>fK8QXz(I0_#ONgUK>L+nMlLT)p_K=4DOnCMd|JGm^ai75VHnRiRld2T zs4f#A)Q6@V;L*iy$7=LV*undU^$3iNN9e9VM<qHe2{NeD*SI*&4=!7xAX$>Rf9^{o zmR7#GY9vJ&xbkAMZaXG~=SYQ!<n~LE&*JwO9}#sRUeXW@{|_VXYyIY>-C!^M*}_ro zrChp8BmAX-#nIQbKz=-}!JB(LVl}B;LZ-lmgTH<kUcV)4W(1m=p_R0!(Pnq&x4Opr zJk(@x#ppx@sq)e^ZZtBJ)vrMy{Kp4{AjwB%t<IcX1J}&L9GNt&IN-KHpv;AI4G%&} z+6$_n^5<t~G2uqNqj5wcDIVl(X?=kcs=x78q%VjcWnQhjY#^!ii*xfAP!4vS0SSFy zqWu5ubQ(E1SHVnREb%B)jR6e5i^Gq%`+vtfFKsY-#Xi@SpD_a#3-L@1p&Vf#F(wue zXV7x>ABIG5&I(*}d&jNq`>dnuRKT&tz3zkIKZWPV+Y0kJtT9s$GH_Wz{HtlQ-)4mR z-ghjzXh`Y8x^3JoksxB*cdKRoK=pmYBcJWP*WWbpK#ccL4D1QKCMu4`UWt+>M!Xg{ zaCx+vH;4@}cxcyJE??Lyqu%Y=3~U(UfNR_11P=G#o+kEl;166&?M`desC@ClpV&q7 zb;Y>iDb*NyzvNC)>r7@)a|)l$crGD^OA|<)cKhE<Jb>yOzdM@8ijKiJOWGnFlI|_U z4SLy^x5Pcm()MbDoqM9AB5L75dsk%tLE?pZ^}tAj+=`hV_HJRJiW(Dyf3oueyK>Z6 zCn(1oCT>@u5jsG2=!`EDK)<xz$X^^ICm>v}$$cfI3)hmV6y1SgnYmm@8K*nEE8J?} z5397oTbS~kS~>c!R_E#!_Hj3^aeDie+S=N+Hgd&E_dl%dT*;peUrvDD#N_B*o#CPw z+i}q(`A01-$TXRyU;>6I-a&E0JbgatLEJj_<c*<=^j9)ye+~T6{;G390MbHUiNX>| zk?Uj~qGJ%}%^It=bmc?hQoM4&11H*<Vg94`gJ0^&p9ZIWMJ)|oQL(Ts@DbZg0A{#^ zB%<3bUHagW^%r!h2>hV*>B!?_)4omnm?0ps`Sdh)u|E21RH@WRd|;gg1NcLEY{dtL zll^C-p==s1W7gY)v5Iz0EsNaKx)BfMZecI3si!X2DG@Q9?(NS}QL#4HISPnKZuxku z)t}xsNbx}f3)P&xvx15b@ZeLsbu|6SfEp%@X|#MOb@ioEaTXL4EP;r(>ver}KNFaU zfdg%E(UH{TZ6~G_Zq7hb8*~rGjdd&YPYO%hDz@}T;fAfP@@>?2u=xZOD8I+}Tvpl* z)xhQcomUt7-!<CXrbe)cN_bnX2YcJetE}9GVfYkO`mLrJg<T`Bz&qEdh}r5wuGte& zdS)M~#1<L5vvTut4QJGAJj$A!0_g^~n2Zfvc`8*r6UD@2?kVtY%_m0*9XiyH4@9XY z&Aro5>_C7y>jebyL-k<dxDHe0F8QW+BNTxR6yV51t&&Z)49yj_bGXm<s}h$UZ%G39 zSghVNrHzSbN?{Va!ehyzwrCKrWoMmDYz4=S_A-8#J?*~>Rorn>&F)v7g0g~!z>r53 zaN}3RrEm(AjALANU^o0bjaun&m<OR-)!t&YnZb`g^U81)XQVLB?9Zh;c>7eR4*IH? zgumJ=>t@xfqXZV1=P#Al%T0b$GpSEZ`LWY>jT-(_l3vZ`gWhSm<WtmqPQ)G}tNXvB z%2p1#9vh4zC*T``A<rnJ+|II<#Vbb^x>MJBE~9Wtea$~bKh>uGd>eNm^At@B{iqYM zUZ-j`YqDoy`pl?+k)e1lUm7ss8Qpdw1xRQ2erz#%^j%g}<SU}m{lLP1XP2D?tzBn3 z#91SaF%x@-bhvQUvUau$m3#bgm=m(6wdhvDiK6D;b#D&L-kGDXDjlVK|0nb_ujT?A zY152#V8szSKC^QLYfZbJfVO(K`~7bEH`DEM82-qA=Y_xTvaI<l$!v26Y+fQ5k7|gr zxUX`1lXzJbnn>Tu0EP)68s^+CbT`@+Eh$^oZAHW;*6hLa?ViO2D2EI`i=0~lN<04; zPX_B_h|cI+H&ke1q5r`oq8#_6uV=httgc5HPt0+&Dz&N)rebgN_n=>q5j5pN%MK_$ zOgA?EK7Oc%=-Z+-%RhmZrq*Tax=&A!<B!XhD`IR{<~H-TadELdVYb}O70QB`A#fuL z65Rc(Vsa`WQjKG;-0`|M;!VcvPCgLo@5QH?ZS2Xfh`^;(zXz1srZIXcgoVj*)G#}! z6I>24+6yl&<3n$Q680y13^D;_T%8A>CB#xn$6q5u#)qL75Hs9Oj{!*-C<w%%sw|>A z3!$~?Yg|YQ*p_n}9S3rKMIR4Gs%zf=AJ1ETN?6gyl6kAMFNmf0vG+|$xk%61x!D42 z93-|8_<zZP(b>^!$X(#VXol07P=G($4X07kwB8l1eEDaROV|4O8Ib^6k7QaT5~K?j zTJWr=-hKGSXV`JvHn7=pe}SMM3Itfd%mNlUQh}P`91$w55fW^0;-Y=&?1Z0m_y{Nz z$Lo^~*&{sY)YJkavqVj@R%i=w*fILpVm5608zAEjT7~0(@p2P<5b1E3c+?3fIK5Gd zd4?SfftG9aw2KtKNo<Fe42;j>_gJOKJv-+VSylog+@lwK)`-3|Ua6ks>NhJ)?uATr zYvc6_sV8Y#4^|+5JQLIoNcpB$fvCw@1Nm%K7LYaCqEYs!x)J$>(F7!W;3Aab_=Afx z9f35kp6qfigJu<8r~lO<0B1hG+GVgJI4U@+T$Oq(F6wh1t3@dw4j+UoeDtAdqcd+x z4WKk*I?6q%MzaW(aQpZ%_P~Z-(YmKe_6ZI_qVdN;if>d34FAasa%D_z2U6y_Z!%O# zbZGp>`RQFjs`Mv~=2i*wOyL;qVh5!MAP6QJ5zu%Jq%ZRwe`I;}ZEXA}EsWCWDXS_K zHIE;qpU2~4RCba5Z|4K#9k-Y*<~g^9;*kAwGBw<b;vU)+#=&*AfJ9J}IQZN2`Zcps zSmb!iynzdKU}4903h?j9Vr3kv!Tatzwvb?TtJ3dd=gAXo+mAkJSWtf!CRk=njZZC9 z(M&Mz`V{5I5Re=E-Y74<p#n(Pk3z4Q@XR!QNieD$POdM|_pMhWveNL*@zU_kn+Q@f zO8;m9@hXa-lr-Ia8cj>-+l?Z?fZRYi<nt0@b_L4$-f`79k_^{NxPV$ok!_H`hZ4l` zwGX23CGn$S0pC3%-1SEDayfVFk?_5WDo7y7{MZW$$~0VEiGfMf@X1K?uo)Br!m1*h znTYM$t{vpu1K8>T_rvp5!puh^=0?~`zu|HsU)dA1?Uhhvr=am?{vB~8Vl(=MvpyjH zlQ?MKWam??)|*&YF|Cil(%^K172Rjm8d(0=v6Ez=Os{_?TTCVX$TcAQL|Yy5n~^Fz zr!7UF63qw=@-<eH$fN0}J^`M=6+ZJ{H>c#x=?_}|cBn=k&Vy78rgez5apl*=o%WOx z;dSmRs{4?kqNj#;UNElUL<ZR-hmpJy2bYI_($Teo!FY7k_{4M}*yd0n`Yu)46bAIc z4v%)UP+dX={@r|=gbSVX`!vM)^L3fF3uOW5h>gQwq;Q&f;;6-CdTfjENq6R>fOdw{ z<sVOXyq@|>I-@JUE4<c}6+SP$qw*`;5(cZnon_3I?qHX8><yACU0zz&kd~%4#ES%| zTyCgghuOL_$T)ZKLX!Ck$KEzh4v4qXYvXDFlopyjIS$)g)<2h{kNzD!Bem^tAv|75 z@xe#82r4G>mZ5d&FeG%?>_NVp+=<zy-;3I^`m|ux$-kkkU)vH)2}1qaiPe@}5Z|jw z;Z#%*n6!eMw&)ENd7^<K-MXIsf{4lo=8hQ6FeGO<N$<q}9~uGeW!*dHI{dpJ`ERyW z4j7d6E@1asCi}}0Y5v)w!GDk{@mP?wmHx5#qFkQ5Bh;z89YZD)5Z7oa@YjFeg)_w( z(!n|!=p(sHDo}>ibZ~wi3aPAs10DQ9o5*EzSP=YIj+&I&<bZ}G-Aokz>~n-hcHtLZ zow4r97Iv^M<LI>qujWl)e^}=rK~XLFx9qJg0mjt#`zsn+{&~Va{!+@{WVu^PU&kH% zqN=8x_`NTO`dYHn@1Jl8RWO^CQ_9CAng19=eg5|r@FV}2R!if1uuXy!y^L;tBW>-Q zmcyLM?Y`f-nP&dK2BmnzDpRJk4d2QvEo|mG^0%*z1-@(M3qTbFpAj5d6YiYBlJ37y zB(!riO2a-W9BUd@{+}25Yq8&s?{%~3-eVM@RZf1x^JU~8JkIcX)&8YjS^q~W!+Z7X zoJ!AqDa`|`1g0Y;i*pvq{$sHq2~!>aohdq{d1-!IYnJi4@d0K$fOgl)y2t1tQ*AzC z_SKmMD)#BR(T~UAg6}dL35CqnvJ+TNM3AGuBq@_+vJOXIR%J3oj2X65=a8`JXw6Uh zd@@I9*I1qfD4<+ccJ*tv8ed0Ds@ru?$_*orQp4&gFWP2IS^UX&c37QHE}I;3bSWKz zmSOgKlYUa$sGw(dX3~TwaK5#R3Sy3a?1@b?tJoWsIo4CT`!{SuqX9qmYYL}6nn}-f zb_?@eTcvHfls$N+SPI+e79!&h&A7@t{(x#aibJ}l)K{Vj{K6Mh#CRUJ*zC7+8IQL3 z=WU=IQ8q85ZdDQx$|-|Iurw+^O{Z+F77l2>MYXVpj7<6-m9d;tuBY1MQwv+)zZRWD zL8A9I&Kt}7(st7Ib*X+$ziL$o!oJQ=F>*Ne7{N=^`uvJF6ibh?6`1_((MK8#3|~bd zWs2jN?zYhPprC=f(6w=$lf0b!^b{`RBoUKJ1I_4i!BZ2~YXuK(;TJH@<;S(NxnN)K z#gMbF0=__FaG{`8QJKdAc3g0rHr2sGk<*rFqpSM;s<UCr*i;$P$ZvQ>8k$bXdqHq{ z`zN)O=Xxi`b%!{{GFntCgc=I^Oh9%8Uep(v#FXkzz3L+8b~)x!@06C(9@CpMi^Z?R zlEu-BD<0NN|IVdgpL1kV95U5T5#pQHVArP#Bs#y^eHE?ShZ>zY3;*v|5re+9v}830 zn+NHWdf@WT_o^vDaolF=n@%i<N)@N$EzS8*3d3Qn)1|rf9)@rbzR-~+-74a=Wsu95 zsWdo>VBD-9yvBq8hL`+y93sgA%pUlUBzZRek$P0glhscy|8<EVfmWyY>+WzXbw-{* z>rUHh*qY-|UjOVrpXw8<;Zm?e^&7|C4vwprhT*S#4T5tjLI?drbJ5t!+f9n)-?3Q6 zNMO!M`(ZBW_7&q{+cdwJY=|ki*G0mfGF&;G$HiVr7jb?qB`*-~#_SE|+sxlDF{v#B zp7c!=l~i)eM%`q@GnG`%rxT`-P6kDQ%<3#K&JxND-pPw^#!!=fC=qIg4HvE$Pb7_l z!p;HgKL<<NG(-=I4cAIy@4k)+P&dZyi+6WoL$jNSe|R`M27mJ|pgl+`rqJ3!s*QR; z@a0*3o7n$yAGUIexV|&?yQy1AW?-K$&lgfW^3ne%bDB-3{}O76B&0K~;A7t0zqlWZ z1bJ`Q{9ooGE2TNq_@PkFl6`a?MHk9k-`j=!JqGQ40e51*tW7=A-4GBj6BWjb8is#1 z^XxyzN^d5D0}d&_!;SUW<B0vv^-=x>P!awmMDV0p+P3eO`T|F94G|Tu@jF=rUNl$y zPxFSsy2*s=+19vg0ipjz+*=35)irygXs{p&5ZoPt+u-iO-QAtRA!u+7!5Q2gf(0kI zyE{P!2@u@j4td`9yytv%>bq6<pG#50u=ieTx2^tlubJJA>TZAdl^e1-S-JG@urf^P z?JrsqQl_1RZI*&#7IchQO{Zx%rvlE!e}QN_qr(azUvrIJ4-xAyzVTNwV&4CzIqfbH z722+hQ_~<s?L!4&pEE1;gTvfMIB7_7`Cs>-3D81r>hdMnd|RqZ21QU*AreSn`dtpP zhfuloUvx}GH})l{K=h}|{7m5}4ke{im-(-l)eRung%6ZiLOhAwn%CNYFd$8W>={j` zpZr@wR(%%Rp{Y?zd9MD1^NxguL;p=PZ+Zf@n^U8%^=g7_8%dq)^rn@Ua?zj8C106b z`M0hAVZ!}3Lq~IL>bu)4?OsEKR#Nb)A&$)wFvLE!yK<$G%b$(5_L`YyB*@ZXX3!Gm z;hkP*SpD}5Q0ZibK^aH)y(=aT62kK9;jf_gkB-Fqzx9vGc+^Ixm1T(494Y1IQpUhT z#*#R3K++L1HhFs|R^M~e!w<>qD}zANUSI*56omhofAK#fSJs6NHR{>^fhMkG65}O_ zDhV=o(SPY5-DBm<p9O&hp`3da7l`2x^@sl-`)c{ezO=i@L|f#exa{muxO;q86A>z% ztR=+L8UGc<(}s5M-4R0;M@sxyu9@2=N`nabf7uTUAtWG1cI0OR&s+mmT%2tUTmY}4 zNBbMSLA-uT{VuVJIy>TNrztk6L%df`(tqshaq8pdpL5htKj55=f-t3sr=;*U{))Bc zUyCAjIRIYpt%K8(11@BaUNy9n1SBuj|F8}TI4TxcL}GSBv~;DLDMs;~mlR25O#hpC zLlD<kom~%vy2Z-)3ucu9D9rFbY-dJ~-XRMd#JF+-Atc3Ra6jR%@IqgO2aNgzENu}% zOhMqN<1<1DrsYD->@Iu{$%Z`tl??$>B9DBm)Zv{IW5ku~2MOK&`^v<?tL7*o7wh7l zxJspp+&K$46-jtCOZ<PCCB74X7=cAWZG9R&sCicV?>QZ)SGjdz;4wWO6&%sAh<}O< zkXH?-(wT~EoLe4rn#TPmVT{4%hVt>f9EXBNltz7?eKQwZ8{^4jH)<WAYD}(NVH2U3 zph1E`XR1-pmOsqYgBO%Sjmb455zOJt_&QIYPLCWtK~&mtY>cjv^yYa)-U+L|etjOc z{Yb;q`<lMeKj_ECpF-*x(LcB%8LPdX@M(bT05PG}^e>>7PKO0E0De_8Sm_oXyArQw zX0>s%J6rzZdd%!#cengCzjIsZGlS_-++R%X*fY>NvpqHwyWYmjbA7y6X`9a-=D2~I zMfl|Y>-wrzS95E-cmJy2YUWHqK6bs6&+X;pa&^_N!7+8c(8Z{55AY*4m^2a>3nXw@ zqd(Os>*KgLKANdJ@v>DZ<$s=c^<*iYP9ImX@~qg&@8sz1dj0dsW`hL<Ks;4%^={xc zwBD7?Qgv9m{&;#lySdK(W<|(*OEEjEl}W-G)nOz0Q@5_4@y*MRD*a=EuU?IS?=<}M z)+es1ExW7|`t|lR<EwaKi+hVpwro@c8?l+~$fw>pucVo906z~aKH%yt8NJJ=TlrwW zQm=~HM7I9sW?#nEJGklXDSrNn>;}tQ0Fy=7EwdiUu{W_gF9K03#d4$dsk|ccW<9b~ z7g^co9?$7i24AR2mYiR`@3si$xS|^Mm(xm}p+OqZXy6D2-ySElu<K4E_^>0+UuqbE z<T**143IgBPor5kJ=e0ln!Wyn5uh6wMlvuPDEzJ|X?HS_SYLmS2#bcv1sUy$Ry=cH zB#iAz^oY`72}Htp#D>tyuFARzaB$pmIo^De)jl6<8uE;aP(9a)n5`$s!c5bsO>m>n zZezmZ;G>)%37G3JPM6!wm(c0x%P<+-{tjE^^ud0leg<jN_4j(78Ls7$Q|9=+X6nKM z*r#bemTY@LFRzu8@-0BmLT`(pe<%ZkKaepI<N4xvoUm%sZn+HuGWvjNE_mrAZ)ZC2 z>Ihx$Qye7FvFx<m&XPMD^6`7;VgH2N;RaN6>AyF$E0#0&HsFIEaK#^tsPz5X;kG}d zSLSH@AXO);`*fl1AuSNHMJeD))b_h?flFuU9o<Ric;?6Q0=Y7XDd^pXePNt%CS0gB zMzvJM=<}kip?Q@bwIrU?$)}a51Qefzsx=?txUj5-3d@ZNchQN)PBX>e&I6uP$GY37 z1MFc0-({d!bFfyZN3}dtQj?$G%^Uu@<jQFQOZk*j9)^Rb{c3GDni1MFrX;ZXL+BYH z8ZH!V9n$=d?s#5fb8r--Q&a0u<Lz-RLR12~53#?=1kO_MCGN8Y1+wkY*K?jZ1X>aS zR6{}^ryabbgBvyX5t1nf0o`Grs{IJ&ta{#s*|i}yS)DM|V}gF@u=8o+KD9vm31=Dh z)5HkK+*nQ>L}}WIAit~H0Rw>~0qM9pfsk)WhH3^jW_y*z71^CnKPM`|>(lyWzUF}D z*vh8tI{FjsCDW(P-I=6?3NHxh)@a4c+z?-i{rKb4ER38J+#6QwFTKc$kR?#$2G9(p z`9L*bs9m?0wC(BZT6fi3wY})&yMXz@T{N!Y4s~}Z%@k16NT_jLV5u{ot`9yhnmE?^ z*6z9SL1)8P&6dGqvJ?D+#*~*h<ec}3HTkr2J#$Ag<*kNC8$c#S?XP`>=>8!JFR~)Z zs*@yI#YbVWrd&?8p5X=c<;l0T<dmNEe|WC3xJZ8MN+~boh3+`+&u|<e@}`C=5Wc}J zeKRDZ6dv&86MGu3OwJd{Fa9T{^i+e@<|*?d-zGrqToYo3C@)=!6MXrp)G#v+xVOf* zuDrlJ`;6<8Svc77J~>PV{b!%3E01bI-8T$Ed@aaX{f|`oDiC#Qcl~5&b=VZU==wn1 z6`6%k7zvSiqMX}S`4l!2LRNj&<IH;lerrV%t+O~2<M)nH`7~;Gp$Amh$*e$oGU`~X zElJ%!OuAV1<@Gm3+lb&1b_(*b<obUJ92UP~&1zw-kK?QDg-vWENMeQQc=Ym?;;4~? z?`c7mhB<;mcl~7t({mw!1tKS3T~OmD*oX>8Nh3XyjaSQT-{+NypKGQ5k4>;~LRTv{ zf_HjFX2H8Nsx%}kkLQXn+iv8XuLKdI^(tq@#D^9zzTp<ytSNi-M3$DPE7$Er{=VR; z>^8)+Mrl=elZ@<R-W@NXF|Ni#sId*K@|1u<gRyb$h<Vr#-|b$A(=Y17GQquUd3r;# zg--Nkb>@guo<O3#ero89>}3Yme$U#;1E(!#nLGL$H>*s{Sz?SFSA94JLN3-rmX!p< zGM8-(&NG?yh-9t{NmwL^56faA;xCBJJ58q^rdcx(d-TSa5Z^L!)tvl;Zu1<Qi)MYf zF)S6=(1E%+nJ9+;KvjQ=+8}697zF-dUHm$8vTckMpm$m{@q#dnUD`>QHR&(f?dsG8 z^yvN()TR=IH_^x4RKP2W6MqFqU0V?2IJFr0Y`~N!ofIw2D>UxvT*%Q6Y+)1jDH~z@ zK}87!^uDjOl31~*v}RHd15S~OW4V=d<C)TjiN6w&(Ev#s5Us9P3DbJcMd{hZbz0=l zlK#ae*vaU)A9NXz?BeV+mzIwWdOfaTD-R9XZJjQdv#$QVa??~D%lyVk9P)FBm^0SF zz0u}!a2W&*9!{zz6Mp~h-8(#5j1|)5RY0dvS0Hm_czF1z=7%=`a>$P)Bm#zv`_Ie& zcxxFl(zM{H*X(&Wz0uKed*w11QfK%vvp~ZLkkWbgrXN248yV#3;>`*|XdI$u?}Kdr zoBn(uzp49Y_OW=WdHa_z|26;Z6^4Z>gKuQTF3+n=-)IE+&hBda2U9FNFuJt$VT7Vs zt~#1d3hOYHzrjh?UwJsv`=59X{tIE(aW$s6DZa6guf^lplP=<ubaL|fG~uyva-vZL zIU{XWFm(lz+`l|!%<u;~ueI@%5uDf7E#UW?@w;D_ISi6wtZ*RNYZ-~NFhPUVDQm97 z0v_|L?f)zqsNzTO=2sKpE-Wq<I1I|;JM!AB#fun0PqWk;2fj{Rg^1908GMl$3OybM zw#Qw#y(L<U&p-wY|HCkC*WE=55V8T*3Caw1maj*5qK1P6>Kgo;Z4Z57PMXy#wxL~G z>jD=}q?;8LD;@s=*wqqE+Rf<CemjF;Qy2jG&~KlI7vg|cUWbVay_KdZ+2zpBO*I$G zKT!$L47M?2j{~0V2fX`_yS3JNpNvR1Kd!>9d94}%jQ1Mr6fJV|4L)??@c?(YAHeXW zkm>H0Zu*BFHmitQEtNuV9O}6U31fw_Jc(H>Pb<e+6c~PgfwkTCN4*)vHxI1s3V#DL z-aTM`j4LaMW`9J&EIUn87p}~Vuu1AoNW|;1IhqO;I|u^}hBVy?Y86a9PXC6fTN&fS zWbVyGq}BP{)pzMAVykBKv6`fl8^h^?>sf}+Jj2Q3FI(%6Qabp1S%$s(x<U%sGDQd^ zqGt>^INXQkP@r0Ngjf(>Gyf&QZN|^+jo%w_Y_8f1umQoj@BDg?d^zj=1>>m#W<GW; zadW_)cv~)WQR7@!>9^kaRsr|5ZC4Cy{Cjk4drnXqWq@9RwZBQy@elzhggDW8zrNfw zX-}X|S<ly<(g@trz5=cHbn(~E8j&<yr^?I%n^0C5N_v9$)n!nhRQ3bLpQM->d~VHd z0he=j*TPW6Nda}>Z91og6;t%+p)`Rwp;~a19#~3IS2s?$v*Ed^bHfI^ff~O5J9zsb zFu>GGPsTreE)es3@tN~h)Y1jr4o_a|xvymVPQZ*IAr+adL$i2h3WN9N_S8t72br)e z<l%P^7tHtx`ny-GWu+l`T)qD}Qp_$;Z20+it)}AH#@95}&ga0ZSp-SOYsh^bdiY?W z2S$H*T3K8Ar5<M00}C#FKX4xwz9H07JQIz8*HpiNB@9i+b%%4(K>>6=Tu}ZvO4>pS zc7dSke7a`r07;xfV+CjHxIWMGaQcsn)hf<e(^*=S=-nItEJBFfNKzVhozBnx>@kKt z1j|Zh9>|17Z?8Q{dK3AQro~}uemB(KFG<05`Yw}drk(^3;uZL@DSIvi1F(k&8Fum+ z6FMa{<28A@>=vm9iON9%I{iF+BcO^|m~1bUgEDVt(#Le?OQ6HhzAI8()P^fFU^+!+ z$je+#$9d5@;Hh3+cBYyILTG;rc)1$~{5XOj=okj>NR>zb8yE%C{*2grKH5hHM=wps zpyDM9XwV1P@#=MAc#rl!b5`td{paQQ0W+y*MfnDI0j4ba9|P*Vp}{F|0K+Ui$U`l! ztG;R|q7)hO%`eXx<)ctvu^(zM00wv`Cc*Cxe4i%vkfLq9533vo2NYheW{2eD6K;g= z#JSDhfJ#fxLUU20rJ*d{hW_j__`gg)pH})<uc2fM+%ezaQ?TUGygYS1J=C?32|dp` zZanN<^yiEf7b^%h-kC$(NC*E#-vZ8fY}|&;`{k~1BgpqO%B8Ce3Gmw8w(o@6uJ+>$ zzXY`5!3bRnJ<T0$enYnen+=wNggmZyA|^;Ft)llQC7~?)hQ|o<w@tsX&)g96d*1#r zwsdf??gO?Le(Q}~J6LQycHR43J0*kX!YA<`_x<<X|M21ecJBoO0l?dsxH~O~yYKx0 z)olj-dd93&B0v-JhiCT%9v8}X3|a1fEqBWOpK_=F_bvke^a%Jrx(Kkb{I@Ow0LWA- z%>UoJ2>es<|Fw$%=idtdkc!Z3q-=n{%>@MimyQDeE~)yrqX6KwDEI%hqrm@PeFI*_ z@<00qu(EQn{x20||5KG(IwD#_+i_d+t=~=cW<H#FezPld6ue900lEEh$-Y=Tf<zYJ za9M*sCgXM^1@zUvPpX#1$eAhO;*5gl%*!$(rL6JKuH0jdcjFN^?Ab(7dOF%Kpl$j6 z+@~#8rWJ0_NVz6o!?AR8^9*;Svp$Ij=(xN=ZRE6sPqInDACN{GG~%h~7~oR=TwWdZ z%~5?~8kTunq3ZQWAzT%IoPiC~7K#{22o5+mfA8GiJeXVYGlDJnoCq%RJ>a>GLu;09 zgeoy=$n;Nn?WsL3l?cx8CLfX$Utyf~bf^7q{BBy*6MF6{NIiP?CIuDnJe=yMANl^* zh+RoDn$`RMtR+Yi!kRQo^1`=j&%ZL06F}55JlWW)I>MBx(m9~Ks15hMtjt9ofzKtd zo@X6msc-zZ(1<x`8Q0*KJ(^ISS%9inZ?4G4`BoM@!nfTHI^q7%7Qz1Jb8QBm;pRos zRL~-$rm5iyFd=GiC_lG1U~Djf$ENw)G^AlEN7r_bv9m~`AKAY)oAHZKX&+*Za2O}_ z^9BY5D{zc(fca%|400ObrNU`CPx)U_!)fzAum?{^4x!R#JeFf9h8l<B67H0E2ow~= z9wPnOZhR}_Ad8h;;4#W4{l2v}7V}2`!Gf1y?<cQXU`9IETw7+$BuSbo0T9is1L<Wh zPPkM^td#u=)6g4Q)gr7|RS6|zag9PmDwxe&ESlU;es5(n(RCEX()@xF%2C(obP<$L z?(pV1r0^*k)RnlC`czc5f8^JS7$1Hql;GcraVnBnNqq)1E+MW2_7NLZ-e3?D4L5}i zs@9&R9UVI}BJ)1uCRT@@pH`x<9<b1DbW6X%@`+h0nKF&gmUfsaN#8c)%U`XmE!Z3w zyL83K8gn-!u`qa7sZnAgP?A2KY)Lo?XRvYk8Pnv~w<<g$D7ME#U*YS|3fK9MbncJu z#5`FWag#x*d2on*OVl?z2dmp*(P!{X8#!SOPg+P*pxt%Eo2%`2xjE6=Q`rs22_3Gd zBHyboS*uivA-^3e4_+-kyD2T~)z+w4+$AQv)O!|cL4A#I4~_4JzK|($6Ozf!14oZp z^5T){x6tg4L1j57qq9F`e(m7ZXQHc!D|d%SqdD5Y{}yTxvYTb}lR8L0-p6MI&nVv& zN6gy`Huew4+{$njt;D9e!PuhnGK%xygB8p7W2S*2<{jEZlU1Xc%9&M5W|D)JXRD8T zjZqRIL{@4IHRo7JJ#|{N@7u`KqsBiOtOl8A`_<G8e019%KZvD#UtA$QH1y=oF<++m zC+XbVYLICqKapw?YCr2vDaXMV#X#v750{B%XokhfxySxp)l0T=X%HuM9bZjeL9qbC z#!osKR>QikQY-J0_Vo~d`%hnOjn=SI(VO}l#&VM>;&4C$o}D1i)|&QZr%PpznMU_h zWsfNnS*B;OKFviCHeLr37S}nJA*ZZO5!J6UU=jA4-OC<_o1MjxufMb^Jd#}&z<Tvl zWMaQbR3|^bU>ZSbNe6TNZ=DWaUGo1+G3@^@b^8D9x&KuR8^H3PV%YzeLj68RK*G6( z(?{s4#4?AuCnurR7Q^%7*~%6}hfJ|TWaQSG5vO2q^mrvQh~KvsS`11oT1?tPa!VL7 zG*v2mJGfSao#N|aKrkUeaLg{=nDqCoWb>i#m0l|f@nl9_^QMwzt@8$JtsX)}mXtb; z{W@jp`6o}hw$*d39xvC+tsdxCSskuh)1Nc^ye2{`U#nriJY%4sphSh8-zZj>xP12j zWQ+?u_KtjczP?-Y_x!w(y>4x3Y;1g&3}Xh9D7t!%{#4D!v%0c^P8EQLYCinSG4|y) z?&bDW_vKwSR4r6H)R6D<?gA+elOAa|54#4`WjTYPzxy4@UAH;F95Ru14O9$N8dM=v zZ5Q3tIJcqUQ}xSkc9y>%&b#rDUmJ>$FN0r#_`F@?LqbA!b&=zdl#nq{rqGne8f+H= zyo{FJ4yM7y3cJGK;7&@f_ru*T>_c_T62yMzyLZT1+Vs{>De4#4H88T!CeYr{34z{L z_Fzxn{n^srKRdI+CE{vpYF0mqewkUwU`n#lFNT+&q*>0DHCSuLK{Pw5+!$*Zu;>>8 zH9u~R7Kasu00^OYpUJF(1hoPgXQ3`(C}Gtoc#6x9E?XZGK7Rbjod)Fw!l(ChGk58L z(J+!rf^ze%WAwaA0t<KWwiSOMGp~WsErXMmbWyOpN$Vj&JMr&~g0Mx6xfwIT?EiGI zQ9Y{Jg=|;)elvzaUeWLFcXd_A<?o%7W5eSW=R*4hu>acC(ogPVgn%Hlf2dIZhX!yk z?Aj{<*-(zrAf~<VnC^Ec9xvPx6v%(caQyW6%QE}<u$0;F=~9#V@jmwDc|(}#)YsW$ zK`#5nIm25RV?Tg;KNx#)*hp>s?kJb(!-wPy#dx4(<Tm)_O~QvxN@318!E-hw!Z-#D zBnbQJFl}c|kXnyTG})<(_jM7)jnm)Jokogti`4?(2MHr^h>%otX}p1m=LpVaJhx{p z3@saQIfe8XBj95z)>GLD__HNNBgpS7n(R-DRsu&Ve|!L|!?T3k06#J!WTSPKzjn@X zAH|nAvnFI`bsH<Mv3hN%CR|1~Kl7(+#OY&@+SOT$(o1Zy2@T<8raoU};rpx0F4ZQy zK=tq?y$n@Q*l38BXp>l{!P8~0`@0wSr}{GS-nr5So;P^T&O5j@>xfK&Y5$B<vt1l) zvRy>CM=if*1;?7TUsWljL_<UwYk*783gB{=dCZgUhW3lE&p)!VF@kTrRq}U*@!amt zkJDQ`U)&(}f9tnv!yf+@lpx(5C{&6B5jxzfV#GkeJj=I;;Qah{lKji9(`-Lj4>R*y z>F@fWNEfBsaHV^J>4!7E2^mhd7imo&x6eJ1EB-T)#n^o^;7Srsj*1P|S+_Pr5V7~Y z`;Tq(<7owvd(4R3DseN4)%_&q`Yl!&Gl4|A@cq!d^UyF4syA^53)AMb=u|6H?`CUG zzX_Ii><ykQQ|Ili^pKDg%lf^Lx^_OeXJHk06H*ZJ>#$k`R5WOBuNGr<ymZT!Y;`n= zKXhJUK6&?*zVmMdR8sfP9Z<~?%paDB_B@Nv{yCxfj15!Q+8D83<6I{0sO799*Mmkl z$6FaMB%lfG33?_jG@jCnFf3Iq8-l{;YPV3)qK9dNhGXLgrI35QL7P=oM}Vv7N<KmS zBk3>`d?)4Sy>%wV1eIpzH!IGULBjcNd{0W5*dOllC$gQ8U{F2OUm?!SaJ&D$-J}^n zh$AAwVDq%waCF4<piByIY5#NEMHBi~XI5HD)4`zHE%>K<WiOKgFCUkP<0_IqIg`ST zfPV(A6ql%fxyed}0KN_-Z1ske{;rvxS{|JBzQ0szz3ydPYpaIY0CicQ%{qb36OoD0 z+h-@ILe(!!_IbV5^>xjECUWN(@HK=k1PKWi<kCAAwuP#2hXZdLC$|)5SBmx4oM-Gg z;jI$^ye@ASS8JF8m-HC&I6mq(*exo?l047J79-l)F3N`ZT!p$FNnaDw&bjle6_&38 za``Pi0W=Z`u$jXksX6Fe{xEux@n(P1=iIPJp{G);B=?=#GN^lq#SMfr#iB#aVSq1D zL2{IekYdKpkJtzghClRIzmCVM@^P7<H@6>H@#8h4FMDk_PRdS|a`pduXj-eXNJT|I z6~4$X$ia4q77jV(s?_+l^59NfdlV4BjL*m0OQ$80Nx*Gn{M|I%^-H*P?_{!)T$hGs zPgza*TQ}SVlXByp9)jBP)T{CzTwj=wE0siA$tO=|6^Y0>l2RqCflrd4yboN+S2Jd8 zMS9GlvX8~<_Bs^!UL~p%>f+Qj$NKF$N=j7<&QfzWBJ@<Tu^(&GF3o$=VSsM-h<(-E zzm*G(8`gI*a%rJ)kXmV-H9or9Xicw{4rFtv+iI-bvDBKBQAkcmYxzr>?RrlLnbW<~ zY@u%3z`{-H5leAu%ezDT)BnfG_>bAL@~liUJPbn(l@8Q8pwn2)Z>E1$k-OAnY0*^V zuRA*ZQygFu4t#?!QP`rGQE=Rsl!q#W;X%TS?!IRBX(zrsdr1hiOtN(KthDfK&k$2_ zHOS6zcG5P*nef|&v#^zqBv6(sT-M#b3tuCYB9pF8!3DR1D;}RXZjx?NS=SSl2Rnq~ z4O}Bpk4=P|O`QI&nu=ajTeG~qEb64CyI?eHv84NY^^vBtJz{!=Ui<r%u(pb&AJAzw zIQ<*z^}}SMzzFS+&cuMs--4O^IcwqLvo&`dMSa;=yKBWBf;j`su3T+_@|9}Xn3Tf9 zjpdk}xES!Ii2&~3(8U3*W2h^oa2kCLWLDp09T#EuLXQP4I4T78s%Fqkj-e#U8qHi5 zeakp1STuP<b?nP!>=!65Q?2%{EqBuLyI$;#2@AM7jDO@u5DQ>+J_|GB4C@CC{7L39 zP#c43b9SL!SmATPNpkv4`-*+>hs0##Lk_F)KKml-vu_b%8EN-1!IPP?ZZWS$3gUO` zX!5Tpez7}+dW^k#8-3;X<1@D2gREVi`inDGdSR<&1*E1iy4BrIDQ3H+kB^ihA(qXg z>soi)9ji@YmR~N?8YvIVt`C>UH^J{H3_L3j*A}_JvhoKa_2MRyTx`_14jG%L^t~rx z5t25_HbRNw0_&;`+Nr&Tb3su}ypua6bd_N7KPsI-*NI>!3``N^C;F;F$}HWrnqSX@ zRWVv#H(6s0C!V#aB=wvVZRkmev&6Zjy&tau598OwTsl8IgatT%4V(wou{{S*RQE}X zvtPSLx-VkzO@*CR1OamGGwd}NJd)|B99ZE?lL1`6jf(>i=(&FfwA#{Dq4MRt3jVp) zpcUW>Rao;7Efdy4#rcoqE2p1beFwOv_72(E-b@Vs1kXnfhJB$xJr>;Gf7*wZ+9fWI zD$@?&_I_Y<+Bhah8bHqMGOU4FA^!Qci@?(F(UdfP6_&ubCDCgW8Y9Vx@)!e-HwWp} zM|c*C(;$?Qjq|wi3V7N)Qp)N)#-bB{-bLf#=vw>DLo<9MAbz~W`R3k=d{$ghkft(+ z%I7|W8n;MN<apcO138OljXAbdosrjw*z1RJU(tLOT$y!oQ0ZHF#<v3R`!r&X3yjh9 zcU?Pq2EVy~elp>N$W)%Q;{NJum3~~M)>XGZ|Dw~t#X!sR`7}|G+ryi0o%*oB4UD3y zqZX{c_=P;_D~F~u<wI&|_S23}mYQUuUOrkMF7UY^>fqk{AC9h|A9?)oQxgk`nGBpj z8I$UpYj2fl<vmblmdV6Zk^>Q5X`9p?k$iSbnyR7roNiCGP=qhu<1kOq*nY&^nIC#g z^m~?Io-jAOS*ItfTnpDn&vCIGn=j$`gdk!g{TLx|?9Vvwwb;JgBvqopLgU(wKKkAm zf<0ZK%3L>`XZ}O)UF=SYemIbj3<DCU*{J*i)g8TT-1f&%(r<N@%JQioTt)ynG<Z1C zAi&PfmQIW}5)-?-g@Zo6Bl*6%a*EvyR3i8dxBvVpPQ`fQPI-1BhER&rsvHwG?JIlp zl+erDM3Th_fkWlPH<_kAN`6H?D>nIfBz`_W7+CoMZ5tKA#puU)-NRR^K*7%YG<0dz zxZWDh0czQGujrQH{di(CMSpKK)yBgnN8NHE{CqKWy(1Gf2Bt>iV@Grw9JG+nG_8g@ z48$=CDX9!<fcT<437J&nK8Z^B{u6@l>nL9BB#xc7eTVk;BzA_3%b4e0xyfHV#V<~P z9lT@t?+bK(?O4%nVby4NK1mcB4_vplG#Y-Nu7UOLL8C)G!eGBN&Y<*jyqrc3sg&&z z%<B_UNUyxV%HmKjFCX$S&a@1hb6I=DT}9K&qy`cR+(yz-3Z%kLd^?Z7kCfMFV1ZuW zm(CQpADZ-quW)jlNaN>U?joQNdPEvrRGf$XR`Lb5n3Ddui_R(mX*t%I>Xxs}c|5Il z)N?O^9A|*fqXIi-axNuA5c&Ae@2}mSMfU6sT81CyrbBfmFmj%%SK-s+e$sNWkjLf{ zxMq?BFR!m46WLv{_m2z*evL}+$g9iSifG~tS2*=H;Og+qXlC=Z+piF&dvDDk$I=)L zX#a7FbVzSXQAEld%Xf71;?PiKxWqY&g!BDQfKfEYC=7WY1*b>>Jrf(Jfoz(6HW;DY z?p?YGm*zfhu?{VN)g3Cwwl(sb2XJn*n(i4XKa6L)E$KHqxo3yUJ81u3%wqatu$8Md zDE3<0_(bW2COqqC$86uKKO5Qxid8QWg9dJd?>%<hSm&F59YZa697``V7cWEhJGqy) z^TUMjAp=F-zX(H;0|}~>0PcJLKl!;ney;anN3a`DBnbwR{=V7t-w9oXF<(Qc()YLU zua3ZnOScW6+{U8Z=7|T7cEA23Dl}=vpW*t6hU;NCWtly!QOO7G1Lu>U8oT$^&CB9C z>e|67Pf5Ws*n5kh{X;{jTlEc!ROEP8B`O2g>6{&NmiN;GD#M9yGb1Z+I%c{OIpQHk zZ*Vb*L$1So=8)2;T3%l$6^UJ8mEQ?yiEmJ!PhsgQ>WOb5$Iryad_jqZ5gRSDb+y%W zEi#nPSUPCiWQBSD`NQ5GZuFi<4Gyz$(yOybnM01c2E4Gq#Z-TAxVzBy)OiSHHr_T& zU2K(6_N%NzC*BE!NxbQJ)3ckN!pj`vo*^|FNE~f*eBIbPXeGJ&6Gd!!&f1NbEvSvf zI8j(EB3(q#GXeklHxJNGr;F>!WP>Cov~m;waCUj?xA-Z^yz(&gKwo3=ydX2a#(klj zmU)zt?P5e8Mxk+T%JQ#ORx`TQ@0uLH59G|yE*NZk&^|<Z?~3l!DT&=Z)0o-EHO0D$ zpt!yi-$g9mqpg?Lfw9beKee!b{+0JBMfG@=yo*38F4MvGXlf@QzL9u285U$JYyr(s z!)Oo?%PRtcbva+p20h=9VAgg8>Qlm{o53_D7`(<Q{S#nnCjW@@rIc)gXA_v+k%*|f z=U%0kMRR`a0eyixloV#vo}ZI_Nb>Sw(fk;$9g{XApam44=NeQ0&ii%u9zIKE9oKVk zXwIHo`tk0FrB6vCGecsy^e1GjjEb$1w`!???5S#r&-cA<+E*d?`>o9%+|W=hYaY87 ztu#&448luPuWYLai0ev4!GN)llDjlAGY8tEU7YvKm1^EsYmU)}@x)2W5ryLD(@K*B z!#kJ0dv(arE0++<akH=Qv6SucE8?ygs%|G<sxchQD%ISdm17-8((S=-oL*Jxcnpze z(#eKTaao!enkrrM;O1C0UM@l;>aThmv+2q+r=SkK4oMm(eNH`s+8F#~%oI$*_OT!d zgg2eDg5x&&{mW@Ptk5mw3p8bjko@%!W&B-|5sNTqFHf55^Kg=*a0lGoVFrWY)>%?@ zmEYZ*I(=InQl`OE0>{}UJ>55ILVua!64Sx`ET}y{AECaP+NOmmVV1{IiI_gqG+H#; ziP^4Z=H#F1{;DM8SumTRK;Vm(onaS&J%VD#MR700k##{nMAdYT8|z$05#>;c3ZPC4 zV01=|hgCv#R$xl$<l+(F;rT58tyG3Tvn4bL!PDDb_V81J-Z$iFrDYxS%Z3I?>O0pJ zQhs=fY#y8MdZyYXvt#<iad2?pw-y~bulJg0|C7RfLzqz=fW3%Jocd;c@uA%x7UsaN zt@vW&xt-d&4dHdk)41V7LzX<<4oaa*vl@NMaNX{-9a6zt82`Fk)jY#HF`IB?`MWS1 zDzy(K@*P7lcxgNPLWFKw!&D9dj*#m76oxNPW+wY)&&wu!-t5=!rp8~nYoyF_0+24J zz25wNjPPI4#@~&ek-VI3jNN+VYEdqKJ)fzpo@6Fcd;hw*u~Qd;lt)B&x|;ViEkXq` z@}!@y0ip0XY*JlKP0hzLs5$9zo_iS~$R^WBUgR(jpGU{VMRsR@cX#)9X&6e#et}w6 zUz6q%`RfJb5e4{rgdaY9_|MD#`8JtqoTtx(Yoqz;oa6;ui1Sjau-i@2nWFHB#`NVB zfHE=-CL{&<w_SA>3EhL6Pfq7b6JwuH^kDQ5H=I8t7f$dT>~&pk`DY#78|c3t9?TZ9 z@xRLKWOB9^bSm&EA^Fah@GYOl(Q`35{`RM_w%WLt+d{_f`Kmmr6B&-+lih(o%;Q~B zH9FNppiQ{b=51(LWoR#`ryKH2C-~#%?sxumeTvLt4zP;c&rC>J9HJ)U#--@vLrrin zj9z=7<>#u;7ucg#n+KsAOH1bo$PqkYyOPeaKgot_Ccr3Ej-=oMQNcT$@V%of;HIL> zxC+Ya6>orO@iMyukGw7l055?Hkcq9SsjV}sZ3YS0lK>rvHj=PQh_ba=nqY^R6=8z> zUg4KB0E?xVoavrgZTp+ATAA*CxyE=}S{Azuzuk`1&qQpuub-keHWD(cU8op}U50o* zn0KyIBcX4Xj)7h&0xEQYwrJ4>%{hZO>UmPS6{Lxz@vH7lTEquRNMs}MIiAc0yIJ~I z=`k2voW>g*EvgS)9MC;cNM;n{o~8j+Okk6v`Mz<l!ruj?JP5JX>Xpa3{i+!}5K>Y1 z2t7OUjVX3nrr!(jD1%j#O+~?l)$gKw1Yvm{j(9YyMrD^idl=oMX*cW)r!B5|47dx$ z7{pGNj+><yDgU}yBjPh%V72M$ERG9MH*TtOzM0u-4Vg<@JD)}^XV?7nQ+mAFrH^co zU6Vgrif$?Mi)rqg1m9&#8}dEE<ieV)d@8b71}=3TON0BO#G>~XSozT0<7ug>$u23( zo=Q9tc#*5S7xn_u#b=c&(8H&ZZ;c~j@u@6`8bX6bNDigVcZHGn?PB;66+g+1r_~^o z()r-T;X{QK5T}Ykl->N(cJMZJCb~ZrwHX+$pjvgW04$H^a{T^Ij;&&Jlb%{M2v}6G z>ZW-S?-I#2YlqccONWX=T%Y5l7o|`LYb}1Y7^Dm+7L8x;H-!`K<#cmmh))ue9_9JS zoet#i6JAy>ma7-s23(Y>Sq=GC*bXM)*e81H87%dL=(SzOBr<lm`R~6-GBz)Eg2(x8 zE|=mMavSy+(Kj_)s?;V59Vx+jZE9rF)xT=>?N&Z)BsZGs`gYm@|7C~@0w-eQ7S+-R z-d7IUrw2EekPmqM@7t@^Z0CQUOv}ddpIit$uVeSY$)5N%$TdmGXT<6R^M}H^h*L$z zYQzmyQzrnw@457aNS&2Xsmy?NFAmcxR9~qd<!Jzp-(7;sC=KsASl=!A-ufQK%-OC> z%fbVaXp>HTBF8lx{bXnA_bDY%x3jYmWbhk~*X+LMspj|o;*Qx%0DfdWI>}nrmE*S= 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%0Dq-<;?+T^mW|UY~OoVOBvg4R;<XxW29bE6(YgT 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%0DDDMF^bK^A2Mx2YOt92A3I%ZSQKAqAfb{{`e6?7R z#r*UZb~@|$h)T47`SaL-_=RE>L7^DS-dRgZ7r>R`1MNt@fc&ETlF6#ntS(})vs7KK zjd|vWQ^^>ARK_Q-NNAxKrsIrAi7Pmrto}I|PRyuJo8EI=KE+9=ihhVD>Qidi<cM3# zWq7{Ddvu)DcgDs)u%YO`u6L&%Y;n0E6zdB*VgtI1yoTELy!BK%GT^3^)9_ZBTu5Hw zH`_k$dw$|b`?`oV3l*!+0j|2XrFwI#%()St`_nPUEp#+yc<!CR{Qmo>Z<{JS^Yh03 zaySz+0mTQqyFx&gfJn1sDdnu<e&_av>K;aCvBq9cr6t2fjjT%#z!cx`(9I@+4(fsK zjl!L6+w2-7N>?MUs}tH8Zk+QI%Wb)(qGO>Oqbn;M0@N^CM>0cz;t8F0lYb4pU?W~j z(H<crEO)`@_M@7w6Dgy<PFj2VQTnBw$VZR&WGA0V70IV@`9$`Mly1c{hs@qRG}+!W zh<>Z4b@;td@K*%wqZBg77wO({pc{_?yaeH{tS;`E>cTu8gLBtreU7(Z`o8=3Cg!8S zDSCwh!Ann;%mWG|Hm|^an9K_)ED)-06(gARx<L_Zue0}DFi#}TrOrjNIViK&BxC4L zRNebyc2YIGplX+DUe)kFsR$R25C5thG-2FdVv3|d5;LlVL3?Vgtt7IWBybejL2mh# zdP}KbA)f#)2IfQ=U3$**nt9}Du-3JDb&MP%DIUtn>Na9ZvpCxGD8RXl23PX-17TbP zE69#Jbbtq?2=?~pxyj=@ELh_xTXx7AjAQ5&fN^`ps{FD(DwR4LN_WY8cs0+NBC<4P z6V=+aWhu1yU4QS3Yil^ATmZLUuEt&j?X3bQkEjVKTTpIS+3%5iMUVpZ$F8z|478ss z1Av+^Ll{;8{AdY{({gL8-Kkg1+)I>{owPtQ!`g$Z1z1A!U#R=Xzfku#P@+h`D|vk6 z>YX9&(8OKr5=rGR@-hc<rf3WO)I{np>w`}wuAANvIOWr82D0n^`9`kRN*b@IL&Fib zT;wTG;@mM|!24VGd)(J?%g9b`J1V&xe}}=$N*qCKSYK6qR(ncR@g3dV#(<9KvtOTt z(6N{9J0!ppUPsCPmiD3R&J|~BF2fZDN-9()YxkYyvH+&|G(L0KJM4q4*EMqlz?L`X zWC#}H@ruPlJZ*jZw+)wC6=vpv_OPFuc;WgatJvd0vA50Sov8ln@<cHnk29Xv^ljN1 zM`&IbkeRX!;D-Eg4L#`h&ue^6m#<4)0Vgu5Uv=PcWbS<AWWN3entfj-kt1M+egYjt z(f)4MdOsMAVfd7WRR&fnQ!MXI2^1YZ!oCWUg6P3hNos4~I{VeL$l>#X?=ls><8Qd! zdY<O2{RzWw2aSh<kMW<ys!#w;KoS!S^a*4geba~=1D_b?jRSoye%^(#1BN%WdO(HX zU(D&HpG4^a@eG{0Se)-&WHnnJgSWnd_9R6C>$K+5m+`*`hf~Orb^+EL2H>gV?eg<o zoQm*(MiGENp^)?FLUe7w1U@CYfBCQ-gb5Uf?*9%ofMz%We(?S!5SCPV1AhWf1~mEu zyjBD%yPQGfeE}_p8x|5m@)%(&fvh4tdmo^J-`h<9)vEN&SkTZ<esK`T@-zFX*d^}t z>~PJ~`_!a+1fW2p_OyOVpTtkyR<QogR$aY2fVdxU6YkLa&|($=2LD}Sf2n7Rh%2ao zl}pul0PRPCJZ)8>WiQ|OO0W6sdCuP_?(MI{agwdYO17rfZp4S@2KxSaB^1b1@FnB0 z4}yH(Y$K7v;KX}Uzu(_x;=WIpH)tHN3Aa#yW`iJudp|~y!L>gry34@cxq|Ma9bn$L zEdN1+yI}tn8I&Tr%^cD9i$X4?7#<_>FTQ*=tkXQ{UQTufB%Y*9=l7#gC>_Wk5z)=# zt#8m?C)^Zi2O<)r=Wp9aANz7yQY{EP0^$-wlVk)6yrg)OGB}(gh(HedQU;19i3oji z7qOl`3g&DFbwo?JtyjN6fM9bMGHwMZ<vcp>1%~L}^)GoL>h}n7AsqNWZ5a`n$$j|1 zxMrz_Xe0wb+hfH3O*mz|5|8*7d1PcCfb;*<eWB<sAf6gj5nfV@0EGbkP=43Uip!&S zt6;)@mEro-n}T3!R-$slKx+s$+KN|{LUD?s@|Zq~r-M%z#fN?~C!zH<f6ao4F>|II zivQJ@ES4g~I>)A;dlF~W0b*SG?-u$>5@sfmevfSsmzW_xkDLIXjj8i7U$;tt;ig=f z5=>ZF?e6S{cP+X%DE8Ywa!UwEb)OJqUJD2-DNLm&jK|fD0>un;t4Q}PeKZCP#^&+n z(Q~lmYiKPkP{wz&^G{H4I<PX<SX9_C1!`*&1vOQ{DOs1j#WiWsr9c<R(;J2#oEftg z^I(LE>j1r2DE=)<d7zcT>cS%*VYF5skNFS*^R-vSKO>uS!e1-)d(4u5(oW?ua&)TE zSkU3%{3>NjHmlrxPL2?V<RmL3SEm9$t9STB>m{u`Dwce(bo*6_gTbr$wF2=_uKH*X zMFW^YRQiZv|3dqDx;N+q{$DLX$luNdmLaN0;IK44ZUIM*l2<^oLj(S*%ec|fIAh4L zhbGh*=uE_FYFfYr!yD2I0QChpl~=9S{MLVxfBPgRy~I+<DaYgCvBGwZ$A(gwNPL4n z{;8V}wP4PI4CBZ=;dAk)vY78!i9P!D10KN;nTzeYd)C6iscnkxk1Irc^$Deyuy~!2 z?aZj@o}Ij^<hy=b4m8YFXwb_kbUV6;osS_mWbgr<!V4}60X&=G^Swk~O%kwvFy2aS zFRfe)>E7}luUVXedGF0TL-};slN^I?9Ndr>{U_{0AI`dzpg&~Z7ExjlOfTFvF5DLK z%ew@)9bsV_noRxs3UPEiUGfV~`&ey%vXoU2$KvIA@e@H|-rWKy%yp*-3iHiB6z1(o zt0w@3IV*RX?P6%-wYVMOo_jENi~eBNXDoVKe+H-Q4&H?2@~QEhwTu2~{6U)V+z6L} z+xAV7I!>2bqESopfcXpB22q#16|wNm27?}|hFUj+wn2??Y7r-JI``{ElsNn;$p^hM zb~n<`yR_A!E{?E)=WUPwXT9d}fbF~Vh2+r*BdK_^`r|i`$bLVquXtZfW>4)@6nA)` z-d5(u84#3LzDL=BUCRUB>0#Hsk@=|L230$B_%O!~Z8@4sV}<;|>MsQ5XUe4cv-&H> z&ua0cKchhM8)-2O#fDB4*H|yY3D#U?rShF}zW^G9Net(T@di~;1oH<OI-{*+oCLYf zTS;|Yq6E7ps#~_(3icQV^?=fvV`oF?gN=DW`S7B;K@G3B8nd$k`ebke!9qfttIY)R zUeR$#kyEu{B&EvS7S7$5+(%whM$jno0&bJ+G=U?NNB#5Dl^b*`<V4*ngzR#|_ho$A zwIYMx&qlUtcoU^3yEBxQ%?hS|CTuWuL+b{3@0QcbC$FF*^wu~!ux~Ck8pi=7=EyTb zMQ)2V3Ol8#`q3S5|0Rq%P0i$K{(g<5eX~`s9jC*t!pavZlhhQ{M7E}!2DC|dr{gQY zKplX-LXRH;MI3^Px)xVzwWyA##?BePagSBf!?{y4icCNL{Q7e2smh3tVj$obnt1jW zkK?Jb0of+<jW2In^AWFwO*;N4>r>EP9{RN2$P7BlIjo;HD^5x(c@==i#>l()vU0D6 zTgUCo9>{EG2q;u`kDMFYG!&ne38iiA^}xeoSV_#d@I_o=jeUwm{O$v0MnU5DVN2QX zzgOq+1Fg|n*Y?;E(K&LOf!5Z>2^rulZE^LXe1G$~OHZh^Sa1U?N4JZUY$cE+VLk`i zQXmTS*fxv+wi~0N_+ZY0iVhKp1J2^#vN_o&gIS~4s=nW&Z#aF>pW8e4LXbJx^zwGz z^~&c6A&Ogw<K>uaa(-;L{ae$FR^MtE`YXmkbGnEhDtuAj(Ks$3ZMl#BvDT*Sa&wEe zJsE;WL(zk-IUUzSe`3dvR*>zM<f8mWUV_nsz@-C-3S;-kYxdwq<O~&b8o9S%PCNNN zoYHZZK7WM!fsL&S$bk)qe|_o#`Jkd11~Hkjz3q!hU=65Y$NDD-0BwVQ{yvIzZJX^y zWY}WzZ^6FLLAuqcy3KQOHxumt9QKSoxDH+S<KI3RnEwoF|3B8({TNMvibwk2TBl*2 zO`i&Y{Q?Gqc#FOF8fXlDAGJIJlCb+w=srdPyr5dgoG`#oM>ul~eW>k!<_E2q%%_dr z6kVzrkT#Kjf`xwI@c;COC~|1XvFI?hqpF9#ElWTw!|>M|R{!;eMyaW{CT}EO{1<ru z5cocjgAzBQcAyrg?3EIcCHsC!QD(9L!)vee|Lqos-vaUPIi#(Xz>w~5ivJ&yVRd}> z4e00i?;(o-buceP8DNhg;(@jf&?S1{X5UdXZF*q>KOF>(qXxj5fB#z!sCl^!GK!Qq zTKT6jPBrWi^-3S~k8M2hvh&)8GaA{!-wFVtVJu0bJH6b|F5m(h3RWrT(hFOjKv}g1 zm2|etRND3X|EVwl^Z#!F%<0`UZ{}jPg<#kfImV?ZO*dTkQs?;3ue<NElOp9`e7PQI zerond=A|Gk+3+t9C!Vu|5d?d;%f!tD$MJ;Cf8QHvPhj7YRu+wn*;90?6_h1k!j+PW zj`}%&-lKuXj)C+EIz9keN?Ddhhde;)!+8S<%Kt=w)C|HH0IBZBw1eVNk-9<iEWj@| z3{*H05`+>CypO~oN8Pb#-~&bi-i5ztpT*+Op*n-(@s#IoPhB4S9NL|lav?4_;@`(1 z1^)qySpO+X=w&yhbQy41yIG=&p@+ChFd)PQ0RlH#3Gr?b!ss^FsKOjC`w6xa0eh6I zQ(XG^+?nHdT<^&pvTCshbx<?&9>t@65~#hxUgnQ=T69V3Q?bkWK`wI)+A}6dVp1VD zdTiuT^v*m<`B~Yf*f+Y(0R71NvK<=WBu02W-*kX$E*d2Zye}U7({sR-z&M5aGxVG9 zC*5gCeEd^GPout!Ek7^}cQd-W7Z~>^Q#cz|1-V@$7{VQ_y<W<Vo0yehRc0dtQ6BF& zSYCWh@P!Qn3DN>mFob6JQLU5`Bu_E*sZ3NIyz4ED#nVBcmlX-uO<rt+km6C{?Ue)i z^w-0(9(ww`+t;-sKjObNu2a5=nGd`I8Z36@n)V@o0kg@WB+wpfzK@oWgsSw$;P)X9 zQNqo2>+Ju`I8IwxS#G%eaI&jBiU6-AgWCnWBJui=*_7b947_)73#<LR{#k6hPj$yV z3wSRuXOHCV9vVUuIONm-x%Ewh9J3Xe;p~AOAk}#b-o6oSNCHrG0UrMg_z*9mf7}K7 za@D7mE0z0bR=d7(T9tg<%87?Haq;8KTn~#zVPBn_PlODRKRqj~bj@h_baa^LL_d2d zIy8o||E*7@iTeIZo$;${{t2C=9U+X58_fB|xVJ4(XF}-i+<Oe<Au{9NiLIDef6&K- z*T9bAPra|u(sUQK^1$67U>v2-;C!3SdF2VMPb3&Rv*Y!NjYo=k<T_NVzY|_x*$h(L zGS!+Aa9}_ld?@Op$~ikYu7kTMb5Cu>Dh!7vW?iZ|GAvptLBJI%bBcgo&fIbJ^&Kp^ z#C&o)vMs5KEPCf`;ST>w_-;<_YpVZC)gMh9N^SL5Xg#gvgmD9A?%q*gqJEIkqd%2m z19{yyplN@od$b|Pm=@J8>SzJI%qh?%b0`LUEL6WHyp#Wg&}i_x<WpDgio<%CKC0+! zuB}W^A5fY$yPRHqG;P~x(UelOnM71#!=!OQ-3zkgk~770Vfj;I&7T!jm{5PIM-Iqj z6!aRB@JY0H%!)L)A<D(FG;Or$XlvNrYRNZ<0KD<!beF#4Q`AIuKt|c+XU30_dBpIX z&U<A7<&6OaMJXKNf~$lMx{xuc={I0qCcN3T(zF+<VB;6V@lD_2I4xW559UhytM8Gt zDugKgDmKq{m}Z~iMtdKw>r!_-js6bqdjNUR42q{6=>u9kBr|yIypdScUykaF3JkFF zi-@Y+Fd#tc^8rI^1~{U@?e2RJXvL69H;o5IHrrqoI%|Lt6DKX}(~uec`@@#BjmvNw zT{z|X4j?Iujb-?nxD4A`Y!WjpT7yn|ZyFsyla?zgSda(tBcLrU%nC~Q7;kVB`l5Mc zB&}h>Pe68bQVJn#)P~T_eyRojupfZE`A`u6F@#P5!bj?Z{p#a5QIr852<c1T$S%SL z!QTNZ@zcF>AW^`%RFXYt0fY6Wk0bL<{ceOE<2|`HY8N_2%$!0uEqrg_EV>a=$$#p? zat5z~)@Lkq2O+KmqK1zF)p!6U|Az7^`8GwPguci1QtC09YKfRssg<aWPf)%BwuHgS zuo^UxwxMHq9C2%?UtFRf?Ts`?V(-KMMj)gwhgVGh^ywGh--0XQuRLmMDRa)yuzfs? zlJxXBA}-XkWAt#?dNnB@GMlHMB7M^A24z7anaC8aU%0&+u9~W*fz!C`pb23zCI3){ ziyt>}`@IF{jqEu<6Z%vRkr<uc_<?_3{_I?n0smQLOOmx`D4wk2oh}82mH54P8|2tZ zUNlCS?F1hv*%tejx8b%|zd@_ZB@!q3N0;o?!pg=Z!pZ{{s6*G!s<OKqr(9kg(4a5i z_k!?1r!Z=Uf8M6ezn^muA6y=&!UH}b0$ls?UI6z#<Sk$ckdO?4W{^#JDEIF|*aNFb zZ51W<jC**>4T&j_YU}A<ej{#1TzdwvWuKvAgooPG#x7`ecAWMP5x423;*?9NLO^sQ ziD83~kwMdFL*W|(UvV-4ACD^;_V^zao9UkmMZy>{4pq)#ItcoZk>ZW=vep!3M58wH z=F_GumZUvmNMlYa-adax!=4Qj;K-1<ybxX~dxY>}U^NKC6@LK&`k9ZGn6*SPrBV5k zuH&(8Cn#Tp8<4?qGNAO$pfY2E8f1MlIxe|?mc(&DdKSt3%}^)65THAfP=17zEP+Vp zDYJ76=sRHck2nF{20S0sfk5zg`1>skcmsHS@+6(VDWl|SA@1W~iO#mog1`XiD?;DI zBf!_{=aAqK5M{60-%(U>20O3wMcq#_@OB2{{e<{%_KpeC0v;PFA#3*D6Q|$nu_5B5 z*ASB*C{C=v0t7s>g|G80<+|F6CqY@dgn58`37trBkVfXcv*$5{@+Z=s_zA_`fU3-} za95LtB-BaomsK~=u(rscOk)HMb9yfIAH6rm{4aW6^z1}+UW!atHcCy?;rhB~Z{Y@8 zq`s`;WV}f0+iaBgHGj3o>Wz|`LE|{^RCymw_hOFMt%duq5+vxJikkA>`{y=KeR(4X zL-EXU6=#7pAxu@{7Y=HWi;d+$N2fEom(RxKx!1HX0UatM?L~NM{)Fv>IbOMrH>D-! zobvLIIGQ*h!%9u)FB#9d%+)gcIW7W$c!B~BVn(#V(Be!7GhPx9#~DItp1C0_wT&DY z^xK}U^?v}AGy)9KHBRUOy~VPG47232$$=MJM|t4!DnRce2+0LWAHQ$4su^^2G|m7} z<JS=Io<MNQffUn;U(I~s(e`D8K5*$&v#i~3Oefw(_-7u-7ZYXNy~D%7Wq>$<N1%tF z7aa5xyaf9|^B5;Uj~@@>S$(Yjjtzn#6feQ(cY;K{9f?dCq~`9|qAV4WL!pi7{c}O1 z0Z~tY7Cp~C=&3J}nEid&K|~l9G68B!5e~)w);Ym+|L?@@DG|6kr~9We&B$1EKmiO1 zWQF0MYxuYUUFilHLcx7Fh_#nsR3ZDhgbI)^1z=_WV-*e)YtDU)gmh(9DIk_F#6$*? zkO@`^=(fWb?Zx2lnogCqfJ!aieL5>u`<{3|vwb6F16p1BB|oIGrq_@6>jnCsgQ3#? z**b&gEsZzgk8tN1h4DhirBuO2&|?-mIEk>RLa}y(=kifmeVn#1pZh=+5z_m9kSSvl z)Ohd~uANFkCiNz?Y?TQeiJ7hU|EWbH58c@QYSEQj-Px7b<zX;uqmEG1U0YgHjotpn zdEBd9_DXk&2j5ZuQ)%2avo!NhzfG15LSZ}^#RbKl_O?W*+?~*pS4ib;Al3fe8PL|R z)n1KYsm10$JtlZ#2yP?N5D`4N!Dabi!VkkUiwhyfj!dgxE9<(M6nvE}-W3QOB$B29 zLLYFruS}9JXCTA7H)$t*heyG8lHQ_~Mi0%p?(fkFvOTSY>rS^9*Il14|55E2#dY}P zoOpOFm4-Wh>y)W8pfv8$$|<CNq7;6Dd41U1`|1f}wYf8}EX(^4YQp8X0OyXvXYbuC zDamMlIlJ`+@byC+@D1U4$4;i%W9EKa>x0pjTlmdQ+Q`Fx&!3H}&EGxMAq4ZbQJgyk zW=5m?DmrAj-XvO&y>kCv6`@N8#zI=uk&x+GL6Sd)`@i{4v3mQW9Mg85GGM1|5TEZ> z!CzT-R=P&~Jp)j);FL4NEQmzk;np}9@7zF(y&ljhO$gM=ADhPU)NU&aeCx7b)`cDA z_VP0GFwk`QF8TWDw-@~!J<T)s^0eR%PJP%55uINhn3r<e6RAH6A69CauM6iOGacbc ztP7WCRnQS_c`4~}f?4l*)AZ^Uyi&9jxJm6N=(lOs^9W=14Prh)!Ehg<`{}PWho%T( z6Ji5e9M}p9Z@f$2;Wl_Yu9CFcvT){gb+xyoJb7~r_Y{XDI0D2^<kuK|w#V08HMS?0 zp@a0l8&<YjejhEbD>YvCYT!C1uvS@l6&2sE9Ppu=hA`_YBYpM;zraNTj6D+IkB|VH z4Ez9VxtA!bM}_@xo%Gdy;}H+_7x4Ea$Y$$ZOB_d52zPIA^bLXC&1H^3|47C2X3!7= zy!`6!S8t*U9lKm`lO~WWs3J}=gXq0l6Uq8SfCyLMh-?8ECy+rQUb11_zXbmK0C>rU z@j9s==CM1{VKy6Yv?|4i4$n<$2O)jr>^)sGs@pyoS;K<Z)YL>;_3l_W%z?JPjV8XW z(5UhTBh?x})tD~us>VlcTR^D0mQP{fzB-<BMsRr}z%~rA!(YW}FU*}ngar4q?zCBX zHlScf9@a;<M-o4YZydR_lNvx1bA8+?les)PaT|RZqu&H_LYXzWIJ!~H4CA`&JVg9~ zhcBFKKwabICbxWAs5`NCtaL2h&*6v?<Km_@LnQespN>=|i>4snT+MectRE!c!S}fK zvu@0I_X<ZBo-c5EyCL*gce0=$wj+U-?{58pp+*0&_&X9<1KE^gLPrms5%+tp%T8bx z1p8GkxXepkTr4prA`?5v$uolrN6w@Zz$D?~p9wDFdqs8<CqRl1fsskVL%=QM$FQmn z0aNG@dSisoOW{S3caGknK_P^n(5O)Ar|H@Y!0dm5zFH9Af$NIw1K$hI2Pgj-rnHPG z>et<}_{!Pags#;5jp=;hVR>%flDj>XJXisj36K+;+;-L5swq%`=o1X$2U6%0M3v{m zl8(u4pAbnCAibb@kb$qf1EYz)0T7w?wZ8iVg(lF(zhOKEgmN$4;ZTHdk%9CNP^fz$ z1L@0i_&IU^C&~K*hK%63tfE{kAK><HN<xqz-j<1eBieZ{F2Xiq0kuLx8X^G{28oEf zm;Clz!{aFu(mU)d923CLf2sMR_W<eB-nH(R2S^vBUUL6E){p=H4(rGDZ&*KeHUt#! z{{rjB&i)ToPt3~P%2w4{&j5kd69ce%|L0gg#JCWEJ^<clplW2V#rjTMl2y&f*`8I# z0wD5<{r`;hyC3_1!TNFW|9@fqk~L<-W_g}@oN4rBsx_BOD_5eRJUET2oYkK#FUY`_ zAuH#xD2UA}qUoA$+V6{~J%{SR0_BxgtOpV}#cUl_t1bkzDi7BBcTDc)8XI54dsx9@ z^Yk1?E2nME-XG{e-?JW=Ko8f?rs-JWJSDR6^9%2FfBDMmvj<4zepS(Xswqh|A@Eg# zi!kUZp1bSS>FF&NUDc-H=@Drk**@~GuxTfy2j+=AAccn!5ykYQuTi{1C_f_ejw6pe zls0F4axhpq_sx|>A9d66u;r?!Jm6=Vq|PqWzLIHk+c!^nnL!>a-Ilb0hOUrBPA|p= zOs|~x{fj@I_^sqMaZ5J~&uZ;$*4RPZH=o;^+C4r`8zC<om5m%7L!VxM_f@l14gKYt z+P8#WBv7|CNWUYIu3Kqkqp#?hXV-J@ID-O1q;YSlmXd5Xu)z?^p-|z?-g6iCxEWn4 zXFOG@t7gk)79D-Ar&N(NLH>T|?5^H4nl?el*k&%Lsa%K7XV&4W$saMaPD|Gfo%4SL zW}rUMkkOCy(ohTGV;b;jeVr;lyEa!*782r3`vBzg)m@&7ee#Rr`n#l_#9=H;nR9Gw zqrOUla|piu%lxf$I;xT3XZ^$0_BN;Q2wY53fmA`7mv?9FmK#l-Mos)!a>o~)T@3k} zQ1-R6Ygjy9qbzDKspc%|tHvHyG5N>g$NWE4&11ZzBP(1<wZ;tE+B;fetb&r$z7s3N zlXs*@)>g~u^KAg!pD#IDOx6!y-da^vu>XSf(}wjw#1n5TTjb*VMmy5VVVB2!mU@+b zT)98eQ5yKY=rfOp-YhDeaS2?#YDQq$L}E5jxi#byv%m*m%@M2OchAlYo;!WtMQJVK zejqgme96W7NA&k!rBNvCD|mDRfnE81v-v=SrUO$rhf&fM+J!}9{fa}Um3q%@>R2bm zrn5$3KVw<5xr3viz)c?H=le0XqCBU@7_!wDjXc&<L>a`h+O~|Q6P_DydKA|1n6@4& zd9{D5%}bv?tP&PR7p=@Tp-5V@GAFYs<F{rCkzL7yWUB<fdeS9f3r@;J_m084m?^)& zny+mA@MeLFL`|$WiFM39T}sg$k{LC}O31FR`BiyJc|6vpQ(ms<XjR$5>N@Wb1&LW7 zRY4-b?YCW15MBx!W-Yf0Lzpc`M`K}hmCYNQ{JoB8D<rV;>uHlSwl&4G!(;&p>KR+& z&sa#%@i}c(H`^bl1#jb8xU-}*zKW1y(l|xq_Pg<3RnAbh$bCKkhFZ_{*!cJ7ZQWz` z<-#BdA4x$6+`BF})Tf4;v5$2Y@Z<e3-Z%QQM322<di?eeTRP!9RmB^dXgi{Zg$?UI z=mS~uG>mf$v@}daJqc&Unv~e=J>UGXU#dOhRHRCx-{D{i%G2YY%9ORp;i&ZGe#Gjq z2Md<`fU!<Rxk>NHiN)R$Ri^UlBUe_i<K~EFaF+F3DSWSNtb)CUe!ZPJUS~Y}x7jSg z#Ra8_;vq+q>Lq%+T=KowS}w9KI-%i=J4O}xcUcp+D;XJZWDivmn1*fD@A)qLribI* z_2O7hAIEPwcK#v;sVZQQH=LnVf%>;Hy_C81nm+dhcT%b3tR{ghKXo{`slhFnrH*EG z2v0<D`UR~eKPQ&G%Mj@=R78HBUrL|oZi5r~#NVR$SH$cT=iB!SzxpH^aA{u^5IgfH zPSlxmd+eQVYtV#t$<4eY)e9i0SQ`>f^6a9nBGxJI*7>+K1{v+GT`O+oQfRs<vWeT~ zUvMM~tCHfLA#*$P5lQ9P3u{_ge6{=zgon(fb~PH2yOqQw*5z(mi);f^SA0BI_RdB( z6P8^T7cFEq&tl*!Hj7E%U*7=L{q5qZP_!v$Jo`spxUW7wd_QcTtj*(aHs4ffFS<%S zIH^UWIEGPC9M-%oEo}_0f9EHQQDm(#TsB0Ry>}wGYJI&Q{NN}zT8`ISFYCis%J~lm z%^_GXoAcQobv1cmup!-^<eL9?aJzfg_P@g?v-9%s^Z%a%l>f(YJA43cclP*ucG$u| zaGpzaiFH22R8b*|qYIxfCcRx*MbS3HnXa+plfFUMLgaFy;m-NU)U&XZR}bW^cV3;t zcBQ*tBn8)?S5{g+@&1bP1cl>CUq>e$4-fZX?eUhw_QF|FL)M+D7tee_n#1PA!eB{S zMJ>IOf`V!7dMZ6YlB39drI7flEdFqZlUT=dv%kq<2eIe+dp(umGroHFbQ}QzF8f0> z%PPbs<VQ@+DBMrTQJ#~sATxDI4h{_~m3TOAF0GClvy8AHSb4O8pWfWV>pp7)^l}as z;(p*4bnvvc=13B5^teJo9I}c}=?j4Bo>^0V5B$1nMOv4gBg*gY9OZs{yC)(~{Pr0N zH#AlAWb0vgG0S_kUelG5yIn7QrhJKC6z<Q&pU{qleXzUud^YsEEvL4M#C4Zd5E#by z&ZuVD;<NVtB){UQX!;9`>Oe`)$=gSIOB0=hmb<RI1wlo+ALlN|{mvR!4$X&#gNjyU zZq<UfR4`DUzeRf>5t)^<-mPV|=L-y;ND(ElO-waSr%t&rmtY(}^ch95=v~3!q>#ep z@r?$0q;<BYng-X~SIUO`)(2BpT8|fcju8+!O!|yAdP31U>s!sTjQd0Et53bi8!pFi z(@I>oI{gVnJ&w*M1tvXUM)O&FCwq@bX~_?1yz(U+B&ZR*HLBjlIxJuY032OLTX$q$ zk1A(z<4KVh!68}J-|NN8l++)zFKc+-^eUxYomkwhibk_kKIYth55Vo#PcUr)-Mgc& z^9aV(eTREss|{ob5kK$f=HTFFzh&P<xx=ISE>!Ja@ytT$bHLZXqazj3saaZ<B2T^O z_?gh<MF}+sq##Un*Cvb&6k8EXT~VsYEhY+~k{hIygq|&ko-bSlEX+CvdNej|<|qWG zZt#^m%%&HapAF5pB@%EIedr|>?|HxZ5^5eSTlrp`bnwnhb+k$3LZ^Pvt*N%iq{U*e zX^+J9rbhxJk>DmjbB;Y1&XOlk=RfnJaNZTCY3yz@?KY_VSE_=`&Eio|F@M286VGr} z7G1uLlbzPd`OVkEpbhKejp^ZGyUfhd>*#;bc9+t;z(j&K790aNtWR53jmg1({)jPc zs1}{z%6`_6*7K8hQDM$!`tbS{<@YBrlAmEX?<+0#Z@w^eiR#wn<e9Xzjwg_2l%B1+ zZFbe!E~mD9{JAccZ82;216!o8K^$ulQ(&qX1k$i7tS!nj`8_Ily1y0tXZm!-DT!dN z(Y1Ha8@peOw5ieH&FGTx;>+vLQZ^}v@DJnZ`-kv_O%g`y>nhQPk72*DMRS_3nlCc~ z)ExeJ&z~k?pY6Zgnuae=17GmyKc?5XXvVi%SrElKEtPz9XP<Uid7j)m(R*!G23{<J zI33A1ylV^Ecpd+OOr+??=eNX{#d~51ZM)tK!iqjybaK6b!LgY|<+{%=d>?6h-hTIv zO%v@t9<n{m(Nv3j^|}QB{Q-c6o;67)Pp;DCOz#x(6T9Kg?X$zADO7Cxoh85BvtIK3 zz3@vXHq4z6ajcTXNgAK)Uo6wo(?9DEJ}N>V);-pD7dh|Wy;WRvH7%p)U6_|}*y0bK zuLI}KeQZU$-K4a6&~a`eT`rdcw{r3;Rx-j%olH$X5WwD<Pg$?swMLNbtmZhy@g-!O z=Y<B0f<5@h7c(yB|C4NI{E{qH4ItaqF?tPqNK+X<4`qYR*_~~s-I$wBbI_8qm})su zAQlcj76SB9bGz(zO1jWs^_lkykC^mqH2lmvwl^seT0)+Y>7_~6%~2jlBA~HIrkFZ+ z+cz+O<tS3|ZV&dM)*N#e<{nVN8RG)^vpcx+%VIC^X9dCDA{*XGwRy#7(-s)k@3wB3 zQ=sd*N04KTp|95I$dgq|uBVdFbPu<HzTv%h9`jA+S%>cVqj`;mV)nAeH}qFSrZ*^U zkxuaj2J|fXR&&JM1Fzd0S6`YmbcHewfGbOASPlAmhzQ@4uRofYhn<KC9}<~<yC629 z);?6DziQ3>UG~EqX!KZHmYHA-jbHxJ+V3u%<P?CVr<&oez&F<Kx||+<Vl->+P*rCa z%47b=V_}DsXJwo$_kn~xpcb5L&aF%yntcM|z{-7c3&8HuZjX;|oRnDVbmLB_LL6cc z76S8Ow;qD!)7<>$=5hFoEf<5A)N)dTm$Ao59;?lfnAqqr5|L7)-PY{v*|b@QPlL}$ zv(mN>L))(0cv#or##&Q`Phv$|e@?1i>@BkBuYSA=-<gG-Iu7KeI(c<zIzuZ;S2sKA z{USXwq*`0*+8!?e6fi71T*J+!^dJe*+LCNXSIM_MomD%Sf~Kx3u?>BpiTH;6LmdM6 z9zDaBd{kE%%DcjS>t2cH{4n+x#$`^EoEWR%eO_z}#NLsy8?KPh@WW`@J3R|?>YZ=Q z+Vv4Bhre%j=HfuQmGQokwY%$L^XIR}-1>6e2kJ+Sh}8i0osttxN};D-g^i;~SB5~{ zyT_8pEy1GDJ1cSOxt!3__3lPrDW0#qWII;&zcM#!E%X<^8WH!~kUeSoc;%mGxqc+K zLN13{!AZjCG}WXe=roaXVKkd_lTdpBd@2~Aa9h^qFSO;2VEnYC_be=+X$ZWZ%e?n9 zSJ+`sV9B*tInknZN^z-0LzRFSP{HkI0dJ`uNJJPN95`Doey+4CtV$D+g5P8|cvzJ@ zYr1*Z#Z&Y>v_FXqM|9!$p1K?Zf$-VDP>XLDEPb}c9O4JC)`-&yT(3A_*W+CTT->ah zQ|0b$-S6N385RZ13YHp1qVapn;~jqYT&KdSvk#8jy}^MX46yr$<7>rll#k&C4IZ_p zs7_x~Je!jVh2fdTgKQ~J_JfhvehYb&4M*8=hMTJ?iw2i^cut&BF3h*)IE}p1HPTp% z3_U$?o?j&;j$`M8ZCiKESo&|$)@PP2Op<Yq7L;NP<_ZlY9V=caFKL_|^`m~ATKJs2 z^_FytyLfj({i0awZfb(C_4#RVa5Jl#s7LTAYVc|?`@rNXA2yl0oJXB2Sn&4?+nINE z1`Ra^)5(QK+PR*)R(g)~iBWBPgQ7b+-S}5GZ!zgI#H{vcZhmSr6ix+Tl_>!h0WNfl zOBz;Di9<)X-{5wbTBo$&#wyeG%_o>oT;#9UhmqrjlcC_ffwoC0J|#(gVJOfdO8>}z z(c{DQ3+yngz3a9NI{x3KHiO-|?|C+(iS_++)_=`n0~EnqgPVH4reZ_U(^YJq`7+Zp zXigmHLt~=E41SW^X-Ivgig?oRISQBju!S&JJm2Yy0Ku_`au^y;#^Jq((!#7PkttZ_ zp2>4$+DgwuYAkfAeZ~)T$->Ajrs8Y|FdGX7^j}vD4%Y6MI(%L#!RGy=+#t5<B%~xx zP3~ddmlkO`%1QvzyqQCHBy|<ITgHO6K3x}>`V5wd(eZ1j%RJ<_(rSp2GMO;h;1|~u z+V7cJnheD>8G3bRmfAEt)%+Wmyx8P9^$w}fpG#SnblZT<I{O2^gIWu%QL4^_;OhXG zhnH9PVwmzkIsa~Ioqe<}Pi9@y*S2g*Op^CSM*6jaly2T!E{!zr=7Tq^4~EVcJfuFN z!JM%pfk+~jJv7>Ar}$3T=4}40z<VG93_hgvdPC3?)`p9i>&Q%cNlE(fu+(g&N}CXo zI<n^g){ZZBN2iX9rnhXD)dRrV9q$asc$_`|V<5`L<G#aHVSQZ0qm#uyB@lD--Gkk@ zU5vQL&i%}*{D2?~D{{81SjtFh|10rwp@7LgdE8e{Tl3wkX^*xHA(j1^HM(!Jg{ljr zMvrUWI0ibkWON0XX}M=|U#bi|lsf;k0{*%Shi9j22CSg5c%80xD9Ak|U{)eBSoYOD zJ`OY2r7xH&KSr&^a!*39D#|8HatRT>SYu5LSx8a-qiUVvHaYj)#&FfFEv69P78Yih zvsBBldPh85wM6SMPj}IL?x(Lyvs)W_S`01>J#yetT$T@Y3^_b_22@Vg-v%}LP0ydk zwd%nSuiFS3Ue`)~Ao)ThFCNfv)m6Fw0)ROOH(=Q99Cw$=0D)lB-B+&5=(<2c#H>mO zVC+Wa<hE{w!6c{Fm1Up?ne_CEie>`5Hn!W#2&|n%9lat}Jq<mHq!gCLXGp-p3nD?@ zH?z#dt{-B(7po4)-3HI&7m$;ligMUr&k2V2xSZcU*9lgj^$=eb-d)rk8aqTrZPPZM zT9(oISgTBujf0Mf$L>RFyh6#aut_z{uwQJlnoYUZmXx(&WBA#NZ)VxF{Bk;lD>;1I z_<1Gkz~v7IX`a@Nn)5TQ3w|Pl?Q48e%`(qdg7#}Ey7}A9#4g_rwzu~G2)clAEU%<0 zZdUi*k{9)MSv@TSr~+$Cd+4|Gb5e5fOH$P0j{gk!+)B<k2zCu9>%2Oub-3)zYa}it z{SBHa3y}SI&Z2gmme;N4#`*+>J2?;w;4FH0X*CsCd2FZ2EQrwn=D>w|R6L+j&`app zmz@0KtPbkA-NYD3VsRr{tHys3L4TnN#DqlYN(fgtHI<iV$Ej*;oIUW-Fe4N`oAyk! z^Om#T9b)<`7J;>MOs*8X$J*7fxN$fgtmMH7b1Fp`Fq*3J(yB&p3bF$xu}_ASXXY=r zQL!BWtLv$4|Ge_GY!mwk+}Lm>W+L<8<<wX!fVDehw}8jjSno>Zu>8!Fr`~QH?4hdV zo4m1(zBPX#fo*!4VO+i*(s;=`_maN=elC)NYL%A4O<rjuo%&rmW`*B$$$}*-X*Yd& zXD&%MLPX7vdn(OLmnz`0{ZVbHIWuI#c`jE{Xy9tPV_5NYz~N!1U#K9s1ZEcZSwXm_ z((N&^<Kg1Qj{M!F^;df16_?>jUk?}mNe|Y!-8;DOfak4(+di7XL>Mj6*g!yMRTwXR z%GD+2;apd4?IrA{Mt6U2Cxm^c-+c-KzbtLjp-@=A$GKh&P^YAT^H_=p3Y|m!x^YN3 zBr0<E@K6uzIDJ4rTF7r#y2CY5MLxI13W%p>ppUCRLxke;AxZ<<^*`-5xBP-NAn~7_ zT;nY{9_JXV^-Pa?xX~$oto`Yz6c*r=F4Z+~SX*dKmF&&$0p)czwf=m*qCU+>YE)!W z_uIpKBh&S%$A@q+k1m#ci*eiBU;}VNMAfs+coMBKjSu>#4yRM>;hbjBDkWo&VPSg* z=TYpAooJGDh606EvB|HzuQb<kyyR0LbGh2<k)kF0d(rgcEvd1tzlxBRCYToDYAtaM zj9KY!LjAKh3*HI{{*>bDuT;YPbF{R|8P~e)XtFa%oNQxzm!OI(JV72DOT25Q@P|F* z(2l&}vszA*#8}Gw;Q_<2^iC<I*5MfzcT^zOz6HSLwEJ>QaEGUI;pZm3gUC>PzEH^R zH_cC<HISb!P79p-3Q>_C8r~*@qL2wo5Ik1JR6dX08HW+|k(|jAkDrw#9+wy6N}_~* zlRw(`);0X-XK%FmFqCE*866V_=O(ANMKuqmwD2<NAdqykT6(YR6b$pT^F>dJy`BKp zvEQ_&fi`awi^YKaRm}M8Q`h1t9*}Q4xV*SaZipVa7K{2KK}n^g?6-xk@(dXfZbwJw zG*$mu4JFp~q&x{HHa{cRWh=w1yy_5*8N^Iyjq%OT-5PL6ab1?eqw%`#oaz})jg*6P z_?MloedgJ`YY>$_Td5%GA?(<Qw@TK<n|`9k*&n>PpNu>Fdvkr^<K52zeL!zm!cTQ^ zNEgn@nZE`-ygT)M$Slez4Z!#idCZyQ6AZ+PO&B${^t?IgPtskyzDz2y^0bRS<__8+ zKDAMG&&U4V8D^_w)VE7#w<fh-FLLD^=wrCIybb5|-;OpIHXkYL<=(E^kaL)MvF?8E z$OUTzHtKHc&eHt?;PeFJ4L!?z7Eh}0=K>Y<nGJAa1V8mH@9}Nyy8wXoOYjIxxA1wI zKD8nc;(e23=|_<69Il-%7<iTtu{Y6EAhPp2Bs3+t2if5Pbq1rWFcAdSj!{(rJTogu z=4Q@}sEWjb-Ud<i_LnrJEA^?jA_!z8s;~dS&OLwl7e5F7pZ@NZf@(*M6moM~kfaQh zyUI4u5ixdGl(MvY#}fp<_;5j;pk6Sj48Yx7EMyGX^OiD$51!awTruz?bvjZ?t?$<# zc(3k?;)YF|a0;k-z%ONA;3IHql^szMdbH@8dXbC_RQa()NJrjTwG0>zIFr(?>EDvZ zHJIxFieBjwK#a4^@4?!H@Kr52eV|{>dx`w^&rkGFN!K5wOwKGI(=Xp}9%b|5*G#u@ zDESfk5Abil8+e&sxRb6of`5oPLL~XDJ<L?#k9~5m{72$$MIr>M4d2WY*8W(k|0(@q zA6RWZM4Q2CYgv#$5G&gK)<n>=Zxk+(IWh5mJ$IVIOgglk-_Tgy216E2<CSH^d)+tJ zxlu}8qjlCt$H>*qpGsl<a?th;8zW8WiuIntJVvI691Z;geGNVY;Jyj<7>L4GK}kDB zef>S+;l}Z*WIeLOT^E0IWGQmH2fpPaC0~^<l)4uEu%Pjxh>3~)qyzg9ynM=B5%^YF z{7{^lvw7x=v~-ZW)9)TTJ*-E#j|i}T2pRB5>ZgQNCVg3{W~f<tLw9Tx%D8Et%+0Xq z@M?Eh7#O2n(KFc8D6Qt}ksMX~cQg`GRX&{L2CO6>pic;RGcI%5%*|=NJ6;5(MQeJo zpIv#rCgkXTQR*zYDoh&Z)aa=43xFXOMBoENBMDYvthxu|)iRD8c=L<3DW`Mtggk_6 za=>QbhG=XTXnBLGHp{-V0^_TLSW*K@VV8&?JH4LGk1BNdzUF54{J{*`;$K&3%p*(b z{B2ex1Xt^Kp_z~mCq=#MZol|UVq2S#4RW+yGZ$zH7kjqaqAV&p2fp&dl^eMurryld zNL=SGDRwnA{zw%GRG34kH%+ix8Z9KO^Q?TkXr(K-oz%n3EL}+gpPSH;Y0%DiuNf!K zQ%FfAGT3;6!I5W>Ji5UEWFNsWxRUCnW|M>K6%_Rt!Rw<1?<7T42`S~%&Cd|A|7>)b zh#Otru7GfO-+61!3k_m?-nVLR)LAlkbB(qc1QoSA7*k9|<1EQu-6Z`nYQ2+tm=dPU zjq4nDR0dFzS{RLF488FojHZ+84UKm)qARq(qnbW~#Taz%dd_#64r<eK-~uE_31Bx= zX*^nEE!nF>eBiai|8!~o>%6Tw7BAbqjq|B3?h<>a{W+LlxtK=W?R15~IL3C5%i$Ov z%9|k&x?!Fdtp510Kq@?pa7o^BCB%vw`2ITvh!u=}_89o~KQh?Va5Q0JqR;;1x<Cn< zr0bP(&jG}I1FgC}?c!6X`<0`j{6r~m-N^s4ddnSY&PTgvp266Oda-7Eehv9XbIP#B z^F~q!v890<9b9iyrf+D1iHz@OrUb1P%Zkj(-Ac8yvIwQ`&61n6zZvwpAT0Qb0(`-r ztE>BP_C+sw^d{uvT<!MRHAk%VsX80PD4%Gt6zAE3Cf%>Pd?Q}=A%<razcv$gr7X7Q zKNyT|uZ+ENS=5}Y&r9Yhrl58zS1xCS$t!$Rqbhu|=|=->1NdGe1x+?Ujg)8~Po7c# z@n?WlqVWMZEUsJgxycj(_7IFx*+UcKhzusq+#V)wrRq%uY+9>G=Y}|?6IIzlwZC_B zI9?Y<05C#E`ukBm1FK}`+1|iOU~?m41*v@TXx-&ctEi}sfd1xGBB5hqy{Z}Qtu3-7 zSWA*im;ZtXhV@0mvhcwESV~cN?+Ps_5nB{iK&~hd_wM$&+PYMJZ^9arud95pcurNn zd-BaY*puw3Pwe~|!_m8vIr-gD+r%2L(k&<pPz(_)1e?9x4pV;~CL<vkd<A*bB1T3y z1AB#!{-8fU9$TEi+%#JazNC{ejg4U$4wKnTzbguh%lx8YE|r|s9$ydz6;I4D&iy`# zj<Dj(pMDilWCKLg?nBDIwOZ0nnX_LE@^7o#dhhc;u%Nl+X)7}ccQwfjb$JgGp+uKz zAu8{VDjeyyEx3IuD*q($$dKW{1FF)^q0|@6fNwfZhoN5MxGLYUnT{{oVTJ3n#s)^` zjQ~D|ZIpTpNdqA>Ih<F_mFnTP7+GGQYzqmSS99j4El@^e*;t4~XJJL>*&dc?IV6zr z%)K0!*?-5}qjH>d4-i~hF}Z1o<%^uvrs|zL56ZhP5Mgy_OHmd+#<CuZ0-+I{y+A5_ z2GhP=aV^~nC)RP{EJ?+_<>S7QX^Wt(votxX1$Fyy0!R*m5B)ud{k*zG7xSG(T27lY zFrxtVw^Y1`B~QSxUFNNX>a1N4#AX*@7fd&J4F{~_dNH0U)rDaL^m^*^XD<|IZz>Vq z4Zk~)gPuc)xp4*>5SN8sm^bn&n<^2^RNE}~0=+LHS+uL=6B84GW*c;*FB5ji`69Q8 z_qWrk)f4cq_w4htgtsv)If8ymxfGfy^=8-`!<4k*A|FdgVNeC{O-~azXt3H;3l`xB zt&dz#>oufBsu8Bdk6P)Q@0(do<clvp*4r`r4$w}q2%Us49M4I2PqA?f-wZ5?d#ro> ztWkm<5wb*Q4``2db12Ke&V65?Dv=SyJPgMk-j7q4IUbg{J?3Qf1{J;`KLO<OJBW}N zZTmQc<~=lf7D^yNz%x*3Z|5wTs<(Z{JiqyBMk5e3bF$*ZF}#??ROH29@x}+391t)U zUIMsk^tY3g-~nCA6n-)OUVZ=-@hfO6!f$aV>wG@N?I`atW+-);$OLKO0qZx=`)7*X z;f5P*(ShymvVx4uN-=uVIp2L^k!AA?^A<Vv2SDiuH=#J)RHp1SL5A(XMm{rj7I4V6 z%%YB{;0|zGJ1%2}O`FyD$(c+pfAUrBZWNewWATgawlFi7clPCq#%**1k&J2Z4{*IL zUNgTZtl%gQm9-*s8$%QJ{axH6>g`T$FOiOHcstJ#;f2};`TVxO)1h)UomEZdG#l@S z4yo2lVd|jRcx?d0rpFe?U+BeC$Yjy4p#BZSjFsK+#O@IqtZz6uD@Fr!^FY^a`Xe6z z4W#PH5GSuHyO1WZL)GnszEbIk%Az1Iy2<E%`zEu2*#ucMoAssMx0ATi1HWvxYsaj4 zE&V|pb#t1+MNV`(b>SA!SCDefZwKl4c3dV3{A5hKlAJ0trw9r;-*u2p+G-@NJjYwf z&jc&>ET2h&PHI*`3w?4hdDk=n#rR$hNR7dIU2UtN8^4?GwLozF&1q+7y-oG2yFffk zuI%RChZV*LsW0PK9K2mcGxco=ZUm{DcwC?XvI#Glj$J#yv~fyDpz_Pjna5}NOFTf# zm>S&X_Q)3mFE}@Do7&|Hf7G!e1sbEdyjlwz;aGG2^hU(QClg&Z#bPEomXz^GxK}OC zSPdOK6(qj=+)hE~I!`F;M;8uyW9kCF`y#~~XieRKiV(OD-~Hts8t+;?R1WInUVi!p zdPx-=l5ptBM;TyiY#WtEUOHJ94OKMv`OI90-MZ=}TZuK8ivpWU6*AheFW6SK$P!Ia zA37=Lz#Ci+lu!!v2H6Q4|B=^TP3Tpb4LbT*V_nn4{UicDh5;r5!>=HVbAr_M3}`Sl zZsP>{M=%Pk<q&|Sm<8oWtZxb|U(h*(${4ZDEdtdT1z7MEJ>YL%0DLCl%CJS3{852Y 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%0D`q-G#LQhx4%k32+4f%(Vy_Y>46b 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%0DNL=uV~l`5|RXYpi5d8*z!`422_3VdjZ=+U(ZM- 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%0De=&BDvPH)Ec(sQQe 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/doc/plugin_framework.h b/krb5-1-6/src/windows/identity/doc/plugin_framework.h new file mode 100644 index 000000000..cfe40e458 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/plugin_framework.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! +\page pi_framework Plug-in Framework + +\section pi_fw_pnm Introduction to Plug-ins, Modules and Messages + +\subsection pi_fw_pnm_p Plug-ins + +A plug-in is a package that implements a defined API that will perform +credentials management or related tasks on behalf of Network Identity +Manager. + +The Network Identity Manager architecture is message based. The core +of each plug-in is a message handler. The plug-in integrates with the +application by subscribing to, and handling specific types of +messages. + +The plug-in message handler runs in its own thread and receive +asynchronous messages. There are exceptions, such as when one plug-in +requires another plug-in to handle a specific message before it can +handle the message. In addition, during certain operations that +require user interaction, each plug-in can delegate code that will run +in the main application thread (the user interface thread) to process +window messages. + +\subsection pi_fw_pnw_m Modules + +One or more plug-ins can be bundled together into a module. A module +is a dynamically loadable library which exports a specific set of +callbacks. Currently, the only two required callbacks for a module +are : + +- init_module(), and +- exit_module() + +For more information about how a module is structured, see \ref +pi_structure . + +\subsection pi_fw_pnm_msg Messages and Message Queues + +An integral part of this framework is the messaging system. Most of +the communication between the Network Identity Manager application and +plug-ins is conducted through passing messages. + +A message has a type and subtype and is denoted in this documentation +as \< \e message_type, \e message_subtype\>. For example, when a +plug-in is loaded, the first message it receives is \< ::KMSG_SYSTEM, +::KMSG_SYSTEM_INIT \>. + +Each thread in the application, specially threads that were created +for individual plug-in messages handlers, has an associated message +queue that stores and manages all the messages that have been sent to +subscribers in that thread. + +The most common recipient of a message is a message callback function +(see ::kmq_callback_t ). The message handler for a plug-in is one such +example. A message callback function receives the message type, +subtype and two optional parameters for the message. + +Any acceptable recipient can subscribe to broadcast messages of any +type. Once subscribed, whenever a message of that type is broadcast, +the message will get queued on the corresponding message queue. Then, +one of the dispatch functions can dispatch the message to the correct +callback function. (see ::kmq_dispatch). + +Next \subpage pi_fw_pm ... + +*/ + +/*! + +\page pi_fw_pm Module Manager + +The Module Manager is tasked with loading and unloading modules as +well as managing the plug-in message processing. + +When a module is successfully loaded, it registers one or more +plug-ins. The Module Manager creates a new thread for each of these +plug-ins. Then the initialization message to the plug-in is sent and +the message dispatch loop is started in this new thread. Having each +plug-in in a separate thread prevents one plug-in from "hanging" other +plug-ins and the user interface. + +\note For compatibility with future versions of Network Identity +Manager, a plug-in should not depend on the fact that it is running in +its own thread. + +Read more : +- \ref pi_structure + +\section pi_fw_pm_load Module Load Sequence + +When kmm_load_module() is called to load a specific module, the +following sequence of events occur: + +<ul> + + <li> + The registration information for the module is located on the + registry key \c + \\Software\\MIT\\NetIDMgr\\PluginManager\\Modules\\[ModuleName]. \see + \ref config + </li> + + <li> The module will not be loaded if one of the following conditions are + true: + + <ul> + <li> + The \c Disabled value is defined and non-zero. + </li> + + <li> + The \c FailureCount value is defined and exceeds the maximum + failure count. By default, the maximum failure count is three, + although it can be set by adding the registry value \c + ModuleMaxFailureCount in registry key \c + Software\\MIT\\NetIDMgr\\PluginManager\\Modules . + </li> + </ul> + </li> + + <li> + The \c ImagePath value from the registration information is used to + locate the module binary. If it is not an absolute path, then the + binary is located using the standard system search path starting + from the directory in which Network Identity Manager binaries are + located. + </li> + + <li> + The binary is loaded into the address space of Network Identity + Manager along with any dependencies not already loaded. + </li> + + <li> + If the Network Identity Manager core binary is signed, then the + signature is checked against the system and user certificate stores. + If this fails, the module is unloaded. See \ref pi_fw_pm_unload. + </li> + + <li> + The init_module() entry point for the loaded module is called. If + this function returns an error or if no plug-ins are registered, + then the module is immediately unloaded. See \ref pi_fw_pm_unload. + + <ul> + <li> + During processing of init_module(), if any localized resource + libraries are specified using kmm_set_locale_info(), then one of the + localized libraries will be loaded. See \ref pi_localization + </li> + + <li> + During processing of init_module(), the module registers all the + plug-ins that it is implementing by calling kmm_provide_plugin() + for each. + </li> + </ul> + </li> + + <li> + Once init_module() returns, each plug-in is initialized. The method + by which a plug-in is initialized depends on the plug-in type. The + initialization code for the plug-in may indicate that it didn't + initialize properly, in which case the plug-in is immediately + unregistered. No further calls are made to the plug-in. + </li> + + <li> + If no plug-in is successfully loaded, the module is unloaded. See + \ref pi_fw_pm_unload. + </li> +</ul> + + During normal operation, any registered plug-ins for a module can be + unloaded explicitly, or the plug-in itself may signal that it should + be unloaded. If at anytime, all the plug-ins for the module are + unloaded, then the module itself is also unloaded unless the \c + NoUnload registry value is set in the module key. + +\section pi_fw_pm_unload Unload sequence + +<ul> + <li> + For each of the plug-ins that are registered for a module, the exit + code is invoked. The method by which this happens depends on the + plug-in type. The plug-in is not given a chance to veto the + decision to unload. Each plug-in is responsible for performing + cleanup tasks, freeing resources and unsubscribing from any message + classes that it has subscribed to. + </li> + + <li> + Once all the plug-ins have been unloaded, the exit_module() entry + point is called for the module. + </li> + + <li> + If any localized resource libraries were loaded for the module, they + are unloaded. + </li> + + <li> + The module is unloaded. + </li> +</ul> + +The following diagram illustrates the relationship between modules and +plug-ins as implemented in the Kerberos 5 plug-in distributed with +Network Identity Manager. + +\image html modules_plugins_krb5.png + + */ diff --git a/krb5-1-6/src/windows/identity/doc/plugin_locale.h b/krb5-1-6/src/windows/identity/doc/plugin_locale.h new file mode 100644 index 000000000..3c6a236e6 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/plugin_locale.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! +\page pi_localization Localization + +If a module requires localized resources, it can register the +localized resource libraries with the module manager when it receives +the init_module() callback. Note that you can only register localized +resource libraries during init_module(). + +The localized resource library is global to a module. Each plug-in is +not allowed to define its own localization library, although it is +free to load and use any library as it sees fit. The module manager +does not manage these libraries for the plug-in. + +\section pi_loc_spec Specification of localized resources + +In order to register localized resource libraries, a module calls +kmm_set_locale_info(). The \a locales parameter to the function holds +a pointer to an array of ::kmm_module_locale records. Each record +specifies one language code and a filename of a library that holds the +language resources for that language. + +It is recommended that you use the LOCALE_DEF convenience macro when +defining locale records for use with kmm_set_locale_info(). This will +ensure that future changes in the API will only minimally affect your +code. For example: + +\code +kmm_module_locale my_locales[] = { +LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"english.dll", KMM_MLOC_FLAG_DEFAULT), +LOCALE_DEF(MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH), L"dutch.dll", 0), +LOCALE_DEF(MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MODERN), L"spanish.dll", 0) +}; + +int n_locales = sizeof(my_locales)/sizeof(my_locales[0]); + +... + +kmm_set_locale_info(h_module, my_locales, n_locales); + +... +\endcode + +See kmm_set_locale_info() and ::kmm_module_locale for more info. + +\section pi_loc_how Selection of localized resource library + +The module manager searches the array of ::kmm_module_locale objects +passed into the kmm_set_locale_info() function for one that matches +the current user locale (as opposed to the current system locale). A +record matches the locale if it has the same language ID. + +If a match is found, that library is selected. Otherwise, the list is +searched for one that is compatible with the current user locale. A +locale record is compatible with the user locale if the primary +language matches. + +If a match is still not found, the first record in the locale array +that has the ::KMM_MLOC_FLAG_DEFAULT flag set will be selected. + +If a match is still not found, then the kmm_set_locale_info() will +return ::KHM_ERROR_NOT_FOUND. + +\section pi_loc_usage Using localization + +The following convenience macros are available for using a module +handle to load resources from the corresponding resource library. +However, for performance reasons, it is advisable to obtain a handle +to the resource library loaded by the module manager using +kmm_get_resource_module() and then use it to access resources using +the regular WIN32 API. + +- ::kmm_LoadAccelerators +- ::kmm_LoadBitmap +- ::kmm_LoadCursor +- ::kmm_LoadIcon +- ::kmm_LoadImage +- ::kmm_LoadMenu +- ::kmm_LoadString + +*/ + + diff --git a/krb5-1-6/src/windows/identity/doc/plugin_main.h b/krb5-1-6/src/windows/identity/doc/plugin_main.h new file mode 100644 index 000000000..9542150a8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/plugin_main.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! + +\page plug-ins Network Identity Manager Modules and Plug-ins + + The Network Identity Manager application does not include any + ability to manage any specific type of credential. Instead it + exposes a framework on which plug-ins can be implemented to manage + credentials. + + Plug-ins and localization are handled by the Network Identity + Manager Module Manager API. + + The following sections describe plug-ins in detail: + + - \subpage pi_framework + - \subpage pi_pt + - \subpage pi_structure + - \subpage pi_localization +*/ + +/*! \page pi_pt Plug-in Types + +The types of plug-ins that are currently supported by Network Identity +Manager are : + +\section pi_pt_cred Credential Provider + +A credential provider plug-in essentially acts as an interface between +Network Identity Manager and some entity which defines the credentials +for the purpose of managing those credentials. + +There can be more than one credential provider in a module. + +\subsection pi_pt_cred_comm Communication + +Communication between Network Identity Manager and a credential +provider occurs through a message processor. When registering a +credential provider, the module initialization code in init_module() +specifies ::KHM_PITYPE_CRED as the \a type member and sets \a msg_proc +member to a valid message processor in the ::khm_plugin record. + +\subsection pi_pt_cred_init Initialization + +Once init_module() has completed, the module manager sends a +<::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> message to the message processor. + +For credential provider plug-ins, <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> is +guaranteed to be the first message it receives. + +The callback function should return KHM_ERROR_SUCCESS if it +initializes properly or some other value otherwise. If the return +value signals an error, then the plug-in is assumed to have failed +initialization and is immediately unloaded. + +The message processor is automatically subscribed to the following +message types: +- ::KMSG_SYSTEM +- ::KMSG_KCDB + +Although a plug-in can use the <::KMSG_SYSTEM,::KMSG_SYSTEM_INIT> +message enumerate existing credentials in the system, it should not +obtain new credentials. This is because other plug-ins that may depend +on the new credential messages may not be loaded at this time. See the +section on \ref cred_msgs for more information. + +\subsection pi_pt_cred_exit Uninitialization + +When the plug-in is to be removed, the module manager sends a +<::KMSG_SYSTEM,::KMSG_SYSTEM_EXIT> to the message processor. The +plug-in must perform any necessary shutdown operations, free up +resources and unsubscribe from any messages that it has subscribed to. + +This message is guaranteed to be the last message received by a +credentials manager plug-in if the plug-in unsubsribes from all +additional message classes that it subsribed to. + +The message types that the message processor is automatically +subscribed to (See \ref pi_pt_cred_init) do not have to be +unsubscribed from as they are automatically removed. + +\subsection pi_pt_cred_other Other Notes + +Since credential managers may receive privileged information, the +signature requirements for credential managers are specially strict. + +*/ + + diff --git a/krb5-1-6/src/windows/identity/doc/plugin_structure.h b/krb5-1-6/src/windows/identity/doc/plugin_structure.h new file mode 100644 index 000000000..68cee13e7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/plugin_structure.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! + +\page pi_structure Structure of a module + +A Network Identity Manager module is a dynamically loadable library +with a specific set of exported symbols. Each export symbol and +general notes about writing a plug-in module are documented below. + +\section pi_str_reg Registration and Version Information + +[TODO] + +\section pi_str_init Initialization + +Do not use DllMain or other system specific callback routines to +perform intilization tasks other than creating mutexes, initializing +thread local storage and other tasks that must be performed at that +stage. Specifically, do not call any Network Identity Manager API functions from +within DllMain. + +\section pi_str_cb Callbacks + +The callbacks that must be implemented by a module are: + +- init_module() +- exit_module() + + */ diff --git a/krb5-1-6/src/windows/identity/doc/stylesheet.css b/krb5-1-6/src/windows/identity/doc/stylesheet.css new file mode 100644 index 000000000..f1183ee37 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/stylesheet.css @@ -0,0 +1,387 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 160%; + border-bottom: 1px solid #88b7c8; + margin-bottom: 1em; + padding-top: 0.5em; + padding-bottom: 0.5em; + background-color: #e8eef2; +} +H2 { + margin-top: 1em; + font-size: 120%; + padding: 0.5em; + background-color: #f0f0f0; + border-bottom: 1px solid #888888; +} +H3 { + font-size: 100%; +} + +H4 { + font-size: 100%; +} + +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { background: #e8eef2; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; + border-color: #88b7c8; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; +} +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eef3f5; + border-width: 1px; + border-style: solid; + border-color: #dedeee; + -moz-border-radius: 8px 8px 8px 8px; +} +.memname { + white-space: nowrap; + font-weight: bold; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #d5e1e8; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #84b0c7; + font-weight: bold; + -moz-border-radius: 8px 8px 8px 8px; +} +.paramkey { + text-align: right; +} +.paramtype { + white-space: nowrap; +} +.paramname { + color: #602020; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +.directory { font-size: 9pt; font-weight: bold; } +.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } +.directory > h3 { margin-top: 0; } +.directory p { margin: 0px; white-space: nowrap; } +.directory div { display: none; margin: 0px; } +.directory img { vertical-align: -30%; } + +DL.note { + background-color: #eeeeee; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #bbbbbb; + -moz-border-radius: 4px 4px 4px 4px; +} + +DL.note DT { + font-size: 75%; +} + diff --git a/krb5-1-6/src/windows/identity/doc/ui_actions.h b/krb5-1-6/src/windows/identity/doc/ui_actions.h new file mode 100644 index 000000000..04f9aa6f2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/ui_actions.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page khui_actions Actions + + */ diff --git a/krb5-1-6/src/windows/identity/doc/ui_context.h b/krb5-1-6/src/windows/identity/doc/ui_context.h new file mode 100644 index 000000000..9799b5c4a --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/ui_context.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page khui_context Contexts + + \section khui_context_contents Contents + + - \ref khui_context_intro "Introduction" + - \subpage khui_context_using + + \section khui_context_intro Introduction + + Several ::KMSG_CRED messages and many messages depend on the + selections that the user has made on the user interface. The UI + context functions and data structures provide access to this + information. + + The Network Identity Manager user interface presents an outline view of all the + credentials that were provided by credentials providers. This + view consists of headers representing the outline levels and rows + representing individual credentials. + + Users can make multiple selections of credentials or headers from + this view. If all the credentials and subheaders under a + particular outline level are selected, then the header itself is + automatically selected. There may be multiple disjointed + selections of headers and credentials. + + In addition, the current cursor position also acts as a selector. + The credential or header under the cursor may not actually be + selected. The cursor is not the mouse pointer, but the focus + rectangle that may be moved either using the keyboard or by + clicking on a credential or header. + + Thus there are two independent groups of selections: + + - Credentials and headers which are in a selected state at some + specific point in time (the <b>current selection</b>). + + - The current credential or selection which the cursor is on (the + <b>cursor selection</b>). + + There are a few notes on how credentials are selected: + + - An "empty" header (a header that does not contain any credential + rows) does not appear in a UI context. However they can appear + as the current cursor context. + + - At its current implementation, cursor selections of identity, + credential type, and individual credentials are treated as + special cases since they are the most common. + + How the UI context is used when processing a specific action or + message depends on the action or message. If an action operates + on a group of credentials, then the current selection may be used, + and on the other hand if an action or message relates to just one + credential, identity or credential type is invoked, then the + cursor selection is invoked. + + For example, double-clicking a credential, or right clicking and + selecting 'Properties' from the context menu launches the property + window for a credential. This operates on the cursor selection + since that reflects where the user double clicked. However, + choosing 'Destroy' from the context menu invokes a command that + can be applied to a group of credential, and hence uses the + current selection. + + Next: \ref khui_context_using "Using Contexts" + */ + +/*! \page khui_context_using Using Contexts + + \section khui_context_using_1 Obtaining the context + + Typically, messages sent by actions that rely on UI context will + obtain and store the context in a location that is accessible to + the handlers of the message. + + If a plug-in needs to obtain the UI context, it should do so by + calling khui_context_get() and passing in a pointer to a + ::khui_action_context structure. + + Once obtained, the contents of the ::khui_action_context structure + should be considered read-only. When the plug-in is done with the + structure, it should call ::khui_context_release(). This cleans + up any additional memory allocated for storing the context as well + as releasing all the objects that were referenced from the + context. + + \section khui_context_sel_ctx Selection context + + The selection context is specified in the ::khui_action_context + structure in the \a sel_creds and \a n_sel_creds fields. These + combined provide an array of handles to credentials which are + selected. + + \note If \a n_sel_creds is zero, then \a sel_creds may be NULL. + + \section khui_context_cur_ctx Cursor context + + The scope of the cursor context is specified in the \a scope field + of the ::khui_action_context strucutre. The scope can be one of: + + - ::KHUI_SCOPE_NONE + - ::KHUI_SCOPE_IDENT + - ::KHUI_SCOPE_CREDTYPE + - ::KHUI_SCOPE_GROUP + - ::KHUI_SCOPE_CRED + + Depending on the scope, several other members of the strucre may + also be set. + + In general, the cursor context can be a single credential or an + entire outline level. Unlike the selection context, since this + specifies a single point of selection it can not be disjointed. + + The contents of the \a identity, \a cred_type, \a cred, \a headers + and \a n_headers are described in the documentation of each of the + scope values above. + + \subsection khui_context_sel_ctx_grp KHUI_SCOPE_GROUP + + The ::KHUI_SCOPE_GROUP scope is the generic scope which describes + a cursor selection that can not be simplified into any other + scope. + + In this case, the selection is described by an array of + ::khui_header elements each of which specify a criterion for + narrowing down the selection of credentials. The ::khui_header + structure specifies an attribute in the \a attr_id field and a + value in the \a data and \a cb_data fields. The credentials that + are selected are those in the root credential set whose repective + attributes contain the values specified in each of the + ::khui_header elements. + + For example, the following selection: + + \image html credview-select-outline.jpg + + will result in the following header specification: + + \code + ctx.n_headers = 3; + + ctx.headers[0].attr_id = KCDB_ATTR_LOCATION; + ctx.headers[0].data = L"grailauth@KHMTEST"; + ctx.headers[0].cb_data = sizeof(L"grailauth@KHMTEST"); + + ctx.headers[1].attr_id = KCDB_ATTR_ID; + ctx.headers[1].data = &handle_to_identity; + ctx.headers[1].cb_data = sizeof(khm_handle); + + ctx.headers[2].attr_id = KCDB_ATTR_TYPE; + ctx.headers[2].data = &kerberos_5_credtype; + ctx.headers[2].cb_data = sizeof(khm_int32); + \endcode + + \note The attribute that is used to specify the header is not the + display attribute, but the canonical attribute. For example, + in the above, the second header was actually + KCDB_ATTR_ID_NAME. But KCDB_ATTR_ID was used since that is + the canonical source for KCDB_ATTR_ID_NAME. See ::kcdb_attrib + for more information on canonical attributes. +*/ diff --git a/krb5-1-6/src/windows/identity/doc/ui_main.h b/krb5-1-6/src/windows/identity/doc/ui_main.h new file mode 100644 index 000000000..ae6700847 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/ui_main.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page khui User Interface Topics + + \section khui_contents Contents + + - \subpage khui_actions + - \subpage khui_menus + - \subpage khui_context + - \subpage khui_htwnd + */ diff --git a/krb5-1-6/src/windows/identity/doc/ui_menus.h b/krb5-1-6/src/windows/identity/doc/ui_menus.h new file mode 100644 index 000000000..e46ee0840 --- /dev/null +++ b/krb5-1-6/src/windows/identity/doc/ui_menus.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/*! \page khui_menus Menus + + */ diff --git a/krb5-1-6/src/windows/identity/help/Index.hhk b/krb5-1-6/src/windows/identity/help/Index.hhk new file mode 100644 index 000000000..c0ba08a9a --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/Index.hhk @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<HTML> +<HEAD> +<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1"> +<!-- Sitemap 1.0 --> +</HEAD><BODY> +<UL> +</UL> +</BODY></HTML> diff --git a/krb5-1-6/src/windows/identity/help/Makefile b/krb5-1-6/src/windows/identity/help/Makefile new file mode 100644 index 000000000..8838bbd0d --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=help +!include <..\config\Makefile.w32> + +CHMFILE=$(BINDIR)\netidmgr.chm + +INCFILES=$(INCDIR)\khhelp.h + +all: mkdirs $(CHMFILE) $(INCFILES) + +$(CHMFILE): netidmgr.hhp + -$(HHC) netidmgr.hhp + $(CP) netidmgr.chm $(CHMFILE) + +clean:: + if exist ..\obj $(RM) $(INCFILES) + if exist netidmgr.chm $(RM) netidmgr.chm diff --git a/krb5-1-6/src/windows/identity/help/html/about_netidmgr.htm b/krb5-1-6/src/windows/identity/help/html/about_netidmgr.htm new file mode 100644 index 000000000..440831606 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/about_netidmgr.htm @@ -0,0 +1,57 @@ +<html> + +<head> +<title>About Network Identity Manager</title> +<meta name="description" content="About NetIDMgr"> +<meta name="keywords" content> +<link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> + +<body> + +<h1>About Network Identity Manager</h1> +<p>This is strictly an informative page about the origins of Network Identity Manager. +</p> +<h3>In the beginning</h3> +<p>Network Identity Manager was conceived as an identity management solution to +make up for the shortcomings of Leash32 (distributed with MIT Kerberos for Windows) +and AFSCreds (distributed with OpenAFS). </p> +<p>The work started as Unified Credentials Manager, a final project for the MIT +course 6.831 : User Interface Design and Implementation, taught by +<a href="http://people.csail.mit.edu/rcm/">Professor Rob Miller</a>. By the time +actual code was written, it was named Khimaira (which was later changed to Network +Identity Manager around October, 2005). Traces of the name Khimaira might still +exist in the source code. </p> +<p><a href="http://workshop.openafs.org/afsbpw05/talks/khimaira.html">Khimaira: +A Unified Interface for AFS and Kerberos</a> was presented at the +<a href="http://workshop.openafs.org/afsbpw05/">AFS and +Kerberos Best Practices Workshop 2005</a>. </p> +<p>A second talk, +<a href="http://workshop.openafs.org/afsbpw06/talks/asanka.html">Developing +plug-ins for Network Identity Manager</a>, was presented at +<a href="http://workshop.openafs.org/afsbpw06/">AFS and Kerberos Best Practice +Workshop 2006</a>.</p> +<p>The development of Network Identity Manager has been financially supported +(in alphabetical order) by <a href="http://www.fnal.gov/">Fermi National +Accelerator Laboratory</a>, +<a href="http://web.mit.edu">MIT</a> <a href="http://web.mit.edu/ist/">Information +Services and Technology</a>, <a href="http://www.jpl.nasa.gov">NASA Jet Propulsion +Laboratory</a>, <a href="http://www.secure-endpoints.com">Secure Endpoints Inc.</a>, +and <a href="http://www.stanford.edu/">Stanford University</a>. +</p> +<h3>Design</h3> +<p>A plug-in based architecture was chosen so that support for additional credential +types and features could be added without making changes to the mainline code. In +addition to making the application easily extensible, this also allows the AFS plug-in +to be maintained within the OpenAFS code base and separates the code supporting +Kerberos v5 and Kerberos v4 permitting Kerberos v4 to be easily removed from the +Kerberos for Windows distribution. Furthermore, it is anticipated that this would encourage +third party developers to develop plug-ins for Network Identity Manager.&nbsp; +As of September 2007, a Kerberized Certificate Authority credential provider and +a Grid credential provider are available from third parties.</p> +<p>More information about the concepts used in the design of Network Identity Manager +can be found <a href="concepts.htm">here</a>. </p> + +</body> + +</html> diff --git a/krb5-1-6/src/windows/identity/help/html/act_chpw.htm b/krb5-1-6/src/windows/identity/help/html/act_chpw.htm new file mode 100644 index 000000000..a68f73336 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/act_chpw.htm @@ -0,0 +1,35 @@ +<html> +<head> + <title>Network Identity Manager - Change Password</title> + <meta name="description" content="change password"> + <meta name="keywords" content="change password dialog"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> + + <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Changing Passwords"> +</OBJECT> +</head> +<body> + +<h1>Network Identity Manager - Change Password</h1> + +<p>The change password dialog can be invoked from the <a +href="menu_credential.htm">Credentials</a> menu. This is used to +change the password for the primary credentials provider (currently +Kerberos v5). +</p> +<p><img border="0" src="images/screen_chng_pwd.png" width="456" height="244"></p> + +<p>For the default identity provider (Kerberos v5), there are two input +boxes to specify the identity for which the password is to be changed. +The identity uniquely maps to the Kerberos principal of the same name. +Then the current password must be entered along with the new password +twice. +</p> + +<p>Note that currently, when the password for an identity is being +changed, only the associated Kerberos v5 password is changed. +</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/act_destroy_creds.htm b/krb5-1-6/src/windows/identity/help/html/act_destroy_creds.htm new file mode 100644 index 000000000..196631bc9 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/act_destroy_creds.htm @@ -0,0 +1,36 @@ +<html> +<head> + <title>Network Identity Manager - Destroy Credentials</title> + <meta name="description" content="Destroy Credentials"> + <meta name="keywords" content="destroy credentials"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Destroying Credentials"> +<param name="Keyword" value="Ctrl + D"> +<param name="Keyword" value="Delete key"> +</OBJECT></head> +<body> + +<h1>Network Identity Manager - Destroy Credentials</h1> + +<p>This action will attempt to destroy the credentials that are +currently selected in the credentials window. +</p> + +<p>In some cases, you may need to select all the credentials of a +specific type for the delete operation to succeed. This happens when +the credentials provider does not support deleting individual +credentials, but supports deleting all the credentials stored in one +specific location. +</p> + +<p>The action can be invoked by selecting the credentials and then +pressing the <span class="pre">Delete</span> key or by pressing <span +class="pre">Ctrl + D</span>. You can also select the <span +class="pre">Delete credentials</span> action from the context menu +(available via right-clicking inside the credentials window) or the +credentials menu. +</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/act_import_creds.htm b/krb5-1-6/src/windows/identity/help/html/act_import_creds.htm new file mode 100644 index 000000000..c465c060d --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/act_import_creds.htm @@ -0,0 +1,31 @@ +<html> +<head> + <title>Network Identity Manager - Import Credentials</title> + <meta name="description" content="Import Credentials"> + <meta name="keywords" content="Import Credentials"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> + +<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Importing Credentials"> +<param name="Keyword" value="Ctrl + I"> +<param name="Keyword" value="MSLSA"> +</OBJECT></head> +<body> + +<h1>Network Identity Manager - Import Credentials</h1> + +<p>Allows you to import credentials from the Microsoft Windows LSA credentials +cache. Currently, the only credentials provider that supports +importing is Kerberos v5. +</p> + +<p>This action can be invoked via the <a +href="menu_credential.htm">Credentials</a> menu or by pressing <span +class="pre">Ctrl + I</span>. In addition, the Kerberos v5 +configuration pane accessible via the <a +href="menu_options.htm">Options</a> menu contain settings that +control when the importing of credentials are performed at startup. +</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/act_new_creds.htm b/krb5-1-6/src/windows/identity/help/html/act_new_creds.htm new file mode 100644 index 000000000..b329a1adf --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/act_new_creds.htm @@ -0,0 +1,118 @@ +<html> +<head> + <title>Network Identity Manager - New Credentials</title> + <meta name="description" content="obtain new credentials"> + <meta name="keywords" content="new creds"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> + + <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Obtaining New Credentials"> +<param name="Keyword" value="Ctrl + N"> +<param name="Keyword" value="New Credentials Dialog"> +<param name="Keyword" value="Kerberos v5 ticket flags"> +<param name="Keyword" value="Changing Passwords"> +<param name="Keyword" value="Obtain New Credentials at Startup"> +</OBJECT> +</head> +<body> + +<h1>a Network Identity Manager - New Credentials</h1> + +<p>The new credentials dialog can be invoked from the <a +href="menu_credential.htm">Credentials</a> menu, by typing <span +class="pre">Ctrl + N</span>, using the context menu in the credentials +window or using the context menu in the NetIDMgr icon in the system +notification area. +</p> + +<p>Once invoked, you will be presented with a dialog similar to the +following: +</p> + +<p> +<img src="images/screen_new_creds.png" alt="New credentials dialog"/> +<p class="caption">New credentials dialog with a valid identity +selected.</p> + +<p>If the Kerberos v5 identity provider is used, the dialog will ask +for a username and a realm to determine the identity for which new +credentials will be obtained for. Depending on the selected identity, +you may be required to provide a password or other form of +authentication for new credentials to be obtained. +</p> + +<p>Below the prompts is the credentials summary window. This window +provides an overview of the credentials that will be obtained when the +dialog is completed. +</p> + +<h3>Expanded view</h3> + +<p>If you click any of the credentials type hyperlinks in the +credentials summary window or select the <span class="pre">&gt;&gt;</span> button, the dialog will switch to the expanded view. +An example of this is shown below: +</p> + +<p> +<img src="images/screen_new_creds_exp.png" +alt="Expanded new credentials window" /> + +<p class="caption">Expanded view of the new credentials dialog</p> + +<p> +The expanded view provides access to additional options available for +each credential provider. For example, the Kerberos v5 credentials +provider allows you to set the lifetime of the obtained Kerberos +ticket as well as ticket flags such as <i>renewable</i> or +<i>forwardable</i>. +</p> +<p> +<i>Note that the above screenshot is +from an instance of NetIDMgr with Kerberos v5, Kerberos v4, OpenAFS and +Kerberized Certificate Authority providers with a Kerberos v5 identity provider. Actual display may be +different depending on the providers that are active.</i></p> + +<h3>Credentials summary window</h3> + +<p>The credentials summary window provides an overview of the +credentials that will be obtained after the successful completion of +the new credentials dialog. The window contains hyperlinks that will +take you to the corresponding credentials option panels where you will +be able to set additional options for each type. +</p> + +<p>If there is a problem with the selected identity, the credentials +window will display a message describing the problem. For example: +</p> + +<p> +<img src="images/screen_new_creds_err01.png" alt="Credentials summary window showing an invalid identity" /> +</p> + +<p> +The above is an example of what you would see if the provided identity +is invalid. Once the identity provider (in this case, Kerberos v5) +indicates that the identity is invalid, it will be displayed as above +along with a brief description of why the identity was found to be +invalid. Here, the Kerberos v5 identity provider is reporting that the +specified principal does not exist in the Kerberos database. +</p> + +<h3>Additional notes</h3> + +<p>The new credentials dialog can be invoked from the command line using +the <span class="pre"> -i </span> or <span class="pre"> --kinit +</span> command line option. Additionally, if you specify the <span +class="pre"> -a </span> or <span class="pre"> --autoinit </span> +command line option, the new credentials dialog will be displayed if +there are no credentials available. +</p> + +<p> +Setting the <span class="pre">Obtain new credentials at startup (if none are present)</span> option in the <span +class="pre">General</span> configuration panel causes NetIDMgr to behave as if +the <span class="pre">--autoinit</span> option is specified at each execution. +</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/act_renew_creds.htm b/krb5-1-6/src/windows/identity/help/html/act_renew_creds.htm new file mode 100644 index 000000000..a62c92fec --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/act_renew_creds.htm @@ -0,0 +1,40 @@ +<html> +<head> + <title>Network Identity Manager - Renew Credentials</title> + <meta name="description" content="Renew Credentials"> + <meta name="keywords" content="renew, credentials"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> + + <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Renewing Credentials"> +<param name="Keyword" value="Ctrl + R"> +<param name="Keyword" value="Monitor Credential Expiration"> +<param name="Keyword" value="krb524 translator"> +<param name="Keyword" value=""> +<param name="Keyword" value=""> +</OBJECT> +</head> +<body> + +<h1>Network Identity Manager - Renew Credentials</h1> + +<p>The renew credentials action can be invoked via the <a +href="">Credential</a> menu or by pressing <span class="pre">Ctrl + +R</span>. Additionally, if the <span class="pre">Monitor credential +expiration</span> option is enabled for all identities or for a +specific identity, then those credentials will be automatically +renewed whenever possible before they expire.</p> + +<p>An identity must be selected before invoking the renew credentials +action.</p> + +<p>Not all credentials can be renewed. The actual logic of renewing +the credentials is up to each credentials provider. In general, NetIDMgr will invoke each credentials provider to renew their +respective credentials. For Kerberos v5, if the initial ticket is +renewable and not expired, then it will obtain a renewed initial +ticket. For Kerberos v4, once a renewed Kerberos v5 initial ticket is +obtained, it will try to use a Krb524 translator to obtain a new +Kerberos v4 initial ticket.</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/act_set_default.htm b/krb5-1-6/src/windows/identity/help/html/act_set_default.htm new file mode 100644 index 000000000..b6628fac4 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/act_set_default.htm @@ -0,0 +1,30 @@ +<html> +<head> + <title>Network Identity Manager - Set As Default Identity</title> + <meta name="description" content="Set the default identity"> + <meta name="keywords" content="default, identity"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - Set As Default Identity</h1> + +<p> +One identity can be designated as the default identity. The default identity is the +identity used by Kerberos v5 and GSS-API based applications which use the +default Kerberos v5 credential cache and do not request the use of a network identity by name. +</p> +<p> +The following methods can be used to set an identity as the default identity:</p> +<ol> + <li>In the NetIdMgr application window, select the desired identity and + choose the <i>Credentials-&gt;Set Default </i>menu item.</li> + <li>In the NetIdMgr application window, select the desired identity, click + the right mouse button, and choose the <i>Set as default</i> menu item.</li> + <li>Click the right mouse button on the NetIdMgr notification icon.&nbsp; + Choose the desired identity on the <i>Set Default</i> sub-menu.</li> +</ol> +<p>&nbsp;</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/bugs.htm b/krb5-1-6/src/windows/identity/help/html/bugs.htm new file mode 100644 index 000000000..6fbbc140c --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/bugs.htm @@ -0,0 +1,33 @@ +<html> +<head> + <title>Network Identity Manager - Reporting Bugs</title> + <meta name="description" content="Reporting bugs and feature requests"> + <meta name="keywords" content="bugs,features"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - Reporting Bugs</h1> + +<p>If you encounter a bug in the software, please send a bug report via e-mail to +<a href="mailto:kfw-bugs@MIT.EDU" class="mail">kfw-bugs@MIT.EDU</a>. +Please include as much information as possible to assist us in reproducing the problem. +</p> + +<p><a href="mailto:kerberos@MIT.EDU" class="mail">kerberos@MIT.EDU</a> +is a mailing list set up for discussing end user Kerberos issues. It is +gatewayed to the Usenet newsgroup 'comp.protocols.kerberos'. If you +prefer to read it via mail, send a subscription request to +<a href="mailto:kerberos-request@MIT.EDU" class="mail">kerberos-request@MIT.EDU</a> +or subscribe via the web page:</p> + +<p> <a href="http://mailman.mit.edu/mailman/listinfo/kerberos" +class="external"> +http://mailman.mit.edu/mailman/listinfo/kerberos</a></p> + +<p>Information about Kerberos mailing lists can be found at <a +href="http://web.mit.edu/kerberos/mail-lists.html" +class="external">http://web.mit.edu/kerberos/mail-lists.html</a></p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/cmdline_netidmgr.htm b/krb5-1-6/src/windows/identity/help/html/cmdline_netidmgr.htm new file mode 100644 index 000000000..4e11eec90 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/cmdline_netidmgr.htm @@ -0,0 +1,50 @@ +<html> +<head> + <title>Network Identity Manager Command Line Options</title> + <meta name="description" content=""> + <meta name="keywords" content=""> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager Command Line Options</h1> +<p>Command line options for Network Identity Manager are:</p> +<table border="1" width="57%" id="table1"> + <tr> + <td width="140"><font size="1">-a or --autoinit</font></td> + <td><font size="1">Automatic Initialization of Credentials</font></td> + </tr> + <tr> + <td width="140"><font size="1">-i or --kinit</font></td> + <td><font size="1">Obtain New Credentials and then exit</font></td> + </tr> + <tr> + <td width="140"><font size="1">-d or --destroy</font></td> + <td><font size="1">Destroy Credentials belonging to the default identity + and then exit</font></td> + </tr> + <tr> + <td width="140"><font size="1">-r or --renew</font></td> + <td><font size="1">Renew all Credentials and then exit</font></td> + </tr> + <tr> + <td width="140"><font size="1">-x or --exit</font></td> + <td><font size="1">Signal the running instance of Network Identity + Manager to exit</font></td> + </tr> + <tr> + <td width="140"><font size="1">--show</font></td> + <td><font size="1">Open the Network Identity Manager application window of a running instance.</font></td> + </tr> + <tr> + <td width="140"><font size="1">--hide</font></td> + <td><font size="1">Hide the Network Identity Manager application window of a running instance.</font></td> + </tr> + <tr> + <td width="140"><font size="1">--minimize</font></td> + <td><font size="1">Open the Network Identity Manager application window in minimized mode.</font></td> + </tr> +</table> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/concept_cred_pro.htm b/krb5-1-6/src/windows/identity/help/html/concept_cred_pro.htm new file mode 100644 index 000000000..ab8f7c40e --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/concept_cred_pro.htm @@ -0,0 +1,38 @@ +<html> +<head> + <title>Network Identity Manager Concepts: Credentials Provider</title> + <meta name="description" content="NetIDMgr Concepts: Credentials Provider"> + <meta name="keywords" content="credentials provider, concepts"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager Concepts: Credentials Provider</h1> + +<p> +Network Identity Manager relies on plug-ins to provide the majority +of its functionality. A <b>credentials provider</b> is a plug-in +that manages one or more types of credentials. The responsibilities +of a credential provider are: +</p> +<ul> + <li>to maintain the list of credentials and their properties for the supported type</li> + <li>to monitor credential expiration</li> + <li>to provide the logic necessary to obtain additional credentials once the + <a href="concept_ident_pro.htm">identity provider</a> has obtained the + initial credential</li> + <li>to provide the user interface panels necessary to permit the user to + configure the credential provider</li> +</ul> + + +<p>MIT Kerberos for Windows ships with two Network Identity Manager credential +providers supporting Kerberos v5 and Kerberos v4.&nbsp; Credential providers for +the Andrew File System and the Kerberized Certificate Authority are available +separately.</p> +<p> +<img border="0" src="images/screen_config_cred_provider.png" width="542" height="393"></p> + + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/concept_credential.htm b/krb5-1-6/src/windows/identity/help/html/concept_credential.htm new file mode 100644 index 000000000..0fadbf599 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/concept_credential.htm @@ -0,0 +1,31 @@ +<html> +<head> + <title>Network Identity Manager Concepts: Credential</title> + <meta name="description" content="NetIDMgr Concepts: Credential"> + <meta name="keywords" content="credential, concepts"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager Concepts: Credential</h1> + +<p> +In Network Identity Manager, a <b>credential</b> is any digital object that can +be used by a network authentication protocol to assert a specific +<a href="concept_identity.htm">identity</a>.</p> +<p> +As of this writing, Network Identity Manager supports four different types of +credentials:</p> +<ul> + <li>Kerberos v5 tickets</li> + <li>Kerberos v4 tickets</li> + <li>AFS tokens</li> + <li>X.509 certificates issued by a Kerberized Certificate Authority</li> +</ul> +<p>Of these, only Kerberos v5 initial ticket granting tickets can be used as an +identity provider credential.</p> +<p>&nbsp;</p> + + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/concept_ident_pro.htm b/krb5-1-6/src/windows/identity/help/html/concept_ident_pro.htm new file mode 100644 index 000000000..4fca8674e --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/concept_ident_pro.htm @@ -0,0 +1,32 @@ +<html> +<head> + <title>Network Identity Manager Concepts: Identity Provider</title> + <meta name="description" content="NetIDMgr Concepts: Identity Provider"> + <meta name="keywords" content="identity provider, concepts"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager Concepts: Identity Provider</h1> + +<p> +Network Identity Manager relies on plug-ins to provide the majority +of its functionality. One of the requirements is that there be at +least one plug-in that is registered as an <strong>identity provider</strong>. The identity +provider:</p> + +<ul> + <li>defines the identity</li> + <li>provides the engine that drives the <i>Obtain New Credentials</i> dialog</li> + <li>performs the initial authentication which results in a network credential that + can be used in conjunction with subsequent credential providers</li> +</ul> + +<p>Naturally, the identity provider plug-in that is distributed with MIT Kerberos for Windows +is Kerberos v5 based and obtains Kerberos v5 ticket granting tickets as the network credential +that represents the identity.</p> +<img src="images/screen_config_ident_provider.png"> +<p></p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/concept_identity.htm b/krb5-1-6/src/windows/identity/help/html/concept_identity.htm new file mode 100644 index 000000000..ee84920bf --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/concept_identity.htm @@ -0,0 +1,35 @@ +<html> + +<head> +<title>Network Identity Manager Concepts: Identity</title> +<meta name="description" content="NetIDMgr Concepts: Identity"> +<meta name="keywords" content="identity,concepts"> +<link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> + +<body> + +<h1>Network Identity Manager Concepts: Identity</h1> +<p>While there are many approaches to defining what an identity is, as far as the +Network Identity Manager (NetIDMgr) is concerned, an identity is the unique user +identifier that is accepted by a network service. Each credential that is managed +by NetIDMgr is assumed to map to a single identity. The collection of credentials +that map to a single identity is considered to belong to that identity. </p> +<p></p> +<a name="default_identity"></a> +<h3>Default Identity</h3> +<p>The default identity is the identity that will be used by applications when a +specific identity is not requested. The Kerberos v5 plug-in will mark the +credential cache that contains the default identity as the default credentials cache +for the current logon session.</p> +<p>Most applications that implement GSS-API or Kerberos v5 authentication assume +that there is only one Kerberos v5 credential cache and one identity in use by +the user at a time.&nbsp; These applications use the default identity.&nbsp; In +general, if the application does not have a configuration option permitting the +specification of a Kerberos v5 principal, the default identity will be used.</p> +<p>&nbsp;</p> + + +</body> + +</html> diff --git a/krb5-1-6/src/windows/identity/help/html/concepts.htm b/krb5-1-6/src/windows/identity/help/html/concepts.htm new file mode 100644 index 000000000..194aeddfa --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/concepts.htm @@ -0,0 +1,48 @@ +<html> +<head> + <title>Network Identity Manager Concepts</title> + <meta name="description" content="NetIDMgr Concepts"> + <meta name="keywords" content="concepts"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager Concepts</h1> + +<p>The Network Identity Manager (NetIDMgr) organizes and manages credentials +based on how they identify the user to network services. To this end, it is assumed that each +<a href="concept_credential.htm">credential </a>will uniquely identify the user to a service as a single +<a href="concept_identity.htm">identity</a>. When using Kerberos v5 the +identity is the Kerberos principal name. +</p> + +<p>At it's core, NetIDMgr does not possess any knowledge about specific +credentials that might be available to the user or how to manage +them. It relies on several types of plug-ins to provide the +information it needs, and to carry out credentials management tasks. +One primary task is to identify and manage identities. These services +are provided by a plug-in called the <a +href="concept_ident_pro.htm">identity provider</a>. Information about +individual credentials are provided by <a +href="concept_cred_pro.htm">credential providers</a>. Other plug-ins +may extend the functionality of these plug-ins or provide additional +functionality for NetIDMgr. +</p> + +<p> +</p> + +<p>The following topics provider further details: </p> + +<ul> + <li><a href="concept_identity.htm">Identity</a></li> + + <li><a href="concept_ident_pro.htm">Identity Provider</a></li> + + <li><a href="concept_cred_pro.htm">Credentials Provider</a></li> + + <li><a href="concept_credential.htm">Credential</a></li> +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/copyright.htm b/krb5-1-6/src/windows/identity/help/html/copyright.htm new file mode 100644 index 000000000..d31417df4 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/copyright.htm @@ -0,0 +1,48 @@ +<html> +<head> + <title>Network Identity Manager - License</title> + <meta name="description" content="License agreement"> + <meta name="keywords" content="license"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - License</h1> + +<p>This software is being provided to you, the LICENSEE, by the +Massachusetts Institute of Technology (M.I.T) under the following +license. By obtaining, using and/or copying this software, you agree +that you have read, understood, and will comply with these terms and +conditions:</p> + +<p>Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee or royalty is hereby +granted, provided that you agree to comply with the following +copyright notice and statements, including the disclaimer, and that +the same appear on ALL copies of the software and documentation, +including modifications that you make for internal use or for +distribution:</p> + +<p>Copyright 1992-2007 by the Massachusetts Institute of Technology. All +rights reserved.</p> + +<p>THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS +OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not +limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF +MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE +OF THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD +PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.</p> + +<p>The name of the Massachusetts Institute of Technology or M.I.T. may +NOT be used in advertising or publicity pertaining to distribution of +the software. Title to copyright in this software and any associated +documentation shall at all times remain with M.I.T., and USER agrees +to preserve same.</p> + +<p>Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +OLC, X Window System, and Zephyr are trademarks of the Massachusetts +Institute of Technology (MIT). No commercial use of these trademarks +may be made without prior written permission of MIT.</p> + +</body> +</html> diff --git a/krb5-1-6/src/windows/identity/help/html/howdoi.htm b/krb5-1-6/src/windows/identity/help/html/howdoi.htm new file mode 100644 index 000000000..4c49e0d89 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/howdoi.htm @@ -0,0 +1,45 @@ +<html> +<head> + <title>Network Identity Manager - How do I ...</title> + <meta name="description" content="How do I ..."> + <meta name="keywords" content="howto, how do I"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - How do I ...</h1> + +<h3>Startup</h3> +<ul> + + <li><a href="use_start.htm">Start or Open the Network Identity Manager + window</a></li> + +</ul> + +<h3>Credentials related actions</h3> +<ul> + + <li><a href="act_new_creds.htm">Get new credentials</a></li> + + <li><a href="act_renew_creds.htm">Renew credentials</a></li> + + <li><a href="act_import_creds.htm">Import credentials from the MSLSA + cache</a></li> + + <li><a href="act_destroy_creds.htm">Destroy credentials</a></li> + + <li><a href="act_chpw.htm">Change password</a></li> + <li><a href="act_set_default.htm">Setting the default identity</a></li> + +</ul> + +<h3>Credentials view</h3> +<ul> + + <li><a href="use_layout.htm">Managing the advanced credentials view layout</a></li> + +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/images/appicon_empty.png b/krb5-1-6/src/windows/identity/help/html/images/appicon_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..1f509071d30fed359187261c64ce4a7dd1c800b9 GIT binary patch literal 878 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1SD^+kpz+qoCO|{#S9GMKnZan#`O7@K&seF zJbhi+ue0#5^6IDX%54A(xki*YmX>7X7cs0{cg6!K#8Uzka!D;tF3Kz@$;{7V5av`= z28wfm#GUgCDvL7HGfEiN@Sm{)it>R)i&7IoN)<{nb5j{izw>hfWjH}H!TD(=<%vb9 z46z0OLCU$ohG!Nh=OhA^7BOr;u%#a;%mES(Pb|vI%u8oDApNWzD8>%aUs{x$%JB7n z^J|zg=ltB<)VvagZ)c|M2a2(Ql!auL<fJmJcy~#ifq{|1)5S5QV$R&j)<G(UJZ<&% zSCYRoFWa@Ofr*Pr@8I4YjE0Qr57h(&g(gmLxM*<s?Y6ty%muikXTQ}d_S`QwKPAvh zb18>n(YYWmhCfI0yA6c|+dVady}UF7y%N8lJ$v@#$&)W%X5Rnq#F5M+$f<bk_15ok z*|xryKYlb6Y!xucUblYz`E%zwUc7j*V#+0x-mTL*dJGj=vfsXb{n~)XYh`LALk2^6 zdAYc_c<$|W*R$7_UN3byviIy~9~Xar|9jO-L%cdqXE3z4x6j#~d%L;0St2?1y33Rx zqhmI9c6Bv1S4#Kp-><*)$wHNew`H?~KHWPmF+DZW=CTQ=;-2pezxJsst=%f{h`lCZ zE-WnEx9Oa|eLLDKbJnscLds7&u4aXXPMxyp{cro(Qy82$6k8G{Bx=1n?;0MP5)>MG zY)0m+HCw$_%Fis;YcV*#xtOmZNUP<*+D{b>yVe;Wdorg!<*>n-&wF&dISy9qw_J!~ zUh!IrVezWhR>ywqP2qIl*m(P`oxS}}zM^xAEpt9w^f3f^1$nLgdhedx_fM+T_4VcF zJT=#Dt%+xt;T0Mhdwpt9kk|L`-|vg7Gxj{*aWm)K`SZ88-Oby6Zl}cKyzShIJ&%8U z`t)ed?!9~W?%DI?QT*$BIcC0>4K7J6-nuPw)~Zzu5!v(S&tJc8ot&H;!<sPddn#U< zQQ1mN2UKoM3A(>Sa+!e7s&yv7l%fbq7fzaAS=%0NXkdSw{loiAW%0Rq`M0xQ+RyyM b&)X2sQQ>5Mz}W(n)EGQn{an^LB{Ts5cE@Yf literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/appicon_expired.png b/krb5-1-6/src/windows/identity/help/html/images/appicon_expired.png new file mode 100644 index 0000000000000000000000000000000000000000..3aa90d6819fc50dc4d12473dd11b79c2f4ebca55 GIT binary patch literal 1071 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1SD^+kpz+qoCO|{#S9GMKnZan#`O7@K&seF zJbhi+ue0#5^6IDX%54A(xki*YmX>7X7cs0{cg6!K#8Uzka!D;tF3Kz@$;{7V5av`= z28wfm#GUgCDvL7HGfEiN@Sm{)it>R)i&7IoN)<{nb5j{izw>hfWjH}H!TD(=<%vb9 z46z0OLCU$ohG!Nh=OhA^7BOr;u%#a;%mES(Pb|vI%u8oDApNWzD8>%aUs{x$%JB7n z^J|zg=ltB<)VvagZ)c|M2a2(Ql!auL<fJmJcy~#ifq{|1)5S5QV$R&lz8Nv05^N8? z-}zkrex`N#vdJ@3qSly1N-lDm5H%|*R-?<ceBG`Kz6YDC9hY#2H;HV2<m4FQGo4F! z=@!wh=7e99!#=jRxm-$9yOxq>w0CFy^E<_Nd>%*b|I2*;_ovz;mhJ!TcpN$f&+3?c zm482P;?`q%2No}1zWC<M9a2{Nl_Fidq&4HB_SWS;o|){P^jv}=D(cCu;%9$7@7sU* z6Zj^7(Lw`3&-p>3H>aG~z%@Dj?$@W$*EtyuFgLWnoWA`2!fgq{i7PdvLJO98^By$m zS);wAuqrt-z4WPLe&~DMoj-q?tH;|pwmL2CI?kVzCY5>S^+M-&-0~|UUzaTNihlmp z6BuHUu;5;yXY|N6DJv!8gjbTe`^Qt~_m{8N*VmEBW%s(0bwR3cQpD<7Qw={`&+juN zRa(1#H|dtu{iw>^`Tow!?f!dzUOTz$efJ%PMR#*jt)?o8C|!CMxNXe^&soPK_iZY( zKdGB|aI5_EOJ@RjJz5u?So1X4_fnp<l)wi=?a6a%c1+Fx&VSzaq-~VMfycWHrW790 zT=9In)XXnQlTUU1+U|LM|ME+Ti#^g7y*hYOY>i|N@4r{M2N~xy?~DnIewe7eNk!ct zS?n37G~b?!8S@47^<=)gUbrt;`|;||+vV?^I9N6bY%vNvzxLT2!5xN|>+?D+Hhx_9 zs3`GY!RA|cB-6y#m)QM!vSO0E7BHne0;P-1@!{3C`5$$jJnr?#Gj!v%AM?!fE*Vw+ zf4}ehk;a!hclJ)?o52%W8nQ%OFa9n6_WKoIr%sQn*mh57`o7=a-rVdj&OV;g`=dSW z`LaIy>#7#@Pk*1y+b;k9RMpYIy2sbfezo3z=6v0+d+hRh^P+idAAVc6WJdie^Q&Cn z%=7=1eZTc~zK$mUmQ~Fu?UhHStW>{|y?*`++dB#(o|zgJ43Fky3r}KFI3dHu!XSEq z$75pgu|zNS=Rf1(rffJ9<;(G44l_Gb10&A|(F3Xr8akR8MZF{#m;y4M8$F&={N(@M am-b<^Lz~uDpLq)OErX}4pUXO@geCx#%-L%I literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/appicon_good.png b/krb5-1-6/src/windows/identity/help/html/images/appicon_good.png new file mode 100644 index 0000000000000000000000000000000000000000..d8789da9935e224dc2c2301e0e0e0e0e5b7f8524 GIT binary patch literal 1065 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1SD^+kpz+qoCO|{#S9GMKnZan#`O7@K&seF zJbhi+ue0#5^6IDX%54A(xki*YmX>7X7cs0{cg6!K#8Uzka!D;tF3Kz@$;{7V5av`= z28wfm#GUgCDvL7HGfEiN@Sm{)it>R)i&7IoN)<{nb5j{izw>hfWjH}H!TD(=<%vb9 z46z0OLCU$ohG!Nh=OhA^7BOr;u%#a;%mES(Pb|vI%u8oDApNWzD8>%aUs{x$%JB7n z^J|zg=ltB<)VvagZ)c|M2a2(Ql!auL<fJmJcy~#ifq{|1)5S5QV$R&lr~5@hMc6*P zw_BCBciAsPTW9AqC5=uci5eA~DLjowX3Y55Z;<%#|ANAWYE9h2u>xT%JPMpT6M4Cx zPEE++;W*KwGofW>;<D;xyLbIE+@5#UR&U0!t@Hls-#_`YNJ8-8{(hDP7vC!9AF8ST zS<!G|`=_N|xzE3p^|wwmR@=(GAmm%AS;VjE!u$7XTbDl9xqhN=?%!o5k+(N~z4~_c zve$KQq|~?rKdnBabw2cN&D!<tpZn#b%)DMF{rK6be<fv&#p+cXCv{xVj#<g{)cfT1 zlS{U3pJC&B`6|2rJIB5ot@ricT9zz`S^LXqj>zm+iLtxXN@Um~B91+g|IE*IzaTR9 z$MWs4uy}Il-)WN>8Wp$V-hVC4UR#{~@cQ@kv^i0_T%v|)2dfS{M)WBym62Q|v2p6P zTiae%+%TSgF21hf@%lBE9(^TtmY)js)_$;H*Kb!<i}7c>_ThOCvqs6aNZ&1H-QL=# zPkZ|1EiSCzI=5+eiln=t+>}#yx@U-=7TTQE{L;o$V%w!_eRuO&K1vwcU6AxJ&|Aam z&{d%m>Tqs`^r2h4+tTK3{XF%|<;l_NtG=$<T6ycOu8wW8kfdnkyyK1QJ3?#BrPaLp zrd^4frr@bLb)!{9hMQ)6>C)O?S9acicgDJJeM*XtVC6mqX_iw@(wc3v>|Tl;4zqt4 z^ydEOd(%E@&V6EDms#_+?&l?7O1T3{7ys{`+<E-$(QgZk3|$502}g=J_3BBoPu*gB zBWT_Jf2Xpa?VEOlb@JhP`-+}EPh0-=;v4qOo7o>n%-Q?nad^D^*)!eu<~_46&#iv_ zv^+<9_pi%apIs`t<$Y=@SNiL6sqN3--K{NuKYM=duct@l&n;+3NNV0|yRmw+?0liE z_RpV7nXebG3|#s1<${-54}-*v{yltnc<whQmgYnjMh2G_t_RGD4;XzI6<eGH8V-if z<JM!~aBy&#q^QIs=*Yl#fRRs6WJU|Kg@B%l0J9wf+rtK)!1)~=fA^dJWmjSJvk329 Rdl%?W22WQ%mvv4FO#twk&GY~O literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/appicon_warnexp.png b/krb5-1-6/src/windows/identity/help/html/images/appicon_warnexp.png new file mode 100644 index 0000000000000000000000000000000000000000..becdf9e81084248ebcc2177d5b19add46b6ffcd2 GIT binary patch literal 1036 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1SD^+kpz+qoCO|{#S9GMKnZan#`O7@K&seF zJbhi+ue0#5^6IDX%54A(xki*YmX>7X7cs0{cg6!K#8Uzka!D;tF3Kz@$;{7V5av`= z28wfm#GUgCDvL7HGfEiN@Sm{)it>R)i&7IoN)<{nb5j{izw>hfWjH}H!TD(=<%vb9 z46z0OLCU$ohG!Nh=OhA^7BOr;u%#a;%mES(Pb|vI%u8oDApNWzD8>%aUs{x$%JB7n z^J|zg=ltB<)VvagZ)c|M2a2(Ql!auL<fJmJcy~#ifq{|1)5S5QV$R&jXR~8MCEDws z-zh$4`~2LUopX=*to4nF5Ov*^$t@c0>Jreo``y*vU82AEcW7*>Z;IU+(428F%E@tp z#;y(WOSr-=nrW#us+{|NXJ+;J>#rBhee?CMz0IGB3Q56-`{x4#R<XRXcmMmC>{U&V z7HUkJQ8i_@>+7WxU1P8B;_Uym-QIkD{X^4Lo(v5V2fmiQyPIhyerxXX1l}(~X9T(0 z7VI=o;Qx}Fd;G5)H@n%l<KOnm@0n{-VttL(+&e>W+U5zfdYmVf_xLv5<vRE7-`1sk z8{R$p^+<WA(fK1@pIe0sdjG9B6)oHD!oVRM{<d+~oFgR>r<!v)dEfR#ocaH9x%9ex zcVGg6gvIOo{xxNf&SYK+(mwjY<<zT}CdRXlPjUBrz`rpufBoJGmDB19D!;zEwSKQ; z_2;|W?^iwNUCVH#Vd(=0O^wG&wGD*~HXiSuW`x|ke@AciDfexKzmFFggcWdV9q^tw zDZfcJN$v9i=boLC?zVHw&hM*eQ}y8poMtT7>3aMG^MzfaGe4@xR-XQI$IVvkTi3TQ zKPLa&`1Ej3qKVX-H#zEa_7pd43p=sp;FJ#qF=ui)Y!}t_G%LG*4iArGTfTPf+^ha} z`+uLVU3jZNYoe}-)x<7CvBNUmb@C?bRvVrF9K76L&UTwl%Ey~i*Xzap`ta`j?!%nQ z_ZZGUNIexS_?$84Nzm4c&{w;Q<bf$=KPX)+xtWwZ_iLWbJku`^_1D)~OHEzBevWN< z-qF^A+T6E?ev40T&YLE8UtTQo`Od_fJ3bv<e)ruzp<}l%7#v+Y+y3s3uV1yb_2<^V z|MSXSe)EIg6VL9hQh&2!^OqZ+j=jBqegDsOt0FGXD9l&rmGl3#wy);b&Bu%Hu`qJ} zIAhJAu!!kILklD40maQ?2`2fROLpcpF*99gXb|XP5)|w>;lNo?aKf#NCBcSKWCA18 p112SQ5e31{CUvEx|L=YOv;N;7axZDi8Bn5U@O1TaS?83{1OWW=%Od~) literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/appicon_warning.png b/krb5-1-6/src/windows/identity/help/html/images/appicon_warning.png new file mode 100644 index 0000000000000000000000000000000000000000..e72901aebbfa1266fe11ba89c41ae2a05d2ec276 GIT binary patch literal 1064 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1SD^+kpz+qoCO|{#S9GMKnZan#`O7@K&seF zJbhi+ue0#5^6IDX%54A(xki*YmX>7X7cs0{cg6!K#8Uzka!D;tF3Kz@$;{7V5av`= z28wfm#GUgCDvL7HGfEiN@Sm{)it>R)i&7IoN)<{nb5j{izw>hfWjH}H!TD(=<%vb9 z46z0OLCU$ohG!Nh=OhA^7BOr;u%#a;%mES(Pb|vI%u8oDApNWzD8>%aUs{x$%JB7n z^J|zg=ltB<)VvagZ)c|M2a2(Ql!auL<fJmJcy~#ifq{|1)5S5QV$Re_XR~8cMUKt? zeDC+Y>gRsX{EE_zIz5*s3T5k*Dy9WG9(BFb;Uu__>n=wm$GRnXE+6<cN)%gny>=2T zRNl2Qp>XD|4~r9A7I{Q@Uh$cAGDYok;r@HyWyI$;-M0HJfBt=eoRFYRl}Ll2g**EW z=9-yzYM&qW{-SbG>tedR&EIdUMOdG-n6UifIpE+XeCGJP_HTRN&aV7@JZQ>%`~9CH zSbG`HKE1W|^>q84AG^}dxQVP3%;73z*ufC<r>Nw6+3K6j|9NA79Bf?wQ0vFlMtS)? zWefLh{&wtn{2!CIej5)Z%sAN0)Npt9)>n!@^p$g0Jp3fgJuQG?`K;0loExrZe9<d4 z<!OM0#s1%)p1u9f#T?6}K8fSo!reN@zNRT$tw`Ld{eWS!acM{VgpH}^4j1kX)ivR{ z*_l%RyZx1y_u1p$me@;_E`Igc{{Bv;*9*Q_f9iX^vEv>8lCb<P1||j-r5&YQQ3m2k zY9}WA`x#yI`f{ArnfUt=F;=fxuSRT&oE6o+T`Vl_L_}n^D8rlYZr^XYM_XIS{5t0O zUcTn{*^J`N9&EoGmp{G#IAwePW2S4W%&s;Q&+O)GSspmezAdCY{PEG%^6Ft-n@?XZ z%YQJ#>qYyX{ib%Oy!4EkIn6FDH<b*Xv1js+v>GG3Yl7ALZvR}qdB+wm=~)w-i&R%! zDPj({-}6@H;&t=5tPgpM%VehmQ_5{nx>({b(9x17H)T$N*TKYZ5~6(PUi=h)d|ABL z>7a&-NQ3jCU&qQHpW4~D+hM82d6)FO!WfCiqUTB$O)q&ob4RIRdE&qQCx1T<e3kt6 z?D}0#pZ8sgbh;Xt_+si!tC_*;*Q_~jyVWpFLNP7n=8uQW5+@CE&rCVhGxz;{_x#(_ z6WMlbomT(sXU4y^jLbZ)r=++UzA$WVNZR&yWspq7o1EG!`TwPk_pbPub7#*4At45q zZIjejzW;T>MX9Ojp^=7Y4|Besu@+a#L_?hk46G9$HaVzpF|A<F?VtCbp=)mZWP8>f RCxPB%@O1TaS?83{1OSw-(OLii literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/flag-critical.bmp b/krb5-1-6/src/windows/identity/help/html/images/flag-critical.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d643fb31799d8d6ceac0eae8315e7bef993a5745 GIT binary patch literal 822 zcmbVKA#B_*6iqYfK*2N(RK-I>g@py>D;yXoC@4HoP!LcM5O~1gK!8Dj!2yGSfPjE# zI$&TB;7I`i1_l8J0RaZ5y~~fPk%8^&`{()nXUG5B_up<mM2p=be#Q8-j*IAe;UnaK zexyM}6#e=yd-|I_KE7w(H-6b}i=vq4c?xGgolXzUyvf7OApny#O#>M%Ns<I&<J}bx z&#i|5akCGvY6KR&g99+eNS|fdG)?za*svL{olVpTAo~HB$YvOD2GTRO8^>{Q_Io|W zJO5CJ*4b3MaXSA63}V$AAq43;=V@yiqph`vuJ<S+oXD~ErS8qpBPFFIeJ*&M+Bmb= zit8ajx){Er_fo5ErQwA<ta>Tpw1;0ZpX*_s*A@6Q19(eWCfD<{Z7b^PxR_81wWD1y zfc)5{vby6PmgMDn9;H-W*SwTpcHQPpr?o!zrn5t-b)0k{kwX8mADzb-!$ooV+Q2`* zDOr{`OkZVPS(TU)zZV?ak{-3ApIjT%i)H`=z|mn$0e;jTq;r<^-h0%Dmbm$RxoUKH i3~&INBBEE2k$!0ingLt*dBOwOcka)Npfu_KDgFjV+C<v` literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/flag-warning.bmp b/krb5-1-6/src/windows/identity/help/html/images/flag-warning.bmp new file mode 100644 index 0000000000000000000000000000000000000000..edb3fc3c88595f8685a3188ff115b9131611ca2c GIT binary patch literal 822 zcmbV~A#B?~6ox&G1w_+OHBeX$4HgU*RvH~B7zhXq2rLK~2nZ-J2rvi;FfcGMFeo@+ zO$7!91D<4X;DG}VJaFK^fz$r<RawEv_VnNLfA2n@{9bbN<@#;*9M{MnvEIF`H`&E= zJ;V8rxh^ea*{}bK<#O>?Ef(L-_4CE+^{On(5Q2{<rIfw~e-+Z_2>TMo7-0I!W^)gC z^!zELwPz5>;J=H5uY@3&{XSQIyW4v2Z)3XjC-p)gVQL|GEgGTY@u+;BKQOapcNgLZ zNp~T1LOUT2a^({$$c?jARVsft6dQJrb|j*bNrKmpjxplhmB{EUj+&-ceqWb!PIEb3 zbzlN^=GjYW$E7e-JT}Tdm}cf8bSbF-AO7%$E$-3NO>dO%x~>?WG!Aw|?-&;X&z$UP z8ZoySr|s~h{4n$wZ{C^rKFzG$6B(L*I;y5|W<82HLf}H>r*Ygj)qJogS*h9<ji95t zZL!t*uBrQ>S024%o`ti(TFjLh2AbGm3$q9TMdwI)5z!u96ilY~gdZ1z(JeBD226Rt TuS258AD|F|d0mHB{-5%1wIE^R literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/flag_expired.bmp b/krb5-1-6/src/windows/identity/help/html/images/flag_expired.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a3a40feecff222d6782d44a2e13ab4b51114b589 GIT binary patch literal 774 zcmX|;A&jFy6o%Q^WW|ZO&5F%t1>!_=L9AF&u>w)CVv{o`Dk>0&6%`0XMFpaw0<oe3 zQGq}p5Qqu{0zoba1i6gpB^4DF2m}IAQ9<q>-tGN)^ZMq!ZyqzRlOH$N%Ahg)cdT2i zuUJ>g1H7XAW{UEQ(;5<Re+JD4nTC{U8t<kF`yUvy8S+HJ&*$%!W$iw-TJ3CG8Uj)r z$IIms7#&&Ic3szf-)C8`jyiTPn3_qu7uX^RozG`r#IGC&Ti?I1yFGi}s;}{UUBJ}W z9eeVTL<xZBZHRYWH_uzf_o%Kt(Y76#w{6%{fDR}L(S|`lJPuB$HDKG#aWT@yJ25SU zz5L8@3P2P^#0S35A4~96btJhThXIZ@UR@L?dC8GTl7x6XpYi-r5BG!Ct{`~pcer-b zv}_bHUSwHDe3~YVr%VgVvUFA@0;WZPF_z2a(siAD1<&$4C%!0(Z=(bs)!*bP*v4zn znRqWa%95U;8}UL2%Ziygj6(Al%k+3W;To7yUNrnAVru9(X;oFk9}b5w44=oC#`eqD zpU$HXFAXALE=sQZ=rft@@J6&H9s|Uu+qO51UjDgSEN2cwaJRQC6s4M`As#QH+ag(2 dz2o${E)4;;BmlsOhyR!T{GqV`fDluf;J+)g&ISMg literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/flag_renewable.bmp b/krb5-1-6/src/windows/identity/help/html/images/flag_renewable.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3a9dc386f2892cb8eb1d00d4f93c39a2ae953cc6 GIT binary patch literal 1334 zcmeH^u}d3q6vw|7C2cI_2AdQmt+f?e^TR;UtJrcqLu(-+L{B(DVv#5ZJuodQ88T$J zA%nvWH{6gRLxv1D+;BsN8*aGah731k$dDm}!wnfSWXRx<_E+s7*gwGszu$Y02k*Vl z_ocGz3~r2_2Hw$#`S+&q__i>0>+b%m$|}T`2-CJuDwSaMEhN<>N{tfw{XTSE$7W*_ zrf;Hbm(d&b(DGWS89K`CG9;-0K@*@fst^nTqtOVC<DlJd<NEp<s(OiF5J2-ZG@DIW zt_9BI;Q1aDPeHL*M4?_ls>-406=B;p>h(GlTY>7UP)(Kg9K#>_7!HT%bUOInDnL;x zV09LXp}_N8$g%{nCc-jJY@6FiUMArNE;yA#tyZJESD>3Z-B&`vC}23Iz4{$YCKKqI zhF}=Lc5G-}4VtB)*Xu!cWUvYg%dt?V+O)1(C^yRpf&ewD3ukb!+cwprhN@5bbpdKq zg=mOyT^Ih9Pc@iO4O9#U0~m&Zl$C<-w{dn>gjAQ1zD&cR%*{pvRi_HAL+6_s#^W)% zgDzzrq1)|3wq;Zm1r@VGc|C}A%4%6iTWN3_hYIDBDcfi~x;gIzzwe&;A%0NczY36h z_K9K6lSwAYoHGn9E*7MV3;s=his$*~i-e@5r@sVV$e-|;48KLli@9&H*#1c@vmc8^ zmI>L4XU}r8`(NVgx%CeVge=d$3{7)9ADx}w4y_Tgn@BtfM`<44IX<R!n(u`rnnx0e z#79EJN2jOZIZ1jS{`z`jmypBf3rFmH<nzwV(ZbtPLVoN5OKW=@KbL@KhlGT(;aub( jmkUL5uMV<=#G`zQU&-fJ_!T;Xkmz6IGSl2maF6y6xZV)6 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/id-sm.bmp b/krb5-1-6/src/windows/identity/help/html/images/id-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6edfb07d9514fc52ef00b7ce8bf79abbf1303028 GIT binary patch literal 822 zcmb7?p>Kmg6vkQh4@@qICr*&1qN3si0#Sh=*#x2zQHhwCKulIlR8&?@AdwY_$qEFb zk|q-s69`1bi4!L-`wl9aK)dzJ-OD@p@x8}`=`+8#T5-fD?1$67vmV>)*6DtC=;Ho% zoj-m(@4UfiNGe$$(qtZx9Wp|6iN>~#H6fcb2CUCln{+l}fPEtHoD4iM3H5lbgjCJp z6D1gVWEOb%yNqJr?ePk{7NRLOvBx<u@V5OP2HSKczRQdJ?rZM3=mGpk6dtQmi=$S0 zm_OF}YT-MM%h)=OV5_Axb@edc?6&dL<HS&+E_1Y}1o~8iJmy)XE0}|SdkN%Er91e7 zKlo)7wqvAZ7T^dT-^IkCezcI;;x!zPrVeGx#JuKTylUzy&x&l_nq$1if4F~?ysGng LBL9zW|Cjf_TVTQ7 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/logo.jpg b/krb5-1-6/src/windows/identity/help/html/images/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1121f6416bf6f1d4bd107d84d10c94fe2dfc6ca0 GIT binary patch literal 2014 zcmbW!X;hPE76<S*WF;yXNCE*R$Qoo{1Q$wJL_peMt3*IiHf3o;5s{q;kpVJcC@A29 zK-f}5hzJ-qMV5#}t6<s1QZ_|Enjpl0kaxl?opbu3XQuZ#|4+|7&$++*fTQ3q!0zM6 zT#f+{2n2AJ9sqm|H~<J3907+R5O4$%i9n%uqtUXmXsn$4&fQ8_Wo0ES9<Q=jo2a6y zxd)F|H&EBq(be0pM<5!S7?Mo1NqVI1M<7Tf5{*JDqS1;Z6}$@R|1R(`fI$JlKrj@d z0mxt=Pz(g@0f+zqflH^|9{Aq{k%3C*MWSTUJERRwy8#&p6e<IQ!r?HOv^!aP55O>R zg?*-W2t|(oq(&6hEH#&f(zLJd#CZ+~w9Er9q{*W3O3DNkZ5>^b-hPV%mR1K39d<bC zc+AP!<+#_^C%h>qeSCw0L(ZKK4GWLH7;`B$E<S;NCH=1%nOTgytJm@i3a{U|Syo<A zS;hXL`p*4^#-<0{=9bp3?jGKg-lu*1S3eC74UdeDjZaO_%+9@iH~)S?xbkszP4r2; zzOn6s0MLK2ev|#qg^{{sU@#~Qx$T0;#7YCjz~K8#5ejx5$bcwC4YO1f);^b2-zlqU z?kT_pUKl{*wJfHzh1;}$%KkT4+MkmB2K%pT9M}nkNIwsX0m#5c6@yeN^G7Lt*p|kB z!*0zF%t~k=e*7^wuB1nF6MOVv*z!|;*X@)F5pMSING7N0N3UmXW>98Dc*Xu4TM~4z zT*x%f8y3|GgVWC?DT)JYd#Aquft7iutws=7q+q5NV<j&#NZp*sXg`tQo<woo9cg>B zkG3A$yD1L>wO(~)ev*?j5;zD9-@P8FevzCX{4&<!Y95n+d9&0V8OZ&HHg_Ea9(8OC z?OLwE6(zm{6bBqGq!dvMiCIpT!c?spF$i3tW!=en>!z1?&gfmW#S&_{@o(a$ugu0b zCNQ`zS*%*~0cr~fWK6DT&3CLVl<-^8wpb5GU_0?Yx9w9?ZzD)dH`AlP_vaxqmyM`Z zCt0bk=Jk&OBYnRf&!8S|_dxFoZic43TJz?7x9{`Tq!(rV>-V3q)dJ;8B|e+_&PHKc zebqYUta0Awqj5Hqr!riPFADIZBYZmFtC(FhGl}~!yi(aCYha*e<<5UBu$zxq5j_%b z-D)DN$<xQNg`P@r1<tXi66~cN>j2y;OrPi5Q^Tuin^<kJaV{#pOxYtg?dTsKuKgjy zn;}PGMV_e)?j+tOF^eCDX-2GBADPB?Sl*yjj*U4FwEu<cnSbzw9F|Cxf9JobK+QfW zheEUyXR1o}vNIb$XFjoBOd{UliZN&GLg$Pc7k#GpmFH>4Xf|tFxCR|u4o$KFfm~fj z5a4_*Inhrc3qU|}^tO`Zq1QUa&ga^Hb{99vTu$%EYO>P3@=eL-S<0a@jd0%-cBJX_ z+;LM7h{J4!O=5qw?!YaW82=oPNV(-05*IjIDS9qgh}$?(d%$+h+a^F*m{Hem%$ay! zNH-+#$>$vg(vxwYO~kKcH;q96)!vX<_iaVI2D2!h(W|T0tTlrC?0PHgKr&%QUzAJb zix;zd30o0Q4TD?jTNn#3eAJ80TePw>Lu^VJZ|W!yvI(5{1R`tU#-0JSv)9P%0DoCQ z$IP2--rd7A=IHCwrD$XOw}-wMm2aiFRVMyDx90u$+~w9+k?L*SfKSukb(QDxPKPtR z{LJa%4{ToSl<O`Rli;*pbP_+Dy+Ah6FBS(0$r8+K_^Y++mBmA+;?1i2vRq~{6LL*0 z!nCbGL2cDdw_lB@^i&C-UNXp7(KDnI6BO<@b8R}smlkzX8?EdKDg!9ZW{p;rS&8D# zBr`$t>Q5{X=!eJTrv^A;-67H-pA&I9WI=t*WjFK!a!bJ87}^nKdAr;{;$x1{6F&ZG zH0_xK6Mp7Y5&A>>`6-_YF}*rm=|Qad`11v!foXv^1e?^8NasaO5|*qzIC0cns@(~@ zmhL%EvA<0-x$_V!<3yYDwI3M?3`q=48mnHQv`T6XMdf-0@qSvxj3dAih?lY#)%0{o zVHZcWhfT{chHS9KLj~fX8EVwjvu+Sb0)gxp{&((^9@_mM*Ovy1I0)_|qWGn+0DsSD zm8)Po;TECuWwdegUU?R-pVq|@a%gh?DG?HjRq^Q=6FZx|?c`4{#lvWqBdn%m!V-B; zNT!(cC6{^DA^a5c(>d~{^IaM|&Wa*Teu~E^8`!Nc&z`v^FLH|BNRAl1YokhLY<^{& zY3-)k8QST+15dUbBKGEZUCl{ZTO9T-5Lxy`hAB9pckVBJj4NW7Ifvnr4plm`<`1V7 dQh8+!=>hf$-<QiYhL$xbdpKf&KN$!(_782gd@%q3 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/logo_shade.jpg b/krb5-1-6/src/windows/identity/help/html/images/logo_shade.jpg new file mode 100644 index 0000000000000000000000000000000000000000..44f13a15473b5376cff2e7d4532ed9a0387d7f0d GIT binary patch literal 1641 zcmbW!do<K(7zgm*%x`Xf36o(o+Awb8){PN14O$F!L|fxlSxlrtxlF^79b#%W8`EUd zmZ97;B!<$FToTf@H0}x&MPeq>B+QQ8wmoP6*t6UFp6@yDInQ(6^L)-D>y-@yDy~j0 zP5=xB1E}%~$OeFI01AObArUAP5`{*iFpvraDJVcVC1phwJWfLck5gACe5J2N(9~U{ zuC8sWt!rRtWNfrr%WQ)gX@fq=h_w6(42?!Z7)TX@R7nJN0_lGr*<ApO0q6i7gb@Ka z76xKrvL-+a0ANV@w95m3IxsjWpBIf$fL6#Ggem|W27+(|h(sa~^6q$f9YA1_t8_Nn zqf|Zo(Zpl8O|0}BjIKj@z1pr0v7UKAM4|$uj@MXC&^It785vuUEjL?P+id&B(aD+W z;`;6GJv2`*Z=XQ=fuP`nA%`NPq8Z1TF|kP}lT+BIPII{Dc;_>IzL0tG%GKPw{DQ)w z;u{r}!m8?<w`v+1o9;E=Z)t7od@Snf?&<C8A9?ot#pu|}SK||sw==Wv=H5#`%rCoO z0Qe{Cv+N%(tlR}hAV36q*#(0imj}cmkUASttL#0{{>M~_n^+i}LwZhmy@Ia!F0oob zL<gj<XECBLS*HCV`){zsFOq$R{q5=p6hWALc_0>`0Q31AQa1eGl4((1znV*fl5Q2p zW)-YV{BCsA7MoC(7lE%i^S;OTfY~KFX$=HSczQXHS)JbBRAszJ6e$Bt>m<`l!hjG7 zzrw(Ndf;iL?zUG4LHlrXc}WIHCYU!3r4*k+PP}n0_qMe$70f4r^c_3JOO>sq-D(e5 zljf}@d7_%;YzzL=Nn_nxgB4ttsSwufkfYVKj-6{6)SQ$<K99sQV1Z>?_c~1g+2K4K zf#pQ@JWO@)pI$T}8}1g-Gd!VF3VK;6q_4=AaOwGC+4$b@GlHPn$Kix0EpOfCJQnPt z)jT{IxXbBPbyy4LG*^_lgZ{>x^;UUF$dFv;lB2Y*DJFi+`4C$>GgA9tkZDt&7tqc+ zXZYJja5jIkt8-ONu<M{sNzliFanG=+2*}WFtk~)H;Cg|cccYZ;{(Z<Be-`J)_4DOJ zS?HP4H+W-Z!O;^o)m}o)7+hc+lfo*qt1vOEbjwvcfY544aW!QoEZJrFy=$Q*2TMOc zsSTf&q_o+a=UntewfE(0$!nE$p;Lj8OO>INQx<oOehIr4sWH(`F@=iq+GueM;sx{e z=*u?y*1L22!>+aQr<Iy(@gpfh&GCf3aBc5^fVSMlVYkEJGrx=;#*v#daW^!_vrN)X z=OsF3sMFKk_V9)|o!uYK)of*h#N@>R)NJXBh9%oXDtE}oz?uy|x|KFRPna@WZ#JDh z6KdcRNNHk|Ef0GXMQw;X9>yKFd~cH4YB2Z_D+9XK_#<akWk9g+kG`T1BKn1Ymvcd9 z8M9&7;QY#Ji3`bp7UYkaq#b1Cm;rNIO4mb`?(tq|@RFpoWV&?wS;dfqcT@Z}VKM5j zHOH_ymt;VLBU3pDIN^|eHolhEf0A#iqH~1*Y-^H4P#f&ZkgR;zBz~ahW^c!#Zc!4Z zKDQ!oUnHAW4k+|#jQ(mltdw-IaJn#atjE)Q0v~SMh-X;Ot!>D14-jUH^Q*3oJq~&_ zvP9MqH&@F5yYaf65`ixb<TLHJ9P?bD2=>3)oE2T9$ewN*ioRbb?Pf0!=Z6--phZeE zkLl<A$R=v2Kq}e?>y?hAO>}n@Hn&u3HSxv8vFlP}N?egOlSvedcB=*3!$nDr!8Fl; zyQqsx1gOe;mHot}cQAp8<ezYuq#uByh|ar?1wMk*<k}KCFBuMxM|xf1q$lG%?2um= HEm`01u%@-< literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/notification_icon_menu.png b/krb5-1-6/src/windows/identity/help/html/images/notification_icon_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..e5b9a13ad3e183a74846e7da1561c481445c8c7e GIT binary patch literal 8069 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 Ch&!nO literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_app_icon.png b/krb5-1-6/src/windows/identity/help/html/images/screen_app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..86bd210d87abfc971da5c04134c61a555bdb45fc GIT binary patch literal 10789 zcmaKy1yCKq(x?ya1a}MW?(R;4Td)({HE3{xyE`GcySuwvaCdiy|K$FUTd(R>y{fZv zdV8mKznPux>FyB4FH%VGc<=xK07*t#Tp0iW8v&i0!GeSKs9EwmpaYzpw3Z_PfQ|NV z12fH<25A9coMaRvU=|<|p}>ezOq2ruBa+Z`68Yg|X6pbbDj$^wi4dJYB5`9!LkDv^ zCv#gH06N@fGLRhppIpq=&dtHx)XWJ``e~FGBt`y@)WI0|PnE>U+}aqxasLSpbOr9; z6%|_(Cl{cDF+kVu{hvC*e;PM;G_(SOR2={fowZRQG3-CF2GGIA+{P5piN6;FlEM7% z{XZNGjRCjs{>L9`Vz$=S#x_oXyV1lBkPP~tnyR^zl`)|3Y?=xL10W+VqUxG{n&F|T zGuL+C;c+I0GbkJ@BZ(Ghp!}U#2`pl2m_!fSO}QlYN&D2pK@T>9%6-W(Ac>QQ2hKK) z8p_(^kAfaJN1HZ&@g6l;&S0-acy}+Q-yc*QG%-I}%9xRryWN+n{r=1p0Wkv~^5g4^ zi_y}yJME4(#*W9+Iwt+2rFU+c1lc@g^JgqVKb$%~q2t%BsEU`iF^7|tM}*q6J#O`A zDaJUa<PsKK+n0N9H}Xcv?$Lc)rg^~&gF~lpA|yJ2gS}jIm{+y&kDt6vZ-*(aC-iat zn5XV?ix4%*=Z8eK@LDU4hLfYf2FS(25~<TBkW-E}3pyU&rpOialYmbza3y}Q@D*;f zik5Exg9P`rTNHhq2Y$`q<yh@U$q!ojRzpK#ce_8ycRFK&<ZB1Vs+dN|D$q>}wkf-z zx{m#eZkEZ5Szd<xW#ZK7n>dLMWwaVNcz=HdBsg%IgeXy163iEcZg7PZ^cb3`ZiIKj zcR2(DRrDj(Cv5{q`JI&Ah^D&r-zXCXjg^~p7~_T>@|FkSkzVGZgv{c5DO6Z*YnP-+ z<Y~mj#8^|pvyd?)lrZ`Vq%JC9s)@&Ft*<?;ALg!}*Z)dWFy><5QEwTVF##p3$-OSl za_?-J+9YzOdIttd<}C7*i&SYb;h{#VSyQa+>@Kp6_1h*76UV=#*%-nFxbk>^`(RPD zJ(|L1Z*LC=2WL^IO?myS#`5X-M@3zGyzP7AwZy%0AP^@IsFk>@83>%uD$K*c8=U(+ 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_chng_pwd.png b/krb5-1-6/src/windows/identity/help/html/images/screen_chng_pwd.png new file mode 100644 index 0000000000000000000000000000000000000000..0f3704efa34ce71789aaf8da851a0b345bc3937a GIT binary patch literal 10508 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_appearance.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_appearance.png new file mode 100644 index 0000000000000000000000000000000000000000..e2ed86113c336241b3bff1f01600a35457833daf GIT binary patch literal 20195 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 DmSnic literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_cred_provider.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_cred_provider.png new file mode 100644 index 0000000000000000000000000000000000000000..aedb90f3a48e120f33394985104b7318966036d6 GIT binary patch literal 26005 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_general.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_general.png new file mode 100644 index 0000000000000000000000000000000000000000..ce7e528144c5acf0911e62f2e2236d42bc16ea0b GIT binary patch literal 30809 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_global_krb4.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_global_krb4.png new file mode 100644 index 0000000000000000000000000000000000000000..90a5664f41cfa7e42fe5c3b0a00151fb73f40f9c GIT binary patch literal 20681 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 aZ*KiX?9tO7z3gOA;P->2okbPJE8%}yeEePj literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_global_krb5.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_global_krb5.png new file mode 100644 index 0000000000000000000000000000000000000000..d0e28d9cf7c102f853dc6531e1ac01fcacda1943 GIT binary patch literal 21934 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident.png new file mode 100644 index 0000000000000000000000000000000000000000..ac6278ad025d1c1a05da1ad7b82351ea6b838958 GIT binary patch literal 26360 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_krb4.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_krb4.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4c6f4bdd2f311e5ebdba40dcf6e41f1f3713ec GIT binary patch literal 18158 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_krb5.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_krb5.png new file mode 100644 index 0000000000000000000000000000000000000000..484b94d629a498147b6d97eb352857ca7747ff5f GIT binary patch literal 22456 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_provider.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_ident_provider.png new file mode 100644 index 0000000000000000000000000000000000000000..8c709046d84cd4cece1e1cab40590017ead7603a GIT binary patch literal 28809 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 Q1p<8#lM^iyHu(I%0In8<m;e9( literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_idents.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_idents.png new file mode 100644 index 0000000000000000000000000000000000000000..a67fd1747c7b77dc15bf520acfaf4e7becc3a913 GIT binary patch literal 23875 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_notifications.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_notifications.png new file mode 100644 index 0000000000000000000000000000000000000000..e8069ba4c15fa3463ff4cee4c79f6a81817b435c GIT binary patch literal 17223 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 J<i+cc{|7h;LxKPR literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb4.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb4.png new file mode 100644 index 0000000000000000000000000000000000000000..f763a9aa542f621606097164aeeb6f1e9ff3a0a3 GIT binary patch literal 19313 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 Eg8Duzi~s-t literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5.png new file mode 100644 index 0000000000000000000000000000000000000000..e3e651a882627128cf07b4002300fe5267b56b62 GIT binary patch literal 21145 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 UijG!Uh6wnbusnIZ(84|XKZxyF8~^|S literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5_ccache.png new file mode 100644 index 0000000000000000000000000000000000000000..206386bef46ee92350dc31466002101fd03f95c2 GIT binary patch literal 18848 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 LNkvXXu0mjfTsjyr literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_in_krb5_realm.png new file mode 100644 index 0000000000000000000000000000000000000000..e016aa10b5555ff9cd8dc849bd6c30a1e0df86f2 GIT binary patch literal 25097 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 bNuREX66@0e+-y@g4)CX~p|4)4Y9IbzPMo{q literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_ins.png b/krb5-1-6/src/windows/identity/help/html/images/screen_config_plug_ins.png new file mode 100644 index 0000000000000000000000000000000000000000..ec9c749e6c8326ec32cadec8d6a75bf827d70aab GIT binary patch literal 23714 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 V-Z~teaXJA0^v@feE7!6O`!7QEi_ZW6 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_main_wnd.png b/krb5-1-6/src/windows/identity/help/html/images/screen_main_wnd.png new file mode 100644 index 0000000000000000000000000000000000000000..b520c858f54c2c226e9066b875be908057e10a3c GIT binary patch literal 49149 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_main_wnd_basic.png b/krb5-1-6/src/windows/identity/help/html/images/screen_main_wnd_basic.png new file mode 100644 index 0000000000000000000000000000000000000000..488fff33b9d3ab87a7db08c463a80daa40550c52 GIT binary patch literal 24630 zcmZ6y1yCH%7d48zOR&WuxCL8W10lddaCi4bf&>fh65JuUdvJGm_r=}aK7Rl2)vH%; zs-~v8XS#cO`u3UA_w)@_1WBW#5TigrL7~fhlT?C&g8ub!;vm6%<ir(1#y>95PD;|^ zP!;2V!;b`<xtP2d6jXII>Wd-#N1DR;o02>fl*eZ%DBl1msHcxC-vcNp7j`J9BLgTX z{$wa90*CbGAA(R&`gJmrVk&NWry1xvDynbq(yL{==QS;N&yTW9%Qj9U!_&h&T9&mn zo>aNLvoOYEXs9E9hEa4`8u}cyZ7g#?C20MlmH3)3`8O{W4;vdU0T17B^2d)%1VV=g zpK+o4b-w%Yj1&Rbp6#Z}Yd-<kaUsmCU*pf-6ZfmX3O1(mWzk3fIp4>7zdmh?YLE2o zIJ|p9l3-aWp9$`HU&=aiZeiZ;jyF0^#nW=;%r34uABfO+7!uSxH`5kSur43>@?l=f z^fCt(tc^*??%3#QEDN$I&Y}G4=h#ILPSr$ue6wPWgVb=e;M8<x&DdY$LS8r}WYcmU zcTgL8*);DO^byc{a~d0guptr+-f^f{2!gskm))pItac>L5dqfgR?llKwz=z;B)8t$ zlN&OG&zLx8Z=IIe*lrgfXoBvm%2meAjJ+4;F;Jv`UB`$I12h13%m0fn2~y{vuemn5 zD*>?-(MrH+rO#{WH$YYYd8l${<VGzwL5GQi3K75hdp$bzYSWg`FDPFN1I#P03MlpL zU`AgI5G;$xTH$848RD)lz#-=K8#*4JqA!I`>n4ofRyBW*Zs1P{;n@(k91E|Y((-xn z3{p_x#5B~?O|;!XM<)sbkzVVhk0A-n+JOEe#aa#`Vyl6FsHE{#C;ov6{F9LNc9#IW zL%svm>0X_{%p}|J(Y=b(yZh~HR>>i6OBdD;>tu$P4At;xNbJ%a0x_A0#2aMA(yYh0 zP^J?*Kw5$DjO9y&5c4uH02p^iXhv2ae8DKO!|<KlAs9iNobI=0_?MxrV&eE{#Q!>k z$aGQ2`HGz>xOOhXi6Dv;l%g6mAV(utiU+GG-a|bglk9<(vk~7D6pDn1jtQWE7U&!! zZ9z}+0)-e8w)uOaLj;u=5yHrz`M<bI_Uxx<`2%Q_k@T^7s?&1~w!28+K}2NxznLcS zQK0BcM7JPNc%ck9nw@yW^hTWoaE<o;d!f*c(B@cguH~YDfM1SV!(b@@|FRLHPW+c0 zB)J^Av7ifOn(Wd^9A&JJFSLo`mf!i6lWG5L+j)2C(~-km#};$CY)j^SXsdlYy<C+} zL83mMht1hWDdU8j-k%OY+d+k((Q?EWobHH+X?D*x(e#Z13+zI_dawy(Fy2s9`K!^e zg$j{w&268nGb2S>vF89Pe39+Ob<gTtA%?o18%MR}oj~NwdYxQoy<lUbp^jXSS0xu* z$G2`>wit)w+FPUs$vJ)A!nYE-@wK~~>h3HnFso{ITWDv4K*DCf$IHcG0$Zks?aw*X z8Mz<IjQheGmphGNB5Uf{*bxqp%NDHR9y{8tSnVkJrn8Gzb$mg`l_vi{r+3Hr%^)1} zMIOIYUtTmqo!ANE>z6ZgTYz}FzBF<!V=}v+LT~`x7)07?VNeR)dckc<@qt0-H^z_b z{o0^z7%BPD0r_)V3vZFO$MSbBmZwIBC;tNX%SfjU>j<4W!b_0x!*D;5y>|C{jhwDo z%7sVIS~#)PL}lCFC2oV@8|+DJl#Haqa5jzkdL-Zd(64>v^-7TE@l8wks81-*yZd@E zt&>6<nfujTNL*!5mJV00m0>c2ht+N?GJfs3FpsTs*Ms$!&udDS|H632BL%oaBoGW7 zcCqL%y5wJ$%e8szU-#1Ny<aW|{QUf25itNl9(6S}S0_ug_4W1T<>hoyS%VvG6Bm=9 z+i&0Z$I_)|RI(-b^|Ivi2(b5y?}<egr_&$uZ!3$(!WVd0<ZL|7$bCUG%0ASS?pJI5 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_menu_bar.png b/krb5-1-6/src/windows/identity/help/html/images/screen_menu_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..00b775b0a2666c3970ded2c9910279ac2e709775 GIT binary patch literal 871 zcmeAS@N?(olHy`uVBq!ia0y~yVB`U^g*ljj<SWS~c0h`=z$3Dlfk9jdgc;N4UjnLP zU@!6Xb!ETK!o$kS_h4_!Gq8|rM2TZ*Nk)DV!^(AMJb*$xB|ssU)Z*l#%z~24{5%F> zPDN#)I2TCVIlrK?C^J2ygkcT;87rVDA6T>~H4&s#p(HammBI8oKPOOz6C@LypH@<y zSd_{TTks#GoEvO-W^r;(B2Z}&!}bGP`hmh6AmQ-DqP)z!bcO@c&)R`v>=6B>MaiiQ zU;j71hADH-&&^HED`EI{X4-zB7#m1gNM=b+D#MC*m(+oQ!QkoQ7*a9k?W~KvhYdK| zE(g1>xFWjize%KGP}>f6Z?QuTIZPIrKTG&CqYl2mU&eFM_FHc3B$bChXX`3>uJg;A zq+*#+F?r8Dd4Ab87L7goI6b?ouFadf@mp@~Ui&&;9-pdKvy;giQqB}zz8dZ5zc(yp z{-Q{~w<?`CRJfC8PF7A`mGB|*-Qhh4nVK$7ocI02jEsvedKV`v?B0L%Z&A_#Yhn3g z_K$XQe(`j=bS`6V(bl7fv{sgK^qfz9a_a22?*=-5R^3t5p3o2^@asV4wDqMs6}G-| z7E?^z<l1gmEO<t68keONW7Xs>*?ro}Zf83O+&H&2=;-(Vb@#)rNKA0N)&GoT$Es-; zA8T;mhJ{7)#f9g?>Q2S($a%ctWXaA@G2TDIE;=EKiA@jE&fd6rxYy3cgZFu((UX(W zKR)R^xEuBV$-FO-x%s<Yc9!0MB_F$s`Kg%FKhqZ(ZrZIAmEYEHwfH#4(mC3xI>9>i zm#>h$^I}O~k)o}0gv(>TFFv4lA#=~RMD_i5yENslRM@ONJwbG0V17YRgMfY8E%vt5 zki~aYQg*HpyC~dsy5rs9rW*kZLs=vpi+9)f>%FKeescEmFMaOr%oS_g!YxAcX6`xN z+`e80sC1TV-h3G?6>A$2#ftem!jzqq-f3TIT$pB?)6jLX(57x7hhN){m)ebfB8y-D zy}$No`eknZXYXe(@8)TU6chla6e&=;_$HRy&|||=Z2Vcp)1Y#aLeXTElZ^kFm-%+~ TXK+3Ns$%eT^>bP0l+XkK^9X6e literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_menu_credential.png b/krb5-1-6/src/windows/identity/help/html/images/screen_menu_credential.png new file mode 100644 index 0000000000000000000000000000000000000000..588117c4e39ee6c9a22eeae23335c4c2dbc63e34 GIT binary patch literal 9870 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_menu_file.png b/krb5-1-6/src/windows/identity/help/html/images/screen_menu_file.png new file mode 100644 index 0000000000000000000000000000000000000000..5836662e01da256b9d6648e7d3b8d3089317e8e7 GIT binary patch literal 2952 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 M!^;MxdM*+F0d-Vj_W%F@ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_menu_help.png b/krb5-1-6/src/windows/identity/help/html/images/screen_menu_help.png new file mode 100644 index 0000000000000000000000000000000000000000..d39b257e4995cd655f5c267724c3794e46badea2 GIT binary patch literal 5812 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_menu_options.png b/krb5-1-6/src/windows/identity/help/html/images/screen_menu_options.png new file mode 100644 index 0000000000000000000000000000000000000000..528e01e940d8135fe403c83aedd322f91c2284ea GIT binary patch literal 4877 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 Xd>~fw6B0`VaX|O7p;obmZP>p6ftwXg literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_menu_view.png b/krb5-1-6/src/windows/identity/help/html/images/screen_menu_view.png new file mode 100644 index 0000000000000000000000000000000000000000..f977bda45a62207ce1ad1732d07c76984e86f8c9 GIT binary patch literal 6386 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 RpawJm&{EfhRjOJ&`#<%;*>eB@ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_menu_view_cols.png b/krb5-1-6/src/windows/identity/help/html/images/screen_menu_view_cols.png new file mode 100644 index 0000000000000000000000000000000000000000..79954d2b6866aa2408b18f6fb58be491c47790ac GIT binary patch literal 14875 zcmb7r1z1#X)Bb{}2qG+{f(k4MN=kPxf=G9WNaxZaAfX7-CAD-2NJ)c8{RHU-sa-<4 zL8SZttiHVceb@Kj>p~CDo;`cc{mk4mbI%Z{q##XzM}Y@{KnR}5z*Qg+EFbVQh>HzY z(i^l&z<<~5WV9V2kekGqA1t%f0dN-Ns?!sBsjDM6*DqgYMGt;p{k<fm<s|OxWNzyK z$^FzN1D38kfhD+!qmhG!os)&F4TR(x4J}y5!>mi%+POJcn3+343JALd!0L_Ps}3dx zm{X~pED$CT?tQ{*;GJujcT{anom>qZOdxu8=a|#+e_!0f(a72Woaz9n`l~z~EaPI9 zH4PkWENsjme^D;H18Z0ReBRl?$ON)`?z?(%nxriPVPfM1+3SjJ0Bct;r>R*uS(`vU zZVWI0ARtfR;%YCG)+fBJDHo9pKi|E6FcKvBFlHU)@Se1ijN7J8VGoHDRKmYp{AKlS z#s&=EdfmNfIR#pKN$q^@NB5+S!8c+eF4t>8>+6m9UBQ2Sq=bj|A$-w%_}`UEh9|y4 z?}*sFda|Z!Nco9G)x~;<^!<YpY3|MN+fhx^wt>GQnl`VV`F`-{l+-y{NuKU<g;9B* zuwy}?@`{R6{#iTw``}-$H0Raf%XN5tS{eQ3x_zsCT81T~K|P`|vV}`0SP7kX#fu=2 za#kE72u?N%^5x}L#p$tr%}Z%W;?}O7lMfr6@lS=uUx$~LW|~L#iu9-6mw26u3N)B? z>JKyrA3K)iBDw1>u$b_+KjdUCA>CIkISFqakEz;UPqg1deNf5W@;nZs5>4^^P|sQ) z>*2W9pz*6acQ&7?isO(|y6>-!hdkIS!#gH|kur3|f#ITOU+eZow#FS5nH|}0>Z5IM z35yDPbt4f;J9B<}COu_BW)+)t&d%+Q0iPzjK7@De5k;OJy3y=*+j?!cif-f|hphw` zt@FN3-alD6Kh+n`R;Ks8)9LLD2~GP&A8(5jeHT`!-_X!Oba=X16xeqVnDegQWzcPI zaxtamJS-3(;DI<l+Fd=j|0UruZCw_=vmd@>80@04R&l!V5^>(_+;D!%-M^47Nqb6} zA$qnIKJit;)Nb%dFz^Bk<x@OC!;)K^fke=WI3fA2y~V|3Xdea>f*Uso2ncR$P^N0X zzsuCE=jJi><De^nJ6Fx})fDD{ERML&MI({x>^m!i{91+XyIJzUXSD|?&R(IihMD}% zI)-zt9buZ@pO&Y;u5dJ;ud<m>xwE>R^}PwY9KmzU3olE2F`4=*AxXfn>qd$UJ#pa6 zr0_Z}<!-i}tf%L?P9;?4s%l5G;od)~Mw0fr_ncOCpiLiM3Pj4tDN?C5lP4!j!Xo2S zCi5%mNj-gHDqJ_eE_d#wo*$Z;(SU795?l)!Oo{6m-r0Cm7C{slVCq6uE-HGys+XfK zB*M>s*crGPNX}6c_Td5xm|^5tN{Us38<H$A0&Em)GG0dQ*|%yxSDCHTM8UFf>*dkO zOtV1qp=otr#rqSQW+A7m?}Y0$_bnV4k6D`w-yX00ntC66Q-6@2->8?b{djRP-+ex1 z3Tu&2Y->ODqn)s(yEVRniW^DS@q6xeBu=PEwPWG2N3L1^sb9}|h{??l^^f6BHq&>f ztVig~h>@wWI_0i6;03bGW1LX}a60uuM2l@r<wKU6tgq-YO0nQ@3HJ{T-sa}!Bl;&X z0ngCCqzmA00}j4krE;>l#&-NMqbsp8YnF|Sti80>HBj3^e$HD_WPN3orfxAZRqnZY z!+!N*sc)ZbaL?%tzL=XlS1z#dh6FX74;3<qJ*@C1NTpI7I+3tl9#!}<Ff}=ltBK|k zxmnKh?XYJ3RfOfhY0OpaCop^E_+yb%uKi1uUc34F@(P&OJ;6$bZCdDb5m;h&U~x;R z3sl#cPIR=HPJWBhnoWo;&$jw;mCF0o=}v?9c_gbDCt`V9r}3CjNdtkkW1*=Z&a>-> ziZv*j$YXXm!xapFHr_BL_%$|cy?$)LlUd41K6uYh&*kU+W?r05qXn~6&*3<F=Ik;@ z0jqT?@6DsR505<d@2EF<I&x5!^;?;R-=d#q+Zb<Dbly{c`CM<(1D2s);!~Hl-{8{! zyk;m#7?GPrsF>$=zFoYAnz+DXm?RCa;&NZYr`OY;r5=A6PEG*k^=w?0@6tg^%01s- zB8(d;n!VP&h2Cn-?Z~s6i<=tF<a)2f_eIj9y&M)%`X@6&(EgEVn5(NlXR6L=r4@Rz zxo%Pnu);}UU}}KHb>L{=Wm+HKaC~zyxjp^~KA~;F-k{eeNpG`uQp~gctLOAkMbZ6l zb@1xD?Ed|;Ygv1B0-GL&@xrr;2$rP796e9r?Eb+)$6jG?>Vmup944iWQ#P&MEEa4X zB^-uK)8Aa{_%%=H_AX$^a{67`p&zM>D<dQfnQs)iD4KI`L5OaJ_&88l;*g5m!g@{k zSPVi$hoRdmewhYKunR1V-IQ)!u@jUUSat#={on?b*Zn1RA4|{kV{hmV<6jQxQA30c z!}3_(j1rfQeIV42aH%1<*RgRS*uD^KpTDSmD5A^<zgNx1`=BeSeGG}jzG^3pn9>oK z_BNPv5(k>XVMY>ks1SF!6QaV7$PhQ}M^XY&DRUIBX`}Ol*wTfC1#5IALNHn6FL(j7 zpwZEf8Dd#w>H;FM*HEaT>2RxpX+mCE)4MaMywmD{hpA0Dwb5Z_pv<?EL*4Bjp6KC? zG+NGz5GkQ>W7AcUtQX={TijL%9a;4uvTKD9EYgT(Hz>s`bEdK^DV1E($dKFgt%E&$ z;?RkbWy%hY2?wbmT<+ovEFzVyMg<dOTHSh|RQaWhddBAN4&`fBSXetP7@>nqy5iNB z%eSMA*yNwpziO#U6Bsmgb**wGVSf6JF8@oOjyVBtnh$uonbu?2H){(wBYJt*HIwy? zZZy@mHTsBv5Yh6O2ev;YVC`Y+b8fM)pyz^2bI5R+H;<2#g_fxL-CY*S!trmaDPB%| zf#m-B^XdselPFU1-QzDcHJSZqk(H9wg^yD2)-Xe9pwr+>=ulk7KjEd7U!QuxuG5*V z>~UDWo+c!ffLu1Pe-5Wg>RFE;g2nL)x1c6ySjNsyDiuumk4}_xHc|p)wq`veYb}0_ zSygc$i@YK%G>kU-rHa-SFR)0dfq#2uEY3vGMD^eb7U^465;xr^U9qv=r^V9EhwaH$ znf)L4o-KqR*-nblr%R<OYa0gr_gVcaEr%GhnAuAO(+|ajTzL&w)bgs9-e~mA)DGV| z6N7%7ZR3A+K$b)>Mfy{e?8Zmq%RbZwIMKch`2_fv#SHu;ILvPxpov7@5jMP$e*`S; zv6xit+0m+a5w_S<F$h`JfaZg@2`3w_G>q3Fgw}7c#9k1I(eS#?uX`SwN~rVW(7b`* z`S6me<bFS>_iPQPl9uE1_xE2Bl2(*XsD8^@uJe?(IT!hUd?LcRXNU~@0i=H@5xEmN zb`Mr6D$4eu{;=Ej?4Z?il=pty(FGP;b04j)1oouVTPd>5KO@qJ&9Xc$QYH^}$&X88 z#!-S`;w`_F=>C00k}?ox%y76c_v7m;DJkjed)#6+Y}_jAs5v>w%O_H1D$f{0F~y5H zaIpc4_o(jNp}@QxQfGQ-c(q;5qHlZu4$k#kTb{l>Wu?4HsbS%ZrZRBO+2f=d-zuy4 z%JS<$k2C!UdsKQ)30;XJ9U1Q`i%aTee`g`SohZON&-5Dn8*{r+EzfQHMT~`2$Ad{a zv&R|zAIaOt(_r~GEpgLcfDo#>lUcTCj!I2E-~BYmcrP_6>16)fJ{%uf(q^sLTQODJ z6$EcPI}w87s~px|U|}mqmy`oCEB%I_T-sahzhAb_r>Xjz?g@nlb8{cEJ~WcQ!_7U| z`C5nKnxO32F(htfU|>j=Uieg7$W4`$l9H5Eu4U@suJO}z>m#>sP&OfyP&f0`P3rrZ zf2DD&OU`$eWRXY3CVy#SFP6uRf40wj)t$%|=i%Yn+Wxctv^imJ?o&?G-j4WS-v&V; zo4$yuR}YOZ1n-{$X)Qw_{&M8mS$cZ9p7)j}%mL9!RYDAf&0M8=)mME#Nl^B$vy<8g z?ppT9#7i}<BWGLtTAeY~dr?eZEngbVROzAlJeoYmlO^|{^au)f)9!?NVUHt`)ACQ7 zYs2cJ7g)fbynp|Gp5Z6GLf{S!%rFM<Soh4{^i8hvWXpzS7H1|EY)z?d^wrB~^R8I) z<h9WhH(7)CN$7%%Qr>`iCt+>-9s^*mkM}k28Q%~5CS}lbEK>$z?P<sDo;!lEr{%%8 z-r!f0NUQe2R~}X@8Tq`M{4Q&8B<OFCY7?EA@(hpolE&M!!x8BF3??S%!OVro+)wp* z1c-X#&nmKHqVBODwayj;x97flXim{-+V^0*<2tA4@mg6umjQcn@}RcW`GLm>*dB?} zwUo?)rIl_uH^ugzX_W1A@@D<z`sFjR@xmOCLRDuMy;<w+4G%9`KI`ypIzQ<RlKQG} z6%=WI>Jg2z1OfHz@JxxLfW22V_peoyZ1(J)`SYYU5`VU|oD4F^Vm+Dnc3_%f<ZkD$ z|6G%w!2j+F_Jc<a>!?as`yyU%@NnK%GYp0l^}_Y8=QFjOw>d2gHm_(hlOGT3FQ)uj zoue{Yd|_G1LGTv1Yz(p4tb*z~?E?gewWnjLr^w=p99t9KuX&18wlmRpj@L$;4L^H$ z6Wo4fIpR-1ctC-2(0y{-?Y<pcO}$&UUzqz9wN0d>=WAJchp@0P`JrxpI;Gag_l2`B zPj^SQLSIT&+f8Sxm^Ddf_B-f4@B7P+M~F-KgQBV=<TvGj;QHO3^yY@JH-rEiOYK{g zhRO9G7g#i$uBT~Y{YoPdC@8*m1@c<_&u99glm-WH5s8UwRZpEQoIi`<FLZk7Fhp+j zRP-I)@h9?0pZTu}=H`66LZ6W_WDEm4Gr={hcGiMSojPaFsIStd`TwxZ*GU?we$L!K zhR3u?<+w>@(4U=K^t>*w!fmNf#?^IS<%=|B`#_6$OzQmdx4y&hgN}BGW~1Qk6xWKj z<7ac;czOO1OWd={yh??b^=4vrmfeYWy<wQBSczyYe5=f?pF~2xzah-W%WIaKZEFu4 zG%x;n>1O(1U`erEt{Oj*Gc?!Pk|xSS6Z!FnC+k7#%Cmt^gfebgOT?5$jBHkb+jk+k z2gffjuz>a0a&rdKab#(C704l1R`A`kG&PzFiy86T9fUU1GmB3<H5D|{KetXFr@qkv z>4eXcAwpfqIy9&a>R5i+J3oK?s+uH?_QUzk_Pl|CbJfnb5X<Y$sJwU<_K>&SUC|>x z_hG1+*K^k`9F7FG1wL^Q@)RXFeDL2fFlDjr`tWc&Y^d){{os@Pz4kxffSobno+o20 zr$uI)k17d{p>VPabR^L7A0yF}D~P_|vmm*lT@Y=u$F`2G6`FpulbaVIS8fsi?nbDS z%ULo}KA&i{BVz9^ll3_xGXw3f+I*Ft0ox*rr;6ePN;0wUS?H`tGiVbQ^v6S8$~n%_ zwsF!ISa1_4%lMz?-p541J6FGdhRZ$8+G5gs{&U&)Jl8}F!p*8-v8HN{caW;Xv3BWq zcJ&_#*ALy|86}D9c9hgUK~@E{#JZEj=l7U<RwF+}O1d@7c@QeROJk(w0(Lh&G@Q#^ zrPXB7Ta2Jw9#kR{Bf6&^<3Ji+XOZ)^YbQEFSzP&c!F3#>xA2O~rk71@g96IOccXRR z8B!QY%rG%Zo^IobL&VGSsw0^5izS#<-$`_l--mzGR2yC+U?9L3OivHw&uJWaF4NK! zOT!^#6?P*hFo-Aafz=JOsv;pArBl5+_uZZ4K~7H2va+)E_4UKAv+xTn;NK@ECPqf~ z`y>gcZ+_W`)p*xtZP7%{v@u1?V#t^>u`^mQxtFIhYEU;oB(^)fM*G=*wxv1vreYG` zw9sd-Q}@M|P49CLhNyU?GFqGADaEldaCzB{4vhedvg1BnC=2UGcn+a8wE$6-94#@z ziZ-LU?rQ&TnFP2TxKt=5uT7Gm>qetrxPZX;)OR-Tv2&*5jhb^pEH!C`E9%NEI(EWE zswDJVwPjQ9f)I8kr2}|3v2-m)ujx^xzWUW3!=wq4jJSq7jt+}0p}k)FHEMfQ&}PGu zMwvW0r^%6~A>l0NPw47$368~8w(FMI@1RPa<F#(@0}M;F7-M)Pq7E;xaNnPBH8VAx z^xW5jS=!p_*SR|bS6=8&+^pHGN1!XACP6{T)2B0&TO@4J_3_c>l3p$|D7@zg+4ALQ zeC4dEk9(hHc99dj50MI4%yX}+dh*=w)+bkrJ0U(Rvt_*^HQPOcY|jps=Hv9e0K18v z{A}7@?A34ZItAZB2!5RnKVM!M%0FLDJ+pZAYTQ#|!Sc~EAC-r3#@vs`@PJMI{%|Iy z&b(DE>T?NRWbffp`EdZ*%OkN_G00GBvg@SVd`FD;!MldU#KdEC!ztQhqk8dZp*vrr zP)AE^wDzzUT}5y{O?5U6ZpLG8P5Yb^>0v%xw=R05(Q<uTsqr|i?E(w5jQ2tUfsVAp zh)IvA0<Ww6VprDP=bja1ZIy}pvW;{`ktMl~svCPcCBdX-_eLao*uTkpR1lcU;HG`y z_c}SqRn1B9I$E~%1~&q7xqyRT^PQOOnw#?$-5dDU$<`qB=uxrN2<!PE{P9rBq*_qW z9Z$3e^~Q7T(G-!7<xi3n1a-OU@$pjKR1?>(v(L!oplpwd*peow=BlF}1%~J}^<*93 zv8lXr8#EGj-}BXygV*n6@<TH!%i!O2?MGA=f+VXuM@f_yK8w)ZdP(zV3((b$i~a<Z zUWc9fUOWBL`%~VcP^rxRUXkOqZr&-<NDza-mQaa$1sysdF0cR_vG?W0SZB4G&=HSE z`;RvddxiTZC9|QoNnje5)cmRoM~z)J*nw>?7d)04gGu#KKmRI@d3jz4l#avXWS9i3 z@tK=ZVH^D|Dw!N$N9z_m+zN$nK+5X*>S#HKP<W@$vG=qJ+|2n^(SxtT`{Ua~Oy>iW zlU|<N3wwKeOqyqY0T?uajr4iG*?yQT^078<oVkAg!>#k^SJcT0Iq$;Zu*fzozs{D; zQ4^DyxvjPRzWcFf?RU+j%yq3PgK_&E!fCX|btdMA)77bcR*Xzd{R2{7&Y-=|_r1@T zGQ(M!nd#oQ8*{k1nriMeHa2F4iySrLv&{*I#*h`uKd-sKg28NVrtZMuvY%?uuui~% zPjb1MVfM-89<%^*era2}t_hiO^P#EffKL2Kp>C_3ba>B%v(*#doBbR9Be~c5nQ9eJ zD=o5&?rPkq_b&>suC9L1pm^i@^;`b-Q=a?X-QA%fAw>PlgE>_ICy?(6Zq}C7)ObvM zaXvFE4bshqvbQSMD$OmSXPz2OMVA?ccT=D<Xc2RyHj(irBeBQ|@k!f^<Y3a{xE?v3 zD~i_lVWu2T`?ap$)bQK84quGd7hW|qy@B6$hX@jSInK04yC)0T+R}nTqf=kb1QvOp zu1>b9=8}fF=+>L)ao5ye6)4=X)@`3|DtbXuAR=;plG@w$_nLkC@bED8Y$r!mRduq} zvmv=YwGpu(tVI(eJAb#vZlQaeUVV}V_prhkDV=dj`^9c!;~P@)zFeWRSMTjPN#L@( zAzNEpi>cm|H@SfNXKA@&d$wTP(%LFN$kqKzSEiT)?m?)*=eGOdeAMri)D8L1uS~lh z@o(Ilif9nkD-{jWz1Gy8sB%?O?8+Y2&^z_L7iU_`JdZFhJM{3?pcfl7O#xjkgIBd4 z!uTJXZhTtWI%(&8M=!KEt_K94#UfFK2dfP`*#USwHSkhVLsOHs?_>2{Uy0Zm`EFs~ zxrHUZ+9s$ap2zP(bKdv%^)G!kiFG2eK8|068WD{~H#xd?bsaA3qSZJsfYsd`o6`!^ z+sVl-$C+#2U>Pirb<{6m;iNCTBJei<P`17K)@_&z2+>ZvItE!Mt}&(G_{pD<<aecC zGlUBr7ka2CrH)tg2!>uYW8mpZ;rl|G?^`tOXvh8ivHw#k|6a^CFgV@tYNjMV<9SQQ z^YuT%GWEYnBX5*CE6qONKQvVj{cbK;t7k_Id#g8X635h-g=c#+#3ya2O^a^k`CXav z+w2vCcTC+An&64Zpi;)7=2+fm5}evYAY8jlu0|tK)hG%ij83QXN8n9Ts73W^?g#W8 z)0cVtdG+Lpixeg|_GT}zkTs{z$HK;K>_IQjK6{H2-m25rsvZf{Kr)fC>&{gd$PA4b zb|#;&MzskABV!(_>Uo;54i3)%XoF%MUYC`Q7&f^K4N&`}U2czO7u4I~D1>FtY&u!* zi)Ic~j869UT<tcl5QB)1&g<n*CJFFzle6=*5I!mi+D?)7;uso=t5K<Br>s&NX%xKd zXrRwOHZLFUcHC8;Sc8Hkv|IXs;vT#63#*pY=SEF2J3Ua|6W@TpjeXa2!`ByzQKqnP z{+=v@1pBvGg@vPJ>*p--;1(kmW<MX&<yVF>KNySn(rrOz&Ij|MUgKbh%$|L<78yu? z-LXjT0t-H?=$QGW3aXCgc}a+P=ZlSW?fuFky#jMHtrClIs4OURS$eDn*V&lv7}p)i znME3CisvJ(?4Mh0_oYW}Y}lxJtn_usa8V4wkd!87Ds$3IQ}vZXxYXviVVRajwv1AK z>xOsHp2-GrY^huFj{hwhB+8bQjwgiiZSuRtJ{YkhuQCtk^v>|}ds^?dAkvOVmeuyy zzn7GlSXP=-B*2LjF{eP)DO)!S+5hm?!+hH_Tx#5!HRMLZLNccUKB`%vVrs|P-*ef0 zfVVq~fbhDm!uplXlO6>i2N{Gl8&(U;pVHDrfie@pXY`;%3N(-Y)Mlnx%WB8+j6A(~ zsdHU&YI~0lk)*Ys2sOTVBE~Rg)+3U(>?`YW=CoK9OjfkE#Tx;IdOEafLs8`D7T64F zVjvH}ZK3I~hm556fXxx>EB7NwkCkbwifDY&xQk0?=1vIM23R$I1lQEy<rw@M38y^Z z%_f2-i&EJ#X!pA<^v6`$baa0>Sk-CYt1$V!H)K`Bk1>LtuIIX8`x`<7=~ntFKukgL zPX>QT>IMcNy<VmtZ`I?LsI1w{TNt|HM2~H7zFl<Pk4?-m+Xbn*bf)PT*5ffGX?eDu zNLk~$RVPMB!e-Ky8CIdl^&HE830jALupsa=20AEd6jpiE6)XKF+<yp}|HY@NYsnYO z>PWN|#+p^|?ypQDH1e($#H^6m({XXVp1*fZFRsbEjuVQY_%QJK=W*!|8FSnib1oe> znD*ldQ03T^89MIm$IkP<j<LjLLPcuq8y2Tg`%u&6$x;<1tkw%LIwg`J9rMg>ku~&g zdgj%fM!`-WkarX{hmQN{fLj*S2C6z9DXlx}t9e#wNAi;>M^19M%K!S(CuF777rEd@ zcL$vH?Qa@@bG$|Km!kVliO`8JJI@K~Oq!E)UrKAH<h28rt{&p`WOVgco*@$#y1=4) z!jwPDqcg9>V$diyme*8bw-Abrn-IfmzrwkfJ9;}-{b?0)HcWo%!GNyD?3Y|j<x^Nw zt$BQhf~emA9lg?m)d6_iq8$tR4BEzSuUinXnmwYjOpCOgr){yWZ69oXEy3ZF{gn~% zZgzG5ddR=A<UdLrA9p6^o$6#V(fPRh0-HNWX*536-&ZDKmBcH$Ng838jQ1n~fexa` z*t?E}V-Ux$&2@LtC|r)Kh3f1TBDuriDbL=9@KQlxR<ud3fWDYE$Xbi0VkY7Uv2a*2 z4TH4;_t-WuHU&?Fvdo1%8^2Q0DE{+BH|P=nv5VpSUMKR~F6x6WvB?g|W{b0H#$AsH zD?)dqGoh+hh<gHD0}~U7D__|CA#Y-p)1?ZEPnm2JIuq}$_Lot8Glc!Bpz01Jsz|<{ zF_|H6q`-hgw6dUPyHd>!rd8AtW+G1+6__duCNJ4{-Zsc$$%^(s<LyM>0L7PH1&iV3 zb^XJ^XaAYKt!coI6IwXBDZ2`|fTZ+<4BaEEEn$y}igQK-fYxHiVHyR<wfBNOL4B2@ zJmgTADSbaTS7?ldpe|~akuzU_)v6h6KKJ)gm_|7=1o_0u;CYqJUCz700<I&4ZW#{p zMj%+aV1LSsx;4RefkkE6idvGodgm{C2Qgq@9F`VPrb)RLxr8fJC|P*dP80q__`Xzt zdSrG<mrE**P(w}CxKP}OnF2<(;F!{`Gjp!d<h}=VzVyZ8t8c_5C1`F#aIXDVZvR)h zf2*UHhg&Cghd^nDjQ;Z@8nGcQZH>NFB36(Qyo6`=caY3mere%g5O3F_)0A4Uy{VhD z@8s$x*e=BR5M_2n9fT$swHOgPBmefTas=9*$-q3l*$qKKIct$qDZze-Zbk_>PUy+a zxp>a^zHJ*Z^Y1Qa1Qe$2Mw0VohlcoxaZqc#Hj<;w(KYA-i(Pb;pM$zFe9r17Q%Dq> zp5l?&z|i6<r!VG%f&A6)<*Cq>ae}Q0sOA@dO#8+ypHeB3A$7@IrhMfNoAsp7%|a7; zlb_gZr*1KW;EeIEjx5DW5&;hSZ(|9pO>2QnE-qWf!8KfDRyR9cT(2p6jl>C(XfcvT ziIY4~l_3v(yjnbeSzL_f_P+^Ge~XX*ieWipKcAbh9f%y<`hHp)pZ<7`<CRzKX6di3 z{n8_@>pZDcmV*ZjH6;%z5Hek&r8d8xA+M@mkIC^a44$F47HM&lX;Lg!hx|+41r|cv z*%p?FzX{20U46&TJ_5eb33KGh9b}KKJn*&_%p0)CdA&CJlqA<Lpy+i-fJ~>J;{Eky z-|X}WO4PN|vD!sLqr%4^iXvdwDArwFr1!(kg%b-W+TJfODUDGoaB6e+`VABl;_9T7 zE<7K<tE=O}yjbl6B`OzCl+wPZcuD)=q$!6M1#q0?oCxc@{GuPN)j_4^Tom^8PQA9& zOwDMySP$0k*nY-+I2{1O?f;YY?P`p|)Jilzj;iXUvk`zqBR03wJg6l^H*V6ZqMi%$ zZJ<>(&lk9GfyKgjONcZ*g`1FlYqqUcY*4eIf<Ee0eK#vNTZD`pkdANlJJShtJ&YYF zbQNK9h+Wdemb<R-a-#m3TAm7`Kpy<7+C?IR+Qy^mm49{J#;Q=$rvPC3w|zv7Cdxts zi)5I`N|Hf6T8XGp8yf|w)b7$4p&>i;5EZ@v4?y)0E88+Qca$Q~NQd6`GB^^O6CI{o z-ij3MZ*0u6#Ou<@!#s&WoG|6{!P>zIRV4|Ryi@vzR<1?Ihs-)WE*4Ffnlxrks}=%Z zF1oq|;RfP5GLv_%TdYvgL>jm5S--x`$s`Yo-+=+VuExnYz<b4xdsy;RYLh{!U14{- z*gP(<pg~s-E?>ITj*L?5lA8_T5viUnz(oWjjG#1zro;#ej+e0IkQ6m;ruU+~dBY9a zIp622t1g3wy~M<%@Yq=Hqti8{bbl$kDSe@z8z{NDoOYJR^}vleTq1(@A8tdTh!PUJ zrw<?Dd;G@eO8)1VN3ez7DbxxRvEyF<OENY}&}{Q1M1ZpEXxeWB(}0sLsfo!6oPa8s z*7OpkOik$8q{L_ljC)#Oh{;EyRO$a@7?>;+SlaupXA*Tkh-Djuo)+Zc8QD)R_x;rA z$m5{_?<Ou)>t@efV6leG*xOO*X?doztU0NjHtgD|8C>Da*onZlcjp1E&LA!te<EyL z37c4Vj-fXNNs7+m@|vHNyT0eDb$E>A9(U|S@b^-XWX#+(%_2?JYJp{?*7Kz<3)8~- zp{jzM?46a_+?3#3DKR~hesj8gD4RL0;C42T8>$k44&zL&bsqrN`K7J(naec(jv~79 zZWXaVXVuA#vfA$QuJ(`B@AbAB>fLwqctS(B$~k2jImRtk)jBw&0s?>@`LJU*X>9PS zypbH<^QV_mY;^8{dks@ZRjzYA{T`V9CaB1fuzWvanajCY<&y63+=P5jgz83&1+$T< zNr#$dYS9_C`uqhJP0Zo0BwZ?c_?rjxVW8O=?eXDT-u6c~c+!aheaEgBQJK`W+|o}4 zum7Zx>&wd90VH=0x%K`@T8N*UN(QR2UDmroWhlR4m_x3x1c5%k2Ijuxoi<kKBHyA$ zT^HTG<>Sl?{Q?L_pFF)!cfKJf9v5F_WZe$NSdffWe(bu2x2{=@rZR(qMs#dPYgRKX z<{jjX61pU~*>1o27RSN&PXv_rehxY5O#<c70tB0-m5N4L_Qi?&87B^GfTcB0f;wsl z9~iE@NiEW;kj)*pj2?eiXLOTkUM<bdjFR1SHkR=fi+mL!E{1w^s(@%*R9f(NEhp!x zeqzFNC!2STpqMPbTz3Pa6cu2R>!gL9gNs8XHftDT+IzPX&rVMRXAkS5#qeJl{_O;U zl}?gUn+2rqHsYjF>7fOdfbOe1{EU&6#WKd$E8}XPE{7O*xqZ8fHNXE(eG12)rxd8D zL^kTAQ6{Ly0pP2;S4vr4&~aE22%6PReYU4<5G}AKxrJ&2?SVHD`C2l7Dzd9sLdH(# zf`Pik<>c+Hbx8lHJW?G{N@2Pa4YFa(td;dCTn5fTb&#P^dyV-7Vf+^J+3bj}oWl3o zVItmY@ny#;r>6#8ofg=V?u`=}7j{9ZO%8UiFi4^lwEL#s#~(Hl*2I`i$%%X4inGE7 zk2a(vb45N)3cp=q;_>4LbeGJH(`{*KLDJ4u&{q`+#Q@|(1m+noO2og1z&;e-s+T1T z<PA{M#qqVkB*KR$;bb>>afr%&R7oUarGB+s4?DJH26%}=X-rK$*XG8$B#|@U&!Bp1 zk$~+xE2FQG<(?5E+!Y&tO%(EZKC*?+0u_9er6;%#6eCC$mKhgH3i{Rw|3^~g#dhuc zxKI<_j?cwSYh8(`ISb4zLyyz1l_#4Mgoaensr9#mJv4AZO}_E{Es^NtO&Zguos=og zb-ymK;Itrq^08K=7?WAtqse#{tR=oXQhgQW(Z&TPC%(xNSZmMLb;e}dw#=lEy#WA| z{M$f4al%1<!-1GUvH~GhARpS?%@tp;7ccwjO#m?hGX~(q<7JHo(xw!vt$RpCjie5o ztN*5}>*2k2RV`6^9V?odOD+Q{*V-GN!sm0m8~E|(G_k>F*T2J`A9Ivt&FhP<DcfVl zUd*}j0?Cvy#To74$*vI?Ea0)C=r`y3;$B#+(luEFjH*LXe_BGg5a+iGlt(bHfq9b4 zwEs3S@-Kx}bErW21r~n>N+3cMm7xU&n$~W>WGyFq3zr;5#BcbANO4@1GYb+75SpOg z2ye;$a)hnd8v_s-rbcninY9*iPv$OV4sP)0YfL_*ILs-#L1*?xw}}iG<<A=DW#Pey zuOw`rQ|<J1<Cm=W<2n0Y?jn0?X`U=EZ`X8;4~_@Bh6nP{j!nmfu<RxsjCbK{6d4QZ zTml7Z+r(%4lLnh(3sz4&bhALESxxJeD9#V_pbHI}W-O@ffp7DjW*u_9DK=#wFqKCv z%}f}94pI=MGH@_6e?uF`h-Eb2cQ7sDI!%9zsq-#*vl|H6e)E=9taT&sc{7ars=w2$ zAbE+rz{1nY5S<c7&*Aar1YrQ8a8y;O9GKaF!VFEbEWn&dr~KwJ4<Oy3M{z6nj9f@$ z;4M_B6(JYuWS1a`(eI-B!%opCoNcw%D4Abf^7=6-u;tv!hqr+#Ds1(6AN1PC_GpT> z38~C(#Gta-CWI@E;_k!fU^XrD%r;qXh$AGBh<0O_S}@vmSKkBddNw_yC;;Q>k2*Fj z!+4#b^57V1OyiBkszZJgnaC*|w|viP)i^e@mx^p5zRZLUHStq`n<iniD4XE{r<h~V zAP>U5YrswO__OnJ-JgqDnXjs8)V6ZT$=6pFgPf!GA*Z1J_36WjI=|PgRBjhoAdC+O z7riXwh3%W8^%WLY?-?!Ni>~e2+^TlmpqhR;-<>7M<0)BE<L;+!*|RHz=`II$^kO&! z;%BT5y$e;~J+eu?gW(V1eq=wAUAOr`UI`#!Y)CP4!GH^yU@;{LW<Kga_~ai;>BCEY z#)UUpvBa(H@Y)rg9oxLWn|sp%R3-=WWKm?KzVgY54tOm|vw_Z)>dXzM*EKLs)T1w> zp>&-mBFP@S6^5_6+8Nh-VAb-%1gHRWCw|6K!C!@vp9d{H9eID2Q1W6}7>xW7x%l}R zn*@FRu_poGZX=6Qj!j~@bAd&PVeu>d@rn7O+cn+!XpWyOx61u16-=62Vg66-pR#jW z`Ko<+S?uIwebM*QeKt<T#(tZb3a>rwT3Q5iG{6NSF7fv^_J55rKDw0ALffXFgm7)} z0e3?B`$KRQ5Vmx{Q2F~!zr`n4>e)But`p#ZRJoFmO=6ZIr6;AkS(e@HxTPz#ft%_F zUL_yMQcys8f7PHW6-#T>QXmU@5DKk_pf~^nP+tq4cLH-7eYmo_u1Wr+&%B{b@uN3< zbxd`g_mWPv1|~WiVLG^^Y9bG;Y;1bQn4%S^ZpoNQXFR*Wq6eqM!3R*HQKfk=t!Vqk zOY%ZLel+iuuK>8VlF}KC4AE`wTJf%LS7%~xZJ0cQWw(f=rKLq&Pk`XHOI-V{1pU{? z|A!PwN=q?sTm|Yj2^Q6w*9)O7fKG}#lUx(Rwo9bx`yLO2wrU?oJf@qarzAs<V!rbL zh%YJsD3fqkF24o&-bG$dMjn-=@=zld-2+_|X6Ri=$->ac--cO2Jtdue!Syk7Wv*Nl zq2>wR_O8t2Ow4r0)F3lw!DQy+hg(5Zo54hp9h11U+53VQSp2Mbdjli=j$P&QRI)e% z=X*R-m1)V4m%O4#2YMPggfK%JkT{lK(a=Z=X^SUP?w2U-f=I)isI5k$Fb|;x=3Sxe z-e<!a`ZU^ku2qJvPvuFBaGcQpe}H|g2)({;^3)IP9|__y465ksza;ZPO^aIEMi7%r zmooR;G>0#F^PPDnS@iP(d-v*cTAR~`5woAKH=Md|WY#N`HoFye|CxJ}r-8Ze4k;`e zv%8)|Cwj^KS|nPh`g)lE6ae)Ty~CimA1|HVBX3b@dG>ehx8!UmvKx+x&Qnh+iIh7~ zHTyrt$CH}jC^`kf^*h<aK(f8fDHjIpF--TGBz~kZmAG$f6i`%71O#{pbTcLOsSLBe zkWbQNfUr!yOt-Bvyz$)CEW#nXSE#Y8BRbbHm0oD@uYunbQgx}U!Zk8Ju=F@HhI^5e zPQvaH_M73qI%Ju8#*b$<KEaZKdVrAM`KiG6hcC4{DLE}9-i>hpWrobz$@-Tou!(Q7 z+NR!ImgLX&8wKkO_P&vk09pOL;7CT3HUHn3Ed8wn2awGFY4-A8BI%##nYPPiG}Tki zabXvmikzPu$-w?%!=*V(fi1JvX*NlJ`MI6CKJ$~@DH>VdF;<Bwa+1tB4Z9T3pZMC< zG^u{iN5*EwI&<Xx8PQZ|<)x^<W1v3Nm7m01iwVrZ+b}M#ndLQ$j|Jbw9Q<o(sr5OL zU=$RzZV|?lpE&gFQf@)n!&k=MYbpvThQM3EE+MlOQrrebnP9Nno!65wv!=XABrnpO zle3m%LZI~#@Y|2c2}IrdqT|{ti+<h4fGFyDN^3urj^Ezp&)EHl`aEk|v;EEK$mhL1 z{LHW{U$e+^aCGT={Mg=p!=bh*2c|tDh-9Y+!=z>jPD%Sod(8fo7gz}Cp1WqV1L|EP z-Hn}WR~ePVq`5_*1#}1(S6AswWyzOk%@d$pQ8JLyJ}bx=>A@q*XIDLWssA=0U@YU? zagP}D;Jz$oezT%}BO6eUl2K3PUUc+Wj1k&p@<&$2nn;@aX6xZx*fmVL(cZUT2Ranv z@gPTNQ!Mqcfm@j|lxG@qYNr$HnQ)hk*qAWZ@Ih6#TtQON3ZJ$S#AF-)Ag;B$v!p!l z$)-lzU1G>4uIW{%=W9HS(H)<5-E{Jf7)uDgRc8OxS@`Ei!~ICRs$`(;B#5=)x5Gi9 zVO{se62v>P2s`!bK4~ST1!*HR)b7`ktS+#)^*<LG@(-A$BmmP3DmspGgd2Twc(}xn z59+N(d8fSs1&=Q>F^})2rxv(ivKH-?_8qJe2h=NBu83+W!?6L4D0VYuRrjNrON=}3 zG1bC!OVhA<Lk?boj4XFV*5K7EmDeA1lA7s&VcYml1$`$OKd;gi;CgdfSs*-=eGc7$ z%~Q6;Pv8(oZoRA2ND{evYFq(uv3l`O18&BGF4~~I9rffjBV}iwq6UUp5|+k!^<jSo z&&Vj+P=6Z3e*EOYP{)c;lL|>uko-s>T3N}PCOoaEJevRh_akjTRBL#wU#1yey3MJ7 zU{F=ln(#TVrS!hI=xt2Ud|L}j8k3{;KY^3xwwSL)mKVqWqGcQE6eTba0eC8EQ;L<y zwBKF=;IWR7w6xwsYL&>sweSEBUthSF;B0#=&?3v_h0*IPDdmEVZE$w6C2)ayBx$UM zSd-7f6Kq$>Rcmiy%b~PBO0zKE_iw3B|AMJUOnR9|xHglfwforj#F;fpx0nWf(@S}= zU$LZPLdYMbCPAbvML%VVy(Oawbujb;umFXYwmnA@#bL%>BO1hsCC~}YZx<BQ3H*Hq zdPbu$AYRnlD!<5xd8kIPAXJ~=#_w!CKcc_{L;}d0w|`61|8o@lHyxR~F?|=V<SXiy zF+N=E3FeV!$&ef~!-UOkrzqr5tN3oNnxQQJ&Ip(}+t^KxgO?+#iJfdWH-NX+azRT; zwxFO=%_uWNq6WF&Vlj29bbjV54R|t3h|pUZbX@JL_!$O9L0N<G6b!5!{@7sk`LqHI zW|+li``65E!&=bJ`xGiy?h&TNsIH~=n9c}E6GPsQ5^^&CP*Wpl`|`e_X^+irueeig z6sPyY1hd_M0AMXKG9Qoni0ts0PcD1}+y@v$1KlOEy=J~bBcP<1_X1^eazf!@Yh&Ym zedn=1<KZDW$&7@}1<{zlSgEe&?<}jh4+{czM;4oUU$8Qck)KIBDAtp`i$+kD3JZs( zl@Wn<Nw}{=@6VA*X1X_g1=G>f)N>JV)@egc=<bHazxh=L(x9iYNimF4+n;h};$1HN zLn3KY)6_>Ob``Nw%Jh7%U0PYN1B3BH(HR!5FUW`i9^C!adYr%y>|48CIzsI6YFgoN z-K2@=qnQm>Z|AWvy=R{pM$r{A@Se&jPPK<RUK+AlDqPTO+L}Pj{hNQ3Sz&yl2-j=# z0*f#AUaD!&Sd+|uY2~Qv_y2jaF}YSID8O@=-$@RWoxj%)YE^C1hD|{)Oohv70o&_N zU-BpW9Z1Mz`^gujxVAa!M{I>K@*5c0MlL-IJS8@JLGdBh`HoVZW^O+)uC#~{DHv3; zB^6bX6fUso`IR{HhO|TtQ&wDqEWt;XB{GOP7tn@8iciMMof(<*s`PjYB&rMF{Ljr} z7F$2y!gv6d8Xs^#0S>CtzyTx1a9)4|0n7^KKo+y&gWnD&x{1pDA>aTb`|61K87tif z2R#f%Nf%h?D1pVh7=7NnMS|la5PTqhE2=VAhJZ%zqnHdXhWEeF>u*U>=aZb#_11^H z)OW7pq_=bgkyyBIHBazm7h@UV;IIIn5X@(a`86pI!lkB~#s^@{7M6vyw-kr)F}b8U z;uq*|RNgfc05cl<8@YRl_3ilRwy3-4CyC#dosJ+Ktt;4nG-x?mj)kPJBE=^1lM`<; zQX6?nfn_}bno$a11A%|&21;(O!8c>lL#_RQrI`d=%-Bf$+U%h-dnIKeg=$Ni#Kip! z`6d`?D44&1JjeVUBF3rybH1YJV?l9fSGCub?@)loH5@>lOoabizD++c>`yY2-e0#f hpy>PjvKI85Dx|PwKIE^EHSkT4CsGRVPZBTQ{68(!T2cT2 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_new_creds.png b/krb5-1-6/src/windows/identity/help/html/images/screen_new_creds.png new file mode 100644 index 0000000000000000000000000000000000000000..eb461bf7606a2f43385ab76811284a519569c934 GIT binary patch literal 11571 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 b-Xk022&wd2a)Bo=0YK)BqGXlCyO93{>SU9I literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_new_creds_err01.png b/krb5-1-6/src/windows/identity/help/html/images/screen_new_creds_err01.png new file mode 100644 index 0000000000000000000000000000000000000000..4999db898bb7c6d81fa6e383688f1f207a1f4d65 GIT binary patch literal 11757 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 X{V}Q4^Z`7!2LNKiQbOed+P?n-G;up} literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_new_creds_exp.png b/krb5-1-6/src/windows/identity/help/html/images/screen_new_creds_exp.png new file mode 100644 index 0000000000000000000000000000000000000000..f533c977a501675de050882271b614f44481a1e9 GIT binary patch literal 23631 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_tb_standard.png b/krb5-1-6/src/windows/identity/help/html/images/screen_tb_standard.png new file mode 100644 index 0000000000000000000000000000000000000000..5d2f070b34c93d902ba22d59348fbc39dc398884 GIT binary patch literal 10327 zcmaKybx<77^Y<4G4nYD0x8N4sEw~fh-Q8V+YjBs~?(PtR1Pu_JJ3?@m3xPu)^8FQ` zKcB1Go2~csO1-9cr@LpPRg|RBQQo2e0Dvwl^Fa*&V1%Fdd5~bA|KCzJ5<NG_&N4b~ z0DzDEZ-cQan0vMYUb)LEO1@fxM?*k{uK`j1`JW`I?JnlwZtdg>RMt((JWFWq&(a4A zH#1ioXLlPXM*s(zg6dgE`KL=bIs3TUSXsLRHJFq9&nm|MR96d=f2QQ_HVzg5*EJ^c za}V;ro{vtJ?p`LY7Jz~C(?4_6|DD{%&CK59+0+$iA87gfEF=AswM<+cZ5*wD0ixZ= zXYJMh9q-|4W&vD1g&w__NjNz;SU9=^e<#!XpEbmPX6iQX_7*_J=^X7d3_$jSn7ViF ziGhzd-oi@I%;b8OfZNhBs(A=tf*Nb8qtU{ELaB`x9uwnHyE<H7*Lq@A`}?wWQJ3+} z>Tk7!B8R~$2Lpy2)N~r;5G<sS#KidR-BS*$=}G8grk~R;i>xDV@$#MDrC`>i&kQur zZMVk_d@Z!6kjVNA4gkI+86g2!MSv(h0DSWPB5Xs2D((V>35JCQ-~*t=lEcv$Xm68F zaJZMK6DTRn^ttZ7O<qqW@7{j7;mlSyF|X5ms%bQ$Yka!3h5gQ#jHReJog}($q!<?{ zE&IDnpN@sTGovVo;Ctm!4y6{uhvD0%(fG!ad-hH-xdipv`iNPW+&?X<`hUCzab8&1 zQNa!Uq}%ct=3zZJ$eB}VQn@rLz@m>xC7k^JYm7V;ErN(}VTwHTBldsI1NLuGQ2HjV zL&X~ReaX|*FKZ?Y^UD}2o-J`MEc{U*r2*_kg2#zqrVtWErzO%CaBuJd=Zr=gHu<u+ zq@?di-F)}UTOb&$rE;i{)ZJA{IQEkcgzHg=1h|*vlqMJ3@xNEQvrS%3zS&Qx6yI%- z`|9w;g{!d4Hanl`y@p6gdqG7GpDjTe&lR8Ie#=i2l2zsU5m1?nSf6zdJ$<re-{Rd{ zf?AnlpLZd!-@F3<cwVv{Y<=1FF25L?q!<Wea(S?eS<FUNM1grHEc4~zKIVmm*#LF8 zJq!$fx1&Rio!~0J)2ZNyt^A5MoKhqXz^MoaAn|apD#AZ1JgoA(8Z$+t_<#k!wYqnW z!F2520sP7<^D-29ybYK?ySrV}3TQC9ON}|us|Oj*>p&*^tm-OzER{BMADcePy%uMh zfDNA65Fp4P0x){-&PTYO?yl;)AoZYE{usc1SAv>IKCUqVBE>f38tv=OBqFdr``Yks z5-f6GMC1oE5Mr{v-5f)DPngHetVju*LlHL*sXTT7U?g*^LoECbP8^A1`^vMF{>*g; zCb;gpTD-Tnw}}b=&6_f@Rlbs{z%u9VSU^-`L3uqZRV~5<7+CYWPthpQv3y~X_CtEz zyQQ%(@M&0{<r?80ZV!3k=?$-Fr`v4f87j8;EqCvxjT&2qrz4!r`|W8GYCk$^S+(q| zwT-r?BnM0$FA_ov#=LZ%&ehA=lH746qtT*P{5TT6O|Qc<x!TgsMSZt7*_<59Cx6{L zvNwY6tMo{nPNojgJVAA7y9OY@pR`nc$)m*AeHtAIt!kX&{t?R>;jE{(b&0Tc--;JV zAQV7aFQ%sq5&7&u-)ldzepe8h#+ag)6!)ilHn@lm_)>M4=t@KWcb5dal2Ew7X>U4j zYHF&swiYn%(L)fUV`U}daa{ivjf1m|Okwl)&>7YYO*T(QPfyRtXafx1(!q^>VF6wv z%3?r4{r4+Z%G1@=%~pY>Ft1Slfwmp56i_Hy(a?Z}bYmXW<3Mb+ahN^r1Z`WsFBg>s z=jY#ZjB*2?Zb=VCl$29iiZ_#v5?J7Xs-vW=l`&a*AUELe3S@T*4oKKK_Vf#CcAQi( zCUn$VstYG#ZMe-u@rX-lK4Y!V^1A71t6A(i<tJ=`_~Xa#GDKCW$<dcanb4JT-X;_T zP4n&Lx?#Zn;>AeJw>@c`QE=FJTpvFZ-c@aeKrUC;5(*5~??I(=-0oJ1QA&T8xj4W* zNA<CivPG$|rKxIpYFpVmyt26XOxnhAd=VyC#V{XE3MzzbxifdZtUvq~H_LxvA+oWo z_Ed&0(XlP){}_%Wy1=<%WHgPeiJDy<Fsqn}uPz=}C!g8+hDqCb)utRKm@bAOlKi`| z<8r&l`Zo?7U3rhc^ONoD=YnJy*Fqhc!{7#|yN+l#vtC>3rW)(%Saxu$-4eLh&&&&n z0=czm?F6znqnsJZm+%pHgB;QA5>6@bfrdAzQa^&4+EoQeaHB>d5%fMU{_N@Q(Z)l% zytd-fQ`|e%VWca}-~Xkf$ko-*5ZvPfiHV7s?DWpZj8yX14b^Fq74FAG%+bJ&gOlWt zP8JbB5wx(_laPgLNL&jY$)Mba_j~+`=avo^od45~<mBY2AgHgn81j1<ALl%n>4gPt zc^P~un^Kkkd0b@v>XQtSpZCKGnfE$vYVr8^Lx$FlVxQ?xuB&+T+K!#S-@Rns&}%vw zEYXW<S?%3k9SI2VXBc*=e=**Cg*-NUST5ZGo2`F{3LmA!bNqW$<A=PZNcE)8TBD0E z$j=%YgIBa*+d~2bi^+VxG5fKyaP?=tzsGb153)PmeE!Dq$Fh;%U63u92|apBoPfmV zPJae1aEBob>$-Kqe@5{3G2H|8?V&xUNZ}E`Y34E!7DX7aD!?Du>v@tkkv^5hVI@;F z)>Ol;>Muu-VxFy{5NB9_{cv*jDilVxiCy96_hQb$<U-)A_ZnOxo5H}zxD_xsxE=c+ z3sx+;(ki()I}ME|NWo_!Ow#4ftJXu3Ga4Cg4IVC-<BcSttx3t4B6ST7#mpa8nhnRa zL0K3pOB$aH$WEaRltFVg7AK`XPH^q8#`1MX@bKo@6WcmrJ@?<~IW#pi;z@;W1va3k zcoQs`kzWtg>$=Qll-r(`7vAN)&g{K!s~*8uLIlP>iDdM&nVgXY_MJ4Q*G=Q0YFU1s z%1`8?;JeFYH#_ZtOhX|v)8pff=b@QCEBL|>En9Y8JuUTp)p26hze~PXKlujlk1r)C zI@yNT$Q>Q8G`|`%Oe}b6rY*>Ixjn$88`VMFMLAi1vt3wY4$fU^#<ah==+h!K5Iici zBYp7;&s^sz1|XPB*u{97zr4Nm{dY%BHlNGwPxtqcq_^J>%4e|PDFTGlG_Fc2SY{vx zsAe=@3D6KdPgbYc#x|Y55qof8nO4wO{ajyHpeGUPf(7EBQBX?ehzbUF{uHbxx4r3I ziPjvWfcL*nSe(CBR5hc>(JmYKM3j_6tj$i+!3o74IYxil7cSNnQATizR|QI@6@XXj z9F~W|MoVYxbJ#rMlmOtl#)rRyc#Ok0R<HKc6oc6+6YnilByYp^HK+PR+~X}yBx@jL zqMsO9blp*e5r&GUW|za-->NDGAWD$IJSHeR3K$^6uovl&{H+a+$j8m62y0-fw#kl| z_=EiT!XizC^j1il&ULUW{^;GSvKv%b<4f19ee)gnP7G3hPLFJZB7Oa06-pvcCG>)z z^XMPTeufTw+eG15RRjWm%ZZ4#QN#KjKR&V%E-e0333C?*M3s?@o}E`Imv<9#2SSst zwKwXVowZKzp5P4wP?Vm=_x(=E^wgRTE{Kfu0v;%Vqwyp6Zcvff-J@-7pCN5nrh-ND z3Nad@e_#Q1G@4lgbxr{j3;;<`6#uex<ltZvq8##?N;;+p$=Egg_gpJHba~?U`R2R) zJ)eAOB=&dA<^&_Ajcl{|)Y(!<?D=M1UZ3X=T>10<&7%kuy52#%>~in9Q<AWhly!$? zq;f9oURY4%nnzFq;_7jD0PpJhv5iQ}UaPb{r#ipQ<pJthL+7PBO~+BZQH2~^yZIa; zB%^@+X>Ku;?96uyU+%6BR4-&}^r+&esp;v-4OnL{wA7doxLjQL;P#JUb(fXtc#TX# zSPWgc5(8I>hoeYEa48#Lzv!l?A+v1W2x{cf$gKfzsm_ziATt%Bfz<7ER^65{%jS=H z$$uzmxK)dER9H0Pyp(u7w-dFQbZAtOBPE#4eQw@X>oF02e4LVOzrJRg5qa`gP30`Y z5#%M&L?+**+U)*paItMrPkjGn(8kNEv)RpXnMDg1AC^<8GJ8%d5PRusII4%i+3|jh zEcdOCQT7W9;AlWUP6HOGo{^>xx0u*Nygz$5oL<s2>Q|X>aht(xB!BZpxrTUyY$+Vy zFbZpa7MzunG6XqL>L%D~-|)4YNM|mh!(hon*>t|CX`a??G?l#l*!#Np66%jO^c+=; z?SD{^mX=mjRP@p+H{R5a5JR%(_JdZ;;*={O$l=AIpPU>XHfb{<Q6y}^Q-FA%*nsM) zPmN3y!peJv?WAsy!ruq@3Vr)QaX*EegbLe&&;VM&JKtFOSXv`C&(-^+;&;c;wa~}9 zk@U~`Gt<4&snlklOhhWVO#XU=FZ&AsZ<UP<Muf#zoY&a5J=+^5mE8j<Ou^QI+B;Y- zfsR56Wrv?$SYT{u2kd(q-KZ>dsI^<0JZA{0u(WKR-3I9v2#hv}e4{dEZTWYD)1O7a ztI%nW6D^R)mNY~vcmC9&-(iF2Cys7oyS>XS9tr8XbBPcZiee5MgWhjK08usX)9`qQ zew_+kNmYy-VtI2^(eZUS)TNc`>GEexJ?KvQY}fZ476x3fB0mhET_{$wM8Z#s5?PkO z>Lo9TYOL*(o94nx{2Vk9FlKWvPhg5xWYQU1-&`}ALQecW+pdr6l@5K3pU46)Z?||f zA57YmKhaz1@1xtIOACY+{wQImVJRj;X9;oP&#SE+Wlu+@01m2>s<6dd8qG$P^7y%? zn2;;#Jb(F_ys)Ty_krqzypad{NUEB+dJZ$TTmWP$sOR>uIuetI5(p713b%OO1jrEM zkarok8~Gnt#Ip7(VAV>AvJs$N3bG=>4v;&JIg4v(NUDAcF}{<wqp5ASzW+mSbSK8N zFdg1nF>ga5luQQ`Or4PJvjW!|)FmN&*|y%gyyqI5ETa^2*v7pm?GJ(}e#%>~!L(&5 zkTj$dfTPe9cKKcJ=q1lar=`y6{n;w~W>@j-=h?<pL{UVKRld)r4u>})OwmXUg=}(_ zZA=Z_0iQuwqA^`d+g<0oQt*gO?x=_7)UoQ|IJEf9J@ef{ubhF+_ZyG;r-|-<)saDP zJ~ShjM<B#@C`<2!g;KFP4LoCLb)AxpQ@wIA0K{OP@=N=*b0<&08UQ_YM`w;}kb;vn z4eY;v@&hjTICKzUREBPLYc(S_#Wx#@(7>GUn@XskT82Q~9gO(h1^!BH+P`{GrH@)3 zl`)-89>0_jq4f9rPDFZi3$GR?Ct6LfBS4h46!ksJQ$$=~s~ITZ$w8%W(<(ktDV5u8 zk0qzVdIcV}9SU`qE9E>k8wsYUeW^S^nvE(;;+#g3{6dHFWz08ugRJ8k?B{s~K5^}Q z!)kc{n9giVH;~)6tnq7HNR3M9cA4;G)bsH&OQi4S-pCLNLEq>x+bohy%C6R)AH!Gi zxKb(i-6mV%HW!tseqm9eduujmKA}FT?OS4n2{e2P_!(C}ocwLBO4g_sy1ZN9TV23P zETE-|8=t7WUZZ~01vlLrQ}aV~i@-3Hyd@$lSAWX(p`rDvn(yyWU5zM#@Ha8k85^b{ z_xAQk4Mi+o(Gfx>Xa2mZs>-UWGLu1AfFhfck$V;o!&XaO{}4}*6REe$3Y+7^Te4g; zj+9mRTDePOlM_*8?_x1gyru{NAY^^t4XUfkj?vH{(a+-)7cWfwD5C4JpOApjv4zLI z;W#z53*t80DW$DQP82aVL7w=6<1ji@W!dUFKwbg^@Sb=^4vBeWE78f68~0zUPDt=@ zhrM-mGRWod<>%e^_pW(iK@5%nF<{ad@&-KI>1(zveVpM~Hnk8UnRSfw-FGaXH}R^_ zrlFo~Ck7Zsvdd(->3LXrN=38gf47Te&CeACo2Q5uV$E_w8VCtuilUOo^ll!m?)qIG zt_oGG59Uhkmg)=|j6-G&Ec<`!P3HG^`zq<*|6<+qx45;$2yC<WnLi5Z-&)ku6uD0s z8H(Sy0~-KXNQhC~Vd)rf>NT(ktsdQa@YmmH>h4u{e<qb1<bQmx^YPvk?5!E4C&iG{ z%b@;XSL=r#+pWPOe}{YWwyD0_Sa6jP5f%*o?n-X&!37KRu19N&)TEP^`O=7y7QA;R zTvtg^JuL2l67_a1`vHk%=7j|?aNr(cE;;WZj@ZrsBRbECuvKl($dH#NKb}rJfDRKL z=CWtxdGE0GK$ORwp*;Iefpl%nLt#iPhg?MtMir={`UcCJH{HNw7PnJk0P|f1ImrS# zcR_UMiO(nPF7o66oWl+1k)=RpegVO11YC7JM>i%#VKr}J>ka_Gml}K9v)dto6u~Sv zf>rc&81J<238w4DjhXkJUhS)PSfD(#ZYK{K*vj1g<8y0cT5(SvGe7dR2i1qJS;zL+ zA{ivvW+Ezd^=K(hF)V#0tz*lvvlBkBU{ezcAa|_4j7Z}-jb+WJl4GFHz;_#lAa;It z|CTWOuuGpM?gHcm3ZEEcqkCb&-gnw{v{+}*Z8Kk%o&7d&p?-5%51^o+?aoY(D?Puc z>s5BT8=dzGJYx+CG8;s|w_k2BnJbZ%&oDf^@}=s12oGue9D`2m9;3qMBKDOVFG9@J z##}zP@!m=5F*9p$$SJfx={ppKLid(M8MZ@veU3rbw-@xiFiF@H1qjB2W}aWQ4~aB+ z$Z?mwK6Hdf7G#c;(f}1z^HAj{&?SD}-n;V^z?yq78K!Y*tXetolxCArUpV)mUoahh z7kNtuP{1?3A8nGC)@Qhw({@~^`dH9FF7M{iymqpvVcXt7Bk2>55Dw1g4s&;saam*1 z|DzHPa=i8pATYx-d)uD}MI?In!h)-ghaL!);*3kfUn3nO$=h<~h0mwW9$|}%5N7Cc zOiOFkt<|?NIo<5}6x@yja}}P(loM`2Inp_?(-cjq8XdzP9;FGF`6=_Al)*e~NH7D^ zoWu3@8rdg<?&tS#j3=?cE*-<1hHY~L6^dInDk>b9Mb0CLpxZtGwC~REz@1Z7)o5%V z^UHd!&A7(2=ryVpdt@c}ZsDn~e{<!yC^;H}zjGM4fYI3%G*KVea@M=#x0;aWHy^OK z?rx;8{8cAPDoToO=Wd+)>{dp%E(34avKbUG19EV1h{b0$?Dk{^e*XL^x|4M~T7Q7+ z4o~skY2L|bquoV$D$FOonrv8!XY_?dgg`%!&v+`&BXmZm*;43y0PZ=1nCDbnx*DrH z4qWxY#%dp7muYxgy=>xzbki|}@^@Xe=ULkVU6go@&cq*ml7FI$%d}9Mddru^_sD(Z z^ux^xJ6<I(`dY*kuFQ$Ua~)RPU9#-#YGv`K@lDqNrg;D(%DXrTEN?L^Bn5kj|In2E z%39xX3liM8ORO2KI%!23{jg$W!fI)w4mWBMF2I+kRIpM1G21dT2CIlJbBC8og(5hS zgECUBs?}O56br6XM{TDB`HHKlZfgWCGOz7o#WTMU7g(|9{_eQsE=0m_u%w=bq*?tu zd@J^7Lk(yWFqfB?&CSgr0C@*>_xKBocRcb{xq=rec~v$Y7Xv1d4*m&wpScuM?LSc2 zzU3$^J0LKN9i~Lm%-=hh%o^cO0c}OMppuW$XsRbTtk+w=b>w&dwjMuHQ!V8WayKDZ zW}3)e!iEztWX%A2Ms>OCUIXJa!Rf2%>AJMRA7OnqJe%1jn!>DCRb=pVc6nKTT_1Hh z)*yXie|_-9MwBzpVtEU!xannBUpT--vP9$ov+meFv2*F$OF}}zl5sRokY0eGu3@3A zxlO1E+(jKAS8C={&Dv=HV)nn!hoxE=cOwubikV0W?mO4qnjML_1)Z*kaDRdm<t4Tx z9KjxrzR$@Cf7+@krnq(dML@?e&GKD#;DyD^_X#}7zV@T#zAi*3nFT;~Xs%gKTbAdm z0w*>~<ZJOa!cx|oKH%jP`yV>m1UhP|X*rCt{!UA?+1U@hVhVsN5IJN*kbdyvwYa&? zuJ)qorceGJF9v&DBkcDkrXjZA;63B*F>x);Hge})gDF3|Lm@GHPQ_$uRcs4MS#VPh zn&Oi9CfleB)2J)4Riid<!WQrJ^6XnXEf<$Q0RcT+A0w}$$ADL6{~jsH9Q0}luFOU$ zq#?Fk<O!Z*-9ITCxoy_6I$3rfSO`QcEb6i*>U3@)TC8_h-IgX1CY<6C+s2GBloOYq zgYFX-Y#%l;gE|5qe1YfMpL8vk`()EA=-(F>Sutg1MRouvdv_vhd2LNkO&0}tu9-fk z84%yzYE1(XC$OM~#(eY|Carp$hXKBi`4$YnNYl5WaSm?MI5P0pGKJPlG{rSHg=mVq zt|q26k_77>uxRIeGz{fD0<1BX47Y$v96%2<GYA*&6OOQ=qf|amze*kF!oNiXaEjyV zv<VPviZ$rgcGcnI?ZFHrQAuO(6D!fis>91%T>m_?8)Ib|pK|HcXHgXl!J{F0nvb&F z+uPBp{aT?)^_lDp76?lm+5`Y&K=lj26l(AJ3N|iS6;=rS4s#bDZ^yj**i&Ez0&m8Z z$Cg%RBI(k--e`alQAx=6E(Cy40r1DnPhVJsiKf~|RUuKVY~UP8b%PvnB;(N>7KgQI zK1d)@%qJiXW*Ia(YYczYSP;oP6;X3ocTdew?)3_AMMk0!Z=pyUkHJpgIhZf6*MY3p zwu4>g6?vc!k7<lrU8h|WYlae*U{WxoC?Y_Aho<7t^nsNp=x$}Ns=C^#>)?6b%4V$Z zIh>UyLkI>N*3$)EI@}f@uxSPe8`*eft+wW+=rLais3D-@#1cW?u$c5S?A78h8#4-Y zS6AA78+%>Qff1lQd+y;U0fMtqVYAdp$ERd-Up{b$4QAh0&+`@Pee)*QvmE5;#p}S2 z?AbyrH0RCxyW}-9i2*F2IFA>{myWY_!^ic)qDE5;t46cBe01XoIrE@FNeCoF495~V z@qD}icOE={0*Rxb^N$_Z=h>_VJ9i`p){Ki7#qAC13<Lxc4o%qe$(UFeEe$E}j@%pA zapoh&h@7uWGM1K~-wch^XUUjy)Y3?ve%n-L(^TaAM(Gz7iA}36f>>0QV+oO;pCFS2 z2}UHftQ3!Dn^c!-%gQ+xx@8>uEE4%Q>WAFrKL+gTc?FnM<w{dCuh`W=kj2pNrooAu zM`g-YbaH-v0z*x)tex9rPxo3rK2VU?hLGFt<nu6m9c2|8dgrisvdMS-iaPR1nMYG0 z_x^Nus@Za?s<N^Zx~mrmo#a59@C^_aE#;JaVWC`4i-lIA%#Svp?cn6po}NGD21If< zFj+k|HlWRfTnshF@kP(VPBt$2VBCDNdCvGm;s*uYjkGki)A78)=bz#@8XFHjS##p5 zrK+g3pa6ow7^1}(ZI;>%1_rcqhQySJdF%p&A3ts=SpPt<AjVjsVJ!W*Tu8tN7UMGe z;pLGhvtj(kdr+lp`GFuq&YG>pn2%1DGE{U)w#5dCVrtV_rid;w%{|-lrmH8M$IySI zMxH*N#DR(*JskJ>Y#$f_#eJ!vr8J4l#FjA?5BTU;3eH0tU;b7e+y5G6{@!)zB*Z$Y z_1SUJOHgKHrag6vNB+59GnOco!!!{eA8&<R_usmi5#JVL&wz3szsJO)gWaNF_wI^S zLEx=T7?yXo31kS%LEA%d>Qu;Yn*XTA@3hnFw8uvZ`4uK<ss$g3o+WRH#`@}NRlaB8 z!fsKXp6Z@w*-edhRk)dodLwUw#Vuu=sAtU^USmcrQpbaIJm@yTWTOYja6=TQzJ{QS z`kOkw!Yk9);tV52V^l)}CA#L5&lRz>^c^x`*VGCIC9^_2G!Hf02#a`CQdHv+B|ge9 zwvnQ59OV0{ur!wZaY=MBA2jB(w&SxB@xATj77#?y)GUS>&e4W|QqKI?z32YGezNl7 zuC6k=<*yLS&@456O9fe7kal*jopSBQ8Cmk48Z_s{FV>>jmFQ=>CO~)}E1#ko%!L4R z=DVCre?HgL=F>~_&BC{n&k1ppn!!gQzeRgs?E5tI@d4BS>G2h}!>YEHR=da18-vfe zysV6jwN=?o`@dr+<R)&L808!sm^IJK1<m~D3QaYV(mq!cP3Qe(cG#0>*pb@3d?Ftt zk+oD+@X$#&De9j2vz0U3XQa#9FnPZjS%0sWl%`zXrOsjK8_-u*COOS6wfM1U);0_P z%p^RR-^g!lGs&vO+8A|fMD4`rHKW`NajVX8njV{!bs<)A?|yqj!l^i<y~&%t$85Ra z!Am@vKoa{v|95tHnm`4>f{!$4I_P??|8-#RPr`TX|K}G++=yCC>A>vAEAE_={n_G1 z5lO}m83D`I_2fW<E=e-=>*s7b-nCS_jeVKxIY%U)(SsL@a#59ge!-C^O7S47%Qj)B zVHK%m->yiX<}7Q}l%ZiXL+6+A{3@Q1nz~>B9njYpp)u9`Chd4EH>-Cl-?)eY;Cl=j zki+9dD&*@fCMKqEnM@<kqSLf3+#y0EkLJ_^wIs*-;XzVuYfjIe&+UuCZ<-*sagiLj zIBEJyDtWFLm5q}gZ&-~Al^dxc#zGR@Yju6IQyt^RBj(lmcn#^02g88Tf%O}^&Ljv` zr(4<E7>UnLWlvpkk^_@Bo6~T#U0q#3u=R(fkKg9XyI%Z)q<X(va|1gGDvHWA)Aeb< zTQD#5)cK=%xP`X-PvZo2R$A$$D|g}JU!L7C><0>p#uX{apICT!wB}pf_nVrUp2bYP z>@pJsNDtSb@$|%me6!7p4j&RmlDns)O;^#Fzx!%DNV%V=8MG1s<*zVD8|iYCwz7JT zkwqw5AM~Yv%&zdM8)>CmY?%&4ptpl>6;+A1jUx!pdfPke99c`h*leR(v6<O(It)z^ z^|`I(-0R_sd2xYMLUske$8}@m?)+l<JWd(Y+wzxw8A^^CJYuxQe!0uDSi?T2lrXp+ z*uwt%2&02SS2Z=mD6q4%b*GHTiGU$%X3x+3ib@gzhWfv{mgI0a6nZd5bkxP#_a}LD z-tB6^h>Rg`=_tVbYKSUE8W;2CfC?w0$@glgecc}-iEqHGUYDMpUhwcIIvR&|XJ-eU zp~fb=sN%EG<8nODy7MD+4?V5Awe_l8B*66RH`(XdNGCnu=>ZcQ^b}h7endqjQKSW_ znHU+Xt=+3er+K%EF$3?j3}acB%ht%rT07M@0=<a2I6Dj?wh^g$a~<f_*<*+O!CCBI zFrq__$;4H|kr<s(3_Q=d<3R79Z=^r}l72Nb2J#+@rLM>KmIU#S(kX-n;Y%((gx~`D z<yCR>_cna?Kr79bBX3sb#mKR4rksLkku*_9OPebRD1W!x{Fk#!=)bOAjL$L5d0%Qf zo=Sf({~R4~%{=I0)u0WPY|%fjAh5T|wzVDwa#$)1FE^Ua@1elMR%?l*=j3GUPQ&CK zK36R?T~4|@!ov|H4o4Ca5=Ke=1X=r^vws`9(Q7({*l-@b+5$9*w+`I0$EVTu(N4Cu zx6qHu%su->ZZkqw!Au|!h_&x#ZcrkAH^(O1W+-C01{H|R$<Eh>e3it1+|Pwd7yjM* zVSw&e5F;x!xqL~p8SVAdU3NXS7i7Y+H$T}mwspWZX{R$A@AUENR$!}t1!wQ53j|#X z+8S}@B}RfDpO`o~2sn#XTXo+?8d*N^gc~>u?8X2D^D%VMg5+MF5rQ8}9#(iYU5|(W zQshubaDNSxc!sfB*?seY49-Z^#Ev*p@6A`=&*daV!|$*N`<t6$G!5OD0eIL!6*^Aa zpL99YrMH=Ia(!SuEh{D}im=6}Qyx-fJ^hQ_V*vOy&A{EtNG?0KuUecup)5sCU~g-S zEjf#n|L~W`PAGrTyiwwc>@#7IlsH~flk~dt))X9W{=3E6fa&>^-#w3oa8HCE`QUzQ zt7`roBXaDZ7kf`jYc-v_GGDID5oE)Ri*mBs>vw%BwBT2Tv+a}rv``;-aKLBT2VJ@C za+#9ZJhI$NrSY;<QktfTWvye{b-OS`B8~><Eh;d0E^+ljPRpkzTVGgo7nXb;s?mF1 zx{R(cf9i9LQFhMK;9>C)T|fw~)-r?x8fPFSa1kcj=`g_=hW>*cDG7(L164;(Y<)6` ze-0Hl@v=oyO@2I>3{3!u|GLt&m|p<~<=JHv@Rhb1UwQ$6X@ZbU&lh^l3M0y2g$h(_ z1`P4uR~-3f7sSN}<h%g_pXN{jHtPSopa9(j;C(Q>2V*Q#g*rQX`TbXeKz_hqLg1#T zk_8|*yET_7!u4ZZAgeg5w_)u&7X<uW7fwzS1n&}dizDi*sYrec*S#iEi$<WPz8?G% zn`+X+oksf2tG~0a^6hIcV#*yhWyfCwtD;+hqh}XNRU@Xl+Al05s+M1K$!4P#Rc@;? z(Ldah&*yCi2@q(t(BExFfbh1ILia`E?jZsxbX*>$zoAi&hNYF6lh>F$$D~4@zW$d3 z7I|oy{aQbbyjhcN^+zXuJU$Y5W1;_u*=C}x{eCf&is6IlhDd0BE;*2R&1RJ-hG+!; zr?M`*93<pG7cV)C_I~V_n{>h8`ilQ{Xzd!|t>o>x17ZPE@hD9``9o9kBM;Tqk!9i_ zJ+gZdBet6svQ^EI=XKkUF=<XL>fw2+5EgTkK^o~@g-_pQdg2wJYGHrwiaIU^y93So zXS1&s*!c99H>yO{c-eg_$=S`u`Ab3{(<`x$(r$g(rbDRmBpBAsUs!}@Sjin(71Btm zR<dkSo$vngF^#^!i;JBbePI0Yvn5opED%vP=t`kR;%SRRGUNirX&yMOr@b@aCjf9u zo6WdG(ca$_QEaXJyWi-z!~ZoY=a^b4ukV)Utm2n<2Ti^ZDb*2dId^gF=4B48jF?yw zBT^sRJj7*tUTW~<^>)z4(k;>#T+xv|n@w0LCdHX77Hpm^Y!04t9#Ruc4nctkh-^@T z+3m!5W-x0!7=uXZvgU3l5SVSIH=5=SWNACfm^0=+*Xc(W!7=j6WVh##I!;L)vdqOK znv5%mJ^0h9d{<7a1Vw^mTqaS4#U1RsU3hcc{2_=inP^UFe*T)x^53^>KDO1T=aEg3 zFq|kif|R|4xeUDF=(}M)2OK0jBN@LVL-rwG_vQvz1L_0IZm@N8o=12i_~V-KG<oQg luDLo-D4LS&|F5|hc?EXz=KrmA_IyP^R#NFhow)I*{|5+MlcoRw literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/screen_tray_icon.png b/krb5-1-6/src/windows/identity/help/html/images/screen_tray_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6d935d61761d656557fee2e1eaba8743bc0f0ad2 GIT binary patch literal 5846 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 Z^G!;aMtRBW)$QT|6-7;jN;&h;{{zA6HLL&t literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/wdg_collapsed_hi.bmp b/krb5-1-6/src/windows/identity/help/html/images/wdg_collapsed_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cb06b8acbffb74d8fc7208bcf2044038cf4230b1 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZ1H%zM2nGuPiR*(Bz+8ug#&j=G(U0x( za3M@T0!4luSr12;Tr?|y3VvTY0!Nr!O!a^6T!bT_dN>=%0CF+a|9$xoD2@pr;+X3H hBLSc;B;J1@cVN{cI|j(cbPv#Zm_CJzpgEpYE&$N+^RoZ| literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/wdg_expanded_hi.bmp b/krb5-1-6/src/windows/identity/help/html/images/wdg_expanded_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8180b33337d8a120782268a15105acd581e7e1d5 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZ1H%zM2nGuPiR*(Bz+8ug#&j=G(U0x( za3M@T0!4luS&s{0RsZ|a5nKqX`agFr;zC%}|9$xoD2@pr;%Ht5D*KNc0A&ZcdZ6<# MeF_&rb3CbB0NpSIU;qFB literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/wdg_stick_hi.bmp b/krb5-1-6/src/windows/identity/help/html/images/wdg_stick_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8857fec2207fad491c611187501d8dd5e2bcf147 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZm_i}04+H?ZfOu<xihpdM2XQnpx_~Nw z9a#_8g<lI$+3!n7AX<RBAR2*O2*A_}6#sMQB9H{?!bCuEG%Y}pzb_v`bOAM@A&7b) zi46Y#{}1E>bzvf)IHvg!^*|C6&_X@3Q_&m);Q|!^T>>YuszDZns{}HT#qqH5s009^ C@cUl? literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/images/wdg_stuck_hi.bmp b/krb5-1-6/src/windows/identity/help/html/images/wdg_stuck_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3b780712914f23410e4d6925e485edb8cda6f6a2 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZm_i}0Qv<+FBxo2!<&W+2APB<6qYJ3u z*OB#b1k?o-!Kxl&)bC42FcGE}pa{gMKX)!-BCP6xZUBn^efba*p{WOQ;cfu3|Dysl z#X!FRMc{4#vVj1u1Hwh~FHjK84G?7zaUhAN9%2RDOk@UD#bl_5XaSlAHyp?Y0!){n Oi9nPQqY_OcE-nE4K?Gj_ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/help/html/menu_all.htm b/krb5-1-6/src/windows/identity/help/html/menu_all.htm new file mode 100644 index 000000000..c5efbb216 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/menu_all.htm @@ -0,0 +1,41 @@ +<html> +<head> + <title>Network Identity Manager - The Menu Bar</title> + <meta name="description" content="The Menu Bar"> + <meta name="keywords" content="menu bar"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> +<h1>Network Identity Manager - The Menu Bar</h1> + +<p> +Click an item on the menu to go to the description of the submenu, or +choose from the list below. You can activate the menu bar using <span +class="pre">F10</span>. Alternatively, you can activate each +individual submenu by pressing <span class="pre">Alt + +&lt;key&gt;</span> where <span class="pre">key</span> is the +highlighted character on the submenu. +</p> + +<map id="menu_bar_map"> +<area shape = "rect" coords = "0,1,34,20" href = "menu_file.htm"> +<area shape = "rect" coords = "37,2,110,20" href = "menu_credential.htm"> +<area shape = "rect" coords = "117,1,156,20" href = "menu_view.htm"> +<area shape = "rect" coords = "161,1,221,20" href = "menu_options.htm"> +<area shape = "rect" coords = "226,0,269,20" href = "menu_help.htm"> +</map> + +<p> +<img src="images/screen_menu_bar.png" usemap="#menu_bar_map"/> +</p> + +<ul> + <li><a href="menu_file.htm">File menu</li> + <li><a href="menu_credential.htm">Credential menu</li> + <li><a href="menu_view.htm">View menu</li> + <li><a href="menu_options.htm">Options menu</li> + <li><a href="menu_help.htm">Help menu</li> +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/menu_credential.htm b/krb5-1-6/src/windows/identity/help/html/menu_credential.htm new file mode 100644 index 000000000..9a83af039 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/menu_credential.htm @@ -0,0 +1,81 @@ +<html> +<head> + <title>Network Identity Manager - Credential Menu</title> + <meta name="description" content="credential menu"> + <meta name="keywords" content="credential menu"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - Credential Menu</h1> + +<p> +Click an item on the menu to go to the description of the action, or +choose from the list below. You can activate the by pressing <span +class="pre">Alt + C</span> and you can activate each action by +pressing the highlighted character. +</p> + +<p> +Actions which have an associated hot key show this hot key to the +right of the action. You can use the hot key to trigger the action +without invoking the <span class="pre">Credential</span> menu. +</p> + +<p> +<map name="FPMap0"> +<area href="#new" shape="rect" coords="29, 18, 220, 44"> +<area href="#renew" shape="rect" coords="29, 42, 219, 67"> +<area href="#renew" shape="rect" coords="213, 44, 464, 113"> +<area href="#destroy" shape="rect" coords="29, 65, 220, 83"> +<area href="#import" shape="rect" coords="29, 81, 217, 104"> +<area href="#chpw" shape="rect" coords="28, 131, 218, 156"> +<area href="#def" shape="rect" coords="28, 102, 216, 133"> +</map> +<img src="images/screen_menu_credential.png" usemap="#FPMap0"/> +</p> + +<ul> + <li><a name="new"></a> <span class="title">New Credentials ...</span>: + Opens the new credentials acquisition dialog box. If an identity + was selected, then that identity would be made the default for the + new credentials acquisition. However, it can easily be changed in + the dialog. + <p> + See <span class="pre"><a href="act_new_creds.htm">New Credentials + Action</a></span> for more information. + </p></li> + + <li><a name="renew"></a> <span class="title">Renew credentials</span>: + Renews the selected credentials or identity. This action requires + that the selected credentials be renewable. + <p> + See <span class="pre"><a href="act_renew_creds.htm">Renew + Credentials Action</a></span> for more information.</p></li> + + <li><a name="destroy"></a> <span class="title">Destroy + credentials...</span>: Destroys the selected credentials.</li> + + <li><a name="def"></a> <span class="title">Set as default</span>: Sets + the selected identity as the default, if it is not already the + default. The implications of this operation is dependent on the + current <a href="concept_ident_pro.htm">identity provider</a>. + <p> + See <span class="pre"><a href="act_set_default.htm">Set As Default + Action</a></span> for more information.</p></li> + + <li><a name="chpw"></a> <span class="title">Change password...</span>: + Changes the password for the selected identity. However, once the + new password dialog opens, you can change the identity for which the + password is getting changed.</li> + + <li><a name="import"></a> <span class="title">Import + Credentials</span>: Import any existing credentials from external + sources. With the Kerberos v5 <a + href="concept_cred_pro.htm">credentials provider</a>, the Windows logon + identity stored in the Microsoft Windows LSA cache will be imported.</li> + +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/menu_file.htm b/krb5-1-6/src/windows/identity/help/html/menu_file.htm new file mode 100644 index 000000000..f82490efa --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/menu_file.htm @@ -0,0 +1,45 @@ +<html> +<head> + <title>Network Identity Manager - File Menu</title> + <meta name="description" content="File menu"> + <meta name="keywords" content="file menu"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity File Menu</h1> + +<p> +Click an item on the menu to go to the description of the action, or +choose from the list below. You can activate the by pressing <span +class="pre">Alt + F</span> and you can activate each action by +pressing the highlited character. +</p> + +<p> +Actions which have an associated hot key show this hot key to the +right of the action. You can use the hot key to trigger the action +without invoking the <span class="pre">File</span> menu. +</p> + +<p> +<map name="FPMap0"> +<area href="#properties" shape="rect" coords="1, 21, 131, 42"> +<area href="#exit" shape="rect" coords="1, 40, 129, 65"> +</map> +<img src="images/screen_menu_file.png" usemap="#FPMap0"/> +</p> + +<ul> + + <li><a name="properties"></a> + <span class="title">Properties...</span>: Displays a property + sheet for the selected credential, identity or credential type.</li> + + <li><a name="exit"></a> + <span class="title">Exit</span>: Exits Network Identity Manager</li> + +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/menu_help.htm b/krb5-1-6/src/windows/identity/help/html/menu_help.htm new file mode 100644 index 000000000..8f65c71b8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/menu_help.htm @@ -0,0 +1,54 @@ +<html> +<head> + <title>Network Identity Manager - Help Menu</title> + <meta name="description" content="Help Menu"> + <meta name="keywords" content="help menu"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - Help Menu</h1> + +<p> +You can activate the menu by pressing <span class="pre">Alt + H</span> +and you can activate each action by pressing the highlighted character. +</p> + +<p> +You can invoke help anytime by pressing the <span +class="pre">F1</span> key or if you are in a dialog box, by clicking +the question mark icon in the title bar and then clicking on the +dialog box control that you want help with. +</p> + + +<p> +<map name="FPMap0"> +<area href="#contents" shape="rect" coords="173, 22, 373, 43"> +<area href="#index" shape="rect" coords="173, 43, 373, 68"> +<area href="#about" shape="rect" coords="172, 103, 373, 128"> +<area href="#plug-in" shape="rect" coords="173, 67, 372, 102"> +</map> +<img src="images/screen_menu_help.png" usemap="#FPMap0"/> +</p> + +<ul> + + + + <li><a name="contents"></a><span class="title">Contents</span>: Opens + the table of contents for the user documentation</li> + + <li><a name="index"></a><span class="title">Index</span>: Opens the + index for the user documentation</li> + + <li><a name="plug-in"></a><span class="title">Plug-in specific help</span>: + Plug-ins can register their own on-line help.</li> + <li><a name="about"></a><span class="title">About</span>: Opens a + dialog box containing information about this version of NetIDMgr as + well as the modules that are currently loaded.</li> + +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/menu_options.htm b/krb5-1-6/src/windows/identity/help/html/menu_options.htm new file mode 100644 index 000000000..1022a320d --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/menu_options.htm @@ -0,0 +1,65 @@ +<html> +<head> + <title>Network Identity Manager - Options Menu</title> + <meta name="description" content="options menu"> + <meta name="keywords" content="options menu"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - Options Menu</h1> + +<p> +Click an item on the menu to go to the description of the action, or +choose from the list below. You can activate the menu by pressing <span +class="pre">Alt + O</span> and you can activate each action by +pressing the highlighted character. +</p> + + +<p> +<map name="FPMap0"> +<area href="#general" shape="rect" coords="124, 20, 239, 40"> +<area href="#appearance" shape="rect" coords="124, 38, 239, 56"> +<area href="#identities" shape="rect" coords="122, 54, 239, 73"> +<area href="#notifications" shape="rect" coords="123, 71, 239, 93"> +<area href="#plugins" shape="rect" coords="123, 91, 239, 112"> +<area href="#pluginspec" shape="rect" coords="124, 110, 239, 169"> +</map> +<img src="images/screen_menu_options.png" usemap="#FPMap0"/> +</p> + +<ul> + +<li><a name="general"></a><span class="title">General ...</span>: Opens +the NetIDMgr general configuration panel. This panel allows you to +configure settings related to the startup/shutdown of NetIDMgr in +addition to debugging and monitoring options.</li> + +<li><a name="appearance"></a><span class="title">Appearance ...</span>: +Provides options for customizing the appearance of the credentials +window. Currently, the only options provided are for selecting the +font used for the credentials list.</li> + +<li><a name="identities"></a><span class="title">Identities ...</span>: +Opens the identities configuration panel. These options control +credentials defaults for all identities or for specific identities.</li> + +<li><a name="notifications"></a><span class="title">Notifications +...</span>: The notifications configuration panel controls the +settings used by the NetIDMgr timer that triggers warnings and +identity renewals.</li> + +<li><a name="plugins"></a><span class="title">plug-ins ...</span>: +Options for enabling or disabling specific plug-ins and also for +viewing information about loaded plug-ins.</li> + +<li><a name="pluginspec"></a><span class="title">Plugin specific +configuration panels</span>: Each registered plugin can register one +or more configuration panels which will appear on the <span +class="pre">Options</span> menu.</li> + +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/menu_view.htm b/krb5-1-6/src/windows/identity/help/html/menu_view.htm new file mode 100644 index 000000000..2e231457a --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/menu_view.htm @@ -0,0 +1,99 @@ +<html> +<head> + <title>Network Identity Manager - View Menu</title> + <meta name="description" content="View menu"> + <meta name="keywords" content="view menu"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - View Menu</h1> + +<p> +Click an item on the menu to go to the description of the action, or choose from +the list below. You can activate the View Menu by pressing <span +class="pre">Alt + V</span> and you can activate each action by pressing the +highlighted character. +</p> + +<p> +Actions which have an associated hot key show this hot key to the +right of the action. You can use the hot key to trigger the action +without invoking the <span class="pre">View</span> menu. +</p> + +<p> +<map name="menumap"> +<area href="#advanced" shape="rect" coords="91, 20, 230, 39"> +<area href="#choosecol" shape="rect" coords="89, 38, 230, 57"> +<area href="#layout" shape="rect" coords="89, 52, 229, 76"> +<area href="#layout" shape="rect" coords="225, 54, 319, 125"> +<area href="#refresh" shape="rect" coords="91, 77, 226, 101"> +</map> +<img src="images/screen_menu_view.png" usemap="#menumap" /> +</p> + +<ul> + +<li><a name="advanced"></a> <span class="title">Advanced F7</span>: + +Toggles the display mode between <b>basic</b> and <b>advanced</b> modes. +In basic mode, the Network Identity Manager displays a list of identities +and their current status. In the advanced mode, NetIdMgr provides a +customizable list of all discovered credentials. +</li> + +<li><a name="all_ids"></a> <span class="title">All identities</span>: Toggles +the inclusion of all configured identities in the NetIdMgr identity lists.&nbsp; +If all identities is unchecked, only the default identity, pinned identities, +and identities with credentials are included in the NetIdMgr identity lists.</li> + +<li><a name="choosecol"></a> <span class="title">View columns</span>: + +<i>Only available in Advanced mode.</i> +Invokes a submenu from which you can choose the columns that are +displayed in the credentials window. If you change the columns, or +their order, a new custom layout will be created for you which you can +later use using the <span class="pre">Layout</span> submenu later. For +more information about managing layouts, see the <a href="use_layout.htm">Layout</a> topic.</li> + +<li><a name="layout"></a> <span class="title">Layout</span>: +<i>Only available in Advanced mode.</i> Opens a +submenu where you can select the layout for the credentials +display. + <ul> + + <li><span class="title">By Identity</span>: A predefined layout + where the credentials will be grouped by identity and by + credentials type, in that order.</li> + + <li><span class="title">By Type</span>: <b>Not implemented in + this release.</b> A predefined layout + where the credentials are grouped by credentials type</li> + + <li><span class="title">By Location</span>: A predefined layout + where the credentials are grouped by the location where they are + stored in. For Kerberos 5, the location is the name of the + credentials cache in which the tickets are stored, and for AFS, + the location is always the cache manager. Individual <a + href="concept_cred_pro.htm">credential providers</a> choose the + interpretation of the <span class="pre">location</span> property + as the concept of location changes from type to type.</li> + + <li><span class="title">Custom</span>: If you customize any of + the above layouts by adding, removing, reordering or changing + the sort or outline columns, then NetIDMgr will store your new + layout settings under this layout. Invoking this menu item + restores your customizations.</ul> + +</li> + +<li><a name="refresh"></a> <span class="title">Refresh view F5</span>: Refresh +the contents of the credentials view. This queries each <a +href="concept_cred_pro.htm">credential provider</a> for any +credentials and redraws the credentials view.</li> + +</ul> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/nidmgr.css b/krb5-1-6/src/windows/identity/help/html/nidmgr.css new file mode 100644 index 000000000..0fb975eb7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/nidmgr.css @@ -0,0 +1,122 @@ + body { + font-family: helvetica,sans-serif; + font-size: 9pt; + font-style: normal; + background-color: white; + margin-top: 0pt; + margin-left: 0pt; + margin-right: 0pt; + } + + h1 { border-bottom: 1px solid black; + padding: 1em; + font-size: 12pt; + background-color: rgb(247, 247, 247); + } + + h2 { } + + h3 { border-bottom: 1px solid lightgrey; + padding: 1em; + font-size: 11pt; + } + + h4 { border-bottom: 1px dashed lightgrey; + font-size: 10pt; + font-style: italic; + margin-left: 2em; + } + + p { margin-left: 1em; + margin-right: 1em; + } + + p.caption { margin-left: 1em; + margin-right: 1em; + font-style: italic; + } + + div.inline { float: left; + } + + div.sidebar { border: 1px solid rgb(255, 255, 0); + float: right; + background-color: rgb(255, 255, 185); + } + + a.external { } + + a.mail { } + + img { border: 0pt none ; + } + + span.pre { font-family: monospace; + } + + span.title { font-weight: bold; + } + + div.schema-space { border-left: 1px solid rgb(230, 206, 142); + padding: 0pt; + margin-left: 1em; + margin-top: 0.5em; + margin-bottom: 0.5em; + } + + div.schema-templ { border-left: 1px solid rgb(98, 161, 143); + background-color: rgb(208, 242, 233); + } + + div.schema-space-doc { margin: 1em 3em; + } + + p.schema-space { border-top: 1px solid rgb(230, 206, 142); + margin: 0pt; + padding: 1em; + font-weight: bold; + font-size: 10pt; + background-color: rgb(242, 233, 208); + } + + p.schema-reg { margin: 0pt; + padding-top: 0.4em; + padding-bottom: 0.4em; + background-color: rgb(247, 247, 247); + } + + span.schema-label { display: block; + float: left; + margin-left: 2em; + width: 10em; + } + + span.schema-value { width: 100%; + background-color: rgb(255, 255, 255); + padding-top: 0.3em; + padding-bottom: 0.3em; + } + + div.schema-value { border: 1px solid rgb(153, 171, 94); + background-color: rgb(234, 242, 208); + margin-left: 1em; + margin-right: 1em; + margin-bottom: 1em; + } + + p.schema-value-name { margin: 0.5em 1em; + padding: 0.5em 1em; + } + + span.schema-value-name { font-size: 10pt; + font-weight: bold; + } + + p.schema-value-type { } + + p.schema-value-def { } + + div.schema-value-doc { padding: 1em; + } + + diff --git a/krb5-1-6/src/windows/identity/help/html/tb_standard.htm b/krb5-1-6/src/windows/identity/help/html/tb_standard.htm new file mode 100644 index 000000000..69df96a62 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/tb_standard.htm @@ -0,0 +1,80 @@ +<html> +<head> + <title>Network Identity Manager - Standard Toolbar</title> + <meta name="description" content="Standard Toolbar"> + <meta name="keywords" content="standard toolbar"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> + <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Changing Passwords"> +<param name="Keyword" value="New Credentials"> +<param name="Keyword" value="Renew Credentials"> +<param name="Keyword" value="Import Credentials"> +<param name="Keyword" value="Destroy Credentials"> +<param name="Keyword" value="Change Password"> +<param name="Keyword" value="Refresh View"> +<param name="Keyword" value="Help"> +<param name="Keyword" value="Toolbar"> +</OBJECT> + +</head> +<body> + +<h1>Network Identity Manager - Standard Toolbar</h1> + +<p>The standard toolbar appears below along with descriptions of what +each button does. +</p> + +<p> +<img src="images/screen_tb_standard.png" /> +</p> + +<ol> + + <li><span class="title">New credentials</span>: Equivalent to + selecting <span class="pre"><a href="menu_credential.htm#new">New + credentials...</a></span> from the <span class="pre"><a + href="menu_credential.htm">Credential</a></span> menu. + <p> + See <a href="act_new_creds.htm">New Credentials Action</a> for more + information.</p></li> + + <li><span class="title">Renew credentials</span>: Equivalent to + selecting <span class="pre"><a + href="menu_credential.htm#renew">Renew Credentials</a></span> from + the <span class="pre"><a + href="menu_credential.htm">Credential</a></span> menu. + <p> + See <a href="act_renew_creds.htm">Renew Credentials Action</a> for + more information.</li> + + <li><span class="title">Import credentials</span>: Equivalent to + selecting <span class="pre"><a + href="menu_credential.htm#import">Import Credentials</a></span> from + the <span class="pre"><a + href="menu_credential.htm">Credential</a></span> menu. + </li> + + <li><span class="title">Destroy credentials</span>: Equivalent to + selecting <span class="pre"><a + href="menu_credential.htm#destroy">Destroy Credentials</a></span> + from the <span class="pre"><a + href="menu_credential.htm">Credential</a></span> menu.</li> + + <li><span class="title">Change password</span>: Equivalent to + selecting <span class="pre"><a + href="menu_credential.htm#chpw">Change Password ...</a></span> from + the <span class="pre"><a + href="menu_credential.htm">Credential</a></span> menu.</li> + + <li><span class="title">Refresh view</span>: Equivalent to selecting + <span class="pre"><a href="menu_credential.htm#refresh">Refresh + View</a></span> from the <span class="pre"><a + href="menu_credential.htm">Credential</a></span> menu.</li> + + <li><span class="title">Help</span>: Displays documentation</li> + +</ol> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/template.htm b/krb5-1-6/src/windows/identity/help/html/template.htm new file mode 100644 index 000000000..4e33fab94 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/template.htm @@ -0,0 +1,11 @@ +<html> +<head> + <title>Network Identity Manager - title</title> + <meta name="description" content=""> + <meta name="keywords" content=""> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/use_config.htm b/krb5-1-6/src/windows/identity/help/html/use_config.htm new file mode 100644 index 000000000..02e22a641 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/use_config.htm @@ -0,0 +1,306 @@ +<html> + +<head> +<title>Network Identity Manager - Configuration</title> +<meta name="description" content> +<meta name="keywords" content="configuration"> +<link rel="stylesheet" type="text/css" href="nidmgr.css"> +<Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Configuration"> +<param name="Keyword" value="General Options"> +<param name="Keyword" value="Appearance Options"> +<param name="Keyword" value="Notification Options"> +<param name="Keyword" value="Plug-in Management"> +<param name="Keyword" value="Kerberos v5 Configuration"> +<param name="Keyword" value="Kerberos v4 Configuration"> +<param name="Keyword" value="Identity Default Configuration"> +<param name="Keyword" value="Identity Configuration"> +</OBJECT> +<style> +<!-- + li.MsoNormal + {mso-style-parent:""; + margin-bottom:.0001pt; + text-autospace:none; + font-size:10.0pt; + font-family:"Times New Roman"; + margin-left:0pt; margin-right:0pt; margin-top:0pt} +--> +</style> +</head> + +<body> + +<h1>Network Identity Manager - Configuration</h1> +<p>All Network Identity Manager configuration options can be accessed via the +<span class="pre">Options</span> menu. The available configuration panels are: +</p> +<ul> + <li> + <p><span class="title">General</span>: General application options for NetIDMgr.</p> + </li> + <li> + <p><span class="title">Appearance</span>: Allows you to set the font used by + NetIDMgr.</p> + </li> + <li> + <p><span class="title">Identities</span>: Default settings for all identities + and settings for each identity. Details <a href="#cfg_idents">below</a>.</p> + </li> + <li> + <p><span class="title">Notifications</span>: Notification and timer options. + NetIDMgr can issue warnings when credentials are about to expire. This configuration + panel allows you to set the thresholds at which these warnings are issued. For + example, if the warning timeout is set for 10 minutes, NetIDMgr will issue a + warning 10 minutes before a credential expires.</p> + <p>The panel also allows you to control the credentials renew timer. If the + timer is disabled, NetIDMgr will not automatically attempt to renew credentials. + If the <span class="pre">Renew at half life intervals when possible</span> option + is set, then the timer will expire after the credential has less than half its + lifetime left. If the renewal operation fails, it will attempt another renwal + after half of the remaining liftime is over (i.e. when the credential has less + than 1/4 of its original lifetime left) and so on. </p> + </li> + <li> + <p><span class="title">Plug-ins</span>: Enable/disable and check the status of + registered plug-ins. Enabling or disabling a plug-in only takes effect after + a restart of NetIDMgr.</p> + </li> + <li> + <p><span class="title">Kerberos v5</span>: Kerberos v5 Credential Provider Configuration</p> + </li> + <li> + <p><span class="title">Kerberos v4</span>: Kerberos v4 Credential Provider Configuration</p> + </li> +</ul> +<p></p> +<h3>General Options</h3> +<p>The General options dialog, accessed via the Options menu, allows you to configure +operational properties specific to the NetIdMgr application.</p> +<p><img src="images/screen_config_general.png" /> </p> +<p>The <b>Obtain new credentials at startup (if none are present)</b> checkbox will +determine whether or not NetIdMgr will display the New Credentials dialog at startup +when no valid credentials exist.</p> +<p>The <b>Destroy all credentials on exit </b>option can be used to empty all of +the credential caches when the NetIdMgr is terminated.</p> +<p>The <b>Run NetIdMgr in taskbar notification area after window close </b>checkbox +determines the behavior of the window close button. When checked, NetIdMgr will +close the window but will continue running and can be accessed from the taskbar +notification area. When unchecked, NetIdMgr will behave as if File-&gt;Exit was selected +from the menu.</p> +<p><b>Clicking on the notification icon</b> can be configured to either Show Network +Identity Manager or Obtain New Credentials. This option controls which menu item +on the notification icon menu is the default action.</p> +<p>The <b>Monitor network connectivity</b> option determines whether or not NetIdMgr +monitors the configuration of IP addresses on the machine. When IP addresses are +added or removed and this feature is activated, the NetIdMgr will probe the identity +management servers (e.g., Kerberos Key Distribution Centers) to determine if they +are reachable and if so will automatically obtain credentials.</p> +<p>The <b>Log trace events to trace log at the following location</b> option is +used to activate a log file that can be used to help debug the behavior of NetIdMgr +and its plug-ins. Press the <b>Show log</b> button to view the log file in Windows +Notepad. </p> + +<h3>Appearance Options</h3> +<p>The Appearance Options page can be used to select an alternate typeface to be +used when displaying credentials in the NetIdMgr.</p> +<p><img src="images/screen_config_appearance.png" /> </p> + + +<a name="cfg_idents"></a> +<h3>Configuration of default settings for all identities</h3> +<p>The <span class="pre">Identities</span> configuration panel allows you to set +the defaults that will be used for all identities. However, most of the settings +displayed here can be overridden with specific per-identity settings. </p> +<p>The panel will have a number of sub panels (or tabs) corresponding to each plug-in +that maintains per-identity configuration. </p> +<p>A list of identities for which configuration information is maintained will be +shown under the main <span class="pre">Identities</span> configuration panel name. +Each of these correspond to a <a href="#cfg_ident">per identity</a> configuration +panel. </p> +<p>Note that adding or removing an identity in the configuration panel only has +the effect of adding or removing the identity to or from the list of identities +for which configuration information is maintained. </p> + +<h4>Global Identity Settings</h4> +<p><img src="images/screen_config_idents.png" /> </p> +<p class="MsoNormal">There are three general settings that can be used to set +global defaults.</p> +<p class="MsoNormal">The <b>Monitor credential expiration</b> setting determines +whether or not NetIdMgr should monitor the credential lifetimes and issue +expiration notifications.&nbsp;&nbsp; This value is used as the default for all new +identities.</p> +<p class="MsoNormal">The <b>Automatically renew</b> setting determines if <i> +renewable</i> credentials are automatically renewed prior to expiration.&nbsp; This +value is used as the default for all new identities.</p> +<p class="MsoNormal">The <b>Always show in the credentials list (Pinned)</b> +setting determines whether new identities are always pinned within the +credentials list.&nbsp; A pinned identity will always be displayed regardless of +whether or not there are credentials associated with it.</p> + +<h4>Global Kerberos v5 Identity Settings</h4> +<p><img src="images/screen_config_global_krb5.png" /> </p> +<p class="MsoNormal">The global Kerberos v5 settings define default credential +lifetimes and minimum and maximum values for use in constructing the slider +controls used to set the lifetimes.&nbsp; </p> +<p class="MsoNormal">There are two expiration times associated with Kerberos +tickets.&nbsp; The first specifies the length of the time period during which the +tickets are valid for use.&nbsp; The second specifies the length of the renewable +lifetime.&nbsp; Valid Kerberos tickets may have their valid use lifetime repeatedly +extended up until the renewable lifetime expires.&nbsp; The settings on this page are +used to configure default lifetime values for NetIdMgr to use when requesting +Kerberos tickets from the Kerberos server (key distribution center).&nbsp; The +Kerberos server may issue tickets with shorter lifetimes than were requested.</p> +<p class="MsoNormal">The <b>Renewable</b>, <b>Forwardable</b>, and <b> +Addressless</b> options determine whether or not new identities default to +obtaining Kerberos v5 tickets with these options.</p> +<p class="MsoNormal">When <b>Forwardable </b>tickets are received from the +Kerberos Server, these tickets can be forwarded to a remote host when you +connect via telnet, ssh, ftp, rlogin, or similar applications.&nbsp; When tickets are +forwarded, there is no need to obtain Kerberos tickets again to access +Kerberized services on the remote host.&nbsp;&nbsp; <b>Forwardable</b> tickets are often +required when authenticating to a remote host using ssh or ftp when the remote +host requires the ability to authenticate to a remote file system such as AFS.</p> +<p class="MsoNormal">When <b>Renewable</b> tickets are received from the +Kerberos Server, the ticket lifetimes may be renewed without prompting the user +for her password.&nbsp; This allows Kerberos tickets to be issued with short +lifetimes allowing compromised accounts to be disabled on short notice without +requiring the user to enter a password every few hours.&nbsp; When combined with <b> +Automatic Ticket Renewal</b>, NetIdMgr can maintain valid tickets for a week, a +month, or longer by automatically renewing tickets prior to their expiration.&nbsp; +The ability to renew tickets without a password is limited by the ticket’s +renewable lifetime as issued by the Kerberos Server.</p> +<p class="MsoNormal">When <b>Addressless</b> is selected, the tickets do not +contain IP address information.&nbsp; This enables the tickets to be used from behind +Network Address Translators which are frequently found in Cable and DSL Modems.</p> +<p class="MsoNormal">The minimum and maximum ranges are used by the ticket +initialization dialog box when constructing the Lifetime and Renewable Lifetime +sliders.&nbsp; These sliders can be used to modify the requested ticket lifetimes +when Kerberos tickets are initialized.</p> + +<h4>Global Kerberos v4 Identity Settings</h4> +<p><img src="images/screen_config_global_krb4.png" /> </p> +<p class="MsoNormal">When the <b>Obtain Kerberos v4 credentials</b> button is +checked, NetIdMgr will attempt to retrieve Kerberos v4 credentials when ticket +initialization, renewal, or importation is performed. &nbsp;Kerberos realms are +increasingly configured to support only Kerberos v5 (e.g., Windows Active +Directory Domains.)&nbsp; If the realms you use do not support Kerberos v4 it is +suggested that this button be unchecked.</p> +<p class="MsoNormal">Be aware that only the default identity can obtain Kerberos +v4 credentials.&nbsp;&nbsp; This limitation is due to the inability of Kerberos v4 +applications on Microsoft Windows to specify a credentials cache. </p> + + +<a name="cfg_ident"></a> +<h3>Per identity configuration</h3> +<p>You can access the per-identity configuration panel for a specific identity by +selecting the identity name from the list of configuration panels in the configuration +dialog. </p> +<p>These panels are similar to the <span class="pre">Identities</span> configuration +panel, but they change per-identity settings. Changes you make in these panels will +override the defaults set in the <span class="pre">Identities</span> panel. </p> +<h4>Per identity General Configuration</h4> +<p><img src="images/screen_config_ident.png" /> </p> +<p class="MsoNormal">The General page contains a <b>Remove Identity</b> button +that can be used to delete this Identity from the Network Identity Manager.</p> + +<h4>Per identity Kerberos v5 Configuration</h4> + +<p><img src="images/screen_config_ident_krb5.png" /> </p> +<p class="MsoNormal">The Kerberos v5 page displays the name of the credential +cache currently associated with the Identity.</p> + +<h4>Per identity Kerberos v4 Configuration</h4> + +<p><img src="images/screen_config_ident_krb4.png" /></p> +<p class="MsoNormal">The Kerberos v4 page is optional and may not appear on all +systems.&nbsp; Only one identity can obtain Kerberos v4 credentials at a time.&nbsp; </p> + +<h3>Notification Configuration</h3> + +<p><img src="images/screen_config_notifications.png" /> </p> +<p class="MsoNormal">The <b>Renew automatically at</b> check box determines +whether or not renewable tickets will be renewed by NetIdMgr when they reach the +specified time remaining.&nbsp;&nbsp; </p> +<p class="MsoNormal">The <b>Initial warning at</b> check box determines whether +or not a warning will be issued when the specified time remaining is reached.</p> +<p class="MsoNormal">The <b>Final warning at</b> check box determines whether or +not a warning will be issued when the specified time remaining is reached.</p> +<p class="MsoNormal">Notifications are performed in two ways.&nbsp; First, icons are +displayed next to the affected credentials in the flags column of the display.&nbsp; +Second, a balloon tip is displayed off of the NetIdMgr taskbar notification area +icon.</p> + +<h3>Plug-in Configuration</h3> +<p><img src="images/screen_config_plug_ins.png" /> </p> +<p><span style="font-size: 10.0pt; font-family: Times New Roman">The Plug-ins +and Modules page provides status information on the currently loaded plug-ins +and modules include a description of their purpose; whether or not it was loaded +properly; which other modules are required; and what organization developed it. +</span> </p> + +<h4>Kerberos v5 Plug-in Configuration</h4> + +<p><img src="images/screen_config_plug_in_krb5.png" /> </p> +<p class="MsoNormal">The <b>Kerberos v5 Configuration</b> tab allows you to +alter the behavior of&nbsp; the Kerberos v5 identity provider.&nbsp; </p> +<p class="MsoNormal">In the <b>Default Realm</b> field, select a Kerberos realm +from the dropdown list.</p> +<p class="MsoBodyTextIndent2" style="text-indent:0pt">The <b>Include all +configured realms in New Credentials realm list</b> determines whether all of +the realms declared in the Kerberos v5 Configuration file are included in the +realms list of the <b>Obtain New Credentials</b> dialog.&nbsp; If disabled, only the +realms previously used to obtain credentials are displayed.</p> +<p class="MsoBodyTextIndent2" style="text-indent:0pt">The <b>Configuration File +</b>field displays the path to the Kerberos v5 configuration file, krb5.ini.</p> +<p class="MsoNormal"><span style="display: none">The Kerberos libraries depend +on configuration files for their proper operation.&nbsp; When <b>Create file if +missing </b>is checked, NetIdMgr will construct replacements for missing +configuration files upon startup.&nbsp; This is performed by extracting Kerberos +configuration information from the local Windows registry and the Domain Name +System.&nbsp; The contents of the created file may then be edited using the <b> +Kerberos Properties Dialog</b>.&nbsp; [This functionality is not available in this +release.]</span></p> +<p class="MsoNormal">The field labeled <b>Host Name</b> displays the name of +your local machine.&nbsp; The <b>Domain Name</b> field displays the domain to which +your local machine currently belongs.&nbsp;</p> +<p class="MsoNormal">The <b>Import Tickets</b> listbox allows you to configure +how NetIdMgr interacts with the Microsoft Kerberos Authentication Provider.&nbsp; +NetIdMgr will automatically import Kerberos Tickets from the Microsoft LSA at +startup depending upon the selected option and whether or not the Kerberos +Authentication Provider was used for Windows Logon authorization.&nbsp; </p> +<ul style="margin-top: 0pt; margin-bottom: 0pt" type="disc"> + <li class="MsoNormal"><b>Never</b> means do not import tickets from the + MSLSA; </li> + <li class="MsoNormal"><b>Always</b> means do import tickets from the MSLSA; + and </li> + <li class="MsoNormal"><b>Only when the Principal matches</b> means import + tickets from the MSLSA only if the MSLSA Kerberos principal belongs to the + Default Realm.</li> +</ul> +<p class="MsoNormal">When the Windows Logon identity is imported and is +configured as the default identity, the MIT credential cache will be used in +preference to the MSLSA credential cache.</p> + +<h4>Kerberos v5 Realm Configuration</h4> +<p><img src="images/screen_config_plug_in_krb5_realm.png" /> </p> + +<h4>Kerberos v5 Credential Cache Configuration</h4> +<p><img src="images/screen_config_plug_in_krb5_ccache.png" /> </p> +<p class="MsoNormal">The Kerberos Realm Configuration dialog can be used to +manage the contents of the [Realms] and [Domain_Realm] sections of the Kerberos +v5 configuration file.</p> + +<h4>Kerberos v4 Plug-in Configuration</h4> +<p><img src="images/screen_config_plug_in_krb4.png" /> </p> +<p class="MsoBodyTextIndent2" style="text-indent:0pt">Here, you can specify the +name of the in-memory cache used to store the Kerberos v4 tickets.&nbsp; The format +of the name is “API:” followed by the cache name.&nbsp; Disk caches are not supported +by Kerberos for Windows.</p> +<p class="MsoNormal">The paths to the Kerberos v4 configuration files: krb.con +and krbrealm.con may be viewed from this dialog.&nbsp; The default is to store the +configuration files in the Windows directory.</p> + +</body> + +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/use_icon.htm b/krb5-1-6/src/windows/identity/help/html/use_icon.htm new file mode 100644 index 000000000..bb8af5225 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/use_icon.htm @@ -0,0 +1,74 @@ +<html> +<head> + <title>Network Identity Manager Notification Icon</title> + <meta name="description" content="NetIDMgr Notification Icon"> + <meta name="keywords" content="icon, netidmgr, notification, tray"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager Notification Icon</h1> +<h3>Visual Representation of Identity State Information</h3> + +<p>When Network Identity Manager is running, an icon will appear in the taskbar notification area.&nbsp; The icon will change to reflect the current state of +the managed credentials.</p> + +<p>The icons and their meanings are described below:</p> + +<table width="100%" border="1"> + +<tr> +<td><img src="images/appicon_empty.png" /></td> +<td>There are no managed credentials for any identity.</td> +</tr> + +<tr> +<td><img src="images/appicon_good.png" /></td> +<td>There are valid credentials for all the identities.</td> +</tr> + +<tr> +<td><img src="images/appicon_warnexp.png" /></td> <td>Some of the +credentials will expire in the next few minutes. This icon will be +displayed even if automatic renewals are enabled. In this case, the +credentials in question may get renewed before they expire, and the +icon will change to reflect this change.</td> </tr> + +<tr> +<td><img src="images/appicon_expired.png" /></td> +<td>At least one identity's credentials have expired.</td> +</tr> + +<tr> +<td><img src="images/appicon_warning.png" /></td> <td>A warning +message is waiting to be displayed. Click the icon to view the +warning message.</td> </tr> + +</table> + +<h3>Notification Icon Menu</h3> +<p>Clicking on the notification with the second mouse button displays a menu +(see right) which contains the most commonly used Network Identity Manager +operations.&nbsp; </p> + +<ul> + <li><a href="act_new_creds.htm">Obtaining new credentials</a></li> + <li><a href="act_renew_creds.htm">Renew credentials</a></li> + <li><a href="act_import_creds.htm">Import credentials from the Microsoft Logon + Session cache</a></li> + <li><a href="act_destroy_creds.htm">Destroying credentials</a></li> + <li><a href="act_set_default.htm">Setting the Default Identity</a></li> + <li><a href="act_chpw.htm">Change password</a></li> +</ul> + +<div class="sidebar"> +<img src="images/notification_icon_menu.png" /> +<p class="caption">Figure 1. Notification Icon Menu</p> +</div> +<p></p> +<h3>Notification Icon Default Action</h3> + +<p>Clicking on the icon with the first mouse button will open or close the Network Identity Manager application window or open the Obtain New Credentials dialog based upon the current configuration. The behavior can be adjusted from the Options-&gt;General page. Clicking with the second mouse button will display a menu of commands.</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/use_layout.htm b/krb5-1-6/src/windows/identity/help/html/use_layout.htm new file mode 100644 index 000000000..351cafd5f --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/use_layout.htm @@ -0,0 +1,91 @@ +<html> +<head> + <title>Network Identity Manager - Managing the credentials view layout</title> + <meta name="description" content="Managing the credentials view layout"> + <meta name="keywords" content="view, layout"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> + <Object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Credential View Layouts"> +<param name="Keyword" value="Sorting credentials by a column"> +<param name="Keyword" value="Grouping credentials by a column"> +<param name="Keyword" value="Selecting Columns"> +</OBJECT> +</head> +<body> + +<h1>Network Identity Manager - Managing the credentials view layout</h1> + +<p>The credentials view layout provides an outlined view of the +credentials that are being managed by NetIDMgr. The columns that are +displayed in the window, the columns that are used for grouping and +sorting the list of credentials can be customized. </p> + +<p>The following sections provide more details on the types of +customizations that can be performed:</p> + +<ul> + <li><a href="#predef">Predefined layouts</a></li> + <li><a href="#addcol">Adding and removing columns.</a></li> + <li><a href="#sort">Sorting by a column.</a></li> + <li><a href="#group">Grouping by a column.</a></li> +</ul> + +<a name="predef"></a> +<h3>Pre-defined layouts</h3> + +<p>The predefined layouts in NetIDMgr are:</p> + +<ul> + + <li><span class="title">By Identity</span>: Credentials grouped by + identity, credentials type and location, and finally sorted by + credential name.</li> + + <li><span class="title">By Type</span>: Credentials grouped by + credentials type and then by identity.</li> + + <li><span class="title">By Location</span>: Credentials grouped by + location, identity and then by credentials type. The location is + reported by individual credentials providers that indicate where + each credential is stored. For Kerberos 5 and Kerberos 4, this is a + credentials cache name.</li> + +</ul> + +<a name="addcol"></a> +<h3>Adding and removing columns</h3> + +<p>The <span class="pre">View Columns</span> menu lists all the +columns that are available for display. Each column that is already +displayed will have a check mark next to it. Selecting a column that +is not currently being displayed will add that column to the display. +Selecting a column that is is being displayed will remove it from the +display.</p> + +<p>This menu can be reached either by right-clicking the column header +area or by invoking the <span class="pre">View</span> menu. The menu +is shown below.</p> + +<p><img src="images/screen_menu_view_cols.png"/> </p> + +<a name="sort"></a> +<h3>Sorting by a column</h3> + +<p>Clicking on a column header will change the sort order of the +column if it is already being used as a sort key. If the colunm is +not currently being used as a sort key, clicking on the column header +will start sorting in increasing order by that column.</p> + +<p>Double-clicking a column that is not used for grouping will stop +sorting by that column.</p> + +<a name="group"></a> +<h3>Grouping by a column</h3> + +<p>Double-clicking on a column header will start grouping by that +column if the column is currently not being used as a sort key. If +the column is currently being used for grouping, then double-clicking +will stop it from being used for grouping.</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/use_start.htm b/krb5-1-6/src/windows/identity/help/html/use_start.htm new file mode 100644 index 000000000..3e7b5fa82 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/use_start.htm @@ -0,0 +1,70 @@ +<html> +<head> + <title>Network Identity Manager - Starting Network Identity Manager</title> + <meta name="description" content="starting NetIDMgr"> + <meta name="keywords" content="starting"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Network Identity Manager - Starting Network Identity Manager</h1> + +<h3>Opening the Network Identity Manager window from the notification icon</h3> + +<p>Depending on how Network Identity Manager was installed, it may be configured +with a shortcut in the Startup Folder, or it may require a manual start. NetIDMgr is a +notification tray application and therefore it is not listed in the Microsoft +Windows task bar.&nbsp; This design is based on the assumption that most users +rarely interact directly with the application.</p> + +<div class="sidebar"> +<img src="images/screen_tray_icon.png"/> +<p class="caption">Figure 1: NetIDMgr notification icon</p> +</div> + +<p>When NetIDMgr is running, it places an icon in the system +notification area (sometimes referred to as the "system tray") as +shown in figure 1. Details about the state information represented by +the icon can be found <a href="use_icon.htm">here</a>.</p> + +<p>Left clicking on this icon executes the default action which either changes +the view state of the credential list or displays the <i>Obtain New Credentials</i> +dialog. Right clicking on the icon displays a menu.</p> + +<h3>Starting Network Identity Manager from the Start Menu or command line</h3> + +<div class="sidebar"> +<img src="images/screen_app_icon.png" /> +<p class="caption">Figure 2: NetIDMgr application shortcut</p> +</div> + +<p>If NetIDMgr was not configured to start automatically when you +login to Windows, then you need to start it either from the +commandline or the start menu. The start menu application icon is +under "Kerberos for Windows" as shown in figure 2.</p> + +<p>Alternatively, you can type 'netidmgr' at a command shell to start +NetIDMgr as well. When starting this way, you may specify additional +<a href="cmdline_netidmgr.htm">command line options</a>.</p> + +<h3>Configuring startup options</h3> + +<p> +Note that you can configure options related to the startup of NetIDMgr +by using the NetIDMgr configuration dialog box. You can use the menu +items under the <span class="pre">Options</span> menu to invoke the +configuration dialog. +</p> + +<p> +Only one instance of NetIDMgr can be running at any one time. +Attempting to start NetIDMgr while it is still running will not do +anything, unless you provide any command line options that trigger +some action in the running application instance. If more than one +version of NetIDMgr is installed on the system, and the older version +is running at the time the newer version is started, the older version +will exit allowing the newer version to take over. +</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/using.htm b/krb5-1-6/src/windows/identity/help/html/using.htm new file mode 100644 index 000000000..7b5520147 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/using.htm @@ -0,0 +1,58 @@ +<html> +<head> + <title>Using Network Identity Manager</title> + <meta name="description" content="Using NetIDMgr"> + <meta name="keywords" content="using"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> +</head> +<body> + +<h1>Using Network Identity Manager</h1> + +<p> +Depending on how Network Identity Manager was installed, it might already be running +in the Windows taskbar notification area or it might need to be started +manually. See the topic <a href="use_start.htm">Starting +Network Identity Manager</a> for details.&nbsp; +</p> +<p> +To open the NetIDMgr window when the <a href="use_icon.htm">application +icon</a> is displayed in the Windows taskbar notification area, click on the +icon with the 2nd mouse button (usually the right mouse button) and select <b>Show Network Identity Manager window</b> from the menu. +</p> +<p> +If NetIdMgr is not displayed in the Windows taskbar notification area, it can be +started from the +Start Menu, or type 'netidmgr' at a command prompt. +</p> + +<p> +Once the NetIDMgr window is visible, you will be presented with a view +of your existing identities, or a message notifying you that you +don't have any.&nbsp;&nbsp; Details of the credentials view objects <a +href="wnd_main.htm">can be found here.</a> +</p> + +<p> +Brief overviews of how to perform common tasks are linked below: +</p> + +<ul> + <li><a href="act_new_creds.htm">Obtaining new credentials</a></li> + <li><a href="act_renew_creds.htm">Renew credentials</a></li> + <li><a href="act_import_creds.htm">Import credentials from the Microsoft Logon + Session cache</a></li> + <li><a href="act_destroy_creds.htm">Destroying credentials</a></li> + <li><a href="act_chpw.htm">Change password</a></li> + <li><a href="act_set_default.htm">Setting the default identity</a></li> + <li><a href="use_layout.htm">Customizing the advanced credentials view layout</a></li> + <li><a href="use_config.htm">Configuring Network Identity Manager</a></li> + <li><a href="tb_standard.htm">Using the Toolbar</a></li> +</ul> + +<p> +A more comprehensive list of how-to topics can be found in the +<a href="howdoi.htm">How do I...</a> section.</p> + +</body> +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/welcome.htm b/krb5-1-6/src/windows/identity/help/html/welcome.htm new file mode 100644 index 000000000..a12c1d37d --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/welcome.htm @@ -0,0 +1,130 @@ +<html> +<head> + <title>Welcome to the Network Identity Manager</title> + <meta name="description" content="Welcome"> + <meta name="keywords" content="welcome"> + <link rel="stylesheet" type="text/css" href="nidmgr.css"> + <style> +</style> +</head> + +<h1>Welcome to the Network Identity Manager</h1> + +<div class="inline"> +<img src="images/logo.jpg" width="100" height="100"/> +</div> + +<p>Network Identity Manager (NetIdMgr) is a graphical +tool designed to simplify the management of network identities and their credentials +which are used by network authentication protocols while providing +secure access to network services.&nbsp; When NetIDMgr is used with Kerberos v5 each +network identity is a unique Kerberos principal name and the credentials +are Kerberos v5 tickets.&nbsp; Kerberos v5 tickets can be used by NetIDMgr to +obtain Andrew File System (AFS) tokens and X.509 public key certificates if the +appropriate plug-ins are installed.</p> +<p>When you log into Microsoft Windows with a domain account, +your account name and the Windows Domain name when combined form a Kerberos +principal name.&nbsp; As an example, “WINDOWS\jaltman” is actually a short form +representation of +jaltman@WINDOWS.SECURE-ENDPOINTS.COM.&nbsp;&nbsp; Microsoft Windows uses +Kerberos-based network identities for all domain-based network authentications.&nbsp; +</p> +<p>Since Microsoft Windows already provides a network +identity, why do you need NetIdMgr?&nbsp; Here are some examples:</p> +<ol> + <li>Your only network identity is your Windows Domain + account but you have third-party applications that rely on MIT Kerberos for + authentication for access to remote files, e-mail, web data, or other + services.&nbsp; In this scenario, NetIdMgr will automatically import your Windows + Domain credentials into a form that can be used by applications that rely on + MIT Kerberos.</li> + <li>You do not have a Windows Domain account but you must + obtain network credentials in order to securely access a network service.&nbsp; + In this scenario, NetIdMgr can be used to obtain new credentials for network + identities and can automatically renew them before they expire.</li> + <li>You have Kerberos credentials for a network identity + and you have third-party applications that require an alternative form of + network credential, such as an AFS token or a X.509 certificate, which can + be obtained via a Kerberos authentication.&nbsp; In this scenario, NetIdMgr can + automatically use your existing credentials to obtain and renew the + additional network credentials types.</li> + <li>You have a Windows Domain account but you need to + authenticate to a service belonging to a Kerberos realm outside the Windows + Domain.&nbsp; In this scenario, NetIdMgr can be used to manage multiple network + identities, the Windows Domain identity as well as the additional Kerberos + identity required for the external network services.&nbsp; </li> + <li>You have multiple network identities within the same + Kerberos realm which are used for different roles.&nbsp; For example, an + unprivileged user identity and a privileged identity that is only meant to + be used for system administration.&nbsp; In this scenario, NetIdMgr can be used + to obtain credentials for all of your identities and automatically renew + them as necessary.</li> +</ol> +<p>NetIdMgr’s automated credential acquisition and renewal +makes it an invaluable tool which provides users with a Single Sign-on +experience. </p> +<p>NetIdMgr is most commonly configured as a StartUp item that runs an icon in the Taskbar Notification Area until you logout.&nbsp; +While running, NetIDMgr automatically renews your credentials, notifies you of +pending expirations and prompts you when a Kerberized application requires +credentials that have not already been obtained.&nbsp; </p> +<p>When configured to do so, NetIdMgr will prompt you +immediately after it starts to obtain Kerberos credentials.&nbsp; This is often +referred to as logging on to Kerberos.&nbsp; NetIdMgr does not perform a logon in the +sense of the Windows Logon Service.&nbsp; A logon service would do more than manage +Kerberos tickets. A logon service would authenticate you to the local machine, +validate access to your local file system and performs additional set-up tasks. +These are beyond the scope of NetIdMgr. NetIdMgr simply allows you to manage +Kerberos identities on behalf of compatible applications and to change your +Kerberos password.</p> +<p> +NetIDMgr is distributed as a part of MIT Kerberos for Windows +along with the Kerberos v5 and Kerberos v4 plug-ins. Plug-ins for additional +credential types including AFS tokens and KCA certificates are available as +separate distributions.&nbsp; The OpenAFS plug-in, which is required for supporting AFS tokens, is +distributed as part of <a href="http://www.openafs.org/windows.html">OpenAFS for +Windows</a>.&nbsp; The KCA plug-in is distributed by +<a href="http://www.secure-endpoints.com/">Secure Endpoints Inc.</a></p> + +<ul> +<li><a href="copyright.htm">Legal information</a></li> +<li><a href="bugs.htm">Reporting problems</a></li> +</ul> + +<h3>Getting started</h3> + +<ul> +<li><a href="concepts.htm">Network Identity Manager concepts</a></li> +<li><a href="using.htm">Using Network Identity Manager</a></li> +<li><a href="howdoi.htm">How do I ...</a></li> +<li><a href="menu_all.htm">All Menus</a></li> +</ul> + +<h3>Information for developers</h3> + +<p> +If you are interested in developing plug-ins or extending the features +of NetIDMgr, your first stop should be the NetIDMgr SDK which is included in the +MIT Kerberos for Windows SDK.</p> + +<p> +Contact the <a +href="mailto:netidmgr@secure-endpoints.com">netidmgr@secure-endpoints.com</a> +mailing list with questions or comments.</p> + +<h3>External links</h3> + +<ul> +<li><a class="external" href="http://web.mit.edu/kerberos">http://web.mit.edu/kerberos</a>: + +MIT Kerberos distribution +</li> +<li><a class="external" href="http://www.openafs.org/windows.html">http://www.openafs.org/windows.html</a>: + +OpenAFS for Windows +</li> +<li> +<a class="external" href="http://www.secure-endpoints.com/">http://www.secure-endpoints.com/</a>: +Secure Endpoints Inc.</li> +</ul> + +</html> \ No newline at end of file diff --git a/krb5-1-6/src/windows/identity/help/html/wnd_main.htm b/krb5-1-6/src/windows/identity/help/html/wnd_main.htm new file mode 100644 index 000000000..85707cd6e --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/html/wnd_main.htm @@ -0,0 +1,114 @@ +<html> + +<head> +<title>Network Identity Manager - Application Window</title> +<meta name="description" content="Main Window"> +<meta name="keywords" content="main window"> +<link rel="stylesheet" type="text/css" href="nidmgr.css"> +<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> +<param name="Keyword" value="Application Window Basic View"> +<param name="Keyword" value="Application Windows Advanced View"> +<param name="Keyword" value="Identity Views"> +</object> +<style> +v\:* { behavior: url(#default#VML) } +o\:* { behavior: url(#default#VML) } +</style> +<!--[if gte mso 9]><xml><o:shapedefaults v:ext="edit" spidmax="1027"/> + +</xml><![endif]--> +</head> + +<body> + +<h1>Network Identity Manager - Application Window</h1> +<p>The application window of Network Identity Manager can be displayed in two modes: +<b>basic</b> and <b>advanced</b>.</p> +<p>The basic view provides status information of the currently available identities +whereas the advanced view provides more detailed information of all the active credentials.</p> +<div> +<img src="images/screen_main_wnd_basic.png" /> +<p class="caption">Figure 1. Network Identity Manager Basic View</p> +</div> +<div> +<img src="images/screen_main_wnd.png" /> +<p class="caption">Figure 2. Network Identity Manager Advanced View</p> +</div> +<ol> +<li>Menu bar</li> +<li>Tool bar</li> +<li>Credentials list</li> +</ol> +<h3>Identity views</h3> +<p>The advanced credentials view organizes them grouped by identity name and then +by credential type. Each credential is then shown under each group heading sorted +by the credential name. The default headings for the credential view provides you +with a minimal amount of information to reduce clutter. If you wish you can add +columns to the display using the <span class="pre">Choose columns...</span> action +on the <span class="pre"><a href="menu_view.htm">View</a></span> menu. </p> +<p>The header backgrounds and the credential rows change color if the credentials +are about to expire or are expired. </p> +<ul> +<li><span style="background-color:#fbc74d">Headers</span> mean that credentials +at that level will expire unless renewed. Credentials will have a warning icon +next to them.<br /> +The threshold for this can be set as the <span class="pre">Warn</span> parameter +in the <span class="pre">Notifications</span> configuration panel.</li> +<li><span style="background-color:#f08575">Headers</span> mean that credentials +at that level will expire in a few minutes. Credentials will have a critical +icon next to them.<br /> +The threshold for this can be set as the <span class="pre">Warn again</span> +parameter in the <span class="pre">Notifications</span> configuration panel. +</li> +<li><span style="background-color:#ff9090">Headers</span> mean that the credentials +at that level have expired. Credentials will have an expired icon next to them.<br /> +The threshold for this is always zero. </li> +</ul> +<p class="MsoNormal">In its default configuration, the NetIdMgr advanced view displays +a list of network identity names (aka Kerberos principals, user@REALM).&nbsp; Each +entry appears with a +<img border="0" width="16" height="15" src="images\wdg_collapsed_hi.bmp"> +or <img border="0" width="16" height="15" src="images\wdg_expanded_hi.bmp"> +button, a pushpin <img border="0" width="16" height="15" src="images\wdg_stuck_hi.bmp"> +or <img border="0" width="16" height="15" src="images\wdg_stick_hi.bmp">&nbsp; +button and an Identity icon <img border="0" width="16" height="15" src="images\id-sm.bmp"> +to its left.&nbsp; </p> +<p class="MsoNormal">Click on the +<img border="0" width="16" height="15" src="images\wdg_collapsed_hi.bmp"> +button of an identity to expand the branch, displaying a <img border="0" width="16" height="15" src="images\wdg_expanded_hi.bmp"> + +button.&nbsp; Click on the <img border="0" width="16" height="15" src="images\wdg_expanded_hi.bmp"> +button to hide the branch.</p> +<p class="MsoNormal">Click on the pushpin <img border="0" width="16" height="15" src="images\wdg_stuck_hi.bmp"> +or <img border="0" width="16" height="15" src="images\wdg_stick_hi.bmp">&nbsp; +button to pin the identity to the display.&nbsp; A pinned identity will be +displayed in the identity list regardless of whether or not it has matching +credentials.</p> +<p class="MsoNormal">Click on the Identity icon <img border="0" width="16" height="15" src="images\id-sm.bmp"> +to view the identity's properties dialog.</p> +<p class="MsoNormal">To the right of each credential is a flag icon representing +one of the following states: </p> +<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +None&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = credentials are valid</p> +<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +<img border="0" width="16" height="15" src="images\flag_renewable.bmp"> +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; += credentials are valid and renewable</p> +<p class="MsoNormal" style="text-indent:36.0pt"><img border="0" width="16" height="15" src="images\flag-warning.bmp"> +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; += credentials are valid and the initial expiration warning has been issued </p> +<p class="MsoNormal" style="text-indent:36.0pt"> +<img border="0" width="16" height="15" src="images\flag-critical.bmp"> +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; += credentials are valid and the final expiration warning has been issued</p> +<p class="MsoNormal" style="text-indent:36.0pt"> +<img border="0" width="16" height="15" src="images\flag_expired.bmp"> +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; += credentials are invalid or expired</p> +<p class="MsoNormal">&nbsp;</p> +<p>&nbsp;</p> +<p></p> + +</body> + +</html> diff --git a/krb5-1-6/src/windows/identity/help/khhelp.h b/krb5-1-6/src/windows/identity/help/khhelp.h new file mode 100644 index 000000000..f6fbd3f78 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/khhelp.h @@ -0,0 +1,33 @@ +#define IDH_WELCOME 1000 +#define IDH_WIN_MAIN 1001 + +#define IDH_MENU_FILE 1501 +#define IDH_MENU_CRED 1502 +#define IDH_MENU_VIEW 1503 +#define IDH_MENU_OPTIONS 1504 +#define IDH_MENU_HELP 1505 + +#define IDH_ACTION_PROPERTIES 2000 +#define IDH_ACTION_EXIT 2001 +#define IDH_ACTION_NEW_ID 2002 +#define IDH_ACTION_SET_DEF_ID 2003 +#define IDH_ACTION_SET_SRCH_ID 2004 +#define IDH_ACTION_DESTROY_ID 2005 +#define IDH_ACTION_RENEW_ID 2006 +#define IDH_ACTION_PASSWD_ID 2007 +#define IDH_ACTION_NEW_CRED 2008 +#define IDH_ACTION_CHOOSE_COLS 2009 +#define IDH_ACTION_DEBUG_WINDOW 2010 +#define IDH_ACTION_VIEW_REFRESH 2011 +#define IDH_ACTION_OPT_KHIM 2012 +#define IDH_ACTION_OPT_INIT 2013 +#define IDH_ACTION_OPT_NOTIF 2014 + +#define IDH_NC_CREDWND 3000 +#define IDH_NC_OK 3001 +#define IDH_NC_CANCEL 3002 +#define IDH_NC_HELP 3003 +#define IDH_NC_TABBUTTON 3004 +#define IDH_NC_ADVANCED 3005 +#define IDH_NC_TABMAIN 3006 +#define IDH_NC_SETDEF 3007 diff --git a/krb5-1-6/src/windows/identity/help/netidmgr.hhp b/krb5-1-6/src/windows/identity/help/netidmgr.hhp new file mode 100644 index 000000000..b22e07a0a --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/netidmgr.hhp @@ -0,0 +1,35 @@ +[OPTIONS] +Auto Index=Yes +Compatibility=1.1 or later +Compiled file=netidmgr.chm +Contents file=toc.hhc +Default Window=MainHelpWnd +Default topic=html/welcome.htm +Display compile progress=No +Index file=Index.hhk +Language=0x409 English (United States) +Title=NetIDMgr + +[WINDOWS] +MainHelpWnd="NetIDMgr Help","toc.hhc","Index.hhk","html/welcome.htm","html/welcome.htm",,,,,0x42120,,0x384e,[271,372,593,566],0x830000,,,,,,0 + + +[ALIAS] +IDH_ACTION_NEW_ID=html\act_new_creds.htm +IDH_ACTION_PASSWD_ID=html\act_chpw.htm +IDH_WELCOME=html\welcome.htm + +[MAP] +#include khhelp.h + +[TEXT POPUPS] +khhelp.h +popups_newcreds.txt +popups_password.txt + +[INFOTYPES] +Category:Concepts +CategoryDesc:Authentication, authorization and related concepts. +Category:Usage +CategoryDesc:Usage instructions for NetIDMgr + diff --git a/krb5-1-6/src/windows/identity/help/popups.txt b/krb5-1-6/src/windows/identity/help/popups.txt new file mode 100644 index 000000000..564d4ddac --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/popups.txt @@ -0,0 +1 @@ +foo diff --git a/krb5-1-6/src/windows/identity/help/popups_newcreds.txt b/krb5-1-6/src/windows/identity/help/popups_newcreds.txt new file mode 100644 index 000000000..1ab97f378 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/popups_newcreds.txt @@ -0,0 +1,30 @@ +.topic IDH_NC_TABMAIN +Opens the identity selection panel. + +.topic IDH_NC_TABBUTTON +Opens the option panel for this credentials type. + +.topic IDH_NC_OK +Obtains new credentials using the information that you provided. + +.topic IDH_NC_CANCEL +Cancels the new credentials operation. + +.topic IDH_NC_HELP +Provides help for this dialog box. + +.topic IDH_NC_ADVANCED +Expands the dialog and allows you to set additional +options for the credentials that will be obtained +by this dialog. + +.topic IDH_NC_CREDWND +Provides an overview of the credentials that will be obtained +after the successful completion of the new credentials dialog. +Clicking on the hyperlinks will take you to the corresponding +credentials option panels where you will be able to set +additional options for each type. + +.topic IDH_NC_SETDEF +If checked, once the credentials acquisition operation completes, the +identity will be set as the default. diff --git a/krb5-1-6/src/windows/identity/help/popups_password.txt b/krb5-1-6/src/windows/identity/help/popups_password.txt new file mode 100644 index 000000000..567236391 --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/popups_password.txt @@ -0,0 +1,19 @@ +.topic IDH_NC_TABMAIN +Switches to the identity selection panel. + +.topic IDH_NC_TABBUTTON +Switches to the options pangel for this credential type. + +.topic IDH_NC_OK +Change the password for the selected identity. + +.topic IDH_NC_CANCEL +Cancel the change password operation. + +.topic IDH_NC_ADVANCED +Expand the dialog and make the option pages visible for the credential +types for which you will be changing the password for. + +.topic IDH_NC_CREDWND +A brief overview of the credential types and the identities for which +the password will be changed. diff --git a/krb5-1-6/src/windows/identity/help/toc.hhc b/krb5-1-6/src/windows/identity/help/toc.hhc new file mode 100644 index 000000000..34d0f0a4d --- /dev/null +++ b/krb5-1-6/src/windows/identity/help/toc.hhc @@ -0,0 +1,144 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<HTML> +<HEAD> +<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1"> +<!-- Sitemap 1.0 --> +</HEAD><BODY> +<OBJECT type="text/site properties"> + <param name="Category" value="Concepts"> + <param name="CategoryDesc" value="Authentication, authorization and related concepts."> + <param name="Category" value="Usage"> + <param name="CategoryDesc" value="Usage instructions for Network Identity Manager"> + <param name="Window Styles" value="0x800025"> +</OBJECT> +<UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Welcome to Network Identity Manager"> + <param name="Local" value="html\welcome.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="How do I ..."> + <param name="Local" value="html\howdoi.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="About NetIDMgr"> + <param name="Local" value="html\about_netidmgr.htm"> + </OBJECT> + <UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Reporting bugs"> + <param name="Local" value="html\bugs.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="License agreement"> + <param name="Local" value="html\copyright.htm"> + </OBJECT> + </UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Concepts"> + <param name="Local" value="html\concepts.htm"> + </OBJECT> + <UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Identities"> + <param name="Local" value="html\concept_identity.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Identity Provider"> + <param name="Local" value="html\concept_ident_pro.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Credentials Provider"> + <param name="Local" value="html\concept_cred_pro.htm"> + </OBJECT> + </UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Using NetIDMgr"> + <param name="Local" value="html\using.htm"> + </OBJECT> + <UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Starting"> + <param name="Local" value="html\use_start.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Notification icon"> + <param name="Local" value="html\use_icon.htm"> + </OBJECT> + + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Managing the credentials view layout"> + <param name="Local" value="html\use_layout.htm"> + </OBJECT> + + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Configuring NetIDMgr and identities"> + <param name="Local" value="html\use_config.htm"> + </OBJECT> + </UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Menus and Toolbars"> + <param name="Local" value="html\menu_all.htm"> + </OBJECT> + <UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="File Menu"> + <param name="Local" value="html\menu_file.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Credential menu"> + <param name="Local" value="html\menu_credential.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="View Menu"> + <param name="Local" value="html\menu_view.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Options Menu"> + <param name="Local" value="html\menu_options.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Help Menu"> + <param name="Local" value="html\menu_help.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Standard Toolbar"> + <param name="Local" value="html\tb_standard.htm"> + </OBJECT> + </UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Actions"> + </OBJECT> + <UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="New Credentials"> + <param name="Local" value="html\act_new_creds.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Renew Credentials"> + <param name="Local" value="html\act_renew_creds.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Destroy Credentials"> + <param name="Local" value="html\act_destroy_creds.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Set As Default"> + <param name="Local" value="html\act_set_default.htm"> + </OBJECT> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Change Password"> + <param name="Local" value="html\act_chpw.htm"> + </OBJECT> + </UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Windows and dialogs"> + </OBJECT> + <UL> + <LI> <OBJECT type="text/sitemap"> + <param name="Name" value="Main Window"> + <param name="Local" value="html\wnd_main.htm"> + </OBJECT> + </UL> +</UL> +</BODY></HTML> diff --git a/krb5-1-6/src/windows/identity/include/Makefile b/krb5-1-6/src/windows/identity/include/Makefile new file mode 100644 index 000000000..70fe8c408 --- /dev/null +++ b/krb5-1-6/src/windows/identity/include/Makefile @@ -0,0 +1,38 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=include +!include <../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\khdefs.h \ + $(INCDIR)\kherror.h \ + $(INCDIR)\khlist.h \ + $(INCDIR)\khmsgtypes.h \ + $(INCDIR)\netidmgr.h + +all: $(INCFILES) + +clean:: + if exist "$(INCDIR)" $(RM) $(INCFILES) diff --git a/krb5-1-6/src/windows/identity/include/khdefs.h b/krb5-1-6/src/windows/identity/include/khdefs.h new file mode 100644 index 000000000..c39d6f4ea --- /dev/null +++ b/krb5-1-6/src/windows/identity/include/khdefs.h @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHDEFS_H__ +#define __KHIMAIRA_KHDEFS_H__ + +/*! \defgroup khdef Core definitions + + Key type definitions used throughout NetIDMgr. + */ +/*@{*/ +#include<stddef.h> +#include<limits.h> +#include<wchar.h> + +/*!\typedef khm_octet + \brief A byte (8 bit unsigned)*/ + +/*!\typedef khm_int16 + \brief A signed 16 bit quantity */ + +/*!\typedef khm_ui_2 + \brief An unsigned 16 bit quantity */ + +/*!\typedef khm_int32 + \brief A signed 32 bit quantity */ + +/*!\typedef khm_ui_4 + \brief An unsigned 32 bit quantity */ + +/*!\typedef khm_int64 + \brief A signed 64 bit quantity */ + +/*!\typedef khm_ui_8 + \brief An unsigned 64 bit quantity */ + +typedef unsigned __int8 khm_octet; + +typedef __int16 khm_int16; +typedef unsigned __int16 khm_ui_2; + +typedef __int32 khm_int32; +typedef unsigned __int32 khm_ui_4; + +typedef __int64 khm_int64; +typedef unsigned __int64 khm_ui_8; + +#define VALID_INT_BITS INT_MAX +#define VALID_UINT_BITS UINT_MAX + +#define KHM_UINT32_MAX 4294967295 + +#define KHM_INT32_MAX 2147483647 +/* this strange form is necessary since - is a unary operator, not a sign + indicator */ +#define KHM_INT32_MIN (-KHM_INT32_MAX-1) + +#define KHM_UINT16_MAX 65535 + +#define KHM_INT16_MAX 32767 +/* this strange form is necessary since - is a unary operator, not a sign + indicator */ +#define KHM_INT16_MIN (-KHM_INT16_MAX-1) + +/*! \brief Generic handle type. + + Handles in NetIDMgr are generic pointers. +*/ +typedef void * khm_handle; + +/*! \brief The invalid handle + + Just used to indicate that this handle does not point to anything useful. + Usually returned by a function that returns a handle as a signal that the + operation failed. +*/ +#define KHM_INVALID_HANDLE ((khm_handle) NULL) + +/*! \brief Boolean. +*/ +typedef khm_int32 khm_boolean; + +/*! \brief A size + */ +typedef size_t khm_size; + +/*! \typedef ssize_t + \brief Signed size specifier + + Just a signed version of size_t + */ + +#ifndef _SSIZE_T_DEFINED +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif +#define _SSIZE_T_DEFINED +#endif + +typedef ssize_t khm_ssize; + +#if defined(_WIN64) +typedef unsigned __int64 khm_wparm; +/*TODO: is this enough? */ +typedef unsigned __int64 khm_lparm; +#elif defined(_WIN32) +typedef unsigned __int32 khm_wparm; +typedef unsigned __int64 khm_lparm; +#else +#error khm_wparm and khm_lparm need to be defined for this platform +#endif + +/*!\def KHMAPI + \brief Calling convention for NetIDMgr exported functions + + The caling convention for all NetIDMgr exported functions is \b + __stdcall , unless otherwise noted. + */ + +/*!\def KHMEXP + \brief Export prefix for NetIDMgr exported functions + + When compiling source that exports functions, those exported + function declarations will be done as follows: + + \code + __declspec(dllexport) khm_int32 __stdcall function_name(arguments...); + \endcode + + This eliminates the need for a separate exports definition file. + However, it doesn't preserve ordinals, but we aren't guaranteeing + that anyway. + + On the other hand, if a particular function is going to be imported + from a DLL, it should declared as follows: + + \code + __declspec(dllimport) khm_int32 __stdcall function_name(arguments...); + \endcode + + This allows the compiler to properly instrument the import. If the + function is not declared this way, there will be a stub function + generated that will just jump to the proper import, generating + redundant instructions and wasting execution time. + + This macro encapsulates the proper declaration specifier. + */ + +#ifdef _WIN32 +#define KHMAPI __stdcall + +#define KHMEXP_EXP __declspec(dllexport) +#define KHMEXP_IMP __declspec(dllimport) + +#ifdef _NIMLIB_ +#define KHMEXP KHMEXP_EXP +#else +#define KHMEXP KHMEXP_IMP +#endif + +#endif + +/* Generic permission values */ +/*! \brief Generic read permission or request */ +#define KHM_PERM_READ 0x100 + +/*! \brief Generic write permission or request */ +#define KHM_PERM_WRITE 0x200 + +/* Generic flags */ +/*! \brief Generic create request + + For most lookup functions, specifying this flag indicates that if + the requested object is not found it should be created. +*/ +#define KHM_FLAG_CREATE 0x1000 + +/*! \brief Wrap to DWORD boundary + + Returns the smallest integer greater than or equal to the + parameter that is a multiple of 4. + + \note Only use with positive integers. */ +#define UBOUND32(d) ((((d)-1)&~3) + 4) + +/*! \brief Offset a pointer by a number of bytes + + Given a pointer, returns a void pointer that is a given number of + bytes offset from the pointer. + */ +#define BYTEOFFSET(p,off) ((void *)(((char *) (p)) + (off))) + +/*! \brief Check for powers of 2 + + Return TRUE if the operand is a positive power of 2 or 0*/ +#define IS_POW2(d) ((d)>=0 && !((d) & ((d) - 1))) + +/*! \brief Wrap to upper bound based on start and step size + + Return the smallest element in the series <tt>s, s+t, s+2*t, + s+3*t, ...</tt> that is greater than or equal to \c v. +*/ +#define UBOUNDSS(v,start,step) (((v)<=(start))?(start):(start)+((((v)-((start)+1))/(step))+1)*(step)) + +/* \brief Length of an array +*/ +#define ARRAYLENGTH(x) (sizeof(x)/sizeof(x[0])) + +/*! \brief Generic version type*/ +typedef struct tag_khm_version { + khm_ui_2 major; /*!< Major version number */ + khm_ui_2 minor; /*!< Minor version number */ + khm_ui_2 patch; /*!< Patch level */ + khm_ui_2 aux; /*!< Auxilary level (usually carries a build number) */ +} khm_version; + +/*@}*/ +#endif diff --git a/krb5-1-6/src/windows/identity/include/kherror.h b/krb5-1-6/src/windows/identity/include/kherror.h new file mode 100644 index 000000000..a8ee64505 --- /dev/null +++ b/krb5-1-6/src/windows/identity/include/kherror.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Exported */ +#ifndef __KHIMAIRA_KHERROR_H +#define __KHIMAIRA_KHERROR_H + +/*! \defgroup kherror NetIDMgr errors + +@{*/ +/*! \brief Base for error codes + + NetIDMgr errors range from \a KHM_ERROR_BASE to KHM_ERROR_BASE + + KHM_ERROR_RANGE, with the exception of KHM_ERROR_SUCCESS and + KHM_ERROR_NONE. + */ +#define KHM_ERROR_BASE 0x40000000L + +/*! \brief Range for error codes + + NetIDMgr errors range from \a KHM_ERROR_BASE to + KHM_ERROR_BASE + KHM_ERROR_RANGE. +*/ +#define KHM_ERROR_RANGE 256L + +/*! \defgroup kherror_codes Error codes + @{*/ + +/*! \brief No error */ +#define KHM_ERROR_NONE 0x00000000L + +/*! \brief Success. Same as \a KHM_ERROR_NONE */ +#define KHM_ERROR_SUCCESS KHM_ERROR_NONE + +/*! \brief The supplied name was invalid */ +#define KHM_ERROR_INVALID_NAME (KHM_ERROR_BASE + 1) + +/*! \brief Too much data + + A supplied buffer was invalid, was of insufficient size, or a + buffer was of a larger size than expected + */ +#define KHM_ERROR_TOO_LONG (KHM_ERROR_BASE + 2) + +/*! \brief One or more parameters supplied to a function were invalid */ +#define KHM_ERROR_INVALID_PARAM (KHM_ERROR_BASE + 3) + +/*! \brief A duplicate. + + Usually means that something that should have been unique was + found to be not. + */ +#define KHM_ERROR_DUPLICATE (KHM_ERROR_BASE + 4) + +/*! \brief An object was not found + + An object referenced in a parameter was not found. + */ +#define KHM_ERROR_NOT_FOUND (KHM_ERROR_BASE + 5) + +/*! \brief The relevant subsystem is not ready + + Indicates that initialization has not been completed for a + subsystem. + */ +#define KHM_ERROR_NOT_READY (KHM_ERROR_BASE + 6) + +/*! \brief No more resources + + A limited resource has been exhausted. + */ +#define KHM_ERROR_NO_RESOURCES (KHM_ERROR_BASE + 7) + +/*! \brief Type mismatch + */ +#define KHM_ERROR_TYPE_MISMATCH (KHM_ERROR_BASE + 8) + +/*! \brief Already exists + + Usually indicates that an exclusive create operation failed due to + the existence of a similar object. Subtly different from + ::KHM_ERROR_DUPLICATE + */ +#define KHM_ERROR_EXISTS (KHM_ERROR_BASE + 9) + +/*! \brief Operation timed out + */ +#define KHM_ERROR_TIMEOUT (KHM_ERROR_BASE + 10) + +/*! \brief An EXIT message was received + */ +#define KHM_ERROR_EXIT (KHM_ERROR_BASE + 11) + +/*! \brief Unknown or unspecified error + */ +#define KHM_ERROR_UNKNOWN (KHM_ERROR_BASE + 12) + +/*! \brief General error + */ +#define KHM_ERROR_GENERAL KHM_ERROR_UNKNOWN + +/*! \brief An index was out of bounds + */ +#define KHM_ERROR_OUT_OF_BOUNDS (KHM_ERROR_BASE + 13) + +/*! \brief Object already deleted + + One or more objects that were referenced were found to have been + already deleted. + */ +#define KHM_ERROR_DELETED (KHM_ERROR_BASE + 14) + +/*! \brief Invalid operation + + The operation was not permitted to continue for some reason. + Usually because the necessary conditions for the operation haven't + been met yet or the operation can only be performed at certain + times during the execution of NetIDMgr. + */ +#define KHM_ERROR_INVALID_OPERATION (KHM_ERROR_BASE + 15) + +/*! \brief Signature check failed + */ +#define KHM_ERROR_INVALID_SIGNATURE (KHM_ERROR_BASE + 16) + +/*! \brief Not implemented yet + + The operation that was attempted involved invoking functionality + that has not been implemented yet. + */ +#define KHM_ERROR_NOT_IMPLEMENTED (KHM_ERROR_BASE + 17) + +/*! \brief The objects were equivalent + */ +#define KHM_ERROR_EQUIVALENT (KHM_ERROR_BASE + 18) + +/*! \brief No provider exists to service the request +*/ +#define KHM_ERROR_NO_PROVIDER (KHM_ERROR_BASE + 19) + +/*! \brief The operation succeeded, but with errors +*/ +#define KHM_ERROR_PARTIAL (KHM_ERROR_BASE + 20) + +/*! \brief An incompatibility was found */ +#define KHM_ERROR_INCOMPATIBLE (KHM_ERROR_BASE + 21) + +/*! \brief The operation was put on hold + + A request was put on hold or postponed. */ +#define KHM_ERROR_HELD (KHM_ERROR_BASE + 22) + +/*@}*/ /*kherror_codes*/ + +/*! \brief Tests whether a return value indicates success */ +#define KHM_SUCCEEDED(rv) ((rv)==KHM_ERROR_NONE) + +/*! \brief Tests whether a return value indicates failure */ +#define KHM_FAILED(rv) ((rv)!=KHM_ERROR_NONE) + +/*@}*/ +#endif diff --git a/krb5-1-6/src/windows/identity/include/khlist.h b/krb5-1-6/src/windows/identity/include/khlist.h new file mode 100644 index 000000000..ab60ca37d --- /dev/null +++ b/krb5-1-6/src/windows/identity/include/khlist.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Not exported */ +#ifndef _KHIMAIRA_KHLIST_H +#define _KHIMAIRA_KHLIST_H + +/* Note that most of these are "unsafe" macros. Not for general use */ + +/* LIFO lists */ +#define LDCL(type) \ + type * next; \ + type * prev + +#define LINIT(pe) \ + do { \ + (pe)->next = NULL; \ + (pe)->prev = NULL; } while(0) + +#define LPUSH(pph,pe) \ + do { \ + (pe)->next = *pph; \ + (pe)->prev = NULL; \ + if(*(pph)) (*(pph))->prev = (pe); \ + (*(pph)) = (pe); } while(0) + +#define LPOP(pph,ppe) \ + do { \ + *(ppe) = *(pph); \ + if(*(pph)) *(pph) = (*(pph))->next; \ + if(*(pph)) (*(pph))->prev = NULL; \ + if(*(ppe)) (*(ppe))->next = NULL; \ + } while(0) + +#define LDELETE(pph,pe) \ + do { \ + if((pe)->prev) (pe)->prev->next = (pe)->next; \ + if((pe)->next) (pe)->next->prev = (pe)->prev; \ + if(*(pph) == (pe)) *(pph) = (pe)->next; \ + (pe)->next = (pe)->prev = NULL; \ + } while(0) + +#define LEMPTY(pph) (*(pph) == NULL) + +#define LNEXT(pe) ((pe)?(pe)->next:NULL) + +#define LPREV(pe) ((pe)?(pe)->prev:NULL) + +/* Trees with LIFO child lists */ +#define TDCL(type) \ + LDCL(type); \ + type * children; \ + type * parent + +#define TINIT(pe) \ + do { \ + (pe)->children = NULL; \ + (pe)->parent = NULL; } while(0) + +#define TADDCHILD(pt,pe) \ + do { \ + LPUSH(&((pt)->children),(pe)); \ + (pe)->parent = (pt); } while(0) + +#define TFIRSTCHILD(pt) ((pt)?(pt)->children:NULL) + +#define TPOPCHILD(pt, ppe) \ + do { \ + LPOP(&((pt)->children), ppe); \ + if(*(ppe)) (*(ppe))->parent = NULL; \ + } while(0) + +#define TDELCHILD(pt, pe) \ + do { \ + LDELETE(&((pt)->children), (pe)); \ + (pe)->parent = NULL; } while(0) + +#define TPARENT(pe) ((pe)?(pe)->parent:NULL) + +/* FIFO lists */ +#define QDCL(type) \ + type * head; \ + type * tail + +#define QINIT(pq) \ + do { \ + (pq)->head = (pq)->tail = NULL; \ + } while(0) + +#define QPUT(pq, pe) \ + do { \ + LPUSH(&(pq)->tail, (pe)); \ + if(!(pq)->head) (pq)->head = (pe); \ + } while(0) + +#define QPUSH(pq, pe) \ + do { \ + (pe)->next = NULL; \ + (pe)->prev = (pq)->head; \ + if((pq)->head) (pq)->head->next = (pe); \ + if(!(pq)->tail) (pq)->tail = (pe); \ + (pq)->head = (pe); \ + } while (0) + +#define QGET(pq, ppe) \ + do { \ + *(ppe) = (pq)->head; \ + if(*(ppe)) { \ + (pq)->head = (*(ppe))->prev; \ + if( (*(ppe))->prev ) (*(ppe))->prev->next = NULL; \ + (*(ppe))->prev = NULL; \ + if( (pq)->tail == *(ppe)) (pq)->tail = NULL; \ + } \ + } while(0) + +#define QDEL(pq, pe) \ + do { \ + if((pq)->head == (pe)) (pq)->head = LPREV(pe); \ + LDELETE(&((pq)->tail), (pe)); \ + } while(0) + + +#define QGETT(pq,ppe) \ + do { \ + *(ppe) = (pq)->tail; \ + if(*(ppe)) { \ + (pq)->tail = (*(ppe))->next; \ + if( (*(ppe))->next ) (*(ppe))->next->prev = NULL; \ + (*(ppe))->next = NULL; \ + if( (pq)->head == *(ppe)) (pq)->head = NULL; \ + } \ + } while(0) + +#define QTOP(pq) ((pq)->head) +#define QBOTTOM(pq) ((pq)->tail) +#define QNEXT(pe) ((pe)->prev) +#define QPREV(pe) ((pe)->next) + +#define QINSERT(pt, pre, pe) \ + do { \ + if ((pre) == NULL || \ + QNEXT(pre) == NULL) { QPUT(pt, pe); } \ + else { \ + (pe)->prev = (pre)->prev; \ + (pe)->next = (pre); \ + (pre)->prev->next = (pe); \ + (pre)->prev = (pe); \ + }} while(0) + +/* Trees with FIFO child lists */ +#define TQDCL(type) \ + LDCL(type); \ + QDCL(type); \ + type * parent + +#define TQINIT(pe) \ + do { \ + LINIT(pe); \ + QINIT(pe); \ + (pe)->parent = NULL; } while(0) + +#define TQPUTCHILD(pt,pe) \ + do { \ + QPUT((pt), (pe)); \ + (pe)->parent = (pt); } while(0) + +#define TQINSERT(pt, pre, pe) \ + do { \ + QINSERT(pt, pre, pe); \ + (pe)->parent = (pt); } while(0) + +#define TQGETCHILD(pt,ppe) \ + do { \ + QGET(pt, ppe); \ + if (*(ppe)) { *(ppe)->parent = NULL; } \ + } while(0) + +#define TQDELCHILD(pt, pe) \ + do { \ + QDEL(pt, pe); \ + (pe)->parent = NULL; } while(0) + +#define TQFIRSTCHILD(pt) ((pt)?QTOP(pt):NULL) + +#define TQNEXTCHILD(pe) QNEXT(pe) + +#define TQPREVCHILD(pe) QPREV(pe) + +#define TQPARENT(pe) ((pe)?(pe)->parent:NULL) + +#endif diff --git a/krb5-1-6/src/windows/identity/include/khmsgtypes.h b/krb5-1-6/src/windows/identity/include/khmsgtypes.h new file mode 100644 index 000000000..cfb43f94e --- /dev/null +++ b/krb5-1-6/src/windows/identity/include/khmsgtypes.h @@ -0,0 +1,817 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHMSGTYPES_H +#define __KHIMAIRA_KHMSGTYPES_H + +/*! \addtogroup kmq +@{*/ +/*! \defgroup kmq_msg Message Types +@{*/ + +/*! \name Global message types +@{*/ + +/*! \brief System messages. + + All subscribers are subscribed to the system message class by default. + + \see \ref kmq_msg_system +*/ +#define KMSG_SYSTEM 0 + +/*! \brief Ad-hoc messages. + + These are messages that are sent through add hoc publishers and + subscribers. +*/ +#define KMSG_ADHOC 1 + +/*! \brief NetIDMgr Credentials Database messages + + These messages notify subscribers of events related to the + credentials database, such as the registration, unregistration and + modification of identities, attributes, attribute types and + credential types. It also provides notifications of changes to + the root crednetial set. + + \see \ref kmq_msg_kcdb +*/ +#define KMSG_KCDB 2 + +/*! \brief NetIDMgr Module Manager messages + + \see \ref kmq_msg_kmm +*/ +#define KMSG_KMM 3 + +/*! \brief NetIDMgr Credential messages + + Notifications of crednetial events. These are the most important + events that a credentials provider should respond to. The + notifications provide co-oridination between credential providers + for performing basic credentials management tasks such as + obtaining new credentials for an identity, deleting credentials + for an identity, obtaining or deleting credentials of a particular + type for an identity etc. + + \see \ref cred_msgs + \see \ref kmq_msg_cred + */ +#define KMSG_CRED 4 + +/*! \brief Action list messages + + Notifications of changes in action state and firing of custom + actions. + + \see \ref kmq_msg_act + */ +#define KMSG_ACT 5 + +/*! \brief Alert messages + + Notifier is the component which displays alerts and error messages + when the NetIDMgr window is normally in operation and which + displays balloon prompts when the window is minimized to alert the + user to important messages such as credentials expiring etc. + + \note This is an internal message class. Components that are not + the notifier should not be subscribing to alert messages. + + \see \ref kmq_msg_alert + */ +#define KMSG_ALERT 6 + +/*! \brief Identity messages + + These are messages that are sent to the identity provider. These + are generally dispatched through a specific subscription object + and are not broadcast. + + \see \ref kmq_msg_ident + */ +#define KMSG_IDENT 7 + +/*! \brief Base message type ID for customized message types + */ +#define KMSGBASE_USER 16 + +/*@}*/ + +/*! \defgroup kmq_msg_system KMSG_SYSTEM subtypes +@{*/ +/*! \brief Generic initialization message + + This message is used by specific components to signal that the + recipient is to perform initialization tasks. As a convention, + the recipient should return KHM_ERROR_SUCCESS if it successfully + performed the initlization tasks or some other value if it failed + to do so. Failure to successfully initialize is usually taken to + mean that the recipient component is not able to perform its + function. + + Usually this is the first message to be received by the recipient. + + \see \ref pi_pt_cred_init + */ +#define KMSG_SYSTEM_INIT 1 + +/*! \brief Generic uninitialization message + + Used by specific components to signal that the recipient should + perform uninitilization tasks in preparation of termination. The + return value of this message is not used. + + Usually this is the last message to be received by the recipient. + + \see \ref pi_pt_cred_exit + */ +#define KMSG_SYSTEM_EXIT 2 + +/*! \brief Message completion + + This is an internal message + */ +#define KMSG_SYSTEM_COMPLETION 3 +/*@}*/ + +/*! \defgroup kmq_msg_kcdb KMSG_KCDB subtypes +@{*/ +#define KMSG_KCDB_IDENT 1 +#define KMSG_KCDB_CREDTYPE 2 +#define KMSG_KCDB_ATTRIB 3 +#define KMSG_KCDB_TYPE 4 + +/*! \brief Generic credentials request + + \see ::kcdb_cred_request for more information + */ +#define KMSG_KCDB_REQUEST 256 +/*@}*/ + +/*! \defgroup kmq_msg_kmm KMSG_KMM subtypes +@{*/ +#define KMSG_KMM_I_REG 1 + +#define KMSG_KMM_I_DONE 2 +/*@}*/ + +/*! \defgroup kmq_msg_act KMSG_ACT subtypes + @{*/ + +/*! \brief One or more actions changed state + + This message is sent in response to a call to + khui_enable_actions() or khui_enable_action() and indicates that + one or more actions have changed their state. + */ +#define KMSG_ACT_ENABLE 1 + +/*! \brief One or more actions changed check state + + Sent in response to khui_check_radio_action() or + khui_check_action() and indicates that one or more actions have + either been checked or unchecked. + */ +#define KMSG_ACT_CHECK 2 + +/*! \brief Refresh action states + + Sent after a batch of modifications were made to action states. + */ +#define KMSG_ACT_REFRESH 3 + +/*! \brief A new action was created + + Sent when a new custom action was created. The \a uparam + parameter of the message contains the identifier of the newly + created action. +*/ +#define KMSG_ACT_NEW 4 + +/*! \brief A custom action was deleted + + Sent after a custom action is deleted. The \a uparam parameter of + the message contains the identifier of the deleted action. + */ +#define KMSG_ACT_DELETE 5 + +/*! \brief A custom action has been activated + + When a custom action is activated, then the listener of that + custom action receives this message. Note that only the listener + for that custom action will receive this notification. + + \a uparam of the message is set to the identifier of the custom + action. + */ +#define KMSG_ACT_ACTIVATE 6 + +/*! \brief Internal */ +#define KMSG_ACT_BEGIN_CMDLINE 128 + +/*! \brief Internal */ +#define KMSG_ACT_CONTINUE_CMDLINE 129 + +/*! \brief Internal */ +#define KMSG_ACT_SYNC_CFG 130 + +/*! \brief Internal */ +#define KMSG_ACT_END_CMDLINE 131 + +/*@}*/ + +/*! \defgroup kmq_msg_cred KMSG_CRED subtypes + @{*/ +/*! \brief Root credential set changed + + This message is issued when the root credential set successfully + collected credentials from another credential set. + + \a uparam of the message is set to a bitmask indicating the change + that occured. It is a combination of ::KCDB_DELTA_ADD, + ::KCDB_DELTA_DEL and ::KCDB_DELTA_MODIFY. + */ +#define KMSG_CRED_ROOTDELTA 1 + +/*! \brief Re-enumerate credentials + + A notice to all credential providers to re-enumerate their + respective credentials. + + \note May be sent to individual credential subscriptions. + */ +#define KMSG_CRED_REFRESH 2 + +/*! \brief Change the password + + This message notifies credentials providers that a password change + request has been received. + + A plug-in handling this message that wishes to participate in the + password change operation is expected to add a + ::khui_new_creds_by_type to the list of participants in the + ::khui_new_creds structure by calling khui_cw_add_type(). + + The password change operation requires user interaction. Any + plug-ins that are participating in the operation need to provide a + user-interface. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \see khui_cw_add_type(), ::khui_new_creds, ::khui_new_creds_by_type + */ +#define KMSG_CRED_PASSWORD 16 + +/*! \brief Initiate the process of obtaining new credentials + + The UI sends this message to start the process of obtaining new + credentials. See \ref cred_acq for more information about + handling this message. + + A plug-in handling this message that wishes to participate in the + new credentials acquisition operation is expected to add a + ::khui_new_creds_by_type to hte list of participants in the + ::khui_new_creds structure by calling khui_cw_add_type(). + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \see \ref cred_acq, khui_cw_add_type(), ::khui_new_creds, + ::khui_new_creds_by_type + */ +#define KMSG_CRED_NEW_CREDS 17 + +/*! \brief Renew credentials + + This is a notification sent to individual credentials providers + that a specified identity's credentials should be renewed. + + A plug-in handling this message that wishes to participate in the + renew credentials operation is expected to add a + ::khui_new_creds_by_type to the list of participants in the + ::khui_new_creds structure by calling khui_cw_add_type(). + + Message parameters: + - \b vparam : Pointer to a khui_new_creds object + + \see khui_cw_add_type(), ::khui_new_creds, + ::khui_new_creds_by_type + */ +#define KMSG_CRED_RENEW_CREDS 18 + +/*! \brief Dialog setup + + Once ::KMSG_CRED_NEW_CREDS has been responded to by all the + credential types, the UI creates the dialog windows using the data + supplied in the ::khui_new_creds_by_type structures and issues + this message. Each credentials provider is expected to respond by + finalizing dialog creation operations. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \note May be sent to individual credential subscriptions. + */ +#define KMSG_CRED_DIALOG_SETUP 19 + +/*! \brief Dialog pre-start + + Sent after all the credentials providers have responded to + ::KMSG_CRED_DIALOG_SETUP and all the initialization has been + completed. Credentials providers are expected to respond to this + message by loading any default data into the dialog controls for + each credential type. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \note May be sent to individual credential subscriptions. + */ +#define KMSG_CRED_DIALOG_PRESTART 20 + +/*! \brief Dialog start + + A notification that the dialog is now in progress. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \note May be sent to individual credential subscriptions. + */ +#define KMSG_CRED_DIALOG_START 21 + +/*! \brief The primary identity of the new credentials dialog has changed + + This message is not sent out by the UI, but is reserved here for + use by individual credentials providers. The message may be sent + from the dialog procedure to the plugin. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \note Be careful when sending this message. All messages that are + not sent by the system should not be sent via broadcast. + Instead, create a subscription using kmq_create_subscription() + for the individual plugin that you want to send the message + and use one of the per-subscription message functions to send + the actual message. + */ +#define KMSG_CRED_DIALOG_NEW_IDENTITY 22 + +/*! \brief New credentials options have changed. + + This message is not sent out by the UI, but is reserved here for + use by individual credentials providers. The message may be sent + from the dialog procedure to the plugin. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \note Be careful when sending this message. All messages that are + not sent by the system should not be sent via broadcast. + Instead, create a subscription using kmq_create_subscription() + for the individual plugin that you want to send the message + and use one of the per-subscription message functions to send + the actual message. + */ +#define KMSG_CRED_DIALOG_NEW_OPTIONS 23 + +/*! \brief Process dialog + + Sent to all the credential providers to look at the contents of + the given ::khui_new_creds structure and do any required + processing. + + If the \a result field in the structure is set to + ::KHUI_NC_RESULT_PROCESS, then new credentials should be + obtained using the given data. + + Set the \a response field in the structure to indicate how the UI + should proceed from here. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \note May be sent to individual credential subscriptions. + */ +#define KMSG_CRED_PROCESS 24 + +/*! \brief End a credentials acquisition operation + + A notification that the credentials acquisition operation has + ended. + + Message parameters: + - \b vparam : pointer to a ::khui_new_creds structure + + \note May be sent to individual credential subscriptions. + */ +#define KMSG_CRED_END 25 + +/*! \brief Import credentials from the operating system + + Notification to all credentials providers to import any available + credentials from the operating system. + + Message parameters: + - This message does not have any parameters +*/ +#define KMSG_CRED_IMPORT 26 + +/*! \brief Destroy credentials + + Notification that the specified credentials should be destroyed. + Once this message has completed processing a ::KMSG_CRED_REFRESH + message will be issued. + + The credentials that should be destroyed are specified by a + ::khui_action_context structure. The context that should be used + is the selection context. Hence, the credentials that must be + destroyed are the ones lised in the credential set (\a credset). + + Message parameters: + + - \b upram : Unused. Zero. + + - \b vparam : pointer to a ::khui_action_context structure which + describes which credentials need to be destroyed. + + */ +#define KMSG_CRED_DESTROY_CREDS 32 + +#if 0 +/*! \brief Parse an identity + + \note May be sent to individual credential subscriptions. + */ +#define KMSG_CRED_IDENT_PARSE 65 +#endif + +/*! \brief A property page is being launced + + Handlers of this message should determine whether or not they + should participate in the property sheet and if so, add a + ::khui_property_page structure to the property sheet. + + Message parameters: + - \b vparam : pointer to a ::khui_property_sheet structure + */ +#define KMSG_CRED_PP_BEGIN 128 + +/*! \brief A property page is about to be created + + Message parameters: + - \b vparam : pointer to a ::khui_property_sheet structure + + \note This message is merely a notification that the property + sheet is being created. Handlers should not modify the state + of the property sheet or pages at this time. + */ +#define KMSG_CRED_PP_PRECREATE 129 + +/*! \brief A property page has finished processing + + Handlers of this message should remove any ::khui_property_page + structures they added when processing ::KMSG_CRED_PP_BEGIN. + + Message parameters: + - \b vparam : pointer to a ::khui_property_sheet structure + */ +#define KMSG_CRED_PP_END 130 + +/*! \brief A property page has been destroyed + + Message parameters: + - \b vparam : pointer to a ::khui_property_sheet structure + + \note This is a notification that the property sheet processing + has been completed and that the property sheet data structures + should be freed. Any property page data structures should + have already been freed while processing KMSG_CRED_PP_END. + The validity of the ::khui_property_sheet structure should not + be relied upon while processing this message. + */ +#define KMSG_CRED_PP_DESTROY 131 + +/*! \brief An IP address change occurred + + There are no parameters for this message. The NetIDMgr + application handles this message and depending on configuration, + posts message for the individual credentials providers to either + obtain new credentials or renew old ones. + */ +#define KMSG_CRED_ADDR_CHANGE 140 + +/*! \brief Check if a KMSG_CRED subtype is a credentials acquisition message + + Dialog messages are those that deal with the new or initial + credentials acquisition dialog, from initial announcement to + dialog completion. + + Currently, the dialog messages are: + - ::KMSG_CRED_NEW_CREDS + - ::KMSG_CRED_RENEW_CREDS + - ::KMSG_CRED_DIALOG_SETUP + - ::KMSG_CRED_DIALOG_PRESTART + - ::KMSG_CRED_DIALOG_START + - ::KMSG_CRED_DIALOG_NEW_IDENTITY + - ::KMSG_CRED_DIALOG_NEW_OPTIONS + - ::KMSG_CRED_PROCESS + - ::KMSG_CRED_END + + All dialog message numbers are allocated in a contigous block. + + Note that while ::KMSG_CRED_PROCESS and ::KMSG_CRED_END are not + specific to dialogs, they are still included in this predicate + because they are also part of the dialog message sequence. + */ +#define IS_CRED_ACQ_MSG(msg) ((msg) >= 16 && (msg) <=31) + +/*@}*/ /* /KMSG_CRED subtypes */ + +/*! \defgroup kmq_msg_alert KMSG_ALERT Subtypes + @{*/ + +/*! \brief Show an alert + + Message parameters: + - \b vparam : held pointer to a ::khui_alert object + + \note The ::khui_alert object will be released when the processing + of this message completes. + */ +#define KMSG_ALERT_SHOW 1 + +/*! \brief Add an alert to the alert queue + + Message parameters: + - \b vparam : held pointer to a ::khui_alert object + + \note the ::khui_alert object will be released when the queued + messages are displayed. + */ +#define KMSG_ALERT_QUEUE 2 + +/*! \brief Show the next queued alert + + There are no message parameters + */ +#define KMSG_ALERT_SHOW_QUEUED 3 + +/*! \brief Check if there are any queued messages and, if so, update the statusbar + + There are no message parameters + */ +#define KMSG_ALERT_CHECK_QUEUE 4 + +/*! \brief Show a modal alert + + Message parameters: + - \b vparam : held pointer to a ::khui_alert object. + + \note the ::khui_alert object will be released when the queued + messages are displayed. + */ +#define KMSG_ALERT_SHOW_MODAL 5 + +/*@}*/ + +/*! \defgroup kmq_msg_ident KMSG_IDENT Subtypes + @{*/ + +/*! \brief Initialize and start the identity provider + + + Sent by the KCDB to notify the identity provider that it is now + the current identity provider. + + Note that unlike regular plugins, an identity provider can be + loaded and inert (not provide any services). Also, the user may + switch between multiple identity providers on the fly. + */ +#define KMSG_IDENT_INIT 1 + +/*! \brief Stop the identity provider + + Sent by the KCDB as notificaton that the identity provider is no + longer the current provider. + */ +#define KMSG_IDENT_EXIT 2 + +/*! \brief Check if an identity name is valid + + This message is sent to the identity provider to verify the syntax + of an identity name. Note that only the syntax of the name is to + be verfied and not the actual physical existence of said identity. + + Message parameters: + + - \b vparam : pointer to ::kcdb_ident_name_xfer object. The + name to be validated will be in the \a name_src member. The + buffer will be NULL terminated with a maximum limit of + KCDB_IDENT_MAXCCH_NAME characters including the terminating + NULL, consisting only of characters in KCDB_IDENT_VALID_CHARS + The \a result member should be set to one of the following + depending on the result of the validation: + + - KHM_ERROR_SUCCESS : The name was valid + - KHM_ERROR_INVALID_NAME : The name was invalid + */ +#define KMSG_IDENT_VALIDATE_NAME 3 + +/*! \brief Check if an identity is valid + + Sent to the identity provider to verify the validity of the given + identity. The provider should verify that the identity exists and + is in a state where it can be actively used. + + Depending on the result of the validation, the flags of the + identity should be updated. + + Message parameters: + - \b vparam : Handle to an identity cast as a void pointer. + */ +#define KMSG_IDENT_VALIDATE_IDENTITY 4 + +/*! \brief Canonicalize identity name + + The identity provider will be given a name, which it should put in + canonical form, adjusting case and any character replacement or + doing any relevant expansions if applicable, and place it in the + supplied buffer. + + Message parameters: + + - \b vparam : Pointer to a ::kcdb_ident_name_xfer structure + which provides the identity name to canonicalize in the \a + name_src member, and the buffer to store the canonical name + in the \a name_dest member. The \a name_dest buffer is + guaranteed to be at least KCDB_IDENT_MAXCCH_NAME characters + in size. + + If the name cannot be canonicalized for some reason, the + destination buffer should be set to a zero-length string and the + \a result member of the ::kcdb_ident_name_xfer structure should be + set to the error code. If the destination buffer is set to a + zero-length string and \a result is KHM_ERROR_SUCCESS, then the + original name provided in \a name_src is assumed to be already in + canonical form. + */ +#define KMSG_IDENT_CANON_NAME 5 + +/*! \brief Compare names + + Compare two identity names. The names that are given aren't + guaranteed to be in canonical form. The return value should be + akin to strcmp(). + + Message parameters: + + - \b vparam : A pointer to a ::kcdb_ident_name_xfer structure. + The \a name_src member points at the first name, and the \a + name_alt member specifies the second name. The result of the + comparison should be place in \a result. + */ +#define KMSG_IDENT_COMPARE_NAME 6 + +/*! \brief Set the default identity + + Set or unset the default identity. To set the default identity, + the \a uparam parameter will be set to a non-zero value and a + handle to the identity will be specified in \a vparam. To unset + the default identity (i.e. not have a default identity), a zero + value will be specified in \a uparam and no identities will be + specified in \a vparam. + + When setting a default identity, the identity provider will + receive this message prior to the ::KCDB_IDENT_FLAG_DEFAULT bit + being set or reset on any identity. It should return + KHM_ERROR_SUCCESS if the requested operation can be performed. + Returning any other value will abort the operation and will leave + the default identity unchanged. + + When resetting the default identity, this message should be + treated only as a notification. + + Message parameters: + + - \a uparam : Is non-zero if an identity is being made default. If + this is zero, then identity should be the default. + + - \a vparam : A handle to the identity to be made default if \a + uparam is non-zero. NULL otherwise. + + Return value: + + - KHM_ERROR_SUCCESS : The identity should be marked as default + - Any other value : The identity should not be marked as default + + */ +#define KMSG_IDENT_SET_DEFAULT 7 + +/*! \brief Set an identity as searchable + + Set or reset the searchable bit on an identity. If the \a uparam + parameter is non-zero, then the searchable bit is being set. + Otherwise it is being reset. The identity provider should return + KHM_ERROR_SUCCESS in order to indicate that the identity should be + marked as searchable. Any other value will result in the + searchable bit being reset on the identity. + + Message parameters: + + - \a uparam : Is non-zero if the searchable bit is being set. Zero + otherwise. + + - \a vparam : Handle to the identity + + Return value: + + - KHM_ERROR_SUCCESS: The identity should be marked as searchable + - Any other value : The identity should not be marked as default + */ +#define KMSG_IDENT_SET_SEARCHABLE 8 + +/*! \brief Get information about an identity + + */ +#define KMSG_IDENT_GET_INFO 9 + +/*! \brief Enumerate known and accessible identities + */ +#define KMSG_IDENT_ENUM_KNOWN 10 + +/*! \brief Update information about an identity + */ +#define KMSG_IDENT_UPDATE 11 + +/*! \brief Retrieve the user interface callback function + + When obtaining new credentials, the user interface needs to obtain + a callback function which will provide identity selection + controls. + + Message parameters: + + - \a uparam : Not used + + - \a vparam : pointer to a ::khui_ident_new_creds_cb which will + receive the call back. + */ +#define KMSG_IDENT_GET_UI_CALLBACK 12 + +/*! \brief Notification of the creation of an identity + + This should be considered just a notification. The identit + provider does not have an opportunity to veto the creation of an + identity whose name has been found to be valid. However, when + handing this notification, the identity provider can: + + - Change the flags of the identity and/or marking the identity as + invalid. + + - Change the default identity. + + Note that this notification is sent before the general :;KMSG_KCDB + notification of the identity creation is sent. + + Message parameters: + + - \a uparam : Not used. + + - \p vparam : handle to the identity + */ +#define KMSG_IDENT_NOTIFY_CREATE 13 + +/*@}*/ /* /KMSG_IDENT subtypes */ + +/*@}*/ /* / message types */ +/*@}*/ /* / kmq */ + +#endif diff --git a/krb5-1-6/src/windows/identity/include/netidmgr.h b/krb5-1-6/src/windows/identity/include/netidmgr.h new file mode 100644 index 000000000..cc680fcad --- /dev/null +++ b/krb5-1-6/src/windows/identity/include/netidmgr.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __NETIDMGR_H +#define __NETIDMGR_H + +#include "khdefs.h" + +#include "utils.h" +#include "khuidefs.h" +#include "kmq.h" +#include "khmsgtypes.h" +#include "kcreddb.h" +#include "kherr.h" +#include "kherror.h" +#include "kconfig.h" +#include "kmm.h" +#include "kplugin.h" + +#endif diff --git a/krb5-1-6/src/windows/identity/kconfig/Makefile b/krb5-1-6/src/windows/identity/kconfig/Makefile new file mode 100644 index 000000000..bc4667954 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kconfig/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=kconfig +!include <../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\kconfig.h + +OBJFILES= \ + $(OBJ)\kconfigmain.obj \ + $(OBJ)\api.obj + +all: mkdirs $(INCFILES) $(OBJFILES) + +clean:: + if exist "$(INCDIR)" $(RM) $(INCFILES) + +# Tests + +test:: util_test + +util_test: $(OBJ)\utiltest.exe + $(OBJ)\utiltest.exe + +$(OBJ)\utiltest.exe: $(OBJ)\utiltest.obj + $(EXECONLINK) $(OBJFILES) + +$(OBJ)\utiltest.obj: test\utiltest.c + $(C2OBJ) diff --git a/krb5-1-6/src/windows/identity/kconfig/api.c b/krb5-1-6/src/windows/identity/kconfig/api.c new file mode 100644 index 000000000..8317e6c9b --- /dev/null +++ b/krb5-1-6/src/windows/identity/kconfig/api.c @@ -0,0 +1,2661 @@ +/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies +* of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +/* $Id$ */ + +#include<shlwapi.h> +#include<kconfiginternal.h> +#include<netidmgr_intver.h> +#include<assert.h> + +kconf_conf_space * conf_root = NULL; +kconf_handle * conf_handles = NULL; +kconf_handle * conf_free_handles = NULL; + +CRITICAL_SECTION cs_conf_global; +CRITICAL_SECTION cs_conf_handle; +LONG conf_init = 0; +LONG conf_status = 0; + +void init_kconf(void) { + if(InterlockedIncrement(&conf_init) == 1L) { + /* we are the first */ + InitializeCriticalSection(&cs_conf_global); + EnterCriticalSection(&cs_conf_global); + conf_root = khcint_create_empty_space(); + conf_root->name = PWCSDUP(L"Root"); + conf_root->regpath = PWCSDUP(CONFIG_REGPATHW); + conf_root->refcount++; + conf_status = 1; + InitializeCriticalSection(&cs_conf_handle); + LeaveCriticalSection(&cs_conf_global); + } + /* else assume we are already initialized */ +} + +void exit_kconf(void) { + if(khc_is_config_running()) { + kconf_handle * h; + + EnterCriticalSection(&cs_conf_global); + + conf_init = 0; + conf_status = 0; + + khcint_free_space(conf_root); + + LeaveCriticalSection(&cs_conf_global); + DeleteCriticalSection(&cs_conf_global); + + EnterCriticalSection(&cs_conf_handle); + while(conf_free_handles) { + LPOP(&conf_free_handles, &h); + if(h) { + PFREE(h); + } + } + + while(conf_handles) { + LPOP(&conf_handles, &h); + if(h) { + PFREE(h); + } + } + LeaveCriticalSection(&cs_conf_handle); + DeleteCriticalSection(&cs_conf_handle); + } +} + +#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL)) + +#include<stdio.h> + +static void +khcint_dump_space(FILE * f, kconf_conf_space * sp) { + + kconf_conf_space * sc; + + fprintf(f, "c12\t[%S]\t[%S]\t%d\t0x%x\tWin(%s|%s)|%s\n", + ((sp->regpath) ? sp->regpath : L"!No Reg path"), + sp->name, + (int) sp->refcount, + (int) sp->flags, + ((sp->regkey_user)? "HKCU" : ""), + ((sp->regkey_machine)? "HKLM" : ""), + ((sp->schema)? "Schema" : "")); + + + sc = TFIRSTCHILD(sp); + while(sc) { + + khcint_dump_space(f, sc); + + sc = LNEXT(sc); + } +} + +KHMEXP void KHMAPI +khcint_dump_handles(FILE * f) { + if (khc_is_config_running()) { + kconf_handle * h, * sh; + + EnterCriticalSection(&cs_conf_handle); + EnterCriticalSection(&cs_conf_global); + + fprintf(f, "c00\t*** Active handles ***\n"); + fprintf(f, "c01\tHandle\tName\tFlags\tRegpath\n"); + + h = conf_handles; + while(h) { + kconf_conf_space * sp; + + sp = h->space; + + if (!khc_is_handle(h) || sp == NULL) { + + fprintf(f, "c02\t!!INVALID HANDLE!!\n"); + + } else { + + fprintf(f, "c02\t0x%p\t[%S]\t0x%x\t[%S]\n", + h, + sp->name, + h->flags, + sp->regpath); + + sh = khc_shadow(h); + + while(sh) { + + sp = sh->space; + + if (!khc_is_handle(sh) || sp == NULL) { + + fprintf(f, "c02\t0x%p:Shadow:0x%p\t[!!INVALID HANDLE!!]\n", + h, sh); + + } else { + + fprintf(f, "c02\t0x%p:Shadow:0x%p,[%S]\t0x%x\t[%S]\n", + h, sh, + sp->name, + sh->flags, + sp->regpath); + + } + + sh = khc_shadow(sh); + } + + } + + h = LNEXT(h); + } + + fprintf(f, "c03\t------ End ---------\n"); + + fprintf(f, "c10\t*** Active Configuration Spaces ***\n"); + fprintf(f, "c11\tReg path\tName\tRefcount\tFlags\tLayers\n"); + + khcint_dump_space(f, conf_root); + + fprintf(f, "c13\t------ End ---------\n"); + + LeaveCriticalSection(&cs_conf_global); + LeaveCriticalSection(&cs_conf_handle); + + } else { + fprintf(f, "c00\t------- KHC Configuration not running -------\n"); + } +} + +#endif + +/* obtains cs_conf_handle/cs_conf_global */ +kconf_handle * +khcint_handle_from_space(kconf_conf_space * s, khm_int32 flags) +{ + kconf_handle * h; + + EnterCriticalSection(&cs_conf_handle); + LPOP(&conf_free_handles, &h); + if(!h) { + h = PMALLOC(sizeof(kconf_handle)); + assert(h != NULL); + } + ZeroMemory((void *) h, sizeof(kconf_handle)); + + h->magic = KCONF_HANDLE_MAGIC; + khcint_space_hold(s); + h->space = s; + h->flags = flags; + + LPUSH(&conf_handles, h); + LeaveCriticalSection(&cs_conf_handle); + + return h; +} + +/* obtains cs_conf_handle/cs_conf_global */ +void +khcint_handle_free(kconf_handle * h) +{ + kconf_handle * lower; + + EnterCriticalSection(&cs_conf_handle); +#ifdef DEBUG + /* check if the handle is actually in use */ + { + kconf_handle * a; + a = conf_handles; + while(a) { + if(h == a) + break; + a = LNEXT(a); + } + + if(a == NULL) { + DebugBreak(); + + /* hmm. the handle was not in the in-use list */ + LeaveCriticalSection(&cs_conf_handle); + return; + } + } +#endif + while(h) { + LDELETE(&conf_handles, h); + if(h->space) { + khcint_space_release(h->space); + h->space = NULL; + } + lower = h->lower; + h->magic = 0; + LPUSH(&conf_free_handles, h); + h = lower; + } + LeaveCriticalSection(&cs_conf_handle); +} + +/* obains cs_conf_handle/cs_conf_global */ +kconf_handle * +khcint_handle_dup(kconf_handle * o) +{ + kconf_handle * h; + kconf_handle * r; + + r = khcint_handle_from_space(o->space, o->flags); + h = r; + + while(o->lower) { + h->lower = khcint_handle_from_space(o->lower->space, o->lower->flags); + + o = o->lower; + h = h->lower; + } + + return r; +} + +/* obtains cs_conf_global */ +void +khcint_space_hold(kconf_conf_space * s) { + EnterCriticalSection(&cs_conf_global); + s->refcount ++; + LeaveCriticalSection(&cs_conf_global); +} + +/* called with cs_conf_global */ +void +khcint_try_free_space(kconf_conf_space * s) { + + if (TFIRSTCHILD(s) == NULL && + s->refcount == 0 && + s->schema == NULL) { + + kconf_conf_space * p; + + p = TPARENT(s); + + if (p == NULL) + return; + + TDELCHILD(p, s); + + khcint_free_space(s); + + khcint_try_free_space(p); + } +} + +/* obtains cs_conf_global */ +void +khcint_space_release(kconf_conf_space * s) { + khm_int32 l; + + EnterCriticalSection(&cs_conf_global); + + l = -- s->refcount; + if (l == 0) { + if(s->regkey_machine) + RegCloseKey(s->regkey_machine); + if(s->regkey_user) + RegCloseKey(s->regkey_user); + s->regkey_machine = NULL; + s->regkey_user = NULL; + + if (s->flags & + (KCONF_SPACE_FLAG_DELETE_M | + KCONF_SPACE_FLAG_DELETE_U)) { + khcint_remove_space(s, s->flags); + } else { +#ifdef USE_TRY_FREE + /* even if the refcount is zero, we shouldn't free a + configuration space just yet since that doesn't play + well with the configuration space enumeration mechanism + which expects the spaces to dangle around if there is a + corresponding registry key or schema. */ + khcint_try_free_space(s); +#endif + } + } + + LeaveCriticalSection(&cs_conf_global); +} + +/* case sensitive replacement for RegOpenKeyEx */ +LONG +khcint_RegOpenKeyEx(HKEY hkey, LPCWSTR sSubKey, DWORD ulOptions, + REGSAM samDesired, PHKEY phkResult) { + int i; + wchar_t sk_name[KCONF_MAXCCH_NAME]; + FILETIME ft; + size_t cch; + HKEY hkp = NULL; + const wchar_t * t; + LONG rv = ERROR_SUCCESS; + + hkp = hkey; + t = sSubKey; + + /* check for case insensitive prefix first */ + if (!_wcsnicmp(sSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) { + HKEY hkt; + + t = sSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1); + +#ifdef DEBUG + assert(*t == L'\0' || *t == L'\\'); +#endif + + rv = RegOpenKeyEx(hkp, + CONFIG_REGPATHW, + ulOptions, + samDesired, + &hkt); + + if (rv != ERROR_SUCCESS) + return rv; + + if (*t == L'\0') { + *phkResult = hkt; + return rv; + } + + t++; + hkp = hkt; + } + + /* descend down the components of the subkey */ + while(TRUE) { + wchar_t * slash; + HKEY hkt; + + slash = wcschr(t, L'\\'); + if (slash == NULL) + break; + + if (FAILED(StringCchCopyN(sk_name, ARRAYLENGTH(sk_name), + t, slash - t))) { + rv = ERROR_CANTOPEN; + goto _cleanup; + } + + sk_name[slash - t] = L'\0'; + t = slash+1; + + if (khcint_RegOpenKeyEx(hkp, sk_name, ulOptions, samDesired, &hkt) == + ERROR_SUCCESS) { + + if (hkp != hkey) + RegCloseKey(hkp); + hkp = hkt; + + } else { + + rv = ERROR_CANTOPEN; + goto _cleanup; + + } + } + + /* by now hkp is a handle to the parent of the last component in + the subkey. t is a pointer to the last component. */ + + if (FAILED(StringCchLength(t, KCONF_MAXCCH_NAME, &cch))) { + rv = ERROR_CANTOPEN; + goto _cleanup; + } + + /* go through and find the case sensitive match for the key */ + + for (i=0; ;i++) { + LONG l; + DWORD dw; + + dw = ARRAYLENGTH(sk_name); + l = RegEnumKeyEx(hkp, i, sk_name, &dw, + NULL, NULL, NULL, &ft); + + if (l != ERROR_SUCCESS) { + rv = ERROR_CANTOPEN; + goto _cleanup; + } + + if (!(wcsncmp(sk_name, t, cch))) { + /* bingo! ?? */ + if (cch < KCONF_MAXCCH_NAME && + (sk_name[cch] == L'\0' || + sk_name[cch] == L'~')) { + rv = RegOpenKeyEx(hkp, sk_name, ulOptions, + samDesired, phkResult); + goto _cleanup; + } + } + } + + _cleanup: + if (hkp != hkey && hkp != NULL) + RegCloseKey(hkp); + + return rv; +} + +/*! \internal + + \note This function is not a good replacement for RegDeleteKey since + it deletes all the subkeys in addition to the key being deleted. + */ +LONG +khcint_RegDeleteKey(HKEY hKey, + LPCWSTR lpSubKey) { + int i; + wchar_t sk_name[KCONF_MAXCCH_NAME]; + FILETIME ft; + size_t cch; + LONG rv = ERROR_SUCCESS; + + /* go through and find the case sensitive match for the key */ + + if (FAILED(StringCchLength(lpSubKey, KCONF_MAXCCH_NAME, &cch))) + return ERROR_BADKEY; + + for (i=0; ;i++) { + LONG l; + DWORD dw; + + dw = ARRAYLENGTH(sk_name); + l = RegEnumKeyEx(hKey, i, sk_name, &dw, + NULL, NULL, NULL, &ft); + + if (l != ERROR_SUCCESS) { + rv = ERROR_BADKEY; + goto _cleanup; + } + + if (!(wcsncmp(sk_name, lpSubKey, cch))) { + /* bingo! ?? */ + if ((sk_name[cch] == L'\0' || + sk_name[cch] == L'~')) { + + /* instead of calling RegDeleteKey we call SHDeleteKey + because we want to blow off all the subkeys as + well. This is different from the behavior of + RegDeleteKey making khcint_RegDeleteKey not a very + good case sensitive replacement for + RegDeleteKey. */ + + rv = SHDeleteKey(hKey, sk_name); + goto _cleanup; + } + } + } + + _cleanup: + return rv; +} + +LONG +khcint_RegCreateKeyEx(HKEY hKey, + LPCWSTR lpSubKey, + DWORD Reserved, + LPWSTR lpClass, + DWORD dwOptions, + REGSAM samDesired, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + PHKEY phkResult, + LPDWORD lpdwDisposition) { + LONG l; + int i; + long index = 0; + wchar_t sk_name[KCONF_MAXCCH_NAME]; /* hard limit in Windows */ + FILETIME ft; + size_t cch; + const wchar_t * t; + LONG rv = ERROR_SUCCESS; + HKEY hkp = NULL; + + hkp = hKey; + t = lpSubKey; + + /* check for case insensitive prefix first */ + if (!_wcsnicmp(lpSubKey, CONFIG_REGPATHW, ARRAYLENGTH(CONFIG_REGPATHW) - 1)) { + HKEY hkt; + + t = lpSubKey + (ARRAYLENGTH(CONFIG_REGPATHW) - 1); + +#ifdef DEBUG + assert(*t == L'\0' || *t == L'\\'); +#endif + + rv = RegCreateKeyEx(hkp, + CONFIG_REGPATHW, + Reserved, + lpClass, + dwOptions, + samDesired, + lpSecurityAttributes, + &hkt, + lpdwDisposition); + + if (rv != ERROR_SUCCESS) + return rv; + + if (*t == L'\0') { + *phkResult = hkt; + return rv; + } + + t++; + hkp = hkt; + } + + while(TRUE) { + wchar_t * slash; + HKEY hkt; + + slash = wcschr(t, L'\\'); + if (slash == NULL) + break; + + if (FAILED(StringCchCopyN(sk_name, ARRAYLENGTH(sk_name), + t, slash - t))) { + rv = ERROR_CANTOPEN; + goto _cleanup; + } + + sk_name[slash - t] = L'\0'; + t = slash+1; + + if (khcint_RegOpenKeyEx(hkp, sk_name, 0, samDesired, &hkt) == + ERROR_SUCCESS) { + + if (hkp != hKey) + RegCloseKey(hkp); + hkp = hkt; + } else { + + rv = RegCreateKeyEx(hKey, + lpSubKey, + Reserved, + lpClass, + dwOptions, + samDesired, + lpSecurityAttributes, + phkResult, + lpdwDisposition); + goto _cleanup; + } + } + + if (FAILED(StringCchLength(t, KCONF_MAXCCH_NAME, &cch))) { + rv = ERROR_CANTOPEN; + goto _cleanup; + } + + for (i=0; ;i++) { + DWORD dw; + + dw = ARRAYLENGTH(sk_name); + l = RegEnumKeyEx(hkp, i, sk_name, &dw, + NULL, NULL, NULL, &ft); + + if (l != ERROR_SUCCESS) + break; + + if (!(wcsncmp(sk_name, t, cch))) { + /* bingo! ?? */ + if (sk_name[cch] == L'\0' || + sk_name[cch] == L'~') { + l = RegOpenKeyEx(hkp, sk_name, 0, + samDesired, phkResult); + if (l == ERROR_SUCCESS && lpdwDisposition) + *lpdwDisposition = REG_OPENED_EXISTING_KEY; + rv = l; + goto _cleanup; + } + } + + if (!_wcsnicmp(sk_name, t, cch) && + (sk_name[cch] == L'\0' || + sk_name[cch] == L'~')) { + long new_idx; + + if (sk_name[cch] == L'\0') + new_idx = 1; + else if (cch + 1 < KCONF_MAXCCH_NAME) + new_idx = wcstol(sk_name + (cch + 1), NULL, 10); + else + return ERROR_BUFFER_OVERFLOW; + + assert(new_idx > 0); + + if (new_idx > index) + index = new_idx; + } + } + + if (index != 0) { + if (FAILED(StringCbPrintf(sk_name, sizeof(sk_name), + L"%s~%d", t, index))) + return ERROR_BUFFER_OVERFLOW; + } else { + StringCbCopy(sk_name, sizeof(sk_name), t); + } + + rv = RegCreateKeyEx(hkp, + sk_name, + Reserved, + lpClass, + dwOptions, + samDesired, + lpSecurityAttributes, + phkResult, + lpdwDisposition); + + _cleanup: + + if (hkp != hKey && hkp != NULL) + RegCloseKey(hkp); + + return rv; +} + +/* obtains cs_conf_global */ +HKEY +khcint_space_open_key(kconf_conf_space * s, khm_int32 flags) { + HKEY hk = NULL; + int nflags = 0; + DWORD disp; + if(flags & KCONF_FLAG_MACHINE) { + if(s->regkey_machine) + return s->regkey_machine; + if((khcint_RegOpenKeyEx(HKEY_LOCAL_MACHINE, s->regpath, 0, + KEY_READ | KEY_WRITE, &hk) != + ERROR_SUCCESS) && + !(flags & KHM_PERM_WRITE)) { + + if(khcint_RegOpenKeyEx(HKEY_LOCAL_MACHINE, s->regpath, 0, + KEY_READ, &hk) == ERROR_SUCCESS) { + nflags = KHM_PERM_READ; + } + + } + if(!hk && (flags & KHM_FLAG_CREATE)) { + + khcint_RegCreateKeyEx(HKEY_LOCAL_MACHINE, + s->regpath, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hk, + &disp); + } + if(hk) { + EnterCriticalSection(&cs_conf_global); + s->regkey_machine = hk; + s->regkey_machine_flags = nflags; + LeaveCriticalSection(&cs_conf_global); + } + + return hk; + } else { + if(s->regkey_user) + return s->regkey_user; + if((khcint_RegOpenKeyEx(HKEY_CURRENT_USER, s->regpath, 0, + KEY_READ | KEY_WRITE, &hk) != + ERROR_SUCCESS) && + !(flags & KHM_PERM_WRITE)) { + if(khcint_RegOpenKeyEx(HKEY_CURRENT_USER, s->regpath, 0, + KEY_READ, &hk) == ERROR_SUCCESS) { + nflags = KHM_PERM_READ; + } + } + if(!hk && (flags & KHM_FLAG_CREATE)) { + khcint_RegCreateKeyEx(HKEY_CURRENT_USER, + s->regpath, 0, NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, &hk, &disp); + } + if(hk) { + EnterCriticalSection(&cs_conf_global); + s->regkey_user = hk; + s->regkey_user_flags = nflags; + LeaveCriticalSection(&cs_conf_global); + } + + return hk; + } +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_shadow_space(khm_handle upper, khm_handle lower) +{ + kconf_handle * h; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(upper)) { +#ifdef DEBUG + DebugBreak(); +#endif + return KHM_ERROR_INVALID_PARAM; + } + + h = (kconf_handle *) upper; + + EnterCriticalSection(&cs_conf_handle); + if(h->lower) { + EnterCriticalSection(&cs_conf_global); + khcint_handle_free(h->lower); + LeaveCriticalSection(&cs_conf_global); + h->lower = NULL; + } + + if(khc_is_handle(lower)) { + kconf_handle * l; + kconf_handle * lc; + + l = (kconf_handle *) lower; + lc = khcint_handle_dup(l); + h->lower = lc; + } + LeaveCriticalSection(&cs_conf_handle); + + return KHM_ERROR_SUCCESS; +} + +/* no locks */ +kconf_conf_space * +khcint_create_empty_space(void) { + kconf_conf_space * r; + + r = PMALLOC(sizeof(kconf_conf_space)); + assert(r != NULL); + ZeroMemory(r,sizeof(kconf_conf_space)); + + return r; +} + +/* called with cs_conf_global */ +void +khcint_free_space(kconf_conf_space * r) { + kconf_conf_space * c; + + if(!r) + return; + + TPOPCHILD(r, &c); + while(c) { + khcint_free_space(c); + TPOPCHILD(r, &c); + } + + if(r->name) + PFREE(r->name); + + if(r->regpath) + PFREE(r->regpath); + + if(r->regkey_machine) + RegCloseKey(r->regkey_machine); + + if(r->regkey_user) + RegCloseKey(r->regkey_user); + + PFREE(r); +} + +/* obtains cs_conf_global */ +khm_int32 +khcint_open_space(kconf_conf_space * parent, + const wchar_t * sname, size_t n_sname, + khm_int32 flags, kconf_conf_space **result) { + kconf_conf_space * p; + kconf_conf_space * c; + HKEY pkey = NULL; + HKEY ckey = NULL; + wchar_t buf[KCONF_MAXCCH_NAME]; + size_t cb_regpath = 0; + + if(!parent) + p = conf_root; + else + p = parent; + + if(n_sname >= KCONF_MAXCCH_NAME || n_sname <= 0) + return KHM_ERROR_INVALID_PARAM; + + StringCchCopyN(buf, ARRAYLENGTH(buf), sname, n_sname); + + /* see if there is already a config space by this name. if so, + return it. Note that if the configuration space is specified + in a schema, we would find it here. */ + EnterCriticalSection(&cs_conf_global); + c = TFIRSTCHILD(p); + while(c) { + if(c->name && !wcscmp(c->name, buf)) + break; + + c = LNEXT(c); + } + LeaveCriticalSection(&cs_conf_global); + + if(c) { + + if (c->flags & KCONF_SPACE_FLAG_DELETED) { + if (flags & KHM_FLAG_CREATE) { + c->flags &= ~(KCONF_SPACE_FLAG_DELETED | + KCONF_SPACE_FLAG_DELETE_M | + KCONF_SPACE_FLAG_DELETE_U); + } else { + *result = NULL; + return KHM_ERROR_NOT_FOUND; + } + } + + khcint_space_hold(c); + *result = c; + return KHM_ERROR_SUCCESS; + } + + if(!(flags & KHM_FLAG_CREATE)) { + + /* we are not creating the space, so it must exist in the form of a + registry key in HKLM or HKCU. If it existed as a schema, we + would have already retured it above. */ + + if (flags & KCONF_FLAG_USER) + pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_USER); + + if((!pkey || + (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) != + ERROR_SUCCESS)) + && (flags & KCONF_FLAG_MACHINE)) { + + pkey = khcint_space_open_key(p, KHM_PERM_READ | KCONF_FLAG_MACHINE); + if(!pkey || + (khcint_RegOpenKeyEx(pkey, buf, 0, KEY_READ, &ckey) != + ERROR_SUCCESS)) { + *result = NULL; + + return KHM_ERROR_NOT_FOUND; + } + } + + if(ckey) { + RegCloseKey(ckey); + ckey = NULL; + } + } + + c = khcint_create_empty_space(); + + /*SAFE: buf: is of known length < KCONF_MAXCCH_NAME */ + c->name = PWCSDUP(buf); + + /*SAFE: p->regpath: is valid since it was set using this same + function. */ + /*SAFE: buf: see above */ + cb_regpath = (wcslen(p->regpath) + wcslen(buf) + 2) * sizeof(wchar_t); + c->regpath = PMALLOC(cb_regpath); + + assert(c->regpath != NULL); + + /*SAFE: c->regpath: allocated above to be big enough */ + /*SAFE: p->regpath: see above */ + StringCbCopy(c->regpath, cb_regpath, p->regpath); + StringCbCat(c->regpath, cb_regpath, L"\\"); + + /*SAFE: buf: see above */ + StringCbCat(c->regpath, cb_regpath, buf); + + khcint_space_hold(c); + + EnterCriticalSection(&cs_conf_global); + TADDCHILD(p,c); + LeaveCriticalSection(&cs_conf_global); + + *result = c; + return KHM_ERROR_SUCCESS; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags, + khm_handle * result) { + kconf_handle * h; + kconf_conf_space * p; + kconf_conf_space * c = NULL; + size_t cbsize; + const wchar_t * str; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) { + return KHM_ERROR_NOT_READY; + } + + if(!result || (parent && !khc_is_handle(parent))) { +#ifdef DEBUG + DebugBreak(); +#endif + return KHM_ERROR_INVALID_PARAM; + } + + if(!parent) + p = conf_root; + else { + h = (kconf_handle *) parent; + p = khc_space_from_handle(parent); + } + + khcint_space_hold(p); + + /* if none of these flags are specified, make it seem like all of + them were */ + if(!(flags & KCONF_FLAG_USER) && + !(flags & KCONF_FLAG_MACHINE) && + !(flags & KCONF_FLAG_SCHEMA)) + flags |= KCONF_FLAG_USER | KCONF_FLAG_MACHINE | KCONF_FLAG_SCHEMA; + + if(cspace == NULL) { + *result = (khm_handle) khcint_handle_from_space(p, flags); + khcint_space_release(p); + return KHM_ERROR_SUCCESS; + } + + if(FAILED(StringCbLength(cspace, KCONF_MAXCB_PATH, &cbsize))) { + khcint_space_release(p); + *result = NULL; + return KHM_ERROR_INVALID_PARAM; + } + + str = cspace; + while(TRUE) { + const wchar_t * end = NULL; + + if (!(flags & KCONF_FLAG_NOPARSENAME)) { + + end = wcschr(str, L'\\'); /* safe because cspace was + validated above */ + } + + if(!end) { + if(flags & KCONF_FLAG_TRAILINGVALUE) { + /* we are at the value component */ + c = p; + khcint_space_hold(c); + break; + } else + end = str + wcslen(str); /* safe because cspace was + validated above */ + } + + rv = khcint_open_space(p, str, end - str, flags, &c); + + if(KHM_SUCCEEDED(rv) && (*end == L'\\')) { + khcint_space_release(p); + p = c; + c = NULL; + str = end+1; + } + else + break; + } + + khcint_space_release(p); + if(KHM_SUCCEEDED(rv)) { + *result = khcint_handle_from_space(c, flags); + } else + *result = NULL; + + if (c) + khcint_space_release(c); + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_close_space(khm_handle csp) { + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(csp)) { +#ifdef DEBUG + DebugBreak(); +#endif + return KHM_ERROR_INVALID_PARAM; + } + + khcint_handle_free((kconf_handle *) csp); + return KHM_ERROR_SUCCESS; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_read_string(khm_handle pconf, + const wchar_t * pvalue, + wchar_t * buf, + khm_size * bufsize) +{ + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + do { + HKEY hku = NULL; + HKEY hkm = NULL; + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + DWORD size; + DWORD type; + LONG hr; + + int i; + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + + if(KHM_FAILED(khc_open_space( + pconf, + pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + goto _shadow; + + free_space = 1; + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf)) + goto _shadow; + + c = khc_space_from_handle(conf); + + if(khc_is_user_handle(conf)) + hku = khcint_space_open_key(c, KHM_PERM_READ); + + if(khc_is_machine_handle(conf)) + hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE); + + size = (DWORD) *bufsize; + if(hku) { + hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_SZ) { + rv = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + *bufsize = size; + /* if buf==NULL, RegQueryValueEx will return success and just return the + required buffer size in 'size' */ + rv = (buf)? KHM_ERROR_SUCCESS: KHM_ERROR_TOO_LONG; + goto _exit; + } + } else { + if(hr == ERROR_MORE_DATA) { + *bufsize = size; + rv = KHM_ERROR_TOO_LONG; + goto _exit; + } + } + } + + size = (DWORD) *bufsize; + if(hkm) { + hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_SZ) { + rv = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + *bufsize = size; + rv = (buf)? KHM_ERROR_SUCCESS: KHM_ERROR_TOO_LONG; + goto _exit; + } + } else { + if(hr == ERROR_MORE_DATA) { + *bufsize = size; + rv = KHM_ERROR_TOO_LONG; + goto _exit; + } + } + } + + if(c->schema && khc_is_schema_handle(conf)) { + for(i=0;i<c->nSchema;i++) { + if(c->schema[i].type == KC_STRING && !wcscmp(value, c->schema[i].name)) { + /* found it */ + size_t cbsize = 0; + + if(!c->schema[i].value) { + rv = KHM_ERROR_NOT_FOUND; + goto _exit; + } + + if(FAILED(StringCbLength((wchar_t *) c->schema[i].value, KCONF_MAXCB_STRING, &cbsize))) { + rv = KHM_ERROR_NOT_FOUND; + goto _exit; + } + cbsize += sizeof(wchar_t); + + if(!buf || *bufsize < cbsize) { + *bufsize = cbsize; + rv = KHM_ERROR_TOO_LONG; + goto _exit; + } + + StringCbCopy(buf, *bufsize, (wchar_t *) c->schema[i].value); + *bufsize = cbsize; + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } + } + +_shadow: + if(free_space && conf) + khc_close_space(conf); + + if(khc_is_shadowed(pconf)) { + pconf = khc_shadow(pconf); + continue; + } else { + rv = KHM_ERROR_NOT_FOUND; + break; + } + +_exit: + if(free_space && conf) + khc_close_space(conf); + break; + + } while(TRUE); + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_read_int32(khm_handle pconf, const wchar_t * pvalue, khm_int32 * buf) { + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!buf || !pvalue) + return KHM_ERROR_INVALID_PARAM; + + do { + DWORD size; + DWORD type; + LONG hr; + HKEY hku = NULL; + HKEY hkm = NULL; + + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + + int i; + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + if(KHM_FAILED(khc_open_space( + pconf, + pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + goto _shadow; + free_space = 1; + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf) || !buf) + goto _shadow; + + c = khc_space_from_handle(conf); + + if(khc_is_user_handle(conf)) + hku = khcint_space_open_key(c, KHM_PERM_READ); + + if(khc_is_machine_handle(conf)) + hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE); + + size = sizeof(DWORD); + if(hku) { + hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_DWORD) { + rv = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } + } + + size = sizeof(DWORD); + if(hkm) { + hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_DWORD) { + rv= KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + rv= KHM_ERROR_SUCCESS; + goto _exit; + } + } + } + + if(c->schema && khc_is_schema_handle(conf)) { + for(i=0;i<c->nSchema;i++) { + if(c->schema[i].type == KC_INT32 && !wcscmp(value, c->schema[i].name)) { + *buf = (khm_int32) c->schema[i].value; + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } + } +_shadow: + if(free_space && conf) + khc_close_space(conf); + + if(khc_is_shadowed(pconf)) { + pconf = khc_shadow(pconf); + continue; + } else { + rv = KHM_ERROR_NOT_FOUND; + break; + } +_exit: + if(free_space && conf) + khc_close_space(conf); + break; + } + while(TRUE); + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_read_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 * buf) { + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + do { + DWORD size; + DWORD type; + LONG hr; + HKEY hku = NULL; + HKEY hkm = NULL; + + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + + int i; + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + if(KHM_FAILED(khc_open_space( + pconf, + pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + goto _shadow; + free_space = 1; + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf) || !buf) + goto _shadow; + + c = khc_space_from_handle(conf); + + if(khc_is_user_handle(conf)) + hku = khcint_space_open_key(c, KHM_PERM_READ); + + if(khc_is_machine_handle(conf)) + hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE); + + size = sizeof(khm_int64); + if(hku) { + hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_QWORD) { + rv= KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } + } + + size = sizeof(khm_int64); + if(hkm) { + hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_QWORD) { + rv = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } + } + + if(c->schema && khc_is_schema_handle(conf)) { + for(i=0;i<c->nSchema;i++) { + if(c->schema[i].type == KC_INT64 && !wcscmp(value, c->schema[i].name)) { + *buf = (khm_int64) c->schema[i].value; + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } + } + +_shadow: + if(free_space && conf) + khc_close_space(conf); + if(khc_is_shadowed(pconf)) { + pconf = khc_shadow(pconf); + continue; + } else { + rv = KHM_ERROR_NOT_FOUND; + break; + } + +_exit: + if(free_space && conf) + khc_close_space(conf); + break; + + } while(TRUE); + return rv; +} + +/* obtaincs cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_read_binary(khm_handle pconf, const wchar_t * pvalue, + void * buf, khm_size * bufsize) { + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + do { + DWORD size; + DWORD type; + LONG hr; + HKEY hku = NULL; + HKEY hkm = NULL; + + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + if(KHM_FAILED(khc_open_space( + pconf, + pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + goto _shadow; + free_space = 1; + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf)) + goto _shadow; + + c = khc_space_from_handle(conf); + + if(khc_is_user_handle(conf)) + hku = khcint_space_open_key(c, KHM_PERM_READ); + + if(khc_is_machine_handle(conf)) + hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE); + + size = (DWORD) *bufsize; + if(hku) { + hr = RegQueryValueEx(hku, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_BINARY) { + rv = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + *bufsize = size; + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } else { + if(hr == ERROR_MORE_DATA) { + *bufsize = size; + rv = KHM_ERROR_TOO_LONG; + goto _exit; + } + } + } + + size = (DWORD) *bufsize; + if(hkm) { + hr = RegQueryValueEx(hkm, value, NULL, &type, (LPBYTE) buf, &size); + if(hr == ERROR_SUCCESS) { + if(type != REG_BINARY) { + rv = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + else { + *bufsize = size; + rv = KHM_ERROR_SUCCESS; + goto _exit; + } + } else { + if(hr == ERROR_MORE_DATA) { + *bufsize = size; + rv = KHM_ERROR_TOO_LONG; + goto _exit; + } + } + } + + /* binary values aren't supported in schema */ +_shadow: + if(free_space && conf) + khc_close_space(conf); + if(khc_is_shadowed(pconf)) { + pconf = khc_shadow(pconf); + continue; + } else { + rv = KHM_ERROR_NOT_FOUND; + break; + } + +_exit: + if(free_space && conf) + khc_close_space(conf); + break; + + }while (TRUE); + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_write_string(khm_handle pconf, + const wchar_t * pvalue, + wchar_t * buf) +{ + HKEY pk = NULL; + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + LONG hr; + size_t cbsize; + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf)) + return KHM_ERROR_INVALID_OPERATION; + + if(FAILED(StringCbLength(buf, KCONF_MAXCB_STRING, &cbsize))) { + rv = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cbsize += sizeof(wchar_t); + + if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) { + wchar_t tmpbuf[512]; + wchar_t * buffer; + size_t tmpsize = cbsize; + khm_boolean is_equal = FALSE; + + if (cbsize <= sizeof(tmpbuf)) { + buffer = tmpbuf; + } else { + buffer = PMALLOC(cbsize); + } + + if (KHM_SUCCEEDED(khc_read_string(pconf, pvalue, buffer, &tmpsize)) && + tmpsize == cbsize) { + if (khc_handle_flags(pconf) & KCONF_FLAG_IFMODCI) + is_equal = !_wcsicmp(buffer, buf); + else + is_equal = !wcscmp(buffer, buf); + } + + if (buffer != tmpbuf) + PFREE(buffer); + + if (is_equal) { + return KHM_ERROR_SUCCESS; + } + } + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + if(KHM_FAILED(khc_open_space(pconf, pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + return KHM_ERROR_INVALID_PARAM; + free_space = 1; + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf) || !buf) { + rv = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + c = khc_space_from_handle(conf); + + if(khc_is_user_handle(conf)) { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE); + } else { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE); + } + + hr = RegSetValueEx(pk, value, 0, REG_SZ, (LPBYTE) buf, (DWORD) cbsize); + + if(hr != ERROR_SUCCESS) + rv = KHM_ERROR_INVALID_OPERATION; + +_exit: + if(free_space) + khc_close_space(conf); + return rv; +} + +/* obtaincs cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_write_int32(khm_handle pconf, + const wchar_t * pvalue, + khm_int32 buf) +{ + HKEY pk = NULL; + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + LONG hr; + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf)) + return KHM_ERROR_INVALID_OPERATION; + + if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) { + khm_int32 tmpvalue; + + if (KHM_SUCCEEDED(khc_read_int32(pconf, pvalue, &tmpvalue)) && + tmpvalue == buf) { + return KHM_ERROR_SUCCESS; + } + } + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + if(KHM_FAILED(khc_open_space( + pconf, + pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + return KHM_ERROR_INVALID_PARAM; + free_space = 1; + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + c = khc_space_from_handle( conf); + + if(khc_is_user_handle(conf)) { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE); + } else { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE); + } + + hr = RegSetValueEx(pk, value, 0, REG_DWORD, (LPBYTE) &buf, sizeof(khm_int32)); + + if(hr != ERROR_SUCCESS) + rv = KHM_ERROR_INVALID_OPERATION; + + if(free_space) + khc_close_space(conf); + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_write_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 buf) { + HKEY pk = NULL; + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + LONG hr; + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf)) + return KHM_ERROR_INVALID_OPERATION; + + if (khc_handle_flags(pconf) & KCONF_FLAG_WRITEIFMOD) { + khm_int64 tmpvalue; + + if (KHM_SUCCEEDED(khc_read_int64(pconf, pvalue, &tmpvalue)) && + tmpvalue == buf) { + return KHM_ERROR_SUCCESS; + } + } + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + if(KHM_FAILED(khc_open_space( + pconf, + pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + return KHM_ERROR_INVALID_PARAM; + free_space = 1; + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + c = khc_space_from_handle( conf); + + if(khc_is_user_handle(conf)) { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE); + } else { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE); + } + + hr = RegSetValueEx(pk, value, 0, REG_QWORD, (LPBYTE) &buf, sizeof(khm_int64)); + + if(hr != ERROR_SUCCESS) + rv = KHM_ERROR_INVALID_OPERATION; + + if(free_space) + khc_close_space(conf); + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_write_binary(khm_handle pconf, + const wchar_t * pvalue, + void * buf, khm_size bufsize) { + HKEY pk = NULL; + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + LONG hr; + const wchar_t * value = NULL; + int free_space = 0; + khm_handle conf = NULL; + + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf)) + return KHM_ERROR_INVALID_OPERATION; + + if((value = wcsrchr(pvalue, L'\\')) != NULL) { + if(KHM_FAILED(khc_open_space( + pconf, + pvalue, + KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), + &conf))) + return KHM_ERROR_INVALID_PARAM; + free_space = 1; + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } else { + value = pvalue; + conf = pconf; + free_space = 0; + } + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + c = khc_space_from_handle(conf); + + if(khc_is_user_handle(conf)) { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KHM_FLAG_CREATE); + } else { + pk = khcint_space_open_key(c, KHM_PERM_WRITE | KCONF_FLAG_MACHINE | KHM_FLAG_CREATE); + } + + hr = RegSetValueEx(pk, value, 0, REG_BINARY, buf, (DWORD) bufsize); + + if(hr != ERROR_SUCCESS) + rv = KHM_ERROR_INVALID_OPERATION; + + if(free_space) + khc_close_space(conf); + + return rv; +} + +/* no locks */ +KHMEXP khm_int32 KHMAPI +khc_get_config_space_name(khm_handle conf, + wchar_t * buf, khm_size * bufsize) { + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + c = khc_space_from_handle(conf); + + if(!c->name) { + if(buf && *bufsize > 0) + buf[0] = L'\0'; + else { + *bufsize = sizeof(wchar_t); + rv = KHM_ERROR_TOO_LONG; + } + } else { + size_t cbsize; + + if(FAILED(StringCbLength(c->name, KCONF_MAXCB_NAME, &cbsize))) + return KHM_ERROR_UNKNOWN; + + cbsize += sizeof(wchar_t); + + if(!buf || cbsize > *bufsize) { + *bufsize = cbsize; + rv = KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(buf, *bufsize, c->name); + *bufsize = cbsize; + } + } + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_get_config_space_parent(khm_handle conf, khm_handle * parent) { + kconf_conf_space * c; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + c = khc_space_from_handle(conf); + + if(c == conf_root || c->parent == conf_root) + *parent = NULL; + else + *parent = khcint_handle_from_space(c->parent, khc_handle_flags(conf)); + + return KHM_ERROR_SUCCESS; +} + +/* obtains cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_get_type(khm_handle conf, const wchar_t * value) { + HKEY hkm = NULL; + HKEY hku = NULL; + kconf_conf_space * c; + khm_int32 rv; + LONG hr = ERROR_SUCCESS; + DWORD type = 0; + + if(!khc_is_config_running()) + return KC_NONE; + + if(!khc_is_handle(conf)) + return KC_NONE; + + c = khc_space_from_handle(conf); + + if(!khc_is_machine_handle(conf)) + hku = khcint_space_open_key(c, KHM_PERM_READ); + hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE); + + if(hku) + hr = RegQueryValueEx(hku, value, NULL, &type, NULL, NULL); + if(!hku || hr != ERROR_SUCCESS) + hr = RegQueryValueEx(hkm, value, NULL, &type, NULL, NULL); + if(((!hku && !hkm) || hr != ERROR_SUCCESS) && c->schema) { + int i; + + for(i=0; i<c->nSchema; i++) { + if(!wcscmp(c->schema[i].name, value)) { + return c->schema[i].type; + } + } + + return KC_NONE; + } + + switch(type) { + case REG_MULTI_SZ: + case REG_SZ: + rv = KC_STRING; + break; + case REG_DWORD: + rv = KC_INT32; + break; + case REG_QWORD: + rv = KC_INT64; + break; + case REG_BINARY: + rv = KC_BINARY; + break; + default: + rv = KC_NONE; + } + + return rv; +} + +/* obtains cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_value_exists(khm_handle conf, const wchar_t * value) { + HKEY hku = NULL; + HKEY hkm = NULL; + kconf_conf_space * c; + khm_int32 rv = 0; + DWORD t; + int i; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + do { + c = khc_space_from_handle(conf); + + if (khc_is_user_handle(conf)) + hku = khcint_space_open_key(c, KHM_PERM_READ); + if (khc_is_machine_handle(conf)) + hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE); + + if(hku && (RegQueryValueEx(hku, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS)) + rv |= KCONF_FLAG_USER; + if(hkm && (RegQueryValueEx(hkm, value, NULL, &t, NULL, NULL) == ERROR_SUCCESS)) + rv |= KCONF_FLAG_MACHINE; + + if(c->schema && khc_is_schema_handle(conf)) { + for(i=0; i<c->nSchema; i++) { + if(!wcscmp(c->schema[i].name, value)) { + rv |= KCONF_FLAG_SCHEMA; + break; + } + } + } + + /* if the value is not found at this level and the handle is + shadowed, try the next level down. */ + if (rv == 0 && khc_is_shadowed(conf)) + conf = khc_shadow(conf); + else + break; + } while (conf); + + return rv; +} + +/* obtains cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_remove_value(khm_handle conf, const wchar_t * value, khm_int32 flags) { + HKEY hku = NULL; + HKEY hkm = NULL; + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_NOT_FOUND; + DWORD t; + LONG l; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + c = khc_space_from_handle(conf); + + if(khc_is_user_handle(conf)) + hku = khcint_space_open_key(c, KHM_PERM_READ); + hkm = khcint_space_open_key(c, KHM_PERM_READ | KCONF_FLAG_MACHINE); + + if((flags == 0 || + (flags & KCONF_FLAG_USER)) && + hku && (RegQueryValueEx(hku, value, NULL, + &t, NULL, NULL) == ERROR_SUCCESS)) { + l = RegDeleteValue(hku, value); + if (l == ERROR_SUCCESS) + rv = KHM_ERROR_SUCCESS; + else + rv = KHM_ERROR_UNKNOWN; + } + if((flags == 0 || + (flags & KCONF_FLAG_MACHINE)) && + hkm && (RegQueryValueEx(hkm, value, NULL, + &t, NULL, NULL) == ERROR_SUCCESS)) { + l = RegDeleteValue(hkm, value); + if (l == ERROR_SUCCESS) + rv = (rv == KHM_ERROR_UNKNOWN)?KHM_ERROR_PARTIAL: + KHM_ERROR_SUCCESS; + else + rv = (rv == KHM_ERROR_SUCCESS)?KHM_ERROR_PARTIAL: + KHM_ERROR_UNKNOWN; + } + + return rv; +} + +/* called with cs_conf_global held */ +khm_int32 +khcint_remove_space(kconf_conf_space * c, khm_int32 flags) { + kconf_conf_space * cc; + kconf_conf_space * cn; + kconf_conf_space * p; + khm_boolean free_c = FALSE; + + /* TODO: if this is the last child space and the parent is marked + for deletion, delete the parent as well. */ + + p = TPARENT(c); + + /* We don't allow deleting top level keys. They are + predefined. */ +#ifdef DEBUG + assert(p); +#endif + if (!p) + return KHM_ERROR_INVALID_OPERATION; + + cc = TFIRSTCHILD(c); + while (cc) { + cn = LNEXT(cc); + + khcint_remove_space(cc, flags); + + cc = cn; + } + + cc = TFIRSTCHILD(c); + if (!cc && c->refcount == 0) { + TDELCHILD(p, c); + free_c = TRUE; + } else { + c->flags |= (flags & + (KCONF_SPACE_FLAG_DELETE_M | + KCONF_SPACE_FLAG_DELETE_U)); + + /* if all the registry spaces have been marked as deleted and + there is no schema, we should mark the space as deleted as + well. Note that ideally we only need to check for stores + which have data corresponding to this configuration space, + but this is a bit problematic since we don't monitor the + registry for changes. */ + if ((c->flags & + (KCONF_SPACE_FLAG_DELETE_M | + KCONF_SPACE_FLAG_DELETE_U)) == + (KCONF_SPACE_FLAG_DELETE_M | + KCONF_SPACE_FLAG_DELETE_U) && + (!c->schema || c->nSchema == 0)) + + c->flags |= KCONF_SPACE_FLAG_DELETED; + } + + if (c->regpath && p->regpath) { + HKEY hk; + + if (flags & KCONF_SPACE_FLAG_DELETE_U) { + hk = khcint_space_open_key(p, KCONF_FLAG_USER); + + if (hk) + khcint_RegDeleteKey(hk, c->name); + } + if (flags & KCONF_SPACE_FLAG_DELETE_M) { + hk = khcint_space_open_key(p, KCONF_FLAG_MACHINE); + + if (hk) + khcint_RegDeleteKey(hk, c->name); + } + } + + if (free_c) { + khcint_free_space(c); + } + + return KHM_ERROR_SUCCESS; +} + +/* obtains cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_remove_space(khm_handle conf) { + + /* + - mark this space as well as all child spaces as + 'delete-on-close' using flags. Mark should indicate which + repository to delete the space from. (user/machine) + + - When each subspace is released, check if it has been marked + for deletion. If so, delete the marked spaces as well as + removing the space from kconf space tree. + + - When removing a subspace from a space, check if the parent + space has any children left. If there are none, check if the + parent space is also marked for deletion. + */ + kconf_conf_space * c; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_int32 flags = 0; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + c = khc_space_from_handle(conf); + + EnterCriticalSection(&cs_conf_global); + + if (khc_is_machine_handle(conf)) + flags |= KCONF_SPACE_FLAG_DELETE_M; + if (khc_is_user_handle(conf)) + flags |= KCONF_SPACE_FLAG_DELETE_U; + + rv = khcint_remove_space(c, flags); + + LeaveCriticalSection(&cs_conf_global); + + return rv; +} + +/* no locks */ +khm_boolean +khcint_is_valid_name(wchar_t * name) +{ + size_t cbsize; + if(FAILED(StringCbLength(name, KCONF_MAXCB_NAME, &cbsize))) + return FALSE; + return TRUE; +} + +/* no locks */ +khm_int32 +khcint_validate_schema(const kconf_schema * schema, + int begin, + int *end) +{ + int i; + int state = 0; + int end_found = 0; + + i=begin; + while(!end_found) { + switch(state) { + case 0: /* initial. this record should start a config space */ + if(!khcint_is_valid_name(schema[i].name) || + schema[i].type != KC_SPACE) + return KHM_ERROR_INVALID_PARAM; + state = 1; + break; + + case 1: /* we are inside a config space, in the values area */ + if(!khcint_is_valid_name(schema[i].name)) + return KHM_ERROR_INVALID_PARAM; + if(schema[i].type == KC_SPACE) { + if(KHM_FAILED(khcint_validate_schema(schema, i, &i))) + return KHM_ERROR_INVALID_PARAM; + state = 2; + } else if(schema[i].type == KC_ENDSPACE) { + end_found = 1; + if(end) + *end = i; + } else { + if(schema[i].type != KC_STRING && + schema[i].type != KC_INT32 && + schema[i].type != KC_INT64 && + schema[i].type != KC_BINARY) + return KHM_ERROR_INVALID_PARAM; + } + break; + + case 2: /* we are inside a config space, in the subspace area */ + if(schema[i].type == KC_SPACE) { + if(KHM_FAILED(khcint_validate_schema(schema, i, &i))) + return KHM_ERROR_INVALID_PARAM; + } else if(schema[i].type == KC_ENDSPACE) { + end_found = 1; + if(end) + *end = i; + } else { + return KHM_ERROR_INVALID_PARAM; + } + break; + + default: + /* unreachable */ + return KHM_ERROR_INVALID_PARAM; + } + i++; + } + + return KHM_ERROR_SUCCESS; +} + +/* obtains cs_conf_handle/cs_conf_global; called with cs_conf_global */ +khm_int32 +khcint_load_schema_i(khm_handle parent, const kconf_schema * schema, + int begin, int * end) +{ + int i; + int state = 0; + int end_found = 0; + kconf_conf_space * thisconf = NULL; + khm_handle h = NULL; + + i=begin; + while(!end_found) { + switch(state) { + case 0: /* initial. this record should start a config space */ + LeaveCriticalSection(&cs_conf_global); + if(KHM_FAILED(khc_open_space(parent, schema[i].name, + KHM_FLAG_CREATE, &h))) { + EnterCriticalSection(&cs_conf_global); + return KHM_ERROR_INVALID_PARAM; + } + EnterCriticalSection(&cs_conf_global); + thisconf = khc_space_from_handle(h); + thisconf->schema = schema + (begin + 1); + thisconf->nSchema = 0; + state = 1; + break; + + case 1: /* we are inside a config space, in the values area */ + if(schema[i].type == KC_SPACE) { + thisconf->nSchema = i - (begin + 1); + if(KHM_FAILED(khcint_load_schema_i(h, schema, i, &i))) + return KHM_ERROR_INVALID_PARAM; + state = 2; + } else if(schema[i].type == KC_ENDSPACE) { + thisconf->nSchema = i - (begin + 1); + end_found = 1; + if(end) + *end = i; + LeaveCriticalSection(&cs_conf_global); + khc_close_space(h); + EnterCriticalSection(&cs_conf_global); + } + break; + + case 2: /* we are inside a config space, in the subspace area */ + if(schema[i].type == KC_SPACE) { + if(KHM_FAILED(khcint_load_schema_i(h, schema, i, &i))) + return KHM_ERROR_INVALID_PARAM; + } else if(schema[i].type == KC_ENDSPACE) { + end_found = 1; + if(end) + *end = i; + LeaveCriticalSection(&cs_conf_global); + khc_close_space(h); + EnterCriticalSection(&cs_conf_global); + } else { + return KHM_ERROR_INVALID_PARAM; + } + break; + + default: + /* unreachable */ + return KHM_ERROR_INVALID_PARAM; + } + i++; + } + + return KHM_ERROR_SUCCESS; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_load_schema(khm_handle conf, const kconf_schema * schema) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(conf && !khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + if(KHM_FAILED(khcint_validate_schema(schema, 0, NULL))) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_conf_global); + rv = khcint_load_schema_i(conf, schema, 0, NULL); + LeaveCriticalSection(&cs_conf_global); + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global; called with cs_conf_global */ +khm_int32 +khcint_unload_schema_i(khm_handle parent, const kconf_schema * schema, + int begin, int * end) +{ + int i; + int state = 0; + int end_found = 0; + kconf_conf_space * thisconf = NULL; + khm_handle h = NULL; + + i=begin; + while(!end_found) { + switch(state) { + case 0: /* initial. this record should start a config space */ + LeaveCriticalSection(&cs_conf_global); + if(KHM_FAILED(khc_open_space(parent, schema[i].name, 0, &h))) { + EnterCriticalSection(&cs_conf_global); + return KHM_ERROR_INVALID_PARAM; + } + EnterCriticalSection(&cs_conf_global); + thisconf = khc_space_from_handle(h); + if(thisconf->schema == (schema + (begin + 1))) { + thisconf->schema = NULL; + thisconf->nSchema = 0; + } + state = 1; + break; + + case 1: /* we are inside a config space, in the values area */ + if(schema[i].type == KC_SPACE) { + if(KHM_FAILED(khcint_unload_schema_i(h, schema, i, &i))) + return KHM_ERROR_INVALID_PARAM; + state = 2; + } else if(schema[i].type == KC_ENDSPACE) { + end_found = 1; + if(end) + *end = i; + LeaveCriticalSection(&cs_conf_global); + khc_close_space(h); + EnterCriticalSection(&cs_conf_global); + } + break; + + case 2: /* we are inside a config space, in the subspace area */ + if(schema[i].type == KC_SPACE) { + if(KHM_FAILED(khcint_unload_schema_i(h, schema, i, &i))) + return KHM_ERROR_INVALID_PARAM; + } else if(schema[i].type == KC_ENDSPACE) { + end_found = 1; + if(end) + *end = i; + LeaveCriticalSection(&cs_conf_global); + khc_close_space(h); + EnterCriticalSection(&cs_conf_global); + } else { + return KHM_ERROR_INVALID_PARAM; + } + break; + + default: + /* unreachable */ + return KHM_ERROR_INVALID_PARAM; + } + i++; + } + + return KHM_ERROR_SUCCESS; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_unload_schema(khm_handle conf, const kconf_schema * schema) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(conf && !khc_is_handle(conf)) + return KHM_ERROR_INVALID_PARAM; + + if(KHM_FAILED(khcint_validate_schema(schema, 0, NULL))) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_conf_global); + rv = khcint_unload_schema_i(conf, schema, 0, NULL); + LeaveCriticalSection(&cs_conf_global); + + return rv; +} + +/* obtaincs cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_enum_subspaces(khm_handle conf, + khm_handle prev, + khm_handle * next) +{ + kconf_conf_space * s; + kconf_conf_space * c; + kconf_conf_space * p; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!khc_is_handle(conf) || next == NULL || + (prev != NULL && !khc_is_handle(prev))) + return KHM_ERROR_INVALID_PARAM; + + s = khc_space_from_handle(conf); + + if(prev == NULL) { + /* first off, we enumerate all the registry spaces regardless of + whether the handle is applicable for some registry space or not. + See notes for khc_begin_enum_subspaces() for reasons as to why + this is done (notes are in kconfig.h)*/ + + /* go through the user hive first */ + { + HKEY hk_conf; + + hk_conf = khcint_space_open_key(s, 0); + if(hk_conf) { + wchar_t name[KCONF_MAXCCH_NAME]; + khm_handle h; + int idx; + + idx = 0; + while(RegEnumKey(hk_conf, idx, + name, ARRAYLENGTH(name)) == ERROR_SUCCESS) { + wchar_t * tilde; + tilde = wcschr(name, L'~'); + if (tilde) + *tilde = 0; + if(KHM_SUCCEEDED(khc_open_space(conf, name, 0, &h))) + khc_close_space(h); + idx++; + } + } + } + + /* go through the machine hive next */ + { + HKEY hk_conf; + + hk_conf = khcint_space_open_key(s, KCONF_FLAG_MACHINE); + if(hk_conf) { + wchar_t name[KCONF_MAXCCH_NAME]; + khm_handle h; + int idx; + + idx = 0; + while(RegEnumKey(hk_conf, idx, + name, ARRAYLENGTH(name)) == ERROR_SUCCESS) { + wchar_t * tilde; + tilde = wcschr(name, L'~'); + if (tilde) + *tilde = 0; + + if(KHM_SUCCEEDED(khc_open_space(conf, name, + KCONF_FLAG_MACHINE, &h))) + khc_close_space(h); + idx++; + } + } + } + + /* don't need to go through schema, because that was already + done when the schema was loaded. */ + } + + /* at last we are now ready to return the results */ + EnterCriticalSection(&cs_conf_global); + if(prev == NULL) { + c = TFIRSTCHILD(s); + rv = KHM_ERROR_SUCCESS; + } else { + p = khc_space_from_handle(prev); + if(TPARENT(p) == s) + c = LNEXT(p); + else + c = NULL; + } + LeaveCriticalSection(&cs_conf_global); + + if(prev != NULL) + khc_close_space(prev); + + if(c) { + *next = khcint_handle_from_space(c, khc_handle_flags(conf)); + rv = KHM_ERROR_SUCCESS; + } else { + *next = NULL; + rv = KHM_ERROR_NOT_FOUND; + } + + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_write_multi_string(khm_handle conf, const wchar_t * value, wchar_t * buf) +{ + size_t cb; + wchar_t vbuf[KCONF_MAXCCH_STRING]; + wchar_t *tb; + khm_int32 rv; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + if(!khc_is_handle(conf) || buf == NULL || value == NULL) + return KHM_ERROR_INVALID_PARAM; + + if(multi_string_to_csv(NULL, &cb, buf) != KHM_ERROR_TOO_LONG) + return KHM_ERROR_INVALID_PARAM; + + if (cb < sizeof(vbuf)) + tb = vbuf; + else + tb = PMALLOC(cb); + + assert(tb != NULL); + + multi_string_to_csv(tb, &cb, buf); + rv = khc_write_string(conf, value, tb); + + if (tb != vbuf) + PFREE(tb); + return rv; +} + +/* obtains cs_conf_handle/cs_conf_global */ +KHMEXP khm_int32 KHMAPI +khc_read_multi_string(khm_handle conf, const wchar_t * value, + wchar_t * buf, khm_size * bufsize) +{ + wchar_t vbuf[KCONF_MAXCCH_STRING]; + wchar_t * tb; + khm_size cbbuf; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!khc_is_config_running()) + return KHM_ERROR_NOT_READY; + + if(!bufsize) + return KHM_ERROR_INVALID_PARAM; + + rv = khc_read_string(conf, value, NULL, &cbbuf); + if(rv != KHM_ERROR_TOO_LONG) + return rv; + + if (cbbuf < sizeof(vbuf)) + tb = vbuf; + else + tb = PMALLOC(cbbuf); + + assert(tb != NULL); + + rv = khc_read_string(conf, value, tb, &cbbuf); + + if(KHM_FAILED(rv)) + goto _exit; + + rv = csv_to_multi_string(buf, bufsize, tb); + +_exit: + if (tb != vbuf) + PFREE(tb); + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/kconfig/kconfig.h b/krb5-1-6/src/windows/identity/kconfig/kconfig.h new file mode 100644 index 000000000..689992c29 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kconfig/kconfig.h @@ -0,0 +1,960 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCONFIG_H +#define __KHIMAIRA_KCONFIG_H + +#include<khdefs.h> +#include<mstring.h> + +/*! \defgroup kconf NetIDMgr Configuration Provider */ +/*@{*/ + +/*! \brief Configuration schema descriptor record + + The schema descriptor is a convenient way to provide a default set + of configuration options for a part of an application. It + describes the configuration spaces and the values and subspaces + contained in each space. + + \see kconf_load_schema() +*/ +typedef struct tag_kconf_schema { + wchar_t * name; /*!< name of the object being described. + Optional for KC_ENDSPACE type object, + but required for everything else. + Names can be upto KCONF_MAXCCH_NAME + characters in length. */ + khm_int32 type; /*!< type of the object. Can be one of + KC_SPACE, KC_ENDSPACE, KC_INT32, + KC_INT64, KC_STRING or KC_BINARY */ + khm_ui_8 value; /*!< the value of the object. It is not + used for KC_SPACE and KC_ENDSPACE + typed objects. For a KC_STRING, this + contains a pointer to the string + value. The string should not be + longer than KCONF_MAXCCH_STRING + characters. KC_INT32 and KC_INT64 + objects store the value directly in + this field, while KC_BINARY objects do + not support defining a default value + here. */ + wchar_t * description;/*!< a friendly description of the value + or configuration space. */ +} kconf_schema; + +/*! \name Configuration data types + @{*/ +/*! \brief Not a known type */ +#define KC_NONE 0 + +/*! \brief When used as ::kconf_schema \a type, defines the start of a configuration space. + + There should be a subsequent KC_ENDSPACE record in the schema + which defines the end of this configuration space. + + \a name specifies the name of the configuration space. Optionally + use \a description to provide a description.*/ +#define KC_SPACE 1 + +/*! \brief Ends a configuration space started with KC_SPACE */ +#define KC_ENDSPACE 2 + +/*! \brief A 32 bit integer + + Specifies a configuration parameter named \a name which is of this + type. Use \a description to provide an optional description of + the value. + + \a value specifies a default value for this parameter in the lower + 32 bits. +*/ +#define KC_INT32 3 + +/*! \brief A 64 bit integer + + Specifies a configuration parameter named \a name which is of this + type. Use \a description to provide an optional description of + the value. + + \a value specifies a default value for this parameter. +*/ +#define KC_INT64 4 + +/*! \brief A unicode string + + Specifies a configuration parameter named \a name which is of this + type. Use \a description to provide an optional description of + the value. + + \a value specifies a default value for this parameter which should + be a pointer to a NULL terminated unicode string of no more than + ::KCONF_MAXCCH_STRING characters. +*/ +#define KC_STRING 5 + +/*! \brief An unparsed binary stream + + Specifies a configuration parameter named \a name which is of this + type. Use \a description to provide an optional description of + the value. + + Default values are not supported for binary streams. \a value is + ignored. +*/ +#define KC_BINARY 6 +/*@}*/ + +/*! \brief This is the root configuration space */ +#define KCONF_FLAG_ROOT 0x00000001 + +/*! \brief Indicates the configuration store which stores user-specific information */ +#define KCONF_FLAG_USER 0x00000002 + +/*! \brief Indicates the configuration store which stores machine-specific information */ +#define KCONF_FLAG_MACHINE 0x00000004 + +/*! \brief Indicates the configuration store which stores the schema */ +#define KCONF_FLAG_SCHEMA 0x00000008 + +/*! \brief Indicates that the last component of the given configuration path is to be considered to be a configuration value */ +#define KCONF_FLAG_TRAILINGVALUE 0x00000020 + +/*! \brief Only write values back there is a change + + Any write operations using the handle with check if the value + being written is different from the value being read from the + handle. It will only be written if the value is different. + + \note Note that the value being read from a handle takes schema and + shadowed configuration handles into consideration while the value + being written is only written to the topmost layer of + configuration that can be written to. + + \note Note also that this flag does not affect binary values. + */ +#define KCONF_FLAG_WRITEIFMOD 0x00000040 + +/*! \brief Use case-insensitive comparison for KCONF_FLAG_WRITEIFMOD + + When used in combination with \a KCONF_FLAG_WRITEIFMOD , the + string comparison used when determining whether the string read + from the configuration handle is the same as the string being + written will be case insensitive. If this flag is not set, the + comparison will be case sensitive. + */ +#define KCONF_FLAG_IFMODCI 0x00000080 + +/*! \brief Do not parse the configuration space name + + If set, disables the parsing of the configuration space for + subspaces. The space name is taken verbatim to be a configuration + space name. This can be used when there can be forward slashes or + backslahes in the name which are not escaped. + + By default, the configuration space name, + + \code + L"foo\\bar" + \endcode + + is taken to mean the configuration space \a bar which is a + subspace of \a foo. If ::KCONF_FLAG_NOPARSENAME is set, then this + is taken to mean configuration space \a foo\\bar. + */ +#define KCONF_FLAG_NOPARSENAME 0x00000040 + +/*! \brief Maximum number of allowed characters (including terminating NULL) in a name + + \note This is a hard limit in Windows, since we are mapping + configuration spaces to registry keys. +*/ +#define KCONF_MAXCCH_NAME 256 + +/*! \brief Maximum number of allowed bytes (including terminating NULL) in a name */ +#define KCONF_MAXCB_NAME (KCONF_MAXCCH_NAME * sizeof(wchar_t)) + +/*! \brief Maximum level of nesting for configuration spaces + */ +#define KCONF_MAX_DEPTH 16 + +/*! \brief Maximum number of allowed characters (including terminating NULL) in a configuration path */ +#define KCONF_MAXCCH_PATH (KCONF_MAXCCH_NAME * KCONF_MAX_DEPTH) + +/*! \brief Maximum number of allowed bytes (including terminating NULL) in a configuration path */ +#define KCONF_MAXCB_PATH (KCONF_MAXCCH_PATH * sizeof(wchar_t)) + +/*! \brief Maximum number of allowed characters (including terminating NULL) in a string */ +#define KCONF_MAXCCH_STRING KHM_MAXCCH_STRING + +/*! \brief Maximum number of allowed bytes (including terminating NULL) in a string */ +#define KCONF_MAXCB_STRING (KCONF_MAXCCH_STRING * sizeof(wchar_t)) + +/*! \brief Open a configuration space + + Opens the configuration space specified by \a cspace. By default, + the opened space includes user,machine and schema configuration + stores. However, you can specify a subset of these. + + If the configuration space does not exist and the \a flags specify + KHM_FLAG_CREATE, then the configuration space is created. The + stores that are affected by the create operation depend on \a + flags. If the \a flags only specifies ::KCONF_FLAG_MACHINE, then + the configuration space is created in the machine store. If \a + flags specifies any combination of stores including \a + ::KCONF_FLAG_USER, then the configuration space is created in the + user store. Note that ::KCONF_FLAG_SCHEMA is readonly. + + Once opened, use khc_close_space() to close the configuration + space. + + \param[in] parent The parent configuration space. The path + specified in \a cspace is relative to the parent. Set this to + NULL to indicate the root configuration space. + + \param[in] cspace The configuration path. This can be up to + ::KCONF_MAXCCH_PATH characters in length. Use backslashes to + specify hiearchy. Set this to NULL to reopen the parent + configuration space. + + \param[in] flags Flags. This can be a combination of KCONF_FLAG_* + constants and KHM_FLAG_CREATE. If none of ::KCONF_FLAG_USER, + ::KCONF_FLAG_MACHINE or ::KCONF_FLAG_SCHEMA is specified, then + it defaults to all three. + + \param[out] result Pointer to a handle which receives the handle + to the opened configuration space if the call succeeds. + + \note You can re-open a configuration space with different flags + such as ::KCONF_FLAG_MACHINE by specifying NULL for \a cspace + and settings \a flags to the required flags. + +*/ +KHMEXP khm_int32 KHMAPI +khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags, + khm_handle * result); + +/*! \brief Set the shadow space for a configuration handle + + The handle specified by \a lower becomes a shadow for the handle + specified by \a upper. Any configuration value that is queried in + \a upper that does not exist in \a upper will be queried in \a + lower. + + If \a upper already had a shadow handle, that handle will be + replaced by \a lower. The handle \a lower still needs to be + closed by a call to khc_close_space(). However, closing \a lower + will not affect \a upper which will still treat the configuration + space pointed to by \a lower to be it's shadow. + + Shadows are specific to handles and not configuration spaces. + Shadowing a configuration space using one handle does not affect + any other handles which may be obtained for the same configuration + space. + + Specify NULL for \a lower to remove any prior shadow. + */ +KHMEXP khm_int32 KHMAPI +khc_shadow_space(khm_handle upper, khm_handle lower); + +/*! \brief Close a handle opened with khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_close_space(khm_handle conf); + +/*! \brief Read a string value from a configuration space + + The \a value_name parameter specifies the value to read from the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to access the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema + store. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. + + If the value is not found in the configuration space and any + shadowed configuration spaces, the function returns \a + KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified. + + \param[in] buf Buffer to copy the string to. Specify NULL to just + retrieve the number of required bytes. + + \param[in,out] bufsize On entry, specifies the number of bytes of + space available at the location specified by \a buf. On exit + specifies the number of bytes actually copied or the size of + the required buffer if \a buf is NULL or insufficient. + + \retval KHM_ERROR_NOT_READY The configuration provider has not started + \retval KHM_ERROR_INVALID_PARAM One or more of the supplied parameters are not valid + \retval KHM_ERROR_TYPE_MISMATCH The specified value is not a string + \retval KHM_ERROR_TOO_LONG \a buf was NULL or the size of the buffer was insufficient. The required size is in bufsize. + \retval KHM_ERROR_SUCCESS Success. The number of bytes copied is in bufsize. + \retval KHM_ERROR_NOT_FOUND The value was not found. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_read_string(khm_handle conf, + const wchar_t * value_name, + wchar_t * buf, + khm_size * bufsize); + +/*! \brief Read a multi-string value from a configuration space + + The \a value_name parameter specifies the value to read from the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to access the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema + store. + + A multi-string is a pseudo data type. The value in the + configuration store should contain a CSV string. Each comma + separated value in the CSV string is considered to be a separate + value. Empty values are not allowed. The buffer pointed to by \a + buf will receive these values in the form of a series of NULL + terminated strings terminated by an empty string (or equivalently, + the last string will be terminated by a double NULL). + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. + + If the value is not found in the configuration space and any + shadowed configuration spaces, the function returns \a + KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified. + + \param[in] buf Buffer to copy the multi-string to. Specify NULL + to just retrieve the number of required bytes. + + \param[in,out] bufsize On entry, specifies the number of bytes of + space available at the location specified by \a buf. On exit + specifies the number of bytes actually copied or the size of + the required buffer if \a buf is NULL or insufficient. + + \retval KHM_ERROR_NOT_READY The configuration provider has not started + \retval KHM_ERROR_INVALID_PARAM One or more of the supplied parameters are not valid + \retval KHM_ERROR_TYPE_MISMATCH The specified value is not a string + \retval KHM_ERROR_TOO_LONG \a buf was NULL or the size of the buffer was insufficient. The required size is in bufsize. + \retval KHM_ERROR_SUCCESS Success. The number of bytes copied is in bufsize. + \retval KHM_ERROR_NOT_FOUND The value was not found. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_read_multi_string(khm_handle conf, + const wchar_t * value_name, + wchar_t * buf, + khm_size * bufsize); + +/*! \brief Read a 32 bit integer value from a configuration space + + The \a value_name parameter specifies the value to read from the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to access the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema + store. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. + + If the value is not found in the configuration space and any + shadowed configuration spaces, the function returns \a + KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified. + + \param[in] conf Handle to a configuration space + \param[in] value The value to query + \param[out] buf The buffer to receive the value + + \retval KHM_ERROR_NOT_READY The configuration provider has not started. + \retval KHM_ERROR_SUCCESS Success. The value that was read was placed in \a buf + \retval KHM_ERROR_NOT_FOUND The specified value was not found + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_TYPE_MISMATCH The specified value was found but was not of the correct type. + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_read_int32(khm_handle conf, + const wchar_t * value_name, + khm_int32 * buf); + +/*! \brief Read a 64 bit integer value from a configuration space + + The \a value_name parameter specifies the value to read from the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to access the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + - Otherwise, if KCONF_FLAG_SCHEMA was specified, the the schema + store. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. + + If the value is not found in the configuration space and any + shadowed configuration spaces, the function returns \a + KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified. + + \param[in] conf Handle to a configuration space + \param[in] value_name The value to query + \param[out] buf The buffer to receive the value + + \retval KHM_ERROR_NOT_READY The configuration provider has not started + \retval KHM_ERROR_SUCCESS Success. The value that was read was placed in \a buf + \retval KHM_ERROR_NOT_FOUND The specified value was not found + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_TYPE_MISMATCH The specified value was found but was not the correct data type. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_read_int64(khm_handle conf, + const wchar_t * value_name, + khm_int64 * buf); + +/*! \brief Read a binary value from a configuration space + + The \a value_name parameter specifies the value to read from the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to access the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. Also note that the schema store (KCONF_FLAG_SCHEMA) does + not support binary values. + + If the value is not found in the configuration space and any + shadowed configuration spaces, the function returns \a + KHM_ERROR_NOT_FOUND. In this case, the buffer is left unmodified. + + \param[in] buf Buffer to copy the string to. Specify NULL to just + retrieve the number of required bytes. + + \param[in,out] bufsize On entry, specifies the number of bytes of + space available at the location specified by \a buf. On exit + specifies the number of bytes actually copied or the size of + the required buffer if \a buf is NULL or insufficient. + + \retval KHM_ERROR_SUCCESS Success. The data was copied to \a buf. The number of bytes copied is stored in \a bufsize + \retval KHM_ERROR_NOT_FOUND The specified value was not found + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_read_binary(khm_handle conf, + const wchar_t * value_name, + void * buf, + khm_size * bufsize); + +/*! \brief Write a string value to a configuration space + + The \a value_name parameter specifies the value to write to the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to write the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If \a KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if \a KCONF_FLAG_MACHINE was specified, then the + machine configuration space. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. Also note that the schema store (KCONF_FLAG_SCHEMA) is + readonly. + + If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to + khc_open_space() for obtaining the configuration handle, the + specified string will only be written if it is different from the + value being read from the handle. + + If the \a KCONF_FLAG_IFMODCI flag is specified along with the \a + KCONF_FLAG_WRITEIFMOD flag, then the string comparison used will + be case insensitive. + + \param[in] conf Handle to a configuration space + \param[in] value_name Name of value to write + \param[in] buf A NULL terminated unicode string not exceeding KCONF_MAXCCH_STRING in characters including terminating NULL + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_write_string(khm_handle conf, + const wchar_t * value_name, + wchar_t * buf); + +/*! \brief Write a multi-string value to a configuration space + + The \a value_name parameter specifies the value to write to the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to write the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + A multi-string is a pseudo data type. The buffer pointed to by \a + buf should contain a sequence of NULL terminated strings + terminated by an empty string (or equivalently, the last string + should terminate with a double NULL). This will be stored in the + value as a CSV string. + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. Also note that the schema store (KCONF_FLAG_SCHEMA) is + readonly. + + If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to + khc_open_space() for obtaining the configuration handle, the + specified string will only be written if it is different from the + value being read from the handle. + + If the \a KCONF_FLAG_IFMODCI flag is specified along with the \a + KCONF_FLAG_WRITEIFMOD flag, then the string comparison used will + be case insensitive. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_write_multi_string(khm_handle conf, + const wchar_t * value_name, + wchar_t * buf); + +/*! \brief Write a 32 bit integer value to a configuration space + + The \a value_name parameter specifies the value to write to the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to write the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. Also note that the schema store (KCONF_FLAG_SCHEMA) is + readonly. + + If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to + khc_open_space() for obtaining the configuration handle, the + specified string will only be written if it is different from the + value being read from the handle. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_write_int32(khm_handle conf, + const wchar_t * value_name, + khm_int32 buf); + +/*! \brief Write a 64 bit integer value to a configuration space + + The \a value_name parameter specifies the value to write to the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to write the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. Also note that the schema store (KCONF_FLAG_SCHEMA) is + readonly. + + If the \a KCONF_FLAG_WRITEIFMOD flag is specified in the call to + khc_open_space() for obtaining the configuration handle, the + specified string will only be written if it is different from the + value being read from the handle. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_write_int64(khm_handle conf, + const wchar_t * value_name, + khm_int64 buf); + +/*! \brief Write a binary value to a configuration space + + The \a value_name parameter specifies the value to write to the + configuration space. This can be either a value name or a value + path consisting of a series nested configuration space names + followed by the value name all separated by backslashes or forward + slashes. + + For example: If \a conf is a handle to the configuration space \c + 'A/B/C', then the value name \c 'D/E/v' refers to the value named + \c 'v' in the configuration space \c 'A/B/C/D/E'. + + The specific configuration store that is used to write the value + depends on the flags that were specified in the call to + khc_open_space(). The precedence of configuration stores are as + follows: + + - If KCONF_FLAG_USER was specified, then the user configuration + space. + + - Otherwise, if KCONF_FLAG_MACHINE was specified, then the machine + configuration space. + + Note that not specifying any of the configuration store specifiers + in the call to khc_open_space() is equivalent to specifying all + three. Also note that the schema store (KCONF_FLAG_SCHEMA) is + readonly. + + \see khc_open_space() +*/ +KHMEXP khm_int32 KHMAPI +khc_write_binary(khm_handle conf, + const wchar_t * value_name, + void * buf, + khm_size bufsize); + +/*! \brief Get the type of a value in a configuration space + + \return The return value is the type of the specified value, or + KC_NONE if the value does not exist. + */ +KHMEXP khm_int32 KHMAPI +khc_get_type(khm_handle conf, const wchar_t * value_name); + +/*! \brief Check which configuration stores contain a specific value. + + Each value in a configuration space can be contained in zero or + more configuration stores. Use this function to determine which + configuration stores contain the specific value. + + The returned bitmask always indicates a subset of the + configuration stores that were specified when opening the + configuration space corresponding to \a conf. + + If the specified handle is shadowed (see khc_shadow_space()) and + the value is not found in any of the visible stores for the + topmost handle, each of the shadowed handles will be tried in turn + until the value is found. The return value will correspond to the + handle where the value is first found. + + \return A combination of ::KCONF_FLAG_MACHINE, ::KCONF_FLAG_USER + and ::KCONF_FLAG_SCHEMA indicating which stores contain the + value. + */ +KHMEXP khm_int32 KHMAPI +khc_value_exists(khm_handle conf, const wchar_t * value); + +/*! \brief Remove a value from a configuration space + + Removes a value from one or more configuration stores. + + A value can exist in multiple configuration stores. Only the + values that are stored in writable stores can be removed. When + the function searches for values to remove, it will only look in + configuration stores that are specified in the handle. In + addition, the configuration stores affected can be further + narrowed by specifying them in the \a flags parameter. If \a + flags is zero, then all the stores visible to the handle are + searched. If \a flags specifies ::KCONF_FLAG_USER or + ::KCONF_FLAG_MACHINE or both, then only the specified stores are + searched, provided that the stores are visible to the handle. + + This function only operates on the topmost configuration space + visible to the handle. If the configuration handle is shadowed, + the shadowed configuration spaces are unaffected by the removal. + + \param[in] conf Handle to configuration space to remove value from + + \param[in] value_name Value to remove + + \param[in] flags Specifies which configuration stores will be + affected by the removal. See above. + + \retval KHM_ERROR_SUCCESS The value was removed from all the + specified configuration stores. + + \retval KHM_ERROR_NOT_FOUND The value was not found. + + \retval KHM_ERROR_UNKNOWN An unknown error occurred while trying + to remove the value. + + \retval KHM_ERROR_PARTIAL The value was successfully removed from + one or more stores, but the operation failed on one or more + other stores. + */ +KHMEXP khm_int32 KHMAPI +khc_remove_value(khm_handle conf, const wchar_t * value_name, khm_int32 flags); + +/*! \brief Get the name of a configuration space + + \param[in] conf Handle to a configuration space + + \param[out] buf The buffer to receive the name. Set to NULL if + only the size of the buffer is required. + + \param[in,out] bufsize On entry, holds the size of the buffer + pointed to by \a buf. On exit, holds the number of bytes + copied into the buffer including the NULL terminator. + */ +KHMEXP khm_int32 KHMAPI +khc_get_config_space_name(khm_handle conf, + wchar_t * buf, + khm_size * bufsize); + +/*! \brief Get a handle to the parent space + + \param[in] conf Handle to a configuration space + + \param[out] parent Handle to the parent configuration space if the + call succeeds. Receives NULL otherwise. The returned handle + must be closed using khc_close_space() + */ +KHMEXP khm_int32 KHMAPI +khc_get_config_space_parent(khm_handle conf, + khm_handle * parent); + +/*! \brief Load a configuration schema into the specified configuration space + + \param[in] conf Handle to a configuration space or NULL to use the + root configuration space. + + \param[in] schema The schema to load. The schema is assumed to be + well formed. + + \see khc_unload_schema() + */ +KHMEXP khm_int32 KHMAPI +khc_load_schema(khm_handle conf, + const kconf_schema * schema); + +/*! \brief Unload a schema from a configuration space + */ +KHMEXP khm_int32 KHMAPI +khc_unload_schema(khm_handle conf, + const kconf_schema * schema); + +/*! \brief Enumerate the subspaces of a configuration space + + Prepares a configuration space for enumeration and returns the + child spaces in no particular order. + + \param[in] conf The configuration space to enumerate child spaces + + \param[in] prev The previous configuration space returned by + khc_enum_subspaces() or NULL if this is the first call. If + this is not NULL, then the handle passed in \a prev will be + freed. + + \param[out] next If \a prev was NULL, receives the first sub space + found in \a conf. You must \b either call + khc_enum_subspaces() again with the returned handle or call + khc_close_space() to free the returned handle if no more + subspaces are required. \a next can point to the same handle + specified in \a prev. + + \retval KHM_ERROR_SUCCESS The call succeeded. There is a valid + handle to a configuration space in \a first_subspace. + + \retval KHM_ERROR_INVALID_PARAM Either \a conf or \a prev was not a + valid configuration space handle or \a first_subspace is NULL. + Note that \a prev can be NULL. + + \retval KHM_ERROR_NOT_FOUND There were no subspaces in the + configuration space pointed to by \a conf. + + \note The configuration spaces that are enumerated directly belong + to the configuration space given by \a conf. This function + does not enumerate subspaces of shadowed configuration spaces + (see khc_shadow_space()). Even if \a conf was obtained on a + restricted domain (i.e. you specified one or more + configuration stores when you openend the handle and didn't + include all the configuration stores. See khc_open_space()), + the subspaces that are returned are the union of all + configuration spaces in all the configuration stores. This is + not a bug. This is a feature. In NetIDMgr, a configuartion + space exists if some configuration store defines it (or it was + created with a call to khc_open_space() even if no + configuration store defines it yet). This is the tradeoff you + make when using a layered configuration system. + + However, the returned handle has the same domain restrictions + as \a conf. + */ +KHMEXP khm_int32 KHMAPI +khc_enum_subspaces(khm_handle conf, + khm_handle prev, + khm_handle * next); + +/*! \brief Remove a configuration space + + The configuration space will be marked for removal. Once all the + handles for the space have been released, it will be deleted. The + configuration stores that will be affected are the write enabled + configuration stores for the handle. + */ +KHMEXP khm_int32 KHMAPI +khc_remove_space(khm_handle conf); +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/kconfig/kconfiginternal.h b/krb5-1-6/src/windows/identity/kconfig/kconfiginternal.h new file mode 100644 index 000000000..cd65877b3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kconfig/kconfiginternal.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCONFIGINTERNAL_H +#define __KHIMAIRA_KCONFIGINTERNAL_H + +#define _NIMLIB_ + +#include<windows.h> +#include<kconfig.h> +#include<khlist.h> +#include<kherror.h> +#include<utils.h> +#include<strsafe.h> + +/* TODO: Implement configuration provider interfaces + +typedef struct kconf_provider_t { + +} kconf_provider; +*/ + +typedef struct kconf_conf_space_t { + wchar_t * name; + + /* kconf_provider * provider; */ + + /* the regpath is the cumulative path starting from a hive root */ + wchar_t * regpath; + HKEY regkey_user; + khm_int32 regkey_user_flags; + HKEY regkey_machine; + khm_int32 regkey_machine_flags; + + khm_int32 refcount; + khm_int32 flags; + + const kconf_schema * schema; + khm_int32 nSchema; + + TDCL(struct kconf_conf_space_t); +} kconf_conf_space; + +#define KCONF_SPACE_FLAG_DELETE_U 0x00000040 +#define KCONF_SPACE_FLAG_DELETE_M 0x00000080 +#define KCONF_SPACE_FLAG_DELETED 0x00000100 + +typedef struct kconf_conf_handle_t { + khm_int32 magic; + khm_int32 flags; + kconf_conf_space * space; + + struct kconf_conf_handle_t * lower; + + LDCL(struct kconf_conf_handle_t); +} kconf_handle; + +#define KCONF_HANDLE_MAGIC 0x38eb49d2 +#define khc_is_handle(h) ((h) && ((kconf_handle *)h)->magic == KCONF_HANDLE_MAGIC) +#define khc_shadow(h) (((kconf_handle *)h)->lower) +#define khc_is_shadowed(h) (khc_is_handle(h) && khc_shadow(h) != NULL) + +extern kconf_conf_space * conf_root; +extern kconf_handle * conf_handles; +extern kconf_handle * conf_free_handles; +extern CRITICAL_SECTION cs_conf_global; +extern LONG conf_init; +extern LONG conf_status; + +#define khc_is_config_running() (conf_init && conf_status) + +#define CONFIG_REGPATHW L"Software\\MIT\\NetIDMgr" + +void init_kconf(void); +void exit_kconf(void); + +/* handle operations */ +#define khc_space_from_handle(h) (((kconf_handle *) h)->space) +#define khc_is_schema_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_SCHEMA) +#define khc_is_user_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_USER) +#define khc_is_machine_handle(h) (((kconf_handle *) h)->flags & KCONF_FLAG_MACHINE) +#define khc_handle_flags(h) (((kconf_handle *) h)->flags) + +kconf_handle * +khcint_handle_from_space(kconf_conf_space * s, khm_int32 flags); + +void +khcint_handle_free(kconf_handle * h); + +kconf_conf_space * +khcint_create_empty_space(void); + +void +khcint_free_space(kconf_conf_space * r); + +void +khcint_space_hold(kconf_conf_space * s); + +void +khcint_space_release(kconf_conf_space * s); + +HKEY +khcint_space_open_key(kconf_conf_space * s, khm_int32 flags); + +khm_int32 +khcint_remove_space(kconf_conf_space * c, khm_int32 flags); + +#endif diff --git a/krb5-1-6/src/windows/identity/kconfig/kconfigmain.c b/krb5-1-6/src/windows/identity/kconfig/kconfigmain.c new file mode 100644 index 000000000..bcf14625e --- /dev/null +++ b/krb5-1-6/src/windows/identity/kconfig/kconfigmain.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kconfiginternal.h> + +void +kconfig_process_attach(void) { + init_kconf(); +} + +void +kconfig_process_detach(void) { + exit_kconf(); +} diff --git a/krb5-1-6/src/windows/identity/kconfig/registry.c b/krb5-1-6/src/windows/identity/kconfig/registry.c new file mode 100644 index 000000000..d1e4009f2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kconfig/registry.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kconfiginternal.h> + diff --git a/krb5-1-6/src/windows/identity/kconfig/test/utiltest.c b/krb5-1-6/src/windows/identity/kconfig/test/utiltest.c new file mode 100644 index 000000000..f999dfa71 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kconfig/test/utiltest.c @@ -0,0 +1,207 @@ +#include<stdio.h> +#include<kconfig.h> +#include<strsafe.h> + +struct string_pair { + wchar_t * ms; + wchar_t * csv; +}; + +struct string_pair strings[] = { + {L"foo\0bar\0baz,quux\0ab\"cd\0", L"foo,bar,\"baz,quux\",\"ab\"\"cd\""}, + {L"a\0b\0c\0d\0e\0", L"a,b,c,d,e"}, + {L"1\0", L"1"}, + {L"\0", L""}, + {L"b\0a\0", L"b,a"}, + {L"c\0a\0b\0", L"c,a,b"}, + {L"c\0a\0B\0", L"c,a,B"}, + {L"sdf\0Bar\0Foo\0BBB\0", L"sdf,Bar,Foo,BBB"} +}; + +int n_strings = ARRAYLENGTH(strings); + +void print_ms(wchar_t * ms) { + wchar_t * s; + size_t cch; + + s = ms; + while(*s) { + printf("%S\\0", s); + StringCchLength(s, 512, &cch); + s += cch + 1; + } +} + +int ms_to_csv_test(void) { + wchar_t wbuf[512]; + int i; + khm_int32 code = 0; + size_t cbbuf; + size_t cbr; + size_t cbnull; + + printf("khc_multi_string_to_csv() test:\n"); + + for(i=0; i<n_strings; i++) { + cbbuf = sizeof(wbuf); + printf("Multi string:["); + print_ms(strings[i].ms); + printf("]->"); + code = khc_multi_string_to_csv(NULL, &cbnull, strings[i].ms); + code = khc_multi_string_to_csv(wbuf, &cbbuf, strings[i].ms); + if(code) { + printf(" returned %d\n", code); + return code; + } + printf("CSV[%S]", wbuf); + if(wcscmp(wbuf, strings[i].csv)) { + printf(" MISMATCH!"); + return 1; + } + + StringCbLength(wbuf, sizeof(wbuf), &cbr); + cbr+= sizeof(wchar_t); + + if(cbr != cbbuf) { + printf(" Length mismatch"); + return 1; + } + + if(cbnull != cbr) { + printf(" NULL length mismatch"); + return 1; + } + + printf("\n"); + } + + return code; +} + +int csv_to_ms_test(void) { + wchar_t wbuf[512]; + int i; + khm_int32 code = 0; + size_t cbbuf; + size_t cbr; + size_t cbnull; + + printf("khc_csv_to_multi_string() test:\n"); + + for(i=0; i<n_strings; i++) { + cbbuf = sizeof(wbuf); + printf("CSV:[%S]->", strings[i].csv); + code = khc_csv_to_multi_string(NULL, &cbnull, strings[i].csv); + code = khc_csv_to_multi_string(wbuf, &cbbuf, strings[i].csv); + if(code) { + printf(" returned %d\n", code); + return code; + } + printf("MS["); + print_ms(wbuf); + printf("]"); + + if(cbnull != cbbuf) { + printf(" NULL length mismatch"); + return 1; + } + + printf("\n"); + + printf(" Byte length:%d\n", cbbuf); + } + + return code; +} + +int ms_append_test(void) +{ + wchar_t wbuf[512]; + size_t cbbuf; + khm_int32 code; + int i; + + printf("khc_multi_string_append() test:\n"); + + for(i=0; i<n_strings; i++) { + cbbuf = sizeof(wbuf); + khc_csv_to_multi_string(wbuf, &cbbuf, strings[i].csv); + + printf("MS["); + print_ms(wbuf); + printf("] + [foo]=["); + + cbbuf = sizeof(wbuf); + code = khc_multi_string_append(wbuf, &cbbuf, L"foo"); + + if(code) { + printf(" returned %d\n", code); + return code; + } + + print_ms(wbuf); + printf("]\n"); + + printf(" byte length: %d\n", cbbuf); + } + return code; +} + +int ms_delete_test(void) +{ + int code = 0; + wchar_t wbuf[512]; + int i; + size_t cbs; + + printf("khc_multi_string_delete() test:\n"); + for(i=0; i<n_strings; i++) { + cbs = sizeof(wbuf); + khc_csv_to_multi_string(wbuf, &cbs, strings[i].csv); + + printf("MS["); + print_ms(wbuf); + printf("] - [b]=["); + + printf("cs:"); + code = khc_multi_string_delete(wbuf, L"b", KHC_CASE_SENSITIVE); + if(code) { + printf("ci:"); + code = khc_multi_string_delete(wbuf, L"b", 0); + } + if(code) { + printf("pcs:"); + code = khc_multi_string_delete(wbuf, L"b", KHC_CASE_SENSITIVE | KHC_PREFIX); + } + if(code) { + printf("pci:"); + code = khc_multi_string_delete(wbuf, L"b", KHC_PREFIX); + } + + if(!code) + print_ms(wbuf); + else + printf(" returned %d\n", code); + + printf("]\n"); + } + + return code; +} + +int main(int argc, char ** argv) { + + if(ms_to_csv_test()) + return 1; + + if(csv_to_ms_test()) + return 1; + + if(ms_append_test()) + return 1; + + if(ms_delete_test()) + return 1; + + return 0; +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/Makefile b/krb5-1-6/src/windows/identity/kcreddb/Makefile new file mode 100644 index 000000000..abf5efa0a --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=kcreddb +!include <../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\kcreddb.h + +OBJFILES= \ + $(OBJ)\buf.obj \ + $(OBJ)\attrib.obj \ + $(OBJ)\credential.obj \ + $(OBJ)\credset.obj \ + $(OBJ)\credtype.obj \ + $(OBJ)\identity.obj \ + $(OBJ)\init.obj \ + $(OBJ)\kcreddbmain.obj \ + $(OBJ)\type.obj \ + $(OBJ)\kcdbconfig.obj + +$(OBJ)\kcdbconfig.c: kcdbconfig.csv $(CONFDIR)\csvschema.cfg + $(CCSV) $** $@ + +$(OBJ)\kcredres.res: lang\en_us\kcredres.rc + $(RC2RES) + +all: mkdirs $(INCFILES) $(OBJ)\kcredres.res $(OBJFILES) + +clean:: + if exist ..\obj $(RM) $(INCFILES) diff --git a/krb5-1-6/src/windows/identity/kcreddb/attrib.c b/krb5-1-6/src/windows/identity/kcreddb/attrib.c new file mode 100644 index 000000000..983e3cc98 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/attrib.c @@ -0,0 +1,878 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> +#include<assert.h> + +CRITICAL_SECTION cs_attrib; +hashtable * kcdb_attrib_namemap = NULL; +kcdb_attrib_i ** kcdb_attrib_tbl = NULL; +kcdb_attrib_i ** kcdb_property_tbl = NULL; +kcdb_attrib_i * kcdb_attribs = NULL; + +void +kcdb_attrib_add_ref_func(const void * key, void * va) +{ + kcdb_attrib_hold((kcdb_attrib_i *) va); +} + +void +kcdb_attrib_del_ref_func(const void * key, void * va) +{ + kcdb_attrib_release((kcdb_attrib_i *) va); +} + +void +kcdb_attrib_msg_completion(kmq_message * m) +{ + if(m && m->vparam) { + kcdb_attrib_release((kcdb_attrib_i *) m->vparam); + } +} + +khm_int32 +kcdb_attrib_hold(kcdb_attrib_i * ai) +{ + if(!ai) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_attrib); + ai->refcount++; + LeaveCriticalSection(&cs_attrib); + return KHM_ERROR_SUCCESS; +} + +khm_int32 +kcdb_attrib_release(kcdb_attrib_i * ai) +{ + if(!ai) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_attrib); + ai->refcount--; + LeaveCriticalSection(&cs_attrib); + return KHM_ERROR_SUCCESS; +} + +void +kcdb_attrib_post_message(khm_int32 op, kcdb_attrib_i * ai) +{ + kcdb_attrib_hold(ai); + kmq_post_message(KMSG_KCDB, KMSG_KCDB_ATTRIB, op, (void *) ai); +} + +khm_int32 KHMAPI +kcdb_attr_sys_cb(khm_handle vcred, + khm_int32 attr, + void * buf, + khm_size * pcb_buf) +{ + kcdb_cred * c; + + c = (kcdb_cred *) vcred; + + switch(attr) { + case KCDB_ATTR_NAME: + return kcdb_cred_get_name(vcred, buf, pcb_buf); + + case KCDB_ATTR_ID: + if(buf && *pcb_buf >= sizeof(khm_ui_8)) { + *pcb_buf = sizeof(khm_int64); + *((khm_ui_8 *) buf) = (khm_ui_8) c->identity; + return KHM_ERROR_SUCCESS; + } else { + *pcb_buf = sizeof(khm_ui_8); + return KHM_ERROR_TOO_LONG; + } + + case KCDB_ATTR_ID_NAME: + return kcdb_identity_get_name((khm_handle) c->identity, + (wchar_t *) buf, pcb_buf); + + case KCDB_ATTR_TYPE: + if(buf && *pcb_buf >= sizeof(khm_int32)) { + *pcb_buf = sizeof(khm_int32); + *((khm_int32 *) buf) = c->type; + return KHM_ERROR_SUCCESS; + } else { + *pcb_buf = sizeof(khm_int32); + return KHM_ERROR_TOO_LONG; + } + + case KCDB_ATTR_TYPE_NAME: + return kcdb_credtype_describe(c->type, buf, + pcb_buf, KCDB_TS_SHORT); + + case KCDB_ATTR_TIMELEFT: + { + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!buf || *pcb_buf < sizeof(FILETIME)) { + *pcb_buf = sizeof(FILETIME); + rv = KHM_ERROR_TOO_LONG; + } else if(!kcdb_cred_buf_exist(c,KCDB_ATTR_EXPIRE)) { + *pcb_buf = sizeof(FILETIME); + /* setting the timeleft to _I64_MAX has the + interpretation that this credential does not + expire, which is the default behavior if the + expiration time is not known */ + *((FILETIME *) buf) = IntToFt(_I64_MAX); + } else { + FILETIME ftc; + khm_int64 iftc; + + GetSystemTimeAsFileTime(&ftc); + iftc = FtToInt(&ftc); + + *((FILETIME *) buf) = + IntToFt(FtToInt((FILETIME *) + kcdb_cred_buf_get(c,KCDB_ATTR_EXPIRE)) + - iftc); + *pcb_buf = sizeof(FILETIME); + } + + return rv; + } + + case KCDB_ATTR_RENEW_TIMELEFT: + { + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!buf || *pcb_buf < sizeof(FILETIME)) { + *pcb_buf = sizeof(FILETIME); + rv = KHM_ERROR_TOO_LONG; + } else if(!kcdb_cred_buf_exist(c,KCDB_ATTR_RENEW_EXPIRE)) { + *pcb_buf = sizeof(FILETIME); + /* setting the timeleft to _I64_MAX has the + interpretation that this credential does not + expire, which is the default behavior if the + expiration time is not known */ + *((FILETIME *) buf) = IntToFt(_I64_MAX); + } else { + FILETIME ftc; + khm_int64 i_re; + khm_int64 i_ct; + + GetSystemTimeAsFileTime(&ftc); + + i_re = FtToInt(((FILETIME *) + kcdb_cred_buf_get(c, KCDB_ATTR_RENEW_EXPIRE))); + i_ct = FtToInt(&ftc); + + if (i_re > i_ct) + *((FILETIME *) buf) = + IntToFt(i_re - i_ct); + else + *((FILETIME *) buf) = + IntToFt(0); + + *pcb_buf = sizeof(FILETIME); + } + + return rv; + } + + case KCDB_ATTR_FLAGS: + if(buf && *pcb_buf >= sizeof(khm_int32)) { + *pcb_buf = sizeof(khm_int32); + *((khm_int32 *) buf) = c->flags; + return KHM_ERROR_SUCCESS; + } else { + *pcb_buf = sizeof(khm_int32); + return KHM_ERROR_TOO_LONG; + } + + default: + return KHM_ERROR_NOT_FOUND; + } +} + +void +kcdb_attrib_init(void) +{ + kcdb_attrib attrib; + wchar_t sbuf[256]; + + InitializeCriticalSection(&cs_attrib); + kcdb_attrib_namemap = + hash_new_hashtable(KCDB_ATTRIB_HASH_SIZE, + hash_string, + hash_string_comp, + kcdb_attrib_add_ref_func, + kcdb_attrib_del_ref_func); + + kcdb_attrib_tbl = + PMALLOC(sizeof(kcdb_attrib_i *) * (KCDB_ATTR_MAX_ID + 1)); + assert(kcdb_attrib_tbl != NULL); + ZeroMemory(kcdb_attrib_tbl, + sizeof(kcdb_attrib_i *) * (KCDB_ATTR_MAX_ID + 1)); + + kcdb_property_tbl = + PMALLOC(sizeof(kcdb_attrib_i *) * KCDB_ATTR_MAX_PROPS); + assert(kcdb_property_tbl != NULL); + ZeroMemory(kcdb_property_tbl, + sizeof(kcdb_attrib_i *) * KCDB_ATTR_MAX_PROPS); + + kcdb_attribs = NULL; + + /* register standard attributes */ + + /* Name */ + attrib.id = KCDB_ATTR_NAME; + attrib.name = KCDB_ATTRNAME_NAME; + attrib.type = KCDB_TYPE_STRING; + LoadString(hinst_kcreddb, IDS_NAME, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = + KCDB_ATTR_FLAG_REQUIRED | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(wchar_t); + attrib.compute_max_cbsize = KCDB_MAXCB_NAME; + + kcdb_attrib_register(&attrib, NULL); + + /* ID */ + attrib.id = KCDB_ATTR_ID; + attrib.name = KCDB_ATTRNAME_ID; + attrib.type = KCDB_TYPE_INT64; + LoadString(hinst_kcreddb, IDS_IDENTITY, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = + KCDB_ATTR_FLAG_REQUIRED | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_SYSTEM | + KCDB_ATTR_FLAG_HIDDEN; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(khm_int32); + attrib.compute_max_cbsize = sizeof(khm_int32); + + kcdb_attrib_register(&attrib, NULL); + + /* ID Name */ + attrib.id = KCDB_ATTR_ID_NAME; + attrib.alt_id = KCDB_ATTR_ID; + attrib.name = KCDB_ATTRNAME_ID_NAME; + attrib.type = KCDB_TYPE_STRING; + LoadString(hinst_kcreddb, IDS_IDENTITY, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = + KCDB_ATTR_FLAG_REQUIRED | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_ALTVIEW | + KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(wchar_t); + attrib.compute_max_cbsize = KCDB_IDENT_MAXCB_NAME; + + kcdb_attrib_register(&attrib, NULL); + + /* Type */ + attrib.id = KCDB_ATTR_TYPE; + attrib.name = KCDB_ATTRNAME_TYPE; + attrib.type = KCDB_TYPE_INT32; + LoadString(hinst_kcreddb, IDS_TYPE, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = + KCDB_ATTR_FLAG_REQUIRED | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_SYSTEM | + KCDB_ATTR_FLAG_HIDDEN; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(khm_int32); + attrib.compute_max_cbsize = sizeof(khm_int32); + + kcdb_attrib_register(&attrib, NULL); + + /* Type Name */ + attrib.id = KCDB_ATTR_TYPE_NAME; + attrib.alt_id = KCDB_ATTR_TYPE; + attrib.name = KCDB_ATTRNAME_TYPE_NAME; + attrib.type = KCDB_TYPE_STRING; + LoadString(hinst_kcreddb, IDS_TYPE, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = + KCDB_ATTR_FLAG_REQUIRED | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_ALTVIEW | + KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(wchar_t); + attrib.compute_max_cbsize = KCDB_MAXCB_NAME; + + kcdb_attrib_register(&attrib, NULL); + + /* Parent Name */ + attrib.id = KCDB_ATTR_PARENT_NAME; + attrib.name = KCDB_ATTRNAME_PARENT_NAME; + attrib.type = KCDB_TYPE_STRING; + LoadString(hinst_kcreddb, IDS_PARENT, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM | KCDB_ATTR_FLAG_HIDDEN; + attrib.compute_cb = NULL; + attrib.compute_min_cbsize = 0; + attrib.compute_max_cbsize = 0; + + kcdb_attrib_register(&attrib, NULL); + + /* Issed On */ + attrib.id = KCDB_ATTR_ISSUE; + attrib.name = KCDB_ATTRNAME_ISSUE; + attrib.type = KCDB_TYPE_DATE; + LoadString(hinst_kcreddb, IDS_ISSUED, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = NULL; + attrib.compute_min_cbsize = 0; + attrib.compute_max_cbsize = 0; + + kcdb_attrib_register(&attrib, NULL); + + /* Expires On */ + attrib.id = KCDB_ATTR_EXPIRE; + attrib.name = KCDB_ATTRNAME_EXPIRE; + attrib.type = KCDB_TYPE_DATE; + LoadString(hinst_kcreddb, IDS_EXPIRES, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = NULL; + attrib.compute_min_cbsize = 0; + attrib.compute_max_cbsize = 0; + + kcdb_attrib_register(&attrib, NULL); + + /* Renewable Time Expires On */ + attrib.id = KCDB_ATTR_RENEW_EXPIRE; + attrib.name = KCDB_ATTRNAME_RENEW_EXPIRE; + attrib.type = KCDB_TYPE_DATE; + LoadString(hinst_kcreddb, IDS_RENEW_EXPIRES, + sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = NULL; + attrib.compute_min_cbsize = 0; + attrib.compute_max_cbsize = 0; + + kcdb_attrib_register(&attrib, NULL); + + /* Time Left */ + attrib.id = KCDB_ATTR_TIMELEFT; + attrib.alt_id = KCDB_ATTR_EXPIRE; + attrib.name = KCDB_ATTRNAME_TIMELEFT; + attrib.type = KCDB_TYPE_INTERVAL; + LoadString(hinst_kcreddb, IDS_TIMELEFT, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_ALTVIEW | + KCDB_ATTR_FLAG_VOLATILE; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(FILETIME); + attrib.compute_max_cbsize = sizeof(FILETIME); + + kcdb_attrib_register(&attrib, NULL); + + /* Renewable Time Left */ + attrib.id = KCDB_ATTR_RENEW_TIMELEFT; + attrib.alt_id = KCDB_ATTR_RENEW_EXPIRE; + attrib.name = KCDB_ATTRNAME_RENEW_TIMELEFT; + attrib.type = KCDB_TYPE_INTERVAL; + LoadString(hinst_kcreddb, + IDS_RENEW_TIMELEFT, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_ALTVIEW | + KCDB_ATTR_FLAG_VOLATILE; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(FILETIME); + attrib.compute_max_cbsize = sizeof(FILETIME); + + kcdb_attrib_register(&attrib, NULL); + + /* Location of Credential */ + attrib.id = KCDB_ATTR_LOCATION; + attrib.name = KCDB_ATTRNAME_LOCATION; + attrib.type = KCDB_TYPE_STRING; + LoadString(hinst_kcreddb, IDS_LOCATION, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = NULL; + attrib.compute_min_cbsize = 0; + attrib.compute_max_cbsize = 0; + + kcdb_attrib_register(&attrib, NULL); + + /* Lifetime */ + attrib.id = KCDB_ATTR_LIFETIME; + attrib.name = KCDB_ATTRNAME_LIFETIME; + attrib.type = KCDB_TYPE_INTERVAL; + LoadString(hinst_kcreddb, IDS_LIFETIME, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = NULL; + attrib.compute_min_cbsize = 0; + attrib.compute_max_cbsize = 0; + + kcdb_attrib_register(&attrib, NULL); + + /* Renewable Lifetime */ + attrib.id = KCDB_ATTR_RENEW_LIFETIME; + attrib.name = KCDB_ATTRNAME_RENEW_LIFETIME; + attrib.type = KCDB_TYPE_INTERVAL; + LoadString(hinst_kcreddb, + IDS_RENEW_LIFETIME, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = KCDB_ATTR_FLAG_SYSTEM; + attrib.compute_cb = NULL; + attrib.compute_min_cbsize = 0; + attrib.compute_max_cbsize = 0; + + kcdb_attrib_register(&attrib, NULL); + + /* Flags */ + attrib.id = KCDB_ATTR_FLAGS; + attrib.name = KCDB_ATTRNAME_FLAGS; + attrib.type = KCDB_TYPE_INT32; + LoadString(hinst_kcreddb, IDS_FLAGS, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + attrib.flags = + KCDB_ATTR_FLAG_REQUIRED | + KCDB_ATTR_FLAG_COMPUTED | + KCDB_ATTR_FLAG_SYSTEM | + KCDB_ATTR_FLAG_HIDDEN; + attrib.compute_cb = kcdb_attr_sys_cb; + attrib.compute_min_cbsize = sizeof(khm_int32); + attrib.compute_max_cbsize = sizeof(khm_int32); + + kcdb_attrib_register(&attrib, NULL); +} + +void +kcdb_attrib_exit(void) +{ + DeleteCriticalSection(&cs_attrib); + + if(kcdb_attrib_tbl) + PFREE(kcdb_attrib_tbl); + + if(kcdb_property_tbl) + PFREE(kcdb_property_tbl); +} + +KHMEXP khm_int32 KHMAPI +kcdb_attrib_get_id(const wchar_t *name, khm_int32 * id) +{ + kcdb_attrib_i * ai; + + if(!name) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_attrib); + ai = hash_lookup(kcdb_attrib_namemap, (void *) name); + LeaveCriticalSection(&cs_attrib); + + if(ai) { + *id = ai->attr.id; + return KHM_ERROR_SUCCESS; + } else { + *id = KCDB_ATTR_INVALID; + return KHM_ERROR_NOT_FOUND; + } +} + +KHMEXP khm_int32 KHMAPI +kcdb_attrib_register(const kcdb_attrib * attrib, khm_int32 * new_id) +{ + kcdb_attrib_i * ai; + size_t cb_name; + size_t cb_short_desc; + size_t cb_long_desc; + khm_int32 attr_id; + khm_boolean prop = FALSE; + + if(!attrib || + KHM_FAILED(kcdb_type_get_info(attrib->type, NULL)) || + !attrib->name) + return KHM_ERROR_INVALID_PARAM; + + if(FAILED(StringCbLength(attrib->name, KCDB_MAXCB_NAME, &cb_name))) + return KHM_ERROR_TOO_LONG; + cb_name += sizeof(wchar_t); + + if(attrib->short_desc) { + if(FAILED(StringCbLength(attrib->short_desc, KCDB_MAXCB_SHORT_DESC, &cb_short_desc))) + return KHM_ERROR_TOO_LONG; + cb_short_desc += sizeof(wchar_t); + } else + cb_short_desc = 0; + + if(attrib->long_desc) { + if(FAILED(StringCbLength(attrib->long_desc, KCDB_MAXCB_LONG_DESC, &cb_long_desc))) + return KHM_ERROR_TOO_LONG; + cb_long_desc += sizeof(wchar_t); + } else + cb_long_desc = 0; + + if((attrib->flags & KCDB_ATTR_FLAG_COMPUTED) && + (!attrib->compute_cb || + attrib->compute_min_cbsize <= 0 || + attrib->compute_max_cbsize < attrib->compute_min_cbsize)) + return KHM_ERROR_INVALID_PARAM; + + if ((attrib->flags & KCDB_ATTR_FLAG_ALTVIEW) && + KHM_FAILED(kcdb_attrib_get_info(attrib->alt_id, + NULL))) + return KHM_ERROR_INVALID_PARAM; + + prop = !!(attrib->flags & KCDB_ATTR_FLAG_PROPERTY); + + EnterCriticalSection(&cs_attrib); + + if(!prop && + (attrib->id < 0 || attrib->id > KCDB_ATTR_MAX_ID)) + { + if(KHM_FAILED(kcdb_attrib_next_free_id(&attr_id))) { + LeaveCriticalSection(&cs_attrib); + return KHM_ERROR_NO_RESOURCES; + } + } else if (prop && + (attrib->id < KCDB_ATTR_MIN_PROP_ID || + attrib->id > KCDB_ATTR_MAX_PROP_ID)) { + + if(KHM_FAILED(kcdb_attrib_next_free_prop_id(&attr_id))) { + LeaveCriticalSection(&cs_attrib); + return KHM_ERROR_NO_RESOURCES; + } + + } else { + attr_id = attrib->id; + } + +#ifdef DEBUG + assert(!prop || (attr_id >= KCDB_ATTR_MIN_PROP_ID && attr_id <= KCDB_ATTR_MAX_PROP_ID)); + assert(prop || (attr_id >= 0 && attr_id <= KCDB_ATTR_MAX_ID)); +#endif + + if((!prop && kcdb_attrib_tbl[attr_id]) || + (prop && kcdb_property_tbl[attr_id - KCDB_ATTR_MIN_PROP_ID])) { + + LeaveCriticalSection(&cs_attrib); + return KHM_ERROR_DUPLICATE; + + } + + ai = PMALLOC(sizeof(kcdb_attrib_i)); + ZeroMemory(ai, sizeof(kcdb_attrib_i)); + + ai->attr.type = attrib->type; + ai->attr.id = attr_id; + ai->attr.alt_id = attrib->alt_id; + ai->attr.flags = attrib->flags; + ai->attr.compute_cb = attrib->compute_cb; + ai->attr.compute_max_cbsize = attrib->compute_max_cbsize; + ai->attr.compute_min_cbsize = attrib->compute_min_cbsize; + ai->attr.name = PMALLOC(cb_name); + StringCbCopy(ai->attr.name, cb_name, attrib->name); + if(cb_short_desc) { + ai->attr.short_desc = PMALLOC(cb_short_desc); + StringCbCopy(ai->attr.short_desc, cb_short_desc, attrib->short_desc); + } + if(cb_long_desc) { + ai->attr.long_desc = PMALLOC(cb_long_desc); + StringCbCopy(ai->attr.long_desc, cb_long_desc, attrib->long_desc); + } + + LINIT(ai); + + if(!prop) + kcdb_attrib_tbl[attr_id] = ai; + else + kcdb_property_tbl[attr_id - KCDB_ATTR_MIN_PROP_ID] = ai; + + LPUSH(&kcdb_attribs, ai); + + hash_add(kcdb_attrib_namemap, (void *) ai->attr.name, ai); + + LeaveCriticalSection(&cs_attrib); + + kcdb_attrib_post_message(KCDB_OP_INSERT, ai); + + if(new_id) + *new_id = attr_id; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_attrib_get_info( + khm_int32 id, + kcdb_attrib ** attrib) +{ + kcdb_attrib_i * ai; + khm_boolean prop; + + if(id >= 0 && id <= KCDB_ATTR_MAX_ID) + prop = FALSE; + else if(id >= KCDB_ATTR_MIN_PROP_ID && id <= KCDB_ATTR_MAX_PROP_ID) + prop = TRUE; + else + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_attrib); + if(prop) + ai = kcdb_property_tbl[id - KCDB_ATTR_MIN_PROP_ID]; + else + ai = kcdb_attrib_tbl[id]; + LeaveCriticalSection(&cs_attrib); + + if(ai) { + if(attrib) { + *attrib = &(ai->attr); + kcdb_attrib_hold(ai); + } + return KHM_ERROR_SUCCESS; + } else { + if(attrib) + *attrib = NULL; + return KHM_ERROR_NOT_FOUND; + } +} + +KHMEXP khm_int32 KHMAPI kcdb_attrib_release_info(kcdb_attrib * attrib) +{ + if(attrib) + kcdb_attrib_release((kcdb_attrib_i *) attrib); + return KHM_ERROR_SUCCESS; +} + + +KHMEXP khm_int32 KHMAPI kcdb_attrib_unregister(khm_int32 id) +{ + /*TODO: implement this */ + return KHM_ERROR_NOT_IMPLEMENTED; +} + +KHMEXP khm_int32 KHMAPI kcdb_attrib_describe( + khm_int32 id, + wchar_t * buffer, + khm_size * cbsize, + khm_int32 flags) +{ + kcdb_attrib_i * ai; + size_t cb_size = 0; + khm_boolean prop = FALSE; + + if(!cbsize) + return KHM_ERROR_INVALID_PARAM; + + if(id >= 0 && id <= KCDB_ATTR_MAX_ID) + prop = FALSE; + else if(id >= KCDB_ATTR_MIN_PROP_ID && id <= KCDB_ATTR_MAX_PROP_ID) + prop = TRUE; + else + return KHM_ERROR_INVALID_PARAM; + + if(prop) + ai = kcdb_property_tbl[id - KCDB_ATTR_MIN_PROP_ID]; + else + ai = kcdb_attrib_tbl[id]; + + if(!ai) + return KHM_ERROR_NOT_FOUND; + + if((flags & KCDB_TS_SHORT) && + ai->attr.short_desc) + { + if(FAILED(StringCbLength(ai->attr.short_desc, KCDB_MAXCB_SHORT_DESC, &cb_size))) + return KHM_ERROR_UNKNOWN; + cb_size += sizeof(wchar_t); + + if(!buffer || *cbsize < cb_size) { + *cbsize = cb_size; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cbsize, ai->attr.short_desc); + + *cbsize = cb_size; + + return KHM_ERROR_SUCCESS; + } else { + if(FAILED(StringCbLength(ai->attr.long_desc, KCDB_MAXCB_LONG_DESC, &cb_size))) + return KHM_ERROR_UNKNOWN; + cb_size += sizeof(wchar_t); + + if(!buffer || *cbsize < cb_size) { + *cbsize = cb_size; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cbsize, ai->attr.long_desc); + + *cbsize = cb_size; + + return KHM_ERROR_SUCCESS; + } +} + +khm_int32 kcdb_attrib_next_free_prop_id(khm_int32 * id) +{ + int i; + + if(!id) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_attrib); + for(i=0;i < KCDB_ATTR_MAX_PROPS; i++) { + if(!kcdb_property_tbl[i]) + break; + } + LeaveCriticalSection(&cs_attrib); + + if(i < KCDB_ATTR_MAX_PROPS) { + *id = i + KCDB_ATTR_MIN_PROP_ID; + return KHM_ERROR_SUCCESS; + } else { + *id = KCDB_ATTR_INVALID; + return KHM_ERROR_NO_RESOURCES; + } +} + +khm_int32 kcdb_attrib_next_free_id(khm_int32 * id) +{ + int i; + + if(!id) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_attrib); + for(i=0;i<= KCDB_ATTR_MAX_ID; i++) { + if(!kcdb_attrib_tbl[i]) + break; + } + LeaveCriticalSection(&cs_attrib); + + if(i <= KCDB_ATTR_MAX_ID) { + *id = i; + return KHM_ERROR_SUCCESS; + } else { + *id = KCDB_ATTR_INVALID; + return KHM_ERROR_NO_RESOURCES; + } +} + +KHMEXP khm_int32 KHMAPI kcdb_attrib_get_count( + khm_int32 and_flags, + khm_int32 eq_flags, + khm_size * pcount) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_size count = 0; + int i; + + if(pcount == NULL) + return KHM_ERROR_INVALID_PARAM; + + eq_flags &= and_flags; + + EnterCriticalSection(&cs_attrib); + for(i = 0; i <= KCDB_ATTR_MAX_ID; i++) { + if(kcdb_attrib_tbl[i] && + (kcdb_attrib_tbl[i]->attr.flags & and_flags) == eq_flags) + count++; + } + + for(i = 0; i < KCDB_ATTR_MAX_PROPS; i++) { + if(kcdb_property_tbl[i] && + (kcdb_property_tbl[i]->attr.flags & and_flags) == eq_flags) + count++; + } + LeaveCriticalSection(&cs_attrib); + + *pcount = count; + + return rv; +} + +KHMEXP khm_int32 KHMAPI kcdb_attrib_get_ids( + khm_int32 and_flags, + khm_int32 eq_flags, + khm_int32 * plist, + khm_size * pcsize) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_size count = 0; + int i; + + if(plist == NULL || pcsize == NULL) + return KHM_ERROR_INVALID_PARAM; + + eq_flags &= and_flags; + + EnterCriticalSection(&cs_attrib); + for(i = 0; i <= KCDB_ATTR_MAX_ID; i++) { + if(kcdb_attrib_tbl[i] && + (kcdb_attrib_tbl[i]->attr.flags & and_flags) == eq_flags) { + if(count >= *pcsize) { + rv = KHM_ERROR_TOO_LONG; + count++; + } else + plist[count++] = i; + } + } + + for(i = 0; i < KCDB_ATTR_MAX_PROPS; i++) { + if(kcdb_property_tbl[i] && + (kcdb_property_tbl[i]->attr.flags & and_flags) == eq_flags) { + if(count >= *pcsize) { + rv = KHM_ERROR_TOO_LONG; + count++; + } else + plist[count++] = i + KCDB_ATTR_MIN_PROP_ID; + } + } + LeaveCriticalSection(&cs_attrib); + + *pcsize = count; + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/attrib.h b/krb5-1-6/src/windows/identity/kcreddb/attrib.h new file mode 100644 index 000000000..2f0cc0f8e --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/attrib.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCDB_ATTRIB_H +#define __KHIMAIRA_KCDB_ATTRIB_H + +/* Attributes */ + +typedef struct kcdb_attrib_i_t { + kcdb_attrib attr; + + khm_int32 refcount; + + struct kcdb_attrib_i_t * next; + struct kcdb_attrib_i_t * prev; +} kcdb_attrib_i; + +#define KCDB_ATTRIB_HASH_SIZE 31 + +void kcdb_attrib_init(void); +void kcdb_attrib_exit(void); +void kcdb_attrib_add_ref_func(const void * key, void * va); +void kcdb_attrib_del_ref_func(const void * key, void * va); +void kcdb_attrib_msg_completion(kmq_message * m); +khm_int32 kcdb_attrib_next_free_prop_id(khm_int32 * id); +khm_int32 kcdb_attrib_next_free_id(khm_int32 * id); +khm_int32 kcdb_attrib_hold(kcdb_attrib_i * ai); +khm_int32 kcdb_attrib_release(kcdb_attrib_i * ai); +void kcdb_attrib_post_message(khm_int32 op, kcdb_attrib_i * ai); +khm_int32 KHMAPI kcdb_attr_sys_cb(khm_handle cred, khm_int32 attr, void * buf, khm_size * pcb_buf); + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/buf.c b/krb5-1-6/src/windows/identity/kcreddb/buf.c new file mode 100644 index 000000000..521baeb97 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/buf.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> +#include<assert.h> + +void kcdb_buf_new(kcdb_buf * buf, khm_size n_fields) +{ + buf->buffer = PMALLOC(KCDB_BUF_CBBUF_INITIAL); + buf->cb_buffer = KCDB_BUF_CBBUF_INITIAL; + buf->cb_used = 0; + + if(n_fields == KCDB_BUF_DEFAULT) + n_fields = KCDB_BUF_FIELDS_INITIAL; + + assert(n_fields < KCDB_BUF_MAX_SLOTS); + + buf->n_fields = n_fields; + buf->nc_fields = UBOUNDSS(n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH); + buf->fields = PMALLOC(sizeof(buf->fields[0]) * buf->n_fields); + ZeroMemory(buf->fields, sizeof(buf->fields[0]) * buf->n_fields); +} + +void kcdb_buf_delete(kcdb_buf * buf) +{ + buf->cb_buffer = 0; + buf->cb_used = 0; + if(buf->buffer) + PFREE(buf->buffer); + buf->buffer = NULL; + + buf->n_fields = 0; + buf->nc_fields = 0; + if(buf->fields) + PFREE(buf->fields); + buf->fields = NULL; +} + +static void kcdb_buf_assert_size(kcdb_buf * buf, khm_size cbsize) +{ + khm_size new_size; + void * new_buf; + + /* should be less than or equal to the max signed 32 bit int */ + assert(cbsize <= KHM_INT32_MAX); + if(cbsize <= buf->cb_buffer) + return; + + new_size = UBOUNDSS(cbsize, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH); + + assert(new_size > buf->cb_buffer && new_size > 0); + + new_buf = PMALLOC(new_size); + assert(new_buf != NULL); + + memcpy(new_buf, buf->buffer, buf->cb_used); + PFREE(buf->buffer); + buf->buffer = new_buf; +} + +void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize) +{ + khm_size cbnew; + khm_ssize cbdelta; + khm_size cbold; + kcdb_buf_field * f; + + cbnew = UBOUND32(cbsize); + + assert(slot <= KCDB_BUF_APPEND); + + if(slot == KCDB_BUF_APPEND) { + slot = kcdb_buf_slot_by_id(buf, id); + if(slot == KCDB_BUF_INVALID_SLOT) + slot = buf->n_fields; + } + + assert(slot < KCDB_BUF_MAX_SLOTS); + + if((slot + 1) > buf->nc_fields) { + kcdb_buf_field * nf; + khm_size ns; + + ns = UBOUNDSS((slot + 1), KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH); + + nf = PMALLOC(sizeof(buf->fields[0]) * ns); + memcpy(nf, buf->fields, sizeof(buf->fields[0]) * buf->n_fields); + + if(ns > buf->n_fields) + memset(&(nf[buf->n_fields]), 0, sizeof(buf->fields[0]) * (ns - buf->n_fields)); + + PFREE(buf->fields); + buf->fields = nf; + buf->nc_fields = ns; + } + + if((slot + 1) > buf->n_fields) + buf->n_fields = slot + 1; + + f = &(buf->fields[slot]); + + if(f->flags & KCDB_CREDF_FLAG_ALLOCD) { + /* there's already an allocation. we have to resize it to + accomodate the new size */ + cbold = UBOUND32(f->cbsize); + /* demote before substraction */ + cbdelta = ((khm_ssize) cbnew) - (khm_ssize) cbold; + + if(cbnew > cbold) { + kcdb_buf_assert_size(buf, buf->cb_used + cbdelta); + } + + if(buf->cb_used > f->offset + cbold) { + khm_size i; + + memmove( + ((BYTE *) buf->buffer) + (f->offset + cbnew), + ((BYTE *) buf->buffer) + (f->offset + cbold), + buf->cb_used - (f->offset + cbold)); + + for(i=0; i < (int) buf->n_fields; i++) { + if(i != slot && + (buf->fields[i].flags & KCDB_CREDF_FLAG_ALLOCD) && + buf->fields[i].offset > f->offset) + { + buf->fields[i].offset = + (khm_ui_4)(((khm_ssize) buf->fields[i].offset) + cbdelta); + } + } + } + + /* demote integer before adding signed quantity */ + buf->cb_used = (khm_size)(((khm_ssize) buf->cb_used) + cbdelta); + + f->cbsize = (khm_ui_4) cbsize; + + } else { + kcdb_buf_assert_size(buf, buf->cb_used + cbnew); + f->offset = (khm_ui_4) buf->cb_used; + f->cbsize = (khm_ui_4) cbsize; + buf->cb_used += cbnew; + } + + if(cbsize == 0) { + f->flags &= ~KCDB_CREDF_FLAG_ALLOCD; + f->flags &= ~KCDB_CREDF_FLAG_DATA; + f->id = KCDB_BUFF_ID_INVALID; + } else { + f->flags |= KCDB_CREDF_FLAG_ALLOCD; + f->id = id; + } +} + +void kcdb_buf_dup(kcdb_buf * dest, const kcdb_buf * src) +{ + khm_size cb_buf; + khm_size nc_fields; + + cb_buf = UBOUNDSS(src->cb_used, KCDB_BUF_CBBUF_INITIAL, KCDB_BUF_CBBUF_GROWTH); +#if 0 + /* replaced by UBOUNDSS() above */ + (src->cb_used <= kcdb_cred_initial_size)? kcdb_cred_initial_size: + kcdb_cred_initial_size + + (((src->cb_used - (kcdb_cred_initial_size + 1)) / kcdb_cred_growth_factor + 1) * kcdb_cred_growth_factor); +#endif + + kcdb_buf_delete(dest); + + dest->cb_buffer = cb_buf; + dest->cb_used = src->cb_used; + dest->buffer = PMALLOC(cb_buf); + memcpy(dest->buffer, src->buffer, src->cb_used); + + nc_fields = UBOUNDSS(src->n_fields, KCDB_BUF_FIELDS_INITIAL, KCDB_BUF_FIELDS_GROWTH); + dest->nc_fields = nc_fields; + dest->n_fields = src->n_fields; + dest->fields = PMALLOC(nc_fields * sizeof(dest->fields[0])); + memcpy(dest->fields, src->fields, src->n_fields * sizeof(dest->fields[0])); + if(dest->n_fields < dest->nc_fields) + memset(&(dest->fields[dest->n_fields]), 0, (src->nc_fields - src->n_fields) * sizeof(dest->fields[0])); +} + +void kcdb_buf_set_value(kcdb_buf * buf, khm_size slot, khm_ui_2 id, void * src, khm_size cb_src) +{ + void * dest; + kcdb_buf_alloc(buf, slot, id, cb_src); + if(slot == KCDB_BUF_APPEND) { + slot = kcdb_buf_slot_by_id(buf, id); + if(slot == KCDB_BUF_INVALID_SLOT) { +#ifdef DEBUG + assert(FALSE); +#else + return; +#endif + } + } + if(kcdb_buf_exist(buf, slot)) { + dest = kcdb_buf_get(buf, slot); + memcpy(dest, src, cb_src); + + buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA; + } +} + +int kcdb_buf_exist(kcdb_buf * buf, khm_size slot) +{ + if(slot >= buf->n_fields) + return 0; + return (buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD); +} + +int kcdb_buf_val_exist(kcdb_buf * buf, khm_size slot) +{ + if(slot >= buf->n_fields) + return 0; + return (buf->fields[slot].flags & KCDB_CREDF_FLAG_DATA); +} + +void * kcdb_buf_get(kcdb_buf * buf, khm_size slot) +{ + if(slot >= buf->n_fields || + !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD)) + return NULL; + return (((BYTE *) buf->buffer) + buf->fields[slot].offset); +} + +khm_size kcdb_buf_size(kcdb_buf * buf, khm_size slot) +{ + if(slot >= buf->n_fields || + !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD)) + return 0; + return (buf->fields[slot].cbsize); +} + +void kcdb_buf_set_value_flag(kcdb_buf * buf, khm_size slot) +{ + if(slot >= buf->n_fields || + !(buf->fields[slot].flags & KCDB_CREDF_FLAG_ALLOCD)) + return; + + (buf->fields[slot].flags |= KCDB_CREDF_FLAG_DATA); +} + +khm_size kcdb_buf_slot_by_id(kcdb_buf * buf, khm_ui_2 id) +{ + int i; + + for(i=0; i < (int) buf->n_fields; i++) { + if(buf->fields[i].id == id) + break; + } + + if(i < (int) buf->n_fields) + return i; + else + return KCDB_BUF_INVALID_SLOT; +} + +/* API for accessing generic buffers */ + +KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr( + khm_handle record, + khm_int32 attr_id, + khm_int32 * attr_type, + void * buffer, + khm_size * pcb_buf) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_get_attr(record, attr_id, attr_type, buffer, pcb_buf); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_get_attr(record, attr_id, attr_type, buffer, pcb_buf); + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib( + khm_handle record, + const wchar_t * attr_name, + khm_int32 * attr_type, + void * buffer, + khm_size * pcb_buf) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_get_attrib(record, attr_name, attr_type, buffer, pcb_buf); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_get_attrib(record, attr_name, attr_type, buffer, pcb_buf); + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr_string( + khm_handle record, + khm_int32 attr_id, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_get_attr_string(record, attr_id, buffer, pcbbuf, flags); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_get_attr_string(record, attr_id, buffer, pcbbuf, flags); + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP khm_int32 KHMAPI kcdb_buf_get_attrib_string( + khm_handle record, + const wchar_t * attr_name, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_get_attrib_string(record, attr_name, buffer, pcbbuf, flags); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_get_attrib_string(record, attr_name, buffer, pcbbuf, flags); + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP khm_int32 KHMAPI kcdb_buf_set_attr( + khm_handle record, + khm_int32 attr_id, + void * buffer, + khm_size cbbuf) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_set_attr(record, attr_id, buffer, cbbuf); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_set_attr(record, attr_id, buffer, cbbuf); + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP khm_int32 KHMAPI kcdb_buf_set_attrib( + khm_handle record, + const wchar_t * attr_name, + void * buffer, + khm_size cbbuf) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_set_attrib(record, attr_name, buffer, cbbuf); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_set_attrib(record, attr_name, buffer, cbbuf); + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP khm_int32 KHMAPI kcdb_buf_hold(khm_handle record) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_hold(record); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_hold(record); + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP khm_int32 KHMAPI kcdb_buf_release(khm_handle record) +{ + if(kcdb_cred_is_active_cred(record)) + return kcdb_cred_release(record); + else if(kcdb_is_active_identity(record)) + return kcdb_identity_release(record); + else + return KHM_ERROR_INVALID_PARAM; +} + diff --git a/krb5-1-6/src/windows/identity/kcreddb/buf.h b/krb5-1-6/src/windows/identity/kcreddb/buf.h new file mode 100644 index 000000000..723253036 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/buf.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCDB_BUF_H +#define __KHIMAIRA_KCDB_BUF_H + +typedef struct tag_kcdb_buf_field { + khm_ui_2 id; + khm_ui_2 flags; + khm_ui_4 offset; + khm_ui_4 cbsize; +} kcdb_buf_field; + +#define KCDB_CREDF_FLAG_EMPTY 0 +#define KCDB_CREDF_FLAG_DATA 1 +#define KCDB_CREDF_FLAG_INLINE 2 +#define KCDB_CREDF_FLAG_ALLOCD 4 + +#define KCDB_BUFF_ID_INVALID 0xffff + +typedef struct tag_kcdb_buf { + void * buffer; + khm_size cb_buffer; + khm_size cb_used; + + kcdb_buf_field * fields; + khm_size n_fields; + khm_size nc_fields; +} kcdb_buf; + +#define KCDB_BUF_CBBUF_INITIAL 4096 +#define KCDB_BUF_CBBUF_GROWTH 4096 +#define KCDB_BUF_FIELDS_INITIAL 16 +#define KCDB_BUF_FIELDS_GROWTH 16 + +#define KCDB_BUF_APPEND 0x8000 + +#define KCDB_BUF_INVALID_SLOT 0xf0000000 +#define KCDB_BUF_DEFAULT 0xe0000000 + +#define KCDB_BUF_MAX_SLOTS 0x00004000 + +void kcdb_buf_new(kcdb_buf * buf, khm_size n_slots); +void kcdb_buf_delete(kcdb_buf * buf); +void kcdb_buf_alloc(kcdb_buf * buf, khm_size slot, khm_ui_2 id, khm_size cbsize); +void kcdb_buf_dup(kcdb_buf * dest, const kcdb_buf * src); +void kcdb_buf_set_value(kcdb_buf * buf, khm_size slot, khm_ui_2 id, void * src, khm_size cb_src); +int kcdb_buf_exist(kcdb_buf * buf, khm_size slot); +int kcdb_buf_val_exist(kcdb_buf * buf, khm_size slot); +void * kcdb_buf_get(kcdb_buf * buf, khm_size slot); +khm_size kcdb_buf_size(kcdb_buf * buf, khm_size slot); +void kcdb_buf_set_value_flag(kcdb_buf * buf, khm_size slot); +khm_size kcdb_buf_slot_by_id(kcdb_buf * buf, khm_ui_2 id); + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/credential.c b/krb5-1-6/src/windows/identity/kcreddb/credential.c new file mode 100644 index 000000000..c241943d0 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/credential.c @@ -0,0 +1,1092 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> +#include<assert.h> + +/* cs_creds protects the *collection* of credentials, while l_creds + protects the *contents* of individual credentials. */ +CRITICAL_SECTION cs_creds; +kcdb_cred * kcdb_creds = NULL; + +/* a read lock must be obtained when querying any existing credential. + a write lock must be obtained when modifying any existing credential. + */ +RWLOCK l_creds; + +/* serial number */ +khm_ui_8 kcdb_cred_id = 0; + +void kcdb_cred_init(void) +{ + InitializeCriticalSection(&cs_creds); + InitializeRwLock(&l_creds); + kcdb_cred_id = 0; +} + +void kcdb_cred_exit(void) +{ + /*TODO: Free the credentials */ + DeleteCriticalSection(&cs_creds); + DeleteRwLock(&l_creds); +} + +/*! \internal + + can be called by kcdb_cred_dup with a write lock on l_creds and in other + places with a read lock on l_creds. New credentials must be creatable while + holding either lock. */ +KHMEXP khm_int32 KHMAPI +kcdb_cred_create(const wchar_t * name, + khm_handle identity, + khm_int32 cred_type, + khm_handle * result) +{ + kcdb_cred * cred; + size_t cb_name; + + if(!name || !result || + FAILED(StringCbLength(name, KCDB_CRED_MAXCB_NAME, &cb_name)) || + KHM_FAILED(kcdb_credtype_get_info(cred_type, NULL)) || + KHM_FAILED(kcdb_identity_hold(identity))) { + return KHM_ERROR_INVALID_PARAM; + } + + cb_name += sizeof(wchar_t); + + cred = PMALLOC(sizeof(kcdb_cred)); + ZeroMemory(cred, sizeof(kcdb_cred)); + + cred->magic = KCDB_CRED_MAGIC; + cred->identity = identity; + cred->name = PMALLOC(cb_name); + StringCbCopy(cred->name, cb_name, name); + cred->type = cred_type; + + cred->refcount = 1; /* initially held */ + + LINIT(cred); + + kcdb_buf_new(&cred->buf, KCDB_ATTR_MAX_ID + 1); + + /* Not obtaining a write lock on l_cred on purpose. + Well, because no one should be referencing this credential until + this function returns. */ + EnterCriticalSection(&cs_creds); + cred->id = kcdb_cred_id++; + LPUSH(&kcdb_creds, cred); + LeaveCriticalSection(&cs_creds); + + *result = cred; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_update(khm_handle vdest, + khm_handle vsrc) +{ + khm_int32 rv = KHM_ERROR_EQUIVALENT; + kcdb_cred * src; + kcdb_cred * dest; + kcdb_type * t; + kcdb_attrib * a; + void * srcbuf; + void * destbuf; + khm_size cbsrcbuf; + khm_size cbdestbuf; + + int i; + + kcdb_cred_lock_write(); + + if(!kcdb_cred_is_active_cred(vsrc) || + !kcdb_cred_is_active_cred(vdest)) + goto _exit; + + src = (kcdb_cred *) vsrc; + dest = (kcdb_cred *) vdest; + + for(i=0;i<KCDB_ATTR_MAX_ID;i++) { + if(kcdb_cred_val_exist(src, i)) { + /*NOTE: the logic here has to reflect the logic in + kcdb_cred_set_attr() */ + if(KHM_FAILED(kcdb_attrib_get_info(i, &a))) + continue; + + if((a->flags & KCDB_ATTR_FLAG_COMPUTED) || + KHM_FAILED(kcdb_type_get_info(a->type, &t))) { + kcdb_attrib_release_info(a); + continue; + } + + srcbuf = kcdb_cred_buf_get(src,i); + cbsrcbuf = kcdb_cred_buf_size(src, i); + + if(kcdb_cred_val_exist(dest, i)) { + destbuf = kcdb_cred_buf_get(dest, i); + cbdestbuf = kcdb_cred_buf_size(dest, i); + + if(!t->comp(srcbuf, cbsrcbuf, destbuf, cbdestbuf)) + goto _skip_copy; + } + + kcdb_buf_set_value(&dest->buf, i, (khm_ui_2) i, srcbuf, cbsrcbuf); + rv = KHM_ERROR_SUCCESS; + + _skip_copy: + kcdb_attrib_release_info(a); + kcdb_type_release_info(t); + } else { + if (KHM_FAILED(kcdb_attrib_get_info(i, &a))) + continue; + + if (!(a->flags & KCDB_ATTR_FLAG_COMPUTED) && + (a->flags & KCDB_ATTR_FLAG_TRANSIENT) && + kcdb_cred_val_exist(dest, i)) { + kcdb_buf_set_value(&dest->buf, i, (khm_ui_2) i, NULL, 0); + + rv = KHM_ERROR_SUCCESS; + } + + kcdb_attrib_release_info(a); + } + } + + if (dest->flags != src->flags) { + khm_int32 old_flags; + + old_flags = dest->flags; + + dest->flags = (src->flags & ~KCDB_CRED_FLAGMASK_ADDITIVE) | + ((src->flags | dest->flags) & KCDB_CRED_FLAGMASK_ADDITIVE); + + if (dest->flags != old_flags) + rv = KHM_ERROR_SUCCESS; + } + + _exit: + kcdb_cred_unlock_write(); + return rv; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_dup( + khm_handle vcred, + khm_handle * pnewcred) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred; + kcdb_cred * newcred; + khm_handle vnewcred; + + if(!pnewcred) + return KHM_ERROR_INVALID_PARAM; + + *pnewcred = NULL; + + kcdb_cred_lock_write(); + + if(!kcdb_cred_is_active_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + if(KHM_FAILED(kcdb_cred_create(cred->name, + cred->identity, + cred->type, + &vnewcred))) + { + code = KHM_ERROR_UNKNOWN; + goto _exit; + } + + newcred = (kcdb_cred *) vnewcred; + + newcred->flags = cred->flags; + + kcdb_buf_dup(&newcred->buf, &cred->buf); + + /* newcred is already held from the call to kcdb_cred_create */ + *pnewcred = (khm_handle) newcred; + +_exit: + kcdb_cred_unlock_write(); + return code; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_get_serial( + khm_handle vcred, + khm_ui_8 * pserial) +{ + kcdb_cred * c; + + if(!pserial) + return KHM_ERROR_INVALID_PARAM; + + kcdb_cred_lock_read(); + + if(!kcdb_cred_is_active_cred(vcred)) { + kcdb_cred_unlock_read(); + return KHM_ERROR_INVALID_PARAM; + } + + c = (kcdb_cred *) vcred; + + *pserial = c->id; + + kcdb_cred_unlock_read(); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_set_identity( + khm_handle vcred, + khm_handle id) +{ + kcdb_cred * c; + + if(!kcdb_is_identity(id)) + return KHM_ERROR_INVALID_PARAM; + + kcdb_cred_lock_write(); + if(!kcdb_cred_is_active_cred(vcred)) { + kcdb_cred_unlock_write(); + return KHM_ERROR_INVALID_PARAM; + } + + c = (kcdb_cred *) vcred; + + if(c->identity) { + kcdb_identity_release((khm_handle) c->identity); + } + kcdb_identity_hold(id); + c->identity = (kcdb_identity *) id; + + kcdb_cred_unlock_write(); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_get_type( + khm_handle vcred, + khm_int32 * type) +{ + kcdb_cred * c; + + if(!type) + return KHM_ERROR_INVALID_PARAM; + + kcdb_cred_lock_read(); + + if(!kcdb_cred_is_active_cred(vcred)) { + kcdb_cred_unlock_read(); + return KHM_ERROR_INVALID_PARAM; + } + + c = (kcdb_cred *) vcred; + + *type = c->type; + + kcdb_cred_unlock_read(); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_set_attrib( + khm_handle cred, + const wchar_t * name, + void * buffer, + khm_size cbbuf) +{ + khm_int32 attr_id = -1; + + if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) + return KHM_ERROR_INVALID_PARAM; + + return kcdb_cred_set_attr( + cred, + attr_id, + buffer, + cbbuf); +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_set_attr( + khm_handle vcred, + khm_int32 attr_id, + void * buffer, + khm_size cbbuf) +{ + kcdb_cred * cred; + kcdb_type * type = NULL; + kcdb_attrib * attrib = NULL; + khm_size cbdest; + khm_int32 code = KHM_ERROR_SUCCESS; + + if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + kcdb_cred_lock_write(); + + if(!kcdb_cred_is_active_cred(vcred)) { + kcdb_cred_unlock_write(); + return KHM_ERROR_INVALID_PARAM; + } + + cred = (kcdb_cred *) vcred; + + if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { + kcdb_cred_unlock_write(); + return KHM_ERROR_INVALID_PARAM; + } + + if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) + { + kcdb_cred_unlock_write(); + kcdb_attrib_release_info(attrib); + return KHM_ERROR_INVALID_OPERATION; + } + + if (buffer == 0) { + /* we are removing the value */ + kcdb_buf_alloc(&cred->buf, attr_id, (khm_ui_2) attr_id, 0); + code = KHM_ERROR_SUCCESS; + goto _exit; + } + + if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { + kcdb_cred_unlock_write(); + kcdb_attrib_release_info(attrib); + return KHM_ERROR_INVALID_PARAM; + } + + if(!(type->isValid(buffer,cbbuf))) { + code = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + + if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + kcdb_buf_alloc(&cred->buf, attr_id, (khm_ui_2) attr_id, cbdest); + if(!kcdb_cred_buf_exist(cred, attr_id)) { + code = KHM_ERROR_NO_RESOURCES; + goto _exit; + } + + if(KHM_FAILED(code = + type->dup(buffer, cbbuf, kcdb_cred_buf_get(cred,attr_id), &cbdest))) + { + kcdb_buf_alloc(&cred->buf, attr_id, (khm_ui_2) attr_id, 0); + goto _exit; + } + + kcdb_buf_set_value_flag(&cred->buf, attr_id); + +_exit: + kcdb_cred_unlock_write(); + + if(attrib) + kcdb_attrib_release_info(attrib); + if(type) + kcdb_type_release_info(type); + + return code; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib( + khm_handle cred, + const wchar_t * name, + khm_int32 * attr_type, + void * buffer, + khm_size * cbbuf) +{ + khm_int32 attr_id = -1; + + if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) + return KHM_ERROR_NOT_FOUND; + + return kcdb_cred_get_attr( + cred, + attr_id, + attr_type, + buffer, + cbbuf); +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib_string( + khm_handle cred, + const wchar_t * name, + wchar_t * buffer, + khm_size * cbbuf, + khm_int32 flags) +{ + khm_int32 attr_id = -1; + + if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) + return KHM_ERROR_NOT_FOUND; + + return kcdb_cred_get_attr_string( + cred, + attr_id, + buffer, + cbbuf, + flags); +} + +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_attr(khm_handle vcred, + khm_int32 attr_id, + khm_int32 * attr_type, + void * buffer, + khm_size * pcbbuf) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred = NULL; + kcdb_attrib * attrib = NULL; + kcdb_type * type = NULL; + + if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { + return KHM_ERROR_INVALID_PARAM; + } + + if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { + kcdb_attrib_release_info(attrib); + return KHM_ERROR_UNKNOWN; + } + + if(attr_type) + *attr_type = attrib->type; + + kcdb_cred_lock_read(); + if(!kcdb_cred_is_active_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + if(!buffer && !pcbbuf) { + /* in this case the caller is only trying to determine if the + field contains data. We assume that computed fields are + always non-null. */ + code = (kcdb_cred_val_exist(cred, attr_id) || + (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND; + goto _exit; + } + + if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { + code = attrib->compute_cb( + vcred, + attr_id, + buffer, + pcbbuf); + } else if (kcdb_cred_val_exist(cred, attr_id)) { + code = type->dup( + kcdb_cred_buf_get(cred, attr_id), + kcdb_cred_buf_size(cred, attr_id), + buffer, + pcbbuf); + } else { + code = KHM_ERROR_NOT_FOUND; + } + +_exit: + kcdb_cred_unlock_read(); + if(type) + kcdb_type_release_info(type); + if(attrib) + kcdb_attrib_release_info(attrib); + + return code; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_get_attr_string( + khm_handle vcred, + khm_int32 attr_id, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred = NULL; + kcdb_attrib * attrib = NULL; + kcdb_type * type = NULL; + + if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit_nolock; + } + + if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { + code = KHM_ERROR_UNKNOWN; + goto _exit_nolock; + } + + kcdb_cred_lock_read(); + if(!kcdb_cred_is_active_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + if(!buffer && !pcbbuf) { + /* in this case the caller is only trying to determine if the + field contains data. We assume that computed fields are + always non-null. */ + code = (kcdb_cred_val_exist(cred, attr_id) || + (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND; + goto _exit; + } + + if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { + void * buf; + khm_size cbbuf; + + code = attrib->compute_cb(vcred, + attr_id, + NULL, + &cbbuf); + if(code == KHM_ERROR_TOO_LONG) { + wchar_t vbuf[KCDB_MAXCCH_NAME]; + + if (cbbuf < sizeof(vbuf)) + buf = vbuf; + else + buf = PMALLOC(cbbuf); + + code = attrib->compute_cb(vcred, + attr_id, + buf, + &cbbuf); + if(KHM_SUCCEEDED(code)) { + code = type->toString(buf, + cbbuf, + buffer, + pcbbuf, + flags); + } + + if (buf != vbuf) + PFREE(buf); + } + } else { + if(kcdb_cred_buf_exist(cred, attr_id)) { + code = type->toString( + kcdb_cred_buf_get(cred, attr_id), + kcdb_cred_buf_size(cred, attr_id), + buffer, + pcbbuf, + flags); + } else + code = KHM_ERROR_NOT_FOUND; + } + + _exit: + kcdb_cred_unlock_read(); + _exit_nolock: + if(type) + kcdb_type_release_info(type); + if(attrib) + kcdb_attrib_release_info(attrib); + + return code; +} + + +KHMEXP khm_int32 KHMAPI kcdb_cred_get_name( + khm_handle vcred, + wchar_t * buffer, + khm_size * cbbuf) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred = NULL; + size_t cbsize; + + if(!cbbuf) + return KHM_ERROR_INVALID_PARAM; + + kcdb_cred_lock_read(); + + if(!kcdb_cred_is_active_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + if(FAILED(StringCbLength(cred->name, KCDB_CRED_MAXCB_NAME, &cbsize))) { + code = KHM_ERROR_UNKNOWN; + goto _exit; + } + + cbsize += sizeof(wchar_t); + + if(!buffer || *cbbuf < cbsize) { + *cbbuf = cbsize; + code = KHM_ERROR_TOO_LONG; + goto _exit; + } + + StringCbCopy(buffer, *cbbuf, cred->name); + + *cbbuf = cbsize; + +_exit: + + kcdb_cred_unlock_read(); + return code; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_get_identity( + khm_handle vcred, + khm_handle * identity) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred; + + if(!identity) + return KHM_ERROR_INVALID_PARAM; + + kcdb_cred_lock_read(); + + if(!kcdb_cred_is_active_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + kcdb_identity_hold((khm_handle) cred->identity); + + *identity = cred->identity; + +_exit: + kcdb_cred_unlock_read(); + return code; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_hold(khm_handle vcred) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred; + + kcdb_cred_lock_write(); + + if(!kcdb_cred_is_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + cred->refcount++; + +_exit: + kcdb_cred_unlock_write(); + return code; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_release(khm_handle vcred) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred; + + kcdb_cred_lock_write(); + + if(!kcdb_cred_is_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + cred->refcount--; + +_exit: + kcdb_cred_unlock_write(); + + kcdb_cred_check_and_delete(vcred); + + return code; +} + +void kcdb_cred_check_and_delete(khm_handle vcred) +{ + kcdb_cred * cred; + + kcdb_cred_lock_read(); + if(!kcdb_cred_is_cred(vcred)) { + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + if(cred->refcount) + goto _exit; + + kcdb_cred_unlock_read(); + kcdb_cred_lock_write(); + if(!kcdb_cred_is_cred(vcred)) { + /* did we lose the race? */ + goto _exit2; + } + + cred->magic = 0; /* no longer a cred */ + kcdb_identity_release(cred->identity); + + EnterCriticalSection(&cs_creds); + LDELETE(&kcdb_creds, cred); + LeaveCriticalSection(&cs_creds); + + kcdb_buf_delete(&cred->buf); + PFREE(cred->name); + PFREE(cred); + + /*TODO: notifications */ + +_exit2: + kcdb_cred_unlock_write(); + return; + +_exit: + kcdb_cred_unlock_read(); +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_delete(khm_handle vcred) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred * cred; + + kcdb_cred_lock_write(); + + if(!kcdb_cred_is_active_cred(vcred)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = (kcdb_cred *) vcred; + + cred->flags |= KCDB_CRED_FLAG_DELETED; + +_exit: + kcdb_cred_unlock_write(); + + kcdb_cred_check_and_delete(vcred); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_creds_comp_attrib(khm_handle cred1, + khm_handle cred2, + const wchar_t * name) +{ + khm_int32 attr_id; + + if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) + return 0; + + return kcdb_creds_comp_attr(cred1, cred2, attr_id); +} + +KHMEXP khm_int32 KHMAPI +kcdb_creds_comp_attr(khm_handle vcred1, + khm_handle vcred2, + khm_int32 attr_id) +{ + khm_int32 code = 0; + kcdb_cred * cred1; + kcdb_cred * cred2; + kcdb_attrib * attrib = NULL; + kcdb_type * type = NULL; + + if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) + return 0; + + cred1 = (kcdb_cred *) vcred1; + cred2 = (kcdb_cred *) vcred2; + + kcdb_cred_lock_read(); + if( + !kcdb_cred_is_active_cred(vcred1) || + !kcdb_cred_is_active_cred(vcred2)) + goto _exit; + + cred1 = (kcdb_cred *) vcred1; + cred2 = (kcdb_cred *) vcred2; + + if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) + goto _exit; + + if(!(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)) { + int nc = 0; + + if(!kcdb_cred_val_exist(cred1, attr_id)) { + code = -1; + nc = 1; + } + if(!kcdb_cred_val_exist(cred2, attr_id)) { + code += 1; + nc = 1; + } + + if(nc) + goto _exit; + } + + if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) + goto _exit; + + if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { + khm_octet vbuf[KCDB_MAXCB_NAME * 2]; + void * buf1 = NULL; + void * buf2 = NULL; + khm_size cb1; + khm_size cb2; + + code = 0; + + if(attrib->compute_cb(vcred1, attr_id, + NULL, &cb1) != KHM_ERROR_TOO_LONG) + goto _exit_1; + + if(attrib->compute_cb(vcred2, attr_id, + NULL, &cb2) != KHM_ERROR_TOO_LONG) + goto _exit_1; + + if(cb1) { + if (cb1 < sizeof(vbuf)) + buf1 = vbuf; + else + buf1 = PMALLOC(cb1); + + if(KHM_FAILED(attrib->compute_cb(vcred1, attr_id, buf1, &cb1))) + goto _exit_1; + } + + if(cb2) { + if (cb1 + cb2 < sizeof(vbuf)) + buf2 = vbuf + cb1; + else + buf2 = PMALLOC(cb2); + + if(KHM_FAILED(attrib->compute_cb(vcred2, attr_id, buf2, &cb2))) + goto _exit_1; + } + + code = type->comp(buf1, cb1, + buf2, cb2); +_exit_1: + if(buf1 && (buf1 < (void *)vbuf || + buf1 >= (void*)(vbuf + sizeof(vbuf)))) + PFREE(buf1); + if(buf2 && (buf2 < (void *)vbuf || + buf2 >= (void *)(vbuf + sizeof(vbuf)))) + PFREE(buf2); + } else { + code = type->comp( + kcdb_cred_buf_get(cred1, attr_id), + kcdb_cred_buf_size(cred1, attr_id), + kcdb_cred_buf_get(cred2, attr_id), + kcdb_cred_buf_size(cred2, attr_id)); + } + +_exit: + kcdb_cred_unlock_read(); + if(attrib) + kcdb_attrib_release_info(attrib); + if(type) + kcdb_type_release_info(type); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_creds_is_equal(khm_handle vcred1, + khm_handle vcred2) +{ + khm_int32 code = 0; + kcdb_cred * cred1; + kcdb_cred * cred2; + + kcdb_cred_lock_read(); + if(!kcdb_cred_is_active_cred(vcred1) || + !kcdb_cred_is_active_cred(vcred2)) { + + code = FALSE; + goto _exit; + + } + + if(vcred1 == vcred2) { + + code = TRUE; + goto _exit; + + } + + cred1 = vcred1; + cred2 = vcred2; + + if(cred1->identity == cred2->identity && + cred1->type == cred2->type && + !wcscmp(cred1->name, cred2->name)) { + + kcdb_credtype * type; + + code = TRUE; + + if (KHM_SUCCEEDED(kcdb_credtype_get_info(cred1->type, &type))) { + if (type->is_equal && + (*type->is_equal)(vcred1, vcred2, NULL)) + code = 0; + + kcdb_credtype_release_info(type); + } + } + +_exit: + kcdb_cred_unlock_read(); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_flags(khm_handle vcred, + khm_int32 * pflags) +{ + khm_int32 f; + khm_int32 rv = KHM_ERROR_SUCCESS; + kcdb_cred * cred; + int release_lock = TRUE; + + if (pflags == NULL) + return KHM_ERROR_INVALID_PARAM; + + kcdb_cred_lock_read(); + if (!kcdb_cred_is_active_cred(vcred)) { + *pflags = 0; + rv = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = vcred; + f = cred->flags; + + /* Update flags if necessary */ + + if (!(f & KCDB_CRED_FLAG_EXPIRED) && + kcdb_cred_buf_exist(cred, KCDB_ATTR_EXPIRE)) { + + FILETIME ftc; + + GetSystemTimeAsFileTime(&ftc); + if (CompareFileTime(&ftc, ((FILETIME *) + kcdb_cred_buf_get(cred, KCDB_ATTR_EXPIRE))) + >= 0) + f |= KCDB_CRED_FLAG_EXPIRED; + } + +#if 0 + /* Commented out: if the credential has expired, then checking the + renewable time is not useful */ + if (!(f & KCDB_CRED_FLAG_INVALID)) { + if (f & KCDB_CRED_FLAG_RENEWABLE) { + if (kcdb_cred_buf_exist(cred, KCDB_ATTR_RENEW_EXPIRE)) { + FILETIME ftc; + + GetSystemTimeAsFileTime(&ftc); + if (CompareFileTime(&ftc, ((FILETIME *) + kcdb_cred_buf_get(cred, KCDB_ATTR_RENEW_EXPIRE))) >= 0) + f |= KCDB_CRED_FLAG_INVALID; + } + } else { + if (f & KCDB_CRED_FLAG_EXPIRED) + f |= KCDB_CRED_FLAG_INVALID; + } + } + + /* Commented out: this is a read operation. We shouldn't attempt + to lock for writing */ + if (f != cred->flags) { + kcdb_cred_unlock_read(); + kcdb_cred_lock_write(); + /* Did we lose a race? */ + if (kcdb_cred_is_active_cred(vcred)) + cred->flags = f; + else { + rv = KHM_ERROR_INVALID_PARAM; + f = 0; + } + kcdb_cred_unlock_write(); + release_lock = FALSE; + } +#endif + + *pflags = f; + + _exit: + if (release_lock) + kcdb_cred_unlock_read(); + + return rv; +} + +KHMEXP khm_int32 KHMAPI kcdb_cred_set_flags( + khm_handle vcred, + khm_int32 flags, + khm_int32 mask) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + kcdb_cred * cred; + + kcdb_cred_lock_write(); + if(!kcdb_cred_is_active_cred(vcred)) { + rv = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + cred = vcred; + + flags &= ~(KCDB_CRED_FLAG_DELETED); + mask &= ~(KCDB_CRED_FLAG_DELETED); + + cred->flags = + (cred->flags & (~mask)) | + (flags & mask); + + _exit: + kcdb_cred_unlock_write(); + return rv; +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/credential.h b/krb5-1-6/src/windows/identity/kcreddb/credential.h new file mode 100644 index 000000000..49b3953c9 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/credential.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCDB_CREDENTIAL_H +#define __KHIMAIRA_KCDB_CREDENTIAL_H + +/* Credentials */ + +typedef struct kcdb_cred_t { + khm_int32 magic; + khm_ui_8 id; /* serial number */ + kcdb_identity * identity; + khm_int32 type; + wchar_t * name; + + khm_int32 flags; + khm_int32 refcount; + + kcdb_buf buf; + + LDCL(struct kcdb_cred_t); +} kcdb_cred; + +#define KCDB_CRED_MAGIC 0x38fb84a6 + +extern CRITICAL_SECTION cs_creds; +extern kcdb_cred * kcdb_creds; +extern RWLOCK l_creds; +extern khm_ui_8 kcdb_cred_id; + +#define kcdb_cred_val_exist(c,a) kcdb_buf_val_exist(&(c)->buf, a) +#define kcdb_cred_buf_exist(c,a) kcdb_buf_exist(&(c)->buf, a) +#define kcdb_cred_buf_get(c,a) kcdb_buf_get(&(c)->buf, a) +#define kcdb_cred_buf_size(c,a) kcdb_buf_size(&(c)->buf, a) + +#define kcdb_cred_is_cred(c) ((c) && ((kcdb_cred *) c)->magic == KCDB_CRED_MAGIC) +#define kcdb_cred_is_active_cred(c) (kcdb_cred_is_cred(c) && !(((kcdb_cred *) c)->flags & KCDB_CRED_FLAG_DELETED)) + +#define kcdb_cred_lock_read() (LockObtainRead(&l_creds)) +#define kcdb_cred_unlock_read() (LockReleaseRead(&l_creds)) +#define kcdb_cred_lock_write() (LockObtainWrite(&l_creds)) +#define kcdb_cred_unlock_write() (LockReleaseWrite(&l_creds)) + +void kcdb_cred_init(void); +void kcdb_cred_exit(void); +void kcdb_cred_check_and_delete(khm_handle vcred); + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/credset.c b/krb5-1-6/src/windows/identity/kcreddb/credset.c new file mode 100644 index 000000000..92f6c0519 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/credset.c @@ -0,0 +1,1166 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> +#include<assert.h> + +CRITICAL_SECTION cs_credset; +kcdb_credset * kcdb_credsets = NULL; +kcdb_credset * kcdb_root_credset = NULL; + +void +kcdb_credset_init(void) +{ + khm_handle rc; + + InitializeCriticalSection(&cs_credset); + kcdb_credsets = NULL; + + kcdb_credset_create(&rc); + kcdb_root_credset = (kcdb_credset *) rc; + kcdb_root_credset->flags |= KCDB_CREDSET_FLAG_ROOT; +} + +void +kcdb_credset_exit(void) +{ + /*TODO: free the credsets */ + DeleteCriticalSection(&cs_credset); +} + +/* called on an unreleased credset, or with credset::cs held */ +void +kcdb_credset_buf_new(kcdb_credset * cs) +{ + cs->clist = PMALLOC(KCDB_CREDSET_INITIAL_SIZE * + sizeof(kcdb_credset_credref)); + ZeroMemory(cs->clist, + KCDB_CREDSET_INITIAL_SIZE * + sizeof(kcdb_credset_credref)); + cs->nc_clist = KCDB_CREDSET_INITIAL_SIZE; + cs->nclist = 0; +} + +/* called on an unreleased credset, or with credset::cs held */ +void +kcdb_credset_buf_delete(kcdb_credset * cs) +{ + PFREE(cs->clist); + cs->nc_clist = 0; + cs->nclist = 0; +} + +void +kcdb_credset_buf_assert_size(kcdb_credset * cs, khm_int32 nclist) +{ + if(cs->nc_clist < nclist) { + kcdb_credset_credref * new_clist; + + /* nclist had better be greater than KCDB_CREDSET_INITIAL_SIZE */ + nclist = KCDB_CREDSET_INITIAL_SIZE + + (((nclist - (KCDB_CREDSET_INITIAL_SIZE + 1)) / KCDB_CREDSET_GROWTH_FACTOR) + 1) * + KCDB_CREDSET_GROWTH_FACTOR; + + new_clist = PCALLOC(nclist, sizeof(kcdb_credset_credref)); + + memcpy(new_clist, cs->clist, cs->nclist * sizeof(kcdb_credset_credref)); + + PFREE(cs->clist); + + cs->clist = new_clist; + } +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_create(khm_handle * result) +{ + kcdb_credset * cs; + + cs = PMALLOC(sizeof(kcdb_credset)); + ZeroMemory(cs, sizeof(kcdb_credset)); + + cs->magic = KCDB_CREDSET_MAGIC; + InitializeCriticalSection(&(cs->cs)); + LINIT(cs); + kcdb_credset_buf_new(cs); + cs->version = 0; + cs->seal_count = 0; + + EnterCriticalSection(&cs_credset); + LPUSH(&kcdb_credsets, cs); + LeaveCriticalSection(&cs_credset); + + *result = (khm_handle) cs; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_delete(khm_handle vcredset) +{ + kcdb_credset * cs; + int i; + + if(!kcdb_credset_is_credset(vcredset)) { + return KHM_ERROR_INVALID_PARAM; + } + + cs = (kcdb_credset *) vcredset; + + EnterCriticalSection(&cs_credset); + LDELETE(&kcdb_credsets, cs); + LeaveCriticalSection(&cs_credset); + + EnterCriticalSection(&(cs->cs)); + cs->magic = 0; + + for(i=0;i<cs->nclist;i++) { + if(cs->clist[i].cred) { + kcdb_cred_release((khm_handle) cs->clist[i].cred); + } + } + kcdb_credset_buf_delete(cs); + + LeaveCriticalSection(&(cs->cs)); + DeleteCriticalSection(&(cs->cs)); + + PFREE(cs); + + return KHM_ERROR_SUCCESS; +} + +/*! \internal + +Collect credentials from cs2 to cs1 which have already been selected into +cl1 and cl2. + +- Credentials in cl2 that are not in cl1 will get added to cs1 +- Credentials in cl1 that are not in cl2 will get removed from cs1 +- Credentials in cl1 and cl2 will be updated in cs1 + +cl1 and cl2 will be modified. +*/ +khm_int32 +kcdb_credset_collect_core(kcdb_credset * cs1, + kcdb_cred ** cl1, + khm_int32 ncl1, + kcdb_credset * cs2, + kcdb_cred ** cl2, + khm_int32 ncl2, + khm_int32 * delta) +{ + int i, j; + int ldelta = 0; + khm_int32 rv; + + /* find matching creds and update them */ + for(i=0; i<ncl1; i++) + if(cl1[i]) { + for(j=0; j<ncl2; j++) + if(cl2[j] && kcdb_creds_is_equal((khm_handle) cl1[i], (khm_handle) cl2[j])) { + /* they are equivalent. make them equal */ + + /* depending on whether any changes were made, + update ldelta with the proper bit flag */ + + rv = kcdb_cred_update(cl1[i], cl2[j]); + if (rv == KHM_ERROR_SUCCESS) { + kcdb_credset_update_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]); + ldelta |= KCDB_DELTA_MODIFY; + } + + cl2[j] = NULL; + cl1[i] = NULL; + break; + } + } + + /* all the creds that are left in cl1 need to be removed */ + for(i=0; i<ncl1; i++) + if(cl1[i]) { + kcdb_credset_del_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]); + cl1[i] = NULL; + ldelta |= KCDB_DELTA_DEL; + } + + /* all the creds in cl2 need to be added to cs1 */ + for(j=0; j<ncl2; j++) + if(cl2[j]) { + /* duplicate the credential and add it if we are adding it to the + root credential store. */ + if(cs1 == kcdb_root_credset) { + khm_handle h; + + if(KHM_SUCCEEDED(kcdb_cred_dup((khm_handle) cl2[j], &h))) { + kcdb_credset_add_cred((khm_handle) cs1, h, -1); + kcdb_cred_release(h); + } + } else + kcdb_credset_add_cred((khm_handle) cs1, cl2[j], -1); + cl2[j] = NULL; + ldelta |= KCDB_DELTA_ADD; + } + + if(delta) + *delta = ldelta; + + if((cs1 == kcdb_root_credset) && ldelta) { + /* something changed in the root credential set */ + kmq_post_message(KMSG_CRED,KMSG_CRED_ROOTDELTA,ldelta,NULL); + } + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_collect(khm_handle cs_dest, + khm_handle cs_src, + khm_handle identity, + khm_int32 type, + khm_int32 * delta) +{ + kcdb_credset * cs; + kcdb_credset * rcs; + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred ** r_sel = NULL; + kcdb_cred ** c_sel = NULL; + int nr_sel, nc_sel; + int i; + + if((cs_src && !kcdb_credset_is_credset(cs_src)) || + (cs_dest && !kcdb_credset_is_credset(cs_dest)) || + (cs_src == cs_dest)) /* works because credsets use shared + handles */ + return KHM_ERROR_INVALID_PARAM; + + if(identity && !kcdb_is_active_identity(identity)) + return KHM_ERROR_INVALID_PARAM; + + if(cs_src) + cs = (kcdb_credset *) cs_src; + else + cs = kcdb_root_credset; + + if(cs_dest) + rcs = (kcdb_credset *) cs_dest; + else + rcs = kcdb_root_credset; + + if (kcdb_credset_is_sealed(rcs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + EnterCriticalSection(&(rcs->cs)); + + /* enumerate through the root and given credential sets and select + the ones we want */ + + if(rcs->nclist > 0) + r_sel = PMALLOC(sizeof(kcdb_cred *) * rcs->nclist); + if(cs->nclist > 0) + c_sel = PMALLOC(sizeof(kcdb_cred *) * cs->nclist); + nr_sel = 0; + nc_sel = 0; + + for(i=0; i<rcs->nclist; i++) { + if(rcs->clist[i].cred && + (!identity || rcs->clist[i].cred->identity == identity) && + (type==KCDB_CREDTYPE_ALL || rcs->clist[i].cred->type == type)) + { + r_sel[nr_sel++] = rcs->clist[i].cred; + } + } + + for(i=0; i<cs->nclist; i++) { + if(cs->clist[i].cred && + (!identity || cs->clist[i].cred->identity == identity) && + (type==KCDB_CREDTYPE_ALL || cs->clist[i].cred->type == type)) + { + c_sel[nc_sel++] = cs->clist[i].cred; + } + } + + rcs->version++; + + code = kcdb_credset_collect_core( + rcs, + r_sel, + nr_sel, + cs, + c_sel, + nc_sel, + delta); + + LeaveCriticalSection(&(rcs->cs)); + LeaveCriticalSection(&(cs->cs)); + + if(r_sel) + PFREE(r_sel); + if(c_sel) + PFREE(c_sel); + + if (cs_dest == NULL) { + kcdb_identity_refresh_all(); + } + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_collect_filtered(khm_handle cs_dest, + khm_handle cs_src, + kcdb_cred_filter_func filter, + void * rock, + khm_int32 * delta) +{ + kcdb_credset * cs; + kcdb_credset * rcs; + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_cred ** r_sel = NULL; + kcdb_cred ** c_sel = NULL; + int nr_sel, nc_sel; + int i; + khm_int32 cs_f = 0; + khm_int32 rcs_f = 0; + + if((cs_src && !kcdb_credset_is_credset(cs_src)) || + (cs_dest && !kcdb_credset_is_credset(cs_dest)) || + (cs_src == cs_dest)) /* works because credsets use shared + handles */ + return KHM_ERROR_INVALID_PARAM; + + if(cs_src) + cs = (kcdb_credset *) cs_src; + else { + cs = kcdb_root_credset; + cs_f = KCDB_CREDCOLL_FILTER_ROOT; + } + + if(cs_dest) + rcs = (kcdb_credset *) cs_dest; + else { + rcs = kcdb_root_credset; + rcs_f = KCDB_CREDCOLL_FILTER_ROOT; + } + + if (kcdb_credset_is_sealed(rcs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + EnterCriticalSection(&(rcs->cs)); + +#ifdef DEBUG + assert(!(rcs->flags & KCDB_CREDSET_FLAG_ENUM)); + assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + + if(rcs->nclist) + r_sel = PMALLOC(sizeof(kcdb_cred *) * rcs->nclist); + if(cs->nclist) + c_sel = PMALLOC(sizeof(kcdb_cred *) * cs->nclist); + nr_sel = 0; + nc_sel = 0; + + rcs->flags |= KCDB_CREDSET_FLAG_ENUM; + + for(i=0; i<rcs->nclist; i++) { + if(rcs->clist[i].cred && + (*filter)((khm_handle)rcs->clist[i].cred, + KCDB_CREDCOLL_FILTER_DEST | rcs_f, + rock)) + { + r_sel[nr_sel++] = rcs->clist[i].cred; + } + } + + rcs->flags &= ~KCDB_CREDSET_FLAG_ENUM; + cs->flags |= KCDB_CREDSET_FLAG_ENUM; + + for(i=0; i<cs->nclist; i++) { + if(cs->clist[i].cred && filter((khm_handle)rcs->clist[i].cred, KCDB_CREDCOLL_FILTER_SRC | cs_f, rock)) + { + c_sel[nc_sel++] = cs->clist[i].cred; + } + } + + cs->flags &= ~KCDB_CREDSET_FLAG_ENUM; + + rcs->version++; + + code = kcdb_credset_collect_core( + rcs, + r_sel, + nr_sel, + cs, + c_sel, + nc_sel, + delta); + + LeaveCriticalSection(&(rcs->cs)); + LeaveCriticalSection(&(cs->cs)); + + if(r_sel) + PFREE(r_sel); + if(c_sel) + PFREE(c_sel); + + if (cs_dest == NULL) { + kcdb_identity_refresh_all(); + } + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_flush(khm_handle vcredset) +{ + int i; + kcdb_credset * cs; + + if(!kcdb_credset_is_credset(vcredset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) vcredset; + + if (kcdb_credset_is_sealed(cs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + +#ifdef DEBUG + assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + + for(i=0;i<cs->nclist;i++) { + if(cs->clist[i].cred) { + kcdb_cred_release((khm_handle) cs->clist[i].cred); + } + } + cs->nclist = 0; + LeaveCriticalSection(&(cs->cs)); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_extract(khm_handle destcredset, + khm_handle sourcecredset, + khm_handle identity, + khm_int32 type) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_credset * dest; + kcdb_credset * src; + int isRoot = 0; + khm_size srcSize = 0; + int i; + + if(!kcdb_credset_is_credset(destcredset)) + return KHM_ERROR_INVALID_PARAM; + + if(sourcecredset) { + if(!kcdb_credset_is_credset(sourcecredset)) + return KHM_ERROR_INVALID_PARAM; + } else { + sourcecredset = kcdb_root_credset; + } + + if (sourcecredset == kcdb_root_credset) + isRoot = 1; + + src = (kcdb_credset *) sourcecredset; + dest = (kcdb_credset *) destcredset; + + if (kcdb_credset_is_sealed(dest)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(src->cs)); + EnterCriticalSection(&(dest->cs)); + +#ifdef DEBUG + assert(!(dest->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + + if(KHM_FAILED(kcdb_credset_get_size(sourcecredset, &srcSize))) { + code = KHM_ERROR_UNKNOWN; + goto _exit; + } + + kcdb_cred_lock_read(); + + for(i=0; i < (int) srcSize; i++) { + kcdb_cred * c; + + c = src->clist[i].cred; + if(kcdb_cred_is_active_cred((khm_handle) c) && + (!identity || c->identity == identity) && + (type < 0 || c->type == type)) + { + if(isRoot) { + khm_handle newcred; + + kcdb_cred_unlock_read(); + kcdb_cred_dup((khm_handle) c, &newcred); + kcdb_credset_add_cred(destcredset, newcred, -1); + kcdb_cred_release(newcred); + kcdb_cred_lock_read(); + } else { + kcdb_cred_unlock_read(); + kcdb_credset_add_cred(destcredset, (khm_handle) c, -1); + kcdb_cred_lock_read(); + } + } + } + + kcdb_cred_unlock_read(); + +_exit: + LeaveCriticalSection(&(dest->cs)); + LeaveCriticalSection(&(src->cs)); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_extract_filtered(khm_handle destcredset, + khm_handle sourcecredset, + kcdb_cred_filter_func filter, + void * rock) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_credset * dest; + kcdb_credset * src; + int isRoot = 0; + khm_size srcSize = 0; + int i; + + if(!kcdb_credset_is_credset(destcredset)) + return KHM_ERROR_INVALID_PARAM; + + if(sourcecredset) { + if(!kcdb_credset_is_credset(sourcecredset)) + return KHM_ERROR_INVALID_PARAM; + } else { + sourcecredset = kcdb_root_credset; + isRoot = 1; + } + + src = (kcdb_credset *) sourcecredset; + dest = (kcdb_credset *) destcredset; + + if (kcdb_credset_is_sealed(dest)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(src->cs)); + EnterCriticalSection(&(dest->cs)); + +#ifdef DEBUG + assert(!(dest->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + + if(KHM_FAILED(kcdb_credset_get_size(sourcecredset, &srcSize))) { + code = KHM_ERROR_UNKNOWN; + goto _exit; + } + + kcdb_cred_lock_read(); + + dest->flags |= KCDB_CREDSET_FLAG_ENUM; + + for(i=0; i < (int) srcSize; i++) { + kcdb_cred * c; + + c = src->clist[i].cred; + if(kcdb_cred_is_active_cred((khm_handle) c) && + filter(c, 0, rock)) + { + if(isRoot) { + khm_handle newcred; + + kcdb_cred_unlock_read(); + kcdb_cred_dup((khm_handle) c, &newcred); + kcdb_credset_add_cred(destcredset, newcred, -1); + kcdb_cred_release(newcred); + kcdb_cred_lock_read(); + } else { + kcdb_cred_unlock_read(); + kcdb_credset_add_cred(destcredset, (khm_handle) c, -1); + kcdb_cred_lock_read(); + } + } + } + + dest->flags &= ~KCDB_CREDSET_FLAG_ENUM; + + kcdb_cred_unlock_read(); + +_exit: + LeaveCriticalSection(&(dest->cs)); + LeaveCriticalSection(&(src->cs)); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_apply(khm_handle vcredset, kcdb_cred_apply_func f, + void * rock) +{ + kcdb_credset * cs; + khm_int32 rv = KHM_ERROR_SUCCESS; + int i; + + if(vcredset != NULL && !kcdb_credset_is_credset(vcredset)) + return KHM_ERROR_INVALID_PARAM; + + if(vcredset == NULL) { + cs = kcdb_root_credset; + } else { + cs = (kcdb_credset *) vcredset; + } + + EnterCriticalSection(&cs->cs); + +#ifdef DEBUG + assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + + cs->flags |= KCDB_CREDSET_FLAG_ENUM; + + for(i=0; i<cs->nclist; i++) { + if(!kcdb_cred_is_active_cred(cs->clist[i].cred)) + continue; + + if(KHM_FAILED(f((khm_handle) cs->clist[i].cred, rock))) + break; + } + + cs->flags &= ~KCDB_CREDSET_FLAG_ENUM; + + LeaveCriticalSection(&cs->cs); + + if(i<cs->nclist) + rv = KHM_ERROR_EXIT; + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_get_cred(khm_handle vcredset, + khm_int32 idx, + khm_handle * cred) +{ + kcdb_credset * cs; + khm_int32 code = KHM_ERROR_SUCCESS; + + if(!kcdb_credset_is_credset(vcredset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) vcredset; + + *cred = NULL; + + EnterCriticalSection(&(cs->cs)); + if(idx < 0 || idx >= cs->nclist) + code = KHM_ERROR_OUT_OF_BOUNDS; + else if(!cs->clist[idx].cred || !kcdb_cred_is_active_cred((khm_handle) cs->clist[idx].cred)) { + code = KHM_ERROR_DELETED; + if(cs->clist[idx].cred) { + kcdb_cred_release((khm_handle) cs->clist[idx].cred); + cs->clist[idx].cred = NULL; + } + } + else { + kcdb_cred_hold((khm_handle) cs->clist[idx].cred); + *cred = cs->clist[idx].cred; + } + LeaveCriticalSection(&(cs->cs)); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_find_filtered(khm_handle credset, + khm_int32 idx_start, + kcdb_cred_filter_func f, + void * rock, + khm_handle * cred, + khm_int32 * idx) +{ + kcdb_credset * cs; + khm_int32 rv = KHM_ERROR_SUCCESS; + int i; + + if((credset && !kcdb_credset_is_credset(credset)) || !f) + return KHM_ERROR_INVALID_PARAM; + + if(credset) + cs = (kcdb_credset *) credset; + else + cs = kcdb_root_credset; + + EnterCriticalSection(&cs->cs); + + if(idx_start < 0) + i = 0; + else + i = idx_start + 1; + +#ifdef DEBUG + assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + + cs->flags |= KCDB_CREDSET_FLAG_ENUM; + + for(; i < cs->nclist; i++) { + if(kcdb_cred_is_active_cred(cs->clist[i].cred) && + (*f)((khm_handle) cs->clist[i].cred, 0, rock) != 0) + break; + } + + cs->flags &= ~KCDB_CREDSET_FLAG_ENUM; + + if(i < cs->nclist) { + if (cred) { + *cred = (khm_handle) cs->clist[i].cred; + kcdb_cred_hold(*cred); + } + + if(idx) { + *idx = i; + } + } else { + rv = KHM_ERROR_NOT_FOUND; + } + + LeaveCriticalSection(&cs->cs); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_find_cred(khm_handle vcredset, + khm_handle vcred_src, + khm_handle *cred_dest) { + kcdb_credset * cs; + khm_handle cred = NULL; + int idx; + + if (!kcdb_credset_is_credset(vcredset)) + return KHM_ERROR_INVALID_PARAM; + + if (!kcdb_cred_is_active_cred(vcred_src)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) vcredset; + + EnterCriticalSection(&cs->cs); + for (idx = 0; idx < cs->nclist; idx++) { + if (cs->clist[idx].cred && + kcdb_creds_is_equal(vcred_src, cs->clist[idx].cred)) { + cred = cs->clist[idx].cred; + break; + } + } + + if (cred) + kcdb_cred_hold(cred); + + LeaveCriticalSection(&cs->cs); + + if (cred) { + if (cred_dest) + *cred_dest = cred; + else + kcdb_cred_release(cred); + + return KHM_ERROR_SUCCESS; + } else { + return KHM_ERROR_NOT_FOUND; + } +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_del_cred(khm_handle vcredset, + khm_int32 idx) +{ + kcdb_credset * cs; + khm_int32 code = KHM_ERROR_SUCCESS; + + if(!kcdb_credset_is_credset(vcredset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) vcredset; + + if (kcdb_credset_is_sealed(cs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + if(idx < 0 || idx >= cs->nclist) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + if(cs->clist[idx].cred) + kcdb_cred_release((khm_handle) cs->clist[idx].cred); + + if (!(cs->flags & KCDB_CREDSET_FLAG_ENUM)) { + + if(idx + 1 < cs->nclist) + memmove(&(cs->clist[idx]), + &(cs->clist[idx+1]), + sizeof(kcdb_credset_credref) * + (cs->nclist - (idx + 1))); + + cs->nclist--; + } else { + cs->clist[idx].cred = NULL; + } + +_exit: + LeaveCriticalSection(&(cs->cs)); + + return code; +} + +khm_int32 +kcdb_credset_update_cred_ref(khm_handle credset, + khm_handle cred) +{ + kcdb_credset * cs; + khm_int32 code = KHM_ERROR_SUCCESS; + int i; + + if(!kcdb_credset_is_credset(credset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) credset; + + EnterCriticalSection(&(cs->cs)); + + for(i=0; i<cs->nclist; i++) { + if(cs->clist[i].cred == cred) + break; + } + + if(i<cs->nclist) { + cs->clist[i].version = cs->version; + } else { + code = KHM_ERROR_NOT_FOUND; + } + + LeaveCriticalSection(&(cs->cs)); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_del_cred_ref(khm_handle credset, + khm_handle cred) +{ + kcdb_credset * cs; + khm_int32 code = KHM_ERROR_SUCCESS; + int i; + + if(!kcdb_credset_is_credset(credset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) credset; + + if (kcdb_credset_is_sealed(cs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + + for(i=0; i<cs->nclist; i++) { + if(cs->clist[i].cred == cred) + break; + } + + if(i<cs->nclist) { + code = kcdb_credset_del_cred(credset, i); + } else { + code = KHM_ERROR_NOT_FOUND; + } + + LeaveCriticalSection(&(cs->cs)); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_add_cred(khm_handle credset, + khm_handle cred, + khm_int32 idx) +{ + int new_idx; + kcdb_credset * cs; + khm_int32 code = KHM_ERROR_SUCCESS; + + if(!kcdb_credset_is_credset(credset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) credset; + + if (kcdb_credset_is_sealed(cs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + + kcdb_credset_buf_assert_size(cs, cs->nclist + 1); + + if(idx < 0 || idx > cs->nclist) + new_idx = cs->nclist; + else if(idx < cs->nclist){ +#ifdef DEBUG + assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + memmove(&(cs->clist[idx+1]), &(cs->clist[idx]), (cs->nclist - idx)*sizeof(cs->clist[0])); + new_idx = idx; + } else + new_idx = idx; + + kcdb_cred_hold(cred); + + cs->clist[new_idx].cred = (kcdb_cred *) cred; + cs->clist[new_idx].version = cs->version; + cs->nclist++; + + LeaveCriticalSection(&(cs->cs)); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_get_size(khm_handle credset, + khm_size * size) +{ + kcdb_credset * cs; + + *size = 0; + + /* we don't rely on this working, since we can't purge a sealed + credset, although we can measure its size. */ + kcdb_credset_purge(credset); + + if (credset == NULL) + cs = kcdb_root_credset; + else + cs = (kcdb_credset *) credset; + + EnterCriticalSection(&(cs->cs)); + /* while it may seem a bit redundant to get a lock, it ensures that + that the size that we return is consistent with the current state + of the credential set */ + *size = cs->nclist; + LeaveCriticalSection(&(cs->cs)); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_purge(khm_handle credset) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_credset * cs; + int i,j; + + if(!kcdb_credset_is_credset(credset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) credset; + + if (kcdb_credset_is_sealed(cs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + + /* we can't purge a credset while an enumeration operation is in + progress. */ + if (cs->flags & KCDB_CREDSET_FLAG_ENUM) { + code = KHM_ERROR_INVALID_OPERATION; + goto _exit; + } + + for(i=0,j=0; i < cs->nclist; i++) { + if(cs->clist[i].cred) { + if(!kcdb_cred_is_active_cred((khm_handle) cs->clist[i].cred)) { + kcdb_cred_release((khm_handle) cs->clist[i].cred); + } else if(i != j) { + cs->clist[j++] = cs->clist[i]; + } else + j++; + } + } + cs->nclist = j; + + _exit: + LeaveCriticalSection(&(cs->cs)); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_seal(khm_handle credset) { + kcdb_credset * cs; + + if (!kcdb_credset_is_credset(credset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) credset; + + EnterCriticalSection(&cs->cs); + cs->seal_count++; + LeaveCriticalSection(&cs->cs); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_unseal(khm_handle credset) { + kcdb_credset * cs; + khm_int32 rv; + + if (!kcdb_credset_is_credset(credset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) credset; + + EnterCriticalSection(&cs->cs); + if (cs->seal_count > 0) { + cs->seal_count--; + rv = KHM_ERROR_SUCCESS; + } else { + rv = KHM_ERROR_INVALID_OPERATION; + } + LeaveCriticalSection(&cs->cs); + + return rv; +} + +/* These are protected with cs_credset */ +static void * _creds_comp_rock = NULL; +static kcdb_cred_comp_func _creds_comp_func = NULL; + +/* Need cs_credset when calling this function. */ +int __cdecl +kcdb_creds_comp_wrapper(const void * a, const void * b) +{ + return (*_creds_comp_func)((khm_handle) ((kcdb_credset_credref *)a)->cred, + (khm_handle) ((kcdb_credset_credref *)b)->cred, + _creds_comp_rock); +} + +KHMEXP khm_int32 KHMAPI +kcdb_credset_sort(khm_handle credset, + kcdb_cred_comp_func comp, + void * rock) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_credset * cs; + + if(!kcdb_credset_is_credset(credset)) + return KHM_ERROR_INVALID_PARAM; + + cs = (kcdb_credset *) credset; + + if (kcdb_credset_is_sealed(cs)) + return KHM_ERROR_INVALID_OPERATION; + + EnterCriticalSection(&(cs->cs)); + +#ifdef DEBUG + assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); +#endif + + EnterCriticalSection(&cs_credset); + + _creds_comp_rock = rock; + _creds_comp_func = comp; + + qsort(cs->clist, cs->nclist, + sizeof(kcdb_credset_credref), kcdb_creds_comp_wrapper); + + LeaveCriticalSection(&cs_credset); + + LeaveCriticalSection(&(cs->cs)); + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_cred_comp_generic(khm_handle cred1, + khm_handle cred2, + void * rock) +{ + kcdb_cred_comp_order * o = (kcdb_cred_comp_order *) rock; + int i; + khm_int32 r = 0; + khm_int32 f1, f2; + khm_int32 t1, t2; + khm_int32 pt; + + for(i=0; i<o->nFields; i++) { + if (o->fields[i].order & KCDB_CRED_COMP_INITIAL_FIRST) { + + if (o->fields[i].attrib == KCDB_ATTR_TYPE_NAME || + o->fields[i].attrib == KCDB_ATTR_TYPE) { + + kcdb_cred_get_type(cred1, &t1); + kcdb_cred_get_type(cred2, &t2); + kcdb_identity_get_type(&pt); + + if (t1 == t2) + r = 0; + else if (t1 == pt) + r = -1; + else if (t2 == pt) + r = 1; + else + r = 0; + + } else { + + kcdb_cred_get_flags(cred1, &f1); + kcdb_cred_get_flags(cred2, &f2); + + if (((f1 ^ f2) & KCDB_CRED_FLAG_INITIAL) == 0) + r = 0; + else if (f1 & KCDB_CRED_FLAG_INITIAL) + r = -1; + else + r = 1; + + } + + } else { + r = 0; + } + + if (r == 0) + r = kcdb_creds_comp_attr(cred1,cred2,o->fields[i].attrib); + + if(r != 0) { + if(o->fields[i].order & KCDB_CRED_COMP_DECREASING) + r = -r; + break; + } + } + + return r; +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/credset.h b/krb5-1-6/src/windows/identity/kcreddb/credset.h new file mode 100644 index 000000000..ba8ec419e --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/credset.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCDB_CREDSET_H +#define __KHIMAIRA_KCDB_CREDSET_H + +/* credset */ + +typedef struct kcdb_credset_credref_t { + khm_int32 version; + kcdb_cred * cred; +} kcdb_credset_credref; + +typedef struct kcdb_credset_t { + khm_int32 magic; + khm_int32 flags; + CRITICAL_SECTION cs; + + kcdb_credset_credref * clist; + khm_int32 nc_clist; /* total capacity */ + khm_int32 nclist; /* current load */ + + khm_int32 version; /* data version */ + + khm_int32 seal_count; /* number of seals applied to the + credset */ + + struct kcdb_credset_t * next; + struct kcdb_credset_t * prev; +} kcdb_credset; + +#define KCDB_CREDSET_MAGIC 0x63a84f8b + +#define KCDB_CREDSET_FLAG_ROOT 1 + +/* the credset is in the process of being enumerated */ +#define KCDB_CREDSET_FLAG_ENUM 2 + +#define kcdb_credset_is_credset(c) ((c) && ((kcdb_credset *)c)->magic == KCDB_CREDSET_MAGIC) + +#define kcdb_credset_is_sealed(c) ((c)->seal_count != 0) + +#define KCDB_CREDSET_INITIAL_SIZE 256 +#define KCDB_CREDSET_GROWTH_FACTOR 256 + +void kcdb_credset_init(void); +void kcdb_credset_exit(void); +khm_int32 kcdb_credset_update_cred_ref( + khm_handle credset, + khm_handle cred); + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/credtype.c b/krb5-1-6/src/windows/identity/kcreddb/credtype.c new file mode 100644 index 000000000..b88852cfc --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/credtype.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> + +CRITICAL_SECTION cs_credtype; +kcdb_credtype_i ** kcdb_credtype_tbl = NULL; +kcdb_credtype_i * kcdb_credtypes = NULL; + +void kcdb_credtype_init(void) +{ + InitializeCriticalSection(&cs_credtype); + kcdb_credtypes = NULL; + + kcdb_credtype_tbl = PMALLOC(sizeof(kcdb_credtype_i *) * (KCDB_CREDTYPE_MAX_ID+1)); + ZeroMemory(kcdb_credtype_tbl, sizeof(kcdb_credtype_i *) * (KCDB_CREDTYPE_MAX_ID+1)); +} + +void kcdb_credtype_exit(void) +{ + /*TODO:Free up the cred types */ + PFREE(kcdb_credtype_tbl); + DeleteCriticalSection(&cs_credtype); +} + +/* Called with cs_credtype held */ +void kcdb_credtype_check_and_delete(khm_int32 id) +{ + kcdb_credtype_i * ict; + ict = kcdb_credtype_tbl[id]; + if(!ict) + return; + + if((ict->flags & KCDB_CTI_FLAG_DELETED) && + !ict->refcount) + { + kcdb_credtype_tbl[id] = NULL; + LDELETE(&kcdb_credtypes, ict); + + PFREE(ict->ct.name); + if(ict->ct.short_desc) + PFREE(ict->ct.short_desc); + if(ict->ct.long_desc) + PFREE(ict->ct.long_desc); + if(ict->ct.sub) + kmq_delete_subscription(ict->ct.sub); + + PFREE(ict); + } +} + +KHMEXP khm_int32 KHMAPI +kcdb_credtype_register(const kcdb_credtype * type, khm_int32 * new_id) +{ + khm_int32 id; + kcdb_credtype_i * ict; + size_t cb_name; + size_t cb_short_desc; + size_t cb_long_desc; + int i; + + if(!type) + return KHM_ERROR_INVALID_PARAM; + + if(type->id >= KCDB_CREDTYPE_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + if(type->name) { + if(FAILED(StringCbLength(type->name, KCDB_MAXCB_NAME, &cb_name))) + return KHM_ERROR_TOO_LONG; + cb_name += sizeof(wchar_t); + } else + return KHM_ERROR_INVALID_PARAM; + + if(type->short_desc) { + if(FAILED(StringCbLength(type->short_desc, KCDB_MAXCB_SHORT_DESC, &cb_short_desc))) + return KHM_ERROR_TOO_LONG; + cb_short_desc += sizeof(wchar_t); + } else + cb_short_desc = 0; + + if(type->long_desc) { + if(FAILED(StringCbLength(type->long_desc, KCDB_MAXCB_LONG_DESC, &cb_long_desc))) + return KHM_ERROR_TOO_LONG; + cb_long_desc += sizeof(wchar_t); + } else + cb_long_desc = 0; + + if(type->sub == NULL) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + + if(type->id < 0) { + if(KHM_FAILED(kcdb_credtype_get_next_free_id(&id))) { + LeaveCriticalSection(&cs_credtype); + return KHM_ERROR_NO_RESOURCES; + } + } + else + id = type->id; + + if(kcdb_credtype_tbl[id]) { + LeaveCriticalSection(&cs_credtype); + return KHM_ERROR_DUPLICATE; + } + + for(i=0;i<=KCDB_CREDTYPE_MAX_ID;i++) { + if(kcdb_credtype_tbl[i] && !wcscmp(kcdb_credtype_tbl[i]->ct.name, type->name)) { + LeaveCriticalSection(&cs_credtype); + return KHM_ERROR_DUPLICATE; + } + } + + ict = PMALLOC(sizeof(kcdb_credtype_i)); + ZeroMemory(ict, sizeof(kcdb_credtype_i)); + + ict->ct.name = PMALLOC(cb_name); + StringCbCopy(ict->ct.name, cb_name, type->name); + + if(cb_short_desc) { + ict->ct.short_desc = PMALLOC(cb_short_desc); + StringCbCopy(ict->ct.short_desc, cb_short_desc, type->short_desc); + } + + if(cb_long_desc) { + ict->ct.long_desc = PMALLOC(cb_long_desc); + StringCbCopy(ict->ct.long_desc, cb_long_desc, type->long_desc); + } + + ict->ct.id = id; + + ict->ct.icon = type->icon; + + ict->ct.sub = type->sub; + + ict->ct.is_equal = type->is_equal; + + kcdb_credtype_tbl[id] = ict; + + LPUSH(&kcdb_credtypes, ict); + + LeaveCriticalSection(&cs_credtype); + + kcdb_credtype_post_message(KCDB_OP_INSERT, &(ict->ct)); + + if (new_id) + *new_id = id; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_credtype_get_info( + khm_int32 id, + kcdb_credtype ** type) +{ + int found = 0; + + if(id < 0 || id > KCDB_CREDTYPE_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + if(kcdb_credtype_tbl[id] && + !(kcdb_credtype_tbl[id]->flags & KCDB_CTI_FLAG_DELETED)) + { + found = 1; + if(type) { + *type = &(kcdb_credtype_tbl[id]->ct); + kcdb_credtype_hold(kcdb_credtype_tbl[id]); + } + } else { + if(type) + *type = NULL; + } + LeaveCriticalSection(&cs_credtype); + + if(found) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI kcdb_credtype_release_info(kcdb_credtype * type) +{ + kcdb_credtype_i * ict; + + if(!type) + return KHM_ERROR_INVALID_PARAM; + + ict = (kcdb_credtype_i *) type; + return kcdb_credtype_release(ict); +} + +KHMEXP khm_int32 KHMAPI kcdb_credtype_unregister(khm_int32 id) +{ + kcdb_credtype_i * ict; + + if(id < 0 || id > KCDB_CREDTYPE_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + ict = kcdb_credtype_tbl[id]; + ict->flags |= KCDB_CTI_FLAG_DELETED; + kcdb_credtype_check_and_delete(id); + LeaveCriticalSection(&cs_credtype); + + //kcdb_credtype_post_message(KCDB_OP_DELETE, &(ict->ct)); + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_handle KHMAPI kcdb_credtype_get_sub(khm_int32 id) +{ + kcdb_credtype_i * t; + khm_handle s; + + if(id < 0 || id > KCDB_CREDTYPE_MAX_ID) + return NULL; + + EnterCriticalSection(&cs_credtype); + t = kcdb_credtype_tbl[id]; + if(t) + s = t->ct.sub; + else + s = NULL; + LeaveCriticalSection(&cs_credtype); + + return s; +} + +KHMEXP khm_int32 KHMAPI kcdb_credtype_describe( + khm_int32 id, + wchar_t * buf, + khm_size * cbbuf, + khm_int32 flags) +{ + size_t s; + size_t maxs; + wchar_t * str; + kcdb_credtype_i * t; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!cbbuf || id < 0 || id > KCDB_CREDTYPE_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + t = kcdb_credtype_tbl[id]; + if(t) { + if(flags & KCDB_TS_SHORT) { + str = (t->ct.short_desc)?t->ct.short_desc:t->ct.name; + maxs = (t->ct.short_desc)?KCDB_MAXCB_SHORT_DESC:KCDB_MAXCB_NAME; + } else { + str = (t->ct.long_desc)?t->ct.long_desc:((t->ct.short_desc)?t->ct.short_desc:t->ct.name); + maxs = (t->ct.long_desc)?KCDB_MAXCB_LONG_DESC:((t->ct.short_desc)?KCDB_MAXCB_SHORT_DESC:KCDB_MAXCB_NAME); + } + StringCbLength(str, maxs, &s); + s += sizeof(wchar_t); + if(!buf || *cbbuf < s) { + *cbbuf = s; + rv = KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(buf, *cbbuf, str); + *cbbuf = s; + } + } else { + if(buf && *cbbuf > 0) + *buf = L'\0'; + *cbbuf = 0; + rv = KHM_ERROR_NOT_FOUND; + } + LeaveCriticalSection(&cs_credtype); + + return rv; +} + + +KHMEXP khm_int32 KHMAPI kcdb_credtype_get_name( + khm_int32 id, + wchar_t * buf, + khm_size * cbbuf) +{ + size_t s; + kcdb_credtype_i * t; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!cbbuf || id < 0 || id > KCDB_CREDTYPE_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + t = kcdb_credtype_tbl[id]; + if(t) { + StringCbLength(t->ct.name, KCDB_MAXCB_NAME, &s); + s += sizeof(wchar_t); + if(!buf || *cbbuf < s) { + *cbbuf = s; + rv = KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(buf, *cbbuf, t->ct.name); + *cbbuf = s; + } + } else { + *cbbuf = 0; + rv = KHM_ERROR_NOT_FOUND; + } + LeaveCriticalSection(&cs_credtype); + + return rv; +} + +KHMEXP khm_int32 KHMAPI kcdb_credtype_get_id( + const wchar_t * name, + khm_int32 * id) +{ + int i; + + *id = 0; + if(!name) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + for(i=0;i <= KCDB_CREDTYPE_MAX_ID; i++) { + if(kcdb_credtype_tbl[i] && !wcscmp(name, kcdb_credtype_tbl[i]->ct.name)) + break; + } + LeaveCriticalSection(&cs_credtype); + + if(i <= KCDB_CREDTYPE_MAX_ID) { + *id = i; + return KHM_ERROR_SUCCESS; + } else + return KHM_ERROR_NOT_FOUND; +} + +khm_int32 kcdb_credtype_get_next_free_id(khm_int32 * id) +{ + int i; + + EnterCriticalSection(&cs_credtype); + for(i=0;i <= KCDB_CREDTYPE_MAX_ID; i++) { + if(!kcdb_credtype_tbl[i]) + break; + } + LeaveCriticalSection(&cs_credtype); + + if(i <= KCDB_CREDTYPE_MAX_ID) { + *id = i; + return KHM_ERROR_SUCCESS; + } else { + *id = -1; + return KHM_ERROR_NO_RESOURCES; + } +} + +khm_int32 kcdb_credtype_hold(kcdb_credtype_i * ict) { + + if(!ict) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + ict->refcount++; + LeaveCriticalSection(&cs_credtype); + return KHM_ERROR_SUCCESS; +} + +khm_int32 kcdb_credtype_release(kcdb_credtype_i * ict) { + + if(!ict) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_credtype); + ict->refcount--; + kcdb_credtype_check_and_delete(ict->ct.id); + LeaveCriticalSection(&cs_credtype); + return KHM_ERROR_SUCCESS; +} + +void kcdb_credtype_msg_completion(kmq_message * m) +{ + kcdb_credtype_release((kcdb_credtype_i *) m->vparam); +} + +void kcdb_credtype_post_message(khm_int32 op, kcdb_credtype * type) +{ + kcdb_credtype_hold((kcdb_credtype_i *) type); + kmq_post_message(KMSG_KCDB, KMSG_KCDB_CREDTYPE, op, (void *) type); +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/credtype.h b/krb5-1-6/src/windows/identity/kcreddb/credtype.h new file mode 100644 index 000000000..3bb0a7d5e --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/credtype.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCDB_CREDTYPE_H +#define __KHIMAIRA_KCDB_CREDTYPE_H + +/* credtype */ +typedef struct kcdb_credtype_i_t { + kcdb_credtype ct; + khm_int32 refcount; + khm_int32 flags; + + struct kcdb_credtype_i_t * next; + struct kcdb_credtype_i_t * prev; +} kcdb_credtype_i; + +#define KCDB_CTI_FLAG_DELETED 8 + +extern CRITICAL_SECTION cs_credtype; +extern kcdb_credtype_i * kcdb_credtypes; +extern kcdb_credtype_i ** kcdb_credtype_tbl; + +void kcdb_credtype_init(void); +void kcdb_credtype_exit(void); +void kcdb_credtype_check_and_delete(khm_int32 id); +khm_int32 kcdb_credtype_hold(kcdb_credtype_i * ict); +khm_int32 kcdb_credtype_release(kcdb_credtype_i * ict); +void kcdb_credtype_msg_completion(kmq_message * m); +void kcdb_credtype_post_message(khm_int32 op, kcdb_credtype * type); +khm_int32 kcdb_credtype_get_next_free_id(khm_int32 * id); + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/identity.c b/krb5-1-6/src/windows/identity/kcreddb/identity.c new file mode 100644 index 000000000..78cdedbf6 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/identity.c @@ -0,0 +1,1599 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> +#include<assert.h> + +static CRITICAL_SECTION cs_ident; +hashtable * kcdb_identities_namemap = NULL; +khm_int32 kcdb_n_identities = 0; +kcdb_identity * kcdb_identities = NULL; +kcdb_identity * kcdb_def_identity = NULL; +khm_handle kcdb_ident_sub = NULL; /* identity provider */ +khm_int32 kcdb_ident_cred_type = KCDB_CREDTYPE_INVALID; +/* primary credentials type */ +khm_ui_4 kcdb_ident_refresh_cycle = 0; +khm_boolean kcdb_checked_config = FALSE; +khm_boolean kcdb_checking_config = FALSE; + +KHMEXP khm_boolean KHMAPI +kcdb_identity_is_equal(khm_handle identity1, + khm_handle identity2) +{ + + return (identity1 == identity2); + +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_provider(khm_handle sub) +{ + EnterCriticalSection(&cs_ident); + if (sub != kcdb_ident_sub) { + if(kcdb_ident_sub != NULL) { + kmq_send_sub_msg(kcdb_ident_sub, + KMSG_IDENT, + KMSG_IDENT_EXIT, + 0, + 0); + kmq_delete_subscription(kcdb_ident_sub); + } + kcdb_ident_sub = sub; + + if (kcdb_ident_sub) + kmq_send_sub_msg(kcdb_ident_sub, + KMSG_IDENT, + KMSG_IDENT_INIT, + 0, + 0); + } + LeaveCriticalSection(&cs_ident); + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_provider(khm_handle * sub) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) + rv = KHM_ERROR_SUCCESS; + else + rv = KHM_ERROR_NOT_FOUND; + if(sub != NULL) + *sub = kcdb_ident_sub; + LeaveCriticalSection(&cs_ident); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_type(khm_int32 cred_type) +{ + EnterCriticalSection(&cs_ident); + kcdb_ident_cred_type = cred_type; + LeaveCriticalSection(&cs_ident); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_type(khm_int32 * ptype) +{ + if (!ptype) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_ident); + *ptype = kcdb_ident_cred_type; + LeaveCriticalSection(&cs_ident); + + if (*ptype >= 0) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +/* message completion routine */ +void +kcdbint_ident_msg_completion(kmq_message * m) { + kcdb_identity_release(m->vparam); +} + +void +kcdbint_ident_add_ref(const void * key, void * vid) { + /* References in the hashtable are not refcounted */ + + // kcdb_identity_hold(vid); +} + +void +kcdbint_ident_del_ref(const void * key, void * vid) { + /* References in the hashtable are not refcounted */ + + // kcdb_identity_release(vid); +} + +void +kcdbint_ident_init(void) { + InitializeCriticalSection(&cs_ident); + kcdb_identities_namemap = hash_new_hashtable( + KCDB_IDENT_HASHTABLE_SIZE, + hash_string, + hash_string_comp, + kcdbint_ident_add_ref, + kcdbint_ident_del_ref); +} + +void +kcdbint_ident_exit(void) { + EnterCriticalSection(&cs_ident); + hash_del_hashtable(kcdb_identities_namemap); + LeaveCriticalSection(&cs_ident); + DeleteCriticalSection(&cs_ident); +} + +/* NOT called with cs_ident held */ +KHMEXP khm_boolean KHMAPI +kcdb_identity_is_valid_name(const wchar_t * name) +{ + khm_int32 rv; + + /* special case. Note since the string we are comparing with is + of a known length we don't need to check the length of name. */ + if (!wcscmp(name, L"_Schema")) + return FALSE; + + rv = kcdb_identpro_validate_name(name); + + if(rv == KHM_ERROR_NO_PROVIDER || + rv == KHM_ERROR_NOT_IMPLEMENTED) + return TRUE; + else + return KHM_SUCCEEDED(rv); +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_create(const wchar_t *name, + khm_int32 flags, + khm_handle * result) { + kcdb_identity * id = NULL; + kcdb_identity * id_tmp = NULL; + size_t namesize; + + if(!result || !name) + return KHM_ERROR_INVALID_PARAM; + + *result = NULL; + + /* is it there already? */ + EnterCriticalSection(&cs_ident); + id = hash_lookup(kcdb_identities_namemap, (void *) name); + if(id) + kcdb_identity_hold((khm_handle) id); + LeaveCriticalSection(&cs_ident); + + if(id) { + *result = (khm_handle) id; + return KHM_ERROR_SUCCESS; + } else if(!(flags & KCDB_IDENT_FLAG_CREATE)) { + return KHM_ERROR_NOT_FOUND; + } + + flags &= ~KCDB_IDENT_FLAG_CREATE; + + /* nope. create it */ + if((flags & ~KCDB_IDENT_FLAGMASK_RDWR) || + (flags & (KCDB_IDENT_FLAG_DEFAULT | + KCDB_IDENT_FLAG_SEARCHABLE | + KCDB_IDENT_FLAG_STICKY))) { + /* can't specify this flag in create */ + return KHM_ERROR_INVALID_PARAM; + } + + if(!kcdb_identity_is_valid_name(name)) { + return KHM_ERROR_INVALID_NAME; + } + + /* we expect the following will succeed since the above + test passed */ + StringCbLength(name, KCDB_IDENT_MAXCB_NAME, &namesize); + namesize += sizeof(wchar_t); + + id = PMALLOC(sizeof(kcdb_identity)); + ZeroMemory(id, sizeof(kcdb_identity)); + id->magic = KCDB_IDENT_MAGIC; + id->name = PMALLOC(namesize); + StringCbCopy(id->name, namesize, name); + + id->flags = (flags & KCDB_IDENT_FLAGMASK_RDWR); + id->flags |= KCDB_IDENT_FLAG_ACTIVE | KCDB_IDENT_FLAG_EMPTY; + LINIT(id); + + EnterCriticalSection(&cs_ident); + id_tmp = hash_lookup(kcdb_identities_namemap, (void *) id->name); + if(id_tmp) { + /* lost a race */ + kcdb_identity_hold((khm_handle) id_tmp); + *result = (khm_handle) id_tmp; + + PFREE(id->name); + PFREE(id); + + id = NULL; + } else { + khm_handle h_cfg; + + kcdb_identity_hold((khm_handle) id); + hash_add(kcdb_identities_namemap, + (void *) id->name, + (void *) id); + LPUSH(&kcdb_identities, id); + + if(KHM_SUCCEEDED(kcdb_identity_get_config((khm_handle) id, + 0, + &h_cfg))) { + /* don't need to set the KCDB_IDENT_FLAG_CONFIG flags + since kcdb_identity_get_config() sets it for us. */ + khm_int32 sticky; + + if (KHM_SUCCEEDED(khc_read_int32(h_cfg, L"Sticky", &sticky)) && + sticky) { + id->flags |= KCDB_IDENT_FLAG_STICKY; + } + + khc_close_space(h_cfg); + } + } + LeaveCriticalSection(&cs_ident); + + if(id != NULL) { + *result = (khm_handle) id; + + kcdb_identpro_notify_create((khm_handle) id); + + kcdbint_ident_post_message(KCDB_OP_INSERT, id); + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_delete(khm_handle vid) { + kcdb_identity * id; + khm_int32 code = KHM_ERROR_SUCCESS; + + EnterCriticalSection(&cs_ident); + if(!kcdb_is_identity(vid)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + id = (kcdb_identity *) vid; + + if (kcdb_is_active_identity(vid)) { + + id->flags &= ~KCDB_IDENT_FLAG_ACTIVE; + + hash_del(kcdb_identities_namemap, (void *) id->name); + + LeaveCriticalSection(&cs_ident); + + kcdbint_ident_post_message(KCDB_OP_DELETE, id); + + /* Once everybody finishes dealing with the identity deletion, + we will get called again. */ + return KHM_ERROR_SUCCESS; + } else if (id->refcount == 0) { + /* If the identity is not active, it is not in the hashtable + either */ + LDELETE(&kcdb_identities, id); + + if (id->name) + PFREE(id->name); + PFREE(id); + } + /* else, we have an identity that is not active, but has + outstanding references. We have to wait until those references + are freed. Once they are released, kcdb_identity_delete() will + be called again. */ + + _exit: + LeaveCriticalSection(&cs_ident); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_flags(khm_handle vid, + khm_int32 flag, + khm_int32 mask) { + kcdb_identity * id; + khm_int32 oldflags; + khm_int32 newflags; + khm_int32 delta = 0; + khm_int32 rv; + + if (mask == 0) + return KHM_ERROR_SUCCESS; + + if(!kcdb_is_active_identity(vid)) + return KHM_ERROR_INVALID_PARAM; + + id = (kcdb_identity *) vid; + + flag &= mask; + + if((mask & ~KCDB_IDENT_FLAGMASK_RDWR) || + ((flag & KCDB_IDENT_FLAG_INVALID) && (flag & KCDB_IDENT_FLAG_VALID))) + return KHM_ERROR_INVALID_PARAM; + + if((mask & KCDB_IDENT_FLAG_DEFAULT) && + (flag & KCDB_IDENT_FLAG_DEFAULT)) { + /* kcdb_identity_set_default already does checking for + redundant transitions */ + rv = kcdb_identity_set_default(vid); + + if(KHM_FAILED(rv)) + return rv; + + mask &= ~KCDB_IDENT_FLAG_DEFAULT; + flag &= ~KCDB_IDENT_FLAG_DEFAULT; + } + + EnterCriticalSection(&cs_ident); + + if(mask & KCDB_IDENT_FLAG_SEARCHABLE) { + if(!(flag & KCDB_IDENT_FLAG_SEARCHABLE)) { + if(id->flags & KCDB_IDENT_FLAG_SEARCHABLE) { + LeaveCriticalSection(&cs_ident); + rv = kcdb_identpro_set_searchable(vid, FALSE); + EnterCriticalSection(&cs_ident); + if(rv == KHM_ERROR_NO_PROVIDER || + KHM_SUCCEEDED(rv)) { + id->flags &= ~KCDB_IDENT_FLAG_SEARCHABLE; + delta |= KCDB_IDENT_FLAG_SEARCHABLE; + } + } + } else { + if(!(id->flags & KCDB_IDENT_FLAG_SEARCHABLE)) { + LeaveCriticalSection(&cs_ident); + rv = kcdb_identpro_set_searchable(vid, TRUE); + EnterCriticalSection(&cs_ident); + if(rv == KHM_ERROR_NO_PROVIDER || + KHM_SUCCEEDED(rv)) { + id->flags |= KCDB_IDENT_FLAG_SEARCHABLE; + delta |= KCDB_IDENT_FLAG_SEARCHABLE; + } + } + } + + flag &= ~KCDB_IDENT_FLAG_SEARCHABLE; + mask &= ~KCDB_IDENT_FLAG_SEARCHABLE; + } + + if (mask & KCDB_IDENT_FLAG_STICKY) { + if ((flag ^ id->flags) & KCDB_IDENT_FLAG_STICKY) { + khm_handle h_conf; + + if (KHM_SUCCEEDED(kcdb_identity_get_config(vid, + KHM_FLAG_CREATE, + &h_conf))) { + khc_write_int32(h_conf, L"Sticky", + !!(flag & KCDB_IDENT_FLAG_STICKY)); + khc_close_space(h_conf); + } + + id->flags = + ((id->flags & ~KCDB_IDENT_FLAG_STICKY) | + (flag & KCDB_IDENT_FLAG_STICKY)); + + delta |= KCDB_IDENT_FLAG_STICKY; + } + + flag &= ~KCDB_IDENT_FLAG_STICKY; + mask &= ~KCDB_IDENT_FLAG_STICKY; + } + + /* deal with every other flag */ + + oldflags = id->flags; + + id->flags = (id->flags & ~mask) | (flag & mask); + + if (flag & KCDB_IDENT_FLAG_VALID) { + id->flags &= ~(KCDB_IDENT_FLAG_INVALID | KCDB_IDENT_FLAG_UNKNOWN); + } + if (flag & KCDB_IDENT_FLAG_INVALID) { + id->flags &= ~(KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_UNKNOWN); + } + + newflags = id->flags; + + LeaveCriticalSection(&cs_ident); + + delta |= newflags ^ oldflags; + + if((delta & KCDB_IDENT_FLAG_HIDDEN)) { + kcdbint_ident_post_message( + (newflags & KCDB_IDENT_FLAG_HIDDEN)?KCDB_OP_HIDE:KCDB_OP_UNHIDE, + vid); + } + + if((delta & KCDB_IDENT_FLAG_SEARCHABLE)) { + kcdbint_ident_post_message( + (newflags & KCDB_IDENT_FLAG_SEARCHABLE)?KCDB_OP_SETSEARCH:KCDB_OP_UNSETSEARCH, + vid); + } + + if(delta != 0) + kcdbint_ident_post_message(KCDB_OP_MODIFY, vid); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_flags(khm_handle vid, + khm_int32 * flags) { + kcdb_identity * id; + + *flags = 0; + + if(!kcdb_is_active_identity(vid)) + return KHM_ERROR_INVALID_PARAM; + + id = (kcdb_identity *) vid; + + EnterCriticalSection(&cs_ident); + *flags = id->flags; + LeaveCriticalSection(&cs_ident); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_name(khm_handle vid, + wchar_t * buffer, + khm_size * pcbsize) { + size_t namesize; + kcdb_identity * id; + + if(!kcdb_is_active_identity(vid) || !pcbsize) + return KHM_ERROR_INVALID_PARAM; + + id = (kcdb_identity *) vid; + + if(FAILED(StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &namesize))) + return KHM_ERROR_UNKNOWN; + + namesize += sizeof(wchar_t); + + if(!buffer || namesize > *pcbsize) { + *pcbsize = namesize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *pcbsize, id->name); + *pcbsize = namesize; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_default(khm_handle * pvid) { + khm_handle def; + + if (pvid == NULL) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_ident); + def = kcdb_def_identity; + if (def != NULL) + kcdb_identity_hold(def); + LeaveCriticalSection(&cs_ident); + + *pvid = def; + + if (def != NULL) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +static khm_int32 +kcdbint_ident_set_default(khm_handle vid, + khm_boolean invoke_identpro) { + kcdb_identity * new_def; + kcdb_identity * old_def; + khm_int32 rv; + + if (vid != NULL && !kcdb_is_active_identity(vid)) + return KHM_ERROR_INVALID_PARAM; + + new_def = (kcdb_identity *)vid; + + if (new_def != NULL && (new_def->flags & KCDB_IDENT_FLAG_DEFAULT)) + return KHM_ERROR_SUCCESS; + + if ((new_def == NULL && kcdb_def_identity == NULL) || + (new_def == kcdb_def_identity)) + return KHM_ERROR_SUCCESS; + + /* first check with the identity provider if this operation + is permitted. */ + if (invoke_identpro) { + rv = kcdb_identpro_set_default(vid); + if(rv != KHM_ERROR_NO_PROVIDER && KHM_FAILED(rv)) + return rv; + } + + EnterCriticalSection(&cs_ident); + + old_def = kcdb_def_identity; + kcdb_def_identity = new_def; + + if(old_def != new_def) { + if(old_def) { + old_def->flags &= ~KCDB_IDENT_FLAG_DEFAULT; + kcdb_identity_release((khm_handle) old_def); + } + + if(new_def) { + new_def->flags |= KCDB_IDENT_FLAG_DEFAULT; + kcdb_identity_hold((khm_handle) new_def); + } + + LeaveCriticalSection(&cs_ident); + + /* if (invoke_identpro) */ + kcdbint_ident_post_message(KCDB_OP_NEW_DEFAULT, new_def); + } else { + LeaveCriticalSection(&cs_ident); + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_default(khm_handle vid) { + return kcdbint_ident_set_default(vid, TRUE); +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_default_int(khm_handle vid) { + return kcdbint_ident_set_default(vid, FALSE); +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_config(khm_handle vid, + khm_int32 flags, + khm_handle * result) { + khm_handle hkcdb; + khm_handle hidents = NULL; + khm_handle hident = NULL; + khm_int32 rv; + kcdb_identity * id; + + if(kcdb_is_active_identity(vid)) { + id = (kcdb_identity *) vid; + } else { + return KHM_ERROR_INVALID_PARAM; + } + + hkcdb = kcdb_get_config(); + if(hkcdb) { + rv = khc_open_space(hkcdb, L"Identity", 0, &hidents); + if(KHM_FAILED(rv)) + goto _exit; + + rv = khc_open_space(hidents, + id->name, + flags | KCONF_FLAG_NOPARSENAME, + &hident); + + if(KHM_FAILED(rv)) { + khm_int32 oldflags; + EnterCriticalSection(&cs_ident); + oldflags = id->flags; + id->flags &= ~KCDB_IDENT_FLAG_CONFIG; + LeaveCriticalSection(&cs_ident); + if (oldflags & KCDB_IDENT_FLAG_CONFIG) + kcdbint_ident_post_message(KCDB_OP_DELCONFIG, id); + goto _exit; + } + + EnterCriticalSection(&cs_ident); + id->flags |= KCDB_IDENT_FLAG_CONFIG; + LeaveCriticalSection(&cs_ident); + + *result = hident; + } else + rv = KHM_ERROR_UNKNOWN; + +_exit: + if(hidents) + khc_close_space(hidents); + if(hkcdb) + khc_close_space(hkcdb); + return rv; +} + +/*! \note cs_ident must be available. */ +void +kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id) { + kcdb_identity_hold(id); + kmq_post_message(KMSG_KCDB, KMSG_KCDB_IDENT, op, (void *) id); +} + +/*! \note cs_ident must be available. */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_hold(khm_handle vid) { + kcdb_identity * id; + + EnterCriticalSection(&cs_ident); + if(kcdb_is_active_identity(vid)) { + id = vid; + id->refcount++; + } else { + LeaveCriticalSection(&cs_ident); + return KHM_ERROR_INVALID_PARAM; + } + LeaveCriticalSection(&cs_ident); + return ERROR_SUCCESS; +} + +/*! \note cs_ident must be available. */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_release(khm_handle vid) { + kcdb_identity * id; + khm_int32 refcount; + + EnterCriticalSection(&cs_ident); + if(kcdb_is_identity(vid)) { + id = vid; + refcount = --id->refcount; + if(refcount == 0) { + /* We only delete identities which do not have a + configuration. */ + if (id->refcount == 0 && + !(id->flags & KCDB_IDENT_FLAG_CONFIG)) + kcdb_identity_delete(vid); + } + } else { + LeaveCriticalSection(&cs_ident); + return KHM_ERROR_INVALID_PARAM; + } + LeaveCriticalSection(&cs_ident); + return ERROR_SUCCESS; +} + +struct kcdb_idref_result { + kcdb_identity * ident; + khm_int32 flags; + khm_size count; +}; + +static khm_int32 KHMAPI +kcdbint_idref_proc(khm_handle cred, void * r) { + khm_handle vid; + struct kcdb_idref_result *result; + khm_int32 flags; + + result = (struct kcdb_idref_result *) r; + + if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred, &vid))) { + if (result->ident == (kcdb_identity *) vid) { + + result->count++; + kcdb_cred_get_flags(cred, &flags); + + if (flags & KCDB_CRED_FLAG_RENEWABLE) { + result->flags |= KCDB_IDENT_FLAG_CRED_RENEW; + if (flags & KCDB_CRED_FLAG_INITIAL) { + result->flags |= KCDB_IDENT_FLAG_RENEWABLE; + } + } + + if (flags & KCDB_CRED_FLAG_EXPIRED) { + result->flags |= KCDB_IDENT_FLAG_CRED_EXP; + if (flags & KCDB_CRED_FLAG_INITIAL) { + result->flags |= KCDB_IDENT_FLAG_EXPIRED; + } + } + + if (flags & KCDB_CRED_FLAG_INITIAL) { + result->flags |= KCDB_IDENT_FLAG_VALID; + } + } + + kcdb_identity_release(vid); + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_refresh(khm_handle vid) { + kcdb_identity * ident; + khm_int32 code = KHM_ERROR_SUCCESS; + struct kcdb_idref_result result; + + EnterCriticalSection(&cs_ident); + + if (!kcdb_is_active_identity(vid)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + ident = (kcdb_identity *) vid; + + result.ident = ident; + result.flags = 0; + result.count = 0; + + LeaveCriticalSection(&cs_ident); + + kcdb_credset_apply(NULL, kcdbint_idref_proc, &result); + + if (result.count == 0) + result.flags |= KCDB_IDENT_FLAG_EMPTY; + + kcdb_identity_set_flags(vid, result.flags, + KCDB_IDENT_FLAGMASK_RDWR & + ~(KCDB_IDENT_FLAG_DEFAULT | + KCDB_IDENT_FLAG_SEARCHABLE | + KCDB_IDENT_FLAG_STICKY)); + + EnterCriticalSection(&cs_ident); + ident->refresh_cycle = kcdb_ident_refresh_cycle; + + _exit: + LeaveCriticalSection(&cs_ident); + + if (code == 0) + code = kcdb_identpro_update(vid); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_refresh_all(void) { + kcdb_identity * ident; + kcdb_identity * next; + khm_int32 code = KHM_ERROR_SUCCESS; + int hit_count; + + EnterCriticalSection(&cs_ident); + + kcdb_ident_refresh_cycle++; + + /* The do-while loop is here to account for race conditions. We + release cs_ident in the for loop, so we don't actually have a + guarantee that we traversed the whole identity list at the end. + We repeat until all the identities are uptodate. */ + + do { + hit_count = 0; + + for (ident = kcdb_identities; + ident != NULL; + ident = next) { + + if (!kcdb_is_active_identity(ident) || + ident->refresh_cycle == kcdb_ident_refresh_cycle) { + next = LNEXT(ident); + continue; + } + + kcdb_identity_hold((khm_handle) ident); + + LeaveCriticalSection(&cs_ident); + + kcdb_identity_refresh((khm_handle) ident); + + EnterCriticalSection(&cs_ident); + + next = LNEXT(ident); + kcdb_identity_release((khm_handle) ident); + + hit_count++; + } + + } while (hit_count > 0); + + LeaveCriticalSection(&cs_ident); + + return code; +} + +/*****************************************/ +/* Custom property functions */ + +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_attr(khm_handle vid, + khm_int32 attr_id, + void * buffer, + khm_size cbbuf) +{ + kcdb_identity * id = NULL; + kcdb_attrib * attrib = NULL; + kcdb_type * type = NULL; + khm_size slot; + khm_size cbdest; + khm_int32 code = KHM_ERROR_SUCCESS; + + EnterCriticalSection(&cs_ident); + if(!kcdb_is_active_identity(vid)) { + LeaveCriticalSection(&cs_ident); + return KHM_ERROR_INVALID_PARAM; + } + + id = (kcdb_identity *) vid; + + if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS)) { + kcdb_buf_new(&id->buf, KCDB_BUF_DEFAULT); + id->flags |= KCDB_IDENT_FLAG_ATTRIBS; + } + + if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { + LeaveCriticalSection(&cs_ident); + return KHM_ERROR_INVALID_PARAM; + } + +#if 0 + /* actually, even if an attribute is computed, we still allow + those values to be set. This is because computing values + is only for credentials. If a computed value is used as a + property in any other object, it is treated as a regular value + */ + if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) + { + LeaveCriticalSection(&cs_ident); + kcdb_attrib_release_info(attrib); + return KHM_ERROR_INVALID_OPERATION; + } +#endif + + if (buffer == NULL) { + /* we are removing a value */ + slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id); + if (slot != KCDB_BUF_INVALID_SLOT && + kcdb_buf_exist(&id->buf, slot)) + kcdb_buf_alloc(&id->buf, slot, (khm_ui_2) attr_id, 0); + code = KHM_ERROR_SUCCESS; + goto _exit; + } + + if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { + LeaveCriticalSection(&cs_ident); + kcdb_attrib_release_info(attrib); + return KHM_ERROR_INVALID_PARAM; + } + + if(!(type->isValid(buffer,cbbuf))) { + code = KHM_ERROR_TYPE_MISMATCH; + goto _exit; + } + + if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + kcdb_buf_alloc(&id->buf, KCDB_BUF_APPEND, (khm_ui_2) attr_id, cbdest); + slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id); + if(slot == KCDB_BUF_INVALID_SLOT || !kcdb_buf_exist(&id->buf, slot)) { + code = KHM_ERROR_NO_RESOURCES; + goto _exit; + } + + if(KHM_FAILED(code = + type->dup(buffer, cbbuf, kcdb_buf_get(&id->buf, slot), &cbdest))) + { + kcdb_buf_alloc(&id->buf, slot, (khm_ui_2) attr_id, 0); + goto _exit; + } + + kcdb_buf_set_value_flag(&id->buf, slot); + +_exit: + LeaveCriticalSection(&cs_ident); + + if(attrib) + kcdb_attrib_release_info(attrib); + if(type) + kcdb_type_release_info(type); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_attrib(khm_handle vid, + const wchar_t * attr_name, + void * buffer, + khm_size cbbuf) +{ + khm_int32 attr_id = -1; + + if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id))) + return KHM_ERROR_INVALID_PARAM; + + return kcdb_identity_set_attr( + vid, + attr_id, + buffer, + cbbuf); +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attr(khm_handle vid, + khm_int32 attr_id, + khm_int32 * attr_type, + void * buffer, + khm_size * pcbbuf) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_identity * id = NULL; + kcdb_attrib * attrib = NULL; + kcdb_type * type = NULL; + khm_size slot; + + if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { + return KHM_ERROR_INVALID_PARAM; + } + + if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { + kcdb_attrib_release_info(attrib); + return KHM_ERROR_UNKNOWN; + } + + if(attr_type) + *attr_type = attrib->type; + + EnterCriticalSection(&cs_ident); + + if(!kcdb_is_active_identity(vid)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + id = (kcdb_identity *) vid; + + if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) || + (slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id)) == KCDB_BUF_INVALID_SLOT || + !kcdb_buf_val_exist(&id->buf, slot)) + { + code = KHM_ERROR_NOT_FOUND; + goto _exit; + } + + if(!buffer && !pcbbuf) { + /* in this case the caller is only trying to determine if the field + contains data. If we get here, then the value exists. */ + code = KHM_ERROR_SUCCESS; + goto _exit; + } + +#if 0 + if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { + /* we should never hit this case */ +#ifdef DEBUG + assert(FALSE); +#endif + code = KHM_ERROR_INVALID_OPERATION; + } else { +#endif + code = type->dup( + kcdb_buf_get(&id->buf, slot), + kcdb_buf_size(&id->buf, slot), + buffer, + pcbbuf); +#if 0 + } +#endif + +_exit: + LeaveCriticalSection(&cs_ident); + if(type) + kcdb_type_release_info(type); + if(attrib) + kcdb_attrib_release_info(attrib); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attrib(khm_handle vid, + const wchar_t * attr_name, + khm_int32 * attr_type, + void * buffer, + khm_size * pcbbuf) +{ + khm_int32 attr_id = -1; + + if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id))) + return KHM_ERROR_NOT_FOUND; + + return kcdb_identity_get_attr(vid, + attr_id, + attr_type, + buffer, + pcbbuf); +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attr_string(khm_handle vid, + khm_int32 attr_id, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags) +{ + khm_int32 code = KHM_ERROR_SUCCESS; + kcdb_identity * id = NULL; + kcdb_attrib * attrib = NULL; + kcdb_type * type = NULL; + khm_size slot; + + if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { + return KHM_ERROR_INVALID_PARAM; + } + + if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { + kcdb_attrib_release_info(attrib); + return KHM_ERROR_UNKNOWN; + } + + EnterCriticalSection(&cs_ident); + + if(!kcdb_is_active_identity(vid)) { + code = KHM_ERROR_INVALID_PARAM; + goto _exit; + } + + id = (kcdb_identity *) vid; + + if(!(id->flags & KCDB_IDENT_FLAG_ATTRIBS) || + (slot = kcdb_buf_slot_by_id(&id->buf, (khm_ui_2) attr_id)) == KCDB_BUF_INVALID_SLOT || + !kcdb_buf_val_exist(&id->buf, slot)) + { + code = KHM_ERROR_NOT_FOUND; + goto _exit; + } + + if(!buffer && !pcbbuf) { + /* in this case the caller is only trying to determine if the field + contains data. If we get here, then the value exists */ + code = KHM_ERROR_SUCCESS; + goto _exit; + } + +#if 0 + if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { +#ifdef DEBUG + assert(FALSE); +#endif + code = KHM_ERROR_INVALID_OPERATION; + } else { +#endif + if(kcdb_buf_exist(&id->buf, slot)) { + code = type->toString( + kcdb_buf_get(&id->buf, slot), + kcdb_buf_size(&id->buf, slot), + buffer, + pcbbuf, + flags); + } else + code = KHM_ERROR_NOT_FOUND; +#if 0 + } +#endif + +_exit: + LeaveCriticalSection(&cs_ident); + if(type) + kcdb_type_release_info(type); + if(attrib) + kcdb_attrib_release_info(attrib); + + return code; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attrib_string(khm_handle vid, + const wchar_t * attr_name, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags) +{ + khm_int32 attr_id = -1; + + if(KHM_FAILED(kcdb_attrib_get_id(attr_name, &attr_id))) + return KHM_ERROR_NOT_FOUND; + + return kcdb_identity_get_attr_string( + vid, + attr_id, + buffer, + pcbbuf, + flags); +} + +/*****************************************/ +/* Identity provider interface functions */ + +/* NOT called with cs_ident held */ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_validate_name(const wchar_t * name) +{ + kcdb_ident_name_xfer namex; + khm_handle sub; + khm_size cch; + khm_int32 rv = KHM_ERROR_SUCCESS; + + /* we need to verify the length and the contents of the string + before calling the identity provider */ + if(FAILED(StringCchLength(name, KCDB_IDENT_MAXCCH_NAME, &cch))) + return KHM_ERROR_TOO_LONG; + + /* We can't really make an assumption about the valid characters + in an identity. So we let the identity provider decide */ +#ifdef VALIDATE_IDENTIY_CHARACTERS + if(wcsspn(name, KCDB_IDENT_VALID_CHARS) != cch) + return KHM_ERROR_INVALID_NAME; +#endif + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + ZeroMemory(&namex, sizeof(namex)); + + namex.name_src = name; + namex.result = KHM_ERROR_NOT_IMPLEMENTED; + + kmq_send_sub_msg(sub, + KMSG_IDENT, + KMSG_IDENT_VALIDATE_NAME, + 0, + (void *) &namex); + + rv = namex.result; + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_validate_identity(khm_handle identity) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle sub; + + if(!kcdb_is_active_identity(identity)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + rv = kmq_send_sub_msg(sub, + KMSG_IDENT, + KMSG_IDENT_VALIDATE_IDENTITY, + 0, + (void *) identity); + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_canon_name(const wchar_t * name_in, + wchar_t * name_out, + khm_size * cb_name_out) +{ + khm_handle sub; + kcdb_ident_name_xfer namex; + wchar_t name_tmp[KCDB_IDENT_MAXCCH_NAME]; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_size cch; + + if(cb_name_out == 0 || + FAILED(StringCchLength(name_in, KCDB_IDENT_MAXCCH_NAME, &cch))) + return KHM_ERROR_INVALID_NAME; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + ZeroMemory(&namex, sizeof(namex)); + ZeroMemory(name_tmp, sizeof(name_tmp)); + + namex.name_src = name_in; + namex.name_dest = name_tmp; + namex.cb_name_dest = sizeof(name_tmp); + namex.result = KHM_ERROR_NOT_IMPLEMENTED; + + rv = kmq_send_sub_msg(sub, + KMSG_IDENT, + KMSG_IDENT_CANON_NAME, + 0, + (void *) &namex); + + if(KHM_SUCCEEDED(namex.result)) { + const wchar_t * name_result; + khm_size cb; + + if(name_in[0] != 0 && name_tmp[0] == 0) + name_result = name_tmp; + else + name_result = name_in; + + if(FAILED(StringCbLength(name_result, KCDB_IDENT_MAXCB_NAME, &cb))) + rv = KHM_ERROR_UNKNOWN; + else { + cb += sizeof(wchar_t); + if(name_out == 0 || *cb_name_out < cb) { + rv = KHM_ERROR_TOO_LONG; + *cb_name_out = cb; + } else { + StringCbCopy(name_out, *cb_name_out, name_result); + *cb_name_out = cb; + rv = KHM_ERROR_SUCCESS; + } + } + } + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_compare_name(const wchar_t * name1, + const wchar_t * name2) +{ + khm_handle sub; + kcdb_ident_name_xfer namex; + khm_int32 rv = 0; + + /* Generally in kcdb_identpro_* functions we don't emulate + any behavior if the provider is not available, but lacking + a way to make this known, we emulate here */ + rv = wcscmp(name1, name2); + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + ZeroMemory(&namex, sizeof(namex)); + namex.name_src = name1; + namex.name_alt = name2; + namex.result = rv; + + kmq_send_sub_msg(sub, + KMSG_IDENT, + KMSG_IDENT_COMPARE_NAME, + 0, + (void *) &namex); + + rv = namex.result; + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_set_default(khm_handle identity) +{ + khm_handle sub; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if((identity != NULL) && + !kcdb_is_active_identity(identity)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + rv = kmq_send_sub_msg(sub, + KMSG_IDENT, + KMSG_IDENT_SET_DEFAULT, + (identity != NULL), + (void *) identity); + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_set_searchable(khm_handle identity, + khm_boolean searchable) +{ + khm_handle sub; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!kcdb_is_active_identity(identity)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + rv = kmq_send_sub_msg( + sub, + KMSG_IDENT, + KMSG_IDENT_SET_SEARCHABLE, + searchable, + (void *) identity); + } + + return rv; +} + + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_update(khm_handle identity) +{ + khm_handle sub; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!kcdb_is_active_identity(identity)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + rv = kmq_send_sub_msg(sub, + KMSG_IDENT, + KMSG_IDENT_UPDATE, + 0, + (void *) identity); + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_notify_create(khm_handle identity) +{ + khm_handle sub; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!kcdb_is_active_identity(identity)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + rv = kmq_send_sub_msg( + sub, + KMSG_IDENT, + KMSG_IDENT_NOTIFY_CREATE, + 0, + (void *) identity); + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identpro_get_ui_cb(void * rock) +{ + khm_handle sub; + khm_int32 rv = KHM_ERROR_SUCCESS; + + EnterCriticalSection(&cs_ident); + if(kcdb_ident_sub != NULL) { + sub = kcdb_ident_sub; + } else { + sub = NULL; + rv = KHM_ERROR_NO_PROVIDER; + } + LeaveCriticalSection(&cs_ident); + + if(sub != NULL) { + rv = kmq_send_sub_msg( + sub, + KMSG_IDENT, + KMSG_IDENT_GET_UI_CALLBACK, + 0, + rock); + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kcdb_identity_enum(khm_int32 and_flags, + khm_int32 eq_flags, + wchar_t * name_buf, + khm_size * pcb_buf, + khm_size * pn_idents) +{ + kcdb_identity * id; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_size cb_req = 0; + khm_size n_idents = 0; + size_t cb_curr; + size_t cch_curr; + size_t cch_left; + HRESULT hr; + + if ((name_buf == NULL && pcb_buf == NULL && pn_idents == NULL) || + (name_buf != NULL && pcb_buf == NULL)) + return KHM_ERROR_INVALID_PARAM; + + eq_flags &= and_flags; + + EnterCriticalSection(&cs_ident); + + if (!kcdb_checked_config) { + khm_handle h_kcdb = NULL; + khm_handle h_idents = NULL; + khm_handle h_ident = NULL; + + kcdb_checked_config = TRUE; + kcdb_checking_config = TRUE; + + h_kcdb = kcdb_get_config(); + if (!h_kcdb) + goto _config_check_cleanup; + if(KHM_FAILED(khc_open_space(h_kcdb, L"Identity", 0, &h_idents))) + goto _config_check_cleanup; + + while(KHM_SUCCEEDED(khc_enum_subspaces(h_idents, + h_ident, + &h_ident))) { + + wchar_t wname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_handle t_id; + + cb = sizeof(wname); + if (KHM_FAILED(khc_get_config_space_name(h_ident, + wname, + &cb))) + continue; + + LeaveCriticalSection(&cs_ident); + + if (KHM_SUCCEEDED(kcdb_identity_create(wname, + KCDB_IDENT_FLAG_CREATE, + &t_id))) + kcdb_identity_release(t_id); + + EnterCriticalSection(&cs_ident); + } + + _config_check_cleanup: + if (h_kcdb) + khc_close_space(h_kcdb); + if (h_idents) + khc_close_space(h_idents); + + kcdb_checking_config = FALSE; + } + + for ( id = kcdb_identities; + id != NULL; + id = LNEXT(id) ) { + if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) == + KCDB_IDENT_FLAG_ACTIVE) && + ((id->flags & and_flags) == eq_flags)) { + n_idents ++; + hr = StringCbLength(id->name, KCDB_IDENT_MAXCB_NAME, &cb_curr); +#ifdef DEBUG + assert(SUCCEEDED(hr)); +#endif + cb_req += cb_curr + sizeof(wchar_t); + } + } + + cb_req += sizeof(wchar_t); + + if (pn_idents != NULL) + *pn_idents = n_idents; + + if (pcb_buf != NULL && (name_buf == NULL || *pcb_buf < cb_req)) { + *pcb_buf = cb_req; + + rv = KHM_ERROR_TOO_LONG; + } else if(name_buf != NULL) { + cch_left = (*pcb_buf) / sizeof(wchar_t); + + for (id = kcdb_identities; + id != NULL; + id = LNEXT(id)) { + if (((id->flags & KCDB_IDENT_FLAG_ACTIVE) == + KCDB_IDENT_FLAG_ACTIVE) && + ((id->flags & and_flags) == eq_flags)) { + StringCchLength(id->name, KCDB_IDENT_MAXCCH_NAME, + &cch_curr); + cch_curr++; + StringCchCopy(name_buf, cch_left, id->name); + cch_left -= cch_curr; + name_buf += cch_curr; + } + } + + *name_buf = L'\0'; + *pcb_buf = cb_req; + } + + LeaveCriticalSection(&cs_ident); + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/identity.h b/krb5-1-6/src/windows/identity/kcreddb/identity.h new file mode 100644 index 000000000..ba55a201b --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/identity.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCDB_IDENTITY_H +#define __KHIMAIRA_KCDB_IDENTITY_H + +/* Identity */ + +#define KCDB_IDENT_HASHTABLE_SIZE 31 + +typedef struct kcdb_identity_t { + khm_int32 magic; + wchar_t * name; + khm_int32 flags; + khm_int32 refcount; + kcdb_buf buf; + khm_ui_4 refresh_cycle; + LDCL(struct kcdb_identity_t); +} kcdb_identity; + +#define KCDB_IDENT_MAGIC 0x31938d4f + +extern hashtable * kcdb_identities_namemap; +extern khm_int32 kcdb_n_identities; +extern kcdb_identity * kcdb_identities; /* all identities */ +extern kcdb_identity * kcdb_def_identity; /* default identity */ +extern khm_ui_4 kcdb_ident_refresh_cycle; + +void kcdbint_ident_init(void); +void kcdbint_ident_exit(void); +void kcdbint_ident_msg_completion(kmq_message * m); +void kcdbint_ident_post_message(khm_int32 op, kcdb_identity * id); + +#define kcdb_is_identity(id) ((id) && ((kcdb_identity *)(id))->magic == KCDB_IDENT_MAGIC) +#define kcdb_is_active_identity(id) (kcdb_is_identity(id) && (((kcdb_identity *)(id))->flags & KCDB_IDENT_FLAG_ACTIVE)) + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/init.c b/krb5-1-6/src/windows/identity/kcreddb/init.c new file mode 100644 index 000000000..cea97a8c7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/init.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> + +/* set to TRUE when the configuration is loaded */ +static int kcdb_config_loaded = 0; + +/* global state cs */ +static CRITICAL_SECTION cs_kcdb_global; + +/* forward dcl */ +void KHMAPI kcdb_msg_completion(kmq_message * m); + +void kcdb_init(void) { + /* setup the critical sections */ + InitializeCriticalSection(&cs_kcdb_global); + + kmq_set_completion_handler(KMSG_KCDB, kcdb_msg_completion); + + kcdb_credtype_init(); + kcdbint_ident_init(); + kcdb_credset_init(); + kcdb_cred_init(); + kcdb_type_init(); + kcdb_attrib_init(); +} + +void kcdb_exit(void) { + + kcdb_attrib_exit(); + kcdb_type_exit(); + kcdb_cred_exit(); + kcdb_credset_exit(); + kcdbint_ident_exit(); + kcdb_credtype_exit(); + + kmq_set_completion_handler(KMSG_KCDB, NULL); + + DeleteCriticalSection(&cs_kcdb_global); +} + +khm_handle kcdb_get_config(void) { + khm_handle space = NULL; + + EnterCriticalSection(&cs_kcdb_global); + if(!kcdb_config_loaded) { + khc_load_schema(NULL, schema_kcdbconfig); + kcdb_config_loaded = 1; + } + khc_open_space(NULL, L"KCDB", 0, &space); + LeaveCriticalSection(&cs_kcdb_global); + + return space; +} + +void KHMAPI kcdb_msg_completion(kmq_message * m) { + if(!m) + return; + if(m->subtype == KMSG_KCDB_IDENT) + kcdbint_ident_msg_completion(m); + else if(m->subtype == KMSG_KCDB_ATTRIB) + kcdb_attrib_msg_completion(m); + else if(m->subtype == KMSG_KCDB_TYPE) + kcdb_type_msg_completion(m); + else if(m->subtype == KMSG_KCDB_CREDTYPE) + kcdb_credtype_msg_completion(m); +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/kcdbconfig.csv b/krb5-1-6/src/windows/identity/kcreddb/kcdbconfig.csv new file mode 100644 index 000000000..f4b52eea2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/kcdbconfig.csv @@ -0,0 +1,15 @@ +Name,Type,Value,Description +KCDB,KC_SPACE,0,Khimaira Configuration DB + Identity,KC_SPACE,0,Configuration space for identities + _Schema,KC_SPACE,0,Schema for identities + Sticky,KC_INT32,0,Boolean. Is this a sticky identity? + Monitor,KC_INT32,1,Boolean. Enables monitoring the identity + WarnThreshold,KC_INT32,900,In seconds + AllowWarn,KC_INT32,1,Boolean. Allow warning. + CriticalThreshold,KC_INT32,60,In seconds + AllowCritical,KC_INT32,1,Boolean. Allow critical. + AutoRenewThreshold,KC_INT32,60,In seconds + AllowAutoRenew,KC_INT32,1,Boolean. + _Schema,KC_ENDSPACE,0, + Identity,KC_ENDSPACE,0, +KCDB,KC_ENDSPACE,0, diff --git a/krb5-1-6/src/windows/identity/kcreddb/kcreddb.h b/krb5-1-6/src/windows/identity/kcreddb/kcreddb.h new file mode 100644 index 000000000..6621d43cc --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/kcreddb.h @@ -0,0 +1,3329 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCREDDB_H__ +#define __KHIMAIRA_KCREDDB_H__ + +#include<khdefs.h> +#include<time.h> + + +/*! \defgroup kcdb NetIDMgr Credentials Database */ +/*@{*/ + +/*! \brief Maximum length in characters of short description + + The length includes the terminating \a NULL character. + */ +#define KCDB_MAXCCH_SHORT_DESC 256 + +/*! \brief Maximum length in bytes of short description + + The length includes the terminating \a NULL character. + */ +#define KCDB_MAXCB_SHORT_DESC (sizeof(wchar_t) * KCDB_MAXCCH_SHORT_DESC) + +/*! \brief Maximum length in characters of long description + + The length includes the terminating \a NULL character. + */ +#define KCDB_MAXCCH_LONG_DESC 8192 + +/*! \brief Maximum length in characters of long description + + The length includes the terminating \a NULL character. + */ +#define KCDB_MAXCB_LONG_DESC (sizeof(wchar_t) * KCDB_MAXCCH_LONG_DESC) + +/*! \brief Maximum length in characters of name + + The length includes the terminating \a NULL character. + */ +#define KCDB_MAXCCH_NAME 256 + +/*! \brief Maximum length in bytes of short description + + The length includes the terminating \a NULL character. + */ +#define KCDB_MAXCB_NAME (sizeof(wchar_t) * KCDB_MAXCCH_NAME) + +/*! \brief Automatically determine the number of bytes required + + Can be used in most places where a count of bytes is required. + For many objects, the number of bytes that are required can be + determined through context and may be ommited. In such cases you + can use the \a KCDB_CBSIZE_AUTO value to specify that the function + is to determine the size automatically. + + \note Not all functions that take a count of bytes support the \a + KCDB_CBSIZE_AUTO value. +*/ +#define KCDB_CBSIZE_AUTO ((khm_size) -1) + +/*! +\defgroup kcdb_ident Identities + +Functions, macros etc. for manipulating identities. +*/ + +/*@{*/ + +/*! \brief The maximum number of characters (including terminator) that can + be specified as an identity name */ +#define KCDB_IDENT_MAXCCH_NAME 256 + +/*! \brief The maximum number of bytes that can be specified as an identity + name */ +#define KCDB_IDENT_MAXCB_NAME (sizeof(wchar_t) * KCDB_IDENT_MAXCCH_NAME) + +/*! \brief Valid characters in an identity name */ +#define KCDB_IDENT_VALID_CHARS L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._@-/" + +/*! +\name Flags for identities */ +/*@{*/ + +/*! \brief Create the identity if it doesn't already exist. + \note Only to be used with kcdb_identity_create() */ +#define KCDB_IDENT_FLAG_CREATE 0x10000000L + +/*! \brief Has configuration information + + Indicates that the identity has persistent configuration + information associated with it. + */ +#define KCDB_IDENT_FLAG_CONFIG 0x00800000L + +/*! \brief Marks the identity as active. + + An active identity is one that is in active use within NetIDMgr. + + \note This flag is readonly and cannot be specified when creating + or modifying an identity. Once an identity is deleted, it will + no longer have this flag. */ +#define KCDB_IDENT_FLAG_ACTIVE 0x02000000L + + +/*! \brief The identity has custom attributes assigned + */ +#define KCDB_IDENT_FLAG_ATTRIBS 0x08000000L + +/*! \brief This is the default identity. + + At most one identity will have this flag set at any given time. + To set or reset the flag, use kcdb_identity_set_default() */ +#define KCDB_IDENT_FLAG_DEFAULT 0x00000001L + +/*! \brief This identity can be searched. + + The meaning of this flag is left to be interpreted by individual + plugins. */ +#define KCDB_IDENT_FLAG_SEARCHABLE 0x00000002L + +/*! \brief Hidden identity. + + The identity will not show up in the identity list window. Once + the hidden is switched off, the identity (and all associated + credentials) will re-appear in the window */ +#define KCDB_IDENT_FLAG_HIDDEN 0x00000004L + +/*! \brief Invalid identity + + For one reason or another, this identity is invalid. This flag + can be set by an identity provider to indicate that this identity + does not correspond to an actual identity because an external + entity (such as a KDC) has denied it's existence. + + The absence of this flag does not imply that the identity is + valid. The ::KCDB_IDENT_FLAG_VALID bit must be set for that to be + the case. If neither flag is set, then the status of the identity + is not known. +*/ +#define KCDB_IDENT_FLAG_INVALID 0x00000008L + +/*! \brief Valid identity + + The identity has been validated through an external entity, or + it's validity implied through the existence of credentials for the + identity. + + The absence of this flag does not imply that the identity is + invalid. The ::KCDB_IDENT_FLAG_INVALID bit must be set for that + to be the case. If neither flag is set, then the status of the + identity is not known. + */ +#define KCDB_IDENT_FLAG_VALID 0x00000010L + +/*! \brief Expired identity + + This identity has expired and can not be actively used to obtain + credentials. This determination is made based on the input of + some external entity. This flag may only be set by an identity + provider. +*/ +#define KCDB_IDENT_FLAG_EXPIRED 0x00000020L + +/*! \brief Empty identity + + The identity does not have actual credentials associated with it. + */ +#define KCDB_IDENT_FLAG_EMPTY 0x00000040L + +/*! \brief Renewable identity + + The initial credentials associated with this identity are + renewable. Thus making the whole identity renewable. + */ +#define KCDB_IDENT_FLAG_RENEWABLE 0x00000080L + +/*! \brief Required user interaction + + The identity is in a state which requires user interaction to + activate. Currently, the identity may not be in a state where it + can be used to obtain credentials. + + A typical example of this is when the primary password for an + identity has expired. + */ +#define KCDB_IDENT_FLAG_INTERACT 0x00000100L + +/*! \brief Has expired credentials + + The identity has expired credentials associated with it. + */ +#define KCDB_IDENT_FLAG_CRED_EXP 0x00000200L + +/*! \brief Has renewable credentials + + The identity has renewable credentials associated with it. If the + initial credentials of the identity are renewable, then identity + is renewable. Hence the ::KCDB_IDENT_FLAG_RENEWABLE should also + be set. + */ +#define KCDB_IDENT_FLAG_CRED_RENEW 0x00000400L + +/*! \brief Sticky identity + + Sticky identities are identities that are always visible in the + credentials display even if no credentials are associated with it. + */ +#define KCDB_IDENT_FLAG_STICKY 0x00000800L + +/*! \brief Unknown state + + The validity of the identity cannot be determined. This usually + means that an authority could not be contacted. This flag is to + be treated as transient. If ::KCDB_IDENT_FLAG_INVALID or + ::KCDB_IDENT_FLAG_VALID is set for the identity, this flag is to + be ignored. + */ +#define KCDB_IDENT_FLAG_UNKNOWN 0x00001000L + +/*! \brief Read/write flags mask. + + A bitmask that correspond to all the read/write flags in the mask. +*/ +#define KCDB_IDENT_FLAGMASK_RDWR 0x00001fffL + +/*@}*/ + +/*! \name Identity Provider Data Structures +@{*/ + +/*! \brief Name transfer structure + + Used when the KCDB is communicating with the identity provider to + exchange string names of identities. See individual ::KMSG_IDENT + message subtypes for the usage of this structure. + */ +typedef struct tag_kcdb_ident_name_xfer { + const wchar_t * name_src; /*!< An identity name. Does not + exceed KCDB_IDENT_MAXCCH_NAME + characters including terminating + NULL. */ + const wchar_t * name_alt; /*!< An identity name. Does not + exceed KCDB_IDENT_MAXCCH_NAME + characters including terminating + NULL. */ + wchar_t * name_dest; /*!< Pointer to a buffer that is to + receive a response string. The + size of the buffer in bytes is + specified in \a cb_name_dest. */ + khm_size cb_name_dest; /*!< Size of buffer pointed to by \a + name_dest in bytes. */ + khm_int32 result; /*!< Receives a result value, which is + usually an error code defined in + kherror.h, though it is not + always. */ +} kcdb_ident_name_xfer; + +typedef struct tag_kcdb_ident_info { + khm_handle identity; + khm_int32 fields; + + FILETIME expiration; +} kcdb_ident_info; + +/*@}*/ + +/*! \name Identity provider interface functions + + These functions encapsulate safe calls to the current identity + provider. While these functions are exported, applications should + not call these functions directly. They are provided for use by + the NetIDMgr core application. +@{*/ + +/*! \brief Validate an identity name + + The name that is provided will be passed through sets of + validations. One set, which doesn't depend on the identity + provider checks whether the length of the identity name and + whether there are any invalid characters in the identity name. If + the name passes those tests, then the name is passed down to the + identity provider's name validation handler. + + \retval KHM_ERROR_SUCCESS The name is valid + \retval KHM_ERROR_TOO_LONG Too many characters in name + \retval KHM_ERROR_INVALID_NAME There were invalid characters in the name. + \retval KHM_ERROR_NO_PROVIDER There is no identity provider; + however the name passed the length and character tests. + \retval KHM_ERROR_NOT_IMPLEMENTED The identity provider doesn't + implement a name validation handler; however the name passed + the length and character tests. + + \see ::KMSG_IDENT_VALIDATE_NAME + */ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_validate_name(const wchar_t * name); + +/*! \brief Validate an identity + + The identity itself needs to be validated. This may involve + communicating with an external entity. + + \see ::KMSG_IDENT_VALIDATE_IDENTITY + */ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_validate_identity(khm_handle identity); + +/*! \brief Canonicalize the name + + + \see ::KMSG_IDENT_CANON_NAME +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_canon_name(const wchar_t * name_in, + wchar_t * name_out, + khm_size * cb_name_out); + +/*! \brief Compare two identity names + + \see ::KMSG_IDENT_COMPARE_NAME +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_compare_name(const wchar_t * name1, + const wchar_t * name2); + +/*! \brief Set the specified identity as the default + + \see ::KMSG_IDENT_SET_DEFAULT +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_set_default(khm_handle identity); + +/*! \brief Set the specified identity as searchable + + \see ::KMSG_IDENT_SET_SEARCHABLE +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_set_searchable(khm_handle identity, + khm_boolean searchable); + +/*! \brief Update the specified identity + + \see ::KMSG_IDENT_UPDATE +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_update(khm_handle identity); + +/*! \brief Obtain the UI callback + + \a rock is actually a pointer to a ::khui_ident_new_creds_cb which + is to receive the callback. + + \see ::KMSG_IDENT_GET_UI_CALLBACK + */ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_get_ui_cb(void * rock); + +/*! \brief Notify an identity provider of the creation of a new identity + + \see ::KMSG_IDENT_NOTIFY_CREATE +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identpro_notify_create(khm_handle identity); + +/*@}*/ + +/*! \brief Check if the given name is a valid identity name + + \return TRUE or FALSE to the question, is this valid? +*/ +KHMEXP khm_boolean KHMAPI +kcdb_identity_is_valid_name(const wchar_t * name); + +/*! \brief Create or open an identity. + + If the KCDB_IDENT_FLAG_CREATE flag is specified in the flags + parameter a new identity will be created if one does not already + exist with the given name. If an identity by that name already + exists, then the existing identity will be opened. The result + parameter will receive a held reference to the opened identity. + Use kcdb_identity_release() to release the handle. + + \param[in] name Name of identity to create + \param[in] flags If KCDB_IDENT_FLAG_CREATE is specified, then the + identity will be created if it doesn't already exist. + Additional flags can be set here which will be assigned to the + identity if it is created. Additional flags have no effect if + an existing identity is opened. + \param[out] result If the call is successful, this receives a held + reference to the identity. The caller should call + kcdb_identity_release() to release the identity once it is no + longer needed. + */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_create(const wchar_t *name, + khm_int32 flags, + khm_handle * result); + +/*! \brief Mark an identity for deletion. + + The identity will be marked for deletion. The + KCDB_IDENT_FLAG_ACTIVE will no longer be present for this + identity. Once all references to the identity are released, it + will be removed from memory. All associated credentials will also + be removed. */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_delete(khm_handle id); + +/*! \brief Set or unset the specified flags in the specified identity. + + Only flags that are in KCDB_IDENT_FLAGMASK_RDWR can be specifed in + the \a flags parameter or the \a mask parameter. The flags set in + the \a mask parameter of the identity will be set to the + corresponding values in the \a flags parameter. + + If ::KCDB_IDENT_FLAG_INVALID is set using this function, then the + ::KCDB_IDENT_FLAG_VALID will be automatically reset, and vice + versa. Resetting either bit does not undo this change, and will + leave the identity's validity unspecified. Setting either of + ::KCDB_IDENT_FLAG_INVALID or ::KCDB_IDENT_FLAG_VALID will + automatically reset ::KCDB_IDENT_FLAG_UNKNOWN. + + Note that setting or resetting certain flags have other semantic + side-effects: + + - ::KCDB_IDENT_FLAG_DEFAULT : Setting this is equivalent to + calling kcdb_identity_set_default() with \a id. Resetting this + is equivalent to calling kcdb_identity_set_default() with NULL. + + - ::KCDB_IDENT_FLAG_SEARCHABLE : Setting this will result in the + identity provider getting notified of the change. If the + identity provider indicates that searchable flag should not be + set or reset on the identity, then kcdb_identity_set_flags() + will return an error. + + \note kcdb_identity_set_flags() is not atomic. Even if the + function returns a failure code, some flags in the identity may + have been set. When calling kcdb_identity_set_flags() always + check the flags in the identity using kcdb_identity_get_flags() to + check which flags have been set and which have failed. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_flags(khm_handle id, + khm_int32 flags, + khm_int32 mask); + +/*! \brief Return all the flags for the identity + + The returned flags may include internal flags. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_flags(khm_handle id, + khm_int32 * flags); + +/*! \brief Return the name of the identity + + \param[out] buffer Buffer to copy the identity name into. The + maximum size of an identity name is \a KCDB_IDENT_MAXCB_NAME. + If \a buffer is \a NULL, then the required size of the buffer + is returned in \a pcbsize. + + \param[in,out] pcbsize Size of buffer in bytes. */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_name(khm_handle id, + wchar_t * buffer, + khm_size * pcbsize); + +/*! \brief Set the specified identity as the default. + + Specifying NULL effectively makes none of the identities the + default. + + \see kcdb_identity_set_flags() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_default(khm_handle id); + +/*! \brief Mark the specified identity as the default. + + This API is reserved for use by identity providers as a means of + specifying which identity is default. The difference between + kcdb_identity_set_default() and kcdb_identity_set_default_int() is + in semantics. + + - kcdb_identity_set_default() is used to request the KCDB to + designate the specified identity as the default. When + processing the request, the KCDB invokes the identity provider + to do the necessary work to make the identity the default. + + - kcdb_identity_set_default_int() is used by the identity provider + to notify the KCDB that the specified identity is the default. + This does not result in the invocation of any other semantics to + make the identity the default other than releasing the previous + defualt identity and making the specified one the default. + */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_default_int(khm_handle id); + +/*! \brief Get the default identity + + Obtain a held handle to the default identity if there is one. The + handle must be freed using kcdb_identity_release(). + + If there is no default identity, then the handle pointed to by \a + pvid is set to \a NULL and the function returns + KHM_ERROR_NOT_FOUND. */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_default(khm_handle * pvid); + +/*! \brief Get the configuration space for the identity. + + If the configuration space for the identity does not exist and the + flags parameter does not specify ::KHM_FLAG_CREATE, then the + function will return a failure code as specified in + ::khc_open_space(). Depending on whether or not a configuration + space was found, the ::KCDB_IDENT_FLAG_CONFIG flag will be set or + reset for the identity. + + \param[in] id Identity for which the configuraiton space is requested + + \param[in] flags Flags used when calling khc_open_space(). If \a + flags specifies KHM_FLAG_CREATE, then the configuration space + is created. + + \param[out] result The resulting handle. If the call is + successful, this receives a handle to the configuration space. + Use khc_close_space() to close the handle. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_config(khm_handle id, + khm_int32 flags, + khm_handle * result); + +/*! \brief Hold a reference to an identity. + + A reference to an identity (a handle) is only valid while it is + held. \note Once the handle is released, it can not be + revalidated by calling kcdb_identity_hold(). Doing so would lead + to unpredictable consequences. */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_hold(khm_handle id); + +/*! \brief Release a reference to an identity. + \see kcdb_identity_hold() */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_release(khm_handle id); + +/*! \brief Set the identity provider subscription + + If there was a previous subscription, that subscription will be + automatically deleted. + + \param[in] sub New identity provider subscription +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_provider(khm_handle sub); + +/*! \brief Set the primary credentials type + + The primary credentials type is designated by the identity + provider. As such, this function should only be called by an + identity provider. + */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_type(khm_int32 cred_type); + +/*! \brief Retrieve the identity provider subscription + + \param[out] sub Receives the current identity provider + subscription. Set to NULL if only the existence of an + identity provider needs to be checked. + + \retval KHM_ERROR_SUCCESS An identity provider exists. If \a sub + was not NULL, the subscription has been copied there. + + \retval KHM_ERROR_NOT_FOUND There is currently no registered + identity provider. If \a sub was not NULL, the handle it + points to has been set to NULL. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_provider(khm_handle * sub); + +/*! \brief Retrieve the identity provider credentials type + + This is the credentials type that the identity provider has + designated as the primary credentials type. + */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_type(khm_int32 * ptype); + +/*! \brief Returns TRUE if the two identities are equal + + Also returns TRUE if both identities are NULL. + */ +KHMEXP khm_boolean KHMAPI +kcdb_identity_is_equal(khm_handle identity1, + khm_handle identity2); + +/*! \brief Set an attribute in an identity by attribute id + + \param[in] buffer A pointer to a buffer containing the data to + assign to the attribute. Setting \a buffer to NULL has the + effect of removing any data that is already assigned to the + attribute. If \a buffer is non-NULL, then \a cbbuf should + specify the number of bytes in \a buffer. + + \param[in] cbbuf Number of bytes of data in \a buffer. The + individual data type handlers may copy in less than this many + bytes in to the credential. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_attr(khm_handle identity, + khm_int32 attr_id, + void * buffer, + khm_size cbbuf); + +/*! \brief Set an attribute in an identity by name + + The attribute name has to be a KCDB registered attribute or + property. + + \param[in] cbbuf Number of bytes of data in \a buffer. The + individual data type handlers may copy in less than this many + bytes in to the credential. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_set_attrib(khm_handle identity, + const wchar_t * attr_name, + void * buffer, + khm_size cbbuf); + +/*! \brief Get an attribute from an identity by attribute id. + + \param[in] buffer The buffer that is to receive the attribute + value. Set this to NULL if only the required buffer size is + to be returned. + + \param[in,out] cbbuf The number of bytes available in \a buffer. + If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and + sets this to the required buffer size. + + \param[out] attr_type Receives the data type of the attribute. + Set this to NULL if the type is not required. + + \note Set both \a buffer and \a cbbuf to NULL if only the + existence of the attribute is to be checked. If the attribute + exists in this identity then the function will return + KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attr(khm_handle identity, + khm_int32 attr_id, + khm_int32 * attr_type, + void * buffer, + khm_size * pcbbuf); + +/*! \brief Get an attribute from an identity by name. + + \param[in] buffer The buffer that is to receive the attribute + value. Set this to NULL if only the required buffer size is + to be returned. + + \param[in,out] cbbuf The number of bytes available in \a buffer. + If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and + sets this to the required buffer size. + + \note Set both \a buffer and \a cbbuf to NULL if only the + existence of the attribute is to be checked. If the attribute + exists in this identity then the function will return + KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attrib(khm_handle identity, + const wchar_t * attr_name, + khm_int32 * attr_type, + void * buffer, + khm_size * pcbbuf); + +/*! \brief Get the string representation of an identity attribute. + + A shortcut function which generates the string representation of + an identity attribute directly. + + \param[in] identity A handle to an identity + + \param[in] attr_id The attribute to retrieve + + \param[out] buffer A pointer to a string buffer which receives the + string form of the attribute. Set this to NULL if you only + want to determine the size of the required buffer. + + \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry, + holds the size of the buffer pointed to by \a buffer, and on + exit, receives the actual number of bytes that were copied. + + \param[in] flags Flags for the string conversion. Can be set to + one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is + KCDB_TS_LONG. + + \retval KHM_ERROR_SUCCESS Success + \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid + or was not defined for this identity + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the + supplied buffer was insufficient +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attr_string(khm_handle identity, + khm_int32 attr_id, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags); + +/*! \brief Get the string representation of an identity attribute by name. + + A shortcut function which generates the string representation of + an identity attribute directly. + + \param[in] identity A handle to an identity + + \param[in] attrib The name of the attribute to retrieve + + \param[out] buffer A pointer to a string buffer which receives the + string form of the attribute. Set this to NULL if you only + want to determine the size of the required buffer. + + \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry, + holds the size of the buffer pointed to by \a buffer, and on + exit, receives the actual number of bytes that were copied. + + \param[in] flags Flags for the string conversion. Can be set to + one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is + KCDB_TS_LONG. + + \see kcdb_identity_get_attr_string() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_identity_get_attrib_string(khm_handle identity, + const wchar_t * attr_name, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags); + +/*! \brief Enumerate identities + + Enumerates all the active identities that match the criteria + specified using \a and_flags and \a eq_flags. The condition is + applied to all active identities as follows: + + \code + (identity->flags & and_flags) == (eq_flags & and_flags) + \endcode + + Essentially, if a flag is set in \a and_flags, then that flag in + the identity should equal the setting in \a eq_flags. + + \param[in] and_flags See above + + \param[in] eq_flags See above + + \param[out] name_buf Buffer to receive the list of identity names. + Can be NULL if only the required size of the buffer or the + number of matching identities is required. The list is + returned as a multi string. + + \param[in,out] pcb_buf Number of bytes in buffer pointed to by \a + name_buf on entry. On exit, will receive the number of bytes + copied. Can be NULL only if \a name_buf is also NULL. If \a + name_buf is NULL or if \a pcb_buf indicates that the buffer is + insufficient, this will receive the number of bytes required + and the return value of the function will be + KHM_ERROR_TOO_LONG + + \param[out] pn_idents Receives the number of identities that match + the given criteria. + + \retval KHM_ERROR_SUCCESS If \a name_buf was valid, the buffer now + contains a multi string of identities that matched. If \a + pn_idents was valid, it contains the number of identities + matched. + + \retval KHM_ERROR_TOO_LONG No buffer was supplied or the supplied + buffer was insufficient. If \a pn_idents was valid, it + contains the number of identities. + + \retval KHM_ERROR_INVALID_PARAM None of the parameters \a name_buf, + \a pcb_buf and \a pn_idents were supplied, or \a pcb_buf was + NULL when \a name_buf was not. + + \note Calling this function to obtain the required size of the + buffer and then calling it with a that sized buffer is not + guaranteed to work since the list of identities may change + between the two calls. + */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_enum(khm_int32 and_flags, + khm_int32 eq_flags, + wchar_t * name_buf, + khm_size * pcb_buf, + khm_size * pn_idents); + +/*! \brief Refresh identity attributes based on root credential set + + Several flags in an identity are dependent on the credentials that + are associated with it in the root credential set. In addition, + other flags in an identity depend on external factors that need to + be verfied once in a while. This API goes through the root + credential set as well as consulting the identity provider to + update an identity. + + \see kcdb_identity_refresh() + */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_refresh(khm_handle vid); + +/*! \brief Refresh all identities + + Equivalent to calling kcdb_identity_refresh() for all active + identities. + + \see kcdb_identityt_refresh() + */ +KHMEXP khm_int32 KHMAPI +kcdb_identity_refresh_all(void); + +/* KSMG_KCDB_IDENT notifications are structured as follows: + type=KMSG_KCDB + subtype=KMSG_KCDB_IDENT + uparam=one of KCDB_OP_* + blob=handle to identity in question */ + +/*@}*/ + + +/*********************************************************************/ + + +/*! +\defgroup kcdb_creds Credential sets and individual credentials + +@{ +*/ + + +/*! \brief Credentials process function + + This function is called for each credential in a credential set + when supplied to kcdb_credset_apply(). It should return + KHM_ERROR_SUCCESS to continue the operation, or any other value to + terminate the processing. + + \see kcdb_credset_apply() +*/ +typedef khm_int32 +(KHMAPI *kcdb_cred_apply_func)(khm_handle cred, + void * rock); + +/*! \brief Credentials filter function. + + Should return non-zero if the credential passed as \a cred is to + be "accepted". The precise consequence of a non-zero return value + is determined by the individual function that this call back is + passed into. + + This function should not call any other function which may modify + \a cred. + + \see kcdb_credset_collect_filtered() + \see kcdb_credset_extract_filtered() +*/ +typedef khm_int32 +(KHMAPI *kcdb_cred_filter_func)(khm_handle cred, + khm_int32 flags, + void * rock); + +/*! \brief Credentials compare function. + + Asserts a weak ordering on the credentials that are passed in as + \a cred1 and \a cred2. It should return: + + - a negative value if \a cred1 < \a cred2 + - zero if \a cred1 == \a cred2 + - a postive value if \a cred1 > \a cred2 + \see kcdb_credset_sort() + \see ::kcdb_credtype +*/ +typedef khm_int32 +(KHMAPI *kcdb_cred_comp_func)(khm_handle cred1, + khm_handle cred2, + void * rock); + +/*! \defgroup kcdb_credset Credential sets */ +/*@{*/ + +/*! \brief Create a credential set. + + Credential sets are temporary containers for credentials. These + can be used by plug-ins to store credentials while they are being + enumerated from an external source. Once all the credentials have + been collected into the credential set, the plug-in may call + kcdb_credset_collect() to collect the credentials into the root + credential store. + + The user interface will only display credentials that are in the + root credential store. No notifications are generated for changes + to a non-root credential set. + + Use kcdb_credset_delete() to delete the credential set once it is + created. + + \see kcdb_credset_delete() + \see kcdb_credset_collect() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_create(khm_handle * result); + +/** \brief Delete a credential set + + \see kcdb_credset_create() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_delete(khm_handle credset); + +/** \brief Collect credentials from a credential set to another credential set. + + Collecting a subset of credentials from credential set \a cs_src + into credential set \a cs_dest involves the following steps: + + - Select all credentials from \a cs_src that matches the \a + identity and \a type specified in the function call and add them + to the \a cs_dest credential set if they are not there already. + Note that if neither credential set is not the root credential + store, then the credentials will be added by reference, while if + it is the root credential store, the credentials will be + duplicated, and the copies will be added to \a cs_dest. + + - If a selected credential in \a cs_src already exists in \a + cs_dest, then update the credential in \a cs_dest with the + credential fields in \a cs_src. In other words, once a + credential is found to exist in both \a cs_src and \a cs_dest, + all the non-null fields from the credential in \a cs_src will be + copied to the credential in \a cs_dest. Fields which are null + (undefined) in \a cs_src and are non-null in \a cs_dest will be + left unmodified in \a cs_dest. + + One notable exception is the credentials' flags. All flags in + \a cs_src which are not included in + ::KCDB_CRED_FLAGMASK_ADDITIVE will be copied to the + corresponding bits in the flags of \a cs_dest. However, flags + that are included in ::KCDB_CRED_FLAGMASK_ADDITIVE will be added + to the corresponding bits in \a cs_dest. + + (See notes below) + + - Remove all credentials from \a cs_dest that match the \a + identity and \a type that do not appear in \a cs_src. (see notes + below) + + For performance reasons, plugins should use kcdb_credset_collect() + to update the root credentials store instead of adding and + removing individual credentials from the root store. + + Only credentials that are associated with active identities are + affected by kcdb_credset_collect(). + + \param[in] cs_dest A handle to the destination credential set. If + this is \a NULL, then it is assumed to refer to the root + credential store. + + \param[in] cs_src A handle to the source credential set. If this + is NULL, then it is assumed to refer to the root credential + store. + + \param[in] identity A handle to an identity. Setting this to NULL + collects all identities in the credential set. + + \param[in] type A credentials type. Setting this to + KCDB_CREDTYPE_ALL collects all credential types in the set. + + \param[out] delta A bit mask that indicates the modifications that + were made to \a cs_dest as a result of the collect operation. + This is a combination of KCDB_DELTA_* values. This parameter + can be \a NULL if the value is not required. + + \warning If \a identity and \a type is set to a wildcard, all + credentials in the root store that are not in this credentials + set will be deleted. + + \note Two credentials \a A and \a B are considered equal if: + - They refer to the same identity + - Both have the same credential type + - Both have the same name + + \note This is the only supported way of modifying the root + credential store. + + \note \a cs_src and \a cs_dest can not refer to the same + credentials set. + + \note The destination credential set cannot be sealed. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_collect(khm_handle cs_dest, + khm_handle cs_src, + khm_handle identity, + khm_int32 type, + khm_int32 * delta); + +/*! \brief Credentials were added + \see kcdb_credset_collect() */ +#define KCDB_DELTA_ADD 1 + +/*! \brief Credentials were deleted + \see kcdb_credset_collect() */ +#define KCDB_DELTA_DEL 2 + +/*! \brief Credentials were modified + \see kcdb_credset_collect() */ +#define KCDB_DELTA_MODIFY 4 + +/*! \brief Indicates that the credential to be filtered is from the root store. + + \see kcdb_credset_collect_filtered() +*/ +#define KCDB_CREDCOLL_FILTER_ROOT 1 + +/*! \brief Indicates that the credential to be filtered is from the source + credential set + + \see kcdb_credset_collect_filtered() */ +#define KCDB_CREDCOLL_FILTER_SRC 2 + +/*! \brief Indicates that the credential to be filtered is from the destination + credential set + + \see kcdb_credset_collect_filtered() */ +#define KCDB_CREDCOLL_FILTER_DEST 4 + +/*! \brief Collect credentials from one credential set to another using a filter. + + Similar to kcdb_credset_collect() except instead of selecting + credentials by matching against an identity and/or type, a filter + function is called. If the filter function returns non-zero for a + credential, that credential is selected. + + Credentials in the source and destination credential sets are + passed into the filter function. Depending on whether the + credential is in the source credential set or destination + credential set, the \a flag parameter may have either \a + KCDB_CREDCOLL_FILTER_SRC or \a KCDB_CREDCOLL_FILTER_DEST bits set. + Also, if either one of the credential sets is the root credential + store, then additionally \a KCDB_CREDCOLL_FILTER_ROOT would also + be set. + + See the kcdb_credset_collect() documentation for explanations of + the \a cs_src, \a cs_dest and \a delta parameters which perform + identical functions. + + \param[in] filter The filter of type ::kcdb_cred_filter_func + \param[in] rock A custom argument to be passed to the filter function. + + \see kcdb_credset_collect() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_collect_filtered(khm_handle cs_dest, + khm_handle cs_src, + kcdb_cred_filter_func filter, + void * rock, + khm_int32 * delta); + +/*! \brief Flush all credentials from a credential set + + Deletes all the crednetials from the credential set. + + \param[in] credset A handle to a credential set. Cannot be NULL. + + \note The credential set cannot be sealed +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_flush(khm_handle credset); + +/*! \brief Extract credentials from one credential set to another + + Credentials from the source credential set are selected based on + the \a identity and \a type arguements. If a credential is + matched, then it is added to the \a destcredset. + + If the \a sourcecredset is the root credential set, the added + credentials are copies of the actual credentials in the root + credential set. Otherwise the credentials are references to the + original credentials in the \a sourcecredset . + + \param[in] destcredset Destination credential set. Must be valid. + + \param[in] sourcecredset The source credential set. If set to + NULL, extracts from the root credential set. + + \param[in] identity The identity to match in the source credential + set. If set to NULL, matches all identities. + + \param[in] type The credential type to match in the source credential set. + If set to KCDB_CREDTYPE_INVALID, matches all types. + + \note This function does not check for duplicate credentials. + + \note The destination credential set cannot be sealed. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_extract(khm_handle destcredset, + khm_handle sourcecredset, + khm_handle identity, + khm_int32 type); + +/*! \brief Extract credentials from one credential set to another using a filter. + + Similar to kcdb_credset_extract() except a filter function is used + to determine which credentials should be selected. + + \param[in] rock A custom argument to be passed in to the filter function. + + \note The destination credential set cannot be sealed. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_extract_filtered(khm_handle destcredset, + khm_handle sourcecredset, + kcdb_cred_filter_func filter, + void * rock); + +/*! \brief Retrieve a held reference to a credential in a credential set based on index. + + \param[in] idx The index of the credential to retrieve. This is a + zero based index which goes from 0 ... (size of credset - 1). + + \param[out] cred The held reference to a credential. Call + kcdb_cred_release() to release the credential. + + \retval KHM_ERROR_SUCCESS Success. \a cred has a held reference to the credential. + \retval KHM_ERROR_OUT_OF_BOUNDS The index specified in \a idx is out of bounds. + \retval KHM_ERROR_DELETED The credential at index \a idx has been marked as deleted. + + \see kcdb_cred_release() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_get_cred(khm_handle credset, + khm_int32 idx, + khm_handle * cred); + +/*! \brief Search a credential set for a specific credential + + The credential set indicated by \a credset is searched for a + credential that satisfies the predicate function \a f. Each + credential starting at \a idx_start is passed into the predicate + function until it returns a non-zero value. At this point, that + credential is passed in to the \a cred parameter, and the index of + the credential is passed into the \a idx parameter. + + \param[in] credset The credential set to search on. Specify NULL + if you want to search teh root credential set. + + \param[in] idx_start The index at which to start the search after. + The first credential passed to the predicate function will be + at \a idx_start + 1. Specify -1 to start from the beginning + of the credential set. + + \param[in] f The predicate function. The \a flags parameter of + the predicate function will always receive 0. + + \param[in] rock An opaque parameter to be passed to the predicate + function \a f. + + \param[out] cred A held reference to the credential that satisfied + the predicate function or NULL if no such credential was + found. Note that if a valid credential is returned, the + calling function must release the credential using + kcdb_cred_release(). + + \param[out] idx The index of the credential passed in \a cred. + Specify NULL if the index is not required. + + \retval KHM_ERROR_SUCCESS A credential that satisfied the + predicate function was found and was assigned to \a cred. + + \retval KHM_ERROR_NOT_FOUND No credential was found that matched + the predicate function. + + \note When querying credential sets that are shared between + threads, it is possible that another thread modifies the + credential set between successive calls to + kcdb_credset_find_filtered(). Therefore a continued sequences of + searches are not guaranteed to exhastively cover the + credential set nor to not return duplicate matches. Duplicate + matches are possible if the order of the credentials in the + set was changed. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_find_filtered(khm_handle credset, + khm_int32 idx_start, + kcdb_cred_filter_func f, + void * rock, + khm_handle * cred, + khm_int32 * idx); + +/*! \brief Find matching credential + + Searches a credential set for a credential that matches the + specified credential. For a credential to be a match, it must + have the same identity, credential type and name. + + \param[in] credset Credential set to search + + \param[in] cred_src Credetial to search on + + \param[out] cred_dest receieves the matching credential if the + search is successful. If a handle is returend, the + kcdb_cred_release() must be used to release the handle. If + the matching credential is not required, you can pass in NULL. + + \retval KHM_ERROR_SUCCESS The search was successful. A credential + was assigned to \a cred_dest + + \retval KHM_ERROR_NOT_FOUND A matching credential was not found. + */ +KHMEXP khm_int32 KHMAPI +kcdb_credset_find_cred(khm_handle credset, + khm_handle cred_src, + khm_handle *cred_dest); + + +/*! \brief Delete a credential from a credential set. + + The credential at index \a idx will be deleted. All the + credentials that are at indices \a idx + 1 and above will be moved + down to fill the gap and the size of the credential set will + decrease by one. + + Use kcdb_credset_del_cred_ref() to delete a credential by + reference. Using kcdb_credset_del_cred() is faster than + kcdb_credset_del_cred_ref(). + + If you call kcdb_credset_del_cred() or kcdb_credset_del_cred_ref() + from within kcdb_credset_apply(), the credential will only be + marked as deleted. They will not be removed. This means that the + size of the credential set will not decrease. To purge the + deleted credentials from the set, call kcdb_credset_purge() after + kcdb_credset_apply() completes. + + \note The credential set cannot be sealed. + + \see kcdb_credset_del_cred_ref() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_del_cred(khm_handle credset, + khm_int32 idx); + +/*! \brief Delete a credential from a credential set by reference. + + See kcdb_credset_del_cred() for description of what happens when a + credential is deleted from a credential set. + + \note The credential set cannot be sealed. + + \see kcdb_credset_del_cred() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_del_cred_ref(khm_handle credset, + khm_handle cred); + +/*! \brief Add a credential to a credential set. + + The credential is added by reference. In other words, no copy of + the credential is made. + + \param[in] idx Index of the new credential. This must be a value + in the range 0..(previous size of credential set) or -1. If + -1 is specifed, then the credential is appended at the end of + the set. + + \note The credential set cannot be sealed. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_add_cred(khm_handle credset, + khm_handle cred, + khm_int32 idx); + +/*! \brief Get the number of credentials in a credential set. + + Credentials in a credential set may be volatile. When + kcdb_credeset_get_size() is called, the credential set is + compacted to only include credentials that are active at the time. + However, when you are iterating through the credential set, it + might be the case that some credentials would get marked as + deleted. These credentials will remain in the credential set + until the credential set is discarded or another call to + kcdb_credset_get_size() or kdcb_credset_purge() is made. + + If the credential set is sealed, then it will not be compacted and + will include deleted credentials as well. + + \see kcdb_credset_purge() + \see kcdb_credset_get_cred() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_get_size(khm_handle credset, + khm_size * size); + +/*! \brief Removes credentials that have been marked as deleted from a credential set. + + See description of \a kcdb_credset_purge() for a description of + what happens when credntials that are contained in a credential + set are deleted by an external entity. + + \note The credential set cannot be sealed. + + \see kcdb_credset_get_size() + \see kcdb_credset_get_cred() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_purge(khm_handle credset); + +/*! \brief Applies a function to all the credentials in a credentials set + + The given function is called for each credential in a credential + set. With each iteration, the function is called with a handle to + the credential and the user defined parameter \a rock. If the + function returns anything other than KHM_ERROR_SUCCESS, the + processing stops. + + \param[in] credset The credential set to apply the function to, or + NULL if you want to apply this to the root credential set. + + \param[in] f Function to call for each credential + + \param[in] rock An opaque parameter which is to be passed to 'f' + as the second argument. + + \retval KHM_ERROR_SUCCESS All the credentials were processed. + + \retval KHM_ERROR_EXIT The supplied function signalled the + processing to be aborted. + + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_apply(khm_handle credset, + kcdb_cred_apply_func f, + void * rock); + +/*! \brief Sort the contents of a credential set. + + \param[in] rock A custom argument to be passed in to the \a comp function. + + \note The credential set cannot be sealed. + + \see kcdb_cred_comp_generic() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credset_sort(khm_handle credset, + kcdb_cred_comp_func comp, + void * rock); + +/*! \brief Seal a credential set + + Sealing a credential set makes it read-only. To unseal a + credential set, call kcdb_credset_unseal(). + + Sealing is an additive operation. kcdb_credset_seal() can be + called muliple times. However, for every call to + kcdb_credset_seal() a call to kcdb_credset_unseal() must be made + to undo the seal. The credential set will become unsealed when + all the seals are released. + + Once sealed, the credential set will not allow any operation that + might change its contents. However, a selaed credential set can + still be delted. + + \see kcdb_credset_unseal() + */ +KHMEXP khm_int32 KHMAPI +kcdb_credset_seal(khm_handle credset); + +/*! \brief Unseal a credential set + + Undoes what kcdb_credset_seal() did. This does not guarantee that + the credential set is unsealed since there may be other seals. + + \see kcdb_credset_seal() + */ +KHMEXP khm_int32 KHMAPI +kcdb_credset_unseal(khm_handle credset); + +/*! \brief Defines a sort criterion for kcdb_cred_comp_generic() + + \see kcdb_cred_comp_generic() +*/ +typedef struct tag_kcdb_cred_comp_field { + khm_int32 attrib; /*!< a valid attribute ID */ + khm_int32 order; /*!< one of KCDB_CRED_COMP_INCREASING or + KCDB_CRED_COMP_DECREASING. Optionally, + KCDB_CRED_COMP_INITIAL_FIRST may be combined + with either. */ +} kcdb_cred_comp_field; + +/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field + + Sorts lexicographically ascending by string representation of field. +*/ +#define KCDB_CRED_COMP_INCREASING 0 + +/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field + + Sorts lexicographically descending by string representation of + field. + */ +#define KCDB_CRED_COMP_DECREASING 1 + +/*! \brief Defines the sort order for a field in ::kcdb_cred_comp_field + + Any credentials which have the ::KCDB_CRED_FLAG_INITIAL will be + grouped above any that don't. + + If that does not apply, then credentials from the primary + credentials type will be sorted before others. +*/ +#define KCDB_CRED_COMP_INITIAL_FIRST 2 + +/*! \brief Defines the sort criteria for kcdb_cred_comp_generic() + + \see kcdb_cred_comp_generic() +*/ +typedef struct tag_kcdb_cred_comp_order { + khm_int32 nFields; + kcdb_cred_comp_field * fields; +} kcdb_cred_comp_order; + +/*! \brief A generic compare function for comparing credentials. + + This function can be passed as a parameter to kcdb_credset_sort(). + + The \a rock parameter to this function should be a pointer to a + ::kcdb_cred_comp_order object. The \a fields member of the + ::kcdb_cred_comp_order object should point to an array of + ::kcdb_cred_comp_field objects, each of which specifies the sort + order in decreasing order of priority. The number of + ::kcdb_cred_comp_field objects in the array should correspond to + the \a nFields member in the ::kcdb_cred_comp_order object. + + The array of ::kcdb_cred_comp_field objects define the sort + criteria, in order. The \a attrib member should be a valid + attribute ID, while the \a order member determines whether the + sort order is increasing or decreasing. The exact meaning or + increasing or decreasing depends on the data type of the + attribute. + + \param[in] rock a pointer to a ::kcdb_cred_comp_order object +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_comp_generic(khm_handle cred1, + khm_handle cred2, + void * rock); + +/*@}*/ + +/*! \defgroup kcdb_cred Credentials */ +/*@{*/ + +/*! \brief Maximum number of characters in a credential name */ +#define KCDB_CRED_MAXCCH_NAME 256 + +/*! \brief Maximum number of bytes in a credential name */ +#define KCDB_CRED_MAXCB_NAME (sizeof(wchar_t) * KCDB_CRED_MAXCCH_NAME) + +/*! \brief Marked as deleted */ +#define KCDB_CRED_FLAG_DELETED 0x00000008 + +/*! \brief Renewable */ +#define KCDB_CRED_FLAG_RENEWABLE 0x00000010 + +/*! \brief Initial + + Initial credentials form the basis of an identity. Some + properties of an initial credential, such as being renewable, are + directly inherited by the identity. An identity is also + automatically considered valid if it contains a valid initial + credential. + */ +#define KCDB_CRED_FLAG_INITIAL 0x00000020 + +/*! \brief Expired + + The credential's lifetime has ended. + */ +#define KCDB_CRED_FLAG_EXPIRED 0x00000040 + +/*! \brief Invalid + + The credential can no longer serve its intended function. This + may be because it is expired and is not renewable, or its + renewable time period has also expired, or for some other reason. + */ +#define KCDB_CRED_FLAG_INVALID 0x00000080 + +/*! \brief Credential is selected + + Indicates that the credential is selected. Note that using this + flag may be subject to race conditions. + */ +#define KCDB_CRED_FLAG_SELECTED 0x00000100 + +/*! \brief Bitmask indicating all known credential flags + */ +#define KCDB_CRED_FLAGMASK_ALL 0x0000ffff + +/*! \brief External flags + + These are flags that are provided by the credentials providers. + The other flags are internal to KCDB and should not be modified. + */ +#define KCDB_CRED_FLAGMASK_EXT (KCDB_CRED_FLAG_INITIAL | KCDB_CRED_FLAG_EXPIRED | KCDB_CRED_FLAG_INVALID | KCDB_CRED_FLAG_RENEWABLE) + +/*! \brief Bitmask indicating dditive flags + + Additive flags are special flags which are added to exiting + credentials based on new credentials when doing a collect + operation. See details on kcdb_credset_collect() + + \see kcdb_credset_collect() +*/ +#define KCDB_CRED_FLAGMASK_ADDITIVE KCDB_CRED_FLAG_SELECTED + +/*! \brief Generic credentials request + + This data structure is used as the format for a generic + credentials reqeust for a ::KMSG_KCDB_REQUEST message. A plugin + typically publishes this message so that a credentials provider + may handle it and in response, obtain the specified credential. + + While the \a identity, \a type and \a name members of the + structure are all optional, typically one would specify all three + or at least two for a credential provider to be able to provide + the credential unambigously. + + Credential providers do not need to respond to ::KMSG_KCDB_REQUEST + messages. However, if they do, they should make sure that they + are the only credential provider that is responding by setting the + \a semaphore member to a non-zero value. The \a semaphore is set + to zero when a request is initially sent out. When incrementing + the semaphore, the plugin should use a thread safe mechanism to + ensure that there are no race conditions that would allow more + than one provider to respond to the message. + */ +typedef struct tag_kcdb_cred_request { + khm_handle identity; /*!< Identity of the credential. Set + to NULL if not specified. */ + khm_int32 type; /*!< Type of the credential. Set to + KCDB_CREDTYPE_INVALID if not + specified. */ + wchar_t * name; /*!< Name of the credential. Set to + NULL if not specified. */ + + khm_handle dest_credset; /*!< If non-NULL, instructs whoever is + handling the request that the + credential thus obtained be placed + in this credential set in addition + to whereever it may place newly + acquired credentials. Note that + while this can be NULL if the new + credential does not need to be + placed in a credential set, it can + not equal the root credential + set. */ + + void * vparam; /*!< An unspecified + parameter. Specific credential types + may specify how this field is to be + used. */ + + long semaphore; /*!< Incremented by one when this + request is answered. Only one + credential provider is allowed to + answer a ::KMSG_KCDB_REQUEST + message. Initially, when the + message is sent out, this member + should be set to zero. */ +} kcdb_cred_request; + +/*! \brief Create a new credential + + \param[in] name Name of credential. \a name cannot be NULL and cannot + exceed \a KCDB_CRED_MAXCCH_NAME unicode characters including the + \a NULL terminator. + \param[in] identity A reference to an identity. + \param[in] cred_type A credentials type identifier for the credential. + \param[out] result Gets a held reference to the newly created credential. + Call kcdb_cred_release() or kcdb_cred_delete() to release the + reference. + \see kcdb_cred_release() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_create(const wchar_t * name, + khm_handle identity, + khm_int32 cred_type, + khm_handle * result); + +/*! \brief Duplicate an existing credential. + + \param[out] newcred A held reference to the new credential if the call + succeeds. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_dup(khm_handle cred, + khm_handle * newcred); + +/*! \brief Updates one credential using field values from another + + All fields that exist in \a vsrc will get copied to \a vdest and will + overwrite any values that are already there in \a vdest. However any + values that exist in \a vdest taht do not exist in \a vsrc will not be + modified. + + \retval KHM_ERROR_SUCCESS vdest was successfully updated + \retval KHM_ERROR_EQUIVALENT all fields in vsrc were present and equivalent in vdest +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_update(khm_handle vdest, + khm_handle vsrc); + +/*! \brief Set an attribute in a credential by name + + + + \param[in] cbbuf Number of bytes of data in \a buffer. The + individual data type handlers may copy in less than this many + bytes in to the credential. For some data types where the + size of the buffer is fixed or can be determined from its + contents, you can specify ::KCDB_CBSIZE_AUTO for this + parameter. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_set_attrib(khm_handle cred, + const wchar_t * name, + void * buffer, + khm_size cbbuf); + +/*! \brief Set an attribute in a credential by attribute id + + \param[in] buffer A pointer to a buffer containing the data to + assign to the attribute. Setting this to NULL has the effect + of removing any data that is already assigned to the + attribute. If \a buffer is non-NULL, then \a cbbuf should + specify the number of bytes in \a buffer. + + \param[in] cbbuf Number of bytes of data in \a buffer. The + individual data type handlers may copy in less than this many + bytes in to the credential. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_set_attr(khm_handle cred, + khm_int32 attr_id, + void * buffer, + khm_size cbbuf); + +/*! \brief Get an attribute from a credential by name. + + \param[in] buffer The buffer that is to receive the attribute + value. Set this to NULL if only the required buffer size is + to be returned. + + \param[in,out] cbbuf The number of bytes available in \a buffer. + If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and + sets this to the required buffer size. + + \note Set both \a buffer and \a cbbuf to NULL if only the + existence of the attribute is to be checked. If the attribute + exists in this credential then the function will return + KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_attrib(khm_handle cred, + const wchar_t * name, + khm_int32 * attr_type, + void * buffer, + khm_size * cbbuf); + +/*! \brief Get an attribute from a credential by attribute id. + + \param[in] buffer The buffer that is to receive the attribute + value. Set this to NULL if only the required buffer size is + to be returned. + + \param[in,out] cbbuf The number of bytes available in \a buffer. + If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and + sets this to the required buffer size. + + \param[out] attr_type Receives the data type of the attribute. + Set this to NULL if the type is not required. + + \note Set both \a buffer and \a cbbuf to NULL if only the + existence of the attribute is to be checked. If the attribute + exists in this credential then the function will return + KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_attr(khm_handle cred, + khm_int32 attr_id, + khm_int32 * attr_type, + void * buffer, + khm_size * cbbuf); + +/*! \brief Get the name of a credential. + + \param[in] buffer The buffer that is to receive the credential + name. Set this to NULL if only the required buffer size is to + be returned. + + \param[in,out] cbbuf The number of bytes available in \a buffer. + If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and + sets this to the required buffer size. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_name(khm_handle cred, + wchar_t * buffer, + khm_size * cbbuf); + +/*! \brief Get the string representation of a credential attribute. + + A shortcut function which generates the string representation of a + credential attribute directly. + + \param[in] vcred A handle to a credential + + \param[in] attr_id The attribute to retrieve + + \param[out] buffer A pointer to a string buffer which receives the + string form of the attribute. Set this to NULL if you only + want to determine the size of the required buffer. + + \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry, + holds the size of the buffer pointed to by \a buffer, and on + exit, receives the actual number of bytes that were copied. + + \param[in] flags Flags for the string conversion. Can be set to + one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is + KCDB_TS_LONG. + + \retval KHM_ERROR_SUCCESS Success + \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid + or was not defined for this credential + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the + supplied buffer was insufficient +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_attr_string(khm_handle vcred, + khm_int32 attr_id, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags); + +/*! \brief Get the string representation of a credential attribute by name. + + A shortcut function which generates the string representation of a + credential attribute directly. + + \param[in] vcred A handle to a credential + + \param[in] attrib The name of the attribute to retrieve + + \param[out] buffer A pointer to a string buffer which receives the + string form of the attribute. Set this to NULL if you only + want to determine the size of the required buffer. + + \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry, + holds the size of the buffer pointed to by \a buffer, and on + exit, receives the actual number of bytes that were copied. + + \param[in] flags Flags for the string conversion. Can be set to + one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is + KCDB_TS_LONG. + + \see kcdb_cred_get_attr_string() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_attrib_string(khm_handle cred, + const wchar_t * name, + wchar_t * buffer, + khm_size * cbbuf, + khm_int32 flags) ; + + +/*! \brief Get a held reference to the identity associated with a credential + + Use kcdb_identity_release() to release the reference that is + returned. + + \see kcdb_identity_relase() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_identity(khm_handle cred, + khm_handle * identity); + +/*! \brief Set the identity of a credential + + While it is ill-advised to change the identity of a credential + that has been placed in one or more credential sets, there can be + legitimate reasons for doing so. Only change the identity of a + credential that is not placed in a credential set or placed in a + credential set that is only used by a single entity. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_set_identity(khm_handle vcred, + khm_handle id); + +/*! \brief Get the serial number for the credential. + + Each credential gets assigned a serial number at the time it is + created. This will stay with the credential for its lifetime. + + \param[out] pserial Receives the serial number. Cannot be NULL. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_serial(khm_handle cred, + khm_ui_8 * pserial); + +/*! \brief Get the type of the credential. + + The returned type is a credential type. Doh. + + \param[out] type Receives the type. Cannot be NULL. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_type(khm_handle cred, + khm_int32 * type); + +/*! \brief Retrieve flags from a credential + + The flags returned will be place in the location pointed to by \a + flags. Note that the specified credential must be an active + credential for the operation to succeed. This means the + ::KCDB_CRED_FLAG_DELETED will never be retured by this function. + */ +KHMEXP khm_int32 KHMAPI +kcdb_cred_get_flags(khm_handle cred, + khm_int32 * flags); + +/*! \brief Set the flags of a credential + + The flags specified in the \a mask parameter will be set to the + values specified in the \a flags parameter. The flags that are + not included in \a mask will not be modified. + + This function can not be used to set the ::KCDB_CRED_FLAG_DELETED + flag. If this bit is specified in either \a flags or \a mask, it + will be ignored. + + \see ::KCDB_CRED_FLAGMASK_ALL + */ +KHMEXP khm_int32 KHMAPI +kcdb_cred_set_flags(khm_handle cred, + khm_int32 flags, + khm_int32 mask); + +/*! \brief Hold a reference to a credential. + + Use kcdb_cred_release() to release the reference. + + \see kcdb_cred_release() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_hold(khm_handle cred); + +/*! \brief Release a held reference to a credential. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_release(khm_handle cred); + +/*! \brief Delete a credential. + + The credential will be marked for deletion and will continue to + exist until all held references are released. If the credential + is bound to a credential set or the root credential store, it will + be removed from the respective container. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_cred_delete(khm_handle cred); + +/*! \brief Compare an attribute of two credentials by name. + + \return The return value is dependent on the type of the attribute + and indicate a weak ordering of the attribute values of the two + credentials. If one or both credentials do not contain the + attribute, the return value is 0, which signifies that no ordering + can be determined. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_creds_comp_attrib(khm_handle cred1, + khm_handle cred2, + const wchar_t * name); + +/*! \brief Compare an attribute of two credentials by attribute id. + + \return The return value is dependent on the type of the attribute + and indicate a weak ordering of the attribute values of the two + credentials. If one or both credentials do not contain the + attribute, the return value is 0, which signifies that no ordering + can be determined. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_creds_comp_attr(khm_handle cred1, + khm_handle cred2, + khm_int32 attr_id); + +/*! \brief Compare two credentials for equivalence + + \return Non-zero if the two credentials are equal. Zero otherwise. + \note Two credentials are considered equal if all the following hold: + - Both refer to the same identity. + - Both have the same name. + - Both have the same type. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_creds_is_equal(khm_handle cred1, + khm_handle cred2); + +/*@}*/ +/*@}*/ + +/********************************************************************/ + +/*! \defgroup kcdb_type Credential attribute types + +@{*/ + +/*! \brief Convert a field to a string + + Provides a string representation of a field in a credential. The + data buffer can be assumed to be valid. + + On entry, \a s_buf can be NULL if only the required size of the + buffer is to be returned. \a pcb_s_buf should be non-NULL and + should point to a valid variable of type ::khm_size that will, on + entry, contain the size of the buffer pointed to by \a s_buf if \a + s_buf is not \a NULL, and on exit will contain the number of bytes + consumed in \a s_buf, or the required size of the buffer if \a + s_buf was NULL or the size of the buffer was insufficient. + + The implementation should verify the parameters that are passed in + to the function. + + The data pointed to by \a data should not be modified in any way. + + \param[in] data Valid pointer to a block of data + + \param[in] cb_data Number of bytes in data block pointed to by \a + data + + \param[out] s_buf Buffer to receive the string representation of + data. If the data type flags has KCDB_TYPE_FLAG_CB_AUTO, then + this parameter could be set to KCDB_CBSIZE_AUTO. In this + case, the function should compute the size of the input buffer + assuming that the input buffer is valid. + + \param[in,out] pcb_s_buf On entry, contains the size of the buffer + pointed to by \a s_buf, and on exit, contains the number of + bytes used by the string representation of the data including + the NULL terminator + + \param[in] flags Flags for formatting the string + + \retval KHM_ERROR_SUCCESS The string representation of the data + field was successfully copied to \a s_buf and the size of the + buffer used was copied to \a pcb_s_buf. + + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + + \retval KHM_ERROR_TOO_LONG Either \a s_buf was \a NULL or the size + indicated by \a pcb_s_buf was too small to contain the string + representation of the value. The required size of the buffer + is in \a pcb_s_buf. + + \note This documents the expected behavior of this prototype function + + \see ::kcdb_type + */ +typedef khm_int32 +(KHMAPI *kcdb_dtf_toString)(const void * data, + khm_size cb_data, + wchar_t * s_buf, + khm_size * pcb_s_buf, + khm_int32 flags); + +/*! \brief Verifies whetehr the given buffer contains valid data + + The function should examine the buffer and the size of the buffer + and determine whether or not the buffer contains valid data for + this data type. + + The data field pointed to by \a data should not be modified in any + way. + + \param[in] data A pointer to a data buffer + + \param[in] cb_data The number of bytes in the data buffer. If the + data type flags has KCDB_TYPE_FLAG_CB_AUTO, then this + parameter could be set to KCDB_CBSIZE_AUTO. In this case, the + function should compute the size of the input buffer assuming + that the input buffer is valid. + + \return TRUE if the data is valid, FALSE otherwise. + + \note This documents the expected behavior of this prototype function + + \see ::kcdb_type +*/ +typedef khm_boolean +(KHMAPI *kcdb_dtf_isValid)(const void * data, + khm_size cb_data); + +/*! \brief Compare two fields + + Compare the two data fields and return a value indicating their + relative ordering. The return value follows the same + specification as strcmp(). + + Both data buffers that are passed in can be assumed to be valid. + + None of the data buffers should be modified in any way. + + \param[in] data_l Valid pointer to first data buffer + + \param[in] cb_data_l Number of bytes in \a data_l. If the data + type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter + could be set to KCDB_CBSIZE_AUTO. In this case, the function + should compute the size of the input buffer assuming that the + input buffer is valid. + + \param[in] data_r Valid pointer to second data buffer + + \param[in] cb_data_r Number of bytes in \a data_r. If the data + type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter + could be set to KCDB_CBSIZE_AUTO. In this case, the function + should compute the size of the input buffer assuming that the + input buffer is valid. + + \return The return value should be + - Less than zero if \a data_l &lt; \a data_r + - Equal to zero if \a data_l == \a data_r or if this data type can not be compared + - Greater than zero if \a data_l &gt; \a data_r + + \note This documents the expected behavior of this prototype function + + \see ::kcdb_type +*/ +typedef khm_int32 +(KHMAPI *kcdb_dtf_comp)(const void * data_l, + khm_size cb_data_l, + const void * data_r, + khm_size cb_data_r); + +/*! \brief Duplicate a data field + + Duplicates a data field. The buffer pointed to by \a data_src + contains a valid field. The function should copy the field with + appropriate adjustments to \a data_dst. + + The \a data_dst parameter can be NULL if only the required size of + the buffer is needed. In this case, teh function should set \a + pcb_data_dst to the number of bytes required and then return + KHM_ERROR_TOO_LONG. + + \param[in] data_src Pointer to a valid data buffer + + \param[in] cb_data_src Number of bytes in \a data_src. If the data + type flags has KCDB_TYPE_FLAG_CB_AUTO, then this parameter + could be set to KCDB_CBSIZE_AUTO. In this case, the function + should compute the size of the input buffer assuming that the + input buffer is valid. + + \param[out] data_dst Poitner to destination buffer. Could be NULL + if only the required size of the destination buffer is to be + returned. + + \param[in,out] pcb_data_dst On entry specifies the number of bytes + in \a data_dst, and on exit should contain the number of bytes + copied. + + \retval KHM_ERROR_SUCCESS The data was successfully copied. The + number of bytes copied is in \a pcb_data_dst + + \retval KHM_ERROR_INVALID_PARAM One or more parameters is incorrect. + + \retval KHM_ERROR_TOO_LONG Either \a data_dst was NULL or the size + of the buffer was insufficient. The required size is in \a + pcb_data_dst + + \note This documents the expected behavior of this prototype function + + \see ::kcdb_type + */ +typedef khm_int32 +(KHMAPI *kcdb_dtf_dup)(const void * data_src, + khm_size cb_data_src, + void * data_dst, + khm_size * pcb_data_dst); + +/*! \brief A data type descriptor. + + Handles basic operation for a specific data type. + + \see \ref cred_data_types +*/ +typedef struct tag_kcdb_type { + wchar_t * name; + khm_int32 id; + khm_int32 flags; + + khm_size cb_min; + khm_size cb_max; + + kcdb_dtf_toString toString; + /*!< Provides a string representation for a value. */ + + kcdb_dtf_isValid isValid; + /*!< Returns true of the value is valid for this data type */ + + kcdb_dtf_comp comp; + /*!< Compare two values and return \a strcmp style return value */ + + kcdb_dtf_dup dup; + /*!< Duplicate a value into a secondary buffer */ +} kcdb_type; + +/*! \name Flags for kcdb_type::toString +@{*/ +/*! \brief Specify that the short form of the string representation should be returned. + + Flags for #kcdb_type::toString. The flag specifies how long the + string representation should be. The specific length of a short + or long description is not restricted and it is up to the + implementation to choose how to interpret the flags. + + Usually, KCDB_TS_SHORT is specified when the amount of space that + is available to display the string is very restricted. It may be + the case that the string is truncated to facilitate displaying in + a constrainted space. +*/ +#define KCDB_TS_SHORT 1 + +/*! \brief Specify that the long form of the string representation should be returned + + Flags for #kcdb_type::toString. The flag specifies how long the + string representation should be. The specific length of a short + or long description is not restricted and it is up to the + implementation to choose how to interpret the flags. + +*/ +#define KCDB_TS_LONG 0 +/*@}*/ + +/*! \brief The maximum number of bytes allowed for a value of any type */ +#define KCDB_TYPE_MAXCB 16384 + +/*! \name Flags for kcdb_type +@{*/ + +/*! \brief The type supports KCDB_CBSIZE_AUTO. + + Used for types where the size of the object can be determined + through context or by the object content. Such as for objects + that have a fixed size or unicode strings that have a terminator. + + This implies that ALL the object manipulation callbacks that are + defined in this type definition support the KCDB_CBSIZE_AUTO + value. +*/ +#define KCDB_TYPE_FLAG_CB_AUTO 16 + +/*! \brief The \a cb_min member is valid. + + The \a cb_min member defines the minimum number of bytes that an + object of this type will consume. + + \note If this flag is used in conjunction with \a + KCDB_TYPE_FLAG_CB_MAX then, \a cb_min must be less than or equal + to \a cb_max. +*/ +#define KCDB_TYPE_FLAG_CB_MIN 128 + +/*! \brief The \a cb_max member is valid. + + The \a cb_max member defines the maximum number of bytes that an + object of this type will consume. + + \note If this flag is used in conjunction with \a + KCDB_TYPE_FLAG_CB_MIN then, \a cb_min must be less than or + equal to \a cb_max. */ +#define KCDB_TYPE_FLAG_CB_MAX 256 + +/*! \brief Denotes that objects of this type have a fixed size. + + If this flags is specified, then the type definition must also + specify cb_min and cb_max, which must both be the same value. + + \note Implies \a KCDB_TYPE_FLAG_CB_AUTO, \a KCDB_TYPE_FLAG_CB_MIN + and \a KCDB_TYPE_FLAG_CB_MAX. Pay special attention to the + implication of \a KCDB_TYPE_FLAG_AUTO. +*/ +#define KCDB_TYPE_FLAG_CB_FIXED (KCDB_TYPE_FLAG_CB_AUTO|KCDB_TYPE_FLAG_CB_MIN|KCDB_TYPE_FLAG_CB_MAX) + +/*@}*/ + +KHMEXP khm_int32 KHMAPI +kcdb_type_get_id(const wchar_t *name, khm_int32 * id); + +/*! \brief Return the type descriptor for a given type id + + \param[out] info Receives a held reference to a type descriptor. + Use kcdb_type_release_info() to release the handle. If the \a + info parameter is NULL, the function returns KHM_ERROR_SUCCESS + if \a id is a valid type id, and returns KHM_ERROR_NOT_FOUND + otherwise. + + \see kcdb_type_release_info() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_type_get_info(khm_int32 id, kcdb_type ** info); + +/*! \brief Release a reference to a type info structure + + Releases the reference to the type information obtained with a + prior call to kcdb_type_get_info(). + */ +KHMEXP khm_int32 KHMAPI +kcdb_type_release_info(kcdb_type * info); + +/*! \brief Get the name of a type + + Retrieves the non-localized name of the specified type. + */ +KHMEXP khm_int32 KHMAPI +kcdb_type_get_name(khm_int32 id, + wchar_t * buffer, + khm_size * cbbuf); + +/*! \brief Register a credentials attribute type + + The credentials type record pointed to by \a type defines a new + credential attribute type. The \a id member of \a type may be set + to KCDB_TYPE_INVALID to indicate that an attribute ID is to be + generated automatically. + + \param[in] type The type descriptor + \param[out] new_id Receives the identifier for the credential attribute type. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_type_register(const kcdb_type * type, + khm_int32 * new_id); + +/*! \brief Unregister a credential attribute type + + Removes the registration for the specified credentials attribute + type. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_type_unregister(khm_int32 id); + +KHMEXP khm_int32 KHMAPI +kcdb_type_get_next_free(khm_int32 * id); + +/*! \name Conversion functions +@{*/ +/*! \brief Convert a time_t value to FILETIME +*/ +KHMEXP void KHMAPI +TimetToFileTime( time_t t, LPFILETIME pft ); + +/*! \brief Convert a time_t interval to a FILETIME interval +*/ +KHMEXP void KHMAPI +TimetToFileTimeInterval(time_t t, LPFILETIME pft); + +/*! \brief Convert a FILETIME interval to seconds +*/ +KHMEXP long KHMAPI +FtIntervalToSeconds(LPFILETIME pft); + +/*! \brief Convert a FILETIME interval to milliseconds +*/ +KHMEXP long KHMAPI +FtIntervalToMilliseconds(LPFILETIME pft); + +/*! \brief Compare two FILETIME values + + The return value is similar to the return value of strcmp(), based + on the comparison of the two FILETIME values. + */ +KHMEXP long KHMAPI +FtCompare(LPFILETIME pft1, LPFILETIME pft2); + +/*! \brief Convert a FILETIME to a 64 bit int +*/ +KHMEXP khm_int64 KHMAPI FtToInt(LPFILETIME pft); + +/*! \brief Convert a 64 bit int to a FILETIME +*/ +KHMEXP FILETIME KHMAPI IntToFt(khm_int64 i); + +/*! \brief Calculate the difference between two FILETIMEs + + Returns the value of ft1 - ft2 + */ +KHMEXP FILETIME KHMAPI FtSub(LPFILETIME ft1, LPFILETIME ft2); + +/*! \brief Calculate the sum of two FILETIMEs + + Return the value of ft1 + ft2 + */ +KHMEXP FILETIME KHMAPI FtAdd(LPFILETIME ft1, LPFILETIME ft2); + +/*! \brief Convert a FILETIME inverval to a string +*/ +KHMEXP khm_int32 KHMAPI +FtIntervalToString(LPFILETIME data, + wchar_t * buffer, + khm_size * cb_buf); + +/*! \brief Parse a string representing an interval into a FILETIME interval + + The string is a localized string which should look like the + following: + + \code + [number unit] [number unit]... + \endcode + + where \a number is an integer while \a unit is a localized + (possibly abbreviated) unit specification. The value of the + described interval is calculated as the sum of each \a number in + \a units. For example : + + \code + 1 hour 36 minutes + \endcode + + would result in an interval specification that's equivalent to 1 + hour and 36 minutes. Of course there is no restriction on the + order in which the \a number \a unit specifications are given and + the same unit may be repeated multiple times. + + \retval KHM_ERROR_INVALID_PARAM The given string was invalid or had + a token that could not be parsed. It can also mean that \a + pft was NULL or \a str was NULL. + + \retval KHM_ERROR_SUCCESS The string was successfully parsed and + the result was placed in \a pft. +*/ +KHMEXP khm_int32 KHMAPI +IntervalStringToFt(FILETIME * pft, wchar_t * str); + +/*! \brief Return number of milliseconds till next representation change + + Returns the number of milliseconds that must elapse away from the + interval specified in pft \a for the representation of pft to change + from whatever it is right now. + + Returns 0 if the representation is not expected to change. +*/ +KHMEXP long KHMAPI +FtIntervalMsToRepChange(LPFILETIME pft); + +/*! \brief Convert a safe ANSI string to a Unicode string + + The resulting string is guaranteed to be NULL terminated and + within the size limit set by \a cbwstr. + + If the whole string cannot be converted, \a wstr is set to an + empty string. + + \return the number of characters converted. This is always either + the length of the string \a astr or 0. +*/ +KHMEXP int KHMAPI +AnsiStrToUnicode( wchar_t * wstr, size_t cbwstr, const char * astr); + +/*! \brief Convert a Unicode string to ANSI + + The resulting string is guaranteed to be NULL terminated and + within the size limit set by \a cbdest. + + \return the number of characters converted. This is always either + the length of the string \a src or 0. +*/ +KHMEXP int KHMAPI +UnicodeStrToAnsi( char * dest, size_t cbdest, const wchar_t * src); +/*@}*/ + +/*! \name Standard type identifiers and names +@{*/ + +/*! Maximum identifier number */ +#define KCDB_TYPE_MAX_ID 255 + +/*! \brief Invalid type + + Used by functions that return a type identifier to indicate that + the returned type identifier is invalid. Also used to indicate + that a type identifier is not available */ +#define KCDB_TYPE_INVALID (-1) + +/*! \brief All types + + Used by filters to indicate that all types are allowed. +*/ +#define KCDB_TYPE_ALL KCDB_TYPE_INVALID + +/*! \brief Void + + No data. This is not an actual data type. + */ +#define KCDB_TYPE_VOID 0 + +/*! \brief String + + NULL terminated Unicode string. The byte count for a string + attribute always includes the terminating NULL. + */ +#define KCDB_TYPE_STRING 1 + +/*! \brief Data + + A date/time represented in FILETIME format. + */ +#define KCDB_TYPE_DATE 2 + +/*! \brief Interval + + An interval of time represented as the difference between two + FILETIME values. + */ +#define KCDB_TYPE_INTERVAL 3 + +/*! \brief 32-bit integer + + A 32-bit signed integer. + */ +#define KCDB_TYPE_INT32 4 + +/*! \brief 64-bit integer + + A 64-bit integer. + */ +#define KCDB_TYPE_INT64 5 + +/*! \brief Raw data + + A raw data buffer. + */ +#define KCDB_TYPE_DATA 6 + +#define KCDB_TYPENAME_VOID L"Void" +#define KCDB_TYPENAME_STRING L"String" +#define KCDB_TYPENAME_DATE L"Date" +#define KCDB_TYPENAME_INTERVAL L"Interval" +#define KCDB_TYPENAME_INT32 L"Int32" +#define KCDB_TYPENAME_INT64 L"Int64" +#define KCDB_TYPENAME_DATA L"Data" +/*@}*/ +/*@}*/ + +/********************************************************************/ + +/*! \defgroup kcdb_credattr Credential attributes */ +/*@{*/ + +/*! \brief Prototype callback function for computed data types. + + If the flags for a particular attribute specifies that the value + is computed, then a callback function should be specified. The + callback function will be called with a handle to a credential + along with the attribute ID for the requested attribute. The + function should place the computed value in \a buffer. The size + of the buffer in bytes is specifed in \a cbsize. However, if \a + buffer is \a NULL, then the required buffer size should be placed + in \a cbsize. + */ +typedef khm_int32 +(KHMAPI *kcdb_attrib_compute_cb)(khm_handle cred, + khm_int32 id, + void * buffer, + khm_size * cbsize); + +/*! \brief Credential attribute descriptor + + \see kcdb_attrib_register() +*/ +typedef struct tag_kcdb_attrib { + wchar_t * name; /*!< Name. (Not localized, + required) */ + khm_int32 id; /*!< Identifier. When registering, + this can be set to + ::KCDB_ATTR_INVALID if a unique + identifier is to be generated. */ + khm_int32 alt_id; /*!< Alternate identifier. If the \a + flags specify + ::KCDB_ATTR_FLAG_ALTVIEW, then this + field should specify the identifier + of the canonical attribute from + which this attribute is derived. */ + khm_int32 flags; /*!< Flags. Combination of \ref + kcdb_credattr_flags "attribute + flags" */ + + khm_int32 type; /*!< Type of the attribute. Must be valid. */ + + wchar_t * short_desc; /*!< Short description. (Localized, + optional) */ + + wchar_t * long_desc; /*!< Long description. (Localized, + optional) */ + + kcdb_attrib_compute_cb compute_cb; + /*!< Callback. Required if \a flags + specify ::KCDB_ATTR_FLAG_COMPUTED. */ + + khm_size compute_min_cbsize; + /*!< Minimum number of bytes required + to store this attribute. Required + if ::KCDB_ATTR_FLAG_COMPUTED is + specified.*/ + khm_size compute_max_cbsize; + /*!< Maximum number of bytes required + to store this attribute. Required + if ::KCDB_ATTR_FLAG_COMPUTED is + specified.*/ +} kcdb_attrib; + +/*! \brief Retrieve the ID of a named attribute */ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_get_id(const wchar_t *name, + khm_int32 * id); + +/*! \brief Register an attribute + + \param[out] new_id Receives the ID of the newly registered + attribute. If the \a id member of the ::kcdb_attrib object is + set to KCDB_ATTR_INVALID, then a unique ID is generated. */ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_register(const kcdb_attrib * attrib, + khm_int32 * new_id); + +/*! \brief Retrieve the attribute descriptor for an attribute + + The descriptor that is returned must be released through a call to + kcdb_attrib_release_info() + + If only the validity of the attribute identifier needs to be + checked, you can pass in NULL for \a attrib. In this case, if the + identifier is valid, then the funciton will return + KHM_ERROR_SUCCESS, otherwise it will return KHM_ERROR_NOT_FOUND. + + \see kcdb_attrib_release_info() + */ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_get_info(khm_int32 id, + kcdb_attrib ** attrib); + +/*! \brief Release an attribute descriptor + + \see kcdb_attrib_get_info() + */ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_release_info(kcdb_attrib * attrib); + +/*! \brief Unregister an attribute + + Once an attribute ID has been unregistered, it may be reclaimed by + a subsequent call to kcdb_attrib_register(). +*/ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_unregister(khm_int32 id); + +/*! \brief Retrieve the description of an attribute + + \param[in] flags Specify \a KCDB_TS_SHORT to retrieve the short description. */ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_describe(khm_int32 id, + wchar_t * buffer, + khm_size * cbsize, + khm_int32 flags); + +/*! \brief Count attributes + + Counts the number of attributes that match the given criteria. + The criteria is specified against the flags of the attribute. An + attribute is a match if its flags satisfy the condition below: + + \code + (attrib.flags & and_flags) == (eq_flags & and_flags) + \endcode + + The number of attributes that match are returned in \a pcount. + */ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_get_count(khm_int32 and_flags, + khm_int32 eq_flags, + khm_size * pcount); + +/*! \brief List attribute identifiers + + Lists the identifiers of the attributes that match the given + criteria. The criteria is specified against the flags of the + attribute. An attribute is a match if the following condition is + satisfied: + + \code + (attrib.flags & and_flags) == (eq_flags & and_flags) + \endcode + + The list of attributes found are copied to the \a khm_int32 array + specified in \a plist. The number of elements available in the + buffer \a plist is specified in \a pcsize. On exit, \a pcsize + will hold the actual number of attribute identifiers copied to the + array. + + \param[in] and_flags See above + \param[in] eq_flags See above + \param[in] plist A khm_int32 array + \param[in,out] pcsize On entry, holds the number of elements + available in the array pointed to by \a plist. On exit, holds + the number of elements copied to the array. + + \retval KHM_ERROR_SUCCESS The list of attribute identifiers have + been copied. + \retval KHM_ERROR_TOO_LONG The list was too long to fit in the + supplied buffer. As many elements as possible have been + copied to the \a plist array and the required number of + elements has been written to \a pcsize. + + \note The \a pcsize parameter specifies the number of khm_int32 + elements in the array and not the number of bytes in the + array. This is different from the usual size parameters used + in the NetIDMgr API. + */ +KHMEXP khm_int32 KHMAPI +kcdb_attrib_get_ids(khm_int32 and_flags, + khm_int32 eq_flags, + khm_int32 * plist, + khm_size * pcsize); + +/*! \defgroup kcdb_credattr_flags Attribute flags */ +/*@{*/ +/*! \brief The attribute is required */ +#define KCDB_ATTR_FLAG_REQUIRED 0x00000008 + +/*! \brief The attribute is computed. + + If this flag is set, the \a compute_cb, \a compute_min_cbsize and + \a compute_max_cbsize members of the ::kcdb_attrib attribute + descriptor must be assigned valid values. +*/ +#define KCDB_ATTR_FLAG_COMPUTED 0x00000010 + +/*! \brief System attribute. + + This cannot be specified for a custom attribute. Implies that the + value of the attribute is given by the credentials database + itself. +*/ +#define KCDB_ATTR_FLAG_SYSTEM 0x00000020 + +/*! \brief Hidden + + The attribute is not meant to be displayed to the user. Setting + this flag prevents this attribute from being listed in the list of + available data fields in the UI. +*/ +#define KCDB_ATTR_FLAG_HIDDEN 0x00000040 + +/*! \brief Property + + The attribute is a property. The main difference between regular + attributes and properties are that properties are not allocated + off the credentials record. Hence, a property can not be used as + a credentials field. Other objects such as identities can hold + property sets. A property set can hold both regular attributes as + well as properties. +*/ +#define KCDB_ATTR_FLAG_PROPERTY 0x00000080 + +/*! \brief Volatile + + A volatile property is one whose value changes often, such as + ::KCDB_ATTR_TIMELEFT. Some controls will make use of additional + logic to deal with such values, or not display them at all. + */ +#define KCDB_ATTR_FLAG_VOLATILE 0x00000100 + +/*! \brief Alternate view + + The attribute is actually an alternate representation of another + attribute. The Canonical attribute name is specified in \a + alt_id. + + Sometimes a certain attribute may need to be represented in + different ways. You can register multiple attributes for each + view. However, you should also provide a canonical attribute for + whenever the canonical set of attributes of the credential is + required. + */ +#define KCDB_ATTR_FLAG_ALTVIEW 0x00000200 + +/*! \brief Transient attribute + + A transient attribute is one whose absence is meaningful. When + updating one record using another, if a transient attribute is + absent in the source but present in the destination, then the + attribute is removed from the destination. +*/ +#define KCDB_ATTR_FLAG_TRANSIENT 0x00000400 + +/*@}*/ + +/*! \defgroup kcdb_credattr_idnames Standard attribute IDs and names */ +/*@{*/ + +/*! \name Attribute related constants */ +/*@{*/ +/*! \brief Maximum valid attribute ID */ +#define KCDB_ATTR_MAX_ID 255 + +/*! \brief Minimum valid property ID */ +#define KCDB_ATTR_MIN_PROP_ID 4096 + +/*! \brief Maximum number of properties */ +#define KCDB_ATTR_MAX_PROPS 128 + +/*! \brief Maximum valid property ID */ +#define KCDB_ATTR_MAX_PROP_ID (KCDB_ATTR_MIN_PROP_ID + KCDB_ATTR_MAX_PROPS - 1) + +/*! \brief Invalid ID */ +#define KCDB_ATTR_INVALID (-1) + +/*! \brief First custom attribute ID */ +#define KCDB_ATTRID_USER 20 + +/*@}*/ + +/*!\name Attribute identifiers */ +/*@{*/ +/*! \brief Name of the credential + + - \b Type: STRING + - \b Flags: REQUIRED, COMPUTED, SYSTEM + */ +#define KCDB_ATTR_NAME 0 + +/*! \brief The identity handle for the credential + + - \b Type: INT64 + - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN + + \note The handle returned in by specifying this attribute to + kcdb_cred_get_attr() or kcdb_cred_get_attrib() is not held. + While the identity is implicitly held for the duration that + the credential is held, it is not recommended to obtain a + handle to the identity using this method. Use + kcdb_cred_get_identity() instead. +*/ +#define KCDB_ATTR_ID 1 + +/*! \brief The name of the identity + + - \b Type: STRING + - \b Flags: REQUIRED, COMPUTED, SYSTEM + */ +#define KCDB_ATTR_ID_NAME 2 + +/*! \brief The type of the credential + + - \b Type: INT32 + - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN +*/ +#define KCDB_ATTR_TYPE 3 + +/*! \brief Type name for the credential + + - \b Type: STRING + - \b Flags: REQUIRED, COMPUTED, SYSTEM +*/ +#define KCDB_ATTR_TYPE_NAME 4 + +/*! \brief Name of the parent credential + + - \b Type: STRING + - \b Flags: SYSTEM +*/ +#define KCDB_ATTR_PARENT_NAME 5 + +/*! \brief Issed on + + - \b Type: DATE + - \b Flags: SYSTEM +*/ +#define KCDB_ATTR_ISSUE 6 + +/*! \brief Expires on + + - \b Type: DATE + - \b Flags: SYSTEM +*/ +#define KCDB_ATTR_EXPIRE 7 + +/*! \brief Renewable period expires on + + - \b Type: DATE + - \b Flags: SYSTEM +*/ +#define KCDB_ATTR_RENEW_EXPIRE 8 + +/*! \brief Time left till expiration + + - \b Type: INTERVAL + - \b Flags: SYSTEM, COMPUTED, VOLATILE +*/ +#define KCDB_ATTR_TIMELEFT 9 + +#define KCDB_ATTR_RENEW_TIMELEFT 10 + +/*! \brief Location of the credential + + - \b Type: STRING + - \b Flags: SYSTEM +*/ +#define KCDB_ATTR_LOCATION 11 + +/*! \brief Lifetime of the credential + + - \b Type: INTERVAL + - \b Flags: SYSTEM +*/ +#define KCDB_ATTR_LIFETIME 12 + +#define KCDB_ATTR_RENEW_LIFETIME 13 + +/*! \brief Flags for the credential + + - \b Type: INT32 + - \b Flags: REQUIRED, COMPUTED, SYSTEM, HIDDEN + */ +#define KCDB_ATTR_FLAGS 14 + +/*@}*/ + +/*!\name Attribute names */ +/*@{ */ + +#define KCDB_ATTRNAME_NAME L"Name" +#define KCDB_ATTRNAME_ID L"Identity" +#define KCDB_ATTRNAME_ID_NAME L"IdentityName" +#define KCDB_ATTRNAME_TYPE L"TypeId" +#define KCDB_ATTRNAME_TYPE_NAME L"TypeName" +#define KCDB_ATTRNAME_FLAGS L"Flags" + +#define KCDB_ATTRNAME_PARENT_NAME L"Parent" +#define KCDB_ATTRNAME_ISSUE L"Issued" +#define KCDB_ATTRNAME_EXPIRE L"Expires" +#define KCDB_ATTRNAME_RENEW_EXPIRE L"RenewExpires" +#define KCDB_ATTRNAME_TIMELEFT L"TimeLeft" +#define KCDB_ATTRNAME_RENEW_TIMELEFT L"RenewTimeLeft" +#define KCDB_ATTRNAME_LOCATION L"Location" +#define KCDB_ATTRNAME_LIFETIME L"Lifetime" +#define KCDB_ATTRNAME_RENEW_LIFETIME L"RenewLifetime" + +/*@}*/ + +/*@}*/ + +/*@}*/ + +/*****************************************************************************/ + +/*! \defgroup kcdb_credtype Credential types */ +/*@{*/ + +/*! \brief Credential type descriptor */ +typedef struct tag_kcdb_credtype { + wchar_t * name; /*!< name (less than KCDB_MAXCB_NAME bytes) */ + khm_int32 id; + wchar_t * short_desc; /*!< short localized description (less + than KCDB_MAXCB_SHORT_DESC bytes) */ + wchar_t * long_desc; /*!< long localized descriptionn (less + than KCDB_MAXCB_LONG_DESC bytes) */ + khm_handle sub; /*!< Subscription for credentials type + hander. This should be a valid + subscription constructed through a + call to kmq_create_subscription() + and must handle KMSG_CRED messages + that are marked as being sent to + type specific subscriptions. + + The subscription will be + automatically deleted with a call to + kmq_delete_subscription() when the + credentials type is unregistered.*/ + + kcdb_cred_comp_func is_equal; /*!< Used as an additional clause + when comparing two credentials for + equality. The function this is + actually a comparison function, it + should return zero if the two + credentials are equal and non-zero + if they are not. The addtional \a + rock parameter is always zero. + + It can be assumed that the identity, + name and credentials type have + already been found to be equal among + the credentials and the credential + type is the type that is being + registered.*/ + +#ifdef _WIN32 + HICON icon; +#endif +} kcdb_credtype; + +/*! \brief Maximum value of a credential type identifier + + Credential type identifiers are assigned serially unless the + process registering the credential type sets a specific identity. + The maximum identifier number places a hard limit to the number of + credential types that can be registered at one time, which is + KCDB_CREDTYPE_MAX_ID + 1. + */ +#define KCDB_CREDTYPE_MAX_ID 31 + +/*! \brief Specify all credential types + + This value is used by functions which filter credentials based on + credential types. Specifying this value tells the filter to + accept all credential types. + */ +#define KCDB_CREDTYPE_ALL (-1) + +/*! \brief Automatically determine a credential type identifier + + Used with kcdb_credtype_register() to specify that the credential + type identifier should be automatically determined to avoid + collisions. + */ +#define KCDB_CREDTYPE_AUTO (-2) + +/*! \brief An invalid credential type + + Even though any non positive credential type ID is invalid + anywhere where a specific credential type ID is required, this + value is provided for explicit indication that the credential type + is invalid. Also it makes code more readable to have a constant + that shouts out INVALID. + +*/ +#define KCDB_CREDTYPE_INVALID (-3) + +/*! \brief Macro predicate for testing whether a credtype is valid + + Returns TRUE if the given credtype is valid. This is a safe + macro. +*/ +#define KCDB_CREDTYPE_IS_VALID(t) ((t) >= 0) + +/*! \brief Register a credentials type. + + The information given in the \a type parameter is used to register + a new credential type. Note that the \a name member of the \a + type should be unique among all credential types. + + You can specify ::KCDB_CREDTYPE_AUTO as the \a id member of \a + type to let kcdb_credtype_register() determine a suitable + credential type identifier. You can subsequently call + kcdb_credtype_get_id() to retrieve the generated id or pass a + valid pointer to a khm_int32 type variable as \a new_id. + + \param[in] type Credential type descriptor + + \param[out] new_id The credential type identifier that this type + was registered as. + + \retval KHM_ERROR_SUCCESS The credential type was successfully registered. + + \retval KHM_ERROR_INVALID_PARAM One or more of the parameters were invalid + + \retval KHM_ERROR_TOO_LONG One or more of the string fields in \a + type exceeded the character limit for that field. + + \retval KHM_ERROR_NO_RESOURCES When autogenerating credential type + identifiers, this value indicates that the maximum number of + credential types have been registered. No more registrations + can be accepted unless some credentials type is unregisred. + + \retval KHM_ERROR_DUPLICATE The \a name or \a id that was + specified is already in use. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credtype_register(const kcdb_credtype * type, + khm_int32 * new_id); + +/*! \brief Return a held reference to a \a kcdb_credtype object describing the credential type. + + The reference points to a static internal object of type \a + kcdb_credtype. Use the kcdb_credtype_release_info() function to + release the reference. + + Also, the structure passed in as the \a type argument to + kcdb_credtype_register() is not valid as a credential type + descriptor. Use kcdb_credtype_get_info() to obtain the actual + credential type descriptor. + + \param[in] id Credentials type identifier. + + \param[out] type Receives the credentials descriptor handle. If + \a type is NULL, then no handle is returned. However, the + function will still return \a KHM_ERROR_SUCCESS if the \a id + parameter passed in is a valid credentials type identifier. + + \see kcdb_credtype_release_info() + \see kcdb_credtype_register() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_credtype_get_info(khm_int32 id, + kcdb_credtype ** type); + +/*! \brief Release a reference to a \a kcdb_credtype object + + Undoes the hold obtained on a \a kcdb_credtype object from a + previous call to kcdb_credtype_get_info(). + + \see kcdb_credtype_get_info() + */ +KHMEXP khm_int32 KHMAPI +kcdb_credtype_release_info(kcdb_credtype * type); + +/*! \brief Unregister a credentials type + + Undoes the registration performed by kcdb_credtype_register(). + + This should only be done when the credentials provider is being + unloaded. + */ +KHMEXP khm_int32 KHMAPI +kcdb_credtype_unregister(khm_int32 id); + +/*! \brief Retrieve the name of a credentials type + + Given a credentials type identifier, retrieves the name. The name + is not localized and serves as a persistent identifier of the + credentials type. + + \param[out] buf The buffer to receive the name. Could be \a NULL + if only the length of the buffer is required. + + \param[in,out] cbbuf On entry, specifies the size of the buffer + pointed to by \a buf if \a buf is not NULL. On exit, contains + the number of bytes copied to \a buf or the required size of + the buffer. + + \retval KHM_ERROR_SUCCESS The call succeeded. + + \retval KHM_ERROR_TOO_LONG Either \a buf was NULL or the supplied + buffer was not large enough. The required size is in \a cbbuf. + + \retval KHM_ERROR_INVALID_PARAM Invalid parameter. + */ +KHMEXP khm_int32 KHMAPI +kcdb_credtype_get_name(khm_int32 id, + wchar_t * buf, + khm_size * cbbuf); + +/*! \brief Retrieve the type specific subscription for a type + + Given a credentials type, this function returns the credentials + type specific subcription. It may return NULL if the subscription + is not available. + */ +KHMEXP khm_handle KHMAPI +kcdb_credtype_get_sub(khm_int32 id); + +/*! \brief Get the description of a credentials type + + Unlike the name of a credential type, the description is localized. + + \param[in] id Credentials type identifier + + \param[out] buf Receives the description. Can bet set to NULL if + only the size of the buffer is required. + + \param[in,out] cbbuf On entry, specifies the size of the buffer + pointed to by \a buf. On exit, specifies the required size of + the buffer or the number of bytes copied, depending on whether + the call succeeded or not. + + \param[in] flags Specify ::KCDB_TS_SHORT if the short version of + the description is desired if there is more than one. + + \retval KHM_ERROR_SUCCESS The call succeeded + \retval KHM_ERROR_TOO_LONG Either \a buf was NULL or the supplied buffer was insufficient. The required size is specified in \a cbbuf. + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid. + */ +KHMEXP khm_int32 KHMAPI +kcdb_credtype_describe(khm_int32 id, + wchar_t * buf, + khm_size * cbbuf, + khm_int32 flags); + +/*! \brief Look up the identifier of a credentials type by name + + Given a name, looks up the identifier. + + \param[in] name Name of the credentials type + \param[out] id Receives the identifier if the call succeeds + + */ +KHMEXP khm_int32 KHMAPI +kcdb_credtype_get_id(const wchar_t * name, + khm_int32 * id); + +/*@}*/ + +/*********************************************************************/ + +/*! \defgroup kcdb_buf Generic access to buffer + + Currently, credentials and identities both hold record data types. + This set of API's allow an application to access fields in the + records using a single interface. Note that credentials only + accept regular attributes while identities can hold both + attributes and properties. + + Handles to credentials and identities are implicitly also handles + to records. Thus they can be directly used as such. +*/ +/*@{*/ + +/*! \brief Get an attribute from a record by attribute id. + + \param[in] buffer The buffer that is to receive the attribute + value. Set this to NULL if only the required buffer size is + to be returned. + + \param[in,out] cbbuf The number of bytes available in \a buffer. + If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and + sets this to the required buffer size. + + \param[out] attr_type Receives the data type of the attribute. + Set this to NULL if the type is not required. + + \note Set both \a buffer and \a cbbuf to NULL if only the + existence of the attribute is to be checked. If the attribute + exists in this record then the function will return + KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_buf_get_attr(khm_handle record, + khm_int32 attr_id, + khm_int32 * attr_type, + void * buffer, + khm_size * pcb_buf); + +/*! \brief Get an attribute from a record by name. + + \param[in] buffer The buffer that is to receive the attribute + value. Set this to NULL if only the required buffer size is + to be returned. + + \param[in,out] cbbuf The number of bytes available in \a buffer. + If \a buffer is not sufficient, returns KHM_ERROR_TOO_LONG and + sets this to the required buffer size. + + \note Set both \a buffer and \a cbbuf to NULL if only the + existence of the attribute is to be checked. If the attribute + exists in this record then the function will return + KHM_ERROR_SUCCESS, otherwise it returns KHM_ERROR_NOT_FOUND. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_buf_get_attrib(khm_handle record, + const wchar_t * attr_name, + khm_int32 * attr_type, + void * buffer, + khm_size * pcb_buf); + +/*! \brief Get the string representation of a record attribute. + + A shortcut function which generates the string representation of a + record attribute directly. + + \param[in] record A handle to a record + + \param[in] attr_id The attribute to retrieve + + \param[out] buffer A pointer to a string buffer which receives the + string form of the attribute. Set this to NULL if you only + want to determine the size of the required buffer. + + \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry, + holds the size of the buffer pointed to by \a buffer, and on + exit, receives the actual number of bytes that were copied. + + \param[in] flags Flags for the string conversion. Can be set to + one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is + KCDB_TS_LONG. + + \retval KHM_ERROR_SUCCESS Success + \retval KHM_ERROR_NOT_FOUND The given attribute was either invalid + or was not defined for this record + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_TOO_LONG Either \a buffer was NULL or the + supplied buffer was insufficient +*/ +KHMEXP khm_int32 KHMAPI +kcdb_buf_get_attr_string(khm_handle record, + khm_int32 attr_id, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags); + +/*! \brief Get the string representation of a record attribute by name. + + A shortcut function which generates the string representation of a + record attribute directly. + + \param[in] record A handle to a record + + \param[in] attrib The name of the attribute to retrieve + + \param[out] buffer A pointer to a string buffer which receives the + string form of the attribute. Set this to NULL if you only + want to determine the size of the required buffer. + + \param[in,out] pcbbuf A pointer to a #khm_int32 that, on entry, + holds the size of the buffer pointed to by \a buffer, and on + exit, receives the actual number of bytes that were copied. + + \param[in] flags Flags for the string conversion. Can be set to + one of KCDB_TS_LONG or KCDB_TS_SHORT. The default is + KCDB_TS_LONG. + + \see kcdb_cred_get_attr_string() +*/ +KHMEXP khm_int32 KHMAPI +kcdb_buf_get_attrib_string(khm_handle record, + const wchar_t * attr_name, + wchar_t * buffer, + khm_size * pcbbuf, + khm_int32 flags); + +/*! \brief Set an attribute in a record by attribute id + + \param[in] cbbuf Number of bytes of data in \a buffer. The + individual data type handlers may copy in less than this many + bytes in to the record. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_buf_set_attr(khm_handle record, + khm_int32 attr_id, + void * buffer, + khm_size cbbuf); + +/*! \brief Set an attribute in a record by name + + \param[in] cbbuf Number of bytes of data in \a buffer. The + individual data type handlers may copy in less than this many + bytes in to the record. +*/ +KHMEXP khm_int32 KHMAPI +kcdb_buf_set_attrib(khm_handle record, + const wchar_t * attr_name, + void * buffer, + khm_size cbbuf); + +KHMEXP khm_int32 KHMAPI +kcdb_buf_hold(khm_handle record); + +KHMEXP khm_int32 KHMAPI +kcdb_buf_release(khm_handle record); + +/*@}*/ + +/********************************************************************/ + +/* Notification operation constants */ + +#define KCDB_OP_INSERT 1 +#define KCDB_OP_DELETE 2 +#define KCDB_OP_MODIFY 3 +#define KCDB_OP_ACTIVATE 4 +#define KCDB_OP_DEACTIVATE 5 +#define KCDB_OP_HIDE 6 +#define KCDB_OP_UNHIDE 7 +#define KCDB_OP_SETSEARCH 8 +#define KCDB_OP_UNSETSEARCH 9 +#define KCDB_OP_NEW_DEFAULT 10 +#define KCDB_OP_DELCONFIG 11 + +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/kcreddbinternal.h b/krb5-1-6/src/windows/identity/kcreddb/kcreddbinternal.h new file mode 100644 index 000000000..ac07aa75a --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/kcreddbinternal.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCREDDBINTERNAL_H__ +#define __KHIMAIRA_KCREDDBINTERNAL_H__ + +#define _NIMLIB_ + +#include<windows.h> +#include<kcreddb.h> +#include<kmq.h> +#include<khlist.h> +#include<utils.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<kconfig.h> +#include<strsafe.h> + +#include<langres.h> + +#include "buf.h" +#include "identity.h" +#include "attrib.h" +#include "type.h" +#include "credential.h" +#include "credset.h" +#include "credtype.h" + +/* globals */ + +extern HINSTANCE hinst_kcreddb; + +kconf_schema schema_kcdbconfig[]; + +void kcdb_init(void); +void kcdb_exit(void); +khm_handle kcdb_get_config(void); + + +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/kcreddbmain.c b/krb5-1-6/src/windows/identity/kcreddb/kcreddbmain.c new file mode 100644 index 000000000..7702368ce --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/kcreddbmain.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> + +HINSTANCE hinst_kcreddb; + +void +kcdb_process_attach(HINSTANCE hinstDLL) { + hinst_kcreddb = hinstDLL; + kcdb_init(); +} + +void +kcdb_process_detach(void) { + kcdb_exit(); +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/lang/en_us/kcredres.rc b/krb5-1-6/src/windows/identity/kcreddb/lang/en_us/kcredres.rc new file mode 100644 index 000000000..6dce39513 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/lang/en_us/kcredres.rc @@ -0,0 +1,130 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\..\langres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\..\\langres.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE +BEGIN + "..\\..\\langres.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_CREDDB "Khimaira Credentials Database" + IDS_NAME "Service Name" + IDS_IDENTITY "Identity" + IDS_ISSUED "Issued on" + IDS_EXPIRES "Expires on" + IDS_TIMELEFT "Time Remaining" + IDS_LOCATION "Location" + IDS_PARENT "Parent" + IDS_TYPE "Type" + IDS_IVL_EXPIRED "(Expired)" + IDS_IVL_D_H "%I64u days %I64u hours" +END + +STRINGTABLE +BEGIN + IDS_IVL_H_M "%I64u hours %I64u mins" + IDS_IVL_M_S "%I64u mins %I64u secs" + IDS_IVL_S "%I64u seconds" + IDS_IVL_UNKNOWN "(Unknown)" + IDS_LIFETIME "Lifetime" + IDS_IVL_1D "1 day" + IDS_IVL_1H "1 hour" + IDS_IVL_1M "1 minute" + IDS_IVL_1S "1 second" + IDS_IVL_D "%I64u days" + IDS_IVL_H "%I64u hours" + IDS_IVL_M "%I64u minutes" + IDS_IVL_S_SPEC "s,sec,second,seconds,secs" + IDS_IVL_M_SPEC "m,min,mins,minutes" + IDS_IVL_H_SPEC "h,hrs,hours" + IDS_IVL_D_SPEC "d,day,days,ds" +END + +STRINGTABLE +BEGIN + 128 "w,wk,wks,weeks" + IDS_FLAGS "Flags" + IDS_RENEW_TIMELEFT "Renewable Time left" + IDS_RENEW_EXPIRES "Renewable time expires" + IDS_RENEW_LIFETIME "Renewable lifetime" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/krb5-1-6/src/windows/identity/kcreddb/langres.h b/krb5-1-6/src/windows/identity/kcreddb/langres.h new file mode 100644 index 000000000..1c3258b3d --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/langres.h @@ -0,0 +1,48 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\kcreddb\lang\en_us\kcredres.rc +// +#define IDS_CREDDB 101 +#define IDS_NAME 102 +#define IDS_IDENTITY 103 +#define IDS_ISSUED 104 +#define IDS_EXPIRES 105 +#define IDS_TIMELEFT 106 +#define IDS_LOCATION 107 +#define IDS_PARENT 108 +#define IDS_TYPE 109 +#define IDS_IVL_EXPIRED 110 +#define IDS_IVL_D_H 111 +#define IDS_IVL_H_M 112 +#define IDS_IVL_M_S 113 +#define IDS_IVL_S 114 +#define IDS_IVL_UNKNOWN 115 +#define IDS_LIFETIME 116 +#define IDS_IVL_1D 117 +#define IDS_IVL_1H 118 +#define IDS_IVL_1M 119 +#define IDS_IVL_1S 120 +#define IDS_IVL_D 121 +#define IDS_IVL_H 122 +#define IDS_IVL_M 123 +#define IDS_IVL_S_SPEC 124 +#define IDS_IVL_M_SPEC 125 +#define IDS_IVL_H_SPEC 126 +#define IDS_IVL_D_SPEC 127 +#define IDS_IVl_W_SPEC 128 +#define IDS_IVL_W_SPEC 128 +#define IDS_FLAGS 129 +#define IDS_RENEW_TIMELEFT 130 +#define IDS_RENEW_EXPIRES 131 +#define IDS_RENEW_LIFETIME 132 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/resource.h b/krb5-1-6/src/windows/identity/kcreddb/resource.h new file mode 100644 index 000000000..bc587b278 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/resource.h @@ -0,0 +1,27 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by kcreddb.rc +// +#define IDS_PROJNAME 100 +#define IDR_WMDMLOGGER 101 +#define IDS_LOG_SEV_INFO 201 +#define IDS_LOG_SEV_WARN 202 +#define IDS_LOG_SEV_ERROR 203 +#define IDS_LOG_DATETIME 204 +#define IDS_LOG_SRCNAME 205 +#define IDS_DEF_LOGFILE 301 +#define IDS_DEF_MAXSIZE 302 +#define IDS_DEF_SHRINKTOSIZE 303 +#define IDS_DEF_LOGENABLED 304 +#define IDS_MUTEX_TIMEOUT 401 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 201 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/identity/kcreddb/type.c b/krb5-1-6/src/windows/identity/kcreddb/type.c new file mode 100644 index 000000000..e4fd2df2c --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/type.c @@ -0,0 +1,1386 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kcreddbinternal.h> +#include<limits.h> + +CRITICAL_SECTION cs_type; +hashtable * kcdb_type_namemap; +kcdb_type_i ** kcdb_type_tbl; +kcdb_type_i * kcdb_types = NULL; + +/* Void */ + +#define GENERIC_VOID_STR L"(Void)" + +khm_int32 KHMAPI kcdb_type_void_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + size_t cbsize; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + cbsize = sizeof(GENERIC_VOID_STR); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cb_buf, GENERIC_VOID_STR); + + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_boolean KHMAPI kcdb_type_void_isValid( + const void * d, + khm_size cbd) +{ + /* void is always valid, even if d is NULL */ + return TRUE; +} + +khm_int32 KHMAPI kcdb_type_void_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + /* voids can not be compared */ + return 0; +} + +khm_int32 KHMAPI kcdb_type_void_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + if(!cbd_dst) + return KHM_ERROR_INVALID_PARAM; + + *cbd_dst = 0; + + /* copying a void doesn't do much */ + return KHM_ERROR_SUCCESS; +} + + +/* String */ +khm_int32 KHMAPI kcdb_type_string_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + size_t cbsize; + wchar_t * sd; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + sd = (wchar_t *) d; + + if(FAILED(StringCbLength(sd, KCDB_TYPE_MAXCB, &cbsize))) + return KHM_ERROR_INVALID_PARAM; + + cbsize += sizeof(wchar_t); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cb_buf, sd); + + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_boolean KHMAPI kcdb_type_string_isValid( + const void * d, + khm_size cbd) +{ + size_t cbsize; + + if(cbd == KCDB_CBSIZE_AUTO) + cbd = KCDB_TYPE_MAXCB; + + if(FAILED(StringCbLength((wchar_t *) d, cbd, &cbsize))) + return FALSE; + else + return TRUE; +} + +khm_int32 KHMAPI kcdb_type_string_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + return wcscmp((const wchar_t *) d1, (const wchar_t *) d2); +} + +khm_int32 KHMAPI kcdb_type_string_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + size_t cbsize; + + if(!cbd_dst) + return KHM_ERROR_INVALID_PARAM; + + if(cbd_src == KCDB_CBSIZE_AUTO) { + cbd_src = KCDB_TYPE_MAXCB; + } + + if(FAILED(StringCbLength((const wchar_t *) d_src, cbd_src, &cbsize))) { + return KHM_ERROR_UNKNOWN; + } + + cbsize += sizeof(wchar_t); + + if(!d_dst || *cbd_dst < cbsize) { + *cbd_dst = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy((wchar_t *) d_dst, *cbd_dst, (const wchar_t *) d_src); + *cbd_dst = cbsize; + + return KHM_ERROR_SUCCESS; +} + +/* Date and time */ + + +khm_int32 KHMAPI kcdb_type_date_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + size_t cbsize; + size_t cchsize; + wchar_t * bufend; + SYSTEMTIME st_now; + SYSTEMTIME st_d; + SYSTEMTIME st_dl; + FILETIME *ft; + int today = 0; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + ft = (FILETIME *) d; + + GetLocalTime(&st_now); + FileTimeToSystemTime(ft, &st_d); + SystemTimeToTzSpecificLocalTime(NULL, &st_d, &st_dl); + if (st_now.wYear == st_dl.wYear && + st_now.wMonth == st_dl.wMonth && + st_now.wDay == st_dl.wDay) + today = 1; + + if(today && (flags & KCDB_TS_SHORT)) { + cbsize = 0; + } else { + cbsize = GetDateFormat( + LOCALE_USER_DEFAULT, + DATE_SHORTDATE, + &st_dl, + NULL, + NULL, + 0) * sizeof(wchar_t); + } + + cbsize += GetTimeFormat( + LOCALE_USER_DEFAULT, + 0, + &st_dl, + NULL, + NULL, + 0) * sizeof(wchar_t); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + cchsize = cbsize / sizeof(wchar_t); + + if(!today || !(flags & KCDB_TS_SHORT)) { + size_t cch_buf_len; + + GetDateFormat( + LOCALE_USER_DEFAULT, + DATE_SHORTDATE, + &st_dl, + NULL, + buffer, + (int) cchsize); + + StringCchCat(buffer, cchsize, L" "); + + StringCchLength(buffer, cchsize, &cch_buf_len); + + bufend = buffer + cch_buf_len; + cchsize -= cch_buf_len; + } else { + bufend = buffer; + } + + GetTimeFormat( + LOCALE_USER_DEFAULT, + 0, + &st_dl, + NULL, + bufend, + (int) cchsize); + + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_boolean KHMAPI kcdb_type_date_isValid( + const void * d, + khm_size cbd) +{ + return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(FILETIME))); +} + +khm_int32 KHMAPI kcdb_type_date_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + return (khm_int32) CompareFileTime((CONST FILETIME *) d1, (CONST FILETIME *) d2); +} + +khm_int32 KHMAPI kcdb_type_date_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + if(d_dst && *cbd_dst >= sizeof(FILETIME)) { + *cbd_dst = sizeof(FILETIME); + *((FILETIME *) d_dst) = *((FILETIME *) d_src); + return KHM_ERROR_SUCCESS; + } else { + *cbd_dst = sizeof(FILETIME); + return KHM_ERROR_TOO_LONG; + } +} + +/* Interval */ + +/* returns the number of milliseconds that must elapse away from the + interval specified in pft for the representation of pft to change + from whatever it is right now */ +KHMEXP long KHMAPI +FtIntervalMsToRepChange(LPFILETIME pft) +{ + __int64 ms,s,m,h,d; + __int64 ift; + long l; + + ift = FtToInt(pft); + ms = ift / 10000i64; + + if(ms < 0 || ift == _I64_MAX) + return -1; + + s = ms / 1000i64; + m = s / 60; + h = s / 3600; + d = s / (3600*24); + + if (d > 0) { + /* rep change at next hour change */ + l = (long) (ms % (3600*1000i64)); + } else if (h > 0) { + /* rep change at next minute change */ + l = (long) (ms % (60*1000i64)); + } else if (m > 5) { + /* rep change at next minute change */ + l = (long) (ms % (60*1000i64)); + } else { + /* rep change at next second change */ + l = (long) (ms % 1000); + } + + return l; +} + +KHMEXP khm_int32 KHMAPI +FtIntervalToString(LPFILETIME data, wchar_t * buffer, khm_size * cb_buf) +{ + size_t cbsize; + __int64 s,m,h,d; + __int64 ift; + wchar_t ibuf[256]; + wchar_t fbuf[256]; + wchar_t * t; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + ift = FtToInt(data); + s = ift / 10000000i64; + + m = s / 60; + h = s / 3600; + d = s / (3600*24); + + if(ift == _I64_MAX) { +#ifdef INDICATE_UNKNOWN_EXPIRY_TIMES + LoadString(hinst_kcreddb, IDS_IVL_UNKNOWN, ibuf, sizeof(ibuf)/sizeof(wchar_t)); +#else + StringCbCopy(ibuf, sizeof(ibuf), L""); +#endif + } else if(s < 0) { + LoadString(hinst_kcreddb, IDS_IVL_EXPIRED, ibuf, sizeof(ibuf)/sizeof(wchar_t)); + } else if(d > 0) { + h = (s - (d * 3600 * 24)) / 3600; + if(d == 1) { + LoadString(hinst_kcreddb, IDS_IVL_1D, ibuf, ARRAYLENGTH(ibuf)); + } else { + LoadString(hinst_kcreddb, IDS_IVL_D, fbuf, ARRAYLENGTH(fbuf)); + StringCbPrintf(ibuf, sizeof(ibuf), fbuf, d); + } + if(h > 0) { + StringCbCat(ibuf, sizeof(ibuf), L" "); + t = ibuf + wcslen(ibuf); + if(h == 1) + { + LoadString(hinst_kcreddb, IDS_IVL_1H, t, + (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf))); + } else { + LoadString(hinst_kcreddb, IDS_IVL_H, fbuf, + (int) ARRAYLENGTH(fbuf)); + StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, h); + } + } + } else if(h > 0 || m > 5) { + m = (s - (h * 3600)) / 60; + if(h == 1) { + LoadString(hinst_kcreddb, IDS_IVL_1H, ibuf, ARRAYLENGTH(ibuf)); + } else if (h > 1) { + LoadString(hinst_kcreddb, IDS_IVL_H, fbuf, ARRAYLENGTH(fbuf)); + StringCbPrintf(ibuf, sizeof(ibuf), fbuf, h); + } else { + *ibuf = L'\0'; + } + + if(m > 0 || h == 0) { + if (h >= 1) + StringCbCat(ibuf, sizeof(ibuf), L" "); + + t = ibuf + wcslen(ibuf); + if(m == 1) + { + LoadString(hinst_kcreddb, IDS_IVL_1M, t, + (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf))); + } else { + LoadString(hinst_kcreddb, IDS_IVL_M, fbuf, + (int) ARRAYLENGTH(fbuf)); + StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, m); + } + } + } else if(m > 0) { + s -= m * 60; + if(m == 1) { + LoadString(hinst_kcreddb, IDS_IVL_1M, ibuf, ARRAYLENGTH(ibuf)); + } else { + LoadString(hinst_kcreddb, IDS_IVL_M, fbuf, ARRAYLENGTH(fbuf)); + StringCbPrintf(ibuf, sizeof(ibuf), fbuf, m); + } + if(s > 0) { + StringCbCat(ibuf, sizeof(ibuf), L" "); + t = ibuf + wcslen(ibuf); + if(s == 1) + { + LoadString(hinst_kcreddb, IDS_IVL_1S, t, + (int) (ARRAYLENGTH(ibuf) - wcslen(ibuf))); + } else { + LoadString(hinst_kcreddb, IDS_IVL_S, fbuf, + (int) ARRAYLENGTH(fbuf)); + StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, s); + } + } + } else { + if(s == 1) { + LoadString(hinst_kcreddb, IDS_IVL_1S, ibuf, ARRAYLENGTH(ibuf)); + } else { + LoadString(hinst_kcreddb, IDS_IVL_S, fbuf, sizeof(fbuf)/sizeof(wchar_t)); + StringCbPrintf(ibuf, sizeof(ibuf), fbuf, s); + } + } + + StringCbLength(ibuf, sizeof(ibuf), &cbsize); + cbsize += sizeof(wchar_t); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cb_buf, ibuf); + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_int32 KHMAPI +kcdb_type_interval_toString(const void * data, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + return FtIntervalToString((LPFILETIME) data, buffer, cb_buf); +} + +khm_boolean KHMAPI kcdb_type_interval_isValid( + const void * d, + khm_size cbd) +{ + return (d && (cbd == sizeof(FILETIME) || cbd == KCDB_CBSIZE_AUTO)); +} + +khm_int32 KHMAPI kcdb_type_interval_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + __int64 i1, i2; + + i1 = FtToInt((FILETIME *) d1); + i2 = FtToInt((FILETIME *) d2); + + if(i1 < i2) + return -1; + else if(i1 > i2) + return 1; + else + return 0; +} + +khm_int32 KHMAPI kcdb_type_interval_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + if(d_dst && *cbd_dst >= sizeof(FILETIME)) { + *cbd_dst = sizeof(FILETIME); + *((FILETIME *) d_dst) = *((FILETIME *) d_src); + return KHM_ERROR_SUCCESS; + } else { + *cbd_dst = sizeof(FILETIME); + return KHM_ERROR_TOO_LONG; + } +} + +/* Int32 */ + +khm_int32 KHMAPI kcdb_type_int32_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + size_t cbsize; + wchar_t ibuf[12]; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + StringCbPrintf(ibuf, sizeof(ibuf), L"%d", *((khm_int32 *) d)); + StringCbLength(ibuf, sizeof(ibuf), &cbsize); + cbsize += sizeof(wchar_t); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf); + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_boolean KHMAPI kcdb_type_int32_isValid( + const void * d, + khm_size cbd) +{ + return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(khm_int32))); +} + +khm_int32 KHMAPI kcdb_type_int32_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + return *((khm_int32 *) d1) - *((khm_int32 *) d2); +} + +khm_int32 KHMAPI kcdb_type_int32_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + if(d_dst && (*cbd_dst >= sizeof(khm_int32))) { + *cbd_dst = sizeof(khm_int32); + *((khm_int32 *) d_dst) = *((khm_int32 *) d_src); + return KHM_ERROR_SUCCESS; + } else { + *cbd_dst = sizeof(khm_int32); + return KHM_ERROR_TOO_LONG; + } +} + +/* Int64 */ + +khm_int32 KHMAPI kcdb_type_int64_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + size_t cbsize; + wchar_t ibuf[22]; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + StringCbPrintf(ibuf, sizeof(ibuf), L"%I64d", *((__int64 *) d)); + StringCbLength(ibuf, sizeof(ibuf), &cbsize); + cbsize += sizeof(wchar_t); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf); + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_boolean KHMAPI kcdb_type_int64_isValid( + const void * d, + khm_size cbd) +{ + return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(__int64))); +} + +khm_int32 KHMAPI kcdb_type_int64_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + __int64 r = *((__int64 *) d1) - *((__int64 *) d2); + return (r==0i64)?0:((r>0i64)?1:-1); +} + +khm_int32 KHMAPI kcdb_type_int64_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + if(d_dst && (*cbd_dst >= sizeof(__int64))) { + *cbd_dst = sizeof(__int64); + *((__int64 *) d_dst) = *((__int64 *) d_src); + return KHM_ERROR_SUCCESS; + } else { + *cbd_dst = sizeof(__int64); + return KHM_ERROR_TOO_LONG; + } +} + +/* Data */ +#define GENERIC_DATA_STR L"(Data)" + +khm_int32 KHMAPI kcdb_type_data_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + size_t cbsize; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + cbsize = sizeof(GENERIC_DATA_STR); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cb_buf, GENERIC_DATA_STR); + + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_boolean KHMAPI kcdb_type_data_isValid( + const void * d, + khm_size cbd) +{ + /* data is always valid */ + if (cbd != 0 && d == NULL) + return FALSE; + else + return TRUE; +} + +khm_int32 KHMAPI kcdb_type_data_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + khm_size pref; + khm_int32 rv = 0; + + pref = min(cbd1, cbd2); + + if (pref == 0) + return (cbd1 < cbd2)? -1 : ((cbd1 > cbd2)? 1 : 0); + + rv = memcmp(d1, d2, pref); + + if (rv == 0) { + return (cbd1 < cbd2)? -1 : ((cbd1 > cbd2)? 1 : 0); + } else { + return rv; + } +} + +khm_int32 KHMAPI kcdb_type_data_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + if(!cbd_dst || cbd_src == KCDB_CBSIZE_AUTO) + return KHM_ERROR_INVALID_PARAM; + + if(!d_dst || *cbd_dst < cbd_src) { + *cbd_dst = cbd_src; + return KHM_ERROR_TOO_LONG; + } else { + *cbd_dst = cbd_src; + memcpy(d_dst, d_src, cbd_src); + return KHM_ERROR_SUCCESS; + } +} + + +void kcdb_type_msg_completion(kmq_message * m) +{ + kcdb_type_release((kcdb_type_i *) m->vparam); +} + +void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t) +{ + kcdb_type_hold(t); + kmq_post_message(KMSG_KCDB, KMSG_KCDB_TYPE, op, (void *) t); +} + +void kcdb_type_init(void) +{ + kcdb_type type; + + InitializeCriticalSection(&cs_type); + kcdb_type_namemap = hash_new_hashtable( + KCDB_TYPE_HASH_SIZE, + hash_string, + hash_string_comp, + kcdb_type_add_ref, + kcdb_type_del_ref); + kcdb_type_tbl = PMALLOC(sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1)); + ZeroMemory(kcdb_type_tbl, sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1)); + kcdb_types = NULL; + + /*TODO: register standard data types */ + + ZeroMemory(&type, sizeof(type)); + type.comp = kcdb_type_void_comp; + type.dup = kcdb_type_void_dup; + type.isValid = kcdb_type_void_isValid; + type.toString = kcdb_type_void_toString; + type.name = KCDB_TYPENAME_VOID; + type.id = KCDB_TYPE_VOID; + + kcdb_type_register(&type, NULL); + + ZeroMemory(&type, sizeof(type)); + type.comp = kcdb_type_string_comp; + type.dup = kcdb_type_string_dup; + type.isValid = kcdb_type_string_isValid; + type.toString = kcdb_type_string_toString; + type.name = KCDB_TYPENAME_STRING; + type.id = KCDB_TYPE_STRING; + type.flags = KCDB_TYPE_FLAG_CB_AUTO; + + kcdb_type_register(&type, NULL); + + ZeroMemory(&type, sizeof(type)); + type.comp = kcdb_type_date_comp; + type.dup = kcdb_type_date_dup; + type.isValid = kcdb_type_date_isValid; + type.toString = kcdb_type_date_toString; + type.name = KCDB_TYPENAME_DATE; + type.id = KCDB_TYPE_DATE; + type.cb_max = sizeof(FILETIME); + type.cb_min = sizeof(FILETIME); + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + + kcdb_type_register(&type, NULL); + + ZeroMemory(&type, sizeof(type)); + type.comp = kcdb_type_interval_comp; + type.dup = kcdb_type_interval_dup; + type.isValid = kcdb_type_interval_isValid; + type.toString = kcdb_type_interval_toString; + type.name = KCDB_TYPENAME_INTERVAL; + type.id = KCDB_TYPE_INTERVAL; + type.cb_max = sizeof(FILETIME); + type.cb_min = sizeof(FILETIME); + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + + kcdb_type_register(&type, NULL); + + ZeroMemory(&type, sizeof(type)); + type.comp = kcdb_type_int32_comp; + type.dup = kcdb_type_int32_dup; + type.isValid = kcdb_type_int32_isValid; + type.toString = kcdb_type_int32_toString; + type.name = KCDB_TYPENAME_INT32; + type.id = KCDB_TYPE_INT32; + type.cb_max = sizeof(khm_int32); + type.cb_min = sizeof(khm_int32); + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + + kcdb_type_register(&type, NULL); + + ZeroMemory(&type, sizeof(type)); + type.comp = kcdb_type_int64_comp; + type.dup = kcdb_type_int64_dup; + type.isValid = kcdb_type_int64_isValid; + type.toString = kcdb_type_int64_toString; + type.name = KCDB_TYPENAME_INT64; + type.id = KCDB_TYPE_INT64; + type.cb_max = sizeof(__int64); + type.cb_min = sizeof(__int64); + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + + kcdb_type_register(&type, NULL); + + ZeroMemory(&type, sizeof(type)); + type.comp = kcdb_type_data_comp; + type.dup = kcdb_type_data_dup; + type.isValid = kcdb_type_data_isValid; + type.toString = kcdb_type_data_toString; + type.name = KCDB_TYPENAME_DATA; + type.id = KCDB_TYPE_DATA; + + kcdb_type_register(&type, NULL); +} + +void kcdb_type_add_ref(const void *key, void *vt) +{ + kcdb_type_hold((kcdb_type_i *) vt); +} + +void kcdb_type_del_ref(const void *key, void *vt) +{ + kcdb_type_release((kcdb_type_i *) vt); +} + +khm_int32 kcdb_type_hold(kcdb_type_i * t) +{ + if(!t) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_type); + t->refcount++; + LeaveCriticalSection(&cs_type); + + return KHM_ERROR_SUCCESS; +} + +khm_int32 kcdb_type_release(kcdb_type_i * t) +{ + if(!t) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_type); + t->refcount--; + kcdb_type_check_and_delete(t->type.id); + LeaveCriticalSection(&cs_type); + + return KHM_ERROR_SUCCESS; +} + +void kcdb_type_exit(void) +{ + EnterCriticalSection(&cs_type); + PFREE(kcdb_type_tbl); + /*TODO: free up the individual types */ + LeaveCriticalSection(&cs_type); + DeleteCriticalSection(&cs_type); +} + +void kcdb_type_check_and_delete(khm_int32 id) +{ + kcdb_type_i * t; + + if(id < 0 || id > KCDB_TYPE_MAX_ID) + return; + + EnterCriticalSection(&cs_type); + t = kcdb_type_tbl[id]; + if(t && !t->refcount) { + kcdb_type_tbl[id] = NULL; + LDELETE(&kcdb_types, t); + /* must already be out of the hash-table, otherwise refcount should not + be zero */ + PFREE(t->type.name); + PFREE(t); + } + LeaveCriticalSection(&cs_type); +} + +KHMEXP khm_int32 KHMAPI kcdb_type_get_id(const wchar_t *name, khm_int32 * id) +{ + kcdb_type_i * t; + size_t cbsize; + + if(FAILED(StringCbLength(name, KCDB_MAXCB_NAME, &cbsize))) { + /* also fails of name is NULL */ + return KHM_ERROR_INVALID_PARAM; + } + + EnterCriticalSection(&cs_type); + t = hash_lookup(kcdb_type_namemap, (void*) name); + LeaveCriticalSection(&cs_type); + + if(!t) { + *id = KCDB_TYPE_INVALID; + return KHM_ERROR_NOT_FOUND; + } else { + *id = t->type.id; + return KHM_ERROR_SUCCESS; + } +} + +KHMEXP khm_int32 KHMAPI kcdb_type_get_info(khm_int32 id, kcdb_type ** info) +{ + kcdb_type_i * t; + + if(id < 0 || id > KCDB_TYPE_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_type); + t = kcdb_type_tbl[id]; + + if (t) + kcdb_type_hold(t); + LeaveCriticalSection(&cs_type); + + if(info) + *info = (kcdb_type *) t; + else if (t) + kcdb_type_release(t); + + return (t)? KHM_ERROR_SUCCESS : KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI kcdb_type_release_info(kcdb_type * info) +{ + return kcdb_type_release((kcdb_type_i *) info); +} + +KHMEXP khm_int32 KHMAPI kcdb_type_get_name(khm_int32 id, wchar_t * buffer, khm_size * cbbuf) +{ + size_t cbsize; + kcdb_type_i * t; + + if(id < 0 || id > KCDB_TYPE_MAX_ID || !cbbuf) + return KHM_ERROR_INVALID_PARAM; + + t = kcdb_type_tbl[id]; + + if(!t) + return KHM_ERROR_NOT_FOUND; + + if(FAILED(StringCbLength(t->type.name, KCDB_MAXCB_NAME, &cbsize))) + return KHM_ERROR_UNKNOWN; + + cbsize += sizeof(wchar_t); + + if(!buffer || *cbbuf < cbsize) { + *cbbuf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cbbuf, t->type.name); + *cbbuf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_type_register(const kcdb_type * type, khm_int32 * new_id) +{ + kcdb_type_i *t; + size_t cbsize; + khm_int32 type_id; + + if(!type || + !type->comp || + !type->dup || + !type->isValid || + !type->toString || + !type->name) + return KHM_ERROR_INVALID_PARAM; + + if((type->flags & KCDB_TYPE_FLAG_CB_MIN) && + (type->cb_min < 0 || type->cb_min > KCDB_TYPE_MAXCB)) + { + return KHM_ERROR_INVALID_PARAM; + } + + if((type->flags & KCDB_TYPE_FLAG_CB_MAX) && + (type->cb_max < 0 || type->cb_max > KCDB_TYPE_MAXCB)) + { + return KHM_ERROR_INVALID_PARAM; + } + + if((type->flags & KCDB_TYPE_FLAG_CB_MIN) && + (type->flags & KCDB_TYPE_FLAG_CB_MAX) && + (type->cb_max < type->cb_min)) + { + return KHM_ERROR_INVALID_PARAM; + } + + if(FAILED(StringCbLength(type->name, KCDB_MAXCB_NAME, &cbsize))) + return KHM_ERROR_TOO_LONG; + + cbsize += sizeof(wchar_t); + + EnterCriticalSection(&cs_type); + if(type->id == KCDB_TYPE_INVALID) { + kcdb_type_get_next_free(&type_id); + } else if(type->id < 0 || type->id > KCDB_TYPE_MAX_ID) { + LeaveCriticalSection(&cs_type); + return KHM_ERROR_INVALID_PARAM; + } else if(kcdb_type_tbl[type->id]) { + LeaveCriticalSection(&cs_type); + return KHM_ERROR_DUPLICATE; + } else { + type_id = type->id; + } + + if(type_id == KCDB_TYPE_INVALID) { + LeaveCriticalSection(&cs_type); + return KHM_ERROR_NO_RESOURCES; + } + + t = PMALLOC(sizeof(kcdb_type_i)); + ZeroMemory(t, sizeof(kcdb_type_i)); + + t->type.name = PMALLOC(cbsize); + StringCbCopy(t->type.name, cbsize, type->name); + + t->type.comp = type->comp; + t->type.dup = type->dup; + t->type.flags = type->flags; + t->type.id = type_id; + t->type.isValid = type->isValid; + t->type.toString = type->toString; + + LINIT(t); + + kcdb_type_tbl[type_id] = t; + LPUSH(&kcdb_types, t); + + hash_add(kcdb_type_namemap, (void *) t->type.name, (void *) t); + + LeaveCriticalSection(&cs_type); + + if(new_id) + *new_id = type_id; + + kcdb_type_post_message(KCDB_OP_INSERT, t); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kcdb_type_unregister(khm_int32 id) +{ + kcdb_type_i * t; + + if(id < 0 || id > KCDB_TYPE_MAX_ID) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_type); + t = kcdb_type_tbl[id]; + if(t) { + kcdb_type_post_message(KCDB_OP_DELETE, t); + /* we are going to remove t from the hash table. If no one is holding + a reference to it, then we can free it (actually, the del_ref code + will take care of that anyway). If there is a hold, then it will + get freed when they release it. + + Actually, the post_message call above pretty much guarantees that + the type has a hold on it.*/ + t->type.flags |= KCDB_TYPE_FLAG_DELETED; + hash_del(kcdb_type_namemap, t->type.name); + } + LeaveCriticalSection(&cs_type); + + if(t) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI kcdb_type_get_next_free(khm_int32 * id) +{ + int i; + + if(!id) + return KHM_ERROR_INVALID_PARAM; + + /* do a linear search because this function only gets called a few times */ + EnterCriticalSection(&cs_type); + for(i=0; i <= KCDB_TYPE_MAX_ID; i++) { + if(!kcdb_type_tbl[i]) + break; + } + LeaveCriticalSection(&cs_type); + + if(i <= KCDB_TYPE_MAX_ID) { + *id = i; + return KHM_ERROR_SUCCESS; + } else { + *id = KCDB_TYPE_INVALID; + return KHM_ERROR_NO_RESOURCES; + } +} + +/* Conversion functions */ + +KHMEXP void KHMAPI TimetToFileTime( time_t t, LPFILETIME pft ) +{ + LONGLONG ll; + + if ( sizeof(time_t) == 4 ) + ll = Int32x32To64(t, 10000000) + 116444736000000000i64; + else { + ll = t * 10000000i64 + 116444736000000000i64; + } + pft->dwLowDateTime = (DWORD) ll; + pft->dwHighDateTime = (DWORD) (ll >> 32); +} + +KHMEXP void KHMAPI TimetToFileTimeInterval(time_t t, LPFILETIME pft) +{ + LONGLONG ll; + + if ( sizeof(time_t) == 4 ) + ll = Int32x32To64(t, 10000000); + else { + ll = t * 10000000i64; + } + pft->dwLowDateTime = (DWORD) ll; + pft->dwHighDateTime = (DWORD) (ll >> 32); +} + +KHMEXP long KHMAPI FtIntervalToSeconds(LPFILETIME pft) +{ + __int64 i = FtToInt(pft); + return (long) (i / 10000000i64); +} + +KHMEXP long KHMAPI FtIntervalToMilliseconds(LPFILETIME pft) +{ + __int64 i = FtToInt(pft); + return (long) (i / 10000i64); +} + +KHMEXP khm_int64 KHMAPI FtToInt(LPFILETIME pft) { + LARGE_INTEGER ll; + ll.LowPart = pft->dwLowDateTime; + ll.HighPart = pft->dwHighDateTime; + return ll.QuadPart; +} + +KHMEXP FILETIME KHMAPI IntToFt(khm_int64 i) { + LARGE_INTEGER ll; + FILETIME ft; + + ll.QuadPart = i; + ft.dwLowDateTime = ll.LowPart; + ft.dwHighDateTime = ll.HighPart; + + return ft; +} + +KHMEXP FILETIME KHMAPI FtSub(LPFILETIME ft1, LPFILETIME ft2) { + FILETIME d; + LARGE_INTEGER l1, l2; + + l1.LowPart = ft1->dwLowDateTime; + l1.HighPart = ft1->dwHighDateTime; + l2.LowPart = ft2->dwLowDateTime; + l2.HighPart = ft2->dwHighDateTime; + + l1.QuadPart -= l2.QuadPart; + + d.dwLowDateTime = l1.LowPart; + d.dwHighDateTime = l1.HighPart; + + return d; +} + +KHMEXP FILETIME KHMAPI FtAdd(LPFILETIME ft1, LPFILETIME ft2) { + FILETIME d; + LARGE_INTEGER l1, l2; + + l1.LowPart = ft1->dwLowDateTime; + l1.HighPart = ft1->dwHighDateTime; + l2.LowPart = ft2->dwLowDateTime; + l2.HighPart = ft2->dwHighDateTime; + + l1.QuadPart += l2.QuadPart; + + d.dwLowDateTime = l1.LowPart; + d.dwHighDateTime = l1.HighPart; + + return d; +} + +KHMEXP int KHMAPI AnsiStrToUnicode( wchar_t * wstr, size_t cbwstr, const char * astr) +{ + size_t nc; + + if(cbwstr == 0) + return 0; + + nc = strlen(astr); + if(nc == MultiByteToWideChar( + CP_ACP, + 0, + astr, + (int) nc, + wstr, + (int)(cbwstr / sizeof(wchar_t) - 1))) { + wstr[nc] = L'\0'; + } else { + wstr[0] = L'\0'; + nc = 0; + } + + return (int) nc; +} + +KHMEXP int KHMAPI UnicodeStrToAnsi( char * dest, size_t cbdest, const wchar_t * src) +{ + size_t nc; + + if(cbdest == 0) + return 0; + + dest[0] = 0; + + if(FAILED(StringCchLength(src, cbdest, &nc)) || nc*sizeof(char) >= cbdest) + // note that cbdest counts the terminating NULL, while nc doesn't + return 0; + + nc = WideCharToMultiByte( + CP_ACP, + WC_NO_BEST_FIT_CHARS, + src, + (int) nc, + dest, + (int) cbdest, + NULL, + NULL); + + dest[nc] = 0; + + return (int) nc; +} + +#define MAX_IVL_SPECLIST_LEN 256 +#define MAX_IVL_UNITS 5 + +enum _ivl_indices { + IVL_SECONDS = 0, + IVL_MINUTES, + IVL_HOURS, + IVL_DAYS, + IVL_WEEKS +}; + +typedef struct ivspec_t { + wchar_t str[MAX_IVL_SPECLIST_LEN]; + __int64 mul; +} ivspec; + +static ivspec ivspecs[MAX_IVL_UNITS]; +static BOOL ivspecs_loaded = FALSE; + +int _iv_is_in_spec(wchar_t *s, int n, wchar_t * spec) +{ + /* spec strigns are comma separated */ + wchar_t *b, *e; + + b = spec; + while(*b) { + e = wcschr(b, L','); + if(!e) + e = b + wcslen(b); + + if((e - b) == n && !_wcsnicmp(b, s, n)) { + return TRUE; + } + + if(*e) + b = e+1; + else + break; + } + + return FALSE; +} + +KHMEXP khm_int32 KHMAPI IntervalStringToFt(FILETIME * pft, wchar_t * str) +{ + size_t cb; + wchar_t * b; + __int64 t; + + *pft = IntToFt(0); + + /* ideally we should synchronize this, but it doesn't hurt if two + threads do this at the same time, because we only set the ivspecs_loaded + flag when we are done */ + if(!ivspecs_loaded) { + LoadString(hinst_kcreddb, IDS_IVL_S_SPEC, ivspecs[IVL_SECONDS].str, MAX_IVL_SPECLIST_LEN); + ivspecs[IVL_SECONDS].mul = 10000000i64; + LoadString(hinst_kcreddb, IDS_IVL_M_SPEC, ivspecs[IVL_MINUTES].str, MAX_IVL_SPECLIST_LEN); + ivspecs[IVL_MINUTES].mul = ivspecs[IVL_SECONDS].mul * 60; + LoadString(hinst_kcreddb, IDS_IVL_H_SPEC, ivspecs[2].str, MAX_IVL_SPECLIST_LEN); + ivspecs[IVL_HOURS].mul = ivspecs[IVL_MINUTES].mul * 60; + LoadString(hinst_kcreddb, IDS_IVL_D_SPEC, ivspecs[3].str, MAX_IVL_SPECLIST_LEN); + ivspecs[IVL_DAYS].mul = ivspecs[IVL_HOURS].mul * 24; + LoadString(hinst_kcreddb, IDS_IVL_W_SPEC, ivspecs[4].str, MAX_IVL_SPECLIST_LEN); + ivspecs[IVL_WEEKS].mul = ivspecs[IVL_DAYS].mul * 7; + + ivspecs_loaded = TRUE; + } + + if(!str || FAILED(StringCbLength(str, MAX_IVL_SPECLIST_LEN, &cb))) + return KHM_ERROR_INVALID_PARAM; + + b = str; + t = 0; + while(*b) { + __int64 f = 1; + wchar_t *e; + int i; + + while(*b && iswspace(*b)) + b++; + + if(*b && iswdigit(*b)) { + f = _wtoi64(b); + + while(*b && iswdigit(*b)) + b++; + } + + while(*b && iswspace(*b)) + b++; + + if(!*b) /* no unit specified */ + return KHM_ERROR_INVALID_PARAM; + + e = b; + + while(*e && !iswspace(*e)) + e++; + + for(i=0; i < MAX_IVL_UNITS; i++) { + if(_iv_is_in_spec(b, (int)(e-b), ivspecs[i].str)) + break; + } + + if(i==MAX_IVL_UNITS) + return KHM_ERROR_INVALID_PARAM; + + t += f * ivspecs[i].mul; + + b = e; + } + + *pft = IntToFt(t); + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/kcreddb/type.h b/krb5-1-6/src/windows/identity/kcreddb/type.h new file mode 100644 index 000000000..698e5f386 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kcreddb/type.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KCDB_TYPE_H +#define __KHIMAIRA_KCDB_TYPE_H + +/* Types */ + +typedef struct kcdb_type_i_t { + kcdb_type type; + + khm_int32 refcount; + + struct kcdb_type_i_t * next; + struct kcdb_type_i_t * prev; +} kcdb_type_i; + +#define KCDB_TYPE_HASH_SIZE 31 + +#define KCDB_TYPE_FLAG_DELETED 8 + +void kcdb_type_init(void); +void kcdb_type_exit(void); +void kcdb_type_add_ref(const void *key, void *vt); +void kcdb_type_del_ref(const void *key, void *vt); +void kcdb_type_msg_completion(kmq_message * m); +khm_int32 kcdb_type_hold(kcdb_type_i * t); +khm_int32 kcdb_type_release(kcdb_type_i * t); +void kcdb_type_check_and_delete(khm_int32 id); +void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t); + +khm_int32 KHMAPI kcdb_type_void_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags); + +khm_boolean KHMAPI kcdb_type_void_isValid( + const void * d, + khm_size cbd); + +khm_int32 KHMAPI kcdb_type_void_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2); + +khm_int32 KHMAPI kcdb_type_void_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst); + +khm_int32 KHMAPI kcdb_type_string_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags); + +khm_boolean KHMAPI kcdb_type_string_isValid( + const void * d, + khm_size cbd); + +khm_int32 KHMAPI kcdb_type_string_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2); + +khm_int32 KHMAPI kcdb_type_string_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst); + +khm_int32 KHMAPI kcdb_type_date_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags); + +khm_boolean KHMAPI kcdb_type_date_isValid( + const void * d, + khm_size cbd); + +khm_int32 KHMAPI kcdb_type_date_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2); + +khm_int32 KHMAPI kcdb_type_date_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst); + +khm_int32 KHMAPI kcdb_type_interval_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags); + +khm_boolean KHMAPI kcdb_type_interval_isValid( + const void * d, + khm_size cbd); + +khm_int32 KHMAPI kcdb_type_interval_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2); + +khm_int32 KHMAPI kcdb_type_interval_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst); + +khm_int32 KHMAPI kcdb_type_int32_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags); + +khm_boolean KHMAPI kcdb_type_int32_isValid( + const void * d, + khm_size cbd); + +khm_int32 KHMAPI kcdb_type_int32_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2); + +khm_int32 KHMAPI kcdb_type_int32_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst); + +khm_int32 KHMAPI kcdb_type_int64_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags); + +khm_boolean KHMAPI kcdb_type_int64_isValid( + const void * d, + khm_size cbd); + +khm_int32 KHMAPI kcdb_type_int64_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2); + +khm_int32 KHMAPI kcdb_type_int64_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst); + +khm_int32 KHMAPI kcdb_type_data_toString( + const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags); + +khm_boolean KHMAPI kcdb_type_data_isValid( + const void * d, + khm_size cbd); + +khm_int32 KHMAPI kcdb_type_data_comp( + const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2); + +khm_int32 KHMAPI kcdb_type_data_dup( + const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst); + +#endif diff --git a/krb5-1-6/src/windows/identity/kherr/Makefile b/krb5-1-6/src/windows/identity/kherr/Makefile new file mode 100644 index 000000000..3972235b3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kherr/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=kherr +!include <../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\kherr.h + +OBJFILES= \ + $(OBJ)\kherrmain.obj \ + $(OBJ)\kherr.obj + +LIBFILES= + +SDKLIBFILES= \ + strsafe.lib + +all: mkdirs $(INCFILES) $(OBJFILES) + +clean:: + if exist ..\obj $(RM) $(INCFILES) diff --git a/krb5-1-6/src/windows/identity/kherr/kherr.c b/krb5-1-6/src/windows/identity/kherr/kherr.c new file mode 100644 index 000000000..8c43fd811 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kherr/kherr.c @@ -0,0 +1,1580 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kherrinternal.h> +#include<assert.h> +#include<stdarg.h> + +CRITICAL_SECTION cs_error; +DWORD tls_error = 0; +kherr_context * ctx_free_list = NULL; +kherr_context * ctx_root_list = NULL; +kherr_context * ctx_error_list = NULL; +kherr_event * evt_free_list = NULL; + +kherr_handler_node * ctx_handlers = NULL; +khm_size n_ctx_handlers; +khm_size nc_ctx_handlers; + +kherr_serial ctx_serial = 0; + +#ifdef DEBUG +#define DEBUG_CONTEXT + +KHMEXP void +kherr_debug_printf(wchar_t * fmt, ...) +{ + va_list vl; + wchar_t buf[1024]; + + va_start(vl, fmt); + StringCbVPrintf(buf, sizeof(buf), fmt, vl); + OutputDebugString(buf); + va_end(vl); +} +#endif + +KHMEXP void KHMAPI +kherr_add_ctx_handler(kherr_ctx_handler h, + khm_int32 filter, + kherr_serial serial) +{ + khm_size idx; + + assert(h); + + EnterCriticalSection(&cs_error); + if( ctx_handlers == NULL) { + nc_ctx_handlers = CTX_ALLOC_INCR; + n_ctx_handlers = 0; + ctx_handlers = PMALLOC(sizeof(*ctx_handlers) * nc_ctx_handlers); + /* No need to initialize */ + } else if (n_ctx_handlers == nc_ctx_handlers) { + khm_size new_nc; + kherr_handler_node * new_ctxs; + + new_nc = nc_ctx_handlers + CTX_ALLOC_INCR; + new_ctxs = PMALLOC(sizeof(*new_ctxs) * new_nc); + memcpy(new_ctxs, ctx_handlers, n_ctx_handlers * sizeof(*new_ctxs)); + + PFREE(ctx_handlers); + ctx_handlers = new_ctxs; + nc_ctx_handlers = new_nc; + } + + if (filter == 0) + filter = KHERR_CTX_BEGIN | + KHERR_CTX_DESCRIBE | + KHERR_CTX_END | + KHERR_CTX_ERROR | + KHERR_CTX_NEWCHILD | + KHERR_CTX_FOLDCHILD; + + /* Since commit events are the most frequent, we put those + handlers at the top of the list. When dispatching a commit + event, we stop looking at the list when we find a filter that + doesn't filter for commit events. */ + if (filter & KHERR_CTX_EVTCOMMIT) { + idx = 0; + memmove(&ctx_handlers[1], &ctx_handlers[0], + n_ctx_handlers * sizeof(ctx_handlers[0])); + } else { + idx = n_ctx_handlers; + } + + ctx_handlers[idx].h = h; + ctx_handlers[idx].filter = filter; + ctx_handlers[idx].serial = serial; + + n_ctx_handlers++; + + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_remove_ctx_handler(kherr_ctx_handler h, + kherr_serial serial) +{ + khm_size i; + EnterCriticalSection(&cs_error); + + for (i=0 ; i < n_ctx_handlers; i++) { + if (ctx_handlers[i].h == h && + ctx_handlers[i].serial == serial) { + break; + } + } + + if ( i < n_ctx_handlers ) { + n_ctx_handlers --; + for (; i < n_ctx_handlers; i++) { + ctx_handlers[i] = ctx_handlers[i + 1]; + } + } + + LeaveCriticalSection(&cs_error); +} + +/* Called with cs_error held */ +static void +notify_ctx_event(enum kherr_ctx_event e, kherr_context * c) +{ + khm_size i; + + kherr_ctx_handler h; + + for (i=0; i<n_ctx_handlers; i++) { + if (ctx_handlers[i].h && (ctx_handlers[i].filter & e) && + (ctx_handlers[i].serial == 0 || + ctx_handlers[i].serial == c->serial)) { + if (IsBadCodePtr((FARPROC) ctx_handlers[i].h)) { + ctx_handlers[i].h = NULL; + } else { + h = ctx_handlers[i].h; + (*h)(e,c); + + /* a context handler is allowed to remove itself + during a callback. It is, however, not allowed to + remove anything else. */ + if (h != ctx_handlers[i].h) + i--; + } + } else if (e == KHERR_CTX_EVTCOMMIT && + !(ctx_handlers[i].filter & KHERR_CTX_EVTCOMMIT)) { + /* All handlers that filter for commit events are at the + top of the list. If this handler wasn't filtering for + it, then there's no point in goint further down the + list. */ + break; + } + } +} + +void +attach_this_thread(void) +{ + kherr_thread * t; + + t = (kherr_thread *) TlsGetValue(tls_error); + if (t) + return; + + t = PMALLOC(sizeof(kherr_thread) + + sizeof(kherr_context *) * THREAD_STACK_SIZE); + t->nc_ctx = THREAD_STACK_SIZE; + t->n_ctx = 0; + t->ctx = (kherr_context **) &t[1]; + + TlsSetValue(tls_error, t); +} + +void +detach_this_thread(void) +{ + kherr_thread * t; + khm_size i; + + t = (kherr_thread *) TlsGetValue(tls_error); + if (t) { + for(i=0; i < t->n_ctx; i++) { + kherr_release_context(t->ctx[i]); + } + PFREE(t); + TlsSetValue(tls_error, 0); + } +} + +static kherr_context * +peek_context(void) +{ + kherr_thread * t; + + t = (kherr_thread *) TlsGetValue(tls_error); + if (t) { + if (t->n_ctx > 0) { + kherr_context * c; + + c = t->ctx[t->n_ctx - 1]; + + assert(c == NULL || IS_KHERR_CTX(c)); + + return c; + } else { + return NULL; + } + } else + return NULL; +} + +static void +push_context(kherr_context * c) +{ + kherr_thread * t; + + t = (kherr_thread *) TlsGetValue(tls_error); + if (!t) { + attach_this_thread(); + t = (kherr_thread *) TlsGetValue(tls_error); + assert(t); + } + + if (t->n_ctx == t->nc_ctx) { + khm_size nc_new; + khm_size cb_new; + kherr_thread * nt; + + nc_new = t->nc_ctx + THREAD_STACK_SIZE; + cb_new = sizeof(kherr_thread) + + sizeof(kherr_context *) * nc_new; + + nt = PMALLOC(cb_new); + memcpy(nt, t, sizeof(kherr_thread) + + sizeof(kherr_context *) * t->n_ctx); + nt->ctx = (kherr_context **) &nt[1]; + nt->nc_ctx = nc_new; + + PFREE(t); + t = nt; + TlsSetValue(tls_error, t); + } + + assert(t->n_ctx < t->nc_ctx); + t->ctx[t->n_ctx++] = c; + + kherr_hold_context(c); +} + +/* returned pointer is still held */ +static kherr_context * +pop_context(void) +{ + kherr_thread * t; + kherr_context * c; + + t = (kherr_thread *) TlsGetValue(tls_error); + if (t) { + if (t->n_ctx > 0) { + c = t->ctx[--(t->n_ctx)]; + assert(IS_KHERR_CTX(c)); + return c; + } else + return NULL; + } else { + return NULL; + } +} + +static kherr_event * +get_empty_event(void) +{ + kherr_event * e; + + EnterCriticalSection(&cs_error); + if(evt_free_list) { + LPOP(&evt_free_list, &e); + } else { + e = PMALLOC(sizeof(*e)); + } + LeaveCriticalSection(&cs_error); + ZeroMemory(e, sizeof(*e)); + e->severity = KHERR_NONE; + e->magic = KHERR_EVENT_MAGIC; + + return e; +} + +static void +free_event_params(kherr_event * e) +{ + assert(IS_KHERR_EVENT(e)); + + if(parm_type(e->p1) == KEPT_STRINGT) { + assert((void *) parm_data(e->p1)); + PFREE((void*) parm_data(e->p1)); + } + ZeroMemory(&e->p1, sizeof(e->p1)); + + if(parm_type(e->p2) == KEPT_STRINGT) { + assert((void *) parm_data(e->p2)); + PFREE((void*) parm_data(e->p2)); + } + ZeroMemory(&e->p2, sizeof(e->p2)); + + if(parm_type(e->p3) == KEPT_STRINGT) { + assert((void *) parm_data(e->p3)); + PFREE((void*) parm_data(e->p3)); + } + ZeroMemory(&e->p3, sizeof(e->p3)); + + if(parm_type(e->p4) == KEPT_STRINGT) { + assert((void *) parm_data(e->p4)); + PFREE((void*) parm_data(e->p4)); + } + ZeroMemory(&e->p4, sizeof(e->p4)); +} + +static void +free_event(kherr_event * e) +{ + EnterCriticalSection(&cs_error); + + assert(IS_KHERR_EVENT(e)); +#ifdef DEBUG + assert(LNEXT(e) == NULL); + assert(LPREV(e) == NULL); +#endif + +#ifdef DEBUG_CONTEXT + if (!(e->flags & KHERR_RF_STR_RESOLVED)) + resolve_event_strings(e); + + if (e->short_desc && e->long_desc) { + kherr_debug_printf(L"E:%s (%s)\n", e->short_desc, e->long_desc); + } else if (e->short_desc) { + kherr_debug_printf(L"E:%s\n", e->short_desc); + } else if (e->long_desc) { + kherr_debug_printf(L"E:%s\n", e->long_desc); + } else { + kherr_debug_printf(L"E:[No description for event 0x%p]\n", e); + } + + if (e->suggestion) + kherr_debug_printf(L" Suggest:[%s]\n", e->suggestion); + if (e->facility) + kherr_debug_printf(L" Facility:[%s]\n", e->facility); +#endif + + if(e->flags & KHERR_RF_FREE_SHORT_DESC) { + assert(e->short_desc); + PFREE((void *) e->short_desc); + } + if(e->flags & KHERR_RF_FREE_LONG_DESC) { + assert(e->long_desc); + PFREE((void *) e->long_desc); + } + if(e->flags & KHERR_RF_FREE_SUGGEST) { + assert(e->suggestion); + PFREE((void *) e->suggestion); + } + + free_event_params(e); + + ZeroMemory(e, sizeof(e)); + + LPUSH(&evt_free_list, e); + LeaveCriticalSection(&cs_error); +} + +static kherr_context * +get_empty_context(void) +{ + kherr_context * c; + + EnterCriticalSection(&cs_error); + if(ctx_free_list) + LPOP(&ctx_free_list, &c); + else { + c = PMALLOC(sizeof(kherr_context)); + } + + ZeroMemory(c,sizeof(*c)); + c->severity = KHERR_NONE; + c->flags = KHERR_CF_UNBOUND; + c->magic = KHERR_CONTEXT_MAGIC; + c->serial = ++ctx_serial; + + LPUSH(&ctx_root_list, c); + + LeaveCriticalSection(&cs_error); + + return c; +} + + +/* Assumes that the context has been deleted from all relevant + lists */ +static void +free_context(kherr_context * c) +{ + kherr_context * ch; + kherr_event * e; + + assert(IS_KHERR_CTX(c)); + +#ifdef DEBUG_CONTEXT + kherr_debug_printf(L"Freeing context 0x%x\n", c); +#endif + + EnterCriticalSection(&cs_error); + + if (c->desc_event) + free_event(c->desc_event); + c->desc_event = NULL; + + TPOPCHILD(c, &ch); + while(ch) { + free_context(ch); + TPOPCHILD(c, &ch); + } + QGET(c, &e); + while(e) { + free_event(e); + QGET(c, &e); + } + + c->serial = 0; + + LPUSH(&ctx_free_list,c); + LeaveCriticalSection(&cs_error); + +#ifdef DEBUG_CONTEXT + kherr_debug_printf(L"Done with context 0x%x\n", c); +#endif +} + +static void +add_event(kherr_context * c, kherr_event * e) +{ + kherr_event * te; + + assert(IS_KHERR_CTX(c)); + assert(IS_KHERR_EVENT(e)); +#ifdef DEBUG + assert(LPREV(e) == NULL && LNEXT(e) == NULL); +#endif + + EnterCriticalSection(&cs_error); + te = QBOTTOM(c); + if (te && !(te->flags & KHERR_RF_COMMIT)) { + notify_ctx_event(KHERR_CTX_EVTCOMMIT, c); + te->flags |= KHERR_RF_COMMIT; + } + + QPUT(c,e); + if(c->severity >= e->severity) { + if (e->severity <= KHERR_ERROR) + notify_ctx_event(KHERR_CTX_ERROR, c); + + c->severity = e->severity; + c->err_event = e; + c->flags &= ~KHERR_CF_DIRTY; + } + LeaveCriticalSection(&cs_error); +} + +static void +pick_err_event(kherr_context * c) +{ + kherr_event * e; + kherr_event * ce = NULL; + enum kherr_severity s; + + s = KHERR_RESERVED_BANK; + + EnterCriticalSection(&cs_error); + e = QTOP(c); + while(e) { + if(!(e->flags & KHERR_RF_INERT) && + s >= e->severity) { + ce = e; + s = e->severity; + } + e = QNEXT(e); + } + + if(ce) { + c->err_event = ce; + c->severity = ce->severity; + } else { + c->err_event = NULL; + c->severity = KHERR_NONE; + } + + c->flags &= ~KHERR_CF_DIRTY; + LeaveCriticalSection(&cs_error); +} + +static void +va_arg_from_param(va_list * parm, kherr_param p) +{ + int t = parm_type(p); + + khm_int32 * pi; + wchar_t ** ps; + void ** pptr; + khm_int64 * pli; + + if (t != KEPT_NONE) { + switch (t) { + case KEPT_INT32: + case KEPT_UINT32: + pi = (khm_int32 *)(*parm); + va_arg(*parm, khm_int32); + *pi = (khm_int32) parm_data(p); + break; + + case KEPT_STRINGC: + case KEPT_STRINGT: + ps = (wchar_t **) (*parm); + va_arg(*parm, wchar_t *); + *ps = (wchar_t *) parm_data(p); + break; + + case KEPT_PTR: + pptr = (void **) (*parm); + va_arg(*parm, void *); + *pptr = (void *) parm_data(p); + break; + + case KEPT_INT64: + case KEPT_UINT64: + pli = (khm_int64 *) (*parm); + va_arg(*parm, khm_int64); + *pli = (khm_int64) parm_data(p); + break; + +#ifdef DEBUG + default: + assert(FALSE); +#endif + } + } +} + +static void +va_args_from_event(va_list args, kherr_event * e, khm_size cb) +{ + ZeroMemory(args, cb); + + va_arg_from_param(&args, e->p1); + va_arg_from_param(&args, e->p2); + va_arg_from_param(&args, e->p3); + va_arg_from_param(&args, e->p4); +} + +static void +resolve_string_resource(kherr_event * e, + const wchar_t ** str, + va_list vl, + khm_int32 if_flag, + khm_int32 or_flag) +{ + wchar_t tfmt[KHERR_MAXCCH_STRING]; + wchar_t tbuf[KHERR_MAXCCH_STRING]; + size_t chars = 0; + size_t bytes = 0; + + if(e->flags & if_flag) { + if(e->h_module != NULL) + chars = LoadString(e->h_module, (UINT)(INT_PTR) *str, + tfmt, ARRAYLENGTH(tbuf)); + if(e->h_module == NULL || chars == 0) + *str = NULL; + else { + wchar_t * s; + + chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING, tfmt, + 0, 0, tbuf, ARRAYLENGTH(tbuf), &vl); + + if (chars == 0) { + *str = NULL; + } else { + bytes = (chars + 1) * sizeof(wchar_t); + s = PMALLOC(bytes); + assert(s); + StringCbCopy(s, bytes, tbuf); + *str = s; + e->flags |= or_flag; + } + } + e->flags &= ~if_flag; + } +} + +static void +resolve_msg_resource(kherr_event * e, + const wchar_t ** str, + va_list vl, + khm_int32 if_flag, + khm_int32 or_flag) +{ + wchar_t tbuf[KHERR_MAXCCH_STRING]; + size_t chars = 0; + size_t bytes = 0; + + if(e->flags & if_flag) { + if(e->h_module != NULL) { + + chars = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, + (LPCVOID) e->h_module, + (DWORD)(DWORD_PTR) *str, + 0, + tbuf, + ARRAYLENGTH(tbuf), + &vl); + } + + if(e->h_module == NULL || chars == 0) { + *str = NULL; + } else { + wchar_t * s; + + /* MC inserts trailing \r\n to each message unless the + message is terminated with a %0. We remove the last + line break since it is irrelevant to our handling of + the string in the UI. */ + if (tbuf[chars-1] == L'\n') + tbuf[--chars] = L'\0'; + if (tbuf[chars-1] == L'\r') + tbuf[--chars] = L'\0'; + + bytes = (chars + 1) * sizeof(wchar_t); + s = PMALLOC(bytes); + assert(s); + StringCbCopy(s, bytes, tbuf); + *str = s; + e->flags |= or_flag; + } + e->flags &= ~if_flag; + } +} + +static void +resolve_string(kherr_event * e, + const wchar_t ** str, + va_list vl, + khm_int32 mask, + khm_int32 free_if, + khm_int32 or_flag) +{ + wchar_t tbuf[KHERR_MAXCCH_STRING]; + size_t chars; + size_t bytes; + + if (((e->flags & mask) == 0 || + (e->flags & mask) == free_if) && + *str != NULL) { + + chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING, + (LPCVOID) *str, + 0, + 0, + tbuf, + ARRAYLENGTH(tbuf), + &vl); + + if ((e->flags & mask) == free_if) { + PFREE((void *) *str); + } + + e->flags &= ~mask; + + if (chars == 0) { + *str = 0; + } else { + wchar_t * s; + + bytes = (chars + 1) * sizeof(wchar_t); + s = PMALLOC(bytes); + assert(s); + StringCbCopy(s, bytes, tbuf); + *str = s; + e->flags |= or_flag; + } + } + +} + +void +resolve_event_strings(kherr_event * e) +{ + DWORD_PTR args[8]; + va_list vl = (va_list) args; + + va_args_from_event(vl, e, sizeof(args)); + + resolve_string(e, &e->short_desc, vl, + KHERR_RFMASK_SHORT_DESC, + KHERR_RF_FREE_SHORT_DESC, + KHERR_RF_FREE_SHORT_DESC); + + resolve_string(e, &e->long_desc, vl, + KHERR_RFMASK_LONG_DESC, + KHERR_RF_FREE_LONG_DESC, + KHERR_RF_FREE_LONG_DESC); + + resolve_string(e, &e->suggestion, vl, + KHERR_RFMASK_SUGGEST, + KHERR_RF_FREE_SUGGEST, + KHERR_RF_FREE_SUGGEST); + + resolve_string_resource(e, &e->short_desc, vl, + KHERR_RF_RES_SHORT_DESC, + KHERR_RF_FREE_SHORT_DESC); + + resolve_string_resource(e, &e->long_desc, vl, + KHERR_RF_RES_LONG_DESC, + KHERR_RF_FREE_LONG_DESC); + + resolve_string_resource(e, &e->suggestion, vl, + KHERR_RF_RES_SUGGEST, + KHERR_RF_FREE_SUGGEST); + + resolve_msg_resource(e, &e->short_desc, vl, + KHERR_RF_MSG_SHORT_DESC, + KHERR_RF_FREE_SHORT_DESC); + resolve_msg_resource(e, &e->long_desc, vl, + KHERR_RF_MSG_LONG_DESC, + KHERR_RF_FREE_LONG_DESC); + resolve_msg_resource(e, &e->suggestion, vl, + KHERR_RF_MSG_SUGGEST, + KHERR_RF_FREE_SUGGEST); + + /* get rid of dangling reference now that we have done everything + we can with it. Since we have already dealt with all the + parameter inserts, we don't need the parameters anymore + either. */ + free_event_params(e); + + e->h_module = NULL; + e->flags |= KHERR_RF_STR_RESOLVED; +} + + +KHMEXP void KHMAPI +kherr_evaluate_event(kherr_event * e) +{ + if (!IS_KHERR_EVENT(e)) + return; + + EnterCriticalSection(&cs_error); + resolve_event_strings(e); + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_evaluate_last_event(void) +{ + kherr_context * c; + kherr_event * e; + DWORD tid; + + c = peek_context(); + if(!IS_KHERR_CTX(c)) + return; + tid = GetCurrentThreadId(); + + EnterCriticalSection(&cs_error); + e = QBOTTOM(c); + while (e != NULL && e->thread_id != tid) + e = QPREV(e); + + if(!IS_KHERR_EVENT(e)) + goto _exit; + + resolve_event_strings(e); + + _exit: + LeaveCriticalSection(&cs_error); +} + +KHMEXP kherr_event * __cdecl +kherr_reportf(const wchar_t * long_desc_fmt, ...) +{ + va_list vl; + wchar_t buf[1024]; + kherr_event * e; + + va_start(vl, long_desc_fmt); + StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl); +#ifdef DEBUG + OutputDebugString(buf); +#endif + va_end(vl); + + e = kherr_report(KHERR_DEBUG_1, + NULL, NULL, NULL, buf, NULL, 0, + KHERR_SUGGEST_NONE, _vnull(), _vnull(), _vnull(), _vnull(), + KHERR_RF_CSTR_LONG_DESC +#ifdef _WIN32 + ,NULL +#endif + ); + if (IS_KHERR_EVENT(e)) { + kherr_evaluate_event(e); + } + + return e; +} + +KHMEXP kherr_event * __cdecl +kherr_reportf_ex(enum kherr_severity severity, + const wchar_t * facility, + khm_int32 facility_id, +#ifdef _WIN32 + HMODULE hModule, +#endif + const wchar_t * long_desc_fmt, ...) +{ + va_list vl; + wchar_t buf[1024]; + kherr_event * e; + + va_start(vl, long_desc_fmt); + StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl); +#ifdef DEBUG + OutputDebugString(buf); +#endif + va_end(vl); + + e = kherr_report(severity, NULL, facility, NULL, buf, NULL, facility_id, + KHERR_SUGGEST_NONE, + _vnull(), + _vnull(), + _vnull(), + _vnull(), KHERR_RF_CSTR_LONG_DESC +#ifdef _WIN32 + ,hModule +#endif + ); + if (IS_KHERR_EVENT(e)) { + kherr_evaluate_event(e); + } + + return e; +} + +KHMEXP kherr_event * KHMAPI +kherr_report(enum kherr_severity severity, + const wchar_t * short_desc, + const wchar_t * facility, + const wchar_t * location, + const wchar_t * long_desc, + const wchar_t * suggestion, + khm_int32 facility_id, + enum kherr_suggestion suggestion_id, + kherr_param p1, + kherr_param p2, + kherr_param p3, + kherr_param p4, + khm_int32 flags +#ifdef _WIN32 + ,HMODULE h_module +#endif + ) +{ + kherr_context * c; + kherr_event * e; + khm_boolean invalid = FALSE; + + /* sanity check */ + if (!IS_POW2(flags & KHERR_RFMASK_SHORT_DESC) || + !IS_POW2(flags & KHERR_RFMASK_LONG_DESC) || + !IS_POW2(flags & KHERR_RFMASK_SUGGEST)) + invalid = TRUE; + + e = get_empty_event(); + + e->thread_id = GetCurrentThreadId(); + e->time_ticks = GetTickCount(); + GetSystemTimeAsFileTime(&e->time_ft); + + e->severity = severity; + e->short_desc = short_desc; + e->facility = facility; + e->location = location; + e->long_desc = long_desc; + e->suggestion = suggestion; + e->facility_id = facility_id; + e->suggestion_id = suggestion_id; + e->p1 = p1; + e->p2 = p2; + e->p3 = p3; + e->p4 = p4; + e->flags = flags; +#ifdef _WIN32 + e->h_module = h_module; +#endif + + EnterCriticalSection(&cs_error); + c = peek_context(); + + if(!c || invalid) { + /* the reason why we are doing it this way is because p1..p4, + the descriptions and the suggestion may contain allocations + that has to be freed. */ + free_event(e); + e = NULL; + } else { + add_event(c,e); + } + + LeaveCriticalSection(&cs_error); + + return e; +} + +KHMEXP void KHMAPI +kherr_suggest(wchar_t * suggestion, + enum kherr_suggestion suggestion_id, + khm_int32 flags) +{ + kherr_context * c; + kherr_event * e; + DWORD tid; + + if (flags != KHERR_RF_CSTR_SUGGEST && + flags != KHERR_RF_RES_SUGGEST && + flags != KHERR_RF_MSG_SUGGEST && + flags != KHERR_RF_FREE_SUGGEST) + return; + + c = peek_context(); + if(!IS_KHERR_CTX(c)) + return; + + tid = GetCurrentThreadId(); + + EnterCriticalSection(&cs_error); + e = QBOTTOM(c); + while (e != NULL && e->thread_id != tid) + e = QPREV(e); + + if(!IS_KHERR_EVENT(e)) + goto _exit; + + /* if strings have already been resolved in this event, we cant + add any more unresolved strings. */ + if ((flags == KHERR_RF_RES_SUGGEST || + flags == KHERR_RF_MSG_SUGGEST) && + (e->flags & KHERR_RF_STR_RESOLVED)) + goto _exit; + + e->suggestion = suggestion; + e->suggestion_id = suggestion_id; + e->flags |= flags; +_exit: + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_location(wchar_t * location) +{ + kherr_context * c; + kherr_event * e; + DWORD tid; + + c = peek_context(); + if(!IS_KHERR_CTX(c)) + return; + tid = GetCurrentThreadId(); + + EnterCriticalSection(&cs_error); + e = QBOTTOM(c); + while (e != NULL && e->thread_id != tid) + e = QPREV(e); + + if(!IS_KHERR_EVENT(e)) + goto _exit; + e->location = location; +_exit: + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_facility(wchar_t * facility, + khm_int32 facility_id) +{ + kherr_context * c; + kherr_event * e; + DWORD tid; + + c = peek_context(); + if(!IS_KHERR_CTX(c)) + return; + tid = GetCurrentThreadId(); + EnterCriticalSection(&cs_error); + e = QBOTTOM(c); + while (e != NULL && e->thread_id != tid) + e = QPREV(e); + + if(!IS_KHERR_EVENT(e)) + goto _exit; + e->facility = facility; + e->facility_id = facility_id; +_exit: + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_set_desc_event(void) +{ + kherr_context * c; + kherr_event * e; + DWORD tid; + + c = peek_context(); + if(!IS_KHERR_CTX(c)) + return; + tid = GetCurrentThreadId(); + + EnterCriticalSection(&cs_error); + e = QBOTTOM(c); + while (e != NULL && e->thread_id != tid) + e = QPREV(e); + + if(!IS_KHERR_EVENT(e) || c->desc_event) + goto _exit; + + QDEL(c,e); + c->desc_event = e; + e->severity = KHERR_NONE; + resolve_event_strings(e); + + notify_ctx_event(KHERR_CTX_DESCRIBE, c); + +_exit: + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_del_last_event(void) +{ + kherr_context * c; + kherr_event * e; + DWORD tid; + + c = peek_context(); + + if(!IS_KHERR_CTX(c)) + return; + + tid = GetCurrentThreadId(); + + EnterCriticalSection(&cs_error); + e = QBOTTOM(c); + while (e != NULL && e->thread_id != tid) + e = QPREV(e); + + if(IS_KHERR_EVENT(e)) { + QDEL(c, e); + if(c->err_event == e) { + pick_err_event(c); + } + free_event(e); + } + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_push_context(kherr_context * c) +{ + kherr_context * p = NULL; + int new_context = FALSE; + + if (!IS_KHERR_CTX(c)) + return; + + EnterCriticalSection(&cs_error); + p = peek_context(); + if(IS_KHERR_CTX(p) && (c->flags & KHERR_CF_UNBOUND)) { + LDELETE(&ctx_root_list, c); + TADDCHILD(p,c); + c->flags &= ~KHERR_CF_UNBOUND; + kherr_hold_context(p); + new_context = TRUE; + } + push_context(c); + + if (new_context && IS_KHERR_CTX(p)) { + notify_ctx_event(KHERR_CTX_BEGIN, c); + notify_ctx_event(KHERR_CTX_NEWCHILD, p); + } + + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_push_new_context(khm_int32 flags) +{ + kherr_context * p = NULL; + kherr_context * c; + + flags &= KHERR_CFMASK_INITIAL; + + EnterCriticalSection(&cs_error); + p = peek_context(); + c = get_empty_context(); + if(IS_KHERR_CTX(p)) { + LDELETE(&ctx_root_list, c); + TADDCHILD(p,c); + c->flags &= ~KHERR_CF_UNBOUND; + kherr_hold_context(p); + } + c->flags |= flags; + push_context(c); + + notify_ctx_event(KHERR_CTX_BEGIN, c); + if (IS_KHERR_CTX(p)) { + notify_ctx_event(KHERR_CTX_NEWCHILD, p); + } + + LeaveCriticalSection(&cs_error); +} + +static kherr_param +dup_parm(kherr_param p) +{ + if(parm_type(p) == KEPT_STRINGT) { + wchar_t * d = PWCSDUP((wchar_t *)parm_data(p)); + return kherr_val(KEPT_STRINGT, (khm_ui_8) d); + } else + return p; +} + +static kherr_event * +fold_context(kherr_context * c) +{ + kherr_event * e; + kherr_event * g; + + if (!IS_KHERR_CTX(c)) + return NULL; + + EnterCriticalSection(&cs_error); + if(!c->err_event || (c->flags & KHERR_CF_DIRTY)) { + pick_err_event(c); + } + if(c->err_event) { + g = c->err_event; + e = get_empty_event(); + *e = *g; + g->short_desc = NULL; + g->long_desc = NULL; + g->suggestion = NULL; + g->flags &= + ~(KHERR_RF_FREE_SHORT_DESC | + KHERR_RF_FREE_LONG_DESC | + KHERR_RF_FREE_SUGGEST); + LINIT(e); + e->p1 = dup_parm(g->p1); + e->p2 = dup_parm(g->p2); + e->p3 = dup_parm(g->p3); + e->p4 = dup_parm(g->p4); + } else { + e = c->desc_event; + c->desc_event = NULL; + } + + if (IS_KHERR_EVENT(e)) + e->flags |= KHERR_RF_CONTEXT_FOLD; + + LeaveCriticalSection(&cs_error); + + return e; +} + +KHMEXP void KHMAPI +kherr_hold_context(kherr_context * c) +{ + if(!IS_KHERR_CTX(c)) + return; + + EnterCriticalSection(&cs_error); + c->refcount++; + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_release_context(kherr_context * c) +{ + if (!IS_KHERR_CTX(c)) + return; + + EnterCriticalSection(&cs_error); + c->refcount--; + if (c->refcount == 0) { + kherr_event * e; + kherr_context * p; + + e = QBOTTOM(c); + if (IS_KHERR_EVENT(e) && !(e->flags & KHERR_RF_COMMIT)) { + notify_ctx_event(KHERR_CTX_EVTCOMMIT, c); + e->flags |= KHERR_RF_COMMIT; + } + + notify_ctx_event(KHERR_CTX_END, c); + + p = TPARENT(c); + if (IS_KHERR_CTX(p)) { + e = fold_context(c); + if (e) + add_event(p, e); + + TDELCHILD(p, c); + + notify_ctx_event(KHERR_CTX_FOLDCHILD, p); + + kherr_release_context(p); + } else { + LDELETE(&ctx_root_list, c); + } + free_context(c); + } + LeaveCriticalSection(&cs_error); +} + +KHMEXP void KHMAPI +kherr_pop_context(void) +{ + kherr_context * c; + + EnterCriticalSection(&cs_error); + c = pop_context(); + if(IS_KHERR_CTX(c)) { + kherr_release_context(c); + } + LeaveCriticalSection(&cs_error); +} + +KHMEXP kherr_context * KHMAPI +kherr_peek_context(void) +{ + kherr_context * c; + + c = peek_context(); + if (IS_KHERR_CTX(c)) + kherr_hold_context(c); + + return c; +} + +KHMEXP khm_boolean KHMAPI +kherr_is_error(void) +{ + kherr_context * c = peek_context(); + return kherr_is_error_i(c); +} + +KHMEXP khm_boolean KHMAPI +kherr_is_error_i(kherr_context * c) +{ + if(IS_KHERR_CTX(c) && c->severity <= KHERR_ERROR) + return TRUE; + else + return FALSE; +} + +KHMEXP void KHMAPI +kherr_clear_error(void) +{ + kherr_context * c = peek_context(); + if (IS_KHERR_CTX(c)) + kherr_clear_error_i(c); +} + +KHMEXP void KHMAPI +kherr_clear_error_i(kherr_context * c) +{ + kherr_event * e; + if (IS_KHERR_CTX(c)) { + EnterCriticalSection(&cs_error); + e = QTOP(c); + while(e) { + assert(IS_KHERR_EVENT(e)); + + e->flags |= KHERR_RF_INERT; + e = QNEXT(e); + } + c->severity = KHERR_NONE; + c->err_event = NULL; + c->flags &= ~KHERR_CF_DIRTY; + LeaveCriticalSection(&cs_error); + } +} + +/* does the context 'c' use it's own progress marker? If this is + false, the progress marker for the context is derived from the + progress markers of its children. */ +#define CTX_USES_OWN_PROGRESS(c) ((c)->progress_num != 0 || (c)->progress_denom != 0 || ((c)->flags & KHERR_CF_OWN_PROGRESS)) + +KHMEXP void KHMAPI +kherr_set_progress(khm_ui_4 num, khm_ui_4 denom) +{ + kherr_context * c = peek_context(); + if(IS_KHERR_CTX(c)) { + EnterCriticalSection(&cs_error); + + if (num > denom) + num = denom; + + if (c->progress_denom != denom || + c->progress_num != denom) { + + kherr_context * p; + + c->progress_denom = denom; + c->progress_num = num; + + notify_ctx_event(KHERR_CTX_PROGRESS, c); + + for (p = TPARENT(c); + IS_KHERR_CTX(p) && !CTX_USES_OWN_PROGRESS(p); + p = TPARENT(p)) { + + notify_ctx_event(KHERR_CTX_PROGRESS, p); + + } + } + LeaveCriticalSection(&cs_error); + } +} + +KHMEXP void KHMAPI +kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom) +{ + kherr_context * c = peek_context(); + kherr_get_progress_i(c,num,denom); +} + +/* called with cs_error held */ +static void +get_progress(kherr_context * c, khm_ui_4 * pnum, khm_ui_4 * pdenom) +{ + if (CTX_USES_OWN_PROGRESS(c)) { + *pnum = c->progress_num; + *pdenom = c->progress_denom; + } else { + khm_ui_4 num = 0; + khm_ui_4 denom = 0; + + kherr_context * cc; + + for (cc = TFIRSTCHILD(c); + cc; + cc = LNEXT(cc)) { + + khm_ui_4 cnum, cdenom; + + assert(IS_KHERR_CTX(cc)); + + get_progress(cc, &cnum, &cdenom); + + if (cdenom == 0) { + cnum = 0; + } else { + if (cnum > cdenom) + cnum = cdenom; + + if (cdenom != 256) { + cnum = (cnum * 256) / cdenom; + cdenom = 256; + } + } + + num += cnum; + denom += cdenom; + } + + *pnum = num; + *pdenom = denom; + } +} + +KHMEXP void KHMAPI +kherr_get_progress_i(kherr_context * c, + khm_ui_4 * num, + khm_ui_4 * denom) +{ + if (num == NULL || denom == NULL) + return; + + if(IS_KHERR_CTX(c)) { + EnterCriticalSection(&cs_error); + get_progress(c, num, denom); + LeaveCriticalSection(&cs_error); + } else { + *num = 0; + *denom = 0; + } +} + +KHMEXP kherr_event * KHMAPI +kherr_get_first_event(kherr_context * c) +{ + kherr_event * e; + + if (!IS_KHERR_CTX(c)) + return NULL; + + EnterCriticalSection(&cs_error); + e = QTOP(c); + LeaveCriticalSection(&cs_error); + assert(e == NULL || IS_KHERR_EVENT(e)); + return e; +} + +KHMEXP kherr_event * KHMAPI +kherr_get_next_event(kherr_event * e) +{ + kherr_event * ee; + + if (!IS_KHERR_EVENT(e)) + return NULL; + + EnterCriticalSection(&cs_error); + ee = QNEXT(e); + LeaveCriticalSection(&cs_error); + assert(ee == NULL || IS_KHERR_EVENT(ee)); + return ee; +} + +KHMEXP kherr_event * KHMAPI +kherr_get_prev_event(kherr_event * e) +{ + kherr_event * ee; + + if (!IS_KHERR_EVENT(e)) + return NULL; + + EnterCriticalSection(&cs_error); + ee = QPREV(e); + LeaveCriticalSection(&cs_error); + assert(ee == NULL || IS_KHERR_EVENT(ee)); + return ee; +} + +KHMEXP kherr_event * KHMAPI +kherr_get_last_event(kherr_context * c) +{ + kherr_event * e; + + if (!IS_KHERR_CTX(c)) + return NULL; + + EnterCriticalSection(&cs_error); + e = QBOTTOM(c); + LeaveCriticalSection(&cs_error); + assert(e == NULL || IS_KHERR_EVENT(e)); + return e; +} + +KHMEXP kherr_context * KHMAPI +kherr_get_first_context(kherr_context * c) +{ + kherr_context * cc; + + if (c != NULL && !IS_KHERR_CTX(c)) + return NULL; + + EnterCriticalSection(&cs_error); + if (IS_KHERR_CTX(c)) { + cc = TFIRSTCHILD(c); + if (cc) + kherr_hold_context(cc); + } else { + cc = ctx_root_list; + if (cc) + kherr_hold_context(cc); + } + LeaveCriticalSection(&cs_error); + assert(cc == NULL || IS_KHERR_CTX(cc)); + return cc; +} + +KHMEXP kherr_context * KHMAPI +kherr_get_next_context(kherr_context * c) +{ + kherr_context * cc; + + if (!IS_KHERR_CTX(c)) + return NULL; + + EnterCriticalSection(&cs_error); + cc = LNEXT(c); + if (cc) + kherr_hold_context(cc); + LeaveCriticalSection(&cs_error); + assert(cc == NULL || IS_KHERR_CTX(cc)); + return cc; +} + +KHMEXP kherr_event * KHMAPI +kherr_get_err_event(kherr_context * c) +{ + kherr_event * e; + + if (!IS_KHERR_CTX(c)) + return NULL; + + EnterCriticalSection(&cs_error); + if(!c->err_event) { + pick_err_event(c); + } + e = c->err_event; + LeaveCriticalSection(&cs_error); + assert(e == NULL || IS_KHERR_EVENT(e)); + return e; +} + +KHMEXP kherr_event * KHMAPI +kherr_get_desc_event(kherr_context * c) +{ + kherr_event * e; + + if (!IS_KHERR_CTX(c)) + return NULL; + + EnterCriticalSection(&cs_error); + e = c->desc_event; + LeaveCriticalSection(&cs_error); + assert(e == NULL || IS_KHERR_EVENT(e)); + return e; +} + +KHMEXP kherr_param +kherr_dup_string(const wchar_t * s) +{ + wchar_t * dest; + size_t cb_s; + + if (s == NULL) + return _vnull(); + + if (FAILED(StringCbLength(s, KHERR_MAXCB_STRING, &cb_s))) + cb_s = KHERR_MAXCB_STRING; + else + cb_s += sizeof(wchar_t); + + dest = PMALLOC(cb_s); + assert(dest != NULL); + dest[0] = L'\0'; + + StringCbCopy(dest, cb_s, s); + + return _tstr(dest); +} + diff --git a/krb5-1-6/src/windows/identity/kherr/kherr.h b/krb5-1-6/src/windows/identity/kherr/kherr.h new file mode 100644 index 000000000..90a72a35a --- /dev/null +++ b/krb5-1-6/src/windows/identity/kherr/kherr.h @@ -0,0 +1,1126 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHERR_H +#define __KHIMAIRA_KHERR_H + +/*! \defgroup kherr NetIDMgr Error Reporting + + Error reporting functions provide a mechanism to construct + meaningful and user friendly error reports for the user. + + Unlike most of the other NetIDMgr API's, the error reporting APIs + are lightweight and usually do not return an error value. This is + mostly because, these functions are called \b after an error + occurs. + + @{*/ +#include<khdefs.h> +#include<khlist.h> + +/*! \name Customizable macros +@{ */ +#ifndef KHERR_FACILITY +/*! \brief The default facility when reporting errors + + When including this header file, if the KHERR_FACILITY macro is + defined to be a wide character string, then it will be used as the + default facility when for the convenience macros. All of the + calls to the convenience macros in the source file would then have + that facility. + + If left undefined, the convenience macros will leave the facility + value undefined. + */ +#define KHERR_FACILITY NULL +#endif + +#ifndef KHERR_FACILITY_ID +/*! \brief The default facility ID when reporting errors + + When including this header file, if the KHERR_FACILITY_ID macro is + defined to be non-zero, then it will be used as the default + facility identifier for the convenience macros. All of the calls + to the convenience macros in the source file would then have that + facility identifier. + + The default value of 0 means that the facility is undefined. + */ +#define KHERR_FACILITY_ID 0 +#endif + +/*! \define KHERR_HMODULE (undefined) + \brief The default module handle + + When including this header file, if the KHERR_HMODULE macro is + defined to be an identifier that holds the module handle, then the + convenience macros that specify a module handle will use it. + + A default value is not defined for KHERR_HMODULE. Any attempt to + invoke any of the convenience macros that use it should generate a + compile time error. + */ +#ifdef _WIN32 +#ifndef KHERR_HMODULE +#endif +#endif +/*@}*/ + +/*! \brief Parameter types + */ +enum kherr_parm_types { + KEPT_NONE = 0, + KEPT_INT32 = 1, + KEPT_UINT32, + KEPT_INT64, + KEPT_UINT64, + KEPT_STRINGC, /*!< String constant */ + KEPT_STRINGT, /*!< String. Will be freed using + free() when the event is freed */ + KEPT_PTR /*!< Pointer type. */ +}; + + +typedef struct tag_kherr_param { + khm_octet type; + khm_ui_8 data; +} kherr_param; + +/*! \brief Severity levels + + Larger the value, the less severe it is. +*/ +enum tag_kherr_severity { + KHERR_FATAL = 0, /*!< Fatal error.*/ + KHERR_ERROR, /*!< Non-fatal error. We'll probably + survive. See the suggested action. */ + KHERR_WARNING, /*!< Warning. Something almost broke + or soon will. See the suggested + action. */ + KHERR_INFO, /*!< Informational. Something happened + that we would like you to know + about. */ + KHERR_DEBUG_1 = 64, /*!< Verbose debug level 1 (high) + Events at this severity level are + not required to be based on + localized strings. */ + KHERR_DEBUG_2 = 65, /*!< Verbose debug level 2 (medium) + Events at this severity level are + not required to be based on + localized strings. */ + KHERR_DEBUG_3 = 66, /*!< Verbose debug level 3 (low) + Events at this severity level are + not required to be based on + localized strings. */ + KHERR_RESERVED_BANK = 127, /*!< Internal use */ + KHERR_NONE = 128 /*!< Nothing interesting has happened + so far */ +}; + +typedef enum tag_kherr_severity kherr_severity; + +/*! \brief Suggestions */ +enum tag_kherr_suggestion { + KHERR_SUGGEST_NONE = 0, /*!< No suggestions. */ + KHERR_SUGGEST_ABORT, /*!< Abort whatever it was you were + trying. It's not gonna work. */ + KHERR_SUGGEST_RETRY, /*!< Retry. It might work the second + or third time over */ + KHERR_SUGGEST_IGNORE, /*!< Ignore. It might go away. */ + KHERR_SUGGEST_INTERACT, /*!< Further user interaction is + necessary to resolve the situation. + The suggest string in the event + should be prompted to the user. */ + KHERR_SUGGEST_OTHER, /*!< Something else. */ +}; + +typedef enum tag_kherr_suggestion kherr_suggestion; + +/*! \brief An event */ +typedef struct tag_kherr_event { + khm_int32 magic; /*!< Magic number. Always set to + KHERR_EVENT_MAGIC */ + DWORD thread_id; /*!< The thread which reported this + event. */ + const wchar_t * short_desc; /*!< Short description or title + (localized) */ + const wchar_t * facility; /*!< Facility name of the reporter + (not localized) */ + const wchar_t * location; /*!< Location. Usually the function + name or such of where the event + occured (not localized) */ + const wchar_t * long_desc; /*!< A long description of what went + wrong (localized, formatted) */ + const wchar_t * suggestion; /*!< A suggested way to fix it + (localized,formatted) */ + + kherr_severity severity; + /*!< Severity level. One of the + severity levels listed in + enumeration ::kherr_severity */ + khm_int32 facility_id; /*!< Left to the application to + interpret */ + kherr_suggestion suggestion_id; + /*!< One of the suggestion ID's from + the enumeration + ::kherr_suggestion */ + + int flags; /*!< Flags. */ + + kherr_param p1; /*!< Parameter 1 for formatting */ + kherr_param p2; /*!< Parameter 2 for formatting */ + kherr_param p3; /*!< Parameter 3 for formatting */ + kherr_param p4; /*!< Parameter 4 for formatting */ + + DWORD time_ticks; /*!< Time at which event was reported + (as returned by GetTickCount(). */ + FILETIME time_ft; /*!< Time at which event was reported. + Current system time as FILETIME. */ + +#ifdef _WIN32 + HMODULE h_module; /*!< Handle to the module which should + resolve any unresolved resources + references above. */ +#endif + + LDCL(struct tag_kherr_event); +} kherr_event; + +#define KHERR_EVENT_MAGIC 0x0423e84f + +/*! \brief Flags for kherr_event + + Each set of flags that define the type of resource for one value + is mutually exclusive. + */ +enum kherr_event_flags { + KHERR_RF_CSTR_SHORT_DESC= 0x00000000, + /*!< Short description is a constant + string */ + KHERR_RF_RES_SHORT_DESC = 0x00000001, + /*!< Short description is a string + resource */ + KHERR_RF_MSG_SHORT_DESC = 0x00000002, + /*!< Short description is a message + resource */ + KHERR_RF_FREE_SHORT_DESC= 0x00000004, + /*!< Short description is an allocated + string */ + KHERR_RFMASK_SHORT_DESC = 0x00000007, + + KHERR_RF_CSTR_LONG_DESC = 0x00000000, + /*!< Long description is a constant + string */ + KHERR_RF_RES_LONG_DESC = 0x00000008, + /*!< Long description is a string + resource */ + KHERR_RF_MSG_LONG_DESC = 0x00000010, + /*!< Long description is a message + resouce */ + KHERR_RF_FREE_LONG_DESC = 0x00000020, + /*!< Long description is an allocated + string */ + KHERR_RFMASK_LONG_DESC = 0x00000038, + + KHERR_RF_CSTR_SUGGEST = 0x00000000, + /*!< Suggestion is a constant + string */ + KHERR_RF_RES_SUGGEST = 0x00000040, + /*!< Suggestion is a string + resource */ + KHERR_RF_MSG_SUGGEST = 0x00000080, + /*!< Suggestion is a message + resource */ + KHERR_RF_FREE_SUGGEST = 0x00000100, + /*!< Suggestion is an allocated + string */ + KHERR_RFMASK_SUGGEST = 0x000001C0, + + KHERR_RF_STR_RESOLVED = 0x00010000, + /*!< The string resources in the event + have been resolved. */ + KHERR_RF_CONTEXT_FOLD = 0x00020000, + /*!< The event is a representation of + a folded context. */ + + KHERR_RF_INERT = 0x00040000, + /*!< Inert event. The event has + already been dealt with and is no + longer considered significant. */ + KHERR_RF_COMMIT = 0x00080000 + /*!< Committed event. The commit + handlers for this event have already + been called. */ +}; + +/*! \brief Serial number for error contexts */ +typedef khm_ui_4 kherr_serial; + +/*! \brief An error context +*/ +typedef struct tag_kherr_context { + khm_int32 magic; /*!< Magic number. Always set to + KHERR_CONTEXT_MAGIC */ + + kherr_serial serial; /*!< Context instance serial number. + Context objects themselves may be + reused for different contexts as + they are freed and reallocated. + However every instance of a context + is guaranteed to have a unique + serial number as specified in this + field. If an external entity wants + to keep track of the context, it + should keep track of the serial + number as well as the pointer to the + context object. */ + + kherr_severity severity; + /*!< Severity level. One of the + severity levels listed below. This + is the severity level of the context + and is the maximum severity level of + all the events in the queue of + events. */ + + khm_int32 flags; /*!< Flags. Used internally. */ + khm_ui_4 refcount; /*!< Reference count. Used + internally */ + + kherr_event *desc_event; /*!< Description event. The event that + describes the error context. This + points to an event that is not in + the event queue. */ + + kherr_event *err_event; /*!< Significant event. The last one + that caused the severity level to be + what it is right now. This points + to an event that is listed in the + event queue for this context.*/ + + khm_ui_4 progress_num; /*!< Progress numerator */ + khm_ui_4 progress_denom; /*!< Progress denominator */ + + TDCL(struct tag_kherr_context); + QDCL(struct tag_kherr_event); +} kherr_context; + +#define KHERR_CONTEXT_MAGIC 0x34f3238c + +enum kherr_context_flags { + KHERR_CF_NONE = 0x00000000, + /*!< None. */ + + KHERR_CF_DIRTY = 0x00000001, + /*!< Used Internally. Denotes that + the err_event and severity may need + to be recalculated. Cannot be set + as an initial flag. */ + + KHERR_CF_OWN_PROGRESS = 0x00000002, + /*!< The context maintains its own + progress meter as opposed to one + that is derived from child + contexts. */ + + KHERR_CF_UNBOUND = 0x00000004, + /*!< Unbound context. The context + can't be used to log events. Call + kherr_push_context() to associate + the context with the global context + hierarchy. Cannot be set as an + initial flag. */ + + KHERR_CF_TRANSITIVE = 0x00000008, + /*!< Transitive. The context is + automatically made the current + context for all other threads that + handle messages sent or posted by + threads whose current error context + is this one. */ + + KHERR_CFMASK_INITIAL = 0x0000000a, + /*!< Allowed initial flags */ +}; + +/*! \brief Maximum length of a string field in characters including terminating NULL + */ +#define KHERR_MAXCCH_STRING 1024 + +/*! \brief Maximum length of a string field in bytes including terminating NULL + */ +#define KHERR_MAXCB_STRING (KHERR_MAXCCH_STRING * sizeof(wchar_t)) + +/*! \brief Context event + + \see kherr_add_ctx_handler() +*/ +enum kherr_ctx_event { + KHERR_CTX_BEGIN = 0x00000001, /*!< A new context was created */ + KHERR_CTX_DESCRIBE = 0x00000002, /*!< A context was described */ + KHERR_CTX_END = 0x00000004, /*!< A context was closed */ + KHERR_CTX_ERROR = 0x00000008, /*!< A context switched to an + error state */ + KHERR_CTX_EVTCOMMIT = 0x00000010, /*!< A event was committed into + the context */ + KHERR_CTX_NEWCHILD = 0x00000020, /*!< A new child context was created */ + KHERR_CTX_FOLDCHILD = 0x00000040, /*!< A child context was folded */ + KHERR_CTX_PROGRESS = 0x00000080, /*!< Progress marker updated for context */ +}; + +/*! \brief Context event handler + + Context event handlers are invoked when specific events occur with + respect to an error context. The ::kherr_ctx_event parameter + specifies which event occurred using one of the event values + described in the enumeration. The error context in which this + event occurred is specified by the ::kherr_context pointer. + + Note that if the handler needs to keep track of the error context + for later processing, it also needs to keep track of the \a serial + field of the error context. The same context object may be + reused, but the serial number is guaranteed to be unique. + + \see kherr_add_ctx_handler() + */ +typedef void (KHMAPI * kherr_ctx_handler)(enum kherr_ctx_event, + kherr_context *); + +/*! \brief Add a context event handler + + An application can register an event handler that gets notified of + events that pertain to error contexts. More than one handler can + be registered. The order in which the handlers are called is + undefined for any specific event. + + These event occur in the context of individual application + threads. The handler will be called from within the thread that + caused the event. Therefore it is important that the handler is + both reentrant and returns quickly. + + The events that the handler will be notified of are explained + below: + + <b>KHERR_CTX_BEGIN</b>: Notification that a new context was + created. A pointer to the context will be supplied to the + handler. The supplied pointer should not be used to obtain a hold + on the context, as it will prevent the context from being closed. + + <b>KHERR_CTX_DESCRIBE</b>: The thread called + kherr_set_desc_event() to set the description of a context. Once + again, the pointer should not be used to obtain a hold on the + context. + + <b>KHERR_CTX_ERROR</b>: The last event that was reported for the + context was an error event (the severity was was equal or higher + than KHERR_ERROR). The pointer may be used to obtain a hold on + the context. However, it is the application's resonsibility to + make sure that the hold is released later. Otherwise the event + will never be closed. + + <b>KHERR_CTX_END</b>: Closure. This event is signalled when the + last open handle to the context is closed and there is no thread + that is currently active which has this context in its error + context stack. At the time the handler is invoked, the context is + still intact. The pointer that is supplied should not be used to + obtain a handle on the context. + + <b>KHERR_CTX_EVTCOMMIT</b>: An event was committed into the error + context. An event is committed when another event is reported + after the event, or if the context is closed. Since the last + event that is reported can still be modified by adding new + information, the event remains open until it is no longer the last + event or the context is no longer active. When this notification + is received, the last event in the context's event queue is the + event that was committed. + + \param[in] h Context event handler, of type ::kherr_ctx_handler + + \param[in] filter A combination of ::kherr_ctx_event values + indication which notifications should be sent to the handler. + If a \a filter value of zero is provided, all of the events + will be sent to the handler. + + \param[in] serial The serial number of the error context that + should be tracked. If this is zero, all error contexts can + trigger the handler. + */ +KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h, + khm_int32 filter, + kherr_serial serial); + +/*! \brief Remove a context event handler + + Undoes what was done with kherr_add_ctx_handler() + + \see kherr_add_ctx_handler() + */ +KHMEXP void KHMAPI kherr_remove_ctx_handler(kherr_ctx_handler h, + kherr_serial serial); + + +/*! \brief Report an error + + Creates an event, fills in the details specified in the arguments, + and adds it to the current error context. + + If the current thread does not have an error context, no reporting + happens. However, if any of the supplied strings or parameters + are marked as allocated, they will be freed before the function + returns. + + Certain parameters that expect strings can instead be given string + resources, message resources or allocated strings in addition to + constant string. By default, the parameters are expected to be + constant strings. + + <b>Allocated strings</b>: The application can allocate memory for + a string. Since the application is not notified when the event is + no longer used and freed, it \b must indicate that the string is + an allocated string by setting the appropriate flag in the \a + flags parameter. When the event is no longer used, the memory + pointed to by the relevant pointer will be freed through a call to + free(). Not all string parameters take allocated strings. See + individual parameter documentation for details. + + <b>String resources</b>: On WIN32, string resources can be passed + in to kherr_report() using the MAKEINTRESOURCE macro. However, + the application \b must specify that the parameter is a string + resource using the appropriate flag in the \a flags parameter. + The error reporting engine will expand the string against the + module handle passed in the \a h_module parameter when the value + of the string is required. Not all string parameters take string + resources. See individual parameter documentation for details. + Strings loaded through string resources cannot be longer than + ::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL. + + <b>Message resources</b>: On WIN32, message resources can be + passed in to kherr_report() by specifying the message ID where it + ordinarily expects a pointer to a constant string. The + application \b must indicate that the string is a message resource + by using the appropriate flag in the \a flags parameter. When the + value of the string is needed, it is expanded against the module + handle passed in the \a h_module parameter using the message ID. + Not all string parameters take message resources. See individual + parameter documentation for details. Note that the facility and + severity values associated with a message resource are ignored. + Strings loaded through message resources cannot be longer than + ::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL. + + <b>Formatted fields</b>: Parameters that are formatted can have + can have parameter inserts like in printf(). However, specifying + inserts is different from printf() and follows the conventions + used in WIN32 API FormatMessage(). This is because for localized + strings, the order of the parameters in the string may be + different. See the documentation for FormatMessage() for details + on the format string. The same set of parameters (i.e. \a p1, \a + p2, \a p3, \a p4) is used for all formatted strings with + appropriate marshalling for 64 bit types. The size of the string + after expansion must not exceed 65536 bytes inclusive of + terminating NULL. + + \param[in] severity One of ::kherr_severity_level + \param[in] short_desc Short description or title (localized). Can + be a string resource, message resource, allocated string or + constant string. The \a flags parameter should indicate the + type of string used. + \param[in] facility Facility name of the reporter (not localized) + \param[in] location Usually the function name or such of where the + event occured (not localized) + \param[in] long_desc Long description of event (localized, + formatted). Can be a string resource, message resource, + allocated string or constant string. The \a flags parameter + should indicate the type of string used. + \param[in] suggestion Suggested action to correct situation, if + applicable (localized). Can be a string resource, message + resource, allocated string or constant string. The \a flags + parameter should indicate the type of string used. + \param[in] facility_id Identifier of facility. Application + defined. + \param[in] suggestion_id One of the suggestion identifiers from + ::kherr_suggestion_ids + \param[in] p1 First parameter. Used for formatting. + \param[in] p2 Second parameter. Used for formatting. + \param[in] p3 Third parameter. Used for formatting. + \param[in] p4 Fourth parameter. Used for formatting. + \param[in] flags Flags. See ::kherr_report_flags + \param[in] h_module Handle to a module that resolves any string or + message resources used for the \a short_description , \a + long_desc or \a suggestion parameters. This parameter is only + available on WIN32. + + \note With the exception of parameters of type KEPT_STRINGT and + parameters which are flagged for freeing using the \a flags + parameter, all other string parameters are assumed to be + pointers to constant strings. The strings are not copied and + the pointers are used as is. Also, no clean-up is performed + when the event is freed other than that implied by \a flags. + */ +KHMEXP kherr_event * KHMAPI kherr_report( + kherr_severity severity, + const wchar_t * short_desc, + const wchar_t * facility, + const wchar_t * location, + const wchar_t * long_desC, + const wchar_t * suggestion, + khm_int32 facility_id, + kherr_suggestion suggestion_id, + kherr_param p1, + kherr_param p2, + kherr_param p3, + kherr_param p4, + khm_int32 flags +#ifdef _WIN32 + ,HMODULE h_module +#endif +); + +/*! \brief Report a formatted message + + The format string \a long_desc_fmt should be a string constant and + the format specifiers follow that of \a sprintf. This creates an + event with the long description set to the expansion of the format + string against the arguments. + */ +KHMEXP kherr_event * __cdecl +kherr_reportf_ex(kherr_severity severity, + const wchar_t * facility, + khm_int32 facility_id, +#ifdef _WIN32 + HMODULE hModule, +#endif + const wchar_t * long_desc_fmt, + ...); +#define _reportf_ex kherr_reportf_ex + +/*! \brief Report a formatted message + + The format string \a long_desc_fmt should be a string constant and + the format specifiers follow that of \a sprintf. This creates an + event with the long description set to the expansion of the format + string against the arguments. + */ +KHMEXP kherr_event * __cdecl +kherr_reportf(const wchar_t * long_desc_fmt, + ...); +#define _reportf kherr_reportf + +/*! \brief Create a parameter out of a transient string + + A parameter is created by duplicating the string that is passed + into the function. If the string exceeds KHERR_MAXCCH_STRING, + then only the first part of the string that fits within the limit + is duplicated. + + The resulting ::kherr_param must be passed in to kherr_report(). + The event logging framework will free the duplicated string once + the data is no longer required. + */ +KHMEXP kherr_param kherr_dup_string(const wchar_t * s); + +__inline KHMEXP kherr_param +kherr_val(khm_octet ptype, khm_ui_8 pvalue) { + kherr_param p; + + p.type = ptype; + p.data = pvalue; + + return p; +} + +#define _int32(i) kherr_val(KEPT_INT32, (khm_ui_8) i) +#define _uint32(ui) kherr_val(KEPT_UINT32, (khm_ui_8) ui) +#define _int64(i) kherr_val(KEPT_INT64, (khm_ui_8) i) +#define _uint64(ui) kherr_val(KEPT_UINT64, (khm_ui_8) ui) +#define _cstr(cs) kherr_val(KEPT_STRINGC, (khm_ui_8) cs) +#define _tstr(ts) kherr_val(KEPT_STRINGT, (khm_ui_8) ts) +#define _cptr(p) kherr_val(KEPT_PTR, (khm_ui_8) p) +#define _vnull() kherr_val(KEPT_NONE, 0) +#define _dupstr(s) kherr_dup_string(s) + +/* convenience macros for calling kherr_report */ +#ifdef KHERR_HMODULE + +#define _report_cs0(severity, long_description) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE) + +#define _report_cs1(severity, long_description, p1) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE) + +#define _report_cs2(severity, long_description, p1, p2) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, KHERR_HMODULE) + +#define _report_cs3(severity, long_description, p1, p2, p3) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, KHERR_HMODULE) + +#define _report_cs4(severity, long_description, p1, p2, p3, p4) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, KHERR_HMODULE) + +#else + +#define _report_cs0(severity, long_description) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, NULL) + +#define _report_cs1(severity, long_description, p1) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, NULL) + +#define _report_cs2(severity, long_description, p1, p2) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, NULL) + +#define _report_cs3(severity, long_description, p1, p2, p3) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, NULL) + +#define _report_cs4(severity, long_description, p1, p2, p3, p4) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, NULL) +#endif /* !defined(KHERR_HMODULE) */ + +#ifdef _WIN32 +#define _report_sr0(severity, long_desc_id) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE) + +#define _report_sr1(severity, long_desc_id, p1) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE) + +#define _report_sr2(severity, long_desc_id, p1, p2) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE) + +#define _report_sr3(severity, long_desc_id, p1, p2, p3) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE) + +#define _report_sr4(severity, long_desc_id, p1, p2, p3, p4) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE) +#endif + +#ifdef _WIN32 +#define _report_mr0(severity, long_desc_msg_id) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE) + +#define _report_mr1(severity, long_desc_msg_id, p1) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE) + +#define _report_mr2(severity, long_desc_msg_id, p1, p2) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE) + +#define _report_mr3(severity, long_desc_msg_id, p1, p2, p3) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE) + +#define _report_mr4(severity, long_desc_msg_id, p1, p2, p3, p4) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE) +#endif + +#define _report_ts0(severity, long_desc_ptr) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL) + +#define _report_ts1(severity, long_desc_ptr, p1) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL) + +#define _report_ts2(severity, long_desc_ptr, p1, p2) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL) + +#define _report_ts3(severity, long_desc_ptr, p1, p2, p3) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_FREE_LONG_DESC, NULL) + +#define _report_ts4(severity, long_desc_ptr, p1, p2, p3, p4) \ + kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_FREE_LONG_DESC, NULL) + +/*! \brief Set the suggestion and suggestion identifier for the last event + + The event that will be modified is the last event reported by the + calling thread. + */ +KHMEXP void KHMAPI kherr_suggest(wchar_t * suggestion, khm_int32 suggestion_id, khm_int32 flags); +#define _suggest_cs(cs,sid) kherr_suggest((cs), (sid), KHERR_RF_CSTR_SUGGEST) +#define _suggest_ts(ts,sid) kherr_suggest((ts), (sid), KHERR_RF_FREE_SUGGEST) +#define _suggest_sr(sr,sid) kherr_suggest(MAKEINTRESOURCE(sr), (sid), KHERR_RF_RES_SUGGEST) +#define _suggest_mr(mr,sid) kherr_suggest((wchar_t *)(DWORD_PTR)(mr), (sid), KHERR_RF_MSG_SUGGEST) + +/*! \brief Set the location string for the last event + + The event that will be modified is the last event reported by the + calling thread. + */ +KHMEXP void KHMAPI kherr_location(wchar_t * location); +#define _location(l) kherr_location(l) + +/*! \brief Set the facility string and identifier for the last event + + The event that will be modified is the last event reported by the + calling thread. + */ +KHMEXP void KHMAPI kherr_facility(wchar_t * facility, khm_int32 facility_id); +#define _facility(f,fid) kherr_facility((f),(fid)) + +/*! \brief Marks the last event as the descriptor event for the current error context + + Note that marking an event as the descriptor event has the effect + of removing the event from event queue. The event will henceforth + be used as the descriptor for the context. The only effective + fields of a descriptor event are \a short_desc, \a long_desc, \a + facility, \a facility_id and the parameters which are used for + resolving formatted strings in the aforementioned fields. + + Upon calling kherr_set_desc_event(), the event will be + automatically evaluated as if kherr_evaluate_event() was called. + + The event that will be referenced is the last event reported by + the calling thread. + */ +KHMEXP void KHMAPI kherr_set_desc_event(void); +#define _describe kherr_set_desc_event + +/*! \brief Delete the last event + + The event that will be deleted is the last event reported by the + calling thread. + */ +KHMEXP void KHMAPI kherr_del_last_event(void); +#define _del_event kherr_del_last_event + +/*! \brief Create a new context + + The created context is not bound to any thread or any context + hierarchy. Hence it cannot be used to capture any events until it + is used in a call to kherr_push_context(). + + Release the returned context pointer with a call to + kherr_release_context(). + + \param[in] flags Initial flags for the context. Combination of + ::kherr_context_flags + + \note This function is for internal use only. + */ +KHMEXP kherr_context * KHMAPI kherr_create_new_context(khm_int32 flags); + +/*! \brief Obtain a hold on a context */ +KHMEXP void KHMAPI kherr_hold_context(kherr_context * c); + +/*! \brief Release a context */ +KHMEXP void KHMAPI kherr_release_context(kherr_context * c); + +/*! \brief Push an empty context + + Creates an empty context, adds it as a child of the current + thread's error context. If the current thread does not have an + error context, then the created error context will be a root level + context. + + The new context will be the current error context for the calling + thread. + + \param[in] flags Initial flags for the context. Combination of + ::kherr_context_flags + + \see kherr_push_new_context() for more information about thread + specific context stacks. + + */ +KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags); +#define _begin_task kherr_push_new_context + +/*! \brief Push a context + + Each thread has a stack of error contexts. The topmost one is + current. The thread can push or pop contexts on to the stack + independently of the hierarchy of contexts (the only exception, as + explained below is when the context that is being pushed is + unbound). + + If the context being pushed by kherr_push_context() is unbound, + then it will be attached to the current context of the thread as a + child. Once the new context is pushed to the top of the stack, it + will become the current context for the thread. + + The calling thread must call kherr_pop_context() to remove the + context from the top of the stack. Each call to + kherr_push_new_context() or kher_push_context() must have a + corresponding kherr_pop_context() call. + + When the thread terminates, all of the contexts in the thread's + context stack will be automatically removed. + + \see kherr_pop_context() + */ +KHMEXP void KHMAPI kherr_push_context(kherr_context * c); + +/*! \brief Pop a context + + Remove the current error context from the thread's context stack. + If no other open handles exist to the error context, this causes + the error context to collapse into it's parent context or vanish + entirely unless the context contains an error. + + \see kherr_push_context() for more information about thread + specific context stacks. + */ +KHMEXP void KHMAPI kherr_pop_context(void); +#define _end_task kherr_pop_context + +/*! \brief Retrieve the current error context + + The returned pointer must be released with a call to + kherr_release_context(). +*/ +KHMEXP kherr_context * KHMAPI kherr_peek_context(void); + +/*! \brief Check if the current error context indicates an error + + \return TRUE if there is an error. FALSE otherwise. + \see kherr_analyze() + */ +KHMEXP khm_boolean KHMAPI kherr_is_error(void); + +/*! \brief Check if an error context indicates an error + + \return TRUE if there is an error. FALSE otherwise. + \see kherr_analyze() + */ +KHMEXP khm_boolean KHMAPI kherr_is_error_i(kherr_context * c); + +/*! \brief Clear the error state of the current context */ +KHMEXP void KHMAPI kherr_clear_error(void); + +/*! \brief Clear the error state of an error context */ +KHMEXP void KHMAPI kherr_clear_error_i(kherr_context * c); + +/*! \brief Set the progress meter of the current error context + + Setting \a denom to zero removes the progress meter. + */ +KHMEXP void KHMAPI kherr_set_progress(khm_ui_4 num, khm_ui_4 denom); +#define _progress(num,denom) kherr_set_progress((num),(denom)) + +/*! \brief Get the progress meter of the current error context + + This is equivalent to calling kherr_get_progress_i() for the + current error context. I.e. : + + \code + kherr_context * ctx; + + ctx = kherr_peek_context(); + kherr_get_progress_i(ctx, &num, &denom); + kherr_release_context(ctx); + \endcode + + \see kherr_get_progress_i() + */ +KHMEXP void KHMAPI kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom); + +/*! \brief Get the progress meter of an error context + + The progress meter for the current context can be set by calling + kherr_set_progress() (or using the ::_progress macro). The + progress value returned by this function is as follows: + + If one or more of the following conditions are true, then the + returned progress values are the values set for the context using + the most recent call to kherr_set_progress(): + + - if the numerator and the denominator are non-zero + + - if the ::KHERR_CF_OWN_PROGRESS flag is set for the context. + + Otherwise, the function will calculate the progress by enumerating + all the child context for the context and summing up the + normalized numerators and the denominators for them. + */ +KHMEXP void KHMAPI kherr_get_progress_i(kherr_context * c, khm_ui_4 * num, khm_ui_4 * denom); + +/*! \brief Get the first event in a context + + The returned pointer is only valid as long as there is a hold on + \a c. Once the context is released with a call to + kherr_release_context() all pointers to events in the context + become invalid. + + In addition, the last event in a context may still be "active". A + thread can still modify the last event as long as the context is + active. + + \see kherr_get_next_event(), kherr_get_prev_event(), + kherr_get_last_event() + */ +KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c); + +/*! \brief Get the next event + + Call kherr_get_first_event() to obtain the first event in a + context. Subsequent calls to kherr_get_next_event() will yield + other events in the order in which they were reported. The list + ends when kherr_get_next_event() returns NULL. + + The returned pointer is only valid as long as there is a hold on + \a c. Once the context is released with a call to + kherr_release_context() all pointers to events in the context + become invalid. + + In addition, the last event in a context may still be "active". A + thread can still modify the last event as long as the context is + active. + + \see kherr_get_first_event(), kherr_get_prev_event(), + kherr_get_last_event() + */ +KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e); + +/*! \brief Get the previous event + + Returns a pointer to the event that was reported in the context + containing \a e prior to \a e being reported. + + The returned pointer is only valid as long as there is a hold on + the error context. Once the context is released with a call to + kherr_release_context() all pointers to events in the context + become invalid. + + In addition, the last event in a context may still be "active". A + thread can still modify the last event as long as the context is + active. + + \see kherr_get_first_event(), kherr_get_next_event(), + kherr_get_last_event() + */ +KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e); + +/*! \brief Get the last event in an error context + + Returns a pointer to the last error event that that was reported + to the context \a c. + + The returned pointer is only valid as long as there is a hold on + the error context. Once the context is released with a call to + kherr_release_context(), all pointers to events in the context + become invalid. + + In addtion, the last event in a context may still be "active". A + thread can still modify the last event as long as the context is + active. + + \see kherr_get_first_event(), kherr_get_next_event(), + kherr_get_prev_event() + */ +KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c); + +/*! \brief Get the first child context of a context + + Contexts are arranged in a hiearchy. This function returns the + first child of an error context. Use kherr_get_next_context() to + obtain the other contexts. If \a c is \a NULL, this returns the + first root level context. + + The returned pointer must be released with a call to + kherr_release_context() + */ +KHMEXP kherr_context * KHMAPI kherr_get_first_context(kherr_context * c); + +/*! \brief Get the next sibling context of a context + + The returned pointer must be released with a call to + kherr_release_context() + + \see kherr_get_first_context() + */ +KHMEXP kherr_context * KHMAPI kherr_get_next_context(kherr_context * c); + +/*! \brief Get the desciption event for the context + + The description event is the event that was denoted using + kherr_set_desc_event() as the event which describes the context. + + The returned pointer is only valid as long as there is a hold on + \a c. Once the context is released with a call to + kherr_release_context() all pointers to events in the context + becomes invalid. + */ +KHMEXP kherr_event * KHMAPI kherr_get_desc_event(kherr_context * c); + +/*! \brief Get the error event for the context + + The error event for a context is the last event that had the + highest severity level. + + The returned pointer is only valid as long as there is a hold on + \a c. Once the context is released with a call to + kherr_release_context() all pointers to events in the context + becomes invalid. + */ +KHMEXP kherr_event * KHMAPI kherr_get_err_event(kherr_context * c); + +/*! \brief Evaluate an event + + When an event is reported, all the parameters and resource + references that were passed to kherr_report() are kept as-is until + the actual string values are required by the error reporting + library. However, if the string fields are required before then, + an application can call kherr_evaluate_event() to get them. + + This function does the following: + + - Load any referenced string or message resources that are + referenced in the event's short description, long description or + suggestion. + + - Expand any inserts using the parameters that were passed in. + + - Free up allocated strings in for the descriptions or suggestion + fields and any parameters. + + - Update the string fields in the event to contain the newly + generated strings. + + */ +KHMEXP void KHMAPI kherr_evaluate_event(kherr_event * e); + +/*! \brief Evaluate the last event + + Same as kherr_evaluate_event(), but operates on the last event + logged by the current thread. + + \see kherr_evaluate_event() + */ +KHMEXP void KHMAPI kherr_evaluate_last_event(void); +#define _resolve kherr_evaluate_last_event + +/*! \defgroup kherr_fids Standard Facility IDs +@{*/ +#define KHM_FACILITY_KMM 1 +#define KHM_FACILITY_KCDB 2 +#define KHM_FACILITY_UI 3 +#define KHM_FACILITY_KRB5 64 +#define KHM_FACILITY_KRB4 65 +#define KHM_FACILITY_AFS 66 +#define KHM_FACILITY_USER 128 +/*@}*/ + +/*@}*/ + +/* In debug mode, outputs the formatted string to the debug console */ +#ifdef DEBUG +KHMEXP void kherr_debug_printf(wchar_t * fmt, ...); +#endif + +#endif diff --git a/krb5-1-6/src/windows/identity/kherr/kherrinternal.h b/krb5-1-6/src/windows/identity/kherr/kherrinternal.h new file mode 100644 index 000000000..278ce5e52 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kherr/kherrinternal.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHERRORINTERNAL_H +#define __KHIMAIRA_KHERRORINTERNAL_H + +#define _NIMLIB_ + +#include<windows.h> +#include<kherr.h> +#include<utils.h> +#include<strsafe.h> + +#define IS_KHERR_CTX(c) ((c) && (c)->magic == KHERR_CONTEXT_MAGIC) +#define IS_KHERR_EVENT(e) ((e) && (e)->magic == KHERR_EVENT_MAGIC) + +typedef struct tag_kherr_thread { + khm_size nc_ctx; + khm_size n_ctx; + kherr_context ** ctx; +} kherr_thread; + +#define THREAD_STACK_SIZE 8 + +typedef struct tag_kherr_handler_node { + khm_int32 filter; + kherr_ctx_handler h; + kherr_serial serial; +} kherr_handler_node; + +#define CTX_ALLOC_INCR 4 + +#define EVENT_MASK_UNRESOLVED \ + (KHERR_RF_RES_SHORT_DESC|KHERR_RF_MSG_SHORT_DESC| \ + KHERR_RF_RES_LONG_DESC|KHERR_RF_MSG_LONG_DESC| \ + KHERR_RF_RES_SUGGEST|KHERR_RF_MSG_SUGGEST) + +extern CRITICAL_SECTION cs_error; +extern DWORD tls_error; +extern kherr_context * ctx_free_list; +extern kherr_event * evt_free_list; +extern kherr_handler_node * ctx_handlers; +extern khm_size n_ctx_handlers; + +#define parm_type(p) ((p).type) +#define parm_data(p) ((p).data) + +void resolve_event_strings(kherr_event *); +void attach_this_thread(void); +void detach_this_thread(void); +#endif diff --git a/krb5-1-6/src/windows/identity/kherr/kherrmain.c b/krb5-1-6/src/windows/identity/kherr/kherrmain.c new file mode 100644 index 000000000..c7afd7bc2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kherr/kherrmain.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kherrinternal.h> + +void +kherr_process_attach(void) { + InitializeCriticalSection(&cs_error); + tls_error = TlsAlloc(); +} + +void +kherr_process_detach(void) { + TlsFree(tls_error); + DeleteCriticalSection(&cs_error); +} + +void +kherr_thread_attach(void) { + /* We don't call attach_this_thread() here since we only + want to create a context stack for this thread if + someone wants one. */ + /* attach_this_thread(); */ +} + +void +kherr_thread_detach(void) { + detach_this_thread(); +} diff --git a/krb5-1-6/src/windows/identity/kmm/Makefile b/krb5-1-6/src/windows/identity/kmm/Makefile new file mode 100644 index 000000000..6fd85ad80 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=kmm +!include <../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\kmm.h \ + $(INCDIR)\kplugin.h + +OBJFILES= \ + $(OBJ)\kmmmain.obj \ + $(OBJ)\kmm.obj \ + $(OBJ)\kmm_plugin.obj \ + $(OBJ)\kmm_module.obj \ + $(OBJ)\kmm_reg.obj \ + $(OBJ)\kmm_registrar.obj \ + $(OBJ)\kmmconfig.obj + +MSGRESFILE=$(OBJ)\kmm_msgs.res + +$(OBJ)\kmmconfig.c: kmmconfig.csv $(CONFDIR)\csvschema.cfg + $(CCSV) $** $@ + +$(MSGRESFILE): $(OBJ)\kmm_msgs.rc + +$(OBJ)\kmm_msgs.rc: lang\kmm_msgs.mc + $(MC2RC) + +all: mkdirs $(INCFILES) $(MSGRESFILE) $(OBJFILES) + +clean:: + if exist ..\obj $(RM) $(INCFILES) diff --git a/krb5-1-6/src/windows/identity/kmm/kmm.c b/krb5-1-6/src/windows/identity/kmm/kmm.c new file mode 100644 index 000000000..e2784e8fd --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmm.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmminternal.h> +#include<assert.h> + +khm_boolean kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l) +{ + HMODULE h; + + if(l->filename != NULL) { + wchar_t path[MAX_PATH]; + DWORD dw; + + /* construct the path name */ + assert(m->h_module != NULL); + + dw = PathIsFileSpec(l->filename); + + assert(dw); + if (!dw) + return FALSE; + + dw = GetModuleFileName(m->h_module, path, ARRAYLENGTH(path)); + assert(dw != 0); + if (dw == 0) + return FALSE; + + PathRemoveFileSpec(path); + dw = PathAppend(path, l->filename); + assert(dw); + if (!dw) + return FALSE; + + h = LoadLibrary(path); + if(!h) + return FALSE; + + EnterCriticalSection(&cs_kmm); + m->h_resource = h; + m->lcid_resource = (WORD) l->language; + LeaveCriticalSection(&cs_kmm); + + return TRUE; + + } else { + /* in this case, the language resources are assumed to be in the + main module library itself. */ + + EnterCriticalSection(&cs_kmm); + m->h_resource = m->h_module; + m->lcid_resource = (WORD) l->language; + LeaveCriticalSection(&cs_kmm); + + return TRUE; + } +} + + +KHMEXP khm_int32 KHMAPI kmm_set_locale_info(kmm_module module, kmm_module_locale * locales, khm_int32 n_locales) +{ + kmm_module_i * m; + LANGID lcid; + int i; + int * f; + khm_int32 rv = KHM_ERROR_SUCCESS; + + m = kmm_module_from_handle(module); + + if(!m || m->state != KMM_MODULE_STATE_INIT) + return KHM_ERROR_INVALID_OPERATION; + + if(!locales || n_locales < 0) + return KHM_ERROR_INVALID_PARAM; + + f = PMALLOC(n_locales * sizeof(int)); + if(!f) + return KHM_ERROR_UNKNOWN; + ZeroMemory(f, sizeof(int) * n_locales); + + lcid = GetUserDefaultLangID(); + + /* first search for an exact match */ + for(i=0; i<n_locales; i++) { + if(locales[i].language == lcid) { + f[i] = TRUE; + if(kmmint_load_locale_lib(m, &locales[i])) + break; + } + } + + if(i<n_locales) + goto _exit; + + /* ok, that didn't work. Try an inexact match. */ + for(i=0; i<n_locales; i++) { + if(!f[i] && (PRIMARYLANGID(locales[i].language) == PRIMARYLANGID(lcid))) { + f[i] = TRUE; + if(kmmint_load_locale_lib(m,&locales[i])) + break; + } + } + + if(i < n_locales) + goto _exit; + + /* hmm. no matches yet. just try to locate the default locale */ + for(i=0; i<n_locales; i++) { + if(!f[i] && (locales[i].flags & KMM_MLOC_FLAG_DEFAULT)) { + f[i] = TRUE; + if(kmmint_load_locale_lib(m,&locales[i])) + break; + } + } + + if(i < n_locales) + goto _exit; + + /* give up */ + rv = KHM_ERROR_NOT_FOUND; + +_exit: + PFREE(f); + return rv; +} + +#ifdef _WIN32 +KHMEXP HMODULE KHMAPI kmm_get_resource_hmodule(kmm_module vm) +{ + if(!kmm_is_module(vm)) + return NULL; + else + return (kmm_module_from_handle(vm))->h_resource; +} +#endif + +KHMEXP kmm_module KHMAPI +kmm_this_module(void) { + kmm_plugin_i * p; + kmm_module_i * m; + kmm_module vm; + + p = TlsGetValue(tls_kmm); + if (!kmm_is_plugin(p)) + return NULL; + + m = p->module; + vm = kmm_handle_from_module(m); + + kmm_hold_module(vm); + + return vm; +} + +KHMEXP kmm_plugin KHMAPI +kmm_this_plugin(void) { + kmm_plugin_i * p; + kmm_plugin vp; + + p = TlsGetValue(tls_kmm); + if (!kmm_is_plugin(p)) + return NULL; + + vp = kmm_handle_from_plugin(p); + + kmm_hold_plugin(vp); + + return vp; +} diff --git a/krb5-1-6/src/windows/identity/kmm/kmm.h b/krb5-1-6/src/windows/identity/kmm/kmm.h new file mode 100644 index 000000000..56d43984b --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmm.h @@ -0,0 +1,1068 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KMM_H +#define __KHIMAIRA_KMM_H + +#include<khdefs.h> +#include<kmq.h> + +/*! \defgroup kmm NetIDMgr Module Manager +@{*/ + +/*! \brief A handle to a module. +*/ +typedef khm_handle kmm_module; + +/*! \brief A handle to a plugin. + */ +typedef khm_handle kmm_plugin; + +/*! \name Limits + @{*/ + +/*! \brief Maximum number of characters in a name in KMM including the terminating NULL */ +#define KMM_MAXCCH_NAME 256 + +/*! \brief Maximum number of bytes in a name in KMM including the terminating NULL */ +#define KMM_MAXCB_NAME (sizeof(wchar_t) * KMM_MAXCCH_NAME) + +/*! \brief Maximum number of characters in a description in KMM including the terminating NULL */ +#define KMM_MAXCCH_DESC 512 + +/*! \brief Maximum number of bytes in a description in KMM including the terminating NULL */ +#define KMM_MAXCB_DESC (sizeof(wchar_t) * KMM_MAXCCH_NAME) + +/*! \brief Maximum number of characters in a vendor string in KMM including the terminating NULL */ +#define KMM_MAXCCH_VENDOR 256 + +/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */ +#define KMM_MAXCB_VENDOR (sizeof(wchar_t) * KMM_MAXCCH_VENDOR) + +/*! \brief Maximum number of characters in a support URI in KMM including the terminating NULL */ +#define KMM_MAXCCH_SUPPORT 256 + +/*! \brief Maximum number of bytes in a vendor string in KMM including the terminating NULL */ +#define KMM_MAXCB_SUPPORT (sizeof(wchar_t) * KMM_MAXCCH_SUPPORT) + +/*! \brief Maximum number of dependencies per plugin +*/ +#define KMM_MAX_DEPENDENCIES 8 + +/*! \brief Maximum number of dependants per plugin + */ +#define KMM_MAX_DEPENDANTS 32 + +/*! \brief Maximum number of characters a dependency string including trailing double NULL */ +#define KMM_MAXCCH_DEPS (KMM_MAXCCH_NAME * KMM_MAX_DEPENDENCIES + 1) + +/*! \brief Maximum number of bytes in a dependency string including trailing double NULL */ +#define KMM_MAXCB_DEPS (sizeof(wchar_t) * KMM_MAXCCH_DEPS) +/*@}*/ /* Limits */ + +/*! \brief Plugin registration + + \see ::khm_cred_provider +*/ +typedef struct tag_kmm_plugin_reg { + wchar_t * name; /*!< Name of the plugin. Maximum of + KMM_MAXCCH_NAME characters + including the terminating + NULL. Required. */ + + wchar_t * module; /*!< Name of module that owns the + plugin. Maximum of + KMM_MAXCCH_NAME characters + including terminating NULL. + Required. */ + + khm_int32 type; /*!< Type plugin type. One of + KHM_PITYPE_*. Required. */ + khm_int32 flags; /*!< Unused. Set to 0 */ + kmq_callback_t msg_proc; /*!< Message processor. Required. */ + wchar_t * dependencies; /*!< Dependencies. Note that this is + a multi string. (you can use the + KHC multi string functions to + manipulate multi strings or to + convert a comma separated list of + dependencies to a multi string). + Each string in the multi string + is a name of a plugin that this + plugin depends on. Optional (set + to NULL if this plugin has no + dependencies). Maximum of + KMM_MAXCCH_DEPS characters + including terminating double + NULL.*/ + + wchar_t * description; /*!< Description of the plugin. + Maximum of KMM_MAXCCH_DESC + characters including the + terminating + NULL. Localized. Optional (set to + NULL if not provided) */ +#ifdef _WIN32 + HICON icon; /*!< Icon used to represent the + plugin. Optional. (set to NULL if + not provided) */ +#endif +} kmm_plugin_reg; + +/*! \brief Plugin information +*/ +typedef struct tag_kmm_plugin_info { + kmm_plugin_reg reg; /*!< Registration info */ + + khm_int32 state; /*!< Current status of the plugin. + One of ::_kmm_plugin_states */ + + khm_int32 failure_count; /*!< Number of recorded failures in + the plugin */ + FILETIME failure_time; /*!< Time of first recorded failure */ + khm_int32 failure_reason; /*!< The reason for the first recorded + failure */ + + kmm_plugin h_plugin; /*!< Handle to plugin */ + + khm_int32 flags; /*!< Flags for the plugin. Currently + this can only specify + ::KMM_PLUGIN_FLAG_DISABLED. */ +} kmm_plugin_info; + +/*! \brief The plugin is disabled + + This flag will be set in the \a flags field of the + ::kmm_plugin_info structure for a plugin that has been marked as + disabled. If the plugin is currently running, but marked as + disabled for future sessions, then this bit will be set in \a + flags , but the \a state of the plugin will indicate that the + plugin is running. + */ +#define KMM_PLUGIN_FLAG_DISABLED 0x00000400 + +/*! \name Plugin types +@{*/ +/*! \brief A credentials provider + + \see \ref pi_pt_cred for more information. + */ +#define KHM_PITYPE_CRED 1 + +/*! \brief A identity provider + + \see \ref pi_pt_cred for more information + */ +#define KHM_PITYPE_IDENT 2 + +/*! \brief A configuration provider + + \see \ref pi_pt_conf for more information. + */ +#define KHM_PITYPE_CONFIG 3 + +/*! \brief Undefined plugin type + + The plugin doesn't provide any credential type. + */ +#define KHM_PITYPE_MISC 4 + +/*@}*/ + +/*! \brief Plugin states */ +enum _kmm_plugin_states { + KMM_PLUGIN_STATE_FAIL_INIT = -6, /*!< Failed to initialize */ + KMM_PLUGIN_STATE_FAIL_UNKNOWN = -5, /*!< Failed due to unknown + reasons */ + KMM_PLUGIN_STATE_FAIL_MAX_FAILURE = -4, /*!< The plugin has + reached the maximum number + of failures and cannot be + initialized until the + failure count is reset */ + KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED = -3, /*!< Failed because the + plugin was not registered + and automatic registration + failed. */ + KMM_PLUGIN_STATE_FAIL_DISABLED = -2,/*!< Failed because plugin was + disabled by the user. */ + KMM_PLUGIN_STATE_FAIL_LOAD = -1, /*!< The plugin failed to load + due to some unknown + reason. */ + KMM_PLUGIN_STATE_NONE = 0, /*!< Unknown state */ + KMM_PLUGIN_STATE_PLACEHOLDER, /*!< Placeholder. The plugin + hasn't been provided by + anyone yet, but the plugin + record has been created to + keep track of + dependencies. */ + KMM_PLUGIN_STATE_REG, /*!< The plugin is registered + but not initialized */ + KMM_PLUGIN_STATE_PREINIT, /*!< The plugin is in the + process of being + initialized */ + KMM_PLUGIN_STATE_HOLD, /*!< On hold. One or more + dependencies of this plugin + has not been resolved */ + KMM_PLUGIN_STATE_INIT, /*!< The plugin was initialized */ + KMM_PLUGIN_STATE_RUNNING, /*!< The plugin is running */ + KMM_PLUGIN_STATE_EXITED /*!< The plugin has been stopped. */ +}; + +/*! \brief Module registration */ +typedef struct tag_kmm_module_reg { + wchar_t * name; /*!< Identifier for the module */ + wchar_t * path; /*!< Full pathname to module + binary */ + + wchar_t * description; /*!< Description of module */ + + wchar_t * vendor; /*!< Vendor/copyright string */ + + wchar_t * support; /*!< Support URL/contact */ + + khm_int32 n_plugins; /*!< Number of plugins that are + active */ + kmm_plugin_reg * plugin_reg_info; /*!< Array of kmm_plugin_reg + records for each active + plugin */ +} kmm_module_reg; + +/*! \brief Module information record */ +typedef struct tag_kmm_module_info { + kmm_module_reg reg; /*!< Registration info */ + + khm_ui_4 language; /*!< Currently loaded langugage */ + + khm_int32 state; /*!< Current status of the + module */ + + khm_version file_version; /*!< File version for the + module */ + khm_version product_version; /*!< Product version for the + module */ + + khm_int32 failure_count; /*!< Number of times the module + has failed to load */ + FILETIME failure_time; /*!< Time of first recorded + failure */ + khm_int32 failure_reason; /*!< Reason for first failure. + One of the module status + values */ + + kmm_module h_module; /*!< Handle to the module. */ +} kmm_module_info; + +/*! \brief Module states +*/ +enum KMM_MODULE_STATES { + KMM_MODULE_STATE_FAIL_INCOMPAT=-12, /*!< The library containing + the module was not + compatible with this version + of NetIDMgr. */ + KMM_MODULE_STATE_FAIL_INV_MODULE=-11, /*!< The library containing + the module was invalid. */ + KMM_MODULE_STATE_FAIL_UNKNOWN=-10, /*!< Module could not be + loaded due to unknown + reasons. */ + KMM_MODULE_STATE_FAIL_MAX_FAILURE=-9,/*!< The module has failed + too many times already. Not + attempting to restart it + again */ + KMM_MODULE_STATE_FAIL_DUPLICATE=-8, /*!< An attempt was made to + load the same module + twice. */ + KMM_MODULE_STATE_FAIL_NOT_REGISTERED=-7, /*!< The module is not + found among the registered + module list */ + KMM_MODULE_STATE_FAIL_NO_PLUGINS=-6,/*!< The module provided no + plugins, or all the plugins + that are provided are + disabled */ + KMM_MODULE_STATE_FAIL_DISABLED=-5, /*!< Module is disabled and + cannot be loaded */ + KMM_MODULE_STATE_FAIL_LOAD=-4, /*!< The module failed to + initialize */ + KMM_MODULE_STATE_FAIL_INVALID=-3, /*!< The module was invalid. + Typically caused by the + required entrypoints not + being present */ + KMM_MODULE_STATE_FAIL_SIGNATURE=-2, /*!< The module failed to load + due to an unverifiable + signature */ + KMM_MODULE_STATE_FAIL_NOT_FOUND=-1, /*!< The module was not + found */ + KMM_MODULE_STATE_NONE=0, /*!< Unknown state. The handle + is possibly invalid */ + KMM_MODULE_STATE_PREINIT, /*!< The module is being + loaded. init_module() hasn't + been called yet */ + KMM_MODULE_STATE_INIT, /*!< In init_module() */ + KMM_MODULE_STATE_INITPLUG, /*!< Initializing plugins */ + KMM_MODULE_STATE_RUNNING, /*!< Running */ + KMM_MODULE_STATE_EXITPLUG, /*!< Currently exiting plugins */ + KMM_MODULE_STATE_EXIT, /*!< Currently exiting */ + KMM_MODULE_STATE_EXITED /*!< Exited */ +}; + +/*! \brief Start the Module Manager + + \note Only called by the NetIDMgr core. +*/ +KHMEXP void KHMAPI +kmm_init(void); + +/*! \brief Stop the Module Manager + + \note Only called by the NetIDMgr core. +*/ +KHMEXP void KHMAPI +kmm_exit(void); + +/*! \brief Return the plugin handle for the current plugin + + The returned handle represents the plugin which owns the current + thread. The returned handle must be released by calling + kmm_release_plugin(). Returns NULL if the current thread is not + owned by any plugin. + */ +KHMEXP kmm_plugin KHMAPI +kmm_this_plugin(void); + +/*! \brief Return the module handle for the current module + + The returned handle represents the module which owns the current + thread. The returned handle must be released by calling + kmm_release_module() +*/ +KHMEXP kmm_module KHMAPI +kmm_this_module(void); + +/*! \name Flags for kmm_load_module() +@{*/ +/*!\brief Load synchronously + + If this flag is set, then the function waits for the module to be + loaded. The default is to load the module asynchronously. + + When loading a module asynchronously, the kmm_load_module() + function returns KHM_ERROR_SUCCESS and exits without waiting for + the module to load. If \a result is not NULL, it will receive a + valid handle to the module. + + When loading a module synchronously, kmm_load_module() will wait + for the module to completely load. If it fails to load properly, + it will return an error code and set \a result to NULL. +*/ +#define KMM_LM_FLAG_SYNC 1 + +/*! \brief Do not load + + Indicates that the module shouldn't actually be loaded. If the + specified module name identifies a module that has already been + loaded, then the function returns a held handle to the existing + module (use kmm_release_module() to free the handle). Otherwise, + the function returns KHM_ERROR_NOT_FOUND. +*/ +#define KMM_LM_FLAG_NOLOAD 2 +/*@}*/ + +/*! \brief Load a module + + The \a modulename parameter specifies a module to load. Depending + on the configuration, not all of the plugins that are provided by + the module may be loaded. If no plugins are successfully loaded, + the module will be immediately unloaded. + + If the module is currently loaded or is being loaded, then a valid + handle to the existing module is returned. + + When called with KMM_LM_FLAG_SYNC, the function does not return + until the module and the associated plugins are all initialized, + or an error occurs. + + If the KMM_LM_FLAG_NOLOAD flag is set, then a handle to an + existing instance of the module will be returned. If the module + hasn't been loaded yet, then no handle is returned and the + function returns KHM_ERROR_NOT_FOUND. + + See the associated NetIDMgr Module Manager documentation on the + sequence of events associated with loading a module. + + \param[in] modulename Name of the module. The module should have + been registered under this name prior to the call. + \param[in] flags Combination of KMM_LM_FLAG_* + \param[out] result Receives a handle to the loaded module. If the + result is not required, set this to NULL. If \a result is not + NULL, and km_load_module() returns KHM_ERROR_SUCCESS, then + kmm_release_module() must be called to release the handle to + the module. Otherwise, \a result receives NULL. If a handle + is returned, it will be valid regardless of whether the module + fails to load or not. You can use kmm_get_module_state() to + query the progress of the loading process. See + ::KMM_LM_FLAG_SYNC. + + \retval KHM_ERROR_SUCCESS The call succeeded. If \a + KMM_LM_FLAG_SYNC was specified, this means that the module was + successfully loaded. Otherwise, it only means that the module + has been queued up for loading. Use kmm_get_module_state() to + determine if it was successfully loaded. If \a result is not + NULL, a valid handle is returned. + \retval KHM_ERROR_EXISTS The module is already loaded or has been + already queued for loading. If \a result is not NULL, a valid + handle to the existing module instance is returned. + \retval KHM_ERROR_NOT_FOUND If called with KMM_LM_FLAG_NOLOAD, + indicates that the module has not been loaded. Otherwise only + returned when called with KMM_LM_FLAG_SYNC. The module image + was not found. No handle is returned. + \retval KHM_ERROR_INVALID_SIGNATURE Only returned when called with + KMM_LM_FLAG_SYNC. The module was signed with an invalid + certificate. No handle is returned. + \retval KHM_ERROR_UNKNOWN Only returned when called with + KMM_LM_FLAG_SYNC. Some other error has occured. No handle is + returned. + + \see \ref pi_fw_pm_load + \see ::KMM_LM_FLAG_SYNC, ::KMM_LM_FLAG_NOLOAD +*/ +KHMEXP khm_int32 KHMAPI +kmm_load_module(wchar_t * modname, khm_int32 flags, kmm_module * result); + +/*! \brief Hold a handle to a module + + Use kmm_release_module() to release the hold. +*/ +KHMEXP khm_int32 KHMAPI +kmm_hold_module(kmm_module module); + +/*! \brief Release a handle to a module + + Release a held referece to a module that was returned in a call to + kmm_load_module(). +*/ +KHMEXP khm_int32 KHMAPI +kmm_release_module(kmm_module m); + +/*! \brief Query the state of a module + + When loading a module asynchronously you can query the state of + the loading process using this. The return value is a status + indicator. + + \return The return value is one of the ::KMM_MODULE_STATES + enumerations. +*/ +KHMEXP khm_int32 KHMAPI +kmm_get_module_state(kmm_module m); + +/*! \brief Unload a module + + See the associated NetIDMgr Module Manager documentation on the + sequence of events associated with unloading a module. + + \see \ref pi_fw_pm_unload +*/ +KHMEXP khm_int32 KHMAPI +kmm_unload_module(kmm_module module); + +/*! \brief Loads the default modules as specified in the configuration + + The configuration can specify the default set of modules to load. + This function dispatches the necessary message for loading these + modules and reutnrs. +*/ +KHMEXP khm_int32 KHMAPI +kmm_load_default_modules(void); + +/*! \brief Checks whether there are any pending loads + + Returns TRUE if there are modules still waiting to be loaded. +*/ +KHMEXP khm_boolean KHMAPI +kmm_load_pending(void); + +#ifdef _WIN32 + +/*! \brief Returns the Windows module handle from a handle to a NetIDMgr module. + Although it is possible to obtain the Windows module handle and + use it to call Windows API functions, it is not recommended to do + so. This is because that might cause the state of the module to + change in ways which are inconsistent from the internal data + structures that kmm maintains. + */ +KHMEXP HMODULE KHMAPI +kmm_get_hmodule(kmm_module m); +#endif + +/*! \brief Hold a plugin + + Obtains a hold on a plugin. The plugin handle will remain valid + until the hold is released with a call to kmm_release_plugin(). + No guarantees are made on the handle once the handle is released. + */ +KHMEXP khm_int32 KHMAPI +kmm_hold_plugin(kmm_plugin p); + +/*! \brief Release a plugin + + Releases a hold on a plugin obtained through a call to + kmm_hold_plugin(). The plugin handle should no longer be + considered valied once this is called. + */ +KHMEXP khm_int32 KHMAPI +kmm_release_plugin(kmm_plugin p); + +/*! \brief Provide a plugin + + This function must be called for each plugin that the module + provides. + + Note that this function returns immediately and does not + initialize the plugin. All plugins that are provided by a + module will be initialized once the init_module() function + returns. If the plugin has dependencies, it will be kept in a + held state until the plugins that it depends on are successfully + initialized. If the dependencies are not resolved (the dependent + plugins are not loaded), then plugin will not be initialized. + + If the plugin is not registered and \a plugin contains enough + information to perform the registration, then it will be + automatically registered. However, if the plugin is not + registered and cannot be registered using the provided + information, the plugin will not be initialized properly. Note + that automatic registration will always register the plugin in the + user configuration store. + + The \a name and \a msg_proc members of \a plugin are required to + have valid values. The \a icon member may optionally be + specified. The other fields can be specified if the plugin should + be automatically registered, however, the \a module field will be + ignored and will be determined by the \a module handle. + + \param[in] module Handle to this module that is providing the plugin. + \param[in] plugin A plugin descriptor. + + \retval KHM_ERROR_SUCCESS Succeeded. + \retval KHM_ERROR_INVALID_OPERATION The function was not called + during init_module() + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_DUPLICATE The plugin was already provided + + \note This can only be called when handing init_module() +*/ +KHMEXP khm_int32 KHMAPI +kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin); + +/*! \brief Query the state of a plugin. + + \return One of ::_kmm_plugin_states +*/ +KHMEXP khm_int32 KHMAPI +kmm_get_plugin_state(wchar_t * plugin); + +/*! \defgroup kmm_reg Registration + + The functions for managing plugin and module registration. These + functions are also available as static linked libraries for use by + external applications which must register or unregister plugins or + modules. +@{*/ + +/*! \brief Obtain the configuration space for a named plugin + + Note that the named plugin does not have to actually exist. + Configuration spaces for plugins are based solely on the plugin + name and hence can be accessed regardless of whether the specific + plugin is loaded or not. + + \param[in] flags Controls the options for opening the + configuration space. If KHM_FLAG_CREATE is specified, then + the configuration space for the plugin named \a plugin wil be + created if it doesn't already exist. The \a flags parameter + is directly passed into a call to khc_open_space(). + + \param[in] plugin Name of the plugin. The name can not contain + slashes. + + \param[out] result Receives a configuration space handle. The + calling application should free the handle using + khc_close_space(). + + \see khc_open_space() + \see khc_close_space() + */ +KHMEXP khm_int32 KHMAPI +kmm_get_plugin_config(wchar_t * plugin, khm_int32 flags, khm_handle * result); + +/*! \brief Obtain the configuration space for a named module + + The named module does not have to actually exist. Configuration + spaces for modules are based on the basename of the module + (including the extension). + + \param[in] module Name of the module. + + \param[in] flags The flags used to call khc_open_space(). You can + use this to specify a particular configuration store if + needed. + + \param[out] result Receives the handle to a configuration space if + successful. Call khc_close_space() to close the handle. + + \see khc_open_space() + \see khc_close_space() +*/ +KHMEXP khm_int32 KHMAPI +kmm_get_module_config(wchar_t * module, khm_int32 flags, khm_handle * result); + +/*! \brief Retrieve a handle to the configuration space for plugins + + The configuration space for plugins is a container which holds the + configuration subspaces for all the plugins. This is the config + space which must be used to load a configuration space for a + plugin. + + \param[in] flags The flags to pass in to the call to + khc_open_space(). The flags can be used to select a specific + configuration store if needed. + + \param[out] result Receives a handle to the configuration + space. Call khc_close_space() to close the handle + + \see khc_open_space() + \see khc_close_space() + */ +KHMEXP khm_int32 KHMAPI +kmm_get_plugins_config(khm_int32 flags, khm_handle * result); + +/*! \brief Retrieve the handle to the configuration space for modules + + The configuration space for modules is a container which hold the + configuration subspaces for all the modules. Each module + registration ends up in this subspace. + + \param[in] flags The flags to pass in to the call to + khc_open_space(). The flags can be used to select a specific + configuration store if needed. + + \param[out] result Receives a handle to the configuration space. + Call khc_close_space() to close the handle. + + \see khc_open_space() + \see khc_close_space() + */ +KHMEXP khm_int32 KHMAPI +kmm_get_modules_config(khm_int32 flags, khm_handle * result); + +/*! \brief Return information about a loaded module + + The retrieves a block of information about a module. Refer to + ::kmm_module_info for information about the format of the returned + data. + + Note that the size of the required buffer is actually greater than + the size of the ::kmm_module_info structure and accomodates the + ::kmm_plugin_info structures and strings required to complete the + information block. + + Call the function with \a buffer set to NULL and \a cb_buffer + pointing at a khm_size variable to obtain the required size of the + buffer. + + \param[in] module_name Name of a module + \param[in] flags Flags indicating which types of information to + return + \param[out] buffer Points to a buffer that recieves information. + Set this to NULL if only the size of the buffer is required. + \param[in,out] On entry, contains the size of the buffer pointed + to by \a buffer if \a buffer is not NULL. On exit, contains + the required size of the buffer or the number of actual bytes + copied. + + \retval KHM_ERROR_SUCCESS The requested information was copied + \retval KHM_ERROR_INVALID_PARAM One of the parameters was invalid + \retval KHM_ERROR_TOO_LONG The buffer was not large enough or was + NULL. The number of bytes requied is in \a cb_buffer. + \retval KHM_ERROR_NOT_FOUND The specified module is not a + registered module. + */ +KHMEXP khm_int32 KHMAPI +kmm_get_module_info(wchar_t * module_name, khm_int32 flags, + kmm_module_info * buffer, khm_size * cb_buffer); + +/*! \brief Get information about a module + + Similar to kmm_get_module_info(), but uses a module handle instead + of a name, and uses internal buffers for providing string fields. + + The information that is returned should be freed using a call to + kmm_release_module_info_i(). + + \see kmm_release_module_info_i() + */ +KHMEXP khm_int32 KHMAPI +kmm_get_module_info_i(kmm_module module, kmm_module_info * info); + +/*! \brief Release module information + + Releases the information returned by a previous call to + kmm_get_module_info_i(). The contents of the ::kmm_module_info + structure should not have been modified in any way between calling + kmm_get_module_info_i() and kmm_release_module_info_i(). + */ +KHMEXP khm_int32 KHMAPI +kmm_release_module_info_i(kmm_module_info * info); + +/*! \brief Obtain information about a plugin + + Retrieve a block of information about a plugin. See + ::kmm_plugin_info for details about what information can be + returned. Note that some fields may not be available if the + module is not loaded. + + Note that the size of the required buffer is greater than the size + of the ::kmm_plugin_info structure and accounts for strings as + well. Call kmm_get_plugin_info() with \a buffer set to NULL and + \a cb_buffer set to point to a variable of type \a khm_size to + obtain the required size of the structure. + + \param[in] plugin_name Name of the plugin + \param[out] buffer The buffer to receive the plugin information. + Set to \a NULL if only the size of the buffer is required. + \param[in,out] cb_buffer On entry, points to variable that + specifies the size of the buffer pointed to by \a buffer is \a + buffer is not \a NULL. On exit, holds the number of bytes + copied or the required size of the buffer. + + \retval KHM_ERROR_SUCCESS The requested information was + successfully copied to the \a buffer + \retval KHM_ERROR_TOO_LONG The buffer was either \a NULL or + insufficient to hold the requested information. The required + size of the buffer was stored in \a cb_buffer + \retval KHM_ERROR_INVALID_PARAM One or more parameters were + invlaid. + \retval KHM_ERROR_NOT_FOUND The specified plugin was not found + among the registered plugins. +*/ +KHMEXP khm_int32 KHMAPI +kmm_get_plugin_info(wchar_t * plugin_name, + kmm_plugin_info * buffer, + khm_size * cb_buffer); + +/*! \brief Obtain information about a plugin using a plugin handle + + Similar to kmm_get_plugin_info() but uses a plugin handle instead + of a plugin name. If the call is successful, the \a info + structure will be filled with information about the plugin. The + returned info should not be modified in any way and may contain + pointers to internal buffers. + + The returned information must be released with a call to + kmm_release_plugin_info_i(). + */ +KHMEXP khm_int32 KHMAPI +kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info); + +/*! \brief Release plugin information returned by kmm_get_plugin_info_i + + The information returned by kmm_get_plugin_info_i() should not be + modified in any way before calling kmm_release_plugin_info_i(). + Once the call completes, the contents of \a info will be + initialized to zero. + */ +KHMEXP khm_int32 KHMAPI +kmm_release_plugin_info_i(kmm_plugin_info * info); + +/*! \brief Enumerates plugins + + Enumerates through known plugins. This list may not include + plugins which were not loaded by NetIDMgr in this session. + + If the call is successful, a handle to the next plugin in the list + will be placed in \a p_next. The returned handle must be freed + with a call to kmm_release_plugin(). + + If the \a p parameter is set to NULL, then the first plugin handle + will be placed in \a p_next. The handles will not be returned in + any specific order. In addition, the enumeration may not include + all known plugins if the list of plugins changes during + enumeration. + */ +KHMEXP khm_int32 KHMAPI +kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next); + +/*! \brief Enables or disables a plugin + + This function currently does not take effect immediately. However + it marks the plugin as enabled or disabled so that the next time + NetIDMgr starts, the module manager will act accordingly. + + \param[in] p Handle to the plugin + + \param[in] enable If non-zero, the plugin will be marked as + enabled. Otherwise the plugin will be marked as disabled. + */ +KHMEXP khm_int32 KHMAPI +kmm_enable_plugin(kmm_plugin p, khm_boolean enable); + +/*! \brief Register a plugin + + The \a plugin member defines the plugin to be registered. The \a + msg_proc and \a icon members of the structure are ignored. + + At the time kmm_register_plugin() is called, the module specified + by \a module member of the \a plugin parameter must have been already + registered. Otherwise the function call fails. + + If the plugin has already been registered, then all the fields in + the plugin registration will be updated to be in sync with the + information provided in the \a plugin parameter. The failure + counts and associated statistics will not be reset when the + configuration information is updated. + + If the plugin has not been registered, the a new registration + entry is created in the configuration space indicated by the \a + config_flags parameter. In addition, the plugin will be added to + the list of plugins associated with the owning module. + + Note that the module that owns the plugin must be registered in + the same configuration store as the plugin. + + \param[in] plugin Registration info for the plugin. The \a + msg_proc and \a icon members are ignored. All other fields + are required. The \a description member should be localized + to the system locale when registering a plugin in the machine + configuration store and should be localized to the user locale + when registering a plugin in the user configuration store. + \param[in] config_flags Flags for the configuration provider. + These flags are used verbatim to call khc_open_space(), hence + they may be used to pick whether or not the registration is + per machine or per user. + + \see kmm_register_module() + */ +KHMEXP khm_int32 KHMAPI +kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags); + +/*! \brief Register a module + + The \a module parameter specifies the parameters for the module + registration. + + The \a plugin_info member should point to an array of + ::kmm_plugin_info structures unless the \a n_plugins member is + zero, in which case \a plugin_info can be \a NULL. Plugins can be + registered separately using kmm_register_plugin(). + + \param[in] module Information about the module. The name and path + fields are required. The \a plugin_info field can only be \a + NULL if \a n_plugins is zero. + + \param[in] config_flags Flags used to call khc_open_space(). This + can be used to choose the configuration store in which the + module registration will be performed. + */ +KHMEXP khm_int32 KHMAPI +kmm_register_module(kmm_module_reg * module, khm_int32 config_flags); + +/*! \brief Unregister a plugin + + Registration information associated with the plugin will be + removed. In addtion, the plugin will be removed from the list of + plugins provided by the owner module. + + \param[in] plugin Names the plugin to be removed + \param[in] config_flags Flags used to call khc_open_space(). Can + be used to choose the configuraiton store that is affected by + the call. + + \note kmm_unregister_plugin() has no effect on whether the plugin + is loaded or not. The caller must make sure that the plugin + is unloaded and the associated module is either also unloaded + or in a state where the plugin can be unregistered. + */ +KHMEXP khm_int32 KHMAPI +kmm_unregister_plugin(wchar_t * plugin, khm_int32 config_flags); + +/*! \brief Unregister a module + + Registration information associated with the module as well as all + the plugins provided by the module will be removed from the + configuration store. + + \param[in] module Names the module to be removed + + \param[in] config_flags Flags used to call khc_open_space(). Can + be used to choose the configuration store affected by the + call. + + \note kmm_unregister_module() has no effect on the loaded state of + the module. The caller should make sure that the module is + unloaded and in a state where it can be unregistered. + */ +KHMEXP khm_int32 KHMAPI +kmm_unregister_module(wchar_t * module, khm_int32 config_flags); + +/*@}*/ /* kmm_reg */ + +/*! \defgroup kmm_loc Internationalization support + + See \ref pi_localization for more information about + internationalization. + +@{*/ + +/*! \brief Locale descriptor record + + See kmm_set_locale() +*/ +typedef struct tag_kmm_module_locale { + khm_ui_4 language; /*!< A language ID. On Windows, you can use the + MAKELANGID macro to generate this value. */ + wchar_t * filename; /*!< The filename corresponding to this language. + Use NULL to indicate that resources for this + language are to be found in the main module. */ + khm_int32 flags; /*!< Flags. Combination of KMM_MLOC_FLAG_* */ +} kmm_module_locale; + +#define LOCALE_DEF(language_id, filename, flags) {language_id, filename, flags} + +/*! \brief Default (fallback) locale +*/ +#define KMM_MLOC_FLAG_DEFAULT 1 + + +/*! \brief Sets the locale for a loaded module. + + The given locale records are searched in the given order until a + locale that matches the current user locale is found. If no + locales match, then the first locale with the + ::KMM_MLOC_FLAG_DEFAULT flag set will be loaded. If no locales + have that flag set, then the first locale is loaded. + + You can obtain a handle to the loaded library using + kmm_get_resource_hmodule(). This function does not return until a + matched library is loaded. + + Note that the ::kmm_module_locale structure only specifies a + module name for the resource module. This resource module must + exist in the same directory as the \a module. + + \param[in] module The module handle + \param[in] locales An array of ::kmm_module_locale objects + \param[in] n_locales The number of objects in the array pointed to by \a locales + + \retval KHM_ERROR_SUCCESS Succeeded. + \retval KHM_ERROR_NOT_FOUND A matching locale resource library was not found. + \retval KHM_ERROR_INVALID_OPERATION The function was called on a module which is currently not being initalized. + + \see \ref pi_localization + \see kmm_get_resource_hmodule() + + \note This can only be called when handing init_module() +*/ +KHMEXP khm_int32 KHMAPI +kmm_set_locale_info(kmm_module module, + kmm_module_locale * locales, + khm_int32 n_locales); + +#ifdef _WIN32 + +/*! \brief Return the Windows module handle of the resource library of a NetIDMgr module. + + NetIDMgr allows the specification of an alternate resource library + that will be used to load localized resources from. This function + returns a handle to this library. + + While you can use the convenience macros to access resources in a + localization library using the module handle, it is recommended, + for performance reasons, to use this function to obtain the handle + to the resource library and then use that handle in calls to + LoadString, LoadImage etc. directly. +*/ +KHMEXP HMODULE KHMAPI +kmm_get_resource_hmodule(kmm_module m); + +/*! \name Convenience Macros +@{*/ +/*! \brief Convenience macro for using calling LoadAccelerators using a module handle + + \param[in] module A handle to a loaded module. The corresponding resource + module will be located through a call to kmm_get_resource_hmodule() +*/ +#define kmm_LoadAccelerators(module, lpTableName) \ + (LoadAccelerators(kmm_get_resource_hmodule(module), lpTableName)) + +/*! \brief Convenience macro for using calling LoadBitmap using a module handle + + \param[in] module A handle to a loaded module. The corresponding resource + module will be located through a call to kmm_get_resource_hmodule() +*/ +#define kmm_LoadBitmap(module, lpBitmapName) \ + (LoadBitmap(kmm_get_resource_hmodule(module), lpBitmapName)) + +/*! \brief Convenience macro for using calling LoadImage using a module handle + + \param[in] module A handle to a loaded module. The corresponding resource + module will be located through a call to kmm_get_resource_hmodule() +*/ +#define kmm_LoadImage(module, lpszName, uType, cxDesired, cyDesired, fuLoad) \ + (LoadImage(kmm_get_resource_hmodule(module), lpszName, uType, cxDesired, cyDesired, fuLoad)) + +/*! \brief Convenience macro for using calling LoadCursor using a module handle + + \param[in] module A handle to a loaded module. The corresponding resource + module will be located through a call to kmm_get_resource_hmodule() +*/ +#define kmm_LoadCursor(module, lpCursorName) \ + (LoadCursor(kmm_get_resource_hmodule(module), lpCursorName)) + +/*! \brief Convenience macro for using calling LoadIcon using a module handle + + \param[in] module A handle to a loaded module. The corresponding resource + module will be located through a call to kmm_get_resource_hmodule() +*/ +#define kmm_LoadIcon(module, lpIconName) \ + (LoadIcon(kmm_get_resource_hmodule(module), lpIconName)) + +/*! \brief Convenience macro for using calling LoadMenu using a module handle + + \param[in] module A handle to a loaded module. The corresponding resource + module will be located through a call to kmm_get_resource_hmodule() +*/ +#define kmm_LoadMenu(module, lpMenuName) \ + (LoadMenu(kmm_get_resource_hmodule(module), lpMenuName)) + +/*! \brief Convenience macro for using calling LoadString using a module handle + + \param[in] module A handle to a loaded module. The corresponding resource + module will be located through a call to kmm_get_resource_hmodule() +*/ +#define kmm_LoadString(module, uID, lpBuffer, nBufferMax) \ + (LoadString(kmm_get_resource_hmodule(module), uID, lpBuffer, nBufferMax)) +/*@}*/ /* Convenience Macros */ +#endif +/*@}*/ /* group kmm_loc */ +/*@}*/ /* group kmm */ +#endif diff --git a/krb5-1-6/src/windows/identity/kmm/kmm_module.c b/krb5-1-6/src/windows/identity/kmm/kmm_module.c new file mode 100644 index 000000000..13fae87d3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmm_module.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmminternal.h> +#include<netidmgr_version.h> +#include<assert.h> + +/* should only be accessed from the registrar thread */ +khm_size kmm_active_modules = 0; + +kmm_module_i * kmmint_get_module_i(wchar_t * name) +{ + kmm_module_i * m; + size_t sz; + + if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &sz))) + return NULL; + sz += sizeof(wchar_t); + + EnterCriticalSection(&cs_kmm); + m = (kmm_module_i *) hash_lookup(hash_modules, (void *) name); + + if(m == NULL) { + m = PMALLOC(sizeof(kmm_module_i)); + ZeroMemory(m, sizeof(kmm_module_i)); + + m->magic = KMM_MODULE_MAGIC; + m->name = PMALLOC(sz); + StringCbCopy(m->name, sz, name); + m->state = KMM_MODULE_STATE_NONE; + + hash_add(hash_modules, (void *) m->name, (void *) m); + LPUSH(&kmm_all_modules, m); + } + LeaveCriticalSection(&cs_kmm); + + return m; +} + +kmm_module_i * kmmint_find_module_i(wchar_t * name) +{ + kmm_module_i * m; + + EnterCriticalSection(&cs_kmm); + m = (kmm_module_i *) hash_lookup(hash_modules, (void *) name); + LeaveCriticalSection(&cs_kmm); + + return m; +} + +/* called with cs_kmm held */ +void kmmint_free_module(kmm_module_i * m) +{ + m->magic = 0; + + hash_del(hash_modules, m->name); + LDELETE(&kmm_all_modules, m); + + if (m->name) + PFREE(m->name); + + if (m->description) + PFREE(m->description); + + if (m->path) + PFREE(m->path); + + if (m->vendor) + PFREE(m->vendor); + + if (m->support) + PFREE(m->support); + + if (m->version_info) + PFREE(m->version_info); + + PFREE(m); +} + +KHMEXP khm_int32 KHMAPI kmm_hold_module(kmm_module module) +{ + if(!kmm_is_module(module)) + return KHM_ERROR_INVALID_PARAM; + EnterCriticalSection(&cs_kmm); + kmm_module_from_handle(module)->refcount++; + LeaveCriticalSection(&cs_kmm); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kmm_release_module(kmm_module vm) +{ + kmm_module_i * m; + + if(!kmm_is_module(vm)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_kmm); + m = kmm_module_from_handle(vm); + if(! --(m->refcount)) + { + /* note that a 0 ref count means that there are no active + plugins */ + kmmint_free_module(m); + } + LeaveCriticalSection(&cs_kmm); + return KHM_ERROR_SUCCESS; +} + +khm_int32 +kmmint_check_api_version(DWORD v) { + /* for now, we allow API versions in the range + KH_VERSION_API_MINCOMPAT through KH_VERSION_API, inclusive. In + the future when we are swamped with so much time that we don't + know what to do with it, we can actually parse the + apiversion.txt file and create a compatibility table which we + can check against the functions used by the module and decide + whether or not it is compatible. */ + + if (v < KH_VERSION_API_MINCOMPAT || + v > KH_VERSION_API) + return KHM_ERROR_INCOMPATIBLE; + else + return KHM_ERROR_SUCCESS; +} + +struct lang_code { + WORD language; + WORD codepage; +}; + +khm_int32 +kmmint_read_module_info(kmm_module_i * m) { + /* the only fields we can count on at this point are m->name and + m->path */ + DWORD t; + size_t cb; + WORD lang; + khm_int32 rv = KHM_ERROR_SUCCESS; + struct lang_code *languages; + int n_languages; + int i; + wchar_t resname[256]; /* the resource names are a lot shorter */ + wchar_t * r; + VS_FIXEDFILEINFO *vff; + UINT c; + + assert(m->name); + assert(m->path); + + t = TRUE; + cb = GetFileVersionInfoSize(m->path, + &t); + /* if successful, cb gets the size in bytes of the version info + structure and sets t to zero */ + if (t) { + return KHM_ERROR_NOT_FOUND; + } else if (cb == 0) { + _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path)); + return KHM_ERROR_INVALID_PARAM; + } + + if (m->version_info) { + PFREE(m->version_info); + m->version_info = NULL; + } + + m->version_info = PMALLOC(cb); +#ifdef DEBUG + assert(m->version_info); +#endif + + if(!GetFileVersionInfo(m->path, + t, (DWORD) cb, m->version_info)) { + rv = KHM_ERROR_NOT_FOUND; + _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path)); + _location(L"GetFileVersionInfo"); + goto _cleanup; + } + + if(!VerQueryValue(m->version_info, + L"\\VarFileInfo\\Translation", + (LPVOID*) &languages, + &c)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_NO_TRANS, _dupstr(m->path)); + _location(L"VerQueryValue"); + goto _cleanup; + } + + n_languages = (int) (c / sizeof(*languages)); + + /* Try searching for the user's default language first */ + lang = GetUserDefaultLangID(); + for (i = 0; i < n_languages; i++) { + if(languages[i].language == lang) + break; + } + + /* If not, try the system default */ + if (i >= n_languages) { + lang = GetSystemDefaultLangID(); + for (i=0; i<n_languages; i++) + if (languages[i].language == lang) + break; + } + + /* Then try EN_US */ + if (i >= n_languages) { + lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); + for (i=0; i<n_languages; i++) + if (languages[i].language == lang) + break; + } + + /* Language neutral? */ + if (i >= n_languages) { + lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); + for (i=0; i<n_languages; i++) + if (languages[i].language == lang) + break; + } + + /* Just use the first one? */ + if (i >= n_languages) { + i = 0; + } + + if (i >= n_languages) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr0(KHERR_WARNING, MSG_RMI_NO_LOCAL); + goto _cleanup; + } + + /* check module name */ + StringCbPrintf(resname, sizeof(resname), + L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_MODULE), + languages[i].language, + languages[i].codepage); + + if (!VerQueryValue(m->version_info, + resname, (LPVOID *) &r, &c)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, + _cstr(TEXT(NIMV_MODULE))); + goto _cleanup; + } + + if (c > KMM_MAXCB_NAME || + FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, + _cstr(TEXT(NIMV_MODULE))); + goto _cleanup; + } + + if (wcscmp(r, m->name)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr2(KHERR_WARNING, MSG_RMI_MOD_MISMATCH, + _dupstr(r), _dupstr(m->name)); + goto _cleanup; + } + + /* check API version */ + StringCbPrintf(resname, sizeof(resname), + L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_APIVER), + languages[i].language, + languages[i].codepage); + + if (!VerQueryValue(m->version_info, + resname, (LPVOID *) &r, &c)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, + _cstr(TEXT(NIMV_APIVER))); + goto _cleanup; + } + + if (c > KMM_MAXCB_NAME || + FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, + _cstr(TEXT(NIMV_APIVER))); + goto _cleanup; + } + + t = wcstol(r, NULL, 10); + + rv = kmmint_check_api_version(t); + + if (KHM_FAILED(rv)) { + _report_mr2(KHERR_WARNING, MSG_RMI_API_MISMATCH, + _int32(t), _int32(KH_VERSION_API)); + goto _cleanup; + } + + /* Looks good. Now load the description, copyright, support URI + and file versions */ + if (m->description) { + PFREE(m->description); + m->description = NULL; + } + + StringCbPrintf(resname, sizeof(resname), + L"\\StringFileInfo\\%04x%04x\\FileDescription", + languages[i].language, + languages[i].codepage); + + if (!VerQueryValue(m->version_info, + resname, (LPVOID *) &r, &c)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, + _cstr(L"FileDescription")); + goto _cleanup; + } + + if (c > KMM_MAXCB_DESC || + FAILED(StringCbLength(r, KMM_MAXCB_DESC, &cb))) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, + _cstr(L"FileDescription")); + goto _cleanup; + } + + cb += sizeof(wchar_t); + + m->description = PMALLOC(cb); +#ifdef DEBUG + assert(m->description); +#endif + StringCbCopy(m->description, cb, r); + + /* on to the support URI */ + if (m->support) { + PFREE(m->support); + m->support = NULL; + } + + StringCbPrintf(resname, sizeof(resname), + L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_SUPPORT), + languages[i].language, + languages[i].codepage); + + if (!VerQueryValue(m->version_info, + resname, (LPVOID *) &r, &c)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, + _cstr(TEXT(NIMV_SUPPORT))); + goto _cleanup; + } + + if (c > KMM_MAXCB_SUPPORT || + FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, + _cstr(TEXT(NIMV_SUPPORT))); + goto _cleanup; + } + + cb += sizeof(wchar_t); + + m->support = PMALLOC(cb); +#ifdef DEBUG + assert(m->support); +#endif + StringCbCopy(m->support, cb, r); + + /* the vendor/copyright */ + if (m->vendor) { + PFREE(m->vendor); + m->vendor = NULL; + } + + StringCbPrintf(resname, sizeof(resname), + L"\\StringFileInfo\\%04x%04x\\LegalCopyright", + languages[i].language, + languages[i].codepage); + + if (!VerQueryValue(m->version_info, + resname, (LPVOID *) &r, &c)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, + _cstr(L"LegalCopyright")); + goto _cleanup; + } + + if (c > KMM_MAXCB_SUPPORT || + FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, + _cstr(L"LegalCopyright")); + goto _cleanup; + } + + cb += sizeof(wchar_t); + + m->vendor = PMALLOC(cb); +#ifdef DEBUG + assert(m->vendor); +#endif + StringCbCopy(m->vendor, cb, r); + + if (!VerQueryValue(m->version_info, + L"\\", + (LPVOID *) &vff, &c) || + c != sizeof(*vff)) { + + rv = KHM_ERROR_INVALID_PARAM; + _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, + _cstr(L"Fixed Version Info")); + goto _cleanup; + } + + m->file_version.major = HIWORD(vff->dwFileVersionMS); + m->file_version.minor = LOWORD(vff->dwFileVersionMS); + m->file_version.patch = HIWORD(vff->dwFileVersionLS); + m->file_version.aux = LOWORD(vff->dwFileVersionLS); + + m->prod_version.major = HIWORD(vff->dwProductVersionMS); + m->prod_version.minor = LOWORD(vff->dwProductVersionMS); + m->prod_version.patch = HIWORD(vff->dwProductVersionLS); + m->prod_version.aux = LOWORD(vff->dwProductVersionLS); + + rv = KHM_ERROR_SUCCESS; + + _cleanup: + if (KHM_FAILED(rv)) { + if (m->version_info) { + PFREE(m->version_info); + m->version_info = NULL; + } + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI kmm_load_module(wchar_t * modname, + khm_int32 flags, + kmm_module * result) +{ + kmm_module_i * m = NULL; + kmm_module_i * mi; + size_t cbsize; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(FAILED(StringCbLength(modname, KMM_MAXCB_NAME, &cbsize))) + return KHM_ERROR_INVALID_PARAM; + cbsize += sizeof(wchar_t); + + EnterCriticalSection(&cs_kmm); + mi = kmmint_find_module_i(modname); + + if(mi != NULL) { + kmm_hold_module(kmm_handle_from_module(mi)); + /* check if the module has either failed to load either or if + it has been terminated. If so, we try once again to load the + module. */ + if(!(flags & KMM_LM_FLAG_NOLOAD) && + (mi->state < 0 || mi->state == KMM_MODULE_STATE_EXITED)) + { + mi->state = KMM_MODULE_STATE_PREINIT; + } + } + LeaveCriticalSection(&cs_kmm); + + if(flags & KMM_LM_FLAG_NOLOAD) { + if(result) + *result = mi; + else if(mi) + kmm_release_module(kmm_handle_from_module(mi)); + + return (mi)? KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND; + } + + if(mi) { + m = mi; + } else { + m = kmmint_get_module_i(modname); + m->state = KMM_MODULE_STATE_PREINIT; + kmm_hold_module(kmm_handle_from_module(m)); + } + + /* the module is already running or is already being + worked on by the registrar */ + if(m->state != KMM_MODULE_STATE_PREINIT) { + if(result) + *result = kmm_handle_from_module(m); + else + kmm_release_module(kmm_handle_from_module(m)); + + return KHM_ERROR_EXISTS; + } + + kmmint_add_to_module_queue(); + + if(flags & KMM_LM_FLAG_SYNC) { + kmm_hold_module(kmm_handle_from_module(m)); + kmq_send_message(KMSG_KMM, + KMSG_KMM_I_REG, + KMM_REG_INIT_MODULE, + (void*) m); + if(m->state <= 0) { + /* failed to load ? */ + if(m->state == KMM_MODULE_STATE_FAIL_NOT_FOUND) + rv = KHM_ERROR_NOT_FOUND; + else if(m->state == KMM_MODULE_STATE_FAIL_SIGNATURE) + rv = KHM_ERROR_INVALID_SIGNATURE; + else + rv = KHM_ERROR_UNKNOWN; + + kmm_release_module(kmm_handle_from_module(m)); + if(result) + *result = NULL; + } else { + if(result) + *result = kmm_handle_from_module(m); + else + kmm_release_module(kmm_handle_from_module(m)); + } + } else { + kmm_hold_module(kmm_handle_from_module(m)); + kmq_post_message(KMSG_KMM, + KMSG_KMM_I_REG, + KMM_REG_INIT_MODULE, + (void*) m); + if(result) + *result = kmm_handle_from_module(m); + else + kmm_release_module(kmm_handle_from_module(m)); + } + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_get_module_state(kmm_module m) +{ + if(!kmm_is_module(m)) + return KMM_MODULE_STATE_NONE; + else + return kmm_module_from_handle(m)->state; +} + +KHMEXP khm_int32 KHMAPI +kmm_get_module_info_i(kmm_module vm, kmm_module_info * info) { + kmm_module_i * m; + khm_int32 rv; + + EnterCriticalSection(&cs_kmm); + if (!kmm_is_module(vm) || !info) + rv = KHM_ERROR_INVALID_PARAM; + else { + m = kmm_module_from_handle(vm); + + ZeroMemory(info, sizeof(*info)); + + info->reg.name = m->name; + info->reg.path = m->path; + info->reg.vendor = m->vendor; + + info->reg.n_plugins = m->plugin_count; + + info->state = m->state; + + info->h_module = vm; + + info->file_version = m->file_version; + info->product_version = m->prod_version; + kmm_hold_module(vm); + + rv = KHM_ERROR_SUCCESS; + } + LeaveCriticalSection(&cs_kmm); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_release_module_info_i(kmm_module_info * info) { + if (info->h_module) + kmm_release_module(info->h_module); + + ZeroMemory(info, sizeof(*info)); + + return KHM_ERROR_SUCCESS; +} + + +KHMEXP khm_int32 KHMAPI +kmm_unload_module(kmm_module module) { + + if(!kmm_is_module(module)) + return KHM_ERROR_INVALID_PARAM; + + kmm_hold_module(module); + kmq_post_message(KMSG_KMM, + KMSG_KMM_I_REG, + KMM_REG_EXIT_MODULE, + (void *) kmm_module_from_handle(module)); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kmm_load_default_modules(void) { + khm_handle csm = NULL; + khm_handle cs_mod = NULL; + khm_int32 rv; + wchar_t buf[KMM_MAXCCH_NAME]; + khm_size s; + + rv = kmm_get_modules_config(0, &csm); + if(KHM_FAILED(rv)) + return rv; + + _begin_task(KHERR_CF_TRANSITIVE); + _report_mr0(KHERR_NONE, MSG_LOAD_DEFAULT); + _describe(); + + kmmint_add_to_module_queue(); + + while(KHM_SUCCEEDED(khc_enum_subspaces(csm, cs_mod, &cs_mod))) { + + s = sizeof(buf); + if (KHM_FAILED(khc_get_config_space_name(cs_mod, buf, &s))) + continue; + + /* check for schema subspace. This is not an actual module. */ + if (!wcscmp(buf, L"_Schema")) + continue; + + kmm_load_module(buf, 0, NULL); + } + + kmmint_remove_from_module_queue(); + + if(csm) + khc_close_space(csm); + + _end_task(); + + return rv; +} + +#ifdef _WIN32 +KHMEXP HMODULE KHMAPI +kmm_get_hmodule(kmm_module m) +{ + if(!kmm_is_module(m)) + return NULL; + else + return kmm_module_from_handle(m)->h_module; +} +#endif diff --git a/krb5-1-6/src/windows/identity/kmm/kmm_plugin.c b/krb5-1-6/src/windows/identity/kmm/kmm_plugin.c new file mode 100644 index 000000000..89e31ad84 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmm_plugin.c @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmminternal.h> + +/* Called with no locks held to get a kmm_plugin_i structure + that matches the name. First we look in the hash table, and + if one isn't found, we create an empty one. +*/ + +kmm_plugin_i * +kmmint_get_plugin_i(wchar_t * name) +{ + kmm_plugin_i * p; + size_t cb; + + if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb))) + return NULL; + cb += sizeof(wchar_t); + + EnterCriticalSection(&cs_kmm); + p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name); + + if(p == NULL) { + p = PMALLOC(sizeof(kmm_plugin_i)); + ZeroMemory(p, sizeof(kmm_plugin_i)); + p->magic = KMM_PLUGIN_MAGIC; + p->p.name = PMALLOC(cb); + StringCbCopy(p->p.name, cb, name); + p->state = KMM_PLUGIN_STATE_NONE; + + hash_add(hash_plugins, (void *) p->p.name, (void *) p); + kmmint_list_plugin(p); + } + LeaveCriticalSection(&cs_kmm); + + return p; +} + +kmm_plugin_i * +kmmint_find_plugin_i(wchar_t * name) +{ + kmm_plugin_i * p; + size_t cb; + + if(FAILED(StringCbLength(name, KMM_MAXCB_NAME, &cb))) + return NULL; + + EnterCriticalSection(&cs_kmm); + p = (kmm_plugin_i *) hash_lookup(hash_plugins, (void *) name); + LeaveCriticalSection(&cs_kmm); + + return p; +} + +/* the plugin must be delisted before calling this */ +void +kmmint_list_plugin(kmm_plugin_i * p) +{ + EnterCriticalSection(&cs_kmm); + if((p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) || + (p->flags & KMM_PLUGIN_FLAG_IN_LIST)) + { + RaiseException(2, EXCEPTION_NONCONTINUABLE, 0, NULL); + } + p->flags |= KMM_PLUGIN_FLAG_IN_LIST; + LPUSH(&kmm_listed_plugins, p); + LeaveCriticalSection(&cs_kmm); +} + +void +kmmint_delist_plugin(kmm_plugin_i * p) +{ + EnterCriticalSection(&cs_kmm); + if(p->flags & KMM_PLUGIN_FLAG_IN_LIST) { + p->flags &= ~KMM_PLUGIN_FLAG_IN_LIST; + LDELETE(&kmm_listed_plugins, p); + } + if(p->flags & KMM_PLUGIN_FLAG_IN_MODLIST) { + p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST; + LDELETE(&(p->module->plugins), p); + } + LeaveCriticalSection(&cs_kmm); +} + +KHMEXP khm_int32 KHMAPI +kmm_hold_plugin(kmm_plugin p) +{ + kmm_plugin_i * pi; + + if(!kmm_is_plugin(p)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_kmm); + pi = kmm_plugin_from_handle(p); + pi->refcount++; + LeaveCriticalSection(&cs_kmm); + + return KHM_ERROR_SUCCESS; +} + +/* called with cs_kmm held */ +void +kmmint_free_plugin(kmm_plugin_i * pi) +{ + int i; + pi->magic = 0; + + hash_del(hash_plugins, (void *) pi->p.name); + + kmmint_delist_plugin(pi); + + for(i=0; i<pi->n_dependants; i++) { + kmm_release_plugin(kmm_handle_from_plugin(pi->dependants[i])); + pi->dependants[i] = NULL; + } + + if(pi->module) { + kmm_release_module(kmm_handle_from_module(pi->module)); + } + + pi->module = NULL; + pi->p.module = NULL; + + if(pi->p.name) + PFREE(pi->p.name); + pi->p.name = NULL; + + if(pi->p.description) + PFREE(pi->p.description); + pi->p.description = NULL; + + if(pi->p.dependencies) + PFREE(pi->p.dependencies); + pi->p.dependencies = NULL; + + PFREE(pi); +} + +KHMEXP khm_int32 KHMAPI +kmm_enable_plugin(kmm_plugin p, khm_boolean enable) { + kmm_plugin_i * pi; + khm_int32 rv = KHM_ERROR_NOT_FOUND; /* default to error */ + khm_handle csp_plugin = NULL; + + EnterCriticalSection(&cs_kmm); + if (!kmm_is_plugin(p)) { + rv = KHM_ERROR_INVALID_PARAM; + goto _cleanup; + } + + pi = kmm_plugin_from_handle(p); + + if (KHM_FAILED(rv = kmm_get_plugin_config(pi->p.name, 0, &csp_plugin))) { + goto _cleanup; + } + + if (KHM_FAILED(rv = khc_write_int32(csp_plugin, L"Disabled", !enable))) { + goto _cleanup; + } + + rv = KHM_ERROR_SUCCESS; + + _cleanup: + LeaveCriticalSection(&cs_kmm); + + if (csp_plugin) + khc_close_space(csp_plugin); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_get_plugin_info_i(kmm_plugin p, kmm_plugin_info * info) { + khm_int32 rv = KHM_ERROR_SUCCESS; + kmm_plugin_i * pi; + khm_handle csp_plugin; + + if (!info) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_kmm); + if (!kmm_is_plugin(p)) { + rv = KHM_ERROR_INVALID_PARAM; + goto _cleanup; + } + + pi = kmm_plugin_from_handle(p); + + ZeroMemory(info, sizeof(*info)); + + info->reg = pi->p; + info->reg.msg_proc = NULL; + + if (KHM_FAILED(kmm_get_plugin_config(pi->p.name, KHM_PERM_READ, + &csp_plugin))) { + info->failure_count = 0; + *((khm_int64 *)&info->failure_time) = 0; + info->failure_reason = 0; + } else { + if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureCount", + &info->failure_count))) + info->failure_count = 0; + if (KHM_FAILED(khc_read_int64(csp_plugin, L"FailureTime", + (khm_int64 *) &info->failure_time))) + *((khm_int64 *) &info->failure_time) = 0; + if (KHM_FAILED(khc_read_int32(csp_plugin, L"FailureReason", + &info->failure_reason))) + info->failure_reason = 0; + + khc_close_space(csp_plugin); + } + + info->state = pi->state; + + kmm_hold_plugin(p); + info->h_plugin = p; + + info->flags = (pi->flags & KMM_PLUGIN_FLAG_DISABLED); + + _cleanup: + LeaveCriticalSection(&cs_kmm); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_release_plugin_info_i(kmm_plugin_info * info) { + khm_int32 rv; + + if (!info || !info->h_plugin) + return KHM_ERROR_INVALID_PARAM; + + rv = kmm_release_plugin(info->h_plugin); + + ZeroMemory(info, sizeof(info)); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_get_next_plugin(kmm_plugin p, kmm_plugin * p_next) { + khm_int32 rv = KHM_ERROR_SUCCESS; + kmm_plugin_i * pi; + kmm_plugin_i * pi_next = NULL; + kmm_module_i * m; + + EnterCriticalSection(&cs_kmm); + if (p == NULL) { + if (kmm_listed_plugins) + pi_next = kmm_listed_plugins; + else { + for (m = kmm_all_modules; m; m = LNEXT(m)) { + if (m->plugins) { + pi_next = m->plugins; + break; + } + } + } + } else if (kmm_is_plugin(p)) { + pi = kmm_plugin_from_handle(p); + pi_next = LNEXT(pi); + + if (!pi_next) { + /* we have either exhausted the listed plugins or we are + at the end of the module's plugin list */ + if (pi->module) { + m = LNEXT(pi->module); + } else { + m = kmm_all_modules; + } + + for(; m; m = LNEXT(m)) { + if (m->plugins) { + pi_next = m->plugins; + break; + } + } + } + } + + if (pi_next) { + *p_next = kmm_handle_from_plugin(pi_next); + kmm_hold_plugin(*p_next); + } else { + *p_next = NULL; + rv = KHM_ERROR_NOT_FOUND; + } + + LeaveCriticalSection(&cs_kmm); + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_release_plugin(kmm_plugin p) +{ + kmm_plugin_i * pi; + + if(!kmm_is_plugin(p)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_kmm); + pi = kmm_plugin_from_handle(p); + pi->refcount--; + if(pi->refcount == 0) { + kmmint_free_plugin(pi); + } + LeaveCriticalSection(&cs_kmm); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kmm_provide_plugin(kmm_module module, kmm_plugin_reg * plugin) +{ + kmm_module_i * m; + kmm_plugin_i * p; + size_t cb_name = 0; + size_t cb_desc = 0; + size_t cb_dep = 0; + + m = kmm_module_from_handle(module); + + /* can only called when handing init_module() */ + if(m->state != KMM_MODULE_STATE_INIT) + return KHM_ERROR_INVALID_OPERATION; + + if(!plugin || + FAILED(StringCbLength(plugin->name, KMM_MAXCB_NAME - sizeof(wchar_t), + &cb_name)) || + (plugin->description && + FAILED(StringCbLength(plugin->description, + KMM_MAXCB_DESC - sizeof(wchar_t), + &cb_desc))) || + (plugin->dependencies && + KHM_FAILED(multi_string_length_cb(plugin->dependencies, + KMM_MAXCB_DEPS, &cb_dep)))) { + return KHM_ERROR_INVALID_PARAM; + } + + cb_name += sizeof(wchar_t); + cb_desc += sizeof(wchar_t); + + p = kmmint_get_plugin_i(plugin->name); + + /* released below or in kmmint_init_module() */ + kmm_hold_plugin(kmm_handle_from_plugin(p)); + + if(p->state != KMM_PLUGIN_STATE_NONE && + p->state != KMM_PLUGIN_STATE_PLACEHOLDER) + { + kmm_release_plugin(kmm_handle_from_plugin(p)); + return KHM_ERROR_DUPLICATE; + } + + /* released when the plugin quits */ + kmm_hold_module(module); + + p->module = m; + p->p.flags = plugin->flags; + p->p.msg_proc = plugin->msg_proc; + p->p.type = plugin->type; + + if(plugin->description) { + p->p.description = PMALLOC(cb_desc); + StringCbCopy(p->p.description, cb_desc, plugin->description); + } else + p->p.description = NULL; + + if(plugin->dependencies) { + p->p.dependencies = PMALLOC(cb_dep); + multi_string_copy_cb(p->p.dependencies, cb_dep, plugin->dependencies); + } else + p->p.dependencies = NULL; + + p->p.module = p->module->name; + + p->p.icon = plugin->icon; + + p->state = KMM_PLUGIN_STATE_REG; + + kmmint_delist_plugin(p); + EnterCriticalSection(&cs_kmm); + LPUSH(&(m->plugins), p); + p->flags |= KMM_PLUGIN_FLAG_IN_MODLIST; + LeaveCriticalSection(&cs_kmm); + + /* leave the plugin held because it is in the module's plugin list */ + return KHM_ERROR_SUCCESS; +} + diff --git a/krb5-1-6/src/windows/identity/kmm/kmm_reg.c b/krb5-1-6/src/windows/identity/kmm/kmm_reg.c new file mode 100644 index 000000000..e1adaa0c3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmm_reg.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2006, 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmminternal.h> + +KHMEXP khm_int32 KHMAPI +kmm_get_module_info(wchar_t * module_name, khm_int32 flags, + kmm_module_info * buffer, khm_size * cb_buffer) +{ + /*TODO:Implement this */ + return KHM_ERROR_NOT_IMPLEMENTED; +} + +KHMEXP khm_int32 KHMAPI +kmm_get_plugin_info(wchar_t * plugin_name, + kmm_plugin_info * buffer, khm_size * cb_buffer) +{ + /*TODO:Implement this */ + return KHM_ERROR_NOT_IMPLEMENTED; +} + +KHMEXP khm_int32 KHMAPI +kmm_get_plugins_config(khm_int32 flags, khm_handle * result) { + khm_handle csp_root; + khm_handle csp_plugins; + khm_int32 rv; + + rv = khc_open_space(KHM_INVALID_HANDLE, KMM_CSNAME_ROOT, flags, &csp_root); + + if(KHM_FAILED(rv)) + return rv; + + rv = khc_open_space(csp_root, KMM_CSNAME_PLUGINS, flags, &csp_plugins); + khc_close_space(csp_root); + + if(KHM_SUCCEEDED(rv)) + *result = csp_plugins; + else + *result = NULL; + + return rv; +} + + +KHMEXP khm_int32 KHMAPI +kmm_get_modules_config(khm_int32 flags, khm_handle * result) { + khm_handle croot; + khm_handle kmm_all_modules; + khm_int32 rv; + + rv = khc_open_space(NULL, KMM_CSNAME_ROOT, flags, &croot); + + if(KHM_FAILED(rv)) + return rv; + + rv = khc_open_space(croot, KMM_CSNAME_MODULES, flags, &kmm_all_modules); + khc_close_space(croot); + + if(KHM_SUCCEEDED(rv)) + *result = kmm_all_modules; + else + *result = NULL; + + return rv; +} + + +KHMEXP khm_int32 KHMAPI +kmm_get_plugin_config(wchar_t * plugin, khm_int32 flags, khm_handle * result) +{ + khm_handle csplugins; + khm_handle csplugin; + khm_int32 rv; + + if(!plugin || wcschr(plugin, L'/') || wcschr(plugin, L'\\')) + return KHM_ERROR_INVALID_PARAM; + + if(KHM_FAILED(kmm_get_plugins_config(flags, &csplugins))) + return KHM_ERROR_UNKNOWN; + + rv = khc_open_space(csplugins, plugin, flags, &csplugin); + *result = csplugin; + + khc_close_space(csplugins); + + return rv; +} + + +KHMEXP khm_int32 KHMAPI +kmm_get_module_config(wchar_t * module, khm_int32 flags, khm_handle * result) +{ + khm_handle csmodules; + khm_handle csmodule; + khm_int32 rv; + + if(!module || wcschr(module, L'/') || wcschr(module, L'\\')) + return KHM_ERROR_INVALID_PARAM; + + if(KHM_FAILED(kmm_get_modules_config(flags, &csmodules))) + return KHM_ERROR_UNKNOWN; + + rv = khc_open_space(csmodules, module, flags, &csmodule); + *result = csmodule; + + khc_close_space(csmodules); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_plugin = NULL; + khm_handle csp_module = NULL; + size_t cch; + + /* avoid accidently creating the module key if it doesn't exist */ + config_flags &= ~KHM_FLAG_CREATE; + + if((plugin == NULL) || + (plugin->dependencies && + KHM_FAILED(multi_string_length_cch(plugin->dependencies, + KMM_MAXCCH_DEPS, &cch))) || + FAILED(StringCchLength(plugin->module, KMM_MAXCCH_NAME, &cch)) || + (plugin->description && + FAILED(StringCchLength(plugin->description, + KMM_MAXCCH_DESC, &cch))) || + FAILED(StringCchLength(plugin->name, KMM_MAXCCH_NAME, &cch))) + { + return KHM_ERROR_INVALID_PARAM; + } + + /* note that we are retaining the length of the plugin name in + chars in cch */ + cch ++; + +#define CKRV if(KHM_FAILED(rv)) goto _exit + + rv = kmm_get_plugin_config(plugin->name, + config_flags | KHM_FLAG_CREATE, &csp_plugin); + CKRV; + + /* should fail if the module key doesn't exist */ + rv = kmm_get_module_config(plugin->module, config_flags, &csp_module); + CKRV; + + /*TODO: Make sure that the module registration is in the same + config store as the one in which the plugin is going to be + registered */ + + rv = khc_write_string(csp_plugin, L"Module", plugin->module); + CKRV; + if(plugin->description) { + rv = khc_write_string(csp_plugin, L"Description", plugin->description); + CKRV; + } + + if(plugin->dependencies) { + rv = khc_write_multi_string(csp_plugin, L"Dependencies", + plugin->dependencies); + CKRV; + } + + rv = khc_write_int32(csp_plugin, L"Type", plugin->type); + CKRV; + rv = khc_write_int32(csp_plugin, L"Disabled", + !!(plugin->flags & KMM_PLUGIN_FLAG_DISABLED)); + CKRV; + + { + khm_size cb = 0; + wchar_t * pl = NULL; + size_t scb = 0; + + rv = khc_read_multi_string(csp_module, L"PluginList", NULL, &cb); + if(rv != KHM_ERROR_TOO_LONG) { + if (rv == KHM_ERROR_NOT_FOUND) { + + scb = cb = (cch + 1) * sizeof(wchar_t); + pl = PMALLOC(cb); + multi_string_init(pl, cb); + rv = KHM_ERROR_SUCCESS; + + goto add_plugin_to_list; + + } else { + goto _exit; + } + } + + cb += cch * sizeof(wchar_t); + scb = cb; + + pl = PMALLOC(cb); + + rv = khc_read_multi_string(csp_module, L"PluginList", pl, &cb); + if(KHM_FAILED(rv)) { + if(pl) + PFREE(pl); + goto _exit; + } + + add_plugin_to_list: + + if(!multi_string_find(pl, plugin->name, 0)) { + multi_string_append(pl, &scb, plugin->name); + rv = khc_write_multi_string(csp_module, L"PluginList", pl); + } + + PFREE(pl); + CKRV; + } + +#undef CKRV + +_exit: + if(csp_plugin) + khc_close_space(csp_plugin); + if(csp_module) + khc_close_space(csp_module); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_register_module(kmm_module_reg * module, khm_int32 config_flags) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_module = NULL; + size_t cch; + int i; + + if((module == NULL) || + FAILED(StringCchLength(module->name, KMM_MAXCCH_NAME, &cch)) || + (module->description && + FAILED(StringCchLength(module->description, + KMM_MAXCCH_DESC, &cch))) || + FAILED(StringCchLength(module->path, MAX_PATH, &cch)) || + (module->n_plugins > 0 && module->plugin_reg_info == NULL)) { + return KHM_ERROR_INVALID_PARAM; + } + +#define CKRV if(KHM_FAILED(rv)) goto _exit + + rv = kmm_get_module_config(module->name, config_flags | KHM_FLAG_CREATE, + &csp_module); + CKRV; + + rv = khc_write_string(csp_module, L"ImagePath", module->path); + CKRV; + + rv = khc_write_int32(csp_module, L"Disabled", 0); + CKRV; + + /* FileVersion and ProductVersion will be set when the module + is loaded for the first time */ + + for(i=0; i<module->n_plugins; i++) { + rv = kmm_register_plugin(&(module->plugin_reg_info[i]), config_flags); + CKRV; + } + +#undef CKRV +_exit: + if(csp_module) + khc_close_space(csp_module); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_unregister_plugin(wchar_t * plugin, khm_int32 config_flags) +{ + khm_handle csp_plugin = NULL; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kmm_get_plugin_config(plugin, config_flags, &csp_plugin); + + if (KHM_FAILED(rv)) + goto _cleanup; + + rv = khc_remove_space(csp_plugin); + + _cleanup: + + if (csp_plugin) + khc_close_space(csp_plugin); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +kmm_unregister_module(wchar_t * module, khm_int32 config_flags) +{ + khm_handle csp_module = NULL; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kmm_get_module_config(module, config_flags, &csp_module); + + if (KHM_FAILED(rv)) + goto _cleanup; + + rv = khc_remove_space(csp_module); + + _cleanup: + if (csp_module) + khc_close_space(csp_module); + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/kmm/kmm_registrar.c b/krb5-1-6/src/windows/identity/kmm/kmm_registrar.c new file mode 100644 index 000000000..75f3b782a --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmm_registrar.c @@ -0,0 +1,1034 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmminternal.h> +#ifdef DEBUG +#include<assert.h> +#endif + +static LONG pending_modules = 0; +static LONG pending_plugins = 0; +static LONG startup_signal = 0; +static BOOL load_done = FALSE; + +void +kmmint_check_completion(void) { + if (pending_modules == 0 && + pending_plugins == 0 && + InterlockedIncrement(&startup_signal) == 1) { + + load_done = TRUE; + + /* TODO: check for orphaned plugins */ + + kmq_post_message(KMSG_KMM, KMSG_KMM_I_DONE, 0, 0); + } +} + +void +kmmint_add_to_module_queue(void) { + InterlockedIncrement(&pending_modules); +} + +void +kmmint_remove_from_module_queue(void) { + + InterlockedDecrement(&pending_modules); + + kmmint_check_completion(); +} + +void +kmmint_add_to_plugin_queue(kmm_plugin_i * plugin) { + EnterCriticalSection(&cs_kmm); + if (!(plugin->flags & KMM_PLUGIN_FLAG_IN_QUEUE)) { + InterlockedIncrement(&pending_plugins); + plugin->flags |= KMM_PLUGIN_FLAG_IN_QUEUE; + } + LeaveCriticalSection(&cs_kmm); +} + +void +kmmint_remove_from_plugin_queue(kmm_plugin_i * plugin) { + EnterCriticalSection(&cs_kmm); + + if (plugin->flags & KMM_PLUGIN_FLAG_IN_QUEUE) { + InterlockedDecrement(&pending_plugins); + plugin->flags &= ~KMM_PLUGIN_FLAG_IN_QUEUE; + } + + LeaveCriticalSection(&cs_kmm); + kmmint_check_completion(); +} + +KHMEXP khm_boolean KHMAPI +kmm_load_pending(void) { + return !load_done; +} + +/*! \internal + \brief Message handler for the registrar thread. */ +khm_boolean KHMAPI kmmint_reg_cb(khm_int32 msg_type, + khm_int32 msg_sub_type, + khm_ui_4 uparam, + void *vparam) +{ + /* we should only be getting <KMSG_KMM,KMSG_KMM_I_REG> anyway */ + if(msg_type != KMSG_KMM || msg_sub_type != KMSG_KMM_I_REG) + return FALSE; + + switch(uparam) { + case KMM_REG_INIT_MODULE: + kmmint_init_module((kmm_module_i *) vparam); + kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam)); + break; + + case KMM_REG_EXIT_MODULE: + kmmint_exit_module((kmm_module_i *) vparam); + kmm_release_module(kmm_handle_from_module((kmm_module_i *) vparam)); + break; + + case KMM_REG_INIT_PLUGIN: + kmmint_init_plugin((kmm_plugin_i *) vparam); + kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam)); + break; + + case KMM_REG_EXIT_PLUGIN: + kmmint_exit_plugin((kmm_plugin_i *) vparam); + kmm_release_plugin(kmm_handle_from_plugin((kmm_plugin_i *) vparam)); + break; + } + return TRUE; +} + +/*! \internal + \brief The registrar thread. + + The only thing this function does is to dispatch messages to the + callback routine ( kmmint_reg_cb() ) */ +DWORD WINAPI kmmint_registrar(LPVOID lpParameter) +{ + + PDESCTHREAD(L"KMM Registrar", L"KMM"); + + tid_registrar = GetCurrentThreadId(); + + kmq_subscribe(KMSG_KMM, kmmint_reg_cb); + kmq_subscribe(KMSG_SYSTEM, kmmint_reg_cb); + + SetEvent(evt_startup); + + while(KHM_SUCCEEDED(kmq_dispatch(INFINITE))); + + kmq_unsubscribe(KMSG_KMM, kmmint_reg_cb); + kmq_unsubscribe(KMSG_SYSTEM, kmmint_reg_cb); + + ExitThread(0); +} + +/*! \internal + \brief Manages a plugin message thread. + + Each plugin gets its own plugin thread which is used to dispatch + messages to the plugin. This acts as the thread function for the + plugin thread.*/ +DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter) +{ + DWORD rv = 0; + kmm_plugin_i * p = (kmm_plugin_i *) lpParameter; + + PDESCTHREAD(p->p.name, L"KMM"); + + _begin_task(0); + _report_mr1(KHERR_NONE, MSG_PB_START, _cstr(p->p.name)); + _describe(); + + TlsSetValue(tls_kmm, (LPVOID) p); + + kmm_hold_plugin(kmm_handle_from_plugin(p)); + + p->tid_thread = GetCurrentThreadId(); + + rv = (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_INIT, + 0, (void *) &(p->p)); + _report_mr1(KHERR_INFO, MSG_PB_INIT_RV, _int32(rv)); + + /* if it fails to initialize, we exit the plugin */ + if(KHM_FAILED(rv)) { + + kherr_report(KHERR_ERROR, + (wchar_t *) MSG_PB_INIT_FAIL_S, + (wchar_t *) KHERR_FACILITY, + NULL, + (wchar_t *) MSG_PB_INIT_FAIL, + (wchar_t *) MSG_PB_INIT_FAIL_G, + KHERR_FACILITY_ID, + KHERR_SUGGEST_NONE, + _cstr(p->p.name), + _cstr(p->p.description), + _cstr(p->module->path), + _cstr(p->module->support), + KHERR_RF_MSG_SHORT_DESC | + KHERR_RF_MSG_LONG_DESC | + KHERR_RF_MSG_SUGGEST +#ifdef _WIN32 + ,KHERR_HMODULE +#endif + ); + _resolve(); + + /* exit the plugin first. Otherwise it may not uninitialize correctly */ + (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); + + kmmint_remove_from_plugin_queue(p); + rv = 1; + _end_task(); + + p->state = KMM_PLUGIN_STATE_FAIL_INIT; + goto _exit; + } + + /* subscribe to default message classes by plugin type */ + if(p->p.type == KHM_PITYPE_CRED) { + kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); + kmq_subscribe(KMSG_KCDB, p->p.msg_proc); + kmq_subscribe(KMSG_CRED, p->p.msg_proc); + } else if(p->p.type == KHM_PITYPE_IDENT) { + khm_handle h = NULL; + + kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); + kmq_subscribe(KMSG_KCDB, p->p.msg_proc); + + kmq_create_subscription(p->p.msg_proc, &h); + kcdb_identity_set_provider(h); + /* kcdb deletes the subscription when it's done with it */ + } else if(p->p.type == KHM_PITYPE_CONFIG) { + /*TODO: subscribe to configuration provider messages here */ + } + + p->state = KMM_PLUGIN_STATE_RUNNING; + + _report_mr0(KHERR_INFO, MSG_PB_INIT_DONE); + + _end_task(); + + /* if there were any plugins that were waiting for this one to + start, we should start them too */ + EnterCriticalSection(&cs_kmm); + do { + kmm_plugin_i * pd; + int i; + + for(i=0; i < p->n_dependants; i++) { + pd = p->dependants[i]; + + pd->n_unresolved--; + + if(pd->n_unresolved == 0) { + kmmint_add_to_plugin_queue(pd); + kmm_hold_plugin(kmm_handle_from_plugin(pd)); + kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_PLUGIN, (void *) pd); + } + } + } while(FALSE); + LeaveCriticalSection(&cs_kmm); + + kmmint_remove_from_plugin_queue(p); + + /* main message loop */ + while(KHM_SUCCEEDED(kmq_dispatch(INFINITE))); + + /* unsubscribe from default message classes by plugin type */ + if(p->p.type == KHM_PITYPE_CRED) { + kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); + kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); + kmq_unsubscribe(KMSG_CRED, p->p.msg_proc); + } else if (p->p.type == KHM_PITYPE_IDENT) { + kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); + kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); + kcdb_identity_set_provider(NULL); + } else if(p->p.type == KHM_PITYPE_CONFIG) { + /*TODO: unsubscribe from configuration provider messages here */ + } + + p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); + + _exit: + if (p->state >= 0) + p->state = KMM_PLUGIN_STATE_EXITED; + + /* the following call will automatically release the plugin */ + kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, + KMM_REG_EXIT_PLUGIN, (void *) p); + + TlsSetValue(tls_kmm, (LPVOID) 0); + + ExitThread(rv); +} + +/*! \internal + \brief Initialize a plugin + + \note If kmmint_init_plugin() is called on a plugin, then kmmint_exit_plugin() + \b must be called for the plugin. + + \note Should only be called from the context of the registrar thread */ +void kmmint_init_plugin(kmm_plugin_i * p) { + DWORD dummy; + khm_handle csp_plugin = NULL; + khm_handle csp_plugins = NULL; + khm_int32 t; + + /* the following will be undone in kmmint_exit_plugin() */ + kmm_hold_plugin(kmm_handle_from_plugin(p)); + + EnterCriticalSection(&cs_kmm); + if(p->state != KMM_PLUGIN_STATE_REG && + p->state != KMM_PLUGIN_STATE_HOLD) + { + LeaveCriticalSection(&cs_kmm); + goto _exit; + } + + _begin_task(0); + _report_mr1(KHERR_NONE, MSG_IP_TASK_DESC, _cstr(p->p.name)); + _describe(); + + if(p->state == KMM_PLUGIN_STATE_HOLD) { + /* if this plugin was held, then we already had a hold + from the initial attempt to start the plugin. Undo + the hold we did a few lines earlier. */ + kmm_release_plugin(kmm_handle_from_plugin(p)); + + /* same for the plugin count for the module. */ +#ifdef DEBUG + assert(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT); +#endif + p->module->plugin_count--; + p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT; + } + + p->state = KMM_PLUGIN_STATE_PREINIT; + + kmmint_delist_plugin(p); + kmmint_list_plugin(p); + + LeaveCriticalSection(&cs_kmm); + + if(KHM_FAILED(kmm_get_plugins_config(0, &csp_plugins))) { + _report_mr0(KHERR_ERROR, MSG_IP_GET_CONFIG); + + p->state = KMM_PLUGIN_STATE_FAIL_UNKNOWN; + goto _exit; + } + + if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) { + if(KHM_FAILED(kmm_register_plugin(&(p->p), 0))) { + _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED); + + p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED; + goto _exit; + } + + if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) { + _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED); + + p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED; + goto _exit; + } + } + + if (KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"Disabled", &t)) && t) { + p->flags |= KMM_PLUGIN_FLAG_DISABLED; + p->state = KMM_PLUGIN_STATE_FAIL_DISABLED; + goto _exit; + } + +#if 0 + /*TODO: check the failure count and act accordingly */ + if(KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"FailureCount", &t)) && (t > 0)) { + } +#endif + + EnterCriticalSection(&cs_kmm); + + p->n_depends = 0; + p->n_unresolved = 0; + + do { + wchar_t * deps = NULL; + wchar_t * d; + khm_size sz = 0; + + if(khc_read_multi_string(csp_plugin, L"Dependencies", + NULL, &sz) != KHM_ERROR_TOO_LONG) + break; + + deps = PMALLOC(sz); + if(KHM_FAILED(khc_read_multi_string(csp_plugin, L"Dependencies", + deps, &sz))) { + if(deps) + PFREE(deps); + break; + } + + for(d = deps; d && *d; d = multi_string_next(d)) { + kmm_plugin_i * pd; + int i; + + pd = kmmint_get_plugin_i(d); + + if(pd->state == KMM_PLUGIN_STATE_NONE) { + /* the dependant was not previously known */ + pd->state = KMM_PLUGIN_STATE_PLACEHOLDER; + } + + for(i=0; i < pd->n_dependants; i++) { + if(pd->dependants[i] == p) + break; + } + + if(i >= pd->n_dependants) { + if( pd->n_dependants >= KMM_MAX_DEPENDANTS ) { + /*TODO: handle this gracefully */ + RaiseException(1, EXCEPTION_NONCONTINUABLE, 0, NULL); + } + + /* released in kmmint_free_plugin() */ + kmm_hold_plugin(kmm_handle_from_plugin(p)); + pd->dependants[pd->n_dependants] = p; + pd->n_dependants++; + } + + p->n_depends++; + + if(pd->state != KMM_PLUGIN_STATE_RUNNING) { + p->n_unresolved++; + } + } + + if(p->n_unresolved > 0) { + p->state = KMM_PLUGIN_STATE_HOLD; + } + + PFREE(deps); + + } while(FALSE); + +#ifdef DEBUG + assert(!(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT)); +#endif + p->flags |= KMM_PLUGIN_FLAG_IN_MODCOUNT; + p->module->plugin_count++; + + LeaveCriticalSection(&cs_kmm); + + if(p->state == KMM_PLUGIN_STATE_HOLD) { + _report_mr1(KHERR_INFO, MSG_IP_HOLD, _dupstr(p->p.name)); + + goto _exit_post; + } + + kmmint_add_to_plugin_queue(p); + + p->ht_thread = CreateThread(NULL, + 0, + kmmint_plugin_broker, + (LPVOID) p, + CREATE_SUSPENDED, + &dummy); + + p->state = KMM_PLUGIN_STATE_INIT; + + ResumeThread(p->ht_thread); + +_exit_post: + if(csp_plugin != NULL) + khc_close_space(csp_plugin); + + if(csp_plugins != NULL) + khc_close_space(csp_plugins); + + _report_mr2(KHERR_INFO, MSG_IP_STATE, + _dupstr(p->p.name), _int32(p->state)); + + _end_task(); + + return; + + /* jump here if an error condition happens before the plugin + broker thread starts and the plugin should be unloaded */ + +_exit: + if(csp_plugin != NULL) + khc_close_space(csp_plugin); + if(csp_plugins != NULL) + khc_close_space(csp_plugins); + + _report_mr2(KHERR_WARNING, MSG_IP_EXITING, + _dupstr(p->p.name), _int32(p->state)); + _end_task(); + + +#ifdef ASYNC_PLUGIN_UNLOAD_ON_FAILURE + + kmm_hold_plugin(kmm_handle_from_plugin(p)); + + kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p); + +#else + + kmmint_exit_plugin(p); + +#endif +} + +/*! \internal + \brief Uninitialize a plugin + + In addition to terminating the thread, and removing p from the + linked list and hashtable, it also frees up p. + + \note Should only be called from the context of the registrar thread. */ +void kmmint_exit_plugin(kmm_plugin_i * p) { + int np; + khm_boolean release_plugin = TRUE; + + if(p->state == KMM_PLUGIN_STATE_RUNNING || + p->state == KMM_PLUGIN_STATE_INIT) { + + kmq_post_thread_quit_message(p->tid_thread, 0, NULL); + /* when we post the quit message to the plugin thread, the plugin + broker terminates the plugin and posts a EXIT_PLUGIN message, + which calls this function again. We just exit here because + the EXIT_PLUGIN message will end up calling us again momentarily */ + return; + + } + + if(p->ht_thread) { + /* wait for the thread to terminate */ + WaitForSingleObject(p->ht_thread, INFINITE); + p->ht_thread = NULL; + } + + EnterCriticalSection(&cs_kmm); + + /* undo reference count done in kmmint_init_plugin() */ + if(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT) { + + np = --(p->module->plugin_count); + p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT; + + } else { + /* the plugin was not included in the module's plugin_count. + We can't base a decision to unload the module based on this + plugin exiting. */ + np = TRUE; + } + + /* The plugin is in an error state. We need to keep the plugin + record intact so that the failure information is kept around. + Also, we shouldn't release the plugin if it appears that + kmmint_init_plugin() was never called for it. */ + if (p->state < KMM_PLUGIN_STATE_HOLD) { + release_plugin = FALSE; + } + + LeaveCriticalSection(&cs_kmm); + + if(!np) { + /* if this is the last plugin to exit, then notify the + registrar that the module should be removed as well */ + kmm_hold_module(kmm_handle_from_module(p->module)); + kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_MODULE, (void *) p->module); + } + + /* release the hold obtained in kmmint_init_plugin() */ + if (release_plugin) + kmm_release_plugin(kmm_handle_from_plugin(p)); +} + +/*! \internal + \brief Initialize a module + + \a m is not in the linked list yet. + + \note Should only be called from the context of the registrar thread. */ +void kmmint_init_module(kmm_module_i * m) { + HMODULE hm; + init_module_t p_init_module; + kmm_plugin_i * pi; + khm_int32 rv; + khm_handle csp_mod = NULL; + khm_handle csp_mods = NULL; + khm_size sz; + khm_int32 i; + + /* error condition handling */ + BOOL exit_module = FALSE; + BOOL release_module = TRUE; + BOOL record_failure = FALSE; + + /* failure handling */ + khm_int32 max_fail_count = 0; + khm_int64 fail_reset_time = 0; + + _begin_task(0); + _report_mr1(KHERR_NONE, MSG_INIT_MODULE, _cstr(m->name)); + _describe(); + + kmm_hold_module(kmm_handle_from_module(m)); + + /* If the module is not in the pre-init state, we can't + initialize it. */ + if(m->state != KMM_MODULE_STATE_PREINIT) { + _report_mr1(KHERR_INFO, MSG_IM_NOT_PREINIT, _int32(m->state)); + goto _exit; + } + + if(KHM_FAILED(kmm_get_modules_config(0, &csp_mods))) { + _report_mr0(KHERR_ERROR, MSG_IM_GET_CONFIG); + _location(L"kmm_get_modules_config()"); + + m->state = KMM_MODULE_STATE_FAIL_UNKNOWN; + goto _exit; + } + + khc_read_int32(csp_mods, L"ModuleMaxFailureCount", &max_fail_count); + khc_read_int64(csp_mods, L"ModuleFailureCountResetTime", &fail_reset_time); + + if(KHM_FAILED(kmm_get_module_config(m->name, 0, &csp_mod))) { + _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED); + + m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED; + goto _exit; + } + + if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Disabled", &i)) && i) { + _report_mr0(KHERR_INFO, MSG_IM_DISABLED); + + m->state = KMM_MODULE_STATE_FAIL_DISABLED; + goto _exit; + } + + if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"NoUnload", &i)) && i) { + m->flags |= KMM_MODULE_FLAG_NOUNLOAD; + } + + if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"FailureCount", &i))) { + khm_int64 tm; + khm_int64 ct; + FILETIME fct; + khm_int32 last_reason = 0; + + /* reset the failure count if the failure count reset time + period has elapsed */ + tm = 0; + khc_read_int64(csp_mod, L"FailureTime", &tm); + GetSystemTimeAsFileTime(&fct); + + ct = (FtToInt(&fct) - tm) / 10000000i64; + + if(tm > 0 && + ct > fail_reset_time) { + i = 0; + khc_write_int32(csp_mod, L"FailureCount", 0); + khc_write_int64(csp_mod, L"FailureTime", 0); + } + + khc_read_int32(csp_mod, L"FailureReason", &last_reason); + + /* did we exceed the max failure count? However, we ignore + the max failure count if the reason why it didn't load the + last time was because the module wasn't found. */ + if(i > max_fail_count && + last_reason != KMM_MODULE_STATE_FAIL_NOT_FOUND) { + /* failed too many times */ + _report_mr0(KHERR_INFO, MSG_IM_MAX_FAIL); + + m->state = KMM_MODULE_STATE_FAIL_MAX_FAILURE; + goto _exit; + } + } + + if(khc_read_string(csp_mod, KMM_VALNAME_IMAGEPATH, NULL, &sz) == + KHM_ERROR_TOO_LONG) { + if(m->path) + PFREE(m->path); + m->path = PMALLOC(sz); + khc_read_string(csp_mod, KMM_VALNAME_IMAGEPATH, m->path, &sz); + } else { + /* + * If there is no image path, then the module has not been + * installed. Do not report an error and bother the user. + * _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED); + */ + + m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED; + goto _exit; + } + + rv = kmmint_read_module_info(m); + + if (KHM_FAILED(rv)) { + if (rv == KHM_ERROR_INCOMPATIBLE) { + _report_mr0(KHERR_ERROR, MSG_IM_INCOMPATIBLE); + + m->state = KMM_MODULE_STATE_FAIL_INCOMPAT; + } else if (rv == KHM_ERROR_NOT_FOUND) { + _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path)); + + m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND; + } else { + _report_mr0(KHERR_ERROR, MSG_IM_INVALID_MODULE); + + m->state = KMM_MODULE_STATE_FAIL_INV_MODULE; + } + goto _exit; + } + + /* check again */ + if(m->state != KMM_MODULE_STATE_PREINIT) { + _report_mr0(KHERR_ERROR, MSG_IM_NOT_PREINIT); + + goto _exit; + } + + /* from this point on, we must record any failure codes */ + record_failure = TRUE; + + hm = LoadLibrary(m->path); + if(!hm) { + m->h_module = NULL; + m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND; + + _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path)); + + goto _exit; + } + + /* from this point on, we need to discard the module through + exit_module */ + ResetEvent(evt_exit); + + kmm_active_modules++; + + release_module = FALSE; + exit_module = TRUE; + + m->flags |= KMM_MODULE_FLAG_LOADED; + m->h_module = hm; + + /* TODO: check signatures */ + + p_init_module = (init_module_t) GetProcAddress(hm, EXP_INIT_MODULE); + + if(!p_init_module) { + _report_mr1(KHERR_ERROR, MSG_IM_NO_ENTRY, _cstr(EXP_INIT_MODULE)); + + m->state = KMM_MODULE_STATE_FAIL_INVALID; + goto _exit; + } + + m->state = KMM_MODULE_STATE_INIT; + + /* call init_module() */ + rv = (*p_init_module)(kmm_handle_from_module(m)); + + m->flags |= KMM_MODULE_FLAG_INITP; + + if(KHM_FAILED(rv)) { + _report_mr1(KHERR_ERROR, MSG_IM_INIT_FAIL, _int32(rv)); + + m->state = KMM_MODULE_STATE_FAIL_LOAD; + goto _exit; + } + + if(!m->plugins) { + _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS); + + m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS; + record_failure = FALSE; + goto _exit; + } + + m->state = KMM_MODULE_STATE_INITPLUG; + + do { + LPOP(&(m->plugins), &pi); + if(pi) { + pi->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST; + kmmint_init_plugin(pi); + + /* release the hold obtained in kmm_provide_plugin() */ + kmm_release_plugin(kmm_handle_from_plugin(pi)); + } + } while(pi); + + if(!m->plugin_count) { + /* We don't want to report this case. This usually means that + the plugins that were provided by the module were + disabled. */ +#ifdef REPORT_EMPTY_MODULES + _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS); + + m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS; +#endif + record_failure = FALSE; + goto _exit; + } + + m->state = KMM_MODULE_STATE_RUNNING; + + exit_module = FALSE; + record_failure = FALSE; + + _exit: + if(csp_mod) { + if(record_failure) { + FILETIME fct; + + i = 0; + khc_read_int32(csp_mod, L"FailureCount", &i); + i++; + khc_write_int32(csp_mod, L"FailureCount", i); + + if(i==1) { /* first fault */ + GetSystemTimeAsFileTime(&fct); + khc_write_int64(csp_mod, L"FailureTime", FtToInt(&fct)); + } + + khc_write_int32(csp_mod, L"FailureReason", m->state); + } + khc_close_space(csp_mod); + } + + if(csp_mods) + khc_close_space(csp_mods); + + _report_mr2(KHERR_INFO, MSG_IM_MOD_STATE, + _dupstr(m->name), _int32(m->state)); + + kmmint_remove_from_module_queue(); + + /* if something went wrong after init_module was called on the + module code, we need to call exit_module */ + if(exit_module) + kmmint_exit_module(m); + + if(release_module) + kmm_release_module(kmm_handle_from_module(m)); + + if (kherr_is_error()) { + kherr_context * c; + kherr_event * err_e = NULL; + kherr_event * warn_e = NULL; + kherr_event * e; + + c = kherr_peek_context(); + err_e = kherr_get_err_event(c); + for(e = kherr_get_first_event(c); + e; + e = kherr_get_next_event(e)) { + if (e != err_e && + e->severity == KHERR_WARNING) { + warn_e = e; + break; + } + } + + kherr_evaluate_event(err_e); + if (warn_e) + kherr_evaluate_event(warn_e); + + kherr_clear_error(); + + e = kherr_report(KHERR_ERROR, + (wchar_t *) MSG_IMERR_TITLE, + KHERR_FACILITY, + NULL, + err_e->long_desc, + ((warn_e)? (wchar_t *)MSG_IMERR_SUGGEST: NULL), + KHERR_FACILITY_ID, + KHERR_SUGGEST_NONE, + _cstr(m->name), + ((warn_e)? _cstr(warn_e->long_desc):_vnull()), + _vnull(),_vnull(), + KHERR_RF_MSG_SHORT_DESC | + ((warn_e)? KHERR_RF_MSG_SUGGEST: 0), + KHERR_HMODULE); + + kherr_evaluate_event(e); + + kherr_release_context(c); + } + + _end_task(); +} + + +/*! \internal + \brief Uninitializes a module + + \note Should only be called from the context of the registrar + thread */ +void kmmint_exit_module(kmm_module_i * m) { + kmm_plugin_i * p; + + /* Exiting a module happens in two stages. + + If the module state is running (there are active plugins) then + those plugins must be exited. This has to be done from the + plugin threads. The signal for the plugins to exit must be + issued from the registrar. Therefore, we post messages to the + registrar for each plugin we want to remove and exit + kmmint_exit_module(). + + When the last plugin is exited, the plugin management code + automatically signalls the registrar to remove the module. + kmmint_exit_module() gets called again. This is the second + stage, where we call exit_module() for the module and start + unloading everything. + */ + + EnterCriticalSection(&cs_kmm); + + /* get rid of any dangling uninitialized plugins */ + LPOP(&(m->plugins), &p); + while(p) { + p->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST; + kmmint_exit_plugin(p); + + /* release hold from kmm_provide_plugin() */ + kmm_release_plugin(kmm_handle_from_plugin(p)); + + LPOP(&(m->plugins), &p); + } + + if(m->state == KMM_MODULE_STATE_RUNNING) { + int np = 0; + + m->state = KMM_MODULE_STATE_EXITPLUG; + + p = kmm_listed_plugins; + + while(p) { + if(p->module == m && + (p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT)) { + + kmm_hold_plugin(kmm_handle_from_plugin(p)); + kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, + KMM_REG_EXIT_PLUGIN, (void *) p); + np++; + + } + + p = LNEXT(p); + } + +#ifdef DEBUG + assert(np == m->plugin_count); +#endif + + if(np > 0) { + /* we have to go back and wait for the plugins to exit. + when the last plugin exits, it automatically posts + EXIT_MODULE. We can pick up from there when this + happens. */ + LeaveCriticalSection(&cs_kmm); + return; + } + + } else { + +#ifdef DEBUG + assert(m->plugin_count == 0 || + m->state == KMM_MODULE_STATE_EXITPLUG); +#endif + + /* if there are still plug-ins waiting to be unloaded, then we + have to go back and wait for them to finish. Once they are + done, kmmint_exit_module() will get called again. */ + if (m->plugin_count > 0) { + LeaveCriticalSection(&cs_kmm); + return; + } + } + + if(m->flags & KMM_MODULE_FLAG_INITP) { + exit_module_t p_exit_module; + + if(m->state > 0) + m->state = KMM_MODULE_STATE_EXIT; + + p_exit_module = + (exit_module_t) GetProcAddress(m->h_module, + EXP_EXIT_MODULE); + if(p_exit_module) { + LeaveCriticalSection(&cs_kmm); + (*p_exit_module)(kmm_handle_from_module(m)); + EnterCriticalSection(&cs_kmm); + } + } + + if(m->state > 0) + m->state = KMM_MODULE_STATE_EXITED; + + LeaveCriticalSection(&cs_kmm); + + if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) && + m->h_module) { + FreeLibrary(m->h_module); + } + + if(!(m->flags & KMM_MODULE_FLAG_NOUNLOAD) && + m->h_resource && (m->h_resource != m->h_module)) { + FreeLibrary(m->h_resource); + } + + m->h_module = NULL; + m->h_resource = NULL; + + if (m->flags & KMM_MODULE_FLAG_LOADED) { +#ifdef DEBUG + assert(kmm_active_modules > 0); +#endif + kmm_active_modules--; + } + + m->flags = 0; + + /* release the hold obtained in kmmint_init_module() */ + kmm_release_module(kmm_handle_from_module(m)); + + /* Last but not least, now see if there are any modules left that + are running. If not, we can safely signal an exit. */ + if (kmm_active_modules == 0) { + SetEvent(evt_exit); + } +} diff --git a/krb5-1-6/src/windows/identity/kmm/kmmconfig.csv b/krb5-1-6/src/windows/identity/kmm/kmmconfig.csv new file mode 100644 index 000000000..32c334b26 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmmconfig.csv @@ -0,0 +1,47 @@ +Name,Type,Value,Description +PluginManager,KC_SPACE,0,Plugin Manager Configuration + Plugins,KC_SPACE,0,Plugin Specific configuration + PluginMaxFailureCount,KC_INT32,3,Maximum number of failure counts before plugin is disabled + PluginFailureCountResetTime,KC_INT64,36000,Time after first failure at which the failure count is reset + _Schema,KC_SPACE,0,Plugin schema + Module,KC_STRING,<module name>,The name of the module that registered this plugin + Description,KC_STRING,<Description>,Description of the plugin + Dependencies,KC_STRING,<Dependencies>,Multi string of plugin names of plugins that this plugin depends on + Type,KC_INT32,0,The type of the plugin +# Flags,KC_INT32,0,Flags (Deprecated) + Disabled,KC_INT32,0,Plug-in is disabled (Boolean) + NoUnload,KC_INT32,0,Do not unload the plugin (Boolean) + FailureCount,KC_INT32,0,Number of failed loads + FailureTime,KC_INT64,0,FILETIME of first failure + FailureReason,KC_INT32,0,Reason for first failure. One of the plugin status values. + Parameters,KC_SPACE,0,Plugin parameters. The schema beyond this is plugin dependent. + Parameters,KC_ENDSPACE,0, + _Schema,KC_ENDSPACE,0, + Plugins,KC_ENDSPACE,0, + Modules,KC_SPACE,0,Module Specific configuration + ModuleMaxFailureCount,KC_INT32,3,Maximum number of failure counts before module is disabled + ModuleFailureCountResetTime,KC_INT64,72000,Time after first failure at which the failure count is reset + _Schema,KC_SPACE,0,Module schema + ImagePath,KC_STRING,<Path to the library binary>,Path to the DLL (including DLL name) +# Flags,KC_INT32,0,Flags (Deprecated) + Disabled,KC_INT32,0,Module is disabled (Boolean) + FailureCount,KC_INT32,0,Number of failed loads + FailureTime,KC_INT64,0,FILETIME of first failure + FailureReason,KC_INT32,0,Reason for last failure. One of the module status values. + PluginList,KC_STRING,<plugins>,List of plugins implemented in the module + _Schema,KC_ENDSPACE,0, +# The OpenAFS plug-in is installed separately. +# OpenAFS,KC_SPACE,0,OpenAFS Module +# ImagePath,KC_STRING,afscred.dll, +# PluginList,KC_STRING,AfsCred, +# OpenAFS,KC_ENDSPACE,0, +# MITKrb5,KC_SPACE,0,MIT Kerberos V +# ImagePath,KC_STRING,krb5cred.dll, +# PluginList,KC_STRING,Krb5Cred, +# MITKrb5,KC_ENDSPACE,0, +# MITKrb4,KC_SPACE,0,MIT Kerberos IV +# ImagePath,KC_STRING,krb4cred.dll, +# PluginList,KC_STRING,Krb4Cred, +# MITKrb4,KC_ENDSPACE,0, + Modules,KC_ENDSPACE,0, +PluginManager,KC_ENDSPACE,0, diff --git a/krb5-1-6/src/windows/identity/kmm/kmminternal.h b/krb5-1-6/src/windows/identity/kmm/kmminternal.h new file mode 100644 index 000000000..96f8ac24a --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmminternal.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KMMINTERNAL_H +#define __KHIMAIRA_KMMINTERNAL_H + +#define _NIMLIB_ + +#include<windows.h> +#include<shlwapi.h> +#include<strsafe.h> + +#define KHERR_FACILITY kmm_facility +#define KHERR_FACILITY_ID KHM_FACILITY_KMM +#define KHERR_HMODULE ((HMODULE) kmm_hInstance) +#include<kherr.h> + +#include<kmm.h> +#include<khmsgtypes.h> +#include<kherror.h> +#include<kplugin.h> + +#define NOEXPORT + +#include<utils.h> +#include<kconfig.h> +#include<kcreddb.h> +#include<kmm_msgs.h> + +struct kmm_plugin_i_t; /* forward dcl */ + +typedef struct kmm_module_i_t { + khm_int32 magic; + + wchar_t * name; + wchar_t * path; + wchar_t * description; + wchar_t * vendor; + wchar_t * support; + + khm_version file_version; + khm_version prod_version; + + HMODULE h_module; + + HMODULE h_resource; + WORD lcid_resource; + + khm_int32 flags; + khm_int32 state; + khm_int32 plugin_count; /* number of active plugins */ + + void * version_info; + + khm_int32 refcount; + + struct kmm_plugin_i_t * plugins; /* only used for registration */ + + LDCL(struct kmm_module_i_t); +} kmm_module_i; + +#define KMM_MODULE_MAGIC 0x482f4e88 + +#define kmm_is_module(m) ((m) && ((kmm_module_i *)m)->magic == KMM_MODULE_MAGIC) + +#define kmm_module_from_handle(m) ((kmm_module_i *) m) +#define kmm_handle_from_module(m) ((kmm_module) m) + +/* LoadLibrary succeeded for module */ +#define KMM_MODULE_FLAG_LOADED 0x00000001 + +/* init_module entry called */ +#define KMM_MODULE_FLAG_INITP 0x00000002 + +/* the resources have been loaded */ +#define KMM_MODULE_FLAG_RES_LOADED 0x00000008 + +/* the signature has been verified */ +#define KMM_MODULE_FLAG_SIG 0x00000010 + +/* the module is disabled by the user + (option specified in configuration) */ +#define KMM_MODULE_FLAG_DISABLED 0x00000400 + +/* the module should not be unloaded + (option specified in configuration)*/ +#define KMM_MODULE_FLAG_NOUNLOAD 0x00000800 + +/* the module has been removed from the active modules list. */ +#define KMM_MODULE_FLAG_INACTIVE 0x00001000 + +typedef struct kmm_plugin_i_t { + kmm_plugin_reg p; + + khm_int32 magic; + + kmm_module_i * module; + HANDLE ht_thread; + DWORD tid_thread; + + khm_int32 state; + khm_int32 flags; + + int refcount; + + int n_depends; + int n_unresolved; + struct kmm_plugin_i_t * dependants[KMM_MAX_DEPENDANTS]; + int n_dependants; + + LDCL(struct kmm_plugin_i_t); +} kmm_plugin_i; + +#define KMM_PLUGIN_MAGIC 0x320e8fb4 + +#define kmm_is_plugin(p) ((p) && ((kmm_plugin_i *) (p))->magic == KMM_PLUGIN_MAGIC) + +#define kmm_handle_from_plugin(p) ((kmm_plugin) p) +#define kmm_plugin_from_handle(ph) ((kmm_plugin_i *) ph) + +/* the plugin has already been marked for unload */ +#define KMM_PLUGIN_FLAG_UNLOAD 0x00000001 + +/* the plugin is in the kmm_listed_plugins list */ +#define KMM_PLUGIN_FLAG_IN_LIST 0x00000002 + +/* the plugin is in the module's plugin list */ +#define KMM_PLUGIN_FLAG_IN_MODLIST 0x00000004 + +/* the plugin has been included in the pending_plugins count. */ +#define KMM_PLUGIN_FLAG_IN_QUEUE 0x00000010 + +/* the plugin is included in the module's plugin count */ +#define KMM_PLUGIN_FLAG_IN_MODCOUNT 0x00000020 + +/* the plugin is disabled by the user + (option specified in configuration) */ +/* (this is defined in kmm.h) + + #define KMM_PLUGIN_FLAG_DISABLED 0x00000400 + +*/ + +enum kmm_registrar_uparam_t { + KMM_REG_INIT_MODULE, + KMM_REG_EXIT_MODULE, + KMM_REG_INIT_PLUGIN, + KMM_REG_EXIT_PLUGIN +}; + +extern kmm_module_i * kmm_all_modules; +extern khm_size kmm_active_modules; +extern kmm_plugin_i * kmm_listed_plugins; +extern HANDLE ht_registrar; +extern DWORD tid_registrar; +extern DWORD tls_kmm; + +extern hashtable * hash_plugins; +extern hashtable * hash_modules; + +extern CRITICAL_SECTION cs_kmm; +extern int ready; +extern HANDLE evt_startup; +extern HANDLE evt_exit; +extern const wchar_t * kmm_facility; + +extern HINSTANCE kmm_hInstance; + +extern kconf_schema schema_kmmconfig[]; + +/* Registrar */ + +khm_boolean KHMAPI +kmmint_reg_cb(khm_int32 msg_type, + khm_int32 msg_sub_type, + khm_ui_4 uparam, + void *vparam); + +DWORD WINAPI kmmint_registrar(LPVOID lpParameter); + +DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter); + +void kmmint_init_plugin(kmm_plugin_i * p); +void kmmint_exit_plugin(kmm_plugin_i * p); +void kmmint_init_module(kmm_module_i * m); +void kmmint_exit_module(kmm_module_i * m); + +/* Modules */ +kmm_module_i * +kmmint_get_module_i(wchar_t * name); + +kmm_module_i * +kmmint_find_module_i(wchar_t * name); + +void +kmmint_free_module(kmm_module_i * m); + +khm_int32 +kmmint_read_module_info(kmm_module_i * m); + +/* Plugins */ +kmm_plugin_i * +kmmint_get_plugin_i(wchar_t * name); + +kmm_plugin_i * +kmmint_find_plugin_i(wchar_t * name); + +void +kmmint_free_plugin(kmm_plugin_i * pi); + +void +kmmint_list_plugin(kmm_plugin_i * p); + +void +kmmint_delist_plugin(kmm_plugin_i * p); + +khm_boolean +kmmint_load_locale_lib(kmm_module_i * m, kmm_module_locale * l); + +#define KMM_CSNAME_ROOT L"PluginManager" +#define KMM_CSNAME_PLUGINS L"Plugins" +#define KMM_CSNAME_MODULES L"Modules" +#define KMM_VALNAME_LOADLIST L"LoadList" +#define KMM_VALNAME_IMAGEPATH L"ImagePath" + +void +kmmint_add_to_module_queue(void); + +void +kmmint_remove_from_module_queue(void); + +#define _WAIT_FOR_START \ + do { \ + if(ready) break; \ + WaitForSingleObject(evt_startup, INFINITE); \ + } while(0) + +#endif diff --git a/krb5-1-6/src/windows/identity/kmm/kmmmain.c b/krb5-1-6/src/windows/identity/kmm/kmmmain.c new file mode 100644 index 000000000..49384ccdb --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kmmmain.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmminternal.h> + +kmm_module_i * kmm_all_modules = NULL; +kmm_plugin_i * kmm_listed_plugins = NULL; + +HANDLE ht_registrar = NULL; +DWORD tid_registrar = 0; +DWORD tls_kmm = 0; + +#define KMM_HASH_SIZE 31 +hashtable * hash_plugins = NULL; +hashtable * hash_modules = NULL; + +CRITICAL_SECTION cs_kmm; +HANDLE evt_startup = NULL; +HANDLE evt_exit = NULL; +int ready = 0; + +HINSTANCE kmm_hInstance; +const wchar_t * kmm_facility = L"KMM"; + +KHMEXP void KHMAPI kmm_init(void) +{ + DWORD dummy; + + EnterCriticalSection(&cs_kmm); + kmm_all_modules = NULL; + kmm_listed_plugins = NULL; + + tls_kmm = TlsAlloc(); + + hash_plugins = hash_new_hashtable( + KMM_HASH_SIZE, + hash_string, + hash_string_comp, + NULL, + NULL); + + hash_modules = hash_new_hashtable( + KMM_HASH_SIZE, + hash_string, + hash_string_comp, + NULL, + NULL); + + ht_registrar = CreateThread( + NULL, + 0, + kmmint_registrar, + NULL, + 0, + &dummy); + + _WAIT_FOR_START; + + khc_load_schema(NULL, schema_kmmconfig); + + LeaveCriticalSection(&cs_kmm); +} + +KHMEXP void KHMAPI kmm_exit(void) +{ + kmm_module_i * m; + kmm_plugin_i * p; + + EnterCriticalSection(&cs_kmm); + + p = kmm_listed_plugins; + while(p) { + kmm_plugin_i * pn; + + pn = LNEXT(p); + /* plugins that were never resolved should be kicked off the + list. Flipping the refcount will do that if no other + references exist for the plugin. The plugins that were + waiting for unresolved dependencies will automatically get + freed when the placeholders and other plugins get freed. */ + if(p->state == KMM_PLUGIN_STATE_PLACEHOLDER) { + kmm_hold_plugin(kmm_handle_from_plugin(p)); + kmm_release_plugin(kmm_handle_from_plugin(p)); + } + + p = pn; + } + + m = kmm_all_modules; + while(m) { + kmm_unload_module(kmm_handle_from_module(m)); + m = LNEXT(m); + } + + LeaveCriticalSection(&cs_kmm); + WaitForSingleObject(evt_exit, INFINITE); + + kmq_send_thread_quit_message(tid_registrar, 0); + + EnterCriticalSection(&cs_kmm); + + hash_del_hashtable(hash_plugins); + hash_del_hashtable(hash_modules); + + LeaveCriticalSection(&cs_kmm); + + TlsFree(tls_kmm); + + tls_kmm = 0; +} + +void kmm_dll_init(void) +{ + InitializeCriticalSection(&cs_kmm); + evt_startup = CreateEvent(NULL, TRUE, FALSE, NULL); + evt_exit = CreateEvent(NULL, TRUE, TRUE, NULL); +} + +void kmm_dll_exit(void) +{ + DeleteCriticalSection(&cs_kmm); + if(evt_startup) + CloseHandle(evt_startup); + evt_startup = NULL; +} + +void +kmm_process_attach(HINSTANCE hinstDLL) { + kmm_hInstance = hinstDLL; + kmm_dll_init(); +} + +void +kmm_process_detach(void) { + kmm_dll_exit(); +} + diff --git a/krb5-1-6/src/windows/identity/kmm/kplugin.h b/krb5-1-6/src/windows/identity/kmm/kplugin.h new file mode 100644 index 000000000..a5b7a088a --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/kplugin.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KPLUGIN_H +#define __KHIMAIRA_KPLUGIN_H + +#include<kmm.h> +#include<kherror.h> + +/*! \addtogroup kmm +@{*/ +/*! \defgroup kplugin NetIDMgr Plugin Callbacks + +See the following related documentation pages for more information +about NetIDMgr plugins. + +These are prototypes of functions that must be implemented by a NetIDMgr +plugin. + +- \ref plugins +@{*/ + +/*! \brief Initialize the module + + This is the first callback function to be called in a module. + Perform all the required intialization when this is called. As + mentioned in \ref plugins, you should not attempt to call any + NetIDMgr API function from DLLMain or other initialization code + other than this one. + + You should use this call back to register the plugins that will be + implemented in this module and to notify the plugin manager of any + resource libraries that this module will use. + + Call: + - kmm_set_locale() : to set the notify the plugin manager of the + locale specifc resource libraries that are used by this module. + - kmm_provide_plugin() : to register each plugin that is + implemented in this module. + + This function is called in the context of the current user, from + the plug-in manager thread. This same thread is used by the + plug-in manager to load and initialize all the modules for a + session. + + The name of the callback must be init_module(). The calling + convention is KHMAPI, which is currently __stdcall. + + If this function does not register any plugins, the plugin manager + will immediately call exit_module() and unload the module even if + the init_module() function completes successfully. + + \return Return the following values to indicate whether the module + successfully initialized or not. + - KHM_ERROR_SUCCESS : Succeeded. The module manager will call + init_plugin() for each of the registered plugins for the + module. + - any other error code: Signals that the module did not + successfully initialize. The plugin manager will + immediately call exit_module() and then unload the module. + + \note This callback is required. +*/ +KHMEXP_EXP khm_int32 KHMAPI init_module(kmm_module h_module); + +/*! \brief Type for init_module() */ +typedef khm_int32 (KHMAPI *init_module_t)(kmm_module); + +#if defined(_WIN64) +#define EXP_INIT_MODULE "init_module" +#elif defined(_WIN32) +#define EXP_INIT_MODULE "_init_module@4" +#else +#error EXP_INIT_MODULE not defined for platform +#endif + +/*! \brief Plugin procedure + + This is the message processor for a plugin. See \ref pi_fw_pnm_p + for more information. + + Essentially, this is a message subscriber for KMQ messages. +*/ +KHMEXP_EXP khm_int32 KHMAPI _plugin_proc(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam); + +/*! \brief Type for init_plugin() */ +typedef kmq_callback_t _plugin_proc_t; + +/*! \brief Exit a module + + This is the last callback function that the NetIDMgr module + manager calls before unloading the module. When this function is + called, all of the plugins for the module have already been + stopped. However, any localization libraries that were loaded as + a result of init_module() calling kmm_set_locale_info() will still + be loaded. These localization libraries will be unloaded + immediately after this callback returns. + + Use this callback to perform any required cleanup tasks. However, + it is advisable that each plugin perform its own cleanup tasks, + since each plugin may be stopped independently of others. + + \return The return value of this function is ignored. + + \note This callback is not required. +*/ +KHMEXP_EXP khm_int32 KHMAPI exit_module(kmm_module h_module); + +/*! \brief Type for exit_module() */ +typedef khm_int32 (KHMAPI *exit_module_t)(kmm_module); + +#if defined(_WIN64) +#define EXP_EXIT_MODULE "exit_module" +#elif defined(_WIN32) +#define EXP_EXIT_MODULE "_exit_module@4" +#else +#error EXP_EXIT_MODULE not defined for platform +#endif + +/*@}*/ +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/kmm/lang/kmm_msgs.mc b/krb5-1-6/src/windows/identity/kmm/lang/kmm_msgs.mc new file mode 100644 index 000000000..898ffa2fc --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmm/lang/kmm_msgs.mc @@ -0,0 +1,259 @@ +; // ** kmm_msgs.mc + +; /* Since .mc files can contain strings from any language, we define +; all our messages in one file in the /lang/ directory instead of +; language specific subdirectories. */ + +; /* The type is set to (wchar_t *) because that's what we will be +; feeding kherr_report() function. */ + +MessageIdTypedef=LPWSTR + +; /* Severity values as defined in the message definition file are +; currently ignored. */ + +SeverityNames=( + Success=0x0 +) + +LanguageNames=( + English=0x409:MSG_ENU +) + +OutputBase=16 + +; /* Actual messages start here */ + +MessageId=1 +Severity=Success +SymbolicName=MSG_INITIAL +Language=English +Initial placeholder message +. + +MessageId= +SymbolicName=MSG_LOAD_DEFAULT +Language=English +Load default modules +. + +MessageId= +SymbolicName=MSG_INIT_MODULE +Language=English +Initializing module [%1] +. + +MessageId= +SymbolicName=MSG_IM_GET_CONFIG +Language=English +Can't get configuration for modules +. + +MessageId= +SymbolicName=MSG_IM_NOT_PREINIT +Language=English +Module is not in PREINIT state. Current state=[%1!d!] +. + +MessageId= +SymbolicName=MSG_IM_NOT_REGISTERED +Language=English +Module is not registered +. + +MessageId= +SymbolicName=MSG_IM_DISABLED +Language=English +Module is disabled +. + +MessageId= +SymbolicName=MSG_IM_MAX_FAIL +Language=English +Module has failed too many times +. + +MessageId= +SymbolicName=MSG_IM_INVALID_MODULE +Language=English +The DLL containing the module was not of the correct format. +. + +MessageId= +SymbolicName=MSG_IM_INCOMPATIBLE +Language=English +The DLL containing the module was not compatible with this version of NetIDMgr. +. + +Messageid= +SymbolicName=MSG_IM_NOT_FOUND +Language=English +Module binary was not found. Checked path [%1] +. + +MessageId= +SymbolicName=MSG_IM_NO_ENTRY +Language=English +Entry point not found. Checked entry point [%1] +. + +MessageId= +SymbolicName=MSG_IM_INIT_FAIL +Language=English +Module initialization entry point returned failure code [%1!d!] +. + +MessageId= +SymbolicName=MSG_IM_NO_PLUGINS +Language=English +No plug-ins were registered by the module +. + +MessageId= +SymbolicName=MSG_IM_MOD_STATE +Language=English +Module [%1] is in state [%2!d!] +. + +MessageId= +SymbolicName=MSG_IMERR_TITLE +Language=English +Failed to load module %1!s! +. + +MessageId= +SymbolicName=MSG_IMERR_SUGGEST +Language=English +The following information may help resolve this issue: + +%2!s! +. + +MessageId= +SymbolicName=MSG_IP_TASK_DESC +Language=English +Initializing plug-in [%1] +. + +MessageId= +SymbolicName=MSG_IP_GET_CONFIG +Language=English +Can't get configuration for plug-ins +. + +MessageId= +SymbolicName=MSG_IP_NOT_REGISTERED +Language=English +The plug-in is not registered +. + +MessageId= +SymbolicName=MSG_IP_DISABLED +Language=English +The plug-in is disabled +. + +MessageId= +SymbolicName=MSG_IP_HOLD +Language=English +Placing plug-in [%1] on hold +. + +MessageId= +SymbolicName=MSG_IP_STATE +Language=English +Leaving plug-in [%1] in state [%2!d!] +. + +MessageId= +SymbolicName=MSG_IP_EXITING +Language=English +The plug-in [%1] is in error state [%2!d!]. Exiting plug-in. +. + +MessageId= +SymbolicName=MSG_RMI_NOT_FOUND +Language=English +Can't get file version information for path [%1!s!] +. + +MessageId= +SymbolicName=MSG_RMI_NO_TRANS +Language=English +Can't get version resource tranlations list for path [%1!s!] +. + +MessageId= +SymbolicName=MSG_RMI_NO_LOCAL +Language=English +The list of version translations were empty or did not contain a resource for the current user or system locale. +. + +MessageId= +SymbolicName=MSG_RMI_RES_MISSING +Language=English +Required resource %1!s! missing +. + +MessageId= +SymbolicName=MSG_RMI_MOD_MISMATCH +Language=English +The module name specified in the resource is [%1!s!] while the module name as registered is [%2!s!] +. + +MessageId= +SymbolicName=MSG_RMI_RES_TOO_LONG +Language=English +The resource %1!s! is malformed or too long +. + +MessageId= +SymbolicName=MSG_RMI_API_MISMATCH +Language=English +The module was compile for API version %1!d!. However the current API version is %2!d!. +. + +MessageId= +SymbolicName=MSG_PB_START +Language=English +Starting plug-in [%1!s!] +. + +MessageId= +SymbolicName=MSG_PB_INVALID_CODE_PTR +Language=English +The plug-in is no longer valid. This maybe because the module containing the plug-in was unloaded. +. + +MessageId= +SymbolicName=MSG_PB_INIT_RV +Language=English +Initialization of the plug-in returned code %1!d!. +. + +MessageId= +SymbolicName=MSG_PB_INIT_FAIL +Language=English +Initialization of the %1!s! plug-in failed. The plug-in will be unloaded and any functionality provided will not be available. +. + +MessageId= +SymbolicName=MSG_PB_INIT_FAIL_S +Language=English +Plug-in %1!s! failed to initialize +. + +MessageId= +SymbolicName=MSG_PB_INIT_FAIL_G +Language=English +Details for plug-in: +Description: %2!s! +Module: %3!s! +Support: %4!s! +. + +MessageId= +SymbolicName=MSG_PB_INIT_DONE +Language=English +Plug-in running +. diff --git a/krb5-1-6/src/windows/identity/kmq/Makefile b/krb5-1-6/src/windows/identity/kmq/Makefile new file mode 100644 index 000000000..8dcdca405 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=kmq +!include <../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\kmq.h + +OBJFILES= \ + $(OBJ)\kmqmain.obj \ + $(OBJ)\init.obj \ + $(OBJ)\msgtype.obj \ + $(OBJ)\consumer.obj \ + $(OBJ)\publisher.obj \ + $(OBJ)\kmqconfig.obj + +SDKLIBFILES=\ + strsafe.lib + +$(OBJ)\kmqconfig.c: kmqconfig.csv $(CONFDIR)\csvschema.cfg + $(CCSV) $** $@ + +all: mkdirs $(INCFILES) $(OBJFILES) + +clean:: + if exist ..\obj $(RM) $(INCFILES) diff --git a/krb5-1-6/src/windows/identity/kmq/consumer.c b/krb5-1-6/src/windows/identity/kmq/consumer.c new file mode 100644 index 000000000..dd21834c6 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/consumer.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmqinternal.h> +#include<assert.h> + +DWORD kmq_tls_queue; + +CRITICAL_SECTION cs_kmq_msg_ref; + +kmq_message_ref * kmq_msg_ref_free = NULL; + +/* ad-hoc subscriptions */ +kmq_msg_subscription * kmq_adhoc_subs = NULL; + +#ifdef DEBUG + +#include<stdio.h> + +void +kmqint_dump_consumer(FILE * f) { + kmq_message_ref * r; + kmq_msg_subscription * s; + + int n_free = 0; + int n_adhoc = 0; + + EnterCriticalSection(&cs_kmq_msg_ref); + + fprintf(f, "qc0\t*** Free Message References ***\n"); + + fprintf(f, "qc1\tAddress\n"); + + r = kmq_msg_ref_free; + while(r) { + n_free ++; + + fprintf(f, "qc2\t0x%p\n", r); + + r = LNEXT(r); + } + + fprintf(f, "qc3\tTotal free message references : %d\n", n_free); + + fprintf(f, "qc4\t--- End ---\n"); + + LeaveCriticalSection(&cs_kmq_msg_ref); + + EnterCriticalSection(&cs_kmq_global); + + fprintf(f, "qc5\t*** Adhoc Message Subscriptions ***\n"); + + fprintf(f, "qc6\tAddress\tMsg Type\tRcpt Type\tRcpt\tQueue\n"); + + s = kmq_adhoc_subs; + + while(s) { + n_adhoc ++; + + fprintf(f, "qc7\t0x%p\t%d\t%s\t0x%p\t0x%p\n", + s, + s->type, + (s->rcpt_type == KMQ_RCPTTYPE_CB)?"CALLBACK":"HWND", + (s->rcpt_type == KMQ_RCPTTYPE_CB)? s->recipient.cb: (void *) s->recipient.hwnd, + s->queue); + + s = LNEXT(s); + } + + fprintf(f, "qc8\tTotal ad-hoc subscriptions : %d\n", n_adhoc); + + fprintf(f, "qc9\t--- End ---\n"); + + LeaveCriticalSection(&cs_kmq_global); + +} + +#endif + +/*! \internal + \brief Get a message ref object + \note called with cs_kmq_msg_ref held */ +kmq_message_ref * kmqint_get_message_ref(void) { + kmq_message_ref * r; + + LPOP(&kmq_msg_ref_free, &r); + if(!r) { + r = PMALLOC(sizeof(kmq_message_ref)); + } + ZeroMemory(r, sizeof(kmq_message_ref)); + + r->msg = NULL; + r->recipient = NULL; + + return r; +} + +/*! \internal + \brief Free a message ref object + \note called with cs_kmq_msg_ref and cs_kmq_msg held */ +void kmqint_put_message_ref(kmq_message_ref * r) { + if(!r) + return; + if(r->msg) { + r->msg->refcount--; + r->msg = NULL; + } + LPUSH(&kmq_msg_ref_free, r); +} + +/*! \internal + \brief Get the queue associated with the current thread + \note Obtains ::cs_kmq_global + */ +kmq_queue * kmqint_get_thread_queue(void) { + kmq_queue * q; + + q = (kmq_queue *) TlsGetValue(kmq_tls_queue); + if(!q) { + kmqint_attach_this_thread(); + q = (kmq_queue *) TlsGetValue(kmq_tls_queue); + } + + return q; +} + +/*! \internal + \brief Get the topmost message ref for a queue + \note Obtains kmq_queue::cs + */ +void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r) { + EnterCriticalSection(&q->cs); + + if (q->flags & KMQ_QUEUE_FLAG_DELETED) { + *r = NULL; + } else { + QGET(q,r); + if(QTOP(q)) + SetEvent(q->wait_o); + } + + LeaveCriticalSection(&q->cs); +} + +/*! \internal + \brief Post a message to a queue + \note Obtains ::cs_kmq_msg_ref, ::cs_kmq_msg, kmq_queue::cs + */ +void kmqint_post_queue(kmq_queue * q, kmq_message *m) { + kmq_message_ref *r; + + EnterCriticalSection(&q->cs); + if (q->flags & KMQ_QUEUE_FLAG_DELETED) { + LeaveCriticalSection(&q->cs); + return; + } + LeaveCriticalSection(&q->cs); + + EnterCriticalSection(&cs_kmq_msg_ref); + r = kmqint_get_message_ref(); + LeaveCriticalSection(&cs_kmq_msg_ref); + + r->msg = m; + r->recipient = NULL; + + EnterCriticalSection(&cs_kmq_msg); + m->refcount++; + m->nSent++; + LeaveCriticalSection(&cs_kmq_msg); + + EnterCriticalSection(&q->cs); + QPUT(q,r); + SetEvent(q->wait_o); + LeaveCriticalSection(&q->cs); +} + +/*! \internal + \brief Post a message to a subscriber + \note Obtains ::cs_kmq_msg_ref, ::cs_kmq_msg, kmq_queue::cs + \note Should be called with ::cs_kmq_msg held + \note Should be called with ::cs_kmq_types held if try_send is true + */ +void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send) { + if(s->rcpt_type == KMQ_RCPTTYPE_CB) { + kmq_queue *q; + kmq_message_ref *r; + + q = s->queue; + + if(try_send && q->thread == GetCurrentThreadId()) { + khm_int32 rv; + /* we are sending a message from this thread to this + thread. just call the recipient directly, bypassing + the message queue. */ + m->refcount++; + m->nSent++; + rv = s->recipient.cb(m->type, m->subtype, + m->uparam, m->vparam); + m->refcount--; + if(KHM_SUCCEEDED(rv)) + m->nCompleted++; + else + m->nFailed++; + } else { + + EnterCriticalSection(&q->cs); + if (q->flags & KMQ_QUEUE_FLAG_DELETED) { + LeaveCriticalSection(&q->cs); + return; + } + LeaveCriticalSection(&q->cs); + + EnterCriticalSection(&cs_kmq_msg_ref); + r = kmqint_get_message_ref(); + LeaveCriticalSection(&cs_kmq_msg_ref); + + r->msg = m; + r->recipient = s->recipient.cb; + + m->refcount++; + m->nSent++; + + EnterCriticalSection(&q->cs); + QPUT(q,r); + SetEvent(q->wait_o); + LeaveCriticalSection(&q->cs); + } + } + +#ifdef _WIN32 + else if(s->rcpt_type == KMQ_RCPTTYPE_HWND) { + if(try_send && + GetCurrentThreadId() == GetWindowThreadProcessId(s->recipient.hwnd, + NULL)) { + /* kmqint_post does not know whether there are any other + messages waiting to be posted at this point. Hence, + simply sending the message is not the right thing to do + as the recipient may incorrectly assume that the + message has completed when (m->nCompleted + m->nFailed + == m->nSent). Therefore, we only increment nSent after + the message is sent. */ + + m->refcount++; + + /* the kmq_wm_begin()/kmq_wm_end() and kmq_wm_dispatch() + handlers decrement the reference count on the message + when they are done. */ + SendMessage(s->recipient.hwnd, KMQ_WM_DISPATCH, + m->type, (LPARAM) m); + + m->nSent++; + + } else { + m->nSent++; + m->refcount++; + + /* the kmq_wm_begin()/kmq_wm_end() and kmq_wm_dispatch() + handlers decrement the reference count on the message + when they are done. */ + PostMessage(s->recipient.hwnd, KMQ_WM_DISPATCH, + m->type, (LPARAM) m); + } + } +#endif + + else { + /* This could either be because we were passed in an invalid + subscription or because we lost a race to a thread that + deleted an ad-hoc subscription. */ +#ifdef DEBUG + assert(FALSE); +#endif + } +} + +/*! \internal + \brief Subscribes a window to a message type + \note Obtains ::cs_kmq_types + */ +KHMEXP khm_int32 KHMAPI kmq_subscribe_hwnd(khm_int32 type, HWND hwnd) { + kmq_msg_subscription * s; + + s = PMALLOC(sizeof(kmq_msg_subscription)); + ZeroMemory(s, sizeof(*s)); + s->magic = KMQ_MSG_SUB_MAGIC; + LINIT(s); + s->queue = NULL; + s->rcpt_type = KMQ_RCPTTYPE_HWND; + s->recipient.hwnd = hwnd; + kmqint_msg_type_add_sub(type, s); + + return KHM_ERROR_SUCCESS; +} + +/*! \internal + \note Obtains ::cs_kmq_types, ::cs_kmq_global + */ +KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb) { + kmq_msg_subscription * s; + + s = PMALLOC(sizeof(kmq_msg_subscription)); + ZeroMemory(s, sizeof(*s)); + s->magic = KMQ_MSG_SUB_MAGIC; + LINIT(s); + s->queue = kmqint_get_thread_queue(); + s->rcpt_type = KMQ_RCPTTYPE_CB; + s->recipient.cb = cb; + kmqint_msg_type_add_sub(type, s); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw, + khm_handle * result) +{ + kmq_msg_subscription * s; + + s = PMALLOC(sizeof(kmq_msg_subscription)); + ZeroMemory(s, sizeof(*s)); + s->magic = KMQ_MSG_SUB_MAGIC; + LINIT(s); + s->queue = NULL; + s->rcpt_type = KMQ_RCPTTYPE_HWND; + s->recipient.hwnd = hw; + + EnterCriticalSection(&cs_kmq_global); + LPUSH(&kmq_adhoc_subs, s); + LeaveCriticalSection(&cs_kmq_global); + + *result = (khm_handle) s; + + return KHM_ERROR_SUCCESS; +} + +/*! \internal + \note Obtains ::cs_kmq_global +*/ +KHMEXP khm_int32 KHMAPI kmq_create_subscription(kmq_callback_t cb, + khm_handle * result) +{ + kmq_msg_subscription * s; + + s = PMALLOC(sizeof(kmq_msg_subscription)); + ZeroMemory(s, sizeof(*s)); + s->magic = KMQ_MSG_SUB_MAGIC; + LINIT(s); + s->queue = kmqint_get_thread_queue(); + s->rcpt_type = KMQ_RCPTTYPE_CB; + s->recipient.cb = cb; + + EnterCriticalSection(&cs_kmq_global); + LPUSH(&kmq_adhoc_subs, s); + LeaveCriticalSection(&cs_kmq_global); + + *result = (khm_handle) s; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kmq_delete_subscription(khm_handle sub) +{ + kmq_msg_subscription * s; + + s = (kmq_msg_subscription *) sub; + + assert(s->magic == KMQ_MSG_SUB_MAGIC); + + s->type = 0; + + EnterCriticalSection(&cs_kmq_global); + LDELETE(&kmq_adhoc_subs, s); + LeaveCriticalSection(&cs_kmq_global); + + PFREE(s); + + return KHM_ERROR_SUCCESS; +} + +/*! \internal + \brief Unsubscribes a window from a message type + \note Obtains ::cs_kmq_types + */ +KHMEXP khm_int32 KHMAPI kmq_unsubscribe_hwnd(khm_int32 type, HWND hwnd) { + kmq_msg_subscription * s; + + s = kmqint_msg_type_del_sub_hwnd(type, hwnd); + if(s) + PFREE(s); + return (s)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND; +} + +/*! \internal + \brief Unsubscribe a callback from a message type + \note Obtains ::cs_kmq_types, ::cs_kmq_global + */ +KHMEXP khm_int32 KHMAPI kmq_unsubscribe(khm_int32 type, kmq_callback_t cb) { + kmq_msg_subscription * s; + + s = kmqint_msg_type_del_sub_cb(type,cb); + if(s) + PFREE(s); + + return (s)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND; +} + +KHMEXP LRESULT KHMAPI kmq_wm_begin(LPARAM lparm, kmq_message ** m) { + *m = (kmq_message *) lparm; + if ((*m)->err_ctx) { + kherr_push_context((*m)->err_ctx); + } + return TRUE; +} + +/*! \internal + \note Obtains ::cs_kmq_msg + */ +KHMEXP LRESULT KHMAPI kmq_wm_end(kmq_message *m, khm_int32 rv) { + if (m->err_ctx) + kherr_pop_context(); + + EnterCriticalSection(&cs_kmq_msg); + m->refcount--; + if(KHM_SUCCEEDED(rv)) + m->nCompleted++; + else + m->nFailed++; + + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + + return TRUE; +} + +/*! \internal + \note Obtains ::cs_kmq_msg + */ +KHMEXP LRESULT KHMAPI kmq_wm_dispatch(LPARAM lparm, kmq_callback_t cb) { + kmq_message *m; + khm_int32 rv; + + m = (kmq_message *) lparm; + + if (m->err_ctx) + kherr_push_context(m->err_ctx); + + rv = cb(m->type, m->subtype, m->uparam, m->vparam); + + if (m->err_ctx) + kherr_pop_context(); + + EnterCriticalSection(&cs_kmq_msg); + + m->refcount--; + if(KHM_SUCCEEDED(rv)) + m->nCompleted++; + else + m->nFailed++; + + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + + return TRUE; +} + +KHMEXP khm_boolean KHMAPI kmq_is_call_aborted(void) { + /* TODO: Implement this */ + return FALSE; +} + +/*! \internal + + \note Obtains ::cs_kmq_global, kmq_queue::cs, ::cs_kmq_msg_ref, ::cs_kmq_msg, +*/ +KHMEXP khm_int32 KHMAPI kmq_dispatch(kmq_timer timeout) { + kmq_queue * q; + kmq_message_ref * r; + kmq_message *m; + DWORD hr; + + q = kmqint_get_thread_queue(); + + assert(q->wait_o); + + hr = WaitForSingleObject(q->wait_o, timeout); + if(hr == WAIT_OBJECT_0) { + /* signalled */ + kmqint_get_queue_message_ref(q, &r); + + m = r->msg; + + if(m->type != KMSG_SYSTEM || m->subtype != KMSG_SYSTEM_EXIT) { + khm_boolean rv; + + if (m->err_ctx) + kherr_push_context(m->err_ctx); + + /* TODO: before dispatching the message, the message being + dispatched for this thread needs to be stored so that + it can be looked up in kmq_is_call_aborted(). This + needs to happen in kmq_wm_dispatch() and + kmq_wm_begin() as well. */ + + /* dispatch */ + rv = r->recipient(m->type, m->subtype, m->uparam, m->vparam); + + if (m->err_ctx) + kherr_pop_context(); + + EnterCriticalSection(&cs_kmq_msg); + EnterCriticalSection(&cs_kmq_msg_ref); + kmqint_put_message_ref(r); + LeaveCriticalSection(&cs_kmq_msg_ref); + + if(KHM_SUCCEEDED(rv)) + m->nCompleted++; + else + m->nFailed++; + + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + + return KHM_ERROR_SUCCESS; + } else { + EnterCriticalSection(&cs_kmq_msg); + EnterCriticalSection(&cs_kmq_msg_ref); + kmqint_put_message_ref(r); + LeaveCriticalSection(&cs_kmq_msg_ref); + m->nCompleted++; + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + + return KHM_ERROR_EXIT; + } + } else { + return KHM_ERROR_TIMEOUT; + } +} + +/* TODO: rename this file to subscriber.c */ diff --git a/krb5-1-6/src/windows/identity/kmq/init.c b/krb5-1-6/src/windows/identity/kmq/init.c new file mode 100644 index 000000000..1c2023fc8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/init.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmqinternal.h> +#include<kconfig.h> +#include<assert.h> + +CRITICAL_SECTION cs_kmq_global; +kmq_timer kmq_queue_dead_timeout; +kmq_timer kmq_call_dead_timeout; + +kmq_queue * queues; + +LONG kmq_init_once = 0; + +void kmqint_init(void) { + khm_handle hconfig = NULL; + + queues = NULL; + + InitializeCriticalSection(&cs_kmq_global); + InitializeCriticalSection(&cs_kmq_msg); + InitializeCriticalSection(&cs_kmq_msg_ref); + + EnterCriticalSection(&cs_kmq_global); + khc_load_schema(NULL, schema_kmqconfig); + khc_open_space(NULL, KMQ_CONF_SPACE_NAME, KHM_PERM_READ, &hconfig); + if(hconfig) { + khm_int32 t = 0; + + khc_read_int32(hconfig, KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME, &t); + kmq_queue_dead_timeout = t; + + khc_read_int32(hconfig, KMQ_CONF_CALL_DEAD_TIMEOUT_NAME, &t); + kmq_call_dead_timeout = t; + + khc_close_space(hconfig); + } + kmqint_init_msg_types(); + LeaveCriticalSection(&cs_kmq_global); + + kmq_tls_queue = TlsAlloc(); +} + +void kmqint_exit(void) { + EnterCriticalSection(&cs_kmq_global); + kmqint_exit_msg_types(); + LeaveCriticalSection(&cs_kmq_global); + DeleteCriticalSection(&cs_kmq_msg); + DeleteCriticalSection(&cs_kmq_msg_ref); + DeleteCriticalSection(&cs_kmq_global); + + TlsFree(kmq_tls_queue); +} + +/*! \internal + \brief Preps a thread for use with kmq + \note Obtains ::cs_kmq_global + */ +void kmqint_attach_this_thread(void) { + kmq_queue * q; + + EnterCriticalSection(&cs_kmq_global); + + q = (kmq_queue *) TlsGetValue(kmq_tls_queue); + if(!q) { + q = PMALLOC(sizeof(kmq_queue)); + + InitializeCriticalSection(&q->cs); + q->thread = GetCurrentThreadId(); + QINIT(q); + LINIT(q); + q->wait_o = CreateEvent(NULL, FALSE, FALSE, NULL); + q->load = 0; + q->last_post = 0; + q->flags = 0; + + LPUSH(&queues, q); + + TlsSetValue(kmq_tls_queue, (LPVOID) q); + } + + LeaveCriticalSection(&cs_kmq_global); +} + +/*! \internal + \brief Detaches the current thread from kmq + \note Obtains ::cs_kmq_global + */ +void kmqint_detach_this_thread(void) { + kmq_queue * q; + + q = (kmq_queue *) TlsGetValue(kmq_tls_queue); + if(q) { + kmq_message_ref * r; + kmq_message * m; + + EnterCriticalSection(&q->cs); + + if (q->flags & KMQ_QUEUE_FLAG_DETACHING) { +#ifdef DEBUG + assert(FALSE); +#endif + LeaveCriticalSection(&q->cs); + return; + } + + q->flags |= KMQ_QUEUE_FLAG_DELETED | KMQ_QUEUE_FLAG_DETACHING; + + QGET(q, &r); + while(r) { + + m = r->msg; + + LeaveCriticalSection(&q->cs); + + EnterCriticalSection(&cs_kmq_msg); + EnterCriticalSection(&cs_kmq_msg_ref); + kmqint_put_message_ref(r); + LeaveCriticalSection(&cs_kmq_msg_ref); + + m->nFailed++; + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + + EnterCriticalSection(&q->cs); + + QGET(q, &r); + } + + CloseHandle(q->wait_o); + + q->wait_o = NULL; + + q->flags &= ~KMQ_QUEUE_FLAG_DETACHING; + + LeaveCriticalSection(&q->cs); + + /* For now, we don't free the queue. */ + + /* TODO: before we can free the queue, we have to go through + all the message type subscriptions and ad-hoc subscriptions + and make sure no subscriptions exist which refer to this + message queue. */ + } +} + +HANDLE kmq_h_compl = NULL; +kmq_thread_id kmq_tid_compl; + +/* Message transfer */ +struct tag_kmq_msg_xfer { + QDCL(kmq_message); +} kmq_completion_xfer; + +HANDLE compl_wx; +BOOL compl_continue; +CRITICAL_SECTION cs_compl; + +DWORD WINAPI kmqint_completion_thread_proc(LPVOID p) { + kmq_message * m; + kherr_context * ctx; + + PDESCTHREAD(L"Msg completion thread", L"KMQ"); + + EnterCriticalSection(&cs_compl); + do { + + if (QTOP(&kmq_completion_xfer) == NULL) { + LeaveCriticalSection(&cs_compl); + WaitForSingleObject(compl_wx, INFINITE); + EnterCriticalSection(&cs_compl); + /* go through the loop again before checking the queue */ + } else { + QGET(&kmq_completion_xfer, &m); + LeaveCriticalSection(&cs_compl); + EnterCriticalSection(&cs_kmq_msg); + + ctx = m->err_ctx; + + if (ctx) + kherr_push_context(ctx); + + kmqint_put_message(m); + + if (ctx) + kherr_pop_context(); + + LeaveCriticalSection(&cs_kmq_msg); + EnterCriticalSection(&cs_compl); + } + + } while(compl_continue); + + LeaveCriticalSection(&cs_compl); + + ExitThread(0); +} + +int kmqint_call_completion_handler(kmq_msg_completion_handler h, + kmq_message * m) { + if (h == NULL) + return 0; + + /* We only dispatch to the completion thread if we are not the + completion thread. If calling the completion handler results + in more messages completing, then we just call the completion + handler directly. We also make an exception for completions + that happen before the message queue is properly intiailized. */ + + if (kmq_tid_compl != GetCurrentThreadId() && + kmq_h_compl != NULL) { + + EnterCriticalSection(&cs_compl); + QPUT(&kmq_completion_xfer, m); + SetEvent(compl_wx); + LeaveCriticalSection(&cs_compl); + + return 1; + + } else { + h(m); + + return 0; + } +} + +KHMEXP khm_int32 KHMAPI kmq_init(void) { + if (InterlockedIncrement(&kmq_init_once) == 1) { + EnterCriticalSection(&cs_kmq_global); + + InitializeCriticalSection(&cs_compl); + compl_wx = CreateEvent(NULL, FALSE, FALSE, NULL); + compl_continue = TRUE; + QINIT(&kmq_completion_xfer); + + kmq_h_compl = CreateThread(NULL, + 0, + kmqint_completion_thread_proc, + NULL, + 0, + &kmq_tid_compl); + + assert(kmq_h_compl != NULL); + + LeaveCriticalSection(&cs_kmq_global); + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI kmq_exit(void) { + if (InterlockedDecrement(&kmq_init_once) == 0) { + + EnterCriticalSection(&cs_compl); + compl_continue = FALSE; + SetEvent(compl_wx); + LeaveCriticalSection(&cs_compl); + + WaitForSingleObject(kmq_h_compl, INFINITE); + + EnterCriticalSection(&cs_kmq_global); + CloseHandle(kmq_h_compl); + kmq_h_compl = NULL; + kmq_tid_compl = 0; + CloseHandle(compl_wx); + DeleteCriticalSection(&cs_compl); + LeaveCriticalSection(&cs_kmq_global); + } + + return KHM_ERROR_SUCCESS; +} + +#ifdef DEBUG + +void kmqint_dump_consumer(FILE * f); +void kmqint_dump_publisher(FILE * f); + + +KHMEXP void KHMAPI kmqint_dump(FILE * f) { + kmqint_dump_consumer(f); + kmqint_dump_publisher(f); +} + +#endif diff --git a/krb5-1-6/src/windows/identity/kmq/kmq.h b/krb5-1-6/src/windows/identity/kmq/kmq.h new file mode 100644 index 000000000..db6d5b262 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/kmq.h @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KMQ_H__ +#define __KHIMAIRA_KMQ_H__ + +/*! \defgroup kmq NetIDMgr Message Queue + + The Network Identity Manager Message Queue handles all the + messaging within the application and all loaded plug-ins. + + For information about the messaging system and how it is used, + please see \ref pi_fw_pnm_msg . +*/ +/*@{*/ + +#include<khdefs.h> +#include<khlist.h> +#include<kherr.h> + +/* general */ +#ifdef _WIN32 +typedef DWORD kmq_thread_id; +typedef DWORD kmq_timer; +#endif + +#ifdef _WIN32 +/*! \brief Window message for kmq + + This message is sent to the window procedure of a window if that + window is a subscriber to KMQ messages. + + \see kmq_subscribe_hwnd() for more information about handling this + window message + */ +#define KMQ_WM_DISPATCH (WM_APP+0x100) +#endif + +/* callback */ + +/*! \brief A message callback + + Should return TRUE if the message is properly handled. Otherwise + return FALSE */ +typedef khm_int32 (KHMAPI *kmq_callback_t)(khm_int32 msg_type, + khm_int32 msg_sub_type, + khm_ui_4 uparam, + void * vparam); + +/* message */ + +/*! \brief A single response. + + Certain broadcast messages may user scatter-gather type + notification and result gathering. Individual subscribers to a + message attach their individual responses to a ::kmq_response + object and attach that to the message which can later be read by + the sender of the message. + */ +typedef struct tag_kmq_response { + kmq_thread_id thread; + void * response; + + LDCL(struct tag_kmq_response); +} kmq_response; + +/*! \brief A single message + */ +typedef struct tag_kmq_message { + khm_int32 type; /*!< Type of message */ + khm_int32 subtype; /*!< Subtype of message */ + + khm_ui_4 uparam; /*!< Integer parameter */ + void * vparam; /*!< Pointer to parameter blob */ + + khm_int32 nSent; /*!< Number of instances of message + sent (for broadcast messages) */ + + khm_int32 nCompleted; /*!< Number of instances that have + completed processing (for broadcast + messages) */ + + khm_int32 nFailed; /*!< Number of instances that failed + to process (for broadcast + messages) */ + + kmq_response * responses; /*!< List of responses */ + HANDLE wait_o; /*!< Event to wait on (only valid if + the publisher of the message + requested a handle to the call) */ + + kmq_timer timeSent; /*!< Time at which the message was + sent */ + kmq_timer timeExpire; /*!< Time at which the message + expires */ + + kherr_context * err_ctx; /*!< Error context for the message */ + + khm_boolean aborted; /*!< TRUE if the message has been + aborted. */ + + khm_int32 refcount; /*!< Internal use */ + + LDCL(struct tag_kmq_message); /*!< Internal use */ +} kmq_message; + +/*! \brief A handle to a call + */ +typedef kmq_message *kmq_call; + +/* publishers */ + +/*! \brief A completion handler for a message + + Each message type can have a completion handler. Once a message + of this a specific type has been broadcast and handled by all the + subscripbers, the message will be passed down to the completion + handler before the associated data structures are freed. This + allows applications that define message type to also define clean + up for each message. For example, the completion handler can + initiate another message if the messages form a sequence or free + up blocks of memory that was passed as the parameter to the + message. + */ +typedef void (KHMAPI *kmq_msg_completion_handler)(kmq_message *); + +#ifdef NOEXPORT + +KHMEXP khm_int32 KHMAPI kmq_init(void); + +KHMEXP khm_int32 KHMAPI kmq_exit(void); + +#endif + +/*! \brief Register a message type + + Registers a custom message type. The \a name parameter specifies + a language independent name for the message type and must be + unique and must be less than ::KMQ_MAXCCH_TYPE_NAME characters. + + \param[in] name Name of the message type. Upto + ::KMQ_MAXCCH_TYPE_NAME characters including terminating NULL. + The \a name cannot be a zero length string. + + \param[out] new_id Receives the new message type ID. Specify NULL + if the new message type is not required. + + \see kmq_find_type() and kmq_unregister_type() + + \retval KHM_ERROR_INVALID_PARAM The \a name parameter was invalid. + \retval KHM_ERROR_EXISTS A message type with that name already exists. + \retval KHM_ERROR_NO_RESOURCES Can't register any more message types. + \retval KHM_ERROR_SUCCESS The operation succeeded. + */ +KHMEXP khm_int32 KHMAPI kmq_register_type(wchar_t * name, khm_int32 * new_id); + +/*! \brief Find a message type + + Find the message type with the given name. If found, the type ID + is returned in \a id. + + \retval KHM_ERROR_SUCCESS A message type with the given name was + found. + \retval KHM_ERROR_NOT_FOUND A message type with the given name was + not found. + */ +KHMEXP khm_int32 KHMAPI kmq_find_type(wchar_t * name, khm_int32 * id); + +/*! \brief Unregister a message type + + Unregisters a message type that was registered using + kmq_register_type(). + + \retval KHM_ERROR_SUCCESS The specified message type was + successfully unregistered. + + \retval KHM_ERROR_NOT_FOUND The message type was not found. + */ +KHMEXP khm_int32 KHMAPI kmq_unregister_type(khm_int32 id); + +/*! \brief Subscribte to a message type. + + Adds a subscription to messages of type \a type. Subscriptions + are managed per thread. Therefore the subscription is actually + added to the subscription list for the current thread (the thread + which calls kmq_subscribe()). + + When a message of type \a type is received by the thread, it is + dispatched to the callback function identified by \a cb within the + context of this thread. + + \note Calling kmq_subscribe() from within multiple threads with + the same \a type and \a cb will result in multiple + subscriptions. + + \see kmq_unsubscribe() + \see kmq_dispatch() +*/ +KHMEXP khm_int32 KHMAPI kmq_subscribe(khm_int32 type, kmq_callback_t cb); + +/*! \brief Subscribe a window to a message type + + Adds the window specified by \a hwnd to the subscription list for + the message type \a type. When a message of this type is posted, + then the window procedure of the window \a hwnd receives a message + ::KMQ_WM_DISPATCH. + + When a window receives a ::KMQ_WM_DISPATCH message, it means that + a message has been posted which is of a type that the window has + subscribed for. Because of the way Windows handles window + messages and the way NetIDMgr message queues work, a thread which + has a window (or thread) procedure can not call kmq_dispatch() to + handle these messages. For threads that have window or thread + message loops, they must call kmq_subscribe_hwnd() to subscribe a + particular window (for thread message loops, this would be the + HWND of the message window for the thread) to NetIDMgr messages. + + There are two supported ways of handling the ::KMQ_WM_DISPATCH + message. Examples of both are provided below. + + Handling the message inline: + + \code + LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + kmq_message * m; + khm_int32 rv; + ... + switch(uMsg) { + case WM_CREATE: + ... + kmq_subscribe_hwnd(KMSG_CRED, hwnd); + ... + break; + + case WM_DESTROY: + ... + kmq_unsubscribe_hwnd(KMSG_CRED, hwnd); + ... + break; + + ... + case KMQ_WM_DISPATCH: + kmq_wm_begin(lParam,&m); + + if(m->type == KMSG_CRED && m->subtype == KMSG_CRED_ROOTDELTA) { + // do something + rv = KHM_ERROR_SUCCESS; + } + + return kmq_wm_end(m, rv); + ... + }; + ... + } + \endcode + + The other method is to dispatch the ::KMQ_WM_DISPATCH message to a + secondary callback function: + + \code + khm_int32 msg_handler(khm_int32 t, khm_int32 st, khm_ui_4 up, void * pb) { + khm_int32 rv = KHM_ERROR_SUCCESS; + + //handle message + + return rv; + } + + LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + kmq_message * m; + khm_int32 rv; + ... + switch(uMsg) { + ... + + case WM_CREATE: + ... + kmq_subscribe_hwnd(KMSG_CRED, hwnd); + ... + break; + + case WM_DESTROY: + ... + kmq_unsubscribe_hwnd(KMSG_CRED, hwnd); + ... + break; + + ... + case KMQ_WM_DISPATCH: + return kmq_wm_dispatch(lParam, msg_handler); + ... + }; + ... + } + \endcode + + \note Make sure you unsubscribe from the message type when the + window is destroyed. + + \see kmq_unsubscribe_hwnd() + \see kmq_wm_begin() + \see kmq_wm_end() + \see kmq_wm_dispatch() + */ +KHMEXP khm_int32 KHMAPI kmq_subscribe_hwnd(khm_int32 type, HWND hwnd); + +#ifdef _WIN32 +/*! \brief Begins handling a KMQ_WM_DISPATCH message + + \return The return value of this function should be ignored. + + \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH + */ +KHMEXP LRESULT KHMAPI kmq_wm_begin(LPARAM lparm, kmq_message ** m); + +/*! \brief Ends handling a KMQ_WM_DISPATCH message + + \return The return value of this function should be the return + value of the window procedure. See kmq_subscribe_hwnd() + documentation for example + + \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH + */ +KHMEXP LRESULT KHMAPI kmq_wm_end(kmq_message *m, khm_int32 rv); + +/*! \brief Dispatches a KMQ_WM_DISPATCH message to a callback + + \return The return value of this function should be the return + value of the window procedure. See kmq_subscribe_hwnd() + documentation for example. + + \see kmq_subscribe_hwnd() for more details about handling ::KMQ_WM_DISPATCH + */ +KHMEXP LRESULT KHMAPI kmq_wm_dispatch(LPARAM lparm, kmq_callback_t cb); +#endif + +/*! \brief Unsubscribe a callback from a message type + + Removes the subscription for message type \a type for callback + function \a cb from the subscription list for the current thread + (the thread that calls kmq_unsubscribe()). + + \note kmq_unsubscribe() can only remove subscriptions for the subscription + list for the current thread. + + \see kmq_subscribe() + \see kmq_dispatch() +*/ +KHMEXP khm_int32 KHMAPI kmq_unsubscribe(khm_int32 type, kmq_callback_t cb); + +/*! \brief Unsubscribe a window from a message type + + Removes the specific window from the subsription list for message + type \a type. + + \see kmq_subscribe_hwnd() +*/ +KHMEXP khm_int32 KHMAPI kmq_unsubscribe_hwnd(khm_int32 type, HWND hwnd); + +/*! \brief Create an ad-hoc subscription + + An ad-hoc subscription describes a callback point in a thread that + can be dispatched messages to individually without broadcasting. + + \see kmq_post_sub_msg(), kmq_post_sub_msg_ex(), + kmq_send_sub_msg(), kmq_post_subs_msg(), + kmq_post_subs_msg_ex(), kmq_send_subs_msg(), + kmq_delete_subscription() +*/ +KHMEXP khm_int32 KHMAPI kmq_create_subscription( + kmq_callback_t cb, + khm_handle * result); + +/*! \brief Create an ad-hoc subscription for a window + + An ad-hoc subscription describes a window that will be dispatched + messages individually without broadcasting. + + \see kmq_post_sub_msg(), kmq_post_sub_msg_ex(), + kmq_send_sub_msg(), kmq_post_subs_msg(), + kmq_post_subs_msg_ex(), kmq_send_subs_msg(), + kmq_delete_subscription() + */ +KHMEXP khm_int32 KHMAPI kmq_create_hwnd_subscription(HWND hw, + khm_handle * result); + +/*! \brief Delete an ad-hoc subscription + + Deletes a subscriptoin that was created using + kmq_create_subscription() + */ +KHMEXP khm_int32 KHMAPI kmq_delete_subscription(khm_handle sub); + +/*! \brief Post a message to a subscription + + Equivalent of kmq_post_msg() but only posts the message to the + specified subscription. + */ +KHMEXP khm_int32 KHMAPI kmq_post_sub_msg( + khm_handle sub, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam); + +/*! \brief Post a message to a subscription and acquire a handle to the call + */ +KHMEXP khm_int32 KHMAPI kmq_post_sub_msg_ex( + khm_handle sub, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam, + kmq_call * call); + +/*! \brief Send a synchronous message to a subscription + + \retval KHM_ERROR_SUCCESS The call succeeded, and no subscribers reported errors + \retval KHM_ERROR_PARTIAL The call succeeded, but at least one subscriber reported errors + */ +KHMEXP khm_int32 KHMAPI kmq_send_sub_msg( + khm_handle sub, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam); + +/*! \brief Post a message to a group of subscriptions + + The block of memory pointed to by \a subs should be an array of + subscriptions. The number of elements in that array should be \a + n_subs. A message as specified by the remaining parameters will + be dispatched to all of the subscription points in the array. + */ +KHMEXP khm_int32 KHMAPI kmq_post_subs_msg( + khm_handle * subs, + khm_size n_subs, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam); + +/*! \brief Post a message to a group of subscriptions and acquire a handle to the call + + The block of memory pointed to by \a subs should be an array of + subscriptions. The number of elements in that array should be \a + n_subs. A message as specified by the remaining parameters will + be dispatched to all of the subscription points in the array, and + a handle to the call will be returned in \a call. + + The returned \a call will reference all of the dispatches that + were made. +*/ +KHMEXP khm_int32 KHMAPI kmq_post_subs_msg_ex( + khm_handle * subs, + khm_int32 n_subs, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam, + kmq_call * call); + +/*! \brief Send a synchronous message to a group of subscriptions + + The block of memory pointed to by \a subs should be an array of + subscriptions. The number of elements in that array should be \a + n_subs. A message as specified by the remaining parameters will + be dispatched to all of the subscription points in the array. The + function will not return until all of the calls have succeeded. + + \retval KHM_ERROR_SUCCESS The call succeeded, and no subscribers reported errors + \retval KHM_ERROR_PARTIAL The call succeeded, but at least one subscriber reported errors +*/ +KHMEXP khm_int32 KHMAPI kmq_send_subs_msg( + khm_handle *subs, + khm_int32 n_subs, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam); + +/*! \brief Dispatch a message for the current thread. + + This function opens the message list for the current thread and + dispatches the first message instance that is found. Note that if + multiple callbacks subscribe to the same message type in the same + thread, then when a message of that type is received, multiple + message instances are added to the message queue corresponding to + each subscription. + + If no message instances are waiting in the queue, kmq_dispatch() + waits for the \a timeout period for a message. + + \param[in] timeout The timeout period in milliseconds. Specify INFINITE for + kmq_dispatch() to wait indefinitely. + + \retval KHM_ERROR_SUCCESS A message instance was dispatched + \retval KHM_ERROR_TIMEOUT The timeout period elapsed + \retval KHM_ERROR_EXIT The message found on the queue was <KMSG_SYSTEM,KMSG_SYSTEM_EXIT> +*/ +KHMEXP khm_int32 KHMAPI kmq_dispatch(kmq_timer timeout); + +/*! \brief Send a message + + The specified message will be posted to all the subscribers of the + message type. Then the function will wait for all the subscribers + to finish processing the message before returning. + + \param[in] type The type of the message + \param[in] subtype The subtype + \param[in] uparam The khm_ui_4 parameter for the message + \param[in] blob The parameter blob for the message + + \note The internal timeout for this function is INFINITE. If you + it is desirable to use a different timeout, use + kmq_post_message_ex() and kmq_wait() functions. + + \retval KHM_ERROR_SUCCESS The call succeeded and no subscribers returned errors + \retval KHM_ERROR_PARTIAL The call succeeded but at least one subscriber returned an error +*/ +KHMEXP khm_int32 KHMAPI kmq_send_message( + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * blob); + +/*! \brief Post a message + + The specified message will be posted to all the subscribers of the + message type. The function returns immediately. + + If you want to be able to wait for all the subscribers to finish + processing the message, you should use kmq_post_message_ex() + instead. + + \param[in] type The type of the message + \param[in] subtype The subtype + \param[in] uparam The khm_ui_4 parameter for the message + \param[in] blob The parameter blob for the message +*/ +KHMEXP khm_int32 KHMAPI kmq_post_message( + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * blob); + +/*! \brief Post a message and acquire a handle to the call. + + The specified message is posted to all the subscribers. In + addition, a handle is obtained for the call which can be used in + subsequent call to kmq_free_call() or kmq_wait(). + + Call kmq_free_call() to free the handle. + + \param[in] type The type of the message + \param[in] subtype The subtype + \param[in] uparam The khm_ui_4 parameter for the message + \param[in] blob The parameter blob for the message + \param[out] call Receives the call handle. Set to NULL if the call handle is not required. + + \see kmq_free_call() +*/ +KHMEXP khm_int32 KHMAPI kmq_post_message_ex( + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * blob, + kmq_call * call); + +/*! \brief Free a handle to a call obtained through kmq_post_message_ex() + + All call handles obtained through kmq_post_message_ex() must be + freed via a call to kmq_free_call(). +*/ +KHMEXP khm_int32 KHMAPI kmq_free_call(kmq_call call); + +/*! \brief Sends a <KMSG_SYSTEM,KMSG_SYSTEM_EXIT> message to the specified thread. + + The message itself will not be received by any callback function, + however, any kmq_dispatch() function that is currently active of + becomes active will exit with a KHM_ERROR_EXIT code. + kmq_send_thread_quit_message() will wait for this to happen before + returning. + + This function should not be called by the thread identified by the + \a thread parameter. + */ +KHMEXP khm_int32 KHMAPI kmq_send_thread_quit_message( + kmq_thread_id thread, + khm_ui_4 uparam); + +/*! \brief Post a <KMSG_SYSTEM,KMSG_SYSTEM_EXIT> message to the specified thread. + + The message itself will not be received by any callback function, + however, any kmq_dispatch() function that is currently active of + becomes active will exit with a KHM_ERROR_EXIT code. + kmq_post_thread_quit_message() will return immediately. + */ +KHMEXP khm_int32 KHMAPI kmq_post_thread_quit_message( + kmq_thread_id thread, + khm_ui_4 uparam, + kmq_call * call); + +KHMEXP khm_int32 KHMAPI kmq_get_next_response(kmq_call call, void ** resp); + +/*! \brief Check if a specific call has completed + + \return TRUE if the call has completed. FALSE otherwise. +*/ +KHMEXP khm_boolean KHMAPI kmq_has_completed(kmq_call call); + +/*! \brief Wait for a call to complete. + + Waits for the specified call to complete. If the call dispatched + to multiple recipients, the function waits for all dispatches to + complete. + + If the call has already completed, then the function returns + immediately. + + If more than one thread is waiting for a single message to + complete, then only one of them will be released when the message + compeltes. Each subsequent thread will be released as each + released thread calls kmq_free_call(). + + \param[in] call A handle to a call. + \param[in] timeout Specifies, in milliseconds, the amount of time + to wait for the call to complete. Specify INFINITE to wait + indefinitely. + + \retval KHM_ERROR_SUCCESS The call completed + \retval KHM_ERROR_TIMEOUT The timeout period expired + \retval KHM_ERROR_INVALID_PARAM One of the parameters were invalid. +*/ +KHMEXP khm_int32 KHMAPI kmq_wait(kmq_call call, kmq_timer timeout); + +/*! \brief Abort a call + + Abort a pending call. The call handle should have been obtained + using a prior call to kmq_post_message_ex(). + + Note that this function may not abort the call immediately. It + merely marks the message as being in an aborted state. It is upto + the individual handlers of the message to check if the message has + been aborted and act accordingly. + + The handlers are expected to call kmq_is_call_aborted() + periodicially during the processing of specially lengthy + operations during the course of handling a message. That function + will return \a TRUE if the last dispatched message is now in an + aborted state. In which case, the handler is expected to abort + handling the message and return control to the dispatcher. + */ +KHMEXP khm_int32 KHMAPI kmq_abort_call(kmq_call call); + +/*! \brief Check if the last dispatched message was aborted + + The sender of a message may abort it using a call to + kmq_abort_call(). This function checks if the last dispatched + message was aborted. + + A handler of a message is expected to call this function + periodically if handling the message is going to take a specially + long time (e.g. more than 5 or 10 seconds). If the message is + found to be aborted, the handler is expected to abort handling the + message, perform any necessary cleanup and return control to the + dispatcher. + + Doing this allows operations like new credentials acquisition to + be cleanly aborted by the user if she so wishes. Otherwise, + Network Identity Manager has to wait for the message to complete + processing since it has no means of cleanly terminating an + executing plug-in thread. +*/ +KHMEXP khm_boolean KHMAPI kmq_is_call_aborted(void); + +/*! \brief Sets the completion handler for a specified message type. + + \note Only one completion handler can exist for one message type. + Calling this function overwrites the previous completion + handler. +*/ +KHMEXP khm_int32 KHMAPI kmq_set_completion_handler( + khm_int32 type, + kmq_msg_completion_handler hander); + +/*@}*/ +#endif diff --git a/krb5-1-6/src/windows/identity/kmq/kmqconfig.csv b/krb5-1-6/src/windows/identity/kmq/kmqconfig.csv new file mode 100644 index 000000000..317baa60e --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/kmqconfig.csv @@ -0,0 +1,5 @@ +Name,Type,Value,Description +KMQ,KC_SPACE,0,Options for the credentials window + QueueDeadTimeout,KC_INT32,12000, + CallDeadTimeout,KC_INT32,8000, +KMQ,KC_ENDSPACE,0, diff --git a/krb5-1-6/src/windows/identity/kmq/kmqinternal.h b/krb5-1-6/src/windows/identity/kmq/kmqinternal.h new file mode 100644 index 000000000..8ae0ab67e --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/kmqinternal.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KMQINTERNAL_H +#define __KHIMAIRA_KMQINTERNAL_H + +#define _NIMLIB_ + +#include<windows.h> +#include<kmq.h> +#include<khlist.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<kconfig.h> + +#define NOEXPORT + +#include<utils.h> +#include<strsafe.h> + + + + +/*! \brief Message reference */ +typedef struct tag_kmq_message_ref { + kmq_message * msg; /*!< Message that we are referring + to */ + kmq_callback_t recipient; /*!< The recipient of the message */ + + LDCL(struct tag_kmq_message_ref); +} kmq_message_ref; + + + + +/*! \brief Message queue + + Each thread gets its own message queue. When a message is + broadcast to which there is a subscriber in a particular thread, a + reference to the message is placed in the message queue of the + thread. The dispatch procedure then dispatches the message as + described in the message reference. +*/ +typedef struct tag_kmq_queue { + kmq_thread_id thread; /*!< The thread id */ + + CRITICAL_SECTION cs; + HANDLE wait_o; + + khm_int32 load; /*!< Number of messages waiting to be + processed on this message queue. */ + kmq_timer last_post; /*!< Time the last message was + received */ + + khm_int32 flags; /*!< Flags. Currently, it's just KMQ_QUEUE_FLAG_DELETED */ + + /*Q*/ + QDCL(kmq_message_ref); /*!< Queue of message references */ + + /*Lnode*/ + LDCL(struct tag_kmq_queue); +} kmq_queue; + +#define KMQ_QUEUE_FLAG_DELETED 0x00000008 +#define KMQ_QUEUE_FLAG_DETACHING 0x00000010 + +/*! \brief Message subscription + + A subscription binds a recipient with a message type. These are + specific to a thread. I.e. a subscription that was made in one + thread will not receive messages in the context of another thread. +*/ +typedef struct tag_kmq_msg_subscription { + khm_int32 magic; /*!< Magic number. Should always be + ::KMQ_MSG_SUB_MAGIC */ + khm_int32 type; /*!< Type of message */ + khm_int32 rcpt_type; /*!< Type of recipient. One of + ::KMQ_RCPTTYPE_CB or + ::KMQ_RCPTTYPE_HWND */ + union { + kmq_callback_t cb; /*!< Callback if the subscription is + of callback type */ + HWND hwnd; /*!< Window handle if the subscription + is a windows message type */ + } recipient; + + kmq_queue * queue; /*!< Associated queue */ + + /*lnode*/ + LDCL(struct tag_kmq_msg_subscription); +} kmq_msg_subscription; + +#define KMQ_MSG_SUB_MAGIC 0x3821b58e + +/*! \brief Callback recipient type + + The recipient is a callback function */ +#define KMQ_RCPTTYPE_CB 1 + +/*! \brief Windows recipient type + + The recipient is a window */ +#define KMQ_RCPTTYPE_HWND 2 + + + + +/*! \brief A message type + */ +typedef struct tag_kmq_msg_type { + khm_int32 id; /*!< Identifier for the message + type. */ + kmq_msg_subscription * subs; /*!< The list of subscriptions */ + kmq_msg_completion_handler completion_handler; /*!< Completion + handler for the message type */ + + wchar_t * name; /*!< Name of the message type for + named types. Message type names are + language independant. */ + + /*Lnode*/ + LDCL(struct tag_kmq_msg_type); +} kmq_msg_type; + +/*! \brief The maximum number of message types + */ +#define KMQ_MSG_TYPE_MAX 255 + +/*! \brief Maximum number of characters in a message type name + + The count includes the terminating NULL + */ +#define KMQ_MAXCCH_TYPE_NAME 256 + +/*! \brief Maximum number of bytes in a message type name + + Type count includes the terminating NULL + */ +#define KMQ_MAXCB_TYPE_NAME (KMQ_MAXCCH_TYPE_NAME * sizeof(wchar_t)) + + + + +#define KMQ_CONF_SPACE_NAME L"KMQ" +#define KMQ_CONF_QUEUE_DEAD_TIMEOUT_NAME L"QueueDeadTimeout" +#define KMQ_CONF_CALL_DEAD_TIMEOUT_NAME L"CallDeadTimeout" + +extern CRITICAL_SECTION cs_kmq_global; +extern kmq_timer kmq_queue_dead_timeout; +extern kmq_timer kmq_call_dead_timeout; + +extern kmq_queue * queues; + +/* message type */ +extern CRITICAL_SECTION cs_kmq_types; +extern kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX+1]; + +void kmqint_init_msg_types(void); +void kmqint_exit_msg_types(void); +void kmqint_free_msg_type(int t); +void kmqint_msg_type_create(int t); +void kmqint_msg_type_add_sub(int t, kmq_msg_subscription *s); +void kmqint_msg_type_del_sub(kmq_msg_subscription *s); +kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd); +kmq_msg_subscription * kmqint_msg_type_del_sub_cb(khm_int32 t, kmq_callback_t cb); +khm_int32 kmqint_msg_publish(kmq_message * m, khm_boolean try_send); +khm_int32 kmqint_msg_type_set_handler(khm_int32 type, kmq_msg_completion_handler handler); +int kmqint_notify_msg_completion(kmq_message * m); + +/* consumer */ +extern DWORD kmq_tls_queue; + +void kmqint_post_queue(kmq_queue * q, kmq_message *m); +void kmqint_post(kmq_msg_subscription * s, kmq_message * m, khm_boolean try_send); +kmq_queue * kmqint_get_thread_queue(void); +void kmqint_get_queue_message_ref(kmq_queue * q, kmq_message_ref ** r); +void kmqint_put_message_ref(kmq_message_ref * r); + +/* publisher */ +extern CRITICAL_SECTION cs_kmq_msg; +extern CRITICAL_SECTION cs_kmq_msg_ref; + +kmq_message * kmqint_get_message(void); +void kmqint_put_message(kmq_message *m); + +void kmqint_init(void); +void kmqint_exit(void); +void kmqint_attach_this_thread(void); +void kmqint_detach_this_thread(void); + +khm_int32 kmqint_post_message_ex( + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * blob, + kmq_call * call, + khm_boolean try_send); + +int kmqint_call_completion_handler(kmq_msg_completion_handler h, + kmq_message * m); + +/* global */ +extern kconf_schema schema_kmqconfig[]; + +/* Lock hiearchy : + + cs_kmq_types + cs_kmq_msg + cs_kmq_msg_ref + cs_compl + cs_kmq_global + kmq_queue::cs + + If you have a level 'x' lock, you can obtain a level 'x+n' lock. + You can't obtain a 'x-n' lock if you already have a level 'x' lock. + If you don't have any locks, you can obtain any lock. + */ +#endif diff --git a/krb5-1-6/src/windows/identity/kmq/kmqmain.c b/krb5-1-6/src/windows/identity/kmq/kmqmain.c new file mode 100644 index 000000000..fecfc17fd --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/kmqmain.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmqinternal.h> + +void +kmq_process_attach(void) { + kmqint_init(); +} + +void +kmq_process_detach(void) { + kmqint_exit(); +} + +void +kmq_thread_attach(void) { + kmqint_attach_this_thread(); +} + +void +kmq_thread_detach(void) { + kmqint_detach_this_thread(); +} diff --git a/krb5-1-6/src/windows/identity/kmq/msgtype.c b/krb5-1-6/src/windows/identity/kmq/msgtype.c new file mode 100644 index 000000000..b5b23e920 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/msgtype.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmqinternal.h> + +CRITICAL_SECTION cs_kmq_types; + +kmq_msg_type *msg_types[KMQ_MSG_TYPE_MAX + 1]; +kmq_msg_type *all_msg_types = NULL; + +/*! \internal + \brief Initializes the message type data structures + \note called with cs_mkq_global held */ +void kmqint_init_msg_types(void) { + ZeroMemory(msg_types, sizeof(kmq_msg_type *) * (KMQ_MSG_TYPE_MAX + 1)); + InitializeCriticalSection(&cs_kmq_types); +} + +/*! \internal + \brief Frees up the message type data structures + \note called with cs_mkq_global held */ +void kmqint_exit_msg_types(void) { + int i; + + EnterCriticalSection(&cs_kmq_types); + for(i=0;i<KMQ_MSG_TYPE_MAX;i++) { + if(msg_types[i]) + kmqint_free_msg_type(i); + } + LeaveCriticalSection(&cs_kmq_types); + DeleteCriticalSection(&cs_kmq_types); +} + +/*! \internal + \brief Notifies that the message has completed + + \return Zero if the completion handling is done. Nonzero if the + handling is queued. + */ +int kmqint_notify_msg_completion(kmq_message * m) { + kmq_msg_type * mt; + kmq_msg_completion_handler h; + + /* doing it this way to elude race conditions without + obtaining a lock */ + + mt = msg_types[m->type]; + if(mt == NULL) + return 0; + h = mt->completion_handler; + + /* handler is set to NULL before freeing type */ + if(h == NULL || msg_types[m->type] == NULL) + return 0; + + return kmqint_call_completion_handler(h,m); +} + +/* called with cs_mkq_global && cs_kmq_types held */ +void kmqint_free_msg_type(int t) { + kmq_msg_type * pt; + kmq_msg_subscription * s; + + pt = msg_types[t]; + + msg_types[t] = NULL; + + if (pt == NULL) + return; + + /* all the subscriptions attached to a message type are owned by + the message type */ + LPOP(&pt->subs, &s); + while(s) { + s->magic = 0; + + PFREE(s); + + LPOP(&pt->subs, &s); + } + + pt->completion_handler = NULL; + + LDELETE(&all_msg_types, pt); + + PFREE(pt); +} + +/*! \internal + \brief Create a message type + \note Obtains ::cs_kmq_types + */ +void kmqint_msg_type_create(int t) { + if(t < 0 || t > KMQ_MSG_TYPE_MAX) + return; + + EnterCriticalSection(&cs_kmq_types); + if(!msg_types[t]) { + kmq_msg_type * mt; + mt = PMALLOC(sizeof(kmq_msg_type)); + ZeroMemory(mt, sizeof(kmq_msg_type)); + mt->id = t; + LINIT(mt); + mt->subs = NULL; + msg_types[t] = mt; + + LPUSH(&all_msg_types, mt); + } + LeaveCriticalSection(&cs_kmq_types); +} + +KHMEXP khm_int32 KHMAPI kmq_register_type(wchar_t * name, + khm_int32 * new_id) +{ + int i; + khm_int32 rv = KHM_ERROR_SUCCESS; + BOOL registered = FALSE; + int first_free = 0; + size_t sz; + + if(FAILED(StringCbLength(name, KMQ_MAXCB_TYPE_NAME, &sz)) || + sz == 0) + return KHM_ERROR_INVALID_PARAM; + sz += sizeof(wchar_t); + + EnterCriticalSection(&cs_kmq_types); + for(i=KMSGBASE_USER; i <= KMQ_MSG_TYPE_MAX; i++) { + if(msg_types[i] == NULL) { + if(first_free == 0) + first_free = i; + /* continue searching since we might find that this type + is already registered. */ + } else { + if(msg_types[i]->name != NULL && + !wcscmp(msg_types[i]->name, name)) { + + registered = TRUE; + if (new_id) + *new_id = i; + break; + } + } + } + + if(registered) { + rv = KHM_ERROR_EXISTS; + } else if(first_free == 0) { + rv = KHM_ERROR_NO_RESOURCES; + } else { + kmqint_msg_type_create(first_free); + msg_types[first_free]->name = PMALLOC(sz); + StringCbCopy(msg_types[first_free]->name, sz, name); + + if(new_id != NULL) + *new_id = first_free; + } + LeaveCriticalSection(&cs_kmq_types); + + return rv; +} + +KHMEXP khm_int32 KHMAPI kmq_find_type(wchar_t * name, khm_int32 * id) +{ + int i; + + EnterCriticalSection(&cs_kmq_types); + for(i=KMSGBASE_USER; i <= KMQ_MSG_TYPE_MAX; i++) { + if(msg_types[i] != NULL && msg_types[i]->name != NULL) { + if(!wcscmp(msg_types[i]->name, name)) + break; + } + } + LeaveCriticalSection(&cs_kmq_types); + + if(i <= KMQ_MSG_TYPE_MAX) { + if(id != NULL) + *id = i; + return KHM_ERROR_SUCCESS; + } + + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI kmq_unregister_type(khm_int32 id) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(id < KMSGBASE_USER || id > KMQ_MSG_TYPE_MAX) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_kmq_types); + if(msg_types[id] != NULL) { + EnterCriticalSection(&cs_kmq_global); + kmqint_free_msg_type(id); + LeaveCriticalSection(&cs_kmq_global); + } else { + rv = KHM_ERROR_NOT_FOUND; + } + LeaveCriticalSection(&cs_kmq_types); + + return rv; +} + +/*! \internal + \brief Adds a subscription to a message type + \note Obtains ::cs_kmq_types + */ +void kmqint_msg_type_add_sub(int t, kmq_msg_subscription *s) { + kmq_msg_subscription * ts; + + if(t < 0 || t > KMQ_MSG_TYPE_MAX) + return; + + if(!msg_types[t]) + kmqint_msg_type_create(t); + + EnterCriticalSection(&cs_kmq_types); + s->type = t; + /* check if we already have this subscription */ + ts = msg_types[t]->subs; + while(ts) { + if((ts->rcpt_type == s->rcpt_type) && + (((ts->rcpt_type == KMQ_RCPTTYPE_CB) && (ts->recipient.cb == s->recipient.cb)) || + ((ts->rcpt_type == KMQ_RCPTTYPE_HWND) && (ts->recipient.hwnd == s->recipient.hwnd)))) + break; + ts = LNEXT(ts); + } + /* add it if we didn't find it */ + if(!ts) { + LPUSH(&msg_types[t]->subs, s); + } + LeaveCriticalSection(&cs_kmq_types); +} + +/*! \internal + \brief Delete a subscription + \note Obtains ::cs_kmq_types + */ +void kmqint_msg_type_del_sub(kmq_msg_subscription *s) { + int t = s->type; + + EnterCriticalSection(&cs_kmq_types); + if(msg_types[t]) { + LDELETE(&msg_types[t]->subs,s); + } + LeaveCriticalSection(&cs_kmq_types); +} + + +/*! \internal + \brief Deletes a window subscription from a message type + \note Obtains ::cs_kmq_types +*/ +kmq_msg_subscription * kmqint_msg_type_del_sub_hwnd(khm_int32 t, HWND hwnd) { + kmq_msg_subscription *s = NULL; + + if(t < 0 || t > KMQ_MSG_TYPE_MAX) + return NULL; + + EnterCriticalSection(&cs_kmq_types); + if(msg_types[t]) { + s = msg_types[t]->subs; + while(s) { + kmq_msg_subscription * n = LNEXT(s); + if(s->rcpt_type == KMQ_RCPTTYPE_HWND && s->recipient.hwnd == hwnd) { + /*TODO: do more here? */ + LDELETE(&msg_types[t]->subs, s); + break; + } + s = n; + } + } + LeaveCriticalSection(&cs_kmq_types); + + return s; +} + +/*! \internal + \brief Delete a callback from a message type + \note Obtains ::cs_kmq_types, ::cs_kmq_global + */ +kmq_msg_subscription * kmqint_msg_type_del_sub_cb(khm_int32 t, kmq_callback_t cb) { + kmq_msg_subscription *s; + kmq_queue *q; + + if(t < 0 || t > KMQ_MSG_TYPE_MAX) + return NULL; + + if(!msg_types[t]) + return NULL; + + q = kmqint_get_thread_queue(); + + EnterCriticalSection(&cs_kmq_types); + s = msg_types[t]->subs; + while(s) { + kmq_msg_subscription * n = LNEXT(s); + if(s->rcpt_type == KMQ_RCPTTYPE_CB && + s->recipient.cb == cb && + s->queue == q) { + /*TODO: do more here? */ + LDELETE(&msg_types[t]->subs, s); + break; + } + s = n; + } + LeaveCriticalSection(&cs_kmq_types); + + return s; +} + +/*! \internal + \brief Publish a message + \note Obtains ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs, ::cs_kmq_msg + */ +khm_int32 kmqint_msg_publish(kmq_message * m, khm_boolean try_send) { + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(msg_types[m->type]) { + kmq_msg_type *t; + kmq_msg_subscription * s; + + EnterCriticalSection(&cs_kmq_types); + EnterCriticalSection(&cs_kmq_msg); + t = msg_types[m->type]; + s = t->subs; + while(s) { + kmqint_post(s, m, try_send); + s = LNEXT(s); + } + + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + + LeaveCriticalSection(&cs_kmq_msg); + LeaveCriticalSection(&cs_kmq_types); + + } else { + EnterCriticalSection(&cs_kmq_msg); + kmqint_put_message(m); + LeaveCriticalSection(&cs_kmq_msg); + } + return rv; +} + +/*! \internal + \brief Sets the completion handler for a message type + \note Obtains ::cs_kmq_types + */ +khm_int32 kmqint_msg_type_set_handler(khm_int32 type, kmq_msg_completion_handler handler) { + + if (type == KMSG_SYSTEM) + return KHM_ERROR_INVALID_PARAM; + + if(!msg_types[type]) { + if (handler) + kmqint_msg_type_create(type); + else + return KHM_ERROR_SUCCESS; + } + + if(!msg_types[type]) + return KHM_ERROR_NO_RESOURCES; + + EnterCriticalSection(&cs_kmq_types); + msg_types[type]->completion_handler = handler; + LeaveCriticalSection(&cs_kmq_types); + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/kmq/publisher.c b/krb5-1-6/src/windows/identity/kmq/publisher.c new file mode 100644 index 000000000..754288811 --- /dev/null +++ b/krb5-1-6/src/windows/identity/kmq/publisher.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<kmqinternal.h> + +CRITICAL_SECTION cs_kmq_msg; +kmq_message * msg_free = NULL; +kmq_message * msg_active = NULL; + +#ifdef DEBUG + +#include<stdio.h> + +void +kmqint_dump_publisher(FILE * f) { + + int n_free = 0; + int n_active = 0; + kmq_message * m; + + EnterCriticalSection(&cs_kmq_msg); + + fprintf(f, "qp0\t*** Free Messages ***\n"); + fprintf(f, "qp1\tAddress\n"); + + m = msg_free; + while(m) { + n_free++; + + fprintf(f, "qp2\t0x%p\n", m); + + m = LNEXT(m); + } + + fprintf(f, "qp3\tTotal free messages : %d\n", n_free); + + fprintf(f, "qp4\t*** Active Messages ***\n"); + fprintf(f, "qp5\tAddress\tType\tSubtype\tuParam\tvParam\tnSent\tnCompleted\tnFailed\twait_o\trefcount\n"); + + m = msg_active; + while(m) { + + n_active++; + + fprintf(f, "qp6\t0x%p\t%d\t%d\t0x%x\t0x%p\t%d\t%d\t%d\t0x%p\t%d\n", + m, + (int) m->type, + (int) m->subtype, + (unsigned int) m->uparam, + m->vparam, + (int) m->nSent, + (int) m->nCompleted, + (int) m->nFailed, + (void *) m->wait_o, + (int) m->refcount); + + m = LNEXT(m); + } + + fprintf(f, "qp7\tTotal number of active messages = %d\n", n_active); + + fprintf(f, "qp8\t--- End ---\n"); + + LeaveCriticalSection(&cs_kmq_msg); + +} + +#endif + +/*! \internal + \brief Get a message object + \note called with ::cs_kmq_msg held */ +kmq_message * +kmqint_get_message(void) { + kmq_message * m; + + LPOP(&msg_free,&m); + if(!m) { + /* allocate one */ + m = PMALLOC(sizeof(kmq_message)); + } + ZeroMemory((void*)m, sizeof(kmq_message)); + + LPUSH(&msg_active, m); + + return m; +} + +/*! \internal + \brief Frees a message object + \note called with ::cs_kmq_msg held + */ +void +kmqint_put_message(kmq_message *m) { + int queued; + /* we can only free a message if the refcount is zero. + Otherwise we have to wait until the call is freed. */ + if(m->refcount == 0) { + LDELETE(&msg_active, m); + LeaveCriticalSection(&cs_kmq_msg); + queued = kmqint_notify_msg_completion(m); + EnterCriticalSection(&cs_kmq_msg); + if (!queued) { + if(m->err_ctx) { + kherr_release_context(m->err_ctx); + m->err_ctx = NULL; + } + if(m->wait_o) { + CloseHandle(m->wait_o); + m->wait_o = NULL; + } + LPUSH(&msg_free,m); + } + } else if(m->wait_o) { + SetEvent(m->wait_o); + } +} + +/*! \internal + \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs + */ +KHMEXP khm_int32 KHMAPI +kmq_send_message(khm_int32 type, khm_int32 subtype, + khm_ui_4 uparam, void * blob) { + kmq_call c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kmqint_post_message_ex(type, subtype, uparam, blob, &c, TRUE); + if(KHM_FAILED(rv)) + return rv; + + rv = kmq_wait(c, INFINITE); + if(KHM_SUCCEEDED(rv) && c->nFailed > 0) + rv = KHM_ERROR_PARTIAL; + + kmq_free_call(c); + + return rv; +} + +/*! \internal + \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs + */ +KHMEXP khm_int32 KHMAPI +kmq_post_message(khm_int32 type, khm_int32 subtype, + khm_ui_4 uparam, void * blob) { + return kmqint_post_message_ex(type, subtype, uparam, blob, NULL, FALSE); +} + +/*! \internal + \brief Frees a call + \note Obtains ::cs_kmq_msg + */ +KHMEXP khm_int32 KHMAPI +kmq_free_call(kmq_call call) { + kmq_message * m; + + m = call; + + EnterCriticalSection(&cs_kmq_msg); + m->refcount--; + if(!m->refcount) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + + return KHM_ERROR_SUCCESS; +} + +/*! \internal + \note Obtains ::cs_kmq_msg, ::cs_kmq_types, ::cs_kmq_msg_ref, kmq_queue::cs + */ +khm_int32 +kmqint_post_message_ex(khm_int32 type, khm_int32 subtype, khm_ui_4 uparam, + void * blob, kmq_call * call, khm_boolean try_send) +{ + kmq_message * m; + kherr_context * ctx; + + EnterCriticalSection(&cs_kmq_msg); + m = kmqint_get_message(); + LeaveCriticalSection(&cs_kmq_msg); + + m->type = type; + m->subtype = subtype; + m->uparam = uparam; + m->vparam = blob; + + m->timeSent = GetTickCount(); + m->timeExpire = m->timeSent + kmq_call_dead_timeout; + + ctx = kherr_peek_context(); + if (ctx) { + if (ctx->flags & KHERR_CF_TRANSITIVE) { + m->err_ctx = ctx; + /* leave it held */ + } else { + kherr_release_context(ctx); + } + } + + if(call) { + m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL); + *call = m; + m->refcount++; + } else + m->wait_o = NULL; + + kmqint_msg_publish(m, try_send); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kmq_post_message_ex(khm_int32 type, khm_int32 subtype, + khm_ui_4 uparam, void * blob, kmq_call * call) +{ + return kmqint_post_message_ex(type, subtype, uparam, blob, call, FALSE); +} + +KHMEXP khm_int32 KHMAPI +kmq_abort_call(kmq_call call) +{ + /* TODO: Implement this */ + return KHM_ERROR_NOT_IMPLEMENTED; +} + +/*! \internal +*/ +KHMEXP khm_int32 KHMAPI +kmq_post_sub_msg(khm_handle sub, khm_int32 type, khm_int32 subtype, + khm_ui_4 uparam, void * vparam) +{ + return kmq_post_sub_msg_ex(sub, type, subtype, uparam, vparam, NULL); +} + +/*! \internal +*/ +khm_int32 +kmqint_post_sub_msg_ex(khm_handle sub, khm_int32 type, khm_int32 subtype, + khm_ui_4 uparam, void * vparam, + kmq_call * call, khm_boolean try_send) +{ + kmq_message * m; + kherr_context * ctx; + + EnterCriticalSection(&cs_kmq_msg); + m = kmqint_get_message(); + LeaveCriticalSection(&cs_kmq_msg); + + m->type = type; + m->subtype = subtype; + m->uparam = uparam; + m->vparam = vparam; + + m->timeSent = GetTickCount(); + m->timeExpire = m->timeSent + kmq_call_dead_timeout; + + ctx = kherr_peek_context(); + if (ctx) { + if (ctx->flags & KHERR_CF_TRANSITIVE) { + m->err_ctx = ctx; + /* leave it held */ + } else { + kherr_release_context(ctx); + } + } + + if(call) { + m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL); + *call = m; + m->refcount++; + } else + m->wait_o = NULL; + + if (try_send) + EnterCriticalSection(&cs_kmq_types); + EnterCriticalSection(&cs_kmq_msg); + kmqint_post((kmq_msg_subscription *) sub, m, try_send); + + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + if (try_send) + LeaveCriticalSection(&cs_kmq_types); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kmq_post_sub_msg_ex(khm_handle sub, khm_int32 type, khm_int32 subtype, + khm_ui_4 uparam, void * vparam, kmq_call * call) +{ + return kmqint_post_sub_msg_ex(sub, type, subtype, + uparam, vparam, call, FALSE); +} + +khm_int32 +kmqint_post_subs_msg_ex(khm_handle * subs, khm_size n_subs, khm_int32 type, + khm_int32 subtype, khm_ui_4 uparam, void * vparam, + kmq_call * call, khm_boolean try_send) +{ + kmq_message * m; + kherr_context * ctx; + khm_size i; + + if(n_subs == 0) + return KHM_ERROR_SUCCESS; + + EnterCriticalSection(&cs_kmq_msg); + m = kmqint_get_message(); + LeaveCriticalSection(&cs_kmq_msg); + + m->type = type; + m->subtype = subtype; + m->uparam = uparam; + m->vparam = vparam; + + m->timeSent = GetTickCount(); + m->timeExpire = m->timeSent + kmq_call_dead_timeout; + + ctx = kherr_peek_context(); + if (ctx) { + if (ctx->flags & KHERR_CF_TRANSITIVE) { + m->err_ctx = ctx; + /* leave it held */ + } else { + kherr_release_context(ctx); + } + } + + if(call) { + m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL); + *call = m; + m->refcount++; + } else + m->wait_o = NULL; + + if (try_send) + EnterCriticalSection(&cs_kmq_types); + EnterCriticalSection(&cs_kmq_msg); + for(i=0;i<n_subs;i++) { + kmqint_post((kmq_msg_subscription *) subs[i], m, try_send); + } + + if(m->nCompleted + m->nFailed == m->nSent) { + kmqint_put_message(m); + } + LeaveCriticalSection(&cs_kmq_msg); + if (try_send) + EnterCriticalSection(&cs_kmq_types); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kmq_post_subs_msg(khm_handle * subs, + khm_size n_subs, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam) +{ + return kmqint_post_subs_msg_ex(subs, + n_subs, + type, + subtype, + uparam, + vparam, + NULL, + FALSE); +} + +KHMEXP khm_int32 KHMAPI +kmq_post_subs_msg_ex(khm_handle * subs, + khm_int32 n_subs, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam, + kmq_call * call) +{ + return kmqint_post_subs_msg_ex(subs, n_subs, type, subtype, + uparam, vparam, call, FALSE); +} + +KHMEXP khm_int32 KHMAPI +kmq_send_subs_msg(khm_handle *subs, + khm_int32 n_subs, + khm_int32 type, + khm_int32 subtype, + khm_ui_4 uparam, + void * vparam) +{ + kmq_call c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kmqint_post_subs_msg_ex(subs, n_subs, type, subtype, + uparam, vparam, &c, TRUE); + if(KHM_FAILED(rv)) + return rv; + + rv = kmq_wait(c, INFINITE); + if(KHM_SUCCEEDED(rv) && c->nFailed > 0) + rv = KHM_ERROR_PARTIAL; + + kmq_free_call(c); + + return rv; +} + +/*! \internal +*/ +KHMEXP khm_int32 KHMAPI +kmq_send_sub_msg(khm_handle sub, khm_int32 type, khm_int32 subtype, + khm_ui_4 uparam, void * vparam) +{ + kmq_call c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kmqint_post_sub_msg_ex(sub, type, subtype, uparam, vparam, &c, TRUE); + if(KHM_FAILED(rv)) + return rv; + + rv = kmq_wait(c, INFINITE); + if(KHM_SUCCEEDED(rv) && c->nFailed > 0) + rv = KHM_ERROR_PARTIAL; + + kmq_free_call(c); + + return rv; +} + +/*! \internal + \note Obtains ::cs_kmq_global, ::cs_kmq_msg, ::cs_kmq_msg_ref, kmq_queue::cs + */ +KHMEXP khm_int32 KHMAPI +kmq_send_thread_quit_message(kmq_thread_id thread, khm_ui_4 uparam) { + kmq_call c; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kmq_post_thread_quit_message(thread, uparam, &c); + if(KHM_FAILED(rv)) + return rv; + + rv = kmq_wait(c, INFINITE); + + kmq_free_call(c); + + return rv; +} + +/*! \internal + \note Obtains ::cs_kmq_global, ::cs_kmq_msg, ::cs_kmq_msg_ref, kmq_queue::cs + */ +KHMEXP khm_int32 KHMAPI +kmq_post_thread_quit_message(kmq_thread_id thread, + khm_ui_4 uparam, kmq_call * call) { + kmq_message * m; + kmq_queue * q; + + EnterCriticalSection(&cs_kmq_global); + q = queues; + while(q) { + if(q->thread == thread) + break; + q = LNEXT(q); + } + LeaveCriticalSection(&cs_kmq_global); + + if(!q) + return KHM_ERROR_NOT_FOUND; + + EnterCriticalSection(&cs_kmq_msg); + m = kmqint_get_message(); + LeaveCriticalSection(&cs_kmq_msg); + + m->type = KMSG_SYSTEM; + m->subtype = KMSG_SYSTEM_EXIT; + m->uparam = uparam; + m->vparam = NULL; + + m->timeSent = GetTickCount(); + m->timeExpire = m->timeSent + kmq_call_dead_timeout; + + if(call) { + m->wait_o = CreateEvent(NULL,FALSE,FALSE,NULL); + *call = m; + m->refcount++; + } else + m->wait_o = NULL; + + kmqint_post_queue(q, m); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +kmq_get_next_response(kmq_call call, void ** resp) { + /* TODO: Implement this */ + return 0; +} + +KHMEXP khm_boolean KHMAPI +kmq_has_completed(kmq_call call) { + khm_boolean completed; + + EnterCriticalSection(&cs_kmq_msg); + completed = (call->nCompleted + call->nFailed == call->nSent); + LeaveCriticalSection(&cs_kmq_msg); + + return completed; +} + +KHMEXP khm_int32 KHMAPI +kmq_wait(kmq_call call, kmq_timer timeout) { + kmq_message * m = call; + DWORD rv; + /*TODO: check for call free */ + + if(m && m->wait_o) { + rv = WaitForSingleObject(m->wait_o, timeout); + if(rv == WAIT_OBJECT_0) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_TIMEOUT; + } else + return KHM_ERROR_INVALID_PARAM; +} + +/*! \internal + \note Obtains ::cs_kmq_types + */ +KHMEXP khm_int32 KHMAPI +kmq_set_completion_handler(khm_int32 type, + kmq_msg_completion_handler handler) { + return kmqint_msg_type_set_handler(type, handler); +} + + + diff --git a/krb5-1-6/src/windows/identity/nidmgrdll/Makefile b/krb5-1-6/src/windows/identity/nidmgrdll/Makefile new file mode 100644 index 000000000..096a5ef2c --- /dev/null +++ b/krb5-1-6/src/windows/identity/nidmgrdll/Makefile @@ -0,0 +1,126 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=nidmgrdll +!include <../config/Makefile.w32> + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +DLLFILE=$(BINDIR)\nidmgr64.dll +LIBFILE=$(LIBDIR)\nidmgr64.lib +!else +DLLFILE=$(BINDIR)\nidmgr32.dll +LIBFILE=$(LIBDIR)\nidmgr32.lib +!endif + +UTILDIR=$(OBJDIR)\util + +KHERRDIR=$(OBJDIR)\kherr + +KCONFIGDIR=$(OBJDIR)\kconfig + +KMQDIR=$(OBJDIR)\kmq + +KCDBDIR=$(OBJDIR)\kcreddb + +KMMDIR=$(OBJDIR)\kmm + +UIDIR=$(OBJDIR)\uilib + +OBJFILES= \ + $(OBJ)\dllmain.obj \ + $(UTILDIR)\hashtable.obj \ + $(UTILDIR)\sync.obj \ + $(UTILDIR)\mstring.obj \ + $(UTILDIR)\perfstat.obj \ + $(KHERRDIR)\kherrmain.obj \ + $(KHERRDIR)\kherr.obj \ + $(KCONFIGDIR)\kconfigmain.obj \ + $(KCONFIGDIR)\api.obj \ + $(KMQDIR)\kmqmain.obj \ + $(KMQDIR)\init.obj \ + $(KMQDIR)\msgtype.obj \ + $(KMQDIR)\consumer.obj \ + $(KMQDIR)\publisher.obj \ + $(KMQDIR)\kmqconfig.obj \ + $(KCDBDIR)\buf.obj \ + $(KCDBDIR)\attrib.obj \ + $(KCDBDIR)\credential.obj \ + $(KCDBDIR)\credset.obj \ + $(KCDBDIR)\credtype.obj \ + $(KCDBDIR)\identity.obj \ + $(KCDBDIR)\init.obj \ + $(KCDBDIR)\kcreddbmain.obj \ + $(KCDBDIR)\type.obj \ + $(KCDBDIR)\kcdbconfig.obj \ + $(KMMDIR)\kmmmain.obj \ + $(KMMDIR)\kmm.obj \ + $(KMMDIR)\kmm_plugin.obj \ + $(KMMDIR)\kmm_module.obj \ + $(KMMDIR)\kmm_reg.obj \ + $(KMMDIR)\kmm_registrar.obj \ + $(KMMDIR)\kmmconfig.obj \ + $(UIDIR)\rescache.obj \ + $(UIDIR)\action.obj \ + $(UIDIR)\creddlg.obj \ + $(UIDIR)\alert.obj \ + $(UIDIR)\propsheet.obj \ + $(UIDIR)\propwnd.obj \ + $(UIDIR)\uilibmain.obj \ + $(UIDIR)\actiondef.obj \ + $(UIDIR)\acceldef.obj \ + $(UIDIR)\configui.obj \ + $(UIDIR)\trackerwnd.obj \ + $(UIDIR)\uibind.obj \ + $(UIDIR)\version.obj + +RESFILES= \ + $(OBJ)\nidmgrdll.res \ + $(KCDBDIR)\kcredres.res \ + $(KMMDIR)\kmm_msgs.res \ + +SDKLIBFILES= \ + advapi32.lib \ + strsafe.lib \ + comctl32.lib \ + shlwapi.lib \ + version.lib + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +SCLIB=bufferoverflowu.lib +!else +SCLIB= +!endif + +$(DLLFILE): $(OBJFILES) $(RESFILES) + $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES) $(SCLIB) + $(_VC_MANIFEST_EMBED_DLL) + $(_VC_MANIFEST_CLEAN) + +all: mkdirs $(DLLFILE) + +clean:: + if exist $(DLLFILE) $(RM) $(DLLFILE) + if exist $(DLLFILE).manifest $(RM) $(DLLFILE).manifest + diff --git a/krb5-1-6/src/windows/identity/nidmgrdll/Makefile.w2k b/krb5-1-6/src/windows/identity/nidmgrdll/Makefile.w2k new file mode 100644 index 000000000..9dfe2dffb --- /dev/null +++ b/krb5-1-6/src/windows/identity/nidmgrdll/Makefile.w2k @@ -0,0 +1,120 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=nidmgrdll.w2k +!include <../config/Makefile.w2k> + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +DLLFILE=$(BINDIR)\nidmgr64.dll +LIBFILE=$(LIBDIR)\nidmgr64.lib +!else +DLLFILE=$(BINDIR)\nidmgr32.dll +LIBFILE=$(LIBDIR)\nidmgr32.lib +!endif + +UTILDIR=$(OBJDIR)\util + +KHERRDIR=$(OBJDIR)\kherr + +KCONFIGDIR=$(OBJDIR)\kconfig + +KMQDIR=$(OBJDIR)\kmq + +KCDBDIR=$(OBJDIR)\kcreddb + +KMMDIR=$(OBJDIR)\kmm + +UIDIR=$(OBJDIR)\uilib.w2k + +OBJFILES= \ + $(OBJ)\dllmain.obj \ + $(UTILDIR)\hashtable.obj \ + $(UTILDIR)\sync.obj \ + $(UTILDIR)\mstring.obj \ + $(UTILDIR)\perfstat.obj \ + $(KHERRDIR)\kherrmain.obj \ + $(KHERRDIR)\kherr.obj \ + $(KCONFIGDIR)\kconfigmain.obj \ + $(KCONFIGDIR)\api.obj \ + $(KMQDIR)\kmqmain.obj \ + $(KMQDIR)\init.obj \ + $(KMQDIR)\msgtype.obj \ + $(KMQDIR)\consumer.obj \ + $(KMQDIR)\publisher.obj \ + $(KMQDIR)\kmqconfig.obj \ + $(KCDBDIR)\buf.obj \ + $(KCDBDIR)\attrib.obj \ + $(KCDBDIR)\credential.obj \ + $(KCDBDIR)\credset.obj \ + $(KCDBDIR)\credtype.obj \ + $(KCDBDIR)\identity.obj \ + $(KCDBDIR)\init.obj \ + $(KCDBDIR)\kcreddbmain.obj \ + $(KCDBDIR)\type.obj \ + $(KCDBDIR)\kcdbconfig.obj \ + $(KMMDIR)\kmmmain.obj \ + $(KMMDIR)\kmm.obj \ + $(KMMDIR)\kmm_plugin.obj \ + $(KMMDIR)\kmm_module.obj \ + $(KMMDIR)\kmm_reg.obj \ + $(KMMDIR)\kmm_registrar.obj \ + $(KMMDIR)\kmmconfig.obj \ + $(UIDIR)\rescache.obj \ + $(UIDIR)\action.obj \ + $(UIDIR)\creddlg.obj \ + $(UIDIR)\alert.obj \ + $(UIDIR)\propsheet.obj \ + $(UIDIR)\propwnd.obj \ + $(UIDIR)\uilibmain.obj \ + $(UIDIR)\actiondef.obj \ + $(UIDIR)\acceldef.obj \ + $(UIDIR)\configui.obj \ + $(UIDIR)\trackerwnd.obj \ + $(UIDIR)\version.obj + +RESFILES= \ + $(OBJ)\nidmgrdll.res \ + $(KCDBDIR)\kcredres.res \ + $(KMMDIR)\kmm_msgs.res \ + +SDKLIBFILES= \ + advapi32.lib \ + strsafe.lib \ + comctl32.lib \ + shlwapi.lib \ + version.lib + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +SCLIB=bufferoverflowu.lib +!else +SCLIB= +!endif + +$(DLLFILE): $(OBJFILES) $(RESFILES) + $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES) $(SCLIB) + +all: mkdirs $(DLLFILE) + +clean:: + $(RM) $(DLLFILE) diff --git a/krb5-1-6/src/windows/identity/nidmgrdll/dllmain.c b/krb5-1-6/src/windows/identity/nidmgrdll/dllmain.c new file mode 100644 index 000000000..696911df4 --- /dev/null +++ b/krb5-1-6/src/windows/identity/nidmgrdll/dllmain.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<windows.h> + +/* forward dcls */ +void +kherr_process_attach(void); + +void +kherr_process_detach(void); + +void +kherr_thread_attach(void); + +void +kherr_thread_detach(void); + +void +kconfig_process_attach(void); + +void +kconfig_process_detach(void); + +void +kmq_process_attach(void); + +void +kmq_process_detach(void); + +void +kmq_thread_attach(void); + +void +kmq_thread_detach(void); + +void +kcdb_process_attach(HINSTANCE); + +void +kcdb_process_detach(void); + +void +kmm_process_attach(HINSTANCE); + +void +kmm_process_detach(void); + +void +uilib_process_attach(void); + +void +uilib_process_detach(void); + + +BOOL WINAPI DllMain( + HINSTANCE hinstDLL, // handle to DLL module + DWORD fdwReason, // reason for calling function + LPVOID lpReserved ) // reserved +{ + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + kherr_process_attach(); + kconfig_process_attach(); + kmq_process_attach(); + kcdb_process_attach(hinstDLL); + kmm_process_attach(hinstDLL); + uilib_process_attach(); + break; + + case DLL_PROCESS_DETACH: + kherr_process_detach(); + kconfig_process_detach(); + kmq_process_detach(); + kcdb_process_detach(); + kmm_process_detach(); + uilib_process_detach(); + break; + + case DLL_THREAD_ATTACH: + kherr_thread_attach(); + kmq_thread_attach(); + break; + + case DLL_THREAD_DETACH: + kherr_thread_detach(); + kmq_thread_detach(); + break; + } + return TRUE; +} diff --git a/krb5-1-6/src/windows/identity/nidmgrdll/nidmgrdll.rc b/krb5-1-6/src/windows/identity/nidmgrdll/nidmgrdll.rc new file mode 100644 index 000000000..b4e0a9e72 --- /dev/null +++ b/krb5-1-6/src/windows/identity/nidmgrdll/nidmgrdll.rc @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<afxres.h> +#include<netidmgr_intver.h> + +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif + +1 VERSIONINFO + FILEVERSION KH_VERSION_LIST + PRODUCTVERSION KH_VERSION_LIST + FILEFLAGSMASK 0x17L + FILEFLAGS KH_VER_FILEFLAGS + FILEOS KH_VER_FILEOS + FILETYPE KH_VER_FILETYPEDLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", KH_VERSTR_COMPANY_1033 + VALUE "FileDescription", "Network Identity Manager API" + VALUE "FileVersion", KH_VERSTR_VERSION_1033 + VALUE "InternalName", "nidmgr32" + VALUE "LegalCopyright", KH_VERSTR_COPYRIGHT_1033 + VALUE "OriginalFilename", "nidmgr32.dll" + VALUE "ProductName", "Network Identity Manager" + VALUE "ProductVersion", KH_VERSTR_PRODUCT_1033 +#ifdef KH_VERSTR_COMMENT_1033 + VALUE "Comments", KH_VERSTR_COMMENT_1033 +#endif +#ifdef KH_VERSTR_PRIVATE_1033 + VALUE "PrivateBuild", KH_VERSTR_PRIVATE_1033 +#endif +#ifdef KH_VERSTR_SPECIAL_1033 + VALUE "SpecialBuild", KH_VERSTR_SPECIAL_1033 +#endif + END + END + +/* Language independent */ + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END + +END diff --git a/krb5-1-6/src/windows/identity/plugins/common/Makefile b/krb5-1-6/src/windows/identity/plugins/common/Makefile new file mode 100644 index 000000000..6b827dc3e --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/common/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=plugins\common +!include <../../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\krb5common.h \ + $(INCDIR)\dynimport.h + +OBJFILES= \ + $(LIBDIR)\krb5common.obj \ + $(LIBDIR)\dynimport.obj + +all: mkdirs $(INCFILES) $(OBJFILES) + +clean:: + if exist "$(INCDIR)" $(RM) $(INCFILES) + if exist "$(LIBDIR)" $(RM) $(OBJFILES) + +{}.c{$(LIBDIR)}.obj: + $(C2OBJ) diff --git a/krb5-1-6/src/windows/identity/plugins/common/dynimport.c b/krb5-1-6/src/windows/identity/plugins/common/dynimport.c new file mode 100644 index 000000000..ea8bbf905 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/common/dynimport.c @@ -0,0 +1,479 @@ +/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* Copyright (c) 2007 Secure Endpoints Inc. +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies +* of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +/* $Id$ */ + +#include<windows.h> +#include<netidmgr.h> +#include<dynimport.h> + +HINSTANCE hKrb4 = 0; +HINSTANCE hKrb5 = 0; +HINSTANCE hKrb524 = 0; +HINSTANCE hSecur32 = 0; +HINSTANCE hComErr = 0; +HINSTANCE hService = 0; +HINSTANCE hProfile = 0; +HINSTANCE hPsapi = 0; +HINSTANCE hToolHelp32 = 0; +HINSTANCE hCCAPI = 0; + +DWORD AfsAvailable = 0; + +// CCAPI +DECL_FUNC_PTR(cc_initialize); +DECL_FUNC_PTR(cc_shutdown); +DECL_FUNC_PTR(cc_get_NC_info); +DECL_FUNC_PTR(cc_free_NC_info); + +// krb4 functions +DECL_FUNC_PTR(get_krb_err_txt_entry); +DECL_FUNC_PTR(k_isinst); +DECL_FUNC_PTR(k_isname); +DECL_FUNC_PTR(k_isrealm); +DECL_FUNC_PTR(kadm_change_your_password); +DECL_FUNC_PTR(kname_parse); +DECL_FUNC_PTR(krb_get_cred); +DECL_FUNC_PTR(krb_get_krbhst); +DECL_FUNC_PTR(krb_get_lrealm); +DECL_FUNC_PTR(krb_get_pw_in_tkt); +DECL_FUNC_PTR(krb_get_tf_realm); +DECL_FUNC_PTR(krb_mk_req); +DECL_FUNC_PTR(krb_realmofhost); +DECL_FUNC_PTR(tf_init); +DECL_FUNC_PTR(tf_close); +DECL_FUNC_PTR(tf_get_cred); +DECL_FUNC_PTR(tf_get_pname); +DECL_FUNC_PTR(tf_get_pinst); +DECL_FUNC_PTR(LocalHostAddr); +DECL_FUNC_PTR(tkt_string); +DECL_FUNC_PTR(krb_set_tkt_string); +DECL_FUNC_PTR(initialize_krb_error_func); +DECL_FUNC_PTR(initialize_kadm_error_table); +DECL_FUNC_PTR(dest_tkt); +DECL_FUNC_PTR(krb_in_tkt); +DECL_FUNC_PTR(krb_save_credentials); +DECL_FUNC_PTR(krb_get_krbconf2); +DECL_FUNC_PTR(krb_get_krbrealm2); +DECL_FUNC_PTR(krb_life_to_time); + +// krb5 functions +DECL_FUNC_PTR(krb5_change_password); +DECL_FUNC_PTR(krb5_get_init_creds_opt_init); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_change_password_prompt); +DECL_FUNC_PTR(krb5_get_init_creds_password); +DECL_FUNC_PTR(krb5_get_prompt_types); +DECL_FUNC_PTR(krb5_build_principal_ext); +DECL_FUNC_PTR(krb5_cc_get_name); +DECL_FUNC_PTR(krb5_cc_get_type); +DECL_FUNC_PTR(krb5_cc_resolve); +DECL_FUNC_PTR(krb5_cc_default); +DECL_FUNC_PTR(krb5_cc_default_name); +DECL_FUNC_PTR(krb5_cc_set_default_name); +DECL_FUNC_PTR(krb5_cc_initialize); +DECL_FUNC_PTR(krb5_cc_destroy); +DECL_FUNC_PTR(krb5_cc_close); +DECL_FUNC_PTR(krb5_cc_store_cred); +DECL_FUNC_PTR(krb5_cc_copy_creds); +DECL_FUNC_PTR(krb5_cc_retrieve_cred); +DECL_FUNC_PTR(krb5_cc_get_principal); +DECL_FUNC_PTR(krb5_cc_start_seq_get); +DECL_FUNC_PTR(krb5_cc_next_cred); +DECL_FUNC_PTR(krb5_cc_end_seq_get); +DECL_FUNC_PTR(krb5_cc_remove_cred); +DECL_FUNC_PTR(krb5_cc_set_flags); +// DECL_FUNC_PTR(krb5_cc_get_type); +DECL_FUNC_PTR(krb5_free_context); +DECL_FUNC_PTR(krb5_free_cred_contents); +DECL_FUNC_PTR(krb5_free_principal); +DECL_FUNC_PTR(krb5_get_in_tkt_with_password); +DECL_FUNC_PTR(krb5_init_context); +DECL_FUNC_PTR(krb5_parse_name); +DECL_FUNC_PTR(krb5_timeofday); +DECL_FUNC_PTR(krb5_timestamp_to_sfstring); +DECL_FUNC_PTR(krb5_unparse_name); +DECL_FUNC_PTR(krb5_get_credentials); +DECL_FUNC_PTR(krb5_mk_req); +DECL_FUNC_PTR(krb5_sname_to_principal); +DECL_FUNC_PTR(krb5_get_credentials_renew); +DECL_FUNC_PTR(krb5_free_data); +DECL_FUNC_PTR(krb5_free_data_contents); +// DECL_FUNC_PTR(krb5_get_realm_domain); +DECL_FUNC_PTR(krb5_free_unparsed_name); +DECL_FUNC_PTR(krb5_os_localaddr); +DECL_FUNC_PTR(krb5_copy_keyblock_contents); +DECL_FUNC_PTR(krb5_copy_data); +DECL_FUNC_PTR(krb5_free_creds); +DECL_FUNC_PTR(krb5_build_principal); +DECL_FUNC_PTR(krb5_get_renewed_creds); +DECL_FUNC_PTR(krb5_get_default_config_files); +DECL_FUNC_PTR(krb5_free_config_files); +DECL_FUNC_PTR(krb5_get_default_realm); +DECL_FUNC_PTR(krb5_set_default_realm); +DECL_FUNC_PTR(krb5_free_ticket); +DECL_FUNC_PTR(krb5_decode_ticket); +DECL_FUNC_PTR(krb5_get_host_realm); +DECL_FUNC_PTR(krb5_free_host_realm); +DECL_FUNC_PTR(krb5_c_random_make_octets); +DECL_FUNC_PTR(krb5_free_addresses); +DECL_FUNC_PTR(krb5_free_default_realm); +DECL_FUNC_PTR(krb5_string_to_deltat); + +// Krb524 functions +DECL_FUNC_PTR(krb524_init_ets); +DECL_FUNC_PTR(krb524_convert_creds_kdc); + +// ComErr functions +DECL_FUNC_PTR(com_err); +DECL_FUNC_PTR(error_message); + +// Profile functions +DECL_FUNC_PTR(profile_init); +DECL_FUNC_PTR(profile_flush); +DECL_FUNC_PTR(profile_release); +DECL_FUNC_PTR(profile_get_subsection_names); +DECL_FUNC_PTR(profile_free_list); +DECL_FUNC_PTR(profile_get_string); +DECL_FUNC_PTR(profile_get_integer); +DECL_FUNC_PTR(profile_get_values); +DECL_FUNC_PTR(profile_get_relation_names); +DECL_FUNC_PTR(profile_clear_relation); +DECL_FUNC_PTR(profile_add_relation); +DECL_FUNC_PTR(profile_update_relation); +DECL_FUNC_PTR(profile_release_string); +DECL_FUNC_PTR(profile_rename_section); + +// Service functions +DECL_FUNC_PTR(OpenSCManagerA); +DECL_FUNC_PTR(OpenServiceA); +DECL_FUNC_PTR(QueryServiceStatus); +DECL_FUNC_PTR(CloseServiceHandle); +DECL_FUNC_PTR(LsaNtStatusToWinError); + +// LSA Functions +DECL_FUNC_PTR(LsaConnectUntrusted); +DECL_FUNC_PTR(LsaLookupAuthenticationPackage); +DECL_FUNC_PTR(LsaCallAuthenticationPackage); +DECL_FUNC_PTR(LsaFreeReturnBuffer); +DECL_FUNC_PTR(LsaGetLogonSessionData); + +// CCAPI +FUNC_INFO ccapi_fi[] = { + MAKE_FUNC_INFO(cc_initialize), + MAKE_FUNC_INFO(cc_shutdown), + MAKE_FUNC_INFO(cc_get_NC_info), + MAKE_FUNC_INFO(cc_free_NC_info), + END_FUNC_INFO +}; + +FUNC_INFO k4_fi[] = { + MAKE_FUNC_INFO(get_krb_err_txt_entry), + MAKE_FUNC_INFO(k_isinst), + MAKE_FUNC_INFO(k_isname), + MAKE_FUNC_INFO(k_isrealm), + MAKE_FUNC_INFO(kadm_change_your_password), + MAKE_FUNC_INFO(kname_parse), + MAKE_FUNC_INFO(krb_get_cred), + MAKE_FUNC_INFO(krb_get_krbhst), + MAKE_FUNC_INFO(krb_get_lrealm), + MAKE_FUNC_INFO(krb_get_pw_in_tkt), + MAKE_FUNC_INFO(krb_get_tf_realm), + MAKE_FUNC_INFO(krb_mk_req), + MAKE_FUNC_INFO(krb_realmofhost), + MAKE_FUNC_INFO(tf_init), + MAKE_FUNC_INFO(tf_close), + MAKE_FUNC_INFO(tf_get_cred), + MAKE_FUNC_INFO(tf_get_pname), + MAKE_FUNC_INFO(tf_get_pinst), + MAKE_FUNC_INFO(LocalHostAddr), + MAKE_FUNC_INFO(tkt_string), + MAKE_FUNC_INFO(krb_set_tkt_string), + MAKE_FUNC_INFO(initialize_krb_error_func), + MAKE_FUNC_INFO(initialize_kadm_error_table), + MAKE_FUNC_INFO(dest_tkt), + /* MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), */// XXX + MAKE_FUNC_INFO(krb_in_tkt), + MAKE_FUNC_INFO(krb_save_credentials), + MAKE_FUNC_INFO(krb_get_krbconf2), + MAKE_FUNC_INFO(krb_get_krbrealm2), + MAKE_FUNC_INFO(krb_life_to_time), + END_FUNC_INFO +}; + +FUNC_INFO k5_fi[] = { + MAKE_FUNC_INFO(krb5_change_password), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_init), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_change_password_prompt), + MAKE_FUNC_INFO(krb5_get_init_creds_password), + MAKE_FUNC_INFO(krb5_get_prompt_types), + MAKE_FUNC_INFO(krb5_build_principal_ext), + MAKE_FUNC_INFO(krb5_cc_get_name), + MAKE_FUNC_INFO(krb5_cc_get_type), + MAKE_FUNC_INFO(krb5_cc_resolve), + MAKE_FUNC_INFO(krb5_cc_default), + MAKE_FUNC_INFO(krb5_cc_default_name), + MAKE_FUNC_INFO(krb5_cc_set_default_name), + MAKE_FUNC_INFO(krb5_cc_initialize), + MAKE_FUNC_INFO(krb5_cc_destroy), + MAKE_FUNC_INFO(krb5_cc_close), + MAKE_FUNC_INFO(krb5_cc_copy_creds), + MAKE_FUNC_INFO(krb5_cc_store_cred), + MAKE_FUNC_INFO(krb5_cc_retrieve_cred), + MAKE_FUNC_INFO(krb5_cc_get_principal), + MAKE_FUNC_INFO(krb5_cc_start_seq_get), + MAKE_FUNC_INFO(krb5_cc_next_cred), + MAKE_FUNC_INFO(krb5_cc_end_seq_get), + MAKE_FUNC_INFO(krb5_cc_remove_cred), + MAKE_FUNC_INFO(krb5_cc_set_flags), + // MAKE_FUNC_INFO(krb5_cc_get_type), + MAKE_FUNC_INFO(krb5_free_context), + MAKE_FUNC_INFO(krb5_free_cred_contents), + MAKE_FUNC_INFO(krb5_free_principal), + MAKE_FUNC_INFO(krb5_get_in_tkt_with_password), + MAKE_FUNC_INFO(krb5_init_context), + MAKE_FUNC_INFO(krb5_parse_name), + MAKE_FUNC_INFO(krb5_timeofday), + MAKE_FUNC_INFO(krb5_timestamp_to_sfstring), + MAKE_FUNC_INFO(krb5_unparse_name), + MAKE_FUNC_INFO(krb5_get_credentials), + MAKE_FUNC_INFO(krb5_mk_req), + MAKE_FUNC_INFO(krb5_sname_to_principal), + MAKE_FUNC_INFO(krb5_get_credentials_renew), + MAKE_FUNC_INFO(krb5_free_data), + MAKE_FUNC_INFO(krb5_free_data_contents), + // MAKE_FUNC_INFO(krb5_get_realm_domain), + MAKE_FUNC_INFO(krb5_free_unparsed_name), + MAKE_FUNC_INFO(krb5_os_localaddr), + MAKE_FUNC_INFO(krb5_copy_keyblock_contents), + MAKE_FUNC_INFO(krb5_copy_data), + MAKE_FUNC_INFO(krb5_free_creds), + MAKE_FUNC_INFO(krb5_build_principal), + MAKE_FUNC_INFO(krb5_get_renewed_creds), + MAKE_FUNC_INFO(krb5_free_addresses), + MAKE_FUNC_INFO(krb5_get_default_config_files), + MAKE_FUNC_INFO(krb5_free_config_files), + MAKE_FUNC_INFO(krb5_get_default_realm), + MAKE_FUNC_INFO(krb5_set_default_realm), + MAKE_FUNC_INFO(krb5_free_ticket), + MAKE_FUNC_INFO(krb5_decode_ticket), + MAKE_FUNC_INFO(krb5_get_host_realm), + MAKE_FUNC_INFO(krb5_free_host_realm), + MAKE_FUNC_INFO(krb5_c_random_make_octets), + MAKE_FUNC_INFO(krb5_free_default_realm), + MAKE_FUNC_INFO(krb5_string_to_deltat), + END_FUNC_INFO +}; + +FUNC_INFO k524_fi[] = { + MAKE_FUNC_INFO(krb524_init_ets), + MAKE_FUNC_INFO(krb524_convert_creds_kdc), + END_FUNC_INFO +}; + +FUNC_INFO profile_fi[] = { + MAKE_FUNC_INFO(profile_init), + MAKE_FUNC_INFO(profile_flush), + MAKE_FUNC_INFO(profile_release), + MAKE_FUNC_INFO(profile_get_subsection_names), + MAKE_FUNC_INFO(profile_free_list), + MAKE_FUNC_INFO(profile_get_string), + MAKE_FUNC_INFO(profile_get_integer), + MAKE_FUNC_INFO(profile_get_values), + MAKE_FUNC_INFO(profile_get_relation_names), + MAKE_FUNC_INFO(profile_clear_relation), + MAKE_FUNC_INFO(profile_add_relation), + MAKE_FUNC_INFO(profile_update_relation), + MAKE_FUNC_INFO(profile_release_string), + MAKE_FUNC_INFO(profile_rename_section), + END_FUNC_INFO +}; + +FUNC_INFO ce_fi[] = { + MAKE_FUNC_INFO(com_err), + MAKE_FUNC_INFO(error_message), + END_FUNC_INFO +}; + +FUNC_INFO service_fi[] = { + MAKE_FUNC_INFO(OpenSCManagerA), + MAKE_FUNC_INFO(OpenServiceA), + MAKE_FUNC_INFO(QueryServiceStatus), + MAKE_FUNC_INFO(CloseServiceHandle), + MAKE_FUNC_INFO(LsaNtStatusToWinError), + END_FUNC_INFO +}; + +FUNC_INFO lsa_fi[] = { + MAKE_FUNC_INFO(LsaConnectUntrusted), + MAKE_FUNC_INFO(LsaLookupAuthenticationPackage), + MAKE_FUNC_INFO(LsaCallAuthenticationPackage), + MAKE_FUNC_INFO(LsaFreeReturnBuffer), + MAKE_FUNC_INFO(LsaGetLogonSessionData), + END_FUNC_INFO +}; + +// psapi functions +DECL_FUNC_PTR(GetModuleFileNameExA); +DECL_FUNC_PTR(EnumProcessModules); + +FUNC_INFO psapi_fi[] = { + MAKE_FUNC_INFO(GetModuleFileNameExA), + MAKE_FUNC_INFO(EnumProcessModules), + END_FUNC_INFO +}; + +// toolhelp functions +DECL_FUNC_PTR(CreateToolhelp32Snapshot); +DECL_FUNC_PTR(Module32First); +DECL_FUNC_PTR(Module32Next); + +FUNC_INFO toolhelp_fi[] = { + MAKE_FUNC_INFO(CreateToolhelp32Snapshot), + MAKE_FUNC_INFO(Module32First), + MAKE_FUNC_INFO(Module32Next), + END_FUNC_INFO +}; + +khm_int32 init_imports(void) { + OSVERSIONINFO osvi; + int imp_rv = 1; + +#define CKRV(m) \ + do { \ + if(!imp_rv) { \ + _reportf(L"Can't locate all required exports from module [%S]", (m)); \ + goto _err_ret; \ + } \ + } while (FALSE) + +#ifndef _WIN64 + imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0); + CKRV(KRB4_DLL); +#endif + + imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0); + CKRV(KRB5_DLL); + + imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0); + CKRV(COMERR_DLL); + + imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0); + CKRV(SERVICE_DLL); + + imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1); + CKRV(SECUR32_DLL); + +#ifndef _WIN64 + imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1); + CKRV(KRB524_DLL); +#endif + + imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0); + CKRV(PROFILE_DLL); + + imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0); + /* CCAPI_DLL is optional. No error check. */ + + memset(&osvi, 0, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + // XXX: We should really use feature testing, first + // checking for CreateToolhelp32Snapshot. If that's + // not around, we try the psapi stuff. + // + // Only load LSA functions if on NT/2000/XP + if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + // Windows 9x + imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0); + CKRV(TOOLHELPDLL); + + hPsapi = 0; + } + else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Windows NT + imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0); + CKRV(PSAPIDLL); + + hToolHelp32 = 0; + } + + AfsAvailable = TRUE; //afscompat_init(); + + return KHM_ERROR_SUCCESS; + + _err_ret: + return KHM_ERROR_NOT_FOUND; +} + +khm_int32 exit_imports(void) { + //afscompat_close(); + + if (hKrb4) + FreeLibrary(hKrb4); + if (hKrb5) + FreeLibrary(hKrb5); + if (hProfile) + FreeLibrary(hProfile); + if (hComErr) + FreeLibrary(hComErr); + if (hService) + FreeLibrary(hService); + if (hSecur32) + FreeLibrary(hSecur32); + if (hKrb524) + FreeLibrary(hKrb524); + if (hPsapi) + FreeLibrary(hPsapi); + if (hToolHelp32) + FreeLibrary(hToolHelp32); + + return KHM_ERROR_SUCCESS; +} + +int (*Lcom_err)(LPSTR,long,LPSTR,...); +LPSTR (*Lerror_message)(long); +LPSTR (*Lerror_table_name)(long); + +void Leash_load_com_err_callback(FARPROC ce, + FARPROC em, + FARPROC etn) +{ + Lcom_err = (int (*)(LPSTR,long,LPSTR,...)) ce; + Lerror_message = (LPSTR (*)(long)) em; + Lerror_table_name = (LPSTR (*)(long)) etn; +} diff --git a/krb5-1-6/src/windows/identity/plugins/common/dynimport.h b/krb5-1-6/src/windows/identity/plugins/common/dynimport.h new file mode 100644 index 000000000..2c0995cba --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/common/dynimport.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_DYNIMPORT_H +#define __KHIMAIRA_DYNIMPORT_H + +/* Dynamic imports */ +#include<khdefs.h> +#include<tlhelp32.h> + +#if _WIN32_WINNT < 0x0501 +#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include<ntsecapi.h> +#ifdef KHM_SAVE_WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT +#undef KHM_SAVE_WIN32_WINNT +#endif + +extern HINSTANCE hKrb4; +extern HINSTANCE hKrb5; +extern HINSTANCE hProfile; + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _WIN64 +#define CCAPI_DLL "krbcc64.dll" +#define KRBCC32_DLL "krbcc64.dll" +#else +#define CCAPI_DLL "krbcc32.dll" +#define KRBCC32_DLL "krbcc32.dll" +#endif +#define SERVICE_DLL "advapi32.dll" +#define SECUR32_DLL "secur32.dll" + +////////////////////////////////////////////////////////////////////////////// + +#include <loadfuncs-com_err.h> +#include <loadfuncs-krb5.h> +#include <loadfuncs-profile.h> +#include <loadfuncs-krb.h> +#include <loadfuncs-krb524.h> +#include <loadfuncs-lsa.h> + +//// CCAPI +/* In order to avoid including the private CCAPI headers */ +typedef int cc_int32; + +#define CC_API_VER_1 1 +#define CC_API_VER_2 2 + +#define CCACHE_API cc_int32 + +/* +** 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 + +enum { + CC_CRED_VUNKNOWN = 0, // For validation + CC_CRED_V4 = 1, + CC_CRED_V5 = 2, + CC_CRED_VMAX = 3 // For validation +}; + +typedef struct opaque_dll_control_block_type* apiCB; +typedef struct _infoNC { + char* name; + char* principal; + cc_int32 vers; +} infoNC; + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_initialize, + ( + apiCB** cc_ctx, // < DLL's primary control structure. + // returned here, passed everywhere else + cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1) + cc_int32* api_supported, // < if ~NULL, max ver supported by DLL + const char** vendor // < if ~NULL, vendor name in read only C string + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_shutdown, + ( + apiCB** cc_ctx // <> DLL's primary control structure. NULL after + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_get_NC_info, + ( + apiCB* cc_ctx, // > DLL's primary control structure + struct _infoNC*** ppNCi // < (NULL before call) null terminated, + // list of a structs (free via cc_free_infoNC()) + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_free_NC_info, + ( + apiCB* cc_ctx, + struct _infoNC*** ppNCi // < free list of structs returned by + // cc_get_cache_names(). set to NULL on return + ) +); +//// \CCAPI + +extern DWORD AfsAvailable; + +// service definitions +typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD); +typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD); +typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS); +typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE); + +////////////////////////////////////////////////////////////////////////////// + +// CCAPI +extern DECL_FUNC_PTR(cc_initialize); +extern DECL_FUNC_PTR(cc_shutdown); +extern DECL_FUNC_PTR(cc_get_NC_info); +extern DECL_FUNC_PTR(cc_free_NC_info); + +// krb4 functions +extern DECL_FUNC_PTR(get_krb_err_txt_entry); +extern DECL_FUNC_PTR(k_isinst); +extern DECL_FUNC_PTR(k_isname); +extern DECL_FUNC_PTR(k_isrealm); +extern DECL_FUNC_PTR(kadm_change_your_password); +extern DECL_FUNC_PTR(kname_parse); +extern DECL_FUNC_PTR(krb_get_cred); +extern DECL_FUNC_PTR(krb_get_krbhst); +extern DECL_FUNC_PTR(krb_get_lrealm); +extern DECL_FUNC_PTR(krb_get_pw_in_tkt); +extern DECL_FUNC_PTR(krb_get_tf_realm); +extern DECL_FUNC_PTR(krb_mk_req); +extern DECL_FUNC_PTR(krb_realmofhost); +extern DECL_FUNC_PTR(tf_init); +extern DECL_FUNC_PTR(tf_close); +extern DECL_FUNC_PTR(tf_get_cred); +extern DECL_FUNC_PTR(tf_get_pname); +extern DECL_FUNC_PTR(tf_get_pinst); +extern DECL_FUNC_PTR(LocalHostAddr); +extern DECL_FUNC_PTR(tkt_string); +extern DECL_FUNC_PTR(krb_set_tkt_string); +extern DECL_FUNC_PTR(initialize_krb_error_func); +extern DECL_FUNC_PTR(initialize_kadm_error_table); +extern DECL_FUNC_PTR(dest_tkt); +extern DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX +extern DECL_FUNC_PTR(krb_in_tkt); +extern DECL_FUNC_PTR(krb_save_credentials); +extern DECL_FUNC_PTR(krb_get_krbconf2); +extern DECL_FUNC_PTR(krb_get_krbrealm2); +extern DECL_FUNC_PTR(krb_life_to_time); + +// krb5 functions +extern DECL_FUNC_PTR(krb5_change_password); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_init); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_change_password_prompt); +extern DECL_FUNC_PTR(krb5_get_init_creds_password); +extern DECL_FUNC_PTR(krb5_get_prompt_types); +extern DECL_FUNC_PTR(krb5_build_principal_ext); +extern DECL_FUNC_PTR(krb5_cc_get_name); +extern DECL_FUNC_PTR(krb5_cc_get_type); +extern DECL_FUNC_PTR(krb5_cc_resolve); +extern DECL_FUNC_PTR(krb5_cc_default); +extern DECL_FUNC_PTR(krb5_cc_default_name); +extern DECL_FUNC_PTR(krb5_cc_set_default_name); +extern DECL_FUNC_PTR(krb5_cc_initialize); +extern DECL_FUNC_PTR(krb5_cc_destroy); +extern DECL_FUNC_PTR(krb5_cc_close); +extern DECL_FUNC_PTR(krb5_cc_copy_creds); +extern DECL_FUNC_PTR(krb5_cc_store_cred); +extern DECL_FUNC_PTR(krb5_cc_retrieve_cred); +extern DECL_FUNC_PTR(krb5_cc_get_principal); +extern DECL_FUNC_PTR(krb5_cc_start_seq_get); +extern DECL_FUNC_PTR(krb5_cc_next_cred); +extern DECL_FUNC_PTR(krb5_cc_end_seq_get); +extern DECL_FUNC_PTR(krb5_cc_remove_cred); +extern DECL_FUNC_PTR(krb5_cc_set_flags); +// extern DECL_FUNC_PTR(krb5_cc_get_type); +extern DECL_FUNC_PTR(krb5_free_context); +extern DECL_FUNC_PTR(krb5_free_cred_contents); +extern DECL_FUNC_PTR(krb5_free_principal); +extern DECL_FUNC_PTR(krb5_get_in_tkt_with_password); +extern DECL_FUNC_PTR(krb5_init_context); +extern DECL_FUNC_PTR(krb5_parse_name); +extern DECL_FUNC_PTR(krb5_timeofday); +extern DECL_FUNC_PTR(krb5_timestamp_to_sfstring); +extern DECL_FUNC_PTR(krb5_unparse_name); +extern DECL_FUNC_PTR(krb5_get_credentials); +extern DECL_FUNC_PTR(krb5_mk_req); +extern DECL_FUNC_PTR(krb5_sname_to_principal); +extern DECL_FUNC_PTR(krb5_get_credentials_renew); +extern DECL_FUNC_PTR(krb5_free_data); +extern DECL_FUNC_PTR(krb5_free_data_contents); +// extern DECL_FUNC_PTR(krb5_get_realm_domain); +extern DECL_FUNC_PTR(krb5_free_unparsed_name); +extern DECL_FUNC_PTR(krb5_os_localaddr); +extern DECL_FUNC_PTR(krb5_copy_keyblock_contents); +extern DECL_FUNC_PTR(krb5_copy_data); +extern DECL_FUNC_PTR(krb5_free_creds); +extern DECL_FUNC_PTR(krb5_build_principal); +extern DECL_FUNC_PTR(krb5_get_renewed_creds); +extern DECL_FUNC_PTR(krb5_free_addresses); +extern DECL_FUNC_PTR(krb5_get_default_config_files); +extern DECL_FUNC_PTR(krb5_free_config_files); +extern DECL_FUNC_PTR(krb5_get_default_realm); +extern DECL_FUNC_PTR(krb5_set_default_realm); +extern DECL_FUNC_PTR(krb5_free_ticket); +extern DECL_FUNC_PTR(krb5_decode_ticket); +extern DECL_FUNC_PTR(krb5_get_host_realm); +extern DECL_FUNC_PTR(krb5_free_host_realm); +extern DECL_FUNC_PTR(krb5_c_random_make_octets); +extern DECL_FUNC_PTR(krb5_free_default_realm); +extern DECL_FUNC_PTR(krb5_string_to_deltat); + +// Krb524 functions +extern DECL_FUNC_PTR(krb524_init_ets); +extern DECL_FUNC_PTR(krb524_convert_creds_kdc); + +// ComErr functions +extern DECL_FUNC_PTR(com_err); +extern DECL_FUNC_PTR(error_message); + +// Profile functions +extern DECL_FUNC_PTR(profile_init); +extern DECL_FUNC_PTR(profile_flush); +extern DECL_FUNC_PTR(profile_release); +extern DECL_FUNC_PTR(profile_get_subsection_names); +extern DECL_FUNC_PTR(profile_free_list); +extern DECL_FUNC_PTR(profile_get_string); +extern DECL_FUNC_PTR(profile_get_integer); +extern DECL_FUNC_PTR(profile_get_values); +extern DECL_FUNC_PTR(profile_get_relation_names); +extern DECL_FUNC_PTR(profile_clear_relation); +extern DECL_FUNC_PTR(profile_add_relation); +extern DECL_FUNC_PTR(profile_update_relation); +extern DECL_FUNC_PTR(profile_release_string); +extern DECL_FUNC_PTR(profile_rename_section); + +// Service functions +extern DECL_FUNC_PTR(OpenSCManagerA); +extern DECL_FUNC_PTR(OpenServiceA); +extern DECL_FUNC_PTR(QueryServiceStatus); +extern DECL_FUNC_PTR(CloseServiceHandle); +extern DECL_FUNC_PTR(LsaNtStatusToWinError); + +// LSA Functions +extern DECL_FUNC_PTR(LsaConnectUntrusted); +extern DECL_FUNC_PTR(LsaLookupAuthenticationPackage); +extern DECL_FUNC_PTR(LsaCallAuthenticationPackage); +extern DECL_FUNC_PTR(LsaFreeReturnBuffer); +extern DECL_FUNC_PTR(LsaGetLogonSessionData); + +// toolhelp functions +TYPEDEF_FUNC( + HANDLE, + WINAPI, + CreateToolhelp32Snapshot, + (DWORD, DWORD) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32First, + (HANDLE, LPMODULEENTRY32) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32Next, + (HANDLE, LPMODULEENTRY32) + ); + +// psapi functions +TYPEDEF_FUNC( + DWORD, + WINAPI, + GetModuleFileNameExA, + (HANDLE, HMODULE, LPSTR, DWORD) + ); + +TYPEDEF_FUNC( + BOOL, + WINAPI, + EnumProcessModules, + (HANDLE, HMODULE*, DWORD, LPDWORD) + ); + +#define pGetModuleFileNameEx pGetModuleFileNameExA +#define TOOLHELPDLL "kernel32.dll" +#define PSAPIDLL "psapi.dll" + +// psapi functions +extern DECL_FUNC_PTR(GetModuleFileNameExA); +extern DECL_FUNC_PTR(EnumProcessModules); + +// toolhelp functions +extern DECL_FUNC_PTR(CreateToolhelp32Snapshot); +extern DECL_FUNC_PTR(Module32First); +extern DECL_FUNC_PTR(Module32Next); + +khm_int32 init_imports(void); +khm_int32 exit_imports(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/common/krb5common.c b/krb5-1-6/src/windows/identity/plugins/common/krb5common.c new file mode 100644 index 000000000..36d647cc7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/common/krb5common.c @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<windows.h> +#include<netidmgr.h> +#include<dynimport.h> +#include<krb5common.h> +#ifdef DEBUG +#include<assert.h> +#endif +#include<strsafe.h> + +/**************************************/ +/* khm_krb5_error(): */ +/**************************************/ +int +khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, + int FreeContextFlag, krb5_context * ctx, + krb5_ccache * cache) +{ +#ifdef NO_KRB5 + return -1; +#else + +#ifdef SHOW_MESSAGE_IN_AN_ANNOYING_WAY + char message[256]; + const char *errText; + int krb5Error = ((int)(rc & 255)); + + errText = perror_message(rc); + _snprintf(message, sizeof(message), + "%s\n(Kerberos error %ld)\n\n%s failed", + errText, + krb5Error, + FailedFunctionName); + + MessageBoxA(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR | + MB_TASKMODAL | + MB_SETFOREGROUND); +#endif + + if (FreeContextFlag == 1) + { + if (*ctx != NULL) + { + if (*cache != NULL) { + pkrb5_cc_close(*ctx, *cache); + *cache = NULL; + } + + pkrb5_free_context(*ctx); + *ctx = NULL; + } + } + + return rc; + +#endif //!NO_KRB5 +} + +int +khm_krb5_initialize(khm_handle ident, + krb5_context *ctx, + krb5_ccache *cache) +{ +#ifdef NO_KRB5 + return(-1); +#else + + LPCSTR functionName = NULL; + int freeContextFlag = 0; + krb5_error_code rc = -1; + krb5_flags flags = 0; + + if (pkrb5_init_context == NULL) + return 1; + + if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx))) { + functionName = "krb5_init_context()"; + freeContextFlag = 0; + goto on_error; + } + + if(*cache == 0) { + wchar_t wccname[MAX_PATH]; + khm_size cbwccname; + + if(ident != NULL) { + cbwccname = sizeof(wccname); + do { + char ccname[256]; + + if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName", + NULL, wccname, + &cbwccname))) { + cbwccname = sizeof(wccname); + if (KHM_FAILED + (khm_krb5_find_ccache_for_identity(ident, + ctx, + wccname, + &cbwccname))) { +#ifdef DEBUG_LIKE_A_MADMAN + assert(FALSE); +#endif + break; + } + } + + if(UnicodeStrToAnsi(ccname, sizeof(ccname), wccname) == 0) + break; + + if(rc = (*pkrb5_cc_resolve)(*ctx, ccname, cache)) { + functionName = "krb5_cc_resolve()"; + freeContextFlag = 1; + goto on_error; + } + } while(FALSE); + } + +#ifndef FAILOVER_TO_DEFAULT_CCACHE + rc = 1; +#endif + if (*cache == 0 +#ifdef FAILOVER_TO_DEFAULT_CCACHE + && (rc = (*pkrb5_cc_default)(*ctx, cache)) +#endif + ) { + functionName = "krb5_cc_default()"; + freeContextFlag = 1; + goto on_error; + } + } + +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; +#endif + + if ((rc = (*pkrb5_cc_set_flags)(*ctx, *cache, flags))) + { + if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND) + khm_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx, + cache); + else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL) { + if (*cache != NULL) { + (*pkrb5_cc_close)(*ctx, *cache); + *cache = NULL; + } + } + return rc; + } + return 0; + +on_error: + return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache); +#endif //!NO_KRB5 +} + +#define TIMET_TOLERANCE (60*5) + +khm_int32 KHMAPI +khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, + khm_handle ident, + krb5_timestamp * pexpiration) +{ + krb5_principal principal = 0; + char * princ_name = NULL; + krb5_creds creds; + krb5_error_code code; + krb5_error_code cc_code; + krb5_cc_cursor cur; + krb5_timestamp now, expiration = 0; + + wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME]; + char ident_name[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + khm_int32 rv = KHM_ERROR_NOT_FOUND; + + if (!ctx || !cc || !ident || !pexpiration) + return KHM_ERROR_GENERAL; + + code = pkrb5_cc_get_principal(ctx, cc, &principal); + + if ( code ) + return KHM_ERROR_INVALID_PARAM; + + cb = sizeof(w_ident_name); + kcdb_identity_get_name(ident, w_ident_name, &cb); + UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name); + + code = pkrb5_unparse_name(ctx, principal, &princ_name); + + /* compare principal to ident. */ + + if ( code || !princ_name || + strcmp(princ_name, ident_name) ) { + if (princ_name) + pkrb5_free_unparsed_name(ctx, princ_name); + pkrb5_free_principal(ctx, principal); + return KHM_ERROR_UNKNOWN; + } + + pkrb5_free_unparsed_name(ctx, princ_name); + pkrb5_free_principal(ctx, principal); + + code = pkrb5_timeofday(ctx, &now); + + if (code) + return KHM_ERROR_UNKNOWN; + + cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur); + + while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) { + krb5_data * c0 = krb5_princ_name(ctx, creds.server); + krb5_data * c1 = krb5_princ_component(ctx, creds.server, 1); + krb5_data * r = krb5_princ_realm(ctx, creds.server); + + if ( c0 && c1 && r && c1->length == r->length && + !strncmp(c1->data,r->data,r->length) && + !strncmp("krbtgt",c0->data,c0->length) ) { + + /* we have a TGT, check for the expiration time. + * if it is valid and renewable, use the renew time + */ + + if (!(creds.ticket_flags & TKT_FLG_INVALID) && + creds.times.starttime < (now + TIMET_TOLERANCE) && + (creds.times.endtime + TIMET_TOLERANCE) > now) { + expiration = creds.times.endtime; + + if ((creds.ticket_flags & TKT_FLG_RENEWABLE) && + (creds.times.renew_till > creds.times.endtime)) { + expiration = creds.times.renew_till; + } + } + } + } + + if (cc_code == KRB5_CC_END) { + cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur); + rv = KHM_ERROR_SUCCESS; + *pexpiration = expiration; + } + + return rv; +} + +khm_int32 KHMAPI +khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx, + void * buffer, khm_size * pcbbuf) +{ + krb5_context ctx = 0; + krb5_ccache cache = 0; + krb5_error_code code; + apiCB * cc_ctx = 0; + struct _infoNC ** pNCi = NULL; + int i; + khm_int32 t; + wchar_t * ms = NULL; + khm_size cb; + krb5_timestamp expiration = 0; + krb5_timestamp best_match_expiration = 0; + char best_match_ccname[256] = ""; + khm_handle csp_params = NULL; + khm_handle csp_plugins = NULL; + + if (!buffer || !pcbbuf) + return KHM_ERROR_GENERAL; + + ctx = *pctx; + + if (!pcc_initialize || + !pcc_get_NC_info || + !pcc_free_NC_info || + !pcc_shutdown) + goto _skip_cc_iter; + + code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL); + if (code) + goto _exit; + + code = pcc_get_NC_info(cc_ctx, &pNCi); + + if (code) + goto _exit; + + for(i=0; pNCi[i]; i++) { + if (pNCi[i]->vers != CC_CRED_V5) + continue; + + code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache); + if (code) + continue; + + /* need a function to check the cache for the identity + * and determine if it has valid tickets. If it has + * the right identity and valid tickets, store the + * expiration time and the cache name. If it has the + * right identity but no valid tickets, store the ccache + * name and an expiration time of zero. if it does not + * have the right identity don't save the name. + * + * Keep searching to find the best cache available. + */ + + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, + sizeof(best_match_ccname), + "API:"); + StringCbCatA(best_match_ccname, + sizeof(best_match_ccname), + pNCi[i]->name); + expiration = 0; + } + } + + if(ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + _skip_cc_iter: + + if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) { + khc_open_space(csp_plugins, L"Krb5Cred\\Parameters", 0, &csp_params); + khc_close_space(csp_plugins); + csp_plugins = NULL; + } + +#ifdef DEBUG + if (csp_params == NULL) { + assert(FALSE); + } +#endif + + if (csp_params && + KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) { + code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache); + if (code == 0 && cache) { + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, sizeof(best_match_ccname), + "MSLSA:"); + expiration = 0; + } + } + } + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + + cache = 0; + } + + if (csp_params && + khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + == KHM_ERROR_TOO_LONG && + cb > sizeof(wchar_t) * 2) { + + wchar_t * t; + char ccname[MAX_PATH + 6]; + + ms = PMALLOC(cb); + +#ifdef DEBUG + assert(ms); +#endif + + khc_read_multi_string(csp_params, L"FileCCList", ms, &cb); + for(t = ms; t && *t; t = multi_string_next(t)) { + StringCchPrintfA(ccname, ARRAYLENGTH(ccname), + "FILE:%S", t); + + code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); + if (code) + continue; + + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, + sizeof(best_match_ccname), + ccname); + expiration = 0; + } + } + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + PFREE(ms); + } + _exit: + if (csp_params) + khc_close_space(csp_params); + + if (pNCi) + (*pcc_free_NC_info)(cc_ctx, &pNCi); + + if (cc_ctx) + (*pcc_shutdown)(&cc_ctx); + + if (best_match_ccname[0]) { + + if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer, + *pcbbuf, + best_match_ccname)) { + + *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t); + + return KHM_ERROR_SUCCESS; + } + + } + + return KHM_ERROR_GENERAL; +} diff --git a/krb5-1-6/src/windows/identity/plugins/common/krb5common.h b/krb5-1-6/src/windows/identity/plugins/common/krb5common.h new file mode 100644 index 000000000..29cae71ee --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/common/krb5common.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Adapted from multiple Leash header files */ + +#ifndef __KHIMAIRA_KRB5COMMON_H +#define __KHIMAIRA_KRB5COMMON_H + +#include<krb5.h> + +#ifndef NO_KRB5 +int khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, + int FreeContextFlag, krb5_context *ctx, + krb5_ccache *cache); + +int +khm_krb5_get_error_string(krb5_error_code rc, + wchar_t * buffer, + khm_size cb_buffer); + +int khm_krb5_initialize(khm_handle ident, krb5_context *, krb5_ccache *); + +khm_int32 KHMAPI +khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx, + void * buffer, khm_size * pcbbuf); + +khm_int32 KHMAPI +khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, + khm_handle ident, + krb5_timestamp * pexpiration); +#endif /* NO_KRB5 */ + +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/Makefile b/krb5-1-6/src/windows/identity/plugins/krb4/Makefile new file mode 100644 index 000000000..0a8ede8aa --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/Makefile @@ -0,0 +1,106 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=plugins\krb4 +!include <../../config/Makefile.w32> + +DLLFILE=$(BINDIR)\krb4cred.dll + +LIBFILE=$(LIBDIR)\krb4cred.lib + +OBJFILES= \ + $(LIBDIR)\dynimport.obj \ + $(LIBDIR)\krb5common.obj \ + $(OBJ)\krb4main.obj \ + $(OBJ)\krb4plugin.obj \ + $(OBJ)\krb4funcs.obj \ + $(OBJ)\errorfuncs.obj \ + $(OBJ)\krb4config.obj \ + $(OBJ)\krb4configdlg.obj \ + $(OBJ)\krb4newcreds.obj + + + +SDKLIBFILES= + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +SCLIB=bufferoverflowu.lib +LIBFILES= \ + $(LIBDIR)\nidmgr64.lib \ + $(KFWLIBDIR)\loadfuncs.lib +!else +SCLIB= +LIBFILES= \ + $(LIBDIR)\nidmgr32.lib \ + $(KFWLIBDIR)\loadfuncs.lib +!endif + +VERRESFILE=$(OBJ)\version.res + +MSGRESFILE=$(OBJ)\krb4_msgs.res + +$(MSGRESFILE): $(OBJ)\krb4_msgs.rc + +$(OBJ)\krb4_msgs.rc: lang\krb4_msgs.mc + $(MC2RC) + +$(OBJ)\krb4config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg + $(CCSV) $** $@ + +$(DLLFILE): $(OBJFILES) $(VERRESFILE) $(MSGRESFILE) + $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES) $(SCLIB) + $(_VC_MANIFEST_EMBED_DLL) + $(_VC_MANIFEST_CLEAN) + +all: mkdirs $(MSGRESFILE) $(DLLFILE) lang + +lang:: + +# Repeat this block as necessary redefining LANG for additional +# languages. + +# Begin language block +LANG=en_us + +LANGDLL=$(BINDIR)\krb4cred_$(LANG).dll + +lang:: $(LANGDLL) + +$(LANGDLL): $(OBJ)\langres_$(LANG).res $(OBJ)\langres_ver_$(LANG).res + $(DLLRESLINK) + +$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc + $(RC2RES) + +$(OBJ)\langres_ver_$(LANG).res: version.rc + $(RC) $(RFLAGS) $(rincflags) /d LANGVER /d LANG_$(LANG) /fo $@ $** +# End language block + +clean:: +!if defined(INCFILES) + $(RM) $(INCFILES) +!endif + + diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.c b/krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.c new file mode 100644 index 000000000..f436a40a7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> + +#include<strsafe.h> + +extern void (__cdecl *pinitialize_krb_error_func)(); +extern void (__cdecl *pinitialize_kadm_error_table)(); + + +khm_int32 init_error_funcs() +{ + +#if 0 + /*TODO: Do something about this */ + if (plsh_LoadKrb4LeashErrorTables) + plsh_LoadKrb4LeashErrorTables(hLeashInst, 0); +#endif + return KHM_ERROR_SUCCESS; +} + +khm_int32 exit_error_funcs() +{ + return KHM_ERROR_SUCCESS; +} + +// Global Variables. +static long lsh_errno; +static char *err_context; /* error context */ +extern int (*Lcom_err)(LPSTR,long,LPSTR,...); +extern LPSTR (*Lerror_message)(long); +extern LPSTR (*Lerror_table_name)(long); + +#ifdef WIN16 +#define UNDERSCORE "_" +#else +#define UNDERSCORE +#endif + +HWND GetRootParent (HWND Child) +{ + HWND Last = NULL; + while (Child) + { + Last = Child; + Child = GetParent (Child); + } + return Last; +} + + +LPSTR err_describe(LPSTR buf, size_t len, long code) +{ + LPSTR cp, com_err_msg; + int offset; + long table_num; + char *etype; + + offset = (int) (code & 255); + table_num = code - offset; + com_err_msg = Lerror_message(code); + + switch(table_num) + { + case krb_err_base: + case kadm_err_base: + break; + default: + StringCbCopyA(buf, len, com_err_msg); + return buf; + } + + cp = buf; + if (table_num == krb_err_base) + switch(offset) + { + case KDC_NAME_EXP: /* 001 Principal expired */ + case KDC_SERVICE_EXP: /* 002 Service expired */ + case KDC_AUTH_EXP: /* 003 Auth expired */ + case KDC_PKT_VER: /* 004 Protocol version unknown */ + case KDC_P_MKEY_VER: /* 005 Wrong master key version */ + case KDC_S_MKEY_VER: /* 006 Wrong master key version */ + case KDC_BYTE_ORDER: /* 007 Byte order unknown */ + case KDC_PR_N_UNIQUE: /* 009 Principal not unique */ + case KDC_NULL_KEY: /* 010 Principal has null key */ + case KDC_GEN_ERR: /* 011 Generic error from KDC */ + case INTK_W_NOTALL : /* 061 Not ALL tickets returned */ + case INTK_PROT : /* 063 Protocol Error */ + case INTK_ERR : /* 070 Other error */ + com_err_msg = "Something weird happened... try again, and if Leash" + " continues to fail, contact Network Services as listed in the " + "About box."; + break; + case KDC_PR_UNKNOWN: /* 008 Principal unknown */ + com_err_msg = "You have entered an unknown username/instance/realm" + " combination."; + break; + case GC_TKFIL : /* 021 Can't read ticket file */ + case GC_NOTKT : /* 022 Can't find ticket or TGT */ + com_err_msg = "Something is wrong with the memory where your " + "tickets are stored. Try exiting Windows and restarting your " + "computer."; + break; + case MK_AP_TGTEXP : /* 026 TGT Expired */ + /* no extra error msg */ + break; + case RD_AP_TIME : /* 037 delta_t too big */ + com_err_msg = "Your computer's clock is out of sync with the " + "Kerberos server. Please see the help file about correcting " + "your clock."; + break; + + case RD_AP_UNDEC : /* 031 Can't decode authenticator */ + case RD_AP_EXP : /* 032 Ticket expired */ + case RD_AP_NYV : /* 033 Ticket not yet valid */ + case RD_AP_REPEAT : /* 034 Repeated request */ + case RD_AP_NOT_US : /* 035 The ticket isn't for us */ + case RD_AP_INCON : /* 036 Request is inconsistent */ + case RD_AP_BADD : /* 038 Incorrect net address */ + case RD_AP_VERSION : /* 039 protocol version mismatch */ + case RD_AP_MSG_TYPE : /* 040 invalid msg type */ + case RD_AP_MODIFIED : /* 041 message stream modified */ + case RD_AP_ORDER : /* 042 message out of order */ + case RD_AP_UNAUTHOR : /* 043 unauthorized request */ + /* no extra error msg */ + break; + case GT_PW_NULL: /* 51 Current PW is null */ + case GT_PW_BADPW: /* 52 Incorrect current password */ + case GT_PW_PROT: /* 53 Protocol Error */ + case GT_PW_KDCERR: /* 54 Error returned by KDC */ + case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */ + /* no error msg yet */ + break; + + /* Values returned by send_to_kdc */ + case SKDC_RETRY : /* 56 Retry count exceeded */ + case SKDC_CANT : /* 57 Can't send request */ + com_err_msg = "Cannot contact the kerberos server for the selected realm."; + break; + /* no error message on purpose: */ + case INTK_BADPW : /* 062 Incorrect password */ + break; + default: + /* no extra error msg */ + break; + } + else + switch(code) + { + case KADM_INSECURE_PW: + /* if( kadm_info != NULL ){ + * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info); + * } else { + * wsprintf(buf, "%s\nPlease see the help file for information " + * "about secure passwords.", com_err_msg); + * } + * com_err_msg = buf; + */ + + /* The above code would be preferred since it allows site specific + * information to be delivered from the Kerberos server. However the + * message box is too small for VGA screens. + * It does work well if we only have to support 1024x768 + */ + + com_err_msg = "You have entered an insecure or weak password."; + + default: + /* no extra error msg */ + break; + } + if(com_err_msg != buf) { + StringCbCopyA(buf, len, com_err_msg); + } + cp = buf + strlen(buf); + *cp++ = '\n'; + switch(table_num) { + case krb_err_base: + etype = "Kerberos"; + break; + case kadm_err_base: + etype = "Kerberos supplemental"; + break; + default: + etype = Lerror_table_name(table_num); + break; + } + StringCbPrintfA((LPSTR) cp, len - (cp-buf), (LPSTR) "(%s error %d" +#ifdef DEBUG_COM_ERR + " (absolute error %ld)" +#endif + ")", etype, offset + //")\nPress F1 for help on this error.", etype, offset +#ifdef DEBUG_COM_ERR + , code +#endif + ); + + return (LPSTR)buf; +} + diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.h b/krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.h new file mode 100644 index 000000000..d760c6259 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/errorfuncs.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_ERR_H +#define __KHIMAIRA_ERR_H + +/* All error handling and reporting related functions for the krb4/5 + and AFS plugins */ + +#include <errno.h> +#include <com_err.h> +/* + * This is a hack needed because the real com_err.h does + * not define err_func. We need it in the case where + * we pull in the real com_err instead of the krb4 + * impostor. + */ +#ifndef _DCNS_MIT_COM_ERR_H +typedef LPSTR (*err_func)(int, long); +#endif + +#include <krberr.h> +#include <kadm_err.h> + +#define kadm_err_base ERROR_TABLE_BASE_kadm + +#include <stdarg.h> + +#ifndef KRBERR +#define KRBERR(code) (code + krb_err_base) +#endif + +LPSTR err_describe(LPSTR buf, size_t len, long code); + + +/* */ +khm_int32 init_error_funcs(); + +khm_int32 exit_error_funcs(); + + +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/images/plugin.ico b/krb5-1-6/src/windows/identity/plugins/krb4/images/plugin.ico new file mode 100644 index 0000000000000000000000000000000000000000..791b359694d86dcdc85bd083d502db8056283771 GIT binary patch literal 7278 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 Fe*s!^o~Hl+ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krb4configdlg.c b/krb5-1-6/src/windows/identity/plugins/krb4/krb4configdlg.c new file mode 100644 index 000000000..c2ab3f562 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krb4configdlg.c @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> +#include<khuidefs.h> +#include<strsafe.h> +#include<assert.h> + +typedef struct tag_k4_ids_data { + khui_config_init_data cfg; + + khm_int32 get_tix; +} k4_ids_data; + +static void +k4_ids_read_params(k4_ids_data * d) { + khm_int32 t; +#ifdef DEBUG + assert(csp_params); +#endif + + t = 1; + khc_read_int32(csp_params, L"Krb4NewCreds", &t); + d->get_tix = !!t; +} + +static void +k4_ids_write_params(HWND hw, k4_ids_data * d) { + khm_int32 nv; + khm_boolean applied = FALSE; + + if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED) + nv = TRUE; + else + nv = FALSE; + + if (!!nv != !!d->get_tix) { + d->get_tix = !!nv; + khc_write_int32(csp_params, L"Krb4NewCreds", d->get_tix); + applied = TRUE; + } + + khui_cfg_set_flags_inst(&d->cfg, + (applied)?KHUI_CNFLAG_APPLIED:0, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +static void +k4_ids_check_mod(HWND hw, k4_ids_data * d) { + khm_int32 nv; + + if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED) + nv = TRUE; + else + nv = FALSE; + + khui_cfg_set_flags_inst(&d->cfg, + (!!nv != !!d->get_tix)? KHUI_CNFLAG_MODIFIED: 0, + KHUI_CNFLAG_MODIFIED); +} + +INT_PTR CALLBACK +krb4_ids_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + k4_ids_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->cfg = *((khui_config_init_data *) lParam); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + k4_ids_read_params(d); + + CheckDlgButton(hwnd, IDC_CFG_GETTIX, + (d->get_tix)? BST_CHECKED: BST_UNCHECKED); + + break; + + case WM_COMMAND: + d = (k4_ids_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (HIWORD(wParam) == BN_CLICKED) { + k4_ids_check_mod(hwnd, d); + } + break; + + case KHUI_WM_CFG_NOTIFY: + d = (k4_ids_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (HIWORD(wParam) == WMCFG_APPLY) { + k4_ids_write_params(hwnd, d); + } + break; + + case WM_DESTROY: + d = (k4_ids_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d) { + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) 0); + } + + break; + } + + return FALSE; +} + +typedef struct tag_k4_id_data { + khui_config_init_data cfg; + khm_int32 gettix; /* get tickets? */ + khm_boolean is_default_ident; +} k4_id_data; + +void +k4_id_read_params(k4_id_data * d) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_handle ident = NULL; + khm_handle csp_ident = NULL; + khm_handle csp_idk4 = NULL; + khm_int32 flags = 0; + khm_int32 t; + + khc_read_int32(csp_params, L"Krb4NewCreds", &d->gettix); + + *idname = 0; + cb = sizeof(idname); + khui_cfg_get_name(d->cfg.ctx_node, idname, &cb); + + kcdb_identity_create(idname, 0, &ident); + + if (ident == NULL) { + d->gettix = 0; + goto done; + } + + kcdb_identity_get_flags(ident, &flags); + + if (!(flags & KCDB_IDENT_FLAG_DEFAULT)) { + d->gettix = 0; + goto done; + } + + d->is_default_ident = TRUE; + + if (d->gettix == 0) + goto done; + + if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_ident))) + goto done; + + if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED, + 0, &csp_idk4))) + goto close_config; + + if (KHM_SUCCEEDED(khc_read_int32(csp_idk4, L"Krb4NewCreds", &t)) && + !t) + d->gettix = 1; + + close_config: + if (csp_ident) + khc_close_space(csp_ident); + + if (csp_idk4) + khc_close_space(csp_idk4); + + done: + if (ident) + kcdb_identity_release(ident); + + return; +} + +khm_boolean +k4_id_write_params(HWND hwnd, k4_id_data * d) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb_idname = sizeof(idname); + khm_handle ident = NULL; + khm_int32 flags = 0; + khm_handle csp_ident = NULL; + khm_handle csp_idk4 = NULL; + khm_int32 gettix = 0; + khm_boolean applied = FALSE; + + khui_cfg_get_name(d->cfg.ctx_node, idname, &cb_idname); + + kcdb_identity_create(idname, 0, &ident); + + if (ident == NULL) + return FALSE; + + kcdb_identity_get_flags(ident, &flags); + + if (!(flags & KCDB_IDENT_FLAG_DEFAULT)) + goto done_apply; + + if (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) == BST_CHECKED) + gettix = TRUE; + + if (KHM_FAILED(kcdb_identity_get_config(ident, KHM_FLAG_CREATE, + &csp_ident))) + goto done_apply; + + if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED, + KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD, + &csp_idk4))) + goto done_apply; + + khc_write_int32(csp_idk4, L"Krb4NewCreds", gettix); + + applied = TRUE; + + done_apply: + if (ident) + kcdb_identity_release(ident); + + if (csp_ident) + khc_close_space(csp_ident); + + if (csp_idk4) + khc_close_space(csp_idk4); + + return applied; +} + +INT_PTR CALLBACK +krb4_id_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + { + k4_id_data * d; + + d = PMALLOC(sizeof(k4_id_data)); + + if (!d) + break; + + ZeroMemory(d, sizeof(*d)); + + d->cfg = *((khui_config_init_data *) lParam); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + k4_id_read_params(d); + + CheckDlgButton(hwnd, IDC_CFG_GETTIX, + (d->gettix)?BST_CHECKED: BST_UNCHECKED); + EnableWindow(GetDlgItem(hwnd, IDC_CFG_GETTIX), + d->is_default_ident); + + } + break; + + case WM_COMMAND: + { + k4_id_data * d; + + d = (k4_id_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (wParam == MAKEWPARAM(IDC_CFG_GETTIX, + BN_CLICKED)) { + int gettix = 0; + int modified = 0; + + gettix = (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) == + BST_CHECKED); + + modified = (!!gettix != !!d->gettix); + + khui_cfg_set_flags_inst(&d->cfg, + ((modified)?KHUI_CNFLAG_MODIFIED: 0), + KHUI_CNFLAG_MODIFIED); + } + } + break; + + case KHUI_WM_CFG_NOTIFY: + { + k4_id_data * d; + + d = (k4_id_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (HIWORD(wParam) == WMCFG_APPLY) { + khm_int32 applied; + + applied = k4_id_write_params(hwnd, d); + + khui_cfg_set_flags_inst(&d->cfg, + ((applied)? KHUI_CNFLAG_APPLIED: 0), + (KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED)); + } + } + break; + + case WM_DESTROY: + { + k4_id_data * d; + + d = (k4_id_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + PFREE(d); + + SetWindowLongPtr(hwnd, DWLP_USER, 0); + } + break; + } + + return FALSE; +} + +typedef struct tag_k4_config_dlg_data { + khui_config_node node; + char krb_path[MAX_PATH]; + char krbrealm_path[MAX_PATH]; + char tkt_string[MAX_PATH]; +} k4_config_dlg_data; + +INT_PTR CALLBACK +krb4_confg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + static BOOL in_init = FALSE; + k4_config_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + { + wchar_t wbuf[MAX_PATH]; + CHAR krb_path[MAX_PATH]; + CHAR krbrealm_path[MAX_PATH]; + CHAR ticketName[MAX_PATH]; + char * pticketName; + size_t krb_path_sz = sizeof(krb_path); + size_t krbrealm_path_sz = sizeof(krbrealm_path); + khm_size cbsize; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + d->node = (khui_config_node) lParam; + + in_init = TRUE; + + // Set KRB.CON + memset(krb_path, '\0', sizeof(krb_path)); + if (!pkrb_get_krbconf2(krb_path, &krb_path_sz)) { + // Error has happened + } else { // normal find + AnsiStrToUnicode(wbuf, sizeof(wbuf), krb_path); + SetDlgItemText(hwnd, IDC_CFG_CFGPATH, wbuf); + StringCbCopyA(d->krb_path, sizeof(d->krb_path), krb_path); + } + + // Set KRBREALM.CON + memset(krbrealm_path, '\0', sizeof(krbrealm_path)); + if (!pkrb_get_krbrealm2(krbrealm_path, &krbrealm_path_sz)) { + // Error has happened + } else { + AnsiStrToUnicode(wbuf, sizeof(wbuf), krbrealm_path); + SetDlgItemText(hwnd, IDC_CFG_RLMPATH, wbuf); + StringCbCopyA(d->krbrealm_path, sizeof(d->krbrealm_path), + krbrealm_path); + } + + cbsize = sizeof(wbuf); + if (KHM_SUCCEEDED(khc_read_string(csp_params, L"TktString", + wbuf, &cbsize)) && + wbuf[0] != L'\0') { + + UnicodeStrToAnsi(ticketName, sizeof(ticketName), wbuf); + + } else { + + // Set TICKET.KRB file Editbox + *ticketName = 0; + pkrb_set_tkt_string(0); + + pticketName = ptkt_string(); + if (pticketName) + StringCbCopyA(ticketName, sizeof(ticketName), pticketName); + + } + + if (!*ticketName) { + // error + } else { + AnsiStrToUnicode(wbuf, sizeof(wbuf), ticketName); + SetDlgItemText(hwnd, IDC_CFG_CACHE, wbuf); + StringCbCopyA(d->tkt_string, sizeof(d->tkt_string), + ticketName); + } + + in_init = FALSE; + + } + break; + + case WM_COMMAND: + if (MAKEWPARAM(IDC_CFG_CACHE, EN_CHANGE)) { + char tkt_string[MAX_PATH]; + wchar_t wtkt_string[MAX_PATH]; + + if (in_init) { + return TRUE; + } + + d = (k4_config_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + return TRUE; + + tkt_string[0] = 0; + wtkt_string[0] = 0; + + GetDlgItemText(hwnd, IDC_CFG_CACHE, + wtkt_string, ARRAYLENGTH(wtkt_string)); + UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), + wtkt_string); + + if (_stricmp(tkt_string, d->tkt_string)) { + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } else { + khui_cfg_set_flags(d->node, + 0, + KHUI_CNFLAG_MODIFIED); + } + + return TRUE; + } + break; + + case KHUI_WM_CFG_NOTIFY: + if (HIWORD(wParam) == WMCFG_APPLY) { + wchar_t wtkt_string[MAX_PATH]; + char tkt_string[MAX_PATH]; + int t; + + d = (k4_config_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + return TRUE; + + t = GetDlgItemText(hwnd, IDC_CFG_CACHE, + wtkt_string, ARRAYLENGTH(wtkt_string)); + if (t == 0) + return TRUE; + + UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), wtkt_string); + + if (_stricmp(tkt_string, d->tkt_string)) { + + pkrb_set_tkt_string(tkt_string); + + khc_write_string(csp_params, L"TktString", wtkt_string); + + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | + KHUI_CNFLAG_MODIFIED); + khm_krb4_list_tickets(); + } else { + khui_cfg_set_flags(d->node, + 0, + KHUI_CNFLAG_MODIFIED); + } + + return TRUE; + } + break; + + case WM_DESTROY: + d = (k4_config_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d) { + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) 0); + } + + break; + } + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.c b/krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.c new file mode 100644 index 000000000..e5287ca9f --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.c @@ -0,0 +1,897 @@ +/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies +* of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +/* $Id$ */ + +/* Originally this was krb5routines.c in Leash sources. Subsequently +modified and adapted for NetIDMgr */ + +#include<krbcred.h> +#include<kherror.h> + +#define SECURITY_WIN32 +#include <security.h> + +#include <string.h> +#include <time.h> +#include <assert.h> +#include <strsafe.h> + + + +int com_addr(void) +{ + long ipAddr; + char loc_addr[ADDR_SZ]; + CREDENTIALS cred; + char service[40]; + char instance[40]; + // char addr[40]; + char realm[40]; + struct in_addr LocAddr; + int k_errno; + + if (pkrb_get_cred == NULL) + return(KSUCCESS); + + k_errno = (*pkrb_get_cred)(service,instance,realm,&cred); + if (k_errno) + return KRBERR(k_errno); + + while(1) { + ipAddr = (*pLocalHostAddr)(); + LocAddr.s_addr = ipAddr; + StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr)); + if ( strcmp(cred.address,loc_addr) != 0) { + /* TODO: do something about this */ + //Leash_kdestroy (); + break; + } + break; + } // while() + return 0; +} + + +long +khm_krb4_list_tickets(void) +{ + char ptktname[MAX_PATH + 5]; + char pname[ANAME_SZ]; + char pinst[INST_SZ]; + char prealm[REALM_SZ]; + wchar_t wbuf[256]; + int k_errno = 0; + CREDENTIALS c; + int newtickets = 0; + int open = 0; + khm_handle ident = NULL; + khm_handle cred = NULL; + time_t tt; + FILETIME ft; + + kcdb_credset_flush(krb4_credset); + + // Since krb_get_tf_realm will return a ticket_file error, + // we will call tf_init and tf_close first to filter out + // things like no ticket file. Otherwise, the error that + // the user would see would be + // klist: can't find realm of ticket file: No ticket file (tf_util) + // instead of klist: No ticket file (tf_util) + if (ptf_init == NULL) + goto collect; + + com_addr(); + + // Open ticket file + if ((k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))) + { + goto cleanup; + } + // Close ticket file + (void) (*ptf_close)(); + + // We must find the realm of the ticket file here before calling + // tf_init because since the realm of the ticket file is not + // really stored in the principal section of the file, the + // routine we use must itself call tf_init and tf_close. + + if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS) + { + goto cleanup; + } + + // Open ticket file + if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL)) + { + goto cleanup; + } + + StringCchCopyA(ptktname, ARRAYLENGTH(ptktname), (*ptkt_string)()); + + open = 1; + + // Get principal name and instance + if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst))) + { + goto cleanup; + } + + // You may think that this is the obvious place to get the + // realm of the ticket file, but it can't be done here as the + // routine to do this must open the ticket file. This is why + // it was done before tf_init. + StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S", (LPSTR)pname, + (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst, + (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm); + + if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE, &ident))) + { + goto cleanup; + } + + // Get KRB4 tickets + while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS) + { + StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S", + c.service, + (c.instance[0] ? "." : ""), + c.instance, + (c.realm[0] ? "@" : ""), + c.realm); + + if(KHM_FAILED(kcdb_cred_create(wbuf, ident, credtype_id_krb4, &cred))) + continue; + + tt = c.issue_date + c.lifetime * 5L * 60L; + TimetToFileTime(tt, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &ft, sizeof(ft)); + + tt = c.issue_date; + TimetToFileTime(tt, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft)); + + tt = c.lifetime * 5L * 60L; + TimetToFileTimeInterval(tt, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ft, sizeof(ft)); + + AnsiStrToUnicode(wbuf, sizeof(wbuf), ptktname); + kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wbuf, KCDB_CBSIZE_AUTO); + + kcdb_credset_add_cred(krb4_credset, cred, -1); + + kcdb_cred_release(cred); + } // while + + cleanup: + if (ptf_close == NULL) + return(KSUCCESS); + + if (open) + (*ptf_close)(); //close ticket file + + if (k_errno == EOF) + k_errno = 0; + + // XXX the if statement directly below was inserted to eliminate + // an error NO_TKT_FIL on Leash startup. The error occurs from an + // error number thrown from krb_get_tf_realm. We believe this + // change does not eliminate other errors, but it may. + + if (k_errno == NO_TKT_FIL) + k_errno = 0; + + if(ident) + kcdb_identity_release(ident); + +#if 0 + /*TODO: Handle errors here */ + if (k_errno) + { + CHAR message[256]; + CHAR errBuf[256]; + LPCSTR errText; + + if (!Lerror_message) + return -1; + + errText = err_describe(errBuf, KRBERR(k_errno)); + + sprintf(message, "%s\n\n%s failed", errText, functionName); + MessageBox(NULL, message, "Kerberos Four", + MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND); + } +#endif + + collect: + kcdb_credset_collect(NULL, krb4_credset, ident, credtype_id_krb4, NULL); + + return k_errno; +} + +#define KRB_FILE "KRB.CON" +#define KRBREALM_FILE "KRBREALM.CON" +#define KRB5_FILE "KRB5.INI" + +BOOL +khm_krb5_get_profile_file(LPSTR confname, UINT szConfname) +{ + char **configFile = NULL; + if (pkrb5_get_default_config_files(&configFile)) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + + return FALSE; + } + + *confname = 0; + + if (configFile) + { + StringCchCopyA(confname, szConfname, *configFile); + pkrb5_free_config_files(configFile); + } + + if (!*confname) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + } + + return FALSE; +} + +BOOL +khm_get_krb4_con_file(LPSTR confname, UINT szConfname) +{ + if (hKrb5 && !hKrb4) { + // hold krb.con where krb5.ini is located + CHAR krbConFile[MAX_PATH]=""; + LPSTR pFind; + + if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) { + GetWindowsDirectoryA(krbConFile,sizeof(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + + StringCbCatA(krbConFile, sizeof(krbConFile), "\\"); + } + + pFind = strrchr(krbConFile, '\\'); + + if (pFind) { + *pFind = '\0'; + + StringCbCatA(krbConFile, sizeof(krbConFile), "\\"); + StringCbCatA(krbConFile, sizeof(krbConFile), KRB_FILE); + } else { + krbConFile[0] = '\0'; + } + + StringCchCopyA(confname, szConfname, krbConFile); + } else if (hKrb4) { + size_t size = szConfname; + memset(confname, '\0', szConfname); + if (!pkrb_get_krbconf2(confname, &size)) { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB_FILE); + } + } + + return FALSE; +} + +int +readstring(FILE * file, char * buf, int len) +{ + int c,i; + memset(buf, '\0', sizeof(buf)); + for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++) + { + if (i < sizeof(buf)) { + if (c == '\n') { + buf[i] = '\0'; + return i; + } else { + buf[i] = (char)c; + } + } else { + if (c == '\n') { + buf[len-1] = '\0'; + return(i); + } + } + } + if (c == EOF) { + if (i > 0 && i < len) { + buf[i] = '\0'; + return(i); + } else { + buf[len-1] = '\0'; + return(-1); + } + } + return(-1); +} + +/*! \internal + \brief Return a list of configured realms + + The string that is returned is a set of null terminated unicode strings, + each of which denotes one realm. The set is terminated by a zero length + null terminated string. + + The caller should free the returned string using free() + + \return The string with the list of realms or NULL if the operation fails. +*/ +wchar_t * khm_krb5_get_realm_list(void) +{ + wchar_t * rlist = NULL; + + if (pprofile_get_subsection_names && pprofile_free_list) { + const char* rootSection[] = {"realms", NULL}; + const char** rootsec = rootSection; + char **sections = NULL, **cpp = NULL, *value = NULL; + + char krb5_conf[MAX_PATH+1]; + + if (!khm_krb5_get_profile_file(krb5_conf,sizeof(krb5_conf))) { + profile_t profile; + long retval; + const char *filenames[2]; + wchar_t * d; + size_t cbsize; + size_t t; + + filenames[0] = krb5_conf; + filenames[1] = NULL; + retval = pprofile_init(filenames, &profile); + if (!retval) { + retval = pprofile_get_subsection_names(profile, rootsec, &sections); + + if (!retval) + { + /* first figure out how much space to allocate */ + cbsize = 0; + for (cpp = sections; *cpp; cpp++) + { + cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1); + } + cbsize += sizeof(wchar_t); /* double null terminated */ + + rlist = PMALLOC(cbsize); + d = rlist; + for (cpp = sections; *cpp; cpp++) + { + AnsiStrToUnicode(d, cbsize, *cpp); + t = wcslen(d) + 1; + d += t; + cbsize -= sizeof(wchar_t) * t; + } + *d = L'\0'; + } + + pprofile_free_list(sections); + +#if 0 + retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value); + if ( value ) { + disable_noaddresses = config_boolean_to_int(value); + pprofile_release_string(value); + } +#endif + pprofile_release(profile); + } + } + } else { + FILE * file; + char krb_conf[MAX_PATH+1]; + char * p; + size_t cbsize, t; + wchar_t * d; + + if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) && +#if _MSC_VER >= 1400 + !fopen_s(&file, krb_conf, "rt") +#else + (file = fopen(krb_conf, "rt")) +#endif + ) + { + char lineBuf[256]; + + /*TODO: compute the actual required buffer size instead of hardcoding */ + cbsize = 16384; // arbitrary + rlist = PMALLOC(cbsize); + d = rlist; + + // Skip the default realm + readstring(file,lineBuf,sizeof(lineBuf)); + + // Read the defined realms + while (TRUE) + { + if (readstring(file,lineBuf,sizeof(lineBuf)) < 0) + break; + + if (*(lineBuf + strlen(lineBuf) - 1) == '\r') + *(lineBuf + strlen(lineBuf) - 1) = 0; + + for (p=lineBuf; *p ; p++) + { + if (isspace(*p)) { + *p = 0; + break; + } + } + + if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) { + t = strlen(lineBuf) + 1; + if(cbsize > (1 + t*sizeof(wchar_t))) { + AnsiStrToUnicode(d, cbsize, lineBuf); + d += t; + cbsize -= t * sizeof(wchar_t); + } else + break; + } + } + + *d = L'\0'; + + fclose(file); + } + } + + return rlist; +} + +/*! \internal + \brief Get the default realm + + A string will be returned that specifies the default realm. The caller + should free the string using free(). + + Returns NULL if the operation fails. +*/ +wchar_t * khm_krb5_get_default_realm(void) +{ + wchar_t * realm; + size_t cch; + krb5_context ctx=0; + char * def = 0; + + pkrb5_init_context(&ctx); + pkrb5_get_default_realm(ctx,&def); + + if (def) { + cch = strlen(def) + 1; + realm = PMALLOC(sizeof(wchar_t) * cch); + AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def); + pkrb5_free_default_realm(ctx, def); + } else + realm = NULL; + + pkrb5_free_context(ctx); + + return realm; +} + +static +char * +make_postfix(const char * base, + const char * postfix, + char ** rcopy) +{ + size_t base_size; + size_t ret_size; + char * copy = 0; + char * ret = 0; + size_t t; + + if (FAILED(StringCbLengthA(base, STRSAFE_MAX_CCH * sizeof(char), &t))) + goto cleanup; + + base_size = t + 1; + + if (FAILED(StringCbLengthA(postfix, STRSAFE_MAX_CCH * sizeof(char), &t))) + goto cleanup; + + ret_size = base_size + t + 1; + + copy = malloc(base_size); + ret = malloc(ret_size); + + if (!copy || !ret) + goto cleanup; + + StringCbCopyNA(copy, base_size, base, base_size); + StringCbCopyNA(ret, ret_size, base, base_size); + StringCbCopyNA(ret + (base_size - 1), ret_size - (base_size - 1), + postfix, ret_size - (base_size - 1)); + + cleanup: + if (!copy || !ret) { + if (copy) + free(copy); + if (ret) + free(ret); + copy = ret = 0; + } + // INVARIANT: (ret ==> copy) && (copy ==> ret) + *rcopy = copy; + return ret; +} + +void +khm_krb4_set_def_tkt_string(void) { + wchar_t wtkt_string[MAX_PATH]; + char tkt_string[MAX_PATH]; + khm_size cb; + + cb = sizeof(wtkt_string); + + if (KHM_FAILED(khc_read_string(csp_params, L"TktString", + wtkt_string, &cb)) || + wtkt_string[0] == L'\0') { + + pkrb_set_tkt_string(0); + + } else { + + UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), + wtkt_string); + pkrb_set_tkt_string(tkt_string); + } +} + + +static +long +make_temp_cache_v4(const char * postfix) +{ + static char * old_cache = 0; + + if (!pkrb_set_tkt_string || !ptkt_string || !pdest_tkt) + return 0; // XXX - is this appropriate? + + if (old_cache) { + pdest_tkt(); + pkrb_set_tkt_string(old_cache); + free(old_cache); + old_cache = 0; + } + + if (postfix) + { + char * tmp_cache = make_postfix(ptkt_string(), postfix, &old_cache); + + if (!tmp_cache) + return KFAILURE; + + pkrb_set_tkt_string(tmp_cache); + free(tmp_cache); + } + return 0; +} + +long +khm_krb4_changepwd(char * principal, + char * password, + char * newpassword, + char** error_str) +{ + long k_errno; + + if (!pkrb_set_tkt_string || !ptkt_string || !pkadm_change_your_password || + !pdest_tkt) + return KFAILURE; + + k_errno = make_temp_cache_v4("_chgpwd"); + if (k_errno) return k_errno; + k_errno = pkadm_change_your_password(principal, password, newpassword, + error_str); + make_temp_cache_v4(0); + return k_errno; +} + +struct tgt_filter_data { + khm_handle identity; + wchar_t realm[KCDB_IDENT_MAXCCH_NAME]; +}; + +khm_int32 KHMAPI +krb4_tgt_filter(khm_handle cred, khm_int32 flags, void * rock) { + struct tgt_filter_data * pdata; + wchar_t credname[KCDB_MAXCCH_NAME]; + wchar_t * t; + khm_size cb; + khm_int32 ctype; + + pdata = (struct tgt_filter_data *) rock; + cb = sizeof(credname); + + if (KHM_FAILED(kcdb_cred_get_type(cred, &ctype)) || + ctype != credtype_id_krb4) + return 0; + + if (KHM_FAILED(kcdb_cred_get_name(cred, credname, &cb))) + return 0; + + if (wcsncmp(credname, L"krbtgt.", 7)) + return 0; + + t = wcsrchr(credname, L'@'); + if (t == NULL) + return 0; + + if (wcscmp(t+1, pdata->realm)) + return 0; + + return 1; +} + +khm_handle +khm_krb4_find_tgt(khm_handle credset, khm_handle identity) { + khm_handle result = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * t; + khm_size cb; + struct tgt_filter_data filter_data; + + cb = sizeof(idname); + + if (KHM_FAILED(kcdb_identity_get_name(identity, + idname, + &cb))) + return NULL; + + t = wcsrchr(idname, L'@'); + if (t == NULL) + return NULL; + + StringCbCopy(filter_data.realm, sizeof(filter_data.realm), + t + 1); + filter_data.identity = identity; + + if (KHM_FAILED(kcdb_credset_find_filtered(credset, + -1, + krb4_tgt_filter, + &filter_data, + &result, + NULL))) + return NULL; + else + return result; +} + +long +khm_convert524(khm_handle identity) +{ +#ifdef NO_KRB5 + return(0); +#else + krb5_context ctx = 0; + krb5_error_code code = 0; + int icode = 0; + krb5_principal me = 0; + krb5_principal server = 0; + krb5_creds *v5creds = 0; + krb5_creds increds; + krb5_ccache cc = 0; + CREDENTIALS * v4creds = NULL; + static int init_ets = 1; + + if (!pkrb5_init_context || + !pkrb_in_tkt || + !pkrb524_init_ets || + !pkrb524_convert_creds_kdc) + return 0; + + v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS)); + memset((char *) v4creds, 0, sizeof(CREDENTIALS)); + + memset((char *) &increds, 0, sizeof(increds)); + /* + From this point on, we can goto cleanup because increds is + initialized. + */ + + code = khm_krb5_initialize(identity, &ctx, &cc); + if (code) + goto cleanup; + + if ( init_ets ) { + pkrb524_init_ets(ctx); + init_ets = 0; + } + + if (code = pkrb5_cc_get_principal(ctx, cc, &me)) + goto cleanup; + + if ((code = pkrb5_build_principal(ctx, + &server, + krb5_princ_realm(ctx, me)->length, + krb5_princ_realm(ctx, me)->data, + "krbtgt", + krb5_princ_realm(ctx, me)->data, + NULL))) { + goto cleanup; + } + + increds.client = me; + increds.server = server; + increds.times.endtime = 0; + increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + if ((code = pkrb5_get_credentials(ctx, 0, + cc, + &increds, + &v5creds))) { + goto cleanup; + } + + if ((icode = pkrb524_convert_creds_kdc(ctx, + v5creds, + v4creds))) { + goto cleanup; + } + + /* initialize ticket cache */ + if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm) + != KSUCCESS)) { + goto cleanup; + } + + /* stash ticket, session key, etc. for future use */ + if ((icode = pkrb_save_credentials(v4creds->service, + v4creds->instance, + v4creds->realm, + v4creds->session, + v4creds->lifetime, + v4creds->kvno, + &(v4creds->ticket_st), + v4creds->issue_date))) { + goto cleanup; + } + + cleanup: + memset(v4creds, 0, sizeof(v4creds)); + free(v4creds); + + if (v5creds) { + pkrb5_free_creds(ctx, v5creds); + } + if (increds.client == me) + me = 0; + if (increds.server == server) + server = 0; + + if (ctx) + pkrb5_free_cred_contents(ctx, &increds); + + if (server) { + pkrb5_free_principal(ctx, server); + } + + if (me) { + pkrb5_free_principal(ctx, me); + } + + if (ctx && cc) + pkrb5_cc_close(ctx, cc); + + if (ctx) { + pkrb5_free_context(ctx); + } + + return (code || icode); +#endif /* NO_KRB5 */ +} + +long +khm_krb4_kinit(char * aname, + char * inst, + char * realm, + long lifetime, + char * password) { + + wchar_t * functionName = NULL; + wchar_t * err_context = NULL; + int rc4 = 0; + int msg = 0; + + if (pkname_parse == NULL) { + goto cleanup; + } + + err_context = L"getting realm"; + if (!*realm && (rc4 = (int)(*pkrb_get_lrealm)(realm, 1))) { + functionName = L"krb_get_lrealm()"; + msg = IDS_ERR_REALM; + goto cleanup; + } + + err_context = L"checking principal"; + if ((!*aname) || (!(rc4 = (int)(*pk_isname)(aname)))) { + functionName = L"krb_get_lrealm()"; + msg = IDS_ERR_PRINCIPAL; + goto cleanup; + } + + /* optional instance */ + if (!(rc4 = (int)(*pk_isinst)(inst))) { + functionName = L"k_isinst()"; + msg = IDS_ERR_INVINST; + goto cleanup; + } + + if (!(rc4 = (int)(*pk_isrealm)(realm))) { + functionName = L"k_isrealm()"; + msg = IDS_ERR_REALM; + goto cleanup; + } + + khm_krb4_set_def_tkt_string(); + + err_context = L"fetching ticket"; + rc4 = (*pkrb_get_pw_in_tkt)(aname, inst, realm, "krbtgt", realm, + lifetime, password); + + if (rc4) /* XXX: do we want: && (rc != NO_TKT_FIL) as well? */ { + functionName = L"krb_get_pw_in_tkt()"; + msg = IDS_ERR_PWINTKT; + goto cleanup; + } + + return 0; + + cleanup: + { + _report_sr0(KHERR_ERROR, msg); + _location(functionName); + } + return rc4; +} + + +int khm_krb4_kdestroy(void) { + int k_errno = 0; + + if (pdest_tkt != NULL) + { + k_errno = (*pdest_tkt)(); + if (k_errno && (k_errno != RET_TKFIL)) + return KRBERR(k_errno); + } + + return k_errno; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.h b/krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.h new file mode 100644 index 000000000..05ed3e75d --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krb4funcs.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Adapted from multiple Leash header files */ + +#ifndef __KHIMAIRA_KRB5FUNCS_H +#define __KHIMAIRA_KRB5FUNCS_H + +#include<stdlib.h> +#include<krb5.h> + +#include <windows.h> +#define SECURITY_WIN32 +#include <security.h> + +#if _WIN32_WINNT < 0x0501 +#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include<ntsecapi.h> +#ifdef KHM_SAVE_WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT +#undef KHM_SAVE_WIN32_WINNT +#endif + +#include <krb5common.h> + +#define LEASH_DEBUG_CLASS_GENERIC 0 +#define LEASH_DEBUG_CLASS_KRB4 1 +#define LEASH_DEBUG_CLASS_KRB4_APP 2 + +#define LEASH_PRIORITY_LOW 0 +#define LEASH_PRIORITY_HIGH 1 + +#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */ + + +long +khm_convert524(khm_handle identity); + +long +khm_krb4_kinit(char * aname, + char * inst, + char * realm, + long lifetime, + char * password); + +long +khm_krb4_list_tickets(void); + +int khm_krb4_kdestroy(void); + +khm_handle +khm_krb4_find_tgt(khm_handle credset, + khm_handle identity); + +LONG +write_registry_setting( + char* setting, + DWORD type, + void* buffer, + size_t size + ); + +LONG +read_registry_setting_user( + char* setting, + void* buffer, + size_t size + ); + +LONG +read_registry_setting( + char* setting, + void* buffer, + size_t size + ); + +BOOL +get_STRING_from_registry( + HKEY hBaseKey, + char * key, + char * value, + char * outbuf, + DWORD outlen + ); + +BOOL +get_DWORD_from_registry( + HKEY hBaseKey, + char * key, + char * value, + DWORD * result + ); + +int +config_boolean_to_int( + const char *s + ); + +void +khm_krb4_set_def_tkt_string(void); + +wchar_t * khm_krb5_get_default_realm(void); +wchar_t * khm_krb5_get_realm_list(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krb4main.c b/krb5-1-6/src/windows/identity/plugins/krb4/krb4main.c new file mode 100644 index 000000000..6b1c395b2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krb4main.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> + +kmm_module h_khModule; /* KMM's handle to this module */ +HINSTANCE hInstance; +HMODULE hResModule; /* HMODULE to the resource library */ + +khm_int32 type_id_enctype = -1; +khm_int32 type_id_addr_list = -1; +khm_int32 type_id_krb5_flags = -1; + +khm_int32 attr_id_key_enctype = -1; +khm_int32 attr_id_tkt_enctype = -1; +khm_int32 attr_id_addr_list = -1; +khm_int32 attr_id_krb5_flags = -1; + +khm_handle csp_plugins = NULL; +khm_handle csp_krbcred = NULL; +khm_handle csp_params = NULL; + +kmm_module_locale locales[] = { + LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb4cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT) +}; + +int n_locales = ARRAYLENGTH(locales); + +/* These two probably should not do anything */ +void init_krb() { +} + +void exit_krb() { +} + +/* called by the NetIDMgr module manager */ +KHMEXP_EXP khm_int32 KHMAPI init_module(kmm_module h_module) { + khm_int32 rv = KHM_ERROR_SUCCESS; + kmm_plugin_reg pi; + wchar_t buf[256]; + + h_khModule = h_module; + + rv = kmm_set_locale_info(h_module, locales, n_locales); + if(KHM_SUCCEEDED(rv)) { + hResModule = kmm_get_resource_hmodule(h_module); + } else + goto _exit; + + ZeroMemory(&pi, sizeof(pi)); + pi.name = KRB4_PLUGIN_NAME; + pi.type = KHM_PITYPE_CRED; + pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN), + IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + pi.flags = 0; + pi.msg_proc = krb4_cb; + pi.dependencies = KRB4_PLUGIN_DEPS; + pi.description = buf; + LoadString(hResModule, IDS_PLUGIN_DESC, + buf, ARRAYLENGTH(buf)); + kmm_provide_plugin(h_module, &pi); + + if(KHM_FAILED(rv = init_imports())) + goto _exit; + + if(KHM_FAILED(rv = init_error_funcs())) + goto _exit; + + rv = kmm_get_plugins_config(0, &csp_plugins); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_load_schema(csp_plugins, schema_krbconfig); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_open_space(csp_plugins, CSNAME_KRB4CRED, 0, &csp_krbcred); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params); + if(KHM_FAILED(rv)) goto _exit; + + _exit: + return rv; +} + +/* called by the NetIDMgr module manager */ +KHMEXP_EXP khm_int32 KHMAPI exit_module(kmm_module h_module) { + exit_imports(); + exit_error_funcs(); + + if(csp_params) { + khc_close_space(csp_params); + csp_params = NULL; + } + + if(csp_krbcred) { + khc_close_space(csp_krbcred); + csp_krbcred = NULL; + } + + if(csp_plugins) { + khc_unload_schema(csp_plugins, schema_krbconfig); + khc_close_space(csp_plugins); + csp_plugins = NULL; + } + + return KHM_ERROR_SUCCESS; /* the return code is ignored */ +} + +BOOL WINAPI DllMain( + HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved +) +{ + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + hInstance = hinstDLL; + init_krb(); + break; + + case DLL_PROCESS_DETACH: + exit_krb(); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + } + + return TRUE; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krb4newcreds.c b/krb5-1-6/src/windows/identity/plugins/krb4/krb4newcreds.c new file mode 100644 index 000000000..9c200b618 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krb4newcreds.c @@ -0,0 +1,884 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<khuidefs.h> +#include<utils.h> +#include<commctrl.h> +#include<strsafe.h> +#include<krb5.h> +#include<assert.h> + +/* method identifiers should be contiguous */ +#define K4_METHOD_AUTO 0 +#define K4_METHOD_PASSWORD 1 +#define K4_METHOD_K524 2 + +int method_to_id[] = { + IDC_NCK4_AUTO, + IDC_NCK4_PWD, + IDC_NCK4_K524 +}; + +typedef struct tag_k4_dlg_data { + HWND hwnd; + khui_new_creds * nc; + khui_new_creds_by_type * nct; + + khm_boolean k4_enabled; + khm_int32 method; + time_t lifetime; +} k4_dlg_data; + +void k4_update_display(k4_dlg_data * d, BOOL update_methods) { + CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN, + (d->k4_enabled)?BST_CHECKED: BST_UNCHECKED); + + if (d->k4_enabled) { + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), TRUE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), TRUE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), TRUE); + } else { + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), FALSE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), FALSE); + } + +#ifdef DEBUG + assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id)); +#endif + + CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD, method_to_id[d->method]); + + khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled); +} + +void k4_update_data(k4_dlg_data * d) { + int i; + khm_boolean oldstate; + + oldstate = d->k4_enabled; + + if (IsDlgButtonChecked(d->hwnd, IDC_NCK4_OBTAIN) == BST_CHECKED) + d->k4_enabled = TRUE; + else + d->k4_enabled = FALSE; + + if ((oldstate && !d->k4_enabled) || + (!oldstate && d->k4_enabled)) { + + khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled); + } + + d->method = K4_METHOD_AUTO; + + for (i=K4_METHOD_AUTO; i<=K4_METHOD_K524; i++) { + if (IsDlgButtonChecked(d->hwnd, method_to_id[i]) == BST_CHECKED) { + d->method = i; + break; + } + } +} + +khm_boolean k4_should_identity_get_k4(khm_handle ident) { + khm_int32 idflags = 0; + khm_int32 t = TRUE; + khm_handle csp_ident = NULL; + khm_handle csp_k4 = NULL; + khm_boolean get_k4 = TRUE; + khm_boolean id_spec = FALSE; + + if (KHM_FAILED(kcdb_identity_get_flags(ident, &idflags))) + return FALSE; + + if (!(idflags & KCDB_IDENT_FLAG_DEFAULT)) { + /* we only support k4 for one identity, and that is the + default identity. If we are trying to get tickets for a + non-default identity, then we start off as disabled unless + there is no default identity. */ + + khm_handle defident = NULL; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&defident))) { + kcdb_identity_release(defident); + + return FALSE; + } + } + + if (KHM_SUCCEEDED(kcdb_identity_get_config(ident, 0, &csp_ident))) { + if (KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB4CRED, 0, + &csp_k4))) { + khm_int32 t = 0; + + if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t))) { + get_k4 = !!t; + id_spec = TRUE; + } + + khc_close_space(csp_k4); + } + khc_close_space(csp_ident); + } + + /* if there was a value specified for the identity, then that + takes precedence. */ + if (id_spec || !get_k4) + return get_k4; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)) && + !t) + return FALSE; + + return TRUE; +} + +void k4_read_identity_data(k4_dlg_data * d) { + khm_handle csp_ident = NULL; + khm_handle csp_k4 = NULL; + + khm_int32 idflags = 0; + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t))) + d->k4_enabled = !!t; + else + d->k4_enabled = TRUE; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4Method", &t))) + d->method = t; + else + d->method = K4_METHOD_AUTO; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"DefaultLifetime", &t))) + d->lifetime = t; + else + d->lifetime = 10 * 60 * 60; /* 10 hours */ + + if (d->nc->n_identities > 0 && + d->nc->identities[0]) { + + if (KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0], + 0, + &csp_ident))) { + + khc_open_space(csp_ident, CSNAME_KRB4CRED, 0, &csp_k4); + + if (csp_k4) { + if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t))) + d->k4_enabled = !!t; + if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4Method", &t))) + d->method = t; + khc_close_space(csp_k4); + } + + khc_close_space(csp_ident); + } + + if (d->k4_enabled) { + d->k4_enabled = k4_should_identity_get_k4(d->nc->identities[0]); + } + } else { + d->k4_enabled = FALSE; + } + + if (d->method < 0 || d->method > K4_METHOD_K524) + d->method = K4_METHOD_AUTO; +} + +void k4_write_identity_data(k4_dlg_data * d) { + khm_handle csp_ident = NULL; + khm_handle csp_k4 = NULL; + + if (d->nc->n_identities > 0 && + d->nc->identities[0] && + KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0], + KHM_FLAG_CREATE, + &csp_ident))) { + khc_open_space(csp_ident, CSNAME_KRB4CRED, + KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD, + &csp_k4); + + if (csp_k4) { + khc_write_int32(csp_k4, L"Krb4NewCreds", !!d->k4_enabled); + khc_write_int32(csp_k4, L"Krb4Method", d->method); + + khc_close_space(csp_k4); + } + + khc_close_space(csp_ident); + } +} + +void k4_handle_wmnc_notify(k4_dlg_data * d, + WPARAM wParam, + LPARAM lParam) { + switch(HIWORD(wParam)) { + case WMNC_UPDATE_CREDTEXT: + { + if (d->nct->credtext) { + PFREE(d->nct->credtext); + d->nct->credtext = NULL; + } + + if (d->nc->n_identities > 0 && + d->nc->identities[0]) { + + khm_int32 flags = 0; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * atsign; + wchar_t * realm; + khm_size cb; + + kcdb_identity_get_flags(d->nc->identities[0], &flags); + + if (!(flags & KCDB_IDENT_FLAG_VALID)) { + break; + } + + cb = sizeof(idname); + kcdb_identity_get_name(d->nc->identities[0], idname, + &cb); + + atsign = wcsrchr(idname, L'@'); + + if (atsign == NULL || !atsign[1]) + break; + + realm = ++atsign; + + if (d->k4_enabled) { + wchar_t wmethod[128]; + wchar_t wfmt[128]; + wchar_t wct[512]; + + LoadString(hResModule, IDS_CT_TGTFOR, + wfmt, ARRAYLENGTH(wfmt)); + + if (d->method == K4_METHOD_AUTO) + LoadString(hResModule, IDS_METHOD_AUTO, wmethod, + ARRAYLENGTH(wmethod)); + else if (d->method == K4_METHOD_PASSWORD) + LoadString(hResModule, IDS_METHOD_PWD, wmethod, + ARRAYLENGTH(wmethod)); + else if (d->method == K4_METHOD_K524) + LoadString(hResModule, IDS_METHOD_K524, wmethod, + ARRAYLENGTH(wmethod)); + else { + assert(FALSE); + } + + StringCbPrintf(wct, sizeof(wct), wfmt, realm, wmethod); + + StringCbLength(wct, sizeof(wct), &cb); + cb += sizeof(wchar_t); + + d->nct->credtext = PMALLOC(cb); + + StringCbCopy(d->nct->credtext, cb, wct); + } else { + wchar_t wct[256]; + + LoadString(hResModule, IDS_CT_DISABLED, + wct, ARRAYLENGTH(wct)); + + StringCbLength(wct, sizeof(wct), &cb); + cb += sizeof(wchar_t); + + d->nct->credtext = PMALLOC(cb); + + StringCbCopy(d->nct->credtext, cb, wct); + } + } + /* no identities were selected. it is not the + responsibility of krb4 to complain about this. */ + } + break; + + case WMNC_IDENTITY_CHANGE: + k4_read_identity_data(d); + k4_update_display(d, TRUE); + break; + + case WMNC_CREDTEXT_LINK: + { + wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD]; + wchar_t * wids; + khui_htwnd_link * l; + + l = (khui_htwnd_link *) lParam; + + StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len); + wids = wcschr(wid, L':'); + + if (!wids) + break; + else + wids++; + + if (!wcscmp(wids, L"Enable")) { + d->k4_enabled = TRUE; + + k4_update_display(d, TRUE); + khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE); + } + } + break; + } +} + +INT_PTR CALLBACK k4_nc_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + k4_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + { + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->nc = (khui_new_creds *) lParam; + khui_cw_find_type(d->nc, credtype_id_krb4, &d->nct); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d); +#pragma warning(pop) + + d->nct->aux = (LPARAM) d; + d->hwnd = hwnd; + + d->k4_enabled = TRUE; + d->method = K4_METHOD_AUTO; + + k4_update_display(d, TRUE); + } + break; + + case WM_COMMAND: + { + if (HIWORD(wParam) == BN_CLICKED) { + d = (k4_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + k4_update_data(d); + + if (LOWORD(wParam) == IDC_NCK4_OBTAIN) { + k4_update_display(d, TRUE); + } + + return TRUE; + } + } + break; + + case KHUI_WM_NC_NOTIFY: + { + d = (k4_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + k4_handle_wmnc_notify(d, wParam, lParam); + } + break; + + case WM_DESTROY: + { + d = (k4_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + d->nct->aux = 0; + + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + } + break; + } + + return FALSE; +} + +khm_int32 +krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) { + + switch(msg_subtype) { + case KMSG_CRED_NEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + khm_size cbsize; + wchar_t wbuf[256]; + + nc = (khui_new_creds *) vparam; + + nct = PMALLOC(sizeof(*nct)); +#ifdef DEBUG + assert(nct); +#endif + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id_krb4; + nct->ordinal = 3; + LoadString(hResModule, IDS_NC_K4_SHORT, + wbuf, ARRAYLENGTH(wbuf)); + StringCbLength(wbuf, sizeof(wbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->name = PMALLOC(cbsize); + StringCbCopy(nct->name, cbsize, wbuf); + + nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; + + nct->h_module = hResModule; + nct->dlg_proc = k4_nc_dlg_proc; + nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4); + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_RENEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + khm_size cbsize; + wchar_t wbuf[256]; + + nc = (khui_new_creds *) vparam; + + if (!nc->ctx.identity) + break; + + nct = PMALLOC(sizeof(*nct)); +#ifdef DEBUG + assert(nct); +#endif + + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id_krb4; + nct->ordinal = 3; + LoadString(hResModule, IDS_NC_K4_SHORT, + wbuf, ARRAYLENGTH(wbuf)); + StringCbLength(wbuf, sizeof(wbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->name = PMALLOC(cbsize); + StringCbCopy(nct->name, cbsize, wbuf); + + nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_DIALOG_SETUP: + break; + + case KMSG_CRED_PROCESS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct = NULL; + khm_handle ident = NULL; + k4_dlg_data * d = NULL; + long code = 0; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + nc = (khui_new_creds *) vparam; + if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) + break; + + if (nc->subtype == KMSG_CRED_NEW_CREDS || + nc->subtype == KMSG_CRED_RENEW_CREDS) { + khm_int32 method; + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + + d = (k4_dlg_data *) nct->aux; + if (!d || + nc->n_identities == 0 || + nc->identities[0] == NULL || + nc->result != KHUI_NC_RESULT_PROCESS) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + break; + } + + if (!d->k4_enabled) { + k4_write_identity_data(d); + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + break; + } + + method = d->method; + ident = nc->identities[0]; + + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + _begin_task(0); + _report_mr2(KHERR_NONE, MSG_K4_NEW_CREDS, + _cstr(ident), _int32(method)); + _resolve(); + _describe(); + + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + + if ((nc->ctx.scope == KHUI_SCOPE_IDENT && + nc->ctx.identity != NULL) || + + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE && + nc->ctx.cred_type == credtype_id_krb4 && + nc->ctx.identity != NULL) || + + (nc->ctx.scope == KHUI_SCOPE_CRED && + nc->ctx.cred_type == credtype_id_krb4 && + nc->ctx.identity != NULL && + nc->ctx.cred != NULL)) { + + ident = nc->ctx.identity; + + if (!k4_should_identity_get_k4(ident)) { + + _reportf(L"Kerberos 4 is not enabled for this identity. Skipping"); + + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_FAILED | + KHUI_NC_RESPONSE_EXIT); + break; + } + + } else { + + _reportf(L"Kerberos 4 is not within renewal scope. Skipping"); + + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_FAILED | + KHUI_NC_RESPONSE_EXIT); + break; + } + + method = K4_METHOD_K524; /* only k524 is supported + for renewals */ + + _begin_task(0); + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + _report_mr2(KHERR_NONE, MSG_K4_RENEW_CREDS, + _cstr(ident), _int32(method)); + _resolve(); + _describe(); + } else { + assert(FALSE); + break; + } + + if ((method == K4_METHOD_AUTO || + method == K4_METHOD_K524) && + khui_cw_type_succeeded(nc, credtype_id_krb5)) { + + khm_handle tgt; + FILETIME ft_prev; + FILETIME ft_new; + khm_size cb; + + _report_mr0(KHERR_INFO, MSG_K4_TRY_K524); + + tgt = khm_krb4_find_tgt(NULL, ident); + if (tgt) { + cb = sizeof(ft_prev); + if (KHM_FAILED(kcdb_cred_get_attr(tgt, + KCDB_ATTR_EXPIRE, + NULL, + &ft_prev, + &cb))) + ZeroMemory(&ft_prev, sizeof(ft_prev)); + kcdb_cred_release(tgt); + } + + code = khm_convert524(ident); + + _reportf(L"khm_convert524 returns code %d", code); + + if (code == 0) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + assert(d != NULL); + + k4_write_identity_data(d); + + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS && + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE || + nc->ctx.scope == KHUI_SCOPE_CRED)) { + + khm_krb4_list_tickets(); + + tgt = khm_krb4_find_tgt(NULL, ident); + + if (tgt) { + cb = sizeof(ft_new); + ZeroMemory(&ft_new, sizeof(ft_new)); + + kcdb_cred_get_attr(tgt, + KCDB_ATTR_EXPIRE, + NULL, + &ft_new, + &cb); + + kcdb_cred_release(tgt); + } + + if (!tgt || + CompareFileTime(&ft_new, + &ft_prev) <= 0) { + /* The new TGT wasn't much of an + improvement over what we already + had. We should go out and try to + renew the identity now. */ + + khui_action_context ctx; + + _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal"); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->ctx.identity, + KCDB_CREDTYPE_INVALID, + NULL); + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + } + } + + _end_task(); + break; + + } else if (method == K4_METHOD_K524) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_FAILED | + KHUI_NC_RESPONSE_EXIT); + + if (nc->subtype == KMSG_CRED_RENEW_CREDS && + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE || + nc->ctx.scope == KHUI_SCOPE_CRED)) { + /* We were trying to get a new Krb4 TGT + for this identity. Sometimes this + fails because of restrictions placed on + K524d regarding the lifetime of the + issued K4 TGT. In this case, we + trigger a renewal of the identity in + the hope that the new K5 TGT will allow + us to successfully get a new K4 TGT + next time over using the new K5 TGT. */ + + khui_action_context ctx; + + _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal."); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->ctx.identity, + KCDB_CREDTYPE_INVALID, + NULL); + + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + } + + _end_task(); + break; + + } + } + + /* only supported for new credentials */ + if (method == K4_METHOD_AUTO || + method == K4_METHOD_PASSWORD) { + + khm_size n_prompts = 0; + khm_size idx; + khm_size cb; + wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE]; + char pwd[KHUI_MAXCCH_PROMPT_VALUE]; + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + char idname[KCDB_IDENT_MAXCCH_NAME]; + + char * aname = NULL; + char * inst = NULL; + char * realm = NULL; + + assert(nc->subtype == KMSG_CRED_NEW_CREDS); + + _report_mr0(KHERR_INFO, MSG_K4_TRY_PASSWORD); + + code = TRUE; /* just has to be non-zero */ + + khui_cw_get_prompt_count(nc, &n_prompts); + + if (n_prompts == 0) + goto _skip_pwd; + + for (idx = 0; idx < n_prompts; idx++) { + khui_new_creds_prompt * p; + + if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p))) + continue; + + if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD) + break; + } + + if (idx >= n_prompts) { + _reportf(L"Password prompt not found"); + goto _skip_pwd; + } + + khui_cw_sync_prompt_values(nc); + + cb = sizeof(wpwd); + if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx, + wpwd, + &cb))) { + _reportf(L"Failed to obtain password value"); + goto _skip_pwd; + } + + UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd); + + cb = sizeof(widname); + kcdb_identity_get_name(ident, + widname, + &cb); + + UnicodeStrToAnsi(idname, sizeof(idname), widname); + + { + char * atsign; + + atsign = strchr(idname, '@'); + if (atsign == NULL) { + _reportf(L"Identity name does not contain an '@'"); + goto _skip_pwd; + } + + *atsign++ = 0; + + realm = atsign; + } + + { + char * slash; + + slash = strchr(idname, '/'); + if (slash != NULL) { + *slash++ = 0; + inst = slash; + } else { + inst = ""; + } + } + + aname = idname; + + code = khm_krb4_kinit(aname, inst, realm, + (long) d->lifetime, pwd); + + _reportf(L"khm_krb4_kinit returns code %d", code); + + _skip_pwd: + + if (code) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_FAILED); + + } else { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_SUCCESS); + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + + assert(d != NULL); + k4_write_identity_data(d); + + } + } + } + + _end_task(); + } + } + break; + + case KMSG_CRED_END: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct = NULL; + + nc = (khui_new_creds *) vparam; + if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) + break; + + khui_cw_del_type(nc, credtype_id_krb4); + + if (nct->name) + PFREE(nct->name); + + if (nct->credtext) + PFREE(nct->credtext); + + PFREE(nct); + } + break; + } + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krb4plugin.c b/krb5-1-6/src/windows/identity/plugins/krb4/krb4plugin.c new file mode 100644 index 000000000..9a50249f7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krb4plugin.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<khuidefs.h> +#include<utils.h> +#include<commctrl.h> +#include<strsafe.h> +#include<krb5.h> + +khm_int32 credtype_id_krb4 = KCDB_CREDTYPE_INVALID; +khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID; + +khm_boolean krb4_initialized = FALSE; +khm_handle krb4_credset = NULL; + +/* Kerberos IV stuff */ +khm_int32 KHMAPI +krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_SYSTEM_INIT: + { +#ifdef _WIN64 + return KHM_ERROR_NOT_IMPLEMENTED; +#else + kcdb_credtype ct; + wchar_t buf[KCDB_MAXCCH_SHORT_DESC]; + size_t cbsize; + khui_config_node_reg reg; + wchar_t wshort_desc[KHUI_MAXCCH_SHORT_DESC]; + wchar_t wlong_desc[KHUI_MAXCCH_LONG_DESC]; + + /* perform critical registrations and initialization + stuff */ + ZeroMemory(&ct, sizeof(ct)); + ct.id = KCDB_CREDTYPE_AUTO; + ct.name = KRB4_CREDTYPE_NAME; + + if(LoadString(hResModule, IDS_KRB4_SHORT_DESC, + buf, ARRAYLENGTH(buf))) + { + StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize); + cbsize += sizeof(wchar_t); + ct.short_desc = PMALLOC(cbsize); + StringCbCopy(ct.short_desc, cbsize, buf); + } + + /* even though ideally we should be setting limits + based KCDB_MAXCB_LONG_DESC, our long description + actually fits nicely in KCDB_MAXCB_SHORT_DESC */ + if(LoadString(hResModule, IDS_KRB4_LONG_DESC, + buf, ARRAYLENGTH(buf))) + { + StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize); + cbsize += sizeof(wchar_t); + ct.long_desc = PMALLOC(cbsize); + StringCbCopy(ct.long_desc, cbsize, buf); + } + + ct.icon = NULL; /* TODO: set a proper icon */ + kmq_create_subscription(krb4_cb, &ct.sub); + + rv = kcdb_credtype_register(&ct, &credtype_id_krb4); + + if(KHM_SUCCEEDED(rv)) + rv = kcdb_credset_create(&krb4_credset); + + if (KHM_SUCCEEDED(rv)) + rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME, + &credtype_id_krb5); + + if(ct.short_desc) + PFREE(ct.short_desc); + + if(ct.long_desc) + PFREE(ct.long_desc); + + if (KHM_SUCCEEDED(rv)) { + khui_config_node idents; + + ZeroMemory(&reg, sizeof(reg)); + + reg.name = KRB4_CONFIG_NODE_NAME; + reg.short_desc = wshort_desc; + reg.long_desc = wlong_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_KRB4); + reg.dlg_proc = krb4_confg_proc; + reg.flags = 0; + + LoadString(hResModule, IDS_CFG_KRB4_LONG, + wlong_desc, ARRAYLENGTH(wlong_desc)); + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(NULL, &reg); + + khui_cfg_open(NULL, L"KhmIdentities", &idents); + + ZeroMemory(&reg, sizeof(reg)); + + reg.name = KRB4_IDS_CONFIG_NODE_NAME; + reg.short_desc = wshort_desc; + reg.long_desc = wlong_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_KRB4); + reg.dlg_proc = krb4_ids_config_proc; + reg.flags = KHUI_CNFLAG_SUBPANEL; + + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wlong_desc, ARRAYLENGTH(wlong_desc)); + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(idents, &reg); + + ZeroMemory(&reg, sizeof(reg)); + + reg.name = KRB4_ID_CONFIG_NODE_NAME; + reg.short_desc = wshort_desc; + reg.long_desc = wlong_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_KRB4); + reg.dlg_proc = krb4_id_config_proc; + reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL; + + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wlong_desc, ARRAYLENGTH(wlong_desc)); + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(idents, &reg); + + khui_cfg_release(idents); + + } + + /* Lookup common data types */ + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE, + &type_id_enctype))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST, + &type_id_addr_list))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS, + &type_id_krb5_flags))) { + rv = KHM_ERROR_UNKNOWN; + } + + /* Lookup common attributes */ + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE, + &attr_id_key_enctype))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE, + &attr_id_tkt_enctype))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST, + &attr_id_addr_list))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS, + &attr_id_krb5_flags))) { + rv = KHM_ERROR_UNKNOWN; + } + + krb4_initialized = TRUE; + + khm_krb4_set_def_tkt_string(); + + khm_krb4_list_tickets(); +#endif + } + break; + + case KMSG_SYSTEM_EXIT: +#ifdef _WIN64 + /* See above. On 64-bit platforms, we don't support Krb4 at + all. */ + return 0; +#else + if(credtype_id_krb4 >= 0) + { + /* basically just unregister the credential type */ + kcdb_credtype_unregister(credtype_id_krb4); + + kcdb_credset_delete(krb4_credset); + } + break; +#endif + } + + return rv; +} + +khm_int32 KHMAPI +krb4_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_CRED_REFRESH: + { + khm_krb4_list_tickets(); + } + break; + + case KMSG_CRED_DESTROY_CREDS: + { + khui_action_context * ctx; + khm_handle credset; + khm_size nc_root = 0; + khm_size nc_sel = 0; + + ctx = (khui_action_context *) vparam; + + /* if all krb4 tickets are selected, then we destroy all + of them. Otherwise, we do nothing. */ + + kcdb_credset_create(&credset); + + kcdb_credset_extract(credset, ctx->credset, + NULL, credtype_id_krb4); + kcdb_credset_get_size(credset, &nc_sel); + + kcdb_credset_flush(credset); + + kcdb_credset_extract(credset, NULL, + NULL, credtype_id_krb4); + kcdb_credset_get_size(credset, &nc_root); + + kcdb_credset_delete(credset); + + if (nc_root == nc_sel) { + khm_krb4_kdestroy(); + } + } + break; + + default: + if (IS_CRED_ACQ_MSG(msg_subtype)) + return krb4_msg_newcred(msg_type, msg_subtype, uparam, vparam); + } + + return rv; +} + +khm_int32 KHMAPI +krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + switch(msg_type) { + case KMSG_SYSTEM: + return krb4_msg_system(msg_type, msg_subtype, uparam, vparam); + case KMSG_CRED: + return krb4_msg_cred(msg_type, msg_subtype, uparam, vparam); + } + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krbconfig.csv b/krb5-1-6/src/windows/identity/plugins/krb4/krbconfig.csv new file mode 100644 index 000000000..3d791214b --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krbconfig.csv @@ -0,0 +1,17 @@ +Name,Type,Value,Description +Krb4Cred,KC_SPACE,0,"Kerberos IV Credentials Provider" + Module,KC_STRING,"MITKrb4", + Description,KC_STRING,"Kerberos IV Credentials Provider", + Dependencies,KC_STRING,Krb5Cred, + Type,KC_INT32,1, + Flags,KC_INT32,0, + Parameters,KC_SPACE,0,Parameters for KrbCred + Krb4NewCreds,KC_INT32,1,Obtain Kerberos 4 tickets (Boolean) + Krb4Method,KC_INT32,0,Method for acquiring K4 tix. 0-Auto;1-Password;2-K524 + CreateMissingConfig,KC_INT32,0,Create missing configuration files + DefaultLifetime,KC_INT32,36000,Default ticket lifetime + MaxLifetime,KC_INT32,86400,Maximum lifetime + MinLifetime,KC_INT32,60,Minimum lifetime + TktString,KC_STRING,,Ticket string. Use default if NULL + Parameters,KC_ENDSPACE,0, +Krb4Cred,KC_ENDSPACE,0, diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/krbcred.h b/krb5-1-6/src/windows/identity/plugins/krb4/krbcred.h new file mode 100644 index 000000000..0b6a148ee --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/krbcred.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KRBAFSCRED_H +#define __KHIMAIRA_KRBAFSCRED_H + +#include<windows.h> + +#define KHERR_FACILITY L"Krb4Cred" +#define KHERR_FACILITY_ID 65 +#define KHERR_HMODULE hResModule + +#include<netidmgr.h> + +#include<krb4funcs.h> +#include<krb5common.h> +#include<errorfuncs.h> +#include<dynimport.h> + +#include<langres.h> +#include<krb4_msgs.h> + +#define TYPENAME_ENCTYPE L"EncType" +#define TYPENAME_ADDR_LIST L"AddrList" +#define TYPENAME_KRB5_FLAGS L"Krb5Flags" + +#define ATTRNAME_KEY_ENCTYPE L"KeyEncType" +#define ATTRNAME_TKT_ENCTYPE L"TktEncType" +#define ATTRNAME_ADDR_LIST L"AddrList" +#define ATTRNAME_KRB5_FLAGS L"Krb5Flags" +#define ATTRNAME_RENEW_TILL L"RenewTill" +#define ATTRNAME_RENEW_FOR L"RenewFor" + +void init_krb(); +void exit_krb(); + +/* globals */ +extern kmm_module h_khModule; +extern HMODULE hResModule; +extern HINSTANCE hInstance; + +extern khm_int32 type_id_enctype; +extern khm_int32 type_id_addr_list; +extern khm_int32 type_id_krb5_flags; + +extern khm_int32 attr_id_key_enctype; +extern khm_int32 attr_id_tkt_enctype; +extern khm_int32 attr_id_addr_list; +extern khm_int32 attr_id_krb5_flags; +extern khm_int32 attr_id_renew_till; +extern khm_int32 attr_id_renew_for; + +/* Configuration spaces */ +#define CSNAME_KRB4CRED L"Krb4Cred" +#define CSNAME_PARAMS L"Parameters" + +/* plugin constants */ +#define KRB4_PLUGIN_NAME L"Krb4Cred" + +#define KRB4_PLUGIN_DEPS L"Krb5Cred\0" + +#define KRB4_CREDTYPE_NAME L"Krb4Cred" + +#define KRB5_CREDTYPE_NAME L"Krb5Cred" + +#define KRB4_CONFIG_NODE_NAME L"Krb4Config" + +#define KRB4_ID_CONFIG_NODE_NAME L"Krb4IdentConfig" +#define KRB4_IDS_CONFIG_NODE_NAME L"Krb4IdentsConfig" + +extern khm_handle csp_plugins; +extern khm_handle csp_krbcred; +extern khm_handle csp_params; + +extern kconf_schema schema_krbconfig[]; + +/* other globals */ +extern khm_int32 credtype_id_krb4; +extern khm_int32 credtype_id_krb5; + +extern khm_boolean krb4_initialized; + +extern khm_handle krb4_credset; + +/* plugin callbacks */ +khm_int32 KHMAPI +krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam); + +INT_PTR CALLBACK +krb4_confg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +krb4_ids_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +krb4_id_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +khm_int32 +krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam); +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/lang/en_us/langres.rc b/krb5-1-6/src/windows/identity/plugins/krb4/lang/en_us/langres.rc new file mode 100644 index 000000000..1c011ab9c --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/lang/en_us/langres.rc @@ -0,0 +1,205 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\..\langres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\..\\langres.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NC_KRB4 DIALOGEX 0, 0, 300, 166 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Kerberos v4 Ticket Options",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11 + CONTROL "Obtain Kerberos v4 credentials",IDC_NCK4_OBTAIN,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,7,26,128,10 + GROUPBOX "Obtain Kerberos v4 credentials using",IDC_STATIC,7,43,286,72,WS_GROUP + CONTROL "Automatically determine method",IDC_NCK4_AUTO,"Button",BS_AUTORADIOBUTTON,22,59,119,10 + CONTROL "Kerberos v5 to v4 translation",IDC_NCK4_K524,"Button",BS_AUTORADIOBUTTON,22,76,109,10 + CONTROL "Password",IDC_NCK4_PWD,"Button",BS_AUTORADIOBUTTON,22,93,47,10 +END + +IDD_CFG_KRB4 DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Credential cache location",IDC_CFG_LBL_CACHE,7,10,67,8 + EDITTEXT IDC_CFG_CACHE,83,7,165,14,ES_AUTOHSCROLL + LTEXT "Config file path",IDC_CFG_LBL_CFGFILE,7,30,50,8 + EDITTEXT IDC_CFG_CFGPATH,83,27,165,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Browse...",IDC_CFG_CFGBROW,200,95,48,14,NOT WS_VISIBLE + LTEXT "Realm file path",IDC_CFG_LBL_RLMPATH,7,50,48,8 + EDITTEXT IDC_CFG_RLMPATH,83,47,165,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Browse...",IDC_CFG_RLMBROW,200,127,48,14,NOT WS_VISIBLE +END + +IDD_CFG_IDS_KRB4 DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Obtain Kerberos v4 credentials",IDC_CFG_GETTIX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,221,17 + LTEXT "Note that, if enabled, Kerberos v4 credentials will be acquired during initial credential acquisition and during credential renewals.\n\nHowever, currently Kerberos v4 credentials can only be obtained for the default identity.",IDC_STATIC,7,91,221,53,SS_SUNKEN +END + +IDD_CFG_ID_KRB4 DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Obtain Kerberos v4 credentials for this identity",IDC_CFG_GETTIX, + "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,7,165,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_NC_KRB4, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 293 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_CFG_KRB4, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 83 + VERTGUIDE, 196 + VERTGUIDE, 200 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_IDS_KRB4, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_CFG_ID_KRB4, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_PLUGIN ICON "..\\..\\images\\plugin.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_PLUGIN_DESC "Kerberos v4 Credentials Provider" + IDS_NC_K4_SHORT "Kerberos v4" + IDS_ERR_REALM "Could not resolve Kerberos v4 realm" + IDS_ERR_PRINCIPAL "Invalid principal" + IDS_ERR_INVINST "Invalid instance" + IDS_ERR_PWINTKT "Could not obtain Kerberos v4 credentials" + IDS_CT_DISABLED "<p><a id=""SwitchPanel"" param=""Krb4Cred""><b>Krb4</b></a><tab>: Disabled (click <a id=""Krb4Cred:Enable"">here</a> to enable)</p>" + IDS_CT_TGTFOR "<p><a id=""SwitchPanel"" param=""Krb4Cred""><b>Krb4</b></a><tab>: Credentials for realm %s</p>" + IDS_METHOD_AUTO "Automatically determined method" +END + +STRINGTABLE +BEGIN + IDS_KRB4_SHORT_DESC "Kerberos v4" + IDS_KRB4_LONG_DESC "Kerberos v4" + IDS_CFG_KRB4_LONG "Kerberos v4 Configuration" + IDS_CFG_KRB4_SHORT "Kerberos v4" +END + +STRINGTABLE +BEGIN + IDS_METHOD_PWD "Password" + IDS_METHOD_K524 "Kerberos v5 to v4 translation" + IDS_CFG_IDS_KRB4_SHORT "Kerberos v4" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + + diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc b/krb5-1-6/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc new file mode 100644 index 000000000..74fe50905 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc @@ -0,0 +1,57 @@ +; // ** krb5_msgs.mc + +; /* Since .mc files can contain strings from any language, we define +; all our messages in one file in the /lang/ directory instead of +; language specific subdirectories. */ + +; /* The type is set to (wchar_t *) because that's what we will be +; feeding kherr_report() function. */ + +; // MessageIdTypedef=LPWSTR + +; /* Severity values as defined in the message definition file are +; currently ignored. */ + +SeverityNames=( + Success=0x0 +) + +LanguageNames=( + English=0x409:MSG_ENU +) + +OutputBase=16 + +; /* Actual messages start here */ + +MessageId=1 +Severity=Success +SymbolicName=MSG_INITIAL +Language=English +Initial placeholder message +. + +MessageId= +SymbolicName=MSG_K4_NEW_CREDS +Language=English +Getting new Krb4 credentials for [%1!s!] using method [%2!d!] +. + +MessageId= +SymbolicName=MSG_K4_RENEW_CREDS +Language=English +Renewing Krb4 credentials for [%1!s!] using method [%2!d!] +. + +MessageId= +SymbolicName=MSG_K4_TRY_K524 +Language=English +Trying Krb524 ... +. + +MessageId= +SymbolicName=MSG_K4_TRY_PASSWORD +Language=English +Trying Password ... +. + diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/langres.h b/krb5-1-6/src/windows/identity/plugins/krb4/langres.h new file mode 100644 index 000000000..5c0e46f9a --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/langres.h @@ -0,0 +1,49 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc +// +#define IDD_NC_KRB4 103 +#define IDS_PLUGIN_DESC 103 +#define IDD_CFG_KRB4 104 +#define IDS_NC_K4_SHORT 104 +#define IDS_ERR_REALM 105 +#define IDD_CFG_IDS_KRB4 105 +#define IDS_ERR_PRINCIPAL 106 +#define IDD_CFG_ID_KRB4 106 +#define IDS_ERR_INVINST 107 +#define IDI_PLUGIN 107 +#define IDS_ERR_PWINTKT 108 +#define IDS_CT_DISABLED 109 +#define IDS_CT_TGTFOR 110 +#define IDS_METHOD_AUTO 111 +#define IDS_METHOD_PWD 112 +#define IDS_METHOD_K524 113 +#define IDS_CFG_IDS_KRB4_SHORT 114 +#define IDS_KRB4_SHORT_DESC 128 +#define IDS_KRB4_LONG_DESC 129 +#define IDS_CFG_KRB4_LONG 135 +#define IDS_CFG_KRB4_SHORT 136 +#define IDC_CFG_LBL_CACHE 1025 +#define IDC_CFG_LBL_CFGFILE 1026 +#define IDC_CFG_LBL_RLMPATH 1027 +#define IDC_CFG_CACHE 1028 +#define IDC_CFG_CFGPATH 1029 +#define IDC_CFG_RLMPATH 1030 +#define IDC_CFG_CFGBROW 1031 +#define IDC_CFG_RLMBROW 1032 +#define IDC_NCK4_OBTAIN 1033 +#define IDC_NCK4_AUTO 1034 +#define IDC_NCK4_K524 1035 +#define IDC_NCK4_PWD 1036 +#define IDC_CFG_GETTIX 1037 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1043 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb4/version.rc b/krb5-1-6/src/windows/identity/plugins/krb4/version.rc new file mode 100644 index 000000000..d0e074f86 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb4/version.rc @@ -0,0 +1,89 @@ +/* Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* $Id$ */ + +#include<netidmgr_intver.h> + +#ifndef LANGVER + +#define STR_FILEDESC "Kerberos v4 Plugin for Network Identity Manager" +#define STR_INTNAME "krb4cred" +#define STR_ORIGNAME "krb4cred.dll" + +#else + +#ifdef LANG_en_us + +#define STR_FILEDESC "English(US) language resources for the Keberos 4 plugin" +#define STR_INTNAME "krb4cred_en_us" +#define STR_ORIGNAME "krb4cred_en_us.dll" + +#else + +#error Unknown langugae + +#endif + +#endif + +1 VERSIONINFO + FILEVERSION KH_VERSION_LIST + PRODUCTVERSION KH_VERSION_LIST + FILEFLAGSMASK KH_VER_FILEFLAGMASK + FILEFLAGS KH_VER_FILEFLAGS + FILEOS KH_VER_FILEOS + FILETYPE KH_VER_FILETYPEDLL + FILESUBTYPE 0 + { + + BLOCK "StringFileInfo" + { + BLOCK "040904b0" + { + VALUE "CompanyName", KH_VERSTR_COMPANY_1033 + VALUE "FileDescription", STR_FILEDESC + VALUE "FileVersion", KH_VERSTR_VERSION_1033 + VALUE "InternalName", STR_INTNAME + VALUE "LegalCopyright", KH_VERSTR_COPYRIGHT_1033 + VALUE "OriginalFilename", STR_ORIGNAME + VALUE "ProductName", "Network Identity Manager" + VALUE "ProductVersion", KH_VERSTR_PRODUCT_1033 +#ifdef KH_VERSTR_COMMENT_1033 + VALUE "Comment", KH_VERSTR_COMMENT_1033 +#endif +#ifndef LANGVER + VALUE NIMV_MODULE, "MITKrb4" + VALUE NIMV_PLUGINS, "Krb4Cred" + VALUE NIMV_APIVER, KH_VERSION_STRINGAPI + VALUE NIMV_SUPPORT, "http://web.mit.edu/kerberos" +#endif + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1200 + } + } diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/Makefile b/krb5-1-6/src/windows/identity/plugins/krb5/Makefile new file mode 100644 index 000000000..f93fe6819 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/Makefile @@ -0,0 +1,114 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=plugins\krb5 +!include <../../config/Makefile.w32> + +DLLFILE=$(BINDIR)\krb5cred.dll + +LIBFILE=$(LIBDIR)\krb5cred.lib + +OBJFILES= \ + $(LIBDIR)\dynimport.obj \ + $(LIBDIR)\krb5common.obj \ + $(OBJ)\krb5main.obj \ + $(OBJ)\datarep.obj \ + $(OBJ)\errorfuncs.obj \ + $(OBJ)\krb5plugin.obj \ + $(OBJ)\krb5props.obj \ + $(OBJ)\krb5newcreds.obj \ + $(OBJ)\krb5funcs.obj \ + $(OBJ)\krb5config.obj \ + $(OBJ)\krb5identpro.obj \ + $(OBJ)\krb5configdlg.obj \ + $(OBJ)\krb5configcc.obj \ + $(OBJ)\krb5configid.obj \ + $(OBJ)\krb5configids.obj + + + +SDKLIBFILES= \ + netapi32.lib \ + shlwapi.lib \ + comctl32.lib + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +SCLIB=bufferoverflowu.lib +LIBFILES= \ + $(LIBDIR)\nidmgr64.lib \ + $(KFWLIBDIR)\loadfuncs.lib +!else +SCLIB= +LIBFILES= \ + $(LIBDIR)\nidmgr32.lib \ + $(KFWLIBDIR)\loadfuncs.lib +!endif + +MSGRESFILE=$(OBJ)\krb5_msgs.res + +VERRESFILE=$(OBJ)\version.res + +$(OBJ)\krb5config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg + $(CCSV) $** $@ + +$(DLLFILE): $(OBJFILES) $(VERRESFILE) + $(DLLGUILINK) $(MSGRESFILE) $(LIBFILES) $(SDKLIBFILES) $(SCLIB) + $(_VC_MANIFEST_EMBED_DLL) + $(_VC_MANIFEST_CLEAN) + +$(MSGRESFILE): $(OBJ)\krb5_msgs.rc + +$(OBJ)\krb5_msgs.rc: lang\krb5_msgs.mc + $(MC2RC) + +all: mkdirs $(MSGRESFILE) $(DLLFILE) lang + +lang:: + +# Repeat this block as necessary redefining LANG for additional +# languages. + +# Begin language block +LANG=en_us + +LANGDLL=$(BINDIR)\krb5cred_$(LANG).dll + +lang:: $(LANGDLL) + +$(LANGDLL): $(OBJ)\langres_$(LANG).res $(OBJ)\langres_ver_$(LANG).res + $(DLLRESLINK) + +$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc + $(RC2RES) + +$(OBJ)\langres_ver_$(LANG).res: version.rc + $(RC) $(RFLAGS) $(rincflags) /d LANGVER /d LANG_$(LANG) /fo $@ $** +# End language block + +clean:: +!if defined(INCFILES) + $(RM) $(INCFILES) +!endif + diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/datarep.c b/krb5-1-6/src/windows/identity/plugins/krb5/datarep.c new file mode 100644 index 000000000..5c292e478 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/datarep.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Data representation and related functions */ + +#include<winsock2.h> +#include<krbcred.h> +#include<krb5.h> +#include<kherror.h> +#include<strsafe.h> +#include<assert.h> + +khm_int32 KHMAPI +enctype_toString(const void * data, khm_size cbdata, + wchar_t *destbuf, khm_size *pcbdestbuf, + khm_int32 flags) +{ + int resid = 0; + int etype; + wchar_t buf[256]; + size_t cblength; + + if(cbdata != sizeof(khm_int32)) + return KHM_ERROR_INVALID_PARAM; + + etype = *((khm_int32 *) data); + + switch(etype) { + case ENCTYPE_NULL: + resid = IDS_ETYPE_NULL; + break; + + case ENCTYPE_DES_CBC_CRC: + resid = IDS_ETYPE_DES_CBC_CRC; + break; + + case ENCTYPE_DES_CBC_MD4: + resid = IDS_ETYPE_DES_CBC_MD4; + break; + + case ENCTYPE_DES_CBC_MD5: + resid = IDS_ETYPE_DES_CBC_MD5; + break; + + case ENCTYPE_DES_CBC_RAW: + resid = IDS_ETYPE_DES_CBC_RAW; + break; + + case ENCTYPE_DES3_CBC_SHA: + resid = IDS_ETYPE_DES3_CBC_SHA; + break; + + case ENCTYPE_DES3_CBC_RAW: + resid = IDS_ETYPE_DES3_CBC_RAW; + break; + + case ENCTYPE_DES_HMAC_SHA1: + resid = IDS_ETYPE_DES_HMAC_SHA1; + break; + + case ENCTYPE_DES3_CBC_SHA1: + resid = IDS_ETYPE_DES3_CBC_SHA1; + break; + + case ENCTYPE_AES128_CTS_HMAC_SHA1_96: + resid = IDS_ETYPE_AES128_CTS_HMAC_SHA1_96; + break; + + case ENCTYPE_AES256_CTS_HMAC_SHA1_96: + resid = IDS_ETYPE_AES256_CTS_HMAC_SHA1_96; + break; + + case ENCTYPE_ARCFOUR_HMAC: + resid = IDS_ETYPE_ARCFOUR_HMAC; + break; + + case ENCTYPE_ARCFOUR_HMAC_EXP: + resid = IDS_ETYPE_ARCFOUR_HMAC_EXP; + break; + + case ENCTYPE_UNKNOWN: + resid = IDS_ETYPE_UNKNOWN; + break; + +#if 0 + case ENCTYPE_LOCAL_DES3_HMAC_SHA1: + resid = IDS_ETYPE_LOCAL_DES3_HMAC_SHA1; + break; + + case ENCTYPE_LOCAL_RC4_MD4: + resid = IDS_ETYPE_LOCAL_RC4_MD4; + break; +#endif + } + + if(resid != 0) { + LoadString(hResModule, (UINT) resid, buf, ARRAYLENGTH(buf)); + } else { + StringCbPrintf(buf, sizeof(buf), L"#%d", etype); + } + + StringCbLength(buf, ARRAYLENGTH(buf), &cblength); + cblength += sizeof(wchar_t); + + if(!destbuf || *pcbdestbuf < cblength) { + *pcbdestbuf = cblength; + return KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(destbuf, *pcbdestbuf, buf); + *pcbdestbuf = cblength; + return KHM_ERROR_SUCCESS; + } +} + +khm_int32 KHMAPI +addr_list_comp(const void *d1, khm_size cb_d1, + const void *d2, khm_size cb_d2) +{ + if (cb_d1 < cb_d2) + return -1; + if (cb_d1 > cb_d2) + return 1; + return memcmp(d1, d2, cb_d1); +} + +khm_int32 KHMAPI +addr_list_toString(const void *d, khm_size cb_d, + wchar_t *buf, khm_size *pcb_buf, + khm_int32 flags) +{ + wchar_t tbuf[2048]; + wchar_t * strpos; + khm_size cbleft; + size_t t; + k5_serial_address * addrs; + + if (cb_d == 0 || d == NULL) { + tbuf[0] = L'\0'; + } else { + addrs = (k5_serial_address *) d; + + strpos = tbuf; + cbleft = sizeof(tbuf); + tbuf[0] = L'\0'; + + while (TRUE) { + if (cb_d < sizeof(*addrs) || + addrs->magic != K5_SERIAL_ADDRESS_MAGIC || + cb_d < sizeof(*addrs) + addrs->length - sizeof(khm_int32)) + break; + + if (strpos != tbuf) { + if (FAILED(StringCbCatEx(strpos, cbleft, L" ", + &strpos, &cbleft, + 0))) + break; + } + +#ifdef DEBUG + assert(*strpos == L'\0'); +#endif + + one_addr(addrs, strpos, cbleft); + + t = 0; + if (FAILED(StringCchLength(strpos, + cbleft / sizeof(wchar_t), + &t))) + break; + + strpos += t; + cbleft -= t * sizeof(wchar_t); + + t = sizeof(*addrs) + addrs->length - sizeof(khm_int32); + addrs = (k5_serial_address *) BYTEOFFSET(addrs, t); + cb_d -= t; + } + } + + StringCbLength(tbuf, sizeof(tbuf), &t); + + if (!buf || *pcb_buf < t) { + *pcb_buf = t; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buf, *pcb_buf, tbuf); + *pcb_buf = t; + + return KHM_ERROR_SUCCESS; +} + +khm_int32 KHMAPI +krb5flags_toString(const void *d, + khm_size cb_d, + wchar_t *buf, + khm_size *pcb_buf, + khm_int32 f) +{ + wchar_t sbuf[32]; + int i = 0; + khm_size cb; + khm_int32 flags; + + flags = *((khm_int32 *) d); + + if (flags & TKT_FLG_FORWARDABLE) + sbuf[i++] = L'F'; + + if (flags & TKT_FLG_FORWARDED) + sbuf[i++] = L'f'; + + if (flags & TKT_FLG_PROXIABLE) + sbuf[i++] = L'P'; + + if (flags & TKT_FLG_PROXY) + sbuf[i++] = L'p'; + + if (flags & TKT_FLG_MAY_POSTDATE) + sbuf[i++] = L'D'; + + if (flags & TKT_FLG_POSTDATED) + sbuf[i++] = L'd'; + + if (flags & TKT_FLG_INVALID) + sbuf[i++] = L'i'; + + if (flags & TKT_FLG_RENEWABLE) + sbuf[i++] = L'R'; + + if (flags & TKT_FLG_INITIAL) + sbuf[i++] = L'I'; + + if (flags & TKT_FLG_HW_AUTH) + sbuf[i++] = L'H'; + + if (flags & TKT_FLG_PRE_AUTH) + sbuf[i++] = L'A'; + + sbuf[i++] = L'\0'; + + cb = i * sizeof(wchar_t); + + if (!buf || *pcb_buf < cb) { + *pcb_buf = cb; + return KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(buf, *pcb_buf, sbuf); + *pcb_buf = cb; + return KHM_ERROR_SUCCESS; + } +} + +khm_int32 KHMAPI +kvno_toString(const void * data, khm_size cbdata, + wchar_t *destbuf, khm_size *pcbdestbuf, + khm_int32 flags) +{ + int resid = 0; + int kvno; + wchar_t buf[256]; + size_t cblength; + + if (cbdata != sizeof(khm_int32)) + return KHM_ERROR_INVALID_PARAM; + + kvno = *((khm_int32 *) data); + + StringCbPrintf(buf, sizeof(buf), L"#%d", kvno); + + StringCbLength(buf, ARRAYLENGTH(buf), &cblength); + cblength += sizeof(wchar_t); + + if (!destbuf || *pcbdestbuf < cblength) { + *pcbdestbuf = cblength; + return KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(destbuf, *pcbdestbuf, buf); + *pcbdestbuf = cblength; + return KHM_ERROR_SUCCESS; + } +} + +khm_int32 +serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf) +{ + k5_serial_address * addr; + khm_size cb_req; + khm_size t; + khm_boolean overflow = FALSE; + + addr = (k5_serial_address *) buf; + cb_req = 0; + + for(; *a; a++) { + t = sizeof(k5_serial_address) + (*a)->length - sizeof(khm_int32); + cb_req += t; + if (cb_req < *pcbbuf) { + addr->magic = K5_SERIAL_ADDRESS_MAGIC; + addr->addrtype = (*a)->addrtype; + addr->length = (*a)->length; + memcpy(&addr->data, (*a)->contents, (*a)->length); + + addr = (k5_serial_address *) BYTEOFFSET(addr, t); + } else { + overflow = TRUE; + } + } + + *pcbbuf = cb_req; + + return (overflow)?KHM_ERROR_TOO_LONG: KHM_ERROR_SUCCESS; +} + +void +one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf) +{ + wchar_t retstr[256]; + struct hostent *h = NULL; + int no_resolve = 1; + + retstr[0] = L'\0'; + + if ((a->addrtype == ADDRTYPE_INET && a->length == 4) +#ifdef AF_INET6 + || (a->addrtype == ADDRTYPE_INET6 && a->length == 16) +#endif + ) + { + int af = AF_INET; +#ifdef AF_INET6 + if (a->addrtype == ADDRTYPE_INET6) + af = AF_INET6; +#endif + if (!no_resolve) { +#ifdef HAVE_GETIPNODEBYADDR + int err; + h = getipnodebyaddr(&a->data, a->length, af, &err); + if (h) { + StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name); + freehostent(h); + } + else + h = gethostbyaddr(&a->data, a->length, af); + if (h) { + StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name); + } +#endif + if (h) + goto _copy_string; + } + if (no_resolve || !h) { +#ifdef HAVE_INET_NTOP + char buf[46]; + const char *name = inet_ntop(a->addrtype, &a->data, buf, sizeof(buf)); + if (name) { + StringCbPrintf(retstr, sizeof(retstr), L"%S", name); + goto _copy_string; + } +#else + if (a->addrtype == ADDRTYPE_INET) { + khm_ui_4 addr = a->data; + StringCbPrintf(retstr, sizeof(retstr), + L"%d.%d.%d.%d", + (int) (addr & 0xff), + (int) ((addr >> 8) & 0xff), + (int) ((addr >> 16)& 0xff), + (int) ((addr >> 24)& 0xff)); + goto _copy_string; + } +#endif + } + } + + { + wchar_t tmpfmt[128]; + LoadString(hResModule, IDS_UNK_ADDR_FMT, tmpfmt, sizeof(tmpfmt)/sizeof(wchar_t)); + StringCbPrintf(retstr, sizeof(retstr), tmpfmt, a->addrtype); + } + + _copy_string: + StringCbCopy(buf, cbbuf, retstr); +} + diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/datarep.h b/krb5-1-6/src/windows/identity/plugins/krb5/datarep.h new file mode 100644 index 000000000..d81e7b91e --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/datarep.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KRB_DATAREP_H +#define __KHIMAIRA_KRB_DATAREP_H + +typedef struct tag_k5_serial_address { + khm_int32 magic; /* should be K5_SERIAL_ADDRESS_MAGIC */ + khm_int32 addrtype; /* Address type. We only know what to + do with ADDRTYPE_INET and + ADDRTYPE_INET6 */ + khm_size length; /* number of bytes of data in [data]. + This should always be greater than + sizeof(khm_int32) */ + khm_int32 data; /* actually, &data is the beginning of + the data buffer that is [length] + bytes long. */ +} k5_serial_address; + +#define K5_SERIAL_ADDRESS_MAGIC 0x44ce832d + +khm_int32 KHMAPI +enctype_toString(const void * data, khm_size cbdata, + wchar_t *destbuf, khm_size *pcbdestbuf, + khm_int32 flags); + +khm_int32 KHMAPI +addr_list_comp(const void *d1, khm_size cb_d1, + const void *d2, khm_size cb_d2); + +khm_int32 KHMAPI +addr_list_toString(const void *, khm_size, wchar_t *, + khm_size *, khm_int32); + +khm_int32 KHMAPI +krb5flags_toString(const void *, khm_size, wchar_t *, + khm_size *, khm_int32); + +khm_int32 KHMAPI +kvno_toString(const void * data, khm_size cbdata, + wchar_t *destbuf, khm_size *pcbdestbuf, + khm_int32 flags); + +khm_int32 KHMAPI +renew_for_cb(khm_handle cred, khm_int32 id, void * buffer, + khm_size * pcbsize); + +khm_int32 +serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf); + +void +one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf); +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.c b/krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.c new file mode 100644 index 000000000..4c2d78c63 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> + +extern void (__cdecl *pinitialize_krb_error_func)(); +extern void (__cdecl *pinitialize_kadm_error_table)(); + + +khm_int32 init_error_funcs() +{ + return KHM_ERROR_SUCCESS; +} + +khm_int32 exit_error_funcs() +{ + return KHM_ERROR_SUCCESS; +} + +#ifdef DEPRECATED_REMOVABLE +HWND GetRootParent (HWND Child) +{ + HWND Last; + while (Child) + { + Last = Child; + Child = GetParent (Child); + } + return Last; +} +#endif + +void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf, + DWORD * suggestion, + kherr_suggestion * suggest_code) +{ + const char * com_err_msg; + int offset; + long table_num; + DWORD msg_id = 0; + DWORD sugg_id = 0; + kherr_suggestion sugg_code = KHERR_SUGGEST_NONE; + + if (suggestion == NULL || buf == NULL || cbbuf == 0 || suggest_code == 0) + return; + + *buf = L'\0'; + + offset = (int) (code & 255); + table_num = code - offset; + com_err_msg = perror_message(code); + + *suggestion = 0; + *suggest_code = KHERR_SUGGEST_NONE; + + if (WSABASEERR <= code && code < (WSABASEERR + 1064)) { + /* winsock error */ + table_num = WSABASEERR; + offset = code - WSABASEERR; + } + + switch(table_num) + { + case krb_err_base: + case kadm_err_base: + case WSABASEERR: + break; + default: + + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + *suggestion = MSG_ERR_S_INTEGRITY; + } + *suggest_code = KHERR_SUGGEST_RETRY; + AnsiStrToUnicode(buf, cbbuf, com_err_msg); + return; + } + + if (table_num == krb_err_base) { + switch(offset) { + case KDC_NAME_EXP: /* 001 Principal expired */ + case KDC_SERVICE_EXP: /* 002 Service expired */ + case KDC_AUTH_EXP: /* 003 Auth expired */ + case KDC_PKT_VER: /* 004 Protocol version unknown */ + case KDC_P_MKEY_VER: /* 005 Wrong master key version */ + case KDC_S_MKEY_VER: /* 006 Wrong master key version */ + case KDC_BYTE_ORDER: /* 007 Byte order unknown */ + case KDC_PR_N_UNIQUE: /* 009 Principal not unique */ + case KDC_NULL_KEY: /* 010 Principal has null key */ + case KDC_GEN_ERR: /* 011 Generic error from KDC */ + case INTK_W_NOTALL : /* 061 Not ALL tickets returned */ + case INTK_PROT : /* 063 Protocol Error */ + case INTK_ERR : /* 070 Other error */ + msg_id = MSG_ERR_UNKNOWN; + sugg_code = KHERR_SUGGEST_RETRY; + break; + + case KDC_PR_UNKNOWN: /* 008 Principal unknown */ + msg_id = MSG_ERR_PR_UNKNOWN; + sugg_code = KHERR_SUGGEST_RETRY; + break; + case GC_TKFIL : /* 021 Can't read ticket file */ + case GC_NOTKT : /* 022 Can't find ticket or TGT */ + msg_id = MSG_ERR_TKFIL; + sugg_id = MSG_ERR_S_TKFIL; + sugg_code = KHERR_SUGGEST_RETRY; + break; + case MK_AP_TGTEXP : /* 026 TGT Expired */ + /* no extra error msg */ + break; + + case RD_AP_TIME : /* 037 delta_t too big */ + msg_id = MSG_ERR_CLOCKSKEW; + sugg_id = MSG_ERR_S_CLOCKSKEW; + sugg_code = KHERR_SUGGEST_RETRY; + break; + + case RD_AP_UNDEC : /* 031 Can't decode + authenticator */ + case RD_AP_EXP : /* 032 Ticket expired */ + case RD_AP_NYV : /* 033 Ticket not yet valid */ + case RD_AP_REPEAT : /* 034 Repeated request */ + case RD_AP_NOT_US : /* 035 The ticket isn't for us */ + case RD_AP_INCON : /* 036 Request is inconsistent */ + case RD_AP_BADD : /* 038 Incorrect net address */ + case RD_AP_VERSION : /* 039 protocol version mismatch */ + case RD_AP_MSG_TYPE : /* 040 invalid msg type */ + case RD_AP_MODIFIED : /* 041 message stream modified */ + case RD_AP_ORDER : /* 042 message out of order */ + case RD_AP_UNAUTHOR : /* 043 unauthorized request */ + /* no extra error msg */ + sugg_code = KHERR_SUGGEST_RETRY; + break; + + case GT_PW_NULL: /* 51 Current PW is null */ + case GT_PW_BADPW: /* 52 Incorrect current password */ + case GT_PW_PROT: /* 53 Protocol Error */ + case GT_PW_KDCERR: /* 54 Error returned by KDC */ + case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */ + /* no error msg yet */ + sugg_code = KHERR_SUGGEST_RETRY; + break; + + /* Values returned by send_to_kdc */ + case SKDC_RETRY : /* 56 Retry count exceeded */ + case SKDC_CANT : /* 57 Can't send request */ + msg_id = MSG_ERR_KDC_CONTACT; + break; + /* no error message on purpose: */ + case INTK_BADPW : /* 062 Incorrect password */ + sugg_code = KHERR_SUGGEST_RETRY; + break; + default: + /* no extra error msg */ + break; + } + } else if (table_num == kadm_err_base) { + switch(code) { + case KADM_INSECURE_PW: + /* if( kadm_info != NULL ){ + * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info); + * } else { + * wsprintf(buf, "%s\nPlease see the help file for information " + * "about secure passwords.", com_err_msg); + * } + * com_err_msg = buf; + */ + + /* The above code would be preferred since it allows site + * specific information to be delivered from the Kerberos + * server. However the message box is too small for VGA + * screens. It does work well if we only have to support + * 1024x768 + */ + + msg_id = MSG_ERR_INSECURE_PW; + sugg_code = KHERR_SUGGEST_RETRY; + break; + + default: + /* no extra error msg */ + break; + } + } else if (table_num == WSABASEERR) { + switch(code) { + case WSAENETDOWN: + msg_id = MSG_ERR_NETDOWN; + sugg_id = MSG_ERR_S_NETRETRY; + sugg_code = KHERR_SUGGEST_RETRY; + break; + + case WSATRY_AGAIN: + msg_id = MSG_ERR_TEMPDOWN; + sugg_id = MSG_ERR_S_TEMPDOWN; + sugg_code = KHERR_SUGGEST_RETRY; + break; + + case WSAENETUNREACH: + case WSAENETRESET: + case WSAECONNABORTED: + case WSAECONNRESET: + case WSAETIMEDOUT: + case WSAECONNREFUSED: + case WSAEHOSTDOWN: + case WSAEHOSTUNREACH: + msg_id = MSG_ERR_NOHOST; + sugg_id = MSG_ERR_S_NOHOST; + sugg_code = KHERR_SUGGEST_RETRY; + break; + } + } + + if (msg_id != 0) { + FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_IGNORE_INSERTS, + KHERR_HMODULE, + msg_id, + 0, + buf, + (int) (cbbuf / sizeof(buf[0])), + NULL); + } + + if (sugg_id != 0) { + *suggestion = sugg_id; + } + + if (sugg_code != KHERR_SUGGEST_NONE) + *suggest_code = sugg_code; +} + +#ifdef DEPRECATED_REMOVABLE +int lsh_com_err_proc (LPSTR whoami, long code, + LPSTR fmt, va_list args) +{ + int retval; + HWND hOldFocus; + char buf[1024], *cp; + WORD mbformat = MB_OK | MB_ICONEXCLAMATION; + + cp = buf; + memset(buf, '\0', sizeof(buf)); + cp[0] = '\0'; + + if (code) + { + err_describe(buf, code); + while (*cp) + cp++; + } + + if (fmt) + { + if (fmt[0] == '%' && fmt[1] == 'b') + { + fmt += 2; + mbformat = va_arg(args, WORD); + /* if the first arg is a %b, we use it for the message + box MB_??? flags. */ + } + if (code) + { + *cp++ = '\n'; + *cp++ = '\n'; + } + wvsprintfA((LPSTR)cp, fmt, args); + } + hOldFocus = GetFocus(); + retval = MessageBoxA(/*GetRootParent(hOldFocus)*/NULL, buf, whoami, + mbformat | MB_ICONHAND | MB_TASKMODAL); + SetFocus(hOldFocus); + return retval; +} +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.h b/krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.h new file mode 100644 index 000000000..4b1d2e2b5 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/errorfuncs.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_ERR_H +#define __KHIMAIRA_ERR_H + +/* All error handling and reporting related functions for the krb4/5 + and AFS plugins */ + +#include <errno.h> +#include <com_err.h> +/* + * This is a hack needed because the real com_err.h does + * not define err_func. We need it in the case where + * we pull in the real com_err instead of the krb4 + * impostor. + */ +#ifndef _DCNS_MIT_COM_ERR_H +typedef LPSTR (*err_func)(int, long); +#endif + +#include <krberr.h> +#include <kadm_err.h> + +#define kadm_err_base ERROR_TABLE_BASE_kadm + +#include <stdarg.h> + +#ifndef KRBERR +#define KRBERR(code) (code + krb_err_base) +#endif + +/*! \internal + \brief Describe an error + + \param[in] code Error code returned by Kerberos + \param[out] buf Receives the error string + \param[in] cbbuf Size of buffer pointed to by \a buf + \param[out] suggestion Message ID of suggestion + \param[out] suggest_code Suggestion ID +*/ +void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf, + DWORD * suggestion, + kherr_suggestion * suggest_code); + +/* */ +khm_int32 init_error_funcs(); + +khm_int32 exit_error_funcs(); + + +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/images/deleted.ico b/krb5-1-6/src/windows/identity/plugins/krb5/images/deleted.ico new file mode 100644 index 0000000000000000000000000000000000000000..a8063f9ee72d8b209717fad18acb3384f8309e44 GIT binary patch literal 1406 zcma)+El*rg5Qbk;nyf&8S%qj(MUN>KPl7??CjAE(#42=?CYv0GXq!~j@C#N|l+j>{ zLXeOq1w+_0Vfvi8y9uI#yL&$7z30sP+&OnwTH&+4uDU+Fmd4E9(Yo}8wxSVzO@?tf zUs;9|iLWM;VW4NK*=(lSubJ+Ce%0#gsz#%c*4Eavv9Y1?c&yFMO>J#$X?uHH2L}h* z+uPIb?yh!rb~HIo?eC{P=|cHC^yA`>E^co0@!NNdjOMgPiy<^LLo+n%S`JGb-O(N0 z(H*^SYv>KV5j6CM&Y(aK^gs`UKu_W%&M0T2H~fu6#wJs$?CA^!gTY`h7zzmngTY`h z7z~EOgu!4i7z_r3q0nJ47z_r3!C<gNgTvsk&XHLaKw<2kMhhBxe`Hu3bH~U@>abK9 zxamwB7Kf$E0*Axla5x+eN0kZ=hrwZR7<%a(4u`>E2)vTMN{G+!A+GZF>Oh5eV^x(J z?*>!Dv|-R-YIrwpHj*^F8{Tys<&BPi!@uF*kEr3_s7-^R!O*BfKQ^jTPmjV#-;a?R z1bzWqz!CV>(RL1M5O752;KAy+*%Yt@ECEDdSg!yq!Ny=wAOtLYY2@Kd0+#6YD3<;< z^ix2CAz?@u5{85!VW`&$hJYbqNEiYJ($H8BL&A_SBn+gcp~H|cBn$~a;vXbSHYSUl z98T<TWaaK_TyOP7hlhtcIy%zH$%&@Zsm{;Ob#`{9%gak$U0vz=`dYWQx4OT-*W=@( z?*67epPuqNo>1NX8|VZ1D(ZQA*rU4U^XG#!FJb5xcjgOG4|Q>Gv1y1Omf`>Jb9cF- zukT^?Bp>45<FJT(L|oS}e|bFYdSU-`EIqyFzmEUH*{f%*$K<H?TwlzG`bqx)6AcKu literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/images/krb5plugin.ico b/krb5-1-6/src/windows/identity/plugins/krb5/images/krb5plugin.ico new file mode 100644 index 0000000000000000000000000000000000000000..791b359694d86dcdc85bd083d502db8056283771 GIT binary patch literal 7278 zcmeHM4OElo6@IJrXP;T^I>fqlky=YD1&dl;)lIFx)NbhFA7ZN&t7q-34lUx?6siI- zQfRTDg5snaD{9oJu|^3PA!!jK1`Ue*gAw_Y0769c?%p@~5SeR_XFI2!vwr8ie7WC! z-}~JA+@CK|#-3tbnVZ|Qcz>Ezc42G;V<<C}d$O;4GA8XR%5LoIXBji}V(eAggKHcv zI@kHaZS7YWeZoIs&JSTuAq*d+r>8R@J^lgb2XG4DctG0!-PI#l&S8RA$JCS6V29kJ zgB&A|VJOS(a)<tbT+if@tL>{}03t&H?DBdR9PVSEI0aw>%3w!1$VVPNG1MWW|G`01 zVqk-hDA%Jbk7=1C$`BlmGR%zO=h4J!l;u4h$nx+h;d7Y0U61kxpI|2*?kBwu-swEL zMRMdM{6MnYA<Jj_JuHV$^oyK1Ck7Ch_RHm;O!{OZ`Ygu-7@s`GE{~L>k``Mnr;ALZ z5~=ISWipMIJ%%|SIAlk{9vt}Z6DZp4crO{79-2NjEHu4qSZ`cCFiYaXO2u+~j4K`Y zmf*7EqPpmaL!Te6b8LprmlJJ(bO2LCtYZd)p2aKFEMUGrvs%lTTCHXli<zmFX7-UR zg^d!_EGa30H8(e~b*qw?Y;X$GYBfx;O2<rwd=@ZS$&~SWR#sNV>guXkN=gbdnX*`H zgo+gv<ujeuzzq5<HhZXwB}JRq{rjyfHpIl@V`G^{WnfBWGK&aFW_rDjB}5olRaF(s z&(CLCwV6$os#$AmE7R$8tf8TSnayUFm6gR-EL+Aj8Z}!RpkvD9WHx`47JWdU)hgyc zLc^lhrLfrOXtZTTTNaj_oP>6onao3twzModgzVKZl_~{on$Y(mJf~*yYb`8#Eykz9 zxW;RkD%r%M6$<3Yz!IW0$WZ`tWJP`~Y|L}SOA_*eb_c7F6D?D$FffbRiuS6Ii#p`N z#1aw`kcT3SPtWw4BIJQ^%q%G(o+;KUkrO@hb=P7%8n$+cmW>!O3iA?yIngi;=0byc zSmvu`>z1jQDa*pF$g>JLRz~L|m-mrNGfRk%N4^X!MX5wCm8=dqEJ6--#Nhx9yN?{| zk;7)>(1IMAki(EwA<Uq&uqEU5OqFC|0b_Kyzle=@)v)AP0}BXP!cyWbOs!I3Tv_Ow zj%6VaRTzIh#-EI_w_@zGF?Jos-hlC%G2SGMw+!PoV7&eqs}|$>>3Z@QNPP0I*PrU; z9qJ+x9VM}^i%b*~pLXcQ2VDF&eV1vzn?LXxiHErUol)+u_4aa@;1AyAdUsL3mFr0y z&}GchpS|evo2Zw6?c(m~>9_v5Kf8?d^Yiq>^Q52ZHfEU6bKC+!nEtG<MB=wVnB^gr zN<IACUHXy!O}CZL2)|tYiv^1W;V*q;o~W0}JY=$Qo-({ACc3Tke@6JZ_XLUTuYwRM zlhAn&k3gvm|4KbP5?A{7njyU8s_5(9r@t`B#i^J6u8*Im1os5`_Zp3QMfbVxeda_6 zuZnt^yK_UY(F0}(3%h%dcU>YMCPcRDeck(z3m&5f1ic_k_I_qY7`_n~yeFB&@ujkE zzV3dWo-&UCL9Q<dzwIpu-T&zCi4R1*OSh4HLy)UtzVQ5*K|%lmqDxM_WS)z!J8qD; zD!QZowZ+1qk00ozQb|ABfJYSFz2^&E-~H7f;rE|XNc_AsQ1VK@34B9$@7@!IuI~(f zH9`=4UY;^*gD`B?+tNVKX|MEiK_B~g_Z~As_`~47{bsKdgb}j@x)uipdU{QJWgcx9 z^V-0%LtgCbHP79B_Qp5D`!B%jJr55_j~<Q<iHV;N4SH+1cbD;N(d0ZA7hm+7LUHdm ziY#CXhXyTId^m8f7oNZk-F!!4V7S54vm1)2PfT=uYxuyvab7*}!~_CG1LKGciMvCO zTQ(2uGWdakKHPvrCiCRyf5bnXzc-Nl<9$zYd-4Y4PaZw74D8&VI7D;o=n!LO=JSu^ zWNb{dWao~=At#O>8}gme@K|Txf6sr>isehS^6>RW#5W?o@%*_gV_8|Lv8kzP7q-uT zv==ac-lCPumuWXfY%n6e5%G<t>}+Fsd6}{K_U-RIE5?WTae>R08Xtv!`}S=k;tvt` zcD^s1KQC^@@{f&=!f$DA{@$~qtw-S-GR_uU$+J{c-nd~+J#{Min-eFZ%;t+xH!E+f zx7+QL#j}sX$J`ZMy^>c^b+gi{OFf;eJ^4-4rCf7V)y<nB_?^G~tZ3s=_-FNJtXC`+ zYiE448FlB*oe#yckHXJ9tG6P)wKINoRaF$?x1Zg+=c_bh=GipeX>CQ=QkCta>HBQo z95&d>%gSs!qt4qym!#Uah8ye|>E~`#;KS<bs<H-~t*oiB@oHUdZJKI_B`sj`?usoN zkMlE?l{aj)wY9cex9aTpo5qg!hP1TQ-D3Qm@ju(7fG;<H0lL&vuwb+n-t4J{V|&d| zUw;d}{KrKu)3dS9sX-Bx1~;r$XliQY>sDP|`<_iJjd1twU1)2g)du%)VU7TO1mpn9 zN=tK#3JZ31#{VMbGmgJCJ`SdP?&o;Bx1>YiwS36VxC-%W%rNa`hhOB!$J0(iO-(gm zO@ghy9^#xnZVWU4{#F8eOAFjVT&z22X=&zhG&VN!{iMTHhWu|Ab4Rfgc4ER-_><QG zj=z4@PS6}b2Bjs%c&>@t+8uMXor`~dVc<Boo0?$D+FbrzvBC&g6M(kiF0Om`?r|Pk z$RF`J=ckSHgj^Nl@2lk^_RbyKLFRRk+X`R33l8j0fy0Lmg6VuVR9D@ET8w$~-!E{z zkMt<u?_uEhp^w0K;@IsioGYvWz?#9FVJyfA`9rxPA1Q9aPTsW>W(;=VM~3X?*hkfe z;lhRUPW&1uFR6kFuE)6#r;nO{5T9blena1D;MT2Mfc41Fh@6lQBKDr$$uRSEm4nMQ zN+4{?!Nr^lus>x#41eQISQPL9%pY}<@7Wb={9$~o0URArMf}y)IBJ1>z}g`nT3he% zxCwjTUM0-*KE!QDh3@0nR1Y)Ir`5rK1GoM!@ugPgK-`*(aOSw9HnxOba`=q-Z|#(4 zs>h0o3c&e+99HpOsK=UZuScv?5u5ToYsg`4EBe#@pgnnlf2NvOA2|Z=FIWiMwk7bI zZ)m_=I%~Q!KGmM158HU0*mrRKI{HwFK2)O*b+z0E`9S_r++wZG9(sghe!k%#q@F$n zZ)2Si{*KS|oIk1~n+^R(4rvAuj}PH<>{e)V)*tmwad8pWYAIN+Ux%BOl~7Y%jXsba zs>jB5Y|8hXVQP-IIpPqcr|DqLVn?ohq-wZu?lRP44beFVeiPuktsQ?8@!ui#d-vLS zy%!W*gOcK6z;_{7t>^>JBAOp!Pf(AEwdOa>5pSGa4H;+kpwni+RJUW?r|E-^LT1_} zpqa<>hrLAniSch*`7Q5zk$dVb>bLx>SD>(<07`I{l$V$D`AI!d<Ln6$oAN#P4F~=f z#W64%G9l}`Z$Wz`r@iMW7YoN7hi#DtICbbM(9B!-`_tS%>I?Egm3-bYe-WSj%(GY^ zKmRJ=?8SLjg7t_#bm$4{F~X*N&mHcFbz78%W1r7H$Is>ET!+PPo#8m-1MS-wnAtAV zGjZX+G4Z*AvkmbZ;8Jcb<mFl5T7Ev-DumKf@}UBKxPg6HMYt7dsi$rFGwHVIkW|~6 zMW<~VRfg??Dcfegm}4s{Dzwx4qXui&l2ZZu;w_;3G8fX+g*Xp$`1^<60de@Ah{suc z=2$WBYpMm}|MKNaaOqMmT*=FWYuECjxTuicMR48Om)o~(kt8K<o0`0Hhf4WXvN2_^ z(x^I+VpJbi;dd~#F*8G7PBZ9ot{J(!?9AsiZimN0b%nJ}Jx+P8#`>mNL-j?yPIH%P zt`PaZawQK6uHji{Pf%Zq?;*M?zuI+ZpK?#-!IXWCM^pzJkE@R~X6Vz~a!ls|xq!<& z4&u_0&l1rN<rLq`)Z@e{?=gJu(#*Ay57@6%3)H)m|Ms51cSuKk`n+%Np63swd>wQ6 z;DLgpM-DaW)6?2a*;#P$f(dfX7r}yj;`bVi!@(u5YqaCw)5>F|IYTp_`kcN;Jm^`+ z%%HrGpVX6`@kJTqmmvO%)Ke#m&+5|w69L)hvL51qIOQB*K6zbZe>*s!{=zx)5C=Fn zXl5d|IR9yeig-WW|34X^f0yWZ*`XBD`-hF?>#4A=>9~-Yj_a|BD!~)<e`{^HI%3i1 Fe*s!^o~Hl+ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/images/modified.ico b/krb5-1-6/src/windows/identity/plugins/krb5/images/modified.ico new file mode 100644 index 0000000000000000000000000000000000000000..733d9d5348bd94acdca867d77c36a83c42efcc92 GIT binary patch literal 1406 zcmbu9F>4z^5QU$K0xAr$8dWM1S8+X+TlWGts@)Cw2WnENavd-TwsVmLQl!x@P?aK{ zT5jS>g+T;jcZL*`Z}%cd0wxK$)9&89+nx8_?46`N&VvKB<K<In#MKL0m7dY|)TeJ3 z-MG8n+l6z9pXT#!pyyJn)k>?+E8Ts1r(Un8e!s8%{e2CGLyblwjmKjh9v<rG=t$G) zRFla>CnqO5K0em`RqFIKb)mKLOX%bJtJb%-dj0+bMn-d5p+y%OnxPq*RV}+Ij_&A= z?&ywQmlgDaUI+?$L1$2)2YR3fLZByc5@$4Lqc{AGM8+ahs@c;S3<iV2U@$Z!7z_r3 z!C){L8YT<|gTY`h7z_;^27|$1Fc=I5OEfqP4yzoQtpX^F^(?fYq1Q)-#W8n`oTLs* zD+4#33x~yFX=Q=K;cz${4u_+a3J!<CVQ?5~=^PG+!C?rzlD?G?pY9}X<*n6$3h%<K zR%*NpOa;?|L4m2@UAS3DQt&Q#x9w=&==c}>3;uPB3jT%K6c`E&g*w!2qblv`Q5fm# zHd2GYFJKEe0>8Gkm4g}t98o!Vu(sVS3RnV`03tAKuK+B;!eCM$1T6e$<Y7+&mZ<e; zEcI=uyMP8m!jLc|3<*QR&|W7P0)~VkVF(yVLt{P+2}8n=Fp!#t4nx9_FeCtpe~>I$ zm`rkVII+W#Eq9&cdak!RJ3G^CHq-g}xfY9suCA`MTrPEeeXX0D8*MflZMR$9-{0%u z;X!xbQg1FV`HtsQw|)b4AYY4W-Wt~EPsiY=qs|?$?8h<q%eb@1d~E*z-v5>7H{LG! QV|`Z#{_CFnTidPs4kGa7o&W#< literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/images/new.ico b/krb5-1-6/src/windows/identity/plugins/krb5/images/new.ico new file mode 100644 index 0000000000000000000000000000000000000000..1049eb2148f1596a26c22ad7e4522af43af9c49c GIT binary patch literal 1406 zcmb7^p-&u95XL`Jnw&s@IfZCZMUPorgC`-mpmCG_2bhXe=q61_o<p=vDr)!(PF0lA zV2UCa64C^4BrB%B_x7$0RCVuW_szHO&G*}Rdnc{%SzlK>-o2E@jNTAcdPS^g#JLTI z>vFuZOs5iGO{c?!Gega0GtGX^bpPXvR##Uw8jZBJwx*4Z4UNZRZEkLAYimo}+uJ%g zIMCkSo_2S4wX?IM>HF0Fe(Iwxl)pmXFYa`4bE6MmzhPvA6NQK&H8evrG^<(;QyksV z9o^9#y)G;01-+0I^n%Vsfgb3A9teS+<Vl{<oQ<>LZxk{XnNrQ3lfhsx7z_qOLxRCz zFc=I5gP~!<U@#aA27|%S&|xqb3<iV2V6a4k!{D&Wk=Z(c!nJ-15d?aDWLO+?$H*z_ zu(URC(-}A{4ohnb91e%W;cz${tyOS13=V_CP+RA4I1CO$;FX+P3-K8~<gLB6J5b?W znAKX1cY&#3S}-Uu6}$^K3q=av1@E>U%^My6f`7rkZc)L%(3=87fuYccx@~l&Jv|Cn z&UG8<LEsm#1ss82+uF)O4+4&;96VUtZWaYB0ZRZ87`9gcmSABpDG&k{z65pHlYk{^ zKN?GY8|p5g!H_T{3<*QRkTA5@35I|nVMrJP2Fei3haq7|7!n3b6X-A`3<*O5koX71 zl7-16r-qX|9NB8uIj-0Gti!`Y9UUF%`1n{SCnq{TKiApWnJzCcb#-;6>+5UX-rnlr z;X#j&kGk(upH5Ht9Z%_Q{SDL$^;%Zz*0g5-eXwkC3`>{UvfA^!|06KJpU=q`QeEG7 zUDwZtDK+o9N!Kk_wA+)(r29L6{_Otq^}Xi(Tz##yJf0+oPx7G;{MWtsH-t7_L>({l Kw~X&-U5(!qarT4& literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/images/normal.ico b/krb5-1-6/src/windows/identity/plugins/krb5/images/normal.ico new file mode 100644 index 0000000000000000000000000000000000000000..56a702fee1913ebd6925a6d7fcf7f0e123be3062 GIT binary patch literal 1406 zcmd6np>A725Jj(5S2Bo{m>3zfK@A=h8XhUcIBe8E2q`c!u2d<~vVgWyK}o*AsGuI~ zkOl=riYhf>mI|h4$Bk4Kv?}X+p52}6-M#0{K3f`a@9n9smrtb$qZdS%o)H6$Xlt<T zAIF2obT0AHe7@~y8EUy)YWZcU`_Jz+91b-ajkL3~qw#pG$z-DGbgKRReH|PeXf~Va z`1n{yM@Kq5Jk<PE>f|K#Mr-BQ(5Lk`t#5Dj`ol+zjBuh6u}uxl&<xGGmfI<g?&yy0 z=#Ji(HS~twNE&)Wr&FK@dY}hFpeK2fXOy$i8ve#c#v)Uy>}d=JgTY`h7zzmngTY`h z7z~EOgu!4i7z_r3q0nJ47z_r3!C<gNgTvsk&XHLaK%wt<BZ5Hhj|_`r?ie|nIxJNN zzH|l-i^Ec7fy3c&I2;a#qe=yb!{9JD483#?hr{471YSv7CB$cYlUI3rb)dq#F{?_A zcY~>6+AwG^HM|>NHa2N^H@xdO${QX3hJVAqA5p`<QJV%sgP~D}er!~wo*spswjU!k z2>b%JfFtm$qwO5jAmE73!GqOtvnXH*SOSQ^uwDUJf`!4PKnPg)5bVR51T4|(Q7rv! z=%;`NL&A_SBn$~d!ceah3;{#JkT3)cY(p>~hJ+zuNEq0fK!+h=NEi};#6Q?9S(r?6 z_Hc5CBWv$I$MszAbb5NKv$HcT77Lx9pKG;R>GJYYS65fMzP{GY&5iEv?)32Rpv`8Z z`|qi@7Z?1F=Tx`<271SSmGyml+Oxl1yT4q0?k>xIUc3Kg{u}R~pKn_S{_CFnTRg7& E0S~(Oi~s-t literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5configcc.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configcc.c new file mode 100644 index 000000000..13c5ac86b --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configcc.c @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#if _WIN32_WINNT < 0x501 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x501 +#endif + +#include<krbcred.h> +#include<krb5.h> +#include<assert.h> +#include<lm.h> +#include<commctrl.h> +#include<shlwapi.h> + +#include<strsafe.h> + +typedef struct tag_k5_file_cc { + wchar_t path[MAX_PATH]; + khm_int32 flags; +} k5_file_cc; + +#define K5_FCC_ALLOC_INCR 8 + +#define K5_FCC_FLAG_EXISTS 1 + +typedef struct tag_k5_ccc_data { + khm_boolean inc_api; + khm_boolean inc_mslsa; + k5_file_cc * file_ccs; + khm_size n_file_ccs; + khm_size nc_file_ccs; +} k5_ccc_data; + +typedef struct tag_k5_ccc_dlg_data { + khui_config_node node; + k5_ccc_data save; + k5_ccc_data work; +} k5_ccc_dlg_data; + +void k5_free_file_ccs(k5_ccc_data * d) { + if (d->file_ccs) + PFREE(d->file_ccs); + d->n_file_ccs = 0; + d->nc_file_ccs = 0; +} + +void k5_flush_file_ccs(k5_ccc_data * d) { + d->n_file_ccs = 0; +} + +void k5_del_file_cc(k5_ccc_data * d, khm_size idx) { + if (idx > d->n_file_ccs) + return; + + if (idx < d->n_file_ccs - 1) { + MoveMemory(&d->file_ccs[idx], + &d->file_ccs[idx + 1], + sizeof(d->file_ccs[0]) * (d->n_file_ccs - (idx + 1))); + } + + d->n_file_ccs--; +} + +void k5_add_file_cc(k5_ccc_data * d, wchar_t * path) { + khm_size i; + khm_size cch; + + if (FAILED(StringCchLength(path, MAX_PATH, &cch)) || + cch == 0) + return; + + /* see if it's there first */ + for (i=0; i < d->n_file_ccs; i++) { + if(!_wcsicmp(d->file_ccs[i].path, path)) + return; + } + + if (d->n_file_ccs == d->nc_file_ccs) { + k5_file_cc * f; + + d->nc_file_ccs = UBOUNDSS(d->n_file_ccs + 1, + K5_FCC_ALLOC_INCR, + K5_FCC_ALLOC_INCR); +#ifdef DEBUG + assert(d->nc_file_ccs > d->n_file_ccs); +#endif + f = PMALLOC(sizeof(*f) * d->nc_file_ccs); + ZeroMemory(f, sizeof(*f) * d->nc_file_ccs); + + if (d->n_file_ccs > 0) { +#ifdef DEBUG + assert(d->file_ccs != NULL); +#endif + memcpy(f, d->file_ccs, sizeof(*f) * d->n_file_ccs); + } + if (d->file_ccs) + PFREE(d->file_ccs); + d->file_ccs = f; + } + + StringCbCopy(d->file_ccs[d->n_file_ccs].path, + sizeof(d->file_ccs[0].path), + path); + if(PathFileExists(path)) + d->file_ccs[d->n_file_ccs].flags = K5_FCC_FLAG_EXISTS; + else + d->file_ccs[d->n_file_ccs].flags = 0; + + d->n_file_ccs++; +} + +void k5_read_file_cc_data(k5_ccc_data * d) { + khm_int32 t; + wchar_t * fclist = NULL; + wchar_t * fc; + khm_size cb; + +#ifdef DEBUG + assert(csp_params); +#endif + + d->inc_api = TRUE; + t = TRUE; + khc_read_int32(csp_params, L"MsLsaList", &t); + d->inc_mslsa = t; + + if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + != KHM_ERROR_TOO_LONG || + cb <= sizeof(wchar_t) * 2) { + + k5_flush_file_ccs(d); + } else { + fclist = PMALLOC(cb); +#ifdef DEBUG + assert(fclist); +#endif + khc_read_multi_string(csp_params, L"FileCCList", fclist, &cb); + + for(fc = fclist; fc && *fc; fc = multi_string_next(fc)) { + k5_add_file_cc(d, fc); + } + + PFREE(fclist); + } +} + +void k5_write_file_cc_data(k5_ccc_data * d) { + wchar_t * ms; + khm_size cb; + khm_size cbt; + khm_int32 t; + khm_size i; + +#ifdef DEBUG + assert(csp_params); +#endif + if (KHM_FAILED(khc_read_int32(csp_params, L"MsLsaList", &t)) || + !!t != !!d->inc_mslsa) { + khc_write_int32(csp_params, L"MsLsaList", !!d->inc_mslsa); + } + + if (d->n_file_ccs > 0) { + cb = d->n_file_ccs * MAX_PATH * sizeof(wchar_t); + ms = PMALLOC(cb); +#ifdef DEBUG + assert(ms); +#endif + multi_string_init(ms, cb); + + for(i=0; i<d->n_file_ccs; i++) { + cbt = cb; + multi_string_append(ms, &cbt, d->file_ccs[i].path); + } + + khc_write_multi_string(csp_params, L"FileCCList", ms); + + PFREE(ms); + } else { + if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + != KHM_ERROR_TOO_LONG || + cb != sizeof(wchar_t) * 2) + + khc_write_multi_string(csp_params, L"FileCCList", L"\0\0"); + } +} + +void k5_copy_file_cc_data(k5_ccc_data * dest, const k5_ccc_data * src) { + khm_size i; + + k5_flush_file_ccs(dest); + dest->inc_mslsa = src->inc_mslsa; + dest->inc_api = src->inc_api; + + for (i=0; i < src->n_file_ccs; i++) { + k5_add_file_cc(dest, src->file_ccs[i].path); + } +} + +BOOL k5_ccc_get_mod(k5_ccc_dlg_data * d) { + khm_size i, j; + + if (!!d->work.inc_mslsa != !!d->save.inc_mslsa || + !!d->work.inc_api != !!d->save.inc_api || + d->work.n_file_ccs != d->save.n_file_ccs) + return TRUE; + + for (i=0; i < d->work.n_file_ccs; i++) { + for (j=0; j < d->save.n_file_ccs; j++) { + if (!_wcsicmp(d->work.file_ccs[i].path, + d->save.file_ccs[j].path)) + break; + } + if (j >= d->save.n_file_ccs) + return TRUE; + } + + return FALSE; +} + +void k5_ccc_update_ui(HWND hwnd, k5_ccc_dlg_data * d) { + khm_size i; + HWND lv; + + if (d->work.inc_api) + CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_CHECKED); + else + CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_UNCHECKED); + if (d->work.inc_mslsa) + CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_CHECKED); + else + CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_UNCHECKED); + + lv = GetDlgItem(hwnd, IDC_CFG_FCLIST); +#ifdef DEBUG + assert(lv); +#endif + ListView_DeleteAllItems(lv); + + for (i=0; i<d->work.n_file_ccs; i++) { + LVITEM lvi; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_PARAM | LVIF_TEXT; + lvi.lParam = (LPARAM) i; + lvi.pszText = d->work.file_ccs[i].path; + + ListView_InsertItem(lv, &lvi); + } + + if (k5_ccc_get_mod(d)) { + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } else { + khui_cfg_set_flags(d->node, + 0, + KHUI_CNFLAG_MODIFIED); + } +} + +void k5_ccc_update_data(HWND hwnd, k5_ccc_data * d) { + if (IsDlgButtonChecked(hwnd, IDC_CFG_INCAPI) == BST_CHECKED) + d->inc_api = TRUE; + else + d->inc_api = FALSE; + + if (IsDlgButtonChecked(hwnd, IDC_CFG_INCMSLSA) == BST_CHECKED) + d->inc_mslsa = TRUE; + else + d->inc_mslsa = FALSE; + /* everything else is controlled by buttons */ +} + +INT_PTR CALLBACK +k5_ccconfig_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + k5_ccc_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d); +#endif + ZeroMemory(d, sizeof(*d)); + k5_read_file_cc_data(&d->save); + k5_copy_file_cc_data(&d->work, &d->save); + + d->node = (khui_config_node) lParam; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + { + LVCOLUMN lvc; + HWND lv; + wchar_t buf[256]; + RECT r; + + lv = GetDlgItem(hwnd, IDC_CFG_FCLIST); +#ifdef DEBUG + assert(lv); +#endif + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + + LoadString(hResModule, IDS_CFG_FCTITLE, + buf, ARRAYLENGTH(buf)); + + GetWindowRect(lv, &r); + + lvc.pszText = buf; + lvc.cx = (r.right - r.left) * 9 / 10; + + ListView_InsertColumn(lv, 0, &lvc); + } + + SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, EM_SETLIMITTEXT, + MAX_PATH - 1, 0); + + k5_ccc_update_ui(hwnd, d); + break; + + case WM_COMMAND: + d = (k5_ccc_dlg_data *) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + switch(wParam) { + case MAKEWPARAM(IDC_CFG_ADD, BN_CLICKED): + { + wchar_t path[MAX_PATH]; + wchar_t cpath[MAX_PATH]; + khm_size i; + + GetDlgItemText(hwnd, IDC_CFG_FCNAME, + cpath, ARRAYLENGTH(cpath)); + + PathCanonicalize(path, cpath); + + if (!*path) + return TRUE; /* nothing to add */ + + for (i=0; i < d->work.n_file_ccs; i++) { + if (!_wcsicmp(path, d->work.file_ccs[i].path)) { + + /* allow the user to correct case, as appropriate */ + StringCbCopy(d->work.file_ccs[i].path, + sizeof(d->work.file_ccs[i].path), + path); + k5_ccc_update_ui(hwnd, d); + return TRUE; + } + } + + /* not there. we need to add. but check a few things + first */ + if (!PathFileExists(path)) { + wchar_t title[64]; + wchar_t text[128]; + + LoadString(hResModule, IDS_CFG_FCN_WARNING, + title, ARRAYLENGTH(title)); + + LoadString(hResModule, IDS_CFG_FCN_W_NOTFOUND, + text, ARRAYLENGTH(text)); +#if _WIN32_WINNT >= 0x501 + if (IS_COMMCTL6()) + { + EDITBALLOONTIP bt; + + bt.cbStruct = sizeof(bt); + bt.pszTitle = title; + bt.pszText = text; + bt.ttiIcon = TTI_WARNING; + + SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, + EM_SHOWBALLOONTIP, + 0, + (LPARAM) &bt); + } else { +#endif + MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING); +#if _WIN32_WINNT >= 0x501 + } +#endif + } else if (PathIsRelative(path)) { + wchar_t title[64]; + wchar_t text[128]; + + LoadString(hResModule, IDS_CFG_FCN_WARNING, + title, ARRAYLENGTH(title)); + LoadString(hResModule, IDS_CFG_FCN_W_RELATIVE, + text, ARRAYLENGTH(text)); + +#if _WIN32_WINNT >= 0x501 + if (IS_COMMCTL6()) + { + EDITBALLOONTIP bt; + + bt.cbStruct = sizeof(bt); + bt.pszTitle = title; + bt.pszText = text; + bt.ttiIcon = TTI_WARNING; + + SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, + EM_SHOWBALLOONTIP, + 0, + (LPARAM) &bt); + } else { +#endif + MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING); +#if _WIN32_WINNT >= 0x501 + } +#endif + } + + k5_add_file_cc(&d->work, path); + + k5_ccc_update_ui(hwnd, d); + } + return TRUE; + + case MAKEWPARAM(IDC_CFG_BROWSE, BN_CLICKED): + { + OPENFILENAME ofn; + wchar_t path[MAX_PATH * 8]; + wchar_t title[128]; + + ZeroMemory(&ofn, sizeof(ofn)); + ZeroMemory(path, sizeof(path)); + + GetDlgItemText(hwnd, IDC_CFG_FCNAME, + path, ARRAYLENGTH(path)); + + /* don't pass in invalid paths */ + if (!PathFileExists(path)) + *path = 0; + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = L"All files\0*.*\0\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = path; + ofn.nMaxFile = ARRAYLENGTH(path); + ofn.lpstrTitle = title; + + LoadString(hResModule, IDS_CFG_FCOPENTITLE, + title, ARRAYLENGTH(title)); + + ofn.Flags = OFN_ALLOWMULTISELECT | + OFN_DONTADDTORECENT | + OFN_FORCESHOWHIDDEN | + OFN_EXPLORER; + + if (GetOpenFileName(&ofn)) { + wchar_t * p; + wchar_t spath[MAX_PATH]; + + p = multi_string_next(path); + if (p) { + /* multi select */ + for(;p && *p; p = multi_string_next(p)) { + StringCbCopy(spath, sizeof(spath), path); + PathAppend(spath, p); + + k5_add_file_cc(&d->work, spath); + } + } else { + /* single select */ + k5_add_file_cc(&d->work, path); + } + k5_ccc_update_ui(hwnd, d); + } + } + return TRUE; + + case MAKEWPARAM(IDC_CFG_REMOVE, BN_CLICKED): + { + khm_size i; + int lv_idx; + HWND lv; + wchar_t buf[MAX_PATH]; + + lv = GetDlgItem(hwnd, IDC_CFG_FCLIST); +#ifdef DEBUG + assert(lv); +#endif + + lv_idx = -1; + while((lv_idx = ListView_GetNextItem(lv, lv_idx, + LVNI_SELECTED)) != -1) { + ListView_GetItemText(lv, lv_idx, 0, buf, ARRAYLENGTH(buf)); + for (i=0; i < d->work.n_file_ccs; i++) { + if (!_wcsicmp(buf, d->work.file_ccs[i].path)) { + k5_del_file_cc(&d->work, i); + break; + } + } + } + + k5_ccc_update_ui(hwnd, d); + } + return TRUE; + + case MAKEWPARAM(IDC_CFG_INCAPI, BN_CLICKED): + case MAKEWPARAM(IDC_CFG_INCMSLSA, BN_CLICKED): + k5_ccc_update_data(hwnd, &d->work); + k5_ccc_update_ui(hwnd, d); + return TRUE; + } + break; + + case WM_DESTROY: + d = (k5_ccc_dlg_data *) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + k5_free_file_ccs(&d->work); + k5_free_file_ccs(&d->save); + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + d = (k5_ccc_dlg_data *) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + switch(HIWORD(wParam)) { + case WMCFG_APPLY: + if (k5_ccc_get_mod(d)) { + k5_write_file_cc_data(&d->work); + k5_copy_file_cc_data(&d->save, &d->work); + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED); + k5_ccc_update_ui(hwnd, d); + + kmq_post_sub_msg(k5_sub, KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); + } + break; + } + } + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5configdlg.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configdlg.c new file mode 100644 index 000000000..ed11f7ec8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configdlg.c @@ -0,0 +1,2896 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<krb5.h> +#include<assert.h> +#include<lm.h> +#include<commctrl.h> +#include<shlwapi.h> + +#include<strsafe.h> + +#pragma warning(disable: 4204 4221) + +typedef struct tag_k5_realm_kdc { + wchar_t name[K5_MAXCCH_HOST]; + khm_boolean admin; /* admin server? */ + khm_boolean master; /* master kdc? */ + khm_int32 flags; +} k5_realm_kdc; + +#define K5_RKFLAG_DELETED 1 +#define K5_RKFLAG_NEW 2 +#define K5_RKFLAG_MOD_ADMIN 4 +#define K5_RKFLAG_MOD_MASTER 8 + +typedef struct tag_k5_domain_map { + wchar_t name[K5_MAXCCH_HOST]; /* name of host that maps to a + realm */ + khm_int32 flags; +} k5_domain_map; + +#define K5_DMFLAG_DELETED 1 +#define K5_DMFLAG_NEW 2 + +typedef struct tag_k5_realm_data { + wchar_t realm[K5_MAXCCH_REALM]; + k5_realm_kdc kdcs[K5_MAX_KDC]; + khm_size n_kdcs; + k5_domain_map domain_maps[K5_MAX_DOMAIN_MAPPINGS]; + khm_size n_domain_maps; + + khm_int32 flags; +} k5_realm_data; + +#define K5_RDFLAG_DELETED 1 +#define K5_RDFLAG_NEW 2 +#define K5_RDFLAG_MODIFED 4 + +#define K5_REALMS_ALLOC_INCR 8 + +typedef struct tag_k5_config_data { + wchar_t def_realm[K5_MAXCCH_REALM]; /* default realm */ + + wchar_t config_file[MAX_PATH]; /* path to configuration file */ + khm_boolean create_config_file; /* create config_file if missing? */ + khm_boolean inc_realms; /* include full realm list in new + credentials dialog? */ + wchar_t loaded_config_file[MAX_PATH]; /* path to the + configuration file + that has been + loaded into the + realm editor. */ + + /* [libdefaults] */ + khm_boolean dns_lookup_kdc; + khm_boolean dns_lookup_realm; + khm_boolean dns_fallback; + + khm_boolean noaddresses; + + k5_lsa_import lsa_import; /* import mslsa creds? */ + + /* [realms] */ + k5_realm_data *realms; + khm_size n_realms; + khm_size nc_realms; + khm_size c_realm; + + khui_config_node node_main; + khui_config_node node_realm; + + khm_int32 flags; + + /* used by the realm editor */ + HMENU hm_realms_ctx; + HMENU hm_kdc_ctx; + HMENU hm_dmap_ctx; +} k5_config_data; + +#define K5_CDFLAG_MOD_DEF_REALM 0x00000001 +#define K5_CDFLAG_MOD_CONF_FILE 0x00000002 +#define K5_CDFLAG_MOD_DNS_LOOKUP_KDC 0x00000004 +#define K5_CDFLAG_MOD_DNS_LOOKUP_RLM 0x00000008 +#define K5_CDFLAG_MOD_DNS_FALLBACK 0x00000010 +#define K5_CDFLAG_MOD_NOADDRESSES 0x00000020 +#define K5_CDFLAG_MOD_LSA_IMPORT 0x00000040 +#define K5_CDFLAG_MOD_CREATE_CONF 0x00000080 +#define K5_CDFLAG_MOD_INC_REALMS 0x00000100 +#define K5_CDFLAG_MOD_REALMS 0x00001000 + +void +k5_init_config_data(k5_config_data * d) { + ZeroMemory(d, sizeof(*d)); +} + +void +k5_free_config_data(k5_config_data * d) { + if (d->realms) + PFREE(d->realms); + + k5_init_config_data(d); +} + +static void +k5_assert_n_realms(k5_config_data * d, khm_size n) { + khm_size nc_realms; + + if (n <= d->nc_realms) + return; + + nc_realms = UBOUNDSS(n, K5_REALMS_ALLOC_INCR, K5_REALMS_ALLOC_INCR); + assert(nc_realms > d->nc_realms); + + d->realms = PREALLOC(d->realms, nc_realms * sizeof(*(d->realms))); + d->nc_realms = nc_realms; + + ZeroMemory(&d->realms[d->n_realms], + (d->nc_realms - d->n_realms) * sizeof(*(d->realms))); +} + +void +k5_purge_config_data(k5_config_data * d, + khm_boolean purge_realms, + khm_boolean purge_kdcs, + khm_boolean purge_dmap) { + khm_size r; + khm_size k; + khm_size m; + + for (r=0; r < d->n_realms; r++) { + if (purge_realms && + (d->realms[r].flags & K5_RDFLAG_NEW) && + (d->realms[r].flags & K5_RDFLAG_DELETED)) { + + if (d->n_realms > r+1) + MoveMemory(&d->realms[r], &d->realms[r+1], + sizeof(d->realms[0]) * (d->n_realms - (r+1))); + r--; + d->n_realms--; + continue; + } + + for (k=0; k < d->realms[r].n_kdcs; k++) { + if (purge_kdcs && + (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) && + (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) { + if (d->realms[r].n_kdcs > k + 1) + MoveMemory(&d->realms[r].kdcs[k], + &d->realms[r].kdcs[k+1], + sizeof(d->realms[0].kdcs[0]) * + (d->realms[r].n_kdcs - (k+1))); + k--; + d->realms[r].n_kdcs--; + continue; + } + } + + if (K5_MAX_KDC > k+1) + ZeroMemory(&d->realms[r].kdcs[k], + sizeof(d->realms[0].kdcs[0]) * + (K5_MAX_KDC - (k + 1))); + + for (m=0; m < d->realms[r].n_domain_maps; m++) { + if (purge_dmap && + (d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) && + (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED)) { + if (d->realms[r].n_domain_maps > m + 1) + MoveMemory(&d->realms[r].domain_maps[m], + &d->realms[r].domain_maps[m+1], + sizeof(d->realms[0].domain_maps[0]) * + (d->realms[r].n_domain_maps - (m+1))); + m--; + d->realms[r].n_domain_maps--; + continue; + } + } + + if (K5_MAX_DOMAIN_MAPPINGS > m+1) + ZeroMemory(&d->realms[r].domain_maps[m], + sizeof(d->realms[0].domain_maps[0]) * + (K5_MAX_DOMAIN_MAPPINGS - (m+1))); + } + + if (d->nc_realms > r + 1) + ZeroMemory(&d->realms[r], + sizeof(d->realms[0]) * + (d->nc_realms - (r + 1))); +} + +static khm_boolean +k5_is_profile_loaded(void) { +#ifdef DEBUG + assert(pprofile_init); + assert(pprofile_get_subsection_names); + assert(pprofile_get_values); + assert(pprofile_get_string); + assert(pprofile_get_relation_names); + assert(pprofile_free_list); + assert(pprofile_release_string); + assert(pprofile_release); + assert(pprofile_clear_relation); + assert(pprofile_add_relation); + assert(pprofile_update_relation); + assert(pprofile_flush); + assert(pprofile_rename_section); +#endif + + if (!pprofile_init || + !pprofile_get_subsection_names || + !pprofile_get_values || + !pprofile_get_string || + !pprofile_get_relation_names || + !pprofile_free_list || + !pprofile_release_string || + !pprofile_release || + !pprofile_clear_relation || + !pprofile_add_relation || + !pprofile_update_relation || + !pprofile_flush || + !pprofile_rename_section) + + return FALSE; + + return TRUE; +} + +void +k5_read_config_data(k5_config_data * d) { + wchar_t * defrealm; + char config_file[MAX_PATH]; + profile_t profile = NULL; + const char *filenames[2]; + long rv; + khm_size s; + + if (!k5_is_profile_loaded()) + return; + + defrealm = khm_krb5_get_default_realm(); + + if (defrealm) { + StringCbCopy(d->def_realm, sizeof(d->def_realm), defrealm); + PFREE(defrealm); + } else { + StringCbCopy(d->def_realm, sizeof(d->def_realm), L""); + } + + khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file)); + + AnsiStrToUnicode(d->config_file, sizeof(d->config_file), config_file); + + filenames[0] = config_file; + filenames[1] = NULL; + + rv = pprofile_init(filenames, &profile); + + if (!rv) { + const char * sec_realms[] = { "realms", NULL }; + const char * sec_domain_realm[] = { "domain_realm", NULL }; + char ** sections; + char ** dr_from; + char * boolv; + + /* first fish out a few values from [libdefaults] */ + + rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_kdc", + NULL, NULL, &boolv); + if (!rv && boolv) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(boolv, &b)) + d->dns_lookup_kdc = b; + else + d->dns_lookup_kdc = FALSE; + pprofile_release_string(boolv); + } else + d->dns_lookup_kdc = FALSE; + + rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_realm", + NULL, NULL, &boolv); + if (!rv && boolv) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(boolv, &b)) + d->dns_lookup_realm = b; + else + d->dns_lookup_realm = FALSE; + pprofile_release_string(boolv); + } else + d->dns_lookup_realm = FALSE; + + rv = pprofile_get_string(profile, "libdefaults", "dns_fallback", + NULL, NULL, &boolv); + if (!rv && boolv) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(boolv, &b)) + d->dns_fallback = b; + else + d->dns_fallback = FALSE; + pprofile_release_string(boolv); + } else + d->dns_fallback = FALSE; + + rv = pprofile_get_string(profile, "libdefaults", "noaddresses", + NULL, NULL, &boolv); + if (!rv && boolv) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(boolv, &b)) + d->noaddresses = b; + else + d->noaddresses = TRUE; + pprofile_release_string(boolv); + } else + d->noaddresses = TRUE; + + /* now we look at the [realms] section */ + rv = pprofile_get_subsection_names(profile, sec_realms, &sections); + + /* what? no realms? whatever */ + if (rv) goto _skip_realms; + + /* get a count first */ + for (s=0; sections[s] && sections[s][0]; s++); + + k5_assert_n_realms(d, s); + d->n_realms = s; + + /* now go through each and fish out the kdcs, admin_server + and master_kdc. */ + for (s=0; sections[s] && sections[s][0]; s++) { + const char * sec_kdcs[] = + { "realms", sections[s], "kdc", NULL }; + + const char * sec_admin[] = + { "realms", sections[s], "admin_server", NULL }; + + const char * sec_master[] = + { "realms", sections[s], "master_kdc", NULL }; + + char ** values; + + AnsiStrToUnicode(d->realms[s].realm, sizeof(d->realms[s].realm), + sections[s]); + d->realms[s].n_kdcs = 0; + d->realms[s].n_domain_maps = 0; + + rv = pprofile_get_values(profile, sec_kdcs, &values); + if (!rv) { + khm_size i; + + for (i=0 ; values[i] && values[i][0] && i < K5_MAX_KDC; i++) { + AnsiStrToUnicode(d->realms[s].kdcs[i].name, + sizeof(d->realms[s].kdcs[i].name), + values[i]); + + } + d->realms[s].n_kdcs = i; + + pprofile_free_list(values); + } + + rv = pprofile_get_values(profile, sec_admin, &values); + if (!rv) { + khm_size i; + khm_size j; + wchar_t kdc_name[K5_MAXCCH_HOST]; + + for (i=0; values[i] && values[i][0]; i++) { + AnsiStrToUnicode(kdc_name, + sizeof(kdc_name), values[i]); + + for (j=0; j < d->realms[s].n_kdcs; j++) + if (!_wcsicmp(kdc_name, d->realms[s].kdcs[j].name)) + break; + + if (j < d->realms[s].n_kdcs) { + d->realms[s].kdcs[j].admin = TRUE; + } else if (d->realms[s].n_kdcs < K5_MAX_KDC) { + j = d->realms[s].n_kdcs; + StringCbCopy(d->realms[s].kdcs[j].name, + sizeof(d->realms[s].kdcs[j].name), + kdc_name); + d->realms[s].kdcs[j].admin = TRUE; + d->realms[s].n_kdcs ++; + } + } + pprofile_free_list(values); + } + + rv = pprofile_get_values(profile, sec_master, &values); + if (!rv) { + khm_size i; + khm_size j; + wchar_t kdc_name[K5_MAXCCH_HOST]; + + for (i=0; values[i] && values[i][0]; i++) { + AnsiStrToUnicode(kdc_name, sizeof(kdc_name), values[i]); + + for (j=0; j < d->realms[s].n_kdcs; j++) + if (!_wcsicmp(kdc_name, d->realms[s].kdcs[j].name)) + break; + + if (j < d->realms[s].n_kdcs) { + d->realms[s].kdcs[j].master = TRUE; + } else if (d->realms[s].n_kdcs < K5_MAX_KDC) { + j = d->realms[s].n_kdcs; + StringCbCopy(d->realms[s].kdcs[j].name, + sizeof(d->realms[s].kdcs[j].name), + kdc_name); + d->realms[s].kdcs[j].master = TRUE; + d->realms[s].n_kdcs ++; + } + } + + pprofile_free_list(values); + } + } + pprofile_free_list(sections); + + _skip_realms: + + rv = pprofile_get_relation_names(profile, sec_domain_realm, &dr_from); + if (!rv) { + khm_size i; + khm_size j; + char * dr_to; + wchar_t wdr_from[K5_MAXCCH_HOST]; + wchar_t wdr_to[K5_MAXCCH_HOST]; + + for (i=0; dr_from[i] && dr_from[i][0]; i++) { + AnsiStrToUnicode(wdr_from, sizeof(wdr_from), dr_from[i]); + + rv = pprofile_get_string(profile, "domain_realm", dr_from[i], + NULL, NULL, &dr_to); + + if (rv || !dr_to) + continue; + + AnsiStrToUnicode(wdr_to, sizeof(wdr_to), dr_to); + + for (j=0; j < d->n_realms; j++) { + if (!_wcsicmp(wdr_to, d->realms[j].realm)) + break; + } + + if (j >= d->n_realms) { + j = d->n_realms; + k5_assert_n_realms(d, j + 1); + + StringCbCopy(d->realms[j].realm, + sizeof(d->realms[j].realm), + wdr_to); + d->realms[j].n_kdcs = 0; + d->realms[j].n_domain_maps = 0; + + d->n_realms++; + } + + if (d->realms[j].n_domain_maps < K5_MAX_DOMAIN_MAPPINGS) { + khm_size k; + + k = d->realms[j].n_domain_maps; + + StringCbCopy(d->realms[j].domain_maps[k].name, + sizeof(d->realms[j].domain_maps[k].name), + wdr_from); + + d->realms[j].n_domain_maps++; + } + + pprofile_release_string(dr_to); + } + pprofile_free_list(dr_from); + } + pprofile_release(profile); + } + + { + khm_int32 t; + + /* last, read the MSLSA import setting */ + if (KHM_SUCCEEDED(khc_read_int32(csp_params, + L"MsLsaImport", &t))) { + d->lsa_import = t; + } else { + d->lsa_import = K5_LSAIMPORT_ALWAYS; + } + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, + L"UseFullRealmList", &t))) { + d->inc_realms = !!t; + } else { + d->inc_realms = TRUE; + } + } + + d->flags = 0; +} + +int +k5_write_config_data(k5_config_data * d) { + char astr[MAX_PATH * 2]; + char config_file[MAX_PATH]; + profile_t profile = NULL; + const char *filenames[2]; + long rv; + khm_size s; + int applied = FALSE; + + if (d->flags == 0) + return FALSE; + + if (!k5_is_profile_loaded()) + return FALSE; + + /* write the MSLSA import setting */ + if (d->flags & K5_CDFLAG_MOD_LSA_IMPORT) { + khc_write_int32(csp_params, L"MsLsaImport", d->lsa_import); + d->flags &= ~K5_CDFLAG_MOD_LSA_IMPORT; + applied = TRUE; + } + + if (d->flags & K5_CDFLAG_MOD_INC_REALMS) { + khc_write_int32(csp_params, L"UseFullRealmList", d->inc_realms); + d->flags &= ~K5_CDFLAG_MOD_INC_REALMS; + applied = TRUE; + } + + if (!(d->flags & + (K5_CDFLAG_MOD_DEF_REALM | + K5_CDFLAG_MOD_CONF_FILE | + K5_CDFLAG_MOD_DNS_FALLBACK | + K5_CDFLAG_MOD_DNS_LOOKUP_RLM | + K5_CDFLAG_MOD_DNS_LOOKUP_KDC | + K5_CDFLAG_MOD_NOADDRESSES | + K5_CDFLAG_MOD_CREATE_CONF | + K5_CDFLAG_MOD_REALMS))) { + + d->flags = 0; + return applied; + } + + khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file)); + + UnicodeStrToAnsi(astr, sizeof(astr), d->config_file); + + if (_stricmp(config_file, astr)) { + assert(FALSE); + } + + filenames[0] = config_file; + filenames[1] = NULL; + + rv = pprofile_init(filenames, &profile); + +#if FAILOVER_TO_TEMPORARY_FILE + if (rv) { + char temp_file[MAX_PATH]; + + khm_krb5_get_temp_profile_file(temp_file, + ARRAYLENGTH(temp_file)); + + filenames[0] = temp_file; + + rv = pprofile_init(filenames, &profile); + + ?? TODO: Also warn if we are doing this + } +#endif + + if (!rv) { + const char * sec_realms[] = { "realms", NULL }; + const char * sec_domain_realm[] = { "domain_realm", NULL }; + const char * sec_libdefaults[] = { "libdefaults", NULL, NULL }; + khm_size r; + + if (d->flags & K5_CDFLAG_MOD_DEF_REALM) { + if (SUCCEEDED(StringCbLength(d->def_realm, + sizeof(d->def_realm), &s)) && + s > 0) { + char defrealm[K5_MAXCCH_REALM]; + + UnicodeStrToAnsi(defrealm, sizeof(defrealm), + d->def_realm); + + khm_krb5_set_default_realm(d->def_realm); + + sec_libdefaults[1] = "default_realm"; + + pprofile_clear_relation(profile, sec_libdefaults); + + rv = pprofile_add_relation(profile, sec_libdefaults, + defrealm); + applied = TRUE; + } + d->flags &= ~K5_CDFLAG_MOD_DEF_REALM; + } + + if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_KDC) { + + sec_libdefaults[1] = "dns_lookup_kdc"; + + pprofile_clear_relation(profile, sec_libdefaults); + + rv = pprofile_add_relation(profile, sec_libdefaults, + (d->dns_lookup_kdc)? + KRB5_CONF_YES: + KRB5_CONF_NO); + d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_KDC; + applied = TRUE; + } + + if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) { + + sec_libdefaults[1] = "dns_lookup_realm"; + + pprofile_clear_relation(profile, sec_libdefaults); + + rv = pprofile_add_relation(profile, sec_libdefaults, + (d->dns_lookup_realm)? + KRB5_CONF_YES: + KRB5_CONF_NO); + + d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_RLM; + applied = TRUE; + } + + if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) { + + sec_libdefaults[1] = "dns_fallback"; + + pprofile_clear_relation(profile, sec_libdefaults); + + rv = pprofile_add_relation(profile, sec_libdefaults, + (d->dns_fallback)? + KRB5_CONF_YES: + KRB5_CONF_NO); + + d->flags &= ~K5_CDFLAG_MOD_DNS_FALLBACK; + applied = TRUE; + } + + if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) { + + sec_libdefaults[1] = "noaddresses"; + + pprofile_clear_relation(profile, sec_libdefaults); + + rv = pprofile_add_relation(profile, sec_libdefaults, + (d->noaddresses)? + KRB5_CONF_YES: + KRB5_CONF_NO); + + d->flags &= ~K5_CDFLAG_MOD_NOADDRESSES; + applied = TRUE; + } + + /* now we look at the [realms] section */ + + for (r=0; r < d->n_realms; r++) { + char realm[K5_MAXCCH_REALM]; + char host[K5_MAXCCH_HOST]; + + const char * sec_kdcs[] = + { "realms", realm, "kdc", NULL }; + + const char * sec_admin[] = + { "realms", realm, "admin_server", NULL }; + + const char * sec_master[] = + { "realms", realm, "master_kdc", NULL }; + + const char * sec_domain_map[] = + { "domain_realm", host, NULL }; + + char ** values; + + UnicodeStrToAnsi(realm, sizeof(realm), + d->realms[r].realm); + + if (!(d->realms[r].flags & K5_RDFLAG_DELETED) && + (d->realms[r].flags & K5_RDFLAG_NEW)) { + + khm_size k; + khm_size m; + + /* this is a new realm */ + + for (k=0; k < d->realms[r].n_kdcs; k++) { + if (!(d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) { + UnicodeStrToAnsi(host, sizeof(host), + d->realms[r].kdcs[k].name); + + if (d->realms[r].kdcs[k].master) + pprofile_add_relation(profile, sec_master, + host); + + pprofile_add_relation(profile, sec_kdcs, + host); + + if (d->realms[r].kdcs[k].admin) + pprofile_add_relation(profile, sec_admin, + host); + + d->realms[r].kdcs[k].flags &= ~ (K5_RKFLAG_NEW | + K5_RKFLAG_MOD_MASTER | + K5_RKFLAG_MOD_ADMIN); + applied = TRUE; + } + } + + for (m=0; m < d->realms[r].n_domain_maps; m++) { + + UnicodeStrToAnsi(host, sizeof(host), + d->realms[r].domain_maps[m].name); + + if ((d->realms[r].domain_maps[m].flags & + K5_DMFLAG_DELETED) && + !(d->realms[r].domain_maps[m].flags & + K5_DMFLAG_NEW)) { + pprofile_clear_relation(profile, sec_domain_map); + + /* setting this flag indicates that the item + is deleted and not in the profile file + anymore. */ + d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW; + applied = TRUE; + } else if (!(d->realms[r].domain_maps[m].flags & + K5_DMFLAG_DELETED) && + (d->realms[r].domain_maps[m].flags & + K5_DMFLAG_NEW)) { + pprofile_add_relation(profile, sec_domain_map, + realm); + + d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW; + applied = TRUE; + } + } + + d->realms[r].flags &= ~(K5_RDFLAG_NEW | + K5_RDFLAG_MODIFED); + + } else if ((d->realms[r].flags & K5_RDFLAG_DELETED) && + !(d->realms[r].flags & K5_RDFLAG_NEW)) { + + const char * sec_all[] = + { "realms", realm, NULL, NULL }; + khm_size v; + + /* this realm should be deleted */ + + rv = pprofile_get_relation_names(profile, sec_all, + &values); + if (!rv) { + for (v=0; values[v] && values[v][0]; v++) { + sec_all[2] = values[v]; + pprofile_clear_relation(profile, sec_all); + } + sec_all[2] = NULL; + pprofile_rename_section(profile, sec_all, NULL); + pprofile_free_list(values); + applied = TRUE; + } + + rv = pprofile_get_relation_names(profile, sec_domain_realm, + &values); + if (!rv) { + char * maprealm; + + for (v=0; values[v] && values[v][0]; v++) { + + rv = pprofile_get_string(profile, "domain_realm", + values[v], NULL, NULL, + &maprealm); + + if (!rv) { + if (!strcmp(maprealm, realm)) { + StringCbCopyA(host, sizeof(host), + values[v]); + pprofile_clear_relation(profile, + sec_domain_map); + applied = TRUE; + } + pprofile_release_string(maprealm); + } + } + + pprofile_free_list(values); + } + + /* setting this flag indicate that the realm is + deleted and is not in the profile file. */ + d->realms[r].flags |= K5_RDFLAG_NEW; + + } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED) && + (d->realms[r].flags & K5_RDFLAG_MODIFED)) { + khm_size k; + khm_size m; + + /* same as before. check if we have to update the kdc + list or the domain_realm mappings */ + + for (k=0; k < d->realms[r].n_kdcs; k++) { + + if ((d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) && + (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) + continue; + + UnicodeStrToAnsi(host, sizeof(host), + d->realms[r].kdcs[k].name); + + if (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED) { + pprofile_update_relation(profile, sec_kdcs, + host, NULL); + pprofile_update_relation(profile, sec_admin, + host, NULL); + pprofile_update_relation(profile, sec_master, + host, NULL); + + applied = TRUE; + + /* as above, setting 'new' flag to indicate + that the item does not exist in the profile + file. */ + d->realms[r].kdcs[k].flags |= K5_RKFLAG_NEW; + continue; + } + + if (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) { + if (d->realms[r].kdcs[k].master) + pprofile_add_relation(profile, sec_master, + host); + + pprofile_add_relation(profile, sec_kdcs, + host); + + if (d->realms[r].kdcs[k].admin) + pprofile_add_relation(profile, sec_admin, + host); + + d->realms[r].kdcs[k].flags &= ~(K5_RKFLAG_NEW | + K5_RKFLAG_MOD_ADMIN | + K5_RKFLAG_MOD_MASTER); + applied = TRUE; + continue; + } + + if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_MASTER) { + if (!d->realms[r].kdcs[k].master) { + pprofile_update_relation(profile, sec_master, + host, NULL); + } else { + pprofile_update_relation(profile, sec_master, + host, NULL); + pprofile_add_relation(profile, sec_master, + host); + } + + applied = TRUE; + d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_MASTER; + } + + if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_ADMIN) { + if (d->realms[r].kdcs[k].admin) { + pprofile_update_relation(profile, sec_admin, + host, NULL); + pprofile_add_relation(profile, sec_admin, + host); + } else { + pprofile_update_relation(profile, sec_admin, + host, NULL); + } + + applied = TRUE; + d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_ADMIN; + } + } + + for (m=0; m < d->realms[r].n_domain_maps; m++) { + + UnicodeStrToAnsi(host, sizeof(host), + d->realms[r].domain_maps[m].name); + + if ((d->realms[r].domain_maps[m].flags & + K5_DMFLAG_DELETED) && + + !(d->realms[r].domain_maps[m].flags & + K5_DMFLAG_NEW)) { + + pprofile_clear_relation(profile, sec_domain_map); + d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW; + applied = TRUE; + + } else if (!(d->realms[r].domain_maps[m].flags & + K5_DMFLAG_DELETED) && + + (d->realms[r].domain_maps[m].flags & + K5_DMFLAG_NEW)) { + + pprofile_add_relation(profile, sec_domain_map, + realm); + d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW; + applied = TRUE; + + } + } + + d->realms[r].flags &= ~K5_RDFLAG_MODIFED; + } + } + + rv = pprofile_flush(profile); + + pprofile_release(profile); + } + + if (rv) { + khui_alert * alert; + wchar_t title[KHUI_MAXCCH_TITLE]; + wchar_t fmsg[KHUI_MAXCCH_MESSAGE]; + wchar_t msg[KHUI_MAXCCH_MESSAGE]; + wchar_t sugg[KHUI_MAXCCH_SUGGESTION]; + + LoadString(hResModule, IDS_K5ERR_CANTWRITEPROFILE, + title, ARRAYLENGTH(title)); + if (rv) + LoadString(hResModule, IDS_K5ERR_PROFNOWRITE, + fmsg, ARRAYLENGTH(fmsg)); + + LoadString(hResModule, IDS_K5ERR_PROFSUGGEST, + sugg, ARRAYLENGTH(sugg)); + + StringCbPrintf(msg, sizeof(msg), fmsg, config_file); + + khui_alert_create_empty(&alert); + khui_alert_set_severity(alert, (rv)?KHERR_ERROR:KHERR_WARNING); + khui_alert_set_title(alert, title); + khui_alert_set_message(alert, msg); + khui_alert_set_suggestion(alert, sugg); + + khui_alert_show(alert); + } + + d->flags = 0; + + return applied; +} + +/* actual dialog stuff */ + +#define IDX_NORMAL 1 +#define IDX_MODIFIED 2 +#define IDX_NEW 3 +#define IDX_DELETED 4 + +static k5_config_data k5_config_dlg_data; +static khm_boolean k5_dlg_data_valid = FALSE; + +INT_PTR CALLBACK +k5_config_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + { + HWND hw; + khm_size i; + k5_config_data * d; + + wchar_t * t; + wchar_t importopts[256]; + WKSTA_INFO_100 * winfo100; + +#ifdef DEBUG + assert(!k5_dlg_data_valid); +#endif + + k5_init_config_data(&k5_config_dlg_data); + k5_read_config_data(&k5_config_dlg_data); + + k5_dlg_data_valid = TRUE; + + d = &k5_config_dlg_data; + + d->node_main = (khui_config_node) lParam; + + CheckDlgButton(hwnd, IDC_CFG_INCREALMS, + (d->inc_realms)? BST_CHECKED: BST_UNCHECKED); + + hw = GetDlgItem(hwnd, IDC_CFG_DEFREALM); +#ifdef DEBUG + assert(hw); +#endif + + SendMessage(hw, CB_RESETCONTENT, 0, 0); + + for (i=0; i < d->n_realms; i++) { + SendMessage(hw, CB_ADDSTRING, 0, + (LPARAM) d->realms[i].realm); + } + + SendMessage(hw, CB_SELECTSTRING, (WPARAM) -1, + (LPARAM) d->def_realm); + SetDlgItemText(hwnd, IDC_CFG_DEFREALM, d->def_realm); + SendDlgItemMessage(hwnd, IDC_CFG_DEFREALM, CB_LIMITTEXT, + ARRAYLENGTH(d->def_realm) - 1, 0); + + SetDlgItemText(hwnd, IDC_CFG_CFGFILE, d->config_file); + SendDlgItemMessage(hwnd, IDC_CFG_CFGFILE, EM_LIMITTEXT, + ARRAYLENGTH(d->config_file) - 1, 0); + + /* hostname/domain */ + if (NetWkstaGetInfo(NULL, 100, (LPBYTE *) &winfo100) == NERR_Success) { + SetDlgItemText(hwnd, IDC_CFG_HOSTNAME, winfo100->wki100_computername); + SetDlgItemText(hwnd, IDC_CFG_DOMAIN, winfo100->wki100_langroup); + NetApiBufferFree(winfo100); + } + + /* and the import ticket options */ + { + wchar_t csvstring[256]; + khm_size cb; + + csvstring[0] = L'\0'; + + LoadString(hResModule, IDS_K5CFG_IMPORT_OPTIONS, + csvstring, ARRAYLENGTH(csvstring)); + + cb = sizeof(importopts); + csv_to_multi_string(importopts, &cb, csvstring); + } + + hw = GetDlgItem(hwnd, IDC_CFG_IMPORT); +#ifdef DEBUG + assert(hw); +#endif + SendMessage(hw, CB_RESETCONTENT, 0, 0); + + for (t=importopts; + t && *t && *t != L' ' && + t < importopts + ARRAYLENGTH(importopts); + t = multi_string_next(t)) { + + SendMessage(hw, CB_ADDSTRING, 0, (LPARAM) t); + } + + SendMessage(hw, CB_SETCURSEL, 0, d->lsa_import); + t = importopts; + SendMessage(hw, CB_GETLBTEXT, d->lsa_import,(LPARAM) t); + SendMessage(hw, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) t); + } + break; + + case WM_COMMAND: + { + k5_config_data * d; + + d = &k5_config_dlg_data; + + if (d == NULL) + return FALSE; + + if (wParam == MAKEWPARAM(IDC_CFG_IMPORT, CBN_SELCHANGE)) { + int idx; + int modified = FALSE; + + idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_IMPORT, + CB_GETCURSEL, 0, 0); + if (idx != CB_ERR && idx != d->lsa_import) { + d->lsa_import = idx; + d->flags |= K5_CDFLAG_MOD_LSA_IMPORT; + modified = TRUE; + } + + khui_cfg_set_flags(d->node_main, + (modified)?KHUI_CNFLAG_MODIFIED:0, + KHUI_CNFLAG_MODIFIED); + return TRUE; + } + + if (wParam == MAKEWPARAM(IDC_CFG_INCREALMS, BN_CLICKED)) { + if (IsDlgButtonChecked(hwnd, IDC_CFG_INCREALMS) == + BST_CHECKED) { + d->inc_realms = TRUE; + } else { + d->inc_realms = FALSE; + } + d->flags |= K5_CDFLAG_MOD_INC_REALMS; + + khui_cfg_set_flags(d->node_main, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + return TRUE; + } + + if (wParam == MAKEWPARAM(IDC_CFG_DEFREALM, CBN_EDITCHANGE)) { + wchar_t defrealm[K5_MAXCCH_REALM]; + int t; + + t = GetDlgItemText(hwnd, IDC_CFG_DEFREALM, + defrealm, ARRAYLENGTH(defrealm)); + if (t == 0) { + /* we failed to get the default realm from the + control for some reason. */ + SetDlgItemText(hwnd, IDC_CFG_DEFREALM, L""); + StringCbCopy(d->def_realm, sizeof(d->def_realm), + L""); + } else { + StringCbCopy(d->def_realm, sizeof(d->def_realm), + defrealm); + } + + d->flags |= K5_CDFLAG_MOD_DEF_REALM; + + khui_cfg_set_flags(d->node_main, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + return TRUE; + } + + if (wParam == MAKEWPARAM(IDC_CFG_DEFREALM, CBN_SELCHANGE)) { + wchar_t defrealm[K5_MAXCCH_REALM]; + LRESULT cursel, lr; + + cursel = SendDlgItemMessage(hwnd, IDC_CFG_DEFREALM, CB_GETCURSEL, + 0, 0); + if (cursel == CB_ERR) + return TRUE; + + lr = SendDlgItemMessage(hwnd, IDC_CFG_DEFREALM, CB_GETLBTEXTLEN, + cursel, 0); +#ifdef DEBUG + assert(lr < ARRAYLENGTH(defrealm)); +#endif + if (lr >= ARRAYLENGTH(defrealm)) { + /* we really shouldn't have any string here that + exceeds that many characters. But if we do, we + ignore that since we don't consider it + valid. */ + return TRUE; + } + + lr = SendDlgItemMessage(hwnd, IDC_CFG_DEFREALM, CB_GETLBTEXT, + cursel, (LPARAM) defrealm); + if (lr == CB_ERR) { + /* somehow we failed to copy the value anyway + after all those checks. */ +#ifdef DEBUG + assert(FALSE); +#endif + return TRUE; + } + + StringCbCopy(d->def_realm, sizeof(d->def_realm), + defrealm); + + d->flags |= K5_CDFLAG_MOD_DEF_REALM; + + khui_cfg_set_flags(d->node_main, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + + return TRUE; + } + +#ifdef ALLOW_CHANGING_KRB5_CONFIG_FILE + if (wParam == MAKEWPARAM(IDC_CFG_CFGFILE, EN_CHANGE)) { + wchar_t cfgfile[MAX_PATH]; + int t; + + t = GetDlgItemText(hwnd, IDC_CFG_CFGFILE, + cfgfile, ARRAYLENGTH(cfgfile)); + + if (t == 0) { + StringCbCopy(d->config_file, sizeof(d->config_file), + L""); + } else { + StringCbCopy(d->config_file, sizeof(d->config_file), + cfgfile); + } + + d->flags |= K5_CDFLAG_MOD_CONF_FILE; + + khui_cfg_set_flags(d->node_main, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } +#endif + } + break; + + case KHUI_WM_CFG_NOTIFY: + { + k5_config_data * d; + + d = &k5_config_dlg_data; + + if (HIWORD(wParam) == WMCFG_APPLY) { + khm_int32 oflags; + int applied; + + oflags = d->flags; + applied = k5_write_config_data(d); + + if (d->flags != oflags) { + khui_cfg_set_flags(d->node_main, + (applied ? KHUI_CNFLAG_APPLIED : 0), + KHUI_CNFLAG_APPLIED | + KHUI_CNFLAG_MODIFIED); + } + return TRUE; + } + } + break; + + case WM_DESTROY: + { + k5_free_config_data(&k5_config_dlg_data); + k5_dlg_data_valid = FALSE; + } + break; + } + return FALSE; +} + +static HIMAGELIST +k5_get_state_image_list(void) { + HIMAGELIST hil; + HICON hicon; + + hil = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLOR | ILC_MASK, + 4, + 2); + + hicon = LoadImage(hResModule, + MAKEINTRESOURCE(IDI_NORMAL), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + + ImageList_AddIcon(hil, hicon); + + DestroyIcon(hicon); + + hicon = LoadImage(hResModule, + MAKEINTRESOURCE(IDI_MODIFIED), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + + ImageList_AddIcon(hil, hicon); + + DestroyIcon(hicon); + + hicon = LoadImage(hResModule, + MAKEINTRESOURCE(IDI_NEW), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + + ImageList_AddIcon(hil, hicon); + + DestroyIcon(hicon); + + hicon = LoadImage(hResModule, + MAKEINTRESOURCE(IDI_DELETED), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + + ImageList_AddIcon(hil, hicon); + + DestroyIcon(hicon); + + return hil; +} + +static void +k5_update_realms_display(HWND hw_list, k5_config_data * d) { + khm_size i; + LVITEM lvi; + wchar_t buf[64]; + + ListView_DeleteAllItems(hw_list); + + for (i=0; i < d->n_realms; i++) { + if ((d->realms[i].flags & K5_RDFLAG_DELETED) && + (d->realms[i].flags & K5_RDFLAG_NEW)) + continue; + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.pszText = d->realms[i].realm; + lvi.lParam = i; + + if (d->realms[i].flags & K5_RDFLAG_DELETED) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED); + } else if (d->realms[i].flags & K5_RDFLAG_NEW) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW); + } else if (d->realms[i].flags & K5_RDFLAG_MODIFED) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED); + } else { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL); + } + lvi.stateMask = LVIS_STATEIMAGEMASK; + + ListView_InsertItem(hw_list, &lvi); + } + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.pszText = buf; + lvi.lParam = (LPARAM) -1; + + LoadString(hResModule, IDS_CFG_RE_NEWREALM, + buf, ARRAYLENGTH(buf)); + + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW); + lvi.stateMask = LVIS_STATEIMAGEMASK; + + ListView_InsertItem(hw_list, &lvi); + + if (d->flags & K5_CDFLAG_MOD_REALMS) { + khui_cfg_set_flags(d->node_realm, KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } else { + khui_cfg_set_flags(d->node_realm, 0, + KHUI_CNFLAG_MODIFIED); + } +} + +#define K5_KDCSI_ADMIN 1 +#define K5_KDCSI_MASTER 2 + +static void +k5_update_kdcs_display(HWND hw_kdc, k5_config_data * d, khm_size idx_rlm) { + khm_size k; + LVITEM lvi; + int idx_item; + k5_realm_kdc * pkdc; + wchar_t wyes[8]; + wchar_t wno[8]; + wchar_t wbuf[64]; + + ListView_DeleteAllItems(hw_kdc); + + if (d == NULL) + return; + +#ifdef DEBUG + assert(idx_rlm < d->n_realms); +#endif + LoadString(hResModule, IDS_YES, wyes, ARRAYLENGTH(wyes)); + LoadString(hResModule, IDS_NO, wno, ARRAYLENGTH(wno)); + + for (k=0; k < d->realms[idx_rlm].n_kdcs; k++) { + if ((d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_DELETED) && + (d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_NEW)) + continue; + + pkdc = &(d->realms[idx_rlm].kdcs[k]); + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT; + lvi.iItem = K5_MAX_KDC; + lvi.iSubItem = 0; + lvi.lParam = k; + lvi.pszText = pkdc->name; + if (pkdc->flags & K5_RKFLAG_DELETED) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED); + } else if (pkdc->flags & K5_RKFLAG_NEW) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW); + } else if ((pkdc->flags & K5_RKFLAG_MOD_ADMIN) || + (pkdc->flags & K5_RKFLAG_MOD_MASTER)) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED); + } else { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL); + } + lvi.stateMask = LVIS_STATEIMAGEMASK; + + idx_item = ListView_InsertItem(hw_kdc, &lvi); + + lvi.mask = LVIF_TEXT; + lvi.iItem = idx_item; + lvi.iSubItem = K5_KDCSI_ADMIN; + if (pkdc->admin) + lvi.pszText = wyes; + else + lvi.pszText = wno; + ListView_SetItem(hw_kdc, &lvi); + + lvi.iSubItem = K5_KDCSI_MASTER; + if (pkdc->master) + lvi.pszText = wyes; + else + lvi.pszText = wno; + ListView_SetItem(hw_kdc, &lvi); + } + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.pszText = wbuf; + lvi.lParam = (LPARAM) -1; + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW); + lvi.stateMask = LVIS_STATEIMAGEMASK; + + LoadString(hResModule, IDS_CFG_RE_NEWSERVER, + wbuf, ARRAYLENGTH(wbuf)); + + ListView_InsertItem(hw_kdc, &lvi); +} + +static void +k5_update_dmap_display(HWND hw_dm, k5_config_data * d, khm_size idx_rlm) { + khm_size m; + LVITEM lvi; + k5_domain_map * map; + wchar_t wbuf[64]; + + ListView_DeleteAllItems(hw_dm); + + if (d == NULL) + return; + +#ifdef DEBUG + assert(idx_rlm < d->n_realms); +#endif + + for (m=0; m < d->realms[idx_rlm].n_domain_maps; m++) { + map = &(d->realms[idx_rlm].domain_maps[m]); + + if ((map->flags & K5_DMFLAG_NEW) && + (map->flags & K5_DMFLAG_DELETED)) + continue; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM; + lvi.pszText = map->name; + if (map->flags & K5_DMFLAG_DELETED) + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED); + else if (map->flags & K5_DMFLAG_NEW) + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW); + else + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL); + lvi.stateMask = LVIS_STATEIMAGEMASK; + lvi.lParam = m; + + lvi.iItem = K5_MAX_DOMAIN_MAPPINGS; + lvi.iSubItem = 0; + + ListView_InsertItem(hw_dm, &lvi); + } + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE; + lvi.pszText = wbuf; + lvi.lParam = (LPARAM) -1; + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW); + lvi.stateMask = LVIS_STATEIMAGEMASK; + lvi.iItem = 0; + lvi.iSubItem = 0; + + LoadString(hResModule, IDS_CFG_RE_NEWDMAP, + wbuf, ARRAYLENGTH(wbuf)); + + ListView_InsertItem(hw_dm, &lvi); +} + +#define CMD_BASE 3000 +#define CMD_NEW_REALM (CMD_BASE + 1) +#define CMD_DEL_REALM (CMD_BASE + 2) +#define CMD_NEW_SERVER (CMD_BASE + 3) +#define CMD_DEL_SERVER (CMD_BASE + 4) +#define CMD_MAKE_ADMIN (CMD_BASE + 5) +#define CMD_MAKE_MASTER (CMD_BASE + 6) +#define CMD_NEW_DMAP (CMD_BASE + 7) +#define CMD_DEL_DMAP (CMD_BASE + 8) + +struct k5_menu_def { + UINT string; + UINT id; + UINT type; + UINT state; +}; + +struct k5_menu_def k5_menu_realms[] = { + {IDS_CFG_RE_MNR, CMD_NEW_REALM, MFT_STRING, 0}, + {IDS_CFG_RE_MDR, CMD_DEL_REALM, MFT_STRING, 0} +}; + +struct k5_menu_def k5_menu_kdc[] = { + {IDS_CFG_RE_MNK, CMD_NEW_SERVER, MFT_STRING, 0}, + {IDS_CFG_RE_MDK, CMD_DEL_SERVER, MFT_STRING, 0}, + {IDS_CFG_RE_MAK, CMD_MAKE_ADMIN, MFT_STRING, 0}, + {IDS_CFG_RE_MMK, CMD_MAKE_MASTER, MFT_STRING, 0} +}; + +struct k5_menu_def k5_menu_dmap[] = { + {IDS_CFG_RE_MND, CMD_NEW_DMAP, MFT_STRING, 0}, + {IDS_CFG_RE_MDD, CMD_DEL_DMAP, MFT_STRING, 0} +}; + +HMENU +k5_menu_from_def(struct k5_menu_def * def, khm_size n) { + HMENU menu; + MENUITEMINFO mii; + khm_size i; + khm_size cch; + wchar_t buf[1024]; + + menu = CreatePopupMenu(); + + for (i=0; i < n; i++) { + ZeroMemory(&mii, sizeof(mii)); + + mii.cbSize = sizeof(mii); + + if (def[i].type == MFT_STRING) { + LoadString(hResModule, def[i].string, + buf, ARRAYLENGTH(buf)); + StringCchLength(buf, ARRAYLENGTH(buf), &cch); + + mii.fMask = MIIM_STRING | MIIM_ID; + mii.fType = MFT_STRING; + + mii.fState = def[i].state; + mii.wID = def[i].id; + mii.cch = (UINT) cch; + mii.dwTypeData = buf; + + InsertMenuItem(menu, (UINT) i, TRUE, &mii); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } + + return menu; +} + +void +k5_delete_realms(HWND hwnd, k5_config_data * d) { + LVITEM lvi; + int idx; + HWND hw_rlm; + BOOL modified = FALSE; + khm_size r; + + hw_rlm = GetDlgItem(hwnd, IDC_CFG_REALMS); + + idx = -1; + while((idx = ListView_GetNextItem(hw_rlm, idx, + LVNI_SELECTED)) + != -1) { + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = idx; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw_rlm, &lvi); + + if (lvi.lParam != -1 && + (r = lvi.lParam) < d->n_realms) { + d->realms[r].flags ^= K5_RDFLAG_DELETED; + modified = TRUE; + } + } + + if (modified) { + d->flags |= K5_CDFLAG_MOD_REALMS; + + k5_purge_config_data(d, TRUE, TRUE, TRUE); + k5_update_realms_display(hw_rlm, d); + k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0); + k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0); + } +} + +void +k5_delete_servers(HWND hwnd, k5_config_data * d) { + HWND hw_kdc; + LVITEM lvi; + khm_size r; + khm_size k; + int idx; + BOOL modified = FALSE; + + hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC); + r = d->c_realm; + + idx = -1; + while((idx = ListView_GetNextItem(hw_kdc, idx, + LVNI_SELECTED)) + != -1) { + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = idx; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw_kdc, &lvi); + + if (lvi.lParam != -1 && + (k = lvi.lParam) < d->n_realms) { + d->realms[r].kdcs[k].flags ^= K5_RKFLAG_DELETED; + modified = TRUE; + } + } + + if (modified) { + d->flags |= K5_CDFLAG_MOD_REALMS; + d->realms[r].flags |= K5_RDFLAG_MODIFED; + + k5_purge_config_data(d, TRUE, TRUE, TRUE); + k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d); + k5_update_kdcs_display(hw_kdc, d, r); + } +} + +void +k5_delete_dmap(HWND hwnd, k5_config_data * d) { + HWND hw_dmp; + LVITEM lvi; + khm_size r; + khm_size m; + int idx; + BOOL modified = FALSE; + + hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP); + r = d->c_realm; + + idx = -1; + while((idx = ListView_GetNextItem(hw_dmp, idx, + LVNI_SELECTED)) + != -1) { + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = idx; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw_dmp, &lvi); + + if (lvi.lParam != -1 && + (m = lvi.lParam) < d->n_realms) { + d->realms[r].domain_maps[m].flags ^= K5_DMFLAG_DELETED; + modified = TRUE; + } + } + + if (modified) { + d->flags |= K5_CDFLAG_MOD_REALMS; + k5_purge_config_data(d, FALSE, FALSE, TRUE); + + if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) { + d->realms[r].flags |= K5_RDFLAG_MODIFED; + + k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d); + } + + k5_update_dmap_display(hw_dmp, d, r); + } +} + +INT_PTR CALLBACK +k5_realms_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + k5_config_data * d; + + d = &k5_config_dlg_data; + + switch(uMsg) { + case WM_INITDIALOG: + { + LVCOLUMN lvc; + HWND hw; + RECT r; + wchar_t buf[256]; + + assert(k5_dlg_data_valid); + + d->node_realm = (khui_config_node) lParam; + + /* set up columns for the Realms list */ + hw = GetDlgItem(hwnd, IDC_CFG_REALMS); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + r.right -= 5; /* shave a few pixels off the width */ + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + lvc.pszText = buf; + lvc.cx = (r.right - r.left); + LoadString(hResModule, IDS_CFG_RE_REALMS, + buf, ARRAYLENGTH(buf)); + + ListView_InsertColumn(hw, 0, &lvc); + + ListView_SetImageList(hw, + k5_get_state_image_list(), + LVSIL_STATE); + + k5_update_realms_display(hw, d); + + /* set up columns for the servers list */ + hw = GetDlgItem(hwnd, IDC_CFG_KDC); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + r.right -= 5; + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + lvc.pszText = buf; + lvc.cx = (r.right - r.left) * 2 / 4; + LoadString(hResModule, IDS_CFG_RE_HEAD_SVR, + buf, ARRAYLENGTH(buf)); + + ListView_InsertColumn(hw, 0, &lvc); + + lvc.cx = (r.right - r.left) * 1 / 4; + LoadString(hResModule, IDS_CFG_RE_HEAD_ADMIN, + buf, ARRAYLENGTH(buf)); + ListView_InsertColumn(hw, 1, &lvc); + + LoadString(hResModule, IDS_CFG_RE_HEAD_MASTER, + buf, ARRAYLENGTH(buf)); + ListView_InsertColumn(hw, 2, &lvc); + + ListView_SetImageList(hw, + k5_get_state_image_list(), + LVSIL_STATE); + + /* set up columns for the domain/host mapping list */ + hw = GetDlgItem(hwnd, IDC_CFG_DMAP); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + r.right -= 5; + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + lvc.pszText = buf; + lvc.cx = (r.right - r.left); + LoadString(hResModule, IDS_CFG_RE_HEAD_DOMAIN, + buf, ARRAYLENGTH(buf)); + + ListView_InsertColumn(hw, 0, &lvc); + + + ListView_SetImageList(hw, + k5_get_state_image_list(), + LVSIL_STATE); + + /* Now set up the context menus */ + d->hm_realms_ctx = k5_menu_from_def(k5_menu_realms, ARRAYLENGTH(k5_menu_realms)); + d->hm_kdc_ctx = k5_menu_from_def(k5_menu_kdc, ARRAYLENGTH(k5_menu_kdc)); + d->hm_dmap_ctx = k5_menu_from_def(k5_menu_dmap, ARRAYLENGTH(k5_menu_dmap)); + } + break; + + case WM_CONTEXTMENU: + { + UINT id; + HMENU hm = NULL; + int x,y; + + id = GetDlgCtrlID((HWND) wParam); + + if (id == IDC_CFG_REALMS) { + HWND hw_realms; + int n; + MENUITEMINFO mii; + + hm = d->hm_realms_ctx; + + hw_realms = GetDlgItem(hwnd, IDC_CFG_REALMS); +#ifdef DEBUG + assert(hw_realms); +#endif + n = ListView_GetSelectedCount(hw_realms); + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + + if (n == 0) { + mii.fMask = MIIM_STATE; + mii.fState = MFS_DISABLED; + + SetMenuItemInfo(hm, CMD_DEL_REALM, FALSE, &mii); + } else { + + mii.fMask = MIIM_STATE; + mii.fState = MFS_ENABLED; + + SetMenuItemInfo(hm, CMD_DEL_REALM, FALSE, &mii); + } + + } else if (id == IDC_CFG_KDC) { + HWND hw_kdc; + int n; + MENUITEMINFO mii; + + hm = d->hm_kdc_ctx; + + hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC); +#ifdef DEBUG + assert(hw_kdc); +#endif + n = ListView_GetSelectedCount(hw_kdc); + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + + if (n == 1) { + mii.fMask = MIIM_STATE; + mii.fState = MFS_ENABLED; + + SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii); + SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii); + SetMenuItemInfo(hm, CMD_MAKE_MASTER, FALSE, &mii); + } else if (n == 0) { + + mii.fMask = MIIM_STATE; + mii.fState = MFS_DISABLED; + + SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii); + SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii); + SetMenuItemInfo(hm, CMD_MAKE_MASTER,FALSE, &mii); + } else { + + mii.fMask = MIIM_STATE; + mii.fState = MFS_ENABLED; + + SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii); + + mii.fState = MFS_DISABLED; + + SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii); + SetMenuItemInfo(hm, CMD_MAKE_MASTER,FALSE, &mii); + } + + } else if (id == IDC_CFG_DMAP) { + HWND hw_dmap; + MENUITEMINFO mii; + int n; + + hm = d->hm_dmap_ctx; + + hw_dmap = GetDlgItem(hwnd, IDC_CFG_DMAP); +#ifdef DEBUG + assert(hw_dmap); +#endif + + n = ListView_GetSelectedCount(hw_dmap); + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + + if (n == 0) { + mii.fMask = MIIM_STATE; + mii.fState = MFS_DISABLED; + + SetMenuItemInfo(hm, CMD_DEL_DMAP, FALSE, &mii); + } else { + mii.fMask = MIIM_STATE; + mii.fState = MFS_ENABLED; + + SetMenuItemInfo(hm, CMD_DEL_DMAP, FALSE, &mii); + } + } + + if (hm) { + if (LOWORD(lParam) == 0xffff) { + HWND hw; + RECT r; + + hw = GetDlgItem(hwnd, id); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + x = r.left; + y = r.top; + } else { + x = LOWORD(lParam); + y = HIWORD(lParam); + } + + TrackPopupMenu(hm, + TPM_LEFTALIGN | TPM_TOPALIGN, + x, y, + 0, hwnd, NULL); + } + + return TRUE; + } + break; + + case WM_NOTIFY: + { + LPNMHDR pnmh; + HWND hw_rlm = NULL; + HWND hw_kdc = NULL; + HWND hw_dmp = NULL; + int i; + + pnmh = (LPNMHDR) lParam; + + /* catchalls for all three list views */ + switch (pnmh->code) { + case NM_DBLCLK: + { + HWND hw_ctl; + LVITEM lvi; + LVHITTESTINFO hti; + LPNMITEMACTIVATE pnmi; + + if (pnmh->idFrom != IDC_CFG_REALMS && + pnmh->idFrom != IDC_CFG_KDC && + pnmh->idFrom != IDC_CFG_DMAP) + break; + + /* if the user double clicks on the 'new + [something]' item, we start editing it. */ + hw_ctl = pnmh->hwndFrom; + pnmi = (LPNMITEMACTIVATE) lParam; + + ZeroMemory(&hti, sizeof(hti)); + hti.pt = pnmi->ptAction; + + ListView_SubItemHitTest(hw_ctl, &hti); + if (hti.flags & LVHT_ONITEM) { + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_PARAM; + lvi.iItem = hti.iItem; + + ListView_GetItem(hw_ctl, &lvi); + + if (lvi.lParam == -1) + ListView_EditLabel(hw_ctl, hti.iItem); + } + + return TRUE; + } + break; + } + + if (pnmh->idFrom == IDC_CFG_REALMS) { + + hw_rlm = pnmh->hwndFrom; + + switch(pnmh->code) { + case LVN_ITEMCHANGED: + i = ListView_GetSelectedCount(hw_rlm); + hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC); + hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP); + + d->c_realm = (khm_size) -1; + + if (i == 1) { + LVITEM lvi; + wchar_t fmt[256]; + wchar_t buf[K5_MAXCCH_REALM + 256]; + + i = ListView_GetNextItem(hw_rlm, -1, + LVNI_SELECTED); + if (i == -1) + goto _no_selection; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.iItem = i; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw_rlm, &lvi); + + if (lvi.lParam == -1) + goto _no_selection; + + d->c_realm = lvi.lParam; + + k5_update_kdcs_display(hw_kdc, d, lvi.lParam); + k5_update_dmap_display(hw_dmp, d, lvi.lParam); + + LoadString(hResModule, IDS_CFG_RE_KDCS_R, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + d->realms[d->c_realm].realm); + + SetDlgItemText(hwnd, IDC_CFG_SERVERSGRP, buf); + + LoadString(hResModule, IDS_CFG_RE_DMAPS_R, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + d->realms[d->c_realm].realm); + + SetDlgItemText(hwnd, IDC_CFG_DOMAINGRP, buf); + return TRUE; + } + + _no_selection: + { + wchar_t buf[256]; + + k5_update_kdcs_display(hw_kdc, NULL, 0); + k5_update_dmap_display(hw_dmp, NULL, 0); + + LoadString(hResModule, IDS_CFG_RE_KDCS, + buf, ARRAYLENGTH(buf)); + SetDlgItemText(hwnd, IDC_CFG_SERVERSGRP, buf); + + LoadString(hResModule, IDS_CFG_RE_DMAPS, + buf, ARRAYLENGTH(buf)); + SetDlgItemText(hwnd, IDC_CFG_DOMAINGRP, buf); + } + break; + + case LVN_BEGINLABELEDIT: + { + NMLVDISPINFO * pdisp; + LVITEM lvi; + + pdisp = (NMLVDISPINFO *) lParam; + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = pdisp->item.iItem; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw_rlm, &lvi); + + if (pdisp->item.iItem == -1 || + lvi.lParam != -1) { + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE); + } else { + /* allow editing */ + HWND hw_edit; + + hw_edit = ListView_GetEditControl(hw_rlm); + if (hw_edit != NULL) { + SendMessage(hw_edit, + EM_SETLIMITTEXT, + K5_MAXCCH_REALM - 1, + 0); + } + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); + } + + return TRUE; + } + break; + + case LVN_ENDLABELEDIT: + { + NMLVDISPINFO * pdisp; + khm_size n; + + pdisp = (NMLVDISPINFO *) lParam; + + if (pdisp->item.pszText && pdisp->item.pszText[0]) { + khm_size i; + + /* first find out whether this is actually + a new realm */ + + for (i=0; i < d->n_realms; i++) { + if ((d->realms[i].flags & K5_RDFLAG_NEW) && + (d->realms[i].flags & K5_RDFLAG_DELETED)) + continue; + + if (!_wcsicmp(d->realms[i].realm, pdisp->item.pszText)) + break; + } + + if (i < d->n_realms) { + khui_alert * alert = NULL; + wchar_t buf[KHUI_MAXCCH_MESSAGE]; + wchar_t fmt[KHUI_MAXCCH_MESSAGE]; + + khui_alert_create_empty(&alert); + + LoadString(hResModule, IDS_CFG_RE_ARNUT, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + pdisp->item.pszText); + khui_alert_set_title(alert, buf); + + LoadString(hResModule, IDS_CFG_RE_ARNUM, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + pdisp->item.pszText); + khui_alert_set_message(alert, buf); + + khui_alert_add_command(alert, KHUI_PACTION_CLOSE); + khui_alert_set_severity(alert, KHERR_INFO); + + khui_alert_show_modal(alert); + khui_alert_release(alert); + + return TRUE; + } + + n = d->n_realms; + k5_assert_n_realms(d, n+1); + StringCbCopy(d->realms[n].realm, + sizeof(d->realms[n].realm), + pdisp->item.pszText); + d->realms[n].flags = K5_RDFLAG_NEW; + d->n_realms++; + + d->flags |= K5_CDFLAG_MOD_REALMS; + + k5_update_realms_display(hw_rlm, d); + } + + return TRUE; + } + break; + + case LVN_KEYDOWN: + { + NMLVKEYDOWN * pnmk; + + pnmk = (NMLVKEYDOWN *) lParam; + + if (pnmk->wVKey == VK_DELETE) { + k5_delete_realms(hwnd, d); + return TRUE; + } + } + break; + } + } else if (pnmh->idFrom == IDC_CFG_KDC) { + hw_kdc = pnmh->hwndFrom; + + switch (pnmh->code) { + case LVN_BEGINLABELEDIT: + { + NMLVDISPINFO * pdisp; + LVITEM lvi; + + pdisp = (NMLVDISPINFO *) lParam; + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = pdisp->item.iItem; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw_kdc, &lvi); + + /* Only allow editing if the user is trying to + edit the <New server> entry. */ + if (pdisp->item.iItem == -1 || + lvi.lParam != -1) { + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE); + } else { + HWND hw_edit; + + hw_edit = ListView_GetEditControl(hw_kdc); + if (hw_edit != NULL) { + SendMessage(hw_edit, + EM_SETLIMITTEXT, + K5_MAXCCH_HOST - 1, + 0); + } + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); + } + return TRUE; + } + break; + + case LVN_ENDLABELEDIT: + { + NMLVDISPINFO * pdisp; + khm_size r; + khm_size k; + + r = d->c_realm; + + pdisp = (NMLVDISPINFO *) lParam; + + if (pdisp->item.pszText && pdisp->item.pszText[0]) { + + /* first of all, check if we already have + a KDC by this name... */ + for (k=0; k < d->realms[r].n_kdcs; k++) { + if ((d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) && + (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) + continue; + + if (!_wcsicmp(d->realms[r].kdcs[k].name, + pdisp->item.pszText)) + break; + } + + if (k < d->realms[r].n_kdcs) { + khui_alert * alert = NULL; + wchar_t buf[K5_MAXCCH_HOST + 256]; + wchar_t fmt[256]; + + khui_alert_create_empty(&alert); + + LoadString(hResModule, IDS_CFG_RE_ASNUT, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + pdisp->item.pszText, + d->realms[r].realm); + khui_alert_set_title(alert, buf); + + LoadString(hResModule, IDS_CFG_RE_ASNUM, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + pdisp->item.pszText, + d->realms[r].realm); + khui_alert_set_message(alert, buf); + + khui_alert_set_severity(alert, KHERR_INFO); + khui_alert_show_modal(alert); + + khui_alert_release(alert); + + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); + return TRUE; + } + + if (k >= K5_MAX_KDC) { + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); + /* TODO: show a message box saying + there are too many KDC's + already. */ + return TRUE; + } + + StringCbCopy(d->realms[r].kdcs[k].name, + sizeof(d->realms[0].kdcs[0].name), + pdisp->item.pszText); + d->realms[r].kdcs[k].flags = K5_RKFLAG_NEW; + d->realms[r].n_kdcs++; + + k5_update_kdcs_display(hw_kdc, d, d->c_realm); + + if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) { + d->flags |= K5_CDFLAG_MOD_REALMS; + d->realms[r].flags |= K5_RDFLAG_MODIFED; + k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d); + } + } + return TRUE; + } + break; + + case LVN_KEYDOWN: + { + NMLVKEYDOWN * pnmk; + + pnmk = (NMLVKEYDOWN *) lParam; + + if (pnmk->wVKey == VK_DELETE) { + k5_delete_servers(hwnd, d); + } + return TRUE; + } + break; + + case NM_CLICK: + { + LPNMITEMACTIVATE lpnmi; + LVHITTESTINFO hti; + LVITEM lvi; + khm_size r; + khm_size k; + + r = d->c_realm; + + lpnmi = (LPNMITEMACTIVATE) lParam; + + ZeroMemory(&hti, sizeof(hti)); + hti.pt = lpnmi->ptAction; + ListView_SubItemHitTest(hw_kdc, &hti); + + if (hti.iSubItem != 0) { + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_PARAM; + lvi.iItem = hti.iItem; + ListView_GetItem(hw_kdc, &lvi); + + if (lvi.lParam < 0 || lvi.lParam >= (int) d->realms[r].n_kdcs) + return TRUE; + + k = lvi.lParam; + + if (hti.iSubItem == K5_KDCSI_ADMIN) { + d->realms[r].kdcs[k].admin = !d->realms[r].kdcs[k].admin; + d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_ADMIN; + } else if (hti.iSubItem == K5_KDCSI_MASTER) { + if (d->realms[r].kdcs[k].master) { + d->realms[r].kdcs[k].master = FALSE; + d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER; + } else { + khm_size i; + + for (i=0; i < d->realms[r].n_kdcs; i++) { + if ((d->realms[r].kdcs[i].flags & K5_RKFLAG_DELETED) && + (d->realms[r].kdcs[i].flags & K5_RKFLAG_NEW)) + continue; + if (d->realms[r].kdcs[i].master) { + d->realms[r].kdcs[i].master = FALSE; + d->realms[r].kdcs[i].flags |= K5_RKFLAG_MOD_MASTER; + } + } + + d->realms[r].kdcs[k].master = TRUE; + d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER; + } + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) { + d->realms[r].flags |= K5_RDFLAG_MODIFED; + d->flags |= K5_CDFLAG_MOD_REALMS; + k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d); + } + + k5_update_kdcs_display(hw_kdc, d, r); + } + } + break; + } + } else if (pnmh->idFrom == IDC_CFG_DMAP) { + hw_dmp = pnmh->hwndFrom; + + switch (pnmh->code) { + case LVN_BEGINLABELEDIT: + { + NMLVDISPINFO * pdisp; + LVITEM lvi; + + pdisp = (NMLVDISPINFO *) lParam; + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = pdisp->item.iItem; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw_dmp, &lvi); + + /* Only allow editing if the user is trying to + edit the <New domain mapping> entry. */ + if (pdisp->item.iItem == -1 || + lvi.lParam != -1) { + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE); + } else { + HWND hw_edit; + + hw_edit = ListView_GetEditControl(hw_dmp); + if (hw_edit != NULL) { + SendMessage(hw_edit, + EM_SETLIMITTEXT, + K5_MAXCCH_HOST - 1, + 0); + } + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); + } + return TRUE; + } + break; + + case LVN_ENDLABELEDIT: + { + NMLVDISPINFO * pdisp; + khm_size r; + khm_size m; + + r = d->c_realm; + + pdisp = (NMLVDISPINFO *) lParam; + + if (pdisp->item.pszText && pdisp->item.pszText[0]) { + + /* first check if this is unique */ + for (m=0; m < d->realms[r].n_domain_maps; m++) { + if ((d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) && + (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED)) + continue; + + if (!_wcsicmp(d->realms[r].domain_maps[m].name, + pdisp->item.pszText)) + break; + } + + if (m < d->realms[r].n_domain_maps) { + khui_alert * alert; + wchar_t buf[K5_MAXCCH_HOST + 256]; + wchar_t fmt[256]; + + khui_alert_create_empty(&alert); + + LoadString(hResModule, IDS_CFG_RE_DMNUT, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + pdisp->item.pszText, + d->realms[r].realm); + khui_alert_set_title(alert, buf); + + LoadString(hResModule, IDS_CFG_RE_DMNUM, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + pdisp->item.pszText, + d->realms[r].realm); + khui_alert_set_message(alert, buf); + + khui_alert_set_severity(alert, KHERR_INFO); + khui_alert_show_modal(alert); + + khui_alert_release(alert); + + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); + return TRUE; + } + + if (m >= K5_MAX_DOMAIN_MAPPINGS) { + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); + /* TODO: show a message box saying + there are too many domain mappings + already. */ + return TRUE; + } + + StringCbCopy(d->realms[r].domain_maps[m].name, + sizeof(d->realms[0].domain_maps[0].name), + pdisp->item.pszText); + d->realms[r].domain_maps[m].flags = K5_DMFLAG_NEW; + d->realms[r].n_domain_maps++; + + k5_update_dmap_display(hw_dmp, d, d->c_realm); + + if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) { + d->flags |= K5_CDFLAG_MOD_REALMS; + d->realms[r].flags |= K5_RDFLAG_MODIFED; + k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d); + } + } + return TRUE; + } + break; + + case LVN_KEYDOWN: + { + NMLVKEYDOWN * pnmk; + + pnmk = (NMLVKEYDOWN *) lParam; + + if (pnmk->wVKey == VK_DELETE) { + k5_delete_dmap(hwnd, d); + return TRUE; + } + } + break; + } + } /* end of handling DMAP notifications */ + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case CMD_NEW_REALM: + { + ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_REALMS), 0); + + return TRUE; + } + break; + + case CMD_DEL_REALM: + { + k5_delete_realms(hwnd, d); + + return TRUE; + } + break; + + case CMD_NEW_SERVER: + { + ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_KDC), 0); + + return TRUE; + } + break; + + case CMD_DEL_SERVER: + { + k5_delete_servers(hwnd, d); + + return TRUE; + } + break; + + case CMD_MAKE_ADMIN: + { + HWND hw_kdc; + int idx; + khm_size r; + khm_size k; + BOOL modified = FALSE; + + r = d->c_realm; + + hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC); + + if (ListView_GetSelectedCount(hw_kdc) != 1) + return TRUE; + + idx = -1; + while ((idx = ListView_GetNextItem(hw_kdc, idx, + LVNI_SELECTED)) != -1) { + LVITEM lvi; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_PARAM; + lvi.iItem = idx; + ListView_GetItem(hw_kdc, &lvi); + + k = lvi.lParam; + + if (lvi.lParam >= 0 && lvi.lParam < (int) d->realms[r].n_kdcs) { + d->realms[r].kdcs[k].admin = !d->realms[r].kdcs[k].admin; + d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_ADMIN; + modified = TRUE; + + break; + } + } + + if (modified) { + if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) { + d->flags |= K5_CDFLAG_MOD_REALMS; + d->realms[r].flags |= K5_RDFLAG_MODIFED; + k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d); + } + } + + k5_update_kdcs_display(hw_kdc, d, r); + + return TRUE; + } + break; + + case CMD_MAKE_MASTER: + { + HWND hw_kdc; + int idx; + khm_size r; + khm_size k; + BOOL modified = FALSE; + + r = d->c_realm; + + hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC); + + if (ListView_GetSelectedCount(hw_kdc) != 1) + return TRUE; + + idx = -1; + while ((idx = ListView_GetNextItem(hw_kdc, idx, + LVNI_SELECTED)) != -1) { + LVITEM lvi; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_PARAM; + lvi.iItem = idx; + ListView_GetItem(hw_kdc, &lvi); + + k = lvi.lParam; + + if (lvi.lParam >= 0 && lvi.lParam < (int) d->realms[r].n_kdcs) { + if (d->realms[r].kdcs[k].master) { + d->realms[r].kdcs[k].master = FALSE; + } else { + khm_size i; + + for (i=0; i < d->realms[r].n_kdcs; i++) { + if ((d->realms[r].kdcs[i].flags & K5_RKFLAG_NEW) && + (d->realms[r].kdcs[i].flags & K5_RKFLAG_DELETED)) + continue; + + if (d->realms[r].kdcs[i].master) { + d->realms[r].kdcs[i].master = FALSE; + d->realms[r].kdcs[i].flags |= K5_RKFLAG_MOD_MASTER; + } + } + + d->realms[r].kdcs[k].master = TRUE; + } + d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER; + modified = TRUE; + + break; + } + } + + if (modified) { + if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) { + d->flags |= K5_CDFLAG_MOD_REALMS; + d->realms[r].flags |= K5_RDFLAG_MODIFED; + k5_update_realms_display(hwnd, d); + } + } + + k5_update_kdcs_display(hw_kdc, d, r); + + return TRUE; + } + break; + + case CMD_NEW_DMAP: + { + ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_DMAP), 0); + + return TRUE; + } + break; + + case CMD_DEL_DMAP: + { + k5_delete_dmap(hwnd, d); + + return TRUE; + } + break; + } + break; + + case WM_DESTROY: + if (d->hm_realms_ctx) + DestroyMenu(d->hm_realms_ctx); + if (d->hm_kdc_ctx) + DestroyMenu(d->hm_kdc_ctx); + if (d->hm_dmap_ctx) + DestroyMenu(d->hm_dmap_ctx); + + d->hm_realms_ctx = NULL; + d->hm_kdc_ctx = NULL; + d->hm_dmap_ctx = NULL; + break; + + case KHUI_WM_CFG_NOTIFY: + /* the realms dialog receives this notification after the top + level krb5 configuration panel has received it. */ + if (HIWORD(wParam) == WMCFG_APPLY) { + int applied; + + applied = k5_write_config_data(d); + k5_purge_config_data(d, TRUE, TRUE, TRUE); + k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d); + if (d->c_realm != -1) { + k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), d, d->c_realm); + k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), d, d->c_realm); + } else { + k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0); + k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0); + } + khui_cfg_set_flags(d->node_realm, + (applied ? KHUI_CNFLAG_APPLIED : 0), + KHUI_CNFLAG_APPLIED); + + } + break; + } + return FALSE; +} + +void +k5_register_config_panels(void) { + khui_config_node node; + khui_config_node_reg reg; + wchar_t wshort[KHUI_MAXCCH_SHORT_DESC]; + wchar_t wlong[KHUI_MAXCCH_LONG_DESC]; + + ZeroMemory(&reg, sizeof(reg)); + + LoadString(hResModule, IDS_K5CFG_SHORT_DESC, + wshort, ARRAYLENGTH(wshort)); + LoadString(hResModule, IDS_K5CFG_LONG_DESC, + wlong, ARRAYLENGTH(wlong)); + + reg.name = L"Kerberos5"; + reg.short_desc = wshort; + reg.long_desc = wlong; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG); + reg.dlg_proc = k5_config_dlgproc; + reg.flags = 0; + + khui_cfg_register(NULL, &reg); + + if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node))) { + node = NULL; +#ifdef DEBUG + assert(FALSE); +#endif + } + + ZeroMemory(&reg, sizeof(reg)); + + LoadString(hResModule, IDS_K5RLM_SHORT_DESC, + wshort, ARRAYLENGTH(wshort)); + LoadString(hResModule, IDS_K5RLM_LONG_DESC, + wlong, ARRAYLENGTH(wlong)); + + reg.name = L"KerberosRealms"; + reg.short_desc = wshort; + reg.long_desc = wlong; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_REALMS); + reg.dlg_proc = k5_realms_dlgproc; + reg.flags = 0; + + khui_cfg_register(node, &reg); + + ZeroMemory(&reg, sizeof(reg)); + + LoadString(hResModule, IDS_K5CCC_SHORT_DESC, + wshort, ARRAYLENGTH(wshort)); + LoadString(hResModule, IDS_K5CCC_LONG_DESC, + wlong, ARRAYLENGTH(wlong)); + + reg.name = L"KerberosCCaches"; + reg.short_desc = wshort; + reg.long_desc = wlong; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_CACHES); + reg.dlg_proc = k5_ccconfig_dlgproc; + reg.flags = 0; + + khui_cfg_register(node, &reg); + + khui_cfg_release(node); + + if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node))) { + node = NULL; +#ifdef DEBUG + assert(FALSE); +#endif + } + + ZeroMemory(&reg, sizeof(reg)); + + LoadString(hResModule, IDS_K5CFG_IDS_SHORT_DESC, + wshort, ARRAYLENGTH(wshort)); + LoadString(hResModule, IDS_K5CFG_IDS_LONG_DESC, + wlong, ARRAYLENGTH(wlong)); + + reg.name = L"KerberosIdentities"; + reg.short_desc = wshort; + reg.long_desc = wlong; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB); + reg.dlg_proc = k5_ids_tab_dlgproc; + reg.flags = KHUI_CNFLAG_SUBPANEL; + + khui_cfg_register(node, &reg); + + ZeroMemory(&reg, sizeof(reg)); + + LoadString(hResModule, IDS_K5CFG_ID_SHORT_DESC, + wshort, ARRAYLENGTH(wshort)); + LoadString(hResModule, IDS_K5CFG_ID_LONG_DESC, + wlong, ARRAYLENGTH(wlong)); + + reg.name = L"KerberosIdentitiesPlural"; + reg.short_desc = wshort; + reg.long_desc = wlong; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB); + reg.dlg_proc = k5_id_tab_dlgproc; + reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL; + + khui_cfg_register(node, &reg); + + khui_cfg_release(node); +} + +void +k5_unregister_config_panels(void) { + khui_config_node node_main; + khui_config_node node_realms; + khui_config_node node_ids; + khui_config_node node_tab; + khui_config_node node_ccaches; + + if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node_main))) { + node_main = NULL; +#ifdef DEBUG + assert(FALSE); +#endif + } + + if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosRealms", + &node_realms))) { + khui_cfg_remove(node_realms); + khui_cfg_release(node_realms); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosCCaches", + &node_ccaches))) { + khui_cfg_remove(node_ccaches); + khui_cfg_release(node_ccaches); + } +#ifdef DEBUG + else + assert(FALSE); +#endif + + if (node_main) { + khui_cfg_remove(node_main); + khui_cfg_release(node_main); + } + + if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node_ids))) { + node_ids = NULL; +#ifdef DEBUG + assert(FALSE); +#endif + } + + if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentities", &node_tab))) { + khui_cfg_remove(node_tab); + khui_cfg_release(node_tab); + } + if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentitiesPlural", &node_tab))) { + khui_cfg_remove(node_tab); + khui_cfg_release(node_tab); + } + + if (node_ids) + khui_cfg_release(node_ids); +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5configid.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configid.c new file mode 100644 index 000000000..2f3fe62c8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configid.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<krb5.h> +#include<assert.h> +#include<lm.h> +#include<commctrl.h> +#include<shlwapi.h> + +#include<strsafe.h> + +typedef struct tag_k5_id_dlg_data { + khui_config_init_data cfg; + + khm_handle ident; + + khui_tracker tc_life; + khui_tracker tc_renew; + + wchar_t ccache[KRB5_MAXCCH_CCNAME]; + + khm_boolean renewable; + khm_boolean forwardable; + khm_boolean proxiable; + khm_boolean addressless; + + DWORD public_ip; + + time_t life; + time_t renew_life; +} k5_id_dlg_data; + +static void +k5_id_read_params(k5_id_dlg_data * d) { + + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_int32 rv; + khm_int32 t; + khm_handle csp_ident = NULL; + + cb = sizeof(idname); + rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + + rv = kcdb_identity_create(idname, 0, &d->ident); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + + khm_krb5_get_identity_config(d->ident, 0, &csp_ident); + + rv = khc_read_int32(csp_ident, L"DefaultLifetime", &t); + if (KHM_SUCCEEDED(rv)) + d->life = t; + else + d->life = 36000; + + rv = khc_read_int32(csp_ident, L"DefaultRenewLifetime", &t); + if (KHM_SUCCEEDED(rv)) + d->renew_life = t; + else + d->renew_life = 604800; + + rv = khc_read_int32(csp_ident, L"Renewable", &t); + if (KHM_SUCCEEDED(rv)) + d->renewable = !!t; + else + d->renewable = TRUE; + + rv = khc_read_int32(csp_ident, L"Forwardable", &t); + if (KHM_SUCCEEDED(rv)) + d->forwardable = !!t; + else + d->forwardable = FALSE; + + rv = khc_read_int32(csp_ident, L"Proxiable", &t); + if (KHM_SUCCEEDED(rv)) + d->proxiable = !!t; + else + d->proxiable = FALSE; + + rv = khc_read_int32(csp_ident, L"Addressless", &t); + if (KHM_SUCCEEDED(rv)) + d->addressless = !!t; + else + d->addressless = TRUE; + + rv = khc_read_int32(csp_ident, L"PublicIP", &t); + if (KHM_SUCCEEDED(rv)) + d->public_ip = (khm_ui_4) t; + else + d->public_ip = 0; + + cb = sizeof(d->ccache); + rv = khm_krb5_get_identity_default_ccache(d->ident, d->ccache, &cb); + +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + + khui_tracker_initialize(&d->tc_life); + d->tc_life.current = d->life; + d->tc_life.min = 0; + d->tc_life.max = 3600 * 24 * 7; + + khui_tracker_initialize(&d->tc_renew); + d->tc_renew.current = d->renew_life; + d->tc_renew.min = 0; + d->tc_renew.max = 3600 * 24 * 30; + + if (csp_ident) + khc_close_space(csp_ident); +} + +static khm_boolean +k5_id_is_mod(HWND hw, k5_id_dlg_data * d) { + wchar_t ccache[KRB5_MAXCCH_CCNAME]; + DWORD dwaddress = 0; + + GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache)); + + SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS, + 0, (LPARAM) &dwaddress); + + if (_wcsicmp(ccache, d->ccache) || + + d->tc_renew.current != d->renew_life || + + d->tc_life.current != d->life || + + (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED) != d->renewable || + + (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED) != d->forwardable || + + (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED) + != d->addressless || + + dwaddress != d->public_ip) + + return TRUE; + + return FALSE; +} + +static void +k5_id_check_mod(HWND hw, k5_id_dlg_data * d) { + BOOL modified = k5_id_is_mod(hw, d); + + khui_cfg_set_flags_inst(&d->cfg, + (modified)?KHUI_CNFLAG_MODIFIED:0, + KHUI_CNFLAG_MODIFIED); +} + +static void +k5_id_write_params(HWND hw, k5_id_dlg_data * d) { + + khm_handle csp_idroot = NULL; + khm_handle csp_ident = NULL; + wchar_t ccache[KRB5_MAXCCH_CCNAME]; + khm_size cb; + khm_int32 rv; + khm_boolean b; + khm_boolean applied = FALSE; + DWORD dwaddress = 0; + + if (!k5_id_is_mod(hw, d)) + return; + + rv = kcdb_identity_get_config(d->ident, KHM_FLAG_CREATE, &csp_idroot); + if (KHM_SUCCEEDED(rv)) { + khc_open_space(csp_idroot, CSNAME_KRB5CRED, + KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD, + &csp_ident); + } + + if (csp_idroot) + khc_close_space(csp_idroot); + + if (!csp_ident) + return; + + if (d->life != d->tc_life.current) { + d->life = d->tc_life.current; + khc_write_int32(csp_ident, L"DefaultLifetime", (khm_int32) d->life); + applied = TRUE; + } + + if (d->renew_life != d->tc_renew.current) { + d->renew_life = d->tc_renew.current; + khc_write_int32(csp_ident, L"DefaultRenewLifetime", (khm_int32) d->renew_life); + applied = TRUE; + } + + b = (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED); + if (b != d->renewable) { + d->renewable = b; + khc_write_int32(csp_ident, L"Renewable", (khm_int32) b); + applied = TRUE; + } + + b = (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED); + if (b != d->forwardable) { + d->forwardable = b; + khc_write_int32(csp_ident, L"Forwardable", (khm_int32) b); + applied = TRUE; + } + + b = (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED); + if (b != d->addressless) { + d->addressless = b; + khc_write_int32(csp_ident, L"Addressless", (khm_int32) b); + applied = TRUE; + } + + SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS, + 0, (LPARAM) &dwaddress); + + if (dwaddress != d->public_ip) { + d->public_ip = dwaddress; + khc_write_int32(csp_ident, L"PublicIP", (khm_int32) dwaddress); + applied = TRUE; + } + + GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache)); + + if (SUCCEEDED(StringCbLength(ccache, sizeof(ccache), &cb)) && + cb > sizeof(wchar_t)) { + + if (wcscmp(ccache, d->ccache)) { + khc_write_string(csp_ident, L"DefaultCCName", ccache); + StringCbCopy(d->ccache, sizeof(d->ccache), ccache); + applied = TRUE; + } + + } else { + khc_remove_value(csp_ident, L"DefaultCCName", KCONF_FLAG_USER); + d->ccache[0] = L'\0'; + applied = TRUE; + } + + if (csp_ident) + khc_close_space(csp_ident); + + khui_cfg_set_flags_inst(&d->cfg, + (applied ? KHUI_CNFLAG_APPLIED : 0), + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +INT_PTR CALLBACK +k5_id_tab_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + k5_id_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d); +#endif + ZeroMemory(d, sizeof(*d)); + + d->cfg = *((khui_config_init_data *) lParam); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + k5_id_read_params(d); + + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFLIFE), + &d->tc_life); + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFRLIFE), + &d->tc_renew); + khui_tracker_refresh(&d->tc_life); + khui_tracker_refresh(&d->tc_renew); + + SetDlgItemText(hwnd, IDC_CFG_CCACHE, d->ccache); + + CheckDlgButton(hwnd, IDC_CFG_RENEW, + (d->renewable? BST_CHECKED: BST_UNCHECKED)); + + CheckDlgButton(hwnd, IDC_CFG_FORWARD, + (d->forwardable? BST_CHECKED: BST_UNCHECKED)); + + CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS, + (d->addressless? BST_CHECKED: BST_UNCHECKED)); + + SendDlgItemMessage(hwnd, IDC_CFG_PUBLICIP, + IPM_SETADDRESS, + 0, (LPARAM) d->public_ip); + break; + + case WM_COMMAND: + d = (k5_id_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (HIWORD(wParam) == EN_CHANGE || + HIWORD(wParam) == BN_CLICKED) + k5_id_check_mod(hwnd, d); + break; + + case KHUI_WM_CFG_NOTIFY: + d = (k5_id_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (HIWORD(wParam) == WMCFG_APPLY) { + k5_id_write_params(hwnd, d); + } + break; + + case WM_DESTROY: + d = (k5_id_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + khui_tracker_kill_controls(&d->tc_life); + khui_tracker_kill_controls(&d->tc_renew); + + if (d->ident) + kcdb_identity_release(d->ident); + + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + break; + } + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5configids.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configids.c new file mode 100644 index 000000000..4699f056a --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5configids.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<krb5.h> +#include<assert.h> +#include<lm.h> +#include<commctrl.h> +#include<shlwapi.h> + +typedef struct tag_k5_ids_opts { + khm_int32 renewable; + khm_int32 forwardable; + khm_int32 addressless; +} k5_ids_opts; + +typedef struct tag_k5_ids_dlg_data { + khui_config_init_data cfg; + + khui_tracker tc_life; + khui_tracker tc_renew; + khui_tracker tc_life_min; + khui_tracker tc_life_max; + khui_tracker tc_renew_min; + khui_tracker tc_renew_max; + + time_t life; + time_t renew_life; + time_t life_min; + time_t life_max; + time_t renew_min; + time_t renew_max; + + k5_ids_opts opt; + k5_ids_opts opt_saved; + +} k5_ids_dlg_data; + +static khm_boolean +k5_ids_is_mod(k5_ids_dlg_data * d) { + if (d->life != d->tc_life.current || + d->renew_life != d->tc_renew.current || + d->life_max != d->tc_life_max.current || + d->life_min != d->tc_life_min.current || + d->renew_max != d->tc_renew_max.current || + d->renew_min != d->tc_renew_min.current || + !!d->opt.renewable != !!d->opt_saved.renewable || + !!d->opt.forwardable != !!d->opt_saved.forwardable || + !!d->opt.addressless != !!d->opt_saved.addressless) + return TRUE; + return FALSE; +} + +static void +k5_ids_check_mod(k5_ids_dlg_data * d) { + BOOL modified = k5_ids_is_mod(d); + + khui_cfg_set_flags_inst(&d->cfg, + (modified)?KHUI_CNFLAG_MODIFIED:0, + KHUI_CNFLAG_MODIFIED); +} + +static void +k5_ids_write_params(k5_ids_dlg_data * d) { + + khm_int32 rv; + +#ifdef DEBUG + assert(csp_params); +#endif + + if (!k5_ids_is_mod(d)) + return; + +#define WRITEPARAM(po,pn,vn) \ + if (po != pn) { \ + po = pn; \ + rv = khc_write_int32(csp_params, vn, (khm_int32) po); \ + assert(KHM_SUCCEEDED(rv)); \ + } + + WRITEPARAM(d->life,d->tc_life.current, L"DefaultLifetime"); + WRITEPARAM(d->renew_life,d->tc_renew.current, L"DefaultRenewLifetime"); + WRITEPARAM(d->life_max,d->tc_life_max.current, L"MaxLifetime"); + WRITEPARAM(d->life_min,d->tc_life_min.current, L"MinLifetime"); + WRITEPARAM(d->renew_max,d->tc_renew_max.current, L"MaxRenewLifetime"); + WRITEPARAM(d->renew_min,d->tc_renew_min.current, L"MinRenewLifetime"); + WRITEPARAM(d->opt_saved.renewable, d->opt.renewable, L"Renewable"); + WRITEPARAM(d->opt_saved.forwardable, d->opt.forwardable, L"Forwardable"); + WRITEPARAM(d->opt_saved.addressless, d->opt.addressless, L"Addressless"); + +#undef WRITEPARAM + + khui_cfg_set_flags_inst(&d->cfg, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +static void +k5_ids_read_params(k5_ids_dlg_data * d) { + k5_params p; + + khm_krb5_get_identity_params(NULL, &p); + + d->life = p.lifetime; + d->life_max = p.lifetime_max; + d->life_min = p.lifetime_min; + + d->renew_life = p.renew_life; + d->renew_max = p.renew_life_max; + d->renew_min = p.renew_life_min; + + d->opt_saved.forwardable = p.forwardable; + d->opt_saved.renewable = p.renewable; + d->opt_saved.addressless = p.addressless; + + d->opt = d->opt_saved; + + khui_tracker_initialize(&d->tc_life); + d->tc_life.current = d->life; + d->tc_life.min = 0; + d->tc_life.max = 3600 * 24 * 7; + + khui_tracker_initialize(&d->tc_renew); + d->tc_renew.current = d->renew_life; + d->tc_renew.min = 0; + d->tc_renew.max = 3600 * 24 * 30; + + khui_tracker_initialize(&d->tc_life_min); + d->tc_life_min.current = d->life_min; + d->tc_life_min.min = d->tc_life.min; + d->tc_life_min.max = d->tc_life.max; + + khui_tracker_initialize(&d->tc_life_max); + d->tc_life_max.current = d->life_max; + d->tc_life_max.min = d->tc_life.min; + d->tc_life_max.max = d->tc_life.max; + + khui_tracker_initialize(&d->tc_renew_min); + d->tc_renew_min.current = d->renew_min; + d->tc_renew_min.min = d->tc_renew.min; + d->tc_renew_min.max = d->tc_renew.max; + + khui_tracker_initialize(&d->tc_renew_max); + d->tc_renew_max.current = d->renew_max; + d->tc_renew_max.min = d->tc_renew.min; + d->tc_renew_max.max = d->tc_renew.max; +} + +INT_PTR CALLBACK +k5_ids_tab_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + k5_ids_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d); +#endif + ZeroMemory(d, sizeof(*d)); +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + d->cfg = *((khui_config_init_data *) lParam); + + k5_ids_read_params(d); + + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFLIFE), + &d->tc_life); + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFRLIFE), + &d->tc_renew); + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MIN), + &d->tc_life_min); + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MAX), + &d->tc_life_max); + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MIN), + &d->tc_renew_min); + khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MAX), + &d->tc_renew_max); + khui_tracker_refresh(&d->tc_life); + khui_tracker_refresh(&d->tc_life_min); + khui_tracker_refresh(&d->tc_life_max); + khui_tracker_refresh(&d->tc_renew); + khui_tracker_refresh(&d->tc_renew_min); + khui_tracker_refresh(&d->tc_renew_max); + + CheckDlgButton(hwnd, IDC_CFG_RENEW, (d->opt.renewable ? BST_CHECKED: BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_FORWARD, (d->opt.forwardable ? BST_CHECKED: BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS, (d->opt.addressless ? BST_CHECKED: BST_UNCHECKED)); + break; + + case WM_COMMAND: + d = (k5_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (HIWORD(wParam) == EN_CHANGE) { + k5_ids_check_mod(d); + } else if (HIWORD(wParam) == BN_CLICKED) { + switch (LOWORD(wParam)) { + case IDC_CFG_RENEW: + d->opt.renewable = (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED); + break; + + case IDC_CFG_FORWARD: + d->opt.forwardable = (IsDlgButtonChecked(hwnd, IDC_CFG_FORWARD) == BST_CHECKED); + break; + + case IDC_CFG_ADDRESSLESS: + d->opt.addressless = (IsDlgButtonChecked(hwnd, IDC_CFG_ADDRESSLESS) == BST_CHECKED); + break; + } + + k5_ids_check_mod(d); + } + break; + + case KHUI_WM_CFG_NOTIFY: + d = (k5_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + if (HIWORD(wParam) == WMCFG_APPLY) { + k5_ids_write_params(d); + } + break; + + case WM_DESTROY: + d = (k5_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + break; + + khui_tracker_kill_controls(&d->tc_life); + khui_tracker_kill_controls(&d->tc_renew); + khui_tracker_kill_controls(&d->tc_life_min); + khui_tracker_kill_controls(&d->tc_life_max); + khui_tracker_kill_controls(&d->tc_renew_min); + khui_tracker_kill_controls(&d->tc_renew_max); + + PFREE(d); + + SetWindowLongPtr(hwnd, DWLP_USER, 0); + + break; + } + return FALSE; +} + + + diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.c new file mode 100644 index 000000000..59cbe32cc --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.c @@ -0,0 +1,3622 @@ +/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* Copyright (c) 2006,2007 Secure Endpoints Inc. +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies +* of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +/* $Id$ */ + +/* Originally this was krb5routines.c in Leash sources. Subsequently + * modified and adapted for NetIDMgr */ + +#include<krbcred.h> +#include<kherror.h> + +#define SECURITY_WIN32 +#include <security.h> + +#include <string.h> +#include <time.h> +#include <stdlib.h> +#include <assert.h> +#include <strsafe.h> + +long +khm_convert524(krb5_context alt_ctx) +{ + krb5_context ctx = 0; + krb5_error_code code = 0; + int icode = 0; + krb5_principal me = 0; + krb5_principal server = 0; + krb5_creds *v5creds = 0; + krb5_creds increds; + krb5_ccache cc = 0; + CREDENTIALS * v4creds = NULL; + static int init_ets = 1; + + if (!pkrb5_init_context || + !pkrb_in_tkt || + !pkrb524_init_ets || + !pkrb524_convert_creds_kdc) + return 0; + + v4creds = (CREDENTIALS *) PMALLOC(sizeof(CREDENTIALS)); + memset((char *) v4creds, 0, sizeof(CREDENTIALS)); + + memset((char *) &increds, 0, sizeof(increds)); + /* + From this point on, we can goto cleanup because increds is + initialized. + */ + + if (alt_ctx) + { + ctx = alt_ctx; + } + else + { + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + } + + code = pkrb5_cc_default(ctx, &cc); + if (code) goto cleanup; + + if ( init_ets ) { + pkrb524_init_ets(ctx); + init_ets = 0; + } + + if (code = pkrb5_cc_get_principal(ctx, cc, &me)) + goto cleanup; + + if ((code = pkrb5_build_principal(ctx, + &server, + krb5_princ_realm(ctx, me)->length, + krb5_princ_realm(ctx, me)->data, + "krbtgt", + krb5_princ_realm(ctx, me)->data, + NULL))) + { + goto cleanup; + } + + increds.client = me; + increds.server = server; + increds.times.endtime = 0; + increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + if ((code = pkrb5_get_credentials(ctx, 0, + cc, + &increds, + &v5creds))) + { + goto cleanup; + } + + if ((icode = pkrb524_convert_creds_kdc(ctx, + v5creds, + v4creds))) + { + goto cleanup; + } + + /* initialize ticket cache */ + if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm) + != KSUCCESS)) + { + goto cleanup; + } + /* stash ticket, session key, etc. for future use */ + if ((icode = pkrb_save_credentials(v4creds->service, + v4creds->instance, + v4creds->realm, + v4creds->session, + v4creds->lifetime, + v4creds->kvno, + &(v4creds->ticket_st), + v4creds->issue_date))) + { + goto cleanup; + } + +cleanup: + memset(v4creds, 0, sizeof(v4creds)); + PFREE(v4creds); + + if (v5creds) { + pkrb5_free_creds(ctx, v5creds); + } + if (increds.client == me) + me = 0; + if (increds.server == server) + server = 0; + pkrb5_free_cred_contents(ctx, &increds); + if (server) { + pkrb5_free_principal(ctx, server); + } + if (me) { + pkrb5_free_principal(ctx, me); + } + pkrb5_cc_close(ctx, cc); + + if (ctx && (ctx != alt_ctx)) { + pkrb5_free_context(ctx); + } + return !(code || icode); +} + +#ifdef DEPRECATED_REMOVABLE +int com_addr(void) +{ + long ipAddr; + char loc_addr[ADDR_SZ]; + CREDENTIALS cred; + char service[40]; + char instance[40]; + // char addr[40]; + char realm[40]; + struct in_addr LocAddr; + int k_errno; + + if (pkrb_get_cred == NULL) + return(KSUCCESS); + + k_errno = (*pkrb_get_cred)(service,instance,realm,&cred); + if (k_errno) + return KRBERR(k_errno); + + while(1) { + ipAddr = (*pLocalHostAddr)(); + LocAddr.s_addr = ipAddr; + StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr)); + if ( strcmp(cred.address, loc_addr) != 0) { + /* TODO: do something about this */ + //Leash_kdestroy (); + break; + } + break; + } // while() + return 0; +} +#endif + +/* we use these structures to keep track of identities that we find + while going through the API, FILE and MSLSA caches and enumerating + credentials. The only identities we want to keep track of are the + ones that have an initial ticket. We collect information for each + of the identities we find that we have initial tickets for and + then set the properties for the identities at once. */ + +typedef struct tag_ident_data { + khm_handle ident; /* handle to the identity */ + khm_int32 count; /* number of initial tickets we have + found for this identity. */ + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + FILETIME ft_issue; + FILETIME ft_expire; + FILETIME ft_renewexpire; + khm_int32 krb5_flags; +} ident_data; + +typedef struct tag_identlist { + ident_data * list; + khm_size n_list; + khm_size nc_list; +} identlist; + +#define IDLIST_ALLOC_INCR 8 + +static void +tc_prep_idlist(identlist * idlist) { + khm_int32 rv; + khm_size cb_ids = 0; + khm_size n_ids = 0; + khm_size i; + wchar_t * ids = NULL; + wchar_t *thisid; + + idlist->list = NULL; + idlist->n_list = 0; + idlist->nc_list = 0; + + do { + + if (ids) { + PFREE(ids); + ids = NULL; + } + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE, + KCDB_IDENT_FLAG_ACTIVE, + NULL, + &cb_ids, + &n_ids); + + if (rv != KHM_ERROR_TOO_LONG) + break; /* something else is wrong */ + + if (n_ids == 0 || cb_ids == 0) + break; /* no identities to process */ + +#ifdef DEBUG + assert(cb_ids > 0); +#endif + + ids = PMALLOC(cb_ids); +#ifdef DEBUG + assert(ids != NULL); +#endif + if (ids == NULL) + break; + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE, + KCDB_IDENT_FLAG_ACTIVE, + ids, + &cb_ids, + &n_ids); + + if (KHM_SUCCEEDED(rv)) + break; + + } while (TRUE); + + if (ids == NULL) + return; + + if (KHM_FAILED(rv) || n_ids == 0) { + if (ids) + PFREE(ids); + return; + } + + idlist->nc_list = UBOUNDSS(n_ids, IDLIST_ALLOC_INCR, IDLIST_ALLOC_INCR); + + idlist->list = PCALLOC(idlist->nc_list, sizeof(idlist->list[0])); + + for (i = 0, thisid = ids; + thisid && thisid[0]; + thisid = multi_string_next(thisid)) { + + khm_handle ident; + + rv = kcdb_identity_create(thisid, 0, &ident); + + if (KHM_FAILED(rv)) + continue; + + idlist->list[i].ident = ident; + idlist->list[i].count = 0; + + i++; + } + + idlist->n_list = i; + + PFREE(ids); +} + +static ident_data * +tc_add_ident_to_list(identlist * idlist, khm_handle ident) { + khm_size i; + ident_data * d; + + for (i=0; i < idlist->n_list; i++) { + if (kcdb_identity_is_equal(ident, idlist->list[i].ident)) + break; + } + + if (i < idlist->n_list) { + /* we already have this identity on our list. Increment the + count */ + idlist->list[i].count++; + return &idlist->list[i]; + } + + /* it wasn't in our list. Add it */ + + if (idlist->n_list + 1 > idlist->nc_list) { + idlist->nc_list = UBOUNDSS(idlist->n_list + 1, + IDLIST_ALLOC_INCR, + IDLIST_ALLOC_INCR); +#ifdef DEBUG + assert(idlist->n_list + 1 <= idlist->nc_list); +#endif + idlist->list = PREALLOC(idlist->list, + sizeof(idlist->list[0]) * idlist->nc_list); +#ifdef DEBUG + assert(idlist->list); +#endif + ZeroMemory(&idlist->list[idlist->n_list], + sizeof(idlist->list[0]) * + (idlist->nc_list - idlist->n_list)); + } + + d = &idlist->list[idlist->n_list]; + + ZeroMemory(d, sizeof(*d)); + + d->ident = ident; + d->count = 1; + + idlist->n_list++; + + kcdb_identity_hold(ident); + + return d; +} + +static void +tc_set_ident_data(identlist * idlist) { + khm_size i; + wchar_t k5idtype[KCDB_MAXCCH_NAME]; + + k5idtype[0] = L'\0'; + LoadString(hResModule, IDS_KRB5_NC_NAME, + k5idtype, ARRAYLENGTH(k5idtype)); + + for (i=0; i < idlist->n_list; i++) { +#ifdef DEBUG + assert(idlist->list[i].ident); +#endif + + if (idlist->list[i].count > 0) { + khm_int32 t; + + t = credtype_id_krb5; + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE, + &t, + sizeof(t)); + + /* We need to manually add the type name if we want the + name to show up in the property list for the identity. + The type name is only automatically calculated for + credentials. */ + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE_NAME, + k5idtype, + KCDB_CBSIZE_AUTO); + + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_ccname, + idlist->list[i].ccname, + KCDB_CBSIZE_AUTO); + + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_EXPIRE, + &idlist->list[i].ft_expire, + sizeof(idlist->list[i].ft_expire)); + + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_ISSUE, + &idlist->list[i].ft_issue, + sizeof(idlist->list[i].ft_issue)); + + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_flags, + &idlist->list[i].krb5_flags, + sizeof(idlist->list[i].krb5_flags)); + + if (idlist->list[i].ft_renewexpire.dwLowDateTime == 0 && + idlist->list[i].ft_renewexpire.dwHighDateTime == 0) { + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_RENEW_EXPIRE, + NULL, 0); + } else { + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_RENEW_EXPIRE, + &idlist->list[i].ft_renewexpire, + sizeof(idlist->list[i].ft_renewexpire)); + } + + } else { + /* We didn't see any TGTs for this identity. We have to + remove all the Krb5 supplied properties. */ + + khm_int32 t; + khm_size cb; + + cb = sizeof(t); + if (KHM_SUCCEEDED(kcdb_identity_get_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE, NULL, + &t, + &cb)) && + t == credtype_id_krb5) { + + /* disown this and remove all our properties. the + system will GC this identity if nobody claims it.*/ + + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE_NAME, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_ccname, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_EXPIRE, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_ISSUE, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_flags, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + } else { + /* otherwise, this identity doesn't belong to us. We + should leave it as is. */ + } + } + } +} + +static void +tc_free_idlist(identlist * idlist) { + khm_size i; + + for (i=0; i < idlist->n_list; i++) { + if (idlist->list[i].ident != NULL) { + kcdb_identity_release(idlist->list[i].ident); + idlist->list[i].ident = NULL; + } + } + + if (idlist->list) + PFREE(idlist->list); + idlist->list = NULL; + idlist->n_list = 0; + idlist->nc_list = 0; +} + +#ifndef ENCTYPE_LOCAL_RC4_MD4 +#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80 +#endif + +#define MAX_ADDRS 256 + +static long get_tickets_from_cache(krb5_context ctx, + krb5_ccache cache, + identlist * idlist) +{ + krb5_error_code code; + krb5_principal KRBv5Principal; + krb5_flags flags = 0; + krb5_cc_cursor KRBv5Cursor; + krb5_creds KRBv5Credentials; + krb5_ticket *tkt=NULL; + char *ClientName = NULL; + char *PrincipalName = NULL; + wchar_t wbuf[256]; /* temporary conversion buffer */ + wchar_t wcc_name[KRB5_MAXCCH_CCNAME]; /* credential cache name */ + char *sServerName = NULL; + khm_handle ident = NULL; + khm_handle cred = NULL; + time_t tt; + FILETIME ft, eft; + khm_int32 ti; + +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; +#endif + + { + const char * cc_name; + const char * cc_type; + + cc_name = (*pkrb5_cc_get_name)(ctx, cache); + if(cc_name) { + cc_type = (*pkrb5_cc_get_type)(ctx, cache); + if (cc_type) { + StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:%S", cc_type, cc_name); + } else { + AnsiStrToUnicode(wcc_name, sizeof(wcc_name), cc_name); + khm_krb5_canon_cc_name(wcc_name, sizeof(wcc_name)); + } + } else { + cc_type = (*pkrb5_cc_get_type)(ctx, cache); + if (cc_type) { + StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:", cc_type); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + StringCbCopy(wcc_name, sizeof(wcc_name), L""); + } + } + } + + _reportf(L"Getting tickets from cache [%s]", wcc_name); + + if ((code = (*pkrb5_cc_set_flags)(ctx, cache, flags))) + { + if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND) + khm_krb5_error(code, "krb5_cc_set_flags()", 0, &ctx, &cache); + + goto _exit; + } + + if ((code = (*pkrb5_cc_get_principal)(ctx, cache, &KRBv5Principal))) + { + if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND) + khm_krb5_error(code, "krb5_cc_get_principal()", 0, &ctx, &cache); + + goto _exit; + } + + PrincipalName = NULL; + ClientName = NULL; + sServerName = NULL; + if ((code = (*pkrb5_unparse_name)(ctx, KRBv5Principal, + (char **)&PrincipalName))) + { + if (PrincipalName != NULL) + (*pkrb5_free_unparsed_name)(ctx, PrincipalName); + + (*pkrb5_free_principal)(ctx, KRBv5Principal); + + goto _exit; + } + + if (!strcspn(PrincipalName, "@" )) + { + if (PrincipalName != NULL) + (*pkrb5_free_unparsed_name)(ctx, PrincipalName); + + (*pkrb5_free_principal)(ctx, KRBv5Principal); + + goto _exit; + } + + AnsiStrToUnicode(wbuf, sizeof(wbuf), PrincipalName); + if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE, + &ident))) { + /* something bad happened */ + code = 1; + goto _exit; + } + + _reportf(L"Found principal [%s]", wbuf); + + (*pkrb5_free_principal)(ctx, KRBv5Principal); + + if ((code = (*pkrb5_cc_start_seq_get)(ctx, cache, &KRBv5Cursor))) + { + goto _exit; + } + + memset(&KRBv5Credentials, '\0', sizeof(KRBv5Credentials)); + + ClientName = NULL; + sServerName = NULL; + cred = NULL; + + while (!(code = pkrb5_cc_next_cred(ctx, cache, &KRBv5Cursor, + &KRBv5Credentials))) + { + khm_handle tident = NULL; + khm_int32 cred_flags = 0; + + if(ClientName != NULL) + (*pkrb5_free_unparsed_name)(ctx, ClientName); + if(sServerName != NULL) + (*pkrb5_free_unparsed_name)(ctx, sServerName); + if(cred) + kcdb_cred_release(cred); + + ClientName = NULL; + sServerName = NULL; + cred = NULL; + + if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.client, &ClientName)) + { + (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); + khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache); + continue; + } + + if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName)) + { + (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); + khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache); + continue; + } + + /* if the ClientName differs from PrincipalName for some + reason, we need to create a new identity */ + if(strcmp(ClientName, PrincipalName)) { + AnsiStrToUnicode(wbuf, sizeof(wbuf), ClientName); + if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE, + &tident))) { + (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); + continue; + } + } else { + tident = ident; + } + + AnsiStrToUnicode(wbuf, sizeof(wbuf), sServerName); + if(KHM_FAILED(kcdb_cred_create(wbuf, tident, credtype_id_krb5, + &cred))) { + (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); + continue; + } + + if (!KRBv5Credentials.times.starttime) + KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime; + + tt = KRBv5Credentials.times.starttime; + TimetToFileTime(tt, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft)); + + tt = KRBv5Credentials.times.endtime; + TimetToFileTime(tt, &eft); + kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &eft, sizeof(eft)); + + { + FILETIME ftl; + + ftl = FtSub(&eft, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ftl, sizeof(ftl)); + } + + if (KRBv5Credentials.times.renew_till > 0) { + FILETIME ftl; + + tt = KRBv5Credentials.times.renew_till; + TimetToFileTime(tt, &eft); + kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_EXPIRE, &eft, + sizeof(eft)); + + + ftl = FtSub(&eft, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_LIFETIME, &ftl, + sizeof(ftl)); + } + + ti = KRBv5Credentials.ticket_flags; + kcdb_cred_set_attr(cred, attr_id_krb5_flags, &ti, sizeof(ti)); + + /* special flags understood by NetIDMgr */ + { + khm_int32 nflags = 0; + + if (ti & TKT_FLG_RENEWABLE) + nflags |= KCDB_CRED_FLAG_RENEWABLE; + if (ti & TKT_FLG_INITIAL) + nflags |= KCDB_CRED_FLAG_INITIAL; + else { + krb5_data * c0, *c1, *r; + + /* these are macros that do not allocate any memory */ + c0 = krb5_princ_component(ctx,KRBv5Credentials.server,0); + c1 = krb5_princ_component(ctx,KRBv5Credentials.server,1); + r = krb5_princ_realm(ctx,KRBv5Credentials.server); + + if ( c0 && c1 && r && c1->length == r->length && + !strncmp(c1->data,r->data,r->length) && + !strncmp("krbtgt",c0->data,c0->length) ) + nflags |= KCDB_CRED_FLAG_INITIAL; + } + + kcdb_cred_set_flags(cred, nflags, KCDB_CRED_FLAGMASK_EXT); + + cred_flags = nflags; + } + + if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) { + ti = tkt->enc_part.enctype; + kcdb_cred_set_attr(cred, attr_id_tkt_enctype, &ti, sizeof(ti)); + ti = tkt->enc_part.kvno; + kcdb_cred_set_attr(cred, attr_id_kvno, &ti, sizeof(ti)); + pkrb5_free_ticket(ctx, tkt); + tkt = NULL; + } + + ti = KRBv5Credentials.keyblock.enctype; + kcdb_cred_set_attr(cred, attr_id_key_enctype, &ti, sizeof(ti)); + + kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wcc_name, + KCDB_CBSIZE_AUTO); + + if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) { + khm_int32 buffer[1024]; + void * bufp; + khm_size cb; + khm_int32 rv; + + bufp = (void *) buffer; + cb = sizeof(buffer); + + rv = serialize_krb5_addresses(KRBv5Credentials.addresses, + bufp, + &cb); + if (rv == KHM_ERROR_TOO_LONG) { + bufp = PMALLOC(cb); + rv = serialize_krb5_addresses(KRBv5Credentials.addresses, + bufp, + &cb); + } + + if (KHM_SUCCEEDED(rv)) { + kcdb_cred_set_attr(cred, attr_id_addr_list, + bufp, cb); + } + + if (bufp != (void *) buffer) + PFREE(bufp); + } + + if(cred_flags & KCDB_CRED_FLAG_INITIAL) { + FILETIME ft_issue_new; + FILETIME ft_expire_old; + FILETIME ft_expire_new; + ident_data * d; + + /* an initial ticket! Add it to the list of identities we + have seen so far with initial tickets. */ + d = tc_add_ident_to_list(idlist, ident); +#ifdef DEBUG + assert(d); + assert(d->count > 0); +#endif + + tt = KRBv5Credentials.times.endtime; + TimetToFileTime(tt, &ft_expire_new); + + tt = KRBv5Credentials.times.starttime; + TimetToFileTime(tt, &ft_issue_new); + + /* so now, we have to set the properties of the identity + based on the properties of this credential under the + following circumstances: + + - If this is the first time we are hitting this + identity. + + - If this is not the MSLSA: cache and the expiry time + for this credential is longer than the time already + found for this identity. + */ + + ft_expire_old = d->ft_expire; + + if(d->count == 1 + || (CompareFileTime(&ft_expire_new, &ft_expire_old) > 0 && + wcscmp(wcc_name, L"MSLSA:") != 0)) { + + _reportf(L"Setting properties for identity (count=%d)", d->count); + + StringCbCopy(d->ccname, sizeof(d->ccname), + wcc_name); + d->ft_expire = ft_expire_new; + d->ft_issue = ft_issue_new; + + if (KRBv5Credentials.times.renew_till > 0) { + tt = KRBv5Credentials.times.renew_till; + TimetToFileTime(tt, &ft); + d->ft_renewexpire = ft; + } else { + ZeroMemory(&d->ft_renewexpire, sizeof(d->ft_renewexpire)); + } + + d->krb5_flags = KRBv5Credentials.ticket_flags; + } + } + + kcdb_credset_add_cred(krb5_credset, cred, -1); + + (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); + + if(tident != ident) + kcdb_identity_release(tident); + } + + if (PrincipalName != NULL) + (*pkrb5_free_unparsed_name)(ctx, PrincipalName); + + if (ClientName != NULL) + (*pkrb5_free_unparsed_name)(ctx, ClientName); + + if (sServerName != NULL) + (*pkrb5_free_unparsed_name)(ctx, sServerName); + + if (cred) + kcdb_cred_release(cred); + + if ((code == KRB5_CC_END) || (code == KRB5_CC_NOTFOUND)) + { + if ((code = pkrb5_cc_end_seq_get(ctx, cache, &KRBv5Cursor))) + { + goto _exit; + } + + flags = KRB5_TC_OPENCLOSE; +#ifdef KRB5_TC_NOTICKET + flags |= KRB5_TC_NOTICKET; +#endif + if ((code = pkrb5_cc_set_flags(ctx, cache, flags))) + { + goto _exit; + } + } + else + { + goto _exit; + } + +_exit: + + return code; +} + +long +khm_krb5_list_tickets(krb5_context *krbv5Context) +{ + krb5_context ctx = NULL; + krb5_ccache cache = NULL; + krb5_error_code code = 0; + apiCB * cc_ctx = NULL; + struct _infoNC ** pNCi = NULL; + int i; + khm_int32 t; + wchar_t * ms = NULL; + khm_size cb; + identlist idl; + + kcdb_credset_flush(krb5_credset); + tc_prep_idlist(&idl); + + if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) { + goto _exit; + } + + ctx = (*krbv5Context); + + if (!pcc_initialize || + !pcc_get_NC_info || + !pcc_free_NC_info || + !pcc_shutdown) + goto _skip_cc_iter; + + code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL); + if (code) + goto _exit; + + code = pcc_get_NC_info(cc_ctx, &pNCi); + if (code) + goto _exit; + + for(i=0; pNCi[i]; i++) { + char ccname[KRB5_MAXCCH_CCNAME]; + + if (pNCi[i]->vers != CC_CRED_V5) + continue; + + if (FAILED(StringCchPrintfA(ccname, sizeof(ccname), "API:%s", + pNCi[i]->name))) + continue; + + code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); + + if (code) + continue; + + code = get_tickets_from_cache(ctx, cache, &idl); + + if(ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + + cache = 0; + } + + _skip_cc_iter: + + if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + == KHM_ERROR_TOO_LONG && + cb > sizeof(wchar_t) * 2) { + wchar_t * t; + char ccname[KRB5_MAXCCH_CCNAME]; + + ms = PMALLOC(cb); +#ifdef DEBUG + assert(ms); +#endif + khc_read_multi_string(csp_params, L"FileCCList", ms, &cb); + + for(t = ms; t && *t; t = multi_string_next(t)) { + StringCchPrintfA(ccname, ARRAYLENGTH(ccname), + "FILE:%S", t); + + code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); + + if (code) + continue; + + code = get_tickets_from_cache(ctx, cache, &idl); + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + PFREE(ms); + } + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) { + code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache); + + if (code == 0 && cache) { + code = get_tickets_from_cache(ctx, cache, &idl); + } + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + +_exit: + if (pNCi) + (*pcc_free_NC_info)(cc_ctx, &pNCi); + if (cc_ctx) + (*pcc_shutdown)(&cc_ctx); + + kcdb_credset_collect(NULL, krb5_credset, NULL, credtype_id_krb5, NULL); + tc_set_ident_data(&idl); + tc_free_idlist(&idl); + + return(code); +} + +int +khm_krb5_renew_cred(khm_handle cred) +{ + khm_handle identity = NULL; + krb5_error_code code = 0; + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal me = NULL, server = NULL; + krb5_creds in_creds, cc_creds; + krb5_creds * out_creds = NULL; + + wchar_t wname[512]; + khm_size cbname; + char name[512]; + khm_boolean brenewIdentity = FALSE; + khm_boolean istgt = FALSE; + + khm_int32 flags; + int ccflags = 0; + + cbname = sizeof(wname); + kcdb_cred_get_name(cred, wname, &cbname); + _reportf(L"Krb5 renew cred for %s", wname); + + kcdb_cred_get_flags(cred, &flags); + + if (!(flags & KCDB_CRED_FLAG_INITIAL)) { + _reportf(L"Krb5 skipping renewal because this is not an initial credential"); + return 0; + } + + memset(&in_creds, 0, sizeof(in_creds)); + memset(&cc_creds, 0, sizeof(cc_creds)); + + if (cred == NULL) { +#ifdef DEBUG + assert(FALSE); +#endif + goto cleanup; + } + + if (KHM_FAILED(kcdb_cred_get_identity(cred, &identity))) { +#ifdef DEBUG + assert(FALSE); +#endif + goto cleanup; + } + + code = khm_krb5_initialize(identity, &ctx, &cc); + if (code) + goto cleanup; + + code = pkrb5_cc_get_principal(ctx, cc, &me); + if (code) + goto cleanup; + + cbname = sizeof(wname); + if (KHM_FAILED(kcdb_cred_get_name(cred, wname, &cbname))) + goto cleanup; + + UnicodeStrToAnsi(name, sizeof(name), wname); + + code = pkrb5_parse_name(ctx, name, &server); + if (code) + goto cleanup; + + in_creds.client = me; + in_creds.server = server; + + ccflags = KRB5_TC_OPENCLOSE; + pkrb5_cc_set_flags(ctx, cc, ccflags); + + if (strlen("krbtgt") != krb5_princ_name(ctx, server)->length || + strncmp("krbtgt", krb5_princ_name(ctx, server)->data, krb5_princ_name(ctx, server)->length)) + { + code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, name); + if (code) { + code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &in_creds, &cc_creds); + if (code == 0) { + code = pkrb5_cc_remove_cred(ctx, cc, 0, &cc_creds); + if (code) { + brenewIdentity = TRUE; + goto cleanup; + } + } + } + + code = pkrb5_get_credentials(ctx, 0, cc, &in_creds, &out_creds); + } else { + istgt = TRUE; + code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, NULL); + } + + if (code) { + if ( code != KRB5KDC_ERR_ETYPE_NOSUPP || + code != KRB5_KDC_UNREACH) + khm_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc); + goto cleanup; + } + + if (istgt) { + code = pkrb5_cc_initialize(ctx, cc, me); + if (code) goto cleanup; + + ccflags = KRB5_TC_OPENCLOSE; + pkrb5_cc_set_flags(ctx, cc, ccflags); + } + + code = pkrb5_cc_store_cred(ctx, cc, istgt ? &cc_creds : out_creds); + if (code) goto cleanup; + + + cleanup: + if (in_creds.client == me) + in_creds.client = NULL; + if (in_creds.server == server) + in_creds.server = NULL; + + if (me) + pkrb5_free_principal(ctx, me); + + if (server) + pkrb5_free_principal(ctx, server); + + pkrb5_free_cred_contents(ctx, &in_creds); + pkrb5_free_cred_contents(ctx, &cc_creds); + + if (out_creds) + pkrb5_free_creds(ctx, out_creds); + + if (cc && ctx) + pkrb5_cc_close(ctx, cc); + + if (ctx) + pkrb5_free_context(ctx); + + if (identity) { + if (brenewIdentity) + code = khm_krb5_renew_ident(identity); + kcdb_identity_release(identity); + } + + return code; +} + +int +khm_krb5_renew_ident(khm_handle identity) +{ + krb5_error_code code = 0; + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal me = NULL; + krb5_principal server = NULL; + krb5_creds my_creds; + krb5_data *realm = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_int32 k5_flags; + int ccflags; + + memset(&my_creds, 0, sizeof(krb5_creds)); + + if ( !pkrb5_init_context ) + goto cleanup; + + cb = sizeof(idname); + kcdb_identity_get_name(identity, idname, &cb); + + if (khm_krb5_get_identity_flags(identity) & K5IDFLAG_IMPORTED) { +#ifndef NO_REIMPORT_MSLSA_CREDS + /* we are trying to renew the identity that was imported from + MSLSA: */ + BOOL imported; + BOOL retry_import = FALSE; + char cidname[KCDB_IDENT_MAXCCH_NAME]; + khm_handle imported_id = NULL; + khm_size cb; + FILETIME ft_expire; + FILETIME ft_now; + FILETIME ft_threshold; + krb5_principal princ = NULL; + + UnicodeStrToAnsi(cidname, sizeof(cidname), idname); + + imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, &imported_id); + + if (imported == 0) + goto import_failed; + + /* if the imported identity has already expired or will soon, + we clear the cache and try again. */ + khm_krb5_list_tickets(&ctx); + + cb = sizeof(ft_expire); + if (KHM_FAILED(kcdb_identity_get_attr(imported_id, KCDB_ATTR_EXPIRE, + NULL, &ft_expire, &cb))) + goto import_failed; + + GetSystemTimeAsFileTime(&ft_now); + TimetToFileTimeInterval(5 * 60, &ft_threshold); + + ft_now = FtAdd(&ft_now, &ft_threshold); + + if (CompareFileTime(&ft_expire, &ft_now) < 0) { + /* the ticket lifetime is not long enough */ + + code = 0; + + if (ctx == NULL) + code = pkrb5_init_context(&ctx); + if (code) + goto import_failed; + + code = pkrb5_cc_resolve(ctx, "MSLSA:", &cc); + if (code) + goto import_failed; + + code = pkrb5_cc_get_principal(ctx, cc, &princ); + if (code) + goto import_failed; + + pkrb5_cc_initialize(ctx, cc, princ); + + retry_import = TRUE; + } + + import_failed: + + if (imported_id) { + kcdb_identity_release(imported_id); + imported_id = NULL; + } + + if (ctx) { + if (cc) { + pkrb5_cc_close(ctx, cc); + cc = NULL; + } + + if (princ) { + pkrb5_free_principal(ctx, princ); + princ = NULL; + } + + /* leave ctx so we can use it later */ + } + + if (retry_import) + imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, NULL); + + if (imported) + goto cleanup; + + /* if the import failed, then we try to renew the identity via + the usual procedure. */ + +#else + /* if we are suppressing further imports from MSLSA, we just + skip renewing this identity. */ + goto cleanup; +#endif + } + + cb = sizeof(k5_flags); + if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity, + attr_id_krb5_flags, + NULL, + &k5_flags, + &cb)) && + !(k5_flags & TKT_FLG_RENEWABLE)) { + + code = KRB5KDC_ERR_BADOPTION; + goto cleanup; + } + + { + FILETIME ft_now; + FILETIME ft_exp; + + cb = sizeof(ft_exp); + GetSystemTimeAsFileTime(&ft_now); + if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity, + KCDB_ATTR_EXPIRE, + NULL, + &ft_exp, + &cb)) && + CompareFileTime(&ft_exp, &ft_now) < 0) { + + code = KRB5KRB_AP_ERR_TKT_EXPIRED; + goto cleanup; + + } + } + + code = khm_krb5_initialize(identity, &ctx, &cc); + if (code) + goto cleanup; + + code = pkrb5_cc_get_principal(ctx, cc, &me); + if (code) + goto cleanup; + + realm = krb5_princ_realm(ctx, me); + + code = pkrb5_build_principal_ext(ctx, &server, + realm->length,realm->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + realm->length,realm->data, + 0); + + if (code) + goto cleanup; + + my_creds.client = me; + my_creds.server = server; + + pkrb5_cc_set_flags(ctx, cc, KRB5_TC_OPENCLOSE); + code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL); + ccflags = KRB5_TC_OPENCLOSE; +#ifdef KRB5_TC_NOTICKET + ccflags |= KRB5_TC_NOTICKET; +#endif + pkrb5_cc_set_flags(ctx, cc, ccflags); + if (code) { + if ( code != KRB5KDC_ERR_ETYPE_NOSUPP || + code != KRB5_KDC_UNREACH) + khm_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc); + goto cleanup; + } + + code = pkrb5_cc_initialize(ctx, cc, me); + if (code) goto cleanup; + + code = pkrb5_cc_set_flags(ctx, cc, KRB5_TC_OPENCLOSE); + if (code) goto cleanup; + + code = pkrb5_cc_store_cred(ctx, cc, &my_creds); + if (code) goto cleanup; + +cleanup: + if (my_creds.client == me) + my_creds.client = NULL; + if (my_creds.server == server) + my_creds.server = NULL; + + if (ctx) { + pkrb5_free_cred_contents(ctx, &my_creds); + + if (me) + pkrb5_free_principal(ctx, me); + if (server) + pkrb5_free_principal(ctx, server); + if (cc) + pkrb5_cc_close(ctx, cc); + pkrb5_free_context(ctx); + } + + return(code); +} + +int +khm_krb5_kinit(krb5_context alt_ctx, + char * principal_name, + char * password, + char * ccache, + krb5_deltat lifetime, + DWORD forwardable, + DWORD proxiable, + krb5_deltat renew_life, + DWORD addressless, + DWORD publicIP, + krb5_prompter_fct prompter, + void * p_data) +{ + krb5_error_code code = 0; + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal me = NULL; + char* name = NULL; + krb5_creds my_creds; + krb5_get_init_creds_opt options; + krb5_address ** addrs = NULL; + int i = 0, addr_count = 0; + + if (!pkrb5_init_context) + return 0; + + _reportf(L"In khm_krb5_kinit"); + + pkrb5_get_init_creds_opt_init(&options); + pkrb5_get_init_creds_opt_set_change_password_prompt(&options, 0); + + memset(&my_creds, 0, sizeof(my_creds)); + + if (alt_ctx) { + ctx = alt_ctx; + } else { + code = pkrb5_init_context(&ctx); + if (code) + goto cleanup; + } + + if (ccache) { + _reportf(L"Using supplied ccache name %S", ccache); + code = pkrb5_cc_resolve(ctx, ccache, &cc); + } else { + khm_handle identity = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + char ccname[KRB5_MAXCCH_CCNAME]; + char * pccname = principal_name; + khm_size cb; + + idname[0] = L'\0'; + AnsiStrToUnicode(idname, sizeof(idname), principal_name); + + cb = sizeof(ccname); + + if (KHM_SUCCEEDED(kcdb_identity_create(idname, 0, &identity)) && + KHM_SUCCEEDED(khm_krb5_get_identity_default_ccacheA(identity, ccname, &cb))) { + + pccname = ccname; + + } + + if (identity) + kcdb_identity_release(identity); + + code = pkrb5_cc_resolve(ctx, pccname, &cc); + } + + _reportf(L"krb5_cc_resolve returns code %d", code); + + if (code) goto cleanup; + + code = pkrb5_parse_name(ctx, principal_name, &me); + if (code) goto cleanup; + + code = pkrb5_unparse_name(ctx, me, &name); + if (code) goto cleanup; + + if (lifetime == 0) { + khc_read_int32(csp_params, L"DefaultLifetime", &lifetime); + } + + if (lifetime) + pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime); + + pkrb5_get_init_creds_opt_set_forwardable(&options, + forwardable ? 1 : 0); + pkrb5_get_init_creds_opt_set_proxiable(&options, + proxiable ? 1 : 0); + pkrb5_get_init_creds_opt_set_renew_life(&options, + renew_life); + + if (addressless) + pkrb5_get_init_creds_opt_set_address_list(&options,NULL); + else { + krb5_address ** local_addrs=NULL; + DWORD netIPAddr; + + pkrb5_os_localaddr(ctx, &local_addrs); + i = 0; + while ( local_addrs[i++] ); + addr_count = i + 1; + + addrs = (krb5_address **) PMALLOC((addr_count+1) * sizeof(krb5_address *)); + if ( !addrs ) { + pkrb5_free_addresses(ctx, local_addrs); + assert(0); + } + memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1)); + i = 0; + while ( local_addrs[i] ) { + addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address)); + if (addrs[i] == NULL) { + pkrb5_free_addresses(ctx, local_addrs); + assert(0); + } + + addrs[i]->magic = local_addrs[i]->magic; + addrs[i]->addrtype = local_addrs[i]->addrtype; + addrs[i]->length = local_addrs[i]->length; + addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length); + if (!addrs[i]->contents) { + pkrb5_free_addresses(ctx, local_addrs); + assert(0); + } + + memcpy(addrs[i]->contents,local_addrs[i]->contents, + local_addrs[i]->length); /* safe */ + i++; + } + pkrb5_free_addresses(ctx, local_addrs); + + if (publicIP) { + // we are going to add the public IP address specified by the user + // to the list provided by the operating system + addrs[i] = (krb5_address *)PMALLOC(sizeof(krb5_address)); + if (addrs[i] == NULL) + assert(0); + + addrs[i]->magic = KV5M_ADDRESS; + addrs[i]->addrtype = AF_INET; + addrs[i]->length = 4; + addrs[i]->contents = (unsigned char *)PMALLOC(addrs[i]->length); + if (!addrs[i]->contents) + assert(0); + + netIPAddr = htonl(publicIP); + memcpy(addrs[i]->contents,&netIPAddr,4); + } + + pkrb5_get_init_creds_opt_set_address_list(&options,addrs); + } + + code = + pkrb5_get_init_creds_password(ctx, + &my_creds, + me, + password, // password + prompter, // prompter + p_data, // prompter data + 0, // start time + 0, // service name + &options); + _reportf(L"krb5_get_init_creds_password returns code %d", code); + + if (code) goto cleanup; + + code = pkrb5_cc_initialize(ctx, cc, me); + _reportf(L"krb5_cc_initialize returns code %d", code); + if (code) goto cleanup; + + code = pkrb5_cc_store_cred(ctx, cc, &my_creds); + _reportf(L"krb5_cc_store_cred returns code %d", code); + if (code) goto cleanup; + +cleanup: + if ( addrs ) { + for ( i=0;i<addr_count;i++ ) { + if ( addrs[i] ) { + if ( addrs[i]->contents ) + PFREE(addrs[i]->contents); + PFREE(addrs[i]); + } + } + } + if (my_creds.client == me) + my_creds.client = 0; + pkrb5_free_cred_contents(ctx, &my_creds); + if (name) + pkrb5_free_unparsed_name(ctx, name); + if (me) + pkrb5_free_principal(ctx, me); + if (cc) + pkrb5_cc_close(ctx, cc); + if (ctx && (ctx != alt_ctx)) + pkrb5_free_context(ctx); + return(code); +} + +long +khm_krb5_copy_ccache_by_name(krb5_context in_ctx, + wchar_t * wscc_dest, + wchar_t * wscc_src) { + krb5_context ctx = NULL; + krb5_error_code code = 0; + khm_boolean free_ctx; + krb5_ccache cc_src = NULL; + krb5_ccache cc_dest = NULL; + krb5_principal princ_src = NULL; + char scc_dest[KRB5_MAXCCH_CCNAME]; + char scc_src[KRB5_MAXCCH_CCNAME]; + int t; + + t = UnicodeStrToAnsi(scc_dest, sizeof(scc_dest), wscc_dest); + if (t == 0) + return KHM_ERROR_TOO_LONG; + t = UnicodeStrToAnsi(scc_src, sizeof(scc_src), wscc_src); + if (t == 0) + return KHM_ERROR_TOO_LONG; + + if (in_ctx) { + ctx = in_ctx; + free_ctx = FALSE; + } else { + code = pkrb5_init_context(&ctx); + if (code) { + if (ctx) + pkrb5_free_context(ctx); + return code; + } + free_ctx = TRUE; + } + + code = pkrb5_cc_resolve(ctx, scc_dest, &cc_dest); + if (code) + goto _cleanup; + + code = pkrb5_cc_resolve(ctx, scc_src, &cc_src); + if (code) + goto _cleanup; + + code = pkrb5_cc_get_principal(ctx, cc_src, &princ_src); + if (code) + goto _cleanup; + + code = pkrb5_cc_initialize(ctx, cc_dest, princ_src); + if (code) + goto _cleanup; + + code = pkrb5_cc_copy_creds(ctx, cc_src, cc_dest); + + _cleanup: + if (princ_src) + pkrb5_free_principal(ctx, princ_src); + + if (cc_dest) + pkrb5_cc_close(ctx, cc_dest); + + if (cc_src) + pkrb5_cc_close(ctx, cc_src); + + if (free_ctx && ctx) + pkrb5_free_context(ctx); + + return code; +} + +long +khm_krb5_canon_cc_name(wchar_t * wcc_name, + size_t cb_cc_name) { + size_t cb_len; + wchar_t * colon; + + if (FAILED(StringCbLength(wcc_name, + cb_cc_name, + &cb_len))) { +#ifdef DEBUG + assert(FALSE); +#else + return KHM_ERROR_TOO_LONG; +#endif + } + + cb_len += sizeof(wchar_t); + + colon = wcschr(wcc_name, L':'); + + if (colon) { + /* if the colon is just 1 character away from the beginning, + it's a FILE: cc */ + if (colon - wcc_name == 1) { + if (cb_len + 5 * sizeof(wchar_t) > cb_cc_name) + return KHM_ERROR_TOO_LONG; + + memmove(&wcc_name[5], &wcc_name[0], cb_len); + memmove(&wcc_name[0], L"FILE:", sizeof(wchar_t) * 5); + } + + return 0; + } + + if (cb_len + 4 * sizeof(wchar_t) > cb_cc_name) + return KHM_ERROR_TOO_LONG; + + memmove(&wcc_name[4], &wcc_name[0], cb_len); + memmove(&wcc_name[0], L"API:", sizeof(wchar_t) * 4); + + return 0; +} + +int +khm_krb5_cc_name_cmp(const wchar_t * cc_name_1, + const wchar_t * cc_name_2) { + if (!wcsncmp(cc_name_1, L"API:", 4)) + cc_name_1 += 4; + + if (!wcsncmp(cc_name_2, L"API:", 4)) + cc_name_2 += 4; + + return wcscmp(cc_name_1, cc_name_2); +} + +static khm_int32 KHMAPI +khmint_location_comp_func(khm_handle cred1, + khm_handle cred2, + void * rock) { + return kcdb_creds_comp_attr(cred1, cred2, KCDB_ATTR_LOCATION); +} + +struct khmint_location_check { + khm_handle credset; + khm_handle cred; + wchar_t * ccname; + khm_boolean success; +}; + +static khm_int32 KHMAPI +khmint_find_matching_cred_func(khm_handle cred, + void * rock) { + struct khmint_location_check * lc; + + lc = (struct khmint_location_check *) rock; + + if (!kcdb_creds_is_equal(cred, lc->cred)) + return KHM_ERROR_SUCCESS; + if (kcdb_creds_comp_attr(cred, lc->cred, KCDB_ATTR_LOCATION)) + return KHM_ERROR_SUCCESS; + + /* found it */ + lc->success = TRUE; + + /* break the search */ + return !KHM_ERROR_SUCCESS; +} + +static khm_int32 KHMAPI +khmint_location_check_func(khm_handle cred, + void * rock) { + khm_int32 t; + khm_size cb; + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + struct khmint_location_check * lc; + + lc = (struct khmint_location_check *) rock; + + if (KHM_FAILED(kcdb_cred_get_type(cred, &t))) + return KHM_ERROR_SUCCESS; + + if (t != credtype_id_krb5) + return KHM_ERROR_SUCCESS; + + cb = sizeof(ccname); + if (KHM_FAILED(kcdb_cred_get_attr(cred, + KCDB_ATTR_LOCATION, + NULL, + ccname, + &cb))) + return KHM_ERROR_SUCCESS; + + if(wcscmp(ccname, lc->ccname)) + return KHM_ERROR_SUCCESS; + + lc->cred = cred; + + lc->success = FALSE; + + kcdb_credset_apply(lc->credset, + khmint_find_matching_cred_func, + (void *) lc); + + if (!lc->success) + return KHM_ERROR_NOT_FOUND; + else + return KHM_ERROR_SUCCESS; +} + +static khm_int32 KHMAPI +khmint_delete_location_func(khm_handle cred, + void * rock) { + wchar_t cc_cred[KRB5_MAXCCH_CCNAME]; + struct khmint_location_check * lc; + khm_size cb; + + lc = (struct khmint_location_check *) rock; + + cb = sizeof(cc_cred); + + if (KHM_FAILED(kcdb_cred_get_attr(cred, + KCDB_ATTR_LOCATION, + NULL, + cc_cred, + &cb))) + return KHM_ERROR_SUCCESS; + + if (wcscmp(cc_cred, lc->ccname)) + return KHM_ERROR_SUCCESS; + + kcdb_credset_del_cred_ref(lc->credset, + cred); + + return KHM_ERROR_SUCCESS; +} + +int +khm_krb5_destroy_by_credset(khm_handle p_cs) +{ + khm_handle d_cs = NULL; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_size s, cb; + krb5_context ctx = NULL; + krb5_error_code code = 0; + int i; + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + struct khmint_location_check lc; + + rv = kcdb_credset_create(&d_cs); + + assert(KHM_SUCCEEDED(rv) && d_cs != NULL); + + kcdb_credset_extract(d_cs, p_cs, NULL, credtype_id_krb5); + + kcdb_credset_get_size(d_cs, &s); + + if (s == 0) { + _reportf(L"No tickets to delete"); + + kcdb_credset_delete(d_cs); + return 0; + } + + code = pkrb5_init_context(&ctx); + if (code != 0) { + rv = code; + goto _cleanup; + } + + /* we should synchronize the credential lists before we attempt to + make any assumptions on the state of the root credset */ + khm_krb5_list_tickets(&ctx); + + /* so, we need to make a decision about whether to destroy entire + ccaches or just individual credentials. Therefore we first + sort them by ccache. */ + kcdb_credset_sort(d_cs, + khmint_location_comp_func, + NULL); + + /* now, for each ccache we encounter, we check if we have all the + credentials from that ccache in the to-be-deleted list. */ + for (i=0; i < (int) s; i++) { + khm_handle cred; + + if (KHM_FAILED(kcdb_credset_get_cred(d_cs, + i, + &cred))) + continue; + + cb = sizeof(ccname); + rv = kcdb_cred_get_attr(cred, + KCDB_ATTR_LOCATION, + NULL, + ccname, + &cb); + +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + kcdb_cred_release(cred); + + lc.credset = d_cs; + lc.cred = NULL; + lc.ccname = ccname; + lc.success = FALSE; + + kcdb_credset_apply(NULL, + khmint_location_check_func, + (void *) &lc); + + if (lc.success) { + /* ok the destroy the ccache */ + char a_ccname[KRB5_MAXCCH_CCNAME]; + krb5_ccache cc = NULL; + + _reportf(L"Destroying ccache [%s]", ccname); + + UnicodeStrToAnsi(a_ccname, + sizeof(a_ccname), + ccname); + + code = pkrb5_cc_resolve(ctx, + a_ccname, + &cc); + if (code) + goto _delete_this_set; + + code = pkrb5_cc_destroy(ctx, cc); + + if (code) { + _reportf(L"krb5_cc_destroy returns code %d", code); + } + + _delete_this_set: + + lc.credset = d_cs; + lc.ccname = ccname; + + /* note that although we are deleting credentials off the + credential set, the size of the credential set does not + decrease since we are doing it from inside + kcdb_credset_apply(). The deleted creds will simply be + marked as deleted until kcdb_credset_purge() is + called. */ + + kcdb_credset_apply(d_cs, + khmint_delete_location_func, + (void *) &lc); + } + } + + kcdb_credset_purge(d_cs); + + /* the remainder need to be deleted one by one */ + + kcdb_credset_get_size(d_cs, &s); + + for (i=0; i < (int) s; ) { + khm_handle cred; + char a_ccname[KRB5_MAXCCH_CCNAME]; + char a_srvname[KCDB_CRED_MAXCCH_NAME]; + wchar_t srvname[KCDB_CRED_MAXCCH_NAME]; + krb5_ccache cc; + krb5_creds in_cred, out_cred; + krb5_principal princ; + khm_int32 etype; + + if (KHM_FAILED(kcdb_credset_get_cred(d_cs, + i, + &cred))) { + i++; + continue; + } + + cb = sizeof(ccname); + if (KHM_FAILED(kcdb_cred_get_attr(cred, + KCDB_ATTR_LOCATION, + NULL, + ccname, + &cb))) + goto _done_with_this_cred; + + _reportf(L"Looking at ccache [%s]", ccname); + + UnicodeStrToAnsi(a_ccname, + sizeof(a_ccname), + ccname); + + code = pkrb5_cc_resolve(ctx, + a_ccname, + &cc); + + if (code) + goto _skip_similar; + + code = pkrb5_cc_get_principal(ctx, cc, &princ); + + if (code) { + pkrb5_cc_close(ctx, cc); + goto _skip_similar; + } + + _del_this_cred: + + cb = sizeof(etype); + + if (KHM_FAILED(kcdb_cred_get_attr(cred, + attr_id_key_enctype, + NULL, + &etype, + &cb))) + goto _do_next_cred; + + cb = sizeof(srvname); + if (KHM_FAILED(kcdb_cred_get_name(cred, + srvname, + &cb))) + goto _do_next_cred; + + _reportf(L"Attempting to delete ticket %s", srvname); + + UnicodeStrToAnsi(a_srvname, sizeof(a_srvname), srvname); + + ZeroMemory(&in_cred, sizeof(in_cred)); + + code = pkrb5_parse_name(ctx, a_srvname, &in_cred.server); + if (code) + goto _do_next_cred; + in_cred.client = princ; + in_cred.keyblock.enctype = etype; + + code = pkrb5_cc_retrieve_cred(ctx, + cc, + KRB5_TC_MATCH_SRV_NAMEONLY | + KRB5_TC_SUPPORTED_KTYPES, + &in_cred, + &out_cred); + if (code) + goto _do_next_cred_0; + + code = pkrb5_cc_remove_cred(ctx, cc, + KRB5_TC_MATCH_SRV_NAMEONLY | + KRB5_TC_SUPPORTED_KTYPES | + KRB5_TC_MATCH_AUTHDATA, + &out_cred); + + pkrb5_free_cred_contents(ctx, &out_cred); + _do_next_cred_0: + pkrb5_free_principal(ctx, in_cred.server); + _do_next_cred: + + /* check if the next cred is also of the same ccache */ + kcdb_cred_release(cred); + + for (i++; i < (int) s; i++) { + if (KHM_FAILED(kcdb_credset_get_cred(d_cs, + i, + &cred))) + continue; + } + + if (i < (int) s) { + wchar_t newcc[KRB5_MAXCCH_CCNAME]; + + cb = sizeof(newcc); + if (KHM_FAILED(kcdb_cred_get_attr(cred, + KCDB_ATTR_LOCATION, + NULL, + newcc, + &cb)) || + wcscmp(newcc, ccname)) { + i--; /* we have to look at this again */ + goto _done_with_this_set; + } + goto _del_this_cred; + } + + + _done_with_this_set: + pkrb5_free_principal(ctx, princ); + + pkrb5_cc_close(ctx, cc); + + _done_with_this_cred: + kcdb_cred_release(cred); + i++; + continue; + + _skip_similar: + kcdb_cred_release(cred); + + for (++i; i < (int) s; i++) { + wchar_t newcc[KRB5_MAXCCH_CCNAME]; + + if (KHM_FAILED(kcdb_credset_get_cred(d_cs, + i, + &cred))) + continue; + + cb = sizeof(newcc); + if (KHM_FAILED(kcdb_cred_get_attr(cred, + KCDB_ATTR_LOCATION, + NULL, + &newcc, + &cb))) { + kcdb_cred_release(cred); + continue; + } + + if (wcscmp(newcc, ccname)) { + kcdb_cred_release(cred); + break; + } + } + } + + _cleanup: + + if (d_cs) + kcdb_credset_delete(&d_cs); + + if (ctx != NULL) + pkrb5_free_context(ctx); + + return rv; +} + +int +khm_krb5_destroy_identity(khm_handle identity) +{ + krb5_context ctx; + krb5_ccache cache; + krb5_error_code rc; + + ctx = NULL; + cache = NULL; + + if (rc = khm_krb5_initialize(identity, &ctx, &cache)) + return(rc); + + rc = pkrb5_cc_destroy(ctx, cache); + + if (ctx != NULL) + pkrb5_free_context(ctx); + + return(rc); +} + +static BOOL +GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData) +{ + NTSTATUS Status = 0; + HANDLE TokenHandle; + TOKEN_STATISTICS Stats; + DWORD ReqLen; + BOOL Success; + + if (!ppSessionData) + return FALSE; + *ppSessionData = NULL; + + Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle ); + if ( !Success ) + return FALSE; + + Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen ); + CloseHandle( TokenHandle ); + if ( !Success ) + return FALSE; + + Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData ); + if ( FAILED(Status) || !ppSessionData ) + return FALSE; + + return TRUE; +} + +// IsKerberosLogon() does not validate whether or not there are valid +// tickets in the cache. It validates whether or not it is reasonable +// to assume that if we attempted to retrieve valid tickets we could +// do so. Microsoft does not automatically renew expired tickets. +// Therefore, the cache could contain expired or invalid tickets. +// Microsoft also caches the user's password and will use it to +// retrieve new TGTs if the cache is empty and tickets are requested. + +static BOOL +IsKerberosLogon(VOID) +{ + PSECURITY_LOGON_SESSION_DATA pSessionData = NULL; + BOOL Success = FALSE; + + if ( GetSecurityLogonSessionData(&pSessionData) ) { + if ( pSessionData->AuthenticationPackage.Buffer ) { + WCHAR buffer[256]; + WCHAR *usBuffer; + int usLength; + + Success = FALSE; + usBuffer = (pSessionData->AuthenticationPackage).Buffer; + usLength = (pSessionData->AuthenticationPackage).Length; + if (usLength < 256) + { + lstrcpynW (buffer, usBuffer, usLength); + StringCbCatW (buffer, sizeof(buffer), L""); + if ( !lstrcmpW(L"Kerberos",buffer) ) + Success = TRUE; + } + } + pLsaFreeReturnBuffer(pSessionData); + } + return Success; +} + + +BOOL +khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds, + khm_handle * ret_ident) +{ +#ifdef NO_KRB5 + return(FALSE); +#else /* NO_KRB5 */ + krb5_context kcontext = 0; + krb5_error_code code = 0; + krb5_ccache ccache=0; + krb5_ccache mslsa_ccache=0; + krb5_creds creds; + krb5_cc_cursor cursor=0; + krb5_principal princ = 0; + khm_handle ident = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + char ccname[KRB5_MAXCCH_CCNAME]; + char *cache_name = NULL; + char *princ_name = NULL; + BOOL rc = FALSE; + + kherr_reportf(L"Begin : khm_krb5_ms2mit. save_cred=%d\n", (int) save_creds); + + if ( !pkrb5_init_context ) + goto cleanup; + + if (code = pkrb5_init_context(&kcontext)) + goto cleanup; + + kherr_reportf(L"Resolving MSLSA\n"); + + if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if ( save_creds ) { + kherr_reportf(L"Getting principal\n"); + if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) + goto cleanup; + + kherr_reportf(L"Unparsing name\n"); + if (code = pkrb5_unparse_name(kcontext, princ, &princ_name)) + goto cleanup; + + AnsiStrToUnicode(idname, sizeof(idname), princ_name); + + kherr_reportf(L"Unparsed name [%s]", idname); + + /* see if we have to match a specific principal */ + if (match_princ != NULL) { + if (strcmp(princ_name, match_princ)) { + kherr_reportf(L"Principal mismatch. Wanted [%S], found [%S]", + match_princ, princ_name); + goto cleanup; + } + } else if (match_realm) { + wchar_t * wdefrealm; + char defrealm[256]; + krb5_data * princ_realm; + + wdefrealm = khm_krb5_get_default_realm(); + if (wdefrealm == NULL) { + kherr_reportf(L"Can't determine default realm"); + goto cleanup; + } + + princ_realm = krb5_princ_realm(kcontext, princ); + UnicodeStrToAnsi(defrealm, sizeof(defrealm), wdefrealm); + + if (strncmp(defrealm, princ_realm->data, princ_realm->length)) { + kherr_reportf(L"Realm mismatch. Wanted [%S], found [%*S]", + defrealm, princ_realm->length, princ_realm->data); + PFREE(wdefrealm); + goto cleanup; + } + + PFREE(wdefrealm); + } + + if (KHM_SUCCEEDED(kcdb_identity_create(idname, + KCDB_IDENT_FLAG_CREATE, + &ident))) { + khm_size cb; + + cb = sizeof(ccname); + + khm_krb5_get_identity_default_ccacheA(ident, ccname, &cb); + + cache_name = ccname; + + } else { + /* the identity could not be created. we just use the + name of the principal as the ccache name. */ +#ifdef DEBUG + assert(FALSE); +#endif + kherr_reportf(L"Failed to create identity"); + StringCbPrintfA(ccname, sizeof(ccname), "API:%s", princ_name); + cache_name = ccname; + } + + kherr_reportf(L"Resolving target cache [%S]\n", cache_name); + + if (code = pkrb5_cc_resolve(kcontext, cache_name, &ccache)) { + kherr_reportf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", cache_name, code); + + if (code = pkrb5_cc_default(kcontext, &ccache)) { + kherr_reportf(L"Failed to resolve default ccache. Code=%d", code); + goto cleanup; + } + } + + kherr_reportf(L"Initializing ccache\n"); + if (code = pkrb5_cc_initialize(kcontext, ccache, princ)) + goto cleanup; + + kherr_reportf(L"Copying credentials\n"); + if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) + goto cleanup; + + /* and mark the identity as having been imported */ + if (ident) { + khm_krb5_set_identity_flags(ident, K5IDFLAG_IMPORTED, K5IDFLAG_IMPORTED); + + if (ret_ident) { + *ret_ident = ident; + kcdb_identity_hold(*ret_ident); + } + } + + rc = TRUE; + + } else { + /* Enumerate tickets from cache looking for an initial ticket */ + if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) + goto cleanup; + + while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, + &cursor, &creds))) { + if ( creds.ticket_flags & TKT_FLG_INITIAL ) { + rc = TRUE; + pkrb5_free_cred_contents(kcontext, &creds); + break; + } + pkrb5_free_cred_contents(kcontext, &creds); + } + pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor); + } + +cleanup: + kherr_reportf(L" Received code=%d", code); + + if (princ_name) + pkrb5_free_unparsed_name(kcontext, princ_name); + if (princ) + pkrb5_free_principal(kcontext, princ); + if (ccache) + pkrb5_cc_close(kcontext, ccache); + if (mslsa_ccache) + pkrb5_cc_close(kcontext, mslsa_ccache); + if (kcontext) + pkrb5_free_context(kcontext); + if (ident) + kcdb_identity_release(ident); + + return(rc); +#endif /* NO_KRB5 */ +} + +#define KRB_FILE "KRB.CON" +#define KRBREALM_FILE "KRBREALM.CON" +#define KRB5_FILE "KRB5.INI" +#define KRB5_TMP_FILE "KRB5.INI.TMP" + +BOOL +khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname) +{ + GetTempPathA(szConfname, confname); + confname[szConfname-1] = '\0'; + StringCchCatA(confname, szConfname, KRB5_TMP_FILE); + confname[szConfname-1] = '\0'; + return FALSE; +} + +#ifdef NOT_QUITE_IMPLEMENTED_YET +BOOL +khm_krb5_set_profile_file(krb5_context ctx, LPSTR confname) +{ + char *conffiles[2]; + + if (confname == NULL || + pkrb5_set_config_files == NULL || + ctx == NULL) + return FALSE; + + conffiles[0] = confname; + conffiles[1] = NULL; + + if (pkrb5_set_config_files(ctx, conffiles)) + return FALSE; + else + return TRUE; +} +#endif + +BOOL +khm_krb5_get_profile_file(LPSTR confname, UINT szConfname) +{ + char **configFile = NULL; + if (pkrb5_get_default_config_files(&configFile)) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + + return FALSE; + } + + *confname = 0; + + if (configFile) + { + StringCchCopyA(confname, szConfname, *configFile); + pkrb5_free_config_files(configFile); + } + + if (!*confname) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + } + + return FALSE; +} + +BOOL +khm_get_krb4_con_file(LPSTR confname, UINT szConfname) +{ + if (hKrb5 && !hKrb4) { // hold krb.con where krb5.ini is located + CHAR krbConFile[MAX_PATH]=""; + LPSTR pFind; + + //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename); + if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) { + GetWindowsDirectoryA(krbConFile,sizeof(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + StringCchCatA(confname, szConfname, "\\"); + } + + pFind = strrchr(krbConFile, '\\'); + if (pFind) { + *pFind = '\0'; + StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), "\\"); + StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), KRB_FILE); + } + else + krbConFile[0] = '\0'; + + StringCchCopyA(confname, szConfname, krbConFile); + } + else if (hKrb4) { + size_t size = szConfname; + memset(confname, '\0', szConfname); + if (!pkrb_get_krbconf2(confname, &size)) + { // Error has happened + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB_FILE); + } + } + return FALSE; +} + +int +readstring(FILE * file, char * buf, int len) +{ + int c,i; + memset(buf, '\0', sizeof(buf)); + for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++) { + if (i < sizeof(buf)) { + if (c == '\n') { + buf[i] = '\0'; + return i; + } else { + buf[i] = (char) c; + } + } else { + if (c == '\n') { + buf[len-1] = '\0'; + return(i); + } + } + } + if (c == EOF) { + if (i > 0 && i < len) { + buf[i] = '\0'; + return(i); + } else { + buf[len-1] = '\0'; + return(-1); + } + } + return(-1); +} + +/*! \internal + \brief Return a list of configured realms + + The string that is returned is a set of null terminated unicode + strings, each of which denotes one realm. The set is terminated + by a zero length null terminated string. + + The caller should free the returned string using free() + + \return The string with the list of realms or NULL if the + operation fails. +*/ +wchar_t * +khm_krb5_get_realm_list(void) +{ + wchar_t * rlist = NULL; + + if (pprofile_get_subsection_names && pprofile_free_list) { + const char* rootSection[] = {"realms", NULL}; + const char** rootsec = rootSection; + char **sections = NULL, **cpp = NULL, *value = NULL; + + char krb5_conf[MAX_PATH+1]; + + if (!khm_krb5_get_profile_file(krb5_conf,sizeof(krb5_conf))) { + profile_t profile; + long retval; + const char *filenames[2]; + wchar_t * d; + size_t cbsize; + size_t t; + + filenames[0] = krb5_conf; + filenames[1] = NULL; + retval = pprofile_init(filenames, &profile); + if (!retval) { + retval = pprofile_get_subsection_names(profile, rootsec, + &sections); + + if (!retval) + { + /* first figure out how much space to allocate */ + cbsize = 0; + for (cpp = sections; *cpp; cpp++) + { + cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1); + } + cbsize += sizeof(wchar_t); /* double null terminated */ + + rlist = PMALLOC(cbsize); + d = rlist; + for (cpp = sections; *cpp; cpp++) + { + AnsiStrToUnicode(d, cbsize, *cpp); + t = wcslen(d) + 1; + d += t; + cbsize -= sizeof(wchar_t) * t; + } + *d = L'\0'; + } + + pprofile_free_list(sections); + +#if 0 + retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value); + if ( value ) { + disable_noaddresses = config_boolean_to_int(value); + pprofile_release_string(value); + } +#endif + pprofile_release(profile); + } + } + } else { + FILE * file; + char krb_conf[MAX_PATH+1]; + char * p; + size_t cbsize, t; + wchar_t * d; + + if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) && +#if _MSC_VER >= 1400 && __STDC_WANT_SECURE_LIB__ + !fopen_s(&file, krb_conf, "rt") +#else + (file = fopen(krb_conf, "rt")) +#endif + ) + { + char lineBuf[256]; + + /*TODO: compute the actual required buffer size instead of hardcoding */ + cbsize = 16384; // arbitrary + rlist = PMALLOC(cbsize); + d = rlist; + + // Skip the default realm + readstring(file,lineBuf,sizeof(lineBuf)); + + // Read the defined realms + while (TRUE) + { + if (readstring(file,lineBuf,sizeof(lineBuf)) < 0) + break; + + if (*(lineBuf + strlen(lineBuf) - 1) == '\r') + *(lineBuf + strlen(lineBuf) - 1) = 0; + + for (p=lineBuf; *p ; p++) + { + if (isspace(*p)) { + *p = 0; + break; + } + } + + if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) { + t = strlen(lineBuf) + 1; + if(cbsize > (1 + t*sizeof(wchar_t))) { + AnsiStrToUnicode(d, cbsize, lineBuf); + d += t; + cbsize -= t * sizeof(wchar_t); + } else + break; + } + } + + *d = L'\0'; + + fclose(file); + } + } + + return rlist; +} + +/*! \internal + \brief Get the default realm + + A string will be returned that specifies the default realm. The + caller should free the string using PFREE(). + + Returns NULL if the operation fails. +*/ +wchar_t * +khm_krb5_get_default_realm(void) +{ + wchar_t * realm; + size_t cch; + krb5_context ctx=0; + char * def = 0; + + pkrb5_init_context(&ctx); + + if (ctx == 0) + return NULL; + + pkrb5_get_default_realm(ctx,&def); + + if (def) { + cch = strlen(def) + 1; + realm = PMALLOC(sizeof(wchar_t) * cch); + AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def); + pkrb5_free_default_realm(ctx, def); + } else + realm = NULL; + + pkrb5_free_context(ctx); + + return realm; +} + +long +khm_krb5_set_default_realm(wchar_t * realm) { + krb5_context ctx=0; + char * def = 0; + long rv = 0; + char astr[K5_MAXCCH_REALM]; + + UnicodeStrToAnsi(astr, sizeof(astr), realm); + + pkrb5_init_context(&ctx); + pkrb5_get_default_realm(ctx,&def); + + if ((def && strcmp(def, astr)) || + !def) { + rv = pkrb5_set_default_realm(ctx, astr); + } + + if (def) { + pkrb5_free_default_realm(ctx, def); + } + + pkrb5_free_context(ctx); + + return rv; +} + +wchar_t * +khm_get_realm_from_princ(wchar_t * princ) { + wchar_t * t; + + if(!princ) + return NULL; + + for (t = princ; *t; t++) { + if(*t == L'\\') { /* escape */ + t++; + if(! *t) /* malformed */ + break; + } else if (*t == L'@') + break; + } + + if (*t == '@' && *(t+1) != L'\0') + return (t+1); + else + return NULL; +} + +long +khm_krb5_changepwd(char * principal, + char * password, + char * newpassword, + char** error_str) +{ + krb5_error_code rc = 0; + int result_code = 0; + krb5_data result_code_string, result_string; + krb5_context context = 0; + krb5_principal princ = 0; + krb5_get_init_creds_opt opts; + krb5_creds creds; + + result_string.data = 0; + result_code_string.data = 0; + + if ( !pkrb5_init_context ) + goto cleanup; + + if (rc = pkrb5_init_context(&context)) { + goto cleanup; + } + + if (rc = pkrb5_parse_name(context, principal, &princ)) { + goto cleanup; + } + + pkrb5_get_init_creds_opt_init(&opts); + pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); + pkrb5_get_init_creds_opt_set_renew_life(&opts, 0); + pkrb5_get_init_creds_opt_set_forwardable(&opts, 0); + pkrb5_get_init_creds_opt_set_proxiable(&opts, 0); + pkrb5_get_init_creds_opt_set_address_list(&opts,NULL); + + if (rc = pkrb5_get_init_creds_password(context, &creds, princ, + password, 0, 0, 0, + "kadmin/changepw", &opts)) { + if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) { +#if 0 + com_err(argv[0], 0, + "Password incorrect while getting initial ticket"); +#endif + } else { +#if 0 + com_err(argv[0], ret, "getting initial ticket"); +#endif + } + goto cleanup; + } + + if (rc = pkrb5_change_password(context, &creds, newpassword, + &result_code, &result_code_string, + &result_string)) { +#if 0 + com_err(argv[0], ret, "changing password"); +#endif + goto cleanup; + } + + if (result_code) { + int len = result_code_string.length + + (result_string.length ? (sizeof(": ") - 1) : 0) + + result_string.length; + if (len && error_str) { + *error_str = PMALLOC(len + 1); + if (*error_str) + StringCchPrintfA(*error_str, len+1, + "%.*s%s%.*s", + result_code_string.length, + result_code_string.data, + result_string.length?": ":"", + result_string.length, + result_string.data); + } + rc = result_code; + goto cleanup; + } + + cleanup: + if (result_string.data) + pkrb5_free_data_contents(context, &result_string); + + if (result_code_string.data) + pkrb5_free_data_contents(context, &result_code_string); + + if (princ) + pkrb5_free_principal(context, princ); + + if (context) + pkrb5_free_context(context); + + return rc; +} + +khm_int32 KHMAPI +khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy) { + if (kcdb_creds_comp_attr(vcred1, vcred2, KCDB_ATTR_LOCATION) || + kcdb_creds_comp_attr(vcred1, vcred2, attr_id_key_enctype) || + kcdb_creds_comp_attr(vcred1, vcred2, attr_id_tkt_enctype) || + kcdb_creds_comp_attr(vcred1, vcred2, attr_id_kvno)) + return 1; + else + return 0; +} + +void +khm_krb5_set_identity_flags(khm_handle identity, + khm_int32 flag_mask, + khm_int32 flag_value) { + + khm_int32 t = 0; + khm_size cb; + + cb = sizeof(t); + if (KHM_FAILED(kcdb_identity_get_attr(identity, + attr_id_krb5_idflags, + NULL, + &t, &cb))) { + t = 0; + } + + t &= ~flag_mask; + t |= (flag_value & flag_mask); + + kcdb_identity_set_attr(identity, + attr_id_krb5_idflags, + &t, sizeof(t)); +} + +khm_int32 +khm_krb5_get_identity_flags(khm_handle identity) { + khm_int32 t = 0; + khm_size cb; + + cb = sizeof(t); + kcdb_identity_get_attr(identity, + attr_id_krb5_idflags, + NULL, &t, &cb); + + return t; +} + +long +khm_krb5_get_temp_ccache(krb5_context ctx, + krb5_ccache * prcc) { + int rnd = rand(); + char ccname[MAX_PATH]; + long code = 0; + krb5_ccache cc = 0; + + StringCbPrintfA(ccname, sizeof(ccname), "MEMORY:TempCache%8x", rnd); + + code = pkrb5_cc_resolve(ctx, ccname, &cc); + + if (code == 0) + *prcc = cc; + + return code; +} + +/* + + The configuration information for each identity comes from a + multitude of layers organized as follows. The ordering is + decreasing in priority. When looking up a value, the value will be + looked up in each layer in turn starting at level 0. The first + instance of the value found will be the effective value. + + 0 : <identity configuration>\Krb5Cred + + 0.1: per user + + 0.2: per machine + + 1 : <plugin configuration>\Parameters\Realms\<realm of identity> + + 1.1: per user + + 1.2: per machine + + 2 : <plugin configuration>\Parameters + + 2.1: per user + + 2.2: per machine + + 2.3: schema + + */ +khm_int32 +khm_krb5_get_identity_config(khm_handle ident, + khm_int32 flags, + khm_handle * ret_csp) { + + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_i = NULL; + khm_handle csp_ik5 = NULL; + khm_handle csp_realms = NULL; + khm_handle csp_realm = NULL; + khm_handle csp_plugins = NULL; + khm_handle csp_krbcfg = NULL; + khm_handle csp_rv = NULL; + wchar_t realm[KCDB_IDENT_MAXCCH_NAME]; + + realm[0] = L'\0'; + + if (ident) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * trealm; + khm_size cb_idname = sizeof(idname); + + rv = kcdb_identity_get_name(ident, idname, &cb_idname); + if (KHM_SUCCEEDED(rv) && + (trealm = khm_get_realm_from_princ(idname)) != NULL) { + StringCbCopy(realm, sizeof(realm), trealm); + } + } + + if (ident) { + rv = kcdb_identity_get_config(ident, flags, &csp_i); + if (KHM_FAILED(rv)) + goto try_realm; + + rv = khc_open_space(csp_i, CSNAME_KRB5CRED, flags, &csp_ik5); + if (KHM_FAILED(rv)) + goto try_realm; + + try_realm: + + if (realm[0] == L'\0') + goto done_shadow_realm; + + rv = khc_open_space(csp_params, CSNAME_REALMS, flags, &csp_realms); + if (KHM_FAILED(rv)) + goto done_shadow_realm; + + rv = khc_open_space(csp_realms, realm, flags, &csp_realm); + if (KHM_FAILED(rv)) + goto done_shadow_realm; + + rv = khc_shadow_space(csp_realm, csp_params); + + done_shadow_realm: + + if (csp_ik5) { + if (csp_realm) + rv = khc_shadow_space(csp_ik5, csp_realm); + else + rv = khc_shadow_space(csp_ik5, csp_params); + + csp_rv = csp_ik5; + } else { + if (csp_realm) + csp_rv = csp_realm; + } + } + + if (csp_rv == NULL) { + + /* No valid identity specified or the specified identity + doesn't have any configuration. We default to the + parameters key. */ + + /* we don't just return csp_params since that's a global + handle that we shouldn't close until the plugin is + unloaded. The caller is going to close the returned handle + when it is done. So we need to create a new csp_params + that can safely be closed. */ + + rv = kmm_get_plugins_config(0, &csp_plugins); + if (KHM_FAILED(rv)) + goto done; + + rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, flags, &csp_krbcfg); + if (KHM_FAILED(rv)) + goto done; + + rv = khc_open_space(csp_krbcfg, CSNAME_PARAMS, flags, &csp_rv); + } + + done: + + *ret_csp = csp_rv; + + /* leave csp_ik5. If it's non-NULL, then it's the return value */ + /* leave csp_rv. It's the return value. */ + if (csp_i) + khc_close_space(csp_i); + if (csp_realms) + khc_close_space(csp_realms); + + /* csp_realm can also be a return value if csp_ik5 was NULL */ + if (csp_realm && csp_realm != csp_rv) + khc_close_space(csp_realm); + + if (csp_plugins) + khc_close_space(csp_plugins); + if (csp_krbcfg) + khc_close_space(csp_krbcfg); + + return rv; +} + +/* from get_in_tkt.c */ +static krb5_error_code +get_libdefault_string(profile_t profile, const char * realm, + const char * option, char ** ret_val) { + char realmstr[K5_MAXCCH_REALM]; + char **nameval = NULL; + const char * names[4]; + krb5_error_code code = 0; + + names[0] = "libdefaults"; + + if (!realm || !realm[0]) + goto try_number_two; + + StringCbCopyA(realmstr, sizeof(realmstr), realm); + + /* + * Try number one: + * + * [libdefaults] + * REALM = { + * option = <boolean> + * } + */ + + names[1] = realmstr; + names[2] = option; + names[3] = 0; + code = pprofile_get_values(profile, names, &nameval); + if (code == 0 && nameval && nameval[0]) + goto goodbye; + + try_number_two: + + /* + * Try number two: + * + * [libdefaults] + * option = <boolean> + */ + + names[1] = option; + names[2] = 0; + code = pprofile_get_values(profile, names, &nameval); + if (code == 0 && nameval && nameval[0]) + goto goodbye; + + goodbye: + if (!nameval) + return(ENOENT); + + if (!nameval[0]) { + code = ENOENT; + } else { + size_t cb; + + if (FAILED(StringCbLengthA(nameval[0], K5_MAXCCH_REALM * sizeof(char), &cb))) { + code = ENOMEM; + } else { + cb += sizeof(char); + *ret_val = PMALLOC(cb); + + if (!*ret_val) + code = ENOMEM; + else { + StringCbCopyA(*ret_val, cb, nameval[0]); + code = 0; + } + } + } + + pprofile_free_list(nameval); + + return code; +} + + +const struct escape_char_sequences { + wchar_t character; + wchar_t escape; +} file_cc_escapes[] = { + + /* in ASCII order */ + + {L'\"', L'd'}, + {L'$', L'$'}, + {L'%', L'r'}, + {L'\'', L'i'}, + {L'*', L's'}, + {L'/', L'f'}, + {L':', L'c'}, + {L'<', L'l'}, + {L'>', L'g'}, + {L'?', L'q'}, + {L'\\', L'b'}, + {L'|', L'p'} +}; + +static void +escape_string_for_filename(const wchar_t * s, + wchar_t * buf, + khm_size cb_buf) +{ + wchar_t * d; + int i; + + for (d = buf; *s && cb_buf > sizeof(wchar_t) * 3; s++) { + if (iswpunct(*s)) { + for (i=0; i < ARRAYLENGTH(file_cc_escapes); i++) { + if (*s == file_cc_escapes[i].character) + break; + } + + if (i < ARRAYLENGTH(file_cc_escapes)) { + *d++ = L'$'; + *d++ = file_cc_escapes[i].escape; + cb_buf -= sizeof(wchar_t) * 2; + continue; + } + } + + *d++ = *s; + cb_buf -= sizeof(wchar_t); + } + +#ifdef DEBUG + assert(cb_buf >= sizeof(wchar_t)); +#endif + *d++ = L'\0'; +} + +static khm_int32 +get_default_file_cache_for_identity(const wchar_t * idname, + wchar_t * ccname, + khm_size * pcb) +{ + wchar_t escf[KRB5_MAXCCH_CCNAME] = L""; + wchar_t tmppath[KRB5_MAXCCH_CCNAME] = L""; + wchar_t tccname[KRB5_MAXCCH_CCNAME]; + khm_size cb; + + escape_string_for_filename(idname, escf, sizeof(escf)); + GetTempPath(ARRAYLENGTH(tmppath), tmppath); + + /* The path returned by GetTempPath always ends in a backslash. */ + StringCbPrintf(tccname, sizeof(tccname), L"FILE:%skrb5cc.%s", tmppath, escf); + StringCbLength(tccname, sizeof(tccname), &cb); + cb += sizeof(wchar_t); + + if (ccname && *pcb >= cb) { + StringCbCopy(ccname, *pcb, tccname); + *pcb = cb; + return KHM_ERROR_SUCCESS; + } else { + *pcb = cb; + return KHM_ERROR_TOO_LONG; + } +} + +khm_int32 +khm_krb5_get_identity_default_ccache(khm_handle ident, wchar_t * buf, khm_size * pcb) { + khm_handle csp_id = NULL; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_size cbt; + + rv = khm_krb5_get_identity_config(ident, 0, &csp_id); + + cbt = *pcb; + if (KHM_SUCCEEDED(rv)) + rv = khc_read_string(csp_id, L"DefaultCCName", buf, &cbt); + + if ((KHM_FAILED(rv) && rv != KHM_ERROR_TOO_LONG) || + (KHM_SUCCEEDED(rv) && buf[0] == L'\0')) { + /* we need to figure out the default ccache from the principal + name */ + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + khm_size cb; + khm_int32 use_file_cache = 0; + + khc_read_int32(csp_id, L"DefaultToFileCache", &use_file_cache); + + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + + if (use_file_cache) { + cb = sizeof(ccname); + rv = get_default_file_cache_for_identity(idname, ccname, &cb); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + } else { /* generate an API: cache */ + StringCbPrintf(ccname, sizeof(ccname), L"API:%s", idname); + } + khm_krb5_canon_cc_name(ccname, sizeof(ccname)); + + _reportf(L"Setting CCache [%s] for identity [%s]", ccname, idname); + + StringCbLength(ccname, sizeof(ccname), &cb); + cb += sizeof(wchar_t); + + if (buf && *pcb >= cb) { + StringCbCopy(buf, *pcb, ccname); + *pcb = cb; + rv = KHM_ERROR_SUCCESS; + } else { + *pcb = cb; + rv = KHM_ERROR_TOO_LONG; + } + } else if (KHM_SUCCEEDED(rv)) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + *pcb = cbt; + + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + + _reportf(L"Found CCache [%s] for identity [%s]", buf, idname); + } + + if (csp_id != NULL) + khc_close_space(csp_id); + + return rv; +} + +khm_int32 +khm_krb5_get_identity_default_ccacheA(khm_handle ident, char * buf, khm_size * pcb) { + wchar_t wccname[KRB5_MAXCCH_CCNAME]; + khm_size cbcc; + khm_int32 rv; + + cbcc = sizeof(wccname); + rv = khm_krb5_get_identity_default_ccache(ident, wccname, &cbcc); + + if (KHM_SUCCEEDED(rv)) { + cbcc = sizeof(char) * cbcc / sizeof(wchar_t); + if (buf == NULL || *pcb < cbcc) { + *pcb = cbcc; + rv = KHM_ERROR_TOO_LONG; + } else { + UnicodeStrToAnsi(buf, *pcb, wccname); + *pcb = cbcc; + rv = KHM_ERROR_SUCCESS; + } + } + + return rv; +} + +khm_int32 +khm_krb5_get_identity_params(khm_handle ident, k5_params * p) { + + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_id = NULL; + khm_int32 regf = 0; + khm_int32 proff = 0; + khm_int32 e; + khm_int32 v; + CHAR confname[MAX_PATH]; + CHAR realmname[K5_MAXCCH_REALM]; + + ZeroMemory(p, sizeof(*p)); + + rv = khm_krb5_get_identity_config(ident, 0, &csp_id); + if (KHM_FAILED(rv)) + goto done_reg; + + +#define GETVAL(vname, vfield, flag) \ + do { \ + e = khc_value_exists(csp_id, vname); \ + rv = khc_read_int32(csp_id, vname, &v); \ + if (KHM_FAILED(rv)) goto done_reg; \ + p->vfield = v; \ + if ((e & ~KCONF_FLAG_SCHEMA) != 0) regf |= flag; \ + } while(FALSE) + + /* Flags */ + GETVAL(L"Renewable", renewable, K5PARAM_F_RENEW); + GETVAL(L"Forwardable", forwardable, K5PARAM_F_FORW); + GETVAL(L"Proxiable", proxiable, K5PARAM_F_PROX); + GETVAL(L"Addressless", addressless, K5PARAM_F_ADDL); + GETVAL(L"PublicIP", publicIP, K5PARAM_F_PUBIP); + + /* Lifetime */ + GETVAL(L"DefaultLifetime", lifetime, K5PARAM_F_LIFE); + GETVAL(L"MaxLifetime", lifetime_max, K5PARAM_F_LIFE_H); + GETVAL(L"MinLifetime", lifetime_min, K5PARAM_F_LIFE_L); + + /* Renewable lifetime */ + GETVAL(L"DefaultRenewLifetime", renew_life, K5PARAM_F_RLIFE); + GETVAL(L"MaxRenewLifetime", renew_life_max, K5PARAM_F_RLIFE_H); + GETVAL(L"MinRenewLifetime", renew_life_min, K5PARAM_F_RLIFE_L); + +#undef GETVAL + + done_reg: + + if (csp_id) + khc_close_space(csp_id); + + /* if all the parameters were read from the registry, then we have + no reason to read from the profile file. */ + if (regf == K5PARAM_FM_ALL) { + p->source_reg = regf; + return KHM_ERROR_SUCCESS; + } + + if (rv) + return rv; + + /* we need to figure out the realm name, since there might be + per-realm configuration in the profile file. */ + + realmname[0] = '\0'; + + if (ident) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + idname[0] = L'\0'; + cb = sizeof(idname); + rv = kcdb_identity_get_name(ident, idname, &cb); + if (KHM_SUCCEEDED(rv)) { + wchar_t * wrealm; + + wrealm = khm_get_realm_from_princ(idname); + if (wrealm) { + UnicodeStrToAnsi(realmname, sizeof(realmname), wrealm); + } + } + } + + /* If we get here, then some of the settings we read from the + configuration actually came from the schema. In other words, + the values weren't really defined for this identity. So we now + have to read the values from the krb5 configuration file. */ + + if (!khm_krb5_get_profile_file(confname, sizeof(confname))) { + profile_t profile; + const char * filenames[2]; + long retval; + + filenames[0] = confname; + filenames[1] = NULL; + + if (!pprofile_init(filenames, &profile)) { + + /* default ticket lifetime */ + if (!(regf & K5PARAM_F_LIFE)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "ticket_lifetime", &value); + + if (retval == 0 && value) { + krb5_deltat d; + + retval = pkrb5_string_to_deltat(value, &d); + if (retval == KRB5_DELTAT_BADFORMAT) { + /* Historically some sites use relations of + the form 'ticket_lifetime = 24000' where + the unit is left out but is assumed to be + seconds. Then there are other sites which + use the form 'ticket_lifetime = 600' where + the unit is assumed to be minutes. While + these are technically wrong (a unit needs + to be specified), we try to accomodate for + this using the safe assumption that the + unit is seconds and tack an 's' to the end + and see if that works. */ + + size_t cch; + char tmpbuf[256]; + char * buf; + + do { + if (FAILED(StringCchLengthA(value, 1024 /* unresonably large size */, + &cch))) + break; + + cch += sizeof(char) * 2; /* NULL and new 's' */ + if (cch > ARRAYLENGTH(tmpbuf)) + buf = PMALLOC(cch * sizeof(char)); + else + buf = tmpbuf; + + StringCchCopyA(buf, cch, value); + StringCchCatA(buf, cch, "s"); + + retval = pkrb5_string_to_deltat(buf, &d); + if (retval == 0) { + p->lifetime = d; + proff |= K5PARAM_F_LIFE; + } + + if (buf != tmpbuf) + PFREE(buf); + + } while(0); + + } else if (retval == 0) { + p->lifetime = d; + proff |= K5PARAM_F_LIFE; + } + + PFREE(value); + } + } + + if (!(regf & K5PARAM_F_RLIFE)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "renew_lifetime", &value); + if (retval == 0 && value) { + krb5_deltat d; + + retval = pkrb5_string_to_deltat(value, &d); + if (retval == 0) { + p->renew_life = d; + proff |= K5PARAM_F_RLIFE; + } + PFREE(value); + } + } + + if (!(regf & K5PARAM_F_FORW)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "forwardable", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->forwardable = b; + else + p->forwardable = FALSE; + PFREE(value); + proff |= K5PARAM_F_FORW; + } + } + + if (!(regf & K5PARAM_F_RENEW)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "renewable", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->renewable = b; + else + p->renewable = TRUE; + PFREE(value); + proff |= K5PARAM_F_RENEW; + } + } + + if (!(regf & K5PARAM_F_ADDL)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "noaddresses", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->addressless = b; + else + p->addressless = TRUE; + PFREE(value); + proff |= K5PARAM_F_ADDL; + } + } + + if (!(regf & K5PARAM_F_PROX)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "proxiable", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->proxiable = b; + else + p->proxiable = FALSE; + PFREE(value); + proff |= K5PARAM_F_PROX; + } + } + + pprofile_release(profile); + } + } + + p->source_reg = regf; + p->source_prof = proff; + + return rv; +} + +/* Note that p->source_reg and p->source_prof is used in special ways + here. All fields that are flagged in source_reg will be written to + the configuration (if they are different from what + khm_krb5_get_identity_params() reports). All fields that are + flagged in source_prof will be removed from the configuration + (thereby exposing the value defined in the profile file). */ +khm_int32 +khm_krb5_set_identity_params(khm_handle ident, const k5_params * p) { + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_id = NULL; + k5_params p_s; + khm_int32 source_reg = p->source_reg; + khm_int32 source_prof = p->source_prof; + + rv = khm_krb5_get_identity_config(ident, + KHM_PERM_WRITE | KHM_FLAG_CREATE | + KCONF_FLAG_WRITEIFMOD, + &csp_id); + if (KHM_FAILED(rv)) + goto done_reg; + + khm_krb5_get_identity_params(ident, &p_s); + + /* Remove any bits that don't make sense. Not all values can be + specified in the profile file. */ + source_prof &= K5PARAM_FM_PROF; + + /* if a flag appears in both source_prof and source_reg, remove + the flag from source_reg. */ + source_reg &= ~source_prof; + + /* we only write values that have changed, and that are flagged in + source_reg */ + + if ((source_reg & K5PARAM_F_RENEW) && + !!p_s.renewable != !!p->renewable) + khc_write_int32(csp_id, L"Renewable", !!p->renewable); + + if ((source_reg & K5PARAM_F_FORW) && + !!p_s.forwardable != !!p->forwardable) + khc_write_int32(csp_id, L"Forwardable", !!p->forwardable); + + if ((source_reg & K5PARAM_F_PROX) && + !!p_s.proxiable != !!p->proxiable) + khc_write_int32(csp_id, L"Proxiable", !!p->proxiable); + + if ((source_reg & K5PARAM_F_ADDL) && + !!p_s.addressless != !!p->addressless) + khc_write_int32(csp_id, L"Addressless", !!p->addressless); + + if ((source_reg & K5PARAM_F_PUBIP) && + p_s.publicIP != p->publicIP) + khc_write_int32(csp_id, L"PublicIP", p->publicIP); + + if ((source_reg & K5PARAM_F_LIFE) && + p_s.lifetime != p->lifetime) + khc_write_int32(csp_id, L"DefaultLifetime", p->lifetime); + + if ((source_reg & K5PARAM_F_LIFE_H) && + p_s.lifetime_max != p->lifetime_max) + khc_write_int32(csp_id, L"MaxLifetime", p->lifetime_max); + + if ((source_reg & K5PARAM_F_LIFE_L) && + p_s.lifetime_min != p->lifetime_min) + khc_write_int32(csp_id, L"MinLifetime", p->lifetime_min); + + if ((source_reg & K5PARAM_F_RLIFE) && + p_s.renew_life != p->renew_life) + khc_write_int32(csp_id, L"DefaultRenewLifetime", p->renew_life); + + if ((source_reg & K5PARAM_F_RLIFE_H) && + p_s.renew_life_max != p->renew_life_max) + khc_write_int32(csp_id, L"MaxRenewLifetime", p->renew_life_max); + + if ((source_reg & K5PARAM_F_RLIFE_L) && + p_s.renew_life_min != p->renew_life_min) + khc_write_int32(csp_id, L"MinRenewLifetime", p->renew_life_min); + + /* and now, remove the values that are present in source_prof. + Not all values are removed since not all values can be + specified in the profile file. */ + if (source_prof & K5PARAM_F_RENEW) + khc_remove_value(csp_id, L"Renewable", 0); + + if (source_prof & K5PARAM_F_FORW) + khc_remove_value(csp_id, L"Forwardable", 0); + + if (source_prof & K5PARAM_F_PROX) + khc_remove_value(csp_id, L"Proxiable", 0); + + if (source_prof & K5PARAM_F_ADDL) + khc_remove_value(csp_id, L"Addressless", 0); + + if (source_prof & K5PARAM_F_LIFE) + khc_remove_value(csp_id, L"DefaultLifetime", 0); + + if (source_prof & K5PARAM_F_RLIFE) + khc_remove_value(csp_id, L"DefaultRenewLifetime", 0); + + done_reg: + if (csp_id != NULL) + khc_close_space(csp_id); + + return rv; +} + +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +int +khm_krb5_parse_boolean(const char *s, khm_boolean * b) +{ + const char *const *p; + + for(p=conf_yes; *p; p++) { + if (!_stricmp(*p,s)) { + *b = TRUE; + return 0; + } + } + + for(p=conf_no; *p; p++) { + if (!_stricmp(*p,s)) { + *b = FALSE; + return 0; + } + } + + /* Default to "no" */ + return KHM_ERROR_INVALID_PARAM; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.h b/krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.h new file mode 100644 index 000000000..990db269d --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5funcs.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Adapted from multiple Leash header files */ + +#ifndef __KHIMAIRA_KRB5FUNCS_H +#define __KHIMAIRA_KRB5FUNCS_H + +#include<stdlib.h> +#include<krb5.h> + +#include <windows.h> +#define SECURITY_WIN32 +#include <security.h> + +#if _WIN32_WINNT < 0x0501 +#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include<ntsecapi.h> +#ifdef KHM_SAVE_WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT +#undef KHM_SAVE_WIN32_WINNT +#endif + +#include <krb5common.h> + +#define LEASH_DEBUG_CLASS_GENERIC 0 +#define LEASH_DEBUG_CLASS_KRB4 1 +#define LEASH_DEBUG_CLASS_KRB4_APP 2 + +#define LEASH_PRIORITY_LOW 0 +#define LEASH_PRIORITY_HIGH 1 + +#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */ + +#define KRB5_MAXCCH_CCNAME 1024 + +#define KRB5_CONF_YES "yes" +#define KRB5_CONF_NO "no" + +typedef struct tag_k5params { + + khm_int32 source_reg; /* flags indicating which fields were + retrieved using the registry */ + khm_int32 source_prof; /* flags indicating which fields were + retrieved using krb5.ini */ + + khm_boolean renewable; + khm_boolean forwardable; + khm_boolean proxiable; + khm_boolean addressless; + + khm_ui_4 publicIP; + + krb5_deltat lifetime; + krb5_deltat lifetime_min; + krb5_deltat lifetime_max; + + krb5_deltat renew_life; + krb5_deltat renew_life_min; + krb5_deltat renew_life_max; + +} k5_params; + +#define K5PARAM_F_RENEW 0x00000001 +#define K5PARAM_F_FORW 0x00000002 +#define K5PARAM_F_PROX 0x00000004 +#define K5PARAM_F_ADDL 0x00000008 +#define K5PARAM_F_PUBIP 0x00000010 +#define K5PARAM_F_LIFE 0x00000020 +#define K5PARAM_F_RLIFE 0x00000040 +#define K5PARAM_F_LIFE_L 0x00000080 +#define K5PARAM_F_LIFE_H 0x00000100 +#define K5PARAM_F_RLIFE_L 0x00000200 +#define K5PARAM_F_RLIFE_H 0x00000400 + +#define K5PARAM_FM_ALL 0x000007ff +#define K5PARAM_FM_PROF 0x0000007f + +/* Credential and principal operations */ + +BOOL +khm_krb5_ms2mit(char * match_princ, + BOOL match_realm, + BOOL save_creds, + khm_handle * ret_ident); + +int +khm_krb5_kinit(krb5_context alt_ctx, + char * principal_name, + char * password, + char * ccache, + krb5_deltat lifetime, + DWORD forwardable, + DWORD proxiable, + krb5_deltat renew_life, + DWORD addressless, + DWORD publicIP, + krb5_prompter_fct prompter, + void * p_data); + +long +khm_krb5_changepwd(char * principal, + char * password, + char * newpassword, + char** error_str); + +int +khm_krb5_destroy_by_credset(khm_handle p_cs); + +int +khm_krb5_destroy_identity(khm_handle identity); + +long +khm_convert524(krb5_context ctx); + +int +khm_krb5_renew_cred(khm_handle cred); + +int +khm_krb5_renew_ident(khm_handle identity); + +long +khm_krb5_list_tickets(krb5_context *krbv5Context); + +long +khm_krb5_copy_ccache_by_name(krb5_context in_ctx, + wchar_t * wscc_dest, + wchar_t * wscc_src); + +long +khm_krb5_get_temp_ccache(krb5_context ctx, + krb5_ccache * cc); + +khm_int32 KHMAPI +khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy); + + +/* Configuration */ + +BOOL +khm_krb5_get_profile_file(LPSTR confname, UINT szConfname); + +BOOL +khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname); + +wchar_t * +khm_krb5_get_default_realm(void); + +long +khm_krb5_set_default_realm(wchar_t * realm); + +wchar_t * +khm_krb5_get_realm_list(void); + +khm_int32 +khm_krb5_get_identity_config(khm_handle ident, + khm_int32 flags, + khm_handle * ret_csp); + +void +khm_krb5_set_identity_flags(khm_handle identity, + khm_int32 flag_mask, + khm_int32 flag_value); + +khm_int32 +khm_krb5_get_identity_flags(khm_handle identity); + +khm_int32 +khm_krb5_set_identity_params(khm_handle ident, const k5_params * p); + +khm_int32 +khm_krb5_get_identity_params(khm_handle ident, k5_params * p); + +khm_int32 +khm_krb5_get_identity_default_ccache(khm_handle ident, wchar_t * buf, khm_size * pcb); + +khm_int32 +khm_krb5_get_identity_default_ccacheA(khm_handle ident, char * buf, khm_size * pcb); + +/* Utility */ + +wchar_t * +khm_get_realm_from_princ(wchar_t * princ); + +long +khm_krb5_canon_cc_name(wchar_t * wcc_name, + size_t cb_cc_name); + +int +khm_krb5_cc_name_cmp(const wchar_t * cc_name_1, + const wchar_t * cc_name_2); + +int +khm_krb5_parse_boolean(const char *s, khm_boolean * b); + +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5identpro.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5identpro.c new file mode 100644 index 000000000..996918351 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5identpro.c @@ -0,0 +1,1861 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<commctrl.h> +#include<strsafe.h> +#include<krb5.h> +#include<assert.h> + +#define K5_NCID_UN_LABEL (KHUI_CW_ID_MIN + 0) +#define K5_NCID_UN (KHUI_CW_ID_MIN + 1) +#define K5_NCID_REALM_LABEL (KHUI_CW_ID_MIN + 2) +#define K5_NCID_REALM (KHUI_CW_ID_MIN + 3) + +#define NC_UNCHANGE_TIMEOUT 3000 +#define NC_UNCHANGE_TIMER 2 +#define NC_REALMCHANGE_TIMEOUT NC_UNCHANGE_TIMEOUT +#define NC_REALMCHANGE_TIMER 3 + +typedef struct tag_k5_new_cred_data { + HWND hw_username_label; + HWND hw_username; + HWND hw_realm_label; + HWND hw_realm; +} k5_new_cred_data; + +static +void +trim_str(wchar_t * s, khm_size cch) { + wchar_t * c, * last_ws; + + for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++); + + if (((khm_size)(c - s)) >= cch) + return; + + if (c != s && ((khm_size)(c - s)) < cch) { +#if _MSC_VER >= 1400 && __STDC_WANT_SECURE_LIB__ + wmemmove_s(s, cch, c, cch - ((khm_size)(c - s))); +#else + memmove(s, c, (cch - ((khm_size)(c - s))) * sizeof(wchar_t)); +#endif + } + + last_ws = NULL; + for (c = s; *c && ((khm_size)(c - s)) < cch; c++) { + if (!iswspace(*c)) + last_ws = NULL; + else if (last_ws == NULL) + last_ws = c; + } + + if (last_ws) + *last_ws = L'\0'; +} + +/* Runs in the UI thread */ +int +k5_get_realm_from_nc(khui_new_creds * nc, + wchar_t * buf, + khm_size cch_buf) { + k5_new_cred_data * d; + khm_size s; + + d = (k5_new_cred_data *) nc->ident_aux; + buf[0] = L'\0'; + GetWindowText(d->hw_realm, buf, (int) cch_buf); + trim_str(buf, cch_buf); + + StringCchLength(buf, cch_buf, &s); + + return (int) s; +} + +/* set the primary identity of a new credentials dialog depending on + the selection of the username and realm + + Runs in the UI thread +*/ +static void +set_identity_from_ui(khui_new_creds * nc, + k5_new_cred_data * d) { + wchar_t un[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * realm; + khm_size cch; + khm_size cch_left; + khm_handle ident; + LRESULT idx = CB_ERR; + khm_int32 rv = KHM_ERROR_SUCCESS; + + cch = GetWindowTextLength(d->hw_username); + + /* we already set the max length of the edit control to be this. + shouldn't exceed it unless the edit control is confused. */ + assert(cch < KCDB_IDENT_MAXCCH_NAME - 1); + + GetWindowText(d->hw_username, un, ARRAYLENGTH(un)); + trim_str(un, ARRAYLENGTH(un)); + + realm = khm_get_realm_from_princ(un); + if (realm) /* realm was specified */ + goto _set_ident; + + /* the cch we got from GetWindowTextLength can not be trusted to + be exact. For caveats see MSDN for GetWindowTextLength. */ + StringCchLength(un, KCDB_IDENT_MAXCCH_NAME, &cch); + + if (cch >= KCDB_IDENT_MAXCCH_NAME - 3) { + /* has to allow space for the '@' and at least a single + character realm, and the NULL terminator. */ + rv = KHM_ERROR_TOO_LONG; + goto _set_null_ident; + } + + realm = un + cch; /* now points at terminating NULL */ + cch_left = KCDB_IDENT_MAXCCH_NAME - cch; + + *realm++ = L'@'; + *realm = L'\0'; + cch_left--; + + cch = GetWindowTextLength(d->hw_realm); + if (cch == 0 || cch >= cch_left) { + rv = KHM_ERROR_INVALID_NAME; + goto _set_null_ident; + } + + GetWindowText(d->hw_realm, realm, (int) cch_left); + trim_str(realm, cch_left); + + _set_ident: + if (KHM_FAILED(rv = kcdb_identity_create(un, + KCDB_IDENT_FLAG_CREATE, + &ident))) { + goto _set_null_ident; + } + + khui_cw_set_primary_id(nc, ident); + + kcdb_identity_release(ident); + return; + + _set_null_ident: + { + khui_new_creds_by_type * nct = NULL; + wchar_t cmsg[256]; + + khui_cw_find_type(nc, credtype_id_krb5, &nct); + if (nct && nct->hwnd_panel) { + + switch(rv) { + case KHM_ERROR_TOO_LONG: + LoadString(hResModule, IDS_NCERR_IDENT_TOO_LONG, + cmsg, ARRAYLENGTH(cmsg)); + break; + + case KHM_ERROR_INVALID_NAME: + LoadString(hResModule, IDS_NCERR_IDENT_INVALID, + cmsg, ARRAYLENGTH(cmsg)); + break; + + default: + LoadString(hResModule, IDS_NCERR_IDENT_UNKNOWN, + cmsg, ARRAYLENGTH(cmsg)); + } + + SendMessage(nct->hwnd_panel, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, K5_SET_CRED_MSG), + (LPARAM) cmsg); + } + + khui_cw_set_primary_id(nc, NULL); + } + return; +} + +/* runs in the UI thread */ +static BOOL +update_crossfeed(khui_new_creds * nc, + k5_new_cred_data * d, + int ctrl_id_src) { + wchar_t un[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * un_realm; + wchar_t realm[KCDB_IDENT_MAXCCH_NAME]; + khm_size cch; + khm_size cch_left; + int idx; + + cch = (khm_size) GetWindowTextLength(d->hw_username); +#ifdef DEBUG + assert(cch < KCDB_IDENT_MAXCCH_NAME); +#endif + if (cch == 0) + return FALSE; + + GetWindowText(d->hw_username, + un, + ARRAYLENGTH(un)); + trim_str(un, ARRAYLENGTH(un)); + + un_realm = khm_get_realm_from_princ(un); + + if (un_realm == NULL) { + EnableWindow(d->hw_realm, TRUE); + return FALSE; + } + + if (ctrl_id_src == K5_NCID_UN) { + + idx = (int)SendMessage(d->hw_realm, + CB_FINDSTRINGEXACT, + (WPARAM) -1, + (LPARAM) un_realm); + + if (idx != CB_ERR) { + wchar_t srealm[KCDB_IDENT_MAXCCH_NAME]; + + cch = SendMessage(d->hw_realm, + CB_GETLBTEXTLEN, + (WPARAM) idx, + 0); + +#ifdef DEBUG + assert(cch < ARRAYLENGTH(srealm) - 1); +#endif + SendMessage(d->hw_realm, + CB_GETLBTEXT, + (WPARAM) idx, + (LPARAM) srealm); + + if (!_wcsicmp(srealm, un_realm) && wcscmp(srealm, un_realm)) { + /* differ only by case */ + + StringCchCopy(un_realm, ARRAYLENGTH(un) - (un_realm - un), + srealm); + + SetWindowText(d->hw_username, un); + } + } + + SendMessage(d->hw_realm, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) un_realm); + + SetWindowText(d->hw_realm, + un_realm); + + if (GetFocus() == d->hw_realm) { + HWND hw_next = GetNextDlgTabItem(nc->hwnd, d->hw_realm, + FALSE); + if (hw_next) + SetFocus(hw_next); + } + + EnableWindow(d->hw_realm, FALSE); + + return TRUE; + } + /* else... */ + + cch_left = KCDB_IDENT_MAXCCH_NAME - (un_realm - un); + + cch = (khm_size) GetWindowTextLength(d->hw_realm); + +#ifdef DEBUG + assert(cch < KCDB_IDENT_MAXCCH_NAME); +#endif + if (cch == 0) + return FALSE; + + GetWindowText(d->hw_realm, realm, + ARRAYLENGTH(realm)); + trim_str(realm, ARRAYLENGTH(realm)); + + idx = (int)SendMessage(d->hw_realm, + CB_FINDSTRINGEXACT, + (WPARAM) -1, + (LPARAM) realm); + + if (idx != CB_ERR) { + wchar_t srealm[KCDB_IDENT_MAXCCH_NAME]; + + SendMessage(d->hw_realm, + CB_GETLBTEXT, + (WPARAM) idx, + (LPARAM) srealm); + + if (!_wcsicmp(srealm, realm) && wcscmp(srealm, realm)) { + StringCbCopy(realm, sizeof(realm), srealm); + + SetWindowText(d->hw_realm, srealm); + } + } + + StringCchCopy(un_realm, cch_left, realm); + + SendMessage(d->hw_username, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) un); + + SetWindowText(d->hw_username, un); + + return TRUE; +} + +/* Handle window messages for the identity specifiers + + runs in UI thread */ +static LRESULT +handle_wnd_msg(khui_new_creds * nc, + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + k5_new_cred_data * d; + + d = (k5_new_cred_data *) nc->ident_aux; + + switch(uMsg) { + case WM_COMMAND: + switch(wParam) { + case MAKEWPARAM(K5_NCID_UN, CBN_EDITCHANGE): + /* the username has changed. Instead of handling this + for every keystroke, set a timer that elapses some + time afterwards and then handle the event. */ + SetTimer(hwnd, NC_UNCHANGE_TIMER, + NC_UNCHANGE_TIMEOUT, NULL); + return TRUE; + + case MAKEWPARAM(K5_NCID_UN, CBN_KILLFOCUS): + case MAKEWPARAM(K5_NCID_UN, CBN_CLOSEUP): + KillTimer(hwnd, NC_UNCHANGE_TIMER); + + update_crossfeed(nc,d,K5_NCID_UN); + set_identity_from_ui(nc,d); + return TRUE; + + case MAKEWPARAM(K5_NCID_REALM,CBN_EDITCHANGE): + SetTimer(hwnd, NC_REALMCHANGE_TIMER, + NC_REALMCHANGE_TIMEOUT, NULL); + return TRUE; + + case MAKEWPARAM(K5_NCID_REALM,CBN_KILLFOCUS): + case MAKEWPARAM(K5_NCID_REALM,CBN_CLOSEUP): + KillTimer(hwnd, NC_REALMCHANGE_TIMER); + + update_crossfeed(nc,d,K5_NCID_REALM); + set_identity_from_ui(nc, d); + return TRUE; + } + break; + + case WM_TIMER: + if(wParam == NC_UNCHANGE_TIMER) { + KillTimer(hwnd, NC_UNCHANGE_TIMER); + + update_crossfeed(nc, d, K5_NCID_UN); + set_identity_from_ui(nc,d); + return TRUE; + } else if (wParam == NC_REALMCHANGE_TIMER) { + KillTimer(hwnd, NC_REALMCHANGE_TIMER); + + update_crossfeed(nc, d, K5_NCID_REALM); + set_identity_from_ui(nc, d); + return TRUE; + } + break; + } + return FALSE; +} + +/* UI Callback + + runs in UI thread */ +static LRESULT KHMAPI +ui_cb(khui_new_creds * nc, + UINT cmd, + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + k5_new_cred_data * d; + + d = (k5_new_cred_data *) nc->ident_aux; + + switch(cmd) { + case WMNC_IDENT_INIT: + { + wchar_t defident[KCDB_IDENT_MAXCCH_NAME]; + wchar_t wbuf[1024]; + wchar_t * ms = NULL; + wchar_t * t; + wchar_t * defrealm = NULL; + LRESULT lr; + khm_size cb_ms; + khm_size cb; + HWND hw_parent; + khm_int32 rv; + khm_handle hident; + + hw_parent = (HWND) lParam; + defident[0] = L'\0'; + +#ifdef DEBUG + assert(d == NULL); + assert(hw_parent != NULL); +#endif + + d = PMALLOC(sizeof(*d)); + assert(d); + ZeroMemory(d, sizeof(*d)); + + khui_cw_lock_nc(nc); + nc->ident_aux = (LPARAM) d; + khui_cw_unlock_nc(nc); + + LoadString(hResModule, IDS_NC_USERNAME, + wbuf, ARRAYLENGTH(wbuf)); + + d->hw_username_label = CreateWindow + (L"STATIC", + wbuf, + SS_SIMPLE | WS_CHILD | WS_VISIBLE, + 0, 0, 100, 100, /* bogus values */ + hw_parent, + (HMENU) K5_NCID_UN_LABEL, + hInstance, + NULL); + assert(d->hw_username_label != NULL); + + d->hw_username = CreateWindow + (L"COMBOBOX", + L"", + CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL, + 0, 0, 100, 100, /* bogus values */ + hw_parent, + (HMENU) K5_NCID_UN, + hInstance, + NULL); + assert(d->hw_username != NULL); + + SendMessage(d->hw_username, + CB_LIMITTEXT, + (WPARAM)(KCDB_IDENT_MAXCCH_NAME - 1), + 0); + + SendMessage(d->hw_username, + CB_SETEXTENDEDUI, + (WPARAM) TRUE, + 0); + + khui_cw_add_control_row(nc, + d->hw_username_label, + d->hw_username, + KHUI_CTRLSIZE_SMALL); + + LoadString(hResModule, IDS_NC_REALM, + wbuf, ARRAYLENGTH(wbuf)); + + d->hw_realm_label = CreateWindow + (L"STATIC", + wbuf, + SS_SIMPLE | WS_CHILD | WS_VISIBLE, + 0, 0, 100, 100, /* bogus */ + hw_parent, + (HMENU) K5_NCID_REALM_LABEL, + hInstance, + NULL); + assert(d->hw_realm_label != NULL); + + d->hw_realm = CreateWindow + (L"COMBOBOX", + L"", + CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL, + 0, 0, 100, 100, /* bogus */ + hw_parent, + (HMENU) K5_NCID_REALM, + hInstance, + NULL); + assert(d->hw_realm != NULL); + + SendMessage(d->hw_realm, + CB_LIMITTEXT, + (WPARAM) (KCDB_IDENT_MAXCCH_NAME - 1), + 0); + + SendMessage(d->hw_realm, + CB_SETEXTENDEDUI, + (WPARAM) TRUE, + 0); + + khui_cw_add_control_row(nc, + d->hw_realm_label, + d->hw_realm, + KHUI_CTRLSIZE_SMALL); + + /* add the LRU realms and principals to the dropdown + lists */ + rv = khc_read_multi_string(csp_params, + L"LRUPrincipals", + NULL, + &cb_ms); + + if (rv != KHM_ERROR_TOO_LONG || cb_ms <= sizeof(wchar_t) * 2) + goto _add_lru_realms; + + ms = PMALLOC(cb_ms); + assert(ms != NULL); + + cb = cb_ms; + rv = khc_read_multi_string(csp_params, + L"LRUPrincipals", + ms, + &cb); + + assert(KHM_SUCCEEDED(rv)); + + /* the first of these is considered the default identity + if no other default is known */ + StringCbCopy(defident, sizeof(defident), ms); + + t = ms; + while(t && *t) { + SendMessage(d->hw_username, + CB_ADDSTRING, + 0, + (LPARAM) t); + + t = multi_string_next(t); + } + + _add_lru_realms: + /* add the default realm first */ + defrealm = khm_krb5_get_default_realm(); + if (defrealm) { + SendMessage(d->hw_realm, + CB_ADDSTRING, + 0, + (LPARAM) defrealm); + } + + rv = khc_read_multi_string(csp_params, + L"LRURealms", + NULL, + &cb); + + if (rv != KHM_ERROR_TOO_LONG) + goto _done_adding_lru; + + if (ms != NULL) { + if (cb_ms < cb) { + PFREE(ms); + ms = PMALLOC(cb); + assert(ms); + cb_ms = cb; + } + } else { + ms = PMALLOC(cb); + cb_ms = cb; + } + + rv = khc_read_multi_string(csp_params, + L"LRURealms", + ms, + &cb); + + assert(KHM_SUCCEEDED(rv)); + + for (t = ms; t && *t; t = multi_string_next(t)) { + lr = SendMessage(d->hw_realm, + CB_FINDSTRINGEXACT, + (WPARAM) -1, + (LPARAM) t); + if (lr != CB_ERR) + continue; + + SendMessage(d->hw_realm, + CB_ADDSTRING, + 0, + (LPARAM) t); + } + _done_adding_lru: + + { + khm_int32 inc_realms = 0; + + if (KHM_FAILED(khc_read_int32(csp_params, + L"UseFullRealmList", + &inc_realms)) || + !inc_realms) + goto _done_adding_all_realms; + } + + if(ms) + PFREE(ms); + + ms = khm_krb5_get_realm_list(); + if(ms) { + for (t = ms; t && *t; t = multi_string_next(t)) { + lr = SendMessage(d->hw_realm, + CB_FINDSTRINGEXACT, + (WPARAM) -1, + (LPARAM) t); + if (lr != CB_ERR) + continue; + + SendMessage(d->hw_realm, + CB_ADDSTRING, + 0, + (LPARAM) t); + } + } + _done_adding_all_realms: + + /* set the current selection of the realms list */ + if (defrealm) { + SendMessage(d->hw_realm, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) defrealm); + } else { + SendMessage(d->hw_realm, + CB_SETCURSEL, + (WPARAM) 0, + (LPARAM) 0); + } + + if (defrealm) + PFREE(defrealm); + + if (ms) + PFREE(ms); + + /* now see about that default identity */ + if (nc->ctx.identity) { + cb = sizeof(defident); + kcdb_identity_get_name(nc->ctx.identity, + defident, + &cb); + } + + if (defident[0] == L'\0' && + KHM_SUCCEEDED(kcdb_identity_get_default(&hident))) { + cb = sizeof(defident); + kcdb_identity_get_name(hident, defident, &cb); + kcdb_identity_release(hident); + } + + if (defident[0] == L'\0') { + DWORD dw; + + dw = ARRAYLENGTH(defident); + GetUserName(defident, &dw); + } + + t = khm_get_realm_from_princ(defident); + if (t) { + /* there is a realm */ + assert(t != defident); + *--t = L'\0'; + t++; + + SendMessage(d->hw_realm, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) t); + + SendMessage(d->hw_realm, + WM_SETTEXT, + 0, + (LPARAM) t); + } + + if (defident[0] != L'\0') { + /* there is a username */ + SendMessage(d->hw_username, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) defident); + + SendMessage(d->hw_username, + WM_SETTEXT, + 0, + (LPARAM) defident); + } + + set_identity_from_ui(nc, d); + } + return TRUE; + + case WMNC_IDENT_WMSG: + return handle_wnd_msg(nc, hwnd, uMsg, wParam, lParam); + + case WMNC_IDENT_PREPROCESS: + { +#ifdef DEBUG + assert(d != NULL); +#endif + if (d) { + set_identity_from_ui(nc, d); + } + } + return TRUE; + + case WMNC_IDENT_EXIT: + { +#ifdef DEBUG + assert(d != NULL); +#endif + khui_cw_lock_nc(nc); + nc->ident_aux = 0; + khui_cw_unlock_nc(nc); + + /* since we created all the windows as child windows of + the new creds window, they will be destroyed when that + window is destroyed. */ + PFREE(d); + } + return TRUE; + } + return FALSE; +} + +static khm_int32 +k5_ident_validate_name(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + krb5_principal princ = NULL; + char princ_name[KCDB_IDENT_MAXCCH_NAME]; + kcdb_ident_name_xfer * nx; + krb5_error_code code; + wchar_t * atsign; + + nx = (kcdb_ident_name_xfer *) vparam; + + if(UnicodeStrToAnsi(princ_name, sizeof(princ_name), + nx->name_src) == 0) { + nx->result = KHM_ERROR_INVALID_NAME; + return KHM_ERROR_SUCCESS; + } + + assert(k5_identpro_ctx != NULL); + + code = pkrb5_parse_name(k5_identpro_ctx, + princ_name, + &princ); + + if (code) { + nx->result = KHM_ERROR_INVALID_NAME; + return KHM_ERROR_SUCCESS; + } + + if (princ != NULL) + pkrb5_free_principal(k5_identpro_ctx, + princ); + + /* krb5_parse_name() accepts principal names with no realm or an + empty realm. We don't. */ + atsign = wcschr(nx->name_src, L'@'); + if (atsign == NULL || atsign[1] == L'\0') { + nx->result = KHM_ERROR_INVALID_NAME; + } else { + nx->result = KHM_ERROR_SUCCESS; + } + + return KHM_ERROR_SUCCESS; +} + +static void +k5_update_last_default_identity(khm_handle ident) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + cb = sizeof(idname); + if (KHM_FAILED(kcdb_identity_get_name(ident, idname, &cb))) + return; + + assert(csp_params); + + khc_write_string(csp_params, L"LastDefaultIdent", idname); +} + +static khm_int32 +k5_ident_set_default_int(khm_handle def_ident) { + wchar_t id_ccname[KRB5_MAXCCH_CCNAME]; + khm_size cb; + DWORD dw; + LONG l; + HKEY hk_ccname; + DWORD dwType; + DWORD dwSize; + wchar_t reg_ccname[KRB5_MAXCCH_CCNAME]; + +#ifdef DEBUG + assert(def_ident != NULL); +#endif + + cb = sizeof(id_ccname); + if (KHM_FAILED(kcdb_identity_get_attr(def_ident, attr_id_krb5_ccname, NULL, + id_ccname, &cb))) { + _reportf(L"The specified identity does not have the Krb5CCName property"); + + cb = sizeof(id_ccname); + if (KHM_FAILED(khm_krb5_get_identity_default_ccache(def_ident, id_ccname, &cb))) { + return KHM_ERROR_INVALID_PARAM; + } + } + + _reportf(L"Found Krb5CCName property : %s", id_ccname); + + StringCbLength(id_ccname, sizeof(id_ccname), &cb); + cb += sizeof(wchar_t); + + _reportf(L"Setting default CC name in the registry"); + + l = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\MIT\\kerberos5", 0, + KEY_READ | KEY_WRITE, &hk_ccname); + + if (l != ERROR_SUCCESS) + l = RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\MIT\\kerberos5", 0, + NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, + NULL, &hk_ccname, &dw); + + if (l != ERROR_SUCCESS) { + _reportf(L"Can't create registry key : %d", l); + _end_task(); + return KHM_ERROR_UNKNOWN; + } + + dwSize = sizeof(reg_ccname); + + l = RegQueryValueEx(hk_ccname, L"ccname", NULL, &dwType, (LPBYTE) reg_ccname, + &dwSize); + + if (l != ERROR_SUCCESS || + dwType != REG_SZ || + khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) { + + /* we have to write the new value in */ + + l = RegSetValueEx(hk_ccname, L"ccname", 0, REG_SZ, (BYTE *) id_ccname, + (DWORD) cb); + } + + RegCloseKey(hk_ccname); + + if (l == ERROR_SUCCESS) { + _reportf(L"Successfully set the default ccache"); + k5_update_last_default_identity(def_ident); + return KHM_ERROR_SUCCESS; + } else { + _reportf(L"Can't set the registry value : %d", l); + return KHM_ERROR_UNKNOWN; + } +} + +static khm_int32 +k5_ident_set_default(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + /* + Currently, setting the default identity simply sets the + "ccname" registry value at "Software\MIT\kerberos5". + */ + + if (uparam) { + /* an identity is being made default */ + khm_handle def_ident = (khm_handle) vparam; + khm_int32 rv; + +#ifdef DEBUG + assert(def_ident != NULL); +#endif + + { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + cb = sizeof(idname); + kcdb_identity_get_name(def_ident, idname, &cb); + + _begin_task(0); + _report_cs1(KHERR_DEBUG_1, L"Setting default identity [%1!s!]", _cstr(idname)); + _describe(); + } + + rv = k5_ident_set_default_int(def_ident); + + _end_task(); + + return rv; + + } else { + /* the default identity is being forgotten */ + + /* we don't really do anything about this case */ + } + + return KHM_ERROR_SUCCESS; +} + +static khm_int32 +k5_ident_get_ui_cb(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + khui_ident_new_creds_cb * cb; + + cb = (khui_ident_new_creds_cb *) vparam; + + *cb = ui_cb; + + return KHM_ERROR_SUCCESS; +} + +static khm_int32 +k5_ident_notify_create(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + /* a new identity has been created. What we want to do at + this point is to check if the identity belongs to krb5 + and to see if it is the default. */ + + krb5_ccache cc = NULL; + krb5_error_code code; + krb5_principal princ = NULL; + char * princ_nameA = NULL; + wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME]; + wchar_t id_nameW[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_handle ident; + + /* if there is a default identity already, we assume we don't need + to check this one. */ + + khm_handle def_ident; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&def_ident))) { + kcdb_identity_release(def_ident); + + return KHM_ERROR_SUCCESS; + } + + ident = (khm_handle) vparam; + + assert(k5_identpro_ctx != NULL); + + code = pkrb5_cc_default(k5_identpro_ctx, &cc); + if (code) + goto _nc_cleanup; + + code = pkrb5_cc_get_principal(k5_identpro_ctx, + cc, + &princ); + if (code) + goto _nc_cleanup; + + code = pkrb5_unparse_name(k5_identpro_ctx, + princ, + &princ_nameA); + if (code) + goto _nc_cleanup; + + AnsiStrToUnicode(princ_nameW, + sizeof(princ_nameW), + princ_nameA); + + cb = sizeof(id_nameW); + + if (KHM_FAILED(kcdb_identity_get_name(ident, + id_nameW, + &cb))) + goto _nc_cleanup; + + if (!wcscmp(id_nameW, princ_nameW)) { + kcdb_identity_set_default_int(ident); + } + + _nc_cleanup: + if (princ_nameA) + pkrb5_free_unparsed_name(k5_identpro_ctx, + princ_nameA); + if (princ) + pkrb5_free_principal(k5_identpro_ctx, + princ); + if (cc) + pkrb5_cc_close(k5_identpro_ctx, cc); + + return KHM_ERROR_SUCCESS; +} + +struct k5_ident_update_data { + khm_handle identity; + + FILETIME ft_expire; /* expiration */ + FILETIME ft_issue; /* issue */ + FILETIME ft_rexpire; /* renew expiration */ + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + khm_int32 k5_flags; +}; + +/* The logic here has to reflect the logic in khm_krb5_list_tickets(). + We use this to handle an identity update request because some other + plug-in or maybe NetIDMgr itself is about to do something + important(tm) with the identity and needs to make sure that the + properties of the identity are up-to-date. */ +static khm_int32 KHMAPI +k5_ident_update_apply_proc(khm_handle cred, + void * rock) { + struct k5_ident_update_data * d = (struct k5_ident_update_data *) rock; + khm_handle ident = NULL; + khm_int32 t; + khm_int32 flags; + FILETIME t_cexpire; + FILETIME t_rexpire; + khm_size cb; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) || + t != credtype_id_krb5 || + KHM_FAILED(kcdb_cred_get_identity(cred, &ident))) + + return KHM_ERROR_SUCCESS; + + if (!kcdb_identity_is_equal(ident,d->identity)) + + goto _cleanup; + + if (KHM_FAILED(kcdb_cred_get_flags(cred, &flags))) + + flags = 0; + + if (flags & KCDB_CRED_FLAG_INITIAL) { + cb = sizeof(t_cexpire); + if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, + KCDB_ATTR_EXPIRE, + NULL, + &t_cexpire, + &cb))) { + if ((d->ft_expire.dwLowDateTime == 0 && + d->ft_expire.dwHighDateTime == 0) || + CompareFileTime(&t_cexpire, &d->ft_expire) > 0) { + goto update_identity; + } + } + } + + goto _cleanup; + + update_identity: + + d->ft_expire = t_cexpire; + + cb = sizeof(d->ccname); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION, NULL, d->ccname, &cb))) { + d->ccname[0] = L'\0'; + } + + cb = sizeof(d->k5_flags); + if (KHM_FAILED(kcdb_cred_get_attr(cred, attr_id_krb5_flags, NULL, + &d->k5_flags, &cb))) { + d->k5_flags = 0; + } + + cb = sizeof(d->ft_issue); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, NULL, &d->ft_issue, &cb))) { + ZeroMemory(&d->ft_issue, sizeof(d->ft_issue)); + } + + cb = sizeof(t_rexpire); + if ((d->k5_flags & TKT_FLG_RENEWABLE) && + KHM_SUCCEEDED(kcdb_cred_get_attr(cred, + KCDB_ATTR_RENEW_EXPIRE, + NULL, + &t_rexpire, + &cb))) { + d->ft_rexpire = t_rexpire; + } else { + ZeroMemory(&d->ft_rexpire, sizeof(d->ft_rexpire)); + } + + _cleanup: + if (ident) + kcdb_identity_release(ident); + + return rv; +} + +static khm_int32 +k5_ident_update(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + +#if 0 + struct k5_ident_update_data d; +#endif + khm_handle ident; + khm_handle tident; + krb5_ccache cc = NULL; + char * ccname; + krb5_error_code code; + khm_size cb; + wchar_t wid_ccname[MAX_PATH]; + wchar_t w_ccname[MAX_PATH]; + + ident = (khm_handle) vparam; + if (ident == NULL) + return KHM_ERROR_SUCCESS; + +#if 0 + /* we are going to skip doing this here since + khm_krb5_list_tickets() performs this function for us each time + we enumerate tickets. Since it also gets run each time our + list of tickets changes and since we are basing this operation + on existing tickets, we are unlikely to find anything new + here. */ + ZeroMemory(&d, sizeof(d)); + d.identity = ident; + + kcdb_credset_apply(NULL, + k5_ident_update_apply_proc, + (void *) &d); + + if (d.ft_expire.dwLowDateTime != 0 || + d.ft_expire.dwHighDateTime != 0) { + + /* we found a TGT */ + + kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, + &d.ft_expire, sizeof(d.ft_expire)); + if (d.ft_issue.dwLowDateTime != 0 || + d.ft_issue.dwHighDateTime != 0) + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, + &d.ft_issue, sizeof(d.ft_issue)); + else + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0); + + if (d.ft_rexpire.dwLowDateTime != 0 || + d.ft_rexpire.dwHighDateTime != 0) + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, + &d.ft_rexpire, sizeof(d.ft_rexpire)); + else + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + + kcdb_identity_set_attr(ident, attr_id_krb5_flags, + &d.k5_flags, sizeof(d.k5_flags)); + + if (d.ccname[0]) + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, + d.ccname, KCDB_CBSIZE_AUTO); + else + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0); + + } else { + /* Clear out the attributes. We don't have any information + about this identity */ + kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, NULL, 0); + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0); + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0); + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0); + } +#endif + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) { + kcdb_identity_release(tident); + goto _iu_cleanup; + } + + cb = sizeof(wid_ccname); + if (KHM_FAILED(kcdb_identity_get_attr(ident, + attr_id_krb5_ccname, + NULL, + wid_ccname, + &cb))) + goto _iu_cleanup; + + if(k5_identpro_ctx == NULL) + goto _iu_cleanup; + + code = pkrb5_cc_default(k5_identpro_ctx, &cc); + if (code) + goto _iu_cleanup; + + ccname = pkrb5_cc_get_name(k5_identpro_ctx, cc); + if (ccname == NULL) + goto _iu_cleanup; + + AnsiStrToUnicode(w_ccname, sizeof(w_ccname), ccname); + + khm_krb5_canon_cc_name(w_ccname, sizeof(w_ccname)); + khm_krb5_canon_cc_name(wid_ccname, sizeof(wid_ccname)); + + if (!_wcsicmp(w_ccname, wid_ccname)) + kcdb_identity_set_default_int(ident); + + _iu_cleanup: + if (cc && k5_identpro_ctx) + pkrb5_cc_close(k5_identpro_ctx, cc); + + return KHM_ERROR_SUCCESS; +} + +static khm_boolean +k5_refresh_default_identity(krb5_context ctx) { + /* just like notify_create, except now we set the default identity + based on what we find in the configuration */ + krb5_ccache cc = NULL; + krb5_error_code code; + krb5_principal princ = NULL; + char * princ_nameA = NULL; + wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME]; + char * ccname = NULL; + khm_handle ident = NULL; + khm_boolean found_default = FALSE; + + assert(ctx != NULL); + + _begin_task(0); + _report_cs0(KHERR_DEBUG_1, L"Refreshing default identity"); + _describe(); + + code = pkrb5_cc_default(ctx, &cc); + if (code) { + _reportf(L"Can't open default ccache. code=%d", code); + goto _nc_cleanup; + } + + code = pkrb5_cc_get_principal(ctx, cc, &princ); + if (code) { + /* try to determine the identity from the ccache name */ + ccname = pkrb5_cc_get_name(ctx, cc); + + if (ccname) { + char * namepart = strchr(ccname, ':'); + + _reportf(L"CC name is [%S]", ccname); + + if (namepart == NULL) + namepart = ccname; + else + namepart++; + + _reportf(L"Checking if [%S] is a valid identity name", namepart); + + AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), namepart); + if (kcdb_identity_is_valid_name(princ_nameW)) { + kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident); + if (ident) { + _reportf(L"Setting [%S] as the default identity", namepart); + kcdb_identity_set_default_int(ident); + found_default = TRUE; + } + } + } else { + _reportf(L"Can't determine ccache name"); + } + + goto _nc_cleanup; + } + + code = pkrb5_unparse_name(ctx, princ, &princ_nameA); + if (code) + goto _nc_cleanup; + + AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), princ_nameA); + + _reportf(L"Found principal [%s]", princ_nameW); + + if (KHM_FAILED(kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident))) { + _reportf(L"Failed to create identity"); + goto _nc_cleanup; + } + + _reportf(L"Setting default identity to [%s]", princ_nameW); + kcdb_identity_set_default_int(ident); + + found_default = TRUE; + + _nc_cleanup: + + _end_task(); + + if (princ_nameA) + pkrb5_free_unparsed_name(ctx, princ_nameA); + + if (princ) + pkrb5_free_principal(ctx, princ); + + if (cc) + pkrb5_cc_close(ctx, cc); + + if (ident) + kcdb_identity_release(ident); + + return found_default; +} + +static khm_int32 +k5_ident_init(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + khm_boolean found_default; + khm_handle ident; + + found_default = k5_refresh_default_identity(k5_identpro_ctx); + + if (!found_default) { + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + cb = sizeof(widname); + + assert(csp_params); + + if (KHM_SUCCEEDED(khc_read_string(csp_params, L"LastDefaultIdent", + widname, &cb))) { + ident = NULL; + kcdb_identity_create(widname, KCDB_IDENT_FLAG_CREATE, &ident); + if (ident) { + kcdb_identity_set_default_int(ident); + kcdb_identity_release(ident); + + found_default = TRUE; + } + } + } + + if (!found_default) { + + /* There was no default ccache and we don't have a + "LastDefaultIdent" value. Next we see if there are any + identities that have credentials which have a Krb5CCName + property (i.e. an identity that has a Kerberos 5 TGT), and + make it the default. + + Note that since the Krb5Ident plug-in has a dependency on + Krb5Cred, by the time this code runs, we already have a + listing of Kerberos 5 tickets and identities. */ + + wchar_t * idlist = NULL; + wchar_t * thisid; + khm_size cb = 0; + khm_size n_idents = 0; + khm_int32 rv; + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + FILETIME ft_expire; + FILETIME ft_now; + FILETIME ft_threshold; + BOOL match_all = FALSE; + + rv = kcdb_identity_enum(0, 0, NULL, &cb, &n_idents); + + TimetToFileTimeInterval(5 * 60, &ft_threshold); + GetSystemTimeAsFileTime(&ft_now); + ft_now = FtAdd(&ft_now, &ft_threshold); + + while (rv == KHM_ERROR_TOO_LONG && n_idents > 0) { + if (idlist) { + PFREE(idlist); + idlist = NULL; + } + + idlist = PMALLOC(cb); + + if (idlist == NULL) + break; + + rv = kcdb_identity_enum(0, 0, idlist, &cb, &n_idents); + } + + if (KHM_SUCCEEDED(rv)) { + + /* first we try to find an identity that has a valid TGT. + If that fails, then we try to find an identity with + *any* TGT. */ + + try_again: + + for (thisid = idlist; + thisid && *thisid && !found_default; + thisid = multi_string_next(thisid)) { + + if (KHM_SUCCEEDED(kcdb_identity_create(thisid, 0, &ident))) { + khm_size cb_ft = sizeof(FILETIME); + cb = sizeof(ccname); + + if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, attr_id_krb5_ccname, + NULL, ccname, &cb)) && + (match_all || + (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, + NULL, &ft_expire, &cb_ft)) && + CompareFileTime(&ft_expire, &ft_now) > 0))) { + + /* found one */ + k5_ident_set_default_int(ident); + kcdb_identity_set_default_int(ident); + found_default = TRUE; + + } + + kcdb_identity_release(ident); + ident = NULL; + } + } + + if (!found_default && !match_all) { + match_all = TRUE; + goto try_again; + } + } + + if (idlist) { + PFREE(idlist); + idlist = NULL; + } + } + + return KHM_ERROR_SUCCESS; +} + +static khm_int32 +k5_ident_exit(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + /* don't really do anything */ + return KHM_ERROR_SUCCESS; +} + +/* forward dcl */ +khm_int32 KHMAPI +k5_ident_name_comp_func(const void * dl, khm_size cb_dl, + const void * dr, khm_size cb_dr); + +static khm_int32 +k5_ident_compare_name(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + kcdb_ident_name_xfer *px; + + px = (kcdb_ident_name_xfer *) vparam; + + /* note that k5_ident_name_comp_func() ignores the size + specifiers. So we can just pass in 0's. */ + px->result = k5_ident_name_comp_func(px->name_src, 0, + px->name_alt, 0); + + return KHM_ERROR_SUCCESS; +} + +#if 0 +/* copy and paste template for ident provider messages */ +static khm_int32 +k5_ident_(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { +} +#endif + +khm_int32 KHMAPI +k5_msg_ident(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) +{ + switch(msg_subtype) { + case KMSG_IDENT_INIT: + return k5_ident_init(msg_type, + msg_subtype, + uparam, + vparam); + + case KMSG_IDENT_EXIT: + return k5_ident_exit(msg_type, + msg_subtype, + uparam, + vparam); + + case KMSG_IDENT_VALIDATE_NAME: + return k5_ident_validate_name(msg_type, + msg_subtype, + uparam, + vparam); + + case KMSG_IDENT_VALIDATE_IDENTITY: + /* TODO: handle KMSG_IDENT_VALIDATE_IDENTITY */ + break; + + case KMSG_IDENT_CANON_NAME: + /* TODO: handle KMSG_IDENT_CANON_NAME */ + break; + + case KMSG_IDENT_COMPARE_NAME: + return k5_ident_compare_name(msg_type, + msg_subtype, + uparam, + vparam); + + case KMSG_IDENT_SET_DEFAULT: + return k5_ident_set_default(msg_type, + msg_subtype, + uparam, + vparam); + + case KMSG_IDENT_SET_SEARCHABLE: + /* TODO: handle KMSG_IDENT_SET_SEARCHABLE */ + break; + + case KMSG_IDENT_GET_INFO: + /* TODO: handle KMSG_IDENT_GET_INFO */ + break; + + case KMSG_IDENT_UPDATE: + return k5_ident_update(msg_type, + msg_subtype, + uparam, + vparam); + + case KMSG_IDENT_ENUM_KNOWN: + /* TODO: handle KMSG_IDENT_ENUM_KNOWN */ + break; + + case KMSG_IDENT_GET_UI_CALLBACK: + return k5_ident_get_ui_cb(msg_type, + msg_subtype, + uparam, + vparam); + + case KMSG_IDENT_NOTIFY_CREATE: + return k5_ident_notify_create(msg_type, + msg_subtype, + uparam, + vparam); + } + + return KHM_ERROR_SUCCESS; +} + +/* note that we are ignoring the size specifiers. We can do that + because we are guaranteed that dl and dr point to NULL terminated + unicode strings when used with credential data buffers. We also + use the fact that we are ignoring the size specifiers when we call + this function from k5_ident_compare_name() to avoid calculating the + length of the string. */ +khm_int32 KHMAPI +k5_ident_name_comp_func(const void * dl, khm_size cb_dl, + const void * dr, khm_size cb_dr) { + wchar_t * idl = (wchar_t *) dl; + wchar_t * idr = (wchar_t *) dr; + wchar_t * rl; + wchar_t * rr; + khm_int32 r; + + rl = khm_get_realm_from_princ(idl); + rr = khm_get_realm_from_princ(idr); + + if (rl == NULL && rr == NULL) + return wcscmp(idl, idr); + else if (rl == NULL) + return 1; + else if (rr == NULL) + return -1; + + r = wcscmp(rl, rr); + if (r == 0) + return wcscmp(idl, idr); + else + return r; +} + + +/* Identity change notification thread */ + +HANDLE h_ccname_exit_event; +HANDLE h_ccname_thread; + +DWORD WINAPI k5_ccname_monitor_thread(LPVOID lpParameter) { + + HKEY hk_ccname; + HANDLE h_notify; + HANDLE h_waits[2]; + + khm_int32 rv = KHM_ERROR_SUCCESS; + DWORD dwType; + DWORD dwSize; + DWORD dwDisp; + wchar_t reg_ccname[KRB5_MAXCCH_CCNAME]; + LONG l; + + PDESCTHREAD(L"Krb5 CCName Monitor", L"Krb5"); + + l = RegOpenKeyEx(HKEY_CURRENT_USER, + L"Software\\MIT\\kerberos5", + 0, + KEY_READ | KEY_WRITE, + &hk_ccname); + + if (l != ERROR_SUCCESS) + l = RegCreateKeyEx(HKEY_CURRENT_USER, + L"Software\\MIT\\kerberos5", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hk_ccname, + &dwDisp); + + if (l != ERROR_SUCCESS) { + rv = KHM_ERROR_UNKNOWN; + goto _exit; + } + + dwSize = sizeof(reg_ccname); + + l = RegQueryValueEx(hk_ccname, + L"ccname", + NULL, + &dwType, + (LPBYTE) reg_ccname, + &dwSize); + + if (l != ERROR_SUCCESS || + dwType != REG_SZ) { + + reg_ccname[0] = L'\0'; + } + + h_notify = CreateEvent(NULL, FALSE, FALSE, L"Local\\Krb5CCNameChangeNotifier"); + + if (h_notify == NULL) + goto _exit_0; + + /* begin wait loop */ + + h_waits[0] = h_ccname_exit_event; + h_waits[1] = h_notify; + + do { + DWORD dwrv; + + l = RegNotifyChangeKeyValue(hk_ccname, FALSE, + REG_NOTIFY_CHANGE_LAST_SET, + h_notify, TRUE); + + if (l != ERROR_SUCCESS) { + rv = KHM_ERROR_UNKNOWN; + break; + } + + dwrv = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE); + + if (dwrv == WAIT_OBJECT_0) { + /* exit! */ + break; + + } else if (dwrv == WAIT_OBJECT_0 + 1) { + /* change notify! */ + wchar_t new_ccname[KRB5_MAXCCH_CCNAME]; + + dwSize = sizeof(new_ccname); + + l = RegQueryValueEx(hk_ccname, + L"ccname", + NULL, + &dwType, + (LPBYTE) new_ccname, + &dwSize); + + if (l != ERROR_SUCCESS || + dwType != REG_SZ) { + new_ccname[0] = L'\0'; + } + + if (_wcsicmp(new_ccname, reg_ccname)) { + krb5_context ctx = NULL; + + l = pkrb5_init_context(&ctx); + if (l == 0 && ctx != NULL) { + k5_refresh_default_identity(ctx); + StringCbCopy(reg_ccname, sizeof(reg_ccname), new_ccname); + } + + if (ctx) + pkrb5_free_context(ctx); + } + + } else { + /* something went wrong */ + rv = KHM_ERROR_UNKNOWN; + break; + } + + } while (TRUE); + + CloseHandle(h_notify); + + _exit_0: + + RegCloseKey(hk_ccname); + + _exit: + ExitThread(rv); +} + +khm_int32 +k5_msg_system_idpro(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) { + + switch(msg_subtype) { + case KMSG_SYSTEM_INIT: + { + + pkrb5_init_context(&k5_identpro_ctx); + kcdb_identity_set_type(credtype_id_krb5); + + if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_PRINC, + &type_id_krb5_princ))) { + kcdb_type dt; + kcdb_type * pstr; + + kcdb_type_get_info(KCDB_TYPE_STRING, &pstr); + + ZeroMemory(&dt, sizeof(dt)); + dt.name = TYPENAME_KRB5_PRINC; + dt.id = KCDB_TYPE_INVALID; + dt.flags = KCDB_TYPE_FLAG_CB_AUTO; + dt.cb_min = pstr->cb_min; + dt.cb_max = pstr->cb_max; + dt.toString = pstr->toString; + dt.isValid = pstr->isValid; + dt.comp = k5_ident_name_comp_func; + dt.dup = pstr->dup; + + kcdb_type_register(&dt, &type_id_krb5_princ); + + type_regd_krb5_princ = TRUE; + + kcdb_type_release_info(pstr); + } + + if (type_id_krb5_princ != -1) { + kcdb_attrib * attr; + + kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr); + + attr->type = type_id_krb5_princ; + + kcdb_attrib_release_info(attr); + } + + h_ccname_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (h_ccname_exit_event) { + h_ccname_thread = CreateThread(NULL, + 200 * 1024, + k5_ccname_monitor_thread, + NULL, + 0, + NULL); + } else { + h_ccname_thread = NULL; + } + } + break; + + case KMSG_SYSTEM_EXIT: + { + + if (h_ccname_thread) { + SetEvent(h_ccname_exit_event); + WaitForSingleObject(h_ccname_thread, INFINITE); + CloseHandle(h_ccname_thread); + CloseHandle(h_ccname_exit_event); + + h_ccname_exit_event = NULL; + h_ccname_thread = NULL; + } + + if (k5_identpro_ctx) { + pkrb5_free_context(k5_identpro_ctx); + k5_identpro_ctx = NULL; + } + + if (type_id_krb5_princ != -1) { + kcdb_attrib * attr; + + kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr); + + attr->type = KCDB_TYPE_STRING; + + kcdb_attrib_release_info(attr); + } + + /* allow a brief moment for any stale references to die */ + Sleep(100); + + if (type_regd_krb5_princ) { + kcdb_type_unregister(type_id_krb5_princ); + } + } + break; + } + + return KHM_ERROR_SUCCESS; +} + +khm_int32 KHMAPI +k5_ident_callback(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) { + switch(msg_type) { + case KMSG_SYSTEM: + return k5_msg_system_idpro(msg_type, msg_subtype, uparam, vparam); + + case KMSG_IDENT: + return k5_msg_ident(msg_type, msg_subtype, uparam, vparam); + } + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5main.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5main.c new file mode 100644 index 000000000..4875a80f8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5main.c @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> + +kmm_module h_khModule; /* KMM's handle to this module */ +HINSTANCE hInstance; +HMODULE hResModule; /* HMODULE to the resource library */ +const wchar_t * k5_facility = L"Krb5Cred"; + +khm_int32 type_id_enctype = -1; +khm_int32 type_id_addr_list = -1; +khm_int32 type_id_krb5_flags = -1; +khm_int32 type_id_krb5_princ = -1; +khm_int32 type_id_kvno = -1; + +BOOL type_regd_enctype = FALSE; +BOOL type_regd_addr_list = FALSE; +BOOL type_regd_krb5_flags = FALSE; +BOOL type_regd_krb5_princ = FALSE; +BOOL type_regd_kvno = FALSE; + +khm_int32 attr_id_key_enctype = -1; +khm_int32 attr_id_tkt_enctype = -1; +khm_int32 attr_id_addr_list = -1; +khm_int32 attr_id_krb5_flags = -1; +khm_int32 attr_id_krb5_ccname = -1; +khm_int32 attr_id_kvno = -1; +khm_int32 attr_id_krb5_idflags = -1; + +BOOL attr_regd_key_enctype = FALSE; +BOOL attr_regd_tkt_enctype = FALSE; +BOOL attr_regd_addr_list = FALSE; +BOOL attr_regd_krb5_flags = FALSE; +BOOL attr_regd_krb5_ccname = FALSE; +BOOL attr_regd_kvno = FALSE; +BOOL attr_regd_krb5_idflags = FALSE; + +khm_handle csp_plugins = NULL; +khm_handle csp_krbcred = NULL; +khm_handle csp_params = NULL; + +BOOL is_k5_identpro = TRUE; + +khm_ui_4 k5_commctl_version; + +kmm_module_locale locales[] = { + LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb5cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT) +}; +int n_locales = ARRAYLENGTH(locales); + +/* These two should not do anything */ +void init_krb() { +} + +void exit_krb() { +} + +/* called by the NetIDMgr module manager */ +KHMEXP_EXP khm_int32 KHMAPI init_module(kmm_module h_module) { + khm_int32 rv = KHM_ERROR_SUCCESS; + kmm_plugin_reg pi; + wchar_t buf[256]; + + h_khModule = h_module; + + rv = kmm_set_locale_info(h_module, locales, n_locales); + if(KHM_SUCCEEDED(rv)) { + hResModule = kmm_get_resource_hmodule(h_module); + } else + goto _exit; + + k5_commctl_version = khm_get_commctl_version(NULL); + + /* register the plugin */ + ZeroMemory(&pi, sizeof(pi)); + pi.name = KRB5_PLUGIN_NAME; + pi.type = KHM_PITYPE_CRED; + pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN), + IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + pi.flags = 0; + pi.msg_proc = k5_msg_callback; + pi.description = buf; + pi.dependencies = NULL; + LoadString(hResModule, IDS_PLUGIN_DESC, + buf, ARRAYLENGTH(buf)); + kmm_provide_plugin(h_module, &pi); + + ZeroMemory(&pi, sizeof(pi)); + pi.name = KRB5_IDENTPRO_NAME; + pi.type = KHM_PITYPE_IDENT; + pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN), + IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + pi.flags = 0; + pi.msg_proc = k5_ident_callback; + pi.description = buf; + pi.dependencies = KRB5_PLUGIN_NAME L"\0"; + LoadString(hResModule, IDS_IDENTPRO_DESC, + buf, ARRAYLENGTH(buf)); + kmm_provide_plugin(h_module, &pi); + + if(KHM_FAILED(rv = init_imports())) + goto _exit; + + if(KHM_FAILED(rv = init_error_funcs())) + goto _exit; + + /* Register common data types */ + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE, &type_id_enctype))) { + kcdb_type type; + kcdb_type *t32; + + kcdb_type_get_info(KCDB_TYPE_INT32, &t32); + + type.id = KCDB_TYPE_INVALID; + type.name = TYPENAME_ENCTYPE; + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + type.cb_max = t32->cb_max; + type.cb_min = t32->cb_min; + type.isValid = t32->isValid; + type.comp = t32->comp; + type.dup = t32->dup; + type.toString = enctype_toString; + + rv = kcdb_type_register(&type, &type_id_enctype); + kcdb_type_release_info(t32); + + if(KHM_FAILED(rv)) + goto _exit; + type_regd_enctype = TRUE; + } + + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST, &type_id_addr_list))) { + kcdb_type type; + kcdb_type *tdata; + + kcdb_type_get_info(KCDB_TYPE_DATA, &tdata); + + type.id = KCDB_TYPE_INVALID; + type.name = TYPENAME_ADDR_LIST; + type.flags = KCDB_TYPE_FLAG_CB_MIN; + type.cb_min = 0; + type.cb_max = 0; + type.isValid = tdata->isValid; + type.comp = addr_list_comp; + type.dup = tdata->dup; + type.toString = addr_list_toString; + + rv = kcdb_type_register(&type, &type_id_addr_list); + kcdb_type_release_info(tdata); + + if(KHM_FAILED(rv)) + goto _exit; + type_regd_addr_list = TRUE; + } + + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS, &type_id_krb5_flags))) { + kcdb_type type; + kcdb_type *t32; + + kcdb_type_get_info(KCDB_TYPE_INT32, &t32); + + type.id = KCDB_TYPE_INVALID; + type.name = TYPENAME_KRB5_FLAGS; + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + type.cb_max = t32->cb_max; + type.cb_min = t32->cb_min; + type.isValid = t32->isValid; + type.comp = t32->comp; + type.dup = t32->dup; + type.toString = krb5flags_toString; + + rv = kcdb_type_register(&type, &type_id_krb5_flags); + kcdb_type_release_info(t32); + + if(KHM_FAILED(rv)) + goto _exit; + type_regd_krb5_flags = TRUE; + } + + if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KVNO, &type_id_kvno))) { + kcdb_type type; + kcdb_type *t32; + + kcdb_type_get_info(KCDB_TYPE_INT32, &t32); + + type.id = KCDB_TYPE_INVALID; + type.name = TYPENAME_KVNO; + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + type.cb_max = t32->cb_max; + type.cb_min = t32->cb_min; + type.isValid = t32->isValid; + type.comp = t32->comp; + type.dup = t32->dup; + type.toString = kvno_toString; + + rv = kcdb_type_register(&type, &type_id_kvno); + kcdb_type_release_info(t32); + + if (KHM_FAILED(rv)) + goto _exit; + + type_regd_kvno = TRUE; + } + + /* Register common attributes */ + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE, &attr_id_key_enctype))) { + kcdb_attrib attrib; + wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC]; + wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC]; + /* although we are loading a long descriptoin, it still fits + in the short descriptoin buffer */ + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_KEY_ENCTYPE; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = type_id_enctype; + attrib.flags = KCDB_ATTR_FLAG_TRANSIENT; + LoadString(hResModule, IDS_KEY_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf)); + LoadString(hResModule, IDS_KEY_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = lbuf; + + rv = kcdb_attrib_register(&attrib, &attr_id_key_enctype); + + if(KHM_FAILED(rv)) + goto _exit; + + attr_regd_key_enctype = TRUE; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE, &attr_id_tkt_enctype))) { + kcdb_attrib attrib; + wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC]; + wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC]; + /* although we are loading a long descriptoin, it still fits + in the short descriptoin buffer */ + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_TKT_ENCTYPE; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = type_id_enctype; + attrib.flags = KCDB_ATTR_FLAG_TRANSIENT; + LoadString(hResModule, IDS_TKT_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf)); + LoadString(hResModule, IDS_TKT_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = lbuf; + + rv = kcdb_attrib_register(&attrib, &attr_id_tkt_enctype); + + if(KHM_FAILED(rv)) + goto _exit; + + attr_regd_tkt_enctype = TRUE; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST, &attr_id_addr_list))) { + kcdb_attrib attrib; + wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC]; + wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC]; + /* although we are loading a long descriptoin, it still fits + in the short descriptoin buffer */ + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_ADDR_LIST; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = type_id_addr_list; + attrib.flags = KCDB_ATTR_FLAG_TRANSIENT; + LoadString(hResModule, IDS_ADDR_LIST_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf)); + LoadString(hResModule, IDS_ADDR_LIST_LONG_DESC, lbuf, ARRAYLENGTH(lbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = lbuf; + + rv = kcdb_attrib_register(&attrib, &attr_id_addr_list); + + if(KHM_FAILED(rv)) + goto _exit; + + attr_regd_addr_list = TRUE; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS, &attr_id_krb5_flags))) { + kcdb_attrib attrib; + wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC]; + + /* although we are loading a long descriptoin, it still fits + in the short descriptoin buffer */ + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_KRB5_FLAGS; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = type_id_krb5_flags; + attrib.flags = KCDB_ATTR_FLAG_TRANSIENT; + LoadString(hResModule, IDS_KRB5_FLAGS_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = NULL; + + rv = kcdb_attrib_register(&attrib, &attr_id_krb5_flags); + + if(KHM_FAILED(rv)) + goto _exit; + + attr_regd_krb5_flags = TRUE; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_CCNAME, &attr_id_krb5_ccname))) { + kcdb_attrib attrib; + wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC]; + wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC]; + /* although we are loading a long descriptoin, it still fits + in the short descriptoin buffer */ + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_KRB5_CCNAME; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = KCDB_TYPE_STRING; + attrib.flags = + KCDB_ATTR_FLAG_PROPERTY | + KCDB_ATTR_FLAG_TRANSIENT; + LoadString(hResModule, IDS_KRB5_CCNAME_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf)); + LoadString(hResModule, IDS_KRB5_CCNAME_LONG_DESC, lbuf, ARRAYLENGTH(lbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = lbuf; + + rv = kcdb_attrib_register(&attrib, &attr_id_krb5_ccname); + + if(KHM_FAILED(rv)) + goto _exit; + + attr_regd_krb5_ccname = TRUE; + } + + if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KVNO, &attr_id_kvno))) { + kcdb_attrib attrib; + wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC]; + wchar_t lbuf[KCDB_MAXCCH_LONG_DESC]; + /* although we are loading a long description, it still fits + in the short description buffer */ + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_KVNO; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = type_id_kvno; + attrib.flags = KCDB_ATTR_FLAG_TRANSIENT; + LoadString(hResModule, IDS_KVNO_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf)); + LoadString(hResModule, IDS_KVNO_LONG_DESC, lbuf, ARRAYLENGTH(lbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = lbuf; + + rv = kcdb_attrib_register(&attrib, &attr_id_kvno); + + if (KHM_FAILED(rv)) + goto _exit; + + attr_regd_kvno = TRUE; + } + + if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_IDFLAGS, &attr_id_krb5_idflags))) { + kcdb_attrib attrib; + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_KRB5_IDFLAGS; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = KCDB_TYPE_INT32; + attrib.flags = KCDB_ATTR_FLAG_PROPERTY | + KCDB_ATTR_FLAG_HIDDEN; + /* we don't bother localizing these strings since the + attribute is hidden. The user will not see these + descriptions anyway. */ + attrib.short_desc = L"Krb5 ID flags"; + attrib.long_desc = L"Kerberos 5 Identity Flags"; + + rv = kcdb_attrib_register(&attrib, &attr_id_krb5_idflags); + + if (KHM_FAILED(rv)) + goto _exit; + + attr_regd_krb5_idflags = TRUE; + } + + rv = kmm_get_plugins_config(0, &csp_plugins); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_load_schema(csp_plugins, schema_krbconfig); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, 0, &csp_krbcred); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params); + if(KHM_FAILED(rv)) goto _exit; + +_exit: + return rv; +} + +/* called by the NetIDMgr module manager */ +KHMEXP_EXP khm_int32 KHMAPI exit_module(kmm_module h_module) { + exit_imports(); + exit_error_funcs(); + + if(attr_regd_key_enctype) + kcdb_attrib_unregister(attr_id_key_enctype); + if(attr_regd_tkt_enctype) + kcdb_attrib_unregister(attr_id_tkt_enctype); + if(attr_regd_addr_list) + kcdb_attrib_unregister(attr_id_addr_list); + if(attr_regd_krb5_flags) + kcdb_attrib_unregister(attr_id_krb5_flags); + if(attr_regd_krb5_ccname) + kcdb_attrib_unregister(attr_id_krb5_ccname); + if(attr_regd_kvno) + kcdb_attrib_unregister(attr_id_kvno); + if(attr_regd_krb5_idflags) + kcdb_attrib_unregister(attr_id_krb5_idflags); + + if(type_regd_enctype) + kcdb_type_unregister(type_id_enctype); + if(type_regd_addr_list) + kcdb_type_unregister(type_id_addr_list); + if(type_regd_krb5_flags) + kcdb_type_unregister(type_id_krb5_flags); + if(type_regd_kvno) + kcdb_type_unregister(type_id_kvno); + + if(csp_params) { + khc_close_space(csp_params); + csp_params = NULL; + } + + if(csp_krbcred) { + khc_close_space(csp_krbcred); + csp_krbcred = NULL; + } + + if(csp_plugins) { + khc_unload_schema(csp_plugins, schema_krbconfig); + khc_close_space(csp_plugins); + csp_plugins = NULL; + } + + return KHM_ERROR_SUCCESS; /* the return code is ignored */ +} + +BOOL WINAPI DllMain( + HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved +) +{ + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + hInstance = hinstDLL; + init_krb(); + break; + case DLL_PROCESS_DETACH: + exit_krb(); + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + } + + return TRUE; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5newcreds.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5newcreds.c new file mode 100644 index 000000000..6b64302c3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5newcreds.c @@ -0,0 +1,2886 @@ +/* + * Copyright (c) 2006, 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<strsafe.h> +#include<krb5.h> + +#include<commctrl.h> + +#include<assert.h> + +extern LPVOID k5_main_fiber; +extern LPVOID k5_kinit_fiber; + +typedef struct k5_dlg_data_t { + khui_new_creds * nc; + + khui_tracker tc_lifetime; + khui_tracker tc_renew; + + BOOL dirty; /* is the data in sync with the + configuration store? */ + BOOL sync; /* is the data in sync with the kinit + request? */ + DWORD renewable; + DWORD forwardable; + DWORD proxiable; + DWORD addressless; + DWORD publicIP; + + wchar_t * cred_message; /* overrides the credential text, if + non-NULL */ + BOOL pwd_change; /* force a password change */ +} k5_dlg_data; + + +INT_PTR +k5_handle_wm_initdialog(HWND hwnd, + WPARAM wParam, + LPARAM lParam) +{ + HWND hw; + k5_dlg_data * d; + khui_new_creds_by_type * nct; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + /* lParam is a pointer to a khui_new_creds structure */ + d->nc = (khui_new_creds *) lParam; + khui_cw_find_type(d->nc, credtype_id_krb5, &nct); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d); +#pragma warning(pop) + + nct->aux = (LPARAM) d; + + if (d->nc->subtype == KMSG_CRED_NEW_CREDS) { + khui_tracker_initialize(&d->tc_lifetime); + khui_tracker_initialize(&d->tc_renew); + + hw = GetDlgItem(hwnd, IDC_NCK5_LIFETIME_EDIT); + khui_tracker_install(hw, &d->tc_lifetime); + + hw = GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT); + khui_tracker_install(hw, &d->tc_renew); + } + return TRUE; +} + +INT_PTR +k5_handle_wm_destroy(HWND hwnd, + WPARAM wParam, + LPARAM lParam) +{ + k5_dlg_data * d; + khui_new_creds_by_type * nct = NULL; + + d = (k5_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (!d) + return TRUE; + + khui_cw_find_type(d->nc, credtype_id_krb5, &nct); + +#ifdef DEBUG + assert(nct); +#endif + + nct->aux = 0; + + if (d->nc->subtype == KMSG_CRED_NEW_CREDS) { + khui_tracker_kill_controls(&d->tc_renew); + khui_tracker_kill_controls(&d->tc_lifetime); + } + + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + + return TRUE; +} + +LRESULT +k5_force_password_change(k5_dlg_data * d) { + /* we are turning this dialog into a change password dialog... */ + wchar_t wbuf[KHUI_MAXCCH_BANNER]; + + khui_cw_clear_prompts(d->nc); + + LoadString(hResModule, IDS_NC_PWD_BANNER, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_begin_custom_prompts(d->nc, 3, NULL, wbuf); + + LoadString(hResModule, IDS_NC_PWD_PWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_PASSWORD, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + LoadString(hResModule, IDS_NC_PWD_NPWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + d->pwd_change = TRUE; + + if (is_k5_identpro && + d->nc->n_identities > 0 && + d->nc->identities[0]) { + + kcdb_identity_set_flags(d->nc->identities[0], + KCDB_IDENT_FLAG_VALID, + KCDB_IDENT_FLAG_VALID); + + } + + PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), + (LPARAM) d->nc); + + return TRUE; +} + +INT_PTR +k5_handle_wmnc_notify(HWND hwnd, + WPARAM wParam, + LPARAM lParam) +{ + switch(HIWORD(wParam)) { + case WMNC_DIALOG_MOVE: + { + k5_dlg_data * d; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + return TRUE; + + if (d->nc->subtype == KMSG_CRED_NEW_CREDS) { + khui_tracker_reposition(&d->tc_lifetime); + khui_tracker_reposition(&d->tc_renew); + } + + return TRUE; + } + break; + + case WMNC_DIALOG_SETUP: + { + k5_dlg_data * d; + BOOL old_sync; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + return TRUE; + + if (d->nc->subtype == KMSG_CRED_PASSWORD) + return TRUE; + + /* we save the value of the 'sync' field here because some + of the notifications that are generated while setting + the controls overwrite the field. */ + old_sync = d->sync; + + /* need to update the controls with d->* */ + SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, + BM_SETCHECK, + (d->renewable? BST_CHECKED : BST_UNCHECKED), + 0); + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), + !!d->renewable); + + khui_tracker_refresh(&d->tc_lifetime); + khui_tracker_refresh(&d->tc_renew); + + SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, + BM_SETCHECK, + (d->forwardable ? BST_CHECKED : BST_UNCHECKED), + 0); + + SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS, + BM_SETCHECK, + (d->addressless ? BST_CHECKED : BST_UNCHECKED), + 0); + + SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP, + IPM_SETADDRESS, + 0, d->publicIP); + + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless); + + d->sync = old_sync; + } + break; + + case WMNC_CREDTEXT_LINK: + { + k5_dlg_data * d; + khui_htwnd_link * l; + khui_new_creds * nc; + wchar_t linktext[128]; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + return TRUE; + + nc = d->nc; + l = (khui_htwnd_link *) lParam; + + if (!l) + break; + + StringCchCopyN(linktext, ARRAYLENGTH(linktext), + l->id, l->id_len); + + if (!wcscmp(linktext, L"Krb5Cred:!Passwd")) { + return k5_force_password_change(d); + } + } + break; + + case WMNC_UPDATE_CREDTEXT: + { + k5_dlg_data * d; + khui_new_creds * nc; + khui_new_creds_by_type * nct; + wchar_t sbuf[1024]; + wchar_t fbuf[256]; + wchar_t tbuf[256]; + size_t cbsize; + khm_int32 flags; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return TRUE; + + nc = d->nc; + khui_cw_find_type(nc, credtype_id_krb5, &nct); + + if(nct == NULL) + break; + + if(nct->credtext) + PFREE(nct->credtext); + nct->credtext = NULL; + + tbuf[0] = L'\0'; + + if (nc->n_identities > 0 && + KHM_SUCCEEDED(kcdb_identity_get_flags(nc->identities[0], + &flags)) && + (flags & KCDB_IDENT_FLAG_VALID) && + nc->subtype == KMSG_CRED_NEW_CREDS && + !d->pwd_change) { + + if (is_k5_identpro) + k5_get_realm_from_nc(nc, tbuf, ARRAYLENGTH(tbuf)); + else + GetDlgItemText(hwnd, IDC_NCK5_REALM, tbuf, + ARRAYLENGTH(tbuf)); + + /*TODO: if additional realms were specified, then those + must be listed as well */ + LoadString(hResModule, IDS_KRB5_CREDTEXT_0, + fbuf, ARRAYLENGTH(fbuf)); + StringCbPrintf(sbuf, sizeof(sbuf), fbuf, + tbuf); + + StringCbLength(sbuf, sizeof(sbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->credtext = PMALLOC(cbsize); + + StringCbCopy(nct->credtext, cbsize, sbuf); + } else if (nc->n_identities > 0 && + (nc->subtype == KMSG_CRED_PASSWORD || + (nc->subtype == KMSG_CRED_NEW_CREDS && d->pwd_change))) { + cbsize = sizeof(tbuf); + kcdb_identity_get_name(nc->identities[0], tbuf, &cbsize); + + LoadString(hResModule, IDS_KRB5_CREDTEXT_P0, + fbuf, ARRAYLENGTH(fbuf)); + StringCbPrintf(sbuf, sizeof(sbuf), fbuf, tbuf); + + StringCbLength(sbuf, sizeof(sbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->credtext = PMALLOC(cbsize); + + StringCbCopy(nct->credtext, cbsize, sbuf); + } else { + if (d->cred_message) { + StringCbLength(d->cred_message, KHUI_MAXCB_BANNER, + &cbsize); + cbsize += sizeof(wchar_t); + + nct->credtext = PMALLOC(cbsize); + + StringCbCopy(nct->credtext, cbsize, d->cred_message); + } + } + } + break; + + case WMNC_IDENTITY_CHANGE: + { + /* There has been a change of identity */ + k5_dlg_data * d; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + kmq_post_sub_msg(k5_sub, KMSG_CRED, + KMSG_CRED_DIALOG_NEW_IDENTITY, + 0, (void *) d->nc); + } + break; + + case WMNC_DIALOG_PREPROCESS: + { + k5_dlg_data * d; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + if(!d->sync && d->nc->result == KHUI_NC_RESULT_PROCESS) { + kmq_post_sub_msg(k5_sub, KMSG_CRED, + KMSG_CRED_DIALOG_NEW_OPTIONS, + 0, (void *) d->nc); + } + } + break; + + case K5_SET_CRED_MSG: + { + k5_dlg_data * d; + khm_size cb; + wchar_t * msg; + + d = (k5_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + msg = (wchar_t *) lParam; + + if (d->cred_message) { + PFREE(d->cred_message); + d->cred_message = NULL; + } + + if (msg && + SUCCEEDED(StringCbLength(msg, + KHUI_MAXCB_MESSAGE, + &cb))) { + cb += sizeof(wchar_t); + d->cred_message = PMALLOC(cb); +#ifdef DEBUG + assert(d->cred_message); +#endif + StringCbCopy(d->cred_message, cb, msg); + } + } + break; + } + + return 0; +} + +INT_PTR +k5_handle_wm_notify(HWND hwnd, + WPARAM wParam, + LPARAM lParam) { + LPNMHDR pnmh; + k5_dlg_data * d; + + pnmh = (LPNMHDR) lParam; + if (pnmh->idFrom == IDC_NCK5_PUBLICIP && + pnmh->code == IPN_FIELDCHANGED) { + + d = (k5_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return 0; + + SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP, + IPM_GETADDRESS, + 0, (LPARAM) &d->publicIP); + + d->dirty = TRUE; + d->sync = FALSE; + + return TRUE; + } + + return 0; +} + +INT_PTR +k5_handle_wm_command(HWND hwnd, + WPARAM wParam, + LPARAM lParam) +{ + int cid; + int notif; + k5_dlg_data * d; + + d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + cid = LOWORD(wParam); + notif = HIWORD(wParam); + + if(notif == BN_CLICKED && cid == IDC_NCK5_RENEWABLE) { + int c; + c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, + BM_GETCHECK, 0, 0); + if(c==BST_CHECKED) { + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), TRUE); + d->renewable = TRUE; + } else { + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), FALSE); + d->renewable = FALSE; + } + d->dirty = TRUE; + d->sync = FALSE; + } else if(notif == BN_CLICKED && cid == IDC_NCK5_FORWARDABLE) { + int c; + c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, + BM_GETCHECK, 0, 0); + if(c==BST_CHECKED) { + d->forwardable = TRUE; + } else { + d->forwardable = FALSE; + } + d->dirty = TRUE; + d->sync = FALSE; + } else if (notif == BN_CLICKED && cid == IDC_NCK5_ADDRESS) { + int c; + + c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS, + BM_GETCHECK, 0, 0); + + if (c==BST_CHECKED) { + d->addressless = TRUE; + } else { + d->addressless = FALSE; + } + d->dirty = TRUE; + d->sync = FALSE; + + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless); + } else if (notif == EN_CHANGE && (cid == IDC_NCK5_RENEW_EDIT || + cid == IDC_NCK5_LIFETIME_EDIT)) { + d->dirty = TRUE; + d->sync = FALSE; + } else if((notif == CBN_SELCHANGE || + notif == CBN_KILLFOCUS) && + cid == IDC_NCK5_REALM && + !is_k5_identpro) { + /* find out what the realm of the current identity + is, and if they are the same, then we don't do + anything */ + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t realm[KCDB_IDENT_MAXCCH_NAME]; + wchar_t *r; + khm_size cbsize; + khm_handle ident; + int idx; + + if(d->nc->n_identities > 0) { + if(notif == CBN_SELCHANGE) { + idx = (int) SendDlgItemMessage(hwnd, IDC_NCK5_REALM, + CB_GETCURSEL, 0, 0); + SendDlgItemMessage(hwnd, IDC_NCK5_REALM, + CB_GETLBTEXT, idx, (LPARAM) realm); + } else { + GetDlgItemText(hwnd, IDC_NCK5_REALM, + realm, ARRAYLENGTH(realm)); + } + cbsize = sizeof(idname); + if(KHM_SUCCEEDED(kcdb_identity_get_name(d->nc->identities[0], + idname, &cbsize))) { + r = wcschr(idname, L'@'); + if(r && !wcscmp(realm, r+1)) + return 0; /* nothing to do */ + + if(!r) { + r = idname + wcslen(idname); + *r++ = L'@'; + *r++ = 0; + } + + /* if we get here, we have a new user */ + StringCchCopy(r+1, + ARRAYLENGTH(idname) - ((r+1) - idname), + realm); + if(KHM_SUCCEEDED(kcdb_identity_create(idname, + KCDB_IDENT_FLAG_CREATE, + &ident))) { + khui_cw_set_primary_id(d->nc, ident); + kcdb_identity_release(ident); + } + return 0; + } + } + + /* if we get here, we have a new realm, but there is no + identity */ + PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0); + } + + return 0; +} + + +/* Dialog procedure for the Krb5 credentials type panel. + + NOTE: Runs in the context of the UI thread +*/ +INT_PTR CALLBACK +k5_nc_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_INITDIALOG: + return k5_handle_wm_initdialog(hwnd, wParam, lParam); + + case WM_COMMAND: + return k5_handle_wm_command(hwnd, wParam, lParam); + + case KHUI_WM_NC_NOTIFY: + return k5_handle_wmnc_notify(hwnd, wParam, lParam); + + case WM_NOTIFY: + return k5_handle_wm_notify(hwnd, wParam, lParam); + + case WM_DESTROY: + return k5_handle_wm_destroy(hwnd, wParam, lParam); + } + return FALSE; +} + +/* forward dcl */ +krb5_error_code KRB5_CALLCONV +k5_kinit_prompter(krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]); + + + +fiber_job g_fjob; /* global fiber job object */ + +static BOOL +k5_cached_kinit_prompter(void); + +static BOOL +k5_cp_check_continue(void); + +/* + Runs in the context of the krb5 plugin's slave fiber +*/ +VOID CALLBACK +k5_kinit_fiber_proc(PVOID lpParameter) +{ + while(TRUE) + { + if(g_fjob.command == FIBER_CMD_KINIT) { + g_fjob.state = FIBER_STATE_KINIT; + + g_fjob.prompt_set = 0; + + if (k5_cached_kinit_prompter()) { + SwitchToFiber(k5_main_fiber); + + if (g_fjob.command != FIBER_CMD_CONTINUE) + goto _switch_to_main; + + if (!k5_cp_check_continue()) { + g_fjob.code = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto _switch_to_main; + } + } + +#ifdef DEBUG + /* log the state of g_fjob.* */ + _reportf(L"g_fjob state prior to calling khm_krb5_kinit() :"); + _reportf(L" g_fjob.principal = [%S]", g_fjob.principal); + _reportf(L" g_fjob.code = %d", g_fjob.code); + _reportf(L" g_fjob.state = %d", g_fjob.state); + _reportf(L" g_fjob.prompt_set= %d", g_fjob.prompt_set); + _reportf(L" g_fjob.valid_principal = %d", (int) g_fjob.valid_principal); + _reportf(L" g_fjob.ccache = [%s]", g_fjob.ccache); +#endif + + /* If we don't know if we have a valid principal, we + restrict the options that are set when we call kinit. + This way we will be able to use the response from the + KDC to verify the principal. */ + + g_fjob.retry_if_valid_principal = (g_fjob.forwardable || + g_fjob.proxiable || + g_fjob.renewable); + + retry_kinit: + g_fjob.code = + khm_krb5_kinit(0, + g_fjob.principal, + g_fjob.password, + g_fjob.ccache, + g_fjob.lifetime, + g_fjob.valid_principal ? g_fjob.forwardable : 0, + g_fjob.valid_principal ? g_fjob.proxiable : 0, + (g_fjob.valid_principal && g_fjob.renewable ? g_fjob.renew_life : 0), + g_fjob.addressless, + g_fjob.publicIP, + k5_kinit_prompter, + &g_fjob); + + /* If the principal was found to be valid, and if we + restricted the options that were being passed to kinit, + then we need to retry the kinit call. This time we use + the real options. */ + if (g_fjob.state == FIBER_STATE_RETRY_KINIT) { +#ifdef DEBUG + assert(g_fjob.valid_principal); +#endif + g_fjob.state = FIBER_STATE_KINIT; + goto retry_kinit; + } + } + + _switch_to_main: + g_fjob.state = FIBER_STATE_NONE; + + SwitchToFiber(k5_main_fiber); + } +} + +/* return TRUE if we should go ahead with creds acquisition */ +static BOOL +k5_cp_check_continue(void) { + khm_size i; + khm_size n_p; + khui_new_creds_prompt * p; + size_t cch; + +#ifdef DEBUG + assert(g_fjob.nc); +#endif + + if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc, &n_p))) { +#ifdef DEBUG + assert(FALSE); +#endif + return TRUE; + } + + khui_cw_sync_prompt_values(g_fjob.nc); + + g_fjob.null_password = FALSE; + + /* we are just checking whether there was a password field that + was left empty, in which case we can't continue with the + credentials acquisition. */ + for (i=0; i < n_p; i++) { + if(KHM_FAILED(khui_cw_get_prompt(g_fjob.nc, + (int) i, + &p))) + continue; + if(p->type == KHUI_NCPROMPT_TYPE_PASSWORD) { + if (p->value == NULL || + FAILED(StringCchLength(p->value, KHUI_MAXCCH_PROMPT, + &cch)) || + cch == 0) { + g_fjob.null_password = TRUE; + return FALSE; + } else + break; + } + } + + return TRUE; +} + +/* returns true if we find cached prompts */ +static BOOL +k5_cached_kinit_prompter(void) { + BOOL rv = FALSE; + khm_handle ident; + khm_handle csp_idconfig = NULL; + khm_handle csp_k5config = NULL; + khm_handle csp_prcache = NULL; + khm_size cb; + khm_size n_cur_prompts; + khm_int32 n_prompts; + khm_int32 i; + khm_int64 iexpiry; + FILETIME expiry; + FILETIME current; + +#ifdef DEBUG + assert(g_fjob.nc); +#endif + + ident = g_fjob.identity; + if (!ident) + return FALSE; + + /* don't need to hold ident, since it is already held in g_fjob + and it doesn't change until we return */ + + if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_idconfig)) || + + KHM_FAILED(khc_open_space(csp_idconfig, CSNAME_KRB5CRED, + 0, &csp_k5config)) || + + KHM_FAILED(khc_open_space(csp_k5config, CSNAME_PROMPTCACHE, + 0, &csp_prcache)) || + + KHM_FAILED(khc_read_int32(csp_prcache, L"PromptCount", + &n_prompts)) || + n_prompts == 0) + + goto _cleanup; + + if (KHM_SUCCEEDED(khc_read_int64(csp_prcache, L"ExpiresOn", &iexpiry))) { + /* has the cache expired? */ + expiry = IntToFt(iexpiry); + GetSystemTimeAsFileTime(&current); + + if (CompareFileTime(&expiry, &current) < 0) + /* already expired */ + goto _cleanup; + } else { + /* if there is no value for ExpiresOn, we assume the prompts + have already expired. */ + goto _cleanup; + } + + /* we found a prompt cache. We take this to imply that the + principal is valid. */ + g_fjob.valid_principal = TRUE; + + /* check if there are any prompts currently showing. If there are + we check if they are the same as the ones we are going to show. + In which case we just reuse the exisitng prompts */ + if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc, + &n_cur_prompts)) || + n_prompts != (khm_int32) n_cur_prompts) + goto _show_new_prompts; + + for(i = 0; i < n_prompts; i++) { + wchar_t wsname[8]; + wchar_t wprompt[KHUI_MAXCCH_PROMPT]; + khm_handle csp_p = NULL; + khm_int32 p_type; + khm_int32 p_flags; + khui_new_creds_prompt * p; + + if (KHM_FAILED(khui_cw_get_prompt(g_fjob.nc, i, &p))) + break; + + StringCbPrintf(wsname, sizeof(wsname), L"%d", i); + + if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p))) + break; + + cb = sizeof(wprompt); + if (KHM_FAILED(khc_read_string(csp_p, L"Prompt", + wprompt, &cb))) { + khc_close_space(csp_p); + break; + } + + if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type))) + p_type = 0; + + if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags))) + p_flags = 0; + + if ( /* if we received a prompt string, + then it should be the same as the + one that is displayed */ + (wprompt[0] && + (p->prompt == NULL || + wcscmp(wprompt, p->prompt))) || + + /* if we didn't receive one, then + there shouldn't be one displayed. + This case really shouldn't happen + in reality, but we check anyway. */ + (!wprompt[0] && + p->prompt != NULL) || + + /* the type should match */ + (p_type != p->type) || + + /* if this prompt should be hidden, + then it must also be so */ + (p_flags != p->flags) + ) { + + khc_close_space(csp_p); + break; + + } + + + khc_close_space(csp_p); + } + + if (i == n_prompts) { + rv = TRUE; + goto _cleanup; + } + + _show_new_prompts: + + khui_cw_clear_prompts(g_fjob.nc); + + { + wchar_t wbanner[KHUI_MAXCCH_BANNER]; + wchar_t wpname[KHUI_MAXCCH_PNAME]; + + cb = sizeof(wbanner); + if (KHM_FAILED(khc_read_string(csp_prcache, L"Banner", + wbanner, &cb))) + wbanner[0] = 0; + + cb = sizeof(wpname); + if (KHM_FAILED(khc_read_string(csp_prcache, L"Name", + wpname, &cb))) + wpname[0] = 0; + + khui_cw_begin_custom_prompts(g_fjob.nc, + n_prompts, + (wbanner[0]? wbanner: NULL), + (wpname[0]? wpname: NULL)); + } + + for(i = 0; i < n_prompts; i++) { + wchar_t wsname[8]; + wchar_t wprompt[KHUI_MAXCCH_PROMPT]; + khm_handle csp_p = NULL; + khm_int32 p_type; + khm_int32 p_flags; + + StringCbPrintf(wsname, sizeof(wsname), L"%d", i); + + if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p))) + break; + + cb = sizeof(wprompt); + if (KHM_FAILED(khc_read_string(csp_p, L"Prompt", + wprompt, &cb))) { + khc_close_space(csp_p); + break; + } + + if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type))) + p_type = 0; + + if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags))) + p_flags = 0; + + khui_cw_add_prompt(g_fjob.nc, p_type, wprompt, NULL, p_flags); + + khc_close_space(csp_p); + } + + if (i < n_prompts) { + khui_cw_clear_prompts(g_fjob.nc); + } else { + rv = TRUE; + } + + _cleanup: + + if (csp_prcache) + khc_close_space(csp_prcache); + + if (csp_k5config) + khc_close_space(csp_k5config); + + if (csp_idconfig) + khc_close_space(csp_idconfig); + + return rv; +} + +/* Runs in the context of the Krb5 plugin's slave fiber */ +krb5_error_code KRB5_CALLCONV +k5_kinit_prompter(krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]) +{ + int i; + khui_new_creds * nc; + krb5_prompt_type * ptypes; + khm_size ncp; + krb5_error_code code = 0; + BOOL new_prompts = TRUE; + khm_handle csp_prcache = NULL; + +#ifdef DEBUG + _reportf(L"k5_kinit_prompter() received %d prompts with name=[%S] banner=[%S]", + num_prompts, + name, banner); + for (i=0; i < num_prompts; i++) { + _reportf(L"Prompt[%d]: string[%S]", i, prompts[i].prompt); + } +#endif + + /* we got prompts? Then we assume that the principal is valid */ + + if (!g_fjob.valid_principal) { + g_fjob.valid_principal = TRUE; + + /* if the flags that were used to call kinit were restricted + because we didn't know the validity of the principal, then + we need to go back and retry the call with the correct + flags. */ + if (g_fjob.retry_if_valid_principal) { + _reportf(L"Retrying kinit call due to restricted flags on first call."); + g_fjob.state = FIBER_STATE_RETRY_KINIT; + return KRB5_LIBOS_PWDINTR; + } + } + + nc = g_fjob.nc; + + if(pkrb5_get_prompt_types) + ptypes = pkrb5_get_prompt_types(context); + else + ptypes = NULL; + + /* check if we are already showing the right prompts */ + khui_cw_get_prompt_count(nc, &ncp); + + if (num_prompts != (int) ncp) + goto _show_new_prompts; + + for (i=0; i < num_prompts; i++) { + wchar_t wprompt[KHUI_MAXCCH_PROMPT]; + khui_new_creds_prompt * p; + + if(prompts[i].prompt) { + AnsiStrToUnicode(wprompt, sizeof(wprompt), + prompts[i].prompt); + } else { + wprompt[0] = 0; + } + + if (KHM_FAILED(khui_cw_get_prompt(nc, i, &p))) + break; + + if ( /* if we received a prompt string, + then it should be the same as the + one that is displayed */ + (wprompt[0] && + (p->prompt == NULL || + wcscmp(wprompt, p->prompt))) || + /* if we didn't receive one, then + there shouldn't be one displayed. + This case really shouldn't happen + in reality, but we check anyway. */ + (!wprompt[0] && + p->prompt != NULL) || + /* the type should match */ + (ptypes && + ptypes[i] != p->type) || + (!ptypes && + p->type != 0) || + /* if this prompt should be hidden, + then it must also be so */ + (prompts[i].hidden && + !(p->flags & KHUI_NCPROMPT_FLAG_HIDDEN)) || + (!prompts[i].hidden && + (p->flags & KHUI_NCPROMPT_FLAG_HIDDEN)) + ) + break; + } + + if (i < num_prompts) + goto _show_new_prompts; + + new_prompts = FALSE; + + /* ok. looks like we are already showing the same set of prompts + that we were supposed to show. Sync up the values and go + ahead. */ + khui_cw_sync_prompt_values(nc); + goto _process_prompts; + + _show_new_prompts: + /* special case. if there are no actual input controls involved, + then we have to show an alerter window and pass through */ + if (num_prompts == 0) { + wchar_t wbanner[KHUI_MAXCCH_BANNER]; + wchar_t wname[KHUI_MAXCCH_PNAME]; + wchar_t wident[KCDB_IDENT_MAXCCH_NAME]; + wchar_t wmsg[KHUI_MAXCCH_MESSAGE]; + wchar_t wfmt[KHUI_MAXCCH_BANNER]; + khm_size cb; + + if (!banner) { + code = 0; + g_fjob.null_password = FALSE; + goto _exit; + } else { + AnsiStrToUnicode(wbanner, sizeof(wbanner), banner); + } + + if (name) { + AnsiStrToUnicode(wname, sizeof(wname), name); + } else { + LoadString(hResModule, + IDS_KRB5_WARNING, + wname, + ARRAYLENGTH(wname)); + } + + cb = sizeof(wident); + if (KHM_FAILED(kcdb_identity_get_name(g_fjob.identity, wident, &cb))) + wident[0] = L'\0'; + + LoadString(hResModule, + IDS_KRB5_WARN_FMT, + wfmt, + ARRAYLENGTH(wfmt)); + + StringCbPrintf(wmsg, sizeof(wmsg), wfmt, wident, wbanner); + + khui_alert_show_simple(wname, wmsg, KHERR_WARNING); + + code = 0; + g_fjob.null_password = FALSE; + goto _exit; + } + + /* in addition to showing new prompts, we also cache the set of + prompts. */ + if(g_fjob.prompt_set == 0) { + khm_handle csp_idconfig = NULL; + khm_handle csp_idk5 = NULL; + + kcdb_identity_get_config(g_fjob.identity, + KHM_FLAG_CREATE, + &csp_idconfig); + + if (csp_idconfig != NULL) + khc_open_space(csp_idconfig, + CSNAME_KRB5CRED, + KHM_FLAG_CREATE, + &csp_idk5); + + if (csp_idk5 != NULL) + khc_open_space(csp_idk5, + CSNAME_PROMPTCACHE, + KHM_FLAG_CREATE, + &csp_prcache); + + khc_close_space(csp_idconfig); + khc_close_space(csp_idk5); + } + + { + wchar_t wbanner[KHUI_MAXCCH_BANNER]; + wchar_t wname[KHUI_MAXCCH_PNAME]; + FILETIME current; + FILETIME lifetime; + FILETIME expiry; + khm_int64 iexpiry; + khm_int32 t = 0; + + if(banner) + AnsiStrToUnicode(wbanner, sizeof(wbanner), banner); + if(name) + AnsiStrToUnicode(wname, sizeof(wname), name); + + khui_cw_clear_prompts(nc); + + khui_cw_begin_custom_prompts( + nc, + num_prompts, + (banner)?wbanner:NULL, + (name)?wname:NULL); + + if (csp_prcache) { + + if (banner) + khc_write_string(csp_prcache, + L"Banner", + wbanner); + else + khc_write_string(csp_prcache, + L"Banner", + L""); + + if (name) + khc_write_string(csp_prcache, + L"Name", + wname); + else if (csp_prcache) + khc_write_string(csp_prcache, + L"Name", + L""); + + khc_write_int32(csp_prcache, + L"PromptCount", + (khm_int32) num_prompts); + + GetSystemTimeAsFileTime(&current); +#ifdef USE_PROMPT_CACHE_LIFETIME + khc_read_int32(csp_params, L"PromptCacheLifetime", &t); + if (t == 0) + t = 172800; /* 48 hours */ +#else + khc_read_int32(csp_params, L"MaxRenewLifetime", &t); + if (t == 0) + t = 2592000; /* 30 days */ + t += 604800; /* + 7 days */ +#endif + TimetToFileTimeInterval(t, &lifetime); + expiry = FtAdd(&current, &lifetime); + iexpiry = FtToInt(&expiry); + + khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry); + } + } + + for(i=0; i < num_prompts; i++) { + wchar_t wprompt[KHUI_MAXCCH_PROMPT]; + + if(prompts[i].prompt) { + AnsiStrToUnicode(wprompt, sizeof(wprompt), + prompts[i].prompt); + } else { + wprompt[0] = 0; + } + + khui_cw_add_prompt( + nc, + (ptypes?ptypes[i]:0), + wprompt, + NULL, + (prompts[i].hidden?KHUI_NCPROMPT_FLAG_HIDDEN:0)); + + if (csp_prcache) { + khm_handle csp_p = NULL; + wchar_t wnum[8]; /* should be enough for 10 + million prompts */ + + wnum[0] = 0; + StringCbPrintf(wnum, sizeof(wnum), L"%d", i); + + khc_open_space(csp_prcache, wnum, + KHM_FLAG_CREATE, &csp_p); + + if (csp_p) { + khc_write_string(csp_p, L"Prompt", wprompt); + khc_write_int32(csp_p, L"Type", (ptypes?ptypes[i]:0)); + khc_write_int32(csp_p, L"Flags", + (prompts[i].hidden? + KHUI_NCPROMPT_FLAG_HIDDEN:0)); + + khc_close_space(csp_p); + } + } + } + + if (csp_prcache) { + khc_close_space(csp_prcache); + csp_prcache = NULL; + } + + _process_prompts: + /* switch back to main thread if we showed new prompts */ + if (new_prompts) + SwitchToFiber(k5_main_fiber); + + /* we get here after the user selects an action that either + cancles the credentials acquisition operation or triggers the + actual acquisition of credentials. */ + if(g_fjob.command != FIBER_CMD_CONTINUE && + g_fjob.command != FIBER_CMD_KINIT) { + code = KRB5_LIBOS_PWDINTR; + goto _exit; + } + + g_fjob.null_password = FALSE; + + /* otherwise, we need to get the data back from the UI and + return 0 */ + for(i=0; i<num_prompts; i++) { + krb5_data * d; + wchar_t wbuf[512]; + khm_size cbbuf; + size_t cch; + + d = prompts[i].reply; + + cbbuf = sizeof(wbuf); + if(KHM_SUCCEEDED(khui_cw_get_prompt_value(nc, i, wbuf, &cbbuf))) { + UnicodeStrToAnsi(d->data, d->length, wbuf); + if(SUCCEEDED(StringCchLengthA(d->data, d->length, &cch))) + d->length = (unsigned int) cch; + else + d->length = 0; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + d->length = 0; + } + + if (ptypes && + ptypes[i] == KRB5_PROMPT_TYPE_PASSWORD && + d->length == 0) + + g_fjob.null_password = TRUE; + } + + _exit: + + g_fjob.prompt_set++; + + /* entering a NULL password is equivalent to cancelling out */ + if (g_fjob.null_password) + return KRB5_LIBOS_PWDINTR; + else + return code; +} + + +void +k5_read_dlg_params(k5_dlg_data * d, khm_handle identity) +{ + k5_params p; + + khm_krb5_get_identity_params(identity, &p); + + d->renewable = p.renewable; + d->forwardable = p.forwardable; + d->proxiable = p.proxiable; + d->addressless = p.addressless; + d->publicIP = p.publicIP; + + d->tc_lifetime.current = p.lifetime; + d->tc_lifetime.max = p.lifetime_max; + d->tc_lifetime.min = p.lifetime_min; + + d->tc_renew.current = p.renew_life; + d->tc_renew.max = p.renew_life_max; + d->tc_renew.min = p.renew_life_min; + + /* however, if this has externally supplied defaults, we have to + use them too. */ + if (d->nc && d->nc->ctx.vparam && + d->nc->ctx.cb_vparam == sizeof(NETID_DLGINFO)) { + LPNETID_DLGINFO pdlginfo; + + pdlginfo = (LPNETID_DLGINFO) d->nc->ctx.vparam; + if (pdlginfo->size == NETID_DLGINFO_V1_SZ && + pdlginfo->in.use_defaults == 0) { + d->forwardable = pdlginfo->in.forwardable; + d->addressless = pdlginfo->in.noaddresses; + d->tc_lifetime.current = pdlginfo->in.lifetime; + d->tc_renew.current = pdlginfo->in.renew_till; + + if (pdlginfo->in.renew_till == 0) + d->renewable = FALSE; + else + d->renewable = TRUE; + + d->proxiable = pdlginfo->in.proxiable; + d->publicIP = pdlginfo->in.publicip; + } + } + + /* once we read the new data, in, it is no longer considered + dirty */ + d->dirty = FALSE; + d->sync = FALSE; +} + +void +k5_ensure_identity_ccache_is_watched(khm_handle identity, char * ccache) +{ + /* if we used a FILE: ccache, we should add it to FileCCList. + Otherwise the tickets are not going to get listed. */ + do { + wchar_t thisccache[MAX_PATH]; + wchar_t * ccpath; + khm_size cb_cc; + wchar_t * mlist = NULL; + khm_size cb_mlist; + khm_int32 rv; + khm_size t; + + if (ccache != NULL && + strncmp(ccache, "FILE:", 5) != 0) + break; + + if (ccache == NULL) { + cb_cc = sizeof(thisccache); + rv = khm_krb5_get_identity_default_ccache(identity, thisccache, &cb_cc); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + } else { + thisccache[0] = L'\0'; + AnsiStrToUnicode(thisccache, sizeof(thisccache), ccache); + } + + if (wcsncmp(thisccache, L"FILE:", 5)) + break; + + /* the FileCCList is a list of paths. We have to strip out + the FILE: prefix. */ + ccpath = thisccache + 5; + + _reportf(L"Checking if ccache [%s] is in FileCCList", ccpath); + + StringCbLength(ccpath, sizeof(thisccache) - sizeof(wchar_t) * 5, &cb_cc); + cb_cc += sizeof(wchar_t); + + rv = khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb_mlist); + if (rv == KHM_ERROR_TOO_LONG && cb_mlist > sizeof(wchar_t) * 2) { + cb_mlist += cb_cc; + mlist = PMALLOC(cb_mlist); + + t = cb_mlist; + rv = khc_read_multi_string(csp_params, L"FileCCList", mlist, &t); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + if (KHM_FAILED(rv)) + goto failed_filecclist; + + if (multi_string_find(mlist, ccpath, 0) == NULL) { + t = cb_mlist; + multi_string_append(mlist, &t, ccpath); + + khc_write_multi_string(csp_params, L"FileCCList", mlist); + _reportf(L"Added CCache to list"); + } else { + _reportf(L"The CCache is already in the list"); + } + } else { + cb_mlist = cb_cc + sizeof(wchar_t); + mlist = PMALLOC(cb_mlist); + + multi_string_init(mlist, cb_mlist); + t = cb_mlist; + multi_string_append(mlist, &t, ccpath); + + khc_write_multi_string(csp_params, L"FileCCList", mlist); + + _reportf(L"FileCCList was empty. Added CCache"); + } + + failed_filecclist: + + if (mlist) + PFREE(mlist); + + } while(FALSE); +} + +void +k5_write_dlg_params(k5_dlg_data * d, khm_handle identity, char * ccache) +{ + + k5_params p; + + ZeroMemory(&p, sizeof(p)); + + p.source_reg = K5PARAM_FM_ALL; /* we want to write all the + settings to the registry, if + necessary. */ + + p.renewable = d->renewable; + p.forwardable = d->forwardable; + p.proxiable = d->proxiable; + p.addressless = d->addressless; + p.publicIP = d->publicIP; + + p.lifetime = (krb5_deltat) d->tc_lifetime.current; + p.lifetime_max = (krb5_deltat) d->tc_lifetime.max; + p.lifetime_min = (krb5_deltat) d->tc_lifetime.min; + + p.renew_life = (krb5_deltat) d->tc_renew.current; + p.renew_life_max = (krb5_deltat) d->tc_renew.max; + p.renew_life_min = (krb5_deltat) d->tc_renew.min; + + khm_krb5_set_identity_params(identity, &p); + + k5_ensure_identity_ccache_is_watched(identity, ccache); + + /* as in k5_read_dlg_params, once we write the data in, the local + data is no longer dirty */ + d->dirty = FALSE; +} + +void +k5_free_kinit_job(void) +{ + if (g_fjob.principal) + PFREE(g_fjob.principal); + + if (g_fjob.password) + PFREE(g_fjob.password); + + if (g_fjob.identity) + kcdb_identity_release(g_fjob.identity); + + if (g_fjob.ccache) + PFREE(g_fjob.ccache); + + ZeroMemory(&g_fjob, sizeof(g_fjob)); +} + +void +k5_prep_kinit_job(khui_new_creds * nc) +{ + khui_new_creds_by_type * nct; + k5_dlg_data * d; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cbbuf; + size_t size; + khm_handle ident; + LPNETID_DLGINFO pdlginfo; + + khui_cw_find_type(nc, credtype_id_krb5, &nct); + if (!nct) + return; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(nct->hwnd_panel, DWLP_USER); + + if (!d) + return; + + khui_cw_lock_nc(nc); + ident = nc->identities[0]; + kcdb_identity_hold(ident); + khui_cw_unlock_nc(nc); + + cbbuf = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cbbuf); + StringCchLength(idname, ARRAYLENGTH(idname), &size); + size++; + + k5_free_kinit_job(); + + g_fjob.command = FIBER_CMD_KINIT; + g_fjob.nc = nc; + g_fjob.nct = nct; + g_fjob.dialog = nct->hwnd_panel; + g_fjob.principal = PMALLOC(size); + UnicodeStrToAnsi(g_fjob.principal, size, idname); + g_fjob.password = NULL; + g_fjob.lifetime = (krb5_deltat) d->tc_lifetime.current; + g_fjob.forwardable = d->forwardable; + g_fjob.proxiable = d->proxiable; + g_fjob.renewable = d->renewable; + g_fjob.renew_life = (krb5_deltat) d->tc_renew.current; + g_fjob.addressless = d->addressless; + g_fjob.publicIP = d->publicIP; + g_fjob.code = 0; + g_fjob.identity = ident; + g_fjob.prompt_set = 0; + g_fjob.valid_principal = FALSE; + g_fjob.ccache = NULL; + g_fjob.retry_if_valid_principal = FALSE; + + /* the value for + retry_if_valid_principal is not + necessarily the correct value here, + but the correct value will be + assigned k5_kinit_fiber_proc(). */ + + /* if we have external parameters, we should use them as well */ + if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) && + (pdlginfo = nc->ctx.vparam) && + pdlginfo->size == NETID_DLGINFO_V1_SZ) { + wchar_t * t; + + if (pdlginfo->in.ccache[0] && + SUCCEEDED(StringCchLength(pdlginfo->in.ccache, + NETID_CCACHE_NAME_SZ, + &size))) { + g_fjob.ccache = PMALLOC(sizeof(char) * (size + 1)); +#ifdef DEBUG + assert(g_fjob.ccache); +#endif + UnicodeStrToAnsi(g_fjob.ccache, size + 1, + pdlginfo->in.ccache); + + /* this is the same as the output cache */ + + StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache), + pdlginfo->in.ccache); + } else { + wchar_t ccache[MAX_PATH]; + + g_fjob.ccache = NULL; + size = sizeof(ccache); + + khm_krb5_get_identity_default_ccache(ident, ccache, &size); + + StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache), + ccache); + } + + t = khm_get_realm_from_princ(idname); + + if (t) { + StringCbCopy(pdlginfo->out.realm, + sizeof(pdlginfo->out.realm), + t); + + if ((t - idname) > 1) { + StringCchCopyN(pdlginfo->out.username, + ARRAYLENGTH(pdlginfo->out.username), + idname, + (t - idname) - 1); + } else { + StringCbCopy(pdlginfo->out.username, + sizeof(pdlginfo->out.username), + L""); + } + } else { + StringCbCopy(pdlginfo->out.username, + sizeof(pdlginfo->out.username), + idname); + StringCbCopy(pdlginfo->out.realm, + sizeof(pdlginfo->out.realm), + L""); + } + } + + /* leave identity held, since we added a reference above */ +} + +static khm_int32 KHMAPI +k5_find_tgt_filter(khm_handle cred, + khm_int32 flags, + void * rock) { + khm_handle ident = (khm_handle) rock; + khm_handle cident = NULL; + khm_int32 f; + khm_int32 rv; + + if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred, + &cident)) && + cident == ident && + KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &f)) && + (f & KCDB_CRED_FLAG_INITIAL) && + !(f & KCDB_CRED_FLAG_EXPIRED)) + rv = 1; + else + rv = 0; + + if (cident) + kcdb_identity_release(cident); + + return rv; +} + +khm_int32 +k5_remove_from_LRU(khm_handle identity) +{ + wchar_t * wbuf = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_size cb_ms; + khm_int32 rv = KHM_ERROR_SUCCESS; + + cb = sizeof(idname); + rv = kcdb_identity_get_name(identity, idname, &cb); + assert(rv == KHM_ERROR_SUCCESS); + + rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms); + if (rv != KHM_ERROR_TOO_LONG) + cb_ms = sizeof(wchar_t) * 2; + + wbuf = PMALLOC(cb_ms); + assert(wbuf); + + cb = cb_ms; + + if (rv == KHM_ERROR_TOO_LONG) { + rv = khc_read_multi_string(csp_params, L"LRUPrincipals", wbuf, &cb); + assert(KHM_SUCCEEDED(rv)); + + if (multi_string_find(wbuf, idname, KHM_CASE_SENSITIVE) != NULL) { + multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE); + } + } else { + multi_string_init(wbuf, cb_ms); + } + + rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf); + + if (wbuf) + PFREE(wbuf); + + return rv; +} + +khm_int32 +k5_update_LRU(khm_handle identity) +{ + wchar_t * wbuf = NULL; + wchar_t * idname = NULL; + wchar_t * realm = NULL; + khm_size cb; + khm_size cb_ms; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kcdb_identity_get_name(identity, NULL, &cb); + assert(rv == KHM_ERROR_TOO_LONG); + + idname = PMALLOC(cb); + assert(idname); + + rv = kcdb_identity_get_name(identity, idname, &cb); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms); + if (rv != KHM_ERROR_TOO_LONG) + cb_ms = cb + sizeof(wchar_t); + else + cb_ms += cb + sizeof(wchar_t); + + wbuf = PMALLOC(cb_ms); + assert(wbuf); + + cb = cb_ms; + + if (rv == KHM_ERROR_TOO_LONG) { + rv = khc_read_multi_string(csp_params, L"LRUPrincipals", wbuf, &cb); + assert(KHM_SUCCEEDED(rv)); + + if (multi_string_find(wbuf, idname, KHM_CASE_SENSITIVE) != NULL) { + /* it's already there. We remove it here and add it at + the top of the LRU list. */ + multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE); + } + } else { + multi_string_init(wbuf, cb_ms); + } + + cb = cb_ms; + rv = multi_string_prepend(wbuf, &cb, idname); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf); + + realm = khm_get_realm_from_princ(idname); + if (realm == NULL || *realm == L'\0') + goto _done_with_LRU; + + cb = cb_ms; + rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb); + + if (rv == KHM_ERROR_TOO_LONG) { + PFREE(wbuf); + wbuf = PMALLOC(cb); + assert(wbuf); + + cb_ms = cb; + + rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb); + + assert(KHM_SUCCEEDED(rv)); + } else if (rv == KHM_ERROR_SUCCESS) { + if (multi_string_find(wbuf, realm, KHM_CASE_SENSITIVE) != NULL) { + /* remove the realm and add it at the top later. */ + multi_string_delete(wbuf, realm, KHM_CASE_SENSITIVE); + } + } else { + multi_string_init(wbuf, cb_ms); + } + + cb = cb_ms; + rv = multi_string_prepend(wbuf, &cb, realm); + + if (rv == KHM_ERROR_TOO_LONG) { + wbuf = PREALLOC(wbuf, cb); + + rv = multi_string_prepend(wbuf, &cb, realm); + + assert(KHM_SUCCEEDED(rv)); + } + + rv = khc_write_multi_string(csp_params, L"LRURealms", wbuf); + + assert(KHM_SUCCEEDED(rv)); + + _done_with_LRU: + + if (wbuf) + PFREE(wbuf); + if (idname) + PFREE(idname); + + return rv; +} + +/* Handler for CRED type messages + + Runs in the context of the Krb5 plugin +*/ +khm_int32 KHMAPI +k5_msg_cred_dialog(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + + case KMSG_CRED_PASSWORD: + case KMSG_CRED_NEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + wchar_t wbuf[256]; + size_t cbsize; + + nc = (khui_new_creds *) vparam; + + nct = PMALLOC(sizeof(*nct)); + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id_krb5; + nct->ordinal = 1; + + LoadString(hResModule, IDS_KRB5_NC_NAME, + wbuf, ARRAYLENGTH(wbuf)); + StringCbLength(wbuf, sizeof(wbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->name = PMALLOC(cbsize); + StringCbCopy(nct->name, cbsize, wbuf); + + nct->h_module = hResModule; + nct->dlg_proc = k5_nc_dlg_proc; + if (nc->subtype == KMSG_CRED_PASSWORD) + nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5_PASSWORD); + else + nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5); + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_RENEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + + nc = (khui_new_creds *) vparam; + + nct = PMALLOC(sizeof(*nct)); + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id_krb5; + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_DIALOG_PRESTART: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + k5_dlg_data * d; + HWND hwnd; + wchar_t * realms; + wchar_t * t; + wchar_t * defrealm; + + nc = (khui_new_creds *) vparam; + + khui_cw_find_type(nc, credtype_id_krb5, &nct); + + if(!nct) + break; + + hwnd = nct->hwnd_panel; + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(nct->hwnd_panel, DWLP_USER); + + /* this can be NULL if the dialog was closed while the + plug-in thread was processing. */ + if (d == NULL) + break; + + if (!is_k5_identpro) { + + /* enumerate all realms and place in realms combo box */ + SendDlgItemMessage(hwnd, IDC_NCK5_REALM, + CB_RESETCONTENT, + 0, 0); + + realms = khm_krb5_get_realm_list(); + if(realms) { + for (t = realms; t && *t; t = multi_string_next(t)) { + SendDlgItemMessage(hwnd, IDC_NCK5_REALM, + CB_ADDSTRING, + 0, (LPARAM) t); + } + PFREE(realms); + } + + /* and set the default realm */ + defrealm = khm_krb5_get_default_realm(); + if(defrealm) { + SendDlgItemMessage(hwnd, IDC_NCK5_REALM, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) defrealm); + + SendDlgItemMessage(hwnd, IDC_NCK5_REALM, + WM_SETTEXT, + 0, (LPARAM) defrealm); + PFREE(defrealm); + } + } else { /* if krb5 is the identity provider */ + HWND hw_realms; + + /* in this case, the realm selection is done by the + identity provider prompts. */ + + hw_realms = GetDlgItem(hwnd, IDC_NCK5_REALM); +#ifdef DEBUG + assert(hw_realms); +#endif + EnableWindow(hw_realms, FALSE); + } + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + k5_read_dlg_params(d, NULL); + } + + PostMessage(hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0); + } + break; + + case KMSG_CRED_DIALOG_NEW_IDENTITY: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + k5_dlg_data * d; + + nc = (khui_new_creds *) vparam; + + khui_cw_find_type(nc, credtype_id_krb5, &nct); + if (!nct) + break; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(nct->hwnd_panel, DWLP_USER); + + if (d == NULL) + break; + + /* we only load the identity specific defaults if the user + hasn't changed the options */ + khui_cw_lock_nc(nc); + + /* ?: It might be better to not load identity defaults if + the user has already changed options in the dialog. */ + if(/* !d->dirty && */ nc->n_identities > 0 && + nc->subtype == KMSG_CRED_NEW_CREDS) { + + k5_read_dlg_params(d, nc->identities[0]); + + PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0); + } + + khui_cw_unlock_nc(nc); + + /* reset the force-password-change flag if this is a new + identity. */ + d->pwd_change = FALSE; + } + + /* fallthrough */ + case KMSG_CRED_DIALOG_NEW_OPTIONS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + k5_dlg_data * d; + + nc = (khui_new_creds *) vparam; + + khui_cw_find_type(nc, credtype_id_krb5, &nct); + if (!nct) + break; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(nct->hwnd_panel, DWLP_USER); + if (d == NULL) + break; + + if (nc->subtype == KMSG_CRED_PASSWORD) { + khm_size n_prompts = 0; + + khui_cw_get_prompt_count(nc, &n_prompts); + + if (nc->n_identities == 0) { + if (n_prompts) + khui_cw_clear_prompts(nc); + } else if (n_prompts != 3) { + wchar_t wbuf[KHUI_MAXCCH_BANNER]; + + khui_cw_clear_prompts(nc); + + LoadString(hResModule, IDS_NC_PWD_BANNER, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_begin_custom_prompts(nc, 3, NULL, wbuf); + + LoadString(hResModule, IDS_NC_PWD_PWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_PASSWORD, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + LoadString(hResModule, IDS_NC_PWD_NPWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + } + + return KHM_ERROR_SUCCESS; + } + /* else; nc->subtype == KMSG_CRED_NEW_CREDS */ + + assert(nc->subtype == KMSG_CRED_NEW_CREDS); + + /* If we are forcing a password change, then we don't do + anything here. Note that if the identity changed, then + this field would have been reset, so we would proceed + as usual. */ + if (d->pwd_change) + return KHM_ERROR_SUCCESS; + +#if 0 + /* Clearing the prompts at this point is a bad idea since + the prompter depends on the prompts to know if this set + of prompts is the same as the new set and if so, use + the values entered in the old prompts as responses to + the new one. */ + khui_cw_clear_prompts(nc); +#endif + + /* if the fiber is already in a kinit, cancel it */ + if(g_fjob.state == FIBER_STATE_KINIT) { + khm_boolean clear_prompts = TRUE; + + khui_cw_lock_nc(nc); + if (nc->n_identities > 0 && + kcdb_identity_is_equal(nc->identities[0], g_fjob.identity)) { + clear_prompts = FALSE; + } + khui_cw_unlock_nc(nc); + + g_fjob.command = FIBER_CMD_CANCEL; + SwitchToFiber(k5_kinit_fiber); + /* we get here when the cancel operation completes */ + k5_free_kinit_job(); + + if (clear_prompts) + khui_cw_clear_prompts(nc); + } + + khui_cw_lock_nc(nc); + + if(nc->n_identities > 0) { + khm_handle ident = nc->identities[0]; + + kcdb_identity_hold(ident); + + k5_prep_kinit_job(nc); + + /* after the switch to the fiber, the dialog will be + back in sync with the kinit thread. */ + d->sync = TRUE; + + khui_cw_unlock_nc(nc); + + SwitchToFiber(k5_kinit_fiber); + /* we get here when the fiber switches back */ + if(g_fjob.state == FIBER_STATE_NONE) { + wchar_t msg[KHUI_MAXCCH_BANNER]; + khm_size cb; + int code; + + code = g_fjob.code; + + /* Special case. If the users' password has + expired, we force a password change dialog on + top of the new credentials dialog using a set + of custom prompts, but only if we are the + identity provider. */ + if (g_fjob.code == KRB5KDC_ERR_KEY_EXP && + is_k5_identpro) { + + k5_force_password_change(d); + goto done_with_bad_princ; + + } + + if(g_fjob.code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN && + is_k5_identpro) { + kcdb_identity_set_flags(ident, + KCDB_IDENT_FLAG_INVALID, + KCDB_IDENT_FLAG_INVALID); + + khui_cw_clear_prompts(nc); + } + + if (d->cred_message) { + PFREE(d->cred_message); + d->cred_message = NULL; + } + + msg[0] = L'\0'; + + switch(g_fjob.code) { + case 0: + /* we succeeded. This can actually happen if + there was an external program that prompted + for credentials. */ + break; + + case KRB5KDC_ERR_NAME_EXP: + /* principal expired */ + LoadString(hResModule, IDS_K5ERR_NAME_EXPIRED, + msg, ARRAYLENGTH(msg)); + break; + + case KRB5KDC_ERR_KEY_EXP: + { + /* password needs changing. */ + LoadString(hResModule, IDS_K5ERR_KEY_EXPIRED, + msg, ARRAYLENGTH(msg)); + } + break; + + default: + { + DWORD dw_dummy; + kherr_suggestion sug_dummy; + wchar_t fmt[KHUI_MAXCCH_BANNER]; + wchar_t desc[KHUI_MAXCCH_BANNER]; + + LoadString(hResModule, IDS_K5ERR_FMT, + fmt, ARRAYLENGTH(fmt)); + + khm_err_describe(g_fjob.code, + desc, + sizeof(desc), + &dw_dummy, + &sug_dummy); + + StringCbPrintf(msg, sizeof(msg), fmt, desc); + } + } + + if (msg[0]) { + StringCbLength(msg, sizeof(msg), &cb); + cb += sizeof(wchar_t); + + d->cred_message = PMALLOC(cb); + StringCbCopy(d->cred_message, cb, msg); + } + + done_with_bad_princ: + + k5_free_kinit_job(); + + if (is_k5_identpro) { + if (code == 0) + kcdb_identity_set_flags(ident, + KCDB_IDENT_FLAG_VALID, + KCDB_IDENT_FLAG_VALID); + else + kcdb_identity_set_flags(ident, + KCDB_IDENT_FLAG_UNKNOWN, + KCDB_IDENT_FLAG_UNKNOWN); + } + + } else if(g_fjob.state == FIBER_STATE_KINIT) { + /* this is what we want. Leave the fiber there. */ + + if(is_k5_identpro) + kcdb_identity_set_flags(ident, + KCDB_IDENT_FLAG_VALID, + KCDB_IDENT_FLAG_VALID); + } else { + /* huh?? */ +#ifdef DEBUG + assert(FALSE); +#endif + } + + /* since the attributes of the identity have changed, + we should update the cred text as well */ + kcdb_identity_release(ident); + khui_cw_lock_nc(nc); + PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0); + } else { + khui_cw_unlock_nc(nc); + khui_cw_clear_prompts(nc); + khui_cw_lock_nc(nc); + } + + khui_cw_unlock_nc(nc); + } + break; + + case KMSG_CRED_PROCESS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + k5_dlg_data * d; + + khm_int32 r = 0; + + nc = (khui_new_creds *) vparam; + + khui_cw_find_type(nc, credtype_id_krb5, &nct); + + if(!nct) + break; + + /* reset the null_password flag, just in case */ + g_fjob.null_password = FALSE; + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + d = (k5_dlg_data *) nct->aux; + if (d == NULL) + break; + + if (d->pwd_change) { + /* we are forcing a password change */ + goto change_password; + } + + _begin_task(0); + _report_mr0(KHERR_NONE, MSG_CTX_INITAL_CREDS); + _describe(); + + if (g_fjob.state == FIBER_STATE_KINIT) { + if(nc->result == KHUI_NC_RESULT_CANCEL) { + g_fjob.command = FIBER_CMD_CANCEL; + SwitchToFiber(k5_kinit_fiber); + + /* if we cancelled out, then we shouldn't care + about the return code. */ +#ifdef DEBUG + assert(g_fjob.state == FIBER_STATE_NONE); +#endif + g_fjob.code = 0; + + _reportf(L"Cancelling"); + } else if (nc->result == KHUI_NC_RESULT_PROCESS) { + khui_cw_sync_prompt_values(nc); + g_fjob.command = FIBER_CMD_CONTINUE; + SwitchToFiber(k5_kinit_fiber); + + /* We get back here once the fiber finishes + processing */ +#ifdef DEBUG + } else { + assert(FALSE); +#endif + } + } else { + /* we weren't in a KINIT state */ + if (nc->result == KHUI_NC_RESULT_CANCEL) { + /* nothing to report */ + g_fjob.code = 0; + } else if (nc->result == KHUI_NC_RESULT_PROCESS) { + /* g_fjob.code should have the result of the + last kinit attempt. We should leave it + as-is */ +#ifdef DEBUG + } else { + /* unknown result */ + assert(FALSE); +#endif + } + } + + /* special case: if there was no password entered, and + if there is a valid TGT we allow the credential + acquisition to go through */ + if (g_fjob.state == FIBER_STATE_NONE && + g_fjob.code && + g_fjob.null_password && + + (nc->n_identities == 0 || + nc->identities[0] == NULL || + KHM_SUCCEEDED(kcdb_credset_find_filtered + (NULL, + -1, + k5_find_tgt_filter, + nc->identities[0], + NULL, + NULL)))) { + _reportf(L"No password entered, but a valid TGT exists. Continuing"); + g_fjob.code = 0; + } else if (g_fjob.state == FIBER_STATE_NONE && + g_fjob.code == 0 && + nc->n_identities > 0 && + nc->identities[0] != NULL) { + + /* we had a password and we used it to get + tickets. We should reset the IMPORTED flag now + since the tickets are not imported. */ + + khm_krb5_set_identity_flags(nc->identities[0], + K5IDFLAG_IMPORTED, + 0); + } + + if(g_fjob.code != 0) { + wchar_t tbuf[1024]; + DWORD suggestion; + kherr_suggestion suggest_code; + + khm_err_describe(g_fjob.code, tbuf, sizeof(tbuf), + &suggestion, &suggest_code); + + _report_cs0(KHERR_ERROR, tbuf); + if (suggestion != 0) + _suggest_mr(suggestion, suggest_code); + + _resolve(); + + r = KHUI_NC_RESPONSE_FAILED; + + if (suggest_code == KHERR_SUGGEST_RETRY) { + r |= KHUI_NC_RESPONSE_NOEXIT | + KHUI_NC_RESPONSE_PENDING; + } + +#ifdef DEBUG + assert(g_fjob.state == FIBER_STATE_NONE); +#endif + + if (g_fjob.valid_principal && + nc->n_identities > 0 && + nc->identities[0]) { + /* the principal was valid, so we can go ahead + and update the LRU */ + k5_update_LRU(nc->identities[0]); + } + + } else if (nc->result == KHUI_NC_RESULT_PROCESS && + g_fjob.state == FIBER_STATE_NONE) { + krb5_context ctx = NULL; + + _reportf(L"Tickets successfully acquired"); + + r = KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT; + + /* if we successfully obtained credentials, we + should save the current settings in the + identity config space */ + + assert(nc->n_identities > 0); + assert(nc->identities[0]); + + k5_write_dlg_params(d, nc->identities[0], g_fjob.ccache); + + /* We should also quickly refresh the credentials + so that the identity flags and ccache + properties reflect the current state of + affairs. This has to be done here so that + other credentials providers which depend on + Krb5 can properly find the initial creds to + obtain their respective creds. */ + + khm_krb5_list_tickets(&ctx); + + if (nc->set_default) { + _reportf(L"Setting default identity"); + kcdb_identity_set_default(nc->identities[0]); + } + + /* If there is no default identity, then make this the default */ + kcdb_identity_refresh(nc->identities[0]); + { + khm_handle tdefault = NULL; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) { + kcdb_identity_release(tdefault); + } else { + _reportf(L"There was no default identity. Setting default"); + kcdb_identity_set_default(nc->identities[0]); + } + } + + /* and update the LRU */ + k5_update_LRU(nc->identities[0]); + + if (ctx != NULL) + pkrb5_free_context(ctx); + } else if (g_fjob.state == FIBER_STATE_NONE) { + /* the user cancelled the operation */ + r = KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_SUCCESS; + } + + if(g_fjob.state == FIBER_STATE_NONE) { + khui_cw_set_response(nc, credtype_id_krb5, r); + + if (r & KHUI_NC_RESPONSE_NOEXIT) { + /* if we are retrying the call, we should + restart the kinit fiber */ +#ifdef DEBUG + assert(r & KHUI_NC_RESPONSE_PENDING); +#endif + + k5_prep_kinit_job(nc); + SwitchToFiber(k5_kinit_fiber); + } else { + /* free up the fiber data fields. */ + k5_free_kinit_job(); + } + } else { + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_NOEXIT | + KHUI_NC_RESPONSE_PENDING | r); + } + + _end_task(); + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + + FILETIME ftidexp = {0,0}; + FILETIME ftcurrent; + khm_size cb; + + GetSystemTimeAsFileTime(&ftcurrent); + + _begin_task(0); + _report_mr0(KHERR_NONE, MSG_CTX_RENEW_CREDS); + _describe(); + + if (nc->ctx.scope == KHUI_SCOPE_IDENT || + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE && + nc->ctx.cred_type == credtype_id_krb5) || + (nc->ctx.scope == KHUI_SCOPE_CRED && + nc->ctx.cred_type == credtype_id_krb5)) { + int code; + + if (nc->ctx.scope == KHUI_SCOPE_CRED && + nc->ctx.cred != NULL) { + + /* get the expiration time for the identity first. */ + cb = sizeof(ftidexp); +#ifdef DEBUG + assert(nc->ctx.identity != NULL); +#endif + kcdb_identity_get_attr(nc->ctx.identity, + KCDB_ATTR_EXPIRE, + NULL, + &ftidexp, + &cb); + + code = khm_krb5_renew_cred(nc->ctx.cred); + + } else if (nc->ctx.scope == KHUI_SCOPE_IDENT && + nc->ctx.identity != 0) { + /* get the current identity expiration time */ + cb = sizeof(ftidexp); + + kcdb_identity_get_attr(nc->ctx.identity, + KCDB_ATTR_EXPIRE, + NULL, + &ftidexp, + &cb); + + code = khm_krb5_renew_ident(nc->ctx.identity); + } else { + + _reportf(L"No identity specified. Can't renew Kerberos tickets"); + + code = 1; /* it just has to be non-zero */ + } + + if (code == 0) { + _reportf(L"Tickets successfully renewed"); + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_SUCCESS); + } else if (nc->ctx.identity == 0) { + + _report_mr0(KHERR_ERROR, MSG_ERR_NO_IDENTITY); + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_FAILED); + } else if (CompareFileTime(&ftcurrent, &ftidexp) < 0) { + wchar_t tbuf[1024]; + DWORD suggestion; + kherr_suggestion sug_id; + + /* if we failed to get new tickets, but the + identity is still valid, then we assume that + the current tickets are still good enough + for other credential types to obtain their + credentials. */ + + khm_err_describe(code, tbuf, sizeof(tbuf), + &suggestion, &sug_id); + + _report_cs0(KHERR_WARNING, tbuf); + if (suggestion) + _suggest_mr(suggestion, sug_id); + + _resolve(); + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_SUCCESS); + } else { + wchar_t tbuf[1024]; + DWORD suggestion; + kherr_suggestion sug_id; + + khm_err_describe(code, tbuf, sizeof(tbuf), + &suggestion, &sug_id); + + _report_cs0(KHERR_ERROR, tbuf); + if (suggestion) + _suggest_mr(suggestion, sug_id); + + _resolve(); + + khui_cw_set_response(nc, credtype_id_krb5, + ((sug_id == KHERR_SUGGEST_RETRY)?KHUI_NC_RESPONSE_NOEXIT:KHUI_NC_RESPONSE_EXIT) | + KHUI_NC_RESPONSE_FAILED); + } + } else { + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_SUCCESS); + } + + _end_task(); + } else if (nc->subtype == KMSG_CRED_PASSWORD && + nc->result == KHUI_NC_RESULT_PROCESS) { + + change_password: + /* we jump here if there was a password change forced */ + + _begin_task(0); + _report_mr0(KHERR_NONE, MSG_CTX_PASSWD); + _describe(); + + khui_cw_lock_nc(nc); + + if (nc->result == KHUI_NC_RESULT_CANCEL) { + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + + } else if (nc->n_identities == 0 || + nc->identities[0] == NULL) { + _report_mr0(KHERR_ERROR, MSG_PWD_NO_IDENTITY); + _suggest_mr(MSG_PWD_S_NO_IDENTITY, KHERR_SUGGEST_RETRY); + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_FAILED | + KHUI_NC_RESPONSE_NOEXIT); + + } else { + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + char idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t wpwd[KHUI_MAXCCH_PASSWORD]; + char pwd[KHUI_MAXCCH_PASSWORD]; + wchar_t wnpwd[KHUI_MAXCCH_PASSWORD]; + char npwd[KHUI_MAXCCH_PASSWORD]; + wchar_t wnpwd2[KHUI_MAXCCH_PASSWORD]; + wchar_t * wresult; + char * result; + khm_size n_prompts = 0; + khm_size cb; + khm_int32 rv = KHM_ERROR_SUCCESS; + long code = 0; + khm_handle ident; + + khui_cw_get_prompt_count(nc, &n_prompts); + assert(n_prompts == 3); + + ident = nc->identities[0]; + cb = sizeof(widname); + rv = kcdb_identity_get_name(ident, widname, &cb); + if (KHM_FAILED(rv)) { +#ifdef DEBUG + assert(FALSE); +#endif + _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN); + goto _pwd_exit; + } + + cb = sizeof(wpwd); + rv = khui_cw_get_prompt_value(nc, 0, wpwd, &cb); + if (KHM_FAILED(rv)) { +#ifdef DEBUG + assert(FALSE); +#endif + _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN); + goto _pwd_exit; + } + + cb = sizeof(wnpwd); + rv = khui_cw_get_prompt_value(nc, 1, wnpwd, &cb); + if (KHM_FAILED(rv)) { +#ifdef DEBUG + assert(FALSE); +#endif + _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN); + goto _pwd_exit; + } + + cb = sizeof(wnpwd2); + rv = khui_cw_get_prompt_value(nc, 2, wnpwd2, &cb); + if (KHM_FAILED(rv)) { +#ifdef DEBUG + assert(FALSE); +#endif + _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN); + goto _pwd_exit; + } + + if (wcscmp(wnpwd, wnpwd2)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr0(KHERR_ERROR, MSG_PWD_NOT_SAME); + _suggest_mr(MSG_PWD_S_NOT_SAME, KHERR_SUGGEST_INTERACT); + goto _pwd_exit; + } + + if (!wcscmp(wpwd, wnpwd)) { + rv = KHM_ERROR_INVALID_PARAM; + _report_mr0(KHERR_ERROR, MSG_PWD_SAME); + _suggest_mr(MSG_PWD_S_SAME, KHERR_SUGGEST_INTERACT); + goto _pwd_exit; + } + + UnicodeStrToAnsi(idname, sizeof(idname), widname); + UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd); + UnicodeStrToAnsi(npwd, sizeof(npwd), wnpwd); + + result = NULL; + + code = khm_krb5_changepwd(idname, + pwd, + npwd, + &result); + + if (code) + rv = KHM_ERROR_UNKNOWN; + else { + khm_handle csp_idcfg = NULL; + krb5_context ctx = NULL; + + /* we set a new password. now we need to get + initial credentials. */ + + d = (k5_dlg_data *) nct->aux; + + if (d == NULL) { + rv = KHM_ERROR_UNKNOWN; + goto _pwd_exit; + } + + if (nc->subtype == KMSG_CRED_PASSWORD) { + /* since this was just a password change, + we need to load new credentials options + from the configuration store. */ + + k5_read_dlg_params(d, nc->identities[0]); + } + + /* the password change phase is now done */ + d->pwd_change = FALSE; + +#ifdef DEBUG + _reportf(L"Calling khm_krb5_kinit()"); +#endif + code = khm_krb5_kinit(NULL, /* context (create one) */ + idname, /* principal_name */ + npwd, /* new password */ + NULL, /* ccache name (figure out the identity cc)*/ + (krb5_deltat) d->tc_lifetime.current, + d->forwardable, + d->proxiable, + (krb5_deltat)((d->renewable)?d->tc_renew.current:0), + d->addressless, /* addressless */ + d->publicIP, /* public IP */ + NULL, /* prompter */ + NULL /* prompter data */); + + if (code) { + rv = KHM_ERROR_UNKNOWN; + goto _pwd_exit; + } + + /* save the settings that we used for + obtaining the ticket. */ + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + + k5_write_dlg_params(d, nc->identities[0], NULL); + + /* and then update the LRU too */ + k5_update_LRU(nc->identities[0]); + } + + /* and do a quick refresh of the krb5 tickets + so that other plug-ins that depend on krb5 + can look up tickets inside NetIDMgr */ + khm_krb5_list_tickets(&ctx); + + /* if there was no default identity, we make + this one the default. */ + kcdb_identity_refresh(nc->identities[0]); + { + khm_handle tdefault = NULL; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) { + kcdb_identity_release(tdefault); + } else { + _reportf(L"There was no default identity. Setting defualt"); + kcdb_identity_set_default(nc->identities[0]); + } + } + + if (ctx != NULL) + pkrb5_free_context(ctx); + + if (nc->subtype == KMSG_CRED_PASSWORD) { + /* if we obtained new credentials as a + result of successfully changing the + password, we also schedule an identity + renewal for this identity. This allows + the other credential types to obtain + credentials for this identity. */ + khui_action_context ctx; + + _reportf(L"Scheduling renewal of [%s] after password change", + widname); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->identities[0], + KCDB_CREDTYPE_INVALID, + NULL); + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + } + } + + /* result is only set when code != 0 */ + if (code && result) { + size_t len; + + StringCchLengthA(result, KHERR_MAXCCH_STRING, + &len); + wresult = PMALLOC((len + 1) * sizeof(wchar_t)); +#ifdef DEBUG + assert(wresult); +#endif + AnsiStrToUnicode(wresult, (len + 1) * sizeof(wchar_t), + result); + + _report_cs1(KHERR_ERROR, L"%1!s!", _cstr(wresult)); + _resolve(); + + PFREE(result); + PFREE(wresult); + + /* we don't need to report anything more */ + code = 0; + } + + _pwd_exit: + if (KHM_FAILED(rv)) { + if (code) { + wchar_t tbuf[1024]; + DWORD suggestion; + kherr_suggestion sug_id; + + khm_err_describe(code, tbuf, sizeof(tbuf), + &suggestion, &sug_id); + _report_cs0(KHERR_ERROR, tbuf); + + if (suggestion) + _suggest_mr(suggestion, sug_id); + + _resolve(); + } + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_NOEXIT| + KHUI_NC_RESPONSE_FAILED); + } else { + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + } + } + + khui_cw_unlock_nc(nc); + + _end_task(); + } /* KMSG_CRED_PASSWORD */ + } + break; + + case KMSG_CRED_END: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + + nc = (khui_new_creds *) vparam; + khui_cw_find_type(nc, credtype_id_krb5, &nct); + + if(!nct) + break; + + khui_cw_del_type(nc, credtype_id_krb5); + + if (nct->name) + PFREE(nct->name); + if (nct->credtext) + PFREE(nct->credtext); + + PFREE(nct); + + k5_free_kinit_job(); + } + break; + + case KMSG_CRED_IMPORT: + { + khm_int32 t = 0; + +#ifdef DEBUG + assert(csp_params); +#endif + khc_read_int32(csp_params, L"MsLsaImport", &t); + + if (t != K5_LSAIMPORT_NEVER) { + krb5_context ctx = NULL; + khm_handle id_default = NULL; + khm_handle id_imported = NULL; + BOOL imported; + + imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE, + &id_imported); + if (imported) { + if (id_imported) + k5_ensure_identity_ccache_is_watched(id_imported, NULL); + + khm_krb5_list_tickets(&ctx); + + if (ctx) + pkrb5_free_context(ctx); + + kcdb_identity_refresh(id_imported); + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&id_default))) { + kcdb_identity_release(id_default); + id_default = NULL; + } else { + _reportf(L"There was no default identity. Setting default"); + kcdb_identity_set_default(id_imported); + } + + /* and update the LRU */ + k5_update_LRU(id_imported); + } + + if (id_imported) + kcdb_identity_release(id_imported); + } + } + break; + } + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5plugin.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5plugin.c new file mode 100644 index 000000000..61331f384 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5plugin.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<commctrl.h> +#include<strsafe.h> +#include<krb5.h> + +#ifdef DEBUG +#include<assert.h> +#endif + +khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID; +khm_boolean krb5_initialized = FALSE; +khm_handle krb5_credset = NULL; + +khm_handle k5_sub = NULL; + +LPVOID k5_main_fiber = NULL; +LPVOID k5_kinit_fiber = NULL; + +VOID CALLBACK k5_kinit_fiber_proc(PVOID lpParameter); + +krb5_context k5_identpro_ctx = NULL; + +/* The system message handler. + + Runs in the context of the plugin thread */ +khm_int32 KHMAPI +k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_SYSTEM_INIT: + { + kcdb_credtype ct; + wchar_t buf[KCDB_MAXCCH_SHORT_DESC]; + size_t cbsize; + + /* perform critical registrations and initialization + stuff */ + ZeroMemory(&ct, sizeof(ct)); + ct.id = KCDB_CREDTYPE_AUTO; + ct.name = KRB5_CREDTYPE_NAME; + + if(LoadString(hResModule, IDS_KRB5_SHORT_DESC, + buf, ARRAYLENGTH(buf))) { + StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize); + cbsize += sizeof(wchar_t); + ct.short_desc = PMALLOC(cbsize); + StringCbCopy(ct.short_desc, cbsize, buf); + } + + /* even though ideally we should be setting limits + based KCDB_MAXCB_LONG_DESC, our long description + actually fits nicely in KCDB_MAXCB_SHORT_DESC */ + if(LoadString(hResModule, IDS_KRB5_LONG_DESC, + buf, ARRAYLENGTH(buf))) { + StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize); + cbsize += sizeof(wchar_t); + ct.long_desc = PMALLOC(cbsize); + StringCbCopy(ct.long_desc, cbsize, buf); + } + + ct.icon = NULL; /* TODO: set a proper icon */ + + kmq_create_subscription(k5_msg_callback, &ct.sub); + + ct.is_equal = khm_krb5_creds_is_equal; + + rv = kcdb_credtype_register(&ct, &credtype_id_krb5); + + if(KHM_SUCCEEDED(rv)) + rv = kcdb_credset_create(&krb5_credset); + + if(ct.short_desc) + PFREE(ct.short_desc); + + if(ct.long_desc) + PFREE(ct.long_desc); + + if(KHM_SUCCEEDED(rv)) { + krb5_context ctx = NULL; + + krb5_initialized = TRUE; + + /* now convert this thread to a fiber and create a + separate fiber to do kinit stuff */ + k5_main_fiber = ConvertThreadToFiber(NULL); + k5_kinit_fiber = CreateFiber(0,k5_kinit_fiber_proc,NULL); + + ZeroMemory(&g_fjob, sizeof(g_fjob)); + + kmq_create_subscription(k5_msg_callback, &k5_sub); + + k5_register_config_panels(); + + khm_krb5_list_tickets(&ctx); + + if(ctx != NULL) + pkrb5_free_context(ctx); + } + } + break; + + case KMSG_SYSTEM_EXIT: + + k5_unregister_config_panels(); + + if(credtype_id_krb5 >= 0) { + /* basically just unregister the credential type */ + kcdb_credtype_unregister(credtype_id_krb5); + + /* kcdb knows how to deal with bad handles */ + kcdb_credset_delete(krb5_credset); + krb5_credset = NULL; + } + + if(k5_main_fiber != NULL) { + if (k5_kinit_fiber) { +#ifdef DEBUG + assert(k5_kinit_fiber != GetCurrentFiber()); +#endif +#ifdef CLEANUP_FIBERS_ON_EXIT + DeleteFiber(k5_kinit_fiber); + CloseHandle(k5_kinit_fiber); +#endif + k5_kinit_fiber = NULL; + } + + k5_main_fiber = NULL; + } + + if(k5_sub != NULL) { + kmq_delete_subscription(k5_sub); + k5_sub = NULL; + } + + break; + } + + return rv; +} + +khm_int32 KHMAPI +k5_msg_kcdb(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_KCDB_IDENT: + if (uparam == KCDB_OP_DELCONFIG) { + k5_remove_from_LRU((khm_handle) vparam); + } + break; + } + + return rv; +} + + +/* Handler for CRED type messages + + Runs in the context of the Krb5 plugin +*/ +khm_int32 KHMAPI +k5_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_CRED_REFRESH: + { + krb5_context ctx = NULL; + + khm_krb5_list_tickets(&ctx); + + if(ctx != NULL) + pkrb5_free_context(ctx); + } + break; + + case KMSG_CRED_DESTROY_CREDS: + { + khui_action_context * ctx; + + ctx = (khui_action_context *) vparam; + + if (ctx->credset) { + _begin_task(0); + _report_mr0(KHERR_INFO, MSG_ERR_CTX_DESTROY_CREDS); + _describe(); + + khm_krb5_destroy_by_credset(ctx->credset); + + _end_task(); + } + } + break; + + case KMSG_CRED_PP_BEGIN: + k5_pp_begin((khui_property_sheet *) vparam); + break; + + case KMSG_CRED_PP_END: + k5_pp_end((khui_property_sheet *) vparam); + break; + + default: + if(IS_CRED_ACQ_MSG(msg_subtype)) + return k5_msg_cred_dialog(msg_type, msg_subtype, + uparam, vparam); + } + + return rv; +} + +/* The main message handler. We don't do much here, except delegate + to other message handlers + + Runs in the context of the Krb5 plugin +*/ +khm_int32 KHMAPI +k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + switch(msg_type) { + case KMSG_SYSTEM: + return k5_msg_system(msg_type, msg_subtype, uparam, vparam); + case KMSG_CRED: + return k5_msg_cred(msg_type, msg_subtype, uparam, vparam); + case KMSG_KCDB: + return k5_msg_kcdb(msg_type, msg_subtype, uparam, vparam); + } + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krb5props.c b/krb5-1-6/src/windows/identity/plugins/krb5/krb5props.c new file mode 100644 index 000000000..312b576fd --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krb5props.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<krbcred.h> +#include<kherror.h> +#include<khmsgtypes.h> +#include<commctrl.h> +#include<strsafe.h> +#include<krb5.h> +#ifdef DEBUG +#include<assert.h> +#endif + +/* Property page + + Runs in the context of the UI thread. + */ +INT_PTR CALLBACK krb5_pp_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + switch(uMsg) { + case WM_INITDIALOG: + { + khui_property_sheet * s; + PROPSHEETPAGE * p; + wchar_t buf[512]; + wchar_t unavailable[64]; + khm_size cbsize; + khm_int32 rv; + khm_int32 tflags; + + p = (PROPSHEETPAGE *) lParam; + s = (khui_property_sheet *) p->lParam; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s); +#pragma warning(pop) + + LoadString(hResModule, IDS_UNAVAILABLE, + unavailable, ARRAYLENGTH(unavailable)); + + if(s->cred) { + cbsize = sizeof(buf); + kcdb_cred_get_name(s->cred, buf, &cbsize); + SetDlgItemText(hwnd, IDC_PPK5_NAME, buf); + + cbsize = sizeof(buf); + rv = kcdb_cred_get_attr_string(s->cred, + KCDB_ATTR_ISSUE, + buf, &cbsize, 0); + if (KHM_SUCCEEDED(rv)) + SetDlgItemText(hwnd, IDC_PPK5_ISSUE, buf); + else + SetDlgItemText(hwnd, IDC_PPK5_ISSUE, unavailable); + + cbsize = sizeof(buf); + rv = kcdb_cred_get_attr_string(s->cred, + KCDB_ATTR_EXPIRE, + buf, &cbsize, 0); + if (KHM_SUCCEEDED(rv)) + SetDlgItemText(hwnd, IDC_PPK5_VALID, buf); + else + SetDlgItemText(hwnd, IDC_PPK5_VALID, unavailable); + + cbsize = sizeof(buf); + rv = kcdb_cred_get_attr_string(s->cred, + KCDB_ATTR_RENEW_EXPIRE, + buf, &cbsize, 0); + if (KHM_SUCCEEDED(rv)) + SetDlgItemText(hwnd, IDC_PPK5_RENEW, buf); + else + SetDlgItemText(hwnd, IDC_PPK5_RENEW, unavailable); + + tflags = 0; + cbsize = sizeof(tflags); + rv = kcdb_cred_get_attr(s->cred, + attr_id_krb5_flags, + NULL, + &tflags, + &cbsize); + if (KHM_SUCCEEDED(rv)) { + +#define ADDBITFLAG(f,s) \ + if (tflags & f) { \ + LoadString(hResModule, s, buf, ARRAYLENGTH(buf)); \ + SendDlgItemMessage(hwnd, IDC_PPK5_FLAGS, LB_ADDSTRING, 0, (LPARAM) buf); \ + } + + ADDBITFLAG(TKT_FLG_FORWARDABLE, IDS_FLG_FORWARDABLE); + ADDBITFLAG(TKT_FLG_FORWARDED, IDS_FLG_FORWARDED); + ADDBITFLAG(TKT_FLG_PROXIABLE, IDS_FLG_PROXIABLE); + ADDBITFLAG(TKT_FLG_PROXY, IDS_FLG_PROXY); + ADDBITFLAG(TKT_FLG_MAY_POSTDATE, IDS_FLG_MAY_POSTDATE); + ADDBITFLAG(TKT_FLG_POSTDATED, IDS_FLG_POSTDATED); + ADDBITFLAG(TKT_FLG_INVALID, IDS_FLG_INVALID); + ADDBITFLAG(TKT_FLG_RENEWABLE, IDS_FLG_RENEWABLE); + ADDBITFLAG(TKT_FLG_INITIAL, IDS_FLG_INITIAL); + ADDBITFLAG(TKT_FLG_PRE_AUTH, IDS_FLG_PRE_AUTH); + ADDBITFLAG(TKT_FLG_HW_AUTH, IDS_FLG_HW_AUTH); + ADDBITFLAG(TKT_FLG_TRANSIT_POLICY_CHECKED, IDS_FLG_TRANSIT_POL); + ADDBITFLAG(TKT_FLG_OK_AS_DELEGATE, IDS_FLG_OK_DELEGATE); + ADDBITFLAG(TKT_FLG_ANONYMOUS, IDS_FLG_ANONYMOUS); + +#undef ADDBITFLAG + + } + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } + return FALSE; + } + + return FALSE; +} + +void k5_pp_begin(khui_property_sheet * s) +{ + PROPSHEETPAGE *p; + + if(s->credtype == credtype_id_krb5 && + s->cred) { + p = PMALLOC(sizeof(*p)); + ZeroMemory(p, sizeof(*p)); + + p->dwSize = sizeof(*p); + p->dwFlags = 0; + p->hInstance = hResModule; + p->pszTemplate = MAKEINTRESOURCE(IDD_PP_KRB5C); + p->pfnDlgProc = krb5_pp_proc; + p->lParam = (LPARAM) s; + khui_ps_add_page(s, credtype_id_krb5, 0, p, NULL); + } +} + +void k5_pp_end(khui_property_sheet * s) +{ + khui_property_page * p = NULL; + + khui_ps_find_page(s, credtype_id_krb5, &p); + if(p) { + if(p->p_page) + PFREE(p->p_page); + p->p_page = NULL; + } +} + diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krbconfig.csv b/krb5-1-6/src/windows/identity/plugins/krb5/krbconfig.csv new file mode 100644 index 000000000..3bb30ea77 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krbconfig.csv @@ -0,0 +1,45 @@ +Name,Type,Value,Description +Krb5Cred,KC_SPACE,0,Kerberos V Credentials Provider + Module,KC_STRING,MITKrb5, + Description,KC_STRING,Kerberos V Credentials Provider, + Type,KC_INT32,1, + Flags,KC_INT32,0, + Parameters,KC_SPACE,0,Parameters for KrbCred + CreateMissingConfig,KC_INT32,0,Create missing configuration files + MsLsaImport,KC_INT32,1,Automatically import MSLSA credentials: 0-never 1-always 2-if principle matches + MsLsaList,KC_INT32,1,Include MSLSA in the credentials list + FileCCList,KC_STRING,,List of file CCaches to include in listing + AutoRenewTickets,KC_INT32,1,Automatically renew expiring tickets + DefaultLifetime,KC_INT32,36000,Default ticket lifetime + MaxLifetime,KC_INT32,86400,Maximum lifetime + MinLifetime,KC_INT32,60,Minimum lifetime + Forwardable,KC_INT32,1,Obtain forwardable tickets (boolean) + Proxiable,KC_INT32,0,Obtain proxiable tickets (boolean) + Addressless,KC_INT32,1,Obtain addressless tickets (boolean) + PublicIP,KC_INT32,0,Additional public IP address to use (int32) + Renewable,KC_INT32,1,Obtain renewable tickets (boolean) + DefaultRenewLifetime,KC_INT32,604800,Default renewable lifetime + MaxRenewLifetime,KC_INT32,2592000,Maximum renewable lifetime + MinRenewLifetime,KC_INT32,60,Maximum renewable lifetime + UseFullRealmList,KC_INT32,0,Use the full list of realms in the New Creds dialog + LRURealms,KC_STRING,, + LRUPrincipals,KC_STRING,, + LastDefaultIdent,KC_STRING,,Last known default identity + PromptCacheLifetime,KC_INT32,172800,Lifetime of the prompt cache in seconds + DefaultCCName,KC_STRING,,Default CC name (only per identity) + DefaultToFileCache,KC_INT32,0,"If no DefaultCCName is specified for an identity, use a generated FILE: cache instead of an API: cache" + PromptCache,KC_SPACE,0,Cache of prompts (only per identity) + Name,KC_STRING,, + Banner,KC_STRING,, + PromptCount,KC_INT32,0, + ExpiresOn,KC_INT64,0,FILETIME of when the prompt cache is set to expire + (n),KC_SPACE,0,Parameters for each prompt + Prompt,KC_STRING,, + Type,KC_INT32,0, + Flags,KC_INT32,0, + (n),KC_ENDSPACE,0, + PromptCache,KC_ENDSPACE,0, + Realms,KC_SPACE,0,Realm specific configuration (same schema as per identity config) + Realms,KC_ENDSPACE,0, + Parameters,KC_ENDSPACE,0, +Krb5Cred,KC_ENDSPACE,0, diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/krbcred.h b/krb5-1-6/src/windows/identity/plugins/krb5/krbcred.h new file mode 100644 index 000000000..a194343ac --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/krbcred.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KRBAFSCRED_H +#define __KHIMAIRA_KRBAFSCRED_H + +#include<windows.h> + +/* While we generally pull resources out of hResModule, the message + strings for all the languages are kept in the main DLL. */ +#define KHERR_HMODULE hInstance +#define KHERR_FACILITY k5_facility +#define KHERR_FACILITY_ID 64 + +#include<netidmgr.h> + +#include<krb5funcs.h> +#include<krb5common.h> +#include<errorfuncs.h> +#include<dynimport.h> + +#include<langres.h> +#include<datarep.h> +#include<krb5_msgs.h> + +typedef enum tag_k5_lsa_import { + K5_LSAIMPORT_NEVER = 0, + K5_LSAIMPORT_ALWAYS = 1, + K5_LSAIMPORT_MATCH = 2, /* only when the principal name matches */ +} k5_lsa_import; + +#define TYPENAME_ENCTYPE L"EncType" +#define TYPENAME_ADDR_LIST L"AddrList" +#define TYPENAME_KRB5_FLAGS L"Krb5Flags" +#define TYPENAME_KRB5_PRINC L"Krb5Principal" +#define TYPENAME_KVNO L"Kvno" + +#define ATTRNAME_KEY_ENCTYPE L"KeyEncType" +#define ATTRNAME_TKT_ENCTYPE L"TktEncType" +#define ATTRNAME_ADDR_LIST L"AddrList" +#define ATTRNAME_KRB5_FLAGS L"Krb5Flags" +#define ATTRNAME_KRB5_CCNAME L"Krb5CCName" +#define ATTRNAME_KVNO L"Kvno" +#define ATTRNAME_KRB5_IDFLAGS L"Krb5IDFlags" + +/* Flag bits for Krb5IDFlags property */ + +/* identity was imported from MSLSA: */ +#define K5IDFLAG_IMPORTED 0x00000001 + +void init_krb(); +void exit_krb(); + +/* globals */ +extern kmm_module h_khModule; +extern HMODULE hResModule; +extern HINSTANCE hInstance; +extern const wchar_t * k5_facility; + +extern khm_int32 type_id_enctype; +extern khm_int32 type_id_addr_list; +extern khm_int32 type_id_krb5_flags; +extern khm_int32 type_id_krb5_princ; +extern khm_int32 type_id_kvno; + +extern BOOL type_regd_krb5_princ; + +extern khm_int32 attr_id_key_enctype; +extern khm_int32 attr_id_tkt_enctype; +extern khm_int32 attr_id_addr_list; +extern khm_int32 attr_id_krb5_flags; +extern khm_int32 attr_id_krb5_ccname; +extern khm_int32 attr_id_kvno; +extern khm_int32 attr_id_krb5_idflags; + +extern khm_ui_4 k5_commctl_version; + +#define IS_COMMCTL6() (k5_commctl_version >= 0x60000) + +/* Configuration spaces */ +#define CSNAME_KRB5CRED L"Krb5Cred" +#define CSNAME_PARAMS L"Parameters" +#define CSNAME_PROMPTCACHE L"PromptCache" +#define CSNAME_REALMS L"Realms" + +/* plugin constants */ +#define KRB5_PLUGIN_NAME L"Krb5Cred" +#define KRB5_IDENTPRO_NAME L"Krb5Ident" + +#define KRB5_CREDTYPE_NAME L"Krb5Cred" + +/* limits */ +/* maximum number of characters in a realm name */ +#define K5_MAXCCH_REALM 256 + +/* maximum number of characters in a host name */ +#define K5_MAXCCH_HOST 128 + +/* maximum number of KDC's per realm */ +#define K5_MAX_KDC 64 + +/* maximum number of domains that map to a realm */ +#define K5_MAX_DOMAIN_MAPPINGS 32 + +extern khm_handle csp_plugins; +extern khm_handle csp_krbcred; +extern khm_handle csp_params; + +extern kconf_schema schema_krbconfig[]; + +/* other globals */ +extern khm_int32 credtype_id_krb5; + +extern khm_boolean krb5_initialized; + +extern khm_handle krb5_credset; + +extern khm_handle k5_sub; + +extern krb5_context k5_identpro_ctx; + +extern BOOL is_k5_identpro; + +/* plugin callbacks */ +khm_int32 KHMAPI k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam); +khm_int32 KHMAPI k5_ident_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam); + +/* kinit fiber */ +typedef struct _fiber_job_t { + int command; + + khui_new_creds * nc; + khui_new_creds_by_type * nct; + HWND dialog; + + khm_handle identity; + char * principal; + char * password; + char * ccache; + krb5_deltat lifetime; + DWORD forwardable; + DWORD proxiable; + DWORD renewable; + krb5_deltat renew_life; + DWORD addressless; + DWORD publicIP; + + int code; + int state; + int prompt_set; + + BOOL null_password; + BOOL valid_principal; + BOOL retry_if_valid_principal; +} fiber_job; + +extern fiber_job g_fjob; /* global fiber job object */ + +#define FIBER_CMD_KINIT 1 +#define FIBER_CMD_CANCEL 2 +#define FIBER_CMD_CONTINUE 3 + +#define FIBER_STATE_NONE 0 +#define FIBER_STATE_KINIT 1 +#define FIBER_STATE_RETRY_KINIT 2 + +#define K5_SET_CRED_MSG WMNC_USER + +void +k5_pp_begin(khui_property_sheet * s); + +void +k5_pp_end(khui_property_sheet * s); + +khm_int32 KHMAPI +k5_msg_cred_dialog(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam); + +khm_int32 KHMAPI +k5_msg_ident(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam); + +khm_int32 +k5_remove_from_LRU(khm_handle identity); + +int +k5_get_realm_from_nc(khui_new_creds * nc, + wchar_t * buf, + khm_size cch_buf); + +void +k5_register_config_panels(void); + +void +k5_unregister_config_panels(void); + +INT_PTR CALLBACK +k5_ccconfig_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +k5_id_tab_dlgproc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +k5_ids_tab_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/lang/en_us/langres.rc b/krb5-1-6/src/windows/identity/plugins/krb5/lang/en_us/langres.rc new file mode 100644 index 000000000..bcf837587 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/lang/en_us/langres.rc @@ -0,0 +1,507 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\..\langres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\..\\langres.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NC_KRB5 DIALOGEX 0, 0, 300, 166 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Kerberos v5 Credential Options",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11 + LTEXT "Realm",IDC_STATIC,7,25,52,13 + COMBOBOX IDC_NCK5_REALM,60,25,233,51,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Specify &additional realms ...",IDC_NCK5_ADD_REALMS,181,43,112,16,BS_NOTIFY | NOT WS_VISIBLE | WS_DISABLED + LTEXT "&Lifetime",IDC_STATIC,7,67,61,12 + EDITTEXT IDC_NCK5_LIFETIME_EDIT,85,67,107,12,ES_AUTOHSCROLL + CONTROL "&Renewable for",IDC_NCK5_RENEWABLE,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,7,87,64,12 + EDITTEXT IDC_NCK5_RENEW_EDIT,85,87,108,12,ES_AUTOHSCROLL + CONTROL "Can be &forwarded to other machines",IDC_NCK5_FORWARDABLE, + "Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,7,107,132,12 + CONTROL "Addressless",IDC_NCK5_ADDRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,128,54,10 + LTEXT "Additional IP address",IDC_STATIC,118,129,68,8,NOT WS_VISIBLE + CONTROL "",IDC_NCK5_PUBLICIP,"SysIPAddress32",NOT WS_VISIBLE | WS_TABSTOP,193,125,100,15 +END + +IDD_PP_KRB5C DIALOGEX 0, 0, 235, 156 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Kerberos v5" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "Name",IDC_STATIC,7,7,19,8 + LTEXT "Valid till",IDC_STATIC,7,39,24,8 + LTEXT "Renewable till",IDC_STATIC,7,55,45,12 + LTEXT "Issued on",IDC_STATIC,7,23,32,8 + LTEXT "Credential flags",IDC_STATIC,7,75,51,8 + EDITTEXT IDC_PPK5_NAME,72,7,156,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_PPK5_ISSUE,72,23,156,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_PPK5_VALID,72,39,156,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_PPK5_RENEW,72,55,156,12,ES_AUTOHSCROLL | ES_READONLY + LISTBOX IDC_PPK5_FLAGS,72,74,156,75,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +END + +IDD_PP_KRB5 DIALOGEX 0, 0, 235, 156 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Kerberos v5" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "Default realm",IDC_STATIC,7,7,44,8 + LTEXT "Default lifetime",IDC_STATIC,7,22,49,8 + LTEXT "Minimum lifetime",IDC_STATIC,7,37,52,8 + LTEXT "Maximum lifetime",IDC_STATIC,7,52,55,8 + LTEXT "Renewable lifetime",IDC_STATIC,7,67,61,8 + LTEXT "Min. Renewable lifetime",IDC_STATIC,7,82,76,8 + LTEXT "Max. Renewable lifetime",IDC_STATIC,7,97,79,8 + GROUPBOX "Default credential flags",IDC_STATIC,7,113,221,36 + CONTROL "Proxiable",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,129,45,10 + CONTROL "Renewable",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,129,51,10 + CONTROL "Forwardable",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,89,129,56,10 + LTEXT "ATHENA.MIT.EDU",IDC_STATIC,95,7,133,11,0,WS_EX_CLIENTEDGE + LTEXT "10 hours",IDC_STATIC,95,22,133,11,0,WS_EX_CLIENTEDGE + LTEXT "1 minute",IDC_STATIC,95,37,133,11,0,WS_EX_CLIENTEDGE + LTEXT "7 days",IDC_STATIC,95,52,133,11,0,WS_EX_CLIENTEDGE + LTEXT "7 days",IDC_STATIC,95,67,133,11,0,WS_EX_CLIENTEDGE + LTEXT "1 minute",IDC_STATIC,95,82,133,11,0,WS_EX_CLIENTEDGE + LTEXT "21 days",IDC_STATIC,95,97,133,11,0,WS_EX_CLIENTEDGE +END + +IDD_CONFIG DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Default Realm",IDC_CFG_LBL_REALM,13,9,46,8 + COMBOBOX IDC_CFG_DEFREALM,76,7,166,51,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Include all configured realms in New Credentials realm list",IDC_CFG_INCREALMS, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,76,26,166,22 + PUSHBUTTON "Configure Realms ...",IDC_CFG_CFGREALMS,76,46,84,14,NOT WS_VISIBLE | WS_DISABLED + GROUPBOX "Configuration File",IDC_CFG_CFGFILEGRP,7,59,241,47 + LTEXT "Location",IDC_CFG_LBL_CFGFILE,13,74,28,8 + EDITTEXT IDC_CFG_CFGFILE,76,71,166,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Browse...",IDC_CFG_BROWSE,145,89,44,14,NOT WS_VISIBLE + CONTROL "Create file if missing",IDC_CFG_CREATECONFIG,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,76,93,80,10 + PUSHBUTTON "Load into realm editor ...",IDC_CFG_BROWSE2,26,89,100,14,NOT WS_VISIBLE + GROUPBOX "Microsoft Windows® Options",IDC_CFG_WINGRP,7,110,241,65 + LTEXT "Hostname",IDC_CFG_LBL_HOSTNAME,13,123,33,8 + EDITTEXT IDC_CFG_HOSTNAME,76,120,166,14,ES_AUTOHSCROLL | ES_READONLY + LTEXT "Domain",IDC_CFG_LBL_DOMAIN,13,141,24,8 + EDITTEXT IDC_CFG_DOMAIN,76,138,166,14,ES_AUTOHSCROLL | ES_READONLY + LTEXT "Import credentials",IDC_LBL_IMPORT,13,158,45,8 + COMBOBOX IDC_CFG_IMPORT,76,156,166,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + +IDD_CFG_REALMS DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_CFG_REALMS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_TABSTOP,7,19,81,148 + GROUPBOX "Kerberos v5 Servers",IDC_CFG_SERVERSGRP,93,7,155,91 + GROUPBOX "Domain to Realm mappings",IDC_CFG_DOMAINGRP,93,101,155,74 + CONTROL "",IDC_CFG_KDC,"SysListView32",LVS_REPORT | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_TABSTOP,99,19,143,72 + CONTROL "",IDC_CFG_DMAP,"SysListView32",LVS_REPORT | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_TABSTOP,99,111,143,56 +END + +IDD_CFG_IDS_TAB DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Ticket &lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8 + EDITTEXT IDC_CFG_DEFLIFE,94,7,134,14,ES_AUTOHSCROLL + LTEXT "Ticket re&newable lifetime",IDC_CFG_LBL_DEFRLIFE,7,29,80,8 + EDITTEXT IDC_CFG_DEFRLIFE,94,26,134,14,ES_AUTOHSCROLL + CONTROL "&Renewable",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,47,51,10 + CONTROL "&Forwardable",IDC_CFG_FORWARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,94,47,56,10 + CONTROL "&Addressless",IDC_CFG_ADDRESSLESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,63,54,10 + GROUPBOX "Credential lifetime range",IDC_CFG_LIFEGRP,7,79,221,31 + LTEXT "From",IDC_STATIC,13,93,17,8 + EDITTEXT IDC_CFG_LRNG_MIN,38,90,79,14,ES_AUTOHSCROLL + LTEXT "To",IDC_STATIC,125,93,9,8 + EDITTEXT IDC_CFG_LRNG_MAX,143,90,79,14,ES_AUTOHSCROLL + GROUPBOX "Credential renewable lifetime range",IDC_STATIC,7,113,221,31 + LTEXT "From",IDC_STATIC,13,128,17,8 + EDITTEXT IDC_CFG_RLRNG_MIN,38,125,79,14,ES_AUTOHSCROLL + LTEXT "To",IDC_STATIC,125,128,9,8 + EDITTEXT IDC_CFG_RLRNG_MAX,143,125,79,14,ES_AUTOHSCROLL +END + +IDD_CFG_ID_TAB DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Credential lifetime",IDC_CFG_LBL_DEFLIFE,7,10,58,8 + EDITTEXT IDC_CFG_DEFLIFE,91,7,137,14,ES_AUTOHSCROLL + CONTROL "Renewable for",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,41,63,10 + EDITTEXT IDC_CFG_DEFRLIFE,91,39,137,14,ES_AUTOHSCROLL + CONTROL "Can be forwarded to other machines",IDC_CFG_FORWARD, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,59,133,10 + CONTROL "Addressless",IDC_CFG_ADDRESSLESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,77,54,10 + LTEXT "Additional IP address",IDC_STATIC,91,78,68,8,NOT WS_VISIBLE + CONTROL "",IDC_CFG_PUBLICIP,"SysIPAddress32",NOT WS_VISIBLE | WS_TABSTOP,128,89,100,15 + LTEXT "Credential cache",IDC_STATIC,7,132,58,8 + EDITTEXT IDC_CFG_CCACHE,91,130,137,14,ES_AUTOHSCROLL +END + +IDD_NC_KRB5_PASSWORD DIALOGEX 0, 0, 300, 166 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Kerberos v5 Change Password Options",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11 + LTEXT "Realm",IDC_STATIC,7,25,52,13 + COMBOBOX IDC_NCK5_REALM,60,25,233,51,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Specify &additional realms ...",IDC_NCK5_ADD_REALMS,181,43,112,16,BS_NOTIFY | WS_DISABLED +END + +IDD_CFG_CACHES DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "File-based Credential Caches",IDC_CFG_FCGRP,7,26,241,149 + CONTROL "",IDC_CFG_FCLIST,"SysListView32",LVS_REPORT | LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,13,37,229,97 + EDITTEXT IDC_CFG_FCNAME,13,139,173,14,ES_AUTOHSCROLL + PUSHBUTTON "&Browse ...",IDC_CFG_BROWSE,192,139,50,14 + PUSHBUTTON "Add",IDC_CFG_ADD,13,156,50,14 + PUSHBUTTON "Remove Selected",IDC_CFG_REMOVE,88,156,80,14 + CONTROL "Include all API: credentials caches",IDC_CFG_INCAPI, + "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,123,7,125,10 + CONTROL "Include Windows LSA cache (MSLSA:)",IDC_CFG_INCMSLSA, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,7,136,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_NC_KRB5, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 293 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_PP_KRB5C, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 149 + END + + IDD_PP_KRB5, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 149 + END + + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 13 + VERTGUIDE, 76 + VERTGUIDE, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_REALMS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 93 + VERTGUIDE, 99 + VERTGUIDE, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + HORZGUIDE, 19 + HORZGUIDE, 167 + END + + IDD_CFG_IDS_TAB, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + VERTGUIDE, 13 + VERTGUIDE, 94 + VERTGUIDE, 222 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_CFG_ID_TAB, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + VERTGUIDE, 91 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_NC_KRB5_PASSWORD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 293 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_CFG_CACHES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 7 + VERTGUIDE, 13 + VERTGUIDE, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_PLUGIN ICON "..\\..\\images\\krb5plugin.ico" +IDI_DELETED ICON "..\\..\\images\\deleted.ico" +IDI_NEW ICON "..\\..\\images\\new.ico" +IDI_NORMAL ICON "..\\..\\images\\normal.ico" +IDI_MODIFIED ICON "..\\..\\images\\modified.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_UNK_ADDR_FMT "Unknown address type %d" + IDS_KRB5_CREDTEXT_0 "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: Tickets for realm %s</p>" + IDS_KRB5_CCNAME_SHORT_DESC "Kerberos v5 CCache" + IDS_KEY_ENCTYPE_SHORT_DESC "Session EncType" + IDS_TKT_ENCTYPE_SHORT_DESC "Service EncType" + IDS_KEY_ENCTYPE_LONG_DESC "Session Key Encryption Type" + IDS_TKT_ENCTYPE_LONG_DESC "Service Encryption Type" + IDS_ADDR_LIST_SHORT_DESC "Addresses" + IDS_ADDR_LIST_LONG_DESC "Address List" + IDS_ETYPE_NULL "NULL" + IDS_ETYPE_DES_CBC_CRC "DES-CBC-CRC" +END + +STRINGTABLE +BEGIN + IDS_ETYPE_DES_CBC_MD4 "DES-CBC-MD4" + IDS_ETYPE_DES_CBC_MD5 "DES-CBC-MD5" + IDS_ETYPE_DES_CBC_RAW "DES-CBC-RAW" + IDS_ETYPE_DES3_CBC_SHA "DES3-CBC-SHA" + IDS_ETYPE_DES3_CBC_RAW "DES3-CBC-RAW" + IDS_ETYPE_DES_HMAC_SHA1 "DES-HMAC-SHA1" + IDS_ETYPE_DES3_CBC_SHA1 "DES3-CBC-SHA1" + IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 "AES128_CTS-HMAC-SHA1_96" + IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 "AES256_CTS-HMAC-SHA1_96" + IDS_ETYPE_ARCFOUR_HMAC "RC4-HMAC-NT" + IDS_ETYPE_ARCFOUR_HMAC_EXP "RC4-HMAC-NT-EXP" + IDS_ETYPE_UNKNOWN "(Unknown)" + IDS_ETYPE_LOCAL_DES3_HMAC_SHA1 "LOCAL-DES3-HMAC-SHA1" + IDS_ETYPE_LOCAL_RC4_MD4 "LOCAL-RC4-MD4" + IDS_KRB5_SHORT_DESC "Kerberos v5 credentials" + IDS_KRB5_LONG_DESC "Kerberos v5 credentials" +END + +STRINGTABLE +BEGIN + IDS_KRB4_SHORT_DESC "Kerberos v4" + IDS_KRB4_LONG_DESC "Kerberos v4 credentials" + IDS_KRB5_FLAGS_SHORT_DESC "Kerberos v5 Flags" + IDS_RENEW_TILL_SHORT_DESC "Renew Till" + IDS_RENEW_TILL_LONG_DESC "Renewable Till" + IDS_RENEW_FOR_SHORT_DESC "Renew for" + IDS_RENEW_FOR_LONG_DESC "Renewable for" + IDS_KRB5_CCNAME_LONG_DESC "Kerberos v5 Primary Credentials Cache" + IDS_NC_USERNAME "Username" + IDS_NC_REALM "Realm" + IDS_KRB5_WARNING "Kerberos v5 Warning" + IDS_K5ERR_NAME_EXPIRED "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: The selected principal name has expired.</p><p><tab> Please contact your system administrator.</p>" + IDS_K5ERR_KEY_EXPIRED "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: The password for the selected identity has expired.</p><p><tab> Click <a id=""Krb5Cred:!Passwd"">here</a> to change the password</p>" + IDS_KRB5_WARN_FMT "Kerberos v5: %s\n\n%s" + IDS_K5ERR_FMT "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tag>: %s</p>" + IDS_K5CFG_SHORT_DESC "Kerberos v5" +END + +STRINGTABLE +BEGIN + IDS_K5CFG_LONG_DESC "Kerberos v5 Configuration" + IDS_K5RLM_SHORT_DESC "Realms" + IDS_K5RLM_LONG_DESC "Kerberos Realm Configuration" + IDS_K5CFG_IDS_SHORT_DESC "Kerberos v5" + IDS_K5CFG_IDS_LONG_DESC "Kerberos v5 options for all identities" + IDS_K5CFG_ID_SHORT_DESC "Kerberos v5" + IDS_K5CFG_ID_LONG_DESC "Kerberos v5 options for this identity" + IDS_PLUGIN_DESC "Kerberos v5 Credentials Provider" + IDS_NC_PWD_BANNER "Changing Kerberos v5 Password" + IDS_NC_PWD_PWD "Current Password" + IDS_NC_PWD_NPWD "New Password" + IDS_NC_PWD_NPWD_AGAIN "New Password again" + IDS_KRB5_CREDTEXT_P0 "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: Changing password for %s</p>" + IDS_K5CFG_IMPORT_OPTIONS "Never,Always,Only when the principal matches" + IDS_IDENTPRO_DESC "Kerberos v5 Identity Provider" + IDS_K5CCC_SHORT_DESC "Credential Caches" +END + +STRINGTABLE +BEGIN + IDS_K5CCC_LONG_DESC "Kerberos v5 Credential Caches" + IDS_CFG_FCTITLE "File based Credential Caches" + IDS_CFG_FCN_WARNING "Warning:" + IDS_CFG_FCN_W_NOTFOUND "The credentials cache you specified does not exist." + IDS_CFG_FCN_W_RELATIVE "The path you specified not an absolute path." + IDS_CFG_FCOPENTITLE "Select a credential cache to add" + IDS_UNAVAILABLE "(Not available)" + IDS_FLG_FORWARDABLE "Forwardable" + IDS_FLG_FORWARDED "Forwarded" + IDS_FLG_PROXIABLE "Proxiable" + IDS_FLG_PROXY "Proxy" + IDS_FLG_MAY_POSTDATE "May postdate" + IDS_FLG_POSTDATED "Postdated" + IDS_FLG_INVALID "Invalid" + IDS_FLG_RENEWABLE "Renewable" + IDS_FLG_INITIAL "Initial" +END + +STRINGTABLE +BEGIN + IDS_FLG_PRE_AUTH "Pre-authenticated" + IDS_FLG_HW_AUTH "Hardware authentication" + IDS_FLG_TRANSIT_POL "Transit policy checked" + IDS_FLG_OK_DELEGATE "Approved for delegation" + IDS_FLG_ANONYMOUS "Anonymous" + IDS_K5ERR_CANTWRITEPROFILE + "The Kerberos v5 profile file could not be written" + IDS_K5ERR_PROFNOWRITE "The file %s could not be opened as a profile file for writing." + IDS_K5ERR_PROFUSETEMP "The file %s could not be opened for writing. The current changes will be saved to %s temporarily." + IDS_K5ERR_PROFSUGGEST "This may be due to not having privileges to modify the configuration file. Please contact your system administrator to resolve the issue." + IDS_CFG_RE_REALMS "Kerberos Realms" + IDS_CFG_RE_KDCS "Kerberos Servers" + IDS_CFG_RE_DMAPS "Domain mappings" + IDS_CFG_RE_KDCS_R "Kerberos Servers for %s" + IDS_CFG_RE_DMAPS_R "Domains that map to %s" + IDS_CFG_RE_HEAD_SVR "Server" + IDS_CFG_RE_HEAD_ADMIN "Admin" +END + +STRINGTABLE +BEGIN + IDS_CFG_RE_HEAD_MASTER "Master" + IDS_CFG_RE_HEAD_DOMAIN "Domain" + IDS_CFG_RE_NEWREALM "<New realm...>" + IDS_YES "Yes" + IDS_NO "No" + IDS_CFG_RE_NEWSERVER "<New server...>" + IDS_CFG_RE_NEWDMAP "<New domain mapping...>" + IDS_KRB5_NC_NAME "Kerberos v5" + IDS_NCERR_IDENT_TOO_LONG "The identity name is too long." + IDS_NCERR_IDENT_INVALID "The identity name is invalid." + IDS_NCERR_IDENT_UNKNOWN "An unknown error occurred while validating the identity name." + IDS_CFG_RE_ARNUT "Can't add new realm %s" + IDS_CFG_RE_ARNUM "The new realm name %s can't be added because there is already a realm with the same name listed. Please type another name." + IDS_CFG_RE_ASNUT "Can't add new server %s for realm %s" + IDS_CFG_RE_ASNUM "There already is a server named %s for realm %s. The new server can not be added." + IDS_CFG_RE_DMNUT "Can't add new domain map %s for realm %s" +END + +STRINGTABLE +BEGIN + IDS_CFG_RE_DMNUM "There already is a domain named %s mapping to realm %s. The new domain map could not be added." + IDS_CFG_RE_MNR "&Add new realm" + IDS_CFG_RE_MDR "&Remove realm" + IDS_CFG_RE_MNK "&Add new server" + IDS_CFG_RE_MDK "&Remove server" + IDS_CFG_RE_MAK "Toggle a&dmin server" + IDS_CFG_RE_MMK "Toggle &master KDC" + IDS_CFG_RE_MND "&Add new domain mapping" + IDS_CFG_RE_MDD "&Remove domain mapping" + IDS_KVNO_SHORT_DESC "Kvno" + IDS_KVNO_LONG_DESC "Key version number" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + + diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc b/krb5-1-6/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc new file mode 100644 index 000000000..1e9869972 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc @@ -0,0 +1,199 @@ +; // ** krb5_msgs.mc + +; /* Since .mc files can contain strings from any language, we define +; all our messages in one file in the /lang/ directory instead of +; language specific subdirectories. */ + +; /* The type is set to (wchar_t *) because that's what we will be +; feeding kherr_report() function. */ + +; // MessageIdTypedef=LPWSTR + +; /* Severity values as defined in the message definition file are +; currently ignored. */ + +SeverityNames=( + Success=0x0 +) + +LanguageNames=( + English=0x409:MSG_ENU +) + +OutputBase=16 + +; /* Actual messages start here */ + +MessageId=1 +Severity=Success +SymbolicName=MSG_INITIAL +Language=English +Initial placeholder message +. + +MessageId= +SymbolicName=MSG_CTX_INITAL_CREDS +Language=English +Obtaining initial Krb5 credentials +. + +MessageId= +SymbolicName=MSG_CTX_RENEW_CREDS +Language=English +Renewing Krb5 credentials +. + +MessageId= +SymbolicName=MSG_ERR_UNKNOWN +Language=English +An unknown error has occurred. +. + +MessageId= +SymbolicName=MSG_ERR_PR_UNKNOWN +Language=English +You have entered an unknown username/instance/realm combination. +. + +MessageId= +SymbolicName=MSG_ERR_TKFIL +Language=English +The tickets could not be accessed from the memory location where they were stored. +. + +MessageId= +SymbolicName=MSG_ERR_S_TKFIL +Language=English +This may be due to a problem with the memory where your tickets are stored. Restarting your computer might be worth a try. +. + +MessageId= +SymbolicName=MSG_ERR_CLOCKSKEW +Language=English +Your computer's clock is out of sync with the Kerberos server. +. + +MessageId= +SymbolicName=MSG_ERR_S_CLOCKSKEW +Language=English +Synchronize your clock withe the Kerberos server. +. + +MessageId= +SymbolicName=MSG_ERR_KDC_CONTACT +Language=English +Cannot contact the Kerberos server for the requested realm. +. + +MessageId= +SymbolicName=MSG_ERR_INSECURE_PW +Language=English +You have entered an insecure or weak password. +. + +MessageId= +SymbolicName=MSG_ERR_NO_IDENTITY +Language=English +There were no identities for which to renew credentials. +. + +MessageId= +SymbolicName=MSG_CTX_PASSWD +Language=English +Changing Kerberos 5 Password +. + +MessageId= +SymbolicName=MSG_PWD_UNKNOWN +Language=English +Unknown error +. + +MessageId= +SymbolicName=MSG_PWD_NOT_SAME +Language=English +The new passwords are not the same. +. + +MessageId= +SymbolicName=MSG_PWD_S_NOT_SAME +Language=English +The new password is asked for twice to protect against a mistake when setting the new password. Both instances of the new password must be the same. Please correct this and try again. +. + +MessageId= +SymbolicName=MSG_PWD_SAME +Language=English +The new and the old passwords are the same. +. + +MessageId= +SymbolicName=MSG_PWD_S_SAME +Language=English +Please type a new password to continue. +. + +MessageId= +SymbolicName=MSG_PWD_NO_IDENTITY +Language=English +There are no identities selected. +. + +MessageId= +SymbolicName=MSG_PWD_S_NO_IDENTITY +Language=English +Please select an identity to change the password. +. + +MessageId= +SymbolicName=MSG_ERR_S_INTEGRITY +Language=English +This is commonly caused by an incorrect password. Please verify that the password is correct and note that passwords are case sensitive. +. + +MessageId= +SymbolicName=MSG_ERR_CTX_DESTROY_CREDS +Language=English +Destroying Krb5 tickets +. + +MessageId= +SymbolicName=MSG_ERR_NETDOWN +Language=English +A network connection is unavailable +. + +MessageId= +SymbolicName=MSG_ERR_S_NETRETRY +Language=English +Please check your network connection or contact your network administrator for assistance. +. + +MessageId= +SymbolicName=MSG_ERR_TEMPDOWN +Language=English +A temporary network error caused the operation to fail +. + +MessageId= +SymbolicName=MSG_ERR_S_TEMPDOWN +Language=English +Please try again in a few minutes +. + +MessageId= +SymbolicName=MSG_ERR_NOHOST +Language=English +A server could not be reached +. + +MessageId= +SymbolicName=MSG_ERR_S_NOHOST +Language=English +This can be caused by the server being unavailable, network errors, or improper configuration. Please try again or contact your administrator for assistance. +. + +MessageId= +SymbolicName=MSG_ +Language=English +. diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/langres.h b/krb5-1-6/src/windows/identity/plugins/krb5/langres.h new file mode 100644 index 000000000..117754b3e --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/langres.h @@ -0,0 +1,216 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb5\lang\en_us\langres.rc +// +#define IDS_UNK_ADDR_FMT 101 +#define IDD_NC_KRB5 102 +#define IDS_KRB5_CREDTEXT_0 102 +#define IDS_KRB5_CCNAME_SHORT_DESC 103 +#define IDS_KEY_ENCTYPE_SHORT_DESC 104 +#define IDD_CONFIG 104 +#define IDS_TKT_ENCTYPE_SHORT_DESC 105 +#define IDD_CFG_REALMS 105 +#define IDS_KEY_ENCTYPE_LONG_DESC 106 +#define IDD_CFG_IDS_TAB 106 +#define IDS_TKT_ENCTYPE_LONG_DESC 107 +#define IDD_PP_KRB5C 107 +#define IDS_ADDR_LIST_SHORT_DESC 108 +#define IDD_PP_KRB5 108 +#define IDS_ADDR_LIST_LONG_DESC 109 +#define IDD_CFG_ID_TAB 109 +#define IDS_ETYPE_NULL 110 +#define IDD_NC_KRB5_PASSWORD 110 +#define IDS_ETYPE_DES_CBC_CRC 111 +#define IDD_CFG_CACHES 111 +#define IDS_ETYPE_DES_CBC_MD4 112 +#define IDI_PLUGIN 112 +#define IDS_ETYPE_DES_CBC_MD5 113 +#define IDI_DELETED 113 +#define IDS_ETYPE_DES_CBC_RAW 114 +#define IDI_NEW 114 +#define IDS_ETYPE_DES3_CBC_SHA 115 +#define IDI_NORMAL 115 +#define IDS_ETYPE_DES3_CBC_RAW 116 +#define IDI_MODIFIED 116 +#define IDS_ETYPE_DES_HMAC_SHA1 117 +#define IDS_ETYPE_DES3_CBC_SHA1 118 +#define IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 119 +#define IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 120 +#define IDS_ETYPE_ARCFOUR_HMAC 121 +#define IDS_ETYPE_ARCFOUR_HMAC_EXP 122 +#define IDS_ETYPE_UNKNOWN 123 +#define IDS_ETYPE_LOCAL_DES3_HMAC_SHA1 124 +#define IDS_ETYPE_LOCAL_RC4_MD4 125 +#define IDS_KRB5_SHORT_DESC 126 +#define IDS_KRB5_LONG_DESC 127 +#define IDS_KRB4_SHORT_DESC 128 +#define IDS_KRB4_LONG_DESC 129 +#define IDS_KRB5_FLAGS_SHORT_DESC 130 +#define IDS_RENEW_TILL_SHORT_DESC 131 +#define IDS_RENEW_TILL_LONG_DESC 132 +#define IDS_RENEW_FOR_SHORT_DESC 133 +#define IDS_RENEW_FOR_LONG_DESC 134 +#define IDS_KRB5_CCNAME_LONG_DESC 135 +#define IDS_NC_USERNAME 136 +#define IDS_NC_REALM 137 +#define IDS_KRB5_WARNING 138 +#define IDS_K5ERR_NAME_EXPIRED 139 +#define IDS_K5ERR_KEY_EXPIRED 140 +#define IDS_KRB5_WARN_FMT 141 +#define IDS_K5ERR_FMT 142 +#define IDS_K5CFG_SHORT_DESC 143 +#define IDS_K5CFG_LONG_DESC 144 +#define IDS_K5RLM_SHORT_DESC 145 +#define IDS_K5RLM_LONG_DESC 146 +#define IDS_K5CFG_IDS_SHORT_DESC 147 +#define IDS_K5CFG_IDS_LONG_DESC 148 +#define IDS_K5CFG_ID_SHORT_DESC 149 +#define IDS_K5CFG_ID_LONG_DESC 150 +#define IDS_PLUGIN_DESC 151 +#define IDS_NC_PWD_BANNER 152 +#define IDS_NC_PWD_PWD 153 +#define IDS_NC_PWD_NPWD 154 +#define IDS_NC_PWD_NPWD_AGAIN 155 +#define IDS_KRB5_CREDTEXT_P0 156 +#define IDS_K5CFG_IMPORT_OPTIONS 157 +#define IDS_IDENTPRO_DESC 158 +#define IDS_K5CCC_SHORT_DESC 159 +#define IDS_K5CCC_LONG_DESC 160 +#define IDS_CFG_FCTITLE 161 +#define IDS_CFG_FCN_WARNING 162 +#define IDS_CFG_FCN_W_NOTFOUND 163 +#define IDS_CFG_FCN_W_RELATIVE 164 +#define IDS_CFG_FCOPENTITLE 165 +#define IDS_UNAVAILABLE 166 +#define IDS_FLG_FORWARDABLE 167 +#define IDS_FLG_FORWARDED 168 +#define IDS_FLG_PROXIABLE 169 +#define IDS_FLG_PROXY 170 +#define IDS_FLG_MAY_POSTDATE 171 +#define IDS_FLG_POSTDATED 172 +#define IDS_FLG_INVALID 173 +#define IDS_FLG_RENEWABLE 174 +#define IDS_FLG_INITIAL 175 +#define IDS_FLG_PRE_AUTH 176 +#define IDS_FLG_HW_AUTH 177 +#define IDS_FLG_TRANSIT_POL 178 +#define IDS_FLG_OK_DELEGATE 179 +#define IDS_FLG_ANONYMOUS 180 +#define IDS_K5ERR_CANTWRITEPROFILE 181 +#define IDS_K5ERR_PROFNOWRITE 182 +#define IDS_K5ERR_PROFUSETEMP 183 +#define IDS_K5ERR_PROFSUGGEST 184 +#define IDS_CFG_RE_REALMS 185 +#define IDS_CFG_RE_KDCS 186 +#define IDS_CFG_RE_DMAPS 187 +#define IDS_CFG_RE_KDCS_R 188 +#define IDS_CFG_RE_DMAPS_R 189 +#define IDS_CFG_RE_HEAD_SVR 190 +#define IDS_CFG_RE_HEAD_ADMIN 191 +#define IDS_CFG_RE_HEAD_MASTER 192 +#define IDS_CFG_RE_HEAD_DOMAIN 193 +#define IDS_CFG_RE_NEWREALM 194 +#define IDS_YES 195 +#define IDS_NO 196 +#define IDS_CFG_RE_NEWSERVER 197 +#define IDS_CFG_RE_NEWDMAP 198 +#define IDS_KRB5_NC_NAME 199 +#define IDS_NCERR_IDENT_TOO_LONG 200 +#define IDS_NCERR_IDENT_INVALID 201 +#define IDS_NCERR_IDENT_UNKNOWN 202 +#define IDS_CFG_RE_ARNUT 203 +#define IDS_CFG_RE_ARNUM 204 +#define IDS_CFG_RE_ASNUT 205 +#define IDS_CFG_RE_ASNUM 206 +#define IDS_CFG_RE_DMNUT 207 +#define IDS_CFG_RE_DMNUM 208 +#define IDS_CFG_RE_MNR 209 +#define IDS_CFG_RE_MDR 210 +#define IDS_CFG_RE_MNK 211 +#define IDS_CFG_RE_MDK 212 +#define IDS_CFG_RE_MAK 213 +#define IDS_CFG_RE_MMK 214 +#define IDS_CFG_RE_MND 215 +#define IDS_CFG_RE_MDD 216 +#define IDS_KVNO_SHORT_DESC 217 +#define IDS_KVNO_LONG_DESC 218 +#define IDC_NCK5_RENEWABLE 1002 +#define IDC_NCK5_FORWARDABLE 1004 +#define IDC_NCK5_REALM 1005 +#define IDC_NCK5_ADD_REALMS 1006 +#define IDC_NCK5_LIFETIME_EDIT 1008 +#define IDC_NCK5_RENEW_EDIT 1009 +#define IDC_PPK5_CRENEW 1014 +#define IDC_PPK5_CFORWARD 1015 +#define IDC_PPK5_CPROXY 1016 +#define IDC_PPK5_NAME 1017 +#define IDC_PPK5_ISSUE 1018 +#define IDC_PPK5_VALID 1019 +#define IDC_PPK5_RENEW 1020 +#define IDC_CHECK2 1022 +#define IDC_CHECK4 1024 +#define IDC_PPK5_LIFETIME 1024 +#define IDC_CHECK5 1025 +#define IDC_CFG_LBL_REALM 1025 +#define IDC_CFG_DEFREALM 1026 +#define IDC_CFG_LBL_CFGFILE 1029 +#define IDC_CFG_CFGFILE 1030 +#define IDC_CFG_WINGRP 1031 +#define IDC_LBL_IMPORT 1032 +#define IDC_CFG_IMPORT 1033 +#define IDC_CFG_LBL_HOSTNAME 1034 +#define IDC_CFG_HOSTNAME 1035 +#define IDC_CFG_LBL_DOMAIN 1036 +#define IDC_CFG_DOMAIN 1037 +#define IDC_CFG_CREATECONFIG 1038 +#define IDC_CFG_BROWSE 1039 +#define IDC_CFG_CFGFILEGRP 1040 +#define IDC_CFG_CFGREALMS 1041 +#define IDC_CFG_BROWSE2 1042 +#define IDC_CFG_REALMS 1044 +#define IDC_CFG_DOMAINGRP 1045 +#define IDC_CFG_SERVERSGRP 1046 +#define IDC_LIST3 1047 +#define IDC_CFG_KDC 1047 +#define IDC_LIST4 1048 +#define IDC_CFG_DMAP 1048 +#define IDC_CFG_LBL_DEFLIFE 1049 +#define IDC_CFG_DEFLIFE 1050 +#define IDC_CFG_LBL_DEFRLIFE 1051 +#define IDC_CFG_DEFRLIFE 1052 +#define IDC_CFG_LIFEGRP 1053 +#define IDC_CFG_LRNG_MIN 1054 +#define IDC_CFG_LRNG_MAX 1055 +#define IDC_CFG_RLRNG_MIN 1056 +#define IDC_CFG_RLRNG_MAX 1057 +#define IDC_CFG_CCACHE 1058 +#define IDC_CFG_FCGRP 1059 +#define IDC_CFG_FCLIST 1060 +#define IDC_CFG_FCNAME 1062 +#define IDC_CFG_ADD 1064 +#define IDC_CFG_REMOVE 1065 +#define IDC_CFG_INCAPI 1066 +#define IDC_CFG_INCMSLSA 1067 +#define IDC_PPK5_FLAGS 1072 +#define IDC_CFG_INCREALMS 1073 +#define IDC_NCK5_ADDRESS 1074 +#define IDC_IPADDRESS1 1075 +#define IDC_NCK5_PUBLICIP 1075 +#define IDC_CFG_PUBLICIP 1075 +#define IDC_CFG_RENEW 1076 +#define IDC_CHECK3 1077 +#define IDC_CFG_ADDRESSLESS 1077 +#define IDC_CFG_FORWARD 1078 +#define IDC_CHECK1 1079 +#define ID_FOO_BAR 40001 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 219 +#define _APS_NEXT_COMMAND_VALUE 40002 +#define _APS_NEXT_CONTROL_VALUE 1080 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/identity/plugins/krb5/version.rc b/krb5-1-6/src/windows/identity/plugins/krb5/version.rc new file mode 100644 index 000000000..c894dff63 --- /dev/null +++ b/krb5-1-6/src/windows/identity/plugins/krb5/version.rc @@ -0,0 +1,88 @@ +/* Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* $Id$ */ + +#include<netidmgr_intver.h> + +#ifndef LANGVER + +#define STR_FILEDESC "Kerberos v5 Plugin for Network Identity Manager" +#define STR_INTNAME "krb5cred" +#define STR_ORIGNAME "krb5cred.dll" + +#else + +#ifdef LANG_en_us + +#define STR_FILEDESC "English(US) language resources for the Keberos 5 plugin" +#define STR_INTNAME "krb5cred_en_us" +#define STR_ORIGNAME "krb5cred_en_us.dll" + +#else + +#error Unknown langugae + +#endif + +#endif + +1 VERSIONINFO + FILEVERSION KH_VERSION_LIST + PRODUCTVERSION KH_VERSION_LIST + FILEFLAGSMASK KH_VER_FILEFLAGMASK + FILEFLAGS KH_VER_FILEFLAGS + FILEOS KH_VER_FILEOS + FILETYPE KH_VER_FILETYPEDLL + FILESUBTYPE 0 + { + BLOCK "StringFileInfo" + { + BLOCK "040904b0" + { + VALUE "CompanyName", KH_VERSTR_COMPANY_1033 + VALUE "FileDescription", STR_FILEDESC + VALUE "FileVersion", KH_VERSTR_VERSION_1033 + VALUE "InternalName", STR_INTNAME + VALUE "LegalCopyright", KH_VERSTR_COPYRIGHT_1033 + VALUE "OriginalFilename", STR_ORIGNAME + VALUE "ProductName", "Network Identity Manager" + VALUE "ProductVersion", KH_VERSTR_PRODUCT_1033 +#ifdef KH_VERSTR_COMMENT_1033 + VALUE "Comment", KH_VERSTR_COMMENT_1033 +#endif +#ifndef LANGVER + VALUE NIMV_MODULE, "MITKrb5" + VALUE NIMV_PLUGINS, "Krb5Cred,Krb5Ident" + VALUE NIMV_APIVER, KH_VERSION_STRINGAPI + VALUE NIMV_SUPPORT, "http://web.mit.edu/kerberos" +#endif + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 0x4b0 + } + } diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/Makefile b/krb5-1-6/src/windows/identity/sample/templates/credprov/Makefile new file mode 100644 index 000000000..898c614ca --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/Makefile @@ -0,0 +1,278 @@ +# +# Copyright (c) 2006 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Environment variables +# --------------------- +# +# Before running the makefile, set the environment variable KFWSDKDIR +# to the directory containing the Kerberos for Windows SDK version 3.1 +# or later. The path should not end in a backslash. + +# Configuration settings +# ---------------------- + +# Declare a few things about our plug-in. + +# TODO: Change the plug-in name +PLUGINNAME=MyPlugin + +# TODO: Change the module name +MODULENAME=MyModule + +# TODO: Change the credtype name +CREDTYPENAME=MyCred + +# TODO: Change this as appropriate +DLLBASENAME=myplugin + +# Version info + +# TODO: Change the version numbers +VERMAJOR=0 +VERMINOR=1 +VERAUX =0 +VERPATCH=0 + +# Leave these as-is +VERLIST=$(VERMAJOR).$(VERMINOR).$(VERAUX).$(VERPATCH) +VERLISTC=$(VERMAJOR),$(VERMINOR),$(VERAUX),$(VERPATCH) + +# Various checks + +!ifndef MSSDK +! error Platform SDK environment variables not set. +!endif + +!ifndef KFWSDKDIR +! error KFWSDKDIR environment variable not set. +!endif + +# Directories + +BUILDROOT=. + +!ifdef NODEBUG +BUILDTYPE=release +!else +BUILDTYPE=debug +!endif + +!ifndef CPU +!error Environment variable 'CPU' is not defined. +!endif + +DEST=$(BUILDROOT)\dest\$(CPU)_$(BUILDTYPE) +OBJ=$(BUILDROOT)\obj\$(CPU)_$(BUILDTYPE) + +!ifndef NIDMRAWDIRS +KFWINCDIR=$(KFWSDKDIR)\inc +NIDMINCDIR=$(KFWINCDIR)\netidmgr +NIDMLIBDIR=$(KFWSDKDIR)\lib\$(CPU) +!else +NIDMINCDIR=$(KFWSDKDIR)\inc +NIDMLIBDIR=$(KFWSDKDIR) +!endif + +# Win32.mak + +!include <Win32.Mak> + +# Program macros + +CD=cd +RM=del /q +MKDIR=mkdir +RMDIR=rmdir +ECHO=echo +CP=copy /y +LINK=link +MC=mc + +# Lots more macros + +incflags = -I"$(NIDMINCDIR)" -I"$(OBJ)" -I. +rincflags = /i "$(NIDMINCDIR)" /i "$(OBJ)" /i . + +ldebug = $(ldebug) /DEBUG +cdebug = $(cdebug) -Os -Zi + +cdefines = $(cdefines) -DUNICODE -D_UNICODE + +C2OBJ=$(CC) $(cdebug) $(cflags) $(incflags) $(cdefines) /Fo"$@" /c $** + +DLLGUILINK=$(LINK) /NOLOGO $(ldebug) $(dlllflags) $(guilibsmt) /OUT:"$@" /IMPLIB:$(DEST)\$(@B).lib $** + +DLLRESLINK=$(LINK) /NOLOGO /DLL /NOENTRY /MACHINE:$(PROCESSOR_ARCHITECTURE) /OUT:"$@" $** + +RC2RES=$(RC) $(RFLAGS) $(rincflags) /fo "$@" $** + +MC2RC=$(MC) $(MCFLAGS) -h "$(OBJ)\" -m 1024 -r "$(OBJ)\" -x "$(OBJ)\" $** + +{}.c{$(OBJ)}.obj: + $(C2OBJ) + +{$(OBJ)}.c{$(OBJ)}.obj: + $(C2OBJ) + +{}.rc{$(OBJ)}.res: + $(RC2RES) + +mkdirs:: +!if !exist($(DEST)) + $(MKDIR) "$(DEST)" +!endif +!if !exist($(OBJ)) + $(MKDIR) "$(OBJ)" +!endif + +clean:: + $(RM) "$(OBJ)\*.*" + $(RM) "$(DEST)\*.*" + +.SUFFIXES: .h + +# +# Manifest handling +# +# Starting with Visual Studio 8, the C compiler and the linker +# generate manifests so that the applications will link with the +# correct side-by-side DLLs at run-time. These are required for +# correct operation under Windows XP. We also have custom manifests +# which need to be merged with the manifests that VS creates. +# +# The syntax for invoking the _VC_MANIFEST_EMBED_foo macro is: +# $(_VC_MANIFEST_EMBED_???) <any additional manifests that need to be merged in> +# + +!ifndef MT +MT=mt.exe -nologo +!endif + +_VC_MANIFEST_EMBED_EXE= \ +if exist "$@.manifest" $(MT) -outputresource:"$@";1 -manifest "$@.manifest" + +_VC_MANIFEST_EMBED_DLL=$(_VC_MANIFEST_EMBED_EXE) + +# Note that if you are merging manifests, then the VS generated +# manifest should be cleaned up after calling _VC_MANIFEST_EMBED_???. +# This ensures that even if the DLL or EXE is executed in-place, the +# embedded manifest will be used. Otherwise the $@.manifest file will +# be used. +_VC_MANIFEST_CLEAN= \ +if exist "$@.manifest" $(RM) "$@.manifest" + +# End of manifest handling + + +# Now for the actual build stuff + +DLL=$(DEST)\$(DLLBASENAME).dll + +LIBFILES= \ + "$(NIDMLIBDIR)\nidmgr32.lib" + +OBJFILES= \ + $(OBJ)\credacq.obj \ + $(OBJ)\credtype.obj \ + $(OBJ)\main.obj \ + $(OBJ)\plugin.obj \ + $(OBJ)\proppage.obj \ + $(OBJ)\config_main.obj \ + $(OBJ)\config_id.obj \ + $(OBJ)\config_ids.obj + +DLLRESFILE=$(OBJ)\version.res + +CONFIGHEADER=$(OBJ)\credacq_config.h + +all: mkdirs $(CONFIGHEADER) $(DLL) lang + +$(CONFIGHEADER): Makefile + $(CP) << "$@" +/* This is a generated file. Do not modify directly. */ + +#pragma once + +#define MYPLUGIN_DLLBASE "$(DLLBASENAME)" + +#define MYPLUGIN_NAME "$(PLUGINNAME)" + +#define MYMODULE_NAME "$(MODULENAME)" + +#define MYCREDTYPE_NAME "$(CREDTYPENAME)" + +#define VERSION_MAJOR $(VERMAJOR) +#define VERSION_MINOR $(VERMINOR) +#define VERSION_AUX $(VERAUX) +#define VERSION_PATCH $(VERPATCH) + +#define VERSION_LIST $(VERLIST) +#define VERSION_LISTC $(VERLISTC) +#define VERSION_STRING "$(VERLIST)" + +<< + +clean:: + $(RM) $(CONFIGHEADER) + +$(DLL): $(OBJFILES) $(DLLRESFILE) + $(DLLGUILINK) $(LIBFILES) + $(_VC_MANIFEST_EMBED_DLL) + $(_VC_MANIFEST_CLEAN) + +clean:: + $(RM) $(DLL) + +# Language specific resources + +# (repeat the following block as needed, redefining LANG for each +# supported language) + +# English-US +LANG=en_us + +LANGDLL=$(DEST)\$(DLLBASENAME)_$(LANG).dll + +lang:: $(LANGDLL) + +$(LANGDLL): $(OBJ)\langres_$(LANG).res $(OBJ)\version_$(LANG).res + $(DLLRESLINK) + $(_VC_MANIFEST_EMBED_DLL) + $(_VC_MANIFEST_CLEAN) + +clean:: + $(RM) $(LANGDLL) + +$(OBJ)\version_$(LANG).res: version.rc + $(RC) $(RFLAGS) $(rincflags) /d LANGRES /d LANG_$(LANG) /fo $@ $** + +clean:: + $(RM) $(OBJ)\version_$(LANG).res + +$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc + $(RC2RES) + +clean:: + $(RM) $(OBJ)\langres_$(LANG).res + +# /English-US diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/README b/krb5-1-6/src/windows/identity/sample/templates/credprov/README new file mode 100644 index 000000000..2ecf88188 --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/README @@ -0,0 +1,250 @@ + + Network Identity Manager + + Credentials Provider Plug-in Template + +------------------------------------------------------------------ + + CONTENTS + + 1. INTRODUCTION + 2. COPYRIGHT AND LICENSE + 3. ROADMAP OF THE TEMPLATE + 4. BUILD REQUIREMENTS + 5. BUILDING + 6. RUNNING THE PLUG-IN + 7. KNOWN ISSUES + 8. SUPPORT / BUG REPORTS + +------------------------------------------------------------------ + +1. INTRODUCTION + + This directory and subdirectories contain a plug-in template for + creating a credentials provider plug-in for Network Identity + Manager. A credentials manager plug-in provides knowledge of a + specifc credentials type to the NetIDMgr application and manages + those credentials on behalf of NetIDMgr. + + This version of the template adheres to the following version + constraints: + + Network Identity Manager API version : 5 + + (This API version corresponds to the MIT Kerberos for Windows + version 3.1). + + The source files in this template can be used to build the plug-in + DLL and the US English resource DLL for the plug-in. In its + current form, the plug-in doesn't do any credentials management. + However, it implements a number of stub functions that can be + filled in to perform the necessary credentials management + operations. + +------------------------------------------------------------------ + +2. COPYRIGHT AND LICENSE + + Copyright (c) 2006 Secure Endpoints Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +------------------------------------------------------------------ + +3. ROADMAP OF THE TEMPLATE + + The template consists of the following files and directories: + + .\README + + This file. + + .\Makefile + + The primary (and only) Makefile used by 'nmake' to build the + plug-in. In addition to providing build directives, it also + contains a set of macros which defines the names and version + information that is used throughout the plug-in code. + + Look for the 'Configuration Settings' section of the Makefile + for the macros. If you are basing a plug-in on this template, + you will want to change these macros. These macros will be + used to generate 'credacq_config.h', a header file included by + 'credprov.h' so that the values of the macros can be used in C + code. + + .\credprov.h + + The main header file for all the C source files in the + plug-in. + + .\main.c + + Provides the entry points for the module. + + .\plugin.c + + Provides the message processing functions and support routines + for implementing the plug-in. Note that some of the message + processing routines have been moved to other sources files + based on their use. + + .\credtype.c + + Functions for handling our credentials type. + + .\credacq.c + + Handlers for the credentials acquisition messages including + handling the user interface for the new credentials dialogs. + + .\proppage.c + + Dialog procedures and support code for displaying property + sheets for credentials that belong to our credentials type. + + .\config_main.c + + Dialog procedures and support code for providing the general + configuration panel for this plug-in. + + .\config_id.c + + Dialog procedures and support code for providing per-identity + configuration for this plug-in. + + .\config_ids.c + + Dialog procedures and support code for providing configuration + for defaults across all identities. + + .\version.rc + + Version information for the plug-in as well as all the + language resource DLLs. + + .\langres.h + + Declarations for the language resources (see below). In its + current form, it was generated via Visual Studio while editing + the language resouces file. + + .\images\plugin.ico + + A generic plug-in icon. + + .\lang\en_us\langres.rc + + US-English language resources. This will be used to create + the language resource DLL. + +------------------------------------------------------------------ + +4. BUILD REQUIREMENTS + + Microsoft(R) Platform SDK (Windows Server 2003 or later) + + (http://www.microsoft.com/msdownload/platformsdk/sdkupdate/) + + Microsoft(R) Visual C++ (Visual Studio 2003 or later) + + Although not tested, the template should build using the + Microsoft Visual C++ toolkit. + + MIT Kerberos for Windows (version 3.1 or later) SDK + + At the current time, version 3.1 is still in beta. However, + the template will not work with the 3.0 SDK due to a number of + changes that were made to the NetIDMgr API between 3.0 and + 3.1. + +------------------------------------------------------------------ + +5. BUILDING + + The build process is fairly starightforward. The source is set up + to build using 'nmake', a build tool distributed with the Platform + SDK as well as with Visual Studio. + + 1. Open a command prompt with a suitable build environment. + + From a plain command prompt, you can set up a debug build + environment targetting Windows XP (32-bit) with: + + > "%PROGRAMFILES%\Microsoft Platform SDK\SetEnv.Cmd" /XP32 /DEBUG + + 2. Set the environment variable KFWSDKDIR to point to the root of + the Kerberos for Windows 3.1 SDK. (i.e. %KFWSDKDIR%\inc + should be the include directory of the SDK) + + > SET KFWSDKDIR=%PROGRAMFILES%\MIT\Kerberos + + 3. Start the build: + + > NMAKE all + + The build target 'all' builds the plug-in and the language + resources. There is an additional build target 'clean' which + removes the temporary files and the binaries generated during + the build. + + Assuming everything goes well, the plug-in binaries should be + created under a subdirectory under 'dest'. The name of the + subdirectory reflects the target architecture and the build + type ('debug' or 'release'). + +------------------------------------------------------------------ + +6. RUNNING THE PLUG-IN + + Once the binaries for the plug-in have been built, you need to + register the plug-in with NetIDMgr by adding a registry value as + follows: + + [HKEY_CURRENT_USER\Software\MIT\NetIDMgr\PluginManager\Modules\<Module name>] + "ImagePath"="<path>" + + The <path> should be the full path to the plug-in DLL. + + <Module name> is the name of the module that you built. The + default value specified in the template is 'MyModule'. This is + the value of the macro 'MODULENAME' defined in the 'Makefile'. + + Once this is done, you need to restart NetIDMgr so that it will + pick up the new plug-in. + +------------------------------------------------------------------ + +7. KNOWN ISSUES + + 1. With the current MIT Kerberos for Windows 3.1 beta, NetIDMgr + will fail to load the plug-in when tries to load the plug-in + for the first time. Restarting NetIDMgr will fix the problem. + This will be fixed in a future beta and the final release of + KfW 3.1 + +------------------------------------------------------------------ + +8. SUPPORT / BUG REPORTS + + Problems should be sent to netidmgr@secure-endpoints.com + +------------------------------------------------------------------ diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/config_id.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/config_id.c new file mode 100644 index 000000000..0fd08617b --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/config_id.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" +#include <assert.h> + +/* Dialog procedures and support functions for handling configuration + dialogs for per-identity configuration. When the configuration + dialog is activated, an instance of this dialog will be created for + each identity that the user touches. */ + +/* The structure that we use to hold state information for the + dialog. */ +typedef struct tag_config_id_dlg_data { + khui_config_init_data cfg; /* instance information for this + dialog */ + + khm_handle ident; /* handle to the identity for this + dialog */ + + /* TODO: Add any fields for holding state here */ +} config_id_dlg_data; + +INT_PTR CALLBACK +config_id_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + config_id_dlg_data * d; + + switch (uMsg) { + case WM_INITDIALOG: + { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_int32 rv; + + d = malloc(sizeof(*d)); + assert(d); + ZeroMemory(d, sizeof(*d)); + + /* for subpanels, lParam is a pointer to a + khui_config_init_data strucutre that provides the + instance and context information. It's not a + persistent strucutre, so we have to make a copy. */ + d->cfg = *((khui_config_init_data *) lParam); + + cb = sizeof(idname); + rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb); + assert(KHM_SUCCEEDED(rv)); + + rv = kcdb_identity_create(idname, 0, &d->ident); + assert(KHM_SUCCEEDED(rv)); + + /* TODO: perform any other required initialization */ + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + } + break; + + case KHUI_WM_CFG_NOTIFY: + d = (config_id_dlg_data *) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + if (HIWORD(wParam) == WMCFG_APPLY) { + /* TODO: apply changes */ + + return TRUE; + } + break; + + case WM_DESTROY: + { + d = (config_id_dlg_data *) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d) { + if (d->ident) + kcdb_identity_release(d->ident); + + /* TODO: perform any other required uninitialization */ + + free(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + } + } + break; + } + + return FALSE; + +} diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/config_ids.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/config_ids.c new file mode 100644 index 000000000..ecc49b20c --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/config_ids.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" +#include<assert.h> + +/* Dialog procedures and support functions for handling configuration + dialogs for all identities. */ + +/* The structure that we use to hold state information for the + dialog. */ +typedef struct tag_config_ids_dlg_data { + khui_config_init_data cfg; /* instance information for this + dialog */ + + /* TODO: Add any fields for holding state here */ +} config_ids_dlg_data; + +INT_PTR CALLBACK +config_ids_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + config_ids_dlg_data * d; + + switch (uMsg) { + case WM_INITDIALOG: + { + d = malloc(sizeof(*d)); + assert(d); + ZeroMemory(d, sizeof(*d)); + + /* for subpanels, lParam is a pointer to a + khui_config_init_data strucutre that provides the + instance and context information. It's not a + persistent strucutre, so we have to make a copy. */ + d->cfg = *((khui_config_init_data *) lParam); + + /* TODO: perform any additional initialization */ + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + } + break; + + case KHUI_WM_CFG_NOTIFY: + d = (config_ids_dlg_data *) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + if (HIWORD(wParam) == WMCFG_APPLY) { + /* TODO: apply changes */ + + return TRUE; + } + break; + + case WM_DESTROY: + d = (config_ids_dlg_data *) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d) { + /* TODO: Perform any additional uninitialization */ + + free (d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + } + break; + } + + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/config_main.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/config_main.c new file mode 100644 index 000000000..cf8061b81 --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/config_main.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" +#include <assert.h> + +/* Dialog procedures and support functions for handling configuration + dialogs for general plug-in configuration. */ + +/* Structure for holding dialog data for the configuration window. */ +typedef struct tag_config_main_dlg_data { + khui_config_node cnode; + + /* TODO: add fields as needed */ +} config_main_dlg_data; + +INT_PTR CALLBACK +config_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + config_main_dlg_data * d; + + switch (uMsg) { + case WM_INITDIALOG: + d = malloc(sizeof(*d)); + assert(d); + ZeroMemory(d, sizeof(*d)); + + /* for configuration panels that are not subpanels, lParam is + a held handle to the configuration node. The handle will + be held for the lifetime of the window. */ + + d->cnode = (khui_config_node) lParam; + + /* TODO: perform any other required initialization stuff + here */ + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + break; + + case KHUI_WM_CFG_NOTIFY: + { + d = (config_main_dlg_data *) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + /* WMCFG_APPLY is the only notification we care about */ + + if (HIWORD(wParam) == WMCFG_APPLY) { + /* TODO: Apply changes and update the state */ + + return TRUE; + } + } + break; + + case WM_DESTROY: + d = (config_main_dlg_data *) + GetWindowLongPtr(hwnd, DWLP_USER); + + /* TODO: perform any other required uninitialization here */ + + if (d) { + free(d); + SetWindowLongPtr(hwnd, DWLP_USER); + } + + break; + } + + return FALSE; + +} diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/credacq.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/credacq.c new file mode 100644 index 000000000..a65686ea4 --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/credacq.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" +#include<assert.h> + +/* This file provides handlers for the credentials acquisition + messages including handling the user interface for the new + credentials dialogs. */ + +/********************************************************************* + +These are stubs for the Window message for the dialog panel. This +dialog panel is the one that is added to the new credentials window +for obtaining new credentials. + +Note that all the UI callbacks run under the UI thread. + + *********************************************************************/ + +/* This structure will hold all the state information we will need to + access from the new credentials panel for our credentials type. */ +struct nc_dialog_data { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + + /* TODO: add any other state information here */ +}; + +/* Note: This callback runs under the UI thread */ +INT_PTR +handle_wm_initdialog(HWND hwnd, WPARAM wParam, LPARAM lParam) { + khui_new_creds * nc = NULL; + khui_new_creds_by_type * nct = NULL; + struct nc_dialog_data * d = NULL; + + nc = (khui_new_creds *) lParam; + khui_cw_find_type(nc, credtype_id, &nct); + + assert(nct); + + d = malloc(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->nc = nc; + d->nct = nct; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d); +#pragma warning(pop) + + nct->aux = (LPARAM) d; /* we can use the auxiliary field to + hold a pointer to d */ + + /* TODO: Perform any additional initialization here */ + + return FALSE; +} + +/* Note: This callback runs under the UI thread */ +INT_PTR +handle_khui_wm_nc_notify(HWND hwnd, WPARAM wParam, LPARAM lParam) { + + struct nc_dialog_data * d; + + /* Refer to the khui_wm_nc_notifications enumeration in the + NetIDMgr SDK for the full list of notification messages that + can be sent. */ + + d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER); + + if (!d) + return TRUE; + + /* these should be set by now */ + assert(d->nc); + assert(d->nct); + + switch (HIWORD(wParam)) { + case WMNC_UPDATE_CREDTEXT: + { + wchar_t fmt[KHUI_MAXCCH_LONG_DESC]; + wchar_t tbuf[256]; + + /* we are being requested to update the credentials + text. We already allocated a buffer when we created the + nct structure. So we can just set the text here.*/ + + /* TODO: The credtext should reflect the credentials that + will be obtained when the new credentials operation + completes. */ + + LoadString(hResModule, IDS_NC_CT_TEMPLATE, + fmt, ARRAYLENGTH(fmt)); + + LoadString(hResModule, IDS_GEN_NONE, + tbuf, ARRAYLENGTH(tbuf)); + + assert(d->nct->credtext); + + StringCbPrintf(d->nct->credtext, KHUI_MAXCB_LONG_DESC, + fmt, tbuf); + } + break; + + case WMNC_CREDTEXT_LINK: + break; + + case WMNC_IDENTITY_CHANGE: + break; + + case WMNC_DIALOG_PREPROCESS: + break; + } + + return TRUE; +} + +/* Note: This callback runs under the UI thread */ +INT_PTR +handle_wm_command(HWND hwnd, WPARAM wParam, LPARAM lParam) { + + struct nc_dialog_data * d; + + d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + /* TODO: handle WM_COMMAND */ + return FALSE; +} + +/* Note: This callback runs under the UI thread */ +INT_PTR +handle_wm_destroy(HWND hwnd, WPARAM wParam, LPARAM lParam) { + + struct nc_dialog_data * d; + + d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER); + + if (d) { + d->nc = NULL; + d->nct = NULL; + + free(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + } + + /* TODO: Perform any additional uninitialization */ + + return FALSE; +} + +/* Dialog procedure for the new credentials panel for our credentials + type. We just dispatch messages here to other functions here. + + Note that this procedure runs under the UI thread. + */ +INT_PTR CALLBACK +nc_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + switch (uMsg) { + case WM_INITDIALOG: + return handle_wm_initdialog(hwnd, wParam, lParam); + + case WM_COMMAND: + return handle_wm_command(hwnd, wParam, lParam); + + case KHUI_WM_NC_NOTIFY: + return handle_khui_wm_nc_notify(hwnd, wParam, lParam); + + case WM_DESTROY: + return handle_wm_destroy(hwnd, wParam, lParam); + + /* TODO: add code for handling other windows messages here. */ + } + + return FALSE; +} + +/******************************************************************* + +The following section contains function stubs for each of the +credentials messages that a credentials provider is likely to want to +handle. It doesn't include a few messages, but they should be easy to +add. Please see the documentation for each of the KMSG_CRED_* +messages for documentation on how to handle each of the messages. + +********************************************************************/ + + +/* Handler for KMSG_CRED_NEW_CREDS */ +khm_int32 +handle_kmsg_cred_new_creds(khui_new_creds * nc) { + + wchar_t wshortdesc[KHUI_MAXCCH_SHORT_DESC]; + size_t cb = 0; + khui_new_creds_by_type * nct = NULL; + + /* This is a minimal handler that just adds a dialog pane to the + new credentials window to handle new credentials acquisition + for this credentials type. */ + + /* TODO: add additional initialization etc. as needed */ + + nct = malloc(sizeof(*nct)); + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id; + nct->ordinal = -1; + + LoadString(hResModule, IDS_CT_SHORT_DESC, + wshortdesc, ARRAYLENGTH(wshortdesc)); + StringCbLength(wshortdesc, sizeof(wshortdesc), &cb); +#ifdef DEBUG + assert(cb > 0); +#endif + cb += sizeof(wchar_t); + + nct->name = malloc(cb); + StringCbCopy(nct->name, cb, wshortdesc); + + /* while we are at it, we should also allocate space for the + credential text. */ + nct->credtext = malloc(KHUI_MAXCB_LONG_DESC); + ZeroMemory(nct->credtext, KHUI_MAXCB_LONG_DESC); + + nct->h_module = hResModule; + nct->dlg_proc = nc_dlg_proc; + nct->dlg_template = MAKEINTRESOURCE(IDD_NEW_CREDS); + + khui_cw_add_type(nc, nct); + + return KHM_ERROR_SUCCESS; +} + +/* Handler for KMSG_CRED_RENEW_CREDS */ +khm_int32 +handle_kmsg_cred_renew_creds(khui_new_creds * nc) { + + khui_new_creds_by_type * nct; + + /* This is a minimal handler that just adds this credential type + to the list of credential types that are participating in this + renewal operation. */ + + /* TODO: add additional initialization etc. as needed */ + + nct = malloc(sizeof(*nct)); + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id; + + khui_cw_add_type(nc, nct); + + return KHM_ERROR_SUCCESS; +} + +/* Handler for KMSG_CRED_DIALOG_PRESTART */ +khm_int32 +handle_kmsg_cred_dialog_prestart(khui_new_creds * nc) { + /* TODO: Handle this message */ + + /* The message is sent after the dialog has been created. The + window handle for the created dialog can be accessed through + the hwnd_panel member of the khui_new_creds_by_type structure + that was added for this credentials type. */ + return KHM_ERROR_SUCCESS; +} + +/* Handler for KMSG_CRED_DIALOG_NEW_IDENTITY */ +/* Not a message sent out by NetIDMgr. See documentation of + KMSG_CRED_DIALOG_NEW_IDENTITY */ +khm_int32 +handle_kmsg_cred_dialog_new_identity(khm_ui_4 uparam, + void * vparam) { + /* TODO: Handle this message */ + return KHM_ERROR_SUCCESS; +} + +/* Handler for KMSG_CRED_DIALOG_NEW_OPTIONS */ +/* Not a message sent out by NetIDMgr. See documentation of + KMSG_CRED_DIALOG_NEW_OPTIONS */ +khm_int32 +handle_kmsg_cred_dialog_new_options(khm_ui_4 uparam, + void * vparam) { + /* TODO: Handle this message */ + return KHM_ERROR_SUCCESS; +} + +/* Handler for KMSG_CRED_PROCESS */ +khm_int32 +handle_kmsg_cred_process(khui_new_creds * nc) { + /* TODO: Handle this message */ + + /* This is where the credentials acquisition should be performed + as determined by the UI. Note that this message is sent even + when the user clicks 'cancel'. The value of nc->result should + be checked before performing any credentials acquisition. If + the value is KHUI_NC_RESULT_CANCEL, then no credentials should + be acquired. Otherwise, the value would be + KHUI_NC_RESULT_PROCESS. */ + + return KHM_ERROR_SUCCESS; +} + +/* Handler for KMSG_CRED_END */ +khm_int32 +handle_kmsg_cred_end(khui_new_creds * nc) { + + khui_new_creds_by_type * nct = NULL; + + /* TODO: Perform any additional uninitialization as needed. */ + + khui_cw_find_type(nc, credtype_id, &nct); + + if (nct) { + + khui_cw_del_type(nc, credtype_id); + + if (nct->name) + free(nct->name); + if (nct->credtext) + free(nct->credtext); + + free(nct); + + } + + return KHM_ERROR_SUCCESS; +} + +/* Handler for KMSG_CRED_IMPORT */ +khm_int32 +handle_kmsg_cred_import(void) { + + /* TODO: Handle this message */ + + return KHM_ERROR_SUCCESS; +} + + +/****************************************************** + Dispatch each message to individual handlers above. + */ +khm_int32 KHMAPI +handle_cred_acq_msg(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_CRED_NEW_CREDS: + return handle_kmsg_cred_new_creds((khui_new_creds *) vparam); + + case KMSG_CRED_RENEW_CREDS: + return handle_kmsg_cred_renew_creds((khui_new_creds *) vparam); + + case KMSG_CRED_DIALOG_PRESTART: + return handle_kmsg_cred_dialog_prestart((khui_new_creds *) vparam); + + case KMSG_CRED_PROCESS: + return handle_kmsg_cred_process((khui_new_creds *) vparam); + + case KMSG_CRED_DIALOG_NEW_IDENTITY: + return handle_kmsg_cred_dialog_new_identity(uparam, vparam); + + case KMSG_CRED_DIALOG_NEW_OPTIONS: + return handle_kmsg_cred_dialog_new_options(uparam, vparam); + + case KMSG_CRED_END: + return handle_kmsg_cred_end((khui_new_creds *) vparam); + + case KMSG_CRED_IMPORT: + return handle_kmsg_cred_import(); + } + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/credprov.h b/krb5-1-6/src/windows/identity/sample/templates/credprov/credprov.h new file mode 100644 index 000000000..14670934d --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/credprov.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* only include this header file once */ +#pragma once + +#ifndef _UNICODE +#ifndef RC_INVOKED +/* This template relies on _UNICODE being defined to call the correct + APIs. */ +#error This template needs to be compiled with _UNICODE +#endif +#endif + +/* Pull in configuration macros from the Makefile */ +#include "credacq_config.h" + +/* declare a few macros about our plugin */ + +/* The following macro will be used throughout the template to refer + to the name of the plugin. The macro is actually defined the + Makefile generated configuration header file. Modify the + PLUGINNAME Makefile macro.*/ +#ifndef MYPLUGIN_NAME +#error MYPLUGIN_NAME not defined +#endif + +/* Also define the unicde equivalent of the name. In general strings + in NetIDMgr are unicode. */ +#define MYPLUGIN_NAMEW _T(MYPLUGIN_NAME) + +/* The name of the module. This is distinct from the name of the + plugin for several reasons. One of which is that a single module + can provide multiple plugins. Also, having a module name distinct + from a plugin name allows multiple vendors to provide the same + plugin. For example, the module name for the MIT Kerberos 5 plugin + is MITKrb5 while the plugin name is Krb5Cred. The macro is + actually defined in the Makefile generated configuration header + file. Modify the MODULENAME Makefile macro.*/ +#ifndef MYMODULE_NAME +#error MYMODULE_NAME not defined +#endif + +#define MYMODULE_NAMEW _T(MYMODULE_NAME) + +/* When logging events from our plugin, the event logging API can + optionally take a facility name to provide a friendly label to + identify where each event came from. We will default to the plugin + name, although it can be anything. */ +#define MYPLUGIN_FACILITYW MYPLUGIN_NAMEW + +/* Base name of the DLL that will be providing the plugin. We use it + to construct names of the DLLs that will contain localized + resources. This is defined in the Makefile and fed in to the build + through there. The macro to change in the Makefile is + DLLBASENAME. */ +#ifndef MYPLUGIN_DLLBASE +#error MYPLUGIN_DLLBASE Not defined! +#endif + +#define MYPLUGIN_DLLBASEW _T(MYPLUGIN_DLLBASE) + +/* Name of the credentials type that will be registered by the plugin. + This macro is actually defined in the Makefile generated + configuration header file. Change the CREDTYPENAME macro in the + Makefile. */ +#ifndef MYCREDTYPE_NAME +#error MYCREDTYPE_NAME not defined +#endif + +#define MYCREDTYPE_NAMEW _T(MYCREDTYPE_NAME) + +/* Configuration node names. We just concatenate a few strings + together, although you should feel free to completely define your + own. */ + +#define CONFIGNODE_MAIN MYCREDTYPE_NAMEW L"Config" +#define CONFIGNODE_ALL_ID MYCREDTYPE_NAMEW L"AllIdents" +#define CONFIGNODE_PER_ID MYCREDTYPE_NAMEW L"PerIdent" + +#include<windows.h> +/* include the standard NetIDMgr header files */ +#include<netidmgr.h> +#include<tchar.h> + +/* declarations for language resources */ +#include "langres.h" + +#ifndef NOSTRSAFE +#include<strsafe.h> +#endif + +/*************************************************** + Externals +***************************************************/ + +extern kmm_module h_khModule; +extern HINSTANCE hInstance; +extern HMODULE hResModule; + +extern const wchar_t * my_facility; + +extern khm_int32 credtype_id; + +/* Function declarations */ + +/* in plugin.c */ +khm_int32 KHMAPI +plugin_msg_proc(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam); + +/* in credtype.c */ +khm_int32 KHMAPI +cred_is_equal(khm_handle cred1, + khm_handle cred2, + void * rock); + +/* in credacq.c */ +khm_int32 KHMAPI +handle_cred_acq_msg(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam); + +/* in proppage.c */ +INT_PTR CALLBACK +pp_cred_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +/* in config_id.c */ +INT_PTR CALLBACK +config_id_dlgproc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +/* in config_ids.c */ +INT_PTR CALLBACK +config_ids_dlgproc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +/* in config_main.c */ +INT_PTR CALLBACK +config_dlgproc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/credtype.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/credtype.c new file mode 100644 index 000000000..cee7df19a --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/credtype.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AND + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" + +/* Functions for handling our credentials type. +*/ + +khm_int32 KHMAPI +cred_is_equal(khm_handle cred1, + khm_handle cred2, + void * rock) { + + khm_int32 result; + + /* TODO: Check any additional fields to determine if the two + credentials are equal or not. */ + + /* Note that this is actually a comparison function. It should + return 0 if the credentials are found to be equal, and non-zero + if they are not. We just set this to 0 if we don't need to + check any additional fields and accept the two credentials as + being equal. By the time this function is called, the + identity, name and type of the credentials have already been + found to be equal. */ + result = 0; + + return result; +} diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/images/plugin.ico b/krb5-1-6/src/windows/identity/sample/templates/credprov/images/plugin.ico new file mode 100644 index 0000000000000000000000000000000000000000..99ffbc411b5f9cf6244bd011297fdb6194a5478b GIT binary patch literal 9110 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 U#!gL^-VAqF8Gl23W3Smi0oL6$(EtDd literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/lang/en_us/langres.rc b/krb5-1-6/src/windows/identity/sample/templates/credprov/lang/en_us/langres.rc new file mode 100644 index 000000000..ebffa5410 --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/lang/en_us/langres.rc @@ -0,0 +1,204 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\..\langres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\..\\langres.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_PLUGIN ICON "..\\..\\images\\plugin.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_PP_CRED DIALOGEX 0, 0, 235, 156 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Property Page" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "TODO: layout property page",IDC_STATIC,60,73,110,8 +END + +IDD_PP_IDENT DIALOGEX 0, 0, 235, 156 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Property Page" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "TODO: layout property page",IDC_STATIC,60,73,106,8 +END + +IDD_NEW_CREDS DIALOGEX 0, 0, 300, 166 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "My Cred Options",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11 +END + +IDD_CONFIG DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN +END + +IDD_CONFIG_ID DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN +END + +IDD_CONFIG_IDS DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_PP_CRED, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 149 + END + + IDD_PP_IDENT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 149 + END + + IDD_NEW_CREDS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 293 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CONFIG_ID, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_CONFIG_IDS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_PLUGIN_DESC "My Credentials Provider Plugin" + IDS_CT_SHORT_DESC "My Cred" + IDS_CT_LONG_DESC "My Credential" +END + +STRINGTABLE +BEGIN + IDS_NC_CT_TEMPLATE "<p><a id=""SwitchPanel"" param=""MyCred""><b>My Cred</b></a><tab>: %s</p>" + IDS_NC_CT_TEMPLATE_NL "<p><tab> %s</p>" + IDS_GEN_NONE "(none)" + IDS_CFG_SHORT_DESC "My Creds" + IDS_CFG_LONG_DESC "My Creds Options" + IDS_CFG_IDS_SHORT_DESC "My Creds" + IDS_CFG_IDS_LONG_DESC "My Creds Options for all identities" + IDS_CFG_ID_SHORT_DESC "My Creds" + IDS_CFG_ID_LONG_DESC "My Creds Options for this identity" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/langres.h b/krb5-1-6/src/windows/identity/sample/templates/credprov/langres.h new file mode 100644 index 000000000..962c4cb22 --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/langres.h @@ -0,0 +1,34 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\sample\templates\credprov\lang\en_us\langres.rc +// +#define IDD_PP_CRED 106 +#define IDD_PP_IDENT 107 +#define IDS_PLUGIN_DESC 109 +#define IDS_CT_SHORT_DESC 110 +#define IDI_PLUGIN 110 +#define IDS_CT_LONG_DESC 111 +#define IDD_NEW_CREDS 112 +#define IDS_NC_CT_TEMPLATE 112 +#define IDS_NC_CT_TEMPLATE_NL 113 +#define IDD_CONFIG 113 +#define IDS_GEN_NONE 114 +#define IDD_CONFIG_ID 114 +#define IDS_CFG_SHORT_DESC 115 +#define IDD_CONFIG_IDS 115 +#define IDS_CFG_LONG_DESC 116 +#define IDS_CFG_IDS_SHORT_DESC 117 +#define IDS_CFG_IDS_LONG_DESC 118 +#define IDS_CFG_ID_SHORT_DESC 119 +#define IDS_CFG_ID_LONG_DESC 120 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 116 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1039 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/main.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/main.c new file mode 100644 index 000000000..07da40d57 --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/main.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" + +/* This file provides the entry points for the module. The purpose of + each entry point is explained below. +*/ + +kmm_module h_khModule; /* KMM's handle to this module */ +HINSTANCE hInstance; /* handle to our DLL */ +HMODULE hResModule; /* handle to DLL containing language specific resources */ + +const wchar_t * my_facility = MYPLUGIN_FACILITYW; + +/* locales and n_locales are used to provide information to NetIDMgr + about the locales that we support. Each locale that is supported + is represented by a single line below. NetIDMgr will pick a + suitable locale from this list as described in the documentation + for kmm_set_locale_info(). */ +kmm_module_locale locales[] = { + + /* there needs to be at least one language that is supported. + Here we declare that to be US English, and make it the + default. */ + LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), + MYPLUGIN_DLLBASEW L"_en_us.dll", /* this is the name of + the DLL. We paste a + trailer to basename + of the DLL. This + DLL should reside in + the same directory + as the plugin + DLL. */ + KMM_MLOC_FLAG_DEFAULT) +}; +int n_locales = ARRAYLENGTH(locales); + +/******************************************************************* + init_module + ***************************************************************** + + This is the entry point for the module. Each module can provide + multiple plugins and each plugin will need a separate entry point. + Generally, the module entry point will set up localized resources + and register the plugins. + +*/ +KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) { + + khm_int32 rv = KHM_ERROR_SUCCESS; + kmm_plugin_reg pi; + wchar_t description[KMM_MAXCCH_DESC]; + int t; + + h_khModule = h_module; + + rv = kmm_set_locale_info(h_module, locales, n_locales); + if(KHM_SUCCEEDED(rv)) { + /* if the call succeeded, then NetIDMgr has picked a localized + resource DLL for us to use. */ + hResModule = kmm_get_resource_hmodule(h_module); + } else + goto _exit; + + /* TODO: Perform any other required initialization operations. */ + + /* register our plugin */ + ZeroMemory(&pi, sizeof(pi)); + + pi.name = MYPLUGIN_NAMEW; /* name of the plugin */ + pi.type = KHM_PITYPE_CRED; /* type. This is a credentials + provider. Setting this type has + the effect of having the plugin + entrypoint being automatically + subscribed to credentials provider + messages. */ + + /* An icon is optional, but we provide one anyway. */ + pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN), + IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + pi.flags = 0; + pi.msg_proc = plugin_msg_proc; + pi.description = description; + pi.dependencies = NULL; + t = LoadString(hResModule, IDS_PLUGIN_DESC, + description, ARRAYLENGTH(description)); + if (!t) + description[0] = L'\0'; + else + description[ARRAYLENGTH(description) - 1] = L'\0'; + + rv = kmm_provide_plugin(h_module, &pi); + + /* TODO: register any additional plugins */ + + /* Returning a successful code (KHM_ERROR_SUCCESS) will cause the + plugins to be initialized. If no plugin is successfully + registered while processing init_module or if a code other than + KHM_ERROR_SUCCESS is returned, the module will be immediately + unloaded. */ + + _exit: + return rv; +} + +/********************************************************** + Exit module + ******************************************************** + + Called by the NetIDMgr module manager when unloading the module. + This will get called even if the module is being unloaded due to an + error code returned by init_module(). This callback is required. */ +KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) { + + /* Unregistering the plugin is not required at this point. */ + + /* TODO: Perform any other required cleanup here. */ + + return KHM_ERROR_SUCCESS; /* the return code is ignored */ +} + +/* General DLL initialization. It is advisable to not do anything + here and also keep in mind that the plugin will be loaded at a time + where some threads have already started. So DLL_THREAD_ATTACH will + not fire for every thread. In addition, the plugin will be + unloaded before the application and all the threads terminate. */ +BOOL WINAPI DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + hInstance = hinstDLL; + break; + + case DLL_PROCESS_DETACH: + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + } + + return TRUE; +} diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/plugin.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/plugin.c new file mode 100644 index 000000000..9b1b0ce94 --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/plugin.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" +#include<assert.h> + +/* This file provides the message processing function and the support + routines for implementing our plugin. Note that some of the + message processing routines have been moved to other source files + based on their use. +*/ + +khm_int32 credtype_id = KCDB_CREDTYPE_INVALID; +khm_handle g_credset = NULL; + +/* Handler for system messages. The only two we handle are + KMSG_SYSTEM_INIT and KMSG_SYSTEM_EXIT. */ +khm_int32 KHMAPI +handle_kmsg_system(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch (msg_subtype) { + + /* This is the first message that will be received by a + plugin. We use it to perform initialization operations + such as registering any credential types, data types and + attributes. */ + case KMSG_SYSTEM_INIT: + { + kcdb_credtype ct; + wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; + wchar_t long_desc[KCDB_MAXCCH_LONG_DESC]; + khui_config_node cnode; + khui_config_node_reg creg; + + /* First and foremost, we need to register a credential + type. */ + ZeroMemory(&ct, sizeof(ct)); + ct.id = KCDB_CREDTYPE_AUTO; + ct.name = MYCREDTYPE_NAMEW; + + short_desc[0] = L'\0'; + LoadString(hResModule, IDS_CT_SHORT_DESC, + short_desc, ARRAYLENGTH(short_desc)); + + long_desc[0] = L'\0'; + LoadString(hResModule, IDS_CT_LONG_DESC, + long_desc, ARRAYLENGTH(long_desc)); + + ct.icon = NULL; /* We skip the icon for now, but you + can assign a handle to an icon + here. The icon will be used to + represent the credentials type.*/ + + kmq_create_subscription(plugin_msg_proc, &ct.sub); + + ct.is_equal = cred_is_equal; + + rv = kcdb_credtype_register(&ct, &credtype_id); + + /* We create a global credential set that we use in the + plug-in thread. This alleviates the need to create one + everytime we need one. Keep in mind that this should + only be used in the plug-in thread and should not be + touched from the UI thread or any other thread. */ + kcdb_credset_create(&g_credset); + + /* TODO: Perform additional initialization operations. */ + + /* TODO: Also list out the credentials of this type that + already exist. */ + + /* Now we register our configuration panels. */ + + + /* This configuration panel is the one that controls + general options. We leave the identity specific and + identity defaults for other configuration panels. */ + + ZeroMemory(&creg, sizeof(creg)); + + short_desc[0] = L'\0'; + + LoadString(hResModule, IDS_CFG_SHORT_DESC, + short_desc, ARRAYLENGTH(short_desc)); + + long_desc[0] = L'\0'; + + LoadString(hResModule, IDS_CFG_LONG_DESC, + long_desc, ARRAYLENGTH(long_desc)); + + creg.name = CONFIGNODE_MAIN; + creg.short_desc = short_desc; + creg.long_desc = long_desc; + creg.h_module = hResModule; + creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG); + creg.dlg_proc = config_dlgproc; + creg.flags = 0; + + khui_cfg_register(NULL, &creg); + + /* Now we do the identity specific and identity default + configuration panels. "KhmIdentities" is a predefined + configuration node under which all the identity spcific + configuration is managed. */ + + if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &cnode))) { + /* this should always work */ + assert(FALSE); + rv = KHM_ERROR_NOT_FOUND; + break; + } + + /* First the tab panel for defaults for all identities */ + + ZeroMemory(&creg, sizeof(creg)); + + short_desc[0] = L'\0'; + LoadString(hResModule, IDS_CFG_IDS_SHORT_DESC, + short_desc, ARRAYLENGTH(short_desc)); + long_desc[0] = L'\0'; + LoadString(hResModule, IDS_CFG_IDS_LONG_DESC, + long_desc, ARRAYLENGTH(long_desc)); + + creg.name = CONFIGNODE_ALL_ID; + creg.short_desc = short_desc; + creg.long_desc = long_desc; + creg.h_module = hResModule; + creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_IDS); + creg.dlg_proc = config_ids_dlgproc; + creg.flags = KHUI_CNFLAG_SUBPANEL; + + khui_cfg_register(cnode, &creg); + + /* Now the panel for per identity configuration */ + + ZeroMemory(&creg, sizeof(creg)); + + short_desc[0] = L'\0'; + LoadString(hResModule, IDS_CFG_ID_SHORT_DESC, + short_desc, ARRAYLENGTH(short_desc)); + long_desc[0] = L'\0'; + LoadString(hResModule, IDS_CFG_ID_LONG_DESC, + long_desc, ARRAYLENGTH(long_desc)); + + creg.name = CONFIGNODE_PER_ID; + creg.short_desc = short_desc; + creg.long_desc = long_desc; + creg.h_module = hResModule; + creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_ID); + creg.dlg_proc = config_id_dlgproc; + creg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL; + + khui_cfg_register(cnode, &creg); + + khui_cfg_release(cnode); + } + break; + + /* This is the last message that will be received by the + plugin. */ + case KMSG_SYSTEM_EXIT: + { + khui_config_node cnode; + khui_config_node cn_idents; + + /* It should not be assumed that initialization of the + plugin went well at this point since we receive a + KMSG_SYSTEM_EXIT even if the initialization failed. */ + + if (credtype_id != KCDB_CREDTYPE_INVALID) { + kcdb_credtype_unregister(credtype_id); + credtype_id = KCDB_CREDTYPE_INVALID; + } + + if (g_credset) { + kcdb_credset_delete(g_credset); + g_credset = NULL; + } + + /* Now unregister any configuration nodes we registered. */ + + if (KHM_SUCCEEDED(khui_cfg_open(NULL, CONFIGNODE_MAIN, &cnode))) { + khui_cfg_remove(cnode); + khui_cfg_release(cnode); + } + + if (KHM_SUCCEEDED(khui_cfg_open(NULL, L"KhmIdentities", &cn_idents))) { + if (KHM_SUCCEEDED(khui_cfg_open(cn_idents, + CONFIGNODE_ALL_ID, + &cnode))) { + khui_cfg_remove(cnode); + khui_cfg_release(cnode); + } + + if (KHM_SUCCEEDED(khui_cfg_open(cn_idents, + CONFIGNODE_PER_ID, + &cnode))) { + khui_cfg_remove(cnode); + khui_cfg_release(cnode); + } + + khui_cfg_release(cn_idents); + } + + /* TODO: Perform additional uninitialization + operations. */ + } + break; + } + + return rv; +} + +/* Handler for credentials the refresh message. */ +khm_int32 +handle_kmsg_cred_refresh(void) { + /* TODO: Re-enumerate the credentials of our credentials type */ + + /* + Re-enumerating credentials would look something like this: + + - flush all credentials from g_credset (kcdb_credset_flush()) + + - list out the credentials and add them to g_credset + + - collect the credentials from g_credset to the root credentials + set. (kcdb_credset_collect()) + + Note that when listing credentials, each credential must be + populated with enough information to locate the actual + credential at a later time. + */ + + return KHM_ERROR_SUCCESS; +} + +/* Handler for destroying credentials */ +khm_int32 +handle_kmsg_cred_destroy_creds(khui_action_context * ctx) { + /* TODO: Destroy credentials of our type as specified by the + action context passed in through vparam. */ + + /* The credential set in ctx->credset contains the credentials + that are to be destroyed. */ + + return KHM_ERROR_SUCCESS; +} + +/* Begin a property sheet */ +khm_int32 +handle_kmsg_cred_pp_begin(khui_property_sheet * ps) { + + /* TODO: Provide the information necessary to show a property + page for a credentials belonging to our credential type. */ + + PROPSHEETPAGE *p; + + if (ps->credtype == credtype_id && + ps->cred) { + /* We have been requested to show a property sheet for one of + our credentials. */ + p = malloc(sizeof(*p)); + ZeroMemory(p, sizeof(*p)); + + p->dwSize = sizeof(*p); + p->dwFlags = 0; + p->hInstance = hResModule; + p->pszTemplate = MAKEINTRESOURCE(IDD_PP_CRED); + p->pfnDlgProc = pp_cred_dlg_proc; + p->lParam = (LPARAM) ps; + khui_ps_add_page(ps, credtype_id, 0, p, NULL); + } + + return KHM_ERROR_SUCCESS; +} + +/* End a property sheet */ +khm_int32 +handle_kmsg_cred_pp_end(khui_property_sheet * ps) { + /* TODO: Handle the end of a property sheet. */ + + khui_property_page * p = NULL; + + khui_ps_find_page(ps, credtype_id, &p); + if (p) { + if (p->p_page) + free(p->p_page); + p->p_page = NULL; + } + + return KHM_ERROR_SUCCESS; +} + +/* IP address change notification */ +khm_int32 +handle_kmsg_cred_addr_change(void) { + /* TODO: Handle this message. */ + + return KHM_ERROR_SUCCESS; +} + +/* Message dispatcher for credentials messages. */ +khm_int32 KHMAPI +handle_kmsg_cred(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_CRED_REFRESH: + return handle_kmsg_cred_refresh(); + + case KMSG_CRED_DESTROY_CREDS: + return handle_kmsg_cred_destroy_creds((khui_action_context *) vparam); + + case KMSG_CRED_PP_BEGIN: + return handle_kmsg_cred_pp_begin((khui_property_sheet *) vparam); + + case KMSG_CRED_PP_END: + return handle_kmsg_cred_pp_end((khui_property_sheet *) vparam); + + case KMSG_CRED_ADDR_CHANGE: + return handle_kmsg_cred_addr_change(); + + default: + /* Credentials acquisition messages are all handled in a + different source file. */ + if (IS_CRED_ACQ_MSG(msg_subtype)) + return handle_cred_acq_msg(msg_type, msg_subtype, + uparam, vparam); + } + + return rv; +} + + +/* This is the main message handler for our plugin. All the plugin + messages end up here where we either handle it directly or dispatch + it to other handlers. */ +khm_int32 KHMAPI plugin_msg_proc(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + switch(msg_type) { + case KMSG_SYSTEM: + return handle_kmsg_system(msg_type, msg_subtype, uparam, vparam); + + case KMSG_CRED: + return handle_kmsg_cred(msg_type, msg_subtype, uparam, vparam); + } + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/proppage.c b/krb5-1-6/src/windows/identity/sample/templates/credprov/proppage.c new file mode 100644 index 000000000..eaffde23e --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/proppage.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include "credprov.h" + +/* Dialog procedure and support code for displaying property sheets + for credentials of type MyCred. */ + +/* Dialog procedure for the property sheet. This will run under the + UI thread when a property sheet is being displayed for one of our + credentials.. */ +INT_PTR CALLBACK +pp_cred_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + switch (uMsg) { + case WM_INITDIALOG: + { + khui_property_sheet * ps; + PROPSHEETPAGE * p; + + p = (PROPSHEETPAGE *) lParam; + ps = (khui_property_sheet *) p->lParam; + + /* TODO: Populate the property sheet controls with values + extracted from the credential. (ps->cred) */ + + return FALSE; + } + } + + return FALSE; +} + diff --git a/krb5-1-6/src/windows/identity/sample/templates/credprov/version.rc b/krb5-1-6/src/windows/identity/sample/templates/credprov/version.rc new file mode 100644 index 000000000..47b032c4f --- /dev/null +++ b/krb5-1-6/src/windows/identity/sample/templates/credprov/version.rc @@ -0,0 +1,94 @@ +/* Copyright (c) 2006 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* $Id$ */ + +#include "credprov.h" +#include<netidmgr_version.h> + +/* We use the same version.rc file for the main plugin DLL as well as + for the localized resource DLLs.*/ + +#ifndef LANGVER + +#define STR_FILEDESC "My Credentials Provider Plugin for NetIDMgr" +#define STR_INTNAME MYPLUGIN_NAME +#define STR_ORIGNAME MYPLUGIN_DLLBASE ".dll" + +#else + +#ifdef LANG_en_us + +#define STR_FILEDESC "English(US) language resources for My Credentials Provider" +#define STR_INTNAME MYPLUGIN_DLLBASE "_en_us" +#define STR_ORIGNAME MYPLUGIN_DLLBASE "_en_us.dll" + +#else + +#error Unknown langugae + +#endif + +#endif + +1 VERSIONINFO + FILEVERSION VERSION_LISTC + PRODUCTVERSION VERSION_LISTC + FILEFLAGSMASK KH_VER_FILEFLAGMASK + FILEFLAGS KH_VER_FILEFLAGS + FILEOS KH_VER_FILEOS + FILETYPE KH_VER_FILETYPEDLL + FILESUBTYPE 0 + { + + BLOCK "StringFileInfo" + { + BLOCK "040904b0" + { + VALUE "CompanyName", "My Company" + VALUE "FileDescription", "My Credentials Provider Plugin" + VALUE "FileVersion", VERSION_STRING + VALUE "InternalName", STR_INTNAME + VALUE "LegalCopyright", "(C) 2006 My Company" + VALUE "OriginalFilename", STR_ORIGNAME + VALUE "ProductName", "My Plugin Product" + VALUE "ProductVersion", VERSION_STRING +#ifndef LANGVER + VALUE NIMV_MODULE, MYMODULE_NAME + +/* if more than one plugin is provided by this module, then all of + those plugins should be listed here separated by commas. */ + VALUE NIMV_PLUGINS, MYPLUGIN_NAME + + VALUE NIMV_APIVER, KH_VERSION_STRINGAPI + VALUE NIMV_SUPPORT, "http://example.com/myplugin" +#endif + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1200 + } + } diff --git a/krb5-1-6/src/windows/identity/ui/Makefile b/krb5-1-6/src/windows/identity/ui/Makefile new file mode 100644 index 000000000..cf20127a3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/Makefile @@ -0,0 +1,109 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=ui +!include <../config/Makefile.w32> + +EXEFILE=$(BINDIR)\netidmgr.exe + +MANIFESTFILE=$(BINDIR)\netidmgr.exe.static.manifest + +OBJFILES= \ + $(OBJ)\main.obj \ + $(OBJ)\mainmenu.obj \ + $(OBJ)\toolbar.obj \ + $(OBJ)\statusbar.obj \ + $(OBJ)\notifier.obj \ + $(OBJ)\timer.obj \ + $(OBJ)\uiconfig.obj \ + $(OBJ)\mainwnd.obj \ + $(OBJ)\credwnd.obj \ + $(OBJ)\htwnd.obj \ + $(OBJ)\passwnd.obj \ + $(OBJ)\newcredwnd.obj \ + $(OBJ)\propertywnd.obj \ + $(OBJ)\credfuncs.obj \ + $(OBJ)\configwnd.obj \ + $(OBJ)\aboutwnd.obj \ + $(OBJ)\reqdaemon.obj \ + $(OBJ)\addrchange.obj \ + $(OBJ)\debugfuncs.obj \ + $(OBJ)\taskbar.obj \ + $(OBJ)\cfg_general_wnd.obj \ + $(OBJ)\cfg_identities_wnd.obj \ + $(OBJ)\cfg_notif_wnd.obj \ + $(OBJ)\cfg_plugins_wnd.obj \ + $(OBJ)\cfg_appear_wnd.obj + +RESFILES= \ + $(OBJ)\khapp.res \ + $(OBJ)\appver.res + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +LIBFILES=$(LIBDIR)\nidmgr64.lib +!else +LIBFILES=$(LIBDIR)\nidmgr32.lib +!endif + +SDKLIBFILES= \ + comctl32.lib \ + shell32.lib \ + htmlhelp.lib \ + iphlpapi.lib \ + shlwapi.lib \ + msimg32.lib \ + ole32.lib + +!if "$(APPVER)" != "5.0" +SDKLIBFILES = $(SDKLIBFILES) uxtheme.lib +!endif + +$(OBJ)\uiconfig.c: uiconfig.csv $(CONFDIR)\csvschema.cfg + $(CCSV) $** $@ + +$(OBJ)\khapp.res: lang\en_us\khapp.rc + $(RC2RES) + +$(OBJ)\appver.res: appver.rc + $(RC2RES) + +!if "$(KH_BUILD)"=="RETAIL" +$(MANIFESTFILE): netidmgr.manifest.$(CPU).$(KH_CLVER) +!else +$(MANIFESTFILE): netidmgr.manifest.$(CPU).$(KH_CLVER).debug +!endif + $(CP) $** $@ + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +SCLIB=bufferoverflowu.lib +!else +SCLIB= +!endif + +$(EXEFILE): $(OBJFILES) $(RESFILES) $(LIBFILES) + $(EXEGUILINK) $(SDKLIBFILES) $(SCLIB) + $(_VC_MANIFEST_EMBED_EXE) $(MANIFESTFILE) + $(_VC_MANIFEST_CLEAN) + +all: mkdirs $(MANIFESTFILE) $(EXEFILE) diff --git a/krb5-1-6/src/windows/identity/ui/Makefile.w2k b/krb5-1-6/src/windows/identity/ui/Makefile.w2k new file mode 100644 index 000000000..a64aea7c3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/Makefile.w2k @@ -0,0 +1,91 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=ui +!include <../config/Makefile.w2k> + +EXEFILE=$(BINDIR)\netidmgr.exe + +OBJFILES= \ + $(OBJ)\main.obj \ + $(OBJ)\mainmenu.obj \ + $(OBJ)\toolbar.obj \ + $(OBJ)\statusbar.obj \ + $(OBJ)\notifier.obj \ + $(OBJ)\timer.obj \ + $(OBJ)\uiconfig.obj \ + $(OBJ)\mainwnd.obj \ + $(OBJ)\credwnd.obj \ + $(OBJ)\htwnd.obj \ + $(OBJ)\passwnd.obj \ + $(OBJ)\newcredwnd.obj \ + $(OBJ)\propertywnd.obj \ + $(OBJ)\credfuncs.obj \ + $(OBJ)\configwnd.obj \ + $(OBJ)\aboutwnd.obj \ + $(OBJ)\reqdaemon.obj \ + $(OBJ)\addrchange.obj \ + $(OBJ)\debugfuncs.obj \ + $(OBJ)\cfg_general_wnd.obj \ + $(OBJ)\cfg_identities_wnd.obj \ + $(OBJ)\cfg_notif_wnd.obj \ + $(OBJ)\cfg_plugins_wnd.obj \ + $(OBJ)\cfg_appear_wnd.obj + +RESFILES= \ + $(OBJ)\khapp.res \ + $(OBJ)\appver.res + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +LIBFILES=$(LIBDIR)\nidmgr64.lib +!else +LIBFILES=$(LIBDIR)\nidmgr32.lib +!endif + +SDKLIBFILES= \ + comctl32.lib \ + shell32.lib \ + htmlhelp.lib \ + iphlpapi.lib \ + shlwapi.lib + +$(OBJ)\uiconfig.c: uiconfig.csv $(CONFDIR)\csvschema.cfg + $(CCSV) $** $@ + +$(OBJ)\khapp.res: lang\en_us\khapp.rc + $(RC2RES) + +$(OBJ)\appver.res: appver.rc + $(RC2RES) + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +SCLIB=bufferoverflowu.lib +!else +SCLIB= +!endif + +$(EXEFILE): $(OBJFILES) $(RESFILES) $(LIBFILES) + $(EXEGUILINK) $(SDKLIBFILES) $(SCLIB) + +all: mkdirs $(EXEFILE) diff --git a/krb5-1-6/src/windows/identity/ui/aboutwnd.c b/krb5-1-6/src/windows/identity/ui/aboutwnd.c new file mode 100644 index 000000000..cc88705d7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/aboutwnd.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<netidmgr_intver.h> +#include<tlhelp32.h> + +#if DEBUG +#include<assert.h> +#endif + +INT_PTR CALLBACK +about_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + { + HANDLE hsnap; + HWND hw; + + SetDlgItemText(hwnd, IDC_PRODUCT, + TEXT(KH_VERSTR_PRODUCT_1033)); + /* retain the original copyright strings */ +#ifdef OVERRIDE_COPYRIGHT + SetDlgItemText(hwnd, IDC_COPYRIGHT, + TEXT(KH_VERSTR_COPYRIGHT_1033)); +#endif + SetDlgItemText(hwnd, IDC_BUILDINFO, + TEXT(KH_VERSTR_BUILDINFO_1033)); + + hsnap = + CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, + 0); + + if (hsnap != INVALID_HANDLE_VALUE) { + LVCOLUMN lvc; + MODULEENTRY32 mod; + RECT r; + + hw = GetDlgItem(hwnd, IDC_MODULES); +#ifdef DEBUG + assert(hw != NULL); +#endif + + GetWindowRect(hw, &r); + OffsetRect(&r, -r.left, -r.top); + + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + + lvc.pszText = L"Name"; + lvc.cx = r.right / 4; + + ListView_InsertColumn(hw, 0, &lvc); + + lvc.pszText = L"Path"; + lvc.cx = (r.right * 3) / 4; + ListView_InsertColumn(hw, 1, &lvc); + + ZeroMemory(&mod, sizeof(mod)); + mod.dwSize = sizeof(mod); + + /* done with columns, now for the actual data */ + if (!Module32First(hsnap, &mod)) + goto _done_with_modules; + + do { + + LVITEM lvi; + int idx; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_TEXT; + lvi.pszText = mod.szModule; + idx = ListView_InsertItem(hw, &lvi); + + lvi.mask = LVIF_TEXT; + lvi.iItem = idx; + lvi.iSubItem = 1; + lvi.pszText = mod.szExePath; + ListView_SetItem(hw, &lvi); + + ZeroMemory(&mod, sizeof(mod)); + mod.dwSize = sizeof(mod); + } while(Module32Next(hsnap, &mod)); + + _done_with_modules: + CloseHandle(hsnap); + } + + khm_add_dialog(hwnd); + khm_enter_modal(hwnd); + } + return FALSE; + + case WM_DESTROY: + khm_del_dialog(hwnd); + return TRUE; + + case WM_CLOSE: + khm_leave_modal(); + DestroyWindow(hwnd); + return TRUE; + + case WM_COMMAND: + if (wParam == MAKEWPARAM(IDOK, BN_CLICKED)) { + khm_leave_modal(); + DestroyWindow(hwnd); + } + return TRUE; + } + + return FALSE; +} + +void +khm_create_about_window(void) { + HWND hwnd; + hwnd = CreateDialog(khm_hInstance, + MAKEINTRESOURCE(IDD_ABOUT), + khm_hwnd_main, + about_dlg_proc); + + ShowWindow(hwnd, SW_SHOW); + /* no need to keep track of the hwnd, since we add it to the + dialog chain in the dialog procedure */ +} diff --git a/krb5-1-6/src/windows/identity/ui/aboutwnd.h b/krb5-1-6/src/windows/identity/ui/aboutwnd.h new file mode 100644 index 000000000..7da709d93 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/aboutwnd.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_ABOUTWND_H +#define __KHIMAIRA_ABOUTWND_H + +void +khm_create_about_window(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/addrchange.c b/krb5-1-6/src/windows/identity/ui/addrchange.c new file mode 100644 index 000000000..3953e4f10 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/addrchange.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<iphlpapi.h> + +static HANDLE evt_terminate = NULL; +static HANDLE h_thread = NULL; + +DWORD WINAPI +addr_change_thread(LPVOID dummy) { + + HANDLE h_waits[2]; + HANDLE h_notify; + + OVERLAPPED overlap; + DWORD ret; + + PDESCTHREAD(L"Address change waiter", L"App"); + + ZeroMemory(&overlap, sizeof(overlap)); + + h_notify = NULL; + overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + do { + ret = NotifyAddrChange(&h_notify, &overlap); + + if (ret != ERROR_IO_PENDING) { + goto _end_thread; /* some error */ + } + + h_waits[0] = overlap.hEvent; + h_waits[1] = evt_terminate; + + ret = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE); + + if ( ret == WAIT_OBJECT_0 ) { + Sleep(3000); /* wait for things to settle down */ + kmq_post_message(KMSG_CRED, KMSG_CRED_ADDR_CHANGE, 0, 0); + } else { + goto _end_thread; + } + } while(TRUE); + + _end_thread: + ExitThread(0); +} + +void +khm_addr_change_notifier_init(void) { + evt_terminate = CreateEvent(NULL, FALSE, FALSE, NULL); + h_thread = CreateThread(NULL, + 64 * 4096, + addr_change_thread, + NULL, + 0, + NULL); +} + +void +khm_addr_change_notifier_exit(void) { + if (h_thread && evt_terminate) { + SetEvent(evt_terminate); + WaitForSingleObject(h_thread, INFINITE); + + CloseHandle(h_thread); + CloseHandle(evt_terminate); + } +} diff --git a/krb5-1-6/src/windows/identity/ui/addrchange.h b/krb5-1-6/src/windows/identity/ui/addrchange.h new file mode 100644 index 000000000..2f605af8c --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/addrchange.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __NETIDMGR_ADDRCHANGE_H +#define __NETIDMGR_ADDRCHANGE_H + +void +khm_addr_change_notifier_init(void); + +void +khm_addr_change_notifier_exit(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/appglobal.h b/krb5-1-6/src/windows/identity/ui/appglobal.h new file mode 100644 index 000000000..235826d07 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/appglobal.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_APPGLOBAL_H +#define __KHIMAIRA_APPGLOBAL_H + +/* Helpfile */ +#define NIDM_HELPFILE L"netidmgr.chm" + +/* global data */ +extern HINSTANCE khm_hInstance; +extern int khm_nCmdShow; +extern const wchar_t * khm_facility; +extern kconf_schema schema_uiconfig[]; +extern khm_ui_4 khm_commctl_version; +extern const khm_version app_version; + +#define IS_COMMCTL6() (khm_commctl_version >= 0x60000) + +/* The structure used to send command-line options to a remote + NetIDMgr session for versions prior to 1.2. */ +typedef struct tag_khm_startup_options_v1 { + BOOL seen; + BOOL processing; + + BOOL init; + BOOL import; + BOOL renew; + BOOL destroy; + + BOOL autoinit; + BOOL exit; + BOOL error_exit; + + BOOL no_main_window; +} khm_startup_options_v1; + +/* Used on NetIDMgr version 1.2.x */ +typedef struct tag_khm_startup_options_v2 { + khm_int32 magic; /* set to STARTUP_OPTIONS_MAGIC */ + DWORD cb_size; /* size of structure, in bytes */ + + BOOL init; + BOOL import; + BOOL renew; + BOOL destroy; + + BOOL autoinit; + BOOL remote_exit; + + khm_int32 code; +} khm_startup_options_v2; + +/* Used on NetIDMgr version 1.3.1 and later */ +typedef struct tag_khm_startup_options_v3 { + struct tag_khm_startup_options_v2 v2opt; + + khm_int32 remote_display; /* combination of SOPTS_DISPLAY_* */ +} khm_startup_options_v3; + +#define STARTUP_OPTIONS_MAGIC 0x1f280e41 + +/* The following macros are used with + tag_khm_startup_options_v3->remote_display */ + +/* Show (unhide) the main window. */ +#define SOPTS_DISPLAY_SHOW 0x00000001 + +/* Hide the main window. (Can't be used with SOPTS_DISPLAY_SHOW) */ +#define SOPTS_DISPLAY_HIDE 0x00000002 + +/* Suppress the default action on the remote end */ +#define SOPTS_DISPLAY_NODEF 0x00000004 + +/* Used internally. */ +typedef struct tag_khm_startup_options_int { + khm_boolean seen; + khm_boolean processing; + khm_boolean remote; /* is this a remote request? */ + + khm_boolean init; + khm_boolean import; + khm_boolean renew; + khm_boolean destroy; + + khm_boolean autoinit; + khm_boolean exit; + khm_boolean remote_exit; + + khm_boolean error_exit; + + khm_boolean no_main_window; + khm_int32 display; /* SOPTS_DISPLAY_* */ + + LONG pending_renewals; +} khm_startup_options; + +extern khm_startup_options khm_startup; + +/* Used to query a remote instance of NetIDMgr for the version. */ +typedef struct tag_khm_query_app_version_v1 { + khm_int32 magic; + + khm_int32 code; + + khm_version ver_caller; + khm_version ver_remote; + + khm_boolean request_swap; +} khm_query_app_version; + +#define KHM_QUERY_APP_VER_MAGIC 0x38f8c2eb + +void khm_add_dialog(HWND dlg); +void khm_del_dialog(HWND dlg); +BOOL khm_is_dialog_active(void); + +void khm_enter_modal(HWND hwnd); +void khm_leave_modal(void); + +void khm_add_property_sheet(khui_property_sheet * s); +void khm_del_property_sheet(khui_property_sheet * s); + +void khm_init_gui(void); +void khm_exit_gui(void); + +void khm_parse_commandline(); +void khm_register_window_classes(void); + +HWND khm_html_help(HWND hwnd, wchar_t * suffix, UINT command, DWORD_PTR data); + +WPARAM khm_message_loop_int(khm_boolean * p_exit); + +int khm_compare_version(const khm_version * v1, const khm_version * v2); + +#define MAX_RES_STRING 1024 + +#define ELLIPSIS L"..." + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/appver.rc b/krb5-1-6/src/windows/identity/ui/appver.rc new file mode 100644 index 000000000..324ad5231 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/appver.rc @@ -0,0 +1,40 @@ + +#include<windows.h> +#include<netidmgr_intver.h> + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION KH_VERSION_LIST + PRODUCTVERSION KH_VERSION_LIST + FILEFLAGSMASK 0x17L + FILEFLAGS KH_VER_FILEFLAGS + FILEOS KH_VER_FILEOS + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", KH_VERSTR_COMPANY_1033 + VALUE "FileDescription", "Network Identity Manager" + VALUE "FileVersion", KH_VERSTR_VERSION_1033 + VALUE "InternalName", "NetIDMgr" + VALUE "LegalCopyright", KH_VERSTR_COPYRIGHT_1033 + VALUE "OriginalFilename", "netidmgr.exe" + VALUE "ProductName", "Network Identity Manager" + VALUE "ProductVersion", KH_VERSTR_PRODUCT_1033 +#ifdef KH_VERSTR_COMMENT_1033 + VALUE "Comment", KH_VERSTR_COMMENT_1033 +#endif + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/krb5-1-6/src/windows/identity/ui/cfg_appear_wnd.c b/krb5-1-6/src/windows/identity/ui/cfg_appear_wnd.c new file mode 100644 index 000000000..93f72857c --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/cfg_appear_wnd.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +static int text_sizes[] = { + 4,6,8,9,10,12,14,16,18 +}; + +typedef struct tag_dlg_data { + khui_config_node node; + HWND hwnd; + LOGFONT lf_base; + LOGFONT lf_work; + HFONT c_font_normal; + HFONT c_font_bold; + int size_idx[ARRAYLENGTH(text_sizes)]; +} dlg_data; + +static void +read_params(HWND hwnd, dlg_data * d) { + + HDC hdc; + + hdc = GetWindowDC(hwnd); + + khm_get_cw_element_font(hdc, + NULL, + FALSE, + &d->lf_base); + + d->lf_work = d->lf_base; + + ReleaseDC(hwnd, hdc); +} + + +static void +write_params(dlg_data * d) { + khm_boolean applied = FALSE; + + if (memcmp(&d->lf_work, &d->lf_base, sizeof(LOGFONT))) { + khm_set_cw_element_font(NULL, &d->lf_work); + d->lf_base = d->lf_work; + applied = TRUE; + } + + khui_cfg_set_flags(d->node, + (applied)? KHUI_CNFLAG_APPLIED: 0, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +static void +check_for_modification(dlg_data * d) { + + khui_cfg_set_flags(d->node, + ((memcmp(&d->lf_work, &d->lf_base, sizeof(LOGFONT)))? + KHUI_CNFLAG_MODIFIED: 0), + KHUI_CNFLAG_MODIFIED); +} + +static void +refresh_view(HWND hwnd, dlg_data * d) { + wchar_t sample[256]; + HFONT hf; + LOGFONT lf; + + LoadString(khm_hInstance, IDS_APR_SAMPLE_TEXT_NORMAL, + sample, ARRAYLENGTH(sample)); + + SetDlgItemText(hwnd, IDC_CFG_SAMPLE_NORMAL, sample); + + LoadString(khm_hInstance, IDS_APR_SAMPLE_TEXT_SEL, + sample, ARRAYLENGTH(sample)); + + SetDlgItemText(hwnd, IDC_CFG_SAMPLE_BOLD, sample); + + lf = d->lf_work; + hf = CreateFontIndirect(&lf); + if (hf == NULL) + return; + + SendDlgItemMessage(hwnd, IDC_CFG_SAMPLE_NORMAL, WM_SETFONT, (WPARAM) hf, TRUE); + + if (d->c_font_normal) + DeleteObject(d->c_font_normal); + + d->c_font_normal = hf; + + lf.lfWeight = FW_BOLD; + + hf = CreateFontIndirect(&lf); + if (hf == NULL) + return; + + SendDlgItemMessage(hwnd, IDC_CFG_SAMPLE_BOLD, WM_SETFONT, (WPARAM) hf, TRUE); + + if (d->c_font_bold) + DeleteObject(d->c_font_bold); + + d->c_font_bold = hf; +} + +struct sel_update_blob { + dlg_data * d; + HDC hdc; +}; + +static int CALLBACK +enum_font_proc(ENUMLOGFONTEXDV * plfe, + ENUMTEXTMETRIC * pntm, + DWORD font_type, + LPARAM lParam) { + struct sel_update_blob * blob = (struct sel_update_blob *) lParam; + LOGFONT * plf = &plfe->elfEnumLogfontEx.elfLogFont; + LRESULT lr; + + lr = SendDlgItemMessage(blob->d->hwnd, + IDC_CFG_FONTS, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) plf->lfFaceName); + + if (lr == CB_ERR) { + SendDlgItemMessage(blob->d->hwnd, + IDC_CFG_FONTS, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) plfe->elfEnumLogfontEx.elfFullName); + } + + return FALSE; +} + +static void +update_selection(dlg_data * d, BOOL update_fonts, BOOL update_effects) { + LOGFONT lf; + struct sel_update_blob blob; + HDC hdc; + + if (update_fonts) { + + ZeroMemory(&lf, sizeof(lf)); + + lf.lfCharSet = ANSI_CHARSET; + StringCbCopy(lf.lfFaceName, sizeof(lf.lfFaceName), + d->lf_work.lfFaceName); + + hdc = GetWindowDC(d->hwnd); + + blob.d = d; + blob.hdc = hdc; + + EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) enum_font_proc, + (LPARAM) &blob, 0); + + ReleaseDC(d->hwnd, hdc); + } + + if (update_effects) { + int i; + HDC hdc; + int pt_height; + + if (d->lf_work.lfWeight >= FW_BOLD) + CheckDlgButton(d->hwnd, IDC_CFG_BOLD, BST_CHECKED); + else + CheckDlgButton(d->hwnd, IDC_CFG_BOLD, BST_UNCHECKED); + + if (d->lf_work.lfItalic) + CheckDlgButton(d->hwnd, IDC_CFG_ITALICS, BST_CHECKED); + else + CheckDlgButton(d->hwnd, IDC_CFG_ITALICS, BST_UNCHECKED); + + hdc = GetWindowDC(d->hwnd); + + pt_height = MulDiv(d->lf_work.lfHeight, 72, + GetDeviceCaps(hdc, LOGPIXELSY)); + + + ReleaseDC(d->hwnd, hdc); + + if (pt_height < 0) + pt_height = - pt_height; + + for (i=0; i < ARRAYLENGTH(text_sizes); i++) { + if (text_sizes[i] >= pt_height) + break; + } + + if (i >= ARRAYLENGTH(text_sizes)) + i = ARRAYLENGTH(text_sizes) - 1; + + SendDlgItemMessage(d->hwnd, IDC_CFG_SIZE, CB_SETCURSEL, + d->size_idx[i], 0); + } +} + +static int CALLBACK +enum_font_families_proc(ENUMLOGFONTEXDV * plfe, + ENUMTEXTMETRIC * pntm, + DWORD font_type, + LPARAM lParam) { + + dlg_data * d = (dlg_data *) lParam; + + SendDlgItemMessage(d->hwnd, IDC_CFG_FONTS, + CB_ADDSTRING, 0, + (LPARAM) plfe->elfEnumLogfontEx.elfLogFont.lfFaceName); + + return TRUE; +} + +INT_PTR CALLBACK +khm_cfg_appearance_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + { + HWND hw_cb; + LOGFONT lf; + HDC hdc; + int i; + wchar_t buf[4]; + + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d != NULL); +#endif + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + ZeroMemory(d, sizeof(*d)); + + d->node = (khui_config_node) lParam; + d->hwnd = hwnd; + + read_params(hwnd, d); + + hw_cb = GetDlgItem(hwnd, IDC_CFG_FONTS); +#ifdef DEBUG + assert(hw_cb); +#endif + SendMessage(hw_cb, CB_RESETCONTENT, 0, 0); + + ZeroMemory(&lf, sizeof(lf)); + lf.lfCharSet = ANSI_CHARSET; + + hdc = GetWindowDC(hwnd); + + EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) enum_font_families_proc, + (LPARAM) d, 0); + + ReleaseDC(hwnd, hdc); + + + for (i=0; i < ARRAYLENGTH(text_sizes); i++) { + LRESULT idx; + + StringCbPrintf(buf, sizeof(buf), L"%d", text_sizes[i]); + + idx = SendDlgItemMessage(hwnd, IDC_CFG_SIZE, + CB_ADDSTRING, 0, (LPARAM) buf); + + SendDlgItemMessage(hwnd, IDC_CFG_SIZE, + CB_SETITEMDATA, idx, text_sizes[i]); + + d->size_idx[i] = (int) idx; + } + + update_selection(d, TRUE, TRUE); + + refresh_view(hwnd, d); + } + return FALSE; + + case WM_COMMAND: + d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + if (wParam == MAKEWPARAM(IDC_CFG_FONTS, CBN_SELCHANGE)) { + LRESULT idx; + wchar_t facename[LF_FACESIZE]; + + idx = SendDlgItemMessage(hwnd, IDC_CFG_FONTS, + CB_GETCURSEL, + 0, 0); + + if (idx == CB_ERR) + return TRUE; + + if (SendDlgItemMessage(hwnd, IDC_CFG_FONTS, + CB_GETLBTEXTLEN, idx, 0) + >= ARRAYLENGTH(facename)) + return TRUE; + + SendDlgItemMessage(hwnd, IDC_CFG_FONTS, + CB_GETLBTEXT, idx, + (LPARAM) facename); + + ZeroMemory(d->lf_work.lfFaceName, + sizeof(d->lf_work.lfFaceName)); + + StringCbCopy(d->lf_work.lfFaceName, + sizeof(d->lf_work.lfFaceName), + facename); + + update_selection(d, FALSE, FALSE); + + refresh_view(hwnd, d); + + check_for_modification(d); + + } else if (wParam == MAKEWPARAM(IDC_CFG_BOLD, BN_CLICKED)) { + + if (IsDlgButtonChecked(hwnd, IDC_CFG_BOLD) == BST_CHECKED) { + d->lf_work.lfWeight = FW_BOLD; + } else { + d->lf_work.lfWeight = 0; + } + + refresh_view(hwnd, d); + + check_for_modification(d); + + } else if (wParam == MAKEWPARAM(IDC_CFG_ITALICS, BN_CLICKED)) { + + d->lf_work.lfItalic = (BYTE) + (IsDlgButtonChecked(hwnd, IDC_CFG_ITALICS) == BST_CHECKED); + + refresh_view(hwnd, d); + + check_for_modification(d); + + } else if (wParam == MAKEWPARAM(IDC_CFG_REVERT, BN_CLICKED)) { + HDC hdc; + + hdc = GetWindowDC(hwnd); + + khm_get_cw_element_font(hdc, NULL, TRUE, &d->lf_work); + + ReleaseDC(hwnd, hdc); + + update_selection(d, TRUE, TRUE); + + refresh_view(hwnd, d); + + check_for_modification(d); + + } else if (wParam == MAKEWPARAM(IDC_CFG_SIZE, CBN_SELCHANGE)) { + HDC hdc; + LPARAM idx; + int points; + + idx = SendDlgItemMessage(hwnd, IDC_CFG_SIZE, + CB_GETCURSEL, 0, 0); + if (idx == CB_ERR) + return TRUE; + + points = (int) SendDlgItemMessage(hwnd, IDC_CFG_SIZE, + CB_GETITEMDATA, idx, 0); + + hdc = GetWindowDC(hwnd); + + d->lf_work.lfHeight = -MulDiv(points, + GetDeviceCaps(hdc, LOGPIXELSY), + 72); + + ReleaseDC(hwnd, hdc); + + refresh_view(hwnd, d); + + check_for_modification(d); + } + + return TRUE; + + case WM_DESTROY: + d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + if (d) { + if (d->c_font_bold) + DeleteObject(d->c_font_bold); + + if (d->c_font_normal) + DeleteObject(d->c_font_normal); + + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + } + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + d = (dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + if (HIWORD(wParam) == WMCFG_APPLY) { + write_params(d); + khui_action_trigger(KHUI_ACTION_LAYOUT_RELOAD, NULL); + } + + return TRUE; + } + + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/ui/cfg_general_wnd.c b/krb5-1-6/src/windows/identity/ui/cfg_general_wnd.c new file mode 100644 index 000000000..f4dfa7712 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/cfg_general_wnd.c @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<shlwapi.h> +#include<khmapp.h> +#include<assert.h> + +typedef struct tag_cfg_data { + BOOL auto_init; + BOOL auto_start; + BOOL auto_import; + BOOL keep_running; + BOOL auto_detect_net; + BOOL log_to_file; + BOOL destroy_creds; + khm_int32 notif_action; +} cfg_data; + +typedef struct tag_dlg_data { + khui_config_node node; + cfg_data saved; + cfg_data work; +} dlg_data; + +static void +read_params(dlg_data * dd) { + cfg_data * d; + khm_handle csp_cw; + khm_int32 t; + + d = &dd->saved; + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, + &csp_cw))) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + khc_read_int32(csp_cw, L"AutoInit", &t); + d->auto_init = !!t; + + khc_read_int32(csp_cw, L"AutoStart", &t); + d->auto_start = !!t; + + khc_read_int32(csp_cw, L"AutoImport", &t); + d->auto_import = !!t; + + khc_read_int32(csp_cw, L"KeepRunning", &t); + d->keep_running = !!t; + + khc_read_int32(csp_cw, L"AutoDetectNet", &t); + d->auto_detect_net = !!t; + + khc_read_int32(csp_cw, L"LogToFile", &t); + d->log_to_file = !!t; + + khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t); + d->destroy_creds = !!t; + + khc_read_int32(csp_cw, L"NotificationAction", &t); + d->notif_action = t; + + khc_close_space(csp_cw); + + dd->work = *d; +} + +static void +write_params(dlg_data * dd) { + cfg_data * d, * s; + khm_handle csp_cw; + BOOL applied = FALSE; + + d = &dd->work; + s = &dd->saved; + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, + &csp_cw))) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + if (!!d->auto_init != !!s->auto_init) { + khc_write_int32(csp_cw, L"AutoInit", d->auto_init); + applied = TRUE; + } + + if (!!d->auto_start != !!s->auto_start) { + khc_write_int32(csp_cw, L"AutoStart", d->auto_start); + applied = TRUE; + } + + if (!!d->auto_import != !!s->auto_import) { + khc_write_int32(csp_cw, L"AutoImport", d->auto_import); + applied = TRUE; + } + + if (!!d->keep_running != !!s->keep_running) { + khc_write_int32(csp_cw, L"KeepRunning", d->keep_running); + applied = TRUE; + } + + if (!!d->auto_detect_net != !!s->auto_detect_net) { + khc_write_int32(csp_cw, L"AutoDetectNet", d->auto_detect_net); + applied = TRUE; + } + + if (!!d->log_to_file != !!s->log_to_file) { + khc_write_int32(csp_cw, L"LogToFile", d->log_to_file); + applied = TRUE; + + if (d->log_to_file) { + khm_start_file_log(); + } else { + khm_stop_file_log(); + } + } + + if (!!d->destroy_creds != !!s->destroy_creds) { + khc_write_int32(csp_cw, L"DestroyCredsOnExit", d->destroy_creds); + applied = TRUE; + } + + if (d->notif_action != s->notif_action) { + khc_write_int32(csp_cw, L"NotificationAction", d->notif_action); + applied = TRUE; + } + + khc_close_space(csp_cw); + + khui_cfg_set_flags(dd->node, + (applied) ? KHUI_CNFLAG_APPLIED : 0, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); + + *s = *d; +} + +static void +check_for_modification(dlg_data * dd) { + cfg_data * d, * s; + d = &dd->work; + s = &dd->saved; + + if (!!d->auto_init != !!s->auto_init || + !!d->auto_start != !!s->auto_start || + !!d->auto_import != !!s->auto_import || + !!d->keep_running != !!s->keep_running || + !!d->auto_detect_net != !!s->auto_detect_net || + !!d->log_to_file != !!s->log_to_file || + !!d->destroy_creds != !!s->destroy_creds || + d->notif_action != s->notif_action) { + + khui_cfg_set_flags(dd->node, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + + } else { + + khui_cfg_set_flags(dd->node, + 0, + KHUI_CNFLAG_MODIFIED); + + } +} + + +static void +strip_ampersands(wchar_t * str) { + wchar_t *f, *t; + + for(f = t = str; *f; f++) + if (*f != L'&') + *t++ = *f; + + *t = L'\0'; +} + +static void +refresh_view(HWND hwnd, dlg_data * d) { + wchar_t buf[512]; + khm_size i; + + CheckDlgButton(hwnd, IDC_CFG_AUTOINIT, + (d->work.auto_init?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_AUTOSTART, + (d->work.auto_start?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_AUTOIMPORT, + (d->work.auto_import?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_KEEPRUNNING, + (d->work.keep_running?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_NETDETECT, + (d->work.auto_detect_net?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_LOGTOFILE, + (d->work.log_to_file?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_DESTROYALL, + (d->work.destroy_creds?BST_CHECKED:BST_UNCHECKED)); + + /* we need populate the notification action combo box control and + set the current selection to match the default action. */ + + if (n_khm_notifier_actions != (khm_size) SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, + CB_GETCOUNT, 0, 0)) { + + for (i=0; i < n_khm_notifier_actions; i++) { + int idx; + + khm_get_action_caption(khm_notifier_actions[i], + buf, sizeof(buf)); + + strip_ampersands(buf); + + idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, + CB_INSERTSTRING, i, + (LPARAM) buf); + +#ifdef DEBUG + if (idx != (int) i) { + assert(FALSE); + } +#endif + } + } + + for (i=0; i < n_khm_notifier_actions; i++) { + if (khm_notifier_actions[i] == d->work.notif_action) + break; + } + + if (i >= n_khm_notifier_actions) { + d->work.notif_action = khm_notifier_actions[0]; + i = 0; + } + + SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, CB_SETCURSEL, i, 0); + + /* in addition, we correct the label on the trace log control to + reflect the actual path that is going to get used */ + if (GetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf, + ARRAYLENGTH(buf)) == 0) { + + khm_get_file_log_path(sizeof(buf), buf); + + SetDlgItemText(hwnd, IDC_CFG_LOGPATH, buf); + } +} + +static void +refresh_data(HWND hwnd, dlg_data * d) { + int idx; + + d->work.auto_init = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOINIT) + == BST_CHECKED); + d->work.auto_start = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOSTART) + == BST_CHECKED); + d->work.auto_import = (IsDlgButtonChecked(hwnd, IDC_CFG_AUTOIMPORT) + == BST_CHECKED); + d->work.keep_running = (IsDlgButtonChecked(hwnd, IDC_CFG_KEEPRUNNING) + == BST_CHECKED); + d->work.auto_detect_net = (IsDlgButtonChecked(hwnd, IDC_CFG_NETDETECT) + == BST_CHECKED); + d->work.log_to_file = (IsDlgButtonChecked(hwnd, IDC_CFG_LOGTOFILE) + == BST_CHECKED); + d->work.destroy_creds = (IsDlgButtonChecked(hwnd, IDC_CFG_DESTROYALL) + == BST_CHECKED); + + idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_NOTACTION, CB_GETCURSEL, 0, 0); + if (idx < 0) + idx = 0; + else if (idx >= (int) n_khm_notifier_actions) + idx = (int) n_khm_notifier_actions - 1; + + d->work.notif_action = khm_notifier_actions[idx]; +} + +INT_PTR CALLBACK +khm_cfg_general_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d != NULL); +#endif + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + ZeroMemory(d, sizeof(*d)); + + d->node = (khui_config_node) lParam; + + read_params(d); + + refresh_view(hwnd, d); + + return FALSE; + + case WM_DESTROY: + d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d) { + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + } + return TRUE; + + case WM_COMMAND: + d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + if (HIWORD(wParam) == BN_CLICKED) { + if (LOWORD(wParam) == IDC_CFG_SHOWLOG) { + /* we need to display the logfile */ + wchar_t buf[512]; + + buf[0] = L'\0'; + khm_get_file_log_path(sizeof(buf), buf); + + if (!buf[0] || + !PathFileExists(buf)) { + + wchar_t title[256]; + wchar_t msg[550]; + wchar_t fmt[256]; + + LoadString(khm_hInstance, IDS_CFG_LOGF_CS, + title, ARRAYLENGTH(title)); + LoadString(khm_hInstance, IDS_CFG_LOGF_CSR, + fmt, ARRAYLENGTH(fmt)); + + StringCbPrintf(msg, sizeof(msg), fmt, buf); + + MessageBox(hwnd, title, msg, MB_OK); + + } else { + wchar_t cmdline[550]; + STARTUPINFO si; + PROCESS_INFORMATION pi; + + StringCbCopy(cmdline, sizeof(cmdline), L"notepad.exe "); + StringCbCat(cmdline, sizeof(cmdline), L"\""); + StringCbCat(cmdline, sizeof(cmdline), buf); + StringCbCat(cmdline, sizeof(cmdline), L"\""); + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + CreateProcess(NULL, + cmdline, + NULL, NULL, + FALSE, + 0, NULL, NULL, + &si, + &pi); + + if (pi.hProcess) + CloseHandle(pi.hProcess); + if (pi.hThread) + CloseHandle(pi.hThread); + + } + } else { + refresh_data(hwnd, d); + check_for_modification(d); + } + } else if (HIWORD(wParam) == CBN_SELCHANGE) { + refresh_data(hwnd, d); + check_for_modification(d); + } + + khm_set_dialog_result(hwnd, 0); + + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + d = (dlg_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + if (HIWORD(wParam) == WMCFG_APPLY) { + write_params(d); + } + + khm_set_dialog_result(hwnd, 0); + + return TRUE; + } + + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/ui/cfg_identities_wnd.c b/krb5-1-6/src/windows/identity/ui/cfg_identities_wnd.c new file mode 100644 index 000000000..02eb44212 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/cfg_identities_wnd.c @@ -0,0 +1,1573 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> +#if _WIN32_WINNT >= 0x0501 +#include<uxtheme.h> +#endif + +static khui_config_node +get_window_node(HWND hwnd) { + return (khui_config_node) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); +} + +static void +set_window_node(HWND hwnd, khui_config_node node) { +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, + (LONG_PTR) node); +#pragma warning(pop) +} + +static void +add_subpanels(HWND hwnd, + khui_config_node ctx_node, + khui_config_node ref_node) { + + HWND hw_tab; + HWND hw_target; + khui_config_node sub; + khui_config_node_reg reg; + khui_config_init_data idata; + int idx; + + hw_tab = GetDlgItem(hwnd, IDC_CFG_TAB); + hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET); +#ifdef DEBUG + assert(hw_tab); + assert(hw_target); +#endif + + if (KHM_FAILED(khui_cfg_get_first_subpanel(ref_node, &sub))) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + idx = 0; + while(sub) { + HWND hwnd_panel; + TCITEM tci; + int iid; + + khui_cfg_get_reg(sub, &reg); + + if ((ctx_node == ref_node && (reg.flags & KHUI_CNFLAG_PLURAL)) || + (ctx_node != ref_node && !(reg.flags & KHUI_CNFLAG_PLURAL))) + goto _next_node; + + idata.ctx_node = ctx_node; + idata.this_node = sub; + idata.ref_node = ref_node; + + hwnd_panel = CreateDialogParam(reg.h_module, + reg.dlg_template, + hwnd, + reg.dlg_proc, + (LPARAM) &idata); + +#ifdef DEBUG + assert(hwnd_panel); +#endif +#if _WIN32_WINNT >= 0x0501 + EnableThemeDialogTexture(hwnd_panel, ETDT_ENABLETAB); +#endif + + ShowWindow(hwnd_panel, SW_HIDE); + + ZeroMemory(&tci, sizeof(tci)); + + tci.mask = TCIF_PARAM | TCIF_TEXT; + tci.lParam = (LPARAM) sub; + tci.pszText = (LPWSTR) reg.short_desc; + + iid = TabCtrl_InsertItem(hw_tab, 0, &tci); + idx++; + + if (reg.flags & KHUI_CNFLAG_PLURAL) { + khui_cfg_set_param_inst(sub, ctx_node, iid); + khui_cfg_set_hwnd_inst(sub, ctx_node, hwnd_panel); + } else { + khui_cfg_set_param(sub, iid); + khui_cfg_set_hwnd(sub, hwnd_panel); + } + + _next_node: + + khui_cfg_get_next_release(&sub); + } + + TabCtrl_SetCurSel(hw_tab, 0); +} + +static void +apply_all(HWND hwnd, + HWND hw_tab, + khui_config_node noderef) { + TCITEM tci; + HWND hw; + khui_config_node_reg reg; + int idx; + int count; + BOOL cont = TRUE; + + count = TabCtrl_GetItemCount(hw_tab); + + for (idx = 0; idx < count && cont; idx++) { + + ZeroMemory(&tci, sizeof(tci)); + + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(hw_tab, + idx, + &tci); + +#ifdef DEBUG + assert(tci.lParam); +#endif + khui_cfg_get_reg((khui_config_node) tci.lParam, &reg); + if (reg.flags & KHUI_CNFLAG_PLURAL) + hw = khui_cfg_get_hwnd_inst((khui_config_node) tci.lParam, + noderef); + else + hw = khui_cfg_get_hwnd((khui_config_node) tci.lParam); +#ifdef DEBUG + assert(hw); +#endif + + SendMessage(hw, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(0, WMCFG_APPLY), (LPARAM) &cont); + } +} + +static void +show_tab_panel(HWND hwnd, + khui_config_node node, + HWND hw_tab, + int idx, + BOOL show) { + TCITEM tci; + HWND hw; + HWND hw_target; + HWND hw_firstctl; + RECT r; + RECT rref; + khui_config_node_reg reg; + + ZeroMemory(&tci, sizeof(tci)); + + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(hw_tab, + idx, + &tci); + +#ifdef DEBUG + assert(tci.lParam); +#endif + khui_cfg_get_reg((khui_config_node) tci.lParam, &reg); + if (reg.flags & KHUI_CNFLAG_PLURAL) + hw = khui_cfg_get_hwnd_inst((khui_config_node) tci.lParam, + node); + else + hw = khui_cfg_get_hwnd((khui_config_node) tci.lParam); +#ifdef DEBUG + assert(hw); +#endif + + if (!show) { + ShowWindow(hw, SW_HIDE); + return; + } + + hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET); +#ifdef DEBUG + assert(hw_target); +#endif + GetWindowRect(hwnd, &rref); + GetWindowRect(hw_target, &r); + + OffsetRect(&r, -rref.left, -rref.top); + + SetWindowPos(hw, + hw_tab, + r.left, r.top, + r.right - r.left, r.bottom - r.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_SHOWWINDOW); + + hw_firstctl = GetNextDlgTabItem(hw, NULL, FALSE); + if (hw_firstctl) { + SetFocus(hw_firstctl); + } +} + +static INT_PTR +handle_cfg_notify(HWND hwnd, + WPARAM wParam, + LPARAM lParam) { + khui_config_node node; + HWND hw; + + node = get_window_node(hwnd); + if (node == NULL) + return TRUE; + + if (HIWORD(wParam) == WMCFG_APPLY) { + + hw = GetDlgItem(hwnd, IDC_CFG_TAB); + + apply_all(hwnd, + hw, + node); + } + + return TRUE; +} + +static INT_PTR +handle_notify(HWND hwnd, + WPARAM wParam, + LPARAM lParam) { + LPNMHDR lpnm; + int i; + + + khui_config_node node; + + lpnm = (LPNMHDR) lParam; + node = get_window_node(hwnd); + if (node == NULL) + return FALSE; + + if (lpnm->idFrom == IDC_CFG_TAB) { + switch(lpnm->code) { + case TCN_SELCHANGING: + i = TabCtrl_GetCurSel(lpnm->hwndFrom); + + show_tab_panel(hwnd, + node, + lpnm->hwndFrom, + i, + FALSE); + break; + + case TCN_SELCHANGE: + i = TabCtrl_GetCurSel(lpnm->hwndFrom); + + show_tab_panel(hwnd, + node, + lpnm->hwndFrom, + i, + TRUE); + break; + } + return TRUE; + } else { + return FALSE; + } +} + +typedef struct tag_ident_props { + BOOL monitor; + BOOL auto_renew; + BOOL sticky; +} ident_props; + +typedef struct tag_ident_data { + khm_handle ident; + wchar_t * idname; + int lv_idx; + + BOOL removed; /* this identity was marked for removal */ + BOOL applied; + BOOL purged; /* this identity was actually removed */ + + khm_int32 flags; + + ident_props saved; + ident_props work; + + HWND hwnd; +} ident_data; + +typedef struct tag_global_props { + BOOL monitor; + BOOL auto_renew; + BOOL sticky; +} global_props; + +typedef struct tag_idents_data { + BOOL valid; + + ident_data * idents; + khm_size n_idents; + khm_size nc_idents; +#define IDENTS_DATA_ALLOC_INCR 8 + + /* global options */ + global_props saved; + global_props work; + BOOL applied; + + int refcount; + + HIMAGELIST hi_status; + int idx_id; + int idx_default; + int idx_modified; + int idx_applied; + int idx_deleted; + + HWND hwnd; + khui_config_init_data cfg; +} idents_data; + +static idents_data cfg_idents = {FALSE, NULL, 0, 0, + {0, 0, 0}, + {0, 0, 0}, + FALSE, + + 0, NULL }; + +static void +read_params_ident(ident_data * d) { + khm_handle csp_ident; + khm_handle csp_cw; + khm_int32 t; + + if (KHM_FAILED(kcdb_identity_get_config(d->ident, + KHM_PERM_READ, + &csp_ident))) { + csp_ident = NULL; + } + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, + &csp_cw))) { + if (csp_ident) { + khc_shadow_space(csp_ident, + csp_cw); + khc_close_space(csp_cw); + } else { + csp_ident = csp_cw; + } + csp_cw = NULL; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + d->saved.monitor = TRUE; + d->saved.auto_renew = TRUE; + d->saved.sticky = FALSE; + d->work = d->saved; + + if (csp_ident) + khc_close_space(csp_ident); + + return; + } + + if (KHM_FAILED(khc_read_int32(csp_ident, L"Monitor", &t))) { +#ifdef DEBUG + assert(FALSE); +#endif + d->saved.monitor = TRUE; + } else { + d->saved.monitor = !!t; + } + + if (KHM_FAILED(khc_read_int32(csp_ident, L"AllowAutoRenew", &t))) { +#ifdef DEBUG + assert(FALSE); +#endif + d->saved.auto_renew = TRUE; + } else { + d->saved.auto_renew = !!t; + } + + if (KHM_FAILED(khc_read_int32(csp_ident, L"Sticky", &t))) { + d->saved.sticky = FALSE; + } else { + d->saved.sticky = !!t; + } + + khc_close_space(csp_ident); + + d->work = d->saved; + d->applied = FALSE; +} + +static void +write_params_ident(ident_data * d) { + khm_handle csp_ident; + + if (d->saved.monitor == d->work.monitor && + d->saved.auto_renew == d->work.auto_renew && + d->saved.sticky == d->work.sticky && + !d->removed) + return; + + if (KHM_FAILED(kcdb_identity_get_config(d->ident, KHM_PERM_WRITE, + &csp_ident))) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + if (d->removed) { + khm_handle h = NULL; + khm_int32 flags = 0; + + khc_remove_space(csp_ident); + + /* calling kcdb_identity_get_config() will update the + KCDB_IDENT_FLAG_CONFIG flag for the identity to reflect the + fact that it nolonger has a configuration. */ + kcdb_identity_get_config(d->ident, 0, &h); + if (h) { + /* what the ? */ +#ifdef DEBUG + assert(FALSE); +#endif + khc_close_space(h); + } +#ifdef DEBUG + kcdb_identity_get_flags(d->ident, &flags); + assert(!(flags & KCDB_IDENT_FLAG_CONFIG)); +#endif + + d->purged = TRUE; + + } else { + + if (d->saved.monitor != d->work.monitor) + khc_write_int32(csp_ident, L"Monitor", !!d->work.monitor); + + if (d->saved.auto_renew != d->work.auto_renew) + khc_write_int32(csp_ident, L"AllowAutoRenew", + !!d->work.auto_renew); + + if (d->saved.sticky != d->work.sticky) { + kcdb_identity_set_flags(d->ident, + (d->work.sticky)?KCDB_IDENT_FLAG_STICKY:0, + KCDB_IDENT_FLAG_STICKY); + } + } + + khc_close_space(csp_ident); + + d->saved = d->work; + + d->applied = TRUE; + + if (d->hwnd && !d->removed) + PostMessage(d->hwnd, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0); + + khm_refresh_config(); +} + +static void +write_params_idents(void) { + khm_handle csp_cw = NULL; + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", + KHM_FLAG_CREATE, &csp_cw))) { + if (cfg_idents.work.monitor != cfg_idents.saved.monitor) { + khc_write_int32(csp_cw, L"DefaultMonitor", + !!cfg_idents.work.monitor); + cfg_idents.saved.monitor = cfg_idents.work.monitor; + cfg_idents.applied = TRUE; + } + if (cfg_idents.work.auto_renew != cfg_idents.saved.auto_renew) { + khc_write_int32(csp_cw, L"DefaultAllowAutoRenew", + !!cfg_idents.work.auto_renew); + cfg_idents.saved.auto_renew = cfg_idents.work.auto_renew; + cfg_idents.applied = TRUE; + } + if (cfg_idents.work.sticky != cfg_idents.saved.sticky) { + khc_write_int32(csp_cw, L"DefaultSticky", + !!cfg_idents.work.sticky); + cfg_idents.saved.sticky = cfg_idents.work.sticky; + cfg_idents.applied = TRUE; + } + + khc_close_space(csp_cw); + csp_cw = NULL; + } + +#if 0 + for (i=0; i < (int)cfg_idents.n_idents; i++) { + write_params_ident(&cfg_idents.idents[i]); + } +#endif + + if (cfg_idents.hwnd) + PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0); +} + +static void +init_idents_data(void) { + khm_int32 rv; + wchar_t * t; + wchar_t * widnames = NULL; + khm_size cb; + int n_tries = 0; + int i; + khm_handle csp_cw = NULL; + + if (cfg_idents.valid) + return; + +#ifdef DEBUG + assert(cfg_idents.idents == NULL); + assert(cfg_idents.n_idents == 0); + assert(cfg_idents.nc_idents == 0); +#endif + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) { + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultMonitor", &t))) + cfg_idents.saved.monitor = !!t; + else + cfg_idents.saved.monitor = TRUE; + + if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultAllowAutoRenew", &t))) + cfg_idents.saved.auto_renew = !!t; + else + cfg_idents.saved.auto_renew = TRUE; + + if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultSticky", &t))) + cfg_idents.saved.sticky = !!t; + else + cfg_idents.saved.sticky = FALSE; + + khc_close_space(csp_cw); + csp_cw = NULL; + + } else { + + cfg_idents.saved.monitor = TRUE; + cfg_idents.saved.auto_renew = TRUE; + cfg_idents.saved.sticky = FALSE; + + } + + cfg_idents.work = cfg_idents.saved; + cfg_idents.applied = FALSE; + + do { + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + NULL, + &cb, + &cfg_idents.n_idents); + + if (rv != KHM_ERROR_TOO_LONG || + cfg_idents.n_idents == 0 || + cb == 0) + break; + + if (widnames) + PFREE(widnames); + widnames = PMALLOC(cb); +#ifdef DEBUG + assert(widnames); +#endif + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + widnames, + &cb, + &cfg_idents.n_idents); + n_tries++; + } while(KHM_FAILED(rv) && + n_tries < 5); + + if (KHM_FAILED(rv) || + cfg_idents.n_idents == 0) { + cfg_idents.n_idents = 0; + goto _cleanup; + } + + cfg_idents.idents = PMALLOC(sizeof(*cfg_idents.idents) * + cfg_idents.n_idents); +#ifdef DEBUG + assert(cfg_idents.idents); +#endif + ZeroMemory(cfg_idents.idents, + sizeof(*cfg_idents.idents) * cfg_idents.n_idents); + cfg_idents.nc_idents = cfg_idents.n_idents; + + i = 0; + for (t = widnames; t && *t; t = multi_string_next(t)) { + khm_handle ident; + + if (KHM_FAILED(kcdb_identity_create(t, 0, &ident))) { + cfg_idents.n_idents--; + continue; + } + + StringCbLength(t, KCDB_IDENT_MAXCB_NAME, &cb); + cb += sizeof(wchar_t); + + cfg_idents.idents[i].idname = PMALLOC(cb); +#ifdef DEBUG + assert(cfg_idents.idents[i].idname); +#endif + StringCbCopy(cfg_idents.idents[i].idname, cb, t); + + cfg_idents.idents[i].ident = ident; + cfg_idents.idents[i].removed = FALSE; + + kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags); +#ifdef DEBUG + assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG); +#endif + + read_params_ident(&cfg_idents.idents[i]); + + i++; + /* leave identity held */ + } + + _cleanup: + + cfg_idents.valid = TRUE; + + if (widnames) + PFREE(widnames); +} + +static void +free_idents_data(void) { + int i; + + if (!cfg_idents.valid) + return; + + for (i=0; i< (int) cfg_idents.n_idents; i++) { + if (cfg_idents.idents[i].ident) + kcdb_identity_release(cfg_idents.idents[i].ident); + if (cfg_idents.idents[i].idname) + PFREE(cfg_idents.idents[i].idname); + } + + if (cfg_idents.idents) + PFREE(cfg_idents.idents); + + cfg_idents.idents = NULL; + cfg_idents.n_idents = 0; + cfg_idents.nc_idents = 0; + cfg_idents.valid = FALSE; +} + +static void +hold_idents_data(void) { + if (!cfg_idents.valid) + init_idents_data(); +#ifdef DEBUG + assert(cfg_idents.valid); +#endif + cfg_idents.refcount++; +} + +static void +release_idents_data(void) { +#ifdef DEBUG + assert(cfg_idents.valid); +#endif + cfg_idents.refcount--; + + if (cfg_idents.refcount == 0) + free_idents_data(); +} + + +static void +refresh_data_idents(HWND hwnd) { + cfg_idents.work.monitor = + (IsDlgButtonChecked(hwnd, IDC_CFG_MONITOR) == BST_CHECKED); + cfg_idents.work.auto_renew = + (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED); + cfg_idents.work.sticky = + (IsDlgButtonChecked(hwnd, IDC_CFG_STICKY) == BST_CHECKED); +} + +static void +refresh_view_idents_state(HWND hwnd) { + BOOL modified; + BOOL applied; + khm_int32 flags = 0; + + applied = cfg_idents.applied; + modified = (cfg_idents.work.monitor != cfg_idents.saved.monitor || + cfg_idents.work.auto_renew != cfg_idents.saved.auto_renew || + cfg_idents.work.sticky != cfg_idents.saved.sticky); + + if (modified) + flags |= KHUI_CNFLAG_MODIFIED; + if (applied) + flags |= KHUI_CNFLAG_APPLIED; + + khui_cfg_set_flags_inst(&cfg_idents.cfg, flags, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +struct ctrl_row_dimensions { + RECT enclosure; + RECT label; + RECT control; +}; + +typedef struct tag_add_ident_data { + khui_new_creds * nc; + + struct ctrl_row_dimensions dim_small; + struct ctrl_row_dimensions dim_medium; + struct ctrl_row_dimensions dim_large; + int row_gap; + + int current_y; + int current_x; + + HWND hwnd_last_ctrl; +} add_ident_data; + +void +get_ctrl_row_metrics(struct ctrl_row_dimensions * dim, HWND hw_lbl, HWND hw_ctl) { + + assert(hw_lbl); + assert(hw_ctl); + + GetWindowRect(hw_lbl, &dim->label); + GetWindowRect(hw_ctl, &dim->control); + + UnionRect(&dim->enclosure, &dim->label, &dim->control); + OffsetRect(&dim->label, + -dim->enclosure.left, + -dim->enclosure.top); + OffsetRect(&dim->control, + -dim->enclosure.left, + -dim->enclosure.top); + OffsetRect(&dim->enclosure, + -dim->enclosure.left, + -dim->enclosure.top); +} + +/* dialog box procedure for the "Add new identity" dialog */ +INT_PTR CALLBACK +khm_cfg_add_ident_proc(HWND hwnd, + UINT umsg, + WPARAM wParam, + LPARAM lParam) { + add_ident_data * d; + + switch(umsg) { + case WM_INITDIALOG: + /* we create a new credentials blob and pull in the identity + selectors from the identity provider. */ + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + khui_cw_create_cred_blob(&d->nc); +#ifdef DEBUG + assert(d->nc != NULL); +#endif + if (d->nc == NULL) { + PFREE(d); + break; + } + + if (KHM_FAILED(kcdb_identpro_get_ui_cb(&d->nc->ident_cb))) { + /* this should have worked. The only reason it would fail + is if there is no identity provider or if the identity + provider does not support providing idnetity + selectors. */ + khui_cw_destroy_cred_blob(d->nc); + PFREE(d); + break; + } + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + /* get metrics for dynamic controls */ + get_ctrl_row_metrics(&d->dim_small, + GetDlgItem(hwnd, IDC_SM_LBL), + GetDlgItem(hwnd, IDC_SM_CTL)); + get_ctrl_row_metrics(&d->dim_medium, + GetDlgItem(hwnd, IDC_MED_LBL), + GetDlgItem(hwnd, IDC_MED_CTL)); + get_ctrl_row_metrics(&d->dim_large, + GetDlgItem(hwnd, IDC_LG_LBL), + GetDlgItem(hwnd, IDC_LG_CTL)); + + { + RECT rlbl; + RECT rctl; + RECT rwnd; + + GetWindowRect(GetDlgItem(hwnd, IDC_SM_LBL), + &rlbl); + GetWindowRect(GetDlgItem(hwnd, IDC_SM_CTL), + &rctl); + GetWindowRect(hwnd, &rwnd); + + OffsetRect(&rlbl, -rwnd.left, -rwnd.top); + OffsetRect(&rctl, -rwnd.left, -rwnd.top); + + d->current_x = rlbl.left; + d->current_y = rctl.top - GetSystemMetrics(SM_CYCAPTION); + + GetWindowRect(GetDlgItem(hwnd, IDC_MED_CTL), + &rlbl); + OffsetRect(&rlbl, -rwnd.left, -rwnd.top); + + d->row_gap = rlbl.top - rctl.bottom; + } + + d->nc->hwnd = hwnd; + + /* now call the UI callback and make it create the + controls. */ + d->nc->ident_cb(d->nc, WMNC_IDENT_INIT, NULL, 0, 0, + (LPARAM) hwnd); + + break; + + case WM_DESTROY: + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0); + + khui_cw_destroy_cred_blob(d->nc); + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + break; + + case KHUI_WM_NC_NOTIFY: + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + switch(HIWORD(wParam)) { + case WMNC_ADD_CONTROL_ROW: + { + khui_control_row * row; + RECT r_lbl, r_inp, r_enc; + struct ctrl_row_dimensions * dim; + HFONT hf; + + row = (khui_control_row *) lParam; + +#ifdef DEBUG + assert(row->label); + assert(row->input); + assert(d); +#endif + + if (row->size == KHUI_CTRLSIZE_SMALL) { + dim = &d->dim_small; + } else if (row->size == KHUI_CTRLSIZE_HALF) { + dim = &d->dim_medium; + } else { + dim = &d->dim_large; +#ifdef DEBUG + assert(row->size == KHUI_CTRLSIZE_FULL); +#endif + } + + CopyRect(&r_enc, &dim->enclosure); + CopyRect(&r_lbl, &dim->label); + CopyRect(&r_inp, &dim->control); + + OffsetRect(&r_enc, d->current_x, d->current_y); + OffsetRect(&r_lbl, r_enc.left, r_enc.top); + OffsetRect(&r_inp, r_enc.left, r_enc.top); + + d->current_y += r_enc.bottom - r_enc.top; + + hf = (HFONT) SendDlgItemMessage(hwnd, IDOK, WM_GETFONT, 0, 0); + + if (row->label) { + SetWindowPos(row->label, + ((d->hwnd_last_ctrl != NULL)? + d->hwnd_last_ctrl : + HWND_TOP), + r_lbl.left, r_lbl.top, + r_lbl.right - r_lbl.left, + r_lbl.bottom - r_lbl.top, + SWP_DEFERERASE | SWP_NOACTIVATE | + SWP_NOOWNERZORDER); + if (hf) + SendMessage(row->label, WM_SETFONT, + (WPARAM) hf, + TRUE); + d->hwnd_last_ctrl = row->label; + } + + if (row->input) { + SetWindowPos(row->input, + ((d->hwnd_last_ctrl != NULL)? + d->hwnd_last_ctrl : + HWND_TOP), + r_inp.left, r_inp.top, + r_inp.right - r_inp.left, + r_inp.bottom - r_inp.top, + SWP_DEFERERASE | SWP_NOACTIVATE | + SWP_NOOWNERZORDER); + if (hf) + SendMessage(row->input, WM_SETFONT, + (WPARAM) hf, + TRUE); + d->hwnd_last_ctrl = row->input; + } + } + break; + + case WMNC_IDENTITY_CHANGE: + break; + } + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t err_msg[1024]; + khm_handle ident = NULL; + khm_handle csp_ident = NULL; + khm_size cb; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_int32 flags = 0; + + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (!d || !d->nc) + break; + + if (d->nc->ident_cb) + d->nc->ident_cb(d->nc, WMNC_IDENT_PREPROCESS, NULL, 0, 0, 0); + + /* check if there was an identity selected */ + if (d->nc->n_identities == 0 || + d->nc->identities[0] == NULL) { + + StringCbCopy(idname, sizeof(idname), L""); + + LoadString(khm_hInstance, IDS_CFG_IDNAME_NON, + err_msg, ARRAYLENGTH(err_msg)); + + goto show_failure; + } + + ident = d->nc->identities[0]; + kcdb_identity_hold(ident); + + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + + /* check if the identity is already in the + configuration */ + if (KHM_SUCCEEDED(kcdb_identity_get_flags(ident, &flags)) && + (flags & KCDB_IDENT_FLAG_CONFIG)) { + + wchar_t fmt[256]; + + LoadString(khm_hInstance, IDS_CFG_IDNAME_EXT, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(err_msg, sizeof(err_msg), fmt, idname); + + kcdb_identity_release(ident); + ident = NULL; + + goto show_failure; + } + + /* now we have to create the identity configuration. */ + if (KHM_FAILED(rv = kcdb_identity_get_config(ident, + KHM_FLAG_CREATE, + &csp_ident))) { + wchar_t fmt[256]; + + LoadString(khm_hInstance, IDS_CFG_IDNAME_CCC, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(err_msg, sizeof(err_msg), fmt, rv); + + kcdb_identity_release(ident); + ident = NULL; + + goto show_failure; + } + + /* create a value so that the configuration space will + actually be created in the registry. We don't want + this new identity to be sticky. */ + khc_write_int32(csp_ident, L"Sticky", 0); + + khm_refresh_config(); + + kcdb_identity_release(ident); + khc_close_space(csp_ident); + + EndDialog(hwnd, 0); + break; + + show_failure: + { + wchar_t title[512]; + wchar_t fmt[256]; + + if (!err_msg[0]) + break; + + LoadString(khm_hInstance, IDS_CFG_IDNAME_PRB, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(title, sizeof(title), fmt, idname); + + MessageBox(hwnd, err_msg, title, MB_OK | MB_ICONSTOP); + + /* don't end the dialog yet */ + break; + } + break; + + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hwnd, 1); + } else { + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d && d->nc && d->nc->ident_cb) { + return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, + hwnd, umsg, wParam, lParam); + } + } + break; + } + + return FALSE; +} + +/* dialog procedure for the "general" pane of the "identities" + configuration node. */ +INT_PTR CALLBACK +khm_cfg_ids_tab_proc(HWND hwnd, + UINT umsg, + WPARAM wParam, + LPARAM lParam) { + + switch(umsg) { + case WM_INITDIALOG: + { + HICON hicon; + + hold_idents_data(); + + cfg_idents.hwnd = hwnd; + cfg_idents.cfg = *((khui_config_init_data *) lParam); + + /* add the status icons */ + if (cfg_idents.hi_status) + goto _done_with_icons; + + cfg_idents.hi_status = + ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLOR8 | ILC_MASK, + 4,4); + + hicon = + LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_ID), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + cfg_idents.idx_id = ImageList_AddIcon(cfg_idents.hi_status, + hicon); + + DestroyIcon(hicon); + + hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DEFAULT), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + cfg_idents.idx_default = ImageList_AddIcon(cfg_idents.hi_status, + hicon) + 1; + + DestroyIcon(hicon); + + hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_MODIFIED), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + cfg_idents.idx_modified = ImageList_AddIcon(cfg_idents.hi_status, + hicon) + 1; + + DestroyIcon(hicon); + + hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_APPLIED), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + cfg_idents.idx_applied = ImageList_AddIcon(cfg_idents.hi_status, + hicon) + 1; + + DestroyIcon(hicon); + + hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DELETED), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + cfg_idents.idx_deleted = ImageList_AddIcon(cfg_idents.hi_status, + hicon) + 1; + + DestroyIcon(hicon); + + _done_with_icons: + + CheckDlgButton(hwnd, IDC_CFG_MONITOR, + (cfg_idents.work.monitor)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CFG_RENEW, + (cfg_idents.work.auto_renew)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CFG_STICKY, + (cfg_idents.work.sticky)?BST_CHECKED:BST_UNCHECKED); + + } + return FALSE; + + case WM_COMMAND: + + if (HIWORD(wParam) == BN_CLICKED) { + UINT ctrl = LOWORD(wParam); + + switch(ctrl) { + case IDC_CFG_MONITOR: + case IDC_CFG_RENEW: + case IDC_CFG_STICKY: + refresh_data_idents(hwnd); + break; + + case IDC_CFG_ADDIDENT: + DialogBoxParam(khm_hInstance, + MAKEINTRESOURCE(IDD_CFG_ADDIDENT), + hwnd, + khm_cfg_add_ident_proc, + (LPARAM) hwnd); + break; + } + + refresh_view_idents_state(hwnd); + } + + khm_set_dialog_result(hwnd, 0); + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + { + switch(HIWORD(wParam)) { + case WMCFG_APPLY: + write_params_idents(); + break; + + case WMCFG_UPDATE_STATE: + refresh_view_idents_state(hwnd); + break; + } + } + return TRUE; + + case WM_DESTROY: + cfg_idents.hwnd = NULL; + + if (cfg_idents.hi_status != NULL) { + ImageList_Destroy(cfg_idents.hi_status); + cfg_idents.hi_status = NULL; + } + release_idents_data(); + + khm_set_dialog_result(hwnd, 0); + + return TRUE; + } + + return FALSE; +} + +/* dialog procedure for the "Identities" configuration node */ +INT_PTR CALLBACK +khm_cfg_identities_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + HWND hw; + switch(uMsg) { + case WM_INITDIALOG: + set_window_node(hwnd, (khui_config_node) lParam); + add_subpanels(hwnd, (khui_config_node) lParam, + (khui_config_node) lParam); + hw = GetDlgItem(hwnd, IDC_CFG_TAB); + show_tab_panel(hwnd, + (khui_config_node) lParam, + hw, + TabCtrl_GetCurSel(hw), + TRUE); + return FALSE; + + case WM_DESTROY: + return 0; + + case KHUI_WM_CFG_NOTIFY: + return handle_cfg_notify(hwnd, wParam, lParam); + + case WM_NOTIFY: + return handle_notify(hwnd, wParam, lParam); + } + + return FALSE; +} + +static ident_data * +find_ident_by_node(khui_config_node node) { + khm_size cb; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + int i; + khm_handle ident = NULL; + + cb = sizeof(idname); + khui_cfg_get_name(node, idname, &cb); + + for (i=0; i < (int)cfg_idents.n_idents; i++) { + if (!wcscmp(cfg_idents.idents[i].idname, idname)) + break; + } + + if (i < (int)cfg_idents.n_idents) { + if (cfg_idents.idents[i].purged) { + /* we are re-creating a purged identity */ + cfg_idents.idents[i].purged = FALSE; + cfg_idents.idents[i].removed = FALSE; + cfg_idents.idents[i].applied = FALSE; + + read_params_ident(&cfg_idents.idents[i]); + } + return &cfg_idents.idents[i]; + } + + /* there is no identity data for this configuration node. We try + to create it. */ + if (KHM_FAILED(kcdb_identity_create(idname, 0, &ident))) + return NULL; + + if (cfg_idents.n_idents >= cfg_idents.nc_idents) { + cfg_idents.nc_idents = UBOUNDSS(cfg_idents.n_idents + 1, + IDENTS_DATA_ALLOC_INCR, + IDENTS_DATA_ALLOC_INCR); +#ifdef DEBUG + assert(cfg_idents.nc_idents > cfg_idents.n_idents); +#endif + cfg_idents.idents = PREALLOC(cfg_idents.idents, + sizeof(*cfg_idents.idents) * + cfg_idents.nc_idents); +#ifdef DEBUG + assert(cfg_idents.idents); +#endif + ZeroMemory(&(cfg_idents.idents[cfg_idents.n_idents]), + sizeof(*cfg_idents.idents) * + (cfg_idents.nc_idents - cfg_idents.n_idents)); + } + + i = (int) cfg_idents.n_idents; + + StringCbLength(idname, KCDB_IDENT_MAXCB_NAME, &cb); + cb += sizeof(wchar_t); + + cfg_idents.idents[i].idname = PMALLOC(cb); +#ifdef DEBUG + assert(cfg_idents.idents[i].idname); +#endif + StringCbCopy(cfg_idents.idents[i].idname, cb, idname); + + cfg_idents.idents[i].ident = ident; + cfg_idents.idents[i].removed = FALSE; + + kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags); +#ifdef DEBUG + assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG); +#endif + + read_params_ident(&cfg_idents.idents[i]); + + cfg_idents.n_idents++; + + /* leave ident held. */ + + return &cfg_idents.idents[i]; +} + +static void +refresh_view_ident(HWND hwnd, khui_config_node node) { + ident_data * d; + + d = find_ident_by_node(node); +#ifdef DEBUG + assert(d); +#endif + + CheckDlgButton(hwnd, IDC_CFG_MONITOR, + (d->work.monitor? BST_CHECKED: BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_RENEW, + (d->work.auto_renew? BST_CHECKED: BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_STICKY, + (d->work.sticky? BST_CHECKED: BST_UNCHECKED)); +} + +static void +mark_remove_ident(HWND hwnd, khui_config_init_data * idata) { + ident_data * d; + + d = find_ident_by_node(idata->ctx_node); +#ifdef DEBUG + assert(d); +#endif + + if (d->removed) + return; + + d->removed = TRUE; + + khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + + EnableWindow(GetDlgItem(hwnd, IDC_CFG_REMOVE), FALSE); +} + +static void +refresh_data_ident(HWND hwnd, khui_config_init_data * idata) { + ident_data * d; + + d = find_ident_by_node(idata->ctx_node); +#ifdef DEBUG + assert(d); +#endif + + if (IsDlgButtonChecked(hwnd, IDC_CFG_MONITOR) == BST_CHECKED) + d->work.monitor = TRUE; + else + d->work.monitor = FALSE; + + if (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED) + d->work.auto_renew = TRUE; + else + d->work.auto_renew = FALSE; + + if (IsDlgButtonChecked(hwnd, IDC_CFG_STICKY) == BST_CHECKED) + d->work.sticky = TRUE; + else + d->work.sticky = FALSE; + + if (d->work.monitor != d->saved.monitor || + d->work.auto_renew != d->saved.auto_renew || + d->work.sticky != d->saved.sticky) { + + khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + + } else { + khui_cfg_set_flags_inst(idata, 0, + KHUI_CNFLAG_MODIFIED); + } +} + +/* dialog procedure for the "general" pane of individual identity + configuration nodes. */ +INT_PTR CALLBACK +khm_cfg_id_tab_proc(HWND hwnd, + UINT umsg, + WPARAM wParam, + LPARAM lParam) { + + khui_config_init_data * idata; + + switch(umsg) { + case WM_INITDIALOG: + { + ident_data * d; + + hold_idents_data(); + + idata = (khui_config_init_data *) lParam; + + khui_cfg_init_dialog_data(hwnd, idata, 0, NULL, NULL); + + refresh_view_ident(hwnd, idata->ctx_node); + + d = find_ident_by_node(idata->ctx_node); + if (d) + d->hwnd = hwnd; +#ifdef DEBUG + else + assert(FALSE); +#endif + } + return FALSE; + + case WM_COMMAND: + khui_cfg_get_dialog_data(hwnd, &idata, NULL); + + if (HIWORD(wParam) == BN_CLICKED) { + switch(LOWORD(wParam)) { + case IDC_CFG_MONITOR: + case IDC_CFG_RENEW: + case IDC_CFG_STICKY: + + refresh_data_ident(hwnd, idata); + if (cfg_idents.hwnd) + PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(1, WMCFG_UPDATE_STATE), 0); + break; + + case IDC_CFG_REMOVE: + mark_remove_ident(hwnd, idata); + if (cfg_idents.hwnd) + PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(1, WMCFG_UPDATE_STATE), 0); + break; + } + } + + khm_set_dialog_result(hwnd, 0); + return TRUE; + + case WM_DESTROY: + { + ident_data * d; + + khui_cfg_get_dialog_data(hwnd, &idata, NULL); + + d = find_ident_by_node(idata->ctx_node); + if (d) + d->hwnd = NULL; + + release_idents_data(); + khui_cfg_free_dialog_data(hwnd); + khm_set_dialog_result(hwnd, 0); + } + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + { + ident_data * d; + BOOL * cont; + + khui_cfg_get_dialog_data(hwnd, &idata, NULL); + + switch (HIWORD(wParam)) { + case WMCFG_APPLY: + cont = (BOOL *) lParam; + d = find_ident_by_node(idata->ctx_node); + write_params_ident(d); + if (d->removed) { + if (cont) + *cont = FALSE; + } else { + khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | + KHUI_CNFLAG_MODIFIED); + } + break; + + case WMCFG_UPDATE_STATE: + refresh_view_ident(hwnd, idata->ctx_node); + refresh_data_ident(hwnd, idata); + break; + } + } + return TRUE; + } + + return FALSE; +} + +/* dialog procedure for individual identity configuration nodes */ +INT_PTR CALLBACK +khm_cfg_identity_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + HWND hw; + + switch(uMsg) { + case WM_INITDIALOG: + { + khui_config_node refnode = NULL; + + set_window_node(hwnd, (khui_config_node) lParam); + + khui_cfg_open(NULL, L"KhmIdentities", &refnode); +#ifdef DEBUG + assert(refnode != NULL); +#endif + add_subpanels(hwnd, + (khui_config_node) lParam, + refnode); + + hw = GetDlgItem(hwnd, IDC_CFG_TAB); + + show_tab_panel(hwnd, + (khui_config_node) lParam, + hw, + TabCtrl_GetCurSel(hw), + TRUE); + + khui_cfg_release(refnode); + } + return FALSE; + + case WM_DESTROY: + return 0; + + case KHUI_WM_CFG_NOTIFY: + return handle_cfg_notify(hwnd, wParam, lParam); + + case WM_NOTIFY: + return handle_notify(hwnd, wParam, lParam); + } + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/ui/cfg_notif_wnd.c b/krb5-1-6/src/windows/identity/ui/cfg_notif_wnd.c new file mode 100644 index 000000000..846d41714 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/cfg_notif_wnd.c @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +typedef struct tag_notif_data { + khui_config_node node; + + BOOL modified; + + BOOL monitor; + BOOL renew; + BOOL halflife; + BOOL warn1; + BOOL warn2; + + khui_tracker tc_renew; + khui_tracker tc_warn1; + khui_tracker tc_warn2; +} notif_data; + +static void +read_params(notif_data * d) { + khm_handle csp_cw; + khm_int32 rv; + khm_int32 t; + + rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, &csp_cw); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_read_int32(csp_cw, L"Monitor", &t); + assert(KHM_SUCCEEDED(rv)); + d->monitor = !!t; + + rv = khc_read_int32(csp_cw, L"AllowAutoRenew", &t); + assert(KHM_SUCCEEDED(rv)); + d->renew = !!t; + + rv = khc_read_int32(csp_cw, L"RenewAtHalfLife", &t); + assert(KHM_SUCCEEDED(rv)); + d->halflife = !!t; + + rv = khc_read_int32(csp_cw, L"AllowWarn", &t); + assert(KHM_SUCCEEDED(rv)); + d->warn1 = !!t; + + rv = khc_read_int32(csp_cw, L"AllowCritical", &t); + assert(KHM_SUCCEEDED(rv)); + d->warn2 = !!t; + + rv = khc_read_int32(csp_cw, L"AutoRenewThreshold", &t); + assert(KHM_SUCCEEDED(rv)); + d->tc_renew.current = t; + + rv = khc_read_int32(csp_cw, L"WarnThreshold", &t); + assert(KHM_SUCCEEDED(rv)); + d->tc_warn1.current = t; + + rv = khc_read_int32(csp_cw, L"CriticalThreshold", &t); + assert(KHM_SUCCEEDED(rv)); + d->tc_warn2.current = t; + + rv = khc_read_int32(csp_cw, L"MaxThreshold", &t); + assert(KHM_SUCCEEDED(rv)); + d->tc_renew.max = t; + d->tc_warn1.max = t; + d->tc_warn2.max = t; + + rv = khc_read_int32(csp_cw, L"MinThreshold", &t); + assert(KHM_SUCCEEDED(rv)); + d->tc_renew.min = t; + d->tc_warn1.min = t; + d->tc_warn2.min = t; + + khc_close_space(csp_cw); + + d->modified = FALSE; +} + +static void +check_for_modification(notif_data * d) { + notif_data t; + + ZeroMemory(&t, sizeof(t)); + + read_params(&t); + + if ((!!d->monitor) != (!!t.monitor) || + (!!d->renew) != (!!t.renew) || + (!!d->halflife) != (!!t.halflife) || + (!!d->warn1) != (!!t.warn1) || + (!!d->warn2) != (!!t.warn2) || + d->tc_renew.current != t.tc_renew.current || + d->tc_warn1.current != t.tc_warn1.current || + d->tc_warn2.current != t.tc_warn2.current) { + + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + + d->modified = TRUE; + + } else { + khui_cfg_set_flags(d->node, + 0, + KHUI_CNFLAG_MODIFIED); + + d->modified = FALSE; + } +} + +static void +write_params(notif_data * d) { + khm_handle csp_cw; + khm_int32 rv; + + if (!d->modified) + return; + + rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, &csp_cw); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_int32(csp_cw, L"Monitor", d->monitor); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_int32(csp_cw, L"AllowAutoRenew", d->renew); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_int32(csp_cw, L"RenewAtHalfLife", d->halflife); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_int32(csp_cw, L"AllowWarn", d->warn1); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_int32(csp_cw, L"AllowCritical", d->warn2); + assert(KHM_SUCCEEDED(rv)); + + + rv = khc_write_int32(csp_cw, L"AutoRenewThreshold", + (khm_int32) d->tc_renew.current); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_int32(csp_cw, L"WarnThreshold", + (khm_int32) d->tc_warn1.current); + assert(KHM_SUCCEEDED(rv)); + + rv = khc_write_int32(csp_cw, L"CriticalThreshold", + (khm_int32) d->tc_warn2.current); + assert(KHM_SUCCEEDED(rv)); + + khc_close_space(csp_cw); + + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); + + khm_timer_refresh(hwnd_notifier); +} + +static void +refresh_view(HWND hwnd, notif_data * d) { + CheckDlgButton(hwnd, IDC_NOTIF_MONITOR, + (d->monitor?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_NOTIF_RENEW, + (d->renew?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_NOTIF_HALFLIFE, + (d->halflife?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_NOTIF_WARN1, + (d->warn1?BST_CHECKED:BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_NOTIF_WARN2, + (d->warn2?BST_CHECKED:BST_UNCHECKED)); + khui_tracker_refresh(&d->tc_renew); + khui_tracker_refresh(&d->tc_warn1); + khui_tracker_refresh(&d->tc_warn2); + if (!d->monitor) { + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR), FALSE); + } else { + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_HALFLIFE), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR), !!(d->renew)); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR), !!(d->warn1)); + EnableWindow(GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR), !!(d->warn2)); + } +} + +static void +refresh_data(HWND hwnd, notif_data * d) { + d->monitor = (IsDlgButtonChecked(hwnd, IDC_NOTIF_MONITOR) + == BST_CHECKED); + d->renew = (IsDlgButtonChecked(hwnd, IDC_NOTIF_RENEW) + == BST_CHECKED); + d->halflife = (IsDlgButtonChecked(hwnd, IDC_NOTIF_HALFLIFE) + == BST_CHECKED); + d->warn1 = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN1) + == BST_CHECKED); + d->warn2 = (IsDlgButtonChecked(hwnd, IDC_NOTIF_WARN2) + == BST_CHECKED); + + check_for_modification(d); +} + +INT_PTR CALLBACK +khm_cfg_notifications_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + notif_data * d; + + switch(uMsg) { + case WM_INITDIALOG: { + HWND hw; + + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d != NULL); +#endif + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + ZeroMemory(d, sizeof(*d)); + + d->node = (khui_config_node) lParam; + + khui_tracker_initialize(&d->tc_renew); + khui_tracker_initialize(&d->tc_warn1); + khui_tracker_initialize(&d->tc_warn2); + + read_params(d); + + hw = GetDlgItem(hwnd, IDC_NOTIF_RENEW_THR); + khui_tracker_install(hw, &d->tc_renew); + + hw = GetDlgItem(hwnd, IDC_NOTIF_WARN1_THR); + khui_tracker_install(hw, &d->tc_warn1); + + hw = GetDlgItem(hwnd, IDC_NOTIF_WARN2_THR); + khui_tracker_install(hw, &d->tc_warn2); + + refresh_view(hwnd, d); + + /* normally we should return TRUE, but in this case we return + FALSE since we don't want to inadvertently steal the focus + from the treeview. */ + return FALSE; + } + + case WM_COMMAND: { + d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + if (HIWORD(wParam) == BN_CLICKED) { + refresh_data(hwnd, d); + refresh_view(hwnd, d); + + check_for_modification(d); + } else if (HIWORD(wParam) == EN_CHANGE) { + SetTimer(hwnd, 1, 500, NULL); + } + + khm_set_dialog_result(hwnd, 0); + + return TRUE; + } + + case WM_TIMER: { + d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + KillTimer(hwnd, 1); + check_for_modification(d); + + khm_set_dialog_result(hwnd, 0); + + return TRUE; + } + + case WM_DESTROY: { + d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + khui_tracker_kill_controls(&d->tc_renew); + khui_tracker_kill_controls(&d->tc_warn1); + khui_tracker_kill_controls(&d->tc_warn2); + + PFREE(d); + + SetWindowLongPtr(hwnd, DWLP_USER, 0); + + khm_set_dialog_result(hwnd, 0); + + return TRUE; + } + + case KHUI_WM_CFG_NOTIFY: { + d = (notif_data *) (DWORD_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + if (HIWORD(wParam) == WMCFG_APPLY) { + write_params(d); + } + + khm_set_dialog_result(hwnd, 0); + + return TRUE; + } + + } + + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/ui/cfg_plugins_wnd.c b/krb5-1-6/src/windows/identity/ui/cfg_plugins_wnd.c new file mode 100644 index 000000000..f0789e8d0 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/cfg_plugins_wnd.c @@ -0,0 +1,654 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +#define MAX_PLUGINS 256 + +typedef struct tag_plugin_data { + kmm_plugin_info plugin; + kmm_module_info module; +} plugin_data; + +typedef struct tag_plugin_dlg_data { + plugin_data * info[MAX_PLUGINS]; + khm_size n_info; + + plugin_data * selected; + HICON plugin_ico; +} plugin_dlg_data; + +void update_dialog_fields(HWND hwnd, + plugin_dlg_data * d, + plugin_data * info) { + wchar_t buf[256]; + UINT resid; + wchar_t * t; + khm_handle csp_module = NULL; + + d->selected = info; + + if (info->plugin.reg.description) + SetDlgItemText(hwnd, IDC_CFG_DESC, info->plugin.reg.description); + else { + wchar_t fmt[128]; + + LoadString(khm_hInstance, IDS_CFG_NODESC, fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, info->plugin.reg.name); + SetDlgItemText(hwnd, IDC_CFG_DESC, buf); + } + + switch(info->plugin.state) { + case KMM_PLUGIN_STATE_FAIL_INIT: + resid = IDS_PISTATE_FAILINIT; + break; + + case KMM_PLUGIN_STATE_FAIL_UNKNOWN: + resid = IDS_PISTATE_FAILUNK; + break; + + case KMM_PLUGIN_STATE_FAIL_MAX_FAILURE: + resid = IDS_PISTATE_FAILMAX; + break; + + case KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED: + resid = IDS_PISTATE_FAILREG; + break; + + case KMM_PLUGIN_STATE_FAIL_DISABLED: + resid = IDS_PISTATE_FAILDIS; + break; + + case KMM_PLUGIN_STATE_FAIL_LOAD: + resid = IDS_PISTATE_FAILLOD; + break; + + case KMM_PLUGIN_STATE_NONE: + case KMM_PLUGIN_STATE_PLACEHOLDER: + resid = IDS_PISTATE_PLACEHOLD; + break; + + case KMM_PLUGIN_STATE_REG: + case KMM_PLUGIN_STATE_PREINIT: + resid = IDS_PISTATE_REG; + break; + + case KMM_PLUGIN_STATE_HOLD: + resid = IDS_PISTATE_HOLD; + break; + + case KMM_PLUGIN_STATE_INIT: + resid = IDS_PISTATE_INIT; + break; + + case KMM_PLUGIN_STATE_RUNNING: + resid = IDS_PISTATE_RUN; + break; + + case KMM_PLUGIN_STATE_EXITED: + resid = IDS_PISTATE_EXIT; + break; + + default: +#ifdef DEBUG + assert(FALSE); +#endif + resid = IDS_PISTATE_FAILUNK; + } + + LoadString(khm_hInstance, resid, + buf, ARRAYLENGTH(buf)); + + SetDlgItemText(hwnd, IDC_CFG_STATE, buf); + + SendDlgItemMessage(hwnd, IDC_CFG_DEPS, + LB_RESETCONTENT, 0, 0); + + for (t = info->plugin.reg.dependencies; t && *t; + t = multi_string_next(t)) { + SendDlgItemMessage(hwnd, IDC_CFG_DEPS, + LB_INSERTSTRING, (WPARAM) -1, (LPARAM) t); + } + + if (info->plugin.reg.module) + SetDlgItemText(hwnd, IDC_CFG_MODULE, + info->plugin.reg.module); + else + SetDlgItemText(hwnd, IDC_CFG_MODULE, + L""); + + if (info->module.reg.vendor) + SetDlgItemText(hwnd, IDC_CFG_VENDOR, + info->module.reg.vendor); + else + SetDlgItemText(hwnd, IDC_CFG_VENDOR, + L""); + + StringCbPrintf(buf, sizeof(buf), L"%u.%u.%u.%u", + (unsigned int) info->module.product_version.major, + (unsigned int) info->module.product_version.minor, + (unsigned int) info->module.product_version.patch, + (unsigned int) info->module.product_version.aux); + + SetDlgItemText(hwnd, IDC_CFG_VERSION, buf); + + if (info->plugin.reg.icon) { + SendDlgItemMessage(hwnd, IDC_CFG_ICON, + STM_SETICON, + (WPARAM) info->plugin.reg.icon, + 0); + } else { + SendDlgItemMessage(hwnd, IDC_CFG_ICON, + STM_SETICON, + (WPARAM) d->plugin_ico, + 0); + } + + if (KHM_SUCCEEDED(kmm_get_module_config(info->module.reg.name, + 0, &csp_module)) && + (khc_value_exists(csp_module, L"ImagePath") & + (KCONF_FLAG_MACHINE | KCONF_FLAG_USER))) { + + EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), TRUE); + } else { + EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE); + } + + if (csp_module) + khc_close_space(csp_module); + + if (info->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) { + EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE); + } else { + EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), TRUE); + } +} + +#define IDX_PLUGIN_NORMAL 1 +#define IDX_PLUGIN_DISABLED 2 +#define IDX_PLUGIN_ERROR 3 + +INT_PTR CALLBACK +khm_cfg_plugins_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + plugin_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + { + kmm_plugin p; + kmm_plugin pn; + kmm_module m; + khm_size i; + LVCOLUMN lvc; + RECT r; + HWND hw; + wchar_t buf[256]; + HIMAGELIST h_ilist; + HICON h_icon; + + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d); +#endif + ZeroMemory(d, sizeof(*d)); +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + p = NULL; + i = 0; + do { + if (KHM_FAILED(kmm_get_next_plugin(p, &pn))) + break; + + if (p) + kmm_release_plugin(p); + p = pn; + +#ifdef DEBUG + assert(d->info[i] == NULL); +#endif + d->info[i] = PMALLOC(sizeof(*(d->info[i]))); +#ifdef DEBUG + assert(d->info[i]); +#endif + ZeroMemory(&d->info[i]->plugin, + sizeof(d->info[i]->plugin)); + + if (KHM_FAILED(kmm_get_plugin_info_i(p, &d->info[i]->plugin))) { + PFREE(d->info[i]); + d->info[i] = NULL; + break; + } + + ZeroMemory(&d->info[i]->module, + sizeof(d->info[i]->module)); + + if (KHM_SUCCEEDED(kmm_load_module(d->info[i]->plugin.reg.module, + KMM_LM_FLAG_NOLOAD, + &m))) { + kmm_get_module_info_i(m, &d->info[i]->module); + kmm_release_module(m); + } + + i ++; + + if (i == MAX_PLUGINS) + break; + } while(p); + + if (p) + kmm_release_plugin(p); + + d->n_info = i; + + /* now populate the list view */ + hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS); +#ifdef DEBUG + assert(hw); +#endif + + h_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLOR8, + 4, 4); + + h_icon = LoadImage(khm_hInstance, + MAKEINTRESOURCE(IDI_CFG_PLUGIN), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); +#ifdef DEBUG + assert(h_icon); +#endif + ImageList_AddIcon(h_ilist, h_icon); + DestroyIcon(h_icon); + + h_icon = LoadImage(khm_hInstance, + MAKEINTRESOURCE(IDI_CFG_PLUGIN_DIS), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); +#ifdef DEBUG + assert(h_icon); +#endif + ImageList_AddIcon(h_ilist, h_icon); + DestroyIcon(h_icon); + + h_icon = LoadImage(khm_hInstance, + MAKEINTRESOURCE(IDI_CFG_PLUGIN_ERR), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); +#ifdef DEBUG + assert(h_icon); +#endif + ImageList_AddIcon(h_ilist, h_icon); + DestroyIcon(h_icon); + + ListView_SetImageList(hw, h_ilist, LVSIL_STATE); + + ZeroMemory(&lvc, sizeof(lvc)); + + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + GetWindowRect(hw, &r); + lvc.cx = ((r.right - r.left) * 95) / 100; + lvc.pszText = buf; + + LoadString(khm_hInstance, IDS_CFG_PI_COL_PLUGINS, + buf, ARRAYLENGTH(buf)); + + ListView_InsertColumn(hw, 0, &lvc); + + for(i=0; i<d->n_info; i++) { + LVITEM lvi; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE; + lvi.lParam = (LPARAM) d->info[i]; + lvi.pszText = d->info[i]->plugin.reg.name; + + if (d->info[i]->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_DISABLED); + } else if (d->info[i]->plugin.state < 0) { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_ERROR); + } else { + lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_NORMAL); + } + + ListView_InsertItem(hw, &lvi); + } + + d->plugin_ico = + (HICON) LoadImage(khm_hInstance, + MAKEINTRESOURCE(IDI_CFG_PLUGIN), + IMAGE_ICON, + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + LR_DEFAULTCOLOR); + } + return FALSE; + + case WM_NOTIFY: + { + LPNMHDR lpnm; + HWND hw; + + d = (plugin_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + if (wParam == IDC_CFG_PLUGINS && + (lpnm = (LPNMHDR) lParam) && + lpnm->code == LVN_ITEMCHANGED) { + + LVITEM lvi; + + hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS); +#ifdef DEBUG + assert(hw); +#endif + if (ListView_GetSelectedCount(hw) != 1) { + SetDlgItemText(hwnd, IDC_CFG_DESC, L""); + SetDlgItemText(hwnd, IDC_CFG_STATE, L""); + SetDlgItemText(hwnd, IDC_CFG_MODULE, L""); + SetDlgItemText(hwnd, IDC_CFG_VENDOR, L""); + SetDlgItemText(hwnd, IDC_CFG_VERSION, L""); + EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE); + SendDlgItemMessage(hwnd, IDC_CFG_DEPS, + LB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_CFG_ICON, STM_SETICON, + (WPARAM) d->plugin_ico, 0); + d->selected = NULL; + } else { + int idx; + plugin_data * info; + + idx = ListView_GetNextItem(hw, -1, LVNI_SELECTED); +#ifdef DEBUG + assert(idx != -1); +#endif + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = idx; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hw, &lvi); +#ifdef DEBUG + assert(lvi.lParam != 0); +#endif + info = (plugin_data *) lvi.lParam; + + update_dialog_fields(hwnd, d, info); + } + } + } + return TRUE; + + case WM_COMMAND: + { + + d = (plugin_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + return FALSE; + + switch (wParam) { + case MAKEWPARAM(IDC_CFG_ENABLE, BN_CLICKED): + if (d->selected != NULL) { + khui_alert * alert = NULL; + wchar_t buf[KHUI_MAXCCH_MESSAGE]; + wchar_t fmt[KHUI_MAXCCH_MESSAGE]; + kmm_plugin p; + + khui_alert_create_empty(&alert); + + LoadString(khm_hInstance, IDS_CFG_P_ENBCNFT, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); + khui_alert_set_title(alert, buf); + + LoadString(khm_hInstance, IDS_CFG_P_ENBCNFM, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); + khui_alert_set_message(alert, buf); + + khui_alert_set_severity(alert, KHERR_INFO); + + khui_alert_show_modal(alert); + + kmm_enable_plugin(d->selected->plugin.h_plugin, TRUE); + + khui_alert_release(alert); + + p = d->selected->plugin.h_plugin; + kmm_hold_plugin(p); + kmm_release_plugin_info_i(&d->selected->plugin); + kmm_get_plugin_info_i(p, &d->selected->plugin); + kmm_release_plugin(p); + + update_dialog_fields(hwnd, d, d->selected); + } + break; + + case MAKEWPARAM(IDC_CFG_DISABLE, BN_CLICKED): + if (d->selected != NULL) { + khui_alert * alert = NULL; + wchar_t buf[KHUI_MAXCCH_MESSAGE]; + wchar_t fmt[KHUI_MAXCCH_MESSAGE]; + wchar_t depends[KHUI_MAXCCH_MESSAGE]; + khm_size i; + kmm_plugin p; + + khui_alert_create_empty(&alert); +#ifdef DEBUG + assert(alert); +#endif + if (alert == NULL) + break; + + LoadString(khm_hInstance, IDS_CFG_P_DELCNFT, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); + khui_alert_set_title(alert, buf); + + LoadString(khm_hInstance, IDS_CFG_P_DELCNFM, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); + khui_alert_set_message(alert, buf); + + depends[0] = L'\0'; + + for (i=0; i<d->n_info; i++) { + wchar_t * t; + + t = d->info[i]->plugin.reg.dependencies; + + while(t) { + if (!wcscmp(t, d->selected->plugin.reg.name)) { + if (depends[0]) + StringCbCat(depends, sizeof(depends), L", "); + StringCbCat(depends, sizeof(depends), + d->info[i]->plugin.reg.name); + break; + } + t = multi_string_next(t); + } + } + + if (depends[0]) { + LoadString(khm_hInstance, IDS_CFG_P_DELCNFS, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, depends); + khui_alert_set_suggestion(alert, buf); + } else { + LoadString(khm_hInstance, IDS_CFG_P_DELNDEP, + buf, ARRAYLENGTH(buf)); + khui_alert_set_suggestion(alert, buf); + } + + khui_alert_add_command(alert, KHUI_PACTION_YES); + khui_alert_add_command(alert, KHUI_PACTION_NO); + + khui_alert_set_severity(alert, KHERR_WARNING); + + if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) && + alert->response == KHUI_PACTION_YES) { + kmm_enable_plugin(d->selected->plugin.h_plugin, FALSE); + } + + khui_alert_release(alert); + + p = d->selected->plugin.h_plugin; + kmm_hold_plugin(p); + kmm_release_plugin_info_i(&d->selected->plugin); + kmm_get_plugin_info_i(p, &d->selected->plugin); + kmm_release_plugin(p); + + update_dialog_fields(hwnd, d, d->selected); + } + break; + + case MAKEWPARAM(IDC_CFG_UNREGISTER, BN_CLICKED): + { + khui_alert * alert = NULL; + wchar_t buf[KHUI_MAXCCH_MESSAGE]; + wchar_t fmt[KHUI_MAXCCH_MESSAGE]; + wchar_t plist[KHUI_MAXCCH_MESSAGE]; + khm_size i; + + if (d->selected == NULL) { +#ifdef DEBUG + assert(FALSE); +#endif + break; + } + + khui_alert_create_empty(&alert); + + LoadString(khm_hInstance, IDS_CFG_P_UNRCNFT, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + d->selected->plugin.reg.name); + + khui_alert_set_title(alert, buf); + + LoadString(khm_hInstance, IDS_CFG_P_UNRCNFM, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, + d->selected->plugin.reg.name); + + khui_alert_set_message(alert, buf); + + plist[0] = L'\0'; + for (i=0; i < d->n_info; i++) { + if (!wcscmp(d->info[i]->module.reg.name, + d->selected->module.reg.name)) { + if (plist[0]) + StringCbCat(plist, sizeof(plist), L", "); + StringCbCat(plist, sizeof(plist), + d->info[i]->plugin.reg.name); + } + } + +#ifdef DEBUG + /* there should have been at least one plugin */ + assert(plist[0]); +#endif + + LoadString(khm_hInstance, IDS_CFG_P_UNRCNFS, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, plist); + khui_alert_set_suggestion(alert, buf); + + khui_alert_add_command(alert, KHUI_PACTION_YES); + khui_alert_add_command(alert, KHUI_PACTION_NO); + + khui_alert_set_severity(alert, KHERR_WARNING); + + if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) && + alert->response == KHUI_PACTION_YES) { + kmm_unregister_module(d->selected->module.reg.name, 0); + + update_dialog_fields(hwnd, d, d->selected); + } + } + break; + + case MAKEWPARAM(IDC_CFG_REGISTER, BN_CLICKED): + { + + } + break; + } + } + return TRUE; + + case WM_DESTROY: + { + khm_size i; + + d = (plugin_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); +#ifdef DEBUG + assert(d); +#endif + if (d == NULL) + return TRUE; + + for (i=0; i<d->n_info; i++) { +#ifdef DEBUG + assert(d->info[i]); +#endif + kmm_release_plugin_info_i(&d->info[i]->plugin); + kmm_release_module_info_i(&d->info[i]->module); + PFREE(d->info[i]); + } + + PFREE(d); + SetWindowLongPtr(hwnd, DWLP_USER, 0); + + khm_set_dialog_result(hwnd, 0); + } + return TRUE; + } + return FALSE; +} diff --git a/krb5-1-6/src/windows/identity/ui/configwnd.c b/krb5-1-6/src/windows/identity/ui/configwnd.c new file mode 100644 index 000000000..f97dc6a4e --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/configwnd.c @@ -0,0 +1,1243 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +static HWND cfgui_hwnd = NULL; + +typedef struct tag_cfgui_wnd_data { + khui_config_node current; + HWND hw_current; + HWND hw_generic_pane; + HBRUSH hbr_white; + HFONT hf_title; + khui_bitmap kbmp_logo; + HIMAGELIST hi_status; + BOOL modified; + int idx_default; + int idx_modified; + int idx_applied; +} cfgui_wnd_data; + +static cfgui_wnd_data * +cfgui_get_wnd_data(HWND hwnd) { + return (cfgui_wnd_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); +} + +static void +cfgui_set_wnd_data(HWND hwnd, cfgui_wnd_data * d) { +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) +} + +static void +cfgui_add_node(cfgui_wnd_data * d, + HWND hwtv, + khui_config_node node, + khui_config_node parent, + BOOL sorted) { + + khui_config_node_reg reg; + khui_config_node c; + wchar_t wbuf[256]; + const wchar_t * short_desc; + TVINSERTSTRUCT s; + HTREEITEM hItem; + + if (node) { + khui_cfg_get_reg(node, &reg); + short_desc = reg.short_desc; + } else { + short_desc = wbuf; + LoadString(khm_hInstance, IDS_CFG_ROOT_NAME, + wbuf, ARRAYLENGTH(wbuf)); + reg.flags = 0; + } + + ZeroMemory(&s, sizeof(s)); + + s.hParent = (node)? + (HTREEITEM) khui_cfg_get_param(parent): + TVI_ROOT; + + s.hInsertAfter = (sorted)? TVI_SORT: TVI_FIRST; + + s.itemex.mask = + TVIF_CHILDREN | + TVIF_PARAM | + TVIF_TEXT | + TVIF_STATE; + + { + khui_config_node n; + + if (KHM_SUCCEEDED(khui_cfg_get_first_child(node, + &n))) { + s.itemex.cChildren = 1; + s.itemex.state = TVIS_EXPANDED; + s.itemex.stateMask = TVIS_EXPANDED; + khui_cfg_release(n); + } else { + s.itemex.cChildren = 0; + s.itemex.state = 0; + s.itemex.stateMask = TVIS_EXPANDED; + } + + s.itemex.state |= INDEXTOSTATEIMAGEMASK(d->idx_default); + s.itemex.stateMask |= TVIS_STATEIMAGEMASK; + } + + s.itemex.lParam = (LPARAM) node; + khui_cfg_hold(node); + + s.itemex.pszText = (LPWSTR) short_desc; + + hItem = TreeView_InsertItem(hwtv, &s); + + khui_cfg_set_param(node, (LPARAM) hItem); + + if (KHM_SUCCEEDED(khui_cfg_get_first_child(node, + &c))) { + do { + cfgui_add_node(d, hwtv, c, node, + !!(reg.flags & KHUI_CNFLAG_SORT_CHILDREN)); + } while (KHM_SUCCEEDED(khui_cfg_get_next_release(&c))); + } +} + +static void +cfgui_initialize_dialog(HWND hwnd) { + cfgui_wnd_data * d; + HWND hwtv; + HWND hwtitle; + HFONT hf; + HDC hdc; + HICON hicon; + + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + return; + + /* create and fill the image list for the treeview */ + + d->hi_status = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + ILC_COLOR8 | ILC_MASK, + 4,4); + + hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_DEFAULT), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + /* note that we can't use index 0 because that is used to indicate + that there is no state image for the node */ + do { + d->idx_default = ImageList_AddIcon(d->hi_status, hicon); + } while(d->idx_default == 0); + + DestroyIcon(hicon); + + hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_MODIFIED), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + d->idx_modified = ImageList_AddIcon(d->hi_status, hicon); + + DestroyIcon(hicon); + + hicon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_APPLIED), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + + d->idx_applied = ImageList_AddIcon(d->hi_status, hicon); + + DestroyIcon(hicon); + + /* now for the treeview */ + hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST); + + TreeView_SetImageList(hwtv, d->hi_status, TVSIL_STATE); + + cfgui_add_node(d, hwtv, NULL, NULL, FALSE); + + hdc = GetDC(hwnd); + hf = CreateFont(-MulDiv(12, + GetDeviceCaps(hdc, LOGPIXELSY), + 72), + 0, /* nWidth */ + 0, /* nEscapement */ + 0, /* nOrientation */ + FW_BOLD, /* fnWeight */ + TRUE, /* fdwItalic */ + FALSE, /* fdwUnderline */ + FALSE, /* fdwStrikeOut */ + DEFAULT_CHARSET, /* fdwCharSet */ + OUT_DEFAULT_PRECIS, /* fdwOutputPrecision */ + CLIP_DEFAULT_PRECIS, /* fdwClipPrecision */ + DEFAULT_QUALITY, /* fdwQuality */ + FF_SWISS | DEFAULT_PITCH, /* pitch&family */ + NULL); /* face */ + ReleaseDC(hwnd, hdc); + + d->hf_title = hf; + + hwtitle = GetDlgItem(hwnd, IDC_CFG_TITLE); + + SendMessage(hwtitle, + WM_SETFONT, + (WPARAM) hf, + (LPARAM) FALSE); +} + +static void +cfgui_free_node(HWND hwtv, HTREEITEM hItem) { + TVITEMEX iex; + HTREEITEM hChItem; + + ZeroMemory(&iex, sizeof(iex)); + + iex.mask = TVIF_PARAM; + iex.hItem = hItem; + + if (TreeView_GetItem(hwtv, &iex)) { + khui_config_node node; + + node = (khui_config_node) iex.lParam; + khui_cfg_release(node); + } + + hChItem = TreeView_GetChild(hwtv, hItem); + while(hChItem) { + cfgui_free_node(hwtv, hChItem); + + hChItem = TreeView_GetNextSibling(hwtv, hChItem); + } +} + +static void +cfgui_uninitialize_dialog(HWND hwnd) { + cfgui_wnd_data * d; + HWND hwtv; + + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + return; + + hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST); + + cfgui_free_node(hwtv, TreeView_GetRoot(hwtv)); + + if (d->hf_title) + DeleteObject(d->hf_title); + + if (d->hi_status) + ImageList_Destroy(d->hi_status); +} + +static HWND +cfgui_create_config_node_window(HWND hwnd, khui_config_node node) { + khui_config_node_reg reg; + khm_int32 rv; + HWND hw_new; + + khui_config_node parent; + + if (KHM_SUCCEEDED(khui_cfg_get_parent(node, &parent))) { + HWND hwp; + + hwp = khui_cfg_get_hwnd(parent); + + if (hwp == NULL) + cfgui_create_config_node_window(hwnd, parent); + + khui_cfg_release(parent); + } + + rv = khui_cfg_get_reg(node, &reg); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + hw_new = CreateDialogParam(reg.h_module, + reg.dlg_template, + hwnd, + reg.dlg_proc, + (LPARAM) node); +#ifdef DEBUG + assert(hw_new); +#endif + khui_cfg_set_hwnd(node, hw_new); + + return hw_new; +} + +static void +cfgui_activate_node(HWND hwnd, khui_config_node node) { + + cfgui_wnd_data * d; + HTREEITEM hItem; + HWND hw_new; + HWND hwtv; + + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + return; + + hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST); + hItem = (HTREEITEM) khui_cfg_get_param(node); + +#ifdef DEBUG + assert(hItem); + assert(hwtv); +#endif + + if (node == NULL) { + hw_new = d->hw_generic_pane; + } else { + + hw_new = khui_cfg_get_hwnd(node); + + if (hw_new == NULL) { + hw_new = cfgui_create_config_node_window(hwnd, node); + } + } + + if (hw_new == d->hw_current) + return; /* nothing to do */ + + { + RECT r_title; + RECT r_pane; + HWND hw; + + if (d->hw_current) + ShowWindow(d->hw_current, SW_HIDE); + + hw = GetDlgItem(hwnd, IDC_CFG_TITLE); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r_title); + + hw = GetDlgItem(hwnd, IDC_CFG_PANE); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r_pane); + + OffsetRect(&r_pane, -r_title.left, -r_title.top); + + SetWindowPos(hw_new, + hwtv, + r_pane.left, r_pane.top, + r_pane.right - r_pane.left, + r_pane.bottom - r_pane.top, + SWP_NOOWNERZORDER | + SWP_SHOWWINDOW | + SWP_NOACTIVATE); + } + + if (node == NULL) { + wchar_t wbuf[256]; + + LoadString(khm_hInstance, IDS_CFG_ROOT_TITLE, + wbuf, ARRAYLENGTH(wbuf)); + + SetDlgItemText(hwnd, IDC_CFG_TITLE, wbuf); + } else { + khm_int32 rv; + khui_config_node_reg reg; + + rv = khui_cfg_get_reg(node, &reg); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + SetDlgItemText(hwnd, IDC_CFG_TITLE, reg.long_desc); + } + + d->hw_current = hw_new; + d->current = node; + + TreeView_SelectItem(hwtv, hItem); +} + +static BOOL +cfgui_check_mod_state(khui_config_node node) { + khm_int32 flags; + khui_config_node c = NULL; + BOOL rv = FALSE; + + flags = khui_cfg_get_flags(node); + + if (flags & KHUI_CNFLAG_MODIFIED) + return TRUE; + + if (KHM_FAILED(khui_cfg_get_first_child(node, &c))) + return FALSE; + + while(c) { + rv = (rv || cfgui_check_mod_state(c)); + khui_cfg_get_next_release(&c); + } + + return rv; +} + +static void +cfgui_apply_settings(khui_config_node node) { + HWND hwnd; + khui_config_node c; + khm_int32 flags; + + hwnd = khui_cfg_get_hwnd(node); + flags = khui_cfg_get_flags(node); + + if (hwnd && (flags & KHUI_CNFLAG_MODIFIED)) { + SendMessage(hwnd, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(0, WMCFG_APPLY), + (LPARAM) node); + } + + if (KHM_FAILED(khui_cfg_get_first_child(node, &c))) + return; + + while (c) { + cfgui_apply_settings(c); + khui_cfg_get_next_release(&c); + } +} + +static void +cfgui_remove_item(HWND hwtv, + HTREEITEM hItem) { + khui_config_node node; + HTREEITEM hChild; + TVITEMEX itemex; + + for (hChild = TreeView_GetChild(hwtv, hItem); + hChild; + hChild = TreeView_GetChild(hwtv, hItem)) { + + cfgui_remove_item(hwtv, hChild); + + } + + ZeroMemory(&itemex, sizeof(itemex)); + + itemex.mask = TVIF_PARAM; + itemex.hItem = hItem; + + TreeView_GetChild(hwtv, &itemex); + + node = (khui_config_node) itemex.lParam; + + if (node) { + HWND hw; + hw = khui_cfg_get_hwnd(node); + + if (hw) + DestroyWindow(hw); + + khui_cfg_release(node); + } + + TreeView_DeleteItem(hwtv, hItem); +} + +struct cfgui_child_info { + HTREEITEM hItem; + khui_config_node node; + BOOL checked; +}; + +#define CI_ALLOC_INCR 8 + +static void +cfgui_sync_node(cfgui_wnd_data * d, + HWND hwtv, + khui_config_node c, + HTREEITEM hItem) { + khui_config_node child; + HTREEITEM hChild; + struct cfgui_child_info * childinfo = NULL; + khm_size n_childinfo = 0; + khm_size nc_childinfo = 0; + khm_size i; + + /* first, get the list of children from the treeview control */ + for (hChild = TreeView_GetChild(hwtv, hItem); + hChild; + hChild = TreeView_GetNextSibling(hwtv, hChild)) { + + if (n_childinfo >= nc_childinfo) { + nc_childinfo = UBOUNDSS(n_childinfo + 1, + CI_ALLOC_INCR, CI_ALLOC_INCR); +#ifdef DEBUG + assert(nc_childinfo > n_childinfo); +#endif + childinfo = PREALLOC(childinfo, + sizeof(*childinfo) * nc_childinfo); +#ifdef DEBUG + assert(childinfo); +#endif + } + + ZeroMemory(&childinfo[n_childinfo], + sizeof(childinfo[n_childinfo])); + + childinfo[n_childinfo].hItem = hChild; + childinfo[n_childinfo].checked = FALSE; + n_childinfo++; + } + + /* now, go through the list of actual nodes and make sure they + match up */ + child = NULL; + for (khui_cfg_get_first_child(c, &child); + child; + khui_cfg_get_next_release(&child)) { + + hChild = (HTREEITEM) khui_cfg_get_param(child); + + for (i=0; i < n_childinfo; i++) { + if (childinfo[i].hItem == hChild) + break; + } + + if (i < n_childinfo) { + childinfo[i].checked = TRUE; + } else { + /* add it to the list, so we can create the node in the + tree view control later. */ + if (n_childinfo >= nc_childinfo) { + nc_childinfo = UBOUNDSS(n_childinfo + 1, + CI_ALLOC_INCR, CI_ALLOC_INCR); +#ifdef DEBUG + assert(nc_childinfo > n_childinfo); +#endif + childinfo = PREALLOC(childinfo, + sizeof(*childinfo) * nc_childinfo); +#ifdef DEBUG + assert(childinfo); +#endif + } + + ZeroMemory(&childinfo[n_childinfo], + sizeof(childinfo[n_childinfo])); + + childinfo[n_childinfo].node = child; + khui_cfg_hold(child); + n_childinfo++; + } + } + + /* by this point, the childinfo list contains items of the + following forms: + + 1. childinfo[i].hItem != NULL && childinfo[i].checked == TRUE + + Corresponds to a tree view item that has a matching + configuration node. Nothing to do here. + + 2. childinfo[i].hItem != NULL && childinfo[i].checked == FALSE + + Corresponds to a tree view item that has no matching + configuration node. These should be removed. + + 3. childinfo[i].hItem == NULL && childinfo[i].node != NULL + + Corresponds to a configuration node that has no matching + tree view item. These nodes should be added. + */ + + /* first do the removals */ + for (i=0; i < n_childinfo; i++) { + if (childinfo[i].hItem == NULL) + break; /* nothing more to see from this point + on */ + if (!childinfo[i].checked) { + /* remove! */ + cfgui_remove_item(hwtv, childinfo[i].hItem); + } + } + + /* continue from where the previous loop left off */ + for (; i < n_childinfo; i++) { +#ifdef DEBUG + assert(childinfo[i].hItem == NULL); + assert(childinfo[i].node != NULL); +#endif + + cfgui_add_node(d, hwtv, childinfo[i].node, c, FALSE); + + khui_cfg_release(childinfo[i].node); + childinfo[i].node = NULL; + } + + if (childinfo) + PFREE(childinfo); + + /* finally recurse through to the next level */ + for (hChild = TreeView_GetChild(hwtv, hItem); + hChild; + hChild = TreeView_GetNextSibling(hwtv, hChild)) { + + TVITEMEX itemex; + + ZeroMemory(&itemex, sizeof(itemex)); + + itemex.mask = TVIF_PARAM; + itemex.hItem = hChild; + + TreeView_GetItem(hwtv, &itemex); + + if (itemex.lParam) { + child = (khui_config_node) itemex.lParam; + + cfgui_sync_node(d, hwtv, child, hChild); + } + } +} + +static void +cfgui_sync_node_list(cfgui_wnd_data * d, HWND hwnd) { + HWND hwtv; + HTREEITEM hItem; + + hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST); + hItem = TreeView_GetRoot(hwtv); + + cfgui_sync_node(d, hwtv, NULL, hItem); +} + +static void +cfgui_update_state(HWND hwnd, + khm_int32 flags, + khui_config_node node) { + cfgui_wnd_data * d; + HWND hwtv; + HTREEITEM hItem; + TVITEMEX itx; + int idx; + + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + return; + + hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST); + hItem = (HTREEITEM) khui_cfg_get_param(node); + + ZeroMemory(&itx, sizeof(itx)); + + if (flags & KHUI_CNFLAG_MODIFIED) + idx = d->idx_modified; + else if (flags & KHUI_CNFLAG_APPLIED) + idx = d->idx_applied; + else + idx = d->idx_default; + + itx.hItem = hItem; + itx.mask = TVIF_STATE; + itx.state = INDEXTOSTATEIMAGEMASK(idx); + itx.stateMask = TVIS_STATEIMAGEMASK; + + TreeView_SetItem(hwtv, &itx); + + if(cfgui_check_mod_state(NULL)) { + EnableWindow(GetDlgItem(hwnd, IDAPPLY), TRUE); + } else { + EnableWindow(GetDlgItem(hwnd, IDAPPLY), FALSE); + } +} + + +/* dialog procedure for the generic dialog */ +static INT_PTR CALLBACK +cfgui_dlgproc_generic(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + cfgui_wnd_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = (cfgui_wnd_data *) lParam; + cfgui_set_wnd_data(hwnd, d); + return TRUE; + + case WM_CTLCOLORSTATIC: + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + break; + + return (BOOL)(DWORD_PTR) d->hbr_white; + + case WM_ERASEBKGND: + { + HDC hdc = (HDC) wParam; + RECT r_client; + RECT r_logo; + RECT r_fill; + + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + break; + + GetClientRect(hwnd, &r_client); + SetRectEmpty(&r_logo); + + r_logo.right = d->kbmp_logo.cx; + r_logo.bottom = d->kbmp_logo.cy; + + OffsetRect(&r_logo, + r_client.right - r_logo.right, + r_client.bottom - r_logo.bottom); + + khui_draw_bitmap(hdc, + r_logo.left, + r_logo.top, + &d->kbmp_logo); + + r_fill.left = 0; + r_fill.top = 0; + r_fill.right = r_logo.left; + r_fill.bottom = r_client.bottom; + FillRect(hdc, &r_fill, d->hbr_white); + + r_fill.left = r_logo.left; + r_fill.right = r_client.right; + r_fill.bottom = r_logo.top; + FillRect(hdc, &r_fill, d->hbr_white); + + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG) TRUE); + } + return TRUE; + } + + return FALSE; +} + +static INT_PTR CALLBACK +cfgui_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + khui_config_node node; + cfgui_wnd_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + node = (khui_config_node) lParam; + + khui_cfg_clear_params(); + + khui_cfg_set_configui_handle(hwnd); + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->hbr_white = CreateSolidBrush(RGB(255,255,255)); + + d->hw_generic_pane = + CreateDialogParam(khm_hInstance, + MAKEINTRESOURCE(IDD_CFG_GENERIC), + hwnd, + cfgui_dlgproc_generic, + (LPARAM) d); + + khui_bitmap_from_hbmp(&d->kbmp_logo, + LoadImage( + khm_hInstance, + MAKEINTRESOURCE(IDB_LOGO_OPAQUE), + IMAGE_BITMAP, + 0, + 0, + LR_DEFAULTCOLOR)); + + cfgui_set_wnd_data(hwnd, d); + + cfgui_initialize_dialog(hwnd); + + cfgui_activate_node(hwnd, node); + + khm_add_dialog(hwnd); + khm_enter_modal(hwnd); + + return TRUE; + + case WM_DESTROY: + cfgui_hwnd = NULL; + + khui_cfg_set_configui_handle(NULL); + + cfgui_uninitialize_dialog(hwnd); + + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + break; + + khui_delete_bitmap(&d->kbmp_logo); + DeleteObject(d->hbr_white); + + cfgui_set_wnd_data(hwnd, NULL); + + khm_del_dialog(hwnd); + + SetForegroundWindow(khm_hwnd_main); + + PFREE(d); + + return FALSE; + + case WM_NOTIFY: + { + LPNMHDR lpnm; + LPNMTREEVIEW lptv; + LPNMTVGETINFOTIP lpgi; + khui_config_node node; + + lpnm = (LPNMHDR) lParam; + + switch (lpnm->code) { + case TVN_SELCHANGED: + lptv = (LPNMTREEVIEW) lParam; + cfgui_activate_node(hwnd, + (khui_config_node) + lptv->itemNew.lParam); + return TRUE; + + case TVN_GETINFOTIP: + lpgi = (LPNMTVGETINFOTIP) lParam; + node = (khui_config_node) lpgi->lParam; + + if (node) { + khm_int32 flags = 0; + + flags = khui_cfg_get_flags(node); + + if (flags & KHUI_CNFLAG_MODIFIED) { + LoadString(khm_hInstance, IDS_CFG_IT_MOD, + lpgi->pszText, lpgi->cchTextMax); + } else if (flags & KHUI_CNFLAG_APPLIED) { + LoadString(khm_hInstance, IDS_CFG_IT_APP, + lpgi->pszText, lpgi->cchTextMax); + } else { + LoadString(khm_hInstance, IDS_CFG_IT_NONE, + lpgi->pszText, lpgi->cchTextMax); + } + } else { + StringCchCopy(lpgi->pszText, lpgi->cchTextMax, L""); + } + + return TRUE; + } + } + return TRUE; + + case WM_CTLCOLORSTATIC: + { + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + break; + + return (BOOL)(DWORD_PTR) d->hbr_white; + } + /* implicit break */ + + case WM_COMMAND: + switch(wParam) { + case MAKEWPARAM(IDCANCEL, BN_CLICKED): + khm_leave_modal(); + DestroyWindow(hwnd); + break; + + case MAKEWPARAM(IDAPPLY, BN_CLICKED): + cfgui_apply_settings(NULL); + break; + + case MAKEWPARAM(IDOK, BN_CLICKED): + cfgui_apply_settings(NULL); + khm_leave_modal(); + DestroyWindow(hwnd); + break; + } + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + switch(HIWORD(wParam)) { + case WMCFG_SHOW_NODE: + cfgui_activate_node(hwnd, (khui_config_node) lParam); + break; + + case WMCFG_UPDATE_STATE: + cfgui_update_state(hwnd, LOWORD(wParam), + (khui_config_node) lParam); + break; + + case WMCFG_SYNC_NODE_LIST: + d = cfgui_get_wnd_data(hwnd); + if (d == NULL) + break; + + cfgui_sync_node_list(d, hwnd); + break; + } + + return TRUE; + } + + return FALSE; +} + +static void +cfgui_create_window(khui_config_node node) { +#ifdef DEBUG + assert(cfgui_hwnd == NULL); +#endif + + khm_refresh_config(); + + cfgui_hwnd = CreateDialogParam(khm_hInstance, + MAKEINTRESOURCE(IDD_CFG_MAIN), + khm_hwnd_main, + cfgui_dlgproc, + (LPARAM) node); +#ifdef DEBUG + assert(cfgui_hwnd != NULL); +#endif + ShowWindow(cfgui_hwnd,SW_SHOW); +} + +static void +cfgui_destroy_window(void) { + if (cfgui_hwnd) + DestroyWindow(cfgui_hwnd); + /* cfgui_hwnd will be set to NULL in the dialog proc */ +} + +void +khm_show_config_pane(khui_config_node node) { + if (cfgui_hwnd != NULL) { + SendMessage(cfgui_hwnd, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(0, WMCFG_SHOW_NODE), + (LPARAM) node); + } else { + cfgui_create_window(node); + } +} + +void khm_refresh_config(void) { + khm_size cb; + khm_size n_idents; + wchar_t * idents = NULL; + wchar_t * t; + khm_int32 rv; + int n_tries = 0; + khui_config_node cfg_ids = NULL; + khui_config_node cfg_r = NULL; + khui_config_node cfg_iter = NULL; + khui_menu_def * omenu; + khm_boolean refresh_menu = FALSE; + + do { + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + NULL, + &cb, + &n_idents); + + if (rv != KHM_ERROR_TOO_LONG || + n_idents == 0) + return; + + if (idents) + PFREE(idents); + idents = PMALLOC(cb); +#ifdef DEBUG + assert(idents); +#endif + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + idents, + &cb, + &n_idents); + + n_tries++; + } while(KHM_FAILED(rv) && + n_tries < 5); + + if (KHM_FAILED(rv)) + goto _cleanup; + + if (KHM_FAILED(khui_cfg_open(NULL, + L"KhmIdentities", + &cfg_ids))) + goto _cleanup; + + for(t = idents; t && *t; t = multi_string_next(t)) { + khui_config_node cfg_id = NULL; + + rv = khui_cfg_open(cfg_ids, + t, + &cfg_id); + + if (KHM_FAILED(rv)) { + khui_config_node_reg reg; + wchar_t wshort[KHUI_MAXCCH_SHORT_DESC]; + wchar_t wlong[KHUI_MAXCCH_LONG_DESC]; + wchar_t wfmt[KHUI_MAXCCH_SHORT_DESC]; + + ZeroMemory(&reg, sizeof(reg)); + + reg.name = t; + reg.short_desc = wshort; + reg.long_desc = wlong; + reg.h_module = khm_hInstance; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDENTITY); + reg.dlg_proc = khm_cfg_identity_proc; + reg.flags = 0; + + LoadString(khm_hInstance, IDS_CFG_IDENTITY_SHORT, + wfmt, ARRAYLENGTH(wfmt)); + StringCbPrintf(wshort, sizeof(wshort), wfmt, t); + + LoadString(khm_hInstance, IDS_CFG_IDENTITY_LONG, + wfmt, ARRAYLENGTH(wfmt)); + StringCbPrintf(wlong, sizeof(wlong), wfmt, t); + + khui_cfg_register(cfg_ids, + &reg); + } else { + khui_cfg_release(cfg_id); + } + } + + for (khui_cfg_get_first_child(cfg_ids, &cfg_iter); + cfg_iter; + khui_cfg_get_next_release(&cfg_iter)) { + + wchar_t cfgname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_handle tident = NULL; + khm_int32 tflags = 0; + + cb = sizeof(cfgname); + khui_cfg_get_name(cfg_iter, cfgname, &cb); + + if (KHM_FAILED(kcdb_identity_create(cfgname, 0, &tident)) || + KHM_FAILED(kcdb_identity_get_flags(tident, &tflags)) || + !(tflags & KCDB_IDENT_FLAG_ACTIVE) || + !(tflags & KCDB_IDENT_FLAG_CONFIG)) { + + /* this configuration node needs to be removed */ + + khui_cfg_remove(cfg_iter); + } + + if (tident) + kcdb_identity_release(tident); + } + + /* Now iterate through the root level configuration nodes and make + sure we have a menu item for each of them. */ + if (KHM_FAILED(khui_cfg_get_first_child(NULL, &cfg_r))) + goto _cleanup; + + omenu = khui_find_menu(KHUI_MENU_OPTIONS); + if (omenu == NULL) + goto _cleanup; + + khui_action_lock(); + + do { + khm_int32 action; + khm_int32 flags; + khui_action * paction; + wchar_t cname[KHUI_MAXCCH_NAME]; + wchar_t wshort[KHUI_MAXCCH_SHORT_DESC]; + khm_size cb; + khm_handle sub; + khui_config_node_reg reg; + + flags = khui_cfg_get_flags(cfg_r); + if (flags & KHUI_CNFLAG_SYSTEM) + goto _next_cfg; + + cb = sizeof(cname); + if (KHM_FAILED(khui_cfg_get_name(cfg_r, cname, &cb))) { +#ifdef DEBUG + assert(FALSE); +#endif + goto _next_cfg; + } + + paction = khui_find_named_action(cname); + + if (!paction) { + khui_cfg_get_reg(cfg_r, &reg); + + kmq_create_hwnd_subscription(khm_hwnd_main, &sub); + + StringCbCopy(wshort, sizeof(wshort), reg.short_desc); + StringCbCat(wshort, sizeof(wshort), L" ..."); + + action = khui_action_create(cname, + wshort, + reg.long_desc, + (void *) CFGACTION_MAGIC, + KHUI_ACTIONTYPE_TRIGGER, + sub); + + if (action == 0) { +#ifdef DEBUG + assert(FALSE); +#endif + goto _next_cfg; + } + + khui_menu_insert_action(omenu, (khm_size) -1, action, 0); + + refresh_menu = TRUE; + } + + _next_cfg: + if (KHM_FAILED(khui_cfg_get_next_release(&cfg_r))) + break; + } while(cfg_r); + + khui_action_unlock(); + + if (refresh_menu) { + khui_refresh_actions(); + } + + _cleanup: + if (cfg_ids) + khui_cfg_release(cfg_ids); + + if (cfg_r) + khui_cfg_release(cfg_r); + + if (idents) + PFREE(idents); +} + +void khm_init_config(void) { + wchar_t wshort[KHUI_MAXCCH_SHORT_DESC]; + wchar_t wlong[KHUI_MAXCCH_LONG_DESC]; + khui_config_node_reg reg; + khui_config_node node; + + reg.short_desc = wshort; + reg.long_desc = wlong; + reg.h_module = khm_hInstance; + reg.flags = KHUI_CNFLAG_SYSTEM; + + reg.name = L"KhmGeneral"; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_GENERAL); + reg.dlg_proc = khm_cfg_general_proc; + LoadString(khm_hInstance, IDS_CFG_GENERAL_SHORT, + wshort, ARRAYLENGTH(wshort)); + LoadString(khm_hInstance, IDS_CFG_GENERAL_LONG, + wlong, ARRAYLENGTH(wlong)); + + khui_cfg_register(NULL, &reg); + + reg.name = L"KhmAppear"; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_APPEAR); + reg.dlg_proc = khm_cfg_appearance_proc; + LoadString(khm_hInstance, IDS_CFG_APPEAR_SHORT, + wshort, ARRAYLENGTH(wshort)); + LoadString(khm_hInstance, IDS_CFG_APPEAR_LONG, + wlong, ARRAYLENGTH(wlong)); + + khui_cfg_register(NULL, &reg); + + reg.name = L"KhmIdentities"; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDENTITIES); + reg.dlg_proc = khm_cfg_identities_proc; + LoadString(khm_hInstance, IDS_CFG_IDENTITIES_SHORT, + wshort, ARRAYLENGTH(wshort)); + LoadString(khm_hInstance, IDS_CFG_IDENTITIES_LONG, + wlong, ARRAYLENGTH(wlong)); + + khui_cfg_register(NULL, &reg); + + node = NULL; + khui_cfg_open(NULL, L"KhmIdentities", &node); +#ifdef DEBUG + assert(node); +#endif + + reg.name = L"KhmIdentitiesTab"; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB); + reg.dlg_proc = khm_cfg_ids_tab_proc; + LoadString(khm_hInstance, IDS_CFG_IDS_TAB_SHORT, + wshort, ARRAYLENGTH(wshort)); + LoadString(khm_hInstance, IDS_CFG_IDS_TAB_LONG, + wlong, ARRAYLENGTH(wlong)); + reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM; + + khui_cfg_register(node, &reg); + + reg.name = L"KhmIdentitiesTabPlural"; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB); + reg.dlg_proc = khm_cfg_id_tab_proc; + LoadString(khm_hInstance, IDS_CFG_ID_TAB_SHORT, + wshort, ARRAYLENGTH(wshort)); + LoadString(khm_hInstance, IDS_CFG_ID_TAB_LONG, + wlong, ARRAYLENGTH(wlong)); + reg.flags = KHUI_CNFLAG_PLURAL | KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_SYSTEM; + + khui_cfg_register(node, &reg); + + reg.flags = KHUI_CNFLAG_SYSTEM; + khui_cfg_release(node); + + reg.name = L"KhmNotifications"; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_NOTIF); + reg.dlg_proc = khm_cfg_notifications_proc; + LoadString(khm_hInstance, IDS_CFG_NOTIF_SHORT, + wshort, ARRAYLENGTH(wshort)); + LoadString(khm_hInstance, IDS_CFG_NOTIF_LONG, + wlong, ARRAYLENGTH(wlong)); + + khui_cfg_register(NULL, &reg); + + reg.name = L"KhmPlugins"; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_PLUGINS); + reg.dlg_proc = khm_cfg_plugins_proc; + LoadString(khm_hInstance, IDS_CFG_PLUGINS_SHORT, + wshort, ARRAYLENGTH(wshort)); + LoadString(khm_hInstance, IDS_CFG_PLUGINS_LONG, + wlong, ARRAYLENGTH(wlong)); + + khui_cfg_register(NULL, &reg); +} + +void khm_exit_config(void) { +} diff --git a/krb5-1-6/src/windows/identity/ui/configwnd.h b/krb5-1-6/src/windows/identity/ui/configwnd.h new file mode 100644 index 000000000..712805fc1 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/configwnd.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_CONFIGWND_H +#define __KHIMAIRA_CONFIGWND_H + +#define CFGACTION_MAGIC 0x38f8 + +void +khm_show_config_pane(khui_config_node node); + +void khm_init_config(void); +void khm_exit_config(void); + +void khm_refresh_config(void); + +/* window procedures for other configuration windows */ +INT_PTR CALLBACK +khm_cfg_general_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +khm_cfg_identities_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +khm_cfg_identity_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +khm_cfg_id_tab_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +khm_cfg_ids_tab_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +khm_cfg_notifications_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +khm_cfg_plugins_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +khm_cfg_appearance_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); +#endif diff --git a/krb5-1-6/src/windows/identity/ui/credfuncs.c b/krb5-1-6/src/windows/identity/ui/credfuncs.c new file mode 100644 index 000000000..c8b6727b8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/credfuncs.c @@ -0,0 +1,1415 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +static BOOL in_dialog = FALSE; +static CRITICAL_SECTION cs_dialog; +static HANDLE in_dialog_evt = NULL; +static LONG init_dialog = 0; +static khm_int32 dialog_result = 0; +static wchar_t dialog_identity[KCDB_IDENT_MAXCCH_NAME]; +static khui_new_creds * dialog_nc = NULL; + +static void +dialog_sync_init(void) { + if (InterlockedIncrement(&init_dialog) == 1) { +#ifdef DEBUG + assert(in_dialog_evt == NULL); + assert(in_dialog == FALSE); +#endif + + InitializeCriticalSection(&cs_dialog); + + in_dialog_evt = CreateEvent(NULL, + TRUE, + TRUE, + L"DialogCompletionEvent"); + } else { + InterlockedDecrement(&init_dialog); + if (in_dialog_evt == NULL) { + Sleep(100); + } + } +} + +BOOL +khm_cred_begin_dialog(void) { + BOOL rv; + + dialog_sync_init(); + + EnterCriticalSection(&cs_dialog); + + if (in_dialog) { + rv = FALSE; + + /* if a dialog is being displayed and we got a another request + to show one, we bring the existing one to the + foreground. */ + if (dialog_nc && dialog_nc->hwnd) { + khm_int32 t = 0; + + if (KHM_SUCCEEDED(khc_read_int32(NULL, + L"CredWindow\\Windows\\NewCred\\ForceToTop", + &t)) && + t != 0) { + + khm_activate_main_window(); + + SetWindowPos(dialog_nc->hwnd, HWND_TOP, 0, 0, 0, 0, + (SWP_NOMOVE | SWP_NOSIZE)); + } + } + + } else { + rv = TRUE; + in_dialog = TRUE; + ResetEvent(in_dialog_evt); + } + + LeaveCriticalSection(&cs_dialog); + return rv; +} + +void +khm_cred_end_dialog(khui_new_creds * nc) { + dialog_sync_init(); + + EnterCriticalSection(&cs_dialog); + if (in_dialog) { + in_dialog = FALSE; + SetEvent(in_dialog_evt); + } + dialog_result = nc->result; +#ifdef DEBUG + assert(dialog_nc == nc); +#endif + dialog_nc = NULL; + if (nc->subtype == KMSG_CRED_NEW_CREDS && + nc->n_identities > 0 && + nc->identities[0]) { + khm_size cb; + + cb = sizeof(dialog_identity); + if (KHM_FAILED(kcdb_identity_get_name(nc->identities[0], + dialog_identity, + &cb))) + dialog_identity[0] = 0; + } else { + dialog_identity[0] = 0; + } + LeaveCriticalSection(&cs_dialog); +} + +BOOL +khm_cred_is_in_dialog(void) { + BOOL rv; + + dialog_sync_init(); + + EnterCriticalSection(&cs_dialog); + rv = in_dialog; + LeaveCriticalSection(&cs_dialog); + + return rv; +} + +khm_int32 +khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result, + wchar_t * ident, khm_size cb_ident) { + khm_int32 rv; + + dialog_sync_init(); + + EnterCriticalSection(&cs_dialog); + if (!in_dialog) + rv = KHM_ERROR_NOT_FOUND; + else { + DWORD dw; + + do { + LeaveCriticalSection(&cs_dialog); + + dw = WaitForSingleObject(in_dialog_evt, timeout); + + EnterCriticalSection(&cs_dialog); + + if (!in_dialog) { + rv = KHM_ERROR_SUCCESS; + if (result) { + *result = dialog_result; + } + if (ident) { + StringCbCopy(ident, cb_ident, dialog_identity); + } + break; + } else if(dw == WAIT_TIMEOUT) { + rv = KHM_ERROR_TIMEOUT; + break; + } + } while(TRUE); + } + LeaveCriticalSection(&cs_dialog); + + return rv; +} + +/* Completion handler for KMSG_CRED messages. We control the overall + logic of credentials acquisition and other operations here. Once a + credentials operation is triggered, each successive message + completion notification will be used to dispatch the messages for + the next step in processing the operation. */ +void KHMAPI +kmsg_cred_completion(kmq_message *m) +{ + khui_new_creds * nc; + +#ifdef DEBUG + assert(m->type == KMSG_CRED); +#else + if(m->type != KMSG_CRED) + return; /* huh? */ +#endif + + switch(m->subtype) { + case KMSG_CRED_PASSWORD: + /* fallthrough */ + case KMSG_CRED_NEW_CREDS: + /* Cred types have attached themselves. Trigger the next + phase. */ + kmq_post_message(KMSG_CRED, KMSG_CRED_DIALOG_SETUP, 0, + m->vparam); + break; + + case KMSG_CRED_RENEW_CREDS: + nc = (khui_new_creds *) m->vparam; + + /* khm_cred_dispatch_process_message() deals with the case + where there are no credential types that wants to + participate in this operation. */ + khm_cred_dispatch_process_message(nc); + break; + + case KMSG_CRED_DIALOG_SETUP: + nc = (khui_new_creds *) m->vparam; + + khm_prep_newcredwnd(nc->hwnd); + + /* all the controls have been created. Now initialize them */ + if (nc->n_types > 0) { + kmq_post_subs_msg(nc->type_subs, + nc->n_types, + KMSG_CRED, + KMSG_CRED_DIALOG_PRESTART, + 0, + m->vparam); + } else { + PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0); + } + break; + + case KMSG_CRED_DIALOG_PRESTART: + /* all prestart stuff is done. Now to activate the dialog */ + nc = (khui_new_creds *) m->vparam; + khm_show_newcredwnd(nc->hwnd); + + kmq_post_subs_msg(nc->type_subs, + nc->n_types, + KMSG_CRED, + KMSG_CRED_DIALOG_START, + 0, + m->vparam); + /* at this point, the dialog window takes over. We let it run + the show until KMSG_CRED_DIALOG_END is posted by the dialog + procedure. */ + break; + + case KMSG_CRED_PROCESS: + /* a wave of these messages have completed. We should check + if there's more */ + nc = (khui_new_creds *) m->vparam; + + /* if we are done processing all the plug-ins, then check if + there were any errors reported. Otherwise we dispatch + another set of messages. */ + if(!khm_cred_dispatch_process_level(nc)) { + + if(kherr_is_error()) { + khui_alert * alert; + kherr_event * evt; + kherr_context * ctx; + wchar_t ws_tfmt[512]; + wchar_t w_idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t ws_title[ARRAYLENGTH(ws_tfmt) + KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + /* For renewals, we suppress the error message for the + following case: + + - The renewal was for an identity + + - There are no identity credentials for the + identity (no credentials that have the same type + as the identity provider). */ + + if (nc->subtype == KMSG_CRED_RENEW_CREDS && + nc->ctx.scope == KHUI_SCOPE_IDENT && + nc->ctx.identity != NULL) { + khm_handle tcs = NULL; /* credential set */ + khm_size count = 0; + khm_int32 id_ctype = KCDB_CREDTYPE_INVALID; + khm_int32 delta = 0; + + kcdb_identity_get_type(&id_ctype); + kcdb_credset_create(&tcs); + kcdb_credset_collect(tcs, NULL, + nc->ctx.identity, + id_ctype, + &delta); + kcdb_credset_get_size(tcs, &count); + kcdb_credset_delete(tcs); + + if (count == 0) { + goto done_with_op; + } + } + + ctx = kherr_peek_context(); + evt = kherr_get_err_event(ctx); + kherr_evaluate_event(evt); + + khui_alert_create_empty(&alert); + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + + khui_alert_set_type(alert, KHUI_ALERTTYPE_ACQUIREFAIL); + + cb = sizeof(w_idname); + if (nc->n_identities == 0 || + KHM_FAILED(kcdb_identity_get_name(nc->identities[0], + w_idname, &cb))) { + /* an identity could not be determined */ + LoadString(khm_hInstance, IDS_NC_FAILED_TITLE, + ws_title, ARRAYLENGTH(ws_title)); + } else { + LoadString(khm_hInstance, IDS_NC_FAILED_TITLE_I, + ws_tfmt, ARRAYLENGTH(ws_tfmt)); + StringCbPrintf(ws_title, sizeof(ws_title), + ws_tfmt, w_idname); + khui_alert_set_ctx(alert, + KHUI_SCOPE_IDENT, + nc->identities[0], + KCDB_CREDTYPE_INVALID, + NULL); + } + + } else if (nc->subtype == KMSG_CRED_PASSWORD) { + + khui_alert_set_type(alert, KHUI_ALERTTYPE_CHPW); + + cb = sizeof(w_idname); + if (nc->n_identities == 0 || + KHM_FAILED(kcdb_identity_get_name(nc->identities[0], + w_idname, &cb))) { + LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE, + ws_title, ARRAYLENGTH(ws_title)); + } else { + LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE_I, + ws_tfmt, ARRAYLENGTH(ws_tfmt)); + StringCbPrintf(ws_title, sizeof(ws_title), + ws_tfmt, w_idname); + khui_alert_set_ctx(alert, + KHUI_SCOPE_IDENT, + nc->identities[0], + KCDB_CREDTYPE_INVALID, + NULL); + } + + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + + khui_alert_set_type(alert, KHUI_ALERTTYPE_RENEWFAIL); + + cb = sizeof(w_idname); + if (nc->ctx.identity == NULL || + KHM_FAILED(kcdb_identity_get_name(nc->ctx.identity, + w_idname, &cb))) { + LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE, + ws_title, ARRAYLENGTH(ws_title)); + } else { + LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE_I, + ws_tfmt, ARRAYLENGTH(ws_tfmt)); + StringCbPrintf(ws_title, sizeof(ws_title), + ws_tfmt, w_idname); + khui_alert_set_ctx(alert, + KHUI_SCOPE_IDENT, + nc->ctx.identity, + KCDB_CREDTYPE_INVALID, + NULL); + } + + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + khui_alert_set_title(alert, ws_title); + khui_alert_set_severity(alert, evt->severity); + + if(!evt->long_desc) + khui_alert_set_message(alert, evt->short_desc); + else + khui_alert_set_message(alert, evt->long_desc); + + if(evt->suggestion) + khui_alert_set_suggestion(alert, evt->suggestion); + + if (nc->subtype == KMSG_CRED_RENEW_CREDS && + nc->ctx.identity != NULL) { + + khm_int32 n_cmd; + + n_cmd = khm_get_identity_new_creds_action(nc->ctx.identity); + + if (n_cmd != 0) { + khui_alert_add_command(alert, n_cmd); + khui_alert_add_command(alert, KHUI_PACTION_CLOSE); + + khui_alert_set_flags(alert, KHUI_ALERT_FLAG_DISPATCH_CMD, + KHUI_ALERT_FLAG_DISPATCH_CMD); + } + } + + khui_alert_show(alert); + khui_alert_release(alert); + + kherr_release_context(ctx); + + kherr_clear_error(); + } + + done_with_op: + + if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, + m->vparam); + } else { + PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), + 0); + } + } + break; + + case KMSG_CRED_END: + /* all is done. */ + { + khui_new_creds * nc; + khm_boolean continue_cmdline = TRUE; + + nc = (khui_new_creds *) m->vparam; + + if (nc->subtype == KMSG_CRED_NEW_CREDS || + nc->subtype == KMSG_CRED_PASSWORD) { + + khm_cred_end_dialog(nc); + + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + + /* if this is a renewal that was triggered while we + were processing the commandline, then we need to + update the pending renewal count. */ + + if (khm_startup.processing) { + LONG renewals; + renewals = InterlockedDecrement(&khm_startup.pending_renewals); + + if (renewals != 0) { + continue_cmdline = FALSE; + } + } + } + + khui_cw_destroy_cred_blob(nc); + + kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); + + if (continue_cmdline) + kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); + } + break; + + /* property sheet stuff */ + + case KMSG_CRED_PP_BEGIN: + /* all the pages should have been added by now. Just send out + the precreate message */ + kmq_post_message(KMSG_CRED, KMSG_CRED_PP_PRECREATE, 0, + m->vparam); + break; + + case KMSG_CRED_PP_END: + kmq_post_message(KMSG_CRED, KMSG_CRED_PP_DESTROY, 0, + m->vparam); + break; + + case KMSG_CRED_DESTROY_CREDS: +#ifdef DEBUG + assert(m->vparam != NULL); +#endif + khui_context_release((khui_action_context *) m->vparam); + PFREE(m->vparam); + + kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); + + kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); + break; + + case KMSG_CRED_IMPORT: + { + khm_boolean continue_cmdline = FALSE; + LONG pending_renewals; + + /* once an import operation ends, we have to trigger a + renewal so that other plug-ins that didn't participate + in the import operation can have a chance at getting + the necessary credentials. + + If we are in the middle of processing the commandline, + we have to be a little bit careful. We can't issue a + commandline conituation message right now because the + import action is still ongoing (since the renewals are + part of the action). Once the renewals have completed, + the completion handler will automatically issue a + commandline continuation message. However, if there + were no identities to renew, then we have to issue the + message ourselves. + */ + + InterlockedIncrement(&khm_startup.pending_renewals); + + khm_cred_renew_all_identities(); + + pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals); + + if (pending_renewals == 0 && khm_startup.processing) + kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); + } + break; + + case KMSG_CRED_REFRESH: + kcdb_identity_refresh_all(); + break; + } +} + +void khm_cred_import(void) +{ + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr0(KHERR_NONE, IDS_CTX_IMPORT); + _describe(); + + kmq_post_message(KMSG_CRED, KMSG_CRED_IMPORT, 0, 0); + + _end_task(); +} + +void khm_cred_set_default(void) +{ + khui_action_context ctx; + khm_int32 rv; + + khui_context_get(&ctx); + + if (ctx.identity) { + rv = kcdb_identity_set_default(ctx.identity); + } + + khui_context_release(&ctx); +} + +void khm_cred_set_default_identity(khm_handle identity) +{ + kcdb_identity_set_default(identity); +} + +void khm_cred_destroy_creds(khm_boolean sync, khm_boolean quiet) +{ + khui_action_context * pctx; + + pctx = PMALLOC(sizeof(*pctx)); +#ifdef DEBUG + assert(pctx); +#endif + + khui_context_get(pctx); + + if(pctx->scope == KHUI_SCOPE_NONE && !quiet) { + /* this really shouldn't be necessary once we start enabling + and disbling actions based on context */ + wchar_t title[256]; + wchar_t message[256]; + + LoadString(khm_hInstance, + IDS_ALERT_NOSEL_TITLE, + title, + ARRAYLENGTH(title)); + + LoadString(khm_hInstance, + IDS_ALERT_NOSEL, + message, + ARRAYLENGTH(message)); + + khui_alert_show_simple(title, + message, + KHERR_WARNING); + + khui_context_release(pctx); + PFREE(pctx); + + return; + } + + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr0(KHERR_NONE, IDS_CTX_DESTROY_CREDS); + _describe(); + + if (sync) + kmq_send_message(KMSG_CRED, + KMSG_CRED_DESTROY_CREDS, + 0, + (void *) pctx); + else + kmq_post_message(KMSG_CRED, + KMSG_CRED_DESTROY_CREDS, + 0, + (void *) pctx); + + _end_task(); +} + +void khm_cred_destroy_identity(khm_handle identity) +{ + khui_action_context * pctx; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + if (identity == NULL) + return; + + pctx = PMALLOC(sizeof(*pctx)); +#ifdef DEBUG + assert(pctx); +#endif + + khui_context_create(pctx, + KHUI_SCOPE_IDENT, + identity, + KCDB_CREDTYPE_INVALID, + NULL); + + cb = sizeof(idname); + kcdb_identity_get_name(identity, idname, &cb); + + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr1(KHERR_NONE, IDS_CTX_DESTROY_ID, _dupstr(idname)); + _describe(); + + kmq_post_message(KMSG_CRED, + KMSG_CRED_DESTROY_CREDS, + 0, + (void *) pctx); + + _end_task(); +} + +void khm_cred_renew_all_identities(void) +{ + khm_size count; + khm_size cb = 0; + khm_size n_idents = 0; + khm_int32 rv; + wchar_t * ident_names = NULL; + wchar_t * this_ident; + + kcdb_credset_get_size(NULL, &count); + + /* if there are no credentials, we just skip over the renew + action. */ + + if (count == 0) + return; + + ident_names = NULL; + + while (TRUE) { + if (ident_names) { + PFREE(ident_names); + ident_names = NULL; + } + + cb = 0; + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0, + NULL, + &cb, &n_idents); + + if (n_idents == 0 || rv != KHM_ERROR_TOO_LONG || + cb == 0) + break; + + ident_names = PMALLOC(cb); + ident_names[0] = L'\0'; + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0, + ident_names, + &cb, &n_idents); + + if (KHM_SUCCEEDED(rv)) + break; + } + + if (ident_names) { + for (this_ident = ident_names; + this_ident && *this_ident; + this_ident = multi_string_next(this_ident)) { + khm_handle ident; + + if (KHM_FAILED(kcdb_identity_create(this_ident, 0, + &ident))) + continue; + + khm_cred_renew_identity(ident); + + kcdb_identity_release(ident); + } + + PFREE(ident_names); + ident_names = NULL; + } +} + +void khm_cred_renew_identity(khm_handle identity) +{ + khui_new_creds * c; + + khui_cw_create_cred_blob(&c); + + c->subtype = KMSG_CRED_RENEW_CREDS; + c->result = KHUI_NC_RESULT_PROCESS; + khui_context_create(&c->ctx, + KHUI_SCOPE_IDENT, + identity, + KCDB_CREDTYPE_INVALID, + NULL); + + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS); + _describe(); + + /* if we are calling this while processing startup actions, we + need to keep track of how many we have issued. */ + if (khm_startup.processing) { + InterlockedIncrement(&khm_startup.pending_renewals); + } + + kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c); + + _end_task(); +} + +void khm_cred_renew_cred(khm_handle cred) +{ + khui_new_creds * c; + + khui_cw_create_cred_blob(&c); + + c->subtype = KMSG_CRED_RENEW_CREDS; + c->result = KHUI_NC_RESULT_PROCESS; + khui_context_create(&c->ctx, + KHUI_SCOPE_CRED, + NULL, + KCDB_CREDTYPE_INVALID, + cred); + + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS); + _describe(); + + /* if we are calling this while processing startup actions, we + need to keep track of how many we have issued. */ + if (khm_startup.processing) { + InterlockedIncrement(&khm_startup.pending_renewals); + } + + kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c); + + _end_task(); +} + +void khm_cred_renew_creds(void) +{ + khui_new_creds * c; + + khui_cw_create_cred_blob(&c); + c->subtype = KMSG_CRED_RENEW_CREDS; + c->result = KHUI_NC_RESULT_PROCESS; + khui_context_get(&c->ctx); + + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr0(KHERR_NONE, IDS_CTX_RENEW_CREDS); + _describe(); + + /* if we are calling this while processing startup actions, we + need to keep track of how many we have issued. */ + if (khm_startup.processing) { + InterlockedIncrement(&khm_startup.pending_renewals); + } + + kmq_post_message(KMSG_CRED, KMSG_CRED_RENEW_CREDS, 0, (void *) c); + + _end_task(); +} + +void khm_cred_change_password(wchar_t * title) +{ + khui_new_creds * nc; + LPNETID_DLGINFO pdlginfo; + khm_size cb; + + if (!khm_cred_begin_dialog()) + return; + + khui_cw_create_cred_blob(&nc); + nc->subtype = KMSG_CRED_PASSWORD; + dialog_nc = nc; + + khui_context_get(&nc->ctx); + + kcdb_identpro_get_ui_cb((void *) &nc->ident_cb); + + assert(nc->ident_cb); + + if (title) { + + if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) { + cb += sizeof(wchar_t); + + nc->window_title = PMALLOC(cb); +#ifdef DEBUG + assert(nc->window_title); +#endif + StringCbCopy(nc->window_title, cb, title); + } + } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) && + (pdlginfo = nc->ctx.vparam) && + pdlginfo->size == NETID_DLGINFO_V1_SZ && + pdlginfo->in.title[0] && + SUCCEEDED(StringCchLength(pdlginfo->in.title, + NETID_TITLE_SZ, + &cb))) { + + cb = (cb + 1) * sizeof(wchar_t); + nc->window_title = PMALLOC(cb); +#ifdef DEBUG + assert(nc->window_title); +#endif + StringCbCopy(nc->window_title, cb, pdlginfo->in.title); + } + + khm_create_newcredwnd(khm_hwnd_main, nc); + + if (nc->hwnd != NULL) { + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr0(KHERR_NONE, IDS_CTX_PASSWORD); + _describe(); + + kmq_post_message(KMSG_CRED, KMSG_CRED_PASSWORD, 0, + (void *) nc); + + _end_task(); + } else { + khui_cw_destroy_cred_blob(nc); + } +} + +void +khm_cred_obtain_new_creds_for_ident(khm_handle ident, wchar_t * title) +{ + khui_action_context ctx; + + if (ident == NULL) + khm_cred_obtain_new_creds(title); + + khui_context_get(&ctx); + + khui_context_set(KHUI_SCOPE_IDENT, + ident, + KCDB_CREDTYPE_INVALID, + NULL, + NULL, + 0, + NULL); + + khm_cred_obtain_new_creds(title); + + khui_context_set_indirect(&ctx); + + khui_context_release(&ctx); +} + +void khm_cred_obtain_new_creds(wchar_t * title) +{ + khui_new_creds * nc; + LPNETID_DLGINFO pdlginfo; + khm_size cb; + + if (!khm_cred_begin_dialog()) + return; + + khui_cw_create_cred_blob(&nc); + nc->subtype = KMSG_CRED_NEW_CREDS; + dialog_nc = nc; + + khui_context_get(&nc->ctx); + + kcdb_identpro_get_ui_cb((void *) &nc->ident_cb); + + if (nc->ident_cb == NULL) { + wchar_t title[256]; + wchar_t msg[512]; + wchar_t suggestion[512]; + khui_alert * a; + + LoadString(khm_hInstance, IDS_ERR_TITLE_NO_IDENTPRO, + title, ARRAYLENGTH(title)); + LoadString(khm_hInstance, IDS_ERR_MSG_NO_IDENTPRO, + msg, ARRAYLENGTH(msg)); + LoadString(khm_hInstance, IDS_ERR_SUGG_NO_IDENTPRO, + suggestion, ARRAYLENGTH(suggestion)); + + khui_alert_create_simple(title, + msg, + KHERR_ERROR, + &a); + khui_alert_set_suggestion(a, suggestion); + + khui_alert_show(a); + + khui_alert_release(a); + + khui_context_release(&nc->ctx); + nc->result = KHUI_NC_RESULT_CANCEL; + khm_cred_end_dialog(nc); + khui_cw_destroy_cred_blob(nc); + return; + } + + if (title) { + if (SUCCEEDED(StringCbLength(title, KHUI_MAXCB_TITLE, &cb))) { + cb += sizeof(wchar_t); + + nc->window_title = PMALLOC(cb); +#ifdef DEBUG + assert(nc->window_title); +#endif + StringCbCopy(nc->window_title, cb, title); + } + } else if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) && + (pdlginfo = nc->ctx.vparam) && + pdlginfo->size == NETID_DLGINFO_V1_SZ && + pdlginfo->in.title[0] && + SUCCEEDED(StringCchLength(pdlginfo->in.title, + NETID_TITLE_SZ, + &cb))) { + + cb = (cb + 1) * sizeof(wchar_t); + nc->window_title = PMALLOC(cb); +#ifdef DEBUG + assert(nc->window_title); +#endif + StringCbCopy(nc->window_title, cb, pdlginfo->in.title); + } + + khm_create_newcredwnd(khm_hwnd_main, nc); + + if (nc->hwnd != NULL) { + _begin_task(KHERR_CF_TRANSITIVE); + _report_sr0(KHERR_NONE, IDS_CTX_NEW_CREDS); + _describe(); + + kmq_post_message(KMSG_CRED, KMSG_CRED_NEW_CREDS, 0, + (void *) nc); + + _end_task(); + } else { + khui_context_release(&nc->ctx); + nc->result = KHUI_NC_RESULT_CANCEL; + khm_cred_end_dialog(nc); + khui_cw_destroy_cred_blob(nc); + } +} + +/* this is called by khm_cred_dispatch_process_message and the + kmsg_cred_completion to initiate and continue checked broadcasts of + KMSG_CRED_DIALOG_PROCESS messages. + + Returns TRUE if more KMSG_CRED_DIALOG_PROCESS messages were + posted. */ +BOOL khm_cred_dispatch_process_level(khui_new_creds *nc) +{ + khm_size i,j; + khm_handle subs[KHUI_MAX_NCTYPES]; + int n_subs = 0; + BOOL cont = FALSE; + khui_new_creds_by_type *t, *d; + + /* at each level, we dispatch a wave of notifications to plug-ins + who's dependencies are all satisfied */ + EnterCriticalSection(&nc->cs); + + /* if any types have already completed, we mark them are processed + and skip them */ + for (i=0; i < nc->n_types; i++) { + t = nc->types[i]; + if(t->flags & KHUI_NC_RESPONSE_COMPLETED) + t->flags |= KHUI_NCT_FLAG_PROCESSED; + } + + for(i=0; i<nc->n_types; i++) { + t = nc->types[i]; + + if((t->flags & KHUI_NCT_FLAG_PROCESSED) || + (t->flags & KHUI_NC_RESPONSE_COMPLETED)) + continue; + + for(j=0; j<t->n_type_deps; j++) { + if(KHM_FAILED(khui_cw_find_type(nc, t->type_deps[j], &d))) + break; + + if(!(d->flags & KHUI_NC_RESPONSE_COMPLETED)) + break; + } + + if(j<t->n_type_deps) /* there are unmet dependencies */ + continue; + + /* all dependencies for this type have been met. */ + subs[n_subs++] = kcdb_credtype_get_sub(t->type); + t->flags |= KHUI_NCT_FLAG_PROCESSED; + cont = TRUE; + } + + LeaveCriticalSection(&nc->cs); + + /* the reason why we are posting messages in batches is because + when the message has completed we know that all the types that + have the KHUI_NCT_FLAG_PROCESSED set have completed processing. + Otherwise we have to individually track each message and update + the type */ + if(n_subs > 0) + kmq_post_subs_msg(subs, n_subs, KMSG_CRED, KMSG_CRED_PROCESS, 0, + (void *) nc); + + return cont; +} + +void +khm_cred_dispatch_process_message(khui_new_creds *nc) +{ + khm_size i; + BOOL pending; + wchar_t wsinsert[512]; + khm_size cbsize; + + /* see if there's anything to do. We can check this without + obtaining a lock */ + if(nc->n_types == 0 || + (nc->subtype == KMSG_CRED_NEW_CREDS && + nc->n_identities == 0) || + (nc->subtype == KMSG_CRED_PASSWORD && + nc->n_identities == 0)) + goto _terminate_job; + + /* check dependencies and stuff first */ + EnterCriticalSection(&nc->cs); + for(i=0; i<nc->n_types; i++) { + nc->types[i]->flags &= ~ KHUI_NCT_FLAG_PROCESSED; + } + LeaveCriticalSection(&nc->cs); + + /* Consindering all that can go wrong here and the desire to + handle errors here separately from others, we create a new task + for the purpose of tracking the credentials acquisition + process. */ + _begin_task(KHERR_CF_TRANSITIVE); + + /* Describe the context */ + if(nc->subtype == KMSG_CRED_NEW_CREDS) { + cbsize = sizeof(wsinsert); + kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize); + + _report_sr1(KHERR_NONE, IDS_CTX_PROC_NEW_CREDS, + _cstr(wsinsert)); + _resolve(); + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + cbsize = sizeof(wsinsert); + + if (nc->ctx.scope == KHUI_SCOPE_IDENT) + kcdb_identity_get_name(nc->ctx.identity, wsinsert, &cbsize); + else if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE) { + if (nc->ctx.identity != NULL) + kcdb_identity_get_name(nc->ctx.identity, wsinsert, + &cbsize); + else + kcdb_credtype_get_name(nc->ctx.cred_type, wsinsert, + &cbsize); + } else if (nc->ctx.scope == KHUI_SCOPE_CRED) { + kcdb_cred_get_name(nc->ctx.cred, wsinsert, &cbsize); + } else { + StringCbCopy(wsinsert, sizeof(wsinsert), L"(?)"); + } + + _report_sr1(KHERR_NONE, IDS_CTX_PROC_RENEW_CREDS, + _cstr(wsinsert)); + _resolve(); + } else if (nc->subtype == KMSG_CRED_PASSWORD) { + cbsize = sizeof(wsinsert); + kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize); + + _report_sr1(KHERR_NONE, IDS_CTX_PROC_PASSWORD, + _cstr(wsinsert)); + _resolve(); + } else { + assert(FALSE); + } + + _describe(); + + pending = khm_cred_dispatch_process_level(nc); + + _end_task(); + + if(!pending) + goto _terminate_job; + + return; + + _terminate_job: + if (nc->subtype == KMSG_CRED_RENEW_CREDS) + kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc); + else + PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0); +} + +void +khm_cred_process_startup_actions(void) { + khm_handle defident = NULL; + + if (!khm_startup.processing) + return; + + if (khm_startup.init || + khm_startup.renew || + khm_startup.destroy || + khm_startup.autoinit) { + kcdb_identity_get_default(&defident); + } + + /* For asynchronous actions, we trigger the action and then exit + the loop. Once the action completes, the completion handler + will trigger a continuation message which will result in this + function getting called again. Then we can proceed with the + rest of the startup actions. */ + do { + if (khm_startup.init) { + + khm_cred_obtain_new_creds_for_ident(defident, NULL); + khm_startup.init = FALSE; + break; + } + + if (khm_startup.import) { + khm_cred_import(); + khm_startup.import = FALSE; + + /* we also set the renew command to false here because we + trigger a renewal for all the identities at the end of + the import operation anyway. */ + khm_startup.renew = FALSE; + break; + } + + if (khm_startup.renew) { + LONG pending_renewals; + + /* if there are no credentials, we just skip over the + renew action. */ + + khm_startup.renew = FALSE; + + InterlockedIncrement(&khm_startup.pending_renewals); + + khm_cred_renew_all_identities(); + + pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals); + + if (pending_renewals != 0) + break; + + /* if there were no pending renewals, then we just fall + through. This means that either there were no + identities to renew, or all the renewals completed. If + all the renewals completed, then the commandline + contiuation message wasn't triggered. Either way, we + must fall through if the count is zero. */ + } + + if (khm_startup.destroy) { + + khm_startup.destroy = FALSE; + + if (defident) { + khm_cred_destroy_identity(defident); + break; + } + } + + if (khm_startup.autoinit) { + khm_size count = 0; + khm_handle credset = NULL; + khm_int32 ctype_ident = KCDB_CREDTYPE_INVALID; + khm_int32 delta = 0; + + khm_startup.autoinit = FALSE; + + kcdb_credset_create(&credset); + kcdb_identity_get_type(&ctype_ident); + + kcdb_credset_collect(credset, NULL, + defident, ctype_ident, + &delta); + + kcdb_credset_get_size(credset, &count); + + kcdb_credset_delete(credset); + + if (count == 0) { + if (defident) + khui_context_set(KHUI_SCOPE_IDENT, + defident, + KCDB_CREDTYPE_INVALID, + NULL, NULL, 0, + NULL); + else + khui_context_reset(); + + khm_cred_obtain_new_creds(NULL); + break; + } + } + + if (khm_startup.exit) { + PostMessage(khm_hwnd_main, + WM_COMMAND, + MAKEWPARAM(KHUI_ACTION_EXIT, 0), 0); + khm_startup.exit = FALSE; + break; + } + + if (khm_startup.display & SOPTS_DISPLAY_HIDE) { + khm_hide_main_window(); + } else if (khm_startup.display & SOPTS_DISPLAY_SHOW) { + khm_show_main_window(); + } + khm_startup.display = 0; + + /* when we get here, then we are all done with the command + line stuff */ + khm_startup.processing = FALSE; + khm_startup.remote = FALSE; + + kmq_post_message(KMSG_ACT, KMSG_ACT_END_CMDLINE, 0, 0); + } while(FALSE); + + if (defident) + kcdb_identity_release(defident); +} + +void +khm_cred_begin_startup_actions(void) { + khm_handle csp_cw; + + if (khm_startup.seen) + return; + + if (!khm_startup.remote && + KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) { + + khm_int32 t = 0; + + khc_read_int32(csp_cw, L"Autoinit", &t); + if (t) + khm_startup.autoinit = TRUE; + + t = 0; + khc_read_int32(csp_cw, L"AutoImport", &t); + if (t) + khm_startup.import = TRUE; + + khc_close_space(csp_cw); + + } + + /* if this is a remote request, and no specific options were + specified other than --renew, then we perform the default + action, as if the user clicked on the tray icon. */ + if (khm_startup.remote && + !khm_startup.exit && + !khm_startup.destroy && + !khm_startup.autoinit && + !khm_startup.init && + !khm_startup.remote_exit && + !khm_startup.import && + !khm_startup.display) { + + khm_int32 def_action = khm_get_default_notifier_action(); + + if (def_action > 0) { + khui_action_trigger(def_action, NULL); + } + } + + khm_startup.seen = TRUE; + khm_startup.processing = TRUE; + + khm_cred_process_startup_actions(); +} + +void +khm_cred_refresh(void) { + kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, NULL); +} + +void +khm_cred_addr_change(void) { + khm_handle csp_cw = NULL; + khm_int32 check_net = 0; + + wchar_t * ids = NULL; + wchar_t * t; + khm_size cb; + khm_size n_idents; + + FILETIME ft_now; + FILETIME ft_exp; + FILETIME ft_issue; + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", + 0, &csp_cw))) { + khc_read_int32(csp_cw, L"AutoDetectNet", &check_net); + + khc_close_space(csp_cw); + } + + if (!check_net) + return; + + while(TRUE) { + if (ids) + PFREE(ids); + ids = NULL; + + if (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID | + KCDB_IDENT_FLAG_RENEWABLE, + KCDB_IDENT_FLAG_VALID | + KCDB_IDENT_FLAG_RENEWABLE, + NULL, + &cb, + &n_idents) != KHM_ERROR_TOO_LONG) + break; + + ids = PMALLOC(cb); + + if (KHM_SUCCEEDED + (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID | + KCDB_IDENT_FLAG_RENEWABLE, + KCDB_IDENT_FLAG_VALID | + KCDB_IDENT_FLAG_RENEWABLE, + ids, + &cb, + &n_idents))) + break; + } + + if (!ids) + return; + + GetSystemTimeAsFileTime(&ft_now); + + for (t=ids; t && *t; t = multi_string_next(t)) { + khm_handle ident; + + + if (KHM_FAILED + (kcdb_identity_create(t, 0, &ident))) + continue; + + cb = sizeof(ft_issue); + + if (KHM_SUCCEEDED + (kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE, NULL, + &ft_issue, &cb)) && + + (cb = sizeof(ft_exp)) && + KHM_SUCCEEDED + (kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL, + &ft_exp, &cb)) && + + CompareFileTime(&ft_now, &ft_exp) < 0) { + + khm_int64 i_issue; + khm_int64 i_exp; + khm_int64 i_now; + + i_issue = FtToInt(&ft_issue); + i_exp = FtToInt(&ft_exp); + i_now = FtToInt(&ft_now); + + if (i_now > (i_issue + i_exp) / 2) { + + khm_cred_renew_identity(ident); + + } + } + + kcdb_identity_release(ident); + } +} diff --git a/krb5-1-6/src/windows/identity/ui/credfuncs.h b/krb5-1-6/src/windows/identity/ui/credfuncs.h new file mode 100644 index 000000000..9bc289089 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/credfuncs.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_CREDFUNCS_H +#define __KHIMAIRA_CREDFUNCS_H + +void KHMAPI +kmsg_cred_completion(kmq_message *m); + +void +khm_cred_destroy_creds(khm_boolean sync, + khm_boolean quiet); + +void +khm_cred_destroy_identity(khm_handle identity); + +void +khm_cred_renew_all_identities(void); + +void +khm_cred_renew_identity(khm_handle identity); + +void +khm_cred_renew_cred(khm_handle cred); + +void +khm_cred_renew_creds(void); + +void +khm_cred_obtain_new_creds(wchar_t * window_title); + +void +khm_cred_obtain_new_creds_for_ident(khm_handle ident, wchar_t * title); + +void +khm_cred_set_default(void); + +void khm_cred_set_default_identity(khm_handle identity); + +void +khm_cred_change_password(wchar_t * window_title); + +void +khm_cred_dispatch_process_message(khui_new_creds *nc); + +BOOL +khm_cred_dispatch_process_level(khui_new_creds *nc); + +BOOL +khm_cred_is_in_dialog(void); + +khm_int32 +khm_cred_wait_for_dialog(DWORD timeout, khm_int32 * result, + wchar_t * ident, khm_size cb_ident); + +void +khm_cred_begin_startup_actions(void); + +void +khm_cred_process_startup_actions(void); + +void +khm_cred_refresh(void); + +void +khm_cred_addr_change(void); + +void +khm_cred_import(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/credwnd.c b/krb5-1-6/src/windows/identity/ui/credwnd.c new file mode 100644 index 000000000..5b246806d --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/credwnd.c @@ -0,0 +1,5956 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<prsht.h> +#include<assert.h> + +ATOM khui_credwnd_cls; +khm_int32 khui_cw_flag_id; + +khm_int32 attr_to_action[KCDB_ATTR_MAX_ID + 1]; + +/* forward declarations */ +static void +cw_select_row_creds(khui_credwnd_tbl * tbl, int row, int selected); + +static void +cw_set_row_context(khui_credwnd_tbl * tbl, int row); + +static void +cw_update_outline(khui_credwnd_tbl * tbl); + +static void +cw_update_selection_state(khui_credwnd_tbl * tbl); + +static void +cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam); + + +khm_int32 bHideWatermarks = 0; + +void +khm_set_cw_element_font(wchar_t * name, LOGFONT * pfont) { + khm_handle csp_cw = NULL; + wchar_t * element_name; + + if (name == NULL) + element_name = L"FontBase"; + else + element_name = name; + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, + &csp_cw))) + return; + + khc_write_binary(csp_cw, element_name, pfont, sizeof(LOGFONT)); + + khc_close_space(csp_cw); +} + +void +khm_get_cw_element_font(HDC hdc, wchar_t * name, BOOL use_default, LOGFONT * pfont) { + khm_handle csp_cw = NULL; + khm_size cb; + wchar_t * element_name; + khm_boolean try_derive = FALSE; + + if (name == NULL) + element_name = L"FontBase"; + else + element_name = name; + + if (use_default) + goto _use_defaults; + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, + &csp_cw))) + goto _use_defaults; + + cb = sizeof(LOGFONT); + if (KHM_FAILED(khc_read_binary(csp_cw, element_name, pfont, + &cb)) || + cb != sizeof(LOGFONT)) { + try_derive = TRUE; + } + + if (try_derive) { + cb = sizeof(LOGFONT); + if (!name || + KHM_FAILED(khc_read_binary(csp_cw, L"FontBase", pfont, + &cb)) || + cb != sizeof(LOGFONT)) { + khc_close_space(csp_cw); + goto _use_defaults; + } + + if (!wcscmp(name, L"FontHeaderBold") || + !wcscmp(name, L"FontBold")) { + + pfont->lfWeight = FW_BOLD; + + } + } + + khc_close_space(csp_cw); + + return; + + _use_defaults: + + ZeroMemory(pfont, sizeof(*pfont)); + + if (name == NULL) { + LOGFONT lf = { + 0,0, + 0,0, + FW_THIN, + FALSE, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + FF_SWISS, + L"MS Shell Dlg"}; + + lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + + *pfont = lf; + + } else if (!wcscmp(name, L"FontHeader")) { + LOGFONT lf = { + 0,0, + 0,0, + FW_THIN, + FALSE, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + FF_SWISS, + L"MS Shell Dlg"}; + + lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + + *pfont = lf; + + } else if (!wcscmp(name, L"FontHeaderBold")) { + LOGFONT lf = { + 0,0, + 0,0, + FW_BOLD, + FALSE, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + FF_SWISS, + L"MS Shell Dlg"}; + + lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + + *pfont = lf; + + } else if (!wcscmp(name, L"FontNormal")) { + LOGFONT lf = { + 0,0, + 0,0, + FW_THIN, + FALSE, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + FF_SWISS, + L"MS Shell Dlg"}; + + lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + + *pfont = lf; + + } else if (!wcscmp(name, L"FontBold")) { + LOGFONT lf = { + 0,0, + 0,0, + FW_BOLD, + FALSE, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + FF_SWISS, + L"MS Shell Dlg"}; + + lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + + *pfont = lf; + + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } +} + +void +cw_refresh_attribs(HWND hwnd) { + khm_int32 act; + kcdb_attrib * attrib; + khui_menu_def * menu; + khm_int32 i; + + menu = khui_find_menu(KHUI_MENU_COLUMNS); +#ifdef DEBUG + assert(menu); +#endif + + for (i=0; i <= KCDB_ATTR_MAX_ID; i++) { + if (KHM_FAILED(kcdb_attrib_get_info(i, &attrib))) { + if (attr_to_action[i] != 0) { + /* the action should be removed */ + khui_menu_remove_action(menu, attr_to_action[i]); + khui_action_delete(attr_to_action[i]); + attr_to_action[i] = 0; + } + } else { + if (attr_to_action[i] == 0 && + !(attrib->flags & KCDB_ATTR_FLAG_HIDDEN) && + (attrib->short_desc || attrib->long_desc)) { + /* new action */ + khm_handle sub = NULL; + + kmq_create_hwnd_subscription(hwnd, &sub); + + act = khui_action_create(attrib->name, + (attrib->short_desc? + attrib->short_desc: attrib->long_desc), + NULL, + (void *)(UINT_PTR) i, + KHUI_ACTIONTYPE_TOGGLE, + sub); + + attr_to_action[i] = act; + + khui_menu_insert_action(menu, 5000, act, 0); + } + + kcdb_attrib_release_info(attrib); + } + } +} + +khm_int32 +cw_get_custom_attr_id(wchar_t * s) +{ + if(!wcscmp(s, CW_CANAME_FLAGS)) + return CW_CA_FLAGS; + if(!wcscmp(s, CW_CANAME_TYPEICON)) + return CW_CA_TYPEICON; + return 0; +} + +const wchar_t * +cw_get_custom_attr_string(khm_int32 attr_id) +{ + if (attr_id == CW_CA_FLAGS) + return CW_CANAME_FLAGS; + if (attr_id == CW_CA_TYPEICON) + return CW_CANAME_TYPEICON; + return NULL; +} + +void +cw_save_view(khui_credwnd_tbl * tbl, wchar_t * view_name) { + wchar_t * col_list = NULL; + khm_size cb_col_list; + khm_handle csp_cw = NULL; + khm_handle csp_views = NULL; + khm_handle csp_view = NULL; + khm_handle csp_cols = NULL; + khm_size cb; + int i; + + if (tbl->n_cols == 0) + return; + + cb_col_list = (KCONF_MAXCB_NAME + 1) * tbl->n_cols; + + col_list = PMALLOC(cb_col_list); +#ifdef DEBUG + assert(col_list); +#endif + + if (!col_list) + goto _cleanup; + + multi_string_init(col_list, cb_col_list); + + /* if we aren't saving to a specific view, and the view has been + customized, then we save it to "Custom_0", unless we are in the + mini mode, in which case we save it to "Custom_1" */ + if (!view_name && (tbl->flags & KHUI_CW_TBL_CUSTVIEW)) { + if (!(tbl->flags & KHUI_CW_TBL_EXPIDENT)) { + view_name = L"Custom_0"; + } else { + view_name = L"Custom_1"; + } + } + + if (view_name) { + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", + KHM_PERM_READ | KHM_PERM_WRITE, &csp_cw))) + goto _cleanup; + + if (KHM_FAILED(khc_open_space(csp_cw, L"Views", KHM_PERM_READ, &csp_views))) + goto _cleanup; + + if (KHM_FAILED(khc_open_space(csp_views, view_name, + KHM_PERM_WRITE | KHM_FLAG_CREATE, + &csp_view))) + goto _cleanup; + + /* if we are switching to a custom view, then we should mark + that as the default. */ + if (tbl->flags & KHUI_CW_TBL_CUSTVIEW) { + khc_write_string(csp_cw, ((!(tbl->flags & KHUI_CW_TBL_EXPIDENT))? + L"DefaultView": + L"DefaultViewMini"), view_name); + } + + } else { + csp_view = tbl->csp_view; + } + + if (!csp_view) + goto _cleanup; + + if (tbl->flags & KHUI_CW_TBL_EXPIDENT) { + khc_write_int32(csp_view, L"ExpandedIdentity", 1); + } else { + khm_int32 t; + if (KHM_SUCCEEDED(khc_read_int32(csp_view, L"ExpandedIdentity", &t)) && t) + khc_write_int32(csp_view, L"ExpandedIdentity", 0); + } + + if (tbl->flags & KHUI_CW_TBL_NOHEADER) { + khc_write_int32(csp_view, L"NoHeader", 1); + } else { + khm_int32 t; + if (KHM_SUCCEEDED(khc_read_int32(csp_view, L"NoHeader", &t)) && t) + khc_write_int32(csp_view, L"NoHeader", 0); + } + + if (KHM_FAILED(khc_open_space(csp_view, L"Columns", + KHM_PERM_WRITE | KHM_FLAG_CREATE, + &csp_cols))) + goto _cleanup; + + for (i=0; i < tbl->n_cols; i++) { + const wchar_t * attr_name; + kcdb_attrib * attrib = NULL; + khm_handle csp_col = NULL; + + if (tbl->cols[i].attr_id < 0) { + attr_name = cw_get_custom_attr_string(tbl->cols[i].attr_id); + } else { + if (KHM_FAILED(kcdb_attrib_get_info(tbl->cols[i].attr_id, + &attrib))) { +#ifdef DEBUG + assert(FALSE); +#endif + goto _clean_col; + } + + attr_name = attrib->name; + } +#ifdef DEBUG + assert(attr_name); +#endif + + cb = cb_col_list; + multi_string_append(col_list, &cb, attr_name); + + if (KHM_FAILED(khc_open_space(csp_cols, attr_name, + KHM_PERM_WRITE | KHM_FLAG_CREATE, + &csp_col))) + goto _clean_col; + + khc_write_int32(csp_col, L"Width", tbl->cols[i].width); + khc_write_int32(csp_col, L"SortIndex", tbl->cols[i].sort_index); + khc_write_int32(csp_col, L"Flags", tbl->cols[i].flags); + + _clean_col: + + if (csp_col) + khc_close_space(csp_col); + + if (attrib) + kcdb_attrib_release_info(attrib); + } + + khc_write_multi_string(csp_view, L"ColumnList", col_list); + + { + khm_version v = app_version; + + khc_write_binary(csp_view, L"_AppVersion", &v, sizeof(v)); + } + + _cleanup: + + if (view_name) { + if (csp_view) + khc_close_space(csp_view); + + if (csp_views) + khc_close_space(csp_views); + + if (csp_cw) + khc_close_space(csp_cw); + } + + if (csp_cols) + khc_close_space(csp_cols); + + if (col_list) + PFREE(col_list); +} + +static COLORREF +cw_mix_colors(COLORREF c1, COLORREF c2, int alpha) { + int r = (GetRValue(c1) * alpha + GetRValue(c2) * (255 - alpha)) / 255; + int g = (GetGValue(c1) * alpha + GetGValue(c2) * (255 - alpha)) / 255; + int b = (GetBValue(c1) * alpha + GetBValue(c2) * (255 - alpha)) / 255; + +#ifdef DEBUG + assert(alpha >= 0 && alpha < 256); +#endif + + return RGB(r,g,b); +} + +static COLORREF +cw_get_theme_color(khm_handle hc, const wchar_t * name, COLORREF ref_color) { + khm_int32 t; + COLORREF c; + int alpha; + + if (KHM_FAILED(khc_read_int32(hc, name, &t))) { +#ifdef DEBUG + assert(FALSE); +#endif + return ref_color; + } + + alpha = ((t >> 24) & 0xff); + c = (COLORREF) (t & 0xffffff); + return cw_mix_colors(ref_color, c, alpha); +} + +void +cw_load_view(khui_credwnd_tbl * tbl, wchar_t * view, HWND hwnd) { + khm_handle hc_cw = NULL; + khm_handle hc_vs = NULL; + khm_handle hc_v = NULL; + khm_handle hc_cs = NULL; + khm_handle hc_c = NULL; + wchar_t buf[KCONF_MAXCCH_NAME]; + wchar_t * clist = NULL; + khm_size cbsize; + wchar_t * iter = NULL; + int i; + HDC hdc; + LOGFONT log_font; + khm_int32 t; + const wchar_t * viewval; + khm_boolean reopen_csp = FALSE; + + tbl->hwnd = hwnd; + + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) + viewval = L"DefaultViewMini"; + else + viewval = L"DefaultView"; + + if(KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ | KHM_PERM_WRITE, + &hc_cw))) + return; + + khc_read_int32(hc_cw, L"HideWatermarks", &bHideWatermarks); + + if(KHM_FAILED(khc_open_space(hc_cw, L"Views", KHM_PERM_READ, &hc_vs))) + goto _exit; + + if(!view) { + cbsize = sizeof(buf); + if(KHM_FAILED(khc_read_string(hc_cw, viewval, buf, &cbsize))) + goto _exit; + view = buf; + } else { + khc_write_string(hc_cw, viewval, view); + } + + /* in addition, if we are loading the default view, we should + also check the appropriate menu item */ + + if (!wcscmp(view, L"ByIdentity")) + khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT), + KHUI_ACTION_LAYOUT_ID); + else if (!wcscmp(view, L"ByLocation")) + khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT), + KHUI_ACTION_LAYOUT_LOC); + else if (!wcscmp(view, L"ByType")) + khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT), + KHUI_ACTION_LAYOUT_TYPE); + else if (!wcscmp(view, L"Custom_0")) + khui_check_radio_action(khui_find_menu(KHUI_MENU_LAYOUT), + KHUI_ACTION_LAYOUT_CUST); + else { + /* do nothing */ + } + + if (KHM_FAILED(khc_read_int32(hc_cw, L"ViewAllIdents", &tbl->view_all_idents))) + tbl->view_all_idents = 0; + + khui_check_action(KHUI_ACTION_VIEW_ALL_IDS, tbl->view_all_idents); + + kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0); + + if(KHM_FAILED(khc_open_space(hc_vs, view, 0, &hc_v))) + goto _exit; + + /* view data is very sensitive to version changes. We need to + check if this configuration data was created with this version + of NetIDMgr. If not, we switch to using a schema handle. */ + { + khm_version this_v = app_version; + khm_version cfg_v; + + cbsize = sizeof(cfg_v); + if (KHM_FAILED(khc_read_binary(hc_v, L"_AppVersion", &cfg_v, &cbsize)) || + khm_compare_version(&cfg_v, &this_v) != 0) { + + khc_close_space(hc_v); + + if (KHM_FAILED(khc_open_space(hc_vs, view, KCONF_FLAG_SCHEMA, + &hc_v)) && + (wcscmp(view, L"Custom_1") || + KHM_FAILED(khc_open_space(hc_vs, L"CompactIdentity", + KCONF_FLAG_SCHEMA, &hc_v)))) { + goto _exit; + } + + reopen_csp = TRUE; + } + } + + tbl->csp_view = hc_v; + + if(KHM_FAILED(khc_open_space(hc_v, L"Columns", + KHM_PERM_READ | (reopen_csp ? KCONF_FLAG_SCHEMA : 0), + &hc_cs))) + goto _exit; + + cbsize = 0; + if(khc_read_multi_string(hc_v, L"ColumnList", NULL, &cbsize) != KHM_ERROR_TOO_LONG) + goto _exit; + + /* temporary */ + clist = PMALLOC(cbsize); + + if(KHM_FAILED(khc_read_multi_string(hc_v, L"ColumnList", clist, &cbsize))) + goto _exit; + + tbl->n_cols = (int) multi_string_length_n(clist); + tbl->n_total_cols = UBOUNDSS(tbl->n_cols, + KHUI_CW_COL_INITIAL, KHUI_CW_COL_INCREMENT); + tbl->cols = PMALLOC(sizeof(khui_credwnd_col) * tbl->n_total_cols); + ZeroMemory(tbl->cols, sizeof(khui_credwnd_col) * tbl->n_total_cols); + + tbl->flags &= ~(KHUI_CW_TBL_CUSTVIEW | KHUI_CW_TBL_COLSKIP); + + if (KHM_SUCCEEDED(khc_read_int32(hc_v, L"ExpandedIdentity", &t)) && t) { + tbl->flags |= KHUI_CW_TBL_EXPIDENT; + } else { + tbl->flags &= ~KHUI_CW_TBL_EXPIDENT; + } + + if (KHM_SUCCEEDED(khc_read_int32(hc_v, L"NoHeader", &t)) && t) { + tbl->flags |= KHUI_CW_TBL_NOHEADER; + } else { + tbl->flags &= ~KHUI_CW_TBL_NOHEADER; + } + + iter = clist; + i = 0; + while(iter) { + khm_int32 attr_id; + + attr_id = cw_get_custom_attr_id(iter); + if(!attr_id) { + /* a KCDB attribute */ + if(KHM_FAILED(kcdb_attrib_get_id(iter, &attr_id))) { + tbl->flags |= KHUI_CW_TBL_COLSKIP; + goto _skip_col; + } + + if(kcdb_attrib_describe(attr_id, NULL, + &cbsize, KCDB_TS_SHORT) != KHM_ERROR_TOO_LONG || + cbsize == 0) { + tbl->flags |= KHUI_CW_TBL_COLSKIP; + goto _skip_col; + } + + tbl->cols[i].title = PMALLOC(cbsize); + kcdb_attrib_describe(attr_id, tbl->cols[i].title, &cbsize, KCDB_TS_SHORT); + + if (attr_id >= 0 && + attr_id <= KCDB_ATTR_MAX_ID && + attr_to_action[attr_id]) { + khui_check_action(attr_to_action[attr_id], TRUE); + } + + } else { + /* All current custom attributes are represented by icons, + not names */ + tbl->cols[i].title = NULL; + } + + tbl->cols[i].attr_id = attr_id; + + if(KHM_SUCCEEDED(khc_open_space(hc_cs, iter, + KHM_PERM_READ | (reopen_csp ? KCONF_FLAG_SCHEMA : 0), + &hc_c))) { + if(KHM_FAILED(khc_read_int32(hc_c, L"Flags", &(tbl->cols[i].flags)))) + tbl->cols[i].flags = 0; + if(KHM_FAILED(khc_read_int32(hc_c, L"Width", &(tbl->cols[i].width)))) + tbl->cols[i].width = 100; + if(KHM_FAILED(khc_read_int32(hc_c, L"SortIndex", + &(tbl->cols[i].sort_index)))) + tbl->cols[i].sort_index = -1; + khc_close_space(hc_c); + hc_c = NULL; + } else { + tbl->cols[i].flags = 0; + tbl->cols[i].width = -1; + tbl->cols[i].sort_index = -1; + } + i++; +_skip_col: + iter = multi_string_next(iter); + } + + /* refresh the menus since we checked a few items */ + kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0); + + /* adjust the number of columns. We may have skipped columns due to + inconsistencies above */ + tbl->n_cols = i; + + /* now that all the columns have been loaded, load the view + parameters */ + if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingHorizontal", &(tbl->hpad)))) + khc_read_int32(hc_cw, L"PaddingHorizontal", &(tbl->hpad)); + if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingVertical", &(tbl->vpad)))) + khc_read_int32(hc_cw, L"PaddingVertical", &(tbl->vpad)); + if(KHM_FAILED(khc_read_int32(hc_v, L"PaddingHeader", &(tbl->hpad_h)))) + khc_read_int32(hc_cw, L"PaddingHeader", &(tbl->hpad_h)); + if(KHM_FAILED(khc_read_int32(hc_v, L"WarnThreshold", &(tbl->threshold_warn)))) + khc_read_int32(hc_cw, L"WarnThreshold", &(tbl->threshold_warn)); + if(KHM_FAILED(khc_read_int32(hc_v, L"CriticalThreshold", + &(tbl->threshold_critical)))) + khc_read_int32(hc_cw, L"CriticalThreshold", + &(tbl->threshold_critical)); + + /* and the font resources and stuff */ + + tbl->flags |= KHUI_CW_TBL_INITIALIZED | KHUI_CW_TBL_COL_DIRTY | KHUI_CW_TBL_ACTIVE; + + hdc = GetWindowDC(hwnd); + + khm_get_cw_element_font(hdc, L"FontHeader", FALSE, &log_font); + tbl->hf_header = CreateFontIndirect(&log_font); + + if(tbl->hf_header && tbl->hwnd_header) + SendMessage(tbl->hwnd_header, WM_SETFONT, (WPARAM) tbl->hf_header, 0); + + khm_get_cw_element_font(hdc, L"FontHeaderBold", FALSE, &log_font); + tbl->hf_bold_header = CreateFontIndirect(&log_font); + + + khm_get_cw_element_font(hdc, L"FontNormal", FALSE, &log_font); + tbl->hf_normal = CreateFontIndirect(&log_font); + + khm_get_cw_element_font(hdc, L"FontBold", FALSE, &log_font); + tbl->hf_bold = CreateFontIndirect(&log_font); + + ReleaseDC(hwnd, hdc); + + khui_bitmap_from_hbmp(&(tbl->kbm_logo_shade), + LoadImage(khm_hInstance, + MAKEINTRESOURCE(IDB_LOGO_SHADE), + IMAGE_BITMAP, + 0, + 0, + LR_DEFAULTCOLOR)); + + { + +#define SEL_ALPHA 50 + + khm_handle hc_themes = NULL; + khm_handle hc_theme = NULL; + + COLORREF bg_s = 0; + COLORREF bg_normal = 0; + COLORREF bg_gray = 0; + COLORREF bg_hdr = 0; + COLORREF bg_hdr_cred = 0; + COLORREF bg_hdr_warn = 0; + COLORREF bg_hdr_crit = 0; + COLORREF bg_hdr_exp = 0; + + COLORREF bg_hdr_s = 0; + COLORREF bg_hdr_cred_s = 0; + COLORREF bg_hdr_warn_s = 0; + COLORREF bg_hdr_crit_s = 0; + COLORREF bg_hdr_exp_s = 0; + + cbsize = sizeof(buf); + if (KHM_SUCCEEDED(khc_read_string(hc_cw, L"DefaultTheme", buf, &cbsize)) && + KHM_SUCCEEDED(khc_open_space(hc_cw, L"Themes", KHM_PERM_READ, &hc_themes)) && + KHM_SUCCEEDED(khc_open_space(hc_themes, buf, KHM_PERM_READ, &hc_theme))) { + + bg_s = cw_get_theme_color(hc_theme, L"ClrSelection", 0); + bg_normal = cw_get_theme_color(hc_theme, L"ClrBackground", 0); + bg_gray = cw_get_theme_color(hc_theme, L"ClrGray", 0); + bg_hdr = cw_get_theme_color(hc_theme, L"ClrHeader", 0); + bg_hdr_cred = cw_get_theme_color(hc_theme, L"ClrHeaderCred", 0); + bg_hdr_warn = cw_get_theme_color(hc_theme, L"ClrHeaderWarn", 0); + bg_hdr_crit = cw_get_theme_color(hc_theme, L"ClrHeaderCrit", 0); + bg_hdr_exp = cw_get_theme_color(hc_theme, L"ClrHeaderExp", 0); + bg_hdr_s = cw_get_theme_color(hc_theme, L"ClrHeaderSel", bg_s); + bg_hdr_cred_s = cw_get_theme_color(hc_theme, L"ClrHeaderCredSel", bg_s); + bg_hdr_warn_s = cw_get_theme_color(hc_theme, L"ClrHeaderWarnSel", bg_s); + bg_hdr_crit_s = cw_get_theme_color(hc_theme, L"ClrHeaderCritSel", bg_s); + bg_hdr_exp_s = cw_get_theme_color(hc_theme, L"ClrHeaderExpSel", bg_s); + + tbl->cr_normal = cw_get_theme_color(hc_theme, L"ClrText", 0); + tbl->cr_s = cw_get_theme_color(hc_theme, L"ClrTextSel", bg_s); + tbl->cr_hdr_outline = cw_get_theme_color(hc_theme, L"ClrHeaderOutline", 0); + tbl->cr_hdr_normal = cw_get_theme_color(hc_theme, L"ClrTextHeader", 0); + tbl->cr_hdr_s = cw_get_theme_color(hc_theme, L"ClrTextHeaderSel", bg_s); + tbl->cr_hdr_gray = cw_get_theme_color(hc_theme, L"ClrTextHeaderGray", 0); + tbl->cr_hdr_gray_s = cw_get_theme_color(hc_theme, L"ClrTextHeaderGraySel", bg_s); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + if (hc_theme) + khc_close_space(hc_theme); + if (hc_themes) + khc_close_space(hc_themes); + hc_theme = hc_themes = NULL; + + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) { + bg_hdr = bg_normal; + tbl->cr_hdr_outline = bg_gray; + } + + tbl->hb_normal = CreateSolidBrush(bg_normal); + tbl->hb_grey = CreateSolidBrush(bg_gray); + tbl->hb_s = CreateSolidBrush(cw_mix_colors(bg_s, bg_normal, SEL_ALPHA)); + + tbl->hb_hdr_bg = CreateSolidBrush(bg_hdr); + tbl->hb_hdr_bg_cred = CreateSolidBrush(bg_hdr_cred); + tbl->hb_hdr_bg_warn = CreateSolidBrush(bg_hdr_warn); + tbl->hb_hdr_bg_crit = CreateSolidBrush(bg_hdr_crit); + tbl->hb_hdr_bg_exp = CreateSolidBrush(bg_hdr_exp); + + tbl->hb_hdr_bg_s = CreateSolidBrush(bg_s); + tbl->hb_hdr_bg_cred_s = CreateSolidBrush(bg_hdr_cred_s); + tbl->hb_hdr_bg_warn_s = CreateSolidBrush(bg_hdr_warn_s); + tbl->hb_hdr_bg_crit_s = CreateSolidBrush(bg_hdr_crit_s); + tbl->hb_hdr_bg_exp_s = CreateSolidBrush(bg_hdr_exp_s); + } + + tbl->ilist = khui_create_ilist(KHUI_SMICON_CX, KHUI_SMICON_CY-1, 20, 8, 0); + { + HBITMAP hbm; + +#define ADD_BITMAP(i) \ + hbm = LoadImage(khm_hInstance, MAKEINTRESOURCE(i), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); \ + if(hbm) { \ + khui_ilist_add_masked_id(tbl->ilist, hbm, KHUI_TOOLBAR_BGCOLOR, i); \ + DeleteObject(hbm); \ + } + + ADD_BITMAP(IDB_WDG_COLLAPSE); + ADD_BITMAP(IDB_WDG_EXPAND); + ADD_BITMAP(IDB_ID_SM); + ADD_BITMAP(IDB_ID_DIS_SM); + + ADD_BITMAP(IDB_TK_NEW_SM); + ADD_BITMAP(IDB_TK_REFRESH_SM); + ADD_BITMAP(IDB_WDG_COLLAPSE_HI); + ADD_BITMAP(IDB_WDG_EXPAND_HI); + + ADD_BITMAP(IDB_WDG_FLAG); + ADD_BITMAP(IDB_WDG_CREDTYPE); + ADD_BITMAP(IDB_FLAG_WARN); + ADD_BITMAP(IDB_FLAG_EXPIRED); + + ADD_BITMAP(IDB_FLAG_CRITICAL); + ADD_BITMAP(IDB_FLAG_RENEW); + ADD_BITMAP(IDB_WDG_STUCK); + ADD_BITMAP(IDB_WDG_STUCK_HI); + + ADD_BITMAP(IDB_WDG_STICK); + ADD_BITMAP(IDB_WDG_STICK_HI); + ADD_BITMAP(IDB_TK_SM); + +#undef ADD_BITMAP + } + + if (tbl->flags & KHUI_CW_TBL_EXPIDENT) { + tbl->hi_lg_ident = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), + IMAGE_ICON, + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + LR_DEFAULTCOLOR); + } + + tbl->cursor_row = -1; + tbl->scr_left = 0; + tbl->scr_top = 0; + tbl->ext_height = 0; + tbl->ext_width = 0; + + if (reopen_csp) { + khc_close_space(hc_v); + + hc_v = NULL; + + khc_open_space(hc_vs, view, 0, &hc_v); + + tbl->csp_view = hc_v; + } + +_exit: + if(hc_cw) + khc_close_space(hc_cw); + if(hc_vs) + khc_close_space(hc_vs); + if(hc_cs) + khc_close_space(hc_cs); + if(clist) + PFREE(clist); + /* we leave hc_v held, because tbl->csp_view is the same handle. + We keep that open until the view is unloaded. */ +} + +khui_credwnd_ident * +cw_find_ident(khui_credwnd_tbl * tbl, khm_handle ident) { + khm_size i; + + for (i=0; i < tbl->n_idents; i++) { + if (kcdb_identity_is_equal(ident, tbl->idents[i].ident)) + break; + } + + if (i < tbl->n_idents) + return &tbl->idents[i]; + else + return NULL; +} + +khm_int32 KHMAPI +cw_credset_iter_func(khm_handle cred, void * rock) { + khui_credwnd_tbl * tbl = (khui_credwnd_tbl *) rock; + khm_handle ident = NULL; + khm_size i; + khui_credwnd_ident * cwi = NULL; + khm_int32 cred_credtype = KCDB_CREDTYPE_INVALID; + khm_int32 cred_flags = 0; + + kcdb_cred_get_identity(cred, &ident); + + if (ident == NULL) + goto _cleanup; + + for (i=0; i < tbl->n_idents; i++) { + if (kcdb_identity_is_equal(ident, tbl->idents[i].ident)) + break; + } + + if (i >= tbl->n_idents) { + khm_size cb; + + /* need to add this one */ + if (tbl->n_idents == tbl->nc_idents) { + tbl->nc_idents = UBOUNDSS(tbl->n_idents + 1, + CW_IDENT_ALLOC_INCR, + CW_IDENT_ALLOC_INCR); +#ifdef DEBUG + assert(tbl->nc_idents > tbl->n_idents); +#endif + tbl->idents = PREALLOC(tbl->idents, sizeof(tbl->idents[0]) * tbl->nc_idents); +#ifdef DEBUG + assert(tbl->idents); +#endif + ZeroMemory(&tbl->idents[tbl->n_idents], + sizeof(tbl->idents[0]) * (tbl->nc_idents - tbl->n_idents)); + } + + i = tbl->n_idents; + cwi = &tbl->idents[tbl->n_idents++]; + + ZeroMemory(cwi, sizeof(*cwi)); + + cwi->ident = ident; + kcdb_identity_hold(ident); + + cb = sizeof(cwi->name); + kcdb_identity_get_name(ident, cwi->name, &cb); + } + + cwi = &tbl->idents[i]; + + /* this is the first time we are seeing this identity. */ + if (cwi->credcount == 0) { + khm_size cb; + + cb = sizeof(cwi->credtype); + if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_TYPE, NULL, + &cwi->credtype, &cb))) { + cwi->credtype_name[0] = L'\0'; + + cb = sizeof(cwi->credtype_name); + if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_TYPE_NAME, NULL, + &cwi->credtype_name, &cb))) { + cb = sizeof(cwi->credtype_name); + kcdb_credtype_describe(cwi->credtype, cwi->credtype_name, + &cb, KCDB_TS_SHORT); + } + } else { + cwi->credtype = KCDB_CREDTYPE_INVALID; + cwi->credtype_name[0] = L'\0'; + } + + cb = sizeof(cwi->ft_expire); + if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL, + &cwi->ft_expire, &cb))) { + cwi->ft_expire = IntToFt(0); + } + + kcdb_identity_get_flags(cwi->ident, &cwi->ident_flags); + } + + cwi->credcount++; + + kcdb_cred_get_type(cred, &cred_credtype); + if (cred_credtype >= 0 && cred_credtype == cwi->credtype) { + cwi->id_credcount++; + + kcdb_cred_get_flags(cred, &cred_flags); + if (cred_flags & KCDB_CRED_FLAG_INITIAL) { + cwi->init_credcount++; + } + } + + _cleanup: + if (ident) + kcdb_identity_release(ident); + + return KHM_ERROR_SUCCESS; +} + +void +cw_update_creds(khui_credwnd_tbl * tbl) +{ + kcdb_cred_comp_field * fields; + kcdb_cred_comp_order comp_order; + int i; + khm_int32 n; + khm_int32 delta; + khm_handle hc; + khm_int32 flags; + + if(!tbl->credset) { + if(KHM_FAILED(kcdb_credset_create(&(tbl->credset)))) + return; + } + + kcdb_credset_purge(tbl->credset); + + kcdb_identity_refresh_all(); + + kcdb_credset_collect( + tbl->credset, + NULL, + NULL, + KCDB_CREDTYPE_ALL, + &delta); + + /* now we need to figure out how to sort the credentials */ + fields = PMALLOC(sizeof(kcdb_cred_comp_field) * tbl->n_cols); + ZeroMemory(fields, sizeof(kcdb_cred_comp_field) * tbl->n_cols); + + for(i=0, n=0; i<tbl->n_cols; i++) { + if((tbl->cols[i].flags & KHUI_CW_COL_SORT_INC) || + (tbl->cols[i].flags & KHUI_CW_COL_SORT_DEC) || + (tbl->cols[i].flags & KHUI_CW_COL_GROUP)) { + int si; + /* we need to sort by this column */ + si = tbl->cols[i].sort_index; + + if(si < 0 || si >= (int) tbl->n_cols) + { + /* this shouldn't happen */ + tbl->cols[i].flags &= ~(KHUI_CW_COL_SORT_INC | + KHUI_CW_COL_SORT_DEC | + KHUI_CW_COL_GROUP); + continue; + } + + fields[si].attrib = tbl->cols[i].attr_id; + if(tbl->cols[i].flags & KHUI_CW_COL_SORT_DEC) + fields[si].order = KCDB_CRED_COMP_DECREASING; + else + fields[si].order = KCDB_CRED_COMP_INCREASING; + + /* special case. if we are sorting by name, we group + initial tickets before non-initial tickets. + + Also, if we are sorting by credential type name, then + we allow the primary credential type first before + others. */ + + if (fields[si].attrib == KCDB_ATTR_NAME || + fields[si].attrib == KCDB_ATTR_TYPE_NAME) + fields[si].order |= KCDB_CRED_COMP_INITIAL_FIRST; + + if(si >= n) + n = si+1; + } + } + + /* we assume that the sort order is sane */ + /*TODO: don't assume; check if the sort order is sane */ + + comp_order.nFields = n; + comp_order.fields = fields; + + kcdb_credset_sort(tbl->credset, + kcdb_cred_comp_generic, + (void *) &comp_order); + + /* also, if new credentials were added, initialize the UI flag + attribute to 0 */ + if(delta & KCDB_DELTA_ADD) { + khm_size s; + + kcdb_credset_get_size(tbl->credset, &s); + for(i=0;i< (int) s;i++) { + if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset, + (khm_int32) i, &hc))) + continue; /* lost a race */ + if(KHM_FAILED(kcdb_cred_get_attr(hc, khui_cw_flag_id, NULL, + NULL, NULL))) { + flags = 0; + kcdb_cred_set_attr(hc, khui_cw_flag_id, &flags, sizeof(flags)); + } + kcdb_cred_release(hc); + } + } + + /* refresh the per-identity information */ + for (i=0; i < (int) tbl->n_idents; i++) { + tbl->idents[i].credcount = 0; + tbl->idents[i].id_credcount = 0; + tbl->idents[i].init_credcount = 0; + tbl->idents[i].credtype_name[0] = L'\0'; + tbl->idents[i].credtype = KCDB_CREDTYPE_INVALID; + tbl->idents[i].ft_expire = IntToFt(0); + } + + kcdb_credset_apply(tbl->credset, cw_credset_iter_func, (void *) tbl); + + if (fields) + PFREE(fields); +} + +void +cw_del_outline(khui_credwnd_outline *o) { + khui_credwnd_outline * c; + if(!o) + return; + + /* the outline object is still in a list */ + if(o->next || o->prev) + return; + + if(o->header) + PFREE(o->header); + + if ((o->flags & KHUI_CW_O_DATAALLOC) && + o->data) + PFREE(o->data); + + if ((o->flags & KHUI_CW_O_RELIDENT) && + o->data) + kcdb_identity_release((khm_handle) o->data); + + LPOP(&(o->children), &c); + while(c) { + cw_del_outline(c); + LPOP(&(o->children), &c); + } + + ZeroMemory(o, sizeof(*o)); + PFREE(o); +} + +khui_credwnd_outline * +cw_new_outline_node(wchar_t * heading) { + khui_credwnd_outline * o; + size_t cblen; + + o = PMALLOC(sizeof(khui_credwnd_outline)); + ZeroMemory(o, sizeof(khui_credwnd_outline)); + + if(SUCCEEDED(StringCbLength(heading, KHUI_MAXCB_HEADING, &cblen))) { + cblen += sizeof(wchar_t); + o->header = PMALLOC(cblen); + StringCbCopy(o->header, cblen, heading); + } + o->start = -1; + + return o; +} + +/* buf is a handle to a credential or an identity. the kcdb_buf_* + functions work with either. */ +khm_int32 +cw_get_buf_exp_flags(khui_credwnd_tbl * tbl, khm_handle buf) +{ + khm_int32 flags; + long s; + FILETIME ft_expire; + FILETIME ft_current; + FILETIME ft_difference; + khm_size cbsize; + + cbsize = sizeof(ft_expire); + if(KHM_FAILED(kcdb_buf_get_attr(buf, KCDB_ATTR_EXPIRE, NULL, + &ft_expire, &cbsize))) + return 0; + + GetSystemTimeAsFileTime(&ft_current); + ft_difference = FtSub(&ft_expire, &ft_current); + + s = FtIntervalToSeconds(&ft_difference); + + flags = 0; + if(s < 0) + flags = CW_EXPSTATE_EXPIRED; + else if(s < tbl->threshold_critical) + flags = CW_EXPSTATE_CRITICAL; + else if(s < tbl->threshold_warn) + flags = CW_EXPSTATE_WARN; + else + flags = CW_EXPSTATE_NONE; + + return flags; +} + +VOID CALLBACK +cw_timer_proc(HWND hwnd, + UINT uMsg, + UINT_PTR idEvent, + DWORD dwTime) +{ + khui_credwnd_tbl * tbl; + khui_credwnd_row * r; + khm_int32 nflags; + int nr; + long ms; + FILETIME ft; + khm_size cbsize; + int timer_set = 0; + + KillTimer(hwnd, idEvent); + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return; + + r = (khui_credwnd_row *) idEvent; + nr = (int)(r - tbl->rows); + + if(nr < 0 || nr >= tbl->n_rows) + return; + + r->flags &= ~KHUI_CW_ROW_TIMERSET; + + if(r->flags & KHUI_CW_ROW_CRED) { + + nflags = cw_get_buf_exp_flags(tbl, (khm_handle) r->data); + if((r->flags & CW_EXPSTATE_MASK) != nflags) { + /* flags have changed */ + /* the outline needs to be updated */ + cw_update_outline(tbl); + InvalidateRect(tbl->hwnd, NULL, FALSE); + } else { + /* just invalidate the row */ + RECT rc,rr,ri; + + GetClientRect(tbl->hwnd, &rc); + rc.top += tbl->header_height; + + rr = r->r_ext; + OffsetRect(&rr, 0, tbl->header_height - tbl->scr_top); + + if(IntersectRect(&ri, &rc, &rr)) + InvalidateRect(tbl->hwnd, &ri, FALSE); + + cbsize = sizeof(ft); + if(KHM_SUCCEEDED(kcdb_cred_get_attr((khm_handle) r->data, + KCDB_ATTR_TIMELEFT, NULL, + &ft, &cbsize))) { + ms = FtIntervalMsToRepChange(&ft); + if(ms > 0) { + SetTimer(tbl->hwnd, (UINT_PTR) r, ms + 100, cw_timer_proc); + timer_set = 1; + } + } + + if (timer_set) + r->flags |= KHUI_CW_ROW_TIMERSET; + } + } else { + khui_credwnd_outline * o; + khui_credwnd_ident * cwi; + FILETIME ft_now; + + o = (khui_credwnd_outline *) r->data; + + /* we only handle timers for header rows if : + + 1. The table is displaying expanded identity information + 2. The row displaying an expanded view + 3. The relevant outline object is for an identity + + If these conditions aren't met, it is because we lost a + race killing this timer while switching modes. + */ + if (!(tbl->flags & KHUI_CW_TBL_EXPIDENT) || + !(r->flags & KHUI_CW_ROW_EXPVIEW) || + !(o->attr_id == KCDB_ATTR_ID)) + + return; + + nflags = cw_get_buf_exp_flags(tbl, (khm_handle) o->data); + if ((o->flags & CW_EXPSTATE_MASK) != nflags) { + cw_update_outline(tbl); + InvalidateRect(tbl->hwnd, NULL, FALSE); + } else { + RECT rc, rr, ri; + + GetClientRect(tbl->hwnd, &rc); + rc.top += tbl->header_height; + + rr = r->r_ext; + OffsetRect(&rr, 0, tbl->header_height - tbl->scr_top); + + if (IntersectRect(&ri, &rc, &rr)) + InvalidateRect(tbl->hwnd, &ri, FALSE); + + cwi = cw_find_ident(tbl, o->data); + + GetSystemTimeAsFileTime(&ft_now); + if (CompareFileTime(&cwi->ft_expire, &ft_now) > 0) { + ft = FtSub(&cwi->ft_expire, &ft_now); + ms = FtIntervalMsToRepChange(&ft); + if (ms > 0) { + SetTimer(tbl->hwnd, (UINT_PTR) r, ms + 100, cw_timer_proc); + timer_set = 1; + } + } + + if (timer_set) + r->flags |= KHUI_CW_ROW_TIMERSET; + } + } +} + +void +cw_set_tbl_row_cred(khui_credwnd_tbl * tbl, + int row, + khm_handle cred, + int col) +{ + FILETIME ft; + long ms; + khm_size cbsize; + + if((int) tbl->n_total_rows <= row) { + /* we need to resize the allocation */ + khui_credwnd_row * newrows; + int newsize; + + newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT); + newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize); + memcpy(newrows, tbl->rows, sizeof(khui_credwnd_row) * tbl->n_rows); + PFREE(tbl->rows); + tbl->rows = newrows; + tbl->n_total_rows = newsize; + } + + tbl->rows[row].col = col; + tbl->rows[row].data = cred; + tbl->rows[row].flags = KHUI_CW_ROW_CRED; + + /* Set any required timer events */ + cbsize = sizeof(ft); + if(KHM_SUCCEEDED(kcdb_cred_get_attr(cred, KCDB_ATTR_TIMELEFT, NULL, &ft, &cbsize))) { + ms = FtIntervalMsToRepChange(&ft); + if(ms > 0) { + SetTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[row]), ms + 100, cw_timer_proc); + tbl->rows[row].flags |= KHUI_CW_ROW_TIMERSET; + } + } +} + +void +cw_set_tbl_row_header(khui_credwnd_tbl * tbl, + int row, int col, + khui_credwnd_outline * o) +{ + if((int) tbl->n_total_rows <= row) { + /* we need to resize the allocation */ + khui_credwnd_row * newrows; + int newsize; + + newsize = UBOUNDSS(row+1,KHUI_CW_ROW_INITIAL, KHUI_CW_ROW_INCREMENT); + newrows = PMALLOC(sizeof(khui_credwnd_row) * newsize); + memcpy(newrows, tbl->rows, sizeof(khui_credwnd_row) * tbl->n_rows); + PFREE(tbl->rows); + tbl->rows = newrows; + tbl->n_total_rows = newsize; + } + + tbl->rows[row].col = col; + tbl->rows[row].data = (khm_handle) o; + tbl->rows[row].flags = KHUI_CW_ROW_HEADER; + if(o->flags & KHUI_CW_O_SELECTED) + tbl->rows[row].flags |= KHUI_CW_ROW_SELECTED; + + /* if we are showing expanded identity information, we need to set + a timer so that we can update the identity row when the + identity changes. */ + if ((tbl->flags & KHUI_CW_TBL_EXPIDENT) && + tbl->cols[col].attr_id == KCDB_ATTR_ID_NAME) { + + khui_credwnd_ident * cwi; + + tbl->rows[row].flags |= KHUI_CW_ROW_EXPVIEW; + + cwi = cw_find_ident(tbl, o->data); + if (cwi && FtToInt(&cwi->ft_expire) != 0) { + FILETIME ft; + FILETIME ft_now; + + ft = cwi->ft_expire; + GetSystemTimeAsFileTime(&ft_now); + + if (CompareFileTime(&ft, &ft_now) > 0) { + long ms; + + ft = FtSub(&ft, &ft_now); + ms = FtIntervalMsToRepChange(&ft); + if (ms > 0) { + SetTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[row]), ms + 100, + cw_timer_proc); + tbl->rows[row].flags |= KHUI_CW_ROW_TIMERSET; + } + } + } + } +} + +static int +iwcscmp(const void * p1, const void * p2) { + const wchar_t * s1 = *(wchar_t **) p1; + const wchar_t * s2 = *(wchar_t **) p2; + + return wcscmp(s1, s2); +} + +#define MAX_GROUPING 256 + +static void +cw_update_outline(khui_credwnd_tbl * tbl) +{ + int i,j,n_rows; + int level; + int visible; + khm_size n_creds = 0; + khm_handle prevcred = NULL; + khm_handle thiscred = NULL; + /* grouping[0..n_grouping-1] are the columns that we are going to + group the display by. Say we are grouping by identity and then + by type, then grouping[0]=col# of identity and grouping[1]=col# + of type */ + khm_int32 grouping[MAX_GROUPING]; + khui_credwnd_outline * ol = NULL; + int n_grouping; + wchar_t buf[256]; + khm_size cbbuf; + khm_int32 flags; + int selected; + + /* this is called after calling cw_update_creds, so we assume + that the credentials are all loaded and sorted according to + grouping rules */ + + /* if the columns have changed, then any outline info we have + cached are unreliable */ + if(tbl->flags & KHUI_CW_TBL_COL_DIRTY) { + khui_credwnd_outline * o; + LPOP(&(tbl->outline), &o); + while(o) { + cw_del_outline(o); + LPOP(&(tbl->outline), &o); + } + tbl->n_rows = 0; + } + + /* Otherwise, we should reset the outline indices. Just the first + level is enough */ + if (tbl->outline) { + khui_credwnd_outline * o; + + o = tbl->outline; + while(o) { + o->start = -1; + o = LNEXT(o); + } + } + + /* determine the grouping order */ + n_grouping = min(MAX_GROUPING, tbl->n_cols); + for(i=0; i < n_grouping; i++) + grouping[i] = -1; + n_grouping = 0; + + for(i=0; i < (int) tbl->n_cols; i++) { + /* since cw_update_creds has run, the KHUI_CW_COL_GROUP flag + only exists for columns that has a valid sort_index */ + if(tbl->cols[i].flags & KHUI_CW_COL_GROUP) { +#ifdef DEBUG + assert(tbl->cols[i].sort_index < MAX_GROUPING); +#endif + if (tbl->cols[i].sort_index >= MAX_GROUPING) + continue; + + grouping[tbl->cols[i].sort_index] = i; + if(n_grouping <= tbl->cols[i].sort_index) + n_grouping = tbl->cols[i].sort_index + 1; + } + } + + /* if we have sorted by an index without grouping by it, we can't + establish any grouping beyond that index. */ + for(i=0; i < n_grouping; i++) { + if(grouping[i] == -1) + break; + } + n_grouping = i; + + if(!tbl->rows) { + /* we haven't allocated memory yet */ + tbl->n_total_rows = KHUI_CW_ROW_INITIAL; + tbl->n_rows = 0; + tbl->rows = PMALLOC(sizeof(khui_credwnd_row) * tbl->n_total_rows); + } else { + /* kill any pending timers */ + for(i=0; i < (int) tbl->n_rows; i++) + if(tbl->rows[i].flags & KHUI_CW_ROW_TIMERSET) { + KillTimer(tbl->hwnd, (UINT_PTR) &(tbl->rows[i])); + tbl->rows[i].flags &= ~KHUI_CW_ROW_TIMERSET; + } + } + + if(KHM_FAILED(kcdb_credset_get_size(tbl->credset, &n_creds))) + goto _exit; + + n_rows = 0; + prevcred = NULL; + ol = NULL; + + for(i=0; i < (int) n_creds; i++) { + if(KHM_FAILED(kcdb_credset_get_cred(tbl->credset, i, &thiscred))) + continue; + + /* if this credential appears to be the same as another for + this view, we skip it. */ + if(prevcred && n_grouping > 0) { + for(j=0; j < (int) tbl->n_cols; j++) { + if(kcdb_creds_comp_attr(prevcred, thiscred, + tbl->cols[j].attr_id)) + break; + } + + if(j >= (int) tbl->n_cols) { + if (n_rows > 0) { + tbl->rows[n_rows - 1].idx_end = i; + } + continue; + } + } + + if(!prevcred) + level = 0; + else { + for(j=0; j < n_grouping; j++) { + /* determine the grouping level at which thiscred + differs from prevcred */ + if(kcdb_creds_comp_attr(prevcred,thiscred, + tbl->cols[grouping[j]].attr_id)) + break; + } + level = j; + } + + /* now we have to walk up until we get to the parent of the + outline level we should be in */ + while(ol && ol->level >= level) { + + /* we are closing this outline level. */ + ol->length = n_rows - ol->start; + ol->idx_end = i - 1; + + if ((ol->flags & KHUI_CW_O_SELECTED) && + ol->length > 0) { + tbl->n_rows = n_rows; + cw_select_row_creds(tbl, ol->start, TRUE); + } + + ol = TPARENT(ol); + } + + if(ol) { + visible = (ol->flags & KHUI_CW_O_VISIBLE) && + (ol->flags & KHUI_CW_O_EXPAND); + selected = !!(ol->flags & KHUI_CW_O_SELECTED); + } else { + visible = TRUE; + selected = FALSE; + } + + /* now ol points to an outline node at the next highest level + or is NULL if level = 0 */ + + for(j=level; j < n_grouping; j++) { + khui_credwnd_outline * to; + /* now we search for an outline object at the next level + which matches the heading */ + cbbuf = sizeof(buf); + buf[0] = L'\0'; + if(KHM_FAILED + (kcdb_cred_get_attr_string(thiscred, + tbl->cols[grouping[j]].attr_id, + buf, &cbbuf, 0))) { + cbbuf = sizeof(wchar_t); + buf[0] = L'\0'; + } + + if(ol) + to = TFIRSTCHILD(ol); + else + to = tbl->outline; + + while(to) { + if(!wcscmp(buf, to->header)) + break; + to = LNEXT(to); + } + + if(to) { + /* found it */ + ol = to; + } else { + /* not found. create */ + to = cw_new_outline_node(buf); + if(ol) { + TADDCHILD(ol, to); + } else { + LPUSH(&(tbl->outline), to); + } + ol = to; + ol->flags = KHUI_CW_O_EXPAND; + ol->level = j; + ol->col = grouping[j]; + + if(tbl->cols[grouping[j]].attr_id == KCDB_ATTR_ID_NAME) { + khm_handle h; + if(KHM_SUCCEEDED(kcdb_identity_create(buf, 0, &h))) { + ol->attr_id = KCDB_ATTR_ID; + ol->data = (void *) h; + + /* the outline only lasts as long as the + credential, and the credential has a hold + on the identity. */ + kcdb_identity_release(h); + } + else + ol->data = 0; + } else if(tbl->cols[grouping[j]].attr_id == + KCDB_ATTR_TYPE_NAME) { + khm_int32 t; + + ol->attr_id = KCDB_ATTR_TYPE; + if(KHM_SUCCEEDED(kcdb_cred_get_type(thiscred, &t))) + ol->data = (void *)(ssize_t) t; + else + ol->data = (void *)(ssize_t) KCDB_CREDTYPE_INVALID; + } else { + khm_int32 rv; + khm_int32 alt_id; + kcdb_attrib * attrib; + + rv = + kcdb_attrib_get_info(tbl->cols[grouping[j]].attr_id, + &attrib); + assert(KHM_SUCCEEDED(rv)); + + if (attrib->flags & KCDB_ATTR_FLAG_ALTVIEW) + alt_id = attrib->alt_id; + else + alt_id = tbl->cols[grouping[j]].attr_id; + + ol->attr_id = alt_id; + + kcdb_attrib_release_info(attrib); + + rv = kcdb_cred_get_attr(thiscred, + alt_id, + NULL, + NULL, + &cbbuf); + if (rv != KHM_ERROR_TOO_LONG || cbbuf == 0) { + ol->data = NULL; + } else { + ol->data = PMALLOC(cbbuf); + assert(ol->data); + rv = kcdb_cred_get_attr(thiscred, + alt_id, + NULL, + ol->data, + &cbbuf); + assert(KHM_SUCCEEDED(rv)); + ol->cb_data = cbbuf; + ol->flags |= KHUI_CW_O_DATAALLOC; + } + } + } + + /* now ol points at the node at level j we want to be + in */ + ol->start = n_rows; + ol->length = 0; + ol->idx_start = i; + ol->idx_end = i; + ol->flags &= ~(CW_EXPSTATE_MASK | + KHUI_CW_O_SHOWFLAG | + KHUI_CW_O_STICKY | + KHUI_CW_O_EMPTY); + + /* if the outline node is for an identity, then we have to + check the expiration state for the identity. */ + + if (ol->attr_id == KCDB_ATTR_ID) { + khm_handle ident = (khm_handle) ol->data; + + flags = cw_get_buf_exp_flags(tbl, ident); + + if (flags) { + ol->flags |= flags; + ol->flags |= KHUI_CW_O_SHOWFLAG; + } else if (grouping[j] == tbl->n_cols - 1) { + /* if we aren't showing any creds under this + outline level, we should also show any + flags. */ + ol->flags |= KHUI_CW_O_SHOWFLAG; + } + } + + if (grouping[j] == tbl->n_cols - 1) { + ol->flags |= KHUI_CW_O_NOOUTLINE; + } else { + ol->flags &= ~KHUI_CW_O_NOOUTLINE; + } + + if(selected) { + ol->flags |= KHUI_CW_O_SELECTED; + } + if(visible) { + cw_set_tbl_row_header(tbl, n_rows, grouping[j], ol); + n_rows ++; + ol->flags |= KHUI_CW_O_VISIBLE; + } else { + ol->flags &= ~KHUI_CW_O_VISIBLE; + } + visible = visible && (ol->flags & KHUI_CW_O_EXPAND); + selected = (selected || (ol->flags & KHUI_CW_O_SELECTED)); + } + + /* we need to do this here too just in case we were already at + the level we were supposed to be in */ + if (ol) { + visible = visible && (ol->flags & KHUI_CW_O_EXPAND); + selected = (selected || (ol->flags & KHUI_CW_O_SELECTED)); + } + + if(visible && n_grouping > 0 && + grouping[n_grouping - 1] < tbl->n_cols - 1) { + khm_int32 c_flags; + + cw_set_tbl_row_cred(tbl, n_rows, thiscred, + grouping[n_grouping-1]); + + flags = cw_get_buf_exp_flags(tbl, thiscred); + if(flags) { + tbl->rows[n_rows].flags |= flags; + } + + kcdb_cred_get_flags(thiscred, &c_flags); + if(selected || + (c_flags & KCDB_CRED_FLAG_SELECTED)) { + tbl->rows[n_rows].flags |= KHUI_CW_ROW_SELECTED; + } + + tbl->rows[n_rows].idx_start = i; + tbl->rows[n_rows].idx_end = i; + + n_rows++; + } + + if(prevcred) + kcdb_cred_release(prevcred); + prevcred = thiscred; + } + + while(ol) { + /* close all open outline levels */ + + ol->length = n_rows - ol->start; + ol->idx_end = i - 1; + + if ((ol->flags & KHUI_CW_O_SELECTED) && + ol->length > 0) { + tbl->n_rows = n_rows; + cw_select_row_creds(tbl, ol->start, TRUE); + } + + ol = TPARENT(ol); + } + + if(prevcred) { + kcdb_cred_release(prevcred); + prevcred = NULL; + } + + /* Add any default identities with no credentials and sticky + identities that we haven't seen yet */ + if (n_grouping > 0 && + tbl->cols[grouping[0]].attr_id == KCDB_ATTR_ID_NAME) { + + khui_credwnd_outline * o; + wchar_t * idnames = NULL; + wchar_t * t; + khm_size n_idents; + khm_size cb_names; + wchar_t ** idarray = NULL; + int i; + + khm_int32 and_flags = 0; + khm_int32 eq_flags = 0; + + /* see if the default identity is in the list */ + { + khm_handle id_def = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_int32 flags; + + if (KHM_FAILED(kcdb_identity_get_default(&id_def))) { + goto done_with_defident; + } + + kcdb_identity_get_flags(id_def, &flags); + cb = sizeof(idname); + kcdb_identity_get_name(id_def, idname, &cb); + + for (o = tbl->outline; o; o = LNEXT(o)) { + if (!wcscmp(idname, o->header)) + break; + } + + if (o == NULL) { + o = cw_new_outline_node(idname); + LPUSH(&tbl->outline, o); + o->flags = KHUI_CW_O_RELIDENT; + o->level = 0; + o->col = grouping[0]; + o->data = id_def; + o->attr_id = KCDB_ATTR_ID; + o->start = -1; + } else { + kcdb_identity_release(id_def); + } + + if (o->start != -1) + goto done_with_defident; + + o->flags &= ~(KHUI_CW_O_SHOWFLAG | + KHUI_CW_O_NOOUTLINE | + KHUI_CW_O_STICKY); + o->flags |= KHUI_CW_O_EXPAND | KHUI_CW_O_VISIBLE | KHUI_CW_O_EMPTY; + + if (flags & KCDB_IDENT_FLAG_STICKY) + o->flags |= KHUI_CW_O_STICKY; + + o->start = n_rows; + o->length = 1; + o->idx_start = (khm_size) -1; + o->idx_end = (khm_size) -1; + + if (grouping[0] == tbl->n_cols - 1) + o->flags |= KHUI_CW_O_NOOUTLINE; + + cw_set_tbl_row_header(tbl, n_rows, grouping[0], o); + + n_rows ++; + + done_with_defident: + ; + } + + if (tbl->view_all_idents) { + and_flags = 0; + eq_flags = 0; + } else { + and_flags = KCDB_IDENT_FLAG_STICKY; + eq_flags = KCDB_IDENT_FLAG_STICKY; + } + + if (kcdb_identity_enum(and_flags, + eq_flags, + NULL, + &cb_names, + &n_idents) != KHM_ERROR_TOO_LONG || + n_idents == 0 || + cb_names == 0) + goto _cleanup_sticky; + + idnames = PMALLOC(cb_names); + idarray = PMALLOC(n_idents * sizeof(*idarray)); +#ifdef DEBUG + assert(idnames); + assert(idarray); +#endif + + if (KHM_FAILED(kcdb_identity_enum(and_flags, + eq_flags, + idnames, + &cb_names, + &n_idents))) + goto _cleanup_sticky; + + for (i=0, t=idnames; t && *t; t = multi_string_next(t), i++) { + idarray[i] = t; + } + + qsort(idarray, n_idents, sizeof(*idarray), iwcscmp); + + for (i=0; i < (int) n_idents; i++) { + khm_handle h; + khm_int32 f_sticky; + khm_int32 flags; + + if (KHM_FAILED(kcdb_identity_create(idarray[i], + KCDB_IDENT_FLAG_CREATE, &h))) + continue; + + kcdb_identity_get_flags(h, &flags); + + if (flags & KCDB_IDENT_FLAG_STICKY) + f_sticky = KHUI_CW_O_STICKY; + else + f_sticky = 0; + + for (o = tbl->outline; o; o = LNEXT(o)) { + if (!wcscmp(idarray[i], o->header)) + break; + } + + if (o) { + /* found it */ + if (o->start != -1) /* already visible? */ + continue; + o->flags &= (KHUI_CW_O_RELIDENT | KHUI_CW_O_SELECTED); + o->flags |= f_sticky | KHUI_CW_O_VISIBLE | KHUI_CW_O_EMPTY; + + if (!kcdb_identity_is_equal(o->data, h)) { + if (o->flags & KHUI_CW_O_RELIDENT) + kcdb_identity_release(o->data); + o->data = h; + o->flags |= KHUI_CW_O_RELIDENT; + kcdb_identity_hold(h); + } + } else { + /* not found. create */ + o = cw_new_outline_node(idarray[i]); + LPUSH(&tbl->outline, o); + o->flags = f_sticky | KHUI_CW_O_VISIBLE | KHUI_CW_O_EMPTY | KHUI_CW_O_RELIDENT; + o->level = 0; + o->col = grouping[0]; + o->data = h; + kcdb_identity_hold(h); + o->attr_id = KCDB_ATTR_ID; + } + + if (grouping[0] == tbl->n_cols - 1) + o->flags |= KHUI_CW_O_NOOUTLINE; + + kcdb_identity_release(h); + + o->flags &= ~KHUI_CW_O_EXPAND; + o->start = n_rows; + o->length = 1; + o->idx_start = (khm_size) -1; + o->idx_end = (khm_size) -1; + + cw_set_tbl_row_header(tbl, n_rows, grouping[0], o); + + n_rows ++; + } + + _cleanup_sticky: + if (idnames) + PFREE(idnames); + if (idarray) + PFREE(idarray); + } + + tbl->n_rows = n_rows; + tbl->flags |= KHUI_CW_TBL_ROW_DIRTY; + + tbl->flags &= ~KHUI_CW_TBL_COL_DIRTY; + + if (tbl->cursor_row >= tbl->n_rows) + tbl->cursor_row = tbl->n_rows - 1; + if (tbl->cursor_row < 0) + tbl->cursor_row = 0; + +_exit: + + { + khm_handle def_ident = NULL; + khm_int32 def_expstate = 0; + khm_boolean def_empty = TRUE; + + kcdb_identity_get_default(&def_ident); + if (def_ident) { + khui_credwnd_ident * cwi; + + cwi = cw_find_ident(tbl, def_ident); + if (cwi) { + def_empty = (cwi->id_credcount == 0); + } + + def_expstate = cw_get_buf_exp_flags(tbl, def_ident); + } + + if (def_empty) + khm_notify_icon_expstate(KHM_NOTIF_EMPTY); + else if ((def_expstate & CW_EXPSTATE_EXPIRED) == CW_EXPSTATE_EXPIRED) + khm_notify_icon_expstate(KHM_NOTIF_EXP); + else if ((def_expstate & CW_EXPSTATE_WARN) == CW_EXPSTATE_WARN || + (def_expstate & CW_EXPSTATE_CRITICAL) == CW_EXPSTATE_CRITICAL) + khm_notify_icon_expstate(KHM_NOTIF_WARN); + else + khm_notify_icon_expstate(KHM_NOTIF_OK); + } +} + +void +cw_unload_view(khui_credwnd_tbl * tbl) +{ +#define SafeDeleteObject(o) \ + do { \ + if(o) { \ + DeleteObject(o); \ + o = NULL; \ + } \ + } while(0) + + SafeDeleteObject(tbl->hf_header); + SafeDeleteObject(tbl->hf_normal); + SafeDeleteObject(tbl->hf_bold); + SafeDeleteObject(tbl->hf_bold_header); + + SafeDeleteObject(tbl->hb_grey); + SafeDeleteObject(tbl->hb_normal); + SafeDeleteObject(tbl->hb_s); + + SafeDeleteObject(tbl->hb_hdr_bg); + SafeDeleteObject(tbl->hb_hdr_bg_crit); + SafeDeleteObject(tbl->hb_hdr_bg_exp); + SafeDeleteObject(tbl->hb_hdr_bg_warn); + SafeDeleteObject(tbl->hb_hdr_bg_cred); + + SafeDeleteObject(tbl->hb_hdr_bg_s); + SafeDeleteObject(tbl->hb_hdr_bg_crit_s); + SafeDeleteObject(tbl->hb_hdr_bg_exp_s); + SafeDeleteObject(tbl->hb_hdr_bg_warn_s); + SafeDeleteObject(tbl->hb_hdr_bg_cred_s); + +#undef SafeDeleteObject + + if (tbl->hi_lg_ident) { + DestroyIcon(tbl->hi_lg_ident); + tbl->hi_lg_ident = NULL; + } + + if(tbl->credset) { + kcdb_credset_delete(tbl->credset); + tbl->credset = NULL; + } + if(tbl->ilist) { + khui_delete_ilist(tbl->ilist); + tbl->ilist = NULL; + } + + if(tbl->cols) { + int i; + + for(i=0; i < tbl->n_cols; i++) { + if(tbl->cols[i].title) + PFREE(tbl->cols[i].title); + Header_DeleteItem(tbl->hwnd_header, 0); + + if (tbl->cols[i].attr_id >= 0 && + tbl->cols[i].attr_id <= KCDB_ATTR_MAX_ID && + attr_to_action[tbl->cols[i].attr_id]) { + + khui_check_action(attr_to_action[tbl->cols[i].attr_id], FALSE); + + } + } + PFREE(tbl->cols); + tbl->cols = NULL; + tbl->n_cols = 0; + tbl->n_total_cols = 0; + + kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0); + } + + if(tbl->rows) { + PFREE(tbl->rows); + tbl->rows = NULL; + tbl->n_rows = 0; + tbl->n_total_rows = 0; + } + + khui_delete_bitmap(&tbl->kbm_logo_shade); + + if (tbl->csp_view) { + khc_close_space(tbl->csp_view); + tbl->csp_view = NULL; + } + + tbl->cell_height = 0; /* recalculate cell height next time */ + + if (tbl->idents) { + khm_size i; + + for (i=0; i < tbl->n_idents; i++) { + if (tbl->idents[i].ident) { + kcdb_identity_release(tbl->idents[i].ident); + } + } + + PFREE(tbl->idents); + tbl->idents = NULL; + tbl->n_idents = 0; + tbl->nc_idents = 0; + } +} + +void +cw_hditem_from_tbl_col(khui_credwnd_col * col, HDITEM *phi) +{ + size_t cchsize; + + phi->mask = HDI_FORMAT | HDI_LPARAM | HDI_WIDTH; + if(cw_is_custom_attr(col->attr_id)) { + if(col->attr_id == CW_CA_FLAGS) { + phi->fmt = 0; + } else if(col->attr_id == CW_CA_TYPEICON) { + phi->fmt = 0; + } else { + /* what the? */ + /*TODO: throw up and die */ + } + } else { + phi->mask |= HDI_TEXT; + phi->pszText = col->title; + StringCchLength(col->title, KCDB_MAXCCH_SHORT_DESC, &cchsize); + phi->cchTextMax = (int) cchsize; + phi->fmt = HDF_CENTER | HDF_STRING; + } + phi->lParam = col->attr_id; +#if (_WIN32_WINNT >= 0x501) + if (IS_COMMCTL6()) { + if(col->flags & KHUI_CW_COL_SORT_INC) { + phi->fmt |= HDF_SORTUP; + } else if(col->flags & KHUI_CW_COL_SORT_DEC) { + phi->fmt |= HDF_SORTDOWN; + } + } +#endif + if(col->width < 0) { + /*TODO: come up with a better way to handle this case */ + col->width = 200; + } + phi->cxy = col->width; +} + +int +cw_get_cell_height(HDC hdc, HFONT hf) { + SIZE size; + size_t cbbuf; + wchar_t buf[64]; + HFONT hfold = NULL; + + if (hf) + hfold = SelectFont(hdc, hf); + + LoadString(khm_hInstance, IDS_SAMPLE_STRING, buf, sizeof(buf)/sizeof(buf[0])); + StringCchLength(buf, sizeof(buf)/sizeof(buf[0]), &cbbuf); + GetTextExtentPoint32(hdc, buf, (int) cbbuf, &size); + + if (hf) + SelectFont(hdc, hfold); + + return size.cy; +} + +int +cw_update_header_column_width(khui_credwnd_tbl * tbl, int c) { + int idx; + HDITEM hi; + +#ifdef DEBUG + assert(c >= 0 && c < tbl->n_cols); +#endif + + if (tbl->hwnd_header == NULL) + return 0; + + idx = Header_OrderToIndex(tbl->hwnd_header, c); + ZeroMemory(&hi, sizeof(hi)); + hi.mask = HDI_WIDTH; + hi.cxy = tbl->cols[c].width; + return Header_SetItem(tbl->hwnd_header, idx, &hi); +} + +/* returns a bitmask indicating which measures were changed */ +int +cw_update_extents(khui_credwnd_tbl * tbl, + khm_boolean update_scroll) { + int ext_x = 0; + int ext_y = 0; + int i; + int filler_col = -1; + int fill_adjusted = 0; + + recompute_columns: + + ext_x = 0; + for(i=0; i < (int) tbl->n_cols; i++) { + tbl->cols[i].x = ext_x; + if (tbl->cols[i].flags & KHUI_CW_COL_FILLER) { + if (filler_col == -1) + filler_col = i; + } + ext_x += tbl->cols[i].width; + } + + if (filler_col != -1 && !fill_adjusted) { + RECT r; + int delta; + + GetClientRect(tbl->hwnd, &r); + + /* we decrement the width so that the width data area is + strictly less than the width of the client area. Windows + doesn't disable a scrollbar unless the range is strictly + less than the page size. */ + delta = ((r.right - r.left) - 1) - ext_x; + + if (tbl->cols[filler_col].width + delta <= GetSystemMetrics(SM_CXSMICON)) { + tbl->cols[filler_col].width = GetSystemMetrics(SM_CXICON); + } else { + tbl->cols[filler_col].width += delta; + } + + cw_update_header_column_width(tbl, filler_col); + + fill_adjusted = 1; + goto recompute_columns; + } + + if(!tbl->cell_height) { + HDC dc; + int maxheight = 0; + int height; + + dc = GetWindowDC(tbl->hwnd); + + maxheight = cw_get_cell_height(dc, tbl->hf_normal); + height = cw_get_cell_height(dc, tbl->hf_bold); + if (height > maxheight) + maxheight = height; + height = cw_get_cell_height(dc, tbl->hf_header); + if (height > maxheight) + maxheight = height; + height = cw_get_cell_height(dc, tbl->hf_bold_header); + if (height > maxheight) + maxheight = height; + + ReleaseDC(tbl->hwnd, dc); + + tbl->cell_height = height + tbl->vpad * 2; + } + + if (tbl->flags & KHUI_CW_TBL_EXPIDENT) { + RECT r; + + ext_y = 0; + r.left = 0; + r.right = ext_x; + + for (i=0; i < (int) tbl->n_rows; i++) { + r.top = ext_y; + if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW) { + ext_y += tbl->cell_height * CW_EXP_ROW_MULT; + } else { + ext_y += tbl->cell_height; + } + r.bottom = ext_y; + tbl->rows[i].r_ext = r; + } + } else { + RECT r; + + r.left = 0; + r.right = ext_x; + + for (i=0; i < (int) tbl->n_rows; i++) { + r.top = i * tbl->cell_height; + r.bottom = r.top + tbl->cell_height; + + tbl->rows[i].r_ext = r; + } + + ext_y = (int) tbl->n_rows * tbl->cell_height; + } + + tbl->ext_width = ext_x; + tbl->ext_height = ext_y; + + /* useful in the future when implementing variable height rows. + The KHUI_CW_TBL_ROW_DIRTY bit indicates that the rows have + changed and that the y extent has to be recalculated. */ + tbl->flags &= ~KHUI_CW_TBL_ROW_DIRTY; + + if(update_scroll) { + RECT r; + int cl_w; + int cl_h; + SCROLLINFO si; + WINDOWPOS pw; + HDLAYOUT hdl; + + /* update the header control first */ + + retry_update_scroll: + GetClientRect(tbl->hwnd, &r); + + cl_w = r.right - r.left; + cl_h = (r.bottom - r.top); + cl_h -= tbl->header_height; + + if(tbl->scr_top < 0 || tbl->ext_height < cl_h) + tbl->scr_top = 0; + else if(tbl->scr_top > tbl->ext_height - cl_h) + tbl->scr_top = tbl->ext_height - cl_h; + if(tbl->scr_left < 0 || tbl->ext_width < cl_w) + tbl->scr_left = 0; + else if(tbl->scr_left > tbl->ext_width - cl_w) + tbl->scr_left = tbl->ext_width - cl_w; + + /* adjustments for scrolling */ + r.left -= tbl->scr_left; + r.right = max(tbl->ext_width + r.left, r.right); + + hdl.prc = &r; + hdl.pwpos = &pw; + + Header_Layout(tbl->hwnd_header, &hdl); + + if(tbl->header_height == 0) { + tbl->header_height = pw.cy; + goto retry_update_scroll; + } else + tbl->header_height = pw.cy; + + SetWindowPos( + tbl->hwnd_header, + pw.hwndInsertAfter, + pw.x, + pw.y, + pw.cx, + pw.cy, + pw.flags); + + si.cbSize = sizeof(si); + si.nMin = 0; + si.nMax = tbl->ext_height; + si.nPage = cl_h; + si.nPos = tbl->scr_top; + si.fMask = SIF_ALL | SIF_DISABLENOSCROLL; + SetScrollInfo(tbl->hwnd, SB_VERT, &si, TRUE); + + si.cbSize = sizeof(si); + si.nMin = 0; + si.nMax = tbl->ext_width; + si.nPage = cl_w; + si.nPos = tbl->scr_left; + si.fMask = SIF_ALL | SIF_DISABLENOSCROLL; + SetScrollInfo(tbl->hwnd, SB_HORZ, &si, TRUE); + } + + return 0; +} + +void +cw_insert_header_cols(khui_credwnd_tbl * tbl) { + HWND hdr; + HDITEM hi; + int i; + + hdr = tbl->hwnd_header; + + for(i=0; i < (int) tbl->n_cols; i++) { + cw_hditem_from_tbl_col(&(tbl->cols[i]), &hi); + Header_InsertItem(hdr, 512, &hi); + } +} + +#define CW_ER_BLANK 0 +#define CW_ER_GREY 1 +#define CW_ER_SEL 2 + +#pragma warning(push) +#pragma warning(disable: 4701) +void +cw_erase_rect(HDC hdc, + khui_credwnd_tbl * tbl, + RECT * r_wnd, + RECT * r_erase, + int type) +{ + RECT rlogo; + RECT ri; + RECT t; + BOOL rie; + HBRUSH hbr; + + switch(type) { + case CW_ER_BLANK: + hbr = tbl->hb_normal; + break; + + case CW_ER_GREY: + hbr = tbl->hb_grey; + break; + + case CW_ER_SEL: + hbr = tbl->hb_s; + break; + + default: + return; + } + + if(tbl->kbm_logo_shade.cx != -1 && type == CW_ER_BLANK) { + rlogo.left = r_wnd->right - tbl->kbm_logo_shade.cx; + rlogo.right = r_wnd->right; + rlogo.top = r_wnd->bottom - tbl->kbm_logo_shade.cy; + rlogo.bottom = r_wnd->bottom; + if (bHideWatermarks) {rie = FALSE;} + else {rie = IntersectRect(&ri, r_erase, &rlogo);} + } else { + ZeroMemory(&rlogo, sizeof(rlogo)); + ZeroMemory(&ri, sizeof(ri)); + rie = FALSE; + } + + if(!rie) { + FillRect(hdc, r_erase, hbr); + } else { + HDC hdcb = CreateCompatibleDC(hdc); + HBITMAP hbmold = SelectObject(hdcb, tbl->kbm_logo_shade.hbmp); + + BitBlt(hdc, ri.left, ri.top, ri.right - ri.left, ri.bottom - ri.top, + hdcb, ri.left - rlogo.left, ri.top - rlogo.top, SRCCOPY); + + SelectObject(hdcb, hbmold); + DeleteDC(hdcb); + + if(r_erase->top < ri.top && r_erase->left < ri.left) { + t.left = r_erase->left; + t.top = r_erase->top; + t.right = ri.left; + t.bottom = ri.top; + FillRect(hdc, &t, hbr); + } + + if(r_erase->left < ri.left) { + t.left = r_erase->left; + t.top = ri.top; + t.right = ri.left; + t.bottom = ri.bottom; + FillRect(hdc, &t, hbr); + } + + if(r_erase->top < ri.top) { + t.left = ri.left; + t.top = r_erase->top; + t.right = ri.right; + t.bottom = ri.top; + FillRect(hdc, &t, hbr); + } + } +} +#pragma warning(pop) + +void +cw_draw_header(HDC hdc, + khui_credwnd_tbl * tbl, + int row, + RECT * r) +{ + int colattr; + HPEN pl, pold; + khui_credwnd_row * cr; + khui_credwnd_outline * o; + int selected = 0; + khm_int32 idf = 0; + khui_credwnd_ident * cwi = NULL; + + /* each header consists of a couple of widgets and some text */ + /* we need to figure out the background color first */ + + cr = &(tbl->rows[row]); + o = (khui_credwnd_outline *) cr->data; + + colattr = tbl->cols[cr->col].attr_id; + + if (colattr == KCDB_ATTR_ID_NAME) { + khm_handle ident = o->data; + + kcdb_identity_get_flags(ident, &idf); + cwi = cw_find_ident(tbl, ident); + } + + selected = o->flags & KHUI_CW_O_SELECTED; + + { + HBRUSH hbr; + + if(selected) { + if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_EXPIRED) + hbr = tbl->hb_hdr_bg_exp_s; + else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_CRITICAL) + hbr = tbl->hb_hdr_bg_crit_s; + else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_WARN) + hbr = tbl->hb_hdr_bg_warn_s; + else if ((colattr == KCDB_ATTR_ID_NAME) && !(o->flags & KHUI_CW_O_EMPTY) && + cwi && cwi->id_credcount > 0) + hbr = tbl->hb_hdr_bg_cred_s; + else + hbr = tbl->hb_hdr_bg_s; + } else { + if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_EXPIRED) + hbr = tbl->hb_hdr_bg_exp; + else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_CRITICAL) + hbr = tbl->hb_hdr_bg_crit; + else if ((o->flags & CW_EXPSTATE_MASK) == CW_EXPSTATE_WARN) + hbr = tbl->hb_hdr_bg_warn; + else if ((colattr == KCDB_ATTR_ID_NAME) && !(o->flags & KHUI_CW_O_EMPTY) && + cwi && cwi->id_credcount > 0) + hbr = tbl->hb_hdr_bg_cred; + else + hbr = tbl->hb_hdr_bg; + } + + FillRect(hdc, r, hbr); + } + + /* draw the background */ + pl = CreatePen(PS_SOLID, 0, tbl->cr_hdr_outline); + pold = SelectObject(hdc, pl); + MoveToEx(hdc, r->left, r->bottom - 1, NULL); + LineTo(hdc,r->right,r->bottom - 1); + SelectObject(hdc, pold); + DeleteObject(pl); + + if (!(o->flags & KHUI_CW_O_NOOUTLINE) && + !(o->flags & KHUI_CW_O_EMPTY)) { + if((tbl->mouse_state & CW_MOUSE_WOUTLINE) && + tbl->mouse_row == row) { + if(o->flags & KHUI_CW_O_EXPAND) { + khui_ilist_draw_id(tbl->ilist, IDB_WDG_EXPAND_HI, + hdc, r->left, + (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0); + } else { + khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE_HI, + hdc, r->left, + (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0); + } + } else { + if(o->flags & KHUI_CW_O_EXPAND) { + khui_ilist_draw_id(tbl->ilist, IDB_WDG_EXPAND, + hdc, r->left, + (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0); + } else { + khui_ilist_draw_id(tbl->ilist, IDB_WDG_COLLAPSE, + hdc, r->left, + (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0); + } + } + + r->left += KHUI_SMICON_CX * 3 / 2; + } else if (!(o->flags & KHUI_CW_O_NOOUTLINE)) { + r->left += KHUI_SMICON_CX * 3 / 2; + } + + /* try to draw the icon, if there is one */ + if(colattr == KCDB_ATTR_ID_NAME) { + + khui_ilist_draw_id(tbl->ilist, + (((tbl->mouse_state & CW_MOUSE_WSTICKY) && + tbl->mouse_row == row)? + ((idf & KCDB_IDENT_FLAG_STICKY)? + IDB_WDG_STUCK_HI: + IDB_WDG_STICK_HI): + ((idf & KCDB_IDENT_FLAG_STICKY)? + IDB_WDG_STUCK: + IDB_WDG_STICK)), + hdc, + r->left, + (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0); + + r->left += KHUI_SMICON_CX * 3 / 2; + + /* the TRUE part of the 'if' is for drawing large icons. It's + disabled for now until we have new icons. */ + if ((cr->flags & KHUI_CW_ROW_EXPVIEW) && FALSE) { + int cx = GetSystemMetrics(SM_CXICON); + int cy = GetSystemMetrics(SM_CYICON); + + DrawIcon(hdc, r->left, (r->top + r->bottom - cy) / 2, tbl->hi_lg_ident); + + r->left += cx + KHUI_SMICON_CX / 2; + + } else { + khui_ilist_draw_id(tbl->ilist, + (((o->flags & KHUI_CW_O_EMPTY) || + cwi == NULL || cwi->id_credcount == 0)? + IDB_ID_DIS_SM: + IDB_ID_SM), + hdc, + r->left, + (r->top + r->bottom - KHUI_SMICON_CY) / 2, 0); + r->left += KHUI_SMICON_CX * 3 / 2 ; + } + } + + + if (!(cr->flags & KHUI_CW_ROW_EXPVIEW)) { + + SetTextAlign(hdc, TA_BOTTOM | TA_LEFT); + + if(selected) + SetTextColor(hdc, tbl->cr_hdr_s); + else + SetTextColor(hdc, tbl->cr_hdr_normal); + + TextOut(hdc, r->left, r->bottom - tbl->vpad, o->header, (int) wcslen(o->header)); + + if (colattr == KCDB_ATTR_ID_NAME && + (idf & KCDB_IDENT_FLAG_DEFAULT)) { + wchar_t defstr[64]; + SIZE size; + + LoadString(khm_hInstance, IDS_CW_DEFAULT, + defstr, ARRAYLENGTH(defstr)); + + GetTextExtentPoint32(hdc, o->header, (int) wcslen(o->header), + &size); + + r->left += size.cx + KHUI_SMICON_CX * 2; + + TextOut(hdc, r->left, r->bottom - tbl->vpad, + defstr, (int) wcslen(defstr)); + } + } else { + + RECT tr; + int len; + wchar_t typestr[128]; + int cx_id; + SIZE size; + + /* expanded view */ +#ifdef DEBUG + assert(colattr == KCDB_ATTR_ID_NAME); +#endif + + CopyRect(&tr, r); + tr.bottom -= (tr.bottom - tr.top) / 2; /* drawing two lines of text */ + + if (selected) + SetTextColor(hdc, tbl->cr_hdr_s); + else + SetTextColor(hdc, tbl->cr_hdr_normal); + + len = (int) wcslen(o->header); + DrawText(hdc, o->header, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); + GetTextExtentPoint32(hdc, o->header, (int) len, &size); + cx_id = size.cx; + + typestr[0] = L'\0'; + + if ((idf & KCDB_IDENT_FLAG_DEFAULT)) { + if (cwi && cwi->credtype_name[0]) { + wchar_t fmt[64]; + + LoadString(khm_hInstance, IDS_CW_DEFAULTTF, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(typestr, sizeof(typestr), fmt, + cwi->credtype_name); + } else { + LoadString(khm_hInstance, IDS_CW_DEFAULT, + typestr, ARRAYLENGTH(typestr)); + } + } else if (cwi && cwi->credtype_name[0]) { + wchar_t fmt[64]; + + LoadString(khm_hInstance, IDS_CW_TYPEF, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(typestr, sizeof(typestr), fmt, + cwi->credtype_name); + } + + if (typestr[0]) { + int cx_str; + + len = (int) wcslen(typestr); + GetTextExtentPoint32(hdc, typestr, (int) len, &size); + cx_str = size.cx + KHUI_SMICON_CX / 2; + + tr.left = max(tr.right - cx_str, tr.left + cx_id + KHUI_SMICON_CX * 2); + if (selected) + SetTextColor(hdc, tbl->cr_hdr_s); + else + SetTextColor(hdc, tbl->cr_hdr_normal); + DrawText(hdc, typestr, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); + } + + CopyRect(&tr, r); + tr.top += (tr.bottom - tr.top) / 2; + + if (1) { + wchar_t buf[128]; + khui_credwnd_ident * cwi; + + buf[0] = L'\0'; + cwi = cw_find_ident(tbl, o->data); + + if (cwi) { +#ifdef SHOW_CREDENTIAL_COUNTS + if (cwi->credcount == 0) + LoadString(khm_hInstance, IDS_IDEXPDISP_NOCRED, + buf, ARRAYLENGTH(buf)); + else if (cwi->credcount == 1) + LoadString(khm_hInstance, IDS_IDEXPDISP_1CRED, + buf, ARRAYLENGTH(buf)); + else { + wchar_t fmt[128]; + LoadString(khm_hInstance, IDS_IDEXPDISP_NCRED, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, (int) cwi->credcount); + } +#else + if (FtToInt(&cwi->ft_expire) != 0) { + FILETIME ft_now; + + GetSystemTimeAsFileTime(&ft_now); + if (CompareFileTime(&cwi->ft_expire, &ft_now) > 0) { + wchar_t fmt[64]; + wchar_t intstr[128]; + FILETIME ft; + khm_size cb; + + ft = FtSub(&cwi->ft_expire, &ft_now); + intstr[0] = L'\0'; + cb = sizeof(intstr); + FtIntervalToString(&ft, intstr, &cb); + + LoadString(khm_hInstance, IDS_CW_EXPIREF, + fmt, ARRAYLENGTH(fmt)); + StringCbPrintf(buf, sizeof(buf), fmt, intstr); + } else { + LoadString(khm_hInstance, IDS_CW_EXPIRED, + buf, ARRAYLENGTH(buf)); + } + } +#endif + + len = (int) wcslen(buf); + + if (selected) + SetTextColor(hdc, tbl->cr_hdr_s); + else + SetTextColor(hdc, tbl->cr_hdr_normal); + DrawText(hdc, buf, len, &tr, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); + } + } + } +} + +LRESULT +cw_handle_header_msg(khui_credwnd_tbl * tbl, LPNMHEADER ph) { + RECT r; + HDITEM hi; + + switch(ph->hdr.code) { + /*TODO:Make it track smoother */ + case HDN_BEGINTRACK: + { + ZeroMemory(&hi, sizeof(hi)); + hi.mask = HDI_ORDER; + Header_GetItem(tbl->hwnd_header, ph->iItem, &hi); + + if (tbl->cols[hi.iOrder].flags & (KHUI_CW_COL_FIXED_WIDTH | + KHUI_CW_COL_FILLER)) + return TRUE; + else + return FALSE; + } + + case HDN_TRACK: + return FALSE; + + case HDN_ENDTRACK: + { + int width; + hi.mask = HDI_ORDER; + Header_GetItem(ph->hdr.hwndFrom, ph->iItem, &hi); + Header_GetItemRect(ph->hdr.hwndFrom, ph->iItem, &r); + width = r.right - r.left; + if(width != tbl->cols[hi.iOrder].width) { + tbl->cols[hi.iOrder].width = width; + cw_update_extents(tbl, TRUE); + InvalidateRect(tbl->hwnd, NULL, FALSE); + } + } + break; + + case HDN_BEGINDRAG: + { + + ZeroMemory(&hi, sizeof(hi)); + hi.mask = HDI_ORDER; + Header_GetItem(tbl->hwnd_header, ph->iItem, &hi); + + if (tbl->cols[hi.iOrder].flags & KHUI_CW_COL_FIXED_POS) { + return TRUE; + } else { + return FALSE; + } + } + break; + + case HDN_ENDDRAG: + { + int drag_start_index; + int drag_end_index; + int i; + khui_credwnd_col tcol; + int sort_index = 0; + khm_int32 old_flags; + + if (ph->pitem == NULL) + return TRUE; + + hi.mask = HDI_ORDER; + Header_GetItem(tbl->hwnd_header, ph->iItem, &hi); + drag_start_index = hi.iOrder; + drag_end_index = ph->pitem->iOrder; + + /* the user dragged the column which was at drag_start_index + to drag_end_index. */ + + if (drag_end_index == drag_start_index) + return TRUE; + + /* we don't allow dragging in to the "fixed" area. */ + for (i=0; i < tbl->n_cols; i++) { + if (!(tbl->cols[i].flags & KHUI_CW_COL_FIXED_POS)) + break; + } + + if (drag_end_index <= i) + return TRUE; + + tcol = tbl->cols[drag_start_index]; + if (drag_end_index < drag_start_index) { + MoveMemory(&tbl->cols[drag_end_index + 1], + &tbl->cols[drag_end_index], + sizeof(tbl->cols[0]) * + (drag_start_index - drag_end_index)); + } else { + MoveMemory(&tbl->cols[drag_start_index], + &tbl->cols[drag_start_index + 1], + sizeof(tbl->cols[0]) * + (drag_end_index - drag_start_index)); + } + tbl->cols[drag_end_index] = tcol; + + old_flags = tbl->cols[drag_end_index].flags; + + if (drag_end_index < tbl->n_cols - 1) { + khm_int32 tflags = tbl->cols[drag_end_index + 1].flags; + + if (tflags & KHUI_CW_COL_GROUP) { + tbl->cols[drag_end_index].flags |= KHUI_CW_COL_GROUP; + } + + if ((tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) && + !(old_flags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC))) + tbl->cols[drag_end_index].flags |= KHUI_CW_COL_SORT_INC; + } + + if (drag_end_index > 0) { + khm_int32 tflags = tbl->cols[drag_end_index - 1].flags; + + if (!(tflags & KHUI_CW_COL_GROUP)) + tbl->cols[drag_end_index].flags &= ~KHUI_CW_COL_GROUP; + + if (!(tflags & (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC))) + tbl->cols[drag_end_index].flags &= + ~(KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC); + } + + if (old_flags != tbl->cols[drag_end_index].flags) { + cw_hditem_from_tbl_col(&tbl->cols[drag_end_index], &hi); + hi.mask = HDI_FORMAT; + Header_SetItem(tbl->hwnd_header, ph->iItem, &hi); + } + + if ((old_flags ^ tbl->cols[drag_end_index].flags) & + KHUI_CW_COL_GROUP) + tbl->flags |= KHUI_CW_TBL_COL_DIRTY; + + for (i=0; i < tbl->n_cols; i++) { + if (tbl->cols[i].attr_id < 0) + continue; + + if (tbl->cols[i].flags & + (KHUI_CW_COL_GROUP | + KHUI_CW_COL_SORT_INC | + KHUI_CW_COL_SORT_DEC)) + tbl->cols[i].sort_index = sort_index++; + else + break; + } + + tbl->flags |= KHUI_CW_TBL_CUSTVIEW; + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, FALSE); + + return FALSE; + } + break; + + case HDN_ITEMCLICK: + { + int idx; + int hidx; + + hi.mask = HDI_ORDER; + Header_GetItem(tbl->hwnd_header, ph->iItem, &hi); + idx = hi.iOrder; + + if (idx < 0 || idx >= tbl->n_cols) + return FALSE; + + if (tbl->cols[idx].flags & KHUI_CW_COL_META) + return FALSE; + + if (tbl->cols[idx].flags & + (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC)) { + + tbl->cols[idx].flags ^= + (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC); + + cw_hditem_from_tbl_col(&tbl->cols[idx], &hi); + hi.mask = HDI_FORMAT; + Header_SetItem(tbl->hwnd_header, ph->iItem, &hi); + + } else { + int i; + int sort_idx = 0; + + for (i=0; i <= idx; i++) { + if (tbl->cols[i].attr_id < 0) + continue; + + if (!(tbl->flags & + (KHUI_CW_COL_SORT_INC | KHUI_CW_COL_SORT_DEC))) { + tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC; + + cw_hditem_from_tbl_col(&tbl->cols[i], &hi); + hi.mask = HDI_FORMAT; + hidx = Header_OrderToIndex(tbl->hwnd_header, i); + Header_SetItem(tbl->hwnd_header, hidx, &hi); + } + + tbl->cols[i].sort_index = sort_idx++; + } + } + + tbl->flags |= KHUI_CW_TBL_CUSTVIEW; + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, FALSE); + + } + break; + + case HDN_ITEMDBLCLICK: + { + int idx; + int hidx; + + hi.mask = HDI_ORDER; + Header_GetItem(tbl->hwnd_header, ph->iItem, &hi); + idx = hi.iOrder; + + if (idx == 0 || idx >= tbl->n_cols) + return FALSE; + + if (tbl->cols[idx].flags & KHUI_CW_COL_GROUP) { + /* we are removing grouping from this level */ + + int i; + + for (i=idx; i < tbl->n_cols; i++) { + if (!(tbl->cols[i].flags & KHUI_CW_COL_GROUP)) + break; + + tbl->cols[i].flags &= ~KHUI_CW_COL_GROUP; + + cw_hditem_from_tbl_col(&tbl->cols[idx], &hi); + hi.mask = HDI_FORMAT; + hidx = Header_OrderToIndex(tbl->hwnd_header, i); + Header_SetItem(tbl->hwnd_header, hidx, &hi); + } + +#if 0 + } else if (tbl->cols[idx].flags & + (KHUI_CW_COL_SORT_INC | + KHUI_CW_COL_SORT_DEC)) { + int i; + + /* remove the sort condition from a column */ + + for (i=idx; i < tbl->n_cols; i++) { + if (!tbl->cols[i].flags & + (KHUI_CW_COL_SORT_INC | + KHUI_CW_COL_SORT_DEC)) + break; + + tbl->cols[i].flags &= + ~(KHUI_CW_COL_SORT_INC | + KHUI_CW_COL_SORT_DEC); + + cw_hditem_from_tbl_col(&tbl->cols[idx], &hi); + hi.mask = HDI_FORMAT; + hidx = Header_OrderToIndex(tbl->hwnd_header, i); + Header_SetItem(tbl->hwnd_header, hidx, &hi); + } +#endif + } else { + int i; + int sort_index = 0; + + for (i=0; i <= idx; i++) { + if (tbl->cols[i].attr_id < 0) + continue; + + if (!(tbl->cols[i].flags & KHUI_CW_COL_GROUP)) { + tbl->cols[i].flags |= KHUI_CW_COL_GROUP; + + if (!(tbl->cols[i].flags & + (KHUI_CW_COL_SORT_INC | + KHUI_CW_COL_SORT_DEC))) + tbl->cols[i].flags |= KHUI_CW_COL_SORT_INC; + + cw_hditem_from_tbl_col(&tbl->cols[i], &hi); + hi.mask = HDI_FORMAT; + hidx = Header_OrderToIndex(tbl->hwnd_header, i); + Header_SetItem(tbl->hwnd_header, hidx, &hi); + } + + tbl->cols[i].sort_index = sort_index++; + } + } + + tbl->flags |= KHUI_CW_TBL_COL_DIRTY; + tbl->flags |= KHUI_CW_TBL_CUSTVIEW; + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, FALSE); + } + break; + + case NM_CUSTOMDRAW: + { + LPNMCUSTOMDRAW cd; + int idx; + + cd = (LPNMCUSTOMDRAW) ph; + switch(cd->dwDrawStage) { + case CDDS_PREPAINT: + return CDRF_NOTIFYITEMDRAW; + + case CDDS_ITEMPREPAINT: + return CDRF_NOTIFYPOSTPAINT; + + case CDDS_ITEMPOSTPAINT: + if(cd->lItemlParam == CW_CA_FLAGS) + idx = IDB_WDG_FLAG; + else if(cd->lItemlParam == CW_CA_TYPEICON) + idx = IDB_WDG_CREDTYPE; + else + idx = -1; + + khui_ilist_draw_id(tbl->ilist, idx, cd->hdc, cd->rc.left, cd->rc.top, 0); + return 0; + } + } + break; + } + return 0; +} + +LRESULT +cw_wm_create(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + + kmq_subscribe_hwnd(KMSG_CRED, hwnd); + kmq_subscribe_hwnd(KMSG_KCDB, hwnd); + kmq_subscribe_hwnd(KMSG_KMM, hwnd); + + /* freed in cw_wm_destroy */ + tbl = PMALLOC(sizeof(*tbl)); + ZeroMemory(tbl, sizeof(*tbl)); + + /* some versions of VC generate portability warnings for + SetWindowLongPtr */ +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, 0, (LONG_PTR) tbl); +#pragma warning(pop) + + cw_refresh_attribs(hwnd); + + tbl->hwnd_header = CreateWindowEx( + 0, + WC_HEADER, + (LPWSTR) NULL, + WS_CHILD | HDS_BUTTONS | + HDS_FULLDRAG | HDS_HORZ | HDS_HOTTRACK | + HDS_DRAGDROP +#if (_WIN32_WINNT >= 0x501) + | ((IS_COMMCTL6())?HDS_FLAT:0) +#endif + , + 0,0,0,0,hwnd, (HMENU) 0, khm_hInstance, NULL); + + cw_load_view(tbl, NULL /* default view */, hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_select_row(tbl, tbl->cursor_row, 0); + cw_update_selection_state(tbl); + cw_update_extents(tbl, FALSE); + + { + RECT rect; + WINDOWPOS pw; + HDLAYOUT hdl; + + hdl.prc = &rect; + hdl.pwpos = &pw; + GetClientRect(hwnd, &rect); + + Header_Layout(tbl->hwnd_header, &hdl); + + SetWindowPos( + tbl->hwnd_header, + pw.hwndInsertAfter, + pw.x, + pw.y, + pw.cx, + pw.cy, + pw.flags | SWP_SHOWWINDOW); + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +LRESULT +cw_wm_destroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + + kmq_unsubscribe_hwnd(KMSG_CRED, hwnd); + kmq_unsubscribe_hwnd(KMSG_KCDB, hwnd); + kmq_unsubscribe_hwnd(KMSG_KMM, hwnd); + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + + if (tbl) { + cw_save_view(tbl, NULL); + + cw_unload_view(tbl); + + PFREE(tbl); + SetWindowLongPtr(hwnd, 0, 0); + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +/* handles WM_PAINT and WM_PRINTCLIENT */ +LRESULT +cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + HDC hdc = NULL; + PAINTSTRUCT ps; + RECT r,rh; + HFONT hf_old = NULL; + int row_s, row_e; + int col_s, col_e; + int i,j,x,y,xs,xe,ys,ye; + int flag_col = -1; + int d_x = -1; + int selected = 0; + int rowheight = 0; + BOOL has_dc = FALSE; + BOOL has_updaterect = TRUE; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + goto _exit; + + if (wParam != 0) { + /* we assume that if wParam != 0, then that contains a device + context for us to draw in. Otherwise, we have to call + BeginPaint() to get one. */ + hdc = (HDC) wParam; + has_dc = TRUE; + } + + if (!has_dc && !GetUpdateRect(hwnd, &r, FALSE)) { + has_updaterect = FALSE; + } + + if (!has_dc) { + if (has_updaterect) + hdc = BeginPaint(hwnd, &ps); + else + hdc = GetDC(hwnd); + } + + if(tbl->hf_normal) + hf_old = SelectFont(hdc, tbl->hf_normal); + SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP); + SetBkMode(hdc, TRANSPARENT); + + GetClientRect(hwnd,&r); + r.top += tbl->header_height; + + if(tbl->n_rows) { + /* remove the notification window if there is one */ + if(tbl->hwnd_notif) { + DestroyWindow(tbl->hwnd_notif); + tbl->hwnd_notif = NULL; + } + /* we compute the visible area in terms of rows and columns */ + /* row_s : first visible row */ + /* col_s : first visible column */ + /* row_e : last visible row */ + /* col_e : last visible column */ + /* ys : top edge of first visible row */ + /* xs : left edge of first visible column */ + + /* We *NEED* all the meta columns to be on the left */ + + row_s = 0; + ys = 0; + row_e = (int) tbl->n_rows; + x = 0; + col_s = -1; + col_e = -1; + xs = 0; + for(i=0; i < (int) tbl->n_cols; i++) { + if(col_e == -1 && x >= tbl->scr_left + (r.right - r.left)) { + col_e = i; + } + if(tbl->cols[i].attr_id == CW_CA_FLAGS) + flag_col = i; + if(d_x == -1 && !cw_is_custom_attr(tbl->cols[i].attr_id)) + d_x = x; + x += tbl->cols[i].width; + if(col_s == -1 && x > tbl->scr_left) { + col_s = i; + xs = tbl->cols[i].x; + } + } + + if(col_e == -1) + col_e = i; + + if(col_s == -1) + col_s = i; + + if(d_x != -1) + d_x += r.left - tbl->scr_left; + + xs += r.left - tbl->scr_left; + ys += r.top - tbl->scr_top; + xe = r.left + tbl->ext_width - tbl->scr_left; + ye = r.top + tbl->ext_height - tbl->scr_top; + + /* now draw */ + y = ys; + for(i=row_s; i < row_e; i++) { + selected = tbl->rows[i].flags & KHUI_CW_ROW_SELECTED; + rowheight = (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)? tbl->cell_height * CW_EXP_ROW_MULT : tbl->cell_height; + + if(tbl->cursor_row == i) { + if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) + SelectFont(hdc, tbl->hf_bold_header); + else + SelectFont(hdc, tbl->hf_bold); + } else if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) { + SelectFont(hdc, tbl->hf_header); + } + + x = xs; + if(tbl->rows[i].flags & KHUI_CW_ROW_HEADER) { + rh.left = xs; + rh.right = xs; + for(j=col_s; j < tbl->rows[i].col; j++) + rh.right += tbl->cols[j].width; + rh.top = y; + rh.bottom = y + rowheight; + if(rh.right > rh.left) { + cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK); + } + rh.left = rh.right; + rh.right = xe; + + cw_draw_header(hdc, tbl, i, &rh); + } + + if(selected) + SetTextColor(hdc, tbl->cr_s); + else + SetTextColor(hdc, tbl->cr_normal); + + x = xs; + rh.top = y; + rh.bottom = y + rowheight; + for(j=col_s; j < col_e; x += tbl->cols[j++].width) { + wchar_t buf[256]; + khm_size cbbuf; + + rh.left = x; + rh.right = x + tbl->cols[j].width; + + if(!cw_is_custom_attr(tbl->cols[j].attr_id)) { + if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) { + cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK); + + if(j > tbl->rows[i].col) { + cbbuf = sizeof(buf); + if(KHM_FAILED(kcdb_cred_get_attr_string((khm_handle) tbl->rows[i].data, + tbl->cols[j].attr_id, buf, + &cbbuf, KCDB_TS_SHORT))) + continue; + + rh.left += tbl->hpad; + rh.right -= tbl->hpad; + + SetTextAlign(hdc, 0); + DrawText(hdc, buf, (int)((cbbuf / sizeof(wchar_t)) - 1), &rh, + DT_LEFT | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE | DT_END_ELLIPSIS); + } + } + } else { + cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK); + + if(tbl->cols[j].attr_id == CW_CA_FLAGS) { + khui_credwnd_outline * o; + khm_int32 flag; + + if(tbl->rows[i].flags & KHUI_CW_ROW_HEADER) { + o = ((khui_credwnd_outline *) tbl->rows[i].data); + if(o->flags & KHUI_CW_O_SHOWFLAG) + flag = o->flags; + else + flag = 0; + } else { + flag = tbl->rows[i].flags; + } + + flag &= CW_EXPSTATE_MASK; + + if(flag == CW_EXPSTATE_WARN) { + khui_ilist_draw_id(tbl->ilist, IDB_FLAG_WARN, hdc, x, y, 0); + } else if(flag == CW_EXPSTATE_CRITICAL) { + khui_ilist_draw_id(tbl->ilist, IDB_FLAG_CRITICAL, hdc, x, y, 0); + } else if(flag == CW_EXPSTATE_EXPIRED) { + khui_ilist_draw_id(tbl->ilist, IDB_FLAG_EXPIRED, hdc, x, y, 0); + } else if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) { + khm_int32 flags; + + if (KHM_SUCCEEDED(kcdb_cred_get_flags((khm_handle) tbl->rows[i].data, &flags)) && + (flags & KCDB_CRED_FLAG_RENEWABLE)) { + khui_ilist_draw_id(tbl->ilist, + IDB_FLAG_RENEW, + hdc, + x, y, 0); + } else { + khui_ilist_draw_id(tbl->ilist, + IDB_TK_SM, + hdc, + x, y, 0); + } + } + } + } + } + + if(tbl->cursor_row == i) { + rh.left = tbl->scr_left; + rh.right = tbl->scr_left + tbl->ext_width; + DrawFocusRect(hdc, &rh); + } + + if (tbl->cursor_row == i || + (tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) { + SelectFont(hdc, tbl->hf_normal); + } + + y += rowheight; + + } + + if(xe < r.right) { + rh.left = xe; + rh.right = r.right; + rh.top = r.top; + rh.bottom = r.bottom; + + cw_erase_rect(hdc, tbl, &r, &rh, CW_ER_BLANK); + } + + if(ye < r.bottom) { + rh.left = r.left; + rh.right = (xe < r.right)?xe:r.right; + rh.top = ye; + rh.bottom = r.bottom; + + cw_erase_rect(hdc, tbl, &r, &rh, CW_ER_BLANK); + } + + } else { + wchar_t buf[512]; + cw_erase_rect(hdc, tbl, &r, &r, CW_ER_BLANK); + + if(tbl->hwnd_notif == NULL) { + LoadString(khm_hInstance, IDS_NO_CREDS, buf, sizeof(buf)/sizeof(buf[0])); + tbl->hwnd_notif = khm_create_htwnd( + tbl->hwnd, + buf, + r.left,r.top,r.right - r.left,tbl->cell_height * 4, + 0, /* This can be WS_EX_TRANSPARENT, but + we don't fully support it yet. */ + WS_VISIBLE); + if(tbl->hwnd_notif) { + SendMessage(tbl->hwnd_notif, WM_SETFONT, (WPARAM) tbl->hf_normal, (LPARAM) FALSE); + ShowWindow(tbl->hwnd_notif, SW_SHOW); + } + } + } + + if(tbl->hf_normal) + SelectFont(hdc, hf_old); + + if (!has_dc) { + if (has_updaterect) + EndPaint(hwnd,&ps); + else + ReleaseDC(hwnd, hdc); + } + + _exit: + return TRUE; +} + +LRESULT +cw_wm_size(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + RECT rect; + khui_credwnd_tbl * tbl; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl) { + cw_update_extents(tbl, TRUE); + + GetClientRect(hwnd, &rect); + + if(tbl->hwnd_notif) { + SetWindowPos(tbl->hwnd_notif, + tbl->hwnd_header, + rect.left, + tbl->header_height, + rect.right - rect.left, + tbl->cell_height * 4, + 0); + } + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +LRESULT +cw_wm_notify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + LPNMHDR pnmh; + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return 0; + + pnmh = (LPNMHDR) lParam; + if(pnmh->hwndFrom == tbl->hwnd_header) { + LPNMHEADER ph; + ph = (LPNMHEADER) lParam; + return cw_handle_header_msg(tbl, ph); + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +static void cw_pp_begin(khui_property_sheet * s); +static void cw_pp_precreate(khui_property_sheet * s); +static void cw_pp_end(khui_property_sheet * s); +static void cw_pp_destroy(khui_property_sheet *ps); + +LRESULT +cw_kmq_wm_dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + kmq_message * m; + khm_int32 rv = KHM_ERROR_SUCCESS; + khui_credwnd_tbl * tbl; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + + kmq_wm_begin(lParam, &m); + + if (tbl == NULL) + goto _skip_message; + + if(m->type == KMSG_CRED) { + switch (m->subtype) { + case KMSG_CRED_ROOTDELTA: + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + cw_select_row(tbl, tbl->cursor_row, 0); + InvalidateRect(hwnd, NULL, FALSE); + break; + + case KMSG_CRED_PP_BEGIN: + cw_pp_begin((khui_property_sheet *) m->vparam); + break; + + case KMSG_CRED_PP_PRECREATE: + cw_pp_precreate((khui_property_sheet *) m->vparam); + break; + + case KMSG_CRED_PP_END: + cw_pp_end((khui_property_sheet *) m->vparam); + break; + + case KMSG_CRED_PP_DESTROY: + cw_pp_destroy((khui_property_sheet *) m->vparam); + break; + } + } else if (m->type == KMSG_KCDB) { + if (m->subtype == KMSG_KCDB_IDENT && + m->uparam == KCDB_OP_MODIFY) { + + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + cw_set_row_context(tbl, tbl->cursor_row); + InvalidateRect(hwnd, NULL, FALSE); + + } + else if (m->subtype == KMSG_KCDB_IDENT && + m->uparam == KCDB_OP_NEW_DEFAULT) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_handle defid = NULL; + + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + InvalidateRect(hwnd, NULL, FALSE); + + cb = sizeof(idname); + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&defid)) && + defid != NULL && + KHM_SUCCEEDED(kcdb_identity_get_name(defid, idname, &cb)) && + idname[0] != L'\0') { + + khm_notify_icon_tooltip(idname); + + } else { + + LoadString(khm_hInstance, IDS_NOTIFY_READY, + idname, ARRAYLENGTH(idname)); + khm_notify_icon_tooltip(idname); + } + + if (defid) + kcdb_identity_release(defid); + } + else if (m->subtype == KMSG_KCDB_ATTRIB && + (m->uparam == KCDB_OP_INSERT || + m->uparam == KCDB_OP_DELETE)) { + + cw_refresh_attribs(hwnd); + + } + } else if (m->type == KMSG_KMM && + m->subtype == KMSG_KMM_I_DONE) { + + if (tbl->flags & KHUI_CW_TBL_COLSKIP) { + wchar_t cname[KCONF_MAXCCH_NAME]; + khm_size cb; + + cname[0] = L'\0'; + + if (tbl->csp_view) { + cb = sizeof(cname); + khc_get_config_space_name(tbl->csp_view, + cname, + &cb); + } + + cw_unload_view(tbl); + + cw_load_view(tbl, ((cname[0])?cname: NULL), hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_selection_state(tbl); + cw_update_extents(tbl, TRUE); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + } + + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_ACTIVATE) { + /* a column selector menu item was activated */ + + khm_int32 attr_id; + khm_int32 action; + khui_action * paction; + int i; + int first_non_fixed = -1; + + action = m->uparam; + paction = khui_find_action(action); + + if (paction == NULL) + goto _skip_action; + + attr_id = (khm_int32)(INT_PTR) paction->data; + + if (attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) + goto _skip_action; + + for (i=0; i < tbl->n_cols; i++) { + if (tbl->cols[i].attr_id >= 0 && + first_non_fixed == -1) + first_non_fixed = i; + + if (tbl->cols[i].attr_id == attr_id) + break; + } + + if (first_non_fixed == i && + i == tbl->n_cols - 1) { + /* this is the only non-fixed column. We don't allow + deleting it, althoguh there's nothing wrong with doing + so other than not being very useful. */ + goto _skip_action; + } + + if (i < tbl->n_cols) { + khm_int32 sort_index; + + /* we need to remove a column */ + + Header_DeleteItem(tbl->hwnd_header, i); + sort_index = tbl->cols[i].sort_index; + + if (tbl->cols[i].title) + PFREE(tbl->cols[i].title); + tbl->cols[i].title = NULL; + + if (i < tbl->n_cols - 1) { + MoveMemory(&tbl->cols[i], &tbl->cols[i+1], + sizeof(tbl->cols[0]) * (tbl->n_cols - (i + 1))); + } + tbl->n_cols--; + + /* fix the sort index */ + if (sort_index >= 0) { + for (i=0; i < tbl->n_cols; i++) { + if (tbl->cols[i].sort_index > sort_index) + tbl->cols[i].sort_index--; + } + } + + tbl->flags |= KHUI_CW_TBL_COL_DIRTY; + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + + khui_check_action(attr_to_action[attr_id], FALSE); + + tbl->flags |= KHUI_CW_TBL_CUSTVIEW; + + } else { + /* we need to add a column */ + wchar_t buf[KCDB_MAXCCH_SHORT_DESC]; + khm_size cb; + khm_int32 idx = tbl->n_cols; + HDITEM hi; + + /* for now, we only allow KHUI_CW_COL_INITIAL columns */ + if (tbl->n_rows == tbl->n_total_rows) + goto _skip_action; + + cb = sizeof(buf); + if (KHM_FAILED(kcdb_attrib_describe(attr_id, + buf, + &cb, + KCDB_TS_SHORT))) + goto _skip_action; + + tbl->cols[idx].attr_id = attr_id; + tbl->cols[idx].width = 100; + tbl->cols[idx].x = -1; + tbl->cols[idx].flags = 0; + tbl->cols[idx].sort_index = -1; + tbl->cols[idx].title = PMALLOC(cb); +#ifdef DEBUG + assert(tbl->cols[idx].title); +#endif + if (!tbl->cols[idx].title) + goto _skip_action; + + StringCbCopy(tbl->cols[idx].title, + cb, + buf); + + tbl->n_cols++; + + cw_hditem_from_tbl_col(&(tbl->cols[idx]), &hi); + Header_InsertItem(tbl->hwnd_header, 512, &hi); + + tbl->flags |= KHUI_CW_TBL_COL_DIRTY; + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + + khui_check_action(attr_to_action[attr_id], TRUE); + + tbl->flags |= KHUI_CW_TBL_CUSTVIEW; + } + + kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0); + + _skip_action: + ; + } + + _skip_message: + + return kmq_wm_end(m, rv); +} + +static void +cw_select_outline_level(khui_credwnd_outline * o, + BOOL select) +{ + while(o) { + if (select) + o->flags |= KHUI_CW_O_SELECTED; + else + o->flags &= ~KHUI_CW_O_SELECTED; + cw_select_outline_level(TFIRSTCHILD(o), select); + o = LNEXT(o); + } +} + +static void +cw_select_outline(khui_credwnd_outline * o, + BOOL select) +{ + if (select) + o->flags |= KHUI_CW_O_SELECTED; + else + o->flags &= ~KHUI_CW_O_SELECTED; +} + +static void +cw_select_row_creds(khui_credwnd_tbl * tbl, int row, int selected) { + + khm_size j; + khm_size idx_start, idx_end; + +#ifdef DEBUG + assert(row >= 0 && row < tbl->n_rows); +#endif + + if (row >= tbl->n_rows) + return; + + if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) { + khui_credwnd_outline * o; + + o = (khui_credwnd_outline *) tbl->rows[row].data; + idx_start = o->idx_start; + idx_end = o->idx_end; + } else { + idx_start = tbl->rows[row].idx_start; + idx_end = tbl->rows[row].idx_end; + } + + if (idx_start == -1 || idx_end == -1) + return; + + for (j = idx_start; j <= idx_end; j++) { + khm_handle cred = NULL; + + kcdb_credset_get_cred(tbl->credset, (khm_int32) j, &cred); + + if (cred) { + kcdb_cred_set_flags(cred, ((selected)?KCDB_CRED_FLAG_SELECTED:0), + KCDB_CRED_FLAG_SELECTED); + kcdb_cred_release(cred); + } + } +} + +static void +cw_unselect_all(khui_credwnd_tbl * tbl) +{ + int i; + + for(i=0; i<tbl->n_rows; i++) { + tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED; + + cw_select_row_creds(tbl, i, FALSE); + } + + cw_select_outline_level(tbl->outline, FALSE); +} + +static void +cw_update_cred_row_selection_state(khui_credwnd_tbl * tbl, + int row) { + khm_int32 flags; + khm_size idx_start, idx_end; + khm_size k; + khm_boolean found_selected = FALSE; + khm_boolean found_unselected = FALSE; + khm_boolean row_select = TRUE; + +#ifdef DEBUG + assert(row >= 0 && row < tbl->n_rows); +#endif + if (row < 0 || row >= tbl->n_rows) + return; + + idx_start = tbl->rows[row].idx_start; + idx_end = tbl->rows[row].idx_end; + + for (k = idx_start; k <= idx_end && select; k++) { + khm_handle cred = NULL; + + if (KHM_SUCCEEDED(kcdb_credset_get_cred(tbl->credset, (khm_int32) k, + &cred))) { + kcdb_cred_get_flags(cred, &flags); + if (!(flags & KCDB_CRED_FLAG_SELECTED)) { + found_unselected = TRUE; + row_select = FALSE; + } else { + found_selected = TRUE; + } + kcdb_cred_release(cred); + } else { + row_select = FALSE; +#ifdef DEBUG + assert(FALSE); +#endif + } + } + + if (row_select) + tbl->rows[row].flags |= KHUI_CW_ROW_SELECTED; + else + tbl->rows[row].flags &= ~KHUI_CW_ROW_SELECTED; + + if (found_selected && found_unselected) { + /* if there were selected and unselected credentials + associated with the same row, we need to set the selection + state of all of them to match what the user is going to + see. */ + cw_select_row_creds(tbl, row, row_select); + } +} + +static void +cw_update_outline_selection_state(khui_credwnd_tbl * tbl, + khui_credwnd_outline * o) +{ + khm_boolean select = TRUE; + int j; + + for (j = o->start + 1; j < o->start + o->length; j++) { + if (tbl->rows[j].flags & KHUI_CW_ROW_HEADER) { + cw_update_outline_selection_state(tbl, + (khui_credwnd_outline *) + tbl->rows[j].data); + } else { + cw_update_cred_row_selection_state(tbl, j); + } + + if (!(tbl->rows[j].flags & KHUI_CW_ROW_SELECTED)) { + select = FALSE; + } + + if (tbl->rows[j].flags & KHUI_CW_ROW_HEADER) { + j += ((khui_credwnd_outline *) tbl->rows[j].data)->length - 1; + } + } + + /* special case : the header has been collapsed and we are just + using one row. In this case, the for loop above will do + nothing. */ + + if (o->length == 1) { + select = !!(o->flags & KHUI_CW_O_SELECTED); + } else { + cw_select_outline(o, select); + } + + if (select) { + tbl->rows[o->start].flags |= KHUI_CW_ROW_SELECTED; + } else { + tbl->rows[o->start].flags &= ~KHUI_CW_ROW_SELECTED; + } +} + +static void +cw_update_selection_state(khui_credwnd_tbl * tbl) +{ + int i; + + for (i=0; i < tbl->n_rows; i++) { + if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) { + khui_credwnd_outline * o; + + o = (khui_credwnd_outline *) tbl->rows[i].data; + + cw_update_outline_selection_state(tbl, o); + + i += o->length - 1; + } else { + cw_update_cred_row_selection_state(tbl, i); + } + } +} + +/* Examine the current row and set the UI context */ +static void +cw_set_row_context(khui_credwnd_tbl * tbl, int row) +{ + khui_credwnd_outline * o; + BOOL set_context = TRUE; + + if (row < 0 || row >= (int) tbl->n_rows) { + if (tbl->n_rows > 0) + row = 0; + else { + khui_context_reset(); + return; + } + } + + if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) { + + o = (khui_credwnd_outline *) tbl->rows[row].data; + + if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) { + if (TPARENT(o) != NULL) { + khui_credwnd_outline * op; + + op = TPARENT(o); + + if (tbl->cols[op->col].attr_id == KCDB_ATTR_TYPE_NAME && + TPARENT(op) == NULL) { + /* selected a credential type */ + khui_context_set(KHUI_SCOPE_CREDTYPE, + (khm_handle) o->data, + (khm_int32) (DWORD_PTR) op->data, + NULL, + NULL, + 0, + tbl->credset); + } else { + /* we can't narrow it down using the standard set + of scopes. We consider this to be an identity + selection because the user right-clicked on an + identity header. */ + khui_context_set(KHUI_SCOPE_IDENT, + (khm_handle) o->data, + KCDB_CREDTYPE_INVALID, + NULL, + NULL, + 0, + tbl->credset); + } + } else { + /* The user clicked on an identity header. Even + though not all credentials belonging to the + identity maybe within the scope right now, we still + consider this to be an identity scope. */ + khui_context_set(KHUI_SCOPE_IDENT, + (khm_handle) o->data, + KCDB_CREDTYPE_INVALID, + NULL, + NULL, + 0, + tbl->credset); + } + } else if (tbl->cols[o->col].attr_id == KCDB_ATTR_TYPE_NAME) { + if (TPARENT(o) == NULL) { + /* selected an entire cred type */ + khui_context_set(KHUI_SCOPE_CREDTYPE, + NULL, + (khm_int32) (DWORD_PTR) o->data, + NULL, + NULL, + 0, + tbl->credset); + } else { + khui_credwnd_outline * op; + + op = TPARENT(o); + if (tbl->cols[op->col].attr_id == KCDB_ATTR_ID_NAME) { + /* credtype under an identity. Even though not + all the credentials of this credtype belonging + to this identity might be within the scope, we + still consider this to be a type selection + under a specific identity. */ + khui_context_set(KHUI_SCOPE_CREDTYPE, + (khm_handle) op->data, + (khm_int32) (DWORD_PTR) o->data, + NULL, + NULL, + 0, + tbl->credset); + } else { + set_context = FALSE; + } + } + } else { + set_context = FALSE; + } + + if (!set_context) { + /* woohoo. cred group. yay. */ + khui_header headers[KHUI_MAX_HEADERS]; + khm_size n_headers = 0; + + do { + headers[n_headers].attr_id = + o->attr_id; + if (tbl->cols[o->col].attr_id == + KCDB_ATTR_ID_NAME) { + headers[n_headers].data = &(o->data); + headers[n_headers].cb_data = sizeof(khm_handle); + } else if (tbl->cols[o->col].attr_id == + KCDB_ATTR_TYPE_NAME) { + headers[n_headers].data = &(o->data); + headers[n_headers].cb_data = sizeof(khm_int32); + } else { + headers[n_headers].data = o->data; + headers[n_headers].cb_data = o->cb_data; + } + + n_headers++; + + o = TPARENT(o); + } while(o); + + khui_context_set(KHUI_SCOPE_GROUP, + NULL, + KCDB_CREDTYPE_INVALID, + NULL, + headers, + n_headers, + tbl->credset); + } + + } else { + khm_handle cred; + + cred = (khm_handle) tbl->rows[row].data; + + khui_context_set(KHUI_SCOPE_CRED, + NULL, + KCDB_CREDTYPE_INVALID, + cred, + NULL, + 0, + tbl->credset); + } +} + +static void +cw_select_all(khui_credwnd_tbl * tbl) +{ + int i; + + for(i=0; i<tbl->n_rows; i++) { + tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED; + cw_select_row_creds(tbl, i, TRUE); + } + + cw_select_outline_level(tbl->outline, TRUE); + + cw_update_selection_state(tbl); + + cw_set_row_context(tbl, tbl->cursor_row); + + InvalidateRect(tbl->hwnd, NULL, FALSE); +} + +static void +cw_select_row(khui_credwnd_tbl * tbl, int row, WPARAM wParam) +{ + int i; + BOOL toggle; + BOOL extend; + int group_begin; + int group_end; + + if (wParam & MK_CONTROL) { + toggle = TRUE; + extend = FALSE; + } else if (wParam & MK_SHIFT) { + toggle = FALSE; + extend = TRUE; + } else { + toggle = FALSE; + extend = FALSE; + } + + if (row < 0 || row >= (int) tbl->n_rows) + return; + + if (tbl->rows[row].flags & KHUI_CW_ROW_HEADER) { + khui_credwnd_outline * o; + + o = (khui_credwnd_outline *) tbl->rows[row].data; + + group_begin = o->start; + group_end = o->start + o->length - 1; + } else { + group_begin = row; + group_end = row; + } + + if (!toggle && !extend) { + /* selecting a single row */ + cw_unselect_all(tbl); + + tbl->cursor_row = row; + tbl->anchor_row = row; + + for (i = group_begin; i <= group_end; i++) { + tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED; + if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) + cw_select_outline((khui_credwnd_outline *) tbl->rows[i].data, TRUE); + cw_select_row_creds(tbl, i, TRUE); + } + } else if (toggle) { + BOOL select; + + tbl->cursor_row = row; + tbl->anchor_row = row; + + select = !(tbl->rows[row].flags & KHUI_CW_ROW_SELECTED); + + for (i = group_begin; i <= group_end; i++) { + if (select) + tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED; + else + tbl->rows[i].flags &= ~KHUI_CW_ROW_SELECTED; + + if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) + cw_select_outline((khui_credwnd_outline *) tbl->rows[i].data, select); + + cw_select_row_creds(tbl, i, select); + } + } else if (extend) { + int range_begin; + int range_end; + + cw_unselect_all(tbl); + + range_begin = min(row, tbl->anchor_row); + range_end = max(row, tbl->anchor_row); + + for (i = range_begin; i <= range_end; i++) { + tbl->rows[i].flags |= KHUI_CW_ROW_SELECTED; + + if (tbl->rows[i].flags & KHUI_CW_ROW_HEADER) + cw_select_outline((khui_credwnd_outline *) tbl->rows[i].data, TRUE); + + cw_select_row_creds(tbl, i, TRUE); + } + + tbl->cursor_row = row; + } + + cw_update_selection_state(tbl); + + cw_set_row_context(tbl, tbl->cursor_row); + + InvalidateRect(tbl->hwnd, NULL, FALSE); +} + +static void +cw_toggle_outline_state(khui_credwnd_tbl * tbl, + khui_credwnd_outline * o) { + + int old_range_begin; + int old_range_end; + int new_range_begin; + int new_range_end; + + old_range_begin = o->start; + old_range_end = o->start + o->length - 1; + + o->flags ^= KHUI_CW_O_EXPAND; + + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + + new_range_begin = o->start; + new_range_end = o->start + o->length - 1; + + if (tbl->cursor_row > old_range_end) { + tbl->cursor_row -= old_range_end - new_range_end; + } else if (tbl->cursor_row >= old_range_begin && + tbl->cursor_row <= old_range_end) { + tbl->cursor_row = new_range_begin; + } + + if (tbl->anchor_row > old_range_end) { + tbl->anchor_row -= old_range_end - new_range_end; + } else if (tbl->anchor_row >= old_range_begin && + tbl->anchor_row <= old_range_end) { + tbl->anchor_row = new_range_begin; + } + + InvalidateRect(tbl->hwnd, NULL, TRUE); + +} + +LRESULT cw_properties(HWND hwnd); + +LRESULT +cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + int x,y; + RECT r; + int row; + int col; + int i; + int nm_state,nm_row,nm_col; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return 0; + + /* we are basically trying to capture events where the mouse is + hovering over one of the 'hotspots'. There are two kinds of + hotspots one is the little widget thinggy that you click on to + expand or collapse an outline. The other is a text cell that + is partially concealed. */ + + x = GET_X_LPARAM(lParam); + y = GET_Y_LPARAM(lParam); + x += tbl->scr_left; + y += tbl->scr_top - tbl->header_height; + + row = -1; + + for (i=0; i < tbl->n_rows; i++) { + if (y >= tbl->rows[i].r_ext.top && + y < tbl->rows[i].r_ext.bottom) { + row = i; + break; + } + } + + col = -1; + nm_state = CW_MOUSE_NONE; + nm_row = nm_col = -1; + + for(i=0; i < (int) tbl->n_cols; i++) { + if(x >= tbl->cols[i].x && + x < tbl->cols[i].x + tbl->cols[i].width) { + col = i; + break; + } + } + + if(wParam & MK_LBUTTON) + nm_state = CW_MOUSE_LDOWN; + + if(row >= 0 && row < (int) tbl->n_rows) { + nm_state |= CW_MOUSE_ROW; + nm_row = row; + nm_col = col; + if(tbl->rows[row].flags & KHUI_CW_ROW_HEADER) { + khui_credwnd_outline * o; + + o = (khui_credwnd_outline *) tbl->rows[row].data; + + /* are we on a widget then? */ + x -= tbl->cols[o->col].x; + + if (!(o->flags & KHUI_CW_O_NOOUTLINE)) { + if(x >= 0 && x < KHUI_SMICON_CX) /* hit */ { + nm_state |= CW_MOUSE_WOUTLINE | CW_MOUSE_WIDGET; + } else if (tbl->cols[tbl->rows[row].col].attr_id == + KCDB_ATTR_ID_NAME && + col == tbl->rows[row].col && + x >= KHUI_SMICON_CX * 3 / 2 && + x < KHUI_SMICON_CX * 5 / 2){ + nm_state |= CW_MOUSE_WSTICKY | CW_MOUSE_WIDGET; + } else if (tbl->cols[tbl->rows[row].col].attr_id == + KCDB_ATTR_ID_NAME && + col == tbl->rows[row].col && + x >= KHUI_SMICON_CX * 3 && + x < KHUI_SMICON_CX * 4) { + nm_state |= CW_MOUSE_WICON | CW_MOUSE_WIDGET; + } + } else if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) { + if (col == tbl->rows[row].col && + x >= 0 && + x < KHUI_SMICON_CX){ + + nm_state |= CW_MOUSE_WSTICKY | CW_MOUSE_WIDGET; + + } else if (col == tbl->rows[row].col && + x >= KHUI_SMICON_CX * 3 / 2 && + x < KHUI_SMICON_CX * 5 / 2) { + nm_state |= CW_MOUSE_WICON | CW_MOUSE_WIDGET; + } + } + } + } + + /* did the user drag the cursor off the current row? */ + if((tbl->mouse_state & CW_MOUSE_LDOWN) && + (nm_row != tbl->mouse_row)) { + nm_state &= ~CW_MOUSE_WMASK; + } + + if(!(nm_state & CW_MOUSE_LDOWN) && + (tbl->mouse_state & CW_MOUSE_LDOWN) && + tbl->mouse_row == nm_row) { + + if((nm_state & CW_MOUSE_WOUTLINE) && + (tbl->mouse_state & CW_MOUSE_WOUTLINE)) { + /* click on an outline widget */ + khui_credwnd_outline * o; + + o = (khui_credwnd_outline *) tbl->rows[nm_row].data; + tbl->mouse_state = CW_MOUSE_WIDGET | CW_MOUSE_WOUTLINE; + + cw_toggle_outline_state(tbl, o); + + return 0; + } else if ((nm_state & CW_MOUSE_WSTICKY) && + (tbl->mouse_state & CW_MOUSE_WSTICKY)) { + + khui_credwnd_outline * o; + khm_handle ident; + khm_int32 idf = 0; + + o = tbl->rows[nm_row].data; + ident = o->data; + + kcdb_identity_get_flags(ident, &idf); + idf &= KCDB_IDENT_FLAG_STICKY; + kcdb_identity_set_flags(ident, (idf ^ KCDB_IDENT_FLAG_STICKY), + KCDB_IDENT_FLAG_STICKY); + + tbl->mouse_state = CW_MOUSE_WIDGET | CW_MOUSE_WSTICKY; + + khm_refresh_identity_menus(); + + return 0; + } else if ((nm_state & CW_MOUSE_WICON) && + (tbl->mouse_state & CW_MOUSE_WICON)) { + /* click on an row icon */ + cw_select_row(tbl, nm_row, wParam); + cw_properties(hwnd); + } else { + /* click on a row */ + cw_select_row(tbl, nm_row, wParam); + + if (tbl->mouse_col == nm_col && + nm_col >= 0 && + tbl->cols[nm_col].attr_id == CW_CA_FLAGS && + !(tbl->rows[nm_row].flags & KHUI_CW_ROW_HEADER)) { + /* clicked on a cred icon */ + + cw_properties(hwnd); + } + } + } + + /* ok, now if we are changing state, we need to invalidate a few + regions */ + if (((tbl->mouse_state ^ nm_state) & (CW_MOUSE_WIDGET | + CW_MOUSE_WOUTLINE | + CW_MOUSE_WSTICKY)) || + tbl->mouse_row != nm_row) { + + if(tbl->mouse_state & CW_MOUSE_WOUTLINE) { + r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left; + r.top = tbl->mouse_row * tbl->cell_height + + tbl->header_height - tbl->scr_top; + r.right = r.left + KHUI_SMICON_CX; + r.bottom = r.top + tbl->cell_height; + InvalidateRect(tbl->hwnd, &r, TRUE); + } + if(tbl->mouse_state & CW_MOUSE_WSTICKY) { + if (tbl->flags & KHUI_CW_TBL_EXPIDENT) { + + if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) { + r = tbl->rows[tbl->mouse_row].r_ext; + OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top); + r.right = r.left + KHUI_SMICON_CX; + InvalidateRect(tbl->hwnd, &r, TRUE); + } + + } else { + r.left = KHUI_SMICON_CX * 3 / 2 + + tbl->cols[tbl->mouse_col].x - tbl->scr_left; + r.top = tbl->mouse_row * tbl->cell_height + + tbl->header_height - tbl->scr_top; + r.right = r.left + KHUI_SMICON_CX; + r.bottom = r.top + tbl->cell_height; + } + InvalidateRect(tbl->hwnd, &r, TRUE); + } + + if ((tbl->mouse_state & nm_state) & CW_MOUSE_LDOWN) { + if (tbl->mouse_row == nm_row) + tbl->mouse_col = nm_col; + } else { + tbl->mouse_col = nm_col; + tbl->mouse_row = nm_row; + } + tbl->mouse_state = nm_state; + + /* same code block as above */ + if(tbl->mouse_state & CW_MOUSE_WOUTLINE) { + r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left; + r.top = tbl->mouse_row * tbl->cell_height + + tbl->header_height - tbl->scr_top; + r.right = r.left + KHUI_SMICON_CX; + r.bottom = r.top + tbl->cell_height; + InvalidateRect(tbl->hwnd, &r, TRUE); + } + if(tbl->mouse_state & CW_MOUSE_WSTICKY) { + if (tbl->flags & KHUI_CW_TBL_EXPIDENT) { + + if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) { + r = tbl->rows[tbl->mouse_row].r_ext; + OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top); + r.right = r.left + KHUI_SMICON_CX; + InvalidateRect(tbl->hwnd, &r, TRUE); + } + + } else { + r.left = KHUI_SMICON_CX * 3 / 2 + + tbl->cols[tbl->mouse_col].x - tbl->scr_left; + r.top = tbl->mouse_row * tbl->cell_height + + tbl->header_height - tbl->scr_top; + r.right = r.left + KHUI_SMICON_CX; + r.bottom = r.top + tbl->cell_height; + } + InvalidateRect(tbl->hwnd, &r, TRUE); + } + } else if(tbl->mouse_state != nm_state) { + + if ((tbl->mouse_state & nm_state) & CW_MOUSE_LDOWN) { + if (tbl->mouse_row == nm_row) { + tbl->mouse_col = nm_col; + tbl->mouse_state = nm_state; + } + } else { + tbl->mouse_col = nm_col; + tbl->mouse_row = nm_row; + tbl->mouse_state = nm_state; + } + } + + /* if it was a double click, also show the property + window */ + if (uMsg == WM_LBUTTONDBLCLK) { + cw_properties(hwnd); + } + + return 0; +} + +LRESULT +cw_wm_hscroll(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + SCROLLINFO si; + RECT cr; + RECT lr; + RECT sr; + int dx; + int newpos; + + tbl = (khui_credwnd_tbl *) (LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return 0; + + GetClientRect(hwnd, &cr); + dx = tbl->scr_left; + + switch(LOWORD(wParam)) { + case SB_LEFT: + newpos = 0; + break; + + case SB_RIGHT: + newpos = tbl->ext_width; + break; + + case SB_LINELEFT: + newpos = tbl->scr_left - (tbl->ext_width / 12); + break; + + case SB_LINERIGHT: + newpos = tbl->scr_left + (tbl->ext_width / 12); + break; + + case SB_PAGELEFT: + newpos = tbl->scr_left - (cr.right - cr.left); + break; + + case SB_PAGERIGHT: + newpos = tbl->scr_left + (cr.right - cr.left); + break; + + case SB_THUMBTRACK: + case SB_THUMBPOSITION: + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_TRACKPOS; + GetScrollInfo(hwnd, SB_HORZ, &si); + + newpos = si.nTrackPos; + break; + + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + + //cr.top += tbl->header_height; + tbl->scr_left = newpos; + cw_update_extents(tbl, TRUE); + + dx -= tbl->scr_left; + + /* exclude the watermark */ + lr.bottom = cr.bottom; + lr.right = cr.right; + lr.top = max(cr.bottom - tbl->kbm_logo_shade.cy, cr.top); + lr.left = max(cr.right - tbl->kbm_logo_shade.cx, cr.left); + + if(cr.top < lr.top && cr.left < cr.right) { + sr.left = cr.left; + sr.right = cr.right; + sr.top = cr.top; + sr.bottom = lr.top; + ScrollWindowEx( + hwnd, + dx, + 0, + &sr, + &sr, + NULL, + NULL, + SW_INVALIDATE | SW_SCROLLCHILDREN); + } + + if(cr.left < lr.left && lr.top < lr.bottom) { + sr.left = cr.left; + sr.right = lr.left; + sr.top = lr.top; + sr.bottom = lr.bottom; + ScrollWindowEx( + hwnd, + dx, + 0, + &sr, + &sr, + NULL, + NULL, + SW_INVALIDATE | SW_SCROLLCHILDREN); + } + + if(lr.top < lr.bottom && lr.left < lr.right) { + InvalidateRect(hwnd, &lr, FALSE); + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +static void +cw_vscroll_to_pos(HWND hwnd, khui_credwnd_tbl * tbl, int newpos) { + RECT cr; + RECT sr; + RECT lr; + int dy; + + GetClientRect(hwnd, &cr); + cr.top += tbl->header_height; + dy = tbl->scr_top; + + tbl->scr_top = newpos; + cw_update_extents(tbl, TRUE); + + dy -= tbl->scr_top; + + /* exclude watermark */ + lr.bottom = cr.bottom; + lr.right = cr.right; + lr.top = max(cr.bottom - tbl->kbm_logo_shade.cy, cr.top); + lr.left = max(cr.right - tbl->kbm_logo_shade.cx, cr.left); + + if(cr.left < lr.left && cr.top < cr.bottom) { + sr.left = cr.left; + sr.right = lr.left; + sr.top = cr.top; + sr.bottom = cr.bottom; + ScrollWindowEx( + hwnd, + 0, + dy, + &sr, + &sr, + NULL, + NULL, + SW_INVALIDATE); + } + + if(lr.left < lr.right && cr.top < lr.top) { + sr.left = lr.left; + sr.right = lr.right; + sr.top = cr.top; + sr.bottom = lr.top; + ScrollWindowEx( + hwnd, + 0, + dy, + &sr, + &sr, + NULL, + NULL, + SW_INVALIDATE); + } + + if(lr.top < lr.bottom && lr.left < lr.right) { + InvalidateRect(hwnd, &lr, FALSE); + } +} + +LRESULT +cw_wm_vscroll(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + SCROLLINFO si; + int newpos; + RECT cr; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return 0; + + GetClientRect(hwnd, &cr); + cr.top += tbl->header_height; + + switch(LOWORD(wParam)) { + case SB_LEFT: + newpos = 0; + break; + + case SB_BOTTOM: + newpos = tbl->ext_height; + break; + + case SB_LINEUP: + newpos = tbl->scr_top - (tbl->ext_height / 12); + break; + + case SB_LINEDOWN: + newpos = tbl->scr_top + (tbl->ext_height / 12); + break; + + case SB_PAGEUP: + newpos = tbl->scr_top - (cr.bottom - cr.top); + break; + + case SB_PAGEDOWN: + newpos = tbl->scr_top + (cr.bottom - cr.top); + break; + + case SB_THUMBTRACK: + case SB_THUMBPOSITION: + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_TRACKPOS; + GetScrollInfo(hwnd, SB_VERT, &si); + + newpos = si.nTrackPos; + break; + + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + + cw_vscroll_to_pos(hwnd, tbl, newpos); + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +static void +cw_ensure_row_visible(HWND hwnd, khui_credwnd_tbl * tbl, int row) { + RECT r; + int newpos; + + if (row < 0) + row = 0; + else if (row >= (int) tbl->n_rows) + row = (int) tbl->n_rows - 1; + + GetClientRect(hwnd, &r); + r.top += tbl->header_height; + + if (row * tbl->cell_height < tbl->scr_top) { + newpos = row * tbl->cell_height; + } else if ((row + 1) * tbl->cell_height + > tbl->scr_top + (r.bottom - r.top)) { + newpos = ((row + 1) * tbl->cell_height) - (r.bottom - r.top); + } else + return; + + cw_vscroll_to_pos(hwnd, tbl, newpos); +} + +static INT_PTR CALLBACK +cw_pp_ident_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + khui_property_sheet * s; + + switch(uMsg) { + case WM_INITDIALOG: + { + PROPSHEETPAGE * p; + khm_handle ident; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size t; + khm_int32 i; + + p = (PROPSHEETPAGE *) lParam; + s = (khui_property_sheet *) p->lParam; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s); +#pragma warning(pop) + + ident = s->identity; + + t = sizeof(idname); + kcdb_identity_get_name(ident, idname, &t); + SetDlgItemText(hwnd, IDC_PP_IDNAME, idname); + + kcdb_identity_get_flags(ident, &i); + + CheckDlgButton(hwnd, IDC_PP_IDDEF, + ((i & KCDB_IDENT_FLAG_DEFAULT)?BST_CHECKED: + BST_UNCHECKED)); + + /* if it's default, you can't change it further */ + if (i & KCDB_IDENT_FLAG_DEFAULT) { + EnableWindow(GetDlgItem(hwnd, IDC_PP_IDDEF), FALSE); + } + + CheckDlgButton(hwnd, IDC_PP_IDSEARCH, + ((i & KCDB_IDENT_FLAG_SEARCHABLE)?BST_CHECKED: + BST_UNCHECKED)); + + CheckDlgButton(hwnd, IDC_PP_STICKY, + ((i & KCDB_IDENT_FLAG_STICKY)?BST_CHECKED: + BST_UNCHECKED)); + + khui_property_wnd_set_record(GetDlgItem(hwnd, IDC_PP_PROPLIST), + ident); + } + return TRUE; + + case WM_COMMAND: + s = (khui_property_sheet *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (s == NULL) + return 0; + + switch(wParam) { + case MAKEWPARAM(IDC_PP_IDDEF, BN_CLICKED): + /* fallthrough */ + case MAKEWPARAM(IDC_PP_STICKY, BN_CLICKED): + + if (s->status != KHUI_PS_STATUS_NONE) + PropSheet_Changed(s->hwnd, hwnd); + return TRUE; + + case MAKEWPARAM(IDC_PP_CONFIG, BN_CLICKED): + { + khui_config_node cfg_id = NULL; + khui_config_node cfg_ids = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_int32 rv; + + khm_refresh_config(); + + rv = khui_cfg_open(NULL, + L"KhmIdentities", + &cfg_ids); + + if (KHM_FAILED(rv)) + return TRUE; + + cb = sizeof(idname); + if (KHM_SUCCEEDED(kcdb_identity_get_name(s->identity, + idname, + &cb))) { + rv = khui_cfg_open(cfg_ids, + idname, + &cfg_id); + } + + if (cfg_id) + khm_show_config_pane(cfg_id); + else + khm_show_config_pane(cfg_ids); + + if (cfg_ids) + khui_cfg_release(cfg_ids); + if (cfg_id) + khui_cfg_release(cfg_id); + } + return TRUE; + } + return FALSE; + + case WM_NOTIFY: + { + LPPSHNOTIFY lpp; + khm_int32 flags; + + lpp = (LPPSHNOTIFY) lParam; + s = (khui_property_sheet *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (s == NULL) + return 0; + + switch(lpp->hdr.code) { + case PSN_APPLY: + flags = 0; + if (IsDlgButtonChecked(hwnd, IDC_PP_STICKY) == BST_CHECKED) + flags |= KCDB_IDENT_FLAG_STICKY; + if (IsDlgButtonChecked(hwnd, IDC_PP_IDDEF) == BST_CHECKED) + flags |= KCDB_IDENT_FLAG_DEFAULT; + + kcdb_identity_set_flags(s->identity, flags, + KCDB_IDENT_FLAG_STICKY | + KCDB_IDENT_FLAG_DEFAULT); + khm_refresh_identity_menus(); + return TRUE; + + case PSN_RESET: + kcdb_identity_get_flags(s->identity, &flags); + + CheckDlgButton(hwnd, + IDC_PP_IDDEF, + ((flags & KCDB_IDENT_FLAG_DEFAULT)?BST_CHECKED: + BST_UNCHECKED)); + + /* if it's default, you can't change it further */ + if (flags & KCDB_IDENT_FLAG_DEFAULT) { + EnableWindow(GetDlgItem(hwnd, IDC_PP_IDDEF), FALSE); + } + + CheckDlgButton(hwnd, IDC_PP_IDSEARCH, + ((flags & KCDB_IDENT_FLAG_SEARCHABLE)?BST_CHECKED:BST_UNCHECKED)); + + CheckDlgButton(hwnd, IDC_PP_STICKY, + ((flags & KCDB_IDENT_FLAG_STICKY)?BST_CHECKED:BST_UNCHECKED)); + return TRUE; + } + } + break; + } + return FALSE; +} + +static INT_PTR CALLBACK +cw_pp_cred_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + switch(uMsg) { + case WM_INITDIALOG: + { + khui_property_sheet * s; + PROPSHEETPAGE * p; + khm_handle cred; + + p = (PROPSHEETPAGE *) lParam; + s = (khui_property_sheet *) p->lParam; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s); +#pragma warning(pop) + + cred = s->cred; + + khui_property_wnd_set_record( + GetDlgItem(hwnd, IDC_PP_CPROPLIST), + cred); + } + return TRUE; + } + return FALSE; +} + +static void +cw_pp_begin(khui_property_sheet * s) +{ + PROPSHEETPAGE *p; + + if(s->identity) { + p = PMALLOC(sizeof(*p)); + ZeroMemory(p, sizeof(*p)); + + p->dwSize = sizeof(*p); + p->dwFlags = 0; + p->hInstance = khm_hInstance; + p->pszTemplate = MAKEINTRESOURCE(IDD_PP_IDENT); + p->pfnDlgProc = cw_pp_ident_proc; + p->lParam = (LPARAM) s; + + khui_ps_add_page(s, KHUI_PPCT_IDENTITY, 129, p, NULL); + } + + if(s->cred) { + p = PMALLOC(sizeof(*p)); + ZeroMemory(p, sizeof(*p)); + + p->dwSize = sizeof(*p); + p->dwFlags = 0; + p->hInstance = khm_hInstance; + p->pszTemplate = MAKEINTRESOURCE(IDD_PP_CRED); + p->pfnDlgProc = cw_pp_cred_proc; + p->lParam = (LPARAM) s; + + khui_ps_add_page(s, KHUI_PPCT_CREDENTIAL, 128, p, NULL); + } +} + +static void +cw_pp_precreate(khui_property_sheet * s) +{ + khui_ps_show_sheet(khm_hwnd_main, s); + + khm_add_property_sheet(s); +} + +static void +cw_pp_end(khui_property_sheet * s) +{ + khui_property_page * p = NULL; + + khui_ps_find_page(s, KHUI_PPCT_IDENTITY, &p); + if(p) { + PFREE(p->p_page); + p->p_page = NULL; + } + + p = NULL; + + khui_ps_find_page(s, KHUI_PPCT_CREDENTIAL, &p); + if(p) { + PFREE(p->p_page); + p->p_page = NULL; + } +} + +static void +cw_pp_destroy(khui_property_sheet *ps) +{ + if(ps->ctx.scope == KHUI_SCOPE_CRED) { + if(ps->header.pszCaption) + PFREE((LPWSTR) ps->header.pszCaption); + } + + khui_context_release(&ps->ctx); + + khui_ps_destroy_sheet(ps); + + /* this is pretty weird because ps gets freed when + khui_ps_destroy_sheet() is called. However, since destroying + ps involves sending a WM_DESTROY message to the property sheet, + we still need to keep it on the property sheet chain (or else + the messages will not be delivered). This is only safe because + we are not relinquishing the thread in-between destroying ps + and removing it from the chain. */ + + /* TODO: fix this */ + khm_del_property_sheet(ps); +} + +LRESULT +cw_properties(HWND hwnd) +{ + /* show a property sheet of some sort */ + khui_action_context ctx; + khui_property_sheet * ps; + khui_credwnd_tbl * tbl; + + khui_context_get(&ctx); + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return 0; + + if(ctx.scope == KHUI_SCOPE_NONE) { + khui_context_release(&ctx); + return FALSE; + } + + /* if still no context, then we can't show a property sheet */ + if(ctx.scope == KHUI_SCOPE_NONE) { + khui_context_release(&ctx); + return FALSE; + } + + khui_ps_create_sheet(&ps); + + if(ctx.scope == KHUI_SCOPE_IDENT) { + khm_handle ident; + khm_size t; + + ident = ctx.identity; + + ps->header.hInstance = khm_hInstance; + ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP); + + kcdb_identity_get_name(ident, NULL, &t); + + if(t > 0) { + ps->header.pszCaption = PMALLOC(t); + kcdb_identity_get_name(ident, + (wchar_t *) ps->header.pszCaption, &t); + } else { + ps->header.pszCaption = NULL; + } + + ps->ctx = ctx; + ps->identity = ident; + ps->credtype = KCDB_CREDTYPE_INVALID; + + kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps); + + } else if(ctx.scope == KHUI_SCOPE_CREDTYPE) { + khm_size t = 0; + khm_int32 cred_type; + + if (ctx.identity == NULL) { + /* currently, we can't show a property sheet at this point + since most credentials providers don't provide a + property sheet that works without an identity. */ + + khui_context_release(&ctx); + khui_ps_destroy_sheet(ps); + return TRUE; + } + + cred_type = ctx.cred_type; + + ps->header.hInstance = khm_hInstance; + ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP); + + ps->ctx = ctx; + ps->credtype = cred_type; + + if(ctx.identity) { + ps->identity = ctx.identity; + /* also, if there is an associated identity, we assume that + the properties are for the specified credentials type + specific to the identity. Hence we change the title to + something else */ + kcdb_identity_get_name(ctx.identity, NULL, &t); + if (t > 0) { + ps->header.pszCaption = PMALLOC(t); + kcdb_identity_get_name(ctx.identity, (wchar_t *) ps->header.pszCaption, &t); + } else { + ps->header.pszCaption = NULL; + } + } else { + /* we don't actually reach here since we handle this case + above */ + kcdb_credtype_describe(cred_type, NULL, &t, KCDB_TS_LONG); + if(t > 0) { + ps->header.pszCaption = PMALLOC(t); + kcdb_credtype_describe(cred_type, (wchar_t *) ps->header.pszCaption, &t, KCDB_TS_LONG); + } else { + ps->header.pszCaption = NULL; + } + } + + kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps); + } else if(ctx.scope == KHUI_SCOPE_CRED) { + khm_handle cred; + khm_size t; + + cred = ctx.cred; + + ps->header.hInstance = khm_hInstance; + ps->header.pszIcon = MAKEINTRESOURCE(IDI_MAIN_APP); + ps->ctx = ctx; + + kcdb_cred_get_name(cred, NULL, &t); + ps->header.pszCaption = PMALLOC(t); + kcdb_cred_get_name(cred, (LPWSTR) ps->header.pszCaption, &t); + + kcdb_cred_get_identity(cred, &ps->identity); + kcdb_cred_get_type(cred, &ps->credtype); + ps->cred = cred; + + kmq_post_message(KMSG_CRED, KMSG_CRED_PP_BEGIN, 0, (void *) ps); + } else { + khui_context_release(&ctx); + khui_ps_destroy_sheet(ps); + } + + /* by the way, if we are actually opening a property sheet, we + leave ctx held (which is now copied to ps->ctx). it will be + released when the property sheet is destroyed */ + + return TRUE; +} + +LRESULT +cw_wm_command(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + khui_credwnd_tbl * tbl; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return 0; + + if(HIWORD(wParam) == BN_CLICKED && + LOWORD(wParam) == KHUI_HTWND_CTLID) { + + wchar_t wid[256]; + /* a hyperlink was activated */ + khui_htwnd_link * l; + l = (khui_htwnd_link *) lParam; + StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len); + wid[l->id_len] = 0; + + if(!wcscmp(wid, L"NewCreds")) { + PostMessage(khm_hwnd_main, WM_COMMAND, + MAKEWPARAM(KHUI_ACTION_NEW_CRED,0), 0); + } + return TRUE; + } + + switch(LOWORD(wParam)) + { + case KHUI_PACTION_ENTER: + /* enter key is a synonym for the default action, on the + context, which is to lauch a property sheet */ + /* fallthrough */ + case KHUI_ACTION_PROPERTIES: + { + return cw_properties(hwnd); + } + break; + + case KHUI_ACTION_LAYOUT_RELOAD: + { + wchar_t cname[KCONF_MAXCCH_NAME]; + khm_size cb; + + cname[0] = L'\0'; + + if (tbl->csp_view) { + cb = sizeof(cname); + khc_get_config_space_name(tbl->csp_view, + cname, + &cb); + } + + cw_unload_view(tbl); + + cw_load_view(tbl, ((cname[0])?cname: NULL), hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_select_row(tbl, tbl->cursor_row, 0); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + } + break; + + case KHUI_ACTION_LAYOUT_ID: + { + cw_save_view(tbl, NULL); + cw_unload_view(tbl); + + cw_load_view(tbl, L"ByIdentity", hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_select_row(tbl, tbl->cursor_row, 0); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + + } + break; + + case KHUI_ACTION_LAYOUT_LOC: + { + cw_save_view(tbl, NULL); + cw_unload_view(tbl); + + cw_load_view(tbl, L"ByLocation", hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_select_row(tbl, tbl->cursor_row, 0); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + + } + break; + + case KHUI_ACTION_LAYOUT_TYPE: + { + cw_save_view(tbl, NULL); + cw_unload_view(tbl); + + cw_load_view(tbl, L"ByType", hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_select_row(tbl, tbl->cursor_row, 0); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + + } + break; + + case KHUI_ACTION_LAYOUT_CUST: + { + cw_save_view(tbl, NULL); + cw_unload_view(tbl); + + cw_load_view(tbl, L"Custom_0", hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_select_row(tbl, tbl->cursor_row, 0); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + + } + break; + + case KHUI_ACTION_LAYOUT_MINI: + { + cw_save_view(tbl, NULL); + cw_unload_view(tbl); + + cw_load_view(tbl, NULL, hwnd); + cw_insert_header_cols(tbl); + + cw_update_creds(tbl); + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_select_row(tbl, tbl->cursor_row, 0); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + } + break; + + case KHUI_ACTION_VIEW_ALL_IDS: + { + khm_handle hc_cw = NULL; + + tbl->view_all_idents = !tbl->view_all_idents; + + cw_update_outline(tbl); + cw_update_extents(tbl, TRUE); + cw_update_selection_state(tbl); + + InvalidateRect(tbl->hwnd, NULL, TRUE); + + if(KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ | KHM_PERM_WRITE, + &hc_cw))) { + khc_write_int32(hc_cw, L"ViewAllIdents", tbl->view_all_idents); + khc_close_space(hc_cw); + } + + khui_check_action(KHUI_ACTION_VIEW_ALL_IDS, tbl->view_all_idents); + + khm_refresh_identity_menus(); + } + break; + + case KHUI_PACTION_UP: + case KHUI_PACTION_UP_EXTEND: + case KHUI_PACTION_UP_TOGGLE: + { /* cursor up */ + khm_int32 new_row; + WPARAM wp = 0; + + new_row = tbl->cursor_row - 1; + + /* checking both bounds. we make no assumption about the + value of cursor_row before this message */ + if(new_row < 0) + new_row = 0; + if(new_row >= (int) tbl->n_rows) + new_row = (int) tbl->n_rows - 1; + + if (LOWORD(wParam) == KHUI_PACTION_UP) + wp = 0; + else if (LOWORD(wParam) == KHUI_PACTION_UP_EXTEND) + wp = MK_SHIFT; + else if (LOWORD(wParam) == KHUI_PACTION_UP_TOGGLE) + wp = 0; //MK_CONTROL; + else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + cw_select_row(tbl, new_row, wp); + cw_ensure_row_visible(hwnd, tbl, new_row); + } + break; + + case KHUI_PACTION_PGUP_EXTEND: + case KHUI_PACTION_PGUP: + { + khm_int32 new_row; + WPARAM wp; + RECT r; + + if (LOWORD(wParam) == KHUI_PACTION_PGUP_EXTEND) + wp = MK_SHIFT; + else + wp = 0; + + GetClientRect(hwnd, &r); + + new_row = tbl->cursor_row - + ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height; + + if (new_row < 0) + new_row = 0; + if (new_row >= (int) tbl->n_rows) + new_row = (int) tbl->n_rows - 1; + + cw_select_row(tbl, new_row, wp); + cw_ensure_row_visible(hwnd, tbl, new_row); + } + break; + + case KHUI_PACTION_DOWN: + case KHUI_PACTION_DOWN_EXTEND: + case KHUI_PACTION_DOWN_TOGGLE: + { /* cursor down */ + khm_int32 new_row; + WPARAM wp = 0; + + new_row = tbl->cursor_row + 1; + + /* checking both bounds. we make no assumption about the + value of cursor_row before this message */ + if(new_row < 0) + new_row = 0; + if(new_row >= (int) tbl->n_rows) + new_row = (int) tbl->n_rows - 1; + + if (LOWORD(wParam) == KHUI_PACTION_DOWN) + wp = 0; + else if (LOWORD(wParam) == KHUI_PACTION_DOWN_EXTEND) + wp = MK_SHIFT; + else if (LOWORD(wParam) == KHUI_PACTION_DOWN_TOGGLE) + wp = 0; //MK_CONTROL; + else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + cw_select_row(tbl, new_row, wp); + cw_ensure_row_visible(hwnd, tbl, new_row); + } + break; + + case KHUI_PACTION_PGDN_EXTEND: + case KHUI_PACTION_PGDN: + { + khm_int32 new_row; + RECT r; + WPARAM wp; + + if (LOWORD(wParam) == KHUI_PACTION_PGDN_EXTEND) + wp = MK_SHIFT; + else + wp = 0; + + GetClientRect(hwnd, &r); + + new_row = tbl->cursor_row + + ((r.bottom - r.top) - tbl->header_height) / tbl->cell_height; + + if (new_row < 0) + new_row = 0; + if (new_row >= (int) tbl->n_rows) + new_row = (int) tbl->n_rows - 1; + + cw_select_row(tbl, new_row, wp); + cw_ensure_row_visible(hwnd, tbl, new_row); + } + break; + + case KHUI_PACTION_SELALL: + { + cw_select_all(tbl); + } + break; + + case KHUI_PACTION_LEFT: + { /* collapse and up*/ + khui_credwnd_outline * o; + int r; + + if(tbl->cursor_row < 0 || tbl->cursor_row >= (int) tbl->n_rows) { + cw_select_row(tbl, 0, 0); + break; + } + + for(r = tbl->cursor_row; + (r >= 0 && !(tbl->rows[r].flags & KHUI_CW_ROW_HEADER)); + r--); + + if(r < 0) + break; + + /* If we were not on a header, we collapse the innermost + outline. Otherwise, we collpase up to the parent + outline level */ + + if(r != tbl->cursor_row) { + o = (khui_credwnd_outline *) tbl->rows[r].data; + + cw_toggle_outline_state(tbl, o); + } else { + o = (khui_credwnd_outline *) tbl->rows[r].data; + + if(o->flags & KHUI_CW_O_EXPAND) { + cw_toggle_outline_state(tbl, o); + } else { + o = TPARENT(o); + if(o) { + cw_toggle_outline_state(tbl, o); + r = o->start; + } else if(r > 0) + r--; + } + } + + cw_select_row(tbl, r, 0); + } + break; + + case KHUI_PACTION_RIGHT: + { /* expand and down*/ + khui_credwnd_outline * o; + int r; + + if(tbl->cursor_row < 0 || + tbl->cursor_row >= (int) tbl->n_rows) { + cw_select_row(tbl, 0, 0); + break; + } + + r = tbl->cursor_row; + + if(tbl->rows[r].flags & KHUI_CW_ROW_HEADER) { + o = (khui_credwnd_outline *) tbl->rows[r].data; + if(!(o->flags & KHUI_CW_O_EXPAND)) { + cw_toggle_outline_state(tbl, o); + } + } + + r++; + if (r >= (int) tbl->n_rows) + r = (int)tbl->n_rows - 1; + + cw_select_row(tbl, r, 0); + } + break; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +LRESULT +cw_wm_contextmenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + RECT r; + int x,y; + int row; + khui_credwnd_tbl * tbl; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return 0; + + GetWindowRect(hwnd, &r); + + x = GET_X_LPARAM(lParam); + y = GET_Y_LPARAM(lParam); + + /* if the user invokes the context menu using the keyboard, we get + x=-1 and y=-1. In this case, we use the cursor_row as the + target row. */ + if (x == -1 && y == -1) { + + row = tbl->cursor_row; + + if (tbl->flags & KHUI_CW_TBL_EXPIDENT) { + int i; + + y = 0; + for (i=0; i < tbl->n_rows && i < row; i++) { + if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW) + y += tbl->cell_height * CW_EXP_ROW_MULT; + else + y += tbl->cell_height; + } + } else { + y = row * tbl->cell_height; + } + + x = r.left; + y = y + r.top + tbl->header_height - tbl->scr_top; + + goto have_row; + } + + x += tbl->scr_left - r.left; + y += tbl->scr_top - tbl->header_height - r.top; + + if (y < 0) { + /* context menu for header control */ + khm_menu_show_panel(KHUI_MENU_CWHEADER_CTX, + GET_X_LPARAM(lParam), + GET_Y_LPARAM(lParam)); + + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + + if (tbl->flags & KHUI_CW_TBL_EXPIDENT) { + int i, yt; + + yt = 0; + for (i=0; i < tbl->n_rows && yt < y; i++) { + if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW) + yt += tbl->cell_height * CW_EXP_ROW_MULT; + else + yt += tbl->cell_height; + if (yt > y) + break; + } + + row = i; + + } else { + row = y / tbl->cell_height; + } + + if(row < 0 || row >= (int) tbl->n_rows) + return FALSE; + + /* now, if the user has right clicked outside the selection, we + treat the right-click as a regular click before showing the + context menu. */ + if (!(tbl->rows[row].flags & KHUI_CW_ROW_SELECTED)) { + cw_select_row(tbl, row, 0); + } + + x = GET_X_LPARAM(lParam); + y = GET_Y_LPARAM(lParam); + + have_row: + + cw_set_row_context(tbl, row); + + khm_menu_show_panel(KHUI_MENU_IDENT_CTX, x, y); + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +/* copy and paste template */ +#if 0 +LRESULT +cw_wm_msg(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} +#endif + +LRESULT CALLBACK +khm_credwnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_COMMAND: + return cw_wm_command(hwnd, uMsg, wParam, lParam); + + case WM_CREATE: + return cw_wm_create(hwnd, uMsg, wParam, lParam); + + case WM_DESTROY: + return cw_wm_destroy(hwnd, uMsg, wParam, lParam); + + case WM_ERASEBKGND: + /* we don't bother wasting cycles erasing the background + because the foreground elements completely cover the + client area */ + return FALSE; + + case WM_PAINT: + return cw_wm_paint(hwnd, uMsg, wParam, lParam); + + case WM_PRINTCLIENT: + return cw_wm_paint(hwnd, uMsg, wParam, lParam); + + case WM_SIZE: + return cw_wm_size(hwnd, uMsg, wParam, lParam); + + case WM_NOTIFY: + return cw_wm_notify(hwnd, uMsg, wParam, lParam); + + case WM_HSCROLL: + return cw_wm_hscroll(hwnd, uMsg, wParam, lParam); + + case WM_VSCROLL: + return cw_wm_vscroll(hwnd, uMsg, wParam, lParam); + + case KMQ_WM_DISPATCH: + return cw_kmq_wm_dispatch(hwnd, uMsg, wParam, lParam); + + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_MOUSEMOVE: + case WM_LBUTTONUP: + return cw_wm_mouse(hwnd, uMsg, wParam, lParam); + + case WM_CONTEXTMENU: + return cw_wm_contextmenu(hwnd, uMsg, wParam, lParam); + } + + return DefWindowProc(hwnd,uMsg,wParam,lParam); +} + +void +khm_measure_identity_menu_item(HWND hwnd, LPMEASUREITEMSTRUCT lpm, khui_action * act) +{ + wchar_t * cap; + HDC hdc; + SIZE sz; + size_t len; + HFONT hf_old; + + sz.cx = MENU_SIZE_ICON_X; + sz.cy = MENU_SIZE_ICON_Y; + + cap = act->caption; +#ifdef DEBUG + assert(cap); +#endif + hdc = GetDC(khm_hwnd_main); +#ifdef DEBUG + assert(hdc); +#endif + + StringCchLength(cap, KHUI_MAXCCH_NAME, &len); + + hf_old = SelectFont(hdc, (HFONT) GetStockObject(DEFAULT_GUI_FONT)); + + GetTextExtentPoint32(hdc, cap, (int) len, &sz); + + SelectFont(hdc, hf_old); + + ReleaseDC(khm_hwnd_main, hdc); + + lpm->itemWidth = sz.cx + sz.cy * 3 / 2 + GetSystemMetrics(SM_CXSMICON); + lpm->itemHeight = sz.cy * 3 / 2; +} + +void +khm_draw_identity_menu_item(HWND hwnd, LPDRAWITEMSTRUCT lpd, khui_action * act) +{ + khui_credwnd_tbl * tbl; + khm_handle ident; + size_t count = 0; + COLORREF old_clr; + wchar_t * cap; + size_t len; + int margin; + SIZE sz; + HBRUSH hbr; + COLORREF text_clr; + khm_int32 idflags; + khm_int32 expflags; + + tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (tbl == NULL) + return; + + ident = act->data; + cap = act->caption; +#ifdef DEBUG + assert(ident != NULL); + assert(cap != NULL); +#endif + + { + khui_credwnd_ident * cwi; + + cwi = cw_find_ident(tbl, ident); + if (cwi) { + count = cwi->id_credcount; + } else { + count = 0; + } + } + + expflags = cw_get_buf_exp_flags(tbl, ident); + + text_clr = tbl->cr_hdr_normal; + + if (lpd->itemState & (ODS_HOTLIGHT | ODS_SELECTED)) { + hbr = GetSysColorBrush(COLOR_HIGHLIGHT); + text_clr = GetSysColor(COLOR_HIGHLIGHTTEXT); + } else if (expflags == CW_EXPSTATE_EXPIRED) { + hbr = tbl->hb_hdr_bg_exp; + } else if (expflags == CW_EXPSTATE_WARN) { + hbr = tbl->hb_hdr_bg_warn; + } else if (expflags == CW_EXPSTATE_CRITICAL) { + hbr = tbl->hb_hdr_bg_crit; + } else if (count > 0) { + hbr = tbl->hb_hdr_bg_cred; + } else { + hbr = tbl->hb_hdr_bg; + } + + FillRect(lpd->hDC, &lpd->rcItem, hbr); + + SetBkMode(lpd->hDC, TRANSPARENT); + + old_clr = SetTextColor(lpd->hDC, text_clr); + + StringCchLength(cap, KHUI_MAXCCH_NAME, &len); + + GetTextExtentPoint32(lpd->hDC, cap, (int) len, &sz); + margin = sz.cy / 4; + + TextOut(lpd->hDC, lpd->rcItem.left + margin * 2 + GetSystemMetrics(SM_CXSMICON), + lpd->rcItem.top + margin, cap, (int) len); + + SetTextColor(lpd->hDC, old_clr); + + kcdb_identity_get_flags(ident, &idflags); + + if (idflags & KCDB_IDENT_FLAG_DEFAULT) { + HICON hic; + + hic = (HICON) LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_ENABLED), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + if (hic) { + DrawIconEx(lpd->hDC, + lpd->rcItem.left + margin, + lpd->rcItem.top + margin, + hic, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + 0, + hbr, + DI_NORMAL); + DestroyIcon(hic); + } + } +} + +void +khm_register_credwnd_class(void) { + WNDCLASSEX wcx; + kcdb_attrib attrib; + khm_int32 attr_id; + + wcx.cbSize = sizeof(wcx); + wcx.style = CS_DBLCLKS | CS_OWNDC; + wcx.lpfnWndProc = khm_credwnd_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = sizeof(LONG_PTR); + wcx.hInstance = khm_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_CREDWND_CLASS_NAME; + wcx.hIconSm = NULL; + + khui_credwnd_cls = RegisterClassEx(&wcx); + + /* while we are at it, register the credwnd attribute type as well, and + obtain the type ID */ + if(KHM_FAILED(kcdb_attrib_get_id(KHUI_CREDWND_FLAG_ATTRNAME, &attr_id))) { + ZeroMemory(&attrib, sizeof(attrib)); + attrib.id = KCDB_ATTR_INVALID; + attrib.flags = KCDB_ATTR_FLAG_HIDDEN; + attrib.type = KCDB_TYPE_INT32; + attrib.name = KHUI_CREDWND_FLAG_ATTRNAME; + + kcdb_attrib_register(&attrib, &attr_id); + } + + khui_cw_flag_id = attr_id; +} + +void +khm_unregister_credwnd_class(void) { + UnregisterClass(MAKEINTATOM(khui_credwnd_cls), khm_hInstance); +} + +HWND +khm_create_credwnd(HWND parent) { + RECT r; + HWND hwnd; + + ZeroMemory(attr_to_action, sizeof(attr_to_action)); + + GetClientRect(parent, &r); + + hwnd = CreateWindowEx + (0, + MAKEINTATOM(khui_credwnd_cls), + L"", + WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + r.left, + r.top, + r.right - r.left, + r.bottom - r.top, + parent, + NULL, + khm_hInstance, + NULL); + + return hwnd; +} diff --git a/krb5-1-6/src/windows/identity/ui/credwnd.h b/krb5-1-6/src/windows/identity/ui/credwnd.h new file mode 100644 index 000000000..7f9071014 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/credwnd.h @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_CREDWND_H +#define __KHIMAIRA_CREDWND_H + +#define KHUI_CREDWND_CLASS_NAME L"NetIDMgrCredWnd" + +#define KHUI_CREDWND_FLAG_ATTRNAME L"CredWndFlags" + +extern khm_int32 khui_cw_flag_id; + +/* The expiration states */ +#define CW_EXPSTATE_NONE 0x00000000 +#define CW_EXPSTATE_WARN 0x00000400 +#define CW_EXPSTATE_CRITICAL 0x00000800 +#define CW_EXPSTATE_EXPIRED 0x00000c00 + +#define CW_EXPSTATE_MASK 0x00000c00 + +typedef struct khui_credwnd_outline_t { + khm_int32 flags; /* combination of KHUI_CW_O_* */ + khm_int32 start; /* first row of outline */ + khm_int32 length; /* number of rows in outline */ + khm_int32 level; /* outline level */ + khm_int32 col; /* outline column */ + wchar_t *header; /* character string associated with header */ + khm_int32 attr_id; + void * data; /* level specific data : + Identity -> handle to identity + Type -> type ID + otherwise -> canonical data buffer + */ + khm_size cb_data; + + khm_size idx_start; /* index of the first cred in the credset */ + khm_size idx_end; /* index of the last cred in the credset */ + TDCL(struct khui_credwnd_outline_t); +} khui_credwnd_outline; + +#define KHUI_CW_O_EXPAND 0x00000001 +#define KHUI_CW_O_STICKY 0x00000002 +#define KHUI_CW_O_VISIBLE 0x00000004 +#define KHUI_CW_O_SHOWFLAG 0x00000008 +#define KHUI_CW_O_SELECTED 0x00000010 +#define KHUI_CW_O_DATAALLOC 0x00000020 +#define KHUI_CW_O_NOOUTLINE 0x00000040 +#define KHUI_CW_O_RELIDENT 0x00000080 +#define KHUI_CW_O_EMPTY 0x00000100 +/* NOTE: KHUI_CW_O_* shares the same bit-space as CW_EXPSTATE_* */ + +typedef struct khui_credwnd_row_t { + khm_int32 flags; + khm_int32 col; + khm_handle data; + khm_size idx_start; + khm_size idx_end; + RECT r_ext; /* extents of this row */ +} khui_credwnd_row; + +#define KHUI_CW_ROW_CRED 0x00000002 +#define KHUI_CW_ROW_HEADER 0x00000004 +#define KHUI_CW_ROW_TIMERSET 0x00000008 +#define KHUI_CW_ROW_SELECTED 0x00000010 +#define KHUI_CW_ROW_EXPVIEW 0x00000020 +/* NOTE: KHUI_CW_ROW_* shares the same bit-space as CW_EXPSTATE_* */ + +/* row allocation */ +/* initial number of rows to be allocated */ +#define KHUI_CW_ROW_INITIAL 512 +/* allocation increment, if we run out of space */ +#define KHUI_CW_ROW_INCREMENT 512 + +typedef struct khui_credwnd_col_t { + khm_int32 attr_id; + khm_int32 width; /* width of the column (screen units) */ + khm_int32 x; /* starting x coordinate (screen units) */ + khm_int32 flags; /* combination of KHUI_CW_COL_* */ + khm_int32 sort_index; + wchar_t * title; +} khui_credwnd_col; + +/* column allocation */ +/* initial number of columns to be allocated */ +#define KHUI_CW_COL_INITIAL 16 +/* allocation increment, if we run out of space */ +#define KHUI_CW_COL_INCREMENT 16 + +#define KHUI_CW_COL_AUTOSIZE 0x00000001 +#define KHUI_CW_COL_SORT_INC 0x00000002 +#define KHUI_CW_COL_SORT_DEC 0x00000004 +#define KHUI_CW_COL_GROUP 0x00000008 +#define KHUI_CW_COL_FIXED_WIDTH 0x00000010 +#define KHUI_CW_COL_FIXED_POS 0x00000020 +#define KHUI_CW_COL_META 0x00000040 +#define KHUI_CW_COL_FILLER 0x00000080 + +/* Custom column attributes (are not kcdb attributes) */ +#define CW_CA_FLAGS -1 +#define CW_CANAME_FLAGS L"_CWFlags" + +#define CW_CA_TYPEICON -2 +#define CW_CANAME_TYPEICON L"_CWTypeIcon" + +#define cw_is_custom_attr(i) ((i)<0) + +typedef struct tag_khui_credwnd_ident { + + khm_handle ident; + khm_int32 ident_flags; + khm_int32 credtype; + wchar_t name[KCDB_IDENT_MAXCCH_NAME]; + wchar_t credtype_name[KCDB_MAXCCH_NAME]; + + khm_size credcount; /* count of all credentials */ + khm_size id_credcount; /* count of identity credentials + (credentials that are of the + identity type */ + khm_size init_credcount; /* count of initial credentials */ + FILETIME ft_expire; + +} khui_credwnd_ident; + +#define CW_IDENT_ALLOC_INCR 4 + +#define CW_EXP_ROW_MULT 2 + +typedef struct khui_credwnd_tbl_t { + HWND hwnd; /* the window that this table belongs to */ + + khm_handle csp_view; /* handle to the configuration space + that defined the view */ + + khm_int32 scr_top; /* screen units */ + khm_int32 scr_left; /* screen units */ + khm_int32 ext_width; /* screen units */ + khm_int32 ext_height; /* screen units */ + khm_int32 cell_height; /* screen units */ + + HWND hwnd_header; /* header control */ + khm_int32 header_height; /* height of the header */ + HWND hwnd_notif; /* notification control */ + + khui_credwnd_col * cols; /* n_cols elements */ + khui_credwnd_row * rows; /* n_rows elements */ + int n_cols; + int n_total_cols; /* number of columns actually + allocated in cols */ + int n_rows; + int n_total_rows; /* number of rows actually allocated + in rows */ + + khui_credwnd_outline * outline; + + khm_int32 flags; /* combo of KHUI_CW_TBL_* */ + + int cursor_row; /* cursor and selection */ + int anchor_row; /* anchor, for range selections */ + + /* view parameters */ + khm_int32 hpad; + khm_int32 vpad; + khm_int32 hpad_h; /* horizontal padding correction for headers */ + khm_int32 threshold_warn; /* Warning threshold, in seconds*/ + khm_int32 threshold_critical; /* Critical threshold, in seconds */ + + /* graphics objects we are going to need. */ + HFONT hf_normal; /* normal text */ + HFONT hf_header; /* header text */ + HFONT hf_bold; /* bold text */ + HFONT hf_bold_header; /* bold header text */ + + HBRUSH hb_normal; /* normal background brush */ + HBRUSH hb_grey; /* normal background brush (greyed) */ + HBRUSH hb_s; /* normal background brush (selected) */ + + HBRUSH hb_hdr_bg; /* header background brush (normal) */ + HBRUSH hb_hdr_bg_cred; /* header background brush (valid creds) */ + HBRUSH hb_hdr_bg_exp; /* header background brush (expired) */ + HBRUSH hb_hdr_bg_warn; /* header background brush (warn) */ + HBRUSH hb_hdr_bg_crit; /* header background brush (critical) */ + + HBRUSH hb_hdr_bg_s; /* header background brush (selected) */ + HBRUSH hb_hdr_bg_cred_s;/* header background brush (valid creds) */ + HBRUSH hb_hdr_bg_exp_s; /* header background brush (expired,selected) */ + HBRUSH hb_hdr_bg_warn_s;/* header background brush (warn,selected) */ + HBRUSH hb_hdr_bg_crit_s;/* header background brush (critical,selected) */ + + COLORREF cr_normal; /* text color (normal) */ + COLORREF cr_s; /* text color (selected) */ + COLORREF cr_hdr_normal; /* header text color (normal) */ + COLORREF cr_hdr_s; /* header text color (selected) */ + COLORREF cr_hdr_gray; /* header text color (greyed) */ + COLORREF cr_hdr_gray_s; /* header text color (greyed,selected) */ + + COLORREF cr_hdr_outline;/* header outline color */ + + HCURSOR hc_hand; /* the HAND cursor */ + khui_ilist * ilist; /* image list */ + + HICON hi_lg_ident; /* large identity icon */ + + /* mouse state */ + khm_int32 mouse_state; /* state of the mouse can be combo of CW_MOUSE_* values */ + khm_int32 mouse_row; /* row that the mouse state applies to */ + khm_int32 mouse_col; /* col that the mouse state applies to */ + + khui_bitmap kbm_logo_shade; + + /* the credentials set */ + khm_handle credset; + + khui_credwnd_ident * idents; + khm_size n_idents; + khm_size nc_idents; + + khm_int32 view_all_idents; + +} khui_credwnd_tbl; + +#define KHUI_MAXCB_HEADING 256 + +/* table flags */ +#define KHUI_CW_TBL_INITIALIZED 0x00000001 +#define KHUI_CW_TBL_COL_DIRTY 0x00000002 +#define KHUI_CW_TBL_ROW_DIRTY 0x00000004 +#define KHUI_CW_TBL_ACTIVE 0x00000100 +#define KHUI_CW_TBL_CUSTVIEW 0x00000200 +#define KHUI_CW_TBL_COLSKIP 0x00000400 +#define KHUI_CW_TBL_EXPIDENT 0x00000800 +#define KHUI_CW_TBL_NOHEADER 0x00001000 + +/* mouse_state constants */ +#define CW_MOUSE_NONE 0x00000000 /* nothing interesting */ +#define CW_MOUSE_WIDGET 0x00000001 /* mouse is highlighting a + widget */ +#define CW_MOUSE_LDOWN 0x00000002 /* left button is down */ +#define CW_MOUSE_ROW 0x00000004 /* mouse is acive over a valid + row */ +#define CW_MOUSE_WOUTLINE 0x00000008 /* mouse is highlighting an + outline widget */ +#define CW_MOUSE_WSTICKY 0x00000010 /* mouse is highlighting a + sticky widget */ +#define CW_MOUSE_WICON 0x00000020 /* an icon widget. represents + the icon next to identities + and next to credentials. */ + +#define CW_MOUSE_WMASK 0x00000039 /* all widget bits */ + +void khm_unregister_credwnd_class(void); + +void khm_register_credwnd_class(void); + +HWND khm_create_credwnd(HWND parent); + +LRESULT CALLBACK khm_credwnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ); + +void cw_load_view(khui_credwnd_tbl * tbl, wchar_t * viewname, HWND hwnd); + +void cw_update_creds(khui_credwnd_tbl * tbl); + +void cw_unload_view(khui_credwnd_tbl * tbl); + +void cw_hditem_from_tbl_col(khui_credwnd_col * col, HDITEM *phi); + +int cw_update_extents(khui_credwnd_tbl * tbl, khm_boolean update_scroll); + +void cw_insert_header_cols(khui_credwnd_tbl * tbl); + +void khm_get_cw_element_font(HDC hdc, wchar_t * name, BOOL use_default, + LOGFONT * pfont); + +void khm_set_cw_element_font(wchar_t * name, LOGFONT * pfont); + +void khm_draw_identity_menu_item(HWND hwnd, LPDRAWITEMSTRUCT lpd, khui_action * act); + +void khm_measure_identity_menu_item(HWND hwnd, LPMEASUREITEMSTRUCT lpm, khui_action * act); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/debugfuncs.c b/krb5-1-6/src/windows/identity/ui/debugfuncs.c new file mode 100644 index 000000000..384f40ea6 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/debugfuncs.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<tchar.h> + +#include<shlwapi.h> +#include<khmapp.h> + +#include<stdio.h> + +#if DEBUG +#include<assert.h> +#endif + +#define LOGFILENAME "nidmdbg.log" + +CRITICAL_SECTION cs_log; +FILE * logfile = NULL; +BOOL log_started = FALSE; + +wchar_t * +severity_string(kherr_severity severity) { + switch(severity) { + case KHERR_FATAL: + return L"FATAL"; + + case KHERR_ERROR: + return L"ERROR"; + + case KHERR_WARNING: + return L"Warning"; + + case KHERR_INFO: + return L"Info"; + + case KHERR_DEBUG_3: + return L"Debug(3)"; + + case KHERR_DEBUG_2: + return L"Debug(2)"; + + case KHERR_DEBUG_1: + return L"Debug(1)"; + + case KHERR_NONE: + return L"(None)"; + + default: + return L"(Unknown severity)"; + } +} + +void +fprint_systime(FILE * f, SYSTEMTIME *psystime) { + fprintf(logfile, + "%d-%d-%d %02d:%02d:%02d.%03d", + + (int) psystime->wYear, + (int) psystime->wMonth, + (int) psystime->wDay, + + (int) psystime->wHour, + (int) psystime->wMinute, + (int) psystime->wSecond, + (int) psystime->wMilliseconds); +} + +void KHMAPI +debug_event_handler(enum kherr_ctx_event e, + kherr_context * c) { + kherr_event * evt; + + EnterCriticalSection(&cs_log); + + if (!logfile) + goto _done; + + if (e == KHERR_CTX_BEGIN) { + SYSTEMTIME systime; + + GetSystemTime(&systime); + fprintf(logfile, + "%d\t", + c->serial); + + fprint_systime(logfile, &systime); + + fprintf(logfile, + "\t<< Context begin --\n"); + + } else if (e == KHERR_CTX_DESCRIBE) { + evt = kherr_get_desc_event(c); + if (evt) { + kherr_evaluate_event(evt); + fprintf(logfile, + "%d\t Description: %S\n", + c->serial, + (evt->long_desc)? evt->long_desc: evt->short_desc); + } + } else if (e == KHERR_CTX_END) { + SYSTEMTIME systime; + + fprintf(logfile, + "%d\t", + c->serial); + + GetSystemTime(&systime); + fprint_systime(logfile, &systime); + + fprintf(logfile, + "\t>> Context end --\n"); + + } else if (e == KHERR_CTX_EVTCOMMIT) { + evt = kherr_get_last_event(c); + if (evt && (evt->short_desc || evt->long_desc)) { + SYSTEMTIME systime; + + kherr_evaluate_event(evt); + FileTimeToSystemTime(&evt->time_ft, &systime); + + fprintf(logfile, + "%d[%d](%S)\t", + c->serial, + evt->thread_id, + (evt->facility ? evt->facility: L"")); + + fprint_systime(logfile, &systime); + + fprintf(logfile, + "\t%S: %S %S%S%S %S%S%S\n", + + severity_string(evt->severity), + + (evt->short_desc ? evt->short_desc: L""), + + (evt->short_desc ? L"(":L""), + (evt->long_desc ? evt->long_desc: L""), + (evt->short_desc ? L")":L""), + + (evt->suggestion ? L"[":L""), + (evt->suggestion ? evt->suggestion: L""), + (evt->suggestion ? L"]":L"") + ); + } + } + + _done: + + LeaveCriticalSection(&cs_log); +} + +void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf) { +#ifdef DEBUG + assert(cb_buf > sizeof(wchar_t)); +#endif + *buf = L'\0'; + + GetTempPath((DWORD) cb_buf / sizeof(wchar_t), buf); + + StringCbCat(buf, cb_buf, _T(LOGFILENAME)); +} + +void khm_start_file_log(void) { + wchar_t temppath[MAX_PATH]; + khm_handle cs_cw = NULL; + khm_int32 t = 0; + + EnterCriticalSection(&cs_log); + + if (log_started) + goto _done; + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &cs_cw))) + goto _done; + + if (KHM_FAILED(khc_read_int32(cs_cw, L"LogToFile", &t)) || + !t) + goto _done; + + khm_get_file_log_path(sizeof(temppath), temppath); + + logfile = NULL; +#if _MSC_VER >= 1400 && __STDC_WANT_SECURE_LIB__ + _wfopen_s(&logfile, temppath, L"w"); +#else + logfile = _wfopen(temppath, L"w"); +#endif + kherr_add_ctx_handler(debug_event_handler, + KHERR_CTX_BEGIN | + KHERR_CTX_END | + KHERR_CTX_DESCRIBE | + KHERR_CTX_EVTCOMMIT, + 0); + + log_started = TRUE; + + _done: + if (cs_cw) + khc_close_space(cs_cw); + + LeaveCriticalSection(&cs_log); +} + +void khm_stop_file_log(void) { + + EnterCriticalSection(&cs_log); + + if (!log_started) + goto _done; + + kherr_remove_ctx_handler(debug_event_handler, 0); + + if (logfile) + fclose (logfile); + logfile = NULL; + + log_started = FALSE; + + _done: + LeaveCriticalSection(&cs_log); +} + +void khm_init_debug(void) { + InitializeCriticalSection(&cs_log); + + khm_start_file_log(); +} + +void khm_exit_debug(void) { + khm_stop_file_log(); + + DeleteCriticalSection(&cs_log); +} diff --git a/krb5-1-6/src/windows/identity/ui/debugfuncs.h b/krb5-1-6/src/windows/identity/ui/debugfuncs.h new file mode 100644 index 000000000..6467185f3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/debugfuncs.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __NETIDMGR_DEBUGFUNCS_H +#define __NETIDMGR_DEBUGFUNCS_H + +void khm_init_debug(void); +void khm_exit_debug(void); + +void khm_start_file_log(void); +void khm_stop_file_log(void); +void khm_get_file_log_path(khm_size cb_buf, wchar_t * buf); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/htwnd.c b/krb5-1-6/src/windows/identity/ui/htwnd.c new file mode 100644 index 000000000..7586b3e87 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/htwnd.c @@ -0,0 +1,1311 @@ +/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies +* of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +/* $Id$ */ + +#include<khmapp.h> +#include<crtdbg.h> + +ATOM khui_htwnd_cls; + +#define HTW_STYLE_NORMAL 0 + +/* There are currently 4 style "bits" and 3 sizes, which means + there can be 2^4*3=48 possible styles max. If someone is + feeling adventurous you can slightly improve performance of + the parser using this little fact. For now, I don't care. + (hint: combine size and style bits to form a single number + and use it as an index into the styles array) +*/ +#define HTW_STYLE_MAX 48 + +#define HTW_FORMAT_MAX 128 + +#define HTW_TAB_MAX 8 + +#define HTW_DEFAULT (-1) + +#define HTW_NORMAL_SIZE 8 +#define HTW_LARGE_SIZE 12 +#define HTW_HUGE_SIZE 20 + +/* font variant */ +#define FV_ABSOLUTE 0x10000000 + +#define FV_ITALIC 0x00000002 +#define FV_UNDERLINE 0x00000004 +#define FV_STRIKEOUT 0x00000008 +#define FV_BOLD 0x00000010 + +#define FV_NOITALIC 0x00020000 +#define FV_NOUNDERLINE 0x00040000 +#define FV_NOSTRIKEOUT 0x00080000 +#define FV_NOBOLD 0x00100000 + +#define FV_NONE 0x00000000 +#define FV_MASK 0x0000001f + +#define HTW_LINK_ALLOC 8 + +#define ALIGN_LEFT 0 +#define ALIGN_CENTER 1 +#define ALIGN_RIGHT 2 + +struct tx_tbl_t { + wchar_t * string; + LONG value; +} + +htw_color_table[] = { + {L"black", RGB(0,0,0)}, + {L"white", RGB(255,255,255)}, + {L"red", RGB(255,0,0)}, + {L"green", RGB(0,255,0)}, + {L"blue", RGB(0,0,255)}, + {L"grey", RGB(128,128,128)} +}, + +htw_size_table[] = { + {L"normal", HTW_NORMAL_SIZE}, + {L"large", HTW_LARGE_SIZE}, + {L"huge", HTW_HUGE_SIZE} +}, + +htw_align_table[] = { + {L"left", ALIGN_LEFT}, + {L"center", ALIGN_CENTER}, + {L"right", ALIGN_RIGHT} +}; + +typedef struct khui_htwnd_style_t { + LONG height; + LONG variation; /* combination of FV_* */ + + HFONT font; +} khui_htwnd_style; + +typedef struct khui_format_t { + int style_idx; + COLORREF color; +} khui_format; + +typedef struct format_stack_t { + khui_format stack[HTW_FORMAT_MAX]; + int stack_top; +} format_stack; + +typedef struct khui_htwnd_data_t { + int id; /* control ID */ + int flags; + wchar_t * text; + int scroll_left; + int scroll_top; + int ext_width; + int ext_height; + COLORREF bk_color; + HCURSOR hc_hand; + int l_pixel_y; + + khui_htwnd_style styles[HTW_STYLE_MAX]; + int n_styles; + + khui_htwnd_link ** links; + int n_links; + int max_links; + int active_link; + int md_link; + + int tabs[HTW_TAB_MAX]; + int n_tabs; +} khui_htwnd_data; + +static LONG table_lookup(struct tx_tbl_t * tbl, int n, wchar_t * v, int len) +{ + int i; + + for(i=0; i<n; i++) { + if(!_wcsnicmp(tbl[i].string, v, len)) + return tbl[i].value; + } + + return -1; +} + +static void clear_styles(khui_htwnd_data * d) +{ + int i; + + for(i=0; i<d->n_styles; i++) { + if(d->styles[i].font != NULL) { + DeleteObject(d->styles[i].font); + d->styles[i].font = NULL; + } + } + + d->n_styles = 0; +} + +static void format_init(format_stack * s) +{ + s->stack_top = -1; + ZeroMemory(s->stack, sizeof(s->stack)); +} + +static khui_format * format_current(format_stack * s) +{ + if(s->stack_top >= 0) + return &(s->stack[s->stack_top]); + else + return NULL; +} + +static int format_style(format_stack * s) +{ + if(s->stack_top >= 0) + return s->stack[s->stack_top].style_idx; + else + return 0; +} + +static COLORREF format_color(format_stack * s) +{ + if(s->stack_top >= 0) + return s->stack[s->stack_top].color; + else + return 0; +} + +static int format_level(format_stack * s) +{ + return s->stack_top; +} + +static void format_unwind(format_stack * s, int level) +{ + s->stack_top = level; +} + +static void format_push(format_stack * s, khui_htwnd_data * d, LONG height, LONG variation, COLORREF color) +{ + int i; + khui_format * top; + khui_htwnd_style * style; + + _ASSERT(s->stack_top < (HTW_FORMAT_MAX-1)); + + /* formatting is additive unless FV_NORMAL is set in variation */ + top = format_current(s); + if(top) { + style = &(d->styles[top->style_idx]); + if(height == HTW_DEFAULT) + height = style->height; + + if(variation == HTW_DEFAULT) + variation = style->variation; + else if(!(variation & FV_ABSOLUTE)) + variation |= style->variation; + + if(color == HTW_DEFAULT) + color = top->color; + } + + variation &= ~FV_ABSOLUTE; + variation ^= variation & (variation>>16); + variation &= FV_MASK; + + /* now look for an existing style that matches the requested one */ + for(i=0; i<d->n_styles; i++) { + style = &(d->styles[i]); + + if(style->height == height && + style->variation == variation) + break; + } + + s->stack_top++; + + if(i<d->n_styles) { + s->stack[s->stack_top].style_idx = i; + } else { + if(d->n_styles == HTW_STYLE_MAX) { + s->stack[s->stack_top].style_idx = 0; + } else { + s->stack[s->stack_top].style_idx = d->n_styles; + d->styles[d->n_styles].font = NULL; + d->styles[d->n_styles].height = height; + d->styles[d->n_styles].variation = variation; + d->n_styles++; + } + } + s->stack[s->stack_top].color = color; +} + +static void format_pop(format_stack * s) { + if(s->stack_top >= 0) + s->stack_top--; +} + +static wchar_t * token_end(wchar_t * s) { + while(iswalnum(*s) || *s == L'/') + s++; + return s; +} + +static wchar_t * skip_ws(wchar_t * s) { + while(iswspace(*s)) + s++; + return s; +} + +/* s points to something like " = \"value\"" + start and len will point to the start and + length of value. return value will point to the + character following the last double quote. */ +static wchar_t * read_attr(wchar_t * s, wchar_t ** start, int * len) +{ + wchar_t *e; + + *start = NULL; + *len = 0; + + do { + s = skip_ws(s); + if(*s != L'=') + break; + s = skip_ws(++s); + if(*s != L'"') + break; + e = wcschr(++s, L'"'); + if(!e) + break; + + *start = s; + *len = (int) (e - s); + + s = e + 1; + } while(FALSE); + + return s; +} + +/* +We currently support the following tags: + +<a [id="string"] [param="paramstring"]>link text</a> +<b>foo</b> +<u>foo</u> +<i>foo</i> + +<font [color="(color)"] [size="normal|large|huge|(point size)"]>foo</font> + (color)=black|white|red|green|blue|grey +<large>foo</large> +<huge>foo</huge> + +<center>foo</center> +<left>foo</left> +<right>foo</right> + +<p [align="left|center|right"]>foo</p> +<settab pos="(pos)"> +<tab> +*/ + +static int htw_parse_tag( + wchar_t * start, + wchar_t ** end, + int * align, + khui_htwnd_data * d, + format_stack * s, + PPOINT p_abs, + PPOINT p_rel, + int lh, + BOOL dry_run) +{ + wchar_t * c; + int n = 0; + + /* start initially points to the starting '<' */ + c = token_end(++start); + + if(!_wcsnicmp(start,L"a",c-start)) { + /* start of an 'a' tag */ + wchar_t * id_start = NULL; + int id_len = 0; + wchar_t * param_start = NULL; + int param_len = 0; + + /* We don't need to parse the link + if it is just a dry run */ + if(dry_run) { + format_push(s, d, HTW_DEFAULT, HTW_DEFAULT, RGB(0,0,255)); + *end = wcschr(start, L'>'); + return FALSE; + } + + while(c && *c && *c != L'>') { + wchar_t * e; + + c = skip_ws(c); + e = token_end(c); + + if(c==e) + break; + + if(!_wcsnicmp(c,L"id",e-c)) { + c = read_attr(e, &id_start, &id_len); + } else if(!_wcsnicmp(c,L"param",e-c)) { + c = read_attr(e, &param_start, &param_len); + } + } + + if(d->active_link == d->n_links) + format_push(s,d, HTW_DEFAULT, FV_UNDERLINE, RGB(0,0,255)); + else + format_push(s,d, HTW_DEFAULT, FV_NONE, RGB(0,0,255)); + + { + khui_htwnd_link * l; + + if(!d->links) { + d->links = PMALLOC(sizeof(khui_htwnd_link *) * HTW_LINK_ALLOC); + ZeroMemory(d->links, sizeof(khui_htwnd_link *) * HTW_LINK_ALLOC); + d->max_links = HTW_LINK_ALLOC; + d->n_links = 0; + } + + if(d->n_links >= d->max_links) { + khui_htwnd_link ** ll; + int n_new; + + n_new = UBOUNDSS(d->n_links + 1, HTW_LINK_ALLOC, HTW_LINK_ALLOC); + + ll = PMALLOC(sizeof(khui_htwnd_link *) * n_new); + ZeroMemory(ll, sizeof(khui_htwnd_link *) * n_new); + memcpy(ll, d->links, sizeof(khui_htwnd_link *) * d->max_links); + PFREE(d->links); + d->links = ll; + d->max_links = n_new; + } + + l = d->links[d->n_links]; + if(!l) { + l = PMALLOC(sizeof(khui_htwnd_link)); + d->links[d->n_links] = l; + } + + l->id = id_start; + l->id_len = id_len; + l->param = param_start; + l->param_len = param_len; + + l->r.left = p_abs->x; + l->r.top = p_abs->y; + + d->n_links++; + } + + } else if(!_wcsnicmp(start, L"/a", c - start)) { + khui_htwnd_link * l; + + c = wcschr(c,L'>'); + if(!c) + c = c + wcslen(c); + + format_pop(s); + + if(!dry_run) { + l = d->links[d->n_links - 1]; /* last link */ + l->r.right = p_abs->x; + l->r.bottom = p_abs->y + lh; + } + } else if(!_wcsnicmp(start, L"p", c - start)) { + wchar_t * e; + wchar_t * align_s = NULL; + int align_len = 0; + + c = skip_ws(c); + e = token_end(c); + + if(c != e && !_wcsnicmp(c,L"align",e-c)) { + c = read_attr(e, &align_s, &align_len); + } + + c = wcschr(c, L'>'); + if(!c) + c = c + wcslen(c); + + + if(align_s) + *align = table_lookup(htw_align_table, ARRAYLENGTH(htw_align_table), align_s, align_len); + else + *align = ALIGN_LEFT; + + n = 1; + } else if(!_wcsnicmp(start, L"b", c - start)) { + format_push(s,d, HTW_DEFAULT, FV_BOLD, (COLORREF) HTW_DEFAULT); + } else if(!_wcsnicmp(start, L"/b", c - start)) { + format_pop(s); + } else if(!_wcsnicmp(start, L"u", c - start)) { + format_push(s,d, HTW_DEFAULT, FV_UNDERLINE, (COLORREF) HTW_DEFAULT); + } else if(!_wcsnicmp(start, L"/u", c - start)) { + format_pop(s); + } else if(!_wcsnicmp(start, L"i", c - start)) { + format_push(s,d, HTW_DEFAULT, FV_ITALIC, (COLORREF) HTW_DEFAULT); + } else if(!_wcsnicmp(start, L"/i", c - start)) { + format_pop(s); + } else if(!_wcsnicmp(start, L"large", c - start)) { + format_push(s,d,-MulDiv(HTW_LARGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, (COLORREF) HTW_DEFAULT); + } else if(!_wcsnicmp(start, L"/large", c - start)) { + format_pop(s); + } else if(!_wcsnicmp(start, L"huge", c - start)) { + format_push(s,d,-MulDiv(HTW_HUGE_SIZE, d->l_pixel_y, 72), HTW_DEFAULT, (COLORREF) HTW_DEFAULT); + } else if(!_wcsnicmp(start, L"/huge", c - start)) { + format_pop(s); + } else if(!_wcsnicmp(start, L"center", c - start)) { + c = wcschr(c, L'>'); + if(!c) + c = c + wcslen(c); + *align = ALIGN_CENTER; + n = 1; + } else if(!_wcsnicmp(start, L"left", c - start) || + !_wcsnicmp(start, L"p", c - start)) + { + c = wcschr(c, L'>'); + if(!c) + c = c + wcslen(c); + *align = ALIGN_LEFT; + n = 1; + } else if(!_wcsnicmp(start, L"right", c - start)) { + c = wcschr(c, L'>'); + if(!c) + c = c + wcslen(c); + *align = ALIGN_RIGHT; + n = 1; + } else if(!_wcsnicmp(start, L"/center", c - start) || + !_wcsnicmp(start, L"/left", c - start) || + !_wcsnicmp(start, L"/right", c - start) || + !_wcsnicmp(start, L"/p", c - start)) { + c = wcschr(c, L'>'); + if(!c) + c = c + wcslen(c); + *align = ALIGN_LEFT; + n = 1; + } else if(!_wcsnicmp(start, L"font", c - start)) { + wchar_t * color_s = NULL; + int color_len = 0; + wchar_t * size_s = NULL; + int size_len = 0; + LONG color = HTW_DEFAULT; + LONG h = HTW_DEFAULT; + + while(c && *c && *c != L'>') { + wchar_t * e; + + c = skip_ws(c); + e = token_end(c); + + if(c==e) + break; + + if(!_wcsnicmp(c,L"color",e-c)) { + c = read_attr(e, &color_s, &color_len); + } else if(!_wcsnicmp(c,L"size",e-c)) { + c = read_attr(e, &size_s, &size_len); + } + } + + if(color_s) + color = table_lookup(htw_color_table, ARRAYLENGTH(htw_color_table), color_s, color_len); + if(size_s) { + h = table_lookup(htw_size_table, ARRAYLENGTH(htw_size_table), size_s, size_len); + if(h) + h = -MulDiv(h, d->l_pixel_y, 72); + else + h = -MulDiv(HTW_NORMAL_SIZE, d->l_pixel_y, 72); + } + + format_push(s,d,h,HTW_DEFAULT,color); + } else if(!_wcsnicmp(start, L"/font", c - start)) { + format_pop(s); + } else if(!_wcsnicmp(start, L"settab", c - start)) { + wchar_t * e; + wchar_t * pos_s = NULL; + int pos_len; + + c = skip_ws(c); + e = token_end(c); + + if(c != e && !_wcsnicmp(c,L"pos",e-c)) { + c = read_attr(e, &pos_s, &pos_len); + } + + c = wcschr(c, L'>'); + if(!c) + c = c + wcslen(c); + + if(pos_s && d->n_tabs < HTW_TAB_MAX && !dry_run) { + wchar_t * dummy; + LONG bu; + int bx; + int dx; + + bu = GetDialogBaseUnits(); + bx = LOWORD(bu); + + dx = wcstol(pos_s, &dummy, 10); + + d->tabs[d->n_tabs++] = MulDiv(dx, bx, 4); + } + } else if(!_wcsnicmp(start, L"tab", c - start)) { + int i; + + if(!dry_run) { + for(i=0; i < d->n_tabs; i++) { + if(d->tabs[i] > p_rel->x) { + p_rel->x = d->tabs[i]; + break; + } + } + } + } + + if(*c) + c++; + *end = c; + + return n; +} + +static void htw_assert_style(HDC hdc, khui_htwnd_data * d, int style) +{ + LOGFONT lf; + + if(d->styles[style].font) + return; + + /*TODO: we need select different fonts depending on system locale */ + lf.lfHeight = d->styles[style].height; //-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + lf.lfWidth = 0; + lf.lfEscapement = 0; + lf.lfOrientation = 0; + lf.lfWeight = (d->styles[style].variation & FV_BOLD)? FW_BOLD: FW_NORMAL; + lf.lfItalic = (BYTE) !!(d->styles[style].variation & FV_ITALIC); + lf.lfUnderline = (BYTE) !!(d->styles[style].variation & FV_UNDERLINE); + lf.lfStrikeOut = (BYTE) !!(d->styles[style].variation & FV_STRIKEOUT); + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfPitchAndFamily = DEFAULT_PITCH; + + LoadString(khm_hInstance, IDS_DEFAULT_FONT, lf.lfFaceName, ARRAYLENGTH(lf.lfFaceName)); + + d->styles[style].font = CreateFontIndirect(&lf); +} + +static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + HBRUSH hbk; + khui_htwnd_data * d; + RECT r; + SIZE s; + HDC hdc; + wchar_t * text; + format_stack s_stack; + + int align; + int y; + wchar_t * par_start; + int ext_width = 0; + int ext_height = 0; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + return 0; + + if(!GetUpdateRect(hwnd, &r, !(d->flags & KHUI_HTWND_TRANSPARENT))) + return 0; + + if(d->text == NULL) + return 0; + + text = d->text; + + hdc = BeginPaint(hwnd, &ps); + + GetClientRect(hwnd, &r); + +#ifdef DRAW_HTWND_CLIENT_EDGE + /* for the moment, we are skipping on the client edge. */ + if(d->flags & KHUI_HTWND_CLIENTEDGE) + DrawEdge(hdc, &r, EDGE_SUNKEN, BF_ADJUST | BF_RECT | BF_FLAT); +#endif + + hbk = GetSysColorBrush(COLOR_WINDOW); + FillRect(hdc, &r, hbk); + hbk = NULL; /* We don't need to destroy system + brushes */ + + /* push the default format */ + format_init(&s_stack); + + d->l_pixel_y = GetDeviceCaps(hdc, LOGPIXELSY); + format_push(&s_stack,d, -MulDiv(HTW_NORMAL_SIZE, d->l_pixel_y, 72), FV_NONE, RGB(0,0,0)); + + y = r.top - d->scroll_top; + + par_start = text; + + align = ALIGN_LEFT; + + SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP); + if(d->flags & KHUI_HTWND_TRANSPARENT) + SetBkMode(hdc, TRANSPARENT); + + d->n_links = 0; + d->n_tabs = 0; + + while(*par_start) { + wchar_t * p = par_start; + wchar_t * c = NULL; + int p_width = 0; + int s_start; + int l_height = 0; + int x = 0; + POINT pt; + POINT pt_rel; + + s_start = format_level(&s_stack); + + /* begin dry run */ + while(*p) { + if(*p == L'<') { + int talign = -1; + int n = htw_parse_tag(p,&c,&talign,d,&s_stack,NULL,NULL,0,TRUE); + + if(n && p_width) + break; + + p = c; + + if(n && talign >= 0) + align = talign; + } else { + HFONT hfold; + c = wcschr(p, L'<'); + if(!c) + c = p + wcslen(p); + + htw_assert_style(hdc, d, format_style(&s_stack)); + hfold = SelectFont(hdc, d->styles[format_style(&s_stack)].font); + GetTextExtentPoint32(hdc, p, (int)(c - p), &s); + SelectFont(hdc, hfold); + + p_width += s.cx; + if(s.cy > l_height) + l_height = s.cy; + + p = c; + } + } + + /* dry run ends */ + + x = r.left - d->scroll_left; + + if(align == ALIGN_CENTER) { + if (r.right - r.left > p_width) + x += (r.right - r.left)/2 - p_width / 2; + } + + else if(align == ALIGN_RIGHT) { + if (r.right - r.left > p_width) + x += (r.right - r.left) - p_width; + } + + /* begin wet run */ + p = par_start; + format_unwind(&s_stack, s_start); /* unwind format stack */ + + p_width = 0; + + while(p && *p) { + if(*p == L'<') { + int talign = -1; + int n; + + pt.x = x + p_width; + pt.y = y; + pt_rel.x = p_width; + pt_rel.y = 0; + + n = htw_parse_tag(p, &c, &talign, d, &s_stack, &pt, &pt_rel, l_height, FALSE); + + if(n && p_width) { + break; + } + + p_width = pt_rel.x; + + p = c; + if(n && talign >= 0) + align = talign; + } else { + HFONT hfold; + RECT rd; + + c = wcschr(p, L'<'); + if(!c) + c = p + wcslen(p); + + htw_assert_style(hdc, d, format_style(&s_stack)); + hfold = SelectFont(hdc, d->styles[format_style(&s_stack)].font); + SetTextColor(hdc, format_color(&s_stack)); + + GetTextExtentPoint32(hdc, p, (int)(c - p), &s); + rd.left = x + p_width; + rd.top = y; + rd.right = rd.left + s.cx; + rd.bottom = rd.top + l_height; + + DrawText(hdc, p, (int)(c - p), &rd, + DT_BOTTOM | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX); + + p_width += s.cx; + + SelectFont(hdc, hfold); + p = c; + } + } + + if (p_width > ext_width) + ext_width = p_width; + + y += l_height; + par_start = p; + } + + if (y > ext_height) + ext_height = y; + + EndPaint(hwnd, &ps); + + if (d->ext_width < ext_width || + d->ext_height < ext_height) { + SCROLLINFO si; + LONG l; + + /* the extents need to be adjusted. But first check if we + have exactly the right scroll bars we need. */ + if ((ext_width > (r.right - r.left) && + !(d->flags & KHUI_HTWND_HSCROLL)) || + (ext_height > (r.bottom - r.top) && + !(d->flags & KHUI_HTWND_VSCROLL)) || + + (ext_width <= (r.right - r.left) && + (d->flags & KHUI_HTWND_HSCROLL)) || + (ext_height <= (r.bottom - r.top) && + (d->flags & KHUI_HTWND_VSCROLL))) { + + /* need to add scroll bars */ + if (ext_width > (r.right - r.left)) + d->flags |= KHUI_HTWND_HSCROLL; + else + d->flags &= ~KHUI_HTWND_HSCROLL; + + if (ext_height > (r.bottom - r.top)) + d->flags |= KHUI_HTWND_VSCROLL; + else + d->flags &= ~KHUI_HTWND_VSCROLL; + + l = (LONG) GetWindowLongPtr(hwnd, GWL_STYLE); + l &= ~(WS_HSCROLL | WS_VSCROLL); + + l |= ((d->flags & KHUI_HTWND_HSCROLL) ? WS_HSCROLL : 0) | + ((d->flags & KHUI_HTWND_VSCROLL) ? WS_VSCROLL : 0); + + SetWindowLongPtr(hwnd, GWL_STYLE, l); + + InvalidateRect(hwnd, NULL, FALSE); + /* since the client area changed, we do another redraw + before updating the scroll bar positions. */ + } else { + d->ext_width = ext_width; + d->ext_height = ext_height; + + if (d->flags & KHUI_HTWND_HSCROLL) { + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_ALL | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = ext_width; + si.nPage = r.right - r.left; + si.nPos = d->scroll_left; + + SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); + } + + if (d->flags & KHUI_HTWND_VSCROLL) { + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_ALL | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = ext_height; + si.nPage = r.bottom - r.top; + si.nPos = d->scroll_top; + + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + } + } + } + + return 0; +} + +LRESULT CALLBACK khui_htwnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + switch(uMsg) { + case WM_CREATE: + { + CREATESTRUCT * cs; + khui_htwnd_data * d; + size_t cbsize; + + cs = (CREATESTRUCT *) lParam; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + if(cs->dwExStyle & WS_EX_TRANSPARENT) { + d->flags |= KHUI_HTWND_TRANSPARENT; + } + if(cs->dwExStyle & WS_EX_CLIENTEDGE) { + d->flags |= KHUI_HTWND_CLIENTEDGE; + } + if(cs->style & WS_HSCROLL) { + d->flags |= KHUI_HTWND_HSCROLL; + } + if(cs->style & WS_VSCROLL) { + d->flags |= KHUI_HTWND_VSCROLL; + } + d->id = (int)(INT_PTR) cs->hMenu; + + d->active_link = -1; + d->bk_color = RGB(255,255,255); + d->hc_hand = LoadCursor(NULL, IDC_HAND); + + if(SUCCEEDED(StringCbLength(cs->lpszName, KHUI_HTWND_MAXCB_TEXT, &cbsize))) { + cbsize += sizeof(wchar_t); + d->text = PMALLOC(cbsize); + StringCbCopy(d->text, cbsize, cs->lpszName); + } + + /* this is just a flag to the WM_PAINT handler that the + extents haven't been set yet. */ + d->ext_width = -1; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, 0, (LONG_PTR) d); +#pragma warning(pop) + + return 0; + } + break; + + case WM_SETTEXT: + { + wchar_t * newtext; + size_t cbsize; + khui_htwnd_data * d; + BOOL rv; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + return 0; + + newtext = (wchar_t *) lParam; + + if(d->text) { + PFREE(d->text); + d->text = NULL; + } + + if(SUCCEEDED(StringCbLength(newtext, KHUI_HTWND_MAXCB_TEXT, &cbsize))) { + cbsize += sizeof(wchar_t); + d->text = PMALLOC(cbsize); + StringCbCopy(d->text, cbsize, newtext); + rv = TRUE; + } else + rv = FALSE; + + clear_styles(d); + + d->ext_width = -1; + d->scroll_left = 0; + d->scroll_top = 0; + + InvalidateRect(hwnd, NULL, TRUE); + + return rv; + } + break; + + case WM_DESTROY: + { + khui_htwnd_data * d; + int i; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d) { + if(d->text) + PFREE(d->text); + d->text = 0; + + if(d->links) { + for(i=0;i<d->max_links;i++) { + if(d->links[i]) + PFREE(d->links[i]); + } + PFREE(d->links); + } + + clear_styles(d); + + PFREE(d); + SetWindowLongPtr(hwnd, 0, 0); + } + } + break; + + case WM_ERASEBKGND: + { + HDC hdc = (HDC) wParam; + khui_htwnd_data * d; + HBRUSH hbr; + RECT r; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + return FALSE; + + GetClientRect(hwnd, &r); + hbr = GetSysColorBrush(COLOR_WINDOW); + FillRect(hdc, &r, hbr); + + /* no need to destroy the brush since it's a system + brush. */ + + return TRUE; + } + + case WM_SIZE: + { + khui_htwnd_data * d; + + d = (khui_htwnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, 0); + + if (d) { + d->ext_width = 0; + d->ext_height = 0; + } + } + return 0; + + case WM_PAINT: + htw_paint(hwnd, uMsg, wParam, lParam); + return 0; + + case WM_SETCURSOR: + { + khui_htwnd_data * d; + + if(hwnd != (HWND)wParam) + break; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + break; + + if(d->active_link >= 0) { + SetCursor(d->hc_hand); + return TRUE; + } + } + break; + + case WM_SETFOCUS: + { + khui_htwnd_data * d; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + break; + + d->flags |= KHUI_HTWND_FOCUS; + + InvalidateRect(hwnd, NULL, TRUE); + } + break; + + case WM_KILLFOCUS: + { + khui_htwnd_data * d; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + break; + + d->flags &= ~KHUI_HTWND_FOCUS; + + InvalidateRect(hwnd, NULL, TRUE); + } + break; + + case WM_LBUTTONDOWN: + { + khui_htwnd_data * d; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + break; + + d->md_link = d->active_link; + + SetCapture(hwnd); + } + break; + + case WM_LBUTTONUP: + { + khui_htwnd_data * d; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + break; + + if(d->md_link == d->active_link && d->md_link >= 0) { + /* clicked */ + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(d->id, BN_CLICKED), (LPARAM) d->links[d->md_link]); + } + + ReleaseCapture(); + } + break; + + case WM_HSCROLL: + { + khui_htwnd_data * d; + int old_pos; + int new_pos; + int ext; + SCROLLINFO si; + RECT r; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + break; + + old_pos = new_pos = d->scroll_left; + ext = d->ext_width; + + switch(LOWORD(wParam)) { + case SB_THUMBPOSITION: + case SB_ENDSCROLL: + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + GetScrollInfo(hwnd, SB_HORZ, &si); + new_pos = si.nPos; + break; + + case SB_THUMBTRACK: + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_TRACKPOS; + GetScrollInfo(hwnd, SB_HORZ, &si); + new_pos = si.nTrackPos; + break; + + case SB_LINELEFT: + new_pos -= ext / 12; /* arbitrary unit */ + break; + + case SB_LINERIGHT: + new_pos += ext / 12; /* arbitrary unit */ + break; + + case SB_PAGELEFT: + GetClientRect(hwnd, &r); + new_pos -= r.right - r.left; + break; + + case SB_PAGERIGHT: + GetClientRect(hwnd, &r); + new_pos += r.right - r.left; + break; + } + + if (new_pos == old_pos) + break; + + GetClientRect(hwnd, &r); + + if (new_pos > ext - (r.right - r.left)) + new_pos = ext - (r.right - r.left); + + if (new_pos < 0) + new_pos = 0; + + if (new_pos == old_pos) + break; + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = new_pos; + SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); + /* note that Windows sometimes adjusts the position after + setting it with SetScrollInfo. We have to look it up + again to see what value it ended up at. */ + GetScrollInfo(hwnd, SB_HORZ, &si); + new_pos = si.nPos; + + if (new_pos == old_pos) + break; + + d->scroll_left = new_pos; + + ScrollWindow(hwnd, old_pos - new_pos, 0, NULL, NULL); + + return 0; + } + break; + + case WM_MOUSEMOVE: + { + khui_htwnd_data * d; + int i; + POINT p; + int nl; + + d = (khui_htwnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (d == NULL) + break; + + p.x = GET_X_LPARAM(lParam) + d->scroll_left; + p.y = GET_Y_LPARAM(lParam) + d->scroll_top; + + for(i=0; i<d->n_links; i++) { + if(d->links && d->links[i] && PtInRect(&(d->links[i]->r), p)) + break; + } + + if(i == d->n_links) + nl = -1; + else + nl = i; + + if(d->active_link != nl) { + if(d->active_link >= 0) { + if(d->flags & KHUI_HTWND_TRANSPARENT) { + HWND parent = GetParent(hwnd); + if(parent) { + RECT rdest = d->links[d->active_link]->r; + + MapWindowPoints(hwnd, parent, (LPPOINT) &rdest, 2); + InvalidateRect(parent, &rdest, TRUE); + } + } + /* although we are invalidating the rect before setting active_link, + WM_PAINT will not be issued until wndproc returns */ + InvalidateRect(hwnd, &(d->links[d->active_link]->r), TRUE); + } + d->active_link = nl; + if(d->active_link >= 0) { + /* although we are invalidating the rect before setting active_link, + WM_PAINT will not be issued until wndproc returns */ + if(d->flags & KHUI_HTWND_TRANSPARENT) { + HWND parent = GetParent(hwnd); + if(parent) { + RECT rdest = d->links[d->active_link]->r; + + MapWindowPoints(hwnd, parent, (LPPOINT) &rdest, 2); + InvalidateRect(parent, &rdest, TRUE); + } + } + InvalidateRect(hwnd, &(d->links[d->active_link]->r), TRUE); + } + } + } + break; + } + + return DefWindowProc(hwnd, uMsg,wParam,lParam); +} + +void khm_register_htwnd_class(void) +{ + WNDCLASSEX wcx; + + wcx.cbSize = sizeof(wcx); + wcx.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + wcx.lpfnWndProc = khui_htwnd_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = sizeof(LONG_PTR); + wcx.hInstance = khm_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wcx.hbrBackground = CreateSolidBrush(RGB(255,255,255)); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_HTWND_CLASS; + wcx.hIconSm = NULL; + + khui_htwnd_cls = RegisterClassEx(&wcx); +} + +void khm_unregister_htwnd_class(void) +{ + UnregisterClass(MAKEINTATOM(khui_htwnd_cls), khm_hInstance); +} + +HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int height, DWORD ex_style, DWORD style) +{ + + return CreateWindowEx( + ex_style, + MAKEINTATOM(khui_htwnd_cls), + text, + style | WS_CHILD, + x,y,width,height, + parent, + (HMENU) KHUI_HTWND_CTLID, + khm_hInstance, + NULL); +} diff --git a/krb5-1-6/src/windows/identity/ui/htwnd.h b/krb5-1-6/src/windows/identity/ui/htwnd.h new file mode 100644 index 000000000..f842d2d39 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/htwnd.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_HTWND_H +#define __KHIMAIRA_HTWND_H + +#include<khuidefs.h> + +/* +We currently support the following tags: + +<a [id="string"] [param="paramstring"]>link text</a> +<center>foo</center> +<left>foo</left> +<right>foo</right> +*/ + +#define KHUI_HTWND_TRANSPARENT 1 +#define KHUI_HTWND_CLIENTEDGE 2 +#define KHUI_HTWND_HSCROLL 4 +#define KHUI_HTWND_VSCROLL 8 +#define KHUI_HTWND_FOCUS 2048 + +#define KHUI_HTWND_CLASS L"KhmHtWnd" +#define KHUI_HTWND_CTLID 2040 + +#define KHUI_HTWND_MAXCCH_TEXT 2048 +#define KHUI_HTWND_MAXCB_TEXT (sizeof(wchar_t) * KHUI_HTWND_MAXCCH_TEXT) + +HWND khm_create_htwnd(HWND parent, LPWSTR text, int x, int y, int width, int height, DWORD ex_style, DWORD style); +void khm_unregister_htwnd_class(void); +void khm_register_htwnd_class(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/images/app_notify_error.ico b/krb5-1-6/src/windows/identity/ui/images/app_notify_error.ico new file mode 100644 index 0000000000000000000000000000000000000000..9fb30c53e792d60a03a03f64d3a94c33968e1bba GIT binary patch literal 2862 zcmeHJZBSHY6h8aGLI`&e<s(oQn3Zr1LR3s7gcYwwN`y(JC1ziGXR<#{P4t5un;i9r zG&Iq~OlCTxBQ`XWVNu#<MY$$F*2b9-*Bxk9-0ZqBwvo)-)AQb4K*?;H@ux5I-1DA~ z=bZDNcZPk53}m9Dq$Ef)<r|1fh@cbnINB6Lv>vvIo=uy~L_HRwd=Ud=1A;es3E$Xq zi48uk=*AUQTrjxZZerobhoc*gDjYEgFIJrD(xs{n2`Q<nZh#O5p$dbl1|WwZ)#m}B zS8Y+7qdE(@eOJU^74fUOln{q-BtrZKQNTh%XiW`+BQ~umWF4{jV?$QA$sg-7xlLqn z0h9iO#Y85Tl}vt{%R18Jx7|3WIFb0qh1rT_G#bg+dV-9eKHBQjC^?{!Wxt1{b{{!m zbNYfLb@@nY36N90M)6)BmG&U6O`}f4)}PfVw@V|3s*$u`qm2QT@}TF{tfy)Z;yN`- zJ)zMn>M)fAH8OVfk~0{l_?;Tbz3}hVsQ5V0xQkNZcZQM2t5G?)1K2ydH7WsLYJsi2 zo9cXFat>>hfm+Em+bFjKId}Ka-U0O8;UPy~fMoO+zgwej^rW0cedI3%M+vG_h~6aR z-YasTb{1+%ts2z~gekWjxoTP{tMeM>Qb)$N9y0d&XeZ{9EAqE{NX85#?*NsfMi;ma z<g3Ry8gV|$aW7Q|F{53miQL7FZIpqS)IOZcqfsENQK2{wxH9Tz;S8zha|`?#=&>BO zEx}>RK)z(XC-hO*LV2B9<g)I3?@Zt}Pe8fZx<BU;>vi@8n^T@ldwASX)=-p^pHnjy zv82ARXmftf?8IU{qEf0aT)Jo~^tBJdkmab{P#AxgWm!&Qp6zMqYbvuJFwUE|>bco@ zwj@QF<|vtEj*;bu%uhUJx<^sc7gd|htE;M3n;*|yxK2^-F143dEPghlF4=B>rd(0% zV$GN3=|UDL%1R+u$Z`V2lvosep}=lmF3U6Q_PA)rkJ=5gJa^`ts0wi((PL5V_WqyE z{y(>qfZ#IVRiHTvu@^SsyVcUU%1_MmzGSZdk@@gN{YUE)klp}pl|$z)?_tjCWX}JT zxuBbQ#ShF~m;N({&MoL-o_T;dw*xtjFyH$bbMbNJCCGV;K6GySKIXI!nP-5X^AYnb z^e_kfxyP7GzF{u=o_WvUP5ZD*?=Vk&k2z%zbLM{L>_f<fy17T0i!g@;Uo$U850xI~ z9T&!Ph?&~sb}%Qr#hmmm_`8|Y!B2eqB1=d5IpI)0&+HuG`EKUY@0csVU)Ia~;yFEs zxSOK5?aWh}nXRqp0re%!%W$fX%^j!M{P8K4ynfCErvyDLImujgnt2WG2V9+R)$1Y0 z`{15oo<77JbKoTWwK`%BdUzV{FzsjNg_yzC^UMQ(Oz@Krqi1ne%tmkpEXTZz-zzrO zwy@=^GrBD^2tLq#h52H5f}euE%0kS}t2pB@?(bLTO_#3lOTiGod^yC8mw)GcHR2aB z<%rz}p#N>a9ATRbN8c~w{cjBX_78sr>VUfr$doUS_D$v+di%%uQ@j^$<X;&bb$ZTy z4z3M|1*m55FIQDa8yU+(ZQqXb4M$H;@cV=3i(hZ91tk$M3hvliHE=b(dT7)wa!~7u zaXx*}!%HuP!(|7*XhCcmfEVb$uUg-qYm-*J3BE~3@oQ~b-pYn@FeD)Qx|-mJtPO+y nSgpxz8nL+yAuEv|XTp1q@Scmr3(oa0x$vrU$GWT`tKarF-a&AK literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/app_notify_info.ico b/krb5-1-6/src/windows/identity/ui/images/app_notify_info.ico new file mode 100644 index 0000000000000000000000000000000000000000..2e4d51960d37cec43364c88a0b30a76eb2d80106 GIT binary patch literal 2862 zcmeHJZA_C_6h2V3bvlY;!Yp*KPCFcnI9QP3V&gyiXaAQter(y|SO%;y1yM`I4H_mi zGm6YDY_f=mA6ZbUGAXq>K8h5?TI8#iLJOtzg92^k_HB3G77TvOY|DNv-sHabp68yA z=bZO#&jpA821G|k<GKQpBLFf0PzID)uxBMeHez8p3HGc2Xj=u4OzYrG!b#gbIq0*c zA*DC?kS=bdi-HsZl}ZIc`Wzp@#Z7Qg2!;Wci#`XCg^qzGlZODAOdiBdL7_~Bddz}C zc@Tkug2H@|2ZIF#^6*+HlZIq@P>KP9g)+o(Wyxgp>OyyDPdk)Jnc)CZW++_v5hxD& z{DMHSFVQb>F@1?DhKnhUP%$tYtjgnqMvQpsVjG#L%?<|rg2(H`dfb4P7QIA9MnXx6 z1k`FJm`o<9t*wFV>}=@k(}JS05!`M!h(x(iRdo~w2lde0tbp?JQqX8LFg0a?hK4$j z6cquV&j*9S06951u&}TIN~IF?dOZ}0#ZXgIgJ*+KSy>5Mtri>(2VA_^0BLDyP+D37 zZEbB}u~?w4t`2SbK%r;^kH-UIu?S9{tirg1=&u>$O<}wSkVuLkH#Zluva*1~;Xr8# z`cSK(uC^9(KK}%{_kmc1wpCTgw;3wS%R!5LO~@}7`2_+2P$R#i$fpnaWMpK(6vkI5 z6tIAC4H(aXu`Xh)5{cyL+Py$tRN#M70bzK=@D?}WC1Eo!Wf|~x)W#Sd_Yn}yjEst7 zq_9{a<mH!EyuLOnW-|hO1m4>9{<id3)_NX?$K|gVzW2dv?+PO0ckWD$Wv~(0wQhAp z8t+w9e22?R;j-2xZA05wq41Ts6c(G!U6-7|;4$Ka!o(Cle?6C*oVA7%!-y9OQ&}to zSi*!=8`p5Qpv>hWLNkb36&L$vbS67xiQyXwYqttlGnS<ky;Zo9R(*Q>xBs(A|LUtS zJ}}5EX7f$E-Om0e4mvwJ*u6d4E5k#B#5_JutX8YZ<#MI|9Uqq)e@kt-{<}%j*+F!= zyTo7^A(Imm1UY!n$4Afe@pH{j*$wq)JWZD`ksGR3a=S}I`up`{bks<utX6{dWY+CI z_M{Ja#gR4Tva;&q$BvRyztoTm=Nrhis|rGM7#SWWg98I(Y;26!Y&J4G>n7L(Zu<TH zP))?5uj9pgMeT=*50Z-S%1QN!<K*<Or--UmN!;!k%fp8cA6P8rh2h~Lg0-acAoKHc z#OL#w&`0W?&py5M)t6t8ed4|3+rx**_wovw`+~f((t-c~^YqNj%=BX4S{OAN$>ih& zaXOte2ZFu_4oMD{9oSc>*(=I-mq;b#mimUrY#txNem9MI(j7cB&!0PIaylJOngjML zkHc>7!Fn_mAJ|`3`pw~{AF7VGcWF9(SZ@=)w}F<H>my6Hn>KCo-qY!ZF#iX0b8|lH z<YbT4I@yFgnk4&+%1&0F=)w2x8#9ek7V|h|8XcX{>+e0XPft(x+H6yHk7u6pdA$_o zPGPUTkF)8=>J#U>yEN3m{eEg>c!<Jpjv5;?Q56+O$Wr|6+qVa1W?a<l>@0<~qr6^E z$cKAo#&Sh*d5gCDcFUdK9!jsf`^ZmTUS43y9{X{?K0Qq#UkYs~%z;8K-B`mNs1q7$ zRcm%vXUBBkonES6ucKO(EmYm<)707edaAkk8ihGi(>5FBbU5tj=irjv@)hmb?QMTl z^lH1QYgeyO@$sAxhy47!0G-o>#c~1bkht9DS$mc8`i`^pXSz3R*buV+c=v7t*5|`# z={^r@Z@ZO?TqO5&cmMMD8xRD2zQjPWi|rQ}@ji#QHN5UU`#wj<QZb|vMkcN4Vh03% F!Ji+wZMOgb literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/app_notify_none.ico b/krb5-1-6/src/windows/identity/ui/images/app_notify_none.ico new file mode 100644 index 0000000000000000000000000000000000000000..cf60a3e6a38b22c96abf1af201a0452e212eeb26 GIT binary patch literal 2862 zcmeHJOG{%}5H53#iP5xiNbF9JCb`2bdecL%{0H*~W;YB>Z)VXjn}J!hs7O{49nfJG ziXzeoDu{^aN)e3@!u5$SeBv|W`~8g1>aT8cLuVLtF~h7p;k)P7sq<CUsdIDc5G9d9 z4u=DMGQCM6$|ZtKkgfE=O!PCxqOy-ZBol>Fh~CH?zy}EL?@e?@^UDh!{@9B@CipQB z3<ilsj|azII3{p(K(z6e7YH!>i9QC(q5h3N=Aq*VWa*jmV!ccgS??pUK2RQ&1A)Xo z5}+s%y;Wz#{V~4}2fZ+433`zx3l^&YkN$#~v8n_W=2ayzPu95I_zQ9?&15oBad9z) zLLu7R+@ywv2AY|fp^AzMy1cxk&dyHC&(Ei^u`xP4JfxPE7Fu3jrrO$CDl03ahldC1 z>+7T3+*~RxEv2EMA==&DrKYAPT3A@1>gsB`xw)b4?rth7Dx%5BNjg0}rM9*<T3=tM zy1Ke(AkWX|3_NGxf6svWM9c8Jc4oiyDrq^^uViX!iYY2uyh<wMq>L9fC@mH@9!^!w zc;&OYqH>zWt*WnlS+AqA%avwPRbQ6J6qOaPD@RqcJXRYN7Ps4OS6r&<v1VrLbjM4x zT~SqQrqc}B?RJ=LX1l6pI<xKK&Ed#KT&kL$oSrGs!N1L!EfJ=qg9wwbXcJjYHi3ze zv>dN4Cp`Y!bJq9R{-s0tE%5FMd<XqEzze_x7)`jp0_9KO59ogfz6ZVrP)R{5FX#65 zcJArv;laT{#yQM5pBZN`Z*On&!NCFJT;{H>t}~qFJ)ryv`~*lTNi8fa<jTrQ9vB$l ziHQlFySBE*TU%Q?_vGY+FD@>0dm9@YTu@Lj3*IN-7r=uW!xBSHO%0EZj>dfo@BI9n zudc2bb%KwMj#$P-9v&V(1h)iuE8ME8Dn`BFj*bpSjbYRyJ!bJ6i9~e1jEM~y6MNuF zzTO#J)FnL!U-D7s;{2VR9TprPAG3@beDNz>$suYb@9pjBe$LL$^m&GVS$jAf*5i|P z7<_|^{PM`ih|U)u#@es1ule@&mRDC-d1+~h#g6ze_~KW%{r&y=-pPI$IX8UY-QDrx z;v&z^&N6B=qn^k41{XQyxw*N7*bU$J_xFt2&*S6c`ka-Ol{jDg3U_L1O1Ew7+n2tD zFW-iIU((Od&&T=A&CP$+*Vl7vYb*Em_VPb{I}(TN9qt;8dxY)_>n{f00#s5`@&oQA z$FRlI)6)rgl3dE38*7pEOP)dd5%36K8onb(V`F2RrfDIpQ$wya%+-)@4g0R`@9%4f uLBoGR!+%2qMgBvn!u?lGc^{@E+~)}QIl_I8aGxXG=N^F{x*$dGbDsfUb5*DS literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/app_notify_warn.ico b/krb5-1-6/src/windows/identity/ui/images/app_notify_warn.ico new file mode 100644 index 0000000000000000000000000000000000000000..9d43265ef75d08735e0931053b07553fa7c5c04d GIT binary patch literal 2862 zcmeHJZBUd|6h49|lND4NshI>trj>ok^a+8e2<|#UGKRK!%`w|4bS!rrGKQ%c+W4_M zuG12mQtreSJGdyAB|5ygHq3wyC^&x0$3hD%>;g+HuzZ}(eOcZKe`G(L@sD@s?z!jQ z^E~IAd*8X|0!)KI2n`J-IUN>F1BeD79Y_y`?Lhzvnw!wWVf%D|su=)_xDEAi>Ku1# z<7<;Gn-AzO+ds(mE7>$rSy>6l*Xa-a1N196F~L`*rv3)@XtDuBN%m^BTB9MmkNi@t z22m&J=JVTBWIu#tM^dAkz-csOL^x5Bmmv+%Dh)^mb14QQ`a~RCDo!k<$q-mbTNOh6 zKYx|9+8kIJh}axBb)SNzJfs2bEpGt<0T7d;h0Lm2*yiv;jJXsX4hQ7AePA}5L4Mo@ zTCEn63<XeAQv;b~qqLNQ(c^=7YXxk{)xs9L2MQc+$SSXZ45tsgUg9aRz_n}FAd`4f ztmP1|H9`hqZ8jTN2&->&fYI#*g~<YP^Ko#y-C(s^K~YfyN|PDt>+3;9TnfDbRJIyO zBEFQ;3XrR^AUf9o+v@G0=iKF0kYVNVj6;Fb11i$T$H&2Lx062~Xzdgi@uU+rp66Lp z4@!z7iSl$houDNSi^T%zl&8U9fRzRl)YjI5oad(1gOYMnmD^w!ark^bSV?g-Ha0?* zdmNJV1+a^_%-(S@+MQsge9|n(!Q=5jX(`2IG{U7zmmpnl1i8ryX*`Ck98gibCW_Zg z@qR_T_u9Q3xLZ5GZqq{Fe`FP7Pp3TmflRb~ZqcjnF&6&XE2+^zd}7m^Yd0=Vf8qXx z3nJFfS;pA3c?ompE=ipK&Vq=DImwL8OIW;wvBdeCm&V3M%wa5HP0WjoJrp?qv7qSK z^^83_J>+@DV&0ye6fFyirP0dZd5k?d`x$xI1{ryHBmSxT7<>2i882^$3ZoEKKl@g| z11~-CpkiIrtf(-?B4<WE9vwu!lOtBlisBJ1kBlNFa-J-k#dQ|9B5cB9S%j!h`Mb0C zZ1~+e#@qVcoU23C;WErRAt2N4=Y>Y>%Ad@b-`s%*|8ilW(}Oo}-mJTE<Hpik31#ZN zsMwc>s*``>27SJS-*l)5b*(Nu*x84Lt^uTb7u(v}(B*RN_%}yfRt_%D(P5(g0H&1* znEay!*O;uhwV?&SaQux%*C0||z@DBS?Ca~p!NEZs9UT=WIbsOAT$hil@=Uny@Ci&Q zIf<#I6-f6p?sN>G&NYO;5}xXa$T2W5fOKE;IK?)Jr8<JC<ew(R{xRV{ad`3Tt|8pt z<HOF*PO<m)_9E3W37=pv;i`icOg5Kc>K|1S{zH2|Zf*18j`ktk)9n*;Z*6Twsx4w3 ze)kZ2z=AP9mtlPIDWv)(;S-5Z=@`UMJBIPIt`Tf*Zsuno@^p1|N&dNCne`OPe>;P5 zI-`V_{c;R<b`0Terw_k$jpFs|*YWb@%Sbf}sg6td^rNS6<L_rsQE?Vme^(&k(~6Ga z-mYQ%);)sXd&ZFJ6`ntT9<N-vf=x|L68`g(XK=UeEM`_WU}jYvDvOR{MsXSLYih?I zdVP4Pe-zCFV|d}h1+1>F7Uk8eS0#K&Nr|qoun><NIfAE8pT?G!7Hn^C=iiCAPyD=w zhlj<pqxy^V*1(2_1_{sik=`L|^YZd~ii?Z!;>C+o_KBa@B*)0eh?xJmbLXbuIY)ke zehAh3lDfJ&f#MS=4xyu?L!j?Q=<n|r=(`i>yAj65#)R(fZh>R&M3e5B5PHwe{D1Gc MY<kaC`rmW^0DMoEG5`Po literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/app_state_exp.ico b/krb5-1-6/src/windows/identity/ui/images/app_state_exp.ico new file mode 100644 index 0000000000000000000000000000000000000000..b365b6bf3287846dece7a69de55492169119af30 GIT binary patch literal 2862 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 Z1pY-TXM`~L`~9C`;FyhUGAB7@{{*b#F(?24 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/app_state_ok.ico b/krb5-1-6/src/windows/identity/ui/images/app_state_ok.ico new file mode 100644 index 0000000000000000000000000000000000000000..8363fb2c59ba6027c730104215c6e7d883308b1d GIT binary patch literal 2862 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 NP_xehi^K`1<R1!AB?|xm literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/app_state_warn.ico b/krb5-1-6/src/windows/identity/ui/images/app_state_warn.ico new file mode 100644 index 0000000000000000000000000000000000000000..3510e5a5ce79be55a395a1ad97ea8da2a58b70ad GIT binary patch literal 2862 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/cfg_applied.ico b/krb5-1-6/src/windows/identity/ui/images/cfg_applied.ico new file mode 100644 index 0000000000000000000000000000000000000000..4fcdf843c8c4a41c4dd55f3e0ce0707f99a6b63c GIT binary patch literal 1406 zcmc(eEpJp&5Qg6-CE1XQ)~u?4Dprpmwd<SIRIi)x4{8vriX|Z_Ij#ao5Sa1@Rw3vl zxUHe8qDiw!Ti2w4;W@KggD2d(b3WcZXWr+|xmQ}_-rQ7OubxOlMlXmiJtNjMpsm5O ze;ltpPNxz-O{dF_mZ4^|nPxv{y8Zr1>+9<p3<lcR*wEJ2mWIQjwzs#nv$LboXrzOK z1MThYX*?clcXwCQ*Qx#e)H}_Ui_o|EjpkQZdi(hcMn*W%h*(Yy&Cm?Zx|Yi&j_&A= z?&yx*w>9*J-k3D>hEAtI5A;9}gg{T`$vmT+jn?ot5*eFJsj{ar7z_r3!C)vP7z_r3 z!C){L3KIr{!C){L42D97!C){L3<iV25)BT6!#YQ1RRD#)-;D?Yy+1N6j=5vxBz0J- z4E*T~92SSA$^wVO;cz${4o8&=4u`>Ea2R^&91e%UVF<jEwn~W4@@8J;?bU$_@5ZVs zHQo)ThH1l~!PM|>{Mks-@NRh5ag;YY{tf?ze?Ovzf1@@Hh6Y2U4*l4uN<BRaJ#9Zm zY7qDZYyn5$S4Z19s6oIHor4Ff<7QL960igifnmJ@uml@}MS&2o@FU2>nFK7+>rpKI zZRn?f21CM-FeD5KL&8w66AS@E!jLco45T4g4@1I`FeD75CeUF>7!rmAAn^~9B^#4P zP7Y`8aAf7~Yh2IuQIp9;hlhtcIy%zv@v+X%&UAWus`K-6U0ht~^72yG*VnqcyVL#s zy>1^;A5KpAj;B<&e*?WEU(I^nK20rF*VEOtu(}riZT=U}Bgen$bwfdZ5O0Y0#7p8U T@vw?t^hEafy^5+`ub=b>y;{N6 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/cfg_default.ico b/krb5-1-6/src/windows/identity/ui/images/cfg_default.ico new file mode 100644 index 0000000000000000000000000000000000000000..d6e7f24e0d3228aa1738113f11352a2ac04cc08f GIT binary patch literal 1406 zcmc(euTNW16vw|LENK=5m@34ETJ=#_JPD>6ce4KgGf{<JvZTp%h;7Nl40@t!VjK-- zC<F;<GU`Ys&OZ0N)-2d%uf4y%z3+TK?|WaREk3)us_X3wY0T^mtxK<HTN=^VWEeN| zt<7>K@zrcL4D?L3SS+;oxzOW}&)VMJ)@U@+&d!eZ_VzR$kF~$QuY-dFO(qjfr&Apt zAM5DoNQZ}qn!QV%oTNVJTDc5;zy77``+L3r@)aYaIjzxRSQ?t48Jcx1hb@lo=#K8_ zj^1x;=ncKGXy^@{L4h9VfgT8fo~)B~MmZb3;cpZ&ZZf6Hp3Yz}7z_r3p^#uO7z_r3 z!C)v%7z_r3!C){L3LOT6!C){L3<gUyI1CQ!9GR5>3S<8?TF}t@Bg5jDJ4Q}XhoxfR zM`z-&I4l(l91e%W;cz${6%`x~gTvr3^ynN8hrwY8ypp~m#Ao=hu6TPoP~qL!RZ-*J zU}~5)3>r)g@5YafA`S0`cO6H0qvPN3Z}|5kYWO#@X)rVx8aec1Bb9o36h``fjARh_ z1#AIF;8#c6ImjU3h|a--)p2uEz!I<o5P@O60<Z)(2AcvQVBt%n4rdauM9-sG`rFV? z0S$(PAz?@u5{87KUMCm=hJ+zu2pA|sV?PWDL&A_SP@0AgL&A_SBmjwjP%ODI+2qu4 z)(%Hj?Y_tLTAy@!daARtGo7EGYd)Xr>gr0DmzTP^xzX+It?usb^ziVY)oP`urzbuB zPJO(%;D0<L-Toiw1NCav>-J@8xxQYmujRM8mj7-27te;{UybWP*7*!kJ*N$MRfOy8 GhWQ`3QQgV_ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/cfg_deleted.ico b/krb5-1-6/src/windows/identity/ui/images/cfg_deleted.ico new file mode 100644 index 0000000000000000000000000000000000000000..2ef11c7d11ada0ecc655db6d6a886301a516cf1f GIT binary patch literal 1406 zcmbW0u}fS*5XL{jz#$ge94Rakt5{DZq_P)mtnG&U2R11#&DDW`u$@H`NRh_B;2@A9 zPOVL>ECe}-c7_y_-|XFsMXKbzo86u7?e6z`v+tx8?u`xg>(vu!%;*JC(lcU3BicS# z^uu^%NGB3MO(u(umZ4^|nP%T-y8HG~tE;OTjYe8uU)Sd5rpDv3wzjsky}hlSogEz> z9%_GoUweCd+TGpN<aO%cAoWfc%6aJP#SdNF-01D6&lnluL?dF68k(UQnw6G|DUR;w zj_&A=UdtMKLvJJvy`j@7&;vct10m3pJjpY<v(Xy<#zw{>Q>xq37z_r3!C)|SBp3_^ zgTY`h7&;~l27|$1Fc=IS9R`EJU@#aA21_(J3=S)f%w7Q$`nnqt1bV$PERMNj<ZSA& z^fK_!88|EsOD_u?4u`|xa5x;jRB$*94uiu`rE@qO28SW=O4?pRd=@u(FK<-`D!d!B zda3blFf~jY1`Vc$cjIAWlZJQ0yB|mQM#sP5-|(*^YWO#5(_m;YH0n^tMpgRTqtMgV zF;auTFJKEe0>6H=#X$`MjwlXZtRFXv0+xU!fCvoxCjd*ZFqjkw0SiBZeK?bVC8{2s zrM`wb1vD5EhJ+zuNEi}^{yD)AFeD5KL%_f`1oL4?7!rnrfvpL27!rnrApuDIgUynK z$s}hFCwDlq?_G0T&-Fn^M@Kq7KGt+P)yc_;&d<+vc6O%A%S&BdUFrJzTDP~iy1&2I z!^4B_ex=@@p7KAQP~G|uRL6cjt9>g?&6n5O@|yqb*Zf~|sa8nCdTc8Flh>GQZFt@v vGUcy);91TeIBIR}@t80ChWvl~WkHtp!QdtFlz2mYSq9@oOP($2_SpXh;Q->| literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/cfg_mod.ico b/krb5-1-6/src/windows/identity/ui/images/cfg_mod.ico new file mode 100644 index 0000000000000000000000000000000000000000..65e3691ffe37eef19d71f7f78ead1365cd01450e GIT binary patch literal 1406 zcmc(fF;7%c5QPs3CL2Nl%{FYIR8mhPEj<YhHQmI2Kx47S1WQd!NNz`=CKfjQ0k^V{ zsiBdIf`n|MbR-tzcjp0OW$D|Ud*7VBch2|b?yj`JYh^`sJ%1#PxqC`<=`pdO5o6s9 z^WFWzT{@L`YdRe!Ms78m%{2Qy)6Z`owYa#b(P*UQ<z=m|u4+6UYciQ=eSKXU8yni) z-PQK?wzjsmw7I#d>5J6PPU@XbmGjWo(;qs$ywuxIpD{ARiAKbb8k(UQnsqIQC64as zj_&A=-nTXMhTcdTdP8SYpa*)O2ST7Hd6H+8voRX}Mj>O9DOL6i27|$1Fc=Jl1cSj~ zFc=I5Lt(;TFc=I5gTYYfFc=I5gTY`hSfasUa9HQatPY?s_g5o=K<|$Xi(~E>IYk|o zY6BlSHx7%#Qf-05;cz${4u_*!1&71nFgOgobq<Ha;4lPU$yhDKXLylUdwX}F!n?7m zT8(#usbShMXfQRr8y_}`G`t($bsXi5j(@|y;opy_;os;@gQ3CD=tDm?x>8S%!pzu@ zksbto0b9Tk_|?&N4tfx9MCaha>bThyummgtL||B70a${K!J<G2Sa=iE;Y<RS==~^` z{%z=|fCfXtkT4_+2}8nAUndv>hJ+zu2pA|supWklAz?@uC{3WlkT4_+2|(f>6iYTH zi<}xx?r>z)?rU66^g(-jd)nXM*TKPo4i67?a&n^M<71tjo$37iTo)G?y1Kg3_4T!G zZf^ARSL*%I5x?Up-R-}DK2fi-Ubm;I`R%ndS*mOPtgiWg%kO#kcNvg|ak93y_E73M m%Kehc|D;Rge-(JRw{N;#sxLI;U-6n=O>g5R^DE*F!M@)yXTp#G literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/cfg_plugin.ico b/krb5-1-6/src/windows/identity/ui/images/cfg_plugin.ico new file mode 100644 index 0000000000000000000000000000000000000000..99ffbc411b5f9cf6244bd011297fdb6194a5478b GIT binary patch literal 9110 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 U#!gL^-VAqF8Gl23W3Smi0oL6$(EtDd literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/cfg_plugin_dis.ico b/krb5-1-6/src/windows/identity/ui/images/cfg_plugin_dis.ico new file mode 100644 index 0000000000000000000000000000000000000000..853ad401e772015a2e8f1c40dc39a06eb1f50e3c GIT binary patch literal 8854 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 U?GM}Q-3clXfUwzg_|naP0>*F&@&Et; literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/cfg_plugin_err.ico b/krb5-1-6/src/windows/identity/ui/images/cfg_plugin_err.ico new file mode 100644 index 0000000000000000000000000000000000000000..1b1b4ee2e2046f33094256112192ae392f5bd9f6 GIT binary patch literal 8854 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/chpw-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/chpw-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..230ad36a406bd2606a792c457e72942867da5bf9 GIT binary patch literal 822 zcmbVH!3}^Q5W~2DPe*V92Jr9vu46+<Lx7ZvBwVh&wg>l<_f$?sy>O3uw{#Xh)j0v{ zyE;LcV*csj8WR|0DlOV*lp4Vj*Xv29X_JjiBW)Mso2edT=js?iHl|KTAjxwJp%@Qg RF#?8|I*u3^{BI{)!VjzPl#&1d literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/chpw-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/chpw-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..43468cb2a9a68415137887abb325a479e485320c GIT binary patch literal 2430 zcmeH_O$q`r429#;8wldw6L<huZoHD$oa-3pbsi;6B2K9&Oraq^uOE-hT<?#)%;%!< ztoNk%sCOp^jUu-)pNkTvF-OK=r;Urn{?Z=sC*>b}jo-0cr6-pC866=>VubGHMy`9g zpZSf{=yNTJ%=eo-&=I(AH2K(_c5&MeVmhWY4xByUK@!`Mfokb+U)|;K!O|#tQ&Ps{ li(K^r%Ta6vw8_NxOCoh`2lQG{=OMQit;jbnmiBjhcmi)E#asXY literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/chpw-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/chpw-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4cc51e5794584f709d9d2c5aab0bb1a1cc92ad69 GIT binary patch literal 822 zcmb7?p>KpR7{ytaOix{=r<MuiNyNm7CEFh`F@ZoLP9P8n1OickoT!+XKq5{c5D3Hs z0#On~#l*yk3IyWBvKM;cs91Kqe0}-)`fH%jho|+WF=`FJ!?-?<3*%<YjpMqSC~w== zUZSn*hGCGLCy;^f7e(<i6XU1JyhjQ$ilVYCC&GO13GM0U0ZC8|=&f{^Rzc!Ls;Zh2 zTJ^*iC|XL@u=>P<WQ^5yJ@II)m=n8F^_+C`C6H<Q(KO9rl=zY~<))L9O{&V;7Hro^ zIVb>RmSvptVHi5GCno)?06-vdWVn=j)cqzzg~{&4eIvIH96gdpJ5c~g905=1bh%zk zRu){3JCG2z<hovMhg_}TdYpq4Lf{CoF3<CDN8oxKgZy47xlp*D>RX-Z;OBqv-~JcJ CM>cW* literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/chpw.bmp b/krb5-1-6/src/windows/identity/ui/images/chpw.bmp new file mode 100644 index 0000000000000000000000000000000000000000..43d0d5ed940f0216e399cacd57c024a82d9e3a60 GIT binary patch literal 2430 zcmcJQA#B?~6ox&s4FpfCRya)q1_c2H0YOux1r`(-6a)kW1Oylu7#J7?1O^xc1Q-Ma z3<MYi1R4yql0iVgfPq1PK|s_my=uL@IMNiizurB)dw1{4*>}D)f4LuxXVvlFX<um< zv=7E-ykY!&8Gr7)xX1UA@jlqc1Fmh~RW@5K^nlxL-&Z%u?RC4|PN%v_Zok*-wA;7U z#IhvUbsb*9a4`6DuBe3|xxVMI-pORLE7NN8n$_di>~2Rb1j!A8fTuX-CfUxKY-^(; zFZK{TF_~jJwI%OiI2^Kd$J}YUHN6aLMLFEYI9J_xz10^>Of3Yt-qC2p)*W*x=uR`U z_kdZ!N(Jsb6Hvv4Ai3l5*y;C6xzt!rV%{y35g$Vp7lPzQQRFxd^sS~mFTz>cau&7L z)NDq|h;4s4jaS;leYjtl<4EpoHgjE<u|m`3O=wz!Q`WeTw7CVf5F~d#|Lu8R7={~7 z9XB$+buSwpfpy~(<B7=-JHbqwyP+0><i>IA`#!suX-d;oyhv2yy45qkwD77+o>6UX zMlA%%T`rd#VNP3mLiOgYS^I%MF`iNjL2{EMA&dBdQe9ouP4g4Jbd;njmt1ZIK5#aa zgK?gyg&?^+9S_2FW}ho+AxQ3ey-w2ycCU&cNbcV^lH}%ZB+1oJc$HXk>5K3Eylx4X UROv<a|49YKAN<e%%T^DJCu(BJmH+?% literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/disabled.ico b/krb5-1-6/src/windows/identity/ui/images/disabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..6b6a9078c1dd7d32ae13c81919d5c85046256023 GIT binary patch literal 2166 zcmbW2ze{9S6vxl31{EY~BPoP&EtXi{N(fA_7q+psyW~HxS#V%MvegI+!i5mFNCGL+ z_!o>UWFTHhr%i+nQ*4kxX1W)4@Z@vOy>B!jMaX?~f1K|<KR)li_f(`KPh@+0U9A1~ zMC2LsdNJjTk3>FR5cw2soBlbyBa4hQeA{O3HH1~)f70*Uiq6GiI2<yYqW%+AThX~p zvf;nAlpgyfZ*yg(*k@HRQ-q-kb%9(Q+Kp-#ceYkafF&!D#UY)wkt?2n&3Q&kh+Q3g z--qg8d8*ik7Q1Gc@7D}wTRt0^=Jl|x#ADkWs$Fi&Zo^mgHgG7JSXjbZf<@KayRr>D z=I-u^RiiD`teVA4+TX3B{jZUCptM;}b-19~@96!)@MP9)db94V*R0)lCri3EeW`=# zCH<Wa#*>rLxap0?v+ihozc!lc(qO7D>6e3vzFTWfCKgG2)3aQb({o#me>8i~*Xi5z zjx00!qRj2O)0%yIx#_&$Hrd6(-t*xvLz(>aoh&Xc%JTBEtgf!g#>R$hZf?rf)|Tw- z?8xr!t{fg7%E7^b?C<Z(-rk<{U#L8PuJT&0MSsuo<MkhM{r<h2eg6X$0zK003Fcx3 zw15`Sf@yq1<`U5(i-;c4Bf5np^n~uu7(JmgNk-4;8K;bp(G^><HGAd27)TyS6bK4@ zw_cthzz|>vFa#JJ35EbefFZyTU~o(r0t^9$kkDapbQl5*0fqoWfFURv9087C9Q=)d z$|)jageAffVewmrB~m<6D3Ub7;>W;dWD#MBu=ugS5#fk%L^vWGepGNo7$OW220OY4 zM}#55ko_-KE=Ne6a$)=N+UY<=?S!8nHMJ8=iK2-D38qBt#HM{miQ0+UOmwS_PW?pv zM16ZiiTcTO7!nMLbFjz8srcQaFf-a?<P0+PGHe-+Og(?J#=#k6II?kYWB#}a%CKZu zG7y=9{tCd73CuWUgbWKmI(c{|8J2A4;Vkwx*i%4*L19oB6b6MsVer=ph75zkpfF?@ zNJGaT28BUkP#8!}M~6XSP#6>drG6%v5~w&uazyM1hk9=FiSkswm7}90IX*s?)6-Kq zKR=hNt1G#<xR9Hh8@au`mGO8icXxL(old1`8ku}h`R2_VzT-ZpYu|uP<a5jNnrYU* zwP)7m8*V))b=3;(%>P@DF}udvY(^`THF+NdmR6?<556wc!9i^8zSY%2=CPKeHOp$g z+Xfe3w;m661hcNlWJ%=Lw<2$+BA0)PeA$S6^+M$9&qM~Fi2VFYWOP}4%-3Qp_AiFw BZvy}T literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/enabled.ico b/krb5-1-6/src/windows/identity/ui/images/enabled.ico new file mode 100644 index 0000000000000000000000000000000000000000..fc83ad85844df78657b89c0f1a89df059cd8704d GIT binary patch literal 2166 zcmbW2v1?;T5Ql$y=fvhP=-jw6NO2M3dMj5x+#9ZO?QY3`;3gndP8R|J!**9BffQ-{ z4@3}15ig{(o0u~ga=`>5cM1`nd^1m$gi>5C?`ih!{C0Qdd$W&~)KQ}sFT`_0pMD^H zEUDi|;QGChzCingzAJsq=lS)r6OXp>{>&fBZ)q6KqB9zeH2QU<@z38fHk8FJnK37< z?HI!NZ`0SWUu$h`O&c2<+T7gK*4CD`x3{&kv!mVJUG44d>G=3qM@L6GJUrC?{=SBv znO?mzeWfeeA5}kH{i&<BZ}sJO-;*R^87o+A-Gr9V5?XQ%2A`7AGo6f{(KEU)E9eEi z;1u+N&O;TwqF3~aP|*$F@U2GXM4Jen2$Wcqc<D$_lVC_NBp4D5fdoT>A;FMfNH7E@ z3<-t=LxLf}5a=)@7!nK#h6F=0G&m9*$vLPkR6&txGb|aF3`@K+EScn)M46x&mM8;* znNEf!!xCkIBg2v5$Z%vhqEv8X7%~hQ1}|NPBg2qksIl+0Eg^Z@8$ZhH)q#rKg?UkG zau=8iNec-IOoiNq!9wmr?n3U^j>wHp{zCpje&3=({z7dE3<ZWl9emrUO1wP^Pg>tb zYEa2nVXJUd^2OFV2Q{d0ROjHuV!K&XVX3fGASwyt6M&_%urjG4R9N_7#9>b=EY<4~ zEdDk4E}+3+Fc=I5gTY`h#ODM<g~4Dj7%B{e!I%$&!C){L41~teVK5jB1_QvzUkPR` zG$v(YWc&<=MQopw^^v~O$;pXMPfvArcBb?5b6s9u>f+);*Vos&xw+BZ-JS05@AdHT zpvh!HMgPn7e0^oss<7(o{e|~mq37?Q`qzY&`M8uYY{GLgkj8EY(rr)rtt<V4z4@Fu zKVo;-1NIkYt@%0I$6jI`t<iFhat1$Leg?NEvn#{+`9Vt$<EG>1?9e-WP5$%X@t|$< zxc5IU4&DCpvK7C<-(4DC^?i6bz>435zX-7Ex5JA7D}GG(W=7!M{*sT&+Gt`%JLKwY zLG)U6HlZ)M&%>`KItyR15dSGa)6SavvsLo|;V%)){igu)1?@=NHcJ^pd6(aEE<!Z@ zMStGoKeoL_1GC{lYwGcN^z2dHu&LI~ZK7vkV|C2!wvmlL)L^o%!L+M`X?J+=*c<k& dH|p6BqpsPl+q&7<?U~uctz$ODpOWNp@DJ$!6Mp~z literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/flag-critical.bmp b/krb5-1-6/src/windows/identity/ui/images/flag-critical.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d643fb31799d8d6ceac0eae8315e7bef993a5745 GIT binary patch literal 822 zcmbVKA#B_*6iqYfK*2N(RK-I>g@py>D;yXoC@4HoP!LcM5O~1gK!8Dj!2yGSfPjE# zI$&TB;7I`i1_l8J0RaZ5y~~fPk%8^&`{()nXUG5B_up<mM2p=be#Q8-j*IAe;UnaK zexyM}6#e=yd-|I_KE7w(H-6b}i=vq4c?xGgolXzUyvf7OApny#O#>M%Ns<I&<J}bx z&#i|5akCGvY6KR&g99+eNS|fdG)?za*svL{olVpTAo~HB$YvOD2GTRO8^>{Q_Io|W zJO5CJ*4b3MaXSA63}V$AAq43;=V@yiqph`vuJ<S+oXD~ErS8qpBPFFIeJ*&M+Bmb= zit8ajx){Er_fo5ErQwA<ta>Tpw1;0ZpX*_s*A@6Q19(eWCfD<{Z7b^PxR_81wWD1y zfc)5{vby6PmgMDn9;H-W*SwTpcHQPpr?o!zrn5t-b)0k{kwX8mADzb-!$ooV+Q2`* zDOr{`OkZVPS(TU)zZV?ak{-3ApIjT%i)H`=z|mn$0e;jTq;r<^-h0%Dmbm$RxoUKH i3~&INBBEE2k$!0ingLt*dBOwOcka)Npfu_KDgFjV+C<v` literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/flag-warning.bmp b/krb5-1-6/src/windows/identity/ui/images/flag-warning.bmp new file mode 100644 index 0000000000000000000000000000000000000000..edb3fc3c88595f8685a3188ff115b9131611ca2c GIT binary patch literal 822 zcmbV~A#B?~6ox&G1w_+OHBeX$4HgU*RvH~B7zhXq2rLK~2nZ-J2rvi;FfcGMFeo@+ zO$7!91D<4X;DG}VJaFK^fz$r<RawEv_VnNLfA2n@{9bbN<@#;*9M{MnvEIF`H`&E= zJ;V8rxh^ea*{}bK<#O>?Ef(L-_4CE+^{On(5Q2{<rIfw~e-+Z_2>TMo7-0I!W^)gC z^!zELwPz5>;J=H5uY@3&{XSQIyW4v2Z)3XjC-p)gVQL|GEgGTY@u+;BKQOapcNgLZ zNp~T1LOUT2a^({$$c?jARVsft6dQJrb|j*bNrKmpjxplhmB{EUj+&-ceqWb!PIEb3 zbzlN^=GjYW$E7e-JT}Tdm}cf8bSbF-AO7%$E$-3NO>dO%x~>?WG!Aw|?-&;X&z$UP z8ZoySr|s~h{4n$wZ{C^rKFzG$6B(L*I;y5|W<82HLf}H>r*Ygj)qJogS*h9<ji95t zZL!t*uBrQ>S024%o`ti(TFjLh2AbGm3$q9TMdwI)5z!u96ilY~gdZ1z(JeBD226Rt TuS258AD|F|d0mHB{-5%1wIE^R literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/flag_expired.bmp b/krb5-1-6/src/windows/identity/ui/images/flag_expired.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a3a40feecff222d6782d44a2e13ab4b51114b589 GIT binary patch literal 774 zcmX|;A&jFy6o%Q^WW|ZO&5F%t1>!_=L9AF&u>w)CVv{o`Dk>0&6%`0XMFpaw0<oe3 zQGq}p5Qqu{0zoba1i6gpB^4DF2m}IAQ9<q>-tGN)^ZMq!ZyqzRlOH$N%Ahg)cdT2i zuUJ>g1H7XAW{UEQ(;5<Re+JD4nTC{U8t<kF`yUvy8S+HJ&*$%!W$iw-TJ3CG8Uj)r z$IIms7#&&Ic3szf-)C8`jyiTPn3_qu7uX^RozG`r#IGC&Ti?I1yFGi}s;}{UUBJ}W z9eeVTL<xZBZHRYWH_uzf_o%Kt(Y76#w{6%{fDR}L(S|`lJPuB$HDKG#aWT@yJ25SU zz5L8@3P2P^#0S35A4~96btJhThXIZ@UR@L?dC8GTl7x6XpYi-r5BG!Ct{`~pcer-b zv}_bHUSwHDe3~YVr%VgVvUFA@0;WZPF_z2a(siAD1<&$4C%!0(Z=(bs)!*bP*v4zn znRqWa%95U;8}UL2%Ziygj6(Al%k+3W;To7yUNrnAVru9(X;oFk9}b5w44=oC#`eqD zpU$HXFAXALE=sQZ=rft@@J6&H9s|Uu+qO51UjDgSEN2cwaJRQC6s4M`As#QH+ag(2 dz2o${E)4;;BmlsOhyR!T{GqV`fDluf;J+)g&ISMg literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/flag_renewable.bmp b/krb5-1-6/src/windows/identity/ui/images/flag_renewable.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3a9dc386f2892cb8eb1d00d4f93c39a2ae953cc6 GIT binary patch literal 1334 zcmeH^u}d3q6vw|7C2cI_2AdQmt+f?e^TR;UtJrcqLu(-+L{B(DVv#5ZJuodQ88T$J zA%nvWH{6gRLxv1D+;BsN8*aGah731k$dDm}!wnfSWXRx<_E+s7*gwGszu$Y02k*Vl z_ocGz3~r2_2Hw$#`S+&q__i>0>+b%m$|}T`2-CJuDwSaMEhN<>N{tfw{XTSE$7W*_ zrf;Hbm(d&b(DGWS89K`CG9;-0K@*@fst^nTqtOVC<DlJd<NEp<s(OiF5J2-ZG@DIW zt_9BI;Q1aDPeHL*M4?_ls>-406=B;p>h(GlTY>7UP)(Kg9K#>_7!HT%bUOInDnL;x zV09LXp}_N8$g%{nCc-jJY@6FiUMArNE;yA#tyZJESD>3Z-B&`vC}23Iz4{$YCKKqI zhF}=Lc5G-}4VtB)*Xu!cWUvYg%dt?V+O)1(C^yRpf&ewD3ukb!+cwprhN@5bbpdKq zg=mOyT^Ih9Pc@iO4O9#U0~m&Zl$C<-w{dn>gjAQ1zD&cR%*{pvRi_HAL+6_s#^W)% zgDzzrq1)|3wq;Zm1r@VGc|C}A%4%6iTWN3_hYIDBDcfi~x;gIzzwe&;A%0NczY36h z_K9K6lSwAYoHGn9E*7MV3;s=his$*~i-e@5r@sVV$e-|;48KLli@9&H*#1c@vmc8^ zmI>L4XU}r8`(NVgx%CeVge=d$3{7)9ADx}w4y_Tgn@BtfM`<44IX<R!n(u`rnnx0e z#79EJN2jOZIZ1jS{`z`jmypBf3rFmH<nzwV(ZbtPLVoN5OKW=@KbL@KhlGT(;aub( jmkUL5uMV<=#G`zQU&-fJ_!T;Xkmz6IGSl2maF6y6xZV)6 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/help-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/help-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..582bbb0d877a619a830f8696b8c057c04744653f GIT binary patch literal 822 zcmZ8fA&jFy6y;b?PHiqLDpp-iRII3|s93RLldC{hR3H#55ET^&L<M5R3IqayKp+qZ z1OkB|7X$)<pa}v|fj}S-h!Nx-OxwNO%b(`G_g`li_^-cL58R9uet%+pzpiiGkJ;zY z|0A%)433j!NtUjqC`#b_m&;|m0o=B&djRC1D6Cx98HT>@$IoKi1XFFJ(XPgB7~8fb zgs_;VswmI%u%%s6-lR*9YT2~}n=Txhw-j3$hJhr}b<;HazMsOzprsVJJq|Xf+h7o^ zA#Z4hQ*<5wDvF|N2j1vN)(<l_UJt1yUvlYm=tN<N>vUbK#_hsva0<i5ZF$nbWU_2} z$h7Y2x{Bi%`L$ik!3BgBB!8-o;g_>8Y9`YpX_{tj76-osVSwb->_3OeEK709iX@^r z5msSVxk;H6R|)e;i&Z}dK_2%#I<fHKrdbXS?2T}x`F1$901#es!z2eFvn-3^MA&`4 zYj!$=7YXV`v7pd;l8p6X;>hEOvMlkUh~@IH%39VP&zE&;DV^XD%Xt)!&pXWzf+&ir zs$v(!Q@O6I8|LF?$G?crZ~I?cnQ;)?anQxK2zNK&IDBY8Ico1a2_^17RP6-EvMhvI p5MOPYfEk#^AP7$X0AmIR^LC5S^Z9(AmOH8I8t(zIyTb^=e*s`uBF_K- literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/help.bmp b/krb5-1-6/src/windows/identity/ui/images/help.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c7a8a930c47c0741da3b3a968ff26f88d1d9e636 GIT binary patch literal 2430 zcmcgtEsUc;810R_6BR2imt1bes>_OsiWL<V6`RW@x1yqA1)>5`fj}TC5ET^&L<ItY zKvW<Q2t);<xgaVK6}<$3Kp+qZ1fqi6W2a^5ESuaVclYJZbmo2E_vW|E=)3&B^K5sh zzoL9W`Hb?e^9gmQ^9}wVU0R+AR6qZX{TE&CZR2@<xm-}Z9mUm)znCx2PZ`W5$@l$T zlp0|v2PfE3xesH<aRfnN;?bqjFS>#-YeJGl&+{PHvr3}3;L$DpxNu#!nT0m13!xgS zsve?v=#)e|0@v$O@Jo4Ds{5*jV%Mm60NpSQWf==QrL(&5Q7jjWB+GkNm4<xda4cV0 zRzUG2&3VTpiR*M$w?39AihApUXa#EIQwy`B7oSj*V7hu0i7{{tRDso16$QY4$$mjr z`L$7``AHN%lmriKqVs6SBifY2z`CwOfz{PkD<F!~u9gustCEWs$lDww1>+LD%Eh_) ze!qtTtBcWab@U)3N-|uhMV>b?_bQ&k4KG|c49cSc5mwhU&E0PIWG7@9Yr8bRw7Hjp zr*IG1r89r9sx0u>MpoCdti$0jFe0)DoqdvJX%mtggQs}Qix|v|)x{>@CJwYck%Kfz z7)VYCp27~|Rxe_L;FT_xP|bI>BhuCl!uZleYY(2n^4q<LY0<^M76&@kwnT8XO@O)o zzTK;*td@Pi#l~ooxh4GiQFSo}W45<5Tm&(6)$PtKWNrMQMHixg<N4%C1JFQFZ41+- ze0QodE>W*seQAy0mVKbpz^otU1{p8=g0^iKx*#d0idlOM+wD#i@T;{0U5K#vf$k<8 zw&Q*r&&j=bFRGi3OEH)!U?@b@prmQpH&608azhnZ-TM477gaYt45wtk-A+W^Fm2m5 z*VY{;p*s<m=)&g8ipJbL3h)L&KowZs`bxr$yS!9aSA#LRy$6O9o|j~KsZemj{CYH@ zuKt+Ubpv;)PG@zqhNWqW>#VA)(U>FGy;fZHhTKflGz~}6NX=MX<}Z&fmWH&&VljE* z2BU|Y+djqUVa!c=MNtgHz@9RRtS<U5pW8+Yr;JY$UMBhcpx|SO{e@y9>f9`f7F|%U TUYtK8s3_`}_qeA1N~7}&3xJzp literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-delete-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/id-delete-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..68850ab8797e9a8e37eccc9fec3d8f92917612f6 GIT binary patch literal 1014 zcmb_ayJ`YK6g8wz@(C&P1?dDyqlk-@q88#tQP;PKTKHHWprEEmFoI~It%V?1Sc#$_ zDq4sj{z%%Bof|f!SYw1-I5Tq@&bepqohR<&T1D|Ftq&6JB-~24Qr%1ISIlozDh4?Y zhXeit@pv3wuK<t7^9_f?LFaHdjQM<y&1Q457SBJ!<#K^>EEWqi8V&S%J=AJ7bUGaZ zfdFB<-70ECA`#?rIi%BRM59q?wOY!}W;2XNBMOBAg25nGtCb=@n-$S+x6x=cP_0&x zNF+!jpU)H5=ksB?Tq<%||0<OVMxzl1g8{nTE<{m;)oLX!^X2#Z(eL+9@?T%yu-omZ z#&9?U^UXYS97la%daOUQ*-TM`^`%~a$MJZ?WHLdqSR}5=WTIRU1nSLivtF;)sMTKJ zbUI<P*^o>ou~;mq-hRJVtou`sdE<E=p->2RyB!9D0n_R9EKk-bm&@pMI%qbV<lpUf z(;Vdcb9<>&0(--FJSLq~Dn)<h98bPy^I?3JvvVvKL$BBSvwy~GwOaHSGMS7tkNQPi I*~caOClXBQf&c&j literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-delete-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/id-delete-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..11aedd577570da0ec2024610d86ea48b80249fd0 GIT binary patch literal 3186 zcmd^>S4&(`5Xa4X$QKB~zy=W?#D}%uT6R}m%UaeF6?H9WbXQ%wqHFIF3$cM6v0_2R z0%Ad9Ls7wk^$Ykh{<$;Z$|?k0*N}%?m|G5<^E)$V=08^%l=t3>FDKz{E7&K&J_`2E z>a%eFeeHd)vLX|&o0}W_k7h7rAvrn4EHfHQIab%#*RP71RO$qOe}DM-`9Y;p!OP1V za=HA`9335DV`BqPPtV6OnamC6=jR9v3`AL3nb}-7H+N{YTDI8OSVTodAuKEmK|w)~ z$z*VLc1BuS8f<NCh5dNJ+uK_hcY|83MqXYX&#SDgG>a>jD`7AgkeQi@^z?M3rluk( zDG3n~5wNqfLv?jEYHDhr*X!9|ih)G(g?Thi=I-u}&CSghb5$x|l$V!tj7myMP*_-q z?CfmlbUOBv{1(@yJy}~@BR@a?aV#=25^Zg5FXmCrsMUdJX=!0=YHC7VT^;YCsHlkj z_weultt)a(pA?IZjt;YU#MEd)F)%QI{{DXS^z`r=&CSisAiuM+vf%3KikO&~CtQt2 zgZB1zvw6h)`ZW@>v$L3)nZe}bB!-8FnN9H`pL23@U~g}a;^N{bOo~5oFD@?3=4!R^ z*x1;>+S(dcR#q@KH;1vYG4%HKqQ1T!QmOO_k8(+jFYPBdIM{5iPN&EI{yvV5j<CDC z%k262d5$&J3B^}rP>o6?5`=_=JdWk&=JGey>q|9tb#+y!gLK^9-s0@+jQKP+Jv|Ly zUtg{fVk#601Ox=Y$;la|rKMcQG;TB+;p5|j<KyEOGih(%zc*oMXbAWB_c%R0#n#pq z78VxxY?VqSTwGk3p-?E%*Vo5uH#Ro1f20$KhlghI#CQ<*+qYEw{JDdjogFMKEn#$Y z6rG)&NK8x=>fQrCemu?7uC6W|92~rgCvx}p_5>}^3;O26x$5BHAjH>C(5DQXoSay+ zw#az?q#Pm*AWaPq59jlv+NAf_)Wq}kpMO)mkfxIcPz_K`BqSuT-qSec?DIL6erIH4 zpsK2hHIVY7qN0LzJS8QC^`7c<YHI3DxuKz<tOcY8gM)*dJERE(1qDJsPv+hg9Uc9q zOzIyL-}Uu%&e`$taddZgqqeq|`waC~svAq=X*!?I?(*`IbA|GsbZ}&31g)*DtbJl% zH=SeYdqYD5>-@vR1Fo*Fu)V#_T0}KSXG=P?yuAFTe$t-lA7pWH5qEcYti9B4D85uH qq<5D3^{4sNx8vjE5f>N7Eb3Pi6BB=pXSxs4fY<&@ny&M&-hTnh2Waa6 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-delete-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/id-delete-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3447d57a1e559b16e2319b71205f08cf86f98425 GIT binary patch literal 1014 zcmb`FT}YE*6vtod(nzTg46JUVl>`zw5`v(+2*W-GUgS+hS`q}U56pr&nMJy$bJG`e zO|;c0lu^)IO>Og?WHPr&+bp6K2`dVND2Oh8J?|S4$QBDa@IO2Up5Om@&f)B?{I*=u z!zi*rs8FatC{NlT@~===N|L7Ekxr-iA3E98hN<y72QU87zB4wxuDQ_6<YW|8eVX;H z1DD#V@Wv_k#MmN7DLCX|+3FkQ*WO}loeiVWOIcYjkw|8bqb=Rk1YS@*G{athk~I}B zB<VYOg^$Qz+bYgbS~|e+a46#+%nlEh@Ei@Jv(ziEFx?d%Mz`R8=&ZruBNz;4WVQKO zT^?>e|3FXd9aqNZIp&YDYLi!IHIL%rQDk{AEAQx%iOhZC@#{tUrr)!1M~BX?Snp%q zX0tedrKsp0fq;_HBauj8Z+9~F_A^5>A34<%revFoU3FGMV`EfRIfXh&rBWGrt%rC# zj@{|TRDYJrS~I7c+nAVmrr%E{lYeD3KCDLAfBq_aeAATo#@K$s!o%Q5*7ug~oyE~b zOJttQp;?aHf630i1jnt8ocShuCnIkb85I3%KH4rEZoHN=|3FcAqK*??_<}sOK((yU e@4u5Xuk|zFyN#`*n{%yh+@Ah_VwcV%m-;8)z3}1y literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-delete.bmp b/krb5-1-6/src/windows/identity/ui/images/id-delete.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5b1b680300e248f255dbb16f991fd7367d2e6a73 GIT binary patch literal 3186 zcmd^=YfM{Z7{?Dd7Ga|hmlzNi(M^Lg7?6e$gO?e$5i+17vXyHu(2fomV;ckFK*`J` zFeNZ3mr`Vam5C_W!9<6n$faCbC@}5}xnE?{T|TH^{=VmoHsf0x>lb~K|2ZemIeC8P zdCqzM?|Xq~cT&vqCPx>d-9%1A7L+qNK3N?silU`oV`F3ZKPoyd5rGjxlO#+?{ztuX z<M6S&pcgL^y^!C7=kwICztRo6P1#;-gq3>~SlR7{*uG#s!{l(z;>3ybCiA^Q1n?{$ zfJeC&?qyoMUZTOCqCVyw>@yl+=@1Kw8ppO*1qQBbFb_dN$*{80z}osY!oyQd;`)Tf z;E-Y%eqRjZV9gMGt90<L7=)X&2iqNk2=7lK5X}>A4B@I^=X99x1~%h>om~bLidv(& zZ*yZ2_U$;hM4|O#;M9%6|H~1)Q#}M{ejc8&Ei~k&s3lnL3IS!IHN<Rf>v8JTC8K%t z%=kr!kk~SVgzu*zxj7BtjY)(zj5BPy{#OJAgj-->JgJ$k8(^{O5Fc+Ek7fo$$06(I zIegSUhl_2$Af@##!xtzg@jj{huwn!+3-V#Pqi74)#-<SxNv28l>3xC2I|*t3G79^a zk=L_?PdXQnLD*-0m|<!Txjuqjo+8rE(Jf4hT7j1r5B>f9CUd!b5xyGz6}5NPQ8l!N z63q&(s27o`nnU8v2{^IEpe)Cq;_05cUdR6Z(dg~%HHjOal#B-L41T=(8*WV9W7uT_ zE6C}Z$DRXXSXfRN7~6JM!Nw~JHapS`F^bxNt7|0GYPHea&dyFm#)zR^d4!II2WXzY z55>qj3Q50x!!N<gx`oNVomC0vsL$YXBow*1QaCtdZF2vDv$GJlZnYZCq`#}IT#n4k zIT%`d4AtE4_-1?qGE!@H*8<p~S$Nj|4BSQeaO0<;u&kWPU0PZLN5>BdPlD#=7L$1T zf2mw9M>tQ2x~?I7H+c^ggR98xUO?(kv+&Q7<3J!6#WMMp+!YlHD3#4yV)}f>p0!#n z&ZS(y!6N~9!;=jc4>o)c1>kf_I_P`G<}u|tl}ZJlqsOr~wGw*^y5N}Iis!_i;;mpV zG#ZWBnQd)tV3YnGt<fN$c7*X>wtRr`dse0r`}~5T)9K90O(OjhRJY?a@xhbLQ;2Mw zK;ZQ|c=MVLuNC*hUUC)EQkhwq0mma5FQEP4<BoY;Xq|<qX$rx_^L;7@@lt^r{t>Ze zWd=nEP)GcT_N32stHcKvk$!s?LgKshKI1Oa!sl3&S(#z{81yVXMEBxDw9MQ`_3#>U z$gCt0-=)3YyQ~Ksp4hBRX>kdP<kv9&;1BdIKSIOA2IKo_WIiLv-sZtgfU>E{tW0{Q z&Ye#|vAhz4tB;{1zCiCcX|2<EH|_(ZXI(ZsPd~?{G8uTHIE0B4a7-WpCn^SYU)TR@ KJU#cnaQ+)%qlK>k literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/id-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ee55b0f20786dd29a2ff11db0c6615bd4f984067 GIT binary patch literal 822 zcmb7?A#TJl5JlZAud1M;;Hn4M0~AK;HFAs`qF`YUU{Fx7pkPsDU=U#7l?)6F3=9Gc z3=FLP*iBVM*^TyVY>k{ZlbO-HyzX}-YmfU0=i&F<k;nW_@csL~obo`(`F7QH{k)~7 zX{xF!xx21QP)sp+&Dn|4(+9<Ur1W#P_rn`P3g7qr#6vNJ(Mrw*W3YiSJ{tm2!jjJ+ zRx80LxEMm<u&?7fpJMb*4MV{|YAL)mc)ZMya^{T`Xlm*$rFA|=XLPQITO~6*bq1~S z(T^x*U>v`IUov0hk<J;xId~;R3Zal!cq3&Q3);kZH~5sCR@3}BLl+p;CJ!cz&O5tE bj=<G^|0i7de|+1vSc&Vxj$tit-{tcUcV1I{ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/id-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3c04aa2fa9ce7d3d71eb6a12dcf43521dc09f2e7 GIT binary patch literal 3186 zcmd^=SxZ|{6ou`3=^rSCKK4m`2q_qiNlarj2_z0t(8M8W%wVF418P*9H8^0MaK>32 zP;mfJL5)!n6hv|S1OANFyHB|yEfmVV?MpB0+>nQSXYIZAIx0ipZ4`T?+~+5*K5+G( zt2a>}xz8U@<Xu!07607d-{XHQuh$2g&HhJKT^$tED~Uvk<m6;%wOVL28YCvFp-?D( zTQXUkAZA=#JS-LqtL*G-WM*a}H8m9mgMpnvtybgbijS8IVk#6Wc)eZ}6&1nlcEjOt zAU{7J#7|30LrO}@FHAb85FctZNvN%@MNLf&s;a6`US5vk;$k?RPUPj~G2Nv3wN{}_ zolcL=&Q4aLPzcS<&Fl;n6%|as&1OSZRu=Sn{R>wp(`YndY-|jpqoWua8bWVxFFHCp z(Ae0>bo+ch6ciM|Y&O62Stv6j!;F=c6)Z0=V_{(dlarH--QC^IG*?zuvRUWm=E7t$ zF|9&9WU*MWzrT;&-Cb;NZ)0_J6|=Lm7#<!5aT^*MP*zsPyhS}GPbDR31$oHnbm8RW z1n1}HI6gjR?6tKu%*@PSaBvVb<6tnzv|6oJrqk~a2x9K+?7-!6<Kf`}S65ezPrp&G z$H&K+*82K-`2Bu1SE=+f&d$yRF=@}*+e4U`n84H16D}_=ad2>e_4Rd3O-(URH8nM{ z{wkF!jEsy3=JC5t+^=69I64X=91df1bCdPAzrP=)rKKR>^z?iajmL8%kqDOsE^cOD z5FH(jn3x#m7q{Dki;D}<dBi0T$>nn96F&E1V`EtcUSD5}&ZK>j$z-4mC@Cr7eB}b| zB;`H*o{*3rI@9Cvfc!~0*w)sDy1F_90s+|VcBH4LLn4u2adA;pE@cd50Tt~?Utb?u zT3VQ2DRXr?9m`#Q_F}y0-lYES?d>to&dtqXU|;~WCv?xy-KJ8hMAb>NyScdmdFAx< zl;z;`^fbD<x<HxB-|J%N<Nu?zwUuSh^Yb%qZ*OsUc!;H?CD4A-Y?VqSwzjrJ)k*Ba z!a{6pY~b<nk?jrLH`HI+8_Hb%d}6;T(<#eya&j2UXf$Gee*UlVUZ0=ldUtpCPgt+H HVtxM(Di)S+ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-new-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/id-new-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d2a151c373c1a8ca7de594afd7d0d5548a26598f GIT binary patch literal 1014 zcmb`FJ8QyF7=|s~+x~=({RMT^;Am1&3r=E+w;*0nbP%<IcsD|WQBV<e5Oh!k5f>-x zqzJnBPrAO%IVDpqap(u{NlwV~p7UK8_Ul$h<5^js6g?=qS9GI$RMwyPywmB3)Ht8d z_z%V7arpfLd_LbVg~MUZGkE?DZnqmQmkSPu17@=sCX<PZWm!!=5{V$2%_5abAsUTR zFRRr`d5+^W`Ap^=-EJ4nW)szF70F~0UauDxiv=9_qRCe(6|7b(%;$3q1_Owqh(sbm z&$ruOHTjPZ38&Ku)9Dn8#e&`?m&?ImFdz^JQ2uy4V!2#i^g0|4Xf$Mu$72M8LA2X# zlu9M&^?Gc#TTCVsT9^HPe~~9Mu-olWtBG(ros=W}sMqTt{VSKte{$;lY&IM4JdaQ) z1e?u<*=z<9`FviJB_73M5&eE2k|e=sG(r#rv|26dIUEi(Jqm>aMxzlt9uH($ruAnS zhH_-Dl>@1Luh*mhllNFGM(0S)Z@pgA`>6X%&rYWUG7IT+TIomQ>fA4RUGwc5-XZ3z literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-new-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/id-new-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..61c2fd21abf89d775c0bdca75429c043ff708aa5 GIT binary patch literal 3186 zcmd^BSubN@7&iBlxpE<yOyWw!g&4$$DpgfWks`KGTP-b$3Sy5fb|UsYwjlNpf`~AP zNF)+skKgi4-*<AFL5<}kb2BG-d)n`u?|Z)IeV_OFDi6v3Y{i$G>C@g6-%Rn<6rZeY zO`pH7!!K4=6vB0VeU1My42B$NwW;rl($X?fxpH-NLttPa0s;b{R4U=?tAI=<`)f!f zo}w^4J*CiSG#qhpafptNMtFEQLPA1#4+@0>PeUs85``&~$zd=Uke!{4%*;%rr>7%1 zIT?f>5fOo)prB`%v`;ZQR4V;ZQBi^N@^X}vl%TM%5V^Uz(CKtYN=jnh#Q9IIVlh>! zV6?Wjax^tHp{}lu_fS++#Qe2dEn;F~5F8wA#ubaHR)=ADco;)NL+J1CM`vdzT3T9A zQ&Ypdb8>Q!l9Ga`s3>!u#bQQAMqy!L0rT_on3<Wu*w`3jx3{-5=i=gGuC-dNhFmUZ zu3|N$(IjAJX9wHc+gM*;$I{XgrlzJaFfahZt*)*{K|uj)*u%qvx%&GDh|-Wwr^nIJ z5l&7{aBy(I*vreyn4FwMZ*MQC#${z?jOFF!#XOD1{AZZw=jYGHUefmF<|g#|Ox)bu zpt-r3>$bSK$hjUF8DXwfRaM-tgz4t?1INe5=Jn6c&XAg#%C&z9!_s(TV-rS4M{##| zhrYf(I5;?fbUQvi&YG&Ntwm^PD4d+WV{mZLj5jec0cU4tuD_*qUmGLbw6t{W@Biew z`uX|sdU<(yFdB_;baaG^iwonet*s$8HWofUJ~%u)H1FXx3`@^xKGj#D@M8>ndwW=0 zTeJ64uTUS8FWK7KvUgZo<Go{~AwegC?@^v<FT!<ye~*NO1X0|CeNn$iBodGZP(Jl~ zJrWZWLH)71x+*|oYio=9N0=w(o|Tma(kJDwp`ihlm6h!Cc6N3k4Q*^}nDIzAySuxh zxrT*>u@{gZP>)dlY;0`U3sfo<YngO3H#f&#NZ+Za#PFnZlk&T=vch_#^P4ymM>=OH z@5E2QARnQ#hVmhdz4uPFBfoWbcSl!O7xxSGUt3!n$aAGqDZIVCAFY3Nb;Z6&y?c6k z`smqP@ayaASsM=z54gO%#NOT>=druHo4HUfiLa%#W@l$PHy0Nd7N1+1BaCHaWUxkW zZ*SRq>AdOb>EZtiRBzIj@b1$)?epo_TYr<MlYZjk;~9(2u<7Y(baZsEAHQ{-kGx0c S1l3EJOZECl&4l^?`u+=Yr(8Aw literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-new-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/id-new-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9fb17b98c31a33b7339b15bcc5f97f5c02d1090d GIT binary patch literal 1014 zcmb`FUr1A77>5_#XZPI*5kwK8QDI0I-9&_thGC$Th!G7ETi7UfF^yJowzj!{2V|+0 zWT7E}o`@KzrwIS-oS~hjD?Dtm3L@9A+o!X|M94Z2z3{x>_gy@{mk-`!H9xjmign27 zyA8G*lo@QXlpFn5O>eVU3Y1FIH2w#dy4=)v-sSX--)XYnG@ViB@KM#Ta4;HYk2uE; z-y6z=*F`GY+@^kuD?-y)l7^@6I61s%WU1^7&J_L1cCV>_)f>e*sdGKHf>la!W>lkk zK&3n|!vUM$)b9>PdARU}zW66@ze;oY`Fm=gyk%GWGSwYEQ{NjFk@c_izg%S?@fqio zPV=)R_BLl|bO=R1k<gH&<xR6xRmJ1$<=$A1^R_(QFFtZ{JjK4F3RAMo$jArm_AIlr z$xZ#j4k(I(r#Hl@)=ny`7C6_MLJ-!l*>bqunLm1^{h6GWsl9fG6GI91yB2vox<;V{ zA!q6qGMwHpE;)@|(m7m{<Ls4H{K0Qnt=}0O)J-$GJOTP9ax}K(ag1lEA5L=Qc)aLE zB04=i>Az-7ND_gt%3L;&IG?3KlxVpyzwX3hONipi`n&Y+jpu`*N8Iv9=nz7LqW4W_ JZgl_U{u4v&2L}KE literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-new.bmp b/krb5-1-6/src/windows/identity/ui/images/id-new.bmp new file mode 100644 index 0000000000000000000000000000000000000000..54830c1830327fe089be0aa95f594f863fe5af35 GIT binary patch literal 3186 zcmd^=e^8Tk9LMSZuDZPABIVNL5{8)k5Lag)Wr3Uw5-?!E*k}qDKLn(tfFp}U^3oJ1 z!ccQ&;2?)aR!9NDz{bXp0b{t0O@7G)I$(ln_3ryT-gcf^$9nj$@7?G5-aWT{U(fsV z<NbX-B=boJdij#4D+y;3%Sk-pu#!CQua>7A9H_7^jYfn2W5g$=B7`fjD+DPSjB@1> zmH_7?zhVW6=fAuL$3yLS=3pD1{+C!An!t$ZwVe-7aVOS`RajT1f?KH)tB)z@Z&>!l z<Js<^JVs1*WFp=?r^c4A)d)D-gH30;;d`=+=DUa#a3b0t*36XY7xgZpFAN}xL}ZNy zVbXpCebWnnNe?!h?4)&5d4G`0;xN;>g)2nrk9ws1phNOy9R%MEB1Seqvnl=TQ(a)4 zP-6K5T&B$6_#}LM)r5j(6LK4k$ZjyueEy|DL=fF?o$JL$!gVd}z;lQ1=b6Q@hr)Qf zAnF)HiDC?gu8m@U>oD>Nd-qRzT61`{25*pByBGGsIY&+R^je0wjY<&WeE%&}_L*^} zX9A_laU5(PL4K17>4eL>s0HVIA6S_>tco|niD>nUh-cKd@1<uzrqZL{@Ea}-PSNbL z&T)L+HjEE{G14`D=UWZdWf-s~W)v$vse>Rj^ATou_u@UZwY3$oi94YhpTmCf960f} zA#S^c5|ZzIS8vccj;qzeD`N<(@CmpEMnW!^+n6fV0C+qzva-f(?-t|d<>CtDe^!j1 z2@8(Z%)-rc9?1u$Q6wLxdrCn1$$Pg6YuH^VDHGeymPm~7^qhrAWU{?m4A1%-aYY4U zcmhb}J*ZSo!9Uajk5?_=9v(rss2=VcYT@lYNuOO;r$cP)H2nN#(A=#3PdqDErBWd) z`+Woi27~44gH<o(<Jn~vYz{CZGIAbAkKRR4&}}$7FCZ<=jQ;+`*U-v%cyDTI0(;vI zxO{LLE=S~WDr$hEe+#Z$`2*HvF#Lt+=xIjUtlY-NM)-t8VcS_Hf-8Gz@AawZ#7h1U zs-*X<NHjG3iM+g<OTtXg&H-Q2j5OkdyS~4USkkNhMLM{?ynua0zvIHiyF~9j6cpSc zeY1f2`s<9j!8>AUFQEM3)0P_u*<*&|3-j=eGlP{gh!;1`faNg+snh_Wa1tIKbEv8^ zFyeB!d`O8Ooob)ND}fgHN6aF#&IoEwsC&khI|6s#%Qi+^n-*KQP9rzhzPYs4lG>va z5>Z||2QT&l4oGGoQBR<lcoF4)l-Iin^zeO6W@B3ao0m5V4rdAqh5a)lI$nyboH}Sm z??5p&2bp$~_Wiv-4}nYWw$+=yLP~1iBTR}dlj#u{I0d!Z{@Kaela1pQr_puOLVGWD z-|TJBVRO<)*dA4l!otzVGAS;TSv^r+4xTUx(K}P{Ha{6*afy&t*ARa*qPTeEADPx% UFXgUO4xppM{+cc2H`sI5-<tTzOaK4? literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-refresh-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/id-refresh-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7d79343691bf8d24897c7d2c6ed7001bfb8728fa GIT binary patch literal 3186 zcmd^B*Gt@K6m{R1#TQ9nSrkhwh;<Z=eVnzf#uf|eNMegUHZ(RATQm{GhBdLoSRxWk z43;3tssV|?nyA5d|BSP9ZkRz_%_s@`vOoCdH(!~1zI)HP_l`2G=vM=ITs5Con(>Eb z{H__l7?@~2zddWe85nSApM!$~{2xbNUOrM&)6N~?;o<Q0_5IggMMdQg#Y&-YMR0I1 zf`Wn&5D)-=f0f`6%f!S4Mn*<(a&pqGaoxki6KiX0n3|fxhYugFjPL2`h2-R98HtIB zh>MFuR8$ng!oqO<`gP>w<jC98(-VGvelRsPmAQk11Kix)U}t9sYin!d<>g^>bMsR8 zzP?I1pPQSD?Cfl0WMtsZojc+;ZB|rNATu*l{JnPVn%srwxR#cdCTDqP-si@R8<?A$ z(~BDr5QysPYE)HK;lYCkC@n2TK|z7UlXtJLuSacdt=y%gqy)vq#li*eqf)7G_wHRC zenLV5EG#VW`t|GY;)aI)g~yK{%V=q7K|@1>+`-)39PRDxXlrXjYilc-o14Y9p`jrx zEiLi(?OXKq^}*56QMlm!=)YR62IIcBw|60KL_{P82L~}QFo53PUUYPHh@XLhf#~n= zM^8@=Iy*ac__nsT8V>Ds_Gp`&=I7^waiAv5%*-$|Gow3mwjSKR9V`1UUcA7>!~}+i zhb4B6jg1%^8<Y9a(2x$FF(I!@OG`SN)US(+3%tF(<+m#<D_B@q(CweaOioryoM>Zy zejc;4v#__f$IF*5!FxP<^hmg5j*u&3V`ErZS>gHf=VEhbXGhMFTX%PNi7T~D?VrWc z&hOpJ!ut9;Ha0e}y1FW{q#w*lV%yl*AR;0{a*15g7nSNy+`4rOuCA^!SUb|w(?x6K zpYx|rpI(T`7-VH-<M8kh+uPgX=aVN-M4#j-K0aRbSy)&o8dWG<#20FuzMhUhHAViZ ztNs1`3o+^M!-p*(&eyMB@$utF@rC)vTEjYX^X5&-Lq9*I@XEN*?z3mlL<{6oi%;!G zM@N4bPa9+6rl)7%{rkT~@6_t<?k={rw(#c78>v5Pb&BvnO?r8GAvQKv_FlbuCH!-p zx}^@acJ;mK7x`5x{iW7UPEO+J=m=lFe8HzrpCoU|E$z}r@=r}OR~Hu-1z(|1;PdCt zm&T-xZyHgFMp(;gYH9@c`1n|dPyczAI&yY)mKw%6xux&=eADjpt{xs9lH2$1-`D6W zOSDS;vnH|cl$V#ItgKA>kB^TJ7zf56BqT(1N)3#Rj9eO%{eyLtInO#r|B8x=q>jhL z#7N%M)zwK%$+7mXd^7IsJJi)x;u;wlDfY+{IiiMGi&)Q6Q&SNd8Y+2n8te3T#)+{x zy{7Lw`zC+4yu1wRaD03m-QC^NSJ-E$8>LctC7b#%Q&Li-7f>I}N!G#9(NXCu<Wbw# z_1U?~ep6GE)XkHV6XE3DyLXtLo<>(!mvGCTtgkO#1y6gHx?`VbPEz~KamJT*rLywJ m{&#6H&U>?Vv6d$#B?%U5fVPL6cm8Ltkyqy4&$Rhp+WH5N!v&ZC literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-refresh-sm-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/id-refresh-sm-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c9d9addf15b1640dd3654fcfea5fe4342a43c086 GIT binary patch literal 1014 zcmcIixr^Fi5H+OF=1)kOb_G+|X>G7jR1m!ISW#3E6>m{c(M_>p1o6PaO7H>&u@J=7 zLczlGKS}%Yn+eLgn~)~?V7_bSy_q+R{OgbRB3@sF{j*>n1-ldMo#>OW|60!<L?W`w zI-k$@7ZwNv@bKV-!{K0)$z(8@Onmoxy?@PNHd|n|S{b9$=^&TOAr^}vl}aIzNTAhf z*_TSCa6BI0@cDc`kS`XC!C)}J@AvatqtU=<G+zH~HXG-8tvQiMqF%3~QmH_%*Q4ET zquFdC9*=V!i^T$VyB(oWi1~`e;!O>OLIIP>1jFGF9*+m(@tFBY`~AHbtJMno{T?cn zifhT`ayR&=rxJF%9R`B|`;|&1)M_>7QYaJ%27}B?`bwn|5{bkOe!JbGT>g&J>BRNV z=W{rnPLTd?w~I(5g6VXM(P)HpI*r+Ec7vyWY&IJ_K7Ql8{eGYQ`FtMHXjI@XGj_RL zGS}<=(VKc?Hk-Ll(n<YlG#aQ@t4Jo32#3SWk;!D<<R(1zq}6J1JjD>+<#J)YUSH!a z77Oe6UH)t~%Nj@<@lf4vxBH4E%;9jjdB5c8^?Hn_Kf2Qlbvm6t#=pc~?zLJCGz&C0 L)U(U~|2lsHLf+7d literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-refresh-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/id-refresh-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..11d1893b4aaaf27f873feb2b411e9500fb8f9639 GIT binary patch literal 1014 zcmb`FT}TsP6owaF1Y!QQbZ$$BW|)OVrD*0~7NijALR`*elo{Ed)zqBJn28#iX_`8S zWm=;w6Di6dTZt}j)NKs4f>I)kC<=mZpSFqOun3_8?>XOr^StM~I6L<IS}Jfwlp}{Z z<n54`LrVlQN1llRPl3Rx*%%)m=YJ@_{0bS`tL!VC(dM)aQcvq#z3P0$KX=G4G!WBf zA<{5PxPBO4c><m(aja0cBTn8%{Qh|4xpFi*4K|x?f#2b(R#ZK2P;^g_)btF$6Ctdw zmLXJzBF>euPPv{n>a~QP3}bIj8e?N)ZXW7-1G@exG^R<S3XT)dAw}F4NI<m|QBpi+ zvl(T+5?N6Qvb<o_rG;+%rRxUn*uQXN^fO^+5)nQLK-ezAw<HMfI2k6B$+a^fGm#Wk zD(W(|8(-g|XK?BpT_f+=crcmZ1F=LL%_F+8k7z|EI}3LaQLqVVX%M0&DcNe38*jB* zscUFt<kJr#kL|{z&j(3K6v?M5=zi2gc;N<CKKFP1%fCiKXIG~i@4Nwv#X?<UGcj3v zS#I!Q**i}pwSmNFW05oj;nCxR*XvbmDc-t(b@KfKgQOQ<CdFt&R;t76TqwRbMfkOe ziPgrDTXqERZXt?`S%2hp^(|Blex&TxB!?cqW&15FIhsm_hKA<m)6S-2d|;gG=ihF5 zT@x=peCOfBSC^0T7P7T9ZnJi~-L0R`Kke=1<$#&t>7VFFrcvm7>9}|Quk-WS+4pVZ VT`I4&QdHYav!P>A?5xLP>Tik!xZMB% literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-refresh.bmp b/krb5-1-6/src/windows/identity/ui/images/id-refresh.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6357fde4f1defcbde2a77393af3c4b5ffb7c7298 GIT binary patch literal 3186 zcmd^=Yfw~W7{_fYQCSvtSzveBg<W=)1;x0vuA-K@UWO4N3kF36xriEgM=`BYGaS)! zbX4S~f)^~ZaJ&>S5^}$zf_KSlrj?bK4}JS}b{!2SFr56-^v?Xx?K$W9o##34`M+aB zmWcXThf&xX1gQnN3VNlFM%X?XRpLH<EP6UFT)4phQM2YI6A~5Mt;SD{#Ng}yw^(e_ z;(ygEpRgFz+Zs>_Qf{rsc}pD*n`^NbG$1q?8@W9LqSsr`E!Qj>5*kBIO$`MF1yod2 zyfEK?>TLXSTJg<kVQ5whUb~vn?P#>VgN?y}ez7P0^-4sG^AK;Wr2mAO*vcKz`g))n zp-1PZLu>G0`poH6R#x_kZwilN{J}QN2ih33|12Z(&tTkr8m~<yi2U5ptr>)Nsh-z0 zYWfcHL@`B!VUagp$%FBpKLqbY9|p(!;1R4trB{=`FaIC8qa)*)_Vq;~1%)5JKv>~< zCKa@!o3#X|Sqiip^?0NW#BG5FO^OcPszE5;RpCBdgWEWFba4Zp@eOf<QF*J`y?gg_ zx#p+@l8ZY?`t~aGzPU>5vCB*^x`@PAcz&ypcbf<9TRhNg)}c;y=T(^)m!bZYmX?y2 zmq*~pK(rw`JePS{>o?5vLgS^Op`oEiZt$$RtgXDknu;5&F27F7$?u6R5av;k8?JlY zQRN8A)S%v>wes!E3KRjRF8KmSy@}g=EdxI=po!NZ*UQPw%ItDaXHN)=PGo1(9kw^# zVN3lFY^c7)_(iLbER!KWq(X5(jWWLzKSM)5t%w5!2cP9ED=S0wh8kD18sl5TC@Cr7 z#EBEn;+=Vx<H(o<zBvCghtB;({@Hu%YW@*bkPou2<Tw>6aop~L{X$2?!7BRus<H9$ zMDDF4V^@YXXIonvMMXt~hKJ%G<d0{d5cgDI8r`)Qow@HXTuf0*2c_Tt#<45+$*Me0 zKbbAkVQQR>24sE)0uom<JpBlMS<NUvJWP<;%%t#1c$y5Tjc%x>sFBTaMzL0H?Y}%q z$%c&^daSd$x|$hrb7=YT5mmPyaIpRon~qeGxNR?vfgae-m*8d|NARI`hV40xVPZJO zaYpRtNpUH3?Y94FlN(J<O+7L#HD~AK@=;nkXYW1c)Q#UUh6UpgCr4Z(Mcg1m6d}j7 zIuoCmRJLd3(AwIH-Z&6xt}{+YlsJFo`i$?A?MlGdfamg__Bkgvm+8^56xN(2e*Gud zt(IYXUV^AiP_2Z1J|d<@g;QQ$PH}ND<HIK4V3y!mDo6H>@a>N&tbFMLC(_c>dd0M` zTUuIJnzEcR6N3?H#n@yFpnr$px0f8SJtx5~-2r)o5|?l}wtF0~ua#k!CqYu~jI_+f z%6A>DqOq~D*UVF=PGOoHfqunabXzL085P89$pZVLh<?|_fANL-Z5terML9EM<PaPa zoUDBNZ)NzI{d&!_^eiwWlF9p<t@Fj=y@9!{$df+h)c_CrPOwF?LWX#i6h(*<-Do`- z*-!qL(CARapGmP>=fJwOk9*Brn6i@D`zlx<_+a9RE6g}@iIC6FF(U5_gEE>B$8IEL zMXJ^Bnwy)u<ZW+n$9IAs(l?~k*VlK6J)JMz?Sms`u(|HGRqLy6vi#&V5{_RXRPcP$ z-qW~mt7B4Be2@9+>gtG?5z%A3JLZ(A*%S(XWbvduXYL9<c$<~qT_g7BW$QXKG`j`U zJ2PJ>XLp>=*QUk9QUAk3YHvTJxZ_v$wcR7V_7)3EI(Sc5<BVDLghkJJsmz@jyV#MN z$IS<S(0Jz&MVEfD`hIHJHKK&I%{MZMqsNcGRHmiorOQ&t$lc57yN@|~`M!0%Nj-U$ wx96^6<=Wo==bii4o8!#vY@!q9GHp&0@64V@*vvQzzdZcX>+8+C{MYXJ6P@PDq5uE@ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/id-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6edfb07d9514fc52ef00b7ce8bf79abbf1303028 GIT binary patch literal 822 zcmb7?p>Kmg6vkQh4@@qICr*&1qN3si0#Sh=*#x2zQHhwCKulIlR8&?@AdwY_$qEFb zk|q-s69`1bi4!L-`wl9aK)dzJ-OD@p@x8}`=`+8#T5-fD?1$67vmV>)*6DtC=;Ho% zoj-m(@4UfiNGe$$(qtZx9Wp|6iN>~#H6fcb2CUCln{+l}fPEtHoD4iM3H5lbgjCJp z6D1gVWEOb%yNqJr?ePk{7NRLOvBx<u@V5OP2HSKczRQdJ?rZM3=mGpk6dtQmi=$S0 zm_OF}YT-MM%h)=OV5_Axb@edc?6&dL<HS&+E_1Y}1o~8iJmy)XE0}|SdkN%Er91e7 zKlo)7wqvAZ7T^dT-^IkCezcI;;x!zPrVeGx#JuKTylUzy&x&l_nq$1if4F~?ysGng LBL9zW|Cjf_TVTQ7 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id.bmp b/krb5-1-6/src/windows/identity/ui/images/id.bmp new file mode 100644 index 0000000000000000000000000000000000000000..72a93c6a947c4446c95f08f3bd3277e74225822a GIT binary patch literal 3186 zcmd^=Yfw~W7{}>*V@}ODkvcWWG=%7&A?`G0S(wg_uxp7fF0dB_VFF1Fg)U51V~$xC zA-CN{6eSZi60x))S%n3HU3M36xr$umVrqH$(6?XjIkq!S(=^kZ)0cW@p7VY<XXbaF z|NDRb@5^!99uARLjCh8Nnk#CysE0zH63_dqX+}thRKXPp1o%HzN=7zuM(aN+Yt~jp zS}o9<nOpc1b3{GyMH{pBw=#2I3y=IwMe59on2TStu*lv?l-<L^au3gzx|w&NUH*s1 zKKpC-e4R-VQ<IR&%IYp+k9M)*h@WMLeZ*9FWqw$3JE5ZYKliMZx!kac#BX{rh)Osa zKwop2)n9e<VwImI6`gY5lI{<3BjT0y8EZ@<``i#&-w%@c-5}O8{cNo5mDy7NnuA^< z%G}I;fUA_LP03)_r4io0IKsP)SIKR-BJ(YE{j3vxzgpeRQo#)`?cnjx@9P|)&_jCD zW{Nu|C~BWzf7>-aZXV-3!G81nklgd@Cjz`8&iXk=Cr=A+NuG{WsI9@A#_`KPbFAk& zhyBx(x+mG!I!=LegdD*&o$e$4c#rI@`9kAR(d+VcDT;jiM$T4hJwyC(<rmHj+?3hn zos)dhGRE5%uF7Y;;Z#8O^<ptob3Uxcn!QaCv$?sMq||gglXqzvyUp3bTU2*nr%34i z!KG1I<K%Dq&>s8aTvsLFa=8>SrM$P<9Te=|i+}na&XHd^)q4Y*=yi{4O!kyj_({@t zfjN(&a=T()@Q$%N9BedMsd4!^-G7q`@06_X&L4+KC_B&6I0Gd%hibea*W>Z9J$DBy zR%wY?6is+kG|N_M*^--&^e*_Fn!D5KM6+f+VLK}cD|8XMr-4V)Kjj6T0k_+&I<v8{ zk!Ydcnj>!6FH-hKi<y-2envqZk+C{_KA)=G9HF13>LOc24sJd>K$7rk+}Axkf5^u( zB^}Jn{F34_o2pFh`Xo6Eq&)bjX_Ore!=%*@pc9#|sr2$>VJoYRn^a}S8!gm`Jd!f$ zpl?d#;5hjghLPq(x@Q*JJZRP?tIA9?r_y%q4lUz%I5%{Qs;+7FiY$`yPs;k3@;3CQ zbXA$fC8Zp29AfnLZ?sR`rMB;eocnoVK8@mTi!x+US6{CxQ<}N$Z{<?rsKh&Uk2;YH w(tVTHFvv?8?~uQ1x9Ys$oR`^bn9?#xOwVGiB@=yeDm5og{%gD-_rI|J4i5k2Jpcdz literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/id.ico b/krb5-1-6/src/windows/identity/ui/images/id.ico new file mode 100644 index 0000000000000000000000000000000000000000..aa15f05fd29d04bf0a23c94c7b63fa59dc369806 GIT binary patch literal 2862 zcmeHJUu;ul6h9pu9f-Dr>1O}jc6U&=>Bdr6SMRn$r_5OmYKePeD7=h5kj%&=zF2u6 zh=x6hZ%X<!_qdo5eOfRMvMfC5P!vK4*3rbNciUatwfE=wZf_lsxgqM4oaXz^_xsNG zJLlK)HTRatLhH!kaIm*hy@e=9#F!XYP=7g5AMX{hkNT}d6YGiU#Tgzx9)fqTiCD=J zV!>0wTqI18;EnO|ae|2R1akosptvET%Z9~DBR4Xp#{jW@Ccj6vQ$>H=NH$;_5<b&X zBk~~Qc-QcYWctdY$0?%@PljKvWUPSivIz^2u>AdxVBOuPihHs%<lYJ^D=VXs6Gtf? z4pMqzl(f`!YIZuQ%P&z>a+0oTbh0l-x;jgWEKyLB=|b`h%}!5}B1!b-z9{LlDGKn} zD93ZEM!9r~V$F@D>pFchc!;J)lN9e(D1G??$F5UvqfFh*)is^8o72n{yc~_4IYIHR zFrWL9y8V7S8}Fl_EYrluSyHb~(qM0tMotgXp|C=!$uY{Y)*x%$XXwn)X+x(<6Ra=H zIp2vzS+A2~tV?HINugzIgtYWc{%*XN(>X3;If`;Ug=?u-FBcp0aDLc<|3L@#u4&Z) zYrE|ko4vezbG<ms_(_jVvWGU;?lG{p%3ZT17z~v^;w;9icC9OGvA486+E~KdnriJE z9^1Iv#FcgaXSX+2R8^bUwRKZd^DbF7v9;B|$>EF0N(t|@?|I4^2}De+Se{t_^u{~z z;~foFB@!_C)ypRGuWtYDbJq7?|6;_O>On?Hm+`VG%r9Ya<_3~)9mY!@7hbKE5S83e z+-|hEUD)ArBH(eOP4<;)t;qjo^c;E{>d+&(@Vw+f2lHDwUx4vWNkXgFyCNS8c`T_J zWM_WFr^gQCMcIR}M?$Bl$vSp8YoOG6aAa@$ihQ9zuP&mXs<?e|6!G0bw6gAy*Ml~f z3&;2O;Hz^VLjC^In*8+C7kHyH#Cp95vHp_>Ucs+dCOQ8su#{h&|I5$#d?<nE{M*o8 zC*z|defa%{DdZP4WLY2b#vcihqhx>fU+ABi8b^Pm6Ct0B*TW&CE}chVZXQc>IppWE zK;f_X;{Lu)4xwkeA8p<`47}Wfg&S9(Gf!{}bD1^y9~|6|4!)xx_wCqgFCg>NHGpdu z7I>^uU!Tu`-=`Q(97U|D0bN@q48Q+23cqpBME(2ZXK&xax95j(@w1Pi-MYs2sqrZC nSNr~=FUHV~b`~eGz7v}vZv0*SH*x7+@7I^^?}7b4ea`#=(=`(R literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/ident.png b/krb5-1-6/src/windows/identity/ui/images/ident.png new file mode 100644 index 0000000000000000000000000000000000000000..904f0239bc7208ecdcbab6e99ad914ed84b24b28 GIT binary patch literal 423 zcmV;Y0a*TtP)<h;3K|Lk000e1NJLTq000mG000jN1^@s6?Q>5r00004b3#c}2nYxW zd<bNS0000PbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$RIY~r8RCt`F zlfO#>Q2@t3cZ!fhaD#`{5agmoSRgewL_<r9)DT29G)WK+4haqhIkbq9+SngZQ-Rno z@kpYj=^%(k^VT4O6JFDm;@K&F*T?6>=RJ6muIqv!CJzI52{cWkTrML-|4|(R!!QVi zLX--5Zf`1s3tTQ2;c%GD(IL|Th0|<?>cib&f>x^qKxBS~RD6T6kp{VwBwFp>Ss=^u zufW>ET!6$*1n*~+>~Wl@dabv>?RIwwtS!#^*<Tyw{V_*6mH1<v3aov7o19-Y@v2KC zV!QSNy8<Bu7Zshi55f9&8bwh$&N~F{j|lMm^2+6Pot4!n%h8~1S=SXz)1=X8k}sSw zITa*!khBGR78Hv`CdU12Ztdamc>aX}r1sBb7zUCg;q&<%LE8dVRr?05{Qw>@XRbF% RR73y(002ovPDHLkV1i0iuBiY3 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/import-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/import-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4257a1ad9ec59d426773ec0d2e6e8c81ea2e367f GIT binary patch literal 2430 zcmeH`F;2uV5JgSN4UiB@i*f+kNK`bGu5%Ndo3I6yFX24^Wu$G8auoAsCae(H*#v2+ z*0M*=Zv5u^&*bs><=W|ZAl|d?ShuVzcSCgUY5rdy=5RRAaOc4uE?hJA-+iE6hGB3` z`?tbY^%~dr!F8=~THpIk36{8TyB#z3L4<eSlb~Ol-~@O7v1i5*nb1+~HGyk<PI2J| zC%8F{NH)48NMn2*ErIwWv+Pfm%Ym4pL16*S8f61r5=0*Y=%VT}m!ffH4x2_mY;5ND zJZ~mNSL#{ia@pVGJ33F2V4Dx<<(hD<8PIMy0Er3Hm?yabK48=~AIt;}TLMG#C}_2! zrqt3@d}vy5S|3r(Ko{`{WzQ#5RJz19goq7aEusBu1tbc$Yl$^<SubLNqLFD$W^Rby zDVs&wWaZ{1S%sU-1Z`WbJH+E9C>m%|V){0{ybVayX^8;I{4tVz7n`}Y11o<o`>^ux N!fO|<nR7NDJ^}lAHRb>S literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/import-sm-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/import-sm-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b9398c3849040fc6db484cecdb33f3d7faf5178f GIT binary patch literal 774 zcmaKqF;2ul3`GZ!XrZJ_i*f+kNc5Cb=O~k#um#mzV)g(O6p_*(%~58b{lh4Lz;e9K z?Em(+C(kdpH^J?R_{ek5bH{TP9*7})T>H<rux%Uf%d*5dg=vh#80X00KL-Bobi(tT zAciSMi1VLB;m@CEJg1C%J6J{xLu@4<+X>&wN(-@!Sl0ZyifB5`cbz1;WP!l|ZXPXx zWyBm)f<hOHGa!em34lc2-rJs3r}!Sg)AY9;DXkh&dce~Typ}^RaRHc^y0&T^(Su;= zkr)m|6opr#xTHR*;fE2J&t+XO>JU4aoU82n)L&LSeXYp%ufd6ipGKl66bDRAT+5Uy zt6!U>`ZD+Bvw0WeYxg~X>`fUK3Z;%86#%Q|qX97gVa4vNk3d2fbH7K5V|}qY@8Apc C>DlD~ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/import-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/import-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..bc7e4f4c91172fc161adb697e3be7a1c8eaf87f0 GIT binary patch literal 822 zcma))p>Kmg6vjK2AP~)hAWH?JqFE*@_yZ~`mds2{R3H!tL`B6!Ma2XHF@dP4Kp+qm z2n1pRQGq}p5Hvv`5C{YUfj~6-;ON#&tow5Ja_`>n-rc>s*|Tsv=p?{Cpx^cVW^mul z5BfN9h&>*UqPVzhk|efGY%Q7ZXF6Ar<)xx*)@$canWm{IGT_x}rK)OO*QaYb96Z3t zY#2uK4;4iL7|F3$S(eo`<#`TR*LBOXFeXA0h%ARCE(xV+y4~tHjBVQ(6J=S3Xx%ip z4bF%$W=JTGW57s`!Wf6xMDr6XNVPDx!vsqRpCk#$D2l=`B(UqcFILQG5iiX7@#AD7 z%;zGORCWDL20`HaJ~De}@kTlnHHKk_?1&#vH+v5W!9WE0>;xBuRrUcb@0eaJHySG+ zCc&^f5t0K&l8qBlZ!XPpJ^uR6O=pt21AtQOFN9kxodht&ury7#{6gh+8SWw(Wd9$F zU2u0!i*R0wqFVTADL6&hoMf-u#?`M6f<J@uCV45W4Q|8(o?0zTRMh8D=cBfGf4m_6 Nb5S*d?g0jKRbMrI9SZ;e literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/import.bmp b/krb5-1-6/src/windows/identity/ui/images/import.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6c1331dcae07b0d682d9a6eda5ecaf4a156b57c8 GIT binary patch literal 2430 zcmcJQA&lZ!7{}R)CR>3(Og3x|fgqO=BUY>&F@ju34lx3OKp+qZ1OkDmK#<J{1frq> zQBhIRWSc#1kG=G=O}2tbm`f+i>@=a-<&q{>QBi@YXzt&>PT_HLm)l(SpV!B0OMm@; z-}~O{#gF{cT%wogzsK<%j^{X@<es6=<$g%-Cnsrl_idE>HrTs8x7BKr)`S|3xHZud zrQ_rZxpmk#(+BZ*=5o(%Cu%er^?I$>>kSj}{1EN$<MdMUga0=!FUjM_T<!JiZnxXU z8ygMBaiXtL5CjOSR;}XcZl^=gso$U8yy^G*Fsm;XU&BoQ3oDg!xmvBlHO2kq?OVjO zTCF_K+tKp>n?zwsvO#fwefMrO8ZDPg*L4xsp|;!YLj>V2@IBY{T^BuCCXBDH#+c{h zJp88XxM3OwD6o7e+qN?<z^>zvwngxcowRs_>BaP5!YRMT`}dQ{MAvmtG8bfk<fPm% zio(!$x6azKt+=fp+SXq8`@K%5Js1oquKD4EAWY};`Fg#E<wGGkdoI9%Z(FO?a!DHA zfj1$JPN&`Lc6pwsxYyU$q9|&b3U{zf6o=<H2qNajX5$}lEz>k~-CQi})e@(;h8wL` zbI|XP$770nb8{ohlA<W4X<CV39Ks703muQeO7h@2Hi!#NvzKN9CGU$a>-FJqh-6aS z+uK`JRTNn^3<H*-j1J2QH6aK7Qr7`B=JTDmjh&`(L>Cw5Bc2xof#R+|e$+Hgk|eAP zScV84mQfoSH}Jf<qH3~YXxiRvoQCMd*%^{Bo6RWh{rx9!%Vt=T9ZuYGQ=1bUG`6iU z{dK_!2->kMWj2#%GhLOBxTmKTBmv2!xSP!eP6yJ05qxIgF!>UfKgpkz^TkuHP~?=v zav0f5LlH$um|FTg+U=rUk_YrrR4SFG(<x?%;(qz^8L<n3sH!S6^_h{&vK*U;DW0;! zb)3f?iXrf9%UPMB@5RsqZl2>%QK(dki-JWeQ|>HaDz%Ku6)SA_VQG+bJl5m$1GAWR zihF;*K}od*HO@oj0?>RO4q%xp6pG-sP@m0KvOCw0RI6c+tb&V5M-@@rjq?Y%1PWpy z5z@e%^T;*JTb}3sOT&uCD@namT=n-q87W}O=kN#t8|St*Va7hww%LjOSm^s}u!(@k z>ZiERU)>>mIEBDvpxTs^JXA3=@fpD-%jD4>;bVuygp+_M?yH|av8bvz11B-}tjmfX ze<h5^SFMR$Fhi_SBJ5a4!p4nS%65N>ixbfafR3T(JgWxVApLBFsID-izajs4Mxf~T k-(#FiET5@Kc@-6(3eapArF#LcJl-<sG57Gs{~YK30vkKMb^rhX literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/khimaira-cfg.bmp b/krb5-1-6/src/windows/identity/ui/images/khimaira-cfg.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d20b9eb3d84f919e2f1b58c32d80043800dafa55 GIT binary patch literal 30056 zcmeI4cU+WL_WvI{(qS54M=a4z*(95|iAF&|u%HH!ZbKAA>4G5GjSW-~!GZ`#M+BrJ z0z;W$dM^yU7pX%xyZil}XGV#;-|X%mzt?xnA9HgVCIf-t{d~^no^$SfVzS%y3?duf z!Q)!^IQITy7NRG6{cHHTuA2Nq_5wWok8&spC<!PDC<!PDC<!PDC<!PDC<!PDC<!PD zC<!PDC<!PDC<!PDC<!PDC<%ND0)PMe-=$J%TU%TGrydOr4V|5x<KyH1_{Tp!1&ROu zJEx|mcsyQgZ0wCsJ#OB-`Sj`2+S=NIfq}pM?Qj46tt<RHT3cJgu7=$WyB!vK^X|QS zk&%%P9z1yX@ZqCJ(J?U>!vgkyiJK?iCW22Y2%<l0*4laV{ybmhJ9UlkwY0w0)&2^n zYlPP^!fLF<=`7J!*Vod(>uTs}Y8YthF4ELp438RGOVl-%Xz480(KXQ2Hqg{sg264r z;g?}?%XA6L3A(E>x}WJ9ti<UZK79E6`SW>sdGM~Lr>7MT<G=huE|+`A_Tc497ZZ~c zGcqz>zI>UJlLPOzprD|*IH@Eq&}D;>rVQ3>1W`qhB?$8Qytx||sv2u+Z^dGb@t7a= zFkczye66Rw4zINmuWg9aSw_%Vg2OD*#4XXrF4M&=#}QWQ;*4<mh8X-Z3}!i&u!2BX zp{KWc$)Ys|i`Om2e5sHBlfkmj43?FbmwTK#=6>?zvuDpZ9L~td2w22_`2!UAWe7lf zYa1sA2R|R*g!qJyKo!4!{kp6ysUrCBUfuT_kXQs+fgqpFo%@Zt+K)Qgn=!hk7|d2Y z=C68~?=jlzwKe{P$9|@-x0--mj>GF~;THoaf*#;nse@aA*IS{7S+xke+JLYOtGg1U zXn;4=Cw#eBZS7LRVuLkCdWLY}_^eV(vrW5q@4kNhdTD7XIM};)?-a=6Km96T<!Ec? zXlv`_;OOOkIw3wD6jfAI1fbr$c~enQP?>!FqWNlV87*M73_(^Sv%XeS`$0#0ldiU@ zF4h#Ivk|BJ0|E0L0r#yQ?oW&KSL5-k01?3e_!#LgG14<I!sxBW8mz`**Wh5{R^u?M zu(~UBv{&MAUoX~KZ-8C4XwAAMtN47rP{;^zKe%DThV912K0ZFl$;l#-=nrD}@b;YS z91hw!9CCCza`2FgvvWjvcyV#D3{*vBWo30$+KT|2^$>vwf<chw2(o70>@QVR{;H|5 z8LPV;hcUxpx9H=4G9Y}fkN-xW@VSBhdOTqT7Qc*uUy8vP%DAl}06oGgJ={u+t`Qcq zR!`4}fM2agSgohOj-Y0Q)me@=T)$|gP$(3O#ThpOO-xLzjg9wh++=5C6CNH;B9Y#{ zef#ULzy7DI{(t{9V0F;m>7bL-kwXWM9zJ~R=usEvW7n=;1zaeo>S_|{P3^Nw`<KmM zh#+8GixI>KENk}c@6=R(($?9gqhp5E0oU4y$8NysenY@~K_INd6INmIhI)7-g5F9j zeiaV85`$T(qq|BMvkIfT28%J$(OHebtj6IC;Zb|x3N5XrI!iyp=mRK;L{ge?ce{y+ z{no8MyLQ`~7;iJ)5)>4am6g@l*f=>k`3W-$fk1G`@!%1sgU%m7op3qscH%^UpKpF% z9$ZjZ#Hm#Y*S3FQfFK$O0*@fA^|NPxqoVSorlyIO_BM?6HUf4F0k;8<`4)%&l7L^2 zBdo!JieO^bfOxPtLp1tuhB~@Nx;ksII3rzMBW;~!+S*IiHI}KX5>&OZb9I(2PytYo zWzk=!S#8~FyLGFlrKP|1{$u<17;pUX(4j+*A3tU?nL|TEpUUuo)j@|tN1P5hA3Ac} z+1d3tfO2(rbMtUNdDhn_IU#{kTT7>xRQVnJ3XMVpFIx)NAjsEq=6tWJx<y076r`o6 zYpjRegi4F>t)AW&IK8!a!b&{W2(SB@0q!#bW(`hjEe>O-qiLkAwHAvt)Ye_DrMW~+ zZP7wC{M<P@h^jWC0Y4ei;ijf03FXbvU1kTiZS%0SJZrt*+t%vnfuFZ*{Behc#Z{T$ z+uPeeNk#z{aoFMT5vRk)k2<@$xPYQgy1AWpclSQ!e#YZ;fQLu;ojWudiJcy9gGCc9 zNE_gf0*8mQJ73M4_k*gciH^201_Qd<1kxhte~ZI?rLX@v0k@8TTdjv*4Q7tVt-|OS z>1eHnM=hN-np%dcYKs=AV&=?OM{~A0YRCdTWENy25M|BH&218fxBZ^|rlzMYcL(j? z?`Lgw!rJPP&4HgSc5eKBgR84+e0)4u$LQ#&g5wcbIXfOYdho~zXBRh@6YeKmPr04+ zJax(!KzVwe_44xd^t^QG60ssV?7#+nnY7>!1YApDL7anpF@N3$4b2VOxQ#fy9|-z? z!Rmd3$A62*|3y!KJpl*S^qG#<Djlum80{q(^`#oxOXq7YovXfV?m{dwdx7ky$sgbc zemNTfP>_YTw@I$M9o}nddTQs6bJo`Wwg*nz*&MU8bJ}lv<bbWo#*HAb(9lq@)85`* zMH)V=$gW3@Iv;U%J9^yxxa(=xlO88ed3$)A@$wAx_6qd&KI7#DYj?z*YdJUFH-oBV z**pAcix6ZLf~=c2@2iFC-|OOj(8WUlen-&znn3s(hx;=mS~x7YHzWxwG&L4!sq3jN zG+3Zcn5C(PsLqiAf=4(%CLcd(A`#BpTU%NozB)TQ9tU{sGBtJIu_JK*{<C&AUJiE0 z?d=cQ+8?pCJ7#OY*J8(yKm6e9>zkjS-{0T=f4=~}{|&&(&;8V~!$;kmPn<g8=Hce< zb?P)|DZtz7oR3eCuaCcv&sksJ=<v|ExL?j6G=@bGLJ^M3K^PhWuDNs9sj7XWgZow& z^DPGdjW*`bx|pvqn6Dr=(AG4<>KbZm8K|jaR8_R+&M`n1=petT34V?af@mSgo+U_Q z*1fSYQCn+UM@L6@cX#UD%R9`>T+PkTTKybod%(-y_JqCt5eLU(_D;_B_Rfxuhi&bC z{O&vORe1jjV+G6f<)GjbM_pW9KveFY?x%e`JkNM~2m1H~`}qd@`T6_$o)7eodlCgM z@jUTnu(jzovk?eJuosZl;yH7cFHl>huC-26XT7%0m)hFvwY1i2Yp+3TKvlg3Dtam^ z*aZs~&O+q_DgrVe4+!LwUl8ikuC<EAjRFCe&R{c{Y!)jm`nJhWKiO~D61d0mf`g5p zgPohBqqC!fi=)#C2gegm_AUn<P9Adl^JnW=ESADp)z#JAyn4;+gsa;Lx6^K?yia-f zd3yzT`=0ajJMVu6SOxg`UAqt*|12gkF)=CWX>w%H9ox-6&Ot>5`2z--jh($<$pRHa zHT6~Mnt*7nhV~jY^%VeWp$c}+9NpQoA=8kdLLtrlKnlw6KOxAa&Fh;oZnf4ift7^E zW7bk=R4R=|D^7{szG>5b<IR4SJI~wOoN=&sw|6-1;NarmaNH4|*dMpIb3JJL<+}9> zW_A0Qo9Dc|PrA5z0ISm=DxW}KzmPNj7yQqhKXWE9AmH}ZONoiklai8BQc}`VZ&4rk z`+m3TYniSfJ5@tw>(8IRbfM}h4Rs@R_0{mGve0m$3U2;<4P+K%urr|KoIs7c5X5(d zYQE>*)|?xybrmgj;ug4Oz=~W;r%<R=D!C&6;2txpZ6@x!cb>JeJ>%fuZU>-H*E(iv z>tb&Y+)g^#ey(s<p}*X^c_9RKb+^+#r@j19QTd1X2V4k1XHY;uMCgqVpwcqZV`#5# zKXcl$TNMpMFnbMTHh!M^QdQLzY6}fj7Oa>*f7vXR<?tecdXwD7<&>bPwEcWxoU>`| zCFjQYi><5|tztPSadVxxj?1N2k!a*v3WdU;Qt$e^S($Bf-L=!#+Rn$$;WY38*K)9R zv9&!8)85|AQPHd*Rlaj0H2lWR;M1o;SHSA5x8FG*|MUKV7taQU1Ox;J1w9JCgDNU5 z4VpHYFJ91yv9G;%9oAb2_71v&6haGGh@C%Ae?ABdA<RZ_hzekVD4S6fa67VQLEgnZ z^;P#81ZhpeoR&Ibt5^u3*IHNCA{IA;Z*sXbVhxo<hDw1=p;SGOaNKTobmvYlYa4Gn zdry0NS9{Qvjf>3z7aQASuprv(|9q`N{R&d$d$;aH+zh*WF~r;5!`IX2te0PiU%<tH zpo@Wl=YxVmf`VeBBj1C{%*=Y3MI)yXgX|pj)WP8a2uv+xHah1ZnsZU5{kGJ}^z_p# zB*AG%-OGm(VMV=&+bCi;iFnN-5r6_pE#kUnv8V~wGY*GBtf{T8p^(WU2BnjccV^EH zyX_Vyt*ku`*q*Ypb+xr|IbeP4fVGQ_%@OMZhpepDuUe}}zXDbfq4)0Jz8e*O_hMjx zuZMSl_n8X;f#?0tT{?FTSX~MUPJ9-FDhfblW#we&P-;?30}onislcKJ$^pC9MdoWE zb5)U9XlDP<!*L11xqeW@%&HRzB|>4nP}Cq2Hi<>R2L&ZU9|2UOPzbEZ<(1^>8XAez z#AEfhQ}3N{wA#M?=$@ZXSs!q>wmxoi;OK$<2d%A~_w7Hl_h$#oy=x6uDVWuRhzC*O z4<0^v7;*cWpO4>Jzku@rL6-u9F9io*2oAn+^-_Au^Y@@~a&lkg*4CtFdf0p?Qxt%K zZjA;qUj_aAe#k>_K7t%Fm@j<fCFEy`1$<ytFBCQiMU5h%4Ags8Ah0H(5LgM>?3yxS zRaG^;rlwmW?CX;xpFOc>`*w$2yIrlU+^qH=v9fZq`q_T(KBt{l_B(g)+p%l)ij|6F z1$BKifQoz=1zq;2s0(M$20#D?p1TwhaxpmMa!AO-@UYAm8K|NFRBmowUOuHJ?S|zK zkTA%ZfUeX&QWPKpKZmZM`wDfzlk-A;rC1<<38In+1Pwq2B2F$UP?rz|)c{i<<TBWm zWyDHiC6`>?-P+jO+gfnVbFZ11-LBm(KmY8qZ=a*3rR^Te13P!^v)HrC!eWQTj@2tx zD3TSFs}Ju-J&1^meh~fe;girSR|5P4LxRp-K7amVNXYF=7gOS&&Vb6#%P+_;puM=g zf3b?J+(Cr|dXk0SdtJe&zaYq+9e?2$-V}04LOu@#C1)jz!A21ToqUQ=O6ZHiI=+y_ zV81CXt05949C}w*Yfn!{;mtGq%*+n#*zLT>(%Ev4-L73fTUc0{n_HR#C=0-~M&YcY zBBGu|KZ$)58~ZRWHX`a=K+yT1U|@CW!iC5i*RnE_<%)vh3qTbW#^(k(t@#jc@EKGD zT9OZ_S@zAFoqlL1uQW!$WeRybA)hY`KtABA7lBzp45G6M5_O12zObGnl(2;&mXJeb zmzI`Mh~=#k0hEMYU2QqP`0p?^-M8J`ai{rV^PM*47CX(&EzHejk0`4jzfkBp2)cS4 z^(gLPY}}(~i80TUp2lB0cRnNtqVK}xix(f?xtWul0ilP2f<Am<LP^xwv)?b5x8LP_ zKIjVlx7`b8zd3$@UHXX2uI6(%0xlPDiTJ!azKoSjLVyb;CKNaDL=9||RXtNs$K<mq ztg6>#A`Y#stpTdS&d#>P^FF4grhCoItt`x}%`CvXV3>axXRLRfaM-8F7=+$h?4ze~ z(eck?5|W-KrNpJ&zkcIF$b~BxE?vHSIW{6JH#hq|sG_`*jPQF7+rZUf1(a7S?*mUp zZ54vt-}w_e{XUaf4mBN5#!8N>j*o^R#2PwzqI!X-o-dMcMD=W;ge9z_^Tafsn9Sr; zsLf51mX;RS2k+=;y5oHuSnV;j*llKJVP+;nwS9+$xx3}gt9y3P;zPZ>PAifXw2YoT zd7Ah%G3jYy%CnTz__T!R=u06N0o0W%SDr=Q%g@i1@9dQ1CqM9V*sL=bKta%fM**mr zv>fc~$TAJ)O>YL{6?A&xPvElIfD6<G(h~FeGHHRmqqB}FlrRNiCOi=Us|J>!nZfM= zr3rXVO%3ucR-2ga?*L6K)19VfW~T6g4tsNpln`hB%dobr2P17%FE1|zvr34GONvDm zl^U0to{*lIn0ym3UA}Vd+O^mR;ROZxumx69Qu6w4$N@tP^a_B|%$#8b_0BV^9~i_q zCX)*99|oJv23+z;1XeI5TtOXIAmIqbOo5Qf71DVk22Vs~H&EF<eBnrQvqZ>;bs3}% zxcI~uP8Md{wrw*9P=L(TbhoKl;pNi<^^~E(y5T;-$Z)UXS;faDBtJ_`i%-i)%*ag5 z%*xDqd@l?@{qoB%Pa?yMiV6W#X=zr}(Y>F`Vhupe=n9_5GY2T8*%zGZ1=$>#r~niU zj!aqt4oA%8i8*{RlP_Vx1Y9C9gU_e1coe3P!fd6ph9&jG?d^3UA>_s~T#avHZtUE; z6<BTGCL?8P8hUvDTYgdh+x~(6{-MGC;lUvVvjTI7e;S`0o0JhR1N8#U%+sGe0Z_2> z`!M2ONl6jx|CSXdT;2Ko$`2WWTuuND+6eNo5kUqsuZ|2#`rGT91#F%i7U1G=<i;i9 z2}CTe7=%RU3TPYwjf;Y!bHo%@E1f;o*f`wPDHe&L-vGE8MU1<rkC<*n2WZQ5+qQFi zcM0=idwV+H_VxAmy&dcy7#bK<Fe~V9Cnct)C8TC1XJ)0nPdIZkQbVs_hl4Yb_rgkF z7nPM2l^5L(G+iTa`O0ld9)=%KAzSAoBSrV6(h;e2aJ0YYZA(Kvs7l6)%Z9yoE}O*@ zFt|b{UqI#ZY8e6wI5|rQ=qSu~CTFs>b+EG&l6R<~0T;V4^N7V(6BCndGF(TuZeu*Y z(cRV9)7{h8+xxcnJubzwN=;17NXf`d&&<h0Gjnv+dzF1Z^!BY=x5C3hON$H2%kzkt z{<dqNqks-z1=X=U4CSxD<91DCsOTOX<$~=M7-OS@V?C`cLR42=4i_ey%i}S)0y-Z& zN(@h^94>{)BGZL5b{msB-rO?O)dd@Ha$F^G4|W(E1FUT(CO|9fh+_x8va_SJyQ@ov zs}FDuyzN&!tMtUQmuZ<<8QHlnKIBnF1u^%-Z{NOsH!Q3;FN;Xb$h~^-n-4ur2tWV@ zbH><#m8mu|QVO~nLP5#K`1sI7e`lMJ%i{tj2t*#A#p6@CoLZ(p7KU<G0vfxK#-3<x z16J^DfD2j<Inme6jEw;l3{w-6yz6J%S|#o69bKJW-Cf<iJ-whVFfIkNf=uRR@{6qW ztXD5z<-e3==CW1qdCbGGu&_IK?&N1asmckzV*VxM<njT`{sk1gZmx?+D<Y)Qfsa^? zPfUzX4)k=2`9d%-I`locd^!hM@u)071R=?zv4sq-guxwdXd3D1LC?wX`G6}mBFNa- z*aW7D$sQ9EN_sT9#nT3xJdmSyc6D|2_MpM2cve|SFLE-na<lUaatewH(DVSzJT2}i zfVz7(G&3$ZGtgnz!jH4g57a*Tyn}#988HA#&I(Spz?hhrn4B1&f@qO6G;;Y|CbT|L zT!08fC1(Xsz~MW%yy3Q1@HZJQ&clmtTefW33cQSstxZh0C8^D@2(`4rMh}V$g0Zu^ zx1-0?Q=$14T&h>8FJHaL&dtg%$}cJ@LP3?4mAy!eyL<O;c=(N{R~^s%b+O?`Sbq2E z?q!Hnk}^6v@F4(Ypx~^=<mA-o<mAwhw6(d3!4l9pa#nmA8;Hp#yi!l+^oi?OEE<Z7 zQ+egM1F$mPvISV#Y%>v7<~21owE(YXz}4Q_-r3dO)!o+Z<)LU+`I)(SS^4?dg(Z2# zr9~(xIA8ZN`8gcsiHNvz*Kg;3&403{-(_|3$HmgVlF?Bqu=-6@Kx%AqYIq98H99of z*3!y^rH}`RP*KUG1y6vLh|XzdFd5`Zz{M&}cC|F$ym|9B;I(Co?RFDERdHiOV{=n8 z;A(4WYj1AvZ0hW4?eaS92}!TQ_Pn4<Ey&I<%qlE?Ra{!|x~v!lMI;il(~=@0BJSV6 z@;KNj<Xi0zC;NVv69T1l)`df((vFz`gy=&95XSiAlyq`*d>V8%{dRCr+)xjTpv<X& z7^n+Cf!Kf*znW6>rkFt^6~|uN_tQ_n%4G9q87pIcRZ+d9{ynaSmez*W_WJhD<_=GV zvnqU<TbPw!n)kY_=uLTXIk6O)lU1+MQ|{lt9~l|?I5LPB=6vc~9o+A8LSJ=The&Cu zqoYIrDk=a4|BO$KODD%hCdNmG-+?c4A#Ff$!4xrh07^cYRkZ~#Gf5StNw<7pBNYbV zf?;EB%&jbx)JYoZ8&F)0&8?Cam~Hhfo~Jz&sVi7kN?sMd&Mhh{C@n83C%z_DRaVv1 z)a1TMfiuZbQBjYgLP^9Y#N=~V_I>r&-@^qv6vW7*(h=dP6wMaomM#|+fSMYenvzbB zkD+sVY~tPE;7EN#-3O;a?F-gKItNxmdR6U<wDjVftQWU^H*ebXF)L1GJ|w6puDXWC zx~3*kQ?t0SNmTE7O3|!d=N7*yd{dTRT3%FMS%HEg)sXUErUR(xs3<tUT|>-bvtMyD zf64UR?(*3jX!LzZwa~5SWFIqW{i{)F*VyRTIG`FsT^(gLF*!9hH8Bj{K0Pr$EghSl z92uV)92^HxP?)HzQ&}^hfEBHh1iMAAGBQfzZ~bhtanlD}Ham>jRfQsvNRF!>a0we4 z1d>K^gMwK>OqAvoL-bV?mQ@s$SC`k2sz|k@+QO_Cz)E(|{ZUnE0hbH4Zkd1>D|q6O z<oLboQe-=VIO35vA$x{JY0}{)C~n52zp<JeML|uCOid3@PmWHHjZTb%$xA1u2Bp)T zT@5l;;8c(;paBTA4}(i3)}*GSW~HT7<R_dtyjRW&)Mc~VgiS7ld>+Lmu9JxCfmI`4 z(kPU8C{|a%sw}^xqPVQ`HL?0lRZV$KZB;F`mRekpEe8cB56cQ)$x}p;kR{?(^$T-5 z-`uLp4eF&tj`Wg7hI;@M8h|oZ6S8Dsd|-HLXli<N8s^0C`0(fid~r%TH9a&w4Rsxr ziGpJCP-B;+qe3RiDkUi;Jtg%`es;<of8$N>rFGbP7ne~EZvZWSpkCy|$p>*gUtGr% zD_&O>g{5T$ud7Qc02H|rPKVagYG@Uu#g8660#GqAF~wOK0s$W`tE>+o8SL*L91sr= za)$>SMuvt*hDSz0RHLKs0}xn2_)UyX4UA6@Pfm|aj|@r&hek%F6YoB-f<y}_q1iiw zD`xZ2$>dXs<fP~5k%@wr>EztUE|w-BEf^uLP8<#-{b>0k<O@Z7k(ev2;|e7_k%C!u zcXty}QB_vIt|C{E$rTh@HH}ftpc08Ok5Eu>k4#Q#qDaU^4++=7mOii=7#bXe_7Mtd zXjm3~AS$Sr$0o)mAo|b%9G)8QpP1;Ic-KGmZus4=(qG>VPW?JGiR!AS3s|9Mg(eJa zA)OE1Q4yU_tsp1HJ%<DBS*fYjr8zO@oHuPmr4@TS02Vv6w*$Dius0?ULMsed@kI(= z2YY&Ys*202N{FP=8cKO>ZFw!DhQX+Y4nS=JV2XJPw>70F#)<e$pae-yLqj8gf;ln_ zlu$*DO2Mf{$HCY~#wVoXlTygir_cZ#o*wTTo9G*x8kqQX_}9OUy!#dGYiR6UZ})pv zbhdyF4$tP-vIP_lrGotY+4IEbiK)rSuU};mUqqfT+vs4nr93AFn$q&}hs%Z{oDZx- zY=M{~P%x{Zp`qHcYDy`IQAwp&(pV%GpTg%+`68AeJ0&&YS;F(@&$Ck#8|%1eJq87A zYa2>Q7I)xLC?eVNH#t5r3D!L_iTb&8`knOMyFr-K?|@tX#IHkBa#rt#$KUn!HZxIC z0Vvtz3TZr;q|)m6nE2;#ATBX6CncF!l9L_f|1#8*R$EM`(@|V3=<slPY_wk?WN}3- zo`Pc#?mpvjdC5u1iO-)W#Kk|0eHQmDE+HWS-f%?Njo{#5xbZ47^xDge<m~M1S2?d> z^3h#Cfe5x3L}H1!t^qRY`i7>4#uhjk3p`s}J7nc8+CS;;2HnC5*gj}x_V>fhZUY1T zgKyhKY&efbW5|YlBLkugMsa?z{OY79B^705RF@}{NjVe>S^mvT29rf+!<H+L!QnGt zY2YeYSMp*CQsO6%pF~F7zZ-Tp^cFO(ZbL)n*0qbC?(S!OJi~8Zj*fnS`uvla*r%~% z5(y5y!vQ=7oz9Y7ZZ7QCaCt(3P$ZNs>u{tW=ry8S44_76`=HH~4%i-*(d%vzu&87* zdUgnoTEWRQ6da8P;(<|9Rg<2c4i_#bC8_dFK8aK*|27(x#-K4^--AtOb7?FYF0O)g zHB)%PO_w>@*$<<l??>FfclVyGd3F18fY0rVfsqkmXafJ}5%2^DBh}Q@lF3vGg-)X} z(G#954vWp>as{xg!_fs<&s+jMbErpTtUzgUT=LdaPfu5~m=CZ30*o0}a$KM_cv4(Y zke`uU`KGYCnn)s{_ig}H8ktJ3WzeZiHU%<Q7D($;v64fBX7A%ij~_-qgaQZp46vUQ ze&=Rn<bC-KnD8Z#R&`Ys;QD82u~2EjI>nbafzf&d-C~fP?f+O>fUCQ^tEatDKqvh> zX>k~gRuQL7!mF+>ud0&Y6GTF<P7UCq(I|8#iN>m>aj1+>%L<6S?RyK`UXU$7E_(ky zG#kR9hz3^C(b10{K6>)xNhOh3Q(X;_SW8AD@qbAR5^OOf*yy4Ok=TSr;=f3%ySu%u zflnp<4lW^`-cc_Y>T8oq`-g`IAyt4vzNWf{Tty~Vl1WwMS~7(}qB6;Vi~dRcY9<op zPaq!QqQlLhKnxH8D721#5CwXZvyw{-t~CWcIgCakiwPUesB58-D0eN87TA7cBj7^U zP`DvN=325y?C9xiZUT${$hE-l8@Tk|X7O-e`^ZSYR5~o*>45*7R86WO){rVlP*aer z$+YTPzy<pnpIlcn+~BW+EE<RbAJABI6i|x>%OX}(R8>~Wr8N_Y44HB9I9xOm!Q}s! zv}Phv?pod59X%aQ?R7i>t(IF`D`rsI#N5G-#-aYM;o<%fC<aDg`wZO`g5Jg3-nR@2 zqq@ABR8FEmWl>3{*MPbxe;if-4c;oW-ywfMi9LP-F$k7bURDOUKw1zQGbT@`(OC?p z%;b5p+6@*&G|!j!=$d54_0Q6RH4!$j+Il-0d)g&$I~xc3ItB*%1_uWq<r^MGS$&KP zT0M3Ax|*^YGN=oVl~$7IHMM_)7@U!o{0W!_lpc^JLc;I_N@=*ax4ax&3vkW27O;{V z7px95TURr#HDmH}Tpy$*&%V0)`nuk}?U5&7gM)*=%Sztx>Fw&Nt*j+iRFf*IsZ}He z_mKYu%fI{A!GXct?A+AkRJecqO=+o2TEr?ML?YVk`pvcE(t@o(9^?;bTR<X~)YqZ; z!@n{4_sJ^UqC3OtV_Xo1Xe54UVvLWDL;1;Pacjz}$i(UZUw^oc3cfS$-y!<=_34Re z3W<`QmR1V4jhDVDFDoZj5NoQycF_fqN<mXoR9Y<9h=Ki6o`A=P++Hjc$rr?r)2$hk z|2VP#54eEU=m=Vy11p$Np?9>jQL0GsF>$cS{sCE`-2VQLj<$9(iHyn#%!)*&K-xf| zLI9%P4&4AYx+Bl$@&#b<PzMR+Z5%XzK&1s4#D`=af^jCFp9#qsbn>zY=%D~Xad0-~ z?Z5!^H~I$$`v>6>W^Z?ITSF`O*dLS?;QGfO^ndp9aR?}%D+wqGC<!PDC<!PDC<!PD kC<!PDC<!PDC<!PDC<!PDC<!PDC<!PDC<*-k5I~Us2Q%w<e*gdg literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/logo_shade.bmp b/krb5-1-6/src/windows/identity/ui/images/logo_shade.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2e36b9bf2016cf725357f87b9b43dcc9344137b4 GIT binary patch literal 30056 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 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/main_app.ico b/krb5-1-6/src/windows/identity/ui/images/main_app.ico new file mode 100644 index 0000000000000000000000000000000000000000..8dcb29e7a66f097ad2f67b181bb352fb2421d3d9 GIT binary patch literal 25214 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 Nl|lr5Zx?I${{ZwxG8zB? literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tb-blank-small.bmp b/krb5-1-6/src/windows/identity/ui/images/tb-blank-small.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0718d128bfc245c72044f42207c68ab69361dc78 GIT binary patch literal 774 scmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZm_i}0kAl$<7)Bug0HIx8&j0`b literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tb-blank.bmp b/krb5-1-6/src/windows/identity/ui/images/tb-blank.bmp new file mode 100644 index 0000000000000000000000000000000000000000..01adca9e3d8b78b4beea0a9f9d29954b36234989 GIT binary patch literal 2430 zcmZ?rt>a_>12Z700mQOEEDgkr3=%++fx!bR59W*#qaiRF0;3@?8UmvsFd71*Aut*O H6omi)zup2D literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tb-space.bmp b/krb5-1-6/src/windows/identity/ui/images/tb-space.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d85cc5cd745cc44f4ace1de38f2552bf93294a7e GIT binary patch literal 2430 zcmZ?rt>a_>12Z700mQOEEDgkr3=%++fx!bR59UCL>$Cw3v@!PjsJW1U9Sw)ka6ryt aqv>HZJ&dLY<PaE556Gc0T0YP?JpcfUxVK9H literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-delete-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-delete-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..00adcf44365825b43f9c3dc27c2b4cbd7d07b7e0 GIT binary patch literal 1014 zcmd^6yJ`Ya5Z#bI$tR@r3(^P{K|#c|P*m(>Q4m+f!cM^liXbYA7K<+gABbq77Jh(R zh@e;~{z=-Coe5bq7O7HY;M~2#>^W!d%)9vUC~&-Kr$NJuhGz{A!mD<Eh5952gzvaq zF8C{Kw_9CXRaNZwdp-Znvrs6&@AqT5Tw=4?AQFi%4u`{y#_4pz@p#m6KA%Adg+j<= zG6;vme9z@_%-`*HH~f4)k3=E?S(YJ55>lxY*GbcCHY1zOg18oo1<`2qhD&d#)oP$# zsTK$X;C8!_PN&(+;czgQ`tW!>2nK_9{ARPs9+Sxg?RFd0YLz*5yPdx_n++zDi8Z}m zFVEt7c8a2)TrOk1USm3)qSx!8Uazyi)oSIQTrL-kMkAa~=beA2(?O%rz-qMu^+5be zrGjFyh-5N}SS$vg&j(Qy_1Rqe_xpX`>wG@PU@$;D9>;7p!*Dp{_fk&prv1@euDNul k{gOtv+eNF@!eX(|{~3)&D3waw3+-t<9_zKAI{!8Q1Q|N-3IG5A literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-delete-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-delete-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..844fb23a647397b2a5c3bbe22814dbdc881366fd GIT binary patch literal 3186 zcmeHJM@yqo6wU01`2)kiY}66mh!{kygNo6_-WxWsw<K1?3W61^Sh0els3;<eh#~{l zg<Wvx&Ru@OnVdU(!TF+s;4qtf@bdCq-n-}CbI-lWPlNHZMjoy8^M`ePv#zh!^-1&H z`uXSi^+luMQl9(!dpOqnIJmpJ`zM?&EiEA{D+_A>mzS5&>-A`8X!uavm6a9fbUG9l z7b7(_6}Pvy;{W2}0ud1rFdB`>$jCrbQ`3jw9vvOQ$HxaPEiGtmZAEEmDH0PCaejV| z@bGZKqn*po&kuWhdmn;ZRaJ$|%uMmC;Cgs?z+^JnY>cC~xA#pv#u*e8gyiI8i90?% z9<i~ph>ng%U|^u#-P+n(IjiLKd=Ci;fmW-vyQA*KlamwV=H_B{b{6B~;}{$qL{Co- z+S}WuHbX;0c0OEPU8SCCJWo$giC>MOekW#rem)i#7cn|Iih+Rvba!_PCbi(}>nm~G z+}vP)e_wKRa&iLmeU8cc(jE{HU>D;{nABl&bF*kKJw09gl4J6lkdPoegoTA6G&B_M z?(To#6&4oSu*=HI1o!Id>P=kcSzcZ)d6CoA)m1DkEMR(iTJrAi??+cx7aAKILA}(~ z)!8suZ#OqL7z_rRjlQCyqQHJt=cl|AlYK=#$?MkE7S`6*gzK4^8H|mMiJiFq{{B$% zqV6IiBaxGnBmA>($#s2wJ*cI#v$HobtE;QUFa5J-+uPe%Utb4j&fMG_CMG68Es+P- z%iG%<X=!N^E9=6!<m~J$SS~IuI6gjp6_2?xPsTPfG9rAk_YV#Zu(Pv+jg1W~FE3+$ zejbyPlNcTzmfj;ToDICk-Yh66fR~pSf`fx!>@S5=WhW+UH8nLQb>tkQ?eOprySuyC z+}s3bUPniVU^2G8zCLtzcA~AVP3CK5Wu?q0>YrLue80BSKkGn@l9CdcrHnf-FAv$- z*`ig>Q1)w4QIXV;`lWByjdf+6Ie(}h&cWBP6gx5L&tkFQ>FEiNkB@kGc)<1bwd6?s zD`&Z%o}P+-_55HjvuF9+^8EZu-#PnYVq#!6n?(~96%`;3bB>FPlNqkQS5s3X8cIn? eK~hqZ^f1rT5Bo%Y-tqpv{~->(9DMyx4g3ZJvzf5~ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-delete-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-delete-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b9b604f83b136f3049c22941ea0e26fd4b99cbf2 GIT binary patch literal 822 zcmb7?FKog<6vkQS5X<C(m?X;t0#Sjem_U#WS%H{9R3MNQ6BQK`h>8jXqN1YWM8$~{ zCr+F|R3IU#Kp;+3R7^}vkbV6Vl2x$o%j>0g?|0w5-s{V&e%mRfV|>DMUq3gUhjP7B z=c`FI&i|?9Vqx2Mnx^Ng0syRnDWzB0Iw^#}7T0w-=U*+f+wA~*s}=aHg_0xzyk4)t zpIT_U-2x870EO*aNJ<Gfj$`ns?N0$CgfPZzhxLp|>lZN`b4n8&T?w8Sp=`kKF4qQu zG2y;1%{Q(MH$6ROOd{J5U>pJG(U>8%3B;Wq4W`&0E|y3#^razO5zIYL`abRI0pKkA z9+`4x;j>~wBE&^l!L4Y|(cDVAdN`O0!06?pA#8VFHbiAv9ZIQVsmWa82*7z>^xauy ua1f$+Zz#`mn4C_ZMa_L`%n~>Qc0SaVzvFN?D0Ox{Wm-oBAr04GQ@}rQVK*-T literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-delete.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-delete.bmp new file mode 100644 index 0000000000000000000000000000000000000000..01515992940e7b993d0ac3899e93d7075482f8ca GIT binary patch literal 2430 zcmcJQZA?>F7{|{(EQ`r9mwi#UOlDALqmdAkxy=zb=O&13&a6~mvx2Cb&N*=c>cF5? zH;_P31X>&v9IX{BrCOC<-m11LYwZgyE!4H+<(5*Eg1p|gw|j02=w0>!lljm8oSvSZ z^SjS^&ON8=VlwBTfZl_88I-r7yanYYG#_e&BH{PjuLVn>1FH5HqZiNJ_D#aK3GqS4 zZ)L@?VrOF*IWr3gGYNPaZ*o#1I3aH9mob}wcqBc2Hr~JQhc7lovzT88r$Zgg>l9Zm zuiyLqcZqEFR#vQDulGNXdU|>i;^Q|)MMAv0l9OrN1`JF2X+J<Qx%_#UQ)8`G>*CPR z&p%tAw4F`kHa9h;r=>nns|N-K#_1ZIok|J|nOn9bZr@JhDin%inHhIgN*u?B0vaA3 z4mP^GyQ!#1Kk4<3x*xl6e87Q2?ZolEX*(T`oZn8z$FX+r+DYRom3K~`<lIuU*zI<g z%LP$`paHU2EELyAk{)8>iM!{awaePsWwqKnJ8jmWtv0JQE8}P)dmC&cjeGCz-P|)d z4RU#h#nRi`3sHlh0aB~gQ(P}e5)-a&TZdj}*6G@HI+IRk)N0%HI=iL);DP<Slamkq ze2~U%ZEZbww&1$#TARUOv)LeO5Hvt7EiF_U0P6KYDkg^pI<=ZVl}fcrsa7f<w&~oC zF7N2j?wvdK?cI~{%TXFvqtWoVTuE&$L}xaeVeK=LN~Kd=kB{_tCf)toJGT`Wrl_y) zP~Rh-3_^bVBpJtI9ZX5#a5yxsPN%KlmtPiLQmK^i{(=nC5(oqo*8}<Wl9S`TW<x_= zUA;uoabHOcKY~sl;e}m|iH<s)o|>DJP2<AyFN;Kis;XNG1%&*pcsyQ!>mv#8m<zvs zRVuC$G}c}jb#{@2$45ZF54dY1B93Kd7M?pt<C;vSI*Fu$&&M!KrBa<gPx;CfXsYt^ z@+dCh^NbGRCXKkf{9*~OQCv+7J@OM?co-PCtHQ%iaX6(sE{$ukm~Y;=akhZ_>E>z_ zB1B6oDTfM{d>~uDzI2K^;#Ss*%JTC|^Yd;BD?G!G{gVOiB*k448hR!>`(kA!oolvS zl{PJ0!$qq~UR@^qDDrwF^Tzz}8WhGuZ<Z>RPCu-7g3#7W__;Ynr%ya+kdotL{s}6% z<OIcCFmGN#etxw`MCV#M!#|dxu%boFg<^5NT#m^xEbT}$VwA&^&^t0`_aoqXh6nMs z`wv^2iNStyoFK<NzDcid!UNnnb6zPfF1jj}(zsZI4Xr49Jv95mg{o`UWHQ<Hw4*A- z_yaL6eYl|w&`EoYFqv{t&$a_SaPta<!sf<C8n=LJhRG2T$NBsUu~_os0V!fsAcm;4 z?1|0hMhw9li;CIo9ZV)GCZOnmqN1WUObfVhTpwsOH14kjCg84KoeCF4c5XLf@DZcB ztYVCWx7Oo9OC@MQOMidA)7jV8=a{j>fzO!9WEzcaaGGe`g5tk`yZGG`?4(K{2A~tc z6%P*j;cM7B^Hc`@>jTbFER*@S-43R4HJU!OqVna17ZD=|F^W<TYfUB?V1YYpXNnFU z8U59LqtO^VgL=I#XoG<|mKY{yv0`g#Y8(O4xNwnfjHmVo=xf*IW@T}*j-LXrd_NO~ z70z8=dMK5Xk&$^gptQ8KLv+DudOR%}7Z!)(qbol#Q0NeO#AZW8jAh}P78Le73c<MC zG0^BNG%_;sZ!YYQ%jG?G(mi*@9kjHLa!AwKO+9M0&pSH-Aqa)~>Hqvp*Z<N${{UDh B#o_<} literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9100d9a9c7a568a03c58ff4b5590dc4eb8c89660 GIT binary patch literal 1014 zcmd^*yJ`Ya6h$YbPx1*V)7g!U2&S>p&O!tWQ4oA!F`}X%iXw=LqJ{WE@PUXHYT*y0 z6$BOkB<;%F33DNu9|$?H&$*AY@7?>nyFMQkBUC-V>3Grctm8p>)$@0JJSmER8Q1HT zzl`(w%<*`XxLhvM&*^lM=b}gS-g+&SN@$u!BoZMI2$0L=WRKtP$7Zuhh`w8Xv)QCv zE)$Ez2nK_AJRb7-JgHO)yWNhes#q)*W1UW?@A#cgheDyiVzHp#@6%{BC>Dz(lS#ti zFg~9Tr_+hmYUMY6x7(#wtFhnjSuU51Mk89S7Q&a%Abbf;4u^wGCUf`yU@)NFZnN9% z3=M)`uh*$mDrB=+;_*0MuNSx5{bM%f9LD1@hr@yOdd*}qA(2S1TCJE)r-VWwV=rnn r8a3u(^31y3ZV_(`heLY39-GZZYMjkxRI61(i|{j_&*h!T|L^q+$4mON literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..558ba9064477a7038033d8ba7df65075db495d3a GIT binary patch literal 3186 zcmeHI$x35U5KZr!{(+{U7cR2Ug$o-Lafq`fCTg4q)Ci75jiQM-$9cpNN7N`Nii#ql zxQIxDC@usA!JRvIe!}UTYSO%P9%!$6lMD6U<-U9CRGm6?pUz<Wtda4<^VE9mo5#L- z?33oZ=lOg5{G!p&yyNNV2>}am5YWK;8o0Z=Lu_m;^78VKlam9p*^JE0Oqfh2#Kgp? z_EASi2O=XQ5gi@vXDKNus%Mn7xVgE3#bSZW<-+pvGG=FIF+M(yfq?-O7Z+o0ZqCmK zvC`Aik(88#`1p7qWBf}0YI9;%R#swXX9tUmi<p_2!PwZCV0LwNNj{9@@$nIEw;LrT zC5VfQLq<jhQd3g}k1^<UI+=eIv$nPt-QC?tOG`shQIYUWj>&I!cDC@4oSZD*i5VUq zj<B#WgocJ9BqRh{trkH+LH~qVUtceIk<){N18i?^V|{&H@}8ca#^~rM`uh67I<~a5 zfcvYes!&!|hJu0uiH*1k2??SNH9nPV<kn`h37_Qk^z;;mhlj%T#>NJgmX`kT-QVAj z&dyG>wzi_7p#jy^)hI777hZycgJCcjgkz<DwK*{vJMrkBH9I>y!_m<Zc6WENxw(mz zl@-y_#KZ&!2M47N4u?ZxWnD^3OND3Zo|;m_QLYiQt*s3U3k$;M_4PF_FE4R^evaeg zW9;qiVQXs(tE;P+pP$F%<RpfMhS1Z~Bj=i$nuKT8m$gnzO#Bcg`C40BlRDnt--B^n zU0vbg;sPfpC)nTL$MEp5U^2F;sVR(%jKJx1qP@Kxjg5_nh=>sVQ)|kc)aLZx+uJJ` zb#-+hSJX#EMTKaDakEd^uQfF_(wAJLZ?9&eqN3zJp|;pRYB<U@V$$E++Z$eAU-9zt zg6HRFJUl!|j#jJH$H(pMt@!`@{$MZL?RMz(dY}DDEbp9mAN#wxxmh$pJrajGXJuu9 t-@SXiZ|b(Nun_tA`N+-9l^*6^`Y{@fe*3-W0`K?#MFEZi9Q|(%`~nsFzajtt literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-new-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-new-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d2e1fcdc4eb0abcbfd3a0c2e22e1cf91ef18b7bf GIT binary patch literal 1014 zcmdT?J8J?#5WbK;$xldmom~_W3q`DgSO``Yq9Q&(!51iqPY^@|72hHVDx%;6w6Y7> zC<-e6leAxMH|*gVFh!~id^@|d^L;xrcbfOlM~>Q?u<`<41Uw6P;9iCG+diH+j)2+a za>0Mb>2$*3a1e1mpT&NT$D<f0IVAVC*K|6KKp+6O+YPJLidZZr=2$Eis8lKuB=44A zEEbW;WZ?CBVYAs_GMNyM#}N*Pp;oKG^E_lS8Qn)BksthWxr{_2f#Gn7X0wTCG>T+0 ziC{1Yr_%|gQVG3Y54l`UW6R}IqEV~Wkk99_TCFe|jcEO(2GU0;6r%5vvqGVOR;$H! zyOr=;trkk95*CXEt)bKDAe+rXr_;f1w<DEG!C)}ZI<9BK=FshSvD@u1nM}~@_2BdQ zFdmOlC=@W8%|OiIaKPj7(77-k^Yi%}M5EnqqtR$k4$(84&2)zKdL2fik!tk&eM#+1 z<JwQBQ~3RUY&IM0_j|ZpF3PD?D#+z>zw!rzfh31~52n9fuTia5#WRcF^W@*ScmLPB EFWo=ve*gdg literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-new-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-new-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c6abc4ec57366faa57c41b232866c822a41de8d9 GIT binary patch literal 3186 zcmeHIM@ytZ5S_g*dlE0}f}-Gn8Dv2*jydOms2EXHRLqJABSypkhJ&I9MNu(ez=I+q zVnD<Qdh+JYpYV2GEhC@1GdsiT(T4uMp0B&>RlQeLqlv2cs*>?j_f+fV58eE(n_pDc zy65kq{iafJ>c{>4JwE3r2cJ1$ItR|r&*AUykJQvuBqt{$F)<PG@$ra_jfJ0|pTRn6 zYHEU)mlu3}egB$aVPOXED782_IYDl2E@o$EF*P-X(a}*13=E*Fs|y(!85kQI`^yHg zqNAe`5)y*Iz`!??{wwVpS`)LNpa2UC3z(Rgz{to5`uqC@v!$g);-McmH#gYd-$!O< zCISKi1jpOkTi*0RqtVFPT+HI)VzjolA|fIJ>FMdhGdU)|Nl8h<LuhEI>=V<&!vl79 zb~2ruoS;^#WzCq)#Vji;leoy~%E}7n=jSmqGb3>i4-ccSuMZs^9iWaiH8tRQ^2+$q z($d5?;syl;y<%QnT^Z$=+*VXn2%qG2YikRutE<8_<ENe8-d@@7?CeByb2DmdYY`b4 zDfV-6a)cL0M@K|OMTsAId3mU>um2||eJ9@J<fLe}v$KP>wKXg*F3Mf<n4h1I!NEav zcXx{padB~iNx!nPvf$?CCVE;}SYUj7+$bJ%ig7kHG{`yfd3=0~gM$O??(SlJeH}|n zOTw{_j}Kg2Tu@R{B05leS65e5R#r-l+1S{?*49?yG?c5#Z^R^D)6>(U<K^Y0_;Gl6 zh`qf%Y;JC1d3hN<Jv|_2mX?;ncT7x-#7tkTtgJw8ng7f+rF}zdVz#xlff$T|Too1; ziv8^DYy<}fOP#V_i;9Zi?(Pn)Rtx=je0+q1gM-A%+zJm5Hw%;YUS3}C{QQikrzbo- zJmC8JT4F3MEq!C7v9S>w8yk8^(SY^DTCS_BliV^CoAMibAM>HAs!H;=yu2L5Vay2$ z3E;l|Jo^SYWd3e%Z-cqU{Is{X2YVjvkaPX{_r6)5*4EabPjho~uf2%5&3bWmb{5^= zi^Kb8XJ^uXQc_ZIdV2aA18cgvy889^(b19A3iI(jxQxNm(^GQ#Pdn_D)KK~T?(R-B zV*giaqC8`2&HtK<i;FjQ^>?UgdwaXVJ?hTB%RJPd|A;qxFnf|QTer8jM)!=}G4*|D XXh{07sdFE>Prd$Evyb${TwA{Y*~5!3 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-new-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-new-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1868eb4c99fb43390fed0f469e484ddca58f8253 GIT binary patch literal 822 zcma))A#8&{6o$LZlLa+3xh#_t6_XQlvlSDFii(Pf3Pi<;2}H$21)>5`fjCitKp;*a zP9RR4XcGhifj}S-h$mk50?n2Y*6@XUdH4RG%e}jMd7EBOTBZ~qXxyB~)#SFVPtJNb z>Eh{hnp@WRZ`rbQ-Si?#DaUchYuhWv);NNys#-Jiyj?R6#@J@F+3)xC?-<DJZnxa` zi=xQ$yo;3l2bn$3I~)!dd;Jy3%sCIkKx<7W@Dsa)Dm^&&!!V4ZNJ{x7w2%oU7YKqN zj>X*9w$RV2T&nb4>UE?<3$4?G%1M&UqRL3|v1!bvF#zpE(>jBY`7=tNL}^ywATmS~ z;6)u>pV}h)9@LjD>U#-hjSEBz(LkI5@~j|<==GarSy`5rY>Xq)PVUGL7{l=6006q6 jx~@NBSf%iq;-bWP0bWkZ0OTa-J$G7=W7gn+?{DcFYfM`k literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-new.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-new.bmp new file mode 100644 index 0000000000000000000000000000000000000000..36f32eccafcea3d46d20b471acef49e5a6570c50 GIT binary patch literal 2430 zcmcgtA&je76zzVu2*ilVW;R=~;%8GaVnjv77bBX@Pqw0>0)eQgs2DM#qM~9%#Rx=2 z1p<MnKp+qmhzhbnAP@*Pc>;lW0)aq0@x;v@%1qnO&Ln@b**&?uz=L-<_q@yH{*Tp< zog?}ff5Y($j-PS-(D?~tr}I1R|EV^|aRS3%{|){ZUR~Fk&?b`)g!ZyZ*Y#8KXT8%S zG))_gMh_43<#z)L#^Z6bd^Vjn)MwuLe2#l~C`l6f2&$@rhT(7sy|dY@&HMQHsB4;O znjhhOdA2OeUaxn5e-CAC-sNJk-|x$^5Z?l8z6Y-3j7Ot4cvq{H=XsoS<aLQW&rcbM zsw_A!Imd`N0q3@5!RI%8Sg+Tf=Yj>25e;y{7<=KB61+Uia>km-GIop%*lsquHo=Cs zeJ~8ebzQKWR5T}16rJ>v6h)q~BtfJXk+bx9y`Jj&VzFrRZnqo9andxY-+qC^;c(_9 zl2yUtI1a-mvNWl9jzm_=B}{;sZC+HuZnwh{NWKJ2fAs;Z61;I31ip`8aU`n}lXw6Q z05G%7Yuh$>!!ShsHt_3o6HL~;SX+nSX>#y9-*Z_M9!Zb$L@)uBy4h^nyf9(6vx6Xj zWMF>aw~+|q<fWpIyrSR%Hg~r>crKi-l{W7qnoP#a<q{9Kd6BPa?|k2fWIIZfkd%Zp z#<8D`UYN+!*tINsYaUz&hP)<G-^cd`b1lni^Mdh<8G^2#Rkul|RD>Ak#Z|~Y6V0Ja zRH5fshG80p@7QM(Aem?|=&zriU|O3O`#v=6T4qUVo~uHrL}OOJ;Hshn77H2suJ!!9 zT|dPKkA%QXEg2)xZLfz-L#4KPk^bDYm4K;2s#0EYJ{01vD8YV{mAtI59vXQXWl<o@ zqNcmx{k7YLWBa|=<~4%sI+QAx5PMx!(@Ho(421Z?vO!*`1ug4z-^I<%jcr@l_BOAw zA;pIS1c7%_W<pj(Yay<PRCpcGr?2#B6rwwSeFgTa0VY&MLEA!Iwt25@uDF%TXn>*- zG9W^XWbFyWg17He2t(chiVQoC530?ZX1Q)UeJ}2E>Pngs^@y&IVv)q6c-H~kz-Ny< zK#I22=0yYBM!Dh=N@5!4(5Rv?vO-O2e;$&e`3V0xLZ+^3sNALnwt3OKbx*+Mu2<bz zff|q+lIo?387Ve>HZx?}08Og}l)<U@w|ViGuu@?$!Adbs1h^E7j8sOYFjC>?-~L73 ixoSu;p8uP;K(}g;p#ZitwCeu#A-v6dn*H}DoxcH%=obnA literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-refresh-dis-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-refresh-dis-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2745af15100cfbfccc2099a25c12c08c1fccd889 GIT binary patch literal 1014 zcmd5)OUof(6gJI%W`4pfKYjpNnvE<(Aq&^!vOp=K+;3kJN=R}`xg??7QWi>$g@v*p z|75n$IA>!2O-;?I=Y8LL&w0-CyyyL){PkJDA%3iH4}5#z>jR$z-yiFr`1wU3AUxxK zzvEvZ9*^U6I{h`b*=&ZvV8CLrfW=~gUayDMYDF@c#O-!_@m{Z2TrQUv=x#orBNPfD zl}f>8v%%$Z!DKSQ@At#uaKLW2zv{EuECPW5+-^7LMx#*>27>{*-7cSnLLtOrF=R3s z^OBxIp}-vFavAUM@9=uP%&XJsxZh^8LA%|C$K!!WB!W~bMKBnIMxz0F%jI%hU#rzv z=Xg9utJUIuYPA}2xtu}y5{U!~g@WIKv{fn<(EHNd8jS{u#Ui%bEhdu*_f)A=I2;b_ z)#-FXsZ{cLx7%U8UL&1OW53^XJ!z~~t5~g8APwZ1yeyYXzK_LXFdB`>=kr{9JRT7a zhxv~B_j)~?&u7eLGxYm?_<TN0r&B~C5%ylM*HJ2!Si4rMWsXcH^Qxyl#L?+=&}=q& j-p~Iy91cPK6Nv<9PNUI?XGA`pIUn8WzkIajf6o66A1T;2 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-refresh-dis.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-refresh-dis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..45f8099b9279359191b82f0bfb504313e66214aa GIT binary patch literal 3186 zcmeHJM@waC6m<5(^hy*1ilUek=B!8?+A&AWIR{h}MT{6*K`@{#V#JIYQEXIHYy?Fy zqPTI_JAXorb%yuwwX>S0XEAu;d)NEE@18oRs?K@({#o|Bnp}=ApC&I$_ho6ntl!l1 zUq1i7j{Z<n<5FCAcXxPSsvOMC&7r-${XgX;E-nswdU}|hoqdCQbaVvfbbNgLX76XT zGdDL!K|ujbO--@4w}<odb0j7v!rIyzHa0eJc6Nr9m6hxl6&2z1^z^6j=jZ3)>+6e} zni}Nf<iNth0?Z*aG!*&y`SM+6W+u|o(vXyt1RozC7#ka7ZEfve<1!9&Z*FczLqh|y zv$IiAQGxREas&qlOO1Yhen?MGSK`OV$HU0T2pbz4D!8nlIZ>;am>5JwMIj<00%2ic z@b>mrp0%~LMNdx;y1Tp4+1ZJ<wl<0V;ll@*n3%xH$w_M0)YO#snIG#<PEHoyudc3? zu})4-kdcvriHQje4-ccSuTSE(wzdjK{r&w|TwFv*NC>`s`GSFg0rd9vD)Gs&y}dnH zBbS$#muOmCTr4~!BqYGl&`@G1yhKduLoW^u4N1JNt}YO>zP=vr?(XpS_eV=h3nnKg zF*Y`ak&zK4KF?}sXu!qAMKH-3{p;Z108dX(1O^6TcXt<CTU#o1(u>sS)2C13L-I_H z$!~OYw0L1<Wd#ch3;6u`GqSR>;O6EAeSLjsX=y=6M@N>TPM+i6%!7V5Ffb6lU)Nbu zQX+LxtEHtS%*@P4J*>O3vJ&d*>e3JNDZLmF5CHmv9*vBQgq@w8V6%6*PaT*S>tIYi zkB*M2)LB+m269B5Ha9o1yu2)2kB^Vb+^MUpLrO}D^hRuKtaz)mv=n)Hc}Pu7g|4nH zs;jFpJw2_$KXa!3^xyUMwF)L{As#)#UMKgftE*s764%kuQS#=j;hb@Gb(Lr4N?oW0 zai^xH#4FTOf#1>5AzUbU<((d4pAQZW3ZLJ;eZ&6#KDM{FrJtz{dxtq)US7)VAs1$5 zW(W@tms-g$eZ+IzTVG!X^{3zITl(%tOmauQspG}Ph2(K?aDbhi9qDK0O@4U4zrV-r z?JdsE&LmfQnwYHd@bFMP{q^ft$(i`<qnn$XH<(RLO&~^LVWDu9o0|*89Q*k3qx32J z#?sOf%#XN_kB>@x)=xa1)z;QVZEdYQv$r^BUe~DLmc97={EYA4zvJoY2@eks;N0NM zVs9(n;dhOVjWT!0D`y`y_3-czU(;vox1gXP;f;MyKPcW;+&TMRzfV6Bhc%P4fBJ2x ws;ZJb_8{jzb>vyb;mjxRoF&xbM_v`Uzv50!*-O77_Ipg#|E1pf`2X_p7kq&=RR910 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-refresh-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-refresh-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cfee8f71b7a9e6d9db3697f8a09e9f63cbd120ad GIT binary patch literal 822 zcma))p>Kmg6vn&EO^{`xS&$QC=^s!rF)_Jh6%`c~6%`eTiU~wT1p<LMQGr05IB^1j zIDtSQ5GN`sCTN00R8&+{AP~#G^+>a|S;sH$9=UfP?>@MDdFx)c4s?+pF>dQ|)w(~_ zTlKn{s5~Bzn#X#*o|-0OtSrmVizG<`CBm|-f5obk<2Vr8_I%$AN-4y|b+^rcZHPV3 zE1D4m9AdncWm%r*KQpGPg5r@d3?W8d{lW4#LWnR3;y6muL`pf~CJ{u+R7H9Qlz_&x z?donwG@?(r)u%%ekhmr~JdwWxM}QvjGU|BUXTLW~-GLZuwm$Sm*!l<zE3hvNJ`m&8 zA7n+2Q%g6?cRn}i)Mq}gVVu_iF}}S=`&MEX`wb3pTkZ_@bYtJiTyD-#e_dpePK=p! zoYi8OOyG@uu(CS6PE}Ryc3Xrjq_ODGjKO)Bhnm|KnZW7^a0_rh0i5uRYt9`yU$~@7 F`~_t)MC1Sf literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-refresh.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-refresh.bmp new file mode 100644 index 0000000000000000000000000000000000000000..54f1a01b261c791b9f9d62d88ff498543f7568fa GIT binary patch literal 2430 zcmcgtA<U~*810@|vI;~+vvgU-Fa9hQPdrh9sHkX`Cab7GASx;<5ET^&1fl{_fj}S- z2m}IwKvW<QWI-Sh2$moa2*eeLii!%d)AIkck9EuYvur0HH<t_d-1D9LU6}qR{?NH$ zjP@5?KjZod*LR&C(RMn&;`#4XeccAo{PEx5f8kxN*g9B-`9QF5voN<w{;qd@1Ix0D z#eBQn3f~MUST2|K^v!x*Q{Q<xj>9v&6vuJ(5u8pZXqe4r(EEgUx7$IiX__D5e0#Sn z%h6~wolc>wtykdr<MBucIe!hz`4-rgwOlNo@QR}7I8IR%$m<b#o;MksPbDdevMA6Z z8lZ3JI(*)2Hf_C<Bsq=^7D#?Xk|b}umkW4{EX&ihjx0-?P!(mxGTSZJ=9T4xZQE&@ zHY(~)7>14B>T)J|mc}t6d5Ans4wAH9t$3bq^Qx)>kDv~cvm4L>JkPuHR@LQ1(kP08 zppGnwPeqPIL_vTFFtg38X&Q<FQy>}aXluaqcOSrdxs)UdeBX5uX%t>gB?j>V8~|Wu zo7XT5(=>u0K>a=f<5ynHy~epnV%M<|X&Br{Z{t-36Huuzv&{<=!0Y=yBtHUqG`we0 z_}E<2^c)*bUzOJDRTa)0%!Qe4UgQgDuIoaw8@Q^Y>POx4Jz17(UYJ-Uk)>&ds(H2r zqu-ObKF4_z1OX!2ykOLIoinzs@2RfZl_*N=@dl41P|lzLZ(v)REF)aYxSIgURYlX| z{a(b&ZC>pAOqq2>3e@1G<iYFVvtp}LYepM%k|x#p61ld1kktJ?@|@~?e$@MUG{UCA z%r-C5A0O!MzTcN#Ovj|u;aHxmZH`j=SZu0J3e*$MMG|JAkE*~j*ML~GRW%$Av1!Mn z)8@rq!3S1Z_mx*QFp@0u;$UEou*~={St}b<>^0%PL9f@tbR^y8?aI^_jb^Pi=x~nV zDIujBd0UMaOmS~Xs;Vw-n7;#i)!_S2pRn@~_ZMD~qV@yoFwDyw<quhCJrYvJfKmro zRd9tU3tOkWxy7#lJCCE(=A9e!<$+y@j7jV!SHBFm!R|#Fb;T|haOo*+9zAw&?D3bW zzX5Gt<SqwFPajgoOOmHx^kSc~hO{-)LY=qxmAML|@bM_teaK`O29--lfoSsvdC*m; zuGIgsrzg^!GKY+`qSYxXq`RjWo<Z5;L_GzZZNB|&-jt+MbM~UVDzUl?1uU>Ra^yt% zhatu{-UhyZ{U>>HSCgW>|2J{t<sKjK<V<GAIck<RCNME3G3RqZ@lQoodyRd5&fARs H`%dRiaJALj literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/tk-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1e099e6f18ef3890f084838575e4a71cbce42b21 GIT binary patch literal 822 zcma))Ar6Bu6oy%Lfyo_VC)fezcLl`c<ix~8B?5`4KvW<Q6^M!o#KZ&wfxwVVAP@)y z0x^MD_OB&d(q*Jy+LuTBJ<<o=?YB!uu|?cquBN$g)@t3E_Vt5~RaG5a*M1xoA*J_O zilXp55AOMVBINS4pznJn6UM@a9fT0y_oFC6tqqWA5b!u|+qP*M9g+M4GGi=BlG$Fr zn~*u@Qi`%H@dZ9nCs;AyJeE?XX_{r(HOn!O%piog-LC(@dkkRa3KZG^x2|iPmd4x| p=nJPcfC*ohApgba7iQOW7I)#TjN^zOGz<e08(;$5XB+wByZ{dmX(Ipt literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/tk.bmp b/krb5-1-6/src/windows/identity/ui/images/tk.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e689cb830bde150c95e6390d225620fe65ce655e GIT binary patch literal 3186 zcmeH|T};zw6vo-rZk+qfb^%M=k}YIrUu=O*F}UIQ66gx@VG(Q#<*O~Uw0{`!bB;|E zWQcP_Hz9(e;uMr2O2=T+jxnWBD3l_gAR;O;A=#E?H^05I?1Gdf-OaB0CeM5E=Hxs% z=XuU~-;XI+=Cg1D#qBTfynwI3BR(s{{r9=D+{fo3{y9#k6ED0y@Or>A53C9eCpKNr zdbN%SrH&6aYY9!$5)cxG!{Kn7rLxK@{G$}CjMum!C{pegzmyL0%zR3Jy2XwkCMoQ= zf&S7s8Lgv4?mfk>(lWOktK}*9?eF2~il2GByn7K|-;n7RzZ7RemVx~}Q+#Y0qWHof zhVyo^&-S5g>?JTdkv;n=vD@u*b#<ZA8t_+d<E4sD{PuS6%x4yse<HBEYk}KS&W*W7 zw$!!qZfr6#!%iagJ6NaPPDsvHLh?$8E^lOYawb74Gr?6BUQkH*C7F3H!NgPX1w1A< z@aWo<|HPT9Euf^Kjl9omsqUSjqGy^<uS~JE>n5h}Cdh3YL)9`$a?=R1#$m!523b>Q z=j|hXtUT1qiwCc=EHsTLM4vsaQ>8aie)<y9fuqz7+~tt%4wXH(*=@bWcA>G<F@f&l z80p`RqG%pLetMXQ6AnV^2MDa`=heeDo($WJuh9671kd!;<eNFzWMNx%J!hQvIW~Bg zulnv#^~-Jc2ygBDagw6%Z;&UvrD?s+re+uM-wYFV(!qPj26(5opJyYKyj*>aw-U2F z@=%UZqNb&TlEcTjIR1d9kvSS1_c+o&%NJK?DC?eP*X2oy1+SrfoU9AiNjv8v;f#~$ zQ$vIvAH;XPnm50;5tN+m5vSf%NJCpE<uxa`JT*`I!~@Q`<~TWYk6QaIUtXKRRNqc< zOCMW0Z&F~HAV+AdJntgutdrQrAy&kw2|j9PmBKSlqf~@-&_%k=fKq2<Q?7yJYy%s_ z+y+N|NTO0hY1uxs1!lq%QwfMs5Gd*i5Pf`2%;PI@8iJ$)gf}=?lak|6ol?<9-2d%Q zrsn^^HTOIHv%k_kJx{Z3oNRsmq8v7xjYx%hVSh*q`(um@;jI+mtvI3a+SJ@d@k{N4 zhi@{O46{^-(JYZ~lF%8=<QPoEC2hoNwYudf5xXfaLx)_GhfM6uXtkb5m5wl_mUZ$Z WxA=eK^}c)dH+lQy?bHA1fxiH2|MYzT literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/vw-refresh-sm.bmp b/krb5-1-6/src/windows/identity/ui/images/vw-refresh-sm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e3d321ca4d7fe336614a6e6b00c56e21147f594f GIT binary patch literal 822 zcmZXSFO1?q6o<K7a-yQSR5X_n6)T#{iV6e*v7(}4l3RhOIB}u^v7({^fv7-KAXZc$ z5C{YUSy6$gKp-kA5Xch<1OkCTAjo}THci?4<#jTB^YzX9Q}<WrYwNBK>rbBVAJ3Q8 zkGsG1ajss}+V2OojmP8ldVOo?a=C0ao8e$kGf@~SD~h54e%|JJ7DZtcMe%Tmm1X&v z`0u@{$~cabB+0Vu`l#da$aSob?(1^7Ow;%C`Fy=zu%cM?dcAKAnWl*czXFJm=Q;f0 za8RW0`!F3#^K4AlG#w8Cf*^o_B=ghh<T#FD7~Aa@zu(q`p=-KnnL;|E{}$0Sg1D{= zx!dh%7ZFr{@DC(WP2I2z(|ME6^3|twYJ{O!_}Og6K21~nwr%%4T{nay+W9cb7U}Ol zA$~|0>aD7ZPgL@wyKKvl9r5(k{#!0?w=I?=@7%~VA>ox^Nrw1jV+kSMXZb4QQQ)*a zVcC<(L}7fw#Hk1|#4rr0tJ`(EFJAXWdeR?_5=yI?{eDkdD5t5_YDLe%lz3IA1ZM<@ w;Pd%>@hGZ8wU4lnj6jL>NU|2~s`u0B6j))+KZJ2`HK+Vns#ol}8nVXz0ojw=N&o-= literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/vw-refresh.bmp b/krb5-1-6/src/windows/identity/ui/images/vw-refresh.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e87aa3cbc0ba1329e76b173ea9089d895e107340 GIT binary patch literal 2430 zcmchYEsPpL6oBaok|I{D*fiS|fglay#0kWT6$sLhw4!1KVg&-R0)be8K%77z5C{a~ z#0mrgfj}TmkOqN3AZUU>AP|TXh!rPDzh%PQX6`O+)1Q~wxp%Ygee>R%H%sAj^KIfR zdFGEiA9&vLyh*%cP9#3@{+lMA^8(ZNe<S~e>$>GX8?H?LDc)+eQmv@N_x<sByxZ+g zF$u$PHk)<3-RJhK2=o)T=6Uhq`}O<#`xxy7_2J>6)9J*$&{eKquglTtw3QfNpk9_n zqY*(w<4jPw%|=6vcDo&h$BWl5{Ux)ekVZr0-d<$C-#z}m42Q#3s|7>l5+=fdD9q7l zh;^}8EEEdNNTpKY(6-x6+%h~KS%jc+S?%|G$K#RXMh=HPnHh$WOeRw=3G3`Jolb>4 zGt~g1a{K-M*$D1&v6yGGS!m20NTisl+hR1TR<ubzpQkS)EtRU*YPc{sY9J~%2!hpW zMZAN-K+`nBVRJf(kgImew^N1&M0akCz%@{UV1PXvu<E)ljtEs&xh!oq8|n*`@5bHT z9j(A-hMwv=QCzSz-DFr<v-Q=?UFR`iV}bTO51ouvE^SC6wrvwB2POI|I<f1db0eW? z-MH5ET(6R217U*~Ibp%gq{J$BGMQ|*+fu27h2uCXS2F;W)A_)0>Rw~i{Q_OsPz_v= z`Fu{gDwnO+>-BQE%w#ecaV)qI0(#(48!C`aX9|bu;1nKKi*CD9!vLsZnAp%^bRKAx z%Mwt~G%T2_t1F@w<;!QaLCq}NX{Tr{r|nZXKRvcir_FdWHPcbs(9t*|i^W3a0+m8K zmK8M=g@YbNq#5Oc>6LSqWzS}%!LVuBB`RZ>nbvJfI-;mtGD3)23il$H%RxVjE=r;4 z8O`9((nMOTMc=%O{R}7sl}nQ$Btox9!Hst2D@>-<D!mka6n($Z>-EovG{ZoOAgEm0 zMF>!O4&l(^Lc_@YQ200gmPm!W%H3atZMh?a`I<a`ODQhidzH)4OQDguX?%vb?>`lw z(h)`FiVH4hEJ&8087XwA)P=&9Bqv>jqH^WuF0LF72kMBw_%+~KBWys4IQ_V#)KxD3 bi+lOnOa>J3wYOqjK$)L@kLA)|Q4&7@PPaZf literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_collapsed.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_collapsed.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4299854d37656e8af34046a7288c9fdcd5ff0d10 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZ1H%zM2nGuPiR*(Bz+8ug#&j=G(SO_k y(~oHC8yXsrbq|z!pffN5&|w4R9(b4lT?J<o;~r$iSk(h#5a=mf05g6`5&-}Xj2K=3 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_collapsed_hi.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_collapsed_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cb06b8acbffb74d8fc7208bcf2044038cf4230b1 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZ1H%zM2nGuPiR*(Bz+8ug#&j=G(U0x( za3M@T0!4luSr12;Tr?|y3VvTY0!Nr!O!a^6T!bT_dN>=%0CF+a|9$xoD2@pr;+X3H hBLSc;B;J1@cVN{cI|j(cbPv#Zm_CJzpgEpYE&$N+^RoZ| literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_credtype.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_credtype.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3bac3fe5356ebaa52ba3b32cad80f2f95cde1d3a GIT binary patch literal 1014 zcmZ?r{l?4y24+A~1BeBHm>-B485Dpd1RUXGU;tqlxPJZm|G|bYUcC6fy1wCmWnIJn z^4f;~eUqk;<i?XHPySCXZ~WhP;O778?N|PXW|xwzKeN8`|BSQG|2H3g^gptoYS`;f zNJ#i!R$2AGu&nZbMnTE{>gh}1{`bkP{U4BC_}@FF;J<5P{{Q&AGK}zOZ*Twq>g%un zS6_eqfAHal|7)(lhU?GUdG~+Rh8zD~mtFpEIOp7d_jJtoXliPrNPkI5$^TklnyIL* x|6f{N|G%)Z_J2-!&Hs$js{g6QmH!h9EB?pkm;a9jy1k~o2gCh?Ee{au9stj97JUE! literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_expanded.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_expanded.bmp new file mode 100644 index 0000000000000000000000000000000000000000..76ee5b016d83fd71f1bcdc92a204eae9607d71b2 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZ1H%zM2nGuPiR*(Bz+8ug#&j=G(SO_k h(~pBweFHWC^wv;uKdu<SbU!c#fr7XIX8e*Q0stN7Axr=O literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_expanded_hi.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_expanded_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8180b33337d8a120782268a15105acd581e7e1d5 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZ1H%zM2nGuPiR*(Bz+8ug#&j=G(U0x( za3M@T0!4luS&s{0RsZ|a5nKqX`agFr;zC%}|9$xoD2@pr;%Ht5D*KNc0A&ZcdZ6<# MeF_&rb3CbB0NpSIU;qFB literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_flag.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_flag.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c563c56e9f04b8e5cd118bcc4a2728b9d28099f8 GIT binary patch literal 1014 zcmbu6-77<39LFd3_!FeWQbO4-l$c9K@^Ygn%;_u+I~hY>c7e@}Q?eOxv$dv~rLoMi zE2osXn7t)$7mA`xDK5XxIXbI}spD7Q=lAqH&*%I6e$S&)zvs$?P;g@@rvgs-oN{D^ z-1rqIc`_L<F_Ot7{*u$_{PRpU50WGikH;l@xLht+EEdT;UmHOX|Kd$16a0R^WRFNB z0*ay}^L!69O(Pr*OZITP-RRd0WaSS70ijR6Uhz+((I{4|HmJG?6jxNI*TsE4vn-2| zQ9X=|6-Ju_#PkAsMrY7LO`=gdfi`9r?Vcp$>TWO$li|VNMGjJkKcsN>@P?z?6t)x3 zSUZ2jB72Xq<2z^$t^~f;#-dVLlfj$KW?Wp};QHkQr}wY$Uq1cHH#njwQr06F3<@56 zZw7+_F3%ol!xVJ-aZJw6VT7A&^;761Y4qCm)A#edT)%;)mR5nc+wIWlbntq;88wM- ulSm}6yt0bsz9H1nOHj=3plo;<CFNC!#bQ4)BKtjuLLsbgZo%jCrMXXo2o3T8 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_stick.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_stick.bmp new file mode 100644 index 0000000000000000000000000000000000000000..071a238c4d9fe2ddf0c475d1803a2776db76d5d7 GIT binary patch literal 774 zcmc(ZOA3HM3`47eTU~ktPv8OEdv|vpXABc4bpq0r7Ml6+(q=!#!D?;L6+NRTbY~0H z?Ck6Dkn4{^g8W**r4)wFxSXf!-4bE&v~U+xy~@)?RZE5k6N?$*Sib{nBH`y_K1OZA S@EId%V6`}(fqjL};m-}3SO&fT literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_stick_hi.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_stick_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8857fec2207fad491c611187501d8dd5e2bcf147 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZm_i}04+H?ZfOu<xihpdM2XQnpx_~Nw z9a#_8g<lI$+3!n7AX<RBAR2*O2*A_}6#sMQB9H{?!bCuEG%Y}pzb_v`bOAM@A&7b) zi46Y#{}1E>bzvf)IHvg!^*|C6&_X@3Q_&m);Q|!^T>>YuszDZns{}HT#qqH5s009^ C@cUl? literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_stuck.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_stuck.bmp new file mode 100644 index 0000000000000000000000000000000000000000..68295181d54551f38d7ae37a326dd285cd71542c GIT binary patch literal 774 zcmb`CK@vbP3`K((Tb7RC1P);D?sksD*RP#OwG1+oG)dq8YMkmyTnwl^vPCw?LON8D zxpc>=EPq6Byfq`a`rw#R0r2c`VsptGXRV4Qv}M&K`;WY~)qUPP+-eDWg!x}=%$psx f7wl0DkC9hKm4aXJl<2RZN5n5N8)8pLBTS7O`9Kui literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/images/wdg_stuck_hi.bmp b/krb5-1-6/src/windows/identity/ui/images/wdg_stuck_hi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3b780712914f23410e4d6925e485edb8cda6f6a2 GIT binary patch literal 774 zcmZ?rWn*Rl12Z700mK48%n!tj3=%++f#CuZm_i}0Qv<+FBxo2!<&W+2APB<6qYJ3u z*OB#b1k?o-!Kxl&)bC42FcGE}pa{gMKX)!-BCP6xZUBn^efba*p{WOQ;cfu3|Dysl z#X!FRMc{4#vVj1u1Hwh~FHjK84G?7zaUhAN9%2RDOk@UD#bl_5XaSlAHyp?Y0!){n Oi9nPQqY_OcE-nE4K?Gj_ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/khmapp.h b/krb5-1-6/src/windows/identity/ui/khmapp.h new file mode 100644 index 000000000..ba036c649 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/khmapp.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHIMAIRA_H +#define __KHIMAIRA_KHIMAIRA_H + +#include<windows.h> +#include<windowsx.h> +#include<strsafe.h> +#include<commctrl.h> +#include<htmlhelp.h> + +#define KHERR_HMODULE khm_hInstance +#define KHERR_FACILITY khm_facility +#define KHERR_FACILITY_ID 3 + +#define NOEXPORT + +#include<netidmgr.h> + +#include<khhelp.h> +#include<intaction.h> +#include<intalert.h> + +#include<resource.h> +#include<credfuncs.h> +#include<appglobal.h> +#include<mainwnd.h> +#include<mainmenu.h> +#include<toolbar.h> +#include<statusbar.h> +#include<credwnd.h> +#include<htwnd.h> +#include<passwnd.h> +#include<newcredwnd.h> +#include<propertywnd.h> +#include<configwnd.h> +#include<aboutwnd.h> +#include<debugfuncs.h> +#include<taskbar.h> + +#include<reqdaemon.h> +#include<notifier.h> +#include<timer.h> +#include<addrchange.h> + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/lang/en_us/cmdline.rtf b/krb5-1-6/src/windows/identity/ui/lang/en_us/cmdline.rtf new file mode 100644 index 0000000000000000000000000000000000000000..bc3356586f6222d2c4c00cedb4b218bf9343850c GIT binary patch literal 1252 zcmb7D!HU~35bZf%G3Qb*cCzWh?kUhh15FD}OE0=iB-t5OmW-s-Nkjg<Bgf7rOA}Zy z!Ww(t(|dZe7e1DSKpUuAWK$L6=~yUTmU&tY+N#JWlf5XNjd5l8B^PCADFji<HTs}q z4l_?^o(_l6Uc48Tw%TKK9u}dDT2X}Q-F<OaO!>(lo(|#<>Gqkdx)&Q+hz7knqK<R; zxz_Ma$JY60m@91~#T_irVx>J`(-@K%$yq=tbrS<bZYZ5Gt|eQ6bajnZWrnN<*Q7tg zV`3Pc7UrU?m`rnFsCX!H5x0|%Y3(*E$VjYsi!1oPibxi$Zb5q89R^LfJ0hhYW`;0m zCg6?W&WuG-<aPj7pDIJ)#6C(@JT|azo9JrRBhi>0q-OS!{^|=pfO!elo!0<;QoXT? zSKoQSmxUV>fqK(EaFqfm3XQ?t(Wh5R_#+xu-4cX+z}K42YL~M7VB8N*K>OcQ-Qx18 z>)gDdaLG~+Ec3c?K3>>TdRKS6zd2p54X{{#UCuzFT<crZ)Iptd_mxv}GBw=UCmo`9 zyEn^IeP3ef)6th+^kv(D<@1)uCS}`itWC)#8zNfCsV=V$$SsMQ0nY_?`xkjx&DUIW z^wePQG9tTsbryLrPAyP7HTc^>rde2X5(lg={NAa#3dhsS7uE|nVT83yiAbivFPjkG Jh;kUc`v<GqxZwZ* literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/identity/ui/lang/en_us/khapp.rc b/krb5-1-6/src/windows/identity/ui/lang/en_us/khapp.rc new file mode 100644 index 000000000..b851ffe88 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/lang/en_us/khapp.rc @@ -0,0 +1,869 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\..\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\..\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN_APP ICON "..\\..\\images\\main_app.ico" +IDI_ENABLED ICON "..\\..\\images\\enabled.ico" +IDI_DISABLED ICON "..\\..\\images\\disabled.ico" +IDI_NOTIFY_NONE ICON "..\\..\\images\\app_notify_none.ico" +IDI_NOTIFY_INFO ICON "..\\..\\images\\app_notify_info.ico" +IDI_NOTIFY_WARN ICON "..\\..\\images\\app_notify_warn.ico" +IDI_NOTIFY_ERROR ICON "..\\..\\images\\app_notify_error.ico" +IDI_CFG_DEFAULT ICON "..\\..\\images\\cfg_default.ico" +IDI_CFG_MODIFIED ICON "..\\..\\images\\cfg_mod.ico" +IDI_CFG_APPLIED ICON "..\\..\\images\\cfg_applied.ico" +IDI_CFG_DELETED ICON "..\\..\\images\\cfg_deleted.ico" +IDI_ID ICON "..\\..\\images\\id.ico" +IDI_APPICON_WARN ICON "..\\..\\images\\app_state_warn.ico" +IDI_APPICON_EXP ICON "..\\..\\images\\app_state_exp.ico" +IDI_APPICON_OK ICON "..\\..\\images\\app_state_ok.ico" +IDI_CFG_PLUGIN ICON "..\\..\\images\\cfg_plugin.ico" +IDI_CFG_PLUGIN_ERR ICON "..\\..\\images\\cfg_plugin_err.ico" +IDI_CFG_PLUGIN_DIS ICON "..\\..\\images\\cfg_plugin_dis.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_TK_REFRESH BITMAP "..\\..\\images\\tk-refresh.bmp" +IDB_ID BITMAP "..\\..\\images\\id.bmp" +IDB_ID_DELETE BITMAP "..\\..\\images\\id-delete.bmp" +IDB_ID_NEW BITMAP "..\\..\\images\\id-new.bmp" +IDB_ID_REFRESH BITMAP "..\\..\\images\\id-refresh.bmp" +IDB_TK BITMAP "..\\..\\images\\tk.bmp" +IDB_TK_DELETE BITMAP "..\\..\\images\\tk-delete.bmp" +IDB_TK_NEW BITMAP "..\\..\\images\\tk-new.bmp" +IDB_VW_REFRESH_SM BITMAP "..\\..\\images\\vw-refresh-sm.bmp" +IDB_TB_BLANK BITMAP "..\\..\\images\\tb-blank.bmp" +IDB_TB_BLANK_SM BITMAP "..\\..\\images\\tb-blank-small.bmp" +IDB_VW_REFRESH BITMAP "..\\..\\images\\vw-refresh.bmp" +IDB_ID_DELETE_DIS BITMAP "..\\..\\images\\id-delete-dis.bmp" +IDB_ID_DELETE_DIS_SM BITMAP "..\\..\\images\\id-delete-dis-sm.bmp" +IDB_ID_DELETE_SM BITMAP "..\\..\\images\\id-delete-sm.bmp" +IDB_ID_DIS BITMAP "..\\..\\images\\id-dis.bmp" +IDB_ID_DIS_SM BITMAP "..\\..\\images\\id-dis-sm.bmp" +IDB_ID_NEW_DIS BITMAP "..\\..\\images\\id-new-dis.bmp" +IDB_ID_NEW_DIS_SM BITMAP "..\\..\\images\\id-new-dis-sm.bmp" +IDB_ID_NEW_SM BITMAP "..\\..\\images\\id-new-sm.bmp" +IDB_ID_REFRESH_DIS BITMAP "..\\..\\images\\id-refresh-dis.bmp" +IDB_ID_REFRESH_SM BITMAP "..\\..\\images\\id-refresh-sm.bmp" +IDB_ID_REFRESH_DIS_SM BITMAP "..\\..\\images\\id-refresh-sm-dis.bmp" +IDB_TK_DELETE_DIS BITMAP "..\\..\\images\\tk-delete-dis.bmp" +IDB_TK_DELETE_DIS_SM BITMAP "..\\..\\images\\tk-delete-dis-sm.bmp" +IDB_TK_DELETE_SM BITMAP "..\\..\\images\\tk-delete-sm.bmp" +IDB_TK_DIS_SM BITMAP "..\\..\\images\\tk-dis-sm.bmp" +IDB_TK_NEW_DIS BITMAP "..\\..\\images\\tk-new-dis.bmp" +IDB_TK_NEW_DIS_SM BITMAP "..\\..\\images\\tk-new-dis-sm.bmp" +IDB_TK_NEW_SM BITMAP "..\\..\\images\\tk-new-sm.bmp" +IDB_TK_REFRESH_DIS BITMAP "..\\..\\images\\tk-refresh-dis.bmp" +IDB_TK_REFRESH_DIS_SM BITMAP "..\\..\\images\\tk-refresh-dis-sm.bmp" +IDB_TK_REFRESH_SM BITMAP "..\\..\\images\\tk-refresh-sm.bmp" +IDB_TK_SM BITMAP "..\\..\\images\\tk-sm.bmp" +IDB_HELP_SM BITMAP "..\\..\\images\\help-sm.bmp" +IDB_HELP BITMAP "..\\..\\images\\help.bmp" +IDB_LOGO_SHADE BITMAP "..\\..\\images\\logo_shade.bmp" +IDB_WDG_EXPAND BITMAP "..\\..\\images\\wdg_expanded.bmp" +IDB_WDG_COLLAPSE BITMAP "..\\..\\images\\wdg_collapsed.bmp" +IDB_ID_SM BITMAP "..\\..\\images\\id-sm.bmp" +IDB_WDG_EXPAND_HI BITMAP "..\\..\\images\\wdg_expanded_hi.bmp" +IDB_WDG_COLLAPSE_HI BITMAP "..\\..\\images\\wdg_collapsed_hi.bmp" +IDB_WDG_CREDTYPE BITMAP "..\\..\\images\\wdg_credtype.bmp" +IDB_WDG_FLAG BITMAP "..\\..\\images\\wdg_flag.bmp" +IDB_FLAG_WARN BITMAP "..\\..\\images\\flag-warning.bmp" +IDB_FLAG_EXPIRED BITMAP "..\\..\\images\\flag_expired.bmp" +IDB_FLAG_CRITICAL BITMAP "..\\..\\images\\flag-critical.bmp" +IDB_LOGO_OPAQUE BITMAP "..\\..\\images\\khimaira-cfg.bmp" +IDB_IMPORT_SM_DIS BITMAP "..\\..\\images\\import-sm-dis.bmp" +IDB_IMPORT BITMAP "..\\..\\images\\import.bmp" +IDB_IMPORT_DIS BITMAP "..\\..\\images\\import-dis.bmp" +IDB_IMPORT_SM BITMAP "..\\..\\images\\import-sm.bmp" +IDB_CHPW_SM BITMAP "..\\..\\images\\chpw-sm.bmp" +IDB_CHPW BITMAP "..\\..\\images\\chpw.bmp" +IDB_CHPW_DIS BITMAP "..\\..\\images\\chpw-dis.bmp" +IDB_CHPW_DIS_SM BITMAP "..\\..\\images\\chpw-dis-sm.bmp" +IDB_TB_SPACE BITMAP "..\\..\\images\\tb-space.bmp" +IDB_WDG_STUCK_HI BITMAP "..\\..\\images\\wdg_stuck_hi.bmp" +IDB_WDG_STICK BITMAP "..\\..\\images\\wdg_stick.bmp" +IDB_WDG_STICK_HI BITMAP "..\\..\\images\\wdg_stick_hi.bmp" +IDB_WDG_STUCK BITMAP "..\\..\\images\\wdg_stuck.bmp" +IDB_FLAG_RENEW BITMAP "..\\..\\images\\flag_renewable.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MENU_BAR ACCELERATORS +BEGIN + VK_F10, IDA_ACTIVATE_MENU, VIRTKEY, NOINVERT + VK_UP, IDA_UP, VIRTKEY, NOINVERT + VK_DOWN, IDA_DOWN, VIRTKEY, NOINVERT + VK_LEFT, IDA_LEFT, VIRTKEY, NOINVERT + VK_RIGHT, IDA_RIGHT, VIRTKEY, NOINVERT + VK_ESCAPE, IDA_ESC, VIRTKEY, NOINVERT + VK_EXECUTE, IDA_ENTER, VIRTKEY, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NC_NEWCRED DIALOGEX 0, 0, 301, 167 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "UI Row2",IDC_NC_TPL_ROW_LG,7,31,287,18,NOT WS_VISIBLE | WS_BORDER + LTEXT "TplPanel",IDC_NC_TPL_PANEL,7,7,287,153,NOT WS_VISIBLE | WS_BORDER + LTEXT "UI Row",IDC_NC_TPL_ROW,7,7,287,18,NOT WS_VISIBLE | WS_BORDER + LTEXT "TplLabel",IDC_NC_TPL_LABEL,7,8,45,10,NOT WS_VISIBLE | WS_BORDER + LTEXT "TplInput",IDC_NC_TPL_INPUT,54,7,240,13,NOT WS_VISIBLE | WS_BORDER + LTEXT "TplLabelLg",IDC_NC_TPL_LABEL_LG,7,33,146,10,NOT WS_VISIBLE | WS_BORDER + LTEXT "TplInputLg",IDC_NC_TPL_INPUT_LG,155,31,139,13,NOT WS_VISIBLE | WS_BORDER + LTEXT "&Credentials",IDC_NC_CREDTEXT_LABEL,7,66,41,10,NOT WS_VISIBLE | NOT WS_GROUP + CONTROL "",IDC_NC_CREDTEXT,"KhmHtWnd",NOT WS_VISIBLE | WS_TABSTOP,54,65,240,95,WS_EX_CLIENTEDGE + PUSHBUTTON "&Ok",IDOK,101,142,89,18,WS_DISABLED + PUSHBUTTON "&Cancel",IDCANCEL,198,142,54,18 + PUSHBUTTON "&>>",IDC_NC_ADVANCED,260,142,34,18 +END + +IDD_NC_BBAR DIALOGEX 0, 0, 66, 190 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Ok",IDOK,7,7,52,41,WS_DISABLED + PUSHBUTTON "&Cancel",IDCANCEL,7,58,52,19 + PUSHBUTTON "&<<",IDC_NC_BASIC,7,144,52,14 + PUSHBUTTON "&Help",IDC_NC_HELP,7,164,52,19 +END + +IDD_PP_IDENT DIALOGEX 0, 0, 235, 156 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CAPTION +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Identity" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "Name",IDC_STATIC,7,8,19,12 + LTEXT "IdentityName",IDC_PP_IDNAME,34,7,194,12,NOT WS_GROUP,WS_EX_CLIENTEDGE + CONTROL "Default identity",IDC_PP_IDDEF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,34,22,71,12 + CONTROL "Searchable",IDC_PP_IDSEARCH,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,117,36,74,12 + CONTROL "Custom1",IDC_PP_PROPLIST,"NetIDMgrPropertyWnd",WS_TABSTOP,7,51,221,80 + CONTROL "Always visible (sticky)",IDC_PP_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,117,22,85,12 + PUSHBUTTON "Identity configuration ...",IDC_PP_CONFIG,117,135,111,14 +END + +IDD_PP_CRED DIALOGEX 0, 0, 236, 158 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CAPTION +CAPTION "Credential" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Check1",IDC_PP_DUMMY,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,0,1,39,10 + CONTROL "Custom1",IDC_PP_CPROPLIST,"NetIDMgrPropertyWnd",WS_TABSTOP,7,7,222,144 +END + +IDD_CFG_MAIN DIALOGEX 0, 0, 357, 222 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTEXTHELP +CAPTION "Network Identity Manager Configuration" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Title",IDC_CFG_TITLE,0,0,357,20,SS_CENTERIMAGE + CONTROL "",IDC_CFG_NODELIST,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_TRACKSELECT | WS_TABSTOP | 0x800,0,20,100,182 + LTEXT "Static",IDC_CFG_PANE,102,20,255,182,NOT WS_VISIBLE | WS_BORDER + PUSHBUTTON "&Ok",IDOK,162,205,78,16 + PUSHBUTTON "&Cancel",IDCANCEL,246,205,51,16 + PUSHBUTTON "&Apply",IDAPPLY,303,205,51,16,WS_DISABLED +END + +IDD_CFG_GENERIC DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CTEXT "Please select one of the configuration categories on the left.",IDC_STATIC,21,17,212,18,SS_CENTERIMAGE,WS_EX_TRANSPARENT +END + +IDD_CFG_GENERAL DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Startup / Shutdown",IDC_CFG_STARTUP_GROUP,7,7,241,44 + CONTROL "&Obtain new credentials at startup (if none are present)",IDC_CFG_AUTOINIT, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,20,196,10 + CONTROL "&Destroy all credentials on exit",IDC_CFG_DESTROYALL, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,36,111,10 + GROUPBOX "Other",IDC_CFG_OTHER,7,55,241,120 + CONTROL "&Run from taskbar notification area after window close",IDC_CFG_KEEPRUNNING, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,68,230,10 + LTEXT "Clicking on the &notification icon",IDC_CFG_NOTACT_STATIC,26,87,99,8 + COMBOBOX IDC_CFG_NOTACTION,133,85,110,48,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "&Monitor network connectivity",IDC_CFG_NETDETECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,104,106,10 + CONTROL "&Log trace events to trace log at the following location:",IDC_CFG_LOGTOFILE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,121,225,10 + EDITTEXT IDC_CFG_LOGPATH,16,135,173,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "&Show log",IDC_CFG_SHOWLOG,193,135,50,14 + CONTROL "A&utomatically import Windows logon identity",IDC_CFG_AUTOIMPORT, + "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,16,156,165,10 + CONTROL "&Start Network Identity Manager during Windows logon",IDC_CFG_AUTOSTART, + "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,113,165,135,10 +END + +IDD_CFG_IDENTITIES DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_CFG_TAB,"SysTabControl32",WS_TABSTOP,7,7,241,168 + LTEXT "Static",IDC_CFG_TARGET,10,21,235,151,NOT WS_VISIBLE | WS_BORDER +END + +IDD_CFG_NOTIF DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "&Renew automatically at",IDC_NOTIF_RENEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,9,100,10 + EDITTEXT IDC_NOTIF_RENEW_THR,122,7,126,14,ES_AUTOHSCROLL + CONTROL "Renew at &half life intervals when possible",IDC_NOTIF_HALFLIFE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,48,27,148,10 + CONTROL "Initial warning at",IDC_NOTIF_WARN1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,46,100,10 + EDITTEXT IDC_NOTIF_WARN1_THR,122,44,126,14,ES_AUTOHSCROLL + CONTROL "Final warning at",IDC_NOTIF_WARN2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,68,100,10 + EDITTEXT IDC_NOTIF_WARN2_THR,122,66,126,14,ES_AUTOHSCROLL + CONTROL "&Monitor credential expiration",IDC_NOTIF_MONITOR, + "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,7,103,139,10 +END + +IDD_CFG_PLUGINS DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_CFG_PLUGINS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,75,168 + ICON IDI_CFG_PLUGIN,IDC_CFG_ICON,87,11,20,20 + EDITTEXT IDC_CFG_DESC,128,7,120,30,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY + LTEXT "&Module",IDC_CFG_LBL_MOD,87,43,24,8 + EDITTEXT IDC_CFG_MODULE,128,43,120,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "&Version",IDC_STATIC,87,59,24,8 + EDITTEXT IDC_CFG_VERSION,128,59,120,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "Ve&ndor",IDC_CFG_LBL_VEN,87,75,24,8 + EDITTEXT IDC_CFG_VENDOR,128,75,120,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "De&pends on",IDC_CFG_LBL_DEPS,87,93,39,8 + LISTBOX IDC_CFG_DEPS,128,93,120,34,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "&Status",IDC_CFG_LBL_STATE,87,129,22,8 + EDITTEXT IDC_CFG_STATE,128,129,120,12,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "&Enable ...",IDC_CFG_ENABLE,128,144,50,14,WS_DISABLED + PUSHBUTTON "&Disable ...",IDC_CFG_DISABLE,198,144,50,14,WS_DISABLED + PUSHBUTTON "&Unregister plug-in ...",IDC_CFG_UNREGISTER,87,161,72,14,WS_DISABLED + PUSHBUTTON "&Register new plug-in ...",IDC_CFG_REGISTER,169,161,79,14,NOT WS_VISIBLE | WS_DISABLED +END + +IDD_CFG_IDENTITY DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_CFG_TAB,"SysTabControl32",WS_TABSTOP,7,7,241,168 + LTEXT "Static",IDC_CFG_TARGET,10,21,235,151,NOT WS_VISIBLE | WS_BORDER +END + +IDD_CFG_IDS_TAB DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Monitor credential expiration",IDC_CFG_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,107,10 + CONTROL "Automatically renew",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,20,81,10 + CONTROL "Always show in the credentials list (Pinned)",IDC_CFG_STICKY, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,34,151,10 + PUSHBUTTON "&Add new identity...",IDC_CFG_ADDIDENT,17,120,86,14 +END + +IDD_CFG_ID_TAB DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Always show in the credentials list (Pinned)",IDC_CFG_STICKY, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,34,151,10 + CONTROL "Monitor credential expiration",IDC_CFG_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,107,10 + CONTROL "Automatically renew",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,20,81,10 + PUSHBUTTON "Remove identity ...",IDC_CFG_REMOVE,139,122,78,14 +END + +IDD_ABOUT DIALOGEX 0, 0, 324, 238 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Network Identity Manager" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,267,7,50,14 + LTEXT "Productname",IDC_PRODUCT,41,7,225,13,NOT WS_GROUP + LTEXT "© 2005-2007 Massachusetts Institute of Technology\n© 2006-2007 Secure Endpoints Inc.",IDC_COPYRIGHT,41,23,276,23,NOT WS_GROUP + LTEXT "BuildInfo",IDC_BUILDINFO,41,49,276,20,NOT WS_GROUP + ICON IDI_MAIN_APP,IDC_STATIC,6,7,20,20 + CONTROL "",IDC_MODULES,"SysListView32",LVS_REPORT | LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,41,88,276,143 + LTEXT "Loaded modules",IDC_STATIC,41,76,52,8 +END + +IDD_CFG_APPEAR DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Font for credentials display",IDC_STATIC,7,7,241,137 + LTEXT "&Font name",IDC_STATIC,17,22,35,8 + COMBOBOX IDC_CFG_FONTS,62,20,178,51,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "&Size",IDC_STATIC,62,43,14,8 + COMBOBOX IDC_CFG_SIZE,87,41,48,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "&Bold",IDC_CFG_BOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,162,42,29,10 + CONTROL "&Italics",IDC_CFG_ITALICS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,42,35,10 + EDITTEXT IDC_CFG_SAMPLE_NORMAL,62,66,178,21,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_STATICEDGE + EDITTEXT IDC_CFG_SAMPLE_BOLD,62,91,178,21,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_STATICEDGE + PUSHBUTTON "&Revert to default",IDC_CFG_REVERT,168,122,72,14 +END + +IDD_CFG_ADDIDENT DIALOGEX 0, 0, 279, 95 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add new identity" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "&Identity name",IDC_SM_LBL,7,10,46,8,NOT WS_VISIBLE + EDITTEXT IDC_SM_CTL,67,7,205,14,ES_AUTOHSCROLL | NOT WS_VISIBLE + DEFPUSHBUTTON "OK",IDOK,145,74,71,14 + PUSHBUTTON "Cancel",IDCANCEL,222,74,50,14 + LTEXT "&Identity name",IDC_MED_LBL,7,27,130,8,NOT WS_VISIBLE + EDITTEXT IDC_MED_CTL,141,24,131,14,ES_AUTOHSCROLL | NOT WS_VISIBLE + LTEXT "&Identity name",IDC_LG_LBL,7,41,265,8,NOT WS_VISIBLE + EDITTEXT IDC_LG_CTL,141,50,131,14,ES_AUTOHSCROLL | NOT WS_VISIBLE +END + +IDD_CMDLINE DIALOGEX 0, 0, 309, 286 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_CAPTION | WS_SYSMENU +CAPTION "Commandline options for Network Identity Manager" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,252,265,50,14 + ICON IDI_MAIN_APP,IDC_STATIC,7,7,21,20 + LTEXT "Productname",IDC_PRODUCT,40,7,262,13,NOT WS_GROUP + CONTROL "",IDC_CONTENT,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_TABSTOP,40,22,262,231 + LTEXT "© 2005-2007 Massachusetts Institute of Technology\n© 2006-2007 Secure Endpoints Inc.",IDC_COPYRIGHT,7,258,240,21,NOT WS_GROUP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_NC_NEWCRED, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 294 + TOPMARGIN, 7 + BOTTOMMARGIN, 160 + END + + IDD_NC_BBAR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 59 + TOPMARGIN, 7 + BOTTOMMARGIN, 183 + END + + IDD_PP_IDENT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + VERTGUIDE, 34 + VERTGUIDE, 117 + TOPMARGIN, 7 + BOTTOMMARGIN, 149 + END + + IDD_PP_CRED, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 229 + TOPMARGIN, 7 + BOTTOMMARGIN, 151 + END + + IDD_CFG_GENERIC, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_GENERAL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 16 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_IDENTITIES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 10 + VERTGUIDE, 244 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + HORZGUIDE, 22 + HORZGUIDE, 171 + END + + IDD_CFG_NOTIF, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 22 + VERTGUIDE, 122 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_PLUGINS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 87 + VERTGUIDE, 128 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_IDENTITY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_IDS_TAB, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_CFG_ID_TAB, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 317 + VERTGUIDE, 41 + VERTGUIDE, 266 + TOPMARGIN, 7 + BOTTOMMARGIN, 231 + END + + IDD_CFG_APPEAR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 7 + VERTGUIDE, 62 + VERTGUIDE, 240 + VERTGUIDE, 248 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END + + IDD_CFG_ADDIDENT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 272 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END + + IDD_CMDLINE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 302 + VERTGUIDE, 40 + TOPMARGIN, 7 + BOTTOMMARGIN, 279 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// KHMRTFRESOURCE +// + +IDR_CMDLINERTF KHMRTFRESOURCE "cmdline.rtf" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_MAIN_WINDOW_TITLE "Network Identity Manager" + IDS_MENU_FILE "&File" + IDS_MENU_CRED "&Credential" + IDS_MENU_VIEW "&View" +END + +STRINGTABLE +BEGIN + IDS_MENU_OPTIONS "&Options" + IDS_MENU_HELP "&Help" + IDS_ACTION_PROPERTIES "&Properties" + IDS_ACTION_EXIT "E&xit" + IDS_CFG_ROOT_NAME "Network Identity Manager" + IDS_ACTION_SET_DEF_ID "Set as &default" + IDS_ACTION_SET_SRCH_ID "Allow applications to &search" + IDS_CFG_ROOT_TITLE "Network Identity Manager Configuration" + IDS_CFG_GENERAL_SHORT "General" + IDS_ACTION_NEW_CRED "Obtain &new credentials ..." + IDS_ACTION_PASSWD_ID "Change &password" + IDS_ACTION_CHOOSE_COLS "Select columns" + IDS_ACTION_DEBUG_WINDOW "Debug window" + IDS_ACTION_VIEW_REFRESH "Refresh view" + IDS_MENU_LAYOUT "Layout" + IDS_MENU_TOOLBARS "Toolbars" +END + +STRINGTABLE +BEGIN + IDS_ACTION_LAYOUT_ID "By identity" + IDS_ACTION_LAYOUT_TYPE "By type" + IDS_ACTION_LAYOUT_LOC "By location" + IDS_ACTION_TB_STANDARD "Standard" + IDS_ACTION_OPT_KHIM "General" + IDS_ACTION_OPT_IDENTS "Identities" + IDS_ACTION_OPT_NOTIF "Notifications" + IDS_ACTION_HELP_CTX "Help Contents" + IDS_ACTION_HELP_CONTENTS "Contents" + IDS_ACTION_HELP_INDEX "Index" + IDS_ACTION_HELP_ABOUT "About Network Identity Manager" + IDS_CFG_GENERAL_LONG "General options" + IDS_SAMPLE_STRING "Wxy" + IDS_NO_CREDS "<large><p align=""center"">You currently have no credentials.</p><p align=""center"">Click <a id=""NewCreds"">here</a> to obtain new credentials.</p></large>" + IDS_WT_INIT_CREDS "Obtain initial credentials" + IDS_WT_NEW_CREDS "Obtain new credentials" +END + +STRINGTABLE +BEGIN + IDS_NC_IDENTITY "&Identity" + IDS_NC_IDENTS "&Identities" + IDS_NC_CREDTEXT_ID_NONE "<p><b>(No identities specified)</b></p>" + IDS_NC_CREDTEXT_ID_ONE "<p>Selected identity: <b>%s</b></p>" + IDS_NC_CREDTEXT_ID_MANY "<p>Primary identity: <b>%s</b></p><p>Additional identities: <b>%s</b></p>" + IDS_NC_CREDTEXT_ID_INVALID "<font color=""red"">%s (invalid)</font>" + IDS_WTPOST_INIT_CREDS " - Initial credentials" + IDS_WTPOST_NEW_CREDS " - New credentials" + IDS_ACTION_RENEW_CRED "R&enew credentials" + IDS_ACTION_DESTROY_CRED "De&stroy credentials" + IDS_DEFAULT_FONT "MS Shell Dlg" + IDS_NC_CREDTEXT_TABS "<settab pos=""15""><settab pos=""30""><settab pos=""45"">" + IDS_NOTIFY_PREFIX "Network Identity Manager - " + IDS_NOTIFY_READY "Ready" + IDS_NOTIFY_ATTENTION "Attention" + IDS_ALERT_DEFAULT "Alert" +END + +STRINGTABLE +BEGIN + IDS_PACTION_OK "&Ok" + IDS_PACTION_CANCEL "&Cancel" + IDS_PACTION_CLOSE "&Close" + IDS_ALERT_NOSEL_TITLE "No credentials selected" + IDS_ALERT_NOSEL "Please select a credential, a credential type or an identity." + IDS_NC_CREDTEXT_ID_VALID "<font color=""blue"">%s</font>" + IDS_NC_CREDTEXT_ID_UNCHECKED "<font color=""grey"">%s (Unverified)</font>" + IDS_PROP_COL_PROPERTY "Property" + IDS_PROP_COL_VALUE "Value" + IDS_NC_NEW_IDENT "( New identity ... )" + IDS_NC_CREDTEXT_ID_CHECKING "<font color=""grey"">%s (Checking...)</font>" + IDS_ACTION_OPEN_APP "Show Network Identity Manager window" + IDS_CTX_NEW_IDENT "Obtaining new identity" + IDS_CTX_NEW_CREDS "Obtaining new credentials" + IDS_CTX_RENEW_CREDS "Renewing credentials" + IDS_CTX_PROC_NEW_IDENT "Obtaining initial credentials for %1!s!" +END + +STRINGTABLE +BEGIN + IDS_CTX_PROC_NEW_CREDS "Obtaining new credentials for %1!s!" + IDS_CTX_PROC_RENEW_CREDS "Renewing credentials for %1!s!" + IDS_ACTION_CLOSE_APP "Hide Network Identity Manager window" + IDS_NC_FAILED_TITLE "Failed to acquire credentials" + IDS_CFG_IDENTITIES_SHORT "Identities" + IDS_CFG_IDENTITIES_LONG "Global Identity settings" + IDS_CFG_NOTIF_SHORT "Notifications" + IDS_CFG_NOTIF_LONG "Notifications" + IDS_CFG_PLUGINS_SHORT "Plug-ins" + IDS_CFG_PLUGINS_LONG "Plug-ins and Modules" + IDS_CFG_IDENTITY_SHORT "%s" + IDS_CFG_IDENTITY_LONG "Options for %s" + IDS_CTX_DESTROY_CREDS "Destroying credentials" + IDS_WARN_EXPIRE "Some of your credentials will expire in %s" + IDS_WARN_TITLE "Credentials expiration warning" + IDS_ALERT_MOREINFO "...\nClick here for more..." +END + +STRINGTABLE +BEGIN + IDS_WARN_EXPIRED "Some of your credentials have expired." + IDS_WARN_EXPIRE_ID "Credentials for %.180s will expire in %s" + IDS_WARN_EXPIRED_ID "Credentials for %.220s have expired" + IDS_WARN_WM_TITLE "Network Identity Manager is still running" + IDS_WARN_WM_MSG "Click the Network Identity Manager icon below to open the application.\n\nOr right click the icon to access the Network Identity Manager menu." + IDS_CFG_ID_TAB_SHORT "General" + IDS_CFG_ID_TAB_LONG "General options for this identity" + IDS_CFG_IDS_TAB_SHORT "General" + IDS_CFG_IDS_TAB_LONG "General options for all identities" + IDS_CFG_IDS_IDENTITY "Identity" + IDS_ACTION_IMPORT "Import Credentials" + IDS_CTX_IMPORT "Importing credentials from Windows" + IDS_CFG_PI_COL_PLUGINS "Plug-ins" + IDS_PISTATE_FAILUNK "Unknown failure" + IDS_PISTATE_FAILMAX "Maximum failure count reached" + IDS_PISTATE_FAILREG "Not properly registered" +END + +STRINGTABLE +BEGIN + IDS_PISTATE_FAILDIS "Disabled" + IDS_PISTATE_FAILLOD "Failed to initialize" + IDS_PISTATE_PLACEHOLD "Not loaded" + IDS_PISTATE_REG "Not initialized" + IDS_PISTATE_HOLD "Waiting for dependencies" + IDS_PISTATE_INIT "Initializing" + IDS_PISTATE_RUN "Running" + IDS_PISTATE_EXIT "Stopped" + IDS_CTX_PASSWORD "Changing password" + IDS_WT_PASSWORD "Changing password" + IDS_WTPOST_PASSWORD " - Changing password" + IDS_CTX_PROC_PASSWORD "Changing password for %1!s!" + IDS_NC_PWD_FAILED_TITLE "Failed to change password" + IDS_MENU_SETDEF "Set default" + IDS_PACTION_NEXT "Next alert" + IDS_ERR_TITLE_NO_IDENTPRO "Cannot proceed without identity provider" +END + +STRINGTABLE +BEGIN + IDS_ERR_MSG_NO_IDENTPRO "There is no identity provider currently loaded. The identity provider is the component of Network Identity Manager that verifies and performs operations on actual identities. Without this provider, many critical operations cannot be performed." + IDS_ERR_SUGG_NO_IDENTPRO + "This is quite possibly caused by the identity provider module failing to load properly." + IDS_NC_REN_FAILED_TITLE "Failed to renew credentials" + IDS_CW_DEFAULT "(Default)" + IDS_ACTION_OPT_PLUGINS "Plug-ins" + IDS_NC_SETDEF "&Set as default identity" + IDS_NC_ID_DEF "<p>This identity is the default</p>" + IDS_NC_ID_WDEF "<p>Will be the default. (<a id=""NotDef"">Don't make default</a>)</p>" + IDS_NC_ID_NDEF "<p>Not default identity. (<a id=""MakeDef"">make default</a>)</p>" + IDS_PACTION_YES "&Yes" + IDS_PACTION_NO "&No" + IDS_PACTION_YESALL "Y&es to all" + IDS_PACTION_NOALL "N&o to all" + IDS_PACTION_KEEP "&Keep" + IDS_PACTION_REMOVE "&Remove" + IDS_PACTION_DISCARD "&Discard" +END + +STRINGTABLE +BEGIN + IDS_CFG_IT_MOD "Changes need to be applied" + IDS_CFG_IT_APP "Changes have been applied" + IDS_CFG_IT_NONE "No changes" + IDS_CFG_NODESC "(Description for plug-in %s is not available)" + IDS_CFG_P_DELCNFT "About to disable plug-in %s" + IDS_CFG_P_DELCNFM "Are you sure you want to disable plug-in %s ?\n\nOnce disabled, the services provided by the plug-in will no longer be available. In addition, any other plug-ins that depend on this plug-in will also become non functional.\n\nNetwork Identity Manager will need to be restarted for the plug-in to be deactivated." + IDS_CFG_P_DELCNFS "The following plug-ins depend on this plug-in : %s" + IDS_CFG_P_DELNDEP "No other plug-ins depend on this plug-in." + IDS_CFG_P_ENBCNFT "About to enable plug-in %s" + IDS_CFG_P_ENBCNFM "The plug-in %s will be marked as enabled. The plug-in will be come active the next time Network Identity Manager is started." + IDS_PISTATE_FAILINIT "Failed to initialize" + IDS_CFG_P_UNRCNFT "Unregistering plug-in %s" + IDS_CFG_P_UNRCNFM "Are you sure you want to unregister plug-in %s? In addition to this plug-in, any other plug-ins that are provided by the same module will also be unregistered.\n\nThe plug-in will no longer be loaded for subsequent sessions of Network Identity Manager." + IDS_CFG_P_UNRCNFS "Note that if the plug-in was registered by a separate installer, it should be unregistered by the same installer and not through Network Identity Manager.\n\nThe following plug-ins will be unregistered: %s" + IDS_ACTION_LAYOUT_CUST "Custom" + IDS_APR_HEADER_TEXT "Header text" +END + +STRINGTABLE +BEGIN + IDS_APR_HEADER_TEXT_BOLD "Header text (selected)" + IDS_APR_TEXT "Normal text" + IDS_APR_TEXT_BOLD "Normal text (selected)" + IDS_APR_SAMPLE_TEXT_NORMAL "Sample text (normal). 01234567890" + IDS_CFG_APPEAR_SHORT "Appearance" + IDS_CFG_APPEAR_LONG "Appearance" + IDS_ACTION_OPT_APPEAR "Appearance" + IDS_APR_SAMPLE_TEXT_SEL "Sample text (selected). 01234567890" + IDS_CFG_IDNAME_INV "The identity name %s is invalid." + IDS_CFG_IDNAME_PRB "Can't add new identity %s" + IDS_CFG_IDNAME_EXT "The identity name %s already exists." + IDS_CFG_IDNAME_CCR "Can't create new identity. This may be caused by lack of resources or an unknown failure. The code returned was %d." + IDS_CFG_IDNAME_CCC "Can't create identity configuration. This may be caused by lack or resources or not having the correct permissions to create the configuration space. The code returned was %d." + IDS_CFG_LOGF_CS "Can't show log file" + IDS_CFG_LOGF_CSR "The log file %s does not exist." + IDS_ACTIONT_PROPERTIES "Show properties for the current selection" +END + +STRINGTABLE +BEGIN + IDS_ACTIONT_EXIT "Exit Network Identity Manager" + IDS_ACTIONT_SET_DEF_ID "Set the currently selected identity as the default identity" + IDS_ACTIONT_PASSWD_ID "Change the password the currently selected identity" + IDS_ACTIONT_NEW_CRED "Obtain new credentials" + IDS_ACTIONT_RENEW_CRED "Renew or re-obtain credentials for the currently selected identity" + IDS_ACTIONT_DESTROY_CRED "Destroy the selected credentials or identities" + IDS_ACTIONT_VIEW_REFRESH + "Re-obtain information about credentials and refresh the credentials display" + IDS_ACTIONT_OPT_IDENTS "Change options for identities" + IDS_ACTIONT_OPT_KHIM "Change general application settings for Network Identity Manager" + IDS_ACTIONT_OPT_NOTIF "Change notification options" + IDS_ACTIONT_OPT_PLUGINS "Change options for plug-ins and modules" + IDS_ACTIONT_OPT_APPEAR "Change appearance and display settings" + IDS_ACTIONT_HELP_CTX "Display user documentation" + IDS_ACTIONT_IMPORT "Import credentials from external sources such as the Windows LSA" + IDS_NC_FAILED_TITLE_I "Failed to get credentials for %s" + IDS_NC_PWD_FAILED_TITLE_I "Failed to change password for %s" +END + +STRINGTABLE +BEGIN + IDS_NC_REN_FAILED_TITLE_I "Failed to renew credentials for %s" + IDS_CFG_IDNAME_NON "No identity selected. Please select an identity and try again." + IDS_MENU_DESTROY_CRED "Destroy" + IDS_MENU_RENEW_CRED "Renew" + IDS_ACTION_DESTROY_ALL "Destroy all identities" + IDS_ACTION_RENEW_ALL "Renew all identities" + IDS_IDACTION_RENEW "Renew %s" + IDS_IDACTION_DESTROY "Destroy %s" + IDS_CTX_DESTROY_ID "Destroying identity %1!s!" + IDS_NCN_IDENT_INVALID "Identity %s is invalid." + IDS_NCN_IDENT_CHECKING "Checking identity %s ..." + IDS_NCN_IDENT_UNKNOWN "Validity of identity %s couldn't be determined." + IDS_REMOTE_FAIL "The instance of Network Identity Manager that is already running is not responding to the remote request properly. Please check if you are running the latest version of Network Identity Manager software included with MIT Kerberos for Windows." + IDS_REMOTE_FAIL_TITLE "Failed to communicate with Network Identity Manager" + IDS_IDACTION_NEW "Obtain new credentials for %s" + IDS_IDACTIONT_NEW "New credentials for %s" +END + +STRINGTABLE +BEGIN + IDS_IDACTIONT_RENEW "Renew credentials for %s" + IDS_IDACTIONT_DESTROY "Destroy credentials for %s" + IDS_ALERTTYPE_PLUGIN "Failed to load plug-in" + IDS_ALERTTYPE_EXPIRE "Credential expiration warning" + IDS_ALERTTYPE_RENEWFAIL "Failed to renew credentials" + IDS_ALERTTYPE_ACQUIREFAIL "Failed to acquire credentials" + IDS_ALERTTYPE_CHPW "Failed to change password" + IDS_ACTION_LAYOUT_MINI "&Advanced" + IDS_IDEXPDISP_NOCRED "(This identity has no credentials)" + IDS_IDEXPDISP_1CRED "(This identity has 1 credential)" + IDS_IDEXPDISP_NCRED "(This identity has %d credentials)" + IDS_CW_DEFAULTTF "(Default, %s)" + IDS_CW_TYPEF "(%s)" + IDS_CW_EXPIREF "Expires in %s" + IDS_CW_EXPIRED "(Expired)" + IDS_IDACTIONT_SETDEF "Set %s as default identity" +END + +STRINGTABLE +BEGIN + IDS_IDACTION_SETDEF "%s" + IDS_ACTION_VIEW_ALL_IDS "All identities" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + + + + + + diff --git a/krb5-1-6/src/windows/identity/ui/main.c b/krb5-1-6/src/windows/identity/ui/main.c new file mode 100644 index 000000000..f8bcde882 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/main.c @@ -0,0 +1,1075 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Copyright (2) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<shlwapi.h> +#include<khmapp.h> +#include<netidmgr_intver.h> + +/* used for the command-line help dialog */ +#include<richedit.h> + +#if DEBUG +#include<assert.h> + +#if defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL) +/* needed for writing out leaked allocation and handle report */ +#include<stdio.h> +#endif + +#endif + +HINSTANCE khm_hInstance; +const wchar_t * khm_facility = L"NetIDMgr"; +int khm_nCmdShow; +khm_ui_4 khm_commctl_version = 0; + +khm_startup_options khm_startup; + +const khm_version app_version = {KH_VERSION_LIST}; + +HRESULT hr_coinitialize = S_OK; + +#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL)) + +KHMEXP void KHMAPI khcint_dump_handles(FILE * f); +KHMEXP void KHMAPI perf_dump(FILE * f); +KHMEXP void KHMAPI kmqint_dump(FILE * f); + +#endif + +void khm_init_gui(void) { + + hr_coinitialize = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + khui_init_actions(); + khui_init_rescache(); + khui_init_menu(); + khui_init_toolbar(); + khm_init_notifier(); + khm_init_config(); + khm_init_debug(); + khm_init_taskbar_funcs(); +} + +void khm_exit_gui(void) { + khm_exit_taskbar_funcs(); + khm_exit_debug(); + khm_exit_config(); + khm_exit_notifier(); + khui_exit_toolbar(); + khui_exit_menu(); + khui_exit_rescache(); + khui_exit_actions(); + + if (hr_coinitialize == S_OK || + hr_coinitialize == S_FALSE) { + CoUninitialize(); + } +} + +/* This is passed into EnumResourceLanguages(). This returns the + language ID of the first resource of the type and name that's + passed into it. For the resources types we care about, we only + expect there to be one resource for a given name. At the moment we + don't support resource modules that contain resources for multiple + languages. */ +BOOL CALLBACK +khm_enum_res_lang_proc_first(HANDLE hModule, + LPCTSTR lpszType, + LPCTSTR lpszName, + WORD wIDLanguage, + LONG_PTR lParam) +{ + WORD * plangid = (WORD *) lParam; + + *plangid = wIDLanguage; + + return FALSE; +} + +#define KHM_RTF_RESOURCE L"KHMRTFRESOURCE" + +INT_PTR CALLBACK +khm_cmdline_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_INITDIALOG: + { + WORD langID = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); + HRSRC h_resinfo = NULL; + HGLOBAL h_resource = NULL; + LPVOID h_resmem = NULL; + SETTEXTEX ste; + + SetDlgItemText(hwnd, IDC_PRODUCT, + TEXT(KH_VERSTR_PRODUCT_1033)); +#ifdef OVERRIDE_COPYRIGHT + SetDlgItemText(hwnd, IDC_COPYRIGHT, + TEXT(KH_VERSTR_COPYRIGHT_1033)); +#endif + + EnumResourceLanguages(khm_hInstance, + KHM_RTF_RESOURCE, + MAKEINTRESOURCE(IDR_CMDLINERTF), + khm_enum_res_lang_proc_first, + (LONG_PTR) &langID); + + h_resinfo = FindResourceEx(khm_hInstance, + KHM_RTF_RESOURCE, + MAKEINTRESOURCE(IDR_CMDLINERTF), + langID); + if (h_resinfo == NULL) + goto init_failed; + + h_resource = LoadResource(khm_hInstance, h_resinfo); + if (h_resinfo == NULL) + goto init_failed; + + h_resmem = LockResource(h_resource); + if (h_resmem == NULL) + goto init_failed; + + ste.flags = ST_DEFAULT; + ste.codepage = CP_ACP; + + SendDlgItemMessage(hwnd, IDC_CONTENT, EM_SETTEXTEX, (WPARAM) &ste, (LPARAM) h_resmem); + init_failed: + /* none of the above handles need to be freed. */ + + return TRUE; + } + break; + + case WM_COMMAND: + + if (wParam == MAKEWPARAM(IDOK, BN_CLICKED)) { + EndDialog(hwnd, KHM_ERROR_EXIT); + } + + return TRUE; + + case WM_CLOSE: + + EndDialog(hwnd, KHM_ERROR_EXIT); + + return TRUE; + } + + return FALSE; +} + +void khm_show_commandline_help(void) { + HMODULE hm_richedit; + + hm_richedit = LoadLibrary(L"riched20.dll"); + if (hm_richedit == NULL) + return; + + DialogBox(khm_hInstance, MAKEINTRESOURCE(IDD_CMDLINE), + NULL, khm_cmdline_dlg_proc); + + FreeLibrary(hm_richedit); +} + +void khm_parse_commandline(void) { + LPWSTR wcmdline; + LPWSTR * wargs; + int wargc; + int i; + + ZeroMemory(&khm_startup, sizeof(khm_startup)); + + wcmdline = GetCommandLine(); + wargs = CommandLineToArgvW(wcmdline, &wargc); + + for (i=1; i<wargc; i++) { + if (!wcscmp(wargs[i], L"-i") || + !wcscmp(wargs[i], L"--kinit") || + !wcscmp(wargs[i], L"-kinit")) { + khm_startup.init = TRUE; + khm_startup.exit = TRUE; + khm_startup.no_main_window = TRUE; + khm_startup.display |= SOPTS_DISPLAY_NODEF; + } + else if (!wcscmp(wargs[i], L"-m") || + !wcscmp(wargs[i], L"--import") || + !wcscmp(wargs[i], L"-import")) { + khm_startup.import = TRUE; + khm_startup.exit = TRUE; + khm_startup.no_main_window = TRUE; + khm_startup.display |= SOPTS_DISPLAY_NODEF; + } + else if (!wcscmp(wargs[i], L"-r") || + !wcscmp(wargs[i], L"--renew") || + !wcscmp(wargs[i], L"-renew")) { + khm_startup.renew = TRUE; + khm_startup.exit = TRUE; + khm_startup.no_main_window = TRUE; + khm_startup.display |= SOPTS_DISPLAY_NODEF; + } + else if (!wcscmp(wargs[i], L"-d") || + !wcscmp(wargs[i], L"--destroy") || + !wcscmp(wargs[i], L"-destroy")) { + khm_startup.destroy = TRUE; + khm_startup.exit = TRUE; + khm_startup.no_main_window = TRUE; + khm_startup.display |= SOPTS_DISPLAY_NODEF; + } + else if (!wcscmp(wargs[i], L"-a") || + !wcscmp(wargs[i], L"--autoinit") || + !wcscmp(wargs[i], L"-autoinit")) { + khm_startup.autoinit = TRUE; + khm_startup.display |= SOPTS_DISPLAY_NODEF; + } + else if (!wcscmp(wargs[i], L"-x") || + !wcscmp(wargs[i], L"--exit") || + !wcscmp(wargs[i], L"-exit")) { + khm_startup.exit = TRUE; + khm_startup.remote_exit = TRUE; + khm_startup.no_main_window = TRUE; + khm_startup.display |= SOPTS_DISPLAY_NODEF; + } + else if (!wcscmp(wargs[i], L"--minimized")) { + khm_startup.no_main_window = TRUE; + khm_startup.display |= SOPTS_DISPLAY_NODEF; + } + else if (!wcscmp(wargs[i], L"--show")) { + if (khm_startup.display & SOPTS_DISPLAY_HIDE) { + khm_show_commandline_help(); + khm_startup.error_exit = TRUE; + break; + } + + khm_startup.display |= (SOPTS_DISPLAY_SHOW | SOPTS_DISPLAY_NODEF); + } + else if (!wcscmp(wargs[i], L"--hide")) { + if (khm_startup.display & SOPTS_DISPLAY_SHOW) { + khm_show_commandline_help(); + khm_startup.error_exit = TRUE; + break; + } + + khm_startup.display |= (SOPTS_DISPLAY_HIDE | SOPTS_DISPLAY_NODEF); + khm_startup.no_main_window = TRUE; + } + else { + khm_show_commandline_help(); + + khm_startup.error_exit = TRUE; + break; + } + } + + /* special: always enable renew when other options aren't specified */ + if (!khm_startup.exit && + !khm_startup.destroy && + !khm_startup.init && + !khm_startup.remote_exit && + !khm_startup.display) + khm_startup.renew = TRUE; +} + +void khm_register_window_classes(void) { + INITCOMMONCONTROLSEX ics; + + ZeroMemory(&ics, sizeof(ics)); + ics.dwSize = sizeof(ics); + ics.dwICC = + ICC_COOL_CLASSES | + ICC_BAR_CLASSES | + ICC_DATE_CLASSES | + ICC_HOTKEY_CLASS | + ICC_LISTVIEW_CLASSES | + ICC_TAB_CLASSES | + ICC_INTERNET_CLASSES | +#if (_WIN32_WINNT >= 0x501) + ((IS_COMMCTL6())? + ICC_LINK_CLASS | + ICC_STANDARD_CLASSES : + 0) | +#endif + 0; + + InitCommonControlsEx(&ics); + + khm_register_main_wnd_class(); + khm_register_credwnd_class(); + khm_register_htwnd_class(); + khm_register_passwnd_class(); + khm_register_newcredwnd_class(); + khm_register_propertywnd_class(); +} + +void khm_unregister_window_classes(void) { + khm_unregister_main_wnd_class(); + khm_unregister_credwnd_class(); + khm_unregister_htwnd_class(); + khm_unregister_passwnd_class(); + khm_unregister_newcredwnd_class(); + khm_unregister_propertywnd_class(); +} + + +/* we support up to 16 simutaneous dialogs. In reality, more than two + is pretty unlikely. Property sheets are special and are handled + separately. */ +#define MAX_UI_DIALOGS 16 + +typedef struct tag_khui_dialog { + HWND hwnd; + HWND hwnd_next; + BOOL active; +} khui_dialog; + +static khui_dialog khui_dialogs[MAX_UI_DIALOGS]; +static int n_khui_dialogs = 0; +static HWND khui_modal_dialog = NULL; +static BOOL khui_main_window_active; + +/* should only be called from the UI thread */ +void khm_add_dialog(HWND dlg) { + if(n_khui_dialogs < MAX_UI_DIALOGS - 1) { + khui_dialogs[n_khui_dialogs].hwnd = dlg; + khui_dialogs[n_khui_dialogs].hwnd_next = NULL; + khui_dialogs[n_khui_dialogs].active = TRUE; + n_khui_dialogs++; + } else { +#if DEBUG + assert(FALSE); +#endif + } +} + +/* should only be called from the UI thread */ +void khm_enter_modal(HWND hwnd) { + int i; + + if (khui_modal_dialog) { + + /* we are already in a modal loop. */ + +#ifdef DEBUG + assert(hwnd != khui_modal_dialog); +#endif + + for (i=0; i < n_khui_dialogs; i++) { + if (khui_dialogs[i].hwnd == khui_modal_dialog) { + khui_dialogs[i].active = TRUE; + EnableWindow(khui_modal_dialog, FALSE); + break; + } + } + +#ifdef DEBUG + assert(i < n_khui_dialogs); +#endif + + for (i=0; i < n_khui_dialogs; i++) { + if (khui_dialogs[i].hwnd == hwnd) { + khui_dialogs[i].hwnd_next = khui_modal_dialog; + break; + } + } + +#ifdef DEBUG + assert(i < n_khui_dialogs); +#endif + + khui_modal_dialog = hwnd; + + } else { + + /* we are entering a modal loop. preserve the active state of + the overlapped dialogs and proceed with the modal + dialog. */ + + for (i=0; i < n_khui_dialogs; i++) { + if(khui_dialogs[i].hwnd != hwnd) { + khui_dialogs[i].active = IsWindowEnabled(khui_dialogs[i].hwnd); + EnableWindow(khui_dialogs[i].hwnd, FALSE); + } + } + + khui_main_window_active = khm_is_main_window_active(); + EnableWindow(khm_hwnd_main, FALSE); + + khui_modal_dialog = hwnd; + + SetForegroundWindow(hwnd); + } +} + +/* should only be called from the UI thread */ +void khm_leave_modal(void) { + int i; + + for (i=0; i < n_khui_dialogs; i++) { + if (khui_dialogs[i].hwnd == khui_modal_dialog) + break; + } + +#ifdef DEBUG + assert(i < n_khui_dialogs); +#endif + + if (i < n_khui_dialogs && khui_dialogs[i].hwnd_next) { + + /* we need to proceed to the next one down the modal dialog + chain. We are not exiting a modal loop. */ + + khui_modal_dialog = khui_dialogs[i].hwnd_next; + khui_dialogs[i].hwnd_next = FALSE; + + EnableWindow(khui_modal_dialog, TRUE); + + } else { + + HWND last_dialog = NULL; + + /* we are exiting a modal loop. */ + + for (i=0; i < n_khui_dialogs; i++) { + if(khui_dialogs[i].hwnd != khui_modal_dialog) { + EnableWindow(khui_dialogs[i].hwnd, khui_dialogs[i].active); + last_dialog = khui_dialogs[i].hwnd; + } + } + + EnableWindow(khm_hwnd_main, TRUE); + + khui_modal_dialog = NULL; + + if(last_dialog) + SetActiveWindow(last_dialog); + else + SetActiveWindow(khm_hwnd_main); + } +} + +/* should only be called from the UI thread */ +void khm_del_dialog(HWND dlg) { + int i; + for(i=0;i < n_khui_dialogs; i++) { + if(khui_dialogs[i].hwnd == dlg) + break; + } + + if(i < n_khui_dialogs) + n_khui_dialogs--; + else + return; + + for(;i < n_khui_dialogs; i++) { + khui_dialogs[i] = khui_dialogs[i+1]; + } +} + +BOOL khm_check_dlg_message(LPMSG pmsg) { + int i; + BOOL found = FALSE; + for(i=0;i<n_khui_dialogs;i++) { + if(IsDialogMessage(khui_dialogs[i].hwnd, pmsg)) { + found = TRUE; + break; + } + } + + return found; +} + +BOOL khm_is_dialog_active(void) { + HWND hwnd; + int i; + + hwnd = GetForegroundWindow(); + + for (i=0; i<n_khui_dialogs; i++) { + if (khui_dialogs[i].hwnd == hwnd) + return TRUE; + } + + return FALSE; +} + +/* We support at most 256 property sheets simultaneously. 256 + property sheets should be enough for everybody. */ +#define MAX_UI_PROPSHEETS 256 + +khui_property_sheet *_ui_propsheets[MAX_UI_PROPSHEETS]; +int _n_ui_propsheets = 0; + +void khm_add_property_sheet(khui_property_sheet * s) { + if(_n_ui_propsheets < MAX_UI_PROPSHEETS) + _ui_propsheets[_n_ui_propsheets++] = s; + else { +#ifdef DEBUG + assert(FALSE); +#endif + } +} + +void khm_del_property_sheet(khui_property_sheet * s) { + int i; + + for(i=0;i < _n_ui_propsheets; i++) { + if(_ui_propsheets[i] == s) + break; + } + + if(i < _n_ui_propsheets) + _n_ui_propsheets--; + else + return; + + for(;i < _n_ui_propsheets; i++) { + _ui_propsheets[i] = _ui_propsheets[i+1]; + } +} + +BOOL khm_check_ps_message(LPMSG pmsg) { + int i; + khui_property_sheet * ps; + for(i=0;i<_n_ui_propsheets;i++) { + if(khui_ps_check_message(_ui_propsheets[i], pmsg)) { + if(_ui_propsheets[i]->status == KHUI_PS_STATUS_DONE) { + ps = _ui_propsheets[i]; + + ps->status = KHUI_PS_STATUS_DESTROY; + kmq_post_message(KMSG_CRED, KMSG_CRED_PP_END, 0, (void *) ps); + + return TRUE; + } + return TRUE; + } + } + + return FALSE; +} + +static HACCEL ha_menu; + +WPARAM khm_message_loop_int(khm_boolean * p_exit) { + int r; + MSG msg; + + while((r = GetMessage(&msg, NULL, 0,0)) && + (p_exit == NULL || *p_exit)) { + if(r == -1) + break; + if(!khm_check_dlg_message(&msg) && + !khm_check_ps_message(&msg) && + !TranslateAccelerator(khm_hwnd_main, ha_menu, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return msg.wParam; +} + +WPARAM khm_message_loop(void) { + WPARAM w; + ha_menu = khui_create_global_accel_table(); + w = khm_message_loop_int(NULL); + DestroyAcceleratorTable(ha_menu); + return w; +} + +/* Handles all context closures which have a signalled error state. + If the context is a top level context, then the errors are + displayed. */ +void KHMAPI +khm_err_ctx_completion_handler(enum kherr_ctx_event evt, + kherr_context * c) { + kherr_event * e; + khui_alert * a; + + /* we only handle top level contexts here. For others, we allow + the child contexts to fold upward silently. */ + if (c->parent || !kherr_is_error_i(c)) + return; + + for(e = kherr_get_first_event(c); + e; + e = kherr_get_next_event(e)) { + + if (e->severity != KHERR_ERROR && e->severity != KHERR_WARNING) + continue; + + kherr_evaluate_event(e); + + /* we only report errors if there is enough information to + present a message. */ + if (e->short_desc && e->long_desc) { + + khui_alert_create_empty(&a); + + khui_alert_set_severity(a, e->severity); + khui_alert_set_title(a, e->short_desc); + khui_alert_set_message(a, e->long_desc); + if (e->suggestion) + khui_alert_set_suggestion(a, e->suggestion); + + khui_alert_queue(a); + + khui_alert_release(a); + } + } +} + +static wchar_t helpfile[MAX_PATH] = L""; + +HWND khm_html_help(HWND hwnd, wchar_t * suffix, + UINT command, DWORD_PTR data) { + + wchar_t gpath[MAX_PATH + MAX_PATH]; + + if (!*helpfile) { + DWORD dw; + wchar_t ppath[MAX_PATH]; + + dw = GetModuleFileName(NULL, ppath, ARRAYLENGTH(ppath)); + + if (dw == 0) { + StringCbCopy(helpfile, sizeof(helpfile), NIDM_HELPFILE); + } else { + PathRemoveFileSpec(ppath); + PathAppend(ppath, NIDM_HELPFILE); + StringCbCopy(helpfile, sizeof(helpfile), ppath); + } + } + + StringCbCopy(gpath, sizeof(gpath), helpfile); + + if (suffix) + StringCbCat(gpath, sizeof(gpath), suffix); + + return HtmlHelp(hwnd, gpath, command, data); +} + +void khm_load_default_modules(void) { + kmm_load_default_modules(); +} + +int khm_compare_version(const khm_version * v1, const khm_version * v2) { + + if (v1->major != v2->major) + return ((int)v1->major) - ((int)v2->major); + + if (v1->minor != v2->minor) + return ((int)v1->minor) - ((int)v2->minor); + + if (v1->patch != v2->patch) + return ((int)v1->patch) - ((int)v2->patch); + + return ((int)v1->aux - ((int)v2->aux)); +} + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + int rv = 0; + HANDLE h_appmutex; + BOOL slave = FALSE; + int mutex_retries = 5; + + khm_hInstance = hInstance; + khm_nCmdShow = nCmdShow; + + khm_parse_commandline(); + + if (khm_startup.error_exit) + return 0; + + _retry_mutex: + + if (--mutex_retries < 0) + return 2; + + h_appmutex = CreateMutex(NULL, FALSE, L"Local\\NetIDMgr_GlobalAppMutex"); + if (h_appmutex == NULL) + return 5; + if (GetLastError() == ERROR_ALREADY_EXISTS) + slave = TRUE; + + khc_load_schema(NULL, schema_uiconfig); + + _start_app: + + if(!slave) { + + PDESCTHREAD(L"UI", L"App"); + + /* set this so that we don't accidently invoke an API that + inadvertently puts up the new creds dialog at an + inopportune moment, like, say, during the new creds dialog + is open. This only affects this process, and any child + processes started by plugins. */ + SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1"); + + khm_version_init(); + + khm_commctl_version = khm_get_commctl_version(NULL); + + /* we only open a main window if this is the only instance + of the application that is running. */ + kmq_init(); + khm_init_gui(); + kmm_init(); + + kmq_set_completion_handler(KMSG_CRED, kmsg_cred_completion); + + kherr_add_ctx_handler(khm_err_ctx_completion_handler, + KHERR_CTX_END, + 0); + + /* load the standard plugins */ + khm_load_default_modules(); + + khm_register_window_classes(); + + khm_init_request_daemon(); + + khm_create_main_window(); + + if (!khm_startup.no_main_window && + nCmdShow != SW_SHOWMINNOACTIVE && + nCmdShow != SW_MINIMIZE && + nCmdShow != SW_SHOWMINIMIZED) { + + khm_show_main_window(); + } + + khm_refresh_config(); + + rv = (int) khm_message_loop(); + + kmq_set_completion_handler(KMSG_CRED, NULL); + + khm_exit_request_daemon(); + + kmm_exit(); + khm_exit_gui(); + khm_unregister_window_classes(); + kmq_exit(); + + CloseHandle(h_appmutex); + } else { + + /* There is an instance of NetIDMgr already running. */ + + HWND hwnd = NULL; + int retries = 5; + HANDLE hmap; + wchar_t mapname[256]; + DWORD tid; + void * xfer; + khm_query_app_version query_app_version; + khm_version v; + BOOL use_cmd_v1 = FALSE; + khm_size cb = 0; + + CloseHandle(h_appmutex); + + while (hwnd == NULL && retries) { + hwnd = FindWindowEx(NULL, NULL, KHUI_MAIN_WINDOW_CLASS, NULL); + + if (hwnd) + break; + + retries--; + + /* if the app was just starting, we might have to wait + till the main window is created. */ + + Sleep(1000); + } + + if (!hwnd) { + + /* if the app was just exiting, we might see the mutex but + not the window. We go back and check if the mutex is + still there. */ + + goto _retry_mutex; + } + + /* first check if the remote instance supports a version + query */ + + StringCbPrintf(mapname, sizeof(mapname), + QUERY_APP_VER_MAP_FMT, + (tid = GetCurrentThreadId())); + + hmap = CreateFileMapping(INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + 4096, + mapname); + + if (hmap == NULL) + return 3; + + xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, + sizeof(query_app_version)); + + ZeroMemory(&query_app_version, sizeof(query_app_version)); + + if (xfer) { + query_app_version.magic = KHM_QUERY_APP_VER_MAGIC; + query_app_version.code = KHM_ERROR_NOT_IMPLEMENTED; + query_app_version.ver_caller = app_version; + + query_app_version.request_swap = TRUE; + + memcpy(xfer, &query_app_version, sizeof(query_app_version)); + + SendMessage(hwnd, WM_KHUI_QUERY_APP_VERSION, + 0, (LPARAM) tid); + + memcpy(&query_app_version, xfer, sizeof(query_app_version)); + + UnmapViewOfFile(xfer); + xfer = NULL; + } + + CloseHandle(hmap); + hmap = NULL; + + if (query_app_version.magic != KHM_QUERY_APP_VER_MAGIC || + query_app_version.code != KHM_ERROR_SUCCESS) { + + /* We managed to communicate with the remote instance, but + it didn't send us useful information. The remote + instance is not running an actual NetIDMgr instance. + However, it owns a top level window that was registered + with our classname. This instance won't function + properly if we let it proceed. + */ + + wchar_t error_msg[1024]; + wchar_t error_title[256]; + + LoadString(khm_hInstance, IDS_REMOTE_FAIL_TITLE, + error_title, ARRAYLENGTH(error_title)); + LoadString(khm_hInstance, IDS_REMOTE_FAIL, + error_msg, ARRAYLENGTH(error_msg)); + + MessageBox(NULL, error_msg, error_title, + MB_OK); + + goto done_with_remote; + } + + if (query_app_version.code == KHM_ERROR_SUCCESS && + query_app_version.request_swap) { + /* the request for swap was granted. We can now + initialize our instance as the master instance. */ + + slave = FALSE; + goto _start_app; + } + + /* Now we can work on sending the command-line to the remote + instance. However we need to figure out which version of + the startup structure it supports. */ + v.major = 1; + v.minor = 2; + v.patch = 0; + v.aux = 0; + + if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 || + khm_compare_version(&query_app_version.ver_remote, &v) > 0) + use_cmd_v1 = FALSE; + else + use_cmd_v1 = TRUE; + + StringCbPrintf(mapname, sizeof(mapname), + COMMANDLINE_MAP_FMT, + (tid = GetCurrentThreadId())); + + cb = max(sizeof(khm_startup_options_v1), + sizeof(khm_startup_options_v2)); + + cb = UBOUNDSS(cb, 4096, 4096); + +#ifdef DEBUG + assert(cb >= 4096); +#endif + + hmap = CreateFileMapping(INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + (DWORD) cb, + mapname); + + if (hmap == NULL) + return 3; + + /* make the call */ + + if (!use_cmd_v1) { + /* use the v2 structure */ + khm_startup_options_v3 opt; + khm_startup_options_v3 *xferopt; + + ZeroMemory(&opt, sizeof(opt)); + + opt.v2opt.magic = STARTUP_OPTIONS_MAGIC; + + opt.v2opt.init = khm_startup.init; + opt.v2opt.import = khm_startup.import; + opt.v2opt.renew = khm_startup.renew; + opt.v2opt.destroy = khm_startup.destroy; + opt.v2opt.autoinit = khm_startup.autoinit; + opt.v2opt.remote_exit = khm_startup.remote_exit; + opt.remote_display = khm_startup.display; + + opt.v2opt.code = KHM_ERROR_NOT_IMPLEMENTED; + + /* check if we can use the v3 options structure. This + should be possible for 1.3.1 and above. */ + v.major = 1; v.minor = 3; v.patch = 1; v.aux = 0; + if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 || + khm_compare_version(&query_app_version.ver_remote, &v) >= 0) { + + opt.v2opt.cb_size = sizeof(opt); + + } else { + + opt.v2opt.cb_size = sizeof(opt.v2opt); + + } + + xfer = MapViewOfFile(hmap, + FILE_MAP_WRITE, + 0, 0, + opt.v2opt.cb_size); + + xferopt = (khm_startup_options_v3 *) xfer; + + if (xfer) { + memcpy(xfer, &opt, opt.v2opt.cb_size); + + SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2, + 0, (LPARAM) tid); + + /* If it looks like the request was not processed, and + we were using a v3 request, fail-over to a v2 + request. */ + if (xferopt->v2opt.code == KHM_ERROR_NOT_IMPLEMENTED && + opt.v2opt.cb_size == sizeof(opt)) { + + opt.v2opt.cb_size = sizeof(opt.v2opt); + memcpy(xfer, &opt, opt.v2opt.cb_size); + + SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2, + 0, (LPARAM) tid); + } + + /* if it still looks like the request was not + processed, we failover to a v1 call */ + if (xferopt->v2opt.code == KHM_ERROR_NOT_IMPLEMENTED) { + use_cmd_v1 = TRUE; + } else { + memcpy(&opt, xfer, opt.v2opt.cb_size); + } + + UnmapViewOfFile(xfer); + xfer = NULL; + } + } + + if (use_cmd_v1) { + /* use the v1 structure */ + + khm_startup_options_v1 v1opt; + + ZeroMemory(&v1opt, sizeof(v1opt)); + + v1opt.init = khm_startup.init; + v1opt.import = khm_startup.import; + v1opt.renew = khm_startup.renew; + v1opt.destroy = khm_startup.destroy; + v1opt.autoinit = khm_startup.autoinit; + + xfer = MapViewOfFile(hmap, + FILE_MAP_WRITE, + 0, 0, + sizeof(v1opt)); + + if (xfer) { + memcpy(xfer, &v1opt, sizeof(v1opt)); + + SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V1, + 0, (LPARAM) tid); + + UnmapViewOfFile(xfer); + xfer = NULL; + } + } + + done_with_remote: + + if (hmap) + CloseHandle(hmap); + } + +#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL)) + { + FILE * f = NULL; + +#if _MSC_VER >= 1400 && __STDC_WANT_SECURE_LIB__ + if (fopen_s(&f, "memleak.txt", "w") != 0) + goto done_with_dump; +#else + f = fopen("memleak.txt", "w"); + if (f == NULL) + goto done_with_dump; +#endif + + perf_dump(f); + khcint_dump_handles(f); + kmqint_dump(f); + + fclose(f); + + done_with_dump: + ; + } +#endif + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/ui/mainmenu.c b/krb5-1-6/src/windows/identity/ui/mainmenu.c new file mode 100644 index 000000000..8645dc7bc --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/mainmenu.c @@ -0,0 +1,1233 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +HWND khui_main_menu_toolbar; +int mm_last_hot_item = -1; +int mm_next_hot_item = -1; +BOOL mm_hot_track = FALSE; + +#define MAX_ILIST 256 +/* not the same as MENU_SIZE_ICON_* */ +#define ILIST_ICON_X 16 +#define ILIST_ICON_Y 15 + +khui_ilist * il_icon; +int il_icon_id[MAX_ILIST]; + +void khui_init_menu(void) { + int i; + + il_icon = khui_create_ilist(ILIST_ICON_X, + ILIST_ICON_Y, + MAX_ILIST, 5, 0); + for(i=0;i<MAX_ILIST;i++) + il_icon_id[i] = -1; + + khm_refresh_identity_menus(); +} + +void khui_exit_menu(void) { + khui_delete_ilist(il_icon); +} + +int khui_get_icon_index(int id) { + int i; + HBITMAP hbm; + + for(i=0;i<MAX_ILIST;i++) + if(il_icon_id[i] == id) { + return i; + } + + hbm = LoadImage(khm_hInstance, + MAKEINTRESOURCE(id), + IMAGE_BITMAP, + ILIST_ICON_X, ILIST_ICON_Y, + LR_DEFAULTCOLOR); + i = khui_ilist_add_masked(il_icon, hbm, KHUI_TOOLBAR_BGCOLOR); + il_icon_id[i] = id; + DeleteObject(hbm); + + return i; +} + +void khm_get_action_caption(khm_int32 action, wchar_t * buf, khm_size cb_buf) { + khui_action * act; + + StringCbCopy(buf, cb_buf, L""); + + khui_action_lock(); + act = khui_find_action(action); + + if (act == NULL) + goto done; + + if (act->caption) { + StringCbCopy(buf, cb_buf, act->caption); + } else if (act->is_caption) { + LoadString(khm_hInstance, act->is_caption, + buf, (int)(cb_buf / sizeof(wchar_t))); + } + + done: + khui_action_unlock(); +} + +void khm_get_action_tooltip(khm_int32 action, wchar_t * buf, khm_size cb_buf) { + khui_action * act; + + StringCbCopy(buf, cb_buf, L""); + + khui_action_lock(); + act = khui_find_action(action); + + if (act == NULL) + goto done; + + if (act->tooltip) { + StringCbCopy(buf, cb_buf, act->tooltip); + } else if (act->is_tooltip) { + LoadString(khm_hInstance, act->is_tooltip, + buf, (int) (cb_buf / sizeof(wchar_t))); + } + + done: + khui_action_unlock(); +} + +void add_action_to_menu(HMENU hm, khui_action * act, + int idx, int flags) { + MENUITEMINFO mii; + wchar_t buf[MAX_RES_STRING] = L""; + wchar_t accel[MAX_RES_STRING] = L""; + + assert(!act || act->cmd); + + mii.cbSize = sizeof(mii); + mii.fMask = 0; + + if(act == NULL) { + mii.fMask = MIIM_FTYPE; + mii.fType = MFT_SEPARATOR; + } else { + khui_menu_def * def; + + if (act->type == KHUI_ACTIONTYPE_IDENTITY) { + mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_DATA; + mii.fType = MFT_OWNERDRAW; + + mii.dwTypeData = 0; + mii.dwItemData = 0; + } else { + khm_get_action_caption(act->cmd, buf, sizeof(buf)); + + if(khui_get_cmd_accel_string(act->cmd, accel, + ARRAYLENGTH(accel))) { + StringCbCat(buf, sizeof(buf), L"\t"); + StringCbCat(buf, sizeof(buf), accel); + } + + mii.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID; + mii.fType = MFT_STRING; + + mii.dwTypeData = buf; + mii.cch = (int) wcslen(buf); + } + + mii.wID = act->cmd; + + if(act->state & KHUI_ACTIONSTATE_DISABLED) { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } else { + mii.fState = 0; + } + + if((act->type & KHUI_ACTIONTYPE_TOGGLE) && + (act->state & KHUI_ACTIONSTATE_CHECKED)) { + mii.fMask |= MIIM_STATE; + mii.fState |= MFS_CHECKED; + } + + if(act->ib_icon) { + mii.fMask |= MIIM_BITMAP; + mii.hbmpItem = HBMMENU_CALLBACK; + } + + if (flags & KHUI_ACTIONREF_SUBMENU) { + def = khui_find_menu(act->cmd); + if(def) { + mii.fMask |= MIIM_SUBMENU; + mii.hSubMenu = mm_create_menu_from_def(def, FALSE); + } + } + + if(flags & KHUI_ACTIONREF_DEFAULT) { + mii.fMask |= MIIM_STATE; + mii.fState |= MFS_DEFAULT; + } + } + + InsertMenuItem(hm,idx,TRUE,&mii); +} + +static void refresh_menu(HMENU hm, khui_menu_def * def); + +static int refresh_menu_item(HMENU hm, khui_action * act, + int idx, int flags) { + MENUITEMINFO mii; + khui_menu_def * def; + + mii.cbSize = sizeof(mii); + mii.fMask = 0; + + if (flags & KHUI_ACTIONREF_END) { + /* we have been asked to assert that the menu doesn't have + more than idx items */ + mii.fMask = MIIM_FTYPE; + while (GetMenuItemInfo(hm, idx, TRUE, &mii)) { + RemoveMenu(hm, idx, MF_BYPOSITION); + mii.fMask = MIIM_FTYPE; + } + + return 0; + } + + /* Check if the menu item is there. Otherwise we need to add + it. */ + mii.fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE; + if (!GetMenuItemInfo(hm, idx, TRUE, &mii) || + ((flags & KHUI_ACTIONREF_SEP) && !(mii.fType & MFT_SEPARATOR)) || + (!(flags & KHUI_ACTIONREF_SEP) && mii.wID != (WORD) act->cmd)) { + add_action_to_menu(hm, ((flags & KHUI_ACTIONREF_SEP)? NULL : act), + idx, flags); + return 0; + } + + if (flags & KHUI_ACTIONREF_SEP) + return 0; + +#ifdef DEBUG + assert(act); +#endif + if (!act) + return 0; + + if (flags & KHUI_ACTIONREF_DEFAULT) { + if (!(mii.fState & MFS_DEFAULT)) { + mii.fMask |= MIIM_STATE; + mii.fState |= MFS_DEFAULT; + } + } else { + if (mii.fState & MFS_DEFAULT) { + RemoveMenu(hm, idx, MF_BYPOSITION); + add_action_to_menu(hm, act, idx, flags); + return 0; + } + } + + mii.fMask = 0; + + if(act->state & KHUI_ACTIONSTATE_DISABLED) { + mii.fMask |= MIIM_STATE; + mii.fState &= ~MFS_ENABLED; + mii.fState |= MFS_DISABLED; + } else { + mii.fMask |= MIIM_STATE; + mii.fState &= ~MFS_DISABLED; + mii.fState |= MFS_ENABLED; + } + + if(act->type & KHUI_ACTIONTYPE_TOGGLE) { + mii.fMask |= MIIM_STATE; + if (act->state & KHUI_ACTIONSTATE_CHECKED) { + mii.fState &= ~MFS_UNCHECKED; + mii.fState |= MFS_CHECKED; + } else { + mii.fState &= ~MFS_CHECKED; + mii.fState |= MFS_UNCHECKED; + } + } + + SetMenuItemInfo(hm, act->cmd, FALSE, &mii); + + def = khui_find_menu(act->cmd); + + if(def) { + MENUITEMINFO mii2; + + mii2.cbSize = sizeof(mii2); + mii2.fMask = MIIM_SUBMENU; + + if (GetMenuItemInfo(hm, act->cmd, FALSE, &mii2)) { + refresh_menu(mii2.hSubMenu, def); + } + } + + return 0; +} + + +static void refresh_menu(HMENU hm, khui_menu_def * def) { + khui_action_ref * act; + khm_size i, n; + + for(i = 0, n = khui_menu_get_size(def); i < n; i++) { + act = khui_menu_get_action(def, i); + refresh_menu_item(hm, khui_find_action(act->action), (int) i, act->flags); + } + + refresh_menu_item(hm, NULL, (int) i, KHUI_ACTIONREF_END); +} + +static HMENU mm_create_menu_from_def(khui_menu_def * def, BOOL main) { + HMENU hm; + khui_action_ref * act; + khm_size i, n; + + if (main) + hm = CreateMenu(); + else + hm = CreatePopupMenu(); + + for (i = 0, n = khui_menu_get_size(def); i < n; i++) { + act = khui_menu_get_action(def, i); + add_action_to_menu(hm, khui_find_action(act->action), (int) i, act->flags); + } + + return hm; +} + +void mm_begin_hot_track(void); +void mm_end_hot_track(void); + +static void mm_show_panel_def(khui_menu_def * def, LONG x, LONG y) +{ + HMENU hm; + + hm = mm_create_menu_from_def(def, FALSE); + + mm_hot_track = (mm_last_hot_item >= 0); + + if (mm_hot_track) + mm_begin_hot_track(); + + TrackPopupMenuEx(hm, + TPM_LEFTALIGN | TPM_TOPALIGN | + TPM_VERPOSANIMATION, + x, y, khm_hwnd_main, NULL); + + mm_last_hot_item = -1; + + if (mm_hot_track) + mm_end_hot_track(); + + mm_hot_track = FALSE; + + DestroyMenu(hm); +} + +void khm_menu_show_panel(int id, LONG x, LONG y) { + khui_menu_def * def; + + def = khui_find_menu(id); + if(!def) + return; + + mm_show_panel_def(def, x, y); +} + +LRESULT khm_menu_activate(int menu_id) { + khui_menu_def * mmdef; + int nmm; + + mmdef = khui_find_menu(KHUI_MENU_MAIN); + nmm = (int) khui_action_list_length(mmdef->items); + + if(menu_id == MENU_ACTIVATE_DEFAULT) { + if (mm_last_hot_item != -1) + menu_id = mm_last_hot_item; + else + menu_id = 0; + } else if(menu_id == MENU_ACTIVATE_LEFT) { + menu_id = (mm_last_hot_item > 0)? + mm_last_hot_item - 1: + ((mm_last_hot_item == 0)? nmm - 1: 0); + } else if(menu_id == MENU_ACTIVATE_RIGHT) { + menu_id = (mm_last_hot_item >=0 && mm_last_hot_item < nmm - 1)? + mm_last_hot_item + 1: + 0; + } else if(menu_id == MENU_ACTIVATE_NONE) { + menu_id = -1; + } + + SendMessage(khui_main_menu_toolbar, + TB_SETHOTITEM, + menu_id, + 0); + + khm_menu_track_current(); + + return TRUE; +} + +LRESULT khm_menu_measure_item(WPARAM wParam, LPARAM lParam) { + LPMEASUREITEMSTRUCT lpm = (LPMEASUREITEMSTRUCT) lParam; + khui_action * act; + + act = khui_find_action(lpm->itemID); + if (act && act->type == KHUI_ACTIONTYPE_IDENTITY) { + khm_measure_identity_menu_item(khm_hwnd_main_cred, lpm, act); + } else { + lpm->itemWidth = MENU_SIZE_ICON_X; + lpm->itemHeight = MENU_SIZE_ICON_Y; + } + return TRUE; +} + +LRESULT khm_menu_draw_item(WPARAM wParam, LPARAM lParam) { + LPDRAWITEMSTRUCT lpd; + khui_action * act; + + lpd = (LPDRAWITEMSTRUCT) lParam; + act = khui_find_action(lpd->itemID); + + if (act && act->type == KHUI_ACTIONTYPE_IDENTITY) { + + khm_draw_identity_menu_item(khm_hwnd_main_cred, lpd, act); + + } else { + int resid; + int iidx; + UINT style; + + resid = 0; + if((lpd->itemState & ODS_DISABLED) || (lpd->itemState & ODS_GRAYED)) { + resid = act->ib_icon_dis; + } + if(!resid) + resid = act->ib_icon; + + if(!resid) /* nothing to draw */ + return TRUE; + + + iidx = khui_get_icon_index(resid); + if(iidx == -1) + return TRUE; + + + style = ILD_TRANSPARENT; + if(lpd->itemState & ODS_HOTLIGHT || lpd->itemState & ODS_SELECTED) { + style |= ILD_SELECTED; + } + + khui_ilist_draw(il_icon, + iidx, + lpd->hDC, + lpd->rcItem.left, lpd->rcItem.top, style); + } + + return TRUE; +} + +void khm_track_menu(int menu) { + TBBUTTON bi; + RECT r; + RECT wr; + + if (menu != -1) + mm_last_hot_item = menu; + + if (mm_last_hot_item != -1) { + SendMessage(khui_main_menu_toolbar, + TB_GETBUTTON, + mm_last_hot_item, + (LPARAM) &bi); + + SendMessage(khui_main_menu_toolbar, + TB_GETITEMRECT, + mm_last_hot_item, + (LPARAM) &r); + + GetWindowRect(khui_main_menu_toolbar, &wr); + + khm_menu_show_panel(bi.idCommand, wr.left + r.left, wr.top + r.bottom); + + r.left = 0; + + if (mm_next_hot_item != -1) { + mm_last_hot_item = mm_next_hot_item; + mm_next_hot_item = -1; + + PostMessage(khm_hwnd_main, WM_COMMAND, + MAKEWPARAM(KHUI_PACTION_MENU,0), + MAKELPARAM(mm_last_hot_item,1)); + } + } +} + +void khm_menu_track_current(void) { + khm_track_menu(-1); +} + +LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam) { + if((HIWORD(wParam) == 0xffff && lParam == 0) || + (HIWORD(wParam) & MF_POPUP)) { + /* the menu was closed */ + khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL); + } else { + khui_action * act; + int id; + wchar_t buf[MAX_RES_STRING] = L""; + + id = LOWORD(wParam); + act = khui_find_action(id); + if(act == NULL || (act->is_tooltip == 0 && act->tooltip == NULL)) + khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, NULL); + else { + khm_get_action_tooltip(act->cmd, buf, sizeof(buf)); + + khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf); + } + } + return 0; +} + +HHOOK mm_hevt_hook = NULL; +HWND mm_hwnd_menu_panel = NULL; + +LRESULT CALLBACK mm_event_filter(int code, + WPARAM wParam, + LPARAM lParam) { + MSG * m; + RECT r; + int x,y; + + if (code == MSGF_MENU) { + /* do stuff */ + m = (MSG *) lParam; + GetWindowRect(khui_main_menu_toolbar, &r); + + if (m->hwnd != khm_hwnd_main) + mm_hwnd_menu_panel = m->hwnd; + + switch(m->message) { + case WM_MOUSEMOVE: + + x = GET_X_LPARAM(m->lParam); + y = GET_Y_LPARAM(m->lParam); + x -= r.left; + y -= r.top; + + SendMessage(khui_main_menu_toolbar, + m->message, + m->wParam, + MAKELPARAM(x,y)); + break; + } + } + + return CallNextHookEx(mm_hevt_hook, code, wParam, lParam); +} + + +void mm_begin_hot_track(void) { + + if (mm_hevt_hook) + UnhookWindowsHookEx(mm_hevt_hook); + + mm_hevt_hook = SetWindowsHookEx(WH_MSGFILTER, + mm_event_filter, + NULL, + GetCurrentThreadId()); +} + +void mm_end_hot_track(void) { + if (mm_hevt_hook) + UnhookWindowsHookEx(mm_hevt_hook); + + mm_hevt_hook = NULL; + mm_hwnd_menu_panel = NULL; +} + +void mm_cancel_menu(void) { + if (mm_hwnd_menu_panel) + SendMessage(mm_hwnd_menu_panel, WM_CANCELMODE, 0, 0); +} + +LRESULT khm_menu_notify_main(LPNMHDR notice) { + LPNMTOOLBAR nmt; + LRESULT ret = FALSE; + RECT r; + khui_menu_def * mmdef; + khui_action_ref * mm; + int nmm; + + mmdef = khui_find_menu(KHUI_MENU_MAIN); + mm = mmdef->items; + nmm = (int) khui_action_list_length(mm); + + GetWindowRect(khui_main_menu_toolbar, &r); + + nmt = (LPNMTOOLBAR) notice; + switch(notice->code) { + case TBN_DROPDOWN: + khm_track_menu(-1); + /* + khm_menu_show_panel(nmt->iItem, + r.left + nmt->rcButton.left, + r.top + nmt->rcButton.bottom); + */ + ret = TBDDRET_DEFAULT; + break; + + case TBN_HOTITEMCHANGE: + { + LPNMTBHOTITEM nmhi; + int new_item = -1; + + nmhi = (LPNMTBHOTITEM) notice; + + if(nmhi->dwFlags & HICF_LEAVING) + new_item = -1; + else { + int i; + for(i=0; i < nmm; i++) { + if(mm[i].action == nmhi->idNew) { + new_item = i; + break; + } + } + } + + if (mm_hot_track && + new_item != mm_last_hot_item && + new_item != -1 && + mm_last_hot_item != -1) { + + EndMenu(); + mm_next_hot_item = new_item; + + } + + ret = 0; + + if (!mm_hot_track || new_item != -1) + mm_last_hot_item = new_item; + + } break; + + default: + /* hmm. what to do */ + ret = FALSE; + } + return ret; +} + +struct identity_action_map { + khm_handle identity; + khm_int32 renew_cmd; + khm_int32 destroy_cmd; + khm_int32 new_cmd; + khm_int32 setdef_cmd; + int refreshcycle; +}; + +#define IDMAP_ALLOC_INCR 8 + +struct identity_action_map * id_action_map = NULL; +khm_size n_id_action_map = 0; +khm_size nc_id_action_map = 0; + +int idcmd_refreshcycle = 0; + +static struct identity_action_map * +create_identity_cmd_map(khm_handle ident) { + + struct identity_action_map * actmap; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t fmt[128]; + wchar_t caption[KHUI_MAXCCH_SHORT_DESC]; + wchar_t tooltip[KHUI_MAXCCH_SHORT_DESC]; + wchar_t actionname[KHUI_MAXCCH_NAME]; + khm_size cb; + + if (n_id_action_map + 1 > nc_id_action_map) { + nc_id_action_map = UBOUNDSS(n_id_action_map + 1, + IDMAP_ALLOC_INCR, + IDMAP_ALLOC_INCR); +#ifdef DEBUG + assert(nc_id_action_map > n_id_action_map + 1); +#endif + id_action_map = PREALLOC(id_action_map, + nc_id_action_map * sizeof(id_action_map[0])); +#ifdef DEBUG + assert(id_action_map); +#endif + ZeroMemory(&id_action_map[n_id_action_map], + sizeof(id_action_map[0]) * (nc_id_action_map - n_id_action_map)); + } + + actmap = &id_action_map[n_id_action_map]; + n_id_action_map++; + + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + + actmap->identity = ident; + kcdb_identity_hold(ident); + +#define GETFORMAT(I) do { fmt[0] = L'\0'; LoadString(khm_hInstance, I, fmt, ARRAYLENGTH(fmt)); } while(0) +#define EXPFORMAT(d,s) do { StringCbPrintf(d, sizeof(d), fmt, s); } while(0) + /* renew */ + + GETFORMAT(IDS_IDACTIONT_RENEW); + EXPFORMAT(tooltip, idname); + + GETFORMAT(IDS_IDACTION_RENEW); + EXPFORMAT(caption, idname); + + StringCbPrintf(actionname, sizeof(actionname), L"R:%s", idname); + + actmap->renew_cmd = + khui_action_create(actionname, caption, tooltip, NULL, + KHUI_ACTIONTYPE_TRIGGER, NULL); + + /* destroy */ + + GETFORMAT(IDS_IDACTIONT_DESTROY); + EXPFORMAT(tooltip, idname); + + GETFORMAT(IDS_IDACTION_DESTROY); + EXPFORMAT(caption, idname); + + StringCbPrintf(actionname, sizeof(actionname), L"D:%s", idname); + + actmap->destroy_cmd = + khui_action_create(actionname, caption, tooltip, NULL, + KHUI_ACTIONTYPE_TRIGGER, NULL); + + /* new */ + + GETFORMAT(IDS_IDACTIONT_NEW); + EXPFORMAT(tooltip, idname); + + GETFORMAT(IDS_IDACTION_NEW); + EXPFORMAT(caption, idname); + + StringCbPrintf(actionname, sizeof(actionname), L"N:%s", idname); + + actmap->new_cmd = + khui_action_create(actionname, caption, tooltip, NULL, + KHUI_ACTIONTYPE_TRIGGER, NULL); + + /* set default */ + GETFORMAT(IDS_IDACTIONT_SETDEF); + EXPFORMAT(tooltip, idname); + + GETFORMAT(IDS_IDACTION_SETDEF); + EXPFORMAT(caption, idname); + + StringCbPrintf(actionname, sizeof(actionname), L"E:%s", idname); + + actmap->setdef_cmd = + khui_action_create(actionname, caption, tooltip, ident, + KHUI_ACTIONTYPE_IDENTITY, NULL); + + actmap->refreshcycle = idcmd_refreshcycle; + +#undef GETFORMAT +#undef EXPFORMAT + + return actmap; +} + +static void +purge_identity_cmd_map(void) { + khm_size i; + + for (i=0; i < n_id_action_map; i++) { + khm_handle ident; + + if (id_action_map[i].refreshcycle != idcmd_refreshcycle) { + ident = id_action_map[i].identity; + id_action_map[i].identity = NULL; + kcdb_identity_release(ident); + + khui_action_delete(id_action_map[i].renew_cmd); + khui_action_delete(id_action_map[i].destroy_cmd); + khui_action_delete(id_action_map[i].new_cmd); + khui_action_delete(id_action_map[i].setdef_cmd); + + id_action_map[i].renew_cmd = 0; + id_action_map[i].destroy_cmd = 0; + id_action_map[i].new_cmd = 0; + id_action_map[i].setdef_cmd = 0; + } + } +} + +static struct identity_action_map * +get_identity_cmd_map(khm_handle ident) { + khm_size i; + + for (i=0; i < n_id_action_map; i++) { + if (kcdb_identity_is_equal(id_action_map[i].identity, + ident)) + break; + } + + if (i < n_id_action_map) { + id_action_map[i].refreshcycle = idcmd_refreshcycle; + return &id_action_map[i]; + } else { + return create_identity_cmd_map(ident); + } +} + +khm_int32 +khm_get_identity_renew_action(khm_handle ident) { + struct identity_action_map * map; + + map = get_identity_cmd_map(ident); + + if (map) + return map->renew_cmd; + else + return 0; +} + +khm_int32 +khm_get_identity_destroy_action(khm_handle ident) { + struct identity_action_map * map; + + map = get_identity_cmd_map(ident); + + if (map) + return map->destroy_cmd; + else + return 0; +} + +khm_int32 +khm_get_identity_setdef_action(khm_handle ident) { + struct identity_action_map * map; + + map = get_identity_cmd_map(ident); + + if (map) + return map->setdef_cmd; + else + return 0; +} + +khm_int32 +khm_get_identity_new_creds_action(khm_handle ident) { + struct identity_action_map * map; + + map = get_identity_cmd_map(ident); + + if (map) + return map->new_cmd; + else + return 0; +} + +void +khm_refresh_identity_menus(void) { + khui_menu_def * renew_def = NULL; + khui_menu_def * dest_def = NULL; + khui_menu_def * setdef_def = NULL; + wchar_t * idlist = NULL; + wchar_t * idname = NULL; + khm_size cb = 0; + khm_size n_idents = 0; + khm_size t; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_cw = NULL; + khm_int32 idflags; + khm_int32 def_sticky = 0; + khm_int32 all_identities = 0; + khm_boolean sticky_done = FALSE; + khm_boolean added_dest = FALSE; + khm_boolean added_setdef = FALSE; + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) { + khc_read_int32(csp_cw, L"DefaultSticky", &def_sticky); + khc_read_int32(csp_cw, L"ViewAllIdents", &all_identities); + khc_close_space(csp_cw); + csp_cw = NULL; + } + + kcdb_identity_refresh_all(); + + khui_action_lock(); + + idcmd_refreshcycle++; + + do { + if (idlist) + PFREE(idlist); + idlist = NULL; + cb = 0; + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE, + KCDB_IDENT_FLAG_ACTIVE, + NULL, + &cb, + &n_idents); + if (rv != KHM_ERROR_TOO_LONG || cb == 0 || cb == sizeof(wchar_t) * 2) + break; + + idlist = PMALLOC(cb); +#ifdef DEBUG + assert(idlist); +#endif + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE, + KCDB_IDENT_FLAG_ACTIVE, + idlist, + &cb, + &n_idents); + if (rv == KHM_ERROR_TOO_LONG) + continue; + + if (KHM_FAILED(rv)) { + /* something else went wrong. hmm. */ + if (idlist) + PFREE(idlist); + idlist = NULL; + } + break; + + } while(TRUE); + + renew_def = khui_find_menu(KHUI_MENU_RENEW_CRED); + dest_def = khui_find_menu(KHUI_MENU_DESTROY_CRED); + setdef_def = khui_find_menu(KHUI_MENU_SETDEF); +#ifdef DEBUG + assert(renew_def); + assert(dest_def); + assert(setdef_def); +#endif + + t = khui_menu_get_size(renew_def); + while(t) { + khui_menu_remove_action(renew_def, 0); + t--; + } + + t = khui_menu_get_size(dest_def); + while(t) { + khui_menu_remove_action(dest_def, 0); + t--; + } + + t = khui_menu_get_size(setdef_def); + while(t) { + khui_menu_remove_action(setdef_def, 0); + t--; + } + + if (idlist != NULL && n_idents > 1) { + khui_menu_insert_action(renew_def, 0, KHUI_ACTION_RENEW_ALL, 0); + khui_menu_insert_action(renew_def, 1, KHUI_MENU_SEP, 0); + + khui_menu_insert_action(dest_def, 0, KHUI_ACTION_DESTROY_ALL, 0); + khui_menu_insert_action(dest_def, 1, KHUI_MENU_SEP, 0); + } + + for (idname = idlist; idname && idname[0]; + idname = multi_string_next(idname)) { + khm_handle identity = NULL; + + if (KHM_FAILED(kcdb_identity_create(idname, 0, &identity))) { +#ifdef DEBUG + assert(FALSE); +#endif + continue; + } + + idflags = 0; + kcdb_identity_get_flags(identity, &idflags); + + if (!(idflags & KCDB_IDENT_FLAG_STICKY) && def_sticky) { + kcdb_identity_set_flags(identity, + KCDB_IDENT_FLAG_STICKY, + KCDB_IDENT_FLAG_STICKY); + idflags |= KCDB_IDENT_FLAG_STICKY; + sticky_done = TRUE; + } + + if (!(idflags & KCDB_IDENT_FLAG_EMPTY)) { + khui_menu_insert_action(renew_def, 1000, + khm_get_identity_renew_action(identity), + 0); + + khui_menu_insert_action(dest_def, 1000, + khm_get_identity_destroy_action(identity), + 0); + added_dest = TRUE; + } + + if (all_identities || + !(idflags & KCDB_IDENT_FLAG_EMPTY) || + (idflags & KCDB_IDENT_FLAG_STICKY)) { + + khui_menu_insert_action(setdef_def, 1000, + khm_get_identity_setdef_action(identity), + 0); + added_setdef = TRUE; + } + + kcdb_identity_release(identity); + } + + if (idlist) { + PFREE(idlist); + idlist = NULL; + } + + if (added_dest) { + khui_enable_action(KHUI_MENU_RENEW_CRED, TRUE); + khui_enable_action(KHUI_MENU_DESTROY_CRED, TRUE); + khui_enable_action(KHUI_ACTION_RENEW_CRED, TRUE); + khui_enable_action(KHUI_ACTION_DESTROY_CRED, TRUE); + } else { + khui_enable_action(KHUI_MENU_RENEW_CRED, FALSE); + khui_enable_action(KHUI_MENU_DESTROY_CRED, FALSE); + khui_enable_action(KHUI_ACTION_RENEW_CRED, FALSE); + khui_enable_action(KHUI_ACTION_DESTROY_CRED, FALSE); + } + + if (added_setdef) { + khui_enable_action(KHUI_MENU_SETDEF, TRUE); + } else { + khui_enable_action(KHUI_MENU_SETDEF, FALSE); + } + + purge_identity_cmd_map(); + + khui_action_unlock(); + + khui_refresh_actions(); + + if (sticky_done) { + InvalidateRect(khm_hwnd_main_cred, NULL, TRUE); + } +} + +khm_boolean +khm_check_identity_menu_action(khm_int32 act_id) { + + if (act_id == KHUI_ACTION_DESTROY_ALL) { + khm_size i; + + for (i=0; i < n_id_action_map; i++) { + if (id_action_map[i].identity != NULL) { + khm_cred_destroy_identity(id_action_map[i].identity); + } + } + + return TRUE; + } else if (act_id == KHUI_ACTION_RENEW_ALL) { + khm_size i; + + for (i=0; i < n_id_action_map; i++) { + if (id_action_map[i].identity != NULL) { + khm_cred_renew_identity(id_action_map[i].identity); + } + } + + return TRUE; + } else { + khm_size i; + + for (i=0; i < n_id_action_map; i++) { + if (id_action_map[i].identity == NULL) + continue; + + if (id_action_map[i].renew_cmd == act_id) { + khm_cred_renew_identity(id_action_map[i].identity); + return TRUE; + } + + if (id_action_map[i].destroy_cmd == act_id) { + khm_cred_destroy_identity(id_action_map[i].identity); + return TRUE; + } + + if (id_action_map[i].new_cmd == act_id) { + khm_cred_obtain_new_creds_for_ident(id_action_map[i].identity, + NULL); + return TRUE; + } + + if (id_action_map[i].setdef_cmd == act_id) { + khm_cred_set_default_identity(id_action_map[i].identity); + + return TRUE; + } + } + } + + return FALSE; +} + + +HMENU khui_hmenu_main = NULL; + +void khm_menu_refresh_items(void) { + khui_menu_def * def; + + if (!khui_hmenu_main) + return; + + khui_action_lock(); + + def = khui_find_menu(KHUI_MENU_MAIN); + + refresh_menu(khui_hmenu_main, def); + + khui_action_unlock(); + + DrawMenuBar(khm_hwnd_main); +} + +void khm_menu_create_main(HWND parent) { + HMENU hmenu; + khui_menu_def * def; + + def = khui_find_menu(KHUI_MENU_MAIN); + + hmenu = mm_create_menu_from_def(def, TRUE); + + SetMenu(parent, hmenu); + + khui_hmenu_main = hmenu; + + return; + +#ifdef USE_EXPLORER_STYLE_MENU_BAR + HWND hwtb; + REBARBANDINFO rbi; + SIZE sz; + int i; + khui_menu_def * mmdef; + khui_action_ref * mm; + int nmm; + + mmdef = khui_find_menu(KHUI_MENU_MAIN); + mm = mmdef->items; + nmm = (int) khui_action_list_length(mm); + + hwtb = CreateWindowEx(0 +#if (_WIN32_IE >= 0x0501) + | TBSTYLE_EX_MIXEDBUTTONS +#endif + , + TOOLBARCLASSNAME, + (LPWSTR) NULL, + WS_CHILD | + CCS_ADJUSTABLE | + TBSTYLE_FLAT | + TBSTYLE_AUTOSIZE | + TBSTYLE_LIST | + CCS_NORESIZE | + CCS_NOPARENTALIGN | + CCS_NODIVIDER, + 0, 0, 0, 0, rebar, + (HMENU) NULL, khm_hInstance, + NULL); + + if(!hwtb) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + khui_main_menu_toolbar = hwtb; + + SendMessage(hwtb, + TB_BUTTONSTRUCTSIZE, + (WPARAM) sizeof(TBBUTTON), + 0); + + for(i=0; i<nmm; i++) { + khui_add_action_to_toolbar(hwtb, + khui_find_action(mm[i].action), + KHUI_TOOLBAR_ADD_TEXT | + KHUI_TOOLBAR_ADD_DROPDOWN | + KHUI_TOOLBAR_VARSIZE, + NULL); + } + + SendMessage(hwtb, + TB_AUTOSIZE, + 0,0); + + SendMessage(hwtb, + TB_GETMAXSIZE, + 0, + (LPARAM) &sz); + + ZeroMemory(&rbi, sizeof(rbi)); + + rbi.cbSize = sizeof(rbi); + + rbi.fMask = + RBBIM_ID | + RBBIM_STYLE | + RBBIM_CHILD | + RBBIM_CHILDSIZE | + RBBIM_SIZE | + RBBIM_IDEALSIZE; + + rbi.fStyle = + RBBS_USECHEVRON; + + rbi.hwndChild = hwtb; + rbi.wID = KHUI_MENU_MAIN; + rbi.cx = sz.cx; + rbi.cxMinChild = rbi.cx; + rbi.cxIdeal = rbi.cx; + rbi.cyMinChild = sz.cy; + rbi.cyChild = rbi.cyMinChild; + rbi.cyIntegral = rbi.cyMinChild; + rbi.cyMaxChild = rbi.cyMinChild; + + SendMessage(rebar, + RB_INSERTBAND, + 0, + (LPARAM) &rbi); +#endif +} diff --git a/krb5-1-6/src/windows/identity/ui/mainmenu.h b/krb5-1-6/src/windows/identity/ui/mainmenu.h new file mode 100644 index 000000000..54504d5fb --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/mainmenu.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_MAINMENU_H +#define __KHIMAIRA_MAINMENU_H + +extern HWND khui_main_menu_toolbar; + +#define MENU_ACTIVATE_DEFAULT -1 +#define MENU_ACTIVATE_LEFT -2 +#define MENU_ACTIVATE_RIGHT -3 +#define MENU_ACTIVATE_NONE -4 + +extern int mm_last_hot_item; +extern BOOL mm_hot_track; + +void khm_menu_create_main(HWND rebar); +LRESULT khm_menu_handle_select(WPARAM wParam, LPARAM lParam); +LRESULT khm_menu_notify_main(LPNMHDR notice); +LRESULT khm_menu_activate(int menu_id); +void khm_menu_show_panel(int id, LONG x, LONG y); +void khm_menu_track_current(void); +LRESULT khm_menu_measure_item(WPARAM wParam, LPARAM lparam); +LRESULT khm_menu_draw_item(WPARAM wParam, LPARAM lparam); +void khm_menu_refresh_items(void); +khm_boolean khm_check_identity_menu_action(khm_int32 act_id); +void khm_refresh_identity_menus(void); +void khm_get_action_tooltip(khm_int32 action, wchar_t * buf, khm_size cb_buf); +void khm_get_action_caption(khm_int32 action, wchar_t * buf, khm_size cb_buf); + +khm_int32 khm_get_identity_destroy_action(khm_handle ident); +khm_int32 khm_get_identity_renew_action(khm_handle ident); +khm_int32 khm_get_identity_new_creds_action(khm_handle ident); + +static HMENU mm_create_menu_from_def(khui_menu_def * def, BOOL main); +static void mm_show_panel_def(khui_menu_def * def, LONG x, LONG y); + +void khui_init_menu(void); +void khui_exit_menu(void); + +#define MENU_SIZE_ICON_X 16 +#define MENU_SIZE_ICON_Y 16 + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/mainwnd.c b/krb5-1-6/src/windows/identity/ui/mainwnd.c new file mode 100644 index 000000000..42fcd193c --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/mainwnd.c @@ -0,0 +1,1369 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<intaction.h> +#include<assert.h> + +ATOM khm_main_window_class; +ATOM khm_null_window_class; +HWND khm_hwnd_null; +HWND khm_hwnd_main; +HWND khm_hwnd_rebar; +HWND khm_hwnd_main_cred; + +int khm_main_wnd_mode = KHM_MAIN_WND_NORMAL; + +#define MW_RESIZE_TIMER 1 +#define MW_RESIZE_TIMEOUT 2000 +#define MW_REFRESH_TIMER 2 +#define MW_REFRESH_TIMEOUT 600 + +void +khm_set_dialog_result(HWND hwnd, LRESULT lr) { +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_MSGRESULT, lr); +#pragma warning(pop) +} + +static void +mw_restart_refresh_timer(HWND hwnd) { + khm_handle csp_cw; + khm_int32 timeout; + + KillTimer(hwnd, MW_REFRESH_TIMER); + if (KHM_SUCCEEDED(khc_open_space(NULL, + L"CredWindow", + KHM_PERM_READ, + &csp_cw))) { + if (KHM_FAILED(khc_read_int32(csp_cw, + L"RefreshTimeout", + &timeout))) + timeout = MW_REFRESH_TIMEOUT; + khc_close_space(csp_cw); + } else { + timeout = MW_REFRESH_TIMEOUT; + } + + timeout *= 1000; /* convert to milliseconds */ + + SetTimer(hwnd, MW_REFRESH_TIMER, timeout, NULL); +} + +khm_int32 KHMAPI +mw_select_cred(khm_handle cred, void * rock) { + if (cred) + kcdb_cred_set_flags(cred, + KCDB_CRED_FLAG_SELECTED, + KCDB_CRED_FLAG_SELECTED); + + return KHM_ERROR_SUCCESS; +} + +/* perform shutdown operations */ +static void +khm_pre_shutdown(void) { + khm_handle csp_cw = NULL; + khm_handle credset = NULL; + khm_int32 t; + khm_size s; + + /* Check if we should destroy all credentials on exit... */ + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) + return; + + if (KHM_FAILED(khc_read_int32(csp_cw, L"DestroyCredsOnExit", &t)) || + !t) + goto _cleanup; + + if (KHM_FAILED(kcdb_credset_create(&credset))) + goto _cleanup; + + if (KHM_FAILED(kcdb_credset_extract(credset, NULL, NULL, + KCDB_TYPE_INVALID))) + goto _cleanup; + + if (KHM_FAILED(kcdb_credset_get_size(credset, &s)) || + s == 0) + goto _cleanup; + + kcdb_credset_apply(credset, mw_select_cred, NULL); + + khui_context_set(KHUI_SCOPE_GROUP, + NULL, + KCDB_CREDTYPE_INVALID, + NULL, + NULL, + 0, + credset); + + khm_cred_destroy_creds(TRUE, TRUE); + + _cleanup: + + if (credset) + kcdb_credset_delete(credset); + + if (csp_cw) + khc_close_space(csp_cw); +} + +void +khm_process_query_app_ver(khm_query_app_version * papp_ver) { + + if (!papp_ver || papp_ver->magic != KHM_QUERY_APP_VER_MAGIC) + return; + + papp_ver->ver_remote = app_version; + + /* the remote instance has requested swapping in. we check the + version numbers and if the remote instance is newer than us, + then we exit and let the remote instance take over. */ + if (papp_ver->request_swap) { + khm_version ver_caller = papp_ver->ver_caller; + + if (khm_compare_version(&ver_caller, &app_version) > 0) { + + papp_ver->request_swap = TRUE; + + if (khm_hwnd_main) + DestroyWindow(khm_hwnd_main); + + } else { + + papp_ver->request_swap = FALSE; + + } + } + + papp_ver->code = KHM_ERROR_SUCCESS; +} + +static void +khm_ui_cb(LPARAM lParam) { + khui_ui_callback_data * pcbdata; + + pcbdata = (khui_ui_callback_data *) lParam; + + if (pcbdata == NULL || pcbdata->magic != KHUI_UICBDATA_MAGIC) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + +#ifdef DEBUG + assert(pcbdata->cb); +#endif + + /* make the call */ + pcbdata->rv = (*pcbdata->cb)(khm_hwnd_main, pcbdata->rock); +} + + +static void +main_wnd_save_sizepos() { + RECT r; + khm_handle csp_cw; + khm_handle csp_mw; + const wchar_t * wconfig; + + KillTimer(khm_hwnd_main, MW_RESIZE_TIMER); + + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) + wconfig = L"Windows\\MainMini"; + else + wconfig = L"Windows\\Main"; + + GetWindowRect(khm_hwnd_main, &r); + + if (KHM_SUCCEEDED(khc_open_space(NULL, + L"CredWindow", + KHM_PERM_WRITE, + &csp_cw))) { + if (KHM_SUCCEEDED(khc_open_space(csp_cw, + wconfig, + KHM_PERM_WRITE, + &csp_mw))) { + khm_int32 t; + + khc_write_int32(csp_mw, L"XPos", r.left); + khc_write_int32(csp_mw, L"YPos", r.top); + khc_write_int32(csp_mw, L"Width", r.right - r.left); + khc_write_int32(csp_mw, L"Height", r.bottom - r.top); + + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t)) && + t != KHM_DOCK_NONE) { + khc_write_int32(csp_mw, L"Dock", KHM_DOCK_AUTO); + } + + khc_close_space(csp_mw); + } + + khc_close_space(csp_cw); + } +} + +LRESULT CALLBACK +khm_main_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LPNMHDR lpnm; + + switch(uMsg) { + case WM_CREATE: + khm_create_main_window_controls(hwnd); + kmq_subscribe_hwnd(KMSG_CRED, hwnd); + kmq_subscribe_hwnd(KMSG_ACT, hwnd); + kmq_subscribe_hwnd(KMSG_KMM, hwnd); + mw_restart_refresh_timer(hwnd); + + /* if the plug-ins finished loading before the window was + created, we would have missed the KMSG_KMM_I_DONE message. + So we check if the module load is complete and if so, fire + off KMSG_ACT_BEGIN_CMDLINE. */ + if (!kmm_load_pending()) + kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0); + break; + + case WM_DESTROY: + khm_pre_shutdown(); + kmq_unsubscribe_hwnd(KMSG_ACT, hwnd); + kmq_unsubscribe_hwnd(KMSG_CRED, hwnd); + kmq_unsubscribe_hwnd(KMSG_KMM, hwnd); + HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0); + PostQuitMessage(0); + break; + + case WM_NOTIFY: + lpnm = (LPNMHDR) lParam; + if(lpnm->hwndFrom == khui_main_menu_toolbar) { + return khm_menu_notify_main(lpnm); + } else if(lpnm->hwndFrom == khui_hwnd_standard_toolbar) { + return khm_toolbar_notify(lpnm); + } else if(lpnm->hwndFrom == khm_hwnd_rebar) { + return khm_rebar_notify(lpnm); + } else if(lpnm->hwndFrom == khm_hwnd_statusbar) { + return khm_statusbar_notify(lpnm); + } + break; + + case WM_HELP: + khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME); + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + /* general actions */ + case KHUI_ACTION_VIEW_REFRESH: + khm_cred_refresh(); + InvalidateRect(khm_hwnd_main_cred, NULL, FALSE); + return 0; + + case KHUI_ACTION_PASSWD_ID: + if (khm_startup.processing) + return 0; + + khm_cred_change_password(NULL); + return 0; + + case KHUI_ACTION_NEW_CRED: + if (khm_startup.processing) + return 0; + + khm_cred_obtain_new_creds(NULL); + return 0; + + case KHUI_ACTION_RENEW_CRED: + if (khm_startup.processing) + return 0; + + khm_cred_renew_creds(); + return 0; + + case KHUI_ACTION_DESTROY_CRED: + if (khm_startup.processing) + return 0; + + khm_cred_destroy_creds(FALSE, FALSE); + return 0; + + case KHUI_ACTION_SET_DEF_ID: + if (khm_startup.processing) + return 0; + + khm_cred_set_default(); + return 0; + + case KHUI_ACTION_EXIT: + DestroyWindow(hwnd); + return 0; + + case KHUI_ACTION_OPEN_APP: + khm_show_main_window(); + return 0; + + case KHUI_ACTION_CLOSE_APP: + khm_hide_main_window(); + return 0; + + case KHUI_ACTION_OPT_KHIM: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmGeneral", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_IDENTS: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmIdentities", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_APPEAR: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmAppear", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_NOTIF: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmNotifications", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_OPT_PLUGINS: { + khui_config_node node = NULL; + + khui_cfg_open(NULL, L"KhmPlugins", &node); + khm_show_config_pane(node); + } + return 0; + + case KHUI_ACTION_HELP_CTX: + khm_html_help(khm_hwnd_main, NULL, HH_HELP_CONTEXT, IDH_WELCOME); + return 0; + + case KHUI_ACTION_HELP_CONTENTS: + khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_TOC, 0); + return 0; + + case KHUI_ACTION_HELP_INDEX: + khm_html_help(khm_hwnd_main, NULL, HH_DISPLAY_INDEX, (DWORD_PTR) L""); + return 0; + + case KHUI_ACTION_HELP_ABOUT: + khm_create_about_window(); + return 0; + + case KHUI_ACTION_IMPORT: + khm_cred_import(); + return 0; + + case KHUI_ACTION_PROPERTIES: + /* properties are not handled by the main window. + Just bounce it to credwnd. However, use SendMessage + instead of PostMessage so we don't lose context */ + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + case KHUI_ACTION_UICB: + khm_ui_cb(lParam); + return 0; + + /* layout control */ + + case KHUI_ACTION_VIEW_ALL_IDS: + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + case KHUI_ACTION_LAYOUT_MINI: + + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) { + khm_set_main_window_mode(KHM_MAIN_WND_NORMAL); + } else { + khm_set_main_window_mode(KHM_MAIN_WND_MINI); + } + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + case KHUI_ACTION_LAYOUT_RELOAD: + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + case KHUI_ACTION_LAYOUT_ID: + case KHUI_ACTION_LAYOUT_TYPE: + case KHUI_ACTION_LAYOUT_LOC: + case KHUI_ACTION_LAYOUT_CUST: + khm_set_main_window_mode(KHM_MAIN_WND_NORMAL); + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + /* menu commands */ + case KHUI_PACTION_MENU: + if(HIWORD(lParam) == 1) + mm_last_hot_item = LOWORD(lParam); + return khm_menu_activate(MENU_ACTIVATE_DEFAULT); + + case KHUI_PACTION_ESC: + /* if esc is pressed while no menu is active, we close the + main window */ + if (mm_last_hot_item == -1) { + khm_close_main_window(); + return 0; + } + + /* generic, retargetting */ + case KHUI_PACTION_UP: + case KHUI_PACTION_UP_TOGGLE: + case KHUI_PACTION_UP_EXTEND: + case KHUI_PACTION_PGUP: + case KHUI_PACTION_PGUP_EXTEND: + case KHUI_PACTION_DOWN: + case KHUI_PACTION_DOWN_TOGGLE: + case KHUI_PACTION_DOWN_EXTEND: + case KHUI_PACTION_PGDN: + case KHUI_PACTION_PGDN_EXTEND: + case KHUI_PACTION_LEFT: + case KHUI_PACTION_RIGHT: + case KHUI_PACTION_ENTER: + /* menu tracking */ + if(mm_last_hot_item != -1) { + switch(LOWORD(wParam)) { + case KHUI_PACTION_LEFT: + khm_menu_activate(MENU_ACTIVATE_LEFT); + break; + + case KHUI_PACTION_RIGHT: + khm_menu_activate(MENU_ACTIVATE_RIGHT); + break; + + case KHUI_PACTION_ESC: + case KHUI_PACTION_ENTER: + khm_menu_activate(MENU_ACTIVATE_NONE); + break; + + case KHUI_PACTION_DOWN: + khm_menu_track_current(); + break; + } + return 0; + } + + /*FALLTHROUGH*/ + case KHUI_PACTION_DELETE: + + case KHUI_PACTION_SELALL: + /* otherwise fallthrough and bounce to the creds window */ + return SendMessage(khm_hwnd_main_cred, uMsg, + wParam, lParam); + + default: + /* handle custom actions here */ + { + khui_action * act; + + /* check if this is an identity menu action. (custom + actions that were created for renewing or + destroying specific identities). */ + if (khm_check_identity_menu_action(LOWORD(wParam))) + break; + + act = khui_find_action(LOWORD(wParam)); + if (act && act->listener) { + kmq_post_sub_msg(act->listener, KMSG_ACT, KMSG_ACT_ACTIVATE, act->cmd, NULL); + return 0; + } + } + } + break; /* WM_COMMAND */ + + case WM_SYSCOMMAND: + switch(wParam & 0xfff0) { + case SC_MINIMIZE: + khm_hide_main_window(); + return 0; + + case SC_CLOSE: + khm_close_main_window(); + return 0; + } + break; + + case WM_MEASUREITEM: + /* sent to measure the bitmaps associated with a menu item */ + if(!wParam) /* sent by menu */ + return khm_menu_measure_item(wParam, lParam); + break; + + case WM_DRAWITEM: + /* sent to draw a menu item */ + if(!wParam) + return khm_menu_draw_item(wParam, lParam); + break; + + case WM_ERASEBKGND: + /* Don't erase the background. The whole client area is + covered with children. It doesn't need to be erased */ + return TRUE; + break; + + case WM_SIZE: + if(hwnd == khm_hwnd_main && + (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)) { + int cwidth, cheight; + RECT r_rebar, r_status; + + cwidth = LOWORD(lParam); + cheight = HIWORD(lParam); + + /* resize the rebar control */ + SendMessage(khm_hwnd_rebar, WM_SIZE, 0, 0); + + khm_update_statusbar(hwnd); + + GetWindowRect(khm_hwnd_rebar, &r_rebar); + GetWindowRect(khm_hwnd_statusbar, &r_status); + + /* the cred window fills the area between the rebar + and the status bar */ + MoveWindow(khm_hwnd_main_cred, 0, + r_rebar.bottom - r_rebar.top, + r_status.right - r_status.left, + r_status.top - r_rebar.bottom, TRUE); + + SetTimer(hwnd, + MW_RESIZE_TIMER, + MW_RESIZE_TIMEOUT, + NULL); + return 0; + } + break; + + case WM_MOVE: + { + SetTimer(hwnd, + MW_RESIZE_TIMER, + MW_RESIZE_TIMEOUT, + NULL); + + return 0; + } + break; + + case WM_MOVING: + { + RECT * r; + + r = (RECT *) lParam; + khm_adjust_window_dimensions_for_display(r, + KHM_DOCK_AUTO | KHM_DOCKF_XBORDER); + } + return TRUE; + + case WM_TIMER: + if (wParam == MW_RESIZE_TIMER) { + main_wnd_save_sizepos(); + + return 0; + + } else if (wParam == MW_REFRESH_TIMER) { + kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); + + return 0; + + } + break; + + case WM_MENUSELECT: + return khm_menu_handle_select(wParam, lParam); + + case KMQ_WM_DISPATCH: + { + kmq_message * m; + khm_int32 rv = KHM_ERROR_SUCCESS; + + kmq_wm_begin(lParam, &m); + if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_REFRESH) { + khm_menu_refresh_items(); + khm_update_standard_toolbar(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_BEGIN_CMDLINE) { + khm_cred_begin_startup_actions(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_CONTINUE_CMDLINE) { + khm_cred_process_startup_actions(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_END_CMDLINE) { + /* nothing yet */ + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_SYNC_CFG) { + khm_refresh_config(); + } else if (m->type == KMSG_ACT && + m->subtype == KMSG_ACT_ACTIVATE) { + /* some custom action fired */ + + khm_int32 action; + khui_action * paction; + + action = m->uparam; + paction = khui_find_action(action); + if (paction && paction->data == (void *) CFGACTION_MAGIC) { + /* a custom configuration needs to be invoked */ + khui_config_node node; + + if (KHM_SUCCEEDED(khui_cfg_open(NULL, paction->name, &node))) { + khm_show_config_pane(node); + khui_cfg_release(node); + } + } + } else if (m->type == KMSG_CRED && + m->subtype == KMSG_CRED_REFRESH) { + mw_restart_refresh_timer(hwnd); + } else if (m->type == KMSG_CRED && + m->subtype == KMSG_CRED_ADDR_CHANGE) { + khm_cred_addr_change(); + } else if (m->type == KMSG_CRED && + m->subtype == KMSG_CRED_ROOTDELTA) { + khm_refresh_identity_menus(); + } else if (m->type == KMSG_KMM && + m->subtype == KMSG_KMM_I_DONE) { + kmq_post_message(KMSG_ACT, KMSG_ACT_BEGIN_CMDLINE, 0, 0); + } + + return kmq_wm_end(m, rv); + } + + case WM_KHUI_ASSIGN_COMMANDLINE_V1: + { + HANDLE hmap; + void * xfer; + wchar_t mapname[256]; + khm_startup_options_v1 * pv1opt; + int code = KHM_ERROR_SUCCESS; + + StringCbPrintf(mapname, sizeof(mapname), + COMMANDLINE_MAP_FMT, (DWORD) lParam); + + hmap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname); + + if (hmap == NULL) + return 1; + + xfer = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, + sizeof(*pv1opt)); + + if (xfer) { + pv1opt = (khm_startup_options_v1 *) xfer; + + khm_startup.init = pv1opt->init; + khm_startup.import = pv1opt->import; + khm_startup.renew = pv1opt->renew; + khm_startup.destroy = pv1opt->destroy; + + khm_startup.autoinit = pv1opt->autoinit; + khm_startup.error_exit = FALSE; + + khm_startup.no_main_window = FALSE; + khm_startup.remote_exit = FALSE; + khm_startup.display = 0; + + UnmapViewOfFile(xfer); + } else { + code = KHM_ERROR_NOT_FOUND; + } + + CloseHandle(hmap); + + if(InSendMessage()) + ReplyMessage(code); + + if (code == KHM_ERROR_SUCCESS) { + khm_startup.exit = FALSE; + + khm_startup.seen = FALSE; + khm_startup.remote = TRUE; +#ifdef DEBUG + assert(!khm_startup.processing); +#endif + khm_startup.processing = FALSE; + + khm_cred_begin_startup_actions(); + } + + return code; + } + + case WM_KHUI_ASSIGN_COMMANDLINE_V2: + { + HANDLE hmap; + void * xfer; + wchar_t mapname[256]; + khm_startup_options_v2 *pv2opt = NULL; + khm_startup_options_v3 *pv3opt = NULL; + int code = KHM_ERROR_SUCCESS; + + StringCbPrintf(mapname, sizeof(mapname), + COMMANDLINE_MAP_FMT, (DWORD) lParam); + + hmap = OpenFileMapping(FILE_MAP_WRITE, FALSE, mapname); + + if (hmap == NULL) + return 1; + + xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, + sizeof(*pv2opt)); + + if (xfer) { + pv2opt = (khm_startup_options_v2 *) xfer; + + if (pv2opt->magic != STARTUP_OPTIONS_MAGIC || + (pv2opt->cb_size != sizeof(*pv2opt) && + pv2opt->cb_size != sizeof(*pv3opt))) { + code = KHM_ERROR_INVALID_PARAM; + goto done_with_v2_opt; + } + + khm_startup.init = pv2opt->init; + khm_startup.import = pv2opt->import; + khm_startup.renew = pv2opt->renew; + khm_startup.destroy = pv2opt->destroy; + + khm_startup.autoinit = pv2opt->autoinit; + khm_startup.exit = pv2opt->remote_exit; + + pv2opt->code = KHM_ERROR_SUCCESS; + + if (pv2opt->cb_size == sizeof(*pv3opt)) { + pv3opt = (khm_startup_options_v3 *) xfer; + + khm_startup.display = pv3opt->remote_display; + } else { + khm_startup.display = 0; + } + + done_with_v2_opt: + UnmapViewOfFile(xfer); + } else { + code = KHM_ERROR_NOT_FOUND; + } + + CloseHandle(hmap); + + if(InSendMessage()) + ReplyMessage(code); + + if (code == KHM_ERROR_SUCCESS) { + khm_startup.seen = FALSE; + khm_startup.remote = TRUE; +#ifdef DEBUG + assert(!khm_startup.processing); +#endif + khm_startup.processing = FALSE; + + khm_cred_begin_startup_actions(); + } + + return code; + } + + case WM_KHUI_QUERY_APP_VERSION: + { + HANDLE hmap; + void * xfer; + wchar_t mapname[256]; + + StringCbPrintf(mapname, sizeof(mapname), + QUERY_APP_VER_MAP_FMT, (DWORD) lParam); + + hmap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, + FALSE, mapname); + + if (hmap == NULL) + return 1; + + xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, + sizeof(khm_query_app_version)); + + if (xfer) { + khm_process_query_app_ver((khm_query_app_version *) xfer); + + UnmapViewOfFile(xfer); + } + + CloseHandle(hmap); + } + return 0; + + } + return DefWindowProc(hwnd,uMsg,wParam,lParam); +} + +LRESULT CALLBACK +khm_null_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +LRESULT +khm_rebar_notify(LPNMHDR lpnm) { + switch(lpnm->code) { +#if (_WIN32_WINNT >= 0x0501) + case RBN_AUTOBREAK: + { + LPNMREBARAUTOBREAK lpra = (LPNMREBARAUTOBREAK) lpnm; + lpra->fAutoBreak = TRUE; + } + break; +#endif + case RBN_BEGINDRAG: + { + LPNMREBAR lprb = (LPNMREBAR) lpnm; + if ((lprb->dwMask & RBNM_ID) && + lprb->wID == 0) + return 1; + else + return 0; + } + break; + + case NM_CUSTOMDRAW: + return CDRF_DODEFAULT; + break; + } + + return 1; +} + +void +khm_create_main_window_controls(HWND hwnd_main) { + REBARINFO rbi; + HWND hwRebar; + + khm_menu_create_main(hwnd_main); + + hwRebar = + CreateWindowEx(WS_EX_TOOLWINDOW, + REBARCLASSNAME, + L"Rebar", + WS_CHILD | + WS_VISIBLE| + WS_CLIPSIBLINGS | + WS_CLIPCHILDREN | + CCS_NODIVIDER | + RBS_VARHEIGHT | + RBS_FIXEDORDER, + 0,0,0,0, + hwnd_main, + NULL, + khm_hInstance, + NULL); + + if(!hwRebar) { + DWORD dwe = GetLastError(); + return; + } + + khm_hwnd_rebar = hwRebar; + + rbi.cbSize = sizeof(rbi); + rbi.fMask = 0; + rbi.himl = (HIMAGELIST) NULL; + if(!SendMessage(hwRebar, RB_SETBARINFO, 0, (LPARAM) &rbi)) + return; + + /* self attach */ + khm_create_standard_toolbar(hwRebar); + khm_create_statusbar(hwnd_main); + + /* manual attach */ + khm_hwnd_main_cred = khm_create_credwnd(hwnd_main); +} + +void +khm_adjust_window_dimensions_for_display(RECT * pr, int dock) { + + HMONITOR hmon; + RECT rm; + long x, y, width, height; + + x = pr->left; + y = pr->top; + width = pr->right - pr->left; + height = pr->bottom - pr->top; + + /* if the rect doesn't intersect with the display area of any + monitor, we just default to the primary monitor. */ + hmon = MonitorFromRect(pr, MONITOR_DEFAULTTOPRIMARY); + + if (hmon == NULL) { + /* huh? we'll just center this on the primary screen */ + goto nomonitor; + } else { + MONITORINFO mi; + + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + + if (!GetMonitorInfo(hmon, &mi)) + goto nomonitor; + + CopyRect(&rm, &mi.rcWork); + + goto adjust_dims; + } + + nomonitor: + /* for some reason we couldn't get a handle on a monitor or we + couldn't get the metrics for that monitor. We default to + setting things up on the primary monitor. */ + + SetRectEmpty(&rm); + if (!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &rm, 0)) + goto done_with_monitor; + + adjust_dims: + + if (width > (rm.right - rm.left)) + width = rm.right - rm.left; + if (height > (rm.bottom - rm.top)) + height = rm.bottom - rm.top; + + switch (dock & KHM_DOCKF_DOCKHINT) { + case KHM_DOCK_TOPLEFT: + x = rm.left; + y = rm.top; + break; + + case KHM_DOCK_TOPRIGHT: + x = rm.right - width; + y = rm.top; + break; + + case KHM_DOCK_BOTTOMRIGHT: + x = rm.right - width; + y = rm.bottom - height; + break; + + case KHM_DOCK_BOTTOMLEFT: + x = rm.left; + y = rm.bottom - height; + break; + + case KHM_DOCK_AUTO: + { + int cxt, cyt; + + cxt = GetSystemMetrics(SM_CXDRAG); + cyt = GetSystemMetrics(SM_CYDRAG); + + if (x > rm.left && (x - rm.left) < cxt) + x = rm.left; + else if ((x + width) < rm.right && (rm.right - (x + width)) < cxt) + x = rm.right - width; + + if (y > rm.top && (y - rm.top) < cyt) + y = rm.top; + else if ((y + height) < rm.bottom && (rm.bottom - (y + height)) < cyt) + y = rm.bottom - height; + } + break; + } + + if (!(dock & KHM_DOCKF_XBORDER)) { + if (x < rm.left) + x = rm.left; + if (x + width > rm.right) + x = rm.right - width; + if (y < rm.top) + y = rm.top; + if (y + height > rm.bottom) + y = rm.bottom - height; + } + + done_with_monitor: + pr->left = x; + pr->top = y; + pr->right = x + width; + pr->bottom = y + height; + +} + +void +khm_get_main_window_rect(RECT * pr) { + khm_handle csp_mw = NULL; + int x,y,width,height,dock; + RECT r; + const wchar_t * wconfig; + + x = CW_USEDEFAULT; + y = CW_USEDEFAULT; + width = CW_USEDEFAULT; + height = CW_USEDEFAULT; + dock = KHM_DOCK_NONE; + + if (khm_main_wnd_mode == KHM_MAIN_WND_MINI) + wconfig = L"CredWindow\\Windows\\MainMini"; + else + wconfig = L"CredWindow\\Windows\\Main"; + + if (KHM_SUCCEEDED(khc_open_space(NULL, + wconfig, + KHM_PERM_READ, + &csp_mw))) { + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"XPos", &t))) + x = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"YPos", &t))) + y = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Width", &t))) + width = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Height", &t))) + height = t; + if (KHM_SUCCEEDED(khc_read_int32(csp_mw, L"Dock", &t))) + dock = t; + + khc_close_space(csp_mw); + } + + /* If there were no default values, we default to using 1/4 of the + work area centered on the primary monitor. If there were any + docking hints, then the next call to + khm_adjust_window_dimensions_for_display() will reposition the + window. */ + if (width == CW_USEDEFAULT || x == CW_USEDEFAULT) { + RECT wr; + + SetRectEmpty(&wr); + SystemParametersInfo(SPI_GETWORKAREA, 0, &wr, 0); + + if (width == CW_USEDEFAULT) { + width = (wr.right - wr.left) / 2; + height = (wr.bottom - wr.top) / 2; + } + + if (x == CW_USEDEFAULT) { + x = (wr.left + wr.right) / 2 - width / 2; + y = (wr.top + wr.bottom) / 2 - height / 2; + } + } + + /* The saved dimensions might not actually be visible if the user + has changed the resolution of the display or if it's a multiple + monitor system where the monitor on which the Network Identity + Manager window was on previously is no longer connected. We + have to check for that and adjust the dimensions if needed. */ + SetRect(&r, x, y, x + width, y + height); + khm_adjust_window_dimensions_for_display(&r, dock); + + *pr = r; +} + +void +khm_set_main_window_mode(int mode) { + + RECT r; + khm_handle csp_cw; + + if (mode == khm_main_wnd_mode) + return; + + khui_check_action(KHUI_ACTION_LAYOUT_MINI, + ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); + khui_enable_action(KHUI_MENU_LAYOUT, + ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); + khui_enable_action(KHUI_MENU_COLUMNS, + ((mode == KHM_MAIN_WND_MINI)? FALSE : TRUE)); + + khui_refresh_actions(); + + /* + * set the window position before the global khm_main_wnd_mode + * is updated. otherwise, the windows position for the wrong + * mode will be set. Do not set the window position if the + * main application window has not yet been created. + */ + if (khm_hwnd_main) + main_wnd_save_sizepos(); + + khm_main_wnd_mode = mode; + if (khm_hwnd_main) { + khm_get_main_window_rect(&r); + + SetWindowPos(khm_hwnd_main, + NULL, + r.left, r.top, + r.right - r.left, r.bottom - r.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER); + } + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_WRITE, + &csp_cw))) { + + khc_write_int32(csp_cw, L"DefaultWindowMode", mode); + khc_close_space(csp_cw); + + } + + khm_cred_refresh(); +} + +void +khm_create_main_window(void) { + wchar_t buf[1024]; + khm_handle csp_cw = NULL; + RECT r; + + LoadString(khm_hInstance, IDS_MAIN_WINDOW_TITLE, + buf, ARRAYLENGTH(buf)); + + khm_hwnd_null = + CreateWindow(MAKEINTATOM(khm_null_window_class), + buf, + 0, /* Style */ + 0, 0, /* x, y */ + 100, 100, /* width, height */ + NULL, /* parent */ + NULL, /* menu */ + NULL, /* HINSTANCE */ + 0); /* lparam */ + + if (!khm_hwnd_null) + return; + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", + KHM_PERM_READ, + &csp_cw))) { + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"DefaultWindowMode", &t))) { + khm_set_main_window_mode(t); + } + + khc_close_space(csp_cw); + } + + khm_get_main_window_rect(&r); + + khm_hwnd_main = + CreateWindowEx(WS_EX_OVERLAPPEDWINDOW | WS_EX_APPWINDOW, + MAKEINTATOM(khm_main_window_class), + buf, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | + WS_CLIPSIBLINGS, + r.left, r.top, + r.right - r.left, + r.bottom - r.top, + khm_hwnd_null, + NULL, + NULL, + NULL); + + khui_set_main_window(khm_hwnd_main); +} + +void +khm_show_main_window(void) { + + if (khm_nCmdShow == SW_RESTORE) { + HWND hw; + + hw = GetForegroundWindow(); + if (hw != khm_hwnd_main) + SetForegroundWindow(khm_hwnd_main); + } + + if (khm_nCmdShow == SW_SHOWMINIMIZED || + khm_nCmdShow == SW_SHOWMINNOACTIVE || + khm_nCmdShow == SW_MINIMIZE) { + khm_hide_main_window(); + } else { + ShowWindow(khm_hwnd_main, khm_nCmdShow); + UpdateWindow(khm_hwnd_main); + + khm_cred_refresh(); + } + + khm_nCmdShow = SW_RESTORE; +} + +void +khm_activate_main_window(void) { + + if (!SetForegroundWindow(khm_hwnd_main)) { + FLASHWINFO finfo; + + SetActiveWindow(khm_hwnd_main); + + ZeroMemory(&finfo, sizeof(finfo)); + finfo.cbSize = sizeof(finfo); + finfo.hwnd = khm_hwnd_main; + finfo.dwFlags = FLASHW_ALL; + finfo.uCount = 3; + finfo.dwTimeout = 0; + + FlashWindowEx(&finfo); + } +} + +void +khm_close_main_window(void) { + khm_handle csp_cw; + BOOL keep_running = FALSE; + + if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", + KHM_PERM_READ, &csp_cw))) { + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_cw, L"KeepRunning", + &t))) { + keep_running = t; + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + khc_close_space(csp_cw); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + if (keep_running) + khm_hide_main_window(); + else + DestroyWindow(khm_hwnd_main); +} + +void +khm_hide_main_window(void) { + khm_handle csp_notices = NULL; + khm_int32 show_warning = FALSE; + + if (khm_nCmdShow != SW_MINIMIZE && + KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow\\Notices", + KHM_PERM_WRITE, &csp_notices)) && + KHM_SUCCEEDED(khc_read_int32(csp_notices, L"MinimizeWarning", + &show_warning)) && + show_warning != 0) { + + khui_alert * alert; + wchar_t title[KHUI_MAXCCH_TITLE]; + wchar_t msg[KHUI_MAXCCH_MESSAGE]; + + LoadString(khm_hInstance, IDS_WARN_WM_TITLE, + title, ARRAYLENGTH(title)); + LoadString(khm_hInstance, IDS_WARN_WM_MSG, + msg, ARRAYLENGTH(msg)); + + khui_alert_create_simple(title, msg, KHERR_INFO, &alert); + khui_alert_set_flags(alert, KHUI_ALERT_FLAG_REQUEST_BALLOON, + KHUI_ALERT_FLAG_REQUEST_BALLOON); + + khui_alert_show(alert); + + khc_write_int32(csp_notices, L"MinimizeWarning", 0); + } + + if (csp_notices != NULL) + khc_close_space(csp_notices); + + ShowWindow(khm_hwnd_main, SW_HIDE); +} + +BOOL +khm_is_main_window_visible(void) { + return IsWindowVisible(khm_hwnd_main); +} + +BOOL +khm_is_main_window_active(void) { + if (!IsWindowVisible(khm_hwnd_main)) + return FALSE; + if (GetForegroundWindow() == khm_hwnd_main) + return TRUE; + return khm_is_dialog_active(); +} + +void +khm_register_main_wnd_class(void) { + WNDCLASSEX wc; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = 0; + wc.lpfnWndProc = khm_null_wnd_proc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = khm_hInstance; + wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); + wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE); + wc.lpszMenuName = NULL; + wc.lpszClassName = KHUI_NULL_WINDOW_CLASS; + + khm_null_window_class = RegisterClassEx(&wc); + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = khm_main_wnd_proc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = khm_hInstance; + wc.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); + wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wc.hIconSm = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE); + wc.lpszMenuName = NULL; + wc.lpszClassName = KHUI_MAIN_WINDOW_CLASS; + + khm_main_window_class = RegisterClassEx(&wc); +} + +void +khm_unregister_main_wnd_class(void) { + UnregisterClass(MAKEINTATOM(khm_main_window_class),khm_hInstance); + UnregisterClass(MAKEINTATOM(khm_null_window_class),khm_hInstance); +} diff --git a/krb5-1-6/src/windows/identity/ui/mainwnd.h b/krb5-1-6/src/windows/identity/ui/mainwnd.h new file mode 100644 index 000000000..5a00631c1 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/mainwnd.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_MAINWND_H +#define __KHIMAIRA_MAINWND_H + +#define KHUI_MAIN_WINDOW_CLASS L"KhmMainWindowClass" +#define KHUI_NULL_WINDOW_CLASS L"KhmNullWindowClass" + +extern ATOM khm_main_window_class; +extern HWND khm_hwnd_main; +extern HWND khm_hwnd_rebar; +extern HWND khm_hwnd_main_cred; + +#define KHM_MAIN_WND_NORMAL 0 +#define KHM_MAIN_WND_MINI 1 + +extern int khm_main_wnd_mode; + +void khm_register_main_wnd_class(void); +void khm_unregister_main_wnd_class(void); +void khm_create_main_window_controls(HWND); +void khm_create_main_window(void); +void khm_activate_main_window(void); +void khm_show_main_window(void); +void khm_set_main_window_mode(int mode); +void khm_close_main_window(void); +void khm_hide_main_window(void); +BOOL khm_is_main_window_visible(void); +BOOL khm_is_main_window_active(void); +void khm_adjust_window_dimensions_for_display(RECT * pr, int dock); +LRESULT khm_rebar_notify(LPNMHDR lpnm); + +void +khm_set_dialog_result(HWND hwnd, LRESULT lr); + +LRESULT CALLBACK +khm_main_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +#define WM_KHUI_QUERY_APP_VERSION 32809 +#define WM_KHUI_ASSIGN_COMMANDLINE_V1 32808 +#define WM_KHUI_ASSIGN_COMMANDLINE_V2 32810 + +#define COMMANDLINE_MAP_FMT L"Local\\NetIDMgr_Cmdline_%lu" +#define QUERY_APP_VER_MAP_FMT L"Local\\NetIDMgr_QueryVer_%lu" + +/* dock values for window positioning */ +#define KHM_DOCK_NONE 0 +#define KHM_DOCK_TOPLEFT 1 +#define KHM_DOCK_TOPRIGHT 2 +#define KHM_DOCK_BOTTOMRIGHT 3 +#define KHM_DOCK_BOTTOMLEFT 4 +#define KHM_DOCK_AUTO 256 +#define KHM_DOCKF_DOCKHINT 0x0000ffff +#define KHM_DOCKF_XBORDER 0x00010000 +#endif diff --git a/krb5-1-6/src/windows/identity/ui/makeacceldef.pl b/krb5-1-6/src/windows/identity/ui/makeacceldef.pl new file mode 100644 index 000000000..d1cfb2dd2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/makeacceldef.pl @@ -0,0 +1,29 @@ +# + +die "Please specify input and output filenames" if($#ARGV != 1); + +open INF, '<', $ARGV[0] or die "Can't open input file"; +open OUF, '>', $ARGV[1] or die "Can't open output file"; + +print OUF <<EOS; +#include<khimaira.h> + + khui_accel_def khui_accel_global[] = { +EOS + +# skip first line + <INF>; + +while(<INF>) { + print OUF "{".$_."},\n"; +} + +print OUF <<EOS; +}; + +int khui_n_accel_global = sizeof(khui_accel_global) / sizeof(khui_accel_def); + +EOS + +close INF; +close OUF; diff --git a/krb5-1-6/src/windows/identity/ui/makeactiondef.pl b/krb5-1-6/src/windows/identity/ui/makeactiondef.pl new file mode 100644 index 000000000..f99373588 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/makeactiondef.pl @@ -0,0 +1,29 @@ +# + +die "Please specify input and output filenames" if($#ARGV != 1); + +open INF, '<', $ARGV[0] or die "Can't open input file"; +open OUF, '>', $ARGV[1] or die "Can't open output file"; + +print OUF <<EOS; +#include<khimaira.h> + + khui_action khui_actions[] = { +EOS + +# skip first line + <INF>; + +while(<INF>) { + print OUF "{".$_."},\n"; +} + +print OUF <<EOS; +}; + +int khui_n_actions = sizeof(khui_actions) / sizeof(khui_action); + +EOS + +close INF; +close OUF; diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.exe.manifest.i386 b/krb5-1-6/src/windows/identity/ui/netidmgr.exe.manifest.i386 new file mode 100644 index 000000000..3d77cce68 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.exe.manifest.i386 @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="X86" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="X86" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7 b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7 new file mode 100644 index 000000000..0db331bb7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7 @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="amd64" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="amd64" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug new file mode 100644 index 000000000..0db331bb7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc7.debug @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="amd64" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="amd64" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8 b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8 new file mode 100644 index 000000000..6fb1e8d1e --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8 @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="amd64" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="amd64" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.VC80.DebugCRT" + version="8.0.50215.4652" + processorArchitecture="amd64" + publicKeyToken="1fc8b3b9a1e18e3b" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug new file mode 100644 index 000000000..6fb1e8d1e --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.amd64.vc8.debug @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="amd64" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="amd64" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.VC80.DebugCRT" + version="8.0.50215.4652" + processorArchitecture="amd64" + publicKeyToken="1fc8b3b9a1e18e3b" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7 b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7 new file mode 100644 index 000000000..3d77cce68 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7 @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="X86" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="X86" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7.debug b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7.debug new file mode 100644 index 000000000..3d77cce68 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc7.debug @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="X86" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="X86" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8 b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8 new file mode 100644 index 000000000..d2ced7fd2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8 @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="X86" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="X86" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.VC80.DebugCRT" + version="8.0.50215.4652" + processorArchitecture="x86" + publicKeyToken="1fc8b3b9a1e18e3b" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8.debug b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8.debug new file mode 100644 index 000000000..d2ced7fd2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/netidmgr.manifest.i386.vc8.debug @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="X86" + name="MIT.NetIDMgr.UI" + type="win32" +/> +<description>Khimaira Credentials Manager</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="X86" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.VC80.DebugCRT" + version="8.0.50215.4652" + processorArchitecture="x86" + publicKeyToken="1fc8b3b9a1e18e3b" + /> + </dependentAssembly> +</dependency> +</assembly> diff --git a/krb5-1-6/src/windows/identity/ui/newcredwnd.c b/krb5-1-6/src/windows/identity/ui/newcredwnd.c new file mode 100644 index 000000000..e40e9da9a --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/newcredwnd.c @@ -0,0 +1,3034 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Include the OEMRESOURCE constants for locating standard icon + resources. */ +#define OEMRESOURCE + +#include<khmapp.h> +#if _WIN32_WINNT >= 0x0501 +#include<uxtheme.h> +#endif +#include<assert.h> + +ATOM khui_newcredwnd_cls; + +/* forward dcl */ +static void +nc_position_credtext(khui_nc_wnd_data * d); + +/* Common dialog procedure used by the main credential panel + (IDD_NC_NEWCRED) and the button bar (IDC_NC_BBAR). */ + +static void +nc_layout_main_panel(khui_nc_wnd_data * d); + +static void +nc_layout_new_cred_window(khui_nc_wnd_data * d); + +static INT_PTR CALLBACK +nc_common_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_INITDIALOG: + { + khui_nc_wnd_data * d; + + d = (khui_nc_wnd_data *) lParam; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, lParam); +#pragma warning(pop) + + if (d->nc->subtype == KMSG_CRED_PASSWORD) { + ShowWindow(GetDlgItem(hwnd, IDC_NC_ADVANCED), + SW_HIDE); + } + } + return TRUE; + + case WM_COMMAND: + { + int ctrl_id; + + ctrl_id = LOWORD(wParam); + if (ctrl_id < KHUI_CW_ID_MIN || + ctrl_id > KHUI_CW_ID_MAX) { + /* pump it to the parent */ + PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam); + return TRUE; + } /* else we allow the message to fall through and get + passed into the identity provider's message + handler. */ + } + break; + + case KHUI_WM_NC_NOTIFY: + { + khui_nc_wnd_data * d; + d = (khui_nc_wnd_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + /* message sent by parent to notify us of something */ + switch(HIWORD(wParam)) { + case WMNC_DIALOG_EXPAND: + /* fallthrough */ + case WMNC_UPDATE_LAYOUT: + if(hwnd == d->dlg_main) { + + nc_layout_main_panel(d); + + return TRUE; + } + break; /* nop */ + } + } + return TRUE; + } + + /* check if we have a wnd_data, and if so pass the message on to + the identity provider callback. */ + { + khui_nc_wnd_data * d; + + d = (khui_nc_wnd_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + /* TODO: filter out and forward only the messages that + originated or pertain to the identity selection + controls. */ + if (d && d->nc && d->nc->ident_cb) { + return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg, + wParam, lParam); + } + } + + return FALSE; +} + +static void +nc_notify_clear(khui_nc_wnd_data * d) { + + if (d->notif_type == NC_NOTIFY_NONE) + /* there are no notifications anyway. */ + return; + + if (d->hwnd_notif_label) + DestroyWindow(d->hwnd_notif_label); + + if (d->hwnd_notif_aux) + DestroyWindow(d->hwnd_notif_aux); + + d->hwnd_notif_label = NULL; + d->hwnd_notif_aux = NULL; + + SetRectEmpty(&d->r_notif); + + d->notif_type = NC_NOTIFY_NONE; + + /* Note that we must call nc_layout_main_panel() after calling + this to adjust the layout of the main panel. However we aren't + calling it here since we might want to add another set of + notifications or make other changes to the main panel content + before calling nc_layout_main_panel(). */ +} + +static void +nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) { + +#if (_WIN32_IE >= 0x0600) + HDC hdc; + size_t length; + SIZE label_size; +#endif + + RECT r_label; + RECT r_mq; + RECT r_row; + HFONT hfont; + HWND hwnd; + HDWP hdefer; + + /* Clear the notification area. We only support one notification + at a time. */ + nc_notify_clear(d); + +#ifdef DEBUG + assert(d->dlg_main); +#endif + +#if (_WIN32_IE >= 0x0600) + + /* We can only show the marquee control if the comctl32 DLL is + version 6.0 or later. Otherwise we only show the label. */ + + if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) { +#ifdef DEBUG + assert(FALSE); +#endif + length = KHUI_MAXCCH_SHORT_DESC; + } + + /* See how big the notification control needs to be. */ + + hdc = GetDC(d->dlg_main); +#ifdef DEBUG + assert(hdc != NULL); +#endif + + GetTextExtentPoint32(hdc, label, (int) length, &label_size); + + ReleaseDC(d->dlg_main, hdc); + + CopyRect(&r_row, &d->r_row); + + if (label_size.cx > d->r_e_label.right - d->r_e_label.left) { + /* using an entire row */ + CopyRect(&r_label, &d->r_row); + CopyRect(&r_mq, &d->r_n_input); + OffsetRect(&r_mq, 0, r_row.bottom - r_row.top); + r_row.bottom += r_row.bottom - r_row.top; + } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) { + /* using large labels */ + CopyRect(&r_label, &d->r_e_label); + CopyRect(&r_mq, &d->r_e_input); + } else { + /* normal labels */ + CopyRect(&r_label, &d->r_n_label); + CopyRect(&r_mq, &d->r_n_input); + } + + InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4)); + +#else /* _WIN32_IE < 0x0600 */ + + /* We are just showing the label */ + CopyRect(&r_row, &d->r_row); + CopyRect(&r_label, &r_row); + SetRectEmpty(&r_mq); + +#endif /* _WIN32_IE >= 0x0600 */ + + { + long y; + + if (IsRectEmpty(&d->r_custprompt)) { + y = d->r_idspec.bottom; + } else { + y = d->r_custprompt.bottom; + } + + OffsetRect(&r_row, d->r_area.left, y); + OffsetRect(&r_label, r_row.left, r_row.top); + OffsetRect(&r_mq, r_row.left, r_row.top); + } + + hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0); + + hdefer = BeginDeferWindowPos(2); + + /* the label */ + hwnd = CreateWindowEx(0, + L"STATIC", + label, + WS_CHILD | SS_ENDELLIPSIS, + r_label.left, r_label.top, + r_label.right - r_label.left, + r_label.bottom - r_label.top, + d->dlg_main, + NULL, NULL, NULL); +#ifdef DEBUG + assert(hwnd != NULL); +#endif + SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE); + + DeferWindowPos(hdefer, hwnd, NULL, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | + SWP_NOSIZE | SWP_SHOWWINDOW); + + d->hwnd_notif_label = hwnd; + + /* and the marquee */ + +#if (_WIN32_IE >= 0x0600) + + /* unfortunately, the marquee is only available on comctl32 + version 6.0 or later. On previous versions, we only display + the message label. */ + + hwnd = CreateWindowEx(0, + PROGRESS_CLASS, + L"", + WS_CHILD | PBS_MARQUEE, + r_mq.left, r_mq.top, + r_mq.right - r_mq.left, + r_mq.bottom - r_mq.top, + d->dlg_main, + NULL, NULL, NULL); +#ifdef DEBUG + assert(hwnd != NULL); +#endif + + SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100); + + DeferWindowPos(hdefer, hwnd, NULL, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | + SWP_NOSIZE | SWP_SHOWWINDOW); + + d->hwnd_notif_aux = hwnd; + +#endif /* _WIN32_IE >= 0x0600 */ + + EndDeferWindowPos(hdefer); + + CopyRect(&d->r_notif, &r_row); + + d->notif_type = NC_NOTIFY_MARQUEE; + + /* Note that we must call nc_layout_main_panel() after calling + this to adjust the layout of the main panel. However we aren't + calling it here since we might want to add another set of + notifications or make other changes to the main panel content + before calling nc_layout_main_panel(). */ +} + +static void +nc_notify_message(khui_nc_wnd_data * d, + kherr_severity severity, + const wchar_t * message) { + + SIZE icon_size; + LPCTSTR icon_res; + HICON h_icon; + HWND hwnd; + HFONT hfont; + HDWP hdefer; + + RECT r_row; + RECT r_label; + RECT r_icon; + + nc_notify_clear(d); + + icon_size.cx = GetSystemMetrics(SM_CXSMICON); + icon_size.cy = GetSystemMetrics(SM_CYSMICON); + + switch(severity) { + case KHERR_INFO: + icon_res = MAKEINTRESOURCE(OIC_INFORMATION); + break; + + case KHERR_WARNING: + icon_res = MAKEINTRESOURCE(OIC_WARNING); + break; + + case KHERR_ERROR: + icon_res = MAKEINTRESOURCE(OIC_ERROR); + break; + + default: + icon_res = NULL; + } + + if (icon_res != NULL) { + h_icon = (HICON) LoadImage(NULL, + icon_res, + IMAGE_ICON, + icon_size.cx, + icon_size.cy, + LR_DEFAULTCOLOR | LR_SHARED); + } else { + h_icon = NULL; + } + + CopyRect(&r_row, &d->r_row); + +#define CENTERVALUE(w,v) ((w)/2 - (v)/2) + + SetRect(&r_icon, + 0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy), + icon_size.cx, + CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy); + +#undef CENTERVALUE + + CopyRect(&r_label, &r_row); + OffsetRect(&r_label, -r_label.left, -r_label.top); + r_label.left += (icon_size.cx * 3) / 2; + + { + long y; + + if (IsRectEmpty(&d->r_custprompt)) { + y = d->r_idspec.bottom; + } else { + y = d->r_custprompt.bottom; + } + + OffsetRect(&r_row, d->r_area.left, y); + OffsetRect(&r_label, r_row.left, r_row.top); + OffsetRect(&r_icon, r_row.left, r_row.top); + } + + hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0); + + hdefer = BeginDeferWindowPos(2); + + hwnd = CreateWindowEx(0, + L"STATIC", + message, + WS_CHILD | SS_ENDELLIPSIS | SS_CENTER, + r_label.left, r_label.top, + r_label.right - r_label.left, + r_label.bottom - r_label.top, + d->dlg_main, + NULL, NULL, NULL); +#ifdef DEBUG + assert(hwnd != NULL); +#endif + SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE); + + DeferWindowPos(hdefer, hwnd, NULL, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | + SWP_NOSIZE | SWP_SHOWWINDOW); + + d->hwnd_notif_label = hwnd; + + hwnd = CreateWindowEx(0, + L"STATIC", + NULL, + WS_CHILD | SS_ICON | +#if (_WIN32_IE >= 0x0600) + SS_REALSIZECONTROL +#else + 0 +#endif + , + r_icon.left, r_icon.top, + r_icon.right - r_icon.left, + r_icon.bottom - r_icon.top, + d->dlg_main, + NULL, NULL, NULL); +#ifdef DEBUG + assert(hwnd != NULL); +#endif + + if (h_icon && hwnd) + SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0); + + DeferWindowPos(hdefer, hwnd, NULL, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | + SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER); + + d->hwnd_notif_aux = hwnd; + + EndDeferWindowPos(hdefer); + + CopyRect(&d->r_notif, &r_row); + + d->notif_type = NC_NOTIFY_MESSAGE; + + /* Note that we must call nc_layout_main_panel() after calling + this to adjust the layout of the main panel. However we aren't + calling it here since we might want to add another set of + notifications or make other changes to the main panel content + before calling nc_layout_main_panel(). */ +} + +static void +nc_layout_main_panel(khui_nc_wnd_data * d) +{ + RECT r_main; + HWND hw_ct; + HWND hw_ct_label; + HDWP hdwp; + RECT r_used; /* extent used by identity specifiers, + custom prompts and notificaiton + controls. */ + + RECT r_wmain; /* extents of the main window in screen + coordinates. */ + + r_main.left = 0; + r_main.top = 0; + r_main.bottom = NCDLG_HEIGHT; + r_main.right = NCDLG_WIDTH; + + MapDialogRect(d->dlg_main, &r_main); + + CopyRect(&r_used, &d->r_idspec); + + GetWindowRect(d->dlg_main, &r_wmain); + + hdwp = BeginDeferWindowPos(7); + + /* check if the notification area and the custom prompt area are + overlapping. */ + + if (d->notif_type != NC_NOTIFY_NONE) { + long delta_y = 0; + RECT r; + + CopyRect(&r, &d->r_custprompt); + + if (IsRectEmpty(&d->r_custprompt)) { + /* if there are no custom prompts, then the notification + area should be immediately below the identitify + specifers. */ + + delta_y = d->r_idspec.bottom - d->r_notif.top; + } else { + /* otherwise, the notification area should be immediately + below the custom prompt area */ + + delta_y = d->r_custprompt.bottom - d->r_notif.top; + } + + if (delta_y != 0) { + RECT r_lbl; + RECT r_aux; + + if (d->hwnd_notif_label) { + GetWindowRect(d->hwnd_notif_label, &r_lbl); + OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top); + + DeferWindowPos(hdwp, d->hwnd_notif_label, NULL, + r_lbl.left, r_lbl.top, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_NOSIZE); + } + + if (d->hwnd_notif_aux) { + GetWindowRect(d->hwnd_notif_aux, &r_aux); + OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top); + + DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL, + r_aux.left, r_aux.top, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_NOSIZE); + } + + OffsetRect(&d->r_notif, 0, delta_y); + } + } + + if (!IsRectEmpty(&d->r_custprompt)) { + r_used.bottom = max(d->r_custprompt.bottom, + r_used.bottom); + } + + if (!IsRectEmpty(&d->r_notif)) { + r_used.bottom = max(d->r_notif.bottom, + r_used.bottom); + } + + if (d->nc->mode == KHUI_NC_MODE_MINI) { + RECT r_ok; + RECT r_cancel; + RECT r_advanced; + HWND hw; + + hw = GetDlgItem(d->dlg_main, IDOK); +#ifdef DEBUG + assert(hw != NULL); +#endif + GetWindowRect(hw, &r_ok); + OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom); + + DeferWindowPos(hdwp, hw, NULL, + r_ok.left, r_ok.top, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW); + + hw = GetDlgItem(d->dlg_main, IDCANCEL); +#ifdef DEBUG + assert(hw != NULL); +#endif + GetWindowRect(hw, &r_cancel); + OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom); + + DeferWindowPos(hdwp, hw, NULL, + r_cancel.left, r_cancel.top, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW); + + hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED); +#ifdef DEBUG + assert(hw != NULL); +#endif + GetWindowRect(hw, &r_advanced); + OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom); + + DeferWindowPos(hdwp, hw, NULL, + r_advanced.left, r_advanced.top, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW); + + /* and now update the extents of the main panel */ + r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top; + + CopyRect(&d->r_main, &r_main); + + } else { + + HWND hw; + + hw = GetDlgItem(d->dlg_main, IDOK); +#ifdef DEBUG + assert(hw != NULL); +#endif + if (IsWindowVisible(hw)) + DeferWindowPos(hdwp, hw, NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | + SWP_NOOWNERZORDER | SWP_NOZORDER); + + hw = GetDlgItem(d->dlg_main, IDCANCEL); +#ifdef DEBUG + assert(hw != NULL); +#endif + if (IsWindowVisible(hw)) + DeferWindowPos(hdwp, hw, NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | + SWP_NOOWNERZORDER | SWP_NOZORDER); + + hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED); +#ifdef DEBUG + assert(hw != NULL); +#endif + if (IsWindowVisible(hw)) + DeferWindowPos(hdwp, hw, NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | + SWP_NOOWNERZORDER | SWP_NOZORDER); + + d->r_credtext.top = r_used.bottom; + + CopyRect(&d->r_main, &r_main); + } + + /* now update the layout of the credentials text window */ + + hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT); + hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL); +#ifdef DEBUG + assert(hw_ct != NULL); + assert(hw_ct_label != NULL); +#endif + + if (d->nc->mode == KHUI_NC_MODE_MINI || + d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) { + + /* either we aren't supposed to show the credentials text + window, or we don't have enough room. */ + if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) { + + DeferWindowPos(hdwp, hw_ct, NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE); + + DeferWindowPos(hdwp, hw_ct_label, NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE); + + } + + } else { + + DeferWindowPos(hdwp, + hw_ct, NULL, + d->r_credtext.left + d->r_n_input.left, /* x */ + d->r_credtext.top, /* y */ + d->r_n_input.right - d->r_n_input.left, /* width */ + d->r_credtext.bottom - d->r_credtext.top, /* height */ + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_SHOWWINDOW); + + DeferWindowPos(hdwp, + hw_ct_label, NULL, + d->r_credtext.left + d->r_n_label.left, /* x */ + d->r_credtext.top, /* y */ + d->r_n_label.right - d->r_n_label.left, /* width */ + d->r_n_label.bottom - d->r_n_label.top, /* height */ + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_SHOWWINDOW); + } + + EndDeferWindowPos(hdwp); + + /* NOTE: although we updated d->r_main, if the new credentials + window is in mini mode, we must call + nc_layout_new_cred_window() to adjust the size of the new + credentials window to fit the main panel. We don't do it here + because we need to keep these two operations separate. */ +} + +/* Credential type panel comparison function. Tabs are sorted based + on the following criteria: + + 1) By ordinal - Panels with ordinal -1 will be ranked after panels + whose ordinal is not -1. + + 2) By name - Case insensitive comparison of the name. If the panel + does not have a name (i.e. the ->name member is NULL, it will be + ranked after panels which have a name. + */ +static int __cdecl +nc_tab_sort_func(const void * v1, const void * v2) +{ + /* v1 and v2 and of type : khui_new_creds_by_type ** */ + khui_new_creds_by_type *t1, *t2; + + t1 = *((khui_new_creds_by_type **) v1); + t2 = *((khui_new_creds_by_type **) v2); + + if(t1->ordinal != -1) { + if(t2->ordinal != -1) { + if(t1->ordinal == t2->ordinal) { + if (t1->name && t2->name) + return _wcsicmp(t1->name, t2->name); + else if (t1->name) + return -1; + else if (t2->name) + return 1; + else + return 0; + } else { + /* safe to convert to an int here */ + return (int) (t1->ordinal - t2->ordinal); + } + } else + return -1; + } else { + if(t2->ordinal != -1) + return 1; + else if (t1->name && t2->name) + return wcscmp(t1->name, t2->name); + else if (t1->name) + return -1; + else if (t2->name) + return 1; + else + return 0; + } +} + +static void +nc_notify_types(khui_new_creds * c, UINT uMsg, + WPARAM wParam, LPARAM lParam, BOOL sync) +{ + khm_size i; + + for(i=0; i<c->n_types; i++) { + + if (c->types[i]->hwnd_panel == NULL) + continue; + + if (sync) + SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam); + else + PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam); + } +} + +static void +nc_clear_password_fields(khui_nc_wnd_data * d) +{ + khm_size i; + khm_boolean need_sync = FALSE; + + khui_cw_lock_nc(d->nc); + + for (i=0; i < d->nc->n_prompts; i++) { + if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) && + d->nc->prompts[i]->hwnd_edit) { + SetWindowText(d->nc->prompts[i]->hwnd_edit, + L""); + need_sync = TRUE; + } + } + + khui_cw_unlock_nc(d->nc); + + if (need_sync) { + khui_cw_sync_prompt_values(d->nc); + } +} + +/* used by nc_enable_controls */ + +struct nc_enum_wnd_data { + khui_nc_wnd_data * d; + khm_boolean enable; +}; + +static +BOOL CALLBACK +nc_enum_wnd_proc(HWND hwnd, + LPARAM lParam) +{ + struct nc_enum_wnd_data * wd; + + wd = (struct nc_enum_wnd_data *) lParam; + + EnableWindow(hwnd, wd->enable); + + return TRUE; +} + +static void +nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable) +{ + struct nc_enum_wnd_data wd; + + ZeroMemory(&wd, sizeof(wd)); + + wd.d = d; + wd.enable = enable; + + EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd); +} + +#define NC_MAXCCH_CREDTEXT 16384 +#define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t)) + +static void +nc_update_credtext(khui_nc_wnd_data * d) +{ + wchar_t * ctbuf = NULL; + wchar_t * buf; + BOOL okEnable = FALSE; + BOOL validId = FALSE; + HWND hw = NULL; + size_t cch = 0; + + ctbuf = PMALLOC(NC_MAXCB_CREDTEXT); + + assert(ctbuf != NULL); + + LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT); + StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch); + buf = ctbuf + cch; + nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE); + + /* hopefully all the types have updated their credential texts */ + + /* if the dialog is in the mini mode, we have to display + exceptions using a notification. */ + if (d->nc->mode == KHUI_NC_MODE_MINI) { + BOOL need_layout = FALSE; + if (d->nc->n_identities == 0) { + + /* There are no identities selected. We don't show any + notifications here. */ + if (d->notif_type != NC_NOTIFY_NONE) { + nc_notify_clear(d); + need_layout = TRUE; + } + + } else { + + wchar_t id_name[KCDB_IDENT_MAXCCH_NAME]; + wchar_t format[256]; + wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)]; + khm_size cbbuf; + khm_int32 flags; + + kcdb_identity_get_flags(d->nc->identities[0], &flags); + + cbbuf = sizeof(id_name); + kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf); + + if (flags & KCDB_IDENT_FLAG_INVALID) { + + /* identity is invalid */ + LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID, + format, ARRAYLENGTH(format)); + StringCbPrintf(msg, sizeof(msg), format, id_name); + + nc_notify_message(d, KHERR_ERROR, msg); + + need_layout = TRUE; + + } else if ((flags & KCDB_IDENT_FLAG_VALID) || + d->nc->subtype == KMSG_CRED_PASSWORD) { + /* special case: If we are going to change the + password, we don't expect the identity provider to + validate the identity in real time. As such, we + assume that the identity is valid. */ + + /* identity is valid */ + if (d->notif_type != NC_NOTIFY_NONE) { + nc_notify_clear(d); + need_layout = TRUE; + } + + } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) { + + /* unknown state */ + LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN, + format, ARRAYLENGTH(format)); + StringCbPrintf(msg, sizeof(msg), format, id_name); + + nc_notify_message(d, KHERR_WARNING, msg); + + need_layout = TRUE; + + } else { + + /* still checking */ + LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING, + format, ARRAYLENGTH(format)); + StringCbPrintf(msg, sizeof(msg), format, id_name); + + nc_notify_marquee(d, msg); + + need_layout = TRUE; + + } + } + + if (need_layout) { + nc_layout_main_panel(d); + nc_layout_new_cred_window(d); + } + } + + if(d->nc->n_identities == 1) { + wchar_t main_fmt[256]; + wchar_t id_fmt[256]; + wchar_t id_name[KCDB_IDENT_MAXCCH_NAME]; + wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256]; + khm_size cbbuf; + khm_int32 flags; + + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE, + main_fmt, (int) ARRAYLENGTH(main_fmt)); + + cbbuf = sizeof(id_name); + kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf); + + kcdb_identity_get_flags(d->nc->identities[0], &flags); + + if (flags & KCDB_IDENT_FLAG_INVALID) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else if(flags & KCDB_IDENT_FLAG_VALID) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } + + StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name); + + StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), + main_fmt, id_string); + + if (flags & KCDB_IDENT_FLAG_VALID) { + if (flags & KCDB_IDENT_FLAG_DEFAULT) + LoadString(khm_hInstance, IDS_NC_ID_DEF, + id_string, ARRAYLENGTH(id_string)); + else if (d->nc->set_default) + LoadString(khm_hInstance, IDS_NC_ID_WDEF, + id_string, ARRAYLENGTH(id_string)); + else + LoadString(khm_hInstance, IDS_NC_ID_NDEF, + id_string, ARRAYLENGTH(id_string)); + + StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t), + id_string); + } + + } else if(d->nc->n_identities > 1) { + wchar_t *ids_string; + khm_size cb_ids_string; + + wchar_t id_name[KCDB_IDENT_MAXCCH_NAME]; + wchar_t id_fmt[256]; + wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256]; + + wchar_t main_fmt[256]; + khm_size cbbuf; + + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY, + main_fmt, (int) ARRAYLENGTH(main_fmt)); + + /* we are going to concatenate all the identity names into + a comma separated string */ + + /* d->nc->n_identities is at least 2 */ + ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * + (d->nc->n_identities - 1)); + cb_ids_string = + (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * + (d->nc->n_identities - 1); + + assert(ids_string != NULL); + + ids_string[0] = 0; + + { + khm_size i; + khm_int32 flags; + + for(i=1; i<d->nc->n_identities; i++) { + if(i>1) { + StringCbCat(ids_string, cb_ids_string, L","); + } + + flags = 0; + + cbbuf = sizeof(id_name); + kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf); + kcdb_identity_get_flags(d->nc->identities[i], &flags); + if(flags & KCDB_IDENT_FLAG_INVALID) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else if(flags & KCDB_IDENT_FLAG_VALID) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } + + StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name); + StringCbCat(ids_string, cb_ids_string, id_string); + } + + cbbuf = sizeof(id_name); + kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf); + kcdb_identity_get_flags(d->nc->identities[0], &flags); + if(flags & KCDB_IDENT_FLAG_INVALID) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else if(flags & KCDB_IDENT_FLAG_VALID) { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } else { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, + id_fmt, (int) ARRAYLENGTH(id_fmt)); + } + StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name); + + StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), + main_fmt, id_string, ids_string); + + PFREE(ids_string); + } + } else { + LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE, + buf, (int)(NC_MAXCCH_CREDTEXT - cch)); + } + + /* now, append the credtext string from each of the cred types */ + { + khm_size i; + size_t cb; + wchar_t * buf; + + cb = NC_MAXCB_CREDTEXT; + buf = ctbuf; + + for(i=0; i<d->nc->n_types; i++) { + if(d->nc->types[i]->credtext != NULL) { + StringCbCatEx(buf, cb, + d->nc->types[i]->credtext, + &buf, &cb, + 0); + } + } + } + + SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf); + + PFREE(ctbuf); + + /* so depending on whether the primary identity was found to be + invalid, we need to disable the Ok button and set the title to + reflect this */ + + if(d->nc->n_identities > 0) { + khm_int32 flags = 0; + + if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0], + &flags)) && + (flags & KCDB_IDENT_FLAG_VALID)) { + validId = TRUE; + } + } + + if (d->nc->window_title == NULL) { + if(validId) { + wchar_t wpostfix[256]; + wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256]; + khm_size cbsize; + + cbsize = sizeof(wtitle); + kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize); + + if (d->nc->subtype == KMSG_CRED_PASSWORD) + LoadString(khm_hInstance, IDS_WTPOST_PASSWORD, + wpostfix, (int) ARRAYLENGTH(wpostfix)); + else + LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS, + wpostfix, (int) ARRAYLENGTH(wpostfix)); + + StringCbCat(wtitle, sizeof(wtitle), wpostfix); + + SetWindowText(d->nc->hwnd, wtitle); + } else { + wchar_t wtitle[256]; + + if (d->nc->subtype == KMSG_CRED_PASSWORD) + LoadString(khm_hInstance, IDS_WT_PASSWORD, + wtitle, (int) ARRAYLENGTH(wtitle)); + else + LoadString(khm_hInstance, IDS_WT_NEW_CREDS, + wtitle, (int) ARRAYLENGTH(wtitle)); + + SetWindowText(d->nc->hwnd, wtitle); + } + } + + if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) { + if(validId || + d->nc->subtype == KMSG_CRED_PASSWORD) { + /* TODO: check if all the required fields have valid values + before enabling the Ok button */ + okEnable = TRUE; + } + + hw = GetDlgItem(d->dlg_main, IDOK); + EnableWindow(hw, okEnable); + hw = GetDlgItem(d->dlg_bb, IDOK); + EnableWindow(hw, okEnable); + } +} + +static void +nc_layout_new_cred_window(khui_nc_wnd_data * ncd) { + khui_new_creds * c; + RECT r_main; + RECT r_ncdialog; + HDWP hdefer; + + c = ncd->nc; + + r_main.left = 0; + r_main.top = 0; + r_main.right = NCDLG_WIDTH; + r_main.bottom = NCDLG_HEIGHT; + + MapDialogRect(ncd->dlg_main, &r_main); + + hdefer = BeginDeferWindowPos(5); + + if (c->mode == KHUI_NC_MODE_MINI) { + + if (IsWindowVisible(ncd->tab_wnd)) { + DeferWindowPos(hdefer, + ncd->tab_wnd, NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | + SWP_NOMOVE | SWP_NOOWNERZORDER | + SWP_NOSIZE | SWP_NOZORDER); + } + + if (IsWindowVisible(ncd->dlg_bb)) { + DeferWindowPos(hdefer, + ncd->dlg_bb, NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | + SWP_NOMOVE | SWP_NOOWNERZORDER | + SWP_NOSIZE | SWP_NOZORDER); + } + + DeferWindowPos(hdefer, ncd->dlg_main, NULL, + r_main.left, r_main.top, + r_main.right - r_main.left, + r_main.bottom - r_main.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_SHOWWINDOW); + + /* note that the ncd->r_main.bottom may not be the same as + r_main.bottom because ncd->r_main.bottom is set dynamically + depending on custom controls. ncd->r_main is valid only + once nc_layout_main_panel() is called.*/ + CopyRect(&ncd->r_required, &ncd->r_main); + + } else { + RECT r_tabctrl; + RECT r_displayarea; + RECT r_bbar; + khm_size i; + + /* calculate the size of the tab control so that it fits + snugly around the expanded main panel. */ + CopyRect(&r_tabctrl, &r_main); + TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl); + + if (r_tabctrl.left < 0 || + r_tabctrl.top < 0) { + + OffsetRect(&r_tabctrl, + (r_tabctrl.left < 0)? -r_tabctrl.left : 0, + (r_tabctrl.top < 0)? -r_tabctrl.top : 0); + + } + +#ifdef DEBUG + assert(r_tabctrl.left == 0); + assert(r_tabctrl.top == 0); +#endif + + OffsetRect(&r_tabctrl, 0, ncd->r_area.top); + + /* and now calculate the rectangle where the main panel should + be inside the tab control. */ + CopyRect(&r_displayarea, &r_tabctrl); + TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea); + + DeferWindowPos(hdefer, + ncd->tab_wnd, HWND_BOTTOM, + r_tabctrl.left, r_tabctrl.top, + r_tabctrl.right - r_tabctrl.left, + r_tabctrl.bottom - r_tabctrl.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_SHOWWINDOW); + + /* we have to place the button bar just to the right of the + tab panel. */ + r_bbar.left = 0; + r_bbar.top = 0; + r_bbar.right = NCDLG_BBAR_WIDTH; + r_bbar.bottom = NCDLG_BBAR_HEIGHT; + + MapDialogRect(ncd->dlg_main, &r_bbar); + + OffsetRect(&r_bbar, r_tabctrl.right, 0); + + DeferWindowPos(hdefer, + ncd->dlg_bb, NULL, + r_bbar.left, r_bbar.top, + r_bbar.right - r_bbar.left, + r_bbar.bottom - r_bbar.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | SWP_SHOWWINDOW); + + /* move the main panel inside the tab control... */ + DeferWindowPos(hdefer, + ncd->dlg_main, NULL, + r_displayarea.left, r_displayarea.top, + r_displayarea.right - r_displayarea.left, + r_displayarea.bottom - r_displayarea.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | + (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); + + /* and also move all the credential type panels (if they have + been created) inside the tab control too. */ + khui_cw_lock_nc(c); + + for (i=0; i < c->n_types; i++) { + if (c->types[i]->hwnd_panel != NULL) { + DeferWindowPos(hdefer, + c->types[i]->hwnd_panel, NULL, + r_displayarea.left, r_displayarea.top, + r_displayarea.right - r_displayarea.left, + r_displayarea.bottom - r_displayarea.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER | + (ncd->current_panel == c->types[i]->ordinal ? + SWP_SHOWWINDOW : SWP_HIDEWINDOW)); + } + } + + khui_cw_unlock_nc(c); + + /* then update the required size of the new credentials + dialog. */ + ncd->r_required.left = 0; + ncd->r_required.top = 0; + ncd->r_required.right = r_bbar.right; + ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top; + } + + /* commit all the window moves, resizes and hides/shows we did*/ + EndDeferWindowPos(hdefer); + + /* now we have to see if the client area of the new credentials + window is the right size. */ + + GetClientRect(c->hwnd, &r_ncdialog); + + if ( + + ((r_ncdialog.right - r_ncdialog.left != + ncd->r_required.right - ncd->r_required.left) + + || + + (r_ncdialog.bottom - r_ncdialog.top != + ncd->r_required.bottom - ncd->r_required.top)) + + && + + /* we don't bother if the new creds window is already in the + process of changing the size. */ + !ncd->size_changing) { + + /* if not, notify the window that the size needs adjusting. */ + if (IsWindowVisible(c->hwnd)) + PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0); + else + SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0); + } +} + +#define CW_PARAM DWLP_USER + +static LRESULT +nc_handle_wm_create(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LPCREATESTRUCT lpc; + khui_new_creds * c; + khui_nc_wnd_data * ncd; + int x, y; + int width, height; + RECT r; + HFONT hf_main; + + lpc = (LPCREATESTRUCT) lParam; + + ncd = PMALLOC(sizeof(*ncd)); + ZeroMemory(ncd, sizeof(*ncd)); + + c = (khui_new_creds *) lpc->lpCreateParams; + ncd->nc = c; + c->hwnd = hwnd; + +#ifdef DEBUG + assert(c->subtype == KMSG_CRED_NEW_CREDS || + c->subtype == KMSG_CRED_PASSWORD); +#endif + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd); +#pragma warning(pop) + + /* first, create the tab control that will house the main dialog + panel as well as the plug-in specific panels */ + ncd->tab_wnd = CreateWindowEx(0, /* extended style */ + WC_TABCONTROL, + L"TabControloxxrz", /* window name */ + TCS_HOTTRACK | TCS_RAGGEDRIGHT | + TCS_SINGLELINE | TCS_TABS | + WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS, + 0, 0, 100, 100, /* x,y,width height. + We'll be changing + these later + anyway. */ + hwnd, + (HMENU) IDC_NC_TABS, + NULL, + 0); + +#ifdef DEBUG + assert(ncd->tab_wnd != NULL); +#endif + + /* try to create the main dialog panel */ + + ncd->dlg_main = CreateDialogParam(khm_hInstance, + MAKEINTRESOURCE(IDD_NC_NEWCRED), + hwnd, + nc_common_dlg_proc, + (LPARAM) ncd); +#ifdef DEBUG + assert(ncd->dlg_main != NULL); +#endif + + hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0); + if (hf_main) + SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE); + +#if _WIN32_WINNT >= 0x0501 + EnableThemeDialogTexture(ncd->dlg_main, + ETDT_ENABLETAB); +#endif + + { + RECT r_main; + RECT r_area; + RECT r_row; + HWND hw; + + /* During the operation of the new credentials window, we will + need to dynamically change the layout of the controls as a + result of custom prompting from credentials providers and + identity selectors from identity providers. In order to + guide the dynamic layout, we pick out a few metrics from + the dialog template for the main panel. The metrics come + from hidden STATIC controls in the dialog template. */ + + GetWindowRect(ncd->dlg_main, &r_main); + + /* IDC_NC_TPL_PANEL spans the full extent of the dialog that + we can populate with custom controls. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r_area); + OffsetRect(&r_area,-r_main.left, -r_main.top); + CopyRect(&ncd->r_area, &r_area); + + /* IDC_NC_TPL_ROW spans the extent of a row of normal sized + custom controls. A row of custom controls typicall consist + of a text label and an input control. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + CopyRect(&r_row, &r); + OffsetRect(&r,-r.left, -r.top); + CopyRect(&ncd->r_row, &r); + + /* IDC_NC_TPL_LABEL spans the extent that a normal sized + label. The control overlaps IDC_NC_TPL_ROW so we can get + coordinates relative to the row extents. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + OffsetRect(&r,-r_row.left, -r_row.top); + CopyRect(&ncd->r_n_label, &r); + + /* IDC_NC_TPL_INPUT spans the extent of a normal sized input + control in a custom control row. The control overlaps + IDC_NC_TPL_ROW so we can get relative coordinates. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + OffsetRect(&r, -r_row.left, -r_row.top); + CopyRect(&ncd->r_n_input, &r); + + /* IDC_NC_TPL_ROW_LG spans the extent of a row of large sized + controls. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r_row); + + /* IDC_NC_TPL_LABEL_LG is a large sized label. The control + overlaps IDC_NC_TPL_ROW_LG. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + OffsetRect(&r, -r_row.left, -r_row.top); + CopyRect(&ncd->r_e_label, &r); + + /* IDC_NC_TPL_INPUT_LG is a large sized input control. + Overlaps IDC_NC_TPL_ROW_LG. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + OffsetRect(&r, -r_row.left, -r_row.top); + CopyRect(&ncd->r_e_input, &r); + + CopyRect(&ncd->r_credtext, &ncd->r_area); + CopyRect(&ncd->r_idspec, &ncd->r_area); + + ncd->r_idspec.bottom = ncd->r_idspec.top; + + /* And finally the credential text window. The only metric we + take from here is the Y coordinate of the bottom of the + control since the actual size and position of the + credentials window will change depending on the custom + controls being displayed. */ + hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT); +#ifdef DEBUG + assert(hw); +#endif + GetWindowRect(hw, &r); + OffsetRect(&r, -r_main.left, -r_main.top); + ncd->r_credtext.bottom = r.bottom; + } + + /* if the mode is 'mini'*/ + r.left = 0; + r.top = 0; + + if(c->mode == KHUI_NC_MODE_MINI) { + r.right = NCDLG_WIDTH; + r.bottom = NCDLG_HEIGHT; + } else { + r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH; + r.bottom = NCDLG_BBAR_HEIGHT; + } + + MapDialogRect(ncd->dlg_main, &r); + + /* position the new credentials dialog */ + width = r.right - r.left; + height = r.bottom - r.top; + + /* adjust width and height to accomodate NC area */ + { + RECT wr,cr; + + GetWindowRect(hwnd, &wr); + GetClientRect(hwnd, &cr); + + /* the non-client and client areas have already been calculated + at this point. We just use the difference to adjust the width + and height */ + width += (wr.right - wr.left) - (cr.right - cr.left); + height += (wr.bottom - wr.top) - (cr.bottom - cr.top); + } + + /* if the parent window is visible, we center the new credentials + dialog over the parent. Otherwise, we center it on the primary + display. */ + + if (IsWindowVisible(lpc->hwndParent)) { + GetWindowRect(lpc->hwndParent, &r); + } else { + if(!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &r, 0)) { + /* failover to the window coordinates */ + GetWindowRect(lpc->hwndParent, &r); + } + } + x = (r.right + r.left)/2 - width / 2; + y = (r.top + r.bottom)/2 - height / 2; + + /* we want to check if the entire rect is visible on the screen. + If the main window is visible and in basic mode, we might end + up with a rect that is partially outside the screen. */ + { + RECT r; + + SetRect(&r, x, y, x + width, y + height); + khm_adjust_window_dimensions_for_display(&r, 0); + + x = r.left; + y = r.top; + width = r.right - r.left; + height = r.bottom - r.top; + } + + MoveWindow(hwnd, x, y, width, height, FALSE); + + ncd->dlg_bb = CreateDialogParam(khm_hInstance, + MAKEINTRESOURCE(IDD_NC_BBAR), + hwnd, + nc_common_dlg_proc, + (LPARAM) ncd); + +#ifdef DEBUG + assert(ncd->dlg_bb); +#endif + + /* Call the identity provider callback to set the identity + selector controls. These controls need to be there before we + layout the main panel. */ + c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main); + + if (c->mode == KHUI_NC_MODE_EXPANDED) { + SendMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0); + } else { + /* we don't call nc_layout_main_panel() if the dialog is + expanded because posting WMNC_DIALOG_EXPAND to the main + panel results in it getting called anyway. */ + nc_layout_main_panel(ncd); + } + + nc_layout_new_cred_window(ncd); + + /* add this to the dialog chain */ + khm_add_dialog(hwnd); + + return TRUE; +} + +/* add a control row supplied by an identity provider */ +static void +nc_add_control_row(khui_nc_wnd_data * d, + HWND label, + HWND input, + khui_control_size size) +{ + RECT r_row; + RECT r_label; + RECT r_input; + HFONT hf; + HDWP hdefer; + + hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0); + SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE); + SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE); + + CopyRect(&r_row, &d->r_row); + OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom); + + if (size == KHUI_CTRLSIZE_SMALL) { + CopyRect(&r_label, &d->r_n_label); + CopyRect(&r_input, &d->r_n_input); + OffsetRect(&r_label, r_row.left, r_row.top); + OffsetRect(&r_input, r_row.left, r_row.top); + } else if (size == KHUI_CTRLSIZE_HALF) { + CopyRect(&r_label, &d->r_e_label); + CopyRect(&r_input, &d->r_e_input); + OffsetRect(&r_label, r_row.left, r_row.top); + OffsetRect(&r_input, r_row.left, r_row.top); + } else if (size == KHUI_CTRLSIZE_FULL) { + CopyRect(&r_label, &d->r_n_label); + r_label.right = d->r_row.right; + CopyRect(&r_input, &d->r_n_input); + OffsetRect(&r_input, r_row.left, r_row.top); + OffsetRect(&r_input, 0, r_input.bottom); + r_row.bottom += r_input.bottom; + OffsetRect(&r_label, r_row.left, r_row.top); + } else { + SetRectEmpty(&r_label); + SetRectEmpty(&r_input); +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + hdefer = BeginDeferWindowPos(2); + + if (label) + DeferWindowPos(hdefer, label, + ((d->hwnd_last_idspec != NULL)? + d->hwnd_last_idspec: + HWND_TOP), + r_label.left, r_label.top, + r_label.right - r_label.left, + r_label.bottom - r_label.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER); + + if (input) + DeferWindowPos(hdefer, input, + (label ? label : ((d->hwnd_last_idspec != NULL)? + d->hwnd_last_idspec: + HWND_TOP)), + r_input.left, r_input.top, + r_input.right - r_input.left, + r_input.bottom - r_input.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER); + + EndDeferWindowPos(hdefer); + + d->hwnd_last_idspec = (input ? input : label); + + d->r_idspec.bottom = r_row.bottom; + + /* we don't update the layout of the main panel yet, since these + control additions happen before the main panel is displayed. A + call to nc_layout_main_panel() will be made before the main + panel is shown anyway. */ + +} + + +static LRESULT +nc_handle_wm_destroy(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + khui_nc_wnd_data * d; + + /* remove self from dialog chain */ + khm_del_dialog(hwnd); + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + if (d == NULL) + return TRUE; + + d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0); + + if (d->hwnd_notif_label) + DestroyWindow(d->hwnd_notif_label); + if (d->hwnd_notif_aux) + DestroyWindow(d->hwnd_notif_aux); + + if(d->dlg_bb) + DestroyWindow(d->dlg_bb); + if(d->dlg_main) + DestroyWindow(d->dlg_main); + + d->dlg_bb = NULL; + d->dlg_main = NULL; + + PFREE(d); + SetWindowLongPtr(hwnd, CW_PARAM, 0); + + return TRUE; +} + +static LRESULT +nc_handle_wm_command(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + khui_nc_wnd_data * d; + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + if (d == NULL) + return 0; + + switch(HIWORD(wParam)) { + case BN_CLICKED: + switch(LOWORD(wParam)) { + + case IDOK: + d->nc->result = KHUI_NC_RESULT_PROCESS; + + /* fallthrough */ + + case IDCANCEL: + /* the default value for d->nc->result is set to + KHUI_NC_RESULT_CANCEL */ + d->nc->response = KHUI_NC_RESPONSE_PROCESSING; + + nc_enable_controls(d, FALSE); + + nc_notify_types(d->nc, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS), + (LPARAM) d->nc, + TRUE); + + khui_cw_sync_prompt_values(d->nc); + + khm_cred_dispatch_process_message(d->nc); + + /* we won't know whether to abort or not until we get + feedback from the plugins, even if the command was + to cancel */ + { + HWND hw; + + hw = GetDlgItem(d->dlg_main, IDOK); + EnableWindow(hw, FALSE); + hw = GetDlgItem(d->dlg_main, IDCANCEL); + EnableWindow(hw, FALSE); + hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED); + EnableWindow(hw, FALSE); + hw = GetDlgItem(d->dlg_bb, IDOK); + EnableWindow(hw, FALSE); + hw = GetDlgItem(d->dlg_bb, IDCANCEL); + EnableWindow(hw, FALSE); + } + return FALSE; + + case IDC_NC_HELP: + khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID); + return FALSE; + + case IDC_NC_BASIC: + case IDC_NC_ADVANCED: + /* the Options button in the main window was clicked. we + respond by expanding the dialog. */ + PostMessage(hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0); + return FALSE; + + case IDC_NC_CREDTEXT: /* credtext link activated */ + { + khui_htwnd_link * l; + wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD]; + wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD]; + wchar_t * colon; + + l = (khui_htwnd_link *) lParam; + + /* do we have a valid link? */ + if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid)) + return TRUE; /* nope */ + + StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len); + sid[l->id_len] = L'\0'; /* just make sure */ + + if(l->param != NULL && + l->param_len < ARRAYLENGTH(sparam) && + l->param_len > 0) { + + StringCchCopyN(sparam, ARRAYLENGTH(sparam), + l->param, l->param_len); + sparam[l->param_len] = L'\0'; + + } else { + sparam[0] = L'\0'; + } + + /* If the ID is of the form '<credtype>:<link_tag>' + and <credtype> is a valid name of a credentials + type that is participating in the credentials + acquisition process, then we forward the message to + the panel that is providing the UI for that cred + type. We also switch to that panel first, unless + the link is of the form '<credtype>:!<link_tag>'. */ + + colon = wcschr(sid, L':'); + if (colon != NULL) { + khm_int32 credtype; + khui_new_creds_by_type * t; + + *colon = L'\0'; + if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) && + KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){ + *colon = L':'; + + if (t->ordinal != d->current_panel && + *(colon + 1) != L'!') + PostMessage(hwnd, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(t->ordinal, + WMNC_DIALOG_SWITCH_PANEL), + 0); + + return SendMessage(t->hwnd_panel, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_CREDTEXT_LINK), + lParam); + } else { + *colon = L':'; + } + } + + /* if it was for us, then we need to process the message */ + if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) { + khm_int32 credtype; + khui_new_creds_by_type * t; + + if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam, + &credtype)) && + KHM_SUCCEEDED(khui_cw_find_type(d->nc, + credtype, &t))) { + if (t->ordinal != d->current_panel) + PostMessage(hwnd, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(t->ordinal, + WMNC_DIALOG_SWITCH_PANEL), + 0); + } + } else if (!_wcsicmp(sid, L"NotDef")) { + d->nc->set_default = FALSE; + nc_update_credtext(d); + } else if (!_wcsicmp(sid, L"MakeDef")) { + d->nc->set_default = TRUE; + nc_update_credtext(d); + } + } + return FALSE; + +#if 0 + case NC_BN_SET_DEF_ID: + { + d->nc->set_default = + (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID) + == BST_CHECKED); + } + return FALSE; +#endif + } + break; + } + + return TRUE; +} + +static LRESULT nc_handle_wm_moving(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + khui_nc_wnd_data * d; + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + if (d == NULL) + return FALSE; + + nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc, TRUE); + + return FALSE; +} + +static LRESULT nc_handle_wm_nc_notify(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + khui_nc_wnd_data * d; + int id; + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + if (d == NULL) + return FALSE; + + switch(HIWORD(wParam)) { + + case WMNC_DIALOG_SWITCH_PANEL: + id = LOWORD(wParam); + if(id >= 0 && id <= (int) d->nc->n_types) { + /* one of the tab buttons were pressed */ + if(d->current_panel == id) { + return TRUE; /* nothing to do */ + } + + d->current_panel = id; + + TabCtrl_SetCurSel(d->tab_wnd, id); + } + + if(d->nc->mode == KHUI_NC_MODE_EXPANDED) { + nc_layout_new_cred_window(d); + return TRUE; + } + /*else*/ + /* fallthrough */ + + case WMNC_DIALOG_EXPAND: + /* we are switching from basic to advanced or vice versa */ + + if (d->nc->mode == KHUI_NC_MODE_EXPANDED) { + + if (d->current_panel != 0) { + d->current_panel = 0; + TabCtrl_SetCurSel(d->tab_wnd, 0); + nc_layout_new_cred_window(d); + } + + d->nc->mode = KHUI_NC_MODE_MINI; + } else { + d->nc->mode = KHUI_NC_MODE_EXPANDED; + } + + /* if we are switching to the advanced mode, we clear any + notifications because we now have a credential text area + for that. */ + if (d->nc->mode == KHUI_NC_MODE_EXPANDED) + nc_notify_clear(d); + + nc_layout_main_panel(d); + + nc_layout_new_cred_window(d); + + break; + + case WMNC_DIALOG_SETUP: + + if(d->nc->n_types > 0) { + khm_size i; + for(i=0; i < d->nc->n_types;i++) { + + if (d->nc->types[i]->dlg_proc == NULL) { + d->nc->types[i]->hwnd_panel = NULL; + } else { + /* Create the dialog panel */ + d->nc->types[i]->hwnd_panel = + CreateDialogParam(d->nc->types[i]->h_module, + d->nc->types[i]->dlg_template, + d->nc->hwnd, + d->nc->types[i]->dlg_proc, + (LPARAM) d->nc); + +#ifdef DEBUG + assert(d->nc->types[i]->hwnd_panel); +#endif +#if _WIN32_WINNT >= 0x0501 + if (d->nc->types[i]->hwnd_panel) { + EnableThemeDialogTexture(d->nc->types[i]->hwnd_panel, + ETDT_ENABLETAB); + } +#endif + } + } + } + + break; + + case WMNC_DIALOG_ACTIVATE: + { + wchar_t wname[KCDB_MAXCCH_NAME]; + TCITEM tabitem; + khm_int32 t; + + /* About to activate the window. We should add all the + panels to the tab control. */ + +#ifdef DEBUG + assert(d->tab_wnd != NULL); +#endif + + ZeroMemory(&tabitem, sizeof(tabitem)); + + tabitem.mask = TCIF_PARAM | TCIF_TEXT; + + LoadString(khm_hInstance, IDS_NC_IDENTITY, + wname, ARRAYLENGTH(wname)); + + tabitem.pszText = wname; + tabitem.lParam = 0; /* ordinal */ + + TabCtrl_InsertItem(d->tab_wnd, 0, &tabitem); + + khui_cw_lock_nc(d->nc); + + if(d->nc->n_types > 0) { + khm_size i; + + /* We should sort the tabs first. See + nc_tab_sort_func() for sort criteria. */ + qsort(d->nc->types, + d->nc->n_types, + sizeof(*(d->nc->types)), + nc_tab_sort_func); + + for(i=0; i < d->nc->n_types;i++) { + + d->nc->types[i]->ordinal = i + 1; + + if(d->nc->types[i]->name) + tabitem.pszText = d->nc->types[i]->name; + else { + khm_size cbsize; + + cbsize = sizeof(wname); + + if(KHM_FAILED + (kcdb_credtype_describe + (d->nc->types[i]->type, + wname, + &cbsize, + KCDB_TS_SHORT))) { + +#ifdef DEBUG + assert(FALSE); +#endif + wname[0] = L'\0'; + + } + + tabitem.pszText = wname; + + } + + tabitem.lParam = d->nc->types[i]->ordinal; + + TabCtrl_InsertItem(d->tab_wnd, d->nc->types[i]->ordinal, + &tabitem); + } + } + + khui_cw_unlock_nc(d->nc); + + nc_update_credtext(d); + + TabCtrl_SetCurSel(d->tab_wnd, 0); /* the first selected + tab is the main + panel. */ + + /* we don't enable animations until a specific timeout + elapses after showing the window. We don't need to + animate any size changes if the user has barely had a + chance to notice the original size. This prevents the + new cred window from appearing in an animated state. */ + SetTimer(hwnd, NC_TIMER_ENABLEANIMATE, ENABLEANIMATE_TIMEOUT, NULL); + + ShowWindow(hwnd, SW_SHOWNORMAL); + + /* bring the window to the top, if necessary */ + if (KHM_SUCCEEDED(khc_read_int32(NULL, + L"CredWindow\\Windows\\NewCred\\ForceToTop", + &t)) && + + t != 0) { + + BOOL sfw = FALSE; + + /* it used to be that the above condition also called + !khm_is_dialog_active() to find out whether there + was a dialog active. If there was, we wouldn't try + to bring the new cred window to the foreground. But + that was not the behavior we want. */ + + /* if the main window is not visible, then the SetWindowPos() + call is sufficient to bring the new creds window to the + top. However, if the main window is visible but not + active, the main window needs to be activated before a + child window can be activated. */ + + SetActiveWindow(hwnd); + + sfw = SetForegroundWindow(hwnd); + + if (!sfw) { + FLASHWINFO fi; + + ZeroMemory(&fi, sizeof(fi)); + + fi.cbSize = sizeof(fi); + fi.hwnd = hwnd; + fi.dwFlags = FLASHW_ALL; + fi.uCount = 3; + fi.dwTimeout = 0; /* use the default cursor blink rate */ + + FlashWindowEx(&fi); + + d->flashing_enabled = TRUE; + } + + } else { + SetFocus(hwnd); + } + + if (d->nc->n_identities == 0) + break; + /* else */ + /* fallthrough */ + } + + case WMNC_IDENTITY_CHANGE: + { + BOOL okEnable = FALSE; + + nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc, + TRUE); + + if (d->nc->subtype == KMSG_CRED_NEW_CREDS && + d->nc->n_identities > 0 && + d->nc->identities[0]) { + khm_int32 f = 0; + + kcdb_identity_get_flags(d->nc->identities[0], &f); + + if (!(f & KCDB_IDENT_FLAG_DEFAULT)) { + d->nc->set_default = FALSE; + } + } + + nc_update_credtext(d); + + } + break; + + case WMNC_TYPE_STATE: + /* fallthrough */ + case WMNC_UPDATE_CREDTEXT: + nc_update_credtext(d); + break; + + case WMNC_CLEAR_PROMPTS: + { + khm_size i; + + khui_cw_lock_nc(d->nc); + + if(d->hwnd_banner != NULL) { + DestroyWindow(d->hwnd_banner); + d->hwnd_banner = NULL; + } + + if(d->hwnd_name != NULL) { + DestroyWindow(d->hwnd_name); + d->hwnd_name = NULL; + } + + for(i=0;i<d->nc->n_prompts;i++) { + if(!(d->nc->prompts[i]->flags & + KHUI_NCPROMPT_FLAG_STOCK)) { + if(d->nc->prompts[i]->hwnd_static != NULL) + DestroyWindow(d->nc->prompts[i]->hwnd_static); + + if(d->nc->prompts[i]->hwnd_edit != NULL) + DestroyWindow(d->nc->prompts[i]->hwnd_edit); + } + + d->nc->prompts[i]->hwnd_static = NULL; + d->nc->prompts[i]->hwnd_edit = NULL; + } + + khui_cw_unlock_nc(d->nc); + + SetRectEmpty(&d->r_custprompt); + + nc_layout_main_panel(d); + + nc_layout_new_cred_window(d); + } + break; + + case WMNC_SET_PROMPTS: + { + khm_size i; + int y; + HWND hw, hw_prev; + HFONT hf, hfold; + HDC hdc; + BOOL use_large_lables = FALSE; + + /* we assume that WMNC_CLEAR_PROMPTS has already been + received */ + +#ifdef DEBUG + assert(IsRectEmpty(&d->r_custprompt)); +#endif + + khui_cw_lock_nc(d->nc); + +#if 0 + /* special case, we have one prompt and it is a password + prompt. very common */ + if(d->nc->n_prompts == 1 && + d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) { + + hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD); + EnableWindow(hw, TRUE); + + d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK; + d->nc->prompts[0]->hwnd_edit = hw; + d->nc->prompts[0]->hwnd_static = NULL; /* don't care */ + + khui_cw_unlock_nc(d->nc); + break; + } +#endif + /* for everything else */ + + y = d->r_idspec.bottom; + + d->r_custprompt.left = d->r_area.left; + d->r_custprompt.right = d->r_area.right; + d->r_custprompt.top = y; + + hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0); + + if (d->nc->pname != NULL) { + hw = + CreateWindowEx + (0, + L"STATIC", + d->nc->pname, + SS_SUNKEN | WS_CHILD, + d->r_area.left, y, + d->r_row.right, + d->r_n_label.bottom - d->r_n_label.top, + d->dlg_main, + NULL, + khm_hInstance, + NULL); + +#ifdef DEBUG + assert(hw); +#endif + d->hwnd_name = hw; + SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE); + ShowWindow(hw, SW_SHOW); + + y += d->r_n_label.bottom - d->r_n_label.top; + } + + if (d->nc->banner != NULL) { + hw = + CreateWindowEx + (0, + L"STATIC", + d->nc->banner, + WS_CHILD, + d->r_area.left, y, + d->r_row.right, d->r_row.bottom, + d->dlg_main, + NULL, + khm_hInstance, + NULL); +#ifdef DEBUG + assert(hw); +#endif + d->hwnd_banner = hw; + SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE); + ShowWindow(hw, SW_SHOW); + y += d->r_row.bottom; + } + + hw_prev = d->hwnd_last_idspec; + + hdc = GetWindowDC(d->dlg_main); + hfold = SelectObject(hdc,hf); + + /* first do a trial run and see if we should use the + larger text labels or not. This is so that all the + labels and input controls align properly. */ + for (i=0; i < d->nc->n_prompts; i++) { + if (d->nc->prompts[i]->prompt != NULL) { + SIZE s; + + GetTextExtentPoint32(hdc, + d->nc->prompts[i]->prompt, + (int) wcslen(d->nc->prompts[i]->prompt), + &s); + + if(s.cx >= d->r_n_label.right - d->r_n_label.left) { + use_large_lables = TRUE; + break; + } + } + } + + for(i=0; i<d->nc->n_prompts; i++) { + RECT pr, er; + SIZE s; + int dy; + + if(d->nc->prompts[i]->prompt != NULL) { + GetTextExtentPoint32(hdc, + d->nc->prompts[i]->prompt, + (int) wcslen(d->nc->prompts[i]->prompt), + &s); + if(s.cx < d->r_n_label.right - d->r_n_label.left && + !use_large_lables) { + CopyRect(&pr, &d->r_n_label); + CopyRect(&er, &d->r_n_input); + dy = d->r_row.bottom; + } else if(s.cx < + d->r_e_label.right - d->r_e_label.left) { + CopyRect(&pr, &d->r_e_label); + CopyRect(&er, &d->r_e_input); + dy = d->r_row.bottom; + } else { + /* oops. the prompt doesn't fit in our + controls. we need to use up two lines */ + pr.left = 0; + pr.right = d->r_row.right; + pr.top = 0; + pr.bottom = d->r_n_label.bottom - + d->r_n_label.top; + CopyRect(&er, &d->r_n_input); + OffsetRect(&er, 0, pr.bottom); + dy = er.bottom + (d->r_row.bottom - + d->r_n_input.bottom); + } + } else { + SetRectEmpty(&pr); + CopyRect(&er, &d->r_n_input); + dy = d->r_row.bottom; + } + + if(IsRectEmpty(&pr)) { + d->nc->prompts[i]->hwnd_static = NULL; + } else { + OffsetRect(&pr, d->r_area.left, y); + + hw = CreateWindowEx + (0, + L"STATIC", + d->nc->prompts[i]->prompt, + WS_CHILD, + pr.left, pr.top, + pr.right - pr.left, pr.bottom - pr.top, + d->dlg_main, + NULL, + khm_hInstance, + NULL); +#ifdef DEBUG + assert(hw); +#endif + + SendMessage(hw, WM_SETFONT, + (WPARAM) hf, (LPARAM) TRUE); + + SetWindowPos(hw, hw_prev, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | + SWP_NOOWNERZORDER | SWP_NOSIZE | + SWP_SHOWWINDOW); + + d->nc->prompts[i]->hwnd_static = hw; + hw_prev = hw; + } + + OffsetRect(&er, d->r_area.left, y); + + hw = CreateWindowEx + (0, + L"EDIT", + (d->nc->prompts[i]->def ? + d->nc->prompts[i]->def : L""), + WS_CHILD | WS_TABSTOP | + WS_BORDER | ES_AUTOHSCROLL | + ((d->nc->prompts[i]->flags & + KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0), + er.left, er.top, + er.right - er.left, er.bottom - er.top, + d->dlg_main, + NULL, + khm_hInstance, + NULL); + +#ifdef DEBUG + assert(hw); +#endif + + SendMessage(hw, WM_SETFONT, + (WPARAM) hf, (LPARAM) TRUE); + + SetWindowPos(hw, hw_prev, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | + SWP_NOOWNERZORDER | SWP_NOSIZE | + SWP_SHOWWINDOW); + + SendMessage(hw, EM_SETLIMITTEXT, + KHUI_MAXCCH_PROMPT_VALUE -1, + 0); + + d->nc->prompts[i]->hwnd_edit = hw; + + hw_prev = hw; + + y += dy; + } + + if (d->nc->n_prompts > 0 && + d->nc->prompts[0]->hwnd_edit) { + + PostMessage(d->dlg_main, WM_NEXTDLGCTL, + (WPARAM) d->nc->prompts[0]->hwnd_edit, + MAKELPARAM(TRUE, 0)); + + } + + SelectObject(hdc, hfold); + ReleaseDC(d->dlg_main, hdc); + + khui_cw_unlock_nc(d->nc); + + d->r_custprompt.bottom = y; + + if (d->r_custprompt.bottom == d->r_custprompt.top) + SetRectEmpty(&d->r_custprompt); + + nc_layout_main_panel(d); + + nc_layout_new_cred_window(d); + } + break; + + case WMNC_DIALOG_PROCESS_COMPLETE: + { + khui_new_creds * nc; + + nc = d->nc; + + nc->response &= ~KHUI_NC_RESPONSE_PROCESSING; + + if(nc->response & KHUI_NC_RESPONSE_NOEXIT) { + HWND hw; + + nc_enable_controls(d, TRUE); + + /* reset state */ + nc->result = KHUI_NC_RESULT_CANCEL; + + hw = GetDlgItem(d->dlg_main, IDOK); + EnableWindow(hw, TRUE); + hw = GetDlgItem(d->dlg_main, IDCANCEL); + EnableWindow(hw, TRUE); + hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED); + EnableWindow(hw, TRUE); + hw = GetDlgItem(d->dlg_bb, IDOK); + EnableWindow(hw, TRUE); + hw = GetDlgItem(d->dlg_bb, IDCANCEL); + EnableWindow(hw, TRUE); + + nc_clear_password_fields(d); + + return TRUE; + } + + DestroyWindow(hwnd); + + kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc); + } + break; + + /* MUST be called with SendMessage */ + case WMNC_ADD_CONTROL_ROW: + { + khui_control_row * row; + + row = (khui_control_row *) lParam; + +#ifdef DEBUG + assert(row->label); + assert(row->input); +#endif + + nc_add_control_row(d, row->label, row->input, row->size); + } + break; + + case WMNC_UPDATE_LAYOUT: + { + + RECT r_client; + khm_int32 animate; + khm_int32 steps; + khm_int32 timeout; + + /* We are already adjusting the size of the window. The + next time the timer fires, it will notice if the target + size has changed. */ + if (d->size_changing) + return TRUE; + + GetClientRect(hwnd, &r_client); + + if ((r_client.right - r_client.left == + d->r_required.right - d->r_required.left) && + (r_client.bottom - r_client.top == + d->r_required.bottom - d->r_required.top)) { + + /* the window is already at the right size */ + return TRUE; + + } + + if (!IsWindowVisible(hwnd)) { + /* The window is not visible yet. There's no need to + animate anything. */ + + animate = FALSE; + + } else if (KHM_FAILED(khc_read_int32(NULL, + L"CredWindow\\Windows\\NewCred\\AnimateSizeChanges", + &animate))) { +#ifdef DEBUG + assert(FALSE); +#endif + animate = TRUE; + } + + /* if we aren't animating the window resize, then we just + do it in one call. */ + if (!animate || !d->animation_enabled) { + RECT r_window; + + CopyRect(&r_window, &d->r_required); + AdjustWindowRectEx(&r_window, NC_WINDOW_STYLES, FALSE, + NC_WINDOW_EX_STYLES); + + SetWindowPos(hwnd, NULL, 0, 0, + r_window.right - r_window.left, + r_window.bottom - r_window.top, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | + SWP_NOZORDER); + + return TRUE; + } + + if (KHM_FAILED(khc_read_int32(NULL, + L"CredWindow\\Windows\\NewCred\\AnimationSteps", + &steps))) { +#ifdef DEBUG + assert(FALSE); +#endif + steps = NC_SZ_STEPS_DEF; + } else { + + if (steps < NC_SZ_STEPS_MIN) + steps = NC_SZ_STEPS_MIN; + else if (steps > NC_SZ_STEPS_MAX) + steps = NC_SZ_STEPS_MAX; + + } + + if (KHM_FAILED(khc_read_int32(NULL, + L"CredWindow\\Windows\\NewCred\\AnimationStepTimeout", + &timeout))) { +#ifdef DEBUG + assert(FALSE); +#endif + timeout = NC_SZ_TIMEOUT_DEF; + } else { + + if (timeout < NC_SZ_TIMEOUT_MIN) + timeout = NC_SZ_TIMEOUT_MIN; + else if (timeout > NC_SZ_TIMEOUT_MAX) + timeout = NC_SZ_TIMEOUT_MAX; + + } + + CopyRect(&d->sz_ch_source, &r_client); + OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top); + CopyRect(&d->sz_ch_target, &d->r_required); + OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top); + d->sz_ch_increment = 0; + d->sz_ch_max = steps; + d->sz_ch_timeout = timeout; + d->size_changing = TRUE; + + SetTimer(hwnd, NC_TIMER_SIZER, timeout, NULL); + } + break; + } /* switch(HIWORD(wParam)) */ + + return TRUE; +} + +static LRESULT nc_handle_wm_timer(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + khui_nc_wnd_data * d; + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + if (d == NULL) + return FALSE; + + if (wParam == NC_TIMER_SIZER) { + + RECT r_now; + + /* are we done with this sizing operation? */ + if (!d->size_changing || + d->sz_ch_increment >= d->sz_ch_max) { + + d->size_changing = FALSE; + KillTimer(hwnd, NC_TIMER_SIZER); + return 0; + } + + /* have the requirements changed while we were processing the + sizing operation? */ + if ((d->r_required.right - d->r_required.left != + d->sz_ch_target.right) + + || + + (d->r_required.bottom - d->r_required.top != + d->sz_ch_target.bottom)) { + + /* the target size has changed. we need to restart the + sizing operation. */ + + RECT r_client; + + GetClientRect(hwnd, &r_client); + + CopyRect(&d->sz_ch_source, &r_client); + OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top); + CopyRect(&d->sz_ch_target, &d->r_required); + OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top); + d->sz_ch_increment = 0; + + /* leave the other fields alone */ + +#ifdef DEBUG + assert(d->sz_ch_max >= NC_SZ_STEPS_MIN); + assert(d->sz_ch_max <= NC_SZ_STEPS_MAX); + assert(d->sz_ch_timeout >= NC_SZ_TIMEOUT_MIN); + assert(d->sz_ch_timeout <= NC_SZ_TIMEOUT_MAX); + assert(d->size_changing); +#endif + } + + /* we are going to do the next increment */ + d->sz_ch_increment ++; + + /* now, figure out the size of the client area for this + step */ + + r_now.left = 0; + r_now.top = 0; + +#define PROPORTION(v1, v2, i, s) (((v1) * ((s) - (i)) + (v2) * (i)) / (s)) + + r_now.right = PROPORTION(d->sz_ch_source.right, d->sz_ch_target.right, + d->sz_ch_increment, d->sz_ch_max); + + r_now.bottom = PROPORTION(d->sz_ch_source.bottom, d->sz_ch_target.bottom, + d->sz_ch_increment, d->sz_ch_max); + +#undef PROPORTION + +#ifdef DEBUG + { + long dx = ((r_now.right - r_now.left) - d->sz_ch_target.right) * + (d->sz_ch_source.right - d->sz_ch_target.right); + + long dy = ((r_now.bottom - r_now.top) - d->sz_ch_target.bottom) * + (d->sz_ch_source.bottom - d->sz_ch_target.bottom); + + if (dx < 0 || dy < 0) { + KillTimer(hwnd, NC_TIMER_SIZER); + assert(dx >= 0); + assert(dy >= 0); + SetTimer(hwnd, NC_TIMER_SIZER, d->sz_ch_timeout, NULL); + } + } +#endif + + AdjustWindowRectEx(&r_now, NC_WINDOW_STYLES, FALSE, + NC_WINDOW_EX_STYLES); + + { + RECT r; + + GetWindowRect(hwnd, &r); + OffsetRect(&r_now, r.left - r_now.left, r.top - r_now.top); + } + + khm_adjust_window_dimensions_for_display(&r_now, 0); + + SetWindowPos(hwnd, NULL, + r_now.left, r_now.top, + r_now.right - r_now.left, + r_now.bottom - r_now.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOZORDER); + + /* and now we wait for the next timer message */ + + return 0; + } else if (wParam == NC_TIMER_ENABLEANIMATE) { + + d->animation_enabled = TRUE; + KillTimer(hwnd, NC_TIMER_ENABLEANIMATE); + } + + return 0; +} + +static LRESULT nc_handle_wm_notify(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + LPNMHDR nmhdr; + khui_nc_wnd_data * d; + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + if (d == NULL) + return FALSE; + + nmhdr = (LPNMHDR) lParam; + + if (nmhdr->code == TCN_SELCHANGE) { + /* the current tab has changed. */ + int idx; + TCITEM tcitem; + + idx = TabCtrl_GetCurSel(d->tab_wnd); + ZeroMemory(&tcitem, sizeof(tcitem)); + + tcitem.mask = TCIF_PARAM; + TabCtrl_GetItem(d->tab_wnd, idx, &tcitem); + + d->current_panel = (int) tcitem.lParam; + + nc_layout_new_cred_window(d); + + return TRUE; + } + + return FALSE; +} + +static LRESULT nc_handle_wm_help(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + static DWORD ctxids[] = { + NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN, + NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON, + NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON, + NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON, + NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON, + NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON, + NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON, + NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON, + IDOK, IDH_NC_OK, + IDCANCEL, IDH_NC_CANCEL, + IDC_NC_HELP, IDH_NC_HELP, + IDC_NC_ADVANCED, IDH_NC_ADVANCED, + IDC_NC_CREDTEXT, IDH_NC_CREDWND, + 0 + }; + + HELPINFO * hlp; + HWND hw = NULL; + HWND hw_ctrl; + khui_nc_wnd_data * d; + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + if (d == NULL) + return FALSE; + + hlp = (HELPINFO *) lParam; + + if (d->nc->subtype != KMSG_CRED_NEW_CREDS && + d->nc->subtype != KMSG_CRED_PASSWORD) + return TRUE; + + if (hlp->iContextType != HELPINFO_WINDOW) + return TRUE; + + if (hlp->hItemHandle != NULL && + hlp->hItemHandle != hwnd) { + DWORD id; + int i; + + hw_ctrl =hlp->hItemHandle; + + id = GetWindowLong(hw_ctrl, GWL_ID); + for (i=0; ctxids[i] != 0; i += 2) + if (ctxids[i] == id) + break; + + if (ctxids[i] != 0) + hw = khm_html_help(hw_ctrl, + ((d->nc->subtype == KMSG_CRED_NEW_CREDS)? + L"::popups_newcreds.txt": + L"::popups_password.txt"), + HH_TP_HELP_WM_HELP, + (DWORD_PTR) ctxids); + } + + if (hw == NULL) { + khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, + ((d->nc->subtype == KMSG_CRED_NEW_CREDS)? + IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID)); + } + + return TRUE; +} + +static LRESULT nc_handle_wm_activate(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + if (uMsg == WM_MOUSEACTIVATE || + wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) { + + FLASHWINFO fi; + khui_nc_wnd_data * d; + DWORD_PTR ex_style; + + d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM); + + if (d && d->flashing_enabled) { + ZeroMemory(&fi, sizeof(fi)); + + fi.cbSize = sizeof(fi); + fi.hwnd = hwnd; + fi.dwFlags = FLASHW_STOP; + + FlashWindowEx(&fi); + + d->flashing_enabled = FALSE; + } + + ex_style = GetWindowLongPtr(hwnd, GWL_EXSTYLE); + + if (ex_style & WS_EX_TOPMOST) { + SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + } + + return (uMsg == WM_MOUSEACTIVATE)? MA_ACTIVATE : 0; +} + +static LRESULT CALLBACK nc_window_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_MOUSEACTIVATE: + case WM_ACTIVATE: + return nc_handle_wm_activate(hwnd, uMsg, wParam, lParam); + + case WM_CREATE: + return nc_handle_wm_create(hwnd, uMsg, wParam, lParam); + + case WM_DESTROY: + return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam); + + case WM_COMMAND: + return nc_handle_wm_command(hwnd, uMsg, wParam, lParam); + + case WM_NOTIFY: + return nc_handle_wm_notify(hwnd, uMsg, wParam, lParam); + + case WM_MOVE: + case WM_MOVING: + return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam); + + case WM_TIMER: + return nc_handle_wm_timer(hwnd, uMsg, wParam, lParam); + + case WM_HELP: + return nc_handle_wm_help(hwnd, uMsg, wParam, lParam); + + case KHUI_WM_NC_NOTIFY: + return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam); + } + + /* Note that this is technically a dialog box */ + return DefDlgProc(hwnd, uMsg, wParam, lParam); +} + +void khm_register_newcredwnd_class(void) +{ + WNDCLASSEX wcx; + + wcx.cbSize = sizeof(wcx); + wcx.style = CS_DBLCLKS | CS_OWNDC; + wcx.lpfnWndProc = nc_window_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR); + wcx.hInstance = khm_hInstance; + wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); + wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_NEWCREDWND_CLASS; + wcx.hIconSm = NULL; + + khui_newcredwnd_cls = RegisterClassEx(&wcx); +} + +void khm_unregister_newcredwnd_class(void) +{ + UnregisterClass(MAKEINTATOM(khui_newcredwnd_cls), khm_hInstance); +} + +HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c) +{ + wchar_t wtitle[256]; + HWND hwnd; + khm_int32 force_topmost = 0; + + if (c->window_title == NULL) { + if (c->subtype == KMSG_CRED_PASSWORD) + LoadString(khm_hInstance, + IDS_WT_PASSWORD, + wtitle, + ARRAYLENGTH(wtitle)); + else + LoadString(khm_hInstance, + IDS_WT_NEW_CREDS, + wtitle, + ARRAYLENGTH(wtitle)); + } + + khc_read_int32(NULL, L"CredWindow\\Windows\\NewCred\\ForceToTop", &force_topmost); + + hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES | (force_topmost ? WS_EX_TOPMOST : 0), + MAKEINTATOM(khui_newcredwnd_cls), + ((c->window_title)?c->window_title: wtitle), + NC_WINDOW_STYLES, + 0,0,400,400, /* bogus values. the window + is going to resize and + reposition itself + anyway */ + parent, + NULL, + khm_hInstance, + (LPVOID) c); + +#ifdef DEBUG + assert(hwnd != NULL); +#endif + + /* note that the window is not visible yet. That's because, at + this point we don't know what the panels are */ + + return hwnd; +} + +void khm_prep_newcredwnd(HWND hwnd) +{ + SendMessage(hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0); +} + +void khm_show_newcredwnd(HWND hwnd) +{ + /* add all the panels in and prep UI */ + PostMessage(hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0); +} diff --git a/krb5-1-6/src/windows/identity/ui/newcredwnd.h b/krb5-1-6/src/windows/identity/ui/newcredwnd.h new file mode 100644 index 000000000..872cad2ed --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/newcredwnd.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_NEWCREDWND_H +#define __KHIMAIRA_NEWCREDWND_H + +#include<khuidefs.h> + +#define KHUI_NEWCREDWND_CLASS L"KhmNewCredWnd" + +typedef enum tag_nc_notification_types { + NC_NOTIFY_NONE = 0, /* no notification */ + NC_NOTIFY_MARQUEE, /* marquee type notification */ + NC_NOTIFY_PROGRESS, /* progress notification */ + NC_NOTIFY_MESSAGE, /* a message */ +} nc_notification_type; + +typedef struct khui_nc_wnd_data_t { + khui_new_creds * nc; + + /* The tab control */ + + HWND tab_wnd; /* tab control */ + int current_panel; /* ordinal of the current panel being + displayed. */ + + /* The main panel */ + HWND dlg_main; /* main dialog */ + RECT r_main; /* the extent of the main panel that + we have used so far. The rect + includes the size of the area used + by the identity selector controls, + the custom controls added by + credentials providers and the + buttons that may be required when + in the mini mode. */ + RECT r_required; /* required size of the main window */ + + /* The button bar */ + + HWND dlg_bb; /* button bar */ + + /* Sizing the new credentials window */ + + BOOL animation_enabled; /* Flag indicating whether animation + is enabled for the dialg. If this + flag is off, we don't animate size + changes even if the configuration + says so. */ + BOOL size_changing; /* flag indicating that the size of + the main window is being + adjusted. */ + RECT sz_ch_source; /* Source size, from which we are + going towards target size in + sz_ch_max steps. The RECT is self + relative (i.e. left=0 and top=0)*/ + RECT sz_ch_target; /* If we are doing an incremental size + change, this holds the target size + that we were going for. Note that + the target size might change while + we are adjusting the size. So this + helps keep track of whether we need + to start the size change again. The + RECT is self relative (i.e. left=0 + and top=0). */ + int sz_ch_increment; /* Current step of the incremental + size change operation. */ + int sz_ch_max; /* Max number of steps in the size + change operation. */ + int sz_ch_timeout; /* Milliseconds between each increment */ + + BOOL flashing_enabled; /* The window maybe still flashing + from the last call to + FlashWindowEx(). */ + + /* Custom controls and identity specifiers */ + + HWND hwnd_banner; /* static control for banner */ + HWND hwnd_name; /* static control for name */ + + HWND hwnd_last_idspec; /* last identity specifier control */ + + /* Notification windows */ + + nc_notification_type notif_type; /* Type of notification */ + HWND hwnd_notif_label; /* Label for notifications */ + HWND hwnd_notif_aux; /* Other control for notifications */ + + /* Areas of the main panel */ + + RECT r_idspec; /* Area used by identity specifiers + (relative to client) */ + RECT r_custprompt; /* Area used by custom controls (relative + to client) */ + RECT r_notif; /* Area used for notifications. */ + + /* Metrics for custom prompts and identity specifiers */ + + RECT r_row; /* Metrics for a control row (left=0, + top=0, right=width, bottom=height) */ + RECT r_area; /* Area available for controls (relative + to client) */ + RECT r_n_label; /* coords of the static control (relative + to row) */ + RECT r_n_input; /* coords of the edit control (relative to + row) */ + RECT r_e_label; /* coords of the extended edit control + (relative to row) */ + RECT r_e_input; /* coords of the extended edit control + (relative to row) */ + RECT r_credtext; /* Area for credtext window (relative to + row) */ +} khui_nc_wnd_data; + +void khm_register_newcredwnd_class(void); +void khm_unregister_newcredwnd_class(void); +HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c); +void khm_prep_newcredwnd(HWND hwnd); +void khm_show_newcredwnd(HWND hwnd); + +/* Width of the button bar in dialog units */ +#define NCDLG_BBAR_WIDTH 66 +/* Height of the button bar in dialog units */ +#define NCDLG_BBAR_HEIGHT 190 + +/* Control identifier for the tab control in the new credentials + dialog. We declare this here since we will be creating the control + manually. */ +#define IDC_NC_TABS 8001 + +/* This is the first control ID that is created in the custom tabstrip + control buttons. Subsequent buttons get consecutive IDs starting + from this one. */ +#define NC_TS_CTRL_ID_MIN 8002 + +/* Maximum number of controls */ +#define NC_TS_MAX_CTRLS 8 + +/* Maximum control ID */ +#define NC_TS_CTRL_ID_MAX (NC_TS_CTRL_ID_MIN + NC_TS_MAX_CTRLS - 1) + +#define NC_BN_SET_DEF_ID 8012 + +/* the first control ID that may be used by an identity provider */ +#define NC_IS_CTRL_ID_MIN 8016 + +/* the maximum number of controls that may be created by an identity + provider*/ +#define NC_IS_CTRL_MAX_CTRLS 8 + +/* the maximum control ID that may be used by an identity provider */ +#define NC_IS_CTRL_ID_MAX (NC_IS_CTRL_ID_MIN + NC_IS_MAX_CTRLS - 1) + +#define NC_WINDOW_EX_STYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP | WS_EX_APPWINDOW) +#define NC_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN) + +#define NC_SZ_STEPS_MIN 3 +#define NC_SZ_STEPS_DEF 10 +#define NC_SZ_STEPS_MAX 100 + +#define NC_SZ_TIMEOUT_MIN 5 +#define NC_SZ_TIMEOUT_DEF 10 +#define NC_SZ_TIMEOUT_MAX 500 + +#define NC_TIMER_SIZER 1001 +#define NC_TIMER_ENABLEANIMATE 1002 + +#define ENABLEANIMATE_TIMEOUT 400 + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/notifier.c b/krb5-1-6/src/windows/identity/ui/notifier.c new file mode 100644 index 000000000..84db735c0 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/notifier.c @@ -0,0 +1,3174 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define OEMRESOURCE + +#include<khmapp.h> +#include<assert.h> + +#define KHUI_NOTIFIER_CLASS L"KhuiNotifierMsgWindowClass" +#define KHUI_ALERTER_CLASS L"KhuiAlerterWindowClass" +#define KHUI_ALERTBIN_CLASS L"KhuiAlertBinWindowClass" + +#define KHUI_NOTIFIER_WINDOW L"KhuiNotifierMsgWindow" + + +/* The commands that are available as default actions when the user + clicks the notification icon. */ + +khm_int32 khm_notifier_actions[] = { + KHUI_ACTION_OPEN_APP, + KHUI_ACTION_NEW_CRED +}; + +khm_size n_khm_notifier_actions = ARRAYLENGTH(khm_notifier_actions); + +/* notifier message for notification icon */ +#define KHUI_WM_NOTIFIER WM_COMMAND + +#define DRAWTEXTOPTIONS (DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK) + +/* are we showing an alert? */ +#define ALERT_DISPLAYED() (balloon_alert != NULL || khui_alert_windows != NULL) + +/* Forward declarations */ + +struct tag_alerter_wnd_data; +typedef struct tag_alerter_wnd_data alerter_wnd_data; + +struct tag_alert_list; +typedef struct tag_alert_list alert_list; + +static khm_int32 +alert_show(khui_alert * a); + +static khm_int32 +alert_show_minimized(khui_alert * a); + +static khm_int32 +alert_show_normal(khui_alert * a); + +static khm_int32 +alert_show_list(alert_list * alist); + +static khm_int32 +alert_enqueue(khui_alert * a); + +static khm_boolean +alert_is_equal(khui_alert * a1, khui_alert * a2); + +static void +check_for_queued_alerts(void); + +static void +show_queued_alerts(void); + +static khm_int32 +alert_consolidate(alert_list * alist, + khui_alert * alert, + khm_boolean add_from_queue); + +/* Globals */ + +/* window class registration atom for message only notifier window + class */ +ATOM atom_notifier = 0; + +/* window class registration atom for alert windows */ +ATOM atom_alerter = 0; +/* window class registration atom for the alert "bin", which is the + window that holds all the alerts. */ +ATOM atom_alert_bin = 0; + +/* notifier message window */ +HWND hwnd_notifier = NULL; + +BOOL notifier_ready = FALSE; + +/* The list of alert windows currently active */ +alerter_wnd_data * khui_alert_windows = NULL; + +/* Notification icon for when there are no alerts to be displayed */ +int iid_normal = IDI_NOTIFY_NONE; + +/* Tooltip to use when there are no alerts to be displayed */ +wchar_t tip_normal[128] = L""; + +/* Current notifier severity level */ +khm_int32 notifier_severity = KHERR_NONE; + +/* The alert currently being displayed in a balloon */ +khui_alert * balloon_alert = NULL; + +/********************************************************************** + Alert Queue + + The alert queue is the data structure that keeps track of all the + alerts that are waiting to be displayed. Alerts will be placed on + the queue if they cannot be immediately displayed for some reason + (e.g. another alert is being displayed, or the user is working in + another window). +***********************************************************************/ + +#define KHUI_ALERT_QUEUE_MAX 64 + +khui_alert * alert_queue[KHUI_ALERT_QUEUE_MAX]; +khm_int32 alert_queue_head = 0; +khm_int32 alert_queue_tail = 0; + +#define is_alert_queue_empty() (alert_queue_head == alert_queue_tail) +#define is_alert_queue_full() (((alert_queue_tail + 1) % KHUI_ALERT_QUEUE_MAX) == alert_queue_head) + +/* NOTE: the alert queue functions are unsafe to call from any thread + other than the UI thread. */ + +static void +alert_queue_put_alert(khui_alert * a) { + if (is_alert_queue_full()) return; + alert_queue[alert_queue_tail++] = a; + khui_alert_hold(a); + alert_queue_tail %= KHUI_ALERT_QUEUE_MAX; +} + +/* the caller needs to release the alert that's returned */ +static khui_alert * +alert_queue_get_alert(void) { + khui_alert * a; + + if (is_alert_queue_empty()) return NULL; + a = alert_queue[alert_queue_head++]; + alert_queue_head %= KHUI_ALERT_QUEUE_MAX; + + return a; /* held */ +} + +static int +alert_queue_get_size(void) { + if (is_alert_queue_empty()) + return 0; + + if (alert_queue_tail < alert_queue_head) { + return (alert_queue_tail + KHUI_ALERT_QUEUE_MAX - alert_queue_head); + } else { + return alert_queue_tail - alert_queue_head; + } +} + +static khui_alert * +alert_queue_get_alert_by_pos(int pos) { + khui_alert * a; + + if (is_alert_queue_empty() || + pos >= alert_queue_get_size() || + pos < 0) { + return NULL; + } + + a = alert_queue[(alert_queue_head + pos) % KHUI_ALERT_QUEUE_MAX]; + if (a) { + khui_alert_hold(a); + } + return a; +} + +static int +alert_queue_delete_alert(khui_alert * a) { + int idx; + int succ; + + idx = alert_queue_head; + while(idx != alert_queue_tail) { + if (alert_queue[idx] == a) + break; + + idx = (idx + 1) % KHUI_ALERT_QUEUE_MAX; + } + + if (idx == alert_queue_tail) + return 0; + +#ifdef DEBUG + assert(alert_queue[idx]); +#endif + khui_alert_release(alert_queue[idx]); + + succ = (idx + 1) % KHUI_ALERT_QUEUE_MAX; + while(succ != alert_queue_tail) { + alert_queue[idx] = alert_queue[succ]; + + succ = (succ + 1) % KHUI_ALERT_QUEUE_MAX; + idx = (idx + 1) % KHUI_ALERT_QUEUE_MAX; + } + + alert_queue_tail = idx; + return 1; +} + +/* the caller needs to release the alert that's returned */ +static khui_alert * +alert_queue_peek(void) { + khui_alert * a; + + if (is_alert_queue_empty()) + return NULL; + + a = alert_queue[alert_queue_head]; + khui_alert_hold(a); + + return a; +} + +/********************************************************************** + Alert List + + A list of alerts. Currently has a fixed upper limit, but the limit + is high enough for now. +***********************************************************************/ + +typedef struct tag_alert_list { + khui_alert * alerts[KHUI_ALERT_QUEUE_MAX]; + int n_alerts; + wchar_t title[KHUI_MAXCCH_TITLE]; +} alert_list; + +static void +alert_list_init(alert_list * alist) { + ZeroMemory(alist, sizeof(*alist)); +} + +static void +alert_list_set_title(alert_list * alist, wchar_t * title) { + StringCbCopy(alist->title, sizeof(alist->title), title); +} + +static khm_int32 +alert_list_add_alert(alert_list * alist, + khui_alert * alert) { + + if (alist->n_alerts == ARRAYLENGTH(alist->alerts)) + return KHM_ERROR_NO_RESOURCES; + + khui_alert_hold(alert); + alist->alerts[alist->n_alerts++] = alert; + + return KHM_ERROR_SUCCESS; +} + +static void +alert_list_destroy(alert_list * alist) { + int i; + + for (i=0; i < alist->n_alerts; i++) { + if (alist->alerts[i] != NULL) { + khui_alert_release(alist->alerts[i]); + alist->alerts[i] = NULL; + } + } + + alist->n_alerts = 0; +} + + +/********************************************************************** + Notifier Window + + The notifier window manages the notification icon and handles + KMSG_ALERT messages sent from the UI library. The window will exist + for the lifetime of the application. +***********************************************************************/ + +/* These are defined for APPVER >= 0x501. We are defining them here + so that we can build with APPVER = 0x500 and use the same binaries + with Win XP. */ + +#ifndef NIN_BALLOONSHOW +#define NIN_BALLOONSHOW (WM_USER + 2) +#endif + +#ifndef NIN_BALLOONHIDE +#define NIN_BALLOONHIDE (WM_USER + 3) +#endif + +#ifndef NIN_BALLOONTIMEOUT +#define NIN_BALLOONTIMEOUT (WM_USER + 4) +#endif + +#ifndef NIN_BALLOONUSERCLICK +#define NIN_BALLOONUSERCLICK (WM_USER + 5) +#endif + + +static LRESULT CALLBACK +notifier_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + kmq_message * m; + khm_int32 rv; + + if(uMsg == KMQ_WM_DISPATCH) { + kmq_wm_begin(lParam, &m); + rv = KHM_ERROR_SUCCESS; + + if(m->type == KMSG_ALERT) { + /* handle notifier messages */ + switch(m->subtype) { + case KMSG_ALERT_SHOW: + { + khui_alert * a; + + a = (khui_alert *) m->vparam; +#ifdef DEBUG + assert(a != NULL); +#endif + rv = alert_show(a); + khui_alert_release(a); + } + break; + + case KMSG_ALERT_QUEUE: + { + khui_alert * a; + + a = (khui_alert *) m->vparam; +#ifdef DEBUG + assert(a != NULL); +#endif + rv = alert_enqueue(a); + khui_alert_release(a); + } + break; + + case KMSG_ALERT_CHECK_QUEUE: + check_for_queued_alerts(); + break; + + case KMSG_ALERT_SHOW_QUEUED: + show_queued_alerts(); + break; + + case KMSG_ALERT_SHOW_MODAL: + { + khui_alert * a; + + a = (khui_alert *) m->vparam; +#ifdef DEBUG + assert(a != NULL); +#endif + khui_alert_lock(a); + a->flags |= KHUI_ALERT_FLAG_MODAL; + khui_alert_unlock(a); + + rv = alert_show(a); + + if (KHM_SUCCEEDED(rv)) { + khm_message_loop_int(&a->displayed); + } + + khui_alert_release(a); + } + break; + } + } else if (m->type == KMSG_CRED && + m->subtype == KMSG_CRED_ROOTDELTA) { + + KillTimer(hwnd, KHUI_REFRESH_TIMER_ID); + SetTimer(hwnd, KHUI_REFRESH_TIMER_ID, + KHUI_REFRESH_TIMEOUT, + NULL); + + } + + return kmq_wm_end(m, rv); + } else if (uMsg == KHUI_WM_NOTIFIER) { + /* Handle events generated from the notification icon */ + + /* wParam is the identifier of the notify icon, but we only + have one. */ + switch(lParam) { + case WM_CONTEXTMENU: + { + POINT pt; + int menu_id; + khui_menu_def * mdef; + khui_action_ref * act = NULL; + khm_size i, n; + khm_int32 def_cmd; + + /* before we show the context menu, we need to make + sure that the default action for the notification + icon is present in the menu and that it is marked + as the default. */ + + def_cmd = khm_get_default_notifier_action(); + + if (khm_is_main_window_visible()) { + menu_id = KHUI_MENU_ICO_CTX_NORMAL; + + if (def_cmd == KHUI_ACTION_OPEN_APP) + def_cmd = KHUI_ACTION_CLOSE_APP; + } else { + menu_id = KHUI_MENU_ICO_CTX_MIN; + } + + mdef = khui_find_menu(menu_id); + +#ifdef DEBUG + assert(mdef); +#endif + n = khui_menu_get_size(mdef); + for (i=0; i < n; i++) { + act = khui_menu_get_action(mdef, i); + if (!(act->flags & KHUI_ACTIONREF_PACTION) && + (act->action == def_cmd)) + break; + } + + if (i < n) { + if (!(act->flags & KHUI_ACTIONREF_DEFAULT)) { + khui_menu_remove_action(mdef, i); + khui_menu_insert_action(mdef, i, def_cmd, KHUI_ACTIONREF_DEFAULT); + } else { + /* we are all set */ + } + } else { + /* the default action was not found on the context + menu */ +#ifdef DEBUG + assert(FALSE); +#endif + khui_menu_insert_action(mdef, 0, def_cmd, KHUI_ACTIONREF_DEFAULT); + } + + SetForegroundWindow(khm_hwnd_main); + + GetCursorPos(&pt); + khm_menu_show_panel(menu_id, pt.x, pt.y); + + PostMessage(khm_hwnd_main, WM_NULL, 0, 0); + } + break; + + case NIN_SELECT: + /* fall through */ + case NIN_KEYSELECT: + /* If there were any alerts waiting to be shown, we show + them. Otherwise we perform the default action. */ + khm_notify_icon_activate(); + break; + + case NIN_BALLOONUSERCLICK: + if (balloon_alert) { + khui_alert * a; + + khm_notify_icon_change(KHERR_NONE); + + a = balloon_alert; + balloon_alert = NULL; + + khui_alert_lock(a); + a->displayed = FALSE; + + if ((a->flags & KHUI_ALERT_FLAG_DEFACTION) && + !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW) && + a->n_alert_commands > 0) { + PostMessage(khm_hwnd_main, WM_COMMAND, + MAKEWPARAM(a->alert_commands[0], + 0), + 0); + } else if (a->flags & + KHUI_ALERT_FLAG_REQUEST_WINDOW) { + khm_show_main_window(); + alert_show_normal(a); + } + + khui_alert_unlock(a); + khui_alert_release(a); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + break; + + case NIN_BALLOONHIDE: + case NIN_BALLOONTIMEOUT: + khm_notify_icon_change(KHERR_NONE); + if (balloon_alert) { + khui_alert * a; + a = balloon_alert; + balloon_alert = NULL; + + khui_alert_lock(a); + a->displayed = FALSE; + khui_alert_unlock(a); + + khui_alert_release(a); + } + break; + } + } else if (uMsg == WM_TIMER) { + if (wParam == KHUI_TRIGGER_TIMER_ID) { + KillTimer(hwnd, KHUI_TRIGGER_TIMER_ID); + khm_timer_fire(hwnd); + } else if (wParam == KHUI_REFRESH_TIMER_ID) { + KillTimer(hwnd, KHUI_REFRESH_TIMER_ID); + kcdb_identity_refresh_all(); + khm_timer_refresh(hwnd); + } + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +ATOM +khm_register_notifier_wnd_class(void) +{ + WNDCLASSEX wcx; + + ZeroMemory(&wcx, sizeof(wcx)); + + wcx.cbSize = sizeof(wcx); + wcx.style = 0; + wcx.lpfnWndProc = notifier_wnd_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = khm_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = NULL; + wcx.hbrBackground = NULL; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_NOTIFIER_CLASS; + wcx.hIconSm = NULL; + + atom_notifier = RegisterClassEx(&wcx); + + return atom_notifier; +} + +/********************************************************************* + Alerter +**********************************************************************/ + +typedef struct tag_alerter_alert_data { + khui_alert * alert; + + BOOL seen; /* has the user seen this alert? */ + + BOOL has_commands; /* we cache the value here. otherwise + we'll have to get a lock on the + alert each time we have to find out + whether there are any commands for + this alert. */ + + RECT r_alert; /* the entire alert, relative to self. */ + + /* the following rects are relative to the top left of r_alert. */ + + RECT r_title; /* the title. deflate by padding to + get the text rect. */ + RECT r_icon; /* rect for icon */ + RECT r_message; /* rect for the text. no padding + necessary. */ + RECT r_suggestion; /* rect for the suggestion. deflate + by padding to get the suggestion + rect. The suggestion rect includes + space for the small icon on the + left and padding between the icon + and the text. The size of the small + icon are as per system metrics + SM_C{X,Y}SMICON. Padding is + s_pad.cx vertical. */ + + int n_cmd_buttons; /* number of command buttons in this alert. */ + + RECT r_buttons[KHUI_MAX_ALERT_COMMANDS]; + /* rects for the command buttons. */ + + HWND hwnd_buttons[KHUI_MAX_ALERT_COMMANDS]; + /* handles for the command buttons */ + + HWND hwnd_marker; + /* handle to the marker window used as + a tab-stop target when there are + not buttons associated with the + alert. */ + + LDCL(struct tag_alerter_alert_data); +} alerter_alert_data; + +typedef struct tag_alerter_wnd_data { + HWND hwnd; + HFONT hfont; + + wchar_t caption[KHUI_MAXCCH_TITLE]; /* the original + caption for the + dialog. */ + + HWND hw_bin; + HWND hw_scroll; + HWND hw_close; + + int scroll_top; + + int n_cmd_buttons; /* total number of command buttons + in all the alerts being shown in + this dialog. */ + + int c_alert; /* current selected alert. */ + + /* various metrics */ + /* calculated during WM_CREATE */ + SIZE s_button; /* minimum dimensions for command button */ + SIZE s_margin; + RECT r_text; /* only .left and .right are used. rest are 0 */ + RECT r_title; /* only .left, .right and .bottom are used. .top=0 */ + SIZE s_icon; + SIZE s_pad; + + int cx_wnd; + int cy_max_wnd; + + /* derived from the alert sizes */ + SIZE s_alerts; + + QDCL(alerter_alert_data); /* queue of alerts that are being + shown in this window. */ + + LDCL(struct tag_alerter_wnd_data); /* for adding to + khui_alert_windows list. */ + + int n_alerts; + +} alerter_wnd_data; + +#define NTF_PARAM DWLP_USER + +/* dialog sizes in base dialog units */ + +#define NTF_MARGIN 5 +#define NTF_WIDTH 200 +#define NTF_MAXHEIGHT 150 + +#define NTF_TITLE_X NTF_MARGIN +#define NTF_TITLE_WIDTH (NTF_WIDTH - NTF_MARGIN*2) +#define NTF_TITLE_HEIGHT 10 + +#define NTF_TEXT_PAD 2 + +#define NTF_BUTTON_HEIGHT 14 + +#define NTF_TIMEOUT 20000 + +#define ALERT_WINDOW_EX_SYLES (WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP) +#define ALERT_WINDOW_STYLES (WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN | DS_NOIDLEMSG) + +/* Control ids */ +#define IDC_NTF_ALERTBIN 998 +#define IDC_NTF_CLOSE 999 + +#define IDC_NTF_CMDBUTTONS 1001 +#define IDC_FROM_IDX(alert, bn) ((alert) * (KHUI_MAX_ALERT_COMMANDS + 1) + (bn) + 1 + IDC_NTF_CMDBUTTONS) +#define ALERT_FROM_IDC(idc) (((idc) - IDC_NTF_CMDBUTTONS) / (KHUI_MAX_ALERT_COMMANDS + 1)) +#define BUTTON_FROM_IDC(idc) (((idc) - IDC_NTF_CMDBUTTONS) % (KHUI_MAX_ALERT_COMMANDS + 1) - 1) + +/* if the only command in an alert is "Close", we assume that the + alert has no commands. */ +#define ALERT_HAS_CMDS(a) ((a)->n_alert_commands > 1 || ((a)->n_alert_commands == 1 && (a)->alert_commands[0] != KHUI_PACTION_CLOSE)) + +#define SCROLL_LINE_SIZE(d) ((d)->cy_max_wnd / 12) + +static void +add_alert_to_wnd_data(alerter_wnd_data * d, + khui_alert * a) { + alerter_alert_data * aiter; + khm_boolean exists = 0; + + khui_alert_lock(a); + + /* check if the alert is already there */ + aiter = QTOP(d); + while(aiter && !exists) { + if (aiter->alert) { + khui_alert_lock(aiter->alert); + + if (alert_is_equal(aiter->alert, a)) { + exists = TRUE; + } + + khui_alert_unlock(aiter->alert); + } + + aiter = QNEXT(aiter); + } + + a->flags |= KHUI_ALERT_FLAG_DISPLAY_WINDOW; + + if (!exists) { + a->displayed = TRUE; + } + + khui_alert_unlock(a); + + if (!exists) { + alerter_alert_data * adata; + + adata = PMALLOC(sizeof(*adata)); + ZeroMemory(adata, sizeof(*adata)); + + adata->alert = a; + khui_alert_hold(a); + + QPUT(d, adata); + d->n_alerts ++; + } +} + +static alerter_wnd_data * +create_alerter_wnd_data(HWND hwnd, alert_list * l) { + alerter_wnd_data * d; + int i; + LONG dlgb; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->hwnd = hwnd; + + GetWindowText(hwnd, d->caption, ARRAYLENGTH(d->caption)); + + for (i=0; i < l->n_alerts; i++) { + add_alert_to_wnd_data(d, l->alerts[i]); + } + + d->n_alerts = l->n_alerts; + + LPUSH(&khui_alert_windows, d); + + /* Compute a few metrics first */ + + dlgb = GetDialogBaseUnits(); + +#define DLG2SCNX(x) MulDiv((x), LOWORD(dlgb), 4) +#define DLG2SCNY(y) MulDiv((y), HIWORD(dlgb), 8) + + d->cx_wnd = DLG2SCNX(NTF_WIDTH); + d->cy_max_wnd = DLG2SCNY(NTF_MAXHEIGHT); + + d->s_margin.cx = DLG2SCNX(NTF_MARGIN); + d->s_margin.cy = DLG2SCNY(NTF_MARGIN); + + d->r_title.left = DLG2SCNX(NTF_TITLE_X); + d->r_title.right = DLG2SCNX(NTF_TITLE_X + NTF_TITLE_WIDTH); + d->r_title.top = 0; + d->r_title.bottom = DLG2SCNY(NTF_TITLE_HEIGHT); + + d->s_pad.cx = DLG2SCNX(NTF_TEXT_PAD); + d->s_pad.cy = DLG2SCNY(NTF_TEXT_PAD); + + d->s_icon.cx = GetSystemMetrics(SM_CXICON); + d->s_icon.cy = GetSystemMetrics(SM_CYICON); + + d->r_text.left = d->s_margin.cx * 2 + d->s_icon.cx; + d->r_text.right = d->cx_wnd - d->s_margin.cx; + d->r_text.top = 0; + d->r_text.bottom = 0; + + d->s_button.cx = ((d->r_text.right - d->r_text.left) - (KHUI_MAX_ALERT_COMMANDS - 1) * d->s_margin.cx) / KHUI_MAX_ALERT_COMMANDS; + d->s_button.cy = DLG2SCNY(NTF_BUTTON_HEIGHT); + +#undef DLG2SCNX +#undef DLG2SCNY + + d->c_alert = -1; + + return d; +} + +static void +layout_alert(HDC hdc, alerter_wnd_data * d, + alerter_alert_data * adata) { + RECT r; + size_t len; + int y; + int icon_y; + +#ifdef DEBUG + assert(adata->alert); +#endif + + khui_alert_lock(adata->alert); + + y = 0; + + /* Title */ + + y += d->s_margin.cy; + + /* If there is a title and it differs from the title of the + alerter window, then we have to show the alert title + separately. */ + if (adata->alert->title && + wcscmp(adata->alert->title, d->caption)) { + + CopyRect(&adata->r_title, &d->r_title); + OffsetRect(&adata->r_title, 0, y); + + y = adata->r_title.bottom + d->s_margin.cy; + + } else { + + SetRectEmpty(&adata->r_title); + + } + + /* Icon */ + + SetRect(&adata->r_icon, d->s_margin.cx, y, + d->s_margin.cx + d->s_icon.cx, + y + d->s_icon.cy); + + icon_y = adata->r_icon.bottom + d->s_margin.cy; /* the bottom of the icon */ + + /* Message */ + + if (adata->alert->message && + SUCCEEDED(StringCchLength(adata->alert->message, + KHUI_MAXCCH_MESSAGE, + &len))) { + + CopyRect(&r, &d->r_text); + + DrawTextEx(hdc, adata->alert->message, (int) len, + &r, + DRAWTEXTOPTIONS, + NULL); + + OffsetRect(&r, 0, y); + CopyRect(&adata->r_message, &r); + + y = r.bottom + d->s_margin.cy; + + } else { + + SetRectEmpty(&adata->r_message); + + } + + /* Suggestion */ + + if (adata->alert->suggestion && + SUCCEEDED(StringCchLength(adata->alert->suggestion, + KHUI_MAXCCH_SUGGESTION, + &len))) { + int pad = d->s_pad.cx + GetSystemMetrics(SM_CXSMICON); + + CopyRect(&r, &d->r_text); + r.left += pad; + + DrawTextEx(hdc, adata->alert->suggestion, (int) len, + &r, + DRAWTEXTOPTIONS, + NULL); + + r.left -= pad; + + InflateRect(&r, d->s_pad.cx, d->s_pad.cy); + OffsetRect(&r, 0, -r.top + y); + CopyRect(&adata->r_suggestion, &r); + + y = r.bottom + d->s_margin.cy; + + } else { + + SetRectEmpty(&adata->r_suggestion); + + } + + y = max(y, icon_y); + + /* Buttons */ + + if (ALERT_HAS_CMDS(adata->alert)) { + khm_int32 i; + int x, width; + wchar_t caption[KHUI_MAXCCH_SHORT_DESC]; + size_t len; + SIZE s; + int skip_close; + + adata->has_commands = TRUE; + + if (d->n_alerts > 1) + skip_close = TRUE; + else + skip_close = FALSE; + + x = d->r_text.left; + +#ifdef DEBUG + assert(adata->alert->n_alert_commands <= KHUI_MAX_ALERT_COMMANDS); +#endif + + for (i=0; i < adata->alert->n_alert_commands; i++) { + + if (adata->alert->alert_commands[i] == KHUI_PACTION_CLOSE && skip_close) { + SetRectEmpty(&adata->r_buttons[i]); + continue; + } + + caption[0] = L'\0'; + len = 0; + khm_get_action_caption(adata->alert->alert_commands[i], + caption, sizeof(caption)); + StringCchLength(caption, ARRAYLENGTH(caption), &len); + + if (!GetTextExtentPoint32(hdc, caption, (int) len, &s)) { + width = d->s_button.cx; + } else { + width = s.cx + d->s_margin.cx * 2; + } + + if (width < d->s_button.cx) + width = d->s_button.cx; + else if (width > (d->r_text.right - d->r_text.left)) + width = d->r_text.right - d->r_text.left; + + if (x + width > d->r_text.right) { + /* new line */ + x = d->r_text.left; + y += d->s_button.cy + d->s_pad.cy; + } + + SetRect(&adata->r_buttons[i], x, y, x + width, y + d->s_button.cy); + + x += width + d->s_margin.cx; + } + + y += d->s_button.cy + d->s_margin.cy; + } + + khui_alert_unlock(adata->alert); + + /* Now set the rect for the whole alert */ + SetRect(&adata->r_alert, 0, 0, d->cx_wnd, y); + +} + +static void +pick_title_for_alerter_window(alerter_wnd_data * d) { + alerter_alert_data * adata; + wchar_t caption[KHUI_MAXCCH_TITLE]; + khm_boolean common_caption = TRUE; + khui_alert_type ctype = KHUI_ALERTTYPE_NONE; + khm_boolean common_type = TRUE; + + /* - If all the alerts have the same title, then we use the common + title. + + - If all the alerts are of the same type, then we pick a title + that is suitable for the type. + + - All else fails, we use a default caption for the window. + */ + + caption[0] = L'\0'; + adata = QTOP(d); + while (adata && (common_caption || common_type)) { + + if (adata->alert) { + khui_alert_lock(adata->alert); + + if (common_caption) { + if (caption[0] == L'\0') { + if (adata->alert->title) + StringCbCopy(caption, sizeof(caption), adata->alert->title); + } else if (adata->alert->title && + wcscmp(caption, adata->alert->title)) { + common_caption = FALSE; + } + } + + if (common_type) { + if (ctype == KHUI_ALERTTYPE_NONE) + ctype = adata->alert->alert_type; + else if (ctype != adata->alert->alert_type) + common_type = FALSE; + } + + khui_alert_unlock(adata->alert); + } + + adata = QNEXT(adata); + } + + /* just in case someone changes d->caption to a pointer from an + array */ +#ifdef DEBUG + assert(sizeof(d->caption) > sizeof(wchar_t *)); +#endif + + if (common_caption && caption[0] != L'\0') { + StringCbCopy(d->caption, sizeof(d->caption), caption); + } else if (common_type && ctype != KHUI_ALERTTYPE_NONE) { + switch(ctype) { + case KHUI_ALERTTYPE_PLUGIN: + LoadString(khm_hInstance, IDS_ALERTTYPE_PLUGIN, + d->caption, ARRAYLENGTH(d->caption)); + break; + + case KHUI_ALERTTYPE_EXPIRE: + LoadString(khm_hInstance, IDS_ALERTTYPE_EXPIRE, + d->caption, ARRAYLENGTH(d->caption)); + break; + + case KHUI_ALERTTYPE_RENEWFAIL: + LoadString(khm_hInstance, IDS_ALERTTYPE_RENEWFAIL, + d->caption, ARRAYLENGTH(d->caption)); + break; + + case KHUI_ALERTTYPE_ACQUIREFAIL: + LoadString(khm_hInstance, IDS_ALERTTYPE_ACQUIREFAIL, + d->caption, ARRAYLENGTH(d->caption)); + break; + + case KHUI_ALERTTYPE_CHPW: + LoadString(khm_hInstance, IDS_ALERTTYPE_CHPW, + d->caption, ARRAYLENGTH(d->caption)); + break; + + default: + LoadString(khm_hInstance, IDS_ALERT_DEFAULT, + d->caption, ARRAYLENGTH(d->caption)); + } + } else { + LoadString(khm_hInstance, IDS_ALERT_DEFAULT, + d->caption, ARRAYLENGTH(d->caption)); + } + + SetWindowText(d->hwnd, d->caption); +} + +static void +estimate_alerter_wnd_sizes(alerter_wnd_data * d) { + HDC hdc; + HFONT hf_old; + int height = 0; + + alerter_alert_data * adata; + + pick_title_for_alerter_window(d); + + hdc = GetDC(d->hwnd); +#ifdef DEBUG + assert(hdc); +#endif + + if (d->hfont == NULL) + d->hfont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); + +#ifdef DEBUG + assert(d->hfont); +#endif + + hf_old = SelectFont(hdc, d->hfont); + + adata = QTOP(d); + while(adata) { + layout_alert(hdc, d, adata); + + height += adata->r_alert.bottom; + + adata = QNEXT(adata); + } + + SelectFont(hdc, hf_old); + ReleaseDC(d->hwnd, hdc); + + d->s_alerts.cx = d->cx_wnd; + d->s_alerts.cy = height; +} + +static void +layout_command_buttons(alerter_wnd_data * d) { + + alerter_alert_data * adata; + HDWP hdefer; + int y; + + hdefer = BeginDeferWindowPos(d->n_cmd_buttons); + + y = 0; + adata = QTOP(d); + while (adata) { + RECT r; + int i; + + if (!adata->has_commands) + goto done; + + for (i=0; i < adata->n_cmd_buttons; i++) { + if (IsRectEmpty(&adata->r_buttons[i])) { + /* the button is no longer needed */ + if (adata->hwnd_buttons[i] != NULL) { + DestroyWindow(adata->hwnd_buttons[i]); + adata->hwnd_buttons[i] = NULL; + } + + continue; + } + + if (adata->hwnd_buttons[i] == NULL) { + continue; + } + + CopyRect(&r, &adata->r_buttons[i]); + OffsetRect(&r, 0, y - d->scroll_top); + + DeferWindowPos(hdefer, + adata->hwnd_buttons[i], NULL, + r.left, r.top, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | + SWP_NOSIZE); + } + + done: + y += adata->r_alert.bottom; + adata = QNEXT(adata); + } + + EndDeferWindowPos(hdefer); +} + +static void +setup_alerter_window_controls(alerter_wnd_data * d) { + + RECT r_alerts; + RECT r_window; + RECT r_client; + RECT r_parent; + HWND hw_parent; + HWND hw_focus = NULL; + BOOL close_button = FALSE; + BOOL scrollbar = FALSE; + BOOL redraw_scollbar = FALSE; + + /* estimate_alerter_wnd_sizes() must be called before calling + this. */ +#ifdef DEBUG + assert(d->s_alerts.cy > 0); +#endif + + r_alerts.left = 0; + r_alerts.top = 0; + r_alerts.right = d->cx_wnd; + + if (d->s_alerts.cy > d->cy_max_wnd) { + + BOOL redraw = FALSE; + + r_alerts.right += GetSystemMetrics(SM_CXVSCROLL); + r_alerts.bottom = d->cy_max_wnd; + + CopyRect(&r_client, &r_alerts); + r_client.bottom += d->s_margin.cy + d->s_button.cy + d->s_pad.cy; + close_button = TRUE; + + if (d->scroll_top > d->s_alerts.cy - d->cy_max_wnd) + d->scroll_top = d->s_alerts.cy - d->cy_max_wnd; + + scrollbar = TRUE; + } else { + r_alerts.bottom = d->s_alerts.cy; + + CopyRect(&r_client, &r_alerts); + + if (d->n_alerts == 1) { + + if (!QTOP(d)->has_commands) { + r_client.bottom += d->s_margin.cy * 2 + d->s_button.cy; + close_button = TRUE; + } + + } else { + + r_client.bottom += d->s_margin.cy * 2 + d->s_button.cy; + close_button = TRUE; + } + + d->scroll_top = 0; + } + + if (d->hw_bin == NULL) { + d->hw_bin = CreateWindowEx(WS_EX_CONTROLPARENT, + MAKEINTATOM(atom_alert_bin), + L"Alert Container", + WS_CHILD | WS_CLIPCHILDREN | + WS_VISIBLE | + ((scrollbar)? WS_VSCROLL : 0), + r_alerts.left, r_alerts.top, + r_alerts.right - r_alerts.left, + r_alerts.bottom - r_alerts.top, + d->hwnd, + (HMENU) IDC_NTF_ALERTBIN, + khm_hInstance, + (LPVOID) d); + } else { + redraw_scollbar = TRUE; + SetWindowLongPtr(d->hw_bin, GWL_STYLE, + WS_CHILD | WS_CLIPCHILDREN | + WS_VISIBLE | + ((scrollbar)? WS_VSCROLL : 0)); + SetWindowPos(d->hw_bin, NULL, + r_alerts.left, r_alerts.top, + r_alerts.right - r_alerts.left, + r_alerts.bottom - r_alerts.top, + SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE); + } + + if (scrollbar) { + SCROLLINFO si; + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + si.nMin = 0; + si.nMax = d->s_alerts.cy; + si.nPage = d->cy_max_wnd; + si.nPos = d->scroll_top; + + SetScrollInfo(d->hw_bin, SB_VERT, &si, redraw_scollbar); + } + + /* create the action buttons */ + { + alerter_alert_data * adata; + int y; + int idx; + HWND last_window = HWND_TOP; + int n_buttons = 0; + + idx = 0; + y = - d->scroll_top; + adata = QTOP(d); + while(adata) { + if (adata->has_commands) { + int i; + wchar_t caption[KHUI_MAXCCH_SHORT_DESC]; + RECT r; + + if (adata->hwnd_marker) { + DestroyWindow(adata->hwnd_marker); + adata->hwnd_marker = NULL; + } + + khui_alert_lock(adata->alert); + + adata->n_cmd_buttons = adata->alert->n_alert_commands; + + for (i=0; i < adata->alert->n_alert_commands; i++) { + + n_buttons ++; + + if (IsRectEmpty(&adata->r_buttons[i])) { + /* this button is not necessary */ + if (adata->hwnd_buttons[i]) { + DestroyWindow(adata->hwnd_buttons[i]); + adata->hwnd_buttons[i] = NULL; + } + + continue; + } + + if (adata->hwnd_buttons[i] != NULL) { + /* already there */ + CopyRect(&r, &adata->r_buttons[i]); + OffsetRect(&r, 0, y); + + SetWindowPos(adata->hwnd_buttons[i], last_window, + r.left, r.top, + r.right - r.left, + r.bottom - r.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_SHOWWINDOW); + + last_window = adata->hwnd_buttons[i]; + + if (hw_focus == NULL) + hw_focus = adata->hwnd_buttons[i]; + + continue; + } + + khm_get_action_caption(adata->alert->alert_commands[i], + caption, sizeof(caption)); + + CopyRect(&r, &adata->r_buttons[i]); + OffsetRect(&r, 0, y); + + adata->hwnd_buttons[i] = + CreateWindowEx(0, + L"BUTTON", + caption, + WS_CHILD | WS_TABSTOP | BS_NOTIFY, + r.left, r.top, + r.right - r.left, + r.bottom - r.top, + d->hw_bin, + (HMENU) (INT_PTR) IDC_FROM_IDX(idx, i), + khm_hInstance, + NULL); +#ifdef DEBUG + assert(adata->hwnd_buttons[i]); +#endif + + if (d->hfont) { + SendMessage(adata->hwnd_buttons[i], WM_SETFONT, + (WPARAM) d->hfont, FALSE); + } + + SetWindowPos(adata->hwnd_buttons[i], last_window, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + + last_window = adata->hwnd_buttons[i]; + + if (hw_focus == NULL) + hw_focus = adata->hwnd_buttons[i]; + } + + khui_alert_unlock(adata->alert); + } else { + int i; + + /* Destroy any buttons that belong to the alert. We + might have some left over, if there were command + belonging to the alert that were ignored.*/ + + for (i=0; i < adata->n_cmd_buttons; i++) { + if (adata->hwnd_buttons[i]) { + DestroyWindow(adata->hwnd_buttons[i]); + adata->hwnd_buttons[i] = NULL; + } + } + + adata->n_cmd_buttons = 0; + + if (adata->hwnd_marker == NULL) { + adata->hwnd_marker = + CreateWindowEx(0, + L"BUTTON", + L"Marker", + WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_NOTIFY, + -10, 0, + 5, 5, + d->hw_bin, + (HMENU) (INT_PTR) IDC_FROM_IDX(idx, -1), + khm_hInstance, + NULL); +#ifdef DEBUG + assert(adata->hwnd_marker); +#endif + } + + SetWindowPos(adata->hwnd_marker, last_window, + 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | + SWP_NOMOVE | SWP_NOSIZE); + + last_window = adata->hwnd_marker; + + if (scrollbar) { + EnableWindow(adata->hwnd_marker, TRUE); + if (hw_focus == NULL) + hw_focus = adata->hwnd_marker; + } else { + EnableWindow(adata->hwnd_marker, FALSE); + } + } + + y += adata->r_alert.bottom; + adata = QNEXT(adata); + idx++; + } + + d->n_cmd_buttons = n_buttons; + } + + if (close_button) { + if (d->hw_close == NULL) { + wchar_t caption[256]; + + khm_get_action_caption(KHUI_PACTION_CLOSE, caption, sizeof(caption)); + + d->hw_close = CreateWindowEx(0, + L"BUTTON", + caption, + WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP | BS_NOTIFY, + 0,0,100,100, + d->hwnd, + (HMENU) IDC_NTF_CLOSE, + khm_hInstance, + NULL); + +#ifdef DEBUG + assert(d->hw_close); + assert(d->hfont); +#endif + if (d->hfont) + SendMessage(d->hw_close, WM_SETFONT, (WPARAM) d->hfont, FALSE); + } + + { + int x,y,width,height; + + x = d->r_text.left; + y = r_client.bottom - (d->s_margin.cy + d->s_button.cy); + width = d->s_button.cx; + height = d->s_button.cy; + + SetWindowPos(d->hw_close, NULL, + x, y, width, height, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | + SWP_SHOWWINDOW); + } + + if (hw_focus == NULL || d->n_cmd_buttons == 0) + hw_focus = d->hw_close; + + } else { + if (d->hw_close != NULL) { + DestroyWindow(d->hw_close); + d->hw_close = NULL; + } + } + + CopyRect(&r_window, &r_client); + AdjustWindowRectEx(&r_window, ALERT_WINDOW_STYLES, + FALSE, ALERT_WINDOW_EX_SYLES); + OffsetRect(&r_window, -r_window.left, -r_window.top); + + /* center the window above the parent window. */ + + hw_parent = GetWindow(d->hwnd, GW_OWNER); + GetWindowRect(hw_parent, &r_parent); + + { + int x,y; + + x = (r_parent.left + r_parent.right - (r_window.right - r_window.left)) / 2; + y = (r_parent.top + r_parent.bottom - (r_window.bottom - r_window.top)) / 2; + + SetWindowPos(d->hwnd, + HWND_TOP, + x, y, + r_window.right - r_window.left, + r_window.bottom - r_window.top, + SWP_SHOWWINDOW | SWP_NOOWNERZORDER); + } + + if (hw_focus != NULL) + PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw_focus, MAKELPARAM(TRUE, 0)); +} + +static void +scroll_to_position(alerter_wnd_data * d, int new_pos, khm_boolean redraw_scrollbar) { + int delta; + SCROLLINFO si; + HWND hwnd = d->hw_bin; + + if (new_pos < 0) + new_pos = 0; + else if (new_pos > d->s_alerts.cy - d->cy_max_wnd) + new_pos = d->s_alerts.cy - d->cy_max_wnd; + + if (new_pos == d->scroll_top) + return; + + delta = d->scroll_top - new_pos; + + d->scroll_top -= delta; + + ScrollWindowEx(hwnd, 0, delta, + NULL, NULL, NULL, NULL, + SW_INVALIDATE | SW_ERASE); + + layout_command_buttons(d); + + ZeroMemory(&si, sizeof(si)); + + si.fMask = SIF_POS; + si.nPos = d->scroll_top; + + SetScrollInfo(hwnd, SB_VERT, &si, redraw_scrollbar); +} + +static void +select_alert(alerter_wnd_data * d, int alert) { + + int y; + RECT old_sel, new_sel; + alerter_alert_data * adata; + int idx; + + if (d->n_alerts == 1 || + alert < 0 || + alert > d->n_alerts || + d->c_alert == alert) + return; + + SetRectEmpty(&old_sel); + SetRectEmpty(&new_sel); + idx = 0; y = -d->scroll_top; + adata = QTOP(d); + while(adata && (idx <= d->c_alert || idx <= alert)) { + + if (idx == d->c_alert) { + CopyRect(&old_sel, &adata->r_alert); + OffsetRect(&old_sel, 0, y); + } + + if (idx == alert) { + CopyRect(&new_sel, &adata->r_alert); + OffsetRect(&new_sel, 0, y); + } + + y += adata->r_alert.bottom; + idx ++; + adata = QNEXT(adata); + } + + d->c_alert = alert; + if (!IsRectEmpty(&old_sel)) + InvalidateRect(d->hw_bin, &old_sel, TRUE); + if (!IsRectEmpty(&new_sel)) + InvalidateRect(d->hw_bin, &new_sel, TRUE); +} + +static void +ensure_command_is_visible(alerter_wnd_data * d, int id) { + int alert_idx; + int y = 0; + alerter_alert_data * adata; + int new_pos = 0; + + alert_idx = ALERT_FROM_IDC(id); + +#ifdef DEBUG + assert(alert_idx >= 0 && alert_idx < d->n_alerts); +#endif + if (alert_idx >= d->n_alerts || alert_idx < 0) + return; + + adata = QTOP(d); + while(adata && alert_idx > 0) { + y += adata->r_alert.bottom; + alert_idx--; + adata = QNEXT(adata); + } + +#ifdef DEBUG + assert(alert_idx == 0); + assert(adata); + assert(adata->alert); +#endif + if (adata == NULL || alert_idx != 0) + return; + + new_pos = d->scroll_top; + if (y < d->scroll_top) { + new_pos = y; + } else if (y + adata->r_alert.bottom > d->scroll_top + d->cy_max_wnd) { + new_pos = y + adata->r_alert.bottom - d->cy_max_wnd; + } + + if (new_pos != d->scroll_top) + scroll_to_position(d, new_pos, TRUE); + + select_alert(d, ALERT_FROM_IDC(id)); +} + +static void +handle_mouse_select(alerter_wnd_data * d, int mouse_x, int mouse_y) { + int y; + alerter_alert_data * adata; + + y = -d->scroll_top; + adata = QTOP(d); + while(adata) { + if (y <= mouse_y && (y + adata->r_alert.bottom) > mouse_y) { + HWND hw = NULL; + + if (adata->n_cmd_buttons > 0) + hw = adata->hwnd_buttons[0]; + else + hw = adata->hwnd_marker; + + if (hw && !IsWindowEnabled(hw)) + hw = GetNextDlgTabItem(d->hwnd, hw, FALSE); + + if (hw) + PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw, MAKELPARAM(TRUE, 0)); + + return; + } + + y += adata->r_alert.bottom; + adata = QNEXT(adata); + } +} + +static void +process_command_button(alerter_wnd_data * d, int id) { + int alert_idx; + int cmd_idx; + khm_int32 flags = 0; + khm_int32 cmd = 0; + alerter_alert_data * adata; + int i; + + alert_idx = ALERT_FROM_IDC(id); + cmd_idx = BUTTON_FROM_IDC(id); + +#ifdef DEBUG + assert(alert_idx >= 0 && alert_idx < d->n_alerts); +#endif + if (alert_idx >= d->n_alerts || alert_idx < 0) + return; + + if (cmd_idx < 0) { + /* the user selected a marker button. Nothing to do. */ + return; + } + + adata = QTOP(d); + while(adata && alert_idx > 0) { + alert_idx--; + adata = QNEXT(adata); + } + +#ifdef DEBUG + assert(alert_idx == 0); + assert(adata); + assert(adata->alert); +#endif + if (adata == NULL || alert_idx != 0) + return; + + khui_alert_lock(adata->alert); +#ifdef DEBUG + assert(cmd_idx >= 0 && cmd_idx < adata->alert->n_alert_commands); +#endif + + if (cmd_idx >= 0 && cmd_idx < adata->alert->n_alert_commands) { + cmd = adata->alert->alert_commands[cmd_idx]; + } + + flags = adata->alert->flags; + + adata->alert->response = cmd; + + khui_alert_unlock(adata->alert); + + /* if we were supposed to dispatch the command, do so */ + if (cmd != 0 && + cmd != KHUI_PACTION_CLOSE && + (flags & KHUI_ALERT_FLAG_DISPATCH_CMD)) { + PostMessage(khm_hwnd_main, WM_COMMAND, + MAKEWPARAM(cmd, 0), 0); + } + + /* if this was the only alert in the alert group and its close + button was clicked, we close the alert window. Otherwise, the + alert window creates its own close button that closes the + window. */ + if (d->n_alerts == 1) { + PostMessage(d->hwnd, WM_CLOSE, 0, 0); + } + + /* While we are at it, we should disable the buttons for this + alert since we have already dispatched the command for it. */ + if (cmd != 0) { + HWND hw_focus = GetFocus(); + khm_boolean focus_trapped = FALSE; + + for (i=0; i < adata->n_cmd_buttons; i++) { + if (adata->hwnd_buttons[i]) { + if (hw_focus == adata->hwnd_buttons[i]) + focus_trapped = TRUE; + + EnableWindow(adata->hwnd_buttons[i], FALSE); + } + } + + if (focus_trapped) { + hw_focus = GetNextDlgTabItem(d->hwnd, hw_focus, FALSE); + if (hw_focus) + PostMessage(d->hwnd, WM_NEXTDLGCTL, (WPARAM) hw_focus, MAKELPARAM(TRUE,0)); + } + } +} + +static void +destroy_alerter_wnd_data(alerter_wnd_data * d) { + alerter_alert_data * adata; + + LDELETE(&khui_alert_windows, d); + + QGET(d, &adata); + while(adata) { + + if (adata->alert) { + + khui_alert_lock(adata->alert); + + adata->alert->displayed = FALSE; + + khui_alert_unlock(adata->alert); + + khui_alert_release(adata->alert); + adata->alert = NULL; + } + + PFREE(adata); + + QGET(d, &adata); + } + + PFREE(d); +} + +/* both ref and to_add must be locked and held */ +static khm_boolean +alert_can_consolidate(khui_alert * ref, + khui_alert * to_add, + alert_list * alist) { + + /* first check if we can add anything */ + if (alist->n_alerts == ARRAYLENGTH(alist->alerts)) + return FALSE; + +#ifdef DEBUG + assert(to_add != NULL); +#endif + + if (ref == NULL) { + /* we are testing whether to_add should be added to the alist + on its own. */ + if ((to_add->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) && + !(to_add->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW)) { + /* already displayed */ + return FALSE; + } + + if ((to_add->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON | + KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON) { + /* needs to be shown in a balloon */ + return FALSE; + } + + return TRUE; + } + + /* if the ref or to_add are marked for modal, then we can't + consolidate them */ + if ((ref->flags & KHUI_ALERT_FLAG_MODAL) || + (to_add->flags & KHUI_ALERT_FLAG_MODAL)) + return FALSE; + + /* also, if either of them have requested to be exclusively shown + in a balloon, then we can't consolidate them. */ + if (((ref->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON | + KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON) + + || + + ((to_add->flags & (KHUI_ALERT_FLAG_REQUEST_BALLOON | + KHUI_ALERT_FLAG_REQUEST_WINDOW)) == KHUI_ALERT_FLAG_REQUEST_BALLOON)) + return FALSE; + + /* for now, all we check if whether they are of the same type. */ + if (ref->alert_type != KHUI_ALERTTYPE_NONE && + ref->alert_type == to_add->alert_type) + return TRUE; + else + return FALSE; +} + +/* both a1 and a2 must be locked */ +static khm_boolean +alert_is_equal(khui_alert * a1, khui_alert * a2) { + khm_int32 i; + + if ((a1->severity != a2->severity) || + (a1->n_alert_commands != a2->n_alert_commands) || + (a1->title && (!a2->title || wcscmp(a1->title, a2->title))) || + (!a1->title && a2->title) || + (a1->message && (!a2->message || wcscmp(a1->message, a2->message))) || + (!a1->message && a2->message) || + (a1->suggestion && (!a2->suggestion || wcscmp(a1->suggestion, a2->suggestion))) || + (!a1->suggestion && a2->suggestion)) { + + return FALSE; + + } + + for (i=0; i < a1->n_alert_commands; i++) { + if (a1->alert_commands[i] != a2->alert_commands[i]) + return FALSE; + } + + return TRUE; +} + +/* the return value is the number of alerts added to alist */ +static khm_int32 +alert_consolidate(alert_list * alist, + khui_alert * alert, + khm_boolean add_from_queue) { + + khui_alert * listtop; + int queue_size = 0; + int i; + khm_int32 n_added = 0; + +#ifdef DEBUG + assert(alist); +#endif + + if (alist->n_alerts == ARRAYLENGTH(alist->alerts)) { + /* can't add anything */ + + return 0; + } + + /* if the list is empty, we just add one alert */ + if (alist->n_alerts == 0) { + + if (alert) { + khui_alert_lock(alert); + if (alert_can_consolidate(NULL, alert, alist)) { + alert_list_add_alert(alist, alert); + n_added ++; + alert = NULL; + } + khui_alert_unlock(alert); + } + + if (n_added == 0 && add_from_queue) { + khui_alert * q; + int i; + + queue_size = alert_queue_get_size(); + for (i=0; i < queue_size && n_added == 0; i++) { + q = alert_queue_get_alert_by_pos(i); + if (q) { + khui_alert_lock(q); + if (alert_can_consolidate(NULL, q, alist)) { + alert_list_add_alert(alist, q); + n_added++; + alert_queue_delete_alert(q); + } + khui_alert_unlock(q); + khui_alert_release(q); + } + } + } + + if (n_added == 0) { + /* nothing to add */ + return 0; + } + } + + /* at this point, the alert list is not empty */ +#ifdef DEBUG + assert(alist->n_alerts != 0); + assert(alist->alerts[0]); +#endif + + listtop = alist->alerts[0]; + khui_alert_hold(listtop); + khui_alert_lock(listtop); + + queue_size = alert_queue_get_size(); + + if (alert) { + khui_alert_lock(alert); + if (alert_can_consolidate(listtop, alert, alist)) { + alert_list_add_alert(alist, alert); + n_added ++; + } + khui_alert_unlock(alert); + } + + if (add_from_queue) { + for (i=0; i < queue_size; i++) { + khui_alert * a; + + a = alert_queue_get_alert_by_pos(i); + if (a == NULL) + continue; + + khui_alert_lock(a); + if (alert_can_consolidate(listtop, a, alist)) { + alert_queue_delete_alert(a); + alert_list_add_alert(alist, a); + n_added ++; + + queue_size--; + i--; +#ifdef DEBUG + assert(alert_queue_get_size() == queue_size); +#endif + } + khui_alert_unlock(a); + khui_alert_release(a); + } + } + + khui_alert_unlock(listtop); + khui_alert_release(listtop); + + return n_added; +} + +static khm_int32 +alert_check_consolidate_window(alerter_wnd_data * d, khui_alert * a) { + alert_list alist; + alerter_alert_data * adata; + int n_added; + + alert_list_init(&alist); + + adata = QTOP(d); + while(adata) { + +#ifdef DEBUG + assert(adata->alert); +#endif + alert_list_add_alert(&alist, adata->alert); + + adata = QNEXT(adata); + } + + n_added = alert_consolidate(&alist, a, FALSE); + + alert_list_destroy(&alist); + + return n_added; +} + +static khm_int32 +alert_show_minimized(khui_alert * a) { + wchar_t tbuf[64]; /* corresponds to NOTIFYICONDATA::szInfoTitle[] */ + wchar_t mbuf[256]; /* corresponds to NOTIFYICONDATA::szInfo[] */ + +#ifdef DEBUG + assert(a); +#endif + if (a == NULL) + return KHM_ERROR_INVALID_PARAM; + + khui_alert_lock(a); + + if (a->message == NULL) + goto done; + + if (a->title == NULL) { + LoadString(khm_hInstance, IDS_ALERT_DEFAULT, + tbuf, ARRAYLENGTH(tbuf)); + } else { + StringCbCopy(tbuf, sizeof(tbuf), a->title); + } + + if (FAILED(StringCbCopy(mbuf, sizeof(mbuf), a->message)) || + (!(a->flags & KHUI_ALERT_FLAG_DEFACTION) && + (a->n_alert_commands > 0 || + a->suggestion || + (a->flags & KHUI_ALERT_FLAG_VALID_ERROR)))) { + /* if mbuf wasn't big enough, this should have copied a + truncated version of it */ + size_t cch_m, cch_p; + wchar_t postfix[256]; + + cch_p = LoadString(khm_hInstance, IDS_ALERT_MOREINFO, postfix, + ARRAYLENGTH(postfix)); + cch_p++; /* account for NULL */ + + StringCchLength(mbuf, ARRAYLENGTH(mbuf), &cch_m); + cch_m = min(cch_m, ARRAYLENGTH(mbuf) - cch_p); + + StringCchCopy(mbuf + cch_m, ARRAYLENGTH(mbuf) - cch_m, + postfix); + + a->flags |= KHUI_ALERT_FLAG_REQUEST_WINDOW; + } + + a->flags |= KHUI_ALERT_FLAG_DISPLAY_BALLOON; + +#ifdef DEBUG + assert(balloon_alert == NULL); +#endif + + if (balloon_alert) { + khui_alert_lock(balloon_alert); + balloon_alert->displayed = FALSE; + khui_alert_unlock(balloon_alert); + khui_alert_release(balloon_alert); + balloon_alert = NULL; + } + + balloon_alert = a; + khui_alert_hold(a); + + a->displayed = TRUE; + + khm_notify_icon_balloon(a->severity, + tbuf, + mbuf, + NTF_TIMEOUT); + + done: + khui_alert_unlock(a); + + return KHM_ERROR_SUCCESS; +} + +static khm_int32 +alert_show_normal(khui_alert * a) { + wchar_t buf[256]; + wchar_t * title; + alert_list alist; + + khui_alert_lock(a); + + if(a->title == NULL) { + LoadString(khm_hInstance, IDS_ALERT_DEFAULT, + buf, ARRAYLENGTH(buf)); + title = buf; + } else + title = a->title; + + khui_alert_unlock(a); + + alert_list_init(&alist); + alert_list_set_title(&alist, title); + alert_list_add_alert(&alist, a); + + alert_show_list(&alist); + + alert_list_destroy(&alist); + + return KHM_ERROR_SUCCESS; +} + +static khm_int32 +alert_show_list(alert_list * alist) { + HWND hwa; + + /* we don't need to keep track of the window handle + because the window procedure adds it to the dialog + list automatically */ + + hwa = + CreateWindowEx(ALERT_WINDOW_EX_SYLES, + MAKEINTATOM(atom_alerter), + alist->title, + ALERT_WINDOW_STYLES, + 0, 0, 300, 300, // bogus values + khm_hwnd_main, + (HMENU) NULL, + khm_hInstance, + (LPVOID) alist); + + ShowWindow(hwa, SW_SHOW); + + return (hwa != NULL); +} + +static khm_int32 +alert_show(khui_alert * a) { + khm_boolean show_normal = FALSE; + khm_boolean show_mini = FALSE; + + khui_alert_lock(a); + + /* is there an alert already? If so, we just enqueue the message + and let it sit. */ + if (ALERT_DISPLAYED() && + !(a->flags & KHUI_ALERT_FLAG_MODAL)) { + khm_int32 rv; + alerter_wnd_data * wdata; + + khui_alert_unlock(a); + + /* if there are any alerter windows displayed, check if this + alert can be consolidated with any of them. If so, we + should consolidate it. Otherwise, just enqueue it. */ + for(wdata = khui_alert_windows; + wdata; + wdata = LNEXT(wdata)) { + if (alert_check_consolidate_window(wdata, a)) { + + add_alert_to_wnd_data(wdata, a); + estimate_alerter_wnd_sizes(wdata); + setup_alerter_window_controls(wdata); + + return KHM_ERROR_SUCCESS; + + } + } + + rv = alert_enqueue(a); + + if (KHM_SUCCEEDED(rv)) + return KHM_ERROR_HELD; + else + return rv; + } + + if((a->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW) || + ((a->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) && + !(a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW))) { + + /* The alert has already been displayed. */ + + show_normal = FALSE; + show_mini = FALSE; + + } else { + + if(a->err_context != NULL || + a->err_event != NULL) { + a->flags |= KHUI_ALERT_FLAG_VALID_ERROR; + } + + /* depending on the state of the main window, we + need to either show a window or a balloon */ + if ((a->flags & KHUI_ALERT_FLAG_MODAL) || + (khm_is_main_window_active() && + !(a->flags & KHUI_ALERT_FLAG_REQUEST_BALLOON)) || + (a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW)) { + + show_normal = TRUE; + + } else { + + show_mini = TRUE; + + } + } + + khui_alert_unlock(a); + + if (show_normal) + return alert_show_normal(a); + else if (show_mini) + return alert_show_minimized(a); + else + return KHM_ERROR_SUCCESS; +} + +static void +show_queued_alerts(void) { + + if (!ALERT_DISPLAYED()) { + + /* show next consolidated batch */ + alert_list alist; + int n; + + alert_list_init(&alist); + n = alert_consolidate(&alist, NULL, TRUE); + + if (n) { + if (n == 1) { + khui_alert_lock(alist.alerts[0]); + + if (alist.alerts[0]->title) { + alert_list_set_title(&alist, alist.alerts[0]->title); + } else { + wchar_t title[KHUI_MAXCCH_TITLE]; + LoadString(khm_hInstance, IDS_ALERT_DEFAULT, + title, ARRAYLENGTH(title)); + alert_list_set_title(&alist, title); + } + + khui_alert_unlock(alist.alerts[0]); + } else { + wchar_t title[KHUI_MAXCCH_TITLE]; + LoadString(khm_hInstance, IDS_ALERT_DEFAULT, + title, ARRAYLENGTH(title)); + alert_list_set_title(&alist, title); + } + + alert_show_list(&alist); + } + + alert_list_destroy(&alist); + + if (n == 0) { + khui_alert * a; + + /* no alerts were shown above. This maybe because none of + the alerts were consolidatable or they were requested + to be shown in a balloon. In this case, we just take + the first alert from the queue and show it manually. */ + + a = alert_queue_get_alert(); + if (a) { + alert_show(a); + khui_alert_release(a); + } + } + + check_for_queued_alerts(); + } +} + + +static void +check_for_queued_alerts(void) { + if (!is_alert_queue_empty()) { + khui_alert * a; + + a = alert_queue_peek(); + + khui_alert_lock(a); + + if (a->title) { + HICON hi; + int res; + + if (a->severity == KHERR_ERROR) + res = OIC_ERROR; + else if (a->severity == KHERR_WARNING) + res = OIC_WARNING; + else + res = OIC_INFORMATION; + + hi = LoadImage(0, MAKEINTRESOURCE(res), + IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + LR_SHARED); + + khm_statusbar_set_part(KHUI_SBPART_NOTICE, + hi, + a->title); + } else { + khm_statusbar_set_part(KHUI_SBPART_NOTICE, + NULL, NULL); +#ifdef DEBUG + DebugBreak(); +#endif + } + + khui_alert_unlock(a); + khui_alert_release(a); + + } else { + khm_statusbar_set_part(KHUI_SBPART_NOTICE, + NULL, NULL); + } +} + +static khm_int32 +alert_enqueue(khui_alert * a) { + if (is_alert_queue_full()) + return KHM_ERROR_NO_RESOURCES; + + alert_queue_put_alert(a); + check_for_queued_alerts(); + + return KHM_ERROR_SUCCESS; +} + +/* the alerter window is actually a dialog */ +static LRESULT CALLBACK +alerter_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_CREATE: + { + LPCREATESTRUCT lpcs; + alert_list * alist; + alerter_wnd_data * d; + + lpcs = (LPCREATESTRUCT) lParam; + alist = (alert_list *) lpcs->lpCreateParams; + + d = create_alerter_wnd_data(hwnd, alist); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, NTF_PARAM, (LONG_PTR) d); +#pragma warning(pop) + + khm_add_dialog(hwnd); + khm_enter_modal(hwnd); + + estimate_alerter_wnd_sizes(d); + setup_alerter_window_controls(d); + + if (d->hw_close) { + SetFocus(d->hw_close); + } + + return TRUE; + } + break; /* not reached */ + + case WM_DESTROY: + { + alerter_wnd_data * d; + + /* khm_leave_modal() could be here, but instead it is in + the WM_COMMAND handler. This is because the modal loop + has to be exited before DestroyWindow() is issued. */ + //khm_leave_modal(); + khm_del_dialog(hwnd); + + d = (alerter_wnd_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, NTF_PARAM); + + if (d) { + destroy_alerter_wnd_data(d); + SetWindowLongPtr(hwnd, NTF_PARAM, 0); + } + + return TRUE; + } + break; + + case WM_COMMAND: + { + alerter_wnd_data * d; + + d = (alerter_wnd_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, NTF_PARAM); + + if(HIWORD(wParam) == BN_CLICKED) { + if (LOWORD(wParam) == IDC_NTF_CLOSE || + LOWORD(wParam) == KHUI_PACTION_NEXT) { + + khm_leave_modal(); + + DestroyWindow(hwnd); + + return 0; + } + } + } + break; + + case WM_CLOSE: + { + khm_leave_modal(); + + DestroyWindow(hwnd); + + return 0; + } + } + + /* Since this is a custom built dialog, we use DefDlgProc instead + of DefWindowProc. */ + return DefDlgProc(hwnd, uMsg, wParam, lParam); +} + +static LRESULT CALLBACK +alert_bin_wnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + BOOL in_printclient = FALSE; + + switch(uMsg) { + case WM_CREATE: + { + LPCREATESTRUCT lpcs; + alerter_wnd_data * d; + + lpcs = (LPCREATESTRUCT) lParam; + d = (alerter_wnd_data *) lpcs->lpCreateParams; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) d); +#pragma warning(pop) + } + return 0; + + case WM_ERASEBKGND: + /* we erase the background when we are drawing the alerts + anyway. */ + return 0; + + case WM_PRINTCLIENT: + in_printclient = TRUE; + /* fallthrough */ + case WM_PAINT: + { + HDC hdc; + PAINTSTRUCT ps; + RECT r; + HFONT hf_old; + int y; + alerter_wnd_data * d; + alerter_alert_data * adata; + size_t len; + int idx; + + d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#ifdef DEBUG + assert(d); +#endif + if (d == NULL) + break; + + if (in_printclient) { + hdc = (HDC) wParam; + ZeroMemory(&ps, sizeof(ps)); + } else { + hdc = BeginPaint(hwnd, &ps); + } + +#ifdef DEBUG + assert(hdc); + assert(d->hfont); +#endif + +#ifdef ALERT_STATIC_BACKGROUND + if (in_printclient || ps.fErase) { + HBRUSH hb_background; + + hb_background = GetSysColorBrush(COLOR_BTNFACE); + + GetClientRect(hwnd, &r); + FillRect(hdc, &r, hb_background); + } +#endif + + SetBkMode(hdc, TRANSPARENT); + + hf_old = SelectFont(hdc, d->hfont); + + y = -d->scroll_top; + idx = 0; + /* go through the alerts and display them */ + adata = QTOP(d); + while(adata) { + khui_alert * a; + +#ifndef ALERT_STATIC_BACKGROUND +#define MIX_C(v1, v2, p) ((COLOR16)(((int)v1) * p + (((int) v2) * (256 - p)))) +#define ALPHA 50 + if (in_printclient || ps.fErase) { + TRIVERTEX v[2]; + GRADIENT_RECT gr; + COLORREF clr; + COLORREF clr2; + + CopyRect(&r, &adata->r_alert); + OffsetRect(&r, 0, y); + + v[0].x = r.left; + v[0].y = r.top; + v[0].Alpha = 0; + + v[1].x = r.right; + v[1].y = r.bottom; + v[1].Alpha = 0; + + if (idx == d->c_alert) { + clr = GetSysColor(COLOR_HOTLIGHT); + + clr2 = GetSysColor(COLOR_BTNHIGHLIGHT); + v[0].Red = MIX_C(GetRValue(clr), GetRValue(clr2), ALPHA); + v[0].Green = MIX_C(GetGValue(clr), GetGValue(clr2), ALPHA); + v[0].Blue = MIX_C(GetBValue(clr), GetBValue(clr2), ALPHA); + + clr2 = GetSysColor(COLOR_BTNFACE); + v[1].Red = MIX_C(GetRValue(clr), GetRValue(clr2), ALPHA); + v[1].Green = MIX_C(GetGValue(clr), GetGValue(clr2), ALPHA); + v[1].Blue = MIX_C(GetBValue(clr), GetBValue(clr2), ALPHA); + } else { + clr = GetSysColor(COLOR_BTNHIGHLIGHT); + v[0].Red = (COLOR16) ((int)GetRValue(clr)) << 8; + v[0].Green = (COLOR16) ((int)GetGValue(clr)) << 8; + v[0].Blue = (COLOR16) ((int)GetBValue(clr)) << 8; + + clr = GetSysColor(COLOR_BTNFACE); + v[1].Red = (COLOR16) ((int)GetRValue(clr)) << 8; + v[1].Green = (COLOR16) ((int)GetGValue(clr)) << 8; + v[1].Blue = (COLOR16) ((int)GetBValue(clr)) << 8; + } + + gr.UpperLeft = 0; + gr.LowerRight = 1; + GradientFill(hdc, v, 2, &gr, 1, GRADIENT_FILL_RECT_V); + } +#undef ALPHA +#undef MIX_C +#endif + + a = adata->alert; +#ifdef DEBUG + assert(a != NULL); +#endif + khui_alert_lock(a); + + if (!IsRectEmpty(&adata->r_title)) { + + CopyRect(&r, &adata->r_title); + OffsetRect(&r, 0, y); + + StringCchLength(a->title, KHUI_MAXCCH_TITLE, &len); + + DrawEdge(hdc, &r, EDGE_RAISED, BF_RECT | BF_MIDDLE); + + InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy); + + DrawText(hdc, a->title, (int) len, &r, + DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS); + } + + { + HICON hicon; + int iid; + + CopyRect(&r, &adata->r_icon); + OffsetRect(&r, 0, y); + + if(a->severity == KHERR_ERROR) + iid = OIC_HAND; + else if(a->severity == KHERR_WARNING) + iid = OIC_BANG; + else + iid = OIC_NOTE; + + hicon = (HICON) LoadImage(NULL, + MAKEINTRESOURCE(iid), + IMAGE_ICON, + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + LR_SHARED); + + DrawIcon(hdc, r.left, r.top, hicon); + } + + if (a->message) { + + CopyRect(&r, &adata->r_message); + OffsetRect(&r, 0, y); + + StringCchLength(a->message, KHUI_MAXCCH_MESSAGE, &len); + + DrawText(hdc, a->message, (int) len, &r, + DT_WORDBREAK); + } + + if (a->suggestion) { + HICON hicon; + SIZE sz; + + CopyRect(&r, &adata->r_suggestion); + OffsetRect(&r, 0, y); + + DrawEdge(hdc, &r, EDGE_SUNKEN, BF_RECT | BF_MIDDLE); + + InflateRect(&r, -d->s_pad.cx, -d->s_pad.cy); + + sz.cx = GetSystemMetrics(SM_CXSMICON); + sz.cy = GetSystemMetrics(SM_CYSMICON); + + hicon = (HICON) LoadImage(NULL, + MAKEINTRESOURCE(OIC_NOTE), + IMAGE_ICON, + sz.cx, + sz.cy, + LR_SHARED); + + DrawIconEx(hdc, r.left, r.top, hicon, sz.cx, sz.cy, 0, NULL, + DI_NORMAL); + + r.left += d->s_pad.cx + GetSystemMetrics(SM_CXSMICON); + + StringCchLength(a->suggestion, KHUI_MAXCCH_SUGGESTION, &len); + + DrawText(hdc, a->suggestion, (int) len, &r, + DT_WORDBREAK); + } + khui_alert_unlock(a); + + y += adata->r_alert.bottom; + idx++; + + adata = QNEXT(adata); + } + + SelectFont(hdc, hf_old); + + if (!in_printclient) { + EndPaint(hwnd, &ps); + } + } + return 0; + + case WM_VSCROLL: + { + alerter_wnd_data * d; + int new_pos = 0; + SCROLLINFO si; + + d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#ifdef DEBUG + assert(d); +#endif + if (d == NULL) + break; /* we can't handle the message */ + + ZeroMemory(&si, sizeof(si)); + + switch(LOWORD(wParam)) { + case SB_BOTTOM: + new_pos = d->s_alerts.cy - d->cy_max_wnd; + break; + + case SB_LINEDOWN: + new_pos = d->scroll_top + SCROLL_LINE_SIZE(d); + break; + + case SB_LINEUP: + new_pos = d->scroll_top - SCROLL_LINE_SIZE(d); + break; + + case SB_PAGEDOWN: + new_pos = d->scroll_top + d->cy_max_wnd; + break; + + case SB_PAGEUP: + new_pos = d->scroll_top - d->cy_max_wnd; + break; + + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + si.fMask = SIF_TRACKPOS; + GetScrollInfo(hwnd, SB_VERT, &si); + new_pos = si.nTrackPos; + break; + + case SB_TOP: + new_pos = 0; + break; + + case SB_ENDSCROLL: + si.fMask = SIF_POS; + si.nPos = d->scroll_top; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + return 0; + + default: + return 0; + } + + scroll_to_position(d, new_pos, FALSE); + } + return 0; + + case WM_COMMAND: + { + alerter_wnd_data * d; + + d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#ifdef DEBUG + assert(d); +#endif + if (d == NULL) + break; + + if (HIWORD(wParam) == BN_CLICKED) { + process_command_button(d, LOWORD(wParam)); + return 0; + } else if (HIWORD(wParam) == BN_SETFOCUS) { + ensure_command_is_visible(d, LOWORD(wParam)); + return 0; + } + } + break; + + case WM_LBUTTONUP: + { + alerter_wnd_data * d; + int x,y; + + d = (alerter_wnd_data *) (LONG_PTR) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#ifdef DEBUG + assert(d); +#endif + if (d == NULL) + break; + + x = GET_X_LPARAM(lParam); + y = GET_Y_LPARAM(lParam); + + handle_mouse_select(d, x, y); + } + break; + + case WM_SIZE: + { + InvalidateRect(hwnd, NULL, TRUE); + } + break; + + case WM_DESTROY: + { + /* nothing needs to be done here */ + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + } + return 0; + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +ATOM khm_register_alerter_wnd_class(void) +{ + WNDCLASSEX wcx; + + ZeroMemory(&wcx, sizeof(wcx)); + + wcx.cbSize = sizeof(wcx); + wcx.style = + CS_OWNDC | +#if(_WIN32_WINNT >= 0x0501) + ((IS_COMMCTL6())? CS_DROPSHADOW: 0) | +#endif + 0; + wcx.lpfnWndProc = alerter_wnd_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR); + wcx.hInstance = khm_hInstance; + wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP)); + wcx.hCursor = LoadCursor(NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_ALERTER_CLASS; + wcx.hIconSm = NULL; + + atom_alerter = RegisterClassEx(&wcx); + + return atom_alerter; +} + +ATOM khm_register_alert_bin_wnd_class(void) +{ + WNDCLASSEX wcx; + + ZeroMemory(&wcx, sizeof(wcx)); + + wcx.cbSize = sizeof(wcx); + wcx.style = CS_OWNDC; + + wcx.lpfnWndProc = alert_bin_wnd_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = sizeof(LONG_PTR); + wcx.hInstance = khm_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = LoadCursor(NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_ALERTBIN_CLASS; + wcx.hIconSm = NULL; + + atom_alert_bin = RegisterClassEx(&wcx); + + return atom_alert_bin; +} + +/********************************************************************** + Notification Icon +***********************************************************************/ + +#define KHUI_NOTIFY_ICON_ID 0 + +void khm_notify_icon_add(void) { + NOTIFYICONDATA ni; + wchar_t buf[256]; + + ZeroMemory(&ni, sizeof(ni)); + + ni.cbSize = sizeof(ni); + ni.hWnd = hwnd_notifier; + ni.uID = KHUI_NOTIFY_ICON_ID; + ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid_normal)); + ni.uCallbackMessage = KHUI_WM_NOTIFIER; + LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf)); + StringCbCopy(tip_normal, sizeof(tip_normal), buf); + LoadString(khm_hInstance, IDS_NOTIFY_READY, buf, ARRAYLENGTH(buf)); + StringCbCat(tip_normal, sizeof(tip_normal), buf); + + StringCbCopy(ni.szTip, sizeof(ni.szTip), tip_normal); + + Shell_NotifyIcon(NIM_ADD, &ni); + + DestroyIcon(ni.hIcon); + + ni.cbSize = sizeof(ni); + ni.uVersion = NOTIFYICON_VERSION; + Shell_NotifyIcon(NIM_SETVERSION, &ni); +} + +void +khm_notify_icon_balloon(khm_int32 severity, + wchar_t * title, + wchar_t * msg, + khm_int32 timeout) { + NOTIFYICONDATA ni; + int iid; + + if (!msg || !title) + return; + + ZeroMemory(&ni, sizeof(ni)); + ni.cbSize = sizeof(ni); + + if (severity == KHERR_INFO) { + ni.dwInfoFlags = NIIF_INFO; + iid = IDI_NOTIFY_INFO; + } else if (severity == KHERR_WARNING) { + ni.dwInfoFlags = NIIF_WARNING; + iid = IDI_NOTIFY_WARN; + } else if (severity == KHERR_ERROR) { + ni.dwInfoFlags = NIIF_ERROR; + iid = IDI_NOTIFY_ERROR; + } else { + ni.dwInfoFlags = NIIF_NONE; + iid = iid_normal; + } + + ni.hWnd = hwnd_notifier; + ni.uID = KHUI_NOTIFY_ICON_ID; + ni.uFlags = NIF_INFO | NIF_ICON; + ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid)); + + if (FAILED(StringCbCopy(ni.szInfo, sizeof(ni.szInfo), msg))) { + /* too long? */ + StringCchCopyN(ni.szInfo, ARRAYLENGTH(ni.szInfo), + msg, + ARRAYLENGTH(ni.szInfo) - ARRAYLENGTH(ELLIPSIS)); + StringCchCat(ni.szInfo, ARRAYLENGTH(ni.szInfo), + ELLIPSIS); + } + + if (FAILED(StringCbCopy(ni.szInfoTitle, sizeof(ni.szInfoTitle), + title))) { + StringCchCopyN(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle), + title, + ARRAYLENGTH(ni.szInfoTitle) - ARRAYLENGTH(ELLIPSIS)); + StringCchCat(ni.szInfoTitle, ARRAYLENGTH(ni.szInfoTitle), + ELLIPSIS); + } + + ni.uTimeout = timeout; + + Shell_NotifyIcon(NIM_MODIFY, &ni); + + DestroyIcon(ni.hIcon); +} + +void khm_notify_icon_expstate(enum khm_notif_expstate expseverity) { + int new_iid; + + if (expseverity == KHM_NOTIF_OK) + new_iid = IDI_APPICON_OK; + else if (expseverity == KHM_NOTIF_WARN) + new_iid = IDI_APPICON_WARN; + else if (expseverity == KHM_NOTIF_EXP) + new_iid = IDI_APPICON_EXP; + else + new_iid = IDI_NOTIFY_NONE; + + if (iid_normal == new_iid) + return; + + iid_normal = new_iid; + + if (balloon_alert == NULL) + khm_notify_icon_change(KHERR_NONE); +} + +void khm_notify_icon_change(khm_int32 severity) { + NOTIFYICONDATA ni; + wchar_t buf[256]; + int iid; + + if (severity == KHERR_INFO) + iid = IDI_NOTIFY_INFO; + else if (severity == KHERR_WARNING) + iid = IDI_NOTIFY_WARN; + else if (severity == KHERR_ERROR) + iid = IDI_NOTIFY_ERROR; + else + iid = iid_normal; + + ZeroMemory(&ni, sizeof(ni)); + + ni.cbSize = sizeof(ni); + ni.hWnd = hwnd_notifier; + ni.uID = KHUI_NOTIFY_ICON_ID; + ni.uFlags = NIF_ICON | NIF_TIP; + ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid)); + + if (severity == KHERR_NONE) { + StringCbCopy(ni.szTip, sizeof(ni.szTip), tip_normal); + } else { + LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf)); + StringCbCopy(ni.szTip, sizeof(ni.szTip), buf); + LoadString(khm_hInstance, IDS_NOTIFY_ATTENTION, buf, ARRAYLENGTH(buf)); + StringCbCat(ni.szTip, sizeof(ni.szTip), buf); + } + + Shell_NotifyIcon(NIM_MODIFY, &ni); + + DestroyIcon(ni.hIcon); + + notifier_severity = severity; +} + +void khm_notify_icon_tooltip(wchar_t * s) { + wchar_t buf[256]; + + LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf)); + StringCbCat(buf, sizeof(buf), s); + + StringCbCopy(tip_normal, sizeof(tip_normal), buf); + + if (notifier_severity == KHERR_NONE) { + NOTIFYICONDATA ni; + + ZeroMemory(&ni, sizeof(ni)); + + ni.cbSize = sizeof(ni); + ni.hWnd = hwnd_notifier; + ni.uID = KHUI_NOTIFY_ICON_ID; + ni.uFlags = NIF_TIP; + + StringCbCopy(ni.szTip, sizeof(ni.szTip), tip_normal); + + Shell_NotifyIcon(NIM_MODIFY, &ni); + } +} + +void khm_notify_icon_remove(void) { + NOTIFYICONDATA ni; + + ZeroMemory(&ni, sizeof(ni)); + + ni.cbSize = sizeof(ni); + ni.hWnd = hwnd_notifier; + ni.uID = KHUI_NOTIFY_ICON_ID; + + Shell_NotifyIcon(NIM_DELETE, &ni); +} + +khm_int32 +khm_get_default_notifier_action(void) { + khm_int32 def_cmd = KHUI_ACTION_OPEN_APP; + khm_handle csp_cw = NULL; + khm_size i; + + if (KHM_FAILED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, + &csp_cw))) + def_cmd; + + khc_read_int32(csp_cw, L"NotificationAction", &def_cmd); + + khc_close_space(csp_cw); + + for (i=0; i < n_khm_notifier_actions; i++) { + if (khm_notifier_actions[i] == def_cmd) + break; + } + + if (i < n_khm_notifier_actions) + return def_cmd; + else + return KHUI_ACTION_OPEN_APP; +} + +void khm_notify_icon_activate(void) { + /* if there are any notifications waiting to be shown and there + are no alerts already being shown, we show them. Otherwise we + execute the default action. */ + + khm_notify_icon_change(KHERR_NONE); + + if (balloon_alert != NULL && khui_alert_windows == NULL) { + + khui_alert * a; + khm_boolean alert_done = FALSE; + + a = balloon_alert; + balloon_alert = NULL; + + khui_alert_lock(a); + + a->displayed = FALSE; + + if ((a->flags & KHUI_ALERT_FLAG_DEFACTION) && + (a->n_alert_commands > 0)) { + + PostMessage(khm_hwnd_main, WM_COMMAND, + MAKEWPARAM(a->alert_commands[0], + 0), + 0); + alert_done = TRUE; + + } else if (a->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW) { + + alert_show_normal(a); + alert_done = TRUE; + + } + khui_alert_unlock(a); + khui_alert_release(a); + + if (alert_done) + return; + } + + if (!is_alert_queue_empty() && !ALERT_DISPLAYED()) { + + khm_show_main_window(); + show_queued_alerts(); + + return; + } + + + /* if none of the above applied, then we perform the default + action for the notification icon. */ + { + khm_int32 cmd = 0; + + cmd = khm_get_default_notifier_action(); + + if (cmd == KHUI_ACTION_OPEN_APP) { + if (khm_is_main_window_visible()) { + khm_hide_main_window(); + } else { + khm_show_main_window(); + } + } else { + khui_action_trigger(cmd, NULL); + } + + check_for_queued_alerts(); + } +} + +/********************************************************************* + Initialization +**********************************************************************/ + +void khm_init_notifier(void) +{ + if(!khm_register_notifier_wnd_class()) + return; + + if(!khm_register_alerter_wnd_class()) + return; + + if(!khm_register_alert_bin_wnd_class()) + return; + + hwnd_notifier = CreateWindowEx(0, + MAKEINTATOM(atom_notifier), + KHUI_NOTIFIER_WINDOW, + 0, + 0,0,0,0, + HWND_MESSAGE, + NULL, + khm_hInstance, + NULL); + + if(hwnd_notifier != NULL) { + kmq_subscribe_hwnd(KMSG_ALERT, hwnd_notifier); + kmq_subscribe_hwnd(KMSG_CRED, hwnd_notifier); + notifier_ready = TRUE; + + khm_notify_icon_add(); + } else { +#ifdef DEBUG + assert(hwnd_notifier != NULL); +#endif + } + khm_timer_init(); + + khm_addr_change_notifier_init(); +} + +void khm_exit_notifier(void) +{ + khm_addr_change_notifier_exit(); + + khm_timer_exit(); + + if(hwnd_notifier != NULL) { + khm_notify_icon_remove(); + kmq_unsubscribe_hwnd(KMSG_ALERT, hwnd_notifier); + kmq_unsubscribe_hwnd(KMSG_CRED, hwnd_notifier); + DestroyWindow(hwnd_notifier); + hwnd_notifier = NULL; + } + + if(atom_notifier != 0) { + UnregisterClass(MAKEINTATOM(atom_notifier), khm_hInstance); + atom_notifier = 0; + } + + if(atom_alerter != 0) { + UnregisterClass(MAKEINTATOM(atom_alerter), khm_hInstance); + atom_alerter = 0; + } + + if(atom_alert_bin != 0) { + UnregisterClass(MAKEINTATOM(atom_alert_bin), khm_hInstance); + atom_alert_bin = 0; + } + + notifier_ready = FALSE; +} + diff --git a/krb5-1-6/src/windows/identity/ui/notifier.h b/krb5-1-6/src/windows/identity/ui/notifier.h new file mode 100644 index 000000000..2bdbdf701 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/notifier.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_NOTIFIER_H +#define __KHIMAIRA_NOTIFIER_H + +extern HWND hwnd_notifier; + +enum khm_notif_expstate { + KHM_NOTIF_EMPTY, + KHM_NOTIF_OK, + KHM_NOTIF_WARN, + KHM_NOTIF_EXP +}; + +extern khm_int32 khm_notifier_actions[]; +extern khm_size n_khm_notifier_actions; + +void +khm_init_notifier(void); + +void +khm_exit_notifier(void); + +void +khm_notify_icon_change(khm_int32 severity); + +void +khm_notify_icon_tooltip(wchar_t * s); + +void +khm_notify_icon_balloon(khm_int32 severity, + wchar_t * title, + wchar_t * msg, + khm_int32 timeout); + +void +khm_notify_icon_expstate(enum khm_notif_expstate expseverity); + +void +khm_notify_icon_activate(void); + +khm_int32 +khm_get_default_notifier_action(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/passwnd.c b/krb5-1-6/src/windows/identity/ui/passwnd.c new file mode 100644 index 000000000..65cc06fe7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/passwnd.c @@ -0,0 +1,133 @@ +#include<khmapp.h> + +static ATOM sAtom = 0; +static HINSTANCE shInstance = 0; + +/* Callback for the MITPasswordControl +This is a replacement for the normal edit control. It does not show the +annoying password char in the edit box so that the number of chars in the +password are not known. +*/ + +#define PASSWORDCHAR L'#' +#define DLGHT(ht) (HIWORD(GetDialogBaseUnits())*(ht)/8) +#define DLGWD(wd) (LOWORD(GetDialogBaseUnits())*(wd)/4) + +static +LRESULT +CALLBACK +MITPasswordEditProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam + ) +{ + static SIZE pwdcharsz; + BOOL pass_the_buck = FALSE; + + if (message > WM_USER && message < 0x7FFF) + pass_the_buck = TRUE; + + switch(message) + { + case WM_GETTEXT: + case WM_GETTEXTLENGTH: + case WM_SETTEXT: + pass_the_buck = TRUE; + break; + case WM_PAINT: + { + HDC hdc; + PAINTSTRUCT ps; + RECT r; + + hdc = BeginPaint(hWnd, &ps); + GetClientRect(hWnd, &r); + Rectangle(hdc, 0, 0, r.right, r.bottom); + EndPaint(hWnd, &ps); + } + break; + case WM_SIZE: + { + MoveWindow(GetDlgItem(hWnd, 1), DLGWD(2), DLGHT(2), + pwdcharsz.cx / 2, pwdcharsz.cy, TRUE); + } + break; + case WM_LBUTTONDOWN: + case WM_SETFOCUS: + { + SetFocus(GetDlgItem(hWnd, 1)); + } + break; + case WM_CREATE: + { + HWND heditchild; + wchar_t pwdchar = PASSWORDCHAR; + HDC hdc; + /* Create a child window of this control for default processing. */ + hdc = GetDC(hWnd); + GetTextExtentPoint32(hdc, &pwdchar, 1, &pwdcharsz); + ReleaseDC(hWnd, hdc); + + heditchild = + CreateWindow(L"edit", L"", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | + ES_LEFT | ES_PASSWORD | WS_TABSTOP, + 0, 0, 0, 0, + hWnd, + (HMENU)1, + ((LPCREATESTRUCT)lParam)->hInstance, + NULL); + SendMessage(heditchild, EM_SETPASSWORDCHAR, PASSWORDCHAR, 0L); + } + break; + } + + if (pass_the_buck) + return SendMessage(GetDlgItem(hWnd, 1), message, wParam, lParam); + return DefWindowProc(hWnd, message, wParam, lParam); +} + +khm_int32 +khm_register_passwnd_class(void) +{ + if (!sAtom) { + WNDCLASS wndclass; + + memset(&wndclass, 0, sizeof(WNDCLASS)); + + shInstance = khm_hInstance; + + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = (WNDPROC)MITPasswordEditProc; + wndclass.cbClsExtra = sizeof(HWND); + wndclass.cbWndExtra = 0; + wndclass.hInstance = shInstance; + wndclass.hbrBackground = (void *)(COLOR_WINDOW + 1); + wndclass.lpszClassName = MIT_PWD_DLL_CLASS; + wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_IBEAM); + + sAtom = RegisterClass(&wndclass); + } + + return (sAtom)?KHM_ERROR_SUCCESS:KHM_ERROR_UNKNOWN; +} + +khm_int32 +khm_unregister_passwnd_class(void) +{ + BOOL result = TRUE; + + if ((khm_hInstance != shInstance) || !sAtom) { + return KHM_ERROR_INVALID_OPERATION; + } + + result = UnregisterClass(MIT_PWD_DLL_CLASS, khm_hInstance); + if (result) { + sAtom = 0; + shInstance = 0; + return KHM_ERROR_SUCCESS; + } else { + return KHM_ERROR_UNKNOWN; + } +} diff --git a/krb5-1-6/src/windows/identity/ui/passwnd.h b/krb5-1-6/src/windows/identity/ui/passwnd.h new file mode 100644 index 000000000..c3ab8ef31 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/passwnd.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_PASSWND_H +#define __KHIMAIRA_PASSWND_H + +/* Declarations for the MIT password change control. Functionally the + same as the regular Windows password edit control but doesn't + display the '*' password character. */ + +#define MIT_PWD_DLL_CLASS L"MITPasswordWnd" + +khm_int32 khm_unregister_passwnd_class(void); +khm_int32 khm_register_passwnd_class(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/propertywnd.c b/krb5-1-6/src/windows/identity/ui/propertywnd.c new file mode 100644 index 000000000..340684889 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/propertywnd.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +typedef struct tag_pw_data { + khm_handle record; + HWND hwnd_lv; +} pw_data; + +ATOM khui_propertywnd_cls; + +#define ID_LISTVIEW 1 + +#define PW_WM_SET_RECORD WM_USER + +void pw_update_property_data(HWND hw, pw_data * d) +{ + HWND hwnd_lv; + khm_int32 * attrs = NULL; + + hwnd_lv = d->hwnd_lv; + + if(hwnd_lv == NULL) + return; + + ListView_DeleteAllItems(hwnd_lv); + + if(d->record != NULL) { + wchar_t * buffer; + khm_size attr_count; + khm_size i; + khm_size cb_buf; + khm_size t; + LVITEM lvi; + int idx; + + if(KHM_FAILED(kcdb_attrib_get_count( + KCDB_ATTR_FLAG_VOLATILE | + KCDB_ATTR_FLAG_HIDDEN, + 0, + &attr_count))) + return; + + attrs = PMALLOC(sizeof(khm_int32) * attr_count); + assert(attrs != NULL); + + kcdb_attrib_get_ids( + KCDB_ATTR_FLAG_VOLATILE | + KCDB_ATTR_FLAG_HIDDEN, + 0, + attrs, + &attr_count); + + cb_buf = sizeof(wchar_t) * 2048; + buffer = PMALLOC(cb_buf); + assert(buffer != NULL); + + for(i=0; i<attr_count; i++) { + if(KHM_FAILED(kcdb_buf_get_attr(d->record, attrs[i], NULL, NULL, NULL))) + continue; + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_TEXT | LVIF_PARAM; + lvi.iItem = (int) i; + lvi.iSubItem = 0; + lvi.pszText = buffer; + lvi.lParam = (LPARAM) attrs[i]; + + t = cb_buf; + kcdb_attrib_describe(attrs[i], buffer, &t, KCDB_TS_SHORT); + + idx = ListView_InsertItem(hwnd_lv, &lvi); + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.mask = LVIF_TEXT; + lvi.iItem = idx; + lvi.iSubItem = 1; + lvi.pszText = buffer; + + t = cb_buf; + kcdb_buf_get_attr_string(d->record, attrs[i], buffer, &t, 0); + + ListView_SetItem(hwnd_lv, &lvi); + } + + PFREE(attrs); + PFREE(buffer); + } +} + +LRESULT CALLBACK khui_property_wnd_proc( + HWND hwnd, + UINT msg, + WPARAM wParam, + LPARAM lParam) +{ + BOOL child_msg = FALSE; + pw_data * child; + + switch(msg) { + case WM_CREATE: + { + CREATESTRUCT * cs; + LVCOLUMN lvc; + wchar_t sz_title[256]; + + cs = (CREATESTRUCT *) lParam; + + child = PMALLOC(sizeof(*child)); + ZeroMemory(child, sizeof(*child)); + +#pragma warning(push) +#pragma warning(disable:4244) + SetWindowLongPtr(hwnd, 0, (LONG_PTR) child); +#pragma warning(pop) + + child->hwnd_lv = CreateWindow( + WC_LISTVIEW, + L"", + WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | + LVS_REPORT | LVS_SORTASCENDING, + 0, 0, + cs->cx, cs->cy, + hwnd, + (HMENU) ID_LISTVIEW, + khm_hInstance, + NULL); + + ListView_SetExtendedListViewStyle(child->hwnd_lv, + LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); + + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_TEXT | LVCF_WIDTH; + lvc.fmt = LVCFMT_LEFT; + lvc.cx = (cs->cx * 2)/ 5; + lvc.pszText = sz_title; + lvc.iSubItem = 0; + lvc.iOrder = 0; + LoadString(khm_hInstance, IDS_PROP_COL_PROPERTY, sz_title, ARRAYLENGTH(sz_title)); + + ListView_InsertColumn(child->hwnd_lv, 0, &lvc); + + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; + lvc.fmt = LVCFMT_LEFT; + lvc.cx = (cs->cx * 3)/ 5; + lvc.pszText = sz_title; + lvc.iSubItem = 1; + lvc.iOrder = 1; + LoadString(khm_hInstance, IDS_PROP_COL_VALUE, sz_title, ARRAYLENGTH(sz_title)); + + ListView_InsertColumn(child->hwnd_lv, 1, &lvc); + + if(cs->lpCreateParams != NULL) { + child->record = cs->lpCreateParams; + kcdb_buf_hold(child->record); + pw_update_property_data(hwnd, child); + } + } + break; + + case PW_WM_SET_RECORD: + { + child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (child == NULL) + break; + + kcdb_buf_release(child->record); + child->record = (khm_handle) lParam; + kcdb_buf_hold(child->record); + pw_update_property_data(hwnd, child); + } + return 0; + + case WM_DESTROY: + { + child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + if (child) { + kcdb_buf_release(child->record); + PFREE(child); + SetWindowLongPtr(hwnd, 0, 0); + } + } + break; + + case WM_PAINT: + break; + + default: + child = (pw_data *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); + child_msg = TRUE; + } + + /* + if(child_msg && child && child->hwnd_lv) + return SendMessage(child->hwnd_lv, msg, wParam, lParam); + else + */ + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +khm_int32 khm_register_propertywnd_class(void) +{ + WNDCLASSEX wcx; + + wcx.cbSize = sizeof(wcx); + wcx.style = CS_DBLCLKS; + wcx.lpfnWndProc = khui_property_wnd_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = sizeof(LONG_PTR); + wcx.hInstance = khm_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_PROPERTYWND_CLASS_NAME; + wcx.hIconSm = NULL; + + khui_propertywnd_cls = RegisterClassEx(&wcx); + + return (khui_propertywnd_cls == 0)?KHM_ERROR_UNKNOWN:KHM_ERROR_SUCCESS; +} + +khm_int32 khm_unregister_propertywnd_class(void) +{ + UnregisterClass(MAKEINTATOM(khui_propertywnd_cls), khm_hInstance); + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/ui/propertywnd.h b/krb5-1-6/src/windows/identity/ui/propertywnd.h new file mode 100644 index 000000000..c4a738eaf --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/propertywnd.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_PROPERTYWND_H +#define __KHIMAIRA_PROPERTYWND_H + +#define KHUI_PROPERTYWND_CLASS_NAME L"NetIDMgrPropertyWnd" + +khm_int32 khm_register_propertywnd_class(void); + +khm_int32 khm_unregister_propertywnd_class(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/reqdaemon.c b/krb5-1-6/src/windows/identity/ui/reqdaemon.c new file mode 100644 index 000000000..20b126e27 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/reqdaemon.c @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +ATOM reqdaemon_atom = 0; +HANDLE reqdaemon_thread = NULL; +HWND reqdaemon_hwnd = NULL; + +LRESULT CALLBACK +reqdaemonwnd_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + switch(uMsg) { + case WM_CREATE: + break; + + case WM_CLOSE: + DestroyWindow(hwnd); + break; + + case WM_DESTROY: + reqdaemon_hwnd = NULL; + PostQuitMessage(0); + break; + + /* Leash compatibility */ + case ID_OBTAIN_TGT_WITH_LPARAM: + { + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t wmapping[ARRAYLENGTH(KHUI_REQD_MAPPING_FORMAT) + 10]; + khm_handle identity = NULL; + LPNETID_DLGINFO pdlginfo; + LRESULT lr = 1; + khm_int32 result; + HANDLE hmap = NULL; + HRESULT hr; + + hr = StringCbPrintf(wmapping, sizeof(wmapping), + KHUI_REQD_MAPPING_FORMAT, (DWORD) lParam); +#ifdef DEBUG + assert(SUCCEEDED(hr)); +#endif + hmap = CreateFileMapping(INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, 4096, + wmapping); + + if (hmap == NULL) { + return -1; + } else if (hmap != NULL && GetLastError() != ERROR_ALREADY_EXISTS) { + CloseHandle(hmap); + return -1; + } + + pdlginfo = MapViewOfFile(hmap, + FILE_MAP_WRITE, + 0, 0, + sizeof(*pdlginfo)); + + if (pdlginfo == NULL) { + CloseHandle(hmap); + return 1; + } + + if (pdlginfo->in.username[0] && + pdlginfo->in.realm[0] && + SUCCEEDED(StringCbPrintf(widname, + sizeof(widname), + L"%s@%s", + pdlginfo->in.username, + pdlginfo->in.realm))) { + + kcdb_identity_create(widname, + KCDB_IDENT_FLAG_CREATE, + &identity); + } + + widname[0] = 0; + + do { + if (khm_cred_is_in_dialog()) { + khm_cred_wait_for_dialog(INFINITE, NULL, NULL, 0); + } + + if (identity) + khui_context_set_ex(KHUI_SCOPE_IDENT, + identity, + KCDB_CREDTYPE_INVALID, + NULL, + NULL, + 0, + NULL, + pdlginfo, + sizeof(*pdlginfo)); + else + khui_context_reset(); + + if (pdlginfo->dlgtype == NETID_DLGTYPE_TGT) + SendMessage(khm_hwnd_main, WM_COMMAND, + MAKEWPARAM(KHUI_ACTION_NEW_CRED, 0), 0); + else if (pdlginfo->dlgtype == NETID_DLGTYPE_CHPASSWD) + SendMessage(khm_hwnd_main, WM_COMMAND, + MAKEWPARAM(KHUI_ACTION_PASSWD_ID, 0), 0); + else + break; + + if (KHM_FAILED(khm_cred_wait_for_dialog(INFINITE, &result, + widname, + sizeof(widname)))) + continue; + else { + lr = (result != KHUI_NC_RESULT_PROCESS); + break; + } + } while(TRUE); + +#ifdef DEBUG + assert(lr || pdlginfo->dlgtype != NETID_DLGTYPE_TGT || + widname[0]); +#endif + + if (!lr && pdlginfo->dlgtype == NETID_DLGTYPE_TGT && + widname[0]) { + khm_handle out_ident; + wchar_t * atsign; + + atsign = wcsrchr(widname, L'@'); + + if (atsign == NULL) + goto _exit; + + if (KHM_SUCCEEDED(kcdb_identity_create(widname, + 0, + &out_ident))) { + khm_size cb; + + pdlginfo->out.ccache[0] = 0; + + cb = sizeof(pdlginfo->out.ccache); + kcdb_identity_get_attrib(out_ident, + L"Krb5CCName", + NULL, + pdlginfo->out.ccache, + &cb); + kcdb_identity_release(out_ident); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + + *atsign++ = 0; + + StringCbCopy(pdlginfo->out.username, + sizeof(pdlginfo->out.username), + widname); + + StringCbCopy(pdlginfo->out.realm, + sizeof(pdlginfo->out.realm), + atsign); + } + + _exit: + + if (pdlginfo) + UnmapViewOfFile(pdlginfo); + if (hmap) + CloseHandle(hmap); + if (identity) + kcdb_identity_release(identity); + + return lr; + } + +#ifdef DEPRECATED_REMOTE_CALL + /* deprecated */ + case ID_OBTAIN_TGT_WITH_LPARAM: + { + char * param = (char *) GlobalLock((HGLOBAL) lParam); + char * username = NULL; + char * realm = NULL; + char * title = NULL; + char * ccache = NULL; + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t wtitle[KHUI_MAXCCH_TITLE]; + size_t cch; + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle identity = NULL; + NETID_DLGINFO dlginfo; + + if (param) { + if (*param) + title = param; + + if (FAILED(StringCchLengthA(param, KHUI_MAXCCH_TITLE, &cch))) { +#ifdef DEBUG + assert(FALSE); +#endif + rv = KHM_ERROR_INVALID_PARAM; + goto _exit_tgt_with_lparam; + } + + param += cch + 1; + + if (*param) + username = param; + + if (FAILED(StringCchLengthA(param, KCDB_IDENT_MAXCCH_NAME, &cch))) { +#ifdef DEBUG + assert(FALSE); +#endif + rv = KHM_ERROR_INVALID_PARAM; + goto _exit_tgt_with_lparam; + } + + param += cch + 1; + + if (*param) + realm = param; + + if (FAILED(StringCchLengthA(param, KCDB_IDENT_MAXCCH_NAME, &cch))) { +#ifdef DEBUG + assert(FALSE); +#endif + rv = KHM_ERROR_INVALID_PARAM; + goto _exit_tgt_with_lparam; + } + + param += cch + 1; + + if (*param) + ccache = param; + } + + if (username && realm) { + + if (FAILED(StringCbPrintf(widname, sizeof(widname), + L"%hs@%hs", username, realm))) { + rv = KHM_ERROR_INVALID_PARAM; + goto _exit_tgt_with_lparam; + } + + rv = kcdb_identity_create(widname, + KCDB_IDENT_FLAG_CREATE, + &identity); + if (KHM_FAILED(rv)) { + goto _exit_tgt_with_lparam; + } + } + + ZeroMemory(&dlginfo, sizeof(dlginfo)); + + dlginfo.size = NETID_DLGINFO_V1_SZ; + dlginfo.dlgtype = NETID_DLGTYPE_TGT; + + if (title) + StringCbCopy(dlginfo.in.title, sizeof(dlginfo.in.title), + wtitle); + if (username) + AnsiStrToUnicode(dlginfo.in.username, sizeof(dlginfo.in.username), + username); + if (realm) + AnsiStrToUnicode(dlginfo.in.realm, sizeof(dlginfo.in.realm), + realm); + + if (ccache) + AnsiStrToUnicode(dlginfo.in.ccache, sizeof(dlginfo.in.ccache), + ccache); + + dlginfo.in.use_defaults = TRUE; + + do { + if (khm_cred_is_in_dialog()) { + khm_cred_wait_for_dialog(INFINITE); + } + + khui_context_set_ex(KHUI_SCOPE_IDENT, + identity, + KCDB_CREDTYPE_INVALID, + NULL, + NULL, + 0, + NULL, + &dlginfo, + sizeof(dlginfo)); + + if (title) { + AnsiStrToUnicode(wtitle, sizeof(wtitle), + title); + + khm_cred_obtain_new_creds(wtitle); + } else { + khm_cred_obtain_new_creds(NULL); + } + + if (KHM_FAILED(khm_cred_wait_for_dialog(INFINITE))) + continue; + else + break; + } while(TRUE); + + _exit_tgt_with_lparam: + if (identity) + kcdb_identity_release(identity); + + GlobalUnlock((HGLOBAL) lParam); + } + return 0; +#endif + + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +DWORD WINAPI +khm_reqdaemon_thread_proc(LPVOID vparam) { + BOOL rv; + MSG msg; +#ifdef DEBUG + DWORD dw; +#endif + + PDESCTHREAD(L"Remote Request Daemon", L"App"); + + khm_register_reqdaemonwnd_class(); + +#ifdef DEBUG + assert(reqdaemon_atom != 0); +#endif + + reqdaemon_hwnd = CreateWindowEx(0, + MAKEINTATOM(reqdaemon_atom), + KHUI_REQDAEMONWND_NAME, + 0, + 0,0,0,0, + HWND_MESSAGE, + NULL, + khm_hInstance, + NULL); + +#ifdef DEBUG + dw = GetLastError(); + assert(reqdaemon_hwnd != NULL); +#endif + + while(rv = GetMessage(&msg, NULL, 0, 0)) { + if (rv == -1) { +#ifdef DEBUG + assert(FALSE); +#endif + break; + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + reqdaemon_thread = NULL; + + khm_unregister_reqdaemonwnd_class(); + + return 0; +} + +void +khm_register_reqdaemonwnd_class(void) { + WNDCLASSEX wcx; + + ZeroMemory(&wcx, sizeof(wcx)); + + wcx.cbSize = sizeof(wcx); + wcx.style = 0; + wcx.lpfnWndProc = reqdaemonwnd_proc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = khm_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = NULL; + wcx.hbrBackground = NULL; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = KHUI_REQDAEMONWND_CLASS; + wcx.hIconSm = NULL; + + reqdaemon_atom = RegisterClassEx(&wcx); + +#ifdef DEBUG + assert(reqdaemon_atom != 0); +#endif +} + +void +khm_unregister_reqdaemonwnd_class(void) { + if (reqdaemon_atom != 0) { + UnregisterClass(MAKEINTATOM(reqdaemon_atom), khm_hInstance); + reqdaemon_atom = 0; + } +} + +void +khm_init_request_daemon(void) { +#ifdef DEBUG + assert(reqdaemon_thread == NULL); +#endif + + reqdaemon_thread = CreateThread(NULL, + 0, + khm_reqdaemon_thread_proc, + NULL, + 0, + NULL); + +#ifdef DEBUG + assert(reqdaemon_thread != NULL); +#endif +} + +void +khm_exit_request_daemon(void) { + if (reqdaemon_hwnd == NULL) + return; + + SendMessage(reqdaemon_hwnd, WM_CLOSE, 0, 0); +} diff --git a/krb5-1-6/src/windows/identity/ui/reqdaemon.h b/krb5-1-6/src/windows/identity/ui/reqdaemon.h new file mode 100644 index 000000000..99a50f5e0 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/reqdaemon.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_REQDAEMON_H +#define __KHIMAIRA_REQDAEMON_H + +void +khm_register_reqdaemonwnd_class(void); + +void +khm_unregister_reqdaemonwnd_class(void); + +void +khm_init_request_daemon(void); + +void +khm_exit_request_daemon(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/resource.h b/krb5-1-6/src/windows/identity/ui/resource.h new file mode 100644 index 000000000..19cd49de6 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/resource.h @@ -0,0 +1,421 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\ui\lang\en_us\khapp.rc +// +#define IDI_MAIN_APP 104 +#define IDD_PP_CRED 106 +#define IDD_PP_IDENT 107 +#define IDB_TK_REFRESH 108 +#define IDS_MAIN_WINDOW_TITLE 108 +#define IDS_MENU_FILE 109 +#define IDB_ID 110 +#define IDS_MENU_CRED 110 +#define IDB_ID_DELETE 111 +#define IDS_MENU_VIEW 111 +#define IDB_ID_NEW 112 +#define IDS_MENU_OPTIONS 112 +#define IDB_ID_REFRESH 113 +#define IDS_MENU_HELP 113 +#define IDB_TK 114 +#define IDS_ACTION_PROPERTIES 114 +#define IDB_TK_DELETE 115 +#define IDS_ACTION_EXIT 115 +#define IDB_TK_NEW 116 +#define IDS_CFG_ROOT_NAME 116 +#define IDS_ACTION_SET_DEF_ID 117 +#define IDS_ACTION_SET_SRCH_ID 118 +#define IDB_VW_REFRESH_SM 118 +#define IDR_MENU_BAR 119 +#define IDS_CFG_ROOT_TITLE 119 +#define IDS_CFG_GENERAL_SHORT 120 +#define IDB_TB_BLANK 121 +#define IDS_ACTION_NEW_CRED 121 +#define IDS_ACTION_PASSWD_ID 122 +#define IDS_ACTION_CHOOSE_COLS 123 +#define IDB_TB_BLANK_SM 123 +#define IDS_ACTION_DEBUG_WINDOW 124 +#define IDB_VW_REFRESH 124 +#define IDS_ACTION_VIEW_REFRESH 125 +#define IDB_ID_DELETE_DIS 125 +#define IDS_MENU_LAYOUT 126 +#define IDB_ID_DELETE_DIS_SM 126 +#define IDS_MENU_TOOLBARS 127 +#define IDB_ID_DELETE_SM 127 +#define IDS_ACTION_LAYOUT_ID 128 +#define IDB_ID_DIS 128 +#define IDS_ACTION_LAYOUT_TYPE 129 +#define IDB_ID_DIS_SM 129 +#define IDS_ACTION_LAYOUT_LOC 130 +#define IDB_ID_NEW_DIS 130 +#define IDS_ACTION_TB_STANDARD 131 +#define IDB_ID_NEW_DIS_SM 131 +#define IDS_ACTION_OPT_KHIM 132 +#define IDB_ID_NEW_SM 132 +#define IDB_ID_REFRESH_DIS 133 +#define IDS_ACTION_OPT_IDENTS 133 +#define IDS_ACTION_OPT_NOTIF 134 +#define IDB_ID_REFRESH_SM 134 +#define IDS_ACTION_HELP_CTX 135 +#define IDB_ID_REFRESH_DIS_SM 135 +#define IDS_ACTION_HELP_CONTENTS 136 +#define IDB_TK_DELETE_DIS 136 +#define IDS_ACTION_HELP_INDEX 137 +#define IDB_TK_DELETE_DIS_SM 137 +#define IDS_ACTION_HELP_ABOUT 138 +#define IDB_TK_DELETE_SM 138 +#define IDB_TK_DIS_SM 139 +#define IDS_CFG_GENERAL_LONG 139 +#define IDB_TK_NEW_DIS 140 +#define IDS_SAMPLE_STRING 140 +#define IDB_TK_NEW_DIS_SM 141 +#define IDS_NO_CREDS 141 +#define IDB_TK_NEW_SM 142 +#define IDS_WT_INIT_CREDS 142 +#define IDB_TK_REFRESH_DIS 143 +#define IDS_WT_NEW_CREDS 143 +#define IDB_TK_REFRESH_DIS_SM 144 +#define IDS_NC_IDENTITY 144 +#define IDB_TK_REFRESH_SM 145 +#define IDS_NC_IDENTS 145 +#define IDB_TK_SM 146 +#define IDS_NC_CREDTEXT_ID_NONE 146 +#define IDB_HELP_SM 147 +#define IDS_NC_CREDTEXT_ID_ONE 147 +#define IDB_HELP 148 +#define IDS_NC_CREDTEXT_ID_MANY 148 +#define IDB_LOGO_SHADE 149 +#define IDS_NC_CREDTEXT_ID_INVALID 149 +#define IDS_WTPOST_INIT_CREDS 150 +#define IDS_WTPOST_NEW_CREDS 151 +#define IDB_WDG_EXPAND 152 +#define IDS_ACTION_RENEW_CRED 152 +#define IDB_WDG_COLLAPSE 153 +#define IDS_ACTION_DESTROY_CRED 153 +#define IDB_ID_SM 154 +#define IDS_DEFAULT_FONT 154 +#define IDB_WDG_EXPAND_HI 155 +#define IDS_NC_CREDTEXT_TABS 155 +#define IDB_WDG_COLLAPSE_HI 156 +#define IDS_NOTIFY_PREFIX 156 +#define IDB_WDG_CREDTYPE 157 +#define IDS_NOTIFY_READY 157 +#define IDB_WDG_FLAG 158 +#define IDS_NOTIFY_ATTENTION 158 +#define IDB_FLAG_WARN 159 +#define IDS_ALERT_DEFAULT 159 +#define IDB_FLAG_EXPIRED 160 +#define IDS_PACTION_OK 160 +#define IDB_FLAG_CRITICAL 161 +#define IDS_PACTION_CANCEL 161 +#define IDS_PACTION_CLOSE 162 +#define IDD_NC_NEWCRED 162 +#define IDD_NC_BBAR 163 +#define IDS_ALERT_NOSEL_TITLE 163 +#define IDS_ALERT_NOSEL 164 +#define IDI_ENABLED 165 +#define IDS_NC_CREDTEXT_ID_VALID 165 +#define IDI_DISABLED 166 +#define IDS_NC_CREDTEXT_ID_UNCHECKED 166 +#define IDS_PROP_COL_PROPERTY 167 +#define IDS_PROP_COL_VALUE 168 +#define IDI_NOTIFY_NONE 169 +#define IDS_NC_NEW_IDENT 169 +#define IDI_NOTIFY_INFO 170 +#define IDS_NC_CREDTEXT_ID_CHECKING 170 +#define IDI_NOTIFY_WARN 171 +#define IDS_ACTION_OPEN_APP 171 +#define IDI_NOTIFY_ERROR 172 +#define IDS_CTX_NEW_IDENT 172 +#define IDS_CTX_NEW_CREDS 173 +#define IDD_CFG_MAIN 173 +#define IDS_CTX_RENEW_CREDS 174 +#define IDD_CFG_GENERIC 174 +#define IDS_CTX_PROC_NEW_IDENT 175 +#define IDB_LOGO_OPAQUE 175 +#define IDS_CTX_PROC_NEW_CREDS 176 +#define IDD_CFG_GENERAL 176 +#define IDS_CTX_PROC_RENEW_CREDS 177 +#define IDD_CFG_IDENTITIES 177 +#define IDS_ACTION_CLOSE_APP 178 +#define IDD_CFG_NOTIF 178 +#define IDS_NC_FAILED_TITLE 179 +#define IDD_CFG_PLUGINS 179 +#define IDS_CFG_IDENTITIES_SHORT 180 +#define IDD_CFG_IDENTITY 180 +#define IDS_CFG_IDENTITIES_LONG 181 +#define IDI_CFG_DEFAULT 181 +#define IDS_CFG_NOTIF_SHORT 182 +#define IDI_CFG_MODIFIED 182 +#define IDS_CFG_NOTIF_LONG 183 +#define IDI_CFG_APPLIED 183 +#define IDS_CFG_PLUGINS_SHORT 184 +#define IDD_CFG_IDS_TAB 184 +#define IDS_CFG_PLUGINS_LONG 185 +#define IDD_CFG_ID_TAB 185 +#define IDS_CFG_IDENTITY_SHORT 186 +#define IDI_CFG_DELETED 186 +#define IDS_CFG_IDENTITY_LONG 187 +#define IDI_ID 187 +#define IDS_CTX_DESTROY_CREDS 188 +#define IDB_IMPORT_SM_DIS 188 +#define IDS_WARN_EXPIRE 189 +#define IDB_IMPORT 189 +#define IDS_WARN_TITLE 190 +#define IDB_IMPORT_DIS 190 +#define IDS_ALERT_MOREINFO 191 +#define IDB_IMPORT_SM 191 +#define IDS_WARN_EXPIRED 192 +#define IDB_CHPW_SM 192 +#define IDS_WARN_EXPIRE_ID 193 +#define IDB_CHPW 193 +#define IDS_WARN_EXPIRED_ID 194 +#define IDB_CHPW_DIS 194 +#define IDS_WARN_WM_TITLE 195 +#define IDB_CHPW_DIS_SM 195 +#define IDS_WARN_WM_MSG 196 +#define IDD_ABOUT 196 +#define IDS_CFG_ID_TAB_SHORT 197 +#define IDB_TB_SPACE 197 +#define IDS_CFG_ID_TAB_LONG 198 +#define IDB_WDG_STUCK_HI 198 +#define IDS_CFG_IDS_TAB_SHORT 199 +#define IDB_WDG_STICK 199 +#define IDS_CFG_IDS_TAB_LONG 200 +#define IDB_WDG_STICK_HI 200 +#define IDS_CFG_IDS_IDENTITY 201 +#define IDB_WDG_STUCK 201 +#define IDS_ACTION_IMPORT 202 +#define IDS_CTX_IMPORT 203 +#define IDB_FLAG_RENEW 203 +#define IDS_CFG_PI_COL_PLUGINS 204 +#define IDI_APPICON_WARN 204 +#define IDS_PISTATE_FAILUNK 205 +#define IDI_APPICON_EXP 205 +#define IDS_PISTATE_FAILMAX 206 +#define IDI_APPICON_OK 206 +#define IDS_PISTATE_FAILREG 207 +#define IDI_CFG_PLUGIN 207 +#define IDS_PISTATE_FAILDIS 208 +#define IDI_CFG_PLUGIN_ERR 208 +#define IDS_PISTATE_FAILLOD 209 +#define IDI_CFG_PLUGIN_DIS 209 +#define IDS_PISTATE_PLACEHOLD 210 +#define IDD_CFG_APPEAR 210 +#define IDS_PISTATE_REG 211 +#define IDD_CFG_ADDIDENT 211 +#define IDS_PISTATE_HOLD 212 +#define IDD_CMDLINE 212 +#define IDS_PISTATE_INIT 213 +#define IDR_CMDLINERTF 213 +#define IDS_PISTATE_RUN 214 +#define IDS_PISTATE_EXIT 215 +#define IDS_CTX_PASSWORD 216 +#define IDS_WT_PASSWORD 217 +#define IDS_WTPOST_PASSWORD 218 +#define IDS_CTX_PROC_PASSWORD 219 +#define IDS_NC_PWD_FAILED_TITLE 220 +#define IDS_MENU_SETDEF 221 +#define IDS_PACTION_NEXT 222 +#define IDS_ERR_TITLE_NO_IDENTPRO 223 +#define IDS_ERR_MSG_NO_IDENTPRO 224 +#define IDS_ERR_SUGG_NO_IDENTPRO 225 +#define IDS_NC_REN_FAILED_TITLE 226 +#define IDS_CW_DEFAULT 227 +#define IDS_ACTION_OPT_PLUGINS 228 +#define IDS_NC_SETDEF 229 +#define IDS_NC_ID_DEF 230 +#define IDS_NC_ID_WDEF 231 +#define IDS_NC_ID_NDEF 232 +#define IDS_PACTION_YES 233 +#define IDS_PACTION_NO 234 +#define IDS_PACTION_YESALL 235 +#define IDS_PACTION_NOALL 236 +#define IDS_PACTION_KEEP 237 +#define IDS_PACTION_REMOVE 238 +#define IDS_PACTION_DISCARD 239 +#define IDS_CFG_IT_MOD 240 +#define IDS_CFG_IT_APP 241 +#define IDS_CFG_IT_NONE 242 +#define IDS_CFG_NODESC 243 +#define IDS_CFG_P_DELCNFT 244 +#define IDS_CFG_P_DELCNFM 245 +#define IDS_CFG_P_DELCNFS 246 +#define IDS_CFG_P_DELNDEP 247 +#define IDS_CFG_P_ENBCNFT 248 +#define IDS_CFG_P_ENBCNFM 249 +#define IDS_PISTATE_FAILINIT 250 +#define IDS_CFG_P_UNRCNFT 251 +#define IDS_CFG_P_UNRCNFM 252 +#define IDS_CFG_P_UNRCNFS 253 +#define IDS_ACTION_LAYOUT_CUST 254 +#define IDS_APR_HEADER_TEXT 255 +#define IDS_APR_HEADER_TEXT_BOLD 256 +#define IDS_APR_TEXT 257 +#define IDS_APR_TEXT_BOLD 258 +#define IDS_APR_SAMPLE_TEXT_NORMAL 259 +#define IDS_CFG_APPEAR_SHORT 260 +#define IDS_CFG_APPEAR_LONG 261 +#define IDS_ACTION_OPT_APPEAR 262 +#define IDS_APR_SAMPLE_TEXT_SEL 263 +#define IDS_CFG_IDNAME_INV 264 +#define IDS_CFG_IDNAME_PRB 265 +#define IDS_CFG_IDNAME_EXT 266 +#define IDS_CFG_IDNAME_CCR 267 +#define IDS_CFG_IDNAME_CCC 268 +#define IDS_CFG_LOGF_CS 269 +#define IDS_CFG_LOGF_CSR 270 +#define IDS_ACTIONT_PROPERTIES 271 +#define IDS_ACTIONT_EXIT 272 +#define IDS_ACTIONT_SET_DEF_ID 273 +#define IDS_ACTIONT_PASSWD_ID 274 +#define IDS_ACTIONT_NEW_CRED 275 +#define IDS_ACTIONT_RENEW_CRED 276 +#define IDS_ACTIONT_DESTROY_CRED 277 +#define IDS_ACTIONT_VIEW_REFRESH 278 +#define IDS_ACTIONT_OPT_IDENTS 279 +#define IDS_ACTIONT_OPT_KHIM 280 +#define IDS_ACTIONT_OPT_NOTIF 281 +#define IDS_ACTIONT_OPT_PLUGINS 282 +#define IDS_ACTIONT_OPT_APPEAR 283 +#define IDS_ACTIONT_HELP_CTX 284 +#define IDS_ACTIONT_IMPORT 285 +#define IDS_NC_FAILED_TITLE_I 286 +#define IDS_NC_PWD_FAILED_TITLE_I 287 +#define IDS_NC_REN_FAILED_TITLE_I 288 +#define IDS_CFG_IDNAME_NON 289 +#define IDS_MENU_DESTROY_CRED 290 +#define IDS_MENU_RENEW_CRED 291 +#define IDS_ACTION_DESTROY_ALL 292 +#define IDS_ACTION_RENEW_ALL 293 +#define IDS_IDACTION_RENEW 294 +#define IDS_IDACTION_DESTROY 295 +#define IDS_CTX_DESTROY_ID 296 +#define IDS_NCN_IDENT_INVALID 297 +#define IDS_NCN_IDENT_CHECKING 298 +#define IDS_NCN_IDENT_UNKNOWN 299 +#define IDS_REMOTE_FAIL 300 +#define IDS_REMOTE_FAIL_TITLE 301 +#define IDS_IDACTION_NEW 302 +#define IDS_IDACTIONT_NEW 303 +#define IDS_IDACTIONT_RENEW 304 +#define IDS_IDACTIONT_DESTROY 305 +#define IDS_ALERTTYPE_PLUGIN 306 +#define IDS_ALERTTYPE_EXPIRE 307 +#define IDS_ALERTTYPE_RENEWFAIL 308 +#define IDS_ALERTTYPE_ACQUIREFAIL 309 +#define IDS_ALERTTYPE_CHPW 310 +#define IDS_ACTION_LAYOUT_MINI 311 +#define IDS_IDEXPDISP_NOCRED 312 +#define IDS_IDEXPDISP_1CRED 313 +#define IDS_IDEXPDISP_NCRED 314 +#define IDS_CW_DEFAULTTF 315 +#define IDS_CW_TYPEF 316 +#define IDS_CW_EXPIREF 317 +#define IDS_CW_EXPIRED 318 +#define IDS_IDACTIONT_SETDEF 319 +#define IDS_IDACTION_SETDEF 320 +#define IDS_ACTION_VIEW_ALL_IDS 321 +#define IDC_NC_CREDTEXT_LABEL 1009 +#define IDC_NC_CREDTEXT 1012 +#define IDC_NC_HELP 1017 +#define IDC_NC_ADVANCED 1019 +#define IDC_PP_IDNAME 1026 +#define IDC_PP_IDDEF 1027 +#define IDC_PP_IDSEARCH 1028 +#define IDC_PP_PROPLIST 1035 +#define IDC_PP_CPROPLIST 1036 +#define IDC_NC_TPL_ROW 1039 +#define IDC_NC_TPL_PANEL 1040 +#define IDC_NC_TPL_LABEL 1041 +#define IDC_NC_TPL_INPUT 1042 +#define IDC_NC_TPL_LABEL_LG 1043 +#define IDC_NC_TPL_INPUT_LG 1044 +#define IDC_NC_TPL_ROW_LG 1045 +#define IDC_CFG_NODELIST 1045 +#define IDAPPLY 1048 +#define IDC_CFG_TITLE 1050 +#define IDC_CFG_PANE 1051 +#define IDC_NOTIF_MONITOR 1053 +#define IDC_PP_DUMMY 1054 +#define IDC_NOTIF_RENEW 1055 +#define IDC_NOTIF_RENEW_THR 1056 +#define IDC_NOTIF_WARN1 1057 +#define IDC_NOTIF_WARN1_THR 1058 +#define IDC_NOTIF_WARN2 1059 +#define IDC_NOTIF_WARN2_THR 1060 +#define IDC_CFG_KEEPRUNNING 1061 +#define IDC_CFG_STARTUP_GROUP 1062 +#define IDC_CFG_AUTOSTART 1063 +#define IDC_CFG_AUTOIMPORT 1064 +#define IDC_CFG_AUTOINIT 1065 +#define IDC_CFG_OTHER 1066 +#define IDC_CFG_MONITOR 1069 +#define IDC_CFG_STICKY 1070 +#define IDC_CFG_RENEW 1075 +#define IDC_CFG_REMOVE 1076 +#define IDC_CFG_TAB 1077 +#define IDC_CFG_TARGET 1078 +#define IDC_CFG_PLUGINS 1079 +#define IDC_CFG_DESC 1084 +#define IDC_CFG_LBL_STATE 1085 +#define IDC_CFG_STATE 1086 +#define IDC_CFG_LBL_DEPS 1087 +#define IDC_CFG_DEPS 1088 +#define IDC_CFG_DISABLE 1089 +#define IDC_CFG_ENABLE 1090 +#define IDC_CFG_LBL_MOD 1092 +#define IDC_CFG_MODULE 1093 +#define IDC_CFG_LBL_VEN 1094 +#define IDC_CFG_VENDOR 1095 +#define IDC_CFG_REGISTER 1097 +#define IDC_CFG_NETDETECT 1098 +#define IDC_PP_STICKY 1099 +#define IDC_PRODUCT 1100 +#define IDC_COPYRIGHT 1101 +#define IDC_BUILDINFO 1102 +#define IDC_MODULES 1103 +#define IDC_PP_CONFIG 1104 +#define IDC_CFG_UNREGISTER 1107 +#define IDC_CFG_VERSION 1108 +#define IDC_CFG_ICON 1109 +#define IDC_CFG_LOGTOFILE 1110 +#define IDC_CFG_LOGPATH 1111 +#define IDC_NOTIF_HALFLIFE 1112 +#define IDC_CFG_DESTROYALL 1113 +#define IDC_CFG_SAMPLE_NORMAL 1123 +#define IDC_CFG_REVERT 1127 +#define IDC_CFG_FONTS 1128 +#define IDC_CFG_SAMPLE_BOLD 1129 +#define IDC_CFG_SIZE 1130 +#define IDC_CFG_BOLD 1131 +#define IDC_CFG_ITALICS 1132 +#define IDC_CFG_ADDIDENT 1133 +#define IDC_SM_CTL 1134 +#define IDC_CFG_SHOWLOG 1135 +#define IDC_MED_CTL 1135 +#define IDC_LG_CTL 1136 +#define IDC_SM_LBL 1137 +#define IDC_MED_LBL 1138 +#define IDC_LG_LBL 1139 +#define IDC_CFG_NOTACTION 1141 +#define IDC_CFG_NOTACT_STATIC 1142 +#define IDC_NC_BASIC 1143 +#define IDC_CONTENT 1144 +#define IDA_ACTIVATE_MENU 40003 +#define IDA_UP 40004 +#define IDA_DOWN 40005 +#define IDA_LEFT 40006 +#define IDA_RIGHT 40007 +#define IDA_ESC 40008 +#define IDA_ENTER 40009 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 214 +#define _APS_NEXT_COMMAND_VALUE 40010 +#define _APS_NEXT_CONTROL_VALUE 1145 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/identity/ui/statusbar.c b/krb5-1-6/src/windows/identity/ui/statusbar.c new file mode 100644 index 000000000..b785dfdd0 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/statusbar.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#ifdef DEBUG +#include<assert.h> +#endif + +khm_statusbar_part khm_statusbar_parts[] = { + {KHUI_SBPART_INFO, 0, KHUI_SB_WTYPE_FILLER, NULL}, + {KHUI_SBPART_NOTICE, 40, KHUI_SB_WTYPE_RELATIVE, NULL}, +#if 0 + /* Not implemented. This was originally intended to provide + location information. */ + {KHUI_SBPART_LOC, 40, KHUI_SB_WTYPE_ABSOLUTE, NULL} +#endif +}; + +int khm_n_statusbar_parts = sizeof(khm_statusbar_parts) / sizeof(khm_statusbar_part); + +HWND khm_hwnd_statusbar = NULL; + +LRESULT +khm_statusbar_notify(LPNMHDR nmhdr) { + LPNMMOUSE pnmm; + + switch(nmhdr->code) { + case NM_CLICK: + case NM_DBLCLK: + pnmm = (LPNMMOUSE) nmhdr; + + if (pnmm->dwItemSpec >= (DWORD) khm_n_statusbar_parts) + return TRUE; + + if (khm_statusbar_parts[pnmm->dwItemSpec].id == KHUI_SBPART_NOTICE) { + /* means, show next notification */ + kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW_QUEUED, 0, 0); + } + + return TRUE; + } + + return FALSE; +} + +void +khui_statusbar_set_parts(HWND parent) { + int i; + int fillerwidth; + int staticwidth; + int lastx; + int width; + RECT r; + INT * parts; + + GetClientRect(parent, &r); + width = r.right - r.left; + + /* calculate fillerwidth and staticwidth */ + staticwidth = 0; + for(i=0;i<khm_n_statusbar_parts;i++) { + if(khm_statusbar_parts[i].wtype == KHUI_SB_WTYPE_ABSOLUTE) { + staticwidth += khm_statusbar_parts[i].width; + } else if(khm_statusbar_parts[i].wtype == KHUI_SB_WTYPE_RELATIVE) { + staticwidth += (khm_statusbar_parts[i].width * width) / 100; + } + } + + fillerwidth = width - staticwidth; + + parts = PMALLOC(sizeof(INT) * khm_n_statusbar_parts); + + lastx = 0; + for(i=0;i<khm_n_statusbar_parts;i++) { + int w = 0; + switch(khm_statusbar_parts[i].wtype) { + case KHUI_SB_WTYPE_ABSOLUTE: + w = khm_statusbar_parts[i].width; + break; + + case KHUI_SB_WTYPE_RELATIVE: + w = (khm_statusbar_parts[i].width * width) / 100; + break; + + case KHUI_SB_WTYPE_FILLER: + w = fillerwidth; + break; + + default: + w = 0; +#ifdef DEBUG + assert(FALSE); +#endif + } + lastx += w; + + if(i==khm_n_statusbar_parts - 1) + parts[i] = -1; + else + parts[i] = lastx; + } + + SendMessage( + khm_hwnd_statusbar, + SB_SETPARTS, + khm_n_statusbar_parts, + (LPARAM) parts); + + PFREE(parts); +} + +void khm_create_statusbar(HWND parent) { + HWND hwsb; + + hwsb = CreateWindowEx( + 0, + STATUSCLASSNAME, + NULL, + SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE, + 0,0,0,0, + parent, + NULL, + khm_hInstance, + NULL); + + if(!hwsb) + return; + + khm_hwnd_statusbar = hwsb; + + khui_statusbar_set_parts(parent); + + kmq_post_message(KMSG_ALERT, KMSG_ALERT_CHECK_QUEUE, 0, 0); +} + +void khm_update_statusbar(HWND parent) { + MoveWindow(khm_hwnd_statusbar, 0, 0, 0, 0, TRUE); + khui_statusbar_set_parts(parent); +} + +int sb_find_index(int id) { + int i; + + for(i=0;i<khm_n_statusbar_parts;i++) { + if(khm_statusbar_parts[i].id == id) + return i; + } + + return -1; +} + +void khm_statusbar_set_part(int id, HICON icon, wchar_t * text) { + int idx; + + if (!khm_hwnd_statusbar) + return; + + idx = sb_find_index(id); + if(idx < 0) + return; + + if (khm_statusbar_parts[idx].hIcon != NULL) { + DestroyIcon(khm_statusbar_parts[idx].hIcon); + khm_statusbar_parts[idx].hIcon = NULL; + } + + if (icon) { + khm_statusbar_parts[idx].hIcon = CopyImage(icon, IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_COPYFROMRESOURCE); + } + + SendMessage(khm_hwnd_statusbar, + SB_SETICON, + idx, + (LPARAM) (khm_statusbar_parts[idx].hIcon ? khm_statusbar_parts[idx].hIcon:icon)); + + SendMessage(khm_hwnd_statusbar, + SB_SETTEXT, + idx, + (LPARAM) text); +} + + diff --git a/krb5-1-6/src/windows/identity/ui/statusbar.h b/krb5-1-6/src/windows/identity/ui/statusbar.h new file mode 100644 index 000000000..7b79f69b0 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/statusbar.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_STATUSBAR_H +#define __KHIMAIRA_STATUSBAR_H + +typedef struct khm_statusbar_part_t { + int id; + int width; + int wtype; /* one of KHUI_SB_WTYPE_* */ + HICON hIcon; +} khm_statusbar_part; + +#define KHUI_SB_WTYPE_RELATIVE 1 +#define KHUI_SB_WTYPE_ABSOLUTE 2 +#define KHUI_SB_WTYPE_FILLER 4 + +/* statusbar parts */ +#define KHUI_SBPART_INFO 1 +#define KHUI_SBPART_NOTICE 2 +#define KHUI_SBPART_LOC 3 + +extern HWND khm_hwnd_statusbar; +extern khm_statusbar_part khm_statusbar_parts[]; +extern int khm_n_statusbar_parts; + +void khm_create_statusbar(HWND p); +void khm_update_statusbar(HWND parent); +void khm_statusbar_set_part(int id, HICON icon, wchar_t * text); +LRESULT khm_statusbar_notify(LPNMHDR nmhdr); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/taskbar.c b/krb5-1-6/src/windows/identity/ui/taskbar.c new file mode 100644 index 000000000..48a575f64 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/taskbar.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> + +#define COBJMACROS + +#include<shobjidl.h> + +#ifdef DEBUG +#include<assert.h> +#endif + +ITaskbarList *itbl = NULL; + +void +khm_init_taskbar_funcs(void) { + HRESULT hr = NOERROR; + + hr = CoCreateInstance(&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, + &IID_ITaskbarList, &itbl); + +#ifdef DEBUG + assert(itbl != NULL); +#endif + + if (itbl) { + hr = ITaskbarList_HrInit(itbl); +#ifdef DEBUG + assert(hr == NOERROR); +#endif + } +} + +void +khm_exit_taskbar_funcs(void) { + if (itbl) { + ITaskbarList_Release(itbl); + } +} + +void +khm_taskbar_add_window(HWND hwnd) { + HRESULT hr = NOERROR; + + if (itbl) { + hr = ITaskbarList_AddTab(itbl, hwnd); +#ifdef DEBUG + assert(hr == NOERROR); +#endif + } +} + +void +khm_taskbar_remove_window(HWND hwnd) { + HRESULT hr = NOERROR; + + if (itbl) { + hr = ITaskbarList_DeleteTab(itbl, hwnd); +#ifdef DEBUG + assert(hr == NOERROR); +#endif + } +} diff --git a/krb5-1-6/src/windows/identity/ui/taskbar.h b/krb5-1-6/src/windows/identity/ui/taskbar.h new file mode 100644 index 000000000..32adf5c29 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/taskbar.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef NETIDMGR_TASKBAR_H +#define NETIDMGR_TASKBAR_H + +void khm_init_taskbar_funcs(void); + +void khm_exit_taskbar_funcs(void); + +void khm_taskbar_add_window(HWND hwnd); + +void khm_taskbar_remove_window(HWND hwnd); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/timer.c b/krb5-1-6/src/windows/identity/ui/timer.c new file mode 100644 index 000000000..9a270c3ee --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/timer.c @@ -0,0 +1,1015 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +/* The minimum half time interval is 60 seconds*/ +#define TT_MIN_HALFLIFE_INTERVAL 60 + +/* as above, in FILETIME units of 100ns */ +#define FT_MIN_HALFLIFE_INTERVAL (TT_MIN_HALFLIFE_INTERVAL * 10000000i64) + +/* in seconds */ +#if 0 +khm_int32 khui_timeout_warn = KHUI_DEF_TIMEOUT_WARN; +khm_int32 khui_timeout_crit = KHUI_DEF_TIMEOUT_CRIT; +khm_int32 khui_timeout_renew = KHUI_DEF_TIMEOUT_RENEW; + +khm_boolean khui_do_renew = TRUE; +khm_boolean khui_do_warn = TRUE; +khm_boolean khui_do_crit = TRUE; +#endif + +khui_timer_event * khui_timers = NULL; +khm_size khui_n_timers = 0; +khm_size khui_nc_timers = 0; + +CRITICAL_SECTION cs_timers; + +/********************************************************************* + Timers + *********************************************************************/ + + +#define KHUI_TIMER_ALLOC_INCR 16 + +void +khm_timer_init(void) { +#ifdef DEBUG + assert(khui_timers == NULL); +#endif + + khui_nc_timers = KHUI_TIMER_ALLOC_INCR; + khui_n_timers = 0; + khui_timers = PMALLOC(sizeof(*khui_timers) * khui_nc_timers); + +#ifdef DEBUG + assert(khui_timers != NULL); +#endif + + InitializeCriticalSection(&cs_timers); +} + +void +khm_timer_exit(void) { + EnterCriticalSection(&cs_timers); + + if (khui_timers) + PFREE(khui_timers); + khui_timers = NULL; + khui_n_timers = 0; + khui_nc_timers = 0; + + LeaveCriticalSection(&cs_timers); + DeleteCriticalSection(&cs_timers); +} + +/* called with cs_timers held */ +static void +tmr_fire_timer(void) { + int i; + khm_int64 curtime; + khm_int64 err; + khm_int64 next_event; + int tmr_count[KHUI_N_TTYPES]; + khm_int64 tmr_offset[KHUI_N_TTYPES]; + int t; + khm_handle eff_ident = NULL; + khui_timer_type eff_type = 0; /* meaningless */ + int fire_count = 0; + FILETIME ft; + + _begin_task(0); + _report_cs0(KHERR_DEBUG_1, L"Checking for expired timers"); + _describe(); + + TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR_SMALL, &ft); + err = FtToInt(&ft); + GetSystemTimeAsFileTime(&ft); + curtime = FtToInt(&ft); + + next_event = 0; + + ZeroMemory(tmr_count, sizeof(tmr_count)); + ZeroMemory(tmr_offset, sizeof(tmr_offset)); + + for (i=0; i < (int) khui_n_timers; i++) { + if (!(khui_timers[i].flags & + (KHUI_TE_FLAG_STALE | KHUI_TE_FLAG_EXPIRED)) && + khui_timers[i].type != KHUI_TTYPE_ID_MARK && + khui_timers[i].expire < curtime + err) { + + _report_cs3(KHERR_DEBUG_1, L"Expiring timer index=%1!d!, type=%2!d!, key=%3!p!", + _int32(i), _int32(khui_timers[i].type), + _cptr(khui_timers[i].key)); + + t = khui_timers[i].type; + + switch(t) { + case KHUI_TTYPE_ID_RENEW: + _report_cs1(KHERR_DEBUG_1, L"Renewing identity %1!p!", + _cptr(khui_timers[i].key)); + khm_cred_renew_identity(khui_timers[i].key); + khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED; + break; + + case KHUI_TTYPE_CRED_RENEW: + /* the equivalence threshold for setting the timer is + a lot larger than what we are testing for here + (KHUI_TIMEEQ_ERROR vs KHUI_TIMEEQ_ERROR_SMALL) so + we assume that it is safe to trigger a renew_cred + call here without checking if there's an imminent + renew_identity call. */ + _report_cs1(KHERR_DEBUG_1, L"Renewing credential %1!p!", + _cptr(khui_timers[i].key)); + khm_cred_renew_cred(khui_timers[i].key); + khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED; + break; + + default: + if (t < KHUI_N_TTYPES) { + tmr_count[t]++; + if (tmr_offset[t] == 0 || + tmr_offset[t] > khui_timers[i].offset) + tmr_offset[t] = khui_timers[i].offset; + if (next_event == 0 || + next_event > + khui_timers[i].expire + khui_timers[i].offset) + next_event = khui_timers[i].expire + + khui_timers[i].offset; + + if (eff_ident == NULL && + (t == KHUI_TTYPE_ID_EXP || + t == KHUI_TTYPE_ID_CRIT || + t == KHUI_TTYPE_ID_WARN)) { + /* we don't need a hold since we will be done + with the handle before the marker is + expired (the marker is the timer with the + KHUI_TTYPE_ID_MARK which contains a held + handle and is not really a timer.) */ + eff_ident = khui_timers[i].key; + eff_type = t; + } + + fire_count++; + + khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED; + } + else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } + } + } + + /* See if we have anything to do */ + if (next_event == 0) + return; + else { + wchar_t fmt[128]; + wchar_t wtime[128]; + wchar_t wmsg[256]; + wchar_t wtitle[64]; + khm_int64 second; + khui_alert * alert = NULL; + + khm_size cb; + + next_event -= curtime; + + /* Due to measurement errors we may be slightly off on our + next_event calculation which shows up as '4 mins 59 + seconds' instead of '5 mins' and so on when converting to a + string. So we add half a second to make the message + neater. */ + TimetToFileTimeInterval(1, &ft); + second = FtToInt(&ft); + next_event += second / 2; + + cb = sizeof(wtime); + ft = IntToFt(next_event); + FtIntervalToString(&ft, + wtime, + &cb); + + if (fire_count == 1 && + eff_ident != NULL && + (eff_type == KHUI_TTYPE_ID_EXP || + eff_type == KHUI_TTYPE_ID_CRIT || + eff_type == KHUI_TTYPE_ID_WARN)) { + + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + + cb = sizeof(idname); + kcdb_identity_get_name(eff_ident, idname, &cb); + + if (next_event < second) { + LoadString(khm_hInstance, IDS_WARN_EXPIRED_ID, + fmt, ARRAYLENGTH(fmt)); + + StringCbPrintf(wmsg, sizeof(wmsg), fmt, idname); + } else { + LoadString(khm_hInstance, IDS_WARN_EXPIRE_ID, + fmt, ARRAYLENGTH(fmt)); + + StringCbPrintf(wmsg, sizeof(wmsg), fmt, idname, wtime); + } + } else { + if (next_event < second) { + LoadString(khm_hInstance, IDS_WARN_EXPIRED, + wmsg, ARRAYLENGTH(wmsg)); + } else { + LoadString(khm_hInstance, IDS_WARN_EXPIRE, + fmt, ARRAYLENGTH(fmt)); + + StringCbPrintf(wmsg, sizeof(wmsg), fmt, wtime); + } + } + + LoadString(khm_hInstance, IDS_WARN_TITLE, + wtitle, ARRAYLENGTH(wtitle)); + + khui_alert_create_simple(wtitle, wmsg, KHERR_WARNING, &alert); + khui_alert_set_flags(alert, + KHUI_ALERT_FLAG_REQUEST_BALLOON | KHUI_ALERT_FLAG_DISPATCH_CMD, + KHUI_ALERT_FLAG_REQUEST_BALLOON | KHUI_ALERT_FLAG_DISPATCH_CMD); + + if (eff_ident != NULL) { + khm_int32 cmd; + + cmd = khm_get_identity_new_creds_action(eff_ident); + + if (cmd) { + khui_alert_add_command(alert, cmd); + khui_alert_add_command(alert, KHUI_PACTION_CLOSE); + } + } + + khui_alert_show(alert); + khui_alert_release(alert); + } + + _end_task(); + +} + +void +khm_timer_fire(HWND hwnd) { + EnterCriticalSection(&cs_timers); + tmr_fire_timer(); + LeaveCriticalSection(&cs_timers); + + khm_timer_refresh(hwnd); +} + +static int +tmr_update(khm_handle key, khui_timer_type type, __int64 expire, + __int64 offset, void * data, khm_boolean reinstate) { + int i; + wchar_t name[KCDB_MAXCCH_NAME]; + wchar_t tstamp[128]; + wchar_t *type_str = NULL; + SYSTEMTIME st; + FILETIME ft; + FILETIME ftl; + khm_size cb; + + switch(type) { + case KHUI_TTYPE_ID_MARK: + type_str = L"marker"; + break; + + case KHUI_TTYPE_CRED_WARN: + case KHUI_TTYPE_ID_WARN: + type_str = L"warning"; + break; + + case KHUI_TTYPE_CRED_CRIT: + case KHUI_TTYPE_ID_CRIT: + type_str = L"critical"; + break; + + case KHUI_TTYPE_CRED_EXP: + case KHUI_TTYPE_ID_EXP: + type_str = L"expiry"; + break; + + case KHUI_TTYPE_CRED_RENEW: + case KHUI_TTYPE_ID_RENEW: + type_str = L"renew"; + break; + } + + ft = IntToFt(expire); + FileTimeToLocalFileTime(&ft, &ftl); + FileTimeToSystemTime(&ftl, &st); + StringCbPrintf(tstamp, sizeof(tstamp), + L"%d-%d-%d %d:%d:%d", + st.wYear, st.wMonth, st.wDay, + st.wHour, st.wMinute, st.wSecond); + + cb = sizeof(name); name[0] = L'\0'; + if (type_str == NULL) { + + _report_cs2(KHERR_DEBUG_1, + L"Updating uknown timer of type %1!d! exp(%2!s!)", + _int32(type), + _cstr(tstamp)); + _resolve(); + + } else if (type == KHUI_TTYPE_ID_MARK || + type == KHUI_TTYPE_ID_WARN || + type == KHUI_TTYPE_ID_CRIT || + type == KHUI_TTYPE_ID_EXP || + type == KHUI_TTYPE_ID_RENEW) { + + kcdb_identity_get_name(key, name, &cb); + _report_cs3(KHERR_DEBUG_1, + L"Updating identity %1!s! timer for %2!s! exp(%3!s!)", + _cstr(type_str), + _cstr(name), + _cstr(tstamp)); + _resolve(); + + } else if (type == KHUI_TTYPE_CRED_RENEW || + type == KHUI_TTYPE_CRED_WARN || + type == KHUI_TTYPE_CRED_CRIT || + type == KHUI_TTYPE_CRED_EXP) { + + kcdb_cred_get_name(key, name, &cb); + _report_cs3(KHERR_DEBUG_1, + L"Updating credential %1!s! timer for %2!s! exp(%3!s!)", + _cstr(type_str), + _cstr(name), + _cstr(tstamp)); + _resolve(); + + } + + for (i=0; i < (int) khui_n_timers; i++) { + if (khui_timers[i].key == key && + khui_timers[i].type == type) + break; + } + + if (i >= (int) khui_n_timers) { + i = (int) khui_n_timers; + + if (i >= (int) khui_nc_timers) { + khui_timer_event * nt; +#ifdef DEBUG + assert(khui_timers); +#endif + khui_nc_timers = UBOUNDSS(i+1, KHUI_TIMER_ALLOC_INCR, + KHUI_TIMER_ALLOC_INCR); + nt = PMALLOC(sizeof(*nt) * khui_nc_timers); +#ifdef DEBUG + assert(nt); +#endif + memcpy(nt, khui_timers, sizeof(*nt) * khui_n_timers); + + PFREE(khui_timers); + khui_timers = nt; + } + + khui_timers[i].key = key; + khui_timers[i].type = type; + khui_timers[i].flags = 0; + khui_n_timers++; + } + + khui_timers[i].expire = expire; + khui_timers[i].offset = offset; + khui_timers[i].data = data; + + khui_timers[i].flags &= ~KHUI_TE_FLAG_STALE; + if (reinstate) + khui_timers[i].flags &= ~KHUI_TE_FLAG_EXPIRED; + + return i; +} + +/* called with cs_timers held */ +static int +tmr_find(khm_handle key, khui_timer_type type, + khm_int32 and_flags, khm_int32 eq_flags) { + int i; + + eq_flags &= and_flags; + + for (i=0; i < (int) khui_n_timers; i++) { + if (khui_timers[i].key == key && + khui_timers[i].type == type && + (khui_timers[i].flags & and_flags) == eq_flags) + break; + } + + if (i < (int) khui_n_timers) + return i; + else + return -1; +} + +/* called with cs_timers held. */ +static FILETIME +tmr_next_halflife_timeout(int idx, FILETIME * issue, FILETIME * expire) { + FILETIME lifetime; + FILETIME current; + FILETIME ret; + + khm_int64 ilife; + khm_int64 icurrent; + khm_int64 iexpire; + + khm_int64 iret; + + GetSystemTimeAsFileTime(&current); + + /* wha?? */ + if (CompareFileTime(issue, expire) >= 0) + return current; + + lifetime = FtSub(expire, issue); + icurrent = FtToInt(&current); + iexpire = FtToInt(expire); + + ilife = FtToInt(&lifetime); + + while(ilife / 2 > FT_MIN_HALFLIFE_INTERVAL) { + ilife /= 2; + + /* is this the next renewal time? */ + if (iexpire - ilife > icurrent) { + if (idx >= 0 && + khui_timers[idx].expire == iexpire - ilife && + (khui_timers[idx].flags & KHUI_TE_FLAG_EXPIRED)) { + + /* if this renewal time has already been triggered + (note that when the timer fires, it also fires all + events that are within a few seconds of the current + time) then we need to set the alarm for the next + slot down the line. */ + + continue; + + } else { + break; + } + } + } + + iret = iexpire - ilife; + + ret = IntToFt(iret); + + /* if the previous renew timer had fired, we need to mark it as + not expired. However, we leave it to the caller to update the + actual timer and mark it as not stale. */ + if (idx >= 0 && + khui_timers[idx].expire < iret) { + + khui_timers[idx].flags &= ~KHUI_TE_FLAG_EXPIRED; + khui_timers[idx].expire = iret; + } + + return ret; +} + +/* called with cs_timers held. Called once for each credential in the + root credentials set. */ +static khm_int32 KHMAPI +tmr_cred_apply_proc(khm_handle cred, void * rock) { + khm_handle ident = NULL; + int mark_idx; + int idx; + FILETIME ft_expiry; + FILETIME ft_current; + FILETIME ft_creinst; + FILETIME ft_cred_expiry; + FILETIME ft_cred_issue; + FILETIME ft_issue; + FILETIME ft; + FILETIME fte; + FILETIME ft_reinst; + khm_size cb; + wchar_t wname[KCDB_MAXCCH_NAME]; + + cb = sizeof(wname); + wname[0] = L'\0'; + kcdb_cred_get_name(cred, wname, &cb); + + _report_cs1(KHERR_DEBUG_1, L"Looking at cred [%1!s!]", + _cstr(wname)); + _resolve(); + + kcdb_cred_get_identity(cred, &ident); +#ifdef DEBUG + assert(ident); +#endif + + /* now get the expiry for the identity*/ + cb = sizeof(ft_expiry); + if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, + NULL, + &ft_expiry, &cb))) { + + /* failing which, we get the expiry for this credential */ + cb = sizeof(ft_expiry); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE, + NULL, + &ft_expiry, &cb))) { + /* we don't have an expiry time to work with */ + _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. No expiry time", + _cstr(wname)); + _resolve(); + + kcdb_identity_release(ident); + return KHM_ERROR_SUCCESS; + } else { + /* and the time of issue */ + cb = sizeof(ft_issue); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, + NULL, &ft_issue, &cb))) + ZeroMemory(&ft_issue, sizeof(ft_issue)); + } + + } else { + /* also try to get the time of issue. */ + cb = sizeof(ft_issue); + if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE, + NULL, &ft_issue, &cb))) + /* if we fail, we just zero out the time of issue and + failover to using the threshold value to set the expiry + timer instead of the half life algorithm. */ + ZeroMemory(&ft_issue, sizeof(ft_issue)); + } + + /* and the current time */ + GetSystemTimeAsFileTime(&ft_current); + + TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft_reinst); + + ft_creinst = FtAdd(&ft_current, &ft_reinst); + + mark_idx = tmr_find(ident, KHUI_TTYPE_ID_MARK, 0, 0); + + if (mark_idx < 0) { + mark_idx = tmr_update(ident, KHUI_TTYPE_ID_MARK, 0, 0, 0, FALSE); + kcdb_identity_hold(ident); +#ifdef DEBUG + assert(mark_idx >= 0); +#endif + khui_timers[mark_idx].flags |= KHUI_TE_FLAG_STALE; + } + + if (khui_timers[mark_idx].flags & KHUI_TE_FLAG_STALE) { + /* first time we are touching this */ + khm_handle csp_cw = NULL; + khm_handle csp_id = NULL; + khm_int32 rv; + khm_int32 t; + khm_boolean do_warn = TRUE; + khm_boolean do_crit = TRUE; + khm_boolean do_renew = TRUE; + khm_boolean do_halflife = TRUE; + khm_boolean renew_done = FALSE; + khm_boolean monitor = TRUE; + khm_int32 to_warn = KHUI_DEF_TIMEOUT_WARN; + khm_int32 to_crit = KHUI_DEF_TIMEOUT_CRIT; + khm_int32 to_renew = KHUI_DEF_TIMEOUT_RENEW; + + if (CompareFileTime(&ft_expiry, &ft_current) < 0) + /* already expired */ + goto _done_with_ident; + + rv = khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, + &csp_cw); + + assert(KHM_SUCCEEDED(rv)); + + rv = kcdb_identity_get_config(ident, KHM_PERM_READ, &csp_id); + if (KHM_SUCCEEDED(rv)) { + khc_shadow_space(csp_id, csp_cw); + khc_close_space(csp_cw); + } else { + csp_id = csp_cw; + } + csp_cw = NULL; + + rv = khc_read_int32(csp_id, L"Monitor", &t); + if (KHM_SUCCEEDED(rv)) + monitor = t; + + rv = khc_read_int32(csp_id, L"AllowWarn", &t); + if (KHM_SUCCEEDED(rv)) + do_warn = t; + + rv = khc_read_int32(csp_id, L"AllowCritical", &t); + if (KHM_SUCCEEDED(rv)) + do_crit = t; + + rv = khc_read_int32(csp_id, L"AllowAutoRenew", &t); + if (KHM_SUCCEEDED(rv)) + do_renew = t; + + rv = khc_read_int32(csp_id, L"RenewAtHalfLife", &t); + if (KHM_SUCCEEDED(rv)) + do_halflife = t; + + rv = khc_read_int32(csp_id, L"WarnThreshold", &t); + if (KHM_SUCCEEDED(rv)) + to_warn = t; + + rv = khc_read_int32(csp_id, L"CriticalThreshold", &t); + if (KHM_SUCCEEDED(rv)) + to_crit = t; + + rv = khc_read_int32(csp_id, L"AutoRenewThreshold", &t); + if (KHM_SUCCEEDED(rv)) + to_renew = t; + + khc_close_space(csp_id); + + if (monitor && do_renew) { + int prev; + + TimetToFileTimeInterval(to_renew, &ft); + + prev = + tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0); + + if (do_halflife && (ft_issue.dwLowDateTime != 0 || + ft_issue.dwHighDateTime != 0)) + fte = tmr_next_halflife_timeout(prev, &ft_issue, &ft_expiry); + else + fte = FtSub(&ft_expiry, &ft); + + /* we set off a renew notification immediately if the + renew threshold has passed but a renew was never sent. + This maybe because that NetIDMgr was started at the + last minute, or because for some reason the renew timer + could not be triggered earlier. */ + + if (CompareFileTime(&fte, &ft_current) > 0 || + prev == -1 || + !(khui_timers[prev].flags & KHUI_TE_FLAG_EXPIRED)) { + + if (CompareFileTime(&fte, &ft_current) < 0) + fte = ft_current; + + tmr_update(ident, KHUI_TTYPE_ID_RENEW, + FtToInt(&fte), FtToInt(&ft), 0, + CompareFileTime(&fte,&ft_creinst) > 0); + renew_done = TRUE; + + } else { + + /* special case. If the renew timer was in the past + and it was expired, then we retain the record as + long as the credentials are around. If the renewal + failed we don't want to automatically retry + everytime we check the timers. */ + + tmr_update(ident, KHUI_TTYPE_ID_RENEW, + FtToInt(&fte), FtToInt(&ft), 0, FALSE); + + } + } + + if (monitor && do_warn && !renew_done) { + + TimetToFileTimeInterval(to_warn, &ft); + fte = FtSub(&ft_expiry, &ft); + + if (CompareFileTime(&fte, &ft_current) > 0) + tmr_update(ident, KHUI_TTYPE_ID_WARN, + FtToInt(&fte), FtToInt(&ft), 0, + CompareFileTime(&fte, &ft_creinst) > 0); + } + + if (monitor && do_crit && !renew_done) { + TimetToFileTimeInterval(to_crit, &ft); + fte = FtSub(&ft_expiry, &ft); + + if (CompareFileTime(&fte, &ft_current) > 0) + tmr_update(ident, KHUI_TTYPE_ID_CRIT, + FtToInt(&fte), FtToInt(&ft), 0, + CompareFileTime(&fte, &ft_creinst) > 0); + } + + if (monitor && !renew_done) { + if (CompareFileTime(&ft_expiry, &ft_current) > 0) + tmr_update(ident, KHUI_TTYPE_ID_EXP, + FtToInt(&ft_expiry), 0, 0, + CompareFileTime(&fte, &ft_creinst) > 0); + } + + _done_with_ident: + khui_timers[mark_idx].flags &= ~KHUI_TE_FLAG_STALE; + } + + cb = sizeof(ft_cred_expiry); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE, + NULL, + &ft_cred_expiry, + &cb))) { + _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. Can't lookup cred expiry", + _cstr(wname)); + _resolve(); + goto _cleanup; + } + + cb = sizeof(ft_cred_issue); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, + NULL, + &ft_cred_issue, + &cb))) { + + ZeroMemory(&ft_cred_issue, sizeof(ft_cred_issue)); + + } + + TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft); + + { + /* if the credential has a longer lifetime than the identity, + or it expires within KHUI_TIMEEQ_ERROR seconds of the + identity, then we don't need to set any alerts for this + credential. */ + + FILETIME ft_delta; + + ft_delta = FtSub(&ft_expiry, &ft_cred_expiry); + + if (CompareFileTime(&ft_cred_expiry, &ft_expiry) >= 0 || + CompareFileTime(&ft_delta, &ft) < 0) { + + _report_cs1(KHERR_DEBUG_1, + L"Skipping credential [%1!s!]. The expiry time is too close to the identity expiry.", + _cstr(wname)); + _resolve(); + goto _cleanup; + } + } + + if ((idx = tmr_find(ident, KHUI_TTYPE_ID_WARN, 0, 0)) >= 0 && + !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) { + + fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset); + if (CompareFileTime(&fte, &ft_current) > 0) { + tmr_update(cred, KHUI_TTYPE_CRED_WARN, + FtToInt(&fte), + khui_timers[idx].offset, 0, + CompareFileTime(&fte, &ft_creinst) > 0); + kcdb_cred_hold(cred); + } + } + + if ((idx = tmr_find(ident, KHUI_TTYPE_ID_CRIT, 0, 0)) >= 0 && + !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) { + + fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset); + if (CompareFileTime(&fte, &ft_current) > 0) { + tmr_update(cred, KHUI_TTYPE_CRED_CRIT, + FtToInt(&fte), + khui_timers[idx].offset, 0, + CompareFileTime(&fte, &ft_creinst) > 0); + kcdb_cred_hold(cred); + } + } + + if ((idx = tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0)) >= 0 && + !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) { + + int cidx = tmr_find(cred, KHUI_TTYPE_CRED_RENEW, 0, 0); + + if (ft_cred_issue.dwLowDateTime == 0 && + ft_cred_issue.dwHighDateTime == 0) { + fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset); + /* a special case, for a credential whose remaining + lifetime is less than the offset, we try half life on + the current time and the expiry. */ + if (CompareFileTime(&fte, &ft_current) <= 0 && + CompareFileTime(&ft_current, &ft_expiry) < 0) { + fte = tmr_next_halflife_timeout(cidx, &ft_current, &ft_cred_expiry); +#if 0 + /* now, if we already have a renew timer for this + credential that hasn't expired yet and that is set + for earlier than fte, we let it be. */ + if (cidx >= 0 && + khui_timers[cidx].expire < FtToInt(&fte) && + khui_timers[cidx].expire > FtToInt(&ft_current) && + !(khui_timers[cidx].flags & KHUI_TE_FLAG_EXPIRED)) { + + fte = IntToFt(khui_timers[cidx].expire); + + } +#endif + } + } else { + fte = tmr_next_halflife_timeout(cidx, &ft_cred_issue, &ft_cred_expiry); + } + + if (CompareFileTime(&fte, &ft_current) > 0) { + tmr_update(cred, KHUI_TTYPE_CRED_RENEW, + FtToInt(&fte), + khui_timers[idx].offset, 0, + CompareFileTime(&fte, &ft_creinst) > 0); + kcdb_cred_hold(cred); + } + } + + if ((idx = tmr_find(ident, KHUI_TTYPE_ID_EXP, 0, 0)) >= 0 && + !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) { + + if (CompareFileTime(&ft_cred_expiry, &ft_current) > 0) { + tmr_update(cred, KHUI_TTYPE_CRED_EXP, + FtToInt(&ft_cred_expiry), + 0, 0, + CompareFileTime(&ft_cred_expiry, &ft_creinst) > 0); + } + } + + _cleanup: + + if (ident) + kcdb_identity_release(ident); + + return KHM_ERROR_SUCCESS; +} + +/* called with cs_timers held */ +static void +tmr_purge(void) { + int i, j; + + for (i=0,j=0; i < (int) khui_n_timers; i++) { + if (khui_timers[i].flags & KHUI_TE_FLAG_STALE) { + if (khui_timers[i].type == KHUI_TTYPE_ID_MARK) { + kcdb_identity_release(khui_timers[i].key); +#ifdef DEBUG + { + int idx; + + idx = tmr_find(khui_timers[i].key, + KHUI_TTYPE_ID_CRIT, 0, 0); + assert(idx < 0 || + (khui_timers[idx].flags & + KHUI_TE_FLAG_STALE)); + + idx = tmr_find(khui_timers[i].key, + KHUI_TTYPE_ID_RENEW, 0, 0); + assert(idx < 0 || + (khui_timers[idx].flags & + KHUI_TE_FLAG_STALE)); + + idx = tmr_find(khui_timers[i].key, + KHUI_TTYPE_ID_WARN, 0, 0); + assert(idx < 0 || + (khui_timers[idx].flags & + KHUI_TE_FLAG_STALE)); + + idx = tmr_find(khui_timers[i].key, + KHUI_TTYPE_ID_EXP, 0, 0); + assert(idx < 0 || + (khui_timers[idx].flags & + KHUI_TE_FLAG_STALE)); + } +#endif + } else if (khui_timers[i].type == KHUI_TTYPE_CRED_WARN || + khui_timers[i].type == KHUI_TTYPE_CRED_CRIT || + khui_timers[i].type == KHUI_TTYPE_CRED_RENEW || + khui_timers[i].type == KHUI_TTYPE_CRED_EXP) { + kcdb_cred_release(khui_timers[i].key); + } + } else { + if (i != j) + khui_timers[j] = khui_timers[i]; + j++; + } + } + + khui_n_timers = j; +} + +/* go through all the credentials and set timers as appropriate. hwnd + is the window that will receive the timer events.*/ +void +khm_timer_refresh(HWND hwnd) { + int i; + khm_int64 next_event = 0; + khm_int64 curtime; + khm_int64 diff; + + _begin_task(0); + _report_cs0(KHERR_DEBUG_1, L"Refreshing timers"); + _describe(); + + EnterCriticalSection(&cs_timers); + + KillTimer(hwnd, KHUI_TRIGGER_TIMER_ID); + + /* When refreshing timers, we go through all of them and mark them + as stale. Then we go through the credentials in the root + credential set and add or refresh the timers associated with + each identity and credential. Once this is done, we remove the + timers that are still stale, since they are no longer in + use. */ + + for (i=0; i < (int) khui_n_timers; i++) { +#ifdef NOT_IMPLEMENTED_YET + if (khui_timers[i].type == KHUI_TTYPE_BMSG || + khui_timers[i].type == KHUI_TTYPE_SMSG) { + khui_timers[i].flags &= ~KHUI_TE_FLAG_STALE; + } else { +#endif + + khui_timers[i].flags |= KHUI_TE_FLAG_STALE; + +#ifdef NOT_IMPLEMENTED_YET + } +#endif + } + + _report_cs1(KHERR_DEBUG_1, L"Starting with %1!d! timers", + _int32(khui_n_timers)); + + kcdb_credset_apply(NULL, + tmr_cred_apply_proc, + NULL); + + tmr_purge(); + + _report_cs1(KHERR_DEBUG_1, L"Leaving with %1!d! timers", + _int32(khui_n_timers)); + + _check_next_event: + + /* Before we return, we should check if any timers are set to + expire right now. If there are, we should fire the timer + before returning. */ + + next_event = 0; + for (i=0; i < (int) khui_n_timers; i++) { + if (!(khui_timers[i].flags & KHUI_TE_FLAG_EXPIRED) && + khui_timers[i].type != KHUI_TTYPE_ID_MARK && + (next_event == 0 || + next_event > khui_timers[i].expire)) { + + next_event = khui_timers[i].expire; + + } + } + + if (next_event != 0) { + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + curtime = FtToInt(&ft); + + TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR_SMALL, &ft); + diff = FtToInt(&ft); + + if (curtime + diff > next_event) { + tmr_fire_timer(); + goto _check_next_event; + } else { + diff = next_event - curtime; + ft = IntToFt(diff); + SetTimer(hwnd, + KHUI_TRIGGER_TIMER_ID, + FtIntervalToMilliseconds(&ft), + NULL); + } + } + + LeaveCriticalSection(&cs_timers); + + _end_task(); +} diff --git a/krb5-1-6/src/windows/identity/ui/timer.h b/krb5-1-6/src/windows/identity/ui/timer.h new file mode 100644 index 000000000..af4ece723 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/timer.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_TIMER_H +#define __KHIMAIRA_TIMER_H + +/* note that the ordering of the first few enum constants are + significant. The values of the constants up to KHUI_N_TTYPES are + used as indices. */ +typedef enum tag_khui_timer_type { + KHUI_TTYPE_ID_EXP = 0, /* Identity expiration */ + KHUI_TTYPE_ID_CRIT, /* Identity critical */ + KHUI_TTYPE_ID_WARN, /* Identity warning */ + KHUI_TTYPE_CRED_EXP, /* Credential expiration */ + KHUI_TTYPE_CRED_CRIT, /* Credential critical */ + KHUI_TTYPE_CRED_WARN, /* Credential warning */ + + KHUI_N_TTYPES, /* Count of the timers that we + aggregate for notifications */ + + KHUI_TTYPE_ID_MARK, /* Identity marker */ + + KHUI_TTYPE_ID_RENEW, /* Identity auto renewal */ + KHUI_TTYPE_CRED_RENEW, /* Credential renewal */ + +#if 0 + KHUI_TTYPE_BMSG, /* Custom. Sends broadcast message + when triggered.*/ + KHUI_TTYPE_SMSG, /* Custom. Sends subscription message + when triggered. */ +#endif +} khui_timer_type; + +typedef struct tag_khui_timer_event { + khm_handle key; + khui_timer_type type; + + khm_int64 expire; /* time at which the timer expires */ + khm_int64 offset; /* time offset at which the event that the + timer warns of happens */ + void * data; + khm_int32 flags; +} khui_timer_event; + +#define KHUI_TRIGGER_TIMER_ID 48 +#define KHUI_REFRESH_TIMER_ID 49 + +#define KHUI_REFRESH_TIMEOUT 5000 + +#define KHUI_TE_FLAG_EXPIRED 0x00000001 +#define KHUI_TE_FLAG_STALE 0x00000002 + +#define KHUI_DEF_TIMEOUT_WARN 900 +#define KHUI_DEF_TIMEOUT_CRIT 300 +#define KHUI_DEF_TIMEOUT_RENEW 60 + +/* the max absolute difference between two timers (in seconds) that + can exist where we consider both timers to be in the same + timeslot. */ +#define KHUI_TIMEEQ_ERROR 20 + +/* the small error. */ +#define KHUI_TIMEEQ_ERROR_SMALL 1 + +void +khm_timer_refresh(HWND hwnd); + +void +khm_timer_fire(HWND hwnd); + +void +khm_timer_init(void); + +void +khm_timer_exit(void); + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/toolbar.c b/krb5-1-6/src/windows/identity/ui/toolbar.c new file mode 100644 index 000000000..c543e6923 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/toolbar.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include<khmapp.h> +#include<assert.h> + +HWND khui_hwnd_standard_toolbar; +int khui_tb_blank; + +khui_ilist * ilist_toolbar; + +void khui_init_toolbar(void) { + ilist_toolbar = khui_create_ilist(KHUI_TOOLBAR_IMAGE_WIDTH, KHUI_TOOLBAR_IMAGE_HEIGHT, KHUI_TOOLBAR_MAX_BTNS, 5, 0); +} + +void khui_exit_toolbar(void) { + khui_delete_ilist(ilist_toolbar); +} + +LRESULT khm_toolbar_notify(LPNMHDR notice) { + switch(notice->code) { + case TBN_GETINFOTIP: + { + LPNMTBGETINFOTIP git = (LPNMTBGETINFOTIP) notice; + int cmd; + khui_action * a; + + cmd = git->iItem; + a = khui_find_action(cmd); + + if (a) { + if (a->caption) { + StringCchCopy(git->pszText, git->cchTextMax, a->caption); + } else if (a->tooltip) { + StringCchCopy(git->pszText, git->cchTextMax, a->tooltip); + } else if (a->is_caption) { + wchar_t buf[INFOTIPSIZE]; + + buf[0] = L'\0'; + LoadString(khm_hInstance, a->is_caption, + buf, ARRAYLENGTH(buf)); + + StringCchCopy(git->pszText, git->cchTextMax, buf); + } else { + StringCchCopy(git->pszText, git->cchTextMax, L""); + } + } else { + StringCchCopy(git->pszText, + git->cchTextMax, + L""); + } + } + break; + + case TBN_HOTITEMCHANGE: + { + LPNMTBHOTITEM hi = (LPNMTBHOTITEM) notice; + + if (hi->dwFlags & HICF_LEAVING) { + khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, L""); + } else { + khui_action * a; + int cmd; + wchar_t buf[256]; + + cmd = hi->idNew; + a = khui_find_action(cmd); + + buf[0] = L'\0'; + + if (a) { + if (a->tooltip) + StringCbCopy(buf, sizeof(buf), a->tooltip); + else if (a->is_tooltip) { + LoadString(khm_hInstance, a->is_tooltip, + buf, ARRAYLENGTH(buf)); + } + } + + khm_statusbar_set_part(KHUI_SBPART_INFO, NULL, buf); + } + } + break; + + case TBN_DROPDOWN: + { + LPNMTOOLBAR nmtb = (LPNMTOOLBAR) notice; + RECT r; + + GetWindowRect(khui_hwnd_standard_toolbar, &r); + if (nmtb->iItem == KHUI_ACTION_DESTROY_CRED) { + khm_menu_show_panel(KHUI_MENU_DESTROY_CRED, + r.left + nmtb->rcButton.left, + r.top + nmtb->rcButton.bottom); + } else if (nmtb->iItem == KHUI_ACTION_RENEW_CRED) { + khm_menu_show_panel(KHUI_MENU_RENEW_CRED, + r.left + nmtb->rcButton.left, + r.top + nmtb->rcButton.bottom); + } else { + return TBDDRET_NODEFAULT; + } + + return TBDDRET_DEFAULT; + } + break; + + case NM_CUSTOMDRAW: + { + LPNMTBCUSTOMDRAW nmcd = (LPNMTBCUSTOMDRAW) notice; + if(nmcd->nmcd.dwDrawStage == CDDS_PREPAINT) { + return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTERASE; + } else if(nmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { + return CDRF_NOTIFYPOSTPAINT; + } else if(nmcd->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT) { + /* draw the actual icon */ + int iidx; + int ibmp; + HBITMAP hbmp; + RECT r; + + khui_action * act = + khui_find_action((int) nmcd->nmcd.dwItemSpec); + + if(!act || !act->ib_normal) + return CDRF_DODEFAULT; + + if((act->state & KHUI_ACTIONSTATE_DISABLED) && + act->ib_disabled) { + ibmp = act->ib_disabled; + } else if(act->ib_hot && + ((nmcd->nmcd.uItemState & CDIS_HOT) || + (nmcd->nmcd.uItemState & CDIS_SELECTED))){ + ibmp = act->ib_hot; + } else { + ibmp = act->ib_normal; + } + + iidx = khui_ilist_lookup_id(ilist_toolbar, ibmp); + if(iidx < 0) { + hbmp = LoadImage(khm_hInstance, + MAKEINTRESOURCE(ibmp), + IMAGE_BITMAP, + KHUI_TOOLBAR_IMAGE_WIDTH, + KHUI_TOOLBAR_IMAGE_HEIGHT, 0); + iidx = + khui_ilist_add_masked_id(ilist_toolbar, + hbmp, + KHUI_TOOLBAR_BGCOLOR, + ibmp); + DeleteObject(hbmp); + } + + if(iidx < 0) + return CDRF_DODEFAULT; + + CopyRect(&r, &(nmcd->nmcd.rc)); + r.left += ((r.bottom - r.top) - + KHUI_TOOLBAR_IMAGE_HEIGHT) / 2; + r.top += ((r.bottom - r.top) - + KHUI_TOOLBAR_IMAGE_HEIGHT) / 2; +#if 0 + r.left += ((r.right - r.left) - + KHUI_TOOLBAR_IMAGE_WIDTH) / 2; +#endif + khui_ilist_draw(ilist_toolbar, + iidx, + nmcd->nmcd.hdc, + r.left, + r.top, + 0); + + return CDRF_DODEFAULT; + } + } + break; + } + return 0; +} + +void khui_add_action_to_toolbar(HWND tb, khui_action *a, int opt, HIMAGELIST hiList) { + wchar_t buf[MAX_RES_STRING] = L""; + int idx_caption = 0; + TBBUTTON bn; + LRESULT lr; + + ZeroMemory(&bn,sizeof(bn)); + + if(opt & KHUI_TOOLBAR_ADD_SEP) { + bn.fsStyle = BTNS_SEP; + bn.iBitmap = 3; + + lr = SendMessage(tb, + TB_ADDBUTTONS, + 1, + (LPARAM) &bn); +#ifdef DEBUG + assert(lr); +#endif + return; + } + + bn.fsStyle = BTNS_BUTTON; + + if(opt & KHUI_TOOLBAR_VARSIZE) { + bn.fsStyle |= BTNS_AUTOSIZE; + } + + if(opt & KHUI_TOOLBAR_ADD_TEXT) { + int sid = 0; + if((opt & KHUI_TOOLBAR_ADD_LONGTEXT) == + KHUI_TOOLBAR_ADD_LONGTEXT) { + sid = a->is_tooltip; + } + if(!sid) + sid = a->is_caption; + if(sid) { + LoadString(khm_hInstance, + sid, + buf, ARRAYLENGTH(buf)); + buf[wcslen(buf) + 1] = L'\0'; + idx_caption = (int) SendMessage(tb, + TB_ADDSTRING, + (WPARAM) NULL, + (LPARAM) buf); +#if (_WIN32_IE >= 0x0501) + bn.fsStyle |= BTNS_SHOWTEXT; +#endif + bn.iString = idx_caption; + } + } + + if(opt & KHUI_TOOLBAR_ADD_DROPDOWN) { + bn.fsStyle |= BTNS_DROPDOWN; + } + + if((opt & KHUI_TOOLBAR_ADD_BITMAP) && a->ib_normal) { + bn.fsStyle |= TBSTYLE_CUSTOMERASE; + bn.iBitmap = khui_tb_blank; + } else { +#if (_WIN32_IE >= 0x0501) + bn.iBitmap = I_IMAGENONE; +#endif + } + + bn.idCommand = a->cmd; + + if(a->state & KHUI_ACTIONSTATE_DISABLED) { + bn.fsState = 0; + } else { + bn.fsState = TBSTATE_ENABLED; + } + + if(a->state & KHUI_ACTIONSTATE_CHECKED) { + bn.fsState |= TBSTATE_CHECKED; + } + + bn.dwData = 0; + + lr = SendMessage( + tb, + TB_ADDBUTTONS, + 1, + (LPARAM) &bn); + +#ifdef DEBUG + assert(lr); +#endif +} + +void khm_update_standard_toolbar(void) +{ + khui_menu_def * def; + khui_action_ref * aref; + khui_action * act; + + def = khui_find_menu(KHUI_TOOLBAR_STANDARD); + + aref = def->items; + + while(aref && aref->action != KHUI_MENU_END) { + if(aref->action == KHUI_MENU_SEP) { + aref++; + continue; + } + + act = khui_find_action(aref->action); + if(act) { + BOOL enable; + + enable = !(act->state & KHUI_ACTIONSTATE_DISABLED); + SendMessage(khui_hwnd_standard_toolbar, + TB_ENABLEBUTTON, + (WPARAM) act->cmd, + MAKELPARAM(enable, 0)); + } + + aref++; + } +} + +void khm_create_standard_toolbar(HWND rebar) { + HWND hwtb; + SIZE sz; + HBITMAP hbm_blank; + HIMAGELIST hiList; + REBARBANDINFO rbi; + khui_menu_def * def; + khui_action * act; + khui_action_ref * aref; + int idx_blank; + + def = khui_find_menu(KHUI_TOOLBAR_STANDARD); + + if (!def) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + hwtb = CreateWindowEx(0 , + TOOLBARCLASSNAME, + (LPWSTR) NULL, + WS_CHILD | + TBSTYLE_FLAT | + TBSTYLE_AUTOSIZE | + TBSTYLE_TOOLTIPS | + CCS_NORESIZE | + CCS_NOPARENTALIGN | + CCS_ADJUSTABLE | + CCS_NODIVIDER, + 0, 0, 0, 0, rebar, + (HMENU) NULL, khm_hInstance, + NULL); + + if(!hwtb) { +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + +#if (_WIN32_IE >= 0x0501) + SendMessage(hwtb, TB_SETEXTENDEDSTYLE, 0, + TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS); +#endif + + hiList = ImageList_Create( + KHUI_TOOLBAR_IMAGE_WIDTH, + KHUI_TOOLBAR_IMAGE_HEIGHT, + ILC_MASK, + (int) khui_action_list_length(def->items), + 3); + + hbm_blank = LoadImage(khm_hInstance, + MAKEINTRESOURCE(IDB_TB_BLANK), + IMAGE_BITMAP, + KHUI_TOOLBAR_IMAGE_WIDTH, + KHUI_TOOLBAR_IMAGE_HEIGHT, 0); + idx_blank = ImageList_AddMasked(hiList, hbm_blank, RGB(0,0,0)); + + khui_hwnd_standard_toolbar = hwtb; + khui_tb_blank = idx_blank; + + def = khui_find_menu(KHUI_TOOLBAR_STANDARD); + + aref = def->items; + + SendMessage(hwtb, + TB_BUTTONSTRUCTSIZE, + sizeof(TBBUTTON), + 0); + + SendMessage(hwtb, + TB_SETBITMAPSIZE, + 0, + MAKELONG(KHUI_TOOLBAR_IMAGE_WIDTH,KHUI_TOOLBAR_IMAGE_HEIGHT)); + + SendMessage(hwtb, + TB_SETIMAGELIST, + 0, + (LPARAM) hiList); + + SendMessage(hwtb, + TB_SETBUTTONSIZE, + 0, + MAKELONG(KHUI_TOOLBAR_IMAGE_WIDTH,KHUI_TOOLBAR_IMAGE_HEIGHT)); + + while(aref && aref->action != KHUI_MENU_END) { + if(aref->action == KHUI_MENU_SEP) { + khui_add_action_to_toolbar(hwtb, + NULL, + KHUI_TOOLBAR_ADD_SEP, + hiList); + } else { + act = khui_find_action(aref->action); + khui_add_action_to_toolbar(hwtb, + act, + KHUI_TOOLBAR_ADD_BITMAP | + ((aref->flags & KHUI_ACTIONREF_SUBMENU)? + KHUI_TOOLBAR_ADD_DROPDOWN: 0), + hiList); + } + aref ++; + } + + SendMessage(hwtb, + TB_AUTOSIZE, + 0,0); + + SendMessage(hwtb, + TB_GETMAXSIZE, + 0, + (LPARAM) &sz); + + sz.cy += 5; + + ZeroMemory(&rbi, sizeof(rbi)); + + rbi.cbSize = sizeof(rbi); + rbi.fMask = + RBBIM_ID | + RBBIM_CHILD | + RBBIM_CHILDSIZE | + RBBIM_IDEALSIZE | + RBBIM_SIZE | + RBBIM_STYLE; + rbi.fStyle = + RBBS_USECHEVRON | + RBBS_BREAK; + rbi.hwndChild = hwtb; + + rbi.wID = KHUI_TOOLBAR_STANDARD; + rbi.cx = sz.cx; + rbi.cxMinChild = sz.cx; + rbi.cyMinChild = sz.cy; + rbi.cyChild = rbi.cyMinChild; + rbi.cyMaxChild = rbi.cyMinChild; + rbi.cyIntegral = rbi.cyMinChild; + + rbi.cxIdeal = rbi.cx; + + SendMessage(rebar, + RB_INSERTBAND, + 0, + (LPARAM) &rbi); +} diff --git a/krb5-1-6/src/windows/identity/ui/toolbar.h b/krb5-1-6/src/windows/identity/ui/toolbar.h new file mode 100644 index 000000000..ac09c6619 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/toolbar.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_TOOLBAR_H +#define __KHIMAIRA_TOOLBAR_H + +extern HWND khui_hwnd_standard_toolbar; + +void khui_init_toolbar(void); +void khui_exit_toolbar(void); +LRESULT khm_toolbar_notify(LPNMHDR notice); +void khm_create_standard_toolbar(HWND rebar); +void khui_add_action_to_toolbar(HWND toolbar, khui_action * act, int opt, HIMAGELIST hiList); +void khm_update_standard_toolbar(void); + +/* options for khui_add_action_to_toolbar */ +#define KHUI_TOOLBAR_ADD_TEXT 0x00000001 +#define KHUI_TOOLBAR_ADD_BITMAP 0x00000002 +#define KHUI_TOOLBAR_ADD_LONGTEXT 0x00000005 +#define KHUI_TOOLBAR_ADD_DROPDOWN 0x00000008 +#define KHUI_TOOLBAR_ADD_SEP 0x00000010 +#define KHUI_TOOLBAR_VARSIZE 0x00000020 + +#define KHUI_TOOLBAR_IMAGE_WIDTH 29 +#define KHUI_TOOLBAR_IMAGE_HEIGHT 27 +#define KHUI_TOOLBAR_BGCOLOR RGB(0xd7,0xd7,0xd7) +#define KHUI_TOOLBAR_MAX_BTNS 64 + +#endif diff --git a/krb5-1-6/src/windows/identity/ui/uiconfig.csv b/krb5-1-6/src/windows/identity/ui/uiconfig.csv new file mode 100644 index 000000000..3a8006f55 --- /dev/null +++ b/krb5-1-6/src/windows/identity/ui/uiconfig.csv @@ -0,0 +1,273 @@ +#@#include<windows.h> +#@#define RGBA(r,g,b,a) ((((DWORD) ((a) & 0xff)) << 24) | RGB(r,g,b)) +Name,Type,Value,Description +CredWindow,KC_SPACE,0,"Options for the credentials window as well as the Network Identity Manager application." + AutoInit,KC_INT32,0,"Boolean. Prompt for new credentials if no credentials are present during startup." + AutoStart,KC_INT32,0,"[PRIVATE] Boolean. Start Network Identity Manager automatically when the current user logs in." + AutoImport,KC_INT32,1,"Boolean. Import credentials from the LSA cache when Network Identity Manager starts." + AutoDetectNet,KC_INT32,1,"Boolean. Automatically detect network connectivity changes." + HideWatermark,KC_INT32,0,"Boolean. Suppress watermark in Credentials display. NOTE: there is no guarantee that this value will exist in future versions." + KeepRunning,KC_INT32,1,"Boolean. Run from the system notification area after the main window is closed." + DefaultView,KC_STRING,ByIdentity,"[PRIVATE] Name of the default view in Advanced mode." + DefaultViewMini,KC_STRING,CompactIdentity,"[PRIVATE] Name of the default view in Basic mode." + PaddingHorizontal,KC_INT32,4,"[PRIVATE]" + PaddingVertical,KC_INT32,2,"[PRIVATE]" + PaddingHeader,KC_INT32,16,"[PRIVATE]" + Monitor,KC_INT32,1,"Boolean. Monitor credentials for expiration and renewal." + DefaultMonitor,KC_INT32,1,"Boolean. This is the default Monitor value that is assigned for new identities." + RefreshTimeout,KC_INT32,60,"Number of seconds between credentials window refreshes. The credentials window automatically triggers a refresh operation. This value specifies the number of seconds that must elapse between two refreshes. During the refresh, all the credentials provider plug-ins will need to re-enumerate their respective credentials." + WarnThreshold,KC_INT32,900,In seconds + AllowWarn,KC_INT32,1,"Boolean. Enables warning." + CriticalThreshold,KC_INT32,300,In seconds + AllowCritical,KC_INT32,1,Boolean. Enables critical. + AutoRenewThreshold,KC_INT32,600,In seconds + AllowAutoRenew,KC_INT32,1,Boolean. + RenewAtHalfLife,KC_INT32,1,Boolean. Use half-life algorithm for renewals. + DefaultAllowAutoRenew,KC_INT32,1,Default AllowAutoRenew value for new identities + DefaultSticky,KC_INT32,0,Default Sticky value for new identities + MaxThreshold,KC_INT32,86400,Max value for a threshold (1 day) + MinThreshold,KC_INT32,10,Min value for a threshold (0) + LogToFile,KC_INT32,0,Boolean. If true logs trace events to a nidmdbg.log in the temp folder + DestroyCredsOnExit,KC_INT32,0,Boolean. If true; all credentials will be destroyed when NetIDMgr exits. + NotificationAction,KC_INT32,50025,Action to perform when the user clicks on the notification icon. + DefaultWindowMode,KC_INT32,1,(0-normal; 1-mini) + DefaultTheme,KC_STRING,Default,Default theme. The name should correspond to a subspace in Themes + ViewAllIdents,KC_INT32,0,"Boolean. Try to display all known identities if non-zero." + Windows,KC_SPACE,0,Window parameters + _Schema,KC_SPACE,0,Schema + Width,KC_INT32,0, + Height,KC_INT32,0, + XPos,KC_INT32,0, + YPos,KC_INT32,0, + Dock,KC_INT32,0,Dock on window corner (0-none; 1-top left; 2-top right; 3-bottom right; 4-bottom left) + _Schema,KC_ENDSPACE,0, + Main,KC_SPACE,0,Main window + Main,KC_ENDSPACE,0, + MainMini,KC_SPACE,0,Main window (mini mode) + Width,KC_INT32,470, + Height,KC_INT32,500, + Dock,KC_INT32,3, + MainMini,KC_ENDSPACE,0, + NewCred,KC_SPACE,0,New credentials window + ForceToTop,KC_INT32,1,Force new creds window to the top + AnimateSizeChanges,KC_INT32,1,Animate the new creds window when the size needs changing. + AnimationSteps,KC_INT32,7,Number of steps in size-change animation + AnimationStepTimeout,KC_INT32,40,Number of milliseconds to wait between each step of the size-change animation + NewCred,KC_ENDSPACE,0, + Windows,KC_ENDSPACE,0, + Views,KC_SPACE,0,Preconfigured views for credentials + _Schema,KC_SPACE,0,Schema for view definitions + Description,KC_STRING,"",Description of the view + ColumnList,KC_STRING,"","List of columns for the view, in order" + _AppVersion,KC_BINARY,0,Binary version stamp + Columns,KC_SPACE,0,"Column definitions. Each column name should have a corresponding subspace here. The name of the column should be a property or field name, unless it is a pseudo column like _CWFlags." + _Schema,KC_SPACE,0,Column definition schema + Width,KC_INT32,0,Width of the column + SortIndex,KC_INT32,0,Sort index + Flags,KC_INT32,0,Flags (See KHUI_CW_COL_* values) + _Schema,KC_ENDSPACE,0 + Columns,KC_ENDSPACE,0 + _Schema,KC_ENDSPACE,0, + Custom_0,KC_SPACE,0,First custom view. Additional views have names of the form Custom_N + Description,KC_STRING,Custom view, + ColumnList,KC_STRING,"_CWFlags,IdentityName,TypeName,Name,TimeLeft", + Columns,KC_SPACE,0,Columns + _CWFlags,KC_SPACE,0, + Width,KC_INT32,20, + Flags,KC_INT32,112, + _CWFlags,KC_ENDSPACE,0, + IdentityName,KC_SPACE,0, + Width,KC_INT32,100, + SortIndex,KC_INT32,0, + Flags,KC_INT32,11, + IdentityName,KC_ENDSPACE,0 + TypeName,KC_SPACE,0 + Width,KC_INT32,100 + SortIndex,KC_INT32,1 + Flags,KC_INT32,11 + TypeName,KC_ENDSPACE,0 + Name,KC_SPACE,0 + Width,KC_INT32,200 + SortIndex,KC_INT32,2 + Flags,KC_INT32,3 + Name,KC_ENDSPACE,0 + TimeLeft,KC_SPACE,0 + Width,KC_INT32,200 + Flags,KC_INT32,1 + TimeLeft,KC_ENDSPACE,0 + Columns,KC_ENDSPACE,0 + Custom_0,KC_ENDSPACE,0, + ByIdentity,KC_SPACE,0,The default view + Description,KC_STRING,View grouped by identity and credential type, + ColumnList,KC_STRING,"_CWFlags,IdentityName,TypeName,Location,Name,TimeLeft", + Columns,KC_SPACE,0,Columns + _CWFlags,KC_SPACE,0, + Width,KC_INT32,20, + Flags,KC_INT32,112, + _CWFlags,KC_ENDSPACE,0, + IdentityName,KC_SPACE,0, + Width,KC_INT32,100, + SortIndex,KC_INT32,0, + Flags,KC_INT32,11, + IdentityName,KC_ENDSPACE,0 + TypeName,KC_SPACE,0 + Width,KC_INT32,100 + SortIndex,KC_INT32,1 + Flags,KC_INT32,11 + TypeName,KC_ENDSPACE,0 + Location,KC_SPACE,0, + Width,KC_INT32,50 + SortIndex,KC_INT32,2 + Flags,KC_INT32,11 + Location,KC_ENDSPACE,0, + Name,KC_SPACE,0 + Width,KC_INT32,200 + SortIndex,KC_INT32,3 + Flags,KC_INT32,3 + Name,KC_ENDSPACE,0 + TimeLeft,KC_SPACE,0 + Width,KC_INT32,200 + Flags,KC_INT32,1 + TimeLeft,KC_ENDSPACE,0 + Columns,KC_ENDSPACE,0 + ByIdentity,KC_ENDSPACE,0 + ByType,KC_SPACE,0,The default view + Description,KC_STRING,View grouped by type and identity, + ColumnList,KC_STRING,"_CWFlags,TypeName,IdentityName,Name,TimeLeft", + Columns,KC_SPACE,0,Columns + _CWFlags,KC_SPACE,0, + Width,KC_INT32,20, + Flags,KC_INT32,112, + _CWFlags,KC_ENDSPACE,0, + TypeName,KC_SPACE,0 + Width,KC_INT32,100 + SortIndex,KC_INT32,0 + Flags,KC_INT32,11 + TypeName,KC_ENDSPACE,0 + IdentityName,KC_SPACE,0, + Width,KC_INT32,100, + SortIndex,KC_INT32,1, + Flags,KC_INT32,11, + IdentityName,KC_ENDSPACE,0 + Name,KC_SPACE,0 + Width,KC_INT32,200 + SortIndex,KC_INT32,2 + Flags,KC_INT32,3 + Name,KC_ENDSPACE,0 + TimeLeft,KC_SPACE,0 + Width,KC_INT32,200 + Flags,KC_INT32,1 + TimeLeft,KC_ENDSPACE,0 + Columns,KC_ENDSPACE,0 + ByType,KC_ENDSPACE,0 + ByLocation,KC_SPACE,0,View by location + Description,KC_STRING,View grouped by location, + ColumnList,KC_STRING,"_CWFlags,Location,IdentityName,TypeName,Name,TimeLeft", + Columns,KC_SPACE,0,Columns + _CWFlags,KC_SPACE,0, + Width,KC_INT32,20, + Flags,KC_INT32,112, + _CWFlags,KC_ENDSPACE,0, + Location,KC_SPACE,0, + Width,KC_INT32,100, + SortIndex,KC_INT32,0, + Flags,KC_INT32,11, + Location,KC_ENDSPACE,0, + IdentityName,KC_SPACE,0, + Width,KC_INT32,100, + SortIndex,KC_INT32,1, + Flags,KC_INT32,11, + IdentityName,KC_ENDSPACE,0 + TypeName,KC_SPACE,0 + Width,KC_INT32,100 + SortIndex,KC_INT32,2 + Flags,KC_INT32,11 + TypeName,KC_ENDSPACE,0 + Name,KC_SPACE,0 + Width,KC_INT32,200 + SortIndex,KC_INT32,3 + Flags,KC_INT32,3 + Name,KC_ENDSPACE,0 + TimeLeft,KC_SPACE,0 + Width,KC_INT32,200 + Flags,KC_INT32,1 + TimeLeft,KC_ENDSPACE,0 + Columns,KC_ENDSPACE,0 + ByLocation,KC_ENDSPACE,0 + CompactIdentity,KC_SPACE,0,Default Compact View by Identity + Description,KC_STRING,Compact view of identities + ColumnList,KC_STRING,"IdentityName", + ExpandedIdentity,KC_INT32,1,Use expanded display of identity headers + NoHeader,KC_INT32,1,Suppress the column header + Columns,KC_SPACE,0, + IdentityName,KC_SPACE,0, + Width,KC_INT32,415, + SortIndex,KC_INT32,0, + Flags,KC_INT32,171 + IdentityName,KC_ENDSPACE,0, + Columns,KC_ENDSPACE,0, + CompactIdentity,KC_ENDSPACE,0 + Custom_1,KC_SPACE,0,Default Compact View by Identity + Description,KC_STRING,Compact view of identities + ColumnList,KC_STRING,"IdentityName", + ExpandedIdentity,KC_INT32,1,Use expanded display of identity headers + NoHeader,KC_INT32,1,Suppress the column header + Columns,KC_SPACE,0, + IdentityName,KC_SPACE,0, + Width,KC_INT32,415, + SortIndex,KC_INT32,0, + Flags,KC_INT32,171 + IdentityName,KC_ENDSPACE,0, + Columns,KC_ENDSPACE,0, + Custom_1,KC_ENDSPACE,0 + Views,KC_ENDSPACE,0 + Notices,KC_SPACE,0,Notices and alerts + MinimizeWarning,KC_INT32,1,Show the minimize warning? + Notices,KC_ENDSPACE,0 + Themes,KC_SPACE,0,Color schemes for the credentials display + _Schema,KC_SPACE,0,Schema for color schemes + ClrSelection,KC_INT32,0,"Background (Selection)" + ClrBackground,KC_INT32,0,"Background (Normal)" + ClrGray,KC_INT32,0,"Background (Gray)" + ClrHeader,KC_INT32,0,"Header (Normal)" + ClrHeaderCred,KC_INT32,0,"Header (with credentials)" + ClrHeaderWarn,KC_INT32,0,"Header (Warning)" + ClrHeaderCrit,KC_INT32,0,"Header (Critical)" + ClrHeaderExp,KC_INT32,0,"Header (Expired)" + ClrHeaderSel,KC_INT32,0,"Header (Normal, Selected)" + ClrHeaderCredSel,KC_INT32,0,"Header (with credentials, Selected)" + ClrHeaderWarnSel,KC_INT32,0,"Header (Warning, Selected)" + ClrHeaderCritSel,KC_INT32,0,"Header (Critical, Selected)" + ClrHeaderExpSel,KC_INT32,0,"Header (Expired, Selected)" + ClrHeaderOutline,KC_INT32,0,"Header (Outline color)" + ClrText,KC_INT32,0,"Text (Normal)" + ClrTextSel,KC_INT32,0,"Text (Selected)" + ClrTextHeader,KC_INT32,0,"Text (Header)" + ClrTextHeaderSel,KC_INT32,0,"Text (Header, Selected)" + ClrTextHeaderGray,KC_INT32,0,"Text (Header, Gray)" + ClrTextHeaderGraySel,KC_INT32,0,"Text (Header, Gray, Selected)" + _Schema,KC_ENDSPACE,0, + Default,KC_SPACE,0,Default color scheme + ClrSelection,KC_INT32,"RGB(192,192,192)", + ClrBackground,KC_INT32,"RGB(255,255,255)", + ClrGray,KC_INT32,"RGB(240,240,240)", + ClrHeader,KC_INT32,"RGB(240,240,240)", + ClrHeaderCred,KC_INT32,"RGB(184,235,134)", + ClrHeaderWarn,KC_INT32,"RGB(235,235,134)", + ClrHeaderCrit,KC_INT32,"RGB(235,184,134)", + ClrHeaderExp,KC_INT32,"RGB(235,134,134)", + ClrHeaderSel,KC_INT32,"RGB(200,200,200)", + ClrHeaderCredSel,KC_INT32,"RGB(144,195, 94)", + ClrHeaderWarnSel,KC_INT32,"RGB(195,195, 94)", + ClrHeaderCritSel,KC_INT32,"RGB(195,144, 94)", + ClrHeaderExpSel,KC_INT32,"RGB(195, 94, 94)", + ClrHeaderOutline,KC_INT32,"RGB(15,15,15)", + ClrText,KC_INT32,"RGB(15,15,15)", + ClrTextSel,KC_INT32,"RGB(0,0,0)", + ClrTextHeader,KC_INT32,"RGB(15,15,15)", + ClrTextHeaderSel,KC_INT32,"RGB(0,0,0)", + ClrTextHeaderGray,KC_INT32,"RGB(192,192,192)", + ClrTextHeaderGraySel,KC_INT32,"RGB(240,240,240)", + Default,KC_ENDSPACE,0 + Themes,KC_ENDSPACE,0 +CredWindow,KC_ENDSPACE,0 diff --git a/krb5-1-6/src/windows/identity/uilib/Makefile b/krb5-1-6/src/windows/identity/uilib/Makefile new file mode 100644 index 000000000..5c019b454 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/Makefile @@ -0,0 +1,68 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=uilib +!include <../config/Makefile.w32> + +UIDLLOBJFILES= \ + $(OBJ)\rescache.obj \ + $(OBJ)\action.obj \ + $(OBJ)\creddlg.obj \ + $(OBJ)\alert.obj \ + $(OBJ)\propsheet.obj \ + $(OBJ)\propwnd.obj \ + $(OBJ)\uilibmain.obj \ + $(OBJ)\actiondef.obj \ + $(OBJ)\acceldef.obj \ + $(OBJ)\configui.obj \ + $(OBJ)\trackerwnd.obj \ + $(OBJ)\uibind.obj \ + $(OBJ)\version.obj + +INCFILES= \ + $(INCDIR)\khuidefs.h \ + $(INCDIR)\khrescache.h \ + $(INCDIR)\khaction.h \ + $(INCDIR)\khactiondef.h \ + $(INCDIR)\khalerts.h \ + $(INCDIR)\khhtlink.h \ + $(INCDIR)\khnewcred.h \ + $(INCDIR)\khprops.h \ + $(INCDIR)\khconfigui.h \ + $(INCDIR)\khtracker.h \ + $(INCDIR)\khremote.h \ + $(INCDIR)\intaction.h \ + $(INCDIR)\intalert.h + +$(OBJ)\actiondef.c: actions.csv actiondef.cfg + $(CCSV) $** $@ + +$(OBJ)\acceldef.c: accel.csv acceldef.cfg + $(CCSV) $** $@ + +all: mkdirs $(INCFILES) $(UIDLLOBJFILES) + +clean:: + if exist "$(INCDIR)" $(RM) $(INCFILES) + diff --git a/krb5-1-6/src/windows/identity/uilib/accel.csv b/krb5-1-6/src/windows/identity/uilib/accel.csv new file mode 100644 index 000000000..d55bff0b7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/accel.csv @@ -0,0 +1,26 @@ +command,mod,key,scope +KHUI_PACTION_MENU,FVIRTKEY,VK_F10,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_UP,FVIRTKEY,VK_UP,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_UP_EXTEND,FVIRTKEY|FSHIFT,VK_UP,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_UP_TOGGLE,FVIRTKEY|FCONTROL,VK_UP,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_PGUP,FVIRTKEY,VK_PRIOR,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_PGUP_EXTEND,FVIRTKEY|FSHIFT,VK_PRIOR,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_DOWN,FVIRTKEY,VK_DOWN,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_DOWN_EXTEND,FVIRTKEY|FSHIFT,VK_DOWN,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_DOWN_TOGGLE,FVIRTKEY|FCONTROL,VK_DOWN,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_PGDN,FVIRTKEY,VK_NEXT,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_PGDN_EXTEND,FVIRTKEY|FSHIFT,VK_NEXT,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_LEFT,FVIRTKEY,VK_LEFT,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_RIGHT,FVIRTKEY,VK_RIGHT,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_ENTER,FVIRTKEY,VK_RETURN,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_ESC,FVIRTKEY,VK_ESCAPE,KHUI_ACCEL_SCOPE_GLOBAL +#KHUI_PACTION_DELETE,FVIRTKEY,VK_DELETE,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_DESTROY_CRED,FVIRTKEY,VK_DELETE,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_EXIT,FCONTROL|FVIRTKEY,\'X\',KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_VIEW_REFRESH,FVIRTKEY,VK_F5,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_NEW_CRED,FCONTROL|FVIRTKEY,\'N\',KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_RENEW_CRED,FCONTROL|FVIRTKEY,\'R\',KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_IMPORT,FCONTROL|FVIRTKEY,\'I\',KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_DESTROY_CRED,FCONTROL|FVIRTKEY,\'D\',KHUI_ACCEL_SCOPE_GLOBAL +KHUI_ACTION_LAYOUT_MINI,FVIRTKEY,VK_F7,KHUI_ACCEL_SCOPE_GLOBAL +KHUI_PACTION_SELALL,FCONTROL|FVIRTKEY,\'A\',KHUI_ACCEL_SCOPE_GLOBAL diff --git a/krb5-1-6/src/windows/identity/uilib/acceldef.cfg b/krb5-1-6/src/windows/identity/uilib/acceldef.cfg new file mode 100644 index 000000000..20bbeb581 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/acceldef.cfg @@ -0,0 +1,51 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +$file_prefix = <<EOS; +/* +This file was autogenerated from src/ui/acceldef.cfg and src/ui/accel.csv. + +Do not modify directly. +*/ +#define NOEXPORT +#include<khuidefs.h> + +khui_accel_def khui_accel_global[] = { +EOS + +$record_prefix = "{"; + +$record_sep = ",\n"; + +$record_postfix = "}"; + +$file_postfix = <<EOS; + +}; + +int khui_n_accel_global = sizeof(khui_accel_global) / sizeof(khui_accel_def); + +EOS + +$skip_lines = 1; diff --git a/krb5-1-6/src/windows/identity/uilib/action.c b/krb5-1-6/src/windows/identity/uilib/action.c new file mode 100644 index 000000000..04fb52a84 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/action.c @@ -0,0 +1,1672 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define NOEXPORT +#define _NIMLIB_ + +#include<khuidefs.h> +#include<intaction.h> +#include<utils.h> +#include<assert.h> + +#include<strsafe.h> + +khui_action_ref khui_main_menu[] = { + MENU_SUBMENU(KHUI_MENU_FILE), + MENU_SUBMENU(KHUI_MENU_CRED), + MENU_SUBMENU(KHUI_MENU_VIEW), + MENU_SUBMENU(KHUI_MENU_OPTIONS), + MENU_SUBMENU(KHUI_MENU_HELP), + MENU_END() +}; + +khui_action_ref khui_menu_file[] = { + MENU_ACTION(KHUI_ACTION_PROPERTIES), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_EXIT), + MENU_END() +}; + +khui_action_ref khui_menu_cred[] = { + MENU_ACTION(KHUI_ACTION_NEW_CRED), + MENU_SEP(), + MENU_SUBMENU(KHUI_MENU_RENEW_CRED), + MENU_ACTION(KHUI_ACTION_IMPORT), + MENU_SUBMENU(KHUI_MENU_DESTROY_CRED), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_SET_DEF_ID), +#if 0 + /* not implemented yet */ + MENU_ACTION(KHUI_ACTION_SET_SRCH_ID), +#endif + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_PASSWD_ID), + MENU_END() +}; + +khui_action_ref khui_menu_layout[] = { + MENU_ACTION(KHUI_ACTION_LAYOUT_ID), + MENU_ACTION(KHUI_ACTION_LAYOUT_TYPE), + MENU_ACTION(KHUI_ACTION_LAYOUT_LOC), + MENU_ACTION(KHUI_ACTION_LAYOUT_CUST), + MENU_END() +}; + +khui_action_ref khui_menu_toolbars[] = { + MENU_ACTION(KHUI_ACTION_TB_STANDARD), + MENU_END() +}; + +khui_action_ref khui_menu_view[] = { + MENU_ACTION(KHUI_ACTION_LAYOUT_MINI), + MENU_SUBMENU(KHUI_MENU_LAYOUT), + MENU_ACTION(KHUI_ACTION_VIEW_ALL_IDS), + MENU_SUBMENU(KHUI_MENU_COLUMNS), +#if 0 + /* not implemented yet */ + MENU_SUBMENU(KHUI_MENU_TOOLBARS), +#endif + MENU_SEP(), +#if 0 + /* not implemented yet */ + MENU_ACTION(KHUI_ACTION_DEBUG_WINDOW), + MENU_SEP(), +#endif + MENU_ACTION(KHUI_ACTION_VIEW_REFRESH), + MENU_END() +}; + +khui_action_ref khui_menu_options[] = { + MENU_ACTION(KHUI_ACTION_OPT_KHIM), + MENU_ACTION(KHUI_ACTION_OPT_APPEAR), + MENU_ACTION(KHUI_ACTION_OPT_IDENTS), + MENU_ACTION(KHUI_ACTION_OPT_NOTIF), + MENU_ACTION(KHUI_ACTION_OPT_PLUGINS), + MENU_SEP(), + MENU_END() +}; + +khui_action_ref khui_menu_help[] = { + MENU_ACTION(KHUI_ACTION_HELP_CTX), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_HELP_INDEX), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_HELP_ABOUT), + MENU_END() +}; + +khui_action_ref khui_toolbar_standard[] = { + MENU_ACTION(KHUI_ACTION_NEW_CRED), + MENU_SUBMENU(KHUI_ACTION_RENEW_CRED), + MENU_ACTION(KHUI_ACTION_IMPORT), + MENU_SUBMENU(KHUI_ACTION_DESTROY_CRED), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_PASSWD_ID), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_VIEW_REFRESH), + MENU_ACTION(KHUI_PACTION_BLANK), + MENU_ACTION(KHUI_ACTION_HELP_CTX), + MENU_END() +}; + +khui_action_ref khui_menu_ident_ctx[] = { + MENU_ACTION(KHUI_ACTION_PROPERTIES), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_SET_DEF_ID), + MENU_ACTION(KHUI_ACTION_SET_SRCH_ID), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_NEW_CRED), + MENU_ACTION(KHUI_ACTION_RENEW_CRED), + MENU_ACTION(KHUI_ACTION_DESTROY_CRED), + MENU_END() +}; + +khui_action_ref khui_menu_tok_ctx[] = { + MENU_ACTION(KHUI_ACTION_PROPERTIES), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_NEW_CRED), + MENU_ACTION(KHUI_ACTION_RENEW_CRED), + MENU_ACTION(KHUI_ACTION_DESTROY_CRED), + MENU_END() +}; + +khui_action_ref khui_menu_ico_ctx_min[] = { + MENU_DEFACTION(KHUI_ACTION_OPEN_APP), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_NEW_CRED), + MENU_SUBMENU(KHUI_MENU_RENEW_CRED), + MENU_ACTION(KHUI_ACTION_IMPORT), + MENU_SUBMENU(KHUI_MENU_DESTROY_CRED), + MENU_SEP(), + MENU_SUBMENU(KHUI_MENU_SETDEF), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_PASSWD_ID), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_HELP_CTX), + MENU_ACTION(KHUI_ACTION_HELP_ABOUT), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_EXIT), + MENU_END() +}; + +khui_action_ref khui_menu_ico_ctx_normal[] = { + MENU_DEFACTION(KHUI_ACTION_CLOSE_APP), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_NEW_CRED), + MENU_SUBMENU(KHUI_MENU_RENEW_CRED), + MENU_ACTION(KHUI_ACTION_IMPORT), + MENU_SUBMENU(KHUI_MENU_DESTROY_CRED), + MENU_SEP(), + MENU_SUBMENU(KHUI_MENU_SETDEF), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_PASSWD_ID), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_HELP_CTX), + MENU_ACTION(KHUI_ACTION_HELP_ABOUT), + MENU_SEP(), + MENU_ACTION(KHUI_ACTION_EXIT), + MENU_END() +}; + +khui_action_ref khui_menu_cwheader_ctx[] = { + MENU_SUBMENU(KHUI_MENU_COLUMNS), + MENU_SUBMENU(KHUI_MENU_LAYOUT), + MENU_END() +}; + +khui_action_ref khui_menu_columns[] = { + MENU_END() +}; + +khui_action_ref khui_menu_destroy_cred[] = { + MENU_DEFACTION(KHUI_ACTION_DESTROY_ALL), + MENU_END() +}; + +khui_action_ref khui_menu_renew_cred[] = { + MENU_DEFACTION(KHUI_ACTION_RENEW_ALL), + MENU_END() +}; + +khui_action_ref khui_menu_setdef[] = { + MENU_END() +}; + +khui_action_ref khui_pmenu_tok_sel[] = { + MENU_ACTION(KHUI_ACTION_RENEW_CRED), + MENU_ACTION(KHUI_ACTION_DESTROY_CRED), + MENU_END() +}; + +khui_action_ref khui_pmenu_id_sel[] = { + MENU_ACTION(KHUI_ACTION_DESTROY_CRED), + MENU_ACTION(KHUI_ACTION_RENEW_CRED), + MENU_END() +}; + +/* all stock menus and toolbars */ +khui_menu_def khui_all_menus[] = { + CONSTMENU(KHUI_MENU_MAIN, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_main_menu), + CONSTMENU(KHUI_MENU_FILE, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_file), + CONSTMENU(KHUI_MENU_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_cred), + CONSTMENU(KHUI_MENU_VIEW, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_view), + CONSTMENU(KHUI_MENU_LAYOUT, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_layout), + CONSTMENU(KHUI_MENU_TOOLBARS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_toolbars), + CONSTMENU(KHUI_MENU_OPTIONS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_options), + CONSTMENU(KHUI_MENU_HELP, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_help), + CONSTMENU(KHUI_MENU_COLUMNS, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_columns), + CONSTMENU(KHUI_MENU_RENEW_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_renew_cred), + CONSTMENU(KHUI_MENU_DESTROY_CRED, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_destroy_cred), + CONSTMENU(KHUI_MENU_SETDEF, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_menu_setdef), + + /* toolbars */ + CONSTMENU(KHUI_TOOLBAR_STANDARD, KHUI_MENUSTATE_CONSTANT | KHUI_MENUSTATE_SYSTEM, khui_toolbar_standard), + + /* context menus */ + CONSTMENU(KHUI_MENU_IDENT_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_ident_ctx), + CONSTMENU(KHUI_MENU_TOK_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_tok_ctx), + CONSTMENU(KHUI_MENU_ICO_CTX_MIN, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_min), + CONSTMENU(KHUI_MENU_ICO_CTX_NORMAL, KHUI_MENUSTATE_CONSTANT, khui_menu_ico_ctx_normal), + CONSTMENU(KHUI_MENU_CWHEADER_CTX, KHUI_MENUSTATE_CONSTANT, khui_menu_cwheader_ctx), + + /* pseudo menus */ + CONSTMENU(KHUI_PMENU_TOK_SEL, KHUI_MENUSTATE_CONSTANT, khui_pmenu_tok_sel), + CONSTMENU(KHUI_PMENU_ID_SEL, KHUI_MENUSTATE_CONSTANT, khui_pmenu_id_sel) +}; + +int khui_n_all_menus = sizeof(khui_all_menus) / sizeof(khui_menu_def); +khui_menu_def ** khui_cust_menus = NULL; +int khui_nc_cust_menus = 0; +int khui_n_cust_menus = 0; +CRITICAL_SECTION cs_actions; + +#define CACT_NC_ALLOC 32 + +khui_action ** khui_cust_actions = NULL; +int khui_nc_cust_actions = 0; +int khui_n_cust_actions = 0; + +HWND khui_hwnd_main; /* main window, for notifying + action launches and + dispatching messages to the + application. */ + +KHMEXP void KHMAPI +khui_init_actions(void) { + InitializeCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_exit_actions(void) { + DeleteCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_refresh_actions(void) { + kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0); +} + +KHMEXP void KHMAPI +khui_action_lock(void) { + EnterCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_action_unlock(void) { + LeaveCriticalSection(&cs_actions); +} + +KHMEXP khm_int32 KHMAPI +khui_action_create(const wchar_t * name, + const wchar_t * caption, + const wchar_t * tooltip, + void * userdata, + khm_int32 type, + khm_handle hsub) { + khui_action * act; + khm_int32 action = 0; + int i; + size_t s; + + if ((name && FAILED(StringCchLength(name, KHUI_MAXCCH_NAME, &s))) || + !caption || + FAILED(StringCchLength(caption, KHUI_MAXCCH_SHORT_DESC, &s)) || + (tooltip && FAILED(StringCchLength(tooltip, KHUI_MAXCCH_SHORT_DESC, &s))) || + (type != KHUI_ACTIONTYPE_TRIGGER && type != KHUI_ACTIONTYPE_TOGGLE && + type != KHUI_ACTIONTYPE_IDENTITY)) { + return 0; + } + + EnterCriticalSection(&cs_actions); + if (name && (act = khui_find_named_action(name))) { + /* named action already exists */ + action = act->cmd; + goto _done; + } + + for (i=0; i < khui_n_cust_actions; i++) { + if (khui_cust_actions[i] == NULL || + (khui_cust_actions[i]->state & KHUI_ACTIONSTATE_DELETED)) + break; + } + + if (i >= khui_n_cust_actions && + (khui_cust_actions == NULL || + khui_n_cust_actions + 1 > khui_nc_cust_actions)) { + + khui_nc_cust_actions = UBOUNDSS(khui_n_cust_actions + 1, + CACT_NC_ALLOC, + CACT_NC_ALLOC); +#ifdef DEBUG + assert(khui_nc_cust_actions > khui_n_cust_actions + 1); +#endif + khui_cust_actions = PREALLOC(khui_cust_actions, + sizeof(*khui_cust_actions) * khui_nc_cust_actions); +#ifdef DEBUG + assert(khui_cust_actions); +#endif + } + + if (i >= khui_n_cust_actions) { + i = khui_n_cust_actions ++; + act = PMALLOC(sizeof(khui_action)); + } else { + act = khui_cust_actions[i]; + if (act == NULL) + act = PMALLOC(sizeof(khui_action)); + } + +#ifdef DEBUG + assert(act); +#endif + + khui_cust_actions[i] = act; + + ZeroMemory(act, sizeof(*act)); + + act->cmd = KHUI_USERACTION_BASE + i; + act->type = type; + act->name = (name? PWCSDUP(name) : 0); + act->caption = PWCSDUP(caption); + act->tooltip = (tooltip? PWCSDUP(tooltip) : 0); + act->listener = hsub; + act->data = userdata; + act->state = 0; + + action = act->cmd; + + _done: + LeaveCriticalSection(&cs_actions); + + if (action) + kmq_post_message(KMSG_ACT, KMSG_ACT_NEW, action, NULL); + + return action; +} + +KHMEXP void * KHMAPI +khui_action_get_data(khm_int32 action) { + khui_action * act; + void * data; + + EnterCriticalSection(&cs_actions); + act = khui_find_action(action); + if (act == NULL || (act->state & KHUI_ACTIONSTATE_DELETED)) + data = NULL; + else + data = act->data; + LeaveCriticalSection(&cs_actions); + + return data; +} + +KHMEXP void KHMAPI +khui_action_delete(khm_int32 action) { + khui_action * act; + + EnterCriticalSection(&cs_actions); + + act = khui_find_action(action); + + if (act == NULL) { + LeaveCriticalSection(&cs_actions); + return; + } + + /* for the moment, even when the action is deleted, we don't free + up the block of memory used by the khui_action structure. When + a new action is created, it will reuse deleted action + structures. */ + act->state |= KHUI_ACTIONSTATE_DELETED; + if (act->name) + PFREE(act->name); + if (act->caption) + PFREE(act->caption); + if (act->tooltip) + PFREE(act->tooltip); + if (act->listener) + kmq_delete_subscription(act->listener); + act->name = NULL; + act->caption = NULL; + act->tooltip = NULL; + act->listener = NULL; + LeaveCriticalSection(&cs_actions); + + kmq_post_message(KMSG_ACT, KMSG_ACT_DELETE, action, NULL); +} + +#define MENU_NC_ITEMS 8 + +KHMEXP khui_menu_def * KHMAPI +khui_menu_create(khm_int32 action) +{ + khui_menu_def * d; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->cmd = action; + d->nc_items = MENU_NC_ITEMS; + d->items = PMALLOC(sizeof(*(d->items)) * d->nc_items); + + d->state = KHUI_MENUSTATE_ALLOCD; + + if (action) { + int i; + EnterCriticalSection(&cs_actions); + + for (i=0; i < khui_n_cust_menus; i++) { + if (khui_cust_menus[i] == NULL) + break; + } + + if (i >= khui_n_cust_menus) { + + if (khui_n_cust_menus + 1 >= khui_nc_cust_menus) { + khui_nc_cust_menus = UBOUNDSS(khui_n_cust_menus + 1, + CACT_NC_ALLOC, CACT_NC_ALLOC); + khui_cust_menus = + PREALLOC(khui_cust_menus, + sizeof(khui_cust_menus[0]) * khui_nc_cust_menus); + } + + i = khui_n_cust_menus ++; + } + + khui_cust_menus[i] = d; + + LeaveCriticalSection(&cs_actions); + } + + return d; +} + +KHMEXP void KHMAPI +khui_set_main_window(HWND hwnd) { + khui_hwnd_main = hwnd; +} + +KHMEXP void KHMAPI +khui_action_trigger(khm_int32 action, khui_action_context * ctx) { + khui_action_context save; + + if (!khui_hwnd_main) + return; + + if (ctx) { + khui_context_get(&save); + + khui_context_set_indirect(ctx); + } + + SendMessage(khui_hwnd_main, WM_COMMAND, + MAKEWPARAM(action, 0), (LPARAM) 0); + + if (ctx) { + khui_context_set_indirect(&save); + khui_context_release(&save); + } +} + +KHMEXP khui_menu_def * KHMAPI +khui_menu_dup(khui_menu_def * src) +{ + khui_menu_def * d; + size_t i; + size_t n; + + EnterCriticalSection(&cs_actions); + + d = khui_menu_create(src->cmd); + + if (!(src->state & KHUI_MENUSTATE_ALLOCD)) + n = khui_action_list_length(src->items); + else + n = src->n_items; + + for (i=0; i<n; i++) { + if (src->items[i].flags & KHUI_ACTIONREF_PACTION) { + khui_menu_insert_paction(d, (khm_size) -1, src->items[i].p_action, src->items[i].flags); + } else { + khui_menu_insert_action(d, (khm_size) -1, src->items[i].action, 0); + } + } + + LeaveCriticalSection(&cs_actions); + + return d; +} + +KHMEXP void KHMAPI +khui_menu_delete(khui_menu_def * d) +{ + int i; + + /* non-allocated menus are assumed to have no pointers to other + allocated blocks */ + if(!(d->state & KHUI_MENUSTATE_ALLOCD)) { + /* we shouldn't have tried to delete a constant menu */ +#ifdef DEBUG + assert(FALSE); +#endif + return; + } + + EnterCriticalSection(&cs_actions); + + for (i=0; i < khui_n_cust_menus; i++) { + if (khui_cust_menus[i] == d) { + khui_cust_menus[i] = NULL; + break; + } + } + + for(i=0; i< (int) d->n_items; i++) { + if(d->items[i].flags & KHUI_ACTIONREF_FREE_PACTION) + PFREE(d->items[i].p_action); + } + + if(d->items) + PFREE(d->items); + PFREE(d); + + LeaveCriticalSection(&cs_actions); +} + +static void +menu_assert_size(khui_menu_def * d, size_t n) +{ + + assert(d->state & KHUI_MENUSTATE_ALLOCD); + + if(n > (int) d->nc_items) { + khui_action_ref * ni; + + d->nc_items = UBOUNDSS(n, MENU_NC_ITEMS, MENU_NC_ITEMS); + ni = PMALLOC(sizeof(*(d->items)) * d->nc_items); + memcpy(ni, d->items, sizeof(*(d->items)) * d->n_items); + PFREE(d->items); + d->items = ni; + } +} + +static void +menu_const_to_allocd(khui_menu_def * d) +{ + khui_action_ref * olist; + khui_action_ref * nlist; + khm_size n; + + assert(!(d->state & KHUI_MENUSTATE_ALLOCD)); + + olist = d->items; + n = khui_action_list_length(d->items); + + d->nc_items = UBOUNDSS(n, MENU_NC_ITEMS, MENU_NC_ITEMS); + nlist = PMALLOC(sizeof(d->items[0]) * d->nc_items); + memcpy(nlist, olist, sizeof(d->items[0]) * n); + + d->items = nlist; + d->n_items = n; + d->state |= KHUI_MENUSTATE_ALLOCD; +} + +KHMEXP void KHMAPI +khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 action, khm_int32 flags) +{ + khm_size i; + + EnterCriticalSection(&cs_actions); + + if (!(d->state & KHUI_MENUSTATE_ALLOCD)) + menu_const_to_allocd(d); + + assert(d->state & KHUI_MENUSTATE_ALLOCD); + assert(action == KHUI_MENU_SEP || action > 0); + + if (idx < 0 || idx > d->n_items) + idx = d->n_items; + + menu_assert_size(d, d->n_items + 1); + + if (idx < d->n_items) { + memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0])); + } + + d->items[idx].flags = flags; + d->items[idx].action = action; + if (action == KHUI_MENU_SEP) + d->items[idx].flags |= KHUI_ACTIONREF_SEP; + + d->n_items++; + + /* only one action is allowed to have the KHUI_ACTIONREF_DEFAULT + flag */ + if (flags & KHUI_ACTIONREF_DEFAULT) { + for (i=0; i < d->n_items; i++) { + if (i != idx && (d->items[i].flags & KHUI_ACTIONREF_DEFAULT)) + d->items[i].flags &= ~KHUI_ACTIONREF_DEFAULT; + } + } + + LeaveCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * paction, int flags) +{ + khm_size i; + + if (paction == NULL) + return; + + EnterCriticalSection(&cs_actions); + + if (!(d->state & KHUI_MENUSTATE_ALLOCD)) + menu_const_to_allocd(d); + + assert(d->state & KHUI_MENUSTATE_ALLOCD); + + if (idx < 0 || idx > d->n_items) + idx = d->n_items; + + menu_assert_size(d, d->n_items + 1); + + if (idx < d->n_items) { + memmove(&d->items[idx + 1], &d->items[idx], (d->n_items - idx) * sizeof(d->items[0])); + } + + d->items[idx].flags = flags | KHUI_ACTIONREF_PACTION; + d->items[idx].p_action = paction; + + d->n_items++; + + /* only one action is allowed to have the KHUI_ACTIONREF_DEFAULT + flag */ + if (flags & KHUI_ACTIONREF_DEFAULT) { + for (i=0; i < d->n_items; i++) { + if (i != idx && (d->items[i].flags & KHUI_ACTIONREF_DEFAULT)) + d->items[i].flags &= ~KHUI_ACTIONREF_DEFAULT; + } + } + + LeaveCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_menu_remove_action(khui_menu_def * d, khm_size idx) { + + EnterCriticalSection(&cs_actions); + + if (!(d->state & KHUI_MENUSTATE_ALLOCD)) + menu_const_to_allocd(d); + + assert(d->state & KHUI_MENUSTATE_ALLOCD); + + if (idx >= 0 && idx < d->n_items) { + + if (idx < d->n_items - 1) { + memmove(&d->items[idx], &d->items[idx + 1], + ((d->n_items - 1) - idx) * sizeof(d->items[0])); + } + + d->n_items--; + + } + + LeaveCriticalSection(&cs_actions); +} + +KHMEXP khm_size KHMAPI +khui_menu_get_size(khui_menu_def * d) { + + khm_size size; + + EnterCriticalSection(&cs_actions); + + if (d->state & KHUI_MENUSTATE_ALLOCD) + size = d->n_items; + else + size = khui_action_list_length(d->items); + + LeaveCriticalSection(&cs_actions); + + return size; +} + +KHMEXP khui_action_ref * +khui_menu_get_action(khui_menu_def * d, khm_size idx) { + + khui_action_ref * act = NULL; + khm_size n; + + EnterCriticalSection(&cs_actions); + + if (d->state & KHUI_MENUSTATE_ALLOCD) + n = d->n_items; + else + n = khui_action_list_length(d->items); + + if (idx < 0 || idx >= n) + act = NULL; + else + act = &d->items[idx]; + + LeaveCriticalSection(&cs_actions); + + return act; +} + +KHMEXP khui_menu_def * KHMAPI +khui_find_menu(khm_int32 id) { + khui_menu_def * d; + int i; + + if (id < KHUI_USERACTION_BASE) { + + /* the list of system menus are considered immutable. */ + + d = khui_all_menus; + for(i=0;i<khui_n_all_menus;i++) { + if(id == d[i].cmd) + return &d[i]; + } + + return NULL; + } else { + d = NULL; + + EnterCriticalSection(&cs_actions); + for (i=0; i < khui_n_cust_menus; i++) { + if (khui_cust_menus[i] && + khui_cust_menus[i]->cmd == id) { + d = khui_cust_menus[i]; + break; + } + } + LeaveCriticalSection(&cs_actions); + + return d; + } +} + +KHMEXP khui_action * KHMAPI +khui_find_action(khm_int32 id) { + khui_action * act = NULL; + int i; + + if (id < KHUI_USERACTION_BASE) { + act = khui_actions; + for(i=0;i<khui_n_actions;i++) { + if(act[i].cmd == id) + return &act[i]; + } + + return NULL; + } + + EnterCriticalSection(&cs_actions); + if (id >= KHUI_USERACTION_BASE && + (id - KHUI_USERACTION_BASE) < khui_n_cust_actions) { + act = khui_cust_actions[id - KHUI_USERACTION_BASE]; +#ifdef DEBUG + assert(!act || act->cmd == id); +#endif + if (act && (act->state & KHUI_ACTIONSTATE_DELETED)) + act = NULL; + } + LeaveCriticalSection(&cs_actions); + + return act; +} + +KHMEXP khui_action * KHMAPI +khui_find_named_action(const wchar_t * name) { + int i; + khui_action * act; + khui_action ** pact; + + if(!name) + return NULL; + + act = khui_actions; + for(i=0;i<khui_n_actions;i++) { + if(!act[i].name) + continue; + if(!wcscmp(act[i].name, name)) + return &act[i]; + } + + act = NULL; + + EnterCriticalSection(&cs_actions); + + pact = khui_cust_actions; + for(i=0;i<khui_n_cust_actions;i++) { + if(!pact[i] || !pact[i]->name) + continue; + + if(!wcscmp(pact[i]->name, name)) { + + if (!(pact[i]->state & KHUI_ACTIONSTATE_DELETED)) { + act = pact[i]; + } + break; + } + } + + LeaveCriticalSection(&cs_actions); + + return act; +} + +KHMEXP size_t KHMAPI +khui_action_list_length(khui_action_ref * ref) { + size_t c = 0; + + EnterCriticalSection(&cs_actions); + + while(ref && ref->action != KHUI_MENU_END && + !(ref->flags & KHUI_ACTIONREF_END)) { + c++; + ref++; + } + + LeaveCriticalSection(&cs_actions); + + return c; +} + +KHMEXP void KHMAPI +khui_check_radio_action(khui_menu_def * d, khm_int32 cmd) +{ + khui_action_ref * r; + khui_action * act; + + EnterCriticalSection(&cs_actions); + + r = d->items; + while(r && r->action != KHUI_MENU_END && + (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) { + if(r->flags & KHUI_ACTIONREF_PACTION) { + act = r->p_action; + } else { + act = khui_find_action(r->action); + } + + if(act) { + if(act->cmd == cmd) + act->state |= KHUI_ACTIONSTATE_CHECKED; + else + act->state &= ~KHUI_ACTIONSTATE_CHECKED; + } + r++; + } + + LeaveCriticalSection(&cs_actions); + + kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0); +} + +KHMEXP void KHMAPI +khui_check_action(khm_int32 cmd, khm_boolean check) { + khui_action * act; + + act = khui_find_action(cmd); + if (!act) + return; + + EnterCriticalSection(&cs_actions); + + if (check && !(act->state & KHUI_ACTIONSTATE_CHECKED)) + act->state |= KHUI_ACTIONSTATE_CHECKED; + else if (!check && (act->state & KHUI_ACTIONSTATE_CHECKED)) + act->state &= ~KHUI_ACTIONSTATE_CHECKED; + else { + LeaveCriticalSection(&cs_actions); + return; + } + + LeaveCriticalSection(&cs_actions); + + kmq_post_message(KMSG_ACT, KMSG_ACT_CHECK, 0, 0); +} + +KHMEXP void KHMAPI +khui_enable_actions(khui_menu_def * d, khm_boolean enable) +{ + khui_action_ref * r; + int delta = FALSE; + khui_action * act; + + EnterCriticalSection(&cs_actions); + + r = d->items; + while(r && r->action != KHUI_MENU_END && + (!(d->state & KHUI_MENUSTATE_ALLOCD) || (r - d->items) < (int) d->n_items)) { + if(r->flags & KHUI_ACTIONREF_PACTION) { + act = r->p_action; + } else { + act = khui_find_action(r->action); + } + + if(act) { + int old_state = act->state; + + if(enable) + act->state &= ~KHUI_ACTIONSTATE_DISABLED; + else + act->state |= KHUI_ACTIONSTATE_DISABLED; + + if(old_state != act->state) + delta = TRUE; + } + r++; + } + + LeaveCriticalSection(&cs_actions); + + if(delta) { + kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0); + } +} + +KHMEXP void KHMAPI +khui_enable_action(khm_int32 cmd, khm_boolean enable) { + khui_action * act; + + act = khui_find_action(cmd); + if (!act) + return; + + EnterCriticalSection(&cs_actions); + + if (enable && (act->state & KHUI_ACTIONSTATE_DISABLED)) { + act->state &= ~KHUI_ACTIONSTATE_DISABLED; + } else if (!enable && !(act->state & KHUI_ACTIONSTATE_DISABLED)) { + act->state |= KHUI_ACTIONSTATE_DISABLED; + } else { + LeaveCriticalSection(&cs_actions); + return; + } + + LeaveCriticalSection(&cs_actions); + + kmq_post_message(KMSG_ACT, KMSG_ACT_ENABLE, 0, 0); +} + +KHMEXP HACCEL KHMAPI +khui_create_global_accel_table(void) { + int i; + ACCEL * accels; + HACCEL ha; + + accels = PMALLOC(sizeof(ACCEL) * khui_n_accel_global); + for(i=0;i<khui_n_accel_global;i++) { + accels[i].cmd = (WORD) khui_accel_global[i].cmd; + accels[i].fVirt = (BYTE) khui_accel_global[i].mod; + accels[i].key = (WORD) khui_accel_global[i].key; + } + + ha = CreateAcceleratorTable(accels, khui_n_accel_global); + + PFREE(accels); + + return ha; +} + +KHMEXP khm_boolean KHMAPI +khui_get_cmd_accel_string(khm_int32 cmd, + wchar_t * buf, + khm_size bufsiz) { + int i; + khui_accel_def * def; + + /* should at least hold 2 characters */ + if(bufsiz < sizeof(wchar_t) * 2) + return FALSE; + + buf[0] = L'\0'; + + for(i=0;i<khui_n_accel_global;i++) { + if(khui_accel_global[i].cmd == cmd) + break; + } + + if(i==khui_n_accel_global) + return FALSE; + + def = &khui_accel_global[i]; + + if(def->mod & FALT) { + if(FAILED(StringCbCat(buf, bufsiz, L"Alt+"))) + return FALSE; + } + + + if(def->mod & FCONTROL) { + if(FAILED(StringCbCat(buf, bufsiz, L"Ctrl+"))) + return FALSE; + } + + if(def->mod & FSHIFT) { + if(FAILED(StringCbCat(buf, bufsiz, L"Shift+"))) + return FALSE; + } + + if(def->mod & FVIRTKEY) { + wchar_t mbuf[6]; + wchar_t * ap = NULL; + switch(def->key) { + case VK_TAB: + ap = L"Tab"; + break; + + case VK_ESCAPE: + ap = L"Esc"; + break; + + case VK_RETURN: + ap = L"Enter"; + break; + + case VK_F1: + ap = L"F1"; + break; + + case VK_F2: + ap = L"F2"; + break; + + case VK_F3: + ap = L"F3"; + break; + + case VK_F4: + ap = L"F4"; + break; + + case VK_F5: + ap = L"F5"; + break; + + case VK_F6: + ap = L"F6"; + break; + + case VK_F7: + ap = L"F7"; + break; + + case VK_F8: + ap = L"F8"; + break; + + case VK_F9: + ap = L"F9"; + break; + + case VK_F10: + ap = L"F10"; + break; + + case VK_F11: + ap = L"F11"; + break; + + case VK_F12: + ap = L"F12"; + break; + + case VK_DELETE: + ap = L"Del"; + break; + + default: + if((def->key >= '0' && + def->key <= '9') || + (def->key >= 'A' && + def->key <= 'Z')) { + ap = mbuf; + mbuf[0] = (wchar_t) def->key; + mbuf[1] = L'\0'; + } + } + if(ap) { + if(FAILED(StringCbCat(buf, bufsiz, ap))) + return FALSE; + } + else { + if(FAILED(StringCbCat(buf, bufsiz,L"???"))) + return FALSE; + } + + } else { + wchar_t mbuf[2]; + + mbuf[0] = (wchar_t) def->key; + mbuf[1] = L'\0'; + + if(FAILED(StringCbCat(buf, bufsiz, mbuf))) + return FALSE; + } + + return TRUE; +} + +/******************************************/ +/* contexts */ + +#define KHUI_ACTION_CONTEXT_MAGIC 0x39c49db5 + +static khm_int32 KHMAPI +khuiint_filter_selected(khm_handle cred, + khm_int32 vflags, + void * rock) { + khm_int32 flags; + if (KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &flags)) && + (flags & KCDB_CRED_FLAG_SELECTED)) + return TRUE; + else + return FALSE; +} + +static void +khuiint_context_release(khui_action_context * ctx) { + ctx->scope = KHUI_SCOPE_NONE; + if (ctx->identity) + kcdb_identity_release(ctx->identity); + ctx->identity = NULL; + ctx->cred_type = KCDB_CREDTYPE_INVALID; + if (ctx->cred) + kcdb_cred_release(ctx->cred); + ctx->cred = NULL; + ctx->n_headers = 0; + if (ctx->credset) + kcdb_credset_flush(ctx->credset); + ctx->n_sel_creds = 0; + ctx->int_cb_used = 0; + ctx->vparam = NULL; + ctx->cb_vparam = 0; +} + +static void +khuiint_copy_context(khui_action_context * ctxdest, + const khui_action_context * ctxsrc) +{ + ctxdest->scope = ctxsrc->scope; + + if (ctxsrc->scope == KHUI_SCOPE_IDENT) { + ctxdest->identity = ctxsrc->identity; + kcdb_identity_hold(ctxsrc->identity); + } else if (ctxsrc->scope == KHUI_SCOPE_CREDTYPE) { + ctxdest->identity = ctxsrc->identity; + ctxdest->cred_type = ctxsrc->cred_type; + if (ctxsrc->identity != NULL) + kcdb_identity_hold(ctxsrc->identity); + } else if (ctxsrc->scope == KHUI_SCOPE_CRED) { + kcdb_cred_get_identity(ctxsrc->cred, &ctxdest->identity); + kcdb_cred_get_type(ctxsrc->cred, &ctxdest->cred_type); + ctxdest->cred = ctxsrc->cred; + kcdb_cred_hold(ctxsrc->cred); + } else if (ctxsrc->scope == KHUI_SCOPE_GROUP) { + khm_size cb_total; + int i; + + ctxdest->n_headers = ctxsrc->n_headers; + cb_total = 0; + for (i=0; i < (int) ctxsrc->n_headers; i++) { + cb_total += UBOUND32(ctxsrc->headers[i].cb_data); + } + + if (ctxdest->int_cb_buf < cb_total) { + + if (ctxdest->int_buf) + PFREE(ctxdest->int_buf); + + ctxdest->int_cb_buf = cb_total; + ctxdest->int_buf = PMALLOC(cb_total); + } + +#ifdef DEBUG + assert(ctxdest->int_buf || cb_total == 0); +#endif + ctxdest->int_cb_used = 0; + + for (i=0; i < (int) ctxsrc->n_headers; i++) { + ctxdest->headers[i].attr_id = ctxsrc->headers[i].attr_id; + ctxdest->headers[i].cb_data = ctxsrc->headers[i].cb_data; + if (ctxsrc->headers[i].cb_data > 0) { + ctxdest->headers[i].data = + BYTEOFFSET(ctxdest->int_buf, + ctxdest->int_cb_used); + memcpy(ctxdest->headers[i].data, + ctxsrc->headers[i].data, + ctxsrc->headers[i].cb_data); + ctxdest->int_cb_used += + UBOUND32(ctxsrc->headers[i].cb_data); + } else { + ctxdest->headers[i].data = NULL; + } + } + } + + if (ctxsrc->credset) { + + if (ctxdest->credset == NULL) + kcdb_credset_create(&ctxdest->credset); +#ifdef DEBUG + assert(ctxdest->credset != NULL); +#endif + + kcdb_credset_flush(ctxdest->credset); + + kcdb_credset_extract_filtered(ctxdest->credset, + ctxsrc->credset, + khuiint_filter_selected, + NULL); + + kcdb_credset_get_size(ctxdest->credset, + &ctxdest->n_sel_creds); + } else { + if (ctxdest->credset != NULL) + kcdb_credset_flush(ctxdest->credset); + ctxdest->n_sel_creds = 0; + } + + /* For now, we simply transfer the vparam buffer into the new + context. If we are copying, we also need to modify + khui_context_release() to free the allocated buffer */ +#if 0 + if (ctxsrc->vparam && ctxsrc->cb_vparam) { + ctxdest->vparam = PMALLOC(ctxsrc->cb_vparam); +#ifdef DEBUG + assert(ctxdest->vparam); +#endif + memcpy(ctxdest->vparam, ctxsrc->vparam, ctxsrc->cb_vparam); + ctxdest->cb_vparam = ctxsrc->cb_vparam; + } else { +#endif + ctxdest->vparam = ctxsrc->vparam; + ctxdest->cb_vparam = ctxsrc->cb_vparam; +#if 0 + } +#endif +} + +static void +khuiint_context_init(khui_action_context * ctx) { + ctx->magic = KHUI_ACTION_CONTEXT_MAGIC; + ctx->scope = KHUI_SCOPE_NONE; + ctx->identity = NULL; + ctx->cred_type = KCDB_CREDTYPE_INVALID; + ctx->cred = NULL; + ZeroMemory(ctx->headers, sizeof(ctx->headers)); + ctx->n_headers = 0; + ctx->credset = NULL; + ctx->n_sel_creds = 0; + ctx->int_buf = NULL; + ctx->int_cb_buf = 0; + ctx->int_cb_used = 0; + ctx->vparam = NULL; + ctx->cb_vparam = 0; +} + +khui_action_context khui_ctx = { + KHUI_ACTION_CONTEXT_MAGIC, + KHUI_SCOPE_NONE, + NULL, + KCDB_CREDTYPE_INVALID, + NULL, + { + {KCDB_ATTR_INVALID,NULL,0}, + {KCDB_ATTR_INVALID,NULL,0}, + {KCDB_ATTR_INVALID,NULL,0}, + {KCDB_ATTR_INVALID,NULL,0}, + {KCDB_ATTR_INVALID,NULL,0}, + {KCDB_ATTR_INVALID,NULL,0} + }, + 0, + NULL, + 0, + NULL, + 0, + 0, + NULL, + 0}; + +khm_int32 KHMAPI +set_cred_select_flag(khm_handle cred, void * rock) { + kcdb_cred_set_flags(cred, KCDB_CRED_FLAG_SELECTED, + KCDB_CRED_FLAG_SELECTED); + return KHM_ERROR_SUCCESS; +} + +KHMEXP void KHMAPI +khui_context_create(khui_action_context * ctx, + khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred) +{ + khui_action_context tctx; + + khuiint_context_init(&tctx); + khuiint_context_init(ctx); + + tctx.scope = scope; + tctx.identity = identity; + tctx.cred_type = cred_type; + tctx.cred = cred; + + /* fill up the credset based on the scope */ + if (scope != KHUI_SCOPE_NONE) { + if (tctx.credset == NULL) + kcdb_credset_create(&tctx.credset); + else + kcdb_credset_flush(tctx.credset); + + if (scope == KHUI_SCOPE_IDENT) { + kcdb_credset_extract(tctx.credset, + NULL, + tctx.identity, + KCDB_CREDTYPE_INVALID); + } else if (scope == KHUI_SCOPE_CREDTYPE) { + kcdb_credset_extract(tctx.credset, + NULL, + tctx.identity, + tctx.cred_type); + } else if (scope == KHUI_SCOPE_CRED) { + khm_handle dupcred = NULL; + kcdb_cred_dup(cred, &dupcred); + + kcdb_credset_add_cred(tctx.credset, dupcred, -1); + } else { +#ifdef DEBUG + /* KHUI_SCOPE_GROUP is not used with + khui_context_create() */ + assert(FALSE); +#endif + } + + kcdb_credset_apply(tctx.credset, set_cred_select_flag, + NULL); + + kcdb_credset_seal(tctx.credset); + } + + khuiint_copy_context(ctx, &tctx); +} + +KHMEXP void KHMAPI +khui_context_set(khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred, + khui_header *headers, + khm_size n_headers, + khm_handle cs_src) { + + khui_context_set_ex(scope, + identity, + cred_type, + cred, + headers, + n_headers, + cs_src, + NULL, + 0); +} + +KHMEXP void KHMAPI +khui_context_set_ex(khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred, + khui_header *headers, + khm_size n_headers, + khm_handle cs_src, + void * vparam, + khm_size cb_vparam) +{ + khui_action_context tctx; + + EnterCriticalSection(&cs_actions); + + khuiint_context_release(&khui_ctx); + + khuiint_context_init(&tctx); + + tctx.scope = scope; + tctx.identity = identity; + tctx.cred_type = cred_type; + tctx.cred = cred; + if (headers) { + tctx.n_headers = n_headers; + memcpy(tctx.headers, + headers, + sizeof(*headers) * n_headers); + } else { + tctx.n_headers = 0; + } + tctx.credset = cs_src; + tctx.n_sel_creds = 0; /* ignored */ + tctx.vparam = vparam; + tctx.cb_vparam = cb_vparam; + tctx.int_buf = NULL; + tctx.int_cb_buf = 0; + tctx.int_cb_used = 0; + + khuiint_copy_context(&khui_ctx, &tctx); + + khui_context_refresh(); + + LeaveCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_context_set_indirect(khui_action_context * ctx) +{ + EnterCriticalSection(&cs_actions); + + khuiint_context_release(&khui_ctx); + + khuiint_copy_context(&khui_ctx, ctx); + + khui_context_refresh(); + + LeaveCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_context_refresh(void) { + khm_int32 flags; + + EnterCriticalSection(&cs_actions); + if (khui_ctx.identity) { + /* an identity is selected */ + + if (KHM_SUCCEEDED(kcdb_identity_get_flags(khui_ctx.identity, + &flags)) && + (flags & KCDB_IDENT_FLAG_DEFAULT)) { + khui_check_action(KHUI_ACTION_SET_DEF_ID, TRUE); + khui_enable_action(KHUI_ACTION_SET_DEF_ID, FALSE); + } else { + khui_check_action(KHUI_ACTION_SET_DEF_ID, FALSE); + khui_enable_action(KHUI_ACTION_SET_DEF_ID, TRUE); + } + } else { + khui_check_action(KHUI_ACTION_SET_DEF_ID, FALSE); + khui_enable_action(KHUI_ACTION_SET_DEF_ID, FALSE); + } + + if (khui_ctx.scope != KHUI_SCOPE_NONE) { + khui_enable_action(KHUI_ACTION_PROPERTIES, TRUE); + } else { + khui_enable_action(KHUI_ACTION_PROPERTIES, FALSE); + } + + LeaveCriticalSection(&cs_actions); + + kmq_post_message(KMSG_ACT, KMSG_ACT_REFRESH, 0, 0); +} + +KHMEXP void KHMAPI +khui_context_get(khui_action_context * ctx) +{ + EnterCriticalSection(&cs_actions); + + khuiint_context_init(ctx); + khuiint_copy_context(ctx, &khui_ctx); + + if (ctx->credset) { + kcdb_credset_seal(ctx->credset); + } + + LeaveCriticalSection(&cs_actions); +} + +KHMEXP void KHMAPI +khui_context_release(khui_action_context * ctx) +{ +#ifdef DEBUG + assert(ctx->magic == KHUI_ACTION_CONTEXT_MAGIC); +#endif + + khuiint_context_release(ctx); + if (ctx->credset) { + kcdb_credset_unseal(ctx->credset); + kcdb_credset_delete(ctx->credset); + } + ctx->credset = NULL; + if (ctx->int_buf) + PFREE(ctx->int_buf); + ctx->int_buf = NULL; +#if 0 + if (ctx->vparam && ctx->cb_vparam > 0) { + PFREE(ctx->vparam); + ctx->vparam = NULL; + } + ctx->cb_vparam = 0; +#else + ctx->vparam = 0; + ctx->cb_vparam = 0; +#endif +} + +KHMEXP void KHMAPI +khui_context_reset(void) +{ + EnterCriticalSection(&cs_actions); + + khuiint_context_release(&khui_ctx); + + khui_context_refresh(); + + LeaveCriticalSection(&cs_actions); +} + +KHMEXP khm_int32 KHMAPI +khui_context_cursor_filter(khm_handle cred, + khm_int32 flags, + void * rock) { + khui_action_context * ctx = (khui_action_context *) rock; + khm_int32 rv; + + if (ctx->scope == KHUI_SCOPE_NONE) + return 0; + else if (ctx->scope == KHUI_SCOPE_IDENT) { + khm_handle c_ident; + + if (KHM_FAILED(kcdb_cred_get_identity(cred, &c_ident))) + return 0; + + rv = (c_ident == ctx->identity); + + kcdb_identity_release(c_ident); + + return rv; + } else if (ctx->scope == KHUI_SCOPE_CREDTYPE) { + khm_handle c_ident; + khm_int32 c_type; + + if (KHM_FAILED(kcdb_cred_get_type(cred, &c_type)) || + c_type != ctx->cred_type) + return 0; + + if (ctx->identity == NULL) + return 1; + + if (KHM_FAILED(kcdb_cred_get_identity(cred, &c_ident))) + return 0; + + rv = (c_ident == ctx->identity); + + kcdb_identity_release(c_ident); + + return rv; + } else if (ctx->scope == KHUI_SCOPE_CRED) { + return kcdb_creds_is_equal(cred, ctx->cred); + } else if (ctx->scope == KHUI_SCOPE_GROUP) { + int i; + + rv = 1; + + for (i=0; i < (int) ctx->n_headers && rv; i++) { + kcdb_attrib * pattr; + kcdb_type * ptype; + DWORD buffer[1024]; /* 4096 bytes */ + khm_size cb; + + if (kcdb_cred_get_attr(cred, ctx->headers[i].attr_id, + NULL, + NULL, + &cb) != KHM_ERROR_TOO_LONG) { + /* the header doesn't exist anyway */ + rv = (ctx->headers[i].cb_data == 0); + continue; + } +#ifdef DEBUG + assert(cb <= sizeof(buffer)); +#endif + cb = sizeof(buffer); + + if (KHM_FAILED(kcdb_cred_get_attr(cred, + ctx->headers[i].attr_id, + NULL, + (void *) buffer, + &cb))) { + rv = 0; + continue; + } + + if (KHM_FAILED(kcdb_attrib_get_info(ctx->headers[i].attr_id, + &pattr))) { + rv = 0; + continue; + } + + if (KHM_FAILED(kcdb_type_get_info(pattr->type, &ptype))) { + rv = 0; + kcdb_attrib_release_info(pattr); + continue; + } + + if ((*ptype->comp)(ctx->headers[i].data, + ctx->headers[i].cb_data, + (void *) buffer, + cb) != 0) + rv = 1; + + kcdb_type_release_info(ptype); + kcdb_attrib_release_info(pattr); + } + + return rv; + } else + return 0; +} diff --git a/krb5-1-6/src/windows/identity/uilib/actiondef.cfg b/krb5-1-6/src/windows/identity/uilib/actiondef.cfg new file mode 100644 index 000000000..4537c9849 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/actiondef.cfg @@ -0,0 +1,67 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +$file_prefix = <<EOS; +/* +This file was autogenerated from src/ui/actiondef.cfg and src/ui/actions.csv. + +Do not modify directly. +*/ + +#define NOEXPORT + +#include<khuidefs.h> +#include<khhelp.h> +#include<intaction.h> +#include"../ui/resource.h" + +khui_action khui_actions [] = { +EOS + +$record_prefix = "ACTION_FULL("; + +$record_sep = ",\n"; + +$record_postfix = ")"; + +$file_postfix = <<EOS; + +}; + +int khui_n_actions = sizeof(khui_actions) / sizeof(khui_action); + +EOS + +$skip_lines = 1; + +sub rec_handler { + $arr = shift; + if($$arr[2] =~ /^$/) { + $$arr[2] = "NULL"; + } else { + $$arr[2] = "L\"".$$arr[2]."\""; + } +} + +$record_parser = \&rec_handler; diff --git a/krb5-1-6/src/windows/identity/uilib/actions.csv b/krb5-1-6/src/windows/identity/uilib/actions.csv new file mode 100644 index 000000000..dc6286bf2 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/actions.csv @@ -0,0 +1,55 @@ +Command,Type,Name,Img Normal,Img Hot,Img Disabled,Ico Normal,Ico Disabled,Caption,Tooltip,Topic,State +KHUI_MENU_FILE,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_FILE,0,IDH_MENU_FILE,0 +KHUI_MENU_CRED,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_CRED,0,IDH_MENU_CRED,0 +KHUI_MENU_VIEW,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_VIEW,0,IDH_MENU_VIEW,0 +KHUI_MENU_OPTIONS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_OPTIONS,0,IDH_MENU_OPTIONS,0 +KHUI_MENU_HELP,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_HELP,0,IDH_MENU_HELP,0 +KHUI_MENU_LAYOUT,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_LAYOUT,0,0,0 +KHUI_MENU_TOOLBARS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_TOOLBARS,0,0,0 +KHUI_MENU_COLUMNS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_CHOOSE_COLS,0,IDH_ACTION_CHOOSE_COLS,0 +KHUI_MENU_DESTROY_CRED,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_DESTROY_CRED,0,0,0 +KHUI_MENU_RENEW_CRED,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_RENEW_CRED,0,0,0 +KHUI_MENU_SETDEF,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_MENU_SETDEF,0,0,0 +KHUI_ACTION_PROPERTIES,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_PROPERTIES,IDS_ACTIONT_PROPERTIES,IDH_ACTION_PROPERTIES,0 +KHUI_ACTION_EXIT,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_EXIT,IDS_ACTIONT_EXIT,IDH_ACTION_EXIT,0 +KHUI_ACTION_SET_DEF_ID,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_SET_DEF_ID,IDS_ACTIONT_SET_DEF_ID,IDH_ACTION_SET_DEF_ID,0 +KHUI_ACTION_SET_SRCH_ID,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_SET_SRCH_ID,0,IDH_ACTION_SET_SRCH_ID,KHUI_ACTIONSTATE_DISABLED +KHUI_ACTION_PASSWD_ID,KHUI_ACTIONTYPE_TRIGGER,,IDB_CHPW,0,IDB_CHPW_DIS,IDB_CHPW_SM,IDB_CHPW_DIS_SM,IDS_ACTION_PASSWD_ID,IDS_ACTIONT_PASSWD_ID,IDH_ACTION_PASSWD_ID,0 +KHUI_ACTION_NEW_CRED,KHUI_ACTIONTYPE_TRIGGER,,IDB_TK_NEW,0,IDB_TK_NEW_DIS,IDB_TK_NEW_SM,IDB_TK_NEW_DIS_SM,IDS_ACTION_NEW_CRED,IDS_ACTIONT_NEW_CRED,IDH_ACTION_NEW_CRED,0 +KHUI_ACTION_RENEW_CRED,KHUI_ACTIONTYPE_TRIGGER,,IDB_TK_REFRESH,0,IDB_TK_REFRESH_DIS,IDB_TK_REFRESH_SM,IDB_TK_REFRESH_DIS_SM,IDS_ACTION_RENEW_CRED,IDS_ACTIONT_RENEW_CRED,0,0 +KHUI_ACTION_DESTROY_CRED,KHUI_ACTIONTYPE_TRIGGER,,IDB_TK_DELETE,0,IDB_TK_DELETE_DIS,IDB_TK_DELETE_SM,IDB_TK_DELETE_DIS_SM,IDS_ACTION_DESTROY_CRED,IDS_ACTIONT_DESTROY_CRED,0,0 +KHUI_ACTION_LAYOUT_ID,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_ID,0,0,KHUI_ACTIONSTATE_CHECKED +KHUI_ACTION_LAYOUT_TYPE,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_TYPE,0,0,0 +KHUI_ACTION_LAYOUT_LOC,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_LOC,0,0,0 +KHUI_ACTION_LAYOUT_CUST,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_CUST,0,0,0 +KHUI_ACTION_LAYOUT_MINI,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_LAYOUT_MINI,0,0,0 +KHUI_ACTION_TB_STANDARD,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_TB_STANDARD,0,0,KHUI_ACTIONSTATE_CHECKED|KHUI_ACTIONSTATE_DISABLED +KHUI_ACTION_VIEW_ALL_IDS,KHUI_ACTIONTYPE_TRIGGER | KHUI_ACTIONTYPE_TOGGLE,,0,0,0,0,0,IDS_ACTION_VIEW_ALL_IDS,0,0,0 +KHUI_ACTION_DEBUG_WINDOW,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_DEBUG_WINDOW,0,IDH_ACTION_DEBUG_WINDOW,KHUI_ACTIONSTATE_DISABLED +KHUI_ACTION_VIEW_REFRESH,KHUI_ACTIONTYPE_TRIGGER,,IDB_VW_REFRESH,0,0,IDB_VW_REFRESH_SM,0,IDS_ACTION_VIEW_REFRESH,IDS_ACTIONT_VIEW_REFRESH,IDH_ACTION_VIEW_REFRESH,0 +KHUI_ACTION_OPT_IDENTS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_OPT_IDENTS,IDS_ACTIONT_OPT_IDENTS,IDH_ACTION_OPT_INIT,0 +KHUI_ACTION_OPT_KHIM,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_OPT_KHIM,IDS_ACTIONT_OPT_KHIM,IDH_ACTION_OPT_KHIM,0 +KHUI_ACTION_OPT_NOTIF,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_OPT_NOTIF,IDS_ACTIONT_OPT_NOTIF,IDH_ACTION_OPT_NOTIF,0 +KHUI_ACTION_OPT_PLUGINS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_OPT_PLUGINS,IDS_ACTIONT_OPT_PLUGINS,IDH_ACTION_OPT_KHIM,0 +KHUI_ACTION_OPT_APPEAR,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_OPT_APPEAR,IDS_ACTIONT_OPT_APPEAR,0,0 +KHUI_ACTION_HELP_CTX,KHUI_ACTIONTYPE_TRIGGER,,IDB_HELP,0,0,IDB_HELP_SM,0,IDS_ACTION_HELP_CTX,IDS_ACTIONT_HELP_CTX,0,0 +KHUI_ACTION_HELP_CONTENTS,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_HELP_CONTENTS,0,0,0 +KHUI_ACTION_HELP_INDEX,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_HELP_INDEX,0,0,0 +KHUI_ACTION_HELP_ABOUT,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_HELP_ABOUT,0,0,0 +KHUI_ACTION_OPEN_APP,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_OPEN_APP,0,0,0 +KHUI_ACTION_CLOSE_APP,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_CLOSE_APP,0,0,0 +KHUI_ACTION_IMPORT,KHUI_ACTIONTYPE_TRIGGER,,IDB_IMPORT,0,IDB_IMPORT_DIS,IDB_IMPORT_SM,IDB_IMPORT_SM_DIS,IDS_ACTION_IMPORT,IDS_ACTIONT_IMPORT,0,0 +KHUI_ACTION_DESTROY_ALL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_DESTROY_ALL,0,0,0 +KHUI_ACTION_RENEW_ALL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_ACTION_RENEW_ALL,0,0,0 +KHUI_PACTION_OK,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_OK,0,0,0 +KHUI_PACTION_CANCEL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_CANCEL,0,0,0 +KHUI_PACTION_CLOSE,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_CLOSE,0,0,0 +KHUI_PACTION_BLANK,0,,IDB_TB_SPACE,0,IDB_TB_SPACE,IDB_TB_BLANK_SM,IDB_TB_BLANK_SM,0,0,0,KHUI_ACTIONSTATE_DISABLED +KHUI_PACTION_NEXT,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_NEXT,0,0,0 +KHUI_PACTION_YES,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_YES,0,0,0 +KHUI_PACTION_NO,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_NO,0,0,0 +KHUI_PACTION_YESALL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_YESALL,0,0,0 +KHUI_PACTION_NOALL,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_NOALL,0,0,0 +KHUI_PACTION_KEEP,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_KEEP,0,0,0 +KHUI_PACTION_REMOVE,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_REMOVE,0,0,0 +KHUI_PACTION_DISCARD,KHUI_ACTIONTYPE_TRIGGER,,0,0,0,0,0,IDS_PACTION_DISCARD,0,0,0 diff --git a/krb5-1-6/src/windows/identity/uilib/alert.c b/krb5-1-6/src/windows/identity/uilib/alert.c new file mode 100644 index 000000000..02df7a1e3 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/alert.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> +#include<utils.h> +#include<intalert.h> +#include<assert.h> + +#include<strsafe.h> + +/*********************************************************************** + Alerter +***********************************************************************/ + + +khui_alert * kh_alerts = NULL; +CRITICAL_SECTION cs_alerts; + +void +alert_init(void) +{ + InitializeCriticalSection(&cs_alerts); +} + +void +alert_exit(void) +{ + DeleteCriticalSection(&cs_alerts); +} + +KHMEXP khm_int32 KHMAPI +khui_alert_create_empty(khui_alert ** result) +{ + khui_alert * a; + + a = PMALLOC(sizeof(*a)); + ZeroMemory(a, sizeof(*a)); + + a->magic = KHUI_ALERT_MAGIC; + + /* set defaults */ + a->severity = KHERR_INFO; + a->flags = KHUI_ALERT_FLAG_FREE_STRUCT; + a->alert_type = KHUI_ALERTTYPE_NONE; + khui_context_create(&a->ctx, KHUI_SCOPE_NONE, + NULL, KCDB_CREDTYPE_INVALID, + NULL); + + khui_alert_hold(a); + EnterCriticalSection(&cs_alerts); + LPUSH(&kh_alerts, a); + LeaveCriticalSection(&cs_alerts); + + *result = a; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_create_simple(const wchar_t * title, + const wchar_t * message, + khm_int32 severity, + khui_alert ** result) +{ + khui_alert * a; + + khui_alert_create_empty(&a); + khui_alert_set_title(a, title); + khui_alert_set_message(a, message); + khui_alert_set_severity(a, severity); + + *result = a; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_set_title(khui_alert * alert, const wchar_t * title) +{ + size_t cb = 0; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + if(title) { + if(FAILED(StringCbLength(title, + KHUI_MAXCB_TITLE, + &cb))) { + return KHM_ERROR_INVALID_PARAM; + } + cb += sizeof(wchar_t); + } + + EnterCriticalSection(&cs_alerts); + if(alert->title && (alert->flags & KHUI_ALERT_FLAG_FREE_TITLE)) { + PFREE(alert->title); + alert->title = NULL; + alert->flags &= ~KHUI_ALERT_FLAG_FREE_TITLE; + } + if(title) { + alert->title = PMALLOC(cb); + StringCbCopy(alert->title, cb, title); + alert->flags |= KHUI_ALERT_FLAG_FREE_TITLE; + } + LeaveCriticalSection(&cs_alerts); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_set_flags(khui_alert * alert, khm_int32 mask, khm_int32 flags) +{ + assert(alert->magic == KHUI_ALERT_MAGIC); + + if (mask & ~KHUI_ALERT_FLAGMASK_RDWR) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_alerts); + alert->flags = + (alert->flags & ~mask) | + (flags & mask); + LeaveCriticalSection(&cs_alerts); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_set_severity(khui_alert * alert, khm_int32 severity) +{ + + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + alert->severity = severity; + LeaveCriticalSection(&cs_alerts); + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_set_suggestion(khui_alert * alert, + const wchar_t * suggestion) { + size_t cb = 0; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + if(suggestion) { + if(FAILED(StringCbLength(suggestion, + KHUI_MAXCB_MESSAGE - sizeof(wchar_t), + &cb))) { + return KHM_ERROR_INVALID_PARAM; + } + cb += sizeof(wchar_t); + } + + EnterCriticalSection(&cs_alerts); + if(alert->suggestion && + (alert->flags & KHUI_ALERT_FLAG_FREE_SUGGEST)) { + + PFREE(alert->suggestion); + alert->suggestion = NULL; + alert->flags &= ~KHUI_ALERT_FLAG_FREE_SUGGEST; + + } + + if(suggestion) { + alert->suggestion = PMALLOC(cb); + StringCbCopy(alert->suggestion, cb, suggestion); + alert->flags |= KHUI_ALERT_FLAG_FREE_SUGGEST; + } + LeaveCriticalSection(&cs_alerts); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_set_message(khui_alert * alert, const wchar_t * message) +{ + size_t cb = 0; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + if(message) { + if(FAILED(StringCbLength(message, + KHUI_MAXCB_MESSAGE - sizeof(wchar_t), + &cb))) { + return KHM_ERROR_INVALID_PARAM; + } + cb += sizeof(wchar_t); + } + + EnterCriticalSection(&cs_alerts); + if(alert->message && + (alert->flags & KHUI_ALERT_FLAG_FREE_MESSAGE)) { + + PFREE(alert->message); + alert->flags &= ~KHUI_ALERT_FLAG_FREE_MESSAGE; + } + + alert->message = NULL; + + if(message) { + alert->message = PMALLOC(cb); + StringCbCopy(alert->message, cb, message); + alert->flags |= KHUI_ALERT_FLAG_FREE_MESSAGE; + } + LeaveCriticalSection(&cs_alerts); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_clear_commands(khui_alert * alert) +{ + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + alert->n_alert_commands = 0; + LeaveCriticalSection(&cs_alerts); + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_add_command(khui_alert * alert, khm_int32 command_id) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + if(alert->n_alert_commands >= KHUI_MAX_ALERT_COMMANDS) + rv = KHM_ERROR_NO_RESOURCES; + else { + alert->alert_commands[alert->n_alert_commands++] = command_id; + } + LeaveCriticalSection(&cs_alerts); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_set_type(khui_alert * alert, khui_alert_type alert_type) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + alert->alert_type = alert_type; + LeaveCriticalSection(&cs_alerts); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_set_ctx(khui_alert * alert, + khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + khui_context_release(&alert->ctx); + khui_context_create(&alert->ctx, + scope, + identity, + cred_type, + cred); + LeaveCriticalSection(&cs_alerts); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_get_response(khui_alert * alert) +{ + khm_int32 response = 0; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + response = alert->response; + LeaveCriticalSection(&cs_alerts); + + return response; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_show(khui_alert * alert) +{ + assert(alert->magic == KHUI_ALERT_MAGIC); + + khui_alert_hold(alert); + /* the alert will be released when the message is processed */ + kmq_post_message(KMSG_ALERT, KMSG_ALERT_SHOW, 0, (void *) alert); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_show_modal(khui_alert * alert) +{ + khm_int32 rv; + + assert(alert->magic == KHUI_ALERT_MAGIC); + + khui_alert_hold(alert); + rv = kmq_send_message(KMSG_ALERT, KMSG_ALERT_SHOW_MODAL, 0, + (void *) alert); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_queue(khui_alert * alert) +{ + assert(alert->magic == KHUI_ALERT_MAGIC); + + khui_alert_hold(alert); + kmq_post_message(KMSG_ALERT, KMSG_ALERT_QUEUE, 0, (void *) alert); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_show_simple(const wchar_t * title, + const wchar_t * message, + khm_int32 severity) +{ + khui_alert * a = NULL; + khm_int32 rv; + + rv = khui_alert_create_simple(title, message, severity, &a); + + if(KHM_FAILED(rv)) + return rv; + + rv = khui_alert_show(a); + + khui_alert_release(a); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +khui_alert_hold(khui_alert * alert) +{ + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + alert->refcount++; + LeaveCriticalSection(&cs_alerts); + return KHM_ERROR_SUCCESS; +} + +/* called with cs_alert held */ +static void +free_alert(khui_alert * alert) +{ + assert(alert->magic == KHUI_ALERT_MAGIC); + + LDELETE(&kh_alerts, alert); + + if(alert->flags & KHUI_ALERT_FLAG_FREE_TITLE) { + assert(alert->title); + PFREE(alert->title); + alert->title = NULL; + alert->flags &= ~KHUI_ALERT_FLAG_FREE_TITLE; + } + if(alert->flags & KHUI_ALERT_FLAG_FREE_MESSAGE) { + assert(alert->message); + PFREE(alert->message); + alert->message = NULL; + alert->flags &= ~KHUI_ALERT_FLAG_FREE_MESSAGE; + } + if(alert->flags & KHUI_ALERT_FLAG_FREE_SUGGEST) { + assert(alert->suggestion); + PFREE(alert->suggestion); + alert->suggestion = NULL; + alert->flags &= ~KHUI_ALERT_FLAG_FREE_SUGGEST; + } + + khui_context_release(&alert->ctx); + + if(alert->flags & KHUI_ALERT_FLAG_FREE_STRUCT) { + alert->flags &= ~KHUI_ALERT_FLAG_FREE_STRUCT; + alert->magic = 0; + PFREE(alert); + } +} + +KHMEXP khm_int32 KHMAPI +khui_alert_release(khui_alert * alert) +{ + assert(alert->magic == KHUI_ALERT_MAGIC); + + EnterCriticalSection(&cs_alerts); + if((--(alert->refcount)) == 0) { + free_alert(alert); + } + LeaveCriticalSection(&cs_alerts); + return KHM_ERROR_SUCCESS; +} + +KHMEXP void KHMAPI khui_alert_lock(khui_alert * alert) +{ + EnterCriticalSection(&cs_alerts); +} + +KHMEXP void KHMAPI khui_alert_unlock(khui_alert * alert) +{ + LeaveCriticalSection(&cs_alerts); +} diff --git a/krb5-1-6/src/windows/identity/uilib/configui.c b/krb5-1-6/src/windows/identity/uilib/configui.c new file mode 100644 index 000000000..6f4f940a8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/configui.c @@ -0,0 +1,1088 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> +#include<kmm.h> +#include<configui.h> +#include<utils.h> +#include<assert.h> + +#include<strsafe.h> + +khm_int32 cfgui_node_serial; +LONG init_once = 0; +CRITICAL_SECTION cs_cfgui; +khui_config_node_i * cfgui_root_config; +HWND hwnd_cfgui = NULL; + +static khui_config_node_i * +cfgui_create_new_node(void) { + khui_config_node_i * node; + + node = PMALLOC(sizeof(*node)); +#ifdef DEBUG + assert(node); +#endif + ZeroMemory(node, sizeof(*node)); + node->magic = KHUI_CONFIG_NODE_MAGIC; + + EnterCriticalSection(&cs_cfgui); + node->id = ++cfgui_node_serial; + LeaveCriticalSection(&cs_cfgui); + + return node; +} + +/* called with cs_cfgui held */ +static void +cfgui_free_node(khui_config_node_i * node) { + if (!cfgui_is_valid_node(node)) + return; + + if (node->reg.name) + PFREE((void *) node->reg.name); + + if (node->reg.short_desc) + PFREE((void *) node->reg.short_desc); + + if (node->reg.long_desc) + PFREE((void *) node->reg.long_desc); + + node->magic = 0; + + if (node->owner) + kmm_release_plugin(node->owner); + + ZeroMemory(node, sizeof(*node)); + + PFREE(node); +} + + +static void +cfgui_hold_node(khui_config_node_i * node) { + EnterCriticalSection(&cs_cfgui); + node->refcount++; + LeaveCriticalSection(&cs_cfgui); +} + + +static void +cfgui_release_node(khui_config_node_i * node) { + EnterCriticalSection(&cs_cfgui); + node->refcount--; + if (node->refcount == 0 && + (node->flags & KHUI_CN_FLAG_DELETED)) { + khui_config_node_i * parent; + parent = TPARENT(node); +#ifdef DEBUG + assert(TFIRSTCHILD(node) == NULL); + assert(parent != NULL); +#endif + TDELCHILD(parent, node); + cfgui_free_node(node); + cfgui_release_node(parent); + } + LeaveCriticalSection(&cs_cfgui); +} + +static void +cfgui_init_once(void) { + if (init_once == 0 && + InterlockedIncrement(&init_once) == 1) { + InitializeCriticalSection(&cs_cfgui); + cfgui_root_config = cfgui_create_new_node(); + cfgui_node_serial = 0; + hwnd_cfgui = NULL; + } +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_register(khui_config_node vparent, + const khui_config_node_reg * reg) { + + size_t cb_name; + size_t cb_short_desc; + size_t cb_long_desc; + khui_config_node_i * node; + khui_config_node_i * parent; + khui_config_node t; + wchar_t * name; + wchar_t * short_desc; + wchar_t * long_desc; + + cfgui_init_once(); + + if (!reg || + FAILED(StringCbLength(reg->name, + KHUI_MAXCB_NAME, + &cb_name)) || + FAILED(StringCbLength(reg->short_desc, + KHUI_MAXCB_SHORT_DESC, + &cb_short_desc)) || + FAILED(StringCbLength(reg->long_desc, + KHUI_MAXCB_LONG_DESC, + &cb_long_desc)) || + (vparent && + !cfgui_is_valid_node_handle(vparent))) + return KHM_ERROR_INVALID_PARAM; + + if (KHM_SUCCEEDED(khui_cfg_open(vparent, + reg->name, + &t))) { + khui_cfg_release(t); + return KHM_ERROR_DUPLICATE; + } + + cb_name += sizeof(wchar_t); + cb_short_desc += sizeof(wchar_t); + cb_long_desc += sizeof(wchar_t); + + node = cfgui_create_new_node(); + + node->reg = *reg; + node->reg.flags &= KHUI_CNFLAGMASK_STATIC; + + name = PMALLOC(cb_name); + StringCbCopy(name, cb_name, reg->name); + short_desc = PMALLOC(cb_short_desc); + StringCbCopy(short_desc, cb_short_desc, reg->short_desc); + long_desc = PMALLOC(cb_long_desc); + StringCbCopy(long_desc, cb_long_desc, reg->long_desc); + + node->reg.name = name; + node->reg.short_desc = short_desc; + node->reg.long_desc = long_desc; + node->flags = node->reg.flags; + + if (vparent == NULL) { + parent = cfgui_root_config; + } else { + parent = cfgui_node_i_from_handle(vparent); + } + + /* plugin handles should not be obtained lightly. For the moment, + the cleanup of nodes doesn't happen until module unload and + module unload doesn't happen until all the plugin and module + handles have been freed. */ + /* node->owner = kmm_this_plugin(); */ + + EnterCriticalSection(&cs_cfgui); + TADDCHILD(parent, node); + + if (hwnd_cfgui) { + SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0); + } + + LeaveCriticalSection(&cs_cfgui); + + /* when the root config list changes, we need to notify the UI. + this way, the Options menu can be kept in sync. */ + if (parent == cfgui_root_config) { + kmq_post_message(KMSG_ACT, KMSG_ACT_SYNC_CFG, 0, 0); + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_open(khui_config_node vparent, + const wchar_t * name, + khui_config_node * result) { + khui_config_node_i * parent; + khui_config_node_i * c; + size_t sz; + + cfgui_init_once(); + + if ((vparent && + !cfgui_is_valid_node_handle(vparent)) || + FAILED(StringCbLength(name, KHUI_MAXCCH_NAME, &sz)) || + !result) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (vparent) + parent = cfgui_node_i_from_handle(vparent); + else + parent = cfgui_root_config; + + c = TFIRSTCHILD(parent); + while(c) { + if (!(c->flags & KHUI_CN_FLAG_DELETED) && + !wcscmp(c->reg.name, name)) + break; + c = LNEXT(c); + } + + if (c) { + *result = cfgui_handle_from_node_i(c); + cfgui_hold_node(c); + } else { + *result = NULL; + } + LeaveCriticalSection(&cs_cfgui); + + if (*result) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_remove(khui_config_node vnode) { + khui_config_node_i * node; + if (!cfgui_is_valid_node_handle(vnode)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + node = cfgui_node_i_from_handle(vnode); + node->flags |= KHUI_CN_FLAG_DELETED; + + if (hwnd_cfgui) { + SendMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM(0, WMCFG_SYNC_NODE_LIST), 0); + } + + LeaveCriticalSection(&cs_cfgui); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_hold(khui_config_node vnode) { + if (!cfgui_is_valid_node_handle(vnode)) + return KHM_ERROR_INVALID_PARAM; + + cfgui_hold_node(cfgui_node_i_from_handle(vnode)); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_release(khui_config_node vnode) { + if (!cfgui_is_valid_node_handle(vnode)) + return KHM_ERROR_INVALID_PARAM; + + cfgui_release_node(cfgui_node_i_from_handle(vnode)); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_parent(khui_config_node vnode, + khui_config_node * result) { + + khui_config_node_i * node; + khui_config_node_i * parent; + + if(!cfgui_is_valid_node_handle(vnode) || + !result) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) { + node = cfgui_node_i_from_handle(vnode); + parent = TPARENT(node); + if (parent == cfgui_root_config) + parent = NULL; + } else { + parent = NULL; + } + if (parent) { + cfgui_hold_node(parent); + } + LeaveCriticalSection(&cs_cfgui); + + *result = parent; + + if (parent) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_first_child(khui_config_node vparent, + khui_config_node * result) { + khui_config_node_i * parent; + khui_config_node_i * c; + + cfgui_init_once(); + + if((vparent && !cfgui_is_valid_node_handle(vparent)) || + !result) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vparent)) { + parent = cfgui_node_i_from_handle(vparent); + } else if (!vparent) { + parent = cfgui_root_config; + } else { + parent = NULL; + } + + if (parent) { + for(c = TFIRSTCHILD(parent); + c && + ((c->reg.flags & KHUI_CNFLAG_SUBPANEL) || + (c->flags & KHUI_CN_FLAG_DELETED)); + c = LNEXT(c)); + } else { + c = NULL; + } + + if (c) + cfgui_hold_node(c); + LeaveCriticalSection(&cs_cfgui); + + *result = c; + + if (c) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_first_subpanel(khui_config_node vparent, + khui_config_node * result) { + khui_config_node_i * parent; + khui_config_node_i * c; + + cfgui_init_once(); + + if((vparent && !cfgui_is_valid_node_handle(vparent)) || + !result) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vparent)) { + parent = cfgui_node_i_from_handle(vparent); + } else if (!vparent) { + parent = cfgui_root_config; + } else { + parent = NULL; + } + + if (parent) { + for(c = TFIRSTCHILD(parent); + c && + (!(c->reg.flags & KHUI_CNFLAG_SUBPANEL) || + (c->flags & KHUI_CN_FLAG_DELETED)); + c = LNEXT(c)); + } else { + c = NULL; + } + + if (c) + cfgui_hold_node(c); + LeaveCriticalSection(&cs_cfgui); + + *result = c; + + if (c) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_next(khui_config_node vnode, + khui_config_node * result) { + + khui_config_node_i * node; + khui_config_node_i * nxt_node; + + if (!cfgui_is_valid_node_handle(vnode) || + !result) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) { + node = cfgui_node_i_from_handle(vnode); + for(nxt_node = LNEXT(node); + nxt_node && + ((node->reg.flags ^ nxt_node->reg.flags) & + KHUI_CNFLAG_SUBPANEL); + nxt_node = LNEXT(nxt_node)); + if (nxt_node) + cfgui_hold_node(nxt_node); + } else { + nxt_node = NULL; + } + LeaveCriticalSection(&cs_cfgui); + + *result = cfgui_handle_from_node_i(nxt_node); + + if (nxt_node) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_next_release(khui_config_node * pvnode) { + + khui_config_node_i * node; + khui_config_node_i * nxt_node; + + if (!pvnode || + !cfgui_is_valid_node_handle(*pvnode)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(*pvnode)) { + node = cfgui_node_i_from_handle(*pvnode); + for(nxt_node = LNEXT(node); + nxt_node && + (((node->reg.flags ^ nxt_node->reg.flags) & + KHUI_CNFLAG_SUBPANEL) || + (nxt_node->flags & KHUI_CN_FLAG_DELETED)); + nxt_node = LNEXT(nxt_node)); + if (nxt_node) + cfgui_hold_node(nxt_node); + cfgui_release_node(node); + } else { + nxt_node = NULL; + } + LeaveCriticalSection(&cs_cfgui); + + *pvnode = cfgui_handle_from_node_i(nxt_node); + + if (nxt_node) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_reg(khui_config_node vnode, + khui_config_node_reg * reg) { + + khui_config_node_i * node; + + cfgui_init_once(); + + if ((vnode && !cfgui_is_valid_node_handle(vnode)) || + !reg) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) { + node = cfgui_node_i_from_handle(vnode); + *reg = node->reg; + } else if (!vnode) { + node = cfgui_root_config; + *reg = node->reg; + } else { + node = NULL; + ZeroMemory(reg, sizeof(*reg)); + } + LeaveCriticalSection(&cs_cfgui); + + if (node) + return KHM_ERROR_SUCCESS; + else + return KHM_ERROR_INVALID_PARAM; +} + +KHMEXP HWND KHMAPI +khui_cfg_get_hwnd(khui_config_node vnode) { + khui_config_node_i * node; + HWND hwnd; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return NULL; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) + hwnd = node->hwnd; + else + hwnd = NULL; + LeaveCriticalSection(&cs_cfgui); + + return hwnd; +} + +KHMEXP LPARAM KHMAPI +khui_cfg_get_param(khui_config_node vnode) { + khui_config_node_i * node; + LPARAM param; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return 0; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) + param = node->param; + else + param = 0; + LeaveCriticalSection(&cs_cfgui); + + return param; +} + +KHMEXP void KHMAPI +khui_cfg_set_hwnd(khui_config_node vnode, HWND hwnd) { + khui_config_node_i * node; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) + node->hwnd = hwnd; + LeaveCriticalSection(&cs_cfgui); +} + +KHMEXP void KHMAPI +khui_cfg_set_param(khui_config_node vnode, LPARAM param) { + khui_config_node_i * node; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) + node->param = param; + LeaveCriticalSection(&cs_cfgui); +} + +static void +clear_node_data(khui_config_node_i * node) { + node->n_data = 0; +} + +static cfg_node_data * +get_node_data(khui_config_node_i * node, + void * key, + khm_boolean create) { + khm_size i; + + for (i=0; i<node->n_data; i++) { + if (node->data[i].key == key) + return &(node->data[i]); + } + + if (!create) + return NULL; + + if (node->n_data + 1 > node->nc_data) { + cfg_node_data * newdata; + + node->nc_data = UBOUNDSS((node->n_data + 1), + KHUI_NODEDATA_ALLOC_INCR, + KHUI_NODEDATA_ALLOC_INCR); +#ifdef DEBUG + assert(node->nc_data >= node->n_data + 1); +#endif + newdata = PMALLOC(sizeof(*newdata) * node->nc_data); +#ifdef DEBUG + assert(newdata); +#endif + ZeroMemory(newdata, sizeof(*newdata) * node->nc_data); + + if (node->data && node->n_data > 0) { + memcpy(newdata, node->data, node->n_data * sizeof(*newdata)); + PFREE(node->data); + } + node->data = newdata; + } + + node->data[node->n_data].key = key; + node->data[node->n_data].hwnd = NULL; + node->data[node->n_data].param = 0; + node->data[node->n_data].flags = 0; + + node->n_data++; + + return &(node->data[node->n_data - 1]); +} + +KHMEXP HWND KHMAPI +khui_cfg_get_hwnd_inst(khui_config_node vnode, + khui_config_node noderef) { + khui_config_node_i * node; + cfg_node_data * data; + HWND hwnd; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return NULL; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) { + data = get_node_data(node, noderef, FALSE); + if (data) + hwnd = data->hwnd; + else + hwnd = NULL; + } else + hwnd = NULL; + LeaveCriticalSection(&cs_cfgui); + + return hwnd; +} + +KHMEXP LPARAM KHMAPI +khui_cfg_get_param_inst(khui_config_node vnode, + khui_config_node noderef) { + khui_config_node_i * node; + cfg_node_data * data; + LPARAM lParam; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return 0; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) { + data = get_node_data(node, noderef, FALSE); + if (data) + lParam = data->param; + else + lParam = 0; + } else + lParam = 0; + LeaveCriticalSection(&cs_cfgui); + + return lParam; +} + +KHMEXP void KHMAPI +khui_cfg_set_hwnd_inst(khui_config_node vnode, + khui_config_node noderef, + HWND hwnd) { + khui_config_node_i * node; + cfg_node_data * data; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) { + data = get_node_data(node, noderef, TRUE); + if (data) + data->hwnd = hwnd; + } + LeaveCriticalSection(&cs_cfgui); +} + +KHMEXP void KHMAPI +khui_cfg_set_param_inst(khui_config_node vnode, + khui_config_node noderef, + LPARAM param) { + khui_config_node_i * node; + cfg_node_data * data; + + cfgui_init_once(); + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) + node = cfgui_node_i_from_handle(vnode); + else if (!vnode) + node = cfgui_root_config; + else + node = NULL; + + if (node) { + data = get_node_data(node, noderef, TRUE); + if (data) + data->param = param; + } + LeaveCriticalSection(&cs_cfgui); +} + + +/* called with cs_cfgui held */ +static void +cfgui_clear_params(khui_config_node_i * node) { + khui_config_node_i * c; + + node->hwnd = NULL; + node->param = 0; + node->flags &= KHUI_CNFLAGMASK_STATIC; + clear_node_data(node); + + c = TFIRSTCHILD(node); + while(c) { + cfgui_clear_params(c); + c = LNEXT(c); + } +} + +KHMEXP void KHMAPI +khui_cfg_clear_params(void) { + + cfgui_init_once(); + + EnterCriticalSection(&cs_cfgui); + cfgui_clear_params(cfgui_root_config); + LeaveCriticalSection(&cs_cfgui); +} + +KHMEXP void KHMAPI +khui_cfg_set_configui_handle(HWND hwnd) { + EnterCriticalSection(&cs_cfgui); + hwnd_cfgui = hwnd; + LeaveCriticalSection(&cs_cfgui); +} + +KHMEXP void KHMAPI +khui_cfg_set_flags(khui_config_node vnode, + khm_int32 flags, + khm_int32 mask) { + khui_config_node_i * node; + khm_int32 newflags; + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return; + + mask &= KHUI_CNFLAGMASK_DYNAMIC; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) { + + node = cfgui_node_i_from_handle(vnode); + + newflags = + (flags & mask) | + (node->flags & ~mask); + + if (newflags != node->flags) { + node->flags = newflags; + + if (hwnd_cfgui) + PostMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM((WORD)newflags, WMCFG_UPDATE_STATE), + (LPARAM) vnode); + } + } + LeaveCriticalSection(&cs_cfgui); +} + +/* called with cs_cfgui held */ +static void +recalc_node_flags(khui_config_node vnode, khm_boolean plural) { + khui_config_node_i * node; + khui_config_node_i * parent; + khui_config_node_i * subpanel; + cfg_node_data * data; + khm_int32 flags; + +#ifdef DEBUG + assert(cfgui_is_valid_node_handle(vnode)); +#endif + + node = cfgui_node_i_from_handle(vnode); + + if (plural) + parent = TPARENT(node); + else + parent = node; +#ifdef DEBUG + assert(parent); +#endif + + flags = 0; + + for(subpanel = TFIRSTCHILD(parent); subpanel; + subpanel = LNEXT(subpanel)) { + if (!(subpanel->reg.flags & KHUI_CNFLAG_SUBPANEL) || + (plural && !(subpanel->reg.flags & KHUI_CNFLAG_PLURAL)) || + (!plural && (subpanel->reg.flags & KHUI_CNFLAG_PLURAL))) + continue; + + data = get_node_data(subpanel, + vnode, + FALSE); + + if (data) { + flags |= data->flags; + } + } + + flags &= KHUI_CNFLAGMASK_DYNAMIC; + + if ((node->flags & KHUI_CNFLAGMASK_DYNAMIC) == flags) + return; + + node->flags = (node->flags & ~KHUI_CNFLAGMASK_DYNAMIC) | flags; + + if (hwnd_cfgui) + PostMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY, + MAKEWPARAM((WORD) node->flags, WMCFG_UPDATE_STATE), + (LPARAM) vnode); +} + +KHMEXP void KHMAPI +khui_cfg_set_flags_inst(khui_config_init_data * d, + khm_int32 flags, + khm_int32 mask) { + khui_config_node_i * node; + cfg_node_data * data; + + cfgui_init_once(); + if (!cfgui_is_valid_node_handle(d->this_node)) + return; + + mask &= KHUI_CNFLAGMASK_DYNAMIC; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(d->this_node)) + node = cfgui_node_i_from_handle(d->this_node); + else + node = NULL; + + if (node) { + data = get_node_data(node, d->ctx_node, TRUE); + if (data) { + khm_int32 new_flags; + + new_flags = (flags & mask) | + (data->flags & ~mask); + + if (new_flags != data->flags) { + data->flags = new_flags; + + if (d->ctx_node != d->ref_node) + recalc_node_flags(d->ctx_node, TRUE); + else + recalc_node_flags(d->ctx_node, FALSE); + } + } + } + LeaveCriticalSection(&cs_cfgui); +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_flags(khui_config_node vnode) { + khui_config_node_i * node; + khm_int32 flags = 0; + + if (vnode && + !cfgui_is_valid_node_handle(vnode)) + return 0; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) { + + node = cfgui_node_i_from_handle(vnode); + + flags = node->flags; + } + LeaveCriticalSection(&cs_cfgui); + + return flags; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_name(khui_config_node vnode, + wchar_t * buf, + khm_size * cb_buf) { + khui_config_node_i * node; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if (!cb_buf || + !cfgui_is_valid_node_handle(vnode)) + return KHM_ERROR_INVALID_PARAM; + + EnterCriticalSection(&cs_cfgui); + if (cfgui_is_valid_node_handle(vnode)) { + khm_size cb; + + node = cfgui_node_i_from_handle(vnode); + + StringCbLength(node->reg.name, KHUI_MAXCCH_NAME, &cb); + + if (buf == NULL || cb > *cb_buf) { + *cb_buf = cb; + rv = KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(buf, *cb_buf, node->reg.name); + *cb_buf = cb; + } + } else { + rv = KHM_ERROR_INVALID_PARAM; + } + LeaveCriticalSection(&cs_cfgui); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_init_dialog_data(HWND hwnd_dlg, + const khui_config_init_data * data, + khm_size cb_extra, + khui_config_init_data ** new_data, + void ** extra) { + khm_size cb; + khui_config_init_data * d; + + cb = sizeof(khui_config_init_data) + cb_extra; + d = PMALLOC(cb); +#ifdef DEBUG + assert(d); +#endif + ZeroMemory(d, cb); + + *d = *data; + + if (d->ctx_node) + khui_cfg_hold(d->ctx_node); + if (d->this_node) + khui_cfg_hold(d->this_node); + if (d->ref_node) + khui_cfg_hold(d->ref_node); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd_dlg, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + if (new_data) + *new_data = d; + if (extra) + *extra = (void *) (d + 1); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_get_dialog_data(HWND hwnd_dlg, + khui_config_init_data ** data, + void ** extra) { + khui_config_init_data * d; + + d = (khui_config_init_data *) (LONG_PTR) GetWindowLongPtr(hwnd_dlg, + DWLP_USER); +#ifdef DEBUG + assert(d); +#endif + + *data = d; + if (extra) + *extra = (void *) (d + 1); + + return (d)?KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_int32 KHMAPI +khui_cfg_free_dialog_data(HWND hwnd_dlg) { + khui_config_init_data * d; + + d = (khui_config_init_data *) (LONG_PTR) GetWindowLongPtr(hwnd_dlg, + DWLP_USER); +#ifdef DEBUG + assert(d); +#endif + + if (d) { + PFREE(d); + SetWindowLongPtr(hwnd_dlg, DWLP_USER, 0); + } + + return (d)?KHM_ERROR_SUCCESS: KHM_ERROR_NOT_FOUND; +} diff --git a/krb5-1-6/src/windows/identity/uilib/configui.h b/krb5-1-6/src/windows/identity/uilib/configui.h new file mode 100644 index 000000000..bd3a13e8e --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/configui.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_CONFIGUI_H +#define __KHIMAIRA_CONFIGUI_H + +typedef struct tag_cfg_node_data { + void * key; + HWND hwnd; + LPARAM param; + khm_int32 flags; +} cfg_node_data; + +typedef struct tag_khui_config_node_i { + khm_int32 magic; + + khui_config_node_reg reg; + kmm_plugin owner; + khm_int32 id; + + HWND hwnd; + LPARAM param; + + cfg_node_data * data; + khm_size n_data; + khm_size nc_data; + + khm_int32 refcount; + khm_int32 flags; + TDCL(struct tag_khui_config_node_i); +} khui_config_node_i; + +#define KHUI_CONFIG_NODE_MAGIC 0x38f4cb52 + +#define KHUI_NODEDATA_ALLOC_INCR 8 + +#define KHUI_CN_FLAG_DELETED 0x0008 + +#define cfgui_is_valid_node_handle(v) \ +((v) && ((khui_config_node_i *) (v))->magic == KHUI_CONFIG_NODE_MAGIC) + +#define cfgui_is_valid_node(n) \ +((n)->magic == KHUI_CONFIG_NODE_MAGIC) + +#define cfgui_node_i_from_handle(v) \ +((khui_config_node_i *) v) + +#define cfgui_handle_from_node_i(n) \ +((khui_config_node) n) + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/creddlg.c b/krb5-1-6/src/windows/identity/uilib/creddlg.c new file mode 100644 index 000000000..e78ced68c --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/creddlg.c @@ -0,0 +1,719 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> +#include<utils.h> +#include<assert.h> +#include<strsafe.h> + +#define CW_ALLOC_INCR 8 + +static void cw_free_prompts(khui_new_creds * c); + +static void cw_free_prompt(khui_new_creds_prompt * p); + +static khui_new_creds_prompt * +cw_create_prompt( + khm_size idx, + khm_int32 type, + wchar_t * prompt, + wchar_t * def, + khm_int32 flags); + +KHMEXP khm_int32 KHMAPI +khui_cw_create_cred_blob(khui_new_creds ** ppnc) +{ + khui_new_creds * c; + + c = PMALLOC(sizeof(*c)); + ZeroMemory(c, sizeof(*c)); + + c->magic = KHUI_NC_MAGIC; + InitializeCriticalSection(&c->cs); + c->result = KHUI_NC_RESULT_CANCEL; + c->mode = KHUI_NC_MODE_MINI; + + khui_context_create(&c->ctx, KHUI_SCOPE_NONE, NULL, KCDB_CREDTYPE_INVALID, NULL); + + *ppnc = c; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_destroy_cred_blob(khui_new_creds *c) +{ + khm_size i; + size_t len; + EnterCriticalSection(&c->cs); + for(i=0;i<c->n_identities;i++) { + kcdb_identity_release(c->identities[i]); + } + cw_free_prompts(c); + khui_context_release(&c->ctx); + LeaveCriticalSection(&c->cs); + DeleteCriticalSection(&c->cs); + + if (c->password) { + len = wcslen(c->password); + SecureZeroMemory(c->password, sizeof(wchar_t) * len); + PFREE(c->password); + } + + if (c->identities) + PFREE(c->identities); + + if (c->types) + PFREE(c->types); + + if (c->type_subs) + PFREE(c->type_subs); + + if (c->window_title) + PFREE(c->window_title); + + PFREE(c); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_lock_nc(khui_new_creds * c) +{ + EnterCriticalSection(&c->cs); + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_unlock_nc(khui_new_creds * c) +{ + LeaveCriticalSection(&c->cs); + return KHM_ERROR_SUCCESS; +} + +#define NC_N_IDENTITIES 4 + +KHMEXP khm_int32 KHMAPI +khui_cw_add_identity(khui_new_creds * c, + khm_handle id) +{ + if(id == NULL) + return KHM_ERROR_SUCCESS; /* we return success because adding + a NULL id is equivalent to adding + nothing. */ + EnterCriticalSection(&(c->cs)); + + if(c->identities == NULL) { + c->nc_identities = NC_N_IDENTITIES; + c->identities = PMALLOC(sizeof(*(c->identities)) * + c->nc_identities); + c->n_identities = 0; + } else if(c->n_identities + 1 > c->nc_identities) { + khm_handle * ni; + + c->nc_identities = UBOUNDSS(c->n_identities + 1, + NC_N_IDENTITIES, + NC_N_IDENTITIES); + ni = PMALLOC(sizeof(*(c->identities)) * c->nc_identities); + memcpy(ni, c->identities, + sizeof(*(c->identities)) * c->n_identities); + PFREE(c->identities); + c->identities = ni; + } + + kcdb_identity_hold(id); + c->identities[c->n_identities++] = id; + LeaveCriticalSection(&(c->cs)); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_set_primary_id(khui_new_creds * c, + khm_handle id) +{ + khm_size i; + khm_int32 rv; + + EnterCriticalSection(&c->cs); + + /* no change */ + if((c->n_identities > 0 && c->identities[0] == id) || + (c->n_identities == 0 && id == NULL)) { + LeaveCriticalSection(&c->cs); + return KHM_ERROR_SUCCESS; + } + + for(i=0; i<c->n_identities; i++) { + kcdb_identity_release(c->identities[i]); + } + c->n_identities = 0; + + LeaveCriticalSection(&(c->cs)); + rv = khui_cw_add_identity(c,id); + if(c->hwnd != NULL) { + PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), 0); + } + return rv; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_add_type(khui_new_creds * c, + khui_new_creds_by_type * t) +{ + EnterCriticalSection(&c->cs); + + if(c->n_types >= KHUI_MAX_NCTYPES) { + LeaveCriticalSection(&c->cs); + return KHM_ERROR_OUT_OF_BOUNDS; + } + + if(c->types == NULL) { + c->nc_types = CW_ALLOC_INCR; + c->types = PMALLOC(sizeof(*(c->types)) * c->nc_types); + c->type_subs = PMALLOC(sizeof(*(c->type_subs)) * c->nc_types); + c->n_types = 0; + } + + if(c->nc_types < c->n_types + 1) { + void * t; + khm_size n; + + n = UBOUNDSS(c->n_types + 1, CW_ALLOC_INCR, CW_ALLOC_INCR); + + t = PMALLOC(sizeof(*(c->types)) * n); + memcpy(t, (void *) c->types, sizeof(*(c->types)) * c->n_types); + PFREE(c->types); + c->types = t; + + t = PMALLOC(sizeof(*(c->type_subs)) * n); + memcpy(t, (void *) c->type_subs, sizeof(*(c->type_subs)) * c->n_types); + PFREE(c->type_subs); + c->type_subs = t; + + c->nc_types = n; + } + + c->type_subs[c->n_types] = kcdb_credtype_get_sub(t->type); + c->types[c->n_types++] = t; + t->nc = c; + LeaveCriticalSection(&c->cs); + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_del_type(khui_new_creds * c, + khm_int32 type_id) +{ + khm_size i; + + EnterCriticalSection(&c->cs); + for(i=0; i < c->n_types; i++) { + if(c->types[i]->type == type_id) + break; + } + if(i >= c->n_types) { + LeaveCriticalSection(&c->cs); + return KHM_ERROR_NOT_FOUND; + } + c->n_types--; + for(;i < c->n_types; i++) { + c->types[i] = c->types[i+1]; + c->type_subs[i] = c->type_subs[i+1]; + } + LeaveCriticalSection(&c->cs); + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_find_type(khui_new_creds * c, + khm_int32 type, + khui_new_creds_by_type **t) +{ + khm_size i; + + EnterCriticalSection(&c->cs); + *t = NULL; + for(i=0;i<c->n_types;i++) { + if(c->types[i]->type == type) { + *t = c->types[i]; + break; + } + } + LeaveCriticalSection(&c->cs); + + if(*t) + return KHM_ERROR_SUCCESS; + return KHM_ERROR_NOT_FOUND; +} + + +KHMEXP khm_int32 KHMAPI +khui_cw_enable_type(khui_new_creds * c, + khm_int32 type, + khm_boolean enable) +{ + khui_new_creds_by_type * t = NULL; + BOOL delta = FALSE; + + EnterCriticalSection(&c->cs); + if(KHM_SUCCEEDED(khui_cw_find_type(c, type, &t))) { + if(enable) { + delta = t->flags & KHUI_NCT_FLAG_DISABLED; + t->flags &= ~KHUI_NCT_FLAG_DISABLED; + } + else { + delta = !(t->flags & KHUI_NCT_FLAG_DISABLED); + t->flags |= KHUI_NCT_FLAG_DISABLED; + } + } + LeaveCriticalSection(&c->cs); + + if(delta) + PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0,WMNC_TYPE_STATE), (LPARAM) type); + + return (t)?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND; +} + +KHMEXP khm_boolean KHMAPI +khui_cw_type_succeeded(khui_new_creds * c, + khm_int32 type) +{ + khui_new_creds_by_type * t; + khm_boolean s; + + EnterCriticalSection(&c->cs); + if(KHM_SUCCEEDED(khui_cw_find_type(c, type, &t))) { + s = (t->flags & KHUI_NCT_FLAG_PROCESSED) && !(t->flags & KHUI_NC_RESPONSE_FAILED); + } else { + s = FALSE; + } + LeaveCriticalSection(&c->cs); + + return s; +} + +static khui_new_creds_prompt * +cw_create_prompt(khm_size idx, + khm_int32 type, + wchar_t * prompt, + wchar_t * def, + khm_int32 flags) +{ + khui_new_creds_prompt * p; + size_t cb_prompt = 0; + size_t cb_def = 0; + + if(prompt && FAILED(StringCbLength(prompt, KHUI_MAXCB_PROMPT, &cb_prompt))) + return NULL; + if(def && FAILED(StringCbLength(def, KHUI_MAXCB_PROMPT_VALUE, &cb_def))) + return NULL; + + p = PMALLOC(sizeof(*p)); + ZeroMemory(p, sizeof(*p)); + + if(prompt) { + cb_prompt += sizeof(wchar_t); + p->prompt = PMALLOC(cb_prompt); + StringCbCopy(p->prompt, cb_prompt, prompt); + } + + if(def && cb_def > 0) { + cb_def += sizeof(wchar_t); + p->def = PMALLOC(cb_def); + StringCbCopy(p->def, cb_def, def); + } + + p->value = PMALLOC(KHUI_MAXCB_PROMPT_VALUE); + ZeroMemory(p->value, KHUI_MAXCB_PROMPT_VALUE); + + p->type = type; + p->flags = flags; + p->index = idx; + + return p; +} + +static void +cw_free_prompt(khui_new_creds_prompt * p) { + size_t cb; + + if(p->prompt) { + if(SUCCEEDED(StringCbLength(p->prompt, KHUI_MAXCB_PROMPT, &cb))) + SecureZeroMemory(p->prompt, cb); + PFREE(p->prompt); + } + + if(p->def) { + if(SUCCEEDED(StringCbLength(p->def, KHUI_MAXCB_PROMPT, &cb))) + SecureZeroMemory(p->def, cb); + PFREE(p->def); + } + + if(p->value) { + if(SUCCEEDED(StringCbLength(p->value, KHUI_MAXCB_PROMPT_VALUE, &cb))) + SecureZeroMemory(p->value, cb); + PFREE(p->value); + } + + PFREE(p); +} + +static void +cw_free_prompts(khui_new_creds * c) +{ + khm_size i; + + if(c->banner != NULL) { + PFREE(c->banner); + c->banner = NULL; + } + + if(c->pname != NULL) { + PFREE(c->pname); + c->pname = NULL; + } + + for(i=0;i < c->n_prompts; i++) { + if(c->prompts[i]) { + cw_free_prompt(c->prompts[i]); + c->prompts[i] = NULL; + } + } + + if(c->prompts != NULL) { + PFREE(c->prompts); + c->prompts = NULL; + } + + c->nc_prompts = 0; + c->n_prompts = 0; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_clear_prompts(khui_new_creds * c) +{ + /* the WMNC_CLEAR_PROMPT message needs to be sent before freeing + the prompts, because the prompts structure still holds the + window handles for the custom prompt controls. */ + SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_CLEAR_PROMPTS), (LPARAM) c); + + EnterCriticalSection(&c->cs); + cw_free_prompts(c); + LeaveCriticalSection(&c->cs); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_begin_custom_prompts(khui_new_creds * c, + khm_size n_prompts, + wchar_t * banner, + wchar_t * pname) +{ + size_t cb; + + PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_CLEAR_PROMPTS), (LPARAM) c); + + EnterCriticalSection(&c->cs); +#ifdef DEBUG + assert(c->n_prompts == 0); +#endif + cw_free_prompts(c); + + if(SUCCEEDED(StringCbLength(banner, KHUI_MAXCB_BANNER, &cb)) && + cb > 0) { + cb += sizeof(wchar_t); + c->banner = PMALLOC(cb); + StringCbCopy(c->banner, cb, banner); + } else { + c->banner = NULL; + } + + if(SUCCEEDED(StringCbLength(pname, KHUI_MAXCB_PNAME, &cb)) && + cb > 0) { + + cb += sizeof(wchar_t); + c->pname = PMALLOC(cb); + StringCbCopy(c->pname, cb, pname); + + } else { + + c->pname = NULL; + + } + + if(n_prompts > 0) { + c->prompts = PMALLOC(sizeof(*(c->prompts)) * n_prompts); + ZeroMemory(c->prompts, sizeof(*(c->prompts)) * n_prompts); + c->nc_prompts = n_prompts; + c->n_prompts = 0; + + } else { + + c->prompts = NULL; + c->n_prompts = 0; + c->nc_prompts = 0; + + PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_SET_PROMPTS), (LPARAM) c); + } + + LeaveCriticalSection(&c->cs); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_add_prompt(khui_new_creds * c, + khm_int32 type, + wchar_t * prompt, + wchar_t * def, + khm_int32 flags) +{ + khui_new_creds_prompt * p; + + if(c->nc_prompts == 0 || + c->n_prompts == c->nc_prompts) + return KHM_ERROR_INVALID_OPERATION; + +#ifdef DEBUG + assert(c->prompts != NULL); +#endif + + EnterCriticalSection(&c->cs); + p = cw_create_prompt(c->n_prompts, type, prompt, def, flags); + if(p == NULL) { + LeaveCriticalSection(&c->cs); + return KHM_ERROR_INVALID_PARAM; + } + c->prompts[c->n_prompts++] = p; + LeaveCriticalSection(&c->cs); + + if(c->n_prompts == c->nc_prompts) { + PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_SET_PROMPTS), (LPARAM) c); + /* once we are done adding prompts, switch to the auth + panel */ +#if 0 + /* Actually, don't. Doing so can mean an unexpected panel + switch if fiddling on some other panel causes a change in + custom prompts. */ + SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_SWITCH_PANEL), + (LPARAM) c); +#endif + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_get_prompt_count(khui_new_creds * c, + khm_size * np) { + + EnterCriticalSection(&c->cs); + *np = c->n_prompts; + LeaveCriticalSection(&c->cs); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_get_prompt(khui_new_creds * c, + khm_size idx, + khui_new_creds_prompt ** prompt) +{ + khm_int32 rv; + + EnterCriticalSection(&c->cs); + if(c->n_prompts <= idx || + c->prompts == NULL) { + + rv = KHM_ERROR_OUT_OF_BOUNDS; + *prompt = NULL; + } else { + + *prompt = c->prompts[idx]; + rv = KHM_ERROR_SUCCESS; + } + LeaveCriticalSection(&c->cs); + + return rv; +} + +void +khuiint_trim_str(wchar_t * s, khm_size cch) { + wchar_t * c, * last_ws; + + for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++); + + if (((khm_size)(c - s)) >= cch) + return; + + if (c != s && ((khm_size)(c - s)) < cch) { +#if _MSC_VER >= 1400 && __STDC_WANT_SECURE_LIB__ + wmemmove_s(s, cch, c, cch - ((khm_size)(c - s))); +#else + memmove(s, c, (cch - ((khm_size)(c - s)))* sizeof(wchar_t)); +#endif + } + + last_ws = NULL; + for (c = s; *c && ((khm_size)(c - s)) < cch; c++) { + if (!iswspace(*c)) + last_ws = NULL; + else if (last_ws == NULL) + last_ws = c; + } + + if (last_ws) + *last_ws = L'\0'; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_sync_prompt_values(khui_new_creds * c) +{ + khm_size i; + khm_size n; + HWND hw; + wchar_t tmpbuf[KHUI_MAXCCH_PROMPT_VALUE]; + + EnterCriticalSection(&c->cs); + redo_loop: + n = c->n_prompts; + for(i=0; i<n; i++) { + khui_new_creds_prompt * p; + + p = c->prompts[i]; + if(p->hwnd_edit) { + hw = p->hwnd_edit; + LeaveCriticalSection(&c->cs); + + GetWindowText(hw, tmpbuf, ARRAYLENGTH(tmpbuf)); + khuiint_trim_str(tmpbuf, ARRAYLENGTH(tmpbuf)); + + EnterCriticalSection(&c->cs); + if (n != c->n_prompts) + goto redo_loop; + SecureZeroMemory(p->value, KHUI_MAXCB_PROMPT_VALUE); + StringCchCopy(p->value, KHUI_MAXCCH_PROMPT_VALUE, + tmpbuf); + } + } + LeaveCriticalSection(&c->cs); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_get_prompt_value(khui_new_creds * c, + khm_size idx, + wchar_t * buf, + khm_size *cbbuf) +{ + khui_new_creds_prompt * p; + khm_int32 rv; + size_t cb; + + rv = khui_cw_get_prompt(c, idx, &p); + if(KHM_FAILED(rv)) + return rv; + + EnterCriticalSection(&c->cs); + + if(FAILED(StringCbLength(p->value, KHUI_MAXCB_PROMPT_VALUE, &cb))) { + *cbbuf = 0; + if(buf != NULL) + *buf = 0; + LeaveCriticalSection(&c->cs); + return KHM_ERROR_SUCCESS; + } + cb += sizeof(wchar_t); + + if(buf == NULL || *cbbuf < cb) { + *cbbuf = cb; + LeaveCriticalSection(&c->cs); + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buf, *cbbuf, p->value); + *cbbuf = cb; + LeaveCriticalSection(&c->cs); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_cw_set_response(khui_new_creds * c, + khm_int32 type, + khm_int32 response) +{ + khui_new_creds_by_type * t = NULL; + EnterCriticalSection(&c->cs); + khui_cw_find_type(c, type, &t); + c->response |= response & KHUI_NCMASK_RESPONSE; + if(t) { + t->flags &= ~KHUI_NCMASK_RESULT; + t->flags |= (response & KHUI_NCMASK_RESULT); + + if (!(response & KHUI_NC_RESPONSE_NOEXIT) && + !(response & KHUI_NC_RESPONSE_PENDING)) + t->flags |= KHUI_NC_RESPONSE_COMPLETED; + } + LeaveCriticalSection(&c->cs); + return KHM_ERROR_SUCCESS; +} + +/* only called from a identity provider callback */ +KHMEXP khm_int32 KHMAPI +khui_cw_add_control_row(khui_new_creds * c, + HWND label, + HWND input, + khui_control_size size) +{ + if (c && c->hwnd) { + khui_control_row row; + + row.label = label; + row.input = input; + row.size = size; + + SendMessage(c->hwnd, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_ADD_CONTROL_ROW), + (LPARAM) &row); + + return KHM_ERROR_SUCCESS; + } else { + return KHM_ERROR_INVALID_PARAM; + } +} diff --git a/krb5-1-6/src/windows/identity/uilib/intaction.h b/krb5-1-6/src/windows/identity/uilib/intaction.h new file mode 100644 index 000000000..5753a56de --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/intaction.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __NETIDMGR_ACTION_H_INTERNAL +#define __NETIDMGR_ACTION_H_INTERNAL + +/* Internal declarations for exports and data structured used in + nidmgr32.dll and netidmgr.exe */ + +extern HWND khui_hwnd_main; + +typedef struct tag_khui_ui_callback_data { + khm_int32 magic; + khm_ui_callback cb; + void * rock; + khm_int32 rv; +} khui_ui_callback_data; + +#define KHUI_UICBDATA_MAGIC 0x8a08572a + +/*! \addtogroup khui_actions +@{ */ + +/*! \brief An action */ +typedef struct tag_khui_action { + khm_int32 cmd; /*!< action identifier */ + khm_int32 type; /*!< combination of KHUI_ACTIONTYPE_* */ + wchar_t * name; /*!< name for named actions. NULL if + not named. */ + + /* The following fields are only for use by NetIDMgr */ + khm_int16 ib_normal; /*!< (internal) normal bitmap (index) (toolbar sized icon) */ + khm_int16 ib_hot; /*!< (internal) hot bitmap (index) (toolbar sized icon) */ + khm_int16 ib_disabled; /*!< (internal) disabled bitmap (index) (toolbar sized icon) */ + + khm_int16 ib_icon; /*!< (internal) index of small (16x16) icon (for menu) (small icon) */ + khm_int16 ib_icon_dis; /*!< (internal) index of disabled (greyed) icon (small icon) */ + + khm_int16 is_caption; /*!< (internal) index of string resource for caption */ + khm_int16 is_tooltip; /*!< (internal) same for description / tooltip */ + khm_int16 ih_topic; /*!< (internal) help topic */ + + /* The following fields are specified for custom actions */ + wchar_t * caption; /*!< Caption (localized) (limited by + KHUI_MAXCCH_SHORT_DESC). The + caption is used for representing the + action in menus and toolbars. */ + wchar_t * tooltip; /*!< Tooltip (localized) (limited by + KHUI_MAXCCH_SHORT_DESC). If this is + specified, whenever the user hovers + over the menu item or toolbar button + representing the action, the tooltip + will be displayed either on a + tooltip window or in the status + bar. */ + khm_handle listener; /*!< Listener of this action. Should be + a handle to a message + subscription. When the action is + invoked, a message of type + ::KMSG_ACT and subtype + ::KMSG_ACT_ACTIVATE will be posted + to this subscriber. The \a uparam + parameter of the message will have + the identifier of the action. */ + void * data; /*!< User data for custom action. This + field is not used by the UI library. + It is reserved for plugins to store + data that is specific for this + action. The data that's passed in + in the \a userdata parameter to + khui_action_create() will be stored + here and can be retrieved by calling + khui_action_get_data(). */ + void * reserved1; /*!< Reserved. */ + void * reserved2; /*!< Reserved. */ + void * reserved3; /*!< Reserved. */ + + /* For all actions */ + int state; /*!< current state. combination of + KHUI_ACTIONSTATE_* */ +} khui_action; + + +#define KHUI_ACTIONTYPE_IDENTITY 0x00010000 + + +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/intalert.h b/krb5-1-6/src/windows/identity/uilib/intalert.h new file mode 100644 index 000000000..dc4fbc6ef --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/intalert.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHALERTS_H_INTERNAL +#define __KHIMAIRA_KHALERTS_H_INTERNAL + +#include<khalerts.h> +#include<khaction.h> + +/*! \addtogroup khui_alert + +@{ */ + +/*! \internal + + \brief An alert + + Describes an alert message that will be shown to the user in a + variety of ways depending on the state of the NetIDMgr + application. + */ +typedef struct tag_khui_alert { + khm_int32 magic; + /*!< Magic number. Always set to + KHUI_ALERT_MAGIC */ + + khm_int32 severity; + /*!< The severity of the alert. One + of KHERR_ERROR, KHERR_WARNING or + KHERR_INFO. The default is + KHERR_INFO. Do not set directly. + Use khui_alert_set_severity(). */ + + khm_int32 alert_commands[KHUI_MAX_ALERT_COMMANDS]; + /*!< The command buttons associated + with the alert. Use + khui_alert_add_command() to add a + command. The buttons will appear in + the order in which they were added. + The first button will be the + default. Each command should be a + known action identifier. */ + khm_int32 n_alert_commands; + /*!< The number of commands in + alert_commands[]. */ + + wchar_t * title; /*!< The title of the alert. Subject + to ::KHUI_MAXCCH_TITLE. Use + khui_alert_set_title() to set. Do + not modify directly. */ + + wchar_t * message; + /*!< The main message of the alert. + Subject to ::KHUI_MAXCCH_MESSAGE. + Use khui_alert_set_message() to set. + Do not modify direcly. */ + + wchar_t * suggestion; + /*!< A suggestion. Appears below the + message text. Use + khui_alert_set_suggestion() to set. + Do not modify directly. */ + + khm_int32 flags; /*!< combination of + ::khui_alert_flags. Do not modify + directly. */ + + kherr_context * err_context; + /*!< If non-NULL at the time the alert + window is shown, this indicates that + the alert window should provide an + error viewer for the given error + context. */ + + kherr_event * err_event; + /*!< If non-NULL at the time the alert + window is shown, this indicates that + the alert window should provide an + error viewer for the given error + event. If an \a err_context is also + given, the error viewer for the + context will be below this error. */ + + khui_alert_type alert_type; + /*!< The type of alert. */ + + khui_action_context ctx; /*!< Context to which this alert + applies to. */ + + khm_int32 response; + /*!< Once the alert is displayed to + the user, when the user clicks one + of the command buttons, the command + ID will be assigned here. */ + + int refcount; + /*!< internal */ + + khm_boolean displayed; + /*!< TRUE when then the alert is being + displayed on screen. Also used + internally to determine when to + terminate the modal loop */ + + LDCL(struct tag_khui_alert); + /*!< internal */ +} khui_alert; + +#define KHUI_ALERT_MAGIC 0x48c39ce9 + +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khaction.h b/krb5-1-6/src/windows/identity/uilib/khaction.h new file mode 100644 index 000000000..cd6ad8e5e --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khaction.h @@ -0,0 +1,1005 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_ACTION_H +#define __KHIMAIRA_ACTION_H + +/*! \addtogroup khui + @{*/ +/*! \defgroup khui_actions Actions + @{*/ + +struct tag_khui_action; +typedef struct tag_khui_action khui_action; + +/*! \brief Unknown action type + + Unknown action type. + */ +#define KHUI_ACTIONTYPE_NONE 0 + +/*! \brief A trigger type action + + A trigger action usually triggers some event, which is what pretty + much every action does. +*/ +#define KHUI_ACTIONTYPE_TRIGGER 1 + +/*! \brief A toggle type action + + A toggle type action typically changes the CHECKED state of the + action each time it is invoked. + */ +#define KHUI_ACTIONTYPE_TOGGLE 2 + +/*! \brief The action is enabled + + This is the default if no other state is specified. Just means + not-disabled. +*/ +#define KHUI_ACTIONSTATE_ENABLED 0 + +/*! \brief The action is diabled */ +#define KHUI_ACTIONSTATE_DISABLED 1 + +/*! \brief For toggle type actions, the action is checked */ +#define KHUI_ACTIONSTATE_CHECKED 2 + +/*! \brief The action is hot + + Typically this means that the user is hovering the pointing device + over a UI element representing the action. + */ +#define KHUI_ACTIONSTATE_HOT 4 + +/*! \brief The action has been marked for deletion + + For custom actions, this means that the custom action was deleted. + The contents of the custom action fields are no longer valid. + */ +#define KHUI_ACTIONSTATE_DELETED 8 + +#ifdef NOEXPORT +#define ACTION_SIMPLE(c,cap,des,top) \ + {c,KHUI_ACTIONTYPE_TRIGGER,NULL,0,0,0,0,0,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0} + +#define ACTION_FULL(cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,state) \ + {cmd,type,name,inormal,ihot,idis,isml,ismld,capt,toolt,topic,NULL,NULL,NULL,NULL,NULL,NULL,NULL,state} + +#define ACTION_SIMPLE_IMAGE(c,inormal, ihot, idis, isml, ismld,cap, des, top) \ + {c,KHUI_ACTIONTYPE_TRIGGER,NULL,inormal,ihot,idis,isml,ismld,cap,des,top,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0} +#endif + +/*! \brief A reference to an action + + If the \a flags member has the KHUI_ACTIONREF_PACTION bit set, + then the action is referenced by the \a p_action member of the + union. Otherwise the identifier for the action is specified by \a + action member. +*/ +typedef struct tag_khui_action_ref { + int flags; /*!< A combination of KHUI_ACTIONREF_* */ + union { + khm_int32 action; /*!< The action identifier for the + action that is being referrred to. + Only valid if + ::KHUI_ACTIONREF_PACTION is not set + in \a flags. */ + khui_action * p_action; /*!< A pointer to the ::khui_action + structure that describes the action + that is being referred to. Only + valid if ::KHUI_ACTIONREF_PACTION is + set. */ + }; +} khui_action_ref; + +/*! \brief A submenu + + There should exist a menu associated with the action that is being + referred. When displaying this action in a menu, the contents of + the associated menu will appear as a submenu. + */ +#define KHUI_ACTIONREF_SUBMENU 0x01 + +/*! \brief Separator + + This is not an actual action, but represents a separator between + actions. When displaying this action in a menu or a toolbar, a + separating line will be drawn in place of this action. The \a + action and \a p_action members of the structures are unused if + this flag is set. + */ +#define KHUI_ACTIONREF_SEP 0x02 + +/*! \brief Action by reference + + The \a p_action member of the structure points to the + ::khui_action structure that describes the action. + */ +#define KHUI_ACTIONREF_PACTION 0x04 + +#ifdef NOEXPORT +/*! \brief Action should be freed + + \note This flag is reserved for internal use in the NetIDMgr + application. Do not use. + */ +#define KHUI_ACTIONREF_FREE_PACTION 0x08 + +/*! \brief Marks the end of an action sequence + + \note THis flag is reserved for internal use in the NetIDMgr + application. Do not use. + */ +#define KHUI_ACTIONREF_END 0x10 +#endif + +/*! \brief The default action + + When this bit is set in an action reference that describes a menu, + the menu item will be the default item and will be rendered + differently from other menu items. Only useful when defining + context menus. In general, it is good practice to place the + default item at the top of a menu, although the UI library does + not enforce this. This is purely meant as a rendering hint. + + Only one action is allowed to have this flag set. When an action + is added to a menu using khui_menu_insert_action() or + khui_menu_insert_paction() and this flag is set, all other menu + items will be stripped of this flag. + */ +#define KHUI_ACTIONREF_DEFAULT 0x20 + +#ifdef NOEXPORT +#define MENU_ACTION(c) {0,c} +#define MENU_DEFACTION(c) {KHUI_ACTIONREF_DEFAULT, c} +#define MENU_SUBMENU(s) {KHUI_ACTIONREF_SUBMENU,s} +#define MENU_SEP() {KHUI_ACTIONREF_SEP,KHUI_MENU_SEP} +#define MENU_END() {KHUI_ACTIONREF_END,KHUI_MENU_END} +#endif + +/*! \brief Menu definition + + Use the khui_menu_create(), khui_menu_insert_action(), + khui_menu_insert_paction(), khui_menu_get_size(), + khui_menu_get_action() functions to create and manipulate custom + menus. Do not manipulate this structure directly as doing so may + cause inconsistencies in the UI library. +*/ +typedef struct tag_khui_menu_def { + khm_int32 cmd; /*!< Action associated with menu */ + khm_int32 state; /*!< combination of KHUI_MENUSTATE_* */ + khm_size n_items; /*!< The number of actions in the \a items + list. If this is a custom menu, the + ::KHUI_MENUSTATE_ALLOCD bit will be set, + and the contents of this field will be + valid. Otherwise, the contents of this + field is ignored and the list of actions + must be terminated with a + ACTION_LIST_END action. */ + khm_size nc_items; /*!< max number of items in the buffer + alocated for items. Ignored if + ::KHUI_MENUSTATE_ALLOCD is not set in \a + state. */ + khui_action_ref *items; /*!< Action list terminated by, + ACTION_LIST_END. If \a n_items is set + to a value other than -1, the list + doesn't necessarily have to end with a + ACTION_LIST_END. When constructing a + menu using khui_menu_* functions, they + will set the size of this list in the \a + n_items member, and there will be no + ACTION_LIST_END action to terminate the + list. */ +} khui_menu_def; + +#ifdef NOEXPORT +#define CONSTMENU(c,s,i) {c,s,(khm_size)-1,(khm_size)-1,i} +#endif + +/*! \brief Unspecified menu + + Used when there is no single command associated with the entire + menu, such as for ad-hoc context menus. + */ +#define KHUI_MENU_NONE -3 + +/*! \brief Menu end indicator + + For static or constant menus this indicates that this action marks + the end of the list of actions which defined the menu. This is + invalid if used in a dynamic menu (a menu with the + ::KHUI_MENUSTATE_ALLOCD bit set). + */ +#define KHUI_MENU_END -2 + +/*! \brief Menu separator + + A separator for actions. When displaying a menu or showing a + toolbar based on a menu definition, a separator is rendered as a + bar separating the user interface elements for the actions on + either side of this. +*/ +#define KHUI_MENU_SEP -1 + +/*! \brief Constant menu + + The contents of the menu cannot be modified (individual actions in + the menu may be modified, but the order and the contents of the + menu itself cannot be modified. + + This is the default if ::KHUI_MENUSTATE_ALLOCD is not specified. + */ +#define KHUI_MENUSTATE_CONSTANT 0 + +/*! \brief Variable menu + + The menu is dnamically allocated. The list of actions contained + in the menu can be modified. +*/ +#define KHUI_MENUSTATE_ALLOCD 1 + +#ifdef NOEXPORT +/* predefined system menu */ +#define KHUI_MENUSTATE_SYSTEM 2 +#endif + +#ifdef NOEXPORT + +/*! \brief Accelerator definition */ +typedef struct tag_khui_accel_def { + int cmd; + int mod; + int key; + int scope; +} khui_accel_def; + +#define KHUI_ACCEL_SCOPE_GLOBAL 0 + +extern khui_accel_def khui_accel_global[]; +extern int khui_n_accel_global; + +extern khui_action khui_actions[]; +extern int khui_n_actions; + +extern khui_menu_def khui_all_menus[]; +extern int khui_n_all_menus; + +#endif /* NOEXPORT */ + +/* functions */ + +/*! \brief Refresh the global action table + + Changes to system menus and toolbars may not be immediately + reflected in the user interface. Calling this function forces the + UI to reparse the action tables and menus and refresh the + application menu bar and toolbars. + + */ +KHMEXP void KHMAPI +khui_refresh_actions(void); + +/*! \brief Lock the action and menu tables + + This function, along with khui_action_unlock() is used to prevent + changes from being made to shared menus and actions while they are + being updated. In particular, changes to shared menus usually + need to be done in a batch and may suffer corruption of other + threads access or modify the menu while one thread is updating it. + Operations on shared menus should always be done with the actions + locked. +*/ +KHMEXP void KHMAPI +khui_action_lock(void); + +/*! \brief Unlock the action and menu tables + + Unlocks the action and menu tables after a call to + khui_action_lock(). + + \see khui_action_lock() + */ +KHMEXP void KHMAPI +khui_action_unlock(void); + +/*! \brief Create a new menu + + Creates a new menu. The returned data structure must be freed by + a call to khui_menu_delete(). Custom menus that are created this + way are not reference counted or maintained by the UI library. + The caller is responsible for calling khui_menu_delete() when the + data is no longer needed. + + Specifiying an action in the \a action parameter will associate + the menu with the specified action. In this case, if the action + is added to another menu with the ::KHUI_ACTIONREF_SUBMENU flag, + this menu will appear as a submenu within that menu. Only one + menu can be associated with any given action. Custom menus can + not be associated with standard actions. + */ +KHMEXP khui_menu_def * KHMAPI +khui_menu_create(khm_int32 action); + +/*! \brief Duplicate a menu + + Creates a copy of the specified menu. The returned data structure + must be freed by a call to khui_menu_delete(). Custom menus are + not reference counted or maintained by the UI library. The caller + is responsible for calling khui_menu_delete() when the data is no + longer needed. + + Note that even if the original menu was associated with an action, + the duplicate will not be. Modifying the duplicate will not + modify the original menu. Only one menu can be associated with an + action. + */ +KHMEXP khui_menu_def * KHMAPI +khui_menu_dup(khui_menu_def * src); + +/*! \brief Delete a menu + + Deletes a menu created by a call to khui_menu_create() or + khui_menu_dup(). This frees up the memory and associated + resources used by the menu definition. The pointer that is passed + in will no longer be valid. + */ +KHMEXP void KHMAPI +khui_menu_delete(khui_menu_def * d); + +/*! \brief Insert an action into a menu + + The action specified by \a cmd will be inserted in to the menu \a + d at index \a idx. + + \param[in] d The menu to insert the action into + + \param[in] idx The index at which to insert the action. The index + is zero based. If \a idx is (-1) or larger than the largest + index in the menu, the item is appended to the menu. + + \param[in] cmd The command representing the action to insert into + the menu. This should be either a standard action, a user + action created with khui_action_create(), or certain pseudo + actions. Not all pseudo actions can be placed on a menu. + + \param[in] flags Flags for the action. This is a combination of + KHUI_ACTIONREF_* constants. Currently, the only constants + that are valid for this function are: ::KHUI_ACTIONREF_SEP, + ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT. + ::KHUI_ACTIONREF_SEP will be automatically added if the + command is ::KHUI_MENU_SEP. If ::KHUI_ACTIONREF_DEFAULT is + specified, then all other items in the menu will be stripped + of that flag leaving this action as the only one with that + flag set. + */ +KHMEXP void KHMAPI +khui_menu_insert_action(khui_menu_def * d, khm_size idx, khm_int32 cmd, khm_int32 flags); + +#define khui_menu_add_action(d,c) khui_menu_insert_action((d),-1,(c),0) +#pragma deprecated(khui_menu_add_action) + +#ifdef NOEXPORT + +/*! \brief Insert an action by reference into a menu + + The action specified by \a act will be inserted into the menu \a d + at index \a idx. + + \param[in] d The menu to inser the action into. + + \param[in] idx The index at which to insert the action. The index + is zero based. If the index is (-1) or is larger than the + largest index in the menu, then the action is appended to the + menu. + + \param[in] act The action to insert. This is added by reference. + It is the callers reponsibility to ensure that the structure + pointed to by \a act is available throughout the lifetime of + the menu. + + \param[in] flags Flags for the action. This is a combination of + KHUI_ACTIONREF_* constants. Currently, the only constants + that are valid for this function are: ::KHUI_ACTIONREF_SEP, + ::KHUI_ACTIONREF_SUBMENU, ::KHUI_ACTIONREF_DEFAULT. For this + function, ::KHUI_ACTIONREF_PACTION will automatically be aded + when adding the action. ::KHUI_ACTIONREF_SEP will be + automatically added if the command is ::KHUI_MENU_SEP. If + ::KHUI_ACTIONREF_DEFAULT is specified, then all other items in + the menu will be stripped of that flag leaving this action as + the only one with that flag set. +*/ +KHMEXP void KHMAPI +khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * act, khm_int32 flags); + +#define khui_menu_add_paction(d,a,f) khui_menu_insert_paction((d),-1,(a),(f)) +#pragma deprecated(khui_menu_add_paction) + +#endif + +/*! \brief Remove an action from a menu + + The action at the specified index will be removed from the menu. + */ +KHMEXP void KHMAPI +khui_menu_remove_action(khui_menu_def * d, khm_size idx); + +/*! \brief Get the number of items in the menu + + Note that the count includes menu separators. The indices of the + menu items range from 0 to one less than the value returned by + this function. + */ +KHMEXP khm_size KHMAPI +khui_menu_get_size(khui_menu_def * d); + +/*! \brief Get the menu item at a specified index + + The returned reference is only valid while the ::khui_menu_def + structure is valid. In addition, the reference becomes invalid if + the list of actions in the menu data structure is modified in any + way. + + If the specified index is out of bounds, then the function returns + NULL. + + */ +KHMEXP khui_action_ref * +khui_menu_get_action(khui_menu_def * d, khm_size idx); + +/*! \brief Action scope identifiers + + The scope identifier is a value which describes the scope of the + cursor context. See documentation on individual scope identifiers + for details. + + The role of the scope identifier is to provide a summary of the + current cursor context. Specifically, these identify several + special cases of credential selection, such as the selection of an + entire identity, a credential type or a single credential. If + none of these are applicable, then the generic scope identifier + ::KHUI_SCOPE_GROUP is set or ::KHUI_SCOPE_NONE if there is nothing + selected. + + Note that the scope typically only apply to cursor contexts and + not the selection context. Please see + \ref khui_context "UI Contexts" for more information. + + \see \ref khui_context "UI Contexts" +*/ +typedef enum tag_khui_scope { + KHUI_SCOPE_NONE, + /*!< No context. Nothing is selected. */ + + KHUI_SCOPE_IDENT, + /*!< Identity. The selection is the entire identity specified in + the \a identity field of the context. */ + + KHUI_SCOPE_CREDTYPE, + /*!< A credentials type. The selection is an entire credentials + type. If \a identity is non-NULL, then the scope is all the + credentials of type \a cred_type which belong to \a identity. + Otherwise, the selection is all credentials of type \a + cred_type. + + \note The \a identity can be non-NULL even for the case where + all credentials of type \a cred_type under \a identity is the + same scope as all credentials of type \a cred_type under all + identities. */ + + KHUI_SCOPE_GROUP, + /*!< A grouping of credentials. The scope is a group of + credentials which can not be simplified using one of the other + context identifiers. The \a headers array contains \a n_headers + elements describing the outline level that has been selected. + + \see ::khui_header + \see \ref khui_context_sel_ctx_grp "KHUI_SCOPE_GROUP description" */ + + KHUI_SCOPE_CRED + /*!< A single credential. Only a single credential was + selected. The \a cred field of the context specifies the + credential. The \a identity and \a cred_type fields specify the + identity and the credential type respectively. */ +} khui_scope; + + +/*! \brief Outline header + + Describes an outline header in the user interface. + + \see \ref khui_context_sel_ctx_grp "KHUI_SCOPE_GROUP description" + */ +typedef struct tag_khui_header { + khm_int32 attr_id; /*!< Attribute ID */ + void * data; /*!< Value of attribute */ + khm_size cb_data; /*!< Size of the value */ +} khui_header; + +/*! \brief Maximum number of outline headers + + This is the maximum number of fields that the credentials view can + be grouped by. + */ +#define KHUI_MAX_HEADERS 6 + +/*! \brief Action context + + Represents the UI context for an action. + */ +typedef struct tag_khui_action_context { + khm_int32 magic; /*!< Internal. */ + khui_scope scope; /*!< Context scope. One of ::khui_scope*/ + khm_handle identity; /*!< Identity */ + khm_int32 cred_type; /*!< Credential type ID */ + khm_handle cred; /*!< Credential */ + + khui_header headers[KHUI_MAX_HEADERS]; + /*!< The ordered set of outline + headers which define the current + cursor location. */ + + khm_size n_headers; /*!< Number of actual headers defined + above */ + + khm_handle credset; /*!< Handle to a credential set + containing the currently selected + credentials. When the context is + obtained through khui_context_get(), + this credential is returned in a + sealed state. */ + + khm_size n_sel_creds; /*!< Number of selected credentials */ + + void * int_buf; /*!< Internal. Do not use. */ + khm_size int_cb_buf; /*!< Internal. Do not use. */ + khm_size int_cb_used; /*!< Internal. Do not use. */ + + void * vparam; /*!< Optional data */ + khm_size cb_vparam; /*!< Size of optional data */ +} khui_action_context; + +/*! \brief Set the current context + + Changes the UI context to that represented by the parameters to + the function. Note that specifying a valid \a identity or \a cred + parameter will result in an automatic hold on the respective + object. The hold will stay until another call to + khui_context_set() overwrites the identity or credential handle or + a call to khui_context_reset() is made. + + While this API is available, it is only called from the main + NetIDMgr application. Plugins do not have a good reason to call + this API directly and should not do so. + + \param[in] scope The new context scope + + \param[in] identity A handle to an identity. If this is not NULL, + then it should be a valid handle to an identity. Required if + \a scope specifies ::KHUI_SCOPE_IDENT. Optional if \a scope + specifies ::KHUI_SCOPE_CREDTYPE. Ignored otherwise. + + \param[in] cred_type A credentials type. Specify + ::KCDB_CREDTYPE_INVALID if this parameter is not given or not + relevant. Required if \a scope specifies + ::KHUI_SCOPE_CREDTYPE. Ignored otherwise. + + \param[in] cred A handle to a credential. If this parameter is + not NULL it is expected to be a valid handle to a credential. + Required if \a scope specifies ::KHUI_SCOPE_CRED. Ignored + otherwise. + + \param[in] headers An array of headers. The \a n_headers + parameter specifies the number of elements in the array. Set + to NULL if not specified. Required if \a scope specifies + ::KHUI_SCOPE_GROUP. + + \param[in] n_headers Number of elements in \a headers. Must be + less than or equal to ::KHUI_MAX_HEADERS. Required if \a + headers is not NULL. Ignored otherwise. + + \param[in] cs_src A handle to a credential set from which the + selected credentials will be extracted. The credentials that + are selected must have the ::KCDB_CRED_FLAG_SELECTED flag set. + + \note This function should only be called from the UI thread. + */ +KHMEXP void KHMAPI +khui_context_set(khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred, + khui_header *headers, + khm_size n_headers, + khm_handle cs_src); + +/*! \brief Set the current context + + Changes the UI context to that represented by the parameters to + the function. Note that specifying a valid \a identity or \a cred + parameter will result in an automatic hold on the respective + object. The hold will stay until another call to + khui_context_set() overwrites the identity or credential handle or + a call to khui_context_reset() is made. + + While this API is available, it is only called from the main + NetIDMgr application. Plugins do not have a good reason to call + this API directly and should not do so. + + \param[in] scope The new context scope + + \param[in] identity A handle to an identity. If this is not NULL, + then it should be a valid handle to an identity. Required if + \a scope specifies ::KHUI_SCOPE_IDENT. Optional if \a scope + specifies ::KHUI_SCOPE_CREDTYPE. Ignored otherwise. + + \param[in] cred_type A credentials type. Specify + ::KCDB_CREDTYPE_INVALID if this parameter is not given or not + relevant. Required if \a scope specifies + ::KHUI_SCOPE_CREDTYPE. Ignored otherwise. + + \param[in] cred A handle to a credential. If this parameter is + not NULL it is expected to be a valid handle to a credential. + Required if \a scope specifies ::KHUI_SCOPE_CRED. Ignored + otherwise. + + \param[in] headers An array of headers. The \a n_headers + parameter specifies the number of elements in the array. Set + to NULL if not specified. Required if \a scope specifies + ::KHUI_SCOPE_GROUP. + + \param[in] n_headers Number of elements in \a headers. Must be + less than or equal to ::KHUI_MAX_HEADERS. Required if \a + headers is not NULL. Ignored otherwise. + + \param[in] cs_src A handle to a credential set from which the + selected credentials will be extracted. The credentials that + are selected must have the ::KCDB_CRED_FLAG_SELECTED flag set. + + \param[in] vparam Optional parameter blob + + \param[in] cb_vparam Size of parameter blob + + \note This function should only be called from the UI thread. + */ +KHMEXP void KHMAPI +khui_context_set_ex(khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred, + khui_header *headers, + khm_size n_headers, + khm_handle cs_src, + void * vparam, + khm_size cb_vparam); + +/*! \brief Set the current UI context using an existing context + + Copies the context specified in \a ctx into the active UI context. + + \param[in] ctx A pointer to a ::khui_action_context structure that + specifies the new UI context. Cannot be NULL. +*/ +KHMEXP void KHMAPI +khui_context_set_indirect(khui_action_context * ctx); + +/*! \brief Obtain the current UI context + + The parameter specified by \a ctx will receive the current UI + context. If the context contains an identity or a credential + handle, a hold will be obtained on the relevant object. Use + khui_context_release() to release the holds obtained in a prior + call to khui_context_get(). + + \note The returned context should not be modified prior to calling + khui_context_release(). +*/ +KHMEXP void KHMAPI +khui_context_get(khui_action_context * ctx); + +/*! \brief Create a new UI context + + The created context does not have any relation to the current UI + context. This function is provided for use in situations where an + application needs to provide a scope description through a + ::khui_action_context structure. + + Once the application is done with the context, it should call + khui_context_release() to release the created context. + */ +KHMEXP void KHMAPI +khui_context_create(khui_action_context * ctx, + khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred); + +/*! \brief Release a context obtained using khui_context_get() + + Releases all holds obtained on related objects in a prior call to + khui_context_get() and nullifies the context. + + \note The context should not have been modified between calling + khui_context_get() and khui_context_release() + */ +KHMEXP void KHMAPI +khui_context_release(khui_action_context * ctx); + +/*! \brief Reset the UI context + + Nullifies the current UI context and releases any holds obtained + on objects related to the previous context. +*/ +KHMEXP void KHMAPI +khui_context_reset(void); + +/*! \brief Refresh context data + + Setting the UI context involves other side effects such as + activation of or disabling certain actions based on the selection. + If an operation is performed which may affect the side effects, + khui_context_refresh() is called to refresh them. + + An example is when setting the default identity. The state of the + action ::KHUI_ACTION_SET_DEF_ID depends on whether the currently + selected identity is the default. However, if the currently + selected identity becomes the default after selection, then + khui_context_refresh() should be called to adjust the state of the + ::KHUI_ACTION_SET_DEF_ID action. + */ +KHMEXP void KHMAPI +khui_context_refresh(void); + +/*! \brief A filter function that filters for credentials in the cursor context + + This is a function of type ::kcdb_cred_filter_func which can be + used to filter for credentials that are included in the cursor + context. + + The \a rock parameter should be a pointer to a + ::khui_action_context structure which will be used as the filter. + + For example, the following code will extract the cursor context + credentials into the credential set \a my_credset based on the UI + context \a my context: + + \code + kcdb_credset_extract_filtered(my_credset, + NULL, + khui_context_cursor_filter, + (void *) my_context); + \endcode +*/ +KHMEXP khm_int32 KHMAPI +khui_context_cursor_filter(khm_handle cred, + khm_int32 flags, + void * rock); + +/*! \brief Get a string representation of an accelerator + + \param[in] cmd Command for which to obtain the accelerator string for + \param[out] buf Buffer to receive the accelerator string + \param[in] bufsiz Size of the buffer in bytes. Note that the size of the + buffer must be sufficient to hold at least one character and a + NULL terminator. + + \return TRUE if the operation was successful. FALSE otherwise. + */ +KHMEXP khm_boolean KHMAPI khui_get_cmd_accel_string(khm_int32 cmd, wchar_t * buf, khm_size bufsiz); + +#ifdef NOEXPORT +/*! \brief Initializes the global accelerator table + */ +KHMEXP HACCEL KHMAPI khui_create_global_accel_table(void); +#endif + +/*! \brief Find a menu by id + + Finds the menu that is associated with the specified action. + */ +KHMEXP khui_menu_def * KHMAPI khui_find_menu(khm_int32 action); + +#ifdef NOEXPORT + +/* internal */ +KHMEXP void KHMAPI +khui_set_main_window(HWND hwnd); + +#endif + +/*! \brief Trigger an action + + Triggers the specified action using the specified UI context. + + This function does not return until the specified action has been + processed. Many standard actions are asynchronous and they will + return before processing will complete. + + Pseudo actions should not be triggered using khui_action_trigger() + as they only carry meaning when invoked from specific windows or + contexts. + + \param[in] action Action. Should be one of the standard actions + or an action created by khui_action_create() + + \param[in] ctx The UI context to use for the action. If this is + NULL, the action will be triggered under the current UI context. + */ +KHMEXP void KHMAPI +khui_action_trigger(khm_int32 action, khui_action_context * ctx); + +/*! \brief Find an action by id + + \note This function should not be used by plugins. It is there + for use by the NetIDMgr application. +*/ +KHMEXP khui_action * KHMAPI khui_find_action(khm_int32 action); + +#ifdef NOEXPORT +/*! \brief Get the length of the action list */ +KHMEXP size_t KHMAPI khui_action_list_length(khui_action_ref * ref); +#endif + +/*! \brief Create a new action + + Creates a new custom action. The created custom action can be + added to menus, toolbars and can be triggered by + khui_action_trigger(). + + When the action is triggered as a result of the user selecting a + menu item, a toolbar item or as a result of calling + khui_action_trigger(), the subscription identified by \a hsub will + received a message of type ::KMSG_ACT, subtype + ::KMSG_ACT_ACTIVATE. The \a uparam for the message will be the + action identifier that was returned by khui_action_create(). The + \a vparam of the message will currently be set to \a NULL. + + Actions can optionally be named. The name is not actively used by + the Network Identity Manager framework, but can be used to label + actions so that they can be looked up later using + khui_find_named_action(). + + \param[in] name Name for a named action. The name must be unique + among all registered actions. (limited by KHUI_MAXCCH_NAME). + (Optional. Set to NULL if the action is not a named action.) + See \a note below for additional restrictions on the name of + the action. + + \param[in] caption The localized caption for the action. This + will be shown in menus, toolbars and buttons when the action + needs to be represented. (limited by KHUI_MAXCCH_SHORT_DESC) + (Required) + + \param[in] tooltip The localized tooltip for the action. (limited + by KHUI_MAXCCH_SHORT_DESC) (Optional, set to NULL if there is + no tooltip associated with the action) + + \param[in] userdata A custom value. + + \param[in] type The type of the action. Currently it should be + set to either ::KHUI_ACTIONTYPE_TRIGGER or + ::KHUI_ACTIONTYPE_TOGGLE. For ::KHUI_ACTIONTYPE_TOGGLE, the + initial state will be unchecked. Use khui_check_action() + function to change the checked state of the action. + + \param[in] hsub The subscription that is notified when the action + is triggered. (Optional) The subscription must be created with + kmq_create_subscription(). The handle will be released when + it is no longer needed. Hence, the caller should not release + it. + + \return The identifier of the new action or zero if the action + could not be created. + + \note For named custom actions, the name of the action can not be + the same as the name of a configuration node. See + khui_cfg_register_node(). + */ +KHMEXP khm_int32 KHMAPI +khui_action_create(const wchar_t * name, + const wchar_t * caption, + const wchar_t * tooltip, + void * userdata, + khm_int32 type, + khm_handle hsub); + +/* \brief Delete a custom action + + Deletes a custom action created by a call to khui_action_create(). + Custom actions should only be deleted when unloading a plugin. + */ +KHMEXP void KHMAPI +khui_action_delete(khm_int32 action); + +/*! \brief Get the user data associated with a custom action + + This function returns the user data that was specified when the + custom action was created usng khui_action_create(). If the + custom action identifier is invalid or if the custom action does + not contain any user data, this function will return NULL. + */ +KHMEXP void * KHMAPI +khui_action_get_data(khm_int32 action); + +/*! \brief Find an action by name */ +KHMEXP khui_action * KHMAPI khui_find_named_action(const wchar_t * name); + +/*! \brief Enables or disables a group of actions + + The group of actions are specified by the menu definition. All + valid action entries in the menu are marked as enabled or disabled + according to the value of \a enable. + */ +KHMEXP void KHMAPI khui_enable_actions(khui_menu_def * d, khm_boolean enable); + +/*! \brief Enables or disables an action + + The action designated by the command \a action will either be enabled + or disabled depending on the \a enable parameter. If \a enable is + TRUE then the action is enabled. + */ +KHMEXP void KHMAPI khui_enable_action(khm_int32 action, khm_boolean enable); + +/*! \brief Check an action in an action group + + Marks the action denoted by \a action as checked and resets the + checked bit in all other actions. + + \param[in] d A menu definition. + + \param[in] action A command identifier. Setting this to -1 will + reset the checked bit in all the actions in the menu + definition. + */ +KHMEXP void KHMAPI khui_check_radio_action(khui_menu_def * d, khm_int32 action); + +/*! \brief Check an action + + For toggle typed actions, this sets or resets the check. + */ +KHMEXP void KHMAPI khui_check_action(khm_int32 cmd, khm_boolean check); + +#ifdef NOEXPORT +/*!\cond INTERNAL */ + +/*! \brief Initialize actions + + \note Only called by the NetIDMgr application + */ +KHMEXP void KHMAPI khui_init_actions(void); + +/*! \brief Exit actions + + \note Only called by the NetIDMgr application + */ +KHMEXP void KHMAPI khui_exit_actions(void); + +/*! \endcond */ +#endif + +/*@}*/ +/*@}*/ +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khactiondef.h b/krb5-1-6/src/windows/identity/uilib/khactiondef.h new file mode 100644 index 000000000..33d8347eb --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khactiondef.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_ACTIONDEF_H +#define __KHIMAIRA_ACTIONDEF_H + +/*! \ingroup khui_actions + @{*/ +/*! \defgroup khui_std_actions Standard Actions +@{ */ + +/*!\name Standard actions + @{*/ +#define KHUI_ACTION_BASE 50000 + +#define KHUI_ACTION_PROPERTIES (KHUI_ACTION_BASE + 0) +#define KHUI_ACTION_EXIT (KHUI_ACTION_BASE + 1) +#define KHUI_ACTION_SET_DEF_ID (KHUI_ACTION_BASE + 3) +#define KHUI_ACTION_SET_SRCH_ID (KHUI_ACTION_BASE + 4) +#define KHUI_ACTION_PASSWD_ID (KHUI_ACTION_BASE + 7) +#define KHUI_ACTION_NEW_CRED (KHUI_ACTION_BASE + 8) +#define KHUI_ACTION_DEBUG_WINDOW (KHUI_ACTION_BASE + 10) +#define KHUI_ACTION_VIEW_REFRESH (KHUI_ACTION_BASE + 11) +#define KHUI_ACTION_LAYOUT_ID (KHUI_ACTION_BASE + 12) +#define KHUI_ACTION_LAYOUT_TYPE (KHUI_ACTION_BASE + 13) +#define KHUI_ACTION_LAYOUT_LOC (KHUI_ACTION_BASE + 14) +#define KHUI_ACTION_TB_STANDARD (KHUI_ACTION_BASE + 15) +#define KHUI_ACTION_OPT_KHIM (KHUI_ACTION_BASE + 16) +#define KHUI_ACTION_OPT_IDENTS (KHUI_ACTION_BASE + 17) +#define KHUI_ACTION_OPT_NOTIF (KHUI_ACTION_BASE + 18) +#define KHUI_ACTION_HELP_CTX (KHUI_ACTION_BASE + 19) +#define KHUI_ACTION_HELP_CONTENTS (KHUI_ACTION_BASE + 20) +#define KHUI_ACTION_HELP_INDEX (KHUI_ACTION_BASE + 21) +#define KHUI_ACTION_HELP_ABOUT (KHUI_ACTION_BASE + 22) +#define KHUI_ACTION_DESTROY_CRED (KHUI_ACTION_BASE + 23) +#define KHUI_ACTION_RENEW_CRED (KHUI_ACTION_BASE + 24) +#define KHUI_ACTION_OPEN_APP (KHUI_ACTION_BASE + 25) +#define KHUI_ACTION_MENU_ACTIVATE (KHUI_ACTION_BASE + 26) +#define KHUI_ACTION_CLOSE_APP (KHUI_ACTION_BASE + 27) +#define KHUI_ACTION_IMPORT (KHUI_ACTION_BASE + 28) +#define KHUI_ACTION_OPT_PLUGINS (KHUI_ACTION_BASE + 29) +#define KHUI_ACTION_LAYOUT_CUST (KHUI_ACTION_BASE + 30) +#define KHUI_ACTION_OPT_APPEAR (KHUI_ACTION_BASE + 31) +#define KHUI_ACTION_LAYOUT_RELOAD (KHUI_ACTION_BASE + 32) +#define KHUI_ACTION_RENEW_ALL (KHUI_ACTION_BASE + 33) +#define KHUI_ACTION_DESTROY_ALL (KHUI_ACTION_BASE + 34) +#define KHUI_ACTION_UICB (KHUI_ACTION_BASE + 35) +#define KHUI_ACTION_LAYOUT_MINI (KHUI_ACTION_BASE + 36) +#define KHUI_ACTION_VIEW_ALL_IDS (KHUI_ACTION_BASE + 37) +/*@}*/ + +/*! \name Pseudo actions + +Pseudo actions do not trigger any specific function, but acts as a +signal of some generic event which will be interpreted based on +context. + +@{*/ +#define KHUI_PACTION_BASE (KHUI_ACTION_BASE + 500) + +#define KHUI_PACTION_MENU (KHUI_PACTION_BASE + 0) +#define KHUI_PACTION_UP (KHUI_PACTION_BASE + 1) +#define KHUI_PACTION_DOWN (KHUI_PACTION_BASE + 2) +#define KHUI_PACTION_LEFT (KHUI_PACTION_BASE + 3) +#define KHUI_PACTION_RIGHT (KHUI_PACTION_BASE + 4) +#define KHUI_PACTION_ENTER (KHUI_PACTION_BASE + 5) +#define KHUI_PACTION_ESC (KHUI_PACTION_BASE + 6) +#define KHUI_PACTION_OK (KHUI_PACTION_BASE + 7) +#define KHUI_PACTION_CANCEL (KHUI_PACTION_BASE + 8) +#define KHUI_PACTION_CLOSE (KHUI_PACTION_BASE + 9) +#define KHUI_PACTION_DELETE (KHUI_PACTION_BASE + 10) +#define KHUI_PACTION_UP_EXTEND (KHUI_PACTION_BASE + 11) +#define KHUI_PACTION_UP_TOGGLE (KHUI_PACTION_BASE + 12) +#define KHUI_PACTION_DOWN_EXTEND (KHUI_PACTION_BASE + 13) +#define KHUI_PACTION_DOWN_TOGGLE (KHUI_PACTION_BASE + 14) +#define KHUI_PACTION_BLANK (KHUI_PACTION_BASE + 15) +#define KHUI_PACTION_NEXT (KHUI_PACTION_BASE + 16) +#define KHUI_PACTION_SELALL (KHUI_PACTION_BASE + 17) +#define KHUI_PACTION_YES (KHUI_PACTION_BASE + 18) +#define KHUI_PACTION_NO (KHUI_PACTION_BASE + 19) +#define KHUI_PACTION_YESALL (KHUI_PACTION_BASE + 20) +#define KHUI_PACTION_NOALL (KHUI_PACTION_BASE + 21) +#define KHUI_PACTION_REMOVE (KHUI_PACTION_BASE + 22) +#define KHUI_PACTION_KEEP (KHUI_PACTION_BASE + 23) +#define KHUI_PACTION_DISCARD (KHUI_PACTION_BASE + 24) +#define KHUI_PACTION_PGDN (KHUI_PACTION_BASE + 25) +#define KHUI_PACTION_PGUP (KHUI_PACTION_BASE + 26) +#define KHUI_PACTION_PGUP_EXTEND (KHUI_PACTION_BASE + 27) +#define KHUI_PACTION_PGDN_EXTEND (KHUI_PACTION_BASE + 28) + +/*@}*/ + +/*! \name Menus + +Stock menus. + +@{*/ +#define KHUI_MENU_BASE (KHUI_ACTION_BASE + 1000) + +#define KHUI_MENU_MAIN (KHUI_MENU_BASE + 0) +#define KHUI_MENU_FILE (KHUI_MENU_BASE + 1) +#define KHUI_MENU_CRED (KHUI_MENU_BASE + 2) +#define KHUI_MENU_VIEW (KHUI_MENU_BASE + 3) +#define KHUI_MENU_OPTIONS (KHUI_MENU_BASE + 4) +#define KHUI_MENU_HELP (KHUI_MENU_BASE + 5) + +#define KHUI_MENU_LAYOUT (KHUI_MENU_BASE + 6) +#define KHUI_MENU_TOOLBARS (KHUI_MENU_BASE + 7) + +#define KHUI_MENU_IDENT_CTX (KHUI_MENU_BASE + 8) +#define KHUI_MENU_TOK_CTX (KHUI_MENU_BASE + 9) +#define KHUI_MENU_ICO_CTX_MIN (KHUI_MENU_BASE + 12) +#define KHUI_MENU_ICO_CTX_NORMAL (KHUI_MENU_BASE + 13) +#define KHUI_MENU_CWHEADER_CTX (KHUI_MENU_BASE + 14) + +#define KHUI_MENU_COLUMNS (KHUI_MENU_BASE + 15) + +#define KHUI_PMENU_TOK_SEL (KHUI_MENU_BASE + 10) +#define KHUI_PMENU_ID_SEL (KHUI_MENU_BASE + 11) + +#define KHUI_MENU_DESTROY_CRED (KHUI_MENU_BASE + 16) +#define KHUI_MENU_RENEW_CRED (KHUI_MENU_BASE + 17) +#define KHUI_MENU_SETDEF (KHUI_MENU_BASE + 18) + +/*@}*/ + +/*! \name Toolbars +@{*/ +#define KHUI_TOOLBAR_BASE (KHUI_ACTION_BASE + 2000) + +#define KHUI_TOOLBAR_STANDARD (KHUI_TOOLBAR_BASE + 0) +/*@}*/ + +/*! \brief Base for user actions + + When creating new actions, the UI library will allocate command + identifiers starting with this one. +*/ +#define KHUI_USERACTION_BASE (KHUI_ACTION_BASE + 10000) + +/*! \brief Does this command represent a user action? */ +#define IS_USERACTION(cmd) ((cmd) >= KHUI_USERACTION_BASE) +/*@}*/ +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khalerts.h b/krb5-1-6/src/windows/identity/uilib/khalerts.h new file mode 100644 index 000000000..751abce01 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khalerts.h @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHALERTS_H +#define __KHIMAIRA_KHALERTS_H + +/********************************************************************* + Alerter and error reporting +**********************************************************************/ + +/*! \addtogroup khui +@{ */ + +/*!\defgroup khui_alert Alerter and Error Reporting +@{*/ + +struct tag_khui_alert; +typedef struct tag_khui_alert khui_alert; + +#define KHUI_MAX_ALERT_COMMANDS 4 + +/*! \brief Maximum number of characters in title including terminating NULL + */ +#define KHUI_MAXCCH_TITLE 256 + +/*! \brief Maximum number of bytes in title including terminating NULL + */ +#define KHUI_MAXCB_TITLE (KHUI_MAXCCH_TITLE * sizeof(wchar_t)) + +/*! \brief Maximum number of characters in message including terminating NULL + */ +#define KHUI_MAXCCH_MESSAGE 1024 + +/*! \brief Maximum number of bytes in message including terminating NULL + */ +#define KHUI_MAXCB_MESSAGE (KHUI_MAXCCH_MESSAGE * sizeof(wchar_t)) + +/*! \brief Maxumum number of characters in a suggestion including terminating NULL */ +#define KHUI_MAXCCH_SUGGESTION 1024 + +/*! \brief Maximum number of bytes in a suggestion, including terminating NULL */ +#define KHUI_MAXCB_SUGGESTION (KHUI_MAXCCH_SUGGESTION * sizeof(wchar_t)) + +/*! \brief Flags for an alert */ +enum khui_alert_flags { + KHUI_ALERT_FLAG_FREE_STRUCT =0x00000001, + /*!< Internal. Free the structure once the alert is done. */ + + KHUI_ALERT_FLAG_FREE_TITLE =0x00000002, + /*!< Internal. Free the \a title field when the alert is done.*/ + + KHUI_ALERT_FLAG_FREE_MESSAGE =0x00000004, + /*!< Internal. Free the \a message field when the alert is done. */ + + KHUI_ALERT_FLAG_FREE_SUGGEST =0x00000008, + /*!< Internal. Free the \a suggest field when the alert is done */ + + KHUI_ALERT_FLAG_DEFACTION =0x00000010, + /*!< If the message is displayed as a balloon prompt, then perform + the default action when it is clicked. The default action is + the first action added to the alert. Cannot be used if there + are no actions or if ::KHUI_ALERT_FLAG_REQUEST_WINDOW is + specified.*/ + + KHUI_ALERT_FLAG_DISPATCH_CMD =0x00000020, + /*!< If the message has commands, when the user clicks on one of + the command buttons, the corresponding command will be + immediately dispatched as if khui_action_trigger() is called + with a NULL UI context. Otherwise, the selected command will be + stored in the alert and can be retrieved via a call to + khui_alert_get_response(). */ + + KHUI_ALERT_FLAG_VALID_TARGET =0x00010000, + /*!< Internal. There is a valid target for the alert */ + + KHUI_ALERT_FLAG_VALID_ERROR =0x00020000, + /*!< Internal. There is a valid error context associated with the alert */ + + KHUI_ALERT_FLAG_DISPLAY_WINDOW =0x01000000, + /*!< The alert has been displayed in a window */ + + KHUI_ALERT_FLAG_DISPLAY_BALLOON =0x02000000, + /*!< The alert has been displayed in a ballon */ + + KHUI_ALERT_FLAG_REQUEST_WINDOW =0x04000000, + /*!< The alert should be displayed in a window */ + + KHUI_ALERT_FLAG_REQUEST_BALLOON =0x08000000, + /*!< The alert should be displayed in a balloon */ + + KHUI_ALERT_FLAG_MODAL =0x10000000, + /*!< Internal. Modal alert. Do not set direclty. */ + + KHUI_ALERT_FLAGMASK_RDWR =0x0C000030, + /*!< Bit mask of flags that can be set by khui_alert_set_flags() */ +}; + +/*! \brief Alert types + + These types can be set with khui_alert_set_type() to indicate + which type of alert this is. The types defined here are + identified by the Network Identity Manager and will receive + special handling whereever appropriate. + + The type is a hint to the application and will not guarantee a + particular behavior. + */ +typedef enum tag_khui_alert_types { + KHUI_ALERTTYPE_NONE = 0, /*!< No specific alert type */ + KHUI_ALERTTYPE_PLUGIN, /*!< Plug-in or module load related + alert */ + KHUI_ALERTTYPE_EXPIRE, /*!< Credential or identity expiration + warning */ + KHUI_ALERTTYPE_RENEWFAIL, /*!< Failed to renew credentials */ + KHUI_ALERTTYPE_ACQUIREFAIL, /*!< Failed to acquire credentials */ + KHUI_ALERTTYPE_CHPW, /*!< Failed to change password */ +} khui_alert_type; + +/*! \brief Create an empty alert object + + The returned result is a held pointer to a ::khui_alert object. + Use khui_alert_release() to release the object. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_create_empty(khui_alert ** result); + +/*! \brief Create a simple alert object + + The returned result is a held pointer to a ::khui_alert object. + Use khui_alert_release() to release the object. + + \param[in] title The title of the alert. (Required, Localized) + Limited by ::KHUI_MAXCCH_TITLE. + + \param[in] message The message. (Required. Localized). Limited + by ::KHUI_MAXCCH_MESSAGE. + + \param[in] severity One of ::tag_kherr_severity + + \param[out] result Receives a held pointer to a ::khui_alert + object upon successful completion. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_create_simple(const wchar_t * title, + const wchar_t * message, + khm_int32 severity, + khui_alert ** result); + +/*! \brief Set the title of an alert object + + The title is limited by ::KHUI_MAXCCH_TITLE. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_set_title(khui_alert * alert, + const wchar_t * title); + +/*! \brief Set the message of an alert object + + The message is limited by ::KHUI_MAXCCH_MESSAGE. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_set_message(khui_alert * alert, + const wchar_t * message); + +/*! \brief Set the suggestion of an alert object + + The suggestion is limited by ::KHUI_MAXCCH_SUGGESTION + */ +KHMEXP khm_int32 KHMAPI +khui_alert_set_suggestion(khui_alert * alert, + const wchar_t * suggestion); + +/*! \brief Set the severity of the alert object + + The severity value is one of ::tag_kherr_severity + */ +KHMEXP khm_int32 KHMAPI +khui_alert_set_severity(khui_alert * alert, + khm_int32 severity); + +/*! \brief Sets the flags of the alert + + The flags are as defined in ::khui_alert_flags. The bits that are + on in \a mask will be set to the corresponding values in \a flags. + Only the bits specified in ::KHUI_ALERT_FLAGMASK_RDWR can be + specified in \a mask. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_set_flags(khui_alert * alert, khm_int32 mask, khm_int32 flags); + +/*! \brief Clear all the commands from an alert object + + \see khui_alert_add_command() + */ +KHMEXP khm_int32 KHMAPI +khui_alert_clear_commands(khui_alert * alert); + +/*! \brief Add a command to an alert object + + The command ID should be a valid registered action. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_add_command(khui_alert * alert, + khm_int32 command_id); + +/*! \brief Set the type of alert + */ +KHMEXP khm_int32 KHMAPI +khui_alert_set_type(khui_alert * alert, + khui_alert_type type); + +/*! \brief Set the action context for the alert */ +KHMEXP khm_int32 KHMAPI +khui_alert_set_ctx(khui_alert * alert, + khui_scope scope, + khm_handle identity, + khm_int32 cred_type, + khm_handle cred); + +/*! \brief Get the response code from an alert + + Once an alert has been displayed to the user, the user may choose + a command from the list of commands provided in the alert (see + khui_alert_add_command() ). This function can retrieve the + selected command from the alert. + + \return The selected command or \a 0 if no commands were selected. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_get_response(khui_alert * alert); + + +/*! \brief Display an alert + + The alert must have a valid \a severity, \a title and a \a message + to be displayed. Otherwise the function immediately returns with + a failure code. + + The method used to display the alert is as follows: + + - A balloon alert will be shown if one of the following is true: + - The NetIDMgr application is minimized or in the background. + - ::KHUI_ALERT_FLAG_REQUEST_BALLOON is specified in \a flags. + - Otherwise an alert window will be shown. + + If the message, title of the alert is too long to fit in a balloon + prompt, there's a suggestion or if there are custom commands then + a placeholder balloon prompt will be shown which when clicked on, + shows the actual alert in an alert window. + + An exception is when ::KHUI_ALERT_FLAG_DEFACTION is specified in + flags. In this case instead of a placeholder balloon prompt, one + will be shown with the actual title and message (truncated if + necessary). Clicking on the balloon will cause the first command + in the command list to be performed. + + The placeholder balloon prompt will have a title derived from the + first 63 characters of the \a title field in the alert and a + message notifying the user that they should click the balloon + prompt for more information. + + To this end, it is beneficial to limit the length of the title to + 63 characters (64 counting the terminating NULL). This limit is + enforced on Windows. Also, try to make the title descriptive. + + User interaction with the alert will be as follows: + + - If the alert contains no commands, then the alert will be + displayed to the user as described above. A 'close' button will + be added to the alert if the alert is being displayed in a + window. + + - If the alert contains commands, has the + ::KHUI_ALERT_FLAG_DEFACTION flag set and is displayed in a + balloon and the user clicks on it, the first command in the + command list will be executed. + + - If the alert contains commands and does not have the + ::KHUI_ALERT_FLAG_DEFACTION and has the + ::KHUI_ALERT_FLAG_DISPATCH_CMD flag set, then when the user + selects one of the command buttons, the corresponding command + will immediately be dispatched. (see + ::KHUI_ALERT_FLAG_DISPATCH_CMD). + + - If the alert contains command and have neither + ::KHUI_ALERT_FLAG_DEFACTION nor ::KHUI_ALERT_FLAG_DISPATCH_CMD, + then when the user selects one of the command buttons, the + selected command will be stored along with the alert. It can be + retrieved via a call to khui_alert_get_response(). + + */ +KHMEXP khm_int32 KHMAPI +khui_alert_show(khui_alert * alert); + +/*! \brief Display a modal alert + + Similar to khui_alert_show(), but shows a modal alert dialog. The + function does not return until the user has closed the alert. + + This function always opens an alert window (never shows a + balloon). + + */ +KHMEXP khm_int32 KHMAPI +khui_alert_show_modal(khui_alert * alert); + +/*! \brief Queue an alert + + Instead of displaying the alert immediately, the alert is queued + and the status bar updated to notify the user that there is a + pending alert. Once the user activates the pending alert, it will + be displayed as if khui_alert_show() was called. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_queue(khui_alert * alert); + +/*! \brief Display a simple alert + + \see khui_alert_show() + */ +KHMEXP khm_int32 KHMAPI +khui_alert_show_simple(const wchar_t * title, + const wchar_t * message, + khm_int32 severity); + +/*! \brief Obtain a hold on the alert + + An alert structure is only considered valid for the duration that + there is a hold on it. + + Use khui_alert_release() to release the hold. + */ +KHMEXP khm_int32 KHMAPI +khui_alert_hold(khui_alert * alert); + +/*! \brief Release the hold on the alert + + Holds obtained on an alert using any of the functions that either + return a held pointer to an alert or implicitly obtains a hold on + it need to be undone through a call to khui_alert_release(). + */ +KHMEXP khm_int32 KHMAPI +khui_alert_release(khui_alert * alert); + +/*! \brief Lock an alert + + Locking an alert disallows any other thread from accessing the + alert at the same time. NetIDMgr keeps a global list of all alert + objects and the user interface may access any of them at various + points in time. Locking the alert allows a thread to modify an + alert without causing another thread to be exposed to an + inconsistent state. + + Once a thread obtains a lock on the alert, it must call + khui_alert_unlock() to unlock it. Otherwise no other thread will + be able to access the alert. + + \note Currently the alert lock is global. Locking one alert + disallows access to all other alerts as well. + + \note Calling khui_alert_lock() is only necessary if you are + accessing the ::khui_alert structure directly. Calling any of + the khui_alert_* functions to modify the alert does not + require obtaining a lock, as they perform synchronization + internally. +*/ +KHMEXP void KHMAPI +khui_alert_lock(khui_alert * alert); + +/*! \brief Unlock an alert + + \see khui_alert_lock() +*/ +KHMEXP void KHMAPI +khui_alert_unlock(khui_alert * alert); + +/*!@}*/ +/*!@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khconfigui.h b/krb5-1-6/src/windows/identity/uilib/khconfigui.h new file mode 100644 index 000000000..bbc712a36 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khconfigui.h @@ -0,0 +1,627 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHCONFIGUI_H +#define __KHIMAIRA_KHCONFIGUI_H + +/*! \addtogroup khui +@{ */ + +/*! \defgroup khui_cfg Configuration Panels + + Configuration panels are the primary means from which the user is + presented with an interface to change NetIDMgr and plugin + configuration. + +@{ */ + +/*! \brief Configuration window notification message + + This is the message that will be used to notify dialog panels. + + The format of the message is : + - uMsg : KHUI_WM_CFG_NOTIFY + - HIWORD(wParam) : one of ::khui_wm_cfg_notifications + + \note This is the same as ::KHUI_WM_NC_NOTIFY + */ +#define KHUI_WM_CFG_NOTIFY (WM_APP + 0x101) + +/*! \brief Configuration notifications + + These are sent thorugh a ::KHUI_WM_CFG_NOTIFY message. + + The format of the message is : + - uMsg : KHUI_WM_CFG_NOTIFY + - HIWORD(wParam) : one of ::khui_wm_cfg_notifications + */ +enum khui_wm_cfg_notifications { + WMCFG_SHOW_NODE = 1, + /*!< Sent to the configuration dialog to request that the panel + for the specified node be shown. The \a lParam message + parameter will contain a held ::khui_config_node handle. The + sender of the mssage is responsible for releasing the handle.*/ + + WMCFG_UPDATE_STATE = 2, + /*!< Sent to the configuration dialog to indicate that the state + flags for the specified configuration node have changed. + + - LOWORD(wParam) : new flags + - lParam : ::khui_config_node for the node*/ + + WMCFG_APPLY = 3, + /*!< Sent to all the configuration panels when the user clicks the + 'Apply' button or the 'Ok' button. The panels are responsible + for applying the configuration changes and updating their flags + using khui_cfg_set_flags(). */ + + WMCFG_SYNC_NODE_LIST = 4, + /*!< Sent from the UI library to the configuration window to + notify the window that the node list has changed. This message + is sent synchronously before the node is removed. */ +}; + +/*! \brief Registration information for a configuration node + + \see khui_cfg_register_node() +*/ +typedef struct tag_khui_config_node_reg { + const wchar_t * name; /*!< Internal identifier + (not-localized, required). The name + is required to be unique among + sibling nodes. However it is not + required to be unique globally. The + size of the name is constrained by + ::KHUI_MAXCCH_NAME*/ + + const wchar_t * short_desc; /*!< Short description (Localized, + required). This is the name which + identifies the node within a + collection of siblings. The size of + the string is constrained by + ::KHUI_MAXCCH_SHORT_DESC*/ + + const wchar_t * long_desc; /*!< Global name of the node. + (Localized, required). This + uniquely identifies the node in the + collection of all configuration + nodes. The size of the string is + constrained by + ::KHUI_MAXCCH_LONG_DESC.*/ + + HMODULE h_module; /*!< Module which contains the dialog + resource specified in \a + dlg_template */ + + LPWSTR dlg_template; /*!< Dialog template for the + configuration window */ + + DLGPROC dlg_proc; /*!< Dialog procedure */ + + khm_int32 flags; /*!< Flags. Can be a combination of + ::KHUI_CNFLAG_SORT_CHILDREN and + ::KHUI_CNFLAG_SUBPANEL*/ + +} khui_config_node_reg; + +/*! \brief Sort the child nodes by short description */ +#define KHUI_CNFLAG_SORT_CHILDREN 0x0001 + +/*! \brief Is a subpanel */ +#define KHUI_CNFLAG_SUBPANEL 0x0002 + +/*! \brief Node represents a panel that is replicated for all child nodes */ +#define KHUI_CNFLAG_PLURAL 0x0004 + +/*! \brief System node + + \note For internal use by the NetIDMgr application. Do not use. +*/ +#define KHUI_CNFLAG_SYSTEM 0x0010 + +/*! \brief Settings have been modified + + Settings for this configuration panel have been modified. This + flag should be cleared once the settings have been successfully + applied. + */ +#define KHUI_CNFLAG_MODIFIED 0x0100 + +/*! \brief Settings have been applied + + Set once any modified settings were successfully applied. + */ +#define KHUI_CNFLAG_APPLIED 0x0200 + +#define KHUI_CNFLAGMASK_STATIC 0x00ff +#define KHUI_CNFLAGMASK_DYNAMIC 0x0f00 + +/*! \brief Maximum length of the name in characters + + The length includes the terminating NULL + */ +#define KHUI_MAXCCH_NAME 256 + +/*! \brief Maximum length of the name in bytes + + The length includes the terminating NULL + */ +#define KHUI_MAXCB_NAME (KHUI_MAXCCH_NAME * sizeof(wchar_t)) + +/*! \brief Maximum length of the long description in characters + + The length includes the terminating NULL + */ +#define KHUI_MAXCCH_LONG_DESC 1024 + +/*! \brief Maximum length of the long description in bytes + + The length includes the terminating NULL + */ +#define KHUI_MAXCB_LONG_DESC (KHUI_MAXCCH_LONG_DESC * sizeof(wchar_t)) + +/*! \brief Maximum length of the short description in chracters + + The length includes the terminating NULL + */ +#define KHUI_MAXCCH_SHORT_DESC 256 + +/*! \brief Maximum length of the short description in bytes + + The length includes the terminating NULL + */ +#define KHUI_MAXCB_SHORT_DESC (KHUI_MAXCCH_SHORT_DESC * sizeof(wchar_t)) + +/*! \brief Width of a configuration dialog in dialog units + + ::CFGDLG_WIDTH and ::CFGDLG_HEIGHT specify the dimensions of a + configuration dialog width and height in dialog units. The dialog + will be created as a child of the configuration dialog and placed + within it. + */ +#define CFGDLG_WIDTH 255 + +/*! \brief Height of a configuration dialog in dialog units + + \see ::CFGDLG_WIDTH +*/ +#define CFGDLG_HEIGHT 182 + +/*! \brief Width of a configuration tab dialog in dialog units + + ::CFGDLG_TAB_WIDTH and ::CFGDLG_TAB_HEIGHT specify the dimensions + (in dialog units) of a dialog that will be placed within a tab + control for dialogs where multiple display panels need to be + shown. + */ +#define CFGDLG_TAB_WIDTH 235 + +/*! \brief Height of configuration tab dialog in dialog units + + \see ::CFGDLG_TAB_WIDTH + */ +#define CFGDLG_TAB_HEIGHT 151 + +/*! \brief A handle to a configuration node + + \see khui_cfg_open_node(), khui_cfg_close_node() +*/ +typedef khm_handle khui_config_node; + +/*! \brief Initialization data passed in to a subpanel + + When creating a subpanel, a pointer to the following strucutred + will be passed in as the creation parameter for the dialog. +*/ +typedef struct tag_khui_config_init_data { + khui_config_node ctx_node; /*!< The node under which the current + dialog subpanel is being created. */ + + khui_config_node this_node; /*!< The node which provided the + registration information for the + creation of the subpanel. */ + + khui_config_node ref_node; /*!< The parent node of the subpanel + node. In nodes which have the + ::KHUI_CNFLAG_PLURAL, this would be + different from the \a node. This is + the node under which the subpanel + was registered. */ +} khui_config_init_data; + +/*! \brief Register a configuration node + + The caller fills the registration information in the + ::khui_config_node_reg structre. If the call succeeds, the + function will return KHM_ERROR_SUCCESS. + + \param[in] parent Parent of the node to be registered. Set to + NULL if the parent is the root node. + + \param[in] reg Registration information + + \param[out] new_id Receives the new unique identifier of the + configuration node. Pass in NULL if the new identifier is not + required. + + \retval KHM_ERROR_SUCCESS Success + \retval KHM_ERROR_INVALID_PARAM One or more parameters, or fields + of reg were invalid + \retval KHM_ERROR_DUPLICATE A node with the same name exists as a + child of the specified parent node. + + \note The name (not the short or long description) of the node can + not be the same as the name of a custom action. See + khui_action_create(). + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_register(khui_config_node parent, + const khui_config_node_reg * reg); + +/*!\brief Open a configuration node by name + + If successful, the \a result parameter will receive a handle to + the configuration node. Use khui_cfg_release() to release + the handle. + + \param[in] parent Parent node. Set to NULL to specify root node. + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_open(khui_config_node parent, + const wchar_t * name, + khui_config_node * result); + +/*! \brief Remove a configuration node + + Marks a configuration node as deleted. Once all the handles, + including the handle specified in \a node have been released, it + will be deleted. + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_remove(khui_config_node node); + +/*! \brief Hold a handle to a configuration node + + Obtains an additional hold on the handle specified by \a node. + The hold must be released with a call to \a + khui_cfg_release() + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_hold(khui_config_node node); + +/*! \brief Release a handle to a configuration node + + \see khui_cfg_hold() + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_release(khui_config_node node); + +/*! \brief Get the parent of a node + + Returns a held handle to the parent of the node, or NULL if the + current node is a top level node. The returned handle must be + released with khui_cfg_release(). + + \retval KHM_ERROR_SUCCESS The handle to the parent node is in \a result + \retval KHM_ERROR_NOT_FOUND The node is a top level node + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_parent(khui_config_node vnode, + khui_config_node * result); + +/*! \brief Get a handle to the first child node + + If the call is successful, \a result will receieve a handle to the + first child node of the specified node. The returned handle must + be released with a call to khui_cfg_release() + + If \a parent does not have any child nodes, the function will + return KHM_ERROR_NOT_FOUND and set \a result to NULL. + + \param[in] parent Parent node. Set to NULL to specify root node. + \param[out] result Receives a held handle to the first child node. + + \see khui_cfg_get_next() + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_first_child(khui_config_node parent, + khui_config_node * result); + +/*! \brief Get a handle to the first subpanel + + If the call is successful, \a result will receieve a handle to the + first subpanel node of the specified node. The returned handle + must be released with a call to khui_cfg_release() + + If \a parent does not have any subpanels, the function will return + KHM_ERROR_NOT_FOUND and set \a result to NULL. + + A subpanel node is a node which has the ::KHUI_CNFLAG_SUBPANEL + flag set. + + \param[in] parent Parent node. Set to NULL to specify root node. + \param[out] result Receives a held handle to the first subpanel node. + + \see khui_cfg_get_next() + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_first_subpanel(khui_config_node vparent, + khui_config_node * result); + +/*! \brief Get a handle to the next sibling node + + If the call is successful, \a result will receive a held handle to + the next sibling node. The returned handle must be released with + a call to khui_cfg_release(). + + If there are no more sibling nodes, then the function return + KHM_ERROR_NOT_FOUND and set \a result to NULL. + + This function can be used to traverse a list of child nodes as + well as a list of subpanel nodes. + + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_next(khui_config_node node, + khui_config_node * result); + +/*! \brief Get a handle to the next sibling node + + Similar to khui_cfg_get_next(), but implicitly releases the handle + that was supplied. Equivalent to doing : + + \code + khui_cfg_get_next(node, &next); + khui_cfg_release(node); + node = next; + \endcode + + \param[in,out] node On entry, specifies the node whose sibling + needs to be fetched. On exit, will have either NULL or a held + handle to the sibling node. The handle which was supplied to + the function is released. + + \retval KHM_ERROR_SUCCESS The next node is now in \a node + \retval KHM_ERROR_INVALID_PARAM \a node was not a valid handle + \retval KHM_ERROR_NOT_FOUND There are no more siblings. \a node + is set to NULL. + + \note Even if there are no more siblings, the handle specified in + \a node on entry is released. + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_next_release(khui_config_node * node); + +/*! \brief Get the name of a configuration node + + Gets the name (not the short description or the long description) + of the given configuration node. +*/ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_name(khui_config_node node, + wchar_t * buf, + khm_size * cb_buf); + +/*! \brief Get registration information for a node + + The registration information that is returned is a shallow copy of + the data kept by NetIDMgr. In particular, the strings that will + be returned actually point to internal buffers and should not be + modified. + + No further action is necessary to release the information. + However, the returned data ceases to be valid when \a node is + released with a call to khui_cfg_release(). + + \param[in] node Node for which information is requested. Can be NULL if requesting information about the root node. + \param[out] reg Pointer to a ::khui_config_node_reg structure. + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_reg(khui_config_node node, + khui_config_node_reg * reg); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP HWND KHMAPI +khui_cfg_get_hwnd_inst(khui_config_node node, + khui_config_node noderef); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP LPARAM KHMAPI +khui_cfg_get_param_inst(khui_config_node node, + khui_config_node noderef); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP void KHMAPI +khui_cfg_set_hwnd_inst(khui_config_node node, + khui_config_node noderef, + HWND hwnd); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP void KHMAPI +khui_cfg_set_param_inst(khui_config_node node, + khui_config_node noderef, + LPARAM param); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP HWND KHMAPI +khui_cfg_get_hwnd(khui_config_node node); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP LPARAM KHMAPI +khui_cfg_get_param(khui_config_node node); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP void KHMAPI +khui_cfg_set_hwnd(khui_config_node node, HWND hwnd); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP void KHMAPI +khui_cfg_set_param(khui_config_node node, LPARAM param); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP void KHMAPI +khui_cfg_clear_params(void); + +/*! \brief Internal use + + This function is used internally by NetIDMgr. Do not use. +*/ +KHMEXP void KHMAPI +khui_cfg_set_configui_handle(HWND hwnd); + +/*! \brief Update the state for the specified node + + \param[in] node ::khui_config_node handle for the configuration node. + + \param[in] flags New flags. Combination of ::KHUI_CNFLAG_APPLIED and ::KHUI_CNFLAG_MODIFIED + + \param[in] mask Valid bits in \a flags + + \note Should only be called from within the dialog procedure for + the configuration node. + */ +KHMEXP void KHMAPI +khui_cfg_set_flags(khui_config_node vnode, khm_int32 flags, khm_int32 mask); + +/*! \brief Retrieve the state flags for the configuration node + + \see khui_cfg_set_flags() + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_flags(khui_config_node vnode); + +/*! \brief Utility function: Initialize dialog box window data + + This function initializes the dialog box window data using the + ::khui_config_init_data that was passed into the WM_INITDIALOG + message. + + A new block of memory will be alocated to store the dialog data as + well as any extra space specified. A pointer to this memory block + will be stored in the \a DWLP_USER slot in the dialog box. + + The allocated block of memory must be freed by a call to + khui_cfg_free_dialog_data(). While handling other messages, the + dialog data can be retrieved using khui_cfg_get_dialog_data(). + + \param[in] hwnd_dlg Handle to the dialog box + + \param[in] data Pointer to the ::khui_config_init_data that was + passed in to WM_INITDIALOG (this is the value of \a lParam) + + \param[in] cb_extra Number of extra bytes to allocate, along with + the space required to store the contents of + ::khui_config_init_data. The extra space will be initialized + to zero. + + \param[out] new_data Receives a pointer to the copy of the + initialization data that was allocated. Optional. Pass in + NULL if this value is not required. + + \param[out] extra Receives a pointer to the block of extra memory + allocated as specified in \a cb_extra. If \a cb_extra is 0, + then this receives a NULL. + + \see khui_cfg_get_dialog_data(), khui_cfg_free_dialog_data() + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_init_dialog_data(HWND hwnd_dlg, + const khui_config_init_data * data, + khm_size cb_extra, + khui_config_init_data ** new_data, + void ** extra); + +/*! \brief Utility function: Retrieves dialog data + + Retrieves the dialog data previoulsy stored using + khui_cfg_init_dialog_data(). + + \param[in] hwnd_dlg Handle to the dialog box + + \param[out] data Receives a pointer to the ::khui_config_init_data + block. + + \param[out] extra Receives a pointer to the extra memory + allocated. Optional (set to NULL if this value is not needed). +*/ +KHMEXP khm_int32 KHMAPI +khui_cfg_get_dialog_data(HWND hwnd_dlg, + khui_config_init_data ** data, + void ** extra); + +/*! \brief Utility function: Free dialog data + + Deallocates the memory allcated in a previous call to + khui_cfg_init_dialog_data() + */ +KHMEXP khm_int32 KHMAPI +khui_cfg_free_dialog_data(HWND hwnd_dlg); + +/*! \brief Sets the instance flags for a subpanel + + Since there can be more than one subpanel in a configuration + panel, they shouldn't modify the flags of the configuration node + directly. Instead, they should call this function to set the + instance flags. + + The instance flags will be merged with the flags for the + configuration node automatically. + */ +KHMEXP void KHMAPI +khui_cfg_set_flags_inst(khui_config_init_data * d, + khm_int32 flags, + khm_int32 mask); + +/*!@} */ +/*!@} */ +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khhtlink.h b/krb5-1-6/src/windows/identity/uilib/khhtlink.h new file mode 100644 index 000000000..be6abb21c --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khhtlink.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHHTLINK_H +#define __KHIMAIRA_KHHTLINK_H + +/*! \addtogroup khui +@{ */ + +/*! \defgroup khui_hyperlink Hyperlink +@{*/ + +/*! \brief A hyperlink + + When a link in a hypertext window is clicked, this structure is + passed along with the message. + + The link text fields do to point to NULL terminated strings. + Instead, the length fields should be used to extract the string. + */ +typedef struct tag_khui_htwnd_link { + RECT r; /*!< The enclosing rectangle of the + hyperlink. Units are screen units + and the coordinates are relative to + the top left hand corner of the + hypertext area. */ + wchar_t * id; /*!< The value of the \a id attribute + of the link or \a NULL if there was + no \a id attribute. This does not + point to a \a NULL terminated + string. The length of the string is + given by the \a id_len field. */ + int id_len; /*!< The length of the string pointed + to by \a id in characters. + Undefined if \a id is \a NULL. */ + wchar_t * param; /*!< The value of the \a param + attribute of the link or \a NULL if + there was no \a param attribute. + This does not point to a \a NULL + terminated string. The length of + the string is given by the \a + param_len field.*/ + int param_len; /*!< Length of the string pointed to + by \a param in characters. + Undefined if \a param is \a NULL. */ +} khui_htwnd_link; + +#define KHUI_MAXCCH_HTLINK_FIELD 256 +#define KHUI_MAXCB_HTLINK_FIELD (KHUI_MAXCCH_HTLINK_FIELD * sizeof(wchar_t)) + +/*!@}*/ +/*!@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khnewcred.h b/krb5-1-6/src/windows/identity/uilib/khnewcred.h new file mode 100644 index 000000000..db70b41f8 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khnewcred.h @@ -0,0 +1,1132 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHNEWCRED_H +#define __KHIMAIRA_KHNEWCRED_H + +/******************************************************************** + New credentials windows +*********************************************************************/ + +/*! \addtogroup khui +@{ */ + +/*! \defgroup khui_cred Credentials acquisition + + Declarations associated with credentials acquisition. + +@{ */ + +/*! \brief Window message sent to credentials type panels + + This message is sent to the child windows. + + The format of the message is : + - uMsg : KHUI_WM_NC_NOTIFY + - HIWORD(wParam) : one of ::khui_wm_nc_notifications + - LPARAM : pointer to the ::khui_new_creds structure (except where noted) +*/ +#define KHUI_WM_NC_NOTIFY (WM_APP + 0x101) + +/*! \brief The first control ID that may be used by an identity provider */ +#define KHUI_CW_ID_MIN 8016 + +/*! \brief The maximum number of controls that may be created by an identity provider*/ +#define KHUI_CW_MAX_CTRLS 8 + +/*! \brief The maximum control ID that may be used by an identity provider */ +#define KHUI_CW_ID_MAX (KHUI_CW_ID_MIN + KHUI_CW_MAX_CTRLS - 1) + + +/*! \brief Credentials dialog notifications + + These notifications will be sent to the individual dialog + procedures of the credential type panels or to the new credentials + window as a ::KHUI_WM_NC_NOTIFY message. +*/ +enum khui_wm_nc_notifications { + WMNC_DIALOG_EXPAND = 1, + /*!< The dialog is switching from basic to advanced mode or vice + versa. + + In expanded mode, all credentials type panels are visible as + opposed to the compressed mode where they are not visible. The + message is not sent to credentials type panels. + + Only sent to the new credentials window. + */ + + WMNC_DIALOG_SETUP, + /*!< Sent to the new creds window to notify it that the dialog + should create all the type configuration panels. + + Until this message is issued, none of the credentials type + panels exist. The credentials type panels will receive + WM_INITDIALOG etc as per the normal dialog creation process. + + Only sent to the new credentials window. + */ + + WMNC_DIALOG_ACTIVATE, + /*!< Sent to the new creds window to notify it that the dialog + should do final initialization work and activate. + + Only sent to the new credentials window. + */ + + WMNC_DIALOG_MOVE, + /*!< The new credentials window has moved. + + This message is sent to all the credentials type panels when the + new credentials window is being moved. It will be sent + continuously if the user is dragging the window. Plug-ins + rarely need to know their position on the screen. However, if + there are any other windows that were created by the plug-in, + such as floating controls or tooltips, they may need to be + repositioned in response to this message. + + Sent to all the credentials type panels. + */ + + WMNC_DIALOG_SWITCH_PANEL, + /*!< Sent to the new creds window to cause it to switch to the + panel identified by LOWORD(wParam). + + Does nothing if the specified panel is already the current + panel. If the dialog is in compact mode and making the + specified panel visible requires switching to expanded mode, the + dialog will do so. + + Only sent to the new credentials window. + */ + + WMNC_UPDATE_CREDTEXT, + /*!< Update the credentials text associated with a panel. + + During the new credentials operation, each plug-in is expected + to maintain a textual representation of the credentials that the + plug-in expects to obtain for the selected identity. It can, + alternatively, be used to indicate the state of the credentials + type in respect to the selected identity (for example, whether + the credentials type is disabled for the identity and why). + + This text is not visible when the new credentials window is in + basic mode, but it is visible when the window is in advanced + mode. The following image shows the expanded new credentials + window including the credentials text from a several plug-ins: + + \image html new_creds_expanded.png + + Once this message is received, each plug-in should construct its + credentials text string and store it in the \c credtext member + of its ::khui_new_creds_by_type structure as shown in the sample + code below: + + \code + // Handler for window message WM_NC_NOTIFY with + // HWND hwnd, WPARAM wParam and LPARAM lParam + + // This structure holds the dialog data for the panel. We + // assume it has 'nc' and 'nct' fields that point to the + // khui_new_creds and khui_new_creds_by_type structures + // respectively. + + ... + struct nc_dialog_data * d; + ... + + // Retrieve the data structure from the dialog user data. + d = (struct nc_dialog_data *) GetWindowLongPtr(hwnd, DWLP_USER); + + switch (HIWORD(wParam)) { + case WMNC_UPDATE_CREDTEXT: + { + wchar_t buffer[KHUI_MAXCCH_LONG_DESC]; + size_t cb_size; + + // we are being requested to update the credentials text. We + // already allocated a buffer when we created the nct + // structure. So we can just set the text here. + + // The credentials text should reflect the credentials that + // will be obtained when the new credentials operation + // completes. + + assert(d && d->nc && d->nct); + + if (d->nct->credtext) { + free(d->nct->credtext); + d->nct->credtext = NULL; + } + + // We only display something if there is a selected identity + if (d->nc->n_identities > 0) { + StringCbPrintf(buffer, sizeof(buffer), + L"<p>My Credentials<tab>: %s</p>", + get_credential_name(d)); + StringCbLength(buffer, sizeof(buffer), &cb_size); + cb_size += sizeof(wchar_t); // account for the terminating NULL + + d->nct->credtext = malloc(cb_size); + if (d->nct->credtext) { + StringCbCopy(d->nct->credtext, cb_size, buffer); + } + } + + break; + } + + ... // Handler other notifications + } + \endcode + + The text that is specified as the credentials text is formatted + hypertext. For more information about support for formatting + and hypertext and handling hyperlinks, see \ref khui_htwnd. + + \note When this message is sent to the new credentials window, + the application will send the ::WMNC_UPDATE_CREDTEXT message to + all the credential type panels and update the credential text + window. */ + + WMNC_CREDTEXT_LINK, + /*!< A hyperlink was activated. + + Sent to a panel dialog procedure when a user clicks an embedded + link in the credentials text that belongs to that panel. The \a + lParam parameter of the message is a pointer to a + ::khui_htwnd_link structure describing the link. + + \see \ref khui_htwnd + + \note The \a lParam parameter does not point to a + ::khui_new_creds structure for this message. + */ + + WMNC_IDENTITY_CHANGE, + /*!< The primary identity has changed. + + The ::khui_new_creds structure contains a list of identities to + which the current operation should be applied. In its current + implementation, only the first identity in this list is used. + Therefore, the list will contain at most one identity. It is + possible for the list to be empty (for example, if the user + hasn't selected an identity yet). + + When handling this notification, the plug-in should check the \c + n_identities member of the ::khui_new_creds structure to see + whether there are any identities selected. This value would be + either zero or one. If it is non-zero, then a handle to the + selected identity will be in \c khui_new_creds::identities[0]. + + Plug-ins typically use this notfication to load identity + specific settings when a new identity is selected. + + This notification is sent to all the credentials type panels. + */ + + WMNC_CLEAR_PROMPTS, + /*!< Sent to the new creds window to clear any custom prompts. + + Only sent to the new credentials window. + */ + + WMNC_SET_PROMPTS, + /*!< Sent to the new creds window to set custom prompts. + + Only sent to the new credentials window. */ + + WMNC_DIALOG_PREPROCESS, + /*!< The credentials acquisition process is about to start. + + Sent to all the credentials type panels to notify them that the + credentials acquisition process will start. Once all plug-ins + have handled the notification, the application will start + sending out <::KMSG_CRED, ::KMSG_CRED_PROCESS> messages to the + credentials providers which are participating in the new + credentials operation. + */ + + WMNC_DIALOG_PROCESS, + /*!< This notification is no longer used. */ +#pragma deprecated(WMNC_DIALOG_PROCESS) + + WMNC_DIALOG_PROCESS_COMPLETE, + /*!< Sent to the new creds window to indicate that the all the + threads have completed processing.*/ + + WMNC_TYPE_STATE, + /*!< Sent to the new creds window as notification that a + particular credentials type has changed state from enabled to + disabled or vice versa. The LPARAM member of the message + specifies the credentials type identifier for the changed + type */ + + WMNC_ADD_CONTROL_ROW, + /*!< Add a row of controls to a new cred dialog. This is an + internal message. */ + + WMNC_UPDATE_LAYOUT, + /*!< Update the layout of a dialog or window. This is an internal + message. */ +}; + +/*! \brief Plugins can use WMNC_NOTIFY message codes from here on up + + \see ::KHUI_WM_NC_NOTIFY + */ +#define WMNC_USER 2048 + +/*! \brief Notifications to the identity provider + + These notifications are sent through to the identity provider's UI + callback that was obtained using a ::KMSG_IDENT_GET_UI_CB message. + + The callback routine is called from the context of the UI thread + and is expected to not make any blocking calls. One of the + following commands will be passed in as the \a cmd parameter to + the callback. + */ +enum khui_wm_nc_ident_notify { + WMNC_IDENT_INIT, + /*!< Initialize an identity selector for a new credentials + dialog. The \a lParam parameter contains a handle to the + dialog window which will contain the identity selector + controls. The identity provider may make use of the \a + ident_aux field of the ::khui_new_creds structure to hold any + data pertaining to the credentials acquisition dialog.*/ + + WMNC_IDENT_WMSG, + /*!< Windows message. Presumably sent from one of the controls + that was created by the identity provider. The callback is + expected to return TRUE if it processed the message or FALSE + if it did not. The \a uMsg, \a wParam and \a lParam + parameters are set to the values passed in by Windows. */ + + WMNC_IDENT_EXIT, + /*!< Terminate a credentials acquisition dialog. Sent just before + the dialog is terminated. */ + + WMNC_IDENT_PREPROCESS, + /*!< The identity is about to be fetched from the \a + ::khui_new_creds structure. The callback is expected to ensure + that the primary identity listed in that structure is + consistent with the user selection. */ +}; + +/*! \name Standard credtext link IDs +@{*/ + +/*! \brief Switch the panel + + The \a id attribute of the link specifies the ordinal of the panel + to switch to. +*/ +#define CTLINKID_SWITCH_PANEL L"SwitchPanel" + +/*@}*/ + +/*forward dcl*/ +struct tag_khui_new_creds_by_type; +typedef struct tag_khui_new_creds_by_type khui_new_creds_by_type; +struct tag_khui_new_creds_prompt; +typedef struct tag_khui_new_creds_prompt khui_new_creds_prompt; +struct tag_khui_new_creds; +typedef struct tag_khui_new_creds khui_new_creds; + +typedef LRESULT +(KHMAPI *khui_ident_new_creds_cb)(khui_new_creds * nc, + UINT cmd, + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +/*! \brief New credentials acquisition blob + + A pointer to an object of this type is passed in along with the + credentials acquisition messages. + + \see \ref cred_acq for more information +*/ +typedef struct tag_khui_new_creds { + khm_int32 magic; /*!< Internal use */ + + khm_int32 subtype; /*!< Subtype of the request that is + being handled through this object. + One of ::KMSG_CRED_NEW_CREDS, + ::KMSG_CRED_RENEW_CREDS or + ::KMSG_CRED_PASSWORD */ + + CRITICAL_SECTION cs; /*!< Internal use */ + + khm_boolean set_default; /*!< After a successfull credentials + acquisition, set the primary + identity as the default. */ + + khm_handle *identities; /*!< The list of identities associated + with this request. The first + identity in this list (\a + identities[0]) is the primary + identity. */ + + khm_size n_identities; /*!< Number of identities in the list + \a identities */ + + khm_size nc_identities; /*!< Internal use */ + + khui_action_context ctx; /*!< An action context specifying the + context in which the credentials + acquisition operation was + launced. */ + + khm_int32 mode; /*!< The mode of the user interface. + One of ::KHUI_NC_MODE_MINI or + ::KHUI_NC_MODE_EXPANDED. */ + + HWND hwnd; /*!< Handle to the new credentials + window. */ + + struct tag_khui_new_creds_by_type **types; + /*!< Internal use */ + khm_handle *type_subs; /*!< Internal use */ + khm_size n_types; /*!< Internal use */ + khm_size nc_types; /*!< Internal use */ + + khm_int32 result; /*!< One of ::KHUI_NC_RESULT_CANCEL or + ::KHUI_NC_RESULT_PROCESS indicating + the result of the dialog with the + user */ + + khm_int32 response; /*!< Response. See individual message + documentation for info on what to do + with this field */ + + wchar_t *password; /*!< Not used. */ + + /* UI stuff */ + + wchar_t *banner; /*!< Internal use */ + wchar_t *pname; /*!< Internal use */ + khm_size n_prompts; /*!< Internal use */ + khm_size nc_prompts; /*!< Internal use */ + struct tag_khui_new_creds_prompt ** prompts; /*!< Internal use */ + + khui_ident_new_creds_cb ident_cb; /*!< Internal use */ + + wchar_t *window_title; /*!< Internal use */ + + LPARAM ident_aux; /*!< Auxilliary field which is + reserved for use by the identity + provider during the course of + conducting this dialog. */ + +} khui_new_creds; + +#define KHUI_NC_MAGIC 0x84270427 + +/*!\name Result values for khui_new_creds_t::result + @{*/ +#define KHUI_NC_RESULT_PROCESS 0 +#define KHUI_NC_RESULT_CANCEL 1 +/*@}*/ + +/*!\name Mode values for khui_new_creds_t::mode + @{*/ +#define KHUI_NC_MODE_MINI 0 +#define KHUI_NC_MODE_EXPANDED 1 +/*@}*/ + +/*!\name Response values for khui_new_creds_t::response + @{*/ +/*!\brief No known response */ +#define KHUI_NC_RESPONSE_NONE 0 + +/*!\brief It is okay to exit the dialog now + + This is the default, which is why it has a value of zero. In + order to prevent the dialog from exiting, set the + KHUI_NC_RESPONSE_NOEXIT response bit. */ +#define KHUI_NC_RESPONSE_EXIT 0 + +/*!\brief It is NOT okay to exit the dialog now + + Used to indicate that further user-interaction is necessary to + process the dialog. Usually this is accompanied by setting + necessary custom prompts and notifications so the user knows why + the dialog is prompting for more information. + */ +#define KHUI_NC_RESPONSE_NOEXIT 0x00000002 + +/*!\brief The dialog was processed successfully + + Since this is the default response, the value is zero. Use one of + KHUI_NC_RESPONSE_FAILED or KHUI_NC_RESPONSE_PENDING to indicate an + error or pending status. + */ +#define KHUI_NC_RESPONSE_SUCCESS 0 + +/*!\brief The processing of the dialog failed + + Self explanatory. More information about the failure should have + been reported using the khlog API, however, this response value + indicates to other credential types that depend on this credential + type that whatever it was that this credential type was supposed + to do didn't happen. +*/ +#define KHUI_NC_RESPONSE_FAILED 0x00000008 + +/*!\brief Further interaction required + + Set along with KHUI_NC_RESPONSE_NOEXIT although it is not + required. Setting this bit will automatically add the + KHUI_NC_RESPONSE_NOEXIT. + + If this bit is set, all dependent plugins will be set on hold + until another round of processing clears the pending bit. + */ +#define KHUI_NC_RESPONSE_PENDING 0x00000010 + +/*! \brief Completed + + This is automatically set if the plugin sets a response which does + not indicate either KHUI_NC_RESPONSE_NOEXIT or + KHUI_NC_RESPONSE_PENDING, which is considered to mean that the + plugin is completed processing. + + This flag cannot be explicitly specified in a response. + */ +#define KHUI_NC_RESPONSE_COMPLETED 0x00000020 + +/*! \brief Processing + + This is an internal flag set while the credentials acquisition + process is executing. + */ +#define KHUI_NC_RESPONSE_PROCESSING 0x00010000 + +#define KHUI_NCMASK_RESPONSE (KHUI_NC_RESPONSE_EXIT|KHUI_NC_RESPONSE_NOEXIT) +#define KHUI_NCMASK_RESULT (KHUI_NC_RESPONSE_SUCCESS|KHUI_NC_RESPONSE_FAILED|KHUI_NC_RESPONSE_PENDING) +/*@}*/ + +/*!\brief Maximum number of dependencies for a credentials type */ +#define KHUI_MAX_TYPE_DEPS 8 + +/*!\brief Maximum number of credential types for a new creds window */ +#define KHUI_MAX_NCTYPES 16 + +/*!\brief Maximum number of characters in a password + + Length includes the termininating NULL +*/ +#define KHUI_MAXCCH_PASSWORD 512 + +/*! \brief Maximum number of bytes in a password + + Includes terminating NULL +*/ +#define KHUI_MAXCB_PASSWORD (KHUI_MAXCCH_PASSWORD * sizeof(wchar_t)) + +/*! \brief Maximum number of characters in a custom banner + + Length includes terminating NULL +*/ +#define KHUI_MAXCCH_BANNER 256 + + +/*! \brief Maximum number of bytes in a custom banner + + Length includes terminating NULL +*/ +#define KHUI_MAXCB_BANNER (KHUI_MAXCCH_BANNER * sizeof(wchar_t)) + +/*! \brief Maximum number of characters in a panel name + + Length includes terminating NULL +*/ +#define KHUI_MAXCCH_PNAME 256 + +/*! \brief Maximum number of bytes in a panel name + + Length includes terminating NULL +*/ +#define KHUI_MAXCB_PNAME (KHUI_MAXCCH_PNAME * sizeof(wchar_t)) + +/*! \brief A descriptor of a panel in the new credentials acquisition tab + + When processing certain credentials messages such as + ::KMSG_CRED_PASSWORD, ::KMSG_CRED_NEW_CREDS, + ::KMSG_CRED_RENEW_CREDS, a pointer to a ::khui_new_creds structure + will be passed in to the message handler. If the handler of the + message needs to add one or more credentials types as participants + of the operation, the handler will need to call khui_cw_add_type() + and specify a ::khui_new_creds_by_type structure. + + Note that the memory address passed in to the call to + khui_cw_add_type() will not be copied. Therefore, the block of + memory should remain as-is for the lifetime of the + ::khui_new_creds structure or until it is removed with a call to + khui_cw_del_type(). + + Some of the credentials messages that require specifying a + ::khui_new_creds_by_type structure require providing a + user-interface. In these cases, the fields marked for providing a + UI may be required to hold valid values. If the message does not + require providing a UI, these fields will be ignored. +*/ +typedef struct tag_khui_new_creds_by_type { + khui_new_creds * nc; /*!< Internal use. Do not set */ + khm_int32 flags; /*!< Internal use. Do not set */ + + khm_int32 type; /*!< The identifier of the credentials + type. This is a credentials type + identifier allocated with a call to + kcdb_credtype_register(). */ + + khm_int32 type_deps[KHUI_MAX_TYPE_DEPS]; + /*!< credentials types that this + credential type depends on. Each + element defines a credentials type + identifier that this type depends + on for this operation. The number + of valid values in this array + should be specified in the \a + n_type_deps field. */ + + khm_size n_type_deps; /*!< Number of dependencies listed + above. Should be between 0 and + ::KHUI_MAX_TYPE_DEPS. Specify 0 if + there are no dependencies. */ + + khm_size ordinal; /*!< The requested ordinal. The UI + would attempt to place this panel at + the reqested order in the list of + panels. Set to -1 if the order does + not matter. Once the dialog is + activated this field will be updated + to reflect the actual ordinal of the + panel. */ + + wchar_t *name; /*!< Name of the panel (localized, + optional). If NULL, the localized + name of the credentials type is + used. Only used if providing a + user-interface. */ + + HICON icon; /*!< Icon for the panel (optional). + Only used if providing a + user-interface. */ + + wchar_t *tooltip; /*!< Tooltip for the panel (localized, + optional). If NULL, no tooltip will + be assigned for the panel. Only + used if providing a + user-interface. */ + + HMODULE h_module; /*!< Handle to the module containing + the dialog resource. Only used if + providing a user-interface. */ + + LPWSTR dlg_template; /*!< The dialog resource. Only used + if providing a user-interface. */ + DLGPROC dlg_proc; /*!< The dialog procedure. Only used + if providing a user-interface. */ + + HWND hwnd_panel; /*!< The dialog window. Once the + dialog panel is created, a handle to + the panel will be assigned here. + Note that the handle is assigned + after a successful call to + CreateDialogParam and hence would + not be available when handling the + WM_INITDIALOG message from the + dialog procedure. Only used of + providing a user-interface. */ + + HWND hwnd_tc; /*!< Internal use. Do not set */ + + wchar_t *credtext; /*!< A brief description of the + current state of this cred + type. (localized, optional). Only + used if providing a + user-interface. If this field is + non-NULL, then it should point to a + NULL terminated string that does not + exceed ::KHUI_MAXCCH_LONG_DESC + characters in length including the + terminating NULL. + + \see \ref khui_htwnd for information + on how to format the string for this + field. + */ + + LPARAM aux; /*!< auxilliary field. For use by the + plug-in. */ +} khui_new_creds_by_type; + +/*!\name Flags for khui_new_creds_by_type + + Note that KHUI_NC_RESPONSE_SUCCESS, KHUI_NC_RESPONSE_FAILED, + KHUI_NC_RESPONSE_PENDING are also stored in the flags. + +@{*/ +#define KHUI_NCT_FLAG_PROCESSED 1024 +#define KHUI_NCT_FLAG_DISABLED 2048 +/*@}*/ + +/*! \brief Width of a new creds dialog panel in dialog units*/ +#define NCDLG_WIDTH 300 +/*! \brief Height of a new creds dialog panel in dialog units*/ +#define NCDLG_HEIGHT 166 + +/*! \brief A custom prompt */ +typedef struct tag_khui_new_creds_prompt { + khm_size index; /*!< Set to the zero based index + of this prompt. */ + + khm_int32 type; /*!< one of KHUI_NCPROMPT_TYPE_* */ + wchar_t * prompt; /*!< prompt string. Cannot exceed + KHUI_MAXCCH_PROMPT */ + wchar_t * def; /*!< default value. Cannot exceed + KHUI_MAXCCH_PROMPT_VALUE */ + wchar_t * value; /*!< On completion, this is set to the + value that the user entered. Will + not exceed + KHUI_MAXCCH_PROMPT_VALUE */ + + khm_int32 flags; /*!< Combination of + KHUI_NCPROMPT_FLAG_* */ + + HWND hwnd_static; /* internal use */ + HWND hwnd_edit; /* internal use */ +} khui_new_creds_prompt; + +/*! \brief The prompt input is hidden + + The input is hidden for prompts which accept passwords. The + control which represents the input will display an asterisk or a + small circle corresponding to each character typed in, but will + not show the actual character. + */ +#define KHUI_NCPROMPT_FLAG_HIDDEN 1 + +/*! \brief Internal use */ +#define KHUI_NCPROMPT_FLAG_STOCK 2 + +/*! \brief Maximum number of characters in a prompt + + Refers to the prompt text that accompanies an input control. THe + length includes the terminating NULL. + */ +#define KHUI_MAXCCH_PROMPT 256 + +/*! \brief Maximum number of bytes in a prompt + + Refers to the prompt text that accompanies an input control. THe + length includes the terminating NULL. + */ +#define KHUI_MAXCB_PROMPT (KHUI_MAXCCH_PROMPT * sizeof(wchar_t)) + +/*! \brief Maximum number of characters that can be entered in an input control + + Refers to the input control of a prompt. The length includes the + terminating NULL. + */ +#define KHUI_MAXCCH_PROMPT_VALUE 256 + +/*! \brief Maximum number of bytes that can be entered in an input control + + Refers to the input control of a prompt. The length includes the + terminating NULL. + */ +#define KHUI_MAXCB_PROMPT_VALUE (KHUI_MAXCCH_PROMPT_VALUE * sizeof(wchar_t)) + +/* from krb5.h. Redefining here because we don't want to depend on + krb5.h for all credential types */ + +/*! \brief A password control */ +#define KHUI_NCPROMPT_TYPE_PASSWORD 1 + +/*! \brief New password control + + Used when changing the password + */ +#define KHUI_NCPROMPT_TYPE_NEW_PASSWORD 2 + +/*! \brief New password again control + + Used when changing the password + */ +#define KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN 3 + +/*! \brief Preauthentication (reserved) */ +#define KHUI_NCPROMPT_TYPE_PREAUTH 4 + +/*! \brief Control sizes */ +typedef enum tag_khui_control_size { + KHUI_CTRLSIZE_SMALL, + /*!< A small control fits in about 1/5 the width of the new + credentials panel */ + KHUI_CTRLSIZE_HALF, + /*!< Half size controls fit in 1/2 the width of the new + credentials panel */ + KHUI_CTRLSIZE_FULL, + /*!< Takes up the whole width of the crednetials panel */ +} khui_control_size; + +/*! \brief Internal use */ +typedef struct tag_khui_control_row { + HWND label; + HWND input; + khui_control_size size; +} khui_control_row; + +/*! \brief Create a ::khui_new_creds object + + Creates and initializes a ::khui_new_creds object. The created + object must be destroyed using the khui_cw_destroy_cred_blob() + function. + + \note Plugins should not call this function directly. The + necessary ::khui_new_creds objects will be created by + NetIDMgr. + + \see khui_cw_destroy_cred_blob() + */ +KHMEXP khm_int32 KHMAPI +khui_cw_create_cred_blob(khui_new_creds ** c); + +/*! \brief Destroy a ::khui_new_creds object + + Destroys a ::khui_new_creds object that was fomerly created using + a call to khui_cw_create_cred_blob(). + + \note Plugins should not call this function directly. The + necessary ::khui_new_creds objects will be created by + NetIDMgr. + + \see khui_cw_create_cred_blob() +*/ +KHMEXP khm_int32 KHMAPI +khui_cw_destroy_cred_blob(khui_new_creds *c); + +/*! \brief Lock the new_creds object + + When a plugin is accessing the fields of a ::khui_new_creds + object, it must first obtain a lock on the object so that other + threads will not modify the fields at the same time. Locking the + object ensures that the fields of the object will be consistent. + + Use khui_cw_unlock_nc() to undo the lock obtained through a call + to khui_cw_lock_nc(). + + It is not necessary to lock a new credentials object when + modifying it using the NetIDMgr API. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_lock_nc(khui_new_creds * c); + +/*! \brief Unlock a new_creds object + + \see khui_cw_lock_nc() + */ +KHMEXP khm_int32 KHMAPI +khui_cw_unlock_nc(khui_new_creds * c); + +/*! \brief Add a new panel to a new credentials acquisition window + + See the description of ::khui_new_cred_panel for information on + how to populate it to describe a credentials type panel. + + Note that the structure pointed to by \a t is added by reference. + The memory pointed to by \a t is not copied. Hence, the block of + memory and any other blocks pointed to by the + ::khui_new_creds_by_type structure located there should remain + intact for the lifetime of the ::khui_new_creds structure pointed + to by \a c or until the credentials type panel is removed from the + ::khui_new_creds structure with a call to khui_cw_del_type(). + + Generally, a plug-in that calls this function should allocate a + block of memory to contain the ::khui_new_creds_by_type structure, + fill it in and then pass in the address in a call to + khui_cw_add_type() while handling a ::KMSG_CRED_PASSWORD, + ::KMSG_CRED_NEW_CREDS or ::KMSG_CRED_RENEW_CREDS message. Then + the plug-in should remove the reference with a call to + khui_cw_del_type() while processing ::KMSG_CRED_END. + + \see khui_cw_del_type() + \see \ref cred_acq_panel_spec + \see ::khui_new_cred_panel + \see ::khui_new_creds +*/ +KHMEXP khm_int32 KHMAPI +khui_cw_add_type(khui_new_creds * c, + khui_new_creds_by_type * t); + +/*! \brief Remove a panel from a new credentials acquisition window + + \see khui_cw_add_type() + */ +KHMEXP khm_int32 KHMAPI +khui_cw_del_type(khui_new_creds * c, + khm_int32 type); + +/*! \brief Find the panel belonging to a particular credentials type + + This panel would have been added to the new credentials window + using khui_cw_add_type(). + + \see khui_cw_add_type() + */ +KHMEXP khm_int32 KHMAPI +khui_cw_find_type(khui_new_creds * c, + khm_int32 type, + khui_new_creds_by_type **t); + +/*! \brief Enable/disable a particular credentials type + + Enables or disables the panel associated with a particular + credentials type. Does not preclude the credentials type from + participating in the new credentials acquisition. However, the + user will be prevented from interacting with the specific panel. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_enable_type(khui_new_creds * c, + khm_int32 type, + khm_boolean enable); + +/*! \brief Set the primary identity in a new credentials acuisition + + The primary identity dictates many of the defaults and the + semantics associated with the credentials acquision process. + Setting the primary identity also triggers the + ::WMNC_IDENTITY_CHANGE notification which will be sent to all the + credentials type panels. + + Has no effect if the primary identity is already the same as the + one specified in \a id. Specify NULL for \a id if the current + primary identity is to be cleared. + + If the primary identity is changed, then all the additional + identities associated with the new credentials acquisition dialog + will also be discarded. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_set_primary_id(khui_new_creds * c, + khm_handle id); + +/*! \brief Add an additional identity to the new credentials acquisition + + Individual plugins are free to decide how to handle additional + identities. Generally, they would attempt to obtain credentials + for the primary and additional identities, but would not consider + it an error if an additional identity failed to obtain + credentials. + + Calling this function with \a id of NULL does nothing. +*/ +KHMEXP khm_int32 KHMAPI +khui_cw_add_identity(khui_new_creds * c, + khm_handle id); + +/*! \brief Clear all custom prompts + + Removes all the custom prompts from the new credentials dialog. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_clear_prompts(khui_new_creds * c); + +/*! \brief Synchronize custom prompt values + + It is important to synchronize the values before accessing their + values. The controls associated with custom prompts update the + values in the ::khui_new_creds object periodically. However, the + values may lose sync intermittently. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_sync_prompt_values(khui_new_creds * c); + +/*! \brief Begin custom prompting + + Begins the process of defining custom prompts. Implicity removes + all the custom prompts that are currently being displayed. The \a + banner and \a name will be displayed in separate controls above + the set of new custom prompts. + + The controls associated with the prompts will not actually be + created until all the prompts have been added using + khui_cw_add_prompt(). The number of promtps that can be added + will be exactly \a n_prompts. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_begin_custom_prompts(khui_new_creds * c, + khm_size n_prompts, + wchar_t * banner, + wchar_t * name); + +/*! \brief Add a custom prompt + + After khui_cw_begin_custom_prompts() is called, the plugin should + call khui_cw_add_prompt() to add the actual prompts. The number + of prompts that can be added is the \a n_prompts value specified + in the earlier call to \a khui_cw_begin_custom_prompts(). + + Once \a n_prompts prompts have been added, the new prompts will + automatically be created and shown in the user interface. + However, if less than that prompts are added, nothing is displayed + to the user. + + \param[in] c Pointer to ::khui_new_creds structure + + \param[in] type Type of prompt. One of + ::KHUI_NCPROMPT_TYPE_PREAUTH, ::KHUI_NCPROMPT_TYPE_PASSWORD, + ::KHUI_NCPROMPT_TYPE_NEW_PASSWORD, + ::KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN + + \param[in] prompt Text of the prompt. Constrained by + ::KHUI_MAXCCH_PROMPT. (Localized, required) + + \param[in] def Default value. (optional). Constrained by + ::KHUI_MAXCCH_PROMPT_VALUE. Set to NULL if not provided. + + \param[in] flags Flags. Combination of + ::KHUI_NCPROMPT_FLAG_HIDDEN + */ +KHMEXP khm_int32 KHMAPI +khui_cw_add_prompt(khui_new_creds * c, + khm_int32 type, + wchar_t * prompt, + wchar_t * def, + khm_int32 flags); + +/*! \brief Retrieve a custom prompt + + Retrieves an individual prompt. The \a idx parameter is a + zero-based index of the prompt to retrieve. The ordering is the + same as the order in which khui_cw_add_prompt() was called. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_get_prompt(khui_new_creds * c, + khm_size idx, + khui_new_creds_prompt ** prompt); + +/*! \brief Get the number of custom prompts + + Retrieves the number of custom prompts currently displayed. If + this function is called between calling + khui_cw_begin_custom_prompts() and adding all the prompts, the + number returned will be the number of prompts that is expected to + be registered (i.e. the \a n_prompts parameter passed to + khui_cw_begin_custom_prompts()). + */ +KHMEXP khm_int32 KHMAPI +khui_cw_get_prompt_count(khui_new_creds * c, + khm_size * np); + + +/*! \brief Get the value of a custom prompt + + Retrieve the value of a specific prompt. The value is the string + that was typed into the input control associated with a custom + prompt. The \a idx parameter is the zero-based index of the + prompt from which to retrieve the value from. The ordering is the + same as the order in which khui_cw_add_prompt() was called. + + It is important to call khui_cw_sync_prompt_values() before + starting to call khui_cw_get_prompt_value() so that the values + returned are up-to-date. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_get_prompt_value(khui_new_creds * c, + khm_size idx, + wchar_t * buf, + khm_size *cbbuf); + +/*! \brief Set the response for a plugin + + When handling ::KMSG_CRED_DIALOG_PROCESS from within the plugin + thread, it is important to set the response by calling this + function. The response can be used to signal whether the plugin + successfully obtained credentials or whether further interaction + is required, or the credentials acquisition failed. + + The response is a combination of : + - ::KHUI_NC_RESPONSE_PENDING + - ::KHUI_NC_RESPONSE_FAILED + - ::KHUI_NC_RESPONSE_PENDING + - ::KHUI_NC_RESPONSE_SUCCESS + - ::KHUI_NC_RESPONSE_NOEXIT + - ::KHUI_NC_RESPONSE_EXIT + */ +KHMEXP khm_int32 KHMAPI +khui_cw_set_response(khui_new_creds * c, + khm_int32 type, + khm_int32 response); + +/*! \brief Check whether a specified credential type panel succeeded + + This is called during the processing of ::KMSG_CRED_DIALOG_PROCESS + to determine whether a specified credential type succeeded in + obtaining credentials. The credential type that is being queried + should have also been listed as a dependency when adding the + current credentials type, otherwise the type queried may not have + been invoked yet. + + \return TRUE iff the queried type has reported that it successfully + completed the credentials acquision operation. + */ +KHMEXP khm_boolean KHMAPI +khui_cw_type_succeeded(khui_new_creds * c, + khm_int32 type); + +/*! \brief Add a row of controls to the identity specifier area + + Only for use by identity provider callbacks that wish to add an + identity selector control. A row of controls consist of a label + control and some input control. + + When the ::WMNC_IDENT_INIT message is sent to the identity + provider, it receives a handle to the dialog panel in the \a + lParam parameter which should be the parent window of both the + windows specified here. The control ID for any controls created + must fall within the ::KHUI_CW_ID_MIN and ::KHUI_CW_ID_MAX range. + + Both controls will be resized to fit in the row. + + If \a long_label is TRUE then the size of the label will be larger + than normal and will accomodate more text. + */ +KHMEXP khm_int32 KHMAPI +khui_cw_add_control_row(khui_new_creds * c, + HWND label, + HWND input, + khui_control_size size); + +/*!@}*/ /* Credentials acquisition */ +/*!@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khprops.h b/krb5-1-6/src/windows/identity/uilib/khprops.h new file mode 100644 index 000000000..a00c65f7f --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khprops.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHPROPS_H +#define __KHIMAIRA_KHPROPS_H + +#include<prsht.h> + +/********************************************************************* + Property sheets +**********************************************************************/ + +/*! \addtogroup khui + +@{*/ + +/*!\defgroup khui_pp Property sheets +@{*/ + +/* forward dcl */ +struct tag_khui_property_page; + +/*! \brief A property sheet + */ +typedef struct tag_khui_property_sheet { + PROPSHEETHEADER header; /*!< property sheet header */ + khm_int32 status; /*!< status of property sheet. One of + ::KHUI_PS_STATUS_NONE, + ::KHUI_PS_STATUS_RUNNING or + ::KHUI_PS_STATUS_DONE */ + + HWND hwnd; /*!< handle to the property sheet window. + Only valid when \a status is NOT + ::KHUI_PS_STATUS_NONE */ + + HWND hwnd_page; /*!< handle to the current page in the + property sheet. Only valid when \a + status is ::KHUI_PS_STATUS_RUNNING */ + + khui_action_context ctx; /*!< Context for the property sheet. See + documentation for + ::khui_action_context */ + + khm_handle identity; /*!< Handle to the associated identity, + if applicable */ + khm_int32 credtype; /*!< Type ID of the credentials type, if + applicable */ + khm_handle cred; /*!< Handle to the associated credential, + if applicable */ + + khm_int32 n_pages; /*!< Number of property pages. + Upperbound of ::KHUI_PS_MAX_PSP */ + + QDCL(struct tag_khui_property_page); +} khui_property_sheet; + +/*! \brief The property sheet hasn't been created yet */ +#define KHUI_PS_STATUS_NONE 0 + +/*! \brief The property sheet is visible and running */ +#define KHUI_PS_STATUS_RUNNING 1 + +/*! \brief The property sheet has completed running. + + At this point, it is safe to call khui_ps_destroy_sheet() to + destroy the property sheet. +*/ +#define KHUI_PS_STATUS_DONE 2 + +/*! \brief The property sheet is in the process of being destroyed + */ +#define KHUI_PS_STATUS_DESTROY 3 + +/*! \brief Maximum number of property sheet pages in a property sheet */ +#define KHUI_PS_MAX_PSP 16 + + +/*! \brief A property sheet page + */ +typedef struct tag_khui_property_page { + HPROPSHEETPAGE h_page; + LPPROPSHEETPAGE p_page; + HWND hwnd; + khm_int32 credtype; + khm_int32 ordinal; + + LDCL(struct tag_khui_property_page); +} khui_property_page; + +/*! \brief Special pseudo credtype for identity page + */ +#define KHUI_PPCT_IDENTITY (-8) + +/*! \brief Special pseudo credtype for credential page + */ +#define KHUI_PPCT_CREDENTIAL (-9) + +/*! \brief Create a property sheet + + \note Only called by the NetIDMgr application. + */ +KHMEXP khm_int32 KHMAPI +khui_ps_create_sheet(khui_property_sheet ** sheet); + +/*! \brief Add a page to a property sheet + + Called by a plugin or the NetIDMgr application to add a page to a + property sheet. + + Pages can only be added before the property sheet is made visible + to the user. + + \param[in] sheet The property sheet to add the page to + + \param[in] credtype The credentials type ID of the owner of the + property page. This should be set to ::KCDB_CREDTYPE_INVALID + if the type is not relevant. + + \param[in] ordinal Requested ordinal. A positive integer which is + used to order the pages in a property sheet. The pages are + ordered based on ordinal first and then alphabetically by + credentials type name. If the type is unavailable, then the + ordering is undefined. Ordinals for credential type property + pages can be in the range from 0 to 127. Ordinals 128 and + above are reserved. Passing in 0 will work for credentials + providers unless they provide more than one property page per + credential, in which case the ordinal should be used to + enforce an order. + + \param[in] ppage Pointer to structure that will be passed to + CreatePropertySheetPage() to create the property page. The + structure is not managed by NetIDMgr at all, and must exist + until the status of the property sheet changes to + ::KHUI_PS_STATUS_RUNNING. The same pointer will be found in + the \a p_page member of the ::khui_property_page structure. + + \param[out] page A pointer will be returned here that will point + to the newly created khui_property_page structure. Specify + NULL if this value is not required. You can use + khui_ps_find_page() to retrieve a pointer to the structure + later. + */ +KHMEXP khm_int32 KHMAPI +khui_ps_add_page(khui_property_sheet * sheet, + khm_int32 credtype, + khm_int32 ordinal, + LPPROPSHEETPAGE ppage, + khui_property_page ** page); + +/*! \brief Retrieve a property page structure from a property sheet + */ +KHMEXP khm_int32 KHMAPI +khui_ps_find_page(khui_property_sheet * sheet, + khm_int32 credtype, + khui_property_page ** page); + +/*! \brief Display the property sheet + + \note Only called by the NetIDMgr application + */ +KHMEXP HWND KHMAPI +khui_ps_show_sheet(HWND parent, + khui_property_sheet * sheet); + +/*! \brief Check if the given message belongs to the property sheet + + \note Only called by the NetIDMgr application + */ +KHMEXP LRESULT KHMAPI +khui_ps_check_message(khui_property_sheet * sheet, + PMSG msg); + +/*! \brief Destroy a property sheet and all associated data structures. + + \note Only called by the NetIDMgr application. +*/ +KHMEXP khm_int32 KHMAPI +khui_ps_destroy_sheet(khui_property_sheet * sheet); + +KHMEXP khm_int32 KHMAPI +khui_property_wnd_set_record(HWND hwnd_pwnd, khm_handle record); + +/*!@}*/ +/*!@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khremote.h b/krb5-1-6/src/windows/identity/uilib/khremote.h new file mode 100644 index 000000000..3a79d6555 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khremote.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_REMOTE_H +#define __KHIMAIRA_REMOTE_H + +/*! \addtogroup khui + @{*/ +/*! \defgroup khui_remote Connecting to NetIDMgr from another process + @{*/ + +/* Leash compatibility */ +#define ID_OBTAIN_TGT_WITH_LPARAM 32810 + +#define KHUI_REQDAEMONWND_CLASS L"IDMgrRequestDaemonCls" +#define KHUI_REQDAEMONWND_NAME L"IDMgrRequestDaemon" + +#define KHUI_REQD_MAPPING_FORMAT L"Local\\NetIDMgr_DlgInfo_%lu" + +#define NETID_USERNAME_SZ 128 +#define NETID_REALM_SZ 192 +#define NETID_TITLE_SZ 256 +#define NETID_CCACHE_NAME_SZ 264 + +#define NETID_DLGTYPE_TGT 0 +#define NETID_DLGTYPE_CHPASSWD 1 +typedef struct { + DWORD size; + DWORD dlgtype; + // Tells whether dialog box is in change pwd mode or init ticket mode + struct { + WCHAR title[NETID_TITLE_SZ]; + WCHAR username[NETID_USERNAME_SZ]; + WCHAR realm[NETID_REALM_SZ]; + WCHAR ccache[NETID_CCACHE_NAME_SZ]; + DWORD use_defaults; + DWORD forwardable; + DWORD noaddresses; + DWORD lifetime; + DWORD renew_till; + DWORD proxiable; + DWORD publicip; + DWORD must_use_specified_principal; + } in; + struct { + WCHAR username[NETID_USERNAME_SZ]; + WCHAR realm[NETID_REALM_SZ]; + WCHAR ccache[NETID_CCACHE_NAME_SZ]; + } out; + // Version 1 of this structure ends here +} NETID_DLGINFO, *LPNETID_DLGINFO; + +#define NETID_DLGINFO_V1_SZ (10 * sizeof(DWORD) \ + + sizeof(WCHAR) * (NETID_TITLE_SZ + \ + 2 * NETID_USERNAME_SZ + 2 * NETID_REALM_SZ + \ + 2 * NETID_CCACHE_NAME_SZ)) + +/*!@} */ +/*!@} */ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khrescache.h b/krb5-1-6/src/windows/identity/uilib/khrescache.h new file mode 100644 index 000000000..63baa1f72 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khrescache.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_RESCACHE_H +#define __KHIMAIRA_RESCACHE_H + +#include<khdefs.h> + +KHMEXP void KHMAPI +khui_init_rescache(void); + +KHMEXP void KHMAPI +khui_exit_rescache(void); + +KHMEXP void KHMAPI +khui_cache_bitmap(UINT id, HBITMAP hbm); + +KHMEXP HBITMAP KHMAPI +khui_get_cached_bitmap(UINT id); + +typedef struct khui_ilist_t { + int cx; + int cy; + int n; + int ng; + int nused; + HBITMAP img; + HBITMAP mask; + int *idlist; +} khui_ilist; + +typedef struct khui_bitmap_t { + HBITMAP hbmp; + int cx; + int cy; +} khui_bitmap; + +KHMEXP void KHMAPI +khui_bitmap_from_hbmp(khui_bitmap * kbm, HBITMAP hbm); + +KHMEXP void KHMAPI +khui_delete_bitmap(khui_bitmap * kbm); + +KHMEXP void KHMAPI +khui_draw_bitmap(HDC hdc, int x, int y, khui_bitmap * kbm); + +/* image lists */ +KHMEXP khui_ilist * KHMAPI +khui_create_ilist(int cx, int cy, int n, int ng, int opt); + +KHMEXP BOOL KHMAPI +khui_delete_ilist(khui_ilist * il); + +KHMEXP int KHMAPI +khui_ilist_add_masked(khui_ilist * il, HBITMAP hbm, COLORREF cbkg); + +KHMEXP int KHMAPI +khui_ilist_add_masked_id(khui_ilist *il, HBITMAP hbm, + COLORREF cbkg, int id); + +KHMEXP int KHMAPI +khui_ilist_lookup_id(khui_ilist *il, int id); + +KHMEXP void KHMAPI +khui_ilist_draw(khui_ilist * il, int idx, HDC dc, int x, int y, int opt); + +KHMEXP void KHMAPI +khui_ilist_draw_bg(khui_ilist * il, int idx, HDC dc, int x, int y, + int opt, COLORREF bgcolor); + +#define khui_ilist_draw_id(il, id, dc, x, y, opt) \ + khui_ilist_draw((il),khui_ilist_lookup_id((il),(id)),(dc),(x),(y),(opt)) + +#define KHUI_SMICON_CX 16 +#define KHUI_SMICON_CY 16 + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khtracker.h b/krb5-1-6/src/windows/identity/uilib/khtracker.h new file mode 100644 index 000000000..38be29a13 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khtracker.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_TRACKERWND_H +#define __KHIMAIRA_TRACKERWND_H + +#include<time.h> + +/*! \addtogroup khui + +@{ */ + +/*!\defgroup khui_trk Duration sliders + +The duration sliders in the UI are pseudo-log-scaled. This is based +on the assumption that people don't really need 1 minute accuracy when +setting a duration that's several hours long. As a result, it is +easier to hone in on the duration that you want without having +wizardly mouse maneuvering skillz. + +Following are the duration ranges and the granularity that is offered +in each range: + +<table> +<tr><td> Range </td><td> Increment</td></tr> +<tr><td> 0..5m </td><td> 1 min </td></tr> +<tr><td> 5m..1hr </td><td> 5 min </td></tr> +<tr><td> 1hr..4hr </td><td> 15 min </td></tr> +<tr><td> 4hr..10hr </td><td> 30 min </td></tr> +<tr><td> 10hr..24hr</td><td> 1 hr </td></tr> +<tr><td> 24hr..4d </td><td> 6 hr </td></tr> +<tr><td> 4d.. </td><td> 1 day </td></tr> +</table> + +We don't really adjust for durations over 4 days. The ranges we are +concerned with don't get much larger. + +For the purpose of writing this piece of code, I have chosen the term +"tick" to refer to a period of granularity. The number of periods of +granularity (inclusive) within a certain duration interval is referred +to as the number of ticks in the interval. For example, there are 4 +ticks between the interval of 3 minutes to 10 minutes. Each occuring +at the start of 3min, 4, 5 and 10mins. And thusly the slider control +will display 4 ticks if it is displaying the interval 3-10mins. + +@{*/ + +/*! \brief Tracker data */ +typedef struct tag_khui_tracker { + WNDPROC fn_edit; + WNDPROC fn_tracker; + HWND hw_slider; + HWND hw_edit; + int lbl_y; + int lbl_lx; + int lbl_rx; + DWORD act_time; + + time_t current; /*!< Current selection */ + time_t min; /*!< Minimum (inclusive) */ + time_t max; /*!< Maximum (inclusive) */ +} khui_tracker; + +/*! \brief Install a tracker into an edit control + + Once installed, the edit control becomes a duration editor. The + tracker data structure that is supplied should remain as is for + the lifetime of the edit control. + + The tracker strucutre should have been initialized with a call to + khui_tracker_initialize() and should have valid values in the \a + min, \a max and \a current fields. + */ +KHMEXP void KHMAPI +khui_tracker_install(HWND hwnd_edit, khui_tracker * tc); + +KHMEXP void KHMAPI +khui_tracker_reposition(khui_tracker * tc); + +KHMEXP void KHMAPI +khui_tracker_initialize(khui_tracker * tc); + +KHMEXP void KHMAPI +khui_tracker_refresh(khui_tracker * tc); + +KHMEXP void KHMAPI +khui_tracker_kill_controls(khui_tracker * tc); +/*!@}*/ +/*!@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/khuidefs.h b/krb5-1-6/src/windows/identity/uilib/khuidefs.h new file mode 100644 index 000000000..16c4474f7 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/khuidefs.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KHUIDEFS_H +#define __KHIMAIRA_KHUIDEFS_H + +#include<windows.h> +#include<kmq.h> +#include<kcreddb.h> +#include<kherror.h> +#include<kherr.h> +#include<khmsgtypes.h> + +#include<khaction.h> +#include<khactiondef.h> +#include<khhtlink.h> +#include<khnewcred.h> +#include<khprops.h> +#include<khalerts.h> +#include<khconfigui.h> +#include<khtracker.h> + +#ifdef NOEXPORT +#include<khrescache.h> +#endif + +#include<khremote.h> + +/*! \internal */ +KHMEXP void KHMAPI +khm_version_init(void); + +/*! \defgroup khui User Interface + + Functions and data structures for interacting with the user + interface. + +@{*/ + +/*! \brief Get the version of the NetIDMgr library + + \param[out] libver Receives the version of the library. + + \param[out] apiver Receives the API version of the library. + Optional. Set to NULL if this value is not required. + + \note When the NetIDMgr framework loads a plugin, it checks the + version information of the plugin against the version of the + library to determine if the plugin is compatible. + */ +KHMEXP void KHMAPI +khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver); + +/*! \brief Return the version of Common Control library + + Can be used to check the version of the Windows Common Control + library that is currently loaded. The return value of the + function is the packed version value obatained by the macro : + + \code + MAKELONG(vesion->dwMinorVersion, version->dwMajorVersion); + \endcode + + The \a pdvi parameter is optional. Specify NULL if this is not + required. + */ +KHMEXP khm_ui_4 KHMAPI +khm_get_commctl_version(khm_version * pdvi); + +/*! \brief UI callback function + + Used with khui_request_UI_callback(). + + \see khui_request_UI_callback() + */ +typedef khm_int32 +(KHMAPI *khm_ui_callback)(HWND hwnd_main_wnd, void * rock); + +/*! \brief Request a UI callback + + In general, plug-ins in Network Identity Manager run in their own + thread and will not be able to interact with the user directly by + creating windows of its own. There are exceptions to this, such + as when the plug-in is responding to a new credentials request or + if the plug-in provides configuration panels. However, if a + plug-in needs to provide a user interface to the user outside of + the provisions already provided by Network Identity Manager, it + needs to do so from within the user interface thread. + + To do so, a plug-in would provide a callback function of the type + ::khm_ui_callback to this function. The Network Identity Manager + will then call the callback function from within the user + interface thread. At this point, the callback function can create + any windows it wishes to create and interact with the user + directly. + + The callback function would be called synchronously. + khui_request_UI_callback() will not return until the user + interface processes the request and calls the callback function. + The return code of khui_request_UI_callback() will be the return + code of the callback. + + \param[in] cb The callback function which will be called from the + user interface thread. + + \param[in] rock An arbitrary parameter which will be passed into + the callback function. + + \return The return value of \a cb. + + \note When the plug-in creates any windows, it should specify the + window handle provided via the \a hwnd_main_wnd parameter as + the parent window. + + \see ::khm_ui_callback + */ +KHMEXP khm_int32 KHMAPI +khui_request_UI_callback(khm_ui_callback cb, void * rock); + +/*!@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/uilib/propsheet.c b/krb5-1-6/src/windows/identity/uilib/propsheet.c new file mode 100644 index 000000000..068bcf00c --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/propsheet.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> +#include<utils.h> +#ifdef DEBUG +#include<assert.h> +#endif + +CRITICAL_SECTION cs_props; + +void +ps_init(void) { + InitializeCriticalSection(&cs_props); +} + +void +ps_exit(void) { + DeleteCriticalSection(&cs_props); +} + +KHMEXP khm_int32 KHMAPI +khui_ps_create_sheet(khui_property_sheet ** sheet) +{ + khui_property_sheet * ps; + + ps = PMALLOC(sizeof(*ps)); + ZeroMemory(ps, sizeof(*ps)); + + ps->header.dwSize = sizeof(ps->header); + ps->header.dwFlags = PSH_MODELESS | PSH_PROPTITLE; + ps->status = KHUI_PS_STATUS_NONE; + + *sheet = ps; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_ps_add_page(khui_property_sheet * sheet, + khm_int32 credtype, + khm_int32 ordinal, + LPPROPSHEETPAGE ppage, + khui_property_page ** page) +{ + khui_property_page * p; + + p = PMALLOC(sizeof(*p)); + ZeroMemory(p, sizeof(*p)); + + p->credtype = credtype; + p->ordinal = ordinal; + p->p_page = ppage; + + EnterCriticalSection(&cs_props); + QPUT(sheet, p); + sheet->n_pages++; + LeaveCriticalSection(&cs_props); + + if(page) + *page = p; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +khui_ps_find_page(khui_property_sheet * sheet, + khm_int32 credtype, + khui_property_page ** page) +{ + khui_property_page * p; + + EnterCriticalSection(&cs_props); + p = QTOP(sheet); + + while(p) { + if(p->credtype == credtype) + break; + p = QNEXT(p); + } + LeaveCriticalSection(&cs_props); + + if(p) { + *page = p; + return KHM_ERROR_SUCCESS; + } else { + *page = NULL; + return KHM_ERROR_NOT_FOUND; + } +} + +int __cdecl +ps_order_func(const void *l, const void * r) { + khui_property_page * lp; + khui_property_page * rp; + + lp = *(khui_property_page **)l; + rp = *(khui_property_page **)r; + + if (lp->ordinal == rp->ordinal) + return lp->credtype - rp->credtype; + else + return lp->ordinal - rp->ordinal; +} + +KHMEXP HWND KHMAPI +khui_ps_show_sheet(HWND parent, khui_property_sheet * s) +{ + khui_property_page * p; + HPROPSHEETPAGE phpsp[KHUI_PS_MAX_PSP]; + khui_property_page * ppgs[KHUI_PS_MAX_PSP]; + int i; + INT_PTR prv; + HWND hw; + + EnterCriticalSection(&cs_props); + + s->header.hwndParent = parent; + s->header.nPages = s->n_pages; + + p = QTOP(s); + i = 0; + while(p) { + p->h_page = CreatePropertySheetPage(p->p_page); +#ifdef DEBUG + assert(p->h_page); +#endif + ppgs[i++] = p; + p = QNEXT(p); + } + +#ifdef DEBUG + assert(i == s->n_pages); +#endif + + qsort(ppgs, s->n_pages, sizeof(ppgs[0]), ps_order_func); + + for (i=0; i < s->n_pages; i++) { + phpsp[i] = ppgs[i]->h_page; + } + + s->header.phpage = phpsp; + + prv = PropertySheet(&s->header); + + s->header.phpage = NULL; + + if(prv <= 0) { +#ifdef DEBUG + assert(FALSE); +#endif + /*TODO: better handling for this */ + hw = NULL; + } else { + s->status = KHUI_PS_STATUS_RUNNING; + + hw = (HWND) prv; + s->hwnd = hw; + s->hwnd_page = PropSheet_GetCurrentPageHwnd(hw); + } + LeaveCriticalSection(&cs_props); + + return hw; +} + +KHMEXP LRESULT KHMAPI +khui_ps_check_message(khui_property_sheet * sheet, + PMSG pmsg) +{ + LRESULT lr; + + if(sheet->hwnd == NULL) + return FALSE; + + lr = PropSheet_IsDialogMessage(sheet->hwnd, pmsg); + if(lr) { + sheet->hwnd_page = PropSheet_GetCurrentPageHwnd(sheet->hwnd); + if(sheet->hwnd_page == NULL && + sheet->status == KHUI_PS_STATUS_RUNNING) + + sheet->status = KHUI_PS_STATUS_DONE; + } + + return lr; +} + +KHMEXP khm_int32 KHMAPI +khui_ps_destroy_sheet(khui_property_sheet * sheet) +{ + khui_property_page * p; + + EnterCriticalSection(&cs_props); + + DestroyWindow(sheet->hwnd); + sheet->hwnd = NULL; + + QGET(sheet, &p); + while(p) { + PFREE(p); + QGET(sheet, &p); + } + PFREE(sheet); + + LeaveCriticalSection(&cs_props); + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/uilib/propwnd.c b/krb5-1-6/src/windows/identity/uilib/propwnd.c new file mode 100644 index 000000000..ea36e28aa --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/propwnd.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> + + +#define PW_WM_SET_RECORD WM_USER + +KHMEXP khm_int32 KHMAPI khui_property_wnd_set_record(HWND hwnd_pwnd, khm_handle record) +{ + SendMessage(hwnd_pwnd, PW_WM_SET_RECORD, 0, (LPARAM) record); + + return KHM_ERROR_SUCCESS; +} diff --git a/krb5-1-6/src/windows/identity/uilib/rescache.c b/krb5-1-6/src/windows/identity/uilib/rescache.c new file mode 100644 index 000000000..7715cfdee --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/rescache.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define NOEXPORT +#define _NIMLIB_ + +#include<khuidefs.h> +#include<utils.h> + +hashtable * h_bitmaps; + +khm_int32 +hash_id(const void *p) { +#pragma warning(push) +#pragma warning(disable: 4311) + return (khm_int32) p; +#pragma warning(pop) +} + +khm_int32 +comp_id(const void *p1, const void *p2) { +#pragma warning(push) +#pragma warning(disable: 4311) + return ((khm_int32)p1) - ((khm_int32)p2); +#pragma warning(pop) +} + +void +del_ref_object(const void *k, void * data) { + DeleteObject((HGDIOBJ) data); +} + +KHMEXP void KHMAPI +khui_init_rescache(void) { + h_bitmaps = hash_new_hashtable(127, hash_id, comp_id, NULL, + del_ref_object); +} + +KHMEXP void KHMAPI +khui_exit_rescache(void) { + hash_del_hashtable(h_bitmaps); +} + +KHMEXP void KHMAPI +khui_cache_bitmap(UINT id, HBITMAP hbm) { + hash_add(h_bitmaps, (void *)(size_t) id, (void *) hbm); +} + +KHMEXP HBITMAP KHMAPI +khui_get_cached_bitmap(UINT id) { + return (HBITMAP) hash_lookup(h_bitmaps, (void *)(size_t) id); +} + +KHMEXP khui_ilist * KHMAPI +khui_create_ilist(int cx, int cy, int n, int ng, int opt) { + BITMAPV5HEADER head; + HDC hdc; + + khui_ilist * il = PMALLOC(sizeof(khui_ilist)); + il->cx = cx; + il->cy = cy; + il->n = n; + il->ng = ng; + il->nused = 0; + hdc = GetDC(NULL); + head.bV5Size = sizeof(head); + head.bV5Width = cx * n; + head.bV5Height = cy; + head.bV5Planes = 1; + head.bV5BitCount = 24; + head.bV5Compression = BI_RGB; + head.bV5SizeImage = 0; + head.bV5XPelsPerMeter = 2835; + head.bV5YPelsPerMeter = 2835; + head.bV5ClrUsed = 0; + head.bV5ClrImportant = 0; + head.bV5AlphaMask = 0; + head.bV5CSType = LCS_WINDOWS_COLOR_SPACE; + head.bV5Intent = LCS_GM_GRAPHICS; + head.bV5ProfileData = 0; + head.bV5ProfileSize = 0; + head.bV5Reserved = 0; + il->img = CreateDIBitmap(hdc, (BITMAPINFOHEADER *) &head, 0, NULL, NULL, DIB_RGB_COLORS); + il->mask = CreateBitmap(cx * n, cy, 1, 1, NULL); + il->idlist = PMALLOC(sizeof(int) * n); + + return il; +} + +KHMEXP BOOL KHMAPI +khui_delete_ilist(khui_ilist * il) { + DeleteObject(il->img); + DeleteObject(il->mask); + PFREE(il->idlist); + PFREE(il); + + return TRUE; +} + +KHMEXP int KHMAPI +khui_ilist_add_masked_id(khui_ilist *il, + HBITMAP hbm, + COLORREF cbkg, + int id) { + int idx; + + idx = khui_ilist_add_masked(il,hbm,cbkg); + if(idx >= 0) { + il->idlist[idx] = id; + } + + return idx; +} + +KHMEXP int KHMAPI +khui_ilist_lookup_id(khui_ilist *il, int id) { + int i; + + for(i=0;i<il->nused;i++) { + if(il->idlist[i] == id) + return i; + } + + return -1; +} + +KHMEXP int KHMAPI +khui_ilist_add_masked(khui_ilist * il, HBITMAP hbm, COLORREF cbkg) { + HDC dcr,dci,dct,dcb; + HBITMAP hb_oldb, hb_oldi, hb_oldt; + int sx, i; + int x,y; + + dcr = GetDC(NULL); + dci = CreateCompatibleDC(dcr); + dct = CreateCompatibleDC(dcr); + dcb = CreateCompatibleDC(dcr); + ReleaseDC(NULL,dcr); + + i = il->nused++; + il->idlist[i] = -1; + sx = i * il->cx; + + hb_oldb = SelectObject(dcb, hbm); + hb_oldi = SelectObject(dci, il->img); + hb_oldt = SelectObject(dct, il->mask); + + SetBkColor(dct, RGB(0,0,0)); + SetTextColor(dct, RGB(255,255,255)); + + BitBlt(dci, sx, 0, il->cx, il->cy, dcb, 0, 0, SRCCOPY); + for(y=0;y < il->cy; y++) + for(x=0; x<il->cx; x++) { + COLORREF c = GetPixel(dcb, x, y); + if(c==cbkg) { + SetPixel(dct, sx + x, y, RGB(255,255,255)); + SetPixel(dci, sx + x, y, RGB(0,0,0)); + } else { + SetPixel(dct, sx + x, y, RGB(0,0,0)); + } + } + + SelectObject(dct, hb_oldt); + SelectObject(dci, hb_oldi); + SelectObject(dcb, hb_oldb); + + DeleteDC(dcb); + DeleteDC(dct); + DeleteDC(dci); + + return i; +} + +KHMEXP void KHMAPI +khui_ilist_draw(khui_ilist * il, + int idx, + HDC dc, + int x, + int y, + int opt) { + HDC dci; + HBITMAP hb_oldi; + + if(idx < 0) + return; + + dci = CreateCompatibleDC(dc); + + hb_oldi = SelectObject(dci, il->img); + + /*BitBlt(dc, x, y, il->cx, il->cy, dci, idx*il->cx, 0, SRCCOPY); */ + MaskBlt(dc, x, y, il->cx, il->cy, dci, idx * il->cx, 0, il->mask, idx * il->cx, 0, MAKEROP4(SRCPAINT, SRCCOPY)); +/* MaskBlt(dc, x, y, il->cx, il->cy, dci, idx * il->cx, 0, il->mask, idx * il->cx, 0, MAKEROP4(SRCINVERT, SRCCOPY)); */ + + SelectObject(dci, hb_oldi); + + DeleteDC(dci); +} + +KHMEXP void KHMAPI +khui_ilist_draw_bg(khui_ilist * il, + int idx, + HDC dc, + int x, + int y, + int opt, + COLORREF bgcolor) { + HDC dcm; + HBITMAP hb_oldm, hb_mem; + HBRUSH hbr; + RECT r; + + dcm = CreateCompatibleDC(dc); + + hb_mem = CreateCompatibleBitmap(dc, il->cx, il->cy); + + hb_oldm = SelectObject(dcm, hb_mem); + + hbr = CreateSolidBrush(bgcolor); + + r.left = 0; + r.top = 0; + r.right = il->cx; + r.bottom = il->cy; + + FillRect(dcm, &r, hbr); + + khui_ilist_draw(il,idx,dcm,0,0,opt); + + BitBlt(dc,x,y,il->cx,il->cy,dcm,0,0,SRCCOPY); + + SelectObject(dcm, hb_oldm); + + DeleteObject(hb_mem); + DeleteObject(hbr); + + DeleteDC(dcm); +} + + +KHMEXP void KHMAPI +khui_bitmap_from_hbmp(khui_bitmap * kbm, HBITMAP hbm) +{ + HDC hdc; + BITMAPINFO bmi; + + hdc = CreateCompatibleDC(NULL); + + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + kbm->hbmp = hbm; + + if(GetDIBits(hdc, hbm, 0, 0, NULL, &bmi, DIB_RGB_COLORS)) { + kbm->cx = bmi.bmiHeader.biWidth; + kbm->cy = bmi.bmiHeader.biHeight; + } else { + kbm->cx = -1; + kbm->cy = -1; + } + + DeleteDC(hdc); +} + +KHMEXP void KHMAPI +khui_delete_bitmap(khui_bitmap * kbm) { + if (kbm->hbmp) + DeleteObject(kbm->hbmp); + kbm->hbmp = NULL; +} + +KHMEXP void KHMAPI +khui_draw_bitmap(HDC hdc, int x, int y, khui_bitmap * kbm) { + HDC hdcb = CreateCompatibleDC(hdc); + HBITMAP hbmold = SelectObject(hdcb, kbm->hbmp); + + BitBlt(hdc, x, y, kbm->cx, kbm->cy, + hdcb, 0, 0, SRCCOPY); + + SelectObject(hdcb, hbmold); + DeleteDC(hdcb); +} diff --git a/krb5-1-6/src/windows/identity/uilib/trackerwnd.c b/krb5-1-6/src/windows/identity/uilib/trackerwnd.c new file mode 100644 index 000000000..cc434d95f --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/trackerwnd.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> +#include<commctrl.h> +#include<assert.h> + +#define K5_SLIDER_WIDTH 208 +#define K5_SLIDER_HEIGHT 40 + +#define K5_SLIDER_LBL_HPAD 5 +#define K5_SLIDER_LBL_VPAD 22 + +#define KHUI_TRACKER_PROP L"KhmTrackerData" + + +/* Count the number of ticks between tmin and tmax, inclusive +*/ +int time_t_to_ticks(time_t tmin, time_t tmax) +{ + int c = 0; + time_t lo, hi; + + tmin -= tmin % 60; /* our smallest gran is 1 min */ + if(tmax % 60) + tmax += 60 - (tmax % 60); + + lo = tmin; + +#define TFORWARD(limit,gran) \ + if(lo < limit && lo < tmax) { \ + hi = min(tmax, limit); \ + c += (int)((hi - lo) / (gran)); \ + lo = hi; \ + } + + TFORWARD(300,60); + TFORWARD(3600,300); + TFORWARD(3600*4, 60*15); + TFORWARD(3600*10,60*30); + TFORWARD(3600*24,3600); + TFORWARD(3600*24*4,3600*6); + TFORWARD(((time_t)(INFINITE & INT_MAX)),3600*24); + +#undef TFORWARD + + return c; +} + +/* Compute tmax given tmin and ticks such that there are ticks ticks + between tmin and tmax + */ +time_t ticks_to_time_t(int ticks, time_t tmin) +{ + int c = 0; + tmin -= tmin % 60; /* our smallest gran is 1 min */ + +#define SFORWARD(limit,gran) \ + if(tmin < limit && ticks > 0) { \ + c = (int) min(ticks, (limit - tmin) / (gran)); \ + tmin += c * gran; \ + ticks -= c; \ + } + + SFORWARD(300,60); + SFORWARD(3600,300); + SFORWARD(3600*4,60*15); + SFORWARD(3600*10,60*30); + SFORWARD(3600*24,3600); + SFORWARD(3600*24*4,3600*6); + SFORWARD(((time_t)(INFINITE & INT_MAX)),3600*24); + +#undef SFORWARD + + return tmin; +} + +/* Prep a tracker control which works in conjunction with the + duration edit control. + + NOTE: Runs in the context of the UI thread +*/ +void +initialize_tracker(HWND hwnd, + khui_tracker * tc) +{ + RECT r; + FILETIME ft; + wchar_t wbuf[256]; + khm_size cbbuf; + + SendMessage(tc->hw_slider, TBM_SETRANGE, 0, MAKELONG(0, time_t_to_ticks(tc->min, tc->max))); + SendMessage(tc->hw_slider, TBM_SETPOS, TRUE, (LPARAM) time_t_to_ticks(tc->min, tc->current)); + + r.left = K5_SLIDER_LBL_HPAD; + r.top = K5_SLIDER_LBL_VPAD; + r.right = K5_SLIDER_WIDTH - K5_SLIDER_LBL_HPAD; + r.bottom = r.top; + + MapDialogRect(hwnd, &r); + + tc->lbl_y = r.top; + tc->lbl_lx = r.left; + tc->lbl_rx = r.right; + + TimetToFileTimeInterval(tc->current, &ft); + cbbuf = sizeof(wbuf); + FtIntervalToString(&ft, wbuf, &cbbuf); + + SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM)wbuf); +} + + +/* We instance-subclass each tracker control to provide the + functionality that we need. This is the replacement window + procedure + + NOTE: Runs in the context of the UI thread + */ +LRESULT CALLBACK +duration_tracker_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + khui_tracker * tc; + + tc = (khui_tracker *) GetProp(hwnd, KHUI_TRACKER_PROP); +#ifdef DEBUG + assert(tc != NULL); +#endif + + switch(uMsg) { + case WM_PAINT: + { + HDC hdc; + HFONT hf, hfold; + LRESULT lr; + FILETIME ft; + wchar_t buf[256]; + khm_size cbbuf; + + lr = CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam); + + /* Can't use BeginPaint here, since we already called the + window proc */ + hdc = GetWindowDC(hwnd); + + hf = (HFONT) SendMessage(tc->hw_edit, WM_GETFONT, 0, 0); + + hfold = ((HFONT) SelectObject((hdc), (HGDIOBJ)(HFONT)(hf))); + + TimetToFileTimeInterval(tc->min, &ft); + cbbuf = sizeof(buf); + FtIntervalToString(&ft, buf, &cbbuf); + + SetTextColor(hdc, RGB(0,0,0)); + SetBkMode(hdc, TRANSPARENT); + + SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP); + TextOut(hdc, tc->lbl_lx, tc->lbl_y, buf, (int) wcslen(buf)); + + TimetToFileTimeInterval(tc->max, &ft); + cbbuf = sizeof(buf); + FtIntervalToString(&ft, buf, &cbbuf); + + SetTextAlign(hdc, TA_RIGHT | TA_TOP | TA_NOUPDATECP); + TextOut(hdc, tc->lbl_rx, tc->lbl_y, buf, (int) wcslen(buf)); + + ((HFONT) SelectObject((hdc), (HGDIOBJ)(HFONT)(hfold))); + + ReleaseDC(hwnd, hdc); + + return lr; + } + break; + + case WM_KILLFOCUS: + { + if((HWND)wParam != tc->hw_edit) + ShowWindow(hwnd, SW_HIDE); + } + break; + + case WM_LBUTTONUP: + case WM_MOUSEMOVE: + { + LRESULT lr; + + lr = CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam); + + if(wParam & MK_LBUTTON) { + int c = (int) SendMessage(hwnd, TBM_GETPOS, 0, 0); + time_t t = ticks_to_time_t(c, tc->min); + + if(t != tc->current) { + wchar_t buf[256]; + FILETIME ft; + khm_size cbbuf; + + tc->current = t; + //d->dirty = TRUE; + cbbuf = sizeof(buf); + TimetToFileTimeInterval(t, &ft); + FtIntervalToString(&ft, buf, &cbbuf); + SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM) buf); + } + } + return lr; + } + } + + return CallWindowProc(tc->fn_tracker, hwnd, uMsg, wParam, lParam); +} + + +/* Create the subclassed duration slider on behalf of an edit control */ +void +create_edit_sliders(HWND hwnd, + HWND hwnd_dlg, + khui_tracker * tc) +{ + RECT r; + RECT rs; + + GetWindowRect(hwnd, &r); + + rs.top = 0; + rs.left = 0; + rs.right = K5_SLIDER_WIDTH; + rs.bottom = K5_SLIDER_HEIGHT; + MapDialogRect(hwnd_dlg, &rs); + rs.right -= rs.left; + rs.bottom -= rs.top; + + tc->hw_slider = + CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, + TRACKBAR_CLASS, + L"NetIDMgrTimeTickerTrackbar", + WS_POPUP | TBS_AUTOTICKS | TBS_BOTTOM | +#if (_WIN32_IE >= 0x0501) + TBS_DOWNISLEFT | +#endif + TBS_HORZ | WS_CLIPCHILDREN, + r.left,r.bottom,rs.right,rs.bottom, + hwnd, + NULL, + (HINSTANCE)(DWORD_PTR) + GetWindowLongPtr(hwnd, GWLP_HINSTANCE), + NULL); + + SetProp(tc->hw_slider, KHUI_TRACKER_PROP, + (HANDLE) tc); + +#pragma warning(push) +#pragma warning(disable: 4244) + tc->fn_tracker = (WNDPROC)(LONG_PTR) SetWindowLongPtr(tc->hw_slider, GWLP_WNDPROC, (LONG_PTR) duration_tracker_proc); +#pragma warning(pop) +} + +/* An edit control is instance-subclassed to create an edit control + that holds a duration. Welcome to the window procedure. + + NOTE: Runs in the context of the UI thread + */ +LRESULT CALLBACK +duration_edit_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + khui_tracker * tc; + + tc = (khui_tracker *) GetProp(hwnd, KHUI_TRACKER_PROP); + +#ifdef DEBUG + assert(tc != NULL); +#endif + + switch(uMsg) { + case WM_SETFOCUS: + { + HWND p; + + p = GetParent(hwnd); + + /* we are being activated. */ + if(tc->hw_slider == NULL) { + create_edit_sliders(hwnd, p, tc); + initialize_tracker(p, tc); + } + + khui_tracker_reposition(tc); + +#ifdef SHOW_PANEL_ON_FIRST_ACTIVATE + ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE); +#endif + + tc->act_time = GetTickCount(); + } + break; + + case WM_KILLFOCUS: + { + wchar_t wbuf[256]; + FILETIME ft; + khm_size cbbuf; + + if((HWND) wParam != tc->hw_slider) + ShowWindow(tc->hw_slider, SW_HIDE); + + TimetToFileTimeInterval(tc->current, &ft); + cbbuf = sizeof(wbuf); + FtIntervalToString(&ft, wbuf, &cbbuf); + + SendMessage(tc->hw_edit, WM_SETTEXT, 0, (LPARAM)wbuf); + } + break; + + case KHUI_WM_NC_NOTIFY: + if(HIWORD(wParam) == WMNC_DIALOG_SETUP) { + HWND p; + + p = GetParent(hwnd); + + if(tc->hw_slider == NULL) { + create_edit_sliders(hwnd,p,tc); + } + + initialize_tracker(p, tc); + } + return TRUE; + + case WM_LBUTTONUP: + if (IsWindowVisible(tc->hw_slider)) { + DWORD tm; + + tm = GetTickCount(); + if (tm - tc->act_time > 000) + ShowWindow(tc->hw_slider, SW_HIDE); + } else { + ShowWindow(tc->hw_slider, SW_SHOWNOACTIVATE); + } + break; + + /* these messages can potentially change the text in the edit + control. We intercept them and see what changed. We may + need to grab and handle them */ + case EM_REPLACESEL: + case EM_UNDO: + case WM_UNDO: + case WM_CHAR: +#if (_WIN32_WINNT >= 0x0501) + case WM_UNICHAR: +#endif + { + wchar_t buf[256]; + size_t nchars; + time_t ts; + FILETIME ft; + BOOL modified; + LRESULT lr = CallWindowProc(tc->fn_edit, hwnd, uMsg, wParam, lParam); + + modified = (BOOL) SendMessage(hwnd, EM_GETMODIFY, 0, 0); + if(modified) { + /* parse the string */ + if(nchars = (size_t) SendMessage(hwnd, WM_GETTEXT, ARRAYLENGTH(buf), (LPARAM) buf)) { + buf[nchars] = 0; + + if(KHM_SUCCEEDED(IntervalStringToFt(&ft, buf))) { + ts = FtIntervalToSeconds(&ft); + if(ts >= tc->min && ts <= tc->max) { + tc->current = ts; + //d->dirty = TRUE; + if(tc->hw_slider != NULL) + SendMessage(tc->hw_slider, TBM_SETPOS, TRUE, (LPARAM) time_t_to_ticks(tc->min, tc->current)); + } + } + } + SendMessage(hwnd, EM_SETMODIFY, FALSE, 0); + } + + return lr; + } + } + + return CallWindowProc(tc->fn_edit, hwnd, uMsg, wParam, lParam); +} + +KHMEXP void KHMAPI +khui_tracker_install(HWND hwnd_edit, khui_tracker * tc) { +#ifdef DEBUG + assert(hwnd_edit); + assert(tc); +#endif + + tc->hw_edit = hwnd_edit; + + SetProp(hwnd_edit, KHUI_TRACKER_PROP, (HANDLE) tc); + +#pragma warning(push) +#pragma warning(disable: 4244) + tc->fn_edit = (WNDPROC)(LONG_PTR) + SetWindowLongPtr(hwnd_edit, GWLP_WNDPROC, + (LONG_PTR) duration_edit_proc); +#pragma warning(pop) +} + +KHMEXP void KHMAPI +khui_tracker_reposition(khui_tracker * tc) { + RECT r; + + if(tc->hw_slider && tc->hw_edit) { + GetWindowRect(tc->hw_edit, &r); + SetWindowPos(tc->hw_slider, + NULL, + r.left, r.bottom, + 0, 0, + SWP_NOOWNERZORDER | SWP_NOSIZE | + SWP_NOZORDER | SWP_NOACTIVATE); + } +} + +KHMEXP void KHMAPI +khui_tracker_initialize(khui_tracker * tc) { + ZeroMemory(tc, sizeof(*tc)); +} + +KHMEXP void KHMAPI +khui_tracker_refresh(khui_tracker * tc) { + if (!tc->hw_edit) + return; + + SendMessage(tc->hw_edit, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0); +} + +KHMEXP void KHMAPI +khui_tracker_kill_controls(khui_tracker * tc) { + if (tc->hw_slider) + DestroyWindow(tc->hw_slider); + if (tc->hw_edit) + DestroyWindow(tc->hw_edit); + tc->hw_slider = NULL; + tc->hw_edit = NULL; + tc->fn_edit = NULL; + tc->fn_tracker = NULL; +} + + + diff --git a/krb5-1-6/src/windows/identity/uilib/uibind.c b/krb5-1-6/src/windows/identity/uilib/uibind.c new file mode 100644 index 000000000..f2f44cc3e --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/uibind.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2007 Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> +#include<intaction.h> + +#ifdef DEBUG +#include <assert.h> +#endif + +KHMEXP khm_int32 KHMAPI +khui_request_UI_callback(khm_ui_callback cb, void * rock) { + + khui_ui_callback_data cbdata; + +#ifdef DEBUG + assert(khui_hwnd_main); +#endif + + if (khui_hwnd_main == NULL) + return KHM_ERROR_NOT_READY; + + ZeroMemory(&cbdata, sizeof(cbdata)); + cbdata.magic = KHUI_UICBDATA_MAGIC; + cbdata.cb = cb; + cbdata.rock = rock; + cbdata.rv = KHM_ERROR_NOT_IMPLEMENTED; + + SendMessage(khui_hwnd_main, WM_COMMAND, + MAKEWPARAM(KHUI_ACTION_UICB, 0), + (LPARAM) &cbdata); + + return cbdata.rv; +} + + + diff --git a/krb5-1-6/src/windows/identity/uilib/uilibmain.c b/krb5-1-6/src/windows/identity/uilib/uilibmain.c new file mode 100644 index 000000000..25cbcfe33 --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/uilibmain.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<khuidefs.h> + +extern void alert_init(void); +extern void alert_exit(void); +extern void ps_init(void); +extern void ps_exit(void); + +void +uilib_process_attach(void) { + alert_init(); + ps_init(); +} + +void +uilib_process_detach(void) { + ps_exit(); + alert_exit(); +} diff --git a/krb5-1-6/src/windows/identity/uilib/version.c b/krb5-1-6/src/windows/identity/uilib/version.c new file mode 100644 index 000000000..50a15543f --- /dev/null +++ b/krb5-1-6/src/windows/identity/uilib/version.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<shlwapi.h> +#include<khuidefs.h> +#include<netidmgr_intver.h> + +DLLVERSIONINFO ver_commctl; + +static void +get_dll_version(wchar_t * dllname, DLLVERSIONINFO * pdvi) { + HINSTANCE hdll; + + hdll = LoadLibrary(dllname); + + ZeroMemory(pdvi, sizeof(*pdvi)); + + if(hdll) { + DLLGETVERSIONPROC pDllGetVersion; + + pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hdll, "DllGetVersion"); + if(pDllGetVersion) { + pdvi->cbSize = sizeof(*pdvi); + + (*pDllGetVersion)(pdvi); + } + FreeLibrary(hdll); + } +} + +KHMEXP void KHMAPI +khm_version_init(void) { + get_dll_version(L"comctl32.dll", &ver_commctl); +} + +KHMEXP void KHMAPI +khm_get_lib_version(khm_version * libver, khm_ui_4 * apiver) { + if (!libver) + return; + + libver->major = KH_VERSION_MAJOR; + libver->minor = KH_VERSION_MINOR; + libver->patch = KH_VERSION_PATCH; + libver->aux = KH_VERSION_AUX; + + if (apiver) + *apiver = KH_VERSION_API; +} + +KHMEXP khm_ui_4 KHMAPI +khm_get_commctl_version(khm_version * pdvi) { + if (pdvi) { + pdvi->major = (khm_ui_2) ver_commctl.dwMajorVersion; + pdvi->minor = (khm_ui_2) ver_commctl.dwMinorVersion; + pdvi->patch = (khm_ui_2) ver_commctl.dwBuildNumber; + pdvi->aux = (khm_ui_2) ver_commctl.dwPlatformID; + } + + return MAKELONG(ver_commctl.dwMinorVersion, ver_commctl.dwMajorVersion); +} diff --git a/krb5-1-6/src/windows/identity/util/Makefile b/krb5-1-6/src/windows/identity/util/Makefile new file mode 100644 index 000000000..07202869f --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2007 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +MODULE=util +!include <../config/Makefile.w32> + +INCFILES= \ + $(INCDIR)\utils.h \ + $(INCDIR)\hashtable.h \ + $(INCDIR)\mstring.h \ + $(INCDIR)\sync.h \ + $(INCDIR)\perfstat.h + +OBJFILES= \ + $(OBJ)\hashtable.obj \ + $(OBJ)\mstring.obj \ + $(OBJ)\sync.obj \ + $(OBJ)\perfstat.obj + +LIBFILES= + +SDKLIBFILES= + +all: mkdirs $(INCFILES) $(OBJFILES) + +clean:: + if exist ..\obj $(RM) $(INCFILES) diff --git a/krb5-1-6/src/windows/identity/util/hashtable.c b/krb5-1-6/src/windows/identity/util/hashtable.c new file mode 100644 index 000000000..7836179d6 --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/hashtable.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<perfstat.h> +#include<hashtable.h> +#include<stdlib.h> + +KHMEXP hashtable * KHMAPI hash_new_hashtable(khm_int32 n, + hash_function_t hash, + comp_function_t comp, + add_ref_function_t addr, + del_ref_function_t delr) +{ + hashtable * h; + + h = PMALLOC(sizeof(hashtable)); + + h->n = n; + h->addr = addr; + h->comp = comp; + h->delr = delr; + h->hash = hash; + + h->bins = PCALLOC(sizeof(hash_bin *), n); + + return h; +} + +KHMEXP void KHMAPI hash_del_hashtable(hashtable * h) { + hash_bin * b; + int i; + + for(i=0;i<h->n;i++) { + LPOP(&h->bins[i], &b); + while(b) { + if(h->delr) + h->delr(b->key, b->data); + PFREE(b); + LPOP(&h->bins[i], &b); + } + } + + if (h->bins) + PFREE(h->bins); + + PFREE(h); +} + +KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data) { + int hv; + hash_bin * b; + + hv = h->hash(key) % h->n; + b = h->bins[hv]; + while(b) { + if(!h->comp(b->key, key)) { + /* found an existing value */ + if(h->delr) + h->delr(b->key, b->data); + b->key = key; + b->data = data; + if(h->addr) + h->addr(b->key, b->data); + break; + } + b = LNEXT(b); + } + + if(!b) { + b = PMALLOC(sizeof(hash_bin)); + b->data = data; + b->key = key; + LINIT(b); + LPUSH(&h->bins[hv], b); + if(h->addr) + h->addr(b->key, b->data); + } +} + +KHMEXP void KHMAPI hash_del(hashtable * h, const void * key) { + hash_bin * b; + int hv; + + hv = h->hash(key) % h->n; + + b = h->bins[hv]; + while(b) { + if(!h->comp(b->key, key)) { + /* found it */ + LDELETE(&h->bins[hv], b); + if(h->delr) + h->delr(b->key, b->data); + PFREE(b); + break; + } + b = LNEXT(b); + } +} + +KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key) { + hash_bin * b; + int hv; + + hv = h->hash(key) % h->n; + + b = h->bins[hv]; + + while(b) { + if(!h->comp(b->key, key)) { + return b->data; + } + b = LNEXT(b); + } + + return NULL; +} + +KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key) { + hash_bin * b; + int hv; + + hv = h->hash(key) % h->n; + b = h->bins[hv]; + while(b) { + if(!h->comp(b->key, key)) + return 1; + b = LNEXT(b); + } + + return 0; +} + +KHMEXP khm_int32 hash_string(const void *vs) { + /* DJB algorithm */ + + khm_int32 hv = 13331; + wchar_t * c; + + for(c = (wchar_t *) vs; *c; c++) { + hv = ((hv<<5) + hv) + (khm_int32) *c; + } + + return (hv & KHM_INT32_MAX); +} + +KHMEXP khm_int32 hash_string_comp(const void *vs1, const void *vs2) { + return wcscmp((const wchar_t *) vs1, (const wchar_t *) vs2); +} diff --git a/krb5-1-6/src/windows/identity/util/hashtable.h b/krb5-1-6/src/windows/identity/util/hashtable.h new file mode 100644 index 000000000..72fff2294 --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/hashtable.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_HASHTABLE_H +#define __KHIMAIRA_HASHTABLE_H + +/*! \addtogroup util + @{ */ + +/*! \defgroup util_ht Hashtable + @{*/ + +#include<khdefs.h> +#include<khlist.h> + +/*! \brief A hash function + + The function should take a key as a parameter and return an + khm_int32 that serves as the hash of the key. + */ +typedef khm_int32 (*hash_function_t)(const void *key); + +/*! \brief A comparison function + + The function takes two keys and returns a value indicating the + relative ordering of the two keys. + + The return value should be: + - \b Zero if \a key1 == \a key2 + - \b Negative if \a key1 &lt; \a key2 + - \b Positive if \a key1 &gt; \a key2 + */ +typedef khm_int32 (*comp_function_t)(const void *key1, const void *key2); + +/*! \brief Add-reference function + + When an object is successfully added to a hashtable, this function + will be called with the \a key and \a data used to add the object. + The function is allowed to modify \a data, however, the + modification should not alter the \a key or the relationship + between \a key and \a data. + */ +typedef void (*add_ref_function_t)(const void *key, void *data); + +/*! \brief Delete-reference function + + When an object is successfully removed from the hashtable, this + function will be called. As with the add-ref function, the object + can be modified, but the \a key and the relationship between \a + key and \a data should remain intact. + + An object is removed if it is explicitly removed from the + hashtable or another object with the same \a key is added to the + hashtable. There should be a 1-1 correspondence with keys and + objects in the hashtable. The delete-reference function will be + called on all the remaining objects in the hashtable when the + hashtable is deleted. + */ +typedef void (*del_ref_function_t)(const void *key, void *data); + +typedef struct tag_hash_bin { + void * data; + const void * key; + + LDCL(struct tag_hash_bin); +} hash_bin; + +typedef struct hashtable_t { + khm_int32 n; + hash_function_t hash; + comp_function_t comp; + add_ref_function_t addr; + del_ref_function_t delr; + hash_bin ** bins; +} hashtable; + +/*! \brief Create a new hashtable + + \param[in] n Number of bins in hashtable. + \param[in] hash A hash function. Required. + \param[in] comp A comparator. Required. + \param[in] addr An add-ref function. Optional; can be NULL. + \param[in] delr A del-ref function. Optional; can be NULL. + + */ +KHMEXP hashtable * KHMAPI hash_new_hashtable(khm_int32 n, + hash_function_t hash, + comp_function_t comp, + add_ref_function_t addr, + del_ref_function_t delr); + +/*! \brief Delete a hashtable + + \note Not thread-safe. Applications must serialize calls that + reference the same hashtable. + */ +KHMEXP void KHMAPI hash_del_hashtable(hashtable * h); + +/*! \brief Add an object to a hashtable + + Creates an association between the \a key and \a data in the + hashtable \a h. If there is an add-ref function defined for the + hashtable, it will be called with \a key and \data after the + object is added. If there is already an object with the same key + in the hashtable, that object will be removed (and the del-ref + function called, if appilcable) before adding the new object and + before the add-ref function is called for the new object. + + Note that two keys \a key1 and \a key2 are equal (or same) in a + hashtable if the comparator returns zero when called with \a key1 + and \a key2. + + Also note that all additions and removals to the hashtable are + done by reference. No data is copied. Any objects pointed to are + expected to exist for the duration that the object and key are + contained in the hashtable. + + \param[in] h Hashtable + \param[in] key A key. If \a key points to a location in memory, + it should be within the object pointed to by \a data, or be a + constant. Can be NULL. + \param[in] data Data. Cannot be NULL. + + \note Not thread-safe. Applications must serialize calls that + reference the same hashtable. + */ +KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data); + +/*! \brief Delete an object from a hashtable + + Deletes the object in the hashtable \a h that is associated with + key \a key. An object is associated with key \a key if the key \a + key_o that the object is associated with is the same as \a key as + determined by the comparator. If the del-ref function is defined + for the hash-table, it will be called with the \a key_o and \a + data that was used to add the object. + + \note Not thread-safe. Applications must serialize calls that + reference the same hashtable. + */ +KHMEXP void KHMAPI hash_del(hashtable * h, const void * key); + +/*! \brief Resolve and association + + Return the object that is associated with key \a key in hashtable + \a h. An object \a data is associated with key \a key in \a h if + the key \a key_o that was used to add \a data to \a h is equal to + \a key as determined by the comparator. + + Returns NULL if no association is found. + + \note Not thread-safe. Applications must serialize calls that + reference the same hashtable. + */ +KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key); + +/*! \brief Check for the presence of an association + + Returns non-zero if there exists an association between key \a key + and some object in hashtable \a h. See hash_lookup() for + definition of "association". + + Returns zero if there is no association. + + \note (hash_lookup(h,key) == NULL) iff (hash_exist(h,key)==0) + + \note Not thead-safe. Application must serialize calls that + reference the same hashtable. + */ +KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key); + +/*! \brief Compute a hashvalue for a unicode string + + The hash value is computed using DJB with parameter 13331. + + This function is suitable for use as the hash function for a + hashtable if the keys are NULL terminated safe unicode strings + that are either part of the data objects or are constants. + + \param[in] str A pointer to a NULL terminated wchar_t string cast + as (void *). + + \note This function does not check the length of the string \a + str. If the string is not \a NULL terminated, the behavior is + undefined. + */ +KHMEXP khm_int32 hash_string(const void *str); + +/*! \brief Compare two strings + + Compares two strings are returns a value that is in accordance + with the comparator for a hashtable. + + \param[in] vs1 A pointer to a NULL terminated wchar_t string cast + as (void *). + \param[in] vs2 A pointer to a NULL terminated wchar_t string cast + as (void *). + + \note This function does not check the length of the strings \a + vs1 and \a vs2. If the strings are not NULL terminated, the + behavior is undefined. + */ +KHMEXP khm_int32 hash_string_comp(const void *vs1, const void *vs2); + +/*@}*/ +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/util/mstring.c b/krb5-1-6/src/windows/identity/util/mstring.c new file mode 100644 index 000000000..176afc46c --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/mstring.c @@ -0,0 +1,512 @@ +/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies +* of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<mstring.h> +#include<kherror.h> +#include<strsafe.h> +#include<stdlib.h> + +#define TRUE 1 +#define FALSE 0 + +KHMEXP khm_int32 KHMAPI +multi_string_init(wchar_t * ms, + khm_size cb_ms) { + if (!ms || cb_ms < sizeof(wchar_t) * 2) + return KHM_ERROR_INVALID_PARAM; + + memset(ms, 0, cb_ms); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +multi_string_append(wchar_t * ms, + khm_size * pcb_ms, + const wchar_t * str) +{ + wchar_t * s; + size_t cch_s; + size_t cch_t; + size_t cch_r; + + if(!ms || !pcb_ms || !str) + return KHM_ERROR_INVALID_PARAM; + + if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)) || cch_s == 0) + return KHM_ERROR_INVALID_PARAM; + cch_s++; + + s = ms; + + while(*s && ((s - ms) < KHM_MAXCCH_STRING)) { + if(FAILED(StringCchLength(s, KHM_MAXCB_STRING, &cch_t))) + return KHM_ERROR_INVALID_PARAM; + s += cch_t + 1; + } + + if(*s || (s - ms) >= KHM_MAXCCH_STRING) { + return KHM_ERROR_INVALID_PARAM; + } + + /* now s points to the second NULL of the terminating double NULL */ + + cch_r = ((s - ms) + cch_s + 1) * sizeof(wchar_t); + if(*pcb_ms < cch_r) { + *pcb_ms = cch_r; + return KHM_ERROR_TOO_LONG; + } + + *pcb_ms = cch_r; + + StringCchCopy(s, cch_s, str); + s += cch_s; + *s = 0; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +multi_string_prepend(wchar_t * ms, + khm_size * pcb_ms, + const wchar_t * str) +{ + size_t cch_s; + size_t cch_t; + size_t cch_r; + khm_size cb_r; + + if(!ms || !pcb_ms || !str) + return KHM_ERROR_INVALID_PARAM; + + if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s)) || cch_s == 0) + return KHM_ERROR_INVALID_PARAM; + cch_s++; + + if(KHM_FAILED(multi_string_length_cch(ms, + KHM_MAXCCH_STRING, + &cch_r))) + return KHM_ERROR_INVALID_PARAM; + + cch_t = cch_s + cch_r; + cb_r = cch_t * sizeof(wchar_t); + + if (*pcb_ms < cb_r) { + *pcb_ms = cb_r; + return KHM_ERROR_TOO_LONG; + } + + memmove(ms + cch_s, ms, cch_r * sizeof(wchar_t)); + memcpy(ms, str, cch_s * sizeof(wchar_t)); + + *pcb_ms = cb_r; + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +multi_string_delete(wchar_t * ms, + const wchar_t * str, + const khm_int32 flags) +{ + wchar_t * s; + wchar_t * n; + wchar_t * e; + size_t cch; + + if(!ms || !str) + return KHM_ERROR_INVALID_PARAM; + + s = multi_string_find(ms, str, flags); + if(!s) + return KHM_ERROR_NOT_FOUND; + + e = s; + n = NULL; + while(*e && (e - s) < KHM_MAXCCH_STRING) { + if(FAILED(StringCchLength(e, KHM_MAXCCH_STRING, &cch))) + return KHM_ERROR_INVALID_PARAM; + e += cch + 1; + + if(!n) + n = e; + } + + if(*e || (e - s) >= KHM_MAXCCH_STRING) + return KHM_ERROR_INVALID_PARAM; + + if(e == s) + return KHM_ERROR_SUCCESS; + + memmove((void *) s, (void *) n, ((e - n) + 1) * sizeof(wchar_t)); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP wchar_t * KHMAPI +multi_string_find(const wchar_t * ms, + const wchar_t * str, + const khm_int32 flags) +{ + const wchar_t *s; + size_t cch; + size_t cch_s; + + if(!ms || !str) + return NULL; + + if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch_s))) + return NULL; + + s = ms; + + while(*s && (s - ms) < KHM_MAXCCH_STRING) { + if(FAILED(StringCchLength(s, KHM_MAXCCH_STRING, &cch))) + return NULL; + /* cch++ at end */ + + if(flags & KHM_PREFIX) { + if(((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch_s)) || + (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch_s))) + return (wchar_t *) s; + } else { + if((cch == cch_s) && + ((flags & KHM_CASE_SENSITIVE) && !wcsncmp(s, str, cch)) || + (!(flags & KHM_CASE_SENSITIVE) && !_wcsnicmp(s, str, cch))) + return (wchar_t *) s; + } + + s += cch + 1; + } + + return NULL; +} + +KHMEXP khm_int32 KHMAPI +multi_string_to_csv(wchar_t * csvbuf, + khm_size * pcb_csvbuf, + const wchar_t * ms) +{ + size_t cb; + size_t cbt; + const wchar_t * t; + wchar_t * d; + + if(!pcb_csvbuf || !ms) + return KHM_ERROR_INVALID_PARAM; + + /* dry run */ + cbt = 0; + t = ms; + while(*t && cbt <= KHM_MAXCB_STRING) { + khm_boolean quotes = FALSE; + + if(FAILED(StringCbLength(t, KHM_MAXCB_STRING, &cb))) + return KHM_ERROR_INVALID_PARAM; + cb += sizeof(wchar_t); + + cbt += cb; + + if(wcschr(t, L',')) + quotes = TRUE; + + d = (wchar_t *) t; + while(d = wcschr(d, L'"')) { + cbt += sizeof(wchar_t); /* '"'-> '""' */ + d++; + quotes = TRUE; + } + + if(quotes) + cbt += 2*sizeof(wchar_t); /* make room for quotes */ + + t += cb / sizeof(wchar_t); + } + + if(cbt > KHM_MAXCB_STRING) + return KHM_ERROR_INVALID_PARAM; + + /* happens if the multi string contained no strings */ + if(cbt == 0) + cbt = sizeof(wchar_t); + + if(!csvbuf || *pcb_csvbuf < cbt) + { + *pcb_csvbuf = cbt; + return KHM_ERROR_TOO_LONG; + } + + *pcb_csvbuf = cbt; + + /* wet run */ + t = ms; + d = csvbuf; + *csvbuf = 0; + while(*t) { + const wchar_t * s; + + StringCbLength(t, KHM_MAXCB_STRING, &cb); + cb += sizeof(wchar_t); + + if(d != csvbuf) + *d++ = L','; + if(wcschr(t, L',') || wcschr(t, L'"')) { + *d++ = L'"'; + s = t; + while(*s) { + if(*s == L'"') { + *d++ = L'"'; + *d++ = L'"'; + } else + *d++ = *s; + s++; + } + *d++ = L'"'; + *d = 0; + } else { + StringCbCopy(d, cbt - ((d - csvbuf) * sizeof(wchar_t)), t); + d += cb / sizeof(wchar_t) - 1; + } + t += cb / sizeof(wchar_t); + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +csv_to_multi_string(wchar_t * ms, + khm_size * pcb_ms, + const wchar_t * csv) +{ + const wchar_t * t; + wchar_t * p; + size_t cchr; + int field = 1; + + + if(!pcb_ms || !csv) + return KHM_ERROR_INVALID_PARAM; + + cchr = 0; + + /* dry run */ + t = csv; + while(*t && (t - csv) < KHM_MAXCCH_STRING) { + if(field && *t == L'"') { + t++; + while(*t && (t - csv) < KHM_MAXCCH_STRING) { + if(*t == L'"') { + t++; + if(*t != L'"') + break; + } + cchr++; + t++; + } + } + + if(*t) { + cchr++; + if(*t == L',') + field = 1; + else + field = 0; + + t++; + } + } + + if((t - csv) >= KHM_MAXCCH_STRING) + return KHM_ERROR_INVALID_PARAM; + + cchr++; /* last string ends */ + cchr++; /* double NULL */ + + if(!ms || *pcb_ms < (cchr * sizeof(wchar_t))) { + *pcb_ms = cchr * sizeof(wchar_t); + return KHM_ERROR_TOO_LONG; + } + + /* wet run */ + t = csv; + p = ms; + field = 1; + while(*t) { + if(field && *t == L'"') { + t++; + while(*t) { + if(*t == L'"') { + t++; + if(*t != L'"') + break; + } + *p++ = *t; + t++; + } + } + + if(*t == L',') { + *p++ = 0; + field = 1; + t++; + } else if(*t) { + *p++ = *t; + field = 0; + t++; + } + } + + *p++ = 0; /* last string ends */ + *p++ = 0; /* double NULL */ + + *pcb_ms = (p - ms) * sizeof(wchar_t); + + return KHM_ERROR_SUCCESS; +} + +KHMEXP wchar_t * KHMAPI +multi_string_next(const wchar_t * str) +{ + size_t cch; + + if(*str) { + if(FAILED(StringCchLength(str, KHM_MAXCCH_STRING, &cch))) + return NULL; + str += cch + 1; + if(*str) + return (wchar_t *) str; + else + return NULL; + } else { + return NULL; + } +} + +KHMEXP khm_size KHMAPI +multi_string_length_n(const wchar_t * str) +{ + size_t n = 0; + const wchar_t * c = str; + + while(c) { + n++; + c = multi_string_next(c); + } + + return n; +} + +KHMEXP khm_int32 KHMAPI +multi_string_length_cb(const wchar_t * str, + khm_size max_cb, + khm_size * len_cb) +{ + khm_size cch; + khm_int32 rv; + + rv = multi_string_length_cch(str, max_cb / sizeof(wchar_t), &cch); + + if(KHM_FAILED(rv)) + return rv; + + if(len_cb) + *len_cb = cch * sizeof(wchar_t); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +multi_string_length_cch(const wchar_t * str, + khm_size max_cch, + khm_size * len_cch) +{ + const wchar_t * s; + khm_size cch; + size_t tcch; + + if(!str) + return KHM_ERROR_INVALID_PARAM; + + s = str; + cch = 0; + while(*s && (cch < max_cch)) { + if(FAILED(StringCchLength(s, max_cch, &tcch))) + return KHM_ERROR_TOO_LONG; + cch += ++tcch; + s += tcch; + } + + if(cch >= max_cch) + return KHM_ERROR_TOO_LONG; + + if(len_cch) { + *len_cch = ++cch; + } + + return KHM_ERROR_SUCCESS; +} + +KHMEXP khm_int32 KHMAPI +multi_string_copy_cb(wchar_t * s_dest, + khm_size max_cb_dest, + const wchar_t * src) +{ + khm_size cb_dest; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!s_dest) + return KHM_ERROR_INVALID_PARAM; + + rv = multi_string_length_cb(src, max_cb_dest, &cb_dest); + if(KHM_FAILED(rv)) + return rv; + + memmove(s_dest, src, cb_dest); + + return rv; +} + +KHMEXP khm_int32 KHMAPI +multi_string_copy_cch(wchar_t * s_dest, + khm_size max_cch_dest, + const wchar_t * src) +{ + khm_size cch_dest; + khm_int32 rv = KHM_ERROR_SUCCESS; + + if(!s_dest) + return KHM_ERROR_INVALID_PARAM; + + rv = multi_string_length_cch(src, max_cch_dest, &cch_dest); + if(KHM_FAILED(rv)) + return rv; + + memmove(s_dest, src, cch_dest * sizeof(wchar_t)); + + return rv; +} diff --git a/krb5-1-6/src/windows/identity/util/mstring.h b/krb5-1-6/src/windows/identity/util/mstring.h new file mode 100644 index 000000000..497cb777d --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/mstring.h @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_MSTRING_H +#define __KHIMAIRA_MSTRING_H + +#include<khdefs.h> + +/*! \addtogroup util + @{ */ + +/*! \defgroup util_mstring Multi String and CSV functions + @{*/ + +#define KHM_PREFIX 8 + +#define KHM_CASE_SENSITIVE 16 + +#define KHM_MAXCCH_STRING 16384 + +#define KHM_MAXCB_STRING (KHM_MAXCCH_STRING * sizeof(wchar_t)) + +/*! \brief Initialize a multi-string + */ +KHMEXP khm_int32 KHMAPI +multi_string_init(wchar_t * ms, + khm_size cb_ms); + +/*! \brief Prepend a string to a multi string + + Adds the string \a str to the beginning of multi-string \a ms. + + \param[in,out] ms The multi-string to be modified. + + \param[in,out] pcb_ms A pointer to the size of the multistring. + On entry this specifies the size of the buffer pointed to by + \a ms. If the call is successful, on exit this will receive + the new size of the multi string in bytes. If the buffer is + insufficient, the function will return KHM_ERROR_TOO_LONG and + set this to the required size of the buffer in bytes. + + \param[in] str The string to prepend to \a ms. This cannot be + longer than KHM_MAXCCH_STRING in characters including the + terminating NULL. + */ +KHMEXP khm_int32 KHMAPI +multi_string_prepend(wchar_t * ms, + khm_size * pcb_ms, + const wchar_t * str); + +/*! \brief Append a string to a multi-string + + Appends the string specified by \a str to the multi string + specified by \a ms. The size of the multi string in characters + including terminating NULLs after appending \a str can not exceed + KHM_MAXCCH_STRING. + + \param[in] ms The buffer containing the multi string + + \param[in,out] pcb_ms Points to a khm_int32 indicating the size of + the buffer pointed to by \a ms. On entry this contains the + size (in bytes) of the buffer pointed to by \a ms. On exit, + contains the new size of the multi string in bytes. + + \param[in] str The string to append to the multi string. This + string cannot be NULL or an empty (zero length) string. The + length of \a str cannot exceed KHM_MAXCCH_STRING in + characters including terminating NULL. + + \retval KHM_ERROR_SUCCESS The string was appended to the multi string + + \retval KHM_ERROR_TOO_LONG The buffer pointed to by \a ms was + insufficient. The required size of the buffer is in \a pcb_ms + + \retval KHM_ERROR_INVALID_PARAM One of more of the parameters were invalid. + */ +KHMEXP khm_int32 KHMAPI +multi_string_append(wchar_t * ms, + khm_size * pcb_ms, + const wchar_t * str); + +/*! \brief Deletes a string from a multi string + + Deletes the string specified by \a str from the multi string + specified by \a ms. How the string is matched to the strings in + \a ms is determined by \a flags. If more than one match is found, + then only the first match is deleted. + + \param[in] ms The multi string to modify. The length of the multi + string in characters cannot exceed KHM_MAXCCH_STRING. + + \param[in] str The string to search for + + \param[in] flags How \a str is to be matched to existing strings + in \a ms. This could be a combination of KHM_PREFIX and + KHM_CASE_SENSITIVE. If KHM_PREFIX is used, then \a ms is + searched for a string that begins with \a str. Otherwise, \a + str must match the an entire string in the multi string. If + KHM_CASE_SENSITIVE is specified, then a case sensitive match + is performed. The defualt is to use a case insensitive + search. + + \retval KHM_ERROR_SUCCESS A string was matched and deleted from \a ms + + \retval KHM_ERROR_NOT_FOUND No matches were found + + \retval KHM_ERROR_INVALID_PARAM One or more parameters were incorrect. + + \note The search for the existing string is done with + multi_string_find() + */ +KHMEXP khm_int32 KHMAPI +multi_string_delete(wchar_t * ms, + const wchar_t * str, + const khm_int32 flags); + +/*! \brief Search a multi string for a string + + Searches the string specified by \a ms for a string that matches + \a str. How the match is performed is determined by \a flags. + Returns a poitner to the start of the matched string in \a ms. If + more than one string in \a ms matches \a str, then only the first + match is returned. + + \param[in] ms The multi string to search in. The length of the + multi string cannot exceed KHM_MAXCCH_STRING in characters. + + \param[in] str The string to search for + + \param[in] flags How \a str is to be matched to existing strings + in \a ms. This could be a combination of KHM_PREFIX and + KHM_CASE_SENSITIVE. If KHM_PREFIX is used, then \a ms is + searched for a string that begins with \a str. Otherwise, \a + str must match the an entire string in the multi string. If + KHM_CASE_SENSITIVE is specified, then a case sensitive match + is performed. The defualt is to use a case insensitive + search. + + \return A pointer to the start of the first matched string or + NULL if no matches were found. + + */ +KHMEXP wchar_t * KHMAPI +multi_string_find(const wchar_t * ms, + const wchar_t * str, + const khm_int32 flags); + +/*! \brief Convert a multi string to CSV + + Converts a multi string to a comma separated value string based on + the following rules. + + - Each string in the multi string is treated an individual field + + - A field is quoted if it has double quotes or commas + + - Double quotes within quoted fields are escaped by two + consecutive double quotes. + + For example: + + \code + multi_string = L"foo\0bar\0baz,quux\0ab\"cd\0"; + csv_string = L"foo,bar,\"baz,quux\",\"ab\"\"cd\""; + \endcode + + If multi_string_to_csv() is called on \a multi_string above, + you would obtain \a csv_string. + + \param[out] csvbuf The buffer to place the CSV string in. Can be + NULL if only teh size of the needed buffer is required. + + \param[in,out] pcb_csvbuf On entry, points to a khm_int32 that + holds the size of the buffer pointed to by \a csvbuf. On + exit, gets the number of bytes writted to \a csvbuf or the + required size of \a csvbuf if the buffer is too small or \a + csvbuf is NULL. + + \param[in] ms The mutli string to convert to a CSV. + + \retval KHM_ERROR_SUCCESS The multi string was successfully + converted to a CSV string. The number of bytes written is in + \a pcb_csvbuf. The count includes the terminating NULL. + + \retval KHM_ERROR_TOO_LONG The buffer was too small or \a csvbuf + was NULL. The required number of bytes in the buffer is in \a + pcb_csvbuf. + + \retval KHM_ERROR_INVALID_PARAM One or more parameters were ivnalid. + + \see csv_to_multi_string() +*/ +KHMEXP khm_int32 KHMAPI +multi_string_to_csv(wchar_t * csvbuf, + khm_size * pcb_csvbuf, + const wchar_t * ms); + +/*! \brief Converts a CSV to a multi string + + Undoes what multi_string_to_csv() does. + + \param[out] ms The buffer that recieves the multi string. This + can be NULL if only the size of the buffer is requried. + + \param[in,out] pcb_ms On entry contains the number of bytes ni the + buffer poitned to by \a ms. On exit contains the number of + bytes that were copied to \a ms including terminating NULLs, + or if the buffer was too small or \a ms was NULL, holds the + size in bytes of the requied buffer. + + \param[in] csv The CSV string. + + \retval KHM_ERROR_SUCCESS The CSV string was successfully + converted. The number of bytes written is in \a pcb_ms. + + \retval KHM_ERROR_TOO_LONG The provided buffer was too small or \a + ms was NULL. The required size of the buffer in bytes is in \a + pcb_ms. + + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid. + + */ +KHMEXP khm_int32 KHMAPI +csv_to_multi_string(wchar_t * ms, + khm_size * pcb_ms, + const wchar_t * csv); + +/*! \brief Get the next string in a multi string + + When \a str is pointing to a string that is in a multi string, + this function returns a pointer to the next string in the multi + string. + + Typically, one would start by having \a str point to the start of + the multi string (which is the first string in the multi string), + and then call this function repeatedly, until it returns NULL, at + which point the end of the multi string has been reached. + + \param[in] str Pointer to a string in a multi string. Each string + in a multi string cannot exceed KHM_MAXCCH_STRING in charaters + including the terminating NULL. + + \return A pointer to the start of the next string in the multi + string or NULL if there is no more strings. + */ +KHMEXP wchar_t * KHMAPI +multi_string_next(const wchar_t * str); + +/*! \brief Get the length of a multi string in bytes + + The returned length includes the trailing double \a NULL and any + other \a NULL inbetween. + + \param[in] str Pointer to a multi string. + \param[in] max_cb Maximum size that the str can be. This can not + be larger than KHM_MAXCB_STRING. + \param[out] len_cb The length of the string in bytes if the call + is successful. + + \retval KHM_ERROR_SUCCESS The length of the string is in \a len_cb + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_TOO_LONG The multi string is longer than \a + max_cb bytes. + */ +KHMEXP khm_int32 KHMAPI +multi_string_length_cb(const wchar_t * str, + khm_size max_cb, + khm_size * len_cb); + +/*! \brief Get the length of a multi string in characters + + The returned length includes the trailing double \a NULL and any + other \a NULL inbetween. + + \param[in] str Pointer to a multi string. + \param[in] max_cch Maximum size that the str can be. This can not + be larger than KHM_MAXCCH_STRING. + \param[out] len_cch The length of the string in characters if the call + is successful. + + \retval KHM_ERROR_SUCCESS The length of the string is in \a len_cch + \retval KHM_ERROR_INVALID_PARAM One or more parameters were invalid + \retval KHM_ERROR_TOO_LONG The multi string is longer than \a + max_cch characters. + */ +KHMEXP khm_int32 KHMAPI +multi_string_length_cch(const wchar_t * str, + khm_size max_cch, + khm_size * len_cch); + +/*! \brief Get the number of strings in a multi string + */ +KHMEXP khm_size KHMAPI +multi_string_length_n(const wchar_t * str); + +/*! \brief Copy a multi string with byte counts + + Copy a multi string from one location to another. + + \param[out] s_dest Receives a copy of the multi string + \param[in] max_cb_dest Number of bytes in the buffer pointed to by + \a s_dest. + \param[in] src The source multi string + + \retval KHM_ERROR_SUCCESS The multi string was copied successfully + \retval KHM_ERROR_INVALID_PARAM One or more parameters were + invalid. + \retval KHM_ERROR_TOO_LONG The size of the destination buffer was + insufficient. + */ +KHMEXP khm_int32 KHMAPI +multi_string_copy_cb(wchar_t * s_dest, + khm_size max_cb_dest, + const wchar_t * src); + +/*! \brief Copy a multi string with character count + + Copy a multi string from one location to another. + + \param[out] s_dest Receives a copy of the multi string + \param[in] max_cb_dest Number of characters in the buffer pointed + to by \a s_dest. + \param[in] src The source multi string + + \retval KHM_ERROR_SUCCESS The multi string was copied successfully + \retval KHM_ERROR_INVALID_PARAM One or more parameters were + invalid. + \retval KHM_ERROR_TOO_LONG The size of the destination buffer was + insufficient. + */ +KHMEXP khm_int32 KHMAPI +multi_string_copy_cch(wchar_t * s_dest, + khm_size max_cch_dest, + const wchar_t * src); + +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/util/perfstat.c b/krb5-1-6/src/windows/identity/util/perfstat.c new file mode 100644 index 000000000..aece7e273 --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/perfstat.c @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<windows.h> +#include<utils.h> +#include<crtdbg.h> +#include<malloc.h> +#include<stdio.h> +#include<strsafe.h> +#include<assert.h> + +#define HASHSIZE 1151 +#define ALLOCBLOCK 1024 + +#define HASHPTR(p) (((size_t) (p)) % HASHSIZE) + +typedef struct tag_allocation { + const char * file; + int line; + size_t size; + void * ptr; +#ifdef _WIN32 + DWORD thread; +#endif + + LDCL(struct tag_allocation); +} allocation; + +static allocation * ht[HASHSIZE]; + +static allocation * next_alloc = NULL; +static size_t idx_next_alloc = 0; +static allocation * free_alloc = NULL; + +typedef struct tag_thread_info { +#ifdef _WIN32 + DWORD thread; +#else +#error Unsupported platform +#endif + wchar_t name[128]; + wchar_t creator[128]; + + const char * file; + int line; + + LDCL(struct tag_thread_info); +} thread_info; + +static thread_info * threads = NULL; + +static hashtable fn_hash; + +static CRITICAL_SECTION cs_alloc; +static LONG ctr = 0; +static int perf_ready = 0; + +static DWORD init_thread = 0; + +#ifdef _DEBUG +/* */ +#define OPS_TILL_MEM_CHECK 1024 +static int ops_till_mem_check = OPS_TILL_MEM_CHECK; +#endif + +#define _PERF_BLOCK_TYPE(t) (_CLIENT_BLOCK | ((t) << 16)) +#define _RMEM_BLOCK _PERF_BLOCK_TYPE(0) +#define _PERF_BLOCK _PERF_BLOCK_TYPE(1) + +static khm_int32 hash_stringA(const void * vs) { + /* DJB algorithm */ + + khm_int32 hv = 13331; + char * c; + + for (c = (char *) vs; *c; c++) { + hv = ((hv << 5) + hv) + (khm_int32) *c; + } + + return (hv & KHM_INT32_MAX); +} + +static khm_int32 hash_string_compA(const void * vs1, + const void * vs2) { + return strcmp((const char *) vs1, (const char *) vs2); +} + +static void perf_once(void) { + if (InterlockedIncrement(&ctr) == 1) { + InitializeCriticalSection(&cs_alloc); + ZeroMemory(ht, sizeof(ht)); + + next_alloc = _malloc_dbg(sizeof(allocation) * ALLOCBLOCK, _PERF_BLOCK, + __FILE__, __LINE__); + assert(next_alloc); + idx_next_alloc = 0; + free_alloc = NULL; + + ZeroMemory(&fn_hash, sizeof(fn_hash)); + fn_hash.n = 13; + fn_hash.hash = hash_stringA; + fn_hash.comp = hash_string_compA; + fn_hash.bins = _calloc_dbg(fn_hash.n, sizeof(hash_bin *), + _PERF_BLOCK, __FILE__, __LINE__); + + perf_ready = 1; + } else { + DWORD this_thread = GetCurrentThreadId(); + + while(!perf_ready && + init_thread != this_thread) { + Sleep(0); /* relinquish control to the thread + that is initializing the alloc + data. */ + } + } +} + +static allocation * get_allocation(void) { + allocation * a; + + LPOP(&free_alloc, &a); + if (!a) { + if (idx_next_alloc == ALLOCBLOCK) { + next_alloc = _malloc_dbg(sizeof(allocation) * ALLOCBLOCK, + _PERF_BLOCK, + __FILE__, __LINE__); + assert(next_alloc); + idx_next_alloc = 0; + } + + a = &next_alloc[idx_next_alloc]; + idx_next_alloc++; + } + + return a; +} + +#define MAXCB_STR 32768 + +KHMEXP wchar_t * +perf_wcsdup(const char * file, int line, const wchar_t * str) { + size_t cb; + wchar_t * dest; + + if (FAILED(StringCbLength(str, MAXCB_STR, &cb))) + return NULL; + cb += sizeof(wchar_t); + + dest = (wchar_t *) perf_malloc(file, line, cb); + StringCbCopy(dest, cb, str); + + return dest; +} + +KHMEXP char * +perf_strdup(const char * file, int line, const char * str) { + size_t cb; + char * dest; + + if (FAILED(StringCbLengthA(str, MAXCB_STR, &cb))) + return NULL; + cb += sizeof(char); + + dest = (char *) perf_malloc(file, line, cb); + StringCbCopyA(dest, cb, str); + + return dest; +} + +KHMEXP void * +perf_calloc(const char * file, int line, size_t num, size_t size) { + void * ptr; + size_t tsize; + + tsize = num * size; + + ptr = perf_malloc(file,line,tsize); + + if (ptr) { + ZeroMemory(ptr, tsize); + } + + return ptr; +} + +KHMEXP void * +perf_malloc(const char * file, int line, size_t s) { + allocation * a; + void * ptr; + size_t h; + char * fn_copy = NULL; + + perf_once(); + + assert(s > 0); + + EnterCriticalSection(&cs_alloc); + a = get_allocation(); + + ptr = _malloc_dbg(s, _RMEM_BLOCK, file, line); + + assert(ptr); /* TODO: handle this gracefully */ + + if (file[0] == '.' && file[1] == '\\') + file += 2; + + fn_copy = hash_lookup(&fn_hash, file); + if (fn_copy == NULL) { + + size_t cblen = 0; + if (FAILED(StringCbLengthA(file, MAX_PATH * sizeof(char), + &cblen))) + fn_copy = NULL; + else { + fn_copy = _malloc_dbg(cblen + sizeof(char), _PERF_BLOCK, + __FILE__, __LINE__); + if (fn_copy) { + hash_bin * b; + int hv; + + StringCbCopyA(fn_copy, cblen + sizeof(char), file); + + hv = fn_hash.hash(fn_copy) % fn_hash.n; + + b = _malloc_dbg(sizeof(*b), _PERF_BLOCK, + __FILE__, __LINE__); + b->data = fn_copy; + b->key = fn_copy; + LINIT(b); + LPUSH(&fn_hash.bins[hv], b); + } + } + } + + a->file = fn_copy; + a->line = line; + a->size = s; + a->ptr = ptr; +#ifdef _WIN32 + a->thread = GetCurrentThreadId(); +#endif + + h = HASHPTR(ptr); + + LPUSH(&ht[h], a); + +#ifdef _DEBUG + if (-- ops_till_mem_check <= 0) { + assert(_CrtCheckMemory()); + ops_till_mem_check = OPS_TILL_MEM_CHECK; + } +#endif + + LeaveCriticalSection(&cs_alloc); + + return ptr; +} + +KHMEXP void * +perf_realloc(const char * file, int line, void * data, size_t s) { + void * n_data; + allocation * a; + size_t h; + + if (data == NULL) + return perf_malloc(file, line, s); + + perf_once(); + h = HASHPTR(data); + + n_data = _realloc_dbg(data, s, _RMEM_BLOCK, + __FILE__, __LINE__); + + assert(n_data); + + EnterCriticalSection(&cs_alloc); + for (a = ht[h]; a; a = LNEXT(a)) { + if (a->ptr == data) + break; + } + + assert(a); + + LDELETE(&ht[h], a); + + a->size = s; + a->ptr = n_data; + + h = HASHPTR(n_data); + LPUSH(&ht[h], a); + +#ifdef _DEBUG + if (-- ops_till_mem_check <= 0) { + assert(_CrtCheckMemory()); + ops_till_mem_check = OPS_TILL_MEM_CHECK; + } +#endif + + LeaveCriticalSection(&cs_alloc); + + return n_data; +} + +KHMEXP void +perf_free (void * b) { + size_t h; + allocation * a; + + perf_once(); + h = HASHPTR(b); + + EnterCriticalSection(&cs_alloc); + for(a = ht[h]; a; a = LNEXT(a)) { + if (a->ptr == b) + break; + } + + assert(a); + + if (a) { + LDELETE(&ht[h], a); + LPUSH(&free_alloc, a); + + _free_dbg(b, _RMEM_BLOCK); + } + +#ifdef _DEBUG + if (-- ops_till_mem_check <= 0) { + assert(_CrtCheckMemory()); + ops_till_mem_check = OPS_TILL_MEM_CHECK; + } +#endif + + LeaveCriticalSection(&cs_alloc); +} + +KHMEXP void KHMAPI +perf_dump(FILE * f) { + size_t i; + allocation * a; + size_t total = 0; + thread_info * t; + + perf_once(); + + EnterCriticalSection(&cs_alloc); + + fprintf(f, "p00\t*** Threads ***\n"); + fprintf(f, "p00\tFile\tLine\tThread\tName\tCreated by\n"); + + for (t = threads; t; t = LNEXT(t)) { + fprintf(f, "p01\t%s\t%6d\t%6d\t%S\t%S\n", + t->file, t->line, t->thread, + t->name, t->creator); + } + + fprintf(f, "p02\t--- End Threads ---\n"); + + fprintf(f, "p10\t*** Leaked allocations list ***\n"); + fprintf(f, "p11\tFile\tLine\tThread\tSize\tAddress\n"); + + for (i=0; i < HASHSIZE; i++) { + for (a = ht[i]; a; a = LNEXT(a)) { + fprintf(f, "p12\t%s\t%6d\t%6d\t%6d\t0x%p\n", a->file, a->line, + a->thread, a->size, a->ptr); + total += a->size; + } + } + + fprintf(f, "p20\t----------------------------------------\n"); + fprintf(f, "p21\tTotal\t\t%d\n", total); + fprintf(f, "p22\t----------------- End ------------------\n"); + + LeaveCriticalSection(&cs_alloc); +} + +KHMEXP void +perf_set_thread_desc(const char * file, int line, + const wchar_t * name, const wchar_t * creator) { + thread_info * t; + char * fn_copy; + + perf_once(); + + t = malloc(sizeof(*t)); + ZeroMemory(t, sizeof(*t)); + +#ifdef _WIN32 + t->thread = GetCurrentThreadId(); +#else +#error Unsupported platform +#endif + + StringCbCopy(t->name, sizeof(t->name), name); + if (creator) + StringCbCopy(t->creator, sizeof(t->creator), creator); + + if (file[0] == '.' && file[1] == '\\') + file += 2; + + EnterCriticalSection(&cs_alloc); + + fn_copy = hash_lookup(&fn_hash, file); + if (fn_copy == NULL) { + size_t cblen = 0; + if (FAILED(StringCbLengthA(file, MAX_PATH * sizeof(char), + &cblen))) + fn_copy = NULL; + else { + fn_copy = malloc(cblen + sizeof(char)); + if (fn_copy) { + hash_bin * b; + int hv; + + StringCbCopyA(fn_copy, cblen + sizeof(char), file); + + hv = fn_hash.hash(fn_copy) % fn_hash.n; + + b = malloc(sizeof(*b)); + b->data = fn_copy; + b->key = fn_copy; + LINIT(b); + LPUSH(&fn_hash.bins[hv], b); + } + } + } + + t->file = fn_copy; + t->line = line; + + LPUSH(&threads, t); + LeaveCriticalSection(&cs_alloc); +} diff --git a/krb5-1-6/src/windows/identity/util/perfstat.h b/krb5-1-6/src/windows/identity/util/perfstat.h new file mode 100644 index 000000000..0f356583c --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/perfstat.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_PERFSTAT_H +#define __KHIMAIRA_PERFSTAT_H + +#include<khdefs.h> + +#ifdef DEBUG +#define PMALLOC(s) perf_malloc(__FILE__,__LINE__,s) +#define PCALLOC(n,s) perf_calloc(__FILE__,__LINE__,n,s) +#define PREALLOC(d,s) perf_realloc(__FILE__,__LINE__,d,s) +#define PFREE(p) perf_free(p) +#define PDUMP(f) perf_dump(f) +#define PWCSDUP(s) perf_wcsdup(__FILE__,__LINE__,s) +#define PSTRDUP(s) perf_strdup(__FILE__,__LINE__,s) +#define PDESCTHREAD(n,c) perf_set_thread_desc(__FILE__,__LINE__,n,c); +#else +#define PMALLOC(s) malloc(s) +#define PCALLOC(n,s) calloc(n,s) +#define PREALLOC(d,s) realloc(d,s) +#define PFREE(p) free(p) +#define PDUMP(f) ((void) 0) +#define PWCSDUP(s) _wcsdup(s) +#define PSTRDUP(s) strdup(s) +#define PDESCTHREAD(n,c) +#endif + +KHMEXP void * +perf_malloc(const char * file, int line, size_t s); + +KHMEXP void * +perf_realloc(const char * file, int line, void * data, size_t s); + +KHMEXP void +perf_free (void * b); + +KHMEXP wchar_t * +perf_wcsdup(const char * file, int line, const wchar_t * str); + +KHMEXP char * +perf_strdup(const char * file, int line, const char * str); + +KHMEXP void * +perf_calloc(const char * file, int line, size_t num, size_t size); + +KHMEXP void +perf_set_thread_desc(const char * file, int line, + const wchar_t * name, const wchar_t * creator); + +#endif diff --git a/krb5-1-6/src/windows/identity/util/sync.c b/krb5-1-6/src/windows/identity/util/sync.c new file mode 100644 index 000000000..ba20424c4 --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/sync.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define _NIMLIB_ + +#include<windows.h> +#include<sync.h> +#include<assert.h> + +#define LOCK_OPEN 0 +#define LOCK_READING 1 +#define LOCK_WRITING 2 + +KHMEXP void KHMAPI InitializeRwLock(PRWLOCK pLock) +{ + pLock->locks = 0; + pLock->status = LOCK_OPEN; + InitializeCriticalSection(&(pLock->cs)); + pLock->writewx = CreateEvent(NULL, + FALSE, /* Manual reset */ + TRUE, /* Initial state */ + NULL); + pLock->readwx = CreateEvent(NULL, + TRUE, /* Manual reset */ + TRUE, /* Initial state */ + NULL); +} + +KHMEXP void KHMAPI DeleteRwLock(PRWLOCK pLock) +{ + EnterCriticalSection(&pLock->cs); + + CloseHandle(pLock->readwx); + CloseHandle(pLock->writewx); + pLock->readwx = NULL; + pLock->writewx = NULL; + + LeaveCriticalSection(&pLock->cs); + DeleteCriticalSection(&(pLock->cs)); +} + +KHMEXP void KHMAPI LockObtainRead(PRWLOCK pLock) +{ + while(1) { + WaitForSingleObject(pLock->readwx, INFINITE); + EnterCriticalSection(&pLock->cs); + if(pLock->status == LOCK_WRITING) { + LeaveCriticalSection(&(pLock->cs)); + continue; + } else + break; + } + pLock->locks ++; + pLock->status = LOCK_READING; + ResetEvent(pLock->writewx); + LeaveCriticalSection(&(pLock->cs)); +} + +KHMEXP void KHMAPI LockReleaseRead(PRWLOCK pLock) +{ + EnterCriticalSection(&(pLock->cs)); + assert(pLock->status == LOCK_READING); + pLock->locks--; + if(!pLock->locks) { + pLock->status = LOCK_OPEN; + SetEvent(pLock->readwx); + SetEvent(pLock->writewx); + } + LeaveCriticalSection(&(pLock->cs)); +} + +KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock) +{ + EnterCriticalSection(&(pLock->cs)); + if(pLock->status == LOCK_WRITING && + pLock->writer == GetCurrentThreadId()) { + pLock->locks++; + LeaveCriticalSection(&(pLock->cs)); + return; + } + LeaveCriticalSection(&(pLock->cs)); + while(1) { + WaitForSingleObject(pLock->writewx, INFINITE); + EnterCriticalSection(&(pLock->cs)); + if(pLock->status == LOCK_OPEN) + break; + LeaveCriticalSection(&(pLock->cs)); + } + pLock->status = LOCK_WRITING; + pLock->locks++; + pLock->writer = GetCurrentThreadId(); + ResetEvent(pLock->readwx); + ResetEvent(pLock->writewx); + LeaveCriticalSection(&(pLock->cs)); +} + +KHMEXP void KHMAPI LockReleaseWrite(PRWLOCK pLock) +{ + EnterCriticalSection(&(pLock->cs)); + assert(pLock->status == LOCK_WRITING); + pLock->locks--; + if(!pLock->locks) { + pLock->status = LOCK_OPEN; + pLock->writer = 0; + SetEvent(pLock->readwx); + SetEvent(pLock->writewx); + } + LeaveCriticalSection(&(pLock->cs)); +} diff --git a/krb5-1-6/src/windows/identity/util/sync.h b/krb5-1-6/src/windows/identity/util/sync.h new file mode 100644 index 000000000..a95db207e --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/sync.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_SYNC_H +#define __KHIMAIRA_SYNC_H + +#include<khdefs.h> + +/*! \addtogroup util + @{ */ + +/*! \defgroup util_sync Synchronization + @{*/ + +/*! \brief A read/write lock + + A classic read/write lock. Allows multiple readers or a single + writer to access a protected object. Readers will wait for any + pending writer to release the lock, while a writer will wait for + any pending readers to release the lock. +*/ +typedef struct tag_rwlock { + int locks; + int status; + CRITICAL_SECTION cs; + HANDLE readwx; + HANDLE writewx; + + DWORD writer; /* TID of writer thread */ +} rw_lock_t; + +typedef rw_lock_t RWLOCK, *PRWLOCK; + +/*! \brief Initialize a read/write lock. + + A lock <b>must</b> be initialized before it can be used. + Initializing the lock does not grant the caller any locks on the + object. +*/ +KHMEXP void KHMAPI InitializeRwLock(PRWLOCK pLock); + +/*! \brief Delete a read/write lock + + Once the application is done using the read/write lock, it must be + deleted with a call to DeleteRwLock() +*/ +KHMEXP void KHMAPI DeleteRwLock(PRWLOCK pLock); + +/*! \brief Obtains a read lock on the read/write lock + + Multiple readers can obtain read locks on the same r/w lock. + However, if any thread attempts to obtain a write lock on the + object, it will wait until all readers have released the read + locks. + + Call LockReleaseRead() to release the read lock. While the same + thread may obtain multiple read locks on the same object, each + call to LockObtainRead() must have a corresponding call to + LockReleaseRead() to properly relinquish the lock. + + \see LockReleaseRead() +*/ +KHMEXP void KHMAPI LockObtainRead(PRWLOCK pLock); + +/*! \brief Relase a read lock obtained on a read/write lock + + Each call to LockObtainRead() must have a corresponding call to + LockReleaseRead(). Once all read locks are released, any threads + waiting on write locks on the object will be woken and assigned a + write lock. + + \see LockObtainRead() +*/ +KHMEXP void KHMAPI LockReleaseRead(PRWLOCK pLock); + +/*! \brief Obtains a write lock on the read/write lock + + Only a single writer is allowed to lock a single r/w lock. + However, if any thread attempts to obtain a read lock on the + object, it will wait until the writer has released the lock. + + Call LockReleaseWrite() to release the write lock. While the same + thread may obtain multiple write locks on the same object, each + call to LockObtainWrite() must have a corresponding call to + LockReleaseWrite() to properly relinquish the lock. + + \see LockReleaseWrite() +*/ +KHMEXP void KHMAPI LockObtainWrite(PRWLOCK pLock); + +/*! \brief Relase a write lock obtained on a read/write lock + + Each call to LockObtainWrite() must have a corresponding call to + LockReleaseWrite(). Once the write lock is released, any threads + waiting for read or write locks on the object will be woken and + assigned the proper lock. + + \see LockObtainWrite() +*/ +KHMEXP void KHMAPI LockReleaseWrite(PRWLOCK pLock); + +/*@}*/ +/*@}*/ + +#endif diff --git a/krb5-1-6/src/windows/identity/util/utils.h b/krb5-1-6/src/windows/identity/util/utils.h new file mode 100644 index 000000000..4c3bef52f --- /dev/null +++ b/krb5-1-6/src/windows/identity/util/utils.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_UTIL_H +#define __KHIMAIRA_UTIL_H + +/*! \defgroup util Utilities + */ +#include<hashtable.h> +#include<sync.h> +#include<mstring.h> +#include<perfstat.h> + +#endif diff --git a/krb5-1-6/src/windows/installer/nsis/KfWConfigPage.ini b/krb5-1-6/src/windows/installer/nsis/KfWConfigPage.ini new file mode 100644 index 000000000..abc0ed63b --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/KfWConfigPage.ini @@ -0,0 +1,59 @@ +[Settings] +NumFields=7 + +[Field 1] +Type=label +Text=The Kerberos Client may utilize configuration files to assist in contacting KDCs. Where do you want to get these files? +Left=0 +Right=-1 +Top=0 +Bottom=20 + +[Field 2] +Type=RadioButton +Text=Use existing configuration files from a previous installation. +Left=10 +Right=-1 +Top=25 +Bottom=35 + +[Field 3] +Type=RadioButton +Text=Use packaged configuration files. +Left=10 +Right=-1 +Top=40 +Bottom=50 + +[Field 4] +type=RadioButton +Text=Download from web path: +State=0 +Left=10 +Right=-1 +Top=55 +Bottom=65 + +[Field 5] +type=Text +State= +Left=20 +Right=-1 +Top=70 +Bottom=80 + +[Field 6] +type=radioButton +text=Select a directory +Left=10 +Right=-1 +Top=85 +Bottom=95 + +[Field 7] +type=DirRequest +Flags=PATH_MUST_EXIST +Left=20 +Right=-40 +Top=100 +Bottom=110 diff --git a/krb5-1-6/src/windows/installer/nsis/KfWConfigPage2.ini b/krb5-1-6/src/windows/installer/nsis/KfWConfigPage2.ini new file mode 100644 index 000000000..353bf179b --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/KfWConfigPage2.ini @@ -0,0 +1,20 @@ +[Settings] +NumFields=3 + +[Field 1] +Type=label +Text=The Network Identity Manager maybe installed with the following optional functionality. Please check those items you wish activated. +Left=0 +Right=-1 +Top=0 +Bottom=20 + +[Field 2] +Type=CheckBox +Text=Autostart the Network Identity Manager each time you login to Windows. +State=1 +Left=10 +Right=-1 +Top=25 +Bottom=35 + diff --git a/krb5-1-6/src/windows/installer/nsis/kfw-fixed.nsi b/krb5-1-6/src/windows/installer/nsis/kfw-fixed.nsi new file mode 100644 index 000000000..cef8b60dd --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/kfw-fixed.nsi @@ -0,0 +1,1907 @@ +;----------------------------------------------------------------- +; KfW defines and functionality +; Copyright (c) 2004,2005,2006,2007 Massachusetts Institute of Technology +; Copyright (c) 2006,2007 Secure Endpoints Inc. + +!define KFW_VERSION "${KFW_MAJORVERSION}.${KFW_MINORVERSION}.${KFW_PATCHLEVEL}" + +!define PROGRAM_NAME "Kerberos for Windows" +!ifdef RELEASE +!ifndef DEBUG ; !DEBUG on v2.0b4 +Name "MIT ${PROGRAM_NAME} ${KFW_VERSION}" +!else ; DEBUG on v2.0b4 +Name "MIT ${PROGRAM_NAME} ${KFW_VERSION} Checked/Debug" +!endif ; End DEBUG/!DEBUG +!else +!ifdef BETA +!ifndef DEBUG ; !DEBUG on v2.0b4 +Name "MIT ${PROGRAM_NAME} ${KFW_VERSION} Beta ${BETA}" +!else ; DEBUG on v2.0b4 +Name "MIT ${PROGRAM_NAME} ${KFW_VERSION} Beta ${BETA} Checked/Debug" +!endif ; End DEBUG/!DEBUG +!else +!ifndef DEBUG ; !DEBUG on v2.0b4 +Name "MIT ${PROGRAM_NAME} ${KFW_VERSION} ${__DATE__} ${__TIME__}" +!else ; DEBUG on v2.0b4 +Name "MIT ${PROGRAM_NAME} ${KFW_VERSION} ${__DATE__} ${__TIME__} Checked/Debug" +!endif ; End DEBUG/!DEBUG +!endif +!endif +VIProductVersion "${KFW_MAJORVERSION}.${KFW_MINORVERSION}.${KFW_PATCHLEVEL}.00" +VIAddVersionKey "ProductName" "${PROGRAM_NAME}" +VIAddVersionKey "CompanyName" "Massachusetts Institute of Technology" +VIAddVersionKey "FileVersion" ${VIProductVersion} +VIAddVersionKey "ProductVersion" "${KFW_MAJORVERSION}.${KFW_MINORVERSION}.${KFW_PATCHLEVEL}.0" +VIAddVersionKey "FileDescription" "MIT Kerberos for Windows Installer" +VIAddVersionKey "LegalCopyright" "(C)2004,2005,2006,2007" +!ifdef DEBUG +VIAddVersionKey "PrivateBuild" "Checked/Debug" +!endif ; End DEBUG + + +;-------------------------------- +;Configuration + + ;General + SetCompressor lzma +!ifndef DEBUG + OutFile "MITKerberosForWindows.exe" +!else + OutFile "MITKerberosForWindows-DEBUG.exe" +!endif + SilentInstall normal + ShowInstDetails show + XPStyle on + !define MUI_ICON "kfw.ico" + !define MUI_UNICON "kfw.ico" + !define KFW_COMPANY_NAME "Massachusetts Institute of Technology" + !define KFW_PRODUCT_NAME "${PROGRAM_NAME}" + !define KFW_REGKEY_ROOT "Software\MIT\Kerberos\" + !define NIM_REGKEY_ROOT "Software\MIT\NetIDMgr\" + CRCCheck force + !define REPLACEDLL_NOREGISTER + + ;Folder selection page + InstallDir "$PROGRAMFILES\MIT\Kerberos" ; Install to shorter path + + ;Remember install folder + InstallDirRegKey HKLM "${KFW_REGKEY_ROOT}" "" + + ;Remember the installer language + !define MUI_LANGDLL_REGISTRY_ROOT "HKLM" + !define MUI_LANGDLL_REGISTRY_KEY "${KFW_REGKEY_ROOT}" + !define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" + + ;Where are the files? + !define KFW_BIN_DIR "${KFW_TARGETDIR}\bin\i386" + !define KFW_DOC_DIR "${KFW_TARGETDIR}\doc" + !define KFW_INC_DIR "${KFW_TARGETDIR}\inc" + !define KFW_LIB_DIR "${KFW_TARGETDIR}\lib\i386" + !define KFW_SAMPLE_DIR "${KFW_TARGETDIR}\sample" + !define KFW_INSTALL_DIR "${KFW_TARGETDIR}\install" + !define SYSTEMDIR "$%SystemRoot%\System32" + + +;-------------------------------- +;Modern UI Configuration + + !define MUI_LICENSEPAGE + !define MUI_CUSTOMPAGECOMMANDS + !define MUI_WELCOMEPAGE + !define MUI_COMPONENTSPAGE + !define MUI_COMPONENTSPAGE_SMALLDESC + !define MUI_DIRECTORYPAGE + + !define MUI_ABORTWARNING + !define MUI_FINISHPAGE + + !define MUI_UNINSTALLER + !define MUI_UNCONFIRMPAGE + + + !insertmacro MUI_PAGE_WELCOME + !insertmacro MUI_PAGE_LICENSE "Licenses.rtf" + !insertmacro MUI_PAGE_COMPONENTS + !insertmacro MUI_PAGE_DIRECTORY + Page custom KFWPageGetConfigFiles + Page custom KFWPageGetStartupConfig + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" + +;-------------------------------- +;Language Strings + + ;Descriptions + LangString DESC_SecCopyUI ${LANG_ENGLISH} "${PROGRAM_NAME}: English" + + LangString DESC_secClient ${LANG_ENGLISH} "Client: Allows you to utilize MIT Kerberos from your Windows PC." + + LangString DESC_secDebug ${LANG_ENGLISH} "Debug Symbols: Used for debugging problems with MIT Kerberos for Windows" + + LangString DESC_secSDK ${LANG_ENGLISH} "SDK: Allows you to build MIT Kerberos aware applications." + + LangString DESC_secDocs ${LANG_ENGLISH} "Documentation: Release Notes and User Manuals." + +; Popup error messages + LangString RealmNameError ${LANG_ENGLISH} "You must specify a realm name for your client to use." + + LangString ConfigFileError ${LANG_ENGLISH} "You must specify a valid configuration file location from which files can be copied during the install" + + LangString URLError ${LANG_ENGLISH} "You must specify a URL if you choose the option to download the config files." + +; Upgrade/re-install strings + LangString UPGRADE_CLIENT ${LANG_ENGLISH} "Upgrade Kerberos Client" + LangString REINSTALL_CLIENT ${LANG_ENGLISH} "Re-install Kerberos Client" + LangString DOWNGRADE_CLIENT ${LANG_ENGLISH} "Downgrade Kerberos Client" + + LangString UPGRADE_SDK ${LANG_ENGLISH} "Upgrade Kerberos SDK" + LangString REINSTALL_SDK ${LANG_ENGLISH} "Re-install Kerberos SDK" + LangString DOWNGRADE_SDK ${LANG_ENGLISH} "Downgrade Kerberos SDK" + + LangString UPGRADE_DOCS ${LANG_ENGLISH} "Upgrade Kerberos Documentation" + LangString REINSTALL_DOCS ${LANG_ENGLISH} "Re-install Kerberos Documentation" + LangString DOWNGRADE_DOCS ${LANG_ENGLISH} "Downgrade Kerberos Documentation" + + ReserveFile "${KFW_CONFIG_DIR}\sample\krb.con" + ReserveFile "${KFW_CONFIG_DIR}\sample\krbrealm.con" + ReserveFile "${KFW_CONFIG_DIR}\sample\krb5.ini" + !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS ;InstallOptions plug-in + !insertmacro MUI_RESERVEFILE_LANGDLL ;Language selection dialog + +;-------------------------------- +;Reserve Files + + ;Things that need to be extracted on first (keep these lines before any File command!) + ;Only useful for BZIP2 compression + !insertmacro MUI_RESERVEFILE_LANGDLL + +;-------------------------------- +; Load Macros +!include "utils.nsi" + +;-------------------------------- +;Installer Sections + +;---------------------- +; Kerberos for Windows CLIENT +Section "KfW Client" secClient + + SetShellVarContext all + ; Stop any running services or we can't replace the files + ; Stop the running processes + GetTempFileName $R0 + File /oname=$R0 "Killer.exe" + nsExec::Exec '$R0 netidmgr.exe' + nsExec::Exec '$R0 leash32.exe' + nsExec::Exec '$R0 krbcc32s.exe' + nsExec::Exec '$R0 k95.exe' + nsExec::Exec '$R0 k95g.exe' + nsExec::Exec '$R0 krb5.exe' + nsExec::Exec '$R0 gss.exe' + nsExec::Exec '$R0 afscreds.exe' + + RMDir /r "$INSTDIR\bin" + + ; Do client components + SetOutPath "$INSTDIR\bin" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\comerr32.dll" "$INSTDIR\bin\comerr32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\gss.exe" "$INSTDIR\bin\gss.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\gss-client.exe" "$INSTDIR\bin\gss-client.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\gss-server.exe" "$INSTDIR\bin\gss-server.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\gssapi32.dll" "$INSTDIR\bin\gssapi32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\k524init.exe" "$INSTDIR\bin\k524init.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kclnt32.dll" "$INSTDIR\bin\kclnt32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kdestroy.exe" "$INSTDIR\bin\kdestroy.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kinit.exe" "$INSTDIR\bin\kinit.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\klist.exe" "$INSTDIR\bin\klist.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kpasswd.exe" "$INSTDIR\bin\kpasswd.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kvno.exe" "$INSTDIR\bin\kvno.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krb5_32.dll" "$INSTDIR\bin\krb5_32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\k5sprt32.dll" "$INSTDIR\bin\k5sprt32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krb524.dll" "$INSTDIR\bin\krb524.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krbcc32.dll" "$INSTDIR\bin\krbcc32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krbcc32s.exe" "$INSTDIR\bin\krbcc32s.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krbv4w32.dll" "$INSTDIR\bin\krbv4w32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\netidmgr.chm" "$INSTDIR\bin\netidmgr.chm" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krb4cred.dll" "$INSTDIR\bin\krb4cred.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krb5cred.dll" "$INSTDIR\bin\krb5cred.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krb4cred_en_us.dll" "$INSTDIR\bin\krb4cred_en_us.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\krb5cred_en_us.dll" "$INSTDIR\bin\krb5cred_en_us.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\leashw32.dll" "$INSTDIR\bin\leashw32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\ms2mit.exe" "$INSTDIR\bin\ms2mit.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\mit2ms.exe" "$INSTDIR\bin\mit2ms.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kcpytkt.exe" "$INSTDIR\bin\kcpytkt.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kdeltkt.exe" "$INSTDIR\bin\kdeltkt.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\wshelp32.dll" "$INSTDIR\bin\wshelp32.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\xpprof32.dll" "$INSTDIR\bin\xpprof32.dll" "$INSTDIR" + + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "2000" nid_inst2000 + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\netidmgr.exe" "$INSTDIR\bin\netidmgr.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\nidmgr32.dll" "$INSTDIR\bin\nidmgr32.dll" "$INSTDIR" + goto nid_done +nid_inst2000: + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\W2K\netidmgr.exe" "$INSTDIR\bin\netidmgr.exe" "$INSTDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\W2K\nidmgr32.dll" "$INSTDIR\bin\nidmgr32.dll" "$INSTDIR" +nid_done: + +!ifdef DEBUG +!IFDEF CL_1400 + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcr80d.dll" "$INSTDIR\bin\msvcr80d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp80d.dll" "$INSTDIR\bin\msvcp80d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc80d.dll" "$INSTDIR\bin\mfc80d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80CHS.DLL" "$INSTDIR\bin\MFC80CHS.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80CHT.DLL" "$INSTDIR\bin\MFC80CHT.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80DEU.DLL" "$INSTDIR\bin\MFC80DEU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80ENU.DLL" "$INSTDIR\bin\MFC80ENU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80ESP.DLL" "$INSTDIR\bin\MFC80ESP.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80FRA.DLL" "$INSTDIR\bin\MFC80FRA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80ITA.DLL" "$INSTDIR\bin\MFC80ITA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80JPN.DLL" "$INSTDIR\bin\MFC80JPN.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80KOR.DLL" "$INSTDIR\bin\MFC80KOR.DLL" "$INSTDIR" +!ELSE +!IFDEF CL_1310 + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcr71d.dll" "$INSTDIR\bin\msvcr71d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp71d.dll" "$INSTDIR\bin\msvcp71d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc71d.dll" "$INSTDIR\bin\mfc71d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71CHS.DLL" "$INSTDIR\bin\MFC71CHS.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71CHT.DLL" "$INSTDIR\bin\MFC71CHT.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71DEU.DLL" "$INSTDIR\bin\MFC71DEU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71ENU.DLL" "$INSTDIR\bin\MFC71ENU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71ESP.DLL" "$INSTDIR\bin\MFC71ESP.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71FRA.DLL" "$INSTDIR\bin\MFC71FRA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71ITA.DLL" "$INSTDIR\bin\MFC71ITA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71JPN.DLL" "$INSTDIR\bin\MFC71JPN.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71KOR.DLL" "$INSTDIR\bin\MFC71KOR.DLL" "$INSTDIR" +!ELSE +!IFDEF CL_1300 + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcr70d.dll" "$INSTDIR\bin\msvcr70d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp70d.dll" "$INSTDIR\bin\msvcp70d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc70d.dll" "$INSTDIR\bin\mfc70d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70CHS.DLL" "$INSTDIR\bin\MFC70CHS.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70CHT.DLL" "$INSTDIR\bin\MFC70CHT.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70DEU.DLL" "$INSTDIR\bin\MFC70DEU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70ENU.DLL" "$INSTDIR\bin\MFC70ENU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70ESP.DLL" "$INSTDIR\bin\MFC70ESP.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70FRA.DLL" "$INSTDIR\bin\MFC70FRA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70ITA.DLL" "$INSTDIR\bin\MFC70ITA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70JPN.DLL" "$INSTDIR\bin\MFC70JPN.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70KOR.DLL" "$INSTDIR\bin\MFC70KOR.DLL" "$INSTDIR" +!ELSE + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc42d.dll" "$INSTDIR\bin\mfc42d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp60d.dll" "$INSTDIR\bin\msvcp60d.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcrtd.dll" "$INSTDIR\bin\msvcrtd.dll" "$INSTDIR" +!ENDIF +!ENDIF +!ENDIF +!ELSE +!IFDEF CL_1400 + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc80.dll" "$INSTDIR\bin\mfc80.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcr80.dll" "$INSTDIR\bin\msvcr80.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp80.dll" "$INSTDIR\bin\msvcp80.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80CHS.DLL" "$INSTDIR\bin\MFC80CHS.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80CHT.DLL" "$INSTDIR\bin\MFC80CHT.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80DEU.DLL" "$INSTDIR\bin\MFC80DEU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80ENU.DLL" "$INSTDIR\bin\MFC80ENU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80ESP.DLL" "$INSTDIR\bin\MFC80ESP.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80FRA.DLL" "$INSTDIR\bin\MFC80FRA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80ITA.DLL" "$INSTDIR\bin\MFC80ITA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80JPN.DLL" "$INSTDIR\bin\MFC80JPN.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC80KOR.DLL" "$INSTDIR\bin\MFC80KOR.DLL" "$INSTDIR" +!ELSE +!IFDEF CL_1310 + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc71.dll" "$INSTDIR\bin\mfc71.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcr71.dll" "$INSTDIR\bin\msvcr71.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp71.dll" "$INSTDIR\bin\msvcp71.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71CHS.DLL" "$INSTDIR\bin\MFC71CHS.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71CHT.DLL" "$INSTDIR\bin\MFC71CHT.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71DEU.DLL" "$INSTDIR\bin\MFC71DEU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71ENU.DLL" "$INSTDIR\bin\MFC71ENU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71ESP.DLL" "$INSTDIR\bin\MFC71ESP.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71FRA.DLL" "$INSTDIR\bin\MFC71FRA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71ITA.DLL" "$INSTDIR\bin\MFC71ITA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71JPN.DLL" "$INSTDIR\bin\MFC71JPN.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC71KOR.DLL" "$INSTDIR\bin\MFC71KOR.DLL" "$INSTDIR" +!ELSE +!IFDEF CL_1300 + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc70.dll" "$INSTDIR\bin\mfc70.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcr70.dll" "$INSTDIR\bin\msvcr70.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp70.dll" "$INSTDIR\bin\msvcp70.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70CHS.DLL" "$INSTDIR\bin\MFC70CHS.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70CHT.DLL" "$INSTDIR\bin\MFC70CHT.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70DEU.DLL" "$INSTDIR\bin\MFC70DEU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70ENU.DLL" "$INSTDIR\bin\MFC70ENU.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70ESP.DLL" "$INSTDIR\bin\MFC70ESP.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70FRA.DLL" "$INSTDIR\bin\MFC70FRA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70ITA.DLL" "$INSTDIR\bin\MFC70ITA.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70JPN.DLL" "$INSTDIR\bin\MFC70JPN.DLL" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\MFC70KOR.DLL" "$INSTDIR\bin\MFC70KOR.DLL" "$INSTDIR" +!ELSE + !insertmacro ReplaceDLL "${SYSTEMDIR}\mfc42.dll" "$INSTDIR\bin\mfc42.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcp60.dll" "$INSTDIR\bin\msvcp60.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${SYSTEMDIR}\msvcrt.dll" "$INSTDIR\bin\msvcrt.dll" "$INSTDIR" +!ENDIF +!ENDIF +!ENDIF +!ENDIF + !insertmacro ReplaceDLL "${SYSTEMDIR}\psapi.dll" "$INSTDIR\bin\psapi.dll" "$INSTDIR" + + ; Do WINDOWSDIR components + ;SetOutPath "$WINDOWSDIR" +!ifdef DEBUG +!endif + + ; Do Windows SYSDIR (Control panel) + SetOutPath "$SYSDIR" + !insertmacro ReplaceDLL "${KFW_BIN_DIR}\kfwlogon.dll" "$SYSDIR\kfwlogon.dll" "$INSTDIR" + File "${KFW_BIN_DIR}\kfwcpcc.exe" + + ; Get Kerberos config files + Call kfw.GetConfigFiles + + Call KFWCommon.Install + + ; KfW Reg entries + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "VersionString" ${KFW_VERSION} + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "Title" "KfW" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "Description" "${PROGRAM_NAME}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "PathName" "$INSTDIR" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "Software Type" "Authentication" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "MajorVersion" ${KFW_MAJORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "MinorVersion" ${KFW_MINORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "PatchLevel" ${KFW_PATCHLEVEL} + + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "VersionString" ${KFW_VERSION} + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "Title" "KfW" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "Description" "${PROGRAM_NAME}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "PathName" "$INSTDIR" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "Software Type" "Authentication" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "MajorVersion" ${KFW_MAJORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "MinorVersion" ${KFW_MINORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "PatchLevel" ${KFW_PATCHLEVEL} + + ; Daemon entries + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\MIT Kerberos" "" "" + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" "ProviderPath" "$SYSDIR\kfwlogon.dll" + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" "AuthentProviderPath" "$SYSDIR\kfwlogon.dll" + WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" "Class" 2 + WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" "VerboseLogging" 10 + + ; Must also add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\HwOrder + ; and HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order + ; to also include the service name. + Call AddProvider + ReadINIStr $R0 $1 "Field 7" "State" + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" "Name" "MIT Kerberos" + + ; WinLogon Event Notification + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" "Asynchronous" 0 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" "Impersonate" 0 + WriteRegStr HKLM "Software\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" "DLLName" "kfwlogon.dll" + WriteRegStr HKLM "Software\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" "Logon" "KFW_Logon_Event" + + ; NetIdMgr Reg entries + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb5" "ImagePath" "$INSTDIR\bin\krb5cred.dll" + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb5" "PluginList" "Krb5Cred,Krb5Ident" + + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" "Module" "MITKrb5" + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" "Description" "Kerberos v5 Credentials Provider" + WriteRegDWORD HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" "Type" 1 + WriteRegDWORD HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" "Flags" 0 + + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" "Module" "MITKrb5" + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" "Description" "Kerberos v5 Identity Provider" + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" "Dependencies" "Krb5Cred" + WriteRegDWORD HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" "Type" 2 + WriteRegDWORD HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" "Flags" 0 + + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb4" "ImagePath" "$INSTDIR\bin\krb4cred.dll" + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb4" "PluginList" "Krb4Cred" + + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" "Module" "MITKrb4" + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" "Description" "Kerberos v4 Credentials Provider" + WriteRegStr HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" "Dependencies" "Krb5Cred" + WriteRegDWORD HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" "Type" 1 + WriteRegDWORD HKLM "Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" "Flags" 0 + + ;Write start menu entries + CreateDirectory "$SMPROGRAMS\${PROGRAM_NAME}" + SetOutPath "$INSTDIR\bin" + CreateShortCut "$SMPROGRAMS\${PROGRAM_NAME}\Uninstall ${PROGRAM_NAME}.lnk" "$INSTDIR\Uninstall.exe" + + ReadINIStr $R0 $1 "Field 2" "State" ; startup + + CreateShortCut "$SMPROGRAMS\${PROGRAM_NAME}\Network Identity Manager.lnk" "$INSTDIR\bin\netidmgr.exe" "" "$INSTDIR\bin\netidmgr.exe" + +startshort: + StrCmp $R0 "0" nostart + CreateShortCut "$SMSTARTUP\Network Identity Manager.lnk" "$INSTDIR\bin\netidmgr.exe" "" "$INSTDIR\bin\netidmgr.exe" 0 SW_SHOWMINIMIZED + goto checkconflicts + +nostart: + Delete "$SMSTARTUP\Network Identity Manager.lnk" + +checkconflicts: + Call GetSystemPath + Push "krb5_32.dll" + Call SearchPath + Pop $R0 + StrCmp $R0 "" addpath + + Push $R0 + Call GetParent + Pop $R0 + StrCmp $R0 "$INSTDIR\bin" addpath + MessageBox MB_OK|MB_ICONINFORMATION|MB_TOPMOST "A previous installation of MIT Kerberos for Windows binaries has been found in folder $R0. This may interfere with the use of the current installation." + +addpath: + ; Add kfw bin to path + Push "$INSTDIR\bin" + Call AddToSystemPath + + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "2003" addAllowTgtKey + StrCmp $R0 "2000" addAllowTgtKey + StrCmp $R0 "XP" addAllowTgtKey + goto skipAllowTgtKey + +addAllowTgtKey: + ReadRegDWORD $R0 HKLM "SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters" "AllowTGTSessionKey" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "AllowTGTSessionKeyBackup" $R0 + WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters" "AllowTGTSessionKey" "1" + ReadRegDWORD $R0 HKLM "SYSTEM\CurrentControlSet\Control\Lsa\Kerberos" "AllowTGTSessionKey" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "AllowTGTSessionKeyBackup2" $R0 + WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Control\Lsa\Kerberos" "AllowTGTSessionKey" "1" +skipAllowTgtKey: + + ; The following are keys added for Terminal Server compatibility + ; http://support.microsoft.com/default.aspx?scid=kb;EN-US;186499 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\netidmgr" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kinit" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klist" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdestroy" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-client" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-server" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k524init" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kpasswd" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kvno" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\ms2mit" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\mit2ms" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\mit2ms" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kcpytkt" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdeltkt" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k95" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k95g" "Flags" 0x408 + +SectionEnd + +Section "Debug Symbols" secDebug + + SetOutPath "$INSTDIR\bin" + File "${KFW_BIN_DIR}\comerr32.pdb" + File "${KFW_BIN_DIR}\gss.pdb" + File "${KFW_BIN_DIR}\gss-client.pdb" + File "${KFW_BIN_DIR}\gss-server.pdb" + File "${KFW_BIN_DIR}\gssapi32.pdb" + File "${KFW_BIN_DIR}\k524init.pdb" + File "${KFW_BIN_DIR}\kclnt32.pdb" + File "${KFW_BIN_DIR}\kdestroy.pdb" + File "${KFW_BIN_DIR}\kinit.pdb" + File "${KFW_BIN_DIR}\klist.pdb" + File "${KFW_BIN_DIR}\kpasswd.pdb" + File "${KFW_BIN_DIR}\kvno.pdb" + File "${KFW_BIN_DIR}\krb5_32.pdb" + File "${KFW_BIN_DIR}\k5sprt32.pdb" + File "${KFW_BIN_DIR}\krb524.pdb" + File "${KFW_BIN_DIR}\krbcc32.pdb" + File "${KFW_BIN_DIR}\krbcc32s.pdb" + File "${KFW_BIN_DIR}\krbv4w32.pdb" + File "${KFW_BIN_DIR}\leashw32.pdb" + File "${KFW_BIN_DIR}\krb4cred.pdb" + File "${KFW_BIN_DIR}\krb5cred.pdb" + File "${KFW_BIN_DIR}\ms2mit.pdb" + File "${KFW_BIN_DIR}\mit2ms.pdb" + File "${KFW_BIN_DIR}\kcpytkt.pdb" + File "${KFW_BIN_DIR}\kdeltkt.pdb" + File "${KFW_BIN_DIR}\wshelp32.pdb" + File "${KFW_BIN_DIR}\xpprof32.pdb" + + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "2000" nidpdb_inst2000 + File "${KFW_BIN_DIR}\netidmgr.pdb" + File "${KFW_BIN_DIR}\nidmgr32.pdb" + goto nidpdb_done +nidpdb_inst2000: + File "${KFW_BIN_DIR}\W2K\netidmgr.pdb" + File "${KFW_BIN_DIR}\W2K\nidmgr32.pdb" +nidpdb_done: + +!IFDEF DEBUG +!IFDEF CL_1400 + File "${SYSTEMDIR}\msvcr80d.pdb" + File "${SYSTEMDIR}\msvcp80d.pdb" + File "${SYSTEMDIR}\mfc80d.pdb" +!ELSE +!IFDEF CL_1310 + File "${SYSTEMDIR}\msvcr71d.pdb" + File "${SYSTEMDIR}\msvcp71d.pdb" + File "${SYSTEMDIR}\mfc71d.pdb" +!ELSE +!IFDEF CL_1300 + File "${SYSTEMDIR}\msvcr70d.pdb" + File "${SYSTEMDIR}\msvcp70d.pdb" + File "${SYSTEMDIR}\mfc70d.pdb" +!ELSE + File "${SYSTEMDIR}\mfc42d.pdb" + File "${SYSTEMDIR}\msvcp60d.pdb" + File "${SYSTEMDIR}\msvcrtd.pdb" +!ENDIF +!ENDIF +!ENDIF +!ENDIF + + SetOutPath "$SYSDIR" + File "${KFW_BIN_DIR}\kfwlogon.pdb" + File "${KFW_BIN_DIR}\kfwcpcc.pdb" + +SectionEnd + +;---------------------- +; Kerberos for Windows SDK +Section "KfW SDK" secSDK + + RMDir /r "$INSTDIR\inc" + RMDir /r "$INSTDIR\lib" + RMDir /r "$INSTDIR\install" + RMDir /r "$INSTDIR\sample" + + SetOutPath "$INSTDIR\doc" + File /r "${KFW_DOC_DIR}\netiddev.chm" + + SetOutPath "$INSTDIR\inc\kclient" + File /r "${KFW_INC_DIR}\kclient\*" + + SetOutPath "$INSTDIR\inc\krb4" + File /r "${KFW_INC_DIR}\krb4\*" + + SetOutPath "$INSTDIR\inc\krb5" + File /r "${KFW_INC_DIR}\krb5\*" + + SetOutPath "$INSTDIR\inc\krbcc" + File /r "${KFW_INC_DIR}\krbcc\*" + + SetOutPath "$INSTDIR\inc\leash" + File /r "${KFW_INC_DIR}\leash\*" + + SetOutPath "$INSTDIR\inc\loadfuncs" + File /r "${KFW_INC_DIR}\loadfuncs\*" + + SetOutPath "$INSTDIR\inc\netidmgr" + File /r "${KFW_INC_DIR}\netidmgr\*" + + SetOutPath "$INSTDIR\inc\wshelper" + File /r "${KFW_INC_DIR}\wshelper\*" + + SetOutPath "$INSTDIR\lib\i386" + File /r "${KFW_LIB_DIR}\*" + + SetOutPath "$INSTDIR\install" + File /r "${KFW_INSTALL_DIR}\*" + + SetOutPath "$INSTDIR\sample" + File /r "${KFW_SAMPLE_DIR}\*" + + CreateShortCut "$SMPROGRAMS\${PROGRAM_NAME}\Network Identity Developer Documentation.lnk" "$INSTDIR\bin\netiddev.chm" + + Call KFWCommon.Install + + ; KfW Reg entries + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "VersionString" ${KFW_VERSION} + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "Title" "KfW" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "Description" "${PROGRAM_NAME}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "PathName" "$INSTDIR" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "Software Type" "Authentication" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "MajorVersion" ${KFW_MAJORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "MinorVersion" ${KFW_MINORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "PatchLevel" ${KFW_PATCHLEVEL} + + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "VersionString" ${KFW_VERSION} + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "Title" "KfW" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "Description" "${PROGRAM_NAME}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "PathName" "$INSTDIR" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "Software Type" "Authentication" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "MajorVersion" ${KFW_MAJORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "MinorVersion" ${KFW_MINORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "PatchLevel" ${KFW_PATCHLEVEL} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\SDK\${KFW_VERSION}" "PatchLevel" ${KFW_PATCHLEVEL} + +SectionEnd + +;---------------------- +; Kerberos for Windows Documentation +Section "KfW Documentation" secDocs + + RMDir /r "$INSTDIR\doc" + + SetOutPath "$INSTDIR\doc" + File "${KFW_DOC_DIR}\relnotes.html" + File "${KFW_DOC_DIR}\netidmgr_userdoc.pdf" + + Call KFWCommon.Install + + ; KfW Reg entries + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "VersionString" ${KFW_VERSION} + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "Title" "KfW" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "Description" "${PROGRAM_NAME}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "PathName" "$INSTDIR" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "Software Type" "Authentication" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "MajorVersion" ${KFW_MAJORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "MinorVersion" ${KFW_MINORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "PatchLevel" ${KFW_PATCHLEVEL} + + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "VersionString" ${KFW_VERSION} + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "Title" "KfW" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "Description" "${PROGRAM_NAME}" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "PathName" "$INSTDIR" + WriteRegStr HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "Software Type" "Authentication" + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "MajorVersion" ${KFW_MAJORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "MinorVersion" ${KFW_MINORVERSION} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "PatchLevel" ${KFW_PATCHLEVEL} + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\Documentation\${KFW_VERSION}" "PatchLevel" ${KFW_PATCHLEVEL} + + ;Write start menu entries + CreateDirectory "$SMPROGRAMS\${PROGRAM_NAME}" + SetOutPath "$INSTDIR\doc" + CreateShortCut "$SMPROGRAMS\${PROGRAM_NAME}\Release Notes.lnk" "$INSTDIR\doc\relnotes.html" + CreateShortCut "$SMPROGRAMS\${PROGRAM_NAME}\Network Identity Manager User Documentation.lnk" "$INSTDIR\doc\netidmgr_userdoc.pdf" + CreateShortCut "$SMPROGRAMS\${PROGRAM_NAME}\Network Identity Manager Documentation.lnk" "$INSTDIR\bin\netidmgr.chm" +SectionEnd + +;Display the Finish header +;Insert this macro after the sections if you are not using a finish page +;!insertmacro MUI_SECTIONS_FINISHHEADER + +;-------------------------------- +;Installer Functions + +Function .onInit + !insertmacro MUI_LANGDLL_DISPLAY + + ; Set the default install options + Push $0 + + Call IsUserAdmin + Pop $R0 + StrCmp $R0 "true" checkVer + + MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST "You must be an administrator of this machine to install this software." + Abort + +checkVer: + ; Check Version of Windows. Do not install onto Windows 95 + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "95" wrongVersion + StrCmp $R0 "98" wrongVersion + StrCmp $R0 "ME" wrongVersion + StrCmp $R0 "NT 4.0" wrongVersion + goto checkIPHLPAPI + +wrongVersion: + MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST "MIT ${PROGRAM_NAME} requires Microsoft Windows 2000 or higher." + Abort + +checkIPHLPAPI: + ClearErrors + ReadEnvStr $R0 "WinDir" + GetDLLVersion "$R0\System32\iphlpapi.dll" $R1 $R2 + IfErrors +1 +3 + GetDLLVersion "$R0\System\iphlpapi.dll" $R1 $R2 + IfErrors iphlperror + IntOp $R3 $R2 / 0x00010000 + IntCmpU $R3 1952 iphlpwarning checkprevious checkprevious + +iphlperror: + MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST "MIT ${PROGRAM_NAME} requires Internet Explorer version 5.01 or higher. IPHLPAPI.DLL is missing." + Abort + +iphlpwarning: + MessageBox MB_OK|MB_ICONINFORMATION|MB_TOPMOST "IPHLPAPI.DLL must be upgraded. Please install Internet Explorer 5.01 or higher." + +checkprevious: + ClearErrors + ReadRegStr $R0 HKLM \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" \ + "DisplayVersion" + IfErrors testWIX + StrCmp $R0 "${KFW_VERSION}" contInstall + + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ + "${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \ + previous version or `Cancel` to cancel this upgrade or downgrade." \ + IDOK uninstNSIS + Abort + +;Run the uninstaller +uninstNSIS: + ReadRegStr $R0 HKLM \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" \ + "UninstallString" + ClearErrors + ExecWait '$R0 _?=$INSTDIR' ;Do not copy the uninstaller to a temp file + + IfErrors no_remove_uninstaller + ;You can either use Delete /REBOOTOK in the uninstaller or add some code + ;here to remove the uninstaller. Use a registry key to check + ;whether the user has chosen to uninstall. If you are using an uninstaller + ;components page, make sure all sections are uninstalled. + + Push $R1 + Call RestartRequired + Pop $R1 + StrCmp $R1 "1" Restart DoNotRestart + +testWIX: + ClearErrors + ReadRegStr $R0 HKLM \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\{FD5B1F41-81BB-4BBC-9F7E-4B971660AE1A}" \ + "DisplayVersion" + IfErrors testSWRT + + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ + "${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \ + previous version or `Cancel` to cancel this installation." \ + IDOK uninstMSI1 + Abort + +;Run the uninstaller +uninstMSI1: + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "2000" uninstMSI1_2000 + + ClearErrors + ExecWait 'MSIEXEC /x{FD5B1F41-81BB-4BBC-9F7E-4B971660AE1A} /passive /promptrestart' + + IfErrors no_remove_uninstaller + ;You can either use Delete /REBOOTOK in the uninstaller or add some code + ;here to remove the uninstaller. Use a registry key to check + ;whether the user has chosen to uninstall. If you are using an uninstaller + ;components page, make sure all sections are uninstalled. + + Push $R1 + Call RestartRequired + Pop $R1 + StrCmp $R1 "1" Restart DoNotRestart + +uninstMSI1_2000: + ClearErrors + ExecWait 'MSIEXEC /x{FD5B1F41-81BB-4BBC-9F7E-4B971660AE1A}' + + IfErrors no_remove_uninstaller + ;You can either use Delete /REBOOTOK in the uninstaller or add some code + ;here to remove the uninstaller. Use a registry key to check + ;whether the user has chosen to uninstall. If you are using an uninstaller + ;components page, make sure all sections are uninstalled. + + Push $R1 + Call RestartRequired + Pop $R1 + StrCmp $R1 "1" Restart DoNotRestart + +testSWRT: + ClearErrors + ReadRegStr $R0 HKLM \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\{61211594-AAA1-4A98-A299-757326763CC7}" \ + "DisplayVersion" + IfErrors testPismere + + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ + "${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \ + previous version or `Cancel` to cancel this installation." \ + IDOK uninstMSI2 + Abort + +;Run the uninstaller +uninstMSI2: + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "2000" uninstMSI2_2000 + + ClearErrors + ExecWait 'MSIEXEC /x{61211594-AAA1-4A98-A299-757326763CC7} /passive /promptrestart' + + IfErrors no_remove_uninstaller + ;You can either use Delete /REBOOTOK in the uninstaller or add some code + ;here to remove the uninstaller. Use a registry key to check + ;whether the user has chosen to uninstall. If you are using an uninstaller + ;components page, make sure all sections are uninstalled. + + Push $R1 + Call RestartRequired + Pop $R1 + StrCmp $R1 "1" Restart DoNotRestart + +uninstMSI2_2000: + ClearErrors + ExecWait 'MSIEXEC /x{61211594-AAA1-4A98-A299-757326763CC7}' + + IfErrors no_remove_uninstaller + ;You can either use Delete /REBOOTOK in the uninstaller or add some code + ;here to remove the uninstaller. Use a registry key to check + ;whether the user has chosen to uninstall. If you are using an uninstaller + ;components page, make sure all sections are uninstalled. + + Push $R1 + Call RestartRequired + Pop $R1 + StrCmp $R1 "1" Restart DoNotRestart + +testPismere: + ClearErrors + ReadRegStr $R0 HKLM \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\{83977767-388D-4DF8-BB08-3BF2401635BD}" \ + "DisplayVersion" + IfErrors contInstall + + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ + "${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \ + previous version or `Cancel` to cancel this installation." \ + IDOK uninstPismere + Abort + +;Run the uninstaller +uninstPismere: + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "2000" uninstPismere_2000 + + ClearErrors + ExecWait 'MSIEXEC /x{83977767-388D-4DF8-BB08-3BF2401635BD} /passive /promptrestart' + + IfErrors no_remove_uninstaller + ;You can either use Delete /REBOOTOK in the uninstaller or add some code + ;here to remove the uninstaller. Use a registry key to check + ;whether the user has chosen to uninstall. If you are using an uninstaller + ;components page, make sure all sections are uninstalled. + + Push $R1 + Call RestartRequired + Pop $R1 + StrCmp $R1 "1" Restart DoNotRestart + +uninstPismere_2000: + ClearErrors + ExecWait 'MSIEXEC /x{83977767-388D-4DF8-BB08-3BF2401635BD}' + + IfErrors no_remove_uninstaller + ;You can either use Delete /REBOOTOK in the uninstaller or add some code + ;here to remove the uninstaller. Use a registry key to check + ;whether the user has chosen to uninstall. If you are using an uninstaller + ;components page, make sure all sections are uninstalled. + + Push $R1 + Call RestartRequired + Pop $R1 + StrCmp $R1 "1" Restart DoNotRestart + + +Restart: + MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST "Please reboot and then restart the installer." + Abort + MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST "Abort failed" + +DoNotRestart: +no_remove_uninstaller: + +contInstall: + ; Never install debug symbols unless explicitly selected, except in DEBUG mode +!IFNDEF DEBUG + SectionGetFlags ${secDebug} $0 + IntOp $0 $0 & ${SECTION_OFF} + SectionSetFlags ${secDebug} $0 +!ELSE + SectionGetFlags ${secDebug} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secDebug} $0 +!ENDIF + + ; Our logic should be like this. + ; 1) If no KfW components are installed, we do a clean install with default options. (Client/Docs) + ; 2) If existing modules are installed, we keep them selected + ; 3) If it is an upgrade, we set the text accordingly, else we mark it as a re-install + ; TODO: Downgrade? + Call IsAnyKfWInstalled + Pop $R0 + StrCmp $R0 "0" DefaultOptions + + Call ShouldClientInstall + Pop $R2 + + StrCmp $R2 "0" NoClient + StrCmp $R2 "1" ReinstallClient + StrCmp $R2 "2" UpgradeClient + StrCmp $R2 "3" DowngradeClient + + SectionGetFlags ${secClient} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secClient} $0 + ;# !insertmacro SelectSection ${secClient} + goto skipClient +NoClient: + ;StrCpy $1 ${secClient} ; Gotta remember which section we are at now... + SectionGetFlags ${secClient} $0 + IntOp $0 $0 & ${SECTION_OFF} + SectionSetFlags ${secClient} $0 + goto skipClient +UpgradeClient: + SectionGetFlags ${secClient} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secClient} $0 + SectionSetText ${secClient} $(UPGRADE_CLIENT) + goto skipClient +ReinstallClient: + SectionGetFlags ${secClient} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secClient} $0 + SectionSetText ${secClient} $(REINSTALL_CLIENT) + goto skipClient +DowngradeClient: + SectionGetFlags ${secClient} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secClient} $0 + SectionSetText ${secClient} $(DOWNGRADE_CLIENT) + goto skipClient + + +skipClient: + + Call ShouldSDKInstall + Pop $R2 + StrCmp $R2 "0" NoSDK + StrCmp $R2 "1" ReinstallSDK + StrCmp $R2 "2" UpgradeSDK + StrCmp $R2 "3" DowngradeSDK + + SectionGetFlags ${secSDK} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secSDK} $0 + ;# !insertmacro UnselectSection ${secSDK} + goto skipSDK + +UpgradeSDK: + SectionGetFlags ${secSDK} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secSDK} $0 + SectionSetText ${secSDK} $(UPGRADE_SDK) + goto skipSDK + +ReinstallSDK: + SectionGetFlags ${secSDK} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secSDK} $0 + SectionSetText ${secSDK} $(REINSTALL_SDK) + goto skipSDK + +DowngradeSDK: + SectionGetFlags ${secSDK} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secSDK} $0 + SectionSetText ${secSDK} $(DOWNGRADE_SDK) + goto skipSDK + +NoSDK: + SectionGetFlags ${secSDK} $0 + IntOp $0 $0 & ${SECTION_OFF} + SectionSetFlags ${secSDK} $0 + ;# !insertmacro UnselectSection ${secSDK} + goto skipSDK + +skipSDK: + + Call ShouldDocumentationInstall + Pop $R2 + StrCmp $R2 "0" NoDocumentation + StrCmp $R2 "1" ReinstallDocumentation + StrCmp $R2 "2" UpgradeDocumentation + StrCmp $R2 "3" DowngradeDocumentation + + SectionGetFlags ${secDocs} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secDocs} $0 + ;# !insertmacro UnselectSection ${secDocs} + goto skipDocumentation + +UpgradeDocumentation: + SectionGetFlags ${secDocs} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secDocs} $0 + SectionSetText ${secDocs} $(UPGRADE_DOCS) + goto skipDocumentation + +ReinstallDocumentation: + SectionGetFlags ${secDocs} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secDocs} $0 + SectionSetText ${secDocs} $(REINSTALL_DOCS) + goto skipDocumentation + +DowngradeDocumentation: + SectionGetFlags ${secDocs} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secDocs} $0 + SectionSetText ${secDocs} $(DOWNGRADE_DOCS) + goto skipDocumentation + +NoDocumentation: + SectionGetFlags ${secDocs} $0 + IntOp $0 $0 & ${SECTION_OFF} + SectionSetFlags ${secDocs} $0 + ;# !insertmacro UnselectSection ${secDocs} + goto skipDocumentation + +skipDocumentation: + goto end + +DefaultOptions: + ; Client Selected + SectionGetFlags ${secClient} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secClient} $0 + + ; SDK NOT selected + SectionGetFlags ${secSDK} $0 + IntOp $0 $0 & ${SECTION_OFF} + SectionSetFlags ${secSDK} $0 + + ; Documentation selected + SectionGetFlags ${secDocs} $0 + IntOp $0 $0 | ${SF_SELECTED} + SectionSetFlags ${secDocs} $0 + goto end + +end: + Pop $0 + + Push $R0 + + ; See if we can set a default installation path... + ReadRegStr $R0 HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" "PathName" + StrCmp $R0 "" TrySDK + StrCpy $INSTDIR $R0 + goto Nope + +TrySDK: + ReadRegStr $R0 HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" "PathName" + StrCmp $R0 "" TryDocs + StrCpy $INSTDIR $R0 + goto Nope + +TryDocs: + ReadRegStr $R0 HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" "PathName" + StrCmp $R0 "" TryRoot + StrCpy $INSTDIR $R0 + goto Nope + +TryRoot: + ReadRegStr $R0 HKLM "${KFW_REGKEY_ROOT}" "InstallDir" + StrCmp $R0 "" Nope + StrCpy $INSTDIR $R0 + +Nope: + Pop $R0 + + GetTempFilename $0 + File /oname=$0 KfWConfigPage.ini + GetTempFilename $1 + File /oname=$1 KfWConfigPage2.ini + +FunctionEnd + + +;-------------------------------- +; These are our cleanup functions +Function .onInstFailed +Delete $0 +Delete $1 +FunctionEnd + +Function .onInstSuccess +Delete $0 +Delete $1 +FunctionEnd + + +;-------------------------------- +;Descriptions + + !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${secClient} $(DESC_secClient) + !insertmacro MUI_DESCRIPTION_TEXT ${secSDK} $(DESC_secSDK) + !insertmacro MUI_DESCRIPTION_TEXT ${secDocs} $(DESC_secDocs) + !insertmacro MUI_DESCRIPTION_TEXT ${secDebug} $(DESC_secDebug) + !insertmacro MUI_FUNCTION_DESCRIPTION_END + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + ; Make sure the user REALLY wants to do this, unless they did a silent uninstall, in which case...let them! + IfSilent StartRemove ; New in v2.0b4 + MessageBox MB_YESNO "Are you sure you want to remove MIT ${PROGRAM_NAME} from this machine?" IDYES StartRemove + abort + +StartRemove: + + SetShellVarContext all + ; Stop the running processes + GetTempFileName $R0 + File /oname=$R0 "Killer.exe" + nsExec::Exec '$R0 netidmgr.exe' + nsExec::Exec '$R0 krbcc32s.exe' + + Push "$INSTDIR\bin" + Call un.RemoveFromSystemPath + + ; Delete documentation + Delete "$INSTDIR\doc\relnotes.html" + Delete "$INSTDIR\doc\netidmgr_userdoc.pdf" + Delete "$INSTDIR\doc\netiddev.chm" + + Delete /REBOOTOK "$INSTDIR\bin\comerr32.dll" + Delete /REBOOTOK "$INSTDIR\bin\gss.exe" + Delete /REBOOTOK "$INSTDIR\bin\gss-client.exe" + Delete /REBOOTOK "$INSTDIR\bin\gss-server.exe" + Delete /REBOOTOK "$INSTDIR\bin\gssapi32.dll" + Delete /REBOOTOK "$INSTDIR\bin\k524init.exe" + Delete /REBOOTOK "$INSTDIR\bin\kclnt32.dll" + Delete /REBOOTOK "$INSTDIR\bin\kdestroy.exe" + Delete /REBOOTOK "$INSTDIR\bin\kinit.exe" + Delete /REBOOTOK "$INSTDIR\bin\klist.exe" + Delete /REBOOTOK "$INSTDIR\bin\kpasswd.exe" + Delete /REBOOTOK "$INSTDIR\bin\kvno.exe" + Delete /REBOOTOK "$INSTDIR\bin\krb5_32.dll" + Delete /REBOOTOK "$INSTDIR\bin\k5sprt32.dll" + Delete /REBOOTOK "$INSTDIR\bin\krb524.dll" + Delete /REBOOTOK "$INSTDIR\bin\krbcc32.dll" + Delete /REBOOTOK "$INSTDIR\bin\krbcc32s.exe" + Delete /REBOOTOK "$INSTDIR\bin\krbv4w32.dll" + Delete /REBOOTOK "$INSTDIR\bin\netidmgr.exe" + Delete /REBOOTOK "$INSTDIR\bin\netidmgr.chm" + Delete /REBOOTOK "$INSTDIR\bin\nidmgr32.dll" + Delete /REBOOTOK "$INSTDIR\bin\krb4cred.dll" + Delete /REBOOTOK "$INSTDIR\bin\krb5cred.dll" + Delete /REBOOTOK "$INSTDIR\bin\krb4cred_en_us.dll" + Delete /REBOOTOK "$INSTDIR\bin\krb5cred_en_us.dll" + Delete /REBOOTOK "$INSTDIR\bin\leashw32.dll" + Delete /REBOOTOK "$INSTDIR\bin\ms2mit.exe" + Delete /REBOOTOK "$INSTDIR\bin\mit2ms.exe" + Delete /REBOOTOK "$INSTDIR\bin\kcpytkt.exe" + Delete /REBOOTOK "$INSTDIR\bin\kdeltkt.exe" + Delete /REBOOTOK "$INSTDIR\bin\wshelp32.dll" + Delete /REBOOTOK "$INSTDIR\bin\xpprof32.dll" + Delete /REBOOTOK "$SYSDIR\bin\kfwlogon.dll" + Delete /REBOOTOK "$SYSDIR\bin\kfwcpcc.exe" + + Delete /REBOOTOK "$INSTDIR\bin\comerr32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\gss.pdb" + Delete /REBOOTOK "$INSTDIR\bin\gss-client.pdb" + Delete /REBOOTOK "$INSTDIR\bin\gss-server.pdb" + Delete /REBOOTOK "$INSTDIR\bin\gssapi32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\k524init.pdb" + Delete /REBOOTOK "$INSTDIR\bin\kclnt32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\kdestroy.pdb" + Delete /REBOOTOK "$INSTDIR\bin\kinit.pdb" + Delete /REBOOTOK "$INSTDIR\bin\klist.pdb" + Delete /REBOOTOK "$INSTDIR\bin\kpasswd.pdb" + Delete /REBOOTOK "$INSTDIR\bin\kvno.pdb" + Delete /REBOOTOK "$INSTDIR\bin\krb5_32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\k5sprt32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\krb524.pdb" + Delete /REBOOTOK "$INSTDIR\bin\krbcc32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\krbcc32s.pdb" + Delete /REBOOTOK "$INSTDIR\bin\krbv4w32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\netidmgr.pdb" + Delete /REBOOTOK "$INSTDIR\bin\nidmgr32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\krb4cred.pdb" + Delete /REBOOTOK "$INSTDIR\bin\krb5cred.pdb" + Delete /REBOOTOK "$INSTDIR\bin\leashw32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\ms2mit.pdb" + Delete /REBOOTOK "$INSTDIR\bin\mit2ms.pdb" + Delete /REBOOTOK "$INSTDIR\bin\kcpytkt.pdb" + Delete /REBOOTOK "$INSTDIR\bin\kdeltkt.pdb" + Delete /REBOOTOK "$INSTDIR\bin\wshelp32.pdb" + Delete /REBOOTOK "$INSTDIR\bin\xpprof32.pdb" + Delete /REBOOTOK "$SYSDIR\bin\kfwlogon.pdb" + Delete /REBOOTOK "$SYSDIR\bin\kfwcpcc.pdb" + +!IFDEF DEBUG +!IFDEF CL_1400 + Delete /REBOOTOK "$INSTDIR\bin\msvcr80d.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcr80d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\msvcp80d.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp80d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\mfc80d.dll" + Delete /REBOOTOK "$INSTDIR\bin\mfc80d.pdb" +!ELSE +!IFDEF CL_1310 + Delete /REBOOTOK "$INSTDIR\bin\msvcr71d.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcr71d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\msvcp71d.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp71d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\mfc71d.dll" + Delete /REBOOTOK "$INSTDIR\bin\mfc71d.pdb" +!ELSE +!IFDEF CL_1300 + Delete /REBOOTOK "$INSTDIR\bin\msvcr70d.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcr70d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\msvcp70d.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp70d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\mfc70d.dll" + Delete /REBOOTOK "$INSTDIR\bin\mfc70d.pdb" +!ELSE + Delete /REBOOTOK "$INSTDIR\bin\mfc42d.dll" + Delete /REBOOTOK "$INSTDIR\bin\mfc42d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\msvcp60d.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp60d.pdb" + Delete /REBOOTOK "$INSTDIR\bin\msvcrtd.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcrtd.pdb" +!ENDIF +!ENDIF +!ENDIF +!ELSE +!IFDEF CL_1400 + Delete /REBOOTOK "$INSTDIR\bin\mfc80.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcr80.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp80.dll" + Delete /REBOOTOK "$INSTDIR\bin\MFC80CHS.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80CHT.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80DEU.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80ENU.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80ESP.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80FRA.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80ITA.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80JPN.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC80KOR.DLL" +!ELSE +!IFDEF CL_1310 + Delete /REBOOTOK "$INSTDIR\bin\mfc71.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcr71.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp71.dll" + Delete /REBOOTOK "$INSTDIR\bin\MFC71CHS.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71CHT.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71DEU.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71ENU.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71ESP.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71FRA.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71ITA.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71JPN.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC71KOR.DLL" +!ELSE +!IFDEF CL_1300 + Delete /REBOOTOK "$INSTDIR\bin\mfc70.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcr70.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp70.dll" + Delete /REBOOTOK "$INSTDIR\bin\MFC70CHS.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70CHT.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70DEU.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70ENU.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70ESP.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70FRA.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70ITA.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70JPN.DLL" + Delete /REBOOTOK "$INSTDIR\bin\MFC70KOR.DLL" +!ELSE + Delete /REBOOTOK "$INSTDIR\bin\mfc42.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcp60.dll" + Delete /REBOOTOK "$INSTDIR\bin\msvcrt.dll" +!ENDIF +!ENDIF +!ENDIF +!ENDIF + Delete /REBOOTOK "$INSTDIR\bin\psapi.dll" + + RMDir "$INSTDIR\bin" + RmDir "$INSTDIR\doc" + RmDir "$INSTDIR\lib" + RmDir "$INSTDIR\inc" + RmDir "$INSTDIR\install" + RMDir "$INSTDIR" + + Delete "$SMPROGRAMS\${PROGRAM_NAME}\Uninstall ${PROGRAM_NAME}.lnk" + Delete "$SMPROGRAMS\${PROGRAM_NAME}\Network Identity Manager.lnk" + Delete "$SMPROGRAMS\${PROGRAM_NAME}\Release Notes.lnk" + Delete "$SMPROGRAMS\${PROGRAM_NAME}\Network Identity Manager User Documentation.lnk" + Delete "$SMPROGRAMS\${PROGRAM_NAME}\Network Identity Developer Documentation.lnk" + RmDir "$SMPROGRAMS\${PROGRAM_NAME}" + Delete "$SMSTARTUP\Network Identity Manager.lnk" + + IfSilent SkipAsk +; IfFileExists "$WINDIR\krb5.ini" CellExists SkipDelAsk +; RealmExists: + MessageBox MB_YESNO "Would you like to keep your configuration files?" IDYES SkipDel + SkipAsk: + Delete "$WINDIR\krb5.ini" + Delete "$WINDIR\krb.con" + Delete "$WINDIR\krbrealm.con" + + SkipDel: + Delete "$INSTDIR\Uninstall.exe" + + ; Restore previous value of AllowTGTSessionKey + ReadRegDWORD $R0 HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "AllowTGTSessionKeyBackup" + WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters" "AllowTGTSessionKey" $R0 + ReadRegDWORD $R0 HKLM "${KFW_REGKEY_ROOT}\Client\${KFW_VERSION}" "AllowTGTSessionKeyBackup2" + WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Control\Lsa\Kerberos" "AllowTGTSessionKey" $R0 + + ; The following are keys added for Terminal Server compatibility + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\netidmgr" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kinit" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klist" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdestroy" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-client" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-server" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k524init" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kpasswd" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kvno" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\ms2mit" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\mit2ms" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kcpytkt" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdeltkt" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k95" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k95g" + + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Client\CurrentVersion" + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Client" + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Documentation\CurrentVersion" + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\Documentation" + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\SDK\CurrentVersion" + DeleteRegKey HKLM "${KFW_REGKEY_ROOT}\SDK" + DeleteRegKey /ifempty HKLM "${KFW_REGKEY_ROOT}" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" + + ; NIM Registry Keys + DeleteRegKey HKLM "${NIM_REGKEY_ROOT}\PluginManager\Modules\MITKrb5" + DeleteRegKey HKLM "${NIM_REGKEY_ROOT}\PluginManager\Modules\MITKrb4" + DeleteRegKey HKLM "${NIM_REGKEY_ROOT}\PluginManager\Plugins\Krb5Cred" + DeleteRegKey HKLM "${NIM_REGKEY_ROOT}\PluginManager\Plugins\Krb5Ident" + DeleteRegKey HKLM "${NIM_REGKEY_ROOT}\PluginManager\Plugins\Krb4Cred" + DeleteRegKey /ifempty HKLM "${NIM_REGKEY_ROOT}\PluginManager\Modules" + DeleteRegKey /ifempty HKLM "${NIM_REGKEY_ROOT}\PluginManager\Plugins" + DeleteRegKey /ifempty HKLM "${NIM_REGKEY_ROOT}\PluginManager" + DeleteRegKey /ifempty HKLM "${NIM_REGKEY_ROOT}" + + ; WinLogon Event Notification + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\MIT_KFW" + DeleteRegKey HKLM "SYSTEM\CurrentControlSet\Services\MIT Kerberos" + + RMDir "$INSTDIR" + +SectionEnd + +;-------------------------------- +;Uninstaller Functions + +Function un.onInit + + ;Get language from registry + ReadRegStr $LANGUAGE ${MUI_LANGDLL_REGISTRY_ROOT} "${MUI_LANGDLL_REGISTRY_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}" + +FunctionEnd + +Function un.onUninstSuccess + + MessageBox MB_OK "Please reboot your machine to complete uninstallation of the software" + +FunctionEnd + +;------------------------------ +; Get the Configurations files from the Internet + +Function kfw.GetConfigFiles + +;Check if we should download Config Files +ReadINIStr $R0 $0 "Field 4" "State" +StrCmp $R0 "1" DoDownload + +;Do nothing if we're keeping the existing file +ReadINIStr $R0 $0 "Field 2" "State" +StrCmp $R0 "1" done + +ReadINIStr $R0 $0 "Field 3" "State" +StrCmp $R0 "1" UsePackaged + +; If none of these, grab file from other location +goto CheckOther + +DoDownload: + ReadINIStr $R0 $0 "Field 5" "State" + NSISdl::download "$R0/krb5.ini" "$WINDIR\krb5.ini" + NSISdl::download "$R0/krb.con" "$WINDIR\krb.con" + NSISdl::download "$R0/krbrealm.con" "$WINDIR\krbrealm.con" + Pop $R0 ;Get the return value + StrCmp $R0 "success" done + MessageBox MB_OK|MB_ICONSTOP "Download failed: $R0" + goto done + +UsePackaged: + SetOutPath "$WINDIR" + File "${KFW_CONFIG_DIR}\sample\krb5.ini" + File "${KFW_CONFIG_DIR}\sample\krb.con" + File "${KFW_CONFIG_DIR}\sample\krbrealm.con" + goto done + +CheckOther: + ReadINIStr $R0 $0 "Field 7" "State" + StrCmp $R0 "" done + CopyFiles "$R0\krb5.ini" "$WINDIR\krb5.ini" + CopyFiles "$R0\krb.con" "$WINDIR\krb.con" + CopyFiles "$R0\krbrealm.con" "$WINDIR\krbrealm.con" + +done: + +FunctionEnd + + + +;------------------------------- +;Do the page to get the Config files + +Function KFWPageGetConfigFiles + ; Skip this page if we are not installing the client + SectionGetFlags ${secClient} $R0 + IntOp $R0 $R0 & ${SF_SELECTED} + StrCmp $R0 "0" Skip + + ; Set the install options here + +startOver: + WriteINIStr $0 "Field 2" "Flags" "DISABLED" + WriteINIStr $0 "Field 3" "State" "1" + WriteINIStr $0 "Field 4" "State" "0" + WriteINIStr $0 "Field 6" "State" "0" + WriteINIStr $0 "Field 3" "Text" "Use packaged configuration files for the ${SAMPLE_CONFIG_REALM} realm." + WriteINIStr $0 "Field 5" "State" "${HTTP_CONFIG_URL}" + + ; If there is an existing krb5.ini file, allow the user to choose it and make it default + IfFileExists "$WINDIR\krb5.ini" +1 notpresent + WriteINIStr $0 "Field 2" "Flags" "ENABLED" + WriteINIStr $0 "Field 2" "State" "1" + WriteINIStr $0 "Field 3" "State" "0" + + notpresent: + + !insertmacro MUI_HEADER_TEXT "Kerberos Configuration" "Please choose a method for installing the Kerberos Configuration files:" + InstallOptions::dialog $0 + Pop $R1 + StrCmp $R1 "cancel" exit + StrCmp $R1 "back" done + StrCmp $R1 "success" done +exit: Quit +done: + + ; Check that if a file is set, a valid filename is entered... + ReadINIStr $R0 $0 "Field 6" "State" + StrCmp $R0 "1" CheckFileName + + ;Check if a URL is specified, one *IS* specified + ReadINIStr $R0 $0 "Field 4" "State" + StrCmp $R0 "1" CheckURL Skip + + CheckURL: + ReadINIStr $R0 $0 "Field 5" "State" + StrCmp $R0 "" +1 Skip + MessageBox MB_OK|MB_ICONSTOP $(URLError) + WriteINIStr $0 "Field 4" "State" "0" + goto startOver + + CheckFileName: + ReadINIStr $R0 $0 "Field 7" "State" + IfFileExists "$R0\krb5.ini" Skip + + MessageBox MB_OK|MB_ICONSTOP $(ConfigFileError) + WriteINIStr $0 "Field 6" "State" "0" + goto startOver + + Skip: + +FunctionEnd + + +;------------------------------- +;Do the page to get the Startup Configuration + +Function KFWPageGetStartupConfig + ; Skip this page if we are not installing the client + SectionGetFlags ${secClient} $R0 + IntOp $R0 $R0 & ${SF_SELECTED} + StrCmp $R0 "0" Skip + + ; Set the install options here + + !insertmacro MUI_HEADER_TEXT "Network Identity Manager Setup" "Please select Network Identity ticket manager setup options:" + InstallOptions::dialog $1 + Pop $R1 + StrCmp $R1 "cancel" exit + StrCmp $R1 "back" done + StrCmp $R1 "success" done +exit: + Quit +done: +skip: + +FunctionEnd + + +;------------- +; Common install routines for each module +Function KFWCommon.Install + + WriteRegStr HKLM "${KFW_REGKEY_ROOT}" "InstallDir" $INSTDIR + + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" "DisplayName" "${PROGRAM_NAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" "UninstallString" "$INSTDIR\uninstall.exe" +!ifndef DEBUG + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" "DisplayVersion" "${KFW_VERSION}" +!else + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" "DisplayVersion" "${KFW_VERSION} Checked/Debug" +!endif + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" "URLInfoAbout" "http://web.mit.edu/kerberos/" + +!ifdef DEBUG + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\CurrentVersion" "Debug" 1 + WriteRegDWORD HKLM "${KFW_REGKEY_ROOT}\${KFW_VERSION}" "Debug" 1 +!else + ; Delete the DEBUG string + DeleteRegValue HKLM "${KFW_REGKEY_ROOT}\CurrentVersion" "Debug" + DeleteRegValue HKLM "${KFW_REGKEY_ROOT}\${KFW_VERSION}" "Debug" +!endif + + WriteUninstaller "$INSTDIR\Uninstall.exe" +FunctionEnd + + +;------------------------------- +; Check if the client should be checked for default install +Function ShouldClientInstall + Push $R0 + StrCpy $R2 "Client" + Call GetInstalledVersion + Pop $R0 + + StrCmp $R0 "" NotInstalled + ; Now we see if it's an older or newer version + + Call GetInstalledVersionMajor + Pop $R0 + IntCmpU $R0 ${KFW_MAJORVERSION} +1 Upgrade Downgrade + + Call GetInstalledVersionMinor + Pop $R0 + IntCmpU $R0 ${KFW_MINORVERSION} +1 Upgrade Downgrade + + Call GetInstalledVersionPatch + Pop $R0 + IntCmpU $R0 ${KFW_PATCHLEVEL} Reinstall Upgrade Downgrade + +Reinstall: + StrCpy $R0 "1" + Exch $R0 + goto end + +Upgrade: + StrCpy $R0 "2" + Exch $R0 + goto end + +Downgrade: + StrCpy $R0 "3" + Exch $R0 + goto end + +NotInstalled: + StrCpy $R0 "0" + Exch $R0 +end: +FunctionEnd + +;------------------------------- +; Check how the Documentation options should be set +Function ShouldDocumentationInstall + Push $R0 + StrCpy $R2 "Documentation" + Call GetInstalledVersion + Pop $R0 + + StrCmp $R0 "" NotInstalled + ; Now we see if it's an older or newer version + + Call GetInstalledVersionMajor + Pop $R0 + IntCmpU $R0 ${KFW_MAJORVERSION} +1 Upgrade Downgrade + + Call GetInstalledVersionMinor + Pop $R0 + IntCmpU $R0 ${KFW_MINORVERSION} +1 Upgrade Downgrade + + Call GetInstalledVersionPatch + Pop $R0 + IntCmpU $R0 ${KFW_PATCHLEVEL} Reinstall Upgrade Downgrade + +Reinstall: + StrCpy $R0 "1" + Exch $R0 + goto end + +Upgrade: + StrCpy $R0 "2" + Exch $R0 + goto end + +Downgrade: + StrCpy $R0 "3" + Exch $R0 + goto end + + +NotInstalled: + StrCpy $R0 "0" + Exch $R0 +end: +FunctionEnd + + +;------------------------------- +; Check how the SDK options should be set +Function ShouldSDKInstall + Push $R0 + StrCpy $R2 "SDK" + Call GetInstalledVersion + Pop $R0 + + StrCmp $R0 "" NotInstalled + ; Now we see if it's an older or newer version + + Call GetInstalledVersionMajor + Pop $R0 + IntCmpU $R0 ${KFW_MAJORVERSION} +1 Upgrade Downgrade + + Call GetInstalledVersionMinor + Pop $R0 + IntCmpU $R0 ${KFW_MINORVERSION} +1 Upgrade Downgrade + + Call GetInstalledVersionPatch + Pop $R0 + IntCmpU $R0 ${KFW_PATCHLEVEL} Reinstall Upgrade Downgrade + +Reinstall: + StrCpy $R0 "1" + Exch $R0 + goto end + +Upgrade: + StrCpy $R0 "2" + Exch $R0 + goto end + +Downgrade: + StrCpy $R0 "3" + Exch $R0 + goto end + + +NotInstalled: + StrCpy $R0 "0" + Exch $R0 +end: +FunctionEnd + +; See if KfW SDK is installed +; Returns: "1" if it is, 0 if it is not (on the stack) +Function IsSDKInstalled + Push $R0 + StrCpy $R2 "SDK" + Call GetInstalledVersion + Pop $R0 + + StrCmp $R0 "" NotInstalled + + StrCpy $R0 "1" + Exch $R0 + goto end + +NotInstalled: + StrCpy $R0 "0" + Exch $R0 +end: +FunctionEnd + + +; See if KfW Client is installed +; Returns: "1" if it is, 0 if it is not (on the stack) +Function IsClientInstalled + Push $R0 + StrCpy $R2 "Client" + Call GetInstalledVersion + Pop $R0 + + StrCmp $R0 "" NotInstalled + + StrCpy $R0 "1" + Exch $R0 + goto end + +NotInstalled: + StrCpy $R0 "0" + Exch $R0 +end: +FunctionEnd + + + +; See if KfW Documentation is installed +; Returns: "1" if it is, 0 if it is not (on the stack) +Function IsDocumentationInstalled + Push $R0 + StrCpy $R2 "Documentation" + Call GetInstalledVersion + Pop $R0 + + StrCmp $R0 "" NotInstalled + + StrCpy $R0 "1" + Exch $R0 + goto end + +NotInstalled: + StrCpy $R0 "0" + Exch $R0 +end: +FunctionEnd + + + +;Check to see if any KfW component is installed +;Returns: Value on stack: "1" if it is, "0" if it is not +Function IsAnyKfWInstalled + Push $R0 + Push $R1 + Push $R2 + Call IsClientInstalled + Pop $R0 + Call IsSDKInstalled + Pop $R1 + Call IsDocumentationInstalled + Pop $R2 + ; Now we must see if ANY of the $Rn values are 1 + StrCmp $R0 "1" SomethingInstalled + StrCmp $R1 "1" SomethingInstalled + StrCmp $R2 "1" SomethingInstalled + ;Nothing installed + StrCpy $R0 "0" + goto end +SomethingInstalled: + StrCpy $R0 "1" +end: + Pop $R2 + Pop $R1 + Exch $R0 +FunctionEnd + +;-------------------------------- +;Handle what must and what must not be installed +Function .onSelChange + ; If they install the SDK, they MUST install the client + SectionGetFlags ${secSDK} $R0 + IntOp $R0 $R0 & ${SF_SELECTED} + StrCmp $R0 "1" MakeClientSelected + goto end + +MakeClientSelected: + SectionGetFlags ${secClient} $R0 + IntOp $R0 $R0 | ${SF_SELECTED} + SectionSetFlags ${secClient} $R0 + +end: +FunctionEnd + +Function AddProvider + Push $R0 + Push $R1 + ReadRegStr $R0 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder" "ProviderOrder" + Push $R0 + StrCpy $R0 "MIT Kerberos" + Push $R0 + Call StrStr + Pop $R0 + StrCmp $R0 "" DoOther +1 + ReadRegStr $R1 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder" "ProviderOrder" + StrCpy $R0 "$R1,MIT Kerberos" + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder" "ProviderOrder" $R0 +DoOther: + ReadRegStr $R0 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" "ProviderOrder" + Push $R0 + StrCpy $R0 "MIT Kerberos" + Push $R0 + Call StrStr + Pop $R0 + StrCmp $R0 "" +1 End + ReadRegStr $R1 HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" "ProviderOrder" + StrCpy $R0 "$R1,MIT Kerberos" + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" "ProviderOrder" $R0 +End: + Pop $R1 + Pop $R0 +FunctionEnd + +Function un.RemoveProvider + Push $R0 + StrCpy $R0 "MIT Kerberos" + Push $R0 + StrCpy $R0 "SYSTEM\CurrentControlSet\Control\NetworkProvider\HWOrder" + Call un.RemoveFromProvider + StrCpy $R0 "MIT Kerberos" + Push $R0 + StrCpy $R0 "SYSTEM\CurrentControlSet\Control\NetworkProvider\Order" + Call un.RemoveFromProvider + Pop $R0 +FunctionEnd + +Function un.RemoveFromProvider + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + ReadRegStr $1 HKLM "$R0" "ProviderOrder" + StrCpy $5 $1 1 -1 # copy last char + StrCmp $5 "," +2 # if last char != , + StrCpy $1 "$1," # append , + Push $1 + Push "$0," + Call un.StrStr ; Find `$0,` in $1 + Pop $2 ; pos of our dir + StrCmp $2 "" unRemoveFromPath_done + ; else, it is in path + # $0 - path to add + # $1 - path var + StrLen $3 "$0," + StrLen $4 $2 + StrCpy $5 $1 -$4 # $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove + StrCpy $3 $5$6 + + StrCpy $5 $3 1 -1 # copy last char + StrCmp $5 "," 0 +2 # if last char == , + StrCpy $3 $3 -1 # remove last char + + WriteRegStr HKLM "$R0" "ProviderOrder" $3 + + unRemoveFromPath_done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd diff --git a/krb5-1-6/src/windows/installer/nsis/kfw.ico b/krb5-1-6/src/windows/installer/nsis/kfw.ico new file mode 100644 index 0000000000000000000000000000000000000000..8dcb29e7a66f097ad2f67b181bb352fb2421d3d9 GIT binary patch literal 25214 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 Nl|lr5Zx?I${{ZwxG8zB? literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/nsis/kfw.nsi b/krb5-1-6/src/windows/installer/nsis/kfw.nsi new file mode 100644 index 000000000..a6f2733e1 --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/kfw.nsi @@ -0,0 +1,16 @@ +;KfW Install Script for NSIS +; +; Written by Jeffrey Altman <jaltman@mit.edu> +; based on the OpenAFS installer written by Rob Murawski <rsm4@ieee.org> +; +;Based on: +;NSIS Modern User Interface version 1.63 +;MultiLanguage Example Script +;Written by Joost Verburg +; +; This version compiles with NSIS v2.0b4 + +!include site-local.nsi +!include "MUI.nsh" +!include Sections.nsh +!include "kfw-fixed.nsi" diff --git a/krb5-1-6/src/windows/installer/nsis/killer.cpp b/krb5-1-6/src/windows/installer/nsis/killer.cpp new file mode 100644 index 000000000..7ba27fc20 --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/killer.cpp @@ -0,0 +1,380 @@ +/* + Process Killer for NSIS script + + Rob Murawski + + Released under terms of IBM Open Source agreement for OpenAFS + + */ + + +#include <windows.h> +#include <stdio.h> +#include <tlhelp32.h> +#include <vdmdbg.h> + +char strProcessName[256]; + +typedef BOOL (CALLBACK *PROCENUMPROC)(DWORD, WORD, LPSTR, LPARAM); + +typedef struct { + DWORD dwPID; + PROCENUMPROC lpProc; + DWORD lParam; + BOOL bEnd; +} EnumInfoStruct; + +BOOL WINAPI EnumProcs(PROCENUMPROC lpProc, LPARAM lParam); + +BOOL WINAPI Enum16(DWORD dwThreadId, WORD hMod16, WORD hTask16, + PSZ pszModName, PSZ pszFileName, LPARAM lpUserDefined); + +// +// The EnumProcs function takes a pointer to a callback function +// that will be called once per process with the process filename +// and process ID. +// +// lpProc -- Address of callback routine. +// +// lParam -- A user-defined LPARAM value to be passed to +// the callback routine. +// +// Callback function definition: +// BOOL CALLBACK Proc(DWORD dw, WORD w, LPCSTR lpstr, LPARAM lParam); +// +BOOL WINAPI EnumProcs(PROCENUMPROC lpProc, LPARAM lParam) { + + OSVERSIONINFO osver; + HINSTANCE hInstLib = NULL; + HINSTANCE hInstLib2 = NULL; + HANDLE hSnapShot = NULL; + LPDWORD lpdwPIDs = NULL; + PROCESSENTRY32 procentry; + BOOL bFlag; + DWORD dwSize; + DWORD dwSize2; + DWORD dwIndex; + HMODULE hMod; + HANDLE hProcess; + char szFileName[MAX_PATH]; + EnumInfoStruct sInfo; + + // ToolHelp Function Pointers. + HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD, DWORD); + BOOL (WINAPI *lpfProcess32First)(HANDLE, LPPROCESSENTRY32); + BOOL (WINAPI *lpfProcess32Next)(HANDLE, LPPROCESSENTRY32); + + // PSAPI Function Pointers. + BOOL (WINAPI *lpfEnumProcesses)(DWORD *, DWORD, DWORD *); + BOOL (WINAPI *lpfEnumProcessModules)(HANDLE, HMODULE *, DWORD, + LPDWORD); + DWORD (WINAPI *lpfGetModuleBaseName)(HANDLE, HMODULE, LPTSTR, DWORD); + + // VDMDBG Function Pointers. + INT (WINAPI *lpfVDMEnumTaskWOWEx)(DWORD, TASKENUMPROCEX, LPARAM); + + // Retrieve the OS version + osver.dwOSVersionInfoSize = sizeof(osver); + if (!GetVersionEx(&osver)) + return FALSE; + + // If Windows NT 4.0 + if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT + && osver.dwMajorVersion == 4) { + + __try { + + // Get the procedure addresses explicitly. We do + // this so we don't have to worry about modules + // failing to load under OSes other than Windows NT 4.0 + // because references to PSAPI.DLL can't be resolved. + hInstLib = LoadLibraryA("PSAPI.DLL"); + if (hInstLib == NULL) + __leave; + + hInstLib2 = LoadLibraryA("VDMDBG.DLL"); + if (hInstLib2 == NULL) + __leave; + + // Get procedure addresses. + lpfEnumProcesses = (BOOL (WINAPI *)(DWORD *, DWORD, DWORD*)) + GetProcAddress(hInstLib, "EnumProcesses"); + + lpfEnumProcessModules = (BOOL (WINAPI *)(HANDLE, HMODULE *, + DWORD, LPDWORD)) GetProcAddress(hInstLib, + "EnumProcessModules"); + + lpfGetModuleBaseName = (DWORD (WINAPI *)(HANDLE, HMODULE, + LPTSTR, DWORD)) GetProcAddress(hInstLib, + "GetModuleBaseNameA"); + + lpfVDMEnumTaskWOWEx = (INT (WINAPI *)(DWORD, TASKENUMPROCEX, + LPARAM)) GetProcAddress(hInstLib2, "VDMEnumTaskWOWEx"); + + if (lpfEnumProcesses == NULL + || lpfEnumProcessModules == NULL + || lpfGetModuleBaseName == NULL + || lpfVDMEnumTaskWOWEx == NULL) + __leave; + + // + // Call the PSAPI function EnumProcesses to get all of the + // ProcID's currently in the system. + // + // NOTE: In the documentation, the third parameter of + // EnumProcesses is named cbNeeded, which implies that you + // can call the function once to find out how much space to + // allocate for a buffer and again to fill the buffer. + // This is not the case. The cbNeeded parameter returns + // the number of PIDs returned, so if your buffer size is + // zero cbNeeded returns zero. + // + // NOTE: The "HeapAlloc" loop here ensures that we + // actually allocate a buffer large enough for all the + // PIDs in the system. + // + dwSize2 = 256 * sizeof(DWORD); + do { + + if (lpdwPIDs) { + HeapFree(GetProcessHeap(), 0, lpdwPIDs); + dwSize2 *= 2; + } + + lpdwPIDs = (LPDWORD) HeapAlloc(GetProcessHeap(), 0, + dwSize2); + if (lpdwPIDs == NULL) + __leave; + + if (!lpfEnumProcesses(lpdwPIDs, dwSize2, &dwSize)) + __leave; + + } while (dwSize == dwSize2); + + // How many ProcID's did we get? + dwSize /= sizeof(DWORD); + + // Loop through each ProcID. + for (dwIndex = 0; dwIndex < dwSize; dwIndex++) { + + szFileName[0] = 0; + + // Open the process (if we can... security does not + // permit every process in the system to be opened). + hProcess = OpenProcess( + PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, lpdwPIDs[dwIndex]); + if (hProcess != NULL) { + + // Here we call EnumProcessModules to get only the + // first module in the process. This will be the + // EXE module for which we will retrieve the name. + if (lpfEnumProcessModules(hProcess, &hMod, + sizeof(hMod), &dwSize2)) { + + // Get the module name + if (!lpfGetModuleBaseName(hProcess, hMod, + szFileName, sizeof(szFileName))) + szFileName[0] = 0; + } + CloseHandle(hProcess); + } + // Regardless of OpenProcess success or failure, we + // still call the enum func with the ProcID. + if (!lpProc(lpdwPIDs[dwIndex], 0, szFileName, lParam)) + break; + + // Did we just bump into an NTVDM? + if (_stricmp(szFileName, "NTVDM.EXE") == 0) { + + // Fill in some info for the 16-bit enum proc. + sInfo.dwPID = lpdwPIDs[dwIndex]; + sInfo.lpProc = lpProc; + sInfo.lParam = (DWORD) lParam; + sInfo.bEnd = FALSE; + + // Enum the 16-bit stuff. + lpfVDMEnumTaskWOWEx(lpdwPIDs[dwIndex], + (TASKENUMPROCEX) Enum16, (LPARAM) &sInfo); + + // Did our main enum func say quit? + if (sInfo.bEnd) + break; + } + } + + } __finally { + + if (hInstLib) + FreeLibrary(hInstLib); + + if (hInstLib2) + FreeLibrary(hInstLib2); + + if (lpdwPIDs) + HeapFree(GetProcessHeap(), 0, lpdwPIDs); + } + + // If any OS other than Windows NT 4.0. + } else if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS + || (osver.dwPlatformId == VER_PLATFORM_WIN32_NT + && osver.dwMajorVersion > 4)) { + + __try { + + hInstLib = LoadLibraryA("Kernel32.DLL"); + if (hInstLib == NULL) + __leave; + + // If NT-based OS, load VDMDBG.DLL. + if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { + hInstLib2 = LoadLibraryA("VDMDBG.DLL"); + if (hInstLib2 == NULL) + __leave; + } + + // Get procedure addresses. We are linking to + // these functions explicitly, because a module using + // this code would fail to load under Windows NT, + // which does not have the Toolhelp32 + // functions in KERNEL32.DLL. + lpfCreateToolhelp32Snapshot = + (HANDLE (WINAPI *)(DWORD,DWORD)) + GetProcAddress(hInstLib, "CreateToolhelp32Snapshot"); + + lpfProcess32First = + (BOOL (WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress(hInstLib, "Process32First"); + + lpfProcess32Next = + (BOOL (WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress(hInstLib, "Process32Next"); + + if (lpfProcess32Next == NULL + || lpfProcess32First == NULL + || lpfCreateToolhelp32Snapshot == NULL) + __leave; + + if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { + lpfVDMEnumTaskWOWEx = (INT (WINAPI *)(DWORD, TASKENUMPROCEX, + LPARAM)) GetProcAddress(hInstLib2, "VDMEnumTaskWOWEx"); + if (lpfVDMEnumTaskWOWEx == NULL) + __leave; + } + + // Get a handle to a Toolhelp snapshot of all processes. + hSnapShot = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapShot == INVALID_HANDLE_VALUE) { + FreeLibrary(hInstLib); + return FALSE; + } + + // Get the first process' information. + procentry.dwSize = sizeof(PROCESSENTRY32); + bFlag = lpfProcess32First(hSnapShot, &procentry); + + // While there are processes, keep looping. + while (bFlag) { + + // Call the enum func with the filename and ProcID. + if (lpProc(procentry.th32ProcessID, 0, + procentry.szExeFile, lParam)) { + + // Did we just bump into an NTVDM? + if (_stricmp(procentry.szExeFile, "NTVDM.EXE") == 0) { + + // Fill in some info for the 16-bit enum proc. + sInfo.dwPID = procentry.th32ProcessID; + sInfo.lpProc = lpProc; + sInfo.lParam = (DWORD) lParam; + sInfo.bEnd = FALSE; + + // Enum the 16-bit stuff. + lpfVDMEnumTaskWOWEx(procentry.th32ProcessID, + (TASKENUMPROCEX) Enum16, (LPARAM) &sInfo); + + // Did our main enum func say quit? + if (sInfo.bEnd) + break; + } + + procentry.dwSize = sizeof(PROCESSENTRY32); + bFlag = lpfProcess32Next(hSnapShot, &procentry); + + } else + bFlag = FALSE; + } + + } __finally { + + if (hInstLib) + FreeLibrary(hInstLib); + + if (hInstLib2) + FreeLibrary(hInstLib2); + } + + } else + return FALSE; + + // Free the library. + FreeLibrary(hInstLib); + + return TRUE; +} + + +BOOL WINAPI Enum16(DWORD dwThreadId, WORD hMod16, WORD hTask16, + PSZ pszModName, PSZ pszFileName, LPARAM lpUserDefined) { + + BOOL bRet; + + EnumInfoStruct *psInfo = (EnumInfoStruct *)lpUserDefined; + + bRet = psInfo->lpProc(psInfo->dwPID, hTask16, pszFileName, + psInfo->lParam); + + if (!bRet) + psInfo->bEnd = TRUE; + + return !bRet; +} + + +BOOL CALLBACK MyProcessEnumerator(DWORD dwPID, WORD wTask, + LPCSTR szProcess, LPARAM lParam) { + + /*if (wTask == 0) + printf("%5u %s\n", dwPID, szProcess); + else + printf(" %5u %s\n", wTask, szProcess);*/ + + if(stricmp(szProcess,strProcessName)==0) + { + HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); + if(hProcess!=NULL) + TerminateProcess(hProcess,0); + CloseHandle(hProcess); + } + + return TRUE; +} + + +void main(int argc, char *argv[]) +{ + if(argc<2) + { + printf("Please specify the process name to kill\n"); + + return; + } + + if(strlen((argv[1]))<255) + strcpy(strProcessName,(argv[1])); + else + return; + + EnumProcs((PROCENUMPROC) MyProcessEnumerator, 0); + +} diff --git a/krb5-1-6/src/windows/installer/nsis/licenses.rtf b/krb5-1-6/src/windows/installer/nsis/licenses.rtf new file mode 100644 index 000000000..91dd9070e --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/licenses.rtf @@ -0,0 +1,98 @@ +{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033{\fonttbl{\f0\fmodern\fprq1\fcharset0 Courier New;}{\f1\froman\fprq2\fcharset0 Times New Roman;}} +{\*\generator Msftedit 5.41.15.1503;}\viewkind4\uc1\pard\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\f0\fs20 Copyright Notice and Legal Administrivia\par +----------------------------------------\par +\par +Copyright (C) 1985-2006 by the Massachusetts Institute of Technology.\par +\par +All rights reserved.\par +\par +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.\par +\par +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\par +this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Furthermore if you modify this software you must label your software as modified software and not distribute it in such a fashion that it might be confused with the original MIT software. M.I.T. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.\par +\par +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.\par +\par +Individual source code files are copyright MIT, Cygnus Support, OpenVision, Oracle, Sun Soft, FundsXpress, and others.\par +\par +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, and Zephyr are trademarks of the Massachusetts Institute of Technology (MIT). No commercial use of these trademarks may be made without prior written permission of MIT.\par +\par +"Commercial use" means use of a name in a product or other for-profit manner. It does NOT prevent a commercial firm from referring to the MIT trademarks in order to convey information (although in doing so, recognition of their trademark status should be given).\par +\par +----\par +\par +The following copyright and permission notice applies to the OpenVision Kerberos Administration system located in kadmin/create, kadmin/dbutil, kadmin/passwd, kadmin/server, lib/kadm5, and portions of lib/rpc:\par +\par +Copyright, OpenVision Technologies, Inc., 1996, All Rights Reserved\par +\par +WARNING: Retrieving the OpenVision Kerberos Administration system source code, as described below, indicates your acceptance of the following terms. If you do not agree to the following terms, do not retrieve the OpenVision Kerberos administration system.\par +\par +You may freely use and distribute the Source Code and Object Code compiled from it, with or without modification, but this Source Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY OTHER REASON.\par +\par +OpenVision retains all copyrights in the donated Source Code. OpenVision also retains copyright to derivative works of the Source Code, whether created by OpenVision or by a third party. The OpenVision copyright notice must be preserved if derivative works are made based on the donated Source Code.\par +\par +OpenVision Technologies, Inc. has donated this Kerberos Administration system to MIT for inclusion in the standard Kerberos 5 distribution. This donation underscores our commitment to continuing Kerberos technology development and our gratitude for the valuable work which has been performed by MIT and the Kerberos community.\par +\par +----\par +\par +Portions contributed by Matt Crawford <crawdad@fnal.gov> were work performed at Fermi National Accelerator Laboratory, which is operated by Universities Research Association, Inc., under contract DE-AC02-76CHO3000 with the U.S. Department of Energy.\par +\par +---- The implementation of the Yarrow pseudo-random number generator in src/lib/crypto/yarrow has the following copyright:\par +\par +Copyright 2000 by Zero-Knowledge Systems, Inc.\par +\par +Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, 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 Zero-Knowledge Systems, Inc. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Zero-Knowledge Systems, Inc. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.\par +\par +ZERO-KNOWLEDGE SYSTEMS, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ZERO-KNOWLEDGE SYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\par +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\par +\par +---- The implementation of the AES encryption algorithm in src/lib/crypto/aes has the following copyright:\par +\par +Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.\par +All rights reserved.\par +\par +LICENSE TERMS\par +\par +The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that:\par +\par +1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer;\par +\par +2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials;\par +\par +3. the copyright holder's name is not used to endorse products built using this software without specific written permission. \par +\par +DISCLAIMER\par +\par +This software is provided 'as is' with no explcit or implied warranties in respect of any properties, including, but not limited to, correctness and fitness for purpose.\par +\par +\par +\par +Acknowledgements\par +----------------\par +\par +Appreciation Time!!!! There are far too many people to try to thank them all; many people have contributed to the development of Kerberos V5. This is only a partial listing....\par +\par +Thanks to Paul Vixie and the Internet Software Consortium for funding the work of Barry Jaspan. This funding was invaluable for the OV administration server integration, as well as the 1.0 release preparation process.\par +\par +Thanks to John Linn, Scott Foote, and all of the folks at OpenVision Technologies, Inc., who donated their administration server for use in the MIT release of Kerberos.\par +\par +Thanks to Jeff Bigler, Mark Eichin, Marc Horowitz, Nancy Gilman, Ken Raeburn, and all of the folks at Cygnus Support, who provided innumerable bug fixes and portability enhancements to the Kerberos V5 tree. Thanks especially to Jeff Bigler, for the new user and system administrator's documentation.\par +\par +Thanks to Doug Engert from ANL for providing many bug fixes, as well as testing to ensure DCE interoperability.\par +\par +Thanks to Ken Hornstein at NRL for providing many bug fixes and suggestions, and for working on SAM preauthentication.\par +\par +Thanks to Matt Crawford at FNAL for bugfixes and enhancements.\par +\par +Thanks to Sean Mullan and Bill Sommerfeld from Hewlett Packard for their many suggestions and bug fixes.\par +\par +Thanks to Nalin Dahyabhai of RedHat and Chris Evans for locating and providing patches for numerous buffer overruns.\par +\par +Thanks to Christopher Thompson and Marcus Watts for discovering the ftpd security bug.\par +\par +Thanks to Paul Nelson of Thursby Software Systems for implementing the Microsoft set password protocol.\par +\par +Thanks to the members of the Kerberos V5 development team at MIT, both past and present: Danilo Almeida, Jeffrey Altman, Jay Berkenbilt, Richard Basch, Mitch Berger, John Carr, Don Davis, Alexandra Ellwood, Nancy Gilman, Matt Hancher, Sam Hartman, Paul Hill, Marc Horowitz, Eva Jacobus, Miroslav Jurisic, Barry Jaspan, Geoffrey King, John Kohl, Peter Litwack, Scott McGuire, Kevin Mitchell, Cliff Neuman, Paul Park, Ezra Peisach, Chris Provenzano, Ken Raeburn, Jon Rochlis, Jeff Schiller, Jen Selby, Brad Thompson, Harry Tsai, Ted Ts'o, Marshall Vale, Tom Yu.\par +\pard\f1\fs24\par +} +� \ No newline at end of file diff --git a/krb5-1-6/src/windows/installer/nsis/nsi-includes-tagged.nsi b/krb5-1-6/src/windows/installer/nsis/nsi-includes-tagged.nsi new file mode 100644 index 000000000..01bd29986 --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/nsi-includes-tagged.nsi @@ -0,0 +1,8 @@ +!define KFW_TARGETDIR %BUILDDIR%\target +!define KFW_EXTRADIR "%BUILDDIR%\target" +!define KFW_VERSION %VERSION_MAJOR%.%VERSION_MINOR% +!define KFW_MAJORVERSION %VERSION_MAJOR% +!define KFW_MINORVERSION %VERSION_MINOR% +!define KFW_PATCHLEVEL %VERSION_PATCH% +!define CL_1310 + diff --git a/krb5-1-6/src/windows/installer/nsis/site-local-tagged.nsi b/krb5-1-6/src/windows/installer/nsis/site-local-tagged.nsi new file mode 100644 index 000000000..614a27af9 --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/site-local-tagged.nsi @@ -0,0 +1,13 @@ +!define KFW_TARGETDIR %TARGETDIR% +!define KFW_CONFIG_DIR %CONFIGDIR-NSI% +!define KFW_MAJORVERSION %VERSION_MAJOR% +!define KFW_MINORVERSION %VERSION_MINOR% +!define KFW_PATCHLEVEL %VERSION_PATCH% +!define CL_1310 + +!define RELEASE +!define NOT_DEBUG +!define BETA 1 +!define SAMPLE_CONFIG_REALM "ATHENA.MIT.EDU" +!define HTTP_CONFIG_URL "[Obtain a URL from your Kerberos administrator]" + diff --git a/krb5-1-6/src/windows/installer/nsis/utils.nsi b/krb5-1-6/src/windows/installer/nsis/utils.nsi new file mode 100644 index 000000000..e9f98c04e --- /dev/null +++ b/krb5-1-6/src/windows/installer/nsis/utils.nsi @@ -0,0 +1,825 @@ +;----------------------------------------------- +; Common Utility functions not specific to KFW + +;------------------- +; Get the currently installed version and place it on the stack +; Modifies: Nothing +Function GetInstalledVersion + Push $R0 + Push $R1 + Push $R4 + ReadRegStr $R0 HKLM "${KFW_REGKEY_ROOT}\$R2\CurrentVersion" "VersionString" + StrCmp $R0 "" done + +done: + Pop $R4 + Pop $R1 + Exch $R0 +FunctionEnd + +; Functions to get each component of the version number +Function GetInstalledVersionMajor + Push $R0 + Push $R1 + Push $R4 + ReadRegDWORD $R0 HKLM "${KFW_REGKEY_ROOT}\$R2\CurrentVersion" "MajorVersion" + StrCmp $R0 "" done + +done: + Pop $R4 + Pop $R1 + Exch $R0 +FunctionEnd + +Function GetInstalledVersionMinor + Push $R0 + Push $R1 + Push $R4 + ReadRegDWORD $R0 HKLM "${KFW_REGKEY_ROOT}\$R2\CurrentVersion" "MinorVersion" + StrCmp $R0 "" done + +done: + Pop $R4 + Pop $R1 + Exch $R0 +FunctionEnd + +Function GetInstalledVersionPatch + Push $R0 + Push $R1 + Push $R4 + ReadRegDWORD $R0 HKLM "${KFW_REGKEY_ROOT}\$R2\CurrentVersion" "PatchLevel" + StrCmp $R0 "" done + +done: + Pop $R4 + Pop $R1 + Exch $R0 +FunctionEnd + + +;-------------------------------- +; Macros + +;-------------------------------- +; Macros +; Macro - Upgrade DLL File +; Written by Joost Verburg +; ------------------------ +; +; Parameters: +; LOCALFILE - Location of the new DLL file (on the compiler system) +; DESTFILE - Location of the DLL file that should be upgraded +; (on the user's system) +; TEMPBASEDIR - Directory on the user's system to store a temporary file +; when the system has to be rebooted. +; For Win9x support, this should be on the same volume as the +; DESTFILE! +; The Windows temp directory could be located on any volume, +; so you cannot use this directory. +; +; Define REPLACEDLL_NOREGISTER if you want to upgrade a DLL that does not +; have to be registered. +; +; Note: If you want to support Win9x, you can only use +; short filenames (8.3). +; +; Example of usage: +; !insertmacro ReplaceDLL "dllname.dll" "$SYSDIR\dllname.dll" "$SYSDIR" +; + +!macro ReplaceDLL LOCALFILE DESTFILE TEMPBASEDIR + + Push $R0 + Push $R1 + Push $R2 + Push $R3 + Push $R4 + Push $R5 + + ;------------------------ + ;Unique number for labels + + !define REPLACEDLL_UNIQUE ${__LINE__} + + ;------------------------ + ;Copy the parameters used on run-time to a variable + ;This allows the usage of variables as paramter + + StrCpy $R4 "${DESTFILE}" + StrCpy $R5 "${TEMPBASEDIR}" + + ;------------------------ + ;Check file and version + ; + IfFileExists $R4 0 replacedll.copy_${REPLACEDLL_UNIQUE} + + ;ClearErrors + ; GetDLLVersionLocal "${LOCALFILE}" $R0 $R1 + ; GetDLLVersion $R4 $R2 $R3 + ;IfErrors replacedll.upgrade_${REPLACEDLL_UNIQUE} + ; + ;IntCmpU $R0 $R2 0 replacedll.done_${REPLACEDLL_UNIQUE} \ + ; replacedll.upgrade_${REPLACEDLL_UNIQUE} + ;IntCmpU $R1 $R3 replacedll.done_${REPLACEDLL_UNIQUE} \ + ; replacedll.done_${REPLACEDLL_UNIQUE} \ + ; replacedll.upgrade_${REPLACEDLL_UNIQUE} + + ;------------------------ + ;Let's replace the DLL! + + SetOverwrite try + + ;replacedll.upgrade_${REPLACEDLL_UNIQUE}: + !ifndef REPLACEDLL_NOREGISTER + ;Unregister the DLL + UnRegDLL $R4 + !endif + + ;------------------------ + ;Try to copy the DLL directly + + ClearErrors + StrCpy $R0 $R4 + Call :replacedll.file_${REPLACEDLL_UNIQUE} + IfErrors 0 replacedll.noreboot_${REPLACEDLL_UNIQUE} + + ;------------------------ + ;DLL is in use. Copy it to a temp file and Rename it on reboot. + + GetTempFileName $R0 $R5 + Call :replacedll.file_${REPLACEDLL_UNIQUE} + Rename /REBOOTOK $R0 $R4 + + ;------------------------ + ;Register the DLL on reboot + + !ifndef REPLACEDLL_NOREGISTER + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" \ + "Register $R4" 'rundll32.exe "$R4",DllRegisterServer' + !endif + + Goto replacedll.done_${REPLACEDLL_UNIQUE} + + ;------------------------ + ;DLL does not exist - just extract + + replacedll.copy_${REPLACEDLL_UNIQUE}: + StrCpy $R0 $R4 + Call :replacedll.file_${REPLACEDLL_UNIQUE} + + ;------------------------ + ;Register the DLL + + replacedll.noreboot_${REPLACEDLL_UNIQUE}: + !ifndef REPLACEDLL_NOREGISTER + RegDLL $R4 + !endif + + ;------------------------ + ;Done + + replacedll.done_${REPLACEDLL_UNIQUE}: + + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Pop $R1 + Pop $R0 + + ;------------------------ + ;End + + Goto replacedll.end_${REPLACEDLL_UNIQUE} + + ;------------------------ + ;Called to extract the DLL + + replacedll.file_${REPLACEDLL_UNIQUE}: + File /oname=$R0 "${LOCALFILE}" + Return + + replacedll.end_${REPLACEDLL_UNIQUE}: + + ;------------------------ + ;Restore settings + + SetOverwrite lastused + + !undef REPLACEDLL_UNIQUE + +!macroend + + +; GetParameters +; input, none +; output, top of stack (replaces, with e.g. whatever) +; modifies no other variables. + +Function GetParameters + Push $R0 + Push $R1 + Push $R2 + StrCpy $R0 $CMDLINE 1 + StrCpy $R1 '"' + StrCpy $R2 1 + StrCmp $R0 '"' loop + StrCpy $R1 ' ' ; we're scanning for a space instead of a quote + loop: + StrCpy $R0 $CMDLINE 1 $R2 + StrCmp $R0 $R1 loop2 + StrCmp $R0 "" loop2 + IntOp $R2 $R2 + 1 + Goto loop + loop2: + IntOp $R2 $R2 + 1 + StrCpy $R0 $CMDLINE 1 $R2 + StrCmp $R0 " " loop2 + StrCpy $R0 $CMDLINE "" $R2 + Pop $R2 + Pop $R1 + Exch $R0 +FunctionEnd + + +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 + +Function GetSystemPath + Push $0 + + Call IsNT + Pop $0 + StrCmp $0 1 GetPath_NT + ReadEnvStr $0 PATH + goto HavePath +GetPath_NT: + ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" +HavePath: + + Exch $0 +FunctionEnd + +;==================================================== +; AddToSystemPath - Adds the given dir to the search path. +; Input - head of the stack +; Note - Win9x systems requires reboot +;==================================================== +Function AddToSystemPath + Exch $0 + Push $1 + Push $2 + Push $3 + + # don't add if the path doesn't exist + IfFileExists $0 "" AddToPath_done + + Call GetSystemPath + Pop $1 + Push "$1;" + Push "$0;" + Call StrStr + Pop $2 + StrCmp $2 "" 0 AddToPath_done + Push "$1;" + Push "$0\;" + Call StrStr + Pop $2 + StrCmp $2 "" 0 AddToPath_done + GetFullPathName /SHORT $3 $0 + Push "$1;" + Push "$3;" + Call StrStr + Pop $2 + StrCmp $2 "" 0 AddToPath_done + Push "$1;" + Push "$3\;" + Call StrStr + Pop $2 + StrCmp $2 "" 0 AddToPath_done + + Call IsNT + Pop $1 + StrCmp $1 1 AddToPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" a + FileSeek $1 -1 END + FileReadByte $1 $2 + IntCmp $2 26 0 +2 +2 # DOS EOF + FileSeek $1 -1 END # write over EOF + FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" + FileClose $1 + SetRebootFlag true + Goto AddToPath_done + + AddToPath_NT: + ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" + StrCpy $2 $1 1 -1 # copy last char + StrCmp $2 ";" 0 +2 # if last char == ; + StrCpy $1 $1 -1 # remove last char + StrCmp $1 "" AddToPath_NTdoIt + StrCpy $0 "$1;$0" + AddToPath_NTdoIt: + WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + AddToPath_done: + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +;==================================================== +; RemoveFromPath - Remove a given dir from the path +; Input: head of the stack +;==================================================== +Function un.RemoveFromSystemPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + IntFmt $6 "%c" 26 # DOS EOF + + Call un.IsNT + Pop $1 + StrCmp $1 1 unRemoveFromPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" r + GetTempFileName $4 + FileOpen $2 $4 w + GetFullPathName /SHORT $0 $0 + StrCpy $0 "SET PATH=%PATH%;$0" + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoop: + FileRead $1 $3 + StrCpy $5 $3 1 -1 # read last char + StrCmp $5 $6 0 +2 # if DOS EOF + StrCpy $3 $3 -1 # remove DOS EOF so we can compare + StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "" unRemoveFromPath_dosLoopEnd + FileWrite $2 $3 + Goto unRemoveFromPath_dosLoop + unRemoveFromPath_dosLoopRemoveLine: + SetRebootFlag true + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoopEnd: + FileClose $2 + FileClose $1 + StrCpy $1 $WINDIR 2 + Delete "$1\autoexec.bat" + CopyFiles /SILENT $4 "$1\autoexec.bat" + Delete $4 + Goto unRemoveFromPath_done + + unRemoveFromPath_NT: + ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" + StrCpy $5 $1 1 -1 # copy last char + StrCmp $5 ";" +2 # if last char != ; + StrCpy $1 "$1;" # append ; + Push $1 + Push "$0;" + Call un.StrStr ; Find `$0;` in $1 + Pop $2 ; pos of our dir + StrCmp $2 "" unRemoveFromPath_done + ; else, it is in path + # $0 - path to add + # $1 - path var + StrLen $3 "$0;" + StrLen $4 $2 + StrCpy $5 $1 -$4 # $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove + StrCpy $3 $5$6 + + StrCpy $5 $3 1 -1 # copy last char + StrCmp $5 ";" 0 +2 # if last char == ; + StrCpy $3 $3 -1 # remove last char + + WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + unRemoveFromPath_done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +;==================================================== +; IsNT - Returns 1 if the current system is NT, 0 +; otherwise. +; Output: head of the stack +;==================================================== +!macro IsNT un +Function ${un}IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 IsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + + IsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd +!macroend +!insertmacro IsNT "" +!insertmacro IsNT "un." + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Uninstall stuff +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;==================================================== +; StrStr - Finds a given string in another given string. +; Returns -1 if not found and the pos if found. +; Input: head of the stack - string to find +; second in the stack - string to find in +; Output: head of the stack +;==================================================== +!macro StrStr un +Function ${un}StrStr +Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + loop: + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 done + StrCmp $R5 "" done + IntOp $R4 $R4 + 1 + Goto loop +done: + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +FunctionEnd +!macroend +!insertmacro StrStr "" +!insertmacro StrStr "un." + + +!ifdef ADDSHAREDDLLUSED +; AddSharedDLL + ; + ; Increments a shared DLLs reference count. + ; Use by passing one item on the stack (the full path of the DLL). + ; + ; Usage: + ; Push $SYSDIR\myDll.dll + ; Call AddSharedDLL + ; + + Function AddSharedDLL + Exch $R1 + Push $R0 + ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 + IntOp $R0 $R0 + 1 + WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 $R0 + Pop $R0 + Pop $R1 + FunctionEnd + + +; un.RemoveSharedDLL + ; + ; Decrements a shared DLLs reference count, and removes if necessary. + ; Use by passing one item on the stack (the full path of the DLL). + ; Note: for use in the main installer (not the uninstaller), rename the + ; function to RemoveSharedDLL. + ; + ; Usage: + ; Push $SYSDIR\myDll.dll + ; Call un.RemoveSharedDLL + ; + + Function un.RemoveSharedDLL + Exch $R1 + Push $R0 + ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 + StrCmp $R0 "" remove + IntOp $R0 $R0 - 1 + IntCmp $R0 0 rk rk uk + rk: + DeleteRegValue HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 + goto Remove + uk: + WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 $R0 + Goto noremove + remove: + Delete /REBOOTOK $R1 + noremove: + Pop $R0 + Pop $R1 + FunctionEnd +!endif + + +; GetWindowsVersion +; +; Based on Yazno's function, http://yazno.tripod.com/powerpimpit/ +; Updated by Joost Verburg +; +; Returns on top of stack +; +; Windows Version (95, 98, ME, NT x.x, 2000, XP, 2003) +; or +; '' (Unknown Windows Version) +; +; Usage: +; Call GetWindowsVersion +; Pop $R0 +; ; at this point $R0 is "NT 4.0" or whatnot + +Function GetWindowsVersion + + Push $R0 + Push $R1 + + ClearErrors + + ReadRegStr $R0 HKLM \ + "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + + IfErrors 0 lbl_winnt + + ; we are not NT + ReadRegStr $R0 HKLM \ + "SOFTWARE\Microsoft\Windows\CurrentVersion" VersionNumber + + StrCpy $R1 $R0 1 + StrCmp $R1 '4' 0 lbl_error + + StrCpy $R1 $R0 3 + + StrCmp $R1 '4.0' lbl_win32_95 + StrCmp $R1 '4.9' lbl_win32_ME lbl_win32_98 + + lbl_win32_95: + StrCpy $R0 '95' + Goto lbl_done + + lbl_win32_98: + StrCpy $R0 '98' + Goto lbl_done + + lbl_win32_ME: + StrCpy $R0 'ME' + Goto lbl_done + + lbl_winnt: + + StrCpy $R1 $R0 1 + + StrCmp $R1 '3' lbl_winnt_x + StrCmp $R1 '4' lbl_winnt_x + + StrCpy $R1 $R0 3 + + StrCmp $R1 '5.0' lbl_winnt_2000 + StrCmp $R1 '5.1' lbl_winnt_XP + StrCmp $R1 '5.2' lbl_winnt_2003 lbl_error + + lbl_winnt_x: + StrCpy $R0 "NT $R0" 6 + Goto lbl_done + + lbl_winnt_2000: + Strcpy $R0 '2000' + Goto lbl_done + + lbl_winnt_XP: + Strcpy $R0 'XP' + Goto lbl_done + + lbl_winnt_2003: + Strcpy $R0 '2003' + Goto lbl_done + + lbl_error: + Strcpy $R0 '' + lbl_done: + + Pop $R1 + Exch $R0 + +FunctionEnd + + +; Author: Lilla (lilla@earthlink.net) 2003-06-13 +; function IsUserAdmin uses plugin \NSIS\PlusgIns\UserInfo.dll +; This function is based upon code in \NSIS\Contrib\UserInfo\UserInfo.nsi +; This function was tested under NSIS 2 beta 4 (latest CVS as of this writing). +; +; Usage: +; Call IsUserAdmin +; Pop $R0 ; at this point $R0 is "true" or "false" +; +Function IsUserAdmin +Push $R0 +Push $R1 +Push $R2 + +ClearErrors +UserInfo::GetName +IfErrors Win9x +Pop $R1 +UserInfo::GetAccountType +Pop $R2 + +StrCmp $R2 "Admin" 0 Continue +; Observation: I get here when running Win98SE. (Lilla) +; The functions UserInfo.dll looks for are there on Win98 too, +; but just don't work. So UserInfo.dll, knowing that admin isn't required +; on Win98, returns admin anyway. (per kichik) +; MessageBox MB_OK 'User "$R1" is in the Administrators group' +StrCpy $R0 "true" +Goto Done + +Continue: +; You should still check for an empty string because the functions +; UserInfo.dll looks for may not be present on Windows 95. (per kichik) +StrCmp $R2 "" Win9x +StrCpy $R0 "false" +;MessageBox MB_OK 'User "$R1" is in the "$R2" group' +Goto Done + +Win9x: +; comment/message below is by UserInfo.nsi author: +; This one means you don't need to care about admin or +; not admin because Windows 9x doesn't either +;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!" +StrCpy $R0 "false" + +Done: +;MessageBox MB_OK 'User= "$R1" AccountType= "$R2" IsUserAdmin= "$R0"' + +Pop $R2 +Pop $R1 +Exch $R0 +FunctionEnd + +Function RestartRequired +Push $R1 ;Original Variable +Push $R2 +Push $R3 ;Counter Variable + +StrCpy $R1 "0" 1 ;initialize variable with 0 +StrCpy $R3 "0" 0 ;Counter Variable + +;First Check Current User RunOnce Key +EnumRegValue $R2 HKCU "Software\Microsoft\Windows\CurrentVersion\RunOnce" $R3 +StrCmp $R2 "" 0 FoundRestart + +;Next Check Local Machine RunOnce Key +EnumRegValue $R2 HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" $R3 +StrCmp $R2 "" 0 FoundRestart + +EnumRegValue $R2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\FileRenameOperations" $R3 +StrCmp $R2 "" 0 FoundRestart + +NextValue: +EnumRegValue $R2 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager" $R3 +StrCmp $R2 "" ExitFunc 0 +StrCmp $R2 "PendingFileRenameOperations" FoundRestart 0 +IntOp $R3 $R3 + 1 +Goto NextValue + +FoundRestart: +StrCpy $R1 "1" 1 + +ExitFunc: +Pop $R3 +Pop $R2 +Exch $R1 +FunctionEnd + +; GetParent + ; input, top of stack (e.g. C:\Program Files\Poop) + ; output, top of stack (replaces, with e.g. C:\Program Files) + ; modifies no other variables. + ; + ; Usage: + ; Push "C:\Program Files\Directory\Whatever" + ; Call GetParent + ; Pop $R0 + ; ; at this point $R0 will equal "C:\Program Files\Directory" + +Function GetParent + + Exch $R0 + Push $R1 + Push $R2 + Push $R3 + + StrCpy $R1 0 + StrLen $R2 $R0 + + loop: + IntOp $R1 $R1 + 1 + IntCmp $R1 $R2 get 0 get + StrCpy $R3 $R0 1 -$R1 + StrCmp $R3 "\" get + Goto loop + + get: + StrCpy $R0 $R0 -$R1 + + Pop $R3 + Pop $R2 + Pop $R1 + Exch $R0 + +FunctionEnd + +; SearchPath (path, filename) +; input: +; top of stack is the filename +; top of stack minus one is the path +; output: +; top of stack is a fully qualified path or the number "0" +; +; Usage: +; Push "semicolon delimited path" +; Push "filename" +; Call SearchPath +; Pop $R0 ; fqpn +; StrCmp $R0 "" failed +; +; +Function SearchPath + Exch $R0 ; input - filename + Exch + Exch $R1 ; input - semicolon delimited path + Push $R3 ; worker - index to current end character + Push $R4 ; worker - length of $R1 + Push $R5 ; worker - copy of directory string/fqpn to search for + Push $R6 ; worker - single charcter copy or find handle + + StrCpy $R3 0 ; init character index + StrLen $R4 $R1 ; determine length of semicolon delimited path + StrCpy $R5 "" ; init return value + + findDir: ; find a semi-colon or end of string + IntCmp $R3 $R4 exit 0 exit ; we are done if no unprocessed string left + + loop: + StrCpy $R6 $R1 1 $R3 ; get the next character + StrCmp $R6 ";" foundDir ; if it is semi-colon, we have found a dir + IntOp $R3 $R3 + 1 ; increment index + IntCmp $R3 $R4 foundDir ; if we are at end of string, we have a dir + Goto loop ; still more chars in this dir + + foundDir: + StrCpy $R5 $R1 $R3 ; copy the dir to $R5 + StrCpy $R5 "$R5\$R0" ; construct fqpn + IfFileExists $R5 exit ; if file exists we are done + StrCpy $R5 "" ; reset return value to null string + IntOp $R4 $R4 - $R3 ; compute maxlen of new delimited path + IntCmp $R4 0 exit ; no more path left, exit + IntOp $R3 $R3 + 1 ; Increment $R3 past the semi-colon + StrCpy $R1 $R1 $R4 $R3 ; remove dir from the delimited path + StrCpy $R3 0 ; index back to start of new delimited path + goto findDir ; get another directory to look in + + exit: + Pop $R6 + Exch $R5 ; output - fully qualified pathname + Exch + Pop $R4 + Exch + Pop $R3 + Exch + Pop $R1 + Exch + Pop $R0 +FunctionEnd diff --git a/krb5-1-6/src/windows/installer/wix/Binary/bannrbmp.bmp b/krb5-1-6/src/windows/installer/wix/Binary/bannrbmp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..fe26100177d872964fddce9b8ee07addc74414f9 GIT binary patch literal 94554 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 L5<Fp0X2Jggh3MUV literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/completi.ico b/krb5-1-6/src/windows/installer/wix/Binary/completi.ico new file mode 100644 index 0000000000000000000000000000000000000000..93a95a1b190530733b16e26c8f1882e007f43315 GIT binary patch literal 2998 zcmbuBKTKO!6o-!kQasVFkcGvlE8d|UI)In50K11QR0zpZA2L$#LTq=iD@P<nLL@^~ zS|der2mXX1RtAu&CX)w*7%B{QsfC|~QW?~S+wZ*hY)p7w+Vi;Yy?cM(x#ym9uZ=|l za!&>aKNYn<?uiWX930f1$WK9$z8;a!cps#FK?_JPcaa2a%UthPFM-H=BH=!`^D4z+ zk*5mA`4eOGjmD)zdh@kZ;?{7=+I`hA5NtLVUgd8FlG(-G{Q6vbAT{4y$Xo4xFqzCQ ztXuV#9-N<_m-YHhKbcIJzPi=ctw+BbpmzUJ^`#_}$@`XNNh*~J*5mcpmyT{Fvd=Fi z`Lh0cF_}QJ66uvo`L<r$YF^Hfo=L1+eJ{cK?$+XB5Ivd5niY}M?v@vAE|p4u#{jNs zPE7hi^~L5@VI9HuU#fjIFB(t#)o&ht{TqFar~PZ|;Y00fJnh>GD6jEUSAf174_yKJ zn8thmNC8K8<5>!*zZcI^fPO1pYdu~(ce$+Bji<|Y%!{XC+D5z^a~vC=8&mv*YTf5V z^f>KW0_LVk&o#$Tj~_?VZ3&)51{)Iia4CTvpB7-uSNlhL0tEg*yM4}s%+4|Hbsp|5 z(DBZ>)<3^<UOXyF<JTXh)G$&wHj*hBnb|WkwrwPo=bUTH9f`zuM50ecA~BKhgp|tg z`|um^S@;<IH0&g89DW3T7(N8w56`@X0(=I327U}a1S?cX;00db1zskk48IS*0iT7B z!B4|a@);b5AAui+55f1tH{g%qOYnQ}+wgh#JbVs54j+Y&z=z=tyn#3H2HwCM_-n2s zt{twYTrsW*hi||i!<XRq;J4v*_B?bBIu0F$jzEW*zYM<*zX6|xkHJsFPr{GGkH8PZ zhv56+nYU1Y&%n>XkHLq!REO`NGW<UL27DGi20tAVGf6easpbgP9HyEfs@V_UfIo&W z!SBIu!{_1oK03<5$Kj*!5%{ov$H5zT18?9BykR|T*Ad&b!*)GoyJBqD#Dqu#{usUl zzX!h!pNH>qe54G&55EDQg^$5c!*@A8%v+KId<K37ehfYY->pC;Q-<G%-+<4;Q)x3z zV*UjxnFjnZd<lLJejA?RbSY4YPkVuuq0P|7Xdzm+0$p5ONTpJd!^1;)_wJp%dGkg# zH#a4p&&%4{n&fghdHndX#N%<9ot>3vG%8b5Qxb_pWOQ^?!r`zC4Gqb_z<~7i^-1Gz zBR{-&@gM(B@e%Ve+qQL?UCg#mPY-@sPIn>fO2yTmt@=%2SIPeLU^)G4b=40zuL7JN zs9Y}JoxrYQ1bBvu-2v=V2M|Hz%|}0l-~>ypR`b)()Kot?fw=2mF0ZaGFN;*0<^+F@ zhKWvxiCsobpPjv}HY?`j#PzRKYf>{;#?(Y?m47~XTUFq~^>Xy92Uo71PM;kdyk&xB z<$_wN;eYkOJh;MNY{wnF+VtE>MCUgEx@G6*Opo5VKh?jSNG>3MV&~`X)XtrGamSnq zNXG58?iF-*rQVUKncfaFj_&2>5a`!SOKEIjVWHR6z5H5w=1B{1^>%&=;Qyozc>XNL zTfU=b+JL9)0$YIV@6F)qZZ7TodYABbfewGIuNwYKZJ-t3-M<^%0Z7x+Kg#dp`h1jM stF+G3tzSoe?BQ+m>fg%GS%lxs%g;x00{ze5Df)Y)+wT-#t>bsfznDslbN~PV literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/custicon.ico b/krb5-1-6/src/windows/installer/wix/Binary/custicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..878d3ba54b8bfaf2de6ea1e8584bb25726492e5d GIT binary patch literal 2998 zcmc)MKTK*@9Ki9PPm{-FyQ+%|rmO7Q4jq)GF3Qf}Vq;85iorx#6zBjAFKSJUeM3`Q zOkP3<#pm#d113#%Vj#w$5rJ9)mlzu)Z9V;-d-<ncmM;BW5BHw?`<!#{Irnf;q)%SS z=;+6y<M&r0W9&yqbxq_)hsa>R$R`|+Qa+>f$pD`sL2N6m)~#BQB*(#^wd0dRNvG57 zbwZhcqLe<Ou<29!!#2XfC#S>yllNUG9QFFj`$XqND7JQz*k5X&2rt)H68?7G5emgt z_WjjX-m$#AEc?|?JroM6!K%NV_pkn@K<)Z!>79f^q1S%DX&lu+^}~ai_XlIDCZTuL z4{M=dI2^X>UsuaV^@k;fr_8*gdUCY3<{%$3>k>XWYF=$AYz|d7)zP}9L$@W`_506t ze6cM0dLoYd(pU3e{@PW4^v}<C*9{H2^BPdMuIIQnG@x#U<9_uKVCKVS|9%a0`|lpC zx(3uEJ664QKRb<Yb>6yN?l-1(be9as3=SgS=o4M>q;58>eX3OYBWCM0E27^lkJ6_) zMfx9EhI;w2G_4Y3pQhA+57O7)quA#Dmi|62{14^nI%n|{!2xq;ee`u5v##}@-8xTS zrKR@E50b4ZNnR_7W|b^tluV_RI1{XMUE)_FfnyQxmWbOY;+m0c9)E^Ez{l`Dyazi= znZ{4x$MH`55T1UMNqiK)fS<xUvBC@qUhsk!yv#@*e}+H6$M8P92S3Yqa2h{>AICfK zL--p08lS~y@F{!(pTNiQ0lXLQ#=GzeukZ@5@CvW+k8D?L$81|{KDHUt*YMZ)EIxxz z;dSo`bQ~Q(d(m#Ri~jTYGyDNQhWFt;_*wikegZ#^cjAZe^qWlLqxc2<6yDimc6bNn z@n`r0d<^fydz_+XnayctbAs6%XEvS8<`BMyzs6_r8GH(#!1F%3isJ)#FW!xJ>31An z;T2xt6<%>aJgzGq*D;T4i^t{Tam~z#)bQ8%EIxxz;S=~C%SZC~GyDNQhWFt;_#VrL zezTIqNAU~zDZCTkYl5;Wk3Yj7;A41ZT6q|l{RCxsKPA;QK8w%bQ+Ot)#{^~hwkIi3 z$^vDI;-vJNpu4*}DHe-zd3h-p7Z-ARdMby9hmuGnWN&Xz;_<j_Y-~s%5Rk>iMe%yQ zGB-CTZns+|Cnv?_a>>}(m<$gO%i!Rk)c#WP{oA+y@pp=^m`xalp>MNC7)GIx`*}0c zLm0)PmEYdA>%u58`a*6qvc0=&2P!2%A*a*%{L2oE62S$w$r3MsQ80lBNsest1q3Tt z%H^_M{#J+1-`pTxw$JBxcQ-dhN_BNZdwn%RgbCAgX5`66Zg0;^^`g4DvDz0)Wx3Tq z6jTkJ{wa4}(%_Cu5Kr@w$ZalnP6zek9do6ltGyUzbMmEnvpECl^e<AW&^`I?=TrLA z99MHVe-M?5)wTIqe)g!#`er*(B;OpL1<PunE0oT+#%BWZkL&9ZVr6Azz&0O!(*pMS zH*H{_kG4TGuLszATwI@Yvj;2xWQ63`+n}rcZByxd8?>(9Q0htE1Prs8Z;Uj$^UvpJ rWJHZLI_*1?%Ta6oMjEZVtUL?mS4Ri5;In<ZgJ<XUdz|<m|4;cB3zdW( literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/dlgbmp.bmp b/krb5-1-6/src/windows/installer/wix/Binary/dlgbmp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b67c6c246e1293864b3e5c6346cc060d9ff19db1 GIT binary patch literal 474822 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%0D45f&W1QfIIu_ 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 G`Tqyg)F|r! literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/exclamic.ico b/krb5-1-6/src/windows/installer/wix/Binary/exclamic.ico new file mode 100644 index 0000000000000000000000000000000000000000..906ce3246dba72e290f6a3008b19ea129233f213 GIT binary patch literal 766 zcma))v2KGv42DfF5@Q-6bq#75ItJXmsN}tJkH(`gX3Ur&iu>EX>!nOJ`Z@mdeYQam zRk+&rl{79dL~mF>pcWdTiZ-|tMda2o&ojjsk%TlveEsL0x!;v&m<N7}9dmaoG4{<+ z9G*h<qi;{y^QUcOKl0IhXi~kD@3VJ)?9tyVIgbABr;Mk8!bUfMCx7T*6;FWGpMbmf z{^+iOqu*B6aPt#$#tks<c<~8W!14*t-n(mq;iUaC?i1*@(wv13>%$jca0d$R{t35{ zf4ggmF1@>#Q{c~W=J!KRt=1b+y%2>Nzgb*K_n@%2>MPDdTQI8q-Szb#Ql0VVsYIfx W5}8#&WKq>3SJhVJwimgdMdJrzKB>e2 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/info.bmp b/krb5-1-6/src/windows/installer/wix/Binary/info.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7e0ff7f14c24ace2d59e24260b666ca60ef57482 GIT binary patch literal 1078 zcmbW0y-ve06opR-l9@=}pq)_PqC8SIv&9<=QeMd$43&6=ZZKveLsj!#J1I(4B!t`J z>vMnI>sx818*Mg?Y<=EH56Gq|e7lnFD`|^v10KOjx9n2D_xcJLv4l_rJ4X-{W5kg1 zS1H*E@G+Hb^K$KcD$-x@3wwRR(}KHt!M%rjKNlc%Z+ucX-Eos3KbP#GDUB#{M4>2L zcBr$}wjn#5X(DH<4u0ITvP0`~GzxPggEMIkSvvo;;K6qbKKzec{hViLOa4sQLR;$3 z+^O8}W&dWXk>A_dVTvE%Ibh<s9p+H{&5XmjKhul(q8NYrZI^gHQ$pzd<ebt6##eIy z6gz<t#5^Lqle9icHCJ=gs}77~1cAziUlvoGeX2lQB>q4i;&<ff$j9VWDIM0y=DYzL zFwc49e0_ydl)2^v_?U|APjl`F;y!hjPN{Ha(V9WmM31ajqnqAoFv(lyIXJ%4ppN00 y<bIL_Bzq?GgT2PsBW17fWqC`lQ!kxrX#@jx5B$d?T?z)g7Rz+l4H4gAEqw#;leS<0 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/insticon.ico b/krb5-1-6/src/windows/installer/wix/Binary/insticon.ico new file mode 100644 index 0000000000000000000000000000000000000000..94753ac296389ae5b90e56608a5fd1882692985f GIT binary patch literal 2998 zcmc)MKWH0g9LDjV6N8TqPFH90BGc8{op$J8YpEB<y9O^V!64`f8DcGoWC{`}I9ZIz zQ2IxLfI1l2UPJ~NN|Q;02_AxENp%nT4&!o$1i$^h?@970l}fk1m-p^oJ)ifz_uf0n z5t)!XGCTXZ=<>%MkvWdDv$`envn4WpSL6%MXQ^LNCuEYnNE+KOLGOMmO~`pV9URzm zD%EP0qYjk$CrarvDx3aD?}B1w`)B58Wj2pq2A^bnPb9x(9~FZS@>?5eE9rkYEZPQ; zC#_80KKv<YlV`HYq<?5Xey@SfGnq{Kv&R>v-OKNJ7oCkkZeQH<FuJYt%th+Gl}wsE zue@Zg^U6{ETzQ#n>ca7_lbVapldmq0wze`;HdCN&+d1dR*7LU0LEHNN$lkEB*?#-p zbvB#l_ElQ4*|cpFnZguI+l;Jt8<tYnQ?_LXB}uFSpPHhlU}dvY*45X#d}F2ru&z4a zt$q7@&<0yqH}=|EudOd}<!TV*dW@?Z4MJ^KgHZdi2BEgCLAb3!s2!S*9zQf+nqqE4 z--@W4DOJ6mP}L1l)mho9im6|6998e~`2<xyt!e$5Qm?5WsW(*Kt_gMhFZH9`9e&Sw z`6=m1a|m{N)ImuT(%_vo2lkwr_q=*q74NqnrS2&yH<aY+O4e&i7As03MP{OF;Z!7b zAQFEr5=)3gm!;msALC2-JU)S6#ja47@C*2Pd;~v(XWVibpTn=?7x59SaL0ldyx;{d z%hJRj<4gEFK7n7wukamQ!Y|<G@e%wC-orQWb$kt9!58sGd;y=r$MG?I6tD0KukZ@5 z@Ctv!cFK0Z_M9!jwrsqIZ{X|r8oq+pqZiQybP63u$Iwy6Z{m;fC43&Az^~$0@Jsjw z{5(E_pTRS3xs1=@*YS(^$e7jPH>im}#+UGUd;-535w*f<F0q;mtmZtc8DTYN@E*Q_ zuj6a@3ciRh;tTi`K8}y!qxv@vukZ@5@CvV(50C4V$92Htdd}lY@VJ(jMLc{1U&q(* z6?_pt=Jk;#{up1v=kW>rDt^rC!?<-R<8%0R{31SrAGbht)x;m;OZYsVl~$|V*yshS zD-Ykm*YP!c1<&G)S)e+91IpAKb)C9MjZnue(B<W&wA*cY_wJp%efw5kzkV(I`}<NX z7G-a5PYQ*CJbn69QmK?Ydh|%*@whyE_)uc8m^^s!K%&v8%+1Zo{rmT2dU{&C4@!P` z`SQR1o#H!XitD<1CS!{0wpu5@?raYUr=?o@dn)3#+d=+fH#CGp+!BYl!wt4hcD7&a z?uJ0n-*=?j0klqZ+-%+s(ChEJ9SRqCK}s2bet)-RfCwRHw|Q`VpSdG=NyTxTaBk-B zJMOtIIzKx@{Ih?vxx2fwBhvBJS-8Lc8zA&=l5U@$zv=jGb#@l&uX6{W<6lnRbTk;m z;`I9a?#}l1`N_!}2JqXLtQD^VrI-7@@0#x99p7|scUaX>F5ND}lV4tP1CG;ff08Tp zC#BofS2V@snhL}FdSQl&8J}0eb%R__XQ*`k3NEh<5Uw~>7``{28KGzU7guI_dORn% z1o>pB+~z%?^P4A6wkeyNo0FkD7+L4JXMHe~2lEg$`D_4&b8}m!e;<s_>E8pR^Ctr^ lCLe%txdGhf=zR40^d5?NRR+r&UY{Q5ep2}P`k()w@;93z)Y<?5 literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/new.bmp b/krb5-1-6/src/windows/installer/wix/Binary/new.bmp new file mode 100644 index 0000000000000000000000000000000000000000..27881dfe972209bb5825c15cb7bc00bbde46c7c2 GIT binary patch literal 318 zcmZQzU<5(|0RaXO&|qX>5ChRb3=&ZQVnzlQAj!bc04A{!KpBu^Lj!~Yl0YWIfddDC zG)Uq<7%}|+4`Kl^5Q2n21UlFa1RH>Y#L_VR++bZW9?>+&2@U*cm>0<B24Z#~mIC_Y TIs?PQ)j;>w0`Ys0yAd=1E8#zj literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/removico.ico b/krb5-1-6/src/windows/installer/wix/Binary/removico.ico new file mode 100644 index 0000000000000000000000000000000000000000..097cafe274a9b8e05bd6e4bc6fa92abe56c40b51 GIT binary patch literal 2998 zcmc)ML1^1n7zgk#O+oG@9b|%~8!Qtz?AUmN6-JsJx-Ic3mo%5cz|a_!I1adu=eXFe zx7s<`!G|784`U4HWCm?|7z<_CWt6gm38UmNq}ZyQ$TnW^3vBr9FUd}v#)cgRd&-ma z-uL^S<fo_DL_>6e#>d|xv%J1QG=byzxY;85!9g@KO!Ohn$5B5+9iofa6UAY>#m?@w z;t1kA9=8wJ<CJ!Gc5pNU-1;NV%`;SNW|z4;Uj+2WR!{l`hBjlY)8Pok(B`pF$nJ2Y z5O0Ur;&Z#hinmj1Yn=`|{(5C`aXDoQJ6@@5gzgqYakQ=cTE!a+J-6EC`0W}x*xfhc zcH547aYsGzN(?s?I?eZTcIU>8lYAaU{KYRPaUKn^&|SN2UZ1tKP^i!oXO+tGa!;H` z7Z+dLIn8HmZP{zLQ|5)O(i7))kNNpxU*EX3k%}?1$7~;eiIbswsaQy`+DEtB?bT0X zLmTKY<BheiwBaX>NaUT&D%x}}bo=PtnBe{Si6et1Io@Bp^}*HXTIA199M)61$DTKS z^K<WytJkcy<Gq*=`Pko@9{%0*7@;xxljCjw(Y3hMB!?q@^_!2raBQI2rWik_%e+Cu z{0}S%)M?bqr~>Nne^nb8>lpQK)HcS(%Dc?tG<|lRJIE~Yi`K#34fUK;96_|>ar=Nh zPOWvmv$sQyU%#hPgHvANlrC{vDsY<F=H$%bYG%#u5v@NZ@;o4N2Z&sAR8rxK@LTX1 z_yGI@>^$l${1p5oyc2#59^>Zo@M-uZ_!)R7EM}4jp5O_d;AxIj_#*rkd<H%MzW_gv zcW@Sd3Vssa2|otkfLGv4@CEp7_#Au=J`2AN?}2y2yWlxIhv)Ddp2KtaHnu%%Pq96~ z7Qi-V`3AfKUxF{dZ^N6T=b*FD>(Cx(H?#}mtMEnmE%*$40Db{}9)1>n3Vssa2|osp zar1fjH2f0$47_u|>|nvE@J0A7_zZjie!)q69<w=%*_^^`PGUBln9VWx2D}1af-k^t z!{^|0@LBkEcn`cA-evxegXi!Zp2Kr^j{Cvm+QZ{|ipTW;k1K%3H8)4pfLGv4@CEp7 z_#FIz<wGib5q=9k10R52fFH1YFm8$R@M-uZ_!)R7{GbUcaTUG@zXhLx$4v7De6ao# zRKlB_=L&oYz5u@skI5M@K_z?#<WbY8OQ<ubPSimY)ND4XQmN3ZSFh;h%a`=**)w|l z_%Y>jIePf;A!V~!N+y%EzP?T?D=Xyjc<AQMo8)%8>H78S<Z`)aVq$`>T)9FcBO}!K zi_>?H9{t<zsj9A7rCP<?b*?Z?Ra<6JTB@d<BgaB{Us0^EqN<59J1Y#P$#%Y^v;ZWz zd}a)z+RaZ&iYn=bVU*>bF;4UECtFeq#TU_KjU9IG^EChdrj$yC!#*E?#`LBQdh$1| zuq?@bKY-5$z4^&x*k|6L>^B%Y=)_O%|Ndq>8BY0pk}T-azWMEB%FfrKee%EEOoq+R zk9@gb{$@Cd`LnLCX?^lrWqba75q~tQpTB>l+{usl{r#@rDkpXO`UCP?$&{{3k~}D1 zDdW>eB4)Vn^;;d_k81cK(KCPLeYIQk6w(FR+k5|-U>17`mdi5!&g8Rwb+=O_2@?Y@ zV}iQRkL~J4vsp8+nJZNi1dyKj+clc((mpmVC>o-{%BsY4{Lbm-?>3DZPb3mrU6&<Q z6AeSNMCbkwcZ19X`&QTp)+9+ZbaSD07g$r10qQ|yi{VRQkxNq0sH)usNX9`+HtOs^ z4Av9-2@?dvVevrf<P#aJB{NZ!%Rw=LJGq2Wg0%zTBn}{oOitHFb+O9R807OBtDc52 p!l5zB>rFg7qYlv=Jv59r-{Vm-j8Q=hzOLgH>qP(8-zi5l{SUV)2I>F+ literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/repairic.ico b/krb5-1-6/src/windows/installer/wix/Binary/repairic.ico new file mode 100644 index 0000000000000000000000000000000000000000..6fb68610c9af370020f00cd1d0ff589db8d19b6d GIT binary patch literal 2998 zcmc(hKTI1}9LIkLNO-6SohX@5C8MZPrQ)5mLkI9u7GU>~g(^a_R3jsWTgaIXxN=0Y zpeRGtv_^{L4us$;K_~)IHJLo1hynS}Ij+HWz{R1J{Q7x!ws8_Hb?fi=y?ej=etz%W z{ocDXB8GIy&``f<d)*~6%z0=?M<PFaMEbf#uF)UDzrqdap%pP<o91RWBNLInX}Tv` zy0W#k#aRo=`4gpd59iRAbmLgWY;+o7D7o2o!BeZvZ^kb!SkZ-K{NZftLS(Ks9}hL+ zuD`EYR&@ShsO0Lzb8~a@uyheymZ|zmp_U%Hb*MZrj=|r`KN8EbdP5-?;!?Qu?5(4R zOyVKyQR&%&Wkw<qH~zj<d|Z1w%i}0Ve_KjEURdy;TTXl)Nj`4OHmmc``*o@|=Im0l z=lvd?i|Kp#)F7^Yt?e5fUojSb@Kp2P-T3woC+?Mx(d(fbH{4jn5>K_P0Y{IRI<9Mg z*b*kGplg6QYSltf^jjLxaYU&KaYzHi5s5^4b*uqmZF;<m`w>sbY`<R}ljNGlJvCFG zTJ}NQzS^qtrBYj0s9Z0*p<BJd55;J6={{r&;&O=_haNF14S(~A7~1=ZMLT`%U*HO_ zbFKc7bk~`#>F@4yHa}+eI48F;+WKN55}T%bqNVHX^R0s|sr>$vq$)}hX(h`kB{Mrp z#x|6A<Lq<ou>+Ct6Oq7O5r0s`HzBDE{4V?&d=x$iKMgyHkHe3`kHCB32jLkvk$_)@ zpMf8P_rgjYhZlH(7kHVF4E!$q8hjK!2tN%!$vZd>KMFqr?}Z<PufV6_Q}8?R8}M=X zID8B~3?G2^!~5VByn<Ko3SPl0_&Ub{#}kgb96^o=hp)h=;ZyKC@Eh=Y^f+`3It(3v z_Cxy^KLfuDzXl(L55iBwPr{GGkHU|@d*KJ+88?xDUxuH7AA|RHs1Dzt4E!$q8hjK! z2tVx=HAywcspcrv9HE+CsyPT>fltGy;CJ9R;N$RopAKU1VfX;NAKs_GaqtRW!7F$L zuecwU>wx8Y!gAeZxq>X$#Dqu%J`JCO-+|wNkHdG^K9Ygog<pe@!Uy4};X7;}#!X2A zei?oSehl6V->E<;m4V-dUxSarQ)xBLgI!*r6kn5sO2en%ci=bRDNct1rFiQT_%c3& zkKtatQ-MxSPQ<otdG+d*ynOjmwzs!seSKZx@wnW-e_vv;nB2a7Tf*V6+`M^H0)c=` zO-+g4@0aV>uZz#;li}fExq9`g^!4>g<sT(KK6vmSf2Vk*uyVPqZ=-{i%embCuPaL( zh_Y?F`n}c5hA8KGy4?QC(!JHy_kq2=Jvq(;<o30k$-Fy2^6B<wIgc^HJyh%+Ao=w9 zW;y2oB8c?f)5*`}AlRW&EEYe|$uDTrdNvF3VSXmFy1KF=lCP;O`Fb|YDU~yS26d@W zc#*H!Dw}ol?R-%K`u_LITK;AKMP36ZOo6rZ=UQJ{D(vsSV1Sx^Lans5<qwpdbo6|! zk<Np-<DZc~aDIHu@aXO9lmAQ4f5!X+=bwH4Cw6@74(+r~I{MjfjxI&#$GX+nt}e;s zsiE`Hd)iDj^-B8GPy^?VUSC{X!sh4adoJ|+sTc-7IOH$iX##Ef$*B}=YKDHN1-N>( zT9u=tqiWHn<K#C1S1)AWRA1Y#kE+$Qqm$nN8hW~r&DsFSI)AYRH1xAVA)Vo<y7Mo# zfQDWW(OaXMYw8ZbW4gMt189nR%^APVTF;MMuybsx4)xVK+l~Q_-?QfEQcya-vlY@# Qen&t*!ln8D_x~yX0&_g1<NyEw literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Binary/up.bmp b/krb5-1-6/src/windows/installer/wix/Binary/up.bmp new file mode 100644 index 0000000000000000000000000000000000000000..86f6b5a84755483dee8175ebc821d3af0ce866b8 GIT binary patch literal 318 zcma)&F%Ez*3<F(>jinPaBfq3iVrS`7_(?ej5C}1lG<M>oRa7bAIcM3XBn@W5%19)2 zpi~0CfR3A`90Zc8)(X4P;;1!e1a8Ujwl!?g%}lJWd!z?T2-Gq9(9iqVy9{0F7kh<5 P<5%!Eb(Xf+-TO;BySGdd literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/installer/wix/Makefile b/krb5-1-6/src/windows/installer/wix/Makefile new file mode 100644 index 000000000..02de33ca7 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/Makefile @@ -0,0 +1,59 @@ + +# Build language +LANG=1033 + +# Program macros +CANDLE=candle -nologo + +LIGHT=light -nologo + +CD=cd + +RM=del + +MAKE=nmake -nologo + + +# Targets + +OUTPATH=. + +OBJFILE=$(OUTPATH)\kfw.wixobj + +MSIFILE=$(OUTPATH)\kfw.msi + +WIXINCLUDES= \ + config.wxi \ + features.wxi \ + files.wxi \ + property.wxi \ + site-local.wxi \ + lang\strings_$(LANG).wxl \ + lang\ui_$(LANG).wxi \ + lang\config_$(LANG).wxi + +CUSTOMDLL=custom\custom.dll + +all: $(MSIFILE) + +$(OBJFILE): kfw.wxs $(WIXINCLUDES) + $(CANDLE) -out $@ kfw.wxs \ + "-dDate=%DATE%" \ + "-dTime=%TIME%" \ + -dBuildLang=$(LANG) + +$(MSIFILE): $(OBJFILE) $(CUSTOMDLL) + $(LIGHT) -out $@ $(OBJFILE) \ + -loc lang\strings_$(LANG).wxl + +$(CUSTOMDLL): custom\custom.cpp + $(CD) custom + $(MAKE) -f custom.cpp + $(CD) .. + +clean: + $(RM) $(OBJFILE) + $(RM) $(MSIFILE) + $(CD) custom + $(MAKE) -f custom.cpp clean + $(CD) .. diff --git a/krb5-1-6/src/windows/installer/wix/config.wxi b/krb5-1-6/src/windows/installer/wix/config.wxi new file mode 100644 index 000000000..734e16c08 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/config.wxi @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + Copyright (C) 2004, 2005, 2006 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> +<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> + + <!-- include site sepecific customizations --> + <?include site-local.wxi?> + + <!-- Sanity checks --> + <?ifndef var.CL1200?> + <?ifndef var.CL1300?> + <?ifndef var.CL1310?> + <?ifndef var.CL1400?> + <?error Must define one of CL1200, CL1300, CL1310 or CL1400?> + <?endif?> + <?endif?> + <?endif?> + <?endif?> + + <!-- Build type specifications --> + <?ifndef env.CPU?> + <?error CPU is not set ?> + <?endif?> + <?if $(env.CPU) = "i386"?> + <?define InstallerVersion="110"?> + <?define Platform="Intel"?> + <?define Win64="no"?> + <?elseif $(env.CPU) = "AMD64"?> + <?define InstallerVersion="200"?> + <?define Platform="x64"?> + <?define Win64="yes"?> + <?else?> + <?error Unknown build type?> + <?endif?> + + <?define KfwRegRoot="SOFTWARE\MIT\Kerberos"?> + + <?if $(env.CPU) = "i386"?> + <?define BinDir="$(var.TargetDir)bin\i386\"?> + <?define LibDir="$(var.TargetDir)lib\i386\"?> + <?else?> + <?define BinDir="$(var.TargetDir)bin\amd64\"?> + <?define LibDir="$(var.TargetDir)lib\amd64\"?> + <?endif?> + <?define DocDir="$(var.TargetDir)doc\"?> + <?define IncDir="$(var.TargetDir)inc\"?> + <?define InstallDir="$(var.TargetDir)install\"?> + <?define SampleDir="$(var.TargetDir)sample\"?> + <?define SystemDir="$(env.SystemRoot)\System32\"?> + + <?include lang\config_$(var.BuildLang).wxi?> + + <!-- Parameters for the features containing debug symbols --> + <?ifdef DebugSyms?> + <?ifdef Debug?> + <?define DebugSymInstallDefault="followParent"?> + <?define DebugSymLowLevel="30"?> + <?define DebugSymHighLevel="130"?> + <?else?> + <?define DebugSymInstallDefault="followParent"?> + <?define DebugSymLowLevel="130"?> + <?define DebugSymHighLevel="130"?> + <?endif?> + <?endif?> + + <!-- Configuration macros --> + <?ifndef LeashAfsStatus?> + <?define LeashAfsStatus="1"?> + <?endif?> + <?ifndef LeashCreateMissingConfig?> + <?define LeashCreateMissingConfig="0"?> + <?endif?> + <?ifndef LeashAutoRenewTickets?> + <?define LeashAutoRenewTickets="1"?> + <?endif?> + <?ifndef LeashLockFileLocations?> + <?define LeashLockFileLocations="0"?> + <?endif?> + <?ifndef LeashMsLsaImport?> + <?define LeashMsLsaImport="2"?> + <?endif?> + <?ifndef LeashLifetime?> + <?define LeashLifetime="0"?> + <?endif?> + <?ifndef LeashRenewTill?> + <?define LeashRenewTill="0"?> + <?endif?> + <?ifndef LeashRenewable?> + <?define LeashRenewable="0"?> + <?endif?> + <?ifndef LeashForwardable?> + <?define LeashForwardable="1"?> + <?endif?> + <?ifndef LeashNoAddresses?> + <?define LeashNoAddresses="1"?> + <?endif?> + <?ifndef LeashProxiable?> + <?define LeashProxiable="0"?> + <?endif?> + <?ifndef LeashPublicIp?> + <?define LeashPublicIp="0"?> + <?endif?> + <?ifndef LeashUseKrb4?> + <?define LeashUseKrb4="1"?> + <?endif?> + <?ifndef LeashHideKinitOptions?> + <?define LeashHideKinitOptions="0"?> + <?endif?> + <?ifndef LeashLifeMin?> + <?define LeashLifeMin="5"?> + <?endif?> + <?ifndef LeashLifeMax?> + <?define LeashLifeMax="1440"?> + <?endif?> + <?ifndef LeashRenewMin?> + <?define LeashRenewMin="600"?> + <?endif?> + <?ifndef LeashRenewMax?> + <?define LeashRenewMax="43200"?> + <?endif?> + <?ifndef LeashUppercaseRealm?> + <?define LeashUppercaseRealm="1"?> + <?endif?> + <?ifndef LeashTimeHost?> + <?define LeashTimeHost="time"?> + <?endif?> + <?ifndef LeashPreserveKinitOptions?> + <?define LeashPreserveKinitOptions="0"?> + <?endif?> + <!-- These actually have no defaults. --> + <?ifndef Krb4KrbRealms?> + <?define Krb4KrbRealms=""?> + <?endif?> + <?ifndef Krb4KrbConf?> + <?define Krb4KrbConf=""?> + <?endif?> + <?ifndef Krb4ConfigDir?> + <?define Krb4ConfigDir=""?> + <?endif?> + <?ifndef Krb4TicketFile?> + <?define Krb4TicketFile=""?> + <?endif?> + <?ifndef Krb5Config?> + <?define Krb5Config=""?> + <?endif?> + <?ifndef Krb5CcName?> + <?define Krb5CcName=""?> + <?endif?> + <?ifndef Krb5PreserveIdentity?> + <?define Krb5PreserveIdentity="1"?> + <?endif?> + + <!-- If neither NetIDMgr or Leash is specified, we default to NetIDMgr --> + <?ifndef UseNetIDMgr?> + <?ifndef UseLeash?> + <?define UseNetIDMgr="1"?> + <?endif?> + <?endif?> +</Include> \ No newline at end of file diff --git a/krb5-1-6/src/windows/installer/wix/custom/custom.cpp b/krb5-1-6/src/windows/installer/wix/custom/custom.cpp new file mode 100644 index 000000000..a61b632ac --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/custom/custom.cpp @@ -0,0 +1,746 @@ +#ifdef __NMAKE__ + +# NMAKE portion. +# Build with : nmake /f custom.cpp +# Clean with : nmake /f custom.cpp clean + +# Builds custom.dll + +OUTPATH = . + +# program name macros +CC = cl /nologo + +LINK = link /nologo + +RM = del + +DLLFILE = $(OUTPATH)\custom.dll + +DLLEXPORTS =\ + -EXPORT:EnableAllowTgtSessionKey \ + -EXPORT:RevertAllowTgtSessionKey \ + -EXPORT:AbortMsiImmediate \ + -EXPORT:UninstallNsisInstallation \ + -EXPORT:KillRunningProcesses \ + -EXPORT:ListRunningProcesses \ + -EXPORT:InstallNetProvider \ + -EXPORT:UninstallNetProvider + +$(DLLFILE): $(OUTPATH)\custom.obj + $(LINK) /OUT:$@ /DLL $** $(DLLEXPORTS) + +$(OUTPATH)\custom.obj: custom.cpp custom.h + $(CC) /c /Fo$@ custom.cpp + +all: $(DLLFILE) + +clean: + $(RM) $(DLLFILE) + $(RM) $(OUTPATH)\custom.obj + $(RM) $(OUTPATH)\custom.exp + +!IFDEF __C_TEXT__ +#else +/* + +Copyright 2004,2005 by the Massachusetts Institute of Technology + +All rights reserved. + +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 the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/************************************************************** +* custom.cpp : Dll implementing custom action to install Kerberos for Windows +* +* The functions in this file are for use as entry points +* for calls from MSI only. The specific MSI parameters +* are noted in the comments section of each of the +* functions. +* +* rcsid: $Id$ +**************************************************************/ + +#pragma unmanaged + +// Only works for Win2k and above +#define _WIN32_WINNT 0x500 +#include "custom.h" + +// linker stuff +#pragma comment(lib, "msi") +#pragma comment(lib, "advapi32") +#if defined(_M_IA64) || defined(_M_AMD64) +#pragma comment(lib, "bufferoverflowu") +#endif + + +void ShowMsiError( MSIHANDLE hInstall, DWORD errcode, DWORD param ){ + MSIHANDLE hRecord; + + hRecord = MsiCreateRecord(3); + MsiRecordClearData(hRecord); + MsiRecordSetInteger(hRecord, 1, errcode); + MsiRecordSetInteger(hRecord, 2, param); + + MsiProcessMessage( hInstall, INSTALLMESSAGE_ERROR, hRecord ); + + MsiCloseHandle( hRecord ); +} + +#define LSA_KERBEROS_KEY "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos" +#define LSA_KERBEROS_PARM_KEY "SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Parameters" +#define KFW_CLIENT_KEY "SOFTWARE\\MIT\\Kerberos\\Client\\" +#define SESSKEY_VALUE_NAME "AllowTGTSessionKey" + +#define SESSBACKUP_VALUE_NAME "AllowTGTSessionKeyBackup" +#define SESSXPBACKUP_VALUE_NAME "AllowTGTSessionKeyBackupXP" + + +/* Set the AllowTGTSessionKey registry keys on install. Called as a deferred custom action. */ +MSIDLLEXPORT EnableAllowTgtSessionKey( MSIHANDLE hInstall ) { + return SetAllowTgtSessionKey( hInstall, TRUE ); +} + +/* Unset the AllowTGTSessionKey registry keys on uninstall. Called as a deferred custom action. */ +MSIDLLEXPORT RevertAllowTgtSessionKey( MSIHANDLE hInstall ) { + return SetAllowTgtSessionKey( hInstall, FALSE ); +} + +UINT SetAllowTgtSessionKey( MSIHANDLE hInstall, BOOL pInstall ) { + TCHAR tchVersionString[1024]; + TCHAR tchVersionKey[2048]; + DWORD size; + DWORD type; + DWORD value; + HKEY hkKfwClient = NULL; + HKEY hkLsaKerberos = NULL; + HKEY hkLsaKerberosParm = NULL; + UINT rv; + DWORD phase = 0; + + // construct the backup key path + size = sizeof(tchVersionString) / sizeof(TCHAR); + rv = MsiGetProperty( hInstall, _T("CustomActionData"), tchVersionString, &size ); + if(rv != ERROR_SUCCESS) { + if(pInstall) { + ShowMsiError( hInstall, ERR_CUSTACTDATA, rv ); + return rv; + } else { + return ERROR_SUCCESS; + } + } + + _tcscpy( tchVersionKey, _T( KFW_CLIENT_KEY ) ); + _tcscat( tchVersionKey, tchVersionString ); + + phase = 1; + + rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, tchVersionKey, 0, ((pInstall)?KEY_WRITE:KEY_READ), &hkKfwClient ); + if(rv != ERROR_SUCCESS) + goto cleanup; + + phase = 2; + + rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( LSA_KERBEROS_KEY ), 0, KEY_READ | KEY_WRITE, &hkLsaKerberos ); + if(rv != ERROR_SUCCESS) + goto cleanup; + + phase = 3; + + rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( LSA_KERBEROS_PARM_KEY ), 0, KEY_READ | KEY_WRITE, &hkLsaKerberosParm ); + if(rv != ERROR_SUCCESS) { + hkLsaKerberosParm = NULL; + } + + if(pInstall) { + // backup the existing values + if(hkLsaKerberosParm) { + phase = 4; + + size = sizeof(value); + rv = RegQueryValueEx( hkLsaKerberosParm, _T( SESSKEY_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size ); + if(rv != ERROR_SUCCESS) + value = 0; + + phase = 5; + rv = RegSetValueEx( hkKfwClient, _T( SESSBACKUP_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value)); + if(rv != ERROR_SUCCESS) + goto cleanup; + } + + phase = 6; + size = sizeof(value); + rv = RegQueryValueEx( hkLsaKerberos, _T( SESSKEY_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size ); + if(rv != ERROR_SUCCESS) + value = 0; + + phase = 7; + rv = RegSetValueEx( hkKfwClient, _T( SESSXPBACKUP_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value)); + if(rv != ERROR_SUCCESS) + goto cleanup; + + // and now write the actual values + phase = 8; + value = 1; + rv = RegSetValueEx( hkLsaKerberos, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value)); + if(rv != ERROR_SUCCESS) + goto cleanup; + + if(hkLsaKerberosParm) { + phase = 9; + value = 1; + rv = RegSetValueEx( hkLsaKerberosParm, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value)); + if(rv != ERROR_SUCCESS) + goto cleanup; + } + + } else { // uninstalling + // Don't fail no matter what goes wrong. This is also a rollback action. + if(hkLsaKerberosParm) { + size = sizeof(value); + rv = RegQueryValueEx( hkKfwClient, _T( SESSBACKUP_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size ); + if(rv != ERROR_SUCCESS) + value = 0; + + RegSetValueEx( hkLsaKerberosParm, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value)); + } + + size = sizeof(value); + rv = RegQueryValueEx( hkKfwClient, _T( SESSXPBACKUP_VALUE_NAME ), NULL, &type, (LPBYTE) &value, &size ); + if(rv != ERROR_SUCCESS) + value = 0; + + RegSetValueEx( hkLsaKerberos, _T( SESSKEY_VALUE_NAME ), 0, REG_DWORD, (LPBYTE) &value, sizeof(value)); + + RegDeleteValue( hkKfwClient, _T( SESSXPBACKUP_VALUE_NAME ) ); + RegDeleteValue( hkKfwClient, _T( SESSBACKUP_VALUE_NAME ) ); + } + + // all done + rv = ERROR_SUCCESS; + +cleanup: + if(rv != ERROR_SUCCESS && pInstall) { + ShowMsiError(hInstall, 4005, phase); + } + if(hkKfwClient) RegCloseKey( hkKfwClient ); + if(hkLsaKerberos) RegCloseKey( hkLsaKerberos ); + if(hkLsaKerberosParm) RegCloseKey( hkLsaKerberosParm ); + + return rv; +} + +/* Abort the installation (called as an immediate custom action) */ +MSIDLLEXPORT AbortMsiImmediate( MSIHANDLE hInstall ) { + DWORD rv; + DWORD dwSize = 0; + LPTSTR sReason = NULL; + LPTSTR sFormatted = NULL; + MSIHANDLE hRecord = NULL; + LPTSTR cAbortReason = _T("ABORTREASON"); + + rv = MsiGetProperty( hInstall, cAbortReason, _T(""), &dwSize ); + if(rv != ERROR_MORE_DATA) goto _cleanup; + + sReason = new TCHAR[ ++dwSize ]; + + rv = MsiGetProperty( hInstall, cAbortReason, sReason, &dwSize ); + + if(rv != ERROR_SUCCESS) goto _cleanup; + + hRecord = MsiCreateRecord(3); + MsiRecordClearData(hRecord); + MsiRecordSetString(hRecord, 0, sReason); + + dwSize = 0; + + rv = MsiFormatRecord(hInstall, hRecord, "", &dwSize); + if(rv != ERROR_MORE_DATA) goto _cleanup; + + sFormatted = new TCHAR[ ++dwSize ]; + + rv = MsiFormatRecord(hInstall, hRecord, sFormatted, &dwSize); + + if(rv != ERROR_SUCCESS) goto _cleanup; + + MsiCloseHandle(hRecord); + + hRecord = MsiCreateRecord(3); + MsiRecordClearData(hRecord); + MsiRecordSetInteger(hRecord, 1, ERR_ABORT); + MsiRecordSetString(hRecord,2, sFormatted); + MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecord); + +_cleanup: + if(sFormatted) delete sFormatted; + if(hRecord) MsiCloseHandle( hRecord ); + if(sReason) delete sReason; + + return ~ERROR_SUCCESS; +} + +/* Kill specified processes that are running on the system */ +/* Uses the custom table KillProcess. Called as an immediate action. */ + +#define MAX_KILL_PROCESSES 255 +#define FIELD_SIZE 256 + +struct _KillProc { + TCHAR * image; + TCHAR * desc; + BOOL found; + DWORD pid; +}; + +#define RV_BAIL if(rv != ERROR_SUCCESS) goto _cleanup + +MSIDLLEXPORT KillRunningProcesses( MSIHANDLE hInstall ) { + return KillRunningProcessesSlave( hInstall, TRUE ); +} + +/* When listing running processes, we populate the ListBox table with + values associated with the property 'KillableProcesses'. If we + actually find any processes worth killing, then we also set the + 'FoundProcceses' property to '1'. Otherwise we set it to ''. +*/ + +MSIDLLEXPORT ListRunningProcesses( MSIHANDLE hInstall ) { + return KillRunningProcessesSlave( hInstall, FALSE ); +} + +UINT KillRunningProcessesSlave( MSIHANDLE hInstall, BOOL bKill ) +{ + UINT rv = ERROR_SUCCESS; + _KillProc * kpList; + int nKpList = 0; + int i; + int rowNum = 1; + DWORD size; + BOOL found = FALSE; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hViewInsert = NULL; + MSIHANDLE hRecord = NULL; + MSIHANDLE hRecordInsert = NULL; + + HANDLE hSnapshot = NULL; + + PROCESSENTRY32 pe; + + kpList = new _KillProc[MAX_KILL_PROCESSES]; + memset(kpList, 0, sizeof(*kpList) * MAX_KILL_PROCESSES); + + hDatabase = MsiGetActiveDatabase( hInstall ); + if( hDatabase == NULL ) { + rv = GetLastError(); + goto _cleanup; + } + + // If we are only going to list out the processes, delete all the existing + // entries first. + + if(!bKill) { + + rv = MsiDatabaseOpenView( hDatabase, + _T( "DELETE FROM `ListBox` WHERE `ListBox`.`Property` = 'KillableProcesses'" ), + &hView); RV_BAIL; + + rv = MsiViewExecute( hView, NULL ); RV_BAIL; + + MsiCloseHandle( hView ); + + hView = NULL; + + rv = MsiDatabaseOpenView( hDatabase, + _T( "SELECT * FROM `ListBox` WHERE `Property` = 'KillableProcesses'" ), + &hViewInsert); RV_BAIL; + + MsiViewExecute(hViewInsert, NULL); + + hRecordInsert = MsiCreateRecord(4); + + if(hRecordInsert == NULL) { + rv = GetLastError(); + goto _cleanup; + } + } + + // Open a view + rv = MsiDatabaseOpenView( hDatabase, + _T( "SELECT `Image`,`Desc` FROM `KillProcess`" ), + &hView); RV_BAIL; + + rv = MsiViewExecute( hView, NULL ); RV_BAIL; + + do { + rv = MsiViewFetch( hView, &hRecord ); + if(rv != ERROR_SUCCESS) { + if(hRecord) + MsiCloseHandle(hRecord); + hRecord = NULL; + break; + } + + kpList[nKpList].image = new TCHAR[ FIELD_SIZE ]; kpList[nKpList].image[0] = _T('\0'); + kpList[nKpList].desc = new TCHAR[ FIELD_SIZE ]; kpList[nKpList].desc[0] = _T('\0'); + nKpList++; + + size = FIELD_SIZE; + rv = MsiRecordGetString(hRecord, 1, kpList[nKpList-1].image, &size); RV_BAIL; + + size = FIELD_SIZE; + rv = MsiRecordGetString(hRecord, 2, kpList[nKpList-1].desc, &size); RV_BAIL; + + MsiCloseHandle(hRecord); + } while(nKpList < MAX_KILL_PROCESSES); + + hRecord = NULL; + + // now we have all the processes in the array. Check if they are running. + + hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); + if(hSnapshot == INVALID_HANDLE_VALUE) { + rv = GetLastError(); + goto _cleanup; + } + + pe.dwSize = sizeof( PROCESSENTRY32 ); + + if(!Process32First( hSnapshot, &pe )) { + // technically we should at least find the MSI process, but we let this pass + rv = ERROR_SUCCESS; + goto _cleanup; + } + + do { + for(i=0; i<nKpList; i++) { + if(!_tcsicmp( kpList[i].image, pe.szExeFile )) { + // got one + if(bKill) { + // try to kill the process + HANDLE hProcess = NULL; + + // If we encounter an error, instead of bailing + // out, we continue on to the next process. We + // may not have permission to kill all the + // processes we want to kill anyway. If there are + // any files that we want to replace that is in + // use, Windows Installer will schedule a reboot. + // Also, it's not like we have an exhaustive list + // of all the programs that use Kerberos anyway. + + hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID); + if(hProcess == NULL) { + rv = GetLastError(); + break; + } + + if(!TerminateProcess(hProcess, 0)) { + rv = GetLastError(); + CloseHandle(hProcess); + break; + } + + CloseHandle(hProcess); + + } else { + TCHAR buf[256]; + + // we are supposed to just list out the processes + rv = MsiRecordClearData( hRecordInsert ); RV_BAIL; + rv = MsiRecordSetString( hRecordInsert, 1, _T("KillableProcesses")); + rv = MsiRecordSetInteger( hRecordInsert, 2, rowNum++ ); RV_BAIL; + _itot( rowNum, buf, 10 ); + rv = MsiRecordSetString( hRecordInsert, 3, buf ); RV_BAIL; + if(_tcslen(kpList[i].desc)) { + rv = MsiRecordSetString( hRecordInsert, 4, kpList[i].desc ); RV_BAIL; + } else { + rv = MsiRecordSetString( hRecordInsert, 4, kpList[i].image ); RV_BAIL; + } + MsiViewModify(hViewInsert, MSIMODIFY_INSERT_TEMPORARY, hRecordInsert); RV_BAIL; + + found = TRUE; + } + break; + } + } + } while( Process32Next( hSnapshot, &pe ) ); + + if(!bKill) { + // set the 'FoundProcceses' property + if(found) { + MsiSetProperty( hInstall, _T("FoundProcesses"), _T("1")); + } else { + MsiSetProperty( hInstall, _T("FoundProcesses"), _T("")); + } + } + + // Finally: + rv = ERROR_SUCCESS; + +_cleanup: + + if(hRecordInsert) MsiCloseHandle(hRecordInsert); + if(hViewInsert) MsiCloseHandle(hView); + + if(hSnapshot && hSnapshot != INVALID_HANDLE_VALUE) CloseHandle(hSnapshot); + + while(nKpList) { + nKpList--; + delete kpList[nKpList].image; + delete kpList[nKpList].desc; + } + delete kpList; + + if(hRecord) MsiCloseHandle(hRecord); + if(hView) MsiCloseHandle(hView); + + if(hDatabase) MsiCloseHandle(hDatabase); + + if(rv != ERROR_SUCCESS) { + ShowMsiError(hInstall, ERR_PROC_LIST, rv); + } + + return rv; +} + +/* Uninstall NSIS */ +MSIDLLEXPORT UninstallNsisInstallation( MSIHANDLE hInstall ) +{ + DWORD rv = ERROR_SUCCESS; + // lookup the NSISUNINSTALL property value + LPTSTR cNsisUninstall = _T("UPGRADENSIS"); + HANDLE hIo = NULL; + DWORD dwSize = 0; + LPTSTR strPathUninst = NULL; + HANDLE hJob = NULL; + STARTUPINFO sInfo; + PROCESS_INFORMATION pInfo; + + pInfo.hProcess = NULL; + pInfo.hThread = NULL; + + rv = MsiGetProperty( hInstall, cNsisUninstall, _T(""), &dwSize ); + if(rv != ERROR_MORE_DATA) goto _cleanup; + + strPathUninst = new TCHAR[ ++dwSize ]; + + rv = MsiGetProperty( hInstall, cNsisUninstall, strPathUninst, &dwSize ); + if(rv != ERROR_SUCCESS) goto _cleanup; + + // Create a process for the uninstaller + sInfo.cb = sizeof(sInfo); + sInfo.lpReserved = NULL; + sInfo.lpDesktop = _T(""); + sInfo.lpTitle = _T("Foo"); + sInfo.dwX = 0; + sInfo.dwY = 0; + sInfo.dwXSize = 0; + sInfo.dwYSize = 0; + sInfo.dwXCountChars = 0; + sInfo.dwYCountChars = 0; + sInfo.dwFillAttribute = 0; + sInfo.dwFlags = 0; + sInfo.wShowWindow = 0; + sInfo.cbReserved2 = 0; + sInfo.lpReserved2 = 0; + sInfo.hStdInput = 0; + sInfo.hStdOutput = 0; + sInfo.hStdError = 0; + + if(!CreateProcess( + strPathUninst, + _T("Uninstall /S"), + NULL, + NULL, + FALSE, + CREATE_SUSPENDED, + NULL, + NULL, + &sInfo, + &pInfo)) { + pInfo.hProcess = NULL; + pInfo.hThread = NULL; + rv = 40; + goto _cleanup; + }; + + // Create a job object to contain the NSIS uninstall process tree + + JOBOBJECT_ASSOCIATE_COMPLETION_PORT acp; + + acp.CompletionKey = 0; + + hJob = CreateJobObject(NULL, _T("NSISUninstallObject")); + if(!hJob) { + rv = 41; + goto _cleanup; + } + + hIo = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0); + if(!hIo) { + rv = 42; + goto _cleanup; + } + + acp.CompletionPort = hIo; + + SetInformationJobObject( hJob, JobObjectAssociateCompletionPortInformation, &acp, sizeof(acp)); + + AssignProcessToJobObject( hJob, pInfo.hProcess ); + + ResumeThread( pInfo.hThread ); + + DWORD a,b,c; + for(;;) { + if(!GetQueuedCompletionStatus(hIo, &a, (PULONG_PTR) &b, (LPOVERLAPPED *) &c, INFINITE)) { + Sleep(1000); + continue; + } + if(a == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) { + break; + } + } + + rv = ERROR_SUCCESS; + +_cleanup: + if(hIo) CloseHandle(hIo); + if(pInfo.hProcess) CloseHandle( pInfo.hProcess ); + if(pInfo.hThread) CloseHandle( pInfo.hThread ); + if(hJob) CloseHandle(hJob); + if(strPathUninst) delete strPathUninst; + + if(rv != ERROR_SUCCESS) { + ShowMsiError( hInstall, ERR_NSS_FAILED, rv ); + } + return rv; +} + +/* Check and add or remove networkprovider key value + str : target string + str2: string to add/remove + bInst: == 1 if string should be added to target if not already there, + otherwise remove string from target if present. +*/ +int npi_CheckAndAddRemove( LPTSTR str, LPTSTR str2, int bInst ) { + + LPTSTR target, charset, match; + int ret=0; + + target = new TCHAR[lstrlen(str)+3]; + lstrcpy(target,_T(",")); + lstrcat(target,str); + lstrcat(target,_T(",")); + charset = new TCHAR[lstrlen(str2)+3]; + lstrcpy(charset,_T(",")); + lstrcat(charset,str2); + lstrcat(charset,_T(",")); + + match = _tcsstr(target, charset); + + if ((match) && (bInst)) { + ret = INP_ERR_PRESENT; + goto cleanup; + } + + if ((!match) && (!bInst)) { + ret = INP_ERR_ABSENT; + goto cleanup; + } + + if (bInst) // && !match + { + lstrcat(str, _T(",")); + lstrcat(str, str2); + ret = INP_ERR_ADDED; + goto cleanup; + } + + // if (!bInst) && (match) + { + lstrcpy(str+(match-target),match+lstrlen(str2)+2); + str[lstrlen(str)-1]=_T('\0'); + ret = INP_ERR_REMOVED; + goto cleanup; + } + +cleanup: + + delete target; + delete charset; + return ret; +} + +/* Sets the registry keys required for the functioning of the network provider */ + +DWORD InstNetProvider(MSIHANDLE hInstall, int bInst) { + LPTSTR strOrder; + HKEY hkOrder; + LONG rv; + DWORD dwSize; + HANDLE hProcHeap; + + strOrder = (LPTSTR) 0; + + CHECK(rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, STR_KEY_ORDER, 0, KEY_READ | KEY_WRITE, &hkOrder )); + + dwSize = 0; + CHECK(rv = RegQueryValueEx( hkOrder, STR_VAL_ORDER, NULL, NULL, NULL, &dwSize ) ); + + strOrder = new TCHAR[ (dwSize + STR_SERVICE_LEN + 4) * sizeof(TCHAR) ]; + + CHECK(rv = RegQueryValueEx( hkOrder, STR_VAL_ORDER, NULL, NULL, (LPBYTE) strOrder, &dwSize)); + + strOrder[dwSize] = '\0'; /* reg strings are not always nul terminated */ + + npi_CheckAndAddRemove( strOrder, STR_SERVICE , bInst); + + dwSize = (lstrlen( strOrder ) + 1) * sizeof(TCHAR); + + CHECK(rv = RegSetValueEx( hkOrder, STR_VAL_ORDER, NULL, REG_SZ, (LPBYTE) strOrder, dwSize )); + + /* everything else should be set by the MSI tables */ + rv = ERROR_SUCCESS; +_cleanup: + + if( rv != ERROR_SUCCESS ) { + ShowMsiError( hInstall, ERR_NPI_FAILED, rv ); + } + + if(strOrder) delete strOrder; + + return rv; +} + +MSIDLLEXPORT InstallNetProvider( MSIHANDLE hInstall ) { + return InstNetProvider( hInstall, 1 ); +} + +MSIDLLEXPORT UninstallNetProvider( MSIHANDLE hInstall) { + return InstNetProvider( hInstall, 0 ); +} + +#endif +#ifdef __NMAKE__ +!ENDIF +#endif diff --git a/krb5-1-6/src/windows/installer/wix/custom/custom.h b/krb5-1-6/src/windows/installer/wix/custom/custom.h new file mode 100644 index 000000000..2e66671a1 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/custom/custom.h @@ -0,0 +1,81 @@ +/* + +Copyright 2004 by the Massachusetts Institute of Technology + +All rights reserved. + +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 the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/* custom.h + * + * Declarations for Kerberos for Windows MSI setup tools + * + * rcsid : $Id$ + */ + +#pragma once + +#include<windows.h> +#include<setupapi.h> +#include<msiquery.h> +#include<string.h> +#include<tchar.h> +#include<tlhelp32.h> + +#define MSIDLLEXPORT UINT __stdcall + +#define CHECK(x) if((x)) goto _cleanup + +#define CHECKX(x,y) if(!(x)) { msiErr = (y); goto _cleanup; } + +#define CHECK2(x,y) if((x)) { msiErr = (y); goto _cleanup; } + +#define STR_KEY_ORDER _T("SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order") +#define STR_VAL_ORDER _T("ProviderOrder") + +#define STR_SERVICE _T("MIT Kerberos") +#define STR_SERVICE_LEN 12 + + +void ShowMsiError(MSIHANDLE, DWORD, DWORD); +UINT SetAllowTgtSessionKey( MSIHANDLE hInstall, BOOL pInstall ); +UINT KillRunningProcessesSlave( MSIHANDLE hInstall, BOOL bKill ); + +/* exported */ +MSIDLLEXPORT AbortMsiImmediate( MSIHANDLE ); +MSIDLLEXPORT UninstallNsisInstallation( MSIHANDLE hInstall ); +MSIDLLEXPORT RevertAllowTgtSessionKey( MSIHANDLE hInstall ); +MSIDLLEXPORT EnableAllowTgtSessionKey( MSIHANDLE hInstall ); +MSIDLLEXPORT KillRunningProcesses( MSIHANDLE hInstall ) ; +MSIDLLEXPORT ListRunningProcesses( MSIHANDLE hInstall ); +MSIDLLEXPORT InstallNetProvider( MSIHANDLE ); +MSIDLLEXPORT UninstallNetProvider ( MSIHANDLE ); + +#define INP_ERR_PRESENT 1 +#define INP_ERR_ADDED 2 +#define INP_ERR_ABSENT 3 +#define INP_ERR_REMOVED 4 + +/* Custom errors */ +#define ERR_CUSTACTDATA 4001 +#define ERR_NSS_FAILED 4003 +#define ERR_ABORT 4004 +#define ERR_PROC_LIST 4006 +#define ERR_NPI_FAILED 4007 diff --git a/krb5-1-6/src/windows/installer/wix/features.wxi b/krb5-1-6/src/windows/installer/wix/features.wxi new file mode 100644 index 000000000..a15cfcd86 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/features.wxi @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + Copyright (C) 2004, 2005, 2006 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> +<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> + <Feature + Id="feaKfw" + AllowAdvertise="no" + Description="$(loc.KerberosDesc)" + InstallDefault="local" + Title="$(loc.KerberosTitle)" + ConfigurableDirectory="KERBEROSDIR" + Level="30"> + <Feature + Id="feaKfwClient" + AllowAdvertise="no" + Description="$(loc.KerberosClientDesc)" + InstallDefault="local" + Title="$(loc.KerberosClientTitle)" + Level="30"> + + <?ifdef DebugSyms?> + <Feature + Id="feaKfwClientDebug" + AllowAdvertise="no" + Description="$(loc.StrKerberosClientDebugDesc)" + Display="expand" + InstallDefault="$(var.DebugSymInstallDefault)" + Level="$(var.DebugSymLowLevel)" + Title="$(loc.StrKerberosClientDebugTitle)"> + <ComponentRef Id="cmf_bin_debug"/> + <ComponentRef Id="cmp_ClientSystemDebug"/> + <?include runtime_debug.wxi?> + </Feature> + <?endif?> + + <ComponentRef Id="cmf_comerr32_dll" /> + <ComponentRef Id="cmf_gss_exe" /> + <ComponentRef Id="cmf_gss_client_exe" /> + <ComponentRef Id="cmf_gss_server_exe" /> + <ComponentRef Id="cmf_gssapi32_dll" /> + <ComponentRef Id="cmf_kdestroy_exe" /> + <ComponentRef Id="cmf_kcpytkt_exe" /> + <ComponentRef Id="cmf_kdeltkt_exe" /> + <ComponentRef Id="cmf_kinit_exe" /> + <ComponentRef Id="cmf_klist_exe" /> + <ComponentRef Id="cmf_kpasswd_exe" /> + <ComponentRef Id="cmf_kvno_exe" /> + <ComponentRef Id="cmf_krb5_32_dll" /> + <ComponentRef Id="cmf_k5sprt32_dll" /> + <ComponentRef Id="cmf_krbcc32_dll" /> + <ComponentRef Id="cmf_krbcc32s_exe" /> + <ComponentRef Id="cmf_ms2mit_exe" /> + <ComponentRef Id="cmf_mit2ms_exe" /> + <ComponentRef Id="cmf_wshelp32_dll" /> + <ComponentRef Id="cmf_xpprof32_dll" /> + + <ComponentRef Id="cmf_leashw32_dll" /> + + <?if $(var.Platform) = "Intel" ?> + <ComponentRef Id="cmf_leash32_exe" /> + <ComponentRef Id="csc_leash32_exe" /> + + <ComponentRef Id="cmf_k524init_exe" /> + <ComponentRef Id="cmf_kclnt32_dll" /> + <ComponentRef Id="cmf_krb524_dll" /> + <ComponentRef Id="cmf_krbv4w32_dll" /> + <?endif?> + + <ComponentRef Id="cmf_nidmgr32_dll" /> + <?if $(var.Platform) = "Intel" ?> + <ComponentRef Id="cmf_nidmgr32_dll_w2k" /> + <?endif?> + <ComponentRef Id="cmf_krb5cred_dll" /> + <ComponentRef Id="cmf_krb5cred_en_us_dll" /> + <?if $(var.Platform) = "Intel" ?> + <ComponentRef Id="cmf_krb4cred_dll" /> + <ComponentRef Id="cmf_krb4cred_en_us_dll" /> + <?endif?> + <ComponentRef Id="cmf_netidmgr_exe" /> + <?if $(var.Platform) = "Intel" ?> + <ComponentRef Id="cmf_netidmgr_exe_w2k" /> + <?endif?> + <ComponentRef Id="cmf_kfwlogon_DLL" /> + <ComponentRef Id="cmf_kfwcpcc_EXE" /> + + <?if $(var.Platform) = "Intel" ?> + <!-- Kerberos IV options --> + <ComponentRef Id="rcm_krb4_1" /> + <ComponentRef Id="rcm_krb4_2" /> + <ComponentRef Id="rcm_krb4_3" /> + <ComponentRef Id="rcm_krb4_4" /> + <?endif?> + + <!-- Kerberos V options --> + <ComponentRef Id="rcm_krb5_1" /> + <ComponentRef Id="rcm_krb5_2" /> + <ComponentRef Id="rcm_krb5_3" /> + + <?if $(var.Platform) = "Intel" ?> + <!-- Leash config options --> + <ComponentRef Id="rcm_leash_1" /> + <ComponentRef Id="rcm_leash_2" /> + <ComponentRef Id="rcm_leash_3" /> + <ComponentRef Id="rcm_leash_5" /> + <ComponentRef Id="rcm_leash_6" /> + + <?ifdef OldHelp?> + <ComponentRef Id="cmf_leash32_hlp" /> + <?else?> + <ComponentRef Id="cmf_leash32_chm" /> + <?endif?> + <?endif?> + + <!-- Leash dll options --> + <ComponentRef Id="rcm_leashdll_1" /> + <ComponentRef Id="rcm_leashdll_2" /> + <ComponentRef Id="rcm_leashdll_3" /> + <ComponentRef Id="rcm_leashdll_4" /> + <ComponentRef Id="rcm_leashdll_5" /> + <ComponentRef Id="rcm_leashdll_6" /> + <ComponentRef Id="rcm_leashdll_7" /> + <ComponentRef Id="rcm_leashdll_8" /> + <ComponentRef Id="rcm_leashdll_9" /> + <ComponentRef Id="rcm_leashdll_10" /> + <ComponentRef Id="rcm_leashdll_11" /> + <ComponentRef Id="rcm_leashdll_12" /> + <ComponentRef Id="rcm_leashdll_13" /> + <ComponentRef Id="rcm_leashdll_15" /> + <ComponentRef Id="rcm_leashdll_16" /> + <ComponentRef Id="rcm_leashdll_17" /> + + <ComponentRef Id="cmf_psapi_dll" /> + + <ComponentRef Id="cmf_krb5_ini" /> + <ComponentRef Id="cmf_krb_con" /> + <ComponentRef Id="cmf_krbrealm_con" /> + + <ComponentRef Id="rcm_common" /> + <ComponentRef Id="rcm_client" /> + + <Feature Id="feaKfwLeashStartup" AllowAdvertise="no" Display="hidden" Level="130"> + <Condition Level="30">LEASHAUTOSTART = 1</Condition> + <ComponentRef Id="csc_NetIDMgrStartup" /> + <?if $(var.Platform) = "Intel"?> + <ComponentRef Id="csc_LeashStartup" /> + <?endif?> + </Feature> + + <?include runtime.wxi?> + </Feature> <!-- /feaKfwClient --> + + <Feature + Id="feaKfwSDK" + AllowAdvertise="no" + Description="$(loc.KerberosSDKDesc)" + InstallDefault="local" + Level="130" + Title="$(loc.KerberosSDKTitle)"> + + <ComponentRef Id="cmp_dirdoc_netid" /> + <?if $(var.Platform) = "Intel" ?> + <ComponentRef Id="cmp_dirinc_kclient" /> + <ComponentRef Id="cmp_dirinc_krb4" /> + <ComponentRef Id="cmp_dirlib_i386" /> + <?else?> + <ComponentRef Id="cmp_dirlib_amd64" /> + <?endif?> + <ComponentRef Id="cmp_dirinc_krb5_gssapi" /> + <ComponentRef Id="cmp_dirinc_krb5_KerberosIV" /> + <ComponentRef Id="cmp_dirinc_krb5_krb5" /> + <ComponentRef Id="cmp_dirinc_krb5" /> + <ComponentRef Id="cmp_dirinc_krbcc" /> + <ComponentRef Id="cmp_dirinc_leash" /> + <ComponentRef Id="cmp_dirinc_loadfuncs" /> + <ComponentRef Id="cmp_dirinc_wshelper" /> + <ComponentRef Id="cmp_dirinc_wshelper_arpa" /> + <ComponentRef Id="cmp_dirinc_netidmgr" /> + <ComponentRef Id="cmp_dirinstall_nsis" /> + <ComponentRef Id="cmp_dirinstall_wix" /> + <ComponentRef Id="cmp_dirinstall_wix_lang" /> + <ComponentRef Id="cmp_dirinstall_wix_Binary" /> + <ComponentRef Id="cmp_dirinstall_wix_custom" /> + <ComponentRef Id="cmp_credprov_files" /> + <ComponentRef Id="cmp_credprov_images_files" /> + <ComponentRef Id="cmp_credprov_en_us_files" /> + <ComponentRef Id="rcm_common" /> + <ComponentRef Id="rcm_sdk" /> + </Feature> <!-- /feaKfwSDK --> + + <Feature + Id="feaKfwDocs" + AllowAdvertise="no" + Description="$(loc.KerberosDocDesc)" + InstallDefault="local" + Level="30" + Title="$(loc.KerberosDocTitle)"> + + <?if $(var.Platform) = "Intel"?> + <ComponentRef Id="efl_leash_userdoc_pdf" /> + <?endif?> + <ComponentRef Id="efl_netidmgr_userdoc_pdf" /> + <ComponentRef Id="efl_relnotes_html" /> + + <ComponentRef Id="rcm_common" /> + <ComponentRef Id="rcm_docs" /> + </Feature> + + </Feature> +</Include> diff --git a/krb5-1-6/src/windows/installer/wix/files.wxi b/krb5-1-6/src/windows/installer/wix/files.wxi new file mode 100644 index 000000000..360033f06 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/files.wxi @@ -0,0 +1,1103 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + Copyright (C) 2004, 2005, 2006 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> +<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> +<Directory Id="TARGETDIR" Name="SourceDir"> + <Directory Id="SystemFolder" SourceName="System"> + <Component Win64="$(var.Win64)" Id="cmf_kfwlogon_DLL" Guid="$(var.cmf_kfwlogon_DLL_guid)"> + <File Id="filekfwlogon_DLL" Name="kfwlogon.dll" LongName="kfwlogon.dll" KeyPath="yes" DiskId="1" src="$(var.BinDir)kfwlogon.dll" /> + <Registry Id="reg_kfwlogon01" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_kfwlogon02" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" /> + <Registry Id="reg_kfwlogon03" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="Asynchronous" Type="integer" Value="0" /> + <Registry Id="reg_kfwlogon04" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="Impersonate" Type="integer" Value="0" /> + <Registry Id="reg_kfwlogon05" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="DLLName" Type="string" Value="[#filekfwlogon_DLL]" /> + <Registry Id="reg_kfwlogon06" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\Notify\MIT_KFW" Name="Logon" Type="string" Value="KFW_Logon_Event" /> + <Registry Id="reg_kfwlogon07" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_kfwlogon08" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Name="AuthentProviderPath" Type="expandable" Value="[SystemFolder]kfwlogon.dll"/> + <Registry Id="reg_kfwlogon09" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider"/> + <Registry Id="reg_kfwlogon10" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Name="VerboseLogging" Type="integer" Value="10"/> + <Registry Id="reg_kfwlogon11" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Name="ProviderPath" Type="expandable" Value="[SystemFolder]kfwlogon.dll"/> + <Registry Id="reg_kfwlogon12" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Name="Class" Type="integer" Value="2" /> + <Registry Id="reg_kfwlogon13" Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\MIT Kerberos\NetworkProvider" Name="Name" Type="string" Value="MIT Kerberos"/> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_kfwcpcc_EXE" Guid="$(var.cmf_kfwcpcc_EXE_guid)"> + <File Id="filekfwcpcc_EXE" Name="kfwcpcc.exe" LongName="kfwcpcc.exe" DiskId="1" src="$(var.BinDir)kfwcpcc.exe" /> + </Component> + <?ifdef DebugSyms?> + <Component Win64="$(var.Win64)" Id="cmp_ClientSystemDebug" Guid="$(var.cmp_ClientSystemDebug_guid)"> + <File Id="filekfwlogon_PDB" Name="kfwlogon.pdb" LongName="kfwlogon.pdb" KeyPath="yes" DiskId="1" src="$(var.BinDir)kfwlogon.pdb" /> + <File Id="filekfwcpcc_PDB" Name="kfwcpcc.pdb" LongName="kfwcpcc.pdb" DiskId="1" src="$(var.BinDir)kfwcpcc.pdb" /> + </Component> + <?endif?> + </Directory> + <Directory Id="ProgramFilesFolder"> + <Directory Id="dirMIT" Name="MIT" SourceName="."> + <Directory Id="KERBEROSDIR" Name="Kerberos"> + <Directory Id="dirbin" Name="bin" src="$(var.BinDir)"> + + <?if $(var.Platform) = "Intel" ?> + <!-- Kerberos IV options --> + <Component Win64="$(var.Win64)" Id="rcm_krb4_1" Guid="$(var.rcm_krb4_1_guid)" DiskId="1"> + <Registry Id="reg_krb4_1" Root="HKLM" Key="Software\MIT\Kerberos4" Name="krb.realms" Type="string" Value="[KRB4KRBREALMS]" KeyPath="yes"/> + <Condition>KRB4KRBREALMS</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_krb4_2" Guid="$(var.rcm_krb4_2_guid)" DiskId="1"> + <Registry Id="reg_krb4_2" Root="HKLM" Key="Software\MIT\Kerberos4" Name="krb.conf" Type="string" Value="[KRB4KRBCONF]" KeyPath="yes"/> + <Condition>KRB4KRBCONF</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_krb4_3" Guid="$(var.rcm_krb4_3_guid)" DiskId="1"> + <Registry Id="reg_krb4_3" Root="HKLM" Key="Software\MIT\Kerberos4" Name="configdir" Type="string" Value="[KRB4CONFIGDIR]" KeyPath="yes"/> + <Condition>KRB4CONFIGDIR</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_krb4_4" Guid="$(var.rcm_krb4_4_guid)" DiskId="1"> + <Registry Id="reg_krb4_4" Root="HKLM" Key="Software\MIT\Kerberos4" Name="ticketfile" Type="string" Value="[KRB4TICKETFILE]" KeyPath="yes"/> + <Condition>KRB4TICKETFILE</Condition> + </Component> + <?endif?> + + <!-- Kerberos V options --> + <Component Win64="$(var.Win64)" Id="rcm_krb5_1" Guid="$(var.rcm_krb5_1_guid)" DiskId="1"> + <Registry Id="reg_krb5_1" Root="HKLM" Key="Software\MIT\kerberos5" Name="config" Type="string" Value="[KRB5CONFIG]" KeyPath="yes" /> + <Condition>KRB5CONFIG</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_krb5_2" Guid="$(var.rcm_krb5_2_guid)" DiskId="1"> + <Registry Id="reg_krb5_2" Root="HKLM" Key="Software\MIT\kerberos5" Name="ccname" Type="string" Value="[KRB5CCNAME]" KeyPath="yes" /> + <Condition>KRB5CCNAME</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_krb5_3" Guid="$(var.rcm_krb5_3_guid)" DiskId="1"> + <Registry Id="reg_krb5_3" Root="HKLM" Key="Software\MIT\kerberos5" Name="PreserveInitialTicketIdentity" Type="integer" Value="[KRB5PRESERVEIDENTITY]" KeyPath="yes" /> + <Condition>KRB5PRESERVEIDENTITY</Condition> + </Component> + + <Component Win64="$(var.Win64)" Id="cmf_comerr32_dll" Guid="$(var.cmf_comerr32_dll_guid)" DiskId="1"> + <File Id="fil_comerr32_dll" LongName="$(var.cmf_comerr32_dll_name)" Name="$(var.cmf_comerr32_dll_name)" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_gss_exe" Guid="$(var.cmf_gss_exe_guid)" DiskId="1"> + <File Id="fil_gss_exe" LongName="gss.exe" Name="gss.exe" KeyPath="yes" /> + <Registry Id="reg_ts_gss_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_gss_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_gss_client_exe" Guid="$(var.cmf_gss_client_exe_guid)" DiskId="1"> + <File Id="fil_gss_client_exe" LongName="gss-client.exe" Name="gss-clnt.exe" KeyPath="yes" /> + <Registry Id="reg_ts_gss_client_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-client" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_gss_client_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-client" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_gss_server_exe" Guid="$(var.cmf_gss_server_exe_guid)" DiskId="1"> + <File Id="fil_gss_server_exe" LongName="gss-server.exe" Name="gss-srvr.exe" KeyPath="yes" /> + <Registry Id="reg_ts_gss_server_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-server" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_gss_server_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\gss-server" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_gssapi32_dll" Guid="$(var.cmf_gssapi32_dll_guid)" DiskId="1"> + <File Id="fil_gssapi32_dll" LongName="$(var.cmf_gssapi32_dll_name)" Name="$(var.cmf_gssapi32_dll_name)" KeyPath="yes" /> + </Component> + <?if $(var.Platform) = "Intel" ?> + <Component Win64="$(var.Win64)" Id="cmf_k524init_exe" Guid="$(var.cmf_k524init_exe_guid)" DiskId="1"> + <File Id="fil_k524init_exe" LongName="k524init.exe" Name="k524init.exe" KeyPath="yes" /> + <Registry Id="reg_ts_k524init_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k524init" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_k524init_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\k524init" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_kclnt32_dll" Guid="$(var.cmf_kclnt32_dll_guid)" DiskId="1"> + <File Id="fil_kclnt32_dll" LongName="$(var.cmf_kclnt32_dll_name)" Name="$(var.cmf_kclnt32_dll_name)" KeyPath="yes" /> + </Component> + <?endif?> + <Component Win64="$(var.Win64)" Id="cmf_kdestroy_exe" Guid="$(var.cmf_kdestroy_exe_guid)" DiskId="1"> + <File Id="fil_kdestroy_exe" LongName="kdestroy.exe" Name="kdestroy.exe" KeyPath="yes" /> + <Registry Id="reg_ts_kdestroy_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdestroy" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_kdestroy_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdestroy" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_kcpytkt_exe" Guid="$(var.cmf_kcpytkt_exe_guid)" DiskId="1"> + <File Id="fil_kcpytkt_exe" LongName="kcpytkt.exe" Name="kcpytkt.exe" KeyPath="yes" /> + <Registry Id="reg_ts_kcpytkt_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kcpytkt" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_kcpytkt_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kcpytkt" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_kdeltkt_exe" Guid="$(var.cmf_kdeltkt_exe_guid)" DiskId="1"> + <File Id="fil_kdeltkt_exe" LongName="kdeltkt.exe" Name="kdeltkt.exe" KeyPath="yes" /> + <Registry Id="reg_ts_kdeltkt_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdeltkt" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_kdeltkt_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kdeltkt" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_kinit_exe" Guid="$(var.cmf_kinit_exe_guid)" DiskId="1"> + <File Id="fil_kinit_exe" LongName="kinit.exe" Name="kinit.exe" KeyPath="yes" /> + <Registry Id="reg_ts_kinit_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kinit" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_kinit_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kinit" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_klist_exe" Guid="$(var.cmf_klist_exe_guid)" DiskId="1"> + <File Id="fil_klist_exe" LongName="klist.exe" Name="klist.exe" KeyPath="yes" /> + <Registry Id="reg_ts_klist_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klist" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_klist_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klist" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_kpasswd_exe" Guid="$(var.cmf_kpasswd_exe_guid)" DiskId="1"> + <File Id="fil_kpasswd_exe" LongName="kpasswd.exe" Name="kpasswd.exe" KeyPath="yes" /> + <Registry Id="reg_ts_kpasswd_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kpasswd" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_kpasswd_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kpasswd" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_kvno_exe" Guid="$(var.cmf_kvno_exe_guid)" DiskId="1"> + <File Id="fil_kvno_exe" LongName="kvno.exe" Name="kvno.exe" KeyPath="yes" /> + <Registry Id="reg_ts_kvno_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kvno" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_kvno_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kvno" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_krb5_32_dll" Guid="$(var.cmf_krb5_32_dll_guid)" DiskId="1"> + <File Id="fil_krb5_32_dll" LongName="$(var.cmf_krb5_32_dll_name)" Name="$(var.cmf_krb5_32_dll_name)" KeyPath="yes" /> + <Environment Id="env_kclient_path" Action="set" Name="PATH" Part="last" System="yes" Value="[KERBEROSDIR]bin" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_k5sprt32_dll" Guid="$(var.cmf_k5sprt32_dll_guid)" DiskId="1"> + <File Id="fil_k5sprt32_dll" LongName="$(var.cmf_k5sprt32_dll_name)" Name="$(var.cmf_k5sprt32_dll_name)" /> + </Component> + <?if $(var.Platform) = "Intel" ?> + <Component Win64="$(var.Win64)" Id="cmf_krb524_dll" Guid="$(var.cmf_krb524_dll_guid)" DiskId="1"> + <File Id="fil_krb524_dll" LongName="$(var.cmf_krb524_dll_name)" Name="$(var.cmf_krb524_dll_name)" KeyPath="yes" /> + </Component> + <?endif?> + <Component Win64="$(var.Win64)" Id="cmf_krbcc32_dll" Guid="$(var.cmf_krbcc32_dll_guid)" DiskId="1"> + <File Id="fil_krbcc32_dll" LongName="$(var.cmf_krbcc32_dll_name)" Name="$(var.cmf_krbcc32_dll_name)" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_krbcc32s_exe" Guid="$(var.cmf_krbcc32s_exe_guid)" DiskId="1"> + <File Id="fil_krbcc32s_exe" LongName="$(var.cmf_krbcc32s_exe_name)" Name="$(var.cmf_krbcc32s_exe_name)" KeyPath="yes" /> + <Registry Id="reg_ts_krbcc32s_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\krbcc32s" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_krbcc32s_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\krbcc32s" Name="Flags" Type="integer" Value="1032" /> + </Component> + <?if $(var.Platform) = "Intel" ?> + <Component Win64="$(var.Win64)" Id="cmf_krbv4w32_dll" Guid="$(var.cmf_krbv4w32_dll_guid)" DiskId="1"> + <File Id="fil_krbv4w32_dll" LongName="$(var.cmf_krbv4w32_dll_name)" Name="$(var.cmf_krbv4w32_dll_name)" KeyPath="yes" /> + </Component> + + <Component Win64="$(var.Win64)" Id="cmf_leash32_exe" Guid="$(var.cmf_leash32_exe_guid)" DiskId="1"> + <File Id="fil_leash32_exe" LongName="leash32.exe" Name="leash32.exe" KeyPath="yes" /> + <Registry Id="reg_ts_leash32_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\leash32" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_leash32_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\leash32" Name="Flags" Type="integer" Value="1032" /> + </Component> + + <Component Win64="$(var.Win64)" Id="csc_leash32_exe" Guid="$(var.csc_leash32_exe_guid)" DiskId="1"> + <Shortcut Id="sc_leash32_exe" Advertise="no" Directory="dirShortcut" LongName="Leash Kerberos Ticket Manager.lnk" Name="Leash32.lnk" Arguments="[LEASHAUTOINIT]" Target="[!fil_leash32_exe]" /> + <Condition>USELEASH</Condition> + </Component> + + <!-- Leash32 configuration --> + <Component Win64="$(var.Win64)" Id="rcm_leash_1" Guid="$(var.rcm_leash_1_guid)" DiskId="1"> + <Registry Id="reg_leash_1" Root="HKLM" Key="Software\MIT\Leash32\Settings" Name="AfsStatus" Type="integer" Value="[LEASHAFSSTATUS]" KeyPath="yes"/> + <Condition>LEASHAFSSTATUS</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leash_2" Guid="$(var.rcm_leash_2_guid)" DiskId="1"> + <Registry Id="reg_leash_2" Root="HKLM" Key="Software\MIT\Leash32\Settings" Name="createmissingconfig" Type="integer" Value="[LEASHCREATEMISSINGCONFIG]" KeyPath="yes"/> + <Condition>LEASHCREATEMISSINGCONFIG</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leash_3" Guid="$(var.rcm_leash_3_guid)" DiskId="1"> + <Registry Id="reg_leash_3" Root="HKLM" Key="Software\MIT\Leash32\Settings" Name="AutoRenewTickets" Type="integer" Value="[LEASHAUTORENEWTICKETS]" KeyPath="yes"/> + <Condition>LEASHAUTORENEWTICKETS</Condition> + </Component> + <!-- + <Component Win64="$(var.Win64)" Id="rcm_leash_4" Guid="$(var.rcm_leash_4_guid)" DiskId="1"> + <Registry Id="reg_leash_4" Root="HKLM" Key="Software\MIT\Leash" Action="createKey" KeyPath="yes"/> + </Component> + --> + <Component Win64="$(var.Win64)" Id="rcm_leash_5" Guid="$(var.rcm_leash_5_guid)" DiskId="1"> + <Registry Id="reg_leash_5" Root="HKLM" Key="Software\MIT\Leash" Name="lock_file_locations" Type="integer" Value="[LEASHLOCKFILELOCATIONS]" KeyPath="yes"/> + <Condition>LEASHLOCKFILELOCATIONS</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leash_6" Guid="$(var.rcm_leash_6_guid)" DiskId="1"> + <Registry Id="reg_leash_6" Root="HKLM" Key="Software\MIT\Leash" Name="MsLsaImport" Type="integer" Value="[LEASHMSLSAIMPORT]" KeyPath="yes"/> + <Condition>LEASHMSLSAIMPORT</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="csc_LeashStartup" Guid="$(var.csc_LeashStartup_guid)" DiskId="1"> + <Registry Id="reg_sc_leash_marker" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="LeashAutoStart" Type="integer" Value="1" KeyPath="yes" /> + <Shortcut Id="sc_leash_exe_startup" Advertise="no" Directory="StartupFolder" LongName="Leash Credentials Manager.lnk" Name="leash32.lnk" Arguments="[LEASHAUTOINIT]" Target="[dirbin]leash32.exe" Show="minimized" /> + <Condition>USELEASH</Condition> + </Component> + + <?ifdef OldHelp?> + <Component Win64="$(var.Win64)" Id="cmf_leash32_hlp" Guid="$(var.cmf_leash32_hlp_guid)" DiskId="1"> + <File Id="fil_leash32_hlp" LongName="leash32.hlp" Name="leash32.hlp" KeyPath="yes" /> + </Component> + <?else?> + <Component Win64="$(var.Win64)" Id="cmf_leash32_chm" Guid="$(var.cmf_leash32_chm_guid)" DiskId="1"> + <File Id="fil_leash32_chm" LongName="leash32.chm" Name="leash32.chm" KeyPath="yes" /> + </Component> + <?endif?> + <?endif?> + + <Component Win64="$(var.Win64)" Id="cmf_leashw32_dll" Guid="$(var.cmf_leashw32_dll_guid)" DiskId="1"> + <File Id="fil_leashw32_dll" LongName="$(var.cmf_leashw32_dll_name)" Name="$(var.cmf_leashw32_dll_name)" KeyPath="yes" /> + </Component> + + <!-- Leash DLL configuration --> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_1" Guid="$(var.rcm_leashdll_1_guid)" DiskId="1"> + <Registry Id="reg_leashdll_1" Root="HKLM" Key="Software\MIT\Leash" Name="lifetime" Type="integer" Value="[LEASHLIFETIME]" KeyPath="yes"/> + <Condition>LEASHLIFETIME</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_2" Guid="$(var.rcm_leashdll_2_guid)" DiskId="1"> + <Registry Id="reg_leashdll_2" Root="HKLM" Key="Software\MIT\Leash" Name="renew_till" Type="integer" Value="[LEASHRENEWTILL]" KeyPath="yes"/> + <Condition>LEASHRENEWTILL</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_3" Guid="$(var.rcm_leashdll_3_guid)" DiskId="1"> + <Registry Id="reg_leashdll_3" Root="HKLM" Key="Software\MIT\Leash" Name="renewable" Type="integer" Value="[LEASHRENEWABLE]" KeyPath="yes"/> + <Condition>LEASHRENEWABLE</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_4" Guid="$(var.rcm_leashdll_4_guid)" DiskId="1"> + <Registry Id="reg_leashdll_4" Root="HKLM" Key="Software\MIT\Leash" Name="forwardable" Type="integer" Value="[LEASHFORWARDABLE]" KeyPath="yes"/> + <Condition>LEASHFORWARDABLE</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_5" Guid="$(var.rcm_leashdll_5_guid)" DiskId="1"> + <Registry Id="reg_leashdll_5" Root="HKLM" Key="Software\MIT\Leash" Name="noaddresses" Type="integer" Value="[LEASHNOADDRESSES]" KeyPath="yes"/> + <Condition>LEASHNOADDRESSES</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_6" Guid="$(var.rcm_leashdll_6_guid)" DiskId="1"> + <Registry Id="reg_leashdll_6" Root="HKLM" Key="Software\MIT\Leash" Name="proxiable" Type="integer" Value="[LEASHPROXIABLE]" KeyPath="yes"/> + <Condition>LEASHPROXIABLE</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_7" Guid="$(var.rcm_leashdll_7_guid)" DiskId="1"> + <Registry Id="reg_leashdll_7" Root="HKLM" Key="Software\MIT\Leash" Name="publicip" Type="integer" Value="[LEASHPUBLICIP]" KeyPath="yes"/> + <Condition>LEASHPUBLICIP</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_8" Guid="$(var.rcm_leashdll_8_guid)" DiskId="1"> + <Registry Id="reg_leashdll_8" Root="HKLM" Key="Software\MIT\Leash" Name="usekrb4" Type="integer" Value="[LEASHUSEKRB4]" KeyPath="yes"/> + <Condition>LEASHUSEKRB4</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_9" Guid="$(var.rcm_leashdll_9_guid)" DiskId="1"> + <Registry Id="reg_leashdll_9" Root="HKLM" Key="Software\MIT\Leash" Name="hide_kinit_options" Type="integer" Value="[LEASHHIDEKINITOPTIONS]" KeyPath="yes"/> + <Condition>LEASHHIDEKINITOPTIONS</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_10" Guid="$(var.rcm_leashdll_10_guid)" DiskId="1"> + <Registry Id="reg_leashdll_10" Root="HKLM" Key="Software\MIT\Leash" Name="life_min" Type="integer" Value="[LEASHLIFEMIN]" KeyPath="yes"/> + <Condition>LEASHLIFEMIN</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_11" Guid="$(var.rcm_leashdll_11_guid)" DiskId="1"> + <Registry Id="reg_leashdll_11" Root="HKLM" Key="Software\MIT\Leash" Name="life_max" Type="integer" Value="[LEASHLIFEMAX]" KeyPath="yes"/> + <Condition>LEASHLIFEMAX</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_12" Guid="$(var.rcm_leashdll_12_guid)" DiskId="1"> + <Registry Id="reg_leashdll_12" Root="HKLM" Key="Software\MIT\Leash" Name="renew_min" Type="integer" Value="[LEASHRENEWMIN]" KeyPath="yes"/> + <Condition>LEASHRENEWMIN</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_13" Guid="$(var.rcm_leashdll_13_guid)" DiskId="1"> + <Registry Id="reg_leashdll_13" Root="HKLM" Key="Software\MIT\Leash" Name="renew_max" Type="integer" Value="[LEASHRENEWMAX]" KeyPath="yes"/> + <Condition>LEASHRENEWMAX</Condition> + </Component> + <!-- + <Component Win64="$(var.Win64)" Id="rcm_leashdll_14" Guid="$(var.rcm_leashdll_14_guid)" DiskId="1"> + <Registry Id="reg_leashdll_14" Root="HKLM" Key="Software\MIT\Leash32\Settings" Action="createKey" /> + </Component> + --> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_15" Guid="$(var.rcm_leashdll_15_guid)" DiskId="1"> + <Registry Id="reg_leashdll_15" Root="HKLM" Key="Software\MIT\Leash32\Settings" Name="uppercaserealm" Type="integer" Value="[LEASHUPPERCASEREALM]" KeyPath="yes"/> + <Condition>LEASHUPPERCASEREALM</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_16" Guid="$(var.rcm_leashdll_16_guid)" DiskId="1"> + <Registry Id="reg_leashdll_16" Root="HKLM" Key="Software\MIT\Leash32\Settings" Name="timehost" Type="string" Value="[LEASHTIMEHOST]" KeyPath="yes"/> + <Condition>LEASHTIMEHOST</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="rcm_leashdll_17" Guid="$(var.rcm_leashdll_17_guid)" DiskId="1"> + <Registry Id="reg_leashdll_17" Root="HKLM" Key="Software\MIT\Leash" Name="preserve_kinit_options" Type="integer" Value="[LEASHPRESERVEKINITOPTIONS]" KeyPath="yes"/> + <Condition>LEASHPRESERVEKINITOPTIONS</Condition> + </Component> + + <Component Win64="$(var.Win64)" Id="cmf_ms2mit_exe" Guid="$(var.cmf_ms2mit_exe_guid)" DiskId="1"> + <File Id="fil_ms2mit_exe" LongName="ms2mit.exe" Name="ms2mit.exe" KeyPath="yes" /> + <Registry Id="reg_ts_ms2mit_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\ms2mit" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_ms2mit_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\ms2mit" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mit2ms_exe" Guid="$(var.cmf_mit2ms_exe_guid)" DiskId="1"> + <File Id="fil_mit2ms_exe" LongName="mit2ms.exe" Name="mit2ms.exe" KeyPath="yes" /> + <Registry Id="reg_ts_mit2ms_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\mit2ms" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_mit2ms_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\mit2ms" Name="Flags" Type="integer" Value="1032" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_wshelp32_dll" Guid="$(var.cmf_wshelp32_dll_guid)" DiskId="1"> + <File Id="fil_wshelp32_dll" LongName="$(var.cmf_wshelp32_dll_name)" Name="$(var.cmf_wshelp32_dll_name)" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_xpprof32_dll" Guid="$(var.cmf_xpprof32_dll_guid)" DiskId="1"> + <File Id="fil_xpprof32_dll" LongName="$(var.cmf_xpprof32_dll_name)" Name="$(var.cmf_xpprof32_dll_name)" KeyPath="yes" /> + </Component> + + <!-- NetIDMgr --> + <Component Win64="$(var.Win64)" Id="cmf_nidmgr32_dll" Guid="$(var.cmf_nidmgr32_dll_guid)" DiskId="1" Transitive="yes"> + <File Id="fil_nidmgr32_dll" LongName="$(var.cmf_nidmgr32_dll_name)" Name="$(var.cmf_nidmgr32_dll_name)" KeyPath="yes" /> + <Condition>VersionNT &gt; 500</Condition> + </Component> + <?if $(var.Platform) = "Intel" ?> + <Component Win64="$(var.Win64)" Id="cmf_nidmgr32_dll_w2k" Guid="$(var.cmf_nidmgr32_dll_w2k_guid)" DiskId="1" Transitive="yes"> + <File Id="fil_nidmgr32_dll_w2k" LongName="$(var.cmf_nidmgr32_dll_name)" Name="$(var.cmf_nidmgr32_dll_name)" KeyPath="yes" src="$(var.BinDir)W2K\nidmgr32.dll" /> + <Condition>VersionNT &lt;= 500</Condition> + </Component> + <?endif?> + <Component Win64="$(var.Win64)" Id="cmf_krb5cred_dll" Guid="$(var.cmf_krb5cred_dll_guid)" DiskId="1"> + <File Id="fil_krb5cred_dll" LongName="$(var.cmf_krb5cred_dll_name)" Name="$(var.cmf_krb5cred_dll_name)" KeyPath="yes" /> + <Registry Id="reg_krb5cred_1" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb5" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_krb5cred_2" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb5" Name="ImagePath" Type="string" Value="[#fil_krb5cred_dll]" /> + <Registry Id="reg_krb5cred_3" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb5" Name="PluginList" Type="string" Value="Krb5Cred,Krb5Ident" /> + <Registry Id="reg_krb5cred_4" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_krb5cred_5" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" Name="Module" Type="string" Value="MITKrb5" /> + <Registry Id="reg_krb5cred_6" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" Name="Description" Type="string" Value="Kerberos v5 Credentials Provider" /> + <Registry Id="reg_krb5cred_7" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" Name="Type" Type="integer" Value="1" /> + <Registry Id="reg_krb5cred_8" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred" Name="Flags" Type="integer" Value="0" /> + <Registry Id="reg_krb5cred_9" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_krb5cred_a" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" Name="Module" Type="string" Value="MITKrb5" /> + <Registry Id="reg_krb5cred_b" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" Name="Description" Type="string" Value="Kerberos v5 Identity Provider" /> + <Registry Id="reg_krb5cred_c" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" Name="Dependencies" Type="string" Value="Krb5Cred" /> + <Registry Id="reg_krb5cred_d" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" Name="Type" Type="integer" Value="2" /> + <Registry Id="reg_krb5cred_e" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Ident" Name="Flags" Type="integer" Value="0" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_krb5cred_en_us_dll" Guid="$(var.cmf_krb5cred_en_us_dll_guid)" DiskId="1"> + <File Id="fil_krb5cred_en_us_dll" LongName="$(var.cmf_krb5cred_en_us_dll_name)" Name="krb5cenu.dll" KeyPath="yes" /> + </Component> + <?if $(var.Platform) = "Intel" ?> + <Component Win64="$(var.Win64)" Id="cmf_krb4cred_dll" Guid="$(var.cmf_krb4cred_dll_guid)" DiskId="1"> + <File Id="fil_krb4cred_dll" LongName="$(var.cmf_krb4cred_dll_name)" Name="$(var.cmf_krb4cred_dll_name)" KeyPath="yes" /> + <Registry Id="reg_krb4cred_1" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb4" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_krb4cred_2" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb4" Name="ImagePath" Type="string" Value="[#fil_krb4cred_dll]" /> + <Registry Id="reg_krb4cred_3" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Modules\MITKrb4" Name="PluginList" Type="string" Value="Krb4Cred" /> + <Registry Id="reg_krb4cred_4" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_krb4cred_5" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" Name="Module" Type="string" Value="MITKrb4" /> + <Registry Id="reg_krb4cred_6" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" Name="Description" Type="string" Value="Kerberos v4 Credentials Provider" /> + <Registry Id="reg_krb4cred_7" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" Name="Dependencies" Type="string" Value="Krb5Cred" /> + <Registry Id="reg_krb4cred_8" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" Name="Type" Type="integer" Value="1" /> + <Registry Id="reg_krb4cred_9" Root="HKLM" Key="Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred" Name="Flags" Type="integer" Value="0" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_krb4cred_en_us_dll" Guid="$(var.cmf_krb4cred_en_us_dll_guid)" DiskId="1"> + <File Id="fil_krb4cred_en_us_dll" LongName="$(var.cmf_krb4cred_en_us_dll_name)" Name="krb4cenu.dll" KeyPath="yes" /> + </Component> + <?endif?> + <Component Win64="$(var.Win64)" Id="cmf_netidmgr_exe" Guid="$(var.cmf_netidmgr_exe_guid)" DiskId="1" Transitive="yes"> + <File Id="fil_netidmgr_exe" LongName="netidmgr.exe" Name="netidmgr.exe" KeyPath="yes" /> + <File Id="fil_netidmgr_chm" LongName="netidmgr.chm" Name="netidmgr.chm" /> + <Registry Id="reg_ts_netidmgr_0" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\netidmgr" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_netidmgr_1" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\netidmgr" Name="Flags" Type="integer" Value="1032" /> + <Shortcut Id="sc_netidmgr_exe" Advertise="no" Directory="dirShortcut" LongName="Network Identity Manager.lnk" Name="netidmgr.lnk" Target="[dirbin]netidmgr.exe" Show="minimized" WorkingDirectory="dirbin"/> + <Shortcut Id="sc_netidmgr_chm" Advertise="no" Directory="dirShortcut" LongName="Network Identity Manager Documentation.lnk" Name="netidchm.lnk" Target="[dirbin]netidmgr.chm" WorkingDirectory="dirbin"/> + <Condition>VersionNT &gt; 500</Condition> + </Component> + <?if $(var.Platform) = "Intel" ?> + <Component Win64="$(var.Win64)" Id="cmf_netidmgr_exe_w2k" Guid="$(var.cmf_netidmgr_exe_w2k_guid)" DiskId="1" Transitive="yes"> + <File Id="fil_netidmgr_exe_w2k" LongName="netidmgr.exe" Name="netidmgr.exe" KeyPath="yes" src="$(var.BinDir)W2K\netidmgr.exe"/> + <File Id="fil_netidmgr_chm_w2k" LongName="netidmgr.chm" Name="netidmgr.chm" /> + <Registry Id="reg_ts_netidmgr_0_w2k" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\netidmgr" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_ts_netidmgr_1_w2k" Root="HKLM" Key="Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\netidmgr" Name="Flags" Type="integer" Value="1032" /> + <Shortcut Id="sc_netidmgr_exe_w2k" Advertise="no" Directory="dirShortcut" LongName="Network Identity Manager.lnk" Name="netidmgr.lnk" Target="[dirbin]netidmgr.exe" Show="minimized" WorkingDirectory="dirbin"/> + <Shortcut Id="sc_netidmgr_chm_w2k" Advertise="no" Directory="dirShortcut" LongName="Network Identity Manager Documentation.lnk" Name="netidchm.lnk" Target="[dirbin]netidmgr.chm" WorkingDirectory="dirbin"/> + <Condition>VersionNT &lt;= 500</Condition> + </Component> + <?endif?> + <Component Win64="$(var.Win64)" Id="csc_NetIDMgrStartup" Guid="$(var.csc_NetIDMgrStartup_guid)" DiskId="1"> + <Registry Id="reg_sc_nidmgr_marker" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="NetIDMgrAutoStart" Type="integer" Value="1" KeyPath="yes" /> + <Shortcut Id="sc_netidmgr_exe_startup" Advertise="no" Directory="StartupFolder" LongName="Network Identity Manager.lnk" Name="netidmgr.lnk" Target="[dirbin]netidmgr.exe" Show="minimized" /> + <Condition>USENETIDMGR</Condition> + </Component> + <!-- /NetIDMgr --> + + <!-- Debug symbols --> + <?ifdef DebugSyms?> + <Component Win64="$(var.Win64)" Id="cmf_bin_debug" Guid="$(var.cmf_bin_debug_guid)" DiskId="1"> + <?if $(var.Platform) = "Intel" ?> + <File Id="fil_k524init_pdb" LongName="k524init.pdb" Name="k524init.pdb" /> + <File Id="fil_krb524_pdb" LongName="krb524.pdb" Name="krb524.pdb" /> + <File Id="fil_kclnt32_pdb" LongName="kclnt32.pdb" Name="kclnt32.pdb" /> + <File Id="fil_leash32_pdb" LongName="leash32.pdb" Name="leash32.pdb" /> + + <File Id="fil_comerr32_pdb" LongName="comerr32.pdb" Name="comerr32.pdb" /> + <File Id="fil_gssapi32_pdb" LongName="gssapi32.pdb" Name="gssapi32.pdb" /> + <File Id="fil_krb5_32_pdb" LongName="krb5_32.pdb" Name="krb5_32.pdb" KeyPath="yes" /> + <File Id="fil_k5sprt32_pdb" LongName="k5sprt32.pdb" Name="k5sprt32.pdb" /> + <File Id="fil_krbcc32_pdb" LongName="krbcc32.pdb" Name="krbcc32.pdb" /> + <File Id="fil_krbcc32s_pdb" LongName="krbcc32s.pdb" Name="krbcc32s.pdb" /> + <File Id="fil_krbv4w32_pdb" LongName="krbv4w32.pdb" Name="krbv4w32.pdb" /> + <File Id="fil_leashw32_pdb" LongName="leashw32.pdb" Name="leashw32.pdb" /> + <File Id="fil_wshelp32_pdb" LongName="wshelp32.pdb" Name="wshelp32.pdb" /> + <File Id="fil_xpprof32_pdb" LongName="xpprof32.pdb" Name="xpprof32.pdb" /> + <File Id="fil_krb4cred_pdb" LongName="krb4cred.pdb" Name="krb4cred.pdb" /> + <File Id="fil_krb5cred_pdb" LongName="krb5cred.pdb" Name="krb5cred.pdb" /> + <File Id="fil_nidmgr32_pdb" LongName="nidmgr32.pdb" Name="nidmgr32.pdb" /> + <?else?> + <File Id="fil_comerr64_pdb" LongName="comerr64.pdb" Name="comerr64.pdb" /> + <File Id="fil_gssapi64_pdb" LongName="gssapi64.pdb" Name="gssapi64.pdb" /> + <File Id="fil_krb5_64_pdb" LongName="krb5_64.pdb" Name="krb5_64.pdb" KeyPath="yes" /> + <File Id="fil_k5sprt64_pdb" LongName="k5sprt64.pdb" Name="k5sprt64.pdb" /> + <File Id="fil_krbcc64_pdb" LongName="krbcc64.pdb" Name="krbcc64.pdb" /> + <File Id="fil_krbcc64s_pdb" LongName="krbcc64s.pdb" Name="krbcc64s.pdb" /> + <File Id="fil_leashw64_pdb" LongName="leashw64.pdb" Name="leashw64.pdb" /> + <File Id="fil_wshelp64_pdb" LongName="wshelp64.pdb" Name="wshelp64.pdb" /> + <File Id="fil_xpprof64_pdb" LongName="xpprof64.pdb" Name="xpprof64.pdb" /> + <File Id="fil_krb5cred_pdb" LongName="krb5cred.pdb" Name="krb5cred.pdb" /> + <File Id="fil_nidmgr64_pdb" LongName="nidmgr64.pdb" Name="nidmgr64.pdb" /> + <?endif?> + <File Id="fil_gss_pdb" LongName="gss.pdb" Name="gss.pdb" /> + <File Id="fil_gss_client_pdb" LongName="gss-client.pdb" Name="gss-clnt.pdb" /> + <File Id="fil_gss_server_pdb" LongName="gss-server.pdb" Name="gss-srvr.pdb" /> + <File Id="fil_kdestroy_pdb" LongName="kdestroy.pdb" Name="kdestroy.pdb" /> + <File Id="fil_kcpytkt_pdb" LongName="kcpytkt.pdb" Name="kcpytkt.pdb" /> + <File Id="fil_kdeltkt_pdb" LongName="kdeltkt.pdb" Name="kdeltkt.pdb" /> + <File Id="fil_kinit_pdb" LongName="kinit.pdb" Name="kinit.pdb" /> + <File Id="fil_klist_pdb" LongName="klist.pdb" Name="klist.pdb" /> + <File Id="fil_kpasswd_pdb" LongName="kpasswd.pdb" Name="kpasswd.pdb" /> + <File Id="fil_kvno_pdb" LongName="kvno.pdb" Name="kvno.pdb" /> + <File Id="fil_ms2mit_pdb" LongName="ms2mit.pdb" Name="ms2mit.pdb" /> + <File Id="fil_mit2ms_pdb" LongName="mit2ms.pdb" Name="mit2ms.pdb" /> + <File Id="fil_netidmgr_pdb" LongName="netidmgr.pdb" Name="netidmgr.pdb" /> + </Component> + <?endif?> + + <!-- Runtime (for compilers previous to VS8) --> + <?ifndef Debug?> + <?ifdef CL1200?> + <Component Win64="$(var.Win64)" Id="cmf_mfc42_dll" Guid="BE2D0D08-E26E-4906-BEEA-1C550BA9B405" DiskId="1"> + <File Id="fil_mfc42_dll" LongName="mfc42.dll" Name="mfc42.dll" src="$(var.SystemDir)mfc42.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcp60_dll" Guid="7DBB5E61-AA59-4FD8-87CA-7F139D355050" DiskId="1"> + <File Id="fil_msvcp60_dll" LongName="msvcp60.dll" Name="msvcp60.dll" src="$(var.SystemDir)msvcp60.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcrt_dll" Guid="07B1612B-F52B-4A22-BC20-948BB7D50916" DiskId="1"> + <File Id="fil_msvcrt_dll" LongName="msvcrt.dll" Name="msvcrt.dll" src="$(var.SystemDir)msvcrt.dll" KeyPath="yes" /> + </Component> + <?endif?> + <?ifdef CL1300?> + <Component Win64="$(var.Win64)" Id="cmf_mfc70_dll" Guid="E064D66F-45A5-46FA-A0C0-EE68B5DCA248" DiskId="1"> + <File Id="fil_mfc70_dll" LongName="mfc70.dll" Name="mfc70.dll" src="$(var.SystemDir)mfc70.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcr70_dll" Guid="3489059D-B8C5-4F9A-9DF9-CC8F19B97898" DiskId="1"> + <File Id="fil_msvcr70_dll" LongName="msvcr70.dll" Name="msvcr70.dll" src="$(var.SystemDir)msvcr70.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcp70_dll" Guid="E3E6DC28-A229-45D7-804B-BC5A2CAB86B6" DiskId="1"> + <File Id="fil_msvcp70_dll" LongName="msvcp70.dll" Name="msvcp70.dll" src="$(var.SystemDir)msvcp70.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70chs_dll" Guid="CAFD61A5-8A13-4A7C-AA15-6FEED7D43A3A" DiskId="1"> + <File Id="fil_mfc70chs_dll" LongName="mfc70chs.dll" Name="mfc70chs.dll" src="$(var.SystemDir)mfc70chs.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70cht_dll" Guid="A3F60016-825A-4096-A45F-98B4972FF1CA" DiskId="1"> + <File Id="fil_mfc70cht_dll" LongName="mfc70cht.dll" Name="mfc70cht.dll" src="$(var.SystemDir)mfc70cht.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70deu_dll" Guid="D146EE00-8880-4E39-A131-784B947883DB" DiskId="1"> + <File Id="fil_mfc70deu_dll" LongName="mfc70deu.dll" Name="mfc70deu.dll" src="$(var.SystemDir)mfc70deu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70enu_dll" Guid="11E2059D-62E6-40DF-87C1-B03E425048CE" DiskId="1"> + <File Id="fil_mfc70enu_dll" LongName="mfc70enu.dll" Name="mfc70enu.dll" src="$(var.SystemDir)mfc70enu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70esp_dll" Guid="3D1AAC2A-0FB1-4EF7-8406-1BF771CEB4BB" DiskId="1"> + <File Id="fil_mfc70esp_dll" LongName="mfc70esp.dll" Name="mfc70esp.dll" src="$(var.SystemDir)mfc70esp.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70fra_dll" Guid="36A2B8B3-E6C6-4725-96B8-82905D2ADE4E" DiskId="1"> + <File Id="fil_mfc70fra_dll" LongName="mfc70fra.dll" Name="mfc70fra.dll" src="$(var.SystemDir)mfc70fra.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70ita_dll" Guid="4EE49FC8-ED41-48F4-90A9-1FC06FE6237D" DiskId="1"> + <File Id="fil_mfc70ita_dll" LongName="mfc70ita.dll" Name="mfc70ita.dll" src="$(var.SystemDir)mfc70ita.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70jpn_dll" Guid="A6ADFFF1-C48B-446C-9B7D-6137F00EC0E4" DiskId="1"> + <File Id="fil_mfc70jpn_dll" LongName="mfc70jpn.dll" Name="mfc70jpn.dll" src="$(var.SystemDir)mfc70jpn.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70kor_dll" Guid="720F98E2-5525-41CA-8734-98B0A5756708" DiskId="1"> + <File Id="fil_mfc70kor_dll" LongName="mfc70kor.dll" Name="mfc70kor.dll" src="$(var.SystemDir)mfc70kor.dll" KeyPath="yes" /> + </Component> + <?endif?> + <?ifdef CL1310?> + <Component Win64="$(var.Win64)" Id="cmf_mfc71_dll" Guid="6A4854A8-35AE-42CB-9671-9F6F096BE20C" DiskId="1"> + <File Id="fil_mfc71_dll" LongName="mfc71.dll" Name="mfc71.dll" src="$(var.SystemDir)mfc71.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcr71_dll" Guid="C6952DEE-E62A-4635-9CE8-405F1E459FB2" DiskId="1"> + <File Id="fil_msvcr71_dll" LongName="msvcr71.dll" Name="msvcr71.dll" src="$(var.SystemDir)msvcr71.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcp71_dll" Guid="CA7D0EDE-0B81-4709-86E9-31DC8543918F" DiskId="1"> + <File Id="fil_msvcp71_dll" LongName="msvcp71.dll" Name="msvcp71.dll" src="$(var.SystemDir)msvcp71.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71chs_dll" Guid="693F64CF-1AE5-4756-94CC-095ED48C217F" DiskId="1"> + <File Id="fil_mfc71chs_dll" LongName="mfc71chs.dll" Name="mfc71chs.dll" src="$(var.SystemDir)mfc71chs.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71cht_dll" Guid="A5552AAE-048F-41AB-AC2D-6C96411D812D" DiskId="1"> + <File Id="fil_mfc71cht_dll" LongName="mfc71cht.dll" Name="mfc71cht.dll" src="$(var.SystemDir)mfc71cht.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71deu_dll" Guid="E8AE39B8-1B23-4DC9-944F-CA823F53CFF3" DiskId="1"> + <File Id="fil_mfc71deu_dll" LongName="mfc71deu.dll" Name="mfc71deu.dll" src="$(var.SystemDir)mfc71deu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71enu_dll" Guid="1FF5B6B6-4015-40F1-AEFF-004DBCFDB5E7" DiskId="1"> + <File Id="fil_mfc71enu_dll" LongName="mfc71enu.dll" Name="mfc71enu.dll" src="$(var.SystemDir)mfc71enu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71esp_dll" Guid="028AC2DA-B4F9-4A9E-A728-1100B3C7E259" DiskId="1"> + <File Id="fil_mfc71esp_dll" LongName="mfc71esp.dll" Name="mfc71esp.dll" src="$(var.SystemDir)mfc71esp.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71fra_dll" Guid="7D6C3457-F08C-426C-BEE2-8D9F214223C5" DiskId="1"> + <File Id="fil_mfc71fra_dll" LongName="mfc71fra.dll" Name="mfc71fra.dll" src="$(var.SystemDir)mfc71fra.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71ita_dll" Guid="5CE98F88-CD33-4887-9634-B6263B6DB3CB" DiskId="1"> + <File Id="fil_mfc71ita_dll" LongName="mfc71ita.dll" Name="mfc71ita.dll" src="$(var.SystemDir)mfc71ita.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71jpn_dll" Guid="6DE66BB3-5DD2-4D87-89E4-D73FF405932C" DiskId="1"> + <File Id="fil_mfc71jpn_dll" LongName="mfc71jpn.dll" Name="mfc71jpn.dll" src="$(var.SystemDir)mfc71jpn.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71kor_dll" Guid="B7290849-638E-4C39-9E56-0D73CF564D69" DiskId="1"> + <File Id="fil_mfc71kor_dll" LongName="mfc71kor.dll" Name="mfc71kor.dll" src="$(var.SystemDir)mfc71kor.dll" KeyPath="yes" /> + </Component> + <?endif?> + <?else?> <!-- Debug --> + <?ifdef CL1200?> + <Component Win64="$(var.Win64)" Id="cmf_mfc42d_dll" Guid="B7360C15-61FA-409F-8F0A-87B96FB30BBD" DiskId="1"> + <File Id="fil_mfc42d_dll" LongName="mfc42d.dll" Name="mfc42d.dll" src="$(var.SystemDir)mfc42d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcp60d_dll" Guid="BFF28D63-B60A-48B6-A403-A7DE00BDB37E" DiskId="1"> + <File Id="fil_msvcp60d_dll" LongName="msvcp60d.dll" Name="msvcp60d.dll" src="$(var.SystemDir)msvcp60d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcrtd_dll" Guid="69069738-3202-43C3-92A3-4139816B6527" DiskId="1"> + <File Id="fil_msvcrtd_dll" LongName="msvcrtd.dll" Name="msvcrtd.dll" src="$(var.SystemDir)msvcrtd.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_runtime_debug1200" Guid="3FAD9513-AB33-4eed-9359-E96F8D5ABD2A" DiskId="1"> + <File Id="fil_mfc42d_pdb" LongName="mfc42d.pdb" Name="mfc42d.pdb" src="$(var.SystemDir)mfc42d.pdb" /> + <File Id="fil_msvcp60d_pdb" LongName="msvcp60d.pdb" Name="msvcp60d.pdb" src="$(var.SystemDir)msvcp60d.pdb" /> + <File Id="fil_msvcrtd_pdb" LongName="msvcrtd.pdb" Name="msvcrtd.pdb" src="$(var.SystemDir)msvcrtd.pdb" KeyPath="yes" /> + </Component> + <?endif?> + <?ifdef CL1300?> + <Component Win64="$(var.Win64)" Id="cmf_mfc70d_dll" Guid="40C7120A-9B28-4DD1-86D0-9F66056A2463" DiskId="1"> + <File Id="fil_mfc70d_dll" LongName="mfc70d.dll" Name="mfc70d.dll" src="$(var.SystemDir)mfc70d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcr70d_dll" Guid="D0A7B06E-6F65-4559-A99A-63C4C837BE0E" DiskId="1"> + <File Id="fil_msvcr70d_dll" LongName="msvcr70d.dll" Name="msvcr70d.dll" src="$(var.SystemDir)msvcr70d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcp70d_dll" Guid="DC82F644-8705-4C89-BE63-4CD6680BF580" DiskId="1"> + <File Id="fil_msvcp70d_dll" LongName="msvcp70d.dll" Name="msvcp70d.dll" src="$(var.SystemDir)msvcp70d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70chs_dll" Guid="CAFD61A5-8A13-4A7C-AA15-6FEED7D43A3A" DiskId="1"> + <File Id="fil_mfc70chs_dll" LongName="mfc70chs.dll" Name="mfc70chs.dll" src="$(var.SystemDir)mfc70chs.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70cht_dll" Guid="A3F60016-825A-4096-A45F-98B4972FF1CA" DiskId="1"> + <File Id="fil_mfc70cht_dll" LongName="mfc70cht.dll" Name="mfc70cht.dll" src="$(var.SystemDir)mfc70cht.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70deu_dll" Guid="D146EE00-8880-4E39-A131-784B947883DB" DiskId="1"> + <File Id="fil_mfc70deu_dll" LongName="mfc70deu.dll" Name="mfc70deu.dll" src="$(var.SystemDir)mfc70deu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70enu_dll" Guid="11E2059D-62E6-40DF-87C1-B03E425048CE" DiskId="1"> + <File Id="fil_mfc70enu_dll" LongName="mfc70enu.dll" Name="mfc70enu.dll" src="$(var.SystemDir)mfc70enu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70esp_dll" Guid="3D1AAC2A-0FB1-4EF7-8406-1BF771CEB4BB" DiskId="1"> + <File Id="fil_mfc70esp_dll" LongName="mfc70esp.dll" Name="mfc70esp.dll" src="$(var.SystemDir)mfc70esp.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70fra_dll" Guid="36A2B8B3-E6C6-4725-96B8-82905D2ADE4E" DiskId="1"> + <File Id="fil_mfc70fra_dll" LongName="mfc70fra.dll" Name="mfc70fra.dll" src="$(var.SystemDir)mfc70fra.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70ita_dll" Guid="4EE49FC8-ED41-48F4-90A9-1FC06FE6237D" DiskId="1"> + <File Id="fil_mfc70ita_dll" LongName="mfc70ita.dll" Name="mfc70ita.dll" src="$(var.SystemDir)mfc70ita.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70jpn_dll" Guid="A6ADFFF1-C48B-446C-9B7D-6137F00EC0E4" DiskId="1"> + <File Id="fil_mfc70jpn_dll" LongName="mfc70jpn.dll" Name="mfc70jpn.dll" src="$(var.SystemDir)mfc70jpn.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc70kor_dll" Guid="720F98E2-5525-41CA-8734-98B0A5756708" DiskId="1"> + <File Id="fil_mfc70kor_dll" LongName="mfc70kor.dll" Name="mfc70kor.dll" src="$(var.SystemDir)mfc70kor.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_runtime_debug1300" Guid="157D7DE8-6AFE-44b3-A317-840667C76D0D" DiskId="1"> + <File Id="fil_mfc70d_pdb" LongName="mfc70d.pdb" Name="mfc70d.pdb" src="$(var.SystemDir)mfc70d.pdb" /> + <File Id="fil_msvcr70d_pdb" LongName="msvcr70d.pdb" Name="msvcr70d.pdb" src="$(var.SystemDir)msvcr70d.pdb" KeyPath="yes" /> + <File Id="fil_msvcp70d_pdb" LongName="msvcp70d.pdb" Name="msvcp70d.pdb" src="$(var.SystemDir)msvcp70d.pdb" /> + </Component> + <?endif?> + <?ifdef CL1310?> + <Component Win64="$(var.Win64)" Id="cmf_mfc71d_dll" Guid="0E0A47A3-892C-4526-8591-C719E1A184F2" DiskId="1"> + <File Id="fil_mfc71d_dll" LongName="mfc71d.dll" Name="mfc71d.dll" src="$(var.SystemDir)mfc71d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcr71d_dll" Guid="CB2A282D-CF73-4DA8-929D-8035776F4FB8" DiskId="1"> + <File Id="fil_msvcr71d_dll" LongName="msvcr71d.dll" Name="msvcr71d.dll" src="$(var.SystemDir)msvcr71d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_msvcp71d_dll" Guid="7D6003B6-B3A1-417A-BE16-5DDD52023456" DiskId="1"> + <File Id="fil_msvcp71d_dll" LongName="msvcp71d.dll" Name="msvcp71d.dll" src="$(var.SystemDir)msvcp71d.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71chs_dll" Guid="693F64CF-1AE5-4756-94CC-095ED48C217F" DiskId="1"> + <File Id="fil_mfc71chs_dll" LongName="mfc71chs.dll" Name="mfc71chs.dll" src="$(var.SystemDir)mfc71chs.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71cht_dll" Guid="A5552AAE-048F-41AB-AC2D-6C96411D812D" DiskId="1"> + <File Id="fil_mfc71cht_dll" LongName="mfc71cht.dll" Name="mfc71cht.dll" src="$(var.SystemDir)mfc71cht.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71deu_dll" Guid="E8AE39B8-1B23-4DC9-944F-CA823F53CFF3" DiskId="1"> + <File Id="fil_mfc71deu_dll" LongName="mfc71deu.dll" Name="mfc71deu.dll" src="$(var.SystemDir)mfc71deu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71enu_dll" Guid="1FF5B6B6-4015-40F1-AEFF-004DBCFDB5E7" DiskId="1"> + <File Id="fil_mfc71enu_dll" LongName="mfc71enu.dll" Name="mfc71enu.dll" src="$(var.SystemDir)mfc71enu.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71esp_dll" Guid="028AC2DA-B4F9-4A9E-A728-1100B3C7E259" DiskId="1"> + <File Id="fil_mfc71esp_dll" LongName="mfc71esp.dll" Name="mfc71esp.dll" src="$(var.SystemDir)mfc71esp.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71fra_dll" Guid="7D6C3457-F08C-426C-BEE2-8D9F214223C5" DiskId="1"> + <File Id="fil_mfc71fra_dll" LongName="mfc71fra.dll" Name="mfc71fra.dll" src="$(var.SystemDir)mfc71fra.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71ita_dll" Guid="5CE98F88-CD33-4887-9634-B6263B6DB3CB" DiskId="1"> + <File Id="fil_mfc71ita_dll" LongName="mfc71ita.dll" Name="mfc71ita.dll" src="$(var.SystemDir)mfc71ita.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71jpn_dll" Guid="6DE66BB3-5DD2-4D87-89E4-D73FF405932C" DiskId="1"> + <File Id="fil_mfc71jpn_dll" LongName="mfc71jpn.dll" Name="mfc71jpn.dll" src="$(var.SystemDir)mfc71jpn.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_mfc71kor_dll" Guid="B7290849-638E-4C39-9E56-0D73CF564D69" DiskId="1"> + <File Id="fil_mfc71kor_dll" LongName="mfc71kor.dll" Name="mfc71kor.dll" src="$(var.SystemDir)mfc71kor.dll" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_runtime_debug1310" Guid="0125814E-9EED-4d57-A4E6-3E685CE5AB5C" DiskId="1"> + <File Id="fil_mfc71d_pdb" LongName="mfc71d.pdb" Name="mfc71d.pdb" src="$(var.SystemDir)mfc71d.pdb" /> + <File Id="fil_msvcr71d_pdb" LongName="msvcr71d.pdb" Name="msvcr71d.pdb" src="$(var.SystemDir)msvcr71d.pdb" KeyPath="yes" /> + <File Id="fil_msvcp71d_pdb" LongName="msvcp71d.pdb" Name="msvcp71d.pdb" src="$(var.SystemDir)msvcp71d.pdb" /> + </Component> + <?endif?> + <?endif?> + + <Component Win64="$(var.Win64)" Id="cmf_psapi_dll" Guid="877F4DD5-8AE0-451C-8F4D-C27F6F30D221" DiskId="1"> + <File Id="fil_psapi_dll" LongName="psapi.dll" Name="psapi.dll" src="$(var.SystemDir)psapi.dll" KeyPath="yes" /> + </Component> + + </Directory> <!-- /bin --> + + <Directory Id="dirinc" Name="inc" src="$(var.IncDir)"> + <?if $(var.Platform) = "Intel"?> + <Directory Id="dirinc_kclient" Name="kclient" src="$(var.IncDir)kclient\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_kclient" Guid="96215203-7FF5-4576-AAC5-F5035B64CC37" DiskId="1"> + <File Id="fil_kclient_h" LongName="kclient.h" Name="kclient.h" KeyPath="yes" /> + <File Id="fil_kcmacerr_h" LongName="kcmacerr.h" Name="kcmacerr.h" /> + </Component> + </Directory> + <Directory Id="dirinc_krb4" Name="krb4" src="$(var.IncDir)krb4\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_krb4" Guid="5D2E3F2E-87AE-4905-84AC-AC503662D1B0" DiskId="1"> + <File Id="fil_com_err_h" LongName="com_err.h" Name="com_err.h" /> + <File Id="fil_conf_pc_h" LongName="conf-pc.h" Name="conf-pc.h" /> + <File Id="fil_conf_h" LongName="conf.h" Name="conf.h" /> + <File Id="fil_des_h" LongName="des.h" Name="des.h" /> + <File Id="fil_kadm_err_h" LongName="kadm_err.h" Name="kadm_err.h" /> + <File Id="fil_krb_h" LongName="krb.h" Name="krb.h" KeyPath="yes" /> + <File Id="fil_krberr_h" LongName="krberr.h" Name="krberr.h" /> + <File Id="fil_mit_copy_h" LongName="mit_copy.h" Name="mit_copy.h" /> + <File Id="fil_osconf_h" LongName="osconf.h" Name="osconf.h" /> + </Component> + </Directory> + <?endif?> + <Directory Id="dirinc_krb5" Name="krb5" src="$(var.IncDir)krb5\"> + <Directory Id="dirinc_krb5_gssapi" Name="gssapi" src="$(var.IncDir)\krb5\gssapi\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_krb5_gssapi" Guid="BD3C190B-1EBB-4d14-81DD-B2000DC4EAC7" DiskId="1"> + <File Id="fil_gssapi_h" LongName="gssapi.h" Name="gssapi.h" KeyPath="yes" /> + <File Id="fil_gssapi_generic_h" LongName="gssapi_generic.h" Name="GSSAPI_G.H" /> + <File Id="fil_gssapi_krb5_h" LongName="gssapi_krb5.h" Name="GSSAPI_K.H" /> + </Component> + </Directory> + <Directory Id="dirinc_krb5_KerberosIV" LongName="KerberosIV" Name="krb4" src="$(var.IncDir)\krb5\KerberosIV\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_krb5_KerberosIV" Guid="307B8031-2589-4f92-A303-EF4231328490" DiskId="1"> + <File Id="fil_des_.h" LongName="des.h" Name="des.h" /> + <File Id="fil_kadm_err_.h" LongName="kadm_err.h" Name="kadm_err.h" /> + <File Id="fil_krb_.h" LongName="krb.h" Name="krb.h" KeyPath="yes" /> + <File Id="fil_krb_err_.h" LongName="krb_err.h" Name="krb_err.h" /> + <File Id="fil_mit_copyright_.h" LongName="mit-copyright.h" Name="MIT-COPY.H" /> + </Component> + </Directory> + <Directory Id="dirinc_krb5_krb5" Name="krb5" src="$(var.IncDir)\krb5\krb5\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_krb5_krb5" Guid="D1E4E3D8-EF04-4DD6-B01E-F87876509869" DiskId="1"> + <File Id="fil_krb5_h_inc" LongName="krb5.h" Name="krb5.h" KeyPath="yes" /> + </Component> + </Directory> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_krb5" Guid="7FD8008B-2F46-4613-8A09-989F643258F1" DiskId="1"> + <File Id="fil_com_err_.h" LongName="com_err.h" Name="com_err.h" /> + <File Id="fil_krb5_.h" LongName="krb5.h" Name="krb5.h" KeyPath="yes" /> + <File Id="fil_profile_.h" LongName="profile.h" Name="profile.h" /> + <File Id="fil_win_mac_.h" LongName="win-mac.h" Name="win-mac.h" /> + </Component> + </Directory> + <Directory Id="dirinc_krbcc" Name="krbcc" src="$(var.IncDir)krbcc\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_krbcc" Guid="2CE4B708-7D45-41e4-8A53-BF2D78451A81" DiskId="1"> + <File Id="fil_cacheapi_h" LongName="cacheapi.h" Name="cacheapi.h" KeyPath="yes" /> + </Component> + </Directory> + <Directory Id="dirinc_leash" Name="leash" src="$(var.IncDir)leash\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_leash" Guid="FCF269AB-D9BC-49bd-B9F3-D6EA9697D8D7" DiskId="1"> + <File Id="fil_leasherr_h" LongName="leasherr.h" Name="leasherr.h" /> + <File Id="fil_leashinfo_h" LongName="leashinfo.h" Name="LEASHINF.H" /> + <File Id="fil_leashwin_h" LongName="leashwin.h" Name="leashwin.h" KeyPath="yes" /> + </Component> + </Directory> + <Directory Id="dirinc_loadfuncs" LongName="loadfuncs" Name="loadfunc" src="$(var.IncDir)loadfuncs\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_loadfuncs" Guid="C8E59D05-4502-498b-A107-1DF65C3A27D3" DiskId="1"> + <File Id="fil_loadfuncs_afs_h" LongName="loadfuncs-afs.h" Name="LF-AFS.H" /> + <File Id="fil_loadfuncs_afs36_h" LongName="loadfuncs-afs36.h" Name="LF-AFS36.H" /> + <File Id="fil_loadfuncs_com_err_h" LongName="loadfuncs-com_err.h" Name="LF-COMER.H" /> + <File Id="fil_loadfuncs_krb_h" LongName="loadfuncs-krb.h" Name="LF-KRB.H" /> + <File Id="fil_loadfuncs_krb5_h" LongName="loadfuncs-krb5.h" Name="LF-KRB5.H" /> + <File Id="fil_loadfuncs_krb524_h" LongName="loadfuncs-krb524.h" Name="LF-K524.H" /> + <File Id="fil_loadfuncs_leash_h" LongName="loadfuncs-leash.h" Name="LF-LEASH.H" /> + <File Id="fil_loadfuncs_lsa_h" LongName="loadfuncs-lsa.h" Name="LF-LFA.H" /> + <File Id="fil_loadfuncs_profile_h" LongName="loadfuncs-profile.h" Name="LF-PROF.H" /> + <File Id="fil_loadfuncs_wshelper_h" LongName="loadfuncs-wshelper.h" Name="LF-WSHLP.H" /> + <File Id="fil_loadfuncs_c" LongName="loadfuncs.c" Name="LOADFUNC.C" /> + <File Id="fil_loadfuncs_h" LongName="loadfuncs.h" Name="LOADFUNC.H" KeyPath="yes" /> + </Component> + </Directory> + <Directory Id="dirinc_netidmgr" Name="netidmgr" src="$(var.IncDir)netidmgr\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_netidmgr" Guid="EBD8BA04-574A-4081-A994-BCEC8ACBC878" DiskId="1"> + <File Id="fil_hashtable_h" LongName="hashtable.h" Name="HASHTABL.H" /> + <File Id="fil_kconfig_h" LongName="kconfig.h" Name="kconfig.h" /> + <File Id="fil_kcreddb_h" LongName="kcreddb.h" Name="kcreddb.h" /> + <File Id="fil_khaction_h" LongName="khaction.h" Name="khaction.h" /> + <File Id="fil_khactiondef_h" LongName="khactiondef.h" Name="KHACTDEF.H" /> + <File Id="fil_khalerts_h" LongName="khalerts.h" Name="khalerts.h" /> + <File Id="fil_khconfigui_h" LongName="khconfigui.h" Name="KHCONFUI.H" /> + <File Id="fil_khdefs_h" LongName="khdefs.h" Name="khdefs.h" /> + <File Id="fil_kherr_h" LongName="kherr.h" Name="kherr.h" /> + <File Id="fil_kherror_h" LongName="kherror.h" Name="kherror.h" /> + <File Id="fil_khhtlink_h" LongName="khhtlink.h" Name="khhtlink.h" /> + <File Id="fil_khlist_h" LongName="khlist.h" Name="khlist.h" /> + <File Id="fil_khmsgtypes_h" LongName="khmsgtypes.h" Name="KHMSGTYP.H" /> + <File Id="fil_khnewcred_h" LongName="khnewcred.h" Name="KHNEWCRD.H" /> + <File Id="fil_khprops_h" LongName="khprops.h" Name="khprops.h" /> + <File Id="fil_khremote_h" LongName="khremote.h" Name="khremote.h" /> + <File Id="fil_khrescache_h" LongName="khrescache.h" Name="KHRESCHE.H" /> + <File Id="fil_khtracker_h" LongName="khtracker.h" Name="KHTRACKR.H" /> + <File Id="fil_khuidefs_h" LongName="khuidefs.h" Name="khuidefs.h" KeyPath="yes" /> + <File Id="fil_kmm_h" LongName="kmm.h" Name="kmm.h" /> + <File Id="fil_kmq_h" LongName="kmq.h" Name="kmq.h" /> + <File Id="fil_kplugin_h" LongName="kplugin.h" Name="kplugin.h" /> + <File Id="fil_mstring_h" LongName="mstring.h" Name="mstring.h" /> + <File Id="fil_sync_h" LongName="sync.h" Name="sync.h" /> + <File Id="fil_utils_h" LongName="utils.h" Name="utils.h" /> + <File Id="fil_perfstat_h" LongName="perfstat.h" Name="perfstat.h" /> + <File Id="fil_netidmgr_h" LongName="netidmgr.h" Name="netidmgr.h" /> + <File Id="fil_netidmgr_version_h" LongName="netidmgr_version.h" Name="netidmvr.h" /> + </Component> + </Directory> + <Directory Id="dirinc_wshelper" Name="wshelper" src="$(var.IncDir)wshelper\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_wshelper" Guid="5A4FCD76-6DC6-455c-B465-FD8123252EBD" DiskId="1"> + <File Id="fil_hesiod_h" LongName="hesiod.h" Name="hesiod.h" /> + <File Id="fil_mitwhich_h" LongName="mitwhich.h" Name="mitwhich.h" /> + <File Id="fil_resolv_h" LongName="resolv.h" Name="resolv.h" /> + <File Id="fil_wshelper_h" LongName="wshelper.h" Name="wshelper.h" KeyPath="yes" /> + </Component> + <Directory Id="dirinc_wshelper_arpa" Name="arpa" src="$(var.IncDir)\wshelper\arpa\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinc_wshelper_arpa" Guid="42A19215-91D6-4cd6-8BE8-95105849B862" DiskId="1"> + <File Id="fil_nameser_h" LongName="nameser.h" Name="nameser.h" KeyPath="yes" /> + </Component> + </Directory> + </Directory> + </Directory> + + <Directory Id="dirlib" Name="lib" src="$(var.LibDir)"> + <?if $(var.Platform) = "Intel" ?> + <Directory Id="dirlib_i386" Name="i386" src="$(var.LibDir)"> + <Component Win64="$(var.Win64)" Id="cmp_dirlib_i386" Guid="CFEE3ED4-92D4-49e1-BB78-8BCBC60C3E57" DiskId="1"> + <File Id="fil_comerr32_lib" LongName="comerr32.lib" Name="comerr32.lib" /> + <File Id="fil_delaydlls_32_lib" LongName="delaydlls.lib" Name="DELAYDLL.LIB" /> + <File Id="fil_getopt_32_lib" LongName="getopt.lib" Name="getopt.lib" /> + <File Id="fil_gssapi32_lib" LongName="gssapi32.lib" Name="gssapi32.lib" /> + <File Id="fil_kclnt32_lib" LongName="kclnt32.lib" Name="kclnt32.lib" /> + <File Id="fil_krb524_32_lib" LongName="krb524.lib" Name="krb524.lib" /> + <File Id="fil_krbv4w32_lib" LongName="krbv4w32.lib" Name="krbv4w32.lib" /> + <File Id="fil_krb5_32_lib" LongName="krb5_32.lib" Name="krb5_32.lib" KeyPath="yes" /> + <File Id="fil_krbcc32_lib" LongName="krbcc32.lib" Name="krbcc32.lib" /> + <File Id="fil_leashw32_lib" LongName="leashw32.lib" Name="leashw32.lib" /> + <File Id="fil_loadfuncs_32_lib" LongName="loadfuncs.lib" Name="LOADFUNC.LIB" /> + <File Id="fil_wshelp32_lib" LongName="wshelp32.lib" Name="wshelp32.lib" /> + <File Id="fil_xpprof32_lib" LongName="xpprof32.lib" Name="xpprof32.lib" /> + <File Id="fil_nidmgr32_lib" LongName="nidmgr32.lib" Name="nidmgr32.lib" /> + </Component> + </Directory> + <?endif?> + <?if $(var.Platform) = "x64" ?> + <Directory Id="dirlib_amd64" Name="amd64" src="$(var.LibDir)"> + <Component Win64="$(var.Win64)" Id="cmp_dirlib_amd64" Guid="F9A54201-FFD6-4a45-B021-276D9F6C40A2" DiskId="1"> + <File Id="fil_comerr64_lib" LongName="comerr64.lib" Name="comerr64.lib" /> + <File Id="fil_delaydlls_64_lib" LongName="delaydlls.lib" Name="DELAYDLL.LIB" /> + <File Id="fil_getopt_64_lib" LongName="getopt.lib" Name="getopt.lib" /> + <File Id="fil_gssapi64_lib" LongName="gssapi64.lib" Name="gssapi64.lib" /> + <File Id="fil_krb5_64_lib" LongName="krb5_64.lib" Name="krb5_64.lib" KeyPath="yes" /> + <File Id="fil_krbcc64_lib" LongName="krbcc64.lib" Name="krbcc64.lib" /> + <File Id="fil_leashw64_lib" LongName="leashw64.lib" Name="leashw64.lib" /> + <File Id="fil_loadfuncs_64_lib" LongName="loadfuncs.lib" Name="LOADFUNC.LIB" /> + <File Id="fil_wshelp64_lib" LongName="wshelp64.lib" Name="wshelp64.lib" /> + <File Id="fil_xpprof64_lib" LongName="xpprof64.lib" Name="xpprof64.lib" /> + <File Id="fil_nidmgr64_lib" LongName="nidmgr64.lib" Name="nidmgr64.lib" /> + </Component> + </Directory> + <?endif?> + </Directory> + + <Directory Id="dirinstall" Name="install" src="$(var.InstallDir)"> + <Directory Id="dirinstall_nsis" Name="nsis" src="$(var.InstallDir)nsis\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinstall_nsis" Guid="711C3910-5369-44f3-A023-E09E86A1C749" DiskId="1"> + <File Id="fil_kfw_fixed_nsi" LongName="kfw-fixed.nsi" Name="KFW-FIXD.NSI" KeyPath="yes" /> + <File Id="fil_kfw_ico" LongName="kfw.ico" Name="kfw.ico" /> + <File Id="fil_kfw_nsi" LongName="kfw.nsi" Name="kfw.nsi" /> + <File Id="fil_KfWConfigPage_ini" LongName="KfWConfigPage.ini" Name="KFWCONP.INI" /> + <File Id="fil_KfWConfigPage2_ini" LongName="KfWConfigPage2.ini" Name="KFWCONP2.INI" /> + <File Id="fil_killer_cpp" LongName="killer.cpp" Name="killer.cpp" /> + <File Id="fil_licenses_rtf" LongName="licenses.rtf" Name="licenses.rtf" /> + <File Id="fil_site_local_nsi" LongName="site-local-tagged.nsi" Name="SITE-LCN.NSI" /> + <File Id="fil_nsi_incl" LongName="nsi-includes-tagged.nsi" Name="NSI-INCL.NSI" /> + <File Id="fil_utils_nsi" LongName="utils.nsi" Name="utils.nsi" /> + </Component> + </Directory> + <Directory Id="dirinstall_wix" Name="wix" src="$(var.InstallDir)wix\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinstall_wix" Guid="14DD16AB-6920-4ee1-8B78-623F39DB70BB" DiskId="1"> + <File Id="fil_config_wxi" LongName="config.wxi" Name="config.wxi" /> + <File Id="fil_features_wxi" LongName="features.wxi" Name="features.wxi" /> + <File Id="fil_files_wxi" LongName="files.wxi" Name="files.wxi" /> + <File Id="fil_kfw_wxs" LongName="kfw.wxs" Name="kfw.wxs" KeyPath="yes" /> + <File Id="fil_Makefile_" LongName="Makefile" Name="Makefile" /> + <File Id="fil_property_wxi" LongName="property.wxi" Name="property.wxi" /> + <File Id="fil_site_local_wxi" LongName="site-local-tagged.wxi" Name="SITE-LCL.WXI" /> + </Component> + <Directory Id="dirinstall_wix_lang" Name="lang" src="$(var.InstallDir)wix\lang\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinstall_wix_lang" Guid="70741A69-1103-4B54-B146-2E14C271945D" DiskId="1"> + <File Id="fil_config_1033_wxi" LongName="config_1033.wxi" Name="CFG-1033.WXI" KeyPath="yes" /> + <File Id="fil_strings_1033_wxl" LongName="strings_1033.wxl" Name="STR-1033.WXL" /> + <File Id="fil_ui_1033_wxi" LongName="ui_1033.wxi" Name="ui_1033.wxi" /> + </Component> + </Directory> + <Directory Id="dirinstall_wix_Binary" Name="Binary" src="$(var.InstallDir)wix\Binary\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinstall_wix_Binary" Guid="5F021D71-A398-41FD-8F9C-9C0665C18660" DiskId="1"> + <File Id="fil_bannrbmp_bmp" LongName="bannrbmp.bmp" Name="bannrbmp.bmp" /> + <File Id="fil_completi_ico" LongName="completi.ico" Name="completi.ico" /> + <File Id="fil_custicon_ico" LongName="custicon.ico" Name="custicon.ico" /> + <File Id="fil_dlgbmp_bmp" LongName="dlgbmp.bmp" Name="dlgbmp.bmp" /> + <File Id="fil_exclamic_ico" LongName="exclamic.ico" Name="exclamic.ico" /> + <File Id="fil_info_bmp" LongName="info.bmp" Name="info.bmp" /> + <File Id="fil_insticon_ico" LongName="insticon.ico" Name="insticon.ico" /> + <File Id="fil_new_bmp" LongName="new.bmp" Name="new.bmp" /> + <File Id="fil_removico_ico" LongName="removico.ico" Name="removico.ico" /> + <File Id="fil_repairic_ico" LongName="repairic.ico" Name="repairic.ico" /> + <File Id="fil_up_bmp" LongName="up.bmp" Name="up.bmp" /> + </Component> + </Directory> + <Directory Id="dirinstall_wix_custom" Name="custom" src="$(var.InstallDir)wix\custom\"> + <Component Win64="$(var.Win64)" Id="cmp_dirinstall_wix_custom" Guid="872AA948-39B0-4CDC-B764-7EB69F280E50" DiskId="1"> + <File Id="fil_custom_cpp" LongName="custom.cpp" Name="custom.cpp" KeyPath="yes" /> + <File Id="fil_custom_h" LongName="custom.h" Name="custom.h" /> + </Component> + </Directory> + </Directory> + </Directory> + + <Directory Id="dirdoc" Name="doc" src="$(var.DocDir)"> + <?if $(var.Platform) = "Intel" ?> + <Component Win64="$(var.Win64)" Id="efl_leash_userdoc_pdf" Guid="68FB24DD-5EC2-4db1-AD42-5B9DDEC247C5" DiskId="1"> + <File Id="fil_leash_userdoc_pdf" LongName="leash_userdoc.pdf" Name="leash.pdf" KeyPath="yes"> + <Shortcut Id="sc_leash_userdoc_pdf" Advertise="no" Directory="dirShortcut" LongName="Leash User Documentation.lnk" Name="leashdoc.lnk" /> + </File> + <Condition>USELEASH</Condition> + </Component> + <?endif?> + <Component Win64="$(var.Win64)" Id="efl_netidmgr_userdoc_pdf" Guid="7F5A91C1-C6D3-4F64-A6AC-C0AF337B4ED6" DiskId="1"> + <File Id="fil_netidmgr_userdoc_pdf" LongName="netidmgr_userdoc.pdf" Name="netidmgr.pdf" KeyPath="yes"> + <Shortcut Id="sc_netidmgr_userdoc_pdf" Advertise="no" Directory="dirShortcut" LongName="Network Identity Manager User Documentation.lnk" Name="netiddoc.lnk" /> + </File> + <Condition>USENETIDMGR</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="cmp_dirdoc_netid" Guid="D501BAF7-7E63-4864-AFED-1528D1C59B1B" DiskId="1"> + <File Id="fil_netidmgr_devdoc_chm" Name="netiddev.chm" KeyPath="yes"> + <Shortcut Id="sc_netidmgr_devdoc_chm" Advertise="no" Directory="dirShortcut" LongName="Network Identity Manager Developer Documentation.lnk" Name="netiddev.lnk" /> + </File> + <Condition>USENETIDMGR</Condition> + </Component> + <Component Win64="$(var.Win64)" Id="efl_relnotes_html" Guid="C65F920A-039D-4839-848F-0AD7B445F376" DiskId="1"> + <File Id="fil_relnotes_html" LongName="relnotes.html" Name="RELNOTES.HTM" KeyPath="yes"> + <Shortcut Id="sc_relnotes_html" Advertise="no" Directory="dirShortcut" LongName="Release Notes.lnk" Name="relnotes.lnk" /> + </File> + </Component> + </Directory> + + <Directory Id="dirsample" Name="sample" src="$(var.SampleDir)"> + <Directory Id="dirsample_templ" LongName="templates" Name="template" src="$(var.SampleDir)templates\"> + <Directory Id="dirsample_t_credprov" Name="credprov" src="$(var.SampleDir)templates\credprov\"> + <Component Win64="$(var.Win64)" Id="cmp_credprov_files" Guid="0D5A01A0-8DA9-4FED-9766-8B4DE6273145" DiskId="1"> + <File Id="fil_credprov_Makefile" Name="Makefile" KeyPath="yes" /> + <File Id="fil_credprov_config_id_c" Name="conf_id.c" LongName="config_id.c" /> + <File Id="fil_credprov_config_ids_c" Name="conf_ids.c" LongName="config_ids.c" /> + <File Id="fil_credprov_config_main_c" Name="conf_mn.c" LongName="config_main.c" /> + <File Id="fil_credprov_credacq_c" Name="credacq.c" /> + <File Id="fil_credprov_credprov_h" Name="credprov.h" /> + <File Id="fil_credprov_credtype_c" Name="credtype.c" /> + <File Id="fil_credprov_langres_h" Name="langres.h" /> + <File Id="fil_credprov_main_c" Name="main.c" /> + <File Id="fil_credprov_plugin_c" Name="plugin.c" /> + <File Id="fil_credprov_proppage_c" Name="proppage.c" /> + <File Id="fil_credprov_README" Name="README" /> + <File Id="fil_credprov_version_rc" Name="version.rc" /> + </Component> + + <Directory Id="dirsample_t_credprov_images" Name="images" src="$(var.SampleDir)templates\credprov\images\"> + <Component Win64="$(var.Win64)" Id="cmp_credprov_images_files" Guid="8A6CD5B8-482D-435F-9172-8F0B6AAA3C3F" DiskId="1"> + <File Id="fil_credprov_plugin_ico" Name="plugin.ico" KeyPath="yes" /> + </Component> + </Directory> + + <Directory Id="dirsample_t_credprov_lang" Name="lang" src="$(var.SampleDir)templates\credprov\lang\"> + <Directory Id="dirsample_t_credprov_lang_enus" Name="en_us" src="$(var.SampleDir)templates\credprov\lang\en_us\"> + <Component Win64="$(var.Win64)" Id="cmp_credprov_en_us_files" Guid="69C982D3-A1D3-4E23-9629-DE1842937F1D" DiskId="1"> + <File Id="fil_credprov_en_us_langres_rc" Name="langres.rc" KeyPath="yes" /> + </Component> + </Directory> + </Directory> + </Directory> + </Directory> + </Directory> + + </Directory> <!-- /Kerberos --> + </Directory> <!-- /MIT --> + </Directory> <!-- /Program Files --> + <Directory Id="WindowsFolder"> + <Component Win64="$(var.Win64)" Id="cmf_krb5_ini" Guid="C1AF0670-BBF1-4AA6-B2A6-6C8B1584A1F4" NeverOverwrite="yes" Permanent="yes" DiskId="1"> + <File Id="fil_krb5_ini" LongName="krb5.ini" Name="krb5.ini" src="$(var.ConfigDir)krb5.ini" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_krb_con" Guid="5E91A051-CF14-45FF-BF64-CEE78A7A90C2" NeverOverwrite="yes" Permanent="yes" DiskId="1"> + <File Id="fil_krb_con" LongName="krb.con" Name="krb.con" src="$(var.ConfigDir)krb.con" KeyPath="yes" /> + </Component> + <Component Win64="$(var.Win64)" Id="cmf_krbrealm_con" Guid="D667B54F-1C98-43FB-87C6-0F0517623B90" NeverOverwrite="yes" Permanent="yes" DiskId="1"> + <File Id="fil_krbrealm_con" LongName="krbrealm.con" Name="krbrealm.con" src="$(var.ConfigDir)krbrealm.con" KeyPath="yes" /> + </Component> + </Directory> + + <Directory Id="ProgramMenuFolder"> + <Directory Id="dirShortcut" LongName="$(loc.ProductName)" Name="KFW"> + </Directory> + </Directory> + <Directory Id="StartupFolder"> + </Directory> + + <Component Win64="$(var.Win64)" Id="rcm_common" Guid="486D84B6-CCE5-4b95-B8E2-7DFBDB4CF9A2"> + <Registry Id="reg_common0" Root="HKLM" Key="$(var.KfwRegRoot)" Action="createKeyAndRemoveKeyOnUninstall" /> + <Registry Id="reg_common1" Root="HKLM" Key="$(var.KfwRegRoot)" KeyPath="yes" /> + <Registry Id="reg_common2" Root="HKLM" Key="$(var.KfwRegRoot)" Name="InstallDir" Type="string" Value="[KERBEROSDIR]"/> + <?ifdef Debug?> + <Registry Id="reg_common3" Root="HKLM" Key="$(var.KfwRegRoot)\CurrentVersion" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_common4" Root="HKLM" Key="$(var.KfwRegRoot)\CurrentVersion" Name="Debug" Type="integer" Value="1"/> + <Registry Id="reg_common5" Root="HKLM" Key="$(var.KfwRegRoot)\$(var.VersionString)" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_common6" Root="HKLM" Key="$(var.KfwRegRoot)\$(var.VersionString)" Name="Debug" Type="integer" Value="1"/> + <?else?> + <Registry Id="reg_common7" Root="HKLM" Key="$(var.KfwRegRoot)\CurrentVersion" Action="removeKeyOnInstall"/> + <Registry Id="reg_common8" Root="HKLM" Key="$(var.KfwRegRoot)\$(var.VersionString)" Action="removeKeyOnInstall"/> + <?endif?> + </Component> + + <Component Win64="$(var.Win64)" Id="rcm_client" Guid="901179B2-7369-43b1-ACF3-4C7F37482CC7"> + <Registry Id="reg_client0" Root="HKLM" Key="$(var.KfwRegRoot)\Client" Action="createKeyAndRemoveKeyOnUninstall"/> + + <Registry Id="reg_client1" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_client2" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" /> + <Registry Id="reg_client3" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="VersionString" Type="string" Value="$(var.VersionString)" /> + <Registry Id="reg_client4" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="Title" Type="string" Value="KfW" /> + <Registry Id="reg_client5" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="Description" Type="string" Value="$(var.ProductFullName)" /> + <Registry Id="reg_client6" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="PathName" Type="string" Value="[KERBEROSDIR]" /> + <Registry Id="reg_client7" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="Software Type" Type="string" Value="Authentication" /> + <Registry Id="reg_client8" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="MajorVersion" Type="integer" Value="$(var.VersionMajor)" /> + <Registry Id="reg_client9" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="MinorVersion" Type="integer" Value="$(var.VersionMinor)" /> + <Registry Id="reg_client10" Root="HKLM" Key="$(var.KfwRegRoot)\Client\CurrentVersion" Name="PatchLevel" Type="integer" Value="$(var.VersionPatch)" /> + + <Registry Id="reg_client11" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_client12" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" KeyPath="yes" /> + <Registry Id="reg_client13" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="VersionString" Type="string" Value="$(var.VersionString)" /> + <Registry Id="reg_client14" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="Title" Type="string" Value="KfW" /> + <Registry Id="reg_client15" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="Description" Type="string" Value="$(var.ProductFullName)" /> + <Registry Id="reg_client16" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="PathName" Type="string" Value="[KERBEROSDIR]" /> + <Registry Id="reg_client17" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="Software Type" Type="string" Value="Authentication" /> + <Registry Id="reg_client18" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="MajorVersion" Type="integer" Value="$(var.VersionMajor)" /> + <Registry Id="reg_client19" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="MinorVersion" Type="integer" Value="$(var.VersionMinor)" /> + <Registry Id="reg_client20" Root="HKLM" Key="$(var.KfwRegRoot)\Client\$(var.VersionString)" Name="PatchLevel" Type="integer" Value="$(var.VersionPatch)" /> + </Component> + + <Component Win64="$(var.Win64)" Id="rcm_sdk" Guid="96AA90C7-8C60-4341-A15B-3DEDF29DA9F1"> + <Registry Id="reg_sdk0" Root="HKLM" Key="$(var.KfwRegRoot)\SDK" Action="createKeyAndRemoveKeyOnUninstall"/> + + <Registry Id="reg_sdk1" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_sdk2" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" /> + <Registry Id="reg_sdk3" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="VersionString" Type="string" Value="$(var.VersionString)" /> + <Registry Id="reg_sdk4" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="Title" Type="string" Value="KfW" /> + <Registry Id="reg_sdk5" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="Description" Type="string" Value="$(var.ProductFullName)" /> + <Registry Id="reg_sdk6" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="PathName" Type="string" Value="[KERBEROSDIR]" /> + <Registry Id="reg_sdk7" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="Software Type" Type="string" Value="Authentication" /> + <Registry Id="reg_sdk8" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="MajorVersion" Type="integer" Value="$(var.VersionMajor)" /> + <Registry Id="reg_sdk9" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="MinorVersion" Type="integer" Value="$(var.VersionMinor)" /> + <Registry Id="reg_sdk10" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\CurrentVersion" Name="PatchLevel" Type="integer" Value="$(var.VersionPatch)" /> + + <Registry Id="reg_sdk11" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_sdk12" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" KeyPath="yes" /> + <Registry Id="reg_sdk13" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="VersionString" Type="string" Value="$(var.VersionString)" /> + <Registry Id="reg_sdk14" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="Title" Type="string" Value="KfW" /> + <Registry Id="reg_sdk15" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="Description" Type="string" Value="$(var.ProductFullName)" /> + <Registry Id="reg_sdk16" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="PathName" Type="string" Value="[KERBEROSDIR]" /> + <Registry Id="reg_sdk17" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="Software Type" Type="string" Value="Authentication" /> + <Registry Id="reg_sdk18" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="MajorVersion" Type="integer" Value="$(var.VersionMajor)" /> + <Registry Id="reg_sdk19" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="MinorVersion" Type="integer" Value="$(var.VersionMinor)" /> + <Registry Id="reg_sdk20" Root="HKLM" Key="$(var.KfwRegRoot)\SDK\$(var.VersionString)" Name="PatchLevel" Type="integer" Value="$(var.VersionPatch)" /> + </Component> + + <Component Win64="$(var.Win64)" Id="rcm_docs" Guid="C7EADA0F-8FF7-4e7b-9372-5553BDD5812F"> + <Registry Id="reg_docs0" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation" Action="createKeyAndRemoveKeyOnUninstall"/> + + <Registry Id="reg_docs1" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_docs2" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" /> + <Registry Id="reg_docs3" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="VersionString" Type="string" Value="$(var.VersionString)" /> + <Registry Id="reg_docs4" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="Title" Type="string" Value="KfW" /> + <Registry Id="reg_docs5" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="Description" Type="string" Value="$(var.ProductFullName)" /> + <Registry Id="reg_docs6" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="PathName" Type="string" Value="[KERBEROSDIR]" /> + <Registry Id="reg_docs7" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="Software Type" Type="string" Value="Authentication" /> + <Registry Id="reg_docs8" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="MajorVersion" Type="integer" Value="$(var.VersionMajor)" /> + <Registry Id="reg_docs9" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="MinorVersion" Type="integer" Value="$(var.VersionMinor)" /> + <Registry Id="reg_docs10" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\CurrentVersion" Name="PatchLevel" Type="integer" Value="$(var.VersionPatch)" /> + + <Registry Id="reg_docs11" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Action="createKeyAndRemoveKeyOnUninstall"/> + <Registry Id="reg_docs12" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" KeyPath="yes" /> + <Registry Id="reg_docs13" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="VersionString" Type="string" Value="$(var.VersionString)" /> + <Registry Id="reg_docs14" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="Title" Type="string" Value="KfW" /> + <Registry Id="reg_docs15" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="Description" Type="string" Value="$(var.ProductFullName)" /> + <Registry Id="reg_docs16" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="PathName" Type="string" Value="[KERBEROSDIR]" /> + <Registry Id="reg_docs17" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="Software Type" Type="string" Value="Authentication" /> + <Registry Id="reg_docs18" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="MajorVersion" Type="integer" Value="$(var.VersionMajor)" /> + <Registry Id="reg_docs19" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="MinorVersion" Type="integer" Value="$(var.VersionMinor)" /> + <Registry Id="reg_docs20" Root="HKLM" Key="$(var.KfwRegRoot)\Documentation\$(var.VersionString)" Name="PatchLevel" Type="integer" Value="$(var.VersionPatch)" /> + </Component> + + <!-- Shared assembly runtime for VS 2005 --> + <?ifdef CL1400?> + <?ifdef env.CommonProgramFiles6432?> + <?define CPF="$(env.CommonProgramFiles(x86)"?> + <?else?> + <?define CPF="$(env.CommonProgramFiles)"?> + <?endif?> + + <?if $(var.Platform) = "x64" ?> + <?ifndef Debug?> + <Merge Id="MSVCRT8MEM" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_CRT_x86_x64.msm"/> + <Merge Id="MSVCRT8POL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_CRT_x86_x64.msm"/> + <Merge Id="MSVCRT8MFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_MFC_x86_x64.msm"/> + <Merge Id="MSVCRT8PFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_MFC_x86_x64.msm"/> + <Merge Id="MSVCRT8MFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_MFCLOC_x86_x64.msm"/> + <Merge Id="MSVCRT8PFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_MFCLOC_x86_x64.msm"/> + <?else?> + <Merge Id="MSVCRT8MEM" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_DebugCRT_x86_x64.msm"/> + <Merge Id="MSVCRT8POL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_DebugCRT_x86_x64.msm"/> + <Merge Id="MSVCRT8MFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_DebugMFC_x86_x64.msm"/> + <Merge Id="MSVCRT8PFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_DebugMFC_x86_x64.msm"/> + <Merge Id="MSVCRT8MFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_MFCLOC_x86_x64.msm"/> + <Merge Id="MSVCRT8PFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_MFCLOC_x86_x64.msm"/> + <?endif?> + <?else?> + <?ifndef Debug?> + <Merge Id="MSVCRT8MEM" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_CRT_x86.msm"/> + <Merge Id="MSVCRT8POL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_CRT_x86.msm"/> + <Merge Id="MSVCRT8MFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_MFC_x86.msm"/> + <Merge Id="MSVCRT8PFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_MFC_x86.msm"/> + <Merge Id="MSVCRT8MFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_MFCLOC_x86.msm"/> + <Merge Id="MSVCRT8PFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_MFCLOC_x86.msm"/> + <?else?> + <Merge Id="MSVCRT8MEM" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_DebugCRT_x86.msm"/> + <Merge Id="MSVCRT8POL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_DebugCRT_x86.msm"/> + <Merge Id="MSVCRT8MFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_DebugMFC_x86.msm"/> + <Merge Id="MSVCRT8PFC" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_DebugMFC_x86.msm"/> + <Merge Id="MSVCRT8MFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\Microsoft_VC80_MFCLOC_x86.msm"/> + <Merge Id="MSVCRT8PFL" DiskId="1" Language="0" src="$(var.CPF)\Merge Modules\policy_8_0_Microsoft_VC80_MFCLOC_x86.msm"/> + <?endif?> + <?endif?> + <?endif?> + +</Directory> +</Include> diff --git a/krb5-1-6/src/windows/installer/wix/kfw.wxs b/krb5-1-6/src/windows/installer/wix/kfw.wxs new file mode 100644 index 000000000..02bfb6898 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/kfw.wxs @@ -0,0 +1,240 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + Copyright (C) 2004,2005, 2006 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> + +<!-- configuration --> +<?include config.wxi?> +<?include platform.wxi?> + +<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> + <Product + Id="$(var.ProductCode)" + Codepage="$(var.CodePage)" + Language="$(var.Language)" + Manufacturer="$(loc.Manufacturer)" + Name="$(var.ProductName)" + UpgradeCode="$(var.UpgradeCode)" + Version="$(var.VersionString)"> + + <!-- The weird package code results in a new one being generated each time we compile --> + <Package + Id="????????-????-????-????-????????????" + Keywords="Installer,MSI,Database" + Description="$(var.ProductName)" + Comments="$(var.ProductFullName)" + Manufacturer="$(loc.Manufacturer)" + InstallerVersion="110" + Languages="$(var.Language)" + Compressed="yes" + SummaryCodepage="$(var.CodePage)" + /> + + <?include lang\ui_$(var.BuildLang).wxi?> + <?include files.wxi?> + <?include features.wxi?> + <?include property.wxi?> + + <!-- Launch conditions --> + <Condition Message="$(loc.AdminRequired)">Privileged</Condition> + <Condition Message="$(loc.OsVersionRequired)">VersionNT &gt;= 500</Condition> + <Condition Message="$(loc.CMNotSelected)">USELEASH Or USENETIDMGR</Condition> + <Condition Message="$(loc.CMDupSelected)">Not (USELEASH And USENETIDMGR)</Condition> + + <!-- Custom actions --> + <Binary Id="binCustom" src="custom\custom.dll" /> + + <CustomAction + Id="EnableTgtSessionKey" + BinaryKey="binCustom" + DllEntry="EnableAllowTgtSessionKey" + Execute="deferred" + Impersonate="no" + Return="check" /> + <Property Id="EnableTgtSessionKey" Value="$(var.VersionString)" /> + + <CustomAction + Id="RevertTgtSessionKey" + BinaryKey="binCustom" + DllEntry="RevertAllowTgtSessionKey" + Execute="deferred" + Impersonate="no" + Return="check" /> + <Property Id="RevertTgtSessionKey" Value="$(var.VersionString)" /> + + <CustomAction + Id="RollbackTgtSessionKey" + BinaryKey="binCustom" + DllEntry="RevertAllowTgtSessionKey" + Execute="rollback" + Impersonate="no" + Return="check" /> + <Property Id="RollbackTgtSessionKey" Value="$(var.VersionString)" /> + + <CustomAction + Id="RemoveNsisInstallation" + BinaryKey="binCustom" + DllEntry="UninstallNsisInstallation" + Execute="immediate" /> + + <CustomAction + Id="AbortCantRemoveNSIS" + Value="[CantRemoveNSISError]" + Property="CantRemoveNSISError" /> + + <CustomAction + Id="AbortNoIE" + Value="[NoIE501Error]" + Property="NoIE501Error" /> + + <CustomAction + Id="ListRunningProcesses" + BinaryKey="binCustom" + DllEntry="ListRunningProcesses" + Execute="immediate" + Return="ignore" /> + + <CustomAction + Id="KillRunningProcesses" + BinaryKey="binCustom" + DllEntry="KillRunningProcesses" + Execute="immediate" + Return="ignore" /> + + <CustomAction + Id="InstallNetProvider" + BinaryKey="binCustom" + DllEntry="InstallNetProvider" + Impersonate="no" + Execute="deferred" /> + + <CustomAction + Id="RemoveNetProvider" + BinaryKey="binCustom" + DllEntry="UninstallNetProvider" + Impersonate="no" + Return="ignore" + Execute="deferred" /> + + <CustomAction + Id="RollbackNetProvider" + BinaryKey="binCustom" + DllEntry="UninstallNetProvider" + Return="ignore" + Execute="rollback" /> + + <!-- Installation Sequences --> + <AdminExecuteSequence /> + <InstallExecuteSequence> + <Custom Action="KillRunningProcesses" After="InstallValidate"/> + <RemoveExistingProducts After="KillRunningProcesses">(Not Installed) And (UPGRADEPISMERE Or UPGRADEKFW)</RemoveExistingProducts> + <!-- When running with a UI, CCP_Success property is not passed down to the server. --> + <Custom Action="AbortNoIE" Before="RemoveNsisInstallation">UILevel = 0 And (Not Installed) And (CCP_Success &lt;&gt; 1)</Custom> + <Custom Action="RemoveNsisInstallation" Before="AbortCantRemoveNSIS">UPGRADENSIS &lt;&gt; "" And UILevel &gt;= 4</Custom> + <Custom Action="AbortCantRemoveNSIS" Before="CostInitialize">UPGRADENSIS &lt;&gt; "" And UILevel &lt; 4</Custom> + <Custom Action="RollbackTgtSessionKey" After="WriteRegistryValues">VersionNT &gt;= 500 And &amp;feaKfwClient=3</Custom> + <Custom Action="EnableTgtSessionKey" After="RollbackTgtSessionKey">VersionNT &gt;= 500 And &amp;feaKfwClient=3</Custom> + <Custom Action="RevertTgtSessionKey" Before="RemoveRegistryValues">VersionNT &gt;= 500 And &amp;feaKfwClient=2</Custom> + + <Custom Action="RollbackNetProvider" After="EnableTgtSessionKey">&amp;feaKfwClient=3</Custom> + <Custom Action="InstallNetProvider" After="RollbackNetProvider">&amp;feaKfwClient=3</Custom> + <Custom Action="RemoveNetProvider" After="InstallNetProvider">&amp;feaKfwClient=2</Custom> + </InstallExecuteSequence> + + <!-- Upgrade paths --> + + <!-- MIT Project Pismere MSI --> + <Upgrade Id="83977767-388D-4DF8-BB08-3BF2401635BD"> + <UpgradeVersion IgnoreRemoveFailure="no" IncludeMinimum="no" Maximum="4.0.0" MigrateFeatures="no" Property="UPGRADEPISMERE"/> + </Upgrade> + + <!-- KfW MSI --> + <Upgrade Id="61211594-AAA1-4A98-A299-757326763CC7"> + <UpgradeVersion IgnoreRemoveFailure="no" IncludeMinimum="no" Maximum="$(var.VersionString)" IncludeMaximum="yes" MigrateFeatures="yes" Property="UPGRADEKFW" /> + </Upgrade> + + <!-- NSIS installation --> + <!-- The NSIS installation, being non-MSI, is detected and removed through other means. --> + + <!-- Check and warn if we don't have the right version of IE installed --> + <ComplianceCheck> + <DirectorySearch Id="ccd_iphlpapi" Depth="1" Path="[SystemFolder]"> + <FileSearch Id="cc_iphlp" MinDate="1999-04-23T00:00:00-05:00" Name="iphlpapi.dll" /> + </DirectorySearch> + </ComplianceCheck> + + <!-- We embed all the files in a single cabinet. --> + <Media Id="1" Cabinet="Disk1" CompressionLevel="high" EmbedCab="yes" /> + + <!-- Custom table used by KillProcesses custom action --> + <CustomTable Id="KillProcess"> + <Column Id="Id" PrimaryKey="yes" Nullable="no" Type="string" Width="32" /> + <Column Id="Image" Nullable="no" Type="string" Width="255" /> + <Column Id="Desc" Nullable="yes" Type="string" Width="255" /> + + <Row> + <Data Column="Id">kpLeash</Data> + <Data Column="Image">leash32.exe</Data> + <Data Column="Desc">Leash Ticket Manager</Data> + </Row> + <Row> + <Data Column="Id">kpNetIDMgr</Data> + <Data Column="Image">netidmgr.exe</Data> + <Data Column="Desc">Network Identity Manager</Data> + </Row> + <Row> + <Data Column="Id">kpKrbcc</Data> + <Data Column="Image">krbcc32s.exe</Data> + <Data Column="Desc">Kerberos Credential Cache</Data> + </Row> + <Row> + <Data Column="Id">kpK95</Data> + <Data Column="Image">k95.exe</Data> + <Data Column="Desc">Kermit 95</Data> + </Row> + <Row> + <Data Column="Id">kpK95g</Data> + <Data Column="Image">k95g.exe</Data> + <Data Column="Desc">Kermit 95 GUI</Data> + </Row> + <Row> + <Data Column="Id">kpkrb5</Data> + <Data Column="Image">krb5.exe</Data> + <Data Column="Desc">Kerberos Client</Data> + </Row> + <Row> + <Data Column="Id">kpgss</Data> + <Data Column="Image">gss.exe</Data> + <Data Column="Desc">GSSAPI Test Client</Data> + </Row> + <Row> + <Data Column="Id">kpafscreds</Data> + <Data Column="Image">afscreds.exe</Data> + <Data Column="Desc">AFS Credentials Manager</Data> + </Row> + </CustomTable> + </Product> +</Wix> + diff --git a/krb5-1-6/src/windows/installer/wix/lang/config_1033.wxi b/krb5-1-6/src/windows/installer/wix/lang/config_1033.wxi new file mode 100644 index 000000000..0fc62e3d1 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/lang/config_1033.wxi @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + Copyright (C) 2004 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> +<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> + + <?define VersionString="$(var.VersionMajor).$(var.VersionMinor).$(var.VersionPatch)"?> + + <?ifdef var.Release?> + <?ifndef var.Debug?> + <?define ProductFullName="$(loc.ProductMIT) $(loc.ProductName) $(var.VersionString)"?> + <?else?> + <?define ProductFullName="$(loc.ProductMIT) $(loc.ProductName) $(var.VersionString) $(loc.ProductDebug)"?> + <?endif?> + <?else?> + <?ifdef var.Beta?> + <?ifndef var.Debug?> + <?define ProductFullName="$(loc.ProductMIT) $(loc.ProductName) $(var.VersionString) $(loc.ProductBeta) $(var.Beta) "?> + <?else?> + <?define ProductFullName="$(loc.ProductMIT) $(loc.ProductName) $(var.VersionString) $(loc.ProductBeta) $(var.Beta) $(loc.ProductDebug)"?> + <?endif?> + <?else?> + + <?ifndef var.Date?> + <?error Date string must be specified?> + <?endif?> + + <?ifndef var.Time?> + <?error Time string must be specified?> + <?endif?> + + <?ifndef var.Debug?> + <?define ProductFullName="$(loc.ProductMIT) $(loc.ProductName) $(var.VersionString) $(var.Date) $(var.Time)"?> + <?else?> + <?define ProductFullName="$(loc.ProductMIT) $(loc.ProductName) $(var.VersionString) $(var.Date) $(var.Time) $(loc.ProductDebug)"?> + <?endif?> + <?endif?> + <?endif?> + + <!-- Language specific configuration (English) --> + <?define ProductName="$(var.ProductFullName)"?> + <?define CodePage="1252"?> + <?define Language="1033"?> + + <?define ARPComments="$(loc.ARPComments) $(var.Date) $(var.Time)"?> +</Include> \ No newline at end of file diff --git a/krb5-1-6/src/windows/installer/wix/lang/license.rtf b/krb5-1-6/src/windows/installer/wix/lang/license.rtf new file mode 100644 index 000000000..dd7b0b6ea --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/lang/license.rtf @@ -0,0 +1,102 @@ +{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033{\fonttbl{\f0\fmodern\fprq1\fcharset0 Courier New;}{\f1\froman\fprq2\fcharset0 Times New Roman;}} +{\*\generator Msftedit 5.41.15.1507;}\viewkind4\uc1\pard\nowidctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\f0\fs20 Copyright Notice and Legal Administrivia\par +----------------------------------------\par +\par +Copyright (C) 1985-2005 by the Massachusetts Institute of Technology.\par +\par +All rights reserved.\par +\par +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.\par +\par +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\par +this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Furthermore if you modify this software you must label your software as modified software and not distribute it in such a fashion that it might be confused with the original MIT software. M.I.T. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.\par +\par +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.\par +\par +Individual source code files are copyright MIT, Cygnus Support, OpenVision, Oracle, Sun Soft, FundsXpress, and others.\par +\par +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, and Zephyr are trademarks of the Massachusetts Institute of Technology (MIT). No commercial use of these trademarks may be made without prior written permission of MIT.\par +\par +"Commercial use" means use of a name in a product or other for-profit manner. It does NOT prevent a commercial firm from referring to the MIT trademarks in order to convey information (although in doing so, recognition of their trademark status should be given).\par +\par +----\par +\par +The following copyright and permission notice applies to the OpenVision Kerberos Administration system located in kadmin/create, kadmin/dbutil, kadmin/passwd, kadmin/server, lib/kadm5, and portions of lib/rpc:\par +\par +Copyright, OpenVision Technologies, Inc., 1996, All Rights Reserved\par +\par +WARNING: Retrieving the OpenVision Kerberos Administration system source code, as described below, indicates your acceptance of the following terms. If you do not agree to the following terms, do not retrieve the OpenVision Kerberos administration system.\par +\par +You may freely use and distribute the Source Code and Object Code compiled from it, with or without modification, but this Source Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY OTHER REASON.\par +\par +OpenVision retains all copyrights in the donated Source Code. OpenVision also retains copyright to derivative works of the Source Code, whether created by OpenVision or by a third party. The OpenVision copyright notice must be preserved if derivative works are made based on the donated Source Code.\par +\par +OpenVision Technologies, Inc. has donated this Kerberos Administration system to MIT for inclusion in the standard Kerberos 5 distribution. This donation underscores our commitment to continuing Kerberos technology development and our gratitude for the valuable work which has been performed by MIT and the Kerberos community.\par +\par +----\par +\par +Portions contributed by Matt Crawford <crawdad@fnal.gov> were work performed at Fermi National Accelerator Laboratory, which is operated by Universities Research Association, Inc., under contract DE-AC02-76CHO3000 with the U.S. Department of Energy.\par +\par +\pard ----\f1\fs24\par +\pard\nowidctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\f0\fs20\par +The implementation of the Yarrow pseudo-random number generator in src/lib/crypto/yarrow has the following copyright:\par +\par +Copyright 2000 by Zero-Knowledge Systems, Inc.\par +\par +Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, 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 Zero-Knowledge Systems, Inc. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Zero-Knowledge Systems, Inc. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.\par +\par +ZERO-KNOWLEDGE SYSTEMS, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ZERO-KNOWLEDGE SYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\par +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\par +\par +\pard ----\f1\fs24\par +\pard\nowidctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\f0\fs20\par +The implementation of the AES encryption algorithm in src/lib/crypto/aes has the following copyright:\par +\par +Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.\par +All rights reserved.\par +\par +LICENSE TERMS\par +\par +The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that:\par +\par +1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer;\par +\par +2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials;\par +\par +3. the copyright holder's name is not used to endorse products built using this software without specific written permission. \par +\par +DISCLAIMER\par +\par +This software is provided 'as is' with no explcit or implied warranties in respect of any properties, including, but not limited to, correctness and fitness for purpose.\par +\par +\par +\par +Acknowledgements\par +----------------\par +\par +Appreciation Time!!!! There are far too many people to try to thank them all; many people have contributed to the development of Kerberos V5. This is only a partial listing....\par +\par +Thanks to Paul Vixie and the Internet Software Consortium for funding the work of Barry Jaspan. This funding was invaluable for the OV administration server integration, as well as the 1.0 release preparation process.\par +\par +Thanks to John Linn, Scott Foote, and all of the folks at OpenVision Technologies, Inc., who donated their administration server for use in the MIT release of Kerberos.\par +\par +Thanks to Jeff Bigler, Mark Eichin, Marc Horowitz, Nancy Gilman, Ken Raeburn, and all of the folks at Cygnus Support, who provided innumerable bug fixes and portability enhancements to the Kerberos V5 tree. Thanks especially to Jeff Bigler, for the new user and system administrator's documentation.\par +\par +Thanks to Doug Engert from ANL for providing many bug fixes, as well as testing to ensure DCE interoperability.\par +\par +Thanks to Ken Hornstein at NRL for providing many bug fixes and suggestions, and for working on SAM preauthentication.\par +\par +Thanks to Matt Crawford at FNAL for bugfixes and enhancements.\par +\par +Thanks to Sean Mullan and Bill Sommerfeld from Hewlett Packard for their many suggestions and bug fixes.\par +\par +Thanks to Nalin Dahyabhai of RedHat and Chris Evans for locating and providing patches for numerous buffer overruns.\par +\par +Thanks to Christopher Thompson and Marcus Watts for discovering the ftpd security bug.\par +\par +Thanks to Paul Nelson of Thursby Software Systems for implementing the Microsoft set password protocol.\par +\par +Thanks to the members of the Kerberos V5 development team at MIT, both past and present: Danilo Almeida, Jeffrey Altman, Jay Berkenbilt, Richard Basch, Mitch Berger, John Carr, Don Davis, Alexandra Ellwood, Nancy Gilman, Matt Hancher, Sam Hartman, Paul Hill, Marc Horowitz, Eva Jacobus, Miroslav Jurisic, Barry Jaspan, Geoffrey King, John Kohl, Peter Litwack, Scott McGuire, Kevin Mitchell, Cliff Neuman, Paul Park, Ezra Peisach, Chris Provenzano, Ken Raeburn, Jon Rochlis, Jeff Schiller, Jen Selby, Brad Thompson, Harry Tsai, Ted Ts'o, Marshall Vale, Tom Yu.\par +\pard\nowidctlpar\f1\fs24\par +} +� \ No newline at end of file diff --git a/krb5-1-6/src/windows/installer/wix/lang/strings_1033.wxl b/krb5-1-6/src/windows/installer/wix/lang/strings_1033.wxl new file mode 100644 index 000000000..881334376 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/lang/strings_1033.wxl @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<WixLocalization> +<!-- + + Copyright (C) 2004 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> + <String Id="ProductName">Kerberos for Windows</String> + <String Id="ProductNameShort">KFW</String> + <String Id="ProductMIT">MIT</String> + <String Id="ProductDebug">Debug/Checked</String> + <String Id="ProductBeta">Beta</String> + + <String Id="Manufacturer">Massachusetts Institute of Technology</String> + + <String Id="KerberosTitle">Kerberos for Windows</String> + <String Id="KerberosDesc">Kerberos for Windows</String> + + <String Id="KerberosClientTitle">Client</String> + <String Id="KerberosClientDesc">Kerberos client utilities, libraries and documentation</String> + + <String Id="StrKerberosClientDebugTitle">Debug symbols</String> + <String Id="StrKerberosClientDebugDesc">Debugging symbols for Kerberos for Windows components.</String> + + <String Id="StrLeashExeTitle">Leash Credentials Manager</String> + <String Id="StrLeashExeDesc">Leash credentials manager</String> + + <String Id="KerberosSDKTitle">SDK</String> + <String Id="KerberosSDKDesc">Libraries and header files for developing software with Kerberos</String> + + <String Id="KerberosDocTitle">Documentation</String> + <String Id="KerberosDocDesc">Documentation</String> + + <String Id="AdminRequired">You need administrative privileges to install Kerberos for Windows</String> + <String Id="OsVersionRequired">This product requires Windows 2000/XP/2003. The current operating system is not supported.</String> + <String Id="CMNotSelected">Neither Leash nor Network Identity Manager has been selected for this package. Please contact your administrator or the provider of this installation package to resolve this issue.</String> + <String Id="CMDupSelected">Both Leash and Network Identity Manager has been selected for this package. Only one of these can be selected at one time. Please contact your administrator or the provider of this installation package to resolve this issue.</String> + + <String Id="CantRemoveNSIS">The NSIS based installation of Kerberos for Windows could not be uninstalled because the NSIS uninstaller must be run in Full UI mode.</String> + <String Id="IE501Required">Kerberos for Windows requires Microsoft Internet Explorer version 5.01 or higher. Please resolve this and run the installer again.</String> + + <String Id="ARPComments">Build of</String> + +</WixLocalization> \ No newline at end of file diff --git a/krb5-1-6/src/windows/installer/wix/lang/ui_1033.wxi b/krb5-1-6/src/windows/installer/wix/lang/ui_1033.wxi new file mode 100644 index 000000000..bae778175 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/lang/ui_1033.wxi @@ -0,0 +1,1239 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + Copyright (C) 2004,2005, 2006 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> +<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> + <UI> + <Dialog Id="AdminWelcomeDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Property="InstallMode" Value="Server Image">1</Publish> + <Publish Event="NewDialog" Value="AdminInstallPointDlg">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="30" Transparent="yes" NoPrefix="yes"> + <Text>The [Wizard] will create a server image of [ProductName], at a specified network location. Click Next to continue or Cancel to exit the [Wizard].</Text> + </Control> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}Welcome to the [ProductName] [Wizard]</Text> + </Control> + </Dialog> + <Dialog Id="ExitDialog" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Finish]"> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Cancel]" /> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Click the Finish button to exit the [Wizard].</Text> + </Control> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}Completing the [ProductName] [Wizard]</Text> + </Control> + </Dialog> + <Dialog Id="FatalError" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Finish]"> + <Publish Event="EndDialog" Value="Exit">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Cancel]" /> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}[ProductName] [Wizard] ended prematurely</Text> + </Control> + <Control Id="Description1" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes"> + <Text>[ProductName] setup ended prematurely because of an error. Your system has not been modified. To install this program at a later time, please run the installation again.</Text> + </Control> + <Control Id="Description2" Type="Text" X="135" Y="115" Width="220" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Click the Finish button to exit the [Wizard].</Text> + </Control> + </Dialog> + <Dialog Id="PrepareDlg" Width="370" Height="270" Title="[ProductName] [Setup]" Modeless="yes"> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Please wait while the [Wizard] prepares to guide you through the installation.</Text> + </Control> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}Welcome to the [ProductName] [Wizard]</Text> + </Control> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" TabSkip="yes" Text="[ButtonText_Back]" /> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" TabSkip="yes" Text="[ButtonText_Next]" /> + <Control Id="ActionData" Type="Text" X="135" Y="125" Width="220" Height="30" Transparent="yes" NoPrefix="yes"> + <Subscribe Event="ActionData" Attribute="Text" /> + </Control> + <Control Id="ActionText" Type="Text" X="135" Y="100" Width="220" Height="20" Transparent="yes" NoPrefix="yes"> + <Subscribe Event="ActionText" Attribute="Text" /> + </Control> + </Dialog> + <Dialog Id="ProgressDlg" Width="370" Height="270" Title="[ProductName] [Setup]" Modeless="yes"> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Next]" /> + <Control Id="Text" Type="Text" X="35" Y="65" Width="300" Height="20"> + <Text>Please wait while the [Wizard] [Progress2] [ProductName]. This may take several minutes.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Title" Type="Text" X="20" Y="15" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont][Progress1] [ProductName]</Text> + </Control> + <Control Id="ActionText" Type="Text" X="70" Y="100" Width="265" Height="10"> + <Subscribe Event="ActionText" Attribute="Text" /> + </Control> + <Control Id="ProgressBar" Type="ProgressBar" X="35" Y="115" Width="300" Height="10" ProgressBlocks="yes" Text="Progress done"> + <Subscribe Event="SetProgress" Attribute="Progress" /> + </Control> + <Control Id="StatusLabel" Type="Text" X="35" Y="100" Width="35" Height="10" Text="Status:" /> + </Dialog> + <Dialog Id="UserExit" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Finish]"> + <Publish Event="EndDialog" Value="Exit">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Cancel]" /> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}[ProductName] [Wizard] was interrupted</Text> + </Control> + <Control Id="Description1" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes"> + <Text>[ProductName] setup was interrupted. Your system has not been modified. To install this program at a later time, please run the installation again.</Text> + </Control> + <Control Id="Description2" Type="Text" X="135" Y="115" Width="220" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Click the Finish button to exit the [Wizard].</Text> + </Control> + </Dialog> + <Dialog Id="AdminBrowseDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="17" Property="TARGETDIR" /> + <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_OK]"> + <Publish Event="SetTargetPath" Value="TARGETDIR">1</Publish> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="Reset" Value="0">1</Publish> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="ComboLabel" Type="Text" X="25" Y="58" Width="44" Height="10" TabSkip="no" Text="&amp;Look in:" /> + <Control Id="DirectoryCombo" Type="DirectoryCombo" X="70" Y="55" Width="220" Height="80" Property="TARGETDIR" Removable="yes" Fixed="yes" Remote="yes"> + <Subscribe Event="IgnoreChange" Attribute="IgnoreChange" /> + </Control> + <Control Id="Up" Type="PushButton" X="298" Y="55" Width="19" Height="19" ToolTip="Up One Level" Icon="yes" FixedSize="yes" IconSize="16" Text="Up"> + <Publish Event="DirectoryListUp" Value="0">1</Publish> + </Control> + <Control Id="NewFolder" Type="PushButton" X="325" Y="55" Width="19" Height="19" ToolTip="Create A New Folder" Icon="yes" FixedSize="yes" IconSize="16" Text="New"> + <Publish Event="DirectoryListNew" Value="0">1</Publish> + </Control> + <Control Id="DirectoryList" Type="DirectoryList" X="25" Y="83" Width="320" Height="110" Property="TARGETDIR" Sunken="yes" TabSkip="no" /> + <Control Id="PathLabel" Type="Text" X="25" Y="205" Width="59" Height="10" TabSkip="no" Text="&amp;Folder name:" /> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Browse to the destination folder</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Change current destination folder</Text> + </Control> + </Dialog> + <Dialog Id="AdminInstallPointDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Text" Type="Text" X="25" Y="80" Width="320" Height="10" TabSkip="no"> + <Text>&amp;Enter a new network location or click Browse to browse to one.</Text> + </Control> + <Control Id="PathEdit" Type="PathEdit" X="25" Y="93" Width="320" Height="18" Property="TARGETDIR" /> + <Control Id="Browse" Type="PushButton" X="289" Y="119" Width="56" Height="17" Text="[ButtonText_Browse]"> + <Publish Event="SpawnDialog" Value="AdminBrowseDlg">1</Publish> + </Control> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="AdminWelcomeDlg">1</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="SetTargetPath" Value="TARGETDIR">1</Publish> + <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Please specify a network location for the server image of [ProductName] product</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Network Location</Text> + </Control> + </Dialog> + <Dialog Id="BrowseDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="18" Property="_BrowseProperty" Indirect="yes" /> + <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_OK]"> + <Publish Event="SetTargetPath" Value="[_BrowseProperty]">1</Publish> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="Reset" Value="0">1</Publish> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="ComboLabel" Type="Text" X="25" Y="58" Width="44" Height="10" TabSkip="no" Text="&amp;Look in:" /> + <Control Id="DirectoryCombo" Type="DirectoryCombo" X="70" Y="55" Width="220" Height="80" Property="_BrowseProperty" Indirect="yes" Fixed="yes" Remote="yes"> + <Subscribe Event="IgnoreChange" Attribute="IgnoreChange" /> + </Control> + <Control Id="Up" Type="PushButton" X="298" Y="55" Width="19" Height="19" ToolTip="Up One Level" Icon="yes" FixedSize="yes" IconSize="16" Text="Up"> + <Publish Event="DirectoryListUp" Value="0">1</Publish> + </Control> + <Control Id="NewFolder" Type="PushButton" X="325" Y="55" Width="19" Height="19" ToolTip="Create A New Folder" Icon="yes" FixedSize="yes" IconSize="16" Text="New"> + <Publish Event="DirectoryListNew" Value="0">1</Publish> + </Control> + <Control Id="DirectoryList" Type="DirectoryList" X="25" Y="83" Width="320" Height="110" Property="_BrowseProperty" Sunken="yes" Indirect="yes" TabSkip="no" /> + <Control Id="PathLabel" Type="Text" X="25" Y="205" Width="59" Height="10" TabSkip="no" Text="&amp;Folder name:" /> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Browse to the destination folder</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Change current destination folder</Text> + </Control> + </Dialog> + <Dialog Id="CancelDlg" Y="10" Width="260" Height="85" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="No" Type="PushButton" X="132" Y="57" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_No]"> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="Yes" Type="PushButton" X="72" Y="57" Width="56" Height="17" Text="[ButtonText_Yes]"> + <Publish Event="EndDialog" Value="Exit">1</Publish> + </Control> + <Control Id="Text" Type="Text" X="48" Y="15" Width="194" Height="30"> + <Text>Are you sure you want to cancel [ProductName] installation?</Text> + </Control> + <Control Id="Icon" Type="Icon" X="15" Y="15" Width="24" Height="24" ToolTip="Information icon" FixedSize="yes" IconSize="32" Text="[InfoIcon]" /> + </Dialog> + <Dialog Id="CustomizeDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes" TrackDiskSpace="yes"> + <Control Id="Tree" Type="SelectionTree" X="25" Y="85" Width="175" Height="95" Property="_BrowseProperty" Sunken="yes" TabSkip="no" Text="Tree of selections" /> + <Control Id="Browse" Type="PushButton" X="304" Y="200" Width="56" Height="17" Text="[ButtonText_Browse]"> + <Publish Event="SelectionBrowse" Value="BrowseDlg">1</Publish> + <Condition Action="hide">Installed</Condition> + </Control> + <Control Id="Reset" Type="PushButton" X="42" Y="243" Width="56" Height="17" Text="[ButtonText_Reset]"> + <Publish Event="Reset" Value="0">1</Publish> + <Subscribe Event="SelectionNoItems" Attribute="Enabled" /> + </Control> + <Control Id="DiskCost" Type="PushButton" X="111" Y="243" Width="56" Height="17"> + <Text>Disk &amp;Usage</Text> + <Publish Event="SpawnDialog" Value="DiskCostDlg">1</Publish> + <Subscribe Event="SelectionNoItems" Attribute="Enabled" /> + </Control> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="MaintenanceTypeDlg">InstallMode = "Change"</Publish> + <Publish Event="NewDialog" Value="SetupTypeDlg">InstallMode = "Custom"</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="NewDialog" Value="VerifyReadyDlg">( &amp;feaKfwClient &lt;&gt; 3 And !feaKfwClient &lt;&gt; 3 ) And Not FoundProcesses</Publish> + <Publish Event="NewDialog" Value="RunningProcessDlg">( &amp;feaKfwClient &lt;&gt; 3 And !feaKfwClient &lt;&gt; 3 ) And FoundProcesses</Publish> + <Publish Event="NewDialog" Value="KerberosOptions">&amp;feaKfwClient = 3 Or !feaKfwClient = 3</Publish> + <Subscribe Event="SelectionNoItems" Attribute="Enabled" /> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Text" Type="Text" X="25" Y="55" Width="320" Height="20"> + <Text>Click on the icons in the tree below to change the way features will be installed.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Select the way you want features to be installed.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Custom Setup</Text> + </Control> + <Control Id="Box" Type="GroupBox" X="210" Y="81" Width="140" Height="98" /> + <Control Id="ItemDescription" Type="Text" X="215" Y="90" Width="131" Height="30"> + <Text>Multiline description of the currently selected item.</Text> + <Subscribe Event="SelectionDescription" Attribute="Text" /> + </Control> + <Control Id="ItemSize" Type="Text" X="215" Y="130" Width="131" Height="45"> + <Text>The size of the currently selected item.</Text> + <Subscribe Event="SelectionSize" Attribute="Text" /> + </Control> + <Control Id="Location" Type="Text" X="75" Y="200" Width="215" Height="20"> + <Text>&lt;The selection's path&gt;</Text> + <Subscribe Event="SelectionPath" Attribute="Text" /> + <Subscribe Event="SelectionPathOn" Attribute="Visible" /> + <Condition Action="hide">Installed</Condition> + </Control> + <Control Id="LocationLabel" Type="Text" X="25" Y="200" Width="50" Height="10" Text="Location:"> + <Subscribe Event="SelectionPathOn" Attribute="Visible" /> + <Condition Action="hide">Installed</Condition> + </Control> + </Dialog> + <Dialog Id="DiskCostDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_OK]"> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Text" Type="Text" X="20" Y="53" Width="330" Height="40"> + <Text>The highlighted volumes (if any) do not have enough disk space available for the currently selected features. You can either remove some files from the highlighted volumes, or choose to install less features onto local drive(s), or select different destination drive(s).</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="20" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>The disk space required for the installation of the selected features.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Disk Space Requirements</Text> + </Control> + <Control Id="VolumeList" Type="VolumeCostList" X="20" Y="100" Width="330" Height="120" Sunken="yes" Fixed="yes" Remote="yes"> + <Text>{120}{70}{70}{70}{70}</Text> + </Control> + </Dialog> + <Dialog Id="ErrorDlg" Y="10" Width="270" Height="105" Title="Installer Information" ErrorDialog="yes" NoMinimize="yes"> + <Control Id="ErrorText" Type="Text" X="48" Y="15" Width="205" Height="60" TabSkip="no" Text="Information text" /> + <Control Id="Y" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Yes]"> + <Publish Event="EndDialog" Value="ErrorYes">1</Publish> + </Control> + <Control Id="A" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Cancel]"> + <Publish Event="EndDialog" Value="ErrorAbort">1</Publish> + </Control> + <Control Id="C" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Cancel]"> + <Publish Event="EndDialog" Value="ErrorCancel">1</Publish> + </Control> + <Control Id="ErrorIcon" Type="Icon" X="15" Y="15" Width="24" Height="24" ToolTip="Information icon" FixedSize="yes" IconSize="32" Text="[InfoIcon]" /> + <Control Id="I" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Ignore]"> + <Publish Event="EndDialog" Value="ErrorIgnore">1</Publish> + </Control> + <Control Id="N" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_No]"> + <Publish Event="EndDialog" Value="ErrorNo">1</Publish> + </Control> + <Control Id="O" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_OK]"> + <Publish Event="EndDialog" Value="ErrorOk">1</Publish> + </Control> + <Control Id="R" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Retry]"> + <Publish Event="EndDialog" Value="ErrorRetry">1</Publish> + </Control> + </Dialog> + <Dialog Id="FilesInUse" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes" KeepModeless="yes"> + <Control Id="Retry" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Retry]"> + <Publish Event="EndDialog" Value="Retry">1</Publish> + </Control> + <Control Id="Ignore" Type="PushButton" X="235" Y="243" Width="56" Height="17" Text="[ButtonText_Ignore]"> + <Publish Event="EndDialog" Value="Ignore">1</Publish> + </Control> + <Control Id="Exit" Type="PushButton" X="166" Y="243" Width="56" Height="17" Text="[ButtonText_Exit]"> + <Publish Event="EndDialog" Value="Exit">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Text" Type="Text" X="20" Y="55" Width="330" Height="30"> + <Text>The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="20" Y="23" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Some files that need to be updated are currently in use.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Files in Use</Text> + </Control> + <Control Id="List" Type="ListBox" X="20" Y="87" Width="330" Height="130" Property="FileInUseProcess" Sunken="yes" TabSkip="yes" /> + </Dialog> + + <Dialog Id="RunningProcessDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes" KeepModeless="yes"> + + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="CustomizeDlg">(InstallMode = "Custom" OR InstallMode = "Change") AND &amp;feaKfwClient &lt;&gt; 3 And !feaKfwClient &lt;&gt; 3</Publish> + <Publish Event="NewDialog" Value="KerberosOptions">(InstallMode = "Custom" OR InstallMode = "Change") AND ( &amp;feaKfwClient = 3 Or !feaKfwClient = 3 )</Publish> + <Publish Event="NewDialog" Value="MaintenanceTypeDlg">InstallMode = "Repair"</Publish> + <Publish Event="NewDialog" Value="SetupTypeDlg">InstallMode = "Typical" OR InstallMode = "Complete"</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Text" Type="Text" X="20" Y="55" Width="330" Height="30"> + <Text>The following applications are currently running and need to be closed in order for the installation to progress. Please close them manually or click Next to let [Wizard] close them for you.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="20" Y="23" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Some running processes need to be closed.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Close Running Proccesses</Text> + </Control> + <Control Id="List" Type="ListBox" X="20" Y="87" Width="330" Height="130" Property="KillableProcesses" Sunken="yes" TabSkip="yes" /> + </Dialog> + + + <Dialog Id="CCPErrorDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes" KeepModeless="yes"> + + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]" Disabled="yes"> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Text="[ButtonText_Finish]"> + <Publish Event="EndDialog" Value="Exit">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Disabled="yes" Text="[ButtonText_Cancel]"> + </Control> + + <Control Id="ErrorText" Type="Text" X="20" Y="70" Width="280" Height="75"> + <Text>[ProductName] requires a newer version of iphlpapi.dll than the one that is currently installed on this computer. This file is included in Microsoft Internet Explorer version 5.01 or later. Please install this and re-run the [ProductName] installer.</Text> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="20" Y="23" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>[ProgramName] requires a newer version of iphlpapi.dll</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Compliance Check Failed!</Text> + </Control> + </Dialog> + + <Dialog Id="LicenseAgreementDlg" Width="370" Height="270" Title="[ProductName] License Agreement" NoMinimize="yes"> + <Control Id="Buttons" Type="RadioButtonGroup" X="20" Y="187" Width="330" Height="40" Property="IAgree" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="WelcomeDlg">1</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="NewDialog" Value="UserRegistrationDlg">IAgree = "Yes" AND ShowUserRegistrationDlg = 1</Publish> + <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish> + <Publish Event="NewDialog" Value="RemovePreviousDlg">IAgree = "Yes" AND ShowUserRegistrationDlg &lt;&gt; 1 AND (UPGRADEPISMERE OR UPGRADEKFW OR UPGRADENSIS &lt;&gt; "")</Publish> + <Publish Event="NewDialog" Value="SetupTypeDlg">IAgree = "Yes" AND ShowUserRegistrationDlg &lt;&gt; 1 AND NOT (UPGRADEPISMERE OR UPGRADEKFW OR UPGRADENSIS &lt;&gt; "")</Publish> + <Condition Action="disable">IAgree &lt;&gt; "Yes"</Condition> + <Condition Action="enable">IAgree = "Yes"</Condition> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="AgreementText" Type="ScrollableText" X="20" Y="60" Width="330" Height="120" Sunken="yes" TabSkip="no"> + <Text src=".\lang\license.rtf"/> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Please read the following license agreement carefully</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]End-User License Agreement</Text> + </Control> + </Dialog> + <Dialog Id="MaintenanceTypeDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="ChangeLabel" Type="Text" X="105" Y="65" Width="100" Height="10" TabSkip="no"> + <Text>[DlgTitleFont]&amp;Modify</Text> + </Control> + <Control Id="ChangeButton" Type="PushButton" X="50" Y="65" Width="38" Height="38" ToolTip="Modify Installation" Default="yes" Icon="yes" FixedSize="yes" IconSize="32" Text="[CustomSetupIcon]"> + <Publish Property="InstallMode" Value="Change">1</Publish> + <Publish Property="Progress1" Value="Changing">1</Publish> + <Publish Property="Progress2" Value="changes">1</Publish> + <Publish Event="NewDialog" Value="CustomizeDlg">1</Publish> + </Control> + <Control Id="RepairLabel" Type="Text" X="105" Y="114" Width="100" Height="10" TabSkip="no"> + <Text>[DlgTitleFont]Re&amp;pair</Text> + </Control> + <Control Id="RepairButton" Type="PushButton" X="50" Y="114" Width="38" Height="38" ToolTip="Repair Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[RepairIcon]"> + <Publish Property="InstallMode" Value="Repair">1</Publish> + <Publish Property="Progress1" Value="Repairing">1</Publish> + <Publish Property="Progress2" Value="repaires">1</Publish> + <Publish Event="NewDialog" Value="VerifyRepairDlg">1</Publish> + </Control> + <Control Id="RemoveLabel" Type="Text" X="105" Y="163" Width="100" Height="10" TabSkip="no"> + <Text>[DlgTitleFont]&amp;Remove</Text> + </Control> + <Control Id="RemoveButton" Type="PushButton" X="50" Y="163" Width="38" Height="38" ToolTip="Remove Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[RemoveIcon]"> + <Publish Property="InstallMode" Value="Remove">1</Publish> + <Publish Property="Progress1" Value="Removing">1</Publish> + <Publish Property="Progress2" Value="removes">1</Publish> + <Publish Event="NewDialog" Value="VerifyRemoveDlg">1</Publish> + </Control> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Next]" /> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Select the operation you wish to perform.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="240" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Modify, Repair or Remove installation</Text> + </Control> + <Control Id="ChangeText" Type="Text" X="105" Y="78" Width="230" Height="20"> + <Text>Allows users to change the way features are installed.</Text> + </Control> + <Control Id="RemoveText" Type="Text" X="105" Y="176" Width="230" Height="20"> + <Text>Removes [ProductName] from your computer.</Text> + </Control> + <Control Id="RepairText" Type="Text" X="105" Y="127" Width="230" Height="30"> + <Text>Repairs errors in the most recent installation state - fixes missing or corrupt files, shortcuts and registry entries.</Text> + </Control> + </Dialog> + <Dialog Id="MaintenanceWelcomeDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish> + <Publish Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>The [Wizard] will allow you to change the way [ProductName] features are installed on your computer or even to remove [ProductName] from your computer. Click Next to continue or Cancel to exit the [Wizard].</Text> + </Control> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}Welcome to the [ProductName] [Wizard]</Text> + </Control> + </Dialog> + <Dialog Id="OutOfDiskDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_OK]"> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Text" Type="Text" X="20" Y="53" Width="330" Height="40"> + <Text>The highlighted volumes do not have enough disk space available for the currently selected features. You can either remove some files from the highlighted volumes, or choose to install less features onto local drive(s), or select different destination drive(s).</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="20" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Disk space required for the installation exceeds available disk space.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Out of Disk Space</Text> + </Control> + <Control Id="VolumeList" Type="VolumeCostList" X="20" Y="100" Width="330" Height="120" Sunken="yes" Fixed="yes" Remote="yes"> + <Text>{120}{70}{70}{70}{70}</Text> + </Control> + </Dialog> + <Dialog Id="OutOfRbDiskDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="No" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_No]"> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="Yes" Type="PushButton" X="240" Y="243" Width="56" Height="17" Text="[ButtonText_Yes]"> + <Publish Event="EnableRollback" Value="False">1</Publish> + <Publish Event="EndDialog" Value="Return">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Text" Type="Text" X="20" Y="53" Width="330" Height="40"> + <Text>The highlighted volumes do not have enough disk space available for the currently selected features. You can either remove some files from the highlighted volumes, or choose to install less features onto local drive(s), or select different destination drive(s).</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="20" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes"> + <Text>Disk space required for the installation exceeds available disk space.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Out of Disk Space</Text> + </Control> + <Control Id="VolumeList" Type="VolumeCostList" X="20" Y="140" Width="330" Height="80" Sunken="yes" Fixed="yes" Remote="yes" ShowRollbackCost="yes"> + <Text>{120}{70}{70}{70}{70}</Text> + </Control> + <Control Id="Text2" Type="Text" X="20" Y="94" Width="330" Height="40"> + <Text>Alternatively, you may choose to disable the installer's rollback functionality. This allows the installer to restore your computer's original state should the installation be interrupted in any way. Click Yes if you wish to take the risk to disable rollback.</Text> + </Control> + </Dialog> + <Dialog Id="RemovePreviousDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Confirm" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Confirm"> + <Publish Event="NewDialog" Value="SetupTypeDlg">1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" FixedSize="yes" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="LicenseAgreementDlg">ShowUserRegistrationDlg &lt;&gt; 1</Publish> + <Publish Event="NewDialog" Value="UserRegistrationDlg">ShowUserRegistrationDlg = 1</Publish> + </Control> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Other versions of [ProductName] need to be removed.</Text> + </Control> + <Control Id="Text" Type="Text" X="25" Y="70" Width="320" Height="45"> + <Text>Click Confirm to uninstall the following version of Kerberos for Windows installed on this computer. Installation of [ProductName] cannot continue unless this program is removed.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Uninstall previous versions</Text> + </Control> + <Control Id="RemoveIcon" Type="Icon" X="25" Y="130" Width="32" Height="32" IconSize="32" Text="[RemoveIcon]" /> + <Control Id="RemoveProductPismere" Type="Text" X="60" Y="146" Width="200" Height="15" Hidden="yes" Transparent="yes" NoPrefix="yes"> + <Text>MIT Project Pismere Kerberos for Windows : Product code [UPGRADEPISMERE]</Text> + <Condition Action="show">UPGRADEPISMERE</Condition> + </Control> + <Control Id="RemoveProductKfw" Type="Text" X="60" Y="146" Width="200" Height="15" Hidden="yes" Transparent="yes" NoPrefix="yes"> + <Text>MIT Kerberos for Windows : Product code [UPGRADEKFW]</Text> + <Condition Action="show">UPGRADEKFW</Condition> + </Control> + <Control Id="RemoveProductKfwNSIS" Type="Text" X="60" Y="146" Width="200" Height="15" Hidden="yes" Transparent="yes" NoPrefix="yes"> + <Text>MIT Kerberos for Windows (NSIS installer): [NSISVERSION]</Text> + <Condition Action="show">UPGRADENSIS &lt;&gt; ""</Condition> + </Control> + </Dialog> + <Dialog Id="ResumeDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Install" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Install]"> + <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace &lt;&gt; 1</Publish> + <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="30" Transparent="yes" NoPrefix="yes"> + <Text>The [Wizard] will complete the installation of [ProductName] on your computer. Click Install to continue or Cancel to exit the [Wizard].</Text> + </Control> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}Resuming the [ProductName] [Wizard]</Text> + </Control> + </Dialog> + <Dialog Id="SetupTypeDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="TypicalLabel" Type="Text" X="105" Y="65" Width="100" Height="10" TabSkip="no"> + <Text>[DlgTitleFont]&amp;Typical</Text> + </Control> + <Control Id="TypicalButton" Type="PushButton" X="50" Y="65" Width="38" Height="38" ToolTip="Typical Installation" Default="yes" Icon="yes" FixedSize="yes" IconSize="32" Text="[InstallerIcon]"> + <Publish Property="InstallMode" Value="Typical">1</Publish> + <Publish Event="SetInstallLevel" Value="50">1</Publish> + <Publish Event="NewDialog" Value="VerifyReadyDlg">Not FoundProcesses</Publish> + <Publish Event="NewDialog" Value="RunningProcessDlg">FoundProcesses</Publish> + </Control> + <Control Id="CustomLabel" Type="Text" X="105" Y="118" Width="100" Height="10" TabSkip="no"> + <Text>[DlgTitleFont]C&amp;ustom</Text> + </Control> + <Control Id="CustomButton" Type="PushButton" X="50" Y="118" Width="38" Height="38" ToolTip="Custom Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[CustomSetupIcon]"> + <Publish Property="InstallMode" Value="Custom">1</Publish> + <Publish Event="NewDialog" Value="CustomizeDlg">1</Publish> + </Control> + <Control Id="CompleteLabel" Type="Text" X="105" Y="171" Width="100" Height="10" TabSkip="no"> + <Text>[DlgTitleFont]C&amp;omplete</Text> + </Control> + <Control Id="CompleteButton" Type="PushButton" X="50" Y="171" Width="38" Height="38" ToolTip="Complete Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[CompleteSetupIcon]"> + <Publish Property="InstallMode" Value="Complete">1</Publish> + <Publish Event="SetInstallLevel" Value="1000">1</Publish> + <Publish Event="NewDialog" Value="VerifyReadyDlg">Not FoundProcesses</Publish> + <Publish Event="NewDialog" Value="RunningProcessDlg">FoundProcesses</Publish> + </Control> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="LicenseAgreementDlg">ShowUserRegistrationDlg &lt;&gt; 1 AND NOT (UPGRADEPISMERE OR UPGRADEKFW)</Publish> + <Publish Event="NewDialog" Value="UserRegistrationDlg">ShowUserRegistrationDlg = 1 AND NOT (UPGRADEPISMERE OR UPGRADEKFW)</Publish> + <Publish Event="NewDialog" Value="RemovePreviousDlg">UPGRADEPISMERE OR UPGRADEKFW OR UPGRADENSIS &lt;&gt; ""</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Next]" /> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Choose the setup type that best suits your needs</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Choose Setup Type</Text> + </Control> + <Control Id="CompleteText" Type="Text" X="105" Y="184" Width="230" Height="20"> + <Text>All program features will be installed. (Requires most disk space)</Text> + </Control> + <Control Id="CustomText" Type="Text" X="105" Y="131" Width="230" Height="30"> + <Text>Allows users to choose which program features will be installed and where they will be installed. Recommended for advanced users.</Text> + </Control> + <Control Id="TypicalText" Type="Text" X="105" Y="78" Width="230" Height="20"> + <Text>Installs the most common program features. Recommended for most users.</Text> + </Control> + </Dialog> + <Dialog Id="UserRegistrationDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="NameLabel" Type="Text" X="45" Y="73" Width="100" Height="15" TabSkip="no" Text="&amp;User Name:" /> + <Control Id="NameEdit" Type="Edit" X="45" Y="85" Width="220" Height="18" Property="USERNAME" Text="{80}" /> + <Control Id="OrganizationLabel" Type="Text" X="45" Y="110" Width="100" Height="15" TabSkip="no" Text="&amp;Organization:" /> + <Control Id="OrganizationEdit" Type="Edit" X="45" Y="122" Width="220" Height="18" Property="COMPANYNAME" Text="{80}" /> + <Control Id="CDKeyLabel" Type="Text" X="45" Y="147" Width="50" Height="10" TabSkip="no"> + <Text>CD &amp;Key:</Text> + </Control> + <Control Id="CDKeyEdit" Type="MaskedEdit" X="45" Y="159" Width="250" Height="16" Property="PIDKEY" Text="[PIDTemplate]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="ValidateProductID" Value="0">0</Publish> + <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish> + <Publish Event="NewDialog" Value="SetupTypeDlg">ProductID</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Please enter your customer information</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Customer Information</Text> + </Control> + </Dialog> + + <Dialog Id="KerberosOptions" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + + <Control Id="txtLeash" Type="Text" X="25" Y="55" Width="280" Height="30"> + <Text>The Network Identity Manager may be installed with the following optional functionality. Please check those items that you wish to activate.</Text> + </Control> + + <Control Id="koAutoStartText" Type="CheckBox" X="25" Y="95" Width="280" Height="30" CheckBoxValue="1" Property="LEASHAUTOSTART" > + <Text>Autostart the Network Identity Manager each time you login to Windows</Text> + </Control> + + <Control Id="koAutoInitText" Type="CheckBox" X="25" Y="130" Width="280" Height="30" CheckBoxValue="-autoinit" Property="LEASHAUTOINIT" > + <Text>Ensure that the Kerberos tickets are available throughout the Windows login session</Text> + </Control> + + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="CustomizeDlg">1</Publish> + </Control> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="NewDialog" Value="VerifyReadyDlg">Not FoundProcesses</Publish> + <Publish Event="NewDialog" Value="RunningProcessDlg">FoundProcesses</Publish> + <Publish Event="AddLocal" Value="feaKfwLeashStartup">LEASHAUTOSTART = 1</Publish> + <Publish Event="Remove" Value="feaKfwLeashStartup">LEASHAUTOSTART &lt;&gt; 1</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>Network Identity Manager startup options</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Kerberos Options</Text> + </Control> + </Dialog> + + <Dialog Id="VerifyReadyDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes" TrackDiskSpace="yes"> + <Control Id="Install" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Install]"> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace &lt;&gt; 1</Publish> + <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="AdminInstallPointDlg">InstallMode = "Server Image"</Publish> + <Publish Event="NewDialog" Value="CustomizeDlg">(InstallMode = "Custom" OR InstallMode = "Change") AND &amp;feaKfwClient &lt;&gt; 3 And !feaKfwClient &lt;&gt; 3</Publish> + <Publish Event="NewDialog" Value="KerberosOptions">(InstallMode = "Custom" OR InstallMode = "Change") AND ( &amp;feaKfwClient = 3 Or !feaKfwClient = 3 )</Publish> + <Publish Event="NewDialog" Value="MaintenanceTypeDlg">InstallMode = "Repair"</Publish> + <Publish Event="NewDialog" Value="SetupTypeDlg">InstallMode = "Typical" OR InstallMode = "Complete"</Publish> + </Control> + <Control Id="Text" Type="Text" X="25" Y="70" Width="320" Height="20"> + <Text>Click Install to begin the installation. If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>The [Wizard] is ready to begin the [InstallMode] installation</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Ready to Install</Text> + </Control> + </Dialog> + <Dialog Id="VerifyRemoveDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes" TrackDiskSpace="yes"> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish> + </Control> + <Control Id="Remove" Type="PushButton" X="236" Y="243" Width="56" Height="17" Text="[ButtonText_Remove]"> + <Publish Event="Remove" Value="All">OutOfDiskSpace &lt;&gt; 1</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace &lt;&gt; 1</Publish> + <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Text" Type="Text" X="25" Y="70" Width="320" Height="30"> + <Text>Click Remove to remove [ProductName] from your computer. If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>You have chosen to remove the program from your computer.</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Remove Kerberos for Windows</Text> + </Control> + </Dialog> + <Dialog Id="VerifyRepairDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes" TrackDiskSpace="yes"> + <Control Id="Repair" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Repair]"> + <Publish Event="ReinstallMode" Value="ecmus">OutOfDiskSpace &lt;&gt; 1</Publish> + <Publish Event="Reinstall" Value="All">OutOfDiskSpace &lt;&gt; 1</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace &lt;&gt; 1</Publish> + <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" TabSkip="no" Text="[BannerBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]"> + <Publish Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish> + </Control> + <Control Id="Text" Type="Text" X="25" Y="70" Width="320" Height="30"> + <Text>Click Repair to repair the installation of [ProductName]. If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.</Text> + </Control> + <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>The [Wizard] is ready to begin the repair of [ProductName].</Text> + </Control> + <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"> + <Text>[DlgTitleFont]Repair Kerberos for Windows</Text> + </Control> + </Dialog> + <Dialog Id="WaitForCostingDlg" Y="10" Width="260" Height="85" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Return" Type="PushButton" X="102" Y="57" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Return]"> + <Publish Event="EndDialog" Value="Exit">1</Publish> + </Control> + <Control Id="Text" Type="Text" X="48" Y="15" Width="194" Height="30"> + <Text>Please wait while the installer finishes determining your disk space requirements.</Text> + </Control> + <Control Id="Icon" Type="Icon" X="15" Y="15" Width="24" Height="24" ToolTip="Exclamation icon" FixedSize="yes" IconSize="32" Text="[ExclamationIcon]" /> + </Dialog> + <Dialog Id="WelcomeDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes"> + <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]"> + <Publish Event="NewDialog" Value="LicenseAgreementDlg">(Installed) Or (CCP_Success = 1)</Publish> + <Publish Event="NewDialog" Value="CCPErrorDlg">(Not Installed) And (CCP_Success &lt;&gt; 1)</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" /> + <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="30" Transparent="yes" NoPrefix="yes"> + <Text>The [Wizard] will install [ProductName] on your computer. Click Next to continue or Cancel to exit the [Wizard].</Text> + </Control> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\VerdanaBold13}Welcome to the [ProductName] [Wizard]</Text> + </Control> + </Dialog> + <RadioButtonGroup Property="IAgree"> + <RadioButton Text="{\DlgFont8}I &amp;accept the terms in the License Agreement" X="5" Y="0" Width="250" Height="15" Value="Yes"></RadioButton> + <RadioButton Text="{\DlgFont8}I &amp;do not accept the terms in the License Agreement" X="5" Y="20" Width="250" Height="15" Value="No"></RadioButton> + </RadioButtonGroup> + <TextStyle Id="DlgFont8" FaceName="Tahoma" Size="8" /> + <TextStyle Id="DlgFontBold8" FaceName="Tahoma" Size="8" Bold="yes" /> + <TextStyle Id="VerdanaBold13" FaceName="Verdana" Size="13" Bold="yes" /> + <UIText Id="AbsentPath" /> + <UIText Id="bytes">bytes</UIText> + <UIText Id="GB">GB</UIText> + <UIText Id="KB">KB</UIText> + <UIText Id="MB">MB</UIText> + <UIText Id="MenuAbsent">Entire feature will be unavailable</UIText> + <UIText Id="MenuAdvertise">Feature will be installed when required</UIText> + <UIText Id="MenuAllCD">Entire feature will be installed to run from CD</UIText> + <UIText Id="MenuAllLocal">Entire feature will be installed on local hard drive</UIText> + <UIText Id="MenuAllNetwork">Entire feature will be installed to run from network</UIText> + <UIText Id="MenuCD">Will be installed to run from CD</UIText> + <UIText Id="MenuLocal">Will be installed on local hard drive</UIText> + <UIText Id="MenuNetwork">Will be installed to run from network</UIText> + <UIText Id="ScriptInProgress">Gathering required information...</UIText> + <UIText Id="SelAbsentAbsent">This feature will remain uninstalled</UIText> + <UIText Id="SelAbsentAdvertise">This feature will be set to be installed when required</UIText> + <UIText Id="SelAbsentCD">This feature will be installed to run from CD</UIText> + <UIText Id="SelAbsentLocal">This feature will be installed on the local hard drive</UIText> + <UIText Id="SelAbsentNetwork">This feature will be installed to run from the network</UIText> + <UIText Id="SelAdvertiseAbsent">This feature will become unavailable</UIText> + <UIText Id="SelAdvertiseAdvertise">Will be installed when required</UIText> + <UIText Id="SelAdvertiseCD">This feature will be available to run from CD</UIText> + <UIText Id="SelAdvertiseLocal">This feature will be installed on your local hard drive</UIText> + <UIText Id="SelAdvertiseNetwork">This feature will be available to run from the network</UIText> + <UIText Id="SelCDAbsent">This feature will be uninstalled completely, you won't be able to run it from CD</UIText> + <UIText Id="SelCDAdvertise">This feature will change from run from CD state to set to be installed when required</UIText> + <UIText Id="SelCDCD">This feature will remain to be run from CD</UIText> + <UIText Id="SelCDLocal">This feature will change from run from CD state to be installed on the local hard drive</UIText> + <UIText Id="SelChildCostNeg">This feature frees up [1] on your hard drive.</UIText> + <UIText Id="SelChildCostPos">This feature requires [1] on your hard drive.</UIText> + <UIText Id="SelCostPending">Compiling cost for this feature...</UIText> + <UIText Id="SelLocalAbsent">This feature will be completely removed</UIText> + <UIText Id="SelLocalAdvertise">This feature will be removed from your local hard drive, but will be set to be installed when required</UIText> + <UIText Id="SelLocalCD">This feature will be removed from your local hard drive, but will be still available to run from CD</UIText> + <UIText Id="SelLocalLocal">This feature will remain on you local hard drive</UIText> + <UIText Id="SelLocalNetwork">This feature will be removed from your local hard drive, but will be still available to run from the network</UIText> + <UIText Id="SelNetworkAbsent">This feature will be uninstalled completely, you won't be able to run it from the network</UIText> + <UIText Id="SelNetworkAdvertise">This feature will change from run from network state to set to be installed when required</UIText> + <UIText Id="SelNetworkLocal">This feature will change from run from network state to be installed on the local hard drive</UIText> + <UIText Id="SelNetworkNetwork">This feature will remain to be run from the network</UIText> + <UIText Id="SelParentCostNegNeg">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</UIText> + <UIText Id="SelParentCostNegPos">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</UIText> + <UIText Id="SelParentCostPosNeg">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</UIText> + <UIText Id="SelParentCostPosPos">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</UIText> + <UIText Id="TimeRemaining">Time remaining: {[1] minutes }{[2] seconds}</UIText> + <UIText Id="VolumeCostAvailable">Available</UIText> + <UIText Id="VolumeCostDifference">Difference</UIText> + <UIText Id="VolumeCostRequired">Required</UIText> + <UIText Id="VolumeCostSize">Disk Size</UIText> + <UIText Id="VolumeCostVolume">Volume</UIText> + <ProgressText Action="InstallValidate">Validating install</ProgressText> + <ProgressText Action="InstallFiles" Template="File: [1], Directory: [9], Size: [6]">Copying new files</ProgressText> + <ProgressText Action="InstallAdminPackage" Template="File: [1], Directory: [9], Size: [6]">Copying network install files</ProgressText> + <ProgressText Action="FileCost">Computing space requirements</ProgressText> + <ProgressText Action="CostInitialize">Computing space requirements</ProgressText> + <ProgressText Action="CostFinalize">Computing space requirements</ProgressText> + <ProgressText Action="CreateShortcuts" Template="Shortcut: [1]">Creating shortcuts</ProgressText> + <ProgressText Action="PublishComponents" Template="Component ID: [1], Qualifier: [2]">Publishing Qualified Components</ProgressText> + <ProgressText Action="PublishFeatures" Template="Feature: [1]">Publishing Product Features</ProgressText> + <ProgressText Action="PublishProduct">Publishing product information</ProgressText> + <ProgressText Action="RegisterClassInfo" Template="Class Id: [1]">Registering Class servers</ProgressText> + <ProgressText Action="RegisterExtensionInfo" Template="Extension: [1]">Registering extension servers</ProgressText> + <ProgressText Action="RegisterMIMEInfo" Template="MIME Content Type: [1], Extension: [2]">Registering MIME info</ProgressText> + <ProgressText Action="RegisterProgIdInfo" Template="ProgId: [1]">Registering program identifiers</ProgressText> + <ProgressText Action="AllocateRegistrySpace" Template="Free space: [1]">Allocating registry space</ProgressText> + <ProgressText Action="AppSearch" Template="Property: [1], Signature: [2]">Searching for installed applications</ProgressText> + <ProgressText Action="BindImage" Template="File: [1]">Binding executables</ProgressText> + <ProgressText Action="CCPSearch">Searching for qualifying products</ProgressText> + <ProgressText Action="CreateFolders" Template="Folder: [1]">Creating folders</ProgressText> + <ProgressText Action="DeleteServices" Template="Service: [1]">Deleting services</ProgressText> + <ProgressText Action="DuplicateFiles" Template="File: [1], Directory: [9], Size: [6]">Creating duplicate files</ProgressText> + <ProgressText Action="FindRelatedProducts" Template="Found application: [1]">Searching for related applications</ProgressText> + <ProgressText Action="InstallODBC">Installing ODBC components</ProgressText> + <ProgressText Action="InstallServices" Template="Service: [2]">Installing new services</ProgressText> + <ProgressText Action="LaunchConditions">Evaluating launch conditions</ProgressText> + <ProgressText Action="MigrateFeatureStates" Template="Application: [1]">Migrating feature states from related applications</ProgressText> + <ProgressText Action="MoveFiles" Template="File: [1], Directory: [9], Size: [6]">Moving files</ProgressText> + <ProgressText Action="PatchFiles" Template="File: [1], Directory: [2], Size: [3]">Patching files</ProgressText> + <ProgressText Action="ProcessComponents">Updating component registration</ProgressText> + <ProgressText Action="RegisterComPlus" Template="AppId: [1]{{, AppType: [2], Users: [3], RSN: [4]}}">Registering COM+ Applications and Components</ProgressText> + <ProgressText Action="RegisterFonts" Template="Font: [1]">Registering fonts</ProgressText> + <ProgressText Action="RegisterProduct" Template="[1]">Registering product</ProgressText> + <ProgressText Action="RegisterTypeLibraries" Template="LibID: [1]">Registering type libraries</ProgressText> + <ProgressText Action="RegisterUser" Template="[1]">Registering user</ProgressText> + <ProgressText Action="RemoveDuplicateFiles" Template="File: [1], Directory: [9]">Removing duplicated files</ProgressText> + <ProgressText Action="RemoveEnvironmentStrings" Template="Name: [1], Value: [2], Action [3]">Updating environment strings</ProgressText> + <ProgressText Action="RemoveExistingProducts" Template="Application: [1], Command line: [2]">Removing applications</ProgressText> + <ProgressText Action="RemoveFiles" Template="File: [1], Directory: [9]">Removing files</ProgressText> + <ProgressText Action="RemoveFolders" Template="Folder: [1]">Removing folders</ProgressText> + <ProgressText Action="RemoveIniValues" Template="File: [1], Section: [2], Key: [3], Value: [4]">Removing INI files entries</ProgressText> + <ProgressText Action="RemoveODBC">Removing ODBC components</ProgressText> + <ProgressText Action="RemoveRegistryValues" Template="Key: [1], Name: [2]">Removing system registry values</ProgressText> + <ProgressText Action="RemoveShortcuts" Template="Shortcut: [1]">Removing shortcuts</ProgressText> + <ProgressText Action="RMCCPSearch">Searching for qualifying products</ProgressText> + <ProgressText Action="SelfRegModules" Template="File: [1], Folder: [2]">Registering modules</ProgressText> + <ProgressText Action="SelfUnregModules" Template="File: [1], Folder: [2]">Unregistering modules</ProgressText> + <ProgressText Action="SetODBCFolders">Initializing ODBC directories</ProgressText> + <ProgressText Action="StartServices" Template="Service: [1]">Starting services</ProgressText> + <ProgressText Action="StopServices" Template="Service: [1]">Stopping services</ProgressText> + <ProgressText Action="UnpublishComponents" Template="Component ID: [1], Qualifier: [2]">Unpublishing Qualified Components</ProgressText> + <ProgressText Action="UnpublishFeatures" Template="Feature: [1]">Unpublishing Product Features</ProgressText> + <ProgressText Action="UnregisterClassInfo" Template="Class Id: [1]">Unregister Class servers</ProgressText> + <ProgressText Action="UnregisterComPlus" Template="AppId: [1]{{, AppType: [2]}}">Unregistering COM+ Applications and Components</ProgressText> + <ProgressText Action="UnregisterExtensionInfo" Template="Extension: [1]">Unregistering extension servers</ProgressText> + <ProgressText Action="UnregisterFonts" Template="Font: [1]">Unregistering fonts</ProgressText> + <ProgressText Action="UnregisterMIMEInfo" Template="MIME Content Type: [1], Extension: [2]">Unregistering MIME info</ProgressText> + <ProgressText Action="UnregisterProgIdInfo" Template="ProgId: [1]">Unregistering program identifiers</ProgressText> + <ProgressText Action="UnregisterTypeLibraries" Template="LibID: [1]">Unregistering type libraries</ProgressText> + <ProgressText Action="WriteEnvironmentStrings" Template="Name: [1], Value: [2], Action [3]">Updating environment strings</ProgressText> + <ProgressText Action="WriteIniValues" Template="File: [1], Section: [2], Key: [3], Value: [4]">Writing INI files values</ProgressText> + <ProgressText Action="WriteRegistryValues" Template="Key: [1], Name: [2], Value: [3]">Writing system registry values</ProgressText> + <ProgressText Action="Advertise">Advertising application</ProgressText> + <ProgressText Action="GenerateScript" Template="[1]">Generating script operations for action:</ProgressText> + <ProgressText Action="InstallSFPCatalogFile" Template="File: [1], Dependencies: [2]">Installing system catalog</ProgressText> + <ProgressText Action="MsiPublishAssemblies" Template="Application Context:[1], Assembly Name:[2]">Publishing assembly information</ProgressText> + <ProgressText Action="MsiUnpublishAssemblies" Template="Application Context:[1], Assembly Name:[2]">Unpublishing assembly information</ProgressText> + <ProgressText Action="Rollback" Template="[1]">Rolling back action:</ProgressText> + <ProgressText Action="RollbackCleanup" Template="File: [1]">Removing backup files</ProgressText> + <ProgressText Action="UnmoveFiles" Template="File: [1], Directory: [9]">Removing moved files</ProgressText> + <ProgressText Action="UnpublishProduct">Unpublishing product information</ProgressText> + <Error Id="0">{{Fatal error: }}</Error> + <Error Id="1">{{Error [1]. }}</Error> + <Error Id="2">Warning [1]. </Error> + <Error Id="3" /> + <Error Id="4">Info [1]. </Error> + <Error Id="5">The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is [1]. {{The arguments are: [2], [3], [4]}}</Error> + <Error Id="6" /> + <Error Id="7">{{Disk full: }}</Error> + <Error Id="8">Action [Time]: [1]. [2]</Error> + <Error Id="9">[ProductName]</Error> + <Error Id="10">{[2]}{, [3]}{, [4]}</Error> + <Error Id="11">Message type: [1], Argument: [2]</Error> + <Error Id="12">=== Logging started: [Date] [Time] ===</Error> + <Error Id="13">=== Logging stopped: [Date] [Time] ===</Error> + <Error Id="14">Action start [Time]: [1].</Error> + <Error Id="15">Action ended [Time]: [1]. Return value [2].</Error> + <Error Id="16">Time remaining: {[1] minutes }{[2] seconds}</Error> + <Error Id="17">Out of memory. Shut down other applications before retrying.</Error> + <Error Id="18">Installer is no longer responding.</Error> + <Error Id="19">Installer stopped prematurely.</Error> + <Error Id="20">Please wait while Windows configures [ProductName]</Error> + <Error Id="21">Gathering required information...</Error> + <Error Id="22">Removing older versions of this application...</Error> + <Error Id="23">Preparing to remove older versions of this application...</Error> + <Error Id="32">{[ProductName] }Setup completed successfully.</Error> + <Error Id="33">{[ProductName] }Setup failed.</Error> + <Error Id="1101">Error reading from file: [2]. {{ System error [3].}} Verify that the file exists and that you can access it.</Error> + <Error Id="1301">Cannot create the file '[2]'. A directory with this name already exists. Cancel the install and try installing to a different location.</Error> + <Error Id="1302">Please insert the disk: [2]</Error> + <Error Id="1303">The installer has insufficient privileges to access this directory: [2]. The installation cannot continue. Log on as administrator or contact your system administrator.</Error> + <Error Id="1304">Error writing to file: [2]. Verify that you have access to that directory.</Error> + <Error Id="1305">Error reading from file [2]. {{ System error [3].}} Verify that the file exists and that you can access it.</Error> + <Error Id="1306">Another application has exclusive access to the file '[2]'. Please shut down all other applications, then click Retry.</Error> + <Error Id="1307">There is not enough disk space to install this file: [2]. Free some disk space and click Retry, or click Cancel to exit.</Error> + <Error Id="1308">Source file not found: [2]. Verify that the file exists and that you can access it.</Error> + <Error Id="1309">Error reading from file: [3]. {{ System error [2].}} Verify that the file exists and that you can access it.</Error> + <Error Id="1310">Error writing to file: [3]. {{ System error [2].}} Verify that you have access to that directory.</Error> + <Error Id="1311">Source file not found{{(cabinet)}}: [2]. Verify that the file exists and that you can access it.</Error> + <Error Id="1312">Cannot create the directory '[2]'. A file with this name already exists. Please rename or remove the file and click retry, or click Cancel to exit.</Error> + <Error Id="1313">The volume [2] is currently unavailable. Please select another.</Error> + <Error Id="1314">The specified path '[2]' is unavailable.</Error> + <Error Id="1315">Unable to write to the specified folder: [2].</Error> + <Error Id="1316">A network error occurred while attempting to read from the file: [2]</Error> + <Error Id="1317">An error occurred while attempting to create the directory: [2]</Error> + <Error Id="1318">A network error occurred while attempting to create the directory: [2]</Error> + <Error Id="1319">A network error occurred while attempting to open the source file cabinet: [2]</Error> + <Error Id="1320">The specified path is too long: [2]</Error> + <Error Id="1321">The Installer has insufficient privileges to modify this file: [2].</Error> + <Error Id="1322">A portion of the folder path '[2]' is invalid. It is either empty or exceeds the length allowed by the system.</Error> + <Error Id="1323">The folder path '[2]' contains words that are not valid in folder paths.</Error> + <Error Id="1324">The folder path '[2]' contains an invalid character.</Error> + <Error Id="1325">'[2]' is not a valid short file name.</Error> + <Error Id="1326">Error getting file security: [3] GetLastError: [2]</Error> + <Error Id="1327">Invalid Drive: [2]</Error> + <Error Id="1328">Error applying patch to file [2]. It has probably been updated by other means, and can no longer be modified by this patch. For more information contact your patch vendor. {{System Error: [3]}}</Error> + <Error Id="1329">A file that is required cannot be installed because the cabinet file [2] is not digitally signed. This may indicate that the cabinet file is corrupt.</Error> + <Error Id="1330">A file that is required cannot be installed because the cabinet file [2] has an invalid digital signature. This may indicate that the cabinet file is corrupt.{{ Error [3] was returned by WinVerifyTrust.}}</Error> + <Error Id="1331">Failed to correctly copy [2] file: CRC error.</Error> + <Error Id="1332">Failed to correctly move [2] file: CRC error.</Error> + <Error Id="1333">Failed to correctly patch [2] file: CRC error.</Error> + <Error Id="1334">The file '[2]' cannot be installed because the file cannot be found in cabinet file '[3]'. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package.</Error> + <Error Id="1335">The cabinet file '[2]' required for this installation is corrupt and cannot be used. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package.</Error> + <Error Id="1336">There was an error creating a temporary file that is needed to complete this installation.{{ Folder: [3]. System error code: [2]}}</Error> + <Error Id="1401">Could not create key: [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel. </Error> + <Error Id="1402">Could not open key: [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel. </Error> + <Error Id="1403">Could not delete value [2] from key [3]. {{ System error [4].}} Verify that you have sufficient access to that key, or contact your support personnel. </Error> + <Error Id="1404">Could not delete key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel. </Error> + <Error Id="1405">Could not read value [2] from key [3]. {{ System error [4].}} Verify that you have sufficient access to that key, or contact your support personnel. </Error> + <Error Id="1406">Could not write value [2] to key [3]. {{ System error [4].}} Verify that you have sufficient access to that key, or contact your support personnel.</Error> + <Error Id="1407">Could not get value names for key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel.</Error> + <Error Id="1408">Could not get sub key names for key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel.</Error> + <Error Id="1409">Could not read security information for key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel.</Error> + <Error Id="1410">Could not increase the available registry space. [2] KB of free registry space is required for the installation of this application.</Error> + <Error Id="1500">Another installation is in progress. You must complete that installation before continuing this one.</Error> + <Error Id="1501">Error accessing secured data. Please make sure the Windows Installer is configured properly and try the install again.</Error> + <Error Id="1502">User '[2]' has previously initiated an install for product '[3]'. That user will need to run that install again before they can use that product. Your current install will now continue.</Error> + <Error Id="1503">User '[2]' has previously initiated an install for product '[3]'. That user will need to run that install again before they can use that product.</Error> + <Error Id="1601">Out of disk space -- Volume: '[2]'; required space: [3] KB; available space: [4] KB. Free some disk space and retry.</Error> + <Error Id="1602">Are you sure you want to cancel?</Error> + <Error Id="1603">The file [2][3] is being held in use{ by the following process: Name: [4], Id: [5], Window Title: '[6]'}. Close that application and retry.</Error> + <Error Id="1604">The product '[2]' is already installed, preventing the installation of this product. The two products are incompatible.</Error> + <Error Id="1605">There is not enough disk space on the volume '[2]' to continue the install with recovery enabled. [3] KB are required, but only [4] KB are available. Click Ignore to continue the install without saving recovery information, click Retry to check for available space again, or click Cancel to quit the installation.</Error> + <Error Id="1606">Could not access network location [2].</Error> + <Error Id="1607">The following applications should be closed before continuing the install:</Error> + <Error Id="1608">Could not find any previously installed compliant products on the machine for installing this product.</Error> + <Error Id="1609">An error occurred while applying security settings. [2] is not a valid user or group. This could be a problem with the package, or a problem connecting to a domain controller on the network. Check your network connection and click Retry, or Cancel to end the install. {{Unable to locate the user's SID, system error [3]}}</Error> + <Error Id="1701">The key [2] is not valid. Verify that you entered the correct key.</Error> + <Error Id="1702">The installer must restart your system before configuration of [2] can continue. Click Yes to restart now or No if you plan to manually restart later.</Error> + <Error Id="1703">You must restart your system for the configuration changes made to [2] to take effect. Click Yes to restart now or No if you plan to manually restart later.</Error> + <Error Id="1704">An installation for [2] is currently suspended. You must undo the changes made by that installation to continue. Do you want to undo those changes?</Error> + <Error Id="1705">A previous installation for this product is in progress. You must undo the changes made by that installation to continue. Do you want to undo those changes?</Error> + <Error Id="1706">An installation package for the product [2] cannot be found. Try the installation again using a valid copy of the installation package '[3]'.</Error> + <Error Id="1707">Installation completed successfully.</Error> + <Error Id="1708">Installation failed.</Error> + <Error Id="1709">Product: [2] -- [3]</Error> + <Error Id="1710">You may either restore your computer to its previous state or continue the install later. Would you like to restore?</Error> + <Error Id="1711">An error occurred while writing installation information to disk. Check to make sure enough disk space is available, and click Retry, or Cancel to end the install.</Error> + <Error Id="1712">One or more of the files required to restore your computer to its previous state could not be found. Restoration will not be possible.</Error> + <Error Id="1713">[2] cannot install one of its required products. Contact your technical support group. {{System Error: [3].}}</Error> + <Error Id="1714">The older version of [2] cannot be removed. Contact your technical support group. {{System Error [3].}}</Error> + <Error Id="1715">Installed [2]</Error> + <Error Id="1716">Configured [2]</Error> + <Error Id="1717">Removed [2]</Error> + <Error Id="1718">File [2] was rejected by digital signature policy.</Error> + <Error Id="1719">The Windows Installer Service could not be accessed. This can occur if you are running Windows in safe mode, or if the Windows Installer is not correctly installed. Contact your support personnel for assistance.</Error> + <Error Id="1720">There is a problem with this Windows Installer package. A script required for this install to complete could not be run. Contact your support personnel or package vendor. {{Custom action [2] script error [3], [4]: [5] Line [6], Column [7], [8] }}</Error> + <Error Id="1721">There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. {{Action: [2], location: [3], command: [4] }}</Error> + <Error Id="1722">There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. {{Action [2], location: [3], command: [4] }}</Error> + <Error Id="1723">There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor. {{Action [2], entry: [3], library: [4] }}</Error> + <Error Id="1724">Removal completed successfully.</Error> + <Error Id="1725">Removal failed.</Error> + <Error Id="1726">Advertisement completed successfully.</Error> + <Error Id="1727">Advertisement failed.</Error> + <Error Id="1728">Configuration completed successfully.</Error> + <Error Id="1729">Configuration failed.</Error> + <Error Id="1730">You must be an Administrator to remove this application. To remove this application, you can log on as an Administrator, or contact your technical support group for assistance.</Error> + <Error Id="1801">The path [2] is not valid. Please specify a valid path.</Error> + <Error Id="1802">Out of memory. Shut down other applications before retrying.</Error> + <Error Id="1803">There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to go back to the previously selected volume.</Error> + <Error Id="1804">There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to return to the browse dialog and select a different volume.</Error> + <Error Id="1805">The folder [2] does not exist. Please enter a path to an existing folder.</Error> + <Error Id="1806">You have insufficient privileges to read this folder.</Error> + <Error Id="1807">A valid destination folder for the install could not be determined.</Error> + <Error Id="1901">Error attempting to read from the source install database: [2].</Error> + <Error Id="1902">Scheduling reboot operation: Renaming file [2] to [3]. Must reboot to complete operation.</Error> + <Error Id="1903">Scheduling reboot operation: Deleting file [2]. Must reboot to complete operation.</Error> + <Error Id="1904">Module [2] failed to register. HRESULT [3]. Contact your support personnel.</Error> + <Error Id="1905">Module [2] failed to unregister. HRESULT [3]. Contact your support personnel.</Error> + <Error Id="1906">Failed to cache package [2]. Error: [3]. Contact your support personnel.</Error> + <Error Id="1907">Could not register font [2]. Verify that you have sufficient permissions to install fonts, and that the system supports this font.</Error> + <Error Id="1908">Could not unregister font [2]. Verify that you that you have sufficient permissions to remove fonts.</Error> + <Error Id="1909">Could not create Shortcut [2]. Verify that the destination folder exists and that you can access it.</Error> + <Error Id="1910">Could not remove Shortcut [2]. Verify that the shortcut file exists and that you can access it.</Error> + <Error Id="1911">Could not register type library for file [2]. Contact your support personnel.</Error> + <Error Id="1912">Could not unregister type library for file [2]. Contact your support personnel.</Error> + <Error Id="1913">Could not update the ini file [2][3]. Verify that the file exists and that you can access it.</Error> + <Error Id="1914">Could not schedule file [2] to replace file [3] on reboot. Verify that you have write permissions to file [3].</Error> + <Error Id="1915">Error removing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.</Error> + <Error Id="1916">Error installing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.</Error> + <Error Id="1917">Error removing ODBC driver: [4], ODBC error [2]: [3]. Verify that you have sufficient privileges to remove ODBC drivers.</Error> + <Error Id="1918">Error installing ODBC driver: [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.</Error> + <Error Id="1919">Error configuring ODBC data source: [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.</Error> + <Error Id="1920">Service '[2]' ([3]) failed to start. Verify that you have sufficient privileges to start system services.</Error> + <Error Id="1921">Service '[2]' ([3]) could not be stopped. Verify that you have sufficient privileges to stop system services.</Error> + <Error Id="1922">Service '[2]' ([3]) could not be deleted. Verify that you have sufficient privileges to remove system services.</Error> + <Error Id="1923">Service '[2]' ([3]) could not be installed. Verify that you have sufficient privileges to install system services.</Error> + <Error Id="1924">Could not update environment variable '[2]'. Verify that you have sufficient privileges to modify environment variables.</Error> + <Error Id="1925">You do not have sufficient privileges to complete this installation for all users of the machine. Log on as administrator and then retry this installation.</Error> + <Error Id="1926">Could not set file security for file '[3]'. Error: [2]. Verify that you have sufficient privileges to modify the security permissions for this file.</Error> + <Error Id="1927">Component Services (COM+ 1.0) are not installed on this computer. This installation requires Component Services in order to complete successfully. Component Services are available on Windows 2000.</Error> + <Error Id="1928">Error registering COM+ Application. Contact your support personnel for more information.</Error> + <Error Id="1929">Error unregistering COM+ Application. Contact your support personnel for more information.</Error> + <Error Id="1930">The description for service '[2]' ([3]) could not be changed.</Error> + <Error Id="1931">The Windows Installer service cannot update the system file [2] because the file is protected by Windows. You may need to update your operating system for this program to work correctly. {{Package version: [3], OS Protected version: [4]}}</Error> + <Error Id="1932">The Windows Installer service cannot update the protected Windows file [2]. {{Package version: [3], OS Protected version: [4], SFP Error: [5]}}</Error> + <Error Id="1933">The Windows Installer service cannot update one or more protected Windows files. {{SFP Error: [2]. List of protected files:\r\n[3]}}</Error> + <Error Id="1934">User installations are disabled via policy on the machine.</Error> + <Error Id="1935">An error occured during the installation of assembly component [2]. HRESULT: [3]. {{assembly interface: [4], function: [5], assembly name: [6]}}</Error> + + <Error Id="4001">Custom action data not found. STATUS [2]</Error> + <Error Id="4003">NSIS Uninstallation failed. Status [2]</Error> + <Error Id="4004">ABORT: [2]</Error> + <Error Id="4005">Custom action failed. Phase [2]</Error> + <Error Id="4006">Failed to determine running processes. Status [2]</Error> + <Error Id="4007">Failed to install Kerberos network provider. Status [2]</Error> + <AdminUISequence> + <Show Dialog="FatalError" OnExit="error" /> + <Show Dialog="UserExit" OnExit="cancel" /> + <Show Dialog="ExitDialog" OnExit="success" /> + <Show Dialog="PrepareDlg" Before="CostInitialize" /> + <Show Dialog="AdminWelcomeDlg" After="CostFinalize" /> + <Show Dialog="ProgressDlg" After="AdminWelcomeDlg" /> + </AdminUISequence> + <InstallUISequence> + <Custom Action="ListRunningProcesses" After="MigrateFeatureStates" /> + <Show Dialog="FatalError" OnExit="error" /> + <Show Dialog="UserExit" OnExit="cancel" /> + <Show Dialog="ExitDialog" OnExit="success" /> + <Show Dialog="PrepareDlg" After="LaunchConditions" /> + <Show Dialog="WelcomeDlg" After="ListRunningProcesses">NOT Installed</Show> + <Show Dialog="ResumeDlg" After="WelcomeDlg">Installed AND (RESUME OR Preselected)</Show> + <Show Dialog="MaintenanceWelcomeDlg" After="ResumeDlg">Installed AND NOT RESUME AND NOT Preselected</Show> + <Show Dialog="ProgressDlg" After="MaintenanceWelcomeDlg" /> + </InstallUISequence> + </UI> + <Property Id="ErrorDialog"><![CDATA[ErrorDlg]]></Property> + <Property Id="DefaultUIFont"><![CDATA[DlgFont8]]></Property> + <Property Id="ButtonText_No"><![CDATA[&No]]></Property> + <Property Id="ButtonText_Install"><![CDATA[&Install]]></Property> + <Property Id="ButtonText_Next"><![CDATA[&Next >]]></Property> + <Property Id="Setup"><![CDATA[Setup]]></Property> + <Property Id="ButtonText_Browse"><![CDATA[Br&owse]]></Property> + <Property Id="CustomSetupIcon"><![CDATA[custicon]]></Property> + <Property Id="RepairIcon"><![CDATA[repairic]]></Property> + <Property Id="ExclamationIcon"><![CDATA[exclamic]]></Property> + <Property Id="ButtonText_Repair"><![CDATA[&Repair]]></Property> + <Property Id="ButtonText_Back"><![CDATA[< &Back]]></Property> + <Property Id="InstallMode"><![CDATA[Typical]]></Property> + <Property Id="Progress2"><![CDATA[installs]]></Property> + <Property Id="Progress1"><![CDATA[Installing]]></Property> + <Property Id="Wizard"><![CDATA[Setup Wizard]]></Property> + <Property Id="RemoveIcon"><![CDATA[removico]]></Property> + <Property Id="ButtonText_Yes"><![CDATA[&Yes]]></Property> + <Property Id="ButtonText_Ignore"><![CDATA[&Ignore]]></Property> + <Property Id="ButtonText_Reset"><![CDATA[&Reset]]></Property> + <Property Id="ButtonText_Refresh"><![CDATA[&Refresh]]></Property> + <Property Id="ButtonText_Remove"><![CDATA[&Remove]]></Property> + <Property Id="ShowUserRegistrationDlg"><![CDATA[0]]></Property> + <Property Id="ButtonText_Exit"><![CDATA[&Exit]]></Property> + <Property Id="ButtonText_Return"><![CDATA[&Return]]></Property> + <Property Id="ButtonText_OK"><![CDATA[OK]]></Property> + <Property Id="CompleteSetupIcon"><![CDATA[completi]]></Property> + <Property Id="ButtonText_Resume"><![CDATA[&Resume]]></Property> + <Property Id="ButtonText_Close"><![CDATA[&Close]]></Property> + <Property Id="InstallerIcon"><![CDATA[insticon]]></Property> + <Property Id="ButtonText_Finish"><![CDATA[&Finish]]></Property> + <Property Id="PROMPTROLLBACKCOST"><![CDATA[P]]></Property> + <Property Id="PIDTemplate"><![CDATA[12345<###-%%%%%%%>@@@@@]]></Property> + <Property Id="DlgTitleFont"><![CDATA[{&DlgFontBold8}]]></Property> + <Property Id="ButtonText_Cancel"><![CDATA[Cancel]]></Property> + <Property Id="InfoIcon"><![CDATA[info]]></Property> + <Property Id="ButtonText_Retry"><![CDATA[&Retry]]></Property> + <Property Id="IAgree"><![CDATA[No]]></Property> + <Property Id="BannerBitmap"><![CDATA[bannrbmp]]></Property> + <Property Id="DialogBitmap"><![CDATA[dlgbmp]]></Property> + <Binary Id="bannrbmp" src="Binary\bannrbmp.bmp" /> + <Binary Id="completi" src="Binary\completi.ico" /> + <Binary Id="custicon" src="Binary\custicon.ico" /> + <Binary Id="dlgbmp" src="Binary\dlgbmp.bmp" /> + <Binary Id="exclamic" src="Binary\exclamic.ico" /> + <Binary Id="info" src="Binary\info.bmp" /> + <Binary Id="insticon" src="Binary\insticon.ico" /> + <Binary Id="New" src="Binary\New.bmp" /> + <Binary Id="removico" src="Binary\removico.ico" /> + <Binary Id="repairic" src="Binary\repairic.ico" /> + <Binary Id="Up" src="Binary\up.bmp" /> +</Include> diff --git a/krb5-1-6/src/windows/installer/wix/msi-deployment-guide.txt b/krb5-1-6/src/windows/installer/wix/msi-deployment-guide.txt new file mode 100644 index 000000000..3a3c28ebc --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/msi-deployment-guide.txt @@ -0,0 +1,946 @@ + +Kerberos for Windows + + MSI Deployment Guide + +---------------------------------------------------------------------- + + Contents + + 1. Introduction + 1.1 Requirements + 1.2 Authoring a Transform + 2. Configuration Options + 2.1 Configurable Properties + 2.1.1 Setting Properties + 2.1.2 Leash GUI Properties + 2.1.3 Leash DLL Properties + 2.1.4 Kerberos IV Properties + 2.1.5 Kerberos V Properties + 2.2 Existing Registry Entries + 2.3 Replacing Configuration Files + 3. Network Identity Manager Settings + 3.1 Common Settings for NetIDMgr + 3.1.1 General Settings + 3.1.2 Common Plug-in Settings + 3.1.3 Settings for the Kerberos 5 Credentials Provider Plug-in + 3.1.4 Settings for the kerberos 4 Credentials Provider Plug-in + 4. Additional Resources + 5. Upgrades + 6. FAQ + +---------------------------------------------------------------------- + +1. Introduction + + Beginning with "Kerberos for Windows" version 2.6.5, a MSI installer + option is available for those who wish to use "Windows Installer" + for installing Kerberos and for organizations that wish to deploy + Kerberos through Group Policy. + + This document provides a guide for authoring transforms used to + customize the MSI package for a particular organization. Although + many settings can be deployed via transforms, in an Active + Directory environment it is advisable to deploy registry settings + and configuration files through group policy and/or startup + scripts so that machines where "Kerberos for Windows" is already + installed will pick up these customizations. + +1.1 Requirements + + The information in this document applies to MSI packages + distributed with "Kerberos for Windows" releases from 2.6.5 and + onwards or MSI packages built from corresponding source + releases. Not all releases support all the configuration options + documented here. + + Authoring a "Windows Installer" transform requires additional + software for editing the MSI database tables and generating the + transform from the modified MSI package. ORCA.EXE and MSITRAN.EXE + which are included in the Windows Platform SDK ("Windows Installer" + SDK) can be used for this purpose. + + For reference, the schema for the MSI package is based on + SCHEMA.MSI distributed with the Platform SDK. + + For general information about "Windows Installer", refer to : + + http://msdn.microsoft.com/library/en-us/msi/setup/windows_installer_start_page.asp + + For general information about authoring MSI transforms, refer to : + + http://msdn.microsoft.com/library/en-us/msi/setup/transforms.asp + + The remainder of this document assumes some familiarity with + authoring transforms. While the MSDN documentation for Windows + Installer is a bit dense, it is recommended that you read through + the guide on MSI transforms found at the second link above. Also + MSDN includes a step-by-step example for creating a transform at: + + http://msdn.microsoft.com/library/en-us/msi/setup/a_customization_transform_example.asp + +1.2 Authoring a Transform + + Transforms describe a set of modifications to be performed on an + existing MSI for the purpose of customizing it. This is + ordinarily done by making a copy of the MSI to be customized, + modifying the copy and then using the old and the new MSI to + generate a transform. + + E.g: + > copy kfw.msi kfw-modified.msi + + (edit the kfw-modified.msi to include the necessary changes) + + > msitran -g kfw.msi kfw-modified.msi kfw-transform.mst + + (generates kfw-transform.mst, which is the transform) + + Transforms have an extension of .mst. 'msitran' is a tool + distributed as part of the "Windows Installer" SDK (which in turn is + a part of the Windows Platform SDK). + + You can test a transform by : + + > copy kfw.msi kfw-test.msi + > msitran -a kfw-transform.mst kfw-test.msi + + and then checking the resulting kfw-test.msi to see if all the + changes you have made above to kfw-modified.msi is present in + kfw-test.msi. 'msitran' will complain if some modification in the + transform can not be successfully applied. + + As mentioned above, you can use a tool like ORCA.EXE to edit the + MSI databases directly when editing kfw-modified.msi. More + details are given below. + +---------------------------------------------------------------------- + +2. Configuration Options + + The logic necessary to implement all of the settings described in + the release notes are present in the MSI. Most of these can be + controlled by setting the corresponding properties to the desired + value. Some settings may require modifying existing registry + entries (though not recommended) or adding new resources (like + files or registry keys). Instructions for performing these tasks + are below. + +2.1 Configurable Properties + + Most configurable properties correspond to registry keys or + values. Please refer to the release notes for more information + about how these registry settings are used. + + Due to the logic invoked based on the existence of these registry + keys or values, they are only set if the associated property is + defined to have a non null value. If the associated property is + not defined in the MSI, the registry key or value will not be + touched. By default, the MSI does not contain these properties + and hence will not set the registry keys. You will need to add + properties as needed to the MSI. + + When one of the configurable properties is set, the installer will + use the property value to set the corresponding setting in the + HKEY_LOCAL_MACHINE registry hive. HKEY_CURRENT_USER hive is not + touched by the installer. + + For each property, the associated registry setting is referenced + by the same text used in the release notes ('Registry and + Environment Settings' section). + + Strings are quoted using single quotes (e.g. 'a string'). An empty + string is denoted as ''. Note that you can't author null values + into the 'Property' table. + + Numeric values should be authored as decimal strings. + +2.1.1 Setting Properties + + In order to set a property, + + a. Open the MSI in ORCA.EXE + + b. Select the 'Property' table from the list of tables on the left. + + c. Find the property in the list of properties on the right, + double click the value and type the new value. + + d. If the property does not exist in the property list, right + click the list and select 'Add Row', type the property name + and the desired value. + +2.1.2 Leash GUI properties + + LEASHAFSSTATUS + Setting: afs token retrieval + Values : '0' or '1' + + LEASHCREATEMISSINGCONFIG + Setting: automatic generation of missing configuration files + Values : '0' or '1' + + LEASHAUTORENEWTICKETS + Setting: automatic ticket renewal + Values : '0' or '1' + + LEASHLOCKFILELOCATIONS + Setting: lock configuration files location + Values : '0' or '1' + + LEASHMSLSAIMPORT + Setting: automatic importation of MSLSA credentials + Values : '0', '1' or '2' + +2.1.3 Leash32 DLL properties + + LEASHLIFETIME + Setting: default lifetime (minutes) + Values : numeric + + LEASHRENEWTILL + Setting: default renew till time (minutes) + Values : numeric + + LEASHRENEWABLE + Setting: default renewable tickets setting + Values : '0' or '1' + + LEASHFORWARDABLE + Setting: default forwardable tickets setting + Values : '0' or '1' + + LEASHNOADDRESSES + Setting: default addressless tickets setting + Values : '0' or '1' + + LEASHPROXIABLE + Setting: default proxiable tickets setting + Values : '0' or '1' + + LEASHPUBLICIP + Setting: default public ipv4 address + Values : numeric + + LEASHUSEKRB4 + Setting: request kerberos iv tickets + Values : '0' or '1' + + LEASHHIDEKINITOPTIONS + Setting: hide advanced kinit options in dialog + Values : '0' or '1' + + LEASHLIFEMIN + Setting: minimum kinit dialog lifetime + Values : numeric + + LEASHLIFEMAX + Setting: maximum kinit dialog lifetime + Values : numeric + + LEASHRENEWMIN + Setting: minimum kinit dialog renew till time + Values : numeric + + LEASHRENEWMAX + Setting: maximum kinit dialog renew till time + Values : numeric + + LEASHUPPERCASEREALM + Setting: upper case realm + Values : '0' or '1' + + LEASHTIMEHOST + Setting: timesync host + Values : string + + LEASHPRESERVEKINITOPTIONS + Setting: Preserve ticket initialization dialog options + Values : numeric + +2.1.4 Kerberos 4 properties + + KRB4KRBREALMS (realms full pathname) + KRB4KRBCONF (config full pathname) + KRB4KRBCONFIDIR (dir for both files) + Setting: location of krbrealm & krbconf + Values : string + (note that the three registry settings are conditioned + independently. I.e. If you only set KRB4KRBCONF, only the + krb.conf setting will be written.) + + KRB4TICKETFILE + Setting: ticket file + Values : string + +2.1.5 Kerberos 5 properties + + KRB5CONFIG + Setting: location of krb5.ini + Values : string + + KRB5CCNAME + Setting: Default credentials cache name + Values : string + + KRB5PRESERVEIDENTITY + Setting: MSLSA: credential cache client principal identity generation + Values : '0' or '1' + +2.2 Existing Registry Entries + + You can change existing registry values subject to the + restrictions mentioned in the Windows Platform SDK. Pay special + attention to component keypaths and try to only change the 'Value' + column in the 'Registry' table. If you want to add additional + registry keys please refer to section 3 (Additional Resources). + +2.3 Replacing Configuration Files + + The Kerberos configuration files (krb5.ini, krb.con, krbrealm.con) + can be replaced by your own configuration files. These files are + contained in separate MSI components so that you can disable them + individually. + + The recommended method for replacing these files is to first + disable the components containing the configuration files that you + want to replace, and then add new components for the replacement + files. This is outlined below (assuming you are using ORCA.EXE to + author the transform). + + Note that transforms are not a good way to add a new file as an + embedded stream. The method outlined here places the file in the + same directory as the MSI for deployment. + + The walkthrough below is to add a custom 'krb5.ini' file. + + 1) Disable the component that contains the configuration file that + you want to replace. + + 1.1) Locate and select the 'Component' table in the 'Tables' + list. + + 1.2) In the Component table, locate the component you need to + change ( Ctrl-F invokes the 'Find' dialog). The component + names are listed below in section 2.3.1. For this + example, the component name is 'cmf_krb5_ini'. + + 1.3) Go to the 'Condition' column of the component. + + 1.4) Enter a condition that evaluates to + false. I.e. 'DONOTINSTALL'. (Note that an undefined + property always evaluates to false). + + Note that you can also use this step to disable other + configuration files without providing replacements. + + 2) Add a new component containing the new configuration file. + + 2.1) Select the 'Component' table in the 'Tables' list. + + 2.2) Select 'Tables'->'Add Row' (Ctrl-R). + + 2.3) Enter the following : + + Component : cmf_my_krb5_ini + ComponentId : {835BAAC6-5E54-BFFE-DBCB2F240711} + Directory_ : WindowsFolder + Attributes : 144 + Condition : + KeyPath : fil_my_krb5_ini + + Note that the ComponentId is an uppercase GUID. You can + generate one using GUIDGEN.EXE or UUIDGEN.EXE, both of + which are included in the Platform SDK. + + The Attributes value of 144 is a sum of + msidbComponentAttributesPermanent (16) and + msidbComponentAttributesNeverOverwrite (128). This + ensures that local modifications are not overwritten or + lost during an installation or uninstallation. These are + the same settings used on the default configuration files. + + 'fil_my_krb5_ini' is a key into the 'File' table which we + will fill later. + + 3) Add a new feature to hold the new component. + + 3.1) Select the 'Feature' table. + + 3.2) Add a new row (Ctrl-R or 'Tables'->'Add Row') with the + following values: + + Feature : fea_my_krb5_ini + Feature_Parent: feaKfwClient + Title : + Description : + Display : 0 + Level : 30 + Directory_ : + Attributes : 8 + + It is important to create the new feature under the + 'feaKfwClient' feature, which will ensure that the + configuration file will be installed when the client + binaries are installed. + + Setting 'Display' to 0 will hide this feature from the + feature selection dialog during an interactive + installation. A value of 30 for 'Level' allows this + feature to be installed by default (on a 'Typical' + installation). + + The 'Attributes' value is + msidbFeatureAttributesDisallowAdvertise (8), which is set + on all features in the KfW MSI. The KfW MSI is not + designed for an advertised installation. + + 4) Join the component and the feature. + + 4.1) Select the 'FeatureComponents' table. + + 4.2) Add a new row with the following values: + + Feature : fea_my_krb5_ini + Component : cmf_my_krb5_ini + + 5) Add an entry to the 'File' table. + + 5.1) Select the 'File' table. + + 5.2) Add a new row with the following values: + + File : fil_my_krb5_ini + Component_ : cmf_my_krb5_ini + FileName : krb5.ini + FileSize : (enter file size here) + ... + Attributes : 8192 + Sequence : 1000 + (leave other fields blank) + + The 'Attributes' value is msidbFileAttributesNonCompressed + (8192). This is because we will be placing this file in + the same directory as the MSI instead of embedding the + file in it. Transforms do not support updating compressed + sources or adding new cabinet streams. + + Finally, the 'Sequence' value of 1000 will be used later + to distinguish the file as being in a separate source + location than the other files in the MSI. + + 6) Set a media source for the file. + + 6.1) Select the 'Media' table. + + 6.2) Add a row with the following values : + + DiskId : 2 + LastSequence : 1000 + ... + (leave other fields blank) + + The sequence number of 1000 designates this as the media + source for the newly added file. + +2.3.1 Components for Configuration Files + + krb5.ini : 'cmf_krb5_ini' (ID {C1AF0670-BBF1-4AA6-B2A6-6C8B1584A1F4}) + krb.con : 'cmf_krb_con' (ID {5391A051-CF14-45FF-BF64-CEE78A7A90C2}) + krbrealm.con: 'cmf_krbrealm_con' (ID {D667B54F-1C98-43FB-87C6-0F0517623B90}) + +---------------------------------------------------------------------- + +3. Network Identity Manager Settings + + Configuration options for Network Identity Manager (NetIDMgr) are + stored in the Windows registry. Each option can exist in the user + registry hive or the machine registry hive or both. The value + defined in the user hive always overrides the value defined in the + machine registry hive. + + All registry keys used by NetIDMgr exist under the key + 'Software\MIT\NetIDMgr' under the user and machine hive. + Deploying a specific configuration option can be achieved by + setting the corresponding registry value either by authoring the + keys into the MSI via a transform or by deploying a registry based + Group Policy Object. For deployment purposes, it is advisable to + deploy values to the machine hive instead of the user hive. + Deploying per user settings via the MSI is not supported at this + time. + +3.1 Common settings for NetIDMgr + + The following sections describe a partial list of options that can + be specified for NetIDMgr. Each set of options is described as a + set of registry values. Each section is preceded by the registry + key under which the values of that section must be specified. + +3.1.1 General settings + + Registry key : 'Software\MIT\NetIDMgr\CredWindow' + -------------- + + Value : AllowAutoRenew + Type : DWORD (Boolean) + Default : 1 + + Enables automatic credential renewal. + + + Value : AllowCritical + Type : DWORD (Boolean) + Default : 1 + + Enables critical warning notifications. + + + Value : AllowWarn + Type : DWORD (Boolean) + Default : 1 + + Enables warning notifications. + + + Value : AutoDetectNet + Type : DWORD (0 or 1) + Default : 1 + + If '1', automatically detects network connectivity changes. + Network connectivity change notifications are then sent out to + individual plug-ins which can perform actions such as renewing + credentials or obtaining new credentials. + + + Value : AutoImport + Type : DWORD (0 or 1) + Default : 1 + + If '1', imports credentials from the Windows LSA cache when + NetIDMgr starts. + + + Value : AutoInit + Type : DWORD (0 or 1) + Default : 0 + + If this value is '1', shows the new credentials dialog if + there are no credentials when NetIDMgr starts. + + + Value : AutoStart + Type : DWORD (0 or 1) + Default : 0 + + Start NetIDMgr when Windows starts + + + Value : AutoRenewThreshold + Type : DWORD (seconds) + Default : 600 + + Specifies the time period before credential expiration that will + trigger a credential renewal. Requires AllowAutoRenew to be enabled. + + + Value : CriticalThreshold + Type : DWORD (seconds) + Default : 300 + + Specifies the time period before credential expiration that will + trigger the second and final warning balloon. Requires AllowCritical + to be enabled. + + + Value : DefaultAllowAutoRenew + Type : DWORD (Boolean) + Default : 1 + + Specifies the Default AllowAutoRenew value for new identities. + + + Value : DefaultSticky + Type : DWORD (0 or 1) + Default : 1 + + If '0', new identities will not be pinned to the display by default. + If '1', new identities will be pinned to the display by default. + + + Value : DefaultWindowMode + Type : DWORD (0 or 1) + Default : 1 + + If '0', Advanced mode is used + If '1', Basic mode is used + + Value : DestroyCredsOnExit + Type : DWORD (0 or 1) + Default : 0 + + If '1', all credentials will be destroyed when NetIDMgr exits. + + Value : KeepRunning + Type : DWORD (0 or 1) + Default : 1 + + If '1', when NetIDMgr application is closed, it will continue + to run in the Windows System Notification Area (System Tray). + The application can be exited by choosing the 'Exit' menu + option. If '0', closing the application will cause it to + exit completely. + + Value : LogToFile + Type : DWORD (0 or 1) + Default : 0 + + If '1', debugging information is logged to %TEMP%\nidmdbg.log + + + Value : NotificationAction + Type : DWORD (50008 or 50025) + Default : 50025 + + If '50025', the default notification icon menu action will be to + Show the Network Identity Manager application windows. + If '50008', the default notification icon menu action will be to + display the Obtain New Credentials dialog. + + + Value : RefreshTimeout + Type : DWORD (seconds) + Default : 60 + + Specifies how often the credential list is refreshed. + + + Value : RenewAtHalfLife + Type : DWORD (Boolean) + Default : 1 + + Enables the use of a half-life algorithm for credential renewals. + + + Value : WarnThreshold + Type : DWORD (seconds) + Default : 900 + + Specifies the time period before credential expiration that will + trigger the first warning balloon. Requires AllowWarn to be enabled. + + +3.1.2 Common Plug-in settings + + Registry key : 'Software\MIT\NetIDMgr\PluginManager\Plugins\<plug-in name>' + -------------- + + The '<plug-in name>' is one of the following for the standard plug-ins : + + Krb5Cred : Kerberos 5 credentials provider + Krb5Ident: Kerberos 5 Identity provider + Krb4Cred : Kerberos 4 credentials provider + + Consult the vendors for the plug-in names of other third party + plug-ins. Additionally, the plug-ins configuration panel in the + NetIDMgr application provides a list of currently registered + plug-ins. + + Value : Disabled + Type : DWORD (0 or 1) + Default : 0 + + If '1', the plug-in will not be loaded. + + Value : NoUnload + Type : DWORD (0 or 1) + Default : 0 + + If '1', the plug-in will not be unloaded from memory when the + NetIDMgr application exits or if the plug-in is stopped. The + plug-in binary will remain loaded until NetIDMgr terminates. + +3.1.3 Settings for the Kerberos 5 credentials provider plug-in + + Registry key : 'Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred\Parameters' + -------------- + + Value : AutoRenewTickets + Type : DWORD (0 or 1) + Default : 1 + + If '1', automatically renews expiring tickets. The thresholds + at which renewals happen are controlled in general NetIDMgr + settings. + + Value : CreateMissingConfig + Type : DWORD (0 or 1) + Default : 0 + + If '1', creates any missing configuration files. + + Value : MsLsaImport + Type : DWORD (0, 1 or 2) + Default : 1 + + Controls how credentials are imported from the MSLSA cache. + This setting can be one of the following. + + 0 : Never + 1 : Always + 2 : Only if the principal matches + + Note that this setting only controls how the Kerberos 5 + plug-in handles importing of credentials from the MSLSA cache. + Whether or not credentials are imported at start-up is + controlled via general NetIDMgr settings as described in + section 3.1.1. + + Value : MsLsaList + Type : DWORD (0 or 1) + Default : 1 + + If '1', includes credentials from the MSLSA cache in the + credentials listing. + + + Value : UseFullRealmList + Type : DWORD (0 or 1) + Default : 0 + + If '1', uses the full realms list as determined by parsing the + krb5.ini configuration file in the new credentials dialog box. + If this is '0', only the last recently used list of realms + will be used. + + +3.1.3.1 Per-identity settings + + Registry key 1: 'Software\MIT\NetIDMgr\KCDB\Identity\<principal name>\Krb5Cred' + Registry key 2: 'Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred\Parameters\Realms\<realm>' + Registry key 3: 'Software\MIT\NetIDMgr\PluginManager\Plugins\Krb5Cred\Parameters' + -------------- + + These settings are generally maintained per-identity. However, if + a particular setting is not specified for an identity or if the + identity is new, then the values will be looked up in the + per-realm configuration key and in the global parameters key in + turn. Global defaults should be set in the global parameters key + (key 3). + + Value : Addressless + Type : DWORD (boolean) + Default : 1 + + Determines if addressless tickets will be obtained for new identities. + + + Value : DefaultLifetime + Type : DWORD + Default : 36000 + + Default ticket lifetime, in seconds. + + Value : DefaultRenewLifetime + Type : DWORD + Default : 604800 + + Default renewable lifetime, in seconds. + + Value : FileCCList + Type : SZ + Default : <not specified> + + Specifies a comma delimited list of FILE credential caches to monitor + for credentials. + + Value : Forwardable + Type : DWORD (0 or 1) + Default : 0 + + Obtain forwardable tickets. + + Value : MaxLifetime + Type : DWORD + Default : 86400 + + Maximum lifetime, in seconds. This value is used to set the + range of the user interface controls that allow setting the + lifetime of a ticket. + + Value : MaxRenewLifetime + Type : DWORD + Default : 2592000 + + Maximum renewable lifetime, in seconds. The value is used to + set the range of the user interface controls that allow + setting the renewable lifetime of a ticket. + + Value : MinLifetime + Type : DWORD + Default : 60 + + Minimum lifetime, in seconds. This value is used to set the + range of the user interface controls that allow setting the + lifetime of a ticket. + + Value : MinRenewLifetime + Type : DWORD + Default : 60 + + Minimum renewable lifetime, in seconds. This value is used to + set the range of the user interface controls that allow + setting the renewable lifetime of a ticket. + + Value : Proxiable + Type : DWORD (0 or 1) + Default : 0 + + Obtain proxiable tickets. + + Value : Renewable + Type : DWORD (0 or 1) + Default : 1 + + Obtain renewable tickets. + + +3.1.4 Settings for the Kerberos 4 Credentials Provider Plug-in + + Registry key 1: 'Software\MIT\NetIDMgr\KCDB\Identity\<principal name>\Krb4Cred' + Registry key 2: 'Software\MIT\NetIDMgr\PluginManager\Plugins\Krb4Cred\Parameters' + --------------- + + Theses settings are also maintained per identity. However, if the + setting is not specified for some identity or if the identity is + new, then the global default will be used (registry key 2). + Global defaults should be set in the second registry key. + + Value : Krb4NewCreds + Type : DWORD (0 or 1) + Default : 1 + + If '1', obtains Kerberos 4 credentials. Note that currently, + only one identity can have Kerberos 4 credentials at one time. + + Value : Krb4Method + Type : DWORD (0, 1 or 2) + Default : 0 + + Method for obtaining Kerberos 4 credentials. The values are + as follows: + + 0 : Automatically determine method + 1 : Use password + 2 : Use Kerberos 5 to 4 translation + + Value : DefaultLifetime + Type : DWORD + Default : 36000 + + The default ticket lifetime, in seconds. + + Value : MaxLifetime + Type : DWORD + Default : 86400 + + Maximum lifetime, in seconds. This value is used to set the + range of the user interface controls that allow setting the + lifetime. + + Value : MinLifetime + Type : DWORD + Default : 60 + + Minimum lifetime, in seconds. This value is used to set the + range of the user interface controls that allow setting the + lifetime. + +---------------------------------------------------------------------- + +4. Additional Resources + + If you want to add registry keys or files you need to create new + components and features for those. + + Add new features under the 'feaKfwClient' feature and set the + 'Level' column for those features to equal the 'Level' for their + parent features for consistency. Note that none of the features + in the "Kerberos for Windows" MSI package are designed to be + installed to run from 'source' or 'advertised'. It is recommended + that you set 'msidbFeatureAttributesFavorLocal' (0), + 'msidbFeatureAttributesFollowParent' (2) and + 'msidbFeatureAttributesDisallowAdvertise' (8) attributes for new + features. + + If you are creating new components, retain the same component GUID + when creating new transforms against new releases of the Kerberos + MSI package. + + It is beyond the scope of this document to provide a comprehensive + overview of how to add new resources through a transform. Please + refer to the "Windows Installer" documentation for details. The + relevant section is at : + + http://msdn.microsoft.com/library/en-us/msi/setup/using_transforms_to_add_resources.asp + + A sample walkthrough of adding a new configuration file is in + section 2.3. + +---------------------------------------------------------------------- + +5. Upgrades + + The MSI package is designed to uninstall previous versions of + "Kerberos for Windows" during installation. Note that it doesn't + directly upgrade an existing installation. This is intentional + and ensures that development releases which do not have strictly + increasing version numbers are properly upgraded. + + Versions of Kerberos that are upgraded by the MSI package are : + + 1) "Kerberos for Windows" 32-bit i386 MSI package + + Upgrade code {61211594-AAA1-4A98-A299-757326763CC7} + Upto current release + + 2) "Kerberos for Windows" 64-bit amd64 MSI package + + Upgrade code {6DA9CD86-6028-4852-8C94-452CAC229244} + Upto current release + + 2) "MIT Project Pismere Kerberos for Windows" MSI package and + "MIT SWRT Kerberos for Windows" MSI + + Upgrade code {83977767-388D-4DF8-BB08-3BF2401635BD} + All versions + + 3) "Kerberos for Windows" NSIS package + + All versions + + Note that versions of the "Kerberos for Windows" NSIS package had + a bug where it couldn't be uninstalled properly in unattended + mode. Therefore the MSI package will not try to uninstall an + "Kerberos for Windows" NSIS package if running unattended. This + means that group policy based deployments will fail on machines + that have the "Kerberos for Windows" NSIS package installed. + + Note that the NSIS package is only available for 32-bit i386. + You cannot install both the 32-bit NSIS and 64-bit amd64 MSI + packages on the same machine. To install both 32-bit and 64-bit + KFW, you must use the MSI packages of both. + + If you have used a different MSI package to install Kerberos for + Windows and wish to upgrade it you can author rows into the + 'Upgrade' table to have the "Kerberos for Windows" MSI replace these + installations for you. + +---------------------------------------------------------------------- + +6. FAQ + + (Q/A's will be added here as needed) + +---------------------------------------------------------------------- +$Id$ + diff --git a/krb5-1-6/src/windows/installer/wix/platform.wxi b/krb5-1-6/src/windows/installer/wix/platform.wxi new file mode 100644 index 000000000..93f173348 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/platform.wxi @@ -0,0 +1,191 @@ +<?xml version="1.0"?> +<Include> +<!-- Platform specific GUID's and other definitions --> +<?if $(var.Platform) = "x64" ?> + <?define UpgradeCode="6DA9CD86-6028-4852-8C94-452CAC229244"?> + <?define cmf_kfwlogon_DLL_guid="CFC0B7C9-9A59-4022-89B3-25E0941D0369"?> + <?define cmf_kfwcpcc_EXE_guid="83F51B6D-F3C6-44cf-AC91-D1D6498FFA44"?> + <?define cmp_ClientSystemDebug_guid="7B25B1E0-A22A-43c7-BA97-C30FCA3B1230"?> + <?define rcm_krb4_1_guid="B3CF770A-2C0F-44c0-8F5B-7B808369D225"?> + <?define rcm_krb4_2_guid="0CF5732A-7659-4cf9-8D01-7E75E6DA2639"?> + <?define rcm_krb4_3_guid="6A279F11-E441-49cb-80F0-3D807D7230DE"?> + <?define rcm_krb4_4_guid="CACB3731-C532-4d28-9E44-FFF35C1376D5"?> + <?define rcm_krb5_1_guid="21883AD6-1C00-4f1d-9922-477CF63CE6BF"?> + <?define rcm_krb5_2_guid="88CEA446-4617-46bc-916F-2AAA1E1EACF8"?> + <?define rcm_krb5_3_guid="28BFF4DB-D09E-4031-AB5D-232F6F707A45"?> + <?define cmf_comerr32_dll_guid="3C34EFDA-3F93-4aa6-AA44-718AA25DD346"?> + <?define cmf_comerr32_dll_name="comerr64.dll"?> + <?define cmf_gss_exe_guid="805EBB97-4860-40d4-A038-5E56717EAFB4"?> + <?define cmf_gss_client_exe_guid="5F192562-436C-4800-93C7-148F7D46F521"?> + <?define cmf_gss_server_exe_guid="33651319-01CB-4f2c-9B96-50F0F53E9CDF"?> + <?define cmf_gssapi32_dll_guid="ACD1D3FA-3E96-47a6-8A39-88BDA2EA3C9D"?> + <?define cmf_gssapi32_dll_name="gssapi64.dll"?> + <?define cmf_k524init_exe_guid="63630B70-D9B1-47bc-905D-E4DFA6F9D0D1"?> + <?define cmf_kclnt32_dll_guid="C26B3CAA-607C-42db-956C-9AA379CCE892"?> + <?define cmf_kclnt32_dll_name="kclnt64.dll"?> + <?define cmf_kdestroy_exe_guid="58AB2858-3513-4e4d-B76C-915B0D0DEE82"?> + <?define cmf_kcpytkt_exe_guid="B2BA9697-4E42-433d-BA85-79A49A622D84"?> + <?define cmf_kdeltkt_exe_guid="998BF60D-75EF-4807-BDA3-7DDE47C4F00F"?> + <?define cmf_kinit_exe_guid="6855B2B9-D3EB-42ce-B0EA-EFCD5960B635"?> + <?define cmf_klist_exe_guid="1AE98193-6596-4460-9B42-15C734E28CE8"?> + <?define cmf_kpasswd_exe_guid="669A2965-413F-4003-9F43-4615CC7C3B1A"?> + <?define cmf_kvno_exe_guid="56C95EBA-2A53-4567-AA44-9A0EE01BB390"?> + <?define cmf_krb5_32_dll_guid="8B7190D6-76BD-442b-893B-1EED4E26EC0A"?> + <?define cmf_krb5_32_dll_name="krb5_64.dll"?> + <?define cmf_k5sprt32_dll_guid="2DD8CE7D-8C8E-4cfb-BC73-765858DD1418"?> + <?define cmf_k5sprt32_dll_name="k5sprt64.dll"?> + <?define cmf_krb524_dll_guid="4FAFB2A6-FC42-466b-9A86-42C3150252E2"?> + <?define cmf_krb524_dll_name="krb524.dll"?> + <?define cmf_krbcc32_dll_guid="56DAD1B9-4A59-46e6-81CA-54E2B6C9D618"?> + <?define cmf_krbcc32_dll_name="krbcc64.dll"?> + <?define cmf_krbcc32s_exe_guid="0192F58B-9129-426d-A271-E18455EDC80E"?> + <?define cmf_krbcc32s_exe_name="krbcc64s.exe"?> + <?define cmf_krbv4w32_dll_guid="D195FADB-A3B0-4023-A824-8895552CDC56"?> + <?define cmf_krbv4w32_dll_name="krbv4w64.dll"?> + <?define cmf_leash32_exe_guid="D195FADB-A3B0-4023-A824-8895552CDC56"?> + <?define csc_leash32_exe_guid="9D43350A-A8AE-4405-AB82-64E90E5A1A70"?> + <?define rcm_leash_1_guid="7E5517FF-FB76-431f-A92B-2895C9BE7E98"?> + <?define rcm_leash_2_guid="008208AC-46BE-4ca4-BEA7-8FCAAD8BA7C3"?> + <?define rcm_leash_3_guid="008208AC-46BE-4ca4-BEA7-8FCAAD8BA7C3"?> + <?define rcm_leash_4_guid="D20180CC-B68D-4a6d-95E4-5EB07B9EADCD"?> + <?define rcm_leash_5_guid="AF3B73AE-86ED-42f5-987A-9831B8799D2F"?> + <?define rcm_leash_6_guid="0C72D4F8-096B-4295-8F0A-6B5723A8593D"?> + <?define csc_LeashStartup_guid="228192C5-D847-4c46-A726-0E8211742349"?> + <?define cmf_leash32_hlp_guid="228192C5-D847-4c46-A726-0E8211742349"?> + <?define cmf_leash32_chm_guid="769B54EB-9B96-4abe-9B72-9EF346C8C03D"?> + <?define cmf_leashw32_dll_guid="7222B9E1-EE70-4ccb-929F-43D45574AA83"?> + <?define cmf_leashw32_dll_name="leashw64.dll"?> + <?define rcm_leashdll_1_guid="64BC62DF-F1D6-423a-B4E0-E75E214BAC26"?> + <?define rcm_leashdll_2_guid="64BC62DF-F1D6-423a-B4E0-E75E214BAC26"?> + <?define rcm_leashdll_3_guid="64BC62DF-F1D6-423a-B4E0-E75E214BAC26"?> + <?define rcm_leashdll_4_guid="989B5FC5-63DC-47d6-BBBC-EE1B355127F6"?> + <?define rcm_leashdll_5_guid="989B5FC5-63DC-47d6-BBBC-EE1B355127F6"?> + <?define rcm_leashdll_6_guid="AC35CE64-9D8D-4a21-AB1F-18803C69E7B4"?> + <?define rcm_leashdll_7_guid="02014C27-BAC8-4b86-95F8-43F9BF55064A"?> + <?define rcm_leashdll_8_guid="DE70F57C-D3F8-4c1d-B868-A77DA04D9DD3"?> + <?define rcm_leashdll_9_guid="A809042D-66F3-4a6a-B8EC-77C40C88F3E3"?> + <?define rcm_leashdll_10_guid="E61875A4-F33C-419f-97B8-D2ACA3EBD4BB"?> + <?define rcm_leashdll_11_guid="3732992E-34C4-430a-B081-C8601BA44A61"?> + <?define rcm_leashdll_12_guid="2237072A-1955-4ca4-ABB3-78037E16F696"?> + <?define rcm_leashdll_13_guid="6F626DB7-B0A6-4c1d-889E-A2DA742DFC4B"?> + <?define rcm_leashdll_14_guid="109674B4-7390-49cc-9DB1-B9402E4C5645"?> + <?define rcm_leashdll_15_guid="8AC8500D-2279-4a3c-82E9-4C0ED79A6EFC"?> + <?define rcm_leashdll_16_guid="ED6BD7FE-7879-4da6-882D-98DEF6198F60"?> + <?define rcm_leashdll_17_guid="E5F8A4DF-442E-4d24-B5E2-9F36A4F7E15D"?> + <?define cmf_ms2mit_exe_guid="8AEC1FDA-4A45-4878-8C0B-465D46ACE306"?> + <?define cmf_mit2ms_exe_guid="3CE7BAE8-22DA-4911-B370-4C700861BDFD"?> + <?define cmf_wshelp32_dll_guid="24648FE7-D952-499c-8023-AFE4C7E52296"?> + <?define cmf_wshelp32_dll_name="wshelp64.dll"?> + <?define cmf_xpprof32_dll_guid="B1112677-50A4-4430-846B-F824C859E3DF"?> + <?define cmf_xpprof32_dll_name="xpprof64.dll"?> + <?define cmf_nidmgr32_dll_guid="8538212A-9BD5-4d62-BF29-36D853385F0A"?> + <?define cmf_nidmgr32_dll_name="nidmgr64.dll"?> + <?define cmf_nidmgr32_dll_w2k_guid="01655D48-C596-48f8-A0C3-5DB3FC833444"?> + <?define cmf_krb5cred_dll_guid="CC182AB1-E333-4501-8DEA-5A8D4FD36D0D"?> + <?define cmf_krb5cred_dll_name="krb5cred.dll"?> + <?define cmf_krb5cred_en_us_dll_guid="223B7E9D-290F-40b8-89B3-F8337A8E082D"?> + <?define cmf_krb5cred_en_us_dll_name="krb5cred_en_us.dll"?> + <?define cmf_krb4cred_dll_guid="AF3DB848-786B-4e0b-9D8F-F9074D0631F2"?> + <?define cmf_krb4cred_dll_name="krb4cred.dll"?> + <?define cmf_krb4cred_en_us_dll_guid="4D180CEF-59CD-4c39-872C-F84F58008107"?> + <?define cmf_krb4cred_en_us_dll_name="krb4cred_en_us.dll"?> + <?define cmf_netidmgr_exe_guid="487545C9-F145-4fb9-8610-5652A6C3FE48"?> + <?define cmf_netidmgr_exe_w2k_guid="F9D3A2A1-8BAE-41ff-BB50-2E6923D3368B"?> + <?define csc_NetIDMgrStartup_guid="7081976D-E9D5-424a-9564-917E0529E4D0"?> + <?define cmf_bin_debug_guid="F3432C85-89D9-4bd6-BD82-4ED49A118338"?> +<?elseif $(var.Platform) = "Intel"?> + <?define UpgradeCode="61211594-AAA1-4A98-A299-757326763CC7"?> + <?define cmf_kfwlogon_DLL_guid="2F104FEB-2D61-458A-BAE3-B153F151E728"?> + <?define cmf_kfwcpcc_EXE_guid="C3284E7A-3665-45A6-B64E-C909B1D1BAA6"?> + <?define cmp_ClientSystemDebug_guid="2D13ED48-53C2-4878-B196-2AD7F4100998"?> + <?define rcm_krb4_1_guid="34262966-9196-49D6-86C9-AE98D3116DC0"?> + <?define rcm_krb4_2_guid="812334C6-EBDF-482C-8CB3-A6398AF9EDFC"?> + <?define rcm_krb4_3_guid="5556ECD9-8721-41C2-846C-034C239B48F1"?> + <?define rcm_krb4_4_guid="61371A93-7F59-439D-A89C-070E100F465B"?> + <?define rcm_krb5_1_guid="E190F8B9-51FA-4FB1-884C-C8AFA37F8653"?> + <?define rcm_krb5_2_guid="AE7D4305-6193-4094-8C82-73862AE01DCE"?> + <?define rcm_krb5_3_guid="853EE035-99AA-489A-8FB6-74C76624E92A"?> + <?define cmf_comerr32_dll_guid="D8F455F9-E648-4C61-A69D-7116ADEC2DBB"?> + <?define cmf_comerr32_dll_name="comerr32.dll"?> + <?define cmf_gss_exe_guid="8CAF09C4-68A2-46DC-A618-AEF16D832E54"?> + <?define cmf_gss_client_exe_guid="983E0887-0C8B-49AB-8F59-DFE3A4E45E89"?> + <?define cmf_gss_server_exe_guid="B165FE41-D0DD-4DFC-92E6-A99ADA23BE8B"?> + <?define cmf_gssapi32_dll_guid="5B0F2989-BB85-40BF-BB7A-E77693972CF9"?> + <?define cmf_gssapi32_dll_name="gssapi32.dll"?> + <?define cmf_k524init_exe_guid="20BE4EA5-C465-4AF3-9A4F-BB80934167E3"?> + <?define cmf_kclnt32_dll_guid="D396C1E7-080E-49F5-92BA-73BCEDF09C8E"?> + <?define cmf_kclnt32_dll_name="kclnt32.dll"?> + <?define cmf_kdestroy_exe_guid="D1E9C111-7760-4EE6-86CF-D4B4064B0ABA"?> + <?define cmf_kcpytkt_exe_guid="6B20E57C-0033-4dcf-B3C9-74ED0B2CF46E"?> + <?define cmf_kdeltkt_exe_guid="C7528C87-9B61-439a-8EA8-AD4BE3D758F9"?> + <?define cmf_kinit_exe_guid="80643A09-EF28-4714-BC62-B64FC5B17CAA"?> + <?define cmf_klist_exe_guid="24FB6003-BC7A-4BF1-9503-82D398EC02D7"?> + <?define cmf_kpasswd_exe_guid="3FA4AB96-FF12-460A-814E-3380E220787C"?> + <?define cmf_kvno_exe_guid="7759D524-1F88-4483-975F-DDD33A511512"?> + <?define cmf_krb5_32_dll_guid="31E40356-CBAC-4FC6-9A34-C6F6C72A27CA"?> + <?define cmf_krb5_32_dll_name="krb5_32.dll"?> + <?define cmf_k5sprt32_dll_guid="F2381331-9201-4c02-866F-2038676771D4"?> + <?define cmf_k5sprt32_dll_name="k5sprt32.dll"?> + <?define cmf_krb524_dll_guid="98685874-A9AA-4BC5-9830-271D9CF52C17"?> + <?define cmf_krb524_dll_name="krb524.dll"?> + <?define cmf_krbcc32_dll_guid="A50FA27D-F203-4C19-9047-B7976171FB94"?> + <?define cmf_krbcc32_dll_name="krbcc32.dll"?> + <?define cmf_krbcc32s_exe_guid="7D5F0817-DACF-4B54-BB8D-94DD63626DB5"?> + <?define cmf_krbcc32s_exe_name="krbcc32s.exe"?> + <?define cmf_krbv4w32_dll_guid="DFA23F6C-5297-4876-AF52-6F7CF2CB34AC"?> + <?define cmf_krbv4w32_dll_name="krbv4w32.dll"?> + <?define cmf_leash32_exe_guid="990D5F6B-4CEE-4706-96F4-F7AF12F97DF7"?> + <?define csc_leash32_exe_guid="8A096700-47B1-4A0B-B7B5-44F75086DEAE"?> + <?define rcm_leash_1_guid="B91648A0-26F7-43BB-A954-202FF3811E3C"?> + <?define rcm_leash_2_guid="0D8DCC52-F855-4C46-86A1-198E6EE0CB8A"?> + <?define rcm_leash_3_guid="9610A7E3-251F-4286-B776-1C3AF5DE7815"?> + <?define rcm_leash_4_guid="815AED84-2437-4EBC-B561-F847833DB3A5"?> + <?define rcm_leash_5_guid="A0D3D75F-762E-4D5C-909B-53E7396CEDB6"?> + <?define rcm_leash_6_guid="F675C145-6F9D-4BC4-9DA0-CAFB47A96A71"?> + <?define csc_LeashStartup_guid="0DF73BCD-F34E-4B01-AA71-0EE08EB62F70"?> + <?define cmf_leash32_hlp_guid="919616D6-1605-4A79-8E33-C18A0D0F25E3"?> + <?define cmf_leash32_chm_guid="C50E5E0A-B822-4419-855B-1713637BCA6A"?> + <?define cmf_leashw32_dll_guid="8C145D48-A2FC-4C28-BC05-4368545F1184"?> + <?define cmf_leashw32_dll_name="leashw32.dll"?> + <?define rcm_leashdll_1_guid="54C949DA-AF1E-4412-81AF-F502BD5904D2"?> + <?define rcm_leashdll_2_guid="9B553794-45E7-49FB-B6D9-1C3C9BB6E00D"?> + <?define rcm_leashdll_3_guid="E3D1284C-17F6-41E3-9AA7-2ED05432060F"?> + <?define rcm_leashdll_4_guid="A02831D5-48B2-4E82-A670-EDCEBC197273"?> + <?define rcm_leashdll_5_guid="5FDB0C01-6668-43E3-9C83-2CD364D97BF3"?> + <?define rcm_leashdll_6_guid="999BD59C-5C1E-446E-9D38-F4E26DD27D09"?> + <?define rcm_leashdll_7_guid="C908AA17-DD21-4193-BA1D-535A2FD3D803"?> + <?define rcm_leashdll_8_guid="02926245-2327-46F9-AEF6-89E2DB0D90E1"?> + <?define rcm_leashdll_9_guid="B45BBA29-7A67-4FF7-AAA4-80044D46C451"?> + <?define rcm_leashdll_10_guid="1DDC4D78-BDB4-48CD-A4E9-024FA9706100"?> + <?define rcm_leashdll_11_guid="39134333-58C7-4C6B-B690-2322D3AE928A"?> + <?define rcm_leashdll_12_guid="BBB6F5C3-290F-4A21-A630-E8630C6EAB67"?> + <?define rcm_leashdll_13_guid="0F86A73E-DB31-45E7-9156-BE0EC99076A7"?> + <?define rcm_leashdll_14_guid="FE0F06A2-62E7-46C1-9BFF-337C50DB78C7"?> + <?define rcm_leashdll_15_guid="2DAC4693-6435-4278-A584-3D2B74BE87D5"?> + <?define rcm_leashdll_16_guid="FE3DDD47-CCDE-44F8-8C86-97F2C3545443"?> + <?define rcm_leashdll_17_guid="1B685E1B-32F2-49A5-9B7D-4288741A2C17"?> + <?define cmf_ms2mit_exe_guid="63D189DC-5EE4-49E2-B5E9-6E74A28602C8"?> + <?define cmf_mit2ms_exe_guid="4F487781-5B55-48c1-A3FA-8BC6ECA4FEA1"?> + <?define cmf_wshelp32_dll_guid="B9D9F5F1-CA93-4F56-B6F8-343F21484CDE"?> + <?define cmf_wshelp32_dll_name="wshelp32.dll"?> + <?define cmf_xpprof32_dll_guid="A7DF8BAF-7188-4C24-89FB-C8EB51571FD2"?> + <?define cmf_xpprof32_dll_name="xpprof32.dll"?> + <?define cmf_nidmgr32_dll_guid="EEBA3A0D-CE3D-42F1-8854-D7F63F597202"?> + <?define cmf_nidmgr32_dll_name="nidmgr32.dll"?> + <?define cmf_nidmgr32_dll_w2k_guid="33F42D7C-03CE-465F-9E0A-5F486FE64B04"?> + <?define cmf_krb5cred_dll_guid="27A7723A-F0D9-4F06-892C-54F0AC6014C3"?> + <?define cmf_krb5cred_dll_name="krb5cred.dll"?> + <?define cmf_krb5cred_en_us_dll_guid="EA9ABE05-A85B-43BB-8741-50D3C3128632"?> + <?define cmf_krb5cred_en_us_dll_name="krb5cred_en_us.dll"?> + <?define cmf_krb4cred_dll_guid="E3B86954-9D5D-4929-A5E6-B22ED03E6D6C"?> + <?define cmf_krb4cred_dll_name="krb4cred.dll"?> + <?define cmf_krb4cred_en_us_dll_guid="3FF40A29-E2C3-40F3-B81C-2948494BE4B0"?> + <?define cmf_krb4cred_en_us_dll_name="krb4cred_en_us.dll"?> + <?define cmf_netidmgr_exe_guid="AEB06D67-B4F3-45B1-AC1E-5C1AFF747756"?> + <?define cmf_netidmgr_exe_w2k_guid="0F85D4F3-7897-4FE3-8501-AD0C383CCB4F"?> + <?define csc_NetIDMgrStartup_guid="669227E3-0ADC-4173-90C3-631FCFC8EBC3"?> + <?define cmf_bin_debug_guid="C8468854-8261-4781-8119-A612636841E3"?> +<?else?> + <?error Unknown platform?> +<?endif?> +</Include> diff --git a/krb5-1-6/src/windows/installer/wix/property.wxi b/krb5-1-6/src/windows/installer/wix/property.wxi new file mode 100644 index 000000000..b392333fc --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/property.wxi @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + + Copyright (C) 2004, 2005, 2006 by the Massachusetts Institute of Technology. + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + --> +<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> + + <!-- Important: This product should only be installed in all-user mode --> + <Property Id="ALLUSERS">1</Property> + + <Property Id="LEASHAUTOINIT" Admin="yes" Secure="yes">-autoinit</Property> + <Property Id="LEASHAUTOSTART" Admin="yes" Secure="yes">1</Property> + + <Property Id="ARPCOMMENTS">$(var.ARPComments)</Property> + <Property Id="ARPCONTACT">kerberos@mit.edu</Property> + <Property Id="ARPURLINFOABOUT">http://web.mit.edu/kerberos</Property> + <Property Id="ARPHELPLINK">http://web.mit.edu/kerberos</Property> + <Property Id="INSTALLLEVEL">50</Property> + <Property Id="ComponentDownload">http://web.mit.edu/kerberos</Property> + + <Property Id="UPGRADENSIS"> + <RegistrySearch Id="regsrch_NSIS" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Kerberos for Windows" Name="UninstallString" Type="file"/> + </Property> + + <Property Id="NSISVERSION"> + <RegistrySearch Id="regsrch_NSISV" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Kerberos for Windows" Name="DisplayVersion" Type="raw" /> + </Property> + + <Property Id="CantRemoveNSISError">$(loc.CantRemoveNSIS)</Property> + <Property Id="NoIE501Error">$(loc.IE501Required)</Property> + + <!-- Additional properties relating to the UI are in the appropriate UI.wxi file --> + + <!-- Configuration properties. If these properties are defined, then + the corresponding component will be enabled. If the corresponding + variable value is the empty string (""), then the properties will + not be defined. --> +<?ifdef UseDefaultProperties?> + <Property Id="LEASHAFSSTATUS" Admin="yes" Secure="yes">$(var.LeashAfsStatus)</Property> + <Property Id="LEASHCREATEMISSINGCONFIG" Admin="yes" Secure="yes">$(var.LeashCreateMissingConfig)</Property> + <Property Id="LEASHAUTORENEWTICKETS" Admin="yes" Secure="yes">$(var.LeashAutoRenewTickets)</Property> + <Property Id="LEASHLOCKFILELOCATIONS" Admin="yes" Secure="yes">$(var.LeashLockFileLocations)</Property> + <Property Id="LEASHMSLSAIMPORT" Admin="yes" Secure="yes">$(var.LeashMsLsaImport)</Property> + <Property Id="LEASHLIFETIME" Admin="yes" Secure="yes">$(var.LeashLifetime)</Property> + <Property Id="LEASHRENEWTILL" Admin="yes" Secure="yes">$(var.LeashRenewTill)</Property> + <Property Id="LEASHRENEWABLE" Admin="yes" Secure="yes">$(var.LeashRenewable)</Property> + <Property Id="LEASHFORWARDABLE" Admin="yes" Secure="yes">$(var.LeashForwardable)</Property> + <Property Id="LEASHNOADDRESSES" Admin="yes" Secure="yes">$(var.LeashNoAddresses)</Property> + <Property Id="LEASHPROXIABLE" Admin="yes" Secure="yes">$(var.LeashProxiable)</Property> + <Property Id="LEASHPUBLICIP" Admin="yes" Secure="yes">$(var.LeashPublicIp)</Property> + <Property Id="LEASHUSEKRB4" Admin="yes" Secure="yes">$(var.LeashUseKrb4)</Property> + <Property Id="LEASHHIDEKINITOPTIONS" Admin="yes" Secure="yes">$(var.LeashHideKinitOptions)</Property> + <Property Id="LEASHLIFEMIN" Admin="yes" Secure="yes">$(var.LeashLifeMin)</Property> + <Property Id="LEASHLIFEMAX" Admin="yes" Secure="yes">$(var.LeashLifeMax)</Property> + <Property Id="LEASHRENEWMIN" Admin="yes" Secure="yes">$(var.LeashRenewMin)</Property> + <Property Id="LEASHRENEWMAX" Admin="yes" Secure="yes">$(var.LeashRenewMax)</Property> + <Property Id="LEASHUPPERCASEREALM" Admin="yes" Secure="yes">$(var.LeashUppercaseRealm)</Property> + <Property Id="LEASHTIMEHOST" Admin="yes" Secure="yes">$(var.LeashTimeHost)</Property> + <Property Id="LEASHPRESERVEKINITOPTIONS" Admin="yes" Secure="yes">$(var.LeashPreserveKinitOptions)</Property> + <Property Id="KRB4KRBREALMS" Admin="yes" Secure="yes">$(var.Krb4KrbRealms)</Property> + <Property Id="KRB4KRBCONF" Admin="yes" Secure="yes">$(var.Krb4KrbConf)</Property> + <Property Id="KRB4CONFIGDIR" Admin="yes" Secure="yes">$(var.Krb4ConfigDir)</Property> + <Property Id="KRB4TICKETFILE" Admin="yes" Secure="yes">$(var.Krb4TicketFile)</Property> + <Property Id="KRB5CONFIG" Admin="yes" Secure="yes">$(var.Krb5Config)</Property> + <Property Id="KRB5CCNAME" Admin="yes" Secure="yes">$(var.Krb5CcName)</Property> + <Property Id="KRB5PRESERVEIDENTITY" Admin="yes" Secure="yes">$(var.Krb5PreserveIdentity)</Property> +<?endif?> +<?ifdef UseLeash?> + <Property Id="USELEASH" Admin="yes" Secure="yes">$(var.UseLeash)</Property> +<?endif?> +<?ifdef UseNetIDMgr?> + <Property Id="USENETIDMGR" Admin="yes" Secure="yes">$(var.UseNetIDMgr)</Property> +<?endif?> +</Include> \ No newline at end of file diff --git a/krb5-1-6/src/windows/installer/wix/runtime.wxi b/krb5-1-6/src/windows/installer/wix/runtime.wxi new file mode 100644 index 000000000..7b09fea2c --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/runtime.wxi @@ -0,0 +1,90 @@ +<?xml version="1.0"?> +<Include> + <?ifdef CL1400 ?> + <MergeRef Id="MSVCRT8MEM"/> + <MergeRef Id="MSVCRT8POL"/> + <MergeRef Id="MSVCRT8MFC"/> + <MergeRef Id="MSVCRT8PFC"/> + <MergeRef Id="MSVCRT8MFL"/> + <MergeRef Id="MSVCRT8PFL"/> + <?endif?> +<?ifndef Debug?> + <?ifdef CL1310 ?> + <?ifdef comment?> + <MergeRef Id="mergeVC1310LibMFC" /> + <MergeRef Id="mergeVC1310LibCRT" /> + <?else?> + <ComponentRef Id="cmf_mfc71_dll" /> + <ComponentRef Id="cmf_msvcr71_dll" /> + <ComponentRef Id="cmf_msvcp71_dll" /> + <ComponentRef Id="cmf_mfc71chs_dll" /> + <ComponentRef Id="cmf_mfc71cht_dll" /> + <ComponentRef Id="cmf_mfc71deu_dll" /> + <ComponentRef Id="cmf_mfc71enu_dll" /> + <ComponentRef Id="cmf_mfc71esp_dll" /> + <ComponentRef Id="cmf_mfc71fra_dll" /> + <ComponentRef Id="cmf_mfc71ita_dll" /> + <ComponentRef Id="cmf_mfc71jpn_dll" /> + <ComponentRef Id="cmf_mfc71kor_dll" /> + <?endif?> + <?endif?> + <?ifdef CL1300 ?> + <?ifdef comment?> + <MergeRef Id="mergeVC1300LibMFC" /> + <MergeRef Id="mergeVC1300LibCRT" /> + <?else?> + <ComponentRef Id="cmf_mfc70_dll" /> + <ComponentRef Id="cmf_msvcr70_dll" /> + <ComponentRef Id="cmf_msvcp70_dll" /> + <ComponentRef Id="cmf_mfc70chs_dll" /> + <ComponentRef Id="cmf_mfc70cht_dll" /> + <ComponentRef Id="cmf_mfc70deu_dll" /> + <ComponentRef Id="cmf_mfc70enu_dll" /> + <ComponentRef Id="cmf_mfc70esp_dll" /> + <ComponentRef Id="cmf_mfc70fra_dll" /> + <ComponentRef Id="cmf_mfc70ita_dll" /> + <ComponentRef Id="cmf_mfc70jpn_dll" /> + <ComponentRef Id="cmf_mfc70kor_dll" /> + <?endif?> + <?endif?> + <?ifdef CL1200 ?> + <ComponentRef Id="cmf_mfc42_dll" /> + <ComponentRef Id="cmf_msvcp60_dll" /> + <ComponentRef Id="cmf_msvcrt_dll" /> + <?endif?> +<?else?> + <?ifdef CL1310 ?> + <ComponentRef Id="cmf_mfc71d_dll" /> + <ComponentRef Id="cmf_msvcr71d_dll" /> + <ComponentRef Id="cmf_msvcp71d_dll" /> + <ComponentRef Id="cmf_mfc71chs_dll" /> + <ComponentRef Id="cmf_mfc71cht_dll" /> + <ComponentRef Id="cmf_mfc71deu_dll" /> + <ComponentRef Id="cmf_mfc71enu_dll" /> + <ComponentRef Id="cmf_mfc71esp_dll" /> + <ComponentRef Id="cmf_mfc71fra_dll" /> + <ComponentRef Id="cmf_mfc71ita_dll" /> + <ComponentRef Id="cmf_mfc71jpn_dll" /> + <ComponentRef Id="cmf_mfc71kor_dll" /> + <?endif?> + <?ifdef CL1300 ?> + <ComponentRef Id="cmf_mfc70d_dll" /> + <ComponentRef Id="cmf_msvcr70d_dll" /> + <ComponentRef Id="cmf_msvcp70d_dll" /> + <ComponentRef Id="cmf_mfc70chs_dll" /> + <ComponentRef Id="cmf_mfc70cht_dll" /> + <ComponentRef Id="cmf_mfc70deu_dll" /> + <ComponentRef Id="cmf_mfc70enu_dll" /> + <ComponentRef Id="cmf_mfc70esp_dll" /> + <ComponentRef Id="cmf_mfc70fra_dll" /> + <ComponentRef Id="cmf_mfc70ita_dll" /> + <ComponentRef Id="cmf_mfc70jpn_dll" /> + <ComponentRef Id="cmf_mfc70kor_dll" /> + <?endif?> + <?ifdef CL1200 ?> + <ComponentRef Id="cmf_mfc42d_dll" /> + <ComponentRef Id="cmf_msvcp60d_dll" /> + <ComponentRef Id="cmf_msvcrtd_dll" /> + <?endif?> +<?endif?> +</Include> \ No newline at end of file diff --git a/krb5-1-6/src/windows/installer/wix/runtime_debug.wxi b/krb5-1-6/src/windows/installer/wix/runtime_debug.wxi new file mode 100644 index 000000000..30bc566e9 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/runtime_debug.wxi @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<Include> + <?ifdef Debug?> + <?ifdef CL1310 ?> + <ComponentRef Id="cmf_runtime_debug1310" /> + <?endif?> + <?ifdef CL1300 ?> + <ComponentRef Id="cmf_runtime_debug1300" /> + <?endif?> + <?ifdef CL1200 ?> + <ComponentRef Id="cmf_runtime_debug1200" /> + <?endif?> + <?endif?> +</Include> diff --git a/krb5-1-6/src/windows/installer/wix/site-local-tagged.wxi b/krb5-1-6/src/windows/installer/wix/site-local-tagged.wxi new file mode 100644 index 000000000..c9a565112 --- /dev/null +++ b/krb5-1-6/src/windows/installer/wix/site-local-tagged.wxi @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8"?> +<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi"> + + <!-- User configurable options --> + + <!-- Items enclosed in double percent marks will be substituted by + the build script. --> + + <!-- TargetDir should point to build target directory and must end with + a backslash. If not specified, assume we are in TargetDir\install --> + + <?define TargetDir="%TARGETDIR%\"?> + + <!-- ConfigDir should point to directory containing configuration files + (krb5.ini, krb.con, krbrealm.con) to be bundled with the installer. + The directory name should end with a backslash. --> + + <?define ConfigDir="%CONFIGDIR-WIX%\"?> + + <!-- VersionMajor, VersionMinor and VersionPatch must all be specified, or + none should be specified (in which case, the defaults will be + selected below. --> + + <!-- version defs go here --> + <?define VersionMajor="%VERSION_MAJOR%"?> + <?define VersionMinor="%VERSION_MINOR%"?> + <?define VersionPatch="%VERSION_PATCH%"?> + + <!-- BuildLang is the language code for the installation. If you are + changing this, you should also change the ProductCode below. --> + <?ifndef BuildLang?> + <?define BuildLang="1033"?> + <?endif?> + + <!-- ProductCode is an uppercase GUID. Each release should have its + own ProductCode. If one is not defined, we generate a random one. --> + <?ifndef ProductCode?> + <?define ProductCode="????????-????-????-????-????????????"?> + <?endif?> + + <!-- DefaultRealm, is your default realm. Must be uppercase --> + <?define DefaultRealm="ATHENA.MIT.EDU"?> + + <!-- One of the following must be defined and must correspond to the + version of compiler used for building Kerberos for Windows --> + + <!-- <?define CL1200?> --> + <!-- <?define CL1300?> --> + <?define CL1310?> + <!-- <?define CL1400?> --> + + <!-- At most one of the following could be defined and must correspond + to the type of build performed. --> + <!-- <?define Debug?> --> + <?define Release?> + + <!-- We are including debug symbols anyway. Undefine this for a leaner + installer without debug syms. --> + <?define DebugSyms?> + + <!-- Optional defines --> + <?define Beta="1"?> <!-- Numeric Beta identifier --> + <!-- <?define OldHelp?> --> <!-- Specifies the use of the old leash32.hlp file + instead of the new leash32.chm file --> + + + <!-- End of user configurable options --> + + <!-- Assert that required options are defined, or select defaults if + they weren't --> + + <?ifndef TargetDir?> + <?define TargetDir="$(sys.SOURCEFILEDIR)..\"?> + <?endif?> + + <?ifndef ConfigDir?> + <?define ConfigDir="$(env.SystemRoot)\"?> + <?endif?> + + <?ifndef VersionMajor?> + <?define VersionMajor="3"?> + <?define VersionMinor="2"?> + <?define VersionPatch="0"?> + <?else?> + <?if Not ($(var.VersionMinor) And $(var.VersionPatch))?> + <?error VersionMajor, VersionMinor and VersionPatch should be specified together?> + <?endif?> + <?endif?> + + <?ifndef ProductCode?> + <?error Must define ProductCode?> + <?endif?> + + <?ifndef BuildLang?> + <?error Must define BuildLang?> + <?endif?> + + <!-- DefaultRealm. Must be uppercase. --> + <?ifndef DefaultRealm?> + <?error Must define DefaultRealm?> + <?endif?> + + <!-- The build makefile defines 'Date' and 'Time' which are strings that + identify the time at which the build was performed. --> +</Include> \ No newline at end of file diff --git a/krb5-1-6/src/windows/kfwlogon/Makefile.in b/krb5-1-6/src/windows/kfwlogon/Makefile.in new file mode 100644 index 000000000..0d7fcc565 --- /dev/null +++ b/krb5-1-6/src/windows/kfwlogon/Makefile.in @@ -0,0 +1,47 @@ +# Makefile for the KFW Network Provider +# + +thisconfigdir=./.. +myfulldir=windows/nplogon +mydir=. +BUILDTOP=$(REL)..$(S).. +DEFINES = +LOCALINCLUDES = -I$(BUILDTOP) -I$(PISMERE)\athena\util\loadfuncs \ + -I$(PISMERE)\athena\auth\krb5\src\include\kerberosIV \ + -I$(PISMERE)\athena\auth\krb4\include \ + -I$(PISMERE)\athena\auth\leash\include +PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR) + +SYSLIBS = kernel32.lib user32.lib advapi32.lib wsock32.lib secur32.lib userenv.lib + +VERSIONRC = $(BUILDTOP)\windows\version.rc +RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY + +KFWLOGON=$(OUTPRE)kfwlogon.dll +KFWCPCC=$(OUTPRE)kfwcpcc.exe + +LIBRES=$(KFWLOGON:.dll=.res) +EXERES=$(KFWCPCC:.exe=.res) + +$(LIBRES): $(VERSIONRC) + $(RC) $(RCFLAGS) -DKFWLOGON_LIB -fo $@ -r $** +$(EXERES): $(VERSIONRC) + $(RC) $(RCFLAGS) -DKFWCPCC_APP -fo $@ -r $** + +all-windows:: $(OUTPRE)kfwlogon.dll $(OUTPRE)kfwcpcc.exe + +$(KFWLOGON): $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj $(LIBRES) + link $(DLL_LINKOPTS) -out:$@ $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj -entry:DllEntryPoint -def:kfwlogon.def $(SYSLIBS) $(KLIB) $(CLIB) $(LIBRES) + $(_VC_MANIFEST_EMBED_DLL) + +$(KFWCPCC): $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(EXERES) + link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(SYSLIBS) $(KLIB) $(CLIB) $(EXERES) + $(_VC_MANIFEST_EMBED_EXE) + +install:: + copy $(OUTPRE)kfwlogon.dll $(DESTDIR) + copy $(OUTPRE)kfwcpcc.exe $(DESTDIR) + +clean:: + $(RM) $(OUTPRE)*.exe $(OUTPRE)*.dll $(OUTPRE)*.res + diff --git a/krb5-1-6/src/windows/kfwlogon/kfwcommon.c b/krb5-1-6/src/windows/kfwlogon/kfwcommon.c new file mode 100644 index 000000000..c07bd81c3 --- /dev/null +++ b/krb5-1-6/src/windows/kfwlogon/kfwcommon.c @@ -0,0 +1,1352 @@ +/* +Copyright 2005,2006 by the Massachusetts Institute of Technology +Copyright 2007 by Secure Endpoints Inc. + +All rights reserved. + +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 the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +#include "kfwlogon.h" +#include <windows.h> +#include <Aclapi.h> +#include <userenv.h> +#include <Sddl.h> + +#include <io.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> + +#include <winsock2.h> +#include <lm.h> +#include <nb30.h> + +#include <errno.h> +#include <malloc.h> + + +/* Function Pointer Declarations for Delayed Loading */ +// CCAPI +DECL_FUNC_PTR(cc_initialize); +DECL_FUNC_PTR(cc_shutdown); +DECL_FUNC_PTR(cc_get_NC_info); +DECL_FUNC_PTR(cc_free_NC_info); + +// leash functions +DECL_FUNC_PTR(Leash_get_default_lifetime); +DECL_FUNC_PTR(Leash_get_default_forwardable); +DECL_FUNC_PTR(Leash_get_default_renew_till); +DECL_FUNC_PTR(Leash_get_default_noaddresses); +DECL_FUNC_PTR(Leash_get_default_proxiable); +DECL_FUNC_PTR(Leash_get_default_publicip); +DECL_FUNC_PTR(Leash_get_default_use_krb4); +DECL_FUNC_PTR(Leash_get_default_life_min); +DECL_FUNC_PTR(Leash_get_default_life_max); +DECL_FUNC_PTR(Leash_get_default_renew_min); +DECL_FUNC_PTR(Leash_get_default_renew_max); +DECL_FUNC_PTR(Leash_get_default_renewable); +DECL_FUNC_PTR(Leash_get_default_mslsa_import); + +// krb5 functions +DECL_FUNC_PTR(krb5_change_password); +DECL_FUNC_PTR(krb5_get_init_creds_opt_init); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list); +DECL_FUNC_PTR(krb5_get_init_creds_password); +DECL_FUNC_PTR(krb5_build_principal_ext); +DECL_FUNC_PTR(krb5_cc_get_name); +DECL_FUNC_PTR(krb5_cc_resolve); +DECL_FUNC_PTR(krb5_cc_default); +DECL_FUNC_PTR(krb5_cc_default_name); +DECL_FUNC_PTR(krb5_cc_set_default_name); +DECL_FUNC_PTR(krb5_cc_initialize); +DECL_FUNC_PTR(krb5_cc_destroy); +DECL_FUNC_PTR(krb5_cc_close); +DECL_FUNC_PTR(krb5_cc_store_cred); +DECL_FUNC_PTR(krb5_cc_copy_creds); +DECL_FUNC_PTR(krb5_cc_retrieve_cred); +DECL_FUNC_PTR(krb5_cc_get_principal); +DECL_FUNC_PTR(krb5_cc_start_seq_get); +DECL_FUNC_PTR(krb5_cc_next_cred); +DECL_FUNC_PTR(krb5_cc_end_seq_get); +DECL_FUNC_PTR(krb5_cc_remove_cred); +DECL_FUNC_PTR(krb5_cc_set_flags); +DECL_FUNC_PTR(krb5_cc_get_type); +DECL_FUNC_PTR(krb5_free_context); +DECL_FUNC_PTR(krb5_free_cred_contents); +DECL_FUNC_PTR(krb5_free_principal); +DECL_FUNC_PTR(krb5_get_in_tkt_with_password); +DECL_FUNC_PTR(krb5_init_context); +DECL_FUNC_PTR(krb5_parse_name); +DECL_FUNC_PTR(krb5_timeofday); +DECL_FUNC_PTR(krb5_timestamp_to_sfstring); +DECL_FUNC_PTR(krb5_unparse_name); +DECL_FUNC_PTR(krb5_get_credentials); +DECL_FUNC_PTR(krb5_mk_req); +DECL_FUNC_PTR(krb5_sname_to_principal); +DECL_FUNC_PTR(krb5_get_credentials_renew); +DECL_FUNC_PTR(krb5_free_data); +DECL_FUNC_PTR(krb5_free_data_contents); +DECL_FUNC_PTR(krb5_free_unparsed_name); +DECL_FUNC_PTR(krb5_os_localaddr); +DECL_FUNC_PTR(krb5_copy_keyblock_contents); +DECL_FUNC_PTR(krb5_copy_data); +DECL_FUNC_PTR(krb5_free_creds); +DECL_FUNC_PTR(krb5_build_principal); +DECL_FUNC_PTR(krb5_get_renewed_creds); +DECL_FUNC_PTR(krb5_get_default_config_files); +DECL_FUNC_PTR(krb5_free_config_files); +DECL_FUNC_PTR(krb5_get_default_realm); +DECL_FUNC_PTR(krb5_free_default_realm); +DECL_FUNC_PTR(krb5_free_ticket); +DECL_FUNC_PTR(krb5_decode_ticket); +DECL_FUNC_PTR(krb5_get_host_realm); +DECL_FUNC_PTR(krb5_free_host_realm); +DECL_FUNC_PTR(krb5_free_addresses); +DECL_FUNC_PTR(krb5_c_random_make_octets); + +// ComErr functions +DECL_FUNC_PTR(com_err); +DECL_FUNC_PTR(error_message); + +// Profile functions +DECL_FUNC_PTR(profile_init); +DECL_FUNC_PTR(profile_release); +DECL_FUNC_PTR(profile_get_subsection_names); +DECL_FUNC_PTR(profile_free_list); +DECL_FUNC_PTR(profile_get_string); +DECL_FUNC_PTR(profile_release_string); + +// Service functions +DECL_FUNC_PTR(OpenSCManagerA); +DECL_FUNC_PTR(OpenServiceA); +DECL_FUNC_PTR(QueryServiceStatus); +DECL_FUNC_PTR(CloseServiceHandle); +DECL_FUNC_PTR(LsaNtStatusToWinError); + +// LSA Functions +DECL_FUNC_PTR(LsaConnectUntrusted); +DECL_FUNC_PTR(LsaLookupAuthenticationPackage); +DECL_FUNC_PTR(LsaCallAuthenticationPackage); +DECL_FUNC_PTR(LsaFreeReturnBuffer); +DECL_FUNC_PTR(LsaGetLogonSessionData); + +// CCAPI +FUNC_INFO ccapi_fi[] = { + MAKE_FUNC_INFO(cc_initialize), + MAKE_FUNC_INFO(cc_shutdown), + MAKE_FUNC_INFO(cc_get_NC_info), + MAKE_FUNC_INFO(cc_free_NC_info), + END_FUNC_INFO +}; + +FUNC_INFO leash_fi[] = { + MAKE_FUNC_INFO(Leash_get_default_lifetime), + MAKE_FUNC_INFO(Leash_get_default_renew_till), + MAKE_FUNC_INFO(Leash_get_default_forwardable), + MAKE_FUNC_INFO(Leash_get_default_noaddresses), + MAKE_FUNC_INFO(Leash_get_default_proxiable), + MAKE_FUNC_INFO(Leash_get_default_publicip), + MAKE_FUNC_INFO(Leash_get_default_use_krb4), + MAKE_FUNC_INFO(Leash_get_default_life_min), + MAKE_FUNC_INFO(Leash_get_default_life_max), + MAKE_FUNC_INFO(Leash_get_default_renew_min), + MAKE_FUNC_INFO(Leash_get_default_renew_max), + MAKE_FUNC_INFO(Leash_get_default_renewable), + END_FUNC_INFO +}; + +FUNC_INFO leash_opt_fi[] = { + MAKE_FUNC_INFO(Leash_get_default_mslsa_import), + END_FUNC_INFO +}; + +FUNC_INFO k5_fi[] = { + MAKE_FUNC_INFO(krb5_change_password), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_init), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list), + MAKE_FUNC_INFO(krb5_get_init_creds_password), + MAKE_FUNC_INFO(krb5_build_principal_ext), + MAKE_FUNC_INFO(krb5_cc_get_name), + MAKE_FUNC_INFO(krb5_cc_resolve), + MAKE_FUNC_INFO(krb5_cc_default), + MAKE_FUNC_INFO(krb5_cc_default_name), + MAKE_FUNC_INFO(krb5_cc_set_default_name), + MAKE_FUNC_INFO(krb5_cc_initialize), + MAKE_FUNC_INFO(krb5_cc_destroy), + MAKE_FUNC_INFO(krb5_cc_close), + MAKE_FUNC_INFO(krb5_cc_copy_creds), + MAKE_FUNC_INFO(krb5_cc_store_cred), + MAKE_FUNC_INFO(krb5_cc_retrieve_cred), + MAKE_FUNC_INFO(krb5_cc_get_principal), + MAKE_FUNC_INFO(krb5_cc_start_seq_get), + MAKE_FUNC_INFO(krb5_cc_next_cred), + MAKE_FUNC_INFO(krb5_cc_end_seq_get), + MAKE_FUNC_INFO(krb5_cc_remove_cred), + MAKE_FUNC_INFO(krb5_cc_set_flags), + MAKE_FUNC_INFO(krb5_cc_get_type), + MAKE_FUNC_INFO(krb5_free_context), + MAKE_FUNC_INFO(krb5_free_cred_contents), + MAKE_FUNC_INFO(krb5_free_principal), + MAKE_FUNC_INFO(krb5_get_in_tkt_with_password), + MAKE_FUNC_INFO(krb5_init_context), + MAKE_FUNC_INFO(krb5_parse_name), + MAKE_FUNC_INFO(krb5_timeofday), + MAKE_FUNC_INFO(krb5_timestamp_to_sfstring), + MAKE_FUNC_INFO(krb5_unparse_name), + MAKE_FUNC_INFO(krb5_get_credentials), + MAKE_FUNC_INFO(krb5_mk_req), + MAKE_FUNC_INFO(krb5_sname_to_principal), + MAKE_FUNC_INFO(krb5_get_credentials_renew), + MAKE_FUNC_INFO(krb5_free_data), + MAKE_FUNC_INFO(krb5_free_data_contents), + MAKE_FUNC_INFO(krb5_free_unparsed_name), + MAKE_FUNC_INFO(krb5_os_localaddr), + MAKE_FUNC_INFO(krb5_copy_keyblock_contents), + MAKE_FUNC_INFO(krb5_copy_data), + MAKE_FUNC_INFO(krb5_free_creds), + MAKE_FUNC_INFO(krb5_build_principal), + MAKE_FUNC_INFO(krb5_get_renewed_creds), + MAKE_FUNC_INFO(krb5_free_addresses), + MAKE_FUNC_INFO(krb5_get_default_config_files), + MAKE_FUNC_INFO(krb5_free_config_files), + MAKE_FUNC_INFO(krb5_get_default_realm), + MAKE_FUNC_INFO(krb5_free_default_realm), + MAKE_FUNC_INFO(krb5_free_ticket), + MAKE_FUNC_INFO(krb5_decode_ticket), + MAKE_FUNC_INFO(krb5_get_host_realm), + MAKE_FUNC_INFO(krb5_free_host_realm), + MAKE_FUNC_INFO(krb5_free_addresses), + MAKE_FUNC_INFO(krb5_c_random_make_octets), + END_FUNC_INFO +}; + +FUNC_INFO profile_fi[] = { + MAKE_FUNC_INFO(profile_init), + MAKE_FUNC_INFO(profile_release), + MAKE_FUNC_INFO(profile_get_subsection_names), + MAKE_FUNC_INFO(profile_free_list), + MAKE_FUNC_INFO(profile_get_string), + MAKE_FUNC_INFO(profile_release_string), + END_FUNC_INFO +}; + +FUNC_INFO ce_fi[] = { + MAKE_FUNC_INFO(com_err), + MAKE_FUNC_INFO(error_message), + END_FUNC_INFO +}; + +FUNC_INFO service_fi[] = { + MAKE_FUNC_INFO(OpenSCManagerA), + MAKE_FUNC_INFO(OpenServiceA), + MAKE_FUNC_INFO(QueryServiceStatus), + MAKE_FUNC_INFO(CloseServiceHandle), + MAKE_FUNC_INFO(LsaNtStatusToWinError), + END_FUNC_INFO +}; + +FUNC_INFO lsa_fi[] = { + MAKE_FUNC_INFO(LsaConnectUntrusted), + MAKE_FUNC_INFO(LsaLookupAuthenticationPackage), + MAKE_FUNC_INFO(LsaCallAuthenticationPackage), + MAKE_FUNC_INFO(LsaFreeReturnBuffer), + MAKE_FUNC_INFO(LsaGetLogonSessionData), + END_FUNC_INFO +}; + +/* Static Declarations */ +static int inited = 0; +static HINSTANCE hKrb5 = 0; +static HINSTANCE hKrb524 = 0; +static HINSTANCE hSecur32 = 0; +static HINSTANCE hAdvApi32 = 0; +static HINSTANCE hComErr = 0; +static HINSTANCE hService = 0; +static HINSTANCE hProfile = 0; +static HINSTANCE hLeash = 0; +static HINSTANCE hLeashOpt = 0; +static HINSTANCE hCCAPI = 0; + +static DWORD TraceOption = 0; +static HANDLE hDLL; + +BOOL IsDebugLogging(void) +{ + DWORD LSPsize; + HKEY NPKey; + DWORD dwDebug = FALSE; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\MIT Kerberos\\NetworkProvider", + 0, KEY_QUERY_VALUE, &NPKey) == ERROR_SUCCESS) + { + LSPsize=sizeof(dwDebug); + if (RegQueryValueEx(NPKey, "Debug", NULL, NULL, (LPBYTE)&dwDebug, &LSPsize) != ERROR_SUCCESS) + { + dwDebug = FALSE; + } + RegCloseKey (NPKey); + } + + return(dwDebug ? TRUE : FALSE); +} + +void DebugEvent0(char *a) +{ + HANDLE h; char *ptbuf[1]; + + if (IsDebugLogging()) { + h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME); + if (h) { + ptbuf[0] = a; + ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL); + DeregisterEventSource(h); + } + } +} + +#define MAXBUF_ 512 +void DebugEvent(char *b,...) +{ + HANDLE h; char *ptbuf[1],buf[MAXBUF_+1]; + va_list marker; + + if (IsDebugLogging()) { + h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME); + if (h) { + va_start(marker,b); + StringCbVPrintf(buf, MAXBUF_+1,b,marker); + buf[MAXBUF_] = '\0'; + ptbuf[0] = buf; + ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL); + DeregisterEventSource(h); + va_end(marker); + } + } +} + +void +UnloadFuncs( + FUNC_INFO fi[], + HINSTANCE h + ) +{ + int n; + if (fi) + for (n = 0; fi[n].func_ptr_var; n++) + *(fi[n].func_ptr_var) = 0; + if (h) FreeLibrary(h); +} + +int +LoadFuncs( + const char* dll_name, + FUNC_INFO fi[], + HINSTANCE* ph, // [out, optional] - DLL handle + int* pindex, // [out, optional] - index of last func loaded (-1 if none) + int cleanup, // cleanup function pointers and unload on error + int go_on, // continue loading even if some functions cannot be loaded + int silent // do not pop-up a system dialog if DLL cannot be loaded + ) +{ + HINSTANCE h; + int i, n, last_i; + int error = 0; + UINT em; + + if (ph) *ph = 0; + if (pindex) *pindex = -1; + + for (n = 0; fi[n].func_ptr_var; n++) + *(fi[n].func_ptr_var) = 0; + + if (silent) + em = SetErrorMode(SEM_FAILCRITICALERRORS); + h = LoadLibrary(dll_name); + if (silent) + SetErrorMode(em); + + if (!h) + return 0; + + last_i = -1; + for (i = 0; (go_on || !error) && (i < n); i++) + { + void* p = (void*)GetProcAddress(h, fi[i].func_name); + if (!p) + error = 1; + else + { + last_i = i; + *(fi[i].func_ptr_var) = p; + } + } + if (pindex) *pindex = last_i; + if (error && cleanup && !go_on) { + for (i = 0; i < n; i++) { + *(fi[i].func_ptr_var) = 0; + } + FreeLibrary(h); + return 0; + } + if (ph) *ph = h; + if (error) return 0; + return 1; +} + +static HANDLE hInitMutex = NULL; +static BOOL bInit = FALSE; + +/* KFW_initialize cannot be called from DllEntryPoint */ +void +KFW_initialize(void) +{ + static int inited = 0; + + if ( !inited ) { + char mutexName[MAX_PATH]; + HANDLE hMutex = NULL; + + sprintf(mutexName, "AFS KFW Init pid=%d", getpid()); + + hMutex = CreateMutex( NULL, TRUE, mutexName ); + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) { + return; + } + } + if ( !inited ) { + inited = 1; + LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0); + LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0); + LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0); + LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1); + LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0); + LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0); + LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0); + LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0); + } + ReleaseMutex(hMutex); + CloseHandle(hMutex); + } +} + +void +KFW_cleanup(void) +{ + if (hLeashOpt) + FreeLibrary(hLeashOpt); + if (hCCAPI) + FreeLibrary(hCCAPI); + if (hLeash) + FreeLibrary(hLeash); + if (hKrb524) + FreeLibrary(hKrb524); + if (hSecur32) + FreeLibrary(hSecur32); + if (hService) + FreeLibrary(hService); + if (hComErr) + FreeLibrary(hComErr); + if (hProfile) + FreeLibrary(hProfile); + if (hKrb5) + FreeLibrary(hKrb5); +} + + +int +KFW_is_available(void) +{ + KFW_initialize(); + if ( hKrb5 && hComErr && hService && +#ifdef USE_MS2MIT + hSecur32 && +#endif /* USE_MS2MIT */ + hProfile && hLeash && hCCAPI ) + return TRUE; + + return FALSE; +} + +/* Given a principal return an existing ccache or create one and return */ +int +KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc) +{ + krb5_context ctx; + char * pname = 0; + char * ccname = 0; + krb5_error_code code; + + if (!pkrb5_init_context) + return 0; + + if ( alt_ctx ) { + ctx = alt_ctx; + } else { + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + } + + if ( principal ) { + code = pkrb5_unparse_name(ctx, principal, &pname); + if (code) goto cleanup; + + ccname = (char *)malloc(strlen(pname) + 5); + sprintf(ccname,"API:%s",pname); + + DebugEvent0(ccname); + code = pkrb5_cc_resolve(ctx, ccname, cc); + } else { + code = pkrb5_cc_default(ctx, cc); + if (code) goto cleanup; + } + + cleanup: + if (ccname) + free(ccname); + if (pname) + pkrb5_free_unparsed_name(ctx,pname); + if (ctx && (ctx != alt_ctx)) + pkrb5_free_context(ctx); + return(code); +} + + +int +KFW_kinit( krb5_context alt_ctx, + krb5_ccache alt_cc, + HWND hParent, + char *principal_name, + char *password, + krb5_deltat lifetime, + DWORD forwardable, + DWORD proxiable, + krb5_deltat renew_life, + DWORD addressless, + DWORD publicIP + ) +{ + krb5_error_code code = 0; + krb5_context ctx = 0; + krb5_ccache cc = 0; + krb5_principal me = 0; + char* name = 0; + krb5_creds my_creds; + krb5_get_init_creds_opt options; + krb5_address ** addrs = NULL; + int i = 0, addr_count = 0; + + if (!pkrb5_init_context) + return 0; + + pkrb5_get_init_creds_opt_init(&options); + memset(&my_creds, 0, sizeof(my_creds)); + + if (alt_ctx) + { + ctx = alt_ctx; + } + else + { + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + } + + if ( alt_cc ) { + cc = alt_cc; + } else { + code = pkrb5_cc_default(ctx, &cc); + if (code) goto cleanup; + } + + code = pkrb5_parse_name(ctx, principal_name, &me); + if (code) + goto cleanup; + + code = pkrb5_unparse_name(ctx, me, &name); + if (code) + goto cleanup; + + if (lifetime == 0) + lifetime = pLeash_get_default_lifetime(); + lifetime *= 60; + + if (renew_life > 0) + renew_life *= 60; + + if (lifetime) + pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime); + pkrb5_get_init_creds_opt_set_forwardable(&options, + forwardable ? 1 : 0); + pkrb5_get_init_creds_opt_set_proxiable(&options, + proxiable ? 1 : 0); + pkrb5_get_init_creds_opt_set_renew_life(&options, + renew_life); + if (addressless) + pkrb5_get_init_creds_opt_set_address_list(&options,NULL); + else { + if (publicIP) + { + // we are going to add the public IP address specified by the user + // to the list provided by the operating system + krb5_address ** local_addrs=NULL; + DWORD netIPAddr; + + pkrb5_os_localaddr(ctx, &local_addrs); + while ( local_addrs[i++] ); + addr_count = i + 1; + + addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *)); + if ( !addrs ) { + pkrb5_free_addresses(ctx, local_addrs); + goto cleanup; + } + memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1)); + i = 0; + while ( local_addrs[i] ) { + addrs[i] = (krb5_address *)malloc(sizeof(krb5_address)); + if (addrs[i] == NULL) { + pkrb5_free_addresses(ctx, local_addrs); + goto cleanup; + } + + addrs[i]->magic = local_addrs[i]->magic; + addrs[i]->addrtype = local_addrs[i]->addrtype; + addrs[i]->length = local_addrs[i]->length; + addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length); + if (!addrs[i]->contents) { + pkrb5_free_addresses(ctx, local_addrs); + goto cleanup; + } + + memcpy(addrs[i]->contents,local_addrs[i]->contents, + local_addrs[i]->length); /* safe */ + i++; + } + pkrb5_free_addresses(ctx, local_addrs); + + addrs[i] = (krb5_address *)malloc(sizeof(krb5_address)); + if (addrs[i] == NULL) + goto cleanup; + + addrs[i]->magic = KV5M_ADDRESS; + addrs[i]->addrtype = AF_INET; + addrs[i]->length = 4; + addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length); + if (!addrs[i]->contents) + goto cleanup; + + netIPAddr = htonl(publicIP); + memcpy(addrs[i]->contents,&netIPAddr,4); + + pkrb5_get_init_creds_opt_set_address_list(&options,addrs); + + } + } + + code = pkrb5_get_init_creds_password(ctx, + &my_creds, + me, + password, // password + NULL, // no prompter + hParent, // prompter data + 0, // start time + 0, // service name + &options); + if (code) + goto cleanup; + + code = pkrb5_cc_initialize(ctx, cc, me); + if (code) + goto cleanup; + + code = pkrb5_cc_store_cred(ctx, cc, &my_creds); + if (code) + goto cleanup; + + cleanup: + if ( addrs ) { + for ( i=0;i<addr_count;i++ ) { + if ( addrs[i] ) { + if ( addrs[i]->contents ) + free(addrs[i]->contents); + free(addrs[i]); + } + } + } + if (my_creds.client == me) + my_creds.client = 0; + pkrb5_free_cred_contents(ctx, &my_creds); + if (name) + pkrb5_free_unparsed_name(ctx, name); + if (me) + pkrb5_free_principal(ctx, me); + if (cc && (cc != alt_cc)) + pkrb5_cc_close(ctx, cc); + if (ctx && (ctx != alt_ctx)) + pkrb5_free_context(ctx); + return(code); +} + + +int +KFW_get_cred( char * username, + char * password, + int lifetime, + char ** reasonP ) +{ + krb5_context ctx = 0; + krb5_ccache cc = 0; + char * realm = 0; + krb5_principal principal = 0; + char * pname = 0; + krb5_error_code code; + + if (!pkrb5_init_context || !username || !password || !password[0]) + return 0; + + DebugEvent0(username); + + code = pkrb5_init_context(&ctx); + if ( code ) goto cleanup; + + code = pkrb5_get_default_realm(ctx, &realm); + + if (realm) { + pname = malloc(strlen(username) + strlen(realm) + 2); + if (!pname) + goto cleanup; + strcpy(pname, username); + strcat(pname, "@"); + strcat(pname, realm); + } else { + goto cleanup; + } + + DebugEvent0(realm); + DebugEvent0(pname); + + code = pkrb5_parse_name(ctx, pname, &principal); + if ( code ) goto cleanup; + + DebugEvent0("parsed name"); + code = KFW_get_ccache(ctx, principal, &cc); + if ( code ) goto cleanup; + + DebugEvent0("got ccache"); + + if ( lifetime == 0 ) + lifetime = pLeash_get_default_lifetime(); + + DebugEvent0("got lifetime"); + + code = KFW_kinit( ctx, cc, HWND_DESKTOP, + pname, + password, + lifetime, + pLeash_get_default_forwardable(), + pLeash_get_default_proxiable(), + pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0, + pLeash_get_default_noaddresses(), + pLeash_get_default_publicip()); + DebugEvent0("kinit returned"); + if ( code ) goto cleanup; + + cleanup: + if ( pname ) + free(pname); + if ( realm ) + pkrb5_free_default_realm(ctx, realm); + if ( cc ) + pkrb5_cc_close(ctx, cc); + + if ( code && reasonP ) { + *reasonP = (char *)perror_message(code); + } + return(code); +} + +int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken) +{ + // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY; + PSID pSystemSID = NULL; + DWORD SystemSIDlength = 0, UserSIDlength = 0; + PACL ccacheACL = NULL; + DWORD ccacheACLlength = 0; + PTOKEN_USER pTokenUser = NULL; + DWORD retLen; + DWORD gle; + int ret = 0; + + if (!filename) { + DebugEvent0("KFW_set_ccache_dacl - invalid parms"); + return 1; + } + + DebugEvent0("KFW_set_ccache_dacl"); + + /* Get System SID */ + if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) { + DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError()); + ret = 1; + goto cleanup; + } + + /* Create ACL */ + SystemSIDlength = GetLengthSid(pSystemSID); + ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + + SystemSIDlength - sizeof(DWORD); + + if (hUserToken) { + if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen)) + { + if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { + pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen); + + if (!GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen)) + { + DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError()); + } + } + } + + if (pTokenUser) { + UserSIDlength = GetLengthSid(pTokenUser->User.Sid); + + ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength + - sizeof(DWORD); + } + } + + ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength); + if (!ccacheACL) { + DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError()); + ret = 1; + goto cleanup; + } + + InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION); + AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0, + STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, + pSystemSID); + if (pTokenUser) { + AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0, + STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, + pTokenUser->User.Sid); + if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, + NULL, + NULL, + ccacheACL, + NULL)) { + gle = GetLastError(); + DebugEvent("SetNamedSecurityInfo DACL (1) failed: GLE = 0x%lX", gle); + if (gle != ERROR_NO_TOKEN) + ret = 1; + } + if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION, + pTokenUser->User.Sid, + NULL, + NULL, + NULL)) { + gle = GetLastError(); + DebugEvent("SetNamedSecurityInfo OWNER (2) failed: GLE = 0x%lX", gle); + if (gle != ERROR_NO_TOKEN) + ret = 1; + } + } else { + if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, + NULL, + NULL, + ccacheACL, + NULL)) { + gle = GetLastError(); + DebugEvent("SetNamedSecurityInfo DACL (3) failed: GLE = 0x%lX", gle); + if (gle != ERROR_NO_TOKEN) + ret = 1; + } + } + + cleanup: + if (pSystemSID) + LocalFree(pSystemSID); + if (pTokenUser) + LocalFree(pTokenUser); + if (ccacheACL) + LocalFree(ccacheACL); + return ret; +} + +int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID) +{ + // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY; + PSID pSystemSID = NULL; + DWORD SystemSIDlength = 0, UserSIDlength = 0; + PACL ccacheACL = NULL; + DWORD ccacheACLlength = 0; + DWORD gle; + int ret = 0; + + if (!filename) { + DebugEvent0("KFW_set_ccache_dacl_with_user_sid - invalid parms"); + return 1; + } + + DebugEvent0("KFW_set_ccache_dacl_with_user_sid"); + + /* Get System SID */ + if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) { + DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError()); + ret = 1; + goto cleanup; + } + + /* Create ACL */ + SystemSIDlength = GetLengthSid(pSystemSID); + ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + + SystemSIDlength - sizeof(DWORD); + + if (pUserSID) { + UserSIDlength = GetLengthSid(pUserSID); + + ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength + - sizeof(DWORD); + } + + ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength); + if (!ccacheACL) { + DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError()); + ret = 1; + goto cleanup; + } + + InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION); + AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0, + STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, + pSystemSID); + if (pUserSID) { + AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0, + STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, + pUserSID); + if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, + NULL, + NULL, + ccacheACL, + NULL)) { + gle = GetLastError(); + DebugEvent("SetNamedSecurityInfo DACL (4) failed: GLE = 0x%lX", gle); + if (gle != ERROR_NO_TOKEN) + ret = 1; + } + if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION, + pUserSID, + NULL, + NULL, + NULL)) { + gle = GetLastError(); + DebugEvent("SetNamedSecurityInfo OWNER (5) failed: GLE = 0x%lX", gle); + if (gle != ERROR_NO_TOKEN) + ret = 1; + } + } else { + if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, + NULL, + NULL, + ccacheACL, + NULL)) { + gle = GetLastError(); + DebugEvent("SetNamedSecurityInfo DACL (6) failed: GLE = 0x%lX", gle); + if (gle != ERROR_NO_TOKEN) + ret = 1; + } + } + + cleanup: + if (pSystemSID) + LocalFree(pSystemSID); + if (ccacheACL) + LocalFree(ccacheACL); + return ret; +} + +int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size) +{ + int retval = 0; + DWORD dwSize = size-1; /* leave room for nul */ + DWORD dwLen = 0; + + if (!hUserToken || !newfilename || size <= 0) + return 1; + + *newfilename = '\0'; + + dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize); + if ( !dwLen || dwLen > dwSize ) + dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize); + if ( !dwLen || dwLen > dwSize ) + return 1; + + newfilename[dwSize] = '\0'; + return 0; +} + +void +KFW_copy_cache_to_system_file(const char * user, const char * filename) +{ + char cachename[MAX_PATH + 8] = "FILE:"; + krb5_context ctx = 0; + krb5_error_code code; + krb5_principal princ = 0; + krb5_ccache cc = 0; + krb5_ccache ncc = 0; + PSECURITY_ATTRIBUTES pSA = NULL; + + if (!pkrb5_init_context || !user || !filename) + return; + + strncat(cachename, filename, sizeof(cachename)); + cachename[sizeof(cachename)-1] = '\0'; + + DebugEvent("KFW_Logon_Event - ccache %s", cachename); + + DeleteFile(filename); + + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + + code = pkrb5_parse_name(ctx, user, &princ); + if (code) goto cleanup; + + code = KFW_get_ccache(ctx, princ, &cc); + if (code) goto cleanup; + + code = pkrb5_cc_resolve(ctx, cachename, &ncc); + if (code) goto cleanup; + + code = pkrb5_cc_initialize(ctx, ncc, princ); + if (code) goto cleanup; + + code = KFW_set_ccache_dacl(filename, NULL); + if (code) goto cleanup; + + code = pkrb5_cc_copy_creds(ctx,cc,ncc); + + cleanup: + if ( cc ) { + pkrb5_cc_close(ctx, cc); + cc = 0; + } + if ( ncc ) { + pkrb5_cc_close(ctx, ncc); + ncc = 0; + } + if ( princ ) { + pkrb5_free_principal(ctx, princ); + princ = 0; + } + + if (ctx) + pkrb5_free_context(ctx); +} + +int +KFW_copy_file_cache_to_default_cache(char * filename) +{ + char cachename[MAX_PATH + 8] = "FILE:"; + krb5_context ctx = 0; + krb5_error_code code; + krb5_principal princ = 0; + krb5_ccache cc = 0; + krb5_ccache ncc = 0; + int retval = 1; + + if (!pkrb5_init_context || !filename) + return 1; + + if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) ) + return 1; + + code = pkrb5_init_context(&ctx); + if (code) return 1; + + strcat(cachename, filename); + + code = pkrb5_cc_resolve(ctx, cachename, &cc); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_resolve failed"); + goto cleanup; + } + + code = pkrb5_cc_get_principal(ctx, cc, &princ); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_get_principal failed"); + goto cleanup; + } + + code = pkrb5_cc_default(ctx, &ncc); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_default failed"); + goto cleanup; + } + if (!code) { + code = pkrb5_cc_initialize(ctx, ncc, princ); + + if (!code) + code = pkrb5_cc_copy_creds(ctx,cc,ncc); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_copy_creds failed"); + goto cleanup; + } + } + if ( ncc ) { + pkrb5_cc_close(ctx, ncc); + ncc = 0; + } + + retval=0; /* success */ + + cleanup: + if ( cc ) { + pkrb5_cc_close(ctx, cc); + cc = 0; + } + + DeleteFile(filename); + + if ( princ ) { + pkrb5_free_principal(ctx, princ); + princ = 0; + } + + if (ctx) + pkrb5_free_context(ctx); + + return 0; +} + + +int +KFW_copy_file_cache_to_api_cache(char * filename) +{ + char cachename[MAX_PATH + 8] = "FILE:"; + krb5_context ctx = 0; + krb5_error_code code; + krb5_principal princ = 0; + krb5_ccache cc = 0; + krb5_ccache ncc = 0; + char *name = NULL; + int retval = 1; + + if (!pkrb5_init_context || !filename) + return 1; + + if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) ) + return 1; + + code = pkrb5_init_context(&ctx); + if (code) return 1; + + strcat(cachename, filename); + + code = pkrb5_cc_resolve(ctx, cachename, &cc); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_resolve failed"); + goto cleanup; + } + + code = pkrb5_cc_get_principal(ctx, cc, &princ); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_get_principal failed"); + goto cleanup; + } + + code = pkrb5_unparse_name(ctx, princ, &name); + if (code) { + DebugEvent0("kfwcpcc krb5_unparse_name failed"); + goto cleanup; + } + + sprintf(cachename, "API:%s", name); + + code = pkrb5_cc_resolve(ctx, cachename, &ncc); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_default failed"); + goto cleanup; + } + if (!code) { + code = pkrb5_cc_initialize(ctx, ncc, princ); + + if (!code) + code = pkrb5_cc_copy_creds(ctx,cc,ncc); + if (code) { + DebugEvent0("kfwcpcc krb5_cc_copy_creds failed"); + goto cleanup; + } + } + if ( ncc ) { + pkrb5_cc_close(ctx, ncc); + ncc = 0; + } + + retval=0; /* success */ + + cleanup: + if (name) + pkrb5_free_unparsed_name(ctx, name); + + if ( cc ) { + pkrb5_cc_close(ctx, cc); + cc = 0; + } + + DeleteFile(filename); + + if ( princ ) { + pkrb5_free_principal(ctx, princ); + princ = 0; + } + + if (ctx) + pkrb5_free_context(ctx); + + return 0; +} + + +int +KFW_destroy_tickets_for_principal(char * user) +{ + krb5_context ctx = 0; + krb5_error_code code; + krb5_principal princ = 0; + krb5_ccache cc = 0; + + if (!pkrb5_init_context) + return 0; + + code = pkrb5_init_context(&ctx); + if (code) return 1; + + code = pkrb5_parse_name(ctx, user, &princ); + if (code) goto loop_cleanup; + + code = KFW_get_ccache(ctx, princ, &cc); + if (code) goto loop_cleanup; + + code = pkrb5_cc_destroy(ctx, cc); + if (!code) cc = 0; + + loop_cleanup: + if ( cc ) { + pkrb5_cc_close(ctx, cc); + cc = 0; + } + if ( princ ) { + pkrb5_free_principal(ctx, princ); + princ = 0; + } + + pkrb5_free_context(ctx); + return 0; +} + + +/* There are scenarios in which an interactive logon will not + * result in the LogonScript being executed. This will result + * in orphaned cache files being left in the Temp directory. + * This function will search for cache files in the Temp + * directory and delete any that are older than five minutes. + */ +void +KFW_cleanup_orphaned_caches(void) +{ + char * temppath = NULL; + char * curdir = NULL; + DWORD count, count2; + WIN32_FIND_DATA FindFileData; + HANDLE hFind = INVALID_HANDLE_VALUE; + FILETIME now; + ULARGE_INTEGER uli_now; + FILETIME expired; + + count = GetTempPath(0, NULL); + if (count <= 0) + return; + temppath = (char *) malloc(count); + if (!temppath) + goto cleanup; + count2 = GetTempPath(count, temppath); + if (count2 <= 0 || count2 > count) + goto cleanup; + + count = GetCurrentDirectory(0, NULL); + curdir = (char *)malloc(count); + if (!curdir) + goto cleanup; + count2 = GetCurrentDirectory(count, curdir); + if (count2 <= 0 || count2 > count) + goto cleanup; + + if (!SetCurrentDirectory(temppath)) + goto cleanup; + + GetSystemTimeAsFileTime(&now); + uli_now.u.LowPart = now.dwLowDateTime; + uli_now.u.HighPart = now.dwHighDateTime; + + uli_now.QuadPart -= 3000000000; /* 5 minutes == 3 billion 100 nano seconds */ + + expired.dwLowDateTime = uli_now.u.LowPart; + expired.dwHighDateTime = uli_now.u.HighPart; + + hFind = FindFirstFile("kfwlogon-*", &FindFileData); + if (hFind != INVALID_HANDLE_VALUE) { + do { + if (CompareFileTime(&FindFileData.ftCreationTime, &expired) < 0) { + DebugEvent("Deleting orphaned cache file: \"%s\"", FindFileData.cFileName); + DeleteFile(FindFileData.cFileName); + } + } while ( FindNextFile(hFind, &FindFileData) ); + } + + SetCurrentDirectory(curdir); + + cleanup: + if (temppath) + free(temppath); + if (hFind != INVALID_HANDLE_VALUE) + FindClose(hFind); + if (curdir) + free(curdir); +} diff --git a/krb5-1-6/src/windows/kfwlogon/kfwcpcc.c b/krb5-1-6/src/windows/kfwlogon/kfwcpcc.c new file mode 100644 index 000000000..fb0861e47 --- /dev/null +++ b/krb5-1-6/src/windows/kfwlogon/kfwcpcc.c @@ -0,0 +1,39 @@ +/* + +Copyright 2005 by the Massachusetts Institute of Technology + +All rights reserved. + +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 the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +#include <windows.h> +#include "kfwlogon.h" + +int main(int argc, char *argv[]) +{ + if ( argc != 2 ) + return 1; + + KFW_initialize(); + + return KFW_copy_file_cache_to_api_cache(argv[1]); +} + + diff --git a/krb5-1-6/src/windows/kfwlogon/kfwlogon.c b/krb5-1-6/src/windows/kfwlogon/kfwlogon.c new file mode 100644 index 000000000..54d7a5a1d --- /dev/null +++ b/krb5-1-6/src/windows/kfwlogon/kfwlogon.c @@ -0,0 +1,634 @@ +/* +Copyright 2005,2006 by the Massachusetts Institute of Technology +Copyright 2007 by Secure Endpoints Inc. + +All rights reserved. + +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 the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +#include "kfwlogon.h" + +#include <io.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> + +#include <winsock2.h> +#include <lm.h> +#include <nb30.h> + +static HANDLE hDLL; + +static HANDLE hInitMutex = NULL; +static BOOL bInit = FALSE; + + +BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved) +{ + hDLL = dll; + switch (reason) { + case DLL_PROCESS_ATTACH: + /* Initialization Mutex */ + hInitMutex = CreateMutex(NULL, FALSE, NULL); + break; + + case DLL_PROCESS_DETACH: + CloseHandle(hInitMutex); + break; + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + default: + /* Everything else succeeds but does nothing. */ + break; + } + + return TRUE; +} + +DWORD APIENTRY NPGetCaps(DWORD index) +{ + switch (index) { + case WNNC_NET_TYPE: + /* We aren't a file system; We don't have our own type; use somebody else's. */ + return WNNC_NET_SUN_PC_NFS; + case WNNC_START: + /* Say we are already started, even though we might wait after we receive NPLogonNotify */ + return 1; + + default: + return 0; + } +} + + +static BOOL +WINAPI +UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen) +{ + CPINFO CodePageInfo; + + GetCPInfo(CP_ACP, &CodePageInfo); + + if (CodePageInfo.MaxCharSize > 1) + // Only supporting non-Unicode strings + return FALSE; + + if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0') + { + // Looks like unicode, better translate it + // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS + WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2, + lpszOutputString, nOutStringLen-1, NULL, NULL); + lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0'; + return TRUE; + } + + lpszOutputString[0] = '\0'; + return FALSE; +} // UnicodeStringToANSI + + +static BOOL +is_windows_vista(void) +{ + static BOOL fChecked = FALSE; + static BOOL fIsWinVista = FALSE; + + if (!fChecked) + { + OSVERSIONINFO Version; + + memset (&Version, 0x00, sizeof(Version)); + Version.dwOSVersionInfoSize = sizeof(Version); + + if (GetVersionEx (&Version)) + { + if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT && + Version.dwMajorVersion >= 6) + fIsWinVista = TRUE; + } + fChecked = TRUE; + } + + return fIsWinVista; +} + + +/* Construct a Logon Script that will cause the LogonEventHandler to be executed + * under in the logon session + */ + +#define RUNDLL32_CMDLINE "rundll32.exe kfwlogon.dll,LogonEventHandler " +VOID +ConfigureLogonScript(LPWSTR *lpLogonScript, char * filename) { + DWORD dwLogonScriptLen; + LPWSTR lpScript; + LPSTR lpTemp; + + if (!lpLogonScript) + return; + *lpLogonScript = NULL; + + if (!filename) + return; + + dwLogonScriptLen = strlen(RUNDLL32_CMDLINE) + strlen(filename) + 2; + lpTemp = (LPSTR) malloc(dwLogonScriptLen); + if (!lpTemp) + return; + + _snprintf(lpTemp, dwLogonScriptLen, "%s%s", RUNDLL32_CMDLINE, filename); + + SetLastError(0); + dwLogonScriptLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, NULL, 0); + DebugEvent("ConfigureLogonScript %s requires %d bytes gle=0x%x", lpTemp, dwLogonScriptLen, GetLastError()); + + lpScript = LocalAlloc(LMEM_ZEROINIT, dwLogonScriptLen * 2); + if (lpScript) { + if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpTemp, -1, lpScript, 2 * dwLogonScriptLen)) + *lpLogonScript = lpScript; + else { + DebugEvent("ConfigureLogonScript - MultiByteToWideChar failed gle = 0x%x", GetLastError()); + LocalFree(lpScript); + } + } else { + DebugEvent("LocalAlloc failed gle=0x%x", GetLastError()); + } + free(lpTemp); +} + + +DWORD APIENTRY NPLogonNotify( + PLUID lpLogonId, + LPCWSTR lpAuthentInfoType, + LPVOID lpAuthentInfo, + LPCWSTR lpPreviousAuthentInfoType, + LPVOID lpPreviousAuthentInfo, + LPWSTR lpStationName, + LPVOID StationHandle, + LPWSTR *lpLogonScript) +{ + char uname[MAX_USERNAME_LENGTH+1]=""; + char password[MAX_PASSWORD_LENGTH+1]=""; + char logonDomain[MAX_DOMAIN_LENGTH+1]=""; + + MSV1_0_INTERACTIVE_LOGON *IL; + + DWORD code = 0; + + char *reason; + char *ctemp; + + BOOLEAN interactive = TRUE; + HWND hwndOwner = (HWND)StationHandle; + BOOLEAN lowercased_name = TRUE; + + /* Can we load KFW binaries? */ + if ( !KFW_is_available() ) + return 0; + + DebugEvent0("NPLogonNotify start"); + + /* Remote Desktop / Terminal Server connections to existing sessions + * are interactive logons. Unfortunately, because the session already + * exists the logon script does not get executed and this prevents + * us from being able to execute the rundll32 entrypoint + * LogonEventHandlerA which would process the credential cache this + * routine will produce. Therefore, we must cleanup orphaned cache + * files from this routine. We will take care of it before doing + * anything else. + */ + KFW_cleanup_orphaned_caches(); + + /* Are we interactive? */ + if (lpStationName) + interactive = (wcsicmp(lpStationName, L"WinSta0") == 0); + + if ( !interactive ) { + char station[64]="station"; + DWORD rv; + + SetLastError(0); + rv = WideCharToMultiByte(CP_UTF8, 0, lpStationName, -1, + station, sizeof(station), NULL, NULL); + DebugEvent("Skipping NPLogonNotify- LoginId(%d,%d) - Interactive(%d:%s) - gle %d", + lpLogonId->HighPart, lpLogonId->LowPart, interactive, rv != 0 ? station : "failure", GetLastError()); + return 0; + } else + DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart); + + /* Initialize Logon Script to none */ + *lpLogonScript=NULL; + + /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for + * our purposes */ + + if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") && + wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") ) + { + char msg[64]; + WideCharToMultiByte(CP_ACP, 0, lpAuthentInfoType, -1, + msg, sizeof(msg), NULL, NULL); + msg[sizeof(msg)-1]='\0'; + DebugEvent("NPLogonNotify - Unsupported Authentication Info Type: %s", msg); + return 0; + } + + IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo; + + /* Convert from Unicode to ANSI */ + + /*TODO: Use SecureZeroMemory to erase passwords */ + if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) || + !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) || + !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH)) + return 0; + + /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */ + ctemp = strchr(uname, '@'); + if (ctemp) *ctemp = 0; + + /* is the name all lowercase? */ + for ( ctemp = uname; *ctemp ; ctemp++) { + if ( !islower(*ctemp) ) { + lowercased_name = FALSE; + break; + } + } + + code = KFW_get_cred(uname, password, 0, &reason); + DebugEvent("NPLogonNotify - KFW_get_cred uname=[%s] code=[%d]",uname, code); + + /* remove any kerberos 5 tickets currently held by the SYSTEM account + * for this user + */ + if (!code) { + char filename[MAX_PATH+1] = ""; + char acctname[MAX_USERNAME_LENGTH+MAX_DOMAIN_LENGTH+3]=""; + PSID pUserSid = NULL; + LPTSTR pReferencedDomainName = NULL; + DWORD dwSidLen = 0, dwDomainLen = 0, count; + SID_NAME_USE eUse; + + if (_snprintf(acctname, sizeof(acctname), "%s\\%s", logonDomain, uname) < 0) { + code = -1; + goto cleanup; + } + + count = GetTempPath(sizeof(filename), filename); + if (count == 0 || count > (sizeof(filename)-1)) { + code = -1; + goto cleanup; + } + + if (_snprintf(filename, sizeof(filename), "%s\\kfwlogon-%x.%x", + filename, lpLogonId->HighPart, lpLogonId->LowPart) < 0) + { + code = -1; + goto cleanup; + } + + KFW_copy_cache_to_system_file(uname, filename); + + /* Need to determine the SID */ + + /* First get the size of the required buffers */ + LookupAccountName (NULL, + acctname, + pUserSid, + &dwSidLen, + pReferencedDomainName, + &dwDomainLen, + &eUse); + if(dwSidLen){ + pUserSid = (PSID) malloc (dwSidLen); + memset(pUserSid,0,dwSidLen); + } + + if(dwDomainLen){ + pReferencedDomainName = (LPTSTR) malloc (dwDomainLen * sizeof(TCHAR)); + memset(pReferencedDomainName,0,dwDomainLen * sizeof(TCHAR)); + } + + //Now get the SID and the domain name + if (pUserSid && LookupAccountName( NULL, + acctname, + pUserSid, + &dwSidLen, + pReferencedDomainName, + &dwDomainLen, + &eUse)) + { + DebugEvent("LookupAccountName obtained user %s sid in domain %s", acctname, pReferencedDomainName); + code = KFW_set_ccache_dacl_with_user_sid(filename, pUserSid); + +#ifdef USE_WINLOGON_EVENT + /* If we are on Vista, setup a LogonScript + * that will execute the LogonEventHandler entry point via rundll32.exe + */ + if (is_windows_vista()) { + ConfigureLogonScript(lpLogonScript, filename); + if (*lpLogonScript) + DebugEvent0("LogonScript assigned"); + else + DebugEvent0("No Logon Script"); + } +#else + ConfigureLogonScript(lpLogonScript, filename); + if (*lpLogonScript) + DebugEvent0("LogonScript assigned"); + else + DebugEvent0("No Logon Script"); +#endif + } else { + DebugEvent0("LookupAccountName failed"); + DeleteFile(filename); + code = -1; + } + + cleanup: + if (pUserSid) + free(pUserSid); + if (pReferencedDomainName) + free(pReferencedDomainName); + } + + KFW_destroy_tickets_for_principal(uname); + + if (code) { + char msg[128]; + HANDLE h; + char *ptbuf[1]; + + StringCbPrintf(msg, sizeof(msg), "Kerberos ticket acquisition failed: %s", reason); + + h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME); + ptbuf[0] = msg; + ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL, 1, 0, ptbuf, NULL); + DeregisterEventSource(h); + SetLastError(code); + } + + if (code) + DebugEvent0("NPLogonNotify failure"); + else + DebugEvent0("NPLogonNotify success"); + + return code; +} + + +DWORD APIENTRY NPPasswordChangeNotify( + LPCWSTR lpAuthentInfoType, + LPVOID lpAuthentInfo, + LPCWSTR lpPreviousAuthentInfoType, + LPVOID lpPreviousAuthentInfo, + LPWSTR lpStationName, + LPVOID StationHandle, + DWORD dwChangeInfo) +{ + return 0; +} + +#include <userenv.h> +#include <Winwlx.h> + +#ifdef COMMENT +typedef struct _WLX_NOTIFICATION_INFO { + ULONG Size; + ULONG Flags; + PWSTR UserName; + PWSTR Domain; + PWSTR WindowStation; + HANDLE hToken; + HDESK hDesktop; + PFNMSGECALLBACK pStatusCallback; +} WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO; +#endif + +VOID KFW_Startup_Event( PWLX_NOTIFICATION_INFO pInfo ) +{ + DebugEvent0("KFW_Startup_Event"); +} + +static BOOL +GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData) +{ + NTSTATUS Status = 0; +#if 0 + HANDLE TokenHandle; +#endif + TOKEN_STATISTICS Stats; + DWORD ReqLen; + BOOL Success; + + if (!ppSessionData) + return FALSE; + *ppSessionData = NULL; + +#if 0 + Success = OpenProcessToken( HANDLE GetCurrentProcess(), TOKEN_QUERY, &TokenHandle ); + if ( !Success ) + return FALSE; +#endif + + Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen ); +#if 0 + CloseHandle( TokenHandle ); +#endif + if ( !Success ) + return FALSE; + + Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData ); + if ( FAILED(Status) || !ppSessionData ) + return FALSE; + + return TRUE; +} + +VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo ) +{ +#ifdef USE_WINLOGON_EVENT + WCHAR szUserW[128] = L""; + char szUserA[128] = ""; + char szPath[MAX_PATH] = ""; + char szLogonId[128] = ""; + DWORD count; + char filename[MAX_PATH] = ""; + char newfilename[MAX_PATH] = ""; + char commandline[MAX_PATH+256] = ""; + STARTUPINFO startupinfo; + PROCESS_INFORMATION procinfo; + HANDLE hf = NULL; + + LUID LogonId = {0, 0}; + PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL; + + HKEY hKey1 = NULL, hKey2 = NULL; + + DebugEvent0("KFW_Logon_Event - Start"); + + GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData ); + + if ( pLogonSessionData ) { + LogonId = pLogonSessionData->LogonId; + DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart); + + _snprintf(szLogonId, sizeof(szLogonId), "kfwlogon-%d.%d",LogonId.HighPart, LogonId.LowPart); + LsaFreeReturnBuffer( pLogonSessionData ); + } else { + DebugEvent0("KFW_Logon_Event - Unable to determine LogonId"); + return; + } + + count = GetEnvironmentVariable("TEMP", filename, sizeof(filename)); + if ( count > sizeof(filename) || count == 0 ) { + GetWindowsDirectory(filename, sizeof(filename)); + } + + if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) { + DebugEvent0("KFW_Logon_Event - filename too long"); + return; + } + + strcat(filename, "\\"); + strcat(filename, szLogonId); + + hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (hf == INVALID_HANDLE_VALUE) { + DebugEvent0("KFW_Logon_Event - file cannot be opened"); + return; + } + CloseHandle(hf); + + if (KFW_set_ccache_dacl(filename, pInfo->hToken)) { + DebugEvent0("KFW_Logon_Event - unable to set dacl"); + DeleteFile(filename); + return; + } + + if (KFW_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) { + DebugEvent0("KFW_Logon_Event - unable to obtain temp directory"); + return; + } + + if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) { + DebugEvent0("KFW_Logon_Event - new filename too long"); + return; + } + + strcat(newfilename, "\\"); + strcat(newfilename, szLogonId); + + if (!MoveFileEx(filename, newfilename, + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { + DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError()); + return; + } + + _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", newfilename); + + GetStartupInfo(&startupinfo); + if (CreateProcessAsUser( pInfo->hToken, + "kfwcpcc.exe", + commandline, + NULL, + NULL, + FALSE, + CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, + NULL, + NULL, + &startupinfo, + &procinfo)) + { + DebugEvent("KFW_Logon_Event - CommandLine %s", commandline); + + WaitForSingleObject(procinfo.hProcess, 30000); + + CloseHandle(procinfo.hThread); + CloseHandle(procinfo.hProcess); + } else { + DebugEvent0("KFW_Logon_Event - CreateProcessFailed"); + } + + DeleteFile(newfilename); + + DebugEvent0("KFW_Logon_Event - End"); +#endif /* USE_WINLOGON_EVENT */ +} + + +/* Documentation on the use of RunDll32 entrypoints can be found + * at http://support.microsoft.com/kb/164787 + */ +void CALLBACK +LogonEventHandlerA(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) +{ + HANDLE hf = NULL; + char commandline[MAX_PATH+256] = ""; + STARTUPINFO startupinfo; + PROCESS_INFORMATION procinfo; + + DebugEvent0("LogonEventHandler - Start"); + + /* Validate lpszCmdLine as a file */ + hf = CreateFile(lpszCmdLine, GENERIC_READ | DELETE, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (hf == INVALID_HANDLE_VALUE) { + DebugEvent("LogonEventHandler - \"%s\" cannot be opened", lpszCmdLine); + return; + } + CloseHandle(hf); + + + _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", lpszCmdLine); + + GetStartupInfo(&startupinfo); + SetLastError(0); + if (CreateProcess( NULL, + commandline, + NULL, + NULL, + FALSE, + CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, + NULL, + NULL, + &startupinfo, + &procinfo)) + { + DebugEvent("KFW_Logon_Event - CommandLine %s", commandline); + + WaitForSingleObject(procinfo.hProcess, 30000); + + CloseHandle(procinfo.hThread); + CloseHandle(procinfo.hProcess); + } else { + DebugEvent("KFW_Logon_Event - CreateProcessFailed \"%s\" GLE 0x%x", + commandline, GetLastError()); + DebugEvent("KFW_Logon_Event PATH %s", getenv("PATH")); + } + + DeleteFile(lpszCmdLine); + + DebugEvent0("KFW_Logon_Event - End"); +} diff --git a/krb5-1-6/src/windows/kfwlogon/kfwlogon.def b/krb5-1-6/src/windows/kfwlogon/kfwlogon.def new file mode 100644 index 000000000..85ba1028c --- /dev/null +++ b/krb5-1-6/src/windows/kfwlogon/kfwlogon.def @@ -0,0 +1,14 @@ +LIBRARY KFWLOGON + +EXPORTS + + DllEntryPoint + NPGetCaps + NPLogonNotify + NPPasswordChangeNotify + KFW_Logon_Event + LogonEventHandlerA + + + + diff --git a/krb5-1-6/src/windows/kfwlogon/kfwlogon.h b/krb5-1-6/src/windows/kfwlogon/kfwlogon.h new file mode 100644 index 000000000..2f1a62b6e --- /dev/null +++ b/krb5-1-6/src/windows/kfwlogon/kfwlogon.h @@ -0,0 +1,215 @@ +/* + +Copyright 2005,2006 by the Massachusetts Institute of Technology +Copyright 2007 by Secure Endpoints Inc. + +All rights reserved. + +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 the Massachusetts +Institute of Technology (M.I.T.) not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/* We only support VC 1200 and above anyway */ +#pragma once + +/* _WIN32_WINNT must be 0x0501 or greater to pull in definition of + * all required LSA data types when the Vista SDK NtSecAPI.h is used. + */ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#else +#if _WIN32_WINNT < 0x0501 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#endif + +#include <windows.h> +#include <npapi.h> +#define SECURITY_WIN32 +#include <security.h> +#include <ntsecapi.h> +#include <tchar.h> +#include <strsafe.h> + +typedef int errcode_t; + +#include <loadfuncs-lsa.h> +#include <krb5.h> +#include <loadfuncs-com_err.h> +#include <loadfuncs-krb5.h> +#include <loadfuncs-profile.h> +#include <loadfuncs-leash.h> + +// service definitions +#define SERVICE_DLL "advapi32.dll" +typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD); +typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD); +typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS); +typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE); + +/* In order to avoid including the private CCAPI headers */ +typedef int cc_int32; + +#define CC_API_VER_1 1 +#define CC_API_VER_2 2 + +#define CCACHE_API cc_int32 + +/* +** 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 + +enum { + CC_CRED_VUNKNOWN = 0, // For validation + CC_CRED_V4 = 1, + CC_CRED_V5 = 2, + CC_CRED_VMAX = 3 // For validation +}; + +typedef struct opaque_dll_control_block_type* apiCB; +typedef struct _infoNC { + char* name; + char* principal; + cc_int32 vers; +} infoNC; + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_initialize, + ( + apiCB** cc_ctx, // < DLL's primary control structure. + // returned here, passed everywhere else + cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1) + cc_int32* api_supported, // < if ~NULL, max ver supported by DLL + const char** vendor // < if ~NULL, vendor name in read only C string + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_shutdown, + ( + apiCB** cc_ctx // <> DLL's primary control structure. NULL after + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_get_NC_info, + ( + apiCB* cc_ctx, // > DLL's primary control structure + struct _infoNC*** ppNCi // < (NULL before call) null terminated, + // list of a structs (free via cc_free_infoNC()) + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_free_NC_info, + ( + apiCB* cc_ctx, + struct _infoNC*** ppNCi // < free list of structs returned by + // cc_get_cache_names(). set to NULL on return + ) +); +/* End private ccapiv2 headers */ + +#define CCAPI_DLL "krbcc32.dll" + + +/* */ +#define MAX_USERNAME_LENGTH 256 +#define MAX_PASSWORD_LENGTH 256 +#define MAX_DOMAIN_LENGTH 256 + +#define KFW_LOGON_EVENT_NAME TEXT("MIT Kerberos") + +BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved); + +DWORD APIENTRY NPGetCaps(DWORD index); + +DWORD APIENTRY NPLogonNotify( + PLUID lpLogonId, + LPCWSTR lpAuthentInfoType, + LPVOID lpAuthentInfo, + LPCWSTR lpPreviousAuthentInfoType, + LPVOID lpPreviousAuthentInfo, + LPWSTR lpStationName, + LPVOID StationHandle, + LPWSTR *lpLogonScript); + +DWORD APIENTRY NPPasswordChangeNotify( + LPCWSTR lpAuthentInfoType, + LPVOID lpAuthentInfo, + LPCWSTR lpPreviousAuthentInfoType, + LPVOID lpPreviousAuthentInfo, + LPWSTR lpStationName, + LPVOID StationHandle, + DWORD dwChangeInfo); + +#ifdef __cplusplus +extern "C" { +#endif + +void UnloadFuncs(FUNC_INFO [], HINSTANCE); + +int LoadFuncs(const char*, FUNC_INFO [], HINSTANCE*, int*, int, int, int); + +void DebugEvent0(char *a); +void DebugEvent(char *b,...); + +DWORD MapAuthError(DWORD code); + +static BOOL WINAPI UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen); + +int KFW_is_available(void); +int KFW_get_cred( char * username, char * password, int lifetime, char ** reasonP ); +void KFW_copy_cache_to_system_file(const char * user, const char * filename); +int KFW_destroy_tickets_for_principal(char * user); +int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken); +int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID); +int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size); +void KFW_cleanup_orphaned_caches(void); + +void CALLBACK LogonEventHandlerA(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); + +#ifdef __cplusplus +} +#endif diff --git a/krb5-1-6/src/windows/lib/Makefile.in b/krb5-1-6/src/windows/lib/Makefile.in new file mode 100644 index 000000000..c911de701 --- /dev/null +++ b/krb5-1-6/src/windows/lib/Makefile.in @@ -0,0 +1,17 @@ +BUILDTOP = ..\.. + +lib-windows: $(OUTPRE)libwin.lib + +SRCS= vardlg.c gic.c registry.c + +OBJS= $(OUTPRE)vardlg.obj $(OUTPRE)gic.obj $(OUTPRE)registry.obj + +$(OUTPRE)libwin.lib: $(OBJS) + lib /nologo /out:$*.lib $(OBJS) + +all-windows:: lib-windows + +clean-windows:: + $(RM) $(OUTPRE)*.exp $(OUTPRE)*.map $(OUTPRE)libwin.lib $(OUTPRE)*.obj + +install-windows:: diff --git a/krb5-1-6/src/windows/lib/cacheapi.h b/krb5-1-6/src/windows/lib/cacheapi.h new file mode 100644 index 000000000..722eb7e54 --- /dev/null +++ b/krb5-1-6/src/windows/lib/cacheapi.h @@ -0,0 +1,458 @@ +/* + * $Id$ + * + * Copyright 1997 by the Regents of the University of Michigan + * + * This software is being provided to you, the LICENSEE, by the + * Regents of the University of Michigan (UM) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Permission to use, copy, modify and distribute this software and its + * documentation for any purpose and without fee or royalty is hereby + * granted, provided that you agree to comply with the following copyright + * notice and statements, including the disclaimer, and that the same + * appear on ALL copies of the software and documentation, including + * modifications that you make for internal use or for distribution: + * + * Copyright 1997 by the Regents of the University of Michigan. + * All rights reserved. + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND UM MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, UM MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY + * OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED + * SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the University of Michigan or UM may NOT be used in + * advertising or publicity pertaining to distribution of the software. + * Title to copyright in this software and any associated documentation + * shall at all times remain with UM, and USER agrees to preserve same. + * + * The University of Michigan + * c/o Steve Rothwell <sgr@umich.edu> + * 535 W. William Street + * Ann Arbor, Michigan 48013-4943 + * U.S.A. + */ + +/* +** CacheAPI.h +** +** The externally visible functions and data structures +** for the Kerberos Common Cache DLL +** This should be the ONLY externally visible file. +** This is ALL anyone should need to call the API. +** +** +*/ + +#ifndef Krb_CCacheAPI_h_ +#define Krb_CCacheAPI_h_ + +#include <windows.h> + +//typedef int cc_int32; +#define cc_int32 long +#define cc_uint32 unsigned long + +typedef cc_int32 cc_time_t; + +#define CC_API_VER_1 1 +#define CC_API_VER_2 2 + +//enum { +// CC_API_VER_1 = 1, +// CC_API_VER_2 = 2 +//}; + +#define CCACHE_API __declspec(dllexport) cc_int32 + +/* +** 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 + + +/* +** types, structs, & constants +*/ +// Flag bits promised by Ted "RSN" +#define CC_FLAGS_RESERVED 0xFFFFFFFF + +typedef cc_uint32 cc_nc_flags; // set via constants above + +typedef struct opaque_dll_control_block_type* apiCB; +typedef struct opaque_ccache_pointer_type* ccache_p; +typedef struct opaque_credential_iterator_type* ccache_cit; + +#if 0 +enum _cc_data_type { + type_ticket = 0, /* 0 for ticket, second_ticket */ + /* Ted's draft spec says these are to be + "as defined in the Kerberos V5 protocol" + all I can find are typdefs, + can't find an enumerated type or #define + */ + type_address, /* = <"as defined in the Kerberos V5 protocol"> */ + type_authdata, /* = <"as defined in the Kerberos V5 protocol"> */ + type_encryption, /* = <"as defined in the Kerberos V5 protocol"> */ + cc_data_type_max /* for validation */ +}; +#endif + +typedef struct _cc_data +{ + cc_uint32 type; // should be one of _cc_data_type + cc_uint32 length; + unsigned char* data; // the proverbial bag-o-bits +} cc_data; + +// V5 Credentials +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; + cc_uint32 is_skey; + cc_uint32 ticket_flags; + cc_data ** addresses; + cc_data ticket; + cc_data second_ticket; + cc_data ** authdata; +} cc_creds; + + +// begin V4 stuff +// use an enumerated type so all callers infer the same meaning +// these values are what krbv4win uses internally. +#define STK_AFS 0 +#define STK_DES 1 + +// K4 uses a MAX_KTXT_LEN of 1250 to hold a ticket +// K95 uses 256 +// To be safe I'll use the larger number, but a factor of 5!!! +#define MAX_V4_CRED_LEN 1250 + +// V4 Credentials + +enum { + KRB_NAME_SZ = 40, + KRB_INSTANCE_SZ = 40, + KRB_REALM_SZ = 40 +}; + +typedef struct cc_V4credential { + unsigned char kversion; + char principal[KRB_NAME_SZ + 1]; + char principal_instance[KRB_INSTANCE_SZ + 1]; + char service[KRB_NAME_SZ + 1]; + char service_instance[KRB_INSTANCE_SZ + 1]; + char realm[KRB_REALM_SZ + 1]; + unsigned char session_key[8]; + cc_int32 kvno; // k95 used BYTE skvno + cc_int32 str_to_key; // k4 infers dynamically, k95 stores + long issue_date; // k95 called this issue_time + cc_int32 lifetime; // k95 used LONG expiration_time + cc_uint32 address; // IP Address of local host + cc_int32 ticket_sz; // k95 used BYTE, k4 ktext uses int to hold up to 1250 + unsigned char ticket[MAX_V4_CRED_LEN]; + unsigned long oops; // zero to catch runaways +} V4Cred_type; + +enum { + CC_CRED_VUNKNOWN = 0, // For validation + CC_CRED_V4 = 1, + CC_CRED_V5 = 2, + CC_CRED_VMAX = 3 // For validation +}; + +typedef union cred_ptr_union_type { + V4Cred_type* pV4Cred; + cc_creds* pV5Cred; +} cred_ptr_union; + +typedef struct cred_union_type { + cc_int32 cred_type; + cred_ptr_union cred; +} cred_union; + +typedef struct _infoNC { + char* name; + char* principal; + cc_int32 vers; +} infoNC; + + +/* +** The official (externally visible) API +*/ + +#ifdef __cplusplus +extern "C" /* this entire list of functions */ +{ +#endif /* __cplusplus */ + +/* +** Main cache routines : initialize, shutdown, get_cache_names, & get_change_time +*/ +CCACHE_API +cc_initialize( + apiCB** cc_ctx, // < DLL's primary control structure. + // returned here, passed everywhere else + cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1) + cc_int32* api_supported, // < if ~NULL, max ver supported by DLL + const char** vendor // < if ~NULL, vendor name in read only C string + ); + +CCACHE_API +cc_shutdown( + apiCB** cc_ctx // <> DLL's primary control structure. NULL after call. + ); + +CCACHE_API +cc_get_change_time( + apiCB* cc_ctx, // > DLL's primary control structure + cc_time_t* time // < time of last change to main cache + ); + + +/* +** Named Cache (NC) routines +** create, open, close, destroy, get_principal, get_cred_version, & +** lock_request +** +** Multiple NCs are allowed within the main cache. Each has a Name +** and kerberos version # (V4 or V5). Caller gets "ccache_ptr"s for +** NCs. +*/ +CCACHE_API +cc_create( + apiCB* cc_ctx, // > DLL's primary control structure + const char* name, // > name of cache to be [destroyed if exists, then] created + const char* principal, + cc_int32 vers, // > ticket version (CC_CRED_V4 or CC_CRED_V5) + cc_uint32 cc_flags, // > options + ccache_p** ccache_ptr // < NC control structure + ); + +CCACHE_API +cc_open( + apiCB* cc_ctx, // > DLL's primary control structure + const char* name, // > name of pre-created cache + cc_int32 vers, // > ticket version (CC_CRED_V4 or CC_CRED_V5) + cc_uint32 cc_flags, // > options + ccache_p** ccache_ptr // < NC control structure + ); + +CCACHE_API +cc_close( + apiCB* cc_ctx, // > DLL's primary control structure + ccache_p** ccache_ptr // <> NC control structure. NULL after call. + ); + +CCACHE_API +cc_destroy( + apiCB* cc_ctx, // > DLL's primary control structure + ccache_p** ccache_ptr // <> NC control structure. NULL after call. + ); + +/* +** Ways to get information about the NCs +*/ + +CCACHE_API +cc_seq_fetch_NCs_begin( + apiCB* cc_ctx, + ccache_cit** itNCs + ); + +CCACHE_API +cc_seq_fetch_NCs_end( + apiCB* cc_ctx, + ccache_cit** itNCs + ); + +CCACHE_API +cc_seq_fetch_NCs_next( + apiCB* cc_ctx, + ccache_p** ccache_ptr, + ccache_cit* itNCs + ); + +CCACHE_API +cc_seq_fetch_NCs( + apiCB* cc_ctx, // > DLL's primary control structure + ccache_p** ccache_ptr, // < NC control structure (free via cc_close()) + ccache_cit** itNCs // <> iterator used by DLL, + // set to NULL before first call + // returned NULL at CC_END + ); + +CCACHE_API +cc_get_NC_info( + apiCB* cc_ctx, // > DLL's primary control structure + struct _infoNC*** ppNCi // < (NULL before call) null terminated, + // list of a structs (free via cc_free_infoNC()) + ); + +CCACHE_API +cc_free_NC_info( + apiCB* cc_ctx, + struct _infoNC*** ppNCi // < free list of structs returned by + // cc_get_cache_names(). set to NULL on return + ); + +/* +** Functions that provide distinguishing characteristics of NCs. +*/ + +CCACHE_API +cc_get_name( + apiCB* cc_ctx, // > DLL's primary control structure + const ccache_p* ccache_ptr, // > NC control structure + char** name // < name of NC associated with ccache_ptr + // (free via cc_free_name()) + ); + +CCACHE_API +cc_set_principal( + apiCB* cc_ctx, // > DLL's primary control structure + const ccache_p* ccache_pointer, // > NC control structure + const cc_int32 vers, + const char* principal // > name of principal associated with NC + // Free via cc_free_principal() + ); + +CCACHE_API +cc_get_principal( + apiCB* cc_ctx, // > DLL's primary control structure + const ccache_p* ccache_pointer, // > NC control structure + char** principal // < name of principal associated with NC + // Free via cc_free_principal() + ); + +CCACHE_API +cc_get_cred_version( + apiCB* cc_ctx, // > DLL's primary control structure + const ccache_p* ccache_ptr, // > NC control structure + cc_int32* vers // < ticket version associated with NC + ); + +#define CC_LOCK_UNLOCK 1 +#define CC_LOCK_READER 2 +#define CC_LOCK_WRITER 3 +#define CC_LOCK_NOBLOCK 16 + +CCACHE_API +cc_lock_request( + apiCB* cc_ctx, // > DLL's primary control structure + const ccache_p* ccache_ptr, // > NC control structure + const cc_int32 lock_type // > one (or combination) of above defined + // lock types + ); + + +/* +** Credentials routines (work within an NC) +** store, remove_cred, seq_fetch_creds +*/ +CCACHE_API +cc_store( + apiCB* cc_ctx, // > DLL's primary control structure + ccache_p* ccache_ptr, // > NC control structure + const cred_union creds // > credentials to be copied into NC + ); + +CCACHE_API +cc_remove_cred( + apiCB* cc_ctx, // > DLL's primary control structure + ccache_p* ccache_ptr, // > NC control structure + const cred_union cred // > credentials to remove from NC + ); + +CCACHE_API +cc_seq_fetch_creds( + apiCB* cc_ctx, // > DLL's primary control structure + const ccache_p* ccache_ptr, // > NC control structure + cred_union** creds, // < filled in by DLL, free via cc_free_creds() + ccache_cit** itCreds // <> iterator used by DLL, set to NULL + // before first call -- Also NULL for final + // call if loop ends before CC_END + ); + +CCACHE_API +cc_seq_fetch_creds_begin( + apiCB* cc_ctx, + const ccache_p* ccache_ptr, + ccache_cit** itCreds + ); + +CCACHE_API +cc_seq_fetch_creds_end( + apiCB* cc_ctx, + ccache_cit** itCreds + ); + +CCACHE_API +cc_seq_fetch_creds_next( + apiCB* cc_ctx, + cred_union** cred, + ccache_cit* itCreds + ); + +/* +** methods of liberation, +** or freeing space via the free that goes with the malloc used to get it +** It's important to use the free carried in the DLL, not the one supplied +** by your compiler vendor. +** +** freeing a NULL pointer is not treated as an error +*/ +CCACHE_API +cc_free_principal( + apiCB* cc_ctx, // > DLL's primary control structure + char** principal // <> ptr to principal to be freed, returned as NULL + // (from cc_get_principal()) + ); + +CCACHE_API +cc_free_name( + apiCB* cc_ctx, // > DLL's primary control structure + char** name // <> ptr to name to be freed, returned as NULL + // (from cc_get_name()) + ); + +CCACHE_API +cc_free_creds( + apiCB* cc_ctx, // > DLL's primary control structure + cred_union** pCred // <> cred (from cc_seq_fetch_creds()) to be freed + // Returned as NULL. + ); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif /* __cplusplus */ + +#endif /* Krb_CCacheAPI_h_ */ diff --git a/krb5-1-6/src/windows/lib/gic.c b/krb5-1-6/src/windows/lib/gic.c new file mode 100644 index 000000000..51e752dc0 --- /dev/null +++ b/krb5-1-6/src/windows/lib/gic.c @@ -0,0 +1,157 @@ +/* + * 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 *name, + 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), name, 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/krb5-1-6/src/windows/lib/gic.h b/krb5-1-6/src/windows/lib/gic.h new file mode 100644 index 000000000..23213163d --- /dev/null +++ b/krb5-1-6/src/windows/lib/gic.h @@ -0,0 +1,28 @@ +/* + * 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 *, + const char *, int, krb5_prompt []); + +#endif /* _WINDOWS_LIB_GIC_H */ diff --git a/krb5-1-6/src/windows/lib/registry.c b/krb5-1-6/src/windows/lib/registry.c new file mode 100644 index 000000000..7dfbb5bff --- /dev/null +++ b/krb5-1-6/src/windows/lib/registry.c @@ -0,0 +1,231 @@ +/* + * 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/krb5-1-6/src/windows/lib/registry.h b/krb5-1-6/src/windows/lib/registry.h new file mode 100644 index 000000000..d628d2bcb --- /dev/null +++ b/krb5-1-6/src/windows/lib/registry.h @@ -0,0 +1,40 @@ +/* + * 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/krb5-1-6/src/windows/lib/vardlg.c b/krb5-1-6/src/windows/lib/vardlg.c new file mode 100644 index 000000000..dae8cdbbc --- /dev/null +++ b/krb5-1-6/src/windows/lib/vardlg.c @@ -0,0 +1,453 @@ +/* + * 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 *name, 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, name ? + strlen(name) < 30 ? name : "Kerberos V5" : + "Kerberos V5", + "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/krb5-1-6/src/windows/lib/vardlg.h b/krb5-1-6/src/windows/lib/vardlg.h new file mode 100644 index 000000000..e609d4a1d --- /dev/null +++ b/krb5-1-6/src/windows/lib/vardlg.h @@ -0,0 +1,32 @@ +/* + * 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 *, const char *, WORD, krb5_prompt *, WORD); + +void vardlg_config(HWND, WORD, const char *, WORD, krb5_prompt *, WORD); + +#endif /* _WINDOWS_LIB_VARDLG_H */ diff --git a/krb5-1-6/src/windows/ms2mit/Makefile.in b/krb5-1-6/src/windows/ms2mit/Makefile.in new file mode 100644 index 000000000..0bb4d8d70 --- /dev/null +++ b/krb5-1-6/src/windows/ms2mit/Makefile.in @@ -0,0 +1,41 @@ +# Makefile for the Microsoft to MIT cache converter. +# Works for k5 release only. +# + +thisconfigdir=./.. +myfulldir=windows/ms2mit +mydir=. +BUILDTOP=$(REL)..$(S).. +DEFINES = +PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR) + +VERSIONRC = $(BUILDTOP)\windows\version.rc +RCFLAGS=$(CPPFLAGS) -I$(SRCTOP) -D_WIN32 -DRES_ONLY + +MS2MIT=$(OUTPRE)ms2mit.exe +MIT2MS=$(OUTPRE)mit2ms.exe + +MS2MITRES=$(MS2MIT:.exe=.res) +MIT2MSRES=$(MIT2MS:.exe=.res) + +$(MS2MITRES): $(VERSIONRC) + $(RC) $(RCFLAGS) -DMS2MIT_APP -fo $@ -r $** +$(MIT2MSRES): $(VERSIONRC) + $(RC) $(RCFLAGS) -DMIT2MS_APP -fo $@ -r $** + +all-windows:: $(MS2MIT) $(MIT2MS) + +$(MS2MIT): $(OUTPRE)ms2mit.obj $(MS2MITRES) + link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)ms2mit.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj user32.lib advapi32.lib $(KLIB) $(CLIB) $(MS2MITRES) + $(_VC_MANIFEST_EMBED_EXE) + +$(MIT2MS): $(OUTPRE)mit2ms.obj $(MIT2MSRES) + link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)mit2ms.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.obj user32.lib advapi32.lib $(KLIB) $(CLIB) $(MIT2MSRES) + $(_VC_MANIFEST_EMBED_EXE) + +install:: + copy $(OUTPRE)ms2mit.exe $(DESTDIR) + copy $(OUTPRE)mit2ms.exe $(DESTDIR) + +clean:: + $(RM) $(OUTPRE)*.exe diff --git a/krb5-1-6/src/windows/ms2mit/mit2ms.c b/krb5-1-6/src/windows/ms2mit/mit2ms.c new file mode 100644 index 000000000..6f30d9f6d --- /dev/null +++ b/krb5-1-6/src/windows/ms2mit/mit2ms.c @@ -0,0 +1,149 @@ +/* + * mit2ms.c + * + */ +/* + * Copyright (C) 2003,2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include "krb5.h" +#include <stdio.h> +#include <string.h> + +extern int optind; +extern char *optarg; + +static char *prog; + +static void +xusage(void) +{ + fprintf(stderr, "xusage: %s [-c ccache]\n", prog); + exit(1); +} + +void +main( + int argc, + char *argv[] + ) +{ + krb5_context kcontext; + krb5_error_code code; + krb5_ccache ccache=NULL; + krb5_ccache mslsa_ccache=NULL; + krb5_cc_cursor cursor; + krb5_creds creds; + krb5_principal princ; + int initial_ticket = 0; + int option; + char * ccachestr = 0; + + prog = strrchr(argv[0], '/'); + prog = prog ? (prog + 1) : argv[0]; + + while ((option = getopt(argc, argv, "c:h")) != -1) { + switch (option) { + case 'c': + ccachestr = optarg; + break; + case 'h': + default: + xusage(); + break; + } + } + + if (code = krb5_init_context(&kcontext)) { + com_err(argv[0], code, "while initializing kerberos library"); + exit(1); + } + + if (ccachestr) + code = krb5_cc_resolve(kcontext, ccachestr, &ccache); + else + code = krb5_cc_default(kcontext, &ccache); + if (code) { + com_err(argv[0], code, "while getting default ccache"); + krb5_free_principal(kcontext, princ); + krb5_free_context(kcontext); + exit(1); + } + + /* Enumerate tickets from cache looking for an initial ticket */ + if ((code = krb5_cc_start_seq_get(kcontext, ccache, &cursor))) { + com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache"); + krb5_cc_close(kcontext, ccache); + krb5_free_context(kcontext); + exit(1); + } + + while (!(code = krb5_cc_next_cred(kcontext, ccache, &cursor, &creds))) + { + if ( creds.ticket_flags & TKT_FLG_INITIAL ) { + krb5_free_cred_contents(kcontext, &creds); + initial_ticket = 1; + break; + } + krb5_free_cred_contents(kcontext, &creds); + } + krb5_cc_end_seq_get(kcontext, ccache, &cursor); + + if ( !initial_ticket ) { + fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MIT default cache\n", + argv[0]); + krb5_cc_close(kcontext, ccache); + krb5_free_context(kcontext); + exit(1); + } + + if (code = krb5_cc_get_principal(kcontext, ccache, &princ)) { + com_err(argv[0], code, "while obtaining default MIT principal"); + krb5_cc_close(kcontext, ccache); + krb5_free_context(kcontext); + exit(1); + } + + if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) { + com_err(argv[0], code, "while opening MS LSA ccache"); + krb5_cc_close(kcontext, ccache); + krb5_free_context(kcontext); + exit(1); + } + + if (code = krb5_cc_copy_creds(kcontext, ccache, mslsa_ccache)) { + com_err (argv[0], code, "while copying default MIT ccache to MSLSA ccache"); + krb5_free_principal(kcontext, princ); + krb5_cc_close(kcontext, ccache); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + + krb5_free_principal(kcontext, princ); + krb5_cc_close(kcontext, ccache); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + return(0); +} diff --git a/krb5-1-6/src/windows/ms2mit/ms2mit.c b/krb5-1-6/src/windows/ms2mit/ms2mit.c new file mode 100644 index 000000000..5999a1847 --- /dev/null +++ b/krb5-1-6/src/windows/ms2mit/ms2mit.c @@ -0,0 +1,171 @@ +/* + * ms2mit.c + * + */ +/* + * Copyright (C) 2003 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include "krb5.h" +#include <stdio.h> +#include <string.h> + +extern int optind; +extern char *optarg; + +static char *prog; + +static void +xusage(void) +{ + fprintf(stderr, "xusage: %s [-c ccache]\n", prog); + exit(1); +} + +void +main( + int argc, + char *argv[] + ) +{ + krb5_context kcontext; + krb5_error_code code; + krb5_ccache ccache=NULL; + krb5_ccache mslsa_ccache=NULL; + krb5_cc_cursor cursor; + krb5_creds creds; + krb5_principal princ; + int initial_ticket = 0; + int option; + char * ccachestr = 0; + + prog = strrchr(argv[0], '/'); + prog = prog ? (prog + 1) : argv[0]; + + while ((option = getopt(argc, argv, "c:h")) != -1) { + switch (option) { + case 'c': + ccachestr = optarg; + break; + case 'h': + default: + xusage(); + break; + } + } + + if (code = krb5_init_context(&kcontext)) { + com_err(argv[0], code, "while initializing kerberos library"); + exit(1); + } + + if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) { + com_err(argv[0], code, "while opening MS LSA ccache"); + krb5_free_context(kcontext); + exit(1); + } + + if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, KRB5_TC_NOTICKET)) { + com_err(argv[0], code, "while setting KRB5_TC_NOTICKET flag"); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + + /* Enumerate tickets from cache looking for an initial ticket */ + if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) { + com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache"); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + + while (!(code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds))) + { + if ( creds.ticket_flags & TKT_FLG_INITIAL ) { + krb5_free_cred_contents(kcontext, &creds); + initial_ticket = 1; + break; + } + krb5_free_cred_contents(kcontext, &creds); + } + krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor); + + if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, 0)) { + com_err(argv[0], code, "while clearing flags"); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + + if ( !initial_ticket ) { + fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n", + argv[0]); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + + if (code = krb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) { + com_err(argv[0], code, "while obtaining MS LSA principal"); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + + if (ccachestr) + code = krb5_cc_resolve(kcontext, ccachestr, &ccache); + else + code = krb5_cc_default(kcontext, &ccache); + if (code) { + com_err(argv[0], code, "while getting default ccache"); + krb5_free_principal(kcontext, princ); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + if (code = krb5_cc_initialize(kcontext, ccache, princ)) { + com_err (argv[0], code, "when initializing ccache"); + krb5_free_principal(kcontext, princ); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_cc_close(kcontext, ccache); + krb5_free_context(kcontext); + exit(1); + } + + if (code = krb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) { + com_err (argv[0], code, "while copying MS LSA ccache to default ccache"); + krb5_free_principal(kcontext, princ); + krb5_cc_close(kcontext, ccache); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + exit(1); + } + + krb5_free_principal(kcontext, princ); + krb5_cc_close(kcontext, ccache); + krb5_cc_close(kcontext, mslsa_ccache); + krb5_free_context(kcontext); + return(0); +} diff --git a/krb5-1-6/src/windows/version.rc b/krb5-1-6/src/windows/version.rc new file mode 100644 index 000000000..de4daff7e --- /dev/null +++ b/krb5-1-6/src/windows/version.rc @@ -0,0 +1,329 @@ +#include <windows.h> +#include <winver.h> +#include "patchlevel.h" +#include "winlevel.h" + +/* + * BEGIN COMMON VERSION INFO for GSS and Kerberos version resources + */ + +#define XSTR(x) #x +#define STR(x) XSTR(x) + +#define MAJOR_MINOR STR(KRB5_MAJOR_RELEASE) "." STR(KRB5_MINOR_RELEASE) + +#if KRB5_PATCH_LEVEL != 0 +#define MAYBE_PATCH "." STR(KRB5_PATCHLEVEL) +#else +#define MAYBE_PATCH "" +#endif + +#ifdef KRB5_RELTAIL +#define RELTAIL "-" KRB5_RELTAIL +#else +#define RELTAIL "" +#endif + +#ifdef BETA +#define BETA_FLAG VS_FF_PRERELEASE +#else +#define BETA_FLAG 0 +#endif + +#if !defined(_WIN32) +#define Targ_OS VOS__WINDOWS16 +#else +#define Targ_OS VOS__WINDOWS32 +#endif + +/* we're going to stamp all the DLLs with the same version number */ + +#define K5_PRODUCT_VERSION_STRING MAJOR_MINOR MAYBE_PATCH RELTAIL "\0" +#define K5_PRODUCT_VERSION KRB5_MAJOR_RELEASE, KRB5_MINOR_RELEASE, KRB5_PATCHLEVEL, KRB5_BUILDLEVEL + +#define K5_COPYRIGHT "Copyright (C) 1997-2007 by the Massachusetts Institute of Technology\0" +#define K5_COMPANY_NAME "Massachusetts Institute of Technology.\0" + +/* + * END COMMON VERSION INFO + */ + + +/* + * BEGIN SPECIFIC VERSION INFO for GSS and Kerberos version resources + */ + +#ifdef SUPPORT_LIB +#define K5_DESCRIPTION "Kerberos v5 support - internal support code for MIT Kerberos v5 /GSS distribution" +#define K5_INTERNAL_NAME "krb5support\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#error not win32?? +#else +#define K5_ORIGINAL_NAME "k5sprt32.dll\0" +#endif +#endif /* support */ + +#ifdef CE_LIB +#define K5_DESCRIPTION "COM_ERR - Common Error Handler for MIT Kerberos v5 / GSS distribution\0" +#define K5_INTERNAL_NAME "comerr\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#define K5_ORIGINAL_NAME "comerr16.dll\0" +#else +#define K5_ORIGINAL_NAME "comerr32.dll\0" +#endif +#endif /* comerr */ + +#ifdef PROF_LIB +#define K5_DESCRIPTION "PROFILE - Profile Library MIT Kerberos v5 / GSS distribution\0" +#define K5_INTERNAL_NAME "profile\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#define K5_ORIGINAL_NAME "xpprof16.dll\0" +#else +#define K5_ORIGINAL_NAME "xpprof32.dll\0" +#endif +#endif /* profile */ + +#ifdef KRB5_LIB +#define K5_DESCRIPTION "Kerberos v5 - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "krb5\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#define K5_ORIGINAL_NAME "krb5_16.dll\0" +#else +#define K5_ORIGINAL_NAME "krb5_32.dll\0" +#endif +#endif /* KRB5 */ + +#ifdef GSSAPI_LIB +#define K5_DESCRIPTION "GSSAPI - GSS API implementation for Kerberos 5 mechanism\0" +#define K5_INTERNAL_NAME "gssapi\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#define K5_ORIGINAL_NAME "gssapi.dll\0" +#else +#define K5_ORIGINAL_NAME "gssapi32.dll\0" +#endif +#endif /* GSSAPI */ + +#ifdef KRB4_LIB +#define K5_DESCRIPTION "Kerberos v4 - MIT GSS / Kerberos v4 and v5 distribution\0" +#define K5_INTERNAL_NAME "krb4\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#define K5_ORIGINAL_NAME "krb4_16.dll\0" +#else +#define K5_ORIGINAL_NAME "krb4_32.dll\0" +#endif +#endif /* KRB4 */ + +#ifdef SAPKRB_LIB +#define K5_DESCRIPTION "Kerberos v5 - MIT GSS / Kerberos v5 distribution (for SAP)\0" +#define K5_INTERNAL_NAME "sapkrb5\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#define K5_ORIGINAL_NAME "sapkrb16.dll\0" +#else +#define K5_ORIGINAL_NAME "sapkrb32.dll\0" +#endif +#endif /* SAPKRB */ + +#ifdef SAPGSS_LIB +#define K5_DESCRIPTION "GSSAPI - GSS API implementation for Kerberos 5 mechanism(for SAP)\0" +#define K5_INTERNAL_NAME "sapgss\0" +#define K5_FILETYPE VFT_DLL +#if !defined(_WIN32) +#define K5_ORIGINAL_NAME "sapgss16.dll\0" +#else +#define K5_ORIGINAL_NAME "sapgss32.dll\0" +#endif +#endif /* SAPGSS */ + +#ifdef KRB5_APP +#define K5_DESCRIPTION "KRB5 Ticket Manager - MIT GSS / Kerberos v5 distribution\0" +#define K5_FILETYPE VFT_APP +#define K5_INTERNAL_NAME "KRB5\0" +#define K5_ORIGINAL_NAME "krb5.exe\0" +#endif /* KRB5_APP */ + +#ifdef GSS_APP +#define K5_DESCRIPTION "GSS - GSS Sample Application for MIT Kerberos v5 / GSS distribution\0" +#define K5_FILETYPE VFT_APP +#define K5_INTERNAL_NAME "GSS\0" +#define K5_ORIGINAL_NAME "gss.exe\0" +#endif + +#ifdef TELNET_APP +#define K5_DESCRIPTION "Telnet - Telnet Application for MIT Kerberos v5 / GSS distribution\0" +#define K5_FILETYPE VFT_APP +#define K5_INTERNAL_NAME "TELNET\0" +#define K5_ORIGINAL_NAME "telnet.exe\0" +#endif + +#ifdef KRB524_LIB +#define K5_DESCRIPTION "Kerberos v5 to v4 - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "krb524\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "krb524.dll\0" +#endif /* KRB524_LIB */ + +#ifdef KRB524_INIT +#define K5_DESCRIPTION "Kerberos v5 to v4 Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "krb524_init\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "krb524_init.exe\0" +#endif /* KRB524_INIT */ + +#ifdef MS2MIT_APP +#define K5_DESCRIPTION "Microsoft LSA to MIT Credential Cache Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "ms2mit\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "ms2mit.exe\0" +#endif /* MS2MIT_APP */ + +#ifdef MIT2MS_APP +#define K5_DESCRIPTION "MIT to Microsoft LSA Credential Cache Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "mit2ms\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "mit2ms.exe\0" +#endif /* MIT2MS_APP */ + +#ifdef KVNO_APP +#define K5_DESCRIPTION "Key Version Number Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kvno\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kvno.exe\0" +#endif /* KVNO_APP */ + +#ifdef KPASSWD_APP +#define K5_DESCRIPTION "Kerberos Change Password Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kpasswd\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kpasswd.exe\0" +#endif /* KPASSWD_APP */ + +#ifdef KFWLOGON_LIB +#define K5_DESCRIPTION "Kerberos Network Provider - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kfwlogon\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kfwlogon.dll\0" +#endif /* KFWLOGON_LIB */ + +#ifdef KFWCPCC_APP +#define K5_DESCRIPTION "Copy Credential Cache Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kfwcpcc\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kfwcpcc.exe\0" +#endif /* KFWCPCC_APP */ + +#ifdef KCPYTKT_APP +#define K5_DESCRIPTION "Kerberos Copy Ticket Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kcpytkt\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kcpytkt.exe\0" +#endif /* KCPYTKT_APP */ + +#ifdef KDELTKT_APP +#define K5_DESCRIPTION "Kerberos Delete Ticket Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kdeltkt\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kdeltkt.exe\0" +#endif /* KDELTKT_APP */ + +#ifdef KDESTROY_APP +#define K5_DESCRIPTION "Kerberos Destroy Credential Cache Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kdestroy\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kdestroy.exe\0" +#endif /* KDESTROY_APP */ + +#ifdef KINIT_APP +#define K5_DESCRIPTION "Kerberos Initialize Credential Cache Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "kinit\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "kinit.exe\0" +#endif /* KINIT_APP */ + +#ifdef KLIST_APP +#define K5_DESCRIPTION "Kerberos List Credential Cache Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "klist\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "klist.exe\0" +#endif /* KLIST_APP */ + +#ifdef GSS_CLIENT_APP +#define K5_DESCRIPTION "GSS Sample Client Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "gss-client\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "gss-client.exe\0" +#endif /* GSS_CLIENT_APP */ + +#ifdef GSS_SERVER_APP +#define K5_DESCRIPTION "GSS Sample Server Application - MIT GSS / Kerberos v5 distribution\0" +#define K5_INTERNAL_NAME "gss-server\0" +#define K5_FILETYPE VFT_DLL +#define K5_ORIGINAL_NAME "gss-server.exe\0" +#endif /* GSS_SERVER_APP */ + + +/* + * END SPECIFIC VERSION INFO + */ + +VS_VERSION_INFO VERSIONINFO +FILEVERSION K5_PRODUCT_VERSION +PRODUCTVERSION K5_PRODUCT_VERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS (VS_FF_DEBUG | VS_FF_PRIVATEBUILD | BETA_FLAG) +FILEOS Targ_OS +FILETYPE K5_FILETYPE +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END + + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN +#if defined(VER_EXTRA_LABEL) && defined(VER_EXTRA_VALUE) + VALUE VER_EXTRA_LABEL, VER_EXTRA_VALUE +#endif +#ifdef VER_COMMENT + VALUE "Comment", VER_COMMENT +#endif +#ifdef VER_USERNAME + VALUE "Built By", VER_USERNAME +#endif +#ifdef VER_HOSTNAME + VALUE "Build Host", VER_HOSTNAME +#endif +#ifdef VER_DATE + VALUE "Build Time", VER_DATE +#endif +#ifdef VER_VENDOR + VALUE "Modified by Vendor", VER_VENDOR +#endif + VALUE "CompanyName", K5_COMPANY_NAME + VALUE "FileDescription", K5_DESCRIPTION + VALUE "FileVersion", K5_PRODUCT_VERSION_STRING + VALUE "InternalName", K5_INTERNAL_NAME +#ifdef VER_LEGALTRADEMARK_STR + VALUE VER_LEGALTRADEMARK_STR +#else + VALUE "LegalTrademarks", "\0" +#endif + VALUE "OriginalFilename", K5_ORIGINAL_NAME + VALUE "ProductName", K5_ORIGINAL_NAME + VALUE "ProductVersion", K5_PRODUCT_VERSION_STRING + + VALUE "LegalCopyright", K5_COPYRIGHT +#ifdef VER_SPECIALBUILD + VALUE "SpecialBuild", VER_SPECIALBUILD +#endif + END + END +END diff --git a/krb5-1-6/src/windows/winlevel.h b/krb5-1-6/src/windows/winlevel.h new file mode 100644 index 000000000..e87a7451d --- /dev/null +++ b/krb5-1-6/src/windows/winlevel.h @@ -0,0 +1,33 @@ +/* + * winlevel.h + * + * Copyright (C) 2006 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This is the slave file for Windows version stamping purposes. +/* This value should be an ever increasing number that is + * updated for each alpha, beta, final release. This will ensure + * that file identifiers are unique + */ +#define KRB5_BUILDLEVEL 14 diff --git a/krb5-1-6/src/windows/wintel/Makefile.in b/krb5-1-6/src/windows/wintel/Makefile.in new file mode 100644 index 000000000..1ff8f599b --- /dev/null +++ b/krb5-1-6/src/windows/wintel/Makefile.in @@ -0,0 +1,46 @@ +# Makefile for the Kerberos for Windows telnet client +# Works for both k4 and k5 releases. +# +OBJS = $(OUTPRE)telnet.obj $(OUTPRE)negotiat.obj $(OUTPRE)auth.obj \ + $(OUTPRE)edit.obj $(OUTPRE)emul.obj $(OUTPRE)font.obj \ + $(OUTPRE)intern.obj $(OUTPRE)screen.obj $(OUTPRE)encrypt.obj \ + $(OUTPRE)genget.obj + +##### Options +# Set NODEBUG if building release instead of debug +!IF ! defined(KVERSION) +KRBOPT =-DFORWARD -DAUTHENTICATION -DENCRYPTION -DDES_ENCRYPTION +KVERSION= 5 +!endif +KRB = KRB$(KVERSION) + +BUILDTOP=..\.. +LOCALINCLUDES= /I$(BUILDTOP) /I$(BUILDTOP)\include /I$(BUILDTOP)\include\krb5 \ + /I$(BUILDTOP)\lib\crypto\des +RESFILE = $(OUTPRE)telnet.res +XOBJS = $(RESFILE) $(OUTPRE)k5stream.obj $(OUTPRE)enc_des.obj + +DEFINES = /D$(KRB)=1 $(KRBOPT) +RFLAGS = $(LOCALINCLUDES) +RCFLAGS = $(RFLAGS) -D_WIN32 -DTELNET_APP + +##### Linker +LINK = link +LIBS = $(KLIB) $(CLIB) $(WLIB) +SYSLIBS = kernel32.lib ws2_32.lib user32.lib gdi32.lib comdlg32.lib +LFLAGS = /nologo $(LOPTS) + +all:: Makefile $(OUTPRE)telnet.exe + +$(OUTPRE)telnet.exe: telnet.def $(OBJS) $(XOBJS) $(LIBS) + $(LINK) $(LFLAGS) /map:$*.map /out:$@ $(OBJS) $(XOBJS) \ + $(LIBS) $(SYSLIBS) $(SCLIB) + $(_VC_MANIFEST_EMBED_EXE) + +install:: + copy $(OUTPRE)telnet.exe $(DESTDIR) + +clean:: + $(RM) $(OUTPRE)*.exe $(OUTPRE)*.res $(OUTPRE)*.map + +$(RESFILE): ..\version.rc diff --git a/krb5-1-6/src/windows/wintel/auth.c b/krb5-1-6/src/windows/wintel/auth.c new file mode 100644 index 000000000..28f515b6c --- /dev/null +++ b/krb5-1-6/src/windows/wintel/auth.c @@ -0,0 +1,867 @@ +/* + * Implements Kerberos 4 authentication + */ + +#ifdef KRB4 +#include <windows.h> +#include <time.h> +#include <string.h> +#include "winsock.h" +#include "kerberos.h" +#endif +#ifdef KRB5 +#include <time.h> +#include <string.h> +#include "krb5.h" +#include "com_err.h" +#endif + +#include "telnet.h" +#include "telnet_arpa.h" + +#ifdef ENCRYPTION +#include "encrypt.h" +#endif + +/* + * Constants + */ +#ifdef KRB4 +#define KRB_AUTH 0 +#define KRB_REJECT 1 +#define KRB_ACCEPT 2 +#define KRB_CHALLENGE 3 +#define KRB_RESPONSE 4 +#endif +#ifdef KRB5 +#define KRB_AUTH 0 /* Authentication data follows */ +#define KRB_REJECT 1 /* Rejected (reason might follow) */ +#define KRB_ACCEPT 2 /* Accepted */ +#define KRB_RESPONSE 3 /* Response for mutual auth. */ + +#define KRB_FORWARD 4 /* Forwarded credentials follow */ +#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ +#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ +#endif + +#ifndef KSUCCESS /* Let K5 use K4 constants */ +#define KSUCCESS 0 +#define KFAILURE 255 +#endif + +/* + * Globals + */ +#ifdef KRB4 +static CREDENTIALS cred; +static KTEXT_ST auth; + +#define KRB_SERVICE_NAME "rcmd" +#define KERBEROS_VERSION KERBEROS_V4 + +static int auth_how; +static int k4_auth_send(kstream); +static int k4_auth_reply(kstream, unsigned char *, int); +#endif + +#ifdef KRB5 +static krb5_data auth; +static int auth_how; +static krb5_auth_context auth_context; +krb5_keyblock *session_key = NULL; +#ifdef FORWARD +void kerberos5_forward(kstream); +#endif + +#define KRB_SERVICE_NAME "host" +#define KERBEROS_VERSION AUTHTYPE_KERBEROS_V5 + +static int k5_auth_send(kstream, int); +static int k5_auth_reply(kstream, int, unsigned char *, int); +#endif + +static int Data(kstream, int, void *, int); + +#ifdef ENCRYPTION +BOOL encrypt_flag = 1; +#endif +#ifdef FORWARD +BOOL forward_flag = 1; /* forward tickets? */ +BOOL forwardable_flag = 1; /* get forwardable tickets to forward? */ +BOOL forwarded_tickets = 0; /* were tickets forwarded? */ +#endif + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_KERBEROS_V5, }; + +static int +Data(kstream ks, int type, void *d, int c) +{ + unsigned char *p = str_data + 4; + unsigned char *cd = (unsigned char *)d; + + if (c == -1) + c = strlen((char *)cd); + + *p++ = AUTHTYPE_KERBEROS_V5; + *p = AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL; +#ifdef ENCRYPTION + *p |= AUTH_ENCRYPT_ON; +#endif + p++; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + + return(TelnetSend(ks, (LPSTR)str_data, p - str_data, 0)); +} + +#ifdef ENCRYPTION +/* + * Function: Enable or disable the encryption process. + * + * Parameters: + * enable - TRUE to enable, FALSE to disable. + */ +static void +auth_encrypt_enable(BOOL enable) +{ + encrypt_flag = enable; +} +#endif + +/* + * Function: Abort the authentication process + * + * Parameters: + * ks - kstream to send abort message to. + */ +static void +auth_abort(kstream ks, char *errmsg, long r) +{ + char buf[9]; + + wsprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_IS, AUTHTYPE_NULL, + AUTHTYPE_NULL, IAC, SE); + TelnetSend(ks, (LPSTR)buf, 8, 0); + + if (errmsg != NULL) { + strTmp[sizeof(strTmp) - 1] = '\0'; + strncpy(strTmp, errmsg, sizeof(strTmp) - 1); + + if (r != KSUCCESS) { + strncat(strTmp, "\n", sizeof(strTmp) - 1 - strlen(strTmp)); +#ifdef KRB4 + lstrcat(strTmp, krb_get_err_text((int)r)); +#endif +#ifdef KRB5 + lstrcat(strTmp, error_message(r)); +#endif + } + + MessageBox(HWND_DESKTOP, strTmp, "Kerberos authentication failed!", + MB_OK | MB_ICONEXCLAMATION); + } +} + + +/* + * Function: Copy data to buffer, doubling IAC character if present. + * + * Parameters: + * kstream - kstream to send abort message to. + */ +static int +copy_for_net(unsigned char *to, unsigned char *from, int c) +{ + int n; + + n = c; + + while (c-- > 0) { + if ((*to++ = *from++) == IAC) { + n++; + *to++ = IAC; + } + } + + return n; +} + + +/* + * Function: Parse authentication send command + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - the sub-command data. + * + * end_sub - index of the character in the 'parsedat' array which + * is the last byte in a sub-negotiation + * + * Returns: Kerberos error code. + */ +static int +auth_send(kstream ks, unsigned char *parsedat, int end_sub) +{ + char buf[2048]; /* be sure that this is > auth.length+9 */ + char *pname; + int plen; + int r; + int i; + + auth_how = -1; + + for (i = 2; i+1 <= end_sub; i += 2) { + if (parsedat[i] == KERBEROS_VERSION) + if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) { + auth_how = parsedat[i+1] & AUTH_HOW_MASK; + break; + } + } + + if (auth_how == -1) { + auth_abort(ks, NULL, 0); + return KFAILURE; + } + +#ifdef KRB4 + r = k4_auth_send(ks); +#endif /* KRB4 */ + +#ifdef KRB5 + r = k5_auth_send(ks, auth_how); +#endif /* KRB5 */ + + if (!r) + return KFAILURE; + + plen = strlen(szUserName); /* Set by k#_send if needed */ + pname = szUserName; + + wsprintf(buf, "%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME); + memcpy(&buf[4], pname, plen); + wsprintf(&buf[plen + 4], "%c%c", IAC, SE); + TelnetSend(ks, (LPSTR)buf, lstrlen(pname)+6, 0); + + wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_IS, + KERBEROS_VERSION, auth_how | AUTH_WHO_CLIENT, KRB_AUTH); + +#if KRB4 + auth.length = copy_for_net(&buf[7], auth.dat, auth.length); +#endif /* KRB4 */ +#if KRB5 + auth.length = copy_for_net(&buf[7], auth.data, auth.length); +#endif /* KRB5 */ + + wsprintf(&buf[auth.length+7], "%c%c", IAC, SE); + + TelnetSend(ks, (LPSTR)buf, auth.length+9, 0); + + return KSUCCESS; +} + +/* + * Function: Parse authentication reply command + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - the sub-command data. + * + * end_sub - index of the character in the 'parsedat' array which + * is the last byte in a sub-negotiation + * + * Returns: Kerberos error code. + */ +static int +auth_reply(kstream ks, unsigned char *parsedat, int end_sub) +{ + int n; + +#ifdef KRB4 + n = k4_auth_reply(ks, parsedat, end_sub); +#endif + +#ifdef KRB5 + n = k5_auth_reply(ks, auth_how, parsedat, end_sub); +#endif + + return n; +} + +/* + * Function: Parse the athorization sub-options and reply. + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - sub-option string to parse. + * + * end_sub - last charcter position in parsedat. + */ +void +auth_parse(kstream ks, unsigned char *parsedat, int end_sub) +{ + if (parsedat[1] == TELQUAL_SEND) + auth_send(ks, parsedat, end_sub); + + if (parsedat[1] == TELQUAL_REPLY) + auth_reply(ks, parsedat, end_sub); +} + + +/* + * Function: Initialization routine called kstream encryption system. + * + * Parameters: + * str - kstream to send abort message to. + * + * data - user data. + */ +int +auth_init(kstream str, kstream_ptr data) +{ +#ifdef ENCRYPTION + encrypt_init(str, data); +#endif + return 0; +} + + +/* + * Function: Destroy routine called kstream encryption system. + * + * Parameters: + * str - kstream to send abort message to. + * + * data - user data. + */ +void +auth_destroy(kstream str) +{ +} + + +/* + * Function: Callback to encrypt a block of characters + * + * Parameters: + * out - return as pointer to converted buffer. + * + * in - the buffer to convert + * + * str - the stream being encrypted + * + * Returns: number of characters converted. + */ +int +auth_encrypt(struct kstream_data_block *out, + struct kstream_data_block *in, + kstream str) +{ + out->ptr = in->ptr; + + out->length = in->length; + + return(out->length); +} + + +/* + * Function: Callback to decrypt a block of characters + * + * Parameters: + * out - return as pointer to converted buffer. + * + * in - the buffer to convert + * + * str - the stream being encrypted + * + * Returns: number of characters converted. + */ +int +auth_decrypt(struct kstream_data_block *out, + struct kstream_data_block *in, + kstream str) +{ + out->ptr = in->ptr; + + out->length = in->length; + + return(out->length); +} + +#ifdef KRB4 +/* + * + * K4_auth_send - gets authentication bits we need to send to KDC. + * + * Result is left in auth + * + * Returns: 0 on failure, 1 on success + */ +static int +k4_auth_send(kstream ks) +{ + int r; /* Return value */ + char instance[INST_SZ]; + char *realm; + char buf[256]; + + memset(instance, 0, sizeof(instance)); + + if (realm = krb_get_phost(szHostName)) + lstrcpy(instance, realm); + + realm = krb_realmofhost(szHostName); + + if (!realm) { + strcpy(buf, "Can't find realm for host \""); + strncat(buf, szHostName, sizeof(buf) - 1 - strlen(buf)); + strncat(buf, "\"", sizeof(buf) - 1 - strlen(buf)); + auth_abort(ks, buf, 0); + return KFAILURE; + } + + r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0); + + if (r == 0) + r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred); + + if (r) { + strcpy(buf, "Can't get \""); + strncat(buf, KRB_SERVICE_NAME, sizeof(buf) - 1 - strlen(buf)); + if (instance[0] != 0) { + strncat(buf, ".", sizeof(buf) - 1 - strlen(buf)); + lstrcat(buf, instance); + } + strncat(buf, "@", sizeof(buf) - 1 - strlen(buf)); + lstrcat(buf, realm); + strncat(buf, "\" ticket", sizeof(buf) - 1 - strlen(buf)); + auth_abort(ks, buf, r); + + return r; + } + + if (!szUserName[0]) /* Copy if not there */ + strcpy(szUserName, cred.pname); + + return(1); +} + +/* + * Function: K4 parse authentication reply command + * + * Parameters: + * ks - kstream to send abort message to. + * + * parsedat - the sub-command data. + * + * end_sub - index of the character in the 'parsedat' array which + * is the last byte in a sub-negotiation + * + * Returns: Kerberos error code. + */ +static int +k4_auth_reply(kstream ks, unsigned char *parsedat, int end_sub) +{ + time_t t; + int x; + char buf[512]; + int i; + des_cblock session_key; + des_key_schedule sched; + static des_cblock challenge; + + if (end_sub < 4) + return KFAILURE; + + if (parsedat[2] != KERBEROS_V4) + return KFAILURE; + + if (parsedat[4] == KRB_REJECT) { + buf[0] = 0; + + for (i = 5; i <= end_sub; i++) { + if (parsedat[i] == IAC) + break; + buf[i-5] = parsedat[i]; + buf[i-4] = 0; + } + + if (!buf[0]) + strcpy(buf, "Authentication rejected by remote machine!"); + MessageBox(HWND_DESKTOP, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + } + + if (parsedat[4] == KRB_ACCEPT) { + if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) + return KSUCCESS; + + if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) + return KFAILURE; + + des_key_sched(cred.session, sched); + + t = time(NULL); + memcpy(challenge, &t, 4); + memcpy(&challenge[4], &t, 4); + des_ecb_encrypt(&challenge, &session_key, sched, 1); + + /* + * Increment the challenge by 1, and encrypt it for + * later comparison. + */ + for (i = 7; i >= 0; --i) { + x = (unsigned int)challenge[i] + 1; + challenge[i] = x; /* ignore overflow */ + if (x < 256) /* if no overflow, all done */ + break; + } + + des_ecb_encrypt(&challenge, &challenge, sched, 1); + + wsprintf(buf, "%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_IS, + KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, KRB_CHALLENGE); + memcpy(&buf[7], session_key, 8); + wsprintf(&buf[15], "%c%c", IAC, SE); + TelnetSend(ks, (LPSTR)buf, 17, 0); + + return KSUCCESS; + } + + if (parsedat[4] == KRB_RESPONSE) { + if (end_sub < 12) + return KFAILURE; + + if (memcmp(&parsedat[5], challenge, sizeof(challenge)) != 0) { + MessageBox(HWND_DESKTOP, "Remote machine is being impersonated!", + NULL, MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + } + + return KSUCCESS; + } + + return KFAILURE; + +} + +#endif /* KRB4 */ + +#ifdef KRB5 + +/* + * + * K5_auth_send - gets authentication bits we need to send to KDC. + * + * Code lifted from telnet sample code in the appl directory. + * + * Result is left in auth + * + * Returns: 0 on failure, 1 on success + * + */ + +static int +k5_auth_send(kstream ks, int how) +{ + krb5_error_code r; + krb5_ccache ccache; + krb5_creds creds; + krb5_creds * new_creds; + extern krb5_flags krb5_kdc_default_options; + krb5_flags ap_opts; + char type_check[2]; + krb5_data check_data; + int len; +#ifdef ENCRYPTION + krb5_keyblock *newkey = 0; +#endif + + if (r = krb5_cc_default(k5_context, &ccache)) { + com_err(NULL, r, "while authorizing."); + return(0); + } + + memset((char *)&creds, 0, sizeof(creds)); + if (r = krb5_sname_to_principal(k5_context, szHostName, KRB_SERVICE_NAME, + KRB5_NT_SRV_HST, &creds.server)) { + com_err(NULL, r, "while authorizing."); + return(0); + } + + if (r = krb5_cc_get_principal(k5_context, ccache, &creds.client)) { + com_err(NULL, r, "while authorizing."); + krb5_free_cred_contents(k5_context, &creds); + return(0); + } + if (szUserName[0] == '\0') { /* Get user name now */ + len = krb5_princ_component(k5_context, creds.client, 0)->length; + memcpy(szUserName, + krb5_princ_component(k5_context, creds.client, 0)->data, + len); + szUserName[len] = '\0'; + } + + if (r = krb5_get_credentials(k5_context, 0, + ccache, &creds, &new_creds)) { + com_err(NULL, r, "while authorizing."); + krb5_free_cred_contents(k5_context, &creds); + return(0); + } + + ap_opts = 0; + if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) + ap_opts = AP_OPTS_MUTUAL_REQUIRED; + +#ifdef ENCRYPTION + ap_opts |= AP_OPTS_USE_SUBKEY; +#endif + + if (auth_context) { + krb5_auth_con_free(k5_context, auth_context); + auth_context = 0; + } + if ((r = krb5_auth_con_init(k5_context, &auth_context))) { + com_err(NULL, r, "while initializing auth context"); + return(0); + } + + krb5_auth_con_setflags(k5_context, auth_context, + KRB5_AUTH_CONTEXT_RET_TIME); + + type_check[0] = AUTHTYPE_KERBEROS_V5; + type_check[1] = AUTH_WHO_CLIENT| (how & AUTH_HOW_MASK); +#ifdef ENCRYPTION + type_check[1] |= AUTH_ENCRYPT_ON; +#endif + check_data.magic = KV5M_DATA; + check_data.length = 2; + check_data.data = (char *)&type_check; + + r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts, + NULL, new_creds, &auth); + +#ifdef ENCRYPTION + krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey); + if (session_key) { + krb5_free_keyblock(k5_context, session_key); + session_key = 0; + } + + if (newkey) { + /* + * keep the key in our private storage, but don't use it + * yet---see kerberos5_reply() below + */ + if ((newkey->enctype != ENCTYPE_DES_CBC_CRC) && + (newkey-> enctype != ENCTYPE_DES_CBC_MD5)) { + if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) || + (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5)) + /* use the session key in credentials instead */ + krb5_copy_keyblock(k5_context, &new_creds->keyblock, &session_key); + else + ; /* What goes here? XXX */ + } else { + krb5_copy_keyblock(k5_context, newkey, &session_key); + } + krb5_free_keyblock(k5_context, newkey); + } +#endif /* ENCRYPTION */ + + krb5_free_cred_contents(k5_context, &creds); + krb5_free_creds(k5_context, new_creds); + + if (r) { + com_err(NULL, r, "while authorizing."); + return(0); + } + + return(1); +} + +/* + * + * K5_auth_reply -- checks the reply for mutual authentication. + * + * Code lifted from telnet sample code in the appl directory. + * + */ +static int +k5_auth_reply(kstream ks, int how, unsigned char *data, int cnt) +{ +#ifdef ENCRYPTION + Session_Key skey; +#endif + static int mutual_complete = 0; + + data += 4; /* Point to status byte */ + + switch (*data++) { + case KRB_REJECT: + if (cnt > 0) { + char *s; + wsprintf(strTmp, "Kerberos V5 refuses authentication because\n\t"); + s = strTmp + strlen(strTmp); + strncpy(s, data, cnt); + s[cnt] = 0; + } else + wsprintf(strTmp, "Kerberos V5 refuses authentication"); + MessageBox(HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION); + + return KFAILURE; + + case KRB_ACCEPT: + if (!mutual_complete) { + if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) { + wsprintf(strTmp, + "Kerberos V5 accepted you, but didn't provide" + " mutual authentication"); + MessageBox(HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION); + return KFAILURE; + } +#ifdef ENCRYPTION + if (session_key) { + skey.type = SK_DES; + skey.length = 8; + skey.data = session_key->contents; + encrypt_session_key(&skey, 0); + } +#endif + } + +#ifdef FORWARD + if (forward_flag) + kerberos5_forward(ks); +#endif + + return KSUCCESS; + break; + + case KRB_RESPONSE: + if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* the rest of the reply should contain a krb_ap_rep */ + krb5_ap_rep_enc_part *reply; + krb5_data inbuf; + krb5_error_code r; + + inbuf.length = cnt; + inbuf.data = (char *)data; + + if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) { + com_err(NULL, r, "while authorizing."); + return KFAILURE; + } + krb5_free_ap_rep_enc_part(k5_context, reply); + +#ifdef ENCRYPTION + if (encrypt_flag && session_key) { + skey.type = SK_DES; + skey.length = 8; + skey.data = session_key->contents; + encrypt_session_key(&skey, 0); + } +#endif + mutual_complete = 1; + } + return KSUCCESS; + +#ifdef FORWARD + case KRB_FORWARD_ACCEPT: + forwarded_tickets = 1; + return KSUCCESS; + + case KRB_FORWARD_REJECT: + forwarded_tickets = 0; + if (cnt > 0) { + char *s; + + wsprintf(strTmp, + "Kerberos V5 refuses forwarded credentials because\n\t"); + s = strTmp + strlen(strTmp); + strncpy(s, data, cnt); + s[cnt] = 0; + } else + wsprintf(strTmp, "Kerberos V5 refuses forwarded credentials"); + + MessageBox(HWND_DESKTOP, strTmp, "", MB_OK | MB_ICONEXCLAMATION); + return KFAILURE; +#endif /* FORWARD */ + + default: + return KFAILURE; /* Unknown reply type */ + } +} + +#ifdef FORWARD +void +kerberos5_forward(kstream ks) +{ + krb5_error_code r; + krb5_ccache ccache; + krb5_principal client = 0; + krb5_principal server = 0; + krb5_data forw_creds; + + forw_creds.data = 0; + + if ((r = krb5_cc_default(k5_context, &ccache))) { + com_err(NULL, r, "Kerberos V5: could not get default ccache"); + return; + } + + if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) { + com_err(NULL, r, "Kerberos V5: could not get default principal"); + goto cleanup; + } + + if ((r = krb5_sname_to_principal(k5_context, szHostName, KRB_SERVICE_NAME, + KRB5_NT_SRV_HST, &server))) { + com_err(NULL, r, "Kerberos V5: could not make server principal"); + goto cleanup; + } + + if ((r = krb5_auth_con_genaddrs(k5_context, auth_context, ks->fd, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))) { + com_err(NULL, r, "Kerberos V5: could not gen local full address"); + goto cleanup; + } + + if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client, server, + ccache, forwardable_flag, &forw_creds)) { + com_err(NULL, r, "Kerberos V5: error getting forwarded creds"); + goto cleanup; + } + + /* Send forwarded credentials */ + if (!Data(ks, KRB_FORWARD, forw_creds.data, forw_creds.length)) { + MessageBox(HWND_DESKTOP, + "Not enough room for authentication data", "", + MB_OK | MB_ICONEXCLAMATION); + } + +cleanup: + if (client) + krb5_free_principal(k5_context, client); + if (server) + krb5_free_principal(k5_context, server); +#if 0 /* XXX */ + if (forw_creds.data) + free(forw_creds.data); +#endif + krb5_cc_close(k5_context, ccache); +} +#endif /* FORWARD */ + +#endif /* KRB5 */ diff --git a/krb5-1-6/src/windows/wintel/auth.h b/krb5-1-6/src/windows/wintel/auth.h new file mode 100644 index 000000000..e0f60ec40 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/auth.h @@ -0,0 +1,28 @@ +/* + * Implements Kerberos 4 authentication and ecryption + */ + +#ifndef WINTEL_AUTH_H +#define WINTEL_AUTH_H + +void auth_parse(kstream, unsigned char *, int); + +int auth_init(kstream, kstream_ptr); + +void auth_destroy(kstream); + +int auth_encrypt(struct kstream_data_block *, struct kstream_data_block *, + kstream); + +int auth_decrypt(struct kstream_data_block *, struct kstream_data_block *, + kstream); + +extern BOOL forward_flag; +extern BOOL forwardable_flag; +extern BOOL forwarded_tickets; + +#ifdef ENCRYPTION +extern BOOL encrypt_flag; +#endif + +#endif /* WINTEL_AUTH_H */ diff --git a/krb5-1-6/src/windows/wintel/dialog.h b/krb5-1-6/src/windows/wintel/dialog.h new file mode 100644 index 000000000..c95ec0491 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/dialog.h @@ -0,0 +1,42 @@ +#define IDM_SHOWCONSOLE 700 + +#define IDM_OPENTELNETDLG 200 +#define TEL_CONNECT_NAME 201 +#define TEL_USEDEFAULTS 202 +#define TEL_MANUALCONFIGURE 203 +#define TEL_OK 204 +#define TEL_CANCEL 206 +#define IDC_FORWARD 207 +#define IDC_FORWARDFORWARD 208 +#define IDC_ENCRYPT 210 +#define TEL_CONNECT_USERID 211 + +#define IDM_SEND_IP 800 +#define IDM_SEND_AYT 801 +#define IDM_SEND_ABORT 802 + +#define CON_SESSIONNAME 302 +#define CON_WINDOWTITLE 304 +#define CON_COLUMNS132 305 +#define CON_COLUMNS80 306 +#define CON_BACKSPACE 307 +#define CON_DELETE 308 +#define CON_CRLF 309 +#define CON_CRNUL 310 +#define CON_BUFFERS 311 +#define CON_SENDS 312 +#define CON_OK 320 +#define CON_USEDEFAULTS 321 +#define CONFIGDLG 300 +#define CON_SCRLBCK 317 +#define CON_NUMLINES 318 + +#define PRINTQUEUE 400 + +#define IDM_PRINTQUEUE 500 + +#define TEL_PUSH1 601 +#define TEL_PUSH2 602 +#define TEL_PUSH3 603 +#define TEL_PUSH4 604 +#define TEL_PUSH5 605 diff --git a/krb5-1-6/src/windows/wintel/edit.c b/krb5-1-6/src/windows/wintel/edit.c new file mode 100644 index 000000000..aa230cfc9 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/edit.c @@ -0,0 +1,444 @@ +/* edit.c */ + +#include <windows.h> +#include <commdlg.h> +#include <ctype.h> +#include <assert.h> +#include "screen.h" + +char *cInvertedArray; +int bMouseDown = FALSE; +int bSelection; + +static int iLocStart; +static int iLocEnd; + +void Edit_LbuttonDown( + HWND hWnd, + LPARAM lParam) +{ + SCREEN *pScr; + HMENU hMenu; + int iTmp; + int iXlocStart; + int iYlocStart; + HDC hDC; + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + hDC = GetDC(hWnd); + for (iTmp = 0; iTmp < pScr->width * pScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, iTmp % pScr->width * pScr->cxChar, + (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + bSelection = FALSE; + hMenu = GetMenu(hWnd); + EnableMenuItem(hMenu, IDM_COPY, MF_GRAYED); + ReleaseDC(hWnd, hDC); + iXlocStart = (int) LOWORD(lParam) / pScr->cxChar; + if (iXlocStart >= pScr->width) + iXlocStart = pScr->width - 1; + iYlocStart = (int) HIWORD(lParam) / pScr->cyChar; + if (iYlocStart >= pScr->height) + iYlocStart = pScr->height - 1; + iLocStart = iXlocStart + iYlocStart * pScr->width; + bMouseDown = TRUE; + +} /* Edit_LbuttonDown */ + + +void Edit_LbuttonUp( + HWND hWnd, + LPARAM lParam) +{ + SCREEN *pScr; + int iTmp; + int iTmp2; + HMENU hMenu; + + bMouseDown = FALSE; + if (bSelection) + return; + bSelection = TRUE; + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + iTmp = (int) LOWORD(lParam) / pScr->cxChar; + if (iTmp >= pScr->width) + iTmp = pScr->width - 1; + iTmp2 = (int) HIWORD(lParam) / pScr->cyChar; + if (iTmp2 >= pScr->height) + iTmp2 = pScr->height - 1; + iLocEnd = iTmp + iTmp2 * pScr->width; + if (iLocEnd == iLocStart) { + bSelection = FALSE; + } + else { + hMenu = GetMenu(hWnd); + EnableMenuItem(hMenu, IDM_COPY, MF_ENABLED); + } + +} /* Edit_LbuttonUp */ + + +void Edit_MouseMove(HWND hWnd, LPARAM lParam){ + SCREEN *pScr; + int iTmp; + int iTmp2; + int iXlocCurr; + int iYlocCurr; + int iLocCurr; + int iX; + int iX2; + int iY; + int iY2; + SCREENLINE *pScrLine; + HDC hDC; + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + hDC = GetDC(hWnd); + iXlocCurr = (int) LOWORD(lParam) / pScr->cxChar; + if (iXlocCurr >= pScr->width) + iXlocCurr = pScr->width - 1; + iYlocCurr = (int) HIWORD(lParam) / pScr->cyChar; + if (iYlocCurr >= pScr->height) + iYlocCurr = pScr->height - 1; + iLocCurr = iXlocCurr + (iYlocCurr * pScr->width); + if (iLocCurr > iLocStart) { + for (iTmp=0; iTmp < iLocStart; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, (iTmp % pScr->width) * pScr->cxChar, + (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + iX = iLocStart % pScr->width; + iY = (int) (iLocStart / pScr->width); + iX2 = iLocCurr % pScr->width; + iY2 = (int) (iLocCurr / pScr->width); + if (iY == iY2) { + pScrLine = GetScreenLineFromY(pScr, iY); + for (iTmp2 = iX; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iY)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iY * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iY)] = pScrLine->text[iTmp2]; + } + } + } + else { + pScrLine = GetScreenLineFromY(pScr, iY); + + for (iTmp2 = iX; iTmp2 < pScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iY)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iY * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iY)] = pScrLine->text[iTmp2]; + } + } + + for (iTmp = iY + 1; iTmp < iY2; iTmp++) { + pScrLine = GetScreenLineFromY(pScr, iTmp); + for (iTmp2 = 0; iTmp2 < pScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iTmp)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iTmp * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iTmp)] = pScrLine->text[iTmp2]; + } + } + } + + if (iY2 != iY) { + pScrLine = GetScreenLineFromY(pScr, iY2); + for (iTmp2 = 0; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iY2)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iY2 * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iY2)] = pScrLine->text[iTmp2]; + } + } + } + } + + for (iTmp = iLocCurr; iTmp < pScr->width * pScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, (iTmp % pScr->width) * pScr->cxChar, (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + } + else { /* going backwards */ + for (iTmp = 0; iTmp < iLocCurr; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, (iTmp % pScr->width) * pScr->cxChar, (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + iX = iLocCurr % pScr->width; + iY = (int) (iLocCurr / pScr->width); + iX2 = (iLocStart % pScr->width); + iY2 = (int) (iLocStart / pScr->width); + if (iY == iY2) { + pScrLine = GetScreenLineFromY(pScr, iY); + for (iTmp2= iX; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iY)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iY * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iY)] = pScrLine->text[iTmp2]; + } + } + } + else { + pScrLine = GetScreenLineFromY(pScr, iY); + for (iTmp2 = iX; iTmp2 < pScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iY)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iY * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iY)] = pScrLine->text[iTmp2]; + } + } + for (iTmp = iY + 1; iTmp < iY2; iTmp++) { + pScrLine = GetScreenLineFromY(pScr, iTmp); + for (iTmp2 = 0; iTmp2 < pScr->width; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iTmp)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iTmp * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iTmp)] = pScrLine->text[iTmp2]; + } + } + } + if (iY2 != iY) { + pScrLine = GetScreenLineFromY(pScr, iY2); + for (iTmp2 = 0; iTmp2 < iX2; iTmp2++) { + if ((!cInvertedArray[iTmp2 + (pScr->width * iY2)]) && pScrLine->text[iTmp2]) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iY2 * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (pScr->width * iY2)] = pScrLine->text[iTmp2]; + } + } + } + } + for (iTmp = iLocStart; iTmp < pScr->width * pScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, (iTmp % pScr->width) * pScr->cxChar, (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + } + ReleaseDC(hWnd, hDC); +} /* Edit_MouseMove */ + + +void Edit_ClearSelection( + SCREEN *pScr) +{ + int iTmp; + HDC hDC; + HMENU hMenu; + + hDC = GetDC(pScr->hWnd); + for (iTmp = 0; iTmp < pScr->width * pScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, (iTmp % pScr->width) * pScr->cxChar, + (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + bSelection = FALSE; + hMenu=GetMenu(pScr->hWnd); + EnableMenuItem(hMenu, IDM_COPY, MF_GRAYED); + ReleaseDC(pScr->hWnd, hDC); +} /* Edit_ClearSelection */ + + +void Edit_Copy( + HWND hWnd) +{ + int iTmp,iIdx; + HGLOBAL hCutBuffer; + LPSTR lpCutBuffer; + SCREEN *pScr; + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + hCutBuffer= GlobalAlloc(GHND, (DWORD) (pScr->width * pScr->height + 1)); + lpCutBuffer= GlobalLock(hCutBuffer); + + if (iLocStart > iLocEnd) { /* swap variables */ + iTmp = iLocStart; + iLocStart = iLocEnd; + iLocEnd = iLocStart; + } + iTmp = iLocStart; + iIdx = 0; + while (iTmp < iLocEnd) { + if (!cInvertedArray[iTmp]) { + lpCutBuffer[iIdx++] = '\r'; + lpCutBuffer[iIdx++] = '\n'; + iTmp = (((int) (iTmp / pScr->width)) + 1) * pScr->width; + continue; + } + lpCutBuffer[iIdx++] = cInvertedArray[iTmp++]; + } + lpCutBuffer[iIdx] = 0; + GlobalUnlock(hCutBuffer); + OpenClipboard(hWnd); + EmptyClipboard(); + SetClipboardData(CF_TEXT, hCutBuffer); + CloseClipboard(); + +} /* Edit_Copy */ + + +void Edit_Paste( + HWND hWnd) +{ + HGLOBAL hClipMemory; + static HGLOBAL hMyClipBuffer; + LPSTR lpClipMemory; + LPSTR lpMyClipBuffer; + SCREEN *pScr; + + if (hMyClipBuffer) + GlobalFree(hMyClipBuffer); + OpenClipboard(hWnd); + hClipMemory = GetClipboardData(CF_TEXT); + hMyClipBuffer = GlobalAlloc(GHND, GlobalSize(hClipMemory)); + lpMyClipBuffer = GlobalLock(hMyClipBuffer); + lpClipMemory= GlobalLock(hClipMemory); + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + lstrcpy(lpMyClipBuffer, lpClipMemory); +#if 0 + OutputDebugString(lpMyClipBuffer); +#endif + PostMessage(pScr->hwndTel, WM_MYSCREENBLOCK, (WPARAM) hMyClipBuffer, (LPARAM) pScr); + CloseClipboard(); + GlobalUnlock(hClipMemory); + GlobalUnlock(hMyClipBuffer); + +} /* Edit_Paste */ + + +void Edit_LbuttonDblclk( + HWND hWnd, + LPARAM lParam) +{ + HDC hDC; + SCREEN *pScr; + int iTmp; + int iTmp2; + int iXlocStart; + int iYloc; + SCREENLINE *pScrLine; + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + hDC = GetDC(hWnd); + for (iTmp = 0; iTmp < pScr->width * pScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, (iTmp % pScr->width) * pScr->cxChar, + (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + bSelection = FALSE; + iXlocStart = (int) LOWORD(lParam) / pScr->cxChar; + if (iXlocStart >= pScr->width) + iXlocStart = pScr->width - 1; + iYloc = (int) HIWORD(lParam) / pScr->cyChar; + if (iYloc >= pScr->height) + iYloc = pScr->height - 1; + iLocStart = iXlocStart + (iYloc * pScr->width); + + pScrLine = GetScreenLineFromY(pScr, iYloc); + + iTmp = iXlocStart; + while (isalnum((int) pScrLine->text[iTmp])) { + PatBlt(hDC, iTmp * pScr->cxChar, iYloc * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp + (iYloc * pScr->width)] = pScrLine->text[iTmp]; + iTmp++; + } + iTmp2 = iXlocStart - 1; + while (isalnum((int) pScrLine->text[iTmp2])) { + PatBlt(hDC, iTmp2 * pScr->cxChar, iYloc * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp2 + (iYloc * pScr->width)] = pScrLine->text[iTmp2]; + iTmp2--; + } + iLocStart = (iTmp2 + 1) + (iYloc * pScr->width); + iLocEnd = iTmp + (iYloc * pScr->width); + + bSelection = TRUE; + ReleaseDC(hWnd, hDC); + +} /* Edit_LbuttonDblclk */ + + +void Edit_TripleClick( + HWND hWnd, + LPARAM lParam) +{ + HDC hDC; + SCREEN *pScr; + int iTmp; + int iYloc; + SCREENLINE *pScrLine; + +#if 0 + OutputDebugString("Triple Click \r\n"); +#endif + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + hDC = GetDC(hWnd); + for (iTmp = 0; iTmp < pScr->width * pScr->height; iTmp++) { + if (cInvertedArray[iTmp]) { + PatBlt(hDC, (iTmp % pScr->width) * pScr->cxChar, + (int) (iTmp / pScr->width) * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp] = 0; + } + } + bSelection = FALSE; + iYloc = (int) HIWORD(lParam) / pScr->cyChar; + if (iYloc >= pScr->height) + iYloc = pScr->height - 1; + iLocStart = iYloc * pScr->width; + + pScrLine = GetScreenLineFromY(pScr, iYloc); + + for (iTmp = 0; iTmp < pScr->width; iTmp++) { + if (pScrLine->text[iTmp]) { + PatBlt(hDC, iTmp * pScr->cxChar, iYloc * pScr->cyChar, + pScr->cxChar, pScr->cyChar, DSTINVERT); + cInvertedArray[iTmp + (iYloc * pScr->width)] = pScrLine->text[iTmp]; + } + else + break; + } + iLocEnd = iTmp + (iYloc * pScr->width); + + bSelection = TRUE; + ReleaseDC(hWnd, hDC); + +} /* Edit_TripleClick */ diff --git a/krb5-1-6/src/windows/wintel/emul.c b/krb5-1-6/src/windows/wintel/emul.c new file mode 100644 index 000000000..18547ab80 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/emul.c @@ -0,0 +1,766 @@ +/* emul.c */ + +#include "windows.h" +#include "screen.h" + + +static int +ScreenEmChars(SCREEN *pScr, char *c, int len) +{ + /* + * Function: Send a string of characters to the screen. Placement + * continues as long as the stream of characters does not contain any + * control chracters or cause wrapping to another line. When a control + * character is encountered or wrapping occurs, display stops and a + * count of the number of characters is returned. + * + * Parameters: + * pScr - the screen to place the characters on. + * c - the string of characters to place on the screen. + * len - the number of characters contained in the string + * + * Returns: The number of characters actually placed on the screen. + */ + + int insert; + int ocount; + int attrib; + int extra; + int nchars; + char *acurrent; /* place to put attributes */ + char *current; /* place to put characters */ + char *start; + SCREENLINE *pScrLine; + + if (len <= 0) + return(0); + + if (pScr->x != pScr->width - 1) + pScr->bWrapPending = FALSE; + else { + if (pScr->bWrapPending) { + pScr->x = 0; + pScr->bWrapPending = FALSE; + ScreenIndex(pScr); + } + } + + pScrLine = GetScreenLineFromY(pScr, pScr->y); + if (pScrLine == NULL) + return(0); + + current = &pScrLine->text[pScr->x]; + acurrent = &pScrLine->attrib[pScr->x]; + start = current; + ocount = pScr->x; + extra = 0; + + attrib = pScr->attrib; + insert = pScr->IRM; + + for (nchars = 0; nchars < len && *c >= 32; nchars++) { + if (insert) + ScreenInsChar(pScr, 1); + + *current = *c; + *acurrent = (char) attrib; + c++; + if (pScr->x < pScr->width - 1) { + acurrent++; + current++; + pScr->x++; + } + else { + extra = 1; + if (pScr->DECAWM) { + pScr->bWrapPending = TRUE; + nchars++; + break; + } + } + } + + ScreenDraw(pScr, ocount, pScr->y, pScr->attrib, + pScr->x - ocount + extra, start); + + return(nchars); +} + + +void +ScreenEm(LPSTR c, int len, SCREEN *pScr) +{ + int escflg; /* vt100 escape level */ + RECT rc; + unsigned int ic; + char stat[20]; + int i; + int nchars; + + if (pScr->screen_bottom != pScr->buffer_bottom) { + ScreenUnscroll(pScr); + InvalidateRect(pScr->hWnd, NULL, TRUE); + SetScrollPos(pScr->hWnd, SB_VERT, pScr->numlines, TRUE); + } + + ScreenCursorOff(pScr); + escflg = pScr->escflg; + +#ifdef UM + if (pScr->localprint && len > 0) { /* see if printer needs anything */ + pcount = send_localprint(c, len); + len -= pcount; + c += pcount; + } +#endif + + while (len > 0) { + /* + * look at first character in the vt100 string, if it is a + * non-printable ascii code + */ + while((*c < 32) && (escflg == 0) && (len > 0)) { + switch(*c) { + + case 0x1b: /* ESC found (begin vt100 control sequence) */ + escflg++; + break; + + case -1: /* IAC from telnet session */ + escflg = 6; + break; + +#ifdef CISB + case 0x05: /* CTRL-E found (answerback) */ + bp_ENQ(); + break; +#endif + + case 0x07: /* CTRL-G found (bell) */ + ScreenBell(pScr); + break; + + case 0x08: /* CTRL-H found (backspace) */ + ScreenBackspace(pScr); + break; + + case 0x09: /* CTRL-I found (tab) */ + ScreenTab(pScr); /* Later change for versatile tabbing */ + break; + + case 0x0a: /* CTRL-J found (line feed) */ + case 0x0b: /* CTRL-K found (treat as line feed) */ + case 0x0c: /* CTRL-L found (treat as line feed) */ + ScreenIndex(pScr); + break; + + case 0x0d: /* CTRL-M found (carriage feed) */ + ScreenCarriageFeed(pScr); + break; + +#if 0 + case 0x0e: /* CTRL-N found (invoke Graphics (G1) character set) */ + if (pScr->G1) + pScr->attrib = VSgraph(pScr->attrib); + else + pScr->attrib = VSnotgraph(pScr->attrib); + pScr->charset = 1; + break; + + case 0x0f: /* CTRL-O found (invoke 'normal' (G0) character set) */ + if(pScr->G0) + pScr->attrib = VSgraph(pScr->attrib); + else + pScr->attrib = VSnotgraph(pScr->attrib); + pScr->charset = 0; + break; +#endif + +#ifdef CISB + case 0x10: /* CTRL-P found (undocumented in vt100) */ + bp_DLE(c, len); + len = 0; + break; +#endif + +#if 0 + case 0x11: /* CTRL-Q found (XON) (unused presently) */ + case 0x13: /* CTRL-S found (XOFF) (unused presently) */ + case 0x18: /* CTRL-X found (CAN) (unused presently) */ + case 0x1a: /* CTRL-Z found (SUB) (unused presently) */ + break; +#endif + } + + c++; /* advance to the next character in the string */ + len--; /* decrement the counter */ + } + + if (escflg == 0) { /* check for normal character to print */ + nchars = ScreenEmChars(pScr, c, len); + c += nchars; + len -= nchars; + } + + while ((len > 0) && (escflg == 1)) { /* ESC character was found */ + switch(*c) { + + case 0x08: /* CTRL-H found (backspace) */ + ScreenBackspace(pScr); + break; + + /* + * mostly cursor movement options, and DEC private stuff following + */ + case '[': + ScreenApClear(pScr); + escflg = 2; + break; + + case '#': /* various screen adjustments */ + escflg = 3; + break; + + case '(': /* G0 character set options */ + escflg = 4; + break; + + case ')': /* G1 character set options */ + escflg = 5; + break; + + case '>': /* keypad numeric mode (DECKPAM) */ + pScr->DECPAM = 0; + escflg = 0; + break; + + case '=': /* keypad application mode (DECKPAM) */ + pScr->DECPAM = 1; + escflg = 0; + break; + + case '7': /* save cursor (DECSC) */ + ScreenSaveCursor(pScr); + escflg = 0; + break; + + case '8': /* restore cursor (DECRC) */ + ScreenRestoreCursor(pScr); + escflg = 0; + break; + +#if 0 + case 'c': /* reset to initial state (RIS) */ + ScreenReset(pScr); + escflg = 0; + break; +#endif + + case 'D': /* index (move down one line) (IND) */ + ScreenIndex(pScr); + escflg = 0; + break; + + case 'E': /* next line (move down one line and to first column) (NEL) */ + pScr->x = 0; + ScreenIndex(pScr); + escflg = 0; + break; + + case 'H': /* horizontal tab set (HTS) */ + pScr->tabs[pScr->x] = 'x'; + escflg = 0; + break; + +#ifdef CISB + case 'I': /* undoumented in vt100 */ + bp_ESC_I(); + break; +#endif + + case 'M': /* reverse index (move up one line) (RI) */ + ScreenRevIndex(pScr); + escflg = 0; + break; + + case 'Z': /* identify terminal (DECID) */ + escflg = 0; + break; + + default: + /* put the ESC character into the Screen */ + ScreenEmChars(pScr, "\033", 1); + /* put the next character into the Screen */ + ScreenEmChars(pScr, c, 1); + escflg = 0; + break; + + } /* end switch */ + + c++; + len--; + } + + while((escflg == 2) && (len > 0)) { /* '[' handling */ + switch(*c) { + + case 0x08: /* backspace */ + ScreenBackspace(pScr); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': /* numeric parameters */ + if (pScr->parms[pScr->parmptr] < 0) + pScr->parms[pScr->parmptr] = 0; + pScr->parms[pScr->parmptr] *= 10; + pScr->parms[pScr->parmptr] += *c - '0'; + break; + + case '?': /* vt100 mode change */ + pScr->parms[pScr->parmptr++] = -2; + break; + + case ';': /* parameter divider */ + pScr->parmptr++; + break; + + case 'A': /* cursor up (CUU) */ + pScr->bWrapPending = FALSE; + rc.left = pScr->x * pScr->cxChar; + rc.right = (pScr->x + 1) * pScr->cxChar; + rc.top = pScr->cyChar * pScr->y; + rc.bottom = pScr->cyChar * (pScr->y + 1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + if (pScr->parms[0] < 1) + pScr->y--; + else + pScr->y -= pScr->parms[0]; + if(pScr->y < pScr->top) + pScr->y = pScr->top; + ScreenRange(pScr); + escflg = 0; + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); + break; + + case 'B': /* cursor down (CUD) */ + pScr->bWrapPending = FALSE; + rc.left = pScr->x * pScr->cxChar; + rc.right = (pScr->x + 1) * pScr->cxChar; + rc.top = pScr->cyChar * pScr->y; + rc.bottom = pScr->cyChar * (pScr->y + 1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + if (pScr->parms[0] < 1) + pScr->y++; + else + pScr->y += pScr->parms[0]; + if (pScr->y > pScr->bottom) + pScr->y = pScr->bottom; + ScreenRange(pScr); + escflg = 0; + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); + break; + + case 'C': /* cursor forward (right) (CUF) */ + pScr->bWrapPending = FALSE; + rc.left = pScr->x * pScr->cxChar; + rc.right = (pScr->x + 1) * pScr->cxChar; + rc.top = pScr->cyChar * pScr->y; + rc.bottom = pScr->cyChar * (pScr->y +1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + if(pScr->parms[0] < 1) + pScr->x++; + else + pScr->x += pScr->parms[0]; + ScreenRange(pScr); + if (pScr->x > pScr->width) + pScr->x = pScr->width; + escflg = 0; + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); + break; + + case 'D': /* cursor backward (left) (CUB) */ + pScr->bWrapPending = FALSE; + rc.left = pScr->x * pScr->cxChar; + rc.right = (pScr->x + 1) * pScr->cxChar; + rc.top = pScr->cyChar * pScr->y; + rc.bottom = pScr->cyChar * (pScr->y + 1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + if(pScr->parms[0] < 1) + pScr->x--; + else + pScr->x -= pScr->parms[0]; + ScreenRange(pScr); + escflg = 0; + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); + break; + + case 'f': /* horizontal & vertical position (HVP) */ + case 'H': /* cursor position (CUP) */ + pScr->bWrapPending = FALSE; + rc.left = pScr->x * pScr->cxChar; + rc.right = (pScr->x + 1) * pScr->cxChar; + rc.top = pScr->cyChar * pScr->y; + rc.bottom = pScr->cyChar * (pScr->y + 1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + pScr->x = pScr->parms[1] - 1; + pScr->y = pScr->parms[0] - 1; + ScreenRange(pScr); /* make certain the cursor position is valid */ + escflg = 0; + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); + break; + + case 'J': /* erase in display (ED) */ + switch(pScr->parms[0]) { + + case -1: + case 0: /* erase from active position to end of screen */ + ScreenEraseToEndOfScreen(pScr); + break; + case 1: /* erase from start of screen to active position */ +#if 0 + ScreenEraseToPosition(pScr); +#endif + break; + + case 2: /* erase whole screen */ + ScreenEraseScreen(pScr); + break; + + default: + break; + } + + escflg = 0; + break; + + case 'K': /* erase in line (EL) */ + switch(pScr->parms[0]) { + case -1: + case 0: /* erase to end of line */ + ScreenEraseToEOL(pScr); + break; + + case 1: /* erase to beginning of line */ + ScreenEraseToBOL(pScr); + break; + + case 2: /* erase whole line */ + ScreenEraseLine(pScr, -1); + break; + + default: + break; + } + + escflg = 0; + break; + + case 'L': /* insert n lines preceding current line (IL) */ + if (pScr->parms[0] < 1) + pScr->parms[0] = 1; + ScreenInsLines(pScr, pScr->parms[0], -1); + escflg = 0; + break; + + case 'M': /* delete n lines from current position downward (DL) */ + if (pScr->parms[0] < 1) + pScr->parms[0] = 1; + ScreenDelLines(pScr, pScr->parms[0], -1); + escflg = 0; + break; + + case 'P': /* delete n chars from cursor to the left (DCH) */ + if (pScr->parms[0] < 1) + pScr->parms[0] = 1; + ScreenDelChars(pScr, pScr->parms[0]); + escflg = 0; + break; + +#if 0 + case 'R': /* receive cursor position status from host */ + break; +#endif + +#if 0 + case 'c': /* device attributes (DA) */ + ScreenSendIdent(); + escflg = 0; + break; +#endif + + case 'g': /* tabulation clear (TBC) */ + if (pScr->parms[0] == 3)/* clear all tabs */ + ScreenTabClear(pScr); + else + if (pScr->parms[0] <= 0) /* clear tab stop at active position */ + pScr->tabs[pScr->x] = ' '; + escflg = 0; + break; + + case 'h': /* set mode (SM) */ + ScreenSetOption(pScr,1); + escflg = 0; + break; + + case 'i': /* toggle printer */ +#if 0 + if(pScr->parms[pScr->parmptr] == 5) + pScr->localprint = 1; + else if (pScr->parms[pScr->parmptr] == 4) + pScr->localprint = 0; +#endif + escflg = 0; + break; + + case 'l': /* reset mode (RM) */ + ScreenSetOption(pScr,0); + escflg = 0; + break; + + case 'm': /* select graphics rendition (SGR) */ + { + int temp = 0; + + while (temp <= pScr->parmptr) { + if (pScr->parms[temp] < 1) + pScr->attrib &= 128; + else + pScr->attrib |= 1 << (pScr->parms[temp] - 1); + temp++; + } + } + escflg = 0; + break; + + case 'n': /* device status report (DSR) */ + switch (pScr->parms[0]) { +#if 0 + case 0: /* response from vt100; ready, no malfunctions */ + case 3: /* response from vt100; malfunction, retry */ +#endif + case 5: /* send status */ + case 6: /* send active position */ + wsprintf(stat, "\033[%d;%dR", pScr->y + 1, pScr->x + 1); + for (i = 0; stat[i]; i++) + SendMessage(pScr->hwndTel, WM_MYSCREENCHAR, + stat[i], (LPARAM) pScr); + break; + } /* end switch */ + escflg = 0; + break; + + case 'q': /* load LEDs (unsupported) (DECLL) */ + escflg = 0; + break; + + case 'r': /* set top & bottom margins (DECSTBM) */ + if (pScr->parms[0] < 0) + pScr->top = 0; + else + pScr->top = pScr->parms[0] - 1; + if (pScr->parms[1] < 0) + pScr->bottom = pScr->height - 1; + else + pScr->bottom = pScr->parms[1] - 1; + if (pScr->top < 0) + pScr->top = 0; + if (pScr->top > pScr->height-1) + pScr->top = pScr->height-1; + if (pScr->bottom < 1) + pScr->bottom = pScr->height; + if (pScr->bottom >= pScr->height) + pScr->bottom = pScr->height - 1; + if (pScr->top >= pScr->bottom) {/* check for valid scrolling region */ + if (pScr->bottom >= 1) /* + * assume the bottom value has + * precedence, unless it is as the + * top of the screen + */ + pScr->top = pScr->bottom - 1; + else /* totally psychotic case, bottom of screen set to the very top line, move the bottom to below the top */ + pScr->bottom = pScr->top + 1; + } + pScr->x = 0; + pScr->y = 0; +#if 0 + if (pScr->DECORG) + pScr->y = pScr->top; /* origin mode relative */ +#endif + escflg = 0; + break; + +#if 0 + case 'x': /* request/report terminal parameters + (DECREQTPARM/DECREPTPARM) */ + case 'y': /* invoke confidence test (DECTST) */ + break; +#endif + + default: + escflg = 0; + break; + + } + + c++; + len--; + +#if 0 + if (pScr->localprint && (len > 0)) { /* see if printer needs anything */ + pcount = send_localprint(c, len); + len -= pcount; + c += pcount; + } +#endif + } + + while ((escflg == 3) && (len > 0)) { /* # Handling */ + switch (*c) { + case 0x08: /* backspace */ + ScreenBackspace(pScr); + break; + +#if 0 + case '3': /* top half of double line (DECDHL) */ + case '4': /* bottom half of double line (DECDHL) */ + case '5': /* single width line (DECSWL) */ + case '6': /* double width line (DECDWL) */ + break; +#endif + + case '8': /* screen alignment display (DECALN) */ + ScreenAlign(pScr); + escflg = 0; + break; + + default: + escflg = 0; + break; + + } + + c++; + len--; + } + + while ((escflg == 4) && (len > 0)) { /* ( Handling (GO character set) */ + switch (*c) { + + case 0x08: /* backspace */ + ScreenBackspace(pScr); + break; + +#if 0 + case 'A': /* united kingdom character set (unsupported) */ + case 'B': /* ASCII character set */ + case '1': /* choose standard graphics (same as ASCII) */ + pScr->G0 = 0; + if (!pScr->charset) + pScr->attrib = ScreenNotGraph(pScr->attrib); + escflg = 0; + break; + + case '0': /* choose special graphics set */ + case '2': /* alternate character set (special graphics) */ + pScr->G0 = 1; + if(!pScr->charset) + pScr->attrib = ScreenGraph(pScr->attrib); + escflg = 0; + break; +#endif + + default: + escflg = 0; + break; + } + + c++; + len--; + + } /* end while */ + + while((escflg == 5) && (len > 0)) { /* ) Handling (G1 handling) */ + switch (*c) { + + case 0x08: /* backspace */ + ScreenBackspace(pScr); + break; + +#if 0 + case 'A': /* united kingdom character set (unsupported) */ + case 'B': /* ASCII character set */ + case '1': /* choose standard graphics (same as ASCII) */ + pScr->G1 = 0; + if (pScr->charset) + pScr->attrib = ScreenNotGraph(pScr->attrib); + escflg = 0; + break; + + case '0': /* choose special graphics set */ + case '2': /* alternate character set (special graphics) */ + pScr->G1 = 1; + if(pScr->charset) + pScr->attrib = ScreenGraph(pScr->attrib); + escflg = 0; + break; +#endif + + default: + escflg = 0; + break; + } /* end switch */ + + c++; + len--; + } /* end while */ + + while ((escflg >= 6) && (escflg <= 10) && (len > 0)) { /* Handling IAC */ + ic = (unsigned char) *c; + switch (escflg) { + + case 6: /* Handling IAC xx */ + if (ic == 255) /* if IAC */ + escflg = 0; + else if (ic == 250) /* if SB */ + escflg = 7; + else + escflg = 9; + break; + + case 7: /* Handling IAC SB xx */ + if (ic == 255) /* if IAC */ + escflg = 8; + break; + + case 8: /* Handling IAC SB IAC xx */ + if (ic == 255) /* if IAC IAC */ + escflg = 7; + else if (ic == 240) /* if IAC SE */ + escflg = 0; + break; + + case 9: /* IAC xx xx */ + escflg = 0; + break; + } + c++; /* advance to the next character in the string */ + len--; /* decrement the counter */ + } + + if (escflg > 2 && escflg < 6 && len > 0) { + escflg = 0; + c++; + len--; + } + } + pScr->escflg = escflg; + ScreenCursorOn(pScr); +} diff --git a/krb5-1-6/src/windows/wintel/enc_des.c b/krb5-1-6/src/windows/wintel/enc_des.c new file mode 100644 index 000000000..7bf72f488 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/enc_des.c @@ -0,0 +1,725 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* based on @(#)enc_des.c 8.1 (Berkeley) 6/4/93 */ + +#ifdef ENCRYPTION + +#include "telnet_arpa.h" +#include <stdio.h> +#include <stdlib.h> + +#include "telnet.h" + +#include "encrypt.h" + +#define CFB 0 +#define OFB 1 + +#define NO_SEND_IV 1 +#define NO_RECV_IV 2 +#define NO_KEYID 4 +#define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) +#define SUCCESS 0 +#define xFAILED -1 + + +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; + struct stinfo { + Block str_output; + Block str_feed; + Block str_iv; + Block str_ikey; + Schedule str_sched; + int str_index; + int str_flagshift; + } streams[2]; +}; + +static struct fb fb[2]; + +struct keyidlist { + char *keyid; + int keyidlen; + char *key; + int keylen; + int flags; +} keyidlist [] = { + { "\0", 1, 0, 0, 0 }, /* default key of zero */ + { 0, 0, 0, 0, 0 } +}; + +#define KEYFLAG_MASK 03 + +#define KEYFLAG_NOINIT 00 +#define KEYFLAG_INIT 01 +#define KEYFLAG_OK 02 +#define KEYFLAG_BAD 03 + +#define KEYFLAG_SHIFT 2 + +#define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) + +#define FB64_IV 1 +#define FB64_IV_OK 2 +#define FB64_IV_BAD 3 + +extern kstream EncryptKSGlobalHack; + +void fb64_stream_iv (Block, struct stinfo *); +void fb64_init (struct fb *); +static int fb64_start (struct fb *, int, int); +int fb64_is (unsigned char *, int, struct fb *); +int fb64_reply (unsigned char *, int, struct fb *); +static void fb64_session (Session_Key *, int, struct fb *); +void fb64_stream_key (Block, struct stinfo *); +int fb64_keyid (int, unsigned char *, int *, struct fb *); + + void +cfb64_init(server) + int server; +{ + fb64_init(&fb[CFB]); + fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; + fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); + fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); +} + + void +ofb64_init(server) + int server; +{ + fb64_init(&fb[OFB]); + fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; + fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); + fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); +} + + void +fb64_init(fbp) + register struct fb *fbp; +{ + memset((void *)fbp, 0, sizeof(*fbp)); + fbp->state[0] = fbp->state[1] = xFAILED; + fbp->fb_feed[0] = IAC; + fbp->fb_feed[1] = SB; + fbp->fb_feed[2] = TELOPT_ENCRYPT; + fbp->fb_feed[3] = ENCRYPT_IS; +} + +/* + * Returns: + * -1: some error. Negotiation is done, encryption not ready. + * 0: Successful, initial negotiation all done. + * 1: successful, negotiation not done yet. + * 2: Not yet. Other things (like getting the key from + * Kerberos) have to happen before we can continue. + */ + int +cfb64_start(dir, server) + int dir; + int server; +{ + return(fb64_start(&fb[CFB], dir, server)); +} + int +ofb64_start(dir, server) + int dir; + int server; +{ + return(fb64_start(&fb[OFB], dir, server)); +} + + static int +fb64_start(fbp, dir, server) + struct fb *fbp; + int dir; + int server; +{ + int x; + unsigned char *p; + register int state; + + switch (dir) { + case DIR_DECRYPT: + /* + * This is simply a request to have the other side + * start output (our input). He will negotiate an + * IV so we need not look for it. + */ + state = fbp->state[dir-1]; + if (state == xFAILED) + state = IN_PROGRESS; + break; + + case DIR_ENCRYPT: + state = fbp->state[dir-1]; + if (state == xFAILED) + state = IN_PROGRESS; + else if ((state & NO_SEND_IV) == 0) + break; + + if (!VALIDKEY(fbp->krbdes_key)) { + fbp->need_start = 1; + break; + } + state &= ~NO_SEND_IV; + state |= NO_RECV_IV; + /* + * 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); + p = fbp->fb_feed + 3; + *p++ = ENCRYPT_IS; + p++; + *p++ = FB64_IV; + for (x = 0; x < sizeof(Block); ++x) { + if ((*p++ = fbp->temp_feed[x]) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; +#ifdef DEBUG + printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); +#endif + TelnetSend(EncryptKSGlobalHack, fbp->fb_feed, p - fbp->fb_feed, 0); + break; + default: + return(xFAILED); + } + return(fbp->state[dir-1] = state); +} + +/* + * Returns: + * -1: some error. Negotiation is done, encryption not ready. + * 0: Successful, initial negotiation all done. + * 1: successful, negotiation not done yet. + */ + int +cfb64_is(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_is(data, cnt, &fb[CFB])); +} + int +ofb64_is(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_is(data, cnt, &fb[OFB])); +} + + int +fb64_is(data, cnt, fbp) + unsigned char *data; + int cnt; + struct fb *fbp; +{ + unsigned char *p; + register int state = fbp->state[DIR_DECRYPT-1]; + + if (cnt-- < 1) + goto failure; + + switch (*data++) { + case FB64_IV: + if (cnt != sizeof(Block)) { +#ifdef DEBUG + if (encrypt_debug_mode) + printf("CFB64: initial vector failed on size\r\n"); +#endif + state = xFAILED; + goto failure; + } + +#ifdef DEBUG + if (encrypt_debug_mode) { + printf("CFB64: initial vector received\r\n"); + printf("Initializing Decrypt stream\r\n"); + } +#endif + fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); + + p = fbp->fb_feed + 3; + *p++ = ENCRYPT_REPLY; + p++; + *p++ = FB64_IV_OK; + *p++ = IAC; + *p++ = SE; +#ifdef DEBUG + printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); +#endif + TelnetSend(EncryptKSGlobalHack, fbp->fb_feed, p - fbp->fb_feed, 0); + + state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; + break; + + default: +#if 0 + if (encrypt_debug_mode) { + printf("Unknown option type: %d\r\n", *(data-1)); + printd(data, cnt); + printf("\r\n"); + } +#endif + /* FALL THROUGH */ + failure: + /* + * We failed. Send an FB64_IV_BAD option + * to the other side so it will know that + * things failed. + */ + p = fbp->fb_feed + 3; + *p++ = ENCRYPT_REPLY; + p++; + *p++ = FB64_IV_BAD; + *p++ = IAC; + *p++ = SE; +#ifdef DEBUG + printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); +#endif + TelnetSend(EncryptKSGlobalHack, fbp->fb_feed, p - fbp->fb_feed, 0); + + break; + } + return(fbp->state[DIR_DECRYPT-1] = state); +} + +/* + * Returns: + * -1: some error. Negotiation is done, encryption not ready. + * 0: Successful, initial negotiation all done. + * 1: successful, negotiation not done yet. + */ + int +cfb64_reply(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_reply(data, cnt, &fb[CFB])); +} + int +ofb64_reply(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_reply(data, cnt, &fb[OFB])); +} + + + int +fb64_reply(data, cnt, fbp) + unsigned char *data; + int cnt; + struct fb *fbp; +{ + register int state = fbp->state[DIR_ENCRYPT-1]; + + if (cnt-- < 1) + goto failure; + + switch (*data++) { + case FB64_IV_OK: + fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); + if (state == xFAILED) + state = IN_PROGRESS; + state &= ~NO_RECV_IV; + encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); + break; + + case FB64_IV_BAD: + memset(fbp->temp_feed, 0, sizeof(Block)); + fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); + state = xFAILED; + break; + + default: +#if 0 + if (encrypt_debug_mode) { + printf("Unknown option type: %d\r\n", data[-1]); + printd(data, cnt); + printf("\r\n"); + } +#endif + /* FALL THROUGH */ + failure: + state = xFAILED; + break; + } + return(fbp->state[DIR_ENCRYPT-1] = state); +} + + void +cfb64_session(key, server) + Session_Key *key; + int server; +{ + fb64_session(key, server, &fb[CFB]); +} + + void +ofb64_session(key, server) + Session_Key *key; + int server; +{ + fb64_session(key, server, &fb[OFB]); +} + + static void +fb64_session(key, server, fbp) + Session_Key *key; + int server; + struct fb *fbp; +{ + + if (!key || key->type != SK_DES) { +#ifdef DEBUG + if (encrypt_debug_mode) + printf("Can't set krbdes's session key (%d != %d)\r\n", + key ? key->type : -1, SK_DES); +#endif + 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]); + + if (fbp->once == 0) { + des_init_random_number_generator(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 + * that we have the key. + */ + if (fbp->need_start) { + fbp->need_start = 0; + fb64_start(fbp, DIR_ENCRYPT, server); + } +} + +/* + * We only accept a keyid of 0. If we get a keyid of + * 0, then mark the state as SUCCESS. + */ + int +cfb64_keyid(dir, kp, lenp) + int dir, *lenp; + unsigned char *kp; +{ + return(fb64_keyid(dir, kp, lenp, &fb[CFB])); +} + + int +ofb64_keyid(dir, kp, lenp) + int dir, *lenp; + unsigned char *kp; +{ + return(fb64_keyid(dir, kp, lenp, &fb[OFB])); +} + + int +fb64_keyid(dir, kp, lenp, fbp) + int dir, *lenp; + unsigned char *kp; + struct fb *fbp; +{ + register int state = fbp->state[dir-1]; + + if (*lenp != 1 || (*kp != '\0')) { + *lenp = 0; + return(state); + } + + if (state == xFAILED) + state = IN_PROGRESS; + + state &= ~NO_KEYID; + + return(fbp->state[dir-1] = state); +} + +#if 0 + void +fb64_printsub(data, cnt, buf, buflen, type) + unsigned char *data, *buf, *type; + int cnt, buflen; +{ + char lbuf[32]; + register int i; + char *cp; + + buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ + buflen -= 1; + + switch(data[2]) { + case FB64_IV: + sprintf(lbuf, "%s_IV", type); + cp = lbuf; + goto common; + + case FB64_IV_OK: + sprintf(lbuf, "%s_IV_OK", type); + cp = lbuf; + goto common; + + case FB64_IV_BAD: + sprintf(lbuf, "%s_IV_BAD", type); + cp = lbuf; + goto common; + + default: + sprintf(lbuf, " %d (unknown)", data[2]); + cp = lbuf; + common: + for (; (buflen > 0) && (*buf = *cp++); buf++) + buflen--; + for (i = 3; i < cnt; i++) { + sprintf(lbuf, " %d", data[i]); + for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) + buflen--; + } + break; + } +} + + void +cfb64_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + fb64_printsub(data, cnt, buf, buflen, "CFB64"); +} + + void +ofb64_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + fb64_printsub(data, cnt, buf, buflen, "OFB64"); +} +#endif + + void +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); +} + + void +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_output, (void *)stp->str_iv, sizeof(Block)); + + stp->str_index = sizeof(Block); +} + +/* + * DES 64 bit Cipher Feedback + * + * key --->+-----+ + * +->| DES |--+ + * | +-----+ | + * | v + * INPUT --(--------->(+)+---> DATA + * | | + * +-------------+ + * + * + * Given: + * iV: Initial vector, 64 bits (8 bytes) long. + * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). + * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. + * + * V0 = DES(iV, key) + * On = Dn ^ Vn + * V(n+1) = DES(On, key) + */ + + void +cfb64_encrypt(s, c) + register unsigned char *s; + int c; +{ + register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; + register int index; + + index = stp->str_index; + while (c-- > 0) { + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1); + memcpy((void *)stp->str_feed,(void *)b,sizeof(Block)); + index = 0; + } + + /* On encryption, we store (feed ^ data) which is cypher */ + *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); + s++; + index++; + } + stp->str_index = index; +} + + int +cfb64_decrypt(data) + int data; +{ + register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; + int index; + + if (data == -1) { + /* + * Back up one byte. It is assumed that we will + * never back up more than one byte. If we do, this + * may or may not work. + */ + if (stp->str_index) + --stp->str_index; + return(0); + } + + index = stp->str_index++; + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1); + memcpy((void *)stp->str_feed, (void *)b, sizeof(Block)); + stp->str_index = 1; /* Next time will be 1 */ + index = 0; /* But now use 0 */ + } + + /* On decryption we store (data) which is cypher. */ + stp->str_output[index] = data; + return(data ^ stp->str_feed[index]); +} + +/* + * DES 64 bit Output Feedback + * + * key --->+-----+ + * +->| DES |--+ + * | +-----+ | + * +-----------+ + * v + * INPUT -------->(+) ----> DATA + * + * Given: + * iV: Initial vector, 64 bits (8 bytes) long. + * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). + * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. + * + * V0 = DES(iV, key) + * V(n+1) = DES(Vn, key) + * On = Dn ^ Vn + */ + void +ofb64_encrypt(s, c) + register unsigned char *s; + int c; +{ + register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; + register int index; + + index = stp->str_index; + while (c-- > 0) { + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1); + memcpy((void *)stp->str_feed,(void *)b,sizeof(Block)); + index = 0; + } + *s++ ^= stp->str_feed[index]; + index++; + } + stp->str_index = index; +} + + int +ofb64_decrypt(data) + int data; +{ + register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; + int index; + + if (data == -1) { + /* + * Back up one byte. It is assumed that we will + * never back up more than one byte. If we do, this + * may or may not work. + */ + if (stp->str_index) + --stp->str_index; + return(0); + } + + index = stp->str_index++; + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1); + memcpy((void *)stp->str_feed, (void *)b, sizeof(Block)); + stp->str_index = 1; /* Next time will be 1 */ + index = 0; /* But now use 0 */ + } + + return(data ^ stp->str_feed[index]); +} + +#endif /* ENCRYPTION */ diff --git a/krb5-1-6/src/windows/wintel/enc_des.h b/krb5-1-6/src/windows/wintel/enc_des.h new file mode 100644 index 000000000..b7f0f95fd --- /dev/null +++ b/krb5-1-6/src/windows/wintel/enc_des.h @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)enc-proto.h 8.1 (Berkeley) 6/4/93 + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +#ifdef ENCRYPTION +void encrypt_init (char *, int); +Encryptions *findencryption (int); +void encrypt_auto (int); +void decrypt_auto (int); +void encrypt_is (unsigned char *, int); +void encrypt_reply (unsigned char *, int); +void encrypt_start_input (int); +void encrypt_session_key (Session_Key *, int); +void encrypt_end_input (void); +void encrypt_start_output (int); +void encrypt_end_output (void); +void encrypt_send_request_start (void); +void encrypt_send_request_end (void); +void encrypt_send_end (void); +void encrypt_wait (void); +int encrypt_is_encrypting (void); +void encrypt_send_support (void); +void encrypt_send_keyid (int, unsigned char *, int, int); +int net_write (unsigned char *, int); + +#ifdef TELENTD +void encrypt_wait (void); +#else +int encrypt_cmd (int, char **); +void encrypt_display (void); +#endif + +void krbdes_encrypt (unsigned char *, int); +int krbdes_decrypt (int); +int krbdes_is (unsigned char *, int); +int krbdes_reply (unsigned char *, int); +void krbdes_init (int); +int krbdes_start (int, int); +void krbdes_session (Session_Key *, int); +void krbdes_printsub (unsigned char *, int, unsigned char *, int); + +void cfb64_encrypt (unsigned char *, int); +int cfb64_decrypt (int); +void cfb64_init (int); +int cfb64_start (int, int); +int cfb64_is (unsigned char *, int); +int cfb64_reply (unsigned char *, int); +void cfb64_session (Session_Key *, int); +int cfb64_keyid (int, unsigned char *, int *); +void cfb64_printsub (unsigned char *, int, unsigned char *, int); + +void ofb64_encrypt (unsigned char *, int); +int ofb64_decrypt (int); +void ofb64_init (int); +int ofb64_start (int, int); +int ofb64_is (unsigned char *, int); +int ofb64_reply (unsigned char *, int); +void ofb64_session (Session_Key *, int); +int ofb64_keyid (int, unsigned char *, int *); +void ofb64_printsub (unsigned char *, int, unsigned char *, int); + +int des_new_random_key (Block); +void des_set_random_generator_seed (Block); +void des_key_sched (Block, Schedule); +void des_ecb_encrypt (Block, Block, Schedule, int); +int des_string_to_key (char *, Block); +#endif /* ENCRYPTION */ diff --git a/krb5-1-6/src/windows/wintel/encrypt.c b/krb5-1-6/src/windows/wintel/encrypt.c new file mode 100644 index 000000000..6d97ccd5d --- /dev/null +++ b/krb5-1-6/src/windows/wintel/encrypt.c @@ -0,0 +1,999 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* based on @(#)encrypt.c 8.1 (Berkeley) 6/4/93 */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifdef ENCRYPTION + +#include <stdio.h> + +#define isprefix(a, b) (!strncmp((a), (b), strlen(b))) + +#ifdef KRB4 +#include <windows.h> +#include <time.h> +#include <string.h> +#include "winsock.h" +#include "kerberos.h" +#endif +#ifdef KRB5 +#include <time.h> +#include <string.h> +#include "krb5.h" +#include "com_err.h" +#endif + +#include "telnet.h" +#include "encrypt.h" + +#define ENCRYPT_NAMES +#include "telnet_arpa.h" + +/* + * These function pointers point to the current routines + * for encrypting and decrypting data. + */ +void (*encrypt_output) (unsigned char *, int); +int (*decrypt_input) (int); + +#ifdef DEBUG +int encrypt_debug_mode = 1; +int encrypt_verbose = 1; +#else +int encrypt_verbose = 0; +#endif + +static char dbgbuf [10240]; + +static int decrypt_mode = 0; +static int encrypt_mode = 0; +static int autoencrypt = 1; +static int autodecrypt = 1; +static int havesessionkey = 0; + +kstream EncryptKSGlobalHack = NULL; + +#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) + +static long i_support_encrypt = + typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64); +static long i_support_decrypt = + typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64); +static long i_wont_support_encrypt = 0; +static long i_wont_support_decrypt = 0; +#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) +#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) + +static long remote_supports_encrypt = 0; +static long remote_supports_decrypt = 0; + +static Encryptions encryptions[] = { + { "DES_CFB64", + ENCTYPE_DES_CFB64, + cfb64_encrypt, + cfb64_decrypt, + cfb64_init, + cfb64_start, + cfb64_is, + cfb64_reply, + cfb64_session, + cfb64_keyid, + NULL }, + { "DES_OFB64", + ENCTYPE_DES_OFB64, + ofb64_encrypt, + ofb64_decrypt, + ofb64_init, + ofb64_start, + ofb64_is, + ofb64_reply, + ofb64_session, + ofb64_keyid, + NULL }, + { 0, }, +}; + +static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, + ENCRYPT_SUPPORT }; +static unsigned char str_suplen = 0; +static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; +static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; + +void encrypt_request_end(void); +void encrypt_request_start(unsigned char *, int); +void encrypt_enc_keyid(unsigned char *, int); +void encrypt_dec_keyid(unsigned char *, int); +void encrypt_support(unsigned char *, int); +void encrypt_start(unsigned char *, int); +void encrypt_end(void); + +int encrypt_ks_stream(struct kstream_data_block *, /* output */ + struct kstream_data_block *, /* input */ + struct kstream *); + +int decrypt_ks_stream(struct kstream_data_block *, /* output */ + struct kstream_data_block *, /* input */ + struct kstream *); + +int +encrypt_ks_stream(struct kstream_data_block *i, + struct kstream_data_block *o, + struct kstream *ks) +{ + + /* + * this is really quite bogus, since it does an in-place encryption... + */ + if (encrypt_output) { + encrypt_output(i->ptr, i->length); + return 1; + } + + return 0; +} + + +int +decrypt_ks_stream(struct kstream_data_block *i, + struct kstream_data_block *o, + struct kstream *ks) +{ + unsigned int len; + /* + * this is really quite bogus, since it does an in-place decryption... + */ + if (decrypt_input) { + for (len = 0 ; len < i->length ; len++) + ((unsigned char *)i->ptr)[len] + = decrypt_input(((unsigned char *)i->ptr)[len]); + return 1; + } + + return 0; +} + +int +decrypt_ks_hack(unsigned char *buf, int cnt) +{ + int len; + /* + * this is really quite bogus, since it does an in-place decryption... + */ + for (len = 0 ; len < cnt ; len++) + buf[len] = decrypt_input(buf[len]); + +#ifdef DEBUG + hexdump("hack:", buf, cnt); +#endif + return 1; +} + +#ifdef DEBUG +int +printsub(char c, unsigned char *s, size_t len) +{ + size_t i; + char *p = dbgbuf; + + *p++ = c; + + for (i = 0 ; (i < len) && (p - dbgbuf + 3 < sizeof(dbgbuf)) ; i++) + p += sprintf(p, "%02x ", s[i]); + dbgbuf[sizeof(dbgbuf) - 1] = '\0'; + + strncat(p, "\n", sizeof(dbgbuf) - 1 - (p - dbgbuf)); + + OutputDebugString(dbgbuf); + + return 0; +} +#endif + +/* + * parsedat[0] == the suboption we might be negoating, + */ +void +encrypt_parse(kstream ks, unsigned char *parsedat, int end_sub) +{ + char *p = dbgbuf; + +#ifdef DEBUG + printsub('<', parsedat, end_sub); +#endif + + switch(parsedat[1]) { + case ENCRYPT_START: + encrypt_start(parsedat + 2, end_sub - 2); + break; + case ENCRYPT_END: + encrypt_end(); + break; + case ENCRYPT_SUPPORT: + encrypt_support(parsedat + 2, end_sub - 2); + break; + case ENCRYPT_REQSTART: + encrypt_request_start(parsedat + 2, end_sub - 2); + break; + case ENCRYPT_REQEND: + /* + * We can always send an REQEND so that we cannot + * get stuck encrypting. We should only get this + * if we have been able to get in the correct mode + * anyhow. + */ + encrypt_request_end(); + break; + case ENCRYPT_IS: + encrypt_is(parsedat + 2, end_sub - 2); + break; + case ENCRYPT_REPLY: + encrypt_reply(parsedat + 2, end_sub - 2); + break; + case ENCRYPT_ENC_KEYID: + encrypt_enc_keyid(parsedat + 2, end_sub - 2); + break; + case ENCRYPT_DEC_KEYID: + encrypt_dec_keyid(parsedat + 2, end_sub - 2); + break; + default: + break; + } +} + +/* XXX */ +Encryptions * +findencryption(type) + int type; +{ + Encryptions *ep = encryptions; + + if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) + return(0); + while (ep->type && ep->type != type) + ++ep; + return(ep->type ? ep : 0); +} + +Encryptions * +finddecryption(int type) +{ + Encryptions *ep = encryptions; + + if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) + return(0); + while (ep->type && ep->type != type) + ++ep; + return(ep->type ? ep : 0); +} + +#define MAXKEYLEN 64 + +static struct key_info { + unsigned char keyid[MAXKEYLEN]; + int keylen; + int dir; + int *modep; + Encryptions *(*getcrypt)(); +} ki[2] = { + { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, + { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, +}; + +void +encrypt_init(kstream iks, kstream_ptr data) +{ + Encryptions *ep = encryptions; + + i_support_encrypt = i_support_decrypt = 0; + remote_supports_encrypt = remote_supports_decrypt = 0; + encrypt_mode = 0; + decrypt_mode = 0; + encrypt_output = NULL; + decrypt_input = NULL; + + str_suplen = 4; + + EncryptKSGlobalHack = iks; + + while (ep->type) { +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>I will support %s\n", + ENCTYPE_NAME(ep->type)); + OutputDebugString(dbgbuf); + } +#endif + i_support_encrypt |= typemask(ep->type); + i_support_decrypt |= typemask(ep->type); + if ((i_wont_support_decrypt & typemask(ep->type)) == 0) + if ((str_send[str_suplen++] = ep->type) == IAC) + str_send[str_suplen++] = IAC; + if (ep->init) + (*ep->init)(0); + ++ep; + } + str_send[str_suplen++] = IAC; + str_send[str_suplen++] = SE; +} + +void +encrypt_send_support() +{ + if (str_suplen) { + /* + * If the user has requested that decryption start + * immediatly, then send a "REQUEST START" before + * we negotiate the type. + */ + if (autodecrypt) + encrypt_send_request_start(); + TelnetSend(EncryptKSGlobalHack, str_send, str_suplen, 0); + +#ifdef DEBUG + printsub('>', &str_send[2], str_suplen - 2); +#endif + + str_suplen = 0; + } +} + +/* + * Called when ENCRYPT SUPPORT is received. + */ +void +encrypt_support(typelist, cnt) + unsigned char *typelist; + int cnt; +{ + register int type, use_type = 0; + Encryptions *ep; + + /* + * Forget anything the other side has previously told us. + */ + remote_supports_decrypt = 0; + + while (cnt-- > 0) { + type = *typelist++; +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Remote supports %s (%d)\n", + ENCTYPE_NAME(type), type); + OutputDebugString(dbgbuf); + } +#endif + if ((type < ENCTYPE_CNT) && + (I_SUPPORT_ENCRYPT & typemask(type))) { + remote_supports_decrypt |= typemask(type); + if (use_type == 0) + use_type = type; + } + } + if (use_type) { + ep = findencryption(use_type); + if (!ep) + return; + type = ep->start ? (*ep->start)(DIR_ENCRYPT, 0) : 0; +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>(*ep->start)() %s returned %d (%s)\n", + ENCTYPE_NAME(use_type), type, ENCRYPT_NAME(type)); + OutputDebugString(dbgbuf); + } +#endif + if (type < 0) + return; + encrypt_mode = use_type; + if (type == 0) + encrypt_start_output(use_type); + } +} + +void +encrypt_is(data, cnt) + unsigned char *data; + int cnt; +{ + Encryptions *ep; + register int type, ret; + + if (--cnt < 0) + return; + type = *data++; + if (type < ENCTYPE_CNT) + remote_supports_encrypt |= typemask(type); + if (!(ep = finddecryption(type))) { +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>encrypt_reply: " + "Can't find type %s (%d) for initial negotiation\n", + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + OutputDebugString(dbgbuf); + } +#endif + return; + } + if (!ep->is) { +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>encrypt_reply: " + "No initial negotiation needed for type %s (%d)\n", + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + OutputDebugString(dbgbuf); + } +#endif + ret = 0; + } else { + ret = (*ep->is)(data, cnt); +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, "encrypt_reply: " + "(*ep->is)(%x, %d) returned %s(%d)\n", data, cnt, + (ret < 0) ? "FAIL " : + (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); + OutputDebugString(dbgbuf); + } +#endif + } + if (ret < 0) { + autodecrypt = 0; + } else { + decrypt_mode = type; + if (ret == 0 && autodecrypt) + encrypt_send_request_start(); + } +} + +void +encrypt_reply(data, cnt) + unsigned char *data; + int cnt; +{ + Encryptions *ep; + register int ret, type; + + if (--cnt < 0) + return; + type = *data++; + if (!(ep = findencryption(type))) { +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Can't find type %s (%d) for initial negotiation\n", + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + OutputDebugString(dbgbuf); + } +#endif + return; + } + if (!ep->reply) { +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>No initial negotiation needed for type %s (%d)\n", + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + OutputDebugString(dbgbuf); + } +#endif + ret = 0; + } else { + ret = (*ep->reply)(data, cnt); +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, "(*ep->reply)(%x, %d) returned %s(%d)\n", + data, cnt, + (ret < 0) ? "FAIL " : + (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); + OutputDebugString(dbgbuf); + } +#endif + } +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>encrypt_reply returned %d\n", ret); + OutputDebugString(dbgbuf); + } +#endif + if (ret < 0) { + autoencrypt = 0; + } else { + encrypt_mode = type; + if (ret == 0 && autoencrypt) + encrypt_start_output(type); + } +} + +/* + * Called when a ENCRYPT START command is received. + */ +void +encrypt_start(data, cnt) + unsigned char *data; + int cnt; +{ + Encryptions *ep; + + if (!decrypt_mode) { + /* + * Something is wrong. We should not get a START + * command without having already picked our + * decryption scheme. Send a REQUEST-END to + * attempt to clear the channel... + */ + /* printf("Warning, Cannot decrypt input stream!!!\n"); */ + encrypt_send_request_end(); + MessageBox(NULL, "Warning, Cannot decrypt input stream!!!", NULL, + MB_OK | MB_ICONEXCLAMATION); + return; + } + + if (ep = finddecryption(decrypt_mode)) { + extern BOOL encrypt_flag; + + decrypt_input = ep->input; + EncryptKSGlobalHack->decrypt = decrypt_ks_stream; + encrypt_flag = 2; /* XXX hack */ + + if (encrypt_verbose) { + sprintf(dbgbuf, "[ Input is now decrypted with type %s ]\n", + ENCTYPE_NAME(decrypt_mode)); + OutputDebugString(dbgbuf); + } +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Start to decrypt input with type %s\n", + ENCTYPE_NAME(decrypt_mode)); + OutputDebugString(dbgbuf); + } +#endif + } else { + char buf[1024]; + wsprintf(buf, "Warning, Cannot decrypt type %s (%d)!!!", + ENCTYPE_NAME_OK(decrypt_mode) + ? ENCTYPE_NAME(decrypt_mode) : "(unknown)", + decrypt_mode); + MessageBox(NULL, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + encrypt_send_request_end(); + } +} + +void +encrypt_session_key(key, server) + Session_Key *key; + int server; +{ + Encryptions *ep = encryptions; + + havesessionkey = 1; + + while (ep->type) { + if (ep->session) + (*ep->session)(key, server); +#if defined(notdef) + if (!encrypt_output && autoencrypt && !server) + encrypt_start_output(ep->type); + if (!decrypt_input && autodecrypt && !server) + encrypt_send_request_start(); +#endif + ++ep; + } +} + +/* + * Called when ENCRYPT END is received. + */ +void +encrypt_end() +{ + decrypt_input = NULL; + EncryptKSGlobalHack->decrypt = NULL; +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Input is back to clear text\n"); + OutputDebugString(dbgbuf); + } +#endif + if (encrypt_verbose) { + sprintf(dbgbuf, "[ Input is now clear text ]\n"); + OutputDebugString(dbgbuf); + } +} + +/* + * Called when ENCRYPT REQUEST-END is received. + */ +void +encrypt_request_end() +{ + encrypt_send_end(); +} + +/* + * Called when ENCRYPT REQUEST-START is received. If we receive + * this before a type is picked, then that indicates that the + * other side wants us to start encrypting data as soon as we + * can. + */ +void +encrypt_request_start(data, cnt) + unsigned char *data; + int cnt; +{ + if (encrypt_mode == 0) { + return; + } + encrypt_start_output(encrypt_mode); +} + +static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; + +void +encrypt_keyid(); + +void +encrypt_enc_keyid(keyid, len) + unsigned char *keyid; + int len; +{ + encrypt_keyid(&ki[1], keyid, len); +} + +void +encrypt_dec_keyid(keyid, len) + unsigned char *keyid; + int len; +{ + encrypt_keyid(&ki[0], keyid, len); +} + +void +encrypt_keyid(kp, keyid, len) + struct key_info *kp; + unsigned char *keyid; + int len; +{ + Encryptions *ep; + int dir = kp->dir; + register int ret = 0; + + if (!(ep = (*kp->getcrypt)(*kp->modep))) { + if (len == 0) + return; + kp->keylen = 0; + } else if (len == 0) { + /* + * Empty option, indicates a failure. + */ + if (kp->keylen == 0) + return; + kp->keylen = 0; + if (ep->keyid) + (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); + + } else if ((len != kp->keylen) || (memcmp(keyid, kp->keyid, len) != 0)) { + /* + * Length or contents are different + */ + kp->keylen = len; + memcpy(kp->keyid, keyid, len); + if (ep->keyid) + (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); + } else { + if (ep->keyid) + ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); + if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) + encrypt_start_output(*kp->modep); + return; + } + + encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); +} + +void +encrypt_send_keyid(dir, keyid, keylen, saveit) + int dir; + unsigned char *keyid; + int keylen; + int saveit; +{ + unsigned char *strp; + + str_keyid[3] = (dir == DIR_ENCRYPT) + ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; + if (saveit) { + struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; + memcpy(kp->keyid, keyid, keylen); + kp->keylen = keylen; + } + + for (strp = &str_keyid[4]; keylen > 0; --keylen) { + if ((*strp++ = *keyid++) == IAC) + *strp++ = IAC; + } + *strp++ = IAC; + *strp++ = SE; + TelnetSend(EncryptKSGlobalHack, str_keyid, strp - str_keyid, 0); + +#ifdef DEBUG + printsub('>', &str_keyid[2], strp - str_keyid - 2); +#endif + +} + +void +encrypt_auto(on) + int on; +{ + if (on < 0) + autoencrypt ^= 1; + else + autoencrypt = on ? 1 : 0; +} + +void +decrypt_auto(on) + int on; +{ + if (on < 0) + autodecrypt ^= 1; + else + autodecrypt = on ? 1 : 0; +} + +void +encrypt_start_output(type) + int type; +{ + Encryptions *ep; + register unsigned char *p; + register int i; + + if (!(ep = findencryption(type))) { +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Can't encrypt with type %s (%d)\n", + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + OutputDebugString(dbgbuf); + } +#endif + return; + } + if (ep->start) { + i = (*ep->start)(DIR_ENCRYPT, 0); +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Encrypt start: %s (%d) %s\n", + (i < 0) ? "failed" : + "initial negotiation in progress", + i, ENCTYPE_NAME(type)); + OutputDebugString(dbgbuf); + } +#endif + if (i) + return; + } + p = str_start + 3; + *p++ = ENCRYPT_START; + for (i = 0; i < ki[0].keylen; ++i) { + if ((*p++ = ki[0].keyid[i]) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + TelnetSend(EncryptKSGlobalHack, str_start, p - str_start, 0); +#ifdef DEBUG + printsub('>', &str_start[2], p - &str_start[2]); +#endif + + /* + * If we are already encrypting in some mode, then + * encrypt the ring (which includes our request) in + * the old mode, mark it all as "clear text" and then + * switch to the new mode. + */ + encrypt_output = ep->output; + EncryptKSGlobalHack->encrypt = encrypt_ks_stream; + encrypt_mode = type; +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Started to encrypt output with type %s\n", + ENCTYPE_NAME(type)); + OutputDebugString(dbgbuf); + } +#endif + if (encrypt_verbose) { + sprintf(dbgbuf, "[ Output is now encrypted with type %s ]\n", + ENCTYPE_NAME(type)); + OutputDebugString(dbgbuf); + } +} + +void +encrypt_send_end() +{ + if (!encrypt_output) + return; + + str_end[3] = ENCRYPT_END; + TelnetSend(EncryptKSGlobalHack, str_end, sizeof(str_end), 0); +#ifdef DEBUG + printsub('>', &str_end[2], sizeof(str_end) - 2); +#endif + + /* + * Encrypt the output buffer now because it will not be done by + * netflush... + */ + encrypt_output = 0; + EncryptKSGlobalHack->encrypt = NULL; +#ifdef DEBUG + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Output is back to clear text\n"); + OutputDebugString(dbgbuf); + } +#endif + if (encrypt_verbose) { + sprintf(dbgbuf, "[ Output is now clear text ]\n"); + OutputDebugString(dbgbuf); + } +} + +void +encrypt_send_request_start() +{ + register unsigned char *p; + register int i; + + p = &str_start[3]; + *p++ = ENCRYPT_REQSTART; + for (i = 0; i < ki[1].keylen; ++i) { + if ((*p++ = ki[1].keyid[i]) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + TelnetSend(EncryptKSGlobalHack, str_start, p - str_start, 0); +#ifdef DEBUG + printsub('>', &str_start[2], p - &str_start[2]); + + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Request input to be encrypted\n"); + OutputDebugString(dbgbuf); + } +#endif +} + +void +encrypt_send_request_end() +{ + str_end[3] = ENCRYPT_REQEND; + TelnetSend(EncryptKSGlobalHack, str_end, sizeof(str_end), 0); +#ifdef DEBUG + printsub('>', &str_end[2], sizeof(str_end) - 2); + + if (encrypt_debug_mode) { + sprintf(dbgbuf, ">>>Request input to be clear text\n"); + OutputDebugString(dbgbuf); + } +#endif +} + +int encrypt_is_encrypting() +{ + if (encrypt_output && decrypt_input) + return 1; + return 0; +} + +#ifdef DEBUG +void +encrypt_debug(mode) + int mode; +{ + encrypt_debug_mode = mode; +} +#endif + +#if 0 +void +encrypt_gen_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + char tbuf[16], *cp; + + cnt -= 2; + data += 2; + buf[buflen-1] = '\0'; + buf[buflen-2] = '*'; + buflen -= 2;; + for (; cnt > 0; cnt--, data++) { + sprintf(tbuf, " %d", *data); + for (cp = tbuf; *cp && buflen > 0; --buflen) + *buf++ = *cp++; + if (buflen <= 0) + return; + } + *buf = '\0'; +} + +void +encrypt_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + Encryptions *ep; + register int type = data[1]; + + for (ep = encryptions; ep->type && ep->type != type; ep++) + ; + + if (ep->printsub) + (*ep->printsub)(data, cnt, buf, buflen); + else + encrypt_gen_printsub(data, cnt, buf, buflen); +} +#endif + +#endif /* ENCRYPTION */ diff --git a/krb5-1-6/src/windows/wintel/encrypt.h b/krb5-1-6/src/windows/wintel/encrypt.h new file mode 100644 index 000000000..4d7afb176 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/encrypt.h @@ -0,0 +1,178 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)encrypt.h 8.1 (Berkeley) 6/4/93 + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifdef ENCRYPTION + +#ifndef __ENCRYPTION__ +#define __ENCRYPTION__ + +#define DIR_DECRYPT 1 +#define DIR_ENCRYPT 2 + +typedef unsigned char Block[8]; +typedef unsigned char *BlockT; +typedef struct { Block _; } Schedule[16]; + +#define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | key[4] | key[5] | key[6] | key[7]) + +#define SAMEKEY(k1, k2) (!memcmp((void *)k1, (void *)k2, sizeof(Block))) + +typedef struct { + short type; + int length; + unsigned char *data; +} Session_Key; + +#ifdef DEBUG +int printsub(char, unsigned char *, size_t); +#endif + +void encrypt_parse(kstream, unsigned char *, int); + +typedef struct { + char *name; + int type; + void (*output) (unsigned char *, int); + int (*input) (int); + void (*init) (int); + int (*start) (int, int); + int (*is) (unsigned char *, int); + int (*reply) (unsigned char *, int); + void (*session) (Session_Key *, int); + int (*keyid) (int, unsigned char *, int *); + void (*printsub) (unsigned char *, int, unsigned char *, int); +} Encryptions; + +#define SK_DES 1 /* Matched Kerberos v5 ENCTYPE_DES */ + +void encrypt_init (kstream, kstream_ptr); +Encryptions *findencryption (int); +void encrypt_auto (int); +void decrypt_auto (int); +void encrypt_is (unsigned char *, int); +void encrypt_reply (unsigned char *, int); +void encrypt_start_input (int); +void encrypt_session_key (Session_Key *, int); +void encrypt_end_input (void); +void encrypt_start_output (int); +void encrypt_end_output (void); +void encrypt_send_request_start (void); +void encrypt_send_request_end (void); +void encrypt_send_end (void); +void encrypt_wait (void); +int encrypt_is_encrypting (void); +void encrypt_send_support (void); +void encrypt_send_keyid (int, unsigned char *, int, int); +int net_write (unsigned char *, int); + +int encrypt_cmd (int, char **); +void encrypt_display (void); + +void krbdes_encrypt (unsigned char *, int); +int krbdes_decrypt (int); +int krbdes_is (unsigned char *, int); +int krbdes_reply (unsigned char *, int); +void krbdes_init (int); +int krbdes_start (int, int); +void krbdes_session (Session_Key *, int); +void krbdes_printsub (unsigned char *, int, unsigned char *, int); + +void cfb64_encrypt (unsigned char *, int); +int cfb64_decrypt (int); +void cfb64_init (int); +int cfb64_start (int, int); +int cfb64_is (unsigned char *, int); +int cfb64_reply (unsigned char *, int); +void cfb64_session (Session_Key *, int); +int cfb64_keyid (int, unsigned char *, int *); +void cfb64_printsub (unsigned char *, int, unsigned char *, int); + +void ofb64_encrypt (unsigned char *, int); +int ofb64_decrypt (int); +void ofb64_init (int); +int ofb64_start (int, int); +int ofb64_is (unsigned char *, int); +int ofb64_reply (unsigned char *, int); +void ofb64_session (Session_Key *, int); +int ofb64_keyid (int, unsigned char *, int *); +void ofb64_printsub (unsigned char *, int, unsigned char *, int); + +int KRB5_CALLCONV + des_new_random_key (Block); +void KRB5_CALLCONV + des_set_random_generator_seed (Block); +void KRB5_CALLCONV + des_key_sched (Block, Schedule); +void KRB5_CALLCONV + des_ecb_encrypt (Block, Block, Schedule, int); + +/* int des_string_to_key (char *, Block); */ + + +#ifdef DEBUG +extern int encrypt_debug_mode; +#endif + +extern int (*decrypt_input) (int); +extern void (*encrypt_output) (unsigned char *, int); + +int decrypt_ks_hack(unsigned char *, int); + +#endif /* __ENCRYPTION__ */ + +#endif /* ENCRYPTION */ diff --git a/krb5-1-6/src/windows/wintel/font.c b/krb5-1-6/src/windows/wintel/font.c new file mode 100644 index 000000000..d2858cd10 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/font.c @@ -0,0 +1,100 @@ +/* font.c */ + +#include <windows.h> +#include <commdlg.h> +#include <assert.h> +#include "screen.h" +#include "ini.h" + +void ProcessFontChange( + HWND hWnd) +{ + static DWORD dwFontColor; /* Color of font if one has been selected */ + CHOOSEFONT cf; + HDC hDC; + SCREEN *pScr; + TEXTMETRIC tm; + char buf[16]; + char szStyle[LF_FACESIZE]; + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert(pScr != NULL); + + cf.lStructSize = sizeof(cf); + cf.hwndOwner = hWnd; + cf.lpLogFont = (LPLOGFONT) &(pScr->lf); + cf.lpszStyle = szStyle; + cf.Flags = CF_INITTOLOGFONTSTRUCT; /* | CF_USESTYLE; */ + cf.Flags |= CF_SCREENFONTS; +#if 0 + cf.Flags |= CF_ANSIONLY; +#endif + cf.Flags |= CF_FORCEFONTEXIST; + cf.Flags |= CF_FIXEDPITCHONLY; + cf.Flags |= CF_NOSIMULATIONS; + + if (ChooseFont(&cf)) { + if (pScr->hSelectedFont) + DeleteObject(pScr->hSelectedFont); + + pScr->hSelectedFont = CreateFontIndirect(&(pScr->lf)); + pScr->lf.lfUnderline = TRUE; + pScr->hSelectedULFont = CreateFontIndirect(&(pScr->lf)); + pScr->lf.lfUnderline = FALSE; + hDC = GetDC(hWnd); + SelectObject(hDC, pScr->hSelectedFont); + GetTextMetrics(hDC, &tm); + pScr->cxChar = tm.tmAveCharWidth; + pScr->cyChar = tm.tmHeight + tm.tmExternalLeading; + ReleaseDC(hWnd, hDC); + SetWindowPos(hWnd, NULL, 0, 0, pScr->cxChar * pScr->width + + FRAME_WIDTH, pScr->cyChar * pScr->height + + FRAME_HEIGHT, SWP_NOMOVE | SWP_NOZORDER); + + dwFontColor = RGB(255, 255, 255); + InvalidateRect(hWnd, NULL, TRUE); + } + + WritePrivateProfileString(INI_FONT, "FaceName", pScr->lf.lfFaceName, TELNET_INI); + wsprintf(buf, "%d", (int) pScr->lf.lfHeight); + WritePrivateProfileString(INI_FONT, "Height", buf, TELNET_INI); + wsprintf(buf, "%d", (int) pScr->lf.lfWidth); + WritePrivateProfileString(INI_FONT, "Width", buf, TELNET_INI); + wsprintf(buf, "%d", (int) pScr->lf.lfEscapement); + WritePrivateProfileString(INI_FONT, "Escapement", buf, TELNET_INI); + wsprintf(buf, "%d", (int) pScr->lf.lfCharSet); + WritePrivateProfileString(INI_FONT, "CharSet", buf, TELNET_INI); + wsprintf(buf, "%d", (int) pScr->lf.lfPitchAndFamily); + WritePrivateProfileString(INI_FONT, "PitchAndFamily", buf, TELNET_INI); + + return; + +} /* ProcessFontChange */ + + +void InitializeStruct( + WORD wCommDlgType, + LPSTR lpStruct, + HWND hWnd) +{ + LPCHOOSEFONT lpFontChunk; + + if (wCommDlgType == IDC_FONT) { + lpFontChunk = (LPCHOOSEFONT) lpStruct; + + lpFontChunk->lStructSize = sizeof(CHOOSEFONT); + lpFontChunk->hwndOwner = hWnd; + lpFontChunk->Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY + | CF_INITTOLOGFONTSTRUCT | CF_APPLY; + lpFontChunk->rgbColors = RGB(0, 0, 255); + lpFontChunk->lCustData = 0L; + lpFontChunk->lpfnHook = NULL; + lpFontChunk->lpTemplateName = NULL; + lpFontChunk->hInstance = NULL; + lpFontChunk->lpszStyle = NULL; + lpFontChunk->nFontType = SCREEN_FONTTYPE; + lpFontChunk->nSizeMin = 0; + lpFontChunk->nSizeMax = 0; + } + +} /* InitialiseStruct */ diff --git a/krb5-1-6/src/windows/wintel/genget.c b/krb5-1-6/src/windows/wintel/genget.c new file mode 100644 index 000000000..4e760d72e --- /dev/null +++ b/krb5-1-6/src/windows/wintel/genget.c @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* based on @(#)genget.c 8.1 (Berkeley) 6/4/93 */ + +#include <ctype.h> + +#define LOWER(x) (isupper(x) ? tolower(x) : (x)) +/* + * The prefix function returns 0 if *s1 is not a prefix + * of *s2. If *s1 exactly matches *s2, the negative of + * the length is returned. If *s1 is a prefix of *s2, + * the length of *s1 is returned. + */ + int +isprefix(s1, s2) + register char *s1, *s2; +{ + char *os1; + register char c1, c2; + + if (*s1 == '\0') + return(-1); + os1 = s1; + c1 = *s1; + c2 = *s2; + while (LOWER(c1) == LOWER(c2)) { + if (c1 == '\0') + break; + c1 = *++s1; + c2 = *++s2; + } + return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); +} + +static char *ambiguous; /* special return value for command routines */ + + char ** +genget(name, table, stlen) + char *name; /* name to match */ + char **table; /* name entry in table */ + int stlen; +{ + register char **c, **found; + register int n; + + if (name == 0) + return 0; + + found = 0; + for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { + if ((n = isprefix(name, *c)) == 0) + continue; + if (n < 0) /* exact match */ + return(c); + if (found) + return(&ambiguous); + found = c; + } + return(found); +} + +/* + * Function call version of Ambiguous() + */ + int +Ambiguous(s) + char *s; +{ + return((char **)s == &ambiguous); +} diff --git a/krb5-1-6/src/windows/wintel/ini.h b/krb5-1-6/src/windows/wintel/ini.h new file mode 100644 index 000000000..f26c162e3 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/ini.h @@ -0,0 +1,16 @@ +/* Defines INI file vocabulary */ +#define TELNET_INI "kerberos.ini" + +#define INI_TELNET "Telnet" +#define INI_FONT "Font" +#define INI_WIDTH "Width" +#define INI_HEIGHT "Height" +#define INI_POSITION "Position" +#define INI_BACKSPACE "Backspace" +#define INI_BACKSPACE_BS "BS" +#define INI_BACKSPACE_DEL "DEL" + +#define INI_HOSTS "Telnet Hosts" +#define INI_HOST "Host" +#define INI_HOST_BS "BS" +#define INI_HOST_DEL "DEL" diff --git a/krb5-1-6/src/windows/wintel/intern.c b/krb5-1-6/src/windows/wintel/intern.c new file mode 100644 index 000000000..0cdd5537d --- /dev/null +++ b/krb5-1-6/src/windows/wintel/intern.c @@ -0,0 +1,815 @@ +/* intern.c */ + +#include <windows.h> +#include <string.h> +#include <assert.h> +#include "screen.h" + +#define ScreenClearAttrib 0 + +SCREENLINE * +GetScreenLineFromY(SCREEN *pScr, int y) +{ + SCREENLINE *pScrLine; + int idx; + + pScrLine = pScr->screen_top; + for (idx = 0; idx < pScr->height; idx++) { + if (idx == y) + return(pScrLine); + if (pScrLine == NULL) + return(NULL); + pScrLine = pScrLine->next; + } + + return(NULL); +} + + +SCREENLINE * +ScreenClearLine(SCREEN *pScr, SCREENLINE *pScrLine) +{ + memset(pScrLine->attrib, ScreenClearAttrib, pScr->width); + memset(pScrLine->text, ' ', pScr->width); + return(pScrLine); +} + + +void +ScreenUnscroll(SCREEN *pScr) +{ + int idx; + SCREENLINE *pScrLine; + + if (pScr->screen_bottom == pScr->buffer_bottom) + return; + + pScr->screen_bottom = pScr->buffer_bottom; + pScrLine = pScr->screen_bottom; + for (idx = 1; idx < pScr->height; idx++) { + if (pScrLine == NULL) + return; + pScrLine = pScrLine->prev; + } + pScr->screen_top = pScrLine; +} + + +void +ScreenCursorOn(SCREEN *pScr) +{ + int y; + int nlines; + + if (pScr->screen_bottom != pScr->buffer_bottom) + nlines = pScr->numlines - GetScrollPos(pScr->hWnd, SB_VERT); + else + nlines = 0; + + y = pScr->y + nlines; + SetCaretPos(pScr->x * pScr->cxChar, (y+1) * pScr->cyChar); + ShowCaret(pScr->hWnd); +} + + +void +ScreenCursorOff(SCREEN *pScr) +{ + HideCaret(pScr->hWnd); +} + + +void +ScreenELO(SCREEN *pScr, int s) +{ + SCREENLINE *pScrLine; + RECT rc; + + if (s < 0) + s = pScr->y; + + pScrLine = GetScreenLineFromY(pScr,s); + memset(pScrLine->attrib, ScreenClearAttrib, pScr->width); + memset(pScrLine->text, ' ', pScr->width); + rc.left = 0; + rc.right = pScr->width * pScr->cxChar; + rc.top = pScr->cyChar * s; + rc.bottom = pScr->cyChar * (s+1); + InvalidateRect(pScr->hWnd, &rc, TRUE); +} + +void +ScreenEraseScreen(SCREEN *pScr) +{ + int i; + int x1 = 0; + int y1 = 0; + int x2 = pScr->width; + int y2 = pScr->height; + int n = -1; + + for(i = 0; i < pScr->height; i++) + ScreenELO(pScr,i); + + InvalidateRect(pScr->hWnd, NULL, TRUE); + UpdateWindow(pScr->hWnd); +} + + +void +ScreenTabClear(SCREEN *pScr) +{ + int x = 0; + + while(x <= pScr->width) { + pScr->tabs[x] = ' '; + x++; + } +} + + +void +ScreenTabInit(SCREEN *pScr) +{ + int x = 0; + + ScreenTabClear(pScr); + + while(x <= pScr->width) { + pScr->tabs[x] = 'x'; + x += 8; + } + pScr->tabs[pScr->width] = 'x'; +} + + +void +ScreenReset(SCREEN *pScr) +{ + pScr->top = 0; + pScr->bottom = pScr->height-1; + pScr->parmptr = 0; + pScr->escflg = 0; + pScr->DECAWM = 1; + pScr->bWrapPending = FALSE; + pScr->DECCKM = 0; + pScr->DECPAM = 0; + /* pScr->DECORG = 0; */ + /* pScr->Pattrib = -1; */ + pScr->IRM = 0; + pScr->attrib = 0; + pScr->x = 0; + pScr->y = 0; + /* pScr->charset = 0; */ + ScreenEraseScreen(pScr); + ScreenTabInit(pScr); +#if 0 + /* + * QAK - 7/27/90: added because resetting the virtual screen's + * wrapping flag doesn't reset telnet window's wrapping + */ + set_vtwrap(pScrn, pScr->DECAWM); +#endif +} + + +void +ScreenListMove(SCREENLINE *TD, SCREENLINE *BD, SCREENLINE *TI, SCREENLINE *BI) +{ + if (TD->prev != NULL) + TD->prev->next = BD->next; /* Maintain circularity */ + + if (BD->next != NULL) + BD->next->prev = TD->prev; + + TD->prev = TI; /* Place the node in its new home */ + BD->next = BI; + + if (TI != NULL) + TI->next = TD; /* Ditto prev->prev */ + + if (BI != NULL) + BI->prev = BD; +} + + +void +ScreenDelLines(SCREEN *pScr, int n, int s) +{ + SCREENLINE *BI; + SCREENLINE *TI; + SCREENLINE *TD; + SCREENLINE *BD; + SCREENLINE *pLine; + int idx; + RECT rc; + HDC hDC; + + pScr->bWrapPending = FALSE; + + if (s < 0) + s = pScr->y; + + if (s + n - 1 > pScr->bottom) + n = pScr->bottom - s + 1; + + TD = GetScreenLineFromY(pScr, s); + BD = GetScreenLineFromY(pScr, s + n - 1); + TI = GetScreenLineFromY(pScr, pScr->bottom); + BI = TI->next; + + /* + * Adjust the top of the screen and buffer if they will move. + */ + if (TD == pScr->screen_top) { + if (pScr->screen_top == pScr->buffer_top) + pScr->buffer_top = BD->next; + pScr->screen_top = BD->next; + } + + /* + * Adjust the bottom of the screen and buffer if they will move. + */ + if (TI == pScr->screen_bottom) { + if (pScr->screen_bottom == pScr->buffer_bottom) + pScr->buffer_bottom = BD; + pScr->screen_bottom = BD; + } + + if (TI != BD) + ScreenListMove(TD, BD, TI, BI); + + /* + * Clear the lines moved from the deleted area to the + * bottom of the scrolling area. + */ + pLine = TI; + + for (idx = 0; idx < n; idx++) { + pLine = pLine->next; + ScreenClearLine(pScr, pLine); + } + + /* CheckScreen(pScr); */ + + /* + * Scroll the affected area on the screen. + */ + rc.left = 0; + rc.right = pScr->width * pScr->cxChar; + rc.top = s * pScr->cyChar; + rc.bottom = (pScr->bottom + 1) * pScr->cyChar; + + hDC = GetDC(pScr->hWnd); + + ScrollDC(hDC, 0, -pScr->cyChar * n, &rc, &rc, NULL, NULL); + + PatBlt(hDC, 0, (pScr->bottom - n + 1) * pScr->cyChar, + pScr->width * pScr->cxChar, n * pScr->cyChar, WHITENESS); + + ReleaseDC(pScr->hWnd, hDC); +} + + +void +ScreenInsertLine(SCREEN *pScr, int s) +{ + ScreenInsLines(pScr, 1, s); +} + + +void +ScreenInsLines(SCREEN *pScr, int n, int s) +{ + SCREENLINE *TI; + SCREENLINE *BI; + SCREENLINE *TD; + SCREENLINE *BD; + SCREENLINE *pLine; + int idx; + RECT rc; + HDC hDC; + + pScr->bWrapPending = FALSE; + + if (s < 0) + s = pScr->y; + + if (s + n - 1 > pScr->bottom) + n = pScr->bottom - s + 1; + + /* + * Determine the top and bottom of the insert area. Also determine + * the top and bottom of the area to be deleted and moved to the + * insert area. + */ + BI = GetScreenLineFromY(pScr, s); + TI = BI->prev; + TD = GetScreenLineFromY(pScr, pScr->bottom - n + 1); + BD = GetScreenLineFromY(pScr, pScr->bottom); + + /* + * Adjust the top of the screen and buffer if they will move. + */ + if (BI == pScr->screen_top) { + if (pScr->screen_top == pScr->buffer_top) + pScr->buffer_top = TD; + pScr->screen_top = TD; + } + + /* + * Adjust the bottom of the screen and buffer if they will move. + */ + if (BD == pScr->screen_bottom) { + if (pScr->screen_bottom == pScr->buffer_bottom) + pScr->buffer_bottom = TD->prev; + pScr->screen_bottom = TD->prev; + } + + /* + * Move lines from the bottom of the scrolling region to the insert area. + */ + if (TD != BI) + ScreenListMove(TD,BD,TI,BI); + + /* + * Clear the inserted lines + */ + pLine = GetScreenLineFromY(pScr, s); + + for (idx = 0; idx < n; idx++) { + ScreenClearLine(pScr, pLine); + pLine = pLine->next; + } + + /* CheckScreen(pScr); */ + + /* + * Scroll the affected area on the screen. + */ + rc.left = 0; + rc.right = pScr->width * pScr->cxChar; + rc.top = s * pScr->cyChar; + rc.bottom = (pScr->bottom + 1) * pScr->cyChar; + + hDC = GetDC(pScr->hWnd); + + ScrollDC(hDC, 0, pScr->cyChar * n, &rc, &rc, NULL, NULL); + + PatBlt(hDC, 0, s * pScr->cyChar, + pScr->width * pScr->cxChar, n * pScr->cyChar, WHITENESS); + + ReleaseDC(pScr->hWnd, hDC); +} + + +void +ScreenIndex(SCREEN * pScr) +{ + if (pScr->y >= pScr->bottom) + ScreenScroll(pScr); + else + pScr->y++; + + pScr->bWrapPending = FALSE; +} + + +void +ScreenWrapNow(SCREEN *pScr, int *xp, int *yp) +{ + if (pScr->bWrapPending && pScr->x >= pScr->width - 1) { + pScr->x = 0; + ScreenIndex(pScr); + } + + pScr->bWrapPending = FALSE; + + *xp = pScr->x; + *yp = pScr->y; +} + + +void +ScreenEraseToEOL(SCREEN *pScr) +{ + int x1 = pScr->x; + int y1 = pScr->y; + int x2 = pScr->width; + int y2 = pScr->y; + int n = -1; + SCREENLINE *pScrLine; + RECT rc; + + ScreenWrapNow(pScr, &x1, &y1); + + y2 = y1; +#if 0 + wsprintf(strTmp,"[EraseEOL:%d]",y2); + OutputDebugString(strTmp); +#endif + pScrLine = GetScreenLineFromY(pScr,y2); + memset(&pScrLine->attrib[x1], ScreenClearAttrib, pScr->width-x1+1); + memset(&pScrLine->text[x1], ' ', pScr->width - x1 + 1); + rc.left = x1 * pScr->cxChar; + rc.right = pScr->width * pScr->cxChar; + rc.top = pScr->cyChar * y1; + rc.bottom = pScr->cyChar * (y1 + 1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + UpdateWindow(pScr->hWnd); +} + + +void +ScreenDelChars(SCREEN *pScr, int n) +{ + int x = pScr->x; + int y = pScr->y; + int width; + SCREENLINE *pScrLine; + RECT rc; + + pScr->bWrapPending = FALSE; + + pScrLine = GetScreenLineFromY(pScr, y); + + width = pScr->width - x - n; + + if (width > 0) { + memmove(&pScrLine->attrib[x], &pScrLine->attrib[x + n], width); + memmove(&pScrLine->text[x], &pScrLine->text[x + n], width); + } + + memset(&pScrLine->attrib[pScr->width - n], ScreenClearAttrib, n); + memset(&pScrLine->text[pScr->width - n], ' ', n); + + rc.left = x * pScr->cxChar; + rc.right = pScr->width * pScr->cxChar; + rc.top = pScr->cyChar * y; + rc.bottom = pScr->cyChar * (y + 1); + + InvalidateRect(pScr->hWnd, &rc, TRUE); + + UpdateWindow(pScr->hWnd); +} + + +void +ScreenRevIndex(SCREEN *pScr) +{ + SCREENLINE *pScrLine; + SCREENLINE *pTopLine; + + pScr->bWrapPending = FALSE; + pScrLine = GetScreenLineFromY(pScr, pScr->y); + pTopLine = GetScreenLineFromY(pScr, pScr->top); + + if(pScrLine == pTopLine) + ScreenInsertLine(pScr, pScr->y); + else + pScr->y--; +} + + +void +ScreenEraseToBOL(SCREEN *pScr) +{ + int x1 = 0; + int y1 = pScr->y; + int x2 = pScr->x; + int y2 = pScr->y; + int n = -1; + SCREENLINE *pScrLine; + + pScrLine = GetScreenLineFromY(pScr, pScr->y); + + ScreenWrapNow(pScr, &x2, &y1); + y2 = y1; + memset(pScrLine->attrib, ScreenClearAttrib, x2); + memset(pScrLine->text, ' ', x2); +} + + +void +ScreenEraseLine(SCREEN *pScr, int s) +{ + int x1 = 0; + int y1 = s; + int x2 = pScr->width; + int y2 = s; + int n = -1; + SCREENLINE *pScrLine; + RECT rc; + + if (s < 0) { + ScreenWrapNow(pScr, &x1, &y1); + s = y2 = y1; + x1 = 0; + } + + pScrLine = GetScreenLineFromY(pScr,y1); + memset(pScrLine->attrib, ScreenClearAttrib, pScr->width); + memset(pScrLine->text, ' ', pScr->width); + rc.left = 0; + rc.right = pScr->width * pScr->cxChar; + rc.top = pScr->cyChar * y1; + rc.bottom = pScr->cyChar * (y1+1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); +} + + +void +ScreenEraseToEndOfScreen(SCREEN *pScr) +{ + int i; + int x1 = 0; + int y1 = pScr->y+1; + int x2 = pScr->width; + int y2 = pScr->height; + int n = -1; + + ScreenWrapNow(pScr, &x1, &y1); + y1++; + x1 = 0; + i = y1; + ScreenEraseToEOL(pScr); + while (i < pScr->height) { + ScreenELO(pScr, i); + ScreenEraseLine(pScr, i); + i++; + } +} + + +void +ScreenRange(SCREEN *pScr) +{ + if (pScr->x < 0) + pScr->x = 0; + + if (pScr->x >= pScr->width) + pScr->x = pScr->width - 1; + + if (pScr->y < 0) + pScr->y = 0; + + if (pScr->y >= pScr->height) + pScr->y = pScr->height - 1; +} + + +void +ScreenAlign(SCREEN *pScr) /* vt100 alignment, fill screen with 'E's */ +{ + char *tt; + int i; + int j; + SCREENLINE *pScrLine; + + pScrLine = GetScreenLineFromY(pScr, pScr->top); + ScreenEraseScreen(pScr); + + for(j = 0; j < pScr->height; j++) { + tt = &pScrLine->text[0]; + for(i = 0; i <= pScr->width; i++) + *tt++ = 'E'; + pScrLine = pScrLine->next; + } +} + + +void +ScreenApClear(SCREEN *pScr) +{ + /* + * reset all the ANSI parameters back to the default state + */ + for(pScr->parmptr=5; pScr->parmptr>=0; pScr->parmptr--) + pScr->parms[pScr->parmptr] = -1; + + pScr->parmptr = 0; +} + + +void +ScreenSetOption(SCREEN *pScr, int toggle) +{ + if (pScr->parms[0] == -2 && pScr->parms[1] == 1) + pScr->DECCKM = toggle; + +#if 0 + switch(pScr->parms[0]) { + + case -2: /* Set on the '?' char */ + switch(pScr->parms[1]) { + + case 1: /* set/reset cursor key mode */ + pScr->DECCKM = toggle; + break; + +#ifdef NOT_SUPPORTED + case 2: /* set/reset ANSI/vt52 mode */ + break; +#endif + + case 3: /* set/reset column mode */ + pScr->x = pScr->y = 0; /* Clear the screen, mama! */ + ScreenEraseScreen(pScr); +#if 0 /* removed for variable screen size */ + if (toggle) /* 132 column mode */ + pScr->width = pScr->allwidth; + else + pScr->width = 79; +#endif + break; + +#ifdef NOT_SUPPORTED + case 4: /* set/reset scrolling mode */ + case 5: /* set/reset screen mode */ + case 6: /* set/rest origin mode */ + pScr->DECORG = toggle; + break; +#endif + + case 7: /* set/reset wrap mode */ + pScr->DECAWM = toggle; +#if 0 + /* + * QAK - 7/27/90: added because resetting the virtual screen's + * wrapping flag doesn't reset telnet window's wrapping + */ + set_vtwrap(pScrn, fpScr->DECAWM); +#endif + break; + +#ifdef NOT_SUPPORTED + case 8: /* set/reset autorepeat mode */ + case 9: /* set/reset interlace mode */ + break; +#endif + + default: + break; + } /* end switch */ + break; + + case 4: + pScr->IRM=toggle; + break; + + default: + break; + + } /* end switch */ +#endif +} + + +#ifdef NOT_SUPPORTED +void +ScreenTab(SCREEN *pScr) +{ + if (pScr->x> = pScr->width) + pScr->x = pScr->width; + pScr->x++; + while (pScr->tabs[fpScr->x] != 'x' && pScr->x < pScr->width) + pScr->x++; +} +#endif + + +BOOL +ScreenInsChar(SCREEN *pScr, int x) +{ + int i; + SCREENLINE *pScrLine; + RECT rc; + + pScrLine = GetScreenLineFromY(pScr, pScr->y); + if (pScrLine == NULL) + return(FALSE); + + for(i = pScr->width - x; i >= pScr->x; i--) { + pScrLine->text[x+i] = pScrLine->text[i]; + pScrLine->attrib[x+i] = pScrLine->attrib[i]; + } + + memset(&pScrLine->attrib[pScr->x], ScreenClearAttrib, x); + memset(&pScrLine->text[pScr->x], ' ', x); + rc.left = pScr->cxChar * x; + rc.right = pScr->cxChar * (x + pScr->x); + rc.top = pScr->cyChar * (pScr->y - 1); + rc.bottom = pScr->cyChar * pScr->y; + InvalidateRect(pScr->hWnd, &rc, TRUE); + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); + return(TRUE); +} + + +void +ScreenSaveCursor(SCREEN *pScr) +{ + pScr->Px = pScr->x; + pScr->Py = pScr->y; + pScr->Pattrib = pScr->attrib; +} + + +void +ScreenRestoreCursor(SCREEN *pScr) +{ + pScr->x = pScr->Px; + pScr->y = pScr->Py; + ScreenRange(pScr); +} + + +void +ScreenDraw(SCREEN *pScr, int x, int y, int a, int len, char *c) +{ + int idx; + SCREENLINE *pScrLine; + RECT rc; + + pScrLine = GetScreenLineFromY(pScr, y); + assert(pScrLine != NULL); + + for(idx = x; idx < x + len; idx++) { + pScrLine->text[idx] = c[idx - x]; + pScrLine->attrib[idx - x] = a; + } + + rc.left = pScr->cxChar * x; + rc.right = pScr->cxChar * (x + len); + rc.top = pScr->cyChar * pScr->y; + rc.bottom = pScr->cyChar * (pScr->y + 1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + SendMessage(pScr->hWnd, WM_PAINT, 0, 0); +} + + +#if ! defined(NDEBUG) + +BOOL +CheckScreen(SCREEN *pScr) +{ + SCREENLINE *pLinePrev; + SCREENLINE *pLine; + int nscreen = 0; + int nbuffer = 0; + int topline = 0; + char buf[512]; + BOOL bBottom; + BOOL bOK; + + pLine = pScr->buffer_top; + + if (pLine == NULL) { + OutputDebugString("CheckScreen: buffer_top invalid"); + MessageBox(NULL, "buffer_top invalid", "CheckScreen", MB_OK); + return(FALSE); + } + + bBottom = FALSE; + while (TRUE) { + pLinePrev = pLine; + if (nscreen > 0 || pLine == pScr->screen_top) + if (!bBottom) + nscreen++; + nbuffer++; + if (pLine == pScr->screen_top) + topline = nbuffer - 1; + if (pLine == pScr->screen_bottom) + bBottom = TRUE; + pLine = pLine->next; + if (pLine == NULL) + break; + if (pLine->prev != pLinePrev) { + wsprintf(buf, + "Previous ptr of line %d does not match next ptr of line %d", + nbuffer, nbuffer - 1); + OutputDebugString(buf); + MessageBox(NULL, buf, "CheckScreen", MB_OK); + } + } + + if (pLinePrev == pScr->buffer_bottom && nscreen == pScr->height) + bOK = TRUE; + else { + OutputDebugString("CheckScreen: Invalid number of lines on screen"); + bOK = FALSE; + } + + wsprintf(buf, "screen.width = %d\nscreen.height = %d\nscreen.maxlines = %d\nscreen.numlines = %d\nscreen.x = %d\nscreen.y = %d\nscreen.top = %d\nscreen.bottom = %d\nActual top line = %d\nActual buffer lines = %d\nActual screen lines = %d\nBottom of buffer is %s", + pScr->width, pScr->height, pScr->maxlines, pScr->numlines, + pScr->x, pScr->y, pScr->top, pScr->bottom, + topline, nbuffer, nscreen, + (pLinePrev == pScr->buffer_bottom) ? "valid" : "invalid"); + + MessageBox(NULL, buf, "CheckScreen", MB_OK); + + return(bOK); +} + +#endif diff --git a/krb5-1-6/src/windows/wintel/k5stream.c b/krb5-1-6/src/windows/wintel/k5stream.c new file mode 100644 index 000000000..a31538518 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/k5stream.c @@ -0,0 +1,119 @@ +/* + * + * K5stream + * + * Emulates the kstream package in Kerberos 4 + * + */ + +#include <stdio.h> +#include <io.h> +#include <malloc.h> +#include "telnet.h" +#include "k5stream.h" +#include "auth.h" + +int +kstream_destroy(kstream ks) +{ + if (ks != NULL) { + auth_destroy(ks); /* Destroy authorizing */ + + closesocket(ks->fd); /* Close the socket??? */ + free(ks); + } + return 0; +} + +void +kstream_set_buffer_mode(kstream ks, int mode) +{ +} + + +kstream +kstream_create_from_fd(int fd, + const struct kstream_crypt_ctl_block *ctl, + kstream_ptr data) +{ + kstream ks; + int n; + BOOL on = 1; + + ks = malloc(sizeof(struct kstream_int)); + if (ks == NULL) + return NULL; + + ks->fd = fd; + + setsockopt(ks->fd, SOL_SOCKET, SO_OOBINLINE, (const char *)&on, sizeof(on)); + + n = auth_init(ks, data); /* Initialize authorizing */ + if (n) { + free(ks); + return NULL; + } + + ks->encrypt = NULL; + ks->decrypt = NULL; + + return ks; +} + +int +kstream_write(kstream ks, void *p_data, size_t p_len) +{ + int n; + struct kstream_data_block i; + +#ifdef DEBUG + hexdump("plaintext:", p_data, p_len); +#endif + + if (ks->encrypt) { + i.ptr = p_data; + i.length = p_len; + ks->encrypt(&i, NULL, NULL); +#ifdef DEBUG + hexdump("cyphertext:", p_data, p_len); +#endif + } + + n = send(ks->fd, p_data, p_len, 0); /* Write the data */ + + return n; /* higher layer does retries */ +} + + +int +kstream_read(kstream ks, void *p_data, size_t p_len) +{ + int n; + struct kstream_data_block i; + + n = recv(ks->fd, p_data, p_len, 0); /* read the data */ + + if (n < 0) + return n; + +#ifdef DEBUG + hexdump("input data:", p_data, n); +#endif + + if (ks->decrypt) { + extern int encrypt_flag; + + if (encrypt_flag == 2) + encrypt_flag = 1; + + i.ptr = p_data; + i.length = n; + ks->decrypt(&i, NULL, NULL); +#ifdef DEBUG + hexdump("decrypted data:", p_data, n); +#endif + } + + return n; /* higher layer does retries */ +} + diff --git a/krb5-1-6/src/windows/wintel/k5stream.h b/krb5-1-6/src/windows/wintel/k5stream.h new file mode 100644 index 000000000..3a63ca1d8 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/k5stream.h @@ -0,0 +1,57 @@ +/* Header file for encrypted-stream library. + * Written by Ken Raeburn (Raeburn@Cygnus.COM). + * Copyright (C) 1991, 1992, 1994 by Cygnus Support. + * + * 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. + * Cygnus Support makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef K5STREAM_H +#define K5STREAM_H + +typedef struct kstream_int { /* Object we pass around */ + int fd; /* Open socket descriptor */ + int (*encrypt)(struct kstream_data_block *, /* output */ + struct kstream_data_block *, /* input */ + struct kstream *kstream); + int (*decrypt)(struct kstream_data_block *, /* output */ + struct kstream_data_block *, /* input */ + struct kstream *kstream); +} *kstream; + +typedef void *kstream_ptr; /* Data send on the kstream */ + +struct kstream_data_block { + kstream_ptr ptr; + size_t length; +}; + +struct kstream_crypt_ctl_block { + int (*encrypt)(struct kstream_data_block *, /* output */ + struct kstream_data_block *, /* input */ + kstream); + int (*decrypt)(struct kstream_data_block *, /* output */ + struct kstream_data_block *, /* input */ + kstream); + int (*init)(kstream, kstream_ptr); + void (*destroy)(kstream); +}; + + +/* Prototypes */ + +int kstream_destroy(kstream); +void kstream_set_buffer_mode(kstream, int); +kstream kstream_create_from_fd(int fd, + const struct kstream_crypt_ctl_block *, + kstream_ptr); +int kstream_write(kstream, void *, size_t); +int kstream_read(kstream, void *, size_t); + +#endif /* K5STREAM_H */ diff --git a/krb5-1-6/src/windows/wintel/ktelnet.doc b/krb5-1-6/src/windows/wintel/ktelnet.doc new file mode 100644 index 0000000000000000000000000000000000000000..64e4f452697bdd664faa1be51e115c9506bf784a GIT binary patch literal 16384 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 Ycp}u;e@5B}^l_zsi(h;8@Y|&S2Q5ZA<p2Nx literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/wintel/ktelnet.hlp b/krb5-1-6/src/windows/wintel/ktelnet.hlp new file mode 100644 index 0000000000000000000000000000000000000000..e44cebfe574db2e6254ed0e249edcfd70b10f3eb GIT binary patch literal 9204 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 DM|puD literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/wintel/ktelnet.hpj b/krb5-1-6/src/windows/wintel/ktelnet.hpj new file mode 100644 index 000000000..d69185cd8 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/ktelnet.hpj @@ -0,0 +1,92 @@ +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; Help Project File for KTELNET +; +; This file is maintained by RoboHELP. Do not modify this file directly. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[OPTIONS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Options section contains the following information: +; +; The optional BMROOT= entry sets the directories in which the Help Compiler +; will look for graphics. +; +; The CONTENTS= tells WinHelp which topic contains the contents. +; +; The TITLE= is displayed in the Title Bar of WINHELP.EXE +; +; The BUILD= setting allows you to create different Help systems from +; the same source file. +; +; The COMPRESS= option tells the Help Compiler how much to compress +; the Help file. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +;BMROOT=C:\WINDOWS\DESKTOP\KERBEROS 5\WIN95 GUI\CNS HELP +TITLE=Kerb*Net Telnet for Windows +BUILD=WINDOWS +NOTES=1 + + +OLDKEYPHRASE=NO +OPTCDROM=0 +REPORT=YES +COMPRESS=12 +ERRORLOG=C:\windows\desktop\kerberos 5\win95 gui\cns help\KTELNET.ERR +[BUILDTAGS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Build Tags section specifies to the Help Compiler the names +; of all the valid build tags used in this Help project. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +WINDOWS + + +[CONFIG] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Config section defines macros which will run at startup. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + + + +[FILES] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Files section specifies the RTF files for a project. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +KTELNET.RTF +[ALIAS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Alias section sets up aliases for Topic IDs in your Help system. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[MAP] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Map section specifies the project HH files. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[BITMAPS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Bitmaps section specifies the referenced bitmaps used in +; your help system. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[WINDOWS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Windows section contains all of the information about the windows +; in a Help project. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +;Gloss = "Glossary",(100,100,350,350),0,(255,255,255),(255,255,255) +main=,,29188,, +(w95sec)=,,20740,(r14745599),(r14745599),f2 + + +[BAGGAGE] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Baggage section specifies any additional files. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + diff --git a/krb5-1-6/src/windows/wintel/ncsa.ico b/krb5-1-6/src/windows/wintel/ncsa.ico new file mode 100644 index 0000000000000000000000000000000000000000..8a6cb6a564b581cb96115998f13bc864e432c31b GIT binary patch literal 766 zcmZvaF?NJ73`B=)-h<Am(n6VAY>u=yh;Oi0;wULox(h|#bN<M%u$u_RwyYV+GDscI zG`-07^(4JAzkvz7gHF$kQYQAl%@VKXxlN2L!K|D!ff}!B^$PHKi=iaO)d(GJF!yLf z(UD)2q;yD7?C*jPvhN<Nn(q==drYvX9uxGn*xwDh{jFdbS~wcWgL_M^XP-IMMvpeL zG}I;JRCVv(4*DOzlxq!sqp46Z@<m$Hk-A><Rcc=E(CwJ+Q{0Ru>SgnYAiu8n9ZV0a z&xtwr!?h>X?@f++@89)ZiqEj=TY|jPW94q{>_!iM{1RsfBS^WSpC#k;xq?C`&@T<? a2OjIuVE+t8xJE)}Jm%=&7(yfTQTP|72n06( literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/wintel/negotiat.c b/krb5-1-6/src/windows/wintel/negotiat.c new file mode 100644 index 000000000..685092df5 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/negotiat.c @@ -0,0 +1,865 @@ +/* + * negotiat.c + * + * Telnet option negotiation functions + * + +/* + * Includes + */ + +/* #define USETEK */ +/* #define USERAS */ + +#ifdef DEBUG /* define this to print the raw network data to debuging monitor */ +#define NEGOTIATEDEBUG +#endif + +#if 0 +#define PRINT_EVERYTHING /* talk a lot */ +#endif + +#include <time.h> +#include "telnet.h" +#include "telnet_arpa.h" +#include "auth.h" +#include "encrypt.h" + +#define STNORM 0 +#define NEGOTIATE 1 +#define ESCFOUND 5 +#define IACFOUND 6 + +unsigned char parsedat[256]; + +/* Local functions */ +static void parse_subnegotiat(kstream ks,int end_sub); + +/* Local variables */ +static char *telstates[]={ + "EOF", + "Suspend Process", + "Abort Process", + "Unknown (239)", + "Subnegotiation End", + "NOP", + "Data Mark", + "Break", + "Interrupt Process", + "Abort Output", + "Are You There", + "Erase Character", + "Erase Line", + "Go Ahead", + "Subnegotiate", + "Will", + "Won't", + "Do", + "Don't" +}; + +static char *teloptions[256]={ /* ascii strings for Telnet options */ + "Binary", /* 0 */ + "Echo", + "Reconnection", + "Supress Go Ahead", + "Message Size Negotiation", + "Status", /* 5 */ + "Timing Mark", + "Remote Controlled Trans and Echo", + "Output Line Width", + "Output Page Size", + "Output Carriage-Return Disposition", /* 10 */ + "Output Horizontal Tab Stops", + "Output Horizontal Tab Disposition", + "Output Formfeed Disposition", + "Output Vertical Tabstops", + "Output Vertical Tab Disposition", /* 15 */ + "Output Linefeed Disposition", + "Extended ASCII", + "Logout", + "Byte Macro", + "Data Entry Terminal", /* 20 */ + "SUPDUP", + "SUPDUP Output", + "Send Location", + "Terminal Type", + "End of Record", /* 25 */ + "TACACS User Identification", + "Output Marking", + "Terminal Location Number", + "3270 Regime", + "X.3 PAD", /* 30 */ + "Negotiate About Window Size", + "Terminal Speed", + "Toggle Flow Control", + "Linemode", + "X Display Location", /* 35 */ + "Environment", + "Authentication", + "Data Encryption", + "39", + "40","41","42","43","44","45","46","47","48","49", + "50","51","52","53","54","55","56","57","58","59", + "60","61","62","63","64","65","66","67","68","69", + "70","71","72","73","74","75","76","77","78","79", + "80","81","82","83","84","85","86","87","88","89", + "90","91","92","93","94","95","96","97","98","99", + "100","101","102","103","104","105","106","107","108","109", + "110","111","112","113","114","115","116","117","118","119", + "120","121","122","123","124","125","126","127","128","129", + "130","131","132","133","134","135","136","137","138","139", + "140","141","142","143","144","145","146","147","148","149", + "150","151","152","153","154","155","156","157","158","159", + "160","161","162","163","164","165","166","167","168","169", + "170","171","172","173","174","175","176","177","178","179", + "180","181","182","183","184","185","186","187","188","189", + "190","191","192","193","194","195","196","197","198","199", + "200","201","202","203","204","205","206","207","208","209", + "210","211","212","213","214","215","216","217","218","219", + "220","221","222","223","224","225","226","227","228","229", + "230","231","232","233","234","235","236","237","238","239", + "240","241","242","243","244","245","246","247","248","249", + "250","251","252","253","254", + "Extended Options List" /* 255 */ +}; + +static char *LMoptions[]={ /* ascii strings for Linemode sub-options */ + "None", "MODE", "FORWARDMASK", "SLC" +}; + +static char *ModeOptions[]={ /* ascii strings for Linemode edit options */ + "None", "EDIT", "TRAPSIG", "ACK", "SOFT TAB", "LIT ECHO" +}; + +static char *SLCoptions[]={ /* ascii strings for Linemode SLC characters */ + "None", "SYNCH", "BREAK", "IP", "ABORT OUTPUT", + "AYT", "EOR", "ABORT", "EOF", "SUSP", + "EC", "EL", "EW", "RP", "LNEXT", + "XON", "XOFF", "FORW1", "FORW2", "MCL", + "MCR", "MCWL", "MCWR", "MCBOL", "MCEOL", + "INSRT", "OVER", "ECR", "EWR", "EBOL", + "EEOL" +}; + +static char *SLCflags[]={ /* ascii strings for Linemode SLC flags */ + "SLC_NOSUPPORT", "SLC_CANTCHANGE", "SLC_VALUE", "SLC_DEFAULT" +}; + +/* Linemode default character for each function */ +static unsigned char LMdefaults[NTELOPTS + 1]={ + (unsigned char)-1, /* zero isn't used */ + (unsigned char)-1, /* we don't support SYNCH */ + 3, /* ^C is default for BRK */ + 3, /* ^C is default for IP */ + 15, /* ^O is default for AO */ + 25, /* ^Y is default for AYT */ /* 5 */ + (unsigned char)-1, /* we don't support EOR */ + 3, /* ^C is default for ABORT */ + 4, /* ^D is default for EOF */ + 26, /* ^Z is default for SUSP */ + 8, /* ^H is default for EC */ /* 10 */ + 21, /* ^U is default for EL */ + 23, /* ^W is default for EW */ + 18, /* ^R is default for RP */ + 22, /* ^V is default for LNEXT */ + 17, /* ^Q is default for XON */ /* 15 */ + 19, /* ^S is default for XOFF */ + 22, /* ^V is default for FORW1 */ + 5, /* ^E is default for FORW2 */ + (unsigned char)-1, /* we don't support MCL */ + (unsigned char)-1, /* we don't support MCR */ /* 20 */ + (unsigned char)-1, /* we don't support MCWL */ + (unsigned char)-1, /* we don't support MCWR */ + (unsigned char)-1, /* we don't support MCBOL */ + (unsigned char)-1, /* we don't support MCEOL */ + (unsigned char)-1, /* we don't support INSRT */ /* 25 */ + (unsigned char)-1, /* we don't support OVER */ + (unsigned char)-1, /* we don't support ECR */ + (unsigned char)-1, /* we don't support EWR */ + (unsigned char)-1, /* we don't support EBOL */ + (unsigned char)-1 /* we don't support EEOL */ /* 30 */ +}; + + +/* + * Function : start_negotiation() + * Purpose : Send the initial negotiations on the network and print + * the negotitations to the console screen. + * Parameters : + * dat - the port number to write to + * cvs - the console's virtual screen + * Returns : none + * Calls : tprintf(), netprintf() + * Called by : dosessions() + */ +void +start_negotiation(kstream ks) +{ + char buf[128]; + + /* Send the initial telnet negotiations */ +#ifdef ENCRYPTION /* XXX */ + if (encrypt_flag) + wsprintf(buf,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", + IAC, WILL, TELOPT_AUTHENTICATION, + IAC, WILL, TELOPT_ENCRYPT, + IAC, DO, TELOPT_SGA, + IAC, DO, TELOPT_ECHO, + IAC, WILL, TELOPT_NAWS + ); + else +#endif + wsprintf(buf,"%c%c%c%c%c%c%c%c%c%c%c%c", + IAC, WILL, TELOPT_AUTHENTICATION, + IAC, DO, TELOPT_SGA, + IAC, DO, TELOPT_ECHO, + IAC, WILL, TELOPT_NAWS + ); + TelnetSend(ks,buf,lstrlen(buf),0); + +#ifdef NOT + /* check whether we are going to be output mapping */ + if(tw->mapoutput) { + netprintf(tw->pnum,"%c%c%c",IAC,DO,TELOPT_BINARY); + /* set the flag indicating we wanted server to start transmitting binary */ + tw->uwantbinary=1; + netprintf(tw->pnum,"%c%c%c",IAC,WILL,TELOPT_BINARY); + /* set the flag indicating we want to start transmitting binary */ + tw->iwantbinary=1; + } /* end if */ +#endif + + /* Print to the console what we just did */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n",telstates[DO - TELCMD_FIRST], + teloptions[TELOPT_ECHO]); + OutputDebugString(strTmp); + wsprintf(strTmp,"SEND: %s %s\r\n",telstates[DO - TELCMD_FIRST], + teloptions[TELOPT_SGA]); + OutputDebugString(strTmp); + wsprintf(strTmp,"SEND: %s %s\r\n",telstates[WILL - TELCMD_FIRST], + teloptions[TELOPT_NAWS]); + OutputDebugString(strTmp); + +#ifdef NOT + tprintf(cvs,"SEND: %s %s\r\n",telstates[DO - TELCMD_FIRST], + teloptions[BINARY]); + tprintf(cvs,"SEND: %s %s\r\n",telstates[WILL - TELCMD_FIRST], + teloptions[BINARY]); +#endif +#endif +} /* end start_negotiation() */ + +/* + * parse + * Do the telnet negotiation parsing. + * + * look at the string which has just come in from outside and + * check for special sequences that we are interested in. + * + * Tries to pass through routine strings immediately, waiting for special + * characters ESC and IAC to change modes. + */ +void +parse(CONNECTION *con,unsigned char *st,int cnt) +{ + static int sub_pos; /* the position we are in the subnegotiation parsing */ + static int end_sub; /* index of last byte in parsedat in a subnegotiation */ + unsigned char *mark, *orig; + char buf[256]; + kstream ks; + + ks = con->ks; + +#ifdef PRINT_EVERYTHING + hexdump("Options to process:", st, cnt); +#endif /* PRINT_EVERYTHING */ + + orig = st; /* remember beginning point */ + mark = st + cnt; /* set to end of input string */ + +#ifdef HUH + netpush(tw->pnum); +#endif + + /* + * traverse string, looking for any special characters which indicate that + * we need to change modes. + */ + while(st < mark) { + + while(con->telstate != STNORM && st < mark) { + switch(con->telstate) { + case IACFOUND: /* telnet option negotiation */ + if(*st == IAC) { /* real data=255 */ + st++; /* real 255 will get sent */ + con->telstate = STNORM; + break; + } /* end if */ + + if(*st > 239) { + con->telstate = *st++; /* by what the option is */ + break; + } /* end if */ + +#ifdef NEGOTIATEDEBUG + wsprintf(buf, "\r\n strange telnet option"); + OutputDebugString(buf); +#endif + orig=++st; + con->telstate=STNORM; + break; + + case EL: /* received a telnet erase line command */ + case EC: /* received a telnet erase character command */ + case AYT: /* received a telnet Are-You-There command */ + case AO: /* received a telnet Abort Output command */ + case IP: /* received a telnet Interrupt Process command */ + case BREAK: /* received a telnet Break command */ + case DM: /* received a telnet Data Mark command */ + case NOP: /* received a telnet No Operation command */ + case SE: /* received a telnet Subnegotiation End command */ + case ABORT: /* received a telnet Abort Process command */ + case SUSP: /* received a telnet Suspend Process command */ + case xEOF: /* received a telnet EOF command */ +#ifdef NEGOTIATEDEBUG + wsprintf(buf,"RECV: %s\r\n", + telstates[con->telstate-TELCMD_FIRST]); + OutputDebugString(buf); +#endif + con->telstate=STNORM; + orig=++st; + break; + + case GA: /* telnet go ahead option*/ +#ifdef NEGOTIATEDEBUG + wsprintf(buf,"RECV: %s\r\n", + telstates[con->telstate-TELCMD_FIRST]); + OutputDebugString(buf); +#endif + con->telstate=STNORM; + orig=++st; + break; + + case DO: /* received a telnet DO negotiation */ +#ifdef NEGOTIATEDEBUG + wsprintf(buf,"RECV: %s %s\r\n", + telstates[con->telstate-TELCMD_FIRST],teloptions[*st]); + OutputDebugString(buf); +#endif + switch(*st) { +#ifdef NOT + case TELOPT_BINARY: /* DO: binary transmission */ + if(!tw->ibinary) { /* binary */ + if(!tw->iwantbinary) { + netprintf(tw->pnum,"%c%c%c", + IAC,WILL,BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[BINARY]); + } /* end if */ + else + tw->iwantbinary=0; /* turn off this now */ + tw->ibinary=1; + } /* end if */ + else { + if(tw->condebug>0) + tprintf(cv,"NO REPLY NEEDED: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[BINARY]); + } /* end else */ + break; +#endif + + case TELOPT_SGA: /* DO: Suppress go-ahead */ + if(!con->igoahead) { /* suppress go-ahead */ + wsprintf(buf,"%c%c%c",IAC,WILL,TELOPT_SGA); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[TELOPT_SGA]); + OutputDebugString(strTmp); + OutputDebugString("igoahead"); +#endif + con->igoahead=1; + } /* end if */ + else { +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp, + "NO REPLY NEEDED: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[TELOPT_SGA]); + OutputDebugString(strTmp); +#endif + } /* end else */ + break; + + case TELOPT_TTYPE: /* DO: terminal type negotiation */ + if(!con->termsent) { + con->termsent=TRUE; + wsprintf(buf,"%c%c%c",IAC,WILL,TELOPT_TTYPE); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[TELOPT_TTYPE]); + OutputDebugString(strTmp); +#endif + } /* end if */ + else { +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"NO REPLY NEEDED: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[TELOPT_TTYPE]); + OutputDebugString(strTmp); +#endif + } /* end else */ + break; + +#ifdef LATER + case TELOPT_LINEMODE: /* DO: linemode negotiation */ + tw->lmflag=1; /* set the linemode flag */ + netprintf(tw->pnum,"%c%c%c",IAC,WILL,TELOPT_LINEMODE); + /* + * Tell the other side to send us + * its default character set + */ + netprintf(tw->pnum,"%c%c%c%c", + IAC,SB,TELOPT_LINEMODE,SLC,0,SLC_DEFAULT,0,IAC,SE); + if(tw->condebug>0) { + tprintf(cv,"SEND: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[TELOPT_LINEMODE]); + tprintf(cv, + "SEND: SB LINEMODE SLC 0 SLC_DEFAULT 0 IAC SE\r\n"); + } /* end if */ + break; +#endif + case TELOPT_NAWS: /* DO: Negotiate About Window Size */ + con->bResizeable=TRUE; + send_naws(con); + break; + + case TELOPT_AUTHENTICATION: /* DO: Authentication requested */ + wsprintf(buf, "%c%c%c", IAC, WILL, TELOPT_AUTHENTICATION); + TelnetSend(ks, buf, lstrlen(buf), 0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[WILL - TELCMD_FIRST], + teloptions[TELOPT_AUTHENTICATION]); + OutputDebugString(strTmp); +#endif + break; + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: /* DO: Remote is willing to receive encrypted */ + wsprintf(buf, "%c%c%c", IAC, + (encrypt_flag ? WILL : WONT), TELOPT_ENCRYPT); + TelnetSend(ks, buf, lstrlen(buf), 0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[(encrypt_flag ? WILL : WONT) + - TELCMD_FIRST], + teloptions[TELOPT_ENCRYPT]); + OutputDebugString(strTmp); +#endif + break; +#endif /* ENCRYPTION */ + + default: /* DO: */ + wsprintf(buf, "%c%c%c", IAC, WONT, *st); + TelnetSend(ks, buf, lstrlen(buf), 0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[WONT - TELCMD_FIRST], teloptions[*st]); + OutputDebugString(strTmp); +#endif + break; + + } /* end switch */ + con->telstate = STNORM; + orig = ++st; + break; + + case DONT: /* Received a telnet DONT option */ + switch (*st) { + case TELOPT_NAWS: + con->bResizeable=FALSE; +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"RECV: %s %s\r\n", + telstates[con->telstate-TELCMD_FIRST],teloptions[*st]); + OutputDebugString(strTmp); +#endif + break; + +#ifdef NOT + case BINARY: /* DONT: check for binary neg. */ + if(tw->ibinary) { /* binary */ + if(!tw->iwantbinary) { + netprintf(tw->pnum,"%c%c%c",IAC,WONT,BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %s %s\r\n", + telstates[WONT-TELCMD_FIRST], + teloptions[BINARY]); + } /* end if */ + else + tw->iwantbinary=0; /* turn off this now */ + tw->ibinary=0; + tw->mapoutput=0; /* turn output mapping off */ + } /* end if */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"NO REPLY NEEDED: %s %s\r\n", + telstates[WONT-TELCMD_FIRST], + teloptions[BINARY]); + OutputDebugString(strTmp); +#endif + break; +#endif +#ifdef ENCRYPTION + case ENCRYPTION: + break; +#endif + } + + /* all these just fall through to here... */ + + con->telstate=STNORM; + orig=++st; + break; + + case WILL: /* received a telnet WILL option */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"RECV: %s %s\r\n", + telstates[con->telstate-TELCMD_FIRST], + teloptions[*st]); + OutputDebugString(strTmp); +#endif + switch(*st) { +#ifdef NOT + case TELOPT_BINARY: /* WILL: binary */ + if(!tw->ubinary) { /* binary */ + if(!tw->uwantbinary) { + netprintf(tw->pnum,"%c%c%c", + IAC,DO,TELOPT_BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %s %s\r\n", + telstates[DO - TELCMD_FIRST], + teloptions[TELOPT_BINARY]); + } /* end if */ + else + tw->uwantbinary=0; /* turn off this now */ + tw->ubinary=1; + } /* end if */ + else { + if(tw->condebug>0) + tprintf(cv,"NO REPLY NEEDED: %s %s\r\n", + telstates[DO - TELCMD_FIRST], + teloptions[TELOPT_BINARY]); + } /* end else */ + break; +#endif + + case TELOPT_SGA: /* WILL: suppress go-ahead */ + if(!con->ugoahead) { + con->ugoahead=1; + wsprintf(buf,"%c%c%c",IAC,DO,TELOPT_SGA); /* ack */ + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[DO - TELCMD_FIRST], + teloptions[TELOPT_SGA]); + OutputDebugString(strTmp); +#endif + } /* end if */ + break; + + case TELOPT_ECHO: /* WILL: echo */ + if(!con->echo) { + con->echo = 1; + wsprintf(buf, "%c%c%c", IAC, DO, TELOPT_ECHO); /* ack */ + TelnetSend(ks, buf, lstrlen(buf), 0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[DO - TELCMD_FIRST], + teloptions[TELOPT_ECHO]); + OutputDebugString(strTmp); +#endif + } /* end if */ + break; + + case TELOPT_TM: /* WILL: Timing mark */ + con->timing=0; + break; +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: /* WILL: decrypt our input */ + wsprintf(buf, "%c%c%c", IAC, + (encrypt_flag ? DO : DONT), TELOPT_ENCRYPT); + TelnetSend(ks, buf, lstrlen(buf), 0); + if (encrypt_flag) + encrypt_send_support(); + +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[(encrypt_flag ? DO : DONT) - TELCMD_FIRST], + teloptions[TELOPT_ENCRYPT]); + OutputDebugString(strTmp); +#endif + break; +#endif + + default: + wsprintf(buf,"%c%c%c",IAC,DONT,*st); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[DONT-TELCMD_FIRST],teloptions[*st]); + OutputDebugString(strTmp); +#endif + break; + } /* end switch */ + con->telstate=STNORM; + orig=++st; + break; + + case WONT: /* Received a telnet WONT option */ +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"RECV: %s %s\r\n", + telstates[con->telstate-TELCMD_FIRST],teloptions[*st]); + OutputDebugString((LPSTR)strTmp); +#endif + con->telstate=STNORM; + switch(*st++) { /* which option? */ +#ifdef NOT + case BINARY: /* WONT: binary */ + if(tw->ubinary) { /* binary */ + if(!tw->uwantbinary) { + netprintf(tw->pnum,"%c%c%c", + IAC,DONT,BINARY); + if(tw->condebug>0) + tprintf(cv,"SEND: %s %s\r\n", + telstates[DONT-TELCMD_FIRST], + teloptions[BINARY]); + } /* end if */ + else + tw->uwantbinary=0; /* turn off this now */ + tw->ubinary=0; + tw->mapoutput=0; /* turn output mapping off */ + } /* end if */ + else { + if(tw->condebug>0) + tprintf(cv,"NO REPLY NEEDED: %s %s\r\n", + telstates[DONT-TELCMD_FIRST], + teloptions[BINARY]); + } /* end else */ + break; + +#endif + case TELOPT_ECHO: /* WONT: echo */ + if(con->echo) { + con->echo=0; + wsprintf(buf,"%c%c%c",IAC,DONT,TELOPT_ECHO); + TelnetSend(ks,buf,lstrlen(buf),0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SEND: %s %s\r\n", + telstates[DONT-TELCMD_FIRST], + teloptions[TELOPT_ECHO]); + OutputDebugString(strTmp); + OutputDebugString("Other side won't echo!"); +#endif + } /* end if */ + break; + + case TELOPT_TM: /* WONT: Telnet timing mark option */ + con->timing=0; + break; + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: /* WONT: don't encrypt our input */ + break; +#endif + + default: + break; + } /* end switch */ + orig=st; + break; + + case SB: /* telnet sub-options negotiation */ + con->telstate=NEGOTIATE; + orig=st; + end_sub=0; + sub_pos=con->substate=0; /* Defined for each */ +#ifdef OLD_WAY + break; +#endif + + case NEGOTIATE: + /* until we change sub-negotiation states, accumulate bytes */ + if(con->substate==0) { + if(*st==IAC) { /* check if we found an IAC byte */ + if(*(st+1)==IAC) { /* skip over double IAC's */ + st++; + parsedat[sub_pos++]=*st++; + } /* end if */ + else { + end_sub=sub_pos; + con->substate=*st++; + } /* end else */ + } /* end if */ + else /* otherwise, just stash the byte */ + parsedat[sub_pos++]=*st++; + } /* end if */ + else { + con->substate=*st++; + /* check if we've really ended the sub-negotiations */ + if(con->substate==SE) + parse_subnegotiat(ks,end_sub); + + orig=st; + /* + * XXX hack to decrypt the rest of the buffer + */ + if (encrypt_flag == 2) { + decrypt_ks_hack(orig, mark - orig); + encrypt_flag = 1; + } + + con->telstate=STNORM; + } /* end else */ + break; + + default: + con->telstate=STNORM; + break; + } /* end switch */ + } /* end while */ + + /* + * quick scan of the remaining string, skip chars while they are + * uninteresting + */ + if(con->telstate==STNORM && st<mark) { + /* + * skip along as fast as possible until an interesting character is found + */ + while(st<mark && *st!=27 && *st!=IAC) { +#if 0 + if(!tw->ubinary) + *st&=127; /* mask off high bit */ +#endif + st++; + } /* end while */ +#if 0 + if(!tw->timing) + parsewrite(tw,orig,st-orig); +#endif + orig=st; /* forget what we have sent already */ + if(st<mark) + switch(*st) { + case IAC: /* telnet IAC */ + con->telstate=IACFOUND; + st++; + break; + + default: +#ifdef NEGOTIATEDEBUG + wsprintf(buf," strange char>128 0x%x\r\n", *st); + OutputDebugString(buf); +#endif + st++; + break; + } /* end switch */ + } /* end if */ + } /* end while */ +} /* end parse() */ + +/* + * Function : parse_subnegotiat() + * Purpose : Parse the telnet sub-negotiations read into the parsedat + * array. + * Parameters : + * end_sub - index of the character in the 'parsedat' array which + * is the last byte in a sub-negotiation + * Returns : none + * Calls : + * Called by : parse() + */ +static void +parse_subnegotiat(kstream ks, int end_sub) +{ + char buf[128]; + + switch(parsedat[0]) { + case TELOPT_TTYPE: + if(parsedat[1]==1) { + /* QAK!!! */ wsprintf(buf,"%c%c%c%cvt100%c%c",IAC,SB,TELOPT_TTYPE, + 0,IAC,SE); + TelnetSend(ks,(LPSTR)buf,11,0); +#ifdef NEGOTIATEDEBUG + wsprintf(strTmp,"SB TERMINAL-TYPE SEND\r\n" + "SEND: SB TERMINAL-TYPE IS vt100 \r\n len=%d \r\n", + lstrlen((LPSTR)buf)); + OutputDebugString(strTmp); +#endif + } + break; + + case TELOPT_AUTHENTICATION: + auth_parse(ks, parsedat, end_sub); + break; +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + if (encrypt_flag) + encrypt_parse(ks, parsedat, end_sub); + break; +#endif + default: + break; + } /* end switch */ +} /* parse_subnegotiat */ + + +/* + * Function : send_naws + * Purpose : Send a window size sub-negotiation. + * Parameters : + * ks - the kstream to send to. + * Returns : none + */ +void +send_naws(CONNECTION *con) +{ + unsigned char buf[40]; + int len; + + wsprintf(buf, "%c%c%c", IAC, SB, TELOPT_NAWS); + len = 3; + + buf[len++] = HIBYTE(con->width); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = LOBYTE(con->width); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = HIBYTE(con->height); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = LOBYTE(con->height); + if (buf[len-1] == IAC) buf[len++] = IAC; + + buf[len++] = IAC; + buf[len++] = SE; + + TelnetSend(con->ks, buf, len, 0); + +#ifdef NEGOTIATEDEBUG + wsprintf(buf, "SEND: SB NAWS %d %d %d %d IAC SE\r\n", + HIBYTE(con->width), LOBYTE(con->width), + HIBYTE(con->height), LOBYTE(con->height)); + OutputDebugString(buf); +#endif + +} /* send_naws */ diff --git a/krb5-1-6/src/windows/wintel/resource.h b/krb5-1-6/src/windows/wintel/resource.h new file mode 100644 index 000000000..0d39d5ca0 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by telnet.rc +// +#define IDD_DIALOG1 101 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40005 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/krb5-1-6/src/windows/wintel/screen.c b/krb5-1-6/src/windows/wintel/screen.c new file mode 100644 index 000000000..206c97c89 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/screen.c @@ -0,0 +1,1147 @@ +/* screen.c */ + +#include <windows.h> +#include <commdlg.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "telnet.h" +#include "ini.h" +#include "auth.h" + +extern char *encrypt_output; /* XXX hack... I wonder if this will work. These are */ +extern char *decrypt_input; /* XXX really functions... */ + +extern char *cInvertedArray; +extern int bMouseDown; +extern int bSelection; + +static SCREEN *ScreenList; +static HINSTANCE hInst; +static char szScreenClass[] = "ScreenWClass"; +static char szScreenMenu[] = "ScreenMenu"; +static char cursor_key[8][4] = { /* Send for cursor keys */ + "\x1B[D", "\x1B[A", "\x1B[C", "\x1B[B", /* Normal mode */ + "\x1BOD", "\x1BOA", "\x1BOC", "\x1BOB", /* Numpad on mode */ +}; + +void +ScreenInit(HINSTANCE hInstance) +{ + BOOL b; + WNDCLASS wc; + + hInst = hInstance; + + ScreenList = NULL; + + wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; /* Class style(s) */ + wc.lpfnWndProc = ScreenWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(long); + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance, "TERMINAL"); + wc.hCursor = LoadCursor(NULL, IDC_IBEAM); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = szScreenMenu; + wc.lpszClassName = szScreenClass; + + b = RegisterClass(&wc); + assert(b); +} + + +void +SetScreenInstance(HINSTANCE hInstance) +{ + hInst = hInstance; +} + +int +GetNewScreen(void) +{ + SCREEN *pScr; + static int id = 0; + + pScr = (SCREEN *) calloc(sizeof(SCREEN), 1); + if (pScr == NULL) + return(-1); + + if (ScreenList == NULL) { + pScr->next = NULL; + pScr->prev = NULL; + } + else { + if (ScreenList->next == NULL) { + ScreenList->next = ScreenList; + ScreenList->prev = ScreenList; + } + pScr->next = ScreenList; + pScr->prev = ScreenList->prev; + ScreenList->prev->next = pScr; + ScreenList->prev = pScr; + } + + ScreenList = pScr; + return(id++); +} + +SCREENLINE * +ScreenNewLine(void) +{ + SCREENLINE *pScrLine; + + pScrLine = calloc(sizeof(SCREENLINE) + 2*MAX_LINE_WIDTH, 1); + if (pScrLine == NULL) + return (NULL); + pScrLine->text = &pScrLine->buffer[0]; + pScrLine->attrib = &pScrLine->buffer[MAX_LINE_WIDTH]; + return(pScrLine); +} + +static void +MakeWindowTitle(char *host, int width, int height, char *title, int nchars) +{ + char buf[128]; + int hlen; + + hlen = strlen(host); + + title[0] = 0; + + if (hlen + 1 > nchars) + return; + + strcpy(title, host); + + wsprintf(buf, " (%dh x %dw)", height, width); + + if ((int) strlen(buf) + hlen + 1 > nchars) + return; + + strcat(title, buf); +} + + +SCREEN * +InitNewScreen(CONFIG *Config) +{ + TEXTMETRIC tm; + HMENU hMenu = NULL; + SCREEN *scr = NULL; + SCREENLINE *pScrLine; + SCREENLINE *pScrLineLast; + int id; + int idx = 0; + char title[128]; + HDC hDC; + HFONT hFont; + + id = GetNewScreen(); + if (id == -1) + return(0); + + scr = ScreenList; + assert(scr != NULL); + + hMenu = LoadMenu(hInst, szScreenMenu); + assert(hMenu != NULL); + + scr->title = Config->title; + MakeWindowTitle(Config->title, Config->width, Config->height, + title, sizeof(title)); + + scr->hwndTel = Config->hwndTel; /* save HWND of calling window */ + + if (Config->backspace) { + CheckMenuItem(hMenu, IDM_BACKSPACE, MF_CHECKED); + CheckMenuItem(hMenu, IDM_DELETE, MF_UNCHECKED); + } else { + CheckMenuItem(hMenu, IDM_BACKSPACE, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_DELETE, MF_CHECKED); + } + + hDC = GetDC(NULL); + assert(hDC != NULL); + + scr->lf.lfPitchAndFamily = FIXED_PITCH; + GetPrivateProfileString(INI_FONT, "FaceName", "Courier", scr->lf. + lfFaceName, LF_FACESIZE, TELNET_INI); + scr->lf.lfHeight = (int) GetPrivateProfileInt(INI_FONT, "Height", 0, TELNET_INI); + scr->lf.lfWidth = (int) GetPrivateProfileInt(INI_FONT, "Width", 0, TELNET_INI); + scr->lf.lfPitchAndFamily = (BYTE) GetPrivateProfileInt(INI_FONT, "PitchAndFamily", 0, TELNET_INI); + scr->lf.lfCharSet = (BYTE) GetPrivateProfileInt(INI_FONT, "CharSet", 0, TELNET_INI); + scr->lf.lfEscapement = (BYTE) GetPrivateProfileInt(INI_FONT, "Escapement", 0, TELNET_INI); + scr->lf.lfQuality = PROOF_QUALITY; + scr->hSelectedFont = CreateFontIndirect((LPLOGFONT) &(scr->lf)); + hFont = SelectObject(hDC, scr->hSelectedFont); + GetTextMetrics(hDC, (LPTEXTMETRIC) &tm); + SelectObject(hDC, hFont); + scr->cxChar = tm.tmAveCharWidth; + scr->cyChar = tm.tmHeight + tm.tmExternalLeading; + + ReleaseDC(NULL, hDC); + + scr->width = Config->width; + scr->height = Config->height; + scr->ID = id; + scr->x = 0; + scr->y = 0; + scr->Oldx = 0; + scr->Oldy = 0; + scr->attrib = 0; + scr->DECAWM = 1; + scr->bWrapPending = FALSE; + scr->top = 0; + scr->bottom = scr->height-1; + scr->parmptr = 0; + scr->escflg = 0; + scr->bAlert = FALSE; + scr->numlines = 0; + scr->maxlines = 150; + + cInvertedArray = calloc(scr->width * scr->height, 1); + + pScrLineLast = ScreenNewLine(); + if (pScrLineLast == NULL) + return(NULL); + scr->screen_top = scr->buffer_top = pScrLineLast; + + for (idx = 0; idx < scr->height - 1; idx++) { + pScrLine = ScreenNewLine(); + if (pScrLine == NULL) + return(NULL); + pScrLine->prev = pScrLineLast; + pScrLineLast->next = pScrLine; + pScrLineLast = pScrLine; + } + + scr->screen_bottom = scr->buffer_bottom = pScrLine; + + scr->hWnd = CreateWindow(szScreenClass, title, WS_OVERLAPPEDWINDOW | WS_VSCROLL, + CW_USEDEFAULT, CW_USEDEFAULT, + scr->cxChar * scr->width + FRAME_WIDTH, + scr->cyChar * scr->height + FRAME_HEIGHT, + NULL, hMenu, hInst, scr); + assert(scr->hWnd != NULL); + + ShowWindow(scr->hWnd, SW_SHOW); + + CreateCaret(scr->hWnd, NULL, scr->cxChar, 2); + SetCaretPos(scr->x*scr->cxChar, (scr->y+1) * scr->cyChar); + ShowCaret(scr->hWnd); + + return(ScreenList); +} + + +void DeleteTopLine( + SCREEN *pScr) +{ + assert(pScr->buffer_top != NULL); + + pScr->buffer_top = pScr->buffer_top->next; + assert(pScr->buffer_top != NULL); + + free(pScr->buffer_top->prev); + pScr->buffer_top->prev = NULL; + + pScr->numlines--; + +} /* DeleteTopLine */ + + +static void SetScreenScrollBar( + SCREEN *pScr) +{ + if (pScr->numlines <= 0) { + SetScrollRange(pScr->hWnd, SB_VERT, 0, 100, FALSE); + SetScrollPos(pScr->hWnd, SB_VERT, 0, TRUE); + EnableScrollBar(pScr->hWnd, SB_VERT, ESB_DISABLE_BOTH); + } + else { + SetScrollRange(pScr->hWnd, SB_VERT, 0, pScr->numlines, FALSE); + SetScrollPos(pScr->hWnd, SB_VERT, pScr->numlines, TRUE); + EnableScrollBar(pScr->hWnd, SB_VERT, ESB_ENABLE_BOTH); + } + +} /* SetScreenScrollBar */ + + +int ScreenScroll( + SCREEN *pScr) +{ + SCREENLINE *pScrLine; + SCREENLINE *pPrev; + SCREENLINE *pNext; + SCREENLINE *pScrollTop; + SCREENLINE *pScrollBottom; + BOOL bFullScreen = TRUE; + HDC hDC; + RECT rc; + + Edit_ClearSelection(pScr); + + pScrollTop = GetScreenLineFromY(pScr, pScr->top); + + pScrollBottom = GetScreenLineFromY(pScr, pScr->bottom); + + if (pScrollTop != pScr->screen_top) { + bFullScreen = FALSE; + rc.left = 0; + rc.right = pScr->cxChar * pScr->width; + rc.top = pScr->cyChar * (pScr->top); + rc.bottom = pScr->cyChar * (pScr->bottom+1); + + pNext = pScrollTop->next; + pPrev = pScrollTop->prev; + + pPrev->next = pNext; + pNext->prev = pPrev; + + pScrLine = pScrollTop; + ScreenClearLine(pScr, pScrLine); + } + else { + pScr->numlines++; + pScrLine = ScreenNewLine(); + if (pScrLine == NULL) + return(0); + pScr->screen_top = pScrollTop->next; + } + + if (pScrLine == NULL) + return(0); + + pNext = pScrollBottom->next; + pScrollBottom->next = pScrLine; + pScrLine->next = pNext; + pScrLine->prev = pScrollBottom; + if (pNext != NULL) + pNext->prev = pScrLine; + + if (pScrollBottom != pScr->screen_bottom) { + bFullScreen = FALSE; + rc.left = 0; + rc.right = pScr->cxChar * pScr->width; + rc.top = pScr->cyChar * pScr->top; + rc.bottom = pScr->cyChar * (pScr->bottom+1); + } + else { + if (pScr->screen_bottom == pScr->buffer_bottom) + pScr->buffer_bottom = pScrLine; + pScr->screen_bottom = pScrLine; + } + +#if 0 + CheckScreen(fpScr); +#endif + + pScr->y++; + + if (pScr->y > pScr->bottom) + pScr->y = pScr->bottom; + + hDC = GetDC(pScr->hWnd); + assert(hDC != NULL); + + if (bFullScreen) + ScrollDC(hDC, 0, -pScr->cyChar, NULL, NULL, NULL, NULL); + else + ScrollDC(hDC, 0, -pScr->cyChar, &rc, &rc, NULL, NULL); + + PatBlt(hDC, 0, pScr->bottom * pScr->cyChar, + pScr->width * pScr->cxChar, pScr->cyChar, WHITENESS); + + ReleaseDC(pScr->hWnd, hDC); + + if (pScr->numlines == pScr->maxlines) + DeleteTopLine(pScr); + else + SetScreenScrollBar(pScr); + + return(1); + +} /* ScreenScroll */ + + +int DrawTextScreen( + RECT rcInvalid, + SCREEN *pScr, + HDC hDC) +{ + SCREENLINE *pScrLineTmp; + SCREENLINE *pScrLine; + int x = 0; + int y = 0; + int left = 0; + int right = 0; + int i; + int len; + char attrib; +#define YPOS (y*pScr->cyChar) + + pScrLine = pScr->screen_top; + + for (y = 0; y < pScr->height; y++) { + if (!pScrLine) + continue; + + if (YPOS >= rcInvalid.top - pScr->cyChar && + YPOS <= rcInvalid.bottom + pScr->cyChar) { + + if (y < 0) + y = 0; + + if (y >= pScr->height) + y = pScr->height - 1; + + left = (rcInvalid.left / pScr->cxChar) - 1; + + right = (rcInvalid.right / pScr->cxChar) + 1; + + if (left < 0) + left = 0; + + if (right > pScr->width - 1) + right = pScr->width - 1; + + x = left; + + while (x <= right) { + if (!pScrLine->text[x]) { + x++; + continue; + } + + if (SCR_isrev(pScrLine->attrib[x])) { + SelectObject(hDC, pScr->hSelectedFont); + SetTextColor(hDC, RGB(255, 255, 255)); + SetBkColor(hDC, RGB(0, 0, 0)); + } + else if (SCR_isblnk(pScrLine->attrib[x])) { + SelectObject(hDC, pScr->hSelectedFont); + SetTextColor(hDC, RGB(255, 0, 0)); + SetBkColor(hDC, RGB(255, 255, 255)); + } + else if (SCR_isundl(pScrLine->attrib[x])) { + SetTextColor(hDC, RGB(255, 0, 0)); + SetBkColor(hDC, RGB(255, 255, 255)); + SelectObject(hDC, pScr->hSelectedULFont); + } + else { + SelectObject(hDC,pScr->hSelectedFont); + SetTextColor(hDC, RGB(0, 0, 0)); + SetBkColor(hDC, RGB(255, 255, 255)); + } + + len = 1; + attrib = pScrLine->attrib[x]; + for (i = x + 1; i <= right; i++) { + if (pScrLine->attrib[i] != attrib || !pScrLine->text[i]) + break; + len++; + } + + TextOut(hDC, x*pScr->cxChar, y*pScr->cyChar, &pScrLine->text[x], len); + x += len; + } + } + pScrLineTmp = pScrLine->next; + pScrLine = pScrLineTmp; + } + + return(0); + +} /* DrawTextScreen */ + + +static BOOL SetInternalScreenSize( + SCREEN *pScr, + int width, + int height) +{ + RECT rc; + char *p; + int idx; + int n; + int newlines; + SCREENLINE *pNewLine; + SCREENLINE *pTopLine; + SCREENLINE *pBottomLine; +#if 0 + int col; + int row; + int dydestbottom; +#endif + + GetClientRect(pScr->hWnd, &rc); + + width = (rc.right - rc.left) / pScr->cxChar; + height = (rc.bottom - rc.top) / pScr->cyChar; + + if (pScr->height == height && pScr->width == width) + return(FALSE); + + pScr->Oldx = 0; + pScr->Oldy = 0; + pScr->attrib = 0; + + /* + Reallocate the inverted array of bytes and copy the values + from the old screen to the new screen. + */ + p = calloc(width * height, 1); + + ScreenCursorOff(pScr); + +#if 0 /* Copy inversion array to desitination */ + for (col = 0; col < width; col++) { + for (row = 0; row < height; row++) { + dydestbottom = height - 1 - row; + if (col < pScr->width && dydestbottom < pScr->height - 1) + p[row * width + col] = + cInvertedArray[(pScr->height - 1 - dydestbottom) * pScr->width + col]; + } + } +#endif + + free(cInvertedArray); + cInvertedArray = p; + + /* + Append any new lines which need to be added to accomodate the new + screen size. + */ + pBottomLine = pScr->buffer_bottom; + newlines = height - (pScr->height + pScr->numlines); + + if (newlines > 0) { + pScr->y += pScr->numlines; + pScr->numlines = 0; + + for (idx = 0; idx < newlines; idx++) { + pNewLine = ScreenNewLine(); + if (pNewLine == NULL) + return(FALSE); + pNewLine->prev = pBottomLine; + if (pBottomLine == NULL) + return(FALSE); + pBottomLine->next = pNewLine; + pBottomLine = pNewLine; + } + } + + /* + If we already have plenty of lines, then we need to get rid of the + scrollback lines, if too many exist. The cursor should end up + the same distance from the bottom of the screen as is started out + in this instance. + */ + if (newlines < 0) { + pScr->y = (height - 1) - (pScr->bottom - pScr->y); + if (pScr->y < 0) + pScr->y = 0; + pScr->numlines = -newlines; + n = pScr->numlines - pScr->maxlines; + for (idx = 0; idx < n; idx++) + DeleteTopLine(pScr); + } + + /* + Calculate the position of the buffer relative to the screen. + */ + pScr->screen_bottom = pBottomLine; + pScr->buffer_bottom = pBottomLine; + + pTopLine = pBottomLine; + + for (idx = 1; idx < height; idx++) { + pTopLine = pTopLine->prev; + } + + pScr->screen_top = pTopLine; + pScr->width = width; + pScr->height = height; + pScr->top = 0; + pScr->bottom = height - 1; + + if (pScr->x >= width) + pScr->x = width - 1; + + if (pScr->y >= height) + pScr->y = height - 1; + + SetScreenScrollBar(pScr); + ScreenCursorOn(pScr); + return(TRUE); + +} /* SetInternalScreenSize */ + + +static int ScreenAdjustUp( + SCREEN *pScr, + int n) +{ + int idx; + SCREENLINE *pLine1; + SCREENLINE *pLine2; + + for (idx = 0; idx < n; idx++) { + if (pScr->screen_top == pScr->buffer_top) + return(-idx); + pLine1 = pScr->screen_top->prev; + if (pLine1 == NULL) + return(-idx); + pLine2 = pScr->screen_bottom->prev; + if (pLine2 == NULL) + return(-idx); + pScr->screen_top = pLine1; + pScr->screen_bottom = pLine2; + } + + return(idx); + +} /* ScreenAdjustUp */ + + +static int ScreenAdjustDown( + SCREEN *pScr, + int n) +{ + int idx; + SCREENLINE *pLine1; + SCREENLINE *pLine2; + + for (idx = 0; idx < n; idx++) { + if (pScr->screen_bottom == pScr->buffer_bottom) + return(-idx); + pLine1 = pScr->screen_top->next; + if (pLine1 == NULL) + return(-idx); + pLine2 = pScr->screen_bottom->next; + if (pLine2 == NULL) + return(-idx); + pScr->screen_top = pLine1; + pScr->screen_bottom = pLine2; + } + + return(idx); + +} /* ScreenAdjustDown */ + + +long PASCAL ScreenWndProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + MINMAXINFO *lpmmi; + SCREEN *pScr; + HMENU hMenu; + PAINTSTRUCT ps; + int x = 0; + int y = 0; + int ScrollPos; + int tmpScroll = 0; + int idx; + HDC hDC; + RECT rc; + char title[128]; + static int bDoubleClick = FALSE; + + switch (message) { + + case WM_COMMAND: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + + switch (wParam) { + + case IDM_EXIT: + if (MessageBox(hWnd, "Terminate this connection?", "Telnet", MB_OKCANCEL) == IDOK) { + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + SendMessage(pScr->hwndTel, WM_MYSCREENCLOSE, 0, (LPARAM) pScr); + } + break; + + case IDM_BACKSPACE: + hMenu = GetMenu(hWnd); + CheckMenuItem(hMenu, IDM_BACKSPACE, MF_CHECKED); + CheckMenuItem(hMenu, IDM_DELETE, MF_UNCHECKED); + SendMessage(pScr->hwndTel, WM_MYSCREENCHANGEBKSP, VK_BACK, (LPARAM) pScr); + break; + + case IDM_DELETE: + hMenu = GetMenu(hWnd); + CheckMenuItem(hMenu, IDM_BACKSPACE, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_DELETE, MF_CHECKED); + SendMessage(pScr->hwndTel, WM_MYSCREENCHANGEBKSP, 0x7f, (LPARAM) pScr); + break; + + case IDM_FONT: + ScreenCursorOff(pScr); + ProcessFontChange(hWnd); + ScreenCursorOn(pScr); + break; + + case IDM_COPY: + Edit_Copy(hWnd); + hMenu=GetMenu(hWnd); + Edit_ClearSelection(pScr); + break; + + case IDM_PASTE: + Edit_Paste(hWnd); + break; + + case IDM_HELP_INDEX: + WinHelp(hWnd, HELP_FILE, HELP_INDEX, 0); + break; + + case IDM_ABOUT: +#ifdef CYGNUS +#ifdef KRB4 + strcpy(strTmp, " Kerberos 4 for Windows\n"); +#endif +#ifdef KRB5 + strcpy(strTmp, " KerbNet for Windows\n"); +#endif + strcat(strTmp, "\n Version 1.00\n\n"); + strcat(strTmp, " For support, contact:\n"); + strcat(strTmp, " Cygnus Support - (415) 903-1400\n"); +#else /* CYGNUS */ + strcpy(strTmp, " Kerberos 5 Telnet for Windows\n"); + strcat(strTmp, " ALPHA SNAPSHOT 2\n\n"); +#endif /* CYGNUS */ + if (encrypt_flag) { + strcat(strTmp, "\n[Encryption of output requested. State: "); + strcat(strTmp, (encrypt_output ? "encrypting]" : "INACTIVE]")); + strcat(strTmp, "\n[Decryption of input requested. State: "); + strcat(strTmp, (decrypt_input ? "decrypting]\n" : "INACTIVE]\n")); + } + MessageBox(NULL, strTmp, "Kerberos", MB_OK); + break; + +#if defined(DEBUG) + case IDM_DEBUG: + CheckScreen(pScr); + break; +#endif + } + + break; + + case WM_NCCREATE: + pScr = (SCREEN *) ((LPCREATESTRUCT) lParam)->lpCreateParams; + pScr->hWnd = hWnd; + SetWindowLong(hWnd, SCREEN_HANDLE, (LONG) pScr); + SetScrollRange(hWnd, SB_VERT, 0, 100, FALSE); + SetScrollPos(hWnd, SB_VERT, 0, TRUE); + EnableScrollBar(hWnd, SB_VERT, ESB_DISABLE_BOTH); + return(TRUE); + + case WM_VSCROLL: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + + ScreenCursorOff(pScr); + + switch(wParam) { + + case SB_LINEDOWN: + if (ScreenAdjustDown(pScr, 1) <= 0) + break; + hDC = GetDC(hWnd); + assert(hDC != NULL); + rc.left = 0; + rc.right = pScr->cxChar * pScr->width; + rc.top = 0; + rc.bottom = pScr->cyChar * (pScr->bottom + 1); + ScrollDC(hDC, 0, -pScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.top = pScr->cyChar * pScr->bottom; + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos = GetScrollPos(hWnd, SB_VERT); + SetScrollPos(hWnd, SB_VERT, ScrollPos + 1, TRUE); + UpdateWindow(hWnd); + break; + + case SB_LINEUP: + if (ScreenAdjustUp(pScr, 1) <= 0) + break; + hDC = GetDC(hWnd); + assert(hDC != NULL); + rc.left = 0; + rc.right = pScr->cxChar * pScr->width; + rc.top = 0; + rc.bottom = pScr->cyChar * (pScr->bottom + 1); + ScrollDC(hDC, 0, pScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.bottom = pScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos = GetScrollPos(pScr->hWnd, SB_VERT); + SetScrollPos(hWnd,SB_VERT, ScrollPos - 1, TRUE); + UpdateWindow(hWnd); + break; + + case SB_PAGEDOWN: + idx = abs(ScreenAdjustDown(pScr, pScr->height)); + hDC = GetDC(hWnd); + assert(hDC != NULL); + rc.left = 0; + rc.right = pScr->cxChar * pScr->width; + rc.top = 0; + rc.bottom = pScr->cyChar * (pScr->bottom+1); + ScrollDC(hDC, 0, -idx * pScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.top = pScr->cyChar * (pScr->bottom - idx + 1); + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos=GetScrollPos(hWnd, SB_VERT); + SetScrollPos(hWnd, SB_VERT, ScrollPos + idx, TRUE); + break; + + case SB_PAGEUP: + idx = abs(ScreenAdjustUp(pScr, pScr->height)); + hDC = GetDC(hWnd); + assert(hDC != NULL); + rc.left = 0; + rc.right = pScr->cxChar * pScr->width; + rc.top = 0; + rc.bottom = pScr->cyChar * (pScr->bottom + 1); + ScrollDC(hDC, 0, idx * pScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + rc.bottom = idx * pScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + ScrollPos=GetScrollPos(hWnd, SB_VERT); + SetScrollPos(hWnd, SB_VERT, ScrollPos - idx, TRUE); + break; + + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + ScrollPos = GetScrollPos(hWnd, SB_VERT); + tmpScroll = ScrollPos - LOWORD(lParam); + if (tmpScroll == 0) + break; + if (tmpScroll > 0) + ScreenAdjustUp(pScr, tmpScroll); + else + ScreenAdjustDown(pScr, -tmpScroll); + if (abs(tmpScroll) < pScr->height) { + hDC = GetDC(hWnd); + assert(hDC != NULL); + rc.left = 0; + rc.right = pScr->cxChar * pScr->width; + rc.top = 0; + rc.bottom = pScr->cyChar * (pScr->bottom + 1); + ScrollDC(hDC, 0, tmpScroll * pScr->cyChar, &rc, &rc, NULL, NULL); + ReleaseDC(hWnd, hDC); + if (tmpScroll > 0) { + rc.bottom = tmpScroll * pScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + } + else { + rc.top = (pScr->bottom + tmpScroll + 1) * pScr->cyChar; + InvalidateRect(hWnd, &rc, TRUE); + } + } + else + InvalidateRect(hWnd, NULL, TRUE); + + SetScrollPos(hWnd, SB_VERT, LOWORD(lParam), TRUE); + UpdateWindow(hWnd); + break; + } + + ScreenCursorOn(pScr); + break; + + case WM_KEYDOWN: + if (wParam == VK_INSERT) { + if (GetKeyState(VK_SHIFT) < 0) + PostMessage(hWnd, WM_COMMAND, IDM_PASTE, 0); + else if (GetKeyState(VK_CONTROL) < 0) + PostMessage(hWnd, WM_COMMAND, IDM_COPY, 0); + break; + } + /* + ** Check for cursor keys. With control pressed, we treat as + ** keyboard equivalents to scrolling. Otherwise, we send + ** a WM_MYCURSORKEY message with the appropriate string + ** to be sent. Sending the actual string allows the upper + ** level to be ignorant of keyboard modes, etc. + */ + if (wParam < VK_PRIOR || wParam > VK_DOWN) /* Is it a cursor key? */ + break; + + if (GetKeyState (VK_CONTROL) >= 0) { /* No control key */ + if (wParam >= VK_LEFT && wParam <= VK_DOWN) { + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + wParam = wParam - VK_LEFT + (pScr->DECCKM ? 4 : 0); + SendMessage (pScr->hwndTel, WM_MYCURSORKEY, + strlen(cursor_key[wParam]), + (LPARAM) (char *) cursor_key[wParam]); + } + } else { /* Control is down */ + switch (wParam) { + case VK_PRIOR: /* Page up */ + SendMessage(hWnd, WM_VSCROLL, SB_PAGEUP, 0); + break; + case VK_NEXT: /* Page down */ + SendMessage(hWnd, WM_VSCROLL, SB_PAGEDOWN, 0); + break; + case VK_UP: /* Line up */ + SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0); + break; + case VK_DOWN: /* Line down */ + SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0); + break; + } + } + UpdateWindow(hWnd); + break; + + case WM_CHAR: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + SendMessage(pScr->hwndTel, WM_MYSCREENCHAR, wParam, (LPARAM) pScr); + break; + + case WM_INITMENU: + if (IsClipboardFormatAvailable(CF_TEXT)) + EnableMenuItem((HMENU) wParam, IDM_PASTE, MF_ENABLED); + else + EnableMenuItem((HMENU) wParam, IDM_PASTE, MF_GRAYED); + if (bSelection) + EnableMenuItem((HMENU) wParam, IDM_COPY, MF_ENABLED); + else + EnableMenuItem((HMENU) wParam, IDM_COPY, MF_GRAYED); + break; + + case WM_GETMINMAXINFO: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + if (pScr == NULL) /* Used on creation when window word not set */ + pScr = ScreenList; + lpmmi = (MINMAXINFO *) lParam; + if (FRAME_WIDTH + MAX_LINE_WIDTH * pScr->cxChar < lpmmi->ptMaxSize.x) + lpmmi->ptMaxSize.x = FRAME_WIDTH + MAX_LINE_WIDTH * pScr->cxChar; + lpmmi->ptMaxTrackSize.x = lpmmi->ptMaxSize.x; + lpmmi->ptMinTrackSize.x = FRAME_WIDTH + 20 * pScr->cxChar; + lpmmi->ptMinTrackSize.y = FRAME_HEIGHT + 4 * pScr->cyChar; + break; + + case WM_LBUTTONDOWN: + if (bDoubleClick) + Edit_TripleClick(hWnd, lParam); + else + Edit_LbuttonDown(hWnd, lParam); + break; + + case WM_LBUTTONUP: + Edit_LbuttonUp(hWnd, lParam); + break; + + case WM_LBUTTONDBLCLK: + bDoubleClick = TRUE; + SetTimer(hWnd, TIMER_TRIPLECLICK, GetDoubleClickTime(), NULL); + Edit_LbuttonDblclk(hWnd, lParam); + break; + + case WM_TIMER: + if (wParam == TIMER_TRIPLECLICK) + bDoubleClick = FALSE; + break; + + case WM_RBUTTONUP: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + Edit_Copy(hWnd); + Edit_ClearSelection(pScr); + Edit_Paste(hWnd); + break; + + case WM_MOUSEMOVE: + if (bMouseDown) + Edit_MouseMove(hWnd, lParam); + break; + + case WM_RBUTTONDOWN: +#if 0 + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + wsprintf(strTmp,"fp->x=%d fp->y=%d text=%s \r\n", + pScr->screen_top->x, pScr->screen_top->y, pScr->screen_top->text); + OutputDebugString(strTmp); +#endif + break; + + case WM_PAINT: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + BeginPaint (hWnd, &ps); + SelectObject(ps.hdc, pScr->hSelectedFont); + if (pScr->screen_bottom != NULL) + DrawTextScreen(ps.rcPaint, pScr, ps.hdc); + else + OutputDebugString("screen_bottom is NULL.\r\n"); + EndPaint(hWnd, &ps); + break; + + case WM_CLOSE: + if (MessageBox(hWnd, "Terminate this connection?", "Telnet", MB_OKCANCEL) == IDOK) { + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + SendMessage(pScr->hwndTel, WM_MYSCREENCLOSE, 0, (LPARAM) pScr); + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + break; + + case WM_DESTROY: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + if (pScr != NULL) + DeleteObject(pScr->hSelectedFont); + return (DefWindowProc(hWnd, message, wParam, lParam)); + + case WM_ACTIVATE: + if (wParam != WA_INACTIVE) { + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + if (pScr->bAlert) { + char strTitle[128]; + int idx; + + GetWindowText(hWnd, strTitle, sizeof(strTitle)); + if (strTitle[0] == ALERT) { + idx = lstrlen(strTitle); + strTitle[idx - 2] = 0; + SetWindowText(hWnd, &strTitle[2]); + pScr->bAlert = FALSE; + } + } + } + return (DefWindowProc(hWnd, message, wParam, lParam)); + + case WM_SIZE: + if (wParam == SIZE_MINIMIZED) + break; + + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + + if (SetInternalScreenSize(pScr, LOWORD(lParam), HIWORD(lParam))) { + SendMessage(pScr->hwndTel, WM_MYSCREENSIZE, 0, + MAKELONG(pScr->width, pScr->height)); + } + MakeWindowTitle(pScr->title, pScr->width, pScr->height, + title, sizeof(title)); + SetWindowText(hWnd, title); + break; + + case WM_SETFOCUS: + pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE); + assert (pScr != NULL); + CreateCaret(hWnd, NULL, pScr->cxChar, 2); + ScreenCursorOn(pScr); + break; + + case WM_KILLFOCUS: + DestroyCaret(); + break; + + default: + return(DefWindowProc(hWnd, message, wParam, lParam)); + } + + return(0); + +} /* ScreenWndProc */ + + +void ScreenBell( + SCREEN *pScr) +{ + char strTitle[128]; + int idx; + + MessageBeep(MB_ICONEXCLAMATION); + if (pScr->hWnd != GetActiveWindow()) { + FlashWindow(pScr->hWnd, TRUE); + if (!pScr->bAlert) { + strTitle[0] = ALERT; + strTitle[1] = SPACE; + GetWindowText(pScr->hWnd, &strTitle[2], sizeof(strTitle) - 2); + idx = lstrlen(strTitle); + strTitle[idx] = SPACE; + strTitle[idx+1] = ALERT; + strTitle[idx+2] = 0; + SetWindowText(pScr->hWnd, strTitle); + } + FlashWindow(pScr->hWnd, FALSE); + pScr->bAlert = TRUE; + } + +} /* ScreenBell */ + + +void ScreenBackspace(SCREEN *pScr) +{ + RECT rc; + + pScr->bWrapPending = FALSE; + rc.left = pScr->x * pScr->cxChar; + rc.right = (pScr->x + 1) * pScr->cxChar; + rc.top = pScr->cyChar * pScr->y; + rc.bottom = pScr->cyChar * (pScr->y + 1); + InvalidateRect(pScr->hWnd, &rc, TRUE); + pScr->x--; + if (pScr->x < 0) + pScr->x = 0; + UpdateWindow(pScr->hWnd); + +} /* ScreenBackspace */ + + +void ScreenTab( + SCREEN *pScr) +{ + int num_spaces; + int idx; + SCREENLINE *pScrLine; + int iTest = 0; + HDC hDC; + + num_spaces = TAB_SPACES - (pScr->x % TAB_SPACES); + if (pScr->x + num_spaces >= pScr->width) + num_spaces = pScr->width - pScr->x; + pScrLine = GetScreenLineFromY(pScr, pScr->y); + if (pScrLine == NULL) + return; + for (idx = 0; idx < num_spaces; idx++, pScr->x++) { + if (!pScrLine->text[pScr->x]) + iTest=1; + if (iTest) + pScrLine->text[pScr->x] = SPACE; + } + hDC = GetDC(pScr->hWnd); + assert(hDC != NULL); + SelectObject(hDC, pScr->hSelectedFont); + TextOut(hDC, (pScr->x - num_spaces) * pScr->cxChar, pScr->y * pScr->cyChar, + pScrLine->text + pScr->x - num_spaces, num_spaces); + ReleaseDC(pScr->hWnd, hDC); + if (pScr->x >= pScr->width) + pScr->x = pScr->width - 1; + pScr->bWrapPending = FALSE; + +} /* ScreenTab */ + + +void ScreenCarriageFeed( + SCREEN *pScr) +{ + pScr->bWrapPending = FALSE; + pScr->x = 0; + +} /* ScreenCarriageFeed */ diff --git a/krb5-1-6/src/windows/wintel/screen.h b/krb5-1-6/src/windows/wintel/screen.h new file mode 100644 index 000000000..7cba678ce --- /dev/null +++ b/krb5-1-6/src/windows/wintel/screen.h @@ -0,0 +1,325 @@ +extern long PASCAL ScreenWndProc(HWND,UINT,WPARAM,LPARAM); + +/* +* Definition of attribute bits in the Virtual Screen +* +* 0 - Bold +* 1 - +* 2 - +* 3 - Underline +* 4 - Blink +* 5 - +* 6 - Reverse +* 7 - Graphics character set +* +*/ +#define SCR_isbold(x) (x & 0x01) +#define SCR_isundl(x) (x & 0x08) +#define SCR_isblnk(x) (x & 0x10) +#define SCR_isrev(x) (x & 0x40) +#define SCR_setrev(x) (x ^= 0x40) +#define SCR_isgrph(x) (x & 0x80) +#define SCR_inattr(x) (x & 0xd9) +#define SCR_graph(x) (x | 0x80) +#define SCR_notgraph(x) (x & 0x7F) + +#define SCREEN_HANDLE 0 /* offset in extra window info */ + +#define WM_MYSCREENCHAR (WM_USER+1) +#define WM_MYSCREENBLOCK (WM_USER+2) +#define WM_MYSYSCHAR (WM_USER+3) +#define WM_MYSCREENCLOSE (WM_USER+4) +#define WM_MYSCREENCHANGEBKSP (WM_USER+5) +#define WM_MYSCREENSIZE (WM_USER+6) +#define WM_NETWORKEVENT (WM_USER+7) +#define WM_HOSTNAMEFOUND (WM_USER+8) +#define WM_MYCURSORKEY (WM_USER+9) + +#define FRAME_HEIGHT ((2* GetSystemMetrics(SM_CYFRAME))+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYMENU)+3) +#define FRAME_WIDTH (2*GetSystemMetrics(SM_CXFRAME)+GetSystemMetrics(SM_CXVSCROLL)) +#define TAB_SPACES 8 +#define SPACE 32 +#define ALERT 0x21 +#define MAX_LINE_WIDTH 512 /* not restricted to 1 byte */ + +typedef struct SCREENLINE { + struct SCREENLINE *next; + struct SCREENLINE *prev; + int width; + char *text; + char *attrib; + char buffer[0]; +} SCREENLINE; + +typedef struct SCREEN { + LPSTR title; + HWND hWnd; + HWND hwndTel; + SCREENLINE *screen_top; + SCREENLINE *screen_bottom; + SCREENLINE *buffer_top; + SCREENLINE *buffer_bottom; + int ID; + int type; + int width; + int height; + int maxlines; /* Maximum number of scrollback lines */ + int numlines; /* Current number of scrollback lines */ + int savelines; /* Save lines off top? */ + int ESscroll; /* Scroll screen when ES received */ + int attrib; /* current attribute */ + int x; /* current cursor position */ + int y; /* current cursor position */ + int Oldx; /* internally used to redraw cursor */ + int Oldy; + int Px; /* saved cursor pos and attribute */ + int Py; + int Pattrib; + int VSIDC; /* Insert/Delete character mode 0=draw line */ + int DECAWM; /* AutoWrap mode 0=off */ + BOOL bWrapPending; /* AutoWrap mode is on - wrap on next character */ + int DECCKM; /* Cursor key mode */ + int DECPAM; /* keyPad Application mode */ + int IRM; /* Insert/Replace mode */ + int escflg; /* Current Escape level */ + int top; /* Vertical bounds of screen */ + int bottom; + int parmptr; + int cxChar; /* Width of the current font */ + int cyChar; /* Height of the current font */ + BOOL bAlert; + int parms[6]; /* Ansi Params */ + LOGFONT lf; + HFONT hSelectedFont; + HFONT hSelectedULFont; + char tabs[MAX_LINE_WIDTH]; + struct SCREEN *next; + struct SCREEN *prev; +} SCREEN; + +typedef struct CONFIG { + LPSTR title; + HWND hwndTel; + int ID; + int type; + int height; + int width; + int maxlines; /* Maximum number of scrollback lines */ + int backspace; + int ESscroll; /* Scroll screen when ES received */ + int VSIDC; /* Insert/Delete character mode 0=draw line */ + int DECAWM; /* AutoWrap mode 0=off */ + int IRM; /* Insert/Replace mode */ +} CONFIG; + +#define TELNET_SCREEN 0 +#define CONSOLE_SCREEN 1 + +#define IDM_FONT 100 +#define IDM_BACKSPACE 101 +#define IDM_DELETE 102 +#define IDM_ABOUT 103 +#define IDM_HELP_INDEX 104 +#define IDM_EXIT 105 + +#define HELP_FILE "ktelnet.hlp" + +#define IDM_COPY 200 +#define IDM_PASTE 201 +#define IDM_DEBUG 202 + +#define TIMER_TRIPLECLICK 1000 + +#define IDC_ALLOCFAIL 1 +#define IDC_LOCKFAIL 2 +#define IDC_LOADSTRINGFAIL 3 +#define IDC_FONT 6 + +#define DESIREDPOINTSIZE 12 + +/* +Prototypes +*/ + void NEAR InitializeStruct( + WORD wCommDlgType, + LPSTR lpStruct, + HWND hWnd); + + void ScreenInit( + HINSTANCE hInstance); + + void SetScreenInstance( + HINSTANCE hInstance); + + SCREENLINE *ScreenNewLine(); + + void ScreenBell( + SCREEN *pScr); + + void ScreenBackspace( + SCREEN *pScr); + + void ScreenTab( + SCREEN *pScr); + + void ScreenCarriageFeed( + SCREEN *pScr); + + int ScreenScroll( + SCREEN *pScr); + + void DeleteTopLine( + SCREEN *pScr); + +/* +emul.c +*/ + void ScreenEm( + LPSTR c, + int len, + SCREEN *pScr); + +/* +intern.c +*/ + SCREENLINE *GetScreenLineFromY( + SCREEN *pScr, + int y); + + SCREENLINE *ScreenClearLine( + SCREEN *pScr, + SCREENLINE *pScrLine); + + void ScreenUnscroll( + SCREEN *pScr); + + void ScreenELO( + SCREEN *pScr, + int s); + + void ScreenEraseScreen( + SCREEN *pScr); + + void ScreenTabClear( + SCREEN *pScr); + + void ScreenTabInit( + SCREEN *pScr); + + void ScreenReset( + SCREEN *pScr); + + void ScreenIndex( + SCREEN *pScr); + + void ScreenWrapNow( + SCREEN *pScr, + int *xp, + int *yp); + + void ScreenEraseToEOL( + SCREEN *pScr); + + void ScreenEraseToBOL( + SCREEN *pScr); + + void ScreenEraseLine( + SCREEN *pScr, + int s); + + void ScreenEraseToEndOfScreen( + SCREEN *pScr); + + void ScreenRange( + SCREEN *pScr); + + void ScreenAlign( + SCREEN *pScr); + + void ScreenApClear( + SCREEN *pScr); + + void ScreenSetOption( + SCREEN *pScr, + int toggle); + + BOOL ScreenInsChar( + SCREEN *pScr, + int x); + + void ScreenSaveCursor( + SCREEN *pScr); + + void ScreenRestoreCursor( + SCREEN *pScr); + + void ScreenDraw( + SCREEN *pScr, + int x, + int y, + int a, + int len, + char *c); + + void ScreenCursorOff( + SCREEN *pScr); + + void ScreenCursorOn( + SCREEN *pScr); + + void ScreenDelChars( + SCREEN *pScr, + int n); + + void ScreenRevIndex( + SCREEN *pScr); + + void ScreenDelLines( + SCREEN *pScr, + int n, + int s); + + void ScreenInsLines( + SCREEN *pScr, + int n, + int s); + + #if ! defined(NDEBUG) + BOOL CheckScreen( + SCREEN *pScr); + #endif + + void ProcessFontChange( + HWND hWnd); + + void Edit_LbuttonDown( + HWND hWnd, + LPARAM lParam); + + void Edit_LbuttonDblclk( + HWND hWnd, + LPARAM lParam); + + void Edit_LbuttonUp( + HWND hWnd, + LPARAM lParam); + + void Edit_TripleClick( + HWND hWnd, + LPARAM lParam); + + void Edit_MouseMove( + HWND hWnd, + LPARAM lParam); + + void Edit_ClearSelection( + SCREEN *pScr); + + void Edit_Copy( + HWND hWnd); + + void Edit_Paste( + HWND hWnd); + + SCREEN *InitNewScreen( + CONFIG *Config); diff --git a/krb5-1-6/src/windows/wintel/struct.h b/krb5-1-6/src/windows/wintel/struct.h new file mode 100644 index 000000000..bc1cc4912 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/struct.h @@ -0,0 +1,29 @@ +#include "winsock.h" +#ifdef KRB4 + #include "kstream.h" +#endif +#ifdef KRB5 + #include "k5stream.h" +#endif + +#define HCONNECTION HGLOBAL + +typedef struct CONNECTION { + SCREEN *pScreen; /* handle to screen associated with connection */ + kstream ks; + SOCKET socket; + int pnum; /* port number associated with connection */ + int telstate; /* telnet state for this connection */ + int substate; /* telnet subnegotiation state */ + int termsent; + int echo; + int ugoahead; + int igoahead; + int timing; + int backspace; + int ctrl_backspace; + int termstate; /* terminal type for this connection */ + int width; + int height; + BOOL bResizeable; +} CONNECTION; diff --git a/krb5-1-6/src/windows/wintel/telnet.c b/krb5-1-6/src/windows/wintel/telnet.c new file mode 100644 index 000000000..449471b7b --- /dev/null +++ b/krb5-1-6/src/windows/wintel/telnet.c @@ -0,0 +1,904 @@ +/**************************************************************************** + + Program: telnet.c + + PURPOSE: Windows networking kernel - Telnet + + FUNCTIONS: + + WinMain() - calls initialization function, processes message loop + InitApplication() - initializes window data and registers window + InitInstance() - saves instance handle and creates main window + MainWndProc() - processes messages + About() - processes messages for "About" dialog box + + COMMENTS: + + Windows can have several copies of your application running at the + same time. The variable hInst keeps track of which instance this + application is so that processing will be to the correct window. + + ****************************************************************************/ + +#include <windows.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "telnet.h" +#include "auth.h" + +static HANDLE hInst; +static HWND hWnd; +static CONFIG *tmpConfig; +static CONNECTION *con = NULL; +static char hostdata[MAXGETHOSTSTRUCT]; +static SCREEN *pScr; +static int debug = 1; + +char strTmp[1024]; /* Scratch buffer */ +BOOL bAutoConnection = FALSE; +short port_no = 23; +char szUserName[64]; /* Used in auth.c */ +char szHostName[64]; + +#ifdef KRB4 +#define WINDOW_CLASS "K4_telnetWClass" +#endif + +#ifdef KRB5 +krb5_context k5_context; +#define WINDOW_CLASS "K5_telnetWClass" +#endif + +/* + * + * FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int) + * + * PURPOSE: calls initialization function, processes message loop + * + * COMMENTS: + * + * Windows recognizes this function by name as the initial entry point + * for the program. This function calls the application initialization + * routine, if no other instance of the program is running, and always + * calls the instance initialization routine. It then executes a message + * retrieval and dispatch loop that is the top-level control structure + * for the remainder of execution. The loop is terminated when a WM_QUIT + * message is received, at which time this function exits the application + * instance by returning the value passed by PostQuitMessage(). + * + * If this function must abort before entering the message loop, it + * returns the conventional value NULL. + */ + +int PASCAL +WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + + if (!hPrevInstance) + if (!InitApplication(hInstance)) + return(FALSE); + + /* + * Perform initializations that apply to a specific instance + */ + bAutoConnection = parse_cmdline(lpCmdLine); + + if (!InitInstance(hInstance, nCmdShow)) + return(FALSE); + +#ifdef _WIN32 + SetDebugErrorLevel(SLE_WARNING); +#endif + + /* + * Acquire and dispatch messages until a WM_QUIT message is received. + */ + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + /* Process all non-network messages */ + while (PeekMessage(&msg, NULL, 0, WM_NETWORKEVENT-1, PM_REMOVE) || + PeekMessage(&msg, NULL, WM_NETWORKEVENT+1, (UINT)-1, PM_REMOVE)) + { + if (msg.message == WM_QUIT) // Special case: WM_QUIT -- return + return msg.wParam; // the value from PostQuitMessage + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (msg.wParam); /* Returns the value from PostQuitMessage */ +} + +/* + * FUNCTION: InitApplication(HINSTANCE) + * + * PURPOSE: Initializes window data and registers window class + * + * COMMENTS: + * + * This function is called at initialization time only if no other + * instances of the application are running. This function performs + * initialization tasks that can be done once for any number of running + * instances. + * + * In this case, we initialize a window class by filling out a data + * structure of type WNDCLASS and calling the Windows RegisterClass() + * function. Since all instances of this application use the same window + * class, we only need to do this when the first instance is initialized. + */ + +BOOL +InitApplication(HINSTANCE hInstance) +{ + WNDCLASS wc; + + ScreenInit(hInstance); + + /* + * Fill in window class structure with parameters that describe the + * main window. + */ + wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */ + wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages for + * windows of this class. + */ + wc.cbClsExtra = 0; /* No per-class extra data. */ + wc.cbWndExtra = 0; /* No per-window extra data. */ + wc.hInstance = hInstance; /* Application that owns the class. */ + wc.hIcon = NULL; /* LoadIcon(hInstance, "NCSA"); */ + wc.hCursor = NULL; /* Cursor(NULL, IDC_ARROW); */ + wc.hbrBackground = NULL; /* GetStockObject(WHITE_BRUSH); */ + wc.lpszMenuName = NULL; /* Name of menu resource in .RC file. */ + wc.lpszClassName = WINDOW_CLASS; /* Name used in call to CreateWindow. */ + + return(RegisterClass(&wc)); +} + + +/* + * FUNCTION: InitInstance(HANDLE, int) + * + * PURPOSE: Saves instance handle and creates main window + * + * COMMENTS: + * + * This function is called at initialization time for every instance of + * this application. This function performs initialization tasks that + * cannot be shared by multiple instances. + * + * In this case, we save the instance handle in a static variable and + * create and display the main program window. + */ +BOOL +InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + int xScreen = 0; + int yScreen = 0; + WSADATA wsaData; + + SetScreenInstance(hInstance); + + /* + * Save the instance handle in static variable, which will be used in + * many subsequence calls from this application to Windows. + */ + hInst = hInstance; + + /* + * Create a main window for this application instance. + */ + hWnd = CreateWindow( + WINDOW_CLASS, /* See RegisterClass() call. */ + "TCPWin", /* Text for window title bar. */ + WS_SYSMENU, /* Window style. */ + xScreen / 3, /* Default horizontal position. */ + yScreen / 3, /* Default vertical position. */ + xScreen / 3, /* Default width. */ + yScreen / 3, /* Default height. */ + NULL, /* Overlapped windows have no parent */ + NULL, /* Use the window class menu. */ + hInstance, /* This instance owns this window. */ + NULL); /* Pointer not needed. */ + + if (!hWnd) + return (FALSE); + + if (WSAStartup(0x0101, &wsaData) != 0) { /* Initialize the network */ + MessageBox(NULL, "Couldn't initialize Winsock!", NULL, + MB_OK | MB_ICONEXCLAMATION); + return(FALSE); + } + + if (!OpenTelnetConnection()) { + WSACleanup(); + return(FALSE); + } + +#ifdef KRB5 + krb5_init_context(&k5_context); +#endif + + return (TRUE); +} + +char buf[2048]; + +/* + * FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM) + * + * PURPOSE: Processes messages + * + * MESSAGES: + * + * WM_COMMAND - application menu (About dialog box) + * WM_DESTROY - destroy window + */ +LRESULT CALLBACK +MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HGLOBAL hBuffer; + LPSTR lpBuffer; + int iEvent, cnt, ret; + char *tmpCommaLoc; + struct sockaddr_in remote_addr; + struct hostent *remote_host; + + switch (message) { + case WM_MYSCREENCHANGEBKSP: + if (!con) + break; + con->backspace = wParam; + if (con->backspace == VK_BACK) { + con->ctrl_backspace = 0x7f; + WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, + INI_BACKSPACE_BS, TELNET_INI); + } + else { + con->ctrl_backspace = VK_BACK; + WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, + INI_BACKSPACE_DEL, TELNET_INI); + } + GetPrivateProfileString(INI_HOSTS, INI_HOST "0", "", buf, 128, TELNET_INI); + tmpCommaLoc = strchr(buf, ','); + if (tmpCommaLoc == NULL) { + strcat (buf, ","); + tmpCommaLoc = strchr(buf, ','); + } + if (tmpCommaLoc) { + tmpCommaLoc++; + if (con->backspace == VK_BACK) + strcpy(tmpCommaLoc, INI_HOST_BS); + else + strcpy(tmpCommaLoc, INI_HOST_DEL); + } + WritePrivateProfileString(INI_HOSTS, INI_HOST "0", buf, TELNET_INI); + break; + + case WM_MYSCREENCHAR: + { + unsigned char c; + + if (!con) + break; + if (wParam == VK_BACK) + c = con->backspace; + else if (wParam == 0x7f) + c = con->ctrl_backspace; + else if (wParam == VK_SPACE && GetKeyState(VK_CONTROL) < 0) + c = 0; + else + c = wParam; + TelnetSend(con->ks, &c, 1, 0); + } + break; + + case WM_MYCURSORKEY: + /* Acts as a send through: buffer is lParam and length in wParam */ + if (!con) + break; + memcpy(buf, (char *)lParam, wParam); + TelnetSend (con->ks, buf, wParam, 0); + break; + + case WM_MYSCREENBLOCK: + if (!con) + break; + hBuffer = (HGLOBAL) wParam; + lpBuffer = GlobalLock(hBuffer); + TelnetSend(con->ks, lpBuffer, lstrlen(lpBuffer), 0); + GlobalUnlock(hBuffer); + break; + + case WM_MYSCREENCLOSE: +#if 0 + if (con) + { + kstream_destroy(con->ks); + con->ks = NULL; + } +#endif + DestroyWindow(hWnd); + break; + + case WM_QUERYOPEN: + return(0); + break; + + case WM_DESTROY: /* message: window being destroyed */ + if (con) + { + kstream_destroy(con->ks); + free(con); + WSACleanup(); + } + PostQuitMessage(0); + break; + + case WM_NETWORKEVENT: + iEvent = WSAGETSELECTEVENT(lParam); + + switch (iEvent) { + + case FD_READ: + if (con == NULL) + break; + cnt = kstream_read(con->ks, buf, 1500); + buf[cnt] = 0; + parse((CONNECTION *)con, (unsigned char *)buf, cnt); + ScreenEm(buf, cnt, con->pScreen); + break; + + case FD_CLOSE: + kstream_destroy(con->ks); + free(con); + con = NULL; + WSACleanup(); + PostQuitMessage(0); + break; + + case FD_CONNECT: + ret = WSAGETSELECTERROR(lParam); + if (ret) { + wsprintf(buf, "Error %d on Connect", ret); + MessageBox(NULL, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + kstream_destroy(con->ks); + free(con); + WSACleanup(); + PostQuitMessage(0); + break; + } + start_negotiation(con->ks); + break; + } + + break; + + case WM_HOSTNAMEFOUND: + ret = WSAGETASYNCERROR(lParam); + if (ret) { + wsprintf(buf, "Error %d on GetHostbyName", ret); + MessageBox(NULL, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + kstream_destroy(con->ks); + free(con); + WSACleanup(); + PostQuitMessage(0); + break; + } + + remote_host = (struct hostent *)hostdata; + remote_addr.sin_family = AF_INET; + memcpy(&(remote_addr.sin_addr), &(remote_host->h_addr[0]), 4); + remote_addr.sin_port = htons(port_no); + + connect(con->socket, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)); + break; + + case WM_MYSCREENSIZE: + con->width = LOWORD(lParam); /* width in characters */ + con->height = HIWORD(lParam); /* height in characters */ + if (con->bResizeable && con->ks) + send_naws(con); + wsprintf(buf, "%d", con->height); + WritePrivateProfileString(INI_TELNET, INI_HEIGHT, buf, TELNET_INI); + wsprintf(buf, "%d", con->width); + WritePrivateProfileString(INI_TELNET, INI_WIDTH, buf, TELNET_INI); + break; + + default: /* Passes it on if unproccessed */ + return(DefWindowProc(hWnd, message, wParam, lParam)); + } + return (0); +} + + +/* + * + * FUNCTION: SaveHostName(hostname, port) + * + * PURPOSE: Saves the currently selected host name and port number + * in the KERBEROS.INI file and returns the preferred backspace + * setting if one exists for that host. + * + * RETURNS: VK_BACK or 0x7f depending on the desired backspace setting. + */ +int +SaveHostName(char *host, int port) +{ + char buf[128]; /* Scratch buffer */ + char fullhost[128]; /* Host & port combination */ + char hostName[10][128]; /* Entries from INI files */ + char *comma; /* For parsing del/bs info */ + int len; /* Length of fullhost */ + int n; /* Number of items written */ + int i; /* Index */ + int bs; /* What we return */ + + if (port == 23) /* Default telnet port */ + strcpy(fullhost, host); /* ...then don't add it on */ + else + wsprintf(fullhost, "%s %d", host, port); + len = strlen(fullhost); + + comma = NULL; + for (i = 0; i < 10; i++) { + wsprintf(buf, INI_HOST "%d", i); /* INI item to fetch */ + GetPrivateProfileString(INI_HOSTS, buf, "", hostName[i], + 128, TELNET_INI); + + if (!hostName[i][0]) + break; + + if (strncmp (hostName[i], fullhost, len)) /* A match?? */ + continue; /* Nope, keep going */ + comma = strchr (hostName[i], ','); + } + + if (comma) { + ++comma; /* Past the comma */ + while (*comma == ' ') /* Past leading white space */ + ++comma; + bs = VK_BACK; /* Default for unknown entry */ + if (_stricmp(comma, INI_HOST_DEL) == 0) + bs = 0x7f; + } + else { /* No matching entry */ + GetPrivateProfileString(INI_TELNET, INI_BACKSPACE, INI_BACKSPACE_BS, + buf, sizeof(buf), TELNET_INI); + bs = VK_BACK; /* Default value */ + if (_stricmp(buf, INI_BACKSPACE_DEL) == 0) + bs = 0x7f; + } + + /* + * Build up default host name + */ + strcpy(buf, fullhost); + strcat(buf, ", "); + strcat(buf, (bs == VK_BACK) ? INI_BACKSPACE_BS : INI_BACKSPACE_DEL); + WritePrivateProfileString(INI_HOSTS, INI_HOST "0", buf, TELNET_INI); + + n = 0; + for (i = 0; i < 10; i++) { + if (!hostName[i][0]) /* End of the list? */ + break; + if (strncmp(hostName[i], fullhost, len) != 0) { + wsprintf(buf, INI_HOST "%d", ++n); + WritePrivateProfileString(INI_HOSTS, buf, hostName[i], TELNET_INI); + } + } + return(bs); +} + + +int +OpenTelnetConnection(void) +{ + int nReturn, ret; + struct sockaddr_in sockaddr; + char *p; + static struct kstream_crypt_ctl_block ctl; + char buf[128]; + + tmpConfig = calloc(sizeof(CONFIG), 1); + + if (bAutoConnection) { + tmpConfig->title = calloc(lstrlen(szHostName), 1); + lstrcpy(tmpConfig->title, (char *) szHostName); + } else { + nReturn = DoDialog("OPENTELNETDLG", OpenTelnetDlg); + if (nReturn == FALSE) + return(FALSE); + } + + con = (CONNECTION *) GetNewConnection(); + if (con == NULL) + return(0); + + tmpConfig->width = + GetPrivateProfileInt(INI_TELNET, INI_WIDTH, DEF_WIDTH, TELNET_INI); + + tmpConfig->height = + GetPrivateProfileInt(INI_TELNET, INI_HEIGHT, DEF_HEIGHT, TELNET_INI); + con->width = tmpConfig->width; + con->height = tmpConfig->height; + + con->backspace = SaveHostName(tmpConfig->title, port_no); + + if (con->backspace == VK_BACK) { + tmpConfig->backspace = TRUE; + con->ctrl_backspace = 0x7f; + } else { + tmpConfig->backspace = FALSE; + con->ctrl_backspace = 0x08; + } + + tmpConfig->hwndTel = hWnd; + con->pScreen = InitNewScreen(tmpConfig); + if (!con->pScreen) { + assert(FALSE); + free(con->pScreen); + free(con); + free(tmpConfig); + return(-1); + } + + ret = (SOCKET) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (ret == SOCKET_ERROR) { + wsprintf(buf, "Socket error on socket = %d!", WSAGetLastError()); + MessageBox(NULL, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + if (con->pScreen != NULL) + DestroyWindow(con->pScreen->hWnd); + free(con); + free(tmpConfig); + return(-1); + } + + con->socket = ret; + + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + sockaddr.sin_port = htons(0); + + ret = bind(con->socket, (struct sockaddr *) &sockaddr, + (int) sizeof(struct sockaddr_in)); + + if (ret == SOCKET_ERROR) { + wsprintf(buf, "Socket error on bind!"); + MessageBox(NULL, buf, NULL, MB_OK | MB_ICONEXCLAMATION); + if (con->pScreen != NULL) + DestroyWindow(con->pScreen->hWnd); + free(con); + free(tmpConfig); + return(-1); + } + + WSAAsyncSelect(con->socket, hWnd, WM_NETWORKEVENT, + FD_READ | FD_CLOSE | FD_CONNECT); + + lstrcpy(szHostName, tmpConfig->title); + p = strchr(szHostName, '@'); + if (p != NULL) { + *p = 0; + strcpy (szUserName, szHostName); + strcpy(szHostName, ++p); + } + + WSAAsyncGetHostByName(hWnd, WM_HOSTNAMEFOUND, szHostName, hostdata, + MAXGETHOSTSTRUCT); + + ctl.encrypt = auth_encrypt; + ctl.decrypt = auth_decrypt; + ctl.init = auth_init; + ctl.destroy = auth_destroy; + + con->ks = kstream_create_from_fd(con->socket, &ctl, NULL); + + if (con->ks == NULL) + return(-1); + + kstream_set_buffer_mode(con->ks, 0); + + return(1); +} + + +CONNECTION * +GetNewConnection(void) +{ + CONNECTION *pCon; + + pCon = calloc(sizeof(CONNECTION), 1); + if (pCon == NULL) + return NULL; + pCon->backspace = TRUE; + pCon->bResizeable = TRUE; + return(pCon); +} + + +int +DoDialog(char *szDialog, DLGPROC lpfnDlgProc) +{ + int nReturn; + + nReturn = DialogBox(hInst, szDialog, hWnd, lpfnDlgProc); + return (nReturn); +} + + +/* + * FUNCTION: OpenTelnetDlg(HWND, unsigned, WORD, LONG) + * + * PURPOSE: Processes messages for "Open New Telnet Connection" dialog box + * + * MESSAGES: + * + * WM_INITDIALOG - initialize dialog box + * WM_COMMAND - Input received + */ +INT_PTR CALLBACK +OpenTelnetDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char szConnectName[256]; + HDC hDC; + int xExt, yExt; + DWORD Ext; + HWND hEdit; + int n; + int iHostNum = 0; + char tmpName[128]; + char tmpBuf[80]; + char *tmpCommaLoc; + + switch (message) { + case WM_INITDIALOG: + hDC = GetDC(hDlg); + Ext = GetDialogBaseUnits(); + xExt = (190 *LOWORD(Ext)) /4 ; + yExt = (72 * HIWORD(Ext)) /8 ; + GetPrivateProfileString(INI_HOSTS, INI_HOST "0", "", tmpName, + 128, TELNET_INI); + if (tmpName[0]) { + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) + *tmpCommaLoc = '\0'; + SetDlgItemText(hDlg, TEL_CONNECT_NAME, tmpName); + } + hEdit = GetWindow(GetDlgItem(hDlg, TEL_CONNECT_NAME), GW_CHILD); + while (TRUE) { + wsprintf(tmpBuf, INI_HOST "%d", iHostNum++); + GetPrivateProfileString(INI_HOSTS, tmpBuf, "", tmpName, + 128, TELNET_INI); + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) + *tmpCommaLoc = '\0'; + if (tmpName[0]) + SendDlgItemMessage(hDlg, TEL_CONNECT_NAME, CB_ADDSTRING, 0, + (LPARAM) ((LPSTR) tmpName)); + else + break; + } +#ifdef FORWARD + EnableWindow(GetDlgItem(hDlg, IDC_FORWARD), 1); + SendDlgItemMessage(hDlg, IDC_FORWARD, BM_SETCHECK, forward_flag, 0); + if (forward_flag) + EnableWindow(GetDlgItem(hDlg, IDC_FORWARDFORWARD), 1); + else + EnableWindow(GetDlgItem(hDlg, IDC_FORWARDFORWARD), 0); + SendDlgItemMessage(hDlg, IDC_FORWARDFORWARD, BM_SETCHECK, + forwardable_flag, 0); +#endif + +#ifdef ENCRYPTION + EnableWindow(GetDlgItem(hDlg, IDC_ENCRYPT), 1); + SendDlgItemMessage(hDlg, IDC_ENCRYPT, + BM_SETCHECK, encrypt_flag, 0); +#endif + + EnableWindow(GetDlgItem(hDlg, TEL_CONNECT_USERID), 1); + + SetWindowPos(hDlg, NULL, + (GetSystemMetrics(SM_CXSCREEN)/2)-(xExt/2), + (GetSystemMetrics(SM_CYSCREEN)/2)-(yExt/2), + 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); + ReleaseDC(hDlg, hDC); + SendMessage(hEdit, WM_USER + 1, 0, 0); + SendMessage(hDlg, WM_SETFOCUS, 0, 0); + return (TRUE); + + case WM_COMMAND: + switch (wParam) { + case TEL_CANCEL: + case IDCANCEL: /* From the menu */ + EndDialog(hDlg, FALSE); + break; + +#ifdef FORWARD + case IDC_FORWARD: + forward_flag = (BOOL)SendDlgItemMessage(hDlg, IDC_FORWARD, + BM_GETCHECK, 0, 0); + if (forward_flag) + EnableWindow(GetDlgItem(hDlg, IDC_FORWARDFORWARD), 1); + else + EnableWindow(GetDlgItem(hDlg, IDC_FORWARDFORWARD), 0); + break; + + case IDC_FORWARDFORWARD: + forwardable_flag = (BOOL)SendDlgItemMessage(hDlg, IDC_FORWARDFORWARD, + BM_GETCHECK, 0, 0); + break; +#endif + +#if ENCRYPTION + case IDC_ENCRYPT: + encrypt_flag = (BOOL)SendDlgItemMessage(hDlg, IDC_ENCRYPT, + BM_GETCHECK, 0, 0); + break; +#endif + case TEL_CONNECT_USERID: + GetDlgItemText(hDlg, TEL_CONNECT_USERID, szUserName, sizeof(szUserName)); + break; + + case TEL_OK: + GetDlgItemText(hDlg, TEL_CONNECT_NAME, szConnectName, 256); + + n = parse_cmdline (szConnectName); + if (! n) { + MessageBox(hDlg, "You must enter a session name!", + NULL, MB_OK); + break; + } + tmpConfig->title = calloc(lstrlen(szHostName) + 1, 1); + lstrcpy(tmpConfig->title, szConnectName); + EndDialog(hDlg, TRUE); + break; + } + return (FALSE); + } + return(FALSE); +} + + +/* + * + * FUNCTION: TelnetSend(kstream ks, char *buf, int len, int flags) + * + * PURPOSE: This is a replacement for the WinSock send() function, to + * send a buffer of characters to an output socket. It differs + * by retrying endlessly if sending the bytes would cause + * the send() to block. <gnu@cygnus.com> observed EWOULDBLOCK + * errors when running using TCP Software's PC/TCP 3.0 stack, + * even when writing as little as 109 bytes into a socket + * that had no more than 9 bytes queued for output. Note also + * that a kstream is used during output rather than a socket + * to facilitate encryption. + * + * Eventually, for cleanliness and responsiveness, this + * routine should not loop; instead, if the send doesn't + * send all the bytes, it should put them into a buffer + * and return. Message handling code would send out the + * buffer whenever it gets an FD_WRITE message. + */ +int +TelnetSend(kstream ks, char *buf, int len, int flags) +{ + int writelen; + int origlen = len; + + while (TRUE) { + writelen = kstream_write(ks, buf, len); + + if (writelen == len) /* Success, first or Nth time */ + return (origlen); + + if (writelen == SOCKET_ERROR) { + if (WSAGetLastError() != WSAEWOULDBLOCK) + return (SOCKET_ERROR); /* Some error */ + /* For WOULDBLOCK, immediately repeat the send. */ + } + else { + /* Partial write; update the pointers and retry. */ + len -= writelen; + buf += writelen; + } + } +} + + +/* + * Function: Trim leading and trailing white space from a string. + * + * Parameters: + * s - the string to trim. + */ +void +trim(char *s) +{ + int l; + int i; + + for (i = 0; s[i]; i++) + if (s[i] != ' ' && s[i] != '\t') + break; + + l = strlen(&s[i]); + memmove(s, &s[i], l + 1); + + for (l--; l >= 0; l--) { + if (s[l] != ' ' && s[l] != '\t') + break; + } + s[l + 1] = 0; +} + + +/* + * + * Parse_cmdline + * + * Reads hostname and port number off the command line. + * + * Formats: telnet + * telnet <host> + * telnet <host> <port no> + * telnet -p <port no> + * + * Returns: TRUE if we have a hostname + */ +BOOL +parse_cmdline(char *cmdline) +{ + char *ptr; + + *szHostName = '\0'; /* Nothing yet */ + if (*cmdline == '\0') /* Empty command line? */ + return(FALSE); + + trim (cmdline); /* Remove excess spaces */ + ptr = strchr (cmdline, ' '); /* Find 2nd token */ + + if (ptr != NULL) { /* Port number given */ + *ptr++ = '\0'; /* Separate into 2 words */ + port_no = atoi (ptr); + } + + if (*cmdline != '-' && *cmdline != '/') { /* Host name given */ + lstrcpy (szHostName, cmdline); + return(TRUE); + } + + return(FALSE); +} + +#ifdef DEBUG +void +hexdump(char *msg, unsigned char *st, int cnt) +{ + int i; + char strTmp[128]; + + OutputDebugString("\r\n"); + if (msg != NULL) { + OutputDebugString(msg); + OutputDebugString("\r\n"); + } + for(i = 0 ; i < cnt ; i++) { + int j; + + for(j = 0 ; (j < 16) && ((i + j) < cnt) ; j++) { + wsprintf(strTmp,"%02x ", st[i + j]); + if (j == 8) + OutputDebugString("| "); + OutputDebugString(strTmp); + } + i += j - 1; + OutputDebugString("\r\n"); + } /* end for */ +} +#endif diff --git a/krb5-1-6/src/windows/wintel/telnet.def b/krb5-1-6/src/windows/wintel/telnet.def new file mode 100644 index 000000000..e2d2ab93f --- /dev/null +++ b/krb5-1-6/src/windows/wintel/telnet.def @@ -0,0 +1,39 @@ +; module-definition file for testdll -- used by LINK.EXE +NAME TELNET +DESCRIPTION 'Sample Microsoft Windows Application' +EXETYPE WINDOWS +STUB 'WINSTUB.EXE' +SEGMENTS _TEXT CLASS 'CODE' PRELOAD +CODE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE +HEAPSIZE 10240 + +; All functions that will be called by any Windows routine +; MUST be exported. + +EXPORTS + MainWndProc @1 ; name of window processing function + OpenTelnetDlg @3 ; name of "Open New Telnet Connection" Dialog Function + +IMPORTS + WINSOCK.WSAStartup + WINSOCK.WSACleanup + WINSOCK.WSAAsyncSelect + WINSOCK.WSAGetLastError + WINSOCK.WSAAsyncGetHostByName + WINSOCK.listen + WINSOCK.accept + WINSOCK.__wsafdisset + WINSOCK.socket + WINSOCK.bind + WINSOCK.gethostbyname + WINSOCK.getsockname + WINSOCK.htons + WINSOCK.connect + WINSOCK.recv + WINSOCK.send + WINSOCK.htonl + WINSOCK.closesocket + WINSOCK.select + WINSOCK.ioctlsocket + WINSOCK.getpeername diff --git a/krb5-1-6/src/windows/wintel/telnet.h b/krb5-1-6/src/windows/wintel/telnet.h new file mode 100644 index 000000000..cd1904a14 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/telnet.h @@ -0,0 +1,41 @@ +#ifndef TELNET_H_INC +#define TELNET_H_INC + +#include <windows.h> +#include <stdarg.h> + +#ifdef KRB5 +#include "krb5.h" +#include "k5stream.h" +#endif + +#include "dialog.h" +#include "screen.h" +#include "struct.h" +#include "wt-proto.h" +#include "winsock.h" +#include "ini.h" + +/* globals */ +extern char szAutoHostName[64]; +extern char szUserName[64]; +extern char szHostName[64]; + +#ifdef KRB5 +extern krb5_context k5_context; +#endif + +extern void parse(CONNECTION *, unsigned char *, int); + +extern void send_naws(CONNECTION *); + +extern char strTmp[1024]; + +#define DEF_WIDTH 80 +#define DEF_HEIGHT 24 + +#ifdef DEBUG +void hexdump(char *, unsigned char *, int); +#endif + +#endif /* TELNET_H_INC */ diff --git a/krb5-1-6/src/windows/wintel/telnet.rc b/krb5-1-6/src/windows/wintel/telnet.rc new file mode 100644 index 000000000..6fd62c21e --- /dev/null +++ b/krb5-1-6/src/windows/wintel/telnet.rc @@ -0,0 +1,247 @@ +//Microsoft Developer Studio generated resource script. +// +// XXX since modified by hand... + +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "dialog.h" +#include "screen.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +OPENTELNETDLG DIALOG DISCARDABLE 63, 65, 175, 129 +#ifdef _WIN32 +STYLE DS_ABSALIGN | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | + WS_SYSMENU +#else +STYLE DS_ABSALIGN | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +#endif +CAPTION "Open New Telnet Connection" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "To Host:",IDC_STATIC,3,10,33,10,NOT WS_GROUP + COMBOBOX TEL_CONNECT_NAME,37,9,128,76,CBS_DROPDOWN | WS_VSCROLL | + WS_GROUP | WS_TABSTOP + CONTROL "Forward credentials",IDC_FORWARD,"Button", + BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,37,28,77,10 + CONTROL "Forward remote credentials",IDC_FORWARDFORWARD,"Button", + BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,37,44,101,10 + CONTROL "Enable encryption",IDC_ENCRYPT,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,37,60,73,10 + CONTROL "Connect as userid",IDC_STATIC,"Static", + SS_LEFTNOWORDWRAP,15,84,58,8 + EDITTEXT TEL_CONNECT_USERID,77,82,80,13,ES_AUTOHSCROLL | + WS_DISABLED + DEFPUSHBUTTON "OK",TEL_OK,20,106,51,14,WS_GROUP + PUSHBUTTON "Cancel",TEL_CANCEL,106,106,51,14 +END + +ABOUTBOX DIALOG DISCARDABLE 69, 33, 175, 148 +STYLE DS_ABSALIGN | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About TCPwin" +BEGIN + ICON "NCSA",-1,15,12,16,16 + CTEXT "Microsoft Windows",-1,48,11,93,8 + CTEXT "NCSA TCP/IP Networking Kernel",-1,38,21,120,8 + CTEXT "Version 1.0b2",-1,20,31,144,8 + PUSHBUTTON "OK",IDOK,72,126,39,14,WS_GROUP | NOT WS_TABSTOP + CTEXT "Written By:",606,20,50,144,8 + CTEXT "Jon Mittelhauser (jonm@ncsa.uiuc.edu)",607,20,61,144,8 + CTEXT "Chris Wilson (cwilson@ncsa.uiuc.edu)",608,20,71,144,8 + CTEXT "Special Thanks to:",609,21,97,143,8 + CTEXT "Joe Lepore for DPMI interface code",610,20,107,144,8 + CTEXT "Keberized by: Cygnus Support",611,20,82,144,8 +END + +CONFIG_DLG DIALOG DISCARDABLE 6, 18, 160, 130 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Configure Session" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Session Name:",301,1,5,54,8 + LTEXT "Default Session",CON_SESSIONNAME,55,5,105,8 + LTEXT "Window Title:",303,1,17,49,8 + EDITTEXT CON_WINDOWTITLE,53,15,102,12,ES_AUTOHSCROLL + CONTROL "132",CON_COLUMNS132,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,53,33,39,10 + CONTROL "80",CON_COLUMNS80,"Button",BS_AUTORADIOBUTTON,110,33,39, + 10 + CONTROL "Backspace",CON_BACKSPACE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,53,46,49,10 + CONTROL "Delete",CON_DELETE,"Button",BS_AUTORADIOBUTTON,110,46, + 39,10 + CONTROL "CRLF",CON_CRLF,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 53,59,39,10 + CONTROL "CR-NUL",CON_CRNUL,"Button",BS_AUTORADIOBUTTON,110,59,39, + 10 + CONTROL "Buffers",CON_BUFFERS,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,53,72,39,10 + CONTROL "Sends",CON_SENDS,"Button",BS_AUTORADIOBUTTON,110,72,39, + 10 + LTEXT "Columns",313,1,33,49,8 + LTEXT "Backspace is",314,1,46,51,8 + LTEXT "Return Sends",315,1,59,49,8 + LTEXT "Echo Mode",316,1,72,49,8 + CONTROL "Scrollback",CON_SCRLBCK,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,1,86,50,10 + EDITTEXT CON_NUMLINES,53,85,28,12,ES_AUTOHSCROLL + LTEXT "lines",319,85,86,33,8 + DEFPUSHBUTTON "OK",CON_OK,20,108,50,14,WS_GROUP + PUSHBUTTON "Use Defaults",CON_USEDEFAULTS,90,108,50,14 +END + +IDM_PRINTQUEUE DIALOG DISCARDABLE 69, 25, 160, 80 +STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_VSCROLL | WS_HSCROLL | WS_SYSMENU +CAPTION "Print Queue" +FONT 8, "MS Sans Serif" +BEGIN +END + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 183, 92 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,126,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,126,24,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +NCSA ICON DISCARDABLE "ncsa.ico" +TERMINAL ICON DISCARDABLE "terminal.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +SCREENMENU MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit Alt+F4", IDM_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Copy Cltr+Ins", IDM_COPY + MENUITEM "&Paste Shift+Ins", IDM_PASTE + END + POPUP "&Options" + BEGIN + MENUITEM "&Backspace", IDM_BACKSPACE + MENUITEM "&Delete", IDM_DELETE, CHECKED + MENUITEM SEPARATOR + MENUITEM "&Font...", IDM_FONT + END +#if 0 + POPUP "&Send", GRAYED + BEGIN + MENUITEM "&Interrupt Process", IDM_SEND_IP + MENUITEM "&Are You There?", IDM_SEND_AYT + MENUITEM "A&bort Process", IDM_SEND_ABORT + END +#endif + POPUP "&Help" + BEGIN + MENUITEM "&Index...", IDM_HELP_INDEX + MENUITEM SEPARATOR + MENUITEM "&About...", IDM_ABOUT + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""dialog.h""\r\n" + "#include ""screen.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 176 + TOPMARGIN, 7 + BOTTOMMARGIN, 85 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + +#include "..\version.rc" diff --git a/krb5-1-6/src/windows/wintel/telnet_arpa.h b/krb5-1-6/src/windows/wintel/telnet_arpa.h new file mode 100644 index 000000000..f6d0eb566 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/telnet_arpa.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)telnet.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _TELNET_H_ +#define _TELNET_H_ + +/* + * Definitions for the TELNET protocol. + */ +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#ifdef TELCMDS +char *telcmds[] = { + "EOF", "SUSP", "ABORT", "EOR", + "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", + "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0, +}; +#else +extern char *telcmds[]; +#endif + +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ + (unsigned int)(x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascic character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_XDISPLOC 35 /* X Display Location */ +#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ +#define TELOPT_AUTHENTICATION 37/* Authenticate */ +#define TELOPT_ENCRYPT 38 /* Encryption option */ +#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ +#define TELOPT_EXOPL 255 /* extended-options-list */ + + +#define NTELOPTS (1+TELOPT_NEW_ENVIRON) +#ifdef TELOPTS +char *telopts[NTELOPTS+1] = { + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", + "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", + "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", + "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", + "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", + "TACACS UID", "OUTPUT MARKING", "TTYLOC", + "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", + "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", + "ENCRYPT", "NEW-ENVIRON", + 0, +}; +#define TELOPT_FIRST TELOPT_BINARY +#define TELOPT_LAST TELOPT_NEW_ENVIRON +#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) +#define TELOPT(x) telopts[(x)-TELOPT_FIRST] +#endif + +/* sub-option qualifiers */ +#define TELQUAL_IS 0 /* option is... */ +#define TELQUAL_SEND 1 /* send option */ +#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ +#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ +#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ + +#define LFLOW_OFF 0 /* Disable remote flow control */ +#define LFLOW_ON 1 /* Enable remote flow control */ +#define LFLOW_RESTART_ANY 2 /* Restart output on any char */ +#define LFLOW_RESTART_XON 3 /* Restart output only on XON */ + +/* + * LINEMODE suboptions + */ + +#define LM_MODE 1 +#define LM_FORWARDMASK 2 +#define LM_SLC 3 + +#define MODE_EDIT 0x01 +#define MODE_TRAPSIG 0x02 +#define MODE_ACK 0x04 +#define MODE_SOFT_TAB 0x08 +#define MODE_LIT_ECHO 0x10 + +#define MODE_MASK 0x1f + +/* Not part of protocol, but needed to simplify things... */ +#define MODE_FLOW 0x0100 +#define MODE_ECHO 0x0200 +#define MODE_INBIN 0x0400 +#define MODE_OUTBIN 0x0800 +#define MODE_FORCE 0x1000 + +#define SLC_SYNCH 1 +#define SLC_BRK 2 +#define SLC_IP 3 +#define SLC_AO 4 +#define SLC_AYT 5 +#define SLC_EOR 6 +#define SLC_ABORT 7 +#define SLC_EOF 8 +#define SLC_SUSP 9 +#define SLC_EC 10 +#define SLC_EL 11 +#define SLC_EW 12 +#define SLC_RP 13 +#define SLC_LNEXT 14 +#define SLC_XON 15 +#define SLC_XOFF 16 +#define SLC_FORW1 17 +#define SLC_FORW2 18 + +#define NSLC 18 + +/* + * For backwards compatability, we define SLC_NAMES to be the + * list of names if SLC_NAMES is not defined. + */ +#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ + "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ + "LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0, +#ifdef SLC_NAMES +char *slc_names[] = { + SLC_NAMELIST +}; +#else +extern char *slc_names[]; +#define SLC_NAMES SLC_NAMELIST +#endif + +#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) +#define SLC_NAME(x) slc_names[x] + +#define SLC_NOSUPPORT 0 +#define SLC_CANTCHANGE 1 +#define SLC_VARIABLE 2 +#define SLC_DEFAULT 3 +#define SLC_LEVELBITS 0x03 + +#define SLC_FUNC 0 +#define SLC_FLAGS 1 +#define SLC_VALUE 2 + +#define SLC_ACK 0x80 +#define SLC_FLUSHIN 0x40 +#define SLC_FLUSHOUT 0x20 + +#define OLD_ENV_VAR 1 +#define OLD_ENV_VALUE 0 +#define NEW_ENV_VAR 0 +#define NEW_ENV_VALUE 1 +#define ENV_ESC 2 +#define ENV_USERVAR 3 + +/* + * AUTHENTICATION suboptions + */ + +/* + * Who is authenticating who ... + */ +#define AUTH_WHO_CLIENT 0 /* Client authenticating server */ +#define AUTH_WHO_SERVER 1 /* Server authenticating client */ +#define AUTH_WHO_MASK 1 + +/* + * amount of authentication done + */ +#define AUTH_HOW_ONE_WAY 0 +#define AUTH_HOW_MUTUAL 2 +#define AUTH_HOW_MASK 2 + +/* + * should we be encrypting? (not yet formally standardized) + */ +#define AUTH_ENCRYPT_OFF 0 +#define AUTH_ENCRYPT_ON 4 +#define AUTH_ENCRYPT_MASK 4 + +#define AUTHTYPE_NULL 0 +#define AUTHTYPE_KERBEROS_V4 1 +#define AUTHTYPE_KERBEROS_V5 2 +#define AUTHTYPE_SPX 3 +#define AUTHTYPE_MINK 4 +#define AUTHTYPE_CNT 5 + +#define AUTHTYPE_TEST 99 + +#ifdef AUTH_NAMES +char *authtype_names[] = { + "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0, +}; +#else +extern char *authtype_names[]; +#endif + +#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) +#define AUTHTYPE_NAME(x) authtype_names[x] + +/* + * ENCRYPTion suboptions + */ +#define ENCRYPT_IS 0 /* I pick encryption type ... */ +#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ +#define ENCRYPT_REPLY 2 /* Initial setup response */ +#define ENCRYPT_START 3 /* Am starting to send encrypted */ +#define ENCRYPT_END 4 /* Am ending encrypted */ +#define ENCRYPT_REQSTART 5 /* Request you start encrypting */ +#define ENCRYPT_REQEND 6 /* Request you send encrypting */ +#define ENCRYPT_ENC_KEYID 7 +#define ENCRYPT_DEC_KEYID 8 +#define ENCRYPT_CNT 9 + +#define ENCTYPE_ANY 0 +#define ENCTYPE_DES_CFB64 1 +#define ENCTYPE_DES_OFB64 2 +#define ENCTYPE_CNT 3 + +#ifdef ENCRYPT_NAMES +char *encrypt_names[] = { + "IS", "SUPPORT", "REPLY", "START", "END", + "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", + 0, +}; +char *enctype_names[] = { + "ANY", "DES_CFB64", "DES_OFB64", 0, +}; +#else +extern char *encrypt_names[]; +extern char *enctype_names[]; +#endif + + +#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) +#define ENCRYPT_NAME(x) encrypt_names[x] + +#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) +#define ENCTYPE_NAME(x) enctype_names[x] + +#endif /* !_TELNET_H_ */ diff --git a/krb5-1-6/src/windows/wintel/telopts.h b/krb5-1-6/src/windows/wintel/telopts.h new file mode 100644 index 000000000..54d67cde3 --- /dev/null +++ b/krb5-1-6/src/windows/wintel/telopts.h @@ -0,0 +1,164 @@ +/* + * telopts.h + * Used for telnet options + **************************************************************************** + * * + * * + * NCSA Telnet * + * by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer * + * Additions by Kurt Mahan, Heeren Pathak, & Quincey Koziol * + * * + * National Center for Supercomputing Applications * + * 152 Computing Applications Building * + * 605 E. Springfield Ave. * + * Champaign, IL 61820 * + * * + **************************************************************************** + * Quincey Koziol + * Defines for telnet options and related things + */ + +#ifndef TELOPTS_H +#define TELOPTS_H + +#define NUMLMODEOPTIONS 30 + +/* Definitions for telnet protocol */ + +#define STNORM 0 + +/* Definition of the lowest telnet byte following an IAC byte */ +#define LOW_TEL_OPT 236 + +#define TEL_EOF 236 +#define SUSP 237 +#define ABORT 238 + +#define SE 240 +#define NOP 241 +#define DM 242 +#define BREAK 243 +#define IP 244 +#define AO 245 +#define AYT 246 +#define EC 247 +#define EL 248 +#define GOAHEAD 249 +#define SB 250 +#define WILLTEL 251 +#define WONTTEL 252 +#define DOTEL 253 +#define DONTTEL 254 +#define IAC 255 + +/* Assigned Telnet Options */ +#define BINARY 0 +#define ECHO 1 +#define RECONNECT 2 +#define SGA 3 +#define AMSN 4 +#define STATUS 5 +#define TIMING 6 +#define RCTAN 7 +#define OLW 8 +#define OPS 9 +#define OCRD 10 +#define OHTS 11 +#define OHTD 12 +#define OFFD 13 +#define OVTS 14 +#define OVTD 15 +#define OLFD 16 +#define XASCII 17 +#define LOGOUT 18 +#define BYTEM 19 +#define DET 20 +#define SUPDUP 21 +#define SUPDUPOUT 22 +#define SENDLOC 23 +#define TERMTYPE 24 +#define EOR 25 +#define TACACSUID 26 +#define OUTPUTMARK 27 +#define TERMLOCNUM 28 +#define REGIME3270 29 +#define X3PAD 30 +#define NAWS 31 +#define TERMSPEED 32 +#define TFLOWCNTRL 33 +#define LINEMODE 34 + +#define MODE 1 +#define MODE_EDIT 1 +#define MODE_TRAPSIG 2 +#define MODE_ACK 4 +#define MODE_SOFT_TAB 8 +#define MODE_LIT_ECHO 16 + +#define FORWARDMASK 2 + +#define SLC 3 +#define SLC_DEFAULT 3 +#define SLC_VALUE 2 +#define SLC_CANTCHANGE 1 +#define SLC_NOSUPPORT 0 +#define SLC_LEVELBITS 3 + +#define SLC_ACK 128 +#define SLC_FLUSHIN 64 +#define SLC_FLUSHOUT 32 + +#define SLC_SYNCH 1 +#define SLC_BRK 2 +#define SLC_IP 3 +#define SLC_AO 4 +#define SLC_AYT 5 +#define SLC_EOR 6 +#define SLC_ABORT 7 +#define SLC_EOF 8 +#define SLC_SUSP 9 +#define SLC_EC 10 +#define SLC_EL 11 +#define SLC_EW 12 +#define SLC_RP 13 +#define SLC_LNEXT 14 +#define SLC_XON 15 +#define SLC_XOFF 16 +#define SLC_FORW1 17 +#define SLC_FORW2 18 +#define SLC_MCL 19 +#define SLC_MCR 20 +#define SLC_MCWL 21 +#define SLC_MCWR 22 +#define SLC_MCBOL 23 +#define SLC_MCEOL 24 +#define SLC_INSRT 25 +#define SLC_OVER 26 +#define SLC_ECR 27 +#define SLC_EWR 28 +#define SLC_EBOL 29 +#define SLC_EEOL 30 + +#define XDISPLOC 35 +#define ENVIRONMENT 36 +#define AUTHENTICATION 37 +#define TELOPT_AUTHENTICATION AUTHENTICATION +#define DATA_ENCRYPTION 38 +#define XOPTIONS 255 + +#define LINEMODE_MODES_SUPPORTED 0x1B +/* + * set this flag for linemode special functions which are supported by + * Telnet, even though they are not currently active. This is to allow + * the other side to negotiate to a "No Support" state for an option + * and then change later to supporting it, so we know it's ok to change + * our "No Support" state to something else ("Can't Change", "Value", + * whatever) + */ +#define SLC_SUPPORTED 0x10 + +#define ESCFOUND 5 +#define IACFOUND 6 +#define NEGOTIATE 1 + +#endif /* telopts.h */ diff --git a/krb5-1-6/src/windows/wintel/terminal.ico b/krb5-1-6/src/windows/wintel/terminal.ico new file mode 100644 index 0000000000000000000000000000000000000000..7ec59e980f2318ce2d830297ae2bc2813aa3ddb6 GIT binary patch literal 766 zcmb_aF%rTs3{!zSMl-RJk!SF<{H%EjBV$IkAhlPpbKQayIg#x|aj(F{k<taS*8#Y4 zy%ULe5ED-HKxS^=W`Gm(ye{<IqLhN1GZSr@XiYnULm|0;n>DN7S*7OqBK8Zc+C3kC z5gTig_GXTlI`0aqFW_;D1*HCfsOLeBDSsJD0|jaL@|_e|5Z@n<vk^7u`We{jrp+>c YHID)upTL=o+8elO6<2%&+nv(=0AA{XzyJUM literal 0 HcmV?d00001 diff --git a/krb5-1-6/src/windows/wintel/wt-proto.h b/krb5-1-6/src/windows/wintel/wt-proto.h new file mode 100644 index 000000000..15b9c1a8e --- /dev/null +++ b/krb5-1-6/src/windows/wintel/wt-proto.h @@ -0,0 +1,63 @@ +/* wt-proto.h */ +BOOL +InitApplication( + HINSTANCE + ); + +BOOL +InitInstance( + HINSTANCE, + int + ); + +LRESULT +CALLBACK +MainWndProc( + HWND, + UINT, + WPARAM, + LPARAM + ); + +INT_PTR +CALLBACK +OpenTelnetDlg( + HWND, + UINT, + WPARAM, + LPARAM + ); + +int +TelnetSend( + kstream, + char *, + int, + int + ); + +int +OpenTelnetConnection( + void + ); + +int +DoDialog( + char *szDialog, + DLGPROC lpfnDlgProc + ); + +BOOL +parse_cmdline( + char *cmdline + ); + +CONNECTION * +GetNewConnection( + void + ); + +void +start_negotiation( + kstream ks + ); -- 2.26.2